summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/INSTALL427
-rw-r--r--src/INSTALLami.txt34
-rw-r--r--src/INSTALLmac.txt164
-rw-r--r--src/INSTALLpc.txt310
-rw-r--r--src/INSTALLvms.txt375
-rw-r--r--src/Make_agui.mak356
-rw-r--r--src/Make_aros.mak29
-rw-r--r--src/Make_bc3.mak173
-rw-r--r--src/Make_bc5.mak1006
-rw-r--r--src/Make_cyg.mak498
-rw-r--r--src/Make_dice.mak209
-rw-r--r--src/Make_djg.mak102
-rw-r--r--src/Make_dvc.mak105
-rw-r--r--src/Make_ivc.mak648
-rw-r--r--src/Make_manx.mak322
-rw-r--r--src/Make_ming.mak555
-rw-r--r--src/Make_mint.mak56
-rw-r--r--src/Make_morph.mak88
-rw-r--r--src/Make_mpw.mak3843
-rw-r--r--src/Make_mvc.mak888
-rw-r--r--src/Make_os2.mak147
-rw-r--r--src/Make_ro.mak168
-rw-r--r--src/Make_sas.mak345
-rw-r--r--src/Make_vms.mms457
-rw-r--r--src/Make_w16.mak196
-rw-r--r--src/README.txt140
-rw-r--r--src/VisVim/Commands.cpp693
-rw-r--r--src/VisVim/Commands.h127
-rw-r--r--src/VisVim/DSAddIn.cpp160
-rw-r--r--src/VisVim/DSAddIn.h53
-rw-r--r--src/VisVim/OleAut.cpp781
-rw-r--r--src/VisVim/OleAut.h73
-rw-r--r--src/VisVim/README_VisVim.txt322
-rw-r--r--src/VisVim/Reg.cpp56
-rw-r--r--src/VisVim/Register.bat1
-rw-r--r--src/VisVim/Resource.h29
-rw-r--r--src/VisVim/StdAfx.cpp6
-rw-r--r--src/VisVim/StdAfx.h73
-rw-r--r--src/VisVim/UnRegist.bat1
-rw-r--r--src/VisVim/VisVim.cpp152
-rw-r--r--src/VisVim/VisVim.def11
-rw-r--r--src/VisVim/VisVim.dllbin0 -> 49664 bytes
-rw-r--r--src/VisVim/VisVim.h33
-rw-r--r--src/VisVim/VisVim.mak205
-rw-r--r--src/VisVim/VisVim.odl61
-rw-r--r--src/VisVim/VisVim.rc199
-rw-r--r--src/VisVim/VsReadMe.txt91
-rw-r--r--src/arabic.c1168
-rw-r--r--src/arabic.h258
-rw-r--r--src/ascii.h201
-rwxr-xr-xsrc/auto/configure8692
-rw-r--r--src/bigvim.bat3
-rw-r--r--src/buffer.c5071
-rw-r--r--src/charset.c1795
-rw-r--r--src/config.aap.in115
-rw-r--r--src/config.h.in361
-rw-r--r--src/config.mk.dist5
-rw-r--r--src/config.mk.in137
-rwxr-xr-xsrc/configure4
-rw-r--r--src/configure.in2660
-rw-r--r--src/dehqx.py40
-rw-r--r--src/diff.c2208
-rw-r--r--src/digraph.c2513
-rw-r--r--src/dimm.idl544
-rw-r--r--src/dlldata.c38
-rw-r--r--src/dosinst.c2461
-rw-r--r--src/dosinst.h645
-rw-r--r--src/edit.c7614
-rw-r--r--src/eval.c10682
-rw-r--r--src/ex_cmds.c6198
-rw-r--r--src/ex_cmds.h961
-rw-r--r--src/ex_cmds2.c5711
-rw-r--r--src/ex_docmd.c9711
-rw-r--r--src/ex_eval.c2004
-rw-r--r--src/ex_getln.c5371
-rw-r--r--src/farsi.c2312
-rw-r--r--src/farsi.h234
-rw-r--r--src/feature.h1184
-rw-r--r--src/fileio.c8750
-rw-r--r--src/fold.c3250
-rw-r--r--src/getchar.c4636
-rw-r--r--src/glbl_ime.cpp261
-rw-r--r--src/glbl_ime.h31
-rw-r--r--src/globals.h1381
-rw-r--r--src/gui.c4740
-rw-r--r--src/gui.h525
-rw-r--r--src/gui_amiga.c1795
-rw-r--r--src/gui_amiga.h52
-rw-r--r--src/gui_at_fs.c2880
-rw-r--r--src/gui_at_sb.c1213
-rw-r--r--src/gui_at_sb.h161
-rw-r--r--src/gui_athena.c2230
-rw-r--r--src/gui_beos.cc3347
-rw-r--r--src/gui_beos.h49
-rw-r--r--src/gui_beval.c1268
-rw-r--r--src/gui_beval.h76
-rw-r--r--src/gui_gtk.c3035
-rw-r--r--src/gui_gtk_f.c942
-rw-r--r--src/gui_gtk_f.h83
-rw-r--r--src/gui_gtk_vms.h734
-rw-r--r--src/gui_gtk_x11.c6589
-rw-r--r--src/gui_mac.c5820
-rw-r--r--src/gui_mac.icnsbin0 -> 38515 bytes
-rw-r--r--src/gui_mac.r33
-rw-r--r--src/gui_motif.c3090
-rw-r--r--src/gui_photon.c3060
-rw-r--r--src/gui_riscos.c3547
-rw-r--r--src/gui_riscos.h32
-rw-r--r--src/gui_w16.c1524
-rw-r--r--src/gui_w32.c4077
-rw-r--r--src/gui_w32_rc.h8
-rw-r--r--src/gui_w48.c3402
-rw-r--r--src/gui_x11.c3748
-rw-r--r--src/guiw16rc.h17
-rw-r--r--src/gvim.exe.mnf22
-rw-r--r--src/hangulin.c1621
-rw-r--r--src/if_cscope.c2270
-rw-r--r--src/if_cscope.h96
-rw-r--r--src/if_ole.cpp778
-rw-r--r--src/if_ole.h289
-rw-r--r--src/if_ole.idl45
-rw-r--r--src/if_perl.xs1150
-rw-r--r--src/if_perlsfio.c66
-rw-r--r--src/if_python.c2807
-rw-r--r--src/if_ruby.c868
-rw-r--r--src/if_sniff.c1210
-rw-r--r--src/if_sniff.h18
-rw-r--r--src/if_tcl.c2118
-rw-r--r--src/if_xcmdsrv.c1441
-rw-r--r--src/iid_ole.c50
-rw-r--r--src/infplist.xml51
-rw-r--r--src/integration.c1198
-rw-r--r--src/integration.h453
-rw-r--r--src/keymap.h484
-rw-r--r--src/link.3907
-rwxr-xr-xsrc/link.sh136
-rw-r--r--src/macros.h245
-rw-r--r--src/main.aap1014
-rw-r--r--src/mark.c1617
-rw-r--r--src/mbyte.c5833
-rw-r--r--src/memfile.c1312
-rw-r--r--src/memline.c4378
-rw-r--r--src/menu.c2385
-rw-r--r--src/message.c3165
-rw-r--r--src/misc1.c8455
-rw-r--r--src/misc2.c5556
-rwxr-xr-xsrc/mkinstalldirs40
-rw-r--r--src/move.c2796
-rw-r--r--src/mysign1
-rw-r--r--src/nbdebug.c182
-rw-r--r--src/nbdebug.h81
-rw-r--r--src/netbeans.c3185
-rw-r--r--src/normal.c8508
-rw-r--r--src/ops.c6114
-rw-r--r--src/option.c9383
-rw-r--r--src/option.h802
-rw-r--r--src/os_amiga.c1619
-rw-r--r--src/os_amiga.h201
-rw-r--r--src/os_beos.c206
-rw-r--r--src/os_beos.h25
-rw-r--r--src/os_beos.rsrcbin0 -> 6956 bytes
-rw-r--r--src/os_dos.h125
-rw-r--r--src/os_mac.build91
-rw-r--r--src/os_mac.c1451
-rw-r--r--src/os_mac.h411
-rw-r--r--src/os_mac.rsr.hqx659
-rw-r--r--src/os_mac.sit.hqx439
-rw-r--r--src/os_macosx.c612
-rw-r--r--src/os_mint.h13
-rw-r--r--src/os_msdos.c3114
-rw-r--r--src/os_msdos.h106
-rw-r--r--src/os_mswin.c3245
-rw-r--r--src/os_os2_cfg.h251
-rw-r--r--src/os_qnx.c162
-rw-r--r--src/os_qnx.h19
-rw-r--r--src/os_riscos.c1288
-rw-r--r--src/os_riscos.h169
-rw-r--r--src/os_unix.c6189
-rw-r--r--src/os_unix.h531
-rw-r--r--src/os_unixx.h130
-rw-r--r--src/os_vms.c657
-rw-r--r--src/os_vms_conf.h185
-rw-r--r--src/os_vms_fix.com276
-rw-r--r--src/os_vms_mms.c76
-rw-r--r--src/os_w32dll.c24
-rw-r--r--src/os_w32exe.c136
-rw-r--r--src/os_win16.c424
-rw-r--r--src/os_win16.h142
-rw-r--r--src/os_win32.c4790
-rw-r--r--src/os_win32.h190
-rwxr-xr-xsrc/osdef.sh99
-rw-r--r--src/osdef1.h.in137
-rw-r--r--src/osdef2.h.in88
-rwxr-xr-xsrc/pathdef.sh11
-rw-r--r--src/po/Make_ming.mak67
-rw-r--r--src/po/Make_mvc.mak62
-rw-r--r--src/po/Makefile135
-rw-r--r--src/po/README.txt104
-rw-r--r--src/po/README_mingw.txt101
-rw-r--r--src/po/README_mvc.txt94
-rw-r--r--src/po/af.po6244
-rw-r--r--src/po/ca.po6341
-rw-r--r--src/po/cleanup.vim7
-rw-r--r--src/po/cs.cp1250.po5954
-rw-r--r--src/po/cs.po5954
-rw-r--r--src/po/de.po6091
-rw-r--r--src/po/en_GB.po48
-rw-r--r--src/po/es.po6780
-rw-r--r--src/po/fr.po6888
-rw-r--r--src/po/it.po6638
-rw-r--r--src/po/ja.po6587
-rw-r--r--src/po/ja.sjis.po6587
-rw-r--r--src/po/ko.po6580
-rw-r--r--src/po/no.po6630
-rw-r--r--src/po/pl.cp1250.po6576
-rw-r--r--src/po/pl.po6576
-rw-r--r--src/po/ru.cp1251.po6658
-rw-r--r--src/po/ru.po6658
-rw-r--r--src/po/sjiscorr.c50
-rw-r--r--src/po/sk.cp1250.po5998
-rw-r--r--src/po/sk.po5998
-rw-r--r--src/po/sv.po6516
-rw-r--r--src/po/uk.po6225
-rw-r--r--src/po/zh_CN.UTF-8.po5937
-rw-r--r--src/po/zh_CN.cp936.po5937
-rw-r--r--src/po/zh_CN.po5937
-rw-r--r--src/po/zh_TW.UTF-8.po6389
-rw-r--r--src/po/zh_TW.po6389
-rw-r--r--src/proto.h251
-rw-r--r--src/proto/buffer.pro66
-rw-r--r--src/proto/charset.pro49
-rw-r--r--src/proto/diff.pro23
-rw-r--r--src/proto/digraph.pro9
-rw-r--r--src/proto/edit.pro36
-rw-r--r--src/proto/eval.pro60
-rw-r--r--src/proto/ex_cmds.pro52
-rw-r--r--src/proto/ex_cmds2.pro76
-rw-r--r--src/proto/ex_docmd.pro41
-rw-r--r--src/proto/ex_eval.pro29
-rw-r--r--src/proto/ex_getln.pro47
-rw-r--r--src/proto/fileio.pro39
-rw-r--r--src/proto/fold.pro40
-rw-r--r--src/proto/getchar.pro61
-rw-r--r--src/proto/gui.pro61
-rw-r--r--src/proto/gui_amiga.pro67
-rw-r--r--src/proto/gui_athena.pro31
-rw-r--r--src/proto/gui_beos.pro14
-rw-r--r--src/proto/gui_beval.pro10
-rw-r--r--src/proto/gui_gtk.pro24
-rw-r--r--src/proto/gui_gtk_x11.pro67
-rw-r--r--src/proto/gui_mac.pro142
-rw-r--r--src/proto/gui_motif.pro39
-rw-r--r--src/proto/gui_photon.pro66
-rw-r--r--src/proto/gui_riscos.pro67
-rw-r--r--src/proto/gui_w16.pro73
-rw-r--r--src/proto/gui_w32.pro89
-rw-r--r--src/proto/gui_x11.pro70
-rw-r--r--src/proto/hangulin.pro9
-rw-r--r--src/proto/if_cscope.pro9
-rw-r--r--src/proto/if_ole.pro5
-rw-r--r--src/proto/if_perl.pro8
-rw-r--r--src/proto/if_perlsfio.pro3
-rw-r--r--src/proto/if_python.pro8
-rw-r--r--src/proto/if_ruby.pro9
-rw-r--r--src/proto/if_tcl.pro10
-rw-r--r--src/proto/if_xcmdsrv.pro11
-rw-r--r--src/proto/main.pro25
-rw-r--r--src/proto/mark.pro26
-rw-r--r--src/proto/mbyte.pro86
-rw-r--r--src/proto/memfile.pro17
-rw-r--r--src/proto/memline.pro31
-rw-r--r--src/proto/menu.pro21
-rw-r--r--src/proto/message.pro57
-rw-r--r--src/proto/misc1.pro87
-rw-r--r--src/proto/misc2.pro91
-rw-r--r--src/proto/move.pro40
-rw-r--r--src/proto/netbeans.pro24
-rw-r--r--src/proto/normal.pro23
-rw-r--r--src/proto/ops.pro53
-rw-r--r--src/proto/option.pro52
-rw-r--r--src/proto/os_amiga.pro46
-rw-r--r--src/proto/os_beos.pro4
-rw-r--r--src/proto/os_mac.pro64
-rw-r--r--src/proto/os_msdos.pro48
-rw-r--r--src/proto/os_mswin.pro60
-rw-r--r--src/proto/os_qnx.pro8
-rw-r--r--src/proto/os_riscos.pro49
-rw-r--r--src/proto/os_unix.pro70
-rw-r--r--src/proto/os_vms.pro14
-rw-r--r--src/proto/os_win16.pro12
-rw-r--r--src/proto/os_win32.pro48
-rw-r--r--src/proto/pty.pro3
-rw-r--r--src/proto/quickfix.pro21
-rw-r--r--src/proto/regexp.pro16
-rw-r--r--src/proto/screen.pro46
-rw-r--r--src/proto/search.pro33
-rw-r--r--src/proto/syntax.pro42
-rw-r--r--src/proto/tag.pro8
-rw-r--r--src/proto/term.pro58
-rw-r--r--src/proto/termlib.pro8
-rw-r--r--src/proto/ui.pro61
-rw-r--r--src/proto/undo.pro18
-rw-r--r--src/proto/version.pro9
-rw-r--r--src/proto/window.pro44
-rw-r--r--src/proto/workshop.pro48
-rw-r--r--src/pty.c425
-rw-r--r--src/quickfix.c2232
-rw-r--r--src/regexp.c6115
-rw-r--r--src/regexp.h80
-rw-r--r--src/screen.c8437
-rw-r--r--src/search.c4487
-rw-r--r--src/structs.h1887
-rw-r--r--src/swis.s143
-rw-r--r--src/syntax.c8456
-rw-r--r--src/tag.c3534
-rw-r--r--src/tearoff.bmpbin0 -> 118 bytes
-rw-r--r--src/tee/Makefile15
-rw-r--r--src/tee/tee.c153
-rw-r--r--src/term.c5381
-rw-r--r--src/term.h156
-rw-r--r--src/termlib.c628
-rw-r--r--src/testdir/Make_amiga.mak97
-rw-r--r--src/testdir/Make_dos.mak64
-rw-r--r--src/testdir/Make_os2.mak52
-rw-r--r--src/testdir/Make_vms.mms124
-rw-r--r--src/testdir/Makefile58
-rw-r--r--src/testdir/amiga.vim4
-rw-r--r--src/testdir/dos.vim7
-rw-r--r--src/testdir/dotest.in3
-rw-r--r--src/testdir/main.aap58
-rw-r--r--src/testdir/os2.vim3
-rw-r--r--src/testdir/test1.in40
-rw-r--r--src/testdir/test1.ok1
-rw-r--r--src/testdir/test10.in57
-rw-r--r--src/testdir/test10.ok23
-rw-r--r--src/testdir/test10a.in73
-rw-r--r--src/testdir/test10a.ok23
-rw-r--r--src/testdir/test11.in77
-rw-r--r--src/testdir/test11.ok61
-rw-r--r--src/testdir/test12.in52
-rw-r--r--src/testdir/test12.ok10
-rw-r--r--src/testdir/test13.in58
-rw-r--r--src/testdir/test13.ok30
-rw-r--r--src/testdir/test14.in65
-rw-r--r--src/testdir/test14.ok17
-rw-r--r--src/testdir/test15.in136
-rw-r--r--src/testdir/test15.ok111
-rw-r--r--src/testdir/test16.in10
-rw-r--r--src/testdir/test16.ok2
-rw-r--r--src/testdir/test17.in27
-rw-r--r--src/testdir/test17.ok3
-rw-r--r--src/testdir/test17a.in3
-rw-r--r--src/testdir/test18.in16
-rw-r--r--src/testdir/test18.ok4
-rw-r--r--src/testdir/test19.in23
-rw-r--r--src/testdir/test19.ok7
-rw-r--r--src/testdir/test2.in29
-rw-r--r--src/testdir/test2.ok4
-rw-r--r--src/testdir/test20.in22
-rw-r--r--src/testdir/test20.ok6
-rw-r--r--src/testdir/test21.in19
-rw-r--r--src/testdir/test21.ok2
-rw-r--r--src/testdir/test22.in13
-rw-r--r--src/testdir/test22.ok4
-rw-r--r--src/testdir/test23.in15
-rw-r--r--src/testdir/test23.ok2
-rw-r--r--src/testdir/test24.in21
-rw-r--r--src/testdir/test24.ok7
-rw-r--r--src/testdir/test25.in31
-rw-r--r--src/testdir/test25.ok1
-rw-r--r--src/testdir/test26.in43
-rw-r--r--src/testdir/test26.ok10
-rw-r--r--src/testdir/test27.in20
-rw-r--r--src/testdir/test27.ok2
-rw-r--r--src/testdir/test28.inbin0 -> 364 bytes
-rw-r--r--src/testdir/test28.ok2
-rw-r--r--src/testdir/test29.in67
-rw-r--r--src/testdir/test29.ok28
-rw-r--r--src/testdir/test3.in1217
-rw-r--r--src/testdir/test3.ok1090
-rw-r--r--src/testdir/test30.in183
-rw-r--r--src/testdir/test30.ok96
-rw-r--r--src/testdir/test31.in68
-rw-r--r--src/testdir/test31.ok11
-rw-r--r--src/testdir/test32.in56
-rw-r--r--src/testdir/test32.ok15
-rw-r--r--src/testdir/test33.in34
-rw-r--r--src/testdir/test33.ok23
-rw-r--r--src/testdir/test34.in31
-rw-r--r--src/testdir/test34.ok1
-rw-r--r--src/testdir/test35.in21
-rw-r--r--src/testdir/test35.ok4
-rw-r--r--src/testdir/test36.in40
-rw-r--r--src/testdir/test36.ok16
-rw-r--r--src/testdir/test37.in116
-rw-r--r--src/testdir/test37.ok33
-rw-r--r--src/testdir/test38.in33
-rw-r--r--src/testdir/test38.ok13
-rw-r--r--src/testdir/test39.in24
-rw-r--r--src/testdir/test39.ok5
-rw-r--r--src/testdir/test4.in31
-rw-r--r--src/testdir/test4.ok17
-rw-r--r--src/testdir/test40.in63
-rw-r--r--src/testdir/test40.ok11
-rw-r--r--src/testdir/test41.in24
-rw-r--r--src/testdir/test41.ok3
-rw-r--r--src/testdir/test42.inbin0 -> 2368 bytes
-rw-r--r--src/testdir/test42.okbin0 -> 407 bytes
-rw-r--r--src/testdir/test43.in27
-rw-r--r--src/testdir/test43.ok8
-rw-r--r--src/testdir/test44.in37
-rw-r--r--src/testdir/test44.ok11
-rw-r--r--src/testdir/test45.in72
-rw-r--r--src/testdir/test45.ok16
-rw-r--r--src/testdir/test46.in27
-rw-r--r--src/testdir/test46.ok13
-rw-r--r--src/testdir/test47.in44
-rw-r--r--src/testdir/test47.ok3
-rw-r--r--src/testdir/test48.in74
-rw-r--r--src/testdir/test48.ok21
-rw-r--r--src/testdir/test49.in13
-rw-r--r--src/testdir/test49.ok92
-rw-r--r--src/testdir/test49.vim9666
-rw-r--r--src/testdir/test5.in29
-rw-r--r--src/testdir/test5.ok9
-rw-r--r--src/testdir/test50.in85
-rw-r--r--src/testdir/test50.ok14
-rw-r--r--src/testdir/test51.in34
-rw-r--r--src/testdir/test51.ok15
-rw-r--r--src/testdir/test52.in65
-rw-r--r--src/testdir/test52.ok18
-rw-r--r--src/testdir/test6.in24
-rw-r--r--src/testdir/test6.ok18
-rw-r--r--src/testdir/test7.in26
-rw-r--r--src/testdir/test7.ok12
-rw-r--r--src/testdir/test8.in24
-rw-r--r--src/testdir/test8.ok6
-rw-r--r--src/testdir/test9.in12
-rw-r--r--src/testdir/test9.ok2
-rw-r--r--src/testdir/todos.vim3
-rw-r--r--src/testdir/unix.vim3
-rw-r--r--src/testdir/vms.vim4
-rw-r--r--src/toolbar.phi1283
-rwxr-xr-xsrc/toolcheck36
-rw-r--r--src/tools.bmpbin0 -> 5158 bytes
-rw-r--r--src/tools16.bmpbin0 -> 3838 bytes
-rw-r--r--src/typemap14
-rw-r--r--src/ui.c3060
-rw-r--r--src/undo.c1380
-rw-r--r--src/uninstal.c438
-rw-r--r--src/version.c1219
-rw-r--r--src/version.h40
-rw-r--r--src/vim.def4
-rw-r--r--src/vim.h1788
-rw-r--r--src/vim.icobin0 -> 1078 bytes
-rw-r--r--src/vim.rc135
-rw-r--r--src/vim.tlbbin0 -> 1792 bytes
-rw-r--r--src/vim16.def5
-rw-r--r--src/vim16.rc81
-rw-r--r--src/vim_alert.icobin0 -> 1078 bytes
-rw-r--r--src/vim_error.icobin0 -> 1078 bytes
-rw-r--r--src/vim_icon.xbm14
-rw-r--r--src/vim_info.icobin0 -> 1078 bytes
-rw-r--r--src/vim_mask.xbm14
-rw-r--r--src/vim_quest.icobin0 -> 1078 bytes
-rw-r--r--src/vimrun.c117
-rwxr-xr-xsrc/vimtbar.dllbin0 -> 35602 bytes
-rw-r--r--src/vimtbar.h185
-rw-r--r--src/vimtbar.libbin0 -> 1024 bytes
-rwxr-xr-xsrc/vimtutor61
-rwxr-xr-xsrc/which.sh12
-rw-r--r--src/window.c4946
-rw-r--r--src/workshop.c1885
-rw-r--r--src/workshop.h28
-rw-r--r--src/wsdebug.c179
-rw-r--r--src/wsdebug.h81
-rw-r--r--src/xpm_w32.c60
-rw-r--r--src/xpm_w32.h7
-rw-r--r--src/xxd/Make_amiga.mak18
-rw-r--r--src/xxd/Make_bc3.mak31
-rw-r--r--src/xxd/Make_bc5.mak18
-rw-r--r--src/xxd/Make_cyg.mak27
-rw-r--r--src/xxd/Make_djg.mak9
-rw-r--r--src/xxd/Make_mvc.mak11
-rw-r--r--src/xxd/Make_os2.mak11
-rw-r--r--src/xxd/Make_vms.mms69
-rw-r--r--src/xxd/Makefile7
-rw-r--r--src/xxd/xxd.c767
488 files changed, 521276 insertions, 0 deletions
diff --git a/src/INSTALL b/src/INSTALL
new file mode 100644
index 000000000..b1aa6a879
--- /dev/null
+++ b/src/INSTALL
@@ -0,0 +1,427 @@
+INSTALL - Installation of Vim on different machines.
+
+This file contains instructions for compiling Vim. If you already have an
+executable version of Vim, you don't need this.
+
+Contents:
+1. Generic
+2. Unix
+3. RISC OS
+4. Macintosh
+5. OS/2 (with EMX 0.9b)
+6. Atari MiNT
+
+For OS/390 Unix see ../runtime/doc/os_390.txt
+For BeBox see ../runtime/doc/os_beos.txt.
+For Amiga see INSTALLami.txt
+For PC (MS-DOS, Windows NT, Windows 95) see INSTALLpc.txt
+For Macintosh see INSTALLmac.txt
+
+
+1. Generic
+==========
+
+If you compile Vim without specifying anything, you will get the default
+behaviour as is documented, which should be fine for most people.
+
+For features that you can't enable/disable in another way, you can edit the
+file "feature.h" to match your preferences.
+
+
+2. Unix
+=======
+
+Summary:
+1. make run configure, compile and link
+2. make install installation in /usr/local
+
+This will include the GUI and X11 libraries, if you have them. If you want a
+version of Vim that is small and starts up quickly, see the Makefile for how
+to disable the GUI and X11. If you don't have Motif and/or X11, these
+features will be disabled automatically.
+
+See the start of Makefile for more detailed instructions about how to compile
+Vim.
+
+If you need extra compiler and/or linker arguments, set $CFLAGS and/or $LIBS
+before starting configure. Example:
+
+ env CFLAGS=-I/usr/local/include LIBS=-lm make
+
+This is only needed for things that configure doesn't offer a specific argument
+for or figures out by itself. First try running configure without extra
+arguments.
+
+GNU Autoconf and a few other tools have been used to make Vim work on many
+different Unix systems. The advantage of this is that Vim should compile
+on most sytems without any adjustments. The disadvantage is that when
+adjustments are required, it takes some time to understand what is happening.
+
+If configure finds all library files and then complains when linking that some
+of them can't be found, your linker doesn't return an error code for missing
+libraries. Vim should be linked fine anyway, mostly you can just ignore these
+errors.
+
+If you run configure by hand (not using the Makefile), remember that any
+changes in the Makefile have no influence on configure. This may be what you
+want, but maybe not!
+
+The advantage of running configure separately, is that you can write a script
+to build Vim, without changing the Makefile or feature.h. Example (using sh):
+
+ CFLAGS=-DCOMPILER_FLAG ./configure --enable-gui=motif
+
+One thing to watch out for: If the configure script itself changes, running
+"make" will execute it again, but without your arguments. Do "make clean" and
+run configure again.
+
+If you are compiling Vim for several machines, for each machine:
+ a. make shadow
+ b. mv shadow machine_name
+ c. cd machine_name
+ d. make; make install
+
+[Don't use a path for machine_name, just a directory name, otherwise the links
+that "make shadow" creates won't work.]
+
+
+Unix: COMPILING WITH/WITHOUT GUI
+
+These configure arguments can be used to select which GUI to use:
+--enable-gui= gtk, motif, athena or auto
+--disable-gtk-check
+--disable-motif-check
+--disable-athena-check
+
+--enable-gui defaults to "auto", so it will automatically look for a GUI (in
+the order of GTK, Motif, then Athena). If one is found, then is uses it and
+does not proceed to check any of the remaining ones. Otherwise, it moves on
+to the next one.
+
+--enable-{gtk,motif,athena}-check all default to "yes", such that if
+--enable-gui is "auto" (which it is by default), GTK, Motif, and Athena will
+be checked for. If you want to *exclude* a certain check, then you use
+--disable-{gtk,motif,athena}-check.
+
+For example, if --enable-gui is set to "auto", but you don't want it look for
+Motif, you then also specify --disable-motif-check. This results in only
+checking for GTK and Athena.
+
+Lastly, if you know which one you want to use, then you can just do
+--enable-gui={gtk,motif,athena}. So if you wanted to only use Motif, then
+you'd specify --enable-gui=motif. Once you specify what you want, the
+--enable-{gtk,motif,athena}-check options are ignored.
+
+For compiling with the GTK+ GUI, you need a recent version of glib and gtk+.
+Configure checks for at least version 1.1.16, but below 2.0. An older versions
+is not selected automatically. If you want to use it anyway, run configure
+with "--disable-gtktest". GTK 2.0 doesn't work yet.
+GTK requires an ANSI C compiler. If you fail to compile Vim with GTK+ (it
+is the preferred choice), try selecting another one in the Makefile.
+If you are sure you have GTK installed, but for some reason configure says you
+do not, you may have left-over header files and/or library files from an older
+(and incompatible) version of GTK. if this is the case, please check
+auto/config.log for any error messages that may give you a hint as to what's
+happening.
+
+Unix: COMPILING WITH MULTI-BYTE
+
+When you want to compile with the multi-byte features enabled, make sure you
+compile on a machine where the locale settings actually work. otherwise the
+configure tests may fail. You need to compile with "big" features:
+
+ ./configure --with-features=big
+
+Unix: COMPILING ON LINUX
+
+On Linux, when using -g to compile (which is default for gcc), the executable
+will probably be statically linked. If you don't want this, remove the -g
+option from CFLAGS.
+
+Unix: PUTTING vimrc IN /etc
+
+Some Linux distributions prefer to put the global vimrc file in /etc, and the
+Vim runtime files in /usr. This can be done with:
+ ./configure --prefix=/usr
+ make VIMRCLOC=/etc VIMRUNTIMEDIR=/usr/share/vim MAKE="make -e"
+
+Unix: COMPILING ON NeXT
+
+Add the "-posix" argument to the compiler by using one of these commands:
+ setenv CC 'cc -posix' (csh)
+ export CC='cc -posix' (sh)
+And run configure with "--disable-motif-check".
+
+
+3. RISC OS
+=============
+
+Much file renaming is needed before you can compile anything.
+You'll need UnixLib to link against, GCC and GNU make.
+
+I suggest you get the RISC OS binary distribution, which includes the
+Templates file and the loader.
+
+Try here: http://www.ecs.soton.ac.uk/~tal197
+
+Do
+ :help riscos
+
+within the editor for more information, or read the os_riscos.txt help file.
+
+
+4. Macintosh
+============
+
+Vim should work on the Macintosh, but I don't have a makefile for it.
+Work is being done to update the Macintosh port. It's a lot of work; don't
+expect it soon.
+
+
+5. OS/2
+=======
+
+Summary:
+ren Makefile Makefile.unix
+ren makefile.os2 Makefile
+make
+
+This port of Vim to OS/2 is based on the emx environment together
+with GNU C. The main design goal of emx is to simplify porting Unix
+software to OS/2 and DOS. Because of this, almost all the Unix defines
+etc. already existing in the Vim source code could be reused. Only where
+OS/2 specifics came into play were additional changes necessary. Those
+places can be found by searching for "OS2" and "__EMX__" (I've tried to
+keep emx-specific things separate from generic OS/2 stuff).
+
+Note: This OS/2 port works well for me and an additional OS/2 user on
+ the Vim development team (Karsten Sievert); however, since I
+ haven't had any other feedback from other people, that either
+ means no (OS/2-specific) bugs exist, or no one has yet created
+ a situation in which any bugs are apparent.
+ Report any problems or other comments to paul@wau.mis.ah.nl
+ (email valid up to at least September 1996, after that try
+ paul@wurtel.hobby.nl, paul@murphy.nl, or paulS@toecompst.nl).
+ Textmode/notextmode and binary mode both seem to work well.
+
+Prerequisites:
+- To compile, you need the emx environment (at least rev. 0.9b), GCC,
+ some make utility (GNU make works fine). These are generally
+ available as (ask Archie about them):
+ emxrt.zip emx runtime package
+ emxdev.zip emx development system (without compiler)
+ GNU programs compiled for emx, patches and patched sources:
+ gnudev1.zip GNU development tools compiled for emx (part 1)
+ gnudev2.zip GNU development tools compiled for emx (part 2)
+ gnumake.zip GNU make
+- Don't set a TERM environment variable; Vim defaults to os2ansi
+ which is available as a builtin termcap entry. Using other values
+ may give problems! (OS/2 ANSI emulation is quite limited.) If you
+ need to set TERM for other programs, you may consider putting
+ set term=os2ansi in the vimrc file.
+
+Check vim_os2.txt for additional info on running Vim.
+
+
+6. Atari MiNT
+=============
+
+
+To compile Vim for MiNT you may either copy makefile.mint to Makefile or use
+the Unix Makefile adapted for the MiNT configuration.
+
+Now proceed as described in the Unix section.
+
+Prerequisites:
+
+You need a curses or termcap library that supports non-alphanumeric
+termcap names. If you don't have any, link with termlib.o.
+
+-----------------------------------------------------------------------------
+
+The rest of this file is based on the INSTALL file that comes with GNU
+autoconf 2.12. Not everything applies to Vim. Read Makefile too!
+
+
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/src/INSTALLami.txt b/src/INSTALLami.txt
new file mode 100644
index 000000000..0acd6fdff
--- /dev/null
+++ b/src/INSTALLami.txt
@@ -0,0 +1,34 @@
+INSTALLami.txt - Installation of Vim from source on Amiga
+
+This file contains instructions for compiling Vim. If you already have an
+executable version of Vim, you don't need this.
+
+The file "feature.h" can be edited to match your preferences. You can skip
+this, then you will get the default behavior as is documented, which should
+be fine for most people.
+
+
+Summary:
+make -f Make_manx.mak Manx C
+make -f Make_sas.mak Lattice/SAS C
+make -f Make_dice.mak DICE
+
+The Manx compiler is preferred, it was used to produce the Amiga executable
+and has been tested most. You should not get any errors or warnings.
+
+The SAS compiler can be used. Older versions (6.0 to 6.3) don't work with the
+optimizer switched on. This seems to be fixed with 6.5 or 6.56, but this has
+not been tested much. Also disable optimizing when the compiler runs out of
+memory or crashes the system (yes, that happens; did I say the Manx compiler
+is preferred?).
+
+The DICE makefile has been reported to work by one person only.
+
+You will have to set the "VIM" environment variable to the location of the
+documentation files.
+
+
+MorphOS
+
+Use the Make_morph.mak Makefile:
+ make -f Make_morph.mak
diff --git a/src/INSTALLmac.txt b/src/INSTALLmac.txt
new file mode 100644
index 000000000..8b944c379
--- /dev/null
+++ b/src/INSTALLmac.txt
@@ -0,0 +1,164 @@
+INSTALLmac.txt - Installation of Vim on Macintosh
+
+This file contains instructions for compiling Vim. If you already have an
+executable version of Vim, you don't need this.
+
+An alternate way of building that Benji Fisher uses can be found here:
+
+ http://macvim.swdev.org/OSX/#Developers
+
+----------------------------------------------------------------------------
+Summary
+----------------------------------------------------------------------------
+
+1 MacOS X
+ 1.1. Carbon interface
+ 1.2. X (Athena, GTK, Motif) or plain text.
+
+2 MacOS Classic
+ 2.1. CodeWarrior
+ 2.2. MPW
+
+NOTE: The Carbon version can only be compiled properly under
+ MacOS X.
+
+----------------------------------------------------------------------------
+1 MacOS X
+----------------------------------------------------------------------------
+
+1.0 Considerations
+
+ Only '/' supported as path separator.
+
+1.1 Carbon interface (default)
+
+ You can compile vim with the standard Unix routine:
+ cd ..
+ ./configure
+ make; make install
+
+ This will create a working Vim.app application bundle in the src
+ directory. You can move this bundle (the Vim.app directory) anywhere
+ you want, for example, /Applications.
+
+1.2 X-Windows or Plain Text
+
+ If you do not want the Carbon interface, you must explicitly tell
+ configure to use a different GUI.
+
+ cd ..
+ ./configure --enable-gui=gtk2
+ make; make install
+
+ NOTE: The following GUI options are supported:
+ no (for text), motif, athena, nextaw
+ gtk, gtk2, gnome, gnome2,
+
+ NOTE: You need to first install XFree86 and XDarwin.
+ Please visit http://www.XDarwin.org
+
+----------------------------------------------------------------------------
+MacOS 9
+----------------------------------------------------------------------------
+
+Both ':' and '/' supported as path separator.
+
+2.1: Compiling with CodeWarior
+
+ 1. Expand the resource file:
+ open ../src/os_mac.rsr.hqx to produce ../src/gui_mac.rsrc:
+ % cd vim62/src
+ % open -a StuffIt\ Expander os_mac.rsr.hqx
+
+ 2. Expand the project file:
+ - ../src/os_mac.sit.hqx (to produce ../src/vim.mcp)
+
+ 3. Open vim.mcp with CodeWarior
+
+ This is a CodeWarior 9 project file. When using a newer version,
+ you need to convert the file. you may also need to change some
+ access path.
+
+ NOTE: the current project file is old, you need to add a few files:
+ (ex_cmds2.c, fold.c, mbyte.c, move.c)
+
+ 4. Select the target PPC, 68k FAT (with/without debugger)
+
+ 5. Compile
+
+2.2: Compiling with MPW.
+
+ 0. You will need a recent version of the MPW and the Universal Interfaces.
+ You can get both at:
+ ftp://ftp.apple.com/developer/Tool_Chest/Interfaces-Libraries/
+ ftp://ftp.apple.com/developer/Tool_Chest/Core_Mac_OS_Tools/
+ For a Carbon version you will need a recent Carbon SDK as well.
+ (When you have an older version already installed you not be able to
+ compile a carbon version. Update "CreateMake" which is available at
+ Apple.
+
+ 1. Expand the resource file:
+ open ../src/os_mac.rsr.hqx to produce ../src/gui_mac.rsrc:
+ % cd vim62/src
+ % open -a StuffIt\ Expander os_mac.rsr.hqx
+
+ 3. Double click on os_make.make, the MPW will now open in the correct
+ folder and load the CreateVimMake script. Change to the Worksheet
+ window. Type "os_mac.build" and hit Enter (not Return). A dialog box
+ will appear. Select the target you want. (Vim-68k, Vim-ppc, Vim-carbon)
+
+ 4. Select "Build" from the menu (or type command-B). Type the program name
+ into the dialog box.
+
+------------------------------------------------------
+
+OLD FILE: SOME INFO MAY STILL BE USEFUL
+
+NOTE: Users of more recent CodeWarrior version may have to reset the library
+ path, and change the mch_delay in os_mac.c so the finalTick is unsigned.
+
+Compilation instructions:
+
+1. Visit the Vim ftp site (see ftp://ftp.vim.org/pub/vim/MIRRORS)
+ and obtain the following five files:
+
+ unix/vim-X.X-src1.tar.gz
+ unix/vim-X.X-src2.tar.gz
+ unix/vim-X.X-rt1.tar.gz
+ unix/vim-X.X-rt2.tar.gz
+ extra/vim-X.X-extra.tar.gz
+
+ where X.X is the version number.
+
+ NOTE: the language support is not yet supported
+
+2. Expand the archives.
+
+3. Apply patches if they exist. (Patch files are found in the ftp
+ site in the "patches" directory.)
+
+4. Edit vim-X.X/src/feature.h for your preference. (You can skip
+ this, then you will get the default behavior as is documented,
+ which should be fine for most people.)
+
+ For example, if you want to add the FEAT_MBYTE feature, turn on
+ #define FEAT_MBYTE
+
+5. Expand the resource file:
+
+ - vim-X.X/src/os_mac.rsr.hqx (to produce vim-X.X/src/gui_mac.rsrc)
+
+6. If using CodeWarrior, expand the project file:
+
+ - vim-X.X/src/os_mac.sit.hqx (to produce vim-X.X/src/vim.mcp)
+
+ The latter file is the CodeWarrior project file to be used.
+
+7. Launch CodeWarrior by double clicking vim.mcp.
+
+8. Check additional files if you include non-standard features.
+
+ For example, if you added the MULTI_BYTE feature, check
+ Extras/mbyte.c in the project window.
+
+9. Compile and you will obtain binaries: vimPPC, Vim 68k, and/or vimFAT.
diff --git a/src/INSTALLpc.txt b/src/INSTALLpc.txt
new file mode 100644
index 000000000..1e7d3297a
--- /dev/null
+++ b/src/INSTALLpc.txt
@@ -0,0 +1,310 @@
+INSTALLpc.txt - Installation of Vim on PC
+
+This file contains instructions for compiling Vim. If you already have an
+executable version of Vim, you don't need this.
+
+More information can be found here:
+
+ http://mywebpage.netscape.com/sharppeople/vim/howto/
+
+The file "feature.h" can be edited to match your preferences. You can skip
+this, then you will get the default behavior as is documented, which should
+be fine for most people.
+
+
+Contents:
+1. MS-DOS
+2. Win32 (Windows NT and Windows 95)
+3. Windows NT with OpenNT
+4. Windows 3.1
+5. Using Mingw
+6. Cross compiling for Win32 from a Linux machine
+7. Building with Python support
+
+
+1. MS-DOS
+=========
+
+Summary:
+ren Make_bc3.mak Makefile; make 16 bit, Borland C++ and Turbo C++
+ren Make_tcc.mak Makefile; make 16 bit, Turbo C
+make -f Make_djg.mak 32 bit, DJGPP 2.0
+make -f Make_bc5.mak 32 bit, Borland C++ 5.0 (edit it to
+ define DOS)
+
+Warning: Be sure to use the right make.exe. Microsoft C make doesn't work;
+Borland make only works with Make_bc3.mak, Make_bc5.mak and Make_tcc.mak;
+DJGPP/GNU make must be used for Make_djg.mak.
+
+The Borland C++ compiler has been used to generate the MS-DOS executable; it
+should work without problems. You will probably have to change the paths for
+LIBPATH and INCLUDEPATH in the start of the Makefile. You will get two
+warnings which can be ignored (one about _chmod and one about precompiled
+header files).
+
+The "spawno" library by Ralf Brown was used in order to free memory when Vim
+starts a shell or other external command. Only about 200 bytes are taken from
+conventional memory. When recompiling get the spawno library from Simtel,
+directory "msdos/c". It is called something like "spwno413.zip". Or follow
+the instructions in the Makefile to remove the library.
+
+The Turbo C Makefile has not been tested much lately. It is included for those
+that don't have C++. You may need to make a few changes to get it to work.
+
+DJGPP needs to be installed properly to compile Vim; you need a lot of things
+before it works. When your setup is OK, Vim should compile with just one
+warning (about an argument to signal()).
+
+Make_bc5.mak is for those that have Borland C++ 5.0 or later. At the top of
+the file, there are some variables you can change to make either a 32-bit
+Windows exe (GUI or console mode), or a 16-bit MS-DOS version.
+
+If you get all kinds of strange error messages when compiling, try adding <CR>
+characters at the end of each line.
+
+
+2. Win32 (Windows NT and Windows 95)
+====================================
+
+Summary:
+vcvars32 Setup paths for nmake and MSVC
+
+nmake -f Make_mvc.mak console Win32 SDK or Microsoft Visual C++
+nmake -f Make_mvc.mak GUI=yes GUI Microsoft Visual C++
+nmake -f Make_mvc.mak OLE=yes OLE Microsoft Visual C++
+nmake -f Make_mvc.mak PERL=C:\Perl PYTHON=C:\Python etc.
+ Perl, Python, etc.
+ Microsoft Visual C++
+
+make -f Make_bc5.mak GUI Borland C++ 5.x
+make -f Make_bc5.mak console Borland C++ 5.x (change the file)
+nmake -f Make_ivc.mak CFG="Vim - Win32 Release gvim"
+ GUI Microsoft Visual C++ 4.x or later
+nmake -f Make_ivc.mak CFG="Vim - Win32 Release gvim OLE"
+ OLE Microsoft Visual C++ 4.x or later
+
+make -f Make_cyg.mak various Cygnus gcc
+make -f Make_mingw.mak various MingW with gcc
+
+See the specific files for comments and options.
+
+These files have been supplied by George V. Reilly, Ben Singer, Ken Scott and
+Ron Aaron; they have been tested. The Cygnus one many not fully work yet.
+With Cygnus gcc you can use the Unix Makefile instead (you need to get the
+Unix archive then). Then you get a Cygwin application (feels like Vim is
+runnin on Unix), while with Make_cyg.mak you get a Windows application (like
+with the other makefiles).
+
+You can also use the Visual C++ IDE: use File/Open workspace, select the
+Make_ivc.mak file, then select Build/Build all. This builds the GUI version
+by default.
+
+Vim for Win32 compiles with the Microsoft Visual C++ 2.0 compiler and later,
+and with the Borland C++ 4.5 32-bit compiler and later. It compiles on
+Windows 95 and all four NT platforms: i386, Alpha, MIPS, and PowerPC. The
+NT/i386 and the Windows 95 binaries are identical. Use Make_mvc.mak to
+compile with Visual C++ and Make_bc5.mak to compile with Borland C++.
+
+Make_mvc.mak allows a Vim to be built with various different features and
+debug support. Debugging with MS Devstudio is provided by Make_dvc.mak.
+For a description of the use of Make_dvc.mak, look in Make_mvc.mak.
+
+For compiling Gvim with IME support on far-east Windows, uncomment the
+MULTI_BYTE_IME define in the src/feature.h file before compiling.
+
+The Win32 console binary was compiled with Visual C++ version 5.0, using
+Make_mvc.mak and Make_bc5.mak (Borland C). Other compilers should also work.
+If you get all kinds of strange error messages when compiling (you shouldn't
+with the Microsoft or Borland 32-bit compilers), try adding <CR> characters
+at the end of each line.
+
+You probably need to run "vcvars32" before using "nmake".
+
+For making the Win32s version, you need Microsoft Visual C++ 4.1 OR EARLIER.
+In version 4.2 support for Win32s was dropped! Use this command:
+ nmake -f Make_mvc.mak GUI=yes
+
+See the respective Makefiles for more comments.
+
+
+3. Windows NT with OpenNT
+=========================
+
+(contributed by Michael A. Benzinger)
+
+Building Vim on OpenNT 2.0 on Windows NT 4.0, with Softway's prerelease gcc:
+1. export CONFIG_SHELL=//D/OpenNT/bin/sh
+2. Make the following exports for modifying config.mk:
+ export CFLAGS=-O -Wshadow
+ export X_PRE_LIBS=-lXmu
+2. Run configure as follows:
+ configure --prefix=/vim --bindir=/bin/opennt --enable-gui=Motif
+ If you don't have OpenNTif (Motif support), use this:
+ configure --prefix=/vim --bindir=/bin/opennt --enable-gui=Athena
+3. Edit Makefile to perform the following since the Makefile include syntax
+ differs from that of gmake:
+ #include config.mk
+ .include "config.mk"
+4. Change all install links to be "ln -f" and not "ln -s".
+5. Change to the 'ctags' directory and configure.
+6. Edit the Makefile and remove spurious spaces from lines 99 and 114.
+7. Change slink to "ln -f" from "ln -s".
+8. Return to the src directory.
+9. make
+
+
+4. Windows 3.1x
+===============
+
+make -f Make_w16.mak 16 bit, Borland C++ 5.0
+
+Warning: Be sure to use the right make.exe. It should be Borland make.
+
+You will almost certainly have to change the paths for libs and include files
+in the Makefile. Look for "D:\BC5" and "ctl3dv2". You will get a number of
+warnings which can be ignored ( _chmod, precompiled header files, and
+"possibly incorrect assignment").
+
+The makefile should also work for BC++ 4.0 and 4.5, but may need tweaking to
+remove unsupported compiler & liker options.
+
+
+5. Mingw
+========
+
+(written by Ron Aaron: <ronaharon@yahoo.com>)
+
+This is about how to produce a Win32 binary of gvim with Mingw.
+
+First, you need to get the 'mingw32' compiler, which is free for the download
+at:
+
+ http://www.mingw.org/
+
+Once you have downloaded the compiler binaries, unpack them on your hard disk
+somewhere, and put them on your PATH. If you are on Win95/98 you can edit
+your AUTOEXEC.BAT file with a line like:
+
+ set PATH=C:\GCC-2.95.2\BIN;%PATH%
+
+or on NT/2000, go to the Control Panel, System, and edit the environment from
+there.
+
+Test if gcc is on your path. From a CMD (or COMMAND on '95/98):
+
+ C:\> gcc --version
+ 2.95.2
+
+ C:\> make --version
+ GNU Make version 3.77 (...etc...)
+
+Now you are ready to rock 'n' roll. Unpack the vim sources (look on
+www.vim.org for exactly which version of the vim files you need).
+
+Change directory to 'vim\src':
+
+ C:\> cd vim\src
+ C:\VIM\SRC>
+
+and you type:
+
+ make -f Make_ming.mak gvim.exe
+
+After churning for a while, you will end up with 'gvim.exe' in the 'vim\src'
+directory.
+
+You should not need to do *any* editing of any files to get vim compiled this
+way. If, for some reason, you want the console-mode-only version of vim (this
+is NOT recommended on Win32, especially on '95/'98!!!), you need only change
+the 'gvim.exe' to 'vim.exe' in the 'make' commands given above.
+
+If you are dismayed by how big the EXE is, I strongly recommend you get 'UPX'
+(also free!) and compress the file (typical compression is 50%). UPX can be
+found at
+ http://upx.tsx.org/
+
+
+ADDITION: NLS support with Mingw
+
+(by Eduardo F. Amatria <eferna1@platea.pntic.mec.es>)
+
+If you want National Language Support, read the file src/po/README_mingw.txt.
+You need to uncomment lines in Make_ming.mak to have NLS defined.
+
+
+6. Cross compiling for Win32 from a Linux machine
+=================================================
+
+(written by Ron Aaron: <ronaharon@yahoo.com> with help from
+Martin Kahlert <martin.kahlert@infineon.com>)
+
+If you like, you can compile the 'mingw' Win32 version from the comfort of
+your Linux (or other unix) box. To do this, you need to follow a few steps:
+
+ 1) Install the mingw32 cross-compiler (if you have it, go to step 2)
+ 1a) from 'ftp://ftp.nanotech.wisc.edu/pub/khan/gnu-win32/mingw32/snapshots/gcc-2.95.2-1',
+ get:
+ binutils-19990818-1-src.tar.gz
+ mingw-msvcrt-20000203.zip
+ gcc-2.95.2-1-x86-win32.diff.gz
+ 1b) from 'http://gcc.gnu.org/' get:
+ gcc-2.95.2.tar.gz
+ 1c) create a place to put the compiler source and binaries:
+ (assuming you are in the home directory)
+ mkdir gcc-bin
+ mkdir gcc-src
+ 1d) unpack the sources:
+ cd gcc-src
+ tar xzf ../binutils-19990818-1-src.tar.gz
+ tar xzf ../gcc-2.95.2.tar.gz
+ unzip ../mingw-msvcrt-20000203
+ 1e) build the different tools:
+ export PREFIX=~/gcc-bin/
+ cd gcc-2.95.2
+ zcat ../gcc-2.95.2-1-x86-win32.diff.gz | patch -p1 -E
+ cd ../binutils-19990818
+ ./configure --target=i586-pc-mingw32msvc --prefix=$PREFIX
+ make
+ make install
+ cd ../gcc-2.95.2
+ ./configure --target=i586-pc-mingw32msvc \
+ --with-libs=~/gcc-bin/i386-mingw32msvc/lib \
+ --with-headers=~/gcc-bin/i386-mingw32msvc/include \
+ --enable-languages=c++ \
+ --prefix=$PREFIX
+ make
+ make install
+ 1f) Add $PREFIX/bin to your $PATH.
+
+ 2) get the *unix* version of the vim sources
+ 3) in 'Make_ming.mak', set 'CROSS' to '1' instead of '0'.
+ 4) make -f Make_ming.mak gvim.exe
+
+Now you have created the Windows binary from your Linux box! Have fun...
+
+7. Building with Python support
+=================================================
+
+(written by Ron Aaron: <ronaharon@yahoo.com>)
+
+This has been tested with the mingw32 compiler, and the ActiveState
+ActivePython:
+ http://www.ActiveState.com/Products/ActivePython/
+
+After installing the ActivePython, you will have to create a 'mingw32'
+'libpython20.a' to link with:
+ cd $PYTHON/libs
+ pexports python20.dll > python20.def
+ dlltool -d python20.def -l libpython20.a
+
+Once that is done, edit the 'Make_ming.mak' so the PYTHON variable points to
+the root of the Python installation (C:\Python20, for example). If you are
+cross-compiling on Linux with the mingw32 setup, you need to also convert all
+the 'Include' files to *unix* line-endings. This bash command will do it
+easily:
+ for fil in *.h ; do vim -e -c 'set ff=unix|w|q' $fil
+
+Now just do:
+ make -f Make_ming.mak gvim.exe
+
+and you will end up with a Python-enabled, Win32 version. Enjoy!
diff --git a/src/INSTALLvms.txt b/src/INSTALLvms.txt
new file mode 100644
index 000000000..f7df6a740
--- /dev/null
+++ b/src/INSTALLvms.txt
@@ -0,0 +1,375 @@
+INSTALLvms.txt - Installation of Vim on OpenVMS
+
+Maintainer: Zoltan Arpadffy <arpadffy@polarfox.com>
+Last change: 2003 May 04
+
+This file contains instructions for compiling Vim on Openvms.
+If you already have an executable version of Vim, you don't need this.
+
+If you skip settings described here, then you will get the default Vim
+behavior as it is documented, which should be fine for most users.
+
+The file "feature.h" can be edited to match your preferences, but this files
+does not describe possibilities hidden in feature.h acrobatics, however
+parameters from MAKE_VMS.MMS actively uses and sets up parameters in relation
+with feature.h
+
+More information and case analysis you can found in os_vms.txt
+([runtime.doc]os_vms.txt or :help vms from vim prompt)
+
+Contents:
+1. Download files
+2. Configuration
+3. Compilation DECC
+4. Compilation VAXC
+5. CTAGS, XXD
+6. Deployment
+7. GTK and other features
+8. Notes
+9. Authors
+
+----------------------------------------------------------------------------
+1. Download files
+
+1.1. Visit the Vim ftp site (see ftp://ftp.vim.org/pub/vim/MIRRORS)
+ and obtain the following three files:
+
+ unix/vim-X.X-src.tar.gz
+ unix/vim-X.X-rt.tar.gz
+ extra/vim-X.X-extra.tar.gz
+
+ where X.X is the version number.
+
+1.2. Expand the three archives.
+
+1.3. Apply patches if they exist. (Patch files are found in the ftp
+ site in the "patches" directory.)
+
+1.4. You will need either the DECSET mms utility or the freely available clone
+ of it called mmk (VMS has no make utility in the standard distribution).
+ You can download mmk from http://www.openvms.digital.com/freeware/MMK/
+
+1.5. If you want to have Perl, Python or Tcl support in Vim you will need VMS
+ distributions for them as well.
+
+1.6 If you want to have GTK executable, you need to have properly installed
+ GTK libraries.
+
+NOTE: procedure in chapter 1 describes source code preparation from multi OS
+code,however it is available OpenVMS oprimized (and tested) source code from:
+ftp://ftp.polarhome.com/pub/vim/source/vms/
+
+Current OpenVMS source code as .zip or .tar.gz file is possible to download
+from CVS mirror ftp://ftp.polarhome.com/pub/cvs/SOURCE/
+
+
+2. Configuration
+
+2.1. Edit vim-X.X/src/feature.h for your preference. (You can skip
+ this, then you will get the default behavior as is documented,
+ which should be fine for most people.)
+
+ For example, if you want to add the MULTI_BYTE feature, turn on
+ #define MULTI_BYTE
+
+2.2 Edit vim-X.X/src/Make_vms.mms to customize your Vim. Options are:
+
+ Parameter name : MODEL
+ Description : Build model selection
+ Options: : TINY - Almost no features enabled, not even
+ multiple windows
+ SMALL - Few features enabled, as basic as possible
+ NORMAL - A default selection of features enabled
+ BIG - Many features enabled, as rich as possible.
+ (OpenVMS default)
+ HUGE - All possible featues enabled.
+ Uncommented - will default to BIG
+ Default : MODEL = BIG
+
+ Parameter name : GUI
+ Description : GUI or terminal mode executable
+ Options: : YES - GUI executable
+ Uncommented - char only
+ Default : GUI = YES
+
+ Parameter name : GTK
+ Description : Enable GTK in GUI mode.
+ It enables features as toolbar etc.
+ Options: : YES - GTK executable
+ Uncommented - without GTK
+ Default : Uncommented
+
+ Parameter name : DECC
+ Description : Compiler selection
+ Options: : YES - DECC compiler
+ Uncommented - VAXC compiler
+ Default : DECC = YES
+
+ Parameter name : CCVER
+ Description : Compiler version with :ver command
+ Options: : YES - Compiler version info will be added
+ Uncommented - will not be added
+ Default : CCVER = YES
+
+ Parameter name : DEBUG
+ Description : Building a debug version
+ Options: : YES - debug version will be built
+ Uncommented - building normal executable
+ Default : Uncommented
+
+ Parameter name : VIM_TCL
+ Description : Add Tcl support
+ Options: : YES - Build with support
+ Uncommented - build without support.
+ Default : Uncommented
+
+ Parameter name : VIM_PERL
+ Description : Add Perl support
+ Options: : YES - Build with support
+ Uncommented - build without support.
+ Default : Uncommented
+
+ Parameter name : VIM_PYTHON
+ Description : Add Python support
+ Options: : YES - Build with support
+ Uncommented - build without support.
+ Default : Uncommented
+
+
+ Parameter name : VIM_XIM
+ Description : X Input Method. For entering special languages
+ like chinese and Japanese. Please define just
+ one: VIM_XIM or VIM_HANGULIN
+ Options: : YES - Build with support
+ Uncommented - build without support.
+ Default : Uncommented
+
+ Parameter name : VIM_HANGULIN
+ Description : Internal Hangul input method. GUI only.
+ Please define just one: VIM_XIM or VIM_HANGULIN
+ Options: : YES - Build with support
+ Uncommented - build without support.
+ Default : Uncommented
+
+ Parameter name : VIM_TAG_ANYWHITE
+ Description : Allow any white space to separate the fields in a
+ tags file
+ When not defined, only a TAB is allowed.
+ Options: : YES - Build with support
+ Uncommented - build without support.
+ Default : Uncommented
+
+ You can edit the *_INC and *_LIB qualifiers, but it is really
+ not recommended for beginners.
+
+3. Compilation DECC
+
+3.1. If you have MSS on your system, the command
+
+ mms /descrip=Make_vms.mms
+
+ will start building your own customized version of Vim.
+ The adequate command for mmk is:
+
+ mmk /descrip=Make_vms.mms
+
+ NOTE: Because of empty /auto/config.h (needed for Unix configure) build
+ will fail with very strange messages. Therefore before building, it is
+ recommended to make one clean up, to prepare everything for OpenVMS
+ development. The command is:
+
+ mms /descrip=Make_vms.mms clean
+
+4. Compilation VAXC
+
+4.1. VAXC compiler is not fully ANSI C compatible in pre-processor directives
+ semantics, therefore you have to use a converter program what will do the
+ lion part of the job.
+
+ @os_vms_fix.com *.c *.h <.proto>*.pro
+
+ more information can be found in os_vms_fix.com file itself.
+
+ NOTE: even if os_vms_fix.com will fix all pre-processor directives it will
+ leave singe (long) line directives. You have to fix them manually.
+ Known problematic files are option.h and option.c
+
+4.2. After the conversion you can continue building as it has been described
+ above.
+
+5. CTAGS, XXD
+
+5.1. MMS_VIM.EXE is building together with VIM.EXE, but for CTAGS.EXE and
+ XXD.EXE you should change to subdirectory <.CTAGS> or <.XXD> and build
+ them separately.
+
+5.2. In these directories you can found one make file for VMS as well.
+ Please read the detailed build instructions in the related *.MMS file.
+
+6. Deployment
+
+6.1. Copy over all executables to the deployment directory.
+
+6.2. Vim uses a special directory structure to hold the document and runtime
+ files:
+
+ vim (or wherever)
+ |-- doc
+ |-- syntax
+ vimrc (system rc files)
+ gvimrc
+
+6.3 Define logicals VIM
+
+ define/nolog VIM device:[leading-path-here.vim]
+
+ to get vim.exe to find its document, filetype, and syntax files.
+
+ Now, if you are lucky you should have one own built, customized and
+ working Vim.
+
+7. GTK and other features
+
+7.1 General notes
+
+ To be able to build external GUI or language support wyo have to enable
+ related feature in MAKE_VMS.MMS file. Usually it need some extra tuning
+ around include files, shared libraries etc.
+
+ Please note, that leading "," are valuable for MMS/MMK syntax.
+
+ MAKE_VMS.MMS uses defines as described below:
+
+7.1.1 feature_DEF = ,"SOME_FEATURE"
+
+ Submits definition to compiler preprocessor to enable code blocks
+ defined with
+ #ifdef SOME_FEATURE
+ {some code here}
+ #endif
+
+ Example: TCL_DEF = ,"FEAT_TCL"
+
+
+7.1.2 feature_SRC = code1.c code2.c
+
+ Defines source code related with particular feature.
+ Example: TCL_SRC = if_tcl.c
+
+7.1.3 feature_OBJ = code1.obj code2.obj
+
+ Lists objects created from source codes listed in feature_SRC
+ Example: PERL_OBJ = if_perlsfio.obj if_perl.obj
+
+7.1.4 feature_LIB = ,OS_VMS_TCL.OPT/OPT
+
+ Defines the libraries that have to be used for build.
+ If it is an OPT file then MAKE_VMS.MMS creates OPT files
+ in gen_feature procedure.
+
+ Example:
+ PERL_LIB = ,OS_VMS_PERL.OPT/OPT
+
+.IFDEF VIM_PERL
+perl_env :
+ -@ write sys$output "creating OS_VMS_PERL.OPT file."
+ -@ open/write opt_file OS_VMS_PERL.OPT
+ -@ write opt_file "PERLSHR /share"
+ -@ close opt_file
+.ELSE
+perl_env :
+ -@ !
+.ENDIF
+
+
+7.1.5 feature_INC = ,dka0:[tcl80.generic]
+
+ Defines the directory where the necessary include files are.
+ Example: TCL_INC = ,dka0:[tcl80.generic]
+
+7.2 GTK
+
+ To build VIM with GTK you have to install GTK on your OpenVMS.
+ So far it works just on Alphas. More information at:
+ http://www.openvms.compaq.com/openvms/products/ips/gtk.html
+
+ You need also the OpenVMS Porting Library:
+ http://www.openvms.compaq.com/openvms/products/ips/porting.html
+
+ Enable GTK in make_vms.mms file with GTK = YES
+ Define GTK_ROOT that points to your GTK root directory.
+
+ Build it as normally.
+
+ Used sharable images are:
+ gtk_root:[glib]libglib.exe /share,-
+ gtk_root:[glib.gmodule]libgmodule.exe /share,-
+ gtk_root:[gtk.gdk]libgdk.exe /share,-
+ gtk_root:[gtk.gtk]libgtk.exe /share
+
+ During runtime it is suggested to have all these files installed and
+ copyed to SYS$LIBRARY: to be able to use it without problems.
+ Also VMS_JACKETS.EXE from OpenVMS Porting Library.
+
+ Please note, that GTK uses /name=(as_is,short)/float=ieee/ieee=denorm
+ complier directives that is not compatible with "standard" VMS usage,
+ therefore other external features might fail as PERL, PYTHON and TCL
+ support.
+
+7.3 PERL
+
+ You have to install OpenVMS perl package from:
+ http://www.openvms.compaq.com/openvms/products/ips/apache/csws_perl_relnotes.html or build on your own from sources downloaded from http://www.perl.org
+
+ You need defined PERLSHR logical that points to PERL shareable image
+ (or you can just copy over to SYS$LIBRARY:)
+
+ Enable Perl feature at make_vms.mms with VIM_PERL = YES
+
+ Edit PERL_INC = to point to perl includes directory where is extern.h
+
+ Build as usually.
+
+7.4 PYTHON
+
+ You have to install an OpenVMS python package.
+ Set up the normal Python work environment.
+
+ You have to have defined PYTHON_INCLUDE and PYTHON_OLB logicals.
+ PYTHON_INCLUDE should point to Python include files where for ex:
+ python.h is located.
+ Enable Python feature at make_vms.mms with VIM_PYTHON = YES
+
+ Build as usually.
+
+7.5 TCL
+
+ You have to install an OpenVMS TCL package.
+ Set up the normal TCL work environment.
+
+ You have to have defined TCLSHR logical that points to shareable image.
+
+ Enable TCL feature at make_vms.mms with VIM_TCL = YES
+
+ Edit TCL_INC = to point to TCL includes directory where is tcl.h
+
+ Build as usually.
+
+8. Notes
+
+8.1. New Compaq C compiler
+
+ If you are using Compaq C compiler V6.2 or newer, Informational messages
+ of the type QUESTCOMPARE will be displayed. You should ignore those
+ messages ; they are generated only because some test comparisons are done
+ with variables which type vary depending on the OS. Under VMS, those are
+ "unsigned" and the compiler issue a message whenever the comparison is
+ done with '<=' to 0. However, the code is correct and will behave as
+ expected.
+ ( Jerome Lauret <JLAURET@mail.chem.sunysb.edu> Vim 6.0n )
+ NOTE: from version 6.0ad Vim code has been reviewed and these warnings
+ have been corrected.
+
+9. Authors
+
+ Initial version, 2000 Jul 19, Zoltan Arpadffy <arpadffy@polarfox.com>
diff --git a/src/Make_agui.mak b/src/Make_agui.mak
new file mode 100644
index 000000000..7b30a1976
--- /dev/null
+++ b/src/Make_agui.mak
@@ -0,0 +1,356 @@
+#
+# Makefile for VIM on the Amiga, using SAS/Lattice C 6.0 to 6.56
+#
+# Do NOT use the peephole optimizer with a version before 6.55!
+# It messes up all kinds of things:
+# For 6.0 and 6.1, expand_env() will not work correctly.
+# For 6.2 and 6.3 the call to free_line in u_freeentry is wrong.
+# Don't know about 6.50, might work...
+# Version 6.56 seems to be working fine.
+# You should use Manx Aztec C whenever possible.
+#
+# The prototypes from Manx and SAS are incompatible. If the prototypes
+# were generated by Manx, first do "touch *.c; make proto" before "make".
+# The prototypes generated on Unix work for both.
+#
+# Note: Not all dependencies are included. This was done to avoid having
+# to compile everything when a global variable or function is added.
+
+#>>>>> choose options:
+
+#ANSI CODES
+ANSIOFF = *e[0m
+BBOLD = *e[1m
+WBOLD = *e[2m
+ITALIC = *e[3m
+UNDERLI = *e[4m
+ANSIOFF = *e[0m
+FCOL1 = *e[31m
+FCOL2 = *e[32m
+FCOL3 = *e[33m
+FCOL4 = *e[34m
+BCOL1 = *e[41m
+BCOL2 = *e[42m
+BCOL3 = *e[43m
+BCOL4 = *e[44m
+
+
+### See feature.h for a list of optionals.
+### Any other defines can be included here.
+
+DEFINES = DEF=NO_ARP DEF=AMIGA DEF=NEWSASC DEF=FEAT_GUI_AMIGA \
+ DEF="SASC=658" #" this fixes a bug in the syntax highlighting
+
+#>>>>> if HAVE_TGETENT is defined termlib.o has to be used
+#TERMLIB = termlib.o
+TERMLIB =
+
+#>>>>> choose NODEBUG for normal compiling, the other for debugging and
+# profiling
+# don't switch on debugging when generating proto files, it crashes the
+# compiler.
+DBG = NODEBUG
+#DBG = DBG=FULLFLUSH
+#DBG = DBG=LINE
+
+#>>>>> choose NOOPTPEEP for 6.0 to 6.3, NOOPT for debugging
+#OPTIMIZE=NOOPTPEEP OPT
+
+# for 6.58 you can use the line below, but be warned it takes a loooonnnggg time
+#OPTIMIZE=OPT OPTIMIZERSCHEDULER OPTIMIZERTIME NoOPTIMIZERALIAS \
+# OptimizerComplexity=10 OptimizerDepth=10 OptimizerRecurDepth=10 \
+# OptimizerInLocal OPTPEEP
+OPTIMIZE=OPT OPTIMIZERTIME NoOPTIMIZERALIAS \
+ OptimizerComplexity=10 OptimizerDepth=10 OptimizerRecurDepth=10 \
+ OptimizerInLocal OPTPEEP
+#OPTIMIZE = NOOPT
+
+# no optimization, (works on all platforms)
+#OPTIMIZE=NOOPT
+
+#generate code for your processor - note however, that the 060 selection will work for 040's
+# as well.
+#CPU=68000
+#CPU=68020
+#CPU=68030
+#CPU=68040
+CPU=68060
+
+
+#Error reporting - I use rexx for reporting, but console reporting may be more
+#useful for some people.
+#ERROR = ERRORCONSOLE ERRORSOURCE ERRORHIGHLIGHT
+ERROR = ERRORREXX ERRORCONSOLE ERRORSOURCE ERRORHIGHLIGHT
+
+
+#memory types, if you have fast use it :->,
+# ANY = will work on all machines
+# FAST = this is the best option, for speed
+# CHIP = not necessary for this application.
+#MEMORYTYPE=FAST
+MEMORYTYPE=ANY
+
+#MEMSIZE - this is for compile time only for speed of compilation
+#default is LARGE
+MEMSIZE=HUGE
+#MEMSIZE=LARGE
+#MEMSIZE=SMALL
+
+#>>>>> end of choices
+###########################################################################
+
+CC = sc
+
+GST=vim.gst
+DEP = $(GST)
+
+
+CFLAGS = NOLINK $(DBG) CPU=$(CPU) NOSTACKCHECK
+CFLAGS2 = $(OPTIMIZE) $(ERROR) GSTIMMEDIATE GST=$(GST)
+CFLAGS3 =NOSINT SCODE SDATA STRINGMERGE MEMSIZE=$(MEMSIZE)
+CFLAGS4 = $(DEFINES) DATAMEMORY=$(MEMORYTYPE)
+
+PROPT = DEF=PROTO GPROTO GPPARM MAXIMUMERRORS=999 GENPROTOSTATICS GENPROTOPARAMETERS
+
+SRC = \
+ buffer.c \
+ charset.c \
+ diff.c \
+ digraph.c \
+ edit.c \
+ eval.c \
+ ex_cmds.c \
+ ex_cmds2.c \
+ ex_docmd.c \
+ ex_eval.c \
+ ex_getln.c \
+ fileio.c \
+ fold.c \
+ getchar.c \
+ main.c \
+ mark.c \
+ memfile.c \
+ memline.c \
+ menu.c \
+ message.c \
+ misc1.c \
+ misc2.c \
+ move.c \
+ normal.c \
+ ops.c \
+ option.c \
+ os_amiga.c \
+ quickfix.c \
+ regexp.c \
+ screen.c \
+ search.c \
+ syntax.c \
+ tag.c \
+ term.c \
+ ui.c \
+ undo.c \
+ window.c \
+ version.c \
+ gui_amiga.c \
+ gui.c
+
+OBJ = buffer.o charset.o diff.o digraph.o edit.o eval.o ex_cmds.o ex_cmds2.o ex_docmd.o ex_eval.o ex_getln.o \
+ fileio.o fold.o getchar.o main.o mark.o memfile.o memline.o menu.o message.o misc1.o misc2.o move.o \
+ normal.o ops.o option.o os_amiga.o quickfix.o regexp.o screen.o search.o syntax.o \
+ tag.o term.o ui.o undo.o window.o gui_amiga.o gui.o $(TERMLIB)
+
+PRO = \
+ buffer.pro \
+ charset.pro \
+ diff.pro \
+ digraph.pro \
+ edit.pro \
+ eval.pro \
+ ex_cmds.pro \
+ ex_cmds2.pro \
+ ex_docmd.pro \
+ ex_eval.pro \
+ ex_getln.pro \
+ fileio.pro \
+ fold.pro \
+ getchar.pro \
+ main.pro \
+ mark.pro \
+ memfile.pro \
+ memline.pro \
+ menu.pro \
+ message.pro \
+ misc1.pro \
+ misc2.pro \
+ move.pro \
+ normal.pro \
+ ops.pro \
+ option.pro \
+ os_amiga.pro \
+ quickfix.pro \
+ regexp.pro \
+ screen.pro \
+ search.pro \
+ syntax.pro \
+ tag.pro \
+ term.pro \
+ termlib.pro \
+ ui.pro \
+ undo.pro \
+ window.pro \
+ version.pro \
+ gui_amiga.pro \
+ gui.pro
+
+all:
+ @echo "$(BCOL2)building prototypes, this may take some time$(ANSIOFF)"
+ @smake proto
+ @echo "$(BCOL2)building vim production version$(ANSIOFF)"
+ @smake vim
+
+Vim: scoptions proto $(OBJ) version.c version.h
+ $(CC) $(CFLAGS) version.c
+ $(CC) LINK $(OPT) $(COPTS) $(OBJ) version.o $(DBG) PNAME=Vim
+
+debug: scoption protos $(OBJ) version.c version.h
+ $(CC) $(CFLAGS) version.c
+ $(CC) LINK $(COPTS) $(OBJ) version.o $(DBG) PNAME=Vim
+
+proto: $(PRO)
+
+tags: $(SRC)
+ spat ctags $(SRC) *.h
+ #csh -c ctags $(SRC) *.h
+
+# can't use delete here, too many file names
+clean:
+ @echo removing all object files
+ -delete $(OBJ) >nil:
+
+clobber: clean
+ @echo removing all prototype files
+ -delete $(PRO) SCOPTIONS vim $(GST) > NIL:
+
+
+# generate an options file, as there is no way the amiga command line can handle the
+# lengths that this makefile will impose on the shell.
+scoptions: smakefile
+ @echo "$(BCOL2)Generating $(ANSIOFF)$(FCOL4)- $@$(ANSIOFF)"
+ @echo $(CFLAGS) > scoptions
+ @echo $(CFLAGS1) >> scoptions
+ @echo $(CFLAGS2) >> scoptions
+ @echo $(CFLAGS3) >> scoptions
+ @echo $(CFLAGS4) >> scoptions
+ @echo $(COPTS) >>scoptions
+ @echo scoptions has been built
+
+
+#generate GlobalSymbolTable, which both speeds up the compile time, but also
+#solves some problems with prototypes, and types that are defined in a unixy
+#manner.
+#
+#I use a preprocessing stage here to work arounda bug in the GST generator, in
+#that it does not handle nested makefiles properly in this stage.
+$(GST): scoptions vim.h keymap.h macros.h ascii.h term.h structs.h gui.h gui_amiga.h
+ @echo "$(BCOL2)Generating Global Symbol Table $(ANSIOFF)$(FCOL4) $(GST) $(ANSIOFF)"
+ $(CC) PREPROCESSORONLY gui_amiga.h objectname pre.h
+ $(CC) MGST=$(GST) pre.h ignore=105,316
+ del pre.h
+
+
+###########################################################################
+
+.c.o:
+ @echo "$(BCOL2)Generating object for $(ANSIOFF)$(FCOL4) $*.c -> $@$(ANSIOFF)"
+ $(CC) $*.c
+
+.c.pro:
+ @echo "$(BCOL2)Generating prototypes for $(ANSIOFF)$(FCOL4) $*.c -> $@$(ANSIOFF)"
+ @$(CC) NOERRORREXX GPFILE=$*.pro $(PROPT) $*.c ignore=306,316,317,304
+
+$(PRO): $(GST)
+$(OBJ): $(GST)
+
+# dependancies
+buffer.o: buffer.c $(DEP)
+buffer.pro: buffer.c $(DEP)
+charset.o: charset.c $(DEP)
+charset.pro: charset.c $(DEP)
+diff.o: diff.c $(DEP)
+diff.pro: diff.c $(DEP)
+digraph.o: digraph.c $(DEP)
+digraph.pro: digraph.c $(DEP)
+edit.o: edit.c $(DEP)
+edit.pro: edit.c $(DEP)
+eval.o: eval.c $(DEP)
+eval.pro: eval.c $(DEP)
+ex_cmds.o: ex_cmds.c $(DEP)
+ex_cmds.pro: ex_cmds.c $(DEP)
+ex_cmds2.o: ex_cmds2.c $(DEP)
+ex_cmds2.pro: ex_cmds2.c $(DEP)
+ex_docmd.o: ex_docmd.c ex_cmds.h $(DEP)
+ex_docmd.pro: ex_docmd.c ex_cmds.h $(DEP)
+ex_eval.o: ex_eval.c ex_cmds.h $(DEP)
+ex_eval.pro: ex_eval.c ex_cmds.h $(DEP)
+ex_getln.o: ex_getln.c $(DEP)
+ex_getln.pro: ex_getln.c $(DEP)
+fileio.o: fileio.c $(DEP)
+fileio.pro: fileio.c $(DEP)
+fold.o: fold.c $(DEP)
+fold.pro: fold.c $(DEP)
+getchar.o: getchar.c $(DEP)
+getchar.pro: getchar.c $(DEP)
+main.o: main.c globals.h $(DEP)
+main.pro: main.c globals.h $(DEP)
+mark.o: mark.c $(DEP)
+mark.pro: mark.c $(DEP)
+memfile.o: memfile.c $(DEP)
+memfile.pro: memfile.c $(DEP)
+memline.o: memline.c $(DEP)
+memline.pro: memline.c $(DEP)
+menu.o: menu.c $(DEP)
+menu.pro: menu.c $(DEP)
+message.o: message.c $(DEP)
+message.pro: message.c $(DEP)
+misc1.o: misc1.c $(DEP)
+misc1.pro: misc1.c $(DEP)
+misc2.o: misc2.c $(DEP)
+misc2.pro: misc2.c $(DEP)
+move.o: move.c $(DEP)
+move.pro: move.c $(DEP)
+normal.o: normal.c $(DEP)
+normal.pro: normal.c $(DEP)
+ops.o: ops.c $(DEP)
+ops.pro: ops.c $(DEP)
+option.o: option.c $(DEP)
+option.pro: option.c $(DEP)
+os_amiga.o: os_amiga.c $(DEP)
+os_amiga.pro: os_amiga.c $(DEP)
+quickfix.o: quickfix.c $(DEP)
+quickfix.pro: quickfix.c $(DEP)
+regexp.o: regexp.c $(DEP)
+regexp.pro: regexp.c $(DEP)
+screen.o: screen.c $(DEP)
+screen.pro: screen.c $(DEP)
+search.o: search.c $(DEP)
+search.pro: search.c $(DEP)
+syntax.o: syntax.c $(DEP)
+syntax.pro: syntax.c $(DEP)
+tag.o: tag.c $(DEP)
+tag.pro: tag.c $(DEP)
+term.o: term.c $(DEP)
+term.pro: term.c $(DEP)
+termlib.o: termlib.c $(DEP)
+termlib.pro: termlib.c $(DEP)
+ui.o: ui.c $(DEP)
+ui.pro: ui.c $(DEP)
+undo.o: undo.c $(DEP)
+undo.pro: undo.c $(DEP)
+window.o: window.c $(DEP)
+window.pro: window.c $(DEP)
+gui_amiga.o: gui_amiga.c $(DEP) amiga.h
+#gui_amiga.pro: gui_amiga.c $(DEP) amiga.h
+amiga.o: amiga.c $(DEP) amiga.h
+amiga.pro: amiga.c $(DEP) amiga.h
+gui.o: gui.c $(DEP)
+gui.pro: gui.c $(DEP)
diff --git a/src/Make_aros.mak b/src/Make_aros.mak
new file mode 100644
index 000000000..5d26eef0e
--- /dev/null
+++ b/src/Make_aros.mak
@@ -0,0 +1,29 @@
+# Makefile for AROS
+
+CFLAGS = -pipe -O2 -Wall -Iproto \
+ -DNO_ARP -DUSE_TMPNAM -DFEAT_GUI_AMIGA
+
+PRG = VIM
+LIBS =
+CC = i386-linux-aros-gcc
+LD = i386-linux-aros-gcc
+RM = rm
+
+SRCS = buffer.c charset.c diff.c digraph.c edit.c eval.c ex_cmds.c \
+ ex_cmds2.c ex_docmd.c ex_eval.c ex_getln.c fileio.c fold.c getchar.c \
+ main.c mark.c mbyte.c memfile.c memline.c menu.c message.c misc1.c \
+ misc2.c move.c normal.c ops.c option.c os_amiga.c quickfix.c \
+ regexp.c screen.c search.c syntax.c tag.c term.c ui.c undo.c \
+ version.c window.c gui_amiga.c gui.c
+
+OBJS = $(SRCS:.c=.o)
+
+
+$(PRG): $(OBJS)
+ ${LD} -o $(PRG) $(OBJS) $(LIBS)
+
+.c.o:
+ ${CC} -c ${CFLAGS} $< -o $@
+
+clean:
+ $(RM) -fv $(OBJS) $(PRG)
diff --git a/src/Make_bc3.mak b/src/Make_bc3.mak
new file mode 100644
index 000000000..1d27081a1
--- /dev/null
+++ b/src/Make_bc3.mak
@@ -0,0 +1,173 @@
+# Makefile for Borland C++ 3.1 or 4.0 to compile a 16 bit version of Vim.
+#
+# There are compilation options at the end of this file.
+#
+# Command line variables:
+# BOR path to root of Borland C (E:\BORLANDC)
+# DEBUG set to "yes" for debugging (no)
+# SPAWNO path to the spawno library directory, empty if you do not have
+# it; use 8.3 filenames! (C:\CC\SPAWN)
+
+.AUTODEPEND
+
+!ifndef BOR
+BOR = E:\BORLANDC
+!endif
+
+!if ("$(DEBUG)" == "yes")
+DEBUG_FLAG = -v
+!else
+DEBUG_FLAG =
+!endif
+
+CC = $(BOR)\bin\bcc.exe +VIM.CFG
+TLINK = $(BOR)\bin\tlink.exe
+
+!ifndef SPAWNO
+SPAWNO = C:\CC\SPAWN
+!endif
+
+!if ("$(SPAWNO)" == "")
+LIBPATH = $(BOR)\LIB
+INCLUDEPATH = $(BOR)\INCLUDE
+SPAWND =
+SPAWNL =
+!else
+LIBPATH = $(BOR)\LIB;$(SPAWNO)
+INCLUDEPATH = $(BOR)\INCLUDE;$(SPAWNO)
+SPAWND = ;SPAWNO
+SPAWNL = spawnl.lib
+!endif
+
+
+# *Implicit Rules*
+#
+# use -v for debugging
+#
+.c.obj:
+ $(CC) -c $(DEBUG_FLAG) {$< }
+
+# *List Macros*
+
+
+EXE_dependencies = \
+ buffer.obj \
+ charset.obj \
+ diff.obj \
+ digraph.obj \
+ edit.obj \
+ eval.obj \
+ ex_cmds.obj \
+ ex_cmds2.obj \
+ ex_docmd.obj \
+ ex_eval.obj \
+ ex_getln.obj \
+ fileio.obj \
+ fold.obj \
+ getchar.obj \
+ main.obj \
+ mark.obj \
+ memfile.obj \
+ memline.obj \
+ menu.obj \
+ message.obj \
+ misc1.obj \
+ misc2.obj \
+ move.obj \
+ os_msdos.obj \
+ normal.obj \
+ ops.obj \
+ option.obj \
+ quickfix.obj \
+ regexp.obj \
+ screen.obj \
+ search.obj \
+ syntax.obj \
+ tag.obj \
+ term.obj \
+ ui.obj \
+ undo.obj \
+ window.obj
+
+all: vim.exe install.exe uninstal.exe xxd/xxd.exe
+
+# *Explicit Rules*
+
+vim.exe: vim.cfg $(EXE_dependencies) version.c
+ $(CC) $(DEBUG_FLAG) -c version.c
+ $(TLINK) /x/c/L$(LIBPATH) $(DEBUG_FLAG) @&&|
+c0l.obj $(EXE_dependencies) version.obj
+vim
+ # no map file
+$(SPAWNL) cl.lib
+|
+
+install.exe: dosinst.c
+ $(CC) -einstall $(DEBUG_FLAG) dosinst.c
+
+uninstal.exe: uninstal.c
+ $(CC) $(DEBUG_FLAG) uninstal.c
+
+# This may fail for older make versions, building xxd will fail anyway then.
+xxd/xxd.exe: xxd/xxd.c
+ cd xxd
+ $(MAKE) -f Make_bc3.mak BOR=$(BOR) DEBUG=$(DEBUG)
+ cd ..
+
+# cleaning up: Delete all generated files
+clean:
+ -del *.obj
+ -del vim.exe
+ -del vim.sym
+ -del install.exe
+ -del uninstal.exe
+ -del xxd\*.obj
+ -del xxd\xxd.exe
+ -del vim.cfg
+ -del testdir\*.out
+
+# Individual File Dependencies (incomplete)
+ex_docmd.obj: ex_docmd.c ex_cmds.h
+
+ex_eval.obj: ex_eval.c ex_cmds.h
+
+main.obj: main.c globals.h option.h
+
+term.obj: term.c term.h
+
+version.obj: version.c version.h
+
+
+# Compiler Configuration File
+#
+# The following compile options can be changed for better machines.
+# replace -1- with -2 to produce code for a 80286 or higher
+# replace -1- with -3 to produce code for a 80386 or higher
+# add -v for source debugging
+vim.cfg: Make_bc3.mak
+ copy &&|
+-ml
+-1-
+-f-
+-C
+-N
+-O
+-Z
+-k-
+-d
+-h
+-vi-
+-H=VIM.SYM
+-w-par
+-weas
+-wpre
+-Iproto
+-I$(INCLUDEPATH)
+-L$(LIBPATH)
+-DMSDOS$(SPAWND)
+| vim.cfg
+
+test:
+ cd testdir
+ $(MAKE) -f Make_dos.mak small
+ cd ..
diff --git a/src/Make_bc5.mak b/src/Make_bc5.mak
new file mode 100644
index 000000000..73d9440d8
--- /dev/null
+++ b/src/Make_bc5.mak
@@ -0,0 +1,1006 @@
+#
+# Makefile for Vim.
+# Compiler: Borland C++ 5.0 and later 32-bit compiler
+# Targets: Dos16 or Win32 (Windows NT and Windows 95) (with/without GUI)
+#
+# Contributed by Ben Singer.
+# Updated 4/1997 by Ron Aaron
+# 6/1997 - added support for 16 bit DOS
+# Note: this has been tested, and works, for BC5. Your mileage may vary.
+# Has been reported NOT to work with BC 4.52. Maybe it can be fixed?
+# 10/1997 - ron - fixed bugs w/ BC 5.02
+# 8/1998 - ron - updated with new targets, fixed some stuff
+# 3/2000 - Bram: Made it work with BC 5.5 free command line compiler,
+# cleaned up variables.
+# 6/2001 - Dan - Added support for compiling Python and TCL
+# 7/2001 - Dan - Added support for compiling Ruby
+#
+# It builds on Windows 95 and NT-Intel, producing the same binary in either
+# case. To build using Microsoft Visual C++, use Make_mvc.mak.
+#
+# This should work with the free Borland command line compiler, version 5.5.
+# You need at least sp1 (service pack 1). With sp2 it compiles faster.
+# Use a command like this:
+# <path>\bin\make /f Make_bc5.mak BOR=<path>
+#
+
+# let the make utility do the hard work:
+.AUTODEPEND
+.CACHEAUTODEPEND
+
+# VARIABLES:
+# name value (default)
+#
+# BOR path to root of Borland C install (c:\bc5)
+# LINK name of the linker ($(BOR)\bin\ilink if OSTYPE is DOS16,
+# $(BOR)\bin\ilink32 otherwise)
+# GUI no or yes: set to yes if you want the GUI version (yes)
+# PERL define to path to Perl dir to get Perl support (not defined)
+# PERL_VER define to version of Perl being used (56)
+# DYNAMIC_PERL no or yes: set to yes to load the Perl DLL dynamically (no)
+# PYTHON define to path to Python dir to get PYTHON support (not defined)
+# PYTHON_VER define to version of Python being used (22)
+# DYNAMIC_PYTHON no or yes: use yes to load the Python DLL dynamically (no)
+# TCL define to path to TCL dir to get TCL support (not defined)
+# TCL_VER define to version of TCL being used (83)
+# DYNAMIC_TCL no or yes: use yes to load the TCL DLL dynamically (no)
+# RUBY define to path to Ruby dir to get Ruby support (not defined)
+# NOTE: You may have to remove the defines for uid_t and gid_t
+# from the Ruby config.h header file.
+# RUBY_VER define to version of Ruby being used (16)
+# NOTE: compilation on WinNT/2K/XP requires
+# at least version 1.6.5 of Ruby. Earlier versions
+# of Ruby will cause a compile error on these systems.
+# DYNAMIC_RUBY no or yes: use yes to load the Ruby DLL dynamically (no)
+# MBYTE no or yes: set to yes for multi-byte support (yes)
+# IME no or yes: set to yes for multi-byte IME support (yes)
+# DYNAMIC_IME no or yes: set to yes to load imm32.dll dynamically (yes)
+# GETTEXT no or yes: set to yes for multi-language support (yes)
+# ICONV no or yes: set to yes for dynamic iconv support (yes)
+# OLE no or yes: set to yes to make OLE gvim (no)
+# OSTYPE DOS16 or WIN32 (WIN32)
+# DEBUG no or yes: set to yes if you wish a DEBUGging build (no)
+# CODEGUARD no or yes: set to yes if you want to use CODEGUARD (no)
+# CPUNR 1 through 6: select -CPU argument to compile with (3)
+# 3 for 386, 4 for 486, 5 for pentium, 6 for pentium pro.
+# USEDLL no or yes: set to yes to use the Runtime library DLL (no)
+# For USEDLL=yes the cc3250.dll is required to run Vim.
+# VIMDLL no or yes: create vim32.dll, and stub (g)vim.exe (no)
+# ALIGN 1, 2 or 4: Alignment to use (4 for Win32, 2 for DOS16)
+# FASTCALL no or yes: set to yes to use register-based function protocol (yes)
+# OPTIMIZE SPACE, SPEED, or MAXSPEED: type of optimization (MAXSPEED)
+# POSTSCRIPT no or yes: set to yes for PostScript printing
+# FEATURES TINY, SMALL, NORMAL, BIG or HUGE
+# (BIG for WIN32, SMALL for DOS16)
+# WINVER 0x0400 or 0x0500: minimum Win32 version to support (0x0400)
+# CSCOPE no or yes: include support for Cscope interface (yes)
+# NETBEANS no or yes: include support for Netbeans interface (yes if GUI
+# is yes)
+# XPM define to path to XPM dir to get support for loading XPM images.
+
+### BOR: root of the BC installation
+!if ("$(BOR)"=="")
+BOR = c:\bc5
+!endif
+
+### LINK: Name of the linker: tlink or ilink32 (this is below, depends on
+# $(OSTYPE)
+
+### GUI: yes for GUI version, no for console version
+!if ("$(GUI)"=="")
+GUI = yes
+!endif
+
+### MBYTE: yes for multibyte support, no to disable it.
+!if ("$(MBYTE)"=="")
+MBYTE = yes
+!endif
+
+### IME: yes for multibyte support, no to disable it.
+!if ("$(IME)"=="")
+IME = yes
+!endif
+!if ("$(DYNAMIC_IME)"=="")
+DYNAMIC_IME = yes
+!endif
+
+### GETTEXT: yes for multilanguage support, no to disable it.
+!if ("$(GETTEXT)"=="")
+GETTEXT = yes
+!endif
+
+### ICONV: yes to enable dynamic-iconv support, no to disable it
+!if ("$(ICONV)"=="")
+ICONV = yes
+!endif
+
+### CSCOPE: yes to enable Cscope support, no to disable it
+!if ("$(CSCOPE)"=="")
+CSCOPE = yes
+!endif
+
+### NETBEANS: yes to enable NetBeans interface support, no to disable it
+!if ("$(NETBEANS)"=="") && ("$(GUI)"=="yes")
+NETBEANS = yes
+!endif
+
+### PERL: uncomment this line if you want perl support in vim
+# PERL=c:\perl
+
+### PYTHON: uncomment this line if you want python support in vim
+# PYTHON=c:\python22
+
+### RUBY: uncomment this line if you want ruby support in vim
+# RUBY=c:\ruby
+
+### TCL: uncomment this line if you want tcl support in vim
+# TCL=c:\tcl
+
+### OLE: no for normal gvim, yes for OLE-capable gvim (only works with GUI)
+#OLE = yes
+
+### OSTYPE: DOS16 for Windows 3.1 version, WIN32 for Windows 95/98/NT/2000
+# version
+!if ("$(OSTYPE)"=="")
+OSTYPE = WIN32
+!endif
+
+### DEBUG: Uncomment to make an executable for debugging
+# DEBUG = yes
+!if ("$(DEBUG)"=="yes")
+DEBUG_FLAG = -v
+!endif
+
+### CODEGUARD: Uncomment to use the CODEGUARD stuff (BC 5.0 or later):
+# CODEGUARD = yes
+!if ("$(CODEGUARD)"=="yes")
+CODEGUARD_FLAG = -vG
+!endif
+
+### CPUNR: set your target processor (3 to 6)
+!if ("$(CPUNR)" == "i386") || ("$(CPUNR)" == "3")
+CPUNR = 3
+!elif ("$(CPUNR)" == "i486") || ("$(CPUNR)" == "4")
+CPUNR = 4
+!elif ("$(CPUNR)" == "i586") || ("$(CPUNR)" == "5")
+CPUNR = 5
+!elif ("$(CPUNR)" == "i686") || ("$(CPUNR)" == "6")
+CPUNR = 6
+!else
+CPUNR = 3
+!endif
+
+### Comment out to use precompiled headers (faster, but uses lots of disk!)
+HEADERS = -H -H=vim.csm -Hc
+
+### USEDLL: no for statically linked version of run-time, yes for DLL runtime
+!if ("$(USEDLL)"=="")
+USEDLL = no
+!endif
+
+### VIMDLL: yes for a DLL version of VIM (NOT RECOMMENDED), no otherwise
+#VIMDLL = yes
+
+### ALIGN: alignment you desire: (1,2 or 4: s/b 4 for Win32, 2 for DOS)
+!if ("$(ALIGN)"=="")
+!if ($(OSTYPE)==DOS16)
+ALIGN = 2
+!else
+ALIGN = 4
+!endif
+!endif
+
+### FASTCALL: yes to use FASTCALL calling convention (RECOMMENDED!), no otherwise
+# Incompatible when calling external functions (like MSVC-compiled DLLs), so
+# don't use FASTCALL when linking with external libs.
+!if ("$(FASTCALL)"=="") && \
+ ("$(PYTHON)"=="") && \
+ ("$(PERL)"=="") && \
+ ("$(TCL)"=="") && \
+ ("$(RUBY)"=="") && \
+ ("$(ICONV)"!="yes") && \
+ ("$(IME)"!="yes") && \
+ ("$(MBYTE)"!="yes") && \
+ ("$(XPM)"=="")
+FASTCALL = yes
+!endif
+
+### OPTIMIZE: SPEED to optimize for speed, SPACE otherwise (SPEED RECOMMENDED)
+!if ("$(OPTIMIZE)"=="")
+OPTIMIZE = MAXSPEED
+!endif
+
+### FEATURES: TINY, SMALL, NORMAL, BIG or HUGE (BIG for WIN32, SMALL for DOS16)
+!if ("$(FEATURES)"=="")
+! if ($(OSTYPE)==DOS16)
+FEATURES = SMALL
+! else
+FEATURES = BIG
+! endif
+!endif
+
+### POSTSCRIPT: uncomment this line if you want PostScript printing
+#POSTSCRIPT = yes
+
+###
+# If you have a fixed directory for $VIM or $VIMRUNTIME, other than the normal
+# default, use these lines.
+#VIMRCLOC = somewhere
+#VIMRUNTIMEDIR = somewhere
+
+### Set the default $(WINVER) to make it work with Bcc 5.5.
+!ifndef WINVER
+WINVER = 0x0400
+!endif
+
+#
+# Sanity checks for the above options:
+#
+
+!if ($(OSTYPE)==DOS16)
+!if (($(CPUNR)+0)>4)
+!error CPUNR Must be less than or equal to 4 for DOS16
+!endif
+
+!if (($(ALIGN)+0)>2)
+!error ALIGN Must be less than or equal to 2 for DOS16
+!endif
+
+!else # not DOS16
+!if (($(CPUNR)+0)<3)
+!error CPUNR Must be greater or equal to 3 for WIN32
+!endif
+!endif
+
+!if ($(OSTYPE)!=WIN32) && ($(OSTYPE)!=DOS16)
+!error Check the OSTYPE variable again: $(OSTYPE) is not supported!
+!endif
+
+#
+# Optimizations: change as desired (RECOMMENDATION: Don't change!):
+#
+!if ("$(DEBUG)"=="yes")
+OPT = -Od -N
+!else
+!if ("$(OPTIMIZE)"=="SPACE")
+OPT = -O1 -f- -d
+!elif ("$(OPTIMIZE)"=="MAXSPEED")
+OPT = -O2 -f- -d -Ocavi -O
+!else
+OPT = -O2 -f- -d -Oc -O
+!endif
+!if ("$(FASTCALL)"=="yes")
+OPT = $(OPT) -pr
+!endif
+!if ("$(CODEGUARD)"!="yes")
+OPT = $(OPT) -vi-
+!endif
+!endif
+!if ($(OSTYPE)==DOS16)
+!undef GUI
+!undef VIMDLL
+!undef USEDLL
+!endif
+# shouldn't have to change:
+LIB = $(BOR)\lib
+INCLUDE = $(BOR)\include;.;proto
+DEFINES = -DFEAT_$(FEATURES) -DWIN32 -DHAVE_PATHDEF \
+ -DWINVER=$(WINVER) -D_WIN32_WINNT=$(WINVER)
+
+!ifdef PERL
+INTERP_DEFINES = $(INTERP_DEFINES) -DFEAT_PERL
+INCLUDE = $(PERL)\lib\core;$(INCLUDE)
+! ifndef PERL_VER
+PERL_VER = 56
+! endif
+! if ("$(DYNAMIC_PERL)" == "yes")
+! if ($(PERL_VER) > 55)
+INTERP_DEFINES = $(INTERP_DEFINES) -DDYNAMIC_PERL -DDYNAMIC_PERL_DLL=\"perl$(PERL_VER).dll\"
+PERL_LIB_FLAG = /nodefaultlib:
+! else
+! message "Cannot dynamically load Perl versions less than 5.6. Loading statically..."
+! endif
+! endif
+!endif
+
+!ifdef PYTHON
+INTERP_DEFINES = $(INTERP_DEFINES) -DFEAT_PYTHON
+INCLUDE = $(PYTHON)\include;$(INCLUDE)
+!ifndef PYTHON_VER
+PYTHON_VER = 22
+!endif
+!if "$(DYNAMIC_PYTHON)" == "yes"
+INTERP_DEFINES = $(INTERP_DEFINES) -DDYNAMIC_PYTHON -DDYNAMIC_PYTHON_DLL=\"python$(PYTHON_VER).dll\"
+PYTHON_LIB_FLAG = /nodefaultlib:
+!endif
+!endif
+
+!ifdef RUBY
+!ifndef RUBY_VER
+RUBY_VER = 16
+!endif
+!ifndef RUBY_VER_LONG
+RUBY_VER_LONG = 1.6
+!endif
+
+!if "$(RUBY_VER)" == "16"
+!ifndef RUBY_PLATFORM
+RUBY_PLATFORM = i586-mswin32
+!endif
+!ifndef RUBY_INSTALL_NAME
+RUBY_INSTALL_NAME = mswin32-ruby$(RUBY_VER)
+!endif
+!else
+!ifndef RUBY_PLATFORM
+RUBY_PLATFORM = i386-mswin32
+!endif
+!ifndef RUBY_INSTALL_NAME
+RUBY_INSTALL_NAME = msvcrt-ruby$(RUBY_VER)
+!endif
+!endif
+
+INTERP_DEFINES = $(INTERP_DEFINES) -DFEAT_RUBY
+INCLUDE = $(RUBY)\lib\ruby\$(RUBY_VER_LONG)\$(RUBY_PLATFORM);$(INCLUDE)
+
+!if "$(DYNAMIC_RUBY)" == "yes"
+INTERP_DEFINES = $(INTERP_DEFINES) -DDYNAMIC_RUBY -DDYNAMIC_RUBY_DLL=\"$(RUBY_INSTALL_NAME).dll\"
+INTERP_DEFINES = $(INTERP_DEFINES) -DDYNAMIC_RUBY_VER=$(RUBY_VER)
+RUBY_LIB_FLAG = /nodefaultlib:
+!endif
+!endif
+
+!ifdef TCL
+INTERP_DEFINES = $(INTERP_DEFINES) -DFEAT_TCL
+INCLUDE = $(TCL)\include;$(INCLUDE)
+!ifndef TCL_VER
+TCL_VER = 83
+!endif
+TCL_LIB = $(TCL)\lib\tcl$(TCL_VER).lib
+TCL_LIB_FLAG =
+!if "$(DYNAMIC_TCL)" == "yes"
+INTERP_DEFINES = $(INTERP_DEFINES) -DDYNAMIC_TCL -DDYNAMIC_TCL_DLL=\"tcl$(TCL_VER).dll\"
+TCL_LIB = tclstub$(TCL_VER)-bor.lib
+TCL_LIB_FLAG =
+!endif
+!endif
+#
+# DO NOT change below:
+#
+CPUARG = -$(CPUNR)
+ALIGNARG = -a$(ALIGN)
+#
+!if ("$(DEBUG)"=="yes")
+DEFINES=$(DEFINES) -DDEBUG
+!endif
+#
+!if ("$(OLE)"=="yes")
+DEFINES = $(DEFINES) -DFEAT_OLE
+!endif
+#
+!if ("$(MBYTE)"=="yes")
+MBDEFINES = $(MBDEFINES) -DFEAT_MBYTE
+!endif
+!if ("$(IME)"=="yes")
+MBDEFINES = $(MBDEFINES) -DFEAT_MBYTE_IME
+!if ("$(DYNAMIC_IME)" == "yes")
+MBDEFINES = $(MBDEFINES) -DDYNAMIC_IME
+!endif
+!endif
+!if ("$(ICONV)"=="yes")
+MBDEFINES = $(MBDEFINES) -DDYNAMIC_ICONV
+!endif
+!if ("$(GETTEXT)"=="yes")
+MBDEFINES = $(MBDEFINES) -DDYNAMIC_GETTEXT
+!endif
+
+!if ("$(CSCOPE)"=="yes")
+DEFINES = $(DEFINES) -DFEAT_CSCOPE
+!endif
+
+!if ("$(NETBEANS)"=="yes")
+DEFINES = $(DEFINES) -DFEAT_NETBEANS_INTG
+!if ("$(DEBUG)"=="yes")
+DEFINES = $(DEFINES) -DNBDEBUG
+NBDEBUG_DEP = nbdebug.h nbdebug.c
+!endif
+!endif
+
+!ifdef XPM
+DEFINES = $(DEFINES) -DFEAT_XPM_W32
+INCLUDE = $(XPM)\include;$(INCLUDE)
+!endif
+
+!if ("$(GUI)"=="yes")
+DEFINES = $(DEFINES) -DFEAT_GUI_W32 -DFEAT_CLIPBOARD
+!if ("$(DEBUG)"=="yes")
+TARGET = gvimd.exe
+!else
+TARGET = gvim.exe
+!endif
+!if ("$(VIMDLL)"=="yes")
+EXETYPE=-WD
+DEFINES = $(DEFINES) -DVIMDLL
+!else
+EXETYPE=-W
+!endif
+STARTUPOBJ = c0w32.obj
+LINK2 = -aa
+RESFILE = vim.res
+!else
+!if ("$(DEBUG)"=="yes")
+TARGET = vimd.exe
+!else
+# for now, anyway: VIMDLL is only for the GUI version
+!undef VIMDLL
+TARGET = vim.exe
+!endif
+!if ($(OSTYPE)==DOS16)
+DEFINES= -DFEAT_$(FEATURES) -DMSDOS
+EXETYPE=-ml
+STARTUPOBJ = c0l.obj
+LINK2 =
+!else
+EXETYPE=-WC
+STARTUPOBJ = c0x32.obj
+LINK2 = -ap -OS -o -P
+!endif
+RESFILE = vim.res
+!endif
+
+!if ("$(USEDLL)"=="yes")
+DEFINES = $(DEFINES) -D_RTLDLL
+!endif
+
+!if ("$(DEBUG)"=="yes")
+OBJDIR = $(OSTYPE)\objdbg
+!else
+!if ("$(GUI)"=="yes")
+!if ("$(OLE)"=="yes")
+OBJDIR = $(OSTYPE)\oleobj
+!else
+OBJDIR = $(OSTYPE)\gobj
+!endif
+!else
+OBJDIR = $(OSTYPE)\obj
+!endif
+!endif
+
+!if ("$(POSTSCRIPT)"=="yes")
+DEFINES = $(DEFINES) -DMSWINPS
+!endif
+
+##### BASE COMPILER/TOOLS RULES #####
+MAKE = $(BOR)\bin\make
+CFLAGS = -w-aus -w-par -w-pch -w-ngu -w-csu -I$(INCLUDE)
+!if ($(OSTYPE)==DOS16)
+BRC =
+!if ("$(LINK)"=="")
+LINK = $(BOR)\BIN\TLink
+!endif
+CC = $(BOR)\BIN\Bcc
+LFLAGS = -Tde -c -m -L$(LIB) $(DEBUG_FLAG) $(LINK2)
+LFLAGSDLL =
+CFLAGS = $(CFLAGS) -H- $(HEADERS)
+!else
+BRC = $(BOR)\BIN\brc32
+!if ("$(LINK)"=="")
+LINK = $(BOR)\BIN\ILink32
+!endif
+CC = $(BOR)\BIN\Bcc32
+LFLAGS = -OS -Tpe -c -m -L$(LIB) $(DEBUG_FLAG) $(LINK2)
+LFLAGSDLL = -Tpd -c -m -L$(LIB) $(DEBUG_FLAG) $(LINK2)
+CFLAGS = $(CFLAGS) -d -RT- -k- -Oi $(HEADERS) -f-
+!endif
+
+CC1 = -c
+CC2 = -o
+CCARG = +$(OBJDIR)\bcc.cfg
+
+# implicit rules:
+
+# Without the following, the implicit rule in BUILTINS.MAK is picked up
+# for a rule for .c.obj rather than the local implicit rule
+.SUFFIXES
+.SUFFIXES .c .obj
+.path.c = .
+
+{.}.c{$(OBJDIR)}.obj:
+ $(CC) $(CCARG) $(CC1) -n$(OBJDIR)\ {$< }
+
+.cpp.obj:
+ $(CC) $(CCARG) $(CC1) $(CC2)$@ $*.cpp
+
+!if ($(OSTYPE)==DOS16)
+!else # win32:
+vimmain = \
+ $(OBJDIR)\os_w32exe.obj
+!if ("$(VIMDLL)"=="yes")
+vimwinmain = \
+ $(OBJDIR)\os_w32dll.obj
+!else
+vimwinmain = \
+ $(OBJDIR)\os_w32exe.obj
+!endif
+!endif
+
+vimobj = \
+ $(OBJDIR)\buffer.obj \
+ $(OBJDIR)\charset.obj \
+ $(OBJDIR)\diff.obj \
+ $(OBJDIR)\digraph.obj \
+ $(OBJDIR)\edit.obj \
+ $(OBJDIR)\eval.obj \
+ $(OBJDIR)\ex_cmds.obj \
+ $(OBJDIR)\ex_cmds2.obj \
+ $(OBJDIR)\ex_docmd.obj \
+ $(OBJDIR)\ex_eval.obj \
+ $(OBJDIR)\ex_getln.obj \
+ $(OBJDIR)\fileio.obj \
+ $(OBJDIR)\fold.obj \
+ $(OBJDIR)\getchar.obj \
+ $(OBJDIR)\main.obj \
+ $(OBJDIR)\mark.obj \
+ $(OBJDIR)\memfile.obj \
+ $(OBJDIR)\memline.obj \
+ $(OBJDIR)\menu.obj \
+ $(OBJDIR)\message.obj \
+ $(OBJDIR)\misc1.obj \
+ $(OBJDIR)\misc2.obj \
+ $(OBJDIR)\move.obj \
+ $(OBJDIR)\mbyte.obj \
+ $(OBJDIR)\normal.obj \
+ $(OBJDIR)\ops.obj \
+ $(OBJDIR)\option.obj \
+ $(OBJDIR)\quickfix.obj \
+ $(OBJDIR)\regexp.obj \
+ $(OBJDIR)\screen.obj \
+ $(OBJDIR)\search.obj \
+ $(OBJDIR)\syntax.obj \
+ $(OBJDIR)\tag.obj \
+ $(OBJDIR)\term.obj \
+ $(OBJDIR)\ui.obj \
+ $(OBJDIR)\undo.obj \
+ $(OBJDIR)\version.obj \
+ $(OBJDIR)\window.obj \
+ $(OBJDIR)\pathdef.obj
+
+!if ("$(OLE)"=="yes")
+vimobj = $(vimobj) \
+ $(OBJDIR)\if_ole.obj
+!endif
+
+!ifdef PERL
+vimobj = $(vimobj) \
+ $(OBJDIR)\if_perl.obj
+!endif
+
+!ifdef PYTHON
+vimobj = $(vimobj) \
+ $(OBJDIR)\if_python.obj
+!endif
+
+!ifdef RUBY
+vimobj = $(vimobj) \
+ $(OBJDIR)\if_ruby.obj
+!endif
+
+!ifdef TCL
+vimobj = $(vimobj) \
+ $(OBJDIR)\if_tcl.obj
+!endif
+
+!if ("$(CSCOPE)"=="yes")
+vimobj = $(vimobj) \
+ $(OBJDIR)\if_cscope.obj
+!endif
+
+!if ("$(NETBEANS)"=="yes")
+vimobj = $(vimobj) \
+ $(OBJDIR)\netbeans.obj $(OBJDIR)\gui_beval.obj
+!endif
+
+!ifdef XPM
+vimobj = $(vimobj) \
+ $(OBJDIR)\xpm_w32.obj
+!endif
+
+!if ("$(VIMDLL)"=="yes")
+vimdllobj = $(vimobj)
+!if ("$(DEBUG)"=="yes")
+DLLTARGET = vim32d.dll
+!else
+DLLTARGET = vim32.dll
+!endif
+!else
+DLLTARGET = joebob
+!endif
+
+!if ("$(GUI)"=="yes")
+vimobj = $(vimobj) \
+ $(vimwinmain) \
+ $(OBJDIR)\gui.obj \
+ $(OBJDIR)\gui_w32.obj
+!endif
+
+!if ($(OSTYPE)==WIN32)
+vimobj = $(vimobj) \
+ $(OBJDIR)\os_win32.obj $(OBJDIR)\os_mswin.obj
+!elif ($(OSTYPE)==DOS16)
+vimobj = $(vimobj) \
+ $(OBJDIR)\os_msdos.obj
+!endif
+# Blab what we are going to do:
+MSG = Compiling $(OSTYPE) $(TARGET) $(OLETARGET), with:
+!if ("$(GUI)"=="yes")
+MSG = $(MSG) GUI
+!endif
+!if ("$(OLE)"=="yes")
+MSG = $(MSG) OLE
+!endif
+!if ("$(USEDLL)"=="yes")
+MSG = $(MSG) USEDLL
+!endif
+!if ("$(VIMDLL)"=="yes")
+MSG = $(MSG) VIMDLL
+!endif
+!if ("$(FASTCALL)"=="yes")
+MSG = $(MSG) FASTCALL
+!endif
+!if ("$(MBYTE)"=="yes")
+MSG = $(MSG) MBYTE
+!endif
+!if ("$(IME)"=="yes")
+MSG = $(MSG) IME
+! if "$(DYNAMIC_IME)" == "yes"
+MSG = $(MSG)(dynamic)
+! endif
+!endif
+!if ("$(GETTEXT)"=="yes")
+MSG = $(MSG) GETTEXT
+!endif
+!if ("$(ICONV)"=="yes")
+MSG = $(MSG) ICONV
+!endif
+!if ("$(DEBUG)"=="yes")
+MSG = $(MSG) DEBUG
+!endif
+!if ("$(CODEGUARD)"=="yes")
+MSG = $(MSG) CODEGUARD
+!endif
+!if ("$(CSCOPE)"=="yes")
+MSG = $(MSG) CSCOPE
+!endif
+!if ("$(NETBEANS)"=="yes")
+MSG = $(MSG) NETBEANS
+!endif
+!ifdef XPM
+MSG = $(MSG) XPM
+!endif
+!ifdef PERL
+MSG = $(MSG) PERL
+! if "$(DYNAMIC_PERL)" == "yes"
+MSG = $(MSG)(dynamic)
+! endif
+!endif
+!ifdef PYTHON
+MSG = $(MSG) PYTHON
+! if "$(DYNAMIC_PYTHON)" == "yes"
+MSG = $(MSG)(dynamic)
+! endif
+!endif
+!ifdef RUBY
+MSG = $(MSG) RUBY
+! if "$(DYNAMIC_RUBY)" == "yes"
+MSG = $(MSG)(dynamic)
+! endif
+!endif
+!ifdef TCL
+MSG = $(MSG) TCL
+! if "$(DYNAMIC_TCL)" == "yes"
+MSG = $(MSG)(dynamic)
+! endif
+!endif
+MSG = $(MSG) cpu=$(CPUARG)
+MSG = $(MSG) Align=$(ALIGNARG)
+
+!message $(MSG)
+
+!if ($(OSTYPE)==DOS16)
+TARGETS = $(TARGET)
+!else
+!if ("$(VIMDLL)"=="yes")
+TARGETS = $(DLLTARGET)
+!endif
+TARGETS = $(TARGETS) $(TARGET)
+!endif
+
+# Targets:
+all: vim vimrun.exe install.exe xxd uninstal.exe GvimExt/gvimext.dll
+
+vim: $(OSTYPE) $(OBJDIR) $(OBJDIR)\bcc.cfg $(TARGETS)
+ @if exist $(OBJDIR)\version.obj del $(OBJDIR)\version.obj
+ @if exist auto\pathdef.c del auto\pathdef.c
+
+$(OSTYPE):
+ -@md $(OSTYPE)
+
+$(OBJDIR):
+ -@md $(OBJDIR)
+
+xxd:
+ @cd xxd
+ $(MAKE) /f Make_bc5.mak BOR="$(BOR)" BCC="$(CC)"
+ @cd ..
+
+GvimExt/gvimext.dll: GvimExt/gvimext.cpp GvimExt/gvimext.rc GvimExt/gvimext.h
+ cd GvimExt
+ $(MAKE) /f Make_bc5.mak USEDLL=$(USEDLL) BOR=$(BOR)
+ cd ..
+
+install.exe: dosinst.c $(OBJDIR)\bcc.cfg
+!if ($(OSTYPE)==WIN32)
+ $(CC) $(CCARG) -WC -DWIN32 -einstall dosinst.c
+!else
+ $(CC) $(CCARG) -WC -einstall dosinst.c
+!endif
+
+uninstal.exe: uninstal.c $(OBJDIR)\bcc.cfg
+!if ($(OSTYPE)==WIN32)
+ $(CC) $(CCARG) -WC -DWIN32 -O2 -euninstal uninstal.c
+!else
+ $(CC) $(CCARG) -WC -O2 -euninstal uninstal.c
+!endif
+
+clean:
+!if "$(OS)" == "Windows_NT"
+ # For Windows NT/2000, doesn't work on Windows 95/98...
+ # $(COMSPEC) needed to ensure rmdir.exe is not run
+ -@$(COMSPEC) /C rmdir /Q /S $(OBJDIR)
+!else
+ # For Windows 95/98, doesn't work on Windows NT/2000...
+ -@deltree /y $(OBJDIR)
+!endif
+ -@del *.res
+ -@del vim32*.dll
+ -@del vim32*.lib
+ -@del *vim*.exe
+ -@del *install*.exe
+ -@del *.csm
+ -@del *.map
+ -@del *.ilc
+ -@del *.ild
+ -@del *.ilf
+ -@del *.ils
+ -@del *.tds
+!ifdef PERL
+ -@del perl.lib
+!endif
+!ifdef PYTHON
+ -@del python.lib
+!endif
+!ifdef RUBY
+ -@del ruby.lib
+!endif
+!ifdef TCL
+ -@del tcl.lib
+!endif
+!ifdef XPM
+ -@del xpm.lib
+!endif
+ cd xxd
+ $(MAKE) /f Make_bc5.mak BOR="$(BOR)" clean
+ cd ..
+ cd GvimExt
+ $(MAKE) /f Make_bc5.mak BOR="$(BOR)" clean
+ cd ..
+
+$(DLLTARGET): $(OBJDIR) $(vimdllobj)
+ $(LINK) @&&|
+ $(LFLAGSDLL) +
+ c0d32.obj +
+ $(vimdllobj)
+ $<,$*
+!if ("$(CODEGUARD)"=="yes")
+ cg32.lib+
+!endif
+# $(OSTYPE)==WIN32 causes os_mswin.c compilation. FEAT_SHORTCUT in it needs OLE
+!if ("$(OLE)"=="yes" || $(OSTYPE)==WIN32)
+ ole2w32.lib +
+!endif
+!if ($(OSTYPE)==WIN32)
+ import32.lib+
+!ifdef PERL
+ $(PERL_LIB_FLAG)perl.lib+
+!endif
+!ifdef PYTHON
+ $(PYTHON_LIB_FLAG)python.lib+
+!endif
+!ifdef RUBY
+ $(RUBY_LIB_FLAG)ruby.lib+
+!endif
+!ifdef TCL
+ $(TCL_LIB_FLAG)tcl.lib+
+!endif
+!ifdef XPM
+ xpm.lib+
+!endif
+!if ("$(USEDLL)"=="yes")
+ cw32i.lib
+!else
+ cw32.lib
+!endif
+ vim.def
+!else
+ cl.lib
+!endif
+|
+
+!if ("$(VIMDLL)"=="yes")
+$(TARGET): $(OBJDIR) $(DLLTARGET) $(vimmain) $(OBJDIR)\$(RESFILE)
+!else
+$(TARGET): $(OBJDIR) $(vimobj) $(OBJDIR)\$(RESFILE)
+!endif
+ $(LINK) @&&|
+ $(LFLAGS) +
+ $(STARTUPOBJ) +
+!if ("$(VIMDLL)"=="yes")
+ $(vimmain)
+!else
+ $(vimobj)
+!endif
+ $<,$*
+!if ($(OSTYPE)==WIN32)
+!if ("$(CODEGUARD)"=="yes")
+ cg32.lib+
+!endif
+# $(OSTYPE)==WIN32 causes os_mswin.c compilation. FEAT_SHORTCUT in it needs OLE
+!if ("$(OLE)"=="yes" || $(OSTYPE)==WIN32)
+ ole2w32.lib +
+!endif
+ import32.lib+
+!ifdef PERL
+ $(PERL_LIB_FLAG)perl.lib+
+!endif
+!ifdef PYTHON
+ $(PYTHON_LIB_FLAG)python.lib+
+!endif
+!ifdef RUBY
+ $(RUBY_LIB_FLAG)ruby.lib+
+!endif
+!ifdef TCL
+ $(TCL_LIB_FLAG)tcl.lib+
+!endif
+!ifdef XPM
+ xpm.lib+
+!endif
+!if ("$(USEDLL)"=="yes")
+ cw32i.lib
+!else
+ cw32.lib
+!endif
+
+ $(OBJDIR)\$(RESFILE)
+!else
+ emu.lib + cl.lib
+!endif
+|
+
+test:
+ cd testdir
+ $(MAKE) /NOLOGO -f Make_dos.mak win32
+ cd ..
+
+$(OBJDIR)\ex_docmd.obj: ex_docmd.c ex_cmds.h
+
+$(OBJDIR)\ex_eval.obj: ex_eval.c ex_cmds.h
+
+$(OBJDIR)\if_ole.obj: if_ole.cpp
+
+$(OBJDIR)\if_perl.obj: if_perl.c perl.lib
+ $(CC) $(CCARG) $(CC1) $(CC2)$@ -pc if_perl.c
+
+if_perl.c: if_perl.xs typemap
+ $(PERL)\bin\perl.exe $(PERL)\lib\ExtUtils\xsubpp -prototypes -typemap \
+ $(PERL)\lib\ExtUtils\typemap if_perl.xs > $@
+
+$(OBJDIR)\if_python.obj: if_python.c python.lib
+ $(CC) $(CCARG) $(CC1) $(CC2)$@ -pc if_python.c
+
+$(OBJDIR)\if_ruby.obj: if_ruby.c ruby.lib
+ $(CC) $(CCARG) $(CC1) $(CC2)$@ -pc if_ruby.c
+
+$(OBJDIR)\if_tcl.obj: if_tcl.c tcl.lib
+ $(CC) $(CCARG) $(CC1) $(CC2)$@ -pc if_tcl.c
+
+$(OBJDIR)\xpm_w32.obj: xpm_w32.c xpm.lib
+ $(CC) $(CCARG) $(CC1) $(CC2)$@ -pc xpm_w32.c
+
+$(OBJDIR)\netbeans.obj: netbeans.c $(NBDEBUG_DEP)
+ $(CC) $(CCARG) $(CC1) $(CC2)$@ netbeans.c
+
+$(OBJDIR)\vim.res: vim.rc version.h tools.bmp tearoff.bmp \
+ vim.ico vim_error.ico vim_alert.ico vim_info.ico vim_quest.ico
+ $(BRC) -fo$(OBJDIR)\vim.res -i $(BOR)\include -w32 -r vim.rc @&&|
+ $(DEFINES)
+|
+
+$(OBJDIR)\pathdef.obj: auto\pathdef.c
+ $(CC) $(CCARG) $(CC1) $(CC2)$@ auto\pathdef.c
+
+
+# Need to escape both quotes and backslashes in $INTERP_DEFINES
+INTERP_DEFINES_ESC_BKS=$(INTERP_DEFINES:\=\\)
+INTERP_DEFINES_ESC=$(INTERP_DEFINES_ESC_BKS:"=\")
+
+# Note: the silly /*"*/ below are there to trick make into accepting
+# the # character as something other than a comment without messing up
+# the preprocessor directive.
+auto\pathdef.c::
+ -@md auto
+ @echo creating auto/pathdef.c
+ @copy /y &&|
+/* pathdef.c */
+/*"*/#include "vim.h"/*"*/
+
+char_u *default_vim_dir = (char_u *)"$(VIMRCLOC:\=\\)";
+char_u *default_vimruntime_dir = (char_u *)"$(VIMRUNTIMEDIR:\=\\)";
+char_u *all_cflags = (char_u *)"$(CC:\=\\) $(CFLAGS:\=\\) $(DEFINES) $(MBDEFINES) $(INTERP_DEFINES_ESC) $(OPT) $(EXETYPE) $(CPUARG) $(ALIGNARG) $(DEBUG_FLAG) $(CODEGUARD_FLAG)";
+char_u *all_lflags = (char_u *)"$(LINK:\=\\) $(LFLAGS:\=\\)";
+char_u *compiled_user = (char_u *)"$(USERNAME)";
+char_u *compiled_sys = (char_u *)"$(USERDOMAIN)";
+| auto\pathdef.c
+
+perl.lib: $(PERL)\lib\CORE\perl$(PERL_VER).lib
+ coff2omf $(PERL)\lib\CORE\perl$(PERL_VER).lib $@
+
+python.lib: $(PYTHON)\libs\python$(PYTHON_VER).lib
+ coff2omf $(PYTHON)\libs\python$(PYTHON_VER).lib $@
+
+ruby.lib: $(RUBY)\lib\$(RUBY_INSTALL_NAME).lib
+ coff2omf $(RUBY)\lib\$(RUBY_INSTALL_NAME).lib $@
+
+# For some reason, the coff2omf method doesn't work on libXpm.lib, so
+# we have to manually generate an import library straight from the DLL.
+xpm.lib: $(XPM)\lib\libXpm.lib
+ implib -a $@ $(XPM)\bin\libXpm.dll
+
+tcl.lib: $(TCL_LIB)
+!if ("$(DYNAMIC_TCL)" == "yes")
+ copy $(TCL_LIB) $@
+!else
+ coff2omf $(TCL_LIB) $@
+!endif
+
+!if ("$(DYNAMIC_TCL)" == "yes")
+tclstub$(TCL_VER)-bor.lib:
+ -@IF NOT EXIST $@ ECHO You must download tclstub$(TCL_VER)-bor.lib separately and\
+ place it in the src directory in order to compile a dynamic TCL-enabled\
+ (g)vim with the Borland compiler. You can get the tclstub$(TCL_VER)-bor.lib file\
+ at http://mywebpage.netscape.com/sharppeople/vim/tclstub$(TCL_VER)-bor.lib
+!endif
+
+# vimrun.exe:
+vimrun.exe: vimrun.c
+!if ("$(USEDLL)"=="yes")
+ $(CC) -WC -O1 -I$(INCLUDE) -L$(LIB) -D_RTLDLL vimrun.c cw32mti.lib
+!else
+ $(CC) -WC -O1 -I$(INCLUDE) -L$(LIB) vimrun.c
+!endif
+
+# The dependency on $(OBJDIR) is to have bcc.cfg generated each time.
+$(OBJDIR)\bcc.cfg: Make_bc5.mak $(OBJDIR)
+ copy /y &&|
+ $(CFLAGS)
+ -L$(LIB)
+ $(DEFINES)
+ $(MBDEFINES)
+ $(INTERP_DEFINES)
+ $(EXETYPE)
+ $(DEBUG_FLAG)
+ $(OPT)
+ $(CODEGUARD_FLAG)
+ $(CPUARG)
+ $(ALIGNARG)
+| $@
+
+# vi:set sts=4 sw=4:
diff --git a/src/Make_cyg.mak b/src/Make_cyg.mak
new file mode 100644
index 000000000..e58e3d14c
--- /dev/null
+++ b/src/Make_cyg.mak
@@ -0,0 +1,498 @@
+#
+# Makefile for VIM on Win32, using Cygnus gcc
+# Last updated by Dan Sharp. Last Change: 2004 Apr 23
+#
+# This compiles Vim as a Windows application. If you want Vim to run as a
+# Cygwin application use the Makefile (just like on Unix).
+#
+# GUI no or yes: set to yes if you want the GUI version (yes)
+# PERL define to path to Perl dir to get Perl support (not defined)
+# PERL_VER define to version of Perl being used (56)
+# DYNAMIC_PERL no or yes: set to yes to load the Perl DLL dynamically (yes)
+# PYTHON define to path to Python dir to get PYTHON support (not defined)
+# PYTHON_VER define to version of Python being used (22)
+# DYNAMIC_PYTHON no or yes: use yes to load the Python DLL dynamically (yes)
+# TCL define to path to TCL dir to get TCL support (not defined)
+# TCL_VER define to version of TCL being used (83)
+# DYNAMIC_TCL no or yes: use yes to load the TCL DLL dynamically (yes)
+# RUBY define to path to Ruby dir to get Ruby support (not defined)
+# RUBY_VER define to version of Ruby being used (16)
+# DYNAMIC_RUBY no or yes: use yes to load the Ruby DLL dynamically (yes)
+# GETTEXT no or yes: set to yes for dynamic gettext support (yes)
+# ICONV no or yes: set to yes for dynamic iconv support (yes)
+# MBYTE no or yes: set to yes to include multibyte support (yes)
+# IME no or yes: set to yes to include IME support (yes)
+# DYNAMIC_IME no or yes: set to yes to load imm32.dll dynamically (yes)
+# OLE no or yes: set to yes to make OLE gvim (no)
+# DEBUG no or yes: set to yes if you wish a DEBUGging build (no)
+# CPUNR i386 through pentium4: select -mcpu argument to compile with (i386)
+# ARCH i386 through pentium4: select -march argument to compile with (i386)
+# USEDLL no or yes: set to yes to use the Runtime library DLL (no)
+# For USEDLL=yes the cygwin1.dll is required to run Vim.
+# POSTSCRIPT no or yes: set to yes for PostScript printing (no)
+# FEATURES TINY, SMALL, NORMAL, BIG or HUGE (BIG)
+# WINVER Lowest Win32 version to support. (0x0400)
+# CSCOPE no or yes: to include cscope interface support (yes)
+# OPTIMIZE SPACE, SPEED, or MAXSPEED: set optimization level (MAXSPEED)
+# NETBEANS no or yes: to include netbeans interface support (yes when GUI
+# is yes)
+# XPM define to path to XPM dir to get XPM image support (not defined)
+#>>>>> choose options:
+ifndef GUI
+GUI=yes
+endif
+
+ifndef FEATURES
+FEATURES = BIG
+endif
+
+ifndef GETTEXT
+GETTEXT = yes
+endif
+
+ifndef ICONV
+ICONV = yes
+endif
+
+ifndef MBYTE
+MBYTE = yes
+endif
+
+ifndef IME
+IME = yes
+endif
+
+ifndef CPUNR
+CPUNR = i386
+endif
+
+ifndef ARCH
+ARCH = i386
+endif
+
+ifndef WINVER
+WINVER = 0x0400
+endif
+
+ifndef CSCOPE
+CSCOPE = yes
+endif
+
+ifndef NETBEANS
+ifeq ($(GUI),yes)
+NETBEANS = yes
+endif
+endif
+
+ifndef OPTIMIZE
+OPTIMIZE = MAXSPEED
+endif
+
+### See feature.h for a list of optionals.
+### Any other defines can be included here.
+
+DEFINES = -DWIN32 -DHAVE_PATHDEF -DFEAT_$(FEATURES) \
+ -DWINVER=$(WINVER) -D_WIN32_WINNT=$(WINVER)
+INCLUDES = -mcpu=$(CPUNR) -march=$(ARCH) -Iproto
+
+#>>>>> name of the compiler and linker, name of lib directory
+CC = gcc
+RC = windres
+
+##############################
+# DYNAMIC_PERL=yes and no both work
+##############################
+ifdef PERL
+DEFINES += -DFEAT_PERL
+INCLUDES += -I$(PERL)/lib/CORE
+EXTRA_OBJS += $(OUTDIR)/if_perl.o
+
+ifndef DYNAMIC_PERL
+DYNAMIC_PERL = yes
+endif
+
+ifndef PERL_VER
+PERL_VER = 56
+endif
+
+ifeq (yes, $(DYNAMIC_PERL))
+DEFINES += -DDYNAMIC_PERL -DDYNAMIC_PERL_DLL=\"perl$(PERL_VER).dll\"
+else
+EXTRA_LIBS += $(PERL)/lib/CORE/perl$(PERL_VER).lib
+endif
+endif
+
+##############################
+# DYNAMIC_PYTHON=yes works.
+# DYNAMIC_PYTHON=no does not (unresolved externals on link).
+##############################
+ifdef PYTHON
+DEFINES += -DFEAT_PYTHON
+INCLUDES += -I$(PYTHON)/include
+EXTRA_OBJS += $(OUTDIR)/if_python.o
+
+ifndef DYNAMIC_PYTHON
+DYNAMIC_PYTHON = yes
+endif
+
+ifndef PYTHON_VER
+PYTHON_VER = 22
+endif
+
+ifeq (yes, $(DYNAMIC_PYTHON))
+DEFINES += -DDYNAMIC_PYTHON -DDYNAMIC_PYTHON_DLL=\"python$(PYTHON_VER).dll\"
+else
+EXTRA_LIBS += $(PYTHON)/libs/python$(PYTHON_VER).lib
+endif
+endif
+
+##############################
+# DYNAMIC_RUBY=yes works.
+# DYNAMIC_RUBY=no does not (process exits).
+##############################
+ifdef RUBY
+
+ifndef RUBY_VER
+RUBY_VER=16
+endif
+
+ifndef RUBY_VER_LONG
+RUBY_VER_LONG=1.6
+endif
+
+ifndef DYNAMIC_RUBY
+DYNAMIC_RUBY = yes
+endif
+
+ifeq ($(RUBY_VER), 16)
+ifndef RUBY_PLATFORM
+RUBY_PLATFORM = i586-mswin32
+endif
+ifndef RUBY_INSTALL_NAME
+RUBY_INSTALL_NAME = mswin32-ruby$(RUBY_VER)
+endif
+else
+ifndef RUBY_PLATFORM
+RUBY_PLATFORM = i386-mswin32
+endif
+ifndef RUBY_INSTALL_NAME
+RUBY_INSTALL_NAME = msvcrt-ruby$(RUBY_VER)
+endif
+endif
+
+DEFINES += -DFEAT_RUBY
+INCLUDES += -I$(RUBY)/lib/ruby/$(RUBY_VER_LONG)/$(RUBY_PLATFORM)
+EXTRA_OBJS += $(OUTDIR)/if_ruby.o
+
+ifeq (yes, $(DYNAMIC_RUBY))
+DEFINES += -DDYNAMIC_RUBY -DDYNAMIC_RUBY_DLL=\"$(RUBY_INSTALL_NAME).dll\"
+DEFINES += -DDYNAMIC_RUBY_VER=$(RUBY_VER)
+else
+EXTRA_LIBS += $(RUBY)/lib/$(RUBY_INSTALL_NAME).lib
+endif
+endif
+
+##############################
+# DYNAMIC_TCL=yes and no both work.
+##############################
+ifdef TCL
+DEFINES += -DFEAT_TCL
+INCLUDES += -I$(TCL)/include
+EXTRA_OBJS += $(OUTDIR)/if_tcl.o
+
+ifndef DYNAMIC_TCL
+DYNAMIC_TCL = yes
+endif
+
+ifndef TCL_VER
+TCL_VER = 83
+endif
+
+ifeq (yes, $(DYNAMIC_TCL))
+DEFINES += -DDYNAMIC_TCL -DDYNAMIC_TCL_DLL=\"tcl$(TCL_VER).dll\"
+EXTRA_LIBS += $(TCL)/lib/tclstub$(TCL_VER).lib
+else
+EXTRA_LIBS += $(TCL)/lib/tcl$(TCL_VER).lib
+endif
+endif
+
+##############################
+ifeq (yes, $(GETTEXT))
+DEFINES += -DDYNAMIC_GETTEXT
+endif
+
+##############################
+ifeq (yes, $(ICONV))
+DEFINES += -DDYNAMIC_ICONV
+endif
+
+##############################
+ifeq (yes, $(MBYTE))
+DEFINES += -DFEAT_MBYTE
+endif
+
+##############################
+ifeq (yes, $(IME))
+DEFINES += -DFEAT_MBYTE_IME
+
+ifndef DYNAMIC_IME
+DYNAMIC_IME = yes
+endif
+
+ifeq (yes, $(DYNAMIC_IME))
+DEFINES += -DDYNAMIC_IME
+else
+EXTRA_LIBS += -limm32
+endif
+endif
+
+##############################
+ifeq (yes, $(DEBUG))
+DEFINES += -DDEBUG
+INCLUDES += -g -fstack-check
+DEBUG_SUFFIX = d
+else
+
+ifeq ($(OPTIMIZE), SIZE)
+OPTFLAG = -Os
+else
+ifeq ($(OPTIMIZE), MAXSPEED)
+OPTFLAG = -O3 -fomit-frame-pointer -freg-struct-return -malign-double
+else
+OPTFLAG = -O2
+endif
+endif
+
+# A bug in the GCC <= 3.2 optimizer can cause a crash. The
+# following option removes the problem optimization.
+OPTFLAG += -fno-strength-reduce
+
+INCLUDES += -s
+
+endif
+
+##############################
+# USEDLL=yes will build a Cygwin32 executable that relies on cygwin1.dll.
+# USEDLL=no will build a Mingw32 executable with no extra dll dependencies.
+##############################
+ifeq (yes, $(USEDLL))
+DEFINES += -D_MAX_PATH=256 -D__CYGWIN__
+else
+INCLUDES += -mno-cygwin
+endif
+
+##############################
+ifeq (yes, $(POSTSCRIPT))
+DEFINES += -DMSWINPS
+endif
+
+##############################
+ifeq (yes, $(CSCOPE))
+DEFINES += -DFEAT_CSCOPE
+EXTRA_OBJS += $(OUTDIR)/if_cscope.o
+endif
+
+##############################
+ifeq (yes, $(NETBEANS))
+DEFINES += -DFEAT_NETBEANS_INTG
+EXTRA_OBJS += $(OUTDIR)/netbeans.o $(OUTDIR)/gui_beval.o
+EXTRA_LIBS += -lwsock32
+
+ifeq (yes, $(DEBUG))
+DEFINES += -DNBDEBUG
+NBDEBUG_DEP = nbdebug.h nbdebug.c
+endif
+
+endif
+
+##############################
+ifdef XPM
+DEFINES += -DFEAT_XPM_W32
+INCLUDES += -I$(XPM)/include
+EXTRA_OBJS += $(OUTDIR)/xpm_w32.o
+EXTRA_LIBS += -L$(XPM)/lib -lXpm
+endif
+
+##############################
+ifeq (yes, $(OLE))
+DEFINES += -DFEAT_OLE
+EXTRA_OBJS += $(OUTDIR)/if_ole.o
+EXTRA_LIBS += -loleaut32 -lstdc++
+endif
+
+##############################
+ifeq ($(GUI),yes)
+EXE = gvim$(DEBUG_SUFFIX).exe
+OUTDIR = gobj$(DEBUG_SUFFIX)
+DEFINES += -DFEAT_GUI_W32 -DFEAT_CLIPBOARD
+EXTRA_OBJS += $(OUTDIR)/gui.o $(OUTDIR)/gui_w32.o $(OUTDIR)/os_w32exe.o
+EXTRA_LIBS += -mwindows -lcomctl32
+else
+EXE = vim$(DEBUG_SUFFIX).exe
+OUTDIR = obj$(DEBUG_SUFFIX)
+LIBS += -luser32 -lgdi32 -lcomdlg32
+endif
+
+##############################
+ifneq (sh.exe, $(SHELL))
+DEL = rm
+DIRSLASH = /
+else
+DEL = del
+DIRSLASH = \\
+endif
+
+#>>>>> end of choices
+###########################################################################
+
+INCL = vim.h globals.h option.h keymap.h macros.h ascii.h term.h os_win32.h \
+ structs.h version.h
+
+CFLAGS = $(OPTFLAG) $(DEFINES) $(INCLUDES)
+
+RCFLAGS = -O coff $(DEFINES)
+
+OBJ = \
+ $(OUTDIR)/buffer.o \
+ $(OUTDIR)/charset.o \
+ $(OUTDIR)/diff.o \
+ $(OUTDIR)/digraph.o \
+ $(OUTDIR)/edit.o \
+ $(OUTDIR)/eval.o \
+ $(OUTDIR)/ex_cmds.o \
+ $(OUTDIR)/ex_cmds2.o \
+ $(OUTDIR)/ex_docmd.o \
+ $(OUTDIR)/ex_eval.o \
+ $(OUTDIR)/ex_getln.o \
+ $(OUTDIR)/fileio.o \
+ $(OUTDIR)/fold.o \
+ $(OUTDIR)/getchar.o \
+ $(OUTDIR)/main.o \
+ $(OUTDIR)/mark.o \
+ $(OUTDIR)/memfile.o \
+ $(OUTDIR)/memline.o \
+ $(OUTDIR)/menu.o \
+ $(OUTDIR)/message.o \
+ $(OUTDIR)/misc1.o \
+ $(OUTDIR)/misc2.o \
+ $(OUTDIR)/move.o \
+ $(OUTDIR)/mbyte.o \
+ $(OUTDIR)/normal.o \
+ $(OUTDIR)/ops.o \
+ $(OUTDIR)/option.o \
+ $(OUTDIR)/os_win32.o \
+ $(OUTDIR)/os_mswin.o \
+ $(OUTDIR)/pathdef.o \
+ $(OUTDIR)/quickfix.o \
+ $(OUTDIR)/regexp.o \
+ $(OUTDIR)/screen.o \
+ $(OUTDIR)/search.o \
+ $(OUTDIR)/syntax.o \
+ $(OUTDIR)/tag.o \
+ $(OUTDIR)/term.o \
+ $(OUTDIR)/ui.o \
+ $(OUTDIR)/undo.o \
+ $(OUTDIR)/version.o \
+ $(OUTDIR)/vimrc.o \
+ $(OUTDIR)/window.o \
+ $(EXTRA_OBJS)
+
+all: $(EXE) xxd/xxd.exe vimrun.exe install.exe uninstal.exe GvimExt/gvimext.dll
+
+# According to the Cygwin doc 1.2 FAQ, kernel32 should not be specified for
+# linking unless calling ld directly.
+# See /usr/doc/cygwin-doc-1.2/html/faq_toc.html#TOC93 for more information.
+$(EXE): $(OUTDIR) $(OBJ)
+ $(CC) $(CFLAGS) -o $(EXE) $(OBJ) $(LIBS) -luuid -lole32 $(EXTRA_LIBS)
+
+xxd/xxd.exe: xxd/xxd.c
+ $(MAKE) -C xxd -f Make_cyg.mak USEDLL=$(USEDLL)
+
+GvimExt/gvimext.dll: GvimExt/gvimext.cpp GvimExt/gvimext.rc GvimExt/gvimext.h
+ $(MAKE) -C GvimExt -f Make_ming.mak
+
+vimrun.exe: vimrun.c
+ $(CC) $(CFLAGS) -o vimrun.exe vimrun.c $(LIBS)
+
+install.exe: dosinst.c
+ $(CC) $(CFLAGS) -o install.exe dosinst.c $(LIBS) -luuid -lole32
+
+uninstal.exe: uninstal.c
+ $(CC) $(CFLAGS) -o uninstal.exe uninstal.c $(LIBS)
+
+$(OUTDIR):
+ mkdir $(OUTDIR)
+
+tags:
+ command /c ctags *.c $(INCL)
+
+clean:
+ -$(DEL) $(OUTDIR)$(DIRSLASH)*.o
+ -rmdir $(OUTDIR)
+ -$(DEL) *.exe
+ifdef PERL
+ -$(DEL) if_perl.c
+endif
+ -$(DEL) pathdef.c
+ $(MAKE) -C xxd -f Make_cyg.mak clean
+ $(MAKE) -C GvimExt -f Make_ming.mak clean
+
+###########################################################################
+
+$(OUTDIR)/%.o : %.c $(INCL)
+ $(CC) -c $(CFLAGS) $< -o $@
+
+$(OUTDIR)/ex_docmd.o: ex_docmd.c $(INCL) ex_cmds.h
+ $(CC) -c $(CFLAGS) ex_docmd.c -o $(OUTDIR)/ex_docmd.o
+
+$(OUTDIR)/ex_eval.o: ex_eval.c $(INCL) ex_cmds.h
+ $(CC) -c $(CFLAGS) ex_eval.c -o $(OUTDIR)/ex_eval.o
+
+$(OUTDIR)/if_cscope.o: if_cscope.c $(INCL) if_cscope.h
+ $(CC) -c $(CFLAGS) if_cscope.c -o $(OUTDIR)/if_cscope.o
+
+$(OUTDIR)/if_ole.o: if_ole.cpp $(INCL)
+ $(CC) -c $(CFLAGS) -D__IID_DEFINED__ if_ole.cpp -o $(OUTDIR)/if_ole.o
+
+if_perl.c: if_perl.xs typemap
+ perl $(PERL)/lib/ExtUtils/xsubpp -prototypes -typemap \
+ $(PERL)/lib/ExtUtils/typemap if_perl.xs > $@
+
+$(OUTDIR)/if_perl.o: if_perl.c $(INCL)
+ifeq (yes, $(USEDLL))
+ $(CC) -c $(CFLAGS) -I/usr/include/mingw -D__MINGW32__ if_perl.c -o $(OUTDIR)/if_perl.o
+endif
+
+$(OUTDIR)/if_ruby.o: if_ruby.c $(INCL)
+ifeq (16, $(RUBY_VER))
+ $(CC) -c $(CFLAGS) -U_WIN32 if_ruby.c -o $(OUTDIR)/if_ruby.o
+endif
+
+$(OUTDIR)/netbeans.o: netbeans.c $(INCL) $(NBDEBUG_DEP)
+ $(CC) -c $(CFLAGS) netbeans.c -o $(OUTDIR)/netbeans.o
+
+$(OUTDIR)/vimrc.o: vim.rc version.h gui_w32_rc.h
+ $(RC) $(RCFLAGS) vim.rc -o $(OUTDIR)/vimrc.o
+
+pathdef.c: $(INCL)
+ifneq (sh.exe, $(SHELL))
+ @echo creating pathdef.c
+ @echo '/* pathdef.c */' > pathdef.c
+ @echo '#include "vim.h"' >> pathdef.c
+ @echo 'char_u *default_vim_dir = (char_u *)"$(VIMRCLOC)";' >> pathdef.c
+ @echo 'char_u *default_vimruntime_dir = (char_u *)"$(VIMRUNTIMEDIR)";' >> pathdef.c
+ @echo 'char_u *all_cflags = (char_u *)"$(CC) $(CFLAGS)";' >> pathdef.c
+ @echo 'char_u *all_lflags = (char_u *)"$(CC) -s -o $(EXE) $(LIBS) -luuid -lole32 $(EXTRA_LIBS)";' >> pathdef.c
+ @echo 'char_u *compiled_user = (char_u *)"$(USERNAME)";' >> pathdef.c
+ @echo 'char_u *compiled_sys = (char_u *)"$(USERDOMAIN)";' >> pathdef.c
+else
+ @echo creating pathdef.c
+ @echo /* pathdef.c */ > pathdef.c
+ @echo #include "vim.h" >> pathdef.c
+ @echo char_u *default_vim_dir = (char_u *)"$(VIMRCLOC)"; >> pathdef.c
+ @echo char_u *default_vimruntime_dir = (char_u *)"$(VIMRUNTIMEDIR)"; >> pathdef.c
+ @echo char_u *all_cflags = (char_u *)"$(CC) $(CFLAGS)"; >> pathdef.c
+ @echo char_u *all_lflags = (char_u *)"$(CC) -s -o $(EXE) $(LIBS) -luuid -lole32 $(EXTRA_LIBS)"; >> pathdef.c
+ @echo char_u *compiled_user = (char_u *)"$(USERNAME)"; >> pathdef.c
+ @echo char_u *compiled_sys = (char_u *)"$(USERDOMAIN)"; >> pathdef.c
+endif
diff --git a/src/Make_dice.mak b/src/Make_dice.mak
new file mode 100644
index 000000000..77f6cba22
--- /dev/null
+++ b/src/Make_dice.mak
@@ -0,0 +1,209 @@
+#
+# Makefile for VIM, using DICE 3
+#
+
+#>>>>> choose options:
+### See feature.h for a list of optionals.
+### Any other defines can be included here.
+DEFINES = -DHAVE_TGETENT -DUP_BC_PC_EXTERN -DOSPEED_EXTERN
+
+#>>>>> if HAVE_TGETENT is defined o/termlib.o has to be used
+TERMLIB = o/termlib.o
+#TERMLIB =
+
+#>>>>> end of choices
+###########################################################################
+
+CFLAGS = -c -DAMIGA -Iproto $(DEFINES)
+
+SYMS = vim.syms
+PRE = -H${SYMS}=vim.h
+LIBS = -la
+CC = dcc
+LD = dcc
+
+.c.o:
+ ${CC} ${PRE} ${CFLAGS} $< -o $@
+
+SRC = \
+ buffer.c \
+ charset.c \
+ diff.c \
+ digraph.c \
+ edit.c \
+ eval.c \
+ ex_cmds.c \
+ ex_cmds2.c \
+ ex_docmd.c \
+ ex_eval.c \
+ ex_getln.c \
+ fileio.c \
+ fold.c \
+ getchar.c \
+ main.c \
+ mark.c \
+ memfile.c \
+ memline.c \
+ menu.c \
+ message.c \
+ misc1.c \
+ misc2.c \
+ move.c \
+ mbyte.c \
+ normal.c \
+ ops.c \
+ option.c \
+ os_amiga.c \
+ quickfix.c \
+ regexp.c \
+ screen.c \
+ search.c \
+ syntax.c \
+ tag.c \
+ term.c \
+ ui.c \
+ undo.c \
+ window.c \
+ version.c
+
+OBJ = o/buffer.o \
+ o/charset.o \
+ o/diff.o \
+ o/digraph.o \
+ o/edit.o \
+ o/eval.o \
+ o/ex_cmds.o \
+ o/ex_cmds2.o \
+ o/ex_docmd.o \
+ o/ex_eval.o \
+ o/ex_getln.o \
+ o/fileio.o \
+ o/fold.o \
+ o/getchar.o \
+ o/main.o \
+ o/mark.o \
+ o/memfile.o \
+ o/memline.o \
+ o/menu.o \
+ o/message.o \
+ o/misc1.o \
+ o/misc2.o \
+ o/move.o \
+ o/mbyte.o \
+ o/normal.o \
+ o/ops.o \
+ o/option.o \
+ o/os_amiga.o \
+ o/quickfix.o \
+ o/regexp.o \
+ o/screen.o \
+ o/search.o \
+ o/syntax.o \
+ o/tag.o \
+ o/term.o \
+ o/ui.o \
+ o/undo.o \
+ o/window.o \
+ $(TERMLIB)
+
+Vim: $(OBJ) version.c version.h
+ ${CC} $(CFLAGS) version.c -o o/version.o
+ ${LD} -o Vim $(OBJ) o/version.o $(LIBS)
+
+debug: $(OBJ) version.c version.h
+ ${CC} $(CFLAGS) version.c -o o/version.o
+ ${LD} -s -o Vim $(OBJ) o/version.o $(LIBS)
+
+tags:
+ csh -c ctags $(SRC) *.h
+
+clean:
+ delete o/*.o Vim $(SYMS)
+
+$(SYMS) : vim.h globals.h keymap.h macros.h ascii.h term.h os_amiga.h structs.h
+ delete $(SYMS)
+
+###########################################################################
+
+o/buffer.o: buffer.c $(SYMS)
+
+o/charset.o: charset.c $(SYMS)
+
+o/diff.o: diff.c $(SYMS)
+
+o/digraph.o: digraph.c $(SYMS)
+
+o/edit.o: edit.c $(SYMS)
+
+o/eval.o: eval.c $(SYMS)
+
+o/ex_cmds.o: ex_cmds.c $(SYMS)
+
+o/ex_cmds2.o: ex_cmds2.c $(SYMS)
+
+o/ex_docmd.o: ex_docmd.c $(SYMS) ex_cmds.h
+
+o/ex_eval.o: ex_eval.c $(SYMS) ex_cmds.h
+
+o/ex_getln.o: ex_getln.c $(SYMS)
+
+o/fileio.o: fileio.c $(SYMS)
+
+o/fold.o: fold.c $(SYMS)
+
+o/getchar.o: getchar.c $(SYMS)
+
+o/main.o: main.c $(SYMS)
+
+o/mark.o: mark.c $(SYMS)
+
+o/memfile.o: memfile.c $(SYMS)
+
+o/memline.o: memline.c $(SYMS)
+
+o/menu.o: menu.c $(SYMS)
+
+o/message.o: message.c $(SYMS)
+
+o/misc1.o: misc1.c $(SYMS)
+
+o/misc2.o: misc2.c $(SYMS)
+
+o/move.o: move.c $(SYMS)
+
+o/mbyte.o: mbyte.c $(SYMS)
+
+o/normal.o: normal.c $(SYMS)
+
+o/ops.o: ops.c $(SYMS)
+
+o/option.o: option.c $(SYMS)
+# Because of a bug in DC1 2.06.40, initialisation of unions does not
+# work correctly. dc1-21 is DC1 2.06.21 which does work.
+# rename dc1-21 dc1
+ ${CC} ${CFLAGS} option.c -o o/option.o
+# rename dc1 dc1-21
+
+o/os_amiga.o: os_amiga.c $(SYMS) os_amiga.h
+
+o/quickfix.o: quickfix.c $(SYMS)
+
+o/regexp.o: regexp.c $(SYMS) regexp.h
+
+o/screen.o: screen.c $(SYMS)
+
+o/search.o: search.c $(SYMS) regexp.h
+
+o/syntax.o: syntax.c $(SYMS)
+
+o/tag.o: tag.c $(SYMS)
+
+o/term.o: term.c $(SYMS) term.h
+
+o/termlib.o: termlib.c $(SYMS)
+
+o/ui.o: ui.c $(SYMS)
+
+o/undo.o: undo.c $(SYMS)
+
+o/window.o: window.c $(SYMS)
diff --git a/src/Make_djg.mak b/src/Make_djg.mak
new file mode 100644
index 000000000..02c42b878
--- /dev/null
+++ b/src/Make_djg.mak
@@ -0,0 +1,102 @@
+#
+# Makefile for VIM on MSDOS, using DJGPP 2.0
+#
+
+#>>>>> choose options:
+
+### See feature.h for a list of optionals.
+### Any other defines can be included here.
+
+DEFINES =
+
+#>>>>> name of the compiler and linker, name of lib directory
+CC = gcc
+
+#>>>>> end of choices
+###########################################################################
+
+INCL = vim.h globals.h option.h keymap.h macros.h ascii.h term.h os_msdos.h structs.h
+CFLAGS = -O2 -DMSDOS -Iproto $(DEFINES) -Wall -Dinterrupt= -Dfar= -DMAXMEM=512 -D_NAIVE_DOS_REGS
+
+OBJ = \
+ obj/buffer.o \
+ obj/charset.o \
+ obj/diff.o \
+ obj/digraph.o \
+ obj/edit.o \
+ obj/eval.o \
+ obj/ex_cmds.o \
+ obj/ex_cmds2.o \
+ obj/ex_docmd.o \
+ obj/ex_eval.o \
+ obj/ex_getln.o \
+ obj/fileio.o \
+ obj/fold.o \
+ obj/getchar.o \
+ obj/main.o \
+ obj/mark.o \
+ obj/memfile.o \
+ obj/memline.o \
+ obj/menu.o \
+ obj/message.o \
+ obj/misc1.o \
+ obj/misc2.o \
+ obj/move.o \
+ obj/mbyte.o \
+ obj/normal.o \
+ obj/ops.o \
+ obj/option.o \
+ obj/os_msdos.o \
+ obj/quickfix.o \
+ obj/regexp.o \
+ obj/screen.o \
+ obj/search.o \
+ obj/syntax.o \
+ obj/tag.o \
+ obj/term.o \
+ obj/ui.o \
+ obj/undo.o \
+ obj/window.o \
+ $(TERMLIB)
+
+all: vim.exe install.exe uninstal.exe xxd/xxd.exe
+
+# version.c is compiled each time, so that it sets the build time.
+vim.exe: obj $(OBJ) version.c version.h
+ $(CC) $(CFLAGS) -s -o vim.exe version.c $(OBJ) -lpc
+
+install.exe: dosinst.c
+ $(CC) $(CFLAGS) -s -o install.exe dosinst.c -lpc
+
+uninstal.exe: uninstal.c
+ $(CC) $(CFLAGS) -s -o uninstal.exe uninstal.c -lpc
+
+# This requires GNU make.
+xxd/xxd.exe: xxd/xxd.c
+ $(MAKE) --directory=xxd -f Make_djg.mak
+
+obj:
+ mkdir obj
+
+tags:
+ command /c ctags *.c $(INCL) ex_cmds.h
+
+clean:
+ -del obj\*.o
+ -rmdir obj
+ -del vim.exe
+ -del install.exe
+ -del xxd\xxd.exe
+ -del testdir\*.out
+
+# This requires GNU make.
+test:
+ $(MAKE) --directory=testdir -f Make_dos.mak
+
+###########################################################################
+
+obj/%.o: %.c obj $(INCL)
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+# Extra dependency (there are actually many more...)
+obj/ex_docmd.o: ex_cmds.h
diff --git a/src/Make_dvc.mak b/src/Make_dvc.mak
new file mode 100644
index 000000000..46377f07d
--- /dev/null
+++ b/src/Make_dvc.mak
@@ -0,0 +1,105 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+!IF "$(CFG)" == ""
+CFG=Vim - Win32 IDE for Make_mvc.mak
+!MESSAGE No configuration specified. Defaulting to Vim - Win32 IDE for\
+ Make_mvc.mak.
+!ENDIF
+
+!IF "$(CFG)" != "Vim - Win32 IDE for Make_mvc.mak"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Make_dvc.mak" CFG="Vim - Win32 IDE for Make_mvc.mak"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Vim - Win32 IDE for Make_mvc.mak" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "Vim - Win32 IDE for Make_mvc.mak"
+CPP=cl.exe
+RSC=rc.exe
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Target_Dir ""
+OUTDIR=.
+INTDIR=.
+
+ALL : "$(OUTDIR)\vimrun.exe"
+
+CLEAN :
+ -@erase ".\vimrun.exe"
+ -@erase ".\vimrun.obj"
+
+# ADD CPP /nologo /c
+# ADD BASE RSC /l 0x809
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/Make_dvc.bsc"
+BSC32_SBRS=
+LINK32=link.exe
+# ADD BASE LINK32 /machine:IX86
+# ADD LINK32 /nologo /pdb:none /machine:IX86 /out:"vimrun.exe"
+LINK32_FLAGS=/nologo /pdb:none /machine:IX86 /out:"$(OUTDIR)/vimrun.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/vimrun.obj"
+
+"$(OUTDIR)\vimrun.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+CPP_PROJ=/nologo /ML /c
+
+.c.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+################################################################################
+# Begin Target
+
+# Name "Vim - Win32 IDE for Make_mvc.mak"
+################################################################################
+# Begin Source File
+
+SOURCE=.\vimrun.c
+
+"$(INTDIR)\vimrun.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+# End Target
+# End Project
+################################################################################
diff --git a/src/Make_ivc.mak b/src/Make_ivc.mak
new file mode 100644
index 000000000..94a153060
--- /dev/null
+++ b/src/Make_ivc.mak
@@ -0,0 +1,648 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.00
+# ** DO NOT EDIT **
+#
+# Make_ivc.mak Makefile to build vim in both IDE and nmake.
+# This file can be imported as a workspace into Visual Studio. It must be in
+# DOS fileformat then!
+#
+# It is worth making the file read-only as the VC4 IDE will try to overwrite
+# it with a HUGELY expanded clone of itself.
+#
+# The following points are worth noting:
+# 1) Comments here are ignored by VC[456].0 IDEs
+# 2) # ADD LINK32 /pdb:.\Dbg/vimd.pdb is written so rather than
+# # ADD LINK32 /pdb:".\Dbg/vimd.pdb" to avoid VC4 -> VC5 conversion failure
+# 3) It is good to delete .pdb file before linking to cope with switch among
+# VC[456] as IDE clean action does not remove that file and link clashes
+# with it. The following works in VC5 but not in VC4 which does not support
+# pre-link actions. The nmake action does such deletions.
+# Begin Special Build Tool
+PreLink_Cmds=@if exist .\oleDbg\gvimd.pdb del .\oleDbg\gvimd.pdb
+# End Special Build Tool
+# 4) I was unable to make !IFDEF OLE, etc. work in the VC4 IDE.
+# I was aiming for 4 configurations with sub-configurations selected by
+# environment variables.
+# 5) Optimisation is not supported by disabled versions of VC. This results in
+# messages for Release builds like:
+# Command line warning D4025 : overriding '/O2' with '/Od'
+# 6) nmake 1.62 and later support batch compilation. I was unable to use this
+# in a manner acceptable to earlier IDEs.
+#
+# History
+#
+# When Who What
+# 2001-07-06 W.Briscoe Original derived from Make_[go]vc.mak with less noise
+# 2001-07-08 W.Briscoe Further noise reduction; consistent .map and .pdb logic
+# Added install.exe rule, etc.; Removed unused libraries.
+# 2001-08-09 W.Briscoe Restored VC4.0-required trailing space in !MESSAGE afore
+# Enhanced if_ole.idl rule to use /out argument.
+# Default rules now relative to . to reduce IDE/nmake difs
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+!IF "$(CFG)" == ""
+CFG=Vim - Win32 Release gvim OLE
+!MESSAGE No configuration specified. Defaulting to Vim - Win32 Release gvim OLE.
+!ENDIF
+
+!IF "$(CFG)" != "Vim - Win32 Release gvim OLE"\
+ && "$(CFG)" != "Vim - Win32 Debug gvim OLE"\
+ && "$(CFG)" != "Vim - Win32 Release gvim"\
+ && "$(CFG)" != "Vim - Win32 Debug gvim"\
+ && "$(CFG)" != "Vim - Win32 Release vim"\
+ && "$(CFG)" != "Vim - Win32 Debug vim"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Make_ivc.mak" CFG="Vim - Win32 Debug vim"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Vim - Win32 Release gvim OLE" (based on "Win32 (x86) Console Application")
+!MESSAGE "Vim - Win32 Debug gvim OLE" (based on "Win32 (x86) Console Application")
+!MESSAGE "Vim - Win32 Release gvim" (based on "Win32 (x86) Console Application")
+!MESSAGE "Vim - Win32 Debug gvim" (based on "Win32 (x86) Console Application")
+!MESSAGE "Vim - Win32 Release vim" (based on "Win32 (x86) Console Application")
+!MESSAGE "Vim - Win32 Debug vim" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+DEL_TREE = rmdir /s /q
+!ELSE
+NULL=nul
+DEL_TREE = deltree /y
+!ENDIF
+
+# Begin Project
+# PROP Target_Last_Scanned "Vim - Win32 Debug vim"
+# PROP Use_MFC 0
+
+RSC=rc.exe
+CPP=cl.exe
+LINK32=link.exe
+
+CPP_PROJ= /nologo /MT /W3 /GX /I ".\proto" /D "WIN32" /c
+# ADD CPP /nologo /MT /W3 /GX /I ".\proto" /D "WIN32" /c
+
+LINK32_FLAGS= oldnames.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib comctl32.lib advapi32.lib shell32.lib ole32.lib uuid.lib /nologo /machine:I386 /nodefaultlib
+# ADD LINK32 oldnames.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib comctl32.lib advapi32.lib shell32.lib ole32.lib uuid.lib /nologo /machine:I386 /nodefaultlib
+# SUBTRACT LINK32 /incremental:yes
+
+RSC_PROJ= /l 0x409 /d "FEAT_GUI_W32"
+# ADD RSC /l 0x409 /d "FEAT_GUI_W32"
+
+!IF "$(CFG)" == "Vim - Win32 Release gvim OLE"
+
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir .\oleRel
+# PROP Intermediate_Dir .\oleRel
+
+INTDIR=.\oleRel
+VIM=gvim
+EXTRAS="$(INTDIR)/if_ole.obj" "$(INTDIR)/vim.res" "$(INTDIR)/gui.obj" "$(INTDIR)/gui_w32.obj" "$(INTDIR)/os_w32exe.obj"
+
+CPP_PROJ=$(CPP_PROJ) /O2 /D "NDEBUG" /D "FEAT_GUI_W32" /D "DYNAMIC_GETTEXT" /D "FEAT_OLE" /Fd.\oleRel/ /Fo.\oleRel/
+# ADD CPP /O2 /D "NDEBUG" /D "FEAT_GUI_W32" /D "DYNAMIC_GETTEXT" /D "FEAT_OLE" /Fd.\oleRel/ /Fo.\oleRel/
+
+RSC_PROJ=$(RSC_PROJ) /I ".\oleRel" /d "NDEBUG" /d "FEAT_OLE" /fo.\oleRel\vim.res
+# ADD RSC /I ".\oleRel" /d "NDEBUG" /d "FEAT_OLE" /fo.\oleRel\vim.res
+
+LINK32_FLAGS=$(LINK32_FLAGS) /pdb:none libc.lib oleaut32.lib /subsystem:windows /out:.\gvim.exe
+# ADD LINK32 /pdb:none libc.lib oleaut32.lib /subsystem:windows /out:.\gvim.exe
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug gvim OLE"
+
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir .\oleDbg
+# PROP Intermediate_Dir .\oleDbg
+
+INTDIR=.\oleDbg
+VIM=gvimd
+EXTRAS="$(INTDIR)/if_ole.obj" "$(INTDIR)/vim.res" "$(INTDIR)/gui.obj" "$(INTDIR)/gui_w32.obj" "$(INTDIR)/os_w32exe.obj"
+
+CPP_PROJ=$(CPP_PROJ) /Zi /Od /D "_DEBUG" /D "FEAT_GUI_W32" /D "DYNAMIC_GETTEXT" /D "FEAT_OLE" /Fd.\oleDbg/ /Fo.\oleDbg/
+# ADD CPP /Zi /Od /D "_DEBUG" /D "FEAT_GUI_W32" /D "DYNAMIC_GETTEXT" /D "FEAT_OLE" /Fd.\oleDbg/ /Fo.\oleDbg/
+
+RSC_PROJ=$(RSC_PROJ) /I .\oleDbg /d "_DEBUG" /d "FEAT_OLE" /fo.\oleDbg\vim.res
+# ADD RSC /I .\oleDbg /d "_DEBUG" /d "FEAT_OLE" /fo.\oleDbg\vim.res
+
+LINK32_FLAGS=$(LINK32_FLAGS) libcd.lib oleaut32.lib /subsystem:windows /debug /profile /pdb:.\oleDbg/gvimd.pdb /map:.\oleDbg\gvimd.map /out:.\gvimd.exe
+# ADD LINK32 libcd.lib oleaut32.lib /subsystem:windows /debug /profile /pdb:.\oleDbg/gvimd.pdb /map:.\oleDbg\gvimd.map /out:.\gvimd.exe
+
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Release gvim"
+
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir .\gRel
+# PROP Intermediate_Dir .\gRel
+
+INTDIR=.\gRel
+VIM=gvim
+EXTRAS="$(INTDIR)/vim.res" "$(INTDIR)/gui.obj" "$(INTDIR)/gui_w32.obj" "$(INTDIR)/os_w32exe.obj"
+
+CPP_PROJ=$(CPP_PROJ) /O2 /D "NDEBUG" /D "FEAT_GUI_W32" /Fd.\gRel/ /Fo.\gRel/
+# ADD CPP /O2 /D "NDEBUG" /D "FEAT_GUI_W32" /Fd.\gRel/ /Fo.\gRel/
+
+RSC_PROJ=$(RSC_PROJ) /d "NDEBUG" /fo.\gRel\vim.res
+# ADD RSC /d "NDEBUG" /fo.\gRel\vim.res
+
+LINK32_FLAGS=$(LINK32_FLAGS) /pdb:none libc.lib /subsystem:windows /out:.\gvim.exe
+# ADD LINK32 /pdb:none libc.lib /subsystem:windows /out:.\gvim.exe
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug gvim"
+
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir .\gDbg
+# PROP Intermediate_Dir .\gDbg
+
+INTDIR=.\gDbg
+VIM=gvimd
+EXTRAS="$(INTDIR)/vim.res" "$(INTDIR)/gui.obj" "$(INTDIR)/gui_w32.obj" "$(INTDIR)/os_w32exe.obj"
+
+CPP_PROJ=$(CPP_PROJ) /Zi /Od /D "_DEBUG" /D "FEAT_GUI_W32" /Fd.\gDbg/ /Fo.\gDbg/
+# ADD CPP /Zi /Od /D "_DEBUG" /D "FEAT_GUI_W32" /Fd.\gDbg/ /Fo.\gDbg/
+
+RSC_PROJ=$(RSC_PROJ) /d "_DEBUG" /fo.\gDbg\vim.res
+# ADD RSC /d "_DEBUG" /fo.\gDbg\vim.res
+
+LINK32_FLAGS=$(LINK32_FLAGS) libcd.lib /subsystem:windows /debug /profile /pdb:.\gDbg/gvimd.pdb /map:.\gDbg\gvimd.map /out:.\gvimd.exe
+# ADD LINK32 libcd.lib /subsystem:windows /debug /profile /pdb:.\gDbg/gvimd.pdb /map:.\gDbg\gvimd.map /out:.\gvimd.exe
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Release vim"
+
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir .\Rel
+# PROP Intermediate_Dir .\Rel
+
+INTDIR=.\Rel
+VIM=vim
+EXTRAS=
+
+CPP_PROJ=$(CPP_PROJ) /O2 /D "NDEBUG" /Fd.\Rel/ /Fo.\Rel/
+# ADD CPP /O2 /D "NDEBUG" /Fd.\Rel/ /Fo.\Rel/
+
+LINK32_FLAGS=$(LINK32_FLAGS) /pdb:none libc.lib /subsystem:console /out:.\vim.exe
+# ADD LINK32 /pdb:none libc.lib /subsystem:console /out:.\vim.exe
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug vim"
+
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir .\Dbg
+# PROP Intermediate_Dir .\Dbg
+
+INTDIR=.\Dbg
+VIM=vimd
+EXTRAS=
+
+CPP_PROJ=$(CPP_PROJ) /Zi /Od /D "_DEBUG" /Fd.\Dbg/ /Fo.\Dbg/
+# ADD CPP /Zi /Od /D "_DEBUG" /Fd.\Dbg/ /Fo.\Dbg/
+
+LINK32_FLAGS=$(LINK32_FLAGS) libcd.lib /subsystem:console /debug /profile /pdb:.\Dbg/vimd.pdb /map:.\Dbg/vimd.map /out:.\vimd.exe
+# ADD LINK32 libcd.lib /subsystem:console /debug /profile /pdb:.\Dbg/vimd.pdb /map:.\Dbg/vimd.map /out:.\vimd.exe
+
+!ENDIF
+
+ALL : .\$(VIM).exe vimrun.exe install.exe uninstal.exe xxd/xxd.exe GvimExt/gvimext.dll
+
+LINK32_OBJS= \
+ $(EXTRAS) \
+ "$(INTDIR)/buffer.obj" \
+ "$(INTDIR)/charset.obj" \
+ "$(INTDIR)/diff.obj" \
+ "$(INTDIR)/digraph.obj" \
+ "$(INTDIR)/edit.obj" \
+ "$(INTDIR)/eval.obj" \
+ "$(INTDIR)/ex_cmds.obj" \
+ "$(INTDIR)/ex_cmds2.obj" \
+ "$(INTDIR)/ex_docmd.obj" \
+ "$(INTDIR)/ex_eval.obj" \
+ "$(INTDIR)/ex_getln.obj" \
+ "$(INTDIR)/fileio.obj" \
+ "$(INTDIR)/fold.obj" \
+ "$(INTDIR)/getchar.obj" \
+ "$(INTDIR)/main.obj" \
+ "$(INTDIR)/mark.obj" \
+ "$(INTDIR)/mbyte.obj" \
+ "$(INTDIR)/memfile.obj" \
+ "$(INTDIR)/memline.obj" \
+ "$(INTDIR)/menu.obj" \
+ "$(INTDIR)/message.obj" \
+ "$(INTDIR)/misc1.obj" \
+ "$(INTDIR)/misc2.obj" \
+ "$(INTDIR)/move.obj" \
+ "$(INTDIR)/normal.obj" \
+ "$(INTDIR)/ops.obj" \
+ "$(INTDIR)/option.obj" \
+ "$(INTDIR)/os_mswin.obj" \
+ "$(INTDIR)/os_win32.obj" \
+ "$(INTDIR)/quickfix.obj" \
+ "$(INTDIR)/regexp.obj" \
+ "$(INTDIR)/screen.obj" \
+ "$(INTDIR)/search.obj" \
+ "$(INTDIR)/syntax.obj" \
+ "$(INTDIR)/tag.obj" \
+ "$(INTDIR)/term.obj" \
+ "$(INTDIR)/ui.obj" \
+ "$(INTDIR)/undo.obj" \
+ "$(INTDIR)/version.obj" \
+ "$(INTDIR)/window.obj"
+
+".\$(VIM).exe" : "$(INTDIR)" $(EXTRAS) $(LINK32_OBJS)
+ @if exist $(INTDIR)\$(VIM).pdb del $(INTDIR)\$(VIM).pdb
+ $(LINK32) $(LINK32_FLAGS) $(LINK32_OBJS)
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+CLEAN :
+ -@if exist "$(INTDIR)/$(NULL)" $(DEL_TREE) "$(INTDIR)"
+ -@if exist $(VIM).exe erase $(VIM).exe
+ -@if exist $(VIM).ilk erase $(VIM).ilk
+ -@if exist $(VIM).map erase $(VIM).map
+ -@if exist $(VIM).pdb erase $(VIM).pdb
+ -@if exist DLLDATA.C erase DLLDATA.C
+ -@if exist Make_ivc.bak attrib -r Make_ivc.bak
+ -@if exist Make_ivc.bak erase Make_ivc.bak
+ -@if exist Make_ivc.dsp erase Make_ivc.dsp
+ -@if exist Make_ivc.dsw erase Make_ivc.dsw
+ -@if exist Make_ivc.mdp erase Make_ivc.mdp
+ -@if exist Make_ivc.ncb erase Make_ivc.ncb
+ -@if exist Make_ivc.opt erase Make_ivc.opt
+ -@if exist Make_ivc.plg erase Make_ivc.plg
+ -@if exist dosinst.obj erase dosinst.obj
+ -@if exist install.exe erase install.exe
+ -@if exist uninstal.exe erase uninstal.exe
+ -@if exist uninstal.obj erase uninstal.obj
+ -@if exist vimrun.exe erase vimrun.exe
+ -@if exist vimrun.obj erase vimrun.obj
+
+
+install.exe: dosinst.c
+ $(CPP) /Fe$@ /nologo /W3 -DNDEBUG -DWIN32 dosinst.c kernel32.lib shell32.lib ole32.lib advapi32.lib uuid.lib
+
+uninstal.exe: uninstal.c
+ $(CPP) /nologo /W3 -DNDEBUG -DWIN32 uninstal.c shell32.lib advapi32.lib
+
+vimrun.exe: vimrun.c
+ $(CPP) /nologo /W3 -DNDEBUG vimrun.c
+
+xxd/xxd.exe: xxd/xxd.c
+ cd xxd
+ $(MAKE) /NOLOGO -f Make_mvc.mak
+ cd ..
+
+GvimExt/gvimext.dll: GvimExt/gvimext.cpp GvimExt/gvimext.rc GvimExt/gvimext.h
+ cd GvimExt
+ $(MAKE) /NOLOGO -f Makefile
+ cd ..
+
+{.}.c{$(INTDIR)/}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+{.}.cpp{$(INTDIR)/}.obj:
+ $(CPP) $(CPP_PROJ) /I $(INTDIR) $<
+
+{.}.rc{$(INTDIR)/}.res:
+ $(RSC) $(RSC_PROJ) $<
+
+# Begin Target
+
+# Name "Vim - Win32 Release gvim OLE"
+# Name "Vim - Win32 Debug gvim OLE"
+# Name "Vim - Win32 Release gvim"
+# Name "Vim - Win32 Debug gvim"
+# Name "Vim - Win32 Release vim"
+# Name "Vim - Win32 Debug vim"
+
+# Begin Source File
+
+SOURCE=.\buffer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\charset.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\diff.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\digraph.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\edit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\eval.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ex_cmds.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ex_cmds2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ex_docmd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ex_eval.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ex_getln.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fileio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fold.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\getchar.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\gui.c
+
+!IF "$(CFG)" == "Vim - Win32 Release vim"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug vim"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gui_w32.c
+
+!IF "$(CFG)" == "Vim - Win32 Release vim"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug vim"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\os_w32exe.c
+
+!IF "$(CFG)" == "Vim - Win32 Release vim"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug vim"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\if_ole.cpp
+
+!IF "$(CFG)" == "Vim - Win32 Release gvim OLE"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build
+
+"$(INTDIR)\if_ole.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\if_ole.h"
+ cl.exe /nologo /MT /W3 /GX /I ".\proto" /D "WIN32" /c /O2 /D "NDEBUG" /D "FEAT_GUI_W32" /D "FEAT_OLE" /Fd.\oleRel/ /Fo.\oleRel/ /I ".\oleRel" .\if_ole.cpp
+ @rem This is the default rule with /I "$(IntDir)" added
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug gvim OLE"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build
+
+"$(INTDIR)\if_ole.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\if_ole.h"
+ cl.exe /nologo /MT /W3 /GX /I ".\proto" /D "WIN32" /c /Zi /Od /D "_DEBUG" /D "FEAT_GUI_W32" /D "FEAT_OLE" /Fd.\oleDbg/ /Fo.\oleDbg/ /I ".\oleDbg" .\if_ole.cpp
+ @rem This is the default rule with /I "$(IntDir)" added
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Release gvim"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug gvim"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Release vim"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug vim"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\if_ole.idl
+
+!IF "$(CFG)" == "Vim - Win32 Release gvim OLE"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build
+
+"$(INTDIR)\if_ole.h" : $(SOURCE) "$(INTDIR)"
+ if exist .\if_ole.h del .\if_ole.h
+ midl /out .\oleRel /iid iid_ole.c /tlb vim.tlb /proxy nul /header if_ole.h .\if_ole.idl
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug gvim OLE"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build
+
+"$(INTDIR)\if_ole.h" : $(SOURCE) "$(INTDIR)"
+ if exist .\if_ole.h del .\if_ole.h
+ midl /out .\oleDbg /iid iid_ole.c /tlb vim.tlb /proxy nul /header if_ole.h .\if_ole.idl
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Release gvim"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug gvim"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Release vim"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug vim"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mark.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mbyte.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\memfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\memline.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\menu.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\message.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc1.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\move.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\normal.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ops.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\option.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os_mswin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os_win32.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\quickfix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\regexp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\screen.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\search.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\syntax.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\tag.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\term.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ui.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\undo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\version.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\vim.rc
+
+!IF "$(CFG)" == "Vim - Win32 Release gvim OLE"
+
+"$(INTDIR)\vim.res" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\if_ole.h"
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug gvim OLE"
+
+"$(INTDIR)\vim.res" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\if_ole.h"
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Release gvim"
+
+"$(INTDIR)\vim.res" : $(SOURCE) "$(INTDIR)"
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug gvim"
+
+"$(INTDIR)\vim.res" : $(SOURCE) "$(INTDIR)"
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Release vim"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "Vim - Win32 Debug vim"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\window.c
+# End Source File
+# End Target
+# End Project
diff --git a/src/Make_manx.mak b/src/Make_manx.mak
new file mode 100644
index 000000000..b7c06e986
--- /dev/null
+++ b/src/Make_manx.mak
@@ -0,0 +1,322 @@
+#
+# Makefile for VIM on the Amiga, using Aztec/Manx C 5.0 or later
+#
+# Note: Not all dependencies are included. This was done to avoid having
+# to compile everything when a global variable or function is added.
+# Careful when changing a global struct or variable!
+#
+
+#>>>>> choose options:
+
+### See feature.h for a list of optionals.
+### Any other defines can be included here.
+DEFINES =
+
+#>>>>> if HAVE_TGETENT is defined obj/termlib.o has to be used
+#TERMLIB = obj/termlib.o
+TERMLIB =
+
+#>>>>> choose between debugging (-bs) or optimizing (-so)
+OPTIONS = -so
+#OPTIONS = -bs
+
+#>>>>> end of choices
+###########################################################################
+
+CFLAGS = $(OPTIONS) -wapruq -ps -qf -Iproto $(DEFINES) -DAMIGA
+
+LIBS = -lc16
+SYMS = vim.syms
+CC = cc
+LN = ln
+LNFLAGS = +q
+SHELL = csh
+REN = $(SHELL) -c mv -f
+DEL = $(SHELL) -c rm -f
+
+SRC = buffer.c \
+ charset.c \
+ diff.c \
+ digraph.c \
+ edit.c \
+ eval.c \
+ ex_cmds.c \
+ ex_cmds2.c \
+ ex_docmd.c \
+ ex_eval.c \
+ ex_getln.c \
+ fileio.c \
+ fold.c \
+ getchar.c \
+ main.c \
+ mark.c \
+ memfile.c \
+ memline.c \
+ menu.c \
+ message.c \
+ misc1.c \
+ misc2.c \
+ move.c \
+ mbyte.c \
+ normal.c \
+ ops.c \
+ option.c \
+ os_amiga.c \
+ quickfix.c \
+ regexp.c \
+ screen.c \
+ search.c \
+ syntax.c \
+ tag.c \
+ term.c \
+ ui.c \
+ undo.c \
+ window.c \
+ version.c
+
+INCL = vim.h feature.h keymap.h macros.h ascii.h term.h structs.h os_amiga.h
+
+OBJ = obj/buffer.o \
+ obj/charset.o \
+ obj/diff.o \
+ obj/digraph.o \
+ obj/edit.o \
+ obj/eval.o \
+ obj/ex_cmds.o \
+ obj/ex_cmds2.o \
+ obj/ex_docmd.o \
+ obj/ex_eval.o \
+ obj/ex_getln.o \
+ obj/fileio.o \
+ obj/fold.o \
+ obj/getchar.o \
+ obj/main.o \
+ obj/mark.o \
+ obj/memfile.o \
+ obj/memline.o \
+ obj/menu.o \
+ obj/message.o \
+ obj/misc1.o \
+ obj/misc2.o \
+ obj/move.o \
+ obj/mbyte.o \
+ obj/normal.o \
+ obj/ops.o \
+ obj/option.o \
+ obj/os_amiga.o \
+ obj/quickfix.o \
+ obj/regexp.o \
+ obj/screen.o \
+ obj/search.o \
+ obj/syntax.o \
+ obj/tag.o \
+ obj/term.o \
+ obj/ui.o \
+ obj/undo.o \
+ obj/window.o \
+ $(TERMLIB)
+
+PRO = proto/buffer.pro \
+ proto/charset.pro \
+ proto/diff.pro \
+ proto/digraph.pro \
+ proto/edit.pro \
+ proto/eval.pro \
+ proto/ex_cmds.pro \
+ proto/ex_cmds2.pro \
+ proto/ex_docmd.pro \
+ proto/ex_eval.pro \
+ proto/ex_getln.pro \
+ proto/fileio.pro \
+ proto/fold.pro \
+ proto/getchar.pro \
+ proto/main.pro \
+ proto/mark.pro \
+ proto/memfile.pro \
+ proto/memline.pro \
+ proto/menu.pro \
+ proto/message.pro \
+ proto/misc1.pro \
+ proto/misc2.pro \
+ proto/move.pro \
+ proto/mbyte.pro \
+ proto/normal.pro \
+ proto/ops.pro \
+ proto/option.pro \
+ proto/os_amiga.pro \
+ proto/quickfix.pro \
+ proto/regexp.pro \
+ proto/screen.pro \
+ proto/search.pro \
+ proto/syntax.pro \
+ proto/tag.pro \
+ proto/term.pro \
+ proto/termlib.pro \
+ proto/ui.pro \
+ proto/undo.pro \
+ proto/window.pro
+
+all: Vim xxd/Xxd
+
+Vim: obj $(OBJ) version.c version.h
+ $(CC) $(CFLAGS) version.c -o obj/version.o
+ $(LN) $(LNFLAGS) -m -o Vim $(OBJ) obj/version.o $(LIBS)
+
+debug: obj $(OBJ) version.c version.h
+ $(CC) $(CFLAGS) version.c -o obj/version.o
+ $(LN) $(LNFLAGS) -m -g -o Vim $(OBJ) obj/version.o $(LIBS)
+
+xxd/Xxd: xxd/xxd.c
+ $(SHELL) -c cd xxd; make -f Make_amiga.mak; cd ..
+
+# Making prototypes with Manx has been removed, because it caused too many
+# problems.
+#proto: $(SYMS) $(PRO)
+
+obj:
+ makedir obj
+
+tags: $(SRC) $(INCL)
+ $(SHELL) -c ctags $(SRC) *.h
+
+# can't use delete here, too many file names
+clean:
+ $(DEL) $(OBJ) obj/version.o \
+ obj/termlib.o Vim $(SYMS) xxd/Xxd
+
+test:
+ $(SHELL) -c cd testdir; make -f Make_amiga.mak; cd ..
+
+$(SYMS): $(INCL) $(PRO)
+ $(CC) $(CFLAGS) -ho$(SYMS) vim.h
+
+###########################################################################
+
+# Unfortunately, Manx's make doesn't understand a .c.o rule, so each
+# compilation command has to be given explicitly.
+
+CCSYM = $(CC) $(CFLAGS) -hi$(SYMS) -o
+CCNOSYM = $(CC) $(CFLAGS) -o
+
+$(OBJ): $(SYMS)
+
+obj/buffer.o: buffer.c
+ $(CCSYM) $@ buffer.c
+
+obj/charset.o: charset.c
+ $(CCSYM) $@ charset.c
+
+obj/diff.o: diff.c
+ $(CCSYM) $@ diff.c
+
+obj/digraph.o: digraph.c
+ $(CCSYM) $@ digraph.c
+
+obj/edit.o: edit.c
+ $(CCSYM) $@ edit.c
+
+obj/eval.o: eval.c
+ $(CCSYM) $@ eval.c
+
+obj/ex_cmds.o: ex_cmds.c
+ $(CCSYM) $@ ex_cmds.c
+
+obj/ex_cmds2.o: ex_cmds2.c
+ $(CCSYM) $@ ex_cmds2.c
+
+# Don't use $(SYMS) here, because ex_docmd.c defines DO_DECLARE_EXCMD
+obj/ex_docmd.o: ex_docmd.c ex_cmds.h
+ $(CCNOSYM) $@ ex_docmd.c
+
+obj/ex_eval.o: ex_eval.c ex_cmds.h
+ $(CCSYM) $@ ex_eval.c
+
+obj/ex_getln.o: ex_getln.c
+ $(CCSYM) $@ ex_getln.c
+
+obj/fileio.o: fileio.c
+ $(CCSYM) $@ fileio.c
+
+obj/fold.o: fold.c
+ $(CCSYM) $@ fold.c
+
+obj/getchar.o: getchar.c
+ $(CCSYM) $@ getchar.c
+
+# Don't use $(SYMS) here, because main.c defines EXTERN
+obj/main.o: main.c option.h globals.h
+ $(CCNOSYM) $@ main.c
+
+obj/mark.o: mark.c
+ $(CCSYM) $@ mark.c
+
+obj/memfile.o: memfile.c
+ $(CCSYM) $@ memfile.c
+
+obj/memline.o: memline.c
+ $(CCSYM) $@ memline.c
+
+obj/menu.o: menu.c
+ $(CCSYM) $@ menu.c
+
+# Don't use $(SYMS) here, because message.c defines MESSAGE_FILE
+obj/message.o: message.c
+ $(CCNOSYM) $@ message.c
+
+obj/misc1.o: misc1.c
+ $(CCSYM) $@ misc1.c
+
+obj/misc2.o: misc2.c
+ $(CCSYM) $@ misc2.c
+
+obj/move.o: move.c
+ $(CCSYM) $@ move.c
+
+obj/mbyte.o: mbyte.c
+ $(CCSYM) $@ mbyte.c
+
+obj/normal.o: normal.c
+ $(CCSYM) $@ normal.c
+
+obj/ops.o: ops.c
+ $(CCSYM) $@ ops.c
+
+# Don't use $(SYMS) here, because option.h defines variables here
+obj/option.o: option.c
+ $(CCNOSYM) $@ option.c
+
+obj/os_amiga.o: os_amiga.c
+ $(CCSYM) $@ os_amiga.c
+
+obj/quickfix.o: quickfix.c
+ $(CCSYM) $@ quickfix.c
+
+obj/regexp.o: regexp.c
+ $(CCSYM) $@ regexp.c
+
+obj/screen.o: screen.c
+ $(CCSYM) $@ screen.c
+
+obj/search.o: search.c
+ $(CCSYM) $@ search.c
+
+obj/syntax.o: syntax.c
+ $(CCSYM) $@ syntax.c
+
+obj/tag.o: tag.c
+ $(CCSYM) $@ tag.c
+
+obj/term.o: term.c term.h
+ $(CCSYM) $@ term.c
+
+obj/termlib.o: termlib.c
+ $(CCSYM) $@ termlib.c
+
+obj/ui.o: ui.c
+ $(CCSYM) $@ ui.c
+
+obj/undo.o: undo.c
+ $(CCSYM) $@ undo.c
+
+obj/window.o: window.c
+ $(CCSYM) $@ window.c
diff --git a/src/Make_ming.mak b/src/Make_ming.mak
new file mode 100644
index 000000000..06780627b
--- /dev/null
+++ b/src/Make_ming.mak
@@ -0,0 +1,555 @@
+# Makefile for VIM on Win32, using 'EGCS/mingw32 1.1.2'.
+# Info at http://www.mingw.org
+# Also requires 'GNU make 3.77', which you can get through a link
+# to 'JanJaap's page from the above page.
+# Get missing libraries from http://gnuwin32.sf.net.
+#
+# Tested on Win32 NT 4 and Win95.
+#
+# To make everything, just 'make -f Make_ming.mak'
+# To make just e.g. gvim.exe, 'make -f Make_ming.mak gvim.exe'
+# After a run, you can 'make -f Make_ming.mak clean' to clean up
+#
+# NOTE: Sometimes 'GNU Make' will stop after building vimrun.exe -- I think
+# it's just run out of memory or something. Run again, and it will continue
+# with 'xxd'.
+#
+# "make upx" makes *compressed* versions of the GUI and console EXEs, using the
+# excellent UPX compressor:
+# http://upx.sourceforge.net/
+#
+# Maintained by Ron Aaron <ronaharon@yahoo.com>
+# updated 2003 Jan 20
+
+#>>>>> choose options:
+# set to yes for a debug build
+DEBUG=no
+# set to SIZE for size, SPEED for speed, MAXSPEED for maximium optimization
+OPTIMIZE=MAXSPEED
+# set to yes to make gvim, no for vim
+GUI=yes
+# FEATURES=[TINY | SMALL | NORMAL | BIG | HUGE]
+# set to TINY to make minimal version (few features)
+FEATURES=BIG
+# set to one of i386, i486, i586, i686 as the *target* processor
+CPUNR=i686
+# set to same choices as 'CPUNR', but will prevent running on 'lower' cpus:
+ARCH=i386
+# set to yes to cross-compile from unix; no=native Windows
+CROSS=no
+# set to path to iconv.h and libiconv.a to enable using 'iconv.dll'
+#ICONV="."
+ICONV=yes
+GETTEXT=yes
+# set to yes to include multibyte support
+MBYTE=yes
+# set to yes to include IME support
+IME=yes
+DYNAMIC_IME=yes
+# set to yes to enable writing a postscript file with :hardcopy
+POSTSCRIPT=no
+# set to yes to enable OLE support
+OLE=no
+# Set the default $(WINVER) to make it work with pre-Win2k
+WINVER = 0x0400
+# Set to yes to enable Cscope support
+CSCOPE=yes
+# Set to yes to enable Netbeans support
+NETBEANS=$(GUI)
+
+
+# If the user doesn't want gettext, undefine it.
+ifeq (no, $(GETTEXT))
+GETTEXT=
+endif
+# Added by E.F. Amatria <eferna1@platea.ptic.mec.es> 2001 Feb 23
+# Uncomment the first line and one of the following three if you want Native Language
+# Support. You'll need gnu_gettext.win32, a MINGW32 Windows PORT of gettext by
+# Franco Bez <franco.bez@gmx.de>. It may be found at
+# http://home.a-city.de/franco.bez/gettext/gettext_win32_en.html
+# Tested with mingw32 with GCC-2.95.2 on Win98
+# Updated 2001 Jun 9
+#GETTEXT=c:/gettext.win32.msvcrt
+#STATIC_GETTEXT=USE_STATIC_GETTEXT
+#DYNAMIC_GETTEXT=USE_GETTEXT_DLL
+#DYNAMIC_GETTEXT=USE_SAFE_GETTEXT_DLL
+SAFE_GETTEXT_DLL_OBJ = $(GETTEXT)/src/safe_gettext_dll/safe_gettext_dll.o
+# Alternatively, if you uncomment the two following lines, you get a "safe" version
+# without linking the safe_gettext_dll.o object file.
+#DYNAMIC_GETTEXT=DYNAMIC_GETTEXT
+#GETTEXT_DYNAMIC=gnu_gettext.dll
+INTLPATH=$(GETTEXT)/lib/mingw32
+INTLLIB=gnu_gettext
+
+# If you are using gettext-0.10.35 from http://sourceforge.net/projects/gettext
+# or gettext-0.10.37 from http://sourceforge.net/projects/mingwrep/
+# uncomment the following, but I can't build a static versión with them, ?-(|
+#GETTEXT=c:/gettext-0.10.37-20010430
+#STATIC_GETTEXT=USE_STATIC_GETTEXT
+#DYNAMIC_GETTEXT=DYNAMIC_GETTEXT
+#INTLPATH=$(GETTEXT)/lib
+#INTLLIB=intl
+
+# uncomment 'PERL' if you want a perl-enabled version
+#PERL=C:/perl
+ifdef PERL
+ifndef PERL_VER
+PERL_VER=56
+endif
+ifndef DYNAMIC_PERL
+DYNAMIC_PERL=yes
+endif
+# on Linux, for cross-compile, it's here:
+#PERLLIB=/home/ron/ActivePerl/lib
+# on NT, it's here:
+PERLLIB=$(PERL)/lib
+PERLLIBS=$(PERLLIB)/Core
+endif
+
+# Python support -- works with the ActiveState python 2.0 release (and others
+# too, probably)
+#
+# uncomment 'PYTHON' to make python-enabled version
+# Put the path to the python distro here. If cross compiling from Linux, you
+# will also need to convert the header files to unix instead of dos format:
+# for fil in *.h ; do vim -e -c 'set ff=unix|w|q' $fil
+# and also, you will need to make a mingw32 'libpython20.a' to link with:
+# cd $PYTHON/libs
+# pexports python20.dll > python20.def
+# dlltool -d python20.def -l libpython20.a
+# on my Linux box, I put the Python stuff here:
+#PYTHON=/home/ron/ActivePython-2.0.0-202/src/Core
+# on my NT box, it's here:
+#PYTHON=c:/python20
+
+ifdef PYTHON
+ifndef DYNAMIC_PYTHON
+DYNAMIC_PYTHON=yes
+endif
+
+ifndef PYTHON_VER
+PYTHON_VER=22
+endif
+
+ifeq (no,$(DYNAMIC_PYTHON))
+PYTHONLIB=-L$(PYTHON)/libs -lpython$(PYTHON_VER)
+endif
+# my include files are in 'win32inc' on Linux, and 'include' in the standard
+# NT distro (ActiveState)
+ifeq ($(CROSS),no)
+PYTHONINC=-I $(PYTHON)/include
+else
+PYTHONINC=-I $(PYTHON)/win32inc
+endif
+endif
+
+# TCL interface:
+# TCL=[Path to TCL directory]
+# DYNAMIC_TCL=yes (to load the TCL DLL dynamically)
+# TCL_VER=[TCL version, eg 83, 84] (default is 83)
+#TCL=c:/tcl
+ifdef TCL
+ifndef DYNAMIC_TCL
+DYNAMIC_TCL=yes
+endif
+ifndef TCL_VER
+TCL_VER = 83
+endif
+TCLINC += -I$(TCL)/include
+endif
+
+
+# Ruby interface:
+# RUBY=[Path to Ruby directory]
+# DYNAMIC_RUBY=yes (to load the Ruby DLL dynamically)
+# RUBY_VER=[Ruby version, eg 16, 17] (default is 16)
+# RUBY_VER_LONG=[Ruby version, eg 1.6, 1.7] (default is 1.6)
+# You must set RUBY_VER_LONG when change RUBY_VER.
+#RUBY=c:/ruby
+ifdef RUBY
+ifndef DYNAMIC_RUBY
+DYNAMIC_RUBY=yes
+endif
+# Set default value
+ifndef RUBY_VER
+RUBY_VER = 16
+endif
+ifndef RUBY_VER_LONG
+RUBY_VER_LONG = 1.6
+endif
+
+ifeq ($(RUBY_VER), 16)
+ifndef RUBY_PLATFORM
+RUBY_PLATFORM = i586-mswin32
+endif
+ifndef RUBY_INSTALL_NAME
+RUBY_INSTALL_NAME = mswin32-ruby$(RUBY_VER)
+endif
+else
+ifndef RUBY_PLATFORM
+RUBY_PLATFORM = i386-mswin32
+endif
+ifndef RUBY_INSTALL_NAME
+RUBY_INSTALL_NAME = msvcrt-ruby$(RUBY_VER)
+endif
+endif
+
+RUBYINC =-I $(RUBY)/lib/ruby/$(RUBY_VER_LONG)/$(RUBY_PLATFORM)
+ifeq (no, $(DYNAMIC_RUBY))
+RUBYLIB = -L$(RUBY)/lib -l$(RUBY_INSTALL_NAME)
+endif
+
+endif # RUBY
+
+# See feature.h for a list of options.
+# Any other defines can be included here.
+DEF_GUI=-DFEAT_GUI_W32 -DFEAT_CLIPBOARD
+DEFINES=-DWIN32 -DWINVER=$(WINVER) -D_WIN32_WINNT=$(WINVER) \
+ -DHAVE_PATHDEF -DFEAT_$(FEATURES)
+ifeq ($(CROSS),yes)
+# cross-compiler:
+CC = i586-pc-mingw32msvc-gcc
+DEL = rm
+WINDRES = i586-pc-mingw32msvc-windres
+else
+# normal (Windows) compilation:
+CC = gcc
+ifneq (sh.exe, $(SHELL))
+DEL = rm
+DIRSLASH = /
+else
+DEL = del
+DIRSLASH = \\
+endif
+WINDRES = windres
+endif
+
+#>>>>> end of choices
+###########################################################################
+
+CFLAGS = -Iproto $(DEFINES) -pipe -w -march=$(ARCH) -mcpu=$(CPUNR) -Wall
+
+ifdef GETTEXT
+DEFINES +=-DHAVE_GETTEXT -DHAVE_LOCALE_H
+GETTEXTINCLUDE = $(GETTEXT)/include
+GETTEXTLIB = $(INTLPATH)
+ifeq (yes, $(GETTEXT))
+DEFINES +=-DDYNAMIC_GETTEXT
+else
+ifdef DYNAMIC_GETTEXT
+DEFINES +=-D$(DYNAMIC_GETTEXT)
+ifdef GETTEXT_DYNAMIC
+DEFINES += -DGETTEXT_DYNAMIC -DGETTEXT_DLL=\"$(GETTEXT_DYNAMIC)\"
+endif
+endif
+endif
+endif
+
+ifdef PERL
+CFLAGS += -I$(PERLLIBS) -DFEAT_PERL -L$(PERLLIBS)
+ifeq (yes, $(DYNAMIC_PERL))
+CFLAGS += -DDYNAMIC_PERL -DDYNAMIC_PERL_DLL=\"perl$(PERL_VER).dll\"
+endif
+endif
+
+ifdef RUBY
+CFLAGS += -DFEAT_RUBY $(RUBYINC)
+ifeq (yes, $(DYNAMIC_RUBY))
+CFLAGS += -DDYNAMIC_RUBY -DDYNAMIC_RUBY_DLL=\"$(RUBY_INSTALL_NAME).dll\"
+CFLAGS += -DDYNAMIC_RUBY_VER=$(RUBY_VER)
+endif
+endif
+
+ifdef PYTHON
+CFLAGS += -DFEAT_PYTHON $(PYTHONINC)
+ifeq (yes, $(DYNAMIC_PYTHON))
+CFLAGS += -DDYNAMIC_PYTHON -DDYNAMIC_PYTHON_DLL=\"python$(PYTHON_VER).dll\"
+endif
+endif
+
+ifdef TCL
+CFLAGS += -DFEAT_TCL $(TCLINC)
+ifeq (yes, $(DYNAMIC_TCL))
+CFLAGS += -DDYNAMIC_TCL -DDYNAMIC_TCL_DLL=\"tcl$(TCL_VER).dll\"
+endif
+endif
+
+ifeq ($(POSTSCRIPT),yes)
+DEFINES += -DMSWINPS
+endif
+
+ifeq (yes, $(OLE))
+DEFINES += -DFEAT_OLE
+endif
+
+ifeq ($(CSCOPE),yes)
+DEFINES += -DFEAT_CSCOPE
+endif
+
+ifeq ($(NETBEANS),yes)
+DEFINES += -DFEAT_NETBEANS_INTG
+ifeq ($(DEBUG), yes)
+DEFINES += -DNBDEBUG
+NBDEBUG_INCL = nbdebug.h
+NBDEBUG_SRC = nbdebug.c
+endif
+endif
+
+ifdef XPM
+CFLAGS += -DFEAT_XPM_W32 -I $(XPM)/include
+endif
+
+ifeq ($(DEBUG),yes)
+CFLAGS += -g -fstack-check
+DEBUG_SUFFIX=d
+else
+ifeq ($(OPTIMIZE), SIZE)
+CFLAGS += -Os
+else
+ifeq ($(OPTIMIZE), MAXSPEED)
+CFLAGS += -O3
+CFLAGS += -fomit-frame-pointer -freg-struct-return -malign-double
+else # SPEED
+CFLAGS += -O2
+endif
+endif
+CFLAGS += -s
+endif
+
+LIB = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lcomdlg32 -lcomctl32
+GUIOBJ = $(OUTDIR)/gui.o $(OUTDIR)/gui_w32.o $(OUTDIR)/os_w32exe.o
+OBJ = \
+ $(OUTDIR)/buffer.o \
+ $(OUTDIR)/charset.o \
+ $(OUTDIR)/diff.o \
+ $(OUTDIR)/digraph.o \
+ $(OUTDIR)/edit.o \
+ $(OUTDIR)/eval.o \
+ $(OUTDIR)/ex_cmds.o \
+ $(OUTDIR)/ex_cmds2.o \
+ $(OUTDIR)/ex_docmd.o \
+ $(OUTDIR)/ex_eval.o \
+ $(OUTDIR)/ex_getln.o \
+ $(OUTDIR)/fileio.o \
+ $(OUTDIR)/fold.o \
+ $(OUTDIR)/getchar.o \
+ $(OUTDIR)/main.o \
+ $(OUTDIR)/mark.o \
+ $(OUTDIR)/memfile.o \
+ $(OUTDIR)/memline.o \
+ $(OUTDIR)/menu.o \
+ $(OUTDIR)/message.o \
+ $(OUTDIR)/misc1.o \
+ $(OUTDIR)/misc2.o \
+ $(OUTDIR)/move.o \
+ $(OUTDIR)/mbyte.o \
+ $(OUTDIR)/normal.o \
+ $(OUTDIR)/ops.o \
+ $(OUTDIR)/option.o \
+ $(OUTDIR)/os_win32.o \
+ $(OUTDIR)/os_mswin.o \
+ $(OUTDIR)/pathdef.o \
+ $(OUTDIR)/quickfix.o \
+ $(OUTDIR)/regexp.o \
+ $(OUTDIR)/screen.o \
+ $(OUTDIR)/search.o \
+ $(OUTDIR)/syntax.o \
+ $(OUTDIR)/tag.o \
+ $(OUTDIR)/term.o \
+ $(OUTDIR)/ui.o \
+ $(OUTDIR)/undo.o \
+ $(OUTDIR)/version.o \
+ $(OUTDIR)/vimrc.o \
+ $(OUTDIR)/window.o
+
+ifdef PERL
+OBJ += $(OUTDIR)/if_perl.o
+endif
+ifdef PYTHON
+OBJ += $(OUTDIR)/if_python.o
+endif
+ifdef RUBY
+OBJ += $(OUTDIR)/if_ruby.o
+endif
+ifdef TCL
+OBJ += $(OUTDIR)/if_tcl.o
+endif
+ifeq ($(CSCOPE),yes)
+OBJ += $(OUTDIR)/if_cscope.o
+endif
+ifeq ($(NETBEANS),yes)
+OBJ += $(OUTDIR)/netbeans.o $(OUTDIR)/gui_beval.o
+LIB += -lwsock32
+endif
+ifdef XPM
+OBJ += $(OUTDIR)/xpm_w32.o
+# You'll need libXpm.a from http://gnuwin32.sf.net
+LIB += -L $(XPM)/lib -lXpm
+endif
+
+
+ifeq ($(GUI),yes)
+TARGET := gvim$(DEBUG_SUFFIX).exe
+DEFINES += $(DEF_GUI)
+OBJ += $(GUIOBJ)
+LFLAGS += -mwindows
+OUTDIR = gobj$(DEBUG_SUFFIX)
+else
+TARGET := vim$(DEBUG_SUFFIX).exe
+OUTDIR = obj$(DEBUG_SUFFIX)
+endif
+
+ifdef GETTEXT
+ifneq (yes, $(GETTEXT))
+CFLAGS += -I$(GETTEXTINCLUDE)
+ifndef STATIC_GETTEXT
+LIB += -L$(GETTEXTLIB) -l$(INTLLIB)
+ifeq (USE_SAFE_GETTEXT_DLL, $(DYNAMIC_GETTEXT))
+OBJ+=$(SAFE_GETTEXT_DLL_OBJ)
+endif
+else
+LIB += -L$(GETTEXTLIB) -lintl
+endif
+endif
+endif
+
+ifdef PERL
+ifeq (no, $(DYNAMIC_PERL))
+LIB += -lperl$(PERL_VER)
+endif
+endif
+
+ifdef TCL
+LIB += -L$(TCL)/lib
+ifeq (yes, $(DYNAMIC_TCL))
+LIB += -ltclstub$(TCL_VER)
+else
+LIB += -ltcl$(TCL_VER)
+endif
+endif
+
+ifeq (yes, $(OLE))
+LIB += -loleaut32 -lstdc++
+OBJ += $(OUTDIR)/if_ole.o
+endif
+
+ifeq (yes, $(MBYTE))
+DEFINES += -DFEAT_MBYTE
+endif
+
+ifeq (yes, $(IME))
+DEFINES += -DFEAT_MBYTE_IME
+ifeq (yes, $(DYNAMIC_IME))
+DEFINES += -DDYNAMIC_IME
+else
+LIB += -limm32
+endif
+endif
+
+ifdef ICONV
+ifneq (yes, $(ICONV))
+LIB += -L$(ICONV)
+CFLAGS += -I$(ICONV)
+endif
+DEFINES+=-DDYNAMIC_ICONV
+endif
+
+all: $(TARGET) vimrun.exe xxd/xxd.exe install.exe uninstal.exe GvimExt/gvimext.dll
+
+vimrun.exe: vimrun.c
+ $(CC) $(CFLAGS) -o vimrun.exe vimrun.c $(LIB)
+
+install.exe: dosinst.c
+ $(CC) $(CFLAGS) -o install.exe dosinst.c $(LIB) -lole32 -luuid
+
+uninstal.exe: uninstal.c
+ $(CC) $(CFLAGS) -o uninstal.exe uninstal.c $(LIB)
+
+$(TARGET): $(OUTDIR) $(OBJ)
+ $(CC) $(CFLAGS) $(LFLAGS) -o $@ $(OBJ) $(LIB) -lole32 -luuid $(PYTHONLIB) $(RUBYLIB)
+
+upx: exes
+ upx gvim.exe
+ upx vim.exe
+
+xxd/xxd.exe: xxd/xxd.c
+ $(MAKE) -C xxd -f Make_cyg.mak
+
+GvimExt/gvimext.dll: GvimExt/gvimext.cpp GvimExt/gvimext.rc GvimExt/gvimext.h
+ $(MAKE) -C GvimExt -f Make_ming.mak
+
+clean:
+ -$(DEL) $(OUTDIR)$(DIRSLASH)*.o
+ -$(DEL) $(OUTDIR)$(DIRSLASH)*.res
+ -rmdir $(OUTDIR)
+ -$(DEL) *.exe
+ -$(DEL) pathdef.c
+ifdef PERL
+ -$(DEL) if_perl.c
+endif
+ $(MAKE) -C GvimExt -f Make_ming.mak clean
+ $(MAKE) -C xxd -f Make_cyg.mak clean
+
+###########################################################################
+INCL = vim.h feature.h os_win32.h os_dos.h ascii.h keymap.h term.h macros.h \
+ structs.h regexp.h option.h ex_cmds.h proto.h globals.h farsi.h \
+ gui.h
+
+$(OUTDIR)/%.o : %.c $(INCL)
+ $(CC) -c $(CFLAGS) $< -o $@
+
+$(OUTDIR)/vimres.res: vim.rc version.h gui_w32_rc.h
+ $(WINDRES) $(DEFINES) vim.rc $(OUTDIR)/vimres.res
+
+$(OUTDIR)/vimrc.o: $(OUTDIR)/vimres.res
+ $(WINDRES) $(OUTDIR)/vimres.res $(OUTDIR)/vimrc.o
+
+$(OUTDIR):
+ mkdir $(OUTDIR)
+
+$(OUTDIR)/ex_docmd.o: ex_docmd.c $(INCL) ex_cmds.h
+ $(CC) -c $(CFLAGS) ex_docmd.c -o $(OUTDIR)/ex_docmd.o
+
+$(OUTDIR)/ex_eval.o: ex_eval.c $(INCL) ex_cmds.h
+ $(CC) -c $(CFLAGS) ex_eval.c -o $(OUTDIR)/ex_eval.o
+
+$(OUTDIR)/if_cscope.o: if_cscope.c $(INCL) if_cscope.h
+ $(CC) -c $(CFLAGS) if_cscope.c -o $(OUTDIR)/if_cscope.o
+
+$(OUTDIR)/if_ole.o: if_ole.cpp $(INCL)
+ $(CC) $(CFLAGS) -D__IID_DEFINED__ -c -o $(OUTDIR)/if_ole.o if_ole.cpp
+
+$(OUTDIR)/if_ruby.o: if_ruby.c $(INCL)
+ifeq (16, $(RUBY))
+ $(CC) $(CFLAGS) -U_WIN32 -c -o $(OUTDIR)/if_ruby.o if_ruby.c
+endif
+
+if_perl.c: if_perl.xs typemap
+ perl $(PERLLIB)/ExtUtils/xsubpp -prototypes -typemap \
+ $(PERLLIB)/ExtUtils/typemap if_perl.xs > $@
+
+$(OUTDIR)/netbeans.o: netbeans.c $(INCL) $(NBDEBUG_INCL) $(NBDEBUG_SRC)
+ $(CC) -c $(CFLAGS) netbeans.c -o $(OUTDIR)/netbeans.o
+
+pathdef.c: $(INCL)
+ifneq (sh.exe, $(SHELL))
+ @echo creating pathdef.c
+ @echo '/* pathdef.c */' > pathdef.c
+ @echo '#include "vim.h"' >> pathdef.c
+ @echo 'char_u *default_vim_dir = (char_u *)"$(VIMRCLOC)";' >> pathdef.c
+ @echo 'char_u *default_vimruntime_dir = (char_u *)"$(VIMRUNTIMEDIR)";' >> pathdef.c
+ @echo 'char_u *all_cflags = (char_u *)"$(CC) $(CFLAGS)";' >> pathdef.c
+ @echo 'char_u *all_lflags = (char_u *)"$(CC) -s -o $(TARGET) $(LIB) -luuid -lole32 $(PYTHONLIB) $(RUBYLIB)";' >> pathdef.c
+ @echo 'char_u *compiled_user = (char_u *)"$(USERNAME)";' >> pathdef.c
+ @echo 'char_u *compiled_sys = (char_u *)"$(USERDOMAIN)";' >> pathdef.c
+else
+ @echo creating pathdef.c
+ @echo /* pathdef.c */ > pathdef.c
+ @echo #include "vim.h" >> pathdef.c
+ @echo char_u *default_vim_dir = (char_u *)"$(VIMRCLOC)"; >> pathdef.c
+ @echo char_u *default_vimruntime_dir = (char_u *)"$(VIMRUNTIMEDIR)"; >> pathdef.c
+ @echo char_u *all_cflags = (char_u *)"$(CC) $(CFLAGS)"; >> pathdef.c
+ @echo char_u *all_lflags = (char_u *)"$(CC) -s -o $(TARGET) $(LIB) -luuid -lole32 $(PYTHONLIB) $(RUBYLIB)"; >> pathdef.c
+ @echo char_u *compiled_user = (char_u *)"$(USERNAME)"; >> pathdef.c
+ @echo char_u *compiled_sys = (char_u *)"$(USERDOMAIN)"; >> pathdef.c
+endif
diff --git a/src/Make_mint.mak b/src/Make_mint.mak
new file mode 100644
index 000000000..6bcaacb84
--- /dev/null
+++ b/src/Make_mint.mak
@@ -0,0 +1,56 @@
+#
+# Makefile for Vim on MiNT vim:ts=8:sw=8:tw=78
+#
+# This is a wrapper around the Unix Makefile. It is configured to accompany
+# the MiNT distribution of Vim.
+#
+# See "Makefile" for instructions how to run "make".
+#
+# BUT: Always run: "make -f Make_mint.mak config",
+# and then: "make -f Make_mint.mak"!
+# Otherwise the postprocessing won't get done.
+#
+
+### This Makefile has been succesfully tested on these systems.
+### Check the (*) column for remarks, listed below.
+### Later code changes may cause small problems, otherwise Vim is supposed to
+### compile and run without problems.
+
+#system: configurations: version (*) tested by:
+#------------- ------------------------ ------- - ----------
+#MiNT 1.12.5 gcc gcc-2.6.1 3.29 Jens Felderhoff
+#MiNT 1.12.6 gcc gcc-2.6.1 -GUI 4.6b Jens Felderhoff
+#MiNT 1.12.6 gcc gcc-2.6.1 -GUI 4.6 Jens Felderhoff
+
+# set this to the pathname prefix of your symbol link editor, i.e. if it is
+# /usr/local/bin/sym-ld set:
+#
+SYMLDPREFIX = /usr/local/bin/sym-
+#SYMLDPREFIX = /gnu/bin/sym-
+
+POSTPROCESS = fixstk 20k $(VIMTARGET)
+DBGPOSTPROCESS = fixstk 20k $(DBGTARGET)
+DBGLDFLAGS = -B$(SYMLDPREFIX)
+DBGTARGET = $(VIMTARGET).sym
+
+
+# Default target is making the executable and then do the post processing
+all: $(VIMTARGET) $(TOOLS)
+ $(POSTPROCESS)
+
+debug: $(DBGTARGET)
+ $(DBGPOSTPROCESS)
+
+#################### include the Unix Makefile ###############
+
+include Makefile
+
+
+### (M) MiNT with gcc 2.6.1 and gdb 3.5
+CC = gcc -mint
+CFLAGS = -g -O -Iproto
+
+$(DBGTARGET): $(OBJ) version.c version.h
+ $(CC) -c $(ALL_CFLAGS) version.c
+ $(CC) $(LDFLAGS) $(DBGLDFLAGS) -o $(DBGTARGET) -g $(OBJ) \
+ version.o $(ALL_LIBS)
diff --git a/src/Make_morph.mak b/src/Make_morph.mak
new file mode 100644
index 000000000..f9ceb50c5
--- /dev/null
+++ b/src/Make_morph.mak
@@ -0,0 +1,88 @@
+#
+# Makefile for VIM, using MorphOS SDK (gcc 2.95.3)
+#
+
+# Uncomment the following two lines and comment the two after in
+# case you want to play with GVIM MorphOS. But it's still known
+# to not work at all. So meanwhile it's better to stick with VIM.
+
+# GVIM = -DFEAT_GUI_AMIGA
+# GVIMSRC = gui_amiga.c gui.c
+
+GVIM =
+GVIMSRC =
+
+CFLAGS = -c \
+ -pipe \
+ -O2 \
+ -Wall \
+ \
+ -DNO_ARP \
+ -DUSE_TMPNAM \
+ ${GVIM} \
+ \
+ -I proto \
+ \
+ -noixemul
+
+PRG = Vim
+LIBS = -noixemul -s
+CC = gcc
+LD = gcc
+OBJDUMP = objdump
+RM = rm
+
+.c.o:
+ ${CC} ${CFLAGS} $< -o $@
+
+SRC = buffer.c \
+ charset.c \
+ diff.c \
+ digraph.c \
+ edit.c \
+ eval.c \
+ ex_cmds.c \
+ ex_cmds2.c \
+ ex_docmd.c \
+ ex_eval.c \
+ ex_getln.c \
+ fileio.c \
+ fold.c \
+ getchar.c \
+ main.c \
+ mark.c \
+ mbyte.c \
+ memfile.c \
+ memline.c \
+ menu.c \
+ message.c \
+ misc1.c \
+ misc2.c \
+ move.c \
+ normal.c \
+ ops.c \
+ option.c \
+ os_amiga.c \
+ quickfix.c \
+ regexp.c \
+ screen.c \
+ search.c \
+ syntax.c \
+ tag.c \
+ term.c \
+ ui.c \
+ undo.c \
+ version.c \
+ window.c \
+ ${GVIMSRC}
+
+OBJ = $(SRC:.c=.o)
+
+$(PRG): $(OBJ)
+ ${LD} -o $(PRG) $(OBJ) $(LIBS)
+
+dump: $(PRG)
+ $(OBJDUMP) --reloc --disassemble-all $(PRG) > $(PRG).s
+
+clean:
+ $(RM) -fv $(OBJ) $(PRG) $(PRG).s
diff --git a/src/Make_mpw.mak b/src/Make_mpw.mak
new file mode 100644
index 000000000..8a98d68a0
--- /dev/null
+++ b/src/Make_mpw.mak
@@ -0,0 +1,3843 @@
+# File: VIm.make
+# Target: VIm
+# Created: Sunday, December 29, 2000 09:55:14 PM
+
+
+MAKEFILE = VIm.make
+¥MondoBuild¥ = {MAKEFILE} # Make blank to avoid rebuilds when makefile is modified
+
+ObjDir = :obj:
+Includes = ¶
+ -i :src:proto:
+CFlags = -w 2,35 -enum int
+Sym-PPC = -sym off
+
+PPCCOptions = {Includes} {CFlags} {Sym-PPC}
+
+
+### Source Files ###
+
+SrcFiles = ¶
+ :src:buffer.c ¶
+ :src:charset.c ¶
+ :src:diff.c ¶
+ :src:digraph.c ¶
+ :src:edit.c ¶
+ :src:eval.c ¶
+ :src:ex_cmds.c ¶
+ :src:ex_cmds2.c ¶
+ :src:ex_docmd.c ¶
+ :src:ex_eval.c ¶
+ :src:ex_getln.c ¶
+ :src:fileio.c ¶
+ :src:fold.c ¶
+ :src:getchar.c ¶
+ :src:gui.c ¶
+ :src:gui_mac.c ¶
+ :src:if_cscope.c ¶
+ :src:main.c ¶
+ :src:mark.c ¶
+ :src:memfile.c ¶
+ :src:memline.c ¶
+ :src:menu.c ¶
+ :src:message.c ¶
+ :src:misc1.c ¶
+ :src:misc2.c ¶
+ :src:move.c ¶
+ :src:multibyte.c ¶
+ :src:normal.c ¶
+ :src:ops.c ¶
+ :src:option.c ¶
+ :src:os_mac.c ¶
+ :src:pty.c ¶
+ :src:quickfix.c ¶
+ :src:regexp.c ¶
+ :src:screen.c ¶
+ :src:search.c ¶
+ :src:syntax.c ¶
+ :src:tag.c ¶
+ :src:term.c ¶
+ :src:termlib.c ¶
+ :src:ui.c ¶
+ :src:undo.c ¶
+ :src:version.c ¶
+ :src:window.c ¶
+ :src:wsdebug.c
+
+
+### Object Files ###
+
+ObjFiles-PPC = ¶
+ "{ObjDir}buffer.c.x" ¶
+ "{ObjDir}charset.c.x" ¶
+ "{ObjDir}diff.c.x" ¶
+ "{ObjDir}digraph.c.x" ¶
+ "{ObjDir}edit.c.x" ¶
+ "{ObjDir}eval.c.x" ¶
+ "{ObjDir}ex_cmds.c.x" ¶
+ "{ObjDir}ex_cmds2.c.x" ¶
+ "{ObjDir}ex_docmd.c.x" ¶
+ "{ObjDir}ex_eval.c.x" ¶
+ "{ObjDir}ex_getln.c.x" ¶
+ "{ObjDir}fileio.c.x" ¶
+ "{ObjDir}fold.c.x" ¶
+ "{ObjDir}getchar.c.x" ¶
+ "{ObjDir}gui.c.x" ¶
+ "{ObjDir}gui_mac.c.x" ¶
+ "{ObjDir}if_cscope.c.x" ¶
+ "{ObjDir}main.c.x" ¶
+ "{ObjDir}mark.c.x" ¶
+ "{ObjDir}memfile.c.x" ¶
+ "{ObjDir}memline.c.x" ¶
+ "{ObjDir}menu.c.x" ¶
+ "{ObjDir}message.c.x" ¶
+ "{ObjDir}misc1.c.x" ¶
+ "{ObjDir}misc2.c.x" ¶
+ "{ObjDir}move.c.x" ¶
+ "{ObjDir}multibyte.c.x" ¶
+ "{ObjDir}normal.c.x" ¶
+ "{ObjDir}ops.c.x" ¶
+ "{ObjDir}option.c.x" ¶
+ "{ObjDir}os_mac.c.x" ¶
+ "{ObjDir}pty.c.x" ¶
+ "{ObjDir}quickfix.c.x" ¶
+ "{ObjDir}regexp.c.x" ¶
+ "{ObjDir}screen.c.x" ¶
+ "{ObjDir}search.c.x" ¶
+ "{ObjDir}syntax.c.x" ¶
+ "{ObjDir}tag.c.x" ¶
+ "{ObjDir}term.c.x" ¶
+ "{ObjDir}termlib.c.x" ¶
+ "{ObjDir}ui.c.x" ¶
+ "{ObjDir}undo.c.x" ¶
+ "{ObjDir}version.c.x" ¶
+ "{ObjDir}window.c.x" ¶
+ "{ObjDir}wsdebug.c.x"
+
+
+### Libraries ###
+
+LibFiles-PPC = ¶
+ "{SharedLibraries}InterfaceLib" ¶
+ "{SharedLibraries}MathLib" ¶
+ "{SharedLibraries}StdCLib" ¶
+ "{PPCLibraries}StdCRuntime.o" ¶
+ "{PPCLibraries}PPCStdCLib.o" ¶
+ "{PPCLibraries}PPCCRuntime.o" ¶
+ "{PPCLibraries}PPCToolLibs.o"
+
+
+### Default Rules ###
+
+.c.x Ä .c {¥MondoBuild¥}
+ {PPCC} {depDir}{default}.c -o {targDir}{default}.c.x {PPCCOptions}
+
+
+### Build Rules ###
+
+VIm ÄÄ {ObjFiles-PPC} {LibFiles-PPC} {¥MondoBuild¥}
+ PPCLink ¶
+ -o {Targ} ¶
+ {ObjFiles-PPC} ¶
+ {LibFiles-PPC} ¶
+ {Sym-PPC} ¶
+ -mf -d ¶
+ -t 'APPL' ¶
+ -c 'VIM!'
+
+
+
+### Required Dependencies ###
+
+"{ObjDir}buffer.c.x" Ä :src:buffer.c
+"{ObjDir}charset.c.x" Ä :src:charset.c
+"{ObjDir}diff.c.x" Ä :src:diff.c
+"{ObjDir}digraph.c.x" Ä :src:digraph.c
+"{ObjDir}edit.c.x" Ä :src:edit.c
+"{ObjDir}eval.c.x" Ä :src:eval.c
+"{ObjDir}ex_cmds.c.x" Ä :src:ex_cmds.c
+"{ObjDir}ex_cmds2.c.x" Ä :src:ex_cmds2.c
+"{ObjDir}ex_docmd.c.x" Ä :src:ex_docmd.c
+"{ObjDir}ex_eval.c.x" Ä :src:ex_eval.c
+"{ObjDir}ex_getln.c.x" Ä :src:ex_getln.c
+"{ObjDir}fileio.c.x" Ä :src:fileio.c
+"{ObjDir}fold.c.x" Ä :src:fold.c
+"{ObjDir}getchar.c.x" Ä :src:getchar.c
+"{ObjDir}gui.c.x" Ä :src:gui.c
+"{ObjDir}gui_mac.c.x" Ä :src:gui_mac.c
+"{ObjDir}if_cscope.c.x" Ä :src:if_cscope.c
+"{ObjDir}main.c.x" Ä :src:main.c
+"{ObjDir}mark.c.x" Ä :src:mark.c
+"{ObjDir}memfile.c.x" Ä :src:memfile.c
+"{ObjDir}memline.c.x" Ä :src:memline.c
+"{ObjDir}menu.c.x" Ä :src:menu.c
+"{ObjDir}message.c.x" Ä :src:message.c
+"{ObjDir}misc1.c.x" Ä :src:misc1.c
+"{ObjDir}misc2.c.x" Ä :src:misc2.c
+"{ObjDir}move.c.x" Ä :src:move.c
+"{ObjDir}multibyte.c.x" Ä :src:multibyte.c
+"{ObjDir}normal.c.x" Ä :src:normal.c
+"{ObjDir}ops.c.x" Ä :src:ops.c
+"{ObjDir}option.c.x" Ä :src:option.c
+"{ObjDir}os_mac.c.x" Ä :src:os_mac.c
+"{ObjDir}pty.c.x" Ä :src:pty.c
+"{ObjDir}quickfix.c.x" Ä :src:quickfix.c
+"{ObjDir}regexp.c.x" Ä :src:regexp.c
+"{ObjDir}screen.c.x" Ä :src:screen.c
+"{ObjDir}search.c.x" Ä :src:search.c
+"{ObjDir}syntax.c.x" Ä :src:syntax.c
+"{ObjDir}tag.c.x" Ä :src:tag.c
+"{ObjDir}term.c.x" Ä :src:term.c
+"{ObjDir}termlib.c.x" Ä :src:termlib.c
+"{ObjDir}ui.c.x" Ä :src:ui.c
+"{ObjDir}undo.c.x" Ä :src:undo.c
+"{ObjDir}version.c.x" Ä :src:version.c
+"{ObjDir}window.c.x" Ä :src:window.c
+"{ObjDir}wsdebug.c.x" Ä :src:wsdebug.c
+
+
+### Optional Dependencies ###
+### Build this target to generate "include file" dependencies. ###
+
+Dependencies Ä $OutOfDate
+ MakeDepend ¶
+ -append {MAKEFILE} ¶
+ -ignore "{CIncludes}" ¶
+ -objdir "{ObjDir}" ¶
+ -objext .x ¶
+ {Includes} ¶
+ {SrcFiles}
+
+
+#*** Dependencies: Cut here ***
+# These dependencies were produced at 12:17:02 Uhr on Fre, 29. Dez 2000 by MakeDepend
+
+:obj:buffer.c.x Ä ¶
+ :src:buffer.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:charset.c.x Ä ¶
+ :src:charset.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:diff.c.x Ä ¶
+ :src:diff.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:digraph.c.x Ä ¶
+ :src:digraph.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:edit.c.x Ä ¶
+ :src:edit.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:eval.c.x Ä ¶
+ :src:eval.c ¶
+ :src:vim.h ¶
+ :src:version.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:ex_cmds.c.x Ä ¶
+ :src:ex_cmds.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:ex_cmds2.c.x Ä ¶
+ :src:ex_cmds2.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:ex_docmd.c.x Ä ¶
+ :src:ex_docmd.c ¶
+ :src:vim.h ¶
+ :src:ex_cmds.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:ex_eval.c.x Ä ¶
+ :src:ex_eval.c ¶
+ :src:vim.h ¶
+ :src:ex_cmds.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:ex_getln.c.x Ä ¶
+ :src:ex_getln.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:fileio.c.x Ä ¶
+ :src:fileio.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:fold.c.x Ä ¶
+ :src:fold.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:getchar.c.x Ä ¶
+ :src:getchar.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:gui.c.x Ä ¶
+ :src:gui.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:gui_mac.c.x Ä ¶
+ :src:gui_mac.c ¶
+ :src:vim.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:farsi.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:src:gui_mac.r Ä ¶
+ :src:gui_mac.r ¶
+ "{RIncludes}"SysTypes.r ¶
+ "{RIncludes}"Types.r ¶
+ :src:version.h ¶
+ "{RIncludes}"Fonts.r ¶
+ "{RIncludes}"IntlResources.r ¶
+ "{RIncludes}"Sound.r ¶
+ "{RIncludes}"ConditionalMacros.r ¶
+ "{RIncludes}"MacTypes.r ¶
+ "{RIncludes}"Controls.r ¶
+ "{RIncludes}"ControlDefinitions.r ¶
+ "{RIncludes}"MacWindows.r ¶
+ "{RIncludes}"Dialogs.r ¶
+ "{RIncludes}"Menus.r ¶
+ "{RIncludes}"Icons.r ¶
+ "{RIncludes}"Finder.r ¶
+ "{RIncludes}"Quickdraw.r ¶
+ "{RIncludes}"Processes.r ¶
+ "{RIncludes}"AppleEvents.r ¶
+ "{RIncludes}"Script.r ¶
+ "{RIncludes}"Collections.r ¶
+ "{RIncludes}"PictUtils.r ¶
+ "{RIncludes}"AEDataModel.r
+
+:obj:if_cscope.c.x Ä ¶
+ :src:if_cscope.c ¶
+ :src:vim.h ¶
+ :src:if_cscope.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:main.c.x Ä ¶
+ :src:main.c ¶
+ :src:vim.h ¶
+ :src:farsi.c ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:mark.c.x Ä ¶
+ :src:mark.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:memfile.c.x Ä ¶
+ :src:memfile.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:memline.c.x Ä ¶
+ :src:memline.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:menu.c.x Ä ¶
+ :src:menu.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:message.c.x Ä ¶
+ :src:message.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:misc1.c.x Ä ¶
+ :src:misc1.c ¶
+ :src:vim.h ¶
+ :src:version.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:misc2.c.x Ä ¶
+ :src:misc2.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:move.c.x Ä ¶
+ :src:move.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:multibyte.c.x Ä ¶
+ :src:multibyte.c ¶
+ :src:vim.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:farsi.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:normal.c.x Ä ¶
+ :src:normal.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:ops.c.x Ä ¶
+ :src:ops.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:option.c.x Ä ¶
+ :src:option.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:os_mac.c.x Ä ¶
+ :src:os_mac.c ¶
+ :src:vim.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:farsi.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:pty.c.x Ä ¶
+ :src:pty.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:quickfix.c.x Ä ¶
+ :src:quickfix.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:regexp.c.x Ä ¶
+ :src:regexp.c ¶
+ :src:vim.h ¶
+ :src:option.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:screen.c.x Ä ¶
+ :src:screen.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:search.c.x Ä ¶
+ :src:search.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:syntax.c.x Ä ¶
+ :src:syntax.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:tag.c.x Ä ¶
+ :src:tag.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:term.c.x Ä ¶
+ :src:term.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:termlib.c.x Ä ¶
+ :src:termlib.c ¶
+ :src:vim.h ¶
+ :src:proto:termlib.pro ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:ui.c.x Ä ¶
+ :src:ui.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:undo.c.x Ä ¶
+ :src:undo.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:version.c.x Ä ¶
+ :src:version.c ¶
+ :src:vim.h ¶
+ :src:version.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:window.c.x Ä ¶
+ :src:window.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
+
+:obj:wsdebug.c.x Ä ¶
+ :src:wsdebug.c ¶
+ :src:vim.h ¶
+ :src:auto:config.h ¶
+ :src:feature.h ¶
+ :src:os_unix.h ¶
+ :src:os_mac.h ¶
+ :src:workshop.h ¶
+ :src:ascii.h ¶
+ :src:keymap.h ¶
+ :src:term.h ¶
+ :src:macros.h ¶
+ :src:structs.h ¶
+ :src:globals.h ¶
+ :src:option.h ¶
+ :src:ex_cmds.h ¶
+ :src:proto.h ¶
+ :src:integration.h ¶
+ :src:wsdebug.h ¶
+ :src:regexp.h ¶
+ :src:gui.h ¶
+ :src:farsi.h ¶
+ :src:proto:os_unix.pro ¶
+ :src:proto:os_mac.pro ¶
+ :src:proto:buffer.pro ¶
+ :src:proto:charset.pro ¶
+ :src:proto:if_cscope.pro ¶
+ :src:proto:diff.pro ¶
+ :src:proto:digraph.pro ¶
+ :src:proto:edit.pro ¶
+ :src:proto:eval.pro ¶
+ :src:proto:ex_cmds.pro ¶
+ :src:proto:ex_cmds2.pro ¶
+ :src:proto:ex_docmd.pro ¶
+ :src:proto:ex_eval.pro ¶
+ :src:proto:ex_getln.pro ¶
+ :src:proto:fileio.pro ¶
+ :src:proto:fold.pro ¶
+ :src:proto:getchar.pro ¶
+ :src:proto:hangulin.pro ¶
+ :src:proto:main.pro ¶
+ :src:proto:mark.pro ¶
+ :src:proto:memfile.pro ¶
+ :src:proto:memline.pro ¶
+ :src:proto:menu.pro ¶
+ :src:proto:message.pro ¶
+ :src:proto:misc1.pro ¶
+ :src:proto:misc2.pro ¶
+ :src:proto:move.pro ¶
+ :src:proto:multibyte.pro ¶
+ :src:proto:normal.pro ¶
+ :src:proto:ops.pro ¶
+ :src:proto:option.pro ¶
+ :src:proto:quickfix.pro ¶
+ :src:proto:regexp.pro ¶
+ :src:proto:screen.pro ¶
+ :src:proto:search.pro ¶
+ :src:proto:syntax.pro ¶
+ :src:proto:tag.pro ¶
+ :src:proto:term.pro ¶
+ :src:proto:termlib.pro ¶
+ :src:proto:ui.pro ¶
+ :src:proto:undo.pro ¶
+ :src:proto:version.pro ¶
+ :src:proto:window.pro ¶
+ :src:proto:if_python.pro ¶
+ :src:proto:if_tcl.pro ¶
+ :src:proto:if_ruby.pro ¶
+ :src:proto:gui.pro ¶
+ :src:proto:pty.pro ¶
+ :src:proto:gui_gtk.pro ¶
+ :src:proto:gui_gtk_x11.pro ¶
+ :src:proto:gui_motif.pro ¶
+ :src:proto:gui_athena.pro ¶
+ :src:proto:gui_mac.pro ¶
+ :src:proto:gui_x11.pro ¶
+ :src:proto:workshop.pro ¶
+ :src:proto:if_perl.pro ¶
+ :src:proto:if_perlsfio.pro
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak
new file mode 100644
index 000000000..8ee77b63c
--- /dev/null
+++ b/src/Make_mvc.mak
@@ -0,0 +1,888 @@
+# Makefile for Vim on Win32 (Windows NT and Windows 95), using the
+# Microsoft Visual C++ 2.x and MSVC 4.x compilers (or newer).
+# It builds on Windows 95 and all four NT platforms: i386, Alpha, MIPS, and
+# PowerPC. The NT/i386 binary and the Windows 95 binary are identical.
+#
+# This makefile can build the console, GUI, OLE-enable, Perl-enabled and
+# Python-enabled versions of vim for Win32 platforms.
+#
+# When compiling different versions, do "nmake clean" first!
+#
+# The basic command line to build vim is:
+# nmake -f Make_mvc.mak
+# This will build the console version of vim with no additional interfaces.
+# To add interfaces, define any of the following:
+# GUI interface: GUI=yes (default is no)
+# OLE interface: OLE=yes (usually with GUI=yes)
+# Multibyte support: MBYTE=yes
+# IME support: IME=yes (requires GUI=yes)
+# DYNAMIC_IME=[yes or no] (to load the imm32.dll dynamically, default
+# is yes)
+# Global IME support: GIME=yes (requires GUI=yes)
+# Perl interface:
+# PERL=[Path to Perl directory]
+# DYNAMIC_PERL=yes (to load the Perl DLL dynamically)
+# PERL_VER=[Perl version, in the form 55 (5.005), 56 (5.6.x), etc] (default is 56)
+# Python interface:
+# PYTHON=[Path to Python directory]
+# DYNAMIC_PYTHON=yes (to load the Python DLL dynamically)
+# PYTHON_VER=[Python version, eg 15, 20] (default is 22)
+# Ruby interface:
+# RUBY=[Path to Ruby directory]
+# DYNAMIC_RUBY=yes (to load the Ruby DLL dynamically)
+# RUBY_VER=[Ruby version, eg 16, 17] (default is 18)
+# RUBY_VER_LONG=[Ruby version, eg 1.6, 1.7] (default is 1.8)
+# You must set RUBY_VER_LONG when change RUBY_VER.
+# Tcl interface:
+# TCL=[Path to Tcl directory]
+# DYNAMIC_TCL=yes (to load the Tcl DLL dynamically)
+# TCL_VER=[Tcl version, e.g. 80, 83] (default is 83)
+# TCL_VER_LONG=[Tcl version, eg 8.3] (default is 8.3)
+# You must set TCL_VER_LONG when you set TCL_VER.
+# Debug version: DEBUG=yes
+# Mapfile: MAP=[no, yes or lines] (default is yes)
+# no: Don't write a mapfile.
+# yes: Write a normal mapfile.
+# lines: Write a mapfile with line numbers (only for VC6 and later)
+# SNiFF+ interface: SNIFF=yes
+# Cscope support: CSCOPE=yes
+# Iconv library support (always dynamically loaded):
+# ICONV=[yes or no] (default is yes)
+# Intl library support (always dynamically loaded):
+# GETTEXT=[yes or no] (default is yes)
+# See http://sourceforge.net/projects/gettext/
+# PostScript printing: POSTSCRIPT=yes (default is no)
+# Feature Set: FEATURES=[TINY, SMALL, NORMAL, BIG, or HUGE] (default is BIG)
+# Version Support: WINVER=[0x0400, 0x0500] (default is 0x0400)
+# Processor Version: CPUNR=[i386, i486, i586, i686] (default is i386)
+# Optimization: OPTIMIZE=[SPACE, SPEED, MAXSPEED] (default is MAXSPEED)
+# Netbeans Support: NETBEANS=[yes or no] (default is yes if GUI is yes)
+# XPM Image Support: XPM=[path to XPM directory]
+#
+# You can combine any of these interfaces
+#
+# Example: To build the non-debug, GUI version with Perl interface:
+# nmake -f Make_mvc.mak GUI=yes PERL=C:\Perl
+#
+# To build using Borland C++, use Make_bc3.mak or Make_bc5.mak.
+#
+# DEBUG with Make_mvc.mak and Make_dvc.mak:
+# This makefile gives a fineness of control which is not supported in
+# Visual C++ configuration files. Therefore, debugging requires a bit of
+# extra work.
+# Make_dvc.mak is a Visual C++ project to access that support.
+# To use Make_dvc.mak:
+# 1) Build Vim with Make_mvc.mak.
+# Use a "DEBUG=yes" argument to build Vim with debug support.
+# E.g. the following builds gvimd.exe:
+# nmake -f Make_mvc.mak debug=yes gui=yes
+# 2) Use MS Devstudio and set it up to allow that file to be debugged:
+# i) Pass Make_dvc.mak to the IDE.
+# Use the "open workspace" menu entry to load Make_dvc.mak.
+# Alternatively, from the command line:
+# msdev /nologo Make_dvc.mak
+# Note: Make_dvc.mak is in VC4.0 format. Later VC versions see
+# this and offer to convert it to their own format. Accept that.
+# It creates a file called Make_dvc.dsw which can then be used
+# for further operations. E.g.
+# msdev /nologo Make_dvc.dsw
+# ii) Set the built executable for debugging:
+# a) Alt+F7/Debug takes you to the Debug dialog.
+# b) Fill "Executable for debug session". e.g. gvimd.exe
+# c) Fill "Program arguments". e.g. -R dosinst.c
+# d) Complete the dialog
+# 3) You can now debug the executable you built with Make_mvc.mak
+#
+# Note: Make_dvc.mak builds vimrun.exe, because it must build something
+# to be a valid makefile..
+
+### See feature.h for a list of optionals.
+# If you want to build some optional features without modifying the source,
+# you can set DEFINES on the command line, e.g.,
+# nmake -f makefile.mvc "DEFINES=-DEMACS_TAGS"
+
+# Build on both Windows NT and Windows 95
+
+TARGETOS = BOTH
+
+# Select one of eight object code directories, depends on GUI, OLE and DEBUG.
+# If you change something else, do "make clean" first!
+!if "$(GUI)" == "yes"
+OBJDIR = .\ObjG
+!else
+OBJDIR = .\ObjC
+!endif
+!if "$(OLE)" == "yes"
+OBJDIR = $(OBJDIR)O
+!endif
+!if "$(DEBUG)" == "yes"
+OBJDIR = $(OBJDIR)d
+!endif
+
+# ntwin32.mak requires that CPU be set appropriately
+
+!ifdef PROCESSOR_ARCHITECTURE
+# We're on Windows NT or using VC 6
+CPU = $(PROCESSOR_ARCHITECTURE)
+! if "$(CPU)" == "x86"
+CPU = i386
+! endif
+!else # !PROCESSOR_ARCHITECTURE
+# We're on Windows 95
+CPU = i386
+!endif # !PROCESSOR_ARCHITECTURE
+
+
+# Build a retail version by default
+
+!if "$(DEBUG)" != "yes"
+NODEBUG = 1
+!else
+MAKEFLAGS_GVIMEXT = DEBUG=yes
+!endif
+
+
+# Build a multithreaded version for the Windows 95 dead keys hack
+# Commented out because it doesn't work.
+# MULTITHREADED = 1
+
+
+# Get all sorts of useful, standard macros from the SDK. (Note that
+# MSVC 2.2 does not install <ntwin32.mak> in the \msvc20\include
+# directory, but you can find it in \msvc20\include on the CD-ROM.
+# You may also need <win32.mak> from the same place.)
+
+!include <ntwin32.mak>
+
+
+#>>>>> path of the compiler and linker; name of include and lib directories
+# PATH = c:\msvc20\bin;$(PATH)
+# INCLUDE = c:\msvc20\include
+# LIB = c:\msvc20\lib
+
+!ifndef CTAGS
+CTAGS = ctags
+!endif
+
+!if "$(SNIFF)" == "yes"
+# SNIFF - Include support for SNiFF+.
+SNIFF_INCL = if_sniff.h
+SNIFF_OBJ = $(OBJDIR)/if_sniff.obj
+SNIFF_LIB = shell32.lib
+SNIFF_DEFS = -DFEAT_SNIFF
+# The SNiFF integration needs multithreaded libraries!
+MULTITHREADED = yes
+!endif
+
+!ifndef CSCOPE
+CSCOPE = yes
+!endif
+
+!if "$(CSCOPE)" == "yes"
+# CSCOPE - Include support for Cscope
+CSCOPE_INCL = if_cscope.h
+CSCOPE_OBJ = $(OBJDIR)/if_cscope.obj
+CSCOPE_DEFS = -DFEAT_CSCOPE
+!endif
+
+!ifndef NETBEANS
+NETBEANS = $(GUI)
+!endif
+
+!if "$(NETBEANS)" == "yes"
+# NETBEANS - Include support for Netbeans integration
+NETBEANS_PRO = proto/netbeans.pro
+NETBEANS_OBJ = $(OBJDIR)/netbeans.obj $(OBJDIR)/gui_beval.obj
+NETBEANS_DEFS = -DFEAT_NETBEANS_INTG
+!if "$(DEBUG)" == "yes"
+NBDEBUG_DEFS = -DNBDEBUG
+NBDEBUG_INCL = nbdebug.h
+NBDEBUG_SRC = nbdebug.c
+!endif
+NETBEANS_LIB = WSock32.lib
+!endif
+
+!ifdef XPM
+# XPM - Include support for XPM signs
+# you can get xpm.lib from http://iamphet.nm.ru/xpm or create it yourself
+XPM_OBJ = $(OBJDIR)/xpm_w32.obj
+XPM_DEFS = -DFEAT_XPM_W32
+XPM_LIB = $(XPM)\lib\libXpm.lib
+XPM_INC = -I $(XPM)\include
+!endif
+
+!if defined(USE_MSVCRT)
+CVARS = $(cvarsdll)
+!elseif defined(MULTITHREADED)
+CVARS = $(cvarsmt)
+!else
+CVARS = $(cvars)
+!endif
+
+# need advapi32.lib for GetUserName()
+# need shell32.lib for ExtractIcon()
+# gdi32.lib and comdlg32.lib for printing support
+# ole32.lib and uuid.lib are needed for FEAT_SHORTCUT
+CON_LIB = advapi32.lib shell32.lib gdi32.lib comdlg32.lib ole32.lib uuid.lib
+!if "$(VC6)" == "yes"
+CON_LIB = $(CON_LIB) /DELAYLOAD:comdlg32.dll /DELAYLOAD:ole32.dll DelayImp.lib
+!endif
+
+### Set the default $(WINVER) to make it work with VC++7.0 (VS.NET)
+# When set to 0x0500 ":browse" stops working.
+!ifndef WINVER
+WINVER = 0x0400
+!endif
+
+# If you have a fixed directory for $VIM or $VIMRUNTIME, other than the normal
+# default, use these lines.
+#VIMRCLOC = somewhere
+#VIMRUNTIMEDIR = somewhere
+
+CFLAGS = -c /W3 /nologo $(CVARS) -I. -Iproto -DHAVE_PATHDEF -DWIN32 \
+ $(SNIFF_DEFS) $(CSCOPE_DEFS) $(NETBEANS_DEFS) \
+ $(NBDEBUG_DEFS) $(XPM_DEFS) \
+ $(DEFINES) -DWINVER=$(WINVER) -D_WIN32_WINNT=$(WINVER)
+
+#>>>>> end of choices
+###########################################################################
+
+!ifdef OS
+OS_TYPE = winnt
+DEL_TREE = rmdir /s /q
+!else
+OS_TYPE = win95
+DEL_TREE = deltree /y
+!endif
+
+INTDIR=$(OBJDIR)
+OUTDIR=$(OBJDIR)
+
+# Convert processor ID to MVC-compatible number
+!if "$(CPUNR)" == "i386"
+CPUARG = /G3
+!elseif "$(CPUNR)" == "i486"
+CPUARG = /G4
+!elseif "$(CPUNR)" == "i586"
+CPUARG = /G5
+!elseif "$(CPUNR)" == "i686"
+CPUARG = /G6
+!else
+CPUARG =
+!endif
+
+!ifdef NODEBUG
+VIM = vim
+!if "$(OPTIMIZE)" == "SPACE"
+OPTFLAG = /O1
+!elseif "$(OPTIMIZE)" == "SPEED"
+OPTFLAG = /O2
+!else # MAXSPEED
+OPTFLAG = /Ox
+!endif
+CFLAGS = $(CFLAGS) $(OPTFLAG) -DNDEBUG /Zi $(CPUARG)
+RCFLAGS = $(rcflags) $(rcvars) -DNDEBUG
+PDB = /Fd$(OUTDIR)/
+LINK_PDB = /PDB:$(OUTDIR)/
+! ifdef USE_MSVCRT
+CFLAGS = $(CFLAGS) -MD
+LIBC = msvcrt.lib
+! elseif defined(MULTITHREADED)
+LIBC = libcmt.lib
+! else
+LIBC = libc.lib
+! endif
+!else # DEBUG
+VIM = vimd
+# MSVC 4.1
+PDB = /Fd$(OUTDIR)/
+LINK_PDB = /PDB:$(OUTDIR)/
+# MSVC 2.2
+# PDB = /Fd$(OUTDIR)/vim.pdb
+# LINK_PDB = /PDB:$(OUTDIR)/vim.pdb
+CFLAGS = $(CFLAGS) -D_DEBUG -DDEBUG /Zi /Od
+RCFLAGS = $(rcflags) $(rcvars) -D_DEBUG -DDEBUG
+# The /fixed:no is needed for Quantify. Assume not 4.? as unsupported in VC4.0.
+! if "$(_NMAKE_VER)" == ""
+LIBC =
+! else
+LIBC = /fixed:no
+! endif
+
+! ifndef USE_MSVCRT
+LIBC = $(LIBC) libcd.lib
+! else
+CFLAGS = $(CFLAGS) -MDd
+LIBC = $(LIBC) msvcrtd.lib
+! endif
+!endif # DEBUG
+
+INCL = vim.h os_win32.h ascii.h feature.h globals.h keymap.h macros.h \
+ proto.h option.h structs.h term.h $(SNIFF_INCL) $(CSCOPE_INCL) \
+ $(NBDEBUG_INCL)
+
+OBJ = \
+ $(OUTDIR)\buffer.obj \
+ $(OUTDIR)\charset.obj \
+ $(OUTDIR)\diff.obj \
+ $(OUTDIR)\digraph.obj \
+ $(OUTDIR)\edit.obj \
+ $(OUTDIR)\eval.obj \
+ $(OUTDIR)\ex_cmds.obj \
+ $(OUTDIR)\ex_cmds2.obj \
+ $(OUTDIR)\ex_docmd.obj \
+ $(OUTDIR)\ex_eval.obj \
+ $(OUTDIR)\ex_getln.obj \
+ $(OUTDIR)\fileio.obj \
+ $(OUTDIR)\fold.obj \
+ $(OUTDIR)\getchar.obj \
+ $(OUTDIR)\main.obj \
+ $(OUTDIR)\mark.obj \
+ $(OUTDIR)\mbyte.obj \
+ $(OUTDIR)\memfile.obj \
+ $(OUTDIR)\memline.obj \
+ $(OUTDIR)\menu.obj \
+ $(OUTDIR)\message.obj \
+ $(OUTDIR)\misc1.obj \
+ $(OUTDIR)\misc2.obj \
+ $(OUTDIR)\move.obj \
+ $(OUTDIR)\normal.obj \
+ $(OUTDIR)\ops.obj \
+ $(OUTDIR)\option.obj \
+ $(OUTDIR)\os_mswin.obj \
+ $(OUTDIR)\os_win32.obj \
+ $(OUTDIR)\pathdef.obj \
+ $(OUTDIR)\quickfix.obj \
+ $(OUTDIR)\regexp.obj \
+ $(OUTDIR)\screen.obj \
+ $(OUTDIR)\search.obj \
+ $(OUTDIR)\syntax.obj \
+ $(OUTDIR)\tag.obj \
+ $(OUTDIR)\term.obj \
+ $(OUTDIR)\ui.obj \
+ $(OUTDIR)\undo.obj \
+ $(OUTDIR)\window.obj \
+ $(OUTDIR)\vim.res
+
+!if "$(OLE)" == "yes"
+CFLAGS = $(CFLAGS) -DFEAT_OLE
+RCFLAGS = $(RCFLAGS) -DFEAT_OLE
+OLE_OBJ = $(OUTDIR)\if_ole.obj
+OLE_IDL = if_ole.idl
+OLE_LIB = oleaut32.lib
+!endif
+
+!if "$(IME)" == "yes"
+CFLAGS = $(CFLAGS) -DFEAT_MBYTE_IME
+!ifndef DYNAMIC_IME
+DYNAMIC_IME = yes
+!endif
+!if "$(DYNAMIC_IME)" == "yes"
+CFLAGS = $(CFLAGS) -DDYNAMIC_IME
+!else
+IME_LIB = imm32.lib
+!endif
+!endif
+
+!if "$(GIME)" == "yes"
+CFLAGS = $(CFLAGS) -DGLOBAL_IME
+OBJ = $(OBJ) $(OUTDIR)\dimm_i.obj $(OUTDIR)\glbl_ime.obj
+MBYTE = yes
+!endif
+
+!if "$(MBYTE)" == "yes"
+CFLAGS = $(CFLAGS) -DFEAT_MBYTE
+!endif
+
+!if "$(GUI)" == "yes"
+SUBSYSTEM = windows
+CFLAGS = $(CFLAGS) -DFEAT_GUI_W32
+RCFLAGS = $(RCFLAGS) -DFEAT_GUI_W32
+VIM = g$(VIM)
+GUI_INCL = \
+ gui.h \
+ regexp.h \
+ ascii.h \
+ ex_cmds.h \
+ farsi.h \
+ feature.h \
+ globals.h \
+ keymap.h \
+ macros.h \
+ option.h \
+ os_dos.h \
+ os_win32.h
+GUI_OBJ = \
+ $(OUTDIR)\gui.obj \
+ $(OUTDIR)\gui_w32.obj \
+ $(OUTDIR)\os_w32exe.obj
+GUI_LIB = \
+ oldnames.lib kernel32.lib gdi32.lib $(IME_LIB) \
+ winspool.lib comctl32.lib advapi32.lib shell32.lib \
+ /machine:$(CPU) /nodefaultlib
+!else
+SUBSYSTEM = console
+!endif
+
+# iconv.dll library (dynamically loaded)
+!ifndef ICONV
+ICONV = yes
+!endif
+!if "$(ICONV)" == "yes"
+CFLAGS = $(CFLAGS) -DDYNAMIC_ICONV
+!endif
+
+# libintl.dll library
+!ifndef GETTEXT
+GETTEXT = yes
+!endif
+!if "$(GETTEXT)" == "yes"
+CFLAGS = $(CFLAGS) -DDYNAMIC_GETTEXT
+!endif
+
+# TCL interface
+!ifdef TCL
+!ifndef TCL_VER
+TCL_VER = 83
+TCL_VER_LONG = 8.3
+!endif
+!message Tcl requested (version $(TCL_VER)) - root dir is "$(TCL)"
+!if "$(DYNAMIC_TCL)" == "yes"
+!message Tcl DLL will be loaded dynamically
+TCL_DLL = tcl$(TCL_VER).dll
+CFLAGS = $(CFLAGS) -DFEAT_TCL -DDYNAMIC_TCL -DDYNAMIC_TCL_DLL=\"$(TCL_DLL)\" -DDYNAMIC_TCL_VER=\"$(TCL_VER_LONG)\"
+TCL_OBJ = $(OUTDIR)\if_tcl.obj
+TCL_INC = /I "$(TCL)\Include" /I "$(TCL)"
+TCL_LIB = $(TCL)\lib\tclstub$(TCL_VER).lib
+!else
+CFLAGS = $(CFLAGS) -DFEAT_TCL
+TCL_OBJ = $(OUTDIR)\if_tcl.obj
+TCL_INC = /I "$(TCL)\Include" /I "$(TCL)"
+TCL_LIB = $(TCL)\lib\tcl$(TCL_VER)vc.lib
+!endif
+!endif
+
+# PYTHON interface
+!ifdef PYTHON
+!ifndef PYTHON_VER
+PYTHON_VER = 22
+!endif
+!message Python requested (version $(PYTHON_VER)) - root dir is "$(PYTHON)"
+!if "$(DYNAMIC_PYTHON)" == "yes"
+!message Python DLL will be loaded dynamically
+!endif
+CFLAGS = $(CFLAGS) -DFEAT_PYTHON
+PYTHON_OBJ = $(OUTDIR)\if_python.obj
+PYTHON_INC = /I "$(PYTHON)\Include" /I "$(PYTHON)\PC"
+!if "$(DYNAMIC_PYTHON)" == "yes"
+CFLAGS = $(CFLAGS) -DDYNAMIC_PYTHON -DDYNAMIC_PYTHON_DLL=\"python$(PYTHON_VER).dll\"
+PYTHON_LIB = /nodefaultlib:python$(PYTHON_VER).lib
+!else
+PYTHON_LIB = $(PYTHON)\libs\python$(PYTHON_VER).lib
+!endif
+!endif
+
+# Perl interface
+!ifdef PERL
+!ifndef PERL_VER
+PERL_VER = 56
+!endif
+!message Perl requested (version $(PERL_VER)) - root dir is "$(PERL)"
+!if "$(DYNAMIC_PERL)" == "yes"
+!if $(PERL_VER) >= 56
+!message Perl DLL will be loaded dynamically
+!else
+!message Dynamic loading is not supported for Perl versions earlier than 5.6.0
+!message Reverting to static loading...
+!undef DYNAMIC_PERL
+!endif
+!endif
+
+# Is Perl installed in architecture-specific directories?
+!if exist($(PERL)\Bin\MSWin32-x86)
+PERL_ARCH = \MSWin32-x86
+!endif
+
+PERL_INCDIR = $(PERL)\Lib$(PERL_ARCH)\Core
+
+# Version-dependent stuff
+!if $(PERL_VER) == 55
+PERL_LIB = $(PERL_INCDIR)\perl.lib
+!else
+PERL_DLL = perl$(PERL_VER).dll
+PERL_LIB = $(PERL_INCDIR)\perl$(PERL_VER).lib
+!endif
+
+CFLAGS = $(CFLAGS) -DFEAT_PERL
+
+# Do we want to load Perl dynamically?
+!if "$(DYNAMIC_PERL)" == "yes"
+CFLAGS = $(CFLAGS) -DDYNAMIC_PERL -DDYNAMIC_PERL_DLL=\"$(PERL_DLL)\"
+!undef PERL_LIB
+!endif
+
+PERL_EXE = $(PERL)\Bin$(PERL_ARCH)\perl
+PERL_INC = /I $(PERL_INCDIR)
+PERL_OBJ = $(OUTDIR)\if_perl.obj $(OUTDIR)\if_perlsfio.obj
+XSUBPP = $(PERL)\lib\ExtUtils\xsubpp
+XSUBPP_TYPEMAP = $(PERL)\lib\ExtUtils\typemap
+
+!endif
+
+#
+# Support Ruby interface
+#
+!ifdef RUBY
+# Set default value
+!ifndef RUBY_VER
+RUBY_VER = 18
+!endif
+!ifndef RUBY_VER_LONG
+RUBY_VER_LONG = 1.8
+!endif
+
+!if $(RUBY_VER) >= 18
+!ifndef RUBY_PLATFORM
+RUBY_PLATFORM = i386-mswin32
+!endif
+!ifndef RUBY_INSTALL_NAME
+RUBY_INSTALL_NAME = msvcrt-ruby$(RUBY_VER)
+!endif
+!else
+!ifndef RUBY_PLATFORM
+RUBY_PLATFORM = i586-mswin32
+!endif
+!ifndef RUBY_INSTALL_NAME
+RUBY_INSTALL_NAME = mswin32-ruby$(RUBY_VER)
+!endif
+!endif # $(RUBY_VER) >= 18
+
+!message Ruby requested (version $(RUBY_VER)) - root dir is "$(RUBY)"
+CFLAGS = $(CFLAGS) -DFEAT_RUBY
+RUBY_OBJ = $(OUTDIR)\if_ruby.obj
+RUBY_INC = /I "$(RUBY)\lib\ruby\$(RUBY_VER_LONG)\$(RUBY_PLATFORM)"
+RUBY_LIB = $(RUBY)\lib\$(RUBY_INSTALL_NAME).lib
+# Do we want to load Ruby dynamically?
+!if "$(DYNAMIC_RUBY)" == "yes"
+!message Ruby DLL will be loaded dynamically
+CFLAGS = $(CFLAGS) -DDYNAMIC_RUBY -DDYNAMIC_RUBY_DLL=\"$(RUBY_INSTALL_NAME).dll\" -DDYNAMIC_RUBY_VER=$(RUBY_VER)
+!undef RUBY_LIB
+!endif
+!endif # RUBY
+
+#
+# Support PostScript printing
+#
+!if "$(POSTSCRIPT)" == "yes"
+CFLAGS = $(CFLAGS) -DMSWINPS
+!endif # POSTSCRIPT
+
+#
+# FEATURES: TINY, SMALL, NORMAL, BIG or HUGE
+#
+!if "$(FEATURES)"==""
+FEATURES = BIG
+!endif
+CFLAGS = $(CFLAGS) -DFEAT_$(FEATURES)
+
+#
+# End extra featuare include
+#
+!message
+
+conflags = /nologo /subsystem:$(SUBSYSTEM) /incremental:no
+
+!IF "$(MAP)" == "yes"
+# "/map" is for debugging
+conflags = $(conflags) /map
+!ELSEIF "$(MAP)" == "lines"
+# "/mapinfo:lines" is for debugging, only works for VC6 and later
+conflags = $(conflags) /map /mapinfo:lines
+!ENDIF
+
+LINKARGS1 = $(linkdebug) $(conflags) /nodefaultlib:libc
+LINKARGS2 = $(CON_LIB) $(GUI_LIB) $(LIBC) $(OLE_LIB) user32.lib $(SNIFF_LIB) \
+ $(PERL_LIB) $(PYTHON_LIB) $(RUBY_LIB) $(TCL_LIB) \
+ $(NETBEANS_LIB) $(XPM_LIB) $(LINK_PDB)
+
+all: $(VIM) vimrun.exe install.exe uninstal.exe xxd/xxd.exe GvimExt/gvimext.dll
+
+$(VIM): $(OUTDIR) $(OBJ) $(GUI_OBJ) $(OLE_OBJ) $(OLE_IDL) $(PERL_OBJ) $(PYTHON_OBJ) $(RUBY_OBJ) $(TCL_OBJ) $(SNIFF_OBJ) $(CSCOPE_OBJ) $(NETBEANS_OBJ) $(XPM_OBJ) version.c version.h
+ $(CC) $(CFLAGS) version.c /Fo$(OUTDIR)/version.obj $(PDB)
+ $(link) $(LINKARGS1) -out:$*.exe $(OBJ) $(GUI_OBJ) $(OLE_OBJ) \
+ $(PERL_OBJ) $(PYTHON_OBJ) $(RUBY_OBJ) $(TCL_OBJ) $(SNIFF_OBJ) \
+ $(CSCOPE_OBJ) $(NETBEANS_OBJ) $(XPM_OBJ) \
+ $(OUTDIR)\version.obj $(LINKARGS2)
+
+$(VIM).exe: $(VIM)
+
+$(OUTDIR):
+ if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
+
+install.exe: dosinst.c
+ $(CC) /nologo -DNDEBUG -DWIN32 dosinst.c kernel32.lib shell32.lib ole32.lib advapi32.lib uuid.lib
+ - if exist install.exe del install.exe
+ ren dosinst.exe install.exe
+
+uninstal.exe: uninstal.c
+ $(CC) /nologo -DNDEBUG -DWIN32 uninstal.c shell32.lib advapi32.lib
+
+vimrun.exe: vimrun.c
+ $(CC) /nologo -DNDEBUG vimrun.c
+
+xxd/xxd.exe: xxd/xxd.c
+ cd xxd
+ $(MAKE) /NOLOGO -f Make_mvc.mak
+ cd ..
+
+GvimExt/gvimext.dll: GvimExt/gvimext.cpp GvimExt/gvimext.rc GvimExt/gvimext.h
+ cd GvimExt
+ $(MAKE) /NOLOGO -f Makefile $(MAKEFLAGS_GVIMEXT)
+ cd ..
+
+
+tags: notags
+ $(CTAGS) *.c *.cpp *.h if_perl.xs proto\*.pro
+
+notags:
+ - if exist tags del tags
+
+clean:
+ - $(DEL_TREE) $(OUTDIR) auto
+ - if exist *.obj del *.obj
+ - if exist $(VIM).exe del $(VIM).exe
+ - if exist $(VIM).ilk del $(VIM).ilk
+ - if exist $(VIM).pdb del $(VIM).pdb
+ - if exist $(VIM).map del $(VIM).map
+ - if exist $(VIM).ncb del $(VIM).ncb
+ - if exist vimrun.exe del vimrun.exe
+ - if exist install.exe del install.exe
+ - if exist uninstal.exe del uninstal.exe
+ - if exist if_perl.c del if_perl.c
+ - if exist dimm.h del dimm.h
+ - if exist dimm_i.c del dimm_i.c
+ - if exist dimm.tlb del dimm.tlb
+ - if exist dosinst.exe del dosinst.exe
+ cd xxd
+ $(MAKE) /NOLOGO -f Make_mvc.mak clean
+ cd ..
+ cd GvimExt
+ $(MAKE) /NOLOGO -f Makefile clean
+ cd ..
+ cd GvimExt
+ $(MAKE) /NOLOGO -f Makefile clean
+ cd ..
+ - if exist testdir\*.out del testdir\*.out
+
+test:
+ cd testdir
+ $(MAKE) /NOLOGO -f Make_dos.mak win32
+ cd ..
+
+###########################################################################
+
+# Create a default rule for transforming .c files to .obj files in $(OUTDIR)
+# Batch compilation is supported by nmake 1.62 (part of VS 5.0) and later)
+!IF "$(_NMAKE_VER)" == ""
+.c{$(OUTDIR)/}.obj:
+!ELSE
+.c{$(OUTDIR)/}.obj::
+!ENDIF
+ $(CC) $(CFLAGS) /Fo$(OUTDIR)/ $(PDB) $<
+
+# Create a default rule for transforming .cpp files to .obj files in $(OUTDIR)
+# Batch compilation is supported by nmake 1.62 (part of VS 5.0) and later)
+!IF "$(_NMAKE_VER)" == ""
+.cpp{$(OUTDIR)/}.obj:
+!ELSE
+.cpp{$(OUTDIR)/}.obj::
+!ENDIF
+ $(CC) $(CFLAGS) /Fo$(OUTDIR)/ $(PDB) $<
+
+$(OUTDIR)/buffer.obj: $(OUTDIR) buffer.c $(INCL)
+
+$(OUTDIR)/charset.obj: $(OUTDIR) charset.c $(INCL)
+
+$(OUTDIR)/diff.obj: $(OUTDIR) diff.c $(INCL)
+
+$(OUTDIR)/digraph.obj: $(OUTDIR) digraph.c $(INCL)
+
+$(OUTDIR)/edit.obj: $(OUTDIR) edit.c $(INCL)
+
+$(OUTDIR)/eval.obj: $(OUTDIR) eval.c $(INCL)
+
+$(OUTDIR)/ex_cmds.obj: $(OUTDIR) ex_cmds.c $(INCL)
+
+$(OUTDIR)/ex_cmds2.obj: $(OUTDIR) ex_cmds2.c $(INCL)
+
+$(OUTDIR)/ex_docmd.obj: $(OUTDIR) ex_docmd.c $(INCL) ex_cmds.h
+
+$(OUTDIR)/ex_eval.obj: $(OUTDIR) ex_eval.c $(INCL) ex_cmds.h
+
+$(OUTDIR)/ex_getln.obj: $(OUTDIR) ex_getln.c $(INCL)
+
+$(OUTDIR)/fileio.obj: $(OUTDIR) fileio.c $(INCL)
+
+$(OUTDIR)/fold.obj: $(OUTDIR) fold.c $(INCL)
+
+$(OUTDIR)/getchar.obj: $(OUTDIR) getchar.c $(INCL)
+
+$(OUTDIR)/gui.obj: $(OUTDIR) gui.c $(INCL) $(GUI_INCL)
+
+$(OUTDIR)/gui_w32.obj: $(OUTDIR) gui_w32.c gui_w48.c $(INCL) $(GUI_INCL)
+
+$(OUTDIR)/if_cscope.obj: $(OUTDIR) if_cscope.c $(INCL)
+
+if_perl.c : if_perl.xs typemap
+ $(PERL_EXE) $(XSUBPP) -prototypes -typemap $(XSUBPP_TYPEMAP) -typemap typemap if_perl.xs > if_perl.c
+
+$(OUTDIR)/if_perl.obj: $(OUTDIR) if_perl.c $(INCL)
+ $(CC) $(CFLAGS) $(PERL_INC) if_perl.c /Fo$(OUTDIR)/if_perl.obj $(PDB)
+
+$(OUTDIR)/if_perlsfio.obj: $(OUTDIR) if_perlsfio.c $(INCL)
+ $(CC) $(CFLAGS) $(PERL_INC) if_perlsfio.c /Fo$(OUTDIR)/if_perlsfio.obj $(PDB)
+
+$(OUTDIR)/if_python.obj: $(OUTDIR) if_python.c $(INCL)
+ $(CC) $(CFLAGS) $(PYTHON_INC) if_python.c /Fo$(OUTDIR)/if_python.obj $(PDB)
+
+$(OUTDIR)/if_ole.obj: $(OUTDIR) if_ole.cpp $(INCL) if_ole.h
+
+$(OUTDIR)/if_ruby.obj: $(OUTDIR) if_ruby.c $(INCL)
+ $(CC) $(CFLAGS) $(RUBY_INC) if_ruby.c /Fo$(OUTDIR)/if_ruby.obj $(PDB)
+
+$(OUTDIR)/if_sniff.obj: $(OUTDIR) if_sniff.c $(INCL)
+ $(CC) $(CFLAGS) if_sniff.c /Fo$(OUTDIR)/if_sniff.obj $(PDB)
+
+$(OUTDIR)/if_tcl.obj: $(OUTDIR) if_tcl.c $(INCL)
+ $(CC) $(CFLAGS) $(TCL_INC) if_tcl.c /Fo$(OUTDIR)/if_tcl.obj $(PDB)
+
+$(OUTDIR)/main.obj: $(OUTDIR) main.c $(INCL)
+
+$(OUTDIR)/mark.obj: $(OUTDIR) mark.c $(INCL)
+
+$(OUTDIR)/memfile.obj: $(OUTDIR) memfile.c $(INCL)
+
+$(OUTDIR)/memline.obj: $(OUTDIR) memline.c $(INCL)
+
+$(OUTDIR)/menu.obj: $(OUTDIR) menu.c $(INCL)
+
+$(OUTDIR)/message.obj: $(OUTDIR) message.c $(INCL)
+
+$(OUTDIR)/misc1.obj: $(OUTDIR) misc1.c $(INCL)
+
+$(OUTDIR)/misc2.obj: $(OUTDIR) misc2.c $(INCL)
+
+$(OUTDIR)/move.obj: $(OUTDIR) move.c $(INCL)
+
+$(OUTDIR)/mbyte.obj: $(OUTDIR) mbyte.c $(INCL)
+
+$(OUTDIR)/netbeans.obj: $(OUTDIR) netbeans.c $(NBDEBUG_SRC) $(INCL)
+
+$(OUTDIR)/normal.obj: $(OUTDIR) normal.c $(INCL)
+
+$(OUTDIR)/option.obj: $(OUTDIR) option.c $(INCL)
+
+$(OUTDIR)/ops.obj: $(OUTDIR) ops.c $(INCL)
+
+$(OUTDIR)/os_mswin.obj: $(OUTDIR) os_mswin.c $(INCL)
+
+$(OUTDIR)/os_win32.obj: $(OUTDIR) os_win32.c $(INCL) os_win32.h
+
+$(OUTDIR)/os_w32exe.obj: $(OUTDIR) os_w32exe.c $(INCL)
+
+$(OUTDIR)/pathdef.obj: $(OUTDIR) auto/pathdef.c $(INCL)
+ $(CC) $(CFLAGS) auto/pathdef.c /Fo$(OUTDIR)/pathdef.obj $(PDB)
+
+$(OUTDIR)/quickfix.obj: $(OUTDIR) quickfix.c $(INCL)
+
+$(OUTDIR)/regexp.obj: $(OUTDIR) regexp.c $(INCL)
+
+$(OUTDIR)/screen.obj: $(OUTDIR) screen.c $(INCL)
+
+$(OUTDIR)/search.obj: $(OUTDIR) search.c $(INCL)
+
+$(OUTDIR)/syntax.obj: $(OUTDIR) syntax.c $(INCL)
+
+$(OUTDIR)/tag.obj: $(OUTDIR) tag.c $(INCL)
+
+$(OUTDIR)/term.obj: $(OUTDIR) term.c $(INCL)
+
+$(OUTDIR)/ui.obj: $(OUTDIR) ui.c $(INCL)
+
+$(OUTDIR)/undo.obj: $(OUTDIR) undo.c $(INCL)
+
+$(OUTDIR)/window.obj: $(OUTDIR) window.c $(INCL)
+
+$(OUTDIR)/xpm_w32.obj: $(OUTDIR) xpm_w32.c
+ $(CC) $(CFLAGS) $(XPM_INC) xpm_w32.c /Fo$(OUTDIR)/xpm_w32.obj $(PDB)
+
+$(OUTDIR)/vim.res: $(OUTDIR) vim.rc version.h tools.bmp tearoff.bmp vim.ico vim_error.ico vim_alert.ico vim_info.ico vim_quest.ico
+ $(RC) /l 0x409 /Fo$(OUTDIR)/vim.res $(RCFLAGS) vim.rc
+
+iid_ole.c if_ole.h vim.tlb: if_ole.idl $(INTDIR) $(OUTDIR)
+ midl /nologo /proxy nul /iid iid_ole.c /tlb vim.tlb /header if_ole.h if_ole.idl
+
+dimm.h dimm_i.c: dimm.idl
+ midl /nologo /proxy nul dimm.idl
+
+$(OUTDIR)/dimm_i.obj: $(OUTDIR) dimm_i.c $(INCL)
+
+$(OUTDIR)/glbl_ime.obj: $(OUTDIR) glbl_ime.cpp dimm.h $(INCL)
+
+auto/pathdef.c: auto
+ @echo creating auto/pathdef.c
+ @echo /* pathdef.c */ > auto\pathdef.c
+ @echo #include "vim.h" >> auto\pathdef.c
+ @echo char_u *default_vim_dir = (char_u *)"$(VIMRCLOC:\=\\)"; >> auto\pathdef.c
+ @echo char_u *default_vimruntime_dir = (char_u *)"$(VIMRUNTIMEDIR:\=\\)"; >> auto\pathdef.c
+ @echo char_u *all_cflags = (char_u *)"$(CC:\=\\) $(CFLAGS)"; >> auto\pathdef.c
+ @echo char_u *all_lflags = (char_u *)"$(link:\=\\) $(LINKARGS1:\=\\) $(LINKARGS2:\=\\)"; >> auto\pathdef.c
+ @echo char_u *compiled_user = (char_u *)"$(USERNAME)"; >> auto\pathdef.c
+ @echo char_u *compiled_sys = (char_u *)"$(USERDOMAIN)"; >> auto\pathdef.c
+
+auto:
+ if not exist auto/nul mkdir auto
+
+# End Custom Build
+proto.h: \
+ proto/buffer.pro \
+ proto/charset.pro \
+ proto/diff.pro \
+ proto/digraph.pro \
+ proto/edit.pro \
+ proto/eval.pro \
+ proto/ex_cmds.pro \
+ proto/ex_cmds2.pro \
+ proto/ex_docmd.pro \
+ proto/ex_eval.pro \
+ proto/ex_getln.pro \
+ proto/fileio.pro \
+ proto/getchar.pro \
+ proto/main.pro \
+ proto/mark.pro \
+ proto/memfile.pro \
+ proto/memline.pro \
+ proto/menu.pro \
+ proto/message.pro \
+ proto/misc1.pro \
+ proto/misc2.pro \
+ proto/move.pro \
+ proto/mbyte.pro \
+ proto/normal.pro \
+ proto/ops.pro \
+ proto/option.pro \
+ proto/os_mswin.pro \
+ proto/os_win32.pro \
+ proto/quickfix.pro \
+ proto/regexp.pro \
+ proto/screen.pro \
+ proto/search.pro \
+ proto/syntax.pro \
+ proto/tag.pro \
+ proto/term.pro \
+ proto/ui.pro \
+ proto/undo.pro \
+ proto/window.pro \
+ $(NETBEANS_PRO)
+
+# vim: set noet sw=8 ts=8 sts=0 wm=0 tw=0:
diff --git a/src/Make_os2.mak b/src/Make_os2.mak
new file mode 100644
index 000000000..4d21dc620
--- /dev/null
+++ b/src/Make_os2.mak
@@ -0,0 +1,147 @@
+#
+# Makefile for VIM on OS/2 using EMX vim:ts=8:sw=8:tw=78
+#
+# Created by: Paul Slootman
+#
+
+### This Makefile has been succesfully tested on these systems.
+### Check the (*) column for remarks, listed below.
+### Later code changes may cause small problems, otherwise Vim is supposed to
+### compile and run without problems.
+### Just to show that this is just like the Unix version!
+
+#system: configurations: version (*) tested by:
+#------------- ------------------------ ------- - ----------
+#OS/2 Warp HPFS gcc-2.7.2+emx-0.9b -GUI 4.5 Paul Slootman
+#OS/2 FAT gcc-2.6.3+emx -GUI 4.5 Karsten Sievert
+
+#>>>>> choose options:
+
+### See feature.h for a list of optionals.
+### Any other defines can be included here.
+
+DEFINES = -DUSE_SYSTEM=1
+
+#>>>>> name of the compiler and linker, name of lib directory
+CC = gcc
+
+#>>>>> end of choices
+
+### Name of target(s)
+TARGET = vim.exe
+
+### Names of the tools that are also made
+TOOLS = xxd/xxd.exe tee/tee.exe
+
+###########################################################################
+
+INCL = vim.h globals.h option.h keymap.h macros.h ascii.h term.h os_unix.h structs.h os_os2_cfg.h
+CFLAGS = -O2 -fno-strength-reduce -DOS2 -Wall -Iproto $(DEFINES)
+
+OBJ = \
+ buffer.o \
+ charset.o \
+ diff.o \
+ digraph.o \
+ edit.o \
+ eval.o \
+ ex_cmds.o \
+ ex_cmds2.o \
+ ex_docmd.o \
+ ex_eval.o \
+ ex_getln.o \
+ fileio.o \
+ fold.o \
+ getchar.o \
+ main.o \
+ mark.o \
+ memfile.o \
+ memline.o \
+ menu.o \
+ message.o \
+ misc1.o \
+ misc2.o \
+ move.o \
+ mbyte.o \
+ normal.o \
+ ops.o \
+ option.o \
+ quickfix.o \
+ regexp.o \
+ screen.o \
+ search.o \
+ syntax.o \
+ tag.o \
+ term.o \
+ ui.o \
+ undo.o \
+ window.o \
+ os_unix.o
+
+LIBS = -ltermcap
+
+# Default target is making the executable
+all: $(TARGET) $(TOOLS)
+
+# Link the target for normal use
+LFLAGS = -Zcrtdll -s -o $(TARGET) $(LIBS)
+
+$(TARGET): $(OBJ) version.c version.h
+ $(CC) $(CFLAGS) version.c $(OBJ) $(LFLAGS)
+
+xxd/xxd.exe: xxd/xxd.c
+ cd xxd & $(MAKE) -f Make_os2.mak
+
+tee/tee.exe: tee/tee.c
+ cd tee & $(MAKE) -f Makefile
+
+test:
+ cd testdir & $(MAKE) -f Make_os2.mak
+
+clean:
+ -del *.o
+ -del *.exe
+ -del *.~ *~ *.bak
+ cd xxd & $(MAKE) -f Make_os2.mak clean
+ cd tee & $(MAKE) -f Makefile clean
+
+###########################################################################
+
+os_unix.o: os_unix.c $(INCL)
+buffer.o: buffer.c $(INCL)
+charset.o: charset.c $(INCL)
+diff.o: diff.c $(INCL)
+digraph.o: digraph.c $(INCL)
+edit.o: edit.c $(INCL)
+eval.o: eval.c $(INCL)
+ex_cmds.o: ex_cmds.c $(INCL)
+ex_cmds2.o: ex_cmds2.c $(INCL)
+ex_docmd.o: ex_docmd.c $(INCL) ex_cmds.h
+ex_eval.o: ex_eval.c $(INCL) ex_cmds.h
+ex_getln.o: ex_getln.c $(INCL)
+fileio.o: fileio.c $(INCL)
+fold.o: fold.c $(INCL)
+getchar.o: getchar.c $(INCL)
+main.o: main.c $(INCL)
+mark.o: mark.c $(INCL)
+memfile.o: memfile.c $(INCL)
+memline.o: memline.c $(INCL)
+menu.o: menu.c $(INCL)
+message.o: message.c $(INCL)
+misc1.o: misc1.c $(INCL)
+misc2.o: misc2.c $(INCL)
+move.o: move.c $(INCL)
+mbyte.o: mbyte.c $(INCL)
+normal.o: normal.c $(INCL)
+ops.o: ops.c $(INCL)
+option.o: option.c $(INCL)
+quickfix.o: quickfix.c $(INCL)
+regexp.o: regexp.c $(INCL)
+screen.o: screen.c $(INCL)
+search.o: search.c $(INCL)
+syntax.o: syntax.c $(INCL)
+tag.o: tag.c $(INCL)
+term.o: term.c $(INCL)
+ui.o: ui.c $(INCL)
+undo.o: undo.c $(INCL)
+window.o: window.c $(INCL)
diff --git a/src/Make_ro.mak b/src/Make_ro.mak
new file mode 100644
index 000000000..6ac2f94b5
--- /dev/null
+++ b/src/Make_ro.mak
@@ -0,0 +1,168 @@
+#
+# Makefile for Vim on RISC OS - Andy Wingate
+#
+
+GCC = gcc -mthrowback
+CFLAGS = -DRISCOS -DFEAT_GUI
+# Optimising on ex_docmd.c seems to cause segfaults on compilation. Needs investigation.
+CCEX_DOCMD = $(GCC) $(CFLAGS)
+CC = $(GCC) $(CFLAGS) -O2
+# -DUP_BC_PC_EXTERN for term.c needed as BC defined in termlib.c and term.c
+
+TERMFLAG = -DUP_BC_PC_EXTERN
+
+ASMFLAGS = -throwback -objasm -gcc
+
+OBJS = o.buffer o.charset o.digraph o.edit o.eval o.ex_cmds o.ex_cmds2 o.diff \
+ o.ex_docmd o.ex_eval o.ex_getln o.fileio o.fold o.getchar o.main o.mark o.mbyte \
+ o.memfile o.memline o.menu o.message o.misc1 o.misc2 o.move \
+ o.normal o.ops o.option o.quickfix o.regexp o.screen o.search \
+ o.syntax o.tag o.term o.termlib o.ui o.undo o.version o.window \
+ o.os_riscos o.swis o.gui o.gui_riscos
+
+Vim: $(OBJS)
+ $(GCC) -o Vim $(OBJS)
+
+install: Vim
+ squeeze -v Vim @.!Vim.Vim
+
+clean:
+ create o.!fake! 0
+ wipe o.* ~cf
+ remove Vim
+
+o.swis: s.swis
+ as $(ASMFLAGS) -o o.swis s.swis
+
+# Rules for object files
+# You shouldn't need to put all this information in as all but term.c have the same
+# rule (and only then to save extra defines) but some versions of make are awkward.
+
+o.buffer: c.buffer
+ $(CC) -c c.buffer -o o.buffer
+
+o.charset: c.charset
+ $(CC) -c c.charset -o o.charset
+
+o.digraph: c.digraph
+ $(CC) -c c.digraph -o o.digraph
+
+o.diff: c.diff
+ $(CC) -c c.diff -o o.diff
+
+o.edit: c.edit
+ $(CC) -c c.edit -o o.edit
+
+o.eval: c.eval
+ $(CC) -c c.eval -o o.eval
+
+o.ex_cmds: c.ex_cmds
+ $(CC) -c c.ex_cmds -o o.ex_cmds
+
+o.ex_cmds2: c.ex_cmds2
+ $(CC) -c c.ex_cmds2 -o o.ex_cmds2
+
+o.ex_docmd: c.ex_docmd
+ $(CCEX_DOCMD) -c c.ex_docmd -o o.ex_docmd
+
+o.ex_eval: c.ex_eval
+ $(CCEX_DOCMD) -c c.ex_eval -o o.ex_eval
+
+o.ex_getln: c.ex_getln
+ $(CC) -c c.ex_getln -o o.ex_getln
+
+o.fileio: c.fileio
+ $(CC) -c c.fileio -o o.fileio
+
+o.fold: c.fold
+ $(CC) -c c.fold -o o.fold
+
+o.getchar: c.getchar
+ $(CC) -c c.getchar -o o.getchar
+
+o.gui: c.gui
+ $(CC) -c c.gui -o o.gui
+
+o.gui_riscos: c.gui_riscos
+ $(CC) -c c.gui_riscos -o o.gui_riscos
+
+o.main: c.main
+ $(CC) -c c.main -o o.main
+
+o.mark: c.mark
+ $(CC) -c c.mark -o o.mark
+
+o.mbyte: c.mbyte
+ $(CC) -c c.mbyte -o o.mbyte
+
+o.memfile: c.memfile
+ $(CC) -c c.memfile -o o.memfile
+
+o.memline: c.memline
+ $(CC) -c c.memline -o o.memline
+
+o.menu: c.menu
+ $(CC) -c c.menu -o o.menu
+
+o.message: c.message
+ $(CC) -c c.message -o o.message
+
+o.misc1: c.misc1
+ $(CC) -c c.misc1 -o o.misc1
+
+o.misc2: c.misc2
+ $(CC) -c c.misc2 -o o.misc2
+
+o.move: c.move
+ $(CC) -c c.move -o o.move
+
+o.normal: c.normal
+ $(CC) -c c.normal -o o.normal
+
+o.ops: c.ops
+ $(CC) -c c.ops -o o.ops
+
+o.option: c.option
+ $(CC) -c c.option -o o.option
+
+o.os_riscos: c.os_riscos
+ $(CC) -c c.os_riscos -o o.os_riscos
+
+o.pty: c.pty
+ $(CC) -c c.pty -o p.pty
+
+o.quickfix: c.quickfix
+ $(CC) -c c.quickfix -o o.quickfix
+
+o.regexp: c.regexp
+ $(CC) -c c.regexp -o o.regexp
+
+o.screen: c.screen
+ $(CC) -c c.screen -o o.screen
+
+o.search: c.search
+ $(CC) -c c.search -o o.search
+
+o.syntax: c.syntax
+ $(CC) -c c.syntax -o o.syntax
+
+o.tag: c.tag
+ $(CC) -c c.tag -o o.tag
+
+o.term: c.term
+ $(CC) $(TERMFLAG) -c c.term -o o.term
+
+o.termlib: c.termlib
+ $(CC) -c c.termlib -o o.termlib
+
+o.ui: c.ui
+ $(CC) -c c.ui -o o.ui
+
+o.undo: c.undo
+ $(CC) -c c.undo -o o.undo
+
+o.version: c.version
+ $(CC) -c c.version -o o.version
+
+o.window: c.window
+ $(CC) -c c.window -o o.window
diff --git a/src/Make_sas.mak b/src/Make_sas.mak
new file mode 100644
index 000000000..827903bbc
--- /dev/null
+++ b/src/Make_sas.mak
@@ -0,0 +1,345 @@
+# vim: set ft=make :
+# Makefile for VIM on the Amiga, using SAS/Lattice C 6.0 to 6.58
+#
+# Do NOT use the peephole optimizer with a version before 6.56!
+# It messes up all kinds of things:
+# For 6.0 and 6.1, expand_env() will not work correctly.
+# For 6.2 and 6.3 the call to free_line in u_freeentry is wrong.
+# The "read.me" file for version 6.56 includes a remark about a fix for the
+# peephole optimizer. Everything before 6.56 will probably fail.
+#
+# You should use Manx Aztec C whenever possible, because it has been tested.
+#
+# The prototypes from Manx and SAS are incompatible. If the prototypes
+# were generated by Manx, first do "touch *.c; make proto" before "make".
+# The prototypes generated on Unix work for both.
+#
+# Note: Not all dependencies are included. This was done to avoid having
+# to compile everything when a global variable or function is added.
+
+#>>>>> choose options:
+
+### See feature.h for a list of optionals.
+### Any other defines can be included here.
+
+# NO_ARP Don't include ARP functions
+# SASC=658 Sas/C version number
+# NEWSASC fixes a bug in the syntax highlighting?
+DEFINES = DEF=NO_ARP DEF=NEWSASC DEF="SASC=658"
+
+#>>>>> if HAVE_TGETENT is defined termlib.o has to be used
+#TERMLIB = termlib.o
+TERMLIB =
+
+#>>>>> choose NODEBUG for normal compiling, the other for debugging and
+# profiling
+# don't switch on debugging when generating proto files, it crashes the
+# compiler.
+DBG = NODEBUG
+#DBG = DBG=SF
+
+#>>>>> choose NOOPTPEEP for 6.0 to 6.3, NOOPT for debugging
+# with version 6.56 and later you can probably use OPT
+OPTIMIZE = OPT
+#OPTIMIZE = NOOPTPEEP
+#OPTIMIZE = NOOPT
+
+# for 6.58 you can use the line below, but be warned it takes a loooonnnggg time
+#OPTIMIZE=OPT OPTIMIZERSCHEDULER OPTIMIZERTIME NoOPTIMIZERALIAS \
+ OptimizerComplexity=10 OptimizerDepth=10 OptimizerRecurDepth=10 \
+ OptimizerInLocal OPTPEEP
+
+#generate code for your processor - 68060 will work for 040's as well.
+CPU=68000
+#CPU=68020
+#CPU=68030
+#CPU=68040
+#CPU=68060
+
+#Error reporting - rexx or console
+ERROR = ERRORCONSOLE ERRORSOURCE ERRORHIGHLIGHT
+#ERROR = ERRORREXX ERRORCONSOLE ERRORSOURCE ERRORHIGHLIGHT
+
+#memory types, if you have fast use it :->,
+# ANY = will work on all machines
+# FAST = this is the best option, for speed
+#MEMORYTYPE=FAST
+MEMORYTYPE=ANY
+
+#MEMSIZE - this is for compile time only for speed of compilation
+#MEMSIZE=HUGE
+MEMSIZE=LARGE
+#MEMSIZE=SMALL
+
+#>>>>> end of choices
+###########################################################################
+
+CC = sc
+GST = vim.gst
+COPTS = SINT SCODE SDATA
+SHELL = csh
+DEL = $(SHELL) -c rm -f
+
+# ignore error messages for uninitialized variables, they are mostly not correct
+CFLAGS = NOLINK $(DBG) CPU=$(CPU) NOSTACKCHECK DEF=AMIGA CODE=FAR idir=proto ignore=317
+CFLAGS2 = $(OPTIMIZE) $(ERROR) GSTIMMEDIATE GST=$(GST)
+CFLAGS3 = $(COPTS) STRINGMERGE MEMSIZE=$(MEMSIZE)
+CFLAGS4 = $(DEFINES) DATAMEMORY=$(MEMORYTYPE)
+
+PROPT = DEF=PROTO GPROTO GPPARM MAXIMUMERRORS=999 GENPROTOSTATICS GENPROTOPARAMETERS
+
+SRC = \
+ buffer.c \
+ charset.c \
+ diff.c \
+ digraph.c \
+ edit.c \
+ eval.c \
+ ex_cmds.c \
+ ex_cmds2.c \
+ ex_docmd.c \
+ ex_eval.c \
+ ex_getln.c \
+ fileio.c \
+ fold.c \
+ getchar.c \
+ main.c \
+ mark.c \
+ memfile.c \
+ memline.c \
+ menu.c \
+ message.c \
+ misc1.c \
+ misc2.c \
+ move.c \
+ mbyte.c \
+ normal.c \
+ ops.c \
+ option.c \
+ os_amiga.c \
+ quickfix.c \
+ regexp.c \
+ screen.c \
+ search.c \
+ syntax.c \
+ tag.c \
+ term.c \
+ ui.c \
+ undo.c \
+ window.c \
+ version.c
+
+OBJ = \
+ buffer.o \
+ charset.o \
+ diff.o \
+ digraph.o \
+ edit.o \
+ eval.o \
+ ex_cmds.o \
+ ex_cmds2.o \
+ ex_docmd.o \
+ ex_eval.o \
+ ex_getln.o \
+ fileio.o \
+ fold.o \
+ getchar.o \
+ main.o \
+ mark.o \
+ memfile.o \
+ memline.o \
+ menu.o \
+ message.o \
+ misc1.o \
+ misc2.o \
+ move.o \
+ mbyte.o \
+ normal.o \
+ ops.o \
+ option.o \
+ os_amiga.o \
+ quickfix.o \
+ regexp.o \
+ screen.o \
+ search.o \
+ syntax.o \
+ tag.o \
+ term.o \
+ ui.o \
+ undo.o \
+ window.o \
+ $(TERMLIB)
+
+PRO = \
+ proto/buffer.pro \
+ proto/charset.pro \
+ proto/diff.pro \
+ proto/digraph.pro \
+ proto/edit.pro \
+ proto/eval.pro \
+ proto/ex_cmds.pro \
+ proto/ex_cmds2.pro \
+ proto/ex_docmd.pro \
+ proto/ex_eval.pro \
+ proto/ex_getln.pro \
+ proto/fileio.pro \
+ proto/fold.pro \
+ proto/getchar.pro \
+ proto/main.pro \
+ proto/mark.pro \
+ proto/memfile.pro \
+ proto/memline.pro \
+ proto/menu.pro \
+ proto/message.pro \
+ proto/misc1.pro \
+ proto/misc2.pro \
+ proto/move.pro \
+ proto/mbyte.pro \
+ proto/normal.pro \
+ proto/ops.pro \
+ proto/option.pro \
+ proto/os_amiga.pro \
+ proto/quickfix.pro \
+ proto/regexp.pro \
+ proto/screen.pro \
+ proto/search.pro \
+ proto/syntax.pro \
+ proto/tag.pro \
+ proto/term.pro \
+ proto/termlib.pro \
+ proto/ui.pro \
+ proto/undo.pro \
+ proto/window.pro
+
+all: proto Vim
+
+Vim: scoptions $(OBJ) version.c version.h
+ $(CC) $(CFLAGS) version.c
+ $(CC) LINK $(COPTS) $(OBJ) version.o $(DBG) PNAME=Vim
+
+debug: scoptions $(OBJ) version.c version.h
+ $(CC) $(CFLAGS) version.c
+ $(CC) LINK $(COPTS) $(OBJ) version.o $(DBG) PNAME=Vim
+
+proto: $(GST) $(PRO)
+
+tags:
+ spat ctags $(SRC) *.h
+# csh -c ctags $(SRC) *.h
+
+# can't use delete here, too many file names
+clean:
+ $(DEL) *.o Vim $(GST)
+
+# generate GlobalSymbolTable, which speeds up the compile time.
+#
+# A preprocessing stage is used to work arounda bug in the GST generator, in
+# that it does not handle nested makefiles properly in this stage.
+# Ignore error message for not producing any code (105).
+$(GST): scoptions vim.h keymap.h macros.h ascii.h term.h structs.h
+ $(CC) $(CFLAGS) PREPROCESSORONLY vim.h objectname pre.h
+ $(CC) MGST=$(GST) pre.h ignore=105
+ $(DEL) pre.h
+
+# generate an options file, because SAS/C smake can't handle the amiga command
+# line can handle the lengths that this makefile will impose on the shell.
+# (Manx's make can do this).
+scoptions: Make_sas.mak
+ @echo "Generating - $@ ..."
+ @echo $(CFLAGS) > scoptions
+ @echo $(CFLAGS1) >> scoptions
+ @echo $(CFLAGS2) >> scoptions
+ @echo $(CFLAGS3) >> scoptions
+ @echo $(CFLAGS4) >> scoptions
+ @echo $(COPTS) >>scoptions
+ @echo done
+
+###########################################################################
+
+$(OBJ): $(GST) vim.h
+$(PRO): $(GST) vim.h
+
+.c.o:
+ $(CC) $(CFLAGS) $*.c
+
+.c.pro:
+ $(CC) $(CFLAGS) GPFILE=proto/$*.pro $(PROPT) $*.c
+
+# dependancies
+buffer.o: buffer.c
+proto/buffer.pro: buffer.c
+charset.o: charset.c
+proto/charset.pro: charset.c
+diff.o: diff.c
+proto/diff.pro: diff.c
+digraph.o: digraph.c
+proto/digraph.pro: digraph.c
+edit.o: edit.c
+proto/edit.pro: edit.c
+eval.o: eval.c
+proto/eval.pro: eval.c
+ex_cmds.o: ex_cmds.c
+proto/ex_cmds.pro: ex_cmds.c
+ex_cmds2.o: ex_cmds2.c
+proto/ex_cmds2.pro: ex_cmds2.c
+ex_docmd.o: ex_docmd.c ex_cmds.h
+proto/ex_docmd.pro: ex_docmd.c ex_cmds.h
+ex_eval.o: ex_eval.c ex_cmds.h
+proto/ex_eval.pro: ex_eval.c ex_cmds.h
+ex_getln.o: ex_getln.c
+proto/ex_getln.pro: ex_getln.c
+fileio.o: fileio.c
+proto/fileio.pro: fileio.c
+fold.o: fold.c
+proto/fold.pro: fold.c
+getchar.o: getchar.c
+proto/getchar.pro: getchar.c
+main.o: main.c
+proto/main.pro: main.c
+mark.o: mark.c
+proto/mark.pro: mark.c
+memfile.o: memfile.c
+proto/memfile.pro: memfile.c
+memline.o: memline.c
+proto/memline.pro: memline.c
+menu.o: menu.c
+proto/menu.pro: menu.c
+message.o: message.c
+proto/message.pro: message.c
+misc1.o: misc1.c
+proto/misc1.pro: misc1.c
+misc2.o: misc2.c
+proto/misc2.pro: misc2.c
+move.o: move.c
+proto/move.pro: move.c
+mbyte.o: mbyte.c
+proto/mbyte.pro: mbyte.c
+normal.o: normal.c
+proto/normal.pro: normal.c
+ops.o: ops.c
+proto/ops.pro: ops.c
+option.o: option.c
+proto/option.pro: option.c
+os_amiga.o: os_amiga.c
+proto/os_amiga.pro: os_amiga.c
+quickfix.o: quickfix.c
+proto/quickfix.pro: quickfix.c
+regexp.o: regexp.c
+proto/regexp.pro: regexp.c
+screen.o: screen.c
+proto/screen.pro: screen.c
+search.o: search.c
+proto/search.pro: search.c
+syntax.o: syntax.c
+proto/syntax.pro: syntax.c
+tag.o: tag.c
+proto/tag.pro: tag.c
+term.o: term.c
+proto/term.pro: term.c
+termlib.o: termlib.c
+proto/termlib.pro: termlib.c
+ui.o: ui.c
+proto/ui.pro: ui.c
+undo.o: undo.c
+proto/undo.pro: undo.c
+window.o: window.c
diff --git a/src/Make_vms.mms b/src/Make_vms.mms
new file mode 100644
index 000000000..f1ce93a29
--- /dev/null
+++ b/src/Make_vms.mms
@@ -0,0 +1,457 @@
+#
+# Makefile for Vim on OpenVMS
+#
+# Maintainer: Zoltan Arpadffy <arpadffy@polarhome.com>
+# Last change: 2004 May 04
+#
+# This has script been tested on VMS 6.2 to 7.3 on DEC Alpha and VAX
+# with MMS and MMK
+#
+# The following could be built:
+# vim.exe: standard (terminal, GUI/Motif, GUI/GTK)
+# dvim.exe: debug
+#
+# Edit the lines in the Configuration section below for fine tuning.
+#
+# To build: mms/descrip=Make_vms.mms
+# To clean up: mms/descrip=Make_vms.mms clean
+#
+# Hints and detailed description could be found in INSTALLVMS.TXT file.
+#
+######################################################################
+# Configuration section.
+######################################################################
+# Platform selection
+# Define this if you will use the VAX platform to build.
+# VAX = YES
+
+# VMS version
+# Uncomment if you use VMS version 6.2 or older
+# OLD_VMS = YES
+
+# Compiler selection.
+# Comment out if you use the VAXC compiler
+DECC = YES
+
+# Build model selection
+# TINY - Almost no features enabled, not even multiple windows
+# SMALL - Few features enabled, as basic as possible
+# NORMAL - A default selection of features enabled
+# BIG - Many features enabled, as rich as possible. (default)
+# HUGE - All possible featues enabled.
+# Please select one of these alternatives above.
+MODEL = BIG
+
+# GUI or terminal mode executable.
+# Comment out if you want just the character terminal mode only.
+GUI = YES
+
+# GUI with GTK
+# If you have GTK installed you might want to enable this option.
+# GTK = YES
+
+# Comment out if you want the compiler version with :ver command.
+# NOTE: This part can make some complications if you're using some
+# predefined symbols/flags for your compiler. If does, just leave behind
+# the comment varialbe CCVER.
+CCVER = YES
+
+# Uncomment if want a debug version. Resulting executable is DVIM.EXE
+# Development purpose only! Normally, it should not be defined. !!!
+# DEBUG = YES
+
+# Languages support for Perl, Python, TCL etc.
+# If you don't need it really, leave them behind the comment.
+# You will need related libraries, include files etc.
+# VIM_TCL = YES
+# VIM_PERL = YES
+# VIM_PYTHON = YES
+# VIM_RUBY = YES
+# VIM_SNIFF = YES
+
+# X Input Method. For entering special languages like chinese and
+# Japanese. Please define just one: VIM_XIM or VIM_HANGULIN
+# If you don't need it really, leave it behind the comment.
+# VIM_XIM = YES
+
+# Internal Hangul input method. GUI only.
+# If you don't need it really, leave it behind the comment.
+# VIM_HANGULIN = YES
+
+# Allow any white space to separate the fields in a tags file
+# When not defined, only a TAB is allowed.
+# VIM_TAG_ANYWHITE = YES
+
+######################################################################
+# Directory, library and include files configuration section.
+# Normally you need not to change anything below. !
+# These may need to be defined if things are not in standard locations
+#
+# You can find some explanation in INSTALLVMS.TXT
+######################################################################
+
+# Compiler setup
+
+.IFDEF VAX
+.IFDEF DECC # VAX with DECC
+CC_DEF = cc/decc
+PREFIX = /prefix=all
+.ELSE # VAX with VAXC
+CC_DEF = cc
+PREFIX =
+CCVER =
+.ENDIF
+.ELSE # AXP wixh DECC
+CC_DEF = cc
+PREFIX = /prefix=all
+.ENDIF
+
+LD_DEF = link
+C_INC = [.proto]
+
+.IFDEF OLD_VMS
+VMS_DEF = ,"OLD_VMS"
+.ENDIF
+
+.IFDEF DEBUG
+DEBUG_DEF = ,"DEBUG"
+TARGET = dvim.exe
+CFLAGS = /debug/noopt$(PREFIX)
+LDFLAGS = /debug
+.ELSE
+TARGET = vim.exe
+CFLAGS = /opt$(PREFIX)
+LDFLAGS =
+.ENDIF
+
+# Predefined VIM directories
+# Please, use $VIM and $VIMRUNTIME logicals instead
+VIMLOC = ""
+VIMRUN = ""
+
+CONFIG_H = os_vms_conf.h
+
+.IFDEF GTK
+.IFDEF GUI
+.ELSE
+GUI = YES
+.ENDIF
+.ENDIF
+
+.IFDEF GUI
+# X/Motif/GTK executable (also works in terminal mode )
+
+.IFDEF GTK
+GTK_DIR = ALPHA$DKA0:[GTK128.]
+DEFS = "HAVE_CONFIG_H","FEAT_GUI_GTK"
+LIBS = ,OS_VMS_GTK.OPT/OPT
+GUI_FLAG = /name=(as_is,short)/float=ieee/ieee=denorm
+GUI_SRC = gui.c gui_gtk.c gui_gtk_f.c gui_gtk_x11.c pty.c
+GUI_OBJ = gui.obj gui_gtk.obj gui_gtk_f.obj gui_gtk_x11.obj pty.obj
+GUI_INC = ,"/gtk_root/gtk","/gtk_root/glib"
+# GUI_INC_VER is used just for :ver information
+# this string should escape from C and DCL in the same time
+GUI_INC_VER= ,\""/gtk_root/gtk\"",\""/gtk_root/glib\""
+.else
+MOTIF = YES
+DEFS = "HAVE_CONFIG_H","FEAT_GUI_MOTIF"
+LIBS = ,OS_VMS_MOTIF.OPT/OPT
+GUI_FLAG =
+GUI_SRC = gui.c gui_motif.c gui_x11.c
+GUI_OBJ = gui.obj gui_motif.obj gui_x11.obj
+GUI_INC =
+.ENDIF
+
+# You need to define these variables if you do not have DECW files
+# at standard location
+GUI_INC_DIR = ,decw$include:
+# GUI_LIB_DIR = ,sys$library:
+
+.ELSE
+# Character terminal only executable
+DEFS = "HAVE_CONFIG_H"
+LIBS =
+.ENDIF
+
+.IFDEF VIM_PERL
+# Perl related setup.
+PERL = perl
+PERL_DEF = ,"FEAT_PERL"
+PERL_SRC = if_perlsfio.c if_perl.xs
+PERL_OBJ = if_perlsfio.obj if_perl.obj
+PERL_LIB = ,OS_VMS_PERL.OPT/OPT
+PERL_INC = ,dka0:[perlbuild.perl.lib.vms_axp.5_6_1.core]
+.ENDIF
+
+.IFDEF VIM_PYTHON
+# Python related setup.
+PYTHON_DEF = ,"FEAT_PYTHON"
+PYTHON_SRC = if_python.c
+PYTHON_OBJ = if_python.obj
+PYTHON_LIB = ,OS_VMS_PYTHON.OPT/OPT
+PYTHON_INC = ,PYTHON_INCLUDE
+.ENDIF
+
+.IFDEF VIM_TCL
+# TCL related setup.
+TCL_DEF = ,"FEAT_TCL"
+TCL_SRC = if_tcl.c
+TCL_OBJ = if_tcl.obj
+TCL_LIB = ,OS_VMS_TCL.OPT/OPT
+TCL_INC = ,dka0:[tcl80.generic]
+.ENDIF
+
+.IFDEF VIM_SNIFF
+# SNIFF related setup.
+SNIFF_DEF = ,"FEAT_SNIFF"
+SNIFF_SRC = if_sniff.c
+SNIFF_OBJ = if_sniff.obj
+SNIFF_LIB =
+SNIFF_INC =
+.ENDIF
+
+.IFDEF VIM_RUBY
+# RUBY related setup.
+RUBY_DEF = ,"FEAT_RUBY"
+RUBY_SRC = if_ruby.c
+RUBY_OBJ = if_ruby.obj
+RUBY_LIB = ,OS_VMS_RUBY.OPT/OPT
+RUBY_INC =
+.ENDIF
+
+.IFDEF VIM_XIM
+# XIM related setup.
+.IFDEF GUI
+XIM_DEF = ,"FEAT_XIM"
+.ENDIF
+.ENDIF
+
+.IFDEF VIM_HANGULIN
+# HANGULIN related setup.
+.IFDEF GUI
+HANGULIN_DEF = ,"FEAT_HANGULIN"
+HANGULIN_SRC = hangulin.c
+HANGULIN_OBJ = hangulin.obj
+.ENDIF
+.ENDIF
+
+.IFDEF VIM_TAG_ANYWHITE
+# TAG_ANYWHITE related setup.
+TAG_DEF = ,"FEAT_TAG_ANYWHITE"
+.ENDIF
+
+
+######################################################################
+# End of configuration section.
+# Please, do not change anything below without programming experience.
+######################################################################
+
+
+MODEL_DEF = "FEAT_$(MODEL)",
+
+# These go into pathdef.c
+VIMUSER = "''F$EDIT(F$GETJPI(" ","USERNAME"),"TRIM")'"
+VIMHOST = "''F$TRNLNM("SYS$NODE")'''F$TRNLNM("UCX$INET_HOST")'.''F$TRNLNM("UCX$INET_DOMAIN")'"
+
+.SUFFIXES : .obj .c
+
+ALL_CFLAGS = /def=($(MODEL_DEF)$(DEFS)$(VMS_DEF)$(DEBUG_DEF)$(PERL_DEF)$(PYTHON_DEF) -
+ $(TCL_DEF)$(SNIFF_DEF)$(RUBY_DEF)$(XIM_DEF)$(HANGULIN_DEF)$(TAG_DEF)) -
+ $(CFLAGS)$(GUI_FLAG) -
+ /include=($(C_INC)$(GUI_INC_DIR)$(GUI_INC)$(PERL_INC)$(PYTHON_INC)$(TCL_INC))
+
+# CFLAGS displayed in :ver information
+# It is specially formated for correct display of unix like includes
+# as $(GUI_INC) - replaced with $(GUI_INC_VER)
+# Otherwise should not be any other difference.
+ALL_CFLAGS_VER = /def=($(MODEL_DEF)$(DEFS)$(VMS_DEF)$(DEBUG_DEF)$(PERL_DEF)$(PYTHON_DEF) -
+ $(TCL_DEF)$(SNIFF_DEF)$(RUBY_DEF)$(XIM_DEF)$(HANGULIN_DEF)$(TAG_DEF)) -
+ $(CFLAGS)$(GUI_FLAG) -
+ /include=($(C_INC)$(GUI_INC_DIR)$(GUI_INC_VER)$(PERL_INC)$(PYTHON_INC)$(TCL_INC))
+
+ALL_LIBS = $(LIBS) $(GUI_LIB_DIR) $(GUI_LIB) \
+ $(PERL_LIB) $(PYTHON_LIB) $(TCL_LIB) $(SNIFF_LIB) $(RUBY_LIB)
+
+SRC = buffer.c charset.c diff.c digraph.c edit.c eval.c ex_cmds.c ex_cmds2.c \
+ ex_docmd.c ex_eval.c ex_getln.c if_xcmdsrv.c fileio.c fold.c getchar.c \
+ main.c mark.c menu.c mbyte.c memfile.c memline.c message.c misc1.c \
+ misc2.c move.c normal.c ops.c option.c quickfix.c regexp.c search.c \
+ syntax.c tag.c term.c termlib.c ui.c undo.c version.c screen.c \
+ window.c os_unix.c os_vms.c pathdef.c \
+ $(GUI_SRC) $(PERL_SRC) $(PYTHON_SRC) $(TCL_SRC) $(SNIFF_SRC) \
+ $(RUBY_SRC) $(HANGULIN_SRC)
+
+OBJ = buffer.obj charset.obj diff.obj digraph.obj edit.obj eval.obj \
+ ex_cmds.obj ex_cmds2.obj ex_docmd.obj ex_eval.obj ex_getln.obj \
+ if_xcmdsrv.obj fileio.obj fold.obj getchar.obj main.obj mark.obj \
+ menu.obj memfile.obj memline.obj message.obj misc1.obj misc2.obj \
+ move.obj mbyte.obj normal.obj ops.obj option.obj quickfix.obj \
+ regexp.obj search.obj syntax.obj tag.obj term.obj termlib.obj \
+ ui.obj undo.obj screen.obj version.obj window.obj os_unix.obj \
+ os_vms.obj pathdef.obj \
+ $(GUI_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(TCL_OBJ) $(SNIFF_OBJ) \
+ $(RUBY_OBJ) $(HANGULIN_OBJ)
+
+# Default target is making the executable
+all : [.auto]config.h mmk_compat motif_env gtk_env perl_env python_env tcl_env ruby_env $(TARGET)
+ ! $@
+
+[.auto]config.h : $(CONFIG_H)
+ copy/nolog $(CONFIG_H) [.auto]config.h
+
+mmk_compat :
+ -@ open/write pd pathdef.c
+ -@ write pd "/* Empty file to satisfy MMK depend. */"
+ -@ write pd "/* It will be owerwritten later on... */"
+ -@ close pd
+clean :
+ -@ if "''F$SEARCH("*.exe")'" .NES. "" then delete/noconfirm/nolog *.exe;*
+ -@ if "''F$SEARCH("*.obj")'" .NES. "" then delete/noconfirm/nolog *.obj;*
+ -@ if "''F$SEARCH("[.auto]config.h")'" .NES. "" then delete/noconfirm/nolog [.auto]config.h;*
+ -@ if "''F$SEARCH("pathdef.c")'" .NES. "" then delete/noconfirm/nolog pathdef.c;*
+ -@ if "''F$SEARCH("if_perl.c")'" .NES. "" then delete/noconfirm/nolog if_perl.c;*
+ -@ if "''F$SEARCH("*.opt")'" .NES. "" then delete/noconfirm/nolog *.opt;*
+
+# Link the target
+$(TARGET) : $(OBJ)
+ $(LD_DEF) $(LDFLAGS) /exe=$(TARGET) $+ $(ALL_LIBS)
+
+.c.obj :
+ $(CC_DEF) $(ALL_CFLAGS) $<
+
+pathdef.c : check_ccver $(CONFIG_H)
+ -@ write sys$output "creating PATHDEF.C file."
+ -@ open/write pd pathdef.c
+ -@ write pd "/* pathdef.c -- DO NOT EDIT! */"
+ -@ write pd "/* This file is automatically created by MAKE_VMS.MMS"
+ -@ write pd " * Change the file MAKE_VMS.MMS Only. */"
+ -@ write pd "typedef unsigned char char_u;"
+ -@ write pd "char_u *default_vim_dir = (char_u *)"$(VIMLOC)";"
+ -@ write pd "char_u *default_vimruntime_dir = (char_u *)"$(VIMRUN)";"
+ -@ write pd "char_u *all_cflags = (char_u *)""$(CC_DEF)$(ALL_CFLAGS_VER)"";"
+ -@ write pd "char_u *all_lflags = (char_u *)""$(LD_DEF)$(LDFLAGS) /exe=$(TARGET) *.OBJ $(ALL_LIBS)"";"
+ -@ write pd "char_u *compiler_version = (char_u *) ""''CC_VER'"";"
+ -@ write pd "char_u *compiled_user = (char_u *) "$(VIMUSER)";"
+ -@ write pd "char_u *compiled_sys = (char_u *) "$(VIMHOST)";"
+ -@ close pd
+
+if_perl.c : if_perl.xs
+ -@ $(PERL) PERL_ROOT:[LIB.ExtUtils]xsubpp -prototypes -typemap -
+ PERL_ROOT:[LIB.ExtUtils]typemap if_perl.xs >> $@
+
+make_vms.mms :
+ -@ write sys$output "The name of the makefile MUST be <MAKE_VMS.MMS> !!!"
+
+.IFDEF CCVER
+# This part can make some complications if you're using some predefined
+# symbols/flags for your compiler. If does, just comment out CCVER variable
+check_ccver :
+ -@ define sys$output cc_ver.tmp
+ -@ $(CC_DEF)/version
+ -@ deassign sys$output
+ -@ open/read file cc_ver.tmp
+ -@ read file CC_VER
+ -@ close file
+ -@ delete/noconfirm/nolog cc_ver.tmp.*
+.ELSE
+check_ccver :
+ -@ !
+.ENDIF
+
+.IFDEF MOTIF
+motif_env :
+ -@ write sys$output "using DECW/Motif environment."
+ -@ write sys$output "creating OS_VMS_MOTIF.OPT file."
+ -@ open/write opt_file OS_VMS_MOTIF.OPT
+ -@ write opt_file "sys$share:decw$xmlibshr12.exe/share,-"
+ -@ write opt_file "sys$share:decw$xtlibshrr5.exe/share,-"
+ -@ write opt_file "sys$share:decw$xlibshr.exe/share"
+ -@ close opt_file
+.ELSE
+motif_env :
+ -@ !
+.ENDIF
+
+
+.IFDEF GTK
+gtk_env :
+ -@ write sys$output "using GTK environment:"
+ -@ define/nolog gtk_root /trans=conc $(GTK_DIR)
+ -@ show logical gtk_root
+ -@ write sys$output " include path: "$(GUI_INC)""
+ -@ write sys$output "creating OS_VMS_GTK.OPT file."
+ -@ open/write opt_file OS_VMS_GTK.OPT
+ -@ write opt_file "gtk_root:[glib]libglib.exe /share,-"
+ -@ write opt_file "gtk_root:[glib.gmodule]libgmodule.exe /share,-"
+ -@ write opt_file "gtk_root:[gtk.gdk]libgdk.exe /share,-"
+ -@ write opt_file "gtk_root:[gtk.gtk]libgtk.exe /share,-"
+ -@ write opt_file "sys$share:decw$xmlibshr12.exe/share,-"
+ -@ write opt_file "sys$share:decw$xtlibshrr5.exe/share,-"
+ -@ write opt_file "sys$share:decw$xlibshr.exe/share"
+ -@ close opt_file
+.ELSE
+gtk_env :
+ -@ !
+.ENDIF
+
+.IFDEF VIM_PERL
+perl_env :
+ -@ write sys$output "using PERL environment:"
+ -@ show logical PERLSHR
+ -@ write sys$output " include path: ""$(PERL_INC)"""
+ -@ show symbol perl
+ -@ open/write pd if_perl.c
+ -@ write pd "/* Empty file to satisfy MMK depend. */"
+ -@ write pd "/* It will be owerwritten later on... */"
+ -@ close pd
+ -@ write sys$output "creating OS_VMS_PERL.OPT file."
+ -@ open/write opt_file OS_VMS_PERL.OPT
+ -@ write opt_file "PERLSHR /share"
+ -@ close opt_file
+.ELSE
+perl_env :
+ -@ !
+.ENDIF
+
+.IFDEF VIM_PYTHON
+python_env :
+ -@ write sys$output "using PYTHON environment:"
+ -@ show logical PYTHON_INCLUDE
+ -@ show logical PYTHON_OLB
+ -@ write sys$output "creating OS_VMS_PYTHON.OPT file."
+ -@ open/write opt_file OS_VMS_PYTHON.OPT
+ -@ write opt_file "PYTHON_OLB:PYTHON.OLB /share"
+ -@ close opt_file
+.ELSE
+python_env :
+ -@ !
+.ENDIF
+
+.IFDEF VIM_TCL
+tcl_env :
+ -@ write sys$output "using TCL environment:"
+ -@ show logical TCLSHR
+ -@ write sys$output " include path: ""$(TCL_INC)"""
+ -@ write sys$output "creating OS_VMS_TCL.OPT file."
+ -@ open/write opt_file OS_VMS_TCL.OPT
+ -@ write opt_file "TCLSHR /share"
+ -@ close opt_file
+.ELSE
+tcl_env :
+ -@ !
+.ENDIF
+
+.IFDEF VIM_RUBY
+ruby_env :
+ -@ write sys$output "using RUBY environment:"
+ -@ write sys$output " include path: ""$(RUBY_INC)"""
+ -@ write sys$output "creating OS_VMS_RUBY.OPT file."
+ -@ open/write opt_file OS_VMS_RUBY.OPT
+ -@ write opt_file "RUBYSHR /share"
+ -@ close opt_file
+.ELSE
+ruby_env :
+ -@ !
+.ENDIF
+
+
diff --git a/src/Make_w16.mak b/src/Make_w16.mak
new file mode 100644
index 000000000..cd425c9c2
--- /dev/null
+++ b/src/Make_w16.mak
@@ -0,0 +1,196 @@
+#
+# Borland C++ 5.0[12] makefile for vim, 16-bit windows gui version
+# By Vince Negri
+# *************************************************************
+# * WARNING!
+# * This was originally produced by the IDE, but has since been
+# * modifed to make it work properly. Adjust with care!
+# * In particular, leave LinkerLocalOptsAtW16_gvim16dexe alone
+# * unless you are a guru.
+# *************************************************************
+#
+# Look for BOR below and either pass a different value or
+# adjust the path as required. For example
+# make -fMake_w16.mak -DBOR=C:\PF\Borland\BC5.01 -B BccW16.cfg
+# make -fMake_w16.mak
+# Note: $(BOR) is effectively ignored unless BccW16.cfg is rebuilt.
+#
+# Does not compile with Borland C++ 4.51 Walter Briscoe 2003-02-24
+# "out of memory" from compiler if gvim16 wildly wrong. WFB 2003-03-04
+#
+# vim16.def must be a DOS-formatted file. (\r\n line endings.)
+# It is a UNIX-formatted file (\n line endings) in vim-*-extra.tar.gz
+
+.AUTODEPEND
+
+#
+# Borland C++ tools
+#
+IMPLIB = Implib
+BCC = Bcc +BccW16.cfg
+TLINK = TLink
+TLIB = TLib
+BRC = Brc
+TASM = Tasm
+#
+# IDE macros
+#
+
+#
+# Options
+#
+!ifndef BOR
+BOR = D:\BC5
+!endif
+
+# !ifndef INTDIR is lethal considering CLEAN below. WFB 2003-03-13
+INTDIR=w16
+
+# /Twe Make the target a Windows .EXE with explicit functions exportable +
+# /x Map file off
+# /l Include source line numbers in object map files`
+# /c case sensitive link
+# /C Case-sensitive exports and imports (16-bit only)
+# /k Produce "No Stack" warning.
+# /Oa Minimise segment alignment
+# /Oc Minimise Chain fixes
+# /Oi Minimise Iterated data
+# /Or Minimise resource alignment
+# /P -P=x Code pack size
+# /V Windows version for application
+# /L Folder to search for library files
+LinkerLocalOptsAtW16_gvim16dexe =/Twe/x/l/c/C/k/Or/Oc/Oa/Oi/P=65535/V3.10
+
+CompInheritOptsAt_gvim16dexe = \
+ -I$(BOR)\INCLUDE;PROTO;. \
+ -DFEAT_GUI;FEAT_GUI_MSWIN;FEAT_GUI_W16;MSWIN;WIN16;MSWIN16_FASTTEXT \
+ -DFEAT_TOOLBAR;WIN16_3DLOOK
+
+#
+# Dependency List
+#
+Dep_Gvim16 = \
+ gvim16.exe
+
+ObjFiles = \
+ $(INTDIR)\buffer.obj\
+ $(INTDIR)\charset.obj\
+ $(INTDIR)\diff.obj\
+ $(INTDIR)\digraph.obj\
+ $(INTDIR)\edit.obj\
+ $(INTDIR)\eval.obj\
+ $(INTDIR)\ex_cmds.obj\
+ $(INTDIR)\ex_cmds2.obj\
+ $(INTDIR)\ex_docmd.obj\
+ $(INTDIR)\ex_eval.obj\
+ $(INTDIR)\ex_getln.obj\
+ $(INTDIR)\fileio.obj\
+ $(INTDIR)\fold.obj\
+ $(INTDIR)\getchar.obj\
+ $(INTDIR)\gui.obj\
+ $(INTDIR)\gui_w16.obj\
+ $(INTDIR)\main.obj\
+ $(INTDIR)\mark.obj\
+ $(INTDIR)\mbyte.obj\
+ $(INTDIR)\memfile.obj\
+ $(INTDIR)\memline.obj\
+ $(INTDIR)\menu.obj\
+ $(INTDIR)\message.obj\
+ $(INTDIR)\misc1.obj\
+ $(INTDIR)\misc2.obj\
+ $(INTDIR)\move.obj\
+ $(INTDIR)\normal.obj\
+ $(INTDIR)\ops.obj\
+ $(INTDIR)\option.obj\
+ $(INTDIR)\os_win16.obj\
+ $(INTDIR)\os_msdos.obj\
+ $(INTDIR)\os_mswin.obj\
+ $(INTDIR)\quickfix.obj\
+ $(INTDIR)\regexp.obj\
+ $(INTDIR)\screen.obj\
+ $(INTDIR)\search.obj\
+ $(INTDIR)\syntax.obj\
+ $(INTDIR)\tag.obj\
+ $(INTDIR)\term.obj\
+ $(INTDIR)\ui.obj\
+ $(INTDIR)\undo.obj\
+ $(INTDIR)\version.obj\
+ $(INTDIR)\window.obj
+
+Dep_gvim16dexe = \
+ vimtbar.lib\
+ vim16.def\
+ $(INTDIR)\vim16.res\
+ $(ObjFiles)
+
+# Without the following, the implicit rule in BUILTINS.MAK is picked up
+# for a rule for .c.obj rather than the local implicit rule
+.SUFFIXES
+.SUFFIXES .c .obj
+.path.c = .
+
+# -P- Force C++ compilation off
+# -c Compilation only
+# -n Place .OBJ files
+{.}.c{$(INTDIR)}.obj:
+ $(BCC) -P- -c -n$(INTDIR)\ {$< }
+
+Gvim16 : BccW16.cfg $(Dep_Gvim16)
+ echo MakeNode
+
+gvim16.exe : $(Dep_gvim16dexe)
+ $(TLINK) $(LinkerLocalOptsAtW16_gvim16dexe) @&&|
+c0wl.obj $(ObjFiles)
+|,$*,,vimtbar ctl3dv2 import cwl, vim16.def,$(INTDIR)\vim16.res
+
+# Force objects to be built if $(BOR) changes
+$(ObjFiles) : Make_w16.mak BccW16.cfg
+
+$(INTDIR)\vim16.res : vim16.rc
+ $(BRC) -R @&&|
+ $(CompInheritOptsAt_gvim16dexe) -fo$*.res $?
+|
+
+
+# Compiler configuration file
+# There is no rule for $(INTDIR) as make always says it does not exist
+BccW16.cfg :
+ -@if not exist $(INTDIR)\$(NULL) mkdir $(INTDIR)
+ Copy &&|
+-3 ; Generate 80386 protected-mode compatible instructions
+-a ; Byte alignment
+-dc ; Move string literals from data segment to code segment
+-ff ; Fast floating point
+-H ; Generate and use precompiled headers
+-H=$(INTDIR)\gvim16.csm ; gvim16.csm is the precompiled header filename
+-k- ; No standard stack frame
+-ml ; Large memory model
+-OW ; Suppress the inc bp/dec bp on windows far functions
+-O1 ; Generate smallest possible code
+-O2 ; Generate fastest possible code (overrides prior -O1 control)
+-pr ; Fastcall calling convention passing parameters in registers
+-R- ; Exclude browser information in generated .OBJ files
+-v- ; Turn off source debugging
+-vi ; Turn inline function expansion on
+-WE ; Only __far _export functions are exported
+-w ; Display warnings
+-w-par ; Suppress: Parameter 'parameter' is never used
+-w-pch ; Cannot create pre-compiled header: initialized data in header
+-w-sig ; identifier' declared but never used
+-w-ucp ; Mixing pointers to different 'char' types
+-wuse ; 'identifier' declared but never used
+ $(CompInheritOptsAt_gvim16dexe)
+| $@
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+DEL_TREE = rmdir /s /q
+!ELSE
+NULL=nul
+DEL_TREE = deltree /y
+!ENDIF
+
+CLEAN:
+ -@if exist $(INTDIR)\$(NULL) $(DEL_TREE) $(INTDIR)
+ -@if exist BccW16.cfg erase BccW16.cfg
+ -@if exist gvim16.exe erase gvim16.exe
diff --git a/src/README.txt b/src/README.txt
new file mode 100644
index 000000000..05b864fa7
--- /dev/null
+++ b/src/README.txt
@@ -0,0 +1,140 @@
+README for the Vim source code
+
+Here are a few hints for finding your way around the source code. This
+doesn't make it less complex than it is, but it gets you started.
+
+You might also want to read ":help development".
+
+
+JUMPING AROUND
+
+First of all, use ":make tags" to generate a tags file, so that you can use
+the ":tag" command to jump around the source code.
+
+To jump to a function or variable definition, move the cursor on the name and
+use the CTRL-] command. Use CTRL-T or CTRL-O to jump back.
+
+To jump to a file, move the cursor on its name and use the "gf" command.
+
+Most code can be found in a file with an obvious name (incomplete list):
+ buffer.c manipulating buffers (loaded files)
+ diff.c diff mode (vimdiff)
+ eval.c expression evaluation
+ fileio.c reading and writing files
+ fold.c folding
+ getchar.c getting characters and key mapping
+ mark.c marks
+ memfile.c storing lines for buffers in a swapfile
+ memline.c storing lines for buffers in memory
+ menu.c menus
+ message.c (error) messages
+ mbyte.c multy-byte character handling
+ ops.c handling operators ("d", "y", "p")
+ option.c options
+ quickfix.c quickfix commands (":make", ":cn")
+ screen.c updating the windows
+ search.c pattern searching
+ tag.c tags
+ term.c terminal handling, termcap codes
+ undo.c undo and redo
+ window.c handling split windows
+
+
+IMPORTANT VARIABLES
+
+The current mode is stored in "State". The values it can have are NORMAL,
+INSERT, CMDLINE, and a few others.
+
+The current window is "curwin". The current buffer is "curbuf". These point
+to structures with the cursor position in the window, option values, the file
+name, etc. These are defined in structs.h.
+
+All the global variables are declared in globals.h.
+
+
+THE MAIN LOOP
+
+This is conveniently called main_loop(). It updates a few things and then
+calls normal_cmd() to process a command. This returns when the command is
+finished.
+
+The basic idea is that Vim waits for the user to type a character and
+processes it until another character is needed. Thus there are several places
+where Vim waits for a character to be typed. The vgetc() function is used for
+this. It also handles mapping.
+
+Updating the screen is mostly postponed until a command or a sequence of
+commands has finished. The work is done by update_screen(), which calls
+win_update() for every window, which calls win_line() for every line.
+See the start of screen.c for more explanations.
+
+
+COMMAND-LINE MODE
+
+When typing a ":", normal_cmd() will call getcmdline() to obtain a line with
+an Ex command. getcmdline() contains a loop that will handle each typed
+character. It returns when hitting <CR> or <Esc> or some other character that
+ends the command line mode.
+
+
+EX COMMANDS
+
+Ex commands are handled by the function do_cmdline(). It does the generic
+parsing of the ":" command line and calls do_one_cmd() for each separate
+command. It also takes care of while loops.
+
+do_one_cmd() parses the range and generic arguments and puts them in the
+exarg_t and passes it to the function that handles the command.
+
+The ":" commands are listed in ex_cmds.h. The third entry of each item is the
+name of the function that handles the command. The last entry are the flags
+that are used for the command.
+
+
+NORMAL MODE COMMANDS
+
+The Normal mode commands are handled by the normal_cmd() function. It also
+handles the optional count and an extra character for some commands. These
+are passed in a cmdarg_t to the function that handles the command.
+
+There is a table nv_cmds in normal.c which lists the first character of every
+command. The second entry of each item is the name of the function that
+handles the command.
+
+
+INSERT MODE COMMANDS
+
+When doing an "i" or "a" command, normal_cmd() will call the edit() function.
+It contains a loop that waits for the next character and handles it. It
+returns when leaving Insert mode.
+
+
+OPTIONS
+
+There is a list with all option names in option.c, called options[].
+
+
+THE GUI
+
+Most of the GUI code is implemented like it was a clever terminal. Typing a
+character, moving a scrollbar, clicking the mouse, etc. are all translated
+into events which are written in the input buffer. These are read by the
+main code, just like reading from a terminal. The code for this is scattered
+through gui.c. For example: gui_send_mouse_event() for a mouse click and
+gui_menu_cb() for a menu action. Key hits are handled by the system-specific
+GUI code, which calls add_to_input_buf() to send the key code.
+
+Updating the GUI window is done by writing codes in the output buffer, just
+like writing to a terminal. When the buffer gets full or is flushed,
+gui_write() will parse the codes and draw the appropriate items. Finally the
+system-specific GUI code will be called to do the work.
+
+
+DEBUGGING THE GUI
+
+Remember to prevent that gvim forks and the debugger thinks Vim has exited,
+add the "-f" argument. In gdb: "run -f -g".
+
+When stepping through display updating code, the focus event is triggerred
+when going from the debugger to Vim and back. To avoid this, recompile with
+some code in gui_focus_change() disabled.
diff --git a/src/VisVim/Commands.cpp b/src/VisVim/Commands.cpp
new file mode 100644
index 000000000..254b7a964
--- /dev/null
+++ b/src/VisVim/Commands.cpp
@@ -0,0 +1,693 @@
+#include "stdafx.h"
+#include <comdef.h> // For _bstr_t
+#include "VisVim.h"
+#include "Commands.h"
+#include "OleAut.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+
+#endif
+
+
+// Change directory before opening file?
+#define CD_SOURCE 0 // Cd to source path
+#define CD_SOURCE_PARENT 1 // Cd to parent directory of source path
+#define CD_NONE 2 // No cd
+
+
+static BOOL g_bEnableVim = TRUE; // Vim enabled
+static BOOL g_bDevStudioEditor = FALSE; // Open file in Dev Studio editor simultaneously
+static int g_ChangeDir = CD_NONE; // CD after file open?
+
+static void VimSetEnableState (BOOL bEnableState);
+static BOOL VimOpenFile (BSTR& FileName, long LineNr);
+static DISPID VimGetDispatchId (COleAutomationControl& VimOle, char* Method);
+static void VimErrDiag (COleAutomationControl& VimOle);
+static void VimChangeDir (COleAutomationControl& VimOle, DISPID DispatchId, BSTR& FileName);
+static void DebugMsg (char* Msg, char* Arg = NULL);
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCommands
+
+CCommands::CCommands ()
+{
+ // m_pApplication == NULL; M$ Code generation bug!!!
+ m_pApplication = NULL;
+ m_pApplicationEventsObj = NULL;
+ m_pDebuggerEventsObj = NULL;
+}
+
+CCommands::~CCommands ()
+{
+ ASSERT (m_pApplication != NULL);
+ if (m_pApplication)
+ {
+ m_pApplication->Release ();
+ m_pApplication = NULL;
+ }
+}
+
+void CCommands::SetApplicationObject (IApplication * pApplication)
+{
+ // This function assumes pApplication has already been AddRef'd
+ // for us, which CDSAddIn did in its QueryInterface call
+ // just before it called us.
+ m_pApplication = pApplication;
+ if (! m_pApplication)
+ return;
+
+ // Create Application event handlers
+ XApplicationEventsObj::CreateInstance (&m_pApplicationEventsObj);
+ if (! m_pApplicationEventsObj)
+ {
+ ReportInternalError ("XApplicationEventsObj::CreateInstance");
+ return;
+ }
+ m_pApplicationEventsObj->AddRef ();
+ m_pApplicationEventsObj->Connect (m_pApplication);
+ m_pApplicationEventsObj->m_pCommands = this;
+
+#ifdef NEVER
+ // Create Debugger event handler
+ CComPtr < IDispatch > pDebugger;
+ if (SUCCEEDED (m_pApplication->get_Debugger (&pDebugger))
+ && pDebugger != NULL)
+ {
+ XDebuggerEventsObj::CreateInstance (&m_pDebuggerEventsObj);
+ m_pDebuggerEventsObj->AddRef ();
+ m_pDebuggerEventsObj->Connect (pDebugger);
+ m_pDebuggerEventsObj->m_pCommands = this;
+ }
+#endif
+
+ // Get settings from registry HKEY_CURRENT_USER\Software\Vim\VisVim
+ HKEY hAppKey = GetAppKey ("Vim");
+ if (hAppKey)
+ {
+ HKEY hSectionKey = GetSectionKey (hAppKey, "VisVim");
+ if (hSectionKey)
+ {
+ g_bEnableVim = GetRegistryInt (hSectionKey, "EnableVim",
+ g_bEnableVim);
+ g_bDevStudioEditor = GetRegistryInt(hSectionKey,"DevStudioEditor",
+ g_bDevStudioEditor);
+ g_ChangeDir = GetRegistryInt (hSectionKey, "ChangeDir",
+ g_ChangeDir);
+ RegCloseKey (hSectionKey);
+ }
+ RegCloseKey (hAppKey);
+ }
+}
+
+void CCommands::UnadviseFromEvents ()
+{
+ ASSERT (m_pApplicationEventsObj != NULL);
+ if (m_pApplicationEventsObj)
+ {
+ m_pApplicationEventsObj->Disconnect (m_pApplication);
+ m_pApplicationEventsObj->Release ();
+ m_pApplicationEventsObj = NULL;
+ }
+
+#ifdef NEVER
+ if (m_pDebuggerEventsObj)
+ {
+ // Since we were able to connect to the Debugger events, we
+ // should be able to access the Debugger object again to
+ // unadvise from its events (thus the VERIFY_OK below--see
+ // stdafx.h).
+ CComPtr < IDispatch > pDebugger;
+ VERIFY_OK (m_pApplication->get_Debugger (&pDebugger));
+ ASSERT (pDebugger != NULL);
+ m_pDebuggerEventsObj->Disconnect (pDebugger);
+ m_pDebuggerEventsObj->Release ();
+ m_pDebuggerEventsObj = NULL;
+ }
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Event handlers
+
+// Application events
+
+HRESULT CCommands::XApplicationEvents::BeforeBuildStart ()
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return S_OK;
+}
+
+HRESULT CCommands::XApplicationEvents::BuildFinish (long nNumErrors, long nNumWarnings)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return S_OK;
+}
+
+HRESULT CCommands::XApplicationEvents::BeforeApplicationShutDown ()
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return S_OK;
+}
+
+// The open document event handle is the place where the real interface work
+// is done.
+// Vim gets called from here.
+//
+HRESULT CCommands::XApplicationEvents::DocumentOpen (IDispatch * theDocument)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+
+ if (! g_bEnableVim)
+ // Vim not enabled or empty command line entered
+ return S_OK;
+
+ // First get the current file name and line number
+
+ // Get the document object
+ CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc (theDocument);
+ if (! pDoc)
+ return S_OK;
+
+ BSTR FileName;
+ long LineNr = -1;
+
+ // Get the document name
+ if (FAILED (pDoc->get_FullName (&FileName)))
+ return S_OK;
+
+ LPDISPATCH pDispSel;
+
+ // Get a selection object dispatch pointer
+ if (SUCCEEDED (pDoc->get_Selection (&pDispSel)))
+ {
+ // Get the selection object
+ CComQIPtr < ITextSelection, &IID_ITextSelection > pSel (pDispSel);
+
+ if (pSel)
+ // Get the selection line number
+ pSel->get_CurrentLine (&LineNr);
+
+ pDispSel->Release ();
+ }
+
+ // Open the file in Vim and position to the current line
+ if (VimOpenFile (FileName, LineNr))
+ {
+ if (! g_bDevStudioEditor)
+ {
+ // Close the document in developer studio
+ CComVariant vSaveChanges = dsSaveChangesPrompt;
+ DsSaveStatus Saved;
+
+ pDoc->Close (vSaveChanges, &Saved);
+ }
+ }
+
+ // We're done here
+ SysFreeString (FileName);
+ return S_OK;
+}
+
+HRESULT CCommands::XApplicationEvents::BeforeDocumentClose (IDispatch * theDocument)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return S_OK;
+}
+
+HRESULT CCommands::XApplicationEvents::DocumentSave (IDispatch * theDocument)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return S_OK;
+}
+
+HRESULT CCommands::XApplicationEvents::NewDocument (IDispatch * theDocument)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+
+ if (! g_bEnableVim)
+ // Vim not enabled or empty command line entered
+ return S_OK;
+
+ // First get the current file name and line number
+
+ CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc (theDocument);
+ if (! pDoc)
+ return S_OK;
+
+ BSTR FileName;
+ HRESULT hr;
+
+ hr = pDoc->get_FullName (&FileName);
+ if (FAILED (hr))
+ return S_OK;
+
+ // Open the file in Vim and position to the current line
+ if (VimOpenFile (FileName, 0))
+ {
+ if (! g_bDevStudioEditor)
+ {
+ // Close the document in developer studio
+ CComVariant vSaveChanges = dsSaveChangesPrompt;
+ DsSaveStatus Saved;
+
+ pDoc->Close (vSaveChanges, &Saved);
+ }
+ }
+
+ SysFreeString (FileName);
+ return S_OK;
+}
+
+HRESULT CCommands::XApplicationEvents::WindowActivate (IDispatch * theWindow)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return S_OK;
+}
+
+HRESULT CCommands::XApplicationEvents::WindowDeactivate (IDispatch * theWindow)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return S_OK;
+}
+
+HRESULT CCommands::XApplicationEvents::WorkspaceOpen ()
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return S_OK;
+}
+
+HRESULT CCommands::XApplicationEvents::WorkspaceClose ()
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return S_OK;
+}
+
+HRESULT CCommands::XApplicationEvents::NewWorkspace ()
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return S_OK;
+}
+
+// Debugger event
+
+HRESULT CCommands::XDebuggerEvents::BreakpointHit (IDispatch * pBreakpoint)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return S_OK;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// VisVim dialog
+
+class CMainDialog : public CDialog
+{
+ public:
+ CMainDialog (CWnd * pParent = NULL); // Standard constructor
+
+ //{{AFX_DATA(CMainDialog)
+ enum { IDD = IDD_ADDINMAIN };
+ int m_ChangeDir;
+ BOOL m_bDevStudioEditor;
+ //}}AFX_DATA
+
+ //{{AFX_VIRTUAL(CMainDialog)
+ protected:
+ virtual void DoDataExchange (CDataExchange * pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ protected:
+ //{{AFX_MSG(CMainDialog)
+ afx_msg void OnEnable();
+ afx_msg void OnDisable();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP ()
+};
+
+CMainDialog::CMainDialog (CWnd * pParent /* =NULL */ )
+ : CDialog (CMainDialog::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CMainDialog)
+ m_ChangeDir = -1;
+ m_bDevStudioEditor = FALSE;
+ //}}AFX_DATA_INIT
+}
+
+void CMainDialog::DoDataExchange (CDataExchange * pDX)
+{
+ CDialog::DoDataExchange (pDX);
+ //{{AFX_DATA_MAP(CMainDialog)
+ DDX_Radio(pDX, IDC_CD_SOURCE_PATH, m_ChangeDir);
+ DDX_Check (pDX, IDC_DEVSTUDIO_EDITOR, m_bDevStudioEditor);
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP (CMainDialog, CDialog)
+ //{{AFX_MSG_MAP(CMainDialog)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP ()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCommands methods
+
+STDMETHODIMP CCommands::VisVimDialog ()
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+
+ // Use m_pApplication to access the Developer Studio Application
+ // object,
+ // and VERIFY_OK to see error strings in DEBUG builds of your add-in
+ // (see stdafx.h)
+
+ VERIFY_OK (m_pApplication->EnableModeless (VARIANT_FALSE));
+
+ CMainDialog Dlg;
+
+ Dlg.m_bDevStudioEditor = g_bDevStudioEditor;
+ Dlg.m_ChangeDir = g_ChangeDir;
+ if (Dlg.DoModal () == IDOK)
+ {
+ g_bDevStudioEditor = Dlg.m_bDevStudioEditor;
+ g_ChangeDir = Dlg.m_ChangeDir;
+
+ // Save settings to registry HKEY_CURRENT_USER\Software\Vim\VisVim
+ HKEY hAppKey = GetAppKey ("Vim");
+ if (hAppKey)
+ {
+ HKEY hSectionKey = GetSectionKey (hAppKey, "VisVim");
+ if (hSectionKey)
+ {
+ WriteRegistryInt (hSectionKey, "DevStudioEditor",
+ g_bDevStudioEditor);
+ WriteRegistryInt (hSectionKey, "ChangeDir", g_ChangeDir);
+ RegCloseKey (hSectionKey);
+ }
+ RegCloseKey (hAppKey);
+ }
+ }
+
+ VERIFY_OK (m_pApplication->EnableModeless (VARIANT_TRUE));
+ return S_OK;
+}
+
+STDMETHODIMP CCommands::VisVimEnable ()
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ VimSetEnableState (true);
+ return S_OK;
+}
+
+STDMETHODIMP CCommands::VisVimDisable ()
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ VimSetEnableState (false);
+ return S_OK;
+}
+
+STDMETHODIMP CCommands::VisVimToggle ()
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ VimSetEnableState (! g_bEnableVim);
+ return S_OK;
+}
+
+STDMETHODIMP CCommands::VisVimLoad ()
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+
+ // Use m_pApplication to access the Developer Studio Application object,
+ // and VERIFY_OK to see error strings in DEBUG builds of your add-in
+ // (see stdafx.h)
+
+ CComBSTR bStr;
+ // Define dispatch pointers for document and selection objects
+ CComPtr < IDispatch > pDispDoc, pDispSel;
+
+ // Get a document object dispatch pointer
+ VERIFY_OK (m_pApplication->get_ActiveDocument (&pDispDoc));
+ if (! pDispDoc)
+ return S_OK;
+
+ BSTR FileName;
+ long LineNr = -1;
+
+ // Get the document object
+ CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc (pDispDoc);
+
+ if (! pDoc)
+ return S_OK;
+
+ // Get the document name
+ if (FAILED (pDoc->get_FullName (&FileName)))
+ return S_OK;
+
+ // Get a selection object dispatch pointer
+ if (SUCCEEDED (pDoc->get_Selection (&pDispSel)))
+ {
+ // Get the selection object
+ CComQIPtr < ITextSelection, &IID_ITextSelection > pSel (pDispSel);
+
+ if (pSel)
+ // Get the selection line number
+ pSel->get_CurrentLine (&LineNr);
+ }
+
+ // Open the file in Vim
+ VimOpenFile (FileName, LineNr);
+
+ SysFreeString (FileName);
+ return S_OK;
+}
+
+
+//
+// Here we do the actual processing and communication with Vim
+//
+
+// Set the enable state and save to registry
+//
+static void VimSetEnableState (BOOL bEnableState)
+{
+ g_bEnableVim = bEnableState;
+ HKEY hAppKey = GetAppKey ("Vim");
+ if (hAppKey)
+ {
+ HKEY hSectionKey = GetSectionKey (hAppKey, "VisVim");
+ if (hSectionKey)
+ WriteRegistryInt (hSectionKey, "EnableVim", g_bEnableVim);
+ RegCloseKey (hAppKey);
+ }
+}
+
+// Open the file 'FileName' in Vim and goto line 'LineNr'
+// 'FileName' is expected to contain an absolute DOS path including the drive
+// letter.
+// 'LineNr' must contain a valid line number or 0, e. g. for a new file
+//
+static BOOL VimOpenFile (BSTR& FileName, long LineNr)
+{
+
+ // OLE automation object for com. with Vim
+ // When the object goes out of scope, it's desctructor destroys the OLE connection;
+ // This is imortant to avoid blocking the object
+ // (in this memory corruption would be likely when terminating Vim
+ // while still running DevStudio).
+ // So keep this object local!
+ COleAutomationControl VimOle;
+
+ // :cd D:/Src2/VisVim/
+ //
+ // Get a dispatch id for the SendKeys method of Vim;
+ // enables connection to Vim if necessary
+ DISPID DispatchId;
+ DispatchId = VimGetDispatchId (VimOle, "SendKeys");
+ if (! DispatchId)
+ // OLE error, can't obtain dispatch id
+ goto OleError;
+
+ OLECHAR Buf[MAX_OLE_STR];
+ char FileNameTmp[MAX_OLE_STR];
+ char VimCmd[MAX_OLE_STR];
+ char *s, *p;
+
+ // Prepend CTRL-\ CTRL-N to exit insert mode
+ VimCmd[0] = 0x1c;
+ VimCmd[1] = 0x0e;
+ VimCmd[2] = 0;
+
+#ifdef SINGLE_WINDOW
+ // Update the current file in Vim if it has been modified.
+ // Disabled, because it could write the file when you don't want to.
+ sprintf (VimCmd + 2, ":up\n");
+#endif
+ if (! VimOle.Method (DispatchId, "s", TO_OLE_STR_BUF (VimCmd, Buf)))
+ goto OleError;
+
+ // Change Vim working directory to where the file is if desired
+ if (g_ChangeDir != CD_NONE)
+ VimChangeDir (VimOle, DispatchId, FileName);
+
+ // Make Vim open the file.
+ // In the filename convert all \ to /, put a \ before a space.
+ sprintf(VimCmd, ":drop ");
+ sprintf(FileNameTmp, "%S", (char *)FileName);
+ s = VimCmd + 6;
+ for (p = FileNameTmp; *p != '\0' && s < FileNameTmp + MAX_OLE_STR - 4;
+ ++p)
+ if (*p == '\\')
+ *s++ = '/';
+ else
+ {
+ if (*p == ' ')
+ *s++ = '\\';
+ *s++ = *p;
+ }
+ *s++ = '\n';
+ *s = '\0';
+
+ if (! VimOle.Method (DispatchId, "s", TO_OLE_STR_BUF (VimCmd, Buf)))
+ goto OleError;
+
+ if (LineNr > 0)
+ {
+ // Goto line
+ sprintf (VimCmd, ":%d\n", LineNr);
+ if (! VimOle.Method (DispatchId, "s", TO_OLE_STR_BUF (VimCmd, Buf)))
+ goto OleError;
+ }
+
+ // Make Vim come to the foreground
+ if (! VimOle.Method ("SetForeground"))
+ VimOle.ErrDiag ();
+
+ // We're done
+ return true;
+
+ OleError:
+ // There was an OLE error
+ // Check if it's the "unknown class string" error
+ VimErrDiag (VimOle);
+ return false;
+}
+
+// Return the dispatch id for the Vim method 'Method'
+// Create the Vim OLE object if necessary
+// Returns a valid dispatch id or null on error
+//
+static DISPID VimGetDispatchId (COleAutomationControl& VimOle, char* Method)
+{
+ // Initialize Vim OLE connection if not already done
+ if (! VimOle.IsCreated ())
+ {
+ if (! VimOle.CreateObject ("Vim.Application"))
+ return NULL;
+ }
+
+ // Get the dispatch id for the SendKeys method.
+ // By doing this, we are checking if Vim is still there...
+ DISPID DispatchId = VimOle.GetDispatchId ("SendKeys");
+ if (! DispatchId)
+ {
+ // We can't get a dispatch id.
+ // This means that probably Vim has been terminated.
+ // Don't issue an error message here, instead
+ // destroy the OLE object and try to connect once more
+ //
+ // In fact, this should never happen, because the OLE aut. object
+ // should not be kept long enough to allow the user to terminate Vim
+ // to avoid memory corruption (why the heck is there no system garbage
+ // collection for those damned OLE memory chunks???).
+ VimOle.DeleteObject ();
+ if (! VimOle.CreateObject ("Vim.Application"))
+ // If this create fails, it's time for an error msg
+ return NULL;
+
+ if (! (DispatchId = VimOle.GetDispatchId ("SendKeys")))
+ // There is something wrong...
+ return NULL;
+ }
+
+ return DispatchId;
+}
+
+// Output an error message for an OLE error
+// Check on the classstring error, which probably means Vim wasn't registered.
+//
+static void VimErrDiag (COleAutomationControl& VimOle)
+{
+ SCODE sc = GetScode (VimOle.GetResult ());
+ if (sc == CO_E_CLASSSTRING)
+ {
+ char Buf[256];
+ sprintf (Buf, "There is no registered OLE automation server named "
+ "\"Vim.Application\".\n"
+ "Use the OLE-enabled version of Vim with VisVim and "
+ "make sure to register Vim by running \"vim -register\".");
+ MessageBox (NULL, Buf, "OLE Error", MB_OK);
+ }
+ else
+ VimOle.ErrDiag ();
+}
+
+// Change directory to the directory the file 'FileName' is in or it's parent
+// directory according to the setting of the global 'g_ChangeDir':
+// 'FileName' is expected to contain an absolute DOS path including the drive
+// letter.
+// CD_NONE
+// CD_SOURCE_PATH
+// CD_SOURCE_PARENT
+//
+static void VimChangeDir (COleAutomationControl& VimOle, DISPID DispatchId, BSTR& FileName)
+{
+ // Do a :cd first
+
+ // Get the path name of the file ("dir/")
+ CString StrFileName = FileName;
+ char Drive[_MAX_DRIVE];
+ char Dir[_MAX_DIR];
+ char DirUnix[_MAX_DIR * 2];
+ char *s, *t;
+
+ _splitpath (StrFileName, Drive, Dir, NULL, NULL);
+
+ // Convert to Unix path name format, escape spaces.
+ t = DirUnix;
+ for (s = Dir; *s; ++s)
+ if (*s == '\\')
+ *t++ = '/';
+ else
+ {
+ if (*s == ' ')
+ *t++ = '\\';
+ *t++ = *s;
+ }
+ *t = '\0';
+
+
+ // Construct the cd command; append /.. if cd to parent
+ // directory and not in root directory
+ OLECHAR Buf[MAX_OLE_STR];
+ char VimCmd[MAX_OLE_STR];
+
+ sprintf (VimCmd, ":cd %s%s%s\n", Drive, DirUnix,
+ g_ChangeDir == CD_SOURCE_PARENT && DirUnix[1] ? ".." : "");
+ VimOle.Method (DispatchId, "s", TO_OLE_STR_BUF (VimCmd, Buf));
+}
+
+#ifdef _DEBUG
+// Print out a debug message
+//
+static void DebugMsg (char* Msg, char* Arg)
+{
+ char Buf[400];
+ sprintf (Buf, Msg, Arg);
+ AfxMessageBox (Buf);
+}
+#endif
+
diff --git a/src/VisVim/Commands.h b/src/VisVim/Commands.h
new file mode 100644
index 000000000..e47c81a13
--- /dev/null
+++ b/src/VisVim/Commands.h
@@ -0,0 +1,127 @@
+// Commands.h : header file
+//
+
+#if !defined(AFX_COMMANDS_H__AC726717_2977_11D1_B2F3_006008040780__INCLUDED_)
+#define AFX_COMMANDS_H__AC726717_2977_11D1_B2F3_006008040780__INCLUDED_
+
+#include "vsvtypes.h"
+
+class CCommands :
+ public CComDualImpl < ICommands,
+ &IID_ICommands,
+ &LIBID_VisVim >,
+ public CComObjectRoot,
+ public CComCoClass < CCommands,
+ &CLSID_Commands >
+{
+ protected:
+ IApplication * m_pApplication;
+
+ public:
+ CCommands ();
+ ~CCommands ();
+ void SetApplicationObject (IApplication * m_pApplication);
+ IApplication *GetApplicationObject ()
+ {
+ return m_pApplication;
+ }
+ void UnadviseFromEvents ();
+
+ BEGIN_COM_MAP (CCommands)
+ COM_INTERFACE_ENTRY (IDispatch)
+ COM_INTERFACE_ENTRY (ICommands)
+ END_COM_MAP ()
+ DECLARE_NOT_AGGREGATABLE (CCommands)
+
+ protected:
+ // This class template is used as the base class for the Application
+ // event handler object and the Debugger event handler object,
+ // which are declared below.
+ template < class IEvents,
+ const IID * piidEvents,
+ const GUID * plibid,
+ class XEvents,
+ const CLSID * pClsidEvents >
+ class XEventHandler :
+ public CComDualImpl < IEvents,
+ piidEvents,
+ plibid >,
+ public CComObjectRoot,
+ public CComCoClass < XEvents,
+ pClsidEvents >
+ {
+ public:
+ BEGIN_COM_MAP (XEvents)
+ COM_INTERFACE_ENTRY (IDispatch)
+ COM_INTERFACE_ENTRY_IID (*piidEvents, IEvents)
+ END_COM_MAP ()
+ DECLARE_NOT_AGGREGATABLE (XEvents)
+ void Connect (IUnknown * pUnk)
+ {
+ VERIFY (SUCCEEDED (AtlAdvise (pUnk, this, *piidEvents,
+ &m_dwAdvise)));
+ }
+ void Disconnect (IUnknown * pUnk)
+ {
+ AtlUnadvise (pUnk, *piidEvents, m_dwAdvise);
+ }
+
+ CCommands *m_pCommands;
+
+ protected:
+ DWORD m_dwAdvise;
+ };
+
+ // This object handles events fired by the Application object
+ class XApplicationEvents : public XEventHandler < IApplicationEvents,
+ &IID_IApplicationEvents,
+ &LIBID_VisVim,
+ XApplicationEvents,
+ &CLSID_ApplicationEvents >
+ {
+ public:
+ // IApplicationEvents methods
+ STDMETHOD (BeforeBuildStart) (THIS);
+ STDMETHOD (BuildFinish) (THIS_ long nNumErrors, long nNumWarnings);
+ STDMETHOD (BeforeApplicationShutDown) (THIS);
+ STDMETHOD (DocumentOpen) (THIS_ IDispatch * theDocument);
+ STDMETHOD (BeforeDocumentClose) (THIS_ IDispatch * theDocument);
+ STDMETHOD (DocumentSave) (THIS_ IDispatch * theDocument);
+ STDMETHOD (NewDocument) (THIS_ IDispatch * theDocument);
+ STDMETHOD (WindowActivate) (THIS_ IDispatch * theWindow);
+ STDMETHOD (WindowDeactivate) (THIS_ IDispatch * theWindow);
+ STDMETHOD (WorkspaceOpen) (THIS);
+ STDMETHOD (WorkspaceClose) (THIS);
+ STDMETHOD (NewWorkspace) (THIS);
+ };
+ typedef CComObject < XApplicationEvents > XApplicationEventsObj;
+ XApplicationEventsObj *m_pApplicationEventsObj;
+
+ // This object handles events fired by the Application object
+ class XDebuggerEvents : public XEventHandler < IDebuggerEvents,
+ &IID_IDebuggerEvents,
+ &LIBID_VisVim,
+ XDebuggerEvents,
+ &CLSID_DebuggerEvents >
+ {
+ public:
+ // IDebuggerEvents method
+ STDMETHOD (BreakpointHit) (THIS_ IDispatch * pBreakpoint);
+ };
+ typedef CComObject < XDebuggerEvents > XDebuggerEventsObj;
+ XDebuggerEventsObj *m_pDebuggerEventsObj;
+
+ public:
+ // ICommands methods
+ STDMETHOD (VisVimDialog) (THIS);
+ STDMETHOD (VisVimEnable) (THIS);
+ STDMETHOD (VisVimDisable) (THIS);
+ STDMETHOD (VisVimToggle) (THIS);
+ STDMETHOD (VisVimLoad) (THIS);
+};
+
+typedef CComObject < CCommands > CCommandsObj;
+
+//{{AFX_INSERT_LOCATION}}
+
+#endif // !defined(AFX_COMMANDS_H__AC726717_2977_11D1_B2F3_006008040780__INCLUDED)
diff --git a/src/VisVim/DSAddIn.cpp b/src/VisVim/DSAddIn.cpp
new file mode 100644
index 000000000..3e7254461
--- /dev/null
+++ b/src/VisVim/DSAddIn.cpp
@@ -0,0 +1,160 @@
+#include "stdafx.h"
+#include "VisVim.h"
+#include "DSAddIn.h"
+#include "Commands.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+
+#endif
+
+// This is called when the user first loads the add-in, and on start-up
+// of each subsequent Developer Studio session
+STDMETHODIMP CDSAddIn::OnConnection (IApplication * pApp, VARIANT_BOOL bFirstTime,
+ long dwCookie, VARIANT_BOOL * OnConnection)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ *OnConnection = VARIANT_FALSE;
+
+ // Store info passed to us
+ IApplication *pApplication = NULL;
+ HRESULT hr;
+
+ hr = pApp->QueryInterface (IID_IApplication, (void **) &pApplication);
+ if (FAILED (hr))
+ {
+ ReportLastError (hr);
+ return E_UNEXPECTED;
+ }
+ if (pApplication == NULL)
+ {
+ ReportInternalError ("IApplication::QueryInterface");
+ return E_UNEXPECTED;
+ }
+
+ m_dwCookie = dwCookie;
+
+ // Create command dispatch, send info back to DevStudio
+ CCommandsObj::CreateInstance (&m_pCommands);
+ if (! m_pCommands)
+ {
+ ReportInternalError ("CCommandsObj::CreateInstance");
+ return E_UNEXPECTED;
+ }
+ m_pCommands->AddRef ();
+
+ // The QueryInterface above AddRef'd the Application object. It will
+ // be Release'd in CCommand's destructor.
+ m_pCommands->SetApplicationObject (pApplication);
+
+ hr = pApplication->SetAddInInfo ((long) AfxGetInstanceHandle (),
+ (LPDISPATCH) m_pCommands, IDR_TOOLBAR_MEDIUM, IDR_TOOLBAR_LARGE,
+ m_dwCookie);
+ if (FAILED (hr))
+ {
+ ReportLastError (hr);
+ return E_UNEXPECTED;
+ }
+
+ // Inform DevStudio of the commands we implement
+ if (! AddCommand (pApplication, "VisVimDialog", "VisVimDialogCmd",
+ IDS_CMD_DIALOG, 0, bFirstTime))
+ return E_UNEXPECTED;
+ if (! AddCommand (pApplication, "VisVimEnable", "VisVimEnableCmd",
+ IDS_CMD_ENABLE, 1, bFirstTime))
+ return E_UNEXPECTED;
+ if (! AddCommand (pApplication, "VisVimDisable", "VisVimDisableCmd",
+ IDS_CMD_DISABLE, 2, bFirstTime))
+ return E_UNEXPECTED;
+ if (! AddCommand (pApplication, "VisVimToggle", "VisVimToggleCmd",
+ IDS_CMD_TOGGLE, 3, bFirstTime))
+ return E_UNEXPECTED;
+ if (! AddCommand (pApplication, "VisVimLoad", "VisVimLoadCmd",
+ IDS_CMD_LOAD, 4, bFirstTime))
+ return E_UNEXPECTED;
+
+ *OnConnection = VARIANT_TRUE;
+ return S_OK;
+}
+
+// This is called on shut-down, and also when the user unloads the add-in
+STDMETHODIMP CDSAddIn::OnDisconnection (VARIANT_BOOL bLastTime)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+
+ m_pCommands->UnadviseFromEvents ();
+ m_pCommands->Release ();
+ m_pCommands = NULL;
+
+ return S_OK;
+}
+
+// Add a command to DevStudio
+// Creates a toolbar button for the command also.
+// 'MethodName' is the name of the methode specified in the .odl file
+// 'StrResId' the resource id of the descriptive string
+// 'GlyphIndex' the image index into the command buttons bitmap
+// Return true on success
+//
+bool CDSAddIn::AddCommand (IApplication* pApp, char* MethodName, char* CmdName,
+ UINT StrResId, UINT GlyphIndex, VARIANT_BOOL bFirstTime)
+{
+ CString CmdString;
+ CString CmdText;
+
+ CmdText.LoadString (StrResId);
+ CmdString = CmdName;
+ CmdString += CmdText;
+
+ CComBSTR bszCmdString (CmdString);
+ CComBSTR bszMethod (MethodName);
+ CComBSTR bszCmdName (CmdName);
+
+ // (see stdafx.h for the definition of VERIFY_OK)
+
+ VARIANT_BOOL bRet;
+ VERIFY_OK (pApp->AddCommand (bszCmdString, bszMethod, GlyphIndex,
+ m_dwCookie, &bRet));
+ if (bRet == VARIANT_FALSE)
+ {
+ // AddCommand failed because a command with this name already exists.
+ ReportInternalError ("IApplication::AddCommand");
+ return FALSE;
+ }
+
+ // Add toolbar buttons only if this is the first time the add-in
+ // is being loaded. Toolbar buttons are automatically remembered
+ // by Developer Studio from session to session, so we should only
+ // add the toolbar buttons once.
+ if (bFirstTime == VARIANT_TRUE)
+ VERIFY_OK (pApp->AddCommandBarButton (dsGlyph, bszCmdName, m_dwCookie));
+
+ return TRUE;
+}
+
+void ReportLastError (HRESULT Err)
+{
+ char *Buf = NULL;
+ char Msg[512];
+
+ FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL, Err,
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+ Buf, 400, NULL);
+ sprintf (Msg, "Unexpected error (Error code: %lx)\n%s", Err, Buf);
+
+ ::MessageBox (NULL, Msg, "VisVim", MB_OK | MB_ICONSTOP);
+ if (Buf)
+ LocalFree (Buf);
+}
+
+void ReportInternalError (char* Fct)
+{
+ char Msg[512];
+
+ sprintf (Msg, "Unexpected error\n%s failed", Fct);
+ ::MessageBox (NULL, Msg, "VisVim", MB_OK | MB_ICONSTOP);
+}
+
diff --git a/src/VisVim/DSAddIn.h b/src/VisVim/DSAddIn.h
new file mode 100644
index 000000000..72828722f
--- /dev/null
+++ b/src/VisVim/DSAddIn.h
@@ -0,0 +1,53 @@
+// DSAddIn.h : header file
+//
+
+#if !defined(AFX_DSADDIN_H__AC726715_2977_11D1_B2F3_006008040780__INCLUDED_)
+#define AFX_DSADDIN_H__AC726715_2977_11D1_B2F3_006008040780__INCLUDED_
+
+#include "commands.h"
+
+// {4F9E01C0-406B-11d2-8006-00001C405077}
+DEFINE_GUID (CLSID_DSAddIn,
+ 0x4f9e01c0, 0x406b, 0x11d2, 0x80, 0x6, 0x0, 0x0, 0x1c, 0x40, 0x50, 0x77);
+
+/////////////////////////////////////////////////////////////////////////////
+// CDSAddIn
+
+class CDSAddIn :
+ public IDSAddIn,
+ public CComObjectRoot,
+ public CComCoClass < CDSAddIn,
+ &CLSID_DSAddIn >
+{
+ public:
+ DECLARE_REGISTRY (CDSAddIn, "VisVim.DSAddIn.1",
+ "VisVim Developer Studio Add-in", IDS_VISVIM_LONGNAME,
+ THREADFLAGS_BOTH)
+
+ CDSAddIn ()
+ {
+ }
+
+ BEGIN_COM_MAP (CDSAddIn)
+ COM_INTERFACE_ENTRY (IDSAddIn)
+ END_COM_MAP ()
+ DECLARE_NOT_AGGREGATABLE (CDSAddIn)
+
+ // IDSAddIns
+ public:
+ STDMETHOD (OnConnection) (THIS_ IApplication * pApp, VARIANT_BOOL bFirstTime,
+ long dwCookie, VARIANT_BOOL * OnConnection);
+ STDMETHOD (OnDisconnection) (THIS_ VARIANT_BOOL bLastTime);
+
+ protected:
+ bool AddCommand (IApplication* pApp, char* MethodName, char* CmdName,
+ UINT StrResId, UINT GlyphIndex, VARIANT_BOOL bFirstTime);
+
+ protected:
+ CCommandsObj * m_pCommands;
+ DWORD m_dwCookie;
+};
+
+//{{AFX_INSERT_LOCATION}}
+
+#endif // !defined(AFX_DSADDIN_H__AC726715_2977_11D1_B2F3_006008040780__INCLUDED)
diff --git a/src/VisVim/OleAut.cpp b/src/VisVim/OleAut.cpp
new file mode 100644
index 000000000..0e01b1ec1
--- /dev/null
+++ b/src/VisVim/OleAut.cpp
@@ -0,0 +1,781 @@
+//
+// Class for creating OLE automation controllers.
+//
+// CreateObject() creates an automation object
+// Invoke() will call a property or method of the automation object.
+// GetProperty() returns a property
+// SetProperty() changes a property
+// Method() invokes a method
+//
+// For example, the following VB code will control Microsoft Word:
+//
+// Private Sub Form_Load()
+// Dim wb As Object
+// Set wb = CreateObject("Word.Basic")
+// wb.AppShow
+// wb.FileNewDefault
+// wb.Insert "This is a test"
+// wb.FileSaveAs "c:\sample.doc)"
+// End Sub
+//
+// A C++ automation controller that does the same can be written as follows:
+// the helper functions:
+//
+// Void FormLoad ()
+// {
+// COleAutomationControl Aut;
+// Aut.CreateObject("Word.Basic");
+// Aut.Method ("AppShow");
+// Aut.Method ("FileNewDefault");
+// Aut.Method ("Insert", "s", (LPOLESTR) OLESTR ("This is a test"));
+// Aut.Method ("FileSaveAs", "s", OLESTR ("c:\\sample.doc"));
+// }
+//
+//
+
+#include "stdafx.h"
+#include <stdarg.h>
+#include "oleaut.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+
+static bool CountArgsInFormat (LPCTSTR Format, UINT* nArgs);
+static LPCTSTR GetNextVarType (LPCTSTR Format, VARTYPE* pVarType);
+
+
+COleAutomationControl::COleAutomationControl ()
+{
+ m_pDispatch = NULL;
+ m_hResult = NOERROR;
+ m_nErrArg = 0;
+ VariantInit (&m_VariantResult);
+}
+
+COleAutomationControl::~COleAutomationControl ()
+{
+ DeleteObject ();
+}
+
+void COleAutomationControl::DeleteObject ()
+{
+ if (m_pDispatch)
+ {
+ m_pDispatch->Release ();
+ m_pDispatch = NULL;
+ }
+}
+
+// Creates an instance of the Automation object and
+// obtains it's IDispatch interface.
+//
+// Parameters:
+// ProgId ProgID of Automation object
+//
+bool COleAutomationControl::CreateObject (char* ProgId)
+{
+ CLSID ClsId; // CLSID of automation object
+ LPUNKNOWN pUnknown = NULL; // IUnknown of automation object
+
+ // Retrieve CLSID from the progID that the user specified
+ LPOLESTR OleProgId = TO_OLE_STR (ProgId);
+ m_hResult = CLSIDFromProgID (OleProgId, &ClsId);
+ if (FAILED (m_hResult))
+ goto error;
+
+ // Create an instance of the automation object and ask for the
+ // IDispatch interface
+ m_hResult = CoCreateInstance (ClsId, NULL, CLSCTX_SERVER,
+ IID_IUnknown, (void**) &pUnknown);
+ if (FAILED (m_hResult))
+ goto error;
+
+ m_hResult = pUnknown->QueryInterface (IID_IDispatch, (void**) &m_pDispatch);
+ if (FAILED (m_hResult))
+ goto error;
+
+ pUnknown->Release ();
+ return true;
+
+error:
+ if (pUnknown)
+ pUnknown->Release ();
+ if (m_pDispatch)
+ m_pDispatch->Release ();
+ return false;
+}
+
+// Return the dispatch id of a named service
+// This id can be used in subsequent calls to GetProperty (), SetProperty () and
+// Method (). This is the prefered method when performance is important.
+//
+DISPID COleAutomationControl::GetDispatchId (char* Name)
+{
+ DISPID DispatchId;
+
+ ASSERT (m_pDispatch);
+
+ // Get DISPID of property/method
+ LPOLESTR OleName = TO_OLE_STR (Name);
+ m_hResult = m_pDispatch->GetIDsOfNames (IID_NULL, &OleName, 1,
+ LOCALE_USER_DEFAULT, &DispatchId);
+ if (FAILED (m_hResult))
+ return NULL;
+ return DispatchId;
+}
+
+// The following functions use these parameters:
+//
+// Parameters:
+//
+// Name Name of property or method.
+//
+// Format Format string that describes the variable list of parameters that
+// follows. The format string can contain the follwoing characters.
+// & = mark the following format character as VT_BYREF
+// B = VT_BOOL
+// i = VT_I2
+// I = VT_I4
+// r = VT_R2
+// R = VT_R4
+// c = VT_CY
+// s = VT_BSTR (string pointer can be passed,
+// BSTR will be allocated by this function).
+// e = VT_ERROR
+// d = VT_DATE
+// v = VT_VARIANT. Use this to pass data types that are not described
+// in the format string. (For example SafeArrays).
+// D = VT_DISPATCH
+// U = VT_UNKNOWN
+//
+// ... Arguments of the property or method.
+// Arguments are described by Format.
+//
+
+bool COleAutomationControl::GetProperty (char* Name)
+{
+ return Invoke (DISPATCH_PROPERTYGET, Name, NULL, NULL);
+}
+
+bool COleAutomationControl::GetProperty (DISPID DispatchId)
+{
+ return Invoke (DISPATCH_PROPERTYGET, DispatchId, NULL, NULL);
+}
+
+bool COleAutomationControl::PutProperty (char* Name, LPCTSTR Format, ...)
+{
+ va_list ArgList;
+
+ va_start (ArgList, Format);
+ bool bRet = Invoke (DISPATCH_PROPERTYPUT, Name, Format, ArgList);
+ va_end (ArgList);
+ return bRet;
+}
+
+bool COleAutomationControl::PutProperty (DISPID DispatchId, LPCTSTR Format, ...)
+{
+ va_list ArgList;
+
+ va_start (ArgList, Format);
+ bool bRet = Invoke (DISPATCH_PROPERTYPUT, DispatchId, Format, ArgList);
+ va_end (ArgList);
+ return bRet;
+}
+
+bool COleAutomationControl::Method (char* Name, LPCTSTR Format, ...)
+{
+ va_list ArgList;
+
+ va_start (ArgList, Format);
+ bool bRet = Invoke (DISPATCH_METHOD, Name, Format, ArgList);
+ va_end (ArgList);
+ return bRet;
+}
+
+bool COleAutomationControl::Method (DISPID DispatchId, LPCTSTR Format, ...)
+{
+ va_list ArgList;
+
+ va_start (ArgList, Format);
+ bool bRet = Invoke (DISPATCH_METHOD, DispatchId, Format, ArgList);
+ va_end (ArgList);
+ return bRet;
+}
+
+bool COleAutomationControl::Invoke (WORD Flags, char* Name,
+ LPCTSTR Format, va_list ArgList)
+{
+ DISPID DispatchId = GetDispatchId (Name);
+ if (! DispatchId)
+ return false;
+ return Invoke (Flags, DispatchId, Format, ArgList);
+}
+
+bool COleAutomationControl::Invoke (WORD Flags, DISPID DispatchId,
+ LPCTSTR Format, va_list ArgList)
+{
+ UINT ArgCount = 0;
+ VARIANTARG* ArgVector = NULL;
+
+ ASSERT (m_pDispatch);
+
+ DISPPARAMS DispatchParams;
+ memset (&DispatchParams, 0, sizeof (DispatchParams));
+
+ // Determine number of arguments
+ if (Format)
+ CountArgsInFormat (Format, &ArgCount);
+
+ // Property puts have a named argument that represents the value that
+ // the property is being assigned.
+ DISPID DispIdNamed = DISPID_PROPERTYPUT;
+ if (Flags & DISPATCH_PROPERTYPUT)
+ {
+ if (ArgCount == 0)
+ {
+ m_hResult = ResultFromScode (E_INVALIDARG);
+ return false;
+ }
+ DispatchParams.cNamedArgs = 1;
+ DispatchParams.rgdispidNamedArgs = &DispIdNamed;
+ }
+
+ if (ArgCount)
+ {
+ // Allocate memory for all VARIANTARG parameters
+ ArgVector = (VARIANTARG*) CoTaskMemAlloc (
+ ArgCount * sizeof (VARIANTARG));
+ if (! ArgVector)
+ {
+ m_hResult = ResultFromScode (E_OUTOFMEMORY);
+ return false;
+ }
+ memset (ArgVector, 0, sizeof (VARIANTARG) * ArgCount);
+
+ // Get ready to walk vararg list
+ LPCTSTR s = Format;
+
+ VARIANTARG *p = ArgVector + ArgCount - 1; // Params go in opposite order
+
+ for (;;)
+ {
+ VariantInit (p);
+ if (! (s = GetNextVarType (s, &p->vt)))
+ break;
+
+ if (p < ArgVector)
+ {
+ m_hResult = ResultFromScode (E_INVALIDARG);
+ goto Cleanup;
+ }
+ switch (p->vt)
+ {
+ case VT_I2:
+ V_I2 (p) = va_arg (ArgList, short);
+ break;
+ case VT_I4:
+ V_I4 (p) = va_arg (ArgList, long);
+ break;
+ case VT_R4:
+ V_R4 (p) = va_arg (ArgList, float);
+ break;
+ case VT_DATE:
+ case VT_R8:
+ V_R8 (p) = va_arg (ArgList, double);
+ break;
+ case VT_CY:
+ V_CY (p) = va_arg (ArgList, CY);
+ break;
+ case VT_BSTR:
+ V_BSTR (p) = SysAllocString (va_arg (ArgList,
+ OLECHAR*));
+ if (! p->bstrVal)
+ {
+ m_hResult = ResultFromScode (E_OUTOFMEMORY);
+ p->vt = VT_EMPTY;
+ goto Cleanup;
+ }
+ break;
+ case VT_DISPATCH:
+ V_DISPATCH (p) = va_arg (ArgList, LPDISPATCH);
+ break;
+ case VT_ERROR:
+ V_ERROR (p) = va_arg (ArgList, SCODE);
+ break;
+ case VT_BOOL:
+ V_BOOL (p) = va_arg (ArgList, BOOL) ? -1 : 0;
+ break;
+ case VT_VARIANT:
+ *p = va_arg (ArgList, VARIANTARG);
+ break;
+ case VT_UNKNOWN:
+ V_UNKNOWN (p) = va_arg (ArgList, LPUNKNOWN);
+ break;
+
+ case VT_I2 | VT_BYREF:
+ V_I2REF (p) = va_arg (ArgList, short*);
+ break;
+ case VT_I4 | VT_BYREF:
+ V_I4REF (p) = va_arg (ArgList, long*);
+ break;
+ case VT_R4 | VT_BYREF:
+ V_R4REF (p) = va_arg (ArgList, float*);
+ break;
+ case VT_R8 | VT_BYREF:
+ V_R8REF (p) = va_arg (ArgList, double*);
+ break;
+ case VT_DATE | VT_BYREF:
+ V_DATEREF (p) = va_arg (ArgList, DATE*);
+ break;
+ case VT_CY | VT_BYREF:
+ V_CYREF (p) = va_arg (ArgList, CY*);
+ break;
+ case VT_BSTR | VT_BYREF:
+ V_BSTRREF (p) = va_arg (ArgList, BSTR*);
+ break;
+ case VT_DISPATCH | VT_BYREF:
+ V_DISPATCHREF (p) = va_arg (ArgList, LPDISPATCH*);
+ break;
+ case VT_ERROR | VT_BYREF:
+ V_ERRORREF (p) = va_arg (ArgList, SCODE*);
+ break;
+ case VT_BOOL | VT_BYREF:
+ {
+ BOOL* pBool = va_arg (ArgList, BOOL*);
+
+ *pBool = 0;
+ V_BOOLREF (p) = (VARIANT_BOOL*) pBool;
+ }
+ break;
+ case VT_VARIANT | VT_BYREF:
+ V_VARIANTREF (p) = va_arg (ArgList, VARIANTARG*);
+ break;
+ case VT_UNKNOWN | VT_BYREF:
+ V_UNKNOWNREF (p) = va_arg (ArgList, LPUNKNOWN*);
+ break;
+
+ default:
+ {
+ m_hResult = ResultFromScode (E_INVALIDARG);
+ goto Cleanup;
+ }
+ break;
+ }
+
+ --p; // Get ready to fill next argument
+ }
+ }
+
+ DispatchParams.cArgs = ArgCount;
+ DispatchParams.rgvarg = ArgVector;
+
+ // Initialize return variant, in case caller forgot. Caller can pass
+ // NULL if return value is not expected.
+ VariantInit (&m_VariantResult);
+
+ // Make the call
+ m_hResult = m_pDispatch->Invoke (DispatchId, IID_NULL, LOCALE_USER_DEFAULT,
+ Flags, &DispatchParams, &m_VariantResult,
+ &m_ExceptionInfo, &m_nErrArg);
+
+ Cleanup:
+ // Cleanup any arguments that need cleanup
+ if (ArgCount)
+ {
+ VARIANTARG* p = ArgVector;
+
+ while (ArgCount--)
+ {
+ switch (p->vt)
+ {
+ case VT_BSTR:
+ VariantClear (p);
+ break;
+ }
+ ++p;
+ }
+ CoTaskMemFree (ArgVector);
+ }
+
+ return FAILED (m_hResult) ? false : true;
+}
+
+#define CASE_SCODE(sc) \
+ case sc: \
+ lstrcpy((char*)ErrName, (char*)#sc); \
+ break;
+
+void COleAutomationControl::ErrDiag ()
+{
+ char ErrName[200];
+
+ SCODE sc = GetScode (m_hResult);
+ switch (sc)
+ {
+ // SCODE's defined in SCODE.H
+ CASE_SCODE (S_OK)
+ CASE_SCODE (S_FALSE)
+ CASE_SCODE (E_UNEXPECTED)
+ CASE_SCODE (E_OUTOFMEMORY)
+ CASE_SCODE (E_INVALIDARG)
+ CASE_SCODE (E_NOINTERFACE)
+ CASE_SCODE (E_POINTER)
+ CASE_SCODE (E_HANDLE)
+ CASE_SCODE (E_ABORT)
+ CASE_SCODE (E_FAIL)
+ CASE_SCODE (E_ACCESSDENIED)
+
+ // SCODE's defined in OLE2.H
+ CASE_SCODE (OLE_E_OLEVERB)
+ CASE_SCODE (OLE_E_ADVF)
+ CASE_SCODE (OLE_E_ENUM_NOMORE)
+ CASE_SCODE (OLE_E_ADVISENOTSUPPORTED)
+ CASE_SCODE (OLE_E_NOCONNECTION)
+ CASE_SCODE (OLE_E_NOTRUNNING)
+ CASE_SCODE (OLE_E_NOCACHE)
+ CASE_SCODE (OLE_E_BLANK)
+ CASE_SCODE (OLE_E_CLASSDIFF)
+ CASE_SCODE (OLE_E_CANT_GETMONIKER)
+ CASE_SCODE (OLE_E_CANT_BINDTOSOURCE)
+ CASE_SCODE (OLE_E_STATIC)
+ CASE_SCODE (OLE_E_PROMPTSAVECANCELLED)
+ CASE_SCODE (OLE_E_INVALIDRECT)
+ CASE_SCODE (OLE_E_WRONGCOMPOBJ)
+ CASE_SCODE (OLE_E_INVALIDHWND)
+ CASE_SCODE (OLE_E_NOT_INPLACEACTIVE)
+ CASE_SCODE (OLE_E_CANTCONVERT)
+ CASE_SCODE (OLE_E_NOSTORAGE)
+
+ CASE_SCODE (DV_E_FORMATETC)
+ CASE_SCODE (DV_E_DVTARGETDEVICE)
+ CASE_SCODE (DV_E_STGMEDIUM)
+ CASE_SCODE (DV_E_STATDATA)
+ CASE_SCODE (DV_E_LINDEX)
+ CASE_SCODE (DV_E_TYMED)
+ CASE_SCODE (DV_E_CLIPFORMAT)
+ CASE_SCODE (DV_E_DVASPECT)
+ CASE_SCODE (DV_E_DVTARGETDEVICE_SIZE)
+ CASE_SCODE (DV_E_NOIVIEWOBJECT)
+
+ CASE_SCODE (OLE_S_USEREG)
+ CASE_SCODE (OLE_S_STATIC)
+ CASE_SCODE (OLE_S_MAC_CLIPFORMAT)
+
+ CASE_SCODE (CONVERT10_E_OLESTREAM_GET)
+ CASE_SCODE (CONVERT10_E_OLESTREAM_PUT)
+ CASE_SCODE (CONVERT10_E_OLESTREAM_FMT)
+ CASE_SCODE (CONVERT10_E_OLESTREAM_BITMAP_TO_DIB)
+ CASE_SCODE (CONVERT10_E_STG_FMT)
+ CASE_SCODE (CONVERT10_E_STG_NO_STD_STREAM)
+ CASE_SCODE (CONVERT10_E_STG_DIB_TO_BITMAP)
+ CASE_SCODE (CONVERT10_S_NO_PRESENTATION)
+
+ CASE_SCODE (CLIPBRD_E_CANT_OPEN)
+ CASE_SCODE (CLIPBRD_E_CANT_EMPTY)
+ CASE_SCODE (CLIPBRD_E_CANT_SET)
+ CASE_SCODE (CLIPBRD_E_BAD_DATA)
+ CASE_SCODE (CLIPBRD_E_CANT_CLOSE)
+
+ CASE_SCODE (DRAGDROP_E_NOTREGISTERED)
+ CASE_SCODE (DRAGDROP_E_ALREADYREGISTERED)
+ CASE_SCODE (DRAGDROP_E_INVALIDHWND)
+ CASE_SCODE (DRAGDROP_S_DROP)
+ CASE_SCODE (DRAGDROP_S_CANCEL)
+ CASE_SCODE (DRAGDROP_S_USEDEFAULTCURSORS)
+
+ CASE_SCODE (OLEOBJ_E_NOVERBS)
+ CASE_SCODE (OLEOBJ_E_INVALIDVERB)
+ CASE_SCODE (OLEOBJ_S_INVALIDVERB)
+ CASE_SCODE (OLEOBJ_S_CANNOT_DOVERB_NOW)
+ CASE_SCODE (OLEOBJ_S_INVALIDHWND)
+ CASE_SCODE (INPLACE_E_NOTUNDOABLE)
+ CASE_SCODE (INPLACE_E_NOTOOLSPACE)
+ CASE_SCODE (INPLACE_S_TRUNCATED)
+
+ // SCODE's defined in COMPOBJ.H
+ CASE_SCODE (CO_E_NOTINITIALIZED)
+ CASE_SCODE (CO_E_ALREADYINITIALIZED)
+ CASE_SCODE (CO_E_CANTDETERMINECLASS)
+ CASE_SCODE (CO_E_CLASSSTRING)
+ CASE_SCODE (CO_E_IIDSTRING)
+ CASE_SCODE (CO_E_APPNOTFOUND)
+ CASE_SCODE (CO_E_APPSINGLEUSE)
+ CASE_SCODE (CO_E_ERRORINAPP)
+ CASE_SCODE (CO_E_DLLNOTFOUND)
+ CASE_SCODE (CO_E_ERRORINDLL)
+ CASE_SCODE (CO_E_WRONGOSFORAPP)
+ CASE_SCODE (CO_E_OBJNOTREG)
+ CASE_SCODE (CO_E_OBJISREG)
+ CASE_SCODE (CO_E_OBJNOTCONNECTED)
+ CASE_SCODE (CO_E_APPDIDNTREG)
+ CASE_SCODE (CLASS_E_NOAGGREGATION)
+ CASE_SCODE (CLASS_E_CLASSNOTAVAILABLE)
+ CASE_SCODE (REGDB_E_READREGDB)
+ CASE_SCODE (REGDB_E_WRITEREGDB)
+ CASE_SCODE (REGDB_E_KEYMISSING)
+ CASE_SCODE (REGDB_E_INVALIDVALUE)
+ CASE_SCODE (REGDB_E_CLASSNOTREG)
+ CASE_SCODE (REGDB_E_IIDNOTREG)
+ CASE_SCODE (RPC_E_CALL_REJECTED)
+ CASE_SCODE (RPC_E_CALL_CANCELED)
+ CASE_SCODE (RPC_E_CANTPOST_INSENDCALL)
+ CASE_SCODE (RPC_E_CANTCALLOUT_INASYNCCALL)
+ CASE_SCODE (RPC_E_CANTCALLOUT_INEXTERNALCALL)
+ CASE_SCODE (RPC_E_CONNECTION_TERMINATED)
+ CASE_SCODE (RPC_E_SERVER_DIED)
+ CASE_SCODE (RPC_E_CLIENT_DIED)
+ CASE_SCODE (RPC_E_INVALID_DATAPACKET)
+ CASE_SCODE (RPC_E_CANTTRANSMIT_CALL)
+ CASE_SCODE (RPC_E_CLIENT_CANTMARSHAL_DATA)
+ CASE_SCODE (RPC_E_CLIENT_CANTUNMARSHAL_DATA)
+ CASE_SCODE (RPC_E_SERVER_CANTMARSHAL_DATA)
+ CASE_SCODE (RPC_E_SERVER_CANTUNMARSHAL_DATA)
+ CASE_SCODE (RPC_E_INVALID_DATA)
+ CASE_SCODE (RPC_E_INVALID_PARAMETER)
+ CASE_SCODE (RPC_E_CANTCALLOUT_AGAIN)
+ CASE_SCODE (RPC_E_UNEXPECTED)
+
+ // SCODE's defined in DVOBJ.H
+ CASE_SCODE (DATA_S_SAMEFORMATETC)
+ CASE_SCODE (VIEW_E_DRAW)
+ CASE_SCODE (VIEW_S_ALREADY_FROZEN)
+ CASE_SCODE (CACHE_E_NOCACHE_UPDATED)
+ CASE_SCODE (CACHE_S_FORMATETC_NOTSUPPORTED)
+ CASE_SCODE (CACHE_S_SAMECACHE)
+ CASE_SCODE (CACHE_S_SOMECACHES_NOTUPDATED)
+
+ // SCODE's defined in STORAGE.H
+ CASE_SCODE (STG_E_INVALIDFUNCTION)
+ CASE_SCODE (STG_E_FILENOTFOUND)
+ CASE_SCODE (STG_E_PATHNOTFOUND)
+ CASE_SCODE (STG_E_TOOMANYOPENFILES)
+ CASE_SCODE (STG_E_ACCESSDENIED)
+ CASE_SCODE (STG_E_INVALIDHANDLE)
+ CASE_SCODE (STG_E_INSUFFICIENTMEMORY)
+ CASE_SCODE (STG_E_INVALIDPOINTER)
+ CASE_SCODE (STG_E_NOMOREFILES)
+ CASE_SCODE (STG_E_DISKISWRITEPROTECTED)
+ CASE_SCODE (STG_E_SEEKERROR)
+ CASE_SCODE (STG_E_WRITEFAULT)
+ CASE_SCODE (STG_E_READFAULT)
+ CASE_SCODE (STG_E_SHAREVIOLATION)
+ CASE_SCODE (STG_E_LOCKVIOLATION)
+ CASE_SCODE (STG_E_FILEALREADYEXISTS)
+ CASE_SCODE (STG_E_INVALIDPARAMETER)
+ CASE_SCODE (STG_E_MEDIUMFULL)
+ CASE_SCODE (STG_E_ABNORMALAPIEXIT)
+ CASE_SCODE (STG_E_INVALIDHEADER)
+ CASE_SCODE (STG_E_INVALIDNAME)
+ CASE_SCODE (STG_E_UNKNOWN)
+ CASE_SCODE (STG_E_UNIMPLEMENTEDFUNCTION)
+ CASE_SCODE (STG_E_INVALIDFLAG)
+ CASE_SCODE (STG_E_INUSE)
+ CASE_SCODE (STG_E_NOTCURRENT)
+ CASE_SCODE (STG_E_REVERTED)
+ CASE_SCODE (STG_E_CANTSAVE)
+ CASE_SCODE (STG_E_OLDFORMAT)
+ CASE_SCODE (STG_E_OLDDLL)
+ CASE_SCODE (STG_E_SHAREREQUIRED)
+ CASE_SCODE (STG_E_NOTFILEBASEDSTORAGE)
+ CASE_SCODE (STG_E_EXTANTMARSHALLINGS)
+ CASE_SCODE (STG_S_CONVERTED)
+
+ // SCODE's defined in STORAGE.H
+ CASE_SCODE (MK_E_CONNECTMANUALLY)
+ CASE_SCODE (MK_E_EXCEEDEDDEADLINE)
+ CASE_SCODE (MK_E_NEEDGENERIC)
+ CASE_SCODE (MK_E_UNAVAILABLE)
+ CASE_SCODE (MK_E_SYNTAX)
+ CASE_SCODE (MK_E_NOOBJECT)
+ CASE_SCODE (MK_E_INVALIDEXTENSION)
+ CASE_SCODE (MK_E_INTERMEDIATEINTERFACENOTSUPPORTED)
+ CASE_SCODE (MK_E_NOTBINDABLE)
+ CASE_SCODE (MK_E_NOTBOUND)
+ CASE_SCODE (MK_E_CANTOPENFILE)
+ CASE_SCODE (MK_E_MUSTBOTHERUSER)
+ CASE_SCODE (MK_E_NOINVERSE)
+ CASE_SCODE (MK_E_NOSTORAGE)
+ CASE_SCODE (MK_E_NOPREFIX)
+ CASE_SCODE (MK_S_REDUCED_TO_SELF)
+ CASE_SCODE (MK_S_ME)
+ CASE_SCODE (MK_S_HIM)
+ CASE_SCODE (MK_S_US)
+ CASE_SCODE (MK_S_MONIKERALREADYREGISTERED)
+
+ // SCODE's defined in DISPATCH.H
+ CASE_SCODE (DISP_E_UNKNOWNINTERFACE)
+ CASE_SCODE (DISP_E_MEMBERNOTFOUND)
+ CASE_SCODE (DISP_E_PARAMNOTFOUND)
+ CASE_SCODE (DISP_E_TYPEMISMATCH)
+ CASE_SCODE (DISP_E_UNKNOWNNAME)
+ CASE_SCODE (DISP_E_NONAMEDARGS)
+ CASE_SCODE (DISP_E_BADVARTYPE)
+ CASE_SCODE (DISP_E_EXCEPTION)
+ CASE_SCODE (DISP_E_OVERFLOW)
+ CASE_SCODE (DISP_E_BADINDEX)
+ CASE_SCODE (DISP_E_UNKNOWNLCID)
+ CASE_SCODE (DISP_E_ARRAYISLOCKED)
+ CASE_SCODE (DISP_E_BADPARAMCOUNT)
+ CASE_SCODE (DISP_E_PARAMNOTOPTIONAL)
+ CASE_SCODE (DISP_E_BADCALLEE)
+ CASE_SCODE (DISP_E_NOTACOLLECTION)
+
+ CASE_SCODE (TYPE_E_BUFFERTOOSMALL)
+ CASE_SCODE (TYPE_E_INVDATAREAD)
+ CASE_SCODE (TYPE_E_UNSUPFORMAT)
+ CASE_SCODE (TYPE_E_REGISTRYACCESS)
+ CASE_SCODE (TYPE_E_LIBNOTREGISTERED)
+ CASE_SCODE (TYPE_E_UNDEFINEDTYPE)
+ CASE_SCODE (TYPE_E_QUALIFIEDNAMEDISALLOWED)
+ CASE_SCODE (TYPE_E_INVALIDSTATE)
+ CASE_SCODE (TYPE_E_WRONGTYPEKIND)
+ CASE_SCODE (TYPE_E_ELEMENTNOTFOUND)
+ CASE_SCODE (TYPE_E_AMBIGUOUSNAME)
+ CASE_SCODE (TYPE_E_NAMECONFLICT)
+ CASE_SCODE (TYPE_E_UNKNOWNLCID)
+ CASE_SCODE (TYPE_E_DLLFUNCTIONNOTFOUND)
+ CASE_SCODE (TYPE_E_BADMODULEKIND)
+ CASE_SCODE (TYPE_E_SIZETOOBIG)
+ CASE_SCODE (TYPE_E_DUPLICATEID)
+ CASE_SCODE (TYPE_E_TYPEMISMATCH)
+ CASE_SCODE (TYPE_E_OUTOFBOUNDS)
+ CASE_SCODE (TYPE_E_IOERROR)
+ CASE_SCODE (TYPE_E_CANTCREATETMPFILE)
+ CASE_SCODE (TYPE_E_CANTLOADLIBRARY)
+ CASE_SCODE (TYPE_E_INCONSISTENTPROPFUNCS)
+ CASE_SCODE (TYPE_E_CIRCULARTYPE)
+
+ default:
+ lstrcpy (ErrName, "UNKNOWN SCODE");
+ }
+
+ char Buf[256];
+ sprintf (Buf, "An OLE error occured:\r\nCode = %s\r\nResult = %lx.",
+ (char*) ErrName, m_hResult);
+ MessageBox (NULL, Buf, "OLE Error", MB_OK);
+}
+
+
+static bool CountArgsInFormat (LPCTSTR Format, UINT* pArgCount)
+{
+ *pArgCount = 0;
+
+ if (! Format)
+ return true;
+
+ while (*Format)
+ {
+ if (*Format == '&')
+ Format++;
+
+ switch (*Format)
+ {
+ case 'b':
+ case 'i':
+ case 'I':
+ case 'r':
+ case 'R':
+ case 'c':
+ case 's':
+ case 'e':
+ case 'd':
+ case 'v':
+ case 'D':
+ case 'U':
+ ++ (*pArgCount);
+ Format++;
+ break;
+ case '\0':
+ default:
+ return false;
+ }
+ }
+ return true;
+}
+
+static LPCTSTR GetNextVarType (LPCTSTR Format, VARTYPE* pVarType)
+{
+ *pVarType = 0;
+ if (*Format == '&')
+ {
+ *pVarType = VT_BYREF;
+ Format++;
+ if (!*Format)
+ return NULL;
+ }
+ switch (*Format)
+ {
+ case 'b':
+ *pVarType |= VT_BOOL;
+ break;
+ case 'i':
+ *pVarType |= VT_I2;
+ break;
+ case 'I':
+ *pVarType |= VT_I4;
+ break;
+ case 'r':
+ *pVarType |= VT_R4;
+ break;
+ case 'R':
+ *pVarType |= VT_R8;
+ break;
+ case 'c':
+ *pVarType |= VT_CY;
+ break;
+ case 's':
+ *pVarType |= VT_BSTR;
+ break;
+ case 'e':
+ *pVarType |= VT_ERROR;
+ break;
+ case 'd':
+ *pVarType |= VT_DATE;
+ break;
+ case 'v':
+ *pVarType |= VT_VARIANT;
+ break;
+ case 'U':
+ *pVarType |= VT_UNKNOWN;
+ break;
+ case 'D':
+ *pVarType |= VT_DISPATCH;
+ break;
+ case '\0':
+ return NULL; // End of Format string
+ default:
+ return NULL;
+ }
+ return ++Format;
+}
+
+#ifndef UNICODE
+char* ConvertToAnsi (OLECHAR* sUnicode)
+{
+ static char BufAscii[MAX_OLE_STR];
+ return ConvertToAnsiBuf (sUnicode, BufAscii);
+}
+
+char* ConvertToAnsiBuf (OLECHAR* sUnicode, char* BufAscii)
+{
+ WideCharToMultiByte (CP_ACP, 0, sUnicode, -1, BufAscii, MAX_OLE_STR, NULL, NULL);
+ return BufAscii;
+}
+
+OLECHAR* ConvertToUnicode (char* sAscii)
+{
+ static OLECHAR BufUnicode[MAX_OLE_STR];
+ return ConvertToUnicodeBuf (sAscii, BufUnicode);
+}
+
+OLECHAR* ConvertToUnicodeBuf (char* sAscii, OLECHAR* BufUnicode)
+{
+ MultiByteToWideChar (CP_ACP, 0, sAscii, -1, BufUnicode, MAX_OLE_STR);
+ return BufUnicode;
+}
+#endif
+
diff --git a/src/VisVim/OleAut.h b/src/VisVim/OleAut.h
new file mode 100644
index 000000000..37de8078b
--- /dev/null
+++ b/src/VisVim/OleAut.h
@@ -0,0 +1,73 @@
+#ifndef __OLEAUT_H__
+#define __OLEAUT_H__
+
+class COleAutomationControl : public CObject
+{
+ public:
+ COleAutomationControl ();
+ ~COleAutomationControl ();
+ bool CreateObject (char* ProgId);
+ DISPID GetDispatchId (char* Name);
+ bool GetProperty (char* Name);
+ bool GetProperty (DISPID DispatchId);
+ bool PutProperty (char* Name, LPCTSTR Format, ...);
+ bool PutProperty (DISPID DispatchId, LPCTSTR Format, ...);
+ bool Method (char* Name, LPCTSTR Format = NULL, ...);
+ bool Method (DISPID DispatchId, LPCTSTR Format = NULL, ...);
+ void DeleteObject ();
+ void ErrDiag ();
+ bool IsCreated ()
+ {
+ return m_pDispatch ? true : false;
+ }
+ bool IsAlive ();
+ HRESULT GetResult ()
+ {
+ return m_hResult;
+ }
+ UINT GetErrArgNr ()
+ {
+ return m_nErrArg;
+ }
+ EXCEPINFO* GetExceptionInfo ()
+ {
+ return &m_ExceptionInfo;
+ }
+ LPVARIANT GetResultVariant ()
+ {
+ return &m_VariantResult;
+ }
+
+ protected:
+ bool Invoke (WORD Flags, char* Name, LPCTSTR Format, va_list ArgList);
+ bool Invoke (WORD Flags, DISPID DispatchId, LPCTSTR Format, va_list ArgList);
+
+ protected:
+ IDispatch* m_pDispatch;
+ HRESULT m_hResult;
+ UINT m_nErrArg;
+ EXCEPINFO m_ExceptionInfo;
+ VARIANTARG m_VariantResult;
+};
+
+#ifdef UNICODE
+ #define FROM_OLE_STRING(str) str
+ #define FROM_OLE_STRING_BUF(str,buf) str
+ #define TO_OLE_STR(str) str
+ #define TO_OLE_STR_BUF(str,buf) str
+ #define MAX_OLE_STR 1
+#else
+ #define FROM_OLE_STR(str) ConvertToAnsi(str)
+ #define FROM_OLE_STR_BUF(str,buf) ConvertToAnsiBuf(str,buf)
+ char* ConvertToAnsi (OLECHAR* sUnicode);
+ char* ConvertToAnsiBuf (OLECHAR* sUnicode, char* Buf);
+ #define TO_OLE_STR(str) ConvertToUnicode(str)
+ #define TO_OLE_STR_BUF(str,buf) ConvertToUnicodeBuf(str,buf)
+ OLECHAR* ConvertToUnicode (char* sAscii);
+ OLECHAR* ConvertToUnicodeBuf (char* sAscii, OLECHAR* Buf);
+ // Maximum length of string that can be converted between Ansi & Unicode
+ #define MAX_OLE_STR 500
+#endif
+
+
+#endif // __OLEAUT_H__
diff --git a/src/VisVim/README_VisVim.txt b/src/VisVim/README_VisVim.txt
new file mode 100644
index 000000000..fe22b12c5
--- /dev/null
+++ b/src/VisVim/README_VisVim.txt
@@ -0,0 +1,322 @@
+===============================
+Visual Studio - Vim Integration
+===============================
+
+Copyright (C) 1997 Heiko Erhardt
+
+VisVim is a Visual Studio Add-In that allows Vim to be integrated
+as the default text editor. It will be used instead of the Visual
+Studio built-in editor when you double-click on a file or press F4
+after compiling (it will go to the proper line in the Vim buffer).
+The file can be loaded exclusively by Vim or additionally to the
+builtin Visual Studio editor (this option can be set in the VisVim
+configuration dialog inside Visual Studio).
+Vim does not replace the Visual Studio editor, it still runs in its
+own window.
+
+VisVim is based upon VisEmacs by Christopher Payne
+(Copyright (C) Christopher Payne 1997).
+
+Author: Heiko Erhardt <Heiko.Erhardt@munich.netsurf.de>
+Based upon: VisEmacs by Christopher Payne <payneca@sagian.com>
+Version: 1.0
+Created: 23 Oct 1997
+Date: 23 Oct 1997
+
+VisVim is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+VisVim is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+
+Requirements
+------------
+
+VisVim works with the *OLE-enabled* version of Vim version 5.0 and higher
+only!!! You must download the extra archive containing the OLE-enabled
+executable from your Vim download site. When building your own Vim
+executable, use the if_ole_vc.mak makefile (Vim 5.1 and higher).
+VisVim needs DevStudio 5.0 or higher. It does not work with DevStudio 4.2.
+
+
+Installation
+------------
+
+1) Close running instances of DevStudio.
+
+2) Copy VisVim.dll into a convenient directory like \vim,
+ \vim\lib, or \vim\addin
+
+3) Register the DLL using regsvr32.exe ... (Skip this on Windows 95/98)
+ Example:
+ > cd \vim\addin
+ > regsvr32 VisVim.dll
+ On NT, you should do this from an administrator account.
+ Before installing a new version of VisVim you should unregister
+ the old one using
+ > regsvr32 -unregister VisVim.dll
+ The batch files register.bat and unregister.bat can do that for you.
+
+3a) If you didn't do this yet: Register the OLE gvim:
+ > gvim -register
+
+4) Start Visual Studio and go to:
+ Tools
+ Customize...
+ Add-Ins and Macro Files
+
+5) Click on Browse, and point Visual Studio to your VisVim.dll file.
+
+6) Click the checkbox to indicate that you want to use the Add-In, and
+ Close the Customize dialog box.
+
+7) You should notice the VisVim Toolbar with the Vim Icon.
+ Click the first item of the toolbar to get to the options dialog.
+
+
+Compiling VisVim
+----------------
+
+Two Options:
+
+1) Load the VisVim.mak file as a Workspace in Visual Studio and compile
+
+2) Use the MSVC command line compiler:
+ vcvars32
+ nmake -f VisVim.mak
+
+
+Using VisVim
+------------
+
+The VisVim DLL exposes several functions to the user. These functions are
+accessible using the toolbar or by assigning hotkeys to them (see below).
+The following functions are visible on the toolbar (from left to right):
+
+1. VisVim settings dialog
+ The settings you adjust here will be saved in the registry and
+ will be reloaded on program startup.
+
+2. Enable Vim
+ Enables Vim as Visual Studio editor. Control will be switched to Vim when:
+ - Clicking a file in the file view
+ - Clicking a compiler error message line
+ - Using the 'File-Open' Dialog
+ - Showing the current source line when encountering a debugger breakpoint.
+ - Using File-New
+
+3. Disable Vim
+ The internal Visual Studio editor will be used to edit files.
+
+4. Toggle enable state
+ Toggles the enable state of VisVim. Use this function if you want to have
+ one button only to activate/deactivate Vim.
+
+5. Load current file in Vim
+ Loads the file shown in the internal editor into Vim. Use this function if
+ you want the internal editor to stay active and just edit one file in Vim.
+ This command works always whether Vim is enabled as default editor or not.
+
+You cannot use DevStudio's debugger commands from inside Vim, so you should
+disable Vim before running the debugger.
+
+You can customize the Vim toolbar itself or add the Vim buttons to other
+toolbars.
+To have fast access to the VisVim options dialog I suggest to create keyboard
+shortcuts:
+
+1) Choose
+ Tools
+ Customize...
+ Keyboard
+2) Choose Category:AddIns and Commands:VisVim.
+3) Choose 'Main' as editor, enter each hotkey and press the Assign button.
+ I suggest:
+ VisVimDialogCmd Alt+Shift+V
+ VisVimEnableCmd Alt+Shift+E
+ VisVimDisableCmd Alt+Shift+D
+ VisVimToggleCmd Alt+Shift+T
+ VisVimLoadCmd Alt+Shift+G
+4) Close the dialog
+
+Now a typical debugging example:
+
+Using "Alt+Shift+d" you turn off Vim before starting the debugger.
+After hitting the breakpoint you single step through your application
+using the internal source code editor and examine variables.
+When you stumble across the line with the null pointer
+assignment, just press "Alt+Shift+g", and correct the error in Vim.
+Save the file, press Alt+Tab to return to DevStudio and press F7 to compile.
+That's it.
+
+
+Troubleshooting
+---------------
+
+1. When opening a file in DevStudio the file is opened in the DevStudio
+ editor and immediately vanishes. No Vim shows up.
+ Cause: Probably you don't have the OLE-enabled Vim or you didn't
+ register it.
+ Explanation: VisVim is notified by DevStudio if an 'open document' event
+ occurs. It then closes the document in the internal editor
+ and tries to start Vim. If Vim isn't properly OLE-registered,
+ this won't work.
+ Workaround: Download and install the OLE-enable version of Vim and
+ execute "gvim -register".
+
+2. Sometimes when clicking on a file, the file won't be opened by Vim but
+ instead the Visual Studio editor comes up.
+ Cause: The file was already loaded by the DevStudio editor.
+ Explanation: VisVim works by hooks exposed by Visual Studio.
+ Most of the functionality works from the OpenDocument hook.
+ If a document is already loaded in the Visual Studio editor,
+ no 'open document' event will be generated when clicking the
+ file in the file list.
+ Workaround: Close the document in Visual Studio first.
+
+3. I can't get VisVim to work. Either the Vim toolbar does not appear at all
+ or weird crashes happen.
+ Cause: The Visual Studio installation is messed up.
+ Explanation: I can't give you one. Ask M$.
+ Workaround: Reinstall DevStudio (I know this is brute, but in some cases
+ it helped). There was one case where the service pack 1 had
+ to be installed, too.
+
+4. If an instance of Vim is already running, VisVim will use that instance
+ and not start a new one.
+ Cause: This is proper OLE behaviour
+ Explanation: Some call it a bug, some a feature. That's just the way OLE
+ works.
+
+5. When being in insert mode in Vim and selecting a file in Visual Studio,
+ the Vim command :e ... is inserted as text instead of being executed.
+ Cause: You probably know...
+ Explanation: The Vim OLE automation interface interpretes the VisVim
+ commands as if they were typed in by the user.
+ So if you're in insert mode Vim considers it to be text.
+ I decided against sending an ESC before the command because
+ it may cause a beep or at least a screen flash when noeb is
+ set.
+ Workaround: Get used to press ESC before switching to DevStudio.
+
+6. I'm tired of VisVim but I can't get rid of it. I can't delete it in
+ Tools-Customize-Add-Ins.
+ Cause: You can't delete an item you once added to the add-ins
+ list box.
+ Explanation: M$ just didn't put a 'delete' button in the dialog box.
+ Unfortunately there is no DEL key accellerator as well...
+ Workaround: You can't kill it, but you can knock it out:
+ 1. Uncheck the check box in front of 'Vim Developer Studio
+ Add-in'.
+ 2. Close Visual Studio.
+ 3. Delete VisVim.dll or move it somewhere it can't be found.
+ 4. Run Visual Studio.
+ 5. Tools -> Cursomize ->Add-ins and Macro-Files.
+ 6. A message appears:
+ ".../VisVim.dll" "This add-in no longer exists. It will
+ no longer be displayed."
+ That's it!
+
+
+Change history
+--------------
+
+1.0a to 1.0
+-----------
+
+- All settings in the VisVim dialog are remembered between DevStudio sessions
+ by keeping them in the registry (HKEY_CURRENT_USER\Software\Vim\VisVim).
+- Added an option to do a :cd before opening the file (having a file opened
+ by clicking it but finding out to be still in C:\Windows\system when trying to
+ open another file by ":e" can be annoying). Change directory can be
+ done to the source file's directory or it's parent directory.
+- Added some explanations to the error message for the CO_E_CLASSSTRING error
+ ("Use OLE Vim and make sure to register...").
+
+1.0 to 1.1a
+-----------
+
+- The VisVim toolbar button now shows the new Vim icon instead of the old one.
+- Made some changes to the documentation, added the troubleshooting chapter
+ and ToDo list.
+- File-New-* now invokes Vim instead of the builtin editor if enabled.
+
+1.1 to 1.1b
+-----------
+
+- Extended the VisVim toolbar to have multiple buttons instead of one.
+- Moved the enable/disable commands from the settings dialog to the toolbar.
+- Added the toggle enable/disable command
+- Added the 'load current file' command.
+
+1.1b to 1.2
+-----------
+
+No new features, just some fine tuning:
+
+- Changed the GUID of the VisVim OLE interface to avoid conflicts with a
+ version of VisEmacs or VisVile on the same computer (Guy Gascoigne)
+- Fixed a bug caused by a bug in the Developer Studio add-in code generator
+ (Clark Morgan)
+- Fixed a memory leak (Clark Morgan)
+- Added an option in the VisVim dialog to prepend ESC before the first command
+ that is sent to Vim. This will avoid inserting the command as text when Vim
+ is still in insert mode.
+- An :update command is sent to Vim before any other command to update the
+ current file if it is modified, or else the following :cd or :e command will fail.
+
+1.2 to 1.3a
+-----------
+
+- Fixed a bug caused by a missing EnableModeless() function call in VimLoad().
+ This seems to reduce VisVim crashing DevStudio on some systems (it
+ occasionally still seems to happen, but it's more stable now).
+ (Vince Negri)
+- Added support for the new CTRL-\ CTRL-N command of Vim 5.4a.
+ This prevents Vim from beeping when a VisVim command is executed an Vim is
+ not in insert mode.
+
+
+ToDo List
+---------
+
+P1 is highest priority, P10 lowest
+
+P9 Switching to DevStudio using ALT-TAB may get annoying. Would be nice to
+ have the option to map ActivateApplication("Visual Studio") in Vim.
+ Vim DLLs would solve that problem.
+
+P8 Execute :tag command in Vim for word under cursor in DevStudio
+
+P7 Controlling the Visual Studio Debugger from inside Vim
+ See message above. Also a 'Debug' highligh group and a
+ command to highlight a certain line would be necessary.
+
+P6 Provide an option to open the current file in VisVim in
+ Visual Studio editor
+ Same as above message. A kind of two way OLE automation would have to be
+ established between VisVim and Vim. Also a 'Debug' highlight group and a
+ command to highlight a certain line would be necessary.
+
+
+Known Problems
+--------------
+
+- Occasional memory corruptions in DevStudio may appear on some systems.
+ Reinstalling DevStudio helped in some cases.
+ The cause of these crashes is unclear; there is no way to debug this.
+ Recompiling VisVim with DevStudio SP3 didn't help.
+ I assume it's a problem deep inside the DevStudio add-in OLE interfaces.
+ This will hopefully be fixed with DevStudio 6.
+
+
+Have fun!
+
+Heiko Erhardt
+Heiko.Erhardt@munich.netsurf.de
+
diff --git a/src/VisVim/Reg.cpp b/src/VisVim/Reg.cpp
new file mode 100644
index 000000000..b4378e545
--- /dev/null
+++ b/src/VisVim/Reg.cpp
@@ -0,0 +1,56 @@
+#include "stdafx.h"
+
+// Returns key for HKEY_CURRENT_USER\"Software"\Company\AppName
+// creating it if it doesn't exist
+// responsibility of the caller to call RegCloseKey() on the returned HKEY
+//
+HKEY GetAppKey (char* AppName)
+{
+ HKEY hAppKey = NULL;
+ HKEY hSoftKey = NULL;
+ if (RegOpenKeyEx (HKEY_CURRENT_USER, "Software", 0, KEY_WRITE | KEY_READ,
+ &hSoftKey) == ERROR_SUCCESS)
+ {
+ DWORD Dummy;
+ RegCreateKeyEx (hSoftKey, AppName, 0, REG_NONE,
+ REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL,
+ &hAppKey, &Dummy);
+ }
+ if (hSoftKey)
+ RegCloseKey (hSoftKey);
+
+ return hAppKey;
+}
+
+// Returns key for
+// HKEY_CURRENT_USER\"Software"\RegistryKey\AppName\Section
+// creating it if it doesn't exist.
+// responsibility of the caller to call RegCloseKey () on the returned HKEY
+//
+HKEY GetSectionKey (HKEY hAppKey, LPCTSTR Section)
+{
+ HKEY hSectionKey = NULL;
+ DWORD Dummy;
+ RegCreateKeyEx (hAppKey, Section, 0, REG_NONE,
+ REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL,
+ &hSectionKey, &Dummy);
+ return hSectionKey;
+}
+
+int GetRegistryInt (HKEY hSectionKey, LPCTSTR Entry, int Default)
+{
+ DWORD Value;
+ DWORD Type;
+ DWORD Count = sizeof (DWORD);
+ if (RegQueryValueEx (hSectionKey, (LPTSTR) Entry, NULL, &Type,
+ (LPBYTE) &Value, &Count) == ERROR_SUCCESS)
+ return Value;
+ return Default;
+}
+
+bool WriteRegistryInt (HKEY hSectionKey, char* Entry, int nValue)
+{
+ return RegSetValueEx (hSectionKey, Entry, NULL, REG_DWORD,
+ (LPBYTE) &nValue, sizeof (nValue)) == ERROR_SUCCESS;
+}
+
diff --git a/src/VisVim/Register.bat b/src/VisVim/Register.bat
new file mode 100644
index 000000000..baef50b0f
--- /dev/null
+++ b/src/VisVim/Register.bat
@@ -0,0 +1 @@
+regsvr32.exe visvim.dll
diff --git a/src/VisVim/Resource.h b/src/VisVim/Resource.h
new file mode 100644
index 000000000..e098b386a
--- /dev/null
+++ b/src/VisVim/Resource.h
@@ -0,0 +1,29 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by VisVim.rc
+//
+#define IDS_VISVIM_LONGNAME 1
+#define IDS_VISVIM_DESCRIPTION 2
+#define IDS_CMD_DIALOG 3
+#define IDS_CMD_ENABLE 4
+#define IDS_CMD_DISABLE 5
+#define IDS_CMD_TOGGLE 6
+#define IDS_CMD_LOAD 7
+#define IDR_TOOLBAR_MEDIUM 128
+#define IDR_TOOLBAR_LARGE 129
+#define IDD_ADDINMAIN 130
+#define IDC_DEVSTUDIO_EDITOR 1000
+#define IDC_CD_SOURCE_PATH 1001
+#define IDC_CD_SOURCE_PARENT 1002
+#define IDC_CD_NONE 1003
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 131
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1004
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/VisVim/StdAfx.cpp b/src/VisVim/StdAfx.cpp
new file mode 100644
index 000000000..f4f6eb51f
--- /dev/null
+++ b/src/VisVim/StdAfx.cpp
@@ -0,0 +1,6 @@
+// Stdafx.cpp : source file that includes just the standard includes
+// VisEmacs.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+#include "atlimpl.cpp"
diff --git a/src/VisVim/StdAfx.h b/src/VisVim/StdAfx.h
new file mode 100644
index 000000000..10bfdc02b
--- /dev/null
+++ b/src/VisVim/StdAfx.h
@@ -0,0 +1,73 @@
+// Stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__AC72670E_2977_11D1_B2F3_006008040780__INCLUDED_)
+#define AFX_STDAFX_H__AC72670E_2977_11D1_B2F3_006008040780__INCLUDED_
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxdisp.h>
+
+#include <atlbase.h>
+//You may derive a class from CComModule and use it if you want to override
+//something, but do not change the name of _Module
+extern CComModule _Module;
+
+#include <atlcom.h>
+
+// Developer Studio Object Model
+#include <ObjModel\addauto.h>
+#include <ObjModel\appdefs.h>
+#include <ObjModel\appauto.h>
+#include <ObjModel\blddefs.h>
+#include <ObjModel\bldauto.h>
+#include <ObjModel\textdefs.h>
+#include <ObjModel\textauto.h>
+#include <ObjModel\dbgdefs.h>
+#include <ObjModel\dbgauto.h>
+
+/////////////////////////////////////////////////////////////////////////////
+// Debugging support
+
+// Use VERIFY_OK around all calls to the Developer Studio objects which
+// you expect to return S_OK.
+// In DEBUG builds of your add-in, VERIFY_OK displays an ASSERT dialog box
+// if the expression returns an HRESULT other than S_OK. If the HRESULT
+// is a success code, the ASSERT box will display that HRESULT. If it
+// is a failure code, the ASSERT box will display that HRESULT plus the
+// error description string provided by the object which raised the error.
+// In RETAIL builds of your add-in, VERIFY_OK just evaluates the expression
+// and ignores the returned HRESULT.
+
+#ifdef _DEBUG
+
+void GetLastErrorDescription (CComBSTR & bstr); // Defined in VisVim.cpp
+#define VERIFY_OK(f) \
+ { \
+ HRESULT hr = (f); \
+ if (hr != S_OK) \
+ { \
+ if (FAILED(hr)) \
+ { \
+ CComBSTR bstr; \
+ GetLastErrorDescription(bstr); \
+ _RPTF2(_CRT_ASSERT, "Object call returned %lx\n\n%S", hr, (BSTR) bstr); \
+ } \
+ else \
+ _RPTF1(_CRT_ASSERT, "Object call returned %lx", hr); \
+ } \
+ }
+
+#else //_DEBUG
+
+#define VERIFY_OK(f) (f);
+
+#endif //_DEBUG
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__AC72670E_2977_11D1_B2F3_006008040780__INCLUDED)
diff --git a/src/VisVim/UnRegist.bat b/src/VisVim/UnRegist.bat
new file mode 100644
index 000000000..9ea105d26
--- /dev/null
+++ b/src/VisVim/UnRegist.bat
@@ -0,0 +1 @@
+regsvr32.exe -unregister visvim.dll
diff --git a/src/VisVim/VisVim.cpp b/src/VisVim/VisVim.cpp
new file mode 100644
index 000000000..222925a89
--- /dev/null
+++ b/src/VisVim/VisVim.cpp
@@ -0,0 +1,152 @@
+// VisVim.cpp : Defines the initialization routines for the DLL.
+//
+
+#include "stdafx.h"
+#include <initguid.h>
+#include "VisVim.h"
+#include "DSAddIn.h"
+#include "Commands.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+
+#endif
+
+CComModule _Module;
+
+BEGIN_OBJECT_MAP (ObjectMap)
+OBJECT_ENTRY (CLSID_DSAddIn, CDSAddIn)
+END_OBJECT_MAP ()
+
+class CVisVimApp : public CWinApp
+{
+ public:
+ CVisVimApp ();
+
+ //{{AFX_VIRTUAL(CVisVimApp)
+ public:
+ virtual BOOL InitInstance ();
+ virtual int ExitInstance ();
+ //}}AFX_VIRTUAL
+
+ //{{AFX_MSG(CVisVimApp)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP ()
+};
+
+BEGIN_MESSAGE_MAP (CVisVimApp, CWinApp)
+//{{AFX_MSG_MAP(CVisVimApp)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP ()
+
+// The one and only CVisVimApp object
+CVisVimApp theApp;
+
+CVisVimApp::CVisVimApp ()
+{
+}
+
+BOOL CVisVimApp::InitInstance ()
+{
+ _Module.Init (ObjectMap, m_hInstance);
+ return CWinApp::InitInstance ();
+}
+
+int CVisVimApp::ExitInstance ()
+{
+ _Module.Term ();
+ return CWinApp::ExitInstance ();
+}
+
+// Special entry points required for inproc servers
+//
+
+STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID * ppv)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return _Module.GetClassObject (rclsid, riid, ppv);
+}
+
+STDAPI DllCanUnloadNow (void)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ return (AfxDllCanUnloadNow () == S_OK && _Module.GetLockCount () == 0)
+ ? S_OK : S_FALSE;
+}
+
+// By exporting DllRegisterServer, you can use regsvr32.exe
+//
+STDAPI DllRegisterServer (void)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+ HRESULT hRes;
+
+ // Registers object, typelib and all interfaces in typelib
+ hRes = _Module.RegisterServer (TRUE);
+ if (FAILED (hRes))
+ // Hack: When this fails we might be a normal user, while the
+ // admin already registered the module. Returning S_OK then
+ // makes it work. When the module was never registered it
+ // will soon fail in another way.
+ // old code: return hRes;
+ return S_OK;
+
+ _ATL_OBJMAP_ENTRY *pEntry = _Module.m_pObjMap;
+ CRegKey key;
+ LONG lRes = key.Open (HKEY_CLASSES_ROOT, _T ("CLSID"));
+
+ if (lRes == ERROR_SUCCESS)
+ {
+ USES_CONVERSION;
+ LPOLESTR lpOleStr;
+
+ StringFromCLSID (*pEntry->pclsid, &lpOleStr);
+ LPTSTR lpsz = OLE2T (lpOleStr);
+
+ lRes = key.Open (key, lpsz);
+ if (lRes == ERROR_SUCCESS)
+ {
+ CString strDescription;
+
+ strDescription.LoadString (IDS_VISVIM_DESCRIPTION);
+ key.SetKeyValue (_T ("Description"), strDescription);
+ }
+ CoTaskMemFree (lpOleStr);
+ }
+
+ if (lRes != ERROR_SUCCESS)
+ hRes = HRESULT_FROM_WIN32 (lRes);
+
+ return hRes;
+
+}
+
+// DllUnregisterServer - Removes entries from the system registry
+//
+STDAPI DllUnregisterServer (void)
+{
+ AFX_MANAGE_STATE (AfxGetStaticModuleState ());
+
+ HRESULT hRes = S_OK;
+ _Module.UnregisterServer ();
+ return hRes;
+}
+
+
+// Debugging support
+
+// GetLastErrorDescription is used in the implementation of the VERIFY_OK
+// macro, defined in stdafx.h.
+
+#ifdef _DEBUG
+
+void GetLastErrorDescription (CComBSTR & bstr)
+{
+ CComPtr < IErrorInfo > pErrorInfo;
+ if (GetErrorInfo (0, &pErrorInfo) == S_OK)
+ pErrorInfo->GetDescription (&bstr);
+}
+
+#endif //_DEBUG
diff --git a/src/VisVim/VisVim.def b/src/VisVim/VisVim.def
new file mode 100644
index 000000000..023d478e7
--- /dev/null
+++ b/src/VisVim/VisVim.def
@@ -0,0 +1,11 @@
+; VisVim.def : Declares the module parameters for the DLL.
+
+LIBRARY "VISVIM"
+DESCRIPTION 'VISVIM Windows Dynamic Link Library'
+
+EXPORTS
+ ; Explicit exports can go here
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
diff --git a/src/VisVim/VisVim.dll b/src/VisVim/VisVim.dll
new file mode 100644
index 000000000..017b41780
--- /dev/null
+++ b/src/VisVim/VisVim.dll
Binary files differ
diff --git a/src/VisVim/VisVim.h b/src/VisVim/VisVim.h
new file mode 100644
index 000000000..775977878
--- /dev/null
+++ b/src/VisVim/VisVim.h
@@ -0,0 +1,33 @@
+// VisVIM.h : main header file for the VisVim DLL
+//
+
+#if !defined(AFX_VISVIM_H__AC72670B_2977_11D1_B2F3_006008040780__INCLUDED_)
+#define AFX_VISVIM_H__AC72670B_2977_11D1_B2F3_006008040780__INCLUDED_
+
+#ifndef __AFXWIN_H__
+#error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // Main symbols
+
+#include <ObjModel\addguid.h>
+#include <ObjModel\appguid.h>
+#include <ObjModel\bldguid.h>
+#include <ObjModel\textguid.h>
+#include <ObjModel\dbgguid.h>
+
+//
+// Prototypes
+//
+
+HKEY GetAppKey (char* AppName);
+HKEY GetSectionKey (HKEY hAppKey, LPCTSTR Section);
+int GetRegistryInt (HKEY hSectionKey, LPCTSTR Entry, int Default);
+bool WriteRegistryInt (HKEY hSectionKey, char* Entry, int nValue);
+void ReportLastError (HRESULT Err);
+void ReportInternalError (char* Fct);
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_VISVIM_H__AC72670B_2977_11D1_B2F3_006008040780__INCLUDED)
diff --git a/src/VisVim/VisVim.mak b/src/VisVim/VisVim.mak
new file mode 100644
index 000000000..30a9cf41f
--- /dev/null
+++ b/src/VisVim/VisVim.mak
@@ -0,0 +1,205 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.00
+# ** DO NOT EDIT **
+#
+# When Who What
+# 1999-08-01 Anon Original VisVim.dsp
+# 2001-08-08 W.Briscoe Back-ported to a condensed VC4 Makefile
+# Reduced inter-dependency of Release and Debug builds.
+#
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+!IF "$(CFG)" == ""
+CFG=VisVim - Win32 Release
+!MESSAGE No configuration specified. Defaulting to VisVim - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "VisVim - Win32 Release" && "$(CFG)" != "VisVim - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "VisVim.mak" CFG="VisVim - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "VisVim - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "VisVim - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+DEL_TREE = rmdir /s /q
+!ELSE
+NULL=nul
+DEL_TREE = deltree /y
+!ENDIF
+# Begin Project
+# PROP Target_Last_Scanned "VisVim - Win32 Release"
+# PROP Use_MFC 2
+CPP=cl.exe
+RSC=rc.exe
+LINK32=link.exe
+
+!IF "$(CFG)" == "VisVim - Win32 Release"
+
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release"
+# PROP Intermediate_Dir ".\Release"
+# PROP Target_Dir ""
+OUTDIR=.\Release
+INTDIR=.\Release
+CPP_OBJS=.\Release/
+
+# ADD CPP /MD /O2 /D "NDEBUG" /I.\Release
+CPP_PROJ= /MD /O2 /D "NDEBUG" /I.\Release
+# ADD RSC /d "NDEBUG
+RSC_PROJ= /d "NDEBUG"
+# ADD LINK32 /pdb:none
+LINK32_FLAGS=/pdb:none
+
+!ELSEIF "$(CFG)" == "VisVim - Win32 Debug"
+
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug"
+# PROP Intermediate_Dir ".\Debug"
+# PROP Target_Dir ""
+OUTDIR=.\Debug
+INTDIR=.\Debug
+CPP_OBJS=.\Debug/
+
+# ADD CPP /MDd /Gm /Zi /Od /D "_DEBUG" /I.\Debug
+CPP_PROJ= /MDd /Gm /Zi /Od /D "_DEBUG" /I.\Debug /Fd"$(INTDIR)/"
+MTL_PROJ= /D "_DEBUG"
+# ADD RSC /d "_DEBUG
+RSC_PROJ= /d "_DEBUG"
+# ADD LINK32 /debug /pdbtype:sept /pdb:".\Debug/VisVim.pdb"
+LINK32_FLAGS=/debug /pdbtype:sept /pdb:"$(OUTDIR)/VisVim.pdb"
+
+!ENDIF
+
+# ADD CPP /nologo /W3 /GX /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_USRDLL" /c
+CPP_PROJ=$(CPP_PROJ) /nologo /W3 /GX /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_USRDLL" /c /Fo"$(INTDIR)/"
+# ADD RSC /l 0x409 /d "_AFXDLL"
+RSC_PROJ=$(RSC_PROJ) /l 0x409 /d "_AFXDLL" /fo"$(INTDIR)/VisVim.res"
+# ADD LINK32 /nologo /subsystem:windows /dll /machine:I386 /incremental:no
+LINK32_FLAGS=$(LINK32_FLAGS) /nologo /subsystem:windows /dll /machine:I386\
+ /incremental:no /def:".\VisVim.def"\
+ /out:"$(OUTDIR)/VisVim.dll" /implib:"$(OUTDIR)/VisVim.lib"
+
+ALL : "$(OUTDIR)\VisVim.dll"
+
+CLEAN :
+ -@if exist "$(INTDIR)/$(NULL)" $(DEL_TREE) "$(INTDIR)"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+LINK32_OBJS= \
+ "$(INTDIR)/VisVim.res" \
+ "$(INTDIR)/VisVim.obj" \
+ "$(INTDIR)/StdAfx.obj" \
+ "$(INTDIR)/Reg.obj" \
+ "$(INTDIR)/DSAddIn.obj" \
+ "$(INTDIR)/OleAut.obj" \
+ "$(INTDIR)/Commands.obj"
+
+"$(OUTDIR)\VisVim.dll" : "$(OUTDIR)" ".\VisVim.def" $(LINK32_OBJS)
+ $(LINK32) $(LINK32_FLAGS) $(LINK32_OBJS)
+
+{.}.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+{.}.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+# Begin Target
+
+# Name "VisVim - Win32 Release"
+# Name "VisVim - Win32 Debug"
+
+# Begin Source File
+
+SOURCE=.\VisVim.cpp
+
+"$(INTDIR)\VisVim.obj" : $(SOURCE) "$(INTDIR)"
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\VisVim.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\VisVim.odl
+
+!IF "$(CFG)" == "VisVim - Win32 Release"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build
+
+"$(INTDIR)\VisVim.tlb" : $(SOURCE) "$(INTDIR)"
+ midl /nologo /mktyplib203 /win32 /tlb VisVim.tlb /h VSVTypes.h .\VisVim.odl /out .\Release /D "NDEBUG"
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "VisVim - Win32 Debug"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build
+
+"$(INTDIR)\VisVim.tlb" : $(SOURCE) "$(INTDIR)"
+ midl /nologo /mktyplib203 /win32 /tlb VisVim.tlb /h VSVTypes.h .\VisVim.odl /out .\Debug /D "_DEBUG"
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+
+"$(INTDIR)\StdAfx.obj" : $(SOURCE) "$(INTDIR)"
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\VisVim.rc
+
+"$(INTDIR)\VisVim.res" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\VisVim.tlb"
+ $(RSC) $(RSC_PROJ) /i "$(INTDIR)" $(SOURCE)
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\Reg.cpp
+
+"$(INTDIR)\Reg.obj" : $(SOURCE) "$(INTDIR)"
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\DSAddIn.cpp
+
+"$(INTDIR)\DSAddIn.obj" : $(SOURCE) "$(INTDIR)"
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\OleAut.cpp
+
+"$(INTDIR)\OleAut.obj" : $(SOURCE) "$(INTDIR)"
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\Commands.cpp
+
+"$(INTDIR)\Commands.obj" : $(SOURCE) "$(INTDIR)"
+
+# End Source File
+# End Target
+# End Project
diff --git a/src/VisVim/VisVim.odl b/src/VisVim/VisVim.odl
new file mode 100644
index 000000000..0491b8f34
--- /dev/null
+++ b/src/VisVim/VisVim.odl
@@ -0,0 +1,61 @@
+// VisVim.odl : type library source for VisVim.dll
+
+// This file will be processed by the Make Type Library (mktyplib) tool to
+// produce the type library (VisVim.tlb).
+
+[ uuid(AC726707-2977-11D1-B2F3-006008040780), version(1.0),
+ helpstring ("VisVim Developer Studio Add-in") ]
+library VisVim
+{
+ importlib("stdole32.tlb");
+ importlib("devshl.dll");
+ importlib("ide\devdbg.pkg");
+
+
+ // Dual interface for CCommands
+ //
+ // All commands that your add-in adds to DevStudio
+ // must appear in this interface. You may use the
+ // ClassView to add methods to this interface, which
+ // will cause stub implementations of those methods to
+ // appear in your CCommands class.
+
+ [ uuid(AC726703-2977-11D1-B2F3-006008040780),
+ oleautomation,
+ dual
+ ]
+
+ interface ICommands : IDispatch
+ {
+ // methods
+ [id(1)]
+ HRESULT VisVimDialog();
+ HRESULT VisVimEnable();
+ HRESULT VisVimDisable();
+ HRESULT VisVimToggle();
+ HRESULT VisVimLoad();
+ };
+
+ // Class information for CCommands
+
+ [ uuid(AC726704-2977-11D1-B2F3-006008040780) ]
+ coclass Commands
+ {
+ [default] interface ICommands;
+ };
+
+ [ hidden, uuid(AC726705-2977-11D1-B2F3-006008040780) ]
+ coclass ApplicationEvents
+ {
+ [default] interface IApplicationEvents;
+ }
+
+ [ hidden, uuid(AC726706-2977-11D1-B2F3-006008040780) ]
+ coclass DebuggerEvents
+ {
+ [default] interface IDebuggerEvents;
+ }
+
+ //{{AFX_APPEND_ODL}}
+ //}}AFX_APPEND_ODL}}
+};
diff --git a/src/VisVim/VisVim.rc b/src/VisVim/VisVim.rc
new file mode 100644
index 000000000..f227e53cb
--- /dev/null
+++ b/src/VisVim/VisVim.rc
@@ -0,0 +1,199 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Englisch (USA) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#endif\r\n"
+ "1 TYPELIB ""VisVim.tlb""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDR_TOOLBAR_MEDIUM BITMAP MOVEABLE PURE "res\\ToolbarM.bmp"
+IDR_TOOLBAR_LARGE BITMAP MOVEABLE PURE "res\\ToolbarL.bmp"
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,1,0,1
+ PRODUCTVERSION 1,1,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "\0"
+ VALUE "FileDescription", "VisVim DLL\0"
+ VALUE "FileVersion", "1, 1, 0, 1\0"
+ VALUE "InternalName", "VisVim\0"
+ VALUE "LegalCopyright", "Copyright (C) 1998\0"
+ VALUE "OriginalFilename", "VisVim.DLL\0"
+ VALUE "ProductName", "VisVim Dynamic Link Library\0"
+ VALUE "ProductVersion", "1, 1, 0, 1\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ADDINMAIN DIALOG DISCARDABLE 0, 0, 178, 124
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Vim Add-In 1.4"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "&Open file in DevStudio editor simultaneously",
+ IDC_DEVSTUDIO_EDITOR,"Button",BS_AUTOCHECKBOX | WS_GROUP |
+ WS_TABSTOP,7,7,153,10
+ GROUPBOX "Current directory",IDC_STATIC,7,35,164,58,WS_GROUP
+ CONTROL "Set to &source file path",IDC_CD_SOURCE_PATH,"Button",
+ BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,17,49,85,10
+ CONTROL "Set to &parent directory of source file path",
+ IDC_CD_SOURCE_PARENT,"Button",BS_AUTORADIOBUTTON,17,63,
+ 143,10
+ CONTROL "Do &not change",IDC_CD_NONE,"Button",BS_AUTORADIOBUTTON,
+ 17,78,63,10
+ DEFPUSHBUTTON "&Ok",IDOK,7,102,74,14,WS_GROUP
+ PUSHBUTTON "&Cancel",IDCANCEL,97,102,74,14,WS_GROUP
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_ADDINMAIN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 171
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 117
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_VISVIM_LONGNAME "Vim Developer Studio Add-In"
+ IDS_VISVIM_DESCRIPTION "Allows integration of Vim as the text editor in Developer Studio."
+ IDS_CMD_DIALOG "\nVim Add-In Dialog\nDisplays the options dialog box of the Vim Add-In\nVim Add-In Dialog"
+ IDS_CMD_ENABLE "\nEnable Vim Add-In\nEnables Vim as Visual Studio editor\nEnable Vim Add-In"
+ IDS_CMD_DISABLE "\nDisable Vim Add-In\nDisables Vim as Visual Studio editor\nDisable Vim Add-In"
+ IDS_CMD_TOGGLE "\nToggle Vim Add-In State\nToggles the enable state of the Vim Add-In\nToggle Vim Add-In State"
+ IDS_CMD_LOAD "\nVim Add-In Load Document\nLoads the current document in Vim\nVim Add-In Load Document"
+END
+
+#endif // Englisch (USA) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif
+#include "afxres.rc" // Standard components
+#endif
+1 TYPELIB "VisVim.tlb"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/VisVim/VsReadMe.txt b/src/VisVim/VsReadMe.txt
new file mode 100644
index 000000000..f480c6be4
--- /dev/null
+++ b/src/VisVim/VsReadMe.txt
@@ -0,0 +1,91 @@
+========================================================================
+ DEVELOPER STUDIO ADD-IN : VisVim
+========================================================================
+
+
+The Add-in Wizard has created this VisVim DLL for you. This DLL not only
+demonstrates the basics of creating a Developer Studio add-in, but it is also
+a starting point for writing your own add-in.
+
+An add-in mainly does two things.
+ (1) It adds commands to Developer Studio, which can then be tied
+ to keystrokes or toolbar buttons by the user or programmatically
+ by the add-in.
+ (2) It responds to events fired by Developer Studio.
+In both cases, the add-in code has access to the full Developer Studio
+Automation Object Model, and may manipulate those objects to affect the
+behavior of Developer Studio.
+
+This file contains a summary of what you will find in each of the files that
+make up your VisVim DLL.
+
+
+VisVim.h
+ This is the main header file for the DLL. It declares the
+ CVisVimApp class.
+
+VisVim.cpp
+ This is the main DLL source file. It contains the class CVisVimApp.
+ It also contains the OLE entry points required of inproc servers.
+
+VisVim.odl
+ This file contains the Object Description Language source code for the
+ type library of your DLL.
+
+VisVim.rc
+ This is a listing of all of the Microsoft Windows resources that the
+ program uses. It includes the sample toolbar bitmap that is stored
+ in the RES subdirectory. This file can be directly edited in Microsoft
+ Developer Studio.
+
+res\VisVim.rc2
+ This file contains resources that are not edited by Microsoft
+ Developer Studio. You should place all resources not
+ editable by the resource editor in this file.
+
+VisVim.def
+ This file contains information about the DLL that must be
+ provided to run with Microsoft Windows. It defines parameters
+ such as the name and description of the DLL. It also exports
+ functions from the DLL.
+
+VisVim.clw
+ This file contains information used by ClassWizard to edit existing
+ classes or add new classes. ClassWizard also uses this file to store
+ information needed to create and edit message maps and dialog data
+ maps and to create prototype member functions.
+
+/////////////////////////////////////////////////////////////////////////////
+Add-in-specific files:
+
+DSAddIn.cpp, DSAddIn.h
+ These files contain the CDSAddIn class, which implements the
+ IDSAddIn interface. This interface contains handlers
+ for connecting and disconnecting the add-in.
+
+Commands.cpp, Commands.h
+ These files contain the CCommands class, which implements your
+ command dispatch interface. This interface contains one method
+ for each command you add to Developer Studio.
+ These files also contain stub implementations of handlers for all events
+ fired by the Developer Studio Application object.
+
+OleAut.cpp
+ These files contain a general OLE automation class used to communicate
+ with vim.
+
+Reg.cpp
+ These files contain functions to access the registry.
+
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named VisVim.pch and a precompiled types file named StdAfx.obj.
+
+Resource.h
+ This is the standard header file, which defines new resource IDs.
+ Microsoft Developer Studio reads and updates this file.
+
diff --git a/src/arabic.c b/src/arabic.c
new file mode 100644
index 000000000..8c1f64c40
--- /dev/null
+++ b/src/arabic.c
@@ -0,0 +1,1168 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * arabic.c: functions for Arabic language
+ *
+ * Included by main.c, when FEAT_ARABIC & FEAT_GUI is defined.
+ *
+ * --
+ *
+ * Author: Nadim Shaikli & Isam Bayazidi
+ *
+ */
+
+static int A_is_a __ARGS((int cur_c));
+static int A_is_s __ARGS((int cur_c));
+static int A_is_f __ARGS((int cur_c));
+static int chg_c_a2s __ARGS((int cur_c));
+static int chg_c_a2i __ARGS((int cur_c));
+static int chg_c_a2m __ARGS((int cur_c));
+static int chg_c_a2f __ARGS((int cur_c));
+static int chg_c_i2m __ARGS((int cur_c));
+static int chg_c_f2m __ARGS((int cur_c));
+static int chg_c_laa2i __ARGS((int hid_c));
+static int chg_c_laa2f __ARGS((int hid_c));
+static int half_shape __ARGS((int c));
+static int A_firstc_laa __ARGS((int c1, int c));
+static int A_is_harakat __ARGS((int c));
+static int A_is_iso __ARGS((int c));
+static int A_is_formb __ARGS((int c));
+static int A_is_ok __ARGS((int c));
+static int A_is_valid __ARGS((int c));
+static int A_is_special __ARGS((int c));
+
+
+/*
+ * Returns True if c is an ISO-8859-6 shaped ARABIC letter (user entered)
+ */
+ static int
+A_is_a(cur_c)
+ int cur_c;
+{
+ switch (cur_c)
+ {
+ case a_HAMZA:
+ case a_ALEF_MADDA:
+ case a_ALEF_HAMZA_ABOVE:
+ case a_WAW_HAMZA:
+ case a_ALEF_HAMZA_BELOW:
+ case a_YEH_HAMZA:
+ case a_ALEF:
+ case a_BEH:
+ case a_TEH_MARBUTA:
+ case a_TEH:
+ case a_THEH:
+ case a_JEEM:
+ case a_HAH:
+ case a_KHAH:
+ case a_DAL:
+ case a_THAL:
+ case a_REH:
+ case a_ZAIN:
+ case a_SEEN:
+ case a_SHEEN:
+ case a_SAD:
+ case a_DAD:
+ case a_TAH:
+ case a_ZAH:
+ case a_AIN:
+ case a_GHAIN:
+ case a_TATWEEL:
+ case a_FEH:
+ case a_QAF:
+ case a_KAF:
+ case a_LAM:
+ case a_MEEM:
+ case a_NOON:
+ case a_HEH:
+ case a_WAW:
+ case a_ALEF_MAKSURA:
+ case a_YEH:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * Returns True if c is an Isolated Form-B ARABIC letter
+ */
+ static int
+A_is_s(cur_c)
+ int cur_c;
+{
+ switch (cur_c)
+ {
+ case a_s_HAMZA:
+ case a_s_ALEF_MADDA:
+ case a_s_ALEF_HAMZA_ABOVE:
+ case a_s_WAW_HAMZA:
+ case a_s_ALEF_HAMZA_BELOW:
+ case a_s_YEH_HAMZA:
+ case a_s_ALEF:
+ case a_s_BEH:
+ case a_s_TEH_MARBUTA:
+ case a_s_TEH:
+ case a_s_THEH:
+ case a_s_JEEM:
+ case a_s_HAH:
+ case a_s_KHAH:
+ case a_s_DAL:
+ case a_s_THAL:
+ case a_s_REH:
+ case a_s_ZAIN:
+ case a_s_SEEN:
+ case a_s_SHEEN:
+ case a_s_SAD:
+ case a_s_DAD:
+ case a_s_TAH:
+ case a_s_ZAH:
+ case a_s_AIN:
+ case a_s_GHAIN:
+ case a_s_FEH:
+ case a_s_QAF:
+ case a_s_KAF:
+ case a_s_LAM:
+ case a_s_MEEM:
+ case a_s_NOON:
+ case a_s_HEH:
+ case a_s_WAW:
+ case a_s_ALEF_MAKSURA:
+ case a_s_YEH:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * Returns True if c is a Final shape of an ARABIC letter
+ */
+ static int
+A_is_f(cur_c)
+ int cur_c;
+{
+ switch (cur_c)
+ {
+ case a_f_ALEF_MADDA:
+ case a_f_ALEF_HAMZA_ABOVE:
+ case a_f_WAW_HAMZA:
+ case a_f_ALEF_HAMZA_BELOW:
+ case a_f_YEH_HAMZA:
+ case a_f_ALEF:
+ case a_f_BEH:
+ case a_f_TEH_MARBUTA:
+ case a_f_TEH:
+ case a_f_THEH:
+ case a_f_JEEM:
+ case a_f_HAH:
+ case a_f_KHAH:
+ case a_f_DAL:
+ case a_f_THAL:
+ case a_f_REH:
+ case a_f_ZAIN:
+ case a_f_SEEN:
+ case a_f_SHEEN:
+ case a_f_SAD:
+ case a_f_DAD:
+ case a_f_TAH:
+ case a_f_ZAH:
+ case a_f_AIN:
+ case a_f_GHAIN:
+ case a_f_FEH:
+ case a_f_QAF:
+ case a_f_KAF:
+ case a_f_LAM:
+ case a_f_MEEM:
+ case a_f_NOON:
+ case a_f_HEH:
+ case a_f_WAW:
+ case a_f_ALEF_MAKSURA:
+ case a_f_YEH:
+ case a_f_LAM_ALEF_MADDA_ABOVE:
+ case a_f_LAM_ALEF_HAMZA_ABOVE:
+ case a_f_LAM_ALEF_HAMZA_BELOW:
+ case a_f_LAM_ALEF:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*
+ * Change shape - from ISO-8859-6/Isolated to Form-B Isolated
+ */
+ static int
+chg_c_a2s(cur_c)
+ int cur_c;
+{
+ int tempc;
+
+ switch (cur_c)
+ {
+ case a_HAMZA:
+ tempc = a_s_HAMZA;
+ break;
+ case a_ALEF_MADDA:
+ tempc = a_s_ALEF_MADDA;
+ break;
+ case a_ALEF_HAMZA_ABOVE:
+ tempc = a_s_ALEF_HAMZA_ABOVE;
+ break;
+ case a_WAW_HAMZA:
+ tempc = a_s_WAW_HAMZA;
+ break;
+ case a_ALEF_HAMZA_BELOW:
+ tempc = a_s_ALEF_HAMZA_BELOW;
+ break;
+ case a_YEH_HAMZA:
+ tempc = a_s_YEH_HAMZA;
+ break;
+ case a_ALEF:
+ tempc = a_s_ALEF;
+ break;
+ case a_TEH_MARBUTA:
+ tempc = a_s_TEH_MARBUTA;
+ break;
+ case a_DAL:
+ tempc = a_s_DAL;
+ break;
+ case a_THAL:
+ tempc = a_s_THAL;
+ break;
+ case a_REH:
+ tempc = a_s_REH;
+ break;
+ case a_ZAIN:
+ tempc = a_s_ZAIN;
+ break;
+ case a_TATWEEL: /* exceptions */
+ tempc = cur_c;
+ break;
+ case a_WAW:
+ tempc = a_s_WAW;
+ break;
+ case a_ALEF_MAKSURA:
+ tempc = a_s_ALEF_MAKSURA;
+ break;
+ case a_BEH:
+ tempc = a_s_BEH;
+ break;
+ case a_TEH:
+ tempc = a_s_TEH;
+ break;
+ case a_THEH:
+ tempc = a_s_THEH;
+ break;
+ case a_JEEM:
+ tempc = a_s_JEEM;
+ break;
+ case a_HAH:
+ tempc = a_s_HAH;
+ break;
+ case a_KHAH:
+ tempc = a_s_KHAH;
+ break;
+ case a_SEEN:
+ tempc = a_s_SEEN;
+ break;
+ case a_SHEEN:
+ tempc = a_s_SHEEN;
+ break;
+ case a_SAD:
+ tempc = a_s_SAD;
+ break;
+ case a_DAD:
+ tempc = a_s_DAD;
+ break;
+ case a_TAH:
+ tempc = a_s_TAH;
+ break;
+ case a_ZAH:
+ tempc = a_s_ZAH;
+ break;
+ case a_AIN:
+ tempc = a_s_AIN;
+ break;
+ case a_GHAIN:
+ tempc = a_s_GHAIN;
+ break;
+ case a_FEH:
+ tempc = a_s_FEH;
+ break;
+ case a_QAF:
+ tempc = a_s_QAF;
+ break;
+ case a_KAF:
+ tempc = a_s_KAF;
+ break;
+ case a_LAM:
+ tempc = a_s_LAM;
+ break;
+ case a_MEEM:
+ tempc = a_s_MEEM;
+ break;
+ case a_NOON:
+ tempc = a_s_NOON;
+ break;
+ case a_HEH:
+ tempc = a_s_HEH;
+ break;
+ case a_YEH:
+ tempc = a_s_YEH;
+ break;
+ default:
+ tempc = 0;
+ }
+
+ return tempc;
+}
+
+
+/*
+ * Change shape - from ISO-8859-6/Isolated to Initial
+ */
+ static int
+chg_c_a2i(cur_c)
+ int cur_c;
+{
+ int tempc;
+
+ switch (cur_c)
+ {
+ case a_YEH_HAMZA:
+ tempc = a_i_YEH_HAMZA;
+ break;
+ case a_HAMZA: /* exceptions */
+ tempc = a_s_HAMZA;
+ break;
+ case a_ALEF_MADDA: /* exceptions */
+ tempc = a_s_ALEF_MADDA;
+ break;
+ case a_ALEF_HAMZA_ABOVE: /* exceptions */
+ tempc = a_s_ALEF_HAMZA_ABOVE;
+ break;
+ case a_WAW_HAMZA: /* exceptions */
+ tempc = a_s_WAW_HAMZA;
+ break;
+ case a_ALEF_HAMZA_BELOW: /* exceptions */
+ tempc = a_s_ALEF_HAMZA_BELOW;
+ break;
+ case a_ALEF: /* exceptions */
+ tempc = a_s_ALEF;
+ break;
+ case a_TEH_MARBUTA: /* exceptions */
+ tempc = a_s_TEH_MARBUTA;
+ break;
+ case a_DAL: /* exceptions */
+ tempc = a_s_DAL;
+ break;
+ case a_THAL: /* exceptions */
+ tempc = a_s_THAL;
+ break;
+ case a_REH: /* exceptions */
+ tempc = a_s_REH;
+ break;
+ case a_ZAIN: /* exceptions */
+ tempc = a_s_ZAIN;
+ break;
+ case a_TATWEEL: /* exceptions */
+ tempc = cur_c;
+ break;
+ case a_WAW: /* exceptions */
+ tempc = a_s_WAW;
+ break;
+ case a_ALEF_MAKSURA: /* exceptions */
+ tempc = a_s_ALEF_MAKSURA;
+ break;
+ case a_BEH:
+ tempc = a_i_BEH;
+ break;
+ case a_TEH:
+ tempc = a_i_TEH;
+ break;
+ case a_THEH:
+ tempc = a_i_THEH;
+ break;
+ case a_JEEM:
+ tempc = a_i_JEEM;
+ break;
+ case a_HAH:
+ tempc = a_i_HAH;
+ break;
+ case a_KHAH:
+ tempc = a_i_KHAH;
+ break;
+ case a_SEEN:
+ tempc = a_i_SEEN;
+ break;
+ case a_SHEEN:
+ tempc = a_i_SHEEN;
+ break;
+ case a_SAD:
+ tempc = a_i_SAD;
+ break;
+ case a_DAD:
+ tempc = a_i_DAD;
+ break;
+ case a_TAH:
+ tempc = a_i_TAH;
+ break;
+ case a_ZAH:
+ tempc = a_i_ZAH;
+ break;
+ case a_AIN:
+ tempc = a_i_AIN;
+ break;
+ case a_GHAIN:
+ tempc = a_i_GHAIN;
+ break;
+ case a_FEH:
+ tempc = a_i_FEH;
+ break;
+ case a_QAF:
+ tempc = a_i_QAF;
+ break;
+ case a_KAF:
+ tempc = a_i_KAF;
+ break;
+ case a_LAM:
+ tempc = a_i_LAM;
+ break;
+ case a_MEEM:
+ tempc = a_i_MEEM;
+ break;
+ case a_NOON:
+ tempc = a_i_NOON;
+ break;
+ case a_HEH:
+ tempc = a_i_HEH;
+ break;
+ case a_YEH:
+ tempc = a_i_YEH;
+ break;
+ default:
+ tempc = 0;
+ }
+
+ return tempc;
+}
+
+
+/*
+ * Change shape - from ISO-8859-6/Isolated to Medial
+ */
+ static int
+chg_c_a2m(cur_c)
+ int cur_c;
+{
+ int tempc;
+
+ switch (cur_c)
+ {
+ case a_HAMZA: /* exception */
+ tempc = a_s_HAMZA;
+ break;
+ case a_ALEF_MADDA: /* exception */
+ tempc = a_f_ALEF_MADDA;
+ break;
+ case a_ALEF_HAMZA_ABOVE: /* exception */
+ tempc = a_f_ALEF_HAMZA_ABOVE;
+ break;
+ case a_WAW_HAMZA: /* exception */
+ tempc = a_f_WAW_HAMZA;
+ break;
+ case a_ALEF_HAMZA_BELOW: /* exception */
+ tempc = a_f_ALEF_HAMZA_BELOW;
+ break;
+ case a_YEH_HAMZA:
+ tempc = a_m_YEH_HAMZA;
+ break;
+ case a_ALEF: /* exception */
+ tempc = a_f_ALEF;
+ break;
+ case a_BEH:
+ tempc = a_m_BEH;
+ break;
+ case a_TEH_MARBUTA: /* exception */
+ tempc = a_f_TEH_MARBUTA;
+ break;
+ case a_TEH:
+ tempc = a_m_TEH;
+ break;
+ case a_THEH:
+ tempc = a_m_THEH;
+ break;
+ case a_JEEM:
+ tempc = a_m_JEEM;
+ break;
+ case a_HAH:
+ tempc = a_m_HAH;
+ break;
+ case a_KHAH:
+ tempc = a_m_KHAH;
+ break;
+ case a_DAL: /* exception */
+ tempc = a_f_DAL;
+ break;
+ case a_THAL: /* exception */
+ tempc = a_f_THAL;
+ break;
+ case a_REH: /* exception */
+ tempc = a_f_REH;
+ break;
+ case a_ZAIN: /* exception */
+ tempc = a_f_ZAIN;
+ break;
+ case a_SEEN:
+ tempc = a_m_SEEN;
+ break;
+ case a_SHEEN:
+ tempc = a_m_SHEEN;
+ break;
+ case a_SAD:
+ tempc = a_m_SAD;
+ break;
+ case a_DAD:
+ tempc = a_m_DAD;
+ break;
+ case a_TAH:
+ tempc = a_m_TAH;
+ break;
+ case a_ZAH:
+ tempc = a_m_ZAH;
+ break;
+ case a_AIN:
+ tempc = a_m_AIN;
+ break;
+ case a_GHAIN:
+ tempc = a_m_GHAIN;
+ break;
+ case a_TATWEEL: /* exception */
+ tempc = cur_c;
+ break;
+ case a_FEH:
+ tempc = a_m_FEH;
+ break;
+ case a_QAF:
+ tempc = a_m_QAF;
+ break;
+ case a_KAF:
+ tempc = a_m_KAF;
+ break;
+ case a_LAM:
+ tempc = a_m_LAM;
+ break;
+ case a_MEEM:
+ tempc = a_m_MEEM;
+ break;
+ case a_NOON:
+ tempc = a_m_NOON;
+ break;
+ case a_HEH:
+ tempc = a_m_HEH;
+ break;
+ case a_WAW: /* exception */
+ tempc = a_f_WAW;
+ break;
+ case a_ALEF_MAKSURA: /* exception */
+ tempc = a_f_ALEF_MAKSURA;
+ break;
+ case a_YEH:
+ tempc = a_m_YEH;
+ break;
+ default:
+ tempc = 0;
+ }
+
+ return tempc;
+}
+
+
+/*
+ * Change shape - from ISO-8859-6/Isolated to final
+ */
+ static int
+chg_c_a2f(cur_c)
+ int cur_c;
+{
+ int tempc;
+
+ /* NOTE: these encodings need to be accounted for
+
+ a_f_ALEF_MADDA;
+ a_f_ALEF_HAMZA_ABOVE;
+ a_f_ALEF_HAMZA_BELOW;
+ a_f_LAM_ALEF_MADDA_ABOVE;
+ a_f_LAM_ALEF_HAMZA_ABOVE;
+ a_f_LAM_ALEF_HAMZA_BELOW;
+ */
+
+ switch (cur_c)
+ {
+ case a_HAMZA: /* exception */
+ tempc = a_s_HAMZA;
+ break;
+ case a_ALEF_MADDA:
+ tempc = a_f_ALEF_MADDA;
+ break;
+ case a_ALEF_HAMZA_ABOVE:
+ tempc = a_f_ALEF_HAMZA_ABOVE;
+ break;
+ case a_WAW_HAMZA:
+ tempc = a_f_WAW_HAMZA;
+ break;
+ case a_ALEF_HAMZA_BELOW:
+ tempc = a_f_ALEF_HAMZA_BELOW;
+ break;
+ case a_YEH_HAMZA:
+ tempc = a_f_YEH_HAMZA;
+ break;
+ case a_ALEF:
+ tempc = a_f_ALEF;
+ break;
+ case a_BEH:
+ tempc = a_f_BEH;
+ break;
+ case a_TEH_MARBUTA:
+ tempc = a_f_TEH_MARBUTA;
+ break;
+ case a_TEH:
+ tempc = a_f_TEH;
+ break;
+ case a_THEH:
+ tempc = a_f_THEH;
+ break;
+ case a_JEEM:
+ tempc = a_f_JEEM;
+ break;
+ case a_HAH:
+ tempc = a_f_HAH;
+ break;
+ case a_KHAH:
+ tempc = a_f_KHAH;
+ break;
+ case a_DAL:
+ tempc = a_f_DAL;
+ break;
+ case a_THAL:
+ tempc = a_f_THAL;
+ break;
+ case a_REH:
+ tempc = a_f_REH;
+ break;
+ case a_ZAIN:
+ tempc = a_f_ZAIN;
+ break;
+ case a_SEEN:
+ tempc = a_f_SEEN;
+ break;
+ case a_SHEEN:
+ tempc = a_f_SHEEN;
+ break;
+ case a_SAD:
+ tempc = a_f_SAD;
+ break;
+ case a_DAD:
+ tempc = a_f_DAD;
+ break;
+ case a_TAH:
+ tempc = a_f_TAH;
+ break;
+ case a_ZAH:
+ tempc = a_f_ZAH;
+ break;
+ case a_AIN:
+ tempc = a_f_AIN;
+ break;
+ case a_GHAIN:
+ tempc = a_f_GHAIN;
+ break;
+ case a_TATWEEL: /* exception */
+ tempc = cur_c;
+ break;
+ case a_FEH:
+ tempc = a_f_FEH;
+ break;
+ case a_QAF:
+ tempc = a_f_QAF;
+ break;
+ case a_KAF:
+ tempc = a_f_KAF;
+ break;
+ case a_LAM:
+ tempc = a_f_LAM;
+ break;
+ case a_MEEM:
+ tempc = a_f_MEEM;
+ break;
+ case a_NOON:
+ tempc = a_f_NOON;
+ break;
+ case a_HEH:
+ tempc = a_f_HEH;
+ break;
+ case a_WAW:
+ tempc = a_f_WAW;
+ break;
+ case a_ALEF_MAKSURA:
+ tempc = a_f_ALEF_MAKSURA;
+ break;
+ case a_YEH:
+ tempc = a_f_YEH;
+ break;
+ default:
+ tempc = 0;
+ }
+
+ return tempc;
+}
+
+
+/*
+ * Change shape - from Initial to Medial
+ */
+ static int
+chg_c_i2m(cur_c)
+ int cur_c;
+{
+ int tempc;
+
+ switch (cur_c)
+ {
+ case a_i_YEH_HAMZA:
+ tempc = a_m_YEH_HAMZA;
+ break;
+ case a_i_BEH:
+ tempc = a_m_BEH;
+ break;
+ case a_i_TEH:
+ tempc = a_m_TEH;
+ break;
+ case a_i_THEH:
+ tempc = a_m_THEH;
+ break;
+ case a_i_JEEM:
+ tempc = a_m_JEEM;
+ break;
+ case a_i_HAH:
+ tempc = a_m_HAH;
+ break;
+ case a_i_KHAH:
+ tempc = a_m_KHAH;
+ break;
+ case a_i_SEEN:
+ tempc = a_m_SEEN;
+ break;
+ case a_i_SHEEN:
+ tempc = a_m_SHEEN;
+ break;
+ case a_i_SAD:
+ tempc = a_m_SAD;
+ break;
+ case a_i_DAD:
+ tempc = a_m_DAD;
+ break;
+ case a_i_TAH:
+ tempc = a_m_TAH;
+ break;
+ case a_i_ZAH:
+ tempc = a_m_ZAH;
+ break;
+ case a_i_AIN:
+ tempc = a_m_AIN;
+ break;
+ case a_i_GHAIN:
+ tempc = a_m_GHAIN;
+ break;
+ case a_i_FEH:
+ tempc = a_m_FEH;
+ break;
+ case a_i_QAF:
+ tempc = a_m_QAF;
+ break;
+ case a_i_KAF:
+ tempc = a_m_KAF;
+ break;
+ case a_i_LAM:
+ tempc = a_m_LAM;
+ break;
+ case a_i_MEEM:
+ tempc = a_m_MEEM;
+ break;
+ case a_i_NOON:
+ tempc = a_m_NOON;
+ break;
+ case a_i_HEH:
+ tempc = a_m_HEH;
+ break;
+ case a_i_YEH:
+ tempc = a_m_YEH;
+ break;
+ default:
+ tempc = 0;
+ }
+
+ return tempc;
+}
+
+
+/*
+ * Change shape - from Final to Medial
+ */
+ static int
+chg_c_f2m(cur_c)
+ int cur_c;
+{
+ int tempc;
+
+ switch (cur_c)
+ {
+ /* NOTE: these encodings are multi-positional, no ?
+ case a_f_ALEF_MADDA:
+ case a_f_ALEF_HAMZA_ABOVE:
+ case a_f_ALEF_HAMZA_BELOW:
+ */
+ case a_f_YEH_HAMZA:
+ tempc = a_m_YEH_HAMZA;
+ break;
+ case a_f_WAW_HAMZA: /* exceptions */
+ case a_f_ALEF:
+ case a_f_TEH_MARBUTA:
+ case a_f_DAL:
+ case a_f_THAL:
+ case a_f_REH:
+ case a_f_ZAIN:
+ case a_f_WAW:
+ case a_f_ALEF_MAKSURA:
+ tempc = cur_c;
+ break;
+ case a_f_BEH:
+ tempc = a_m_BEH;
+ break;
+ case a_f_TEH:
+ tempc = a_m_TEH;
+ break;
+ case a_f_THEH:
+ tempc = a_m_THEH;
+ break;
+ case a_f_JEEM:
+ tempc = a_m_JEEM;
+ break;
+ case a_f_HAH:
+ tempc = a_m_HAH;
+ break;
+ case a_f_KHAH:
+ tempc = a_m_KHAH;
+ break;
+ case a_f_SEEN:
+ tempc = a_m_SEEN;
+ break;
+ case a_f_SHEEN:
+ tempc = a_m_SHEEN;
+ break;
+ case a_f_SAD:
+ tempc = a_m_SAD;
+ break;
+ case a_f_DAD:
+ tempc = a_m_DAD;
+ break;
+ case a_f_TAH:
+ tempc = a_m_TAH;
+ break;
+ case a_f_ZAH:
+ tempc = a_m_ZAH;
+ break;
+ case a_f_AIN:
+ tempc = a_m_AIN;
+ break;
+ case a_f_GHAIN:
+ tempc = a_m_GHAIN;
+ break;
+ case a_f_FEH:
+ tempc = a_m_FEH;
+ break;
+ case a_f_QAF:
+ tempc = a_m_QAF;
+ break;
+ case a_f_KAF:
+ tempc = a_m_KAF;
+ break;
+ case a_f_LAM:
+ tempc = a_m_LAM;
+ break;
+ case a_f_MEEM:
+ tempc = a_m_MEEM;
+ break;
+ case a_f_NOON:
+ tempc = a_m_NOON;
+ break;
+ case a_f_HEH:
+ tempc = a_m_HEH;
+ break;
+ case a_f_YEH:
+ tempc = a_m_YEH;
+ break;
+ /* NOTE: these encodings are multi-positional, no ?
+ case a_f_LAM_ALEF_MADDA_ABOVE:
+ case a_f_LAM_ALEF_HAMZA_ABOVE:
+ case a_f_LAM_ALEF_HAMZA_BELOW:
+ case a_f_LAM_ALEF:
+ */
+ default:
+ tempc = 0;
+ }
+
+ return tempc;
+}
+
+
+/*
+ * Change shape - from Combination (2 char) to an Isolated
+ */
+ static int
+chg_c_laa2i(hid_c)
+ int hid_c;
+{
+ int tempc;
+
+ switch (hid_c)
+ {
+ case a_ALEF_MADDA:
+ tempc = a_s_LAM_ALEF_MADDA_ABOVE;
+ break;
+ case a_ALEF_HAMZA_ABOVE:
+ tempc = a_s_LAM_ALEF_HAMZA_ABOVE;
+ break;
+ case a_ALEF_HAMZA_BELOW:
+ tempc = a_s_LAM_ALEF_HAMZA_BELOW;
+ break;
+ case a_ALEF:
+ tempc = a_s_LAM_ALEF;
+ break;
+ default:
+ tempc = 0;
+ }
+
+ return tempc;
+}
+
+
+/*
+ * Change shape - from Combination-Isolated to Final
+ */
+ static int
+chg_c_laa2f(hid_c)
+ int hid_c;
+{
+ int tempc;
+
+ switch (hid_c)
+ {
+ case a_ALEF_MADDA:
+ tempc = a_f_LAM_ALEF_MADDA_ABOVE;
+ break;
+ case a_ALEF_HAMZA_ABOVE:
+ tempc = a_f_LAM_ALEF_HAMZA_ABOVE;
+ break;
+ case a_ALEF_HAMZA_BELOW:
+ tempc = a_f_LAM_ALEF_HAMZA_BELOW;
+ break;
+ case a_ALEF:
+ tempc = a_f_LAM_ALEF;
+ break;
+ default:
+ tempc = 0;
+ }
+
+ return tempc;
+}
+
+/*
+ * Do "half-shaping" on character "c". Return zero if no shaping.
+ */
+ static int
+half_shape(c)
+ int c;
+{
+ if (A_is_a(c))
+ return chg_c_a2i(c);
+ if (A_is_valid(c) && A_is_f(c))
+ return chg_c_f2m(c);
+ return 0;
+}
+
+/*
+ * Do Arabic shaping on character "c". Returns the shaped character.
+ * out: "ccp" points to the first byte of the character to be shaped.
+ * in/out: "c1p" points to the first composing char for "c".
+ * in: "prev_c" is the previous character (not shaped)
+ * in: "prev_c1" is the first composing char for the previous char
+ * (not shaped)
+ * in: "next_c" is the next character (not shaped).
+ */
+ int
+arabic_shape(c, ccp, c1p, prev_c, prev_c1, next_c)
+ int c;
+ int *ccp;
+ int *c1p;
+ int prev_c;
+ int prev_c1;
+ int next_c;
+{
+ int curr_c;
+ int shape_c;
+ int curr_laa;
+ int prev_laa;
+
+ /* Deal only with Arabic character, pass back all others */
+ if (!A_is_ok(c))
+ return c;
+
+ /* half-shape current and previous character */
+ shape_c = half_shape(prev_c);
+
+ /* Save away current character */
+ curr_c = c;
+
+ curr_laa = A_firstc_laa(c, *c1p);
+ prev_laa = A_firstc_laa(prev_c, prev_c1);
+
+ if (curr_laa)
+ {
+ if (A_is_valid(prev_c) && !A_is_f(shape_c)
+ && !A_is_s(shape_c) && !prev_laa)
+ curr_c = chg_c_laa2f(curr_laa);
+ else
+ curr_c = chg_c_laa2i(curr_laa);
+
+ /* Remove the composing character */
+ *c1p = 0;
+ }
+ else if (!A_is_valid(prev_c) && A_is_valid(next_c))
+ curr_c = chg_c_a2i(c);
+ else if (!shape_c || A_is_f(shape_c) || A_is_s(shape_c) || prev_laa)
+ curr_c = A_is_valid(next_c) ? chg_c_a2i(c) : chg_c_a2s(c);
+ else if (A_is_valid(next_c))
+ curr_c = A_is_iso(c) ? chg_c_a2m(c) : chg_c_i2m(c);
+ else if (A_is_valid(prev_c))
+ curr_c = chg_c_a2f(c);
+ else
+ curr_c = chg_c_a2s(c);
+
+ /* Sanity check -- curr_c should, in the future, never be 0.
+ * We should, in the future, insert a fatal error here. */
+ if (curr_c == NUL)
+ curr_c = c;
+
+ if (curr_c != c && ccp != NULL)
+ {
+ char_u buf[MB_MAXBYTES];
+
+ /* Update the first byte of the character. */
+ (*mb_char2bytes)(curr_c, buf);
+ *ccp = buf[0];
+ }
+
+ /* Return the shaped character */
+ return curr_c;
+}
+
+
+/*
+ * A_firstc_laa returns first character of LAA combination if it exists
+ */
+ static int
+A_firstc_laa(c, c1)
+ int c; /* base character */
+ int c1; /* first composing character */
+{
+ if (c1 != NUL && c == a_LAM && !A_is_harakat(c1))
+ return c1;
+ return 0;
+}
+
+
+/*
+ * A_is_harakat returns TRUE if 'c' is an Arabic Harakat character
+ * (harakat/tanween)
+ */
+ static int
+A_is_harakat(c)
+ int c;
+{
+ return (c >= a_FATHATAN && c <= a_SUKUN);
+}
+
+
+/*
+ * A_is_iso returns TRUE if 'c' is an Arabic ISO-8859-6 character
+ * (alphabet/number/punctuation)
+ */
+ static int
+A_is_iso(c)
+ int c;
+{
+ return ((c >= a_HAMZA && c <= a_GHAIN)
+ || (c >= a_TATWEEL && c <= a_HAMZA_BELOW)
+ || c == a_MINI_ALEF);
+}
+
+
+/*
+ * A_is_formb returns TRUE if 'c' is an Arabic 10646-1 FormB character
+ * (alphabet/number/punctuation)
+ */
+ static int
+A_is_formb(c)
+ int c;
+{
+ return ((c >= a_s_FATHATAN && c <= a_s_DAMMATAN)
+ || c == a_s_KASRATAN
+ || (c >= a_s_FATHA && c <= a_f_LAM_ALEF)
+ || c == a_BYTE_ORDER_MARK);
+}
+
+
+/*
+ * A_is_ok returns TRUE if 'c' is an Arabic 10646 (8859-6 or Form-B)
+ */
+ static int
+A_is_ok(c)
+ int c;
+{
+ return (A_is_iso(c) || A_is_formb(c));
+}
+
+
+/*
+ * A_is_valid returns TRUE if 'c' is an Arabic 10646 (8859-6 or Form-B)
+ * with some exceptions/exclusions
+ */
+ static int
+A_is_valid(c)
+ int c;
+{
+ return (A_is_ok(c) && !A_is_special(c));
+}
+
+
+/*
+ * A_is_special returns TRUE if 'c' is not a special Arabic character.
+ * Specials don't adhere to most of the rules.
+ */
+ static int
+A_is_special(c)
+ int c;
+{
+ return (c == a_HAMZA || c == a_s_HAMZA);
+}
diff --git a/src/arabic.h b/src/arabic.h
new file mode 100644
index 000000000..7328fd226
--- /dev/null
+++ b/src/arabic.h
@@ -0,0 +1,258 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * Arabic characters are catagorized into following types:
+ *
+ * Isolated - iso-8859-6 form char denoted with a_*
+ * Initial - unicode form-B start char denoted with a_i_*
+ * Medial - unicode form-B middle char denoted with a_m_*
+ * Final - unicode form-B final char denoted with a_f_*
+ * Stand-Alone - unicode form-B isolated char denoted with a_s_* (NOT USED)
+ *
+ * --
+ *
+ * Author: Nadim Shaikli & Isam Bayazidi
+ * - (based on Unicode)
+ *
+ */
+
+/*
+ * Arabic ISO-10646-1 character set definition
+ */
+
+/*
+ * Arabic ISO-8859-6 (subset of 10646; 0600 - 06FF)
+ */
+#define a_COMMA 0x060C
+#define a_SEMICOLON 0x061B
+#define a_QUESTION 0x061F
+#define a_HAMZA 0x0621
+#define a_ALEF_MADDA 0x0622
+#define a_ALEF_HAMZA_ABOVE 0x0623
+#define a_WAW_HAMZA 0x0624
+#define a_ALEF_HAMZA_BELOW 0x0625
+#define a_YEH_HAMZA 0x0626
+#define a_ALEF 0x0627
+#define a_BEH 0x0628
+#define a_TEH_MARBUTA 0x0629
+#define a_TEH 0x062a
+#define a_THEH 0x062b
+#define a_JEEM 0x062c
+#define a_HAH 0x062d
+#define a_KHAH 0x062e
+#define a_DAL 0x062f
+#define a_THAL 0x0630
+#define a_REH 0x0631
+#define a_ZAIN 0x0632
+#define a_SEEN 0x0633
+#define a_SHEEN 0x0634
+#define a_SAD 0x0635
+#define a_DAD 0x0636
+#define a_TAH 0x0637
+#define a_ZAH 0x0638
+#define a_AIN 0x0639
+#define a_GHAIN 0x063a
+#define a_TATWEEL 0x0640
+#define a_FEH 0x0641
+#define a_QAF 0x0642
+#define a_KAF 0x0643
+#define a_LAM 0x0644
+#define a_MEEM 0x0645
+#define a_NOON 0x0646
+#define a_HEH 0x0647
+#define a_WAW 0x0648
+#define a_ALEF_MAKSURA 0x0649
+#define a_YEH 0x064a
+
+#define a_FATHATAN 0x064b
+#define a_DAMMATAN 0x064c
+#define a_KASRATAN 0x064d
+#define a_FATHA 0x064e
+#define a_DAMMA 0x064f
+#define a_KASRA 0x0650
+#define a_SHADDA 0x0651
+#define a_SUKUN 0x0652
+
+#define a_MADDA_ABOVE 0x0653
+#define a_HAMZA_ABOVE 0x0654
+#define a_HAMZA_BELOW 0x0655
+
+#define a_ZERO 0x0660
+#define a_ONE 0x0661
+#define a_TWO 0x0662
+#define a_THREE 0x0663
+#define a_FOUR 0x0664
+#define a_FIVE 0x0665
+#define a_SIX 0x0666
+#define a_SEVEN 0x0667
+#define a_EIGHT 0x0668
+#define a_NINE 0x0669
+#define a_PERCENT 0x066a
+#define a_DECIMAL 0x066b
+#define a_THOUSANDS 0x066c
+#define a_STAR 0x066d
+#define a_MINI_ALEF 0x0670
+/* Rest of 8859-6 does not relate to Arabic */
+
+/*
+ * Arabic Presentation Form-B (subset of 10646; FE70 - FEFF)
+ *
+ * s -> isolated
+ * i -> initial
+ * m -> medial
+ * f -> final
+ *
+ */
+#define a_s_FATHATAN 0xfe70
+#define a_m_TATWEEL_FATHATAN 0xfe71
+#define a_s_DAMMATAN 0xfe72
+
+#define a_s_KASRATAN 0xfe74
+
+#define a_s_FATHA 0xfe76
+#define a_m_FATHA 0xfe77
+#define a_s_DAMMA 0xfe78
+#define a_m_DAMMA 0xfe79
+#define a_s_KASRA 0xfe7a
+#define a_m_KASRA 0xfe7b
+#define a_s_SHADDA 0xfe7c
+#define a_m_SHADDA 0xfe7d
+#define a_s_SUKUN 0xfe7e
+#define a_m_SUKUN 0xfe7f
+
+#define a_s_HAMZA 0xfe80
+#define a_s_ALEF_MADDA 0xfe81
+#define a_f_ALEF_MADDA 0xfe82
+#define a_s_ALEF_HAMZA_ABOVE 0xfe83
+#define a_f_ALEF_HAMZA_ABOVE 0xfe84
+#define a_s_WAW_HAMZA 0xfe85
+#define a_f_WAW_HAMZA 0xfe86
+#define a_s_ALEF_HAMZA_BELOW 0xfe87
+#define a_f_ALEF_HAMZA_BELOW 0xfe88
+#define a_s_YEH_HAMZA 0xfe89
+#define a_f_YEH_HAMZA 0xfe8a
+#define a_i_YEH_HAMZA 0xfe8b
+#define a_m_YEH_HAMZA 0xfe8c
+#define a_s_ALEF 0xfe8d
+#define a_f_ALEF 0xfe8e
+#define a_s_BEH 0xfe8f
+#define a_f_BEH 0xfe90
+#define a_i_BEH 0xfe91
+#define a_m_BEH 0xfe92
+#define a_s_TEH_MARBUTA 0xfe93
+#define a_f_TEH_MARBUTA 0xfe94
+#define a_s_TEH 0xfe95
+#define a_f_TEH 0xfe96
+#define a_i_TEH 0xfe97
+#define a_m_TEH 0xfe98
+#define a_s_THEH 0xfe99
+#define a_f_THEH 0xfe9a
+#define a_i_THEH 0xfe9b
+#define a_m_THEH 0xfe9c
+#define a_s_JEEM 0xfe9d
+#define a_f_JEEM 0xfe9e
+#define a_i_JEEM 0xfe9f
+#define a_m_JEEM 0xfea0
+#define a_s_HAH 0xfea1
+#define a_f_HAH 0xfea2
+#define a_i_HAH 0xfea3
+#define a_m_HAH 0xfea4
+#define a_s_KHAH 0xfea5
+#define a_f_KHAH 0xfea6
+#define a_i_KHAH 0xfea7
+#define a_m_KHAH 0xfea8
+#define a_s_DAL 0xfea9
+#define a_f_DAL 0xfeaa
+#define a_s_THAL 0xfeab
+#define a_f_THAL 0xfeac
+#define a_s_REH 0xfead
+#define a_f_REH 0xfeae
+#define a_s_ZAIN 0xfeaf
+#define a_f_ZAIN 0xfeb0
+#define a_s_SEEN 0xfeb1
+#define a_f_SEEN 0xfeb2
+#define a_i_SEEN 0xfeb3
+#define a_m_SEEN 0xfeb4
+#define a_s_SHEEN 0xfeb5
+#define a_f_SHEEN 0xfeb6
+#define a_i_SHEEN 0xfeb7
+#define a_m_SHEEN 0xfeb8
+#define a_s_SAD 0xfeb9
+#define a_f_SAD 0xfeba
+#define a_i_SAD 0xfebb
+#define a_m_SAD 0xfebc
+#define a_s_DAD 0xfebd
+#define a_f_DAD 0xfebe
+#define a_i_DAD 0xfebf
+#define a_m_DAD 0xfec0
+#define a_s_TAH 0xfec1
+#define a_f_TAH 0xfec2
+#define a_i_TAH 0xfec3
+#define a_m_TAH 0xfec4
+#define a_s_ZAH 0xfec5
+#define a_f_ZAH 0xfec6
+#define a_i_ZAH 0xfec7
+#define a_m_ZAH 0xfec8
+#define a_s_AIN 0xfec9
+#define a_f_AIN 0xfeca
+#define a_i_AIN 0xfecb
+#define a_m_AIN 0xfecc
+#define a_s_GHAIN 0xfecd
+#define a_f_GHAIN 0xfece
+#define a_i_GHAIN 0xfecf
+#define a_m_GHAIN 0xfed0
+#define a_s_FEH 0xfed1
+#define a_f_FEH 0xfed2
+#define a_i_FEH 0xfed3
+#define a_m_FEH 0xfed4
+#define a_s_QAF 0xfed5
+#define a_f_QAF 0xfed6
+#define a_i_QAF 0xfed7
+#define a_m_QAF 0xfed8
+#define a_s_KAF 0xfed9
+#define a_f_KAF 0xfeda
+#define a_i_KAF 0xfedb
+#define a_m_KAF 0xfedc
+#define a_s_LAM 0xfedd
+#define a_f_LAM 0xfede
+#define a_i_LAM 0xfedf
+#define a_m_LAM 0xfee0
+#define a_s_MEEM 0xfee1
+#define a_f_MEEM 0xfee2
+#define a_i_MEEM 0xfee3
+#define a_m_MEEM 0xfee4
+#define a_s_NOON 0xfee5
+#define a_f_NOON 0xfee6
+#define a_i_NOON 0xfee7
+#define a_m_NOON 0xfee8
+#define a_s_HEH 0xfee9
+#define a_f_HEH 0xfeea
+#define a_i_HEH 0xfeeb
+#define a_m_HEH 0xfeec
+#define a_s_WAW 0xfeed
+#define a_f_WAW 0xfeee
+#define a_s_ALEF_MAKSURA 0xfeef
+#define a_f_ALEF_MAKSURA 0xfef0
+#define a_s_YEH 0xfef1
+#define a_f_YEH 0xfef2
+#define a_i_YEH 0xfef3
+#define a_m_YEH 0xfef4
+#define a_s_LAM_ALEF_MADDA_ABOVE 0xfef5
+#define a_f_LAM_ALEF_MADDA_ABOVE 0xfef6
+#define a_s_LAM_ALEF_HAMZA_ABOVE 0xfef7
+#define a_f_LAM_ALEF_HAMZA_ABOVE 0xfef8
+#define a_s_LAM_ALEF_HAMZA_BELOW 0xfef9
+#define a_f_LAM_ALEF_HAMZA_BELOW 0xfefa
+#define a_s_LAM_ALEF 0xfefb
+#define a_f_LAM_ALEF 0xfefc
+
+#define a_BYTE_ORDER_MARK 0xfeff
+
+/* Range of Arabic characters that might be shaped. */
+#define ARABIC_CHAR(c) ((c) >= a_HAMZA && (c) <= a_MINI_ALEF)
diff --git a/src/ascii.h b/src/ascii.h
new file mode 100644
index 000000000..8a344ef55
--- /dev/null
+++ b/src/ascii.h
@@ -0,0 +1,201 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * Definitions of various common control characters.
+ * For EBCDIC we have to use different values.
+ */
+
+#ifndef EBCDIC
+
+/* IF_EB(ASCII_constant, EBCDIC_constant) */
+#define IF_EB(a, b) a
+
+#define CharOrd(x) ((x) < 'a' ? (x) - 'A' : (x) - 'a')
+#define CharOrdLow(x) ((x) - 'a')
+#define CharOrdUp(x) ((x) - 'A')
+#define ROT13(c, a) (((((c) - (a)) + 13) % 26) + (a))
+
+#define NUL '\000'
+#define BELL '\007'
+#define BS '\010'
+#define TAB '\011'
+#define NL '\012'
+#define NL_STR (char_u *)"\012"
+#define FF '\014'
+#define CAR '\015' /* CR is used by Mac OS X */
+#define ESC '\033'
+#define ESC_STR (char_u *)"\033"
+#define ESC_STR_nc "\033"
+#define DEL 0x7f
+#define DEL_STR (char_u *)"\177"
+#define CSI 0x9b /* Control Sequence Introducer */
+#define CSI_STR "\233"
+#define DCS 0x90 /* Device Control String */
+#define STERM 0x9c /* String Terminator */
+
+#define POUND 0xA3
+
+#define Ctrl_chr(x) (TOUPPER_ASC(x) ^ 0x40) /* '?' -> DEL, '@' -> ^@, etc. */
+#define Meta(x) ((x) | 0x80)
+
+#define CTRL_F_STR "\006"
+#define CTRL_H_STR "\010"
+#define CTRL_V_STR "\026"
+#define CTRL_W_STR "\027"
+
+#define Ctrl_AT 0 /* @ */
+#define Ctrl_A 1
+#define Ctrl_B 2
+#define Ctrl_C 3
+#define Ctrl_D 4
+#define Ctrl_E 5
+#define Ctrl_F 6
+#define Ctrl_G 7
+#define Ctrl_H 8
+#define Ctrl_I 9
+#define Ctrl_J 10
+#define Ctrl_K 11
+#define Ctrl_L 12
+#define Ctrl_M 13
+#define Ctrl_N 14
+#define Ctrl_O 15
+#define Ctrl_P 16
+#define Ctrl_Q 17
+#define Ctrl_R 18
+#define Ctrl_S 19
+#define Ctrl_T 20
+#define Ctrl_U 21
+#define Ctrl_V 22
+#define Ctrl_W 23
+#define Ctrl_X 24
+#define Ctrl_Y 25
+#define Ctrl_Z 26
+#define Ctrl_LSB 27 /* [ Left Square Bracket */
+#define Ctrl_BSL 28 /* \ BackSLash */
+#define Ctrl_RSB 29 /* ] Right Square Bracket */
+#define Ctrl_HAT 30 /* ^ */
+#define Ctrl__ 31
+
+#else
+
+/* EBCDIC */
+
+/* IF_EB(ASCII_constant, EBCDIC_constant) */
+#define IF_EB(a, b) b
+
+/*
+ * Finding the position in the alphabet is not straightforward in EBCDIC.
+ * There are gaps in the code table.
+ * 'a' + 1 == 'b', but: 'i' + 7 == 'j' and 'r' + 8 == 's'
+ */
+#define CharOrd__(c) ((c) < ('j' - 'a') ? (c) : ((c) < ('s' - 'a') ? (c) - 7 : (c) - 7 - 8))
+#define CharOrdLow(x) (CharOrd__((x) - 'a'))
+#define CharOrdUp(x) (CharOrd__((x) - 'A'))
+#define CharOrd(x) (isupper(x) ? CharOrdUp(x) : CharOrdLow(x))
+
+#define EBCDIC_CHAR_ADD_(x) ((x) < 0?'a':(x)>25?'z':"abcdefghijklmnopqrstuvwxyz"[x])
+#define EBCDIC_CHAR_ADD(c,s) (isupper(c) ? toupper(EBCDIC_CHAR_ADD_(CharOrdUp(c)+(s))) : EBCDIC_CHAR_ADD_(CharOrdLow(c)+(s)))
+
+#define R13_(c) ("abcdefghijklmnopqrstuvwxyz"[((c) + 13) % 26])
+#define ROT13(c, a) (isupper(c) ? toupper(R13_(CharOrdUp(c))) : R13_(CharOrdLow(c)))
+
+#define NUL '\000'
+#define BELL '\x2f'
+#define BS '\x16'
+#define TAB '\x05'
+#define NL '\x15'
+#define NL_STR (char_u *)"\x15"
+#define FF '\x0C'
+#define CAR '\x0D'
+#define ESC '\x27'
+#define ESC_STR (char_u *)"\x27"
+#define ESC_STR_nc "\x27"
+#define DEL 0x07
+#define DEL_STR (char_u *)"\007"
+/* TODO: EBCDIC Code page dependent (here 1047) */
+#define CSI 0x9b /* Control Sequence Introducer */
+#define CSI_STR "\233"
+#define DCS 0x90 /* Device Control String */
+#define STERM 0x9c /* String Terminator */
+
+#define POUND '£'
+
+#define CTRL_F_STR "\056"
+#define CTRL_H_STR "\026"
+#define CTRL_V_STR "\062"
+#define CTRL_W_STR "\046"
+
+#define Ctrl_AT 0x00 /* @ */
+#define Ctrl_A 0x01
+#define Ctrl_B 0x02
+#define Ctrl_C 0x03
+#define Ctrl_D 0x37
+#define Ctrl_E 0x2D
+#define Ctrl_F 0x2E
+#define Ctrl_G 0x2F
+#define Ctrl_H 0x16
+#define Ctrl_I 0x05
+#define Ctrl_J 0x15
+#define Ctrl_K 0x0B
+#define Ctrl_L 0x0C
+#define Ctrl_M 0x0D
+#define Ctrl_N 0x0E
+#define Ctrl_O 0x0F
+#define Ctrl_P 0x10
+#define Ctrl_Q 0x11
+#define Ctrl_R 0x12
+#define Ctrl_S 0x13
+#define Ctrl_T 0x3C
+#define Ctrl_U 0x3D
+#define Ctrl_V 0x32
+#define Ctrl_W 0x26
+#define Ctrl_X 0x18
+#define Ctrl_Y 0x19
+#define Ctrl_Z 0x3F
+#define Ctrl_LSB 0x27 /* [ Left Square Bracket */
+#define Ctrl_RSB 0x1D /* ] Right Square Bracket */
+#define Ctrl_BSL 0x1C /* \ BackSLash */
+#define Ctrl_HAT 0x1E /* ^ */
+#define Ctrl__ 0x1F
+
+#define Ctrl_chr(x) (CtrlTable[(x)])
+extern char CtrlTable[];
+
+#define CtrlChar(x) ((x < ' ') ? CtrlCharTable[(x)] : 0)
+extern char CtrlCharTable[];
+
+#define MetaChar(x) ((x < ' ') ? MetaCharTable[(x)] : 0)
+extern char MetaCharTable[];
+
+#endif /* defined EBCDIC */
+
+/*
+ * Character that separates dir names in a path.
+ * For MS-DOS, WIN32 and OS/2 we use a backslash. A slash mostly works
+ * fine, but there are places where it doesn't (e.g. in a command name).
+ * For Macintosh we use a colon.
+ * For Acorn we use a dot.
+ */
+#ifdef BACKSLASH_IN_FILENAME
+# define PATHSEP psepc
+# define PATHSEPSTR pseps
+#else
+# ifdef COLON_AS_PATHSEP
+# define PATHSEP ':'
+# define PATHSEPSTR ":"
+# else
+# ifdef RISCOS
+# define PATHSEP '.'
+# define PATHSEPSTR "."
+# else
+# define PATHSEP '/'
+# define PATHSEPSTR "/"
+# endif
+# endif
+#endif
diff --git a/src/auto/configure b/src/auto/configure
new file mode 100755
index 000000000..b040a75f5
--- /dev/null
+++ b/src/auto/configure
@@ -0,0 +1,8692 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --disable-darwin Disable Darwin (Mac OS X) support."
+ac_help="$ac_help
+ --with-vim-name=NAME what to call the Vim executable"
+ac_help="$ac_help
+ --with-ex-name=NAME what to call the Ex executable"
+ac_help="$ac_help
+ --with-view-name=NAME what to call the View executable"
+ac_help="$ac_help
+ --with-global-runtime=DIR global runtime directory in 'runtimepath'"
+ac_help="$ac_help
+ --with-modified-by=NAME name of who modified a release version"
+ac_help="$ac_help
+ --with-features=TYPE tiny, small, normal, big or huge (default: normal)"
+ac_help="$ac_help
+ --with-compiledby=NAME name to show in :version message"
+ac_help="$ac_help
+ --disable-xsmp Disable XSMP session management"
+ac_help="$ac_help
+ --disable-xsmp-interact Disable XSMP interaction"
+ac_help="$ac_help
+ --enable-perlinterp Include Perl interpreter."
+ac_help="$ac_help
+ --enable-pythoninterp Include Python interpreter."
+ac_help="$ac_help
+ --with-python-config-dir=PATH Python's config directory"
+ac_help="$ac_help
+ --enable-tclinterp Include Tcl interpreter."
+ac_help="$ac_help
+ --with-tclsh=PATH which tclsh to use (default: tclsh8.0)"
+ac_help="$ac_help
+ --enable-rubyinterp Include Ruby interpreter."
+ac_help="$ac_help
+ --enable-cscope Include cscope interface."
+ac_help="$ac_help
+ --enable-workshop Include Sun Visual Workshop support."
+ac_help="$ac_help
+ --disable-netbeans Disable NetBeans integration support."
+ac_help="$ac_help
+ --enable-sniff Include Sniff interface."
+ac_help="$ac_help
+ --enable-multibyte Include multibyte editing support."
+ac_help="$ac_help
+ --enable-hangulinput Include Hangul input support."
+ac_help="$ac_help
+ --enable-xim Include XIM input support."
+ac_help="$ac_help
+ --enable-fontset Include X fontset output support."
+ac_help="$ac_help
+ --with-x use the X Window System"
+ac_help="$ac_help
+ --enable-gui[=OPTS] X11 GUI [default=auto] [OPTS=auto/no/gtk/gtk2/gnome/gnome2/motif/athena/neXtaw/beos/photon/carbon]"
+ac_help="$ac_help
+ --enable-gtk-check If auto-select GUI, check for GTK [default=yes]"
+ac_help="$ac_help
+ --enable-gtk2-check If GTK GUI, check for GTK+ 2 [default=yes]"
+ac_help="$ac_help
+ --enable-gnome-check If GTK GUI, check for GNOME [default=no]"
+ac_help="$ac_help
+ --enable-motif-check If auto-select GUI, check for Motif [default=yes]"
+ac_help="$ac_help
+ --enable-athena-check If auto-select GUI, check for Athena [default=yes]"
+ac_help="$ac_help
+ --enable-nextaw-check If auto-select GUI, check for neXtaw [default=yes]"
+ac_help="$ac_help
+ --enable-carbon-check If auto-select GUI, check for Carbon [default=yes]"
+ac_help="$ac_help
+ --with-gtk-prefix=PFX Prefix where GTK is installed (optional)"
+ac_help="$ac_help
+ --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)"
+ac_help="$ac_help
+ --disable-gtktest Do not try to compile and run a test GTK program"
+ac_help="$ac_help
+ --with-gnome-includes=DIR Specify location of GNOME headers"
+ac_help="$ac_help
+ --with-gnome-libs=DIR Specify location of GNOME libs"
+ac_help="$ac_help
+ --with-gnome Specify prefix for GNOME files"
+ac_help="$ac_help
+ --with-motif-lib=STRING Library for Motif "
+ac_help="$ac_help
+ --with-tlib=library terminal library to be used "
+ac_help="$ac_help
+ --disable-acl Don't check for ACL support."
+ac_help="$ac_help
+ --disable-gpm Don't use gpm (Linux mouse daemon)."
+ac_help="$ac_help
+ --disable-nls Don't support NLS (gettext())."
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>auto/config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=vim.h
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+cat >> confdefs.h <<\EOF
+#define UNIX 1
+EOF
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:620: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:650: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:680: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:731: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:763: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 774 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:779: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:805: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:810: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:819: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:838: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+ echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:869: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 884 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:890: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 901 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:907: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 918 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:924: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+ cat > conftest.$ac_ext <<EOF
+#line 948 "configure"
+#include "confdefs.h"
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "" >/dev/null 2>&1; then
+ :
+fi
+rm -f conftest*
+ echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
+echo "configure:958: checking for POSIXized ISC" >&5
+if test -d /etc/conf/kconfig.d &&
+ grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+ echo "$ac_t""yes" 1>&6
+ ISC=yes # If later tests want to check for ISC.
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ if test "$GCC" = yes; then
+ CC="$CC -posix"
+ else
+ CC="$CC -Xp"
+ fi
+else
+ echo "$ac_t""no" 1>&6
+ ISC=
+fi
+ for ac_prog in mawk gawk nawk awk
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:982: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AWK="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+AWK="$ac_cv_prog_AWK"
+if test -n "$AWK"; then
+ echo "$ac_t""$AWK" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$AWK" && break
+done
+
+# Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1014: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_STRIP="strip"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_STRIP" && ac_cv_prog_STRIP=":"
+fi
+fi
+STRIP="$ac_cv_prog_STRIP"
+if test -n "$STRIP"; then
+ echo "$ac_t""$STRIP" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+echo "configure:1043: checking for Cygwin environment" >&5
+if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1048 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#ifndef __CYGWIN__
+#define __CYGWIN__ __CYGWIN32__
+#endif
+return __CYGWIN__;
+; return 0; }
+EOF
+if { (eval echo configure:1059: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_cygwin=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_cygwin=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_cygwin" 1>&6
+CYGWIN=
+test "$ac_cv_cygwin" = yes && CYGWIN=yes
+echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
+echo "configure:1076: checking for mingw32 environment" >&5
+if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1081 "configure"
+#include "confdefs.h"
+
+int main() {
+return __MINGW32__;
+; return 0; }
+EOF
+if { (eval echo configure:1088: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_mingw32=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_mingw32=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_mingw32" 1>&6
+MINGW32=
+test "$ac_cv_mingw32" = yes && MINGW32=yes
+
+
+echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+echo "configure:1107: checking for executable suffix" >&5
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+ ac_cv_exeext=.exe
+else
+ rm -f conftest*
+ echo 'int main () { return 0; }' > conftest.$ac_ext
+ ac_cv_exeext=
+ if { (eval echo configure:1117: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ for file in conftest.*; do
+ case $file in
+ *.c | *.o | *.obj) ;;
+ *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
+ esac
+ done
+ else
+ { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
+ fi
+ rm -f conftest*
+ test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
+fi
+fi
+
+EXEEXT=""
+test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
+echo "$ac_t""${ac_cv_exeext}" 1>&6
+ac_exeext=$EXEEXT
+
+
+if test -z "$CFLAGS"; then
+ CFLAGS="-O"
+ test "$GCC" = yes && CFLAGS="-O2 -fno-strength-reduce -Wall"
+fi
+if test "$GCC" = yes; then
+ gccversion=`"$CC" --version | sed -e '2,$d;s/^[^0-9]*\([0-9]\.[0-9.]*\).*$/\1/g'`
+ if test "$gccversion" = "3.0.1" -o "$gccversion" = "3.0.2"; then
+ echo 'GCC 3.0.x has a bug in the optimizer, disabling "-O#"'
+ CFLAGS=`echo "$CFLAGS" | sed 's/-O[23456789]/-O/'`
+ else
+ if test "$gccversion" = "3.1" -o "$gccversion" = "3.2" -o "$gccversion" = "3.2.1" && `echo "$CFLAGS" | grep -v fno-strength-reduce >/dev/null`; then
+ echo 'GCC 3.1 and 3.2 have a bug in the optimizer, adding "-fno-strength-reduce"'
+ CFLAGS="$CFLAGS -fno-strength-reduce"
+ fi
+ fi
+fi
+
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: cannot compile a simple program, check CC and CFLAGS
+ (cross compiling doesn't work)" 1>&2; exit 1; }
+fi
+
+test "$GCC" = yes && CPP_MM=M;
+
+if test -f ./toolcheck; then
+ echo "checking for buggy tools" 1>&6
+echo "configure:1164: checking for buggy tools" >&5
+ sh ./toolcheck 1>&6
+fi
+
+OS_EXTRA_SRC=""; OS_EXTRA_OBJ=""
+
+echo $ac_n "checking for BeOS""... $ac_c" 1>&6
+echo "configure:1171: checking for BeOS" >&5
+case `uname` in
+ BeOS) OS_EXTRA_SRC=os_beos.c; OS_EXTRA_OBJ=objects/os_beos.o
+ BEOS=yes; echo "$ac_t""yes" 1>&6;;
+ *) BEOS=no; echo "$ac_t""no" 1>&6;;
+esac
+
+echo $ac_n "checking for QNX""... $ac_c" 1>&6
+echo "configure:1179: checking for QNX" >&5
+case `uname` in
+ QNX) OS_EXTRA_SRC=os_qnx.c; OS_EXTRA_OBJ=objects/os_qnx.o
+ test -z "$with_x" && with_x=no
+ QNX=yes; echo "$ac_t""yes" 1>&6;;
+ *) QNX=no; echo "$ac_t""no" 1>&6;;
+esac
+
+DEFAULT_VIMNAME=vim
+echo $ac_n "checking for Darwin (Mac OS X)""... $ac_c" 1>&6
+echo "configure:1189: checking for Darwin (Mac OS X)" >&5
+if test "`(uname) 2>/dev/null`" = Darwin; then
+ echo "$ac_t""yes" 1>&6
+
+ echo $ac_n "checking --disable-darwin argument""... $ac_c" 1>&6
+echo "configure:1194: checking --disable-darwin argument" >&5
+ # Check whether --enable-darwin or --disable-darwin was given.
+if test "${enable_darwin+set}" = set; then
+ enableval="$enable_darwin"
+ :
+else
+ enable_darwin="yes"
+fi
+
+ if test "$enable_darwin" = "yes"; then
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking if Darwin files are there""... $ac_c" 1>&6
+echo "configure:1206: checking if Darwin files are there" >&5
+ if test -f os_macosx.c; then
+ echo "$ac_t""yes" 1>&6
+ else
+ echo "$ac_t""no, Darwin support disabled" 1>&6
+ enable_darwin=no
+ fi
+ else
+ echo "$ac_t""yes, Darwin support excluded" 1>&6
+ fi
+
+ if test "$enable_darwin" = "yes"; then
+ MACOSX=yes
+ OS_EXTRA_SCR="os_macosx.c";
+ OS_EXTRA_OBJ="objects/os_macosx.o"
+ CPPFLAGS="$CPPFLAGS -DMACOS_X_UNIX -I/Developer/Headers/FlatCarbon -no-cpp-precomp"
+
+ ac_safe=`echo "Carbon/Carbon.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for Carbon/Carbon.h""... $ac_c" 1>&6
+echo "configure:1225: checking for Carbon/Carbon.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1230 "configure"
+#include "confdefs.h"
+#include <Carbon/Carbon.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1235: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ CARBON=yes
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "x$CARBON" = "xyes"; then
+ if test -z "$with_x"; then
+ with_x=no
+ DEFAULT_VIMNAME=Vim
+ fi
+ fi
+ fi
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+
+have_local_include=''
+have_local_lib=''
+if test "$GCC" = yes; then
+ echo 'void f(){}' > conftest.c
+ have_local_include=`${CC-cc} -no-cpp-precomp -c -v conftest.c 2>&1 | grep '/usr/local/include'`
+ have_local_lib=`${CC-cc} -c -v conftest.c 2>&1 | grep '/usr/local/lib'`
+ rm -f conftest.c conftest.o
+fi
+if test -z "$have_local_lib" -a -d /usr/local/lib; then
+ tt=`echo "$LDFLAGS" | sed -e 's+-L/usr/local/lib ++g' -e 's+-L/usr/local/lib$++g'`
+ if test "$tt" = "$LDFLAGS"; then
+ LDFLAGS="$LDFLAGS -L/usr/local/lib"
+ fi
+fi
+if test -z "$have_local_include" -a -d /usr/local/include; then
+ tt=`echo "$CPPFLAGS" | sed -e 's+-I/usr/local/include ++g' -e 's+-I/usr/local/include$++g'`
+ if test "$tt" = "$CPPFLAGS"; then
+ CPPFLAGS="$CPPFLAGS -I/usr/local/include"
+ fi
+fi
+
+echo $ac_n "checking --with-vim-name argument""... $ac_c" 1>&6
+echo "configure:1292: checking --with-vim-name argument" >&5
+# Check whether --with-vim-name or --without-vim-name was given.
+if test "${with_vim_name+set}" = set; then
+ withval="$with_vim_name"
+ VIMNAME="$withval"; echo "$ac_t""$VIMNAME" 1>&6
+else
+ VIMNAME="$DEFAULT_VIMNAME"; echo "$ac_t""Defaulting to $VIMNAME" 1>&6
+fi
+
+
+echo $ac_n "checking --with-ex-name argument""... $ac_c" 1>&6
+echo "configure:1303: checking --with-ex-name argument" >&5
+# Check whether --with-ex-name or --without-ex-name was given.
+if test "${with_ex_name+set}" = set; then
+ withval="$with_ex_name"
+ EXNAME="$withval"; echo "$ac_t""$EXNAME" 1>&6
+else
+ EXNAME="ex"; echo "$ac_t""Defaulting to ex" 1>&6
+fi
+
+
+echo $ac_n "checking --with-view-name argument""... $ac_c" 1>&6
+echo "configure:1314: checking --with-view-name argument" >&5
+# Check whether --with-view-name or --without-view-name was given.
+if test "${with_view_name+set}" = set; then
+ withval="$with_view_name"
+ VIEWNAME="$withval"; echo "$ac_t""$VIEWNAME" 1>&6
+else
+ VIEWNAME="view"; echo "$ac_t""Defaulting to view" 1>&6
+fi
+
+
+
+echo $ac_n "checking --with-global-runtime argument""... $ac_c" 1>&6
+echo "configure:1326: checking --with-global-runtime argument" >&5
+# Check whether --with-global-runtime or --without-global-runtime was given.
+if test "${with_global_runtime+set}" = set; then
+ withval="$with_global_runtime"
+ echo "$ac_t""$withval" 1>&6; cat >> confdefs.h <<EOF
+#define RUNTIME_GLOBAL "$withval"
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking --with-modified-by argument""... $ac_c" 1>&6
+echo "configure:1340: checking --with-modified-by argument" >&5
+# Check whether --with-modified-by or --without-modified-by was given.
+if test "${with_modified_by+set}" = set; then
+ withval="$with_modified_by"
+ echo "$ac_t""$withval" 1>&6; cat >> confdefs.h <<EOF
+#define MODIFIED_BY "$withval"
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking if character set is EBCDIC""... $ac_c" 1>&6
+echo "configure:1354: checking if character set is EBCDIC" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1356 "configure"
+#include "confdefs.h"
+
+int main() {
+ /* TryCompile function for CharSet.
+ Treat any failure as ASCII for compatibility with existing art.
+ Use compile-time rather than run-time tests for cross-compiler
+ tolerance. */
+#if '0'!=240
+make an error "Character set is not EBCDIC"
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:1369: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ # TryCompile action if true
+cf_cv_ebcdic=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ # TryCompile action if false
+cf_cv_ebcdic=no
+fi
+rm -f conftest*
+# end of TryCompile ])
+# end of CacheVal CvEbcdic
+echo "$ac_t""$cf_cv_ebcdic" 1>&6
+case "$cf_cv_ebcdic" in #(vi
+ yes) cat >> confdefs.h <<\EOF
+#define EBCDIC 1
+EOF
+
+ line_break='"\\n"'
+ ;;
+ *) line_break='"\\012"';;
+esac
+
+
+if test "$cf_cv_ebcdic" = "yes"; then
+echo $ac_n "checking for OS/390 Unix""... $ac_c" 1>&6
+echo "configure:1397: checking for OS/390 Unix" >&5
+case `uname` in
+ OS/390) OS390Unix="yes";
+ if test "$CC" = "cc"; then
+ ccm="$_CC_CCMODE"
+ ccn="CC"
+ else
+ if test "$CC" = "c89"; then
+ ccm="$_CC_C89MODE"
+ ccn="C89"
+ else
+ ccm=1
+ fi
+ fi
+ if test "$ccm" != "1"; then
+ echo ""
+ echo "------------------------------------------"
+ echo " On OS/390 Unix, the environment variable"
+ echo " __CC_${ccn}MODE must be set to \"1\"!"
+ echo " Do:"
+ echo " export _CC_${ccn}MODE=1"
+ echo " and then call configure again."
+ echo "------------------------------------------"
+ exit 1
+ fi
+ CFLAGS="$CFLAGS -D_ALL_SOURCE"; LDFLAGS="$LDFLAGS -Wl,EDIT=NO"
+ echo "$ac_t""yes" 1>&6
+ ;;
+ *) OS390Unix="no";
+ echo "$ac_t""no" 1>&6
+ ;;
+esac
+fi
+
+
+
+echo $ac_n "checking --with-features argument""... $ac_c" 1>&6
+echo "configure:1434: checking --with-features argument" >&5
+# Check whether --with-features or --without-features was given.
+if test "${with_features+set}" = set; then
+ withval="$with_features"
+ features="$withval"; echo "$ac_t""$features" 1>&6
+else
+ features="normal"; echo "$ac_t""Defaulting to normal" 1>&6
+fi
+
+
+dovimdiff=""
+dogvimdiff=""
+case "$features" in
+ tiny) cat >> confdefs.h <<\EOF
+#define FEAT_TINY 1
+EOF
+ ;;
+ small) cat >> confdefs.h <<\EOF
+#define FEAT_SMALL 1
+EOF
+ ;;
+ normal) cat >> confdefs.h <<\EOF
+#define FEAT_NORMAL 1
+EOF
+ dovimdiff="installvimdiff";
+ dogvimdiff="installgvimdiff" ;;
+ big) cat >> confdefs.h <<\EOF
+#define FEAT_BIG 1
+EOF
+ dovimdiff="installvimdiff";
+ dogvimdiff="installgvimdiff" ;;
+ huge) cat >> confdefs.h <<\EOF
+#define FEAT_HUGE 1
+EOF
+ dovimdiff="installvimdiff";
+ dogvimdiff="installgvimdiff" ;;
+ *) echo "$ac_t""Sorry, $features is not supported" 1>&6 ;;
+esac
+
+
+
+
+echo $ac_n "checking --with-compiledby argument""... $ac_c" 1>&6
+echo "configure:1477: checking --with-compiledby argument" >&5
+# Check whether --with-compiledby or --without-compiledby was given.
+if test "${with_compiledby+set}" = set; then
+ withval="$with_compiledby"
+ compiledby="$withval"; echo "$ac_t""$withval" 1>&6
+else
+ compiledby=""; echo "$ac_t""no" 1>&6
+fi
+
+
+
+echo $ac_n "checking --disable-xsmp argument""... $ac_c" 1>&6
+echo "configure:1489: checking --disable-xsmp argument" >&5
+# Check whether --enable-xsmp or --disable-xsmp was given.
+if test "${enable_xsmp+set}" = set; then
+ enableval="$enable_xsmp"
+ :
+else
+ enable_xsmp="yes"
+fi
+
+
+if test "$enable_xsmp" = "yes"; then
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking --disable-xsmp-interact argument""... $ac_c" 1>&6
+echo "configure:1502: checking --disable-xsmp-interact argument" >&5
+ # Check whether --enable-xsmp-interact or --disable-xsmp-interact was given.
+if test "${enable_xsmp_interact+set}" = set; then
+ enableval="$enable_xsmp_interact"
+ :
+else
+ enable_xsmp_interact="yes"
+fi
+
+ if test "$enable_xsmp_interact" = "yes"; then
+ echo "$ac_t""no" 1>&6
+ cat >> confdefs.h <<\EOF
+#define USE_XSMP_INTERACT 1
+EOF
+
+ else
+ echo "$ac_t""yes" 1>&6
+ fi
+else
+ echo "$ac_t""yes" 1>&6
+fi
+
+echo $ac_n "checking --enable-perlinterp argument""... $ac_c" 1>&6
+echo "configure:1525: checking --enable-perlinterp argument" >&5
+# Check whether --enable-perlinterp or --disable-perlinterp was given.
+if test "${enable_perlinterp+set}" = set; then
+ enableval="$enable_perlinterp"
+ :
+else
+ enable_perlinterp="no"
+fi
+
+echo "$ac_t""$enable_perlinterp" 1>&6
+if test "$enable_perlinterp" = "yes"; then
+
+ # Extract the first word of "perl", so it can be a program name with args.
+set dummy perl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1540: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_perl'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_perl" in
+ /*)
+ ac_cv_path_vi_cv_path_perl="$vi_cv_path_perl" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_vi_cv_path_perl="$vi_cv_path_perl" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_perl="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+vi_cv_path_perl="$ac_cv_path_vi_cv_path_perl"
+if test -n "$vi_cv_path_perl"; then
+ echo "$ac_t""$vi_cv_path_perl" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "X$vi_cv_path_perl" != "X"; then
+ echo $ac_n "checking Perl version""... $ac_c" 1>&6
+echo "configure:1574: checking Perl version" >&5
+ if $vi_cv_path_perl -e 'require 5.003_01' >/dev/null 2>/dev/null; then
+ eval `$vi_cv_path_perl -V:usethreads`
+ if test "X$usethreads" = "XUNKNOWN" -o "X$usethreads" = "Xundef"; then
+ badthreads=no
+ else
+ if $vi_cv_path_perl -e 'require 5.6.0' >/dev/null 2>/dev/null; then
+ eval `$vi_cv_path_perl -V:use5005threads`
+ if test "X$use5005threads" = "XUNKNOWN" -o "X$use5005threads" = "Xundef"; then
+ badthreads=no
+ else
+ badthreads=yes
+ echo "$ac_t"">>> Perl > 5.6 with 5.5 threads cannot be used <<<" 1>&6
+ fi
+ else
+ badthreads=yes
+ echo "$ac_t"">>> Perl 5.5 with threads cannot be used <<<" 1>&6
+ fi
+ fi
+ if test $badthreads = no; then
+ echo "$ac_t""OK" 1>&6
+ eval `$vi_cv_path_perl -V:shrpenv`
+ if test "X$shrpenv" = "XUNKNOWN"; then # pre 5.003_04
+ shrpenv=""
+ fi
+ vi_cv_perllib=`$vi_cv_path_perl -MConfig -e 'print $Config{privlibexp}'`
+
+ perlcppflags=`$vi_cv_path_perl -Mlib=$srcdir -MExtUtils::Embed \
+ -e 'ccflags;perl_inc;print"\n"' | sed -e 's/-fno[^ ]*//'`
+ perllibs=`cd $srcdir; $vi_cv_path_perl -MExtUtils::Embed -e 'ldopts' | \
+ sed -e '/Warning/d' -e '/Note (probably harmless)/d' \
+ -e 's/-bE:perl.exp//' -e 's/-lc //'`
+ perlldflags=`cd $srcdir; $vi_cv_path_perl -MExtUtils::Embed \
+ -e 'ccdlflags' | sed -e 's/-bE:perl.exp//'`
+
+ echo $ac_n "checking if compile and link flags for Perl are sane""... $ac_c" 1>&6
+echo "configure:1610: checking if compile and link flags for Perl are sane" >&5
+ cflags_save=$CFLAGS
+ libs_save=$LIBS
+ ldflags_save=$LDFLAGS
+ CFLAGS="$CFLAGS $perlcppflags"
+ LIBS="$LIBS $perllibs"
+ LDFLAGS="$perlldflags $LDFLAGS"
+ cat > conftest.$ac_ext <<EOF
+#line 1618 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1625: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; perl_ok=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no: PERL DISABLED" 1>&6; perl_ok=no
+fi
+rm -f conftest*
+ CFLAGS=$cflags_save
+ LIBS=$libs_save
+ LDFLAGS=$ldflags_save
+ if test $perl_ok = yes; then
+ if test "X$perlcppflags" != "X"; then
+ PERL_CFLAGS="$perlcppflags"
+ fi
+ if test "X$perlldflags" != "X"; then
+ LDFLAGS="$perlldflags $LDFLAGS"
+ fi
+ PERL_LIBS=$perllibs
+ PERL_SRC="auto/if_perl.c if_perlsfio.c"
+ PERL_OBJ="objects/if_perl.o objects/if_perlsfio.o"
+ PERL_PRO="if_perl.pro if_perlsfio.pro"
+ cat >> confdefs.h <<\EOF
+#define FEAT_PERL 1
+EOF
+
+ fi
+ fi
+ else
+ echo "$ac_t"">>> too old; need Perl version 5.003_01 or later <<<" 1>&6
+ fi
+ fi
+
+ if test "x$MACOSX" = "xyes"; then
+ dir=/System/Library/Perl
+ darwindir=$dir/darwin
+ if test -d $darwindir; then
+ PERL=/usr/bin/perl
+ else
+ dir=/System/Library/Perl/5.8.1
+ darwindir=$dir/darwin-thread-multi-2level
+ if test -d $darwindir; then
+ PERL=/usr/bin/perl
+ fi
+ fi
+ if test -n "$PERL"; then
+ PERL_DIR="$dir"
+ PERL_CFLAGS="-DFEAT_PERL -I$darwindir/CORE"
+ PERL_OBJ="objects/if_perl.o objects/if_perlsfio.o $darwindir/auto/DynaLoader/DynaLoader.a"
+ PERL_LIBS="-L$darwindir/CORE -lperl"
+ fi
+ fi
+fi
+
+
+
+
+
+
+
+echo $ac_n "checking --enable-pythoninterp argument""... $ac_c" 1>&6
+echo "configure:1688: checking --enable-pythoninterp argument" >&5
+# Check whether --enable-pythoninterp or --disable-pythoninterp was given.
+if test "${enable_pythoninterp+set}" = set; then
+ enableval="$enable_pythoninterp"
+ :
+else
+ enable_pythoninterp="no"
+fi
+
+echo "$ac_t""$enable_pythoninterp" 1>&6
+if test "$enable_pythoninterp" = "yes"; then
+ # Extract the first word of "python", so it can be a program name with args.
+set dummy python; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1702: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_python'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_python" in
+ /*)
+ ac_cv_path_vi_cv_path_python="$vi_cv_path_python" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_vi_cv_path_python="$vi_cv_path_python" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_python="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+vi_cv_path_python="$ac_cv_path_vi_cv_path_python"
+if test -n "$vi_cv_path_python"; then
+ echo "$ac_t""$vi_cv_path_python" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "X$vi_cv_path_python" != "X"; then
+
+ echo $ac_n "checking Python version""... $ac_c" 1>&6
+echo "configure:1737: checking Python version" >&5
+if eval "test \"`echo '$''{'vi_cv_var_python_version'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ vi_cv_var_python_version=`
+ ${vi_cv_path_python} -c 'import sys; print sys.version[:3]'`
+
+fi
+
+echo "$ac_t""$vi_cv_var_python_version" 1>&6
+
+ echo $ac_n "checking Python is 1.4 or better""... $ac_c" 1>&6
+echo "configure:1749: checking Python is 1.4 or better" >&5
+ if ${vi_cv_path_python} -c \
+ "import sys; sys.exit(${vi_cv_var_python_version} < 1.4)"
+ then
+ echo "$ac_t""yep" 1>&6
+
+ echo $ac_n "checking Python's install prefix""... $ac_c" 1>&6
+echo "configure:1756: checking Python's install prefix" >&5
+if eval "test \"`echo '$''{'vi_cv_path_python_pfx'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ vi_cv_path_python_pfx=`
+ ${vi_cv_path_python} -c \
+ "import sys; print sys.prefix"`
+fi
+
+echo "$ac_t""$vi_cv_path_python_pfx" 1>&6
+
+ echo $ac_n "checking Python's execution prefix""... $ac_c" 1>&6
+echo "configure:1768: checking Python's execution prefix" >&5
+if eval "test \"`echo '$''{'vi_cv_path_python_epfx'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ vi_cv_path_python_epfx=`
+ ${vi_cv_path_python} -c \
+ "import sys; print sys.exec_prefix"`
+fi
+
+echo "$ac_t""$vi_cv_path_python_epfx" 1>&6
+
+
+ if eval "test \"`echo '$''{'vi_cv_path_pythonpath'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ vi_cv_path_pythonpath=`
+ unset PYTHONPATH;
+ ${vi_cv_path_python} -c \
+ "import sys, string; print string.join(sys.path,':')"`
+fi
+
+
+
+ # Check whether --with-python-config-dir or --without-python-config-dir was given.
+if test "${with_python_config_dir+set}" = set; then
+ withval="$with_python_config_dir"
+ vi_cv_path_python_conf="${withval}"
+fi
+
+
+ echo $ac_n "checking Python's configuration directory""... $ac_c" 1>&6
+echo "configure:1799: checking Python's configuration directory" >&5
+if eval "test \"`echo '$''{'vi_cv_path_python_conf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ vi_cv_path_python_conf=
+ for path in "${vi_cv_path_python_pfx}" "${vi_cv_path_python_epfx}"; do
+ for subdir in lib share; do
+ d="${path}/${subdir}/python${vi_cv_var_python_version}/config"
+ if test -d "$d" && test -f "$d/config.c"; then
+ vi_cv_path_python_conf="$d"
+ fi
+ done
+ done
+
+fi
+
+echo "$ac_t""$vi_cv_path_python_conf" 1>&6
+
+ PYTHON_CONFDIR="${vi_cv_path_python_conf}"
+
+ if test "X$PYTHON_CONFDIR" = "X"; then
+ echo "$ac_t""can't find it!" 1>&6
+ else
+
+ if eval "test \"`echo '$''{'vi_cv_path_python_plibs'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ tmp_mkf="/tmp/Makefile-conf$$"
+ cat ${PYTHON_CONFDIR}/Makefile - <<'eof' >${tmp_mkf}
+__:
+ @echo "python_MODLIBS='$(MODLIBS)'"
+ @echo "python_LIBS='$(LIBS)'"
+ @echo "python_SYSLIBS='$(SYSLIBS)'"
+ @echo "python_LINKFORSHARED='$(LINKFORSHARED)'"
+eof
+ eval "`cd ${PYTHON_CONFDIR} && make -f ${tmp_mkf} __ | sed '/ directory /d'`"
+ rm -f ${tmp_mkf}
+ if test "x$MACOSX" = "xyes" && ${vi_cv_path_python} -c \
+ "import sys; sys.exit(${vi_cv_var_python_version} < 2.3)"; then
+ vi_cv_path_python_plibs="-framework Python"
+ else
+ if test "${vi_cv_var_python_version}" = "1.4"; then
+ vi_cv_path_python_plibs="${PYTHON_CONFDIR}/libModules.a ${PYTHON_CONFDIR}/libPython.a ${PYTHON_CONFDIR}/libObjects.a ${PYTHON_CONFDIR}/libParser.a"
+ else
+ vi_cv_path_python_plibs="-L${PYTHON_CONFDIR} -lpython${vi_cv_var_python_version}"
+ fi
+ vi_cv_path_python_plibs="${vi_cv_path_python_plibs} ${python_MODLIBS} ${python_LIBS} ${python_SYSLIBS} ${python_LINKFORSHARED}"
+ vi_cv_path_python_plibs=`echo $vi_cv_path_python_plibs | sed s/-ltermcap//`
+ fi
+
+fi
+
+
+ PYTHON_LIBS="${vi_cv_path_python_plibs}"
+ if test "${vi_cv_path_python_pfx}" = "${vi_cv_path_python_epfx}"; then
+ PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version}"
+ else
+ PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version} -I${vi_cv_path_python_epfx}/include/python${vi_cv_var_python_version}"
+ fi
+ PYTHON_SRC="if_python.c"
+ if test "x$MACOSX" = "xyes"; then
+ PYTHON_OBJ="objects/if_python.o"
+ else
+ PYTHON_OBJ="objects/if_python.o objects/py_config.o"
+ fi
+ if test "${vi_cv_var_python_version}" = "1.4"; then
+ PYTHON_OBJ="$PYTHON_OBJ objects/py_getpath.o"
+ fi
+ PYTHON_GETPATH_CFLAGS="-DPYTHONPATH='\"${vi_cv_path_pythonpath}\"' -DPREFIX='\"${vi_cv_path_python_pfx}\"' -DEXEC_PREFIX='\"${vi_cv_path_python_epfx}\"'"
+
+ echo $ac_n "checking if -pthread should be used""... $ac_c" 1>&6
+echo "configure:1872: checking if -pthread should be used" >&5
+ threadsafe_flag=
+ thread_lib=
+ if test "x$MACOSX" != "xyes"; then
+ test "$GCC" = yes && threadsafe_flag="-pthread"
+ if test "`(uname) 2>/dev/null`" = FreeBSD; then
+ threadsafe_flag="-D_THREAD_SAFE"
+ thread_lib="-pthread"
+ fi
+ fi
+ libs_save_old=$LIBS
+ if test -n "$threadsafe_flag"; then
+ cflags_save=$CFLAGS
+ CFLAGS="$CFLAGS $threadsafe_flag"
+ LIBS="$LIBS $thread_lib"
+ cat > conftest.$ac_ext <<EOF
+#line 1888 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1895: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; PYTHON_CFLAGS="$PYTHON_CFLAGS $threadsafe_flag"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6; LIBS=$libs_save_old
+
+fi
+rm -f conftest*
+ CFLAGS=$cflags_save
+ else
+ echo "$ac_t""no" 1>&6
+ fi
+
+ echo $ac_n "checking if compile and link flags for Python are sane""... $ac_c" 1>&6
+echo "configure:1912: checking if compile and link flags for Python are sane" >&5
+ cflags_save=$CFLAGS
+ libs_save=$LIBS
+ CFLAGS="$CFLAGS $PYTHON_CFLAGS"
+ LIBS="$LIBS $PYTHON_LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 1918 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1925: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; python_ok=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no: PYTHON DISABLED" 1>&6; python_ok=no
+fi
+rm -f conftest*
+ CFLAGS=$cflags_save
+ LIBS=$libs_save
+ if test $python_ok = yes; then
+ cat >> confdefs.h <<\EOF
+#define FEAT_PYTHON 1
+EOF
+
+ else
+ LIBS=$libs_save_old
+ PYTHON_SRC=
+ PYTHON_OBJ=
+ PYTHON_LIBS=
+ PYTHON_CFLAGS=
+ fi
+
+ fi
+ else
+ echo "$ac_t""too old" 1>&6
+ fi
+ fi
+fi
+
+
+
+
+
+
+
+echo $ac_n "checking --enable-tclinterp argument""... $ac_c" 1>&6
+echo "configure:1964: checking --enable-tclinterp argument" >&5
+# Check whether --enable-tclinterp or --disable-tclinterp was given.
+if test "${enable_tclinterp+set}" = set; then
+ enableval="$enable_tclinterp"
+ :
+else
+ enable_tclinterp="no"
+fi
+
+echo "$ac_t""$enable_tclinterp" 1>&6
+
+if test "$enable_tclinterp" = "yes"; then
+
+ echo $ac_n "checking --with-tclsh argument""... $ac_c" 1>&6
+echo "configure:1978: checking --with-tclsh argument" >&5
+ # Check whether --with-tclsh or --without-tclsh was given.
+if test "${with_tclsh+set}" = set; then
+ withval="$with_tclsh"
+ tclsh_name="$withval"; echo "$ac_t""$tclsh_name" 1>&6
+else
+ tclsh_name="tclsh8.0"; echo "$ac_t""no" 1>&6
+fi
+
+ # Extract the first word of "$tclsh_name", so it can be a program name with args.
+set dummy $tclsh_name; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1990: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_tcl'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_tcl" in
+ /*)
+ ac_cv_path_vi_cv_path_tcl="$vi_cv_path_tcl" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_vi_cv_path_tcl="$vi_cv_path_tcl" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_tcl="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+vi_cv_path_tcl="$ac_cv_path_vi_cv_path_tcl"
+if test -n "$vi_cv_path_tcl"; then
+ echo "$ac_t""$vi_cv_path_tcl" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+ if test "X$vi_cv_path_tcl" = "X" -a $tclsh_name = "tclsh8.0"; then
+ tclsh_name="tclsh8.2"
+ # Extract the first word of "$tclsh_name", so it can be a program name with args.
+set dummy $tclsh_name; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2029: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_tcl'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_tcl" in
+ /*)
+ ac_cv_path_vi_cv_path_tcl="$vi_cv_path_tcl" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_vi_cv_path_tcl="$vi_cv_path_tcl" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_tcl="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+vi_cv_path_tcl="$ac_cv_path_vi_cv_path_tcl"
+if test -n "$vi_cv_path_tcl"; then
+ echo "$ac_t""$vi_cv_path_tcl" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+ if test "X$vi_cv_path_tcl" = "X"; then
+ tclsh_name="tclsh"
+ # Extract the first word of "$tclsh_name", so it can be a program name with args.
+set dummy $tclsh_name; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2067: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_tcl'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_tcl" in
+ /*)
+ ac_cv_path_vi_cv_path_tcl="$vi_cv_path_tcl" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_vi_cv_path_tcl="$vi_cv_path_tcl" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_tcl="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+vi_cv_path_tcl="$ac_cv_path_vi_cv_path_tcl"
+if test -n "$vi_cv_path_tcl"; then
+ echo "$ac_t""$vi_cv_path_tcl" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+ if test "X$vi_cv_path_tcl" != "X"; then
+ echo $ac_n "checking Tcl version""... $ac_c" 1>&6
+echo "configure:2102: checking Tcl version" >&5
+ if echo 'exit [expr [info tclversion] < 8.0]' | $vi_cv_path_tcl - ; then
+ tclver=`echo 'puts [info tclversion]' | $vi_cv_path_tcl -`
+ echo "$ac_t""$tclver - OK" 1>&6;
+ tclloc=`echo 'set l [info library];set i [string last lib $l];incr i -2;puts [string range $l 0 $i]' | $vi_cv_path_tcl -`
+
+ echo $ac_n "checking for location of Tcl include""... $ac_c" 1>&6
+echo "configure:2109: checking for location of Tcl include" >&5
+ if test "x$MACOSX" != "xyes"; then
+ tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include"
+ else
+ tclinc="/System/Library/Frameworks/Tcl.framework/Headers"
+ fi
+ for try in $tclinc; do
+ if test -f "$try/tcl.h"; then
+ echo "$ac_t""$try/tcl.h" 1>&6
+ TCL_INC=$try
+ break
+ fi
+ done
+ if test -z "$TCL_INC"; then
+ echo "$ac_t""<not found>" 1>&6
+ SKIP_TCL=YES
+ fi
+ if test -z "$SKIP_TCL"; then
+ echo $ac_n "checking for location of tclConfig.sh script""... $ac_c" 1>&6
+echo "configure:2128: checking for location of tclConfig.sh script" >&5
+ if test "x$MACOSX" != "xyes"; then
+ tclcnf=`echo $tclinc | sed s/include/lib/g`
+ else
+ tclcnf="/System/Library/Frameworks/Tcl.framework"
+ fi
+ for try in $tclcnf; do
+ if test -f $try/tclConfig.sh; then
+ echo "$ac_t""$try/tclConfig.sh" 1>&6
+ . $try/tclConfig.sh
+ TCL_LIBS=`eval echo "$TCL_LIB_SPEC $TCL_LIBS"`
+ TCL_DEFS=`echo $TCL_DEFS | tr ' ' '\012' | sed -e '/^-[^D]/d' -e '/-D[^_]/d' -e 's/-D_/ -D_/' | tr -d '\012'`
+ break
+ fi
+ done
+ if test -z "$TCL_LIBS"; then
+ echo "$ac_t""<not found>" 1>&6
+ echo $ac_n "checking for Tcl library by myself""... $ac_c" 1>&6
+echo "configure:2146: checking for Tcl library by myself" >&5
+ tcllib=`echo $tclinc | sed s/include/lib/g`
+ for ext in .so .a ; do
+ for ver in "" $tclver ; do
+ for try in $tcllib ; do
+ trylib=tcl$ver$ext
+ if test -f $try/lib$trylib ; then
+ echo "$ac_t""$try/lib$trylib" 1>&6
+ TCL_LIBS="-L$try -ltcl$ver -ldl -lm"
+ if test "`(uname) 2>/dev/null`" = SunOS &&
+ uname -r | grep '^5' >/dev/null; then
+ TCL_LIBS="$TCL_LIBS -R $try"
+ fi
+ break 3
+ fi
+ done
+ done
+ done
+ if test -z "$TCL_LIBS"; then
+ echo "$ac_t""<not found>" 1>&6
+ SKIP_TCL=YES
+ fi
+ fi
+ if test -z "$SKIP_TCL"; then
+ cat >> confdefs.h <<\EOF
+#define FEAT_TCL 1
+EOF
+
+ TCL_SRC=if_tcl.c
+ TCL_OBJ=objects/if_tcl.o
+ TCL_PRO=if_tcl.pro
+ TCL_CFLAGS="-I$TCL_INC $TCL_DEFS"
+ fi
+ fi
+ else
+ echo "$ac_t""too old; need Tcl version 8.0 or later" 1>&6
+ fi
+ fi
+fi
+
+
+
+
+
+
+echo $ac_n "checking --enable-rubyinterp argument""... $ac_c" 1>&6
+echo "configure:2192: checking --enable-rubyinterp argument" >&5
+# Check whether --enable-rubyinterp or --disable-rubyinterp was given.
+if test "${enable_rubyinterp+set}" = set; then
+ enableval="$enable_rubyinterp"
+ :
+else
+ enable_rubyinterp="no"
+fi
+
+echo "$ac_t""$enable_rubyinterp" 1>&6
+if test "$enable_rubyinterp" = "yes"; then
+
+ # Extract the first word of "ruby", so it can be a program name with args.
+set dummy ruby; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2207: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_ruby'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_ruby" in
+ /*)
+ ac_cv_path_vi_cv_path_ruby="$vi_cv_path_ruby" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_vi_cv_path_ruby="$vi_cv_path_ruby" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_ruby="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+vi_cv_path_ruby="$ac_cv_path_vi_cv_path_ruby"
+if test -n "$vi_cv_path_ruby"; then
+ echo "$ac_t""$vi_cv_path_ruby" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "X$vi_cv_path_ruby" != "X"; then
+ echo $ac_n "checking Ruby version""... $ac_c" 1>&6
+echo "configure:2241: checking Ruby version" >&5
+ if $vi_cv_path_ruby -e 'VERSION >= "1.6.0" or exit 1' >/dev/null 2>/dev/null; then
+ echo "$ac_t""OK" 1>&6
+ echo $ac_n "checking Ruby header files""... $ac_c" 1>&6
+echo "configure:2245: checking Ruby header files" >&5
+ rubyhdrdir=`$vi_cv_path_ruby -r mkmf -e 'print Config::CONFIG["archdir"] || $hdrdir' 2>/dev/null`
+ if test "X$rubyhdrdir" != "X"; then
+ echo "$ac_t""$rubyhdrdir" 1>&6
+ RUBY_CFLAGS="-I$rubyhdrdir"
+ rubylibs=`$vi_cv_path_ruby -r rbconfig -e 'print Config::CONFIG["LIBS"]'`
+ if test "X$rubylibs" != "X"; then
+ RUBY_LIBS="$rubylibs"
+ fi
+ librubyarg=`$vi_cv_path_ruby -r rbconfig -e 'print Config.expand(Config::CONFIG["LIBRUBYARG"])'`
+ if test -f "$rubyhdrdir/$librubyarg"; then
+ librubyarg="$rubyhdrdir/$librubyarg"
+ else
+ rubylibdir=`$vi_cv_path_ruby -r rbconfig -e 'print Config.expand(Config::CONFIG["libdir"])'`
+ if test -f "$rubylibdir/$librubyarg"; then
+ librubyarg="$rubylibdir/$librubyarg"
+ elif test "$librubyarg" = "libruby.a"; then
+ librubyarg="-lruby"
+ else
+ librubyarg=`$vi_cv_path_ruby -r rbconfig -e "print '$librubyarg'.gsub(/-L\./, %'-L#{Config.expand(Config::CONFIG[\"libdir\"])}')"`
+ fi
+ fi
+
+ if test "X$librubyarg" != "X"; then
+ RUBY_LIBS="$librubyarg $RUBY_LIBS"
+ fi
+ rubyldflags=`$vi_cv_path_ruby -r rbconfig -e 'print Config::CONFIG["LDFLAGS"]'`
+ if test "X$rubyldflags" != "X"; then
+ LDFLAGS="$rubyldflags $LDFLAGS"
+ fi
+ RUBY_SRC="if_ruby.c"
+ RUBY_OBJ="objects/if_ruby.o"
+ RUBY_PRO="if_ruby.pro"
+ cat >> confdefs.h <<\EOF
+#define FEAT_RUBY 1
+EOF
+
+ else
+ echo "$ac_t""not found" 1>&6
+ fi
+ else
+ echo "$ac_t""too old; need Ruby version 1.6.0 or later" 1>&6
+ fi
+ fi
+fi
+
+
+
+
+
+
+echo $ac_n "checking --enable-cscope argument""... $ac_c" 1>&6
+echo "configure:2297: checking --enable-cscope argument" >&5
+# Check whether --enable-cscope or --disable-cscope was given.
+if test "${enable_cscope+set}" = set; then
+ enableval="$enable_cscope"
+ :
+else
+ enable_cscope="no"
+fi
+
+echo "$ac_t""$enable_cscope" 1>&6
+if test "$enable_cscope" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define FEAT_CSCOPE 1
+EOF
+
+fi
+
+echo $ac_n "checking --enable-workshop argument""... $ac_c" 1>&6
+echo "configure:2315: checking --enable-workshop argument" >&5
+# Check whether --enable-workshop or --disable-workshop was given.
+if test "${enable_workshop+set}" = set; then
+ enableval="$enable_workshop"
+ :
+else
+ enable_workshop="no"
+fi
+
+echo "$ac_t""$enable_workshop" 1>&6
+if test "$enable_workshop" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define FEAT_SUN_WORKSHOP 1
+EOF
+
+ WORKSHOP_SRC="workshop.c integration.c"
+
+ WORKSHOP_OBJ="objects/workshop.o objects/integration.o"
+
+ if test "${enable_gui-xxx}" = xxx; then
+ enable_gui=motif
+ fi
+fi
+
+echo $ac_n "checking --disable-netbeans argument""... $ac_c" 1>&6
+echo "configure:2340: checking --disable-netbeans argument" >&5
+# Check whether --enable-netbeans or --disable-netbeans was given.
+if test "${enable_netbeans+set}" = set; then
+ enableval="$enable_netbeans"
+ :
+else
+ enable_netbeans="yes"
+fi
+
+if test "$enable_netbeans" = "yes"; then
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
+echo "configure:2352: checking for socket in -lsocket" >&5
+ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2360 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:2371: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lsocket $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
+echo "configure:2399: checking for gethostbyname in -lnsl" >&5
+ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2407 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+gethostbyname()
+; return 0; }
+EOF
+if { (eval echo configure:2418: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lnsl $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ echo $ac_n "checking whether compiling netbeans integration is possible""... $ac_c" 1>&6
+echo "configure:2446: checking whether compiling netbeans integration is possible" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 2448 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+ /* Check bitfields */
+ struct nbbuf {
+ unsigned int initDone:1;
+ ushort signmaplen;
+ };
+
+int main() {
+
+ /* Check creating a socket. */
+ struct sockaddr_in server;
+ (void)socket(AF_INET, SOCK_STREAM, 0);
+ (void)htons(100);
+ (void)gethostbyname("microsoft.com");
+ if (errno == ECONNREFUSED)
+ (void)connect(1, (struct sockaddr *)&server, sizeof(server));
+
+; return 0; }
+EOF
+if { (eval echo configure:2478: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6; enable_netbeans="no"
+fi
+rm -f conftest*
+else
+ echo "$ac_t""yes" 1>&6
+fi
+if test "$enable_netbeans" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define FEAT_NETBEANS_INTG 1
+EOF
+
+ NETBEANS_SRC="netbeans.c"
+
+ NETBEANS_OBJ="objects/netbeans.o"
+
+fi
+
+echo $ac_n "checking --enable-sniff argument""... $ac_c" 1>&6
+echo "configure:2503: checking --enable-sniff argument" >&5
+# Check whether --enable-sniff or --disable-sniff was given.
+if test "${enable_sniff+set}" = set; then
+ enableval="$enable_sniff"
+ :
+else
+ enable_sniff="no"
+fi
+
+echo "$ac_t""$enable_sniff" 1>&6
+if test "$enable_sniff" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define FEAT_SNIFF 1
+EOF
+
+ SNIFF_SRC="if_sniff.c"
+
+ SNIFF_OBJ="objects/if_sniff.o"
+
+fi
+
+echo $ac_n "checking --enable-multibyte argument""... $ac_c" 1>&6
+echo "configure:2525: checking --enable-multibyte argument" >&5
+# Check whether --enable-multibyte or --disable-multibyte was given.
+if test "${enable_multibyte+set}" = set; then
+ enableval="$enable_multibyte"
+ :
+else
+ enable_multibyte="no"
+fi
+
+echo "$ac_t""$enable_multibyte" 1>&6
+if test "$enable_multibyte" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define FEAT_MBYTE 1
+EOF
+
+fi
+
+echo $ac_n "checking --enable-hangulinput argument""... $ac_c" 1>&6
+echo "configure:2543: checking --enable-hangulinput argument" >&5
+# Check whether --enable-hangulinput or --disable-hangulinput was given.
+if test "${enable_hangulinput+set}" = set; then
+ enableval="$enable_hangulinput"
+ :
+else
+ enable_hangulinput="no"
+fi
+
+echo "$ac_t""$enable_hangulinput" 1>&6
+
+echo $ac_n "checking --enable-xim argument""... $ac_c" 1>&6
+echo "configure:2555: checking --enable-xim argument" >&5
+# Check whether --enable-xim or --disable-xim was given.
+if test "${enable_xim+set}" = set; then
+ enableval="$enable_xim"
+ echo "$ac_t""$enable_xim" 1>&6
+else
+ enable_xim="auto"; echo "$ac_t""defaulting to auto" 1>&6
+fi
+
+
+echo $ac_n "checking --enable-fontset argument""... $ac_c" 1>&6
+echo "configure:2566: checking --enable-fontset argument" >&5
+# Check whether --enable-fontset or --disable-fontset was given.
+if test "${enable_fontset+set}" = set; then
+ enableval="$enable_fontset"
+ :
+else
+ enable_fontset="no"
+fi
+
+echo "$ac_t""$enable_fontset" 1>&6
+
+test -z "$with_x" && with_x=yes
+test "${enable_gui-yes}" != no -a "x$MACOSX" != "xyes" -a "x$QNX" != "xyes" && with_x=yes
+if test "$with_x" = no; then
+ echo "$ac_t""defaulting to: don't HAVE_X11" 1>&6
+else
+
+ # Extract the first word of "xmkmf", so it can be a program name with args.
+set dummy xmkmf; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2586: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_xmkmfpath'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$xmkmfpath" in
+ /*)
+ ac_cv_path_xmkmfpath="$xmkmfpath" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_xmkmfpath="$xmkmfpath" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_xmkmfpath="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+xmkmfpath="$ac_cv_path_xmkmfpath"
+if test -n "$xmkmfpath"; then
+ echo "$ac_t""$xmkmfpath" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+ # If we find X, set shell vars x_includes and x_libraries to the
+# paths, otherwise set no_x=yes.
+# Uses ac_ vars as temps to allow command line to override cache and checks.
+# --without-x overrides everything else, but does not touch the cache.
+echo $ac_n "checking for X""... $ac_c" 1>&6
+echo "configure:2624: checking for X" >&5
+
+# Check whether --with-x or --without-x was given.
+if test "${with_x+set}" = set; then
+ withval="$with_x"
+ :
+fi
+
+# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
+if test "x$with_x" = xno; then
+ # The user explicitly disabled X.
+ have_x=disabled
+else
+ if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then
+ # Both variables are already set.
+ have_x=yes
+ else
+if eval "test \"`echo '$''{'ac_cv_have_x'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # One or both of the vars are not set, and there is no cached value.
+ac_x_includes=NO ac_x_libraries=NO
+rm -fr conftestdir
+if mkdir conftestdir; then
+ cd conftestdir
+ # Make sure to not put "make" in the Imakefile rules, since we grep it out.
+ cat > Imakefile <<'EOF'
+acfindx:
+ @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"'
+EOF
+ if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then
+ # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+ eval `${MAKE-make} acfindx 2>/dev/null | grep -v make`
+ # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+ for ac_extension in a so sl; do
+ if test ! -f $ac_im_usrlibdir/libX11.$ac_extension &&
+ test -f $ac_im_libdir/libX11.$ac_extension; then
+ ac_im_usrlibdir=$ac_im_libdir; break
+ fi
+ done
+ # Screen out bogus values from the imake configuration. They are
+ # bogus both because they are the default anyway, and because
+ # using them would break gcc on systems where it needs fixed includes.
+ case "$ac_im_incroot" in
+ /usr/include) ;;
+ *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;;
+ esac
+ case "$ac_im_usrlibdir" in
+ /usr/lib | /lib) ;;
+ *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;;
+ esac
+ fi
+ cd ..
+ rm -fr conftestdir
+fi
+
+if test "$ac_x_includes" = NO; then
+ # Guess where to find include files, by looking for this one X11 .h file.
+ test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h
+
+ # First, try using that file with no special directory specified.
+cat > conftest.$ac_ext <<EOF
+#line 2686 "configure"
+#include "confdefs.h"
+#include <$x_direct_test_include>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2691: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ # We can compile using X headers with no special include directory.
+ac_x_includes=
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ # Look for the header file in a standard set of common directories.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ for ac_dir in \
+ /usr/X11/include \
+ /usr/X11R6/include \
+ /usr/X11R5/include \
+ /usr/X11R4/include \
+ \
+ /usr/include/X11 \
+ /usr/include/X11R6 \
+ /usr/include/X11R5 \
+ /usr/include/X11R4 \
+ \
+ /usr/local/X11/include \
+ /usr/local/X11R6/include \
+ /usr/local/X11R5/include \
+ /usr/local/X11R4/include \
+ \
+ /usr/local/include/X11 \
+ /usr/local/include/X11R6 \
+ /usr/local/include/X11R5 \
+ /usr/local/include/X11R4 \
+ \
+ /usr/X386/include \
+ /usr/x386/include \
+ /usr/XFree86/include/X11 \
+ \
+ /usr/include \
+ /usr/local/include \
+ /usr/unsupported/include \
+ /usr/athena/include \
+ /usr/local/x11r5/include \
+ /usr/lpp/Xamples/include \
+ \
+ /usr/openwin/include \
+ /usr/openwin/share/include \
+ ; \
+ do
+ if test -r "$ac_dir/$x_direct_test_include"; then
+ ac_x_includes=$ac_dir
+ break
+ fi
+ done
+fi
+rm -f conftest*
+fi # $ac_x_includes = NO
+
+if test "$ac_x_libraries" = NO; then
+ # Check for the libraries.
+
+ test -z "$x_direct_test_library" && x_direct_test_library=Xt
+ test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc
+
+ # See if we find them without any special options.
+ # Don't add to $LIBS permanently.
+ ac_save_LIBS="$LIBS"
+ LIBS="-l$x_direct_test_library $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2760 "configure"
+#include "confdefs.h"
+
+int main() {
+${x_direct_test_function}()
+; return 0; }
+EOF
+if { (eval echo configure:2767: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# We can link X programs with no special library path.
+ac_x_libraries=
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# First see if replacing the include by lib works.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \
+ /usr/X11/lib \
+ /usr/X11R6/lib \
+ /usr/X11R5/lib \
+ /usr/X11R4/lib \
+ \
+ /usr/lib/X11 \
+ /usr/lib/X11R6 \
+ /usr/lib/X11R5 \
+ /usr/lib/X11R4 \
+ \
+ /usr/local/X11/lib \
+ /usr/local/X11R6/lib \
+ /usr/local/X11R5/lib \
+ /usr/local/X11R4/lib \
+ \
+ /usr/local/lib/X11 \
+ /usr/local/lib/X11R6 \
+ /usr/local/lib/X11R5 \
+ /usr/local/lib/X11R4 \
+ \
+ /usr/X386/lib \
+ /usr/x386/lib \
+ /usr/XFree86/lib/X11 \
+ \
+ /usr/lib \
+ /usr/local/lib \
+ /usr/unsupported/lib \
+ /usr/athena/lib \
+ /usr/local/x11r5/lib \
+ /usr/lpp/Xamples/lib \
+ /lib/usr/lib/X11 \
+ \
+ /usr/openwin/lib \
+ /usr/openwin/share/lib \
+ ; \
+do
+ for ac_extension in a so sl; do
+ if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then
+ ac_x_libraries=$ac_dir
+ break 2
+ fi
+ done
+done
+fi
+rm -f conftest*
+fi # $ac_x_libraries = NO
+
+if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then
+ # Didn't find X anywhere. Cache the known absence of X.
+ ac_cv_have_x="have_x=no"
+else
+ # Record where we found X for the cache.
+ ac_cv_have_x="have_x=yes \
+ ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries"
+fi
+fi
+ fi
+ eval "$ac_cv_have_x"
+fi # $with_x != no
+
+if test "$have_x" != yes; then
+ echo "$ac_t""$have_x" 1>&6
+ no_x=yes
+else
+ # If each of the values was on the command line, it overrides each guess.
+ test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+ test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+ # Update the cache value to reflect the command line values.
+ ac_cv_have_x="have_x=yes \
+ ac_x_includes=$x_includes ac_x_libraries=$x_libraries"
+ echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6
+fi
+
+if test "$no_x" = yes; then
+ # Not all programs may use this symbol, but it does not hurt to define it.
+ cat >> confdefs.h <<\EOF
+#define X_DISPLAY_MISSING 1
+EOF
+
+ X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS=
+else
+ if test -n "$x_includes"; then
+ X_CFLAGS="$X_CFLAGS -I$x_includes"
+ fi
+
+ # It would also be nice to do this for all -L options, not just this one.
+ if test -n "$x_libraries"; then
+ X_LIBS="$X_LIBS -L$x_libraries"
+ # For Solaris; some versions of Sun CC require a space after -R and
+ # others require no space. Words are not sufficient . . . .
+ case "`(uname -sr) 2>/dev/null`" in
+ "SunOS 5"*)
+ echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6
+echo "configure:2873: checking whether -R must be followed by a space" >&5
+ ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries"
+ cat > conftest.$ac_ext <<EOF
+#line 2876 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:2883: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_R_nospace=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_R_nospace=no
+fi
+rm -f conftest*
+ if test $ac_R_nospace = yes; then
+ echo "$ac_t""no" 1>&6
+ X_LIBS="$X_LIBS -R$x_libraries"
+ else
+ LIBS="$ac_xsave_LIBS -R $x_libraries"
+ cat > conftest.$ac_ext <<EOF
+#line 2899 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:2906: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_R_space=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_R_space=no
+fi
+rm -f conftest*
+ if test $ac_R_space = yes; then
+ echo "$ac_t""yes" 1>&6
+ X_LIBS="$X_LIBS -R $x_libraries"
+ else
+ echo "$ac_t""neither works" 1>&6
+ fi
+ fi
+ LIBS="$ac_xsave_LIBS"
+ esac
+ fi
+
+ # Check for system-dependent libraries X programs must link with.
+ # Do this before checking for the system-independent R6 libraries
+ # (-lICE), since we may need -lsocket or whatever for X linking.
+
+ if test "$ISC" = yes; then
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet"
+ else
+ # Martyn.Johnson@cl.cam.ac.uk says this is needed for Ultrix, if the X
+ # libraries were built with DECnet support. And karl@cs.umb.edu says
+ # the Alpha needs dnet_stub (dnet does not exist).
+ echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6
+echo "configure:2938: checking for dnet_ntoa in -ldnet" >&5
+ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldnet $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2946 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dnet_ntoa();
+
+int main() {
+dnet_ntoa()
+; return 0; }
+EOF
+if { (eval echo configure:2957: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_lib_dnet_dnet_ntoa = no; then
+ echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6
+echo "configure:2979: checking for dnet_ntoa in -ldnet_stub" >&5
+ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldnet_stub $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2987 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dnet_ntoa();
+
+int main() {
+dnet_ntoa()
+; return 0; }
+EOF
+if { (eval echo configure:2998: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT,
+ # to get the SysV transport functions.
+ # chad@anasazi.com says the Pyramis MIS-ES running DC/OSx (SVR4)
+ # needs -lnsl.
+ # The nsl library prevents programs from opening the X display
+ # on Irix 5.2, according to dickey@clark.net.
+ echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6
+echo "configure:3027: checking for gethostbyname" >&5
+if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3032 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char gethostbyname(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname)
+choke me
+#else
+gethostbyname();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3055: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_gethostbyname=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_gethostbyname=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_func_gethostbyname = no; then
+ echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
+echo "configure:3076: checking for gethostbyname in -lnsl" >&5
+ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3084 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+gethostbyname()
+; return 0; }
+EOF
+if { (eval echo configure:3095: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ # lieder@skyler.mavd.honeywell.com says without -lsocket,
+ # socket/setsockopt and other routines are undefined under SCO ODT
+ # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary
+ # on later versions), says simon@lia.di.epfl.ch: it contains
+ # gethostby* variants that don't use the nameserver (or something).
+ # -lsocket must be given before -lnsl if both are needed.
+ # We assume that if connect needs -lnsl, so does gethostbyname.
+ echo $ac_n "checking for connect""... $ac_c" 1>&6
+echo "configure:3125: checking for connect" >&5
+if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3130 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char connect(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char connect();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_connect) || defined (__stub___connect)
+choke me
+#else
+connect();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3153: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_connect=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_connect=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'connect`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_func_connect = no; then
+ echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6
+echo "configure:3174: checking for connect in -lsocket" >&5
+ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3182 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char connect();
+
+int main() {
+connect()
+; return 0; }
+EOF
+if { (eval echo configure:3193: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX.
+ echo $ac_n "checking for remove""... $ac_c" 1>&6
+echo "configure:3217: checking for remove" >&5
+if eval "test \"`echo '$''{'ac_cv_func_remove'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3222 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char remove(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char remove();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_remove) || defined (__stub___remove)
+choke me
+#else
+remove();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3245: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_remove=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_remove=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'remove`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_func_remove = no; then
+ echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6
+echo "configure:3266: checking for remove in -lposix" >&5
+ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lposix $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3274 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char remove();
+
+int main() {
+remove()
+; return 0; }
+EOF
+if { (eval echo configure:3285: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
+ echo $ac_n "checking for shmat""... $ac_c" 1>&6
+echo "configure:3309: checking for shmat" >&5
+if eval "test \"`echo '$''{'ac_cv_func_shmat'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3314 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shmat(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shmat();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_shmat) || defined (__stub___shmat)
+choke me
+#else
+shmat();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3337: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_shmat=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_shmat=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'shmat`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_func_shmat = no; then
+ echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6
+echo "configure:3358: checking for shmat in -lipc" >&5
+ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lipc $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3366 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shmat();
+
+int main() {
+shmat()
+; return 0; }
+EOF
+if { (eval echo configure:3377: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+ fi
+
+ # Check for libraries that X11R6 Xt/Xaw programs need.
+ ac_save_LDFLAGS="$LDFLAGS"
+ test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries"
+ # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to
+ # check for ICE first), but we must link in the order -lSM -lICE or
+ # we get undefined symbols. So assume we have SM if we have ICE.
+ # These have to be linked with before -lX11, unlike the other
+ # libraries we check for below, so use a different variable.
+ # --interran@uluru.Stanford.EDU, kb@cs.umb.edu.
+ echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6
+echo "configure:3410: checking for IceConnectionNumber in -lICE" >&5
+ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lICE $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3418 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char IceConnectionNumber();
+
+int main() {
+IceConnectionNumber()
+; return 0; }
+EOF
+if { (eval echo configure:3429: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ LDFLAGS="$ac_save_LDFLAGS"
+
+fi
+
+
+ if test "$OS390Unix" = "yes"; then
+ CFLAGS="$CFLAGS -W c,dll"
+ LDFLAGS="$LDFLAGS -W l,dll"
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lSM -lICE -lXmu"
+ fi
+
+
+ if test -d "$x_includes" && test ! -d "$x_libraries"; then
+ x_libraries=`echo "$x_includes" | sed s/include/lib/`
+ echo "$ac_t""Corrected X libraries to $x_libraries" 1>&6
+ X_LIBS="$X_LIBS -L$x_libraries"
+ if test "`(uname) 2>/dev/null`" = SunOS &&
+ uname -r | grep '^5' >/dev/null; then
+ X_LIBS="$X_LIBS -R $x_libraries"
+ fi
+ fi
+
+ if test -d "$x_libraries" && test ! -d "$x_includes"; then
+ x_includes=`echo "$x_libraries" | sed s/lib/include/`
+ echo "$ac_t""Corrected X includes to $x_includes" 1>&6
+ X_CFLAGS="$X_CFLAGS -I$x_includes"
+ fi
+
+ X_CFLAGS="`echo $X_CFLAGS\ | sed 's%-I/usr/include %%'`"
+ X_LIBS="`echo $X_LIBS\ | sed 's%-L/usr/lib %%'`"
+ X_LIBS="`echo $X_LIBS\ | sed -e 's%-R/usr/lib %%' -e 's%-R /usr/lib %%'`"
+
+
+ echo $ac_n "checking if X11 header files can be found""... $ac_c" 1>&6
+echo "configure:3483: checking if X11 header files can be found" >&5
+ cflags_save=$CFLAGS
+ CFLAGS="$CFLAGS $X_CFLAGS"
+ cat > conftest.$ac_ext <<EOF
+#line 3487 "configure"
+#include "confdefs.h"
+#include <X11/Xlib.h>
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:3494: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6; no_x=yes
+fi
+rm -f conftest*
+ CFLAGS=$cflags_save
+
+ if test "${no_x-no}" = yes; then
+ with_x=no
+ else
+ cat >> confdefs.h <<\EOF
+#define HAVE_X11 1
+EOF
+
+ X_LIB="-lXt -lX11";
+
+
+ ac_save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="-L$x_libraries $LDFLAGS"
+
+ echo $ac_n "checking for _XdmcpAuthDoIt in -lXdmcp""... $ac_c" 1>&6
+echo "configure:3520: checking for _XdmcpAuthDoIt in -lXdmcp" >&5
+ac_lib_var=`echo Xdmcp'_'_XdmcpAuthDoIt | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lXdmcp -lXt $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lXdmcp $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3528 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _XdmcpAuthDoIt();
+
+int main() {
+_XdmcpAuthDoIt()
+; return 0; }
+EOF
+if { (eval echo configure:3539: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lXdmcp"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+ echo $ac_n "checking for IceOpenConnection in -lICE""... $ac_c" 1>&6
+echo "configure:3561: checking for IceOpenConnection in -lICE" >&5
+ac_lib_var=`echo ICE'_'IceOpenConnection | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lICE $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3569 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char IceOpenConnection();
+
+int main() {
+IceOpenConnection()
+; return 0; }
+EOF
+if { (eval echo configure:3580: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lSM -lICE"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+ LDFLAGS="$X_LIBS $ac_save_LDFLAGS"
+ echo $ac_n "checking for XpmCreatePixmapFromData in -lXpm""... $ac_c" 1>&6
+echo "configure:3603: checking for XpmCreatePixmapFromData in -lXpm" >&5
+ac_lib_var=`echo Xpm'_'XpmCreatePixmapFromData | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lXpm -lXt $X_PRE_LIBS -lXpm -lX11 $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3611 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char XpmCreatePixmapFromData();
+
+int main() {
+XpmCreatePixmapFromData()
+; return 0; }
+EOF
+if { (eval echo configure:3622: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_PRE_LIBS="$X_PRE_LIBS -lXpm"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+ echo $ac_n "checking if X11 header files implicitly declare return values""... $ac_c" 1>&6
+echo "configure:3644: checking if X11 header files implicitly declare return values" >&5
+ cflags_save=$CFLAGS
+ CFLAGS="$CFLAGS $X_CFLAGS -Werror"
+ cat > conftest.$ac_ext <<EOF
+#line 3648 "configure"
+#include "confdefs.h"
+#include <X11/Xlib.h>
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:3655: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CFLAGS="$CFLAGS -Wno-implicit-int"
+ cat > conftest.$ac_ext <<EOF
+#line 3664 "configure"
+#include "confdefs.h"
+#include <X11/Xlib.h>
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:3671: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cflags_save="$cflags_save -Wno-implicit-int"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""test failed" 1>&6
+
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+ CFLAGS=$cflags_save
+
+ LDFLAGS="$ac_save_LDFLAGS"
+
+ fi
+fi
+
+test "x$with_x" = xno -a "x$BEOS" != "xyes" -a "x$MACOSX" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no
+
+echo $ac_n "checking --enable-gui argument""... $ac_c" 1>&6
+echo "configure:3695: checking --enable-gui argument" >&5
+# Check whether --enable-gui or --disable-gui was given.
+if test "${enable_gui+set}" = set; then
+ enableval="$enable_gui"
+ :
+else
+ enable_gui="auto"
+fi
+
+
+enable_gui_canon=`echo "_$enable_gui" | \
+ sed 's/[ _+-]//g;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
+
+SKIP_GTK=YES
+SKIP_GTK2=YES
+SKIP_GNOME=YES
+SKIP_MOTIF=YES
+SKIP_ATHENA=YES
+SKIP_NEXTAW=YES
+SKIP_PHOTON=YES
+SKIP_BEOS=YES
+SKIP_CARBON=YES
+GUITYPE=NONE
+
+if test "x$BEOS" = "xyes"; then
+ SKIP_BEOS=
+ case "$enable_gui_canon" in
+ no) echo "$ac_t""no GUI support" 1>&6
+ SKIP_BEOS=YES ;;
+ yes|"") echo "$ac_t""yes - automatic GUI support" 1>&6 ;;
+ auto) echo "$ac_t""auto - automatic GUI support" 1>&6 ;;
+ beos) echo "$ac_t""BeOS GUI support" 1>&6 ;;
+ *) echo "$ac_t""Sorry, $enable_gui GUI is not supported" 1>&6
+ SKIP_BEOS=YES ;;
+ esac
+
+elif test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then
+ SKIP_PHOTON=
+ case "$enable_gui_canon" in
+ no) echo "$ac_t""no GUI support" 1>&6
+ SKIP_PHOTON=YES ;;
+ yes|"") echo "$ac_t""yes - automatic GUI support" 1>&6 ;;
+ auto) echo "$ac_t""auto - automatic GUI support" 1>&6 ;;
+ photon) echo "$ac_t""Photon GUI support" 1>&6 ;;
+ *) echo "$ac_t""Sorry, $enable_gui GUI is not supported" 1>&6
+ SKIP_PHOTON=YES ;;
+ esac
+
+elif test "x$MACOSX" = "xyes" -a "x$with_x" = "xno" ; then
+ SKIP_CARBON=
+ case "$enable_gui_canon" in
+ no) echo "$ac_t""no GUI support" 1>&6
+ SKIP_CARBON=YES ;;
+ yes|"") echo "$ac_t""yes - automatic GUI support" 1>&6 ;;
+ auto) echo "$ac_t""auto - automatic GUI support" 1>&6 ;;
+ carbon) echo "$ac_t""Carbon GUI support" 1>&6 ;;
+ *) echo "$ac_t""Sorry, $enable_gui GUI is not supported" 1>&6
+ SKIP_CARBON=YES ;;
+ esac
+
+else
+
+
+ case "$enable_gui_canon" in
+ no|none) echo "$ac_t""no GUI support" 1>&6 ;;
+ yes|""|auto) echo "$ac_t""yes/auto - automatic GUI support" 1>&6
+ SKIP_GTK=
+ SKIP_GTK2=
+ SKIP_GNOME=
+ SKIP_MOTIF=
+ SKIP_ATHENA=
+ SKIP_NEXTAW=
+ SKIP_CARBON=;;
+ gtk) echo "$ac_t""GTK+ 1.x GUI support" 1>&6
+ SKIP_GTK=;;
+ gtk2) echo "$ac_t""GTK+ 2.x GUI support" 1>&6
+ SKIP_GTK=
+ SKIP_GTK2=;;
+ gnome) echo "$ac_t""GNOME 1.x GUI support" 1>&6
+ SKIP_GNOME=
+ SKIP_GTK=;;
+ gnome2) echo "$ac_t""GNOME 2.x GUI support" 1>&6
+ SKIP_GNOME=
+ SKIP_GTK=
+ SKIP_GTK2=;;
+ motif) echo "$ac_t""Motif GUI support" 1>&6
+ SKIP_MOTIF=;;
+ athena) echo "$ac_t""Athena GUI support" 1>&6
+ SKIP_ATHENA=;;
+ nextaw) echo "$ac_t""neXtaw GUI support" 1>&6
+ SKIP_NEXTAW=;;
+ *) echo "$ac_t""Sorry, $enable_gui GUI is not supported" 1>&6 ;;
+ esac
+
+fi
+
+if test "x$SKIP_GTK" != "xYES" -a "$enable_gui_canon" != "gtk" -a "$enable_gui_canon" != "gtk2"; then
+ echo $ac_n "checking whether or not to look for GTK""... $ac_c" 1>&6
+echo "configure:3793: checking whether or not to look for GTK" >&5
+ # Check whether --enable-gtk-check or --disable-gtk-check was given.
+if test "${enable_gtk_check+set}" = set; then
+ enableval="$enable_gtk_check"
+ :
+else
+ enable_gtk_check="yes"
+fi
+
+ echo "$ac_t""$enable_gtk_check" 1>&6
+ if test "x$enable_gtk_check" = "xno"; then
+ SKIP_GTK=YES
+ SKIP_GNOME=YES
+ fi
+fi
+
+if test "x$SKIP_GTK2" != "xYES" -a "$enable_gui_canon" != "gtk2" \
+ -a "$enable_gui_canon" != "gnome2"; then
+ echo $ac_n "checking whether or not to look for GTK+ 2""... $ac_c" 1>&6
+echo "configure:3812: checking whether or not to look for GTK+ 2" >&5
+ # Check whether --enable-gtk2-check or --disable-gtk2-check was given.
+if test "${enable_gtk2_check+set}" = set; then
+ enableval="$enable_gtk2_check"
+ :
+else
+ enable_gtk2_check="yes"
+fi
+
+ echo "$ac_t""$enable_gtk2_check" 1>&6
+ if test "x$enable_gtk2_check" = "xno"; then
+ SKIP_GTK2=YES
+ fi
+fi
+
+if test "x$SKIP_GNOME" != "xYES" -a "$enable_gui_canon" != "gnome" \
+ -a "$enable_gui_canon" != "gnome2"; then
+ echo $ac_n "checking whether or not to look for GNOME""... $ac_c" 1>&6
+echo "configure:3830: checking whether or not to look for GNOME" >&5
+ # Check whether --enable-gnome-check or --disable-gnome-check was given.
+if test "${enable_gnome_check+set}" = set; then
+ enableval="$enable_gnome_check"
+ :
+else
+ enable_gnome_check="no"
+fi
+
+ echo "$ac_t""$enable_gnome_check" 1>&6
+ if test "x$enable_gnome_check" = "xno"; then
+ SKIP_GNOME=YES
+ fi
+fi
+
+if test "x$SKIP_MOTIF" != "xYES" -a "$enable_gui_canon" != "motif"; then
+ echo $ac_n "checking whether or not to look for Motif""... $ac_c" 1>&6
+echo "configure:3847: checking whether or not to look for Motif" >&5
+ # Check whether --enable-motif-check or --disable-motif-check was given.
+if test "${enable_motif_check+set}" = set; then
+ enableval="$enable_motif_check"
+ :
+else
+ enable_motif_check="yes"
+fi
+
+ echo "$ac_t""$enable_motif_check" 1>&6
+ if test "x$enable_motif_check" = "xno"; then
+ SKIP_MOTIF=YES
+ fi
+fi
+
+if test "x$SKIP_ATHENA" != "xYES" -a "$enable_gui_canon" != "athena"; then
+ echo $ac_n "checking whether or not to look for Athena""... $ac_c" 1>&6
+echo "configure:3864: checking whether or not to look for Athena" >&5
+ # Check whether --enable-athena-check or --disable-athena-check was given.
+if test "${enable_athena_check+set}" = set; then
+ enableval="$enable_athena_check"
+ :
+else
+ enable_athena_check="yes"
+fi
+
+ echo "$ac_t""$enable_athena_check" 1>&6
+ if test "x$enable_athena_check" = "xno"; then
+ SKIP_ATHENA=YES
+ fi
+fi
+
+if test "x$SKIP_NEXTAW" != "xYES" -a "$enable_gui_canon" != "nextaw"; then
+ echo $ac_n "checking whether or not to look for neXtaw""... $ac_c" 1>&6
+echo "configure:3881: checking whether or not to look for neXtaw" >&5
+ # Check whether --enable-nextaw-check or --disable-nextaw-check was given.
+if test "${enable_nextaw_check+set}" = set; then
+ enableval="$enable_nextaw_check"
+ :
+else
+ enable_nextaw_check="yes"
+fi
+
+ echo "$ac_t""$enable_nextaw_check" 1>&6;
+ if test "x$enable_nextaw_check" = "xno"; then
+ SKIP_NEXTAW=YES
+ fi
+fi
+
+if test "x$SKIP_CARBON" != "xYES" -a "$enable_gui_canon" != "carbon"; then
+ echo $ac_n "checking whether or not to look for Carbon""... $ac_c" 1>&6
+echo "configure:3898: checking whether or not to look for Carbon" >&5
+ # Check whether --enable-carbon-check or --disable-carbon-check was given.
+if test "${enable_carbon_check+set}" = set; then
+ enableval="$enable_carbon_check"
+ :
+else
+ enable_carbon_check="yes"
+fi
+
+ echo "$ac_t""$enable_carbon_check" 1>&6;
+ if test "x$enable_carbon_check" = "xno"; then
+ SKIP_CARBON=YES
+ fi
+fi
+
+if test "x$MACOSX" = "xyes" -a -z "$SKIP_CARBON" -a "x$CARBON" = "xyes"; then
+ echo $ac_n "checking for Carbon GUI""... $ac_c" 1>&6
+echo "configure:3915: checking for Carbon GUI" >&5
+ echo "$ac_t""yes" 1>&6;
+ GUITYPE=CARBONGUI
+ SKIP_GTK=YES;
+ SKIP_GTK2=YES;
+ SKIP_GNOME=YES;
+ SKIP_MOTIF=YES;
+ SKIP_ATHENA=YES;
+ SKIP_NEXTAW=YES;
+ SKIP_PHOTON=YES;
+ SKIP_BEOS=YES;
+ SKIP_CARBON=YES
+fi
+
+
+
+
+
+
+
+
+
+
+if test -z "$SKIP_GTK"; then
+
+ echo $ac_n "checking --with-gtk-prefix argument""... $ac_c" 1>&6
+echo "configure:3941: checking --with-gtk-prefix argument" >&5
+ # Check whether --with-gtk-prefix or --without-gtk-prefix was given.
+if test "${with_gtk_prefix+set}" = set; then
+ withval="$with_gtk_prefix"
+ gtk_config_prefix="$withval"; echo "$ac_t""$gtk_config_prefix" 1>&6
+else
+ gtk_config_prefix=""; echo "$ac_t""no" 1>&6
+fi
+
+
+ echo $ac_n "checking --with-gtk-exec-prefix argument""... $ac_c" 1>&6
+echo "configure:3952: checking --with-gtk-exec-prefix argument" >&5
+ # Check whether --with-gtk-exec-prefix or --without-gtk-exec-prefix was given.
+if test "${with_gtk_exec_prefix+set}" = set; then
+ withval="$with_gtk_exec_prefix"
+ gtk_config_exec_prefix="$withval"; echo "$ac_t""$gtk_config_prefix" 1>&6
+else
+ gtk_config_exec_prefix=""; echo "$ac_t""no" 1>&6
+fi
+
+
+ echo $ac_n "checking --disable-gtktest argument""... $ac_c" 1>&6
+echo "configure:3963: checking --disable-gtktest argument" >&5
+ # Check whether --enable-gtktest or --disable-gtktest was given.
+if test "${enable_gtktest+set}" = set; then
+ enableval="$enable_gtktest"
+ :
+else
+ enable_gtktest=yes
+fi
+
+ if test "x$enable_gtktest" = "xyes" ; then
+ echo "$ac_t""gtk test enabled" 1>&6
+ else
+ echo "$ac_t""gtk test disabled" 1>&6
+ fi
+
+ if test "x$gtk_config_prefix" != "x" ; then
+ gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix"
+ GTK_CONFIG=$gtk_config_prefix/bin/gtk-config
+ fi
+ if test "x$gtk_config_exec_prefix" != "x" ; then
+ gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix"
+ GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config
+ fi
+ if test "X$GTK_CONFIG" = "X"; then
+ # Extract the first word of "gtk-config", so it can be a program name with args.
+set dummy gtk-config; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3990: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GTK_CONFIG'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GTK_CONFIG" in
+ /*)
+ ac_cv_path_GTK_CONFIG="$GTK_CONFIG" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_GTK_CONFIG="$GTK_CONFIG" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GTK_CONFIG="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GTK_CONFIG" && ac_cv_path_GTK_CONFIG="no"
+ ;;
+esac
+fi
+GTK_CONFIG="$ac_cv_path_GTK_CONFIG"
+if test -n "$GTK_CONFIG"; then
+ echo "$ac_t""$GTK_CONFIG" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "X$GTK_CONFIG" = "Xno"; then
+ # Extract the first word of "gtk12-config", so it can be a program name with args.
+set dummy gtk12-config; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:4027: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GTK12_CONFIG'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GTK12_CONFIG" in
+ /*)
+ ac_cv_path_GTK12_CONFIG="$GTK12_CONFIG" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_GTK12_CONFIG="$GTK12_CONFIG" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GTK12_CONFIG="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GTK12_CONFIG" && ac_cv_path_GTK12_CONFIG="no"
+ ;;
+esac
+fi
+GTK12_CONFIG="$ac_cv_path_GTK12_CONFIG"
+if test -n "$GTK12_CONFIG"; then
+ echo "$ac_t""$GTK12_CONFIG" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ GTK_CONFIG="$GTK12_CONFIG"
+ fi
+ else
+ echo "$ac_t""Using GTK configuration program $GTK_CONFIG" 1>&6
+ fi
+ if test "X$PKG_CONFIG" = "X"; then
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:4069: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$PKG_CONFIG" in
+ /*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_PKG_CONFIG="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
+ ;;
+esac
+fi
+PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+if test -n "$PKG_CONFIG"; then
+ echo "$ac_t""$PKG_CONFIG" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ if test "x$GTK_CONFIG:$PKG_CONFIG" != "xno:no"; then
+ if test "X$SKIP_GTK2" != "XYES"; then
+
+ if test "X$GTK_CONFIG" != "Xno" -o "X$PKG_CONFIG" != "Xno"; then
+ {
+ min_gtk_version=2.2.0
+ echo $ac_n "checking for GTK - version >= $min_gtk_version""... $ac_c" 1>&6
+echo "configure:4111: checking for GTK - version >= $min_gtk_version" >&5
+ no_gtk=""
+ if (test "X$SKIP_GTK2" != "XYES" -a "X$PKG_CONFIG" != "Xno") \
+ && $PKG_CONFIG --exists gtk+-2.0; then
+ {
+ GTK_CFLAGS=`$PKG_CONFIG --cflags gtk+-2.0`
+ GTK_LIBS=`$PKG_CONFIG --libs gtk+-2.0`
+ gtk_major_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+ gtk_minor_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+ gtk_micro_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+ }
+ elif test "X$GTK_CONFIG" != "Xno"; then
+ {
+ GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+ GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+ gtk_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+ gtk_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+ gtk_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+ }
+ else
+ no_gtk=yes
+ fi
+
+ if test "x$enable_gtktest" = "xyes" -a "x$no_gtk" = "x"; then
+ {
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$LIBS $GTK_LIBS"
+
+ rm -f conf.gtktest
+ if test "$cross_compiling" = yes; then
+ echo $ac_n "cross compiling; assumed OK... $ac_c"
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4152 "configure"
+#include "confdefs.h"
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+
+int
+main ()
+{
+int major, minor, micro;
+char *tmp_version;
+
+system ("touch conf.gtktest");
+
+/* HP/UX 9 (%@#!) writes to sscanf strings */
+tmp_version = g_strdup("$min_gtk_version");
+if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+ printf("%s, bad version string\n", "$min_gtk_version");
+ exit(1);
+ }
+
+if ((gtk_major_version > major) ||
+ ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+ ((gtk_major_version == major) && (gtk_minor_version == minor) &&
+ (gtk_micro_version >= micro)))
+{
+ return 0;
+}
+return 1;
+}
+
+EOF
+if { (eval echo configure:4184: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ no_gtk=yes
+fi
+rm -fr conftest*
+fi
+
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ }
+ fi
+ if test "x$no_gtk" = x ; then
+ if test "x$enable_gtktest" = "xyes"; then
+ echo "$ac_t""yes; found version $gtk_major_version.$gtk_minor_version.$gtk_micro_version" 1>&6
+ else
+ echo "$ac_t""found version $gtk_major_version.$gtk_minor_version.$gtk_micro_version" 1>&6
+ fi
+ GTK_LIBNAME="$GTK_LIBS"
+ GUI_INC_LOC="$GTK_CFLAGS"
+ else
+ {
+ echo "$ac_t""no" 1>&6
+ GTK_CFLAGS=""
+ GTK_LIBS=""
+ :
+ }
+ fi
+ }
+ else
+ GTK_CFLAGS=""
+ GTK_LIBS=""
+ :
+ fi
+
+
+ rm -f conf.gtktest
+
+ if test "x$GTK_CFLAGS" != "x"; then
+ SKIP_ATHENA=YES
+ SKIP_NEXTAW=YES
+ SKIP_MOTIF=YES
+ GUITYPE=GTK
+
+ fi
+ fi
+
+ if test "x$GUITYPE" != "xGTK"; then
+ SKIP_GTK2=YES
+
+ if test "X$GTK_CONFIG" != "Xno" -o "X$PKG_CONFIG" != "Xno"; then
+ {
+ min_gtk_version=1.1.16
+ echo $ac_n "checking for GTK - version >= $min_gtk_version""... $ac_c" 1>&6
+echo "configure:4242: checking for GTK - version >= $min_gtk_version" >&5
+ no_gtk=""
+ if (test "X$SKIP_GTK2" != "XYES" -a "X$PKG_CONFIG" != "Xno") \
+ && $PKG_CONFIG --exists gtk+-2.0; then
+ {
+ GTK_CFLAGS=`$PKG_CONFIG --cflags gtk+-2.0`
+ GTK_LIBS=`$PKG_CONFIG --libs gtk+-2.0`
+ gtk_major_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+ gtk_minor_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+ gtk_micro_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+ }
+ elif test "X$GTK_CONFIG" != "Xno"; then
+ {
+ GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+ GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+ gtk_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+ gtk_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+ gtk_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+ }
+ else
+ no_gtk=yes
+ fi
+
+ if test "x$enable_gtktest" = "xyes" -a "x$no_gtk" = "x"; then
+ {
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$LIBS $GTK_LIBS"
+
+ rm -f conf.gtktest
+ if test "$cross_compiling" = yes; then
+ echo $ac_n "cross compiling; assumed OK... $ac_c"
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4283 "configure"
+#include "confdefs.h"
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+
+int
+main ()
+{
+int major, minor, micro;
+char *tmp_version;
+
+system ("touch conf.gtktest");
+
+/* HP/UX 9 (%@#!) writes to sscanf strings */
+tmp_version = g_strdup("$min_gtk_version");
+if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+ printf("%s, bad version string\n", "$min_gtk_version");
+ exit(1);
+ }
+
+if ((gtk_major_version > major) ||
+ ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+ ((gtk_major_version == major) && (gtk_minor_version == minor) &&
+ (gtk_micro_version >= micro)))
+{
+ return 0;
+}
+return 1;
+}
+
+EOF
+if { (eval echo configure:4315: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ no_gtk=yes
+fi
+rm -fr conftest*
+fi
+
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ }
+ fi
+ if test "x$no_gtk" = x ; then
+ if test "x$enable_gtktest" = "xyes"; then
+ echo "$ac_t""yes; found version $gtk_major_version.$gtk_minor_version.$gtk_micro_version" 1>&6
+ else
+ echo "$ac_t""found version $gtk_major_version.$gtk_minor_version.$gtk_micro_version" 1>&6
+ fi
+ GTK_LIBNAME="$GTK_LIBS"
+ GUI_INC_LOC="$GTK_CFLAGS"
+ else
+ {
+ echo "$ac_t""no" 1>&6
+ GTK_CFLAGS=""
+ GTK_LIBS=""
+ :
+ }
+ fi
+ }
+ else
+ GTK_CFLAGS=""
+ GTK_LIBS=""
+ :
+ fi
+
+
+ rm -f conf.gtktest
+
+ if test "x$GTK_CFLAGS" != "x"; then
+ SKIP_ATHENA=YES
+ SKIP_NEXTAW=YES
+ SKIP_MOTIF=YES
+ GUITYPE=GTK
+
+ fi
+ fi
+ fi
+ if test "x$GUITYPE" = "xGTK"; then
+ if test "$gtk_major_version" = 1 -a "0$gtk_minor_version" -lt 2 \
+ -o "$gtk_major_version" = 1 -a "$gtk_minor_version" = 2 -a "0$gtk_micro_version" -lt 3; then
+ echo "$ac_t""this GTK version is old; version 1.2.3 or later is recommended" 1>&6
+ else
+ {
+ if test "0$gtk_major_version" -ge 2; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_GTK2 1
+EOF
+
+ if test "$gtk_minor_version" = 1 -a "0$gtk_micro_version" -ge 1 \
+ || test "0$gtk_minor_version" -ge 2 \
+ || test "0$gtk_major_version" -gt 2; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_GTK_MULTIHEAD 1
+EOF
+
+ fi
+ fi
+ if test -z "$SKIP_GNOME"; then
+ {
+
+
+
+
+
+ # Check whether --with-gnome-includes or --without-gnome-includes was given.
+if test "${with_gnome_includes+set}" = set; then
+ withval="$with_gnome_includes"
+ CFLAGS="$CFLAGS -I$withval"
+
+fi
+
+
+ # Check whether --with-gnome-libs or --without-gnome-libs was given.
+if test "${with_gnome_libs+set}" = set; then
+ withval="$with_gnome_libs"
+ LDFLAGS="$LDFLAGS -L$withval" gnome_prefix=$withval
+
+fi
+
+
+ # Check whether --with-gnome or --without-gnome was given.
+if test "${with_gnome+set}" = set; then
+ withval="$with_gnome"
+ if test x$withval = xyes; then
+ want_gnome=yes
+ have_gnome=yes
+ else
+ if test "x$withval" = xno; then
+ want_gnome=no
+ else
+ want_gnome=yes
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ CFLAGS="$CFLAGS -I$withval/include"
+ gnome_prefix=$withval/lib
+ fi
+ fi
+else
+ want_gnome=yes
+fi
+
+
+ if test "x$want_gnome" = xyes -a "0$gtk_major_version" -ge 2; then
+ {
+ echo $ac_n "checking for libgnomeui-2.0""... $ac_c" 1>&6
+echo "configure:4433: checking for libgnomeui-2.0" >&5
+ if $PKG_CONFIG --exists libgnomeui-2.0; then
+ echo "$ac_t""yes" 1>&6
+ GNOME_LIBS=`$PKG_CONFIG --libs-only-l libgnomeui-2.0`
+ GNOME_LIBDIR=`$PKG_CONFIG --libs-only-L libgnomeui-2.0`
+ GNOME_INCLUDEDIR=`$PKG_CONFIG --cflags libgnomeui-2.0`
+ have_gnome=yes
+ else
+ echo "$ac_t""not found" 1>&6
+ if test "x" = xfail; then
+ { echo "configure: error: Could not find libgnomeui-2.0 via pkg-config" 1>&2; exit 1; }
+ fi
+ fi
+ }
+ elif test "x$want_gnome" = xyes; then
+ {
+ # Extract the first word of "gnome-config", so it can be a program name with args.
+set dummy gnome-config; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:4452: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GNOME_CONFIG'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GNOME_CONFIG" in
+ /*)
+ ac_cv_path_GNOME_CONFIG="$GNOME_CONFIG" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_GNOME_CONFIG="$GNOME_CONFIG" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GNOME_CONFIG="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GNOME_CONFIG" && ac_cv_path_GNOME_CONFIG="no"
+ ;;
+esac
+fi
+GNOME_CONFIG="$ac_cv_path_GNOME_CONFIG"
+if test -n "$GNOME_CONFIG"; then
+ echo "$ac_t""$GNOME_CONFIG" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "$GNOME_CONFIG" = "no"; then
+ no_gnome_config="yes"
+ else
+ echo $ac_n "checking if $GNOME_CONFIG works""... $ac_c" 1>&6
+echo "configure:4489: checking if $GNOME_CONFIG works" >&5
+ if $GNOME_CONFIG --libs-only-l gnome >/dev/null 2>&1; then
+ echo "$ac_t""yes" 1>&6
+ GNOME_LIBS="`$GNOME_CONFIG --libs-only-l gnome gnomeui`"
+ GNOME_LIBDIR="`$GNOME_CONFIG --libs-only-L gnorba gnomeui`"
+ GNOME_INCLUDEDIR="`$GNOME_CONFIG --cflags gnorba gnomeui`"
+ have_gnome=yes
+ else
+ echo "$ac_t""no" 1>&6
+ no_gnome_config="yes"
+ fi
+ fi
+
+ if test x$exec_prefix = xNONE; then
+ if test x$prefix = xNONE; then
+ gnome_prefix=$ac_default_prefix/lib
+ else
+ gnome_prefix=$prefix/lib
+ fi
+ else
+ gnome_prefix=`eval echo \`echo $libdir\``
+ fi
+
+ if test "$no_gnome_config" = "yes"; then
+ echo $ac_n "checking for gnomeConf.sh file in $gnome_prefix""... $ac_c" 1>&6
+echo "configure:4514: checking for gnomeConf.sh file in $gnome_prefix" >&5
+ if test -f $gnome_prefix/gnomeConf.sh; then
+ echo "$ac_t""found" 1>&6
+ echo "loading gnome configuration from" \
+ "$gnome_prefix/gnomeConf.sh"
+ . $gnome_prefix/gnomeConf.sh
+ have_gnome=yes
+ else
+ echo "$ac_t""not found" 1>&6
+ if test x = xfail; then
+ { echo "configure: error: Could not find the gnomeConf.sh file that is generated by gnome-libs install" 1>&2; exit 1; }
+ fi
+ fi
+ fi
+ }
+ fi
+
+ if test x$have_gnome = xyes ; then
+ cat >> confdefs.h <<\EOF
+#define FEAT_GUI_GNOME 1
+EOF
+
+ GUI_INC_LOC="$GUI_INC_LOC $GNOME_INCLUDEDIR"
+ GTK_LIBNAME="$GTK_LIBNAME $GNOME_LIBDIR $GNOME_LIBS"
+ fi
+ }
+ fi
+ }
+ fi
+ fi
+fi
+
+
+if test -z "$SKIP_MOTIF"; then
+ gui_XXX="/usr/XXX/Motif* /usr/Motif*/XXX /usr/XXX /usr/shlib /usr/X11*/XXX /usr/XXX/X11* /usr/dt/XXX /local/Motif*/XXX /local/XXX/Motif* /usr/local/Motif*/XXX /usr/local/XXX/Motif* /usr/local/XXX /usr/local/X11*/XXX /usr/local/LessTif/Motif*/XXX $MOTIFHOME/XXX"
+ GUI_INC_LOC="`echo $GUI_INC_LOC|sed 's%-I%%g'`"
+
+ echo $ac_n "checking for location of Motif GUI includes""... $ac_c" 1>&6
+echo "configure:4552: checking for location of Motif GUI includes" >&5
+ gui_includes="`echo $x_includes|sed 's%/^/^/*$%%'` `echo "$gui_XXX" | sed s/XXX/include/g` $GUI_INC_LOC"
+ GUI_INC_LOC=
+ for try in $gui_includes; do
+ if test -f "$try/Xm/Xm.h"; then
+ GUI_INC_LOC=$try
+ fi
+ done
+ if test -n "$GUI_INC_LOC"; then
+ if test "$GUI_INC_LOC" = /usr/include; then
+ GUI_INC_LOC=
+ echo "$ac_t""in default path" 1>&6
+ else
+ echo "$ac_t""$GUI_INC_LOC" 1>&6
+ fi
+ else
+ echo "$ac_t""<not found>" 1>&6
+ SKIP_MOTIF=YES
+ fi
+fi
+
+
+if test -z "$SKIP_MOTIF"; then
+ echo $ac_n "checking --with-motif-lib argument""... $ac_c" 1>&6
+echo "configure:4576: checking --with-motif-lib argument" >&5
+ # Check whether --with-motif-lib or --without-motif-lib was given.
+if test "${with_motif_lib+set}" = set; then
+ withval="$with_motif_lib"
+ MOTIF_LIBNAME="${withval}"
+fi
+
+
+ if test -n "$MOTIF_LIBNAME"; then
+ echo "$ac_t""$MOTIF_LIBNAME" 1>&6
+ GUI_LIB_LOC=
+ else
+ echo "$ac_t""no" 1>&6
+
+ GUI_LIB_LOC="`echo $GUI_LIB_LOC|sed 's%-L%%g'`"
+
+ echo $ac_n "checking for location of Motif GUI libs""... $ac_c" 1>&6
+echo "configure:4593: checking for location of Motif GUI libs" >&5
+ gui_libs="`echo $x_libraries|sed 's%/^/^/*$%%'` `echo "$gui_XXX" | sed s/XXX/lib/g` `echo "$GUI_INC_LOC" | sed s/include/lib/` $GUI_LIB_LOC"
+ GUI_LIB_LOC=
+ for try in $gui_libs; do
+ for libtry in "$try"/libXm.a "$try"/libXm.so* "$try"/libXm.sl; do
+ if test -f "$libtry"; then
+ GUI_LIB_LOC=$try
+ fi
+ done
+ done
+ if test -n "$GUI_LIB_LOC"; then
+ if test "$GUI_LIB_LOC" = /usr/lib; then
+ GUI_LIB_LOC=
+ echo "$ac_t""in default path" 1>&6
+ else
+ if test -n "$GUI_LIB_LOC"; then
+ echo "$ac_t""$GUI_LIB_LOC" 1>&6
+ if test "`(uname) 2>/dev/null`" = SunOS &&
+ uname -r | grep '^5' >/dev/null; then
+ GUI_LIB_LOC="$GUI_LIB_LOC -R $GUI_LIB_LOC"
+ fi
+ fi
+ fi
+ MOTIF_LIBNAME=-lXm
+ else
+ echo "$ac_t""<not found>" 1>&6
+ SKIP_MOTIF=YES
+ fi
+ fi
+fi
+
+if test -z "$SKIP_MOTIF"; then
+ SKIP_ATHENA=YES
+ SKIP_NEXTAW=YES
+ GUITYPE=MOTIF
+
+fi
+
+
+GUI_X_LIBS=
+
+if test -z "$SKIP_ATHENA"; then
+ echo $ac_n "checking if Athena header files can be found""... $ac_c" 1>&6
+echo "configure:4636: checking if Athena header files can be found" >&5
+ cflags_save=$CFLAGS
+ CFLAGS="$CFLAGS $X_CFLAGS"
+ cat > conftest.$ac_ext <<EOF
+#line 4640 "configure"
+#include "confdefs.h"
+
+#include <X11/Intrinsic.h>
+#include <X11/Xaw/Paned.h>
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:4649: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6; SKIP_ATHENA=YES
+fi
+rm -f conftest*
+ CFLAGS=$cflags_save
+fi
+
+if test -z "$SKIP_ATHENA"; then
+ GUITYPE=ATHENA
+fi
+
+if test -z "$SKIP_NEXTAW"; then
+ echo $ac_n "checking if neXtaw header files can be found""... $ac_c" 1>&6
+echo "configure:4668: checking if neXtaw header files can be found" >&5
+ cflags_save=$CFLAGS
+ CFLAGS="$CFLAGS $X_CFLAGS"
+ cat > conftest.$ac_ext <<EOF
+#line 4672 "configure"
+#include "confdefs.h"
+
+#include <X11/Intrinsic.h>
+#include <X11/neXtaw/Paned.h>
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:4681: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6; SKIP_NEXTAW=YES
+fi
+rm -f conftest*
+ CFLAGS=$cflags_save
+fi
+
+if test -z "$SKIP_NEXTAW"; then
+ GUITYPE=NEXTAW
+fi
+
+if test -z "$SKIP_ATHENA" -o -z "$SKIP_NEXTAW" -o -z "$SKIP_MOTIF"; then
+ if test -n "$GUI_INC_LOC"; then
+ GUI_INC_LOC=-I"`echo $GUI_INC_LOC|sed 's%-I%%'`"
+ fi
+ if test -n "$GUI_LIB_LOC"; then
+ GUI_LIB_LOC=-L"`echo $GUI_LIB_LOC|sed 's%-L%%'`"
+ fi
+
+ ldflags_save=$LDFLAGS
+ LDFLAGS="$X_LIBS $LDFLAGS"
+ echo $ac_n "checking for XShapeQueryExtension in -lXext""... $ac_c" 1>&6
+echo "configure:4709: checking for XShapeQueryExtension in -lXext" >&5
+ac_lib_var=`echo Xext'_'XShapeQueryExtension | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lXext -lXt $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4717 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char XShapeQueryExtension();
+
+int main() {
+XShapeQueryExtension()
+; return 0; }
+EOF
+if { (eval echo configure:4728: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ GUI_X_LIBS="-lXext"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ echo $ac_n "checking for wslen in -lw""... $ac_c" 1>&6
+echo "configure:4749: checking for wslen in -lw" >&5
+ac_lib_var=`echo w'_'wslen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lw $GUI_X_LIBS -lXt $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4757 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char wslen();
+
+int main() {
+wslen()
+; return 0; }
+EOF
+if { (eval echo configure:4768: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lw"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ echo $ac_n "checking for dlsym in -ldl""... $ac_c" 1>&6
+echo "configure:4789: checking for dlsym in -ldl" >&5
+ac_lib_var=`echo dl'_'dlsym | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldl $GUI_X_LIBS -lXt $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4797 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlsym();
+
+int main() {
+dlsym()
+; return 0; }
+EOF
+if { (eval echo configure:4808: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -ldl"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ echo $ac_n "checking for XmuCreateStippledPixmap in -lXmu""... $ac_c" 1>&6
+echo "configure:4829: checking for XmuCreateStippledPixmap in -lXmu" >&5
+ac_lib_var=`echo Xmu'_'XmuCreateStippledPixmap | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lXmu $GUI_X_LIBS -lXt $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4837 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char XmuCreateStippledPixmap();
+
+int main() {
+XmuCreateStippledPixmap()
+; return 0; }
+EOF
+if { (eval echo configure:4848: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ GUI_X_LIBS="-lXmu $GUI_X_LIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$SKIP_MOTIF"; then
+ echo $ac_n "checking for XpEndJob in -lXp""... $ac_c" 1>&6
+echo "configure:4870: checking for XpEndJob in -lXp" >&5
+ac_lib_var=`echo Xp'_'XpEndJob | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lXp $GUI_X_LIBS -lXm -lXt $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4878 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char XpEndJob();
+
+int main() {
+XpEndJob()
+; return 0; }
+EOF
+if { (eval echo configure:4889: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ GUI_X_LIBS="-lXp $GUI_X_LIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+ LDFLAGS=$ldflags_save
+
+ echo $ac_n "checking for extra X11 defines""... $ac_c" 1>&6
+echo "configure:4913: checking for extra X11 defines" >&5
+ NARROW_PROTO=
+ rm -fr conftestdir
+ if mkdir conftestdir; then
+ cd conftestdir
+ cat > Imakefile <<'EOF'
+acfindx:
+ @echo 'NARROW_PROTO="${PROTO_DEFINES}"'
+EOF
+ if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then
+ eval `${MAKE-make} acfindx 2>/dev/null | grep -v make`
+ fi
+ cd ..
+ rm -fr conftestdir
+ fi
+ if test -z "$NARROW_PROTO"; then
+ echo "$ac_t""no" 1>&6
+ else
+ echo "$ac_t""$NARROW_PROTO" 1>&6
+ fi
+
+fi
+
+if test "$enable_xsmp" = "yes"; then
+ cppflags_save=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+ for ac_hdr in X11/SM/SMlib.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:4943: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4948 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:4953: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ CPPFLAGS=$cppflags_save
+fi
+
+
+if test -z "$SKIP_ATHENA" -o -z "$SKIP_NEXTAW" -o -z "$SKIP_MOTIF" -o -z "$SKIP_GTK"; then
+ cppflags_save=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+ for ac_hdr in X11/xpm.h X11/Sunkeysym.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:4990: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4995 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5000: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+ if test ! "$enable_xim" = "no"; then
+ echo $ac_n "checking for XIMText in X11/Xlib.h""... $ac_c" 1>&6
+echo "configure:5029: checking for XIMText in X11/Xlib.h" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 5031 "configure"
+#include "confdefs.h"
+#include <X11/Xlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "XIMText" >/dev/null 2>&1; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+else
+ rm -rf conftest*
+ echo "$ac_t""no; xim has been disabled" 1>&6; enable_xim = "no"
+fi
+rm -f conftest*
+
+ fi
+ CPPFLAGS=$cppflags_save
+
+ if test "$enable_xim" = "auto" -a "$enable_hangulinput" != "yes" \
+ -a "x$GUITYPE" != "xNONE" ; then
+ echo "$ac_t""X GUI selected; xim has been enabled" 1>&6
+ enable_xim="yes"
+ fi
+fi
+
+if test -z "$SKIP_ATHENA" -o -z "$SKIP_NEXTAW" -o -z "$SKIP_MOTIF"; then
+ cppflags_save=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+ for ac_hdr in X11/Xmu/Editres.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:5062: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5067 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5072: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ CPPFLAGS=$cppflags_save
+fi
+
+if test -z "$SKIP_MOTIF"; then
+ cppflags_save=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+ for ac_hdr in Xm/Xm.h Xm/XpmP.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:5108: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5113 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5118: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ CPPFLAGS=$cppflags_save
+fi
+
+if test "x$GUITYPE" = "xNONE" -a "$enable_xim" = "yes"; then
+ echo "$ac_t""no GUI selected; xim has been disabled" 1>&6
+ enable_xim="no"
+fi
+if test "x$GUITYPE" = "xNONE" -a "$enable_fontset" = "yes"; then
+ echo "$ac_t""no GUI selected; fontset has been disabled" 1>&6
+ enable_fontset="no"
+fi
+if test "x$GUITYPE:$enable_fontset" = "xGTK:yes" -a "0$gtk_major_version" -ge 2; then
+ echo "$ac_t""GTK+ 2 GUI selected; fontset has been disabled" 1>&6
+ enable_fontset="no"
+fi
+
+if test -z "$SKIP_BEOS"; then
+ GUITYPE=BEOSGUI
+fi
+
+if test -z "$SKIP_PHOTON"; then
+ GUITYPE=PHOTONGUI
+fi
+
+
+
+
+
+
+if test "$enable_workshop" = "yes" -a -n "$SKIP_MOTIF"; then
+ { echo "configure: error: cannot use workshop without Motif" 1>&2; exit 1; }
+fi
+
+if test "$enable_xim" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define FEAT_XIM 1
+EOF
+
+fi
+if test "$enable_fontset" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define FEAT_XFONTSET 1
+EOF
+
+fi
+
+
+
+
+if test "$enable_hangulinput" = "yes"; then
+ if test "x$GUITYPE" = "xNONE"; then
+ echo "$ac_t""no GUI selected; hangul input has been disabled" 1>&6
+ enable_hangulinput=no
+ else
+ cat >> confdefs.h <<\EOF
+#define FEAT_HANGULIN 1
+EOF
+
+ HANGULIN_SRC=hangulin.c
+
+ HANGULIN_OBJ=objects/hangulin.o
+
+ fi
+fi
+
+
+echo $ac_n "checking quality of toupper""... $ac_c" 1>&6
+echo "configure:5211: checking quality of toupper" >&5
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: failed to compile test program" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5216 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+main() { exit(toupper('A') == 'A' && tolower('z') == 'z'); }
+EOF
+if { (eval echo configure:5221: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ cat >> confdefs.h <<\EOF
+#define BROKEN_TOUPPER 1
+EOF
+ echo "$ac_t""bad" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ echo "$ac_t""good" 1>&6
+fi
+rm -fr conftest*
+fi
+
+
+echo $ac_n "checking whether __DATE__ and __TIME__ work""... $ac_c" 1>&6
+echo "configure:5238: checking whether __DATE__ and __TIME__ work" >&5
+cat > conftest.$ac_ext <<EOF
+#line 5240 "configure"
+#include "confdefs.h"
+
+int main() {
+printf("(" __DATE__ " " __TIME__ ")");
+; return 0; }
+EOF
+if { (eval echo configure:5247: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_DATE_TIME 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+ac_safe=`echo "elf.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for elf.h""... $ac_c" 1>&6
+echo "configure:5263: checking for elf.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5268 "configure"
+#include "confdefs.h"
+#include <elf.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5273: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ HAS_ELF=1
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test "$HAS_ELF" = 1; then
+ echo $ac_n "checking for main in -lelf""... $ac_c" 1>&6
+echo "configure:5296: checking for main in -lelf" >&5
+ac_lib_var=`echo elf'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lelf $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5304 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:5311: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo elf | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lelf $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
+echo "configure:5345: checking for $ac_hdr that defines DIR" >&5
+if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5350 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_hdr>
+int main() {
+DIR *dirp = 0;
+; return 0; }
+EOF
+if { (eval echo configure:5358: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ ac_header_dirent=$ac_hdr; break
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
+echo "configure:5383: checking for opendir in -ldir" >&5
+ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldir $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5391 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:5402: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -ldir"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
+echo "configure:5424: checking for opendir in -lx" >&5
+ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lx $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5432 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:5443: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lx"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:5467: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5472 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5480: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 5497 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 5515 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5536 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:5547: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
+echo "configure:5571: checking for sys/wait.h that is POSIX.1 compatible" >&5
+if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5576 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+int main() {
+int s;
+wait (&s);
+s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+; return 0; }
+EOF
+if { (eval echo configure:5592: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
+if test $ac_cv_header_sys_wait_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+fi
+
+
+if test $ac_cv_header_sys_wait_h = no; then
+ echo $ac_n "checking for sys/wait.h that defines union wait""... $ac_c" 1>&6
+echo "configure:5615: checking for sys/wait.h that defines union wait" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 5617 "configure"
+#include "confdefs.h"
+#include <sys/wait.h>
+int main() {
+union wait xx, yy; xx = yy
+; return 0; }
+EOF
+if { (eval echo configure:5624: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_UNION_WAIT 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+fi
+
+for ac_hdr in stdarg.h stdlib.h string.h sys/select.h sys/utsname.h \
+ termcap.h fcntl.h sgtty.h sys/ioctl.h sys/time.h termio.h \
+ iconv.h langinfo.h unistd.h stropts.h errno.h \
+ sys/resource.h sys/systeminfo.h locale.h \
+ sys/stream.h sys/ptem.h termios.h libc.h sys/statfs.h \
+ poll.h sys/poll.h pwd.h utime.h sys/param.h libintl.h \
+ libgen.h util/debug.h util/msg18n.h frame.h pthread_np.h \
+ sys/acl.h sys/access.h sys/sysctl.h sys/sysinfo.h wchar.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:5655: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5660 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5665: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+if test "x$MACOSX" != "xyes"; then
+ for ac_hdr in strings.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:5697: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5702 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5707: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking if strings.h can be included after string.h""... $ac_c" 1>&6
+echo "configure:5736: checking if strings.h can be included after string.h" >&5
+cppflags_save=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+cat > conftest.$ac_ext <<EOF
+#line 5740 "configure"
+#include "confdefs.h"
+
+#if defined(_AIX) && !defined(_AIX51) && !defined(_NO_PROTO)
+# define _NO_PROTO /* like in os_unix.h, causes conflict for AIX (Winn) */
+ /* but don't do it on AIX 5.1 (Uribarri) */
+#endif
+#ifdef HAVE_XM_XM_H
+# include <Xm/Xm.h> /* This breaks it for HP-UX 11 (Squassabia) */
+#endif
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#if defined(HAVE_STRINGS_H)
+# include <strings.h>
+#endif
+
+int main() {
+int i; i = 0;
+; return 0; }
+EOF
+if { (eval echo configure:5761: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define NO_STRINGS_WITH_STRING_H 1
+EOF
+
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+CPPFLAGS=$cppflags_save
+
+if test $ac_cv_prog_gcc = yes; then
+ echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
+echo "configure:5779: checking whether ${CC-cc} needs -traditional" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat > conftest.$ac_ext <<EOF
+#line 5785 "configure"
+#include "confdefs.h"
+#include <sgtty.h>
+Autoconf TIOCGETP
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "$ac_pattern" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=yes
+else
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat > conftest.$ac_ext <<EOF
+#line 5803 "configure"
+#include "confdefs.h"
+#include <termio.h>
+Autoconf TCGETA
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "$ac_pattern" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:5825: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5830 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:5879: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for mode_t""... $ac_c" 1>&6
+echo "configure:5900: checking for mode_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5905 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])mode_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_mode_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_mode_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_mode_t" 1>&6
+if test $ac_cv_type_mode_t = no; then
+ cat >> confdefs.h <<\EOF
+#define mode_t int
+EOF
+
+fi
+
+echo $ac_n "checking for off_t""... $ac_c" 1>&6
+echo "configure:5933: checking for off_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5938 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_off_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_off_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_off_t" 1>&6
+if test $ac_cv_type_off_t = no; then
+ cat >> confdefs.h <<\EOF
+#define off_t long
+EOF
+
+fi
+
+echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+echo "configure:5966: checking for pid_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5971 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_pid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_pid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_pid_t" 1>&6
+if test $ac_cv_type_pid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define pid_t int
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:5999: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6004 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_size_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+ cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
+echo "configure:6032: checking for uid_t in sys/types.h" >&5
+if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6037 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "uid_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_uid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_uid_t=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_type_uid_t" 1>&6
+if test $ac_cv_type_uid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define uid_t int
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define gid_t int
+EOF
+
+fi
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:6066: checking whether time.h and sys/time.h may both be included" >&5
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6071 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:6080: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+ cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+echo $ac_n "checking for ino_t""... $ac_c" 1>&6
+echo "configure:6101: checking for ino_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_ino_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6106 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])ino_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_ino_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_ino_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_ino_t" 1>&6
+if test $ac_cv_type_ino_t = no; then
+ cat >> confdefs.h <<\EOF
+#define ino_t long
+EOF
+
+fi
+
+echo $ac_n "checking for dev_t""... $ac_c" 1>&6
+echo "configure:6134: checking for dev_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_dev_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6139 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])dev_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_dev_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_dev_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_dev_t" 1>&6
+if test $ac_cv_type_dev_t = no; then
+ cat >> confdefs.h <<\EOF
+#define dev_t unsigned
+EOF
+
+fi
+
+
+echo $ac_n "checking for rlim_t""... $ac_c" 1>&6
+echo "configure:6168: checking for rlim_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_rlim_t'+set}'`\" = set"; then
+ echo "$ac_t""(cached) $ac_cv_type_rlim_t" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6173 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])rlim_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_rlim_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_rlim_t=no
+fi
+rm -f conftest*
+
+ echo "$ac_t""$ac_cv_type_rlim_t" 1>&6
+fi
+if test $ac_cv_type_rlim_t = no; then
+ cat >> confdefs.h <<\EOF
+#define rlim_t unsigned long
+EOF
+fi
+
+echo $ac_n "checking for stack_t""... $ac_c" 1>&6
+echo "configure:6205: checking for stack_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_stack_t'+set}'`\" = set"; then
+ echo "$ac_t""(cached) $ac_cv_type_stack_t" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6210 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#include <signal.h>
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "stack_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_stack_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_stack_t=no
+fi
+rm -f conftest*
+
+ echo "$ac_t""$ac_cv_type_stack_t" 1>&6
+fi
+if test $ac_cv_type_stack_t = no; then
+ cat >> confdefs.h <<\EOF
+#define stack_t struct sigaltstack
+EOF
+fi
+
+echo $ac_n "checking whether stack_t has an ss_base field""... $ac_c" 1>&6
+echo "configure:6240: checking whether stack_t has an ss_base field" >&5
+cat > conftest.$ac_ext <<EOF
+#line 6242 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#include <signal.h>
+#include "confdefs.h"
+
+int main() {
+stack_t sigstk; sigstk.ss_base = 0;
+; return 0; }
+EOF
+if { (eval echo configure:6257: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_SS_BASE 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+olibs="$LIBS"
+echo $ac_n "checking --with-tlib argument""... $ac_c" 1>&6
+echo "configure:6273: checking --with-tlib argument" >&5
+# Check whether --with-tlib or --without-tlib was given.
+if test "${with_tlib+set}" = set; then
+ withval="$with_tlib"
+ :
+fi
+
+if test -n "$with_tlib"; then
+ echo "$ac_t""$with_tlib" 1>&6
+ LIBS="$LIBS -l$with_tlib"
+else
+ echo "$ac_t""automatic terminal library selection" 1>&6
+ case "`uname -s 2>/dev/null`" in
+ OSF1) tlibs="ncurses curses termlib termcap";;
+ *) tlibs="ncurses termlib termcap curses";;
+ esac
+ for libname in $tlibs; do
+ echo $ac_n "checking for tgetent in -l${libname}""... $ac_c" 1>&6
+echo "configure:6291: checking for tgetent in -l${libname}" >&5
+ac_lib_var=`echo ${libname}'_'tgetent | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-l${libname} $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 6299 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgetent();
+
+int main() {
+tgetent()
+; return 0; }
+EOF
+if { (eval echo configure:6310: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo ${libname} | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-l${libname} $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "x$olibs" != "x$LIBS"; then
+ if test "$cross_compiling" = yes; then
+ res="FAIL"
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6342 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+main() {char *s; s=(char *)tgoto("%p1%d", 0, 1); exit(0); }
+EOF
+if { (eval echo configure:6350: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ res="OK"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ res="FAIL"
+fi
+rm -fr conftest*
+fi
+
+ if test "$res" = "OK"; then
+ break
+ fi
+ echo "$ac_t""$libname library is not usable" 1>&6
+ LIBS="$olibs"
+ fi
+ done
+fi
+if test "x$olibs" != "x$LIBS"; then
+ echo $ac_n "checking whether we talk terminfo""... $ac_c" 1>&6
+echo "configure:6372: checking whether we talk terminfo" >&5
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: failed to compile test program." 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6377 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+main()
+{char *s; s=(char *)tgoto("%p1%d", 0, 1); exit(!strcmp(s==0 ? "" : s, "1")); }
+EOF
+if { (eval echo configure:6386: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ echo "$ac_t""no -- we are in termcap land" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ echo "$ac_t""yes -- terminfo spoken here" 1>&6; cat >> confdefs.h <<\EOF
+#define TERMINFO 1
+EOF
+
+fi
+rm -fr conftest*
+fi
+
+else
+ echo "$ac_t""none found" 1>&6
+fi
+
+if test "x$olibs" != "x$LIBS"; then
+ echo $ac_n "checking what tgetent() returns for an unknown terminal""... $ac_c" 1>&6
+echo "configure:6407: checking what tgetent() returns for an unknown terminal" >&5
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: failed to compile test program." 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6412 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+main()
+{char s[10000]; int res = tgetent(s, "thisterminaldoesnotexist"); exit(res != 0); }
+EOF
+if { (eval echo configure:6421: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ echo "$ac_t""zero" 1>&6; cat >> confdefs.h <<\EOF
+#define TGETENT_ZERO_ERR 0
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ echo "$ac_t""non-zero" 1>&6
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo $ac_n "checking whether termcap.h contains ospeed""... $ac_c" 1>&6
+echo "configure:6439: checking whether termcap.h contains ospeed" >&5
+cat > conftest.$ac_ext <<EOF
+#line 6441 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+
+int main() {
+ospeed = 20000
+; return 0; }
+EOF
+if { (eval echo configure:6452: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_OSPEED 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking whether ospeed can be extern""... $ac_c" 1>&6
+echo "configure:6464: checking whether ospeed can be extern" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 6466 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+extern short ospeed;
+
+int main() {
+ospeed = 20000
+; return 0; }
+EOF
+if { (eval echo configure:6478: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define OSPEED_EXTERN 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+
+echo $ac_n "checking whether termcap.h contains UP, BC and PC""... $ac_c" 1>&6
+echo "configure:6496: checking whether termcap.h contains UP, BC and PC" >&5
+cat > conftest.$ac_ext <<EOF
+#line 6498 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+
+int main() {
+if (UP == 0 && BC == 0) PC = 1
+; return 0; }
+EOF
+if { (eval echo configure:6509: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_UP_BC_PC 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking whether UP, BC and PC can be extern""... $ac_c" 1>&6
+echo "configure:6521: checking whether UP, BC and PC can be extern" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 6523 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+extern char *UP, *BC, PC;
+
+int main() {
+if (UP == 0 && BC == 0) PC = 1
+; return 0; }
+EOF
+if { (eval echo configure:6535: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define UP_BC_PC_EXTERN 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+
+echo $ac_n "checking whether tputs() uses outfuntype""... $ac_c" 1>&6
+echo "configure:6553: checking whether tputs() uses outfuntype" >&5
+cat > conftest.$ac_ext <<EOF
+#line 6555 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+
+int main() {
+extern int xx(); tputs("test", 1, (outfuntype)xx)
+; return 0; }
+EOF
+if { (eval echo configure:6566: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_OUTFUNTYPE 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+echo $ac_n "checking whether sys/select.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:6581: checking whether sys/select.h and sys/time.h may both be included" >&5
+cat > conftest.$ac_ext <<EOF
+#line 6583 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/select.h>
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:6593: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define SYS_SELECT_WITH_SYS_TIME 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking for /dev/ptc""... $ac_c" 1>&6
+echo "configure:6610: checking for /dev/ptc" >&5
+if test -r /dev/ptc; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_DEV_PTC 1
+EOF
+
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for SVR4 ptys""... $ac_c" 1>&6
+echo "configure:6622: checking for SVR4 ptys" >&5
+if test -c /dev/ptmx ; then
+ cat > conftest.$ac_ext <<EOF
+#line 6625 "configure"
+#include "confdefs.h"
+
+int main() {
+ptsname(0);grantpt(0);unlockpt(0);
+; return 0; }
+EOF
+if { (eval echo configure:6632: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_SVR4_PTYS 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for ptyranges""... $ac_c" 1>&6
+echo "configure:6650: checking for ptyranges" >&5
+if test -d /dev/ptym ; then
+ pdir='/dev/ptym'
+else
+ pdir='/dev'
+fi
+cat > conftest.$ac_ext <<EOF
+#line 6657 "configure"
+#include "confdefs.h"
+#ifdef M_UNIX
+ yes;
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "yes" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ptys=`echo /dev/ptyp??`
+else
+ rm -rf conftest*
+ ptys=`echo $pdir/pty??`
+fi
+rm -f conftest*
+
+if test "$ptys" != "$pdir/pty??" ; then
+ p0=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\).$/\1/g' | sort -u | tr -d '\012'`
+ p1=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\)$/\1/g' | sort -u | tr -d '\012'`
+ cat >> confdefs.h <<EOF
+#define PTYRANGE0 "$p0"
+EOF
+
+ cat >> confdefs.h <<EOF
+#define PTYRANGE1 "$p1"
+EOF
+
+ echo "$ac_t""$p0 / $p1" 1>&6
+else
+ echo "$ac_t""don't know" 1>&6
+fi
+
+echo $ac_n "checking default tty permissions/group""... $ac_c" 1>&6
+echo "configure:6691: checking default tty permissions/group" >&5
+rm -f conftest_grp
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: failed to compile test program" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6697 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+main()
+{
+ struct stat sb;
+ char *x,*ttyname();
+ int om, m;
+ FILE *fp;
+
+ if (!(x = ttyname(0))) exit(1);
+ if (stat(x, &sb)) exit(1);
+ om = sb.st_mode;
+ if (om & 002) exit(0);
+ m = system("mesg y");
+ if (m == -1 || m == 127) exit(1);
+ if (stat(x, &sb)) exit(1);
+ m = sb.st_mode;
+ if (chmod(x, om)) exit(1);
+ if (m & 002) exit(0);
+ if (sb.st_gid == getgid()) exit(1);
+ if (!(fp=fopen("conftest_grp", "w")))
+ exit(1);
+ fprintf(fp, "%d\n", sb.st_gid);
+ fclose(fp);
+ exit(0);
+}
+
+EOF
+if { (eval echo configure:6729: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+
+ if test -f conftest_grp; then
+ ptygrp=`cat conftest_grp`
+ echo "$ac_t""pty mode: 0620, group: $ptygrp" 1>&6
+ cat >> confdefs.h <<\EOF
+#define PTYMODE 0620
+EOF
+
+ cat >> confdefs.h <<EOF
+#define PTYGROUP $ptygrp
+EOF
+
+ else
+ echo "$ac_t""ptys are world accessable" 1>&6
+ fi
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ echo "$ac_t""can't determine - assume ptys are world accessable" 1>&6
+fi
+rm -fr conftest*
+fi
+
+rm -f conftest_grp
+
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:6760: checking return type of signal handlers" >&5
+if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6765 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:6782: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_type_signal=void
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_type_signal=int
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+
+if test $ac_cv_type_signal = void; then
+ cat >> confdefs.h <<\EOF
+#define SIGRETURN return
+EOF
+
+else
+ cat >> confdefs.h <<\EOF
+#define SIGRETURN return 0
+EOF
+
+fi
+
+echo $ac_n "checking for struct sigcontext""... $ac_c" 1>&6
+echo "configure:6814: checking for struct sigcontext" >&5
+cat > conftest.$ac_ext <<EOF
+#line 6816 "configure"
+#include "confdefs.h"
+
+#include <signal.h>
+test_sig()
+{
+ struct sigcontext *scont;
+ scont = (struct sigcontext *)0;
+ return 1;
+}
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:6830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_SIGCONTEXT 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+echo $ac_n "checking getcwd implementation""... $ac_c" 1>&6
+echo "configure:6846: checking getcwd implementation" >&5
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: failed to compile test program" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6851 "configure"
+#include "confdefs.h"
+
+char *dagger[] = { "IFS=pwd", 0 };
+main()
+{
+ char buffer[500];
+ extern char **environ;
+ environ = dagger;
+ return getcwd(buffer, 500) ? 0 : 1;
+}
+EOF
+if { (eval echo configure:6863: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ echo "$ac_t""it is usable" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ echo "$ac_t""it stinks" 1>&6
+ cat >> confdefs.h <<\EOF
+#define BAD_GETCWD 1
+EOF
+
+fi
+rm -fr conftest*
+fi
+
+
+for ac_func in bcmp fchdir fchown fseeko fsync ftello getcwd getpseudotty \
+ getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \
+ memset nanosleep opendir putenv qsort readlink select setenv \
+ setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
+ sigvec snprintf strcasecmp strerror strftime stricmp strncasecmp \
+ strnicmp strpbrk strtol tgetent towlower towupper usleep utime utimes
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:6888: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6893 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:6916: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking for st_blksize""... $ac_c" 1>&6
+echo "configure:6942: checking for st_blksize" >&5
+cat > conftest.$ac_ext <<EOF
+#line 6944 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+int main() {
+ struct stat st;
+ int n;
+
+ stat("/", &st);
+ n = (int)st.st_blksize;
+; return 0; }
+EOF
+if { (eval echo configure:6956: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_ST_BLKSIZE 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+echo $ac_n "checking whether stat() ignores a trailing slash""... $ac_c" 1>&6
+echo "configure:6971: checking whether stat() ignores a trailing slash" >&5
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: failed to compile test program" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6976 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+main() {struct stat st; exit(stat("configure/", &st) != 0); }
+EOF
+if { (eval echo configure:6982: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define STAT_IGNORES_SLASH 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -fr conftest*
+fi
+
+
+echo $ac_n "checking for iconv_open()""... $ac_c" 1>&6
+echo "configure:6999: checking for iconv_open()" >&5
+save_LIBS="$LIBS"
+LIBS="$LIBS -liconv"
+cat > conftest.$ac_ext <<EOF
+#line 7003 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_ICONV_H
+# include <iconv.h>
+#endif
+
+int main() {
+iconv_open("fr", "to");
+; return 0; }
+EOF
+if { (eval echo configure:7014: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes; with -liconv" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_ICONV 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ LIBS="$save_LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 7026 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_ICONV_H
+# include <iconv.h>
+#endif
+
+int main() {
+iconv_open("fr", "to");
+; return 0; }
+EOF
+if { (eval echo configure:7037: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_ICONV 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking for nl_langinfo(CODESET)""... $ac_c" 1>&6
+echo "configure:7055: checking for nl_langinfo(CODESET)" >&5
+cat > conftest.$ac_ext <<EOF
+#line 7057 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_LANGINFO_H
+# include <langinfo.h>
+#endif
+
+int main() {
+char *cs = nl_langinfo(CODESET);
+; return 0; }
+EOF
+if { (eval echo configure:7068: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_NL_LANGINFO_CODESET 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+echo $ac_n "checking --disable-acl argument""... $ac_c" 1>&6
+echo "configure:7083: checking --disable-acl argument" >&5
+# Check whether --enable-acl or --disable-acl was given.
+if test "${enable_acl+set}" = set; then
+ enableval="$enable_acl"
+ :
+else
+ enable_acl="yes"
+fi
+
+if test "$enable_acl" = "yes"; then
+echo "$ac_t""no" 1>&6
+echo $ac_n "checking for acl_get_file in -lposix1e""... $ac_c" 1>&6
+echo "configure:7095: checking for acl_get_file in -lposix1e" >&5
+ac_lib_var=`echo posix1e'_'acl_get_file | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lposix1e $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 7103 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char acl_get_file();
+
+int main() {
+acl_get_file()
+; return 0; }
+EOF
+if { (eval echo configure:7114: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lposix1e"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for acl_get_file in -lacl""... $ac_c" 1>&6
+echo "configure:7133: checking for acl_get_file in -lacl" >&5
+ac_lib_var=`echo acl'_'acl_get_file | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lacl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 7141 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char acl_get_file();
+
+int main() {
+acl_get_file()
+; return 0; }
+EOF
+if { (eval echo configure:7152: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lacl"
+ echo $ac_n "checking for fgetxattr in -lattr""... $ac_c" 1>&6
+echo "configure:7169: checking for fgetxattr in -lattr" >&5
+ac_lib_var=`echo attr'_'fgetxattr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lattr $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 7177 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char fgetxattr();
+
+int main() {
+fgetxattr()
+; return 0; }
+EOF
+if { (eval echo configure:7188: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lattr"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+
+echo $ac_n "checking for POSIX ACL support""... $ac_c" 1>&6
+echo "configure:7216: checking for POSIX ACL support" >&5
+cat > conftest.$ac_ext <<EOF
+#line 7218 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_ACL_H
+# include <sys/acl.h>
+#endif
+acl_t acl;
+int main() {
+acl = acl_get_file("foo", ACL_TYPE_ACCESS);
+ acl_set_file("foo", ACL_TYPE_ACCESS, acl);
+ acl_free(acl);
+; return 0; }
+EOF
+if { (eval echo configure:7232: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_POSIX_ACL 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+echo $ac_n "checking for Solaris ACL support""... $ac_c" 1>&6
+echo "configure:7247: checking for Solaris ACL support" >&5
+cat > conftest.$ac_ext <<EOF
+#line 7249 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_SYS_ACL_H
+# include <sys/acl.h>
+#endif
+int main() {
+acl("foo", GETACLCNT, 0, NULL);
+
+; return 0; }
+EOF
+if { (eval echo configure:7260: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_SOLARIS_ACL 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+echo $ac_n "checking for AIX ACL support""... $ac_c" 1>&6
+echo "configure:7275: checking for AIX ACL support" >&5
+cat > conftest.$ac_ext <<EOF
+#line 7277 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_SYS_ACL_H
+# include <sys/acl.h>
+#endif
+#ifdef HAVE_SYS_ACCESS_H
+# include <sys/access.h>
+#endif
+#define _ALL_SOURCE
+
+#include <sys/stat.h>
+
+int aclsize;
+struct acl *aclent;
+int main() {
+aclsize = sizeof(struct acl);
+ aclent = (void *)malloc(aclsize);
+ statacl("foo", STX_NORMAL, aclent, aclsize);
+
+; return 0; }
+EOF
+if { (eval echo configure:7299: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_AIX_ACL 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+else
+ echo "$ac_t""yes" 1>&6
+fi
+
+echo $ac_n "checking --disable-gpm argument""... $ac_c" 1>&6
+echo "configure:7317: checking --disable-gpm argument" >&5
+# Check whether --enable-gpm or --disable-gpm was given.
+if test "${enable_gpm+set}" = set; then
+ enableval="$enable_gpm"
+ :
+else
+ enable_gpm="yes"
+fi
+
+
+if test "$enable_gpm" = "yes"; then
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for gpm""... $ac_c" 1>&6
+echo "configure:7330: checking for gpm" >&5
+if eval "test \"`echo '$''{'vi_cv_have_gpm'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ olibs="$LIBS" ; LIBS="-lgpm"
+ cat > conftest.$ac_ext <<EOF
+#line 7336 "configure"
+#include "confdefs.h"
+#include <gpm.h>
+ #include <linux/keyboard.h>
+int main() {
+Gpm_GetLibVersion(NULL);
+; return 0; }
+EOF
+if { (eval echo configure:7344: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ vi_cv_have_gpm=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ vi_cv_have_gpm=no
+fi
+rm -f conftest*
+ LIBS="$olibs"
+
+fi
+
+echo "$ac_t""$vi_cv_have_gpm" 1>&6
+ if test $vi_cv_have_gpm = yes; then
+ LIBS="$LIBS -lgpm"
+ cat >> confdefs.h <<\EOF
+#define HAVE_GPM 1
+EOF
+
+ fi
+else
+ echo "$ac_t""yes" 1>&6
+fi
+
+echo $ac_n "checking for vsnprintf()""... $ac_c" 1>&6
+echo "configure:7371: checking for vsnprintf()" >&5
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: failed to compile test program" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7376 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+ /* Check use of vsnprintf() */
+ void warn(char *fmt, ...);
+ void warn(char *fmt, ...)
+ {
+ va_list ap; char buf[20];
+ va_start(ap, fmt);
+ vsnprintf(buf, 20, fmt, ap);
+ va_end(ap);
+ }
+ main()
+ {
+ warn("testing %s\n", "a very long string that won't fit");
+ exit(0);
+ }
+
+EOF
+if { (eval echo configure:7397: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ cat >> confdefs.h <<\EOF
+#define HAVE_VSNPRINTF 1
+EOF
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -fr conftest*
+fi
+
+
+
+echo $ac_n "checking for rename""... $ac_c" 1>&6
+echo "configure:7415: checking for rename" >&5
+cat > conftest.$ac_ext <<EOF
+#line 7417 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main() {
+rename("this", "that")
+; return 0; }
+EOF
+if { (eval echo configure:7424: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_RENAME 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+echo $ac_n "checking for sysctl""... $ac_c" 1>&6
+echo "configure:7439: checking for sysctl" >&5
+cat > conftest.$ac_ext <<EOF
+#line 7441 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/sysctl.h>
+int main() {
+ int mib[2], r;
+ size_t len;
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_USERMEM;
+ len = sizeof(r);
+ (void)sysctl(mib, 2, &r, &len, (void *)0, (size_t)0);
+
+; return 0; }
+EOF
+if { (eval echo configure:7456: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_SYSCTL 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""not usable" 1>&6
+fi
+rm -f conftest*
+
+echo $ac_n "checking for sysinfo""... $ac_c" 1>&6
+echo "configure:7471: checking for sysinfo" >&5
+cat > conftest.$ac_ext <<EOF
+#line 7473 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/sysinfo.h>
+int main() {
+ struct sysinfo sinfo;
+ int t;
+
+ (void)sysinfo(&sinfo);
+ t = sinfo.totalram;
+
+; return 0; }
+EOF
+if { (eval echo configure:7486: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_SYSINFO 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""not usable" 1>&6
+fi
+rm -f conftest*
+
+echo $ac_n "checking for sysconf""... $ac_c" 1>&6
+echo "configure:7501: checking for sysconf" >&5
+cat > conftest.$ac_ext <<EOF
+#line 7503 "configure"
+#include "confdefs.h"
+#include <unistd.h>
+int main() {
+ (void)sysconf(_SC_PAGESIZE);
+ (void)sysconf(_SC_PHYS_PAGES);
+
+; return 0; }
+EOF
+if { (eval echo configure:7512: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_SYSCONF 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""not usable" 1>&6
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking size of int""... $ac_c" 1>&6
+echo "configure:7528: checking size of int" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: failed to compile test program" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7536 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+ main()
+ {
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", (int)sizeof(int));
+ exit(0);
+ }
+EOF
+if { (eval echo configure:7547: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_int=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_int=0
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_sizeof_int" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+EOF
+
+
+echo $ac_n "checking whether memmove/bcopy/memcpy handle overlaps""... $ac_c" 1>&6
+echo "configure:7568: checking whether memmove/bcopy/memcpy handle overlaps" >&5
+bcopy_test_prog='
+main() {
+ char buf[10];
+ strcpy(buf, "abcdefghi");
+ mch_memmove(buf, buf + 2, 3);
+ if (strncmp(buf, "ababcf", 6))
+ exit(1);
+ strcpy(buf, "abcdefghi");
+ mch_memmove(buf + 2, buf, 3);
+ if (strncmp(buf, "cdedef", 6))
+ exit(1);
+ exit(0); /* libc version works properly. */
+}'
+
+
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: failed to compile test program" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7588 "configure"
+#include "confdefs.h"
+#define mch_memmove(s,d,l) memmove(d,s,l) $bcopy_test_prog
+EOF
+if { (eval echo configure:7592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ cat >> confdefs.h <<\EOF
+#define USEMEMMOVE 1
+EOF
+ echo "$ac_t""memmove does" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: failed to compile test program" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7606 "configure"
+#include "confdefs.h"
+#define mch_memmove(s,d,l) bcopy(d,s,l) $bcopy_test_prog
+EOF
+if { (eval echo configure:7610: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ cat >> confdefs.h <<\EOF
+#define USEBCOPY 1
+EOF
+ echo "$ac_t""bcopy does" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: failed to compile test program" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7624 "configure"
+#include "confdefs.h"
+#define mch_memmove(s,d,l) memcpy(d,s,l) $bcopy_test_prog
+EOF
+if { (eval echo configure:7628: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ cat >> confdefs.h <<\EOF
+#define USEMEMCPY 1
+EOF
+ echo "$ac_t""memcpy does" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -fr conftest*
+fi
+
+fi
+rm -fr conftest*
+fi
+
+fi
+rm -fr conftest*
+fi
+
+
+
+if test "$enable_multibyte" = "yes"; then
+ cflags_save=$CFLAGS
+ ldflags_save=$LDFLAGS
+ if test -n "$x_includes" ; then
+ CFLAGS="$CFLAGS -I$x_includes"
+ LDFLAGS="$X_LIBS $LDFLAGS -lX11"
+ echo $ac_n "checking whether X_LOCALE needed""... $ac_c" 1>&6
+echo "configure:7660: checking whether X_LOCALE needed" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 7662 "configure"
+#include "confdefs.h"
+#include <X11/Xlocale.h>
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:7669: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cat > conftest.$ac_ext <<EOF
+#line 7672 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _Xsetlocale();
+
+int main() {
+_Xsetlocale()
+; return 0; }
+EOF
+if { (eval echo configure:7683: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define X_LOCALE 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+ fi
+ CFLAGS=$cflags_save
+ LDFLAGS=$ldflags_save
+fi
+
+echo $ac_n "checking for _xpg4_setrunelocale in -lxpg4""... $ac_c" 1>&6
+echo "configure:7710: checking for _xpg4_setrunelocale in -lxpg4" >&5
+ac_lib_var=`echo xpg4'_'_xpg4_setrunelocale | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lxpg4 $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 7718 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _xpg4_setrunelocale();
+
+int main() {
+_xpg4_setrunelocale()
+; return 0; }
+EOF
+if { (eval echo configure:7729: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lxpg4"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking how to create tags""... $ac_c" 1>&6
+echo "configure:7751: checking how to create tags" >&5
+test -f tags && mv tags tags.save
+if (eval ctags --version /dev/null | grep Exuberant) < /dev/null 1>&5 2>&1; then
+ TAGPRG="ctags"
+else
+ (eval etags /dev/null) < /dev/null 1>&5 2>&1 && TAGPRG="etags"
+ (eval etags -c /dev/null) < /dev/null 1>&5 2>&1 && TAGPRG="etags -c"
+ (eval ctags /dev/null) < /dev/null 1>&5 2>&1 && TAGPRG="ctags"
+ (eval ctags -t /dev/null) < /dev/null 1>&5 2>&1 && TAGPRG="ctags -t"
+ (eval ctags -ts /dev/null) < /dev/null 1>&5 2>&1 && TAGPRG="ctags -ts"
+ (eval ctags -tvs /dev/null) < /dev/null 1>&5 2>&1 && TAGPRG="ctags -tvs"
+ (eval ctags -i+m /dev/null) < /dev/null 1>&5 2>&1 && TAGPRG="ctags -i+m"
+fi
+test -f tags.save && mv tags.save tags
+echo "$ac_t""$TAGPRG" 1>&6
+
+echo $ac_n "checking how to run man with a section nr""... $ac_c" 1>&6
+echo "configure:7768: checking how to run man with a section nr" >&5
+MANDEF="man"
+(eval man -s 2 read) < /dev/null > /dev/null 2>&5 && MANDEF="man -s"
+echo "$ac_t""$MANDEF" 1>&6
+if test "$MANDEF" = "man -s"; then
+ cat >> confdefs.h <<\EOF
+#define USEMAN_S 1
+EOF
+
+fi
+
+echo $ac_n "checking --disable-nls argument""... $ac_c" 1>&6
+echo "configure:7780: checking --disable-nls argument" >&5
+# Check whether --enable-nls or --disable-nls was given.
+if test "${enable_nls+set}" = set; then
+ enableval="$enable_nls"
+ :
+else
+ enable_nls="yes"
+fi
+
+
+if test "$enable_nls" = "yes"; then
+ echo "$ac_t""no" 1>&6
+ # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:7795: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_MSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$MSGFMT"; then
+ ac_cv_prog_MSGFMT="$MSGFMT" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_MSGFMT="msgfmt"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+MSGFMT="$ac_cv_prog_MSGFMT"
+if test -n "$MSGFMT"; then
+ echo "$ac_t""$MSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ echo $ac_n "checking for NLS""... $ac_c" 1>&6
+echo "configure:7822: checking for NLS" >&5
+ if test -f po/Makefile; then
+ have_gettext="no"
+ if test -n "$MSGFMT"; then
+ cat > conftest.$ac_ext <<EOF
+#line 7827 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+int main() {
+gettext("Test");
+; return 0; }
+EOF
+if { (eval echo configure:7834: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""gettext() works" 1>&6; have_gettext="yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ olibs=$LIBS
+ LIBS="$LIBS -lintl"
+ cat > conftest.$ac_ext <<EOF
+#line 7844 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+int main() {
+gettext("Test");
+; return 0; }
+EOF
+if { (eval echo configure:7851: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""gettext() works with -lintl" 1>&6; have_gettext="yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""gettext() doesn't work" 1>&6;
+ LIBS=$olibs
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ else
+ echo "$ac_t""msgfmt not found - disabled" 1>&6;
+ fi
+ if test $have_gettext = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_GETTEXT 1
+EOF
+
+ MAKEMO=yes
+
+ for ac_func in bind_textdomain_codeset
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:7877: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7882 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:7905: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ echo $ac_n "checking for _nl_msg_cat_cntr""... $ac_c" 1>&6
+echo "configure:7930: checking for _nl_msg_cat_cntr" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 7932 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+ extern int _nl_msg_cat_cntr;
+int main() {
+++_nl_msg_cat_cntr;
+; return 0; }
+EOF
+if { (eval echo configure:7940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define HAVE_NL_MSG_CAT_CNTR 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+ fi
+ else
+ echo "$ac_t""no "po/Makefile" - disabled" 1>&6;
+ fi
+else
+ echo "$ac_t""yes" 1>&6
+fi
+
+ac_safe=`echo "dlfcn.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for dlfcn.h""... $ac_c" 1>&6
+echo "configure:7963: checking for dlfcn.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7968 "configure"
+#include "confdefs.h"
+#include <dlfcn.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:7973: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ DLL=dlfcn.h
+else
+ echo "$ac_t""no" 1>&6
+ac_safe=`echo "dl.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for dl.h""... $ac_c" 1>&6
+echo "configure:7994: checking for dl.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7999 "configure"
+#include "confdefs.h"
+#include <dl.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:8004: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ DLL=dl.h
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+if test x${DLL} = xdlfcn.h; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_DLFCN_H 1
+EOF
+
+ echo $ac_n "checking for dlopen()""... $ac_c" 1>&6
+echo "configure:8033: checking for dlopen()" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 8035 "configure"
+#include "confdefs.h"
+
+int main() {
+
+ extern void* dlopen();
+ dlopen();
+
+; return 0; }
+EOF
+if { (eval echo configure:8045: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;
+ cat >> confdefs.h <<\EOF
+#define HAVE_DLOPEN 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6;
+ echo $ac_n "checking for dlopen() in -ldl""... $ac_c" 1>&6
+echo "configure:8058: checking for dlopen() in -ldl" >&5
+ olibs=$LIBS
+ LIBS="$LIBS -ldl"
+ cat > conftest.$ac_ext <<EOF
+#line 8062 "configure"
+#include "confdefs.h"
+
+int main() {
+
+ extern void* dlopen();
+ dlopen();
+
+; return 0; }
+EOF
+if { (eval echo configure:8072: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;
+ cat >> confdefs.h <<\EOF
+#define HAVE_DLOPEN 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6;
+ LIBS=$olibs
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ echo $ac_n "checking for dlsym()""... $ac_c" 1>&6
+echo "configure:8090: checking for dlsym()" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 8092 "configure"
+#include "confdefs.h"
+
+int main() {
+
+ extern void* dlsym();
+ dlsym();
+
+; return 0; }
+EOF
+if { (eval echo configure:8102: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;
+ cat >> confdefs.h <<\EOF
+#define HAVE_DLSYM 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6;
+ echo $ac_n "checking for dlsym() in -ldl""... $ac_c" 1>&6
+echo "configure:8115: checking for dlsym() in -ldl" >&5
+ olibs=$LIBS
+ LIBS="$LIBS -ldl"
+ cat > conftest.$ac_ext <<EOF
+#line 8119 "configure"
+#include "confdefs.h"
+
+int main() {
+
+ extern void* dlsym();
+ dlsym();
+
+; return 0; }
+EOF
+if { (eval echo configure:8129: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;
+ cat >> confdefs.h <<\EOF
+#define HAVE_DLSYM 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6;
+ LIBS=$olibs
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+elif test x${DLL} = xdl.h; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_DL_H 1
+EOF
+
+ echo $ac_n "checking for shl_load()""... $ac_c" 1>&6
+echo "configure:8152: checking for shl_load()" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 8154 "configure"
+#include "confdefs.h"
+
+int main() {
+
+ extern void* shl_load();
+ shl_load();
+
+; return 0; }
+EOF
+if { (eval echo configure:8164: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;
+ cat >> confdefs.h <<\EOF
+#define HAVE_SHL_LOAD 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6;
+ echo $ac_n "checking for shl_load() in -ldld""... $ac_c" 1>&6
+echo "configure:8177: checking for shl_load() in -ldld" >&5
+ olibs=$LIBS
+ LIBS="$LIBS -ldld"
+ cat > conftest.$ac_ext <<EOF
+#line 8181 "configure"
+#include "confdefs.h"
+
+int main() {
+
+ extern void* shl_load();
+ shl_load();
+
+; return 0; }
+EOF
+if { (eval echo configure:8191: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;
+ cat >> confdefs.h <<\EOF
+#define HAVE_SHL_LOAD 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6;
+ LIBS=$olibs
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+for ac_hdr in setjmp.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:8213: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 8218 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:8223: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+if test "x$MACOSX" = "xyes" -a -n "$PERL"; then
+ if echo $LIBS | grep -e '-ldl' >/dev/null; then
+ LIBS=`echo $LIBS | sed s/-ldl//`
+ PERL_LIBS="$PERL_LIBS -ldl"
+ fi
+fi
+
+if test "x$MACOSX" = "xyes" && test "x$CARBON" = "xyes" \
+ && test "x$GUITYPE" != "xCARBONGUI"; then
+ echo $ac_n "checking whether we need -framework Carbon""... $ac_c" 1>&6
+echo "configure:8260: checking whether we need -framework Carbon" >&5
+ if test "x$enable_multibyte" = "xyes" || test "x$features" == "xbig" \
+ || test "x$features" = "xhuge"; then
+ LIBS="$LIBS -framework Carbon"
+ echo "$ac_t""yes" 1>&6
+ else
+ echo "$ac_t""no" 1>&6
+ fi
+fi
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in auto/config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "auto/config.mk:config.mk.in auto/config.h:config.h.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@AWK@%$AWK%g
+s%@STRIP@%$STRIP%g
+s%@EXEEXT@%$EXEEXT%g
+s%@CPP_MM@%$CPP_MM%g
+s%@OS_EXTRA_SRC@%$OS_EXTRA_SRC%g
+s%@OS_EXTRA_OBJ@%$OS_EXTRA_OBJ%g
+s%@VIMNAME@%$VIMNAME%g
+s%@EXNAME@%$EXNAME%g
+s%@VIEWNAME@%$VIEWNAME%g
+s%@line_break@%$line_break%g
+s%@dovimdiff@%$dovimdiff%g
+s%@dogvimdiff@%$dogvimdiff%g
+s%@compiledby@%$compiledby%g
+s%@vi_cv_path_perl@%$vi_cv_path_perl%g
+s%@vi_cv_perllib@%$vi_cv_perllib%g
+s%@shrpenv@%$shrpenv%g
+s%@PERL_SRC@%$PERL_SRC%g
+s%@PERL_OBJ@%$PERL_OBJ%g
+s%@PERL_PRO@%$PERL_PRO%g
+s%@PERL_CFLAGS@%$PERL_CFLAGS%g
+s%@PERL_LIBS@%$PERL_LIBS%g
+s%@vi_cv_path_python@%$vi_cv_path_python%g
+s%@PYTHON_CONFDIR@%$PYTHON_CONFDIR%g
+s%@PYTHON_LIBS@%$PYTHON_LIBS%g
+s%@PYTHON_GETPATH_CFLAGS@%$PYTHON_GETPATH_CFLAGS%g
+s%@PYTHON_CFLAGS@%$PYTHON_CFLAGS%g
+s%@PYTHON_SRC@%$PYTHON_SRC%g
+s%@PYTHON_OBJ@%$PYTHON_OBJ%g
+s%@vi_cv_path_tcl@%$vi_cv_path_tcl%g
+s%@TCL_SRC@%$TCL_SRC%g
+s%@TCL_OBJ@%$TCL_OBJ%g
+s%@TCL_PRO@%$TCL_PRO%g
+s%@TCL_CFLAGS@%$TCL_CFLAGS%g
+s%@TCL_LIBS@%$TCL_LIBS%g
+s%@vi_cv_path_ruby@%$vi_cv_path_ruby%g
+s%@RUBY_SRC@%$RUBY_SRC%g
+s%@RUBY_OBJ@%$RUBY_OBJ%g
+s%@RUBY_PRO@%$RUBY_PRO%g
+s%@RUBY_CFLAGS@%$RUBY_CFLAGS%g
+s%@RUBY_LIBS@%$RUBY_LIBS%g
+s%@WORKSHOP_SRC@%$WORKSHOP_SRC%g
+s%@WORKSHOP_OBJ@%$WORKSHOP_OBJ%g
+s%@NETBEANS_SRC@%$NETBEANS_SRC%g
+s%@NETBEANS_OBJ@%$NETBEANS_OBJ%g
+s%@SNIFF_SRC@%$SNIFF_SRC%g
+s%@SNIFF_OBJ@%$SNIFF_OBJ%g
+s%@xmkmfpath@%$xmkmfpath%g
+s%@X_CFLAGS@%$X_CFLAGS%g
+s%@X_PRE_LIBS@%$X_PRE_LIBS%g
+s%@X_LIBS@%$X_LIBS%g
+s%@X_EXTRA_LIBS@%$X_EXTRA_LIBS%g
+s%@X_LIB@%$X_LIB%g
+s%@GTK_CONFIG@%$GTK_CONFIG%g
+s%@GTK12_CONFIG@%$GTK12_CONFIG%g
+s%@PKG_CONFIG@%$PKG_CONFIG%g
+s%@GTK_CFLAGS@%$GTK_CFLAGS%g
+s%@GTK_LIBS@%$GTK_LIBS%g
+s%@GTK_LIBNAME@%$GTK_LIBNAME%g
+s%@GNOME_LIBS@%$GNOME_LIBS%g
+s%@GNOME_LIBDIR@%$GNOME_LIBDIR%g
+s%@GNOME_INCLUDEDIR@%$GNOME_INCLUDEDIR%g
+s%@GNOME_CONFIG@%$GNOME_CONFIG%g
+s%@MOTIF_LIBNAME@%$MOTIF_LIBNAME%g
+s%@NARROW_PROTO@%$NARROW_PROTO%g
+s%@GUI_INC_LOC@%$GUI_INC_LOC%g
+s%@GUI_LIB_LOC@%$GUI_LIB_LOC%g
+s%@GUITYPE@%$GUITYPE%g
+s%@GUI_X_LIBS@%$GUI_X_LIBS%g
+s%@HANGULIN_SRC@%$HANGULIN_SRC%g
+s%@HANGULIN_OBJ@%$HANGULIN_OBJ%g
+s%@TAGPRG@%$TAGPRG%g
+s%@MSGFMT@%$MSGFMT%g
+s%@MAKEMO@%$MAKEMO%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"auto/config.mk:config.mk.in"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="auto/config.h:config.h.in"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+
diff --git a/src/bigvim.bat b/src/bigvim.bat
new file mode 100644
index 000000000..12b109d10
--- /dev/null
+++ b/src/bigvim.bat
@@ -0,0 +1,3 @@
+:: command to build big Vim with OLE, Perl, Python, Ruby and Tcl
+nmake -f Make_mvc.mak GUI=yes OLE=yes PERL=E:\perl58 DYNAMIC_PERL=yes PERL_VER=58 PYTHON=e:\python23 DYNAMIC_PYTHON=yes PYTHON_VER=23 RUBY=e:\ruby18 DYNAMIC_RUBY=yes RUBY_VER=18 RUBY_VER_LONG=1.8 TCL=e:\tcl DYNAMIC_TCL=yes %1 IME=yes CSCOPE=yes XPM=e:\xpm
+
diff --git a/src/buffer.c b/src/buffer.c
new file mode 100644
index 000000000..83b570f61
--- /dev/null
+++ b/src/buffer.c
@@ -0,0 +1,5071 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * buffer.c: functions for dealing with the buffer structure
+ */
+
+/*
+ * The buffer list is a double linked list of all buffers.
+ * Each buffer can be in one of these states:
+ * never loaded: BF_NEVERLOADED is set, only the file name is valid
+ * not loaded: b_ml.ml_mfp == NULL, no memfile allocated
+ * hidden: b_nwindows == 0, loaded but not displayed in a window
+ * normal: loaded and displayed in a window
+ *
+ * Instead of storing file names all over the place, each file name is
+ * stored in the buffer list. It can be referenced by a number.
+ *
+ * The current implementation remembers all file names ever used.
+ */
+
+
+#include "vim.h"
+
+#if defined(FEAT_CMDL_COMPL) || defined(FEAT_LISTCMDS) || defined(FEAT_EVAL) || defined(FEAT_PERL)
+static char_u *buflist_match __ARGS((regprog_T *prog, buf_T *buf));
+# define HAVE_BUFLIST_MATCH
+static char_u *fname_match __ARGS((regprog_T *prog, char_u *name));
+#endif
+static void buflist_setfpos __ARGS((buf_T *buf, win_T *win, linenr_T lnum, colnr_T col, int copy_options));
+static wininfo_T *find_wininfo __ARGS((buf_T *buf));
+#ifdef UNIX
+static buf_T *buflist_findname_stat __ARGS((char_u *ffname, struct stat *st));
+static int otherfile_buf __ARGS((buf_T *buf, char_u *ffname, struct stat *stp));
+static int buf_same_ino __ARGS((buf_T *buf, struct stat *stp));
+#else
+static int otherfile_buf __ARGS((buf_T *buf, char_u *ffname));
+#endif
+#ifdef FEAT_TITLE
+static int ti_change __ARGS((char_u *str, char_u **last));
+#endif
+static void free_buffer __ARGS((buf_T *));
+static void free_buffer_stuff __ARGS((buf_T *buf, int free_options));
+static void clear_wininfo __ARGS((buf_T *buf));
+
+#ifdef UNIX
+# define dev_T dev_t
+#else
+# define dev_T unsigned
+#endif
+
+#if defined(FEAT_SIGNS)
+static void insert_sign __ARGS((buf_T *buf, signlist_T *prev, signlist_T *next, int id, linenr_T lnum, int typenr));
+static void buf_delete_signs __ARGS((buf_T *buf));
+#endif
+
+/*
+ * Open current buffer, that is: open the memfile and read the file into memory
+ * return FAIL for failure, OK otherwise
+ */
+ int
+open_buffer(read_stdin, eap)
+ int read_stdin; /* read file from stdin */
+ exarg_T *eap; /* for forced 'ff' and 'fenc' or NULL */
+{
+ int retval = OK;
+#ifdef FEAT_AUTOCMD
+ buf_T *old_curbuf;
+#endif
+
+ /*
+ * The 'readonly' flag is only set when BF_NEVERLOADED is being reset.
+ * When re-entering the same buffer, it should not change, because the
+ * user may have reset the flag by hand.
+ */
+ if (readonlymode && curbuf->b_ffname != NULL
+ && (curbuf->b_flags & BF_NEVERLOADED))
+ curbuf->b_p_ro = TRUE;
+
+ if (ml_open() == FAIL)
+ {
+ /*
+ * There MUST be a memfile, otherwise we can't do anything
+ * If we can't create one for the current buffer, take another buffer
+ */
+ close_buffer(NULL, curbuf, 0);
+ for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next)
+ if (curbuf->b_ml.ml_mfp != NULL)
+ break;
+ /*
+ * if there is no memfile at all, exit
+ * This is OK, since there are no changes to loose.
+ */
+ if (curbuf == NULL)
+ {
+ EMSG(_("E82: Cannot allocate any buffer, exiting..."));
+ getout(2);
+ }
+ EMSG(_("E83: Cannot allocate buffer, using other one..."));
+ enter_buffer(curbuf);
+ return FAIL;
+ }
+
+#ifdef FEAT_AUTOCMD
+ /* The autocommands in readfile() may change the buffer, but only AFTER
+ * reading the file. */
+ old_curbuf = curbuf;
+ modified_was_set = FALSE;
+#endif
+
+ /* mark cursor position as being invalid */
+ changed_line_abv_curs();
+
+ if (curbuf->b_ffname != NULL
+#ifdef FEAT_NETBEANS_INTG
+ && netbeansReadFile
+#endif
+ )
+ {
+#ifdef FEAT_NETBEANS_INTG
+ int oldFire = netbeansFireChanges;
+
+ netbeansFireChanges = 0;
+#endif
+ retval = readfile(curbuf->b_ffname, curbuf->b_fname,
+ (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap, READ_NEW);
+#ifdef FEAT_NETBEANS_INTG
+ netbeansFireChanges = oldFire;
+#endif
+ /* Help buffer is filtered. */
+ if (curbuf->b_help)
+ fix_help_buffer();
+ }
+ else if (read_stdin)
+ {
+ int save_bin = curbuf->b_p_bin;
+ linenr_T line_count;
+
+ /*
+ * First read the text in binary mode into the buffer.
+ * Then read from that same buffer and append at the end. This makes
+ * it possible to retry when 'fileformat' or 'fileencoding' was
+ * guessed wrong.
+ */
+ curbuf->b_p_bin = TRUE;
+ retval = readfile(NULL, NULL, (linenr_T)0,
+ (linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW + READ_STDIN);
+ curbuf->b_p_bin = save_bin;
+ if (retval == OK)
+ {
+ line_count = curbuf->b_ml.ml_line_count;
+ retval = readfile(NULL, NULL, (linenr_T)line_count,
+ (linenr_T)0, (linenr_T)MAXLNUM, eap, READ_BUFFER);
+ if (retval == OK)
+ {
+ /* Delete the binary lines. */
+ while (--line_count >= 0)
+ ml_delete((linenr_T)1, FALSE);
+ }
+ else
+ {
+ /* Delete the converted lines. */
+ while (curbuf->b_ml.ml_line_count > line_count)
+ ml_delete(line_count, FALSE);
+ }
+ /* Put the cursor on the first line. */
+ curwin->w_cursor.lnum = 1;
+ curwin->w_cursor.col = 0;
+#ifdef FEAT_AUTOCMD
+# ifdef FEAT_EVAL
+ apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, FALSE,
+ curbuf, &retval);
+# else
+ apply_autocmds(EVENT_STDINREADPOST, NULL, NULL, FALSE, curbuf);
+# endif
+#endif
+ }
+ }
+
+ /* if first time loading this buffer, init b_chartab[] */
+ if (curbuf->b_flags & BF_NEVERLOADED)
+ (void)buf_init_chartab(curbuf, FALSE);
+
+ /*
+ * Set/reset the Changed flag first, autocmds may change the buffer.
+ * Apply the automatic commands, before processing the modelines.
+ * So the modelines have priority over auto commands.
+ */
+ /* When reading stdin, the buffer contents always needs writing, so set
+ * the changed flag. Unless in readonly mode: "ls | gview -".
+ * When interrupted and 'cpoptions' contains 'i' set changed flag. */
+ if ((read_stdin && !readonlymode && !bufempty())
+#ifdef FEAT_AUTOCMD
+ || modified_was_set /* ":set modified" used in autocmd */
+# ifdef FEAT_EVAL
+ || (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)
+# endif
+#endif
+ || (got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL))
+ changed();
+ else if (retval != FAIL)
+ unchanged(curbuf, FALSE);
+ save_file_ff(curbuf); /* keep this fileformat */
+
+ /* require "!" to overwrite the file, because it wasn't read completely */
+#ifdef FEAT_EVAL
+ if (aborting())
+#else
+ if (got_int)
+#endif
+ curbuf->b_flags |= BF_READERR;
+
+#ifdef FEAT_AUTOCMD
+ /* need to set w_topline, unless some autocommand already did that. */
+ if (!(curwin->w_valid & VALID_TOPLINE))
+ {
+ curwin->w_topline = 1;
+# ifdef FEAT_DIFF
+ curwin->w_topfill = 0;
+# endif
+ }
+# ifdef FEAT_EVAL
+ apply_autocmds_retval(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf, &retval);
+# else
+ apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
+# endif
+#endif
+
+ if (retval != FAIL)
+ {
+#ifdef FEAT_AUTOCMD
+ /*
+ * The autocommands may have changed the current buffer. Apply the
+ * modelines to the correct buffer, if it still exists and is loaded.
+ */
+ if (buf_valid(old_curbuf) && old_curbuf->b_ml.ml_mfp != NULL)
+ {
+ aco_save_T aco;
+
+ /* Go to the buffer that was opened. */
+ aucmd_prepbuf(&aco, old_curbuf);
+#endif
+ do_modelines();
+ curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED);
+
+#ifdef FEAT_AUTOCMD
+# ifdef FEAT_EVAL
+ apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf,
+ &retval);
+# else
+ apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
+# endif
+
+ /* restore curwin/curbuf and a few other things */
+ aucmd_restbuf(&aco);
+ }
+#endif
+ }
+
+#ifdef FEAT_FOLDING
+ /* Need to update automatic folding. */
+ foldUpdateAll(curwin);
+#endif
+
+ return retval;
+}
+
+/*
+ * Return TRUE if "buf" points to a valid buffer (in the buffer list).
+ */
+ int
+buf_valid(buf)
+ buf_T *buf;
+{
+ buf_T *bp;
+
+ for (bp = firstbuf; bp != NULL; bp = bp->b_next)
+ if (bp == buf)
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Close the link to a buffer.
+ * "action" is used when there is no longer a window for the buffer.
+ * It can be:
+ * 0 buffer becomes hidden
+ * DOBUF_UNLOAD buffer is unloaded
+ * DOBUF_DELETE buffer is unloaded and removed from buffer list
+ * DOBUF_WIPE buffer is unloaded and really deleted
+ * When doing all but the first one on the current buffer, the caller should
+ * get a new buffer very soon!
+ *
+ * The 'bufhidden' option can force freeing and deleting.
+ */
+ void
+close_buffer(win, buf, action)
+ win_T *win; /* if not NULL, set b_last_cursor */
+ buf_T *buf;
+ int action;
+{
+#ifdef FEAT_AUTOCMD
+ int is_curbuf;
+ int nwindows = buf->b_nwindows;
+#endif
+ int unload_buf = (action != 0);
+ int del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE);
+ int wipe_buf = (action == DOBUF_WIPE);
+
+#ifdef FEAT_QUICKFIX
+ /*
+ * Force unloading or deleting when 'bufhidden' says so.
+ * The caller must take care of NOT deleting/freeing when 'bufhidden' is
+ * "hide" (otherwise we could never free or delete a buffer).
+ */
+ if (buf->b_p_bh[0] == 'd') /* 'bufhidden' == "delete" */
+ {
+ del_buf = TRUE;
+ unload_buf = TRUE;
+ }
+ else if (buf->b_p_bh[0] == 'w') /* 'bufhidden' == "wipe" */
+ {
+ del_buf = TRUE;
+ unload_buf = TRUE;
+ wipe_buf = TRUE;
+ }
+ else if (buf->b_p_bh[0] == 'u') /* 'bufhidden' == "unload" */
+ unload_buf = TRUE;
+#endif
+
+ if (win != NULL)
+ {
+ /* Set b_last_cursor when closing the last window for the buffer.
+ * Remember the last cursor position and window options of the buffer.
+ * This used to be only for the current window, but then options like
+ * 'foldmethod' may be lost with a ":only" command. */
+ if (buf->b_nwindows == 1)
+ set_last_cursor(win);
+ buflist_setfpos(buf, win,
+ win->w_cursor.lnum == 1 ? 0 : win->w_cursor.lnum,
+ win->w_cursor.col, TRUE);
+ }
+
+#ifdef FEAT_AUTOCMD
+ /* When the buffer is no longer in a window, trigger BufWinLeave */
+ if (buf->b_nwindows == 1)
+ {
+ apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
+ FALSE, buf);
+ if (!buf_valid(buf)) /* autocommands may delete the buffer */
+ return;
+
+ /* When the buffer becomes hidden, but is not unloaded, trigger
+ * BufHidden */
+ if (!unload_buf)
+ {
+ apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname,
+ FALSE, buf);
+ if (!buf_valid(buf)) /* autocmds may delete the buffer */
+ return;
+ }
+# ifdef FEAT_EVAL
+ if (aborting()) /* autocmds may abort script processing */
+ return;
+# endif
+ }
+ nwindows = buf->b_nwindows;
+#endif
+
+ /* decrease the link count from windows (unless not in any window) */
+ if (buf->b_nwindows > 0)
+ --buf->b_nwindows;
+
+ /* Return when a window is displaying the buffer or when it's not
+ * unloaded. */
+ if (buf->b_nwindows > 0 || !unload_buf)
+ {
+ if (buf == curbuf)
+ u_sync(); /* sync undo before going to another buffer */
+ return;
+ }
+
+ /* Always remove the buffer when there is no file name. */
+ if (buf->b_ffname == NULL)
+ del_buf = TRUE;
+
+ /*
+ * Free all things allocated for this buffer.
+ * Also calls the "BufDelete" autocommands when del_buf is TRUE.
+ */
+#ifdef FEAT_AUTOCMD
+ /* Remember if we are closing the current buffer. Restore the number of
+ * windows, so that autocommands in buf_freeall() don't get confused. */
+ is_curbuf = (buf == curbuf);
+ buf->b_nwindows = nwindows;
+#endif
+
+ buf_freeall(buf, del_buf, wipe_buf);
+
+#ifdef FEAT_AUTOCMD
+ /* Autocommands may have deleted the buffer. */
+ if (!buf_valid(buf))
+ return;
+# ifdef FEAT_EVAL
+ /* Autocommands may abort script processing. */
+ if (aborting())
+ return;
+# endif
+
+ /* Autocommands may have opened or closed windows for this buffer.
+ * Decrement the count for the close we do here. */
+ if (buf->b_nwindows > 0)
+ --buf->b_nwindows;
+
+ /*
+ * It's possible that autocommands change curbuf to the one being deleted.
+ * This might cause the previous curbuf to be deleted unexpectedly. But
+ * in some cases it's OK to delete the curbuf, because a new one is
+ * obtained anyway. Therefore only return if curbuf changed to the
+ * deleted buffer.
+ */
+ if (buf == curbuf && !is_curbuf)
+ return;
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ netbeans_file_closed(buf);
+#endif
+#if defined(FEAT_NETBEANS_INTG) || defined(FEAT_SUN_WORKSHOP)
+ /* Change directories when the acd option is set on. */
+ if (p_acd && curbuf->b_ffname != NULL
+ && vim_chdirfile(curbuf->b_ffname) == OK)
+ shorten_fnames(TRUE);
+#endif
+
+ /*
+ * Remove the buffer from the list.
+ */
+ if (wipe_buf)
+ {
+#ifdef FEAT_SUN_WORKSHOP
+ if (usingSunWorkShop)
+ workshop_file_closed_lineno((char *)buf->b_ffname,
+ (int)buf->b_last_cursor.lnum);
+#endif
+ vim_free(buf->b_ffname);
+ vim_free(buf->b_sfname);
+ if (buf->b_prev == NULL)
+ firstbuf = buf->b_next;
+ else
+ buf->b_prev->b_next = buf->b_next;
+ if (buf->b_next == NULL)
+ lastbuf = buf->b_prev;
+ else
+ buf->b_next->b_prev = buf->b_prev;
+ free_buffer(buf);
+ }
+ else
+ {
+ if (del_buf)
+ {
+ /* Free all internal variables and reset option values, to make
+ * ":bdel" compatible with Vim 5.7. */
+ free_buffer_stuff(buf, TRUE);
+
+ /* Make it look like a new buffer. */
+ buf->b_flags = BF_CHECK_RO | BF_NEVERLOADED;
+
+ /* Init the options when loaded again. */
+ buf->b_p_initialized = FALSE;
+ }
+ buf_clear_file(buf);
+ if (del_buf)
+ buf->b_p_bl = FALSE;
+ }
+}
+
+/*
+ * Make buffer not contain a file.
+ */
+ void
+buf_clear_file(buf)
+ buf_T *buf;
+{
+ buf->b_ml.ml_line_count = 1;
+ unchanged(buf, TRUE);
+#ifndef SHORT_FNAME
+ buf->b_shortname = FALSE;
+#endif
+ buf->b_p_eol = TRUE;
+ buf->b_start_eol = TRUE;
+#ifdef FEAT_MBYTE
+ buf->b_p_bomb = FALSE;
+#endif
+ buf->b_ml.ml_mfp = NULL;
+ buf->b_ml.ml_flags = ML_EMPTY; /* empty buffer */
+#ifdef FEAT_NETBEANS_INTG
+ netbeans_deleted_all_lines(buf);
+ netbeansOpenFile = 0; /* reset in netbeans_file_opened() */
+#endif
+}
+
+/*
+ * buf_freeall() - free all things allocated for a buffer that are related to
+ * the file.
+ */
+/*ARGSUSED*/
+ void
+buf_freeall(buf, del_buf, wipe_buf)
+ buf_T *buf;
+ int del_buf; /* buffer is going to be deleted */
+ int wipe_buf; /* buffer is going to be wiped out */
+{
+#ifdef FEAT_AUTOCMD
+ int is_curbuf = (buf == curbuf);
+
+ apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf);
+ if (!buf_valid(buf)) /* autocommands may delete the buffer */
+ return;
+ if (del_buf && buf->b_p_bl)
+ {
+ apply_autocmds(EVENT_BUFDELETE, buf->b_fname, buf->b_fname, FALSE, buf);
+ if (!buf_valid(buf)) /* autocommands may delete the buffer */
+ return;
+ }
+ if (wipe_buf)
+ {
+ apply_autocmds(EVENT_BUFWIPEOUT, buf->b_fname, buf->b_fname,
+ FALSE, buf);
+ if (!buf_valid(buf)) /* autocommands may delete the buffer */
+ return;
+ }
+# ifdef FEAT_EVAL
+ if (aborting()) /* autocmds may abort script processing */
+ return;
+# endif
+
+ /*
+ * It's possible that autocommands change curbuf to the one being deleted.
+ * This might cause curbuf to be deleted unexpectedly. But in some cases
+ * it's OK to delete the curbuf, because a new one is obtained anyway.
+ * Therefore only return if curbuf changed to the deleted buffer.
+ */
+ if (buf == curbuf && !is_curbuf)
+ return;
+#endif
+#ifdef FEAT_DIFF
+ diff_buf_delete(buf); /* Can't use 'diff' for unloaded buffer. */
+#endif
+#ifdef FEAT_TCL
+ tcl_buffer_free(buf);
+#endif
+ u_blockfree(buf); /* free the memory allocated for undo */
+ ml_close(buf, TRUE); /* close and delete the memline/memfile */
+ buf->b_ml.ml_line_count = 0; /* no lines in buffer */
+ u_clearall(buf); /* reset all undo information */
+#ifdef FEAT_SYN_HL
+ syntax_clear(buf); /* reset syntax info */
+#endif
+}
+
+/*
+ * Free a buffer structure and the things it contains related to the buffer
+ * itself (not the file, that must have been done already).
+ */
+ static void
+free_buffer(buf)
+ buf_T *buf;
+{
+ free_buffer_stuff(buf, TRUE);
+#ifdef FEAT_PERL
+ perl_buf_free(buf);
+#endif
+#ifdef FEAT_PYTHON
+ python_buffer_free(buf);
+#endif
+#ifdef FEAT_RUBY
+ ruby_buffer_free(buf);
+#endif
+ vim_free(buf);
+}
+
+/*
+ * Free stuff in the buffer for ":bdel" and when wiping out the buffer.
+ */
+ static void
+free_buffer_stuff(buf, free_options)
+ buf_T *buf;
+ int free_options; /* free options as well */
+{
+ if (free_options)
+ {
+ clear_wininfo(buf); /* including window-local options */
+ free_buf_options(buf, TRUE);
+ }
+#ifdef FEAT_EVAL
+ var_clear(&buf->b_vars); /* free all internal variables */
+#endif
+#ifdef FEAT_USR_CMDS
+ uc_clear(&buf->b_ucmds); /* clear local user commands */
+#endif
+#ifdef FEAT_SIGNS
+ buf_delete_signs(buf); /* delete any signs */
+#endif
+#ifdef FEAT_LOCALMAP
+ map_clear_int(buf, MAP_ALL_MODES, TRUE, FALSE); /* clear local mappings */
+ map_clear_int(buf, MAP_ALL_MODES, TRUE, TRUE); /* clear local abbrevs */
+#endif
+#ifdef FEAT_MBYTE
+ vim_free(buf->b_start_fenc);
+ buf->b_start_fenc = NULL;
+#endif
+}
+
+/*
+ * Free the b_wininfo list for buffer "buf".
+ */
+ static void
+clear_wininfo(buf)
+ buf_T *buf;
+{
+ wininfo_T *wip;
+
+ while (buf->b_wininfo != NULL)
+ {
+ wip = buf->b_wininfo;
+ buf->b_wininfo = wip->wi_next;
+ if (wip->wi_optset)
+ {
+ clear_winopt(&wip->wi_opt);
+#ifdef FEAT_FOLDING
+ deleteFoldRecurse(&wip->wi_folds);
+#endif
+ }
+ vim_free(wip);
+ }
+}
+
+#if defined(FEAT_LISTCMDS) || defined(PROTO)
+/*
+ * Go to another buffer. Handles the result of the ATTENTION dialog.
+ */
+ void
+goto_buffer(eap, start, dir, count)
+ exarg_T *eap;
+ int start;
+ int dir;
+ int count;
+{
+# if defined(FEAT_WINDOWS) \
+ && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG))
+ buf_T *old_curbuf = curbuf;
+
+ swap_exists_action = SEA_DIALOG;
+# endif
+ (void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
+ start, dir, count, eap->forceit);
+# if defined(FEAT_WINDOWS) \
+ && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG))
+ if (swap_exists_action == SEA_QUIT && *eap->cmd == 's')
+ {
+ /* Quitting means closing the split window, nothing else. */
+ win_close(curwin, TRUE);
+ swap_exists_action = SEA_NONE;
+ }
+ else
+ handle_swap_exists(old_curbuf);
+# endif
+}
+#endif
+
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
+/*
+ * Handle the situation of swap_exists_action being set.
+ * It is allowed for "old_curbuf" to be NULL or invalid.
+ */
+ void
+handle_swap_exists(old_curbuf)
+ buf_T *old_curbuf;
+{
+ if (swap_exists_action == SEA_QUIT)
+ {
+ /* User selected Quit at ATTENTION prompt. Go back to previous
+ * buffer. If that buffer is gone or the same as the current one,
+ * open a new, empty buffer. */
+ swap_exists_action = SEA_NONE; /* don't want it again */
+ close_buffer(curwin, curbuf, DOBUF_UNLOAD);
+ if (!buf_valid(old_curbuf) || old_curbuf == curbuf)
+ old_curbuf = buflist_new(NULL, NULL, 1L,
+ BLN_CURBUF | BLN_LISTED | BLN_FORCE);
+ if (old_curbuf != NULL)
+ enter_buffer(old_curbuf);
+ /* If "old_curbuf" is NULL we are in big trouble here... */
+ }
+ else if (swap_exists_action == SEA_RECOVER)
+ {
+ /* User selected Recover at ATTENTION prompt. */
+ msg_scroll = TRUE;
+ ml_recover();
+ MSG_PUTS("\n"); /* don't overwrite the last message */
+ cmdline_row = msg_row;
+ do_modelines();
+ }
+ swap_exists_action = SEA_NONE;
+}
+#endif
+
+#if defined(FEAT_LISTCMDS) || defined(PROTO)
+/*
+ * do_bufdel() - delete or unload buffer(s)
+ *
+ * addr_count == 0: ":bdel" - delete current buffer
+ * addr_count == 1: ":N bdel" or ":bdel N [N ..]" - first delete
+ * buffer "end_bnr", then any other arguments.
+ * addr_count == 2: ":N,N bdel" - delete buffers in range
+ *
+ * command can be DOBUF_UNLOAD (":bunload"), DOBUF_WIPE (":bwipeout") or
+ * DOBUF_DEL (":bdel")
+ *
+ * Returns error message or NULL
+ */
+ char_u *
+do_bufdel(command, arg, addr_count, start_bnr, end_bnr, forceit)
+ int command;
+ char_u *arg; /* pointer to extra arguments */
+ int addr_count;
+ int start_bnr; /* first buffer number in a range */
+ int end_bnr; /* buffer nr or last buffer nr in a range */
+ int forceit;
+{
+ int do_current = 0; /* delete current buffer? */
+ int deleted = 0; /* number of buffers deleted */
+ char_u *errormsg = NULL; /* return value */
+ int bnr; /* buffer number */
+ char_u *p;
+
+#ifdef FEAT_NETBEANS_INTG
+ netbeansCloseFile = 1;
+#endif
+ if (addr_count == 0)
+ {
+ (void)do_buffer(command, DOBUF_CURRENT, FORWARD, 0, forceit);
+ }
+ else
+ {
+ if (addr_count == 2)
+ {
+ if (*arg) /* both range and argument is not allowed */
+ return (char_u *)_(e_trailing);
+ bnr = start_bnr;
+ }
+ else /* addr_count == 1 */
+ bnr = end_bnr;
+
+ for ( ;!got_int; ui_breakcheck())
+ {
+ /*
+ * delete the current buffer last, otherwise when the
+ * current buffer is deleted, the next buffer becomes
+ * the current one and will be loaded, which may then
+ * also be deleted, etc.
+ */
+ if (bnr == curbuf->b_fnum)
+ do_current = bnr;
+ else if (do_buffer(command, DOBUF_FIRST, FORWARD, (int)bnr,
+ forceit) == OK)
+ ++deleted;
+
+ /*
+ * find next buffer number to delete/unload
+ */
+ if (addr_count == 2)
+ {
+ if (++bnr > end_bnr)
+ break;
+ }
+ else /* addr_count == 1 */
+ {
+ arg = skipwhite(arg);
+ if (*arg == NUL)
+ break;
+ if (!VIM_ISDIGIT(*arg))
+ {
+ p = skiptowhite_esc(arg);
+ bnr = buflist_findpat(arg, p, command == DOBUF_WIPE, FALSE);
+ if (bnr < 0) /* failed */
+ break;
+ arg = p;
+ }
+ else
+ bnr = getdigits(&arg);
+ }
+ }
+ if (!got_int && do_current && do_buffer(command, DOBUF_FIRST,
+ FORWARD, do_current, forceit) == OK)
+ ++deleted;
+
+ if (deleted == 0)
+ {
+ if (command == DOBUF_UNLOAD)
+ sprintf((char *)IObuff, _("E515: No buffers were unloaded"));
+ else if (command == DOBUF_DEL)
+ sprintf((char *)IObuff, _("E516: No buffers were deleted"));
+ else
+ sprintf((char *)IObuff, _("E517: No buffers were wiped out"));
+ errormsg = IObuff;
+ }
+ else if (deleted >= p_report)
+ {
+ if (command == DOBUF_UNLOAD)
+ {
+ if (deleted == 1)
+ MSG(_("1 buffer unloaded"));
+ else
+ smsg((char_u *)_("%d buffers unloaded"), deleted);
+ }
+ else if (command == DOBUF_DEL)
+ {
+ if (deleted == 1)
+ MSG(_("1 buffer deleted"));
+ else
+ smsg((char_u *)_("%d buffers deleted"), deleted);
+ }
+ else
+ {
+ if (deleted == 1)
+ MSG(_("1 buffer wiped out"));
+ else
+ smsg((char_u *)_("%d buffers wiped out"), deleted);
+ }
+ }
+ }
+
+#ifdef FEAT_NETBEANS_INTG
+ netbeansCloseFile = 0;
+#endif
+
+ return errormsg;
+}
+
+/*
+ * Implementation of the commands for the buffer list.
+ *
+ * action == DOBUF_GOTO go to specified buffer
+ * action == DOBUF_SPLIT split window and go to specified buffer
+ * action == DOBUF_UNLOAD unload specified buffer(s)
+ * action == DOBUF_DEL delete specified buffer(s) from buffer list
+ * action == DOBUF_WIPE delete specified buffer(s) really
+ *
+ * start == DOBUF_CURRENT go to "count" buffer from current buffer
+ * start == DOBUF_FIRST go to "count" buffer from first buffer
+ * start == DOBUF_LAST go to "count" buffer from last buffer
+ * start == DOBUF_MOD go to "count" modified buffer from current buffer
+ *
+ * Return FAIL or OK.
+ */
+ int
+do_buffer(action, start, dir, count, forceit)
+ int action;
+ int start;
+ int dir; /* FORWARD or BACKWARD */
+ int count; /* buffer number or number of buffers */
+ int forceit; /* TRUE for :...! */
+{
+ buf_T *buf;
+ buf_T *bp;
+ int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
+ || action == DOBUF_WIPE);
+
+ switch (start)
+ {
+ case DOBUF_FIRST: buf = firstbuf; break;
+ case DOBUF_LAST: buf = lastbuf; break;
+ default: buf = curbuf; break;
+ }
+ if (start == DOBUF_MOD) /* find next modified buffer */
+ {
+ while (count-- > 0)
+ {
+ do
+ {
+ buf = buf->b_next;
+ if (buf == NULL)
+ buf = firstbuf;
+ }
+ while (buf != curbuf && !bufIsChanged(buf));
+ }
+ if (!bufIsChanged(buf))
+ {
+ EMSG(_("E84: No modified buffer found"));
+ return FAIL;
+ }
+ }
+ else if (start == DOBUF_FIRST && count) /* find specified buffer number */
+ {
+ while (buf != NULL && buf->b_fnum != count)
+ buf = buf->b_next;
+ }
+ else
+ {
+ bp = NULL;
+ while (count > 0 || (!unload && !buf->b_p_bl && bp != buf))
+ {
+ /* remember the buffer where we start, we come back there when all
+ * buffers are unlisted. */
+ if (bp == NULL)
+ bp = buf;
+ if (dir == FORWARD)
+ {
+ buf = buf->b_next;
+ if (buf == NULL)
+ buf = firstbuf;
+ }
+ else
+ {
+ buf = buf->b_prev;
+ if (buf == NULL)
+ buf = lastbuf;
+ }
+ /* don't count unlisted buffers */
+ if (unload || buf->b_p_bl)
+ {
+ --count;
+ bp = NULL; /* use this buffer as new starting point */
+ }
+ if (bp == buf)
+ {
+ /* back where we started, didn't find anything. */
+ EMSG(_("E85: There is no listed buffer"));
+ return FAIL;
+ }
+ }
+ }
+
+ if (buf == NULL) /* could not find it */
+ {
+ if (start == DOBUF_FIRST)
+ {
+ /* don't warn when deleting */
+ if (!unload)
+ EMSGN(_("E86: Buffer %ld does not exist"), count);
+ }
+ else if (dir == FORWARD)
+ EMSG(_("E87: Cannot go beyond last buffer"));
+ else
+ EMSG(_("E88: Cannot go before first buffer"));
+ return FAIL;
+ }
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+
+#ifdef FEAT_LISTCMDS
+ /*
+ * delete buffer buf from memory and/or the list
+ */
+ if (unload)
+ {
+ int forward;
+ int retval;
+
+ /* When unloading or deleting a buffer that's already unloaded and
+ * unlisted: fail silently. */
+ if (action != DOBUF_WIPE && buf->b_ml.ml_mfp == NULL && !buf->b_p_bl)
+ return FAIL;
+
+ if (!forceit && bufIsChanged(buf))
+ {
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if ((p_confirm || cmdmod.confirm) && p_write)
+ {
+ dialog_changed(buf, FALSE);
+# ifdef FEAT_AUTOCMD
+ if (!buf_valid(buf))
+ /* Autocommand deleted buffer, oops! It's not changed
+ * now. */
+ return FAIL;
+# endif
+ }
+ if (bufIsChanged(buf))
+#endif
+ {
+ EMSGN(_("E89: No write since last change for buffer %ld (add ! to override)"),
+ buf->b_fnum);
+ return FAIL;
+ }
+ }
+
+ /*
+ * If deleting the last (listed) buffer, make it empty.
+ * The last (listed) buffer cannot be unloaded.
+ */
+ for (bp = firstbuf; bp != NULL; bp = bp->b_next)
+ if (bp->b_p_bl && bp != buf)
+ break;
+ if (bp == NULL && buf == curbuf)
+ {
+ if (action == DOBUF_UNLOAD)
+ {
+ EMSG(_("E90: Cannot unload last buffer"));
+ return FAIL;
+ }
+
+ /* Close any other windows on this buffer, then make it empty. */
+#ifdef FEAT_WINDOWS
+ {
+ win_T *wp, *nextwp;
+
+ for (wp = firstwin; wp != NULL; wp = nextwp)
+ {
+ nextwp = wp->w_next;
+ if (wp != curwin && wp->w_buffer == buf)
+ {
+ /* Start all over, autocommands may change the window
+ * layout. */
+ nextwp = firstwin;
+ win_close(wp, FALSE);
+ }
+ }
+ }
+#endif
+ setpcmark();
+ retval = do_ecmd(0, NULL, NULL, NULL, ECMD_ONE,
+ forceit ? ECMD_FORCEIT : 0);
+
+ /*
+ * do_ecmd() may create a new buffer, then we have to delete
+ * the old one. But do_ecmd() may have done that already, check
+ * if the buffer still exists.
+ */
+ if (buf != curbuf && buf_valid(buf) && buf->b_nwindows == 0)
+ close_buffer(NULL, buf, action);
+ return retval;
+ }
+
+#ifdef FEAT_WINDOWS
+ /*
+ * If the deleted buffer is the current one, close the current window
+ * (unless it's the only window).
+ */
+ while (buf == curbuf && firstwin != lastwin)
+ win_close(curwin, FALSE);
+#endif
+
+ /*
+ * If the buffer to be deleted is not the current one, delete it here.
+ */
+ if (buf != curbuf)
+ {
+#ifdef FEAT_WINDOWS
+ close_windows(buf);
+#endif
+ if (buf != curbuf && buf_valid(buf) && buf->b_nwindows <= 0)
+ close_buffer(NULL, buf, action);
+ return OK;
+ }
+
+ /*
+ * Deleting the current buffer: Need to find another buffer to go to.
+ * There must be another, otherwise it would have been handled above.
+ * First use au_new_curbuf, if it is valid.
+ * Then prefer the buffer we most recently visited.
+ * Else try to find one that is loaded, after the current buffer,
+ * then before the current buffer.
+ * Finally use any buffer.
+ */
+ buf = NULL; /* selected buffer */
+ bp = NULL; /* used when no loaded buffer found */
+#ifdef FEAT_AUTOCMD
+ if (au_new_curbuf != NULL && buf_valid(au_new_curbuf))
+ buf = au_new_curbuf;
+# ifdef FEAT_JUMPLIST
+ else
+# endif
+#endif
+#ifdef FEAT_JUMPLIST
+ if (curwin->w_jumplistlen > 0)
+ {
+ int jumpidx;
+
+ jumpidx = curwin->w_jumplistidx - 1;
+ if (jumpidx < 0)
+ jumpidx = curwin->w_jumplistlen - 1;
+
+ forward = jumpidx;
+ while (jumpidx != curwin->w_jumplistidx)
+ {
+ buf = buflist_findnr(curwin->w_jumplist[jumpidx].fmark.fnum);
+ if (buf != NULL)
+ {
+ if (buf == curbuf || !buf->b_p_bl)
+ buf = NULL; /* skip current and unlisted bufs */
+ else if (buf->b_ml.ml_mfp == NULL)
+ {
+ /* skip unloaded buf, but may keep it for later */
+ if (bp == NULL)
+ bp = buf;
+ buf = NULL;
+ }
+ }
+ if (buf != NULL) /* found a valid buffer: stop searching */
+ break;
+ /* advance to older entry in jump list */
+ if (!jumpidx && curwin->w_jumplistidx == curwin->w_jumplistlen)
+ break;
+ if (--jumpidx < 0)
+ jumpidx = curwin->w_jumplistlen - 1;
+ if (jumpidx == forward) /* List exhausted for sure */
+ break;
+ }
+ }
+#endif
+
+ if (buf == NULL) /* No previous buffer, Try 2'nd approach */
+ {
+ forward = TRUE;
+ buf = curbuf->b_next;
+ for (;;)
+ {
+ if (buf == NULL)
+ {
+ if (!forward) /* tried both directions */
+ break;
+ buf = curbuf->b_prev;
+ forward = FALSE;
+ continue;
+ }
+ /* in non-help buffer, try to skip help buffers, and vv */
+ if (buf->b_help == curbuf->b_help && buf->b_p_bl)
+ {
+ if (buf->b_ml.ml_mfp != NULL) /* found loaded buffer */
+ break;
+ if (bp == NULL) /* remember unloaded buf for later */
+ bp = buf;
+ }
+ if (forward)
+ buf = buf->b_next;
+ else
+ buf = buf->b_prev;
+ }
+ }
+ if (buf == NULL) /* No loaded buffer, use unloaded one */
+ buf = bp;
+ if (buf == NULL) /* No loaded buffer, find listed one */
+ {
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (buf->b_p_bl && buf != curbuf)
+ break;
+ }
+ if (buf == NULL) /* Still no buffer, just take one */
+ {
+ if (curbuf->b_next != NULL)
+ buf = curbuf->b_next;
+ else
+ buf = curbuf->b_prev;
+ }
+ }
+
+ /*
+ * make buf current buffer
+ */
+ if (action == DOBUF_SPLIT) /* split window first */
+ {
+# ifdef FEAT_WINDOWS
+ /* jump to first window containing buf if one exists ("useopen") */
+ if (vim_strchr(p_swb, 'u') && buf_jump_open_win(buf))
+ return OK;
+ if (win_split(0, 0) == FAIL)
+# endif
+ return FAIL;
+ }
+#endif
+
+ /* go to current buffer - nothing to do */
+ if (buf == curbuf)
+ return OK;
+
+ /*
+ * Check if the current buffer may be abandoned.
+ */
+ if (action == DOBUF_GOTO && !can_abandon(curbuf, forceit))
+ {
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if ((p_confirm || cmdmod.confirm) && p_write)
+ {
+ dialog_changed(curbuf, FALSE);
+# ifdef FEAT_AUTOCMD
+ if (!buf_valid(buf))
+ /* Autocommand deleted buffer, oops! */
+ return FAIL;
+# endif
+ }
+ if (bufIsChanged(curbuf))
+#endif
+ {
+ EMSG(_(e_nowrtmsg));
+ return FAIL;
+ }
+ }
+
+ /* Go to the other buffer. */
+ set_curbuf(buf, action);
+
+#if defined(FEAT_LISTCMDS) && defined(FEAT_SCROLLBIND)
+ if (action == DOBUF_SPLIT)
+ curwin->w_p_scb = FALSE; /* reset 'scrollbind' */
+#endif
+
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+ if (aborting()) /* autocmds may abort script processing */
+ return FAIL;
+#endif
+
+ return OK;
+}
+
+#endif /* FEAT_LISTCMDS */
+
+/*
+ * Set current buffer to "buf". Executes autocommands and closes current
+ * buffer. "action" tells how to close the current buffer:
+ * DOBUF_GOTO free or hide it
+ * DOBUF_SPLIT nothing
+ * DOBUF_UNLOAD unload it
+ * DOBUF_DEL delete it
+ * DOBUF_WIPE wipe it out
+ */
+ void
+set_curbuf(buf, action)
+ buf_T *buf;
+ int action;
+{
+ buf_T *prevbuf;
+ int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
+ || action == DOBUF_WIPE);
+
+ setpcmark();
+ curwin->w_alt_fnum = curbuf->b_fnum; /* remember alternate file */
+ buflist_altfpos(); /* remember curpos */
+
+#ifdef FEAT_VISUAL
+ /* Don't restart Select mode after switching to another buffer. */
+ VIsual_reselect = FALSE;
+#endif
+
+ /* close_windows() or apply_autocmds() may change curbuf */
+ prevbuf = curbuf;
+
+#ifdef FEAT_AUTOCMD
+ apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
+# ifdef FEAT_EVAL
+ if (buf_valid(prevbuf) && !aborting())
+# else
+ if (buf_valid(prevbuf))
+# endif
+#endif
+ {
+#ifdef FEAT_WINDOWS
+ if (unload)
+ close_windows(prevbuf);
+#endif
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+ if (buf_valid(prevbuf) && !aborting())
+#else
+ if (buf_valid(prevbuf))
+#endif
+ close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL, prevbuf,
+ unload ? action : (action == DOBUF_GOTO
+ && !P_HID(prevbuf)
+ && !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0);
+ }
+#ifdef FEAT_AUTOCMD
+# ifdef FEAT_EVAL
+ /* An autocommand may have deleted buf or aborted the script processing! */
+ if (buf_valid(buf) && !aborting())
+# else
+ if (buf_valid(buf)) /* an autocommand may have deleted buf! */
+# endif
+#endif
+ enter_buffer(buf);
+}
+
+/*
+ * Enter a new current buffer.
+ * Old curbuf must have been abandoned already!
+ */
+ void
+enter_buffer(buf)
+ buf_T *buf;
+{
+ /* Copy buffer and window local option values. Not for a help buffer. */
+ buf_copy_options(buf, BCO_ENTER | BCO_NOHELP);
+ if (!buf->b_help)
+ get_winopts(buf);
+#ifdef FEAT_FOLDING
+ else
+ /* Remove all folds in the window. */
+ clearFolding(curwin);
+ foldUpdateAll(curwin); /* update folds (later). */
+#endif
+
+ /* Get the buffer in the current window. */
+ curwin->w_buffer = buf;
+ curbuf = buf;
+ ++curbuf->b_nwindows;
+
+#ifdef FEAT_DIFF
+ diff_new_buffer();
+#endif
+
+ /* Cursor on first line by default. */
+ curwin->w_cursor.lnum = 1;
+ curwin->w_cursor.col = 0;
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ curwin->w_set_curswant = TRUE;
+
+ /* Make sure the buffer is loaded. */
+ if (curbuf->b_ml.ml_mfp == NULL) /* need to load the file */
+ open_buffer(FALSE, NULL);
+ else
+ {
+ need_fileinfo = TRUE; /* display file info after redraw */
+ (void)buf_check_timestamp(curbuf, FALSE); /* check if file changed */
+#ifdef FEAT_AUTOCMD
+ curwin->w_topline = 1;
+# ifdef FEAT_DIFF
+ curwin->w_topfill = 0;
+# endif
+ apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
+ apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
+#endif
+ }
+
+ /* If autocommands did not change the cursor position, restore cursor lnum
+ * and possibly cursor col. */
+ if (curwin->w_cursor.lnum == 1 && inindent(0))
+ buflist_getfpos();
+
+ check_arg_idx(curwin); /* check for valid arg_idx */
+#ifdef FEAT_TITLE
+ maketitle();
+#endif
+#ifdef FEAT_AUTOCMD
+ if (curwin->w_topline == 1) /* when autocmds didn't change it */
+#endif
+ scroll_cursor_halfway(FALSE); /* redisplay at correct position */
+
+#if defined(FEAT_NETBEANS_INTG) || defined(FEAT_SUN_WORKSHOP)
+ /* Change directories when the acd option is set on. */
+ if (p_acd && curbuf->b_ffname != NULL
+ && vim_chdirfile(curbuf->b_ffname) == OK)
+ shorten_fnames(TRUE);
+#endif
+
+#ifdef FEAT_KEYMAP
+ if (curbuf->b_kmap_state & KEYMAP_INIT)
+ keymap_init();
+#endif
+ redraw_later(NOT_VALID);
+}
+
+/*
+ * functions for dealing with the buffer list
+ */
+
+/*
+ * Add a file name to the buffer list. Return a pointer to the buffer.
+ * If the same file name already exists return a pointer to that buffer.
+ * If it does not exist, or if fname == NULL, a new entry is created.
+ * If (flags & BLN_CURBUF) is TRUE, may use current buffer.
+ * If (flags & BLN_LISTED) is TRUE, add new buffer to buffer list.
+ * If (flags & BLN_DUMMY) is TRUE, don't count it as a real buffer.
+ * If (flags & BLN_FORCE) is TRUE, don't abort on an error.
+ * This is the ONLY way to create a new buffer.
+ */
+static int top_file_num = 1; /* highest file number */
+
+ buf_T *
+buflist_new(ffname, sfname, lnum, flags)
+ char_u *ffname; /* full path of fname or relative */
+ char_u *sfname; /* short fname or NULL */
+ linenr_T lnum; /* preferred cursor line */
+ int flags; /* BLN_ defines */
+{
+ buf_T *buf;
+#ifdef UNIX
+ struct stat st;
+#endif
+
+ fname_expand(curbuf, &ffname, &sfname); /* will allocate ffname */
+
+ /*
+ * If file name already exists in the list, update the entry.
+ */
+#ifdef UNIX
+ /* On Unix we can use inode numbers when the file exists. Works better
+ * for hard links. */
+ if (sfname == NULL || mch_stat((char *)sfname, &st) < 0)
+ st.st_dev = (dev_T)-1;
+#endif
+ if (ffname != NULL && !(flags & BLN_DUMMY) && (buf =
+#ifdef UNIX
+ buflist_findname_stat(ffname, &st)
+#else
+ buflist_findname(ffname)
+#endif
+ ) != NULL)
+ {
+ vim_free(ffname);
+ if (lnum != 0)
+ buflist_setfpos(buf, curwin, lnum, (colnr_T)0, FALSE);
+ /* copy the options now, if 'cpo' doesn't have 's' and not done
+ * already */
+ buf_copy_options(buf, 0);
+ if ((flags & BLN_LISTED) && !buf->b_p_bl)
+ {
+ buf->b_p_bl = TRUE;
+#ifdef FEAT_AUTOCMD
+ if (!(flags & BLN_DUMMY))
+ apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
+#endif
+ }
+ return buf;
+ }
+
+ /*
+ * If the current buffer has no name and no contents, use the current
+ * buffer. Otherwise: Need to allocate a new buffer structure.
+ *
+ * This is the ONLY place where a new buffer structure is allocated!
+ */
+ buf = NULL;
+ if ((flags & BLN_CURBUF)
+ && curbuf != NULL
+ && curbuf->b_ffname == NULL
+ && curbuf->b_nwindows <= 1
+ && (curbuf->b_ml.ml_mfp == NULL || bufempty()))
+ {
+ buf = curbuf;
+#ifdef FEAT_AUTOCMD
+ /* It's like this buffer is deleted. Watch out for autocommands that
+ * change curbuf! If that happens, allocate a new buffer anyway. */
+ if (curbuf->b_p_bl)
+ apply_autocmds(EVENT_BUFDELETE, NULL, NULL, FALSE, curbuf);
+ if (buf == curbuf)
+ apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, FALSE, curbuf);
+# ifdef FEAT_EVAL
+ /* autocmds may abort script processing */
+ if (!(flags & BLN_FORCE) && aborting())
+ return NULL;
+# endif
+#endif
+#ifdef FEAT_QUICKFIX
+# ifdef FEAT_AUTOCMD
+ if (buf == curbuf)
+# endif
+ {
+ /* Make sure 'bufhidden' and 'buftype' are empty */
+ clear_string_option(&buf->b_p_bh);
+ clear_string_option(&buf->b_p_bt);
+ }
+#endif
+ }
+ if (buf != curbuf || curbuf == NULL)
+ {
+ buf = (buf_T *)alloc_clear((unsigned)sizeof(buf_T));
+ if (buf == NULL)
+ {
+ vim_free(ffname);
+ return NULL;
+ }
+ }
+
+ if (ffname != NULL)
+ {
+ buf->b_ffname = ffname;
+ buf->b_sfname = vim_strsave(sfname);
+ }
+
+ clear_wininfo(buf);
+ buf->b_wininfo = (wininfo_T *)alloc_clear((unsigned)sizeof(wininfo_T));
+
+ if ((ffname != NULL && (buf->b_ffname == NULL || buf->b_sfname == NULL))
+ || buf->b_wininfo == NULL)
+ {
+ vim_free(buf->b_ffname);
+ buf->b_ffname = NULL;
+ vim_free(buf->b_sfname);
+ buf->b_sfname = NULL;
+ if (buf != curbuf)
+ free_buffer(buf);
+ return NULL;
+ }
+
+ if (buf == curbuf)
+ {
+ /* free all things allocated for this buffer */
+ buf_freeall(buf, FALSE, FALSE);
+ if (buf != curbuf) /* autocommands deleted the buffer! */
+ return NULL;
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+ /* autocmds may abort script processing */
+ if (!(flags & BLN_FORCE) && aborting())
+ return NULL;
+#endif
+ /* buf->b_nwindows = 0; why was this here? */
+ free_buffer_stuff(buf, FALSE); /* delete local variables et al. */
+#ifdef FEAT_KEYMAP
+ /* need to reload lmaps and set b:keymap_name */
+ curbuf->b_kmap_state |= KEYMAP_INIT;
+#endif
+ }
+ else
+ {
+ /*
+ * put new buffer at the end of the buffer list
+ */
+ buf->b_next = NULL;
+ if (firstbuf == NULL) /* buffer list is empty */
+ {
+ buf->b_prev = NULL;
+ firstbuf = buf;
+ }
+ else /* append new buffer at end of list */
+ {
+ lastbuf->b_next = buf;
+ buf->b_prev = lastbuf;
+ }
+ lastbuf = buf;
+
+ buf->b_fnum = top_file_num++;
+ if (top_file_num < 0) /* wrap around (may cause duplicates) */
+ {
+ EMSG(_("W14: Warning: List of file names overflow"));
+ if (emsg_silent == 0)
+ {
+ out_flush();
+ ui_delay(3000L, TRUE); /* make sure it is noticed */
+ }
+ top_file_num = 1;
+ }
+
+ /*
+ * Always copy the options from the current buffer.
+ */
+ buf_copy_options(buf, BCO_ALWAYS);
+ }
+
+ buf->b_wininfo->wi_fpos.lnum = lnum;
+ buf->b_wininfo->wi_win = curwin;
+
+#ifdef FEAT_EVAL
+ var_init(&buf->b_vars); /* init internal variables */
+#endif
+
+ buf->b_fname = buf->b_sfname;
+#ifdef UNIX
+ if (st.st_dev == (dev_T)-1)
+ buf->b_dev = -1;
+ else
+ {
+ buf->b_dev = st.st_dev;
+ buf->b_ino = st.st_ino;
+ }
+#endif
+ buf->b_u_synced = TRUE;
+ buf->b_flags = BF_CHECK_RO | BF_NEVERLOADED;
+ buf_clear_file(buf);
+ clrallmarks(buf); /* clear marks */
+ fmarks_check_names(buf); /* check file marks for this file */
+ buf->b_p_bl = (flags & BLN_LISTED) ? TRUE : FALSE; /* init 'buflisted' */
+#ifdef FEAT_AUTOCMD
+ if (!(flags & BLN_DUMMY))
+ {
+ apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, buf);
+ if (flags & BLN_LISTED)
+ apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
+# ifdef FEAT_EVAL
+ /* autocmds may abort script processing */
+ if (!(flags & BLN_FORCE) && aborting())
+ return NULL;
+# endif
+ }
+#endif
+
+ return buf;
+}
+
+/*
+ * Free the memory for the options of a buffer.
+ * If "free_p_ff" is TRUE also free 'fileformat', 'buftype' and
+ * 'fileencoding'.
+ */
+ void
+free_buf_options(buf, free_p_ff)
+ buf_T *buf;
+ int free_p_ff;
+{
+ if (free_p_ff)
+ {
+#ifdef FEAT_MBYTE
+ clear_string_option(&buf->b_p_fenc);
+#endif
+ clear_string_option(&buf->b_p_ff);
+#ifdef FEAT_QUICKFIX
+ clear_string_option(&buf->b_p_bh);
+ clear_string_option(&buf->b_p_bt);
+#endif
+ }
+#ifdef FEAT_FIND_ID
+ clear_string_option(&buf->b_p_def);
+ clear_string_option(&buf->b_p_inc);
+# ifdef FEAT_EVAL
+ clear_string_option(&buf->b_p_inex);
+# endif
+#endif
+#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
+ clear_string_option(&buf->b_p_inde);
+ clear_string_option(&buf->b_p_indk);
+#endif
+#ifdef FEAT_CRYPT
+ clear_string_option(&buf->b_p_key);
+#endif
+ clear_string_option(&buf->b_p_kp);
+ clear_string_option(&buf->b_p_mps);
+ clear_string_option(&buf->b_p_fo);
+ clear_string_option(&buf->b_p_isk);
+#ifdef FEAT_KEYMAP
+ clear_string_option(&buf->b_p_keymap);
+ ga_clear(&buf->b_kmap_ga);
+#endif
+#ifdef FEAT_COMMENTS
+ clear_string_option(&buf->b_p_com);
+#endif
+#ifdef FEAT_FOLDING
+ clear_string_option(&buf->b_p_cms);
+#endif
+ clear_string_option(&buf->b_p_nf);
+#ifdef FEAT_SYN_HL
+ clear_string_option(&buf->b_p_syn);
+#endif
+#ifdef FEAT_SEARCHPATH
+ clear_string_option(&buf->b_p_sua);
+#endif
+#ifdef FEAT_AUTOCMD
+ clear_string_option(&buf->b_p_ft);
+#endif
+#ifdef FEAT_OSFILETYPE
+ clear_string_option(&buf->b_p_oft);
+#endif
+#ifdef FEAT_CINDENT
+ clear_string_option(&buf->b_p_cink);
+ clear_string_option(&buf->b_p_cino);
+#endif
+#if defined(FEAT_CINDENT) || defined(FEAT_SMARTINDENT)
+ clear_string_option(&buf->b_p_cinw);
+#endif
+#ifdef FEAT_INS_EXPAND
+ clear_string_option(&buf->b_p_cpt);
+#endif
+#ifdef FEAT_QUICKFIX
+ clear_string_option(&buf->b_p_gp);
+ clear_string_option(&buf->b_p_mp);
+ clear_string_option(&buf->b_p_efm);
+#endif
+ clear_string_option(&buf->b_p_ep);
+ clear_string_option(&buf->b_p_path);
+ clear_string_option(&buf->b_p_tags);
+#ifdef FEAT_INS_EXPAND
+ clear_string_option(&buf->b_p_dict);
+ clear_string_option(&buf->b_p_tsr);
+#endif
+ buf->b_p_ar = -1;
+}
+
+/*
+ * get alternate file n
+ * set linenr to lnum or altfpos.lnum if lnum == 0
+ * also set cursor column to altfpos.col if 'startofline' is not set.
+ * if (options & GETF_SETMARK) call setpcmark()
+ * if (options & GETF_ALT) we are jumping to an alternate file.
+ * if (options & GETF_SWITCH) respect 'switchbuf' settings when jumping
+ *
+ * return FAIL for failure, OK for success
+ */
+ int
+buflist_getfile(n, lnum, options, forceit)
+ int n;
+ linenr_T lnum;
+ int options;
+ int forceit;
+{
+ buf_T *buf;
+#ifdef FEAT_WINDOWS
+ win_T *wp = NULL;
+#endif
+ pos_T *fpos;
+ colnr_T col;
+
+ buf = buflist_findnr(n);
+ if (buf == NULL)
+ {
+ if ((options & GETF_ALT) && n == 0)
+ EMSG(_(e_noalt));
+ else
+ EMSGN(_("E92: Buffer %ld not found"), n);
+ return FAIL;
+ }
+
+ /* if alternate file is the current buffer, nothing to do */
+ if (buf == curbuf)
+ return OK;
+
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ return FAIL;
+#endif
+
+ /* altfpos may be changed by getfile(), get it now */
+ if (lnum == 0)
+ {
+ fpos = buflist_findfpos(buf);
+ lnum = fpos->lnum;
+ col = fpos->col;
+ }
+ else
+ col = 0;
+
+#ifdef FEAT_WINDOWS
+ if (options & GETF_SWITCH)
+ {
+ /* use existing open window for buffer if wanted */
+ if (vim_strchr(p_swb, 'u')) /* useopen */
+ wp = buf_jump_open_win(buf);
+ /* split window if wanted ("split") */
+ if (wp == NULL && vim_strchr(p_swb, 't') && !bufempty())
+ {
+ if (win_split(0, 0) == FAIL)
+ return FAIL;
+# ifdef FEAT_SCROLLBIND
+ curwin->w_p_scb = FALSE;
+# endif
+ }
+ }
+#endif
+
+ ++RedrawingDisabled;
+ if (getfile(buf->b_fnum, NULL, NULL, (options & GETF_SETMARK),
+ lnum, forceit) <= 0)
+ {
+ --RedrawingDisabled;
+
+ /* cursor is at to BOL and w_cursor.lnum is checked due to getfile() */
+ if (!p_sol && col != 0)
+ {
+ curwin->w_cursor.col = col;
+ check_cursor_col();
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ curwin->w_set_curswant = TRUE;
+ }
+ return OK;
+ }
+ --RedrawingDisabled;
+ return FAIL;
+}
+
+/*
+ * go to the last know line number for the current buffer
+ */
+ void
+buflist_getfpos()
+{
+ pos_T *fpos;
+
+ fpos = buflist_findfpos(curbuf);
+
+ curwin->w_cursor.lnum = fpos->lnum;
+ check_cursor_lnum();
+
+ if (p_sol)
+ curwin->w_cursor.col = 0;
+ else
+ {
+ curwin->w_cursor.col = fpos->col;
+ check_cursor_col();
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ curwin->w_set_curswant = TRUE;
+ }
+}
+
+/*
+ * Find file in buffer list by name (it has to be for the current window).
+ * "ffname" must have a full path.
+ */
+ buf_T *
+buflist_findname(ffname)
+ char_u *ffname;
+{
+#ifdef UNIX
+ struct stat st;
+
+ if (mch_stat((char *)ffname, &st) < 0)
+ st.st_dev = (dev_T)-1;
+ return buflist_findname_stat(ffname, &st);
+}
+
+/*
+ * Same as buflist_findname(), but pass the stat structure to avoid getting it
+ * twice for the same file.
+ */
+ static buf_T *
+buflist_findname_stat(ffname, stp)
+ char_u *ffname;
+ struct stat *stp;
+{
+#endif
+ buf_T *buf;
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (!otherfile_buf(buf, ffname
+#ifdef UNIX
+ , stp
+#endif
+ ))
+ return buf;
+ return NULL;
+}
+
+#if defined(FEAT_LISTCMDS) || defined(FEAT_EVAL) || defined(FEAT_PERL) || defined(PROTO)
+/*
+ * Find file in buffer list by a regexp pattern.
+ * Return fnum of the found buffer.
+ * Return < 0 for error.
+ */
+/*ARGSUSED*/
+ int
+buflist_findpat(pattern, pattern_end, unlisted, diffmode)
+ char_u *pattern;
+ char_u *pattern_end; /* pointer to first char after pattern */
+ int unlisted; /* find unlisted buffers */
+ int diffmode; /* find diff-mode buffers only */
+{
+ buf_T *buf;
+ regprog_T *prog;
+ int match = -1;
+ int find_listed;
+ char_u *pat;
+ char_u *patend;
+ int attempt;
+ char_u *p;
+ int toggledollar;
+
+ if (pattern_end == pattern + 1 && (*pattern == '%' || *pattern == '#'))
+ {
+ if (*pattern == '%')
+ match = curbuf->b_fnum;
+ else
+ match = curwin->w_alt_fnum;
+#ifdef FEAT_DIFF
+ if (diffmode && !diff_mode_buf(buflist_findnr(match)))
+ match = -1;
+#endif
+ }
+
+ /*
+ * Try four ways of matching a listed buffer:
+ * attempt == 0: without '^' or '$' (at any position)
+ * attempt == 1: with '^' at start (only at postion 0)
+ * attempt == 2: with '$' at end (only match at end)
+ * attempt == 3: with '^' at start and '$' at end (only full match)
+ * Repeat this for finding an unlisted buffer if there was no matching
+ * listed buffer.
+ */
+ else
+ {
+ pat = file_pat_to_reg_pat(pattern, pattern_end, NULL, FALSE);
+ if (pat == NULL)
+ return -1;
+ patend = pat + STRLEN(pat) - 1;
+ toggledollar = (patend > pat && *patend == '$');
+
+ /* First try finding a listed buffer. If not found and "unlisted"
+ * is TRUE, try finding an unlisted buffer. */
+ find_listed = TRUE;
+ for (;;)
+ {
+ for (attempt = 0; attempt <= 3; ++attempt)
+ {
+ /* may add '^' and '$' */
+ if (toggledollar)
+ *patend = (attempt < 2) ? NUL : '$'; /* add/remove '$' */
+ p = pat;
+ if (*p == '^' && !(attempt & 1)) /* add/remove '^' */
+ ++p;
+ prog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
+ if (prog == NULL)
+ {
+ vim_free(pat);
+ return -1;
+ }
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (buf->b_p_bl == find_listed
+#ifdef FEAT_DIFF
+ && (!diffmode || diff_mode_buf(buf))
+#endif
+ && buflist_match(prog, buf) != NULL)
+ {
+ if (match >= 0) /* already found a match */
+ {
+ match = -2;
+ break;
+ }
+ match = buf->b_fnum; /* remember first match */
+ }
+
+ vim_free(prog);
+ if (match >= 0) /* found one match */
+ break;
+ }
+
+ /* Only search for unlisted buffers if there was no match with
+ * a listed buffer. */
+ if (!unlisted || !find_listed || match != -1)
+ break;
+ find_listed = FALSE;
+ }
+
+ vim_free(pat);
+ }
+
+ if (match == -2)
+ EMSG2(_("E93: More than one match for %s"), pattern);
+ else if (match < 0)
+ EMSG2(_("E94: No matching buffer for %s"), pattern);
+ return match;
+}
+#endif
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+
+/*
+ * Find all buffer names that match.
+ * For command line expansion of ":buf" and ":sbuf".
+ * Return OK if matches found, FAIL otherwise.
+ */
+ int
+ExpandBufnames(pat, num_file, file, options)
+ char_u *pat;
+ int *num_file;
+ char_u ***file;
+ int options;
+{
+ int count = 0;
+ buf_T *buf;
+ int round;
+ char_u *p;
+ int attempt;
+ regprog_T *prog;
+
+ *num_file = 0; /* return values in case of FAIL */
+ *file = NULL;
+
+ /*
+ * attempt == 1: try match with '^', match at start
+ * attempt == 2: try match without '^', match anywhere
+ */
+ for (attempt = 1; attempt <= 2; ++attempt)
+ {
+ if (attempt == 2)
+ {
+ if (*pat != '^') /* there's no '^', no need to try again */
+ break;
+ ++pat; /* skip the '^' */
+ }
+ prog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
+ if (prog == NULL)
+ return FAIL;
+
+ /*
+ * round == 1: Count the matches.
+ * round == 2: Build the array to keep the matches.
+ */
+ for (round = 1; round <= 2; ++round)
+ {
+ count = 0;
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ if (!buf->b_p_bl) /* skip unlisted buffers */
+ continue;
+ p = buflist_match(prog, buf);
+ if (p != NULL)
+ {
+ if (round == 1)
+ ++count;
+ else
+ {
+ if (options & WILD_HOME_REPLACE)
+ p = home_replace_save(buf, p);
+ else
+ p = vim_strsave(p);
+ (*file)[count++] = p;
+ }
+ }
+ }
+ if (count == 0) /* no match found, break here */
+ break;
+ if (round == 1)
+ {
+ *file = (char_u **)alloc((unsigned)(count * sizeof(char_u *)));
+ if (*file == NULL)
+ {
+ vim_free(prog);
+ return FAIL;
+ }
+ }
+ }
+ vim_free(prog);
+ if (count) /* match(es) found, break here */
+ break;
+ }
+
+ *num_file = count;
+ return (count == 0 ? FAIL : OK);
+}
+
+#endif /* FEAT_CMDL_COMPL */
+
+#ifdef HAVE_BUFLIST_MATCH
+/*
+ * Check for a match on the file name for buffer "buf" with regprog "prog".
+ */
+ static char_u *
+buflist_match(prog, buf)
+ regprog_T *prog;
+ buf_T *buf;
+{
+ char_u *match;
+
+ /* First try the short file name, then the long file name. */
+ match = fname_match(prog, buf->b_sfname);
+ if (match == NULL)
+ match = fname_match(prog, buf->b_ffname);
+
+ return match;
+}
+
+/*
+ * Try matching the regexp in "prog" with file name "name".
+ * Return "name" when there is a match, NULL when not.
+ */
+ static char_u *
+fname_match(prog, name)
+ regprog_T *prog;
+ char_u *name;
+{
+ char_u *match = NULL;
+ char_u *p;
+ regmatch_T regmatch;
+
+ if (name != NULL)
+ {
+ regmatch.regprog = prog;
+#ifdef CASE_INSENSITIVE_FILENAME
+ regmatch.rm_ic = TRUE; /* Always ignore case */
+#else
+ regmatch.rm_ic = FALSE; /* Never ignore case */
+#endif
+
+ if (vim_regexec(&regmatch, name, (colnr_T)0))
+ match = name;
+ else
+ {
+ /* Replace $(HOME) with '~' and try matching again. */
+ p = home_replace_save(NULL, name);
+ if (p != NULL && vim_regexec(&regmatch, p, (colnr_T)0))
+ match = name;
+ vim_free(p);
+ }
+ }
+
+ return match;
+}
+#endif
+
+/*
+ * find file in buffer list by number
+ */
+ buf_T *
+buflist_findnr(nr)
+ int nr;
+{
+ buf_T *buf;
+
+ if (nr == 0)
+ nr = curwin->w_alt_fnum;
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (buf->b_fnum == nr)
+ return (buf);
+ return NULL;
+}
+
+/*
+ * Get name of file 'n' in the buffer list.
+ * When the file has no name an empty string is returned.
+ * home_replace() is used to shorten the file name (used for marks).
+ * Returns a pointer to allocated memory, of NULL when failed.
+ */
+ char_u *
+buflist_nr2name(n, fullname, helptail)
+ int n;
+ int fullname;
+ int helptail; /* for help buffers return tail only */
+{
+ buf_T *buf;
+
+ buf = buflist_findnr(n);
+ if (buf == NULL)
+ return NULL;
+ return home_replace_save(helptail ? buf : NULL,
+ fullname ? buf->b_ffname : buf->b_fname);
+}
+
+/*
+ * Set the "lnum" and "col" for the buffer "buf" and the current window.
+ * When "copy_options" is TRUE save the local window option values.
+ * When "lnum" is 0 only do the options.
+ */
+ static void
+buflist_setfpos(buf, win, lnum, col, copy_options)
+ buf_T *buf;
+ win_T *win;
+ linenr_T lnum;
+ colnr_T col;
+ int copy_options;
+{
+ wininfo_T *wip;
+
+ for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next)
+ if (wip->wi_win == win)
+ break;
+ if (wip == NULL)
+ {
+ /* allocate a new entry */
+ wip = (wininfo_T *)alloc_clear((unsigned)sizeof(wininfo_T));
+ if (wip == NULL)
+ return;
+ wip->wi_win = win;
+ if (lnum == 0) /* set lnum even when it's 0 */
+ lnum = 1;
+ }
+ else
+ {
+ /* remove the entry from the list */
+ if (wip->wi_prev)
+ wip->wi_prev->wi_next = wip->wi_next;
+ else
+ buf->b_wininfo = wip->wi_next;
+ if (wip->wi_next)
+ wip->wi_next->wi_prev = wip->wi_prev;
+ if (copy_options && wip->wi_optset)
+ {
+ clear_winopt(&wip->wi_opt);
+#ifdef FEAT_FOLDING
+ deleteFoldRecurse(&wip->wi_folds);
+#endif
+ }
+ }
+ if (lnum != 0)
+ {
+ wip->wi_fpos.lnum = lnum;
+ wip->wi_fpos.col = col;
+ }
+ if (copy_options)
+ {
+ /* Save the window-specific option values. */
+ copy_winopt(&win->w_onebuf_opt, &wip->wi_opt);
+#ifdef FEAT_FOLDING
+ wip->wi_fold_manual = win->w_fold_manual;
+ cloneFoldGrowArray(&win->w_folds, &wip->wi_folds);
+#endif
+ wip->wi_optset = TRUE;
+ }
+
+ /* insert the entry in front of the list */
+ wip->wi_next = buf->b_wininfo;
+ buf->b_wininfo = wip;
+ wip->wi_prev = NULL;
+ if (wip->wi_next)
+ wip->wi_next->wi_prev = wip;
+
+ return;
+}
+
+/*
+ * Find info for the current window in buffer "buf".
+ * If not found, return the info for the most recently used window.
+ * Returns NULL when there isn't any info.
+ */
+ static wininfo_T *
+find_wininfo(buf)
+ buf_T *buf;
+{
+ wininfo_T *wip;
+
+ for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next)
+ if (wip->wi_win == curwin)
+ break;
+ if (wip == NULL) /* if no fpos for curwin, use the first in the list */
+ wip = buf->b_wininfo;
+ return wip;
+}
+
+/*
+ * Reset the local window options to the values last used in this window.
+ * If the buffer wasn't used in this window before, use the values from
+ * the most recently used window. If the values were never set, use the
+ * global values for the window.
+ */
+ void
+get_winopts(buf)
+ buf_T *buf;
+{
+ wininfo_T *wip;
+
+ clear_winopt(&curwin->w_onebuf_opt);
+#ifdef FEAT_FOLDING
+ clearFolding(curwin);
+#endif
+
+ wip = find_wininfo(buf);
+ if (wip != NULL && wip->wi_optset)
+ {
+ copy_winopt(&wip->wi_opt, &curwin->w_onebuf_opt);
+#ifdef FEAT_FOLDING
+ curwin->w_fold_manual = wip->wi_fold_manual;
+ curwin->w_foldinvalid = TRUE;
+ cloneFoldGrowArray(&wip->wi_folds, &curwin->w_folds);
+#endif
+ }
+ else
+ copy_winopt(&curwin->w_allbuf_opt, &curwin->w_onebuf_opt);
+
+#ifdef FEAT_FOLDING
+ /* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */
+ if (p_fdls >= 0)
+ curwin->w_p_fdl = p_fdls;
+#endif
+}
+
+/*
+ * Find the position (lnum and col) for the buffer 'buf' for the current
+ * window.
+ * Returns a pointer to no_position if no position is found.
+ */
+ pos_T *
+buflist_findfpos(buf)
+ buf_T *buf;
+{
+ wininfo_T *wip;
+ static pos_T no_position = {1, 0};
+
+ wip = find_wininfo(buf);
+ if (wip != NULL)
+ return &(wip->wi_fpos);
+ else
+ return &no_position;
+}
+
+/*
+ * Find the lnum for the buffer 'buf' for the current window.
+ */
+ linenr_T
+buflist_findlnum(buf)
+ buf_T *buf;
+{
+ return buflist_findfpos(buf)->lnum;
+}
+
+#if defined(FEAT_LISTCMDS) || defined(PROTO)
+/*
+ * List all know file names (for :files and :buffers command).
+ */
+/*ARGSUSED*/
+ void
+buflist_list(eap)
+ exarg_T *eap;
+{
+ buf_T *buf;
+ int len;
+ int i;
+
+ for (buf = firstbuf; buf != NULL && !got_int; buf = buf->b_next)
+ {
+ /* skip unlisted buffers, unless ! was used */
+ if (!buf->b_p_bl && !eap->forceit)
+ continue;
+ msg_putchar('\n');
+ if (buf_spname(buf) != NULL)
+ STRCPY(NameBuff, buf_spname(buf));
+ else
+ home_replace(buf, buf->b_fname, NameBuff, MAXPATHL, TRUE);
+
+ sprintf((char *)IObuff, "%3d%c%c%c%c%c \"",
+ buf->b_fnum,
+ buf->b_p_bl ? ' ' : 'u',
+ buf == curbuf ? '%' :
+ (curwin->w_alt_fnum == buf->b_fnum ? '#' : ' '),
+ buf->b_ml.ml_mfp == NULL ? ' ' :
+ (buf->b_nwindows == 0 ? 'h' : 'a'),
+ !buf->b_p_ma ? '-' : (buf->b_p_ro ? '=' : ' '),
+ (buf->b_flags & BF_READERR) ? 'x'
+ : (bufIsChanged(buf) ? '+' : ' ')
+ );
+
+ len = (int)STRLEN(IObuff);
+ STRNCPY(IObuff + len, NameBuff, IOSIZE - 20 - len);
+ IObuff[IOSIZE - 20 - len] = NUL; /* make sure it's terminated */
+
+ len = (int)STRLEN(IObuff);
+ IObuff[len++] = '"';
+
+ /* put "line 999" in column 40 or after the file name */
+ IObuff[len] = NUL;
+ i = 40 - vim_strsize(IObuff);
+ do
+ {
+ IObuff[len++] = ' ';
+ } while (--i > 0 && len < IOSIZE - 18);
+ sprintf((char *)IObuff + len, _("line %ld"),
+ buf == curbuf ? curwin->w_cursor.lnum :
+ (long)buflist_findlnum(buf));
+ msg_outtrans(IObuff);
+ out_flush(); /* output one line at a time */
+ ui_breakcheck();
+ }
+}
+#endif
+
+/*
+ * Get file name and line number for file 'fnum'.
+ * Used by DoOneCmd() for translating '%' and '#'.
+ * Used by insert_reg() and cmdline_paste() for '#' register.
+ * Return FAIL if not found, OK for success.
+ */
+ int
+buflist_name_nr(fnum, fname, lnum)
+ int fnum;
+ char_u **fname;
+ linenr_T *lnum;
+{
+ buf_T *buf;
+
+ buf = buflist_findnr(fnum);
+ if (buf == NULL || buf->b_fname == NULL)
+ return FAIL;
+
+ *fname = buf->b_fname;
+ *lnum = buflist_findlnum(buf);
+
+ return OK;
+}
+
+/*
+ * Set the file name for "buf"' to 'ffname', short file name to 'sfname'.
+ * The file name with the full path is also remembered, for when :cd is used.
+ * Returns FAIL for failure (file name already in use by other buffer)
+ * OK otherwise.
+ */
+ int
+setfname(buf, ffname, sfname, message)
+ buf_T *buf;
+ char_u *ffname, *sfname;
+ int message;
+{
+ buf_T *obuf;
+#ifdef UNIX
+ struct stat st;
+#endif
+
+ if (ffname == NULL || *ffname == NUL)
+ {
+ /* Removing the name. */
+ vim_free(buf->b_ffname);
+ vim_free(buf->b_sfname);
+ buf->b_ffname = NULL;
+ buf->b_sfname = NULL;
+#ifdef UNIX
+ st.st_dev = (dev_T)-1;
+#endif
+ }
+ else
+ {
+ fname_expand(buf, &ffname, &sfname); /* will allocate ffname */
+ if (ffname == NULL) /* out of memory */
+ return FAIL;
+
+ /*
+ * if the file name is already used in another buffer:
+ * - if the buffer is loaded, fail
+ * - if the buffer is not loaded, delete it from the list
+ */
+#ifdef UNIX
+ if (mch_stat((char *)ffname, &st) < 0)
+ st.st_dev = (dev_T)-1;
+ obuf = buflist_findname_stat(ffname, &st);
+#else
+ obuf = buflist_findname(ffname);
+#endif
+ if (obuf != NULL && obuf != buf)
+ {
+ if (obuf->b_ml.ml_mfp != NULL) /* it's loaded, fail */
+ {
+ if (message)
+ EMSG(_("E95: Buffer with this name already exists"));
+ vim_free(ffname);
+ return FAIL;
+ }
+ close_buffer(NULL, obuf, DOBUF_WIPE); /* delete from the list */
+ }
+ sfname = vim_strsave(sfname);
+ if (ffname == NULL || sfname == NULL)
+ {
+ vim_free(sfname);
+ vim_free(ffname);
+ return FAIL;
+ }
+#ifdef USE_FNAME_CASE
+# ifdef USE_LONG_FNAME
+ if (USE_LONG_FNAME)
+# endif
+ fname_case(sfname, 0); /* set correct case for short file name */
+#endif
+ vim_free(buf->b_ffname);
+ vim_free(buf->b_sfname);
+ buf->b_ffname = ffname;
+ buf->b_sfname = sfname;
+ }
+ buf->b_fname = buf->b_sfname;
+#ifdef UNIX
+ if (st.st_dev == (dev_T)-1)
+ buf->b_dev = -1;
+ else
+ {
+ buf->b_dev = st.st_dev;
+ buf->b_ino = st.st_ino;
+ }
+#endif
+
+#ifndef SHORT_FNAME
+ buf->b_shortname = FALSE;
+#endif
+
+ buf_name_changed(buf);
+ return OK;
+}
+
+/*
+ * Take care of what needs to be done when the name of buffer "buf" has
+ * changed.
+ */
+ void
+buf_name_changed(buf)
+ buf_T *buf;
+{
+ /*
+ * If the file name changed, also change the name of the swapfile
+ */
+ if (buf->b_ml.ml_mfp != NULL)
+ ml_setname(buf);
+
+ if (curwin->w_buffer == buf)
+ check_arg_idx(curwin); /* check file name for arg list */
+#ifdef FEAT_TITLE
+ maketitle(); /* set window title */
+#endif
+#ifdef FEAT_WINDOWS
+ status_redraw_all(); /* status lines need to be redrawn */
+#endif
+ fmarks_check_names(buf); /* check named file marks */
+ ml_timestamp(buf); /* reset timestamp */
+}
+
+/*
+ * set alternate file name for current window
+ *
+ * Used by do_one_cmd(), do_write() and do_ecmd().
+ * Return the buffer.
+ */
+ buf_T *
+setaltfname(ffname, sfname, lnum)
+ char_u *ffname;
+ char_u *sfname;
+ linenr_T lnum;
+{
+ buf_T *buf;
+
+ /* Create a buffer. 'buflisted' is not set if it's a new buffer */
+ buf = buflist_new(ffname, sfname, lnum, 0);
+ if (buf != NULL)
+ curwin->w_alt_fnum = buf->b_fnum;
+ return buf;
+}
+
+/*
+ * Get alternate file name for current window.
+ * Return NULL if there isn't any, and give error message if requested.
+ */
+ char_u *
+getaltfname(errmsg)
+ int errmsg; /* give error message */
+{
+ char_u *fname;
+ linenr_T dummy;
+
+ if (buflist_name_nr(0, &fname, &dummy) == FAIL)
+ {
+ if (errmsg)
+ EMSG(_(e_noalt));
+ return NULL;
+ }
+ return fname;
+}
+
+/*
+ * Add a file name to the buflist and return its number.
+ * Uses same flags as buflist_new(), except BLN_DUMMY.
+ *
+ * used by qf_init(), main() and doarglist()
+ */
+ int
+buflist_add(fname, flags)
+ char_u *fname;
+ int flags;
+{
+ buf_T *buf;
+
+ buf = buflist_new(fname, NULL, (linenr_T)0, flags);
+ if (buf != NULL)
+ return buf->b_fnum;
+ return 0;
+}
+
+#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
+/*
+ * Adjust slashes in file names. Called after 'shellslash' was set.
+ */
+ void
+buflist_slash_adjust()
+{
+ buf_T *bp;
+
+ for (bp = firstbuf; bp != NULL; bp = bp->b_next)
+ {
+ if (bp->b_ffname != NULL)
+ slash_adjust(bp->b_ffname);
+ if (bp->b_sfname != NULL)
+ slash_adjust(bp->b_sfname);
+ }
+}
+#endif
+
+/*
+ * Set alternate cursor position for current window.
+ * Also save the local window option values.
+ */
+ void
+buflist_altfpos()
+{
+ buflist_setfpos(curbuf, curwin, curwin->w_cursor.lnum,
+ curwin->w_cursor.col, TRUE);
+}
+
+/*
+ * Return TRUE if 'ffname' is not the same file as current file.
+ * Fname must have a full path (expanded by mch_FullName()).
+ */
+ int
+otherfile(ffname)
+ char_u *ffname;
+{
+ return otherfile_buf(curbuf, ffname
+#ifdef UNIX
+ , NULL
+#endif
+ );
+}
+
+ static int
+otherfile_buf(buf, ffname
+#ifdef UNIX
+ , stp
+#endif
+ )
+ buf_T *buf;
+ char_u *ffname;
+#ifdef UNIX
+ struct stat *stp;
+#endif
+{
+ /* no name is different */
+ if (ffname == NULL || *ffname == NUL || buf->b_ffname == NULL)
+ return TRUE;
+ if (fnamecmp(ffname, buf->b_ffname) == 0)
+ return FALSE;
+#ifdef UNIX
+ {
+ struct stat st;
+
+ /* If no struct stat given, get it now */
+ if (stp == NULL)
+ {
+ if (buf->b_dev < 0 || mch_stat((char *)ffname, &st) < 0)
+ st.st_dev = (dev_T)-1;
+ stp = &st;
+ }
+ /* Use dev/ino to check if the files are the same, even when the names
+ * are different (possible with links). Still need to compare the
+ * name above, for when the file doesn't exist yet.
+ * Problem: The dev/ino changes when a file is deleted (and created
+ * again) and remains the same when renamed/moved. We don't want to
+ * mch_stat() each buffer each time, that would be too slow. Get the
+ * dev/ino again when they appear to match, but not when they appear
+ * to be different: Could skip a buffer when it's actually the same
+ * file. */
+ if (buf_same_ino(buf, stp))
+ {
+ buf_setino(buf);
+ if (buf_same_ino(buf, stp))
+ return FALSE;
+ }
+ }
+#endif
+ return TRUE;
+}
+
+#if defined(UNIX) || defined(PROTO)
+/*
+ * Set inode and device number for a buffer.
+ * Must always be called when b_fname is changed!.
+ */
+ void
+buf_setino(buf)
+ buf_T *buf;
+{
+ struct stat st;
+
+ if (buf->b_fname != NULL && mch_stat((char *)buf->b_fname, &st) >= 0)
+ {
+ buf->b_dev = st.st_dev;
+ buf->b_ino = st.st_ino;
+ }
+ else
+ buf->b_dev = -1;
+}
+
+/*
+ * Return TRUE if dev/ino in buffer "buf" matches with "stp".
+ */
+ static int
+buf_same_ino(buf, stp)
+ buf_T *buf;
+ struct stat *stp;
+{
+ return (buf->b_dev >= 0
+ && stp->st_dev == buf->b_dev
+ && stp->st_ino == buf->b_ino);
+}
+#endif
+
+ void
+fileinfo(fullname, shorthelp, dont_truncate)
+ int fullname;
+ int shorthelp;
+ int dont_truncate;
+{
+ char_u *name;
+ int n;
+ char_u *p;
+ char_u *buffer;
+
+ buffer = alloc(IOSIZE);
+ if (buffer == NULL)
+ return;
+
+ if (fullname > 1) /* 2 CTRL-G: include buffer number */
+ {
+ sprintf((char *)buffer, "buf %d: ", curbuf->b_fnum);
+ p = buffer + STRLEN(buffer);
+ }
+ else
+ p = buffer;
+
+ *p++ = '"';
+ if (buf_spname(curbuf) != NULL)
+ STRCPY(p, buf_spname(curbuf));
+ else
+ {
+ if (!fullname && curbuf->b_fname != NULL)
+ name = curbuf->b_fname;
+ else
+ name = curbuf->b_ffname;
+ home_replace(shorthelp ? curbuf : NULL, name, p,
+ (int)(IOSIZE - (p - buffer)), TRUE);
+ }
+
+ sprintf((char *)buffer + STRLEN(buffer),
+ "\"%s%s%s%s%s%s",
+ curbufIsChanged() ? (shortmess(SHM_MOD)
+ ? " [+]" : _(" [Modified]")) : " ",
+ (curbuf->b_flags & BF_NOTEDITED)
+#ifdef FEAT_QUICKFIX
+ && !bt_dontwrite(curbuf)
+#endif
+ ? _("[Not edited]") : "",
+ (curbuf->b_flags & BF_NEW)
+#ifdef FEAT_QUICKFIX
+ && !bt_dontwrite(curbuf)
+#endif
+ ? _("[New file]") : "",
+ (curbuf->b_flags & BF_READERR) ? _("[Read errors]") : "",
+ curbuf->b_p_ro ? (shortmess(SHM_RO) ? "[RO]"
+ : _("[readonly]")) : "",
+ (curbufIsChanged() || (curbuf->b_flags & BF_WRITE_MASK)
+ || curbuf->b_p_ro) ?
+ " " : "");
+ /* With 32 bit longs and more than 21,474,836 lines multiplying by 100
+ * causes an overflow, thus for large numbers divide instead. */
+ if (curwin->w_cursor.lnum > 1000000L)
+ n = (int)(((long)curwin->w_cursor.lnum) /
+ ((long)curbuf->b_ml.ml_line_count / 100L));
+ else
+ n = (int)(((long)curwin->w_cursor.lnum * 100L) /
+ (long)curbuf->b_ml.ml_line_count);
+ if (curbuf->b_ml.ml_flags & ML_EMPTY)
+ {
+ STRCPY(buffer + STRLEN(buffer), _(no_lines_msg));
+ }
+#ifdef FEAT_CMDL_INFO
+ else if (p_ru)
+ {
+ /* Current line and column are already on the screen -- webb */
+ if (curbuf->b_ml.ml_line_count == 1)
+ sprintf((char *)buffer + STRLEN(buffer), _("1 line --%d%%--"), n);
+ else
+ sprintf((char *)buffer + STRLEN(buffer), _("%ld lines --%d%%--"),
+ (long)curbuf->b_ml.ml_line_count, n);
+ }
+#endif
+ else
+ {
+ sprintf((char *)buffer + STRLEN(buffer),
+ _("line %ld of %ld --%d%%-- col "),
+ (long)curwin->w_cursor.lnum,
+ (long)curbuf->b_ml.ml_line_count,
+ n);
+ validate_virtcol();
+ col_print(buffer + STRLEN(buffer),
+ (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1);
+ }
+
+ (void)append_arg_number(curwin, buffer, !shortmess(SHM_FILE), IOSIZE);
+
+ if (dont_truncate)
+ {
+ /* Temporarily set msg_scroll to avoid the message being truncated.
+ * First call msg_start() to get the message in the right place. */
+ msg_start();
+ n = msg_scroll;
+ msg_scroll = TRUE;
+ msg(buffer);
+ msg_scroll = n;
+ }
+ else
+ {
+ p = msg_trunc_attr(buffer, FALSE, 0);
+ if (restart_edit != 0 || (msg_scrolled && !need_wait_return))
+ {
+ /* Need to repeat the message after redrawing when:
+ * - When restart_edit is set (otherwise there will be a delay
+ * before redrawing).
+ * - When the screen was scrolled but there is no wait-return
+ * prompt. */
+ set_keep_msg(p);
+ keep_msg_attr = 0;
+ }
+ }
+
+ vim_free(buffer);
+}
+
+ void
+col_print(buf, col, vcol)
+ char_u *buf;
+ int col;
+ int vcol;
+{
+ if (col == vcol)
+ sprintf((char *)buf, "%d", col);
+ else
+ sprintf((char *)buf, "%d-%d", col, vcol);
+}
+
+#if defined(FEAT_TITLE) || defined(PROTO)
+/*
+ * put file name in title bar of window and in icon title
+ */
+
+static char_u *lasttitle = NULL;
+static char_u *lasticon = NULL;
+
+ void
+maketitle()
+{
+ char_u *p;
+ char_u *t_str = NULL;
+ char_u *i_name;
+ char_u *i_str = NULL;
+ int maxlen = 0;
+ int len;
+ int mustset;
+ char_u buf[IOSIZE];
+ int off;
+
+ if (!redrawing())
+ {
+ /* Postpone updating the title when 'lazyredraw' is set. */
+ need_maketitle = TRUE;
+ return;
+ }
+
+ need_maketitle = FALSE;
+ if (!p_title && !p_icon)
+ return;
+
+ if (p_title)
+ {
+ if (p_titlelen > 0)
+ {
+ maxlen = p_titlelen * Columns / 100;
+ if (maxlen < 10)
+ maxlen = 10;
+ }
+
+ t_str = buf;
+ if (*p_titlestring != NUL)
+ {
+#ifdef FEAT_STL_OPT
+ if (stl_syntax & STL_IN_TITLE)
+ build_stl_str_hl(curwin, t_str, sizeof(buf),
+ p_titlestring, 0, maxlen, NULL);
+ else
+#endif
+ t_str = p_titlestring;
+ }
+ else
+ {
+ /* format: "fname + (path) (1 of 2) - VIM" */
+
+ if (curbuf->b_fname == NULL)
+ STRCPY(buf, _("[No file]"));
+ else
+ {
+ p = transstr(gettail(curbuf->b_fname));
+ STRNCPY(buf, p, IOSIZE - 100);
+ vim_free(p);
+ buf[IOSIZE - 100] = NUL; /* in case it was too long */
+ }
+
+ switch (bufIsChanged(curbuf)
+ + (curbuf->b_p_ro * 2)
+ + (!curbuf->b_p_ma * 4))
+ {
+ case 1: STRCAT(buf, " +"); break;
+ case 2: STRCAT(buf, " ="); break;
+ case 3: STRCAT(buf, " =+"); break;
+ case 4:
+ case 6: STRCAT(buf, " -"); break;
+ case 5:
+ case 7: STRCAT(buf, " -+"); break;
+ }
+
+ if (curbuf->b_fname != NULL)
+ {
+ /* Get path of file, replace home dir with ~ */
+ off = (int)STRLEN(buf);
+ buf[off++] = ' ';
+ buf[off++] = '(';
+ home_replace(curbuf, curbuf->b_ffname,
+ buf + off, IOSIZE - off, TRUE);
+#ifdef BACKSLASH_IN_FILENAME
+ /* avoid "c:/name" to be reduced to "c" */
+ if (isalpha(buf[off]) && buf[off + 1] == ':')
+ off += 2;
+#endif
+ /* remove the file name */
+ p = gettail(buf + off);
+ if (p == buf + off)
+ {
+ /* must be a help buffer */
+ STRCPY(buf + off, _("help"));
+ }
+ else
+ {
+ while (p > buf + off + 1 && vim_ispathsep(p[-1]))
+ --p;
+#ifdef VMS
+ /* path separator is part of the path */
+ ++p;
+#endif
+ *p = NUL;
+ }
+ /* translate unprintable chars */
+ p = transstr(buf + off);
+ STRNCPY(buf + off, p, IOSIZE - off);
+ vim_free(p);
+ buf[IOSIZE - 1] = NUL; /* in case it was too long */
+ STRCAT(buf, ")");
+ }
+
+ append_arg_number(curwin, buf, FALSE, IOSIZE);
+
+#if defined(FEAT_CLIENTSERVER)
+ if (serverName != NULL)
+ {
+ STRCAT(buf, " - ");
+ STRCAT(buf, serverName);
+ }
+ else
+#endif
+ STRCAT(buf, " - VIM");
+
+ if (maxlen > 0)
+ {
+ /* make it shorter by removing a bit in the middle */
+ len = vim_strsize(buf);
+ if (len > maxlen)
+ trunc_string(buf, buf, maxlen);
+ }
+ }
+ }
+ mustset = ti_change(t_str, &lasttitle);
+
+ if (p_icon)
+ {
+ i_str = buf;
+ if (*p_iconstring != NUL)
+ {
+#ifdef FEAT_STL_OPT
+ if (stl_syntax & STL_IN_ICON)
+ build_stl_str_hl(curwin, i_str, sizeof(buf),
+ p_iconstring, 0, 0, NULL);
+ else
+#endif
+ i_str = p_iconstring;
+ }
+ else
+ {
+ if (buf_spname(curbuf) != NULL)
+ i_name = (char_u *)buf_spname(curbuf);
+ else /* use file name only in icon */
+ i_name = gettail(curbuf->b_ffname);
+ *i_str = NUL;
+ /* Truncate name at 100 bytes. */
+ len = STRLEN(i_name);
+ if (len > 100)
+ {
+ len -= 100;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ len += (*mb_tail_off)(i_name, i_name + len) + 1;
+#endif
+ i_name += len;
+ }
+ STRCPY(i_str, i_name);
+ trans_characters(i_str, IOSIZE);
+ }
+ }
+
+ mustset |= ti_change(i_str, &lasticon);
+
+ if (mustset)
+ resettitle();
+}
+
+/*
+ * Used for title and icon: Check if "str" differs from "*last". Set "*last"
+ * from "str" if it does.
+ * Return TRUE when "*last" changed.
+ */
+ static int
+ti_change(str, last)
+ char_u *str;
+ char_u **last;
+{
+ if ((str == NULL) != (*last == NULL)
+ || (str != NULL && *last != NULL && STRCMP(str, *last) != 0))
+ {
+ vim_free(*last);
+ if (str == NULL)
+ *last = NULL;
+ else
+ *last = vim_strsave(str);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Put current window title back (used after calling a shell)
+ */
+ void
+resettitle()
+{
+ mch_settitle(lasttitle, lasticon);
+}
+#endif /* FEAT_TITLE */
+
+#if defined(FEAT_STL_OPT) || defined(PROTO)
+/*
+ * Build a string from the status line items in fmt.
+ * Return length of string in screen cells.
+ *
+ * Items are drawn interspersed with the text that surrounds it
+ * Specials: %-<wid>(xxx%) => group, %= => middle marker, %< => truncation
+ * Item: %-<minwid>.<maxwid><itemch> All but <itemch> are optional
+ *
+ * If maxwidth is not zero, the string will be filled at any middle marker
+ * or truncated if too long, fillchar is used for all whitespace.
+ */
+ int
+build_stl_str_hl(wp, out, outlen, fmt, fillchar, maxwidth, hl)
+ win_T *wp;
+ char_u *out; /* buffer to write into */
+ size_t outlen; /* length of out[] */
+ char_u *fmt;
+ int fillchar;
+ int maxwidth;
+ struct stl_hlrec *hl;
+{
+ char_u *p;
+ char_u *s;
+ char_u *t;
+ char_u *linecont;
+#ifdef FEAT_EVAL
+ win_T *o_curwin;
+ buf_T *o_curbuf;
+#endif
+ int empty_line;
+ colnr_T virtcol;
+ long l;
+ long n;
+ int prevchar_isflag;
+ int prevchar_isitem;
+ int itemisflag;
+ int fillable;
+ char_u *str;
+ long num;
+ int width;
+ int itemcnt;
+ int curitem;
+ int groupitem[STL_MAX_ITEM];
+ int groupdepth;
+ struct stl_item
+ {
+ char_u *start;
+ int minwid;
+ int maxwid;
+ enum
+ {
+ Normal,
+ Empty,
+ Group,
+ Middle,
+ Highlight,
+ Trunc
+ } type;
+ } item[STL_MAX_ITEM];
+ int minwid;
+ int maxwid;
+ int zeropad;
+ char_u base;
+ char_u opt;
+#define TMPLEN 70
+ char_u tmp[TMPLEN];
+
+ if (fillchar == 0)
+ fillchar = ' ';
+ /*
+ * Get line & check if empty (cursorpos will show "0-1").
+ * If inversion is possible we use it. Else '=' characters are used.
+ */
+ linecont = ml_get_buf(wp->w_buffer, wp->w_cursor.lnum, FALSE);
+ empty_line = (*linecont == NUL);
+
+ groupdepth = 0;
+ p = out;
+ curitem = 0;
+ prevchar_isflag = TRUE;
+ prevchar_isitem = FALSE;
+ for (s = fmt; *s;)
+ {
+ if (*s != NUL && *s != '%')
+ prevchar_isflag = prevchar_isitem = FALSE;
+
+ /*
+ * Handle up to the next '%' or the end.
+ */
+ while (*s != NUL && *s != '%' && p + 1 < out + outlen)
+ *p++ = *s++;
+ if (*s == NUL || p + 1 >= out + outlen)
+ break;
+
+ /*
+ * Handle one '%' item.
+ */
+ s++;
+ if (*s == '%')
+ {
+ if (p + 1 >= out + outlen)
+ break;
+ *p++ = *s++;
+ prevchar_isflag = prevchar_isitem = FALSE;
+ continue;
+ }
+ if (*s == STL_MIDDLEMARK)
+ {
+ s++;
+ if (groupdepth > 0)
+ continue;
+ item[curitem].type = Middle;
+ item[curitem++].start = p;
+ continue;
+ }
+ if (*s == STL_TRUNCMARK)
+ {
+ s++;
+ item[curitem].type = Trunc;
+ item[curitem++].start = p;
+ continue;
+ }
+ if (*s == ')')
+ {
+ s++;
+ if (groupdepth < 1)
+ continue;
+ groupdepth--;
+
+ t = item[groupitem[groupdepth]].start;
+ *p = NUL;
+ l = vim_strsize(t);
+ if (curitem > groupitem[groupdepth] + 1
+ && item[groupitem[groupdepth]].minwid == 0)
+ {
+ /* remove group if all items are empty */
+ for (n = groupitem[groupdepth] + 1; n < curitem; n++)
+ if (item[n].type == Normal)
+ break;
+ if (n == curitem)
+ {
+ p = t;
+ l = 0;
+ }
+ }
+ if (l > item[groupitem[groupdepth]].maxwid)
+ {
+ /* truncate, remove n bytes of text at the start */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ /* Find the first character that should be included. */
+ n = 0;
+ while (l >= item[groupitem[groupdepth]].maxwid)
+ {
+ l -= ptr2cells(t + n);
+ n += (*mb_ptr2len_check)(t + n);
+ }
+ }
+ else
+#endif
+ n = (p - t) - item[groupitem[groupdepth]].maxwid + 1;
+
+ *t = '<';
+ mch_memmove(t + 1, t + n, p - (t + n));
+ p = p - n + 1;
+#ifdef FEAT_MBYTE
+ /* Fill up space left over by half a double-wide char. */
+ while (++l < item[groupitem[groupdepth]].minwid)
+ *p++ = fillchar;
+#endif
+
+ /* correct the start of the items for the truncation */
+ for (l = groupitem[groupdepth] + 1; l < curitem; l++)
+ {
+ item[l].start -= n;
+ if (item[l].start < t)
+ item[l].start = t;
+ }
+ }
+ else if (abs(item[groupitem[groupdepth]].minwid) > l)
+ {
+ /* fill */
+ n = item[groupitem[groupdepth]].minwid;
+ if (n < 0)
+ {
+ /* fill by appending characters */
+ n = 0 - n;
+ while (l++ < n && p + 1 < out + outlen)
+ *p++ = fillchar;
+ }
+ else
+ {
+ /* fill by inserting characters */
+ mch_memmove(t + n - l, t, p - t);
+ l = n - l;
+ if (p + l >= out + outlen)
+ l = (out + outlen) - p - 1;
+ p += l;
+ for (n = groupitem[groupdepth] + 1; n < curitem; n++)
+ item[n].start += l;
+ for ( ; l > 0; l--)
+ *t++ = fillchar;
+ }
+ }
+ continue;
+ }
+ minwid = 0;
+ maxwid = 9999;
+ zeropad = FALSE;
+ l = 1;
+ if (*s == '0')
+ {
+ s++;
+ zeropad = TRUE;
+ }
+ if (*s == '-')
+ {
+ s++;
+ l = -1;
+ }
+ if (VIM_ISDIGIT(*s))
+ {
+ minwid = (int)getdigits(&s);
+ if (minwid < 0) /* overflow */
+ minwid = 0;
+ }
+ if (*s == STL_HIGHLIGHT)
+ {
+ item[curitem].type = Highlight;
+ item[curitem].start = p;
+ item[curitem].minwid = minwid > 9 ? 1 : minwid;
+ s++;
+ curitem++;
+ continue;
+ }
+ if (*s == '.')
+ {
+ s++;
+ if (VIM_ISDIGIT(*s))
+ {
+ maxwid = (int)getdigits(&s);
+ if (maxwid <= 0) /* overflow */
+ maxwid = 50;
+ }
+ }
+ minwid = (minwid > 50 ? 50 : minwid) * l;
+ if (*s == '(')
+ {
+ groupitem[groupdepth++] = curitem;
+ item[curitem].type = Group;
+ item[curitem].start = p;
+ item[curitem].minwid = minwid;
+ item[curitem].maxwid = maxwid;
+ s++;
+ curitem++;
+ continue;
+ }
+ if (vim_strchr(STL_ALL, *s) == NULL)
+ {
+ s++;
+ continue;
+ }
+ opt = *s++;
+
+ /* OK - now for the real work */
+ base = 'D';
+ itemisflag = FALSE;
+ fillable = TRUE;
+ num = -1;
+ str = NULL;
+ switch (opt)
+ {
+ case STL_FILEPATH:
+ case STL_FULLPATH:
+ case STL_FILENAME:
+ fillable = FALSE; /* don't change ' ' to fillchar */
+ if (buf_spname(wp->w_buffer) != NULL)
+ STRCPY(NameBuff, buf_spname(wp->w_buffer));
+ else
+ {
+ t = (opt == STL_FULLPATH) ? wp->w_buffer->b_ffname
+ : wp->w_buffer->b_fname;
+ home_replace(wp->w_buffer, t, NameBuff, MAXPATHL, TRUE);
+ }
+ trans_characters(NameBuff, MAXPATHL);
+ if (opt != STL_FILENAME)
+ str = NameBuff;
+ else
+ str = gettail(NameBuff);
+ break;
+
+ case STL_VIM_EXPR: /* '{' */
+ itemisflag = TRUE;
+ t = p;
+ while (*s != '}' && *s != NUL && p + 1 < out + outlen)
+ *p++ = *s++;
+ if (*s != '}') /* missing '}' or out of space */
+ break;
+ s++;
+ *p = 0;
+ p = t;
+
+#ifdef FEAT_EVAL
+ sprintf((char *)tmp, "%d", curbuf->b_fnum);
+ set_internal_string_var((char_u *)"actual_curbuf", tmp);
+
+ o_curbuf = curbuf;
+ o_curwin = curwin;
+ curwin = wp;
+ curbuf = wp->w_buffer;
+
+ str = eval_to_string_safe(p, &t);
+
+ curwin = o_curwin;
+ curbuf = o_curbuf;
+ do_unlet((char_u *)"g:actual_curbuf");
+
+ if (str != NULL && *str != 0)
+ {
+ if (*skipdigits(str) == NUL)
+ {
+ num = atoi((char *)str);
+ vim_free(str);
+ str = NULL;
+ itemisflag = FALSE;
+ }
+ }
+#endif
+ break;
+
+ case STL_LINE:
+ num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY)
+ ? 0L : (long)(wp->w_cursor.lnum);
+ break;
+
+ case STL_NUMLINES:
+ num = wp->w_buffer->b_ml.ml_line_count;
+ break;
+
+ case STL_COLUMN:
+ num = !(State & INSERT) && empty_line
+ ? 0 : (int)wp->w_cursor.col + 1;
+ break;
+
+ case STL_VIRTCOL:
+ case STL_VIRTCOL_ALT:
+ /* In list mode virtcol needs to be recomputed */
+ virtcol = wp->w_virtcol;
+ if (wp->w_p_list && lcs_tab1 == NUL)
+ {
+ wp->w_p_list = FALSE;
+ getvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL);
+ wp->w_p_list = TRUE;
+ }
+ ++virtcol;
+ /* Don't display %V if it's the same as %c. */
+ if (opt == STL_VIRTCOL_ALT
+ && (virtcol == (colnr_T)(!(State & INSERT) && empty_line
+ ? 0 : (int)wp->w_cursor.col + 1)))
+ break;
+ num = (long)virtcol;
+ break;
+
+ case STL_PERCENTAGE:
+ num = (int)(((long)wp->w_cursor.lnum * 100L) /
+ (long)wp->w_buffer->b_ml.ml_line_count);
+ break;
+
+ case STL_ALTPERCENT:
+ str = tmp;
+ get_rel_pos(wp, str);
+ break;
+
+ case STL_ARGLISTSTAT:
+ fillable = FALSE;
+ tmp[0] = 0;
+ if (append_arg_number(wp, tmp, FALSE, (int)sizeof(tmp)))
+ str = tmp;
+ break;
+
+ case STL_KEYMAP:
+ fillable = FALSE;
+ if (get_keymap_str(wp, tmp, TMPLEN))
+ str = tmp;
+ break;
+ case STL_PAGENUM:
+#ifdef FEAT_PRINTER
+ num = get_printer_page_num();
+#else
+ num = 0;
+#endif
+ break;
+
+ case STL_BUFNO:
+ num = wp->w_buffer->b_fnum;
+ break;
+
+ case STL_OFFSET_X:
+ base = 'X';
+ case STL_OFFSET:
+#ifdef FEAT_BYTEOFF
+ l = ml_find_line_or_offset(wp->w_buffer, wp->w_cursor.lnum, NULL);
+ num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) || l < 0 ?
+ 0L : l + 1 + (!(State & INSERT) && empty_line ?
+ 0 : (int)wp->w_cursor.col);
+#endif
+ break;
+
+ case STL_BYTEVAL_X:
+ base = 'X';
+ case STL_BYTEVAL:
+ if (((State & INSERT) && wp == curwin) || empty_line)
+ num = 0;
+ else
+ {
+#ifdef FEAT_MBYTE
+ num = (*mb_ptr2char)(linecont + wp->w_cursor.col);
+#else
+ num = linecont[wp->w_cursor.col];
+#endif
+ }
+ if (num == NL)
+ num = 0;
+ else if (num == CAR && get_fileformat(wp->w_buffer) == EOL_MAC)
+ num = NL;
+ break;
+
+ case STL_ROFLAG:
+ case STL_ROFLAG_ALT:
+ itemisflag = TRUE;
+ if (wp->w_buffer->b_p_ro)
+ str = (char_u *)((opt == STL_ROFLAG_ALT) ? ",RO" : "[RO]");
+ break;
+
+ case STL_HELPFLAG:
+ case STL_HELPFLAG_ALT:
+ itemisflag = TRUE;
+ if (wp->w_buffer->b_help)
+ str = (char_u *)((opt == STL_HELPFLAG_ALT) ? ",HLP"
+ : _("[help]"));
+ break;
+
+#ifdef FEAT_AUTOCMD
+ case STL_FILETYPE:
+ if (*wp->w_buffer->b_p_ft != NUL
+ && STRLEN(wp->w_buffer->b_p_ft) < TMPLEN - 3)
+ {
+ sprintf((char *)tmp, "[%s]", wp->w_buffer->b_p_ft);
+ str = tmp;
+ }
+ break;
+
+ case STL_FILETYPE_ALT:
+ itemisflag = TRUE;
+ if (*wp->w_buffer->b_p_ft != NUL
+ && STRLEN(wp->w_buffer->b_p_ft) < TMPLEN - 2)
+ {
+ sprintf((char *)tmp, ",%s", wp->w_buffer->b_p_ft);
+ for (t = tmp; *t != 0; t++)
+ *t = TOUPPER_LOC(*t);
+ str = tmp;
+ }
+ break;
+#endif
+
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ case STL_PREVIEWFLAG:
+ case STL_PREVIEWFLAG_ALT:
+ itemisflag = TRUE;
+ if (wp->w_p_pvw)
+ str = (char_u *)((opt == STL_PREVIEWFLAG_ALT) ? ",PRV"
+ : _("[Preview]"));
+ break;
+#endif
+
+ case STL_MODIFIED:
+ case STL_MODIFIED_ALT:
+ itemisflag = TRUE;
+ switch ((opt == STL_MODIFIED_ALT)
+ + bufIsChanged(wp->w_buffer) * 2
+ + (!wp->w_buffer->b_p_ma) * 4)
+ {
+ case 2: str = (char_u *)"[+]"; break;
+ case 3: str = (char_u *)",+"; break;
+ case 4: str = (char_u *)"[-]"; break;
+ case 5: str = (char_u *)",-"; break;
+ case 6: str = (char_u *)"[+-]"; break;
+ case 7: str = (char_u *)",+-"; break;
+ }
+ break;
+ }
+
+ item[curitem].start = p;
+ item[curitem].type = Normal;
+ if (str != NULL && *str)
+ {
+ t = str;
+ if (itemisflag)
+ {
+ if ((t[0] && t[1])
+ && ((!prevchar_isitem && *t == ',')
+ || (prevchar_isflag && *t == ' ')))
+ t++;
+ prevchar_isflag = TRUE;
+ }
+ l = vim_strsize(t);
+ if (l > 0)
+ prevchar_isitem = TRUE;
+ if (l > maxwid)
+ {
+ while (l >= maxwid)
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ l -= ptr2cells(t);
+ t += (*mb_ptr2len_check)(t);
+ }
+ else
+#endif
+ l -= byte2cells(*t++);
+ if (p + 1 >= out + outlen)
+ break;
+ *p++ = '<';
+ }
+ if (minwid > 0)
+ {
+ for (; l < minwid && p + 1 < out + outlen; l++)
+ {
+ /* Don't put a "-" in front of a digit. */
+ if (l + 1 == minwid && fillchar == '-' && VIM_ISDIGIT(*t))
+ *p++ = ' ';
+ else
+ *p++ = fillchar;
+ }
+ minwid = 0;
+ }
+ else
+ minwid *= -1;
+ while (*t && p + 1 < out + outlen)
+ {
+ *p++ = *t++;
+ /* Change a space by fillchar, unless fillchar is '-' and a
+ * digit follows. */
+ if (fillable && p[-1] == ' '
+ && (!VIM_ISDIGIT(*t) || fillchar != '-'))
+ p[-1] = fillchar;
+ }
+ for (; l < minwid && p + 1 < out + outlen; l++)
+ *p++ = fillchar;
+ }
+ else if (num >= 0)
+ {
+ int nbase = (base == 'D' ? 10 : (base == 'O' ? 8 : 16));
+ char_u nstr[20];
+
+ if (p + 20 >= out + outlen)
+ break; /* not sufficient space */
+ prevchar_isitem = TRUE;
+ t = nstr;
+ if (opt == STL_VIRTCOL_ALT)
+ {
+ *t++ = '-';
+ minwid--;
+ }
+ *t++ = '%';
+ if (zeropad)
+ *t++ = '0';
+ *t++ = '*';
+ *t++ = nbase == 16 ? base : (nbase == 8 ? 'o' : 'd');
+ *t = 0;
+
+ for (n = num, l = 1; n >= nbase; n /= nbase)
+ l++;
+ if (opt == STL_VIRTCOL_ALT)
+ l++;
+ if (l > maxwid)
+ {
+ l += 2;
+ n = l - maxwid;
+ while (l-- > maxwid)
+ num /= nbase;
+ *t++ = '>';
+ *t++ = '%';
+ *t = t[-3];
+ *++t = 0;
+ sprintf((char *)p, (char *)nstr, 0, num, n);
+ }
+ else
+ sprintf((char *)p, (char *)nstr, minwid, num);
+ p += STRLEN(p);
+ }
+ else
+ item[curitem].type = Empty;
+
+ if (opt == STL_VIM_EXPR)
+ vim_free(str);
+
+ if (num >= 0 || (!itemisflag && str && *str))
+ prevchar_isflag = FALSE; /* Item not NULL, but not a flag */
+ curitem++;
+ }
+ *p = NUL;
+ itemcnt = curitem;
+
+ width = vim_strsize(out);
+ if (maxwidth > 0 && width > maxwidth)
+ {
+ /* Result is too long, must trunctate somewhere. */
+ l = 0;
+ if (itemcnt == 0)
+ s = out;
+ else
+ {
+ for ( ; l < itemcnt; l++)
+ if (item[l].type == Trunc)
+ {
+ /* Truncate at %< item. */
+ s = item[l].start;
+ break;
+ }
+ if (l == itemcnt)
+ {
+ /* No %< item, truncate first item. */
+ s = item[0].start;
+ l = 0;
+ }
+ }
+
+ if (width - vim_strsize(s) >= maxwidth)
+ {
+ /* Truncation mark is beyond max length */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ s = out;
+ width = 0;
+ for (;;)
+ {
+ width += ptr2cells(s);
+ if (width >= maxwidth)
+ break;
+ s += (*mb_ptr2len_check)(s);
+ }
+ /* Fill up for half a double-wide character. */
+ while (++width < maxwidth)
+ *s++ = fillchar;
+ }
+ else
+#endif
+ s = out + maxwidth - 1;
+ for (l = 0; l < itemcnt; l++)
+ if (item[l].start > s)
+ break;
+ itemcnt = l;
+ *s++ = '>';
+ *s = 0;
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ n = 0;
+ while (width >= maxwidth)
+ {
+ width -= ptr2cells(s + n);
+ n += (*mb_ptr2len_check)(s + n);
+ }
+ }
+ else
+#endif
+ n = width - maxwidth + 1;
+ p = s + n;
+ mch_memmove(s + 1, p, STRLEN(p) + 1);
+ *s = '<';
+
+ /* Fill up for half a double-wide character. */
+ while (++width < maxwidth)
+ {
+ s = s + STRLEN(s);
+ *s++ = fillchar;
+ *s = NUL;
+ }
+
+ --n; /* count the '<' */
+ for (; l < itemcnt; l++)
+ {
+ if (item[l].start - n >= s)
+ item[l].start -= n;
+ else
+ item[l].start = s;
+ }
+ }
+ width = maxwidth;
+ }
+ else if (width < maxwidth && STRLEN(out) + maxwidth - width + 1 < outlen)
+ {
+ /* Apply STL_MIDDLE if any */
+ for (l = 0; l < itemcnt; l++)
+ if (item[l].type == Middle)
+ break;
+ if (l < itemcnt)
+ {
+ p = item[l].start + maxwidth - width;
+ mch_memmove(p, item[l].start, STRLEN(item[l].start) + 1);
+ for (s = item[l].start; s < p; s++)
+ *s = fillchar;
+ for (l++; l < itemcnt; l++)
+ item[l].start += maxwidth - width;
+ width = maxwidth;
+ }
+ }
+
+ if (hl != NULL)
+ {
+ for (l = 0; l < itemcnt; l++)
+ {
+ if (item[l].type == Highlight)
+ {
+ hl->start = item[l].start;
+ hl->userhl = item[l].minwid;
+ hl++;
+ }
+ }
+ hl->start = NULL;
+ hl->userhl = 0;
+ }
+
+ return width;
+}
+#endif /* FEAT_STL_OPT */
+
+#if defined(FEAT_STL_OPT) || defined(FEAT_CMDL_INFO) || defined(PROTO)
+/*
+ * Get relative cursor position in window, in the form 99%, using "Top", "Bot"
+ * or "All" when appropriate.
+ */
+ void
+get_rel_pos(wp, str)
+ win_T *wp;
+ char_u *str;
+{
+ long above; /* number of lines above window */
+ long below; /* number of lines below window */
+
+ above = wp->w_topline - 1;
+#ifdef FEAT_DIFF
+ above += diff_check_fill(wp, wp->w_topline) - wp->w_topfill;
+#endif
+ below = wp->w_buffer->b_ml.ml_line_count - wp->w_botline + 1;
+ if (below <= 0)
+ STRCPY(str, above == 0 ? _("All") : _("Bot"));
+ else if (above <= 0)
+ STRCPY(str, _("Top"));
+ else
+ sprintf((char *)str, "%2d%%", above > 1000000L
+ ? (int)(above / ((above + below) / 100L))
+ : (int)(above * 100L / (above + below)));
+}
+#endif
+
+/*
+ * Append (file 2 of 8) to 'buf', if editing more than one file.
+ * Return TRUE if it was appended.
+ */
+ int
+append_arg_number(wp, buf, add_file, maxlen)
+ win_T *wp;
+ char_u *buf;
+ int add_file; /* Add "file" before the arg number */
+ int maxlen; /* maximum nr of chars in buf or zero*/
+{
+ char_u *p;
+
+ if (ARGCOUNT <= 1) /* nothing to do */
+ return FALSE;
+
+ p = buf + STRLEN(buf); /* go to the end of the buffer */
+ if (maxlen && p - buf + 35 >= maxlen) /* getting too long */
+ return FALSE;
+ *p++ = ' ';
+ *p++ = '(';
+ if (add_file)
+ {
+ STRCPY(p, "file ");
+ p += 5;
+ }
+ sprintf((char *)p, wp->w_arg_idx_invalid ? "(%d) of %d)"
+ : "%d of %d)", wp->w_arg_idx + 1, ARGCOUNT);
+ return TRUE;
+}
+
+/*
+ * If fname is not a full path, make it a full path.
+ * Returns pointer to allocated memory (NULL for failure).
+ */
+ char_u *
+fix_fname(fname)
+ char_u *fname;
+{
+ /*
+ * Force expanding the path always for Unix, because symbolic links may
+ * mess up the full path name, even though it starts with a '/'.
+ * Also expand when there is ".." in the file name, try to remove it,
+ * because "c:/src/../README" is equal to "c:/README".
+ * For MS-Windows also expand names like "longna~1" to "longname".
+ */
+#ifdef UNIX
+ return FullName_save(fname, TRUE);
+#else
+ if (!vim_isAbsName(fname) || strstr((char *)fname, "..") != NULL
+#if defined(MSWIN) || defined(DJGPP)
+ || vim_strchr(fname, '~') != NULL
+#endif
+ )
+ return FullName_save(fname, FALSE);
+
+ fname = vim_strsave(fname);
+
+#ifdef USE_FNAME_CASE
+# ifdef USE_LONG_FNAME
+ if (USE_LONG_FNAME)
+# endif
+ {
+ if (fname != NULL)
+ fname_case(fname, 0); /* set correct case for file name */
+ }
+#endif
+
+ return fname;
+#endif
+}
+
+/*
+ * Make "ffname" a full file name, set "sfname" to "ffname" if not NULL.
+ * "ffname" becomes a pointer to allocated memory (or NULL).
+ */
+/*ARGSUSED*/
+ void
+fname_expand(buf, ffname, sfname)
+ buf_T *buf;
+ char_u **ffname;
+ char_u **sfname;
+{
+ if (*ffname == NULL) /* if no file name given, nothing to do */
+ return;
+ if (*sfname == NULL) /* if no short file name given, use ffname */
+ *sfname = *ffname;
+ *ffname = fix_fname(*ffname); /* expand to full path */
+
+#ifdef FEAT_SHORTCUT
+ if (!buf->b_p_bin)
+ {
+ char_u *rfname = NULL;
+
+ /* If the file name is a shortcut file, use the file it links to. */
+ rfname = mch_resolve_shortcut(*ffname);
+ if (rfname)
+ {
+ vim_free(*ffname);
+ *ffname = rfname;
+ *sfname = rfname;
+ }
+ }
+#endif
+}
+
+/*
+ * Get the file name for an argument list entry.
+ */
+ char_u *
+alist_name(aep)
+ aentry_T *aep;
+{
+ buf_T *bp;
+
+ /* Use the name from the associated buffer if it exists. */
+ bp = buflist_findnr(aep->ae_fnum);
+ if (bp == NULL)
+ return aep->ae_fname;
+ return bp->b_fname;
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * do_arg_all(): Open up to 'count' windows, one for each argument.
+ */
+ void
+do_arg_all(count, forceit)
+ int count;
+ int forceit; /* hide buffers in current windows */
+{
+ int i;
+ win_T *wp, *wpnext;
+ char_u *opened; /* array of flags for which args are open */
+ int opened_len; /* lenght of opened[] */
+ int use_firstwin = FALSE; /* use first window for arglist */
+ int split_ret = OK;
+ int p_ea_save;
+ alist_T *alist; /* argument list to be used */
+ buf_T *buf;
+
+ if (ARGCOUNT <= 0)
+ {
+ /* Don't give an error message. We don't want it when the ":all"
+ * command is in the .vimrc. */
+ return;
+ }
+ setpcmark();
+
+ opened_len = ARGCOUNT;
+ opened = alloc_clear((unsigned)opened_len);
+ if (opened == NULL)
+ return;
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+
+ /*
+ * Try closing all windows that are not in the argument list.
+ * Also close windows that are not full width;
+ * When 'hidden' or "forceit" set the buffer becomes hidden.
+ * Windows that have a changed buffer and can't be hidden won't be closed.
+ */
+ for (wp = firstwin; wp != NULL; wp = wpnext)
+ {
+ wpnext = wp->w_next;
+ buf = wp->w_buffer;
+ if (buf->b_ffname == NULL
+ || buf->b_nwindows > 1
+#ifdef FEAT_VERTSPLIT
+ || wp->w_width != Columns
+#endif
+ )
+ i = ARGCOUNT;
+ else
+ {
+ /* check if the buffer in this window is in the arglist */
+ for (i = 0; i < ARGCOUNT; ++i)
+ {
+ if (ARGLIST[i].ae_fnum == buf->b_fnum
+ || fullpathcmp(alist_name(&ARGLIST[i]),
+ buf->b_ffname, TRUE) & FPC_SAME)
+ {
+ if (i < opened_len)
+ opened[i] = TRUE;
+ if (wp->w_alist != curwin->w_alist)
+ {
+ /* Use the current argument list for all windows
+ * containing a file from it. */
+ alist_unlink(wp->w_alist);
+ wp->w_alist = curwin->w_alist;
+ ++wp->w_alist->al_refcount;
+ }
+ break;
+ }
+ }
+ }
+ wp->w_arg_idx = i;
+
+ if (i == ARGCOUNT) /* close this window */
+ {
+ if (P_HID(buf) || forceit || buf->b_nwindows > 1
+ || !bufIsChanged(buf))
+ {
+ /* If the buffer was changed, and we would like to hide it,
+ * try autowriting. */
+ if (!P_HID(buf) && buf->b_nwindows <= 1 && bufIsChanged(buf))
+ {
+ (void)autowrite(buf, FALSE);
+#ifdef FEAT_AUTOCMD
+ /* check if autocommands removed the window */
+ if (!win_valid(wp) || !buf_valid(buf))
+ {
+ wpnext = firstwin; /* start all over... */
+ continue;
+ }
+#endif
+ }
+#ifdef FEAT_WINDOWS
+ if (firstwin == lastwin) /* can't close last window */
+#endif
+ use_firstwin = TRUE;
+#ifdef FEAT_WINDOWS
+ else
+ {
+ win_close(wp, !P_HID(buf) && !bufIsChanged(buf));
+# ifdef FEAT_AUTOCMD
+ /* check if autocommands removed the next window */
+ if (!win_valid(wpnext))
+ wpnext = firstwin; /* start all over... */
+# endif
+ }
+#endif
+ }
+ }
+ }
+
+ /*
+ * Open a window for files in the argument list that don't have one.
+ * ARGCOUNT may change while doing this, because of autocommands.
+ */
+ if (count > ARGCOUNT || count <= 0)
+ count = ARGCOUNT;
+
+ /* Autocommands may do anything to the argument list. Make sure it's not
+ * freed while we are working here by "locking" it. We still have to
+ * watch out for its size to be changed. */
+ alist = curwin->w_alist;
+ ++alist->al_refcount;
+
+#ifdef FEAT_AUTOCMD
+ /* Don't execute Win/Buf Enter/Leave autocommands here. */
+ ++autocmd_no_enter;
+ ++autocmd_no_leave;
+#endif
+ win_enter(lastwin, FALSE);
+ for (i = 0; i < count && i < alist->al_ga.ga_len && !got_int; ++i)
+ {
+ if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1)
+ arg_had_last = TRUE;
+ if (i < opened_len && opened[i])
+ {
+ /* Move the already present window to below the current window */
+ if (curwin->w_arg_idx != i)
+ {
+ for (wpnext = firstwin; wpnext != NULL; wpnext = wpnext->w_next)
+ {
+ if (wpnext->w_arg_idx == i)
+ {
+ win_move_after(wpnext, curwin);
+ break;
+ }
+ }
+ }
+ }
+ else if (split_ret == OK)
+ {
+ if (!use_firstwin) /* split current window */
+ {
+ p_ea_save = p_ea;
+ p_ea = TRUE; /* use space from all windows */
+ split_ret = win_split(0, WSP_ROOM | WSP_BELOW);
+ p_ea = p_ea_save;
+ if (split_ret == FAIL)
+ continue;
+ }
+#ifdef FEAT_AUTOCMD
+ else /* first window: do autocmd for leaving this buffer */
+ --autocmd_no_leave;
+#endif
+
+ /*
+ * edit file i
+ */
+ curwin->w_arg_idx = i;
+ (void)do_ecmd(0, alist_name(&AARGLIST(alist)[i]), NULL, NULL,
+ ECMD_ONE,
+ ((P_HID(curwin->w_buffer)
+ || bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0)
+ + ECMD_OLDBUF);
+#ifdef FEAT_AUTOCMD
+ if (use_firstwin)
+ ++autocmd_no_leave;
+#endif
+ use_firstwin = FALSE;
+ }
+ ui_breakcheck();
+ }
+
+ /* Remove the "lock" on the argument list. */
+ alist_unlink(alist);
+
+#ifdef FEAT_AUTOCMD
+ --autocmd_no_enter;
+#endif
+ win_enter(firstwin, FALSE); /* back to first window */
+#ifdef FEAT_AUTOCMD
+ --autocmd_no_leave;
+#endif
+ vim_free(opened);
+}
+
+# if defined(FEAT_LISTCMDS) || defined(PROTO)
+/*
+ * Open a window for a number of buffers.
+ */
+ void
+ex_buffer_all(eap)
+ exarg_T *eap;
+{
+ buf_T *buf;
+ win_T *wp, *wpnext;
+ int split_ret = OK;
+ int p_ea_save;
+ int open_wins = 0;
+ int r;
+ int count; /* Maximum number of windows to open. */
+ int all; /* When TRUE also load inactive buffers. */
+
+ if (eap->addr_count == 0) /* make as many windows as possible */
+ count = 9999;
+ else
+ count = eap->line2; /* make as many windows as specified */
+ if (eap->cmdidx == CMD_unhide || eap->cmdidx == CMD_sunhide)
+ all = FALSE;
+ else
+ all = TRUE;
+
+ setpcmark();
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+
+ /*
+ * Close superfluous windows (two windows for the same buffer).
+ * Also close windows that are not full-width.
+ */
+ for (wp = firstwin; wp != NULL; wp = wpnext)
+ {
+ wpnext = wp->w_next;
+ if (wp->w_buffer->b_nwindows > 1
+#ifdef FEAT_VERTSPLIT
+ || ((cmdmod.split & WSP_VERT)
+ ? wp->w_height + wp->w_status_height < Rows - p_ch
+ : wp->w_width != Columns)
+#endif
+ )
+ {
+ win_close(wp, FALSE);
+#ifdef FEAT_AUTOCMD
+ wpnext = firstwin; /* just in case an autocommand does something
+ strange with windows */
+ open_wins = 0;
+#endif
+ }
+ else
+ ++open_wins;
+ }
+
+ /*
+ * Go through the buffer list. When a buffer doesn't have a window yet,
+ * open one. Otherwise move the window to the right position.
+ * Watch out for autocommands that delete buffers or windows!
+ */
+#ifdef FEAT_AUTOCMD
+ /* Don't execute Win/Buf Enter/Leave autocommands here. */
+ ++autocmd_no_enter;
+#endif
+ win_enter(lastwin, FALSE);
+#ifdef FEAT_AUTOCMD
+ ++autocmd_no_leave;
+#endif
+ for (buf = firstbuf; buf != NULL && open_wins < count; buf = buf->b_next)
+ {
+ /* Check if this buffer needs a window */
+ if ((!all && buf->b_ml.ml_mfp == NULL) || !buf->b_p_bl)
+ continue;
+
+ /* Check if this buffer already has a window */
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_buffer == buf)
+ break;
+ /* If the buffer already has a window, move it */
+ if (wp != NULL)
+ win_move_after(wp, curwin);
+ else if (split_ret == OK)
+ {
+ /* Split the window and put the buffer in it */
+ p_ea_save = p_ea;
+ p_ea = TRUE; /* use space from all windows */
+ split_ret = win_split(0, WSP_ROOM | WSP_BELOW);
+ ++open_wins;
+ p_ea = p_ea_save;
+ if (split_ret == FAIL)
+ continue;
+
+ /* Open the buffer in this window. */
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ swap_exists_action = SEA_DIALOG;
+#endif
+ set_curbuf(buf, DOBUF_GOTO);
+#ifdef FEAT_AUTOCMD
+# ifdef FEAT_EVAL
+ /* Autocommands deleted the buffer or aborted script
+ * processing!!! */
+ if (!buf_valid(buf) || aborting())
+# else
+ if (!buf_valid(buf)) /* autocommands deleted the buffer!!! */
+# endif
+ {
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ swap_exists_action = SEA_NONE;
+#endif
+ break;
+ }
+#endif
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if (swap_exists_action == SEA_QUIT)
+ {
+ /* User selected Quit at ATTENTION prompt; close this window. */
+ win_close(curwin, TRUE);
+ --open_wins;
+ swap_exists_action = SEA_NONE;
+ }
+ else
+ handle_swap_exists(NULL);
+#endif
+ }
+
+ ui_breakcheck();
+ if (got_int)
+ {
+ (void)vgetc(); /* only break the file loading, not the rest */
+ break;
+ }
+ }
+#ifdef FEAT_AUTOCMD
+ --autocmd_no_enter;
+#endif
+ win_enter(firstwin, FALSE); /* back to first window */
+#ifdef FEAT_AUTOCMD
+ --autocmd_no_leave;
+#endif
+
+ /*
+ * Close superfluous windows.
+ */
+ for (wp = lastwin; open_wins > count; )
+ {
+ r = (P_HID(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
+ || autowrite(wp->w_buffer, FALSE) == OK);
+#ifdef FEAT_AUTOCMD
+ if (!win_valid(wp))
+ {
+ /* BufWrite Autocommands made the window invalid, start over */
+ wp = lastwin;
+ }
+ else
+#endif
+ if (r)
+ {
+ win_close(wp, !P_HID(wp->w_buffer));
+ --open_wins;
+ wp = lastwin;
+ }
+ else
+ {
+ wp = wp->w_prev;
+ if (wp == NULL)
+ break;
+ }
+ }
+}
+# endif /* FEAT_LISTCMDS */
+
+#endif /* FEAT_WINDOWS */
+
+/*
+ * do_modelines() - process mode lines for the current file
+ *
+ * Returns immediately if the "ml" option isn't set.
+ */
+static int chk_modeline __ARGS((linenr_T));
+
+ void
+do_modelines()
+{
+ linenr_T lnum;
+ int nmlines;
+ static int entered = 0;
+
+ if (!curbuf->b_p_ml || (nmlines = (int)p_mls) == 0)
+ return;
+
+ /* Disallow recursive entry here. Can happen when executing a modeline
+ * triggers an autocommand, which reloads modelines with a ":do". */
+ if (entered)
+ return;
+
+ ++entered;
+ for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count && lnum <= nmlines;
+ ++lnum)
+ if (chk_modeline(lnum) == FAIL)
+ nmlines = 0;
+
+ for (lnum = curbuf->b_ml.ml_line_count; lnum > 0 && lnum > nmlines
+ && lnum > curbuf->b_ml.ml_line_count - nmlines; --lnum)
+ if (chk_modeline(lnum) == FAIL)
+ nmlines = 0;
+ --entered;
+}
+
+#include "version.h" /* for version number */
+
+/*
+ * chk_modeline() - check a single line for a mode string
+ * Return FAIL if an error encountered.
+ */
+ static int
+chk_modeline(lnum)
+ linenr_T lnum;
+{
+ char_u *s;
+ char_u *e;
+ char_u *linecopy; /* local copy of any modeline found */
+ int prev;
+ int vers;
+ int end;
+ int retval = OK;
+ char_u *save_sourcing_name;
+ linenr_T save_sourcing_lnum;
+#ifdef FEAT_EVAL
+ scid_T save_SID;
+#endif
+
+ prev = -1;
+ for (s = ml_get(lnum); *s != NUL; ++s)
+ {
+ if (prev == -1 || vim_isspace(prev))
+ {
+ if ((prev != -1 && STRNCMP(s, "ex:", (size_t)3) == 0)
+ || STRNCMP(s, "vi:", (size_t)3) == 0)
+ break;
+ if (STRNCMP(s, "vim", 3) == 0)
+ {
+ if (s[3] == '<' || s[3] == '=' || s[3] == '>')
+ e = s + 4;
+ else
+ e = s + 3;
+ vers = getdigits(&e);
+ if (*e == ':'
+ && (s[3] == ':'
+ || (VIM_VERSION_100 >= vers && isdigit(s[3]))
+ || (VIM_VERSION_100 < vers && s[3] == '<')
+ || (VIM_VERSION_100 > vers && s[3] == '>')
+ || (VIM_VERSION_100 == vers && s[3] == '=')))
+ break;
+ }
+ }
+ prev = *s;
+ }
+
+ if (*s)
+ {
+ do /* skip over "ex:", "vi:" or "vim:" */
+ ++s;
+ while (s[-1] != ':');
+
+ s = linecopy = vim_strsave(s); /* copy the line, it will change */
+ if (linecopy == NULL)
+ return FAIL;
+
+ save_sourcing_lnum = sourcing_lnum;
+ save_sourcing_name = sourcing_name;
+ sourcing_lnum = lnum; /* prepare for emsg() */
+ sourcing_name = (char_u *)"modelines";
+
+ end = FALSE;
+ while (end == FALSE)
+ {
+ s = skipwhite(s);
+ if (*s == NUL)
+ break;
+
+ /*
+ * Find end of set command: ':' or end of line.
+ * Skip over "\:", replacing it with ":".
+ */
+ for (e = s; *e != ':' && *e != NUL; ++e)
+ if (e[0] == '\\' && e[1] == ':')
+ STRCPY(e, e + 1);
+ if (*e == NUL)
+ end = TRUE;
+
+ /*
+ * If there is a "set" command, require a terminating ':' and
+ * ignore the stuff after the ':'.
+ * "vi:set opt opt opt: foo" -- foo not interpreted
+ * "vi:opt opt opt: foo" -- foo interpreted
+ * Accept "se" for compatibility with Elvis.
+ */
+ if (STRNCMP(s, "set ", (size_t)4) == 0
+ || STRNCMP(s, "se ", (size_t)3) == 0)
+ {
+ if (*e != ':') /* no terminating ':'? */
+ break;
+ end = TRUE;
+ s = vim_strchr(s, ' ') + 1;
+ }
+ *e = NUL; /* truncate the set command */
+
+ if (*s != NUL) /* skip over an empty "::" */
+ {
+#ifdef FEAT_EVAL
+ save_SID = current_SID;
+ current_SID = SID_MODELINE;
+#endif
+ retval = do_set(s, OPT_MODELINE | OPT_LOCAL);
+#ifdef FEAT_EVAL
+ current_SID = save_SID;
+#endif
+ if (retval == FAIL) /* stop if error found */
+ break;
+ }
+ s = e + 1; /* advance to next part */
+ }
+
+ sourcing_lnum = save_sourcing_lnum;
+ sourcing_name = save_sourcing_name;
+
+ vim_free(linecopy);
+ }
+ return retval;
+}
+
+#ifdef FEAT_VIMINFO
+ int
+read_viminfo_bufferlist(virp, writing)
+ vir_T *virp;
+ int writing;
+{
+ char_u *tab;
+ linenr_T lnum;
+ colnr_T col;
+ buf_T *buf;
+ char_u *sfname;
+ char_u *xline;
+
+ /* Handle long line and escaped characters. */
+ xline = viminfo_readstring(virp, 1, FALSE);
+
+ /* don't read in if there are files on the command-line or if writing: */
+ if (xline != NULL && !writing && ARGCOUNT == 0
+ && find_viminfo_parameter('%') != NULL)
+ {
+ /* Format is: <fname> Tab <lnum> Tab <col>.
+ * Watch out for a Tab in the file name, work from the end. */
+ lnum = 0;
+ col = 0;
+ tab = vim_strrchr(xline, '\t');
+ if (tab != NULL)
+ {
+ *tab++ = '\0';
+ col = atoi((char *)tab);
+ tab = vim_strrchr(xline, '\t');
+ if (tab != NULL)
+ {
+ *tab++ = '\0';
+ lnum = atol((char *)tab);
+ }
+ }
+
+ /* Expand "~/" in the file name at "line + 1" to a full path.
+ * Then try shortening it by comparing with the current directory */
+ expand_env(xline, NameBuff, MAXPATHL);
+ mch_dirname(IObuff, IOSIZE);
+ sfname = shorten_fname(NameBuff, IObuff);
+ if (sfname == NULL)
+ sfname = NameBuff;
+
+ buf = buflist_new(NameBuff, sfname, (linenr_T)0, BLN_LISTED);
+ if (buf != NULL) /* just in case... */
+ {
+ buf->b_last_cursor.lnum = lnum;
+ buf->b_last_cursor.col = col;
+ buflist_setfpos(buf, curwin, lnum, col, FALSE);
+ }
+ }
+ vim_free(xline);
+
+ return viminfo_readline(virp);
+}
+
+ void
+write_viminfo_bufferlist(fp)
+ FILE *fp;
+{
+ buf_T *buf;
+#ifdef FEAT_WINDOWS
+ win_T *win;
+#endif
+ char_u *line;
+
+ if (find_viminfo_parameter('%') == NULL)
+ return;
+
+ /* Allocate room for the file name, lnum and col. */
+ line = alloc(MAXPATHL + 30);
+ if (line == NULL)
+ return;
+
+#ifdef FEAT_WINDOWS
+ for (win = firstwin; win != NULL; win = win->w_next)
+ set_last_cursor(win);
+#else
+ set_last_cursor(curwin);
+#endif
+
+ fprintf(fp, _("\n# Buffer list:\n"));
+ for (buf = firstbuf; buf != NULL ; buf = buf->b_next)
+ {
+ if (buf->b_fname == NULL
+ || !buf->b_p_bl
+#ifdef FEAT_QUICKFIX
+ || bt_quickfix(buf)
+#endif
+ || removable(buf->b_ffname))
+ continue;
+
+ putc('%', fp);
+ home_replace(NULL, buf->b_ffname, line, MAXPATHL, TRUE);
+ sprintf((char *)line + STRLEN(line), "\t%ld\t%d",
+ (long)buf->b_last_cursor.lnum,
+ buf->b_last_cursor.col);
+ viminfo_writestring(fp, line);
+ }
+ vim_free(line);
+}
+#endif
+
+
+/*
+ * Return special buffer name.
+ * Returns NULL when the buffer has a normal file name.
+ */
+ char *
+buf_spname(buf)
+ buf_T *buf;
+{
+#if defined(FEAT_QUICKFIX) && defined(FEAT_WINDOWS)
+ if (bt_quickfix(buf))
+ return _("[Error List]");
+#endif
+#ifdef FEAT_QUICKFIX
+ /* There is no _file_ when 'buftype' is "nofile", b_sfname
+ * contains the name as specified by the user */
+ if (bt_nofile(buf))
+ {
+ if (buf->b_sfname != NULL)
+ return (char *)buf->b_sfname;
+ return "[Scratch]";
+ }
+#endif
+ if (buf->b_fname == NULL)
+ return _("[No File]");
+ return NULL;
+}
+
+
+#if defined(FEAT_SIGNS) || defined(PROTO)
+/*
+ * Insert the sign into the signlist.
+ */
+ static void
+insert_sign(buf, prev, next, id, lnum, typenr)
+ buf_T *buf; /* buffer to store sign in */
+ signlist_T *prev; /* previous sign entry */
+ signlist_T *next; /* next sign entry */
+ int id; /* sign ID */
+ linenr_T lnum; /* line number which gets the mark */
+ int typenr; /* typenr of sign we are adding */
+{
+ signlist_T *newsign;
+
+ newsign = (signlist_T *)lalloc((long_u)sizeof(signlist_T), FALSE);
+ if (newsign != NULL)
+ {
+ newsign->id = id;
+ newsign->lnum = lnum;
+ newsign->typenr = typenr;
+ newsign->next = next;
+#ifdef FEAT_NETBEANS_INTG
+ newsign->prev = prev;
+ if (next != NULL)
+ next->prev = newsign;
+#endif
+
+ if (prev == NULL)
+ {
+ /* When adding first sign need to redraw the windows to create the
+ * column for signs. */
+ if (buf->b_signlist == NULL)
+ {
+ redraw_buf_later(buf, NOT_VALID);
+ changed_cline_bef_curs();
+ }
+
+ /* first sign in signlist */
+ buf->b_signlist = newsign;
+ }
+ else
+ prev->next = newsign;
+ }
+}
+
+/*
+ * Add the sign into the signlist. Find the right spot to do it though.
+ */
+ void
+buf_addsign(buf, id, lnum, typenr)
+ buf_T *buf; /* buffer to store sign in */
+ int id; /* sign ID */
+ linenr_T lnum; /* line number which gets the mark */
+ int typenr; /* typenr of sign we are adding */
+{
+ signlist_T *sign; /* a sign in the signlist */
+ signlist_T *prev; /* the previous sign */
+
+ prev = NULL;
+ for (sign = buf->b_signlist; sign != NULL; sign = sign->next)
+ {
+ if (lnum == sign->lnum && id == sign->id)
+ {
+ sign->typenr = typenr;
+ return;
+ }
+ else if (
+#ifndef FEAT_NETBEANS_INTG /* keep signs sorted by lnum */
+ id < 0 &&
+#endif
+ lnum < sign->lnum)
+ {
+#ifdef FEAT_NETBEANS_INTG /* insert new sign at head of list for this lnum */
+ /* XXX - GRP: Is this because of sign slide problem? Or is it
+ * really needed? Or is it because we allow multiple signs per
+ * line? If so, should I add that feature to FEAT_SIGNS?
+ */
+ while (prev != NULL && prev->lnum == lnum)
+ prev = prev->prev;
+ if (prev == NULL)
+ sign = buf->b_signlist;
+ else
+ sign = prev->next;
+#endif
+ insert_sign(buf, prev, sign, id, lnum, typenr);
+ return;
+ }
+ prev = sign;
+ }
+#ifdef FEAT_NETBEANS_INTG /* insert new sign at head of list for this lnum */
+ /* XXX - GRP: See previous comment */
+ while (prev != NULL && prev->lnum == lnum)
+ prev = prev->prev;
+ if (prev == NULL)
+ sign = buf->b_signlist;
+ else
+ sign = prev->next;
+#endif
+ insert_sign(buf, prev, sign, id, lnum, typenr);
+
+ return;
+}
+
+ int
+buf_change_sign_type(buf, markId, typenr)
+ buf_T *buf; /* buffer to store sign in */
+ int markId; /* sign ID */
+ int typenr; /* typenr of sign we are adding */
+{
+ signlist_T *sign; /* a sign in the signlist */
+
+ for (sign = buf->b_signlist; sign != NULL; sign = sign->next)
+ {
+ if (sign->id == markId)
+ {
+ sign->typenr = typenr;
+ return sign->lnum;
+ }
+ }
+
+ return 0;
+}
+
+ int_u
+buf_getsigntype(buf, lnum, type)
+ buf_T *buf;
+ linenr_T lnum;
+ int type; /* SIGN_ICON, SIGN_TEXT, SIGN_ANY, SIGN_LINEHL */
+{
+ signlist_T *sign; /* a sign in a b_signlist */
+
+ for (sign = buf->b_signlist; sign != NULL; sign = sign->next)
+ if (sign->lnum == lnum
+ && (type == SIGN_ANY
+# ifdef FEAT_SIGN_ICONS
+ || (type == SIGN_ICON
+ && sign_get_image(sign->typenr) != NULL)
+# endif
+ || (type == SIGN_TEXT
+ && sign_get_text(sign->typenr) != NULL)
+ || (type == SIGN_LINEHL
+ && sign_get_attr(sign->typenr, TRUE) != 0)))
+ return sign->typenr;
+ return 0;
+}
+
+
+ linenr_T
+buf_delsign(buf, id)
+ buf_T *buf; /* buffer sign is stored in */
+ int id; /* sign id */
+{
+ signlist_T **lastp; /* pointer to pointer to current sign */
+ signlist_T *sign; /* a sign in a b_signlist */
+ signlist_T *next; /* the next sign in a b_signlist */
+ linenr_T lnum; /* line number whose sign was deleted */
+
+ lastp = &buf->b_signlist;
+ lnum = 0;
+ for (sign = buf->b_signlist; sign != NULL; sign = next)
+ {
+ next = sign->next;
+ if (sign->id == id)
+ {
+ *lastp = next;
+#ifdef FEAT_NETBEANS_INTG
+ if (next != NULL)
+ next->prev = sign->prev;
+#endif
+ lnum = sign->lnum;
+ vim_free(sign);
+ break;
+ }
+ else
+ lastp = &sign->next;
+ }
+
+ /* When deleted the last sign need to redraw the windows to remove the
+ * sign column. */
+ if (buf->b_signlist == NULL)
+ {
+ redraw_buf_later(buf, NOT_VALID);
+ changed_cline_bef_curs();
+ }
+
+ return lnum;
+}
+
+
+/*
+ * Find the line number of the sign with the requested id. If the sign does
+ * not exist, return 0 as the line number. This will still let the correct file
+ * get loaded.
+ */
+ int
+buf_findsign(buf, id)
+ buf_T *buf; /* buffer to store sign in */
+ int id; /* sign ID */
+{
+ signlist_T *sign; /* a sign in the signlist */
+
+ for (sign = buf->b_signlist; sign != NULL; sign = sign->next)
+ if (sign->id == id)
+ return sign->lnum;
+
+ return 0;
+}
+
+ int
+buf_findsign_id(buf, lnum)
+ buf_T *buf; /* buffer whose sign we are searching for */
+ linenr_T lnum; /* line number of sign */
+{
+ signlist_T *sign; /* a sign in the signlist */
+
+ for (sign = buf->b_signlist; sign != NULL; sign = sign->next)
+ if (sign->lnum == lnum)
+ return sign->id;
+
+ return 0;
+}
+
+
+# if defined(FEAT_NETBEANS_INTG) || defined(PROTO)
+/* see if a given type of sign exists on a specific line */
+ int
+buf_findsigntype_id(buf, lnum, typenr)
+ buf_T *buf; /* buffer whose sign we are searching for */
+ linenr_T lnum; /* line number of sign */
+ int typenr; /* sign type number */
+{
+ signlist_T *sign; /* a sign in the signlist */
+
+ for (sign = buf->b_signlist; sign != NULL; sign = sign->next)
+ if (sign->lnum == lnum && sign->typenr == typenr)
+ return sign->id;
+
+ return 0;
+}
+
+
+# if defined(FEAT_SIGN_ICONS) || defined(PROTO)
+/* return the number of icons on the given line */
+ int
+buf_signcount(buf, lnum)
+ buf_T *buf;
+ linenr_T lnum;
+{
+ signlist_T *sign; /* a sign in the signlist */
+ int count = 0;
+
+ for (sign = buf->b_signlist; sign != NULL; sign = sign->next)
+ if (sign->lnum == lnum)
+ if (sign_get_image(sign->typenr) != NULL)
+ count++;
+
+ return count;
+}
+# endif /* FEAT_SIGN_ICONS */
+# endif /* FEAT_NETBEANS_INTG */
+
+
+/*
+ * Delete signs in buffer "buf".
+ */
+ static void
+buf_delete_signs(buf)
+ buf_T *buf;
+{
+ signlist_T *next;
+
+ while (buf->b_signlist != NULL)
+ {
+ next = buf->b_signlist->next;
+ vim_free(buf->b_signlist);
+ buf->b_signlist = next;
+ }
+}
+
+/*
+ * Delete all signs in all buffers.
+ */
+ void
+buf_delete_all_signs()
+{
+ buf_T *buf; /* buffer we are checking for signs */
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (buf->b_signlist != NULL)
+ {
+ /* Need to redraw the windows to remove the sign column. */
+ redraw_buf_later(buf, NOT_VALID);
+ buf_delete_signs(buf);
+ }
+}
+
+/*
+ * List placed signs for "rbuf". If "rbuf" is NULL do it for all buffers.
+ */
+ void
+sign_list_placed(rbuf)
+ buf_T *rbuf;
+{
+ buf_T *buf;
+ signlist_T *p;
+ char lbuf[BUFSIZ];
+
+ MSG_PUTS_TITLE(_("\n--- Signs ---"));
+ msg_putchar('\n');
+ if (rbuf == NULL)
+ buf = firstbuf;
+ else
+ buf = rbuf;
+ while (buf != NULL)
+ {
+ if (buf->b_signlist != NULL)
+ {
+#ifdef HAVE_SNPRINTF
+ snprintf
+#else
+ sprintf
+#endif
+ (lbuf,
+#ifdef HAVE_SNPRINTF
+ BUFSIZ,
+#endif
+ _("Signs for %s:"), buf->b_fname);
+ MSG_PUTS_ATTR(lbuf, hl_attr(HLF_D));
+ msg_putchar('\n');
+ }
+ for (p = buf->b_signlist; p != NULL; p = p->next)
+ {
+ sprintf(lbuf, _(" line=%ld id=%d name=%s"),
+ (long)p->lnum, p->id, sign_typenr2name(p->typenr));
+ MSG_PUTS(lbuf);
+ msg_putchar('\n');
+ }
+ if (rbuf != NULL)
+ break;
+ buf = buf->b_next;
+ }
+}
+
+/*
+ * Adjust a placed sign for inserted/deleted lines.
+ */
+ void
+sign_mark_adjust(line1, line2, amount, amount_after)
+ linenr_T line1;
+ linenr_T line2;
+ long amount;
+ long amount_after;
+{
+ signlist_T *sign; /* a sign in a b_signlist */
+
+ for (sign = curbuf->b_signlist; sign != NULL; sign = sign->next)
+ {
+ if (sign->lnum >= line1 && sign->lnum <= line2)
+ {
+ if (amount == MAXLNUM)
+ sign->lnum = line1;
+ else
+ sign->lnum += amount;
+ }
+ else if (sign->lnum > line2)
+ sign->lnum += amount_after;
+ }
+}
+#endif /* FEAT_SIGNS */
+
+/*
+ * Set 'buflisted' for curbuf to "on" and trigger autocommands if it changed.
+ */
+ void
+set_buflisted(on)
+ int on;
+{
+ if (on != curbuf->b_p_bl)
+ {
+ curbuf->b_p_bl = on;
+#ifdef FEAT_AUTOCMD
+ if (on)
+ apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, curbuf);
+ else
+ apply_autocmds(EVENT_BUFDELETE, NULL, NULL, FALSE, curbuf);
+#endif
+ }
+}
+
+/*
+ * Read the file for "buf" again and check if the contents changed.
+ * Return TRUE if it changed or this could not be checked.
+ */
+ int
+buf_contents_changed(buf)
+ buf_T *buf;
+{
+ buf_T *newbuf;
+ int differ = TRUE;
+ linenr_T lnum;
+#ifdef FEAT_AUTOCMD
+ aco_save_T aco;
+#else
+ buf_T *old_curbuf = curbuf;
+#endif
+ exarg_T ea;
+
+ /* Allocate a buffer without putting it in the buffer list. */
+ newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
+ if (newbuf == NULL)
+ return TRUE;
+
+ /* Force the 'fileencoding' and 'fileformat' to be equal. */
+ if (prep_exarg(&ea, buf) == FAIL)
+ {
+ wipe_buffer(newbuf, FALSE);
+ return TRUE;
+ }
+
+#ifdef FEAT_AUTOCMD
+ /* set curwin/curbuf to buf and save a few things */
+ aucmd_prepbuf(&aco, newbuf);
+#else
+ curbuf = newbuf;
+ curwin->w_buffer = newbuf;
+#endif
+
+ if (ml_open() == OK
+ && readfile(buf->b_ffname, buf->b_fname,
+ (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM,
+ &ea, READ_NEW | READ_DUMMY) == OK)
+ {
+ /* compare the two files line by line */
+ if (buf->b_ml.ml_line_count == curbuf->b_ml.ml_line_count)
+ {
+ differ = FALSE;
+ for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
+ if (STRCMP(ml_get_buf(buf, lnum, FALSE), ml_get(lnum)) != 0)
+ {
+ differ = TRUE;
+ break;
+ }
+ }
+ }
+ vim_free(ea.cmd);
+
+#ifdef FEAT_AUTOCMD
+ /* restore curwin/curbuf and a few other things */
+ aucmd_restbuf(&aco);
+#else
+ curbuf = old_curbuf;
+ curwin->w_buffer = old_curbuf;
+#endif
+
+ if (curbuf != newbuf) /* safety check */
+ wipe_buffer(newbuf, FALSE);
+
+ return differ;
+}
+
+/*
+ * Wipe out a buffer and decrement the last buffer number if it was used for
+ * this buffer. Call this to wipe out a temp buffer that does not contain any
+ * marks.
+ */
+/*ARGSUSED*/
+ void
+wipe_buffer(buf, aucmd)
+ buf_T *buf;
+ int aucmd; /* When TRUE trigger autocommands. */
+{
+ if (buf->b_fnum == top_file_num - 1)
+ --top_file_num;
+
+#ifdef FEAT_AUTOCMD
+ if (!aucmd) /* Don't trigger BufDelete autocommands here. */
+ ++autocmd_block;
+#endif
+ close_buffer(NULL, buf, DOBUF_WIPE);
+#ifdef FEAT_AUTOCMD
+ if (!aucmd)
+ --autocmd_block;
+#endif
+}
diff --git a/src/charset.c b/src/charset.c
new file mode 100644
index 000000000..2424e27ce
--- /dev/null
+++ b/src/charset.c
@@ -0,0 +1,1795 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+
+#ifdef FEAT_LINEBREAK
+static int win_chartabsize __ARGS((win_T *wp, char_u *p, colnr_T col));
+#endif
+
+#ifdef FEAT_MBYTE
+static int win_nolbr_chartabsize __ARGS((win_T *wp, char_u *s, colnr_T col, int *headp));
+#endif
+
+static int nr2hex __ARGS((int c));
+
+static int chartab_initialized = FALSE;
+
+/* b_chartab[] is an array of 32 bytes, each bit representing one of the
+ * characters 0-255. */
+#define SET_CHARTAB(buf, c) (buf)->b_chartab[(unsigned)(c) >> 3] |= (1 << ((c) & 0x7))
+#define RESET_CHARTAB(buf, c) (buf)->b_chartab[(unsigned)(c) >> 3] &= ~(1 << ((c) & 0x7))
+#define GET_CHARTAB(buf, c) ((buf)->b_chartab[(unsigned)(c) >> 3] & (1 << ((c) & 0x7)))
+
+/*
+ * Fill chartab[]. Also fills curbuf->b_chartab[] with flags for keyword
+ * characters for current buffer.
+ *
+ * Depends on the option settings 'iskeyword', 'isident', 'isfname',
+ * 'isprint' and 'encoding'.
+ *
+ * The index in chartab[] depends on 'encoding':
+ * - For non-multi-byte index with the byte (same as the character).
+ * - For DBCS index with the first byte.
+ * - For UTF-8 index with the character (when first byte is up to 0x80 it is
+ * the same as the character, if the first byte is 0x80 and above it depends
+ * on further bytes).
+ *
+ * The contents of chartab[]:
+ * - The lower two bits, masked by CT_CELL_MASK, give the number of display
+ * cells the character occupies (1 or 2). Not valid for UTF-8 above 0x80.
+ * - CT_PRINT_CHAR bit is set when the character is printable (no need to
+ * translate the character before displaying it). Note that only DBCS
+ * characters can have 2 display cells and still be printable.
+ * - CT_FNAME_CHAR bit is set when the character can be in a file name.
+ * - CT_ID_CHAR bit is set when the character can be in an identifier.
+ *
+ * Return FAIL if 'iskeyword', 'isident', 'isfname' or 'isprint' option has an
+ * error, OK otherwise.
+ */
+ int
+init_chartab()
+{
+ return buf_init_chartab(curbuf, TRUE);
+}
+
+ int
+buf_init_chartab(buf, global)
+ buf_T *buf;
+ int global; /* FALSE: only set buf->b_chartab[] */
+{
+ int c;
+ int c2;
+ char_u *p;
+ int i;
+ int tilde;
+ int do_isalpha;
+
+ if (global)
+ {
+ /*
+ * Set the default size for printable characters:
+ * From <Space> to '~' is 1 (printable), others are 2 (not printable).
+ * This also inits all 'isident' and 'isfname' flags to FALSE.
+ *
+ * EBCDIC: all chars below ' ' are not printable, all others are
+ * printable.
+ */
+ c = 0;
+ while (c < ' ')
+ chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2;
+#ifdef EBCDIC
+ while (c < 255)
+#else
+ while (c <= '~')
+#endif
+ chartab[c++] = 1 + CT_PRINT_CHAR;
+#ifdef FEAT_FKMAP
+ if (p_altkeymap)
+ {
+ while (c < YE)
+ chartab[c++] = 1 + CT_PRINT_CHAR;
+ }
+#endif
+ while (c < 256)
+ {
+#ifdef FEAT_MBYTE
+ /* UTF-8: bytes 0xa0 - 0xff are printable (latin1) */
+ if (enc_utf8 && c >= 0xa0)
+ chartab[c++] = CT_PRINT_CHAR + 1;
+ /* euc-jp characters starting with 0x8e are single width */
+ else if (enc_dbcs == DBCS_JPNU && c == 0x8e)
+ chartab[c++] = CT_PRINT_CHAR + 1;
+ /* other double-byte chars can be printable AND double-width */
+ else if (enc_dbcs != 0 && MB_BYTE2LEN(c) == 2)
+ chartab[c++] = CT_PRINT_CHAR + 2;
+ else
+#endif
+ /* the rest is unprintable by default */
+ chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2;
+ }
+
+#ifdef FEAT_MBYTE
+ /* Assume that every multi-byte char is a filename character. */
+ for (c = 1; c < 256; ++c)
+ if ((enc_dbcs != 0 && MB_BYTE2LEN(c) > 1)
+ || (enc_dbcs == DBCS_JPNU && c == 0x8e)
+ || (enc_utf8 && c >= 0xa0))
+ chartab[c] |= CT_FNAME_CHAR;
+#endif
+ }
+
+ /*
+ * Init word char flags all to FALSE
+ */
+ vim_memset(buf->b_chartab, 0, (size_t)32);
+#ifdef FEAT_MBYTE
+ for (c = 0; c < 256; ++c)
+ {
+ /* double-byte characters are probably word characters */
+ if (enc_dbcs != 0 && MB_BYTE2LEN(c) == 2)
+ SET_CHARTAB(buf, c);
+ }
+#endif
+
+#ifdef FEAT_LISP
+ /*
+ * In lisp mode the '-' character is included in keywords.
+ */
+ if (buf->b_p_lisp)
+ SET_CHARTAB(buf, '-');
+#endif
+
+ /* Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint'
+ * options Each option is a list of characters, character numbers or
+ * ranges, separated by commas, e.g.: "200-210,x,#-178,-"
+ */
+ for (i = global ? 0 : 3; i <= 3; ++i)
+ {
+ if (i == 0)
+ p = p_isi; /* first round: 'isident' */
+ else if (i == 1)
+ p = p_isp; /* second round: 'isprint' */
+ else if (i == 2)
+ p = p_isf; /* third round: 'isfname' */
+ else /* i == 3 */
+ p = buf->b_p_isk; /* fourth round: 'iskeyword' */
+
+ while (*p)
+ {
+ tilde = FALSE;
+ do_isalpha = FALSE;
+ if (*p == '^' && p[1] != NUL)
+ {
+ tilde = TRUE;
+ ++p;
+ }
+ if (VIM_ISDIGIT(*p))
+ c = getdigits(&p);
+ else
+ c = *p++;
+ c2 = -1;
+ if (*p == '-' && p[1] != NUL)
+ {
+ ++p;
+ if (VIM_ISDIGIT(*p))
+ c2 = getdigits(&p);
+ else
+ c2 = *p++;
+ }
+ if (c <= 0 || (c2 < c && c2 != -1) || c2 >= 256
+ || !(*p == NUL || *p == ','))
+ return FAIL;
+
+ if (c2 == -1) /* not a range */
+ {
+ /*
+ * A single '@' (not "@-@"):
+ * Decide on letters being ID/printable/keyword chars with
+ * standard function isalpha(). This takes care of locale for
+ * single-byte characters).
+ */
+ if (c == '@')
+ {
+ do_isalpha = TRUE;
+ c = 1;
+ c2 = 255;
+ }
+ else
+ c2 = c;
+ }
+ while (c <= c2)
+ {
+ if (!do_isalpha || isalpha(c)
+#ifdef FEAT_FKMAP
+ || (p_altkeymap && (F_isalpha(c) || F_isdigit(c)))
+#endif
+ )
+ {
+ if (i == 0) /* (re)set ID flag */
+ {
+ if (tilde)
+ chartab[c] &= ~CT_ID_CHAR;
+ else
+ chartab[c] |= CT_ID_CHAR;
+ }
+ else if (i == 1) /* (re)set printable */
+ {
+ if ((c < ' '
+#ifndef EBCDIC
+ || c > '~'
+#endif
+#ifdef FEAT_FKMAP
+ || (p_altkeymap
+ && (F_isalpha(c) || F_isdigit(c)))
+#endif
+ )
+#ifdef FEAT_MBYTE
+ /* For double-byte we keep the cell width, so
+ * that we can detect it from the first byte. */
+ && !(enc_dbcs && MB_BYTE2LEN(c) == 2)
+#endif
+ )
+ {
+ if (tilde)
+ {
+ chartab[c] = (chartab[c] & ~CT_CELL_MASK)
+ + ((dy_flags & DY_UHEX) ? 4 : 2);
+ chartab[c] &= ~CT_PRINT_CHAR;
+ }
+ else
+ {
+ chartab[c] = (chartab[c] & ~CT_CELL_MASK) + 1;
+ chartab[c] |= CT_PRINT_CHAR;
+ }
+ }
+ }
+ else if (i == 2) /* (re)set fname flag */
+ {
+ if (tilde)
+ chartab[c] &= ~CT_FNAME_CHAR;
+ else
+ chartab[c] |= CT_FNAME_CHAR;
+ }
+ else /* i == 3 */ /* (re)set keyword flag */
+ {
+ if (tilde)
+ RESET_CHARTAB(buf, c);
+ else
+ SET_CHARTAB(buf, c);
+ }
+ }
+ ++c;
+ }
+ p = skip_to_option_part(p);
+ }
+ }
+ chartab_initialized = TRUE;
+ return OK;
+}
+
+/*
+ * Translate any special characters in buf[bufsize] in-place.
+ * The result is a string with only printable characters, but if there is not
+ * enough room, not all characters will be translated.
+ */
+ void
+trans_characters(buf, bufsize)
+ char_u *buf;
+ int bufsize;
+{
+ int len; /* length of string needing translation */
+ int room; /* room in buffer after string */
+ char_u *trs; /* translated character */
+ int trs_len; /* length of trs[] */
+
+ len = (int)STRLEN(buf);
+ room = bufsize - len;
+ while (*buf != 0)
+ {
+# ifdef FEAT_MBYTE
+ /* Assume a multi-byte character doesn't need translation. */
+ if (has_mbyte && (trs_len = (*mb_ptr2len_check)(buf)) > 1)
+ len -= trs_len;
+ else
+# endif
+ {
+ trs = transchar_byte(*buf);
+ trs_len = (int)STRLEN(trs);
+ if (trs_len > 1)
+ {
+ room -= trs_len - 1;
+ if (room <= 0)
+ return;
+ mch_memmove(buf + trs_len, buf + 1, (size_t)len);
+ }
+ mch_memmove(buf, trs, (size_t)trs_len);
+ --len;
+ }
+ buf += trs_len;
+ }
+}
+
+#if defined(FEAT_EVAL) || defined(FEAT_TITLE) || defined(PROTO)
+/*
+ * Translate a string into allocated memory, replacing special chars with
+ * printable chars. Returns NULL when out of memory.
+ */
+ char_u *
+transstr(s)
+ char_u *s;
+{
+ char_u *res;
+ char_u *p;
+#ifdef FEAT_MBYTE
+ int l, len, c;
+ char_u hexbuf[11];
+#endif
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ /* Compute the length of the result, taking account of unprintable
+ * multi-byte characters. */
+ len = 0;
+ p = s;
+ while (*p != NUL)
+ {
+ if ((l = (*mb_ptr2len_check)(p)) > 1)
+ {
+ c = (*mb_ptr2char)(p);
+ p += l;
+ if (vim_isprintc(c))
+ len += l;
+ else
+ {
+ transchar_hex(hexbuf, c);
+ len += STRLEN(hexbuf);
+ }
+ }
+ else
+ {
+ l = byte2cells(*p++);
+ if (l > 0)
+ len += l;
+ else
+ len += 4; /* illegal byte sequence */
+ }
+ }
+ res = alloc((unsigned)(len + 1));
+ }
+ else
+#endif
+ res = alloc((unsigned)(vim_strsize(s) + 1));
+ if (res != NULL)
+ {
+ *res = NUL;
+ p = s;
+ while (*p != NUL)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
+ {
+ c = (*mb_ptr2char)(p);
+ if (vim_isprintc(c))
+ STRNCAT(res, p, l); /* append printable multi-byte char */
+ else
+ transchar_hex(res + STRLEN(res), c);
+ p += l;
+ }
+ else
+#endif
+ STRCAT(res, transchar_byte(*p++));
+ }
+ }
+ return res;
+}
+#endif
+
+#if defined(FEAT_SYN_HL) || defined(FEAT_INS_EXPAND) || defined(PROTO)
+/*
+ * Convert the string "p[len]" to do ignore-case comparing. Uses the current
+ * locale. Returns an allocated string (NULL for out-of-memory).
+ */
+ char_u *
+str_foldcase(str, len)
+ char_u *str;
+ int len;
+{
+ garray_T ga;
+ int i;
+
+#define GA_CHAR(i) ((char_u *)ga.ga_data)[i]
+#define GA_PTR(i) ((char_u *)ga.ga_data + i)
+
+ /* Copy "str" into allocated memory, unmodified. */
+ ga_init2(&ga, 1, 10);
+ if (ga_grow(&ga, len + 1) == FAIL)
+ return NULL;
+ mch_memmove(ga.ga_data, str, (size_t)len);
+ GA_CHAR(len) = NUL;
+ ga.ga_len = len;
+ ga.ga_room -= len;
+
+ /* Make each character lower case. */
+ i = 0;
+ while (GA_CHAR(i) != NUL)
+ {
+#ifdef FEAT_MBYTE
+ if (enc_utf8 || (has_mbyte && MB_BYTE2LEN(GA_CHAR(i)) > 1))
+ {
+ if (enc_utf8)
+ {
+ int c, lc;
+
+ c = utf_ptr2char(GA_PTR(i));
+ lc = utf_tolower(c);
+ if (c != lc)
+ {
+ int ol = utf_char2len(c);
+ int nl = utf_char2len(lc);
+
+ /* If the byte length changes need to shift the following
+ * characters forward or backward. */
+ if (ol != nl)
+ {
+ if (nl > ol)
+ if (ga_grow(&ga, nl - ol) == FAIL)
+ {
+ /* out of memory, keep old char */
+ lc = c;
+ nl = ol;
+ }
+ if (ol != nl)
+ {
+ mch_memmove(GA_PTR(i) + nl, GA_PTR(i) + ol,
+ STRLEN(GA_PTR(i) + ol) + 1);
+ ga.ga_len += nl - ol;
+ ga.ga_room -= nl - ol;
+ }
+ }
+ (void)utf_char2bytes(lc, GA_PTR(i));
+ }
+ }
+ /* skip to next multi-byte char */
+ i += (*mb_ptr2len_check)(GA_PTR(i));
+ }
+ else
+#endif
+ {
+ GA_CHAR(i) = TOLOWER_LOC(GA_CHAR(i));
+ ++i;
+ }
+ }
+
+ return (char_u *)ga.ga_data;
+}
+#endif
+
+/*
+ * Catch 22: chartab[] can't be initialized before the options are
+ * initialized, and initializing options may cause transchar() to be called!
+ * When chartab_initialized == FALSE don't use chartab[].
+ * Does NOT work for multi-byte characters, c must be <= 255.
+ * Also doesn't work for the first byte of a multi-byte, "c" must be a
+ * character!
+ */
+static char_u transchar_buf[7];
+
+ char_u *
+transchar(c)
+ int c;
+{
+ int i;
+
+ i = 0;
+ if (IS_SPECIAL(c)) /* special key code, display as ~@ char */
+ {
+ transchar_buf[0] = '~';
+ transchar_buf[1] = '@';
+ i = 2;
+ c = K_SECOND(c);
+ }
+
+ if ((!chartab_initialized && (
+#ifdef EBCDIC
+ (c >= 64 && c < 255)
+#else
+ (c >= ' ' && c <= '~')
+#endif
+#ifdef FEAT_FKMAP
+ || F_ischar(c)
+#endif
+ )) || (c < 256 && vim_isprintc_strict(c)))
+ {
+ /* printable character */
+ transchar_buf[i] = c;
+ transchar_buf[i + 1] = NUL;
+ }
+ else
+ transchar_nonprint(transchar_buf + i, c);
+ return transchar_buf;
+}
+
+#if defined(FEAT_MBYTE) || defined(PROTO)
+/*
+ * Like transchar(), but called with a byte instead of a character. Checks
+ * for an illegal UTF-8 byte.
+ */
+ char_u *
+transchar_byte(c)
+ int c;
+{
+ if (enc_utf8 && c >= 0x80)
+ {
+ transchar_nonprint(transchar_buf, c);
+ return transchar_buf;
+ }
+ return transchar(c);
+}
+#endif
+
+/*
+ * Convert non-printable character to two or more printable characters in
+ * "buf[]". "buf" needs to be able to hold five bytes.
+ * Does NOT work for multi-byte characters, c must be <= 255.
+ */
+ void
+transchar_nonprint(buf, c)
+ char_u *buf;
+ int c;
+{
+ if (c == NL)
+ c = NUL; /* we use newline in place of a NUL */
+ else if (c == CAR && get_fileformat(curbuf) == EOL_MAC)
+ c = NL; /* we use CR in place of NL in this case */
+
+ if (dy_flags & DY_UHEX) /* 'display' has "uhex" */
+ transchar_hex(buf, c);
+
+#ifdef EBCDIC
+ /* For EBCDIC only the characters 0-63 and 255 are not printable */
+ else if (CtrlChar(c) != 0 || c == DEL)
+#else
+ else if (c <= 0x7f) /* 0x00 - 0x1f and 0x7f */
+#endif
+ {
+ buf[0] = '^';
+#ifdef EBCDIC
+ if (c == DEL)
+ buf[1] = '?'; /* DEL displayed as ^? */
+ else
+ buf[1] = CtrlChar(c);
+#else
+ buf[1] = c ^ 0x40; /* DEL displayed as ^? */
+#endif
+
+ buf[2] = NUL;
+ }
+#ifdef FEAT_MBYTE
+ else if (enc_utf8 && c >= 0x80)
+ {
+ transchar_hex(buf, c);
+ }
+#endif
+#ifndef EBCDIC
+ else if (c >= ' ' + 0x80 && c <= '~' + 0x80) /* 0xa0 - 0xfe */
+ {
+ buf[0] = '|';
+ buf[1] = c - 0x80;
+ buf[2] = NUL;
+ }
+#else
+ else if (c < 64)
+ {
+ buf[0] = '~';
+ buf[1] = MetaChar(c);
+ buf[2] = NUL;
+ }
+#endif
+ else /* 0x80 - 0x9f and 0xff */
+ {
+ /*
+ * TODO: EBCDIC I don't know what to do with this chars, so I display
+ * them as '~?' for now
+ */
+ buf[0] = '~';
+#ifdef EBCDIC
+ buf[1] = '?'; /* 0xff displayed as ~? */
+#else
+ buf[1] = (c - 0x80) ^ 0x40; /* 0xff displayed as ~? */
+#endif
+ buf[2] = NUL;
+ }
+}
+
+ void
+transchar_hex(buf, c)
+ char_u *buf;
+ int c;
+{
+ int i = 0;
+
+ buf[0] = '<';
+#ifdef FEAT_MBYTE
+ if (c > 255)
+ {
+ buf[++i] = nr2hex((unsigned)c >> 12);
+ buf[++i] = nr2hex((unsigned)c >> 8);
+ }
+#endif
+ buf[++i] = nr2hex((unsigned)c >> 4);
+ buf[++i] = nr2hex(c);
+ buf[++i] = '>';
+ buf[++i] = NUL;
+}
+
+/*
+ * Convert the lower 4 bits of byte "c" to its hex character.
+ * Lower case letters are used to avoid the confusion of <F1> being 0xf1 or
+ * function key 1.
+ */
+ static int
+nr2hex(c)
+ int c;
+{
+ if ((c & 0xf) <= 9)
+ return (c & 0xf) + '0';
+ return (c & 0xf) - 10 + 'a';
+}
+
+/*
+ * Return number of display cells occupied by byte "b".
+ * Caller must make sure 0 <= b <= 255.
+ * For multi-byte mode "b" must be the first byte of a character.
+ * A TAB is counted as two cells: "^I".
+ * For UTF-8 mode this will return 0 for bytes >= 0x80, because the number of
+ * cells depends on further bytes.
+ */
+ int
+byte2cells(b)
+ int b;
+{
+#ifdef FEAT_MBYTE
+ if (enc_utf8 && b >= 0x80)
+ return 0;
+#endif
+ return (chartab[b] & CT_CELL_MASK);
+}
+
+/*
+ * Return number of display cells occupied by character "c".
+ * "c" can be a special key (negative number) in which case 3 or 4 is returned.
+ * A TAB is counted as two cells: "^I" or four: "<09>".
+ */
+ int
+char2cells(c)
+ int c;
+{
+ if (IS_SPECIAL(c))
+ return char2cells(K_SECOND(c)) + 2;
+#ifdef FEAT_MBYTE
+ if (c >= 0x80)
+ {
+ /* UTF-8: above 0x80 need to check the value */
+ if (enc_utf8)
+ return utf_char2cells(c);
+ /* DBCS: double-byte means double-width, except for euc-jp with first
+ * byte 0x8e */
+ if (enc_dbcs != 0 && c >= 0x100)
+ {
+ if (enc_dbcs == DBCS_JPNU && ((unsigned)c >> 8) == 0x8e)
+ return 1;
+ return 2;
+ }
+ }
+#endif
+ return (chartab[c & 0xff] & CT_CELL_MASK);
+}
+
+/*
+ * Return number of display cells occupied by character at "*p".
+ * A TAB is counted as two cells: "^I" or four: "<09>".
+ */
+ int
+ptr2cells(p)
+ char_u *p;
+{
+#ifdef FEAT_MBYTE
+ /* For UTF-8 we need to look at more bytes if the first byte is >= 0x80. */
+ if (enc_utf8 && *p >= 0x80)
+ return utf_ptr2cells(p);
+ /* For DBCS we can tell the cell count from the first byte. */
+#endif
+ return (chartab[*p] & CT_CELL_MASK);
+}
+
+/*
+ * Return the number of characters string "s" will take on the screen,
+ * counting TABs as two characters: "^I".
+ */
+ int
+vim_strsize(s)
+ char_u *s;
+{
+ return vim_strnsize(s, (int)MAXCOL);
+}
+
+/*
+ * Return the number of characters string "s[len]" will take on the screen,
+ * counting TABs as two characters: "^I".
+ */
+ int
+vim_strnsize(s, len)
+ char_u *s;
+ int len;
+{
+ int size = 0;
+
+ while (*s != NUL && --len >= 0)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int l = (*mb_ptr2len_check)(s);
+
+ size += ptr2cells(s);
+ s += l;
+ len -= l - 1;
+ }
+ else
+#endif
+ size += byte2cells(*s++);
+ }
+ return size;
+}
+
+/*
+ * Return the number of characters 'c' will take on the screen, taking
+ * into account the size of a tab.
+ * Use a define to make it fast, this is used very often!!!
+ * Also see getvcol() below.
+ */
+
+#define RET_WIN_BUF_CHARTABSIZE(wp, buf, p, col) \
+ if (*(p) == TAB && (!(wp)->w_p_list || lcs_tab1)) \
+ { \
+ int ts; \
+ ts = (buf)->b_p_ts; \
+ return (int)(ts - (col % ts)); \
+ } \
+ else \
+ return ptr2cells(p);
+
+#if defined(FEAT_VREPLACE) || defined(FEAT_EX_EXTRA) || defined(FEAT_GUI) \
+ || defined(FEAT_VIRTUALEDIT) || defined(PROTO)
+ int
+chartabsize(p, col)
+ char_u *p;
+ colnr_T col;
+{
+ RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, p, col)
+}
+#endif
+
+#ifdef FEAT_LINEBREAK
+ static int
+win_chartabsize(wp, p, col)
+ win_T *wp;
+ char_u *p;
+ colnr_T col;
+{
+ RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, p, col)
+}
+#endif
+
+/*
+ * return the number of characters the string 's' will take on the screen,
+ * taking into account the size of a tab
+ */
+ int
+linetabsize(s)
+ char_u *s;
+{
+ colnr_T col = 0;
+
+ while (*s != NUL)
+ col += lbr_chartabsize_adv(&s, col);
+ return (int)col;
+}
+
+/*
+ * Like linetabsize(), but for a given window instead of the current one.
+ */
+ int
+win_linetabsize(wp, p, len)
+ win_T *wp;
+ char_u *p;
+ colnr_T len;
+{
+ colnr_T col = 0;
+ char_u *s;
+
+ for (s = p; *s != NUL && (len == MAXCOL || s < p + len); )
+ {
+ col += win_lbr_chartabsize(wp, s, col, NULL);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ s += (*mb_ptr2len_check)(s);
+ else
+#endif
+ ++s;
+ }
+ return (int)col;
+}
+
+/*
+ * return TRUE if 'c' is a normal identifier character
+ * letters and characters from 'isident' option.
+ */
+ int
+vim_isIDc(c)
+ int c;
+{
+ return (c > 0 && c < 0x100 && (chartab[c] & CT_ID_CHAR));
+}
+
+/*
+ * return TRUE if 'c' is a keyword character: Letters and characters from
+ * 'iskeyword' option for current buffer.
+ * For multi-byte characters mb_get_class() is used (builtin rules).
+ */
+ int
+vim_iswordc(c)
+ int c;
+{
+#ifdef FEAT_MBYTE
+ if (c >= 0x100)
+ {
+ if (enc_dbcs != 0)
+ return dbcs_class((unsigned)c >> 8, c & 0xff) >= 2;
+ if (enc_utf8)
+ return utf_class(c) >= 2;
+ }
+#endif
+ return (c > 0 && c < 0x100 && GET_CHARTAB(curbuf, c) != 0);
+}
+
+/*
+ * Just like vim_iswordc() but uses a pointer to the (multi-byte) character.
+ */
+ int
+vim_iswordp(p)
+ char_u *p;
+{
+#ifdef FEAT_MBYTE
+ if (has_mbyte && MB_BYTE2LEN(*p) > 1)
+ return mb_get_class(p) >= 2;
+#endif
+ return GET_CHARTAB(curbuf, *p) != 0;
+}
+
+#if defined(FEAT_SYN_HL) || defined(PROTO)
+ int
+vim_iswordc_buf(p, buf)
+ char_u *p;
+ buf_T *buf;
+{
+# ifdef FEAT_MBYTE
+ if (has_mbyte && MB_BYTE2LEN(*p) > 1)
+ return mb_get_class(p) >= 2;
+# endif
+ return (GET_CHARTAB(buf, *p) != 0);
+}
+#endif
+
+/*
+ * return TRUE if 'c' is a valid file-name character
+ * Assume characters above 0x100 are valid (multi-byte).
+ */
+ int
+vim_isfilec(c)
+ int c;
+{
+ return (c >= 0x100 || (c > 0 && (chartab[c] & CT_FNAME_CHAR)));
+}
+
+/*
+ * return TRUE if 'c' is a printable character
+ * Assume characters above 0x100 are printable (multi-byte), except for
+ * Unicode.
+ */
+ int
+vim_isprintc(c)
+ int c;
+{
+#ifdef FEAT_MBYTE
+ if (enc_utf8 && c >= 0x100)
+ return utf_printable(c);
+#endif
+ return (c >= 0x100 || (c > 0 && (chartab[c] & CT_PRINT_CHAR)));
+}
+
+/*
+ * Strict version of vim_isprintc(c), don't return TRUE if "c" is the head
+ * byte of a double-byte character.
+ */
+ int
+vim_isprintc_strict(c)
+ int c;
+{
+#ifdef FEAT_MBYTE
+ if (enc_dbcs != 0 && c < 0x100 && MB_BYTE2LEN(c) > 1)
+ return FALSE;
+ if (enc_utf8 && c >= 0x100)
+ return utf_printable(c);
+#endif
+ return (c >= 0x100 || (c > 0 && (chartab[c] & CT_PRINT_CHAR)));
+}
+
+/*
+ * like chartabsize(), but also check for line breaks on the screen
+ */
+ int
+lbr_chartabsize(s, col)
+ unsigned char *s;
+ colnr_T col;
+{
+#ifdef FEAT_LINEBREAK
+ if (!curwin->w_p_lbr && *p_sbr == NUL)
+ {
+#endif
+#ifdef FEAT_MBYTE
+ if (curwin->w_p_wrap)
+ return win_nolbr_chartabsize(curwin, s, col, NULL);
+#endif
+ RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, s, col)
+#ifdef FEAT_LINEBREAK
+ }
+ return win_lbr_chartabsize(curwin, s, col, NULL);
+#endif
+}
+
+/*
+ * Call lbr_chartabsize() and advance the pointer.
+ */
+ int
+lbr_chartabsize_adv(s, col)
+ char_u **s;
+ colnr_T col;
+{
+ int retval;
+
+ retval = lbr_chartabsize(*s, col);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ *s += (*mb_ptr2len_check)(*s);
+ else
+#endif
+ ++*s;
+ return retval;
+}
+
+/*
+ * This function is used very often, keep it fast!!!!
+ *
+ * If "headp" not NULL, set *headp to the size of what we for 'showbreak'
+ * string at start of line. Warning: *headp is only set if it's a non-zero
+ * value, init to 0 before calling.
+ */
+/*ARGSUSED*/
+ int
+win_lbr_chartabsize(wp, s, col, headp)
+ win_T *wp;
+ char_u *s;
+ colnr_T col;
+ int *headp;
+{
+#ifdef FEAT_LINEBREAK
+ int c;
+ int size;
+ colnr_T col2;
+ colnr_T colmax;
+ int added;
+# ifdef FEAT_MBYTE
+ int mb_added = 0;
+# else
+# define mb_added 0
+# endif
+ int numberextra;
+ char_u *ps;
+ int tab_corr = (*s == TAB);
+
+ /*
+ * No 'linebreak' and 'showbreak': return quickly.
+ */
+ if (!wp->w_p_lbr && *p_sbr == NUL)
+#endif
+ {
+#ifdef FEAT_MBYTE
+ if (wp->w_p_wrap)
+ return win_nolbr_chartabsize(wp, s, col, headp);
+#endif
+ RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, s, col)
+ }
+
+#ifdef FEAT_LINEBREAK
+ /*
+ * First get normal size, without 'linebreak'
+ */
+ size = win_chartabsize(wp, s, col);
+ c = *s;
+
+ /*
+ * If 'linebreak' set check at a blank before a non-blank if the line
+ * needs a break here
+ */
+ if (wp->w_p_lbr
+ && vim_isbreak(c)
+ && !vim_isbreak(s[1])
+ && !wp->w_p_list
+ && wp->w_p_wrap
+# ifdef FEAT_VERTSPLIT
+ && wp->w_width != 0
+# endif
+ )
+ {
+ /*
+ * Count all characters from first non-blank after a blank up to next
+ * non-blank after a blank.
+ */
+ numberextra = win_col_off(wp);
+ col2 = col;
+ colmax = W_WIDTH(wp) - numberextra;
+ if (col >= colmax)
+ colmax += (((col - colmax)
+ / (colmax + win_col_off2(wp))) + 1)
+ * (colmax + win_col_off2(wp));
+ for (;;)
+ {
+ ps = s;
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ s += (*mb_ptr2len_check)(s);
+ else
+# endif
+ ++s;
+ c = *s;
+ if (!(c != NUL
+ && (vim_isbreak(c)
+ || (!vim_isbreak(c)
+ && (col2 == col || !vim_isbreak(*ps))))))
+ break;
+
+ col2 += win_chartabsize(wp, s, col2);
+ if (col2 >= colmax) /* doesn't fit */
+ {
+ size = colmax - col;
+ tab_corr = FALSE;
+ break;
+ }
+ }
+ }
+# ifdef FEAT_MBYTE
+ else if (has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1
+ && wp->w_p_wrap && in_win_border(wp, col))
+ {
+ ++size; /* Count the ">" in the last column. */
+ mb_added = 1;
+ }
+# endif
+
+ /*
+ * May have to add something for 'showbreak' string at start of line
+ * Set *headp to the size of what we add.
+ */
+ added = 0;
+ if (*p_sbr != NUL && wp->w_p_wrap && col != 0)
+ {
+ numberextra = win_col_off(wp);
+ col += numberextra + mb_added;
+ if (col >= (colnr_T)W_WIDTH(wp))
+ {
+ col -= W_WIDTH(wp);
+ numberextra = W_WIDTH(wp) - (numberextra - win_col_off2(wp));
+ if (numberextra > 0)
+ col = col % numberextra;
+ }
+ if (col == 0 || col + size > (colnr_T)W_WIDTH(wp))
+ {
+ added = vim_strsize(p_sbr);
+ if (tab_corr)
+ size += (added / wp->w_buffer->b_p_ts) * wp->w_buffer->b_p_ts;
+ else
+ size += added;
+ if (col != 0)
+ added = 0;
+ }
+ }
+ if (headp != NULL)
+ *headp = added + mb_added;
+ return size;
+#endif
+}
+
+#if defined(FEAT_MBYTE) || defined(PROTO)
+/*
+ * Like win_lbr_chartabsize(), except that we know 'linebreak' is off and
+ * 'wrap' is on. This means we need to check for a double-byte character that
+ * doesn't fit at the end of the screen line.
+ */
+ static int
+win_nolbr_chartabsize(wp, s, col, headp)
+ win_T *wp;
+ char_u *s;
+ colnr_T col;
+ int *headp;
+{
+ int n;
+
+ if (*s == TAB && (!wp->w_p_list || lcs_tab1))
+ {
+ n = wp->w_buffer->b_p_ts;
+ return (int)(n - (col % n));
+ }
+ n = ptr2cells(s);
+ /* Add one cell for a double-width character in the last column of the
+ * window, displayed with a ">". */
+ if (n == 2 && MB_BYTE2LEN(*s) > 1 && in_win_border(wp, col))
+ {
+ if (headp != NULL)
+ *headp = 1;
+ return 3;
+ }
+ return n;
+}
+
+/*
+ * Return TRUE if virtual column "vcol" is in the rightmost column of window
+ * "wp".
+ */
+ int
+in_win_border(wp, vcol)
+ win_T *wp;
+ colnr_T vcol;
+{
+ colnr_T width1; /* width of first line (after line number) */
+ colnr_T width2; /* width of further lines */
+
+#ifdef FEAT_VERTSPLIT
+ if (wp->w_width == 0) /* there is no border */
+ return FALSE;
+#endif
+ width1 = W_WIDTH(wp) - win_col_off(wp);
+ if (vcol < width1 - 1)
+ return FALSE;
+ if (vcol == width1 - 1)
+ return TRUE;
+ width2 = width1 + win_col_off2(wp);
+ return ((vcol - width1) % width2 == width2 - 1);
+}
+#endif /* FEAT_MBYTE */
+
+/*
+ * Get virtual column number of pos.
+ * start: on the first position of this character (TAB, ctrl)
+ * cursor: where the cursor is on this character (first char, except for TAB)
+ * end: on the last position of this character (TAB, ctrl)
+ *
+ * This is used very often, keep it fast!
+ */
+ void
+getvcol(wp, pos, start, cursor, end)
+ win_T *wp;
+ pos_T *pos;
+ colnr_T *start;
+ colnr_T *cursor;
+ colnr_T *end;
+{
+ colnr_T vcol;
+ char_u *ptr; /* points to current char */
+ char_u *posptr; /* points to char at pos->col */
+ int incr;
+ int head;
+ int ts = wp->w_buffer->b_p_ts;
+ int c;
+
+ vcol = 0;
+ ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
+ posptr = ptr + pos->col;
+
+ /*
+ * This function is used very often, do some speed optimizations.
+ * When 'list', 'linebreak' and 'showbreak' are not set use a simple loop.
+ * Also use this when 'list' is set but tabs take their normal size.
+ */
+ if ((!wp->w_p_list || lcs_tab1 != NUL)
+#ifdef FEAT_LINEBREAK
+ && !wp->w_p_lbr && *p_sbr == NUL
+#endif
+ )
+ {
+#ifndef FEAT_MBYTE
+ head = 0;
+#endif
+ for (;;)
+ {
+#ifdef FEAT_MBYTE
+ head = 0;
+#endif
+ c = *ptr;
+ /* make sure we don't go past the end of the line */
+ if (c == NUL)
+ {
+ incr = 1; /* NUL at end of line only takes one column */
+ break;
+ }
+ /* A tab gets expanded, depending on the current column */
+ if (c == TAB)
+ incr = ts - (vcol % ts);
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ /* For utf-8, if the byte is >= 0x80, need to look at
+ * further bytes to find the cell width. */
+ if (enc_utf8 && c >= 0x80)
+ incr = utf_ptr2cells(ptr);
+ else
+ incr = CHARSIZE(c);
+
+ /* If a double-cell char doesn't fit at the end of a line
+ * it wraps to the next line, it's like this char is three
+ * cells wide. */
+ if (incr == 2 && wp->w_p_wrap && in_win_border(wp, vcol))
+ {
+ ++incr;
+ head = 1;
+ }
+ }
+ else
+#endif
+ incr = CHARSIZE(c);
+ }
+
+ if (ptr >= posptr) /* character at pos->col */
+ break;
+
+ vcol += incr;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ ptr += (*mb_ptr2len_check)(ptr);
+ else
+#endif
+ ++ptr;
+ }
+ }
+ else
+ {
+ for (;;)
+ {
+ /* A tab gets expanded, depending on the current column */
+ head = 0;
+ incr = win_lbr_chartabsize(wp, ptr, vcol, &head);
+ /* make sure we don't go past the end of the line */
+ if (*ptr == NUL)
+ {
+ incr = 1; /* NUL at end of line only takes one column */
+ break;
+ }
+
+ if (ptr >= posptr) /* character at pos->col */
+ break;
+
+ vcol += incr;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ ptr += (*mb_ptr2len_check)(ptr);
+ else
+#endif
+ ++ptr;
+ }
+ }
+ if (start != NULL)
+ *start = vcol + head;
+ if (end != NULL)
+ *end = vcol + incr - 1;
+ if (cursor != NULL)
+ {
+ if (*ptr == TAB
+ && (State & NORMAL)
+ && !wp->w_p_list
+ && !virtual_active()
+#ifdef FEAT_VISUAL
+ && !(VIsual_active
+ && (*p_sel == 'e' || ltoreq(*pos, VIsual)))
+#endif
+ )
+ *cursor = vcol + incr - 1; /* cursor at end */
+ else
+ *cursor = vcol + head; /* cursor at start */
+ }
+}
+
+/*
+ * Get virtual cursor column in the current window, pretending 'list' is off.
+ */
+ colnr_T
+getvcol_nolist(posp)
+ pos_T *posp;
+{
+ int list_save = curwin->w_p_list;
+ colnr_T vcol;
+
+ curwin->w_p_list = FALSE;
+ getvcol(curwin, posp, NULL, &vcol, NULL);
+ curwin->w_p_list = list_save;
+ return vcol;
+}
+
+#if defined(FEAT_VIRTUALEDIT) || defined(PROTO)
+/*
+ * Get virtual column in virtual mode.
+ */
+ void
+getvvcol(wp, pos, start, cursor, end)
+ win_T *wp;
+ pos_T *pos;
+ colnr_T *start;
+ colnr_T *cursor;
+ colnr_T *end;
+{
+ colnr_T col;
+ colnr_T coladd;
+ colnr_T endadd;
+# ifdef FEAT_MBYTE
+ char_u *ptr;
+# endif
+
+ if (virtual_active())
+ {
+ /* For virtual mode, only want one value */
+ getvcol(wp, pos, &col, NULL, NULL);
+
+ coladd = pos->coladd;
+ endadd = 0;
+# ifdef FEAT_MBYTE
+ /* Cannot put the cursor on part of a wide character. */
+ ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
+ if (pos->col < STRLEN(ptr))
+ {
+ int c = (*mb_ptr2char)(ptr + pos->col);
+
+ if (c != TAB && vim_isprintc(c))
+ {
+ endadd = char2cells(c) - 1;
+ if (coladd >= endadd)
+ coladd -= endadd;
+ else
+ coladd = 0;
+ }
+ }
+# endif
+ col += coladd;
+ if (start != NULL)
+ *start = col;
+ if (cursor != NULL)
+ *cursor = col;
+ if (end != NULL)
+ *end = col + endadd;
+ }
+ else
+ getvcol(wp, pos, start, cursor, end);
+}
+#endif
+
+#if defined(FEAT_VISUAL) || defined(PROTO)
+/*
+ * Get the leftmost and rightmost virtual column of pos1 and pos2.
+ * Used for Visual block mode.
+ */
+ void
+getvcols(wp, pos1, pos2, left, right)
+ win_T *wp;
+ pos_T *pos1, *pos2;
+ colnr_T *left, *right;
+{
+ colnr_T from1, from2, to1, to2;
+
+ if (ltp(pos1, pos2))
+ {
+ getvvcol(wp, pos1, &from1, NULL, &to1);
+ getvvcol(wp, pos2, &from2, NULL, &to2);
+ }
+ else
+ {
+ getvvcol(wp, pos2, &from1, NULL, &to1);
+ getvvcol(wp, pos1, &from2, NULL, &to2);
+ }
+ if (from2 < from1)
+ *left = from2;
+ else
+ *left = from1;
+ if (to2 > to1)
+ {
+ if (*p_sel == 'e' && from2 - 1 >= to1)
+ *right = from2 - 1;
+ else
+ *right = to2;
+ }
+ else
+ *right = to1;
+}
+#endif
+
+/*
+ * skipwhite: skip over ' ' and '\t'.
+ */
+ char_u *
+skipwhite(p)
+ char_u *p;
+{
+ while (vim_iswhite(*p)) /* skip to next non-white */
+ ++p;
+ return p;
+}
+
+/*
+ * skipdigits: skip over digits;
+ */
+ char_u *
+skipdigits(p)
+ char_u *p;
+{
+ while (VIM_ISDIGIT(*p)) /* skip to next non-digit */
+ ++p;
+ return p;
+}
+
+/*
+ * Variant of isdigit() that can handle characters > 0x100.
+ * We don't use isdigit() here, because on some systems it also considers
+ * superscript 1 to be a digit.
+ * Use the VIM_ISDIGIT() macro for simple arguments.
+ */
+ int
+vim_isdigit(c)
+ int c;
+{
+ return (c >= '0' && c <= '9');
+}
+
+/*
+ * Variant of isxdigit() that can handle characters > 0x100.
+ * We don't use isxdigit() here, because on some systems it also considers
+ * superscript 1 to be a digit.
+ */
+ int
+vim_isxdigit(c)
+ int c;
+{
+ return (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'f')
+ || (c >= 'A' && c <= 'F');
+}
+
+/*
+ * skiptowhite: skip over text until ' ' or '\t' or NUL.
+ */
+ char_u *
+skiptowhite(p)
+ char_u *p;
+{
+ while (*p != ' ' && *p != '\t' && *p != NUL)
+ ++p;
+ return p;
+}
+
+#if defined(FEAT_LISTCMDS) || defined(FEAT_SIGNS) || defined(FEAT_SNIFF) \
+ || defined(PROTO)
+/*
+ * skiptowhite_esc: Like skiptowhite(), but also skip escaped chars
+ */
+ char_u *
+skiptowhite_esc(p)
+ char_u *p;
+{
+ while (*p != ' ' && *p != '\t' && *p != NUL)
+ {
+ if ((*p == '\\' || *p == Ctrl_V) && *(p + 1) != NUL)
+ ++p;
+ ++p;
+ }
+ return p;
+}
+#endif
+
+/*
+ * Getdigits: Get a number from a string and skip over it.
+ * Note: the argument is a pointer to a char_u pointer!
+ */
+ long
+getdigits(pp)
+ char_u **pp;
+{
+ char_u *p;
+ long retval;
+
+ p = *pp;
+ retval = atol((char *)p);
+ if (*p == '-') /* skip negative sign */
+ ++p;
+ p = skipdigits(p); /* skip to next non-digit */
+ *pp = p;
+ return retval;
+}
+
+/*
+ * Return TRUE if "lbuf" is empty or only contains blanks.
+ */
+ int
+vim_isblankline(lbuf)
+ char_u *lbuf;
+{
+ char_u *p;
+
+ p = skipwhite(lbuf);
+ return (*p == NUL || *p == '\r' || *p == '\n');
+}
+
+/*
+ * Convert a string into a long and/or unsigned long, taking care of
+ * hexadecimal and octal numbers.
+ * If "hexp" is not NULL, returns a flag to indicate the type of the number:
+ * 0 decimal
+ * '0' octal
+ * 'X' hex
+ * 'x' hex
+ * If "len" is not NULL, the length of the number in characters is returned.
+ * If "nptr" is not NULL, the signed result is returned in it.
+ * If "unptr" is not NULL, the unsigned result is returned in it.
+ */
+ void
+vim_str2nr(start, hexp, len, dooct, dohex, nptr, unptr)
+ char_u *start;
+ int *hexp; /* return: type of number 0 = decimal, 'x'
+ or 'X' is hex, '0' = octal */
+ int *len; /* return: detected length of number */
+ int dooct; /* recognize octal number */
+ int dohex; /* recognize hex number */
+ long *nptr; /* return: signed result */
+ unsigned long *unptr; /* return: unsigned result */
+{
+ char_u *ptr = start;
+ int hex = 0; /* default is decimal */
+ int negative = FALSE;
+ long n = 0;
+ unsigned long un = 0;
+
+ if (ptr[0] == '-')
+ {
+ negative = TRUE;
+ ++ptr;
+ }
+
+ if (ptr[0] == '0') /* could be hex or octal */
+ {
+ hex = ptr[1];
+ if (dohex && (hex == 'X' || hex == 'x') && vim_isxdigit(ptr[2]))
+ ptr += 2; /* hexadecimal */
+ else
+ {
+ if (dooct && VIM_ISDIGIT(hex))
+ hex = '0'; /* octal */
+ else
+ hex = 0; /* 0 by itself is decimal */
+ }
+ }
+
+ /*
+ * Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
+ */
+ if (hex)
+ {
+ if (hex == '0')
+ {
+ /* octal */
+ while ('0' <= *ptr && *ptr <= '7')
+ {
+ n = 8 * n + (long)(*ptr - '0');
+ un = 8 * un + (unsigned long)(*ptr - '0');
+ ++ptr;
+ }
+ }
+ else
+ {
+ /* hex */
+ while (vim_isxdigit(*ptr))
+ {
+ n = 16 * n + (long)hex2nr(*ptr);
+ un = 16 * un + (unsigned long)hex2nr(*ptr);
+ ++ptr;
+ }
+ }
+ }
+ else
+ {
+ /* decimal */
+ while (VIM_ISDIGIT(*ptr))
+ {
+ n = 10 * n + (long)(*ptr - '0');
+ un = 10 * un + (unsigned long)(*ptr - '0');
+ ++ptr;
+ }
+ }
+
+ if (!hex && negative) /* account for leading '-' for decimal numbers */
+ n = -n;
+
+ if (hexp != NULL)
+ *hexp = hex;
+ if (len != NULL)
+ *len = (int)(ptr - start);
+ if (nptr != NULL)
+ *nptr = n;
+ if (unptr != NULL)
+ *unptr = un;
+}
+
+/*
+ * Return the value of a single hex character.
+ * Only valid when the argument is '0' - '9', 'A' - 'F' or 'a' - 'f'.
+ */
+ int
+hex2nr(c)
+ int c;
+{
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return c - '0';
+}
+
+#if defined(FEAT_TERMRESPONSE) \
+ || (defined(FEAT_GUI_GTK) && defined(FEAT_WINDOWS)) || defined(PROTO)
+/*
+ * Convert two hex characters to a byte.
+ * Return -1 if one of the characters is not hex.
+ */
+ int
+hexhex2nr(p)
+ char_u *p;
+{
+ if (!vim_isxdigit(p[0]) || !vim_isxdigit(p[1]))
+ return -1;
+ return (hex2nr(p[0]) << 4) + hex2nr(p[1]);
+}
+#endif
+
+/*
+ * Return TRUE if "str" starts with a backslash that should be removed.
+ * For MS-DOS, WIN32 and OS/2 this is only done when the character after the
+ * backslash is not a normal file name character.
+ * '$' is a valid file name character, we don't remove the backslash before
+ * it. This means it is not possible to use an environment variable after a
+ * backslash. "C:\$VIM\doc" is taken literally, only "$VIM\doc" works.
+ * Although "\ name" is valid, the backslash in "Program\ files" must be
+ * removed. Assume a file name doesn't start with a space.
+ * For multi-byte names, never remove a backslash before a non-ascii
+ * character, assume that all multi-byte characters are valid file name
+ * characters.
+ */
+ int
+rem_backslash(str)
+ char_u *str;
+{
+#ifdef BACKSLASH_IN_FILENAME
+ return (str[0] == '\\'
+# ifdef FEAT_MBYTE
+ && str[1] < 0x80
+# endif
+ && (str[1] == ' '
+ || (str[1] != NUL
+ && str[1] != '*'
+ && str[1] != '?'
+ && !vim_isfilec(str[1]))));
+#else
+ return (str[0] == '\\' && str[1] != NUL);
+#endif
+}
+
+/*
+ * Halve the number of backslashes in a file name argument.
+ * For MS-DOS we only do this if the character after the backslash
+ * is not a normal file character.
+ */
+ void
+backslash_halve(p)
+ char_u *p;
+{
+ for ( ; *p; ++p)
+ if (rem_backslash(p))
+ STRCPY(p, p + 1);
+}
+
+/*
+ * backslash_halve() plus save the result in allocated memory.
+ */
+ char_u *
+backslash_halve_save(p)
+ char_u *p;
+{
+ char_u *res;
+
+ res = vim_strsave(p);
+ if (res == NULL)
+ return p;
+ backslash_halve(res);
+ return res;
+}
+
+#if (defined(EBCDIC) && defined(FEAT_POSTSCRIPT)) || defined(PROTO)
+/*
+ * Table for EBCDIC to ASCII conversion unashamedly taken from xxd.c!
+ * The first 64 entries have been added to map control characters defined in
+ * ascii.h
+ */
+static char_u ebcdic2ascii_tab[256] =
+{
+ 0000, 0001, 0002, 0003, 0004, 0011, 0006, 0177,
+ 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
+ 0020, 0021, 0022, 0023, 0024, 0012, 0010, 0027,
+ 0030, 0031, 0032, 0033, 0033, 0035, 0036, 0037,
+ 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
+ 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
+ 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
+ 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
+ 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
+ 0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174,
+ 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+ 0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176,
+ 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267,
+ 0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077,
+ 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
+ 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042,
+ 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
+ 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
+ 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
+ 0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320,
+ 0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170,
+ 0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327,
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+ 0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347,
+ 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
+ 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
+ 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
+ 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
+ 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
+ 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
+ 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377
+};
+
+/*
+ * Convert a buffer worth of characters from EBCDIC to ASCII. Only useful if
+ * wanting 7-bit ASCII characters out the other end.
+ */
+ void
+ebcdic2ascii(buffer, len)
+ char_u *buffer;
+ int len;
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ buffer[i] = ebcdic2ascii_tab[buffer[i]];
+}
+#endif
diff --git a/src/config.aap.in b/src/config.aap.in
new file mode 100644
index 000000000..7ec74d249
--- /dev/null
+++ b/src/config.aap.in
@@ -0,0 +1,115 @@
+# config.aap.in: recipe transformed into auto/config.aap by configure.
+
+VIMNAME = @VIMNAME@
+EXNAME = @EXNAME@
+VIEWNAME = @VIEWNAME@
+
+CC = @CC@
+DEFS = @DEFS@
+CONF_CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+srcdir = @srcdir@
+VPATH = @srcdir@
+CONF_LDFLAGS = @LDFLAGS@
+CONF_LIBS = @LIBS@
+TAGPRG = @TAGPRG@
+
+CPP = @CPP@
+CPP_MM = @CPP_MM@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS_DIR = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIB@
+
+PERL = @vi_cv_path_perl@
+PERLLIB = @vi_cv_perllib@
+PERL_LIBS = @PERL_LIBS@
+SHRPENV = @shrpenv@
+PERL_SRC = @PERL_SRC@
+PERL_OBJ = @PERL_OBJ@
+PERL_PRO = @PERL_PRO@
+PERL_CFLAGS = @PERL_CFLAGS@
+
+PYTHON_SRC = @PYTHON_SRC@
+PYTHON_OBJ = @PYTHON_OBJ@
+PYTHON_CFLAGS = @PYTHON_CFLAGS@
+PYTHON_LIBS = @PYTHON_LIBS@
+PYTHON_CONFDIR = @PYTHON_CONFDIR@
+PYTHON_GETPATH_CFLAGS = @PYTHON_GETPATH_CFLAGS@
+
+TCL = @vi_cv_path_tcl@
+TCL_SRC = @TCL_SRC@
+TCL_OBJ = @TCL_OBJ@
+TCL_PRO = @TCL_PRO@
+TCL_CFLAGS = @TCL_CFLAGS@
+TCL_LIBS = @TCL_LIBS@
+
+HANGULIN_SRC = @HANGULIN_SRC@
+HANGULIN_OBJ = @HANGULIN_OBJ@
+
+WORKSHOP_SRC = @WORKSHOP_SRC@
+WORKSHOP_OBJ = @WORKSHOP_OBJ@
+
+NETBEANS_SRC = @NETBEANS_SRC@
+NETBEANS_OBJ = @NETBEANS_OBJ@
+
+RUBY = @vi_cv_path_ruby@
+RUBY_SRC = @RUBY_SRC@
+RUBY_OBJ = @RUBY_OBJ@
+RUBY_PRO = @RUBY_PRO@
+RUBY_CFLAGS = @RUBY_CFLAGS@
+RUBY_LIBS = @RUBY_LIBS@
+
+SNIFF_SRC = @SNIFF_SRC@
+SNIFF_OBJ = @SNIFF_OBJ@
+
+AWK = @AWK@
+
+STRIP = @STRIP@
+
+EXEEXT = @EXEEXT@
+
+COMPILEDBY = @compiledby@
+
+INSTALLVIMDIFF = @dovimdiff@
+INSTALLGVIMDIFF = @dogvimdiff@
+
+### Line break character as octal number for "tr"
+NL = @line_break@
+
+### Top directory for everything
+# Can be overruled with "PREFIX=dir", thus delay using it.
+prefix = @prefix@
+
+### Top directory for the binary
+exec_prefix $= @exec_prefix@
+
+### Prefix for location of data files
+BINDIR $= @bindir@
+
+### Prefix for location of data files
+DATADIR $= @datadir@
+
+### Prefix for location of man pages
+MANDIR $= @mandir@
+
+### Do we have a GUI
+GUI = @GUITYPE@
+NARROW_PROTO = @NARROW_PROTO@
+GTK_LIBNAME = @GTK_LIBNAME@
+MOTIF_LIBNAME = @MOTIF_LIBNAME@
+GUI_INC_LOC = @GUI_INC_LOC@
+GUI_LIB_LOC = @GUI_LIB_LOC@
+GUI_X_LIBS = @GUI_X_LIBS@
+
+### Any OS dependent extra source and object file
+OS_EXTRA_SRC = @OS_EXTRA_SRC@
+OS_EXTRA_OBJ = @OS_EXTRA_OBJ@
+
+### If the *.po files are to be translated to *.mo files.
+MAKEMO = @MAKEMO@
+
+# Make sure that "make first" will run "make all" once configure has done its
+# work. This is needed when using the Makefile in the top directory.
+first: all
diff --git a/src/config.h.in b/src/config.h.in
new file mode 100644
index 000000000..bba26623c
--- /dev/null
+++ b/src/config.h.in
@@ -0,0 +1,361 @@
+/*
+ * config.h.in. Generated automatically from configure.in by autoheader, and
+ * manually changed after that.
+ */
+
+/* Define if we have EBCDIC code */
+#undef EBCDIC
+
+/* Define unless no X support found */
+#undef HAVE_X11
+
+/* Define when terminfo support found */
+#undef TERMINFO
+
+/* Define when termcap.h contains ospeed */
+#undef HAVE_OSPEED
+
+/* Define when ospeed can be extern */
+#undef OSPEED_EXTERN
+
+/* Define when termcap.h contains UP, BC and PC */
+#undef HAVE_UP_BC_PC
+
+/* Define when UP, BC and PC can be extern */
+#undef UP_BC_PC_EXTERN
+
+/* Define when termcap.h defines outfuntype */
+#undef HAVE_OUTFUNTYPE
+
+/* Define when __DATE__ " " __TIME__ can be used */
+#undef HAVE_DATE_TIME
+
+/* defined always when using configure */
+#undef UNIX
+
+/* Defined to the size of an int */
+#undef SIZEOF_INT
+
+/*
+ * If we cannot trust one of the following from the libraries, we use our
+ * own safe but probably slower vim_memmove().
+ */
+#undef USEBCOPY
+#undef USEMEMMOVE
+#undef USEMEMCPY
+
+/* Define when "man -s 2" is to be used */
+#undef USEMAN_S
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef mode_t
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef off_t
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef pid_t
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef ino_t
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef dev_t
+
+/* Define to `unsigned long' if <sys/types.h> doesn't define. */
+#undef rlim_t
+
+/* Define to `struct sigaltstack' if <signal.h> doesn't define. */
+#undef stack_t
+
+/* Define if stack_t has the ss_base field. */
+#undef HAVE_SS_BASE
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define if you can safely include both <sys/time.h> and <sys/select.h>. */
+#undef SYS_SELECT_WITH_SYS_TIME
+
+/* Define if you have /dev/ptc */
+#undef HAVE_DEV_PTC
+
+/* Define if you have Sys4 ptys */
+#undef HAVE_SVR4_PTYS
+
+/* Define to range of pty names to try */
+#undef PTYRANGE0
+#undef PTYRANGE1
+
+/* Define mode for pty */
+#undef PTYMODE
+
+/* Define group for pty */
+#undef PTYGROUP
+
+/* Define as the return type of signal handlers (int or void). */
+#undef RETSIGTYPE
+
+/* Define as the command at the end of signal handlers ("" or "return 0;"). */
+#undef SIGRETURN
+
+/* Define if struct sigcontext is present */
+#undef HAVE_SIGCONTEXT
+
+/* Define if touuper/tolower only work on lower/upercase characters */
+#undef BROKEN_TOUPPER
+
+/* Define if stat() ignores a trailing slash */
+#undef STAT_IGNORES_SLASH
+
+/* Define if tgetstr() has a second argument that is (char *) */
+#undef TGETSTR_CHAR_P
+
+/* Define if tgetent() returns zero for an error */
+#undef TGETENT_ZERO_ERR
+
+/* Define if the getcwd() function should not be used. */
+#undef BAD_GETCWD
+
+/* Define if you the function: */
+#undef HAVE_BCMP
+#undef HAVE_FCHDIR
+#undef HAVE_FCHOWN
+#undef HAVE_FSEEKO
+#undef HAVE_FSYNC
+#undef HAVE_FTELLO
+#undef HAVE_GETCWD
+#undef HAVE_GETPSEUDOTTY
+#undef HAVE_GETPWNAM
+#undef HAVE_GETPWUID
+#undef HAVE_GETRLIMIT
+#undef HAVE_GETTIMEOFDAY
+#undef HAVE_GETWD
+#undef HAVE_ICONV
+#undef HAVE_NL_LANGINFO_CODESET
+#undef HAVE_LSTAT
+#undef HAVE_MEMCMP
+#undef HAVE_MEMSET
+#undef HAVE_NANOSLEEP
+#undef HAVE_OPENDIR
+#undef HAVE_PUTENV
+#undef HAVE_QSORT
+#undef HAVE_READLINK
+#undef HAVE_RENAME
+#undef HAVE_SELECT
+#undef HAVE_SETENV
+#undef HAVE_SETPGID
+#undef HAVE_SETSID
+#undef HAVE_SIGACTION
+#undef HAVE_SIGALTSTACK
+#undef HAVE_SIGSET
+#undef HAVE_SIGSETJMP
+#undef HAVE_SIGSTACK
+#undef HAVE_SIGVEC
+#undef HAVE_SNPRINTF
+#undef HAVE_STRCASECMP
+#undef HAVE_STRERROR
+#undef HAVE_STRFTIME
+#undef HAVE_STRICMP
+#undef HAVE_STRNCASECMP
+#undef HAVE_STRNICMP
+#undef HAVE_STRPBRK
+#undef HAVE_STRTOL
+#undef HAVE_ST_BLKSIZE
+#undef HAVE_SYSCONF
+#undef HAVE_SYSCTL
+#undef HAVE_SYSINFO
+#undef HAVE_TGETENT
+#undef HAVE_TOWLOWER
+#undef HAVE_TOWUPPER
+#undef HAVE_USLEEP
+#undef HAVE_UTIME
+#undef HAVE_BIND_TEXTDOMAIN_CODESET
+
+/* Define if you do not have utime(), but do have the utimes() function. */
+#undef HAVE_UTIMES
+
+/* Define if you have the header file: */
+#undef HAVE_DIRENT_H
+#undef HAVE_ERRNO_H
+#undef HAVE_FCNTL_H
+#undef HAVE_FRAME_H
+#undef HAVE_ICONV_H
+#undef HAVE_LANGINFO_H
+#undef HAVE_LIBC_H
+#undef HAVE_LIBGEN_H
+#undef HAVE_LIBINTL_H
+#undef HAVE_LOCALE_H
+#undef HAVE_NDIR_H
+#undef HAVE_POLL_H
+#undef HAVE_PTHREAD_NP_H
+#undef HAVE_PWD_H
+#undef HAVE_SETJMP_H
+#undef HAVE_SGTTY_H
+#undef HAVE_STRINGS_H
+#undef HAVE_STROPTS_H
+#undef HAVE_SYS_ACCESS_H
+#undef HAVE_SYS_ACL_H
+#undef HAVE_SYS_DIR_H
+#undef HAVE_SYS_IOCTL_H
+#undef HAVE_SYS_NDIR_H
+#undef HAVE_SYS_PARAM_H
+#undef HAVE_SYS_POLL_H
+#undef HAVE_SYS_PTEM_H
+#undef HAVE_SYS_RESOURCE_H
+#undef HAVE_SYS_SELECT_H
+#undef HAVE_SYS_STATFS_H
+#undef HAVE_SYS_STREAM_H
+#undef HAVE_SYS_SYSCTL_H
+#undef HAVE_SYS_SYSINFO_H
+#undef HAVE_SYS_SYSTEMINFO_H
+#undef HAVE_SYS_TIME_H
+#undef HAVE_SYS_UTSNAME_H
+#undef HAVE_WCHAR_H
+#undef HAVE_TERMCAP_H
+#undef HAVE_TERMIOS_H
+#undef HAVE_TERMIO_H
+#undef HAVE_UNISTD_H
+#undef HAVE_UTIL_DEBUG_H
+#undef HAVE_UTIL_MSGI18N_H
+#undef HAVE_UTIME_H
+#undef HAVE_X11_SUNKEYSYM_H
+#undef HAVE_XM_XM_H
+#undef HAVE_XM_XPMP_H
+#undef HAVE_X11_XPM_H
+#undef HAVE_X11_XMU_EDITRES_H
+#undef HAVE_X11_SM_SMLIB_H
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define if you have a <sys/wait.h> that is not POSIX.1 compatible. */
+#undef HAVE_UNION_WAIT
+
+/* This is currently unused in vim: */
+/* Define if you have the ANSI C header files. */
+/* #undef STDC_HEADERS */
+
+/* instead, we check a few STDC things ourselves */
+#undef HAVE_STDARG_H
+#undef HAVE_STDLIB_H
+#undef HAVE_STRING_H
+
+/* Define if strings.h cannot be included when strings.h already is */
+#undef NO_STRINGS_WITH_STRING_H
+
+/* Define if you want tiny features. */
+#undef FEAT_TINY
+
+/* Define if you want small features. */
+#undef FEAT_SMALL
+
+/* Define if you want normal features. */
+#undef FEAT_NORMAL
+
+/* Define if you want big features. */
+#undef FEAT_BIG
+
+/* Define if you want huge features. */
+#undef FEAT_HUGE
+
+/* Define if you want to include the Perl interpreter. */
+#undef FEAT_PERL
+
+/* Define if you want to include the Python interpreter. */
+#undef FEAT_PYTHON
+
+/* Define if you want to include the Ruby interpreter. */
+#undef FEAT_RUBY
+
+/* Define if you want to include the Tcl interpreter. */
+#undef FEAT_TCL
+
+/* Define if you want to include the Sniff interface. */
+#undef FEAT_SNIFF
+
+/* Define if you want to add support for ACL */
+#undef HAVE_POSIX_ACL
+#undef HAVE_SOLARIS_ACL
+#undef HAVE_AIX_ACL
+
+/* Define if you want to add support of GPM (Linux console mouse daemon) */
+#undef HAVE_GPM
+
+/* Define if you want to include the Cscope interface. */
+#undef FEAT_CSCOPE
+
+/* Define if you want to include multibyte support. */
+#undef FEAT_MBYTE
+
+/* Define if you want to include fontset support. */
+#undef FEAT_XFONTSET
+
+/* Define if you want to include XIM support. */
+#undef FEAT_XIM
+
+/* Define if you want to include Hangul input support. */
+#undef FEAT_HANGULIN
+
+/* Define if you use GTK and want GNOME support. */
+#undef FEAT_GUI_GNOME
+
+/* Define if GTK+ 2 is available. */
+#undef HAVE_GTK2
+
+/* Define if GTK+ multihead support is available (requires GTK+ >= 2.1.1). */
+#undef HAVE_GTK_MULTIHEAD
+
+/* Define if your X has own locale library */
+#undef X_LOCALE
+
+/* Define if we have dlfcn.h. */
+#undef HAVE_DLFCN_H
+
+/* Define if there is a working gettext(). */
+#undef HAVE_GETTEXT
+
+/* Define if _nl_msg_cat_cntr is present. */
+#undef HAVE_NL_MSG_CAT_CNTR
+
+/* Define if we have dlopen() */
+#undef HAVE_DLOPEN
+
+/* Define if we have dlsym() */
+#undef HAVE_DLSYM
+
+/* Define if we have dl.h. */
+#undef HAVE_DL_H
+
+/* Define if we have shl_load() */
+#undef HAVE_SHL_LOAD
+
+/* Define if you want to include Sun Visual Workshop support. */
+#undef FEAT_SUN_WORKSHOP
+
+/* Define if you want to include NetBeans integration. */
+#undef FEAT_NETBEANS_INTG
+
+/* Define default global runtime path */
+#undef RUNTIME_GLOBAL
+
+/* Define name of who modified a released Vim */
+#undef MODIFIED_BY
+
+/* Define if you want XSMP interaction as well as vanilla swapfile safety */
+#undef USE_XSMP_INTERACT
+
+/* Define if vsnprintf() works */
+#undef HAVE_VSNPRINTF
diff --git a/src/config.mk.dist b/src/config.mk.dist
new file mode 100644
index 000000000..fa7c10850
--- /dev/null
+++ b/src/config.mk.dist
@@ -0,0 +1,5 @@
+the first targets to make vim are: scratch config myself
+srcdir = .
+VIMNAME = vim
+EXNAME = ex
+VIEWNAME = view
diff --git a/src/config.mk.in b/src/config.mk.in
new file mode 100644
index 000000000..046649921
--- /dev/null
+++ b/src/config.mk.in
@@ -0,0 +1,137 @@
+#
+# config.mk.in -- autoconf template for Vim on Unix vim:ts=8:sw=8:
+#
+# DO NOT EDIT config.mk!! It will be overwritten by configure.
+# Edit Makefile and run "make" or run ./configure with other arguments.
+#
+# Configure does not edit the makefile directly. This method is not the
+# standard use of GNU autoconf, but it has two advantages:
+# a) The user can override every choice made by configure.
+# b) Modifications to the makefile are not lost when configure is run.
+#
+# I hope this is worth being nonstandard. jw.
+
+@SET_MAKE@
+
+VIMNAME = @VIMNAME@
+EXNAME = @EXNAME@
+VIEWNAME = @VIEWNAME@
+
+CC = @CC@
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+srcdir = @srcdir@
+VPATH = @srcdir@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+TAGPRG = @TAGPRG@
+
+CPP = @CPP@
+CPP_MM = @CPP_MM@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS_DIR = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIB@
+
+PERL = @vi_cv_path_perl@
+PERLLIB = @vi_cv_perllib@
+PERL_LIBS = @PERL_LIBS@
+SHRPENV = @shrpenv@
+PERL_SRC = @PERL_SRC@
+PERL_OBJ = @PERL_OBJ@
+PERL_PRO = @PERL_PRO@
+PERL_CFLAGS = @PERL_CFLAGS@
+
+PYTHON_SRC = @PYTHON_SRC@
+PYTHON_OBJ = @PYTHON_OBJ@
+PYTHON_CFLAGS = @PYTHON_CFLAGS@
+PYTHON_LIBS = @PYTHON_LIBS@
+PYTHON_CONFDIR = @PYTHON_CONFDIR@
+PYTHON_GETPATH_CFLAGS = @PYTHON_GETPATH_CFLAGS@
+
+TCL = @vi_cv_path_tcl@
+TCL_SRC = @TCL_SRC@
+TCL_OBJ = @TCL_OBJ@
+TCL_PRO = @TCL_PRO@
+TCL_CFLAGS = @TCL_CFLAGS@
+TCL_LIBS = @TCL_LIBS@
+
+HANGULIN_SRC = @HANGULIN_SRC@
+HANGULIN_OBJ = @HANGULIN_OBJ@
+
+WORKSHOP_SRC = @WORKSHOP_SRC@
+WORKSHOP_OBJ = @WORKSHOP_OBJ@
+
+NETBEANS_SRC = @NETBEANS_SRC@
+NETBEANS_OBJ = @NETBEANS_OBJ@
+
+RUBY = @vi_cv_path_ruby@
+RUBY_SRC = @RUBY_SRC@
+RUBY_OBJ = @RUBY_OBJ@
+RUBY_PRO = @RUBY_PRO@
+RUBY_CFLAGS = @RUBY_CFLAGS@
+RUBY_LIBS = @RUBY_LIBS@
+
+SNIFF_SRC = @SNIFF_SRC@
+SNIFF_OBJ = @SNIFF_OBJ@
+
+AWK = @AWK@
+
+STRIP = @STRIP@
+
+EXEEXT = @EXEEXT@
+
+COMPILEDBY = @compiledby@
+
+INSTALLVIMDIFF = @dovimdiff@
+INSTALLGVIMDIFF = @dogvimdiff@
+
+### Line break character as octal number for "tr"
+NL = @line_break@
+
+### Top directory for everything
+prefix = @prefix@
+
+### Top directory for the binary
+exec_prefix = @exec_prefix@
+
+### Prefix for location of data files
+BINDIR = @bindir@
+
+### Prefix for location of data files
+DATADIR = @datadir@
+
+### Prefix for location of man pages
+MANDIR = @mandir@
+
+### Do we have a GUI
+GUI_INC_LOC = @GUI_INC_LOC@
+GUI_LIB_LOC = @GUI_LIB_LOC@
+GUI_SRC = $(@GUITYPE@_SRC)
+GUI_OBJ = $(@GUITYPE@_OBJ)
+GUI_DEFS = $(@GUITYPE@_DEFS)
+GUI_IPATH = $(@GUITYPE@_IPATH)
+GUI_LIBS_DIR = $(@GUITYPE@_LIBS_DIR)
+GUI_LIBS1 = $(@GUITYPE@_LIBS1)
+GUI_LIBS2 = $(@GUITYPE@_LIBS2)
+GUI_INSTALL = $(@GUITYPE@_INSTALL)
+GUI_TARGETS = $(@GUITYPE@_TARGETS)
+GUI_MAN_TARGETS = $(@GUITYPE@_MAN_TARGETS)
+GUI_TESTTARGET = $(@GUITYPE@_TESTTARGET)
+NARROW_PROTO = @NARROW_PROTO@
+GUI_X_LIBS = @GUI_X_LIBS@
+MOTIF_LIBNAME = @MOTIF_LIBNAME@
+GTK_LIBNAME = @GTK_LIBNAME@
+
+### Any OS dependent extra source and object file
+OS_EXTRA_SRC = @OS_EXTRA_SRC@
+OS_EXTRA_OBJ = @OS_EXTRA_OBJ@
+
+### If the *.po files are to be translated to *.mo files.
+MAKEMO = @MAKEMO@
+
+# Make sure that "make first" will run "make all" once configure has done its
+# work. This is needed when using the Makefile in the top directory.
+first: all
diff --git a/src/configure b/src/configure
new file mode 100755
index 000000000..be225eda6
--- /dev/null
+++ b/src/configure
@@ -0,0 +1,4 @@
+#! /bin/sh
+# run the automatically generated configure script
+CONFIG_STATUS=auto/config.status \
+ auto/configure "$@" --srcdir="${srcdir-.}" --cache-file=auto/config.cache
diff --git a/src/configure.in b/src/configure.in
new file mode 100644
index 000000000..2c23e0611
--- /dev/null
+++ b/src/configure.in
@@ -0,0 +1,2660 @@
+dnl configure.in: autoconf script for Vim
+
+dnl Process this file with autoconf 2.12 or 2.13 to produce "configure".
+dnl Should also work with autoconf 2.54 and later.
+
+AC_INIT(vim.h)
+AC_CONFIG_HEADER(auto/config.h:config.h.in)
+
+dnl Being able to run configure means the system is Unix (compatible).
+AC_DEFINE(UNIX)
+AC_PROG_MAKE_SET
+
+dnl Checks for programs.
+AC_PROG_CC dnl required by almost everything
+AC_PROG_CPP dnl required by header file checks
+AC_PROGRAM_EGREP dnl required by AC_EGREP_CPP
+AC_ISC_POSIX dnl required by AC_C_CROSS
+AC_PROG_AWK dnl required for "make html" in ../doc
+
+dnl Don't strip if we don't have it
+AC_CHECK_PROG(STRIP, strip, strip, :)
+
+dnl Check for extention of executables
+AC_EXEEXT
+
+dnl Set default value for CFLAGS if none is defined or it's empty
+if test -z "$CFLAGS"; then
+ CFLAGS="-O"
+ test "$GCC" = yes && CFLAGS="-O2 -fno-strength-reduce -Wall"
+fi
+if test "$GCC" = yes; then
+ gccversion=`"$CC" --version | sed -e '2,$d;s/^[[^0-9]]*\([[0-9]]\.[[0-9.]]*\).*$/\1/g'`
+ if test "$gccversion" = "3.0.1" -o "$gccversion" = "3.0.2"; then
+ echo 'GCC 3.0.x has a bug in the optimizer, disabling "-O#"'
+ CFLAGS=`echo "$CFLAGS" | sed 's/-O[[23456789]]/-O/'`
+ else
+ if test "$gccversion" = "3.1" -o "$gccversion" = "3.2" -o "$gccversion" = "3.2.1" && `echo "$CFLAGS" | grep -v fno-strength-reduce >/dev/null`; then
+ echo 'GCC 3.1 and 3.2 have a bug in the optimizer, adding "-fno-strength-reduce"'
+ CFLAGS="$CFLAGS -fno-strength-reduce"
+ fi
+ fi
+fi
+
+dnl If configure thinks we are cross compiling, there is probably something
+dnl wrong with the CC or CFLAGS settings, give an understandable error message
+if test "$cross_compiling" = yes; then
+ AC_MSG_ERROR([cannot compile a simple program, check CC and CFLAGS
+ (cross compiling doesn't work)])
+fi
+
+dnl gcc-cpp has the wonderful -MM option to produce nicer dependencies
+test "$GCC" = yes && CPP_MM=M; AC_SUBST(CPP_MM)
+
+if test -f ./toolcheck; then
+ AC_CHECKING(for buggy tools)
+ sh ./toolcheck 1>&AC_FD_MSG
+fi
+
+OS_EXTRA_SRC=""; OS_EXTRA_OBJ=""
+
+dnl Check for BeOS, which needs an extra source file
+AC_MSG_CHECKING(for BeOS)
+case `uname` in
+ BeOS) OS_EXTRA_SRC=os_beos.c; OS_EXTRA_OBJ=objects/os_beos.o
+ BEOS=yes; AC_MSG_RESULT(yes);;
+ *) BEOS=no; AC_MSG_RESULT(no);;
+esac
+
+dnl If QNX is found, assume we don't want to use Xphoton
+dnl unless it was specifically asked for (--with-x)
+AC_MSG_CHECKING(for QNX)
+case `uname` in
+ QNX) OS_EXTRA_SRC=os_qnx.c; OS_EXTRA_OBJ=objects/os_qnx.o
+ test -z "$with_x" && with_x=no
+ QNX=yes; AC_MSG_RESULT(yes);;
+ *) QNX=no; AC_MSG_RESULT(no);;
+esac
+
+dnl Check for Darwin and MacOS X
+dnl We do a check for MacOS X in the very beginning because there
+dnl are a lot of other things we need to change besides GUI stuff
+DEFAULT_VIMNAME=vim
+AC_MSG_CHECKING([for Darwin (Mac OS X)])
+if test "`(uname) 2>/dev/null`" = Darwin; then
+ AC_MSG_RESULT(yes)
+
+ AC_MSG_CHECKING(--disable-darwin argument)
+ AC_ARG_ENABLE(darwin,
+ [ --disable-darwin Disable Darwin (Mac OS X) support.],
+ , [enable_darwin="yes"])
+ if test "$enable_darwin" = "yes"; then
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING(if Darwin files are there)
+ if test -f os_macosx.c; then
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT([no, Darwin support disabled])
+ enable_darwin=no
+ fi
+ else
+ AC_MSG_RESULT([yes, Darwin support excluded])
+ fi
+
+ if test "$enable_darwin" = "yes"; then
+ MACOSX=yes
+ OS_EXTRA_SCR="os_macosx.c";
+ OS_EXTRA_OBJ="objects/os_macosx.o"
+ CPPFLAGS="$CPPFLAGS -DMACOS_X_UNIX -I/Developer/Headers/FlatCarbon -no-cpp-precomp"
+
+ dnl If Carbon is found, assume we don't want X11
+ dnl unless it was specifically asked for (--with-x)
+ AC_CHECK_HEADER(Carbon/Carbon.h, CARBON=yes)
+ if test "x$CARBON" = "xyes"; then
+ if test -z "$with_x"; then
+ with_x=no
+ DEFAULT_VIMNAME=Vim
+ fi
+ fi
+ fi
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_SUBST(OS_EXTRA_SRC)
+AC_SUBST(OS_EXTRA_OBJ)
+
+dnl Add /usr/local/lib to $LDFLAGS and /usr/local/include to CFLAGS.
+dnl Only when the directory exists and it wasn't there yet.
+dnl For gcc don't do this when it is already in the default search path.
+have_local_include=''
+have_local_lib=''
+if test "$GCC" = yes; then
+ echo 'void f(){}' > conftest.c
+ dnl -no-cpp-precomp is needed for OS X 10.2 (Ben Fowler)
+ have_local_include=`${CC-cc} -no-cpp-precomp -c -v conftest.c 2>&1 | grep '/usr/local/include'`
+ have_local_lib=`${CC-cc} -c -v conftest.c 2>&1 | grep '/usr/local/lib'`
+ rm -f conftest.c conftest.o
+fi
+if test -z "$have_local_lib" -a -d /usr/local/lib; then
+ tt=`echo "$LDFLAGS" | sed -e 's+-L/usr/local/lib ++g' -e 's+-L/usr/local/lib$++g'`
+ if test "$tt" = "$LDFLAGS"; then
+ LDFLAGS="$LDFLAGS -L/usr/local/lib"
+ fi
+fi
+if test -z "$have_local_include" -a -d /usr/local/include; then
+ tt=`echo "$CPPFLAGS" | sed -e 's+-I/usr/local/include ++g' -e 's+-I/usr/local/include$++g'`
+ if test "$tt" = "$CPPFLAGS"; then
+ CPPFLAGS="$CPPFLAGS -I/usr/local/include"
+ fi
+fi
+
+AC_MSG_CHECKING(--with-vim-name argument)
+AC_ARG_WITH(vim-name, [ --with-vim-name=NAME what to call the Vim executable],
+ VIMNAME="$withval"; AC_MSG_RESULT($VIMNAME),
+ VIMNAME="$DEFAULT_VIMNAME"; AC_MSG_RESULT(Defaulting to $VIMNAME))
+AC_SUBST(VIMNAME)
+AC_MSG_CHECKING(--with-ex-name argument)
+AC_ARG_WITH(ex-name, [ --with-ex-name=NAME what to call the Ex executable],
+ EXNAME="$withval"; AC_MSG_RESULT($EXNAME),
+ EXNAME="ex"; AC_MSG_RESULT(Defaulting to ex))
+AC_SUBST(EXNAME)
+AC_MSG_CHECKING(--with-view-name argument)
+AC_ARG_WITH(view-name, [ --with-view-name=NAME what to call the View executable],
+ VIEWNAME="$withval"; AC_MSG_RESULT($VIEWNAME),
+ VIEWNAME="view"; AC_MSG_RESULT(Defaulting to view))
+AC_SUBST(VIEWNAME)
+
+AC_MSG_CHECKING(--with-global-runtime argument)
+AC_ARG_WITH(global-runtime, [ --with-global-runtime=DIR global runtime directory in 'runtimepath'],
+ AC_MSG_RESULT($withval); AC_DEFINE_UNQUOTED(RUNTIME_GLOBAL, "$withval"),
+ AC_MSG_RESULT(no))
+
+AC_MSG_CHECKING(--with-modified-by argument)
+AC_ARG_WITH(modified-by, [ --with-modified-by=NAME name of who modified a release version],
+ AC_MSG_RESULT($withval); AC_DEFINE_UNQUOTED(MODIFIED_BY, "$withval"),
+ AC_MSG_RESULT(no))
+
+dnl Check for EBCDIC stolen from the LYNX port to OS390 Unix
+AC_MSG_CHECKING(if character set is EBCDIC)
+AC_TRY_COMPILE([ ],
+[ /* TryCompile function for CharSet.
+ Treat any failure as ASCII for compatibility with existing art.
+ Use compile-time rather than run-time tests for cross-compiler
+ tolerance. */
+#if '0'!=240
+make an error "Character set is not EBCDIC"
+#endif ],
+[ # TryCompile action if true
+cf_cv_ebcdic=yes ],
+[ # TryCompile action if false
+cf_cv_ebcdic=no])
+# end of TryCompile ])
+# end of CacheVal CvEbcdic
+AC_MSG_RESULT($cf_cv_ebcdic)
+case "$cf_cv_ebcdic" in #(vi
+ yes) AC_DEFINE(EBCDIC)
+ line_break='"\\n"'
+ ;;
+ *) line_break='"\\012"';;
+esac
+AC_SUBST(line_break)
+
+if test "$cf_cv_ebcdic" = "yes"; then
+dnl If we have EBCDIC we most likley have OS390 Unix, let's test it!
+AC_MSG_CHECKING(for OS/390 Unix)
+case `uname` in
+ OS/390) OS390Unix="yes";
+ dnl If using cc the environment variable _CC_CCMODE must be
+ dnl set to "1", so that some compiler extensions are enabled.
+ dnl If using c89 the environment variable is named _CC_C89MODE.
+ dnl Note: compile with c89 never tested.
+ if test "$CC" = "cc"; then
+ ccm="$_CC_CCMODE"
+ ccn="CC"
+ else
+ if test "$CC" = "c89"; then
+ ccm="$_CC_C89MODE"
+ ccn="C89"
+ else
+ ccm=1
+ fi
+ fi
+ if test "$ccm" != "1"; then
+ echo ""
+ echo "------------------------------------------"
+ echo " On OS/390 Unix, the environment variable"
+ echo " __CC_${ccn}MODE must be set to \"1\"!"
+ echo " Do:"
+ echo " export _CC_${ccn}MODE=1"
+ echo " and then call configure again."
+ echo "------------------------------------------"
+ exit 1
+ fi
+ CFLAGS="$CFLAGS -D_ALL_SOURCE"; LDFLAGS="$LDFLAGS -Wl,EDIT=NO"
+ AC_MSG_RESULT(yes)
+ ;;
+ *) OS390Unix="no";
+ AC_MSG_RESULT(no)
+ ;;
+esac
+fi
+
+
+dnl Check user requested features.
+
+AC_MSG_CHECKING(--with-features argument)
+AC_ARG_WITH(features, [ --with-features=TYPE tiny, small, normal, big or huge (default: normal)],
+ features="$withval"; AC_MSG_RESULT($features),
+ features="normal"; AC_MSG_RESULT(Defaulting to normal))
+
+dovimdiff=""
+dogvimdiff=""
+case "$features" in
+ tiny) AC_DEFINE(FEAT_TINY) ;;
+ small) AC_DEFINE(FEAT_SMALL) ;;
+ normal) AC_DEFINE(FEAT_NORMAL) dovimdiff="installvimdiff";
+ dogvimdiff="installgvimdiff" ;;
+ big) AC_DEFINE(FEAT_BIG) dovimdiff="installvimdiff";
+ dogvimdiff="installgvimdiff" ;;
+ huge) AC_DEFINE(FEAT_HUGE) dovimdiff="installvimdiff";
+ dogvimdiff="installgvimdiff" ;;
+ *) AC_MSG_RESULT([Sorry, $features is not supported]) ;;
+esac
+
+AC_SUBST(dovimdiff)
+AC_SUBST(dogvimdiff)
+
+AC_MSG_CHECKING(--with-compiledby argument)
+AC_ARG_WITH(compiledby, [ --with-compiledby=NAME name to show in :version message],
+ compiledby="$withval"; AC_MSG_RESULT($withval),
+ compiledby=""; AC_MSG_RESULT(no))
+AC_SUBST(compiledby)
+
+AC_MSG_CHECKING(--disable-xsmp argument)
+AC_ARG_ENABLE(xsmp,
+ [ --disable-xsmp Disable XSMP session management],
+ , enable_xsmp="yes")
+
+if test "$enable_xsmp" = "yes"; then
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING(--disable-xsmp-interact argument)
+ AC_ARG_ENABLE(xsmp-interact,
+ [ --disable-xsmp-interact Disable XSMP interaction],
+ , enable_xsmp_interact="yes")
+ if test "$enable_xsmp_interact" = "yes"; then
+ AC_MSG_RESULT(no)
+ AC_DEFINE(USE_XSMP_INTERACT)
+ else
+ AC_MSG_RESULT(yes)
+ fi
+else
+ AC_MSG_RESULT(yes)
+fi
+
+AC_MSG_CHECKING(--enable-perlinterp argument)
+AC_ARG_ENABLE(perlinterp,
+ [ --enable-perlinterp Include Perl interpreter.], ,
+ [enable_perlinterp="no"])
+AC_MSG_RESULT($enable_perlinterp)
+if test "$enable_perlinterp" = "yes"; then
+ AC_SUBST(vi_cv_path_perl)
+ AC_PATH_PROG(vi_cv_path_perl, perl)
+ if test "X$vi_cv_path_perl" != "X"; then
+ AC_MSG_CHECKING(Perl version)
+ if $vi_cv_path_perl -e 'require 5.003_01' >/dev/null 2>/dev/null; then
+ eval `$vi_cv_path_perl -V:usethreads`
+ if test "X$usethreads" = "XUNKNOWN" -o "X$usethreads" = "Xundef"; then
+ badthreads=no
+ else
+ if $vi_cv_path_perl -e 'require 5.6.0' >/dev/null 2>/dev/null; then
+ eval `$vi_cv_path_perl -V:use5005threads`
+ if test "X$use5005threads" = "XUNKNOWN" -o "X$use5005threads" = "Xundef"; then
+ badthreads=no
+ else
+ badthreads=yes
+ AC_MSG_RESULT(>>> Perl > 5.6 with 5.5 threads cannot be used <<<)
+ fi
+ else
+ badthreads=yes
+ AC_MSG_RESULT(>>> Perl 5.5 with threads cannot be used <<<)
+ fi
+ fi
+ if test $badthreads = no; then
+ AC_MSG_RESULT(OK)
+ eval `$vi_cv_path_perl -V:shrpenv`
+ if test "X$shrpenv" = "XUNKNOWN"; then # pre 5.003_04
+ shrpenv=""
+ fi
+ vi_cv_perllib=`$vi_cv_path_perl -MConfig -e 'print $Config{privlibexp}'`
+ AC_SUBST(vi_cv_perllib)
+ dnl Remove "-fno-something", it breaks using cproto.
+ perlcppflags=`$vi_cv_path_perl -Mlib=$srcdir -MExtUtils::Embed \
+ -e 'ccflags;perl_inc;print"\n"' | sed -e 's/-fno[[^ ]]*//'`
+ dnl Remove "-lc", it breaks on FreeBSD when using "-pthread".
+ perllibs=`cd $srcdir; $vi_cv_path_perl -MExtUtils::Embed -e 'ldopts' | \
+ sed -e '/Warning/d' -e '/Note (probably harmless)/d' \
+ -e 's/-bE:perl.exp//' -e 's/-lc //'`
+ dnl Don't add perl lib to $LIBS: if it's not in LD_LIBRARY_PATH
+ dnl a test in configure may fail because of that.
+ perlldflags=`cd $srcdir; $vi_cv_path_perl -MExtUtils::Embed \
+ -e 'ccdlflags' | sed -e 's/-bE:perl.exp//'`
+
+ dnl check that compiling a simple program still works with the flags
+ dnl added for Perl.
+ AC_MSG_CHECKING([if compile and link flags for Perl are sane])
+ cflags_save=$CFLAGS
+ libs_save=$LIBS
+ ldflags_save=$LDFLAGS
+ CFLAGS="$CFLAGS $perlcppflags"
+ LIBS="$LIBS $perllibs"
+ LDFLAGS="$perlldflags $LDFLAGS"
+ AC_TRY_LINK(,[ ],
+ AC_MSG_RESULT(yes); perl_ok=yes,
+ AC_MSG_RESULT(no: PERL DISABLED); perl_ok=no)
+ CFLAGS=$cflags_save
+ LIBS=$libs_save
+ LDFLAGS=$ldflags_save
+ if test $perl_ok = yes; then
+ if test "X$perlcppflags" != "X"; then
+ PERL_CFLAGS="$perlcppflags"
+ fi
+ if test "X$perlldflags" != "X"; then
+ LDFLAGS="$perlldflags $LDFLAGS"
+ fi
+ PERL_LIBS=$perllibs
+ PERL_SRC="auto/if_perl.c if_perlsfio.c"
+ PERL_OBJ="objects/if_perl.o objects/if_perlsfio.o"
+ PERL_PRO="if_perl.pro if_perlsfio.pro"
+ AC_DEFINE(FEAT_PERL)
+ fi
+ fi
+ else
+ AC_MSG_RESULT(>>> too old; need Perl version 5.003_01 or later <<<)
+ fi
+ fi
+
+ if test "x$MACOSX" = "xyes"; then
+ dnl Mac OS X 10.2 or 10.3
+ dir=/System/Library/Perl
+ darwindir=$dir/darwin
+ if test -d $darwindir; then
+ PERL=/usr/bin/perl
+ else
+ dnl Mac OS X 10.3
+ dir=/System/Library/Perl/5.8.1
+ darwindir=$dir/darwin-thread-multi-2level
+ if test -d $darwindir; then
+ PERL=/usr/bin/perl
+ fi
+ fi
+ if test -n "$PERL"; then
+ PERL_DIR="$dir"
+ PERL_CFLAGS="-DFEAT_PERL -I$darwindir/CORE"
+ PERL_OBJ="objects/if_perl.o objects/if_perlsfio.o $darwindir/auto/DynaLoader/DynaLoader.a"
+ PERL_LIBS="-L$darwindir/CORE -lperl"
+ fi
+ fi
+fi
+AC_SUBST(shrpenv)
+AC_SUBST(PERL_SRC)
+AC_SUBST(PERL_OBJ)
+AC_SUBST(PERL_PRO)
+AC_SUBST(PERL_CFLAGS)
+AC_SUBST(PERL_LIBS)
+
+AC_MSG_CHECKING(--enable-pythoninterp argument)
+AC_ARG_ENABLE(pythoninterp,
+ [ --enable-pythoninterp Include Python interpreter.], ,
+ [enable_pythoninterp="no"])
+AC_MSG_RESULT($enable_pythoninterp)
+if test "$enable_pythoninterp" = "yes"; then
+ dnl -- find the python executable
+ AC_PATH_PROG(vi_cv_path_python, python)
+ if test "X$vi_cv_path_python" != "X"; then
+
+ dnl -- get its version number
+ AC_CACHE_CHECK(Python version,vi_cv_var_python_version,
+ [[vi_cv_var_python_version=`
+ ${vi_cv_path_python} -c 'import sys; print sys.version[:3]'`
+ ]])
+
+ dnl -- it must be at least version 1.4
+ AC_MSG_CHECKING(Python is 1.4 or better)
+ if ${vi_cv_path_python} -c \
+ "import sys; sys.exit(${vi_cv_var_python_version} < 1.4)"
+ then
+ AC_MSG_RESULT(yep)
+
+ dnl -- find where python thinks it was installed
+ AC_CACHE_CHECK(Python's install prefix,vi_cv_path_python_pfx,
+ [ vi_cv_path_python_pfx=`
+ ${vi_cv_path_python} -c \
+ "import sys; print sys.prefix"` ])
+
+ dnl -- and where it thinks it runs
+ AC_CACHE_CHECK(Python's execution prefix,vi_cv_path_python_epfx,
+ [ vi_cv_path_python_epfx=`
+ ${vi_cv_path_python} -c \
+ "import sys; print sys.exec_prefix"` ])
+
+ dnl -- python's internal library path
+
+ AC_CACHE_VAL(vi_cv_path_pythonpath,
+ [ vi_cv_path_pythonpath=`
+ unset PYTHONPATH;
+ ${vi_cv_path_python} -c \
+ "import sys, string; print string.join(sys.path,':')"` ])
+
+ dnl -- where the Python implementation library archives are
+
+ AC_ARG_WITH(python-config-dir,
+ [ --with-python-config-dir=PATH Python's config directory],
+ [ vi_cv_path_python_conf="${withval}" ] )
+
+ AC_CACHE_CHECK(Python's configuration directory,vi_cv_path_python_conf,
+ [
+ vi_cv_path_python_conf=
+ for path in "${vi_cv_path_python_pfx}" "${vi_cv_path_python_epfx}"; do
+ for subdir in lib share; do
+ d="${path}/${subdir}/python${vi_cv_var_python_version}/config"
+ if test -d "$d" && test -f "$d/config.c"; then
+ vi_cv_path_python_conf="$d"
+ fi
+ done
+ done
+ ])
+
+ PYTHON_CONFDIR="${vi_cv_path_python_conf}"
+
+ if test "X$PYTHON_CONFDIR" = "X"; then
+ AC_MSG_RESULT([can't find it!])
+ else
+
+ dnl -- we need to examine Python's config/Makefile too
+ dnl see what the interpreter is built from
+ AC_CACHE_VAL(vi_cv_path_python_plibs,
+ [
+ tmp_mkf="/tmp/Makefile-conf$$"
+ cat ${PYTHON_CONFDIR}/Makefile - <<'eof' >${tmp_mkf}
+__:
+ @echo "python_MODLIBS='$(MODLIBS)'"
+ @echo "python_LIBS='$(LIBS)'"
+ @echo "python_SYSLIBS='$(SYSLIBS)'"
+ @echo "python_LINKFORSHARED='$(LINKFORSHARED)'"
+eof
+ dnl -- delete the lines from make about Entering/Leaving directory
+ eval "`cd ${PYTHON_CONFDIR} && make -f ${tmp_mkf} __ | sed '/ directory /d'`"
+ rm -f ${tmp_mkf}
+ if test "x$MACOSX" = "xyes" && ${vi_cv_path_python} -c \
+ "import sys; sys.exit(${vi_cv_var_python_version} < 2.3)"; then
+ vi_cv_path_python_plibs="-framework Python"
+ else
+ if test "${vi_cv_var_python_version}" = "1.4"; then
+ vi_cv_path_python_plibs="${PYTHON_CONFDIR}/libModules.a ${PYTHON_CONFDIR}/libPython.a ${PYTHON_CONFDIR}/libObjects.a ${PYTHON_CONFDIR}/libParser.a"
+ else
+ vi_cv_path_python_plibs="-L${PYTHON_CONFDIR} -lpython${vi_cv_var_python_version}"
+ fi
+ vi_cv_path_python_plibs="${vi_cv_path_python_plibs} ${python_MODLIBS} ${python_LIBS} ${python_SYSLIBS} ${python_LINKFORSHARED}"
+ dnl remove -ltermcap, it can conflict with an earlier -lncurses
+ vi_cv_path_python_plibs=`echo $vi_cv_path_python_plibs | sed s/-ltermcap//`
+ fi
+ ])
+
+ PYTHON_LIBS="${vi_cv_path_python_plibs}"
+ if test "${vi_cv_path_python_pfx}" = "${vi_cv_path_python_epfx}"; then
+ PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version}"
+ else
+ PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version} -I${vi_cv_path_python_epfx}/include/python${vi_cv_var_python_version}"
+ fi
+ PYTHON_SRC="if_python.c"
+ dnl For Mac OSX 10.2 config.o is included in the Python library.
+ if test "x$MACOSX" = "xyes"; then
+ PYTHON_OBJ="objects/if_python.o"
+ else
+ PYTHON_OBJ="objects/if_python.o objects/py_config.o"
+ fi
+ if test "${vi_cv_var_python_version}" = "1.4"; then
+ PYTHON_OBJ="$PYTHON_OBJ objects/py_getpath.o"
+ fi
+ PYTHON_GETPATH_CFLAGS="-DPYTHONPATH='\"${vi_cv_path_pythonpath}\"' -DPREFIX='\"${vi_cv_path_python_pfx}\"' -DEXEC_PREFIX='\"${vi_cv_path_python_epfx}\"'"
+
+ dnl On FreeBSD linking with "-pthread" is required to use threads.
+ dnl _THREAD_SAFE must be used for compiling then.
+ dnl The "-pthread" is added to $LIBS, so that the following check for
+ dnl sigaltstack() will look in libc_r (it's there in libc!).
+ dnl Otherwise, when using GCC, try adding -pthread to $CFLAGS. GCC
+ dnl will then define target-specific defines, e.g., -D_REENTRANT.
+ dnl Don't do this for Mac OSX, -pthread will generate a warning.
+ AC_MSG_CHECKING([if -pthread should be used])
+ threadsafe_flag=
+ thread_lib=
+ if test "x$MACOSX" != "xyes"; then
+ test "$GCC" = yes && threadsafe_flag="-pthread"
+ if test "`(uname) 2>/dev/null`" = FreeBSD; then
+ threadsafe_flag="-D_THREAD_SAFE"
+ thread_lib="-pthread"
+ fi
+ fi
+ libs_save_old=$LIBS
+ if test -n "$threadsafe_flag"; then
+ cflags_save=$CFLAGS
+ CFLAGS="$CFLAGS $threadsafe_flag"
+ LIBS="$LIBS $thread_lib"
+ AC_TRY_LINK(,[ ],
+ AC_MSG_RESULT(yes); PYTHON_CFLAGS="$PYTHON_CFLAGS $threadsafe_flag",
+ AC_MSG_RESULT(no); LIBS=$libs_save_old
+ )
+ CFLAGS=$cflags_save
+ else
+ AC_MSG_RESULT(no)
+ fi
+
+ dnl check that compiling a simple program still works with the flags
+ dnl added for Python.
+ AC_MSG_CHECKING([if compile and link flags for Python are sane])
+ cflags_save=$CFLAGS
+ libs_save=$LIBS
+ CFLAGS="$CFLAGS $PYTHON_CFLAGS"
+ LIBS="$LIBS $PYTHON_LIBS"
+ AC_TRY_LINK(,[ ],
+ AC_MSG_RESULT(yes); python_ok=yes,
+ AC_MSG_RESULT(no: PYTHON DISABLED); python_ok=no)
+ CFLAGS=$cflags_save
+ LIBS=$libs_save
+ if test $python_ok = yes; then
+ AC_DEFINE(FEAT_PYTHON)
+ else
+ LIBS=$libs_save_old
+ PYTHON_SRC=
+ PYTHON_OBJ=
+ PYTHON_LIBS=
+ PYTHON_CFLAGS=
+ fi
+
+ fi
+ else
+ AC_MSG_RESULT(too old)
+ fi
+ fi
+fi
+AC_SUBST(PYTHON_CONFDIR)
+AC_SUBST(PYTHON_LIBS)
+AC_SUBST(PYTHON_GETPATH_CFLAGS)
+AC_SUBST(PYTHON_CFLAGS)
+AC_SUBST(PYTHON_SRC)
+AC_SUBST(PYTHON_OBJ)
+
+AC_MSG_CHECKING(--enable-tclinterp argument)
+AC_ARG_ENABLE(tclinterp,
+ [ --enable-tclinterp Include Tcl interpreter.], ,
+ [enable_tclinterp="no"])
+AC_MSG_RESULT($enable_tclinterp)
+
+if test "$enable_tclinterp" = "yes"; then
+
+ dnl on FreeBSD tclsh is a silly script, look for tclsh8.0 or tclsh8.2
+ AC_MSG_CHECKING(--with-tclsh argument)
+ AC_ARG_WITH(tclsh, [ --with-tclsh=PATH which tclsh to use (default: tclsh8.0)],
+ tclsh_name="$withval"; AC_MSG_RESULT($tclsh_name),
+ tclsh_name="tclsh8.0"; AC_MSG_RESULT(no))
+ AC_PATH_PROG(vi_cv_path_tcl, $tclsh_name)
+ AC_SUBST(vi_cv_path_tcl)
+
+ dnl when no specific version specified, also try 8.2
+ if test "X$vi_cv_path_tcl" = "X" -a $tclsh_name = "tclsh8.0"; then
+ tclsh_name="tclsh8.2"
+ AC_PATH_PROG(vi_cv_path_tcl, $tclsh_name)
+ fi
+ dnl still didn't find it, try without version number
+ if test "X$vi_cv_path_tcl" = "X"; then
+ tclsh_name="tclsh"
+ AC_PATH_PROG(vi_cv_path_tcl, $tclsh_name)
+ fi
+ if test "X$vi_cv_path_tcl" != "X"; then
+ AC_MSG_CHECKING(Tcl version)
+ if echo 'exit [[expr [info tclversion] < 8.0]]' | $vi_cv_path_tcl - ; then
+ tclver=`echo 'puts [[info tclversion]]' | $vi_cv_path_tcl -`
+ AC_MSG_RESULT($tclver - OK);
+ tclloc=`echo 'set l [[info library]];set i [[string last lib $l]];incr i -2;puts [[string range $l 0 $i]]' | $vi_cv_path_tcl -`
+
+ AC_MSG_CHECKING(for location of Tcl include)
+ if test "x$MACOSX" != "xyes"; then
+ tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include"
+ else
+ dnl For Mac OS X 10.3, use the OS-provided framework location
+ tclinc="/System/Library/Frameworks/Tcl.framework/Headers"
+ fi
+ for try in $tclinc; do
+ if test -f "$try/tcl.h"; then
+ AC_MSG_RESULT($try/tcl.h)
+ TCL_INC=$try
+ break
+ fi
+ done
+ if test -z "$TCL_INC"; then
+ AC_MSG_RESULT(<not found>)
+ SKIP_TCL=YES
+ fi
+ if test -z "$SKIP_TCL"; then
+ AC_MSG_CHECKING(for location of tclConfig.sh script)
+ if test "x$MACOSX" != "xyes"; then
+ tclcnf=`echo $tclinc | sed s/include/lib/g`
+ else
+ dnl For Mac OS X 10.3, use the OS-provided framework location
+ tclcnf="/System/Library/Frameworks/Tcl.framework"
+ fi
+ for try in $tclcnf; do
+ if test -f $try/tclConfig.sh; then
+ AC_MSG_RESULT($try/tclConfig.sh)
+ . $try/tclConfig.sh
+ dnl use eval, because tcl 8.2 includes ${TCL_DBGX}
+ TCL_LIBS=`eval echo "$TCL_LIB_SPEC $TCL_LIBS"`
+ dnl Use $TCL_DEFS for -D_THREAD_SAFE et al. But only use the
+ dnl "-D_ABC" items.
+ TCL_DEFS=`echo $TCL_DEFS | tr ' ' '\012' | sed -e '/^-[[^D]]/d' -e '/-D[[^_]]/d' -e 's/-D_/ -D_/' | tr -d '\012'`
+ break
+ fi
+ done
+ if test -z "$TCL_LIBS"; then
+ AC_MSG_RESULT(<not found>)
+ AC_MSG_CHECKING(for Tcl library by myself)
+ tcllib=`echo $tclinc | sed s/include/lib/g`
+ for ext in .so .a ; do
+ for ver in "" $tclver ; do
+ for try in $tcllib ; do
+ trylib=tcl$ver$ext
+ if test -f $try/lib$trylib ; then
+ AC_MSG_RESULT($try/lib$trylib)
+ TCL_LIBS="-L$try -ltcl$ver -ldl -lm"
+ if test "`(uname) 2>/dev/null`" = SunOS &&
+ uname -r | grep '^5' >/dev/null; then
+ TCL_LIBS="$TCL_LIBS -R $try"
+ fi
+ break 3
+ fi
+ done
+ done
+ done
+ if test -z "$TCL_LIBS"; then
+ AC_MSG_RESULT(<not found>)
+ SKIP_TCL=YES
+ fi
+ fi
+ if test -z "$SKIP_TCL"; then
+ AC_DEFINE(FEAT_TCL)
+ TCL_SRC=if_tcl.c
+ TCL_OBJ=objects/if_tcl.o
+ TCL_PRO=if_tcl.pro
+ TCL_CFLAGS="-I$TCL_INC $TCL_DEFS"
+ fi
+ fi
+ else
+ AC_MSG_RESULT(too old; need Tcl version 8.0 or later)
+ fi
+ fi
+fi
+AC_SUBST(TCL_SRC)
+AC_SUBST(TCL_OBJ)
+AC_SUBST(TCL_PRO)
+AC_SUBST(TCL_CFLAGS)
+AC_SUBST(TCL_LIBS)
+
+AC_MSG_CHECKING(--enable-rubyinterp argument)
+AC_ARG_ENABLE(rubyinterp,
+ [ --enable-rubyinterp Include Ruby interpreter.], ,
+ [enable_rubyinterp="no"])
+AC_MSG_RESULT($enable_rubyinterp)
+if test "$enable_rubyinterp" = "yes"; then
+ AC_SUBST(vi_cv_path_ruby)
+ AC_PATH_PROG(vi_cv_path_ruby, ruby)
+ if test "X$vi_cv_path_ruby" != "X"; then
+ AC_MSG_CHECKING(Ruby version)
+ if $vi_cv_path_ruby -e 'VERSION >= "1.6.0" or exit 1' >/dev/null 2>/dev/null; then
+ AC_MSG_RESULT(OK)
+ AC_MSG_CHECKING(Ruby header files)
+ rubyhdrdir=`$vi_cv_path_ruby -r mkmf -e 'print Config::CONFIG[["archdir"]] || $hdrdir' 2>/dev/null`
+ if test "X$rubyhdrdir" != "X"; then
+ AC_MSG_RESULT($rubyhdrdir)
+ RUBY_CFLAGS="-I$rubyhdrdir"
+ rubylibs=`$vi_cv_path_ruby -r rbconfig -e 'print Config::CONFIG[["LIBS"]]'`
+ if test "X$rubylibs" != "X"; then
+ RUBY_LIBS="$rubylibs"
+ fi
+ librubyarg=`$vi_cv_path_ruby -r rbconfig -e 'print Config.expand(Config::CONFIG[["LIBRUBYARG"]])'`
+ if test -f "$rubyhdrdir/$librubyarg"; then
+ librubyarg="$rubyhdrdir/$librubyarg"
+ else
+ rubylibdir=`$vi_cv_path_ruby -r rbconfig -e 'print Config.expand(Config::CONFIG[["libdir"]])'`
+ if test -f "$rubylibdir/$librubyarg"; then
+ librubyarg="$rubylibdir/$librubyarg"
+ elif test "$librubyarg" = "libruby.a"; then
+ dnl required on Mac OS 10.3 where libruby.a doesn't exist
+ librubyarg="-lruby"
+ else
+ librubyarg=`$vi_cv_path_ruby -r rbconfig -e "print '$librubyarg'.gsub(/-L\./, %'-L#{Config.expand(Config::CONFIG[\"libdir\"])}')"`
+ fi
+ fi
+
+ if test "X$librubyarg" != "X"; then
+ RUBY_LIBS="$librubyarg $RUBY_LIBS"
+ fi
+ rubyldflags=`$vi_cv_path_ruby -r rbconfig -e 'print Config::CONFIG[["LDFLAGS"]]'`
+ if test "X$rubyldflags" != "X"; then
+ LDFLAGS="$rubyldflags $LDFLAGS"
+ fi
+ RUBY_SRC="if_ruby.c"
+ RUBY_OBJ="objects/if_ruby.o"
+ RUBY_PRO="if_ruby.pro"
+ AC_DEFINE(FEAT_RUBY)
+ else
+ AC_MSG_RESULT(not found, disabling Ruby)
+ fi
+ else
+ AC_MSG_RESULT(too old; need Ruby version 1.6.0 or later)
+ fi
+ fi
+fi
+AC_SUBST(RUBY_SRC)
+AC_SUBST(RUBY_OBJ)
+AC_SUBST(RUBY_PRO)
+AC_SUBST(RUBY_CFLAGS)
+AC_SUBST(RUBY_LIBS)
+
+AC_MSG_CHECKING(--enable-cscope argument)
+AC_ARG_ENABLE(cscope,
+ [ --enable-cscope Include cscope interface.], ,
+ [enable_cscope="no"])
+AC_MSG_RESULT($enable_cscope)
+if test "$enable_cscope" = "yes"; then
+ AC_DEFINE(FEAT_CSCOPE)
+fi
+
+AC_MSG_CHECKING(--enable-workshop argument)
+AC_ARG_ENABLE(workshop,
+ [ --enable-workshop Include Sun Visual Workshop support.], ,
+ [enable_workshop="no"])
+AC_MSG_RESULT($enable_workshop)
+if test "$enable_workshop" = "yes"; then
+ AC_DEFINE(FEAT_SUN_WORKSHOP)
+ WORKSHOP_SRC="workshop.c integration.c"
+ AC_SUBST(WORKSHOP_SRC)
+ WORKSHOP_OBJ="objects/workshop.o objects/integration.o"
+ AC_SUBST(WORKSHOP_OBJ)
+ if test "${enable_gui-xxx}" = xxx; then
+ enable_gui=motif
+ fi
+fi
+
+AC_MSG_CHECKING(--disable-netbeans argument)
+AC_ARG_ENABLE(netbeans,
+ [ --disable-netbeans Disable NetBeans integration support.],
+ , [enable_netbeans="yes"])
+if test "$enable_netbeans" = "yes"; then
+ AC_MSG_RESULT(no)
+ dnl On Solaris we need the socket and nsl library.
+ AC_CHECK_LIB(socket, socket)
+ AC_CHECK_LIB(nsl, gethostbyname)
+ AC_MSG_CHECKING(whether compiling netbeans integration is possible)
+ AC_TRY_LINK([
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+ /* Check bitfields */
+ struct nbbuf {
+ unsigned int initDone:1;
+ ushort signmaplen;
+ };
+ ], [
+ /* Check creating a socket. */
+ struct sockaddr_in server;
+ (void)socket(AF_INET, SOCK_STREAM, 0);
+ (void)htons(100);
+ (void)gethostbyname("microsoft.com");
+ if (errno == ECONNREFUSED)
+ (void)connect(1, (struct sockaddr *)&server, sizeof(server));
+ ],
+ AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no); enable_netbeans="no")
+else
+ AC_MSG_RESULT(yes)
+fi
+if test "$enable_netbeans" = "yes"; then
+ AC_DEFINE(FEAT_NETBEANS_INTG)
+ NETBEANS_SRC="netbeans.c"
+ AC_SUBST(NETBEANS_SRC)
+ NETBEANS_OBJ="objects/netbeans.o"
+ AC_SUBST(NETBEANS_OBJ)
+fi
+
+AC_MSG_CHECKING(--enable-sniff argument)
+AC_ARG_ENABLE(sniff,
+ [ --enable-sniff Include Sniff interface.], ,
+ [enable_sniff="no"])
+AC_MSG_RESULT($enable_sniff)
+if test "$enable_sniff" = "yes"; then
+ AC_DEFINE(FEAT_SNIFF)
+ SNIFF_SRC="if_sniff.c"
+ AC_SUBST(SNIFF_SRC)
+ SNIFF_OBJ="objects/if_sniff.o"
+ AC_SUBST(SNIFF_OBJ)
+fi
+
+AC_MSG_CHECKING(--enable-multibyte argument)
+AC_ARG_ENABLE(multibyte,
+ [ --enable-multibyte Include multibyte editing support.], ,
+ [enable_multibyte="no"])
+AC_MSG_RESULT($enable_multibyte)
+if test "$enable_multibyte" = "yes"; then
+ AC_DEFINE(FEAT_MBYTE)
+fi
+
+AC_MSG_CHECKING(--enable-hangulinput argument)
+AC_ARG_ENABLE(hangulinput,
+ [ --enable-hangulinput Include Hangul input support.], ,
+ [enable_hangulinput="no"])
+AC_MSG_RESULT($enable_hangulinput)
+
+AC_MSG_CHECKING(--enable-xim argument)
+AC_ARG_ENABLE(xim,
+ [ --enable-xim Include XIM input support.],
+ AC_MSG_RESULT($enable_xim),
+ [enable_xim="auto"; AC_MSG_RESULT(defaulting to auto)])
+dnl defining FEAT_XIM is delayed, so that it can be disabled for older GTK
+
+AC_MSG_CHECKING(--enable-fontset argument)
+AC_ARG_ENABLE(fontset,
+ [ --enable-fontset Include X fontset output support.], ,
+ [enable_fontset="no"])
+AC_MSG_RESULT($enable_fontset)
+dnl defining FEAT_XFONTSET is delayed, so that it can be disabled for no GUI
+
+test -z "$with_x" && with_x=yes
+test "${enable_gui-yes}" != no -a "x$MACOSX" != "xyes" -a "x$QNX" != "xyes" && with_x=yes
+if test "$with_x" = no; then
+ AC_MSG_RESULT(defaulting to: don't HAVE_X11)
+else
+ dnl Do this check early, so that its failure can override user requests.
+
+ AC_PATH_PROG(xmkmfpath, xmkmf)
+
+ AC_PATH_XTRA
+
+ dnl On OS390Unix the X libraries are DLLs. To use them the code must
+ dnl be compiled with a special option.
+ dnl Also add SM, ICE and Xmu to X_EXTRA_LIBS.
+ if test "$OS390Unix" = "yes"; then
+ CFLAGS="$CFLAGS -W c,dll"
+ LDFLAGS="$LDFLAGS -W l,dll"
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lSM -lICE -lXmu"
+ fi
+
+ dnl On my HPUX system the X include dir is found, but the lib dir not.
+ dnl This is a desparate try to fix this.
+
+ if test -d "$x_includes" && test ! -d "$x_libraries"; then
+ x_libraries=`echo "$x_includes" | sed s/include/lib/`
+ AC_MSG_RESULT(Corrected X libraries to $x_libraries)
+ X_LIBS="$X_LIBS -L$x_libraries"
+ if test "`(uname) 2>/dev/null`" = SunOS &&
+ uname -r | grep '^5' >/dev/null; then
+ X_LIBS="$X_LIBS -R $x_libraries"
+ fi
+ fi
+
+ if test -d "$x_libraries" && test ! -d "$x_includes"; then
+ x_includes=`echo "$x_libraries" | sed s/lib/include/`
+ AC_MSG_RESULT(Corrected X includes to $x_includes)
+ X_CFLAGS="$X_CFLAGS -I$x_includes"
+ fi
+
+ dnl Remove "-I/usr/include " from X_CFLAGS, should not be needed.
+ X_CFLAGS="`echo $X_CFLAGS\ | sed 's%-I/usr/include %%'`"
+ dnl Remove "-L/usr/lib " from X_LIBS, should not be needed.
+ X_LIBS="`echo $X_LIBS\ | sed 's%-L/usr/lib %%'`"
+ dnl Same for "-R/usr/lib ".
+ X_LIBS="`echo $X_LIBS\ | sed -e 's%-R/usr/lib %%' -e 's%-R /usr/lib %%'`"
+
+
+ dnl Check if the X11 header files are correctly installed. On some systems
+ dnl Xlib.h includes files that don't exist
+ AC_MSG_CHECKING(if X11 header files can be found)
+ cflags_save=$CFLAGS
+ CFLAGS="$CFLAGS $X_CFLAGS"
+ AC_TRY_COMPILE([#include <X11/Xlib.h>], ,
+ AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no); no_x=yes)
+ CFLAGS=$cflags_save
+
+ if test "${no_x-no}" = yes; then
+ with_x=no
+ else
+ AC_DEFINE(HAVE_X11)
+ X_LIB="-lXt -lX11";
+ AC_SUBST(X_LIB)
+
+ ac_save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="-L$x_libraries $LDFLAGS"
+
+ dnl Check for -lXdmcp (needed on SunOS 4.1.4)
+ dnl For HP-UX 10.20 it must be before -lSM -lICE
+ AC_CHECK_LIB(Xdmcp, _XdmcpAuthDoIt, [X_EXTRA_LIBS="$X_EXTRA_LIBS -lXdmcp"],,
+ [-lXt $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lXdmcp])
+
+ dnl Some systems need -lnsl -lsocket when testing for ICE.
+ dnl The check above doesn't do this, try here (again). Also needed to get
+ dnl them after Xdmcp. link.sh will remove them when not needed.
+ dnl Check for other function than above to avoid the cached value
+ AC_CHECK_LIB(ICE, IceOpenConnection,
+ [X_EXTRA_LIBS="$X_EXTRA_LIBS -lSM -lICE"],, [$X_EXTRA_LIBS])
+
+ dnl Check for -lXpm (needed for some versions of Motif)
+ LDFLAGS="$X_LIBS $ac_save_LDFLAGS"
+ AC_CHECK_LIB(Xpm, XpmCreatePixmapFromData, [X_PRE_LIBS="$X_PRE_LIBS -lXpm"],,
+ [-lXt $X_PRE_LIBS -lXpm -lX11 $X_EXTRA_LIBS])
+
+ dnl Check that the X11 header files don't use implicit declarations
+ AC_MSG_CHECKING(if X11 header files implicitly declare return values)
+ cflags_save=$CFLAGS
+ CFLAGS="$CFLAGS $X_CFLAGS -Werror"
+ AC_TRY_COMPILE([#include <X11/Xlib.h>], ,
+ AC_MSG_RESULT(no),
+ CFLAGS="$CFLAGS -Wno-implicit-int"
+ AC_TRY_COMPILE([#include <X11/Xlib.h>], ,
+ AC_MSG_RESULT(yes); cflags_save="$cflags_save -Wno-implicit-int",
+ AC_MSG_RESULT(test failed)
+ )
+ )
+ CFLAGS=$cflags_save
+
+ LDFLAGS="$ac_save_LDFLAGS"
+
+ fi
+fi
+
+test "x$with_x" = xno -a "x$BEOS" != "xyes" -a "x$MACOSX" != "xyes" -a "x$QNX" != "xyes" && enable_gui=no
+
+AC_MSG_CHECKING(--enable-gui argument)
+AC_ARG_ENABLE(gui,
+ [ --enable-gui[=OPTS] X11 GUI [default=auto] [OPTS=auto/no/gtk/gtk2/gnome/gnome2/motif/athena/neXtaw/beos/photon/carbon]], , enable_gui="auto")
+
+dnl Canonicalize the --enable-gui= argument so that it can be easily compared.
+dnl Do not use character classes for portability with old tools.
+enable_gui_canon=`echo "_$enable_gui" | \
+ sed 's/[[ _+-]]//g;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
+
+dnl Skip everything by default.
+SKIP_GTK=YES
+SKIP_GTK2=YES
+SKIP_GNOME=YES
+SKIP_MOTIF=YES
+SKIP_ATHENA=YES
+SKIP_NEXTAW=YES
+SKIP_PHOTON=YES
+SKIP_BEOS=YES
+SKIP_CARBON=YES
+GUITYPE=NONE
+
+if test "x$BEOS" = "xyes"; then
+ SKIP_BEOS=
+ case "$enable_gui_canon" in
+ no) AC_MSG_RESULT(no GUI support)
+ SKIP_BEOS=YES ;;
+ yes|"") AC_MSG_RESULT(yes - automatic GUI support) ;;
+ auto) AC_MSG_RESULT(auto - automatic GUI support) ;;
+ beos) AC_MSG_RESULT(BeOS GUI support) ;;
+ *) AC_MSG_RESULT([Sorry, $enable_gui GUI is not supported])
+ SKIP_BEOS=YES ;;
+ esac
+
+elif test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then
+ SKIP_PHOTON=
+ case "$enable_gui_canon" in
+ no) AC_MSG_RESULT(no GUI support)
+ SKIP_PHOTON=YES ;;
+ yes|"") AC_MSG_RESULT(yes - automatic GUI support) ;;
+ auto) AC_MSG_RESULT(auto - automatic GUI support) ;;
+ photon) AC_MSG_RESULT(Photon GUI support) ;;
+ *) AC_MSG_RESULT([Sorry, $enable_gui GUI is not supported])
+ SKIP_PHOTON=YES ;;
+ esac
+
+elif test "x$MACOSX" = "xyes" -a "x$with_x" = "xno" ; then
+ SKIP_CARBON=
+ case "$enable_gui_canon" in
+ no) AC_MSG_RESULT(no GUI support)
+ SKIP_CARBON=YES ;;
+ yes|"") AC_MSG_RESULT(yes - automatic GUI support) ;;
+ auto) AC_MSG_RESULT(auto - automatic GUI support) ;;
+ carbon) AC_MSG_RESULT(Carbon GUI support) ;;
+ *) AC_MSG_RESULT([Sorry, $enable_gui GUI is not supported])
+ SKIP_CARBON=YES ;;
+ esac
+
+else
+
+
+ case "$enable_gui_canon" in
+ no|none) AC_MSG_RESULT(no GUI support) ;;
+ yes|""|auto) AC_MSG_RESULT(yes/auto - automatic GUI support)
+ SKIP_GTK=
+ SKIP_GTK2=
+ SKIP_GNOME=
+ SKIP_MOTIF=
+ SKIP_ATHENA=
+ SKIP_NEXTAW=
+ SKIP_CARBON=;;
+ gtk) AC_MSG_RESULT(GTK+ 1.x GUI support)
+ SKIP_GTK=;;
+ gtk2) AC_MSG_RESULT(GTK+ 2.x GUI support)
+ SKIP_GTK=
+ SKIP_GTK2=;;
+ gnome) AC_MSG_RESULT(GNOME 1.x GUI support)
+ SKIP_GNOME=
+ SKIP_GTK=;;
+ gnome2) AC_MSG_RESULT(GNOME 2.x GUI support)
+ SKIP_GNOME=
+ SKIP_GTK=
+ SKIP_GTK2=;;
+ motif) AC_MSG_RESULT(Motif GUI support)
+ SKIP_MOTIF=;;
+ athena) AC_MSG_RESULT(Athena GUI support)
+ SKIP_ATHENA=;;
+ nextaw) AC_MSG_RESULT(neXtaw GUI support)
+ SKIP_NEXTAW=;;
+ *) AC_MSG_RESULT([Sorry, $enable_gui GUI is not supported]) ;;
+ esac
+
+fi
+
+if test "x$SKIP_GTK" != "xYES" -a "$enable_gui_canon" != "gtk" -a "$enable_gui_canon" != "gtk2"; then
+ AC_MSG_CHECKING(whether or not to look for GTK)
+ AC_ARG_ENABLE(gtk-check,
+ [ --enable-gtk-check If auto-select GUI, check for GTK [default=yes]],
+ , enable_gtk_check="yes")
+ AC_MSG_RESULT($enable_gtk_check)
+ if test "x$enable_gtk_check" = "xno"; then
+ SKIP_GTK=YES
+ SKIP_GNOME=YES
+ fi
+fi
+
+if test "x$SKIP_GTK2" != "xYES" -a "$enable_gui_canon" != "gtk2" \
+ -a "$enable_gui_canon" != "gnome2"; then
+ AC_MSG_CHECKING(whether or not to look for GTK+ 2)
+ AC_ARG_ENABLE(gtk2-check,
+ [ --enable-gtk2-check If GTK GUI, check for GTK+ 2 [default=yes]],
+ , enable_gtk2_check="yes")
+ AC_MSG_RESULT($enable_gtk2_check)
+ if test "x$enable_gtk2_check" = "xno"; then
+ SKIP_GTK2=YES
+ fi
+fi
+
+if test "x$SKIP_GNOME" != "xYES" -a "$enable_gui_canon" != "gnome" \
+ -a "$enable_gui_canon" != "gnome2"; then
+ AC_MSG_CHECKING(whether or not to look for GNOME)
+ AC_ARG_ENABLE(gnome-check,
+ [ --enable-gnome-check If GTK GUI, check for GNOME [default=no]],
+ , enable_gnome_check="no")
+ AC_MSG_RESULT($enable_gnome_check)
+ if test "x$enable_gnome_check" = "xno"; then
+ SKIP_GNOME=YES
+ fi
+fi
+
+if test "x$SKIP_MOTIF" != "xYES" -a "$enable_gui_canon" != "motif"; then
+ AC_MSG_CHECKING(whether or not to look for Motif)
+ AC_ARG_ENABLE(motif-check,
+ [ --enable-motif-check If auto-select GUI, check for Motif [default=yes]],
+ , enable_motif_check="yes")
+ AC_MSG_RESULT($enable_motif_check)
+ if test "x$enable_motif_check" = "xno"; then
+ SKIP_MOTIF=YES
+ fi
+fi
+
+if test "x$SKIP_ATHENA" != "xYES" -a "$enable_gui_canon" != "athena"; then
+ AC_MSG_CHECKING(whether or not to look for Athena)
+ AC_ARG_ENABLE(athena-check,
+ [ --enable-athena-check If auto-select GUI, check for Athena [default=yes]],
+ , enable_athena_check="yes")
+ AC_MSG_RESULT($enable_athena_check)
+ if test "x$enable_athena_check" = "xno"; then
+ SKIP_ATHENA=YES
+ fi
+fi
+
+if test "x$SKIP_NEXTAW" != "xYES" -a "$enable_gui_canon" != "nextaw"; then
+ AC_MSG_CHECKING(whether or not to look for neXtaw)
+ AC_ARG_ENABLE(nextaw-check,
+ [ --enable-nextaw-check If auto-select GUI, check for neXtaw [default=yes]],
+ , enable_nextaw_check="yes")
+ AC_MSG_RESULT($enable_nextaw_check);
+ if test "x$enable_nextaw_check" = "xno"; then
+ SKIP_NEXTAW=YES
+ fi
+fi
+
+if test "x$SKIP_CARBON" != "xYES" -a "$enable_gui_canon" != "carbon"; then
+ AC_MSG_CHECKING(whether or not to look for Carbon)
+ AC_ARG_ENABLE(carbon-check,
+ [ --enable-carbon-check If auto-select GUI, check for Carbon [default=yes]],
+ , enable_carbon_check="yes")
+ AC_MSG_RESULT($enable_carbon_check);
+ if test "x$enable_carbon_check" = "xno"; then
+ SKIP_CARBON=YES
+ fi
+fi
+
+if test "x$MACOSX" = "xyes" -a -z "$SKIP_CARBON" -a "x$CARBON" = "xyes"; then
+ AC_MSG_CHECKING(for Carbon GUI)
+ dnl already did this
+ AC_MSG_RESULT(yes);
+ GUITYPE=CARBONGUI
+ dnl skip everything else
+ SKIP_GTK=YES;
+ SKIP_GTK2=YES;
+ SKIP_GNOME=YES;
+ SKIP_MOTIF=YES;
+ SKIP_ATHENA=YES;
+ SKIP_NEXTAW=YES;
+ SKIP_PHOTON=YES;
+ SKIP_BEOS=YES;
+ SKIP_CARBON=YES
+fi
+
+
+dnl
+dnl Get the cflags and libraries from the gtk-config script
+dnl
+
+dnl define an autoconf function to check for a specified version of GTK, and
+dnl try to compile/link a GTK program. this gets used once for GTK 1.1.16.
+dnl
+dnl AM_PATH_GTK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for GTK, and define GTK_CFLAGS and GTK_LIBS
+dnl
+AC_DEFUN(AM_PATH_GTK,
+[
+ if test "X$GTK_CONFIG" != "Xno" -o "X$PKG_CONFIG" != "Xno"; then
+ {
+ min_gtk_version=ifelse([$1], ,0.99.7,$1)
+ AC_MSG_CHECKING(for GTK - version >= $min_gtk_version)
+ no_gtk=""
+ if (test "X$SKIP_GTK2" != "XYES" -a "X$PKG_CONFIG" != "Xno") \
+ && $PKG_CONFIG --exists gtk+-2.0; then
+ {
+ dnl We should be using PKG_CHECK_MODULES() instead of this hack.
+ dnl But I guess the dependency on pkgconfig.m4 is not wanted or
+ dnl something like that.
+ GTK_CFLAGS=`$PKG_CONFIG --cflags gtk+-2.0`
+ GTK_LIBS=`$PKG_CONFIG --libs gtk+-2.0`
+ gtk_major_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
+ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
+ gtk_minor_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
+ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
+ gtk_micro_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
+ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
+ }
+ elif test "X$GTK_CONFIG" != "Xno"; then
+ {
+ GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+ GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+ gtk_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
+ gtk_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
+ gtk_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
+ }
+ else
+ no_gtk=yes
+ fi
+
+ if test "x$enable_gtktest" = "xyes" -a "x$no_gtk" = "x"; then
+ {
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$LIBS $GTK_LIBS"
+
+ dnl
+ dnl Now check if the installed GTK is sufficiently new. (Also sanity
+ dnl checks the results of gtk-config to some extent
+ dnl
+ rm -f conf.gtktest
+ AC_TRY_RUN([
+#include <gtk/gtk.h>
+#include <stdio.h>
+
+int
+main ()
+{
+int major, minor, micro;
+char *tmp_version;
+
+system ("touch conf.gtktest");
+
+/* HP/UX 9 (%@#!) writes to sscanf strings */
+tmp_version = g_strdup("$min_gtk_version");
+if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+ printf("%s, bad version string\n", "$min_gtk_version");
+ exit(1);
+ }
+
+if ((gtk_major_version > major) ||
+ ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+ ((gtk_major_version == major) && (gtk_minor_version == minor) &&
+ (gtk_micro_version >= micro)))
+{
+ return 0;
+}
+return 1;
+}
+],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ }
+ fi
+ if test "x$no_gtk" = x ; then
+ if test "x$enable_gtktest" = "xyes"; then
+ AC_MSG_RESULT(yes; found version $gtk_major_version.$gtk_minor_version.$gtk_micro_version)
+ else
+ AC_MSG_RESULT(found version $gtk_major_version.$gtk_minor_version.$gtk_micro_version)
+ fi
+ ifelse([$2], , :, [$2])
+ else
+ {
+ AC_MSG_RESULT(no)
+ GTK_CFLAGS=""
+ GTK_LIBS=""
+ ifelse([$3], , :, [$3])
+ }
+ fi
+ }
+ else
+ GTK_CFLAGS=""
+ GTK_LIBS=""
+ ifelse([$3], , :, [$3])
+ fi
+ AC_SUBST(GTK_CFLAGS)
+ AC_SUBST(GTK_LIBS)
+ rm -f conf.gtktest
+])
+
+dnl ---------------------------------------------------------------------------
+dnl gnome
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([GNOME_INIT_HOOK],
+[
+ AC_SUBST(GNOME_LIBS)
+ AC_SUBST(GNOME_LIBDIR)
+ AC_SUBST(GNOME_INCLUDEDIR)
+
+ AC_ARG_WITH(gnome-includes,
+ [ --with-gnome-includes=DIR Specify location of GNOME headers],
+ [CFLAGS="$CFLAGS -I$withval"]
+ )
+
+ AC_ARG_WITH(gnome-libs,
+ [ --with-gnome-libs=DIR Specify location of GNOME libs],
+ [LDFLAGS="$LDFLAGS -L$withval" gnome_prefix=$withval]
+ )
+
+ AC_ARG_WITH(gnome,
+ [ --with-gnome Specify prefix for GNOME files],
+ if test x$withval = xyes; then
+ want_gnome=yes
+ ifelse([$1], [], :, [$1])
+ else
+ if test "x$withval" = xno; then
+ want_gnome=no
+ else
+ want_gnome=yes
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ CFLAGS="$CFLAGS -I$withval/include"
+ gnome_prefix=$withval/lib
+ fi
+ fi,
+ want_gnome=yes)
+
+ if test "x$want_gnome" = xyes -a "0$gtk_major_version" -ge 2; then
+ {
+ AC_MSG_CHECKING(for libgnomeui-2.0)
+ if $PKG_CONFIG --exists libgnomeui-2.0; then
+ AC_MSG_RESULT(yes)
+ GNOME_LIBS=`$PKG_CONFIG --libs-only-l libgnomeui-2.0`
+ GNOME_LIBDIR=`$PKG_CONFIG --libs-only-L libgnomeui-2.0`
+ GNOME_INCLUDEDIR=`$PKG_CONFIG --cflags libgnomeui-2.0`
+ $1
+ else
+ AC_MSG_RESULT(not found)
+ if test "x$2" = xfail; then
+ AC_MSG_ERROR(Could not find libgnomeui-2.0 via pkg-config)
+ fi
+ fi
+ }
+ elif test "x$want_gnome" = xyes; then
+ {
+ AC_PATH_PROG(GNOME_CONFIG,gnome-config,no)
+ if test "$GNOME_CONFIG" = "no"; then
+ no_gnome_config="yes"
+ else
+ AC_MSG_CHECKING(if $GNOME_CONFIG works)
+ if $GNOME_CONFIG --libs-only-l gnome >/dev/null 2>&1; then
+ AC_MSG_RESULT(yes)
+ GNOME_LIBS="`$GNOME_CONFIG --libs-only-l gnome gnomeui`"
+ GNOME_LIBDIR="`$GNOME_CONFIG --libs-only-L gnorba gnomeui`"
+ GNOME_INCLUDEDIR="`$GNOME_CONFIG --cflags gnorba gnomeui`"
+ $1
+ else
+ AC_MSG_RESULT(no)
+ no_gnome_config="yes"
+ fi
+ fi
+
+ if test x$exec_prefix = xNONE; then
+ if test x$prefix = xNONE; then
+ gnome_prefix=$ac_default_prefix/lib
+ else
+ gnome_prefix=$prefix/lib
+ fi
+ else
+ gnome_prefix=`eval echo \`echo $libdir\``
+ fi
+
+ if test "$no_gnome_config" = "yes"; then
+ AC_MSG_CHECKING(for gnomeConf.sh file in $gnome_prefix)
+ if test -f $gnome_prefix/gnomeConf.sh; then
+ AC_MSG_RESULT(found)
+ echo "loading gnome configuration from" \
+ "$gnome_prefix/gnomeConf.sh"
+ . $gnome_prefix/gnomeConf.sh
+ $1
+ else
+ AC_MSG_RESULT(not found)
+ if test x$2 = xfail; then
+ AC_MSG_ERROR(Could not find the gnomeConf.sh file that is generated by gnome-libs install)
+ fi
+ fi
+ fi
+ }
+ fi
+])
+
+AC_DEFUN([GNOME_INIT],[
+ GNOME_INIT_HOOK([],fail)
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Check for GTK. First checks for gtk-config, cause it needs that to get the
+dnl correct compiler flags. Then checks for GTK 1.1.16. If that fails, then
+dnl it checks for 1.0.6. If both fail, then continue on for Motif as before...
+dnl ---------------------------------------------------------------------------
+if test -z "$SKIP_GTK"; then
+
+ AC_MSG_CHECKING(--with-gtk-prefix argument)
+ AC_ARG_WITH(gtk-prefix,[ --with-gtk-prefix=PFX Prefix where GTK is installed (optional)],
+ gtk_config_prefix="$withval"; AC_MSG_RESULT($gtk_config_prefix),
+ gtk_config_prefix=""; AC_MSG_RESULT(no))
+
+ AC_MSG_CHECKING(--with-gtk-exec-prefix argument)
+ AC_ARG_WITH(gtk-exec-prefix,[ --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)],
+ gtk_config_exec_prefix="$withval"; AC_MSG_RESULT($gtk_config_prefix),
+ gtk_config_exec_prefix=""; AC_MSG_RESULT(no))
+
+ AC_MSG_CHECKING(--disable-gtktest argument)
+ AC_ARG_ENABLE(gtktest, [ --disable-gtktest Do not try to compile and run a test GTK program],
+ , enable_gtktest=yes)
+ if test "x$enable_gtktest" = "xyes" ; then
+ AC_MSG_RESULT(gtk test enabled)
+ else
+ AC_MSG_RESULT(gtk test disabled)
+ fi
+
+ if test "x$gtk_config_prefix" != "x" ; then
+ gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix"
+ GTK_CONFIG=$gtk_config_prefix/bin/gtk-config
+ fi
+ if test "x$gtk_config_exec_prefix" != "x" ; then
+ gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix"
+ GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config
+ fi
+ if test "X$GTK_CONFIG" = "X"; then
+ AC_PATH_PROG(GTK_CONFIG, gtk-config, no)
+ if test "X$GTK_CONFIG" = "Xno"; then
+ dnl Some distributions call it gtk12-config, annoying!
+ AC_PATH_PROG(GTK12_CONFIG, gtk12-config, no)
+ GTK_CONFIG="$GTK12_CONFIG"
+ fi
+ else
+ AC_MSG_RESULT(Using GTK configuration program $GTK_CONFIG)
+ fi
+ if test "X$PKG_CONFIG" = "X"; then
+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+ fi
+
+ if test "x$GTK_CONFIG:$PKG_CONFIG" != "xno:no"; then
+ dnl First try finding version 2.2.0 or later. The 2.0.x series has
+ dnl problems (bold fonts, --remote doesn't work).
+ if test "X$SKIP_GTK2" != "XYES"; then
+ AM_PATH_GTK(2.2.0,
+ [GTK_LIBNAME="$GTK_LIBS"
+ GUI_INC_LOC="$GTK_CFLAGS"], )
+ if test "x$GTK_CFLAGS" != "x"; then
+ SKIP_ATHENA=YES
+ SKIP_NEXTAW=YES
+ SKIP_MOTIF=YES
+ GUITYPE=GTK
+ AC_SUBST(GTK_LIBNAME)
+ fi
+ fi
+
+ dnl If there is no 2.2.0 or later try the 1.x.x series. We require at
+ dnl least GTK 1.1.16. 1.0.6 doesn't work. 1.1.1 to 1.1.15
+ dnl were test versions.
+ if test "x$GUITYPE" != "xGTK"; then
+ SKIP_GTK2=YES
+ AM_PATH_GTK(1.1.16,
+ [GTK_LIBNAME="$GTK_LIBS"
+ GUI_INC_LOC="$GTK_CFLAGS"], )
+ if test "x$GTK_CFLAGS" != "x"; then
+ SKIP_ATHENA=YES
+ SKIP_NEXTAW=YES
+ SKIP_MOTIF=YES
+ GUITYPE=GTK
+ AC_SUBST(GTK_LIBNAME)
+ fi
+ fi
+ fi
+ dnl Give a warning if GTK is older than 1.2.3
+ if test "x$GUITYPE" = "xGTK"; then
+ if test "$gtk_major_version" = 1 -a "0$gtk_minor_version" -lt 2 \
+ -o "$gtk_major_version" = 1 -a "$gtk_minor_version" = 2 -a "0$gtk_micro_version" -lt 3; then
+ AC_MSG_RESULT(this GTK version is old; version 1.2.3 or later is recommended)
+ else
+ {
+ if test "0$gtk_major_version" -ge 2; then
+ AC_DEFINE(HAVE_GTK2)
+ if test "$gtk_minor_version" = 1 -a "0$gtk_micro_version" -ge 1 \
+ || test "0$gtk_minor_version" -ge 2 \
+ || test "0$gtk_major_version" -gt 2; then
+ AC_DEFINE(HAVE_GTK_MULTIHEAD)
+ fi
+ fi
+ dnl
+ dnl if GTK exists, and it's not the 1.0.x series, then check for GNOME.
+ dnl
+ if test -z "$SKIP_GNOME"; then
+ {
+ GNOME_INIT_HOOK([have_gnome=yes])
+ if test x$have_gnome = xyes ; then
+ AC_DEFINE(FEAT_GUI_GNOME)
+ GUI_INC_LOC="$GUI_INC_LOC $GNOME_INCLUDEDIR"
+ GTK_LIBNAME="$GTK_LIBNAME $GNOME_LIBDIR $GNOME_LIBS"
+ fi
+ }
+ fi
+ }
+ fi
+ fi
+fi
+
+dnl Check for Motif include files location.
+dnl The LAST one found is used, this makes the highest version to be used,
+dnl e.g. when Motif1.2 and Motif2.0 are both present.
+
+if test -z "$SKIP_MOTIF"; then
+ gui_XXX="/usr/XXX/Motif* /usr/Motif*/XXX /usr/XXX /usr/shlib /usr/X11*/XXX /usr/XXX/X11* /usr/dt/XXX /local/Motif*/XXX /local/XXX/Motif* /usr/local/Motif*/XXX /usr/local/XXX/Motif* /usr/local/XXX /usr/local/X11*/XXX /usr/local/LessTif/Motif*/XXX $MOTIFHOME/XXX"
+ dnl Remove "-I" from before $GUI_INC_LOC if it's there
+ GUI_INC_LOC="`echo $GUI_INC_LOC|sed 's%-I%%g'`"
+
+ AC_MSG_CHECKING(for location of Motif GUI includes)
+ gui_includes="`echo $x_includes|sed 's%/[^/][^/]*$%%'` `echo "$gui_XXX" | sed s/XXX/include/g` $GUI_INC_LOC"
+ GUI_INC_LOC=
+ for try in $gui_includes; do
+ if test -f "$try/Xm/Xm.h"; then
+ GUI_INC_LOC=$try
+ fi
+ done
+ if test -n "$GUI_INC_LOC"; then
+ if test "$GUI_INC_LOC" = /usr/include; then
+ GUI_INC_LOC=
+ AC_MSG_RESULT(in default path)
+ else
+ AC_MSG_RESULT($GUI_INC_LOC)
+ fi
+ else
+ AC_MSG_RESULT(<not found>)
+ SKIP_MOTIF=YES
+ fi
+fi
+
+dnl Check for Motif library files location. In the same order as the include
+dnl files, to avoid a mixup if several versions are present
+
+if test -z "$SKIP_MOTIF"; then
+ AC_MSG_CHECKING(--with-motif-lib argument)
+ AC_ARG_WITH(motif-lib,
+ [ --with-motif-lib=STRING Library for Motif ],
+ [ MOTIF_LIBNAME="${withval}" ] )
+
+ if test -n "$MOTIF_LIBNAME"; then
+ AC_MSG_RESULT($MOTIF_LIBNAME)
+ GUI_LIB_LOC=
+ else
+ AC_MSG_RESULT(no)
+
+ dnl Remove "-L" from before $GUI_LIB_LOC if it's there
+ GUI_LIB_LOC="`echo $GUI_LIB_LOC|sed 's%-L%%g'`"
+
+ AC_MSG_CHECKING(for location of Motif GUI libs)
+ gui_libs="`echo $x_libraries|sed 's%/[^/][^/]*$%%'` `echo "$gui_XXX" | sed s/XXX/lib/g` `echo "$GUI_INC_LOC" | sed s/include/lib/` $GUI_LIB_LOC"
+ GUI_LIB_LOC=
+ for try in $gui_libs; do
+ for libtry in "$try"/libXm.a "$try"/libXm.so* "$try"/libXm.sl; do
+ if test -f "$libtry"; then
+ GUI_LIB_LOC=$try
+ fi
+ done
+ done
+ if test -n "$GUI_LIB_LOC"; then
+ dnl Remove /usr/lib, it causes trouble on some systems
+ if test "$GUI_LIB_LOC" = /usr/lib; then
+ GUI_LIB_LOC=
+ AC_MSG_RESULT(in default path)
+ else
+ if test -n "$GUI_LIB_LOC"; then
+ AC_MSG_RESULT($GUI_LIB_LOC)
+ if test "`(uname) 2>/dev/null`" = SunOS &&
+ uname -r | grep '^5' >/dev/null; then
+ GUI_LIB_LOC="$GUI_LIB_LOC -R $GUI_LIB_LOC"
+ fi
+ fi
+ fi
+ MOTIF_LIBNAME=-lXm
+ else
+ AC_MSG_RESULT(<not found>)
+ SKIP_MOTIF=YES
+ fi
+ fi
+fi
+
+if test -z "$SKIP_MOTIF"; then
+ SKIP_ATHENA=YES
+ SKIP_NEXTAW=YES
+ GUITYPE=MOTIF
+ AC_SUBST(MOTIF_LIBNAME)
+fi
+
+dnl Check if the Athena files can be found
+
+GUI_X_LIBS=
+
+if test -z "$SKIP_ATHENA"; then
+ AC_MSG_CHECKING(if Athena header files can be found)
+ cflags_save=$CFLAGS
+ CFLAGS="$CFLAGS $X_CFLAGS"
+ AC_TRY_COMPILE([
+#include <X11/Intrinsic.h>
+#include <X11/Xaw/Paned.h>], ,
+ AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no); SKIP_ATHENA=YES )
+ CFLAGS=$cflags_save
+fi
+
+if test -z "$SKIP_ATHENA"; then
+ GUITYPE=ATHENA
+fi
+
+if test -z "$SKIP_NEXTAW"; then
+ AC_MSG_CHECKING(if neXtaw header files can be found)
+ cflags_save=$CFLAGS
+ CFLAGS="$CFLAGS $X_CFLAGS"
+ AC_TRY_COMPILE([
+#include <X11/Intrinsic.h>
+#include <X11/neXtaw/Paned.h>], ,
+ AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no); SKIP_NEXTAW=YES )
+ CFLAGS=$cflags_save
+fi
+
+if test -z "$SKIP_NEXTAW"; then
+ GUITYPE=NEXTAW
+fi
+
+if test -z "$SKIP_ATHENA" -o -z "$SKIP_NEXTAW" -o -z "$SKIP_MOTIF"; then
+ dnl Prepend -I and -L to $GUI_INC_LOC and $GUI_LIB_LOC if not empty
+ dnl Avoid adding it when it twice
+ if test -n "$GUI_INC_LOC"; then
+ GUI_INC_LOC=-I"`echo $GUI_INC_LOC|sed 's%-I%%'`"
+ fi
+ if test -n "$GUI_LIB_LOC"; then
+ GUI_LIB_LOC=-L"`echo $GUI_LIB_LOC|sed 's%-L%%'`"
+ fi
+
+ dnl Check for -lXext and then for -lXmu
+ ldflags_save=$LDFLAGS
+ LDFLAGS="$X_LIBS $LDFLAGS"
+ AC_CHECK_LIB(Xext, XShapeQueryExtension, [GUI_X_LIBS="-lXext"],,
+ [-lXt $X_PRE_LIBS -lX11 $X_EXTRA_LIBS])
+ dnl For Solaris we need -lw and -ldl before linking with -lXmu works.
+ AC_CHECK_LIB(w, wslen, [X_EXTRA_LIBS="$X_EXTRA_LIBS -lw"],,
+ [$GUI_X_LIBS -lXt $X_PRE_LIBS -lX11 $X_EXTRA_LIBS])
+ AC_CHECK_LIB(dl, dlsym, [X_EXTRA_LIBS="$X_EXTRA_LIBS -ldl"],,
+ [$GUI_X_LIBS -lXt $X_PRE_LIBS -lX11 $X_EXTRA_LIBS])
+ AC_CHECK_LIB(Xmu, XmuCreateStippledPixmap, [GUI_X_LIBS="-lXmu $GUI_X_LIBS"],,
+ [$GUI_X_LIBS -lXt $X_PRE_LIBS -lX11 $X_EXTRA_LIBS])
+ if test -z "$SKIP_MOTIF"; then
+ AC_CHECK_LIB(Xp, XpEndJob, [GUI_X_LIBS="-lXp $GUI_X_LIBS"],,
+ [$GUI_X_LIBS -lXm -lXt $X_PRE_LIBS -lX11 $X_EXTRA_LIBS])
+ fi
+ LDFLAGS=$ldflags_save
+
+ dnl Execute xmkmf to figure out if -DNARROWPROTO is needed.
+ AC_MSG_CHECKING(for extra X11 defines)
+ NARROW_PROTO=
+ rm -fr conftestdir
+ if mkdir conftestdir; then
+ cd conftestdir
+ cat > Imakefile <<'EOF'
+acfindx:
+ @echo 'NARROW_PROTO="${PROTO_DEFINES}"'
+EOF
+ if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then
+ eval `${MAKE-make} acfindx 2>/dev/null | grep -v make`
+ fi
+ cd ..
+ rm -fr conftestdir
+ fi
+ if test -z "$NARROW_PROTO"; then
+ AC_MSG_RESULT(no)
+ else
+ AC_MSG_RESULT($NARROW_PROTO)
+ fi
+ AC_SUBST(NARROW_PROTO)
+fi
+
+dnl Look for XSMP support - but don't necessarily restrict it to X11 GUIs
+dnl use the X11 include path
+if test "$enable_xsmp" = "yes"; then
+ cppflags_save=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+ AC_CHECK_HEADERS(X11/SM/SMlib.h)
+ CPPFLAGS=$cppflags_save
+fi
+
+
+if test -z "$SKIP_ATHENA" -o -z "$SKIP_NEXTAW" -o -z "$SKIP_MOTIF" -o -z "$SKIP_GTK"; then
+ dnl Check for X11/xpm.h and X11/Sunkeysym.h with the GUI include path
+ cppflags_save=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+ AC_CHECK_HEADERS(X11/xpm.h X11/Sunkeysym.h)
+
+ dnl automatically disable XIM when XIMtext isn't in X11/Xlib.h
+ if test ! "$enable_xim" = "no"; then
+ AC_MSG_CHECKING(for XIMText in X11/Xlib.h)
+ AC_EGREP_CPP(XIMText, [#include <X11/Xlib.h>],
+ AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no; xim has been disabled); enable_xim = "no")
+ fi
+ CPPFLAGS=$cppflags_save
+
+ dnl automatically enable XIM when hangul input isn't enabled
+ if test "$enable_xim" = "auto" -a "$enable_hangulinput" != "yes" \
+ -a "x$GUITYPE" != "xNONE" ; then
+ AC_MSG_RESULT(X GUI selected; xim has been enabled)
+ enable_xim="yes"
+ fi
+fi
+
+if test -z "$SKIP_ATHENA" -o -z "$SKIP_NEXTAW" -o -z "$SKIP_MOTIF"; then
+ cppflags_save=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+ AC_CHECK_HEADERS(X11/Xmu/Editres.h)
+ CPPFLAGS=$cppflags_save
+fi
+
+dnl Only use the Xm directory when compiling Motif, don't use it for Athena
+if test -z "$SKIP_MOTIF"; then
+ cppflags_save=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+ AC_CHECK_HEADERS(Xm/Xm.h Xm/XpmP.h)
+ CPPFLAGS=$cppflags_save
+fi
+
+if test "x$GUITYPE" = "xNONE" -a "$enable_xim" = "yes"; then
+ AC_MSG_RESULT(no GUI selected; xim has been disabled)
+ enable_xim="no"
+fi
+if test "x$GUITYPE" = "xNONE" -a "$enable_fontset" = "yes"; then
+ AC_MSG_RESULT(no GUI selected; fontset has been disabled)
+ enable_fontset="no"
+fi
+if test "x$GUITYPE:$enable_fontset" = "xGTK:yes" -a "0$gtk_major_version" -ge 2; then
+ AC_MSG_RESULT(GTK+ 2 GUI selected; fontset has been disabled)
+ enable_fontset="no"
+fi
+
+dnl There is no test for the BeOS GUI, if it's selected it's used
+if test -z "$SKIP_BEOS"; then
+ GUITYPE=BEOSGUI
+fi
+
+if test -z "$SKIP_PHOTON"; then
+ GUITYPE=PHOTONGUI
+fi
+
+AC_SUBST(GUI_INC_LOC)
+AC_SUBST(GUI_LIB_LOC)
+AC_SUBST(GUITYPE)
+AC_SUBST(GUI_X_LIBS)
+
+if test "$enable_workshop" = "yes" -a -n "$SKIP_MOTIF"; then
+ AC_MSG_ERROR([cannot use workshop without Motif])
+fi
+
+dnl defining FEAT_XIM and FEAT_XFONTSET is delayed, so that they can be disabled
+if test "$enable_xim" = "yes"; then
+ AC_DEFINE(FEAT_XIM)
+fi
+if test "$enable_fontset" = "yes"; then
+ AC_DEFINE(FEAT_XFONTSET)
+fi
+
+
+dnl ---------------------------------------------------------------------------
+dnl end of GUI-checking
+dnl ---------------------------------------------------------------------------
+
+
+dnl Only really enable hangul input when GUI and XFONTSET are available
+if test "$enable_hangulinput" = "yes"; then
+ if test "x$GUITYPE" = "xNONE"; then
+ AC_MSG_RESULT(no GUI selected; hangul input has been disabled)
+ enable_hangulinput=no
+ else
+ AC_DEFINE(FEAT_HANGULIN)
+ HANGULIN_SRC=hangulin.c
+ AC_SUBST(HANGULIN_SRC)
+ HANGULIN_OBJ=objects/hangulin.o
+ AC_SUBST(HANGULIN_OBJ)
+ fi
+fi
+
+dnl Checks for libraries and include files.
+
+AC_MSG_CHECKING(quality of toupper)
+AC_TRY_RUN([#include <ctype.h>
+main() { exit(toupper('A') == 'A' && tolower('z') == 'z'); }],
+ AC_DEFINE(BROKEN_TOUPPER) AC_MSG_RESULT(bad),
+ AC_MSG_RESULT(good), AC_MSG_ERROR(failed to compile test program))
+
+AC_MSG_CHECKING(whether __DATE__ and __TIME__ work)
+AC_TRY_COMPILE(, [printf("(" __DATE__ " " __TIME__ ")");],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_DATE_TIME),
+ AC_MSG_RESULT(no))
+
+dnl Checks for header files.
+AC_CHECK_HEADER(elf.h, HAS_ELF=1)
+dnl AC_CHECK_HEADER(dwarf.h, SVR4=1)
+if test "$HAS_ELF" = 1; then
+ AC_CHECK_LIB(elf, main)
+fi
+
+AC_HEADER_DIRENT
+
+dnl check for standard headers, we don't use this in Vim but other stuff
+dnl in autoconf needs it
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+
+dnl If sys/wait.h is not found it might still exist but not be POSIX
+dnl compliant. In that case we define HAVE_UNION_WAIT (for NeXT)
+if test $ac_cv_header_sys_wait_h = no; then
+ AC_MSG_CHECKING([for sys/wait.h that defines union wait])
+ AC_TRY_COMPILE([#include <sys/wait.h>],
+ [union wait xx, yy; xx = yy],
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SYS_WAIT_H)
+ AC_DEFINE(HAVE_UNION_WAIT),
+ AC_MSG_RESULT(no))
+fi
+
+AC_CHECK_HEADERS(stdarg.h stdlib.h string.h sys/select.h sys/utsname.h \
+ termcap.h fcntl.h sgtty.h sys/ioctl.h sys/time.h termio.h \
+ iconv.h langinfo.h unistd.h stropts.h errno.h \
+ sys/resource.h sys/systeminfo.h locale.h \
+ sys/stream.h sys/ptem.h termios.h libc.h sys/statfs.h \
+ poll.h sys/poll.h pwd.h utime.h sys/param.h libintl.h \
+ libgen.h util/debug.h util/msg18n.h frame.h pthread_np.h \
+ sys/acl.h sys/access.h sys/sysctl.h sys/sysinfo.h wchar.h)
+
+dnl On Mac OS X strings.h exists but produces a warning message :-(
+if test "x$MACOSX" != "xyes"; then
+ AC_CHECK_HEADERS(strings.h)
+fi
+
+dnl Check if strings.h and string.h can both be included when defined.
+AC_MSG_CHECKING([if strings.h can be included after string.h])
+cppflags_save=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+AC_TRY_COMPILE([
+#if defined(_AIX) && !defined(_AIX51) && !defined(_NO_PROTO)
+# define _NO_PROTO /* like in os_unix.h, causes conflict for AIX (Winn) */
+ /* but don't do it on AIX 5.1 (Uribarri) */
+#endif
+#ifdef HAVE_XM_XM_H
+# include <Xm/Xm.h> /* This breaks it for HP-UX 11 (Squassabia) */
+#endif
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#if defined(HAVE_STRINGS_H)
+# include <strings.h>
+#endif
+ ], [int i; i = 0;],
+ AC_MSG_RESULT(yes),
+ AC_DEFINE(NO_STRINGS_WITH_STRING_H)
+ AC_MSG_RESULT(no))
+CPPFLAGS=$cppflags_save
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_PROG_GCC_TRADITIONAL
+AC_C_CONST
+AC_TYPE_MODE_T
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_UID_T
+AC_HEADER_TIME
+AC_CHECK_TYPE(ino_t, long)
+AC_CHECK_TYPE(dev_t, unsigned)
+
+AC_MSG_CHECKING(for rlim_t)
+if eval "test \"`echo '$''{'ac_cv_type_rlim_t'+set}'`\" = set"; then
+ AC_MSG_RESULT([(cached) $ac_cv_type_rlim_t])
+else
+ AC_EGREP_CPP(dnl
+changequote(<<,>>)dnl
+<<(^|[^a-zA-Z_0-9])rlim_t[^a-zA-Z_0-9]>>dnl
+changequote([,]),
+ [
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+ ], ac_cv_type_rlim_t=yes, ac_cv_type_rlim_t=no)
+ AC_MSG_RESULT($ac_cv_type_rlim_t)
+fi
+if test $ac_cv_type_rlim_t = no; then
+ cat >> confdefs.h <<\EOF
+#define rlim_t unsigned long
+EOF
+fi
+
+AC_MSG_CHECKING(for stack_t)
+if eval "test \"`echo '$''{'ac_cv_type_stack_t'+set}'`\" = set"; then
+ AC_MSG_RESULT([(cached) $ac_cv_type_stack_t])
+else
+ AC_EGREP_CPP(stack_t,
+ [
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#include <signal.h>
+ ], ac_cv_type_stack_t=yes, ac_cv_type_stack_t=no)
+ AC_MSG_RESULT($ac_cv_type_stack_t)
+fi
+if test $ac_cv_type_stack_t = no; then
+ cat >> confdefs.h <<\EOF
+#define stack_t struct sigaltstack
+EOF
+fi
+
+dnl BSDI uses ss_base while others use ss_sp for the stack pointer.
+AC_MSG_CHECKING(whether stack_t has an ss_base field)
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#include <signal.h>
+#include "confdefs.h"
+ ], [stack_t sigstk; sigstk.ss_base = 0; ],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SS_BASE),
+ AC_MSG_RESULT(no))
+
+olibs="$LIBS"
+AC_MSG_CHECKING(--with-tlib argument)
+AC_ARG_WITH(tlib, [ --with-tlib=library terminal library to be used ],)
+if test -n "$with_tlib"; then
+ AC_MSG_RESULT($with_tlib)
+ LIBS="$LIBS -l$with_tlib"
+else
+ AC_MSG_RESULT([automatic terminal library selection])
+ dnl On HP-UX 10.10 termcap or termlib should be used instead of
+ dnl curses, because curses is much slower.
+ dnl Newer versions of ncurses are preferred over anything.
+ dnl Older versions of ncurses have bugs, get a new one!
+ dnl Digital Unix (OSF1) should use curses (Ronald Schild).
+ case "`uname -s 2>/dev/null`" in
+ OSF1) tlibs="ncurses curses termlib termcap";;
+ *) tlibs="ncurses termlib termcap curses";;
+ esac
+ for libname in $tlibs; do
+ AC_CHECK_LIB(${libname}, tgetent,,)
+ if test "x$olibs" != "x$LIBS"; then
+ dnl It's possible that a library is found but it doesn't work
+ dnl e.g., shared library that cannot be found
+ dnl compile and run a test program to be sure
+ AC_TRY_RUN([
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+main() {char *s; s=(char *)tgoto("%p1%d", 0, 1); exit(0); }],
+ res="OK", res="FAIL", res="FAIL")
+ if test "$res" = "OK"; then
+ break
+ fi
+ AC_MSG_RESULT($libname library is not usable)
+ LIBS="$olibs"
+ fi
+ done
+fi
+if test "x$olibs" != "x$LIBS"; then
+ AC_MSG_CHECKING(whether we talk terminfo)
+ AC_TRY_RUN([
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+main()
+{char *s; s=(char *)tgoto("%p1%d", 0, 1); exit(!strcmp(s==0 ? "" : s, "1")); }],
+ AC_MSG_RESULT([no -- we are in termcap land]),
+ AC_MSG_RESULT([yes -- terminfo spoken here]); AC_DEFINE(TERMINFO),
+ AC_MSG_ERROR(failed to compile test program.))
+else
+ AC_MSG_RESULT(none found)
+fi
+
+if test "x$olibs" != "x$LIBS"; then
+ AC_MSG_CHECKING(what tgetent() returns for an unknown terminal)
+ AC_TRY_RUN([
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+main()
+{char s[10000]; int res = tgetent(s, "thisterminaldoesnotexist"); exit(res != 0); }],
+ AC_MSG_RESULT(zero); AC_DEFINE(TGETENT_ZERO_ERR, 0),
+ AC_MSG_RESULT(non-zero),
+ AC_MSG_ERROR(failed to compile test program.))
+fi
+
+AC_MSG_CHECKING(whether termcap.h contains ospeed)
+AC_TRY_LINK([
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+ ], [ospeed = 20000],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_OSPEED),
+ [AC_MSG_RESULT(no)
+ AC_MSG_CHECKING(whether ospeed can be extern)
+ AC_TRY_LINK([
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+extern short ospeed;
+ ], [ospeed = 20000],
+ AC_MSG_RESULT(yes); AC_DEFINE(OSPEED_EXTERN),
+ AC_MSG_RESULT(no))]
+ )
+
+AC_MSG_CHECKING([whether termcap.h contains UP, BC and PC])
+AC_TRY_LINK([
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+ ], [if (UP == 0 && BC == 0) PC = 1],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_UP_BC_PC),
+ [AC_MSG_RESULT(no)
+ AC_MSG_CHECKING([whether UP, BC and PC can be extern])
+ AC_TRY_LINK([
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+extern char *UP, *BC, PC;
+ ], [if (UP == 0 && BC == 0) PC = 1],
+ AC_MSG_RESULT(yes); AC_DEFINE(UP_BC_PC_EXTERN),
+ AC_MSG_RESULT(no))]
+ )
+
+AC_MSG_CHECKING(whether tputs() uses outfuntype)
+AC_TRY_COMPILE([
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+#endif
+ ], [extern int xx(); tputs("test", 1, (outfuntype)xx)],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_OUTFUNTYPE),
+ AC_MSG_RESULT(no))
+
+dnl On some SCO machines sys/select redefines struct timeval
+AC_MSG_CHECKING([whether sys/select.h and sys/time.h may both be included])
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/select.h>], ,
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(SYS_SELECT_WITH_SYS_TIME),
+ AC_MSG_RESULT(no))
+
+dnl AC_DECL_SYS_SIGLIST
+
+dnl Checks for pty.c (copied from screen) ==========================
+AC_MSG_CHECKING(for /dev/ptc)
+if test -r /dev/ptc; then
+ AC_DEFINE(HAVE_DEV_PTC)
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_MSG_CHECKING(for SVR4 ptys)
+if test -c /dev/ptmx ; then
+ AC_TRY_LINK([], [ptsname(0);grantpt(0);unlockpt(0);],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SVR4_PTYS),
+ AC_MSG_RESULT(no))
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_MSG_CHECKING(for ptyranges)
+if test -d /dev/ptym ; then
+ pdir='/dev/ptym'
+else
+ pdir='/dev'
+fi
+dnl SCO uses ptyp%d
+AC_EGREP_CPP(yes,
+[#ifdef M_UNIX
+ yes;
+#endif
+ ], ptys=`echo /dev/ptyp??`, ptys=`echo $pdir/pty??`)
+dnl if test -c /dev/ptyp19; then
+dnl ptys=`echo /dev/ptyp??`
+dnl else
+dnl ptys=`echo $pdir/pty??`
+dnl fi
+if test "$ptys" != "$pdir/pty??" ; then
+ p0=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\).$/\1/g' | sort -u | tr -d '\012'`
+ p1=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\)$/\1/g' | sort -u | tr -d '\012'`
+ AC_DEFINE_UNQUOTED(PTYRANGE0,"$p0")
+ AC_DEFINE_UNQUOTED(PTYRANGE1,"$p1")
+ AC_MSG_RESULT([$p0 / $p1])
+else
+ AC_MSG_RESULT([don't know])
+fi
+
+dnl **** pty mode/group handling ****
+dnl
+dnl support provided by Luke Mewburn <lm@rmit.edu.au>, 931222
+AC_MSG_CHECKING(default tty permissions/group)
+rm -f conftest_grp
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+main()
+{
+ struct stat sb;
+ char *x,*ttyname();
+ int om, m;
+ FILE *fp;
+
+ if (!(x = ttyname(0))) exit(1);
+ if (stat(x, &sb)) exit(1);
+ om = sb.st_mode;
+ if (om & 002) exit(0);
+ m = system("mesg y");
+ if (m == -1 || m == 127) exit(1);
+ if (stat(x, &sb)) exit(1);
+ m = sb.st_mode;
+ if (chmod(x, om)) exit(1);
+ if (m & 002) exit(0);
+ if (sb.st_gid == getgid()) exit(1);
+ if (!(fp=fopen("conftest_grp", "w")))
+ exit(1);
+ fprintf(fp, "%d\n", sb.st_gid);
+ fclose(fp);
+ exit(0);
+}
+],[
+ if test -f conftest_grp; then
+ ptygrp=`cat conftest_grp`
+ AC_MSG_RESULT([pty mode: 0620, group: $ptygrp])
+ AC_DEFINE(PTYMODE, 0620)
+ AC_DEFINE_UNQUOTED(PTYGROUP,$ptygrp)
+ else
+ AC_MSG_RESULT([ptys are world accessable])
+ fi
+],
+ AC_MSG_RESULT([can't determine - assume ptys are world accessable]),
+ AC_MSG_ERROR(failed to compile test program))
+rm -f conftest_grp
+
+dnl Checks for library functions. ===================================
+
+AC_TYPE_SIGNAL
+
+dnl find out what to use at the end of a signal function
+if test $ac_cv_type_signal = void; then
+ AC_DEFINE(SIGRETURN, [return])
+else
+ AC_DEFINE(SIGRETURN, [return 0])
+fi
+
+dnl check if struct sigcontext is defined (used for SGI only)
+AC_MSG_CHECKING(for struct sigcontext)
+AC_TRY_COMPILE([
+#include <signal.h>
+test_sig()
+{
+ struct sigcontext *scont;
+ scont = (struct sigcontext *)0;
+ return 1;
+} ], ,
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SIGCONTEXT),
+ AC_MSG_RESULT(no))
+
+dnl tricky stuff: try to find out if getcwd() is implemented with
+dnl system("sh -c pwd")
+AC_MSG_CHECKING(getcwd implementation)
+AC_TRY_RUN([
+char *dagger[] = { "IFS=pwd", 0 };
+main()
+{
+ char buffer[500];
+ extern char **environ;
+ environ = dagger;
+ return getcwd(buffer, 500) ? 0 : 1;
+}],
+ AC_MSG_RESULT(it is usable),
+ AC_MSG_RESULT(it stinks)
+ AC_DEFINE(BAD_GETCWD),
+ AC_MSG_ERROR(failed to compile test program))
+
+dnl Check for functions in one big call, to reduce the size of configure
+AC_CHECK_FUNCS(bcmp fchdir fchown fseeko fsync ftello getcwd getpseudotty \
+ getpwnam getpwuid getrlimit gettimeofday getwd lstat memcmp \
+ memset nanosleep opendir putenv qsort readlink select setenv \
+ setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
+ sigvec snprintf strcasecmp strerror strftime stricmp strncasecmp \
+ strnicmp strpbrk strtol tgetent towlower towupper usleep utime utimes)
+
+dnl fstatfs() can take 2 to 4 arguments, try to use st_blksize if possible
+AC_MSG_CHECKING(for st_blksize)
+AC_TRY_COMPILE(
+[#include <sys/types.h>
+#include <sys/stat.h>],
+[ struct stat st;
+ int n;
+
+ stat("/", &st);
+ n = (int)st.st_blksize;],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_ST_BLKSIZE),
+ AC_MSG_RESULT(no))
+
+AC_MSG_CHECKING(whether stat() ignores a trailing slash)
+AC_TRY_RUN(
+[#include <sys/types.h>
+#include <sys/stat.h>
+main() {struct stat st; exit(stat("configure/", &st) != 0); }],
+ AC_MSG_RESULT(yes); AC_DEFINE(STAT_IGNORES_SLASH),
+ AC_MSG_RESULT(no), AC_MSG_ERROR(failed to compile test program))
+
+dnl Link with iconv for charset translation, if not found without library.
+dnl check for iconv() requires including iconv.h
+dnl Add "-liconv" when possible; Solaris has iconv but use GNU iconv when it
+dnl has been installed.
+AC_MSG_CHECKING(for iconv_open())
+save_LIBS="$LIBS"
+LIBS="$LIBS -liconv"
+AC_TRY_LINK([
+#ifdef HAVE_ICONV_H
+# include <iconv.h>
+#endif
+ ], [iconv_open("fr", "to");],
+ AC_MSG_RESULT(yes; with -liconv); AC_DEFINE(HAVE_ICONV),
+ LIBS="$save_LIBS"
+ AC_TRY_LINK([
+#ifdef HAVE_ICONV_H
+# include <iconv.h>
+#endif
+ ], [iconv_open("fr", "to");],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_ICONV),
+ AC_MSG_RESULT(no)))
+
+
+AC_MSG_CHECKING(for nl_langinfo(CODESET))
+AC_TRY_LINK([
+#ifdef HAVE_LANGINFO_H
+# include <langinfo.h>
+#endif
+], [char *cs = nl_langinfo(CODESET);],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_NL_LANGINFO_CODESET),
+ AC_MSG_RESULT(no))
+
+dnl Link with -lposix1e for ACL stuff; if not found, try -lacl for SGI
+dnl when -lacl works, also try to use -lattr (required for Debian).
+AC_MSG_CHECKING(--disable-acl argument)
+AC_ARG_ENABLE(acl,
+ [ --disable-acl Don't check for ACL support.],
+ , [enable_acl="yes"])
+if test "$enable_acl" = "yes"; then
+AC_MSG_RESULT(no)
+AC_CHECK_LIB(posix1e, acl_get_file, [LIBS="$LIBS -lposix1e"],
+ AC_CHECK_LIB(acl, acl_get_file, [LIBS="$LIBS -lacl"
+ AC_CHECK_LIB(attr, fgetxattr, LIBS="$LIBS -lattr",,)],,),)
+
+AC_MSG_CHECKING(for POSIX ACL support)
+AC_TRY_LINK([
+#include <sys/types.h>
+#ifdef HAVE_SYS_ACL_H
+# include <sys/acl.h>
+#endif
+acl_t acl;], [acl = acl_get_file("foo", ACL_TYPE_ACCESS);
+ acl_set_file("foo", ACL_TYPE_ACCESS, acl);
+ acl_free(acl);],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_POSIX_ACL),
+ AC_MSG_RESULT(no))
+
+AC_MSG_CHECKING(for Solaris ACL support)
+AC_TRY_LINK([
+#ifdef HAVE_SYS_ACL_H
+# include <sys/acl.h>
+#endif], [acl("foo", GETACLCNT, 0, NULL);
+ ],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SOLARIS_ACL),
+ AC_MSG_RESULT(no))
+
+AC_MSG_CHECKING(for AIX ACL support)
+AC_TRY_LINK([
+#ifdef HAVE_SYS_ACL_H
+# include <sys/acl.h>
+#endif
+#ifdef HAVE_SYS_ACCESS_H
+# include <sys/access.h>
+#endif
+#define _ALL_SOURCE
+
+#include <sys/stat.h>
+
+int aclsize;
+struct acl *aclent;], [aclsize = sizeof(struct acl);
+ aclent = (void *)malloc(aclsize);
+ statacl("foo", STX_NORMAL, aclent, aclsize);
+ ],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_AIX_ACL),
+ AC_MSG_RESULT(no))
+else
+ AC_MSG_RESULT(yes)
+fi
+
+AC_MSG_CHECKING(--disable-gpm argument)
+AC_ARG_ENABLE(gpm,
+ [ --disable-gpm Don't use gpm (Linux mouse daemon).], ,
+ [enable_gpm="yes"])
+
+if test "$enable_gpm" = "yes"; then
+ AC_MSG_RESULT(no)
+ dnl Checking if gpm support can be compiled
+ AC_CACHE_CHECK([for gpm], vi_cv_have_gpm,
+ [olibs="$LIBS" ; LIBS="-lgpm"]
+ AC_TRY_LINK(
+ [#include <gpm.h>
+ #include <linux/keyboard.h>],
+ [Gpm_GetLibVersion(NULL);],
+ dnl Configure defines HAVE_GPM, if it is defined feature.h defines
+ dnl FEAT_MOUSE_GPM if mouse support is included
+ [vi_cv_have_gpm=yes],
+ [vi_cv_have_gpm=no])
+ [LIBS="$olibs"]
+ )
+ if test $vi_cv_have_gpm = yes; then
+ LIBS="$LIBS -lgpm"
+ AC_DEFINE(HAVE_GPM)
+ fi
+else
+ AC_MSG_RESULT(yes)
+fi
+
+AC_MSG_CHECKING(for vsnprintf())
+AC_TRY_RUN([
+#include <stdio.h>
+#include <stdarg.h>
+ /* Check use of vsnprintf() */
+ void warn(char *fmt, ...);
+ void warn(char *fmt, ...)
+ {
+ va_list ap; char buf[20];
+ va_start(ap, fmt);
+ vsnprintf(buf, 20, fmt, ap);
+ va_end(ap);
+ }
+ main()
+ {
+ warn("testing %s\n", "a very long string that won't fit");
+ exit(0);
+ }
+ ],
+ AC_DEFINE(HAVE_VSNPRINTF) AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no),
+ AC_MSG_ERROR(failed to compile test program))
+
+
+dnl rename needs to be checked separately to work on Nextstep with cc
+AC_MSG_CHECKING(for rename)
+AC_TRY_LINK([#include <stdio.h>], [rename("this", "that")],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_RENAME),
+ AC_MSG_RESULT(no))
+
+dnl sysctl() may exist but not the arguments we use
+AC_MSG_CHECKING(for sysctl)
+AC_TRY_COMPILE(
+[#include <sys/types.h>
+#include <sys/sysctl.h>],
+[ int mib[2], r;
+ size_t len;
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_USERMEM;
+ len = sizeof(r);
+ (void)sysctl(mib, 2, &r, &len, (void *)0, (size_t)0);
+ ],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSCTL),
+ AC_MSG_RESULT(not usable))
+
+dnl sysinfo() may exist but not be Linux compatible
+AC_MSG_CHECKING(for sysinfo)
+AC_TRY_COMPILE(
+[#include <sys/types.h>
+#include <sys/sysinfo.h>],
+[ struct sysinfo sinfo;
+ int t;
+
+ (void)sysinfo(&sinfo);
+ t = sinfo.totalram;
+ ],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSINFO),
+ AC_MSG_RESULT(not usable))
+
+dnl sysconf() may exist but not support what we want to use
+AC_MSG_CHECKING(for sysconf)
+AC_TRY_COMPILE(
+[#include <unistd.h>],
+[ (void)sysconf(_SC_PAGESIZE);
+ (void)sysconf(_SC_PHYS_PAGES);
+ ],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSCONF),
+ AC_MSG_RESULT(not usable))
+
+dnl Our own version of AC_CHECK_SIZEOF(int); fixes a bug when sizeof() can't
+dnl be printed with "%d", and avoids a warning for cross-compiling.
+
+AC_MSG_CHECKING(size of int)
+AC_CACHE_VAL(ac_cv_sizeof_int,
+ [AC_TRY_RUN([#include <stdio.h>
+ main()
+ {
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", (int)sizeof(int));
+ exit(0);
+ }],
+ ac_cv_sizeof_int=`cat conftestval`,
+ ac_cv_sizeof_int=0,
+ AC_MSG_ERROR(failed to compile test program))])
+AC_MSG_RESULT($ac_cv_sizeof_int)
+AC_DEFINE_UNQUOTED(SIZEOF_INT, $ac_cv_sizeof_int)
+
+AC_MSG_CHECKING(whether memmove/bcopy/memcpy handle overlaps)
+[bcopy_test_prog='
+main() {
+ char buf[10];
+ strcpy(buf, "abcdefghi");
+ mch_memmove(buf, buf + 2, 3);
+ if (strncmp(buf, "ababcf", 6))
+ exit(1);
+ strcpy(buf, "abcdefghi");
+ mch_memmove(buf + 2, buf, 3);
+ if (strncmp(buf, "cdedef", 6))
+ exit(1);
+ exit(0); /* libc version works properly. */
+}']
+
+dnl Check for memmove() before bcopy(), makes memmove() be used when both are
+dnl present, fixes problem with incompatibility between Solaris 2.4 and 2.5.
+
+AC_TRY_RUN([#define mch_memmove(s,d,l) memmove(d,s,l) $bcopy_test_prog],
+ AC_DEFINE(USEMEMMOVE) AC_MSG_RESULT(memmove does),
+ AC_TRY_RUN([#define mch_memmove(s,d,l) bcopy(d,s,l) $bcopy_test_prog],
+ AC_DEFINE(USEBCOPY) AC_MSG_RESULT(bcopy does),
+ AC_TRY_RUN([#define mch_memmove(s,d,l) memcpy(d,s,l) $bcopy_test_prog],
+ AC_DEFINE(USEMEMCPY) AC_MSG_RESULT(memcpy does), AC_MSG_RESULT(no),
+ AC_MSG_ERROR(failed to compile test program)),
+ AC_MSG_ERROR(failed to compile test program)),
+ AC_MSG_ERROR(failed to compile test program))
+
+dnl Check for multibyte locale functions
+dnl Find out if _Xsetlocale() is supported by libX11.
+dnl Check if X_LOCALE should be defined.
+
+if test "$enable_multibyte" = "yes"; then
+ cflags_save=$CFLAGS
+ ldflags_save=$LDFLAGS
+ if test -n "$x_includes" ; then
+ CFLAGS="$CFLAGS -I$x_includes"
+ LDFLAGS="$X_LIBS $LDFLAGS -lX11"
+ AC_MSG_CHECKING(whether X_LOCALE needed)
+ AC_TRY_COMPILE([#include <X11/Xlocale.h>],,
+ AC_TRY_LINK_FUNC([_Xsetlocale], [AC_MSG_RESULT(yes)
+ AC_DEFINE(X_LOCALE)], AC_MSG_RESULT(no)),
+ AC_MSG_RESULT(no))
+ fi
+ CFLAGS=$cflags_save
+ LDFLAGS=$ldflags_save
+fi
+
+dnl Link with xpg4, it is said to make Korean locale working
+AC_CHECK_LIB(xpg4, _xpg4_setrunelocale, [LIBS="$LIBS -lxpg4"],,)
+
+dnl Check how we can run ctags
+dnl --version for Exuberant ctags (preferred)
+dnl -t for typedefs (many ctags have this)
+dnl -s for static functions (Elvis ctags only?)
+dnl -v for variables. Dangerous, most ctags take this for 'vgrind style'.
+dnl -i+m to test for older Exuberant ctags
+AC_MSG_CHECKING(how to create tags)
+test -f tags && mv tags tags.save
+if (eval ctags --version /dev/null | grep Exuberant) < /dev/null 1>&AC_FD_CC 2>&1; then
+ TAGPRG="ctags"
+else
+ (eval etags /dev/null) < /dev/null 1>&AC_FD_CC 2>&1 && TAGPRG="etags"
+ (eval etags -c /dev/null) < /dev/null 1>&AC_FD_CC 2>&1 && TAGPRG="etags -c"
+ (eval ctags /dev/null) < /dev/null 1>&AC_FD_CC 2>&1 && TAGPRG="ctags"
+ (eval ctags -t /dev/null) < /dev/null 1>&AC_FD_CC 2>&1 && TAGPRG="ctags -t"
+ (eval ctags -ts /dev/null) < /dev/null 1>&AC_FD_CC 2>&1 && TAGPRG="ctags -ts"
+ (eval ctags -tvs /dev/null) < /dev/null 1>&AC_FD_CC 2>&1 && TAGPRG="ctags -tvs"
+ (eval ctags -i+m /dev/null) < /dev/null 1>&AC_FD_CC 2>&1 && TAGPRG="ctags -i+m"
+fi
+test -f tags.save && mv tags.save tags
+AC_MSG_RESULT($TAGPRG) AC_SUBST(TAGPRG)
+
+dnl Check how we can run man with a section number
+AC_MSG_CHECKING(how to run man with a section nr)
+MANDEF="man"
+(eval man -s 2 read) < /dev/null > /dev/null 2>&AC_FD_CC && MANDEF="man -s"
+AC_MSG_RESULT($MANDEF)
+if test "$MANDEF" = "man -s"; then
+ AC_DEFINE(USEMAN_S)
+fi
+
+dnl Check if gettext() is working and if it needs -lintl
+AC_MSG_CHECKING(--disable-nls argument)
+AC_ARG_ENABLE(nls,
+ [ --disable-nls Don't support NLS (gettext()).], ,
+ [enable_nls="yes"])
+
+if test "$enable_nls" = "yes"; then
+ AC_MSG_RESULT(no)
+ AC_CHECK_PROG(MSGFMT, msgfmt, msgfmt, )
+ AC_MSG_CHECKING([for NLS])
+ if test -f po/Makefile; then
+ have_gettext="no"
+ if test -n "$MSGFMT"; then
+ AC_TRY_LINK(
+ [#include <libintl.h>],
+ [gettext("Test");],
+ AC_MSG_RESULT([gettext() works]); have_gettext="yes",
+ olibs=$LIBS
+ LIBS="$LIBS -lintl"
+ AC_TRY_LINK(
+ [#include <libintl.h>],
+ [gettext("Test");],
+ AC_MSG_RESULT([gettext() works with -lintl]); have_gettext="yes",
+ AC_MSG_RESULT([gettext() doesn't work]);
+ LIBS=$olibs))
+ else
+ AC_MSG_RESULT([msgfmt not found - disabled]);
+ fi
+ if test $have_gettext = "yes"; then
+ AC_DEFINE(HAVE_GETTEXT)
+ MAKEMO=yes
+ AC_SUBST(MAKEMO)
+ dnl this was added in GNU gettext 0.10.36
+ AC_CHECK_FUNCS(bind_textdomain_codeset)
+ dnl _nl_msg_cat_cntr is required for GNU gettext
+ AC_MSG_CHECKING([for _nl_msg_cat_cntr])
+ AC_TRY_LINK(
+ [#include <libintl.h>
+ extern int _nl_msg_cat_cntr;],
+ [++_nl_msg_cat_cntr;],
+ AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_NL_MSG_CAT_CNTR),
+ AC_MSG_RESULT([no]))
+ fi
+ else
+ AC_MSG_RESULT([no "po/Makefile" - disabled]);
+ fi
+else
+ AC_MSG_RESULT(yes)
+fi
+
+dnl Check for dynamic linking loader
+AC_CHECK_HEADER(dlfcn.h, DLL=dlfcn.h, [AC_CHECK_HEADER(dl.h, DLL=dl.h)])
+if test x${DLL} = xdlfcn.h; then
+ AC_DEFINE(HAVE_DLFCN_H, 1, [ Define if we have dlfcn.h. ])
+ AC_MSG_CHECKING([for dlopen()])
+ AC_TRY_LINK(,[
+ extern void* dlopen();
+ dlopen();
+ ],
+ AC_MSG_RESULT(yes);
+ AC_DEFINE(HAVE_DLOPEN, 1, [ Define if we have dlopen() ]),
+ AC_MSG_RESULT(no);
+ AC_MSG_CHECKING([for dlopen() in -ldl])
+ olibs=$LIBS
+ LIBS="$LIBS -ldl"
+ AC_TRY_LINK(,[
+ extern void* dlopen();
+ dlopen();
+ ],
+ AC_MSG_RESULT(yes);
+ AC_DEFINE(HAVE_DLOPEN, 1, [ Define if we have dlopen() ]),
+ AC_MSG_RESULT(no);
+ LIBS=$olibs))
+ dnl ReliantUNIX has dlopen() in libc but everything else in libdl
+ dnl ick :-)
+ AC_MSG_CHECKING([for dlsym()])
+ AC_TRY_LINK(,[
+ extern void* dlsym();
+ dlsym();
+ ],
+ AC_MSG_RESULT(yes);
+ AC_DEFINE(HAVE_DLSYM, 1, [ Define if we have dlsym() ]),
+ AC_MSG_RESULT(no);
+ AC_MSG_CHECKING([for dlsym() in -ldl])
+ olibs=$LIBS
+ LIBS="$LIBS -ldl"
+ AC_TRY_LINK(,[
+ extern void* dlsym();
+ dlsym();
+ ],
+ AC_MSG_RESULT(yes);
+ AC_DEFINE(HAVE_DLSYM, 1, [ Define if we have dlsym() ]),
+ AC_MSG_RESULT(no);
+ LIBS=$olibs))
+elif test x${DLL} = xdl.h; then
+ AC_DEFINE(HAVE_DL_H, 1, [ Define if we have dl.h. ])
+ AC_MSG_CHECKING([for shl_load()])
+ AC_TRY_LINK(,[
+ extern void* shl_load();
+ shl_load();
+ ],
+ AC_MSG_RESULT(yes);
+ AC_DEFINE(HAVE_SHL_LOAD, 1, [ Define if we have shl_load() ]),
+ AC_MSG_RESULT(no);
+ AC_MSG_CHECKING([for shl_load() in -ldld])
+ olibs=$LIBS
+ LIBS="$LIBS -ldld"
+ AC_TRY_LINK(,[
+ extern void* shl_load();
+ shl_load();
+ ],
+ AC_MSG_RESULT(yes);
+ AC_DEFINE(HAVE_SHL_LOAD, 1, [ Define if we have shl_load() ]),
+ AC_MSG_RESULT(no);
+ LIBS=$olibs))
+fi
+AC_CHECK_HEADERS(setjmp.h)
+
+if test "x$MACOSX" = "xyes" -a -n "$PERL"; then
+ dnl -ldl must come after DynaLoader.a
+ if echo $LIBS | grep -e '-ldl' >/dev/null; then
+ LIBS=`echo $LIBS | sed s/-ldl//`
+ PERL_LIBS="$PERL_LIBS -ldl"
+ fi
+fi
+
+if test "x$MACOSX" = "xyes" && test "x$CARBON" = "xyes" \
+ && test "x$GUITYPE" != "xCARBONGUI"; then
+ AC_MSG_CHECKING(whether we need -framework Carbon)
+ dnl check for MACOSX without Carbon GUI, but with FEAT_MBYTE
+ if test "x$enable_multibyte" = "xyes" || test "x$features" == "xbig" \
+ || test "x$features" = "xhuge"; then
+ LIBS="$LIBS -framework Carbon"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+fi
+
+
+dnl write output files
+AC_OUTPUT(auto/config.mk:config.mk.in)
+
+dnl vim: set sw=2 tw=78 fo+=l:
diff --git a/src/dehqx.py b/src/dehqx.py
new file mode 100644
index 000000000..9c9cefb4f
--- /dev/null
+++ b/src/dehqx.py
@@ -0,0 +1,40 @@
+# Python script to get both the data and resource fork from a BinHex encoded
+# file.
+# Author: Taro Muraoka
+# Last Change: 2003 Oct 25
+
+import sys
+import binhex
+
+input = sys.argv[1]
+conv = binhex.HexBin(input)
+info = conv.FInfo
+out = conv.FName
+out_data = out
+out_rsrc = out + '.rsrcfork'
+#print 'out_rsrc=' + out_rsrc
+print 'In file: ' + input
+
+outfile = open(out_data, 'wb')
+print ' Out data fork: ' + out_data
+while 1:
+ d = conv.read(128000)
+ if not d: break
+ outfile.write(d)
+outfile.close()
+conv.close_data()
+
+d = conv.read_rsrc(128000)
+if d:
+ print ' Out rsrc fork: ' + out_rsrc
+ outfile = open(out_rsrc, 'wb')
+ outfile.write(d)
+ while 1:
+ d = conv.read_rsrc(128000)
+ if not d: break
+ outfile.write(d)
+ outfile.close()
+
+conv.close()
+
+# vim:set ts=8 sts=4 sw=4 et:
diff --git a/src/diff.c b/src/diff.c
new file mode 100644
index 000000000..580589e47
--- /dev/null
+++ b/src/diff.c
@@ -0,0 +1,2208 @@
+/* vim:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * diff.c: code for diff'ing two or three buffers.
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_DIFF) || defined(PROTO)
+
+#define DB_COUNT 4 /* up to four buffers can be diff'ed */
+
+/*
+ * Each diffblock defines where a block of lines starts in each of the buffers
+ * and how many lines it occupies in that buffer. When the lines are missing
+ * in the buffer the df_count[] is zero. This is all counted in
+ * buffer lines.
+ * There is always at least one unchanged line in between the diffs.
+ * Otherwise it would have been included in the diff above or below it.
+ * df_lnum[] + df_count[] is the lnum below the change. When in one buffer
+ * lines have been inserted, in the other buffer df_lnum[] is the line below
+ * the insertion and df_count[] is zero. When appending lines at the end of
+ * the buffer, df_lnum[] is one beyond the end!
+ * This is using a linked list, because the number of differences is expected
+ * to be reasonable small. The list is sorted on lnum.
+ */
+typedef struct diffblock diff_T;
+struct diffblock
+{
+ diff_T *df_next;
+ linenr_T df_lnum[DB_COUNT]; /* line number in buffer */
+ linenr_T df_count[DB_COUNT]; /* nr of inserted/changed lines */
+};
+
+static diff_T *first_diff = NULL;
+
+static buf_T *(diffbuf[DB_COUNT]);
+
+static int diff_invalid = TRUE; /* list of diffs is outdated */
+
+static int diff_busy = FALSE; /* ex_diffgetput() is busy */
+
+/* flags obtained from the 'diffopt' option */
+#define DIFF_FILLER 1 /* display filler lines */
+#define DIFF_ICASE 2 /* ignore case */
+#define DIFF_IWHITE 4 /* ignore change in white space */
+static int diff_flags = DIFF_FILLER;
+
+#define LBUFLEN 50 /* length of line in diff file */
+
+static int diff_a_works = MAYBE; /* TRUE when "diff -a" works, FALSE when it
+ doesn't work, MAYBE when not checked yet */
+#if defined(MSWIN) || defined(MSDOS)
+static int diff_bin_works = MAYBE; /* TRUE when "diff --binary" works, FALSE
+ when it doesn't work, MAYBE when not
+ checked yet */
+#endif
+
+static int diff_buf_idx __ARGS((buf_T *buf));
+static void diff_check_unchanged __ARGS((diff_T *dp));
+static int diff_check_sanity __ARGS((diff_T *dp));
+static void diff_redraw __ARGS((int dofold));
+static int diff_write __ARGS((buf_T *buf, char_u *fname));
+static void diff_file __ARGS((char_u *tmp_orig, char_u *tmp_new, char_u *tmp_diff));
+static void diff_clear __ARGS((void));
+static int diff_equal_entry __ARGS((diff_T *dp, int idx1, int idx2));
+static int diff_cmp __ARGS((char_u *s1, char_u *s2));
+#ifdef FEAT_FOLDING
+static void diff_fold_update __ARGS((diff_T *dp, int skip_idx));
+#endif
+static void diff_read __ARGS((int idx_orig, int idx_new, char_u *fname));
+static void diff_copy_entry __ARGS((diff_T *dprev, diff_T *dp, int idx_orig, int idx_new));
+static diff_T *diff_alloc_new __ARGS((diff_T *dprev, diff_T *dp));
+
+#ifndef USE_CR
+# define tag_fgets vim_fgets
+#endif
+
+/*
+ * Call this when a new buffer is being edited in the current window. curbuf
+ * must already have been set.
+ * Marks the current buffer as being part of the diff and requireing updating.
+ * This must be done before any autocmd, because a command the uses info
+ * about the screen contents.
+ */
+ void
+diff_new_buffer()
+{
+ if (curwin->w_p_diff)
+ diff_buf_add(curbuf);
+}
+
+/*
+ * Called when deleting or unloading a buffer: No longer make a diff with it.
+ * Also called when 'diff' is reset in the last window showing a diff for a
+ * buffer.
+ */
+ void
+diff_buf_delete(buf)
+ buf_T *buf;
+{
+ int i;
+
+ i = diff_buf_idx(buf);
+ if (i != DB_COUNT)
+ {
+ diffbuf[i] = NULL;
+ diff_invalid = TRUE;
+ }
+}
+
+/*
+ * Add a buffer to make diffs for.
+ */
+ void
+diff_buf_add(buf)
+ buf_T *buf;
+{
+ int i;
+
+ if (diff_buf_idx(buf) != DB_COUNT)
+ return; /* It's already there. */
+
+ for (i = 0; i < DB_COUNT; ++i)
+ if (diffbuf[i] == NULL)
+ {
+ diffbuf[i] = buf;
+ diff_invalid = TRUE;
+ return;
+ }
+
+ EMSGN(_("E96: Can not diff more than %ld buffers"), DB_COUNT);
+}
+
+/*
+ * Find buffer "buf" in the list of diff buffers.
+ * Return its index or DB_COUNT if not found.
+ */
+ static int
+diff_buf_idx(buf)
+ buf_T *buf;
+{
+ int idx;
+
+ for (idx = 0; idx < DB_COUNT; ++idx)
+ if (diffbuf[idx] == buf)
+ break;
+ return idx;
+}
+
+/*
+ * Mark the diff info as invalid, it will be updated when info is requested.
+ */
+ void
+diff_invalidate()
+{
+ if (curwin->w_p_diff)
+ {
+ diff_invalid = TRUE;
+ diff_redraw(TRUE);
+ }
+}
+
+/*
+ * Called by mark_adjust(): update line numbers.
+ * This attempts to update the changes as much as possible:
+ * When inserting/deleting lines outside of existing change blocks, create a
+ * new change block and update the line numbers in following blocks.
+ * When inserting/deleting lines in existing change blocks, update them.
+ */
+ void
+diff_mark_adjust(line1, line2, amount, amount_after)
+ linenr_T line1;
+ linenr_T line2;
+ long amount;
+ long amount_after;
+{
+ diff_T *dp;
+ diff_T *dprev;
+ diff_T *dnext;
+ int idx;
+ int i;
+ int inserted, deleted;
+ int n, off;
+ linenr_T last;
+ linenr_T lnum_deleted = line1; /* lnum of remaining deletion */
+ int check_unchanged;
+
+ /* Find the index for the current buffer. */
+ idx = diff_buf_idx(curbuf);
+ if (idx == DB_COUNT)
+ return; /* This buffer doesn't have diffs. */
+
+ if (line2 == MAXLNUM)
+ {
+ /* mark_adjust(99, MAXLNUM, 9, 0): insert lines */
+ inserted = amount;
+ deleted = 0;
+ }
+ else if (amount_after > 0)
+ {
+ /* mark_adjust(99, 98, MAXLNUM, 9): a change that inserts lines*/
+ inserted = amount_after;
+ deleted = 0;
+ }
+ else
+ {
+ /* mark_adjust(98, 99, MAXLNUM, -2): delete lines */
+ inserted = 0;
+ deleted = -amount_after;
+ }
+
+ dprev = NULL;
+ dp = first_diff;
+ for (;;)
+ {
+ /* If the change is after the previous diff block and before the next
+ * diff block, thus not touching an existing change, create a new diff
+ * block. Don't do this when ex_diffgetput() is busy. */
+ if ((dp == NULL || dp->df_lnum[idx] - 1 > line2
+ || (line2 == MAXLNUM && dp->df_lnum[idx] > line1))
+ && (dprev == NULL
+ || dprev->df_lnum[idx] + dprev->df_count[idx] < line1)
+ && !diff_busy)
+ {
+ dnext = diff_alloc_new(dprev, dp);
+ if (dnext == NULL)
+ return;
+
+ dnext->df_lnum[idx] = line1;
+ dnext->df_count[idx] = inserted;
+ for (i = 0; i < DB_COUNT; ++i)
+ if (diffbuf[i] != NULL && i != idx)
+ {
+ if (dprev == NULL)
+ dnext->df_lnum[i] = line1;
+ else
+ dnext->df_lnum[i] = line1
+ + (dprev->df_lnum[i] + dprev->df_count[i])
+ - (dprev->df_lnum[idx] + dprev->df_count[idx]);
+ dnext->df_count[i] = deleted;
+ }
+ }
+
+ /* if at end of the list, quit */
+ if (dp == NULL)
+ break;
+
+ /*
+ * Check for these situations:
+ * 1 2 3
+ * 1 2 3
+ * line1 2 3 4 5
+ * 2 3 4 5
+ * 2 3 4 5
+ * line2 2 3 4 5
+ * 3 5 6
+ * 3 5 6
+ */
+ /* compute last line of this change */
+ last = dp->df_lnum[idx] + dp->df_count[idx] - 1;
+
+ /* 1. change completely above line1: nothing to do */
+ if (last >= line1 - 1)
+ {
+ /* 6. change below line2: only adjust for amount_after; also when
+ * "deleted" became zero when deleted all lines between two diffs */
+ if (dp->df_lnum[idx] - (deleted + inserted != 0) > line2)
+ {
+ if (amount_after == 0)
+ break; /* nothing left to change */
+ dp->df_lnum[idx] += amount_after;
+ }
+ else
+ {
+ check_unchanged = FALSE;
+
+ /* 2. 3. 4. 5.: inserted/deleted lines touching this diff. */
+ if (deleted > 0)
+ {
+ if (dp->df_lnum[idx] >= line1)
+ {
+ off = dp->df_lnum[idx] - lnum_deleted;
+ if (last <= line2)
+ {
+ /* 4. delete all lines of diff */
+ if (dp->df_next != NULL
+ && dp->df_next->df_lnum[idx] - 1 <= line2)
+ {
+ /* delete continues in next diff, only do
+ * lines until that one */
+ n = dp->df_next->df_lnum[idx] - lnum_deleted;
+ deleted -= n;
+ n -= dp->df_count[idx];
+ lnum_deleted = dp->df_next->df_lnum[idx];
+ }
+ else
+ n = deleted - dp->df_count[idx];
+ dp->df_count[idx] = 0;
+ }
+ else
+ {
+ /* 5. delete lines at or just before top of diff */
+ n = off;
+ dp->df_count[idx] -= line2 - dp->df_lnum[idx] + 1;
+ check_unchanged = TRUE;
+ }
+ dp->df_lnum[idx] = line1;
+ }
+ else
+ {
+ off = 0;
+ if (last < line2)
+ {
+ /* 2. delete at end of of diff */
+ dp->df_count[idx] -= last - lnum_deleted + 1;
+ if (dp->df_next != NULL
+ && dp->df_next->df_lnum[idx] - 1 <= line2)
+ {
+ /* delete continues in next diff, only do
+ * lines until that one */
+ n = dp->df_next->df_lnum[idx] - 1 - last;
+ deleted -= dp->df_next->df_lnum[idx]
+ - lnum_deleted;
+ lnum_deleted = dp->df_next->df_lnum[idx];
+ }
+ else
+ n = line2 - last;
+ check_unchanged = TRUE;
+ }
+ else
+ {
+ /* 3. delete lines inside the diff */
+ n = 0;
+ dp->df_count[idx] -= deleted;
+ }
+ }
+
+ for (i = 0; i < DB_COUNT; ++i)
+ if (diffbuf[i] != NULL && i != idx)
+ {
+ dp->df_lnum[i] -= off;
+ dp->df_count[i] += n;
+ }
+ }
+ else
+ {
+ if (dp->df_lnum[idx] <= line1)
+ {
+ /* inserted lines somewhere in this diff */
+ dp->df_count[idx] += inserted;
+ check_unchanged = TRUE;
+ }
+ else
+ /* inserted lines somewhere above this diff */
+ dp->df_lnum[idx] += inserted;
+ }
+
+ if (check_unchanged)
+ /* Check if inserted lines are equal, may reduce the
+ * size of the diff. TODO: also check for equal lines
+ * in the middle and perhaps split the block. */
+ diff_check_unchanged(dp);
+ }
+ }
+
+ /* check if this block touches the previous one, may merge them. */
+ if (dprev != NULL && dprev->df_lnum[idx] + dprev->df_count[idx]
+ == dp->df_lnum[idx])
+ {
+ for (i = 0; i < DB_COUNT; ++i)
+ if (diffbuf[i] != NULL)
+ dprev->df_count[i] += dp->df_count[i];
+ dprev->df_next = dp->df_next;
+ vim_free(dp);
+ dp = dprev->df_next;
+ }
+ else
+ {
+ /* Advance to next entry. */
+ dprev = dp;
+ dp = dp->df_next;
+ }
+ }
+
+ dprev = NULL;
+ dp = first_diff;
+ while (dp != NULL)
+ {
+ /* All counts are zero, remove this entry. */
+ for (i = 0; i < DB_COUNT; ++i)
+ if (diffbuf[i] != NULL && dp->df_count[i] != 0)
+ break;
+ if (i == DB_COUNT)
+ {
+ dnext = dp->df_next;
+ vim_free(dp);
+ dp = dnext;
+ if (dprev == NULL)
+ first_diff = dnext;
+ else
+ dprev->df_next = dnext;
+ }
+ else
+ {
+ /* Advance to next entry. */
+ dprev = dp;
+ dp = dp->df_next;
+ }
+
+ }
+ diff_redraw(TRUE);
+
+ /* Recompute the scroll binding, may remove or add filler lines (e.g.,
+ * when adding lines above w_topline). */
+ check_scrollbind((linenr_T)0, 0L);
+}
+
+/*
+ * Allocate a new diff block and link it between "dprev" and "dp".
+ */
+ static diff_T *
+diff_alloc_new(dprev, dp)
+ diff_T *dprev;
+ diff_T *dp;
+{
+ diff_T *dnew;
+
+ dnew = (diff_T *)alloc((unsigned)sizeof(diff_T));
+ if (dnew != NULL)
+ {
+ dnew->df_next = dp;
+ if (dprev == NULL)
+ first_diff = dnew;
+ else
+ dprev->df_next = dnew;
+ }
+ return dnew;
+}
+
+/*
+ * Check if the diff block "dp" can be made smaller for lines at the start and
+ * end that are equal. Called after inserting lines.
+ * This may result in a change where all buffers have zero lines, the caller
+ * must take care of removing it.
+ */
+ static void
+diff_check_unchanged(dp)
+ diff_T *dp;
+{
+ int i_org;
+ int i_new;
+ int off_org, off_new;
+ char_u *line_org;
+ int dir = FORWARD;
+
+ /* Find the first buffers, use it as the original, compare the other
+ * buffer lines against this one. */
+ for (i_org = 0; i_org < DB_COUNT; ++i_org)
+ if (diffbuf[i_org] != NULL)
+ break;
+ if (i_org == DB_COUNT) /* safety check */
+ return;
+
+ if (diff_check_sanity(dp) == FAIL)
+ return;
+
+ /* First check lines at the top, then at the bottom. */
+ off_org = 0;
+ off_new = 0;
+ for (;;)
+ {
+ /* Repeat until a line is found which is different or the number of
+ * lines has become zero. */
+ while (dp->df_count[i_org] > 0)
+ {
+ /* Copy the line, the next ml_get() will invalidate it. */
+ if (dir == BACKWARD)
+ off_org = dp->df_count[i_org] - 1;
+ line_org = vim_strsave(ml_get_buf(diffbuf[i_org],
+ dp->df_lnum[i_org] + off_org, FALSE));
+ if (line_org == NULL)
+ return;
+ for (i_new = i_org + 1; i_new < DB_COUNT; ++i_new)
+ {
+ if (diffbuf[i_new] == NULL)
+ continue;
+ if (dir == BACKWARD)
+ off_new = dp->df_count[i_new] - 1;
+ /* if other buffer doesn't have this line, it was inserted */
+ if (off_new < 0 || off_new >= dp->df_count[i_new])
+ break;
+ if (diff_cmp(line_org, ml_get_buf(diffbuf[i_new],
+ dp->df_lnum[i_new] + off_new, FALSE)) != 0)
+ break;
+ }
+ vim_free(line_org);
+
+ /* Stop when a line isn't equal in all diff buffers. */
+ if (i_new != DB_COUNT)
+ break;
+
+ /* Line matched in all buffers, remove it from the diff. */
+ for (i_new = i_org; i_new < DB_COUNT; ++i_new)
+ if (diffbuf[i_new] != NULL)
+ {
+ if (dir == FORWARD)
+ ++dp->df_lnum[i_new];
+ --dp->df_count[i_new];
+ }
+ }
+ if (dir == BACKWARD)
+ break;
+ dir = BACKWARD;
+ }
+}
+
+/*
+ * Check if a diff block doesn't contain invalid line numbers.
+ * This can happen when the diff program returns invalid results.
+ */
+ static int
+diff_check_sanity(dp)
+ diff_T *dp;
+{
+ int i;
+
+ for (i = 0; i < DB_COUNT; ++i)
+ if (diffbuf[i] != NULL)
+ if (dp->df_lnum[i] + dp->df_count[i] - 1
+ > diffbuf[i]->b_ml.ml_line_count)
+ return FAIL;
+ return OK;
+}
+
+/*
+ * Mark all diff buffers for redraw.
+ */
+ static void
+diff_redraw(dofold)
+ int dofold; /* also recompute the folds */
+{
+ win_T *wp;
+ int n;
+
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_p_diff)
+ {
+ redraw_win_later(wp, NOT_VALID);
+#ifdef FEAT_FOLDING
+ if (dofold && foldmethodIsDiff(wp))
+ foldUpdateAll(wp);
+#endif
+ /* A change may have made filler lines invalid, need to take care
+ * of that for other windows. */
+ if (wp != curwin && wp->w_topfill > 0)
+ {
+ n = diff_check(wp, wp->w_topline);
+ if (wp->w_topfill > n)
+ wp->w_topfill = (n < 0 ? 0 : n);
+ }
+ }
+}
+
+/*
+ * Write buffer "buf" to file "name".
+ * Always use 'fileformat' set to "unix".
+ * Return FAIL for failure
+ */
+ static int
+diff_write(buf, fname)
+ buf_T *buf;
+ char_u *fname;
+{
+ int r;
+ char_u *save_ff;
+
+ save_ff = buf->b_p_ff;
+ buf->b_p_ff = vim_strsave((char_u *)FF_UNIX);
+ r = buf_write(buf, fname, NULL, (linenr_T)1, buf->b_ml.ml_line_count,
+ NULL, FALSE, FALSE, FALSE, TRUE);
+ free_string_option(buf->b_p_ff);
+ buf->b_p_ff = save_ff;
+ return r;
+}
+
+/*
+ * Completely update the diffs for the buffers involved.
+ * This uses the ordinary "diff" command.
+ * The buffers are written to a file, also for unmodified buffers (the file
+ * could have been produced by autocommands, e.g. the netrw plugin).
+ */
+/*ARGSUSED*/
+ void
+ex_diffupdate(eap)
+ exarg_T *eap;
+{
+ buf_T *buf;
+ int idx_orig;
+ int idx_new;
+ char_u *tmp_orig;
+ char_u *tmp_new;
+ char_u *tmp_diff;
+ FILE *fd;
+ int ok;
+
+ /* Delete all diffblocks. */
+ diff_clear();
+ diff_invalid = FALSE;
+
+ /* Use the first buffer as the original text. */
+ for (idx_orig = 0; idx_orig < DB_COUNT; ++idx_orig)
+ if (diffbuf[idx_orig] != NULL)
+ break;
+ if (idx_orig == DB_COUNT)
+ return;
+
+ /* Only need to do something when there is another buffer. */
+ for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new)
+ if (diffbuf[idx_new] != NULL)
+ break;
+ if (idx_new == DB_COUNT)
+ return;
+
+ /* We need three temp file names. */
+ tmp_orig = vim_tempname('o');
+ tmp_new = vim_tempname('n');
+ tmp_diff = vim_tempname('d');
+ if (tmp_orig == NULL || tmp_new == NULL || tmp_diff == NULL)
+ goto theend;
+
+ /*
+ * Do a quick test if "diff" really works. Otherwise it looks like there
+ * are no differences. Can't use the return value, it's non-zero when
+ * there are differences.
+ * May try twice, first with "-a" and then without.
+ */
+ for (;;)
+ {
+ ok = FALSE;
+ fd = fopen((char *)tmp_orig, "w");
+ if (fd != NULL)
+ {
+ fwrite("line1\n", (size_t)6, (size_t)1, fd);
+ fclose(fd);
+ fd = fopen((char *)tmp_new, "w");
+ if (fd != NULL)
+ {
+ fwrite("line2\n", (size_t)6, (size_t)1, fd);
+ fclose(fd);
+ diff_file(tmp_orig, tmp_new, tmp_diff);
+ fd = fopen((char *)tmp_diff, "r");
+ if (fd != NULL)
+ {
+ char_u linebuf[LBUFLEN];
+
+ for (;;)
+ {
+ /* There must be a line that contains "1c1". */
+ if (tag_fgets(linebuf, LBUFLEN, fd))
+ break;
+ if (STRNCMP(linebuf, "1c1", 3) == 0)
+ ok = TRUE;
+ }
+ fclose(fd);
+ }
+ mch_remove(tmp_diff);
+ mch_remove(tmp_new);
+ }
+ mch_remove(tmp_orig);
+ }
+
+#ifdef FEAT_EVAL
+ /* When using 'diffexpr' break here. */
+ if (*p_dex != NUL)
+ break;
+#endif
+
+#if defined(MSWIN) || defined(MSDOS)
+ /* If the "-a" argument works, also check if "--binary" works. */
+ if (ok && diff_a_works == MAYBE && diff_bin_works == MAYBE)
+ {
+ diff_a_works = TRUE;
+ diff_bin_works = TRUE;
+ continue;
+ }
+ if (!ok && diff_a_works == TRUE && diff_bin_works == TRUE)
+ {
+ /* Tried --binary, but it failed. "-a" works though. */
+ diff_bin_works = FALSE;
+ ok = TRUE;
+ }
+#endif
+
+ /* If we checked if "-a" works already, break here. */
+ if (diff_a_works != MAYBE)
+ break;
+ diff_a_works = ok;
+
+ /* If "-a" works break here, otherwise retry without "-a". */
+ if (ok)
+ break;
+ }
+ if (!ok)
+ {
+ EMSG(_("E97: Cannot create diffs"));
+ diff_a_works = MAYBE;
+#if defined(MSWIN) || defined(MSDOS)
+ diff_bin_works = MAYBE;
+#endif
+ goto theend;
+ }
+
+ /* Write the first buffer to a tempfile. */
+ buf = diffbuf[idx_orig];
+ if (diff_write(buf, tmp_orig) == FAIL)
+ goto theend;
+
+ /* Make a difference between the first buffer and every other. */
+ for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new)
+ {
+ buf = diffbuf[idx_new];
+ if (buf == NULL)
+ continue;
+ if (diff_write(buf, tmp_new) == FAIL)
+ continue;
+ diff_file(tmp_orig, tmp_new, tmp_diff);
+
+ /* Read the diff output and add each entry to the diff list. */
+ diff_read(idx_orig, idx_new, tmp_diff);
+ mch_remove(tmp_diff);
+ mch_remove(tmp_new);
+ }
+ mch_remove(tmp_orig);
+
+ diff_redraw(TRUE);
+
+theend:
+ vim_free(tmp_orig);
+ vim_free(tmp_new);
+ vim_free(tmp_diff);
+}
+
+/*
+ * Make a diff between files "tmp_orig" and "tmp_new", results in "tmp_diff".
+ */
+ static void
+diff_file(tmp_orig, tmp_new, tmp_diff)
+ char_u *tmp_orig;
+ char_u *tmp_new;
+ char_u *tmp_diff;
+{
+ char_u *cmd;
+
+#ifdef FEAT_EVAL
+ if (*p_dex != NUL)
+ /* Use 'diffexpr' to generate the diff file. */
+ eval_diff(tmp_orig, tmp_new, tmp_diff);
+ else
+#endif
+ {
+ cmd = alloc((unsigned)(STRLEN(tmp_orig) + STRLEN(tmp_new)
+ + STRLEN(tmp_diff) + STRLEN(p_srr) + 27));
+ if (cmd != NULL)
+ {
+ /* Build the diff command and execute it. Always use -a, binary
+ * differences are of no use. Ignore errors, diff returns
+ * non-zero when differences have been found. */
+ sprintf((char *)cmd, "diff %s%s%s%s%s %s",
+ diff_a_works == FALSE ? "" : "-a ",
+#if defined(MSWIN) || defined(MSDOS)
+ diff_bin_works == TRUE ? "--binary " : "",
+#else
+ "",
+#endif
+ (diff_flags & DIFF_IWHITE) ? "-b " : "",
+ (diff_flags & DIFF_ICASE) ? "-i " : "",
+ tmp_orig, tmp_new);
+ append_redir(cmd, p_srr, tmp_diff);
+ (void)call_shell(cmd, SHELL_FILTER|SHELL_SILENT|SHELL_DOOUT);
+ vim_free(cmd);
+ }
+ }
+}
+
+/*
+ * Create a new version of a file from the current buffer and a diff file.
+ * The buffer is written to a file, also for unmodified buffers (the file
+ * could have been produced by autocommands, e.g. the netrw plugin).
+ */
+ void
+ex_diffpatch(eap)
+ exarg_T *eap;
+{
+ char_u *tmp_orig; /* name of original temp file */
+ char_u *tmp_new; /* name of patched temp file */
+ char_u *buf = NULL;
+ win_T *old_curwin = curwin;
+ char_u *newname = NULL; /* name of patched file buffer */
+#ifdef UNIX
+ char_u dirbuf[MAXPATHL];
+ char_u *fullname = NULL;
+#endif
+#ifdef FEAT_BROWSE
+ char_u *browseFile = NULL;
+ int browse_flag = cmdmod.browse;
+#endif
+
+#ifdef FEAT_BROWSE
+ if (cmdmod.browse)
+ {
+ browseFile = do_browse(FALSE, (char_u *)_("Patch file"),
+ eap->arg, NULL, NULL, BROWSE_FILTER_ALL_FILES, NULL);
+ if (browseFile == NULL)
+ return; /* operation cancelled */
+ eap->arg = browseFile;
+ cmdmod.browse = FALSE; /* don't let do_ecmd() browse again */
+ }
+#endif
+
+ /* We need two temp file names. */
+ tmp_orig = vim_tempname('o');
+ tmp_new = vim_tempname('n');
+ if (tmp_orig == NULL || tmp_new == NULL)
+ goto theend;
+
+ /* Write the current buffer to "tmp_orig". */
+ if (buf_write(curbuf, tmp_orig, NULL,
+ (linenr_T)1, curbuf->b_ml.ml_line_count,
+ NULL, FALSE, FALSE, FALSE, TRUE) == FAIL)
+ goto theend;
+
+#ifdef UNIX
+ /* Get the absolute path of the patchfile, changing directory below. */
+ fullname = FullName_save(eap->arg, FALSE);
+#endif
+ buf = alloc((unsigned)(STRLEN(tmp_orig) + (
+# ifdef UNIX
+ fullname != NULL ? STRLEN(fullname) :
+# endif
+ STRLEN(eap->arg)) + STRLEN(tmp_new) + 16));
+ if (buf == NULL)
+ goto theend;
+
+#ifdef UNIX
+ /* Temporaraly chdir to /tmp, to avoid patching files in the current
+ * directory when the patch file contains more than one patch. When we
+ * have our own temp dir use that instead, it will be cleaned up when we
+ * exit (any .rej files created). Don't change directory if we can't
+ * return to the current. */
+ if (mch_dirname(dirbuf, MAXPATHL) != OK || mch_chdir((char *)dirbuf) != 0)
+ dirbuf[0] = NUL;
+ else
+ {
+# ifdef TEMPDIRNAMES
+ if (vim_tempdir != NULL)
+ mch_chdir((char *)vim_tempdir);
+ else
+# endif
+ mch_chdir("/tmp");
+ shorten_fnames(TRUE);
+ }
+#endif
+
+#ifdef FEAT_EVAL
+ if (*p_pex != NUL)
+ /* Use 'patchexpr' to generate the new file. */
+ eval_patch(tmp_orig,
+# ifdef UNIX
+ fullname != NULL ? fullname :
+# endif
+ eap->arg, tmp_new);
+ else
+#endif
+ {
+ /* Build the patch command and execute it. Ignore errors. Switch to
+ * cooked mode to allow the user to respond to prompts. */
+ sprintf((char *)buf, "patch -o %s %s < \"%s\"", tmp_new, tmp_orig,
+# ifdef UNIX
+ fullname != NULL ? fullname :
+# endif
+ eap->arg);
+ (void)call_shell(buf, SHELL_FILTER | SHELL_COOKED);
+ }
+
+#ifdef UNIX
+ if (dirbuf[0] != NUL)
+ {
+ if (mch_chdir((char *)dirbuf) != 0)
+ EMSG(_(e_prev_dir));
+ shorten_fnames(TRUE);
+ }
+#endif
+
+ /* patch probably has written over the screen */
+ redraw_later(CLEAR);
+
+ /* Delete any .orig or .rej file created. */
+ STRCPY(buf, tmp_new);
+ STRCAT(buf, ".orig");
+ mch_remove(buf);
+ STRCPY(buf, tmp_new);
+ STRCAT(buf, ".rej");
+ mch_remove(buf);
+
+ if (curbuf->b_fname != NULL)
+ {
+ newname = vim_strnsave(curbuf->b_fname,
+ (int)(STRLEN(curbuf->b_fname) + 4));
+ if (newname != NULL)
+ STRCAT(newname, ".new");
+ }
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ if (win_split(0, 0) != FAIL)
+ {
+ /* Pretend it was a ":split fname" command */
+ eap->cmdidx = CMD_split;
+ eap->arg = tmp_new;
+ do_exedit(eap, old_curwin);
+
+ if (curwin != old_curwin) /* split must have worked */
+ {
+ /* Set 'diff', 'scrollbind' on and 'wrap' off. */
+ diff_win_options(curwin, TRUE);
+ diff_win_options(old_curwin, TRUE);
+
+ if (newname != NULL)
+ {
+ /* do a ":file filename.new" on the patched buffer */
+ eap->arg = newname;
+ ex_file(eap);
+
+#ifdef FEAT_AUTOCMD
+ /* Do filetype detection with the new name. */
+ do_cmdline_cmd((char_u *)":doau filetypedetect BufRead");
+#endif
+ }
+ }
+ }
+
+theend:
+ if (tmp_orig != NULL)
+ mch_remove(tmp_orig);
+ vim_free(tmp_orig);
+ if (tmp_new != NULL)
+ mch_remove(tmp_new);
+ vim_free(tmp_new);
+ vim_free(newname);
+ vim_free(buf);
+#ifdef UNIX
+ vim_free(fullname);
+#endif
+#ifdef FEAT_BROWSE
+ vim_free(browseFile);
+ cmdmod.browse = browse_flag;
+#endif
+}
+
+/*
+ * Split the window and edit another file, setting options to show the diffs.
+ */
+ void
+ex_diffsplit(eap)
+ exarg_T *eap;
+{
+ win_T *old_curwin = curwin;
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ if (win_split(0, 0) != FAIL)
+ {
+ /* Pretend it was a ":split fname" command */
+ eap->cmdidx = CMD_split;
+ do_exedit(eap, old_curwin);
+
+ if (curwin != old_curwin) /* split must have worked */
+ {
+ /* Set 'diff', 'scrollbind' on and 'wrap' off. */
+ diff_win_options(curwin, TRUE);
+ diff_win_options(old_curwin, TRUE);
+ }
+ }
+}
+
+/*
+ * Set options to show difs for the current window.
+ */
+/*ARGSUSED*/
+ void
+ex_diffthis(eap)
+ exarg_T *eap;
+{
+ /* Set 'diff', 'scrollbind' on and 'wrap' off. */
+ diff_win_options(curwin, TRUE);
+}
+
+/*
+ * Set options in window "wp" for diff mode.
+ */
+ void
+diff_win_options(wp, addbuf)
+ win_T *wp;
+ int addbuf; /* Add buffer to diff. */
+{
+ wp->w_p_diff = TRUE;
+ wp->w_p_scb = TRUE;
+ wp->w_p_wrap = FALSE;
+# ifdef FEAT_FOLDING
+ {
+ win_T *old_curwin = curwin;
+
+ curwin = wp;
+ curbuf = curwin->w_buffer;
+ set_string_option_direct((char_u *)"fdm", -1, (char_u *)"diff",
+ OPT_LOCAL|OPT_FREE);
+ curwin = old_curwin;
+ curbuf = curwin->w_buffer;
+ wp->w_p_fdc = 2;
+ wp->w_p_fen = TRUE;
+ wp->w_p_fdl = 0;
+ foldUpdateAll(wp);
+ changed_window_setting(); /* make sure topline is not halfway a fold */
+ }
+# endif
+#ifdef FEAT_SCROLLBIND
+ if (vim_strchr(p_sbo, 'h') == NULL)
+ do_cmdline_cmd((char_u *)"set sbo+=hor");
+#endif
+
+ if (addbuf)
+ diff_buf_add(wp->w_buffer);
+ redraw_win_later(wp, NOT_VALID);
+}
+
+/*
+ * Read the diff output and add each entry to the diff list.
+ */
+ static void
+diff_read(idx_orig, idx_new, fname)
+ int idx_orig; /* idx of original file */
+ int idx_new; /* idx of new file */
+ char_u *fname; /* name of diff output file */
+{
+ FILE *fd;
+ diff_T *dprev = NULL;
+ diff_T *dp = first_diff;
+ diff_T *dn, *dpl;
+ long f1, l1, f2, l2;
+ char_u linebuf[LBUFLEN]; /* only need to hold the diff line */
+ int difftype;
+ char_u *p;
+ long off;
+ int i;
+ linenr_T lnum_orig, lnum_new;
+ long count_orig, count_new;
+ int notset = TRUE; /* block "*dp" not set yet */
+
+ fd = fopen((char *)fname, "r");
+ if (fd == NULL)
+ {
+ EMSG(_("E98: Cannot read diff output"));
+ return;
+ }
+
+ for (;;)
+ {
+ if (tag_fgets(linebuf, LBUFLEN, fd))
+ break; /* end of file */
+ if (!isdigit(*linebuf))
+ continue; /* not the start of a diff block */
+
+ /* This line must be one of three formats:
+ * {first}[,{last}]c{first}[,{last}]
+ * {first}a{first}[,{last}]
+ * {first}[,{last}]d{first}
+ */
+ p = linebuf;
+ f1 = getdigits(&p);
+ if (*p == ',')
+ {
+ ++p;
+ l1 = getdigits(&p);
+ }
+ else
+ l1 = f1;
+ if (*p != 'a' && *p != 'c' && *p != 'd')
+ continue; /* invalid diff format */
+ difftype = *p++;
+ f2 = getdigits(&p);
+ if (*p == ',')
+ {
+ ++p;
+ l2 = getdigits(&p);
+ }
+ else
+ l2 = f2;
+ if (l1 < f1 || l2 < f2)
+ continue; /* invalid line range */
+
+ if (difftype == 'a')
+ {
+ lnum_orig = f1 + 1;
+ count_orig = 0;
+ }
+ else
+ {
+ lnum_orig = f1;
+ count_orig = l1 - f1 + 1;
+ }
+ if (difftype == 'd')
+ {
+ lnum_new = f2 + 1;
+ count_new = 0;
+ }
+ else
+ {
+ lnum_new = f2;
+ count_new = l2 - f2 + 1;
+ }
+
+ /* Go over blocks before the change, for which orig and new are equal.
+ * Copy blocks from orig to new. */
+ while (dp != NULL
+ && lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig])
+ {
+ if (notset)
+ diff_copy_entry(dprev, dp, idx_orig, idx_new);
+ dprev = dp;
+ dp = dp->df_next;
+ notset = TRUE;
+ }
+
+ if (dp != NULL
+ && lnum_orig <= dp->df_lnum[idx_orig] + dp->df_count[idx_orig]
+ && lnum_orig + count_orig >= dp->df_lnum[idx_orig])
+ {
+ /* New block overlaps with existing block(s).
+ * First find last block that overlaps. */
+ for (dpl = dp; dpl->df_next != NULL; dpl = dpl->df_next)
+ if (lnum_orig + count_orig < dpl->df_next->df_lnum[idx_orig])
+ break;
+
+ /* If the newly found block starts before the old one, set the
+ * start back a number of lines. */
+ off = dp->df_lnum[idx_orig] - lnum_orig;
+ if (off > 0)
+ {
+ for (i = idx_orig; i < idx_new; ++i)
+ if (diffbuf[i] != NULL)
+ dp->df_lnum[i] -= off;
+ dp->df_lnum[idx_new] = lnum_new;
+ dp->df_count[idx_new] = count_new;
+ }
+ else if (notset)
+ {
+ /* new block inside existing one, adjust new block */
+ dp->df_lnum[idx_new] = lnum_new + off;
+ dp->df_count[idx_new] = count_new - off;
+ }
+ else
+ /* second overlap of new block with existing block */
+ dp->df_count[idx_new] += count_new - count_orig;
+
+ /* Adjust the size of the block to include all the lines to the
+ * end of the existing block or the new diff, whatever ends last. */
+ off = (lnum_orig + count_orig)
+ - (dpl->df_lnum[idx_orig] + dpl->df_count[idx_orig]);
+ if (off < 0)
+ {
+ /* new change ends in existing block, adjust the end if not
+ * done already */
+ if (notset)
+ dp->df_count[idx_new] += -off;
+ off = 0;
+ }
+ for (i = idx_orig; i < idx_new + !notset; ++i)
+ if (diffbuf[i] != NULL)
+ dp->df_count[i] = dpl->df_lnum[i] + dpl->df_count[i]
+ - dp->df_lnum[i] + off;
+
+ /* Delete the diff blocks that have been merged into one. */
+ dn = dp->df_next;
+ dp->df_next = dpl->df_next;
+ while (dn != dp->df_next)
+ {
+ dpl = dn->df_next;
+ vim_free(dn);
+ dn = dpl;
+ }
+ }
+ else
+ {
+ /* Allocate a new diffblock. */
+ dp = diff_alloc_new(dprev, dp);
+ if (dp == NULL)
+ return;
+
+ dp->df_lnum[idx_orig] = lnum_orig;
+ dp->df_count[idx_orig] = count_orig;
+ dp->df_lnum[idx_new] = lnum_new;
+ dp->df_count[idx_new] = count_new;
+
+ /* Set values for other buffers, these must be equal to the
+ * original buffer, otherwise there would have been a change
+ * already. */
+ for (i = idx_orig + 1; i < idx_new; ++i)
+ if (diffbuf[i] != NULL)
+ diff_copy_entry(dprev, dp, idx_orig, i);
+ }
+ notset = FALSE; /* "*dp" has been set */
+ }
+
+ /* for remaining diff blocks orig and new are equal */
+ while (dp != NULL)
+ {
+ if (notset)
+ diff_copy_entry(dprev, dp, idx_orig, idx_new);
+ dprev = dp;
+ dp = dp->df_next;
+ notset = TRUE;
+ }
+
+ fclose(fd);
+}
+
+/*
+ * Copy an entry at "dp" from "idx_orig" to "idx_new".
+ */
+ static void
+diff_copy_entry(dprev, dp, idx_orig, idx_new)
+ diff_T *dprev;
+ diff_T *dp;
+ int idx_orig;
+ int idx_new;
+{
+ long off;
+
+ if (dprev == NULL)
+ off = 0;
+ else
+ off = (dprev->df_lnum[idx_orig] + dprev->df_count[idx_orig])
+ - (dprev->df_lnum[idx_new] + dprev->df_count[idx_new]);
+ dp->df_lnum[idx_new] = dp->df_lnum[idx_orig] - off;
+ dp->df_count[idx_new] = dp->df_count[idx_orig];
+}
+
+/*
+ * Clear the list of diffblocks.
+ */
+ static void
+diff_clear()
+{
+ diff_T *p, *next_p;
+
+ for (p = first_diff; p != NULL; p = next_p)
+ {
+ next_p = p->df_next;
+ vim_free(p);
+ }
+ first_diff = NULL;
+}
+
+/*
+ * Check diff status for line "lnum" in buffer "buf":
+ * Returns 0 for nothing special
+ * Returns -1 for a line that should be highlighted as changed.
+ * Returns -2 for a line that should be highlighted as added/deleted.
+ * Returns > 0 for inserting that many filler lines above it (never happens
+ * when 'diffopt' doesn't contain "filler").
+ * This should only be used for windows where 'diff' is set.
+ */
+ int
+diff_check(wp, lnum)
+ win_T *wp;
+ linenr_T lnum;
+{
+ int idx; /* index in diffbuf[] for this buffer */
+ diff_T *dp;
+ int maxcount;
+ int i;
+ buf_T *buf = wp->w_buffer;
+ int cmp;
+
+ if (diff_invalid)
+ ex_diffupdate(NULL); /* update after a big change */
+
+ if (first_diff == NULL || !wp->w_p_diff) /* no diffs at all */
+ return 0;
+
+ /* safety check: "lnum" must be a buffer line */
+ if (lnum < 1 || lnum > buf->b_ml.ml_line_count + 1)
+ return 0;
+
+ idx = diff_buf_idx(buf);
+ if (idx == DB_COUNT)
+ return 0; /* no diffs for buffer "buf" */
+
+#ifdef FEAT_FOLDING
+ /* A closed fold never has filler lines. */
+ if (hasFoldingWin(wp, lnum, NULL, NULL, TRUE, NULL))
+ return 0;
+#endif
+
+ /* search for a change that includes "lnum" in the list of diffblocks. */
+ for (dp = first_diff; dp != NULL; dp = dp->df_next)
+ if (lnum <= dp->df_lnum[idx] + dp->df_count[idx])
+ break;
+ if (dp == NULL || lnum < dp->df_lnum[idx])
+ return 0;
+
+ if (lnum < dp->df_lnum[idx] + dp->df_count[idx])
+ {
+ int zero = FALSE;
+
+ /* Changed or inserted line. If the other buffers have a count of
+ * zero, the lines were inserted. If the other buffers have the same
+ * count, check if the lines are identical. */
+ cmp = FALSE;
+ for (i = 0; i < DB_COUNT; ++i)
+ if (i != idx && diffbuf[i] != NULL)
+ {
+ if (dp->df_count[i] == 0)
+ zero = TRUE;
+ else
+ {
+ if (dp->df_count[i] != dp->df_count[idx])
+ return -1; /* nr of lines changed. */
+ cmp = TRUE;
+ }
+ }
+ if (cmp)
+ {
+ /* Compare all lines. If they are equal the lines were inserted
+ * in some buffers, deleted in others, but not changed. */
+ for (i = 0; i < DB_COUNT; ++i)
+ if (i != idx && diffbuf[i] != NULL && dp->df_count[i] != 0)
+ if (!diff_equal_entry(dp, idx, i))
+ return -1;
+ }
+ /* If there is no buffer with zero lines then there is no difference
+ * any longer. Happens when making a change (or undo) that removes
+ * the difference. Can't remove the entry here, we might be halfway
+ * updating the window. Just report the text as unchanged. Other
+ * windows might still show the change though. */
+ if (zero == FALSE)
+ return 0;
+ return -2;
+ }
+
+ /* If 'diffopt' doesn't contain "filler", return 0. */
+ if (!(diff_flags & DIFF_FILLER))
+ return 0;
+
+ /* Insert filler lines above the line just below the change. Will return
+ * 0 when this buf had the max count. */
+ maxcount = 0;
+ for (i = 0; i < DB_COUNT; ++i)
+ if (diffbuf[i] != NULL && dp->df_count[i] > maxcount)
+ maxcount = dp->df_count[i];
+ return maxcount - dp->df_count[idx];
+}
+
+/*
+ * Compare two entries in diff "*dp" and return TRUE if they are equal.
+ */
+ static int
+diff_equal_entry(dp, idx1, idx2)
+ diff_T *dp;
+ int idx1;
+ int idx2;
+{
+ int i;
+ char_u *line;
+ int cmp;
+
+ if (dp->df_count[idx1] != dp->df_count[idx2])
+ return FALSE;
+ if (diff_check_sanity(dp) == FAIL)
+ return FALSE;
+ for (i = 0; i < dp->df_count[idx1]; ++i)
+ {
+ line = vim_strsave(ml_get_buf(diffbuf[idx1],
+ dp->df_lnum[idx1] + i, FALSE));
+ if (line == NULL)
+ return FALSE;
+ cmp = diff_cmp(line, ml_get_buf(diffbuf[idx2],
+ dp->df_lnum[idx2] + i, FALSE));
+ vim_free(line);
+ if (cmp != 0)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Compare strings "s1" and "s2" according to 'diffopt'.
+ * Return non-zero when they are different.
+ */
+ static int
+diff_cmp(s1, s2)
+ char_u *s1;
+ char_u *s2;
+{
+ char_u *p1, *p2;
+#ifdef FEAT_MBYTE
+ int l;
+#endif
+
+ if ((diff_flags & (DIFF_ICASE | DIFF_IWHITE)) == 0)
+ return STRCMP(s1, s2);
+ if ((diff_flags & DIFF_ICASE) && !(diff_flags & DIFF_IWHITE))
+ return MB_STRICMP(s1, s2);
+
+ /* Ignore white space changes and possibly ignore case. */
+ p1 = s1;
+ p2 = s2;
+ while (*p1 != NUL && *p2 != NUL)
+ {
+ if (vim_iswhite(*p1) && vim_iswhite(*p2))
+ {
+ p1 = skipwhite(p1);
+ p2 = skipwhite(p2);
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ l = (*mb_ptr2len_check)(p1);
+ if (l != (*mb_ptr2len_check)(p2))
+ break;
+ if (l > 1)
+ {
+ if (STRNCMP(p1, p2, l) != 0
+ && (!enc_utf8
+ || !(diff_flags & DIFF_ICASE)
+ || utf_fold(utf_ptr2char(p1))
+ != utf_fold(utf_ptr2char(p2))))
+ break;
+ p1 += l;
+ p2 += l;
+ }
+ else
+#endif
+ {
+ if (*p1 != *p2 && (!(diff_flags & DIFF_ICASE)
+ || TOLOWER_LOC(*p1) != TOLOWER_LOC(*p2)))
+ break;
+ ++p1;
+ ++p2;
+ }
+ }
+ }
+
+ /* Ignore trailing white space. */
+ p1 = skipwhite(p1);
+ p2 = skipwhite(p2);
+ if (*p1 != NUL || *p2 != NUL)
+ return 1;
+ return 0;
+}
+
+/*
+ * Return the number of filler lines above "lnum".
+ */
+ int
+diff_check_fill(wp, lnum)
+ win_T *wp;
+ linenr_T lnum;
+{
+ int n;
+
+ /* be quick when there are no filler lines */
+ if (!(diff_flags & DIFF_FILLER))
+ return 0;
+ n = diff_check(wp, lnum);
+ if (n <= 0)
+ return 0;
+ return n;
+}
+
+/*
+ * Set the topline of "towin" to match the position in "fromwin", so that they
+ * show the same diff'ed lines.
+ */
+ void
+diff_set_topline(fromwin, towin)
+ win_T *fromwin;
+ win_T *towin;
+{
+ buf_T *buf = fromwin->w_buffer;
+ linenr_T lnum = fromwin->w_topline;
+ int idx;
+ diff_T *dp;
+ int i;
+
+ idx = diff_buf_idx(buf);
+ if (idx == DB_COUNT)
+ return; /* safety check */
+
+ if (diff_invalid)
+ ex_diffupdate(NULL); /* update after a big change */
+
+ towin->w_topfill = 0;
+
+ /* search for a change that includes "lnum" in the list of diffblocks. */
+ for (dp = first_diff; dp != NULL; dp = dp->df_next)
+ if (lnum <= dp->df_lnum[idx] + dp->df_count[idx])
+ break;
+ if (dp == NULL)
+ {
+ /* After last change, compute topline relative to end of file; no
+ * filler lines. */
+ towin->w_topline = towin->w_buffer->b_ml.ml_line_count
+ - (buf->b_ml.ml_line_count - lnum);
+ }
+ else
+ {
+ /* Find index for "towin". */
+ i = diff_buf_idx(towin->w_buffer);
+ if (i == DB_COUNT)
+ return; /* safety check */
+
+ towin->w_topline = lnum + (dp->df_lnum[i] - dp->df_lnum[idx]);
+ if (lnum >= dp->df_lnum[idx])
+ {
+ /* Inside a change: compute filler lines. */
+ if (dp->df_count[i] == dp->df_count[idx])
+ towin->w_topfill = fromwin->w_topfill;
+ else if (dp->df_count[i] > dp->df_count[idx])
+ {
+ if (lnum == dp->df_lnum[idx] + dp->df_count[idx])
+ towin->w_topline = dp->df_lnum[i] + dp->df_count[i]
+ - fromwin->w_topfill;
+ }
+ else
+ {
+ if (towin->w_topline >= dp->df_lnum[i] + dp->df_count[i])
+ {
+ if (diff_flags & DIFF_FILLER)
+ towin->w_topfill = dp->df_lnum[idx]
+ + dp->df_count[idx] - lnum;
+ towin->w_topline = dp->df_lnum[i] + dp->df_count[i];
+ }
+ }
+ }
+ }
+
+ /* safety check (if diff info gets outdated strange things may happen) */
+ towin->w_botfill = FALSE;
+ if (towin->w_topline > towin->w_buffer->b_ml.ml_line_count)
+ {
+ towin->w_topline = towin->w_buffer->b_ml.ml_line_count;
+ towin->w_botfill = TRUE;
+ }
+ if (towin->w_topline < 1)
+ {
+ towin->w_topline = 1;
+ towin->w_topfill = 0;
+ }
+
+ /* When w_topline changes need to recompute w_botline and cursor position */
+ invalidate_botline_win(towin);
+ changed_line_abv_curs_win(towin);
+
+ check_topfill(towin, FALSE);
+#ifdef FEAT_FOLDING
+ (void)hasFoldingWin(towin, towin->w_topline, &towin->w_topline,
+ NULL, TRUE, NULL);
+#endif
+}
+
+/*
+ * This is called when 'diffopt' is changed.
+ */
+ int
+diffopt_changed()
+{
+ char_u *p;
+ int diff_context_new = 6;
+ int diff_flags_new = 0;
+
+ p = p_dip;
+ while (*p != NUL)
+ {
+ if (STRNCMP(p, "filler", 6) == 0)
+ {
+ p += 6;
+ diff_flags_new |= DIFF_FILLER;
+ }
+ else if (STRNCMP(p, "context:", 8) == 0 && VIM_ISDIGIT(p[8]))
+ {
+ p += 8;
+ diff_context_new = getdigits(&p);
+ }
+ else if (STRNCMP(p, "icase", 5) == 0)
+ {
+ p += 5;
+ diff_flags_new |= DIFF_ICASE;
+ }
+ else if (STRNCMP(p, "iwhite", 6) == 0)
+ {
+ p += 6;
+ diff_flags_new |= DIFF_IWHITE;
+ }
+ if (*p != ',' && *p != NUL)
+ return FAIL;
+ if (*p == ',')
+ ++p;
+ }
+
+ /* If "icase" or "iwhite" was added or removed, need to update the diff. */
+ if (diff_flags != diff_flags_new)
+ diff_invalid = TRUE;
+
+ diff_flags = diff_flags_new;
+ diff_context = diff_context_new;
+
+ diff_redraw(TRUE);
+
+ /* recompute the scroll binding with the new option value, may
+ * remove or add filler lines */
+ check_scrollbind((linenr_T)0, 0L);
+
+ return OK;
+}
+
+/*
+ * Find the difference within a changed line.
+ * Returns TRUE if the line was added, no other buffer has it.
+ */
+ int
+diff_find_change(wp, lnum, startp, endp)
+ win_T *wp;
+ linenr_T lnum;
+ int *startp; /* first char of the change */
+ int *endp; /* last char of the change */
+{
+ char_u *line_org;
+ char_u *line_new;
+ int i;
+ int si, ei_org, ei_new;
+ diff_T *dp;
+ int idx;
+ int off;
+ int added = TRUE;
+
+ /* Make a copy of the line, the next ml_get() will invalidate it. */
+ line_org = vim_strsave(ml_get_buf(wp->w_buffer, lnum, FALSE));
+ if (line_org == NULL)
+ return FALSE;
+
+ idx = diff_buf_idx(wp->w_buffer);
+ if (idx == DB_COUNT) /* cannot happen */
+ return FALSE;
+
+ /* search for a change that includes "lnum" in the list of diffblocks. */
+ for (dp = first_diff; dp != NULL; dp = dp->df_next)
+ if (lnum <= dp->df_lnum[idx] + dp->df_count[idx])
+ break;
+ if (dp == NULL || diff_check_sanity(dp) == FAIL)
+ return FALSE;
+
+ off = lnum - dp->df_lnum[idx];
+
+ for (i = 0; i < DB_COUNT; ++i)
+ if (diffbuf[i] != NULL && i != idx)
+ {
+ /* Skip lines that are not in the other change (filler lines). */
+ if (off >= dp->df_count[i])
+ continue;
+ added = FALSE;
+ line_new = ml_get_buf(diffbuf[i], dp->df_lnum[i] + off, FALSE);
+
+ /* Search for start of difference */
+ for (si = 0; line_org[si] != NUL && line_org[si] == line_new[si]; )
+ ++si;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ /* Move back to first byte of character in both lines (may
+ * have "nn^" in line_org and "n^ in line_new). */
+ si -= (*mb_head_off)(line_org, line_org + si);
+ si -= (*mb_head_off)(line_new, line_new + si);
+ }
+#endif
+ if (*startp > si)
+ *startp = si;
+
+ /* Search for end of difference, if any. */
+ if (line_org[si] != NUL || line_new[si] != NUL)
+ {
+ ei_org = (int)STRLEN(line_org);
+ ei_new = (int)STRLEN(line_new);
+ while (ei_org >= *startp && ei_new >= *startp
+ && ei_org >= 0 && ei_new >= 0
+ && line_org[ei_org] == line_new[ei_new])
+ {
+ --ei_org;
+ --ei_new;
+ }
+ if (*endp < ei_org)
+ *endp = ei_org;
+ }
+ }
+
+ vim_free(line_org);
+ return added;
+}
+
+#if defined(FEAT_FOLDING) || defined(PROTO)
+/*
+ * Return TRUE if line "lnum" is not close to a diff block, this line should
+ * be in a fold.
+ * Return FALSE if there are no diff blocks at all in this window.
+ */
+ int
+diff_infold(wp, lnum)
+ win_T *wp;
+ linenr_T lnum;
+{
+ int i;
+ int idx = -1;
+ int other = FALSE;
+ diff_T *dp;
+
+ /* Return if 'diff' isn't set. */
+ if (!wp->w_p_diff)
+ return FALSE;
+
+ for (i = 0; i < DB_COUNT; ++i)
+ {
+ if (diffbuf[i] == wp->w_buffer)
+ idx = i;
+ else if (diffbuf[i] != NULL)
+ other = TRUE;
+ }
+
+ /* return here if there are no diffs in the window */
+ if (idx == -1 || !other)
+ return FALSE;
+
+ if (diff_invalid)
+ ex_diffupdate(NULL); /* update after a big change */
+
+ /* Return if there are no diff blocks. All lines will be folded. */
+ if (first_diff == NULL)
+ return TRUE;
+
+ for (dp = first_diff; dp != NULL; dp = dp->df_next)
+ {
+ /* If this change is below the line there can't be any further match. */
+ if (dp->df_lnum[idx] - diff_context > lnum)
+ break;
+ /* If this change ends before the line we have a match. */
+ if (dp->df_lnum[idx] + dp->df_count[idx] + diff_context > lnum)
+ return FALSE;
+ }
+ return TRUE;
+}
+#endif
+
+/*
+ * "dp" and "do" commands.
+ */
+ void
+nv_diffgetput(put)
+ int put;
+{
+ exarg_T ea;
+
+ ea.arg = (char_u *)"";
+ if (put)
+ ea.cmdidx = CMD_diffput;
+ else
+ ea.cmdidx = CMD_diffget;
+ ea.addr_count = 0;
+ ea.line1 = curwin->w_cursor.lnum;
+ ea.line2 = curwin->w_cursor.lnum;
+ ex_diffgetput(&ea);
+}
+
+/*
+ * ":diffget"
+ * ":diffput"
+ */
+ void
+ex_diffgetput(eap)
+ exarg_T *eap;
+{
+ linenr_T lnum;
+ int count;
+ linenr_T off = 0;
+ diff_T *dp;
+ diff_T *dprev;
+ diff_T *dfree;
+ int idx_cur;
+ int idx_other;
+ int idx_from;
+ int idx_to;
+ int i;
+ int added;
+ char_u *p;
+ aco_save_T aco;
+ buf_T *buf;
+ int start_skip, end_skip;
+ int new_count;
+
+ /* Find the current buffer in the list of diff buffers. */
+ idx_cur = diff_buf_idx(curbuf);
+ if (idx_cur == DB_COUNT)
+ {
+ EMSG(_("E99: Current buffer is not in diff mode"));
+ return;
+ }
+
+ if (*eap->arg == NUL)
+ {
+ /* No argument: Find the other buffer in the list of diff buffers. */
+ for (idx_other = 0; idx_other < DB_COUNT; ++idx_other)
+ if (diffbuf[idx_other] != curbuf && diffbuf[idx_other] != NULL)
+ break;
+ if (idx_other == DB_COUNT)
+ {
+ EMSG(_("E100: No other buffer in diff mode"));
+ return;
+ }
+
+ /* Check that there isn't a third buffer in the list */
+ for (i = idx_other + 1; i < DB_COUNT; ++i)
+ if (diffbuf[i] != curbuf && diffbuf[i] != NULL)
+ {
+ EMSG(_("E101: More than two buffers in diff mode, don't know which one to use"));
+ return;
+ }
+ }
+ else
+ {
+ /* Buffer number or pattern given. Ignore trailing white space. */
+ p = eap->arg + STRLEN(eap->arg);
+ while (p > eap->arg && vim_iswhite(p[-1]))
+ --p;
+ for (i = 0; vim_isdigit(eap->arg[i]) && eap->arg + i < p; ++i)
+ ;
+ if (eap->arg + i == p) /* digits only */
+ i = atol((char *)eap->arg);
+ else
+ {
+ i = buflist_findpat(eap->arg, p, FALSE, TRUE);
+ if (i < 0)
+ return; /* error message already given */
+ }
+ buf = buflist_findnr(i);
+ if (buf == NULL)
+ {
+ EMSG2(_("E102: Can't find buffer \"%s\""), eap->arg);
+ return;
+ }
+ idx_other = diff_buf_idx(buf);
+ if (idx_other == DB_COUNT)
+ {
+ EMSG2(_("E103: Buffer \"%s\" is not in diff mode"), eap->arg);
+ return;
+ }
+ }
+
+ diff_busy = TRUE;
+
+ /* When no range given include the line above or below the cursor. */
+ if (eap->addr_count == 0)
+ {
+ /* Make it possible that ":diffget" on the last line gets line below
+ * the cursor line when there is no difference above the cursor. */
+ if (eap->cmdidx == CMD_diffget
+ && eap->line1 == curbuf->b_ml.ml_line_count
+ && diff_check(curwin, eap->line1) == 0
+ && (eap->line1 == 1 || diff_check(curwin, eap->line1 - 1) == 0))
+ ++eap->line2;
+ else if (eap->line1 > 0)
+ --eap->line1;
+ }
+
+ if (eap->cmdidx == CMD_diffget)
+ {
+ idx_from = idx_other;
+ idx_to = idx_cur;
+ }
+ else
+ {
+ idx_from = idx_cur;
+ idx_to = idx_other;
+ /* Need to make the other buffer the current buffer to be able to make
+ * changes in it. */
+ /* set curwin/curbuf to buf and save a few things */
+ aucmd_prepbuf(&aco, diffbuf[idx_other]);
+ }
+
+ dprev = NULL;
+ for (dp = first_diff; dp != NULL; )
+ {
+ if (dp->df_lnum[idx_cur] > eap->line2 + off)
+ break; /* past the range that was specified */
+
+ dfree = NULL;
+ lnum = dp->df_lnum[idx_to];
+ count = dp->df_count[idx_to];
+ if (dp->df_lnum[idx_cur] + dp->df_count[idx_cur] > eap->line1 + off
+ && u_save(lnum - 1, lnum + count) != FAIL)
+ {
+ /* Inside the specified range and saving for undo worked. */
+ start_skip = 0;
+ end_skip = 0;
+ if (eap->addr_count > 0)
+ {
+ /* A range was specified: check if lines need to be skipped. */
+ start_skip = eap->line1 + off - dp->df_lnum[idx_cur];
+ if (start_skip > 0)
+ {
+ /* range starts below start of current diff block */
+ if (start_skip > count)
+ {
+ lnum += count;
+ count = 0;
+ }
+ else
+ {
+ count -= start_skip;
+ lnum += start_skip;
+ }
+ }
+ else
+ start_skip = 0;
+
+ end_skip = dp->df_lnum[idx_cur] + dp->df_count[idx_cur] - 1
+ - (eap->line2 + off);
+ if (end_skip > 0)
+ {
+ /* range ends above end of current/from diff block */
+ if (idx_cur == idx_from) /* :diffput */
+ {
+ i = dp->df_count[idx_cur] - start_skip - end_skip;
+ if (count > i)
+ count = i;
+ }
+ else /* :diffget */
+ {
+ count -= end_skip;
+ end_skip = dp->df_count[idx_from] - start_skip - count;
+ if (end_skip < 0)
+ end_skip = 0;
+ }
+ }
+ else
+ end_skip = 0;
+ }
+
+ added = 0;
+ for (i = 0; i < count; ++i)
+ {
+ ml_delete(lnum, FALSE);
+ --added;
+ }
+ for (i = 0; i < dp->df_count[idx_from] - start_skip - end_skip; ++i)
+ {
+ linenr_T nr;
+
+ nr = dp->df_lnum[idx_from] + start_skip + i;
+ if (nr > diffbuf[idx_from]->b_ml.ml_line_count)
+ break;
+ p = vim_strsave(ml_get_buf(diffbuf[idx_from], nr, FALSE));
+ if (p != NULL)
+ {
+ ml_append(lnum + i - 1, p, 0, FALSE);
+ vim_free(p);
+ ++added;
+ }
+ }
+ new_count = dp->df_count[idx_to] + added;
+ dp->df_count[idx_to] = new_count;
+
+ if (start_skip == 0 && end_skip == 0)
+ {
+ /* Check if there are any other buffers and if the diff is
+ * equal in them. */
+ for (i = 0; i < DB_COUNT; ++i)
+ if (diffbuf[i] != NULL && i != idx_from && i != idx_to
+ && !diff_equal_entry(dp, idx_from, i))
+ break;
+ if (i == DB_COUNT)
+ {
+ /* delete the diff entry, the buffers are now equal here */
+ dfree = dp;
+ dp = dp->df_next;
+ if (dprev == NULL)
+ first_diff = dp;
+ else
+ dprev->df_next = dp;
+ }
+ }
+
+ /* Adjust marks. This will change the following entries! */
+ if (added != 0)
+ {
+ mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, (long)added);
+ if (curwin->w_cursor.lnum >= lnum)
+ {
+ /* Adjust the cursor position if it's in/after the changed
+ * lines. */
+ if (curwin->w_cursor.lnum >= lnum + count)
+ curwin->w_cursor.lnum += added;
+ else if (added < 0)
+ curwin->w_cursor.lnum = lnum;
+ }
+ }
+ changed_lines(lnum, 0, lnum + count, (long)added);
+
+ if (dfree != NULL)
+ {
+ /* Diff is deleted, update folds in other windows. */
+#ifdef FEAT_FOLDING
+ diff_fold_update(dfree, idx_to);
+#endif
+ vim_free(dfree);
+ }
+ else
+ /* mark_adjust() may have changed the count in a wrong way */
+ dp->df_count[idx_to] = new_count;
+
+ /* When changing the current buffer, keep track of line numbers */
+ if (idx_cur == idx_to)
+ off += added;
+ }
+
+ /* If before the range or not deleted, go to next diff. */
+ if (dfree == NULL)
+ {
+ dprev = dp;
+ dp = dp->df_next;
+ }
+ }
+
+ /* restore curwin/curbuf and a few other things */
+ if (idx_other == idx_to)
+ {
+ /* Syncing undo only works for the current buffer, but we change
+ * another buffer. Sync undo if the command was typed. This isn't
+ * 100% right when ":diffput" is used in a function or mapping. */
+ if (KeyTyped)
+ u_sync();
+ aucmd_restbuf(&aco);
+ }
+
+ diff_busy = FALSE;
+
+ /* Check that the cursor is on a valid character and update it's position.
+ * When there were filler lines the topline has become invalid. */
+ check_cursor();
+ changed_line_abv_curs();
+
+ /* Also need to redraw the other buffers. */
+ diff_redraw(FALSE);
+}
+
+#ifdef FEAT_FOLDING
+/*
+ * Update folds for all diff buffers for entry "dp".
+ * Skip buffer with index "skip_idx".
+ * When there are no diffs, all folds are removed.
+ */
+ static void
+diff_fold_update(dp, skip_idx)
+ diff_T *dp;
+ int skip_idx;
+{
+ int i;
+ win_T *wp;
+
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ for (i = 0; i < DB_COUNT; ++i)
+ if (diffbuf[i] == wp->w_buffer && i != skip_idx)
+ foldUpdate(wp, dp->df_lnum[i],
+ dp->df_lnum[i] + dp->df_count[i]);
+}
+#endif
+
+/*
+ * Return TRUE if buffer "buf" is in diff-mode.
+ */
+ int
+diff_mode_buf(buf)
+ buf_T *buf;
+{
+ return diff_buf_idx(buf) != DB_COUNT;
+}
+
+/*
+ * Move "count" times in direction "dir" to the next diff block.
+ * Return FAIL if there isn't such a diff block.
+ */
+ int
+diff_move_to(dir, count)
+ int dir;
+ long count;
+{
+ int idx;
+ linenr_T lnum = curwin->w_cursor.lnum;
+ diff_T *dp;
+
+ idx = diff_buf_idx(curbuf);
+ if (idx == DB_COUNT || first_diff == NULL)
+ return FAIL;
+
+ if (diff_invalid)
+ ex_diffupdate(NULL); /* update after a big change */
+
+ if (first_diff == NULL) /* no diffs today */
+ return FAIL;
+
+ while (--count >= 0)
+ {
+ /* Check if already before first diff. */
+ if (dir == BACKWARD && lnum <= first_diff->df_lnum[idx])
+ break;
+
+ for (dp = first_diff; ; dp = dp->df_next)
+ {
+ if (dp == NULL)
+ break;
+ if ((dir == FORWARD && lnum < dp->df_lnum[idx])
+ || (dir == BACKWARD
+ && (dp->df_next == NULL
+ || lnum <= dp->df_next->df_lnum[idx])))
+ {
+ lnum = dp->df_lnum[idx];
+ break;
+ }
+ }
+ }
+
+ /* don't end up past the end of the file */
+ if (lnum > curbuf->b_ml.ml_line_count)
+ lnum = curbuf->b_ml.ml_line_count;
+
+ /* When the cursor didn't move at all we fail. */
+ if (lnum == curwin->w_cursor.lnum)
+ return FAIL;
+
+ setpcmark();
+ curwin->w_cursor.lnum = lnum;
+ curwin->w_cursor.col = 0;
+
+ return OK;
+}
+
+#if defined(FEAT_FOLDING) || defined(PROTO)
+/*
+ * For line "lnum" in the current window find the equivalent lnum in window
+ * "wp", compensating for inserted/deleted lines.
+ */
+ linenr_T
+diff_lnum_win(lnum, wp)
+ linenr_T lnum;
+ win_T *wp;
+{
+ diff_T *dp;
+ int idx;
+ int i;
+ linenr_T n;
+
+ idx = diff_buf_idx(curbuf);
+ if (idx == DB_COUNT) /* safety check */
+ return (linenr_T)0;
+
+ if (diff_invalid)
+ ex_diffupdate(NULL); /* update after a big change */
+
+ /* search for a change that includes "lnum" in the list of diffblocks. */
+ for (dp = first_diff; dp != NULL; dp = dp->df_next)
+ if (lnum <= dp->df_lnum[idx] + dp->df_count[idx])
+ break;
+
+ /* When after the last change, compute relative to the last line number. */
+ if (dp == NULL)
+ return wp->w_buffer->b_ml.ml_line_count
+ - (curbuf->b_ml.ml_line_count - lnum);
+
+ /* Find index for "wp". */
+ i = diff_buf_idx(wp->w_buffer);
+ if (i == DB_COUNT) /* safety check */
+ return (linenr_T)0;
+
+ n = lnum + (dp->df_lnum[i] - dp->df_lnum[idx]);
+ if (n > dp->df_lnum[i] + dp->df_count[i])
+ n = dp->df_lnum[i] + dp->df_count[i];
+ return n;
+}
+#endif
+
+#endif /* FEAT_DIFF */
diff --git a/src/digraph.c b/src/digraph.c
new file mode 100644
index 000000000..de61ce2c7
--- /dev/null
+++ b/src/digraph.c
@@ -0,0 +1,2513 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * digraph.c: code for digraphs
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_DIGRAPHS) || defined(PROTO)
+
+#ifdef FEAT_MBYTE
+typedef int result_T;
+#else
+typedef char_u result_T;
+#endif
+
+typedef struct digraph
+{
+ char_u char1;
+ char_u char2;
+ result_T result;
+} digr_T;
+
+static int getexactdigraph __ARGS((int, int, int));
+static void printdigraph __ARGS((digr_T *));
+
+/* digraphs added by the user */
+static garray_T user_digraphs = {0, 0, sizeof(digr_T), 10, NULL};
+
+/*
+ * Note: Characters marked with XX are not included literally, because some
+ * compilers cannot handle them (Amiga SAS/C is the most picky one).
+ */
+#if defined(MSDOS) || defined(OS2)
+ /*
+ * MSDOS digraphs.
+ */
+digr_T digraphdefault[] =
+ {{'C', ',', 128}, /* ~@ XX */
+ {'u', '"', 129}, /* */
+ {'e', '\'', 130}, /* ‚ */
+ {'a', '^', 131}, /* ƒ */
+ {'a', '"', 132}, /* „ */
+ {'a', '`', 133}, /* … */
+ {'a', '@', 134}, /* † */
+ {'c', ',', 135}, /* ~G XX */
+ {'e', '^', 136}, /* ~H XX */
+ {'e', '"', 137}, /* ‰ */
+ {'e', '`', 138}, /* Š */
+ {'i', '"', 139}, /* ‹ */
+ {'i', '^', 140}, /* Π*/
+ {'i', '`', 141}, /* */
+ {'A', '"', 142}, /* ~N XX */
+ {'A', '@', 143}, /* */
+ {'E', '\'', 144}, /* */
+ {'a', 'e', 145}, /* ‘ */
+ {'A', 'E', 146}, /* ’ */
+ {'o', '^', 147}, /* “ */
+ {'o', '"', 148}, /* ” */
+ {'o', '`', 149}, /* • */
+ {'u', '^', 150}, /* – */
+ {'u', '`', 151}, /* — */
+ {'y', '"', 152}, /* ˜ */
+ {'O', '"', 153}, /* ™ */
+ {'U', '"', 154}, /* š */
+ {'c', '|', 155}, /* › */
+ {'$', '$', 156}, /* œ */
+ {'Y', '-', 157}, /* ~] XX */
+ {'P', 't', 158}, /* ž */
+ {'f', 'f', 159}, /* Ÿ */
+ {'a', '\'', 160}, /*   */
+ {'i', '\'', 161}, /* ¡ */
+ {'o', '\'', 162}, /* ¢ */
+ {'u', '\'', 163}, /* x XX */
+ {'n', '~', 164}, /* ¤ */
+ {'N', '~', 165}, /* ¥ */
+ {'a', 'a', 166}, /* ¦ */
+ {'o', 'o', 167}, /* § */
+ {'~', '?', 168}, /* ¨ */
+ {'-', 'a', 169}, /* © */
+ {'a', '-', 170}, /* ª */
+ {'1', '2', 171}, /* « */
+ {'1', '4', 172}, /* ¬ */
+ {'~', '!', 173}, /* ­ */
+ {'<', '<', 174}, /* ® */
+ {'>', '>', 175}, /* ¯ */
+
+ {'s', 's', 225}, /* á */
+ {'j', 'u', 230}, /* æ */
+ {'o', '/', 237}, /* í */
+ {'+', '-', 241}, /* ñ */
+ {'>', '=', 242}, /* ò */
+ {'<', '=', 243}, /* ó */
+ {':', '-', 246}, /* ö */
+ {'~', '~', 247}, /* ÷ */
+ {'~', 'o', 248}, /* ø */
+ {'2', '2', 253}, /* ý */
+ {NUL, NUL, NUL}
+ };
+
+#else /* !MSDOS && !OS2 */
+# ifdef __MINT__
+
+ /*
+ * ATARI digraphs
+ */
+digr_T digraphdefault[] =
+ {{'C', ',', 128}, /* ~@ XX */
+ {'u', '"', 129}, /* */
+ {'e', '\'', 130}, /* ‚ */
+ {'a', '^', 131}, /* ƒ */
+ {'a', '"', 132}, /* „ */
+ {'a', '`', 133}, /* … */
+ {'a', '@', 134}, /* † */
+ {'c', ',', 135}, /* ~G XX */
+ {'e', '^', 136}, /* ~H XX */
+ {'e', '"', 137}, /* ‰ */
+ {'e', '`', 138}, /* Š */
+ {'i', '"', 139}, /* ‹ */
+ {'i', '^', 140}, /* Π*/
+ {'i', '`', 141}, /* */
+ {'A', '"', 142}, /* Ž */
+ {'A', '@', 143}, /* */
+ {'E', '\'', 144}, /* */
+ {'a', 'e', 145}, /* ‘ */
+ {'A', 'E', 146}, /* ’ */
+ {'o', '^', 147}, /* “ */
+ {'o', '"', 148}, /* ” */
+ {'o', '`', 149}, /* • */
+ {'u', '^', 150}, /* – */
+ {'u', '`', 151}, /* — */
+ {'y', '"', 152}, /* ˜ */
+ {'O', '"', 153}, /* ™ */
+ {'U', '"', 154}, /* š */
+ {'c', '|', 155}, /* › */
+ {'$', '$', 156}, /* œ */
+ {'Y', '-', 157}, /* ~] XX */
+ {'s', 's', 158}, /* ž */
+ {'f', 'f', 159}, /* Ÿ */
+ {'a', '\'', 160}, /*   */
+ {'i', '\'', 161}, /* ¡ */
+ {'o', '\'', 162}, /* ¢ */
+ {'u', '\'', 163}, /* £ */
+ {'n', '~', 164}, /* ¤ */
+ {'N', '~', 165}, /* ¥ */
+ {'a', 'a', 166}, /* ¦ */
+ {'o', 'o', 167}, /* § */
+ {'~', '?', 168}, /* ¨ */
+ {'-', 'a', 169}, /* © */
+ {'a', '-', 170}, /* ª */
+ {'1', '2', 171}, /* « */
+ {'1', '4', 172}, /* ¬ */
+ {'~', '!', 173}, /* ­ */
+ {'<', '<', 174}, /* ® */
+ {'>', '>', 175}, /* ¯ */
+ {'j', 'u', 230}, /* æ */
+ {'o', '/', 237}, /* í */
+ {'+', '-', 241}, /* ñ */
+ {'>', '=', 242}, /* ò */
+ {'<', '=', 243}, /* ó */
+ {':', '-', 246}, /* ö */
+ {'~', '~', 247}, /* ÷ */
+ {'~', 'o', 248}, /* ø */
+ {'2', '2', 253}, /* ý */
+ {NUL, NUL, NUL}
+ };
+
+# else /* !__MINT__ */
+# ifdef HPUX_DIGRAPHS
+
+ /*
+ * different HPUX digraphs
+ */
+digr_T digraphdefault[] =
+ {{'A', '`', 161}, /* ¡ */
+ {'A', '^', 162}, /* ¢ */
+ {'E', '`', 163}, /* £ */
+ {'E', '^', 164}, /* ¤ */
+ {'E', '"', 165}, /* ¥ */
+ {'I', '^', 166}, /* ¦ */
+ {'I', '"', 167}, /* § */
+ {'\'', '\'', 168}, /* ¨ */
+ {'`', '`', 169}, /* © */
+ {'^', '^', 170}, /* ª */
+ {'"', '"', 171}, /* « */
+ {'~', '~', 172}, /* ¬ */
+ {'U', '`', 173}, /* ­ */
+ {'U', '^', 174}, /* ® */
+ {'L', '=', 175}, /* ¯ */
+ {'~', '_', 176}, /* ° */
+ {'Y', '\'', 177}, /* ± */
+ {'y', '\'', 178}, /* ² */
+ {'~', 'o', 179}, /* ³ */
+ {'C', ',', 180}, /* ´ */
+ {'c', ',', 181}, /* µ */
+ {'N', '~', 182}, /* ¶ */
+ {'n', '~', 183}, /* · */
+ {'~', '!', 184}, /* ¸ */
+ {'~', '?', 185}, /* ¹ */
+ {'o', 'x', 186}, /* º */
+ {'L', '-', 187}, /* » */
+ {'Y', '=', 188}, /* ¼ */
+ {'p', 'p', 189}, /* ½ */
+ {'f', 'l', 190}, /* ¾ */
+ {'c', '|', 191}, /* ¿ */
+ {'a', '^', 192}, /* À */
+ {'e', '^', 193}, /* Á */
+ {'o', '^', 194}, /* Â */
+ {'u', '^', 195}, /* Ã */
+ {'a', '\'', 196}, /* Ä */
+ {'e', '\'', 197}, /* Å */
+ {'o', '\'', 198}, /* Æ */
+ {'u', '\'', 199}, /* Ç */
+ {'a', '`', 200}, /* È */
+ {'e', '`', 201}, /* É */
+ {'o', '`', 202}, /* Ê */
+ {'u', '`', 203}, /* Ë */
+ {'a', '"', 204}, /* Ì */
+ {'e', '"', 205}, /* Í */
+ {'o', '"', 206}, /* Î */
+ {'u', '"', 207}, /* Ï */
+ {'A', 'o', 208}, /* Ð */
+ {'i', '^', 209}, /* Ñ */
+ {'O', '/', 210}, /* Ò */
+ {'A', 'E', 211}, /* Ó */
+ {'a', 'o', 212}, /* Ô */
+ {'i', '\'', 213}, /* Õ */
+ {'o', '/', 214}, /* Ö */
+ {'a', 'e', 215}, /* × */
+ {'A', '"', 216}, /* Ø */
+ {'i', '`', 217}, /* Ù */
+ {'O', '"', 218}, /* Ú */
+ {'U', '"', 219}, /* Û */
+ {'E', '\'', 220}, /* Ü */
+ {'i', '"', 221}, /* Ý */
+ {'s', 's', 222}, /* Þ */
+ {'O', '^', 223}, /* ß */
+ {'A', '\'', 224}, /* à */
+ {'A', '~', 225}, /* á */
+ {'a', '~', 226}, /* â */
+ {'D', '-', 227}, /* ã */
+ {'d', '-', 228}, /* ä */
+ {'I', '\'', 229}, /* å */
+ {'I', '`', 230}, /* æ */
+ {'O', '\'', 231}, /* ç */
+ {'O', '`', 232}, /* è */
+ {'O', '~', 233}, /* é */
+ {'o', '~', 234}, /* ê */
+ {'S', '~', 235}, /* ë */
+ {'s', '~', 236}, /* ì */
+ {'U', '\'', 237}, /* í */
+ {'Y', '"', 238}, /* î */
+ {'y', '"', 239}, /* ï */
+ {'p', '-', 240}, /* ð */
+ {'p', '~', 241}, /* ñ */
+ {'~', '.', 242}, /* ò */
+ {'j', 'u', 243}, /* ó */
+ {'P', 'p', 244}, /* ô */
+ {'3', '4', 245}, /* õ */
+ {'-', '-', 246}, /* ö */
+ {'1', '4', 247}, /* ÷ */
+ {'1', '2', 248}, /* ø */
+ {'a', '_', 249}, /* ù */
+ {'o', '_', 250}, /* ú */
+ {'<', '<', 251}, /* û */
+ {'x', 'x', 252}, /* ü */
+ {'>', '>', 253}, /* ý */
+ {'+', '-', 254}, /* þ */
+ {'n', 'u', 255}, /* x XX */
+ {NUL, NUL, NUL}
+ };
+
+# else /* !HPUX_DIGRAPHS */
+
+# ifdef EBCDIC
+
+ /*
+ * EBCDIC - ISO digraphs
+ * TODO: EBCDIC Table is Code-Page 1047
+ */
+digr_T digraphdefault[] =
+ {{'a', '^', 66}, /* â */
+ {'a', '"', 67}, /* ä */
+ {'a', '`', 68}, /* à */
+ {'a', '\'', 69}, /* á */
+ {'a', '~', 70}, /* ã */
+ {'a', '@', 71}, /* å */
+ {'a', 'a', 71}, /* å */
+ {'c', ',', 72}, /* ç */
+ {'n', '~', 73}, /* ñ */
+ {'c', '|', 74}, /* ¢ */
+ {'e', '\'', 81}, /* é */
+ {'e', '^', 82}, /* ê */
+ {'e', '"', 83}, /* ë */
+ {'e', '`', 84}, /* è */
+ {'i', '\'', 85}, /* í */
+ {'i', '^', 86}, /* î */
+ {'i', '"', 87}, /* ï */
+ {'i', '`', 88}, /* ì */
+ {'s', 's', 89}, /* ß */
+ {'A', '^', 98}, /* Â */
+ {'A', '"', 99}, /* Ä */
+ {'A', '`', 100}, /* À */
+ {'A', '\'', 101}, /* Á */
+ {'A', '~', 102}, /* Ã */
+ {'A', '@', 103}, /* Å */
+ {'A', 'A', 103}, /* Å */
+ {'C', ',', 104}, /* Ç */
+ {'N', '~', 105}, /* Ñ */
+ {'|', '|', 106}, /* ¦ */
+ {'o', '/', 112}, /* ø */
+ {'E', '\'', 113}, /* É */
+ {'E', '^', 114}, /* Ê */
+ {'E', '"', 115}, /* Ë */
+ {'E', '`', 116}, /* È */
+ {'I', '\'', 117}, /* Í */
+ {'I', '^', 118}, /* Î */
+ {'I', '"', 119}, /* Ï */
+ {'I', '`', 120}, /* Ì */
+ {'O', '/', 128}, /* 0/ XX */
+ {'<', '<', 138}, /* « */
+ {'>', '>', 139}, /* » */
+ {'d', '-', 140}, /* ð */
+ {'y', '\'', 141}, /* ý */
+ {'i', 'p', 142}, /* þ */
+ {'+', '-', 143}, /* ± */
+ {'~', 'o', 144}, /* ° */
+ {'a', '-', 154}, /* ª */
+ {'o', '-', 155}, /* º */
+ {'a', 'e', 156}, /* æ */
+ {',', ',', 157}, /* , XX */
+ {'A', 'E', 158}, /* Æ */
+ {'o', 'x', 159}, /* ¤ - currency symbol in ISO 8859-1 */
+ {'e', '=', 159}, /* ¤ - euro symbol in ISO 8859-15 */
+ {'j', 'u', 160}, /* µ */
+ {'y', '"', 167}, /* x XX */
+ {'~', '!', 170}, /* ¡ */
+ {'~', '?', 171}, /* ¿ */
+ {'D', '-', 172}, /* Ð */
+ {'I', 'p', 174}, /* Þ */
+ {'r', 'O', 175}, /* ® */
+ {'-', ',', 176}, /* ¬ */
+ {'$', '$', 177}, /* £ */
+ {'Y', '-', 178}, /* ¥ */
+ {'~', '.', 179}, /* · */
+ {'c', 'O', 180}, /* © */
+ {'p', 'a', 181}, /* § */
+ {'p', 'p', 182}, /* ¶ */
+ {'1', '4', 183}, /* ¼ */
+ {'1', '2', 184}, /* ½ */
+ {'3', '4', 185}, /* ¾ */
+ {'Y', '\'', 186}, /* Ý */
+ {'"', '"', 187}, /* ¨ */
+ {'-', '=', 188}, /* ¯ */
+ {'\'', '\'', 190}, /* ´ */
+ {'O', 'E', 191}, /* × - OE in ISO 8859-15 */
+ {'/', '\\', 191}, /* × - multiplication symbol in ISO 8859-1 */
+ {'-', '-', 202}, /* ­ */
+ {'o', '^', 203}, /* ô */
+ {'o', '"', 204}, /* ö */
+ {'o', '`', 205}, /* ò */
+ {'o', '\'', 206}, /* ó */
+ {'o', '~', 207}, /* õ */
+ {'1', '1', 218}, /* ¹ */
+ {'u', '^', 219}, /* û */
+ {'u', '"', 220}, /* ü */
+ {'u', '`', 221}, /* ù */
+ {'u', '\'', 222}, /* ú */
+ {':', '-', 225}, /* ÷ - division symbol in ISO 8859-1 */
+ {'o', 'e', 225}, /* ÷ - oe in ISO 8859-15 */
+ {'2', '2', 234}, /* ² */
+ {'O', '^', 235}, /* Ô */
+ {'O', '"', 236}, /* Ö */
+ {'O', '`', 237}, /* Ò */
+ {'O', '\'', 238}, /* Ó */
+ {'O', '~', 239}, /* Õ */
+ {'3', '3', 250}, /* ³ */
+ {'U', '^', 251}, /* Û */
+ {'U', '"', 252}, /* Ü */
+ {'U', '`', 253}, /* Ù */
+ {'U', '\'', 254}, /* Ú */
+ {NUL, NUL, NUL}
+ };
+
+# else
+# if defined(MACOS) && !defined(FEAT_MBYTE)
+
+ /*
+ * Macintosh digraphs
+ */
+digr_T digraphdefault[] =
+ {{'a', 't', 64}, /* @ */
+ {'A', '"', 128}, /* ~@ XX */
+ {'A', 'o', 129}, /* Å */
+ {'C', ',', 130}, /* Ç */
+ {'E', '\'', 131}, /* É */
+ {'N', '~', 132}, /* Ñ */
+ {'O', '"', 133}, /* Ö */
+ {'U', '"', 134}, /* Ü */
+ {'a', '\'', 135}, /* ~G XX */
+ {'a', '`', 136}, /* ~H XX */
+ {'a', '^', 137}, /* â */
+ {'a', '"', 138}, /* ä */
+ {'a', '~', 139}, /* ã */
+ {'a', 'o', 140}, /* å */
+ {'c', ',', 141}, /* ç */
+ {'e', '\'', 142}, /* é */
+ {'e', '`', 143}, /* è */
+ {'e', '^', 144}, /* ê */
+ {'e', '"', 145}, /* ë */
+ {'i', '\'', 146}, /* í */
+ {'i', '`', 147}, /* ì */
+ {'i', '^', 148}, /* î */
+ {'i', '"', 149}, /* ï */
+ {'n', '~', 150}, /* ñ */
+ {'o', '\'', 151}, /* ó */
+ {'o', '`', 152}, /* ò */
+ {'o', '^', 153}, /* ô */
+ {'o', '"', 154}, /* ö */
+ {'o', '~', 155}, /* o */
+ {'u', '\'', 156}, /* ú */
+ {'u', '`', 157}, /* ~] XX */
+ {'u', '^', 158}, /* û */
+ {'u', '"', 159}, /* ü */
+ {'+', '_', 160}, /* Ý */
+ {'~', 'o', 161}, /* ° */
+ {'c', '|', 162}, /* ¢ */
+ {'$', '$', 163}, /* £ */
+ {'p', 'a', 164}, /* § */
+ {'.', '.', 165}, /* * */
+ {'P', 'P', 166}, /* ¶ */
+ {'s', 's', 167}, /* ß */
+ {'r', 'O', 168}, /* ® */
+ {'c', 'O', 169}, /* © */
+ {'T', 'M', 170}, /* */
+ {'=', '/', 173}, /* ‚ */
+ {'A', 'E', 174}, /* Æ */
+ {'O', '/', 175}, /* Ø */
+ {'0', '0', 176}, /* ƒ */
+ {'+', '-', 177}, /* ± */
+ {'<', '=', 178}, /* ¾ */
+ {'>', '=', 179}, /* „ */
+ {'Y', '-', 180}, /* ¥ */
+ {'j', 'u', 181}, /* µ */
+ {'m', 'u', 181}, /* µ */
+ {'d', 'd', 182}, /* */
+ {'S', 'S', 183}, /* … */
+ {'S', 'I', 183}, /* … */
+ {'P', 'I', 184}, /* ½ */
+ {'p', 'i', 185}, /* ¼ */
+ {'I', 'I', 186}, /* † */
+ {'a', '-', 187}, /* » */
+ {'o', '-', 188}, /* º */
+ {'O', 'M', 189}, /* ½ */
+ {'a', 'e', 190}, /* æ */
+ {'o', '/', 191}, /* ø */
+ {'~', '?', 192}, /* ¿ */
+ {'~', '!', 193}, /* ¡ */
+ {'-', ',', 194}, /* ¬ */
+ {'v', '-', 195}, /* ~H XX */
+ {'f', '-', 196}, /* Ÿ */
+ {'~', '~', 197}, /* ‰ */
+ {'D', 'E', 198}, /* */
+ {'<', '<', 199}, /* « */
+ {'>', '>', 200}, /* » */
+ {'.', ':', 201}, /* Š */
+ {'A', '`', 203}, /* À */
+ {'A', '~', 204}, /* Ã */
+ {'O', '~', 205}, /* Õ */
+ {'O', 'E', 206}, /* ‘ */
+ {'o', 'e', 207}, /* ¦ */
+ {'-', '.', 208}, /* - */
+ {'-', '-', 209}, /* - */
+ {'`', '`', 210}, /* " */
+ {'\'', '\'', 211}, /* " */
+ {'`', ' ', 212}, /* ' */
+ {'\'', ' ', 213}, /* ' */
+ {'-', ':', 214}, /* ÷ */
+ {'D', 'I', 215}, /* × */
+ {'y', ':', 216}, /* ÿ */
+ {'Y', ':', 217}, /* */
+ {'/', '/', 218}, /* Ž */
+ {'E', '=', 219}, /* ¤ Euro System >=8.5 */
+ {'o', 'x', 219}, /* ¤ Currency System <=8.1*/
+ {'<', ' ', 220}, /* Ð */
+ {'>', ' ', 221}, /* ð */
+ {'f', 'i', 222}, /* Þ */
+ {'f', 'l', 223}, /* þ */
+ {'+', '+', 224}, /* ý */
+ {'~', '.', 225}, /* · */
+ {',', ' ', 226}, /* ’ */
+ {',', ',', 227}, /* “ */
+ {'%', '.', 228}, /* ” */
+ {'%', '0', 228}, /* ” */
+ {'A', '^', 229}, /* Â */
+ {'E', '^', 230}, /* Ê */
+ {'A', '\'', 231}, /* Á */
+ {'E', '"', 232}, /* Ë */
+ {'E', '`', 233}, /* È */
+ {'I', '\'', 234}, /* Í */
+ {'I', '^', 235}, /* Î */
+ {'I', '"', 236}, /* Ï */
+ {'I', '`', 237}, /* Ì */
+ {'O', '\'', 238}, /* Ó */
+ {'O', '^', 239}, /* Ô */
+ {'A', 'P', 240}, /* • */
+ {'O', '`', 241}, /* Ò */
+ {'U', '\'', 242}, /* Ú */
+ {'U', '^', 243}, /* Û */
+ {'U', '`', 244}, /* Ù */
+ {'i', '.', 245}, /* ž */
+ {NUL, NUL, NUL}
+ };
+
+# else /* !MACOS */
+
+# ifdef OLD_DIGRAPHS
+
+ /*
+ * digraphs compatible with Vim 5.x
+ */
+digr_T digraphdefault[] =
+ {{'~', '!', 161}, /* ¡ */
+ {'c', '|', 162}, /* ¢ */
+ {'$', '$', 163}, /* £ */
+ {'o', 'x', 164}, /* ¤ - currency symbol in ISO 8859-1 */
+ {'e', '=', 164}, /* ¤ - euro symbol in ISO 8859-15 */
+ {'Y', '-', 165}, /* ¥ */
+ {'|', '|', 166}, /* ¦ */
+ {'p', 'a', 167}, /* § */
+ {'"', '"', 168}, /* ¨ */
+ {'c', 'O', 169}, /* © */
+ {'a', '-', 170}, /* ª */
+ {'<', '<', 171}, /* « */
+ {'-', ',', 172}, /* ¬ */
+ {'-', '-', 173}, /* ­ */
+ {'r', 'O', 174}, /* ® */
+ {'-', '=', 175}, /* ¯ */
+ {'~', 'o', 176}, /* ° */
+ {'+', '-', 177}, /* ± */
+ {'2', '2', 178}, /* ² */
+ {'3', '3', 179}, /* ³ */
+ {'\'', '\'', 180}, /* ´ */
+ {'j', 'u', 181}, /* µ */
+ {'p', 'p', 182}, /* ¶ */
+ {'~', '.', 183}, /* · */
+ {',', ',', 184}, /* ¸ */
+ {'1', '1', 185}, /* ¹ */
+ {'o', '-', 186}, /* º */
+ {'>', '>', 187}, /* » */
+ {'1', '4', 188}, /* ¼ */
+ {'1', '2', 189}, /* ½ */
+ {'3', '4', 190}, /* ¾ */
+ {'~', '?', 191}, /* ¿ */
+ {'A', '`', 192}, /* À */
+ {'A', '\'', 193}, /* Á */
+ {'A', '^', 194}, /* Â */
+ {'A', '~', 195}, /* Ã */
+ {'A', '"', 196}, /* Ä */
+ {'A', '@', 197}, /* Å */
+ {'A', 'A', 197}, /* Å */
+ {'A', 'E', 198}, /* Æ */
+ {'C', ',', 199}, /* Ç */
+ {'E', '`', 200}, /* È */
+ {'E', '\'', 201}, /* É */
+ {'E', '^', 202}, /* Ê */
+ {'E', '"', 203}, /* Ë */
+ {'I', '`', 204}, /* Ì */
+ {'I', '\'', 205}, /* Í */
+ {'I', '^', 206}, /* Î */
+ {'I', '"', 207}, /* Ï */
+ {'D', '-', 208}, /* Ð */
+ {'N', '~', 209}, /* Ñ */
+ {'O', '`', 210}, /* Ò */
+ {'O', '\'', 211}, /* Ó */
+ {'O', '^', 212}, /* Ô */
+ {'O', '~', 213}, /* Õ */
+ {'O', '"', 214}, /* Ö */
+ {'/', '\\', 215}, /* × - multiplication symbol in ISO 8859-1 */
+ {'O', 'E', 215}, /* × - OE in ISO 8859-15 */
+ {'O', '/', 216}, /* Ø */
+ {'U', '`', 217}, /* Ù */
+ {'U', '\'', 218}, /* Ú */
+ {'U', '^', 219}, /* Û */
+ {'U', '"', 220}, /* Ü */
+ {'Y', '\'', 221}, /* Ý */
+ {'I', 'p', 222}, /* Þ */
+ {'s', 's', 223}, /* ß */
+ {'a', '`', 224}, /* à */
+ {'a', '\'', 225}, /* á */
+ {'a', '^', 226}, /* â */
+ {'a', '~', 227}, /* ã */
+ {'a', '"', 228}, /* ä */
+ {'a', '@', 229}, /* å */
+ {'a', 'a', 229}, /* å */
+ {'a', 'e', 230}, /* æ */
+ {'c', ',', 231}, /* ç */
+ {'e', '`', 232}, /* è */
+ {'e', '\'', 233}, /* é */
+ {'e', '^', 234}, /* ê */
+ {'e', '"', 235}, /* ë */
+ {'i', '`', 236}, /* ì */
+ {'i', '\'', 237}, /* í */
+ {'i', '^', 238}, /* î */
+ {'i', '"', 239}, /* ï */
+ {'d', '-', 240}, /* ð */
+ {'n', '~', 241}, /* ñ */
+ {'o', '`', 242}, /* ò */
+ {'o', '\'', 243}, /* ó */
+ {'o', '^', 244}, /* ô */
+ {'o', '~', 245}, /* õ */
+ {'o', '"', 246}, /* ö */
+ {':', '-', 247}, /* ÷ - division symbol in ISO 8859-1 */
+ {'o', 'e', 247}, /* ÷ - oe in ISO 8859-15 */
+ {'o', '/', 248}, /* ø */
+ {'u', '`', 249}, /* ù */
+ {'u', '\'', 250}, /* ú */
+ {'u', '^', 251}, /* û */
+ {'u', '"', 252}, /* ü */
+ {'y', '\'', 253}, /* ý */
+ {'i', 'p', 254}, /* þ */
+ {'y', '"', 255}, /* x XX */
+ {NUL, NUL, NUL}
+ };
+# else /* OLD_DIGRAPHS */
+
+ /*
+ * digraphs for Unicode from RFC1345
+ * (also work for ISO-8859-1 aka latin1)
+ */
+digr_T digraphdefault[] =
+ {
+ {'N', 'U', 0x0a}, /* LF for NUL */
+ {'S', 'H', 0x01},
+ {'S', 'X', 0x02},
+ {'E', 'X', 0x03},
+ {'E', 'T', 0x04},
+ {'E', 'Q', 0x05},
+ {'A', 'K', 0x06},
+ {'B', 'L', 0x07},
+ {'B', 'S', 0x08},
+ {'H', 'T', 0x09},
+ {'L', 'F', 0x0a},
+ {'V', 'T', 0x0b},
+ {'F', 'F', 0x0c},
+ {'C', 'R', 0x0d},
+ {'S', 'O', 0x0e},
+ {'S', 'I', 0x0f},
+ {'D', 'L', 0x10},
+ {'D', '1', 0x11},
+ {'D', '2', 0x12},
+ {'D', '3', 0x13},
+ {'D', '4', 0x14},
+ {'N', 'K', 0x15},
+ {'S', 'Y', 0x16},
+ {'E', 'B', 0x17},
+ {'C', 'N', 0x18},
+ {'E', 'M', 0x19},
+ {'S', 'B', 0x1a},
+ {'E', 'C', 0x1b},
+ {'F', 'S', 0x1c},
+ {'G', 'S', 0x1d},
+ {'R', 'S', 0x1e},
+ {'U', 'S', 0x1f},
+ {'S', 'P', 0x20},
+ {'N', 'b', 0x23},
+ {'D', 'O', 0x24},
+ {'A', 't', 0x40},
+ {'<', '(', 0x5b},
+ {'/', '/', 0x5c},
+ {')', '>', 0x5d},
+ {'\'', '>', 0x5e},
+ {'\'', '!', 0x60},
+ {'(', '!', 0x7b},
+ {'!', '!', 0x7c},
+ {'!', ')', 0x7d},
+ {'\'', '?', 0x7e},
+ {'D', 'T', 0x7f},
+ {'P', 'A', 0x80},
+ {'H', 'O', 0x81},
+ {'B', 'H', 0x82},
+ {'N', 'H', 0x83},
+ {'I', 'N', 0x84},
+ {'N', 'L', 0x85},
+ {'S', 'A', 0x86},
+ {'E', 'S', 0x87},
+ {'H', 'S', 0x88},
+ {'H', 'J', 0x89},
+ {'V', 'S', 0x8a},
+ {'P', 'D', 0x8b},
+ {'P', 'U', 0x8c},
+ {'R', 'I', 0x8d},
+ {'S', '2', 0x8e},
+ {'S', '3', 0x8f},
+ {'D', 'C', 0x90},
+ {'P', '1', 0x91},
+ {'P', '2', 0x92},
+ {'T', 'S', 0x93},
+ {'C', 'C', 0x94},
+ {'M', 'W', 0x95},
+ {'S', 'G', 0x96},
+ {'E', 'G', 0x97},
+ {'S', 'S', 0x98},
+ {'G', 'C', 0x99},
+ {'S', 'C', 0x9a},
+ {'C', 'I', 0x9b},
+ {'S', 'T', 0x9c},
+ {'O', 'C', 0x9d},
+ {'P', 'M', 0x9e},
+ {'A', 'C', 0x9f},
+ {'N', 'S', 0xa0},
+ {'!', 'I', 0xa1},
+ {'C', 't', 0xa2},
+ {'P', 'd', 0xa3},
+ {'C', 'u', 0xa4},
+ {'Y', 'e', 0xa5},
+ {'B', 'B', 0xa6},
+ {'S', 'E', 0xa7},
+ {'\'', ':', 0xa8},
+ {'C', 'o', 0xa9},
+ {'-', 'a', 0xaa},
+ {'<', '<', 0xab},
+ {'N', 'O', 0xac},
+ {'-', '-', 0xad},
+ {'R', 'g', 0xae},
+ {'\'', 'm', 0xaf},
+ {'D', 'G', 0xb0},
+ {'+', '-', 0xb1},
+ {'2', 'S', 0xb2},
+ {'3', 'S', 0xb3},
+ {'\'', '\'', 0xb4},
+ {'M', 'y', 0xb5},
+ {'P', 'I', 0xb6},
+ {'.', 'M', 0xb7},
+ {'\'', ',', 0xb8},
+ {'1', 'S', 0xb9},
+ {'-', 'o', 0xba},
+ {'>', '>', 0xbb},
+ {'1', '4', 0xbc},
+ {'1', '2', 0xbd},
+ {'3', '4', 0xbe},
+ {'?', 'I', 0xbf},
+ {'A', '!', 0xc0},
+ {'A', '\'', 0xc1},
+ {'A', '>', 0xc2},
+ {'A', '?', 0xc3},
+ {'A', ':', 0xc4},
+ {'A', 'A', 0xc5},
+ {'A', 'E', 0xc6},
+ {'C', ',', 0xc7},
+ {'E', '!', 0xc8},
+ {'E', '\'', 0xc9},
+ {'E', '>', 0xca},
+ {'E', ':', 0xcb},
+ {'I', '!', 0xcc},
+ {'I', '\'', 0xcd},
+ {'I', '>', 0xce},
+ {'I', ':', 0xcf},
+ {'D', '-', 0xd0},
+ {'N', '?', 0xd1},
+ {'O', '!', 0xd2},
+ {'O', '\'', 0xd3},
+ {'O', '>', 0xd4},
+ {'O', '?', 0xd5},
+ {'O', ':', 0xd6},
+ {'*', 'X', 0xd7},
+ {'O', '/', 0xd8},
+ {'U', '!', 0xd9},
+ {'U', '\'', 0xda},
+ {'U', '>', 0xdb},
+ {'U', ':', 0xdc},
+ {'Y', '\'', 0xdd},
+ {'T', 'H', 0xde},
+ {'s', 's', 0xdf},
+ {'a', '!', 0xe0},
+ {'a', '\'', 0xe1},
+ {'a', '>', 0xe2},
+ {'a', '?', 0xe3},
+ {'a', ':', 0xe4},
+ {'a', 'a', 0xe5},
+ {'a', 'e', 0xe6},
+ {'c', ',', 0xe7},
+ {'e', '!', 0xe8},
+ {'e', '\'', 0xe9},
+ {'e', '>', 0xea},
+ {'e', ':', 0xeb},
+ {'i', '!', 0xec},
+ {'i', '\'', 0xed},
+ {'i', '>', 0xee},
+ {'i', ':', 0xef},
+ {'d', '-', 0xf0},
+ {'n', '?', 0xf1},
+ {'o', '!', 0xf2},
+ {'o', '\'', 0xf3},
+ {'o', '>', 0xf4},
+ {'o', '?', 0xf5},
+ {'o', ':', 0xf6},
+ {'-', ':', 0xf7},
+ {'o', '/', 0xf8},
+ {'u', '!', 0xf9},
+ {'u', '\'', 0xfa},
+ {'u', '>', 0xfb},
+ {'u', ':', 0xfc},
+ {'y', '\'', 0xfd},
+ {'t', 'h', 0xfe},
+ {'y', ':', 0xff},
+
+# ifdef FEAT_MBYTE
+# define USE_UNICODE_DIGRAPHS
+
+ {'A', '-', 0x0100},
+ {'a', '-', 0x0101},
+ {'A', '(', 0x0102},
+ {'a', '(', 0x0103},
+ {'A', ';', 0x0104},
+ {'a', ';', 0x0105},
+ {'C', '\'', 0x0106},
+ {'c', '\'', 0x0107},
+ {'C', '>', 0x0108},
+ {'c', '>', 0x0109},
+ {'C', '.', 0x010a},
+ {'c', '.', 0x010b},
+ {'C', '<', 0x010c},
+ {'c', '<', 0x010d},
+ {'D', '<', 0x010e},
+ {'d', '<', 0x010f},
+ {'D', '/', 0x0110},
+ {'d', '/', 0x0111},
+ {'E', '-', 0x0112},
+ {'e', '-', 0x0113},
+ {'E', '(', 0x0114},
+ {'e', '(', 0x0115},
+ {'E', '.', 0x0116},
+ {'e', '.', 0x0117},
+ {'E', ';', 0x0118},
+ {'e', ';', 0x0119},
+ {'E', '<', 0x011a},
+ {'e', '<', 0x011b},
+ {'G', '>', 0x011c},
+ {'g', '>', 0x011d},
+ {'G', '(', 0x011e},
+ {'g', '(', 0x011f},
+ {'G', '.', 0x0120},
+ {'g', '.', 0x0121},
+ {'G', ',', 0x0122},
+ {'g', ',', 0x0123},
+ {'H', '>', 0x0124},
+ {'h', '>', 0x0125},
+ {'H', '/', 0x0126},
+ {'h', '/', 0x0127},
+ {'I', '?', 0x0128},
+ {'i', '?', 0x0129},
+ {'I', '-', 0x012a},
+ {'i', '-', 0x012b},
+ {'I', '(', 0x012c},
+ {'i', '(', 0x012d},
+ {'I', ';', 0x012e},
+ {'i', ';', 0x012f},
+ {'I', '.', 0x0130},
+ {'i', '.', 0x0131},
+ {'I', 'J', 0x0132},
+ {'i', 'j', 0x0133},
+ {'J', '>', 0x0134},
+ {'j', '>', 0x0135},
+ {'K', ',', 0x0136},
+ {'k', ',', 0x0137},
+ {'k', 'k', 0x0138},
+ {'L', '\'', 0x0139},
+ {'l', '\'', 0x013a},
+ {'L', ',', 0x013b},
+ {'l', ',', 0x013c},
+ {'L', '<', 0x013d},
+ {'l', '<', 0x013e},
+ {'L', '.', 0x013f},
+ {'l', '.', 0x0140},
+ {'L', '/', 0x0141},
+ {'l', '/', 0x0142},
+ {'N', '\'', 0x0143},
+ {'n', '\'', 0x0144},
+ {'N', ',', 0x0145},
+ {'n', ',', 0x0146},
+ {'N', '<', 0x0147},
+ {'n', '<', 0x0148},
+ {'\'', 'n', 0x0149},
+ {'N', 'G', 0x014a},
+ {'n', 'g', 0x014b},
+ {'O', '-', 0x014c},
+ {'o', '-', 0x014d},
+ {'O', '(', 0x014e},
+ {'o', '(', 0x014f},
+ {'O', '"', 0x0150},
+ {'o', '"', 0x0151},
+ {'O', 'E', 0x0152},
+ {'o', 'e', 0x0153},
+ {'R', '\'', 0x0154},
+ {'r', '\'', 0x0155},
+ {'R', ',', 0x0156},
+ {'r', ',', 0x0157},
+ {'R', '<', 0x0158},
+ {'r', '<', 0x0159},
+ {'S', '\'', 0x015a},
+ {'s', '\'', 0x015b},
+ {'S', '>', 0x015c},
+ {'s', '>', 0x015d},
+ {'S', ',', 0x015e},
+ {'s', ',', 0x015f},
+ {'S', '<', 0x0160},
+ {'s', '<', 0x0161},
+ {'T', ',', 0x0162},
+ {'t', ',', 0x0163},
+ {'T', '<', 0x0164},
+ {'t', '<', 0x0165},
+ {'T', '/', 0x0166},
+ {'t', '/', 0x0167},
+ {'U', '?', 0x0168},
+ {'u', '?', 0x0169},
+ {'U', '-', 0x016a},
+ {'u', '-', 0x016b},
+ {'U', '(', 0x016c},
+ {'u', '(', 0x016d},
+ {'U', '0', 0x016e},
+ {'u', '0', 0x016f},
+ {'U', '"', 0x0170},
+ {'u', '"', 0x0171},
+ {'U', ';', 0x0172},
+ {'u', ';', 0x0173},
+ {'W', '>', 0x0174},
+ {'w', '>', 0x0175},
+ {'Y', '>', 0x0176},
+ {'y', '>', 0x0177},
+ {'Y', ':', 0x0178},
+ {'Z', '\'', 0x0179},
+ {'z', '\'', 0x017a},
+ {'Z', '.', 0x017b},
+ {'z', '.', 0x017c},
+ {'Z', '<', 0x017d},
+ {'z', '<', 0x017e},
+ {'O', '9', 0x01a0},
+ {'o', '9', 0x01a1},
+ {'O', 'I', 0x01a2},
+ {'o', 'i', 0x01a3},
+ {'y', 'r', 0x01a6},
+ {'U', '9', 0x01af},
+ {'u', '9', 0x01b0},
+ {'Z', '/', 0x01b5},
+ {'z', '/', 0x01b6},
+ {'E', 'D', 0x01b7},
+ {'A', '<', 0x01cd},
+ {'a', '<', 0x01ce},
+ {'I', '<', 0x01cf},
+ {'i', '<', 0x01d0},
+ {'O', '<', 0x01d1},
+ {'o', '<', 0x01d2},
+ {'U', '<', 0x01d3},
+ {'u', '<', 0x01d4},
+ {'A', '1', 0x01de},
+ {'a', '1', 0x01df},
+ {'A', '7', 0x01e0},
+ {'a', '7', 0x01e1},
+ {'A', '3', 0x01e2},
+ {'a', '3', 0x01e3},
+ {'G', '/', 0x01e4},
+ {'g', '/', 0x01e5},
+ {'G', '<', 0x01e6},
+ {'g', '<', 0x01e7},
+ {'K', '<', 0x01e8},
+ {'k', '<', 0x01e9},
+ {'O', ';', 0x01ea},
+ {'o', ';', 0x01eb},
+ {'O', '1', 0x01ec},
+ {'o', '1', 0x01ed},
+ {'E', 'Z', 0x01ee},
+ {'e', 'z', 0x01ef},
+ {'j', '<', 0x01f0},
+ {'G', '\'', 0x01f4},
+ {'g', '\'', 0x01f5},
+ {';', 'S', 0x02bf},
+ {'\'', '<', 0x02c7},
+ {'\'', '(', 0x02d8},
+ {'\'', '.', 0x02d9},
+ {'\'', '0', 0x02da},
+ {'\'', ';', 0x02db},
+ {'\'', '"', 0x02dd},
+ {'A', '%', 0x0386},
+ {'E', '%', 0x0388},
+ {'Y', '%', 0x0389},
+ {'I', '%', 0x038a},
+ {'O', '%', 0x038c},
+ {'U', '%', 0x038e},
+ {'W', '%', 0x038f},
+ {'i', '3', 0x0390},
+ {'A', '*', 0x0391},
+ {'B', '*', 0x0392},
+ {'G', '*', 0x0393},
+ {'D', '*', 0x0394},
+ {'E', '*', 0x0395},
+ {'Z', '*', 0x0396},
+ {'Y', '*', 0x0397},
+ {'H', '*', 0x0398},
+ {'I', '*', 0x0399},
+ {'K', '*', 0x039a},
+ {'L', '*', 0x039b},
+ {'M', '*', 0x039c},
+ {'N', '*', 0x039d},
+ {'C', '*', 0x039e},
+ {'O', '*', 0x039f},
+ {'P', '*', 0x03a0},
+ {'R', '*', 0x03a1},
+ {'S', '*', 0x03a3},
+ {'T', '*', 0x03a4},
+ {'U', '*', 0x03a5},
+ {'F', '*', 0x03a6},
+ {'X', '*', 0x03a7},
+ {'Q', '*', 0x03a8},
+ {'W', '*', 0x03a9},
+ {'J', '*', 0x03aa},
+ {'V', '*', 0x03ab},
+ {'a', '%', 0x03ac},
+ {'e', '%', 0x03ad},
+ {'y', '%', 0x03ae},
+ {'i', '%', 0x03af},
+ {'u', '3', 0x03b0},
+ {'a', '*', 0x03b1},
+ {'b', '*', 0x03b2},
+ {'g', '*', 0x03b3},
+ {'d', '*', 0x03b4},
+ {'e', '*', 0x03b5},
+ {'z', '*', 0x03b6},
+ {'y', '*', 0x03b7},
+ {'h', '*', 0x03b8},
+ {'i', '*', 0x03b9},
+ {'k', '*', 0x03ba},
+ {'l', '*', 0x03bb},
+ {'m', '*', 0x03bc},
+ {'n', '*', 0x03bd},
+ {'c', '*', 0x03be},
+ {'o', '*', 0x03bf},
+ {'p', '*', 0x03c0},
+ {'r', '*', 0x03c1},
+ {'*', 's', 0x03c2},
+ {'s', '*', 0x03c3},
+ {'t', '*', 0x03c4},
+ {'u', '*', 0x03c5},
+ {'f', '*', 0x03c6},
+ {'x', '*', 0x03c7},
+ {'q', '*', 0x03c8},
+ {'w', '*', 0x03c9},
+ {'j', '*', 0x03ca},
+ {'v', '*', 0x03cb},
+ {'o', '%', 0x03cc},
+ {'u', '%', 0x03cd},
+ {'w', '%', 0x03ce},
+ {'\'', 'G', 0x03d8},
+ {',', 'G', 0x03d9},
+ {'T', '3', 0x03da},
+ {'t', '3', 0x03db},
+ {'M', '3', 0x03dc},
+ {'m', '3', 0x03dd},
+ {'K', '3', 0x03de},
+ {'k', '3', 0x03df},
+ {'P', '3', 0x03e0},
+ {'p', '3', 0x03e1},
+ {'\'', '%', 0x03f4},
+ {'j', '3', 0x03f5},
+ {'I', 'O', 0x0401},
+ {'D', '%', 0x0402},
+ {'G', '%', 0x0403},
+ {'I', 'E', 0x0404},
+ {'D', 'S', 0x0405},
+ {'I', 'I', 0x0406},
+ {'Y', 'I', 0x0407},
+ {'J', '%', 0x0408},
+ {'L', 'J', 0x0409},
+ {'N', 'J', 0x040a},
+ {'T', 's', 0x040b},
+ {'K', 'J', 0x040c},
+ {'V', '%', 0x040e},
+ {'D', 'Z', 0x040f},
+ {'A', '=', 0x0410},
+ {'B', '=', 0x0411},
+ {'V', '=', 0x0412},
+ {'G', '=', 0x0413},
+ {'D', '=', 0x0414},
+ {'E', '=', 0x0415},
+ {'Z', '%', 0x0416},
+ {'Z', '=', 0x0417},
+ {'I', '=', 0x0418},
+ {'J', '=', 0x0419},
+ {'K', '=', 0x041a},
+ {'L', '=', 0x041b},
+ {'M', '=', 0x041c},
+ {'N', '=', 0x041d},
+ {'O', '=', 0x041e},
+ {'P', '=', 0x041f},
+ {'R', '=', 0x0420},
+ {'S', '=', 0x0421},
+ {'T', '=', 0x0422},
+ {'U', '=', 0x0423},
+ {'F', '=', 0x0424},
+ {'H', '=', 0x0425},
+ {'C', '=', 0x0426},
+ {'C', '%', 0x0427},
+ {'S', '%', 0x0428},
+ {'S', 'c', 0x0429},
+ {'=', '"', 0x042a},
+ {'Y', '=', 0x042b},
+ {'%', '"', 0x042c},
+ {'J', 'E', 0x042d},
+ {'J', 'U', 0x042e},
+ {'J', 'A', 0x042f},
+ {'a', '=', 0x0430},
+ {'b', '=', 0x0431},
+ {'v', '=', 0x0432},
+ {'g', '=', 0x0433},
+ {'d', '=', 0x0434},
+ {'e', '=', 0x0435},
+ {'z', '%', 0x0436},
+ {'z', '=', 0x0437},
+ {'i', '=', 0x0438},
+ {'j', '=', 0x0439},
+ {'k', '=', 0x043a},
+ {'l', '=', 0x043b},
+ {'m', '=', 0x043c},
+ {'n', '=', 0x043d},
+ {'o', '=', 0x043e},
+ {'p', '=', 0x043f},
+ {'r', '=', 0x0440},
+ {'s', '=', 0x0441},
+ {'t', '=', 0x0442},
+ {'u', '=', 0x0443},
+ {'f', '=', 0x0444},
+ {'h', '=', 0x0445},
+ {'c', '=', 0x0446},
+ {'c', '%', 0x0447},
+ {'s', '%', 0x0448},
+ {'s', 'c', 0x0449},
+ {'=', '\'', 0x044a},
+ {'y', '=', 0x044b},
+ {'%', '\'', 0x044c},
+ {'j', 'e', 0x044d},
+ {'j', 'u', 0x044e},
+ {'j', 'a', 0x044f},
+ {'i', 'o', 0x0451},
+ {'d', '%', 0x0452},
+ {'g', '%', 0x0453},
+ {'i', 'e', 0x0454},
+ {'d', 's', 0x0455},
+ {'i', 'i', 0x0456},
+ {'y', 'i', 0x0457},
+ {'j', '%', 0x0458},
+ {'l', 'j', 0x0459},
+ {'n', 'j', 0x045a},
+ {'t', 's', 0x045b},
+ {'k', 'j', 0x045c},
+ {'v', '%', 0x045e},
+ {'d', 'z', 0x045f},
+ {'Y', '3', 0x0462},
+ {'y', '3', 0x0463},
+ {'O', '3', 0x046a},
+ {'o', '3', 0x046b},
+ {'F', '3', 0x0472},
+ {'f', '3', 0x0473},
+ {'V', '3', 0x0474},
+ {'v', '3', 0x0475},
+ {'C', '3', 0x0480},
+ {'c', '3', 0x0481},
+ {'G', '3', 0x0490},
+ {'g', '3', 0x0491},
+ {'A', '+', 0x05d0},
+ {'B', '+', 0x05d1},
+ {'G', '+', 0x05d2},
+ {'D', '+', 0x05d3},
+ {'H', '+', 0x05d4},
+ {'W', '+', 0x05d5},
+ {'Z', '+', 0x05d6},
+ {'X', '+', 0x05d7},
+ {'T', 'j', 0x05d8},
+ {'J', '+', 0x05d9},
+ {'K', '%', 0x05da},
+ {'K', '+', 0x05db},
+ {'L', '+', 0x05dc},
+ {'M', '%', 0x05dd},
+ {'M', '+', 0x05de},
+ {'N', '%', 0x05df},
+ {'N', '+', 0x05e0},
+ {'S', '+', 0x05e1},
+ {'E', '+', 0x05e2},
+ {'P', '%', 0x05e3},
+ {'P', '+', 0x05e4},
+ {'Z', 'j', 0x05e5},
+ {'Z', 'J', 0x05e6},
+ {'Q', '+', 0x05e7},
+ {'R', '+', 0x05e8},
+ {'S', 'h', 0x05e9},
+ {'T', '+', 0x05ea},
+ {',', '+', 0x060c},
+ {';', '+', 0x061b},
+ {'?', '+', 0x061f},
+ {'H', '\'', 0x0621},
+ {'a', 'M', 0x0622},
+ {'a', 'H', 0x0623},
+ {'w', 'H', 0x0624},
+ {'a', 'h', 0x0625},
+ {'y', 'H', 0x0626},
+ {'a', '+', 0x0627},
+ {'b', '+', 0x0628},
+ {'t', 'm', 0x0629},
+ {'t', '+', 0x062a},
+ {'t', 'k', 0x062b},
+ {'g', '+', 0x062c},
+ {'h', 'k', 0x062d},
+ {'x', '+', 0x062e},
+ {'d', '+', 0x062f},
+ {'d', 'k', 0x0630},
+ {'r', '+', 0x0631},
+ {'z', '+', 0x0632},
+ {'s', '+', 0x0633},
+ {'s', 'n', 0x0634},
+ {'c', '+', 0x0635},
+ {'d', 'd', 0x0636},
+ {'t', 'j', 0x0637},
+ {'z', 'H', 0x0638},
+ {'e', '+', 0x0639},
+ {'i', '+', 0x063a},
+ {'+', '+', 0x0640},
+ {'f', '+', 0x0641},
+ {'q', '+', 0x0642},
+ {'k', '+', 0x0643},
+ {'l', '+', 0x0644},
+ {'m', '+', 0x0645},
+ {'n', '+', 0x0646},
+ {'h', '+', 0x0647},
+ {'w', '+', 0x0648},
+ {'j', '+', 0x0649},
+ {'y', '+', 0x064a},
+ {':', '+', 0x064b},
+ {'"', '+', 0x064c},
+ {'=', '+', 0x064d},
+ {'/', '+', 0x064e},
+ {'\'', '+', 0x064f},
+ {'1', '+', 0x0650},
+ {'3', '+', 0x0651},
+ {'0', '+', 0x0652},
+ {'a', 'S', 0x0670},
+ {'p', '+', 0x067e},
+ {'v', '+', 0x06a4},
+ {'g', 'f', 0x06af},
+ {'0', 'a', 0x06f0},
+ {'1', 'a', 0x06f1},
+ {'2', 'a', 0x06f2},
+ {'3', 'a', 0x06f3},
+ {'4', 'a', 0x06f4},
+ {'5', 'a', 0x06f5},
+ {'6', 'a', 0x06f6},
+ {'7', 'a', 0x06f7},
+ {'8', 'a', 0x06f8},
+ {'9', 'a', 0x06f9},
+ {'B', '.', 0x1e02},
+ {'b', '.', 0x1e03},
+ {'B', '_', 0x1e06},
+ {'b', '_', 0x1e07},
+ {'D', '.', 0x1e0a},
+ {'d', '.', 0x1e0b},
+ {'D', '_', 0x1e0e},
+ {'d', '_', 0x1e0f},
+ {'D', ',', 0x1e10},
+ {'d', ',', 0x1e11},
+ {'F', '.', 0x1e1e},
+ {'f', '.', 0x1e1f},
+ {'G', '-', 0x1e20},
+ {'g', '-', 0x1e21},
+ {'H', '.', 0x1e22},
+ {'h', '.', 0x1e23},
+ {'H', ':', 0x1e26},
+ {'h', ':', 0x1e27},
+ {'H', ',', 0x1e28},
+ {'h', ',', 0x1e29},
+ {'K', '\'', 0x1e30},
+ {'k', '\'', 0x1e31},
+ {'K', '_', 0x1e34},
+ {'k', '_', 0x1e35},
+ {'L', '_', 0x1e3a},
+ {'l', '_', 0x1e3b},
+ {'M', '\'', 0x1e3e},
+ {'m', '\'', 0x1e3f},
+ {'M', '.', 0x1e40},
+ {'m', '.', 0x1e41},
+ {'N', '.', 0x1e44},
+ {'n', '.', 0x1e45},
+ {'N', '_', 0x1e48},
+ {'n', '_', 0x1e49},
+ {'P', '\'', 0x1e54},
+ {'p', '\'', 0x1e55},
+ {'P', '.', 0x1e56},
+ {'p', '.', 0x1e57},
+ {'R', '.', 0x1e58},
+ {'r', '.', 0x1e59},
+ {'R', '_', 0x1e5e},
+ {'r', '_', 0x1e5f},
+ {'S', '.', 0x1e60},
+ {'s', '.', 0x1e61},
+ {'T', '.', 0x1e6a},
+ {'t', '.', 0x1e6b},
+ {'T', '_', 0x1e6e},
+ {'t', '_', 0x1e6f},
+ {'V', '?', 0x1e7c},
+ {'v', '?', 0x1e7d},
+ {'W', '!', 0x1e80},
+ {'w', '!', 0x1e81},
+ {'W', '\'', 0x1e82},
+ {'w', '\'', 0x1e83},
+ {'W', ':', 0x1e84},
+ {'w', ':', 0x1e85},
+ {'W', '.', 0x1e86},
+ {'w', '.', 0x1e87},
+ {'X', '.', 0x1e8a},
+ {'x', '.', 0x1e8b},
+ {'X', ':', 0x1e8c},
+ {'x', ':', 0x1e8d},
+ {'Y', '.', 0x1e8e},
+ {'y', '.', 0x1e8f},
+ {'Z', '>', 0x1e90},
+ {'z', '>', 0x1e91},
+ {'Z', '_', 0x1e94},
+ {'z', '_', 0x1e95},
+ {'h', '_', 0x1e96},
+ {'t', ':', 0x1e97},
+ {'w', '0', 0x1e98},
+ {'y', '0', 0x1e99},
+ {'A', '2', 0x1ea2},
+ {'a', '2', 0x1ea3},
+ {'E', '2', 0x1eba},
+ {'e', '2', 0x1ebb},
+ {'E', '?', 0x1ebc},
+ {'e', '?', 0x1ebd},
+ {'I', '2', 0x1ec8},
+ {'i', '2', 0x1ec9},
+ {'O', '2', 0x1ece},
+ {'o', '2', 0x1ecf},
+ {'U', '2', 0x1ee6},
+ {'u', '2', 0x1ee7},
+ {'Y', '!', 0x1ef2},
+ {'y', '!', 0x1ef3},
+ {'Y', '2', 0x1ef6},
+ {'y', '2', 0x1ef7},
+ {'Y', '?', 0x1ef8},
+ {'y', '?', 0x1ef9},
+ {';', '\'', 0x1f00},
+ {',', '\'', 0x1f01},
+ {';', '!', 0x1f02},
+ {',', '!', 0x1f03},
+ {'?', ';', 0x1f04},
+ {'?', ',', 0x1f05},
+ {'!', ':', 0x1f06},
+ {'?', ':', 0x1f07},
+ {'1', 'N', 0x2002},
+ {'1', 'M', 0x2003},
+ {'3', 'M', 0x2004},
+ {'4', 'M', 0x2005},
+ {'6', 'M', 0x2006},
+ {'1', 'T', 0x2009},
+ {'1', 'H', 0x200a},
+ {'-', '1', 0x2010},
+ {'-', 'N', 0x2013},
+ {'-', 'M', 0x2014},
+ {'-', '3', 0x2015},
+ {'!', '2', 0x2016},
+ {'=', '2', 0x2017},
+ {'\'', '6', 0x2018},
+ {'\'', '9', 0x2019},
+ {'.', '9', 0x201a},
+ {'9', '\'', 0x201b},
+ {'"', '6', 0x201c},
+ {'"', '9', 0x201d},
+ {':', '9', 0x201e},
+ {'9', '"', 0x201f},
+ {'/', '-', 0x2020},
+ {'/', '=', 0x2021},
+ {'.', '.', 0x2025},
+ {'%', '0', 0x2030},
+ {'1', '\'', 0x2032},
+ {'2', '\'', 0x2033},
+ {'3', '\'', 0x2034},
+ {'1', '"', 0x2035},
+ {'2', '"', 0x2036},
+ {'3', '"', 0x2037},
+ {'C', 'a', 0x2038},
+ {'<', '1', 0x2039},
+ {'>', '1', 0x203a},
+ {':', 'X', 0x203b},
+ {'\'', '-', 0x203e},
+ {'/', 'f', 0x2044},
+ {'0', 'S', 0x2070},
+ {'4', 'S', 0x2074},
+ {'5', 'S', 0x2075},
+ {'6', 'S', 0x2076},
+ {'7', 'S', 0x2077},
+ {'8', 'S', 0x2078},
+ {'9', 'S', 0x2079},
+ {'+', 'S', 0x207a},
+ {'-', 'S', 0x207b},
+ {'=', 'S', 0x207c},
+ {'(', 'S', 0x207d},
+ {')', 'S', 0x207e},
+ {'n', 'S', 0x207f},
+ {'0', 's', 0x2080},
+ {'1', 's', 0x2081},
+ {'2', 's', 0x2082},
+ {'3', 's', 0x2083},
+ {'4', 's', 0x2084},
+ {'5', 's', 0x2085},
+ {'6', 's', 0x2086},
+ {'7', 's', 0x2087},
+ {'8', 's', 0x2088},
+ {'9', 's', 0x2089},
+ {'+', 's', 0x208a},
+ {'-', 's', 0x208b},
+ {'=', 's', 0x208c},
+ {'(', 's', 0x208d},
+ {')', 's', 0x208e},
+ {'L', 'i', 0x20a4},
+ {'P', 't', 0x20a7},
+ {'W', '=', 0x20a9},
+ {'o', 'C', 0x2103},
+ {'c', 'o', 0x2105},
+ {'o', 'F', 0x2109},
+ {'N', '0', 0x2116},
+ {'P', 'O', 0x2117},
+ {'R', 'x', 0x211e},
+ {'S', 'M', 0x2120},
+ {'T', 'M', 0x2122},
+ {'O', 'm', 0x2126},
+ {'A', 'O', 0x212b},
+ {'1', '3', 0x2153},
+ {'2', '3', 0x2154},
+ {'1', '5', 0x2155},
+ {'2', '5', 0x2156},
+ {'3', '5', 0x2157},
+ {'4', '5', 0x2158},
+ {'1', '6', 0x2159},
+ {'5', '6', 0x215a},
+ {'1', '8', 0x215b},
+ {'3', '8', 0x215c},
+ {'5', '8', 0x215d},
+ {'7', '8', 0x215e},
+ {'1', 'R', 0x2160},
+ {'2', 'R', 0x2161},
+ {'3', 'R', 0x2162},
+ {'4', 'R', 0x2163},
+ {'5', 'R', 0x2164},
+ {'6', 'R', 0x2165},
+ {'7', 'R', 0x2166},
+ {'8', 'R', 0x2167},
+ {'9', 'R', 0x2168},
+ {'a', 'R', 0x2169},
+ {'b', 'R', 0x216a},
+ {'c', 'R', 0x216b},
+ {'1', 'r', 0x2170},
+ {'2', 'r', 0x2171},
+ {'3', 'r', 0x2172},
+ {'4', 'r', 0x2173},
+ {'5', 'r', 0x2174},
+ {'6', 'r', 0x2175},
+ {'7', 'r', 0x2176},
+ {'8', 'r', 0x2177},
+ {'9', 'r', 0x2178},
+ {'a', 'r', 0x2179},
+ {'b', 'r', 0x217a},
+ {'c', 'r', 0x217b},
+ {'<', '-', 0x2190},
+ {'-', '!', 0x2191},
+ {'-', '>', 0x2192},
+ {'-', 'v', 0x2193},
+ {'<', '>', 0x2194},
+ {'U', 'D', 0x2195},
+ {'<', '=', 0x21d0},
+ {'=', '>', 0x21d2},
+ {'=', '=', 0x21d4},
+ {'F', 'A', 0x2200},
+ {'d', 'P', 0x2202},
+ {'T', 'E', 0x2203},
+ {'/', '0', 0x2205},
+ {'D', 'E', 0x2206},
+ {'N', 'B', 0x2207},
+ {'(', '-', 0x2208},
+ {'-', ')', 0x220b},
+ {'*', 'P', 0x220f},
+ {'+', 'Z', 0x2211},
+ {'-', '2', 0x2212},
+ {'-', '+', 0x2213},
+ {'*', '-', 0x2217},
+ {'O', 'b', 0x2218},
+ {'S', 'b', 0x2219},
+ {'R', 'T', 0x221a},
+ {'0', '(', 0x221d},
+ {'0', '0', 0x221e},
+ {'-', 'L', 0x221f},
+ {'-', 'V', 0x2220},
+ {'P', 'P', 0x2225},
+ {'A', 'N', 0x2227},
+ {'O', 'R', 0x2228},
+ {'(', 'U', 0x2229},
+ {')', 'U', 0x222a},
+ {'I', 'n', 0x222b},
+ {'D', 'I', 0x222c},
+ {'I', 'o', 0x222e},
+ {'.', ':', 0x2234},
+ {':', '.', 0x2235},
+ {':', 'R', 0x2236},
+ {':', ':', 0x2237},
+ {'?', '1', 0x223c},
+ {'C', 'G', 0x223e},
+ {'?', '-', 0x2243},
+ {'?', '=', 0x2245},
+ {'?', '2', 0x2248},
+ {'=', '?', 0x224c},
+ {'H', 'I', 0x2253},
+ {'!', '=', 0x2260},
+ {'=', '3', 0x2261},
+ {'=', '<', 0x2264},
+ {'>', '=', 0x2265},
+ {'<', '*', 0x226a},
+ {'*', '>', 0x226b},
+ {'!', '<', 0x226e},
+ {'!', '>', 0x226f},
+ {'(', 'C', 0x2282},
+ {')', 'C', 0x2283},
+ {'(', '_', 0x2286},
+ {')', '_', 0x2287},
+ {'0', '.', 0x2299},
+ {'0', '2', 0x229a},
+ {'-', 'T', 0x22a5},
+ {'.', 'P', 0x22c5},
+ {':', '3', 0x22ee},
+ {'.', '3', 0x22ef},
+ {'E', 'h', 0x2302},
+ {'<', '7', 0x2308},
+ {'>', '7', 0x2309},
+ {'7', '<', 0x230a},
+ {'7', '>', 0x230b},
+ {'N', 'I', 0x2310},
+ {'(', 'A', 0x2312},
+ {'T', 'R', 0x2315},
+ {'I', 'u', 0x2320},
+ {'I', 'l', 0x2321},
+ {'<', '/', 0x2329},
+ {'/', '>', 0x232a},
+ {'V', 's', 0x2423},
+ {'1', 'h', 0x2440},
+ {'3', 'h', 0x2441},
+ {'2', 'h', 0x2442},
+ {'4', 'h', 0x2443},
+ {'1', 'j', 0x2446},
+ {'2', 'j', 0x2447},
+ {'3', 'j', 0x2448},
+ {'4', 'j', 0x2449},
+ {'1', '.', 0x2488},
+ {'2', '.', 0x2489},
+ {'3', '.', 0x248a},
+ {'4', '.', 0x248b},
+ {'5', '.', 0x248c},
+ {'6', '.', 0x248d},
+ {'7', '.', 0x248e},
+ {'8', '.', 0x248f},
+ {'9', '.', 0x2490},
+ {'h', 'h', 0x2500},
+ {'H', 'H', 0x2501},
+ {'v', 'v', 0x2502},
+ {'V', 'V', 0x2503},
+ {'3', '-', 0x2504},
+ {'3', '_', 0x2505},
+ {'3', '!', 0x2506},
+ {'3', '/', 0x2507},
+ {'4', '-', 0x2508},
+ {'4', '_', 0x2509},
+ {'4', '!', 0x250a},
+ {'4', '/', 0x250b},
+ {'d', 'r', 0x250c},
+ {'d', 'R', 0x250d},
+ {'D', 'r', 0x250e},
+ {'D', 'R', 0x250f},
+ {'d', 'l', 0x2510},
+ {'d', 'L', 0x2511},
+ {'D', 'l', 0x2512},
+ {'L', 'D', 0x2513},
+ {'u', 'r', 0x2514},
+ {'u', 'R', 0x2515},
+ {'U', 'r', 0x2516},
+ {'U', 'R', 0x2517},
+ {'u', 'l', 0x2518},
+ {'u', 'L', 0x2519},
+ {'U', 'l', 0x251a},
+ {'U', 'L', 0x251b},
+ {'v', 'r', 0x251c},
+ {'v', 'R', 0x251d},
+ {'V', 'r', 0x2520},
+ {'V', 'R', 0x2523},
+ {'v', 'l', 0x2524},
+ {'v', 'L', 0x2525},
+ {'V', 'l', 0x2528},
+ {'V', 'L', 0x252b},
+ {'d', 'h', 0x252c},
+ {'d', 'H', 0x252f},
+ {'D', 'h', 0x2530},
+ {'D', 'H', 0x2533},
+ {'u', 'h', 0x2534},
+ {'u', 'H', 0x2537},
+ {'U', 'h', 0x2538},
+ {'U', 'H', 0x253b},
+ {'v', 'h', 0x253c},
+ {'v', 'H', 0x253f},
+ {'V', 'h', 0x2542},
+ {'V', 'H', 0x254b},
+ {'F', 'D', 0x2571},
+ {'B', 'D', 0x2572},
+ {'T', 'B', 0x2580},
+ {'L', 'B', 0x2584},
+ {'F', 'B', 0x2588},
+ {'l', 'B', 0x258c},
+ {'R', 'B', 0x2590},
+ {'.', 'S', 0x2591},
+ {':', 'S', 0x2592},
+ {'?', 'S', 0x2593},
+ {'f', 'S', 0x25a0},
+ {'O', 'S', 0x25a1},
+ {'R', 'O', 0x25a2},
+ {'R', 'r', 0x25a3},
+ {'R', 'F', 0x25a4},
+ {'R', 'Y', 0x25a5},
+ {'R', 'H', 0x25a6},
+ {'R', 'Z', 0x25a7},
+ {'R', 'K', 0x25a8},
+ {'R', 'X', 0x25a9},
+ {'s', 'B', 0x25aa},
+ {'S', 'R', 0x25ac},
+ {'O', 'r', 0x25ad},
+ {'U', 'T', 0x25b2},
+ {'u', 'T', 0x25b3},
+ {'P', 'R', 0x25b6},
+ {'T', 'r', 0x25b7},
+ {'D', 't', 0x25bc},
+ {'d', 'T', 0x25bd},
+ {'P', 'L', 0x25c0},
+ {'T', 'l', 0x25c1},
+ {'D', 'b', 0x25c6},
+ {'D', 'w', 0x25c7},
+ {'L', 'Z', 0x25ca},
+ {'0', 'm', 0x25cb},
+ {'0', 'o', 0x25ce},
+ {'0', 'M', 0x25cf},
+ {'0', 'L', 0x25d0},
+ {'0', 'R', 0x25d1},
+ {'S', 'n', 0x25d8},
+ {'I', 'c', 0x25d9},
+ {'F', 'd', 0x25e2},
+ {'B', 'd', 0x25e3},
+ {'*', '2', 0x2605},
+ {'*', '1', 0x2606},
+ {'<', 'H', 0x261c},
+ {'>', 'H', 0x261e},
+ {'0', 'u', 0x263a},
+ {'0', 'U', 0x263b},
+ {'S', 'U', 0x263c},
+ {'F', 'm', 0x2640},
+ {'M', 'l', 0x2642},
+ {'c', 'S', 0x2660},
+ {'c', 'H', 0x2661},
+ {'c', 'D', 0x2662},
+ {'c', 'C', 0x2663},
+ {'M', 'd', 0x2669},
+ {'M', '8', 0x266a},
+ {'M', '2', 0x266b},
+ {'M', 'b', 0x266d},
+ {'M', 'x', 0x266e},
+ {'M', 'X', 0x266f},
+ {'O', 'K', 0x2713},
+ {'X', 'X', 0x2717},
+ {'-', 'X', 0x2720},
+ {'I', 'S', 0x3000},
+ {',', '_', 0x3001},
+ {'.', '_', 0x3002},
+ {'+', '"', 0x3003},
+ {'+', '_', 0x3004},
+ {'*', '_', 0x3005},
+ {';', '_', 0x3006},
+ {'0', '_', 0x3007},
+ {'<', '+', 0x300a},
+ {'>', '+', 0x300b},
+ {'<', '\'', 0x300c},
+ {'>', '\'', 0x300d},
+ {'<', '"', 0x300e},
+ {'>', '"', 0x300f},
+ {'(', '"', 0x3010},
+ {')', '"', 0x3011},
+ {'=', 'T', 0x3012},
+ {'=', '_', 0x3013},
+ {'(', '\'', 0x3014},
+ {')', '\'', 0x3015},
+ {'(', 'I', 0x3016},
+ {')', 'I', 0x3017},
+ {'-', '?', 0x301c},
+ {'A', '5', 0x3041},
+ {'a', '5', 0x3042},
+ {'I', '5', 0x3043},
+ {'i', '5', 0x3044},
+ {'U', '5', 0x3045},
+ {'u', '5', 0x3046},
+ {'E', '5', 0x3047},
+ {'e', '5', 0x3048},
+ {'O', '5', 0x3049},
+ {'o', '5', 0x304a},
+ {'k', 'a', 0x304b},
+ {'g', 'a', 0x304c},
+ {'k', 'i', 0x304d},
+ {'g', 'i', 0x304e},
+ {'k', 'u', 0x304f},
+ {'g', 'u', 0x3050},
+ {'k', 'e', 0x3051},
+ {'g', 'e', 0x3052},
+ {'k', 'o', 0x3053},
+ {'g', 'o', 0x3054},
+ {'s', 'a', 0x3055},
+ {'z', 'a', 0x3056},
+ {'s', 'i', 0x3057},
+ {'z', 'i', 0x3058},
+ {'s', 'u', 0x3059},
+ {'z', 'u', 0x305a},
+ {'s', 'e', 0x305b},
+ {'z', 'e', 0x305c},
+ {'s', 'o', 0x305d},
+ {'z', 'o', 0x305e},
+ {'t', 'a', 0x305f},
+ {'d', 'a', 0x3060},
+ {'t', 'i', 0x3061},
+ {'d', 'i', 0x3062},
+ {'t', 'U', 0x3063},
+ {'t', 'u', 0x3064},
+ {'d', 'u', 0x3065},
+ {'t', 'e', 0x3066},
+ {'d', 'e', 0x3067},
+ {'t', 'o', 0x3068},
+ {'d', 'o', 0x3069},
+ {'n', 'a', 0x306a},
+ {'n', 'i', 0x306b},
+ {'n', 'u', 0x306c},
+ {'n', 'e', 0x306d},
+ {'n', 'o', 0x306e},
+ {'h', 'a', 0x306f},
+ {'b', 'a', 0x3070},
+ {'p', 'a', 0x3071},
+ {'h', 'i', 0x3072},
+ {'b', 'i', 0x3073},
+ {'p', 'i', 0x3074},
+ {'h', 'u', 0x3075},
+ {'b', 'u', 0x3076},
+ {'p', 'u', 0x3077},
+ {'h', 'e', 0x3078},
+ {'b', 'e', 0x3079},
+ {'p', 'e', 0x307a},
+ {'h', 'o', 0x307b},
+ {'b', 'o', 0x307c},
+ {'p', 'o', 0x307d},
+ {'m', 'a', 0x307e},
+ {'m', 'i', 0x307f},
+ {'m', 'u', 0x3080},
+ {'m', 'e', 0x3081},
+ {'m', 'o', 0x3082},
+ {'y', 'A', 0x3083},
+ {'y', 'a', 0x3084},
+ {'y', 'U', 0x3085},
+ {'y', 'u', 0x3086},
+ {'y', 'O', 0x3087},
+ {'y', 'o', 0x3088},
+ {'r', 'a', 0x3089},
+ {'r', 'i', 0x308a},
+ {'r', 'u', 0x308b},
+ {'r', 'e', 0x308c},
+ {'r', 'o', 0x308d},
+ {'w', 'A', 0x308e},
+ {'w', 'a', 0x308f},
+ {'w', 'i', 0x3090},
+ {'w', 'e', 0x3091},
+ {'w', 'o', 0x3092},
+ {'n', '5', 0x3093},
+ {'v', 'u', 0x3094},
+ {'"', '5', 0x309b},
+ {'0', '5', 0x309c},
+ {'*', '5', 0x309d},
+ {'+', '5', 0x309e},
+ {'a', '6', 0x30a1},
+ {'A', '6', 0x30a2},
+ {'i', '6', 0x30a3},
+ {'I', '6', 0x30a4},
+ {'u', '6', 0x30a5},
+ {'U', '6', 0x30a6},
+ {'e', '6', 0x30a7},
+ {'E', '6', 0x30a8},
+ {'o', '6', 0x30a9},
+ {'O', '6', 0x30aa},
+ {'K', 'a', 0x30ab},
+ {'G', 'a', 0x30ac},
+ {'K', 'i', 0x30ad},
+ {'G', 'i', 0x30ae},
+ {'K', 'u', 0x30af},
+ {'G', 'u', 0x30b0},
+ {'K', 'e', 0x30b1},
+ {'G', 'e', 0x30b2},
+ {'K', 'o', 0x30b3},
+ {'G', 'o', 0x30b4},
+ {'S', 'a', 0x30b5},
+ {'Z', 'a', 0x30b6},
+ {'S', 'i', 0x30b7},
+ {'Z', 'i', 0x30b8},
+ {'S', 'u', 0x30b9},
+ {'Z', 'u', 0x30ba},
+ {'S', 'e', 0x30bb},
+ {'Z', 'e', 0x30bc},
+ {'S', 'o', 0x30bd},
+ {'Z', 'o', 0x30be},
+ {'T', 'a', 0x30bf},
+ {'D', 'a', 0x30c0},
+ {'T', 'i', 0x30c1},
+ {'D', 'i', 0x30c2},
+ {'T', 'U', 0x30c3},
+ {'T', 'u', 0x30c4},
+ {'D', 'u', 0x30c5},
+ {'T', 'e', 0x30c6},
+ {'D', 'e', 0x30c7},
+ {'T', 'o', 0x30c8},
+ {'D', 'o', 0x30c9},
+ {'N', 'a', 0x30ca},
+ {'N', 'i', 0x30cb},
+ {'N', 'u', 0x30cc},
+ {'N', 'e', 0x30cd},
+ {'N', 'o', 0x30ce},
+ {'H', 'a', 0x30cf},
+ {'B', 'a', 0x30d0},
+ {'P', 'a', 0x30d1},
+ {'H', 'i', 0x30d2},
+ {'B', 'i', 0x30d3},
+ {'P', 'i', 0x30d4},
+ {'H', 'u', 0x30d5},
+ {'B', 'u', 0x30d6},
+ {'P', 'u', 0x30d7},
+ {'H', 'e', 0x30d8},
+ {'B', 'e', 0x30d9},
+ {'P', 'e', 0x30da},
+ {'H', 'o', 0x30db},
+ {'B', 'o', 0x30dc},
+ {'P', 'o', 0x30dd},
+ {'M', 'a', 0x30de},
+ {'M', 'i', 0x30df},
+ {'M', 'u', 0x30e0},
+ {'M', 'e', 0x30e1},
+ {'M', 'o', 0x30e2},
+ {'Y', 'A', 0x30e3},
+ {'Y', 'a', 0x30e4},
+ {'Y', 'U', 0x30e5},
+ {'Y', 'u', 0x30e6},
+ {'Y', 'O', 0x30e7},
+ {'Y', 'o', 0x30e8},
+ {'R', 'a', 0x30e9},
+ {'R', 'i', 0x30ea},
+ {'R', 'u', 0x30eb},
+ {'R', 'e', 0x30ec},
+ {'R', 'o', 0x30ed},
+ {'W', 'A', 0x30ee},
+ {'W', 'a', 0x30ef},
+ {'W', 'i', 0x30f0},
+ {'W', 'e', 0x30f1},
+ {'W', 'o', 0x30f2},
+ {'N', '6', 0x30f3},
+ {'V', 'u', 0x30f4},
+ {'K', 'A', 0x30f5},
+ {'K', 'E', 0x30f6},
+ {'V', 'a', 0x30f7},
+ {'V', 'i', 0x30f8},
+ {'V', 'e', 0x30f9},
+ {'V', 'o', 0x30fa},
+ {'.', '6', 0x30fb},
+ {'-', '6', 0x30fc},
+ {'*', '6', 0x30fd},
+ {'+', '6', 0x30fe},
+ {'b', '4', 0x3105},
+ {'p', '4', 0x3106},
+ {'m', '4', 0x3107},
+ {'f', '4', 0x3108},
+ {'d', '4', 0x3109},
+ {'t', '4', 0x310a},
+ {'n', '4', 0x310b},
+ {'l', '4', 0x310c},
+ {'g', '4', 0x310d},
+ {'k', '4', 0x310e},
+ {'h', '4', 0x310f},
+ {'j', '4', 0x3110},
+ {'q', '4', 0x3111},
+ {'x', '4', 0x3112},
+ {'z', 'h', 0x3113},
+ {'c', 'h', 0x3114},
+ {'s', 'h', 0x3115},
+ {'r', '4', 0x3116},
+ {'z', '4', 0x3117},
+ {'c', '4', 0x3118},
+ {'s', '4', 0x3119},
+ {'a', '4', 0x311a},
+ {'o', '4', 0x311b},
+ {'e', '4', 0x311c},
+ {'a', 'i', 0x311e},
+ {'e', 'i', 0x311f},
+ {'a', 'u', 0x3120},
+ {'o', 'u', 0x3121},
+ {'a', 'n', 0x3122},
+ {'e', 'n', 0x3123},
+ {'a', 'N', 0x3124},
+ {'e', 'N', 0x3125},
+ {'e', 'r', 0x3126},
+ {'i', '4', 0x3127},
+ {'u', '4', 0x3128},
+ {'i', 'u', 0x3129},
+ {'v', '4', 0x312a},
+ {'n', 'G', 0x312b},
+ {'g', 'n', 0x312c},
+ {'1', 'c', 0x3220},
+ {'2', 'c', 0x3221},
+ {'3', 'c', 0x3222},
+ {'4', 'c', 0x3223},
+ {'5', 'c', 0x3224},
+ {'6', 'c', 0x3225},
+ {'7', 'c', 0x3226},
+ {'8', 'c', 0x3227},
+ {'9', 'c', 0x3228},
+ {' ', ' ', 0xe000},
+ {'/', 'c', 0xe001},
+ {'U', 'A', 0xe002},
+ {'U', 'B', 0xe003},
+ {'"', '3', 0xe004},
+ {'"', '1', 0xe005},
+ {'"', '!', 0xe006},
+ {'"', '\'', 0xe007},
+ {'"', '>', 0xe008},
+ {'"', '?', 0xe009},
+ {'"', '-', 0xe00a},
+ {'"', '(', 0xe00b},
+ {'"', '.', 0xe00c},
+ {'"', ':', 0xe00d},
+ {'"', '0', 0xe00e},
+ {'"', '"', 0xe00f},
+ {'"', '<', 0xe010},
+ {'"', ',', 0xe011},
+ {'"', ';', 0xe012},
+ {'"', '_', 0xe013},
+ {'"', '=', 0xe014},
+ {'"', '/', 0xe015},
+ {'"', 'i', 0xe016},
+ {'"', 'd', 0xe017},
+ {'"', 'p', 0xe018},
+ {';', ';', 0xe019},
+ {',', ',', 0xe01a},
+ {'b', '3', 0xe01b},
+ {'C', 'i', 0xe01c},
+ {'f', '(', 0xe01d},
+ {'e', 'd', 0xe01e},
+ {'a', 'm', 0xe01f},
+ {'p', 'm', 0xe020},
+ {'F', 'l', 0xe023},
+ {'G', 'F', 0xe024},
+ {'>', 'V', 0xe025},
+ {'!', '*', 0xe026},
+ {'?', '*', 0xe027},
+ {'J', '<', 0xe028},
+ {'f', 'f', 0xfb00},
+ {'f', 'i', 0xfb01},
+ {'f', 'l', 0xfb02},
+ {'f', 't', 0xfb05},
+ {'s', 't', 0xfb06},
+# endif /* FEAT_MBYTE */
+ {NUL, NUL, NUL}
+ };
+
+# endif /* OLD_DIGRAPHS */
+
+# endif /* Macintosh */
+# endif /* EBCDIC */
+# endif /* !HPUX_DIGRAPHS */
+# endif /* !__MINT__ */
+#endif /* !MSDOS && !OS2 */
+
+/*
+ * handle digraphs after typing a character
+ */
+ int
+do_digraph(c)
+ int c;
+{
+ static int backspaced; /* character before K_BS */
+ static int lastchar; /* last typed character */
+
+ if (c == -1) /* init values */
+ {
+ backspaced = -1;
+ }
+ else if (p_dg)
+ {
+ if (backspaced >= 0)
+ c = getdigraph(backspaced, c, FALSE);
+ backspaced = -1;
+ if ((c == K_BS || c == Ctrl_H) && lastchar >= 0)
+ backspaced = lastchar;
+ }
+ lastchar = c;
+ return c;
+}
+
+/*
+ * Get a digraph. Used after typing CTRL-K on the command line or in normal
+ * mode.
+ * Returns composed character, or NUL when ESC was used.
+ */
+ int
+get_digraph(cmdline)
+ int cmdline; /* TRUE when called from the cmdline */
+{
+ int c, cc;
+
+ ++no_mapping;
+ ++allow_keys;
+ c = safe_vgetc();
+ --no_mapping;
+ --allow_keys;
+ if (c != ESC) /* ESC cancels CTRL-K */
+ {
+ if (IS_SPECIAL(c)) /* insert special key code */
+ return c;
+ if (cmdline)
+ {
+ if (char2cells(c) == 1
+#if defined(FEAT_CRYPT) || defined(FEAT_EVAL)
+ && cmdline_star == 0
+#endif
+ )
+ putcmdline(c, TRUE);
+ }
+#ifdef FEAT_CMDL_INFO
+ else
+ add_to_showcmd(c);
+#endif
+ ++no_mapping;
+ ++allow_keys;
+ cc = safe_vgetc();
+ --no_mapping;
+ --allow_keys;
+ if (cc != ESC) /* ESC cancels CTRL-K */
+ return getdigraph(c, cc, TRUE);
+ }
+ return NUL;
+}
+
+/*
+ * Lookup the pair "char1", "char2" in the digraph tables.
+ * If no match, return "char2".
+ * If "meta" is TRUE and "char1" is a space, return "char2" | 0x80.
+ */
+ static int
+getexactdigraph(char1, char2, meta)
+ int char1;
+ int char2;
+ int meta;
+{
+ int i;
+ int retval = 0;
+ digr_T *dp;
+
+ if (IS_SPECIAL(char1) || IS_SPECIAL(char2))
+ return char2;
+
+ /*
+ * Search user digraphs first.
+ */
+ dp = (digr_T *)user_digraphs.ga_data;
+ for (i = 0; i < user_digraphs.ga_len; ++i)
+ {
+ if ((int)dp->char1 == char1 && (int)dp->char2 == char2)
+ {
+ retval = dp->result;
+ break;
+ }
+ ++dp;
+ }
+
+ /*
+ * Search default digraphs.
+ */
+ if (retval == 0)
+ {
+ dp = digraphdefault;
+ for (i = 0; dp->char1 != 0; ++i)
+ {
+ if ((int)dp->char1 == char1 && (int)dp->char2 == char2)
+ {
+ retval = dp->result;
+ break;
+ }
+ ++dp;
+ }
+ }
+#ifdef FEAT_MBYTE
+# ifdef USE_UNICODE_DIGRAPHS
+ if (retval != 0 && !enc_utf8)
+ {
+ char_u buf[6], *to;
+ vimconv_T vc;
+
+ /*
+ * Convert the Unicode digraph to 'encoding'.
+ */
+ i = utf_char2bytes(retval, buf);
+ retval = 0;
+ vc.vc_type = CONV_NONE;
+ if (convert_setup(&vc, (char_u *)"utf-8", p_enc) == OK)
+ {
+ vc.vc_fail = TRUE;
+ to = string_convert(&vc, buf, &i);
+ if (to != NULL)
+ {
+ retval = (*mb_ptr2char)(to);
+ vim_free(to);
+ }
+ (void)convert_setup(&vc, NULL, NULL);
+ }
+ }
+# endif
+
+ /* Ignore multi-byte characters when not in multi-byte mode. */
+ if (!has_mbyte && retval > 0xff)
+ retval = 0;
+#endif
+
+ if (retval == 0) /* digraph deleted or not found */
+ {
+ if (char1 == ' ' && meta) /* <space> <char> --> meta-char */
+ return (char2 | 0x80);
+ return char2;
+ }
+ return retval;
+}
+
+/*
+ * Get digraph.
+ * Allow for both char1-char2 and char2-char1
+ */
+ int
+getdigraph(char1, char2, meta)
+ int char1;
+ int char2;
+ int meta;
+{
+ int retval;
+
+ if (((retval = getexactdigraph(char1, char2, meta)) == char2)
+ && (char1 != char2)
+ && ((retval = getexactdigraph(char2, char1, meta)) == char1))
+ return char2;
+ return retval;
+}
+
+/*
+ * Add the digraphs in the argument to the digraph table.
+ * format: {c1}{c2} char {c1}{c2} char ...
+ */
+ void
+putdigraph(str)
+ char_u *str;
+{
+ int char1, char2, n;
+ int i;
+ digr_T *dp;
+
+ while (*str != NUL)
+ {
+ str = skipwhite(str);
+ if (*str == NUL)
+ return;
+ char1 = *str++;
+ char2 = *str++;
+ if (char2 == 0)
+ {
+ EMSG(_(e_invarg));
+ return;
+ }
+ if (char1 == ESC || char2 == ESC)
+ {
+ EMSG(_("E104: Escape not allowed in digraph"));
+ return;
+ }
+ str = skipwhite(str);
+ if (!VIM_ISDIGIT(*str))
+ {
+ EMSG(_(e_number_exp));
+ return;
+ }
+ n = getdigits(&str);
+
+ /* If the digraph already exists, replace the result. */
+ dp = (digr_T *)user_digraphs.ga_data;
+ for (i = 0; i < user_digraphs.ga_len; ++i)
+ {
+ if ((int)dp->char1 == char1 && (int)dp->char2 == char2)
+ {
+ dp->result = n;
+ break;
+ }
+ ++dp;
+ }
+
+ /* Add a new digraph to the table. */
+ if (i == user_digraphs.ga_len)
+ {
+ if (ga_grow(&user_digraphs, 1) == OK)
+ {
+ dp = (digr_T *)user_digraphs.ga_data + user_digraphs.ga_len;
+ dp->char1 = char1;
+ dp->char2 = char2;
+ dp->result = n;
+ ++user_digraphs.ga_len;
+ --user_digraphs.ga_room;
+ }
+ }
+ }
+}
+
+ void
+listdigraphs()
+{
+ int i;
+ digr_T *dp;
+
+ msg_putchar('\n');
+
+ dp = digraphdefault;
+ for (i = 0; dp->char1 != NUL && !got_int; ++i)
+ {
+#if defined(USE_UNICODE_DIGRAPHS) && defined(FEAT_MBYTE)
+ digr_T tmp;
+
+ /* May need to convert the result to 'encoding'. */
+ tmp.char1 = dp->char1;
+ tmp.char2 = dp->char2;
+ tmp.result = getexactdigraph(tmp.char1, tmp.char2, FALSE);
+ if (tmp.result != 0 && tmp.result != tmp.char2
+ && (has_mbyte || tmp.result <= 255))
+ printdigraph(&tmp);
+#else
+
+ if (getexactdigraph(dp->char1, dp->char2, FALSE) == dp->result
+# ifdef FEAT_MBYTE
+ && (has_mbyte || dp->result <= 255)
+# endif
+ )
+ printdigraph(dp);
+#endif
+ ++dp;
+ ui_breakcheck();
+ }
+
+ dp = (digr_T *)user_digraphs.ga_data;
+ for (i = 0; i < user_digraphs.ga_len && !got_int; ++i)
+ {
+ printdigraph(dp);
+ ui_breakcheck();
+ ++dp;
+ }
+ must_redraw = CLEAR; /* clear screen, because some digraphs may be
+ wrong, in which case we messed up ScreenLines */
+}
+
+ static void
+printdigraph(dp)
+ digr_T *dp;
+{
+ char_u buf[30];
+ char_u *p;
+
+ int list_width;
+
+ if ((dy_flags & DY_UHEX)
+#ifdef FEAT_MBYTE
+ || has_mbyte
+#endif
+ )
+ list_width = 13;
+ else
+ list_width = 11;
+
+ if (dp->result != 0)
+ {
+ if (msg_col > Columns - list_width)
+ msg_putchar('\n');
+ if (msg_col)
+ while (msg_col % list_width != 0)
+ msg_putchar(' ');
+
+ p = buf;
+ *p++ = dp->char1;
+ *p++ = dp->char2;
+ *p++ = ' ';
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ /* add a space to draw a composing char on */
+ if (enc_utf8 && utf_iscomposing(dp->result))
+ *p++ = ' ';
+ p += (*mb_char2bytes)(dp->result, p);
+ }
+ else
+#endif
+ *p++ = dp->result;
+ if (char2cells(dp->result) == 1)
+ *p++ = ' ';
+ sprintf((char *)p, " %3d", dp->result);
+ msg_outtrans(buf);
+ }
+}
+
+#endif /* FEAT_DIGRAPHS */
+
+#if defined(FEAT_KEYMAP) || defined(PROTO)
+
+/* structure used for b_kmap_ga.ga_data */
+typedef struct
+{
+ char_u *from;
+ char_u *to;
+} kmap_T;
+
+#define KMAP_MAXLEN 20 /* maximum length of "from" or "to" */
+
+static void keymap_unload __ARGS((void));
+
+/*
+ * Set up key mapping tables for the 'keymap' option
+ */
+ char_u *
+keymap_init()
+{
+ curbuf->b_kmap_state &= ~KEYMAP_INIT;
+
+ if (*curbuf->b_p_keymap == NUL)
+ {
+ /* Stop any active keymap and clear the table. */
+ keymap_unload();
+ }
+ else
+ {
+ char_u *buf;
+
+ /* Source the keymap file. It will contain a ":loadkeymap" command
+ * which will call ex_loadkeymap() below. */
+ buf = alloc((unsigned)(STRLEN(curbuf->b_p_keymap)
+# ifdef FEAT_MBYTE
+ + STRLEN(p_enc)
+# endif
+ + 14));
+ if (buf == NULL)
+ return e_outofmem;
+
+# ifdef FEAT_MBYTE
+ /* try finding "keymap/'keymap'_'encoding'.vim" in 'runtimepath' */
+ sprintf((char *)buf, "keymap/%s_%s.vim", curbuf->b_p_keymap, p_enc);
+ if (cmd_runtime(buf, FALSE) == FAIL)
+# endif
+ {
+ /* try finding "keymap/'keymap'.vim" in 'runtimepath' */
+ sprintf((char *)buf, "keymap/%s.vim", curbuf->b_p_keymap);
+ if (cmd_runtime(buf, FALSE) == FAIL)
+ {
+ vim_free(buf);
+ return (char_u *)N_("E544: Keymap file not found");
+ }
+ }
+ vim_free(buf);
+ }
+
+ return NULL;
+}
+
+/*
+ * ":loadkeymap" command: load the following lines as the keymap.
+ */
+ void
+ex_loadkeymap(eap)
+ exarg_T *eap;
+{
+ char_u *line;
+ char_u *p;
+ char_u *s;
+ kmap_T *kp;
+#define KMAP_LLEN 200 /* max length of "to" and "from" together */
+ char_u buf[KMAP_LLEN + 11];
+ int i;
+ char_u *save_cpo = p_cpo;
+
+ if (!getline_equal(eap->getline, eap->cookie, getsourceline))
+ {
+ EMSG(_("E105: Using :loadkeymap not in a sourced file"));
+ return;
+ }
+
+ /*
+ * Stop any active keymap and clear the table.
+ */
+ keymap_unload();
+
+ curbuf->b_kmap_state = 0;
+ ga_init2(&curbuf->b_kmap_ga, (int)sizeof(kmap_T), 20);
+
+ /* Set 'cpoptions' to "C" to avoid line continuation. */
+ p_cpo = (char_u *)"C";
+
+ /*
+ * Get each line of the sourced file, break at the end.
+ */
+ for (;;)
+ {
+ line = eap->getline(0, eap->cookie, 0);
+ if (line == NULL)
+ break;
+
+ p = skipwhite(line);
+ if (*p != '"' && *p != NUL && ga_grow(&curbuf->b_kmap_ga, 1) == OK)
+ {
+ kp = (kmap_T *)curbuf->b_kmap_ga.ga_data + curbuf->b_kmap_ga.ga_len;
+ s = skiptowhite(p);
+ kp->from = vim_strnsave(p, (int)(s - p));
+ p = skipwhite(s);
+ s = skiptowhite(p);
+ kp->to = vim_strnsave(p, (int)(s - p));
+
+ if (kp->from == NULL || kp->to == NULL
+ || STRLEN(kp->from) + STRLEN(kp->to) >= KMAP_LLEN)
+ {
+ vim_free(kp->from);
+ vim_free(kp->to);
+ }
+ else
+ {
+ ++curbuf->b_kmap_ga.ga_len;
+ --curbuf->b_kmap_ga.ga_room;
+ }
+ }
+ vim_free(line);
+ }
+
+ /*
+ * setup ":lnoremap" to map the keys
+ */
+ for (i = 0; i < curbuf->b_kmap_ga.ga_len; ++i)
+ {
+ sprintf((char *)buf, "<buffer> %s %s",
+ ((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from,
+ ((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].to);
+ (void)do_map(2, buf, LANGMAP, FALSE);
+ }
+
+ p_cpo = save_cpo;
+
+ curbuf->b_kmap_state |= KEYMAP_LOADED;
+#ifdef FEAT_WINDOWS
+ status_redraw_curbuf();
+#endif
+}
+
+/*
+ * Stop using 'keymap'.
+ */
+ static void
+keymap_unload()
+{
+ char_u buf[KMAP_MAXLEN + 10];
+ int i;
+ char_u *save_cpo = p_cpo;
+
+ if (!(curbuf->b_kmap_state & KEYMAP_LOADED))
+ return;
+
+ /* Set 'cpoptions' to "C" to avoid line continuation. */
+ p_cpo = (char_u *)"C";
+
+ /* clear the ":lmap"s */
+ for (i = 0; i < curbuf->b_kmap_ga.ga_len; ++i)
+ {
+ sprintf((char *)buf, "<buffer> %s",
+ ((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from);
+ (void)do_map(1, buf, LANGMAP, FALSE);
+ }
+
+ p_cpo = save_cpo;
+
+ ga_clear(&curbuf->b_kmap_ga);
+ curbuf->b_kmap_state &= ~KEYMAP_LOADED;
+#ifdef FEAT_WINDOWS
+ status_redraw_curbuf();
+#endif
+}
+
+#endif /* FEAT_KEYMAP */
+
diff --git a/src/dimm.idl b/src/dimm.idl
new file mode 100644
index 000000000..ac449650e
--- /dev/null
+++ b/src/dimm.idl
@@ -0,0 +1,544 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992-2000.
+//
+// File: dimm.idl
+//
+// Contents: ActiveIMM interface definitions
+//
+//
+//--------------------------------------------------------------------------
+
+cpp_quote("//=--------------------------------------------------------------------------=")
+cpp_quote("// dimm.h")
+cpp_quote("//=--------------------------------------------------------------------------=")
+cpp_quote("// (C) Copyright 1995-1998 Microsoft Corporation. All Rights Reserved.")
+cpp_quote("//")
+cpp_quote("// THIS CODE AND INFORMATION IS PROVIDED \"AS IS\" WITHOUT WARRANTY OF")
+cpp_quote("// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO")
+cpp_quote("// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A")
+cpp_quote("// PARTICULAR PURPOSE.")
+cpp_quote("//=--------------------------------------------------------------------------=")
+cpp_quote("")
+cpp_quote("#pragma comment(lib,\"uuid.lib\")")
+cpp_quote("")
+cpp_quote("//--------------------------------------------------------------------------")
+cpp_quote("// IActiveIMM Interfaces.")
+cpp_quote("")
+
+/*
+Disable a warning about lack of polymorphic type support for the following reasons
+- the only reason to have library block in the file is to make midl accept coclass
+ statement and generate CLSID for CActiveIMM.
+- the generated dimm_i.c has the clsid and that file is used to have clsid available
+- the dimm.tlb is not used at all
+- on top of it, there is no plans to port the app using dimm.idl to 64b platform.
+*/
+/*
+ * midl_pragma is unsupported in midl version 3.01 shipped with VC5.0.
+ * It is supported in midl version 5.01 shipped with VC6.0
+ * I could not produce message 2395. Is this needed? W.Briscoe 2001-08-14
+ */
+#if (__midl >= 501)
+midl_pragma warning( disable: 2395) // polymorphic types not supported in the TLB
+#endif
+
+#ifndef DO_NO_IMPORTS
+import "unknwn.idl";
+#endif
+
+[
+ uuid(4955DD30-B159-11d0-8FCF-00AA006BCC59),
+ helpstring("ActiveIMM"),
+ lcid(0x0000),
+ version(0.1)
+]
+library ActiveIMM
+{
+ importlib("stdole2.tlb");
+
+ cpp_quote("#include <imm.h>")
+
+ cpp_quote("#if 0")
+
+ typedef WORD LANGID;
+
+ typedef struct
+ {
+ LPSTR lpReading;
+ LPSTR lpWord;
+ } REGISTERWORDA;
+
+ typedef struct
+ {
+ LPWSTR lpReading;
+ LPWSTR lpWord;
+ } REGISTERWORDW;
+
+ #define LF_FACESIZE 32
+
+ typedef struct
+ {
+ LONG lfHeight;
+ LONG lfWidth;
+ LONG lfEscapement;
+ LONG lfOrientation;
+ LONG lfWeight;
+ BYTE lfItalic;
+ BYTE lfUnderline;
+ BYTE lfStrikeOut;
+ BYTE lfCharSet;
+ BYTE lfOutPrecision;
+ BYTE lfClipPrecision;
+ BYTE lfQuality;
+ BYTE lfPitchAndFamily;
+ CHAR lfFaceName[LF_FACESIZE];
+ } LOGFONTA;
+
+ typedef struct
+ {
+ LONG lfHeight;
+ LONG lfWidth;
+ LONG lfEscapement;
+ LONG lfOrientation;
+ LONG lfWeight;
+ BYTE lfItalic;
+ BYTE lfUnderline;
+ BYTE lfStrikeOut;
+ BYTE lfCharSet;
+ BYTE lfOutPrecision;
+ BYTE lfClipPrecision;
+ BYTE lfQuality;
+ BYTE lfPitchAndFamily;
+ WCHAR lfFaceName[LF_FACESIZE];
+ } LOGFONTW;
+
+ typedef DWORD HIMC;
+ typedef DWORD HIMCC;
+
+ typedef struct
+ {
+ DWORD dwIndex;
+ DWORD dwStyle;
+ POINT ptCurrentPos;
+ RECT rcArea;
+ } CANDIDATEFORM;
+
+ typedef struct
+ {
+ DWORD dwStyle;
+ POINT ptCurrentPos;
+ RECT rcArea;
+ } COMPOSITIONFORM;
+
+ typedef struct
+ {
+ DWORD dwSize;
+ DWORD dwStyle;
+ DWORD dwCount;
+ DWORD dwSelection;
+ DWORD dwPageStart;
+ DWORD dwPageSize;
+ DWORD dwOffset[1];
+ } CANDIDATELIST;
+
+ #define STYLE_DESCRIPTION_SIZE 32
+
+ typedef struct
+ {
+ DWORD dwStyle;
+ CHAR szDescription[STYLE_DESCRIPTION_SIZE];
+ } STYLEBUFA;
+
+ typedef struct
+ {
+ DWORD dwStyle;
+ WCHAR szDescription[STYLE_DESCRIPTION_SIZE];
+ } STYLEBUFW;
+
+ typedef WORD ATOM;
+
+ cpp_quote("#endif")
+
+ cpp_quote("#if (WINVER < 0x040A)")
+
+ #define IMEMENUITEM_STRING_SIZE 80
+
+ typedef struct
+ {
+ UINT cbSize;
+ UINT fType;
+ UINT fState;
+ UINT wID;
+ HBITMAP hbmpChecked;
+ HBITMAP hbmpUnchecked;
+ DWORD dwItemData;
+ CHAR szString[IMEMENUITEM_STRING_SIZE];
+ HBITMAP hbmpItem;
+ } IMEMENUITEMINFOA;
+
+ typedef struct
+ {
+ UINT cbSize;
+ UINT fType;
+ UINT fState;
+ UINT wID;
+ HBITMAP hbmpChecked;
+ HBITMAP hbmpUnchecked;
+ DWORD dwItemData;
+ WCHAR szString[IMEMENUITEM_STRING_SIZE];
+ HBITMAP hbmpItem;
+ } IMEMENUITEMINFOW;
+
+ cpp_quote("#endif")
+
+ cpp_quote("#ifndef _DDKIMM_H_")
+
+ typedef struct
+ {
+ HWND hWnd;
+ BOOL fOpen;
+ POINT ptStatusWndPos;
+ POINT ptSoftKbdPos;
+ DWORD fdwConversion;
+ DWORD fdwSentence;
+ union
+ {
+ LOGFONTA A;
+ LOGFONTW W;
+ } lfFont;
+ COMPOSITIONFORM cfCompForm;
+ CANDIDATEFORM cfCandForm[4];
+ HIMCC hCompStr;
+ HIMCC hCandInfo;
+ HIMCC hGuideLine;
+ HIMCC hPrivate;
+ DWORD dwNumMsgBuf;
+ HIMCC hMsgBuf;
+ DWORD fdwInit;
+ DWORD dwReserve[3];
+ } INPUTCONTEXT;
+
+ typedef struct
+ {
+ DWORD dwPrivateDataSize;
+ DWORD fdwProperty;
+ DWORD fdwConversionCaps;
+ DWORD fdwSentenceCaps;
+ DWORD fdwUICaps;
+ DWORD fdwSCSCaps;
+ DWORD fdwSelectCaps;
+ } IMEINFO;
+
+ cpp_quote("#endif")
+
+ [
+ object,
+ uuid(08C03412-F96B-11d0-A475-00AA006BCC59),
+ pointer_default(unique)
+ ]
+ interface IEnumRegisterWordA : IUnknown
+ {
+ HRESULT Clone([out] IEnumRegisterWordA **ppEnum);
+ HRESULT Next([in] ULONG ulCount, [out] REGISTERWORDA *rgRegisterWord, [out] ULONG *pcFetched);
+ HRESULT Reset();
+ HRESULT Skip([in] ULONG ulCount);
+ };
+
+ [
+ object,
+ uuid(4955DD31-B159-11d0-8FCF-00AA006BCC59),
+ pointer_default(unique)
+ ]
+ interface IEnumRegisterWordW : IUnknown
+ {
+ HRESULT Clone([out] IEnumRegisterWordW **ppEnum);
+ HRESULT Next([in] ULONG ulCount, [out] REGISTERWORDW *rgRegisterWord, [out] ULONG *pcFetched);
+ HRESULT Reset();
+ HRESULT Skip([in] ULONG ulCount);
+ };
+
+
+ [
+ object,
+ uuid(09b5eab0-f997-11d1-93d4-0060b067b86e),
+ pointer_default(unique)
+ ]
+ interface IEnumInputContext : IUnknown
+ {
+ HRESULT Clone([out] IEnumInputContext **ppEnum);
+ HRESULT Next([in] ULONG ulCount, [out] HIMC *rgInputContext, [out] ULONG *pcFetched);
+ HRESULT Reset();
+ HRESULT Skip([in] ULONG ulCount);
+ };
+
+
+ [
+ object,
+ uuid(b3458082-bd00-11d1-939b-0060b067b86e),
+ pointer_default(unique)
+ ]
+ interface IActiveIMMRegistrar : IUnknown
+ {
+ HRESULT RegisterIME([in] REFCLSID rclsid, [in] LANGID lgid, [in] LPCWSTR pszIconFile, [in] LPCWSTR pszDesc);
+ HRESULT UnregisterIME([in] REFCLSID rclsid);
+ };
+
+ [
+ object,
+ uuid(b5cf2cfa-8aeb-11d1-9364-0060b067b86e),
+ pointer_default(unique)
+ ]
+ interface IActiveIMMMessagePumpOwner : IUnknown
+ {
+ HRESULT Start();
+ HRESULT End();
+ HRESULT OnTranslateMessage([in] const MSG *pMsg);
+ HRESULT Pause([out] DWORD *pdwCookie);
+ HRESULT Resume([in] DWORD dwCookie);
+ }
+
+ [
+ object,
+ uuid(08c0e040-62d1-11d1-9326-0060b067b86e),
+ pointer_default(unique)
+ ]
+ interface IActiveIMMApp : IUnknown
+ {
+ HRESULT AssociateContext([in] HWND hWnd, [in] HIMC hIME, [out] HIMC *phPrev);
+ HRESULT ConfigureIMEA([in] HKL hKL, [in] HWND hWnd, [in] DWORD dwMode, [in] REGISTERWORDA *pData);
+ HRESULT ConfigureIMEW([in] HKL hKL, [in] HWND hWnd, [in] DWORD dwMode, [in] REGISTERWORDW *pData);
+ HRESULT CreateContext([out] HIMC *phIMC);
+ HRESULT DestroyContext([in] HIMC hIME);
+ HRESULT EnumRegisterWordA([in] HKL hKL, [in] LPSTR szReading, [in] DWORD dwStyle, [in] LPSTR szRegister, [in] LPVOID pData, [out] IEnumRegisterWordA **pEnum);
+ HRESULT EnumRegisterWordW([in] HKL hKL, [in] LPWSTR szReading, [in] DWORD dwStyle, [in] LPWSTR szRegister, [in] LPVOID pData, [out] IEnumRegisterWordW **pEnum);
+ HRESULT EscapeA([in] HKL hKL, [in] HIMC hIMC, [in] UINT uEscape, [in, out] LPVOID pData, [out] LRESULT *plResult);
+ HRESULT EscapeW([in] HKL hKL, [in] HIMC hIMC, [in] UINT uEscape, [in, out] LPVOID pData, [out] LRESULT *plResult);
+ HRESULT GetCandidateListA([in] HIMC hIMC, [in] DWORD dwIndex, [in] UINT uBufLen, [out] CANDIDATELIST *pCandList, [out] UINT *puCopied);
+ HRESULT GetCandidateListW([in] HIMC hIMC, [in] DWORD dwIndex, [in] UINT uBufLen, [out] CANDIDATELIST *pCandList, [out] UINT *puCopied);
+ HRESULT GetCandidateListCountA([in] HIMC hIMC, [out] DWORD *pdwListSize, [out] DWORD *pdwBufLen);
+ HRESULT GetCandidateListCountW([in] HIMC hIMC, [out] DWORD *pdwListSize, [out] DWORD *pdwBufLen);
+ HRESULT GetCandidateWindow([in] HIMC hIMC, [in] DWORD dwIndex, [out] CANDIDATEFORM *pCandidate);
+ HRESULT GetCompositionFontA([in] HIMC hIMC, [out] LOGFONTA *plf);
+ HRESULT GetCompositionFontW([in] HIMC hIMC, [out] LOGFONTW *plf);
+ HRESULT GetCompositionStringA([in] HIMC hIMC, [in] DWORD dwIndex, [in] DWORD dwBufLen, [out] LONG *plCopied, [out] LPVOID pBuf);
+ HRESULT GetCompositionStringW([in] HIMC hIMC, [in] DWORD dwIndex, [in] DWORD dwBufLen, [out] LONG *plCopied, [out] LPVOID pBuf);
+ HRESULT GetCompositionWindow([in] HIMC hIMC, [out] COMPOSITIONFORM *pCompForm);
+ HRESULT GetContext([in] HWND hWnd, [out] HIMC *phIMC);
+ HRESULT GetConversionListA([in] HKL hKL, [in] HIMC hIMC, [in] LPSTR pSrc, [in] UINT uBufLen, [in] UINT uFlag, [out] CANDIDATELIST *pDst, [out] UINT *puCopied);
+ HRESULT GetConversionListW([in] HKL hKL, [in] HIMC hIMC, [in] LPWSTR pSrc, [in] UINT uBufLen, [in] UINT uFlag, [out] CANDIDATELIST *pDst, [out] UINT *puCopied);
+ HRESULT GetConversionStatus([in] HIMC hIMC, [out] DWORD *pfdwConversion, [out] DWORD *pfdwSentence);
+ HRESULT GetDefaultIMEWnd([in] HWND hWnd, [out] HWND *phDefWnd);
+ HRESULT GetDescriptionA([in] HKL hKL, [in] UINT uBufLen, [out] LPSTR szDescription, [out] UINT *puCopied);
+ HRESULT GetDescriptionW([in] HKL hKL, [in] UINT uBufLen, [out] LPWSTR szDescription, [out] UINT *puCopied);
+ HRESULT GetGuideLineA([in] HIMC hIMC, [in] DWORD dwIndex, [in] DWORD dwBufLen, [out] LPSTR pBuf, [out] DWORD *pdwResult);
+ HRESULT GetGuideLineW([in] HIMC hIMC, [in] DWORD dwIndex, [in] DWORD dwBufLen, [out] LPWSTR pBuf, [out] DWORD *pdwResult);
+ HRESULT GetIMEFileNameA([in] HKL hKL, [in] UINT uBufLen, [out] LPSTR szFileName, [out] UINT *puCopied);
+ HRESULT GetIMEFileNameW([in] HKL hKL, [in] UINT uBufLen, [out] LPWSTR szFileName, [out] UINT *puCopied);
+ HRESULT GetOpenStatus([in] HIMC hIMC);
+ HRESULT GetProperty([in] HKL hKL, [in] DWORD fdwIndex, [out] DWORD *pdwProperty);
+ HRESULT GetRegisterWordStyleA([in] HKL hKL, [in] UINT nItem, [out] STYLEBUFA *pStyleBuf, [out] UINT *puCopied);
+ HRESULT GetRegisterWordStyleW([in] HKL hKL, [in] UINT nItem, [out] STYLEBUFW *pStyleBuf, [out] UINT *puCopied);
+ HRESULT GetStatusWindowPos([in] HIMC hIMC, [out] POINT *pptPos);
+ HRESULT GetVirtualKey([in] HWND hWnd, [out] UINT *puVirtualKey);
+ HRESULT InstallIMEA([in] LPSTR szIMEFileName, [in] LPSTR szLayoutText, [out] HKL *phKL);
+ HRESULT InstallIMEW([in] LPWSTR szIMEFileName, [in] LPWSTR szLayoutText, [out] HKL *phKL);
+ HRESULT IsIME([in] HKL hKL);
+ HRESULT IsUIMessageA([in] HWND hWndIME, [in] UINT msg, [in] WPARAM wParam, [in] LPARAM lParam);
+ HRESULT IsUIMessageW([in] HWND hWndIME, [in] UINT msg, [in] WPARAM wParam, [in] LPARAM lParam);
+ HRESULT NotifyIME([in] HIMC hIMC, [in] DWORD dwAction, [in] DWORD dwIndex, [in] DWORD dwValue);
+ HRESULT RegisterWordA([in] HKL hKL, [in] LPSTR szReading, [in] DWORD dwStyle, [in] LPSTR szRegister);
+ HRESULT RegisterWordW([in] HKL hKL, [in] LPWSTR szReading, [in] DWORD dwStyle, [in] LPWSTR szRegister);
+ HRESULT ReleaseContext([in] HWND hWnd, [in] HIMC hIMC);
+ HRESULT SetCandidateWindow([in] HIMC hIMC, [in] CANDIDATEFORM *pCandidate);
+ HRESULT SetCompositionFontA([in] HIMC hIMC, [in] LOGFONTA *plf);
+ HRESULT SetCompositionFontW([in] HIMC hIMC, [in] LOGFONTW *plf);
+ HRESULT SetCompositionStringA([in] HIMC hIMC, [in] DWORD dwIndex, [in] LPVOID pComp, [in] DWORD dwCompLen, [in] LPVOID pRead, [in] DWORD dwReadLen);
+ HRESULT SetCompositionStringW([in] HIMC hIMC, [in] DWORD dwIndex, [in] LPVOID pComp, [in] DWORD dwCompLen, [in] LPVOID pRead, [in] DWORD dwReadLen);
+ HRESULT SetCompositionWindow([in] HIMC hIMC, [in] COMPOSITIONFORM *pCompForm);
+ HRESULT SetConversionStatus([in] HIMC hIMC, [in] DWORD fdwConversion, [in] DWORD fdwSentence);
+ HRESULT SetOpenStatus([in] HIMC hIMC, [in] BOOL fOpen);
+ HRESULT SetStatusWindowPos([in] HIMC hIMC, [in] POINT *pptPos);
+ HRESULT SimulateHotKey([in] HWND hWnd, [in] DWORD dwHotKeyID);
+ HRESULT UnregisterWordA([in] HKL hKL, [in] LPSTR szReading, [in] DWORD dwStyle, [in] LPSTR szUnregister);
+ HRESULT UnregisterWordW([in] HKL hKL, [in] LPWSTR szReading, [in] DWORD dwStyle, [in] LPWSTR szUnregister);
+
+ HRESULT Activate([in] BOOL fRestoreLayout);
+ HRESULT Deactivate();
+
+ HRESULT OnDefWindowProc([in] HWND hWnd, [in] UINT Msg, [in] WPARAM wParam, [in] LPARAM lParam, [out] LRESULT *plResult);
+
+ HRESULT FilterClientWindows([in] ATOM *aaClassList, [in] UINT uSize);
+
+ HRESULT GetCodePageA([in] HKL hKL, [out] UINT *uCodePage);
+ HRESULT GetLangId([in] HKL hKL, [out] LANGID *plid);
+
+ // win98/nt5 apis
+ HRESULT AssociateContextEx([in] HWND hWnd, [in] HIMC hIMC, [in] DWORD dwFlags);
+ HRESULT DisableIME([in] DWORD idThread);
+ HRESULT GetImeMenuItemsA([in] HIMC hIMC, [in] DWORD dwFlags, [in] DWORD dwType, [in] IMEMENUITEMINFOA *pImeParentMenu, [out] IMEMENUITEMINFOA *pImeMenu, [in] DWORD dwSize, [out] DWORD *pdwResult);
+ HRESULT GetImeMenuItemsW([in] HIMC hIMC, [in] DWORD dwFlags, [in] DWORD dwType, [in] IMEMENUITEMINFOW *pImeParentMenu, [out] IMEMENUITEMINFOW *pImeMenu, [in] DWORD dwSize, [out] DWORD *pdwResult);
+ HRESULT EnumInputContext([in] DWORD idThread, [out] IEnumInputContext **ppEnum);
+ };
+
+ [
+ object,
+ uuid(08C03411-F96B-11d0-A475-00AA006BCC59),
+ pointer_default(unique)
+ ]
+ interface IActiveIMMIME : IUnknown
+ {
+ HRESULT AssociateContext([in] HWND hWnd, [in] HIMC hIME, [out] HIMC *phPrev);
+ HRESULT ConfigureIMEA([in] HKL hKL, [in] HWND hWnd, [in] DWORD dwMode, [in] REGISTERWORDA *pData);
+ HRESULT ConfigureIMEW([in] HKL hKL, [in] HWND hWnd, [in] DWORD dwMode, [in] REGISTERWORDW *pData);
+ HRESULT CreateContext([out] HIMC *phIMC);
+ HRESULT DestroyContext([in] HIMC hIME);
+ HRESULT EnumRegisterWordA([in] HKL hKL, [in] LPSTR szReading, [in] DWORD dwStyle, [in] LPSTR szRegister, [in] LPVOID pData, [out] IEnumRegisterWordA **pEnum);
+ HRESULT EnumRegisterWordW([in] HKL hKL, [in] LPWSTR szReading, [in] DWORD dwStyle, [in] LPWSTR szRegister, [in] LPVOID pData, [out] IEnumRegisterWordW **pEnum);
+ HRESULT EscapeA([in] HKL hKL, [in] HIMC hIMC, [in] UINT uEscape, [in, out] LPVOID pData, [out] LRESULT *plResult);
+ HRESULT EscapeW([in] HKL hKL, [in] HIMC hIMC, [in] UINT uEscape, [in, out] LPVOID pData, [out] LRESULT *plResult);
+ HRESULT GetCandidateListA([in] HIMC hIMC, [in] DWORD dwIndex, [in] UINT uBufLen, [out] CANDIDATELIST *pCandList, [out] UINT *puCopied);
+ HRESULT GetCandidateListW([in] HIMC hIMC, [in] DWORD dwIndex, [in] UINT uBufLen, [out] CANDIDATELIST *pCandList, [out] UINT *puCopied);
+ HRESULT GetCandidateListCountA([in] HIMC hIMC, [out] DWORD *pdwListSize, [out] DWORD *pdwBufLen);
+ HRESULT GetCandidateListCountW([in] HIMC hIMC, [out] DWORD *pdwListSize, [out] DWORD *pdwBufLen);
+ HRESULT GetCandidateWindow([in] HIMC hIMC, [in] DWORD dwIndex, [out] CANDIDATEFORM *pCandidate);
+ HRESULT GetCompositionFontA([in] HIMC hIMC, [out] LOGFONTA *plf);
+ HRESULT GetCompositionFontW([in] HIMC hIMC, [out] LOGFONTW *plf);
+ HRESULT GetCompositionStringA([in] HIMC hIMC, [in] DWORD dwIndex, [in] DWORD dwBufLen, [out] LONG *plCopied, [out] LPVOID pBuf);
+ HRESULT GetCompositionStringW([in] HIMC hIMC, [in] DWORD dwIndex, [in] DWORD dwBufLen, [out] LONG *plCopied, [out] LPVOID pBuf);
+ HRESULT GetCompositionWindow([in] HIMC hIMC, [out] COMPOSITIONFORM *pCompForm);
+ HRESULT GetContext([in] HWND hWnd, [out] HIMC *phIMC);
+ HRESULT GetConversionListA([in] HKL hKL, [in] HIMC hIMC, [in] LPSTR pSrc, [in] UINT uBufLen, [in] UINT uFlag, [out] CANDIDATELIST *pDst, [out] UINT *puCopied);
+ HRESULT GetConversionListW([in] HKL hKL, [in] HIMC hIMC, [in] LPWSTR pSrc, [in] UINT uBufLen, [in] UINT uFlag, [out] CANDIDATELIST *pDst, [out] UINT *puCopied);
+ HRESULT GetConversionStatus([in] HIMC hIMC, [out] DWORD *pfdwConversion, [out] DWORD *pfdwSentence);
+ HRESULT GetDefaultIMEWnd([in] HWND hWnd, [out] HWND *phDefWnd);
+ HRESULT GetDescriptionA([in] HKL hKL, [in] UINT uBufLen, [out] LPSTR szDescription, [out] UINT *puCopied);
+ HRESULT GetDescriptionW([in] HKL hKL, [in] UINT uBufLen, [out] LPWSTR szDescription, [out] UINT *puCopied);
+ HRESULT GetGuideLineA([in] HIMC hIMC, [in] DWORD dwIndex, [in] DWORD dwBufLen, [out] LPSTR pBuf, [out] DWORD *pdwResult);
+ HRESULT GetGuideLineW([in] HIMC hIMC, [in] DWORD dwIndex, [in] DWORD dwBufLen, [out] LPWSTR pBuf, [out] DWORD *pdwResult);
+ HRESULT GetIMEFileNameA([in] HKL hKL, [in] UINT uBufLen, [out] LPSTR szFileName, [out] UINT *puCopied);
+ HRESULT GetIMEFileNameW([in] HKL hKL, [in] UINT uBufLen, [out] LPWSTR szFileName, [out] UINT *puCopied);
+ HRESULT GetOpenStatus([in] HIMC hIMC);
+ HRESULT GetProperty([in] HKL hKL, [in] DWORD fdwIndex, [out] DWORD *pdwProperty);
+ HRESULT GetRegisterWordStyleA([in] HKL hKL, [in] UINT nItem, [out] STYLEBUFA *pStyleBuf, [out] UINT *puCopied);
+ HRESULT GetRegisterWordStyleW([in] HKL hKL, [in] UINT nItem, [out] STYLEBUFW *pStyleBuf, [out] UINT *puCopied);
+ HRESULT GetStatusWindowPos([in] HIMC hIMC, [out] POINT *pptPos);
+ HRESULT GetVirtualKey([in] HWND hWnd, [out] UINT *puVirtualKey);
+ HRESULT InstallIMEA([in] LPSTR szIMEFileName, [in] LPSTR szLayoutText, [out] HKL *phKL);
+ HRESULT InstallIMEW([in] LPWSTR szIMEFileName, [in] LPWSTR szLayoutText, [out] HKL *phKL);
+ HRESULT IsIME([in] HKL hKL);
+ HRESULT IsUIMessageA([in] HWND hWndIME, [in] UINT msg, [in] WPARAM wParam, [in] LPARAM lParam);
+ HRESULT IsUIMessageW([in] HWND hWndIME, [in] UINT msg, [in] WPARAM wParam, [in] LPARAM lParam);
+ HRESULT NotifyIME([in] HIMC hIMC, [in] DWORD dwAction, [in] DWORD dwIndex, [in] DWORD dwValue);
+ HRESULT RegisterWordA([in] HKL hKL, [in] LPSTR szReading, [in] DWORD dwStyle, [in] LPSTR szRegister);
+ HRESULT RegisterWordW([in] HKL hKL, [in] LPWSTR szReading, [in] DWORD dwStyle, [in] LPWSTR szRegister);
+ HRESULT ReleaseContext([in] HWND hWnd, [in] HIMC hIMC);
+ HRESULT SetCandidateWindow([in] HIMC hIMC, [in] CANDIDATEFORM *pCandidate);
+ HRESULT SetCompositionFontA([in] HIMC hIMC, [in] LOGFONTA *plf);
+ HRESULT SetCompositionFontW([in] HIMC hIMC, [in] LOGFONTW *plf);
+ HRESULT SetCompositionStringA([in] HIMC hIMC, [in] DWORD dwIndex, [in] LPVOID pComp, [in] DWORD dwCompLen, [in] LPVOID pRead, [in] DWORD dwReadLen);
+ HRESULT SetCompositionStringW([in] HIMC hIMC, [in] DWORD dwIndex, [in] LPVOID pComp, [in] DWORD dwCompLen, [in] LPVOID pRead, [in] DWORD dwReadLen);
+ HRESULT SetCompositionWindow([in] HIMC hIMC, [in] COMPOSITIONFORM *pCompForm);
+ HRESULT SetConversionStatus([in] HIMC hIMC, [in] DWORD fdwConversion, [in] DWORD fdwSentence);
+ HRESULT SetOpenStatus([in] HIMC hIMC, [in] BOOL fOpen);
+ HRESULT SetStatusWindowPos([in] HIMC hIMC, [in] POINT *pptPos);
+ HRESULT SimulateHotKey([in] HWND hWnd, [in] DWORD dwHotKeyID);
+ HRESULT UnregisterWordA([in] HKL hKL, [in] LPSTR szReading, [in] DWORD dwStyle, [in] LPSTR szUnregister);
+ HRESULT UnregisterWordW([in] HKL hKL, [in] LPWSTR szReading, [in] DWORD dwStyle, [in] LPWSTR szUnregister);
+
+ // ime helper methods
+ HRESULT GenerateMessage([in] HIMC hIMC);
+
+ // HIMC and HIMCC management api's
+ HRESULT LockIMC([in] HIMC hIMC, [out] INPUTCONTEXT **ppIMC);
+ HRESULT UnlockIMC([in] HIMC hIMC);
+ HRESULT GetIMCLockCount([in] HIMC hIMC, [out] DWORD *pdwLockCount);
+ HRESULT CreateIMCC([in] DWORD dwSize, [out] HIMCC *phIMCC);
+ HRESULT DestroyIMCC([in] HIMCC hIMCC);
+ HRESULT LockIMCC([in] HIMCC hIMCC, [out] void **ppv);
+ HRESULT UnlockIMCC([in] HIMCC hIMCC);
+ HRESULT ReSizeIMCC([in] HIMCC hIMCC, [in] DWORD dwSize, [out] HIMCC *phIMCC);
+ HRESULT GetIMCCSize([in] HIMCC hIMCC, [out] DWORD *pdwSize);
+ HRESULT GetIMCCLockCount([in] HIMCC hIMCC, [out] DWORD *pdwLockCount);
+
+ // hot key manipulation api's
+ HRESULT GetHotKey([in] DWORD dwHotKeyID, [out] UINT *puModifiers, [out] UINT *puVKey, [out] HKL *phKL);
+ HRESULT SetHotKey([in] DWORD dwHotKeyID, [in] UINT uModifiers, [in] UINT uVKey, [in] HKL hKL);
+
+ // soft keyboard api's
+ HRESULT CreateSoftKeyboard([in] UINT uType, [in] HWND hOwner, [in] int x, [in] int y, [out] HWND *phSoftKbdWnd);
+ HRESULT DestroySoftKeyboard([in] HWND hSoftKbdWnd);
+ HRESULT ShowSoftKeyboard([in] HWND hSoftKbdWnd, [in] int nCmdShow);
+
+ HRESULT GetCodePageA([in] HKL hKL, [out] UINT *uCodePage);
+ HRESULT GetLangId([in] HKL hKL, [out] LANGID *plid);
+
+ HRESULT KeybdEvent([in] LANGID lgidIME, [in] BYTE bVk, [in] BYTE bScan, [in] DWORD dwFlags, [in] DWORD dwExtraInfo);
+
+ HRESULT LockModal();
+ HRESULT UnlockModal();
+
+ // win98/nt5 apis
+ HRESULT AssociateContextEx([in] HWND hWnd, [in] HIMC hIMC, [in] DWORD dwFlags);
+ HRESULT DisableIME([in] DWORD idThread);
+ HRESULT GetImeMenuItemsA([in] HIMC hIMC, [in] DWORD dwFlags, [in] DWORD dwType, [in] IMEMENUITEMINFOA *pImeParentMenu, [out] IMEMENUITEMINFOA *pImeMenu, [in] DWORD dwSize, [out] DWORD *pdwResult);
+ HRESULT GetImeMenuItemsW([in] HIMC hIMC, [in] DWORD dwFlags, [in] DWORD dwType, [in] IMEMENUITEMINFOW *pImeParentMenu, [out] IMEMENUITEMINFOW *pImeMenu, [in] DWORD dwSize, [out] DWORD *pdwResult);
+ HRESULT EnumInputContext([in] DWORD idThread, [out] IEnumInputContext **ppEnum);
+ HRESULT RequestMessageA([in] HIMC hIMC, [in] WPARAM wParam, [in] LPARAM lParam, [out] LRESULT *plResult);
+ HRESULT RequestMessageW([in] HIMC hIMC, [in] WPARAM wParam, [in] LPARAM lParam, [out] LRESULT *plResult);
+
+ HRESULT SendIMCA([in] HWND hWnd, [in] UINT uMsg, [in] WPARAM wParam, [in] LPARAM lParam, [out] LRESULT *plResult);
+ HRESULT SendIMCW([in] HWND hWnd, [in] UINT uMsg, [in] WPARAM wParam, [in] LPARAM lParam, [out] LRESULT *plResult);
+
+ HRESULT IsSleeping();
+ };
+
+ [
+ object,
+ uuid(6FE20962-D077-11d0-8FE7-00AA006BCC59),
+ pointer_default(unique)
+ ]
+ interface IActiveIME : IUnknown
+ {
+ HRESULT Inquire([in] DWORD dwSystemInfoFlags, [out] IMEINFO *pIMEInfo, [out] LPWSTR szWndClass, [out] DWORD *pdwPrivate);
+ HRESULT ConversionList([in] HIMC hIMC, [in] LPWSTR szSource, [in] UINT uFlag, [in] UINT uBufLen, [out] CANDIDATELIST *pDest, [out] UINT *puCopied);
+ HRESULT Configure([in] HKL hKL, [in] HWND hWnd, [in] DWORD dwMode, [in] REGISTERWORDW *pRegisterWord);
+ HRESULT Destroy([in] UINT uReserved);
+ HRESULT Escape([in] HIMC hIMC, [in] UINT uEscape, [in, out] void *pData, [out] LRESULT *plResult);
+ HRESULT SetActiveContext([in] HIMC hIMC, [in] BOOL fFlag);
+ HRESULT ProcessKey([in] HIMC hIMC, [in] UINT uVirKey, [in] DWORD lParam, [in] BYTE *pbKeyState);
+ HRESULT Notify([in] HIMC hIMC, [in] DWORD dwAction, [in] DWORD dwIndex, [in] DWORD dwValue);
+ HRESULT Select([in] HIMC hIMC, [in] BOOL fSelect);
+ HRESULT SetCompositionString([in] HIMC hIMC, [in] DWORD dwIndex, [in] void *pComp, [in] DWORD dwCompLen, [in] void *pRead, [in] DWORD dwReadLen);
+ HRESULT ToAsciiEx([in] UINT uVirKey, [in] UINT uScanCode, [in] BYTE *pbKeyState, [in] UINT fuState, [in] HIMC hIMC, [out] DWORD *pdwTransBuf, [out] UINT *puSize);
+ HRESULT RegisterWord([in] LPWSTR szReading, [in] DWORD dwStyle, [in] LPWSTR szString);
+ HRESULT UnregisterWord([in] LPWSTR szReading, [in] DWORD dwStyle, [in] LPWSTR szString);
+ HRESULT GetRegisterWordStyle([in] UINT nItem, [out] STYLEBUFW *pStyleBuf, [out] UINT *puBufSize);
+ HRESULT EnumRegisterWord([in] LPWSTR szReading, [in] DWORD dwStyle, [in] LPWSTR szRegister, [in] LPVOID pData, [out] IEnumRegisterWordW **ppEnum);
+ HRESULT GetCodePageA([out] UINT *uCodePage);
+ HRESULT GetLangId([out] LANGID *plid);
+ };
+
+ [
+ object,
+ uuid(e1c4bf0e-2d53-11d2-93e1-0060b067b86e),
+ pointer_default(unique)
+ ]
+ interface IActiveIME2 : IActiveIME
+ {
+ HRESULT Sleep();
+ HRESULT Unsleep([in] BOOL fDead);
+ };
+
+ [
+ uuid(4955DD33-B159-11d0-8FCF-00AA006BCC59),
+ ]
+ coclass CActiveIMM
+ {
+ [default] interface IActiveIMMApp;
+ interface IActiveIMMIME;
+ interface IActiveIMMRegistrar;
+ interface IActiveIMMMessagePumpOwner;
+ };
+}
diff --git a/src/dlldata.c b/src/dlldata.c
new file mode 100644
index 000000000..d03124cff
--- /dev/null
+++ b/src/dlldata.c
@@ -0,0 +1,38 @@
+/*********************************************************
+ DllData file -- generated by MIDL compiler
+
+ DO NOT ALTER THIS FILE
+
+ This file is regenerated by MIDL on every IDL file compile.
+
+ To completely reconstruct this file, delete it and rerun MIDL
+ on all the IDL files in this DLL, specifying this file for the
+ /dlldata command line option
+
+*********************************************************/
+
+#define PROXY_DELEGATION
+
+#include <rpcproxy.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EXTERN_PROXY_FILE( if_ole )
+
+
+PROXYFILE_LIST_START
+/* Start of list */
+ REFERENCE_PROXY_FILE( if_ole ),
+/* End of list */
+PROXYFILE_LIST_END
+
+
+DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID )
+
+#ifdef __cplusplus
+} /*extern "C" */
+#endif
+
+/* end of generated dlldata file */
diff --git a/src/dosinst.c b/src/dosinst.c
new file mode 100644
index 000000000..deaf15f7a
--- /dev/null
+++ b/src/dosinst.c
@@ -0,0 +1,2461 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * dosinst.c: Install program for Vim on MS-DOS and MS-Windows
+ *
+ * Compile with Make_mvc.mak, Make_bc3.mak, Make_bc5.mak or Make_djg.mak.
+ */
+
+/*
+ * Include common code for dosinst.c and uninstal.c.
+ */
+#define DOSINST
+#include "dosinst.h"
+
+/* Macro to do an error check I was typing over and over */
+#define CHECK_REG_ERROR(code) if (code != ERROR_SUCCESS) { printf("%ld error number: %ld\n", (long)__LINE__, (long)code); return 1; }
+
+int has_vim = 0; /* installable vim.exe exists */
+int has_gvim = 0; /* installable gvim.exe exists */
+
+char oldvimrc[BUFSIZE]; /* name of existing vimrc file */
+char vimrc[BUFSIZE]; /* name of vimrc file to create */
+
+char *default_bat_dir = NULL; /* when not NULL, use this as the default
+ directory to write .bat files in */
+char *default_vim_dir = NULL; /* when not NULL, use this as the default
+ install dir for NSIS */
+#if 0
+char homedir[BUFSIZE]; /* home directory or "" */
+#endif
+
+/*
+ * Structure used for each choice the user can make.
+ */
+struct choice
+{
+ int active; /* non-zero when choice is active */
+ char *text; /* text displayed for this choice */
+ void (*changefunc)(int idx); /* function to change this choice */
+ int arg; /* argument for function */
+ void (*installfunc)(int idx); /* function to install this choice */
+};
+
+struct choice choices[30]; /* choices the user can make */
+int choice_count = 0; /* number of choices available */
+
+#define TABLE_SIZE(s) (int)(sizeof(s) / sizeof(*s))
+
+enum
+{
+ compat_vi = 1,
+ compat_some_enhancements,
+ compat_all_enhancements
+};
+char *(compat_choices[]) =
+{
+ "\nChoose the default way to run Vim:",
+ "Vi compatible",
+ "with some Vim ehancements",
+ "with syntax highlighting and other features switched on",
+};
+int compat_choice = (int)compat_all_enhancements;
+char *compat_text = "- run Vim %s";
+
+enum
+{
+ remap_no = 1,
+ remap_win
+};
+char *(remap_choices[]) =
+{
+ "\nChoose:",
+ "Do not remap keys for Windows behavior",
+ "Remap a few keys for Windows behavior (<C-V>, <C-C>, etc)",
+};
+int remap_choice = (int)remap_win;
+char *remap_text = "- %s";
+
+enum
+{
+ mouse_xterm = 1,
+ mouse_mswin
+};
+char *(mouse_choices[]) =
+{
+ "\nChoose the way how Vim uses the mouse:",
+ "right button extends selection (the Unix way)",
+ "right button has a popup menu (the Windows way)",
+};
+int mouse_choice = (int)mouse_mswin;
+char *mouse_text = "- The mouse %s";
+
+enum
+{
+ vimfiles_dir_none = 1,
+ vimfiles_dir_vim,
+ vimfiles_dir_home
+};
+static char *(vimfiles_dir_choices[]) =
+{
+ "\nCreate plugin directories:",
+ "No",
+ "In the VIM directory",
+ "In your HOME directory",
+};
+static int vimfiles_dir_choice;
+
+/* non-zero when selected to install the popup menu entry. */
+static int install_popup = 0;
+
+/* non-zero when selected to install the "Open with" entry. */
+static int install_openwith = 0;
+
+/* non-zero when need to add an uninstall entry in the registry */
+static int need_uninstall_entry = 0;
+
+/*
+ * Definitions of the directory name (under $VIM) of the vimfiles directory
+ * and its subdirectories:
+ */
+static char *(vimfiles_subdirs[]) =
+{
+ "colors",
+ "compiler",
+ "doc",
+ "ftdetect",
+ "ftplugin",
+ "indent",
+ "keymap",
+ "plugin",
+ "syntax",
+};
+
+/*
+ * Copy a directory name from "dir" to "buf", doubling backslashes.
+ * Also make sure it ends in a double backslash.
+ */
+ static void
+double_bs(char *dir, char *buf)
+{
+ char *d = buf;
+ char *s;
+
+ for (s = dir; *s; ++s)
+ {
+ if (*s == '\\')
+ *d++ = '\\';
+ *d++ = *s;
+ }
+ /* when dir is not empty, it must end in a double backslash */
+ if (d > buf && d[-1] != '\\')
+ {
+ *d++ = '\\';
+ *d++ = '\\';
+ }
+ *d = NUL;
+}
+
+/*
+ * Obtain a choice from a table.
+ * First entry is a question, others are choices.
+ */
+ static int
+get_choice(char **table, int entries)
+{
+ int answer;
+ int idx;
+ char dummy[100];
+
+ do
+ {
+ for (idx = 0; idx < entries; ++idx)
+ {
+ if (idx)
+ printf("%2d ", idx);
+ printf(table[idx]);
+ printf("\n");
+ }
+ printf("Choice: ");
+ if (scanf("%d", &answer) != 1)
+ {
+ scanf("%99s", dummy);
+ answer = 0;
+ }
+ }
+ while (answer < 1 || answer >= entries);
+
+ return answer;
+}
+
+/*
+ * Check if the user unpacked the archives properly.
+ * Sets "runtimeidx".
+ */
+ static void
+check_unpack(void)
+{
+ char buf[BUFSIZE];
+ FILE *fd;
+ struct stat st;
+
+ /* check for presence of the correct version number in installdir[] */
+ runtimeidx = strlen(installdir) - strlen(VIM_VERSION_NODOT);
+ if (runtimeidx <= 0
+ || stricmp(installdir + runtimeidx, VIM_VERSION_NODOT) != 0
+ || (installdir[runtimeidx - 1] != '/'
+ && installdir[runtimeidx - 1] != '\\'))
+ {
+ printf("ERROR: Install program not in directory \"%s\"\n",
+ VIM_VERSION_NODOT);
+ printf("This program can only work when it is located in its original directory\n");
+ myexit(1);
+ }
+
+ /* check if filetype.vim is present, which means the runtime archive has
+ * been unpacked */
+ sprintf(buf, "%s\\filetype.vim", installdir);
+ if (stat(buf, &st) < 0)
+ {
+ printf("ERROR: Cannot find filetype.vim in \"%s\"\n", installdir);
+ printf("It looks like you did not unpack the runtime archive.\n");
+ printf("You must unpack the runtime archive \"vim%srt.zip\" before installing.\n",
+ VIM_VERSION_NODOT + 3);
+ myexit(1);
+ }
+
+ /* Check if vim.exe or gvim.exe is in the current directory. */
+ if ((fd = fopen("gvim.exe", "r")) != NULL)
+ {
+ fclose(fd);
+ has_gvim = 1;
+ }
+ if ((fd = fopen("vim.exe", "r")) != NULL)
+ {
+ fclose(fd);
+ has_vim = 1;
+ }
+ if (!has_gvim && !has_vim)
+ {
+ printf("ERROR: Cannot find any Vim executables in \"%s\"\n\n",
+ installdir);
+ myexit(1);
+ }
+}
+
+/*
+ * Compare paths "p[plen]" to "q[qlen]". Return 0 if they match.
+ * Ignores case and differences between '/' and '\'.
+ * "plen" and "qlen" can be negative, strlen() is used then.
+ */
+ static int
+pathcmp(char *p, int plen, char *q, int qlen)
+{
+ int i;
+
+ if (plen < 0)
+ plen = strlen(p);
+ if (qlen < 0)
+ qlen = strlen(q);
+ for (i = 0; ; ++i)
+ {
+ /* End of "p": check if "q" also ends or just has a slash. */
+ if (i == plen)
+ {
+ if (i == qlen) /* match */
+ return 0;
+ if (i == qlen - 1 && (q[i] == '\\' || q[i] == '/'))
+ return 0; /* match with trailing slash */
+ return 1; /* no match */
+ }
+
+ /* End of "q": check if "p" also ends or just has a slash. */
+ if (i == qlen)
+ {
+ if (i == plen) /* match */
+ return 0;
+ if (i == plen - 1 && (p[i] == '\\' || p[i] == '/'))
+ return 0; /* match with trailing slash */
+ return 1; /* no match */
+ }
+
+ if (!(mytoupper(p[i]) == mytoupper(q[i])
+ || ((p[i] == '/' || p[i] == '\\')
+ && (q[i] == '/' || q[i] == '\\'))))
+ return 1; /* no match */
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * If the executable "**destination" is in the install directory, find another
+ * one in $PATH.
+ * On input "**destination" is the path of an executable in allocated memory
+ * (or NULL).
+ * "*destination" is set to NULL or the location of the file.
+ */
+ static void
+findoldfile(char **destination)
+{
+ char *bp = *destination;
+ size_t indir_l = strlen(installdir);
+ char *cp = bp + indir_l;
+ char *tmpname;
+ char *farname;
+
+ /*
+ * No action needed if exe not found or not in this directory.
+ */
+ if (bp == NULL
+ || strnicmp(bp, installdir, indir_l) != 0
+ || strchr("/\\", *cp++) == NULL
+ || strchr(cp, '\\') != NULL
+ || strchr(cp, '/') != NULL)
+ return;
+
+ tmpname = alloc((int)strlen(cp) + 1);
+ strcpy(tmpname, cp);
+ tmpname[strlen(tmpname) - 1] = 'x'; /* .exe -> .exx */
+
+ if (access(tmpname, 0) == 0)
+ {
+ printf("\nERROR: %s and %s clash. Remove or rename %s.\n",
+ tmpname, cp, tmpname);
+ myexit(1);
+ }
+
+ if (rename(cp, tmpname) != 0)
+ {
+ printf("\nERROR: failed to rename %s to %s: %s\n",
+ cp, tmpname, strerror(0));
+ myexit(1);
+ }
+
+ farname = searchpath_save(cp);
+
+ if (rename(tmpname, cp) != 0)
+ {
+ printf("\nERROR: failed to rename %s back to %s: %s\n",
+ tmpname, cp, strerror(0));
+ myexit(1);
+ }
+
+ free(*destination);
+ free(tmpname);
+ *destination = farname;
+}
+
+/*
+ * Check if there is a vim.[exe|bat|, gvim.[exe|bat|, etc. in the path.
+ * When "check_bat_only" is TRUE, only find "default_bat_dir".
+ */
+ static void
+find_bat_exe(int check_bat_only)
+{
+ int i;
+
+ mch_chdir(sysdrive); /* avoid looking in the "installdir" */
+
+ for (i = 1; i < TARGET_COUNT; ++i)
+ {
+ targets[i].oldbat = searchpath_save(targets[i].batname);
+ if (!check_bat_only)
+ targets[i].oldexe = searchpath_save(targets[i].exename);
+
+ if (default_bat_dir == NULL && targets[i].oldbat != NULL)
+ {
+ default_bat_dir = alloc(strlen(targets[i].oldbat) + 1);
+ strcpy(default_bat_dir, targets[i].oldbat);
+ remove_tail(default_bat_dir);
+ }
+ if (check_bat_only && targets[i].oldbat != NULL)
+ free(targets[i].oldbat);
+ }
+
+ mch_chdir(installdir);
+}
+
+#ifdef WIN3264
+/*
+ * Get the value of $VIMRUNTIME or $VIM and write it in $TEMP/vimini.ini, so
+ * that NSIS can read it.
+ * When not set, use the directory of a previously installed Vim.
+ */
+ static void
+get_vim_env(void)
+{
+ char *vim;
+ char buf[BUFSIZE];
+ FILE *fd;
+ char fname[BUFSIZE];
+
+ /* First get $VIMRUNTIME. If it's set, remove the tail. */
+ vim = getenv("VIMRUNTIME");
+ if (vim != NULL && *vim != 0)
+ {
+ strcpy(buf, vim);
+ remove_tail(buf);
+ vim = buf;
+ }
+ else
+ {
+ vim = getenv("VIM");
+ if (vim == NULL || *vim == 0)
+ {
+ /* Use the directory from an old uninstall entry. */
+ if (default_vim_dir != NULL)
+ vim = default_vim_dir;
+ else
+ /* Let NSIS know there is no default, it should use
+ * $PROGRAMFIlES. */
+ vim = "";
+ }
+ }
+
+ /* NSIS also uses GetTempPath(), thus we should get the same directory
+ * name as where NSIS will look for vimini.ini. */
+ GetTempPath(BUFSIZE, fname);
+ add_pathsep(fname);
+ strcat(fname, "vimini.ini");
+
+ fd = fopen(fname, "w");
+ if (fd != NULL)
+ {
+ /* Make it look like an .ini file, so that NSIS can read it with a
+ * ReadINIStr command. */
+ fprintf(fd, "[vimini]\n");
+ fprintf(fd, "dir=\"%s\"\n", vim);
+ fclose(fd);
+ }
+ else
+ {
+ printf("Failed to open %s\n", fname);
+ Sleep(2000);
+ }
+}
+
+/*
+ * Check for already installed Vims.
+ * Return non-zero when found one.
+ */
+ static int
+uninstall_check(void)
+{
+ HKEY key_handle;
+ HKEY uninstall_key_handle;
+ char *uninstall_key = "software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
+ char subkey_name_buff[BUFSIZE];
+ char temp_string_buffer[BUFSIZE];
+ DWORD local_bufsize = BUFSIZE;
+ FILETIME temp_pfiletime;
+ DWORD key_index;
+ char input;
+ long code;
+ DWORD value_type;
+ DWORD orig_num_keys;
+ DWORD new_num_keys;
+ int foundone = 0;
+
+ code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, uninstall_key, 0, KEY_READ,
+ &key_handle);
+ CHECK_REG_ERROR(code);
+
+ for (key_index = 0;
+ RegEnumKeyEx(key_handle, key_index, subkey_name_buff, &local_bufsize,
+ NULL, NULL, NULL, &temp_pfiletime) != ERROR_NO_MORE_ITEMS;
+ key_index++)
+ {
+ local_bufsize = BUFSIZE;
+ if (strncmp("Vim", subkey_name_buff, 3) == 0)
+ {
+ /* Open the key named Vim* */
+ code = RegOpenKeyEx(key_handle, subkey_name_buff, 0, KEY_READ,
+ &uninstall_key_handle);
+ CHECK_REG_ERROR(code);
+
+ /* get the DisplayName out of it to show the user */
+ code = RegQueryValueEx(uninstall_key_handle, "displayname", 0,
+ &value_type, (LPBYTE)temp_string_buffer,
+ &local_bufsize);
+ local_bufsize = BUFSIZE;
+ CHECK_REG_ERROR(code);
+
+ foundone = 1;
+ printf("\n*********************************************************\n");
+ printf("Vim Install found what looks like an existing Vim version.\n");
+ printf("The name of the entry is:\n");
+ printf("\n \"%s\"\n\n", temp_string_buffer);
+
+ printf("Installing the new version will disable part of the existing version.\n");
+ printf("(The batch files used in a console and the \"Edit with Vim\" entry in\n");
+ printf("the popup menu will use the new version)\n");
+
+ printf("\nDo you want to uninstall \"%s\" now?\n(y)es/(n)o) ", temp_string_buffer);
+ fflush(stdout);
+
+ /* get the UninstallString */
+ code = RegQueryValueEx(uninstall_key_handle, "uninstallstring", 0,
+ &value_type, (LPBYTE)temp_string_buffer, &local_bufsize);
+ local_bufsize = BUFSIZE;
+ CHECK_REG_ERROR(code);
+
+ /* Remember the directory, it is used as the default for NSIS. */
+ default_vim_dir = alloc(strlen(temp_string_buffer) + 1);
+ strcpy(default_vim_dir, temp_string_buffer);
+ remove_tail(default_vim_dir);
+ remove_tail(default_vim_dir);
+
+ input = 'n';
+ do
+ {
+ if (input != 'n')
+ printf("%c is an invalid reply. Please enter either 'y' or 'n'\n", input);
+
+ rewind(stdin);
+ scanf("%c", &input);
+ switch (input)
+ {
+ case 'y':
+ case 'Y':
+ /* save the number of uninstall keys so we can know if
+ * it changed */
+ RegQueryInfoKey(key_handle, NULL, NULL, NULL,
+ &orig_num_keys, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL);
+
+ /* Delete the uninstall key. It has no subkeys, so
+ * this is easy. Do this before uninstalling, that
+ * may try to delete the key as well. */
+ RegDeleteKey(key_handle, subkey_name_buff);
+
+ /* Find existing .bat files before deleting them. */
+ find_bat_exe(TRUE);
+
+ /* Execute the uninstall program. Put it in double
+ * quotes if there is an embedded space. */
+ if (strchr(temp_string_buffer, ' ') != NULL)
+ {
+ char buf[BUFSIZE];
+
+ strcpy(buf, temp_string_buffer);
+ sprintf(temp_string_buffer, "\"%s\"", buf);
+ }
+ run_command(temp_string_buffer);
+
+ /* Check if an unistall reg key was deleted.
+ * if it was, we want to decrement key_index.
+ * if we don't do this, we will skip the key
+ * immediately after any key that we delete. */
+ RegQueryInfoKey(key_handle, NULL, NULL, NULL,
+ &new_num_keys, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL);
+ if (new_num_keys < orig_num_keys)
+ key_index--;
+
+ input = 'y';
+ break;
+
+ case 'n':
+ case 'N':
+ /* Do not uninstall */
+ input = 'n';
+ break;
+
+ default: /* just drop through and redo the loop */
+ break;
+ }
+
+ } while (input != 'n' && input != 'y');
+
+ RegCloseKey(uninstall_key_handle);
+ }
+ }
+ RegCloseKey(key_handle);
+
+ return foundone;
+}
+#endif
+
+/*
+ * Find out information about the system.
+ */
+ static void
+inspect_system(void)
+{
+ char *p;
+ char buf[BUFSIZE];
+ FILE *fd;
+ int i;
+ int foundone;
+
+ /* This may take a little while, let the user know what we're doing. */
+ printf("Inspecting system...\n");
+
+ /*
+ * If $VIM is set, check that it's pointing to our directory.
+ */
+ p = getenv("VIM");
+ if (p != NULL && pathcmp(p, -1, installdir, runtimeidx - 1) != 0)
+ {
+ printf("------------------------------------------------------\n");
+ printf("$VIM is set to \"%s\".\n", p);
+ printf("This is different from where this version of Vim is:\n");
+ strcpy(buf, installdir);
+ *(buf + runtimeidx - 1) = NUL;
+ printf("\"%s\"\n", buf);
+ printf("You must adjust or remove the setting of $VIM,\n");
+ if (interactive)
+ {
+ printf("to be able to use this install program.\n");
+ myexit(1);
+ }
+ printf("otherwise Vim WILL NOT WORK properly!\n");
+ printf("------------------------------------------------------\n");
+ }
+
+ /*
+ * If $VIMRUNTIME is set, check that it's pointing to our runtime directory.
+ */
+ p = getenv("VIMRUNTIME");
+ if (p != NULL && pathcmp(p, -1, installdir, -1) != 0)
+ {
+ printf("------------------------------------------------------\n");
+ printf("$VIMRUNTIME is set to \"%s\".\n", p);
+ printf("This is different from where this version of Vim is:\n");
+ printf("\"%s\"\n", installdir);
+ printf("You must adjust or remove the setting of $VIMRUNTIME,\n");
+ if (interactive)
+ {
+ printf("to be able to use this install program.\n");
+ myexit(1);
+ }
+ printf("otherwise Vim WILL NOT WORK properly!\n");
+ printf("------------------------------------------------------\n");
+ }
+
+ /*
+ * Check if there is a vim.[exe|bat|, gvim.[exe|bat|, etc. in the path.
+ */
+ find_bat_exe(FALSE);
+
+ /*
+ * A .exe in the install directory may be found anyway on Windows 2000.
+ * Check for this situation and find another executable if necessary.
+ * w.briscoe@ponl.com 2001-01-20
+ */
+ foundone = 0;
+ for (i = 1; i < TARGET_COUNT; ++i)
+ {
+ findoldfile(&(targets[i].oldexe));
+ if (targets[i].oldexe != NULL)
+ foundone = 1;
+ }
+
+ if (foundone)
+ {
+ printf("Warning: Found Vim executable(s) in your $PATH:\n");
+ for (i = 1; i < TARGET_COUNT; ++i)
+ if (targets[i].oldexe != NULL)
+ printf("%s\n", targets[i].oldexe);
+ printf("It will be used instead of the version you are installing.\n");
+ printf("Please delete or rename it, or adjust your $PATH setting.\n");
+ }
+
+ /*
+ * Check if there is an existing ../_vimrc or ../.vimrc file.
+ */
+ strcpy(oldvimrc, installdir);
+ strcpy(oldvimrc + runtimeidx, "_vimrc");
+ if ((fd = fopen(oldvimrc, "r")) == NULL)
+ {
+ strcpy(oldvimrc + runtimeidx, "vimrc~1"); /* short version of .vimrc */
+ if ((fd = fopen(oldvimrc, "r")) == NULL)
+ {
+ strcpy(oldvimrc + runtimeidx, ".vimrc");
+ fd = fopen(oldvimrc, "r");
+ }
+ }
+ if (fd != NULL)
+ fclose(fd);
+ else
+ *oldvimrc = NUL;
+
+#if 0 /* currently not used */
+ /*
+ * Get default home directory.
+ * Prefer $HOME if it's set. For Win NT use $HOMEDRIVE and $HOMEPATH.
+ * Otherwise, if there is a "c:" drive use that.
+ */
+ p = getenv("HOME");
+ if (p != NULL && *p != NUL && strlen(p) < BUFSIZE)
+ strcpy(homedir, p);
+ else
+ {
+ p = getenv("HOMEDRIVE");
+ if (p != NULL && *p != NUL && strlen(p) + 2 < BUFSIZE)
+ {
+ strcpy(homedir, p);
+ p = getenv("HOMEPATH");
+ if (p != NULL && *p != NUL && strlen(homedir) + strlen(p) < BUFSIZE)
+ strcat(homedir, p);
+ else
+ strcat(homedir, "\\");
+ }
+ else
+ {
+ struct stat st;
+
+ if (stat("c:\\", &st) == 0)
+ strcpy(homedir, "c:\\");
+ else
+ *homedir = NUL;
+ }
+ }
+#endif
+}
+
+/*
+ * Add a dummy choice to avoid that the numbering changes depending on items
+ * in the environment. The user may type a number he remembered without
+ * looking.
+ */
+ static void
+add_dummy_choice(void)
+{
+ choices[choice_count].installfunc = NULL;
+ choices[choice_count].active = 0;
+ choices[choice_count].changefunc = NULL;
+ choices[choice_count].installfunc = NULL;
+ ++choice_count;
+}
+
+/***********************************************
+ * stuff for creating the batch files.
+ */
+
+/*
+ * Install the vim.bat, gvim.bat, etc. files.
+ */
+ static void
+install_bat_choice(int idx)
+{
+ char *batpath = targets[choices[idx].arg].batpath;
+ char *oldname = targets[choices[idx].arg].oldbat;
+ char *exename = targets[choices[idx].arg].exenamearg;
+ char *vimarg = targets[choices[idx].arg].exearg;
+ FILE *fd;
+ char buf[BUFSIZE];
+
+ if (*batpath != NUL)
+ {
+ fd = fopen(batpath, "w");
+ if (fd == NULL)
+ printf("\nERROR: Cannot open \"%s\" for writing.\n", batpath);
+ else
+ {
+ need_uninstall_entry = 1;
+
+ fprintf(fd, "@echo off\n");
+ fprintf(fd, "rem -- Run Vim --\n\n");
+
+ strcpy(buf, installdir);
+ buf[runtimeidx - 1] = NUL;
+ /* Don't use double quotes for the value here, also when buf
+ * contains a space. The quotes would be included in the value
+ * for MSDOS and NT. */
+ fprintf(fd, "set VIM=%s\n\n", buf);
+
+ strcpy(buf, installdir + runtimeidx);
+ add_pathsep(buf);
+ strcat(buf, exename);
+
+ /* Give an error message when the executable could not be found. */
+ fprintf(fd, "if exist \"%%VIM%%\\%s\" goto havevim\n", buf);
+ fprintf(fd, "echo \"%%VIM%%\\%s\" not found\n", buf);
+ fprintf(fd, "goto eof\n\n");
+ fprintf(fd, ":havevim\n");
+
+ fprintf(fd, "rem collect the arguments in VIMARGS for Win95\n");
+ fprintf(fd, "set VIMARGS=\n");
+ if (*exename == 'g')
+ fprintf(fd, "set VIMNOFORK=\n");
+ fprintf(fd, ":loopstart\n");
+ fprintf(fd, "if .%%1==. goto loopend\n");
+ if (*exename == 'g')
+ {
+ fprintf(fd, "if NOT .%%1==.-f goto noforkarg\n");
+ fprintf(fd, "set VIMNOFORK=1\n");
+ fprintf(fd, ":noforkarg\n");
+ }
+ fprintf(fd, "set VIMARGS=%%VIMARGS%% %%1\n");
+ fprintf(fd, "shift\n");
+ fprintf(fd, "goto loopstart\n\n");
+ fprintf(fd, ":loopend\n");
+
+ fprintf(fd, "if .%%OS%%==.Windows_NT goto ntaction\n\n");
+
+ /* For gvim.exe use "start" to avoid that the console window stays
+ * open. */
+ if (*exename == 'g')
+ {
+ fprintf(fd, "if .%%VIMNOFORK%%==.1 goto nofork\n");
+ fprintf(fd, "start ");
+ }
+
+ /* Do use quotes here if the path includes a space. */
+ if (strchr(installdir, ' ') != NULL)
+ fprintf(fd, "\"%%VIM%%\\%s\" %s %%VIMARGS%%\n", buf, vimarg);
+ else
+ fprintf(fd, "%%VIM%%\\%s %s %%VIMARGS%%\n", buf, vimarg);
+ fprintf(fd, "goto eof\n\n");
+
+ if (*exename == 'g')
+ {
+ fprintf(fd, ":nofork\n");
+ fprintf(fd, "start /w ");
+ /* Do use quotes here if the path includes a space. */
+ if (strchr(installdir, ' ') != NULL)
+ fprintf(fd, "\"%%VIM%%\\%s\" %s %%VIMARGS%%\n", buf,
+ vimarg);
+ else
+ fprintf(fd, "%%VIM%%\\%s %s %%VIMARGS%%\n", buf, vimarg);
+ fprintf(fd, "goto eof\n\n");
+ }
+
+ fprintf(fd, ":ntaction\n");
+ fprintf(fd, "rem for WinNT we can use %%*\n");
+
+ /* For gvim.exe use "start /b" to avoid that the console window
+ * stays open. */
+ if (*exename == 'g')
+ {
+ fprintf(fd, "if .%%VIMNOFORK%%==.1 goto noforknt\n");
+ fprintf(fd, "start \"dummy\" /b ");
+ }
+
+ /* Do use quotes here if the path includes a space. */
+ if (strchr(installdir, ' ') != NULL)
+ fprintf(fd, "\"%%VIM%%\\%s\" %s %%*\n", buf, vimarg);
+ else
+ fprintf(fd, "%%VIM%%\\%s %s %%*\n", buf, vimarg);
+ fprintf(fd, "goto eof\n\n");
+
+ if (*exename == 'g')
+ {
+ fprintf(fd, ":noforknt\n");
+ fprintf(fd, "start \"dummy\" /b /wait ");
+ /* Do use quotes here if the path includes a space. */
+ if (strchr(installdir, ' ') != NULL)
+ fprintf(fd, "\"%%VIM%%\\%s\" %s %%*\n", buf, vimarg);
+ else
+ fprintf(fd, "%%VIM%%\\%s %s %%*\n", buf, vimarg);
+ }
+
+ fprintf(fd, "\n:eof\n");
+ fprintf(fd, "set VIMARGS=\n");
+ if (*exename == 'g')
+ fprintf(fd, "set VIMNOFORK=\n");
+
+ fclose(fd);
+ printf("%s has been %s\n", batpath,
+ oldname == NULL ? "created" : "overwritten");
+ }
+ }
+}
+
+/*
+ * Make the text string for choice "idx".
+ * The format "fmt" is must have one %s item, which "arg" is used for.
+ */
+ static void
+alloc_text(int idx, char *fmt, char *arg)
+{
+ if (choices[idx].text != NULL)
+ free(choices[idx].text);
+
+ choices[idx].text = alloc((int)(strlen(fmt) + strlen(arg)) - 1);
+ sprintf(choices[idx].text, fmt, arg);
+}
+
+/*
+ * Toggle the "Overwrite .../vim.bat" to "Don't overwrite".
+ */
+ static void
+toggle_bat_choice(int idx)
+{
+ char *batname = targets[choices[idx].arg].batpath;
+ char *oldname = targets[choices[idx].arg].oldbat;
+
+ if (*batname == NUL)
+ {
+ alloc_text(idx, " Overwrite %s", oldname);
+ strcpy(batname, oldname);
+ }
+ else
+ {
+ alloc_text(idx, " Do NOT overwrite %s", oldname);
+ *batname = NUL;
+ }
+}
+
+/*
+ * Do some work for a batch file entry: Append the batch file name to the path
+ * and set the text for the choice.
+ */
+ static void
+set_bat_text(int idx, char *batpath, char *name)
+{
+ strcat(batpath, name);
+
+ alloc_text(idx, " Create %s", batpath);
+}
+
+/*
+ * Select a directory to write the batch file line.
+ */
+ static void
+change_bat_choice(int idx)
+{
+ char *path;
+ char *batpath;
+ char *name;
+ int n;
+ char *s;
+ char *p;
+ int count;
+ char **names = NULL;
+ int i;
+ int target = choices[idx].arg;
+
+ name = targets[target].batname;
+ batpath = targets[target].batpath;
+
+ path = getenv("PATH");
+ if (path == NULL)
+ {
+ printf("\nERROR: The variable $PATH is not set\n");
+ return;
+ }
+
+ /*
+ * first round: count number of names in path;
+ * second round: save names to names[].
+ */
+ for (;;)
+ {
+ count = 1;
+ for (p = path; *p; )
+ {
+ s = strchr(p, ';');
+ if (s == NULL)
+ s = p + strlen(p);
+ if (names != NULL)
+ {
+ names[count] = alloc((int)(s - p) + 1);
+ strncpy(names[count], p, s - p);
+ names[count][s - p] = NUL;
+ }
+ ++count;
+ p = s;
+ if (*p != NUL)
+ ++p;
+ }
+ if (names != NULL)
+ break;
+ names = alloc((int)(count + 1) * sizeof(char *));
+ }
+ names[0] = alloc(50);
+ sprintf(names[0], "Select directory to create %s in:", name);
+ names[count] = alloc(50);
+ if (choices[idx].arg == 0)
+ sprintf(names[count], "Do not create any .bat file.");
+ else
+ sprintf(names[count], "Do not create a %s file.", name);
+ n = get_choice(names, count + 1);
+
+ if (n == count)
+ {
+ /* Selected last item, don't create bat file. */
+ *batpath = NUL;
+ if (choices[idx].arg != 0)
+ alloc_text(idx, " Do NOT create %s", name);
+ }
+ else
+ {
+ /* Selected one of the paths. For the first item only keep the path,
+ * for the others append the batch file name. */
+ strcpy(batpath, names[n]);
+ add_pathsep(batpath);
+ if (choices[idx].arg != 0)
+ set_bat_text(idx, batpath, name);
+ }
+
+ for (i = 0; i <= count; ++i)
+ free(names[i]);
+ free(names);
+}
+
+char *bat_text_yes = "Install .bat files to use Vim at the command line:";
+char *bat_text_no = "do NOT install .bat files to use Vim at the command line";
+
+ static void
+change_main_bat_choice(int idx)
+{
+ int i;
+
+ /* let the user select a default directory or NONE */
+ change_bat_choice(idx);
+
+ if (targets[0].batpath[0] != NUL)
+ choices[idx].text = bat_text_yes;
+ else
+ choices[idx].text = bat_text_no;
+
+ /* update the individual batch file selections */
+ for (i = 1; i < TARGET_COUNT; ++i)
+ {
+ /* Only make it active when the first item has a path and the vim.exe
+ * or gvim.exe exists (there is a changefunc then). */
+ if (targets[0].batpath[0] != NUL
+ && choices[idx + i].changefunc != NULL)
+ {
+ choices[idx + i].active = 1;
+ if (choices[idx + i].changefunc == change_bat_choice
+ && targets[i].batpath[0] != NUL)
+ {
+ strcpy(targets[i].batpath, targets[0].batpath);
+ set_bat_text(idx + i, targets[i].batpath, targets[i].batname);
+ }
+ }
+ else
+ choices[idx + i].active = 0;
+ }
+}
+
+/*
+ * Initialize a choice for creating a batch file.
+ */
+ static void
+init_bat_choice(int target)
+{
+ char *batpath = targets[target].batpath;
+ char *oldbat = targets[target].oldbat;
+ char *p;
+ int i;
+
+ choices[choice_count].arg = target;
+ choices[choice_count].installfunc = install_bat_choice;
+ choices[choice_count].active = 1;
+ choices[choice_count].text = NULL; /* will be set below */
+ if (oldbat != NULL)
+ {
+ /* A [g]vim.bat exists: Only choice is to overwrite it or not. */
+ choices[choice_count].changefunc = toggle_bat_choice;
+ *batpath = NUL;
+ toggle_bat_choice(choice_count);
+ }
+ else
+ {
+ if (default_bat_dir != NULL)
+ /* Prefer using the same path as an existing .bat file. */
+ strcpy(batpath, default_bat_dir);
+ else
+ {
+ /* No [g]vim.bat exists: Write it to a directory in $PATH. Use
+ * $WINDIR by default, if it's empty the first item in $PATH. */
+ p = getenv("WINDIR");
+ if (p != NULL && *p != NUL)
+ strcpy(batpath, p);
+ else
+ {
+ p = getenv("PATH");
+ if (p == NULL || *p == NUL) /* "cannot happen" */
+ strcpy(batpath, "C:/Windows");
+ else
+ {
+ i = 0;
+ while (*p != NUL && *p != ';')
+ batpath[i++] = *p++;
+ batpath[i] = NUL;
+ }
+ }
+ }
+ add_pathsep(batpath);
+ set_bat_text(choice_count, batpath, targets[target].batname);
+
+ choices[choice_count].changefunc = change_bat_choice;
+ }
+ ++choice_count;
+}
+
+/*
+ * Set up the choices for installing .bat files.
+ * For these items "arg" is the index in targets[].
+ */
+ static void
+init_bat_choices(void)
+{
+ int i;
+
+ /* The first item is used to switch installing batch files on/off and
+ * setting the default path. */
+ choices[choice_count].text = bat_text_yes;
+ choices[choice_count].changefunc = change_main_bat_choice;
+ choices[choice_count].installfunc = NULL;
+ choices[choice_count].active = 1;
+ choices[choice_count].arg = 0;
+ ++choice_count;
+
+ /* Add items for each batch file target. Only used when not disabled by
+ * the first item. When a .exe exists, don't offer to create a .bat. */
+ for (i = 1; i < TARGET_COUNT; ++i)
+ if (targets[i].oldexe == NULL
+ && (targets[i].exenamearg[0] == 'g' ? has_gvim : has_vim))
+ init_bat_choice(i);
+ else
+ add_dummy_choice();
+}
+
+/*
+ * Install the vimrc file.
+ */
+/*ARGSUSED*/
+ static void
+install_vimrc(int idx)
+{
+ FILE *fd, *tfd;
+ char *fname;
+ char *p;
+
+ /* If an old vimrc file exists, overwrite it.
+ * Otherwise create a new one. */
+ if (*oldvimrc != NUL)
+ fname = oldvimrc;
+ else
+ fname = vimrc;
+
+ fd = fopen(fname, "w");
+ if (fd == NULL)
+ {
+ printf("\nERROR: Cannot open \"%s\" for writing.\n", fname);
+ return;
+ }
+ switch (compat_choice)
+ {
+ case compat_vi:
+ fprintf(fd, "set compatible\n");
+ break;
+ case compat_some_enhancements:
+ fprintf(fd, "set nocompatible\n");
+ break;
+ case compat_all_enhancements:
+ fprintf(fd, "set nocompatible\n");
+ fprintf(fd, "source $VIMRUNTIME/vimrc_example.vim\n");
+ break;
+ }
+ switch (remap_choice)
+ {
+ case remap_no:
+ break;
+ case remap_win:
+ fprintf(fd, "source $VIMRUNTIME/mswin.vim\n");
+ break;
+ }
+ switch (mouse_choice)
+ {
+ case mouse_xterm:
+ fprintf(fd, "behave xterm\n");
+ break;
+ case mouse_mswin:
+ fprintf(fd, "behave mswin\n");
+ break;
+ }
+ if ((tfd = fopen("diff.exe", "r")) != NULL)
+ {
+ /* Use the diff.exe that comes with the self-extracting gvim.exe. */
+ fclose(tfd);
+ fprintf(fd, "\n");
+ fprintf(fd, "set diffexpr=MyDiff()\n");
+ fprintf(fd, "function MyDiff()\n");
+ fprintf(fd, " let opt = '-a --binary '\n");
+ fprintf(fd, " if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif\n");
+ fprintf(fd, " if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif\n");
+ /* Use quotes only when needed, they may cause trouble. */
+ fprintf(fd, " let arg1 = v:fname_in\n");
+ fprintf(fd, " if arg1 =~ ' ' | let arg1 = '\"' . arg1 . '\"' | endif\n");
+ fprintf(fd, " let arg2 = v:fname_new\n");
+ fprintf(fd, " if arg2 =~ ' ' | let arg2 = '\"' . arg2 . '\"' | endif\n");
+ fprintf(fd, " let arg3 = v:fname_out\n");
+ fprintf(fd, " if arg3 =~ ' ' | let arg3 = '\"' . arg3 . '\"' | endif\n");
+ p = strchr(installdir, ' ');
+ if (p != NULL)
+ {
+ /* The path has a space. When using cmd.exe (Win NT/2000/XP) put
+ * quotes around the whole command and around the diff command.
+ * Otherwise put a double quote just before the space and at the
+ * end of the command. Putting quotes around the whole thing
+ * doesn't work on Win 95/98/ME. This is mostly guessed! */
+ fprintf(fd, " if &sh =~ '\\<cmd'\n");
+ fprintf(fd, " silent execute '!\"\"%s\\diff\" ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3 . '\"'\n", installdir);
+ fprintf(fd, " else\n");
+ *p = NUL;
+ fprintf(fd, " silent execute '!%s\" %s\\diff\" ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3\n", installdir, p + 1);
+ *p = ' ';
+ fprintf(fd, " endif\n");
+ }
+ else
+ fprintf(fd, " silent execute '!%s\\diff ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3\n", installdir);
+ fprintf(fd, "endfunction\n");
+ fprintf(fd, "\n");
+ }
+ fclose(fd);
+ printf("%s has been written\n", fname);
+}
+
+ static void
+change_vimrc_choice(int idx)
+{
+ if (choices[idx].installfunc != NULL)
+ {
+ /* Switch to NOT change or create a vimrc file. */
+ if (*oldvimrc != NUL)
+ alloc_text(idx, "Do NOT change startup file %s", oldvimrc);
+ else
+ alloc_text(idx, "Do NOT create startup file %s", vimrc);
+ choices[idx].installfunc = NULL;
+ choices[idx + 1].active = 0;
+ choices[idx + 2].active = 0;
+ choices[idx + 3].active = 0;
+ }
+ else
+ {
+ /* Switch to change or create a vimrc file. */
+ if (*oldvimrc != NUL)
+ alloc_text(idx, "Overwrite startup file %s with:", oldvimrc);
+ else
+ alloc_text(idx, "Create startup file %s with:", vimrc);
+ choices[idx].installfunc = install_vimrc;
+ choices[idx + 1].active = 1;
+ choices[idx + 2].active = 1;
+ choices[idx + 3].active = 1;
+ }
+}
+
+/*
+ * Change the choice how to run Vim.
+ */
+ static void
+change_run_choice(int idx)
+{
+ compat_choice = get_choice(compat_choices, TABLE_SIZE(compat_choices));
+ alloc_text(idx, compat_text, compat_choices[compat_choice]);
+}
+
+/*
+ * Change the choice if keys are to be remapped.
+ */
+ static void
+change_remap_choice(int idx)
+{
+ remap_choice = get_choice(remap_choices, TABLE_SIZE(remap_choices));
+ alloc_text(idx, remap_text, remap_choices[remap_choice]);
+}
+
+/*
+ * Change the choice how to select text.
+ */
+ static void
+change_mouse_choice(int idx)
+{
+ mouse_choice = get_choice(mouse_choices, TABLE_SIZE(mouse_choices));
+ alloc_text(idx, mouse_text, mouse_choices[mouse_choice]);
+}
+
+ static void
+init_vimrc_choices(void)
+{
+ /* set path for a new _vimrc file (also when not used) */
+ strcpy(vimrc, installdir);
+ strcpy(vimrc + runtimeidx, "_vimrc");
+
+ /* Set opposite value and then toggle it by calling change_vimrc_choice() */
+ if (*oldvimrc == NUL)
+ choices[choice_count].installfunc = NULL;
+ else
+ choices[choice_count].installfunc = install_vimrc;
+ choices[choice_count].text = NULL;
+ change_vimrc_choice(choice_count);
+ choices[choice_count].changefunc = change_vimrc_choice;
+ choices[choice_count].active = 1;
+ ++choice_count;
+
+ /* default way to run Vim */
+ alloc_text(choice_count, compat_text, compat_choices[compat_choice]);
+ choices[choice_count].changefunc = change_run_choice;
+ choices[choice_count].installfunc = NULL;
+ choices[choice_count].active = (*oldvimrc == NUL);
+ ++choice_count;
+
+ /* Whether to remap keys */
+ alloc_text(choice_count, remap_text , remap_choices[remap_choice]);
+ choices[choice_count].changefunc = change_remap_choice;
+ choices[choice_count].installfunc = NULL;;
+ choices[choice_count].active = (*oldvimrc == NUL);
+ ++choice_count;
+
+ /* default way to use the mouse */
+ alloc_text(choice_count, mouse_text, mouse_choices[mouse_choice]);
+ choices[choice_count].changefunc = change_mouse_choice;
+ choices[choice_count].installfunc = NULL;;
+ choices[choice_count].active = (*oldvimrc == NUL);
+ ++choice_count;
+}
+
+/*
+ * Add some entries to the registry:
+ * - to add "Edit with Vim" to the context * menu
+ * - to add Vim to the "Open with..." list
+ * - to uninstall Vim
+ */
+/*ARGSUSED*/
+ static void
+install_registry(void)
+{
+#if defined(DJGPP) || defined(WIN3264) || defined(UNIX_LINT)
+ FILE *fd;
+ const char *vim_ext_ThreadingModel = "Apartment";
+ const char *vim_ext_name = "Vim Shell Extension";
+ const char *vim_ext_clsid = "{51EEE242-AD87-11d3-9C1E-0090278BBD99}";
+ char buf[BUFSIZE];
+
+ fd = fopen("vim.reg", "w");
+ if (fd == NULL)
+ printf("ERROR: Could not open vim.reg for writing\n");
+ else
+ {
+ double_bs(installdir, buf); /* double the backslashes */
+
+ /*
+ * Write the registry entries for the "Edit with Vim" menu.
+ */
+ fprintf(fd, "REGEDIT4\n");
+ fprintf(fd, "\n");
+ if (install_popup)
+ {
+ char bufg[BUFSIZE];
+ struct stat st;
+
+ if (stat("gvimext.dll", &st) >= 0)
+ strcpy(bufg, buf);
+ else
+ /* gvimext.dll is in gvimext subdir */
+ sprintf(bufg, "%sgvimext\\\\", buf);
+
+ printf("Creating \"Edit with Vim\" popup menu entry\n");
+
+ fprintf(fd, "HKEY_CLASSES_ROOT\\CLSID\\%s\n", vim_ext_clsid);
+ fprintf(fd, "@=\"%s\"\n", vim_ext_name);
+ fprintf(fd, "[HKEY_CLASSES_ROOT\\CLSID\\%s\\InProcServer32]\n",
+ vim_ext_clsid);
+ fprintf(fd, "@=\"%sgvimext.dll\"\n", bufg);
+ fprintf(fd, "\"ThreadingModel\"=\"%s\"\n", vim_ext_ThreadingModel);
+ fprintf(fd, "\n");
+ fprintf(fd, "[HKEY_CLASSES_ROOT\\*\\shellex\\ContextMenuHandlers\\gvim]\n");
+ fprintf(fd, "@=\"%s\"\n", vim_ext_clsid);
+ fprintf(fd, "\n");
+ fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved]\n");
+ fprintf(fd, "\"%s\"=\"%s\"\n", vim_ext_clsid, vim_ext_name);
+ fprintf(fd, "\n");
+ fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Vim\\Gvim]\n");
+ fprintf(fd, "\"path\"=\"%sgvim.exe\"\n", buf);
+ fprintf(fd, "\n");
+ }
+
+ if (install_openwith)
+ {
+ printf("Creating \"Open with ...\" list entry\n");
+
+ fprintf(fd, "[HKEY_CLASSES_ROOT\\Applications\\gvim.exe]\n\n");
+ fprintf(fd, "[HKEY_CLASSES_ROOT\\Applications\\gvim.exe\\shell]\n\n");
+ fprintf(fd, "[HKEY_CLASSES_ROOT\\Applications\\gvim.exe\\shell\\edit]\n\n");
+ fprintf(fd, "[HKEY_CLASSES_ROOT\\Applications\\gvim.exe\\shell\\edit\\command]\n");
+ fprintf(fd, "@=\"%sgvim.exe \\\"%%1\\\"\"\n\n", buf);
+ fprintf(fd, "[HKEY_CLASSES_ROOT\\.htm\\OpenWithList\\gvim.exe]\n\n");
+ fprintf(fd, "[HKEY_CLASSES_ROOT\\.vim\\OpenWithList\\gvim.exe]\n\n");
+ fprintf(fd, "[HKEY_CLASSES_ROOT\\*\\OpenWithList\\gvim.exe]\n\n");
+ }
+
+ printf("Creating an uninstall entry\n");
+
+ /* The registry entries for uninstalling the menu */
+ fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT "]\n");
+
+ /* For the NSIS installer use the generated uninstaller. */
+ if (interactive)
+ {
+ fprintf(fd, "\"DisplayName\"=\"Vim " VIM_VERSION_SHORT "\"\n");
+ fprintf(fd, "\"UninstallString\"=\"%suninstal.exe\"\n", buf);
+ }
+ else
+ {
+ fprintf(fd, "\"DisplayName\"=\"Vim " VIM_VERSION_SHORT " (self-installing)\"\n");
+ fprintf(fd, "\"UninstallString\"=\"%suninstall-gui.exe\"\n", buf);
+ }
+
+ fclose(fd);
+
+ run_command("regedit /s vim.reg");
+
+ remove("vim.reg");
+ }
+#endif /* if defined(DJGPP) || defined(WIN3264) */
+}
+
+ static void
+change_popup_choice(int idx)
+{
+ if (install_popup == 0)
+ {
+ choices[idx].text = "Install an entry for Vim in the popup menu for the right\n mouse button so that you can edit any file with Vim";
+ install_popup = 1;
+ }
+ else
+ {
+ choices[idx].text = "Do NOT install an entry for Vim in the popup menu for the\n right mouse button to edit any file with Vim";
+ install_popup = 0;
+ }
+}
+
+/*
+ * Only add the choice for the popup menu entry when gvim.exe was found and
+ * both gvimext.dll and regedit.exe exist.
+ */
+ static void
+init_popup_choice(void)
+{
+ struct stat st;
+
+ if (has_gvim
+ && (stat("gvimext.dll", &st) >= 0
+ || stat("gvimext/gvimext.dll", &st) >= 0)
+#ifndef WIN3264
+ && searchpath("regedit.exe") != NULL
+#endif
+ )
+ {
+ choices[choice_count].changefunc = change_popup_choice;
+ choices[choice_count].installfunc = NULL;
+ choices[choice_count].active = 1;
+ change_popup_choice(choice_count); /* set the text */
+ ++choice_count;
+ }
+ else
+ add_dummy_choice();
+}
+
+ static void
+change_openwith_choice(int idx)
+{
+ if (install_openwith == 0)
+ {
+ choices[idx].text = "Add Vim to the \"Open With...\" list in the popup menu for the right\n mouse button so that you can edit any file with Vim";
+ install_openwith = 1;
+ }
+ else
+ {
+ choices[idx].text = "Do NOT add Vim to the \"Open With...\" list in the popup menu for the\n right mouse button to edit any file with Vim";
+ install_openwith = 0;
+ }
+}
+
+/*
+ * Only add the choice for the open-with menu entry when gvim.exe was found
+ * and and regedit.exe exist.
+ */
+ static void
+init_openwith_choice(void)
+{
+ if (has_gvim
+#ifndef WIN3264
+ && searchpath("regedit.exe") != NULL
+#endif
+ )
+ {
+ choices[choice_count].changefunc = change_openwith_choice;
+ choices[choice_count].installfunc = NULL;
+ choices[choice_count].active = 1;
+ change_openwith_choice(choice_count); /* set the text */
+ ++choice_count;
+ }
+ else
+ add_dummy_choice();
+}
+
+#ifdef WIN3264
+/* create_shortcut
+ *
+ * Create a shell link.
+ *
+ * returns 0 on failure, non-zero on successful completion.
+ *
+ * NOTE: Currently untested with mingw.
+ */
+ int
+create_shortcut(
+ const char *shortcut_name,
+ const char *iconfile_path,
+ int iconindex,
+ const char *shortcut_target,
+ const char *shortcut_args,
+ const char *workingdir
+ )
+{
+ IShellLink *shelllink_ptr;
+ HRESULT hres;
+ IPersistFile *persistfile_ptr;
+
+ /* Initialize COM library */
+ hres = CoInitialize(NULL);
+ if (!SUCCEEDED(hres))
+ {
+ printf("Error: Could not open the COM library. Not creating shortcut.\n");
+ return FAIL;
+ }
+
+ /* Instantiate a COM object for the ShellLink, store a pointer to it
+ * in shelllink_ptr. */
+ hres = CoCreateInstance(&CLSID_ShellLink,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ &IID_IShellLink,
+ (void **) &shelllink_ptr);
+
+ if (SUCCEEDED(hres)) /* If the instantiation was successful... */
+ {
+ /* ...Then build a PersistFile interface for the ShellLink so we can
+ * save it as a file after we build it. */
+ hres = shelllink_ptr->lpVtbl->QueryInterface(shelllink_ptr,
+ &IID_IPersistFile, (void **) &persistfile_ptr);
+
+ if (SUCCEEDED(hres))
+ {
+ wchar_t wsz[BUFSIZE];
+
+ /* translate the (possibly) multibyte shortcut filename to windows
+ * Unicode so it can be used as a file name.
+ */
+ MultiByteToWideChar(CP_ACP, 0, shortcut_name, -1, wsz, BUFSIZE);
+
+ /* set the attributes */
+ shelllink_ptr->lpVtbl->SetPath(shelllink_ptr, shortcut_target);
+ shelllink_ptr->lpVtbl->SetWorkingDirectory(shelllink_ptr,
+ workingdir);
+ shelllink_ptr->lpVtbl->SetIconLocation(shelllink_ptr,
+ iconfile_path, iconindex);
+ shelllink_ptr->lpVtbl->SetArguments(shelllink_ptr, shortcut_args);
+
+ /* save the shortcut to a file and return the PersistFile object*/
+ persistfile_ptr->lpVtbl->Save(persistfile_ptr, wsz, 1);
+ persistfile_ptr->lpVtbl->Release(persistfile_ptr);
+ }
+ else
+ {
+ printf("QueryInterface Error\n");
+ return FAIL;
+ }
+
+ /* Return the ShellLink object */
+ shelllink_ptr->lpVtbl->Release(shelllink_ptr);
+ }
+ else
+ {
+ printf("CoCreateInstance Error - hres = %08x\n", (int)hres);
+ return FAIL;
+ }
+
+ return OK;
+}
+
+/*
+ * Build a path to where we will put a specified link.
+ *
+ * Return 0 on error, non-zero on success
+ */
+ int
+build_link_name(
+ char *link_path,
+ const char *link_name,
+ const char *shell_folder_name)
+{
+ char shell_folder_path[BUFSIZE];
+
+ if (get_shell_folder_path(shell_folder_path, shell_folder_name) == FAIL)
+ {
+ printf("An error occurred while attempting to find the path to %s.\n",
+ shell_folder_name);
+ return FAIL;
+ }
+
+ /* Make sure the directory exists (create Start Menu\Programs\Vim).
+ * Ignore errors if it already exists. */
+ vim_mkdir(shell_folder_path, 0755);
+
+ /* build the path to the shortcut and the path to gvim.exe */
+ sprintf(link_path, "%s\\%s.lnk", shell_folder_path, link_name);
+
+ return OK;
+}
+
+ static int
+build_shortcut(
+ const char *name, /* Name of the shortcut */
+ const char *exename, /* Name of the executable (e.g., vim.exe) */
+ const char *args,
+ const char *shell_folder,
+ const char *workingdir)
+{
+ char executable_path[BUFSIZE];
+ char link_name[BUFSIZE];
+
+ sprintf(executable_path, "%s\\%s", installdir, exename);
+
+ if (build_link_name(link_name, name, shell_folder) == FAIL)
+ {
+ printf("An error has occurred. A shortcut to %s will not be created %s.\n",
+ name,
+ *shell_folder == 'd' ? "on the desktop" : "in the Start menu");
+ return FAIL;
+ }
+
+ /* Create the shortcut: */
+ return create_shortcut(link_name, executable_path, 0,
+ executable_path, args, workingdir);
+}
+
+/*
+ * We used to use "homedir" as the working directory, but that is a bad choice
+ * on multi-user systems. Not specifying a directory appears to work best.
+ */
+#define WORKDIR ""
+
+/*
+ * Create shortcut(s) in the Start Menu\Programs\Vim folder.
+ */
+ static void
+install_start_menu(int idx)
+{
+ need_uninstall_entry = 1;
+ printf("Creating start menu\n");
+ if (has_vim)
+ {
+ if (build_shortcut("Vim", "vim.exe", "",
+ VIM_STARTMENU, WORKDIR) == FAIL)
+ return;
+ if (build_shortcut("Vim Read-only", "vim.exe", "-R",
+ VIM_STARTMENU, WORKDIR) == FAIL)
+ return;
+ if (build_shortcut("Vim Diff", "vim.exe", "-d",
+ VIM_STARTMENU, WORKDIR) == FAIL)
+ return;
+ }
+ if (has_gvim)
+ {
+ if (build_shortcut("gVim", "gvim.exe", "",
+ VIM_STARTMENU, WORKDIR) == FAIL)
+ return;
+ if (build_shortcut("gVim Easy", "gvim.exe", "-y",
+ VIM_STARTMENU, WORKDIR) == FAIL)
+ return;
+ if (build_shortcut("gVim Read-only", "gvim.exe", "-R",
+ VIM_STARTMENU, WORKDIR) == FAIL)
+ return;
+ if (build_shortcut("gVim Diff", "gvim.exe", "-d",
+ VIM_STARTMENU, WORKDIR) == FAIL)
+ return;
+ }
+ if (build_shortcut("Uninstall",
+ interactive ? "uninstal.exe" : "uninstall-gui.exe", "",
+ VIM_STARTMENU, installdir) == FAIL)
+ return;
+ /* For Windows NT the working dir of the vimtutor.bat must be right,
+ * otherwise gvim.exe won't be found and using gvimbat doesn't work. */
+ if (build_shortcut("Vim tutor", "vimtutor.bat", "",
+ VIM_STARTMENU, installdir) == FAIL)
+ return;
+ if (build_shortcut("Help", has_gvim ? "gvim.exe" : "vim.exe", "-c h",
+ VIM_STARTMENU, WORKDIR) == FAIL)
+ return;
+ {
+ char shell_folder_path[BUFSIZE];
+
+ /* Creating the URL shortcut works a bit differently... */
+ if (get_shell_folder_path(shell_folder_path, VIM_STARTMENU) == FAIL)
+ {
+ printf("Finding the path of the Start menu failed\n");
+ return ;
+ }
+ add_pathsep(shell_folder_path);
+ strcat(shell_folder_path, "Vim Online.url");
+ if (!WritePrivateProfileString("InternetShortcut", "URL",
+ "http://vim.sf.net/", shell_folder_path))
+ {
+ printf("Creating the Vim online URL failed\n");
+ return;
+ }
+ }
+}
+
+ static void
+toggle_startmenu_choice(int idx)
+{
+ if (choices[idx].installfunc == NULL)
+ {
+ choices[idx].installfunc = install_start_menu;
+ choices[idx].text = "Add Vim to the Start menu";
+ }
+ else
+ {
+ choices[idx].installfunc = NULL;
+ choices[idx].text = "Do NOT add Vim to the Start menu";
+ }
+}
+
+/*
+ * Function to actually create the shortcuts
+ *
+ * Currently I am supplying no working directory to the shortcut. This
+ * means that the initial working dir will be:
+ * - the location of the shortcut if no file is supplied
+ * - the location of the file being edited if a file is supplied (ie via
+ * drag and drop onto the shortcut).
+ */
+ void
+install_shortcut_gvim(int idx)
+{
+ /* Create shortcut(s) on the desktop */
+ if (choices[idx].arg)
+ {
+ (void)build_shortcut(icon_names[0], "gvim.exe",
+ "", "desktop", WORKDIR);
+ need_uninstall_entry = 1;
+ }
+}
+
+ void
+install_shortcut_evim(int idx)
+{
+ if (choices[idx].arg)
+ {
+ (void)build_shortcut(icon_names[1], "gvim.exe",
+ "-y", "desktop", WORKDIR);
+ need_uninstall_entry = 1;
+ }
+}
+
+ void
+install_shortcut_gview(int idx)
+{
+ if (choices[idx].arg)
+ {
+ (void)build_shortcut(icon_names[2], "gvim.exe",
+ "-R", "desktop", WORKDIR);
+ need_uninstall_entry = 1;
+ }
+}
+
+ void
+toggle_shortcut_choice(int idx)
+{
+ char *arg;
+
+ if (choices[idx].installfunc == install_shortcut_gvim)
+ arg = "gVim";
+ else if (choices[idx].installfunc == install_shortcut_evim)
+ arg = "gVim Easy";
+ else
+ arg = "gVim Read-only";
+ if (choices[idx].arg)
+ {
+ choices[idx].arg = 0;
+ alloc_text(idx, "Do NOT create a desktop icon for %s", arg);
+ }
+ else
+ {
+ choices[idx].arg = 1;
+ alloc_text(idx, "Create a desktop icon for %s", arg);
+ }
+}
+#endif /* WIN3264 */
+
+ static void
+init_startmenu_choice(void)
+{
+#ifdef WIN3264
+ /* Start menu */
+ choices[choice_count].changefunc = toggle_startmenu_choice;
+ choices[choice_count].installfunc = NULL;
+ choices[choice_count].active = 1;
+ toggle_startmenu_choice(choice_count); /* set the text */
+ ++choice_count;
+#else
+ add_dummy_choice();
+#endif
+}
+
+/*
+ * Add the choice for the desktop shortcuts.
+ */
+ static void
+init_shortcut_choices(void)
+{
+#ifdef WIN3264
+ /* Shortcut to gvim */
+ choices[choice_count].text = NULL;
+ choices[choice_count].arg = 0;
+ choices[choice_count].active = has_gvim;
+ choices[choice_count].changefunc = toggle_shortcut_choice;
+ choices[choice_count].installfunc = install_shortcut_gvim;
+ toggle_shortcut_choice(choice_count);
+ ++choice_count;
+
+ /* Shortcut to evim */
+ choices[choice_count].text = NULL;
+ choices[choice_count].arg = 0;
+ choices[choice_count].active = has_gvim;
+ choices[choice_count].changefunc = toggle_shortcut_choice;
+ choices[choice_count].installfunc = install_shortcut_evim;
+ toggle_shortcut_choice(choice_count);
+ ++choice_count;
+
+ /* Shortcut to gview */
+ choices[choice_count].text = NULL;
+ choices[choice_count].arg = 0;
+ choices[choice_count].active = has_gvim;
+ choices[choice_count].changefunc = toggle_shortcut_choice;
+ choices[choice_count].installfunc = install_shortcut_gview;
+ toggle_shortcut_choice(choice_count);
+ ++choice_count;
+#else
+ add_dummy_choice();
+ add_dummy_choice();
+ add_dummy_choice();
+#endif
+}
+
+#ifdef WIN3264
+/*
+ * Attempt to register OLE for Vim.
+ */
+ static void
+install_OLE_register(void)
+{
+ char register_command_string[BUFSIZE + 30];
+
+ printf("\n--- Attempting to register Vim with OLE ---\n");
+ printf("(There is no message whether this works or not.)\n");
+
+#ifndef __CYGWIN__
+ sprintf(register_command_string, "\"%s\\gvim.exe\" -silent -register", installdir);
+#else
+ /* handle this differently for Cygwin which sometimes has trouble with
+ * Windows-style pathnames here. */
+ sprintf(register_command_string, "./gvim.exe -silent -register");
+#endif
+ system(register_command_string);
+}
+#endif /* WIN3264 */
+
+/*
+ * Remove the last part of directory "path[]" to get its parent, and put the
+ * result in "to[]".
+ */
+ static void
+dir_remove_last(const char *path, char to[BUFSIZE])
+{
+ char c;
+ long last_char_to_copy;
+ long path_length = strlen(path);
+
+ /* skip the last character just in case it is a '\\' */
+ last_char_to_copy = path_length - 2;
+ c = path[last_char_to_copy];
+
+ while (c != '\\')
+ {
+ last_char_to_copy--;
+ c = path[last_char_to_copy];
+ }
+
+ strncpy(to, path, (size_t)last_char_to_copy);
+ to[last_char_to_copy] = NUL;
+}
+
+ static void
+set_directories_text(int idx)
+{
+ if (vimfiles_dir_choice == (int)vimfiles_dir_none)
+ alloc_text(idx, "Do NOT create plugin directories%s", "");
+ else
+ alloc_text(idx, "Create plugin directories: %s",
+ vimfiles_dir_choices[vimfiles_dir_choice]);
+}
+
+/*
+ * Change the directory that the vim plugin directories will be created in:
+ * $HOME, $VIM or nowhere.
+ */
+ static void
+change_directories_choice(int idx)
+{
+ int choice_count = TABLE_SIZE(vimfiles_dir_choices);
+
+ /* Don't offer the $HOME choice if $HOME isn't set. */
+ if (getenv("HOME") == NULL)
+ --choice_count;
+ vimfiles_dir_choice = get_choice(vimfiles_dir_choices, choice_count);
+ set_directories_text(idx);
+}
+
+/*
+ * Create the plugin directories...
+ */
+/*ARGSUSED*/
+ static void
+install_vimfilesdir(int idx)
+{
+ int i;
+ char *p;
+ char vimdir_path[BUFSIZE];
+ char vimfiles_path[BUFSIZE];
+ char tmp_dirname[BUFSIZE];
+
+ /* switch on the location that the user wants the plugin directories
+ * built in */
+ switch (vimfiles_dir_choice)
+ {
+ case vimfiles_dir_vim:
+ {
+ /* Go to the %VIM% directory - check env first, then go one dir
+ * below installdir if there is no %VIM% environment variable.
+ * The accuracy of $VIM is checked in inspect_system(), so we
+ * can be sure it is ok to use here. */
+ p = getenv("VIM");
+ if (p == NULL) /* No $VIM in path */
+ dir_remove_last(installdir, vimdir_path);
+ else
+ strcpy(vimdir_path, p);
+ break;
+ }
+ case vimfiles_dir_home:
+ {
+ /* Find the $HOME directory. Its existence was already checked. */
+ p = getenv("HOME");
+ if (p == NULL)
+ {
+ printf("Internal error: $HOME is NULL\n");
+ p = "c:\\";
+ }
+ strcpy(vimdir_path, p);
+ break;
+ }
+ case vimfiles_dir_none:
+ {
+ /* Do not create vim plugin directory */
+ return;
+ }
+ }
+
+ /* Now, just create the directory. If it already exists, it will fail
+ * silently. */
+ sprintf(vimfiles_path, "%s\\vimfiles", vimdir_path);
+ vim_mkdir(vimfiles_path, 0755);
+
+ printf("Creating the following directories in \"%s\":\n", vimfiles_path);
+ for (i = 0; i < TABLE_SIZE(vimfiles_subdirs); i++)
+ {
+ sprintf(tmp_dirname, "%s\\%s", vimfiles_path, vimfiles_subdirs[i]);
+ printf(" %s", vimfiles_subdirs[i]);
+ vim_mkdir(tmp_dirname, 0755);
+ }
+ printf("\n");
+}
+
+/*
+ * Add the creation of runtime files to the setup sequence.
+ */
+ static void
+init_directories_choice(void)
+{
+ struct stat st;
+ char tmp_dirname[BUFSIZE];
+ char *p;
+
+ choices[choice_count].text = alloc(150);
+ choices[choice_count].changefunc = change_directories_choice;
+ choices[choice_count].installfunc = install_vimfilesdir;
+ choices[choice_count].active = 1;
+
+ /* Check if the "compiler" directory already exists. That's a good
+ * indication that the plugin directories were already created. */
+ if (getenv("HOME") != NULL)
+ {
+ vimfiles_dir_choice = (int)vimfiles_dir_home;
+ sprintf(tmp_dirname, "%s\\vimfiles\\compiler", getenv("HOME"));
+ if (stat(tmp_dirname, &st) == 0)
+ vimfiles_dir_choice = (int)vimfiles_dir_none;
+ }
+ else
+ {
+ vimfiles_dir_choice = (int)vimfiles_dir_vim;
+ p = getenv("VIM");
+ if (p == NULL) /* No $VIM in path, use the install dir */
+ dir_remove_last(installdir, tmp_dirname);
+ else
+ strcpy(tmp_dirname, p);
+ strcat(tmp_dirname, "\\vimfiles\\compiler");
+ if (stat(tmp_dirname, &st) == 0)
+ vimfiles_dir_choice = (int)vimfiles_dir_none;
+ }
+
+ set_directories_text(choice_count);
+ ++choice_count;
+}
+
+/*
+ * Setup the choices and the default values.
+ */
+ static void
+setup_choices(void)
+{
+ /* install the batch files */
+ init_bat_choices();
+
+ /* (over) write _vimrc file */
+ init_vimrc_choices();
+
+ /* Whether to add Vim to the popup menu */
+ init_popup_choice();
+
+ /* Whether to add Vim to the "Open With..." menu */
+ init_openwith_choice();
+
+ /* Whether to add Vim to the Start Menu. */
+ init_startmenu_choice();
+
+ /* Whether to add shortcuts to the Desktop. */
+ init_shortcut_choices();
+
+ /* Whether to create the runtime directories. */
+ init_directories_choice();
+}
+
+ static void
+print_cmd_line_help(void)
+{
+ printf("Vim installer non-interactive command line arguments:\n");
+ printf("\n");
+ printf("-create-batfiles [vim gvim evim view gview vimdiff gvimdiff]\n");
+ printf(" Create .bat files for Vim variants in the Windows directory.\n");
+ printf("-create-vimrc\n");
+ printf(" Create a default _vimrc file if one does not already exist.\n");
+ printf("-install-popup\n");
+ printf(" Install the Edit-with-Vim context menu entry\n");
+ printf("-install-openwith\n");
+ printf(" Add Vim to the \"Open With...\" context menu list\n");
+#ifdef WIN3264
+ printf("-add-start-menu");
+ printf(" Add Vim to the start menu\n");
+ printf("-install-icons");
+ printf(" Create icons for gVim executables on the desktop\n");
+#endif
+ printf("-create-directories [vim|home]\n");
+ printf(" Create runtime directories to drop plugins into; in the $VIM\n");
+ printf(" or $HOME directory\n");
+#ifdef WIN3264
+ printf("-register-OLE");
+ printf(" Register gvim for OLE\n");
+#endif
+ printf("\n");
+}
+
+/*
+ * Setup installation choices based on command line switches
+ */
+ static void
+command_line_setup_choices(int argc, char **argv)
+{
+ int i, j;
+
+ for (i = 1; i < argc; i++)
+ {
+ if (strcmp(argv[i], "-create-batfiles") == 0)
+ {
+ if (i + 1 == argc)
+ continue;
+ while (argv[i + 1][0] != '-' && i < argc)
+ {
+ i++;
+ for (j = 1; j < TARGET_COUNT; ++j)
+ if ((targets[j].exenamearg[0] == 'g' ? has_gvim : has_vim)
+ && strcmp(argv[i], targets[j].name) == 0)
+ {
+ init_bat_choice(j);
+ break;
+ }
+ if (j == TARGET_COUNT)
+ printf("%s is not a valid choice for -create-batfiles\n",
+ argv[i]);
+
+ if (i + 1 == argc)
+ break;
+ }
+ }
+ else if (strcmp(argv[i], "-create-vimrc") == 0)
+ {
+ /* Setup default vimrc choices. If there is already a _vimrc file,
+ * it will NOT be overwritten.
+ */
+ init_vimrc_choices();
+ }
+ else if (strcmp(argv[i], "-install-popup") == 0)
+ {
+ init_popup_choice();
+ }
+ else if (strcmp(argv[i], "-install-openwith") == 0)
+ {
+ init_openwith_choice();
+ }
+ else if (strcmp(argv[i], "-add-start-menu") == 0)
+ {
+ init_startmenu_choice();
+ }
+ else if (strcmp(argv[i], "-install-icons") == 0)
+ {
+ init_shortcut_choices();
+ }
+ else if (strcmp(argv[i], "-create-directories") == 0)
+ {
+ init_directories_choice();
+ if (argv[i + 1][0] != '-')
+ {
+ i++;
+ if (strcmp(argv[i], "vim") == 0)
+ vimfiles_dir_choice = (int)vimfiles_dir_vim;
+ else if (strcmp(argv[i], "home") == 0)
+ {
+ if (getenv("HOME") == NULL) /* No $HOME in environment */
+ vimfiles_dir_choice = (int)vimfiles_dir_vim;
+ else
+ vimfiles_dir_choice = (int)vimfiles_dir_home;
+ }
+ else
+ {
+ printf("Unknown argument for -create-directories: %s\n",
+ argv[i]);
+ print_cmd_line_help();
+ }
+ }
+ else /* No choice specified, default to vim directory */
+ vimfiles_dir_choice = (int)vimfiles_dir_vim;
+ }
+#ifdef WIN3264
+ else if (strcmp(argv[i], "-register-OLE") == 0)
+ {
+ /* This is always done when gvim is found */
+ }
+#endif
+ else /* Unknown switch */
+ {
+ printf("Got unknown argument argv[%d] = %s\n", i, argv[i]);
+ print_cmd_line_help();
+ }
+ }
+}
+
+
+/*
+ * Show a few screens full of helpful information.
+ */
+ static void
+show_help(void)
+{
+ static char *(items[]) =
+ {
+"Installing .bat files\n"
+"---------------------\n"
+"The vim.bat file is written in one of the directories in $PATH.\n"
+"This makes it possible to start Vim from the command line.\n"
+"If vim.exe can be found in $PATH, the choice for vim.bat will not be\n"
+"present. It is assumed you will use the existing vim.exe.\n"
+"If vim.bat can already be found in $PATH this is probably for an old\n"
+"version of Vim (but this is not checked!). You can overwrite it.\n"
+"If no vim.bat already exists, you can select one of the directories in\n"
+"$PATH for creating the batch file, or disable creating a vim.bat file.\n"
+"\n"
+"If you choose not to create the vim.bat file, Vim can still be executed\n"
+"in other ways, but not from the command line.\n"
+"\n"
+"The same applies to choices for gvim, evim, (g)view, and (g)vimdiff.\n"
+"The first item can be used to change the path for all of them.\n"
+,
+"Creating a _vimrc file\n"
+"----------------------\n"
+"The _vimrc file is used to set options for how Vim behaves.\n"
+"The install program can create a _vimrc file with a few basic choices.\n"
+"You can edit this file later to tune your preferences.\n"
+"If you already have a _vimrc or .vimrc file it can be overwritten.\n"
+"Don't do that if you have made changes to it.\n"
+,
+"Vim features\n"
+"------------\n"
+"(this choice is only available when creating a _vimrc file)\n"
+"1. Vim can run in Vi-compatible mode. Many nice Vim features are then\n"
+" disabled. In the not-Vi-compatible mode Vim is still mostly Vi\n"
+" compatible, but adds nice features like multi-level undo. Only\n"
+" choose Vi-compatible if you really need full Vi compatibility.\n"
+"2. Running Vim with some enhancements is useful when you want some of\n"
+" the nice Vim features, but have a slow computer and want to keep it\n"
+" really fast.\n"
+"3. Syntax highlighting shows many files in color. Not only does this look\n"
+" nice, it also makes it easier to spot errors and you can work faster.\n"
+" The other features include editing compressed files.\n"
+,
+"Windows key mapping\n"
+"-------------------\n"
+"(this choice is only available when creating a _vimrc file)\n"
+"Under MS-Windows the CTRL-C key copies text to the clipboard and CTRL-V\n"
+"pastes text from the clipboard. There are a few more keys like these.\n"
+"Unfortunately, in Vim these keys normally have another meaning.\n"
+"1. Choose to have the keys like they normally are in Vim (useful if you\n"
+" also use Vim on other systems).\n"
+"2. Choose to have the keys work like they are used on MS-Windows (useful\n"
+" if you mostly work on MS-Windows).\n"
+,
+"Mouse use\n"
+"---------\n"
+"(this choice is only available when creating a _vimrc file)\n"
+"The right mouse button can be used in two ways:\n"
+"1. The Unix way is to extend an existing selection. The popup menu is\n"
+" not available.\n"
+"2. The MS-Windows way is to show a popup menu, which allows you to\n"
+" copy/paste text, undo/redo, etc. Extending the selection can still be\n"
+" done by keeping SHIFT pressed while using the left mouse button\n"
+,
+"Edit-with-Vim context menu entry\n"
+"--------------------------------\n"
+"(this choice is only available when gvim.exe and gvimext.dll are present)\n"
+"You can associate different file types with Vim, so that you can (double)\n"
+"click on a file to edit it with Vim. This means you have to individually\n"
+"select each file type.\n"
+"An alternative is the option offered here: Install an \"Edit with Vim\"\n"
+"entry in the popup menu for the right mouse button. This means you can\n"
+"edit any file with Vim.\n"
+,
+"\"Open With...\" context menu entry\n"
+"--------------------------------\n"
+"(this choice is only available when gvim.exe is present)\n"
+"This option adds Vim to the \"Open With...\" entry in the popup menu for\n"
+"the right mouse button. This also makes it possible to edit HTML files\n"
+"directly from Internet Explorer.\n"
+,
+"Add Vim to the Start menu\n"
+"-------------------------\n"
+"In Windows 95 and later, Vim can be added to the Start menu. This will\n"
+"create a submenu with an entry for vim, gvim, evim, vimdiff, etc..\n"
+,
+"Icons on the desktop\n"
+"--------------------\n"
+"(these choices are only available when installing gvim)\n"
+"In Windows 95 and later, shortcuts (icons) can be created on the Desktop.\n"
+,
+"Create plugin directories\n"
+"-------------------------\n"
+"Plugin directories allow extending Vim by dropping a file into a directory.\n"
+"This choice allows creating them in $HOME (if you have a home directory) or\n"
+"$VIM (used for everybody on the system).\n"
+,
+NULL
+ };
+ int i;
+ int c;
+
+ rewind(stdin);
+ printf("\n");
+ for (i = 0; items[i] != NULL; ++i)
+ {
+ printf(items[i]);
+ printf("\n");
+ printf("Hit Enter to continue, b (back) or q (quit help): ");
+ c = getchar();
+ rewind(stdin);
+ if (c == 'b' || c == 'B')
+ {
+ if (i == 0)
+ --i;
+ else
+ i -= 2;
+ }
+ if (c == 'q' || c == 'Q')
+ break;
+ printf("\n");
+ }
+}
+
+/*
+ * Install the choices.
+ */
+ static void
+install(void)
+{
+ int i;
+
+ /* Install the selected choices. */
+ for (i = 0; i < choice_count; ++i)
+ if (choices[i].installfunc != NULL && choices[i].active)
+ (choices[i].installfunc)(i);
+
+ /* Add some entries to the registry, if needed. */
+ if (install_popup
+ || install_openwith
+ || (need_uninstall_entry && interactive)
+ || !interactive)
+ install_registry();
+
+#ifdef WIN3264
+ /* Register gvim with OLE. */
+ if (has_gvim)
+ install_OLE_register();
+#endif
+}
+
+/*
+ * request_choice
+ */
+ static void
+request_choice(void)
+{
+ int i;
+
+ printf("\n\nInstall will do for you:\n");
+ for (i = 0; i < choice_count; ++i)
+ if (choices[i].active)
+ printf("%2d %s\n", i + 1, choices[i].text);
+ printf("To change an item, enter its number\n\n");
+ printf("Enter item number, h (help), d (do it) or q (quit): ");
+}
+
+ int
+main(int argc, char **argv)
+{
+ int i;
+ char buf[BUFSIZE];
+
+ /*
+ * Run interactively if there are no command line arguments.
+ */
+ if (argc > 1)
+ interactive = 0;
+ else
+ interactive = 1;
+
+ /* Initialize this program. */
+ do_inits(argv);
+
+#ifdef WIN3264
+ if (argc > 1 && strcmp(argv[1], "-uninstall-check") == 0)
+ {
+ /* Only check for already installed Vims. Used by NSIS installer. */
+ i = uninstall_check();
+
+ /* Find the value of $VIM, because NSIS isn't able to do this by
+ * itself. */
+ get_vim_env();
+
+ /* When nothing found exit quietly. If something found wait for
+ * return pressed. */
+ if (i)
+ myexit(0);
+ exit(0);
+ }
+#endif
+
+ printf("This program sets up the installation of Vim "
+ VIM_VERSION_MEDIUM "\n\n");
+
+ /* Check if the user unpacked the archives properly. */
+ check_unpack();
+
+#ifdef WIN3264
+ /* Check for already installed Vims. */
+ if (interactive)
+ uninstall_check();
+#endif
+
+ /* Find out information about the system. */
+ inspect_system();
+
+ if (interactive)
+ {
+ /* Setup all the choices. */
+ setup_choices();
+
+ /* Let the user change choices and finally install (or quit). */
+ for (;;)
+ {
+ request_choice();
+ rewind(stdin);
+ if (scanf("%99s", buf) == 1)
+ {
+ if (isdigit(buf[0]))
+ {
+ /* Change a choice. */
+ i = atoi(buf);
+ if (i > 0 && i <= choice_count && choices[i - 1].active)
+ (choices[i - 1].changefunc)(i - 1);
+ else
+ printf("\nIllegal choice\n");
+ }
+ else if (buf[0] == 'h' || buf[0] == 'H')
+ {
+ /* Help */
+ show_help();
+ }
+ else if (buf[0] == 'd' || buf[0] == 'D')
+ {
+ /* Install! */
+ install();
+ printf("\nThat finishes the installation. Happy Vimming!\n");
+ break;
+ }
+ else if (buf[0] == 'q' || buf[0] == 'Q')
+ {
+ /* Quit */
+ printf("\nExiting without anything done\n");
+ break;
+ }
+ else
+ printf("\nIllegal choice\n");
+ }
+ }
+ printf("\n");
+ }
+ else
+ {
+ /*
+ * Run non-interactive - setup according to the command line switches
+ */
+ command_line_setup_choices(argc, argv);
+ install();
+ }
+
+ myexit(0);
+ /*NOTREACHED*/
+ return 0;
+}
diff --git a/src/dosinst.h b/src/dosinst.h
new file mode 100644
index 000000000..5ff4d67a0
--- /dev/null
+++ b/src/dosinst.h
@@ -0,0 +1,645 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * dosinst.h: Common code for dosinst.c and uninstal.c
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifndef UNIX_LINT
+# include <io.h>
+# include <ctype.h>
+
+# ifndef __CYGWIN__
+# include <direct.h>
+# endif
+
+# if defined(_WIN64) || defined(WIN32)
+# define WIN3264
+# include <windows.h>
+# include <shlobj.h>
+# else
+# include <dir.h>
+# include <bios.h>
+# include <dos.h>
+# endif
+#endif
+
+#ifdef UNIX_LINT
+/* Running lint on Unix: Some things are missing. */
+char *searchpath(char *name);
+#endif
+
+#if defined(DJGPP) || defined(UNIX_LINT)
+# include <unistd.h>
+# include <errno.h>
+#endif
+
+#include "version.h"
+
+#if defined(DJGPP) || defined(UNIX_LINT)
+# define vim_mkdir(x, y) mkdir((char *)(x), y)
+#else
+# if defined(WIN3264) && !defined(__BORLANDC__)
+# define vim_mkdir(x, y) _mkdir((char *)(x))
+# else
+# define vim_mkdir(x, y) mkdir((char *)(x))
+# endif
+#endif
+/* ---------------------------------------- */
+
+
+#define BUFSIZE 512 /* long enough to hold a file name path */
+#define NUL 0
+
+#define FAIL 0
+#define OK 1
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#define VIM_STARTMENU "Programs\\Vim " VIM_VERSION_SHORT
+
+int interactive; /* non-zero when running interactively */
+
+/*
+ * Call malloc() and exit when out of memory.
+ */
+ static void *
+alloc(int len)
+{
+ char *s;
+
+ s = malloc(len);
+ if (s == NULL)
+ {
+ printf("ERROR: out of memory\n");
+ exit(1);
+ }
+ return (void *)s;
+}
+
+/*
+ * The toupper() in Bcc 5.5 doesn't work, use our own implementation.
+ */
+ static int
+mytoupper(int c)
+{
+ if (c >= 'a' && c <= 'z')
+ return c - 'a' + 'A';
+ return c;
+}
+
+ static void
+myexit(int n)
+{
+ if (!interactive)
+ {
+ /* Present a prompt, otherwise error messages can't be read. */
+ printf("Press Enter to continue\n");
+ rewind(stdin);
+ (void)getchar();
+ }
+ exit(n);
+}
+
+#ifdef WIN3264
+/* This symbol is not defined in older versions of the SDK or Visual C++ */
+
+#ifndef VER_PLATFORM_WIN32_WINDOWS
+# define VER_PLATFORM_WIN32_WINDOWS 1
+#endif
+
+static DWORD g_PlatformId;
+
+/*
+ * Set g_PlatformId to VER_PLATFORM_WIN32_NT (NT) or
+ * VER_PLATFORM_WIN32_WINDOWS (Win95).
+ */
+ static void
+PlatformId(void)
+{
+ static int done = FALSE;
+
+ if (!done)
+ {
+ OSVERSIONINFO ovi;
+
+ ovi.dwOSVersionInfoSize = sizeof(ovi);
+ GetVersionEx(&ovi);
+
+ g_PlatformId = ovi.dwPlatformId;
+ done = TRUE;
+ }
+}
+
+# ifdef __BORLANDC__
+/* Borland defines its own searchpath() in dir.h */
+# include <dir.h>
+# else
+ static char *
+searchpath(char *name)
+{
+ static char widename[2 * BUFSIZE];
+ static char location[2 * BUFSIZE + 2];
+
+ /* There appears to be a bug in FindExecutableA() on Windows NT.
+ * Use FindExecutableW() instead... */
+ PlatformId();
+ if (g_PlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)name, -1,
+ (LPWSTR)widename, BUFSIZE);
+ if (FindExecutableW((LPCWSTR)widename, (LPCWSTR)"",
+ (LPWSTR)location) > (HINSTANCE)32)
+ {
+ WideCharToMultiByte(CP_ACP, 0, (LPWSTR)location, -1,
+ (LPSTR)widename, 2 * BUFSIZE, NULL, NULL);
+ return widename;
+ }
+ }
+ else
+ {
+ if (FindExecutableA((LPCTSTR)name, (LPCTSTR)"",
+ (LPTSTR)location) > (HINSTANCE)32)
+ return location;
+ }
+ return NULL;
+}
+# endif
+#endif
+
+/*
+ * Call searchpath() and save the result in allocated memory, or return NULL.
+ */
+ static char *
+searchpath_save(char *name)
+{
+ char *p;
+ char *s;
+
+ p = searchpath(name);
+ if (p == NULL)
+ return NULL;
+ s = alloc(strlen(p) + 1);
+ strcpy(s, p);
+ return s;
+}
+
+#ifdef WIN3264
+/*
+ * Get the path to a requested Windows shell folder.
+ *
+ * Return FAIL on error, OK on success
+ */
+ int
+get_shell_folder_path(
+ char *shell_folder_path,
+ const char *shell_folder_name)
+{
+ /*
+ * The following code was successfully built with make_mvc.mak.
+ * The resulting executable worked on Windows 95, Millennium Edition, and
+ * 2000 Professional. But it was changed after testing...
+ */
+ LPITEMIDLIST pidl = 0; /* Pointer to an Item ID list allocated below */
+ LPMALLOC pMalloc; /* Pointer to an IMalloc interface */
+ int csidl;
+ int alt_csidl = -1;
+ static int desktop_csidl = -1;
+ static int programs_csidl = -1;
+ int *pcsidl;
+ int r;
+
+ if (strcmp(shell_folder_name, "desktop") == 0)
+ {
+ pcsidl = &desktop_csidl;
+#ifdef CSIDL_COMMON_DESKTOPDIRECTORY
+ csidl = CSIDL_COMMON_DESKTOPDIRECTORY;
+ alt_csidl = CSIDL_DESKTOP;
+#else
+ csidl = CSIDL_DESKTOP;
+#endif
+ }
+ else if (strncmp(shell_folder_name, "Programs", 8) == 0)
+ {
+ pcsidl = &programs_csidl;
+#ifdef CSIDL_COMMON_PROGRAMS
+ csidl = CSIDL_COMMON_PROGRAMS;
+ alt_csidl = CSIDL_PROGRAMS;
+#else
+ csidl = CSIDL_PROGRAMS;
+#endif
+ }
+ else
+ {
+ printf("\nERROR (internal) unrecognised shell_folder_name: \"%s\"\n\n",
+ shell_folder_name);
+ return FAIL;
+ }
+
+ /* Did this stuff before, use the same ID again. */
+ if (*pcsidl >= 0)
+ {
+ csidl = *pcsidl;
+ alt_csidl = -1;
+ }
+
+retry:
+ /* Initialize pointer to IMalloc interface */
+ if (NOERROR != SHGetMalloc(&pMalloc))
+ {
+ printf("\nERROR getting interface for shell_folder_name: \"%s\"\n\n",
+ shell_folder_name);
+ return FAIL;
+ }
+
+ /* Get an ITEMIDLIST corresponding to the folder code */
+ if (NOERROR != SHGetSpecialFolderLocation(0, csidl, &pidl))
+ {
+ if (alt_csidl < 0 || NOERROR != SHGetSpecialFolderLocation(0,
+ alt_csidl, &pidl))
+ {
+ printf("\nERROR getting ITEMIDLIST for shell_folder_name: \"%s\"\n\n",
+ shell_folder_name);
+ return FAIL;
+ }
+ csidl = alt_csidl;
+ alt_csidl = -1;
+ }
+
+ /* Translate that ITEMIDLIST to a string */
+ r = SHGetPathFromIDList(pidl, shell_folder_path);
+
+ /* Free the data associated with pidl */
+ pMalloc->lpVtbl->Free(pMalloc, pidl);
+ /* Release the IMalloc interface */
+ pMalloc->lpVtbl->Release(pMalloc);
+
+ if (!r)
+ {
+ if (alt_csidl >= 0)
+ {
+ /* We probably get here for Windows 95: the "all users"
+ * desktop/start menu entry doesn't exist. */
+ csidl = alt_csidl;
+ alt_csidl = -1;
+ goto retry;
+ }
+ printf("\nERROR translating ITEMIDLIST for shell_folder_name: \"%s\"\n\n",
+ shell_folder_name);
+ return FAIL;
+ }
+
+ /* If there is an alternative: verify we can write in this directory.
+ * This should cause a retry when the "all users" directory exists but we
+ * are a normal user and can't write there. */
+ if (alt_csidl >= 0)
+ {
+ char tbuf[BUFSIZE];
+ FILE *fd;
+
+ strcpy(tbuf, shell_folder_path);
+ strcat(tbuf, "\\vim write test");
+ fd = fopen(tbuf, "w");
+ if (fd == NULL)
+ {
+ csidl = alt_csidl;
+ alt_csidl = -1;
+ goto retry;
+ }
+ fclose(fd);
+ unlink(tbuf);
+ }
+
+ /*
+ * Keep the found csidl for next time, so that we don't have to do the
+ * write test every time.
+ */
+ if (*pcsidl < 0)
+ *pcsidl = csidl;
+
+ if (strncmp(shell_folder_name, "Programs\\", 9) == 0)
+ strcat(shell_folder_path, shell_folder_name + 8);
+
+ return OK;
+}
+#endif
+
+/*
+ * List of targets. The first one (index zero) is used for the default path
+ * for the batch files.
+ */
+#define TARGET_COUNT 8
+
+struct
+{
+ char *name; /* Vim exe name (without .exe) */
+ char *batname; /* batch file name */
+ char *lnkname; /* shortcut file name */
+ char *exename; /* exe file name */
+ char *exenamearg; /* exe file name when using exearg */
+ char *exearg; /* argument for vim.exe or gvim.exe */
+ char *oldbat; /* path to existing xxx.bat or NULL */
+ char *oldexe; /* path to existing xxx.exe or NULL */
+ char batpath[BUFSIZE]; /* path of batch file to create; not
+ created when it's empty */
+} targets[TARGET_COUNT] =
+{
+ {"all", "batch files"},
+ {"vim", "vim.bat", "Vim.lnk",
+ "vim.exe", "vim.exe", ""},
+ {"gvim", "gvim.bat", "gVim.lnk",
+ "gvim.exe", "gvim.exe", ""},
+ {"evim", "evim.bat", "gVim Easy.lnk",
+ "evim.exe", "gvim.exe", "-y"},
+ {"view", "view.bat", "Vim Read-only.lnk",
+ "view.exe", "vim.exe", "-R"},
+ {"gview", "gview.bat", "gVim Read-only.lnk",
+ "gview.exe", "gvim.exe", "-R"},
+ {"vimdiff", "vimdiff.bat", "Vim Diff.lnk",
+ "vimdiff.exe","vim.exe", "-d"},
+ {"gvimdiff","gvimdiff.bat", "gVim Diff.lnk",
+ "gvimdiff.exe","gvim.exe", "-d"},
+};
+
+#define ICON_COUNT 3
+char *(icon_names[ICON_COUNT]) =
+ {"gVim " VIM_VERSION_SHORT,
+ "gVim Easy " VIM_VERSION_SHORT,
+ "gVim Read only " VIM_VERSION_SHORT};
+char *(icon_link_names[ICON_COUNT]) =
+ {"gVim " VIM_VERSION_SHORT ".lnk",
+ "gVim Easy " VIM_VERSION_SHORT ".lnk",
+ "gVim Read only " VIM_VERSION_SHORT ".lnk"};
+
+/* This is only used for dosinst.c and for uninstal.c when not being able to
+ * directly access registry entries. */
+#if !defined(WIN3264) || defined(DOSINST)
+/*
+ * Run an external command and wait for it to finish.
+ */
+ static void
+run_command(char *cmd)
+{
+ char *cmd_path;
+ char cmd_buf[BUFSIZE];
+ char *p;
+
+ /* On WinNT, 'start' is a shell built-in for cmd.exe rather than an
+ * executable (start.exe) like in Win9x. DJGPP, being a DOS program,
+ * is given the COMSPEC command.com by WinNT, so we have to find
+ * cmd.exe manually and use it. */
+ cmd_path = searchpath_save("cmd.exe");
+ if (cmd_path != NULL)
+ {
+ /* There is a cmd.exe, so this might be Windows NT. If it is,
+ * we need to call cmd.exe explicitly. If it is a later OS,
+ * calling cmd.exe won't hurt if it is present.
+ * Also, "wait" on NT expects a window title argument.
+ */
+ /* Replace the slashes with backslashes. */
+ while ((p = strchr(cmd_path, '/')) != NULL)
+ *p = '\\';
+ sprintf(cmd_buf, "%s /c start \"vimcmd\" /w %s", cmd_path, cmd);
+ free(cmd_path);
+ }
+ else
+ {
+ /* No cmd.exe, just make the call and let the system handle it. */
+ sprintf(cmd_buf, "start /w %s", cmd);
+ }
+ system(cmd_buf);
+}
+#endif
+
+/*
+ * Append a backslash to "name" if there isn't one yet.
+ */
+ static void
+add_pathsep(char *name)
+{
+ int len = strlen(name);
+
+ if (len > 0 && name[len - 1] != '\\' && name[len - 1] != '/')
+ strcat(name, "\\");
+}
+
+/*
+ * The normal chdir() does not change the default drive. This one does.
+ */
+/*ARGSUSED*/
+ int
+change_drive(int drive)
+{
+#ifdef WIN3264
+ char temp[3] = "-:";
+ temp[0] = (char)(drive + 'A' - 1);
+ return !SetCurrentDirectory(temp);
+#else
+# ifndef UNIX_LINT
+ union REGS regs;
+
+ regs.h.ah = 0x0e;
+ regs.h.dl = drive - 1;
+ intdos(&regs, &regs); /* set default drive */
+ regs.h.ah = 0x19;
+ intdos(&regs, &regs); /* get default drive */
+ if (regs.h.al == drive - 1)
+ return 0;
+# endif
+ return -1;
+#endif
+}
+
+/*
+ * Change directory to "path".
+ * Return 0 for success, -1 for failure.
+ */
+ int
+mch_chdir(char *path)
+{
+ if (path[0] == NUL) /* just checking... */
+ return 0;
+ if (path[1] == ':') /* has a drive name */
+ {
+ if (change_drive(mytoupper(path[0]) - 'A' + 1))
+ return -1; /* invalid drive name */
+ path += 2;
+ }
+ if (*path == NUL) /* drive name only */
+ return 0;
+ return chdir(path); /* let the normal chdir() do the rest */
+}
+
+/*
+ * Expand the executable name into a full path name.
+ */
+#if defined(__BORLANDC__) && !defined(WIN3264)
+
+/* Only Borland C++ has this. */
+# define my_fullpath(b, n, l) _fullpath(b, n, l)
+
+#else
+ static char *
+my_fullpath(char *buf, char *fname, int len)
+{
+# ifdef WIN3264
+ /* Only GetModuleFileName() will get the long file name path.
+ * GetFullPathName() may still use the short (FAT) name. */
+ DWORD len_read = GetModuleFileName(NULL, buf, (size_t)len);
+
+ return (len_read > 0 && len_read < (DWORD)len) ? buf : NULL;
+# else
+ char olddir[BUFSIZE];
+ char *p, *q;
+ int c;
+ char *retval = buf;
+
+ if (strchr(fname, ':') != NULL) /* allready expanded */
+ {
+ strncpy(buf, fname, len);
+ }
+ else
+ {
+ *buf = NUL;
+ /*
+ * change to the directory for a moment,
+ * and then do the getwd() (and get back to where we were).
+ * This will get the correct path name with "../" things.
+ */
+ p = strrchr(fname, '/');
+ q = strrchr(fname, '\\');
+ if (q != NULL && (p == NULL || q > p))
+ p = q;
+ q = strrchr(fname, ':');
+ if (q != NULL && (p == NULL || q > p))
+ p = q;
+ if (p != NULL)
+ {
+ if (getcwd(olddir, BUFSIZE) == NULL)
+ {
+ p = NULL; /* can't get current dir: don't chdir */
+ retval = NULL;
+ }
+ else
+ {
+ if (p == fname) /* /fname */
+ q = p + 1; /* -> / */
+ else if (q + 1 == p) /* ... c:\foo */
+ q = p + 1; /* -> c:\ */
+ else /* but c:\foo\bar */
+ q = p; /* -> c:\foo */
+
+ c = *q; /* truncate at start of fname */
+ *q = NUL;
+ if (mch_chdir(fname)) /* change to the directory */
+ retval = NULL;
+ else
+ {
+ fname = q;
+ if (c == '\\') /* if we cut the name at a */
+ fname++; /* '\', don't add it again */
+ }
+ *q = c;
+ }
+ }
+ if (getcwd(buf, len) == NULL)
+ {
+ retval = NULL;
+ *buf = NUL;
+ }
+ /*
+ * Concatenate the file name to the path.
+ */
+ if (strlen(buf) + strlen(fname) >= len - 1)
+ {
+ printf("ERROR: File name too long!\n");
+ myexit(1);
+ }
+ add_pathsep(buf);
+ strcat(buf, fname);
+ if (p)
+ mch_chdir(olddir);
+ }
+
+ /* Replace forward slashes with backslashes, required for the path to a
+ * command. */
+ while ((p = strchr(buf, '/')) != NULL)
+ *p = '\\';
+
+ return retval;
+# endif
+}
+#endif
+
+/*
+ * Remove the tail from a file or directory name.
+ * Puts a NUL on the last '/' or '\'.
+ */
+ static void
+remove_tail(char *path)
+{
+ int i;
+
+ for (i = strlen(path) - 1; i > 0; --i)
+ if (path[i] == '/' || path[i] == '\\')
+ {
+ path[i] = NUL;
+ break;
+ }
+}
+
+
+char installdir[BUFSIZE]; /* top of the installation dir, where the
+ install.exe is located, E.g.:
+ "c:\vim\vim60" */
+int runtimeidx; /* index in installdir[] where "vim60" starts */
+char *sysdrive; /* system drive or "c:\" */
+
+/*
+ * Setup for using this program.
+ * Sets "installdir[]".
+ */
+ static void
+do_inits(char **argv)
+{
+#ifdef DJGPP
+ /*
+ * Use Long File Names by default, if $LFN not set.
+ */
+ if (getenv("LFN") == NULL)
+ putenv("LFN=y");
+#endif
+
+ /* Find out the full path of our executable. */
+ if (my_fullpath(installdir, argv[0], BUFSIZE) == NULL)
+ {
+ printf("ERROR: Cannot get name of executable\n");
+ myexit(1);
+ }
+ /* remove the tail, the executable name "install.exe" */
+ remove_tail(installdir);
+
+ /* change to the installdir */
+ mch_chdir(installdir);
+
+ /* Find the system drive. Only used for searching the Vim executable, not
+ * very important. */
+ sysdrive = getenv("SYSTEMDRIVE");
+ if (sysdrive == NULL || *sysdrive == NUL)
+ sysdrive = "C:\\";
+}
diff --git a/src/edit.c b/src/edit.c
new file mode 100644
index 000000000..9a42f5ae8
--- /dev/null
+++ b/src/edit.c
@@ -0,0 +1,7614 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * edit.c: functions for Insert mode
+ */
+
+#include "vim.h"
+
+#ifdef FEAT_INS_EXPAND
+/*
+ * definitions used for CTRL-X submode
+ */
+#define CTRL_X_WANT_IDENT 0x100
+
+#define CTRL_X_NOT_DEFINED_YET 1
+#define CTRL_X_SCROLL 2
+#define CTRL_X_WHOLE_LINE 3
+#define CTRL_X_FILES 4
+#define CTRL_X_TAGS (5 + CTRL_X_WANT_IDENT)
+#define CTRL_X_PATH_PATTERNS (6 + CTRL_X_WANT_IDENT)
+#define CTRL_X_PATH_DEFINES (7 + CTRL_X_WANT_IDENT)
+#define CTRL_X_FINISHED 8
+#define CTRL_X_DICTIONARY (9 + CTRL_X_WANT_IDENT)
+#define CTRL_X_THESAURUS (10 + CTRL_X_WANT_IDENT)
+#define CTRL_X_CMDLINE 11
+
+#define CHECK_KEYS_TIME 30
+
+#define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT]
+
+static char *ctrl_x_msgs[] =
+{
+ N_(" Keyword completion (^N^P)"), /* ctrl_x_mode == 0, ^P/^N compl. */
+ N_(" ^X mode (^E^Y^L^]^F^I^K^D^V^N^P)"),
+ /* Scroll has it's own msgs, in it's place there is the msg for local
+ * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo */
+ N_(" Keyword Local completion (^N^P)"),
+ N_(" Whole line completion (^L^N^P)"),
+ N_(" File name completion (^F^N^P)"),
+ N_(" Tag completion (^]^N^P)"),
+ N_(" Path pattern completion (^N^P)"),
+ N_(" Definition completion (^D^N^P)"),
+ NULL,
+ N_(" Dictionary completion (^K^N^P)"),
+ N_(" Thesaurus completion (^T^N^P)"),
+ N_(" Command-line completion (^V^N^P)")
+};
+
+static char_u e_hitend[] = N_("Hit end of paragraph");
+
+/*
+ * Structure used to store one match for insert completion.
+ */
+struct Completion
+{
+ struct Completion *next;
+ struct Completion *prev;
+ char_u *str; /* matched text */
+ char_u *fname; /* file containing the match */
+ int original; /* ORIGINAL_TEXT, CONT_S_IPOS or FREE_FNAME */
+ int number; /* sequence number */
+};
+
+/* the original text when the expansion begun */
+#define ORIGINAL_TEXT (1)
+#define FREE_FNAME (2)
+
+/*
+ * All the current matches are stored in a list.
+ * "first_match" points to the start of the list.
+ * "curr_match" points to the currently selected entry.
+ * "shown_match" is different from curr_match during ins_compl_get_exp().
+ */
+static struct Completion *first_match = NULL;
+static struct Completion *curr_match = NULL;
+static struct Completion *shown_match = NULL;
+
+static int started_completion = FALSE;
+static int completion_matches = 0;
+static char_u *complete_pat = NULL;
+static int complete_direction = FORWARD;
+static int shown_direction = FORWARD;
+static int completion_pending = FALSE;
+static pos_T initial_pos;
+static colnr_T complete_col = 0; /* column where the text starts
+ that is being completed */
+static int save_sm;
+static char_u *original_text = NULL; /* text before completion */
+static int continue_mode = 0;
+static expand_T complete_xp;
+
+static int ins_compl_add __ARGS((char_u *str, int len, char_u *, int dir, int reuse));
+static void ins_compl_add_matches __ARGS((int num_matches, char_u **matches, int dir));
+static int ins_compl_make_cyclic __ARGS((void));
+static void ins_compl_dictionaries __ARGS((char_u *dict, char_u *pat, int dir, int flags, int thesaurus));
+static void ins_compl_free __ARGS((void));
+static void ins_compl_clear __ARGS((void));
+static void ins_compl_prep __ARGS((int c));
+static buf_T *ins_compl_next_buf __ARGS((buf_T *buf, int flag));
+static int ins_compl_get_exp __ARGS((pos_T *ini, int dir));
+static void ins_compl_delete __ARGS((void));
+static void ins_compl_insert __ARGS((void));
+static int ins_compl_next __ARGS((int allow_get_expansion));
+static int ins_complete __ARGS((int c));
+static int quote_meta __ARGS((char_u *dest, char_u *str, int len));
+#endif /* FEAT_INS_EXPAND */
+
+#define BACKSPACE_CHAR 1
+#define BACKSPACE_WORD 2
+#define BACKSPACE_WORD_NOT_SPACE 3
+#define BACKSPACE_LINE 4
+
+static void ins_redraw __ARGS((void));
+static void ins_ctrl_v __ARGS((void));
+static void undisplay_dollar __ARGS((void));
+static void insert_special __ARGS((int, int, int));
+static void check_auto_format __ARGS((int));
+static void redo_literal __ARGS((int c));
+static void start_arrow __ARGS((pos_T *end_insert_pos));
+static void stop_insert __ARGS((pos_T *end_insert_pos, int esc));
+static int echeck_abbr __ARGS((int));
+static void replace_push_off __ARGS((int c));
+static int replace_pop __ARGS((void));
+static void replace_join __ARGS((int off));
+static void replace_pop_ins __ARGS((void));
+#ifdef FEAT_MBYTE
+static void mb_replace_pop_ins __ARGS((int cc));
+#endif
+static void replace_flush __ARGS((void));
+static void replace_do_bs __ARGS((void));
+#ifdef FEAT_CINDENT
+static int cindent_on __ARGS((void));
+#endif
+static void ins_reg __ARGS((void));
+static void ins_ctrl_g __ARGS((void));
+static int ins_esc __ARGS((long *count, int cmdchar));
+#ifdef FEAT_RIGHTLEFT
+static void ins_ctrl_ __ARGS((void));
+#endif
+#ifdef FEAT_VISUAL
+static int ins_start_select __ARGS((int c));
+#endif
+static void ins_shift __ARGS((int c, int lastc));
+static void ins_del __ARGS((void));
+static int ins_bs __ARGS((int c, int mode, int *inserted_space_p));
+#ifdef FEAT_MOUSE
+static void ins_mouse __ARGS((int c));
+static void ins_mousescroll __ARGS((int up));
+#endif
+static void ins_left __ARGS((void));
+static void ins_home __ARGS((int c));
+static void ins_end __ARGS((int c));
+static void ins_s_left __ARGS((void));
+static void ins_right __ARGS((void));
+static void ins_s_right __ARGS((void));
+static void ins_up __ARGS((int startcol));
+static void ins_pageup __ARGS((void));
+static void ins_down __ARGS((int startcol));
+static void ins_pagedown __ARGS((void));
+#ifdef FEAT_DND
+static void ins_drop __ARGS((void));
+#endif
+static int ins_tab __ARGS((void));
+static int ins_eol __ARGS((int c));
+#ifdef FEAT_DIGRAPHS
+static int ins_digraph __ARGS((void));
+#endif
+static int ins_copychar __ARGS((linenr_T lnum));
+#ifdef FEAT_SMARTINDENT
+static void ins_try_si __ARGS((int c));
+#endif
+static colnr_T get_nolist_virtcol __ARGS((void));
+
+static colnr_T Insstart_textlen; /* length of line when insert started */
+static colnr_T Insstart_blank_vcol; /* vcol for first inserted blank */
+
+static char_u *last_insert = NULL; /* the text of the previous insert,
+ K_SPECIAL and CSI are escaped */
+static int last_insert_skip; /* nr of chars in front of previous insert */
+static int new_insert_skip; /* nr of chars in front of current insert */
+
+#ifdef FEAT_CINDENT
+static int can_cindent; /* may do cindenting on this line */
+#endif
+
+static int old_indent = 0; /* for ^^D command in insert mode */
+
+#ifdef FEAT_RIGHTLEFT
+int revins_on; /* reverse insert mode on */
+int revins_chars; /* how much to skip after edit */
+int revins_legal; /* was the last char 'legal'? */
+int revins_scol; /* start column of revins session */
+#endif
+
+#if defined(FEAT_MBYTE) && defined(MACOS_CLASSIC)
+static short previous_script = smRoman;
+#endif
+
+static int ins_need_undo; /* call u_save() before inserting a
+ char. Set when edit() is called.
+ after that arrow_used is used. */
+
+static int did_add_space = FALSE; /* auto_format() added an extra space
+ under the cursor */
+
+/*
+ * edit(): Start inserting text.
+ *
+ * "cmdchar" can be:
+ * 'i' normal insert command
+ * 'a' normal append command
+ * 'R' replace command
+ * 'r' "r<CR>" command: insert one <CR>. Note: count can be > 1, for redo,
+ * but still only one <CR> is inserted. The <Esc> is not used for redo.
+ * 'g' "gI" command.
+ * 'V' "gR" command for Virtual Replace mode.
+ * 'v' "gr" command for single character Virtual Replace mode.
+ *
+ * This function is not called recursively. For CTRL-O commands, it returns
+ * and lets the caller handle the Normal-mode command.
+ *
+ * Return TRUE if a CTRL-O command caused the return (insert mode pending).
+ */
+ int
+edit(cmdchar, startln, count)
+ int cmdchar;
+ int startln; /* if set, insert at start of line */
+ long count;
+{
+ int c = 0;
+ char_u *ptr;
+ int lastc;
+ colnr_T mincol;
+ static linenr_T o_lnum = 0;
+ static int o_eol = FALSE;
+ int i;
+ int did_backspace = TRUE; /* previous char was backspace */
+#ifdef FEAT_CINDENT
+ int line_is_white = FALSE; /* line is empty before insert */
+#endif
+ linenr_T old_topline = 0; /* topline before insertion */
+#ifdef FEAT_DIFF
+ int old_topfill = -1;
+#endif
+ int inserted_space = FALSE; /* just inserted a space */
+ int replaceState = REPLACE;
+ int did_restart_edit = restart_edit;
+
+ /* sleep before redrawing, needed for "CTRL-O :" that results in an
+ * error message */
+ check_for_delay(TRUE);
+
+#ifdef HAVE_SANDBOX
+ /* Don't allow inserting in the sandbox. */
+ if (sandbox != 0)
+ {
+ EMSG(_(e_sandbox));
+ return FALSE;
+ }
+#endif
+
+#ifdef FEAT_INS_EXPAND
+ ins_compl_clear(); /* clear stuff for CTRL-X mode */
+#endif
+
+#ifdef FEAT_MOUSE
+ /*
+ * When doing a paste with the middle mouse button, Insstart is set to
+ * where the paste started.
+ */
+ if (where_paste_started.lnum != 0)
+ Insstart = where_paste_started;
+ else
+#endif
+ {
+ Insstart = curwin->w_cursor;
+ if (startln)
+ Insstart.col = 0;
+ }
+ Insstart_textlen = linetabsize(ml_get_curline());
+ Insstart_blank_vcol = MAXCOL;
+ if (!did_ai)
+ ai_col = 0;
+
+ if (cmdchar != NUL && restart_edit == 0)
+ {
+ ResetRedobuff();
+ AppendNumberToRedobuff(count);
+#ifdef FEAT_VREPLACE
+ if (cmdchar == 'V' || cmdchar == 'v')
+ {
+ /* "gR" or "gr" command */
+ AppendCharToRedobuff('g');
+ AppendCharToRedobuff((cmdchar == 'v') ? 'r' : 'R');
+ }
+ else
+#endif
+ {
+ AppendCharToRedobuff(cmdchar);
+ if (cmdchar == 'g') /* "gI" command */
+ AppendCharToRedobuff('I');
+ else if (cmdchar == 'r') /* "r<CR>" command */
+ count = 1; /* insert only one <CR> */
+ }
+ }
+
+ if (cmdchar == 'R')
+ {
+#ifdef FEAT_FKMAP
+ if (p_fkmap && p_ri)
+ {
+ beep_flush();
+ EMSG(farsi_text_3); /* encoded in Farsi */
+ State = INSERT;
+ }
+ else
+#endif
+ State = REPLACE;
+ }
+#ifdef FEAT_VREPLACE
+ else if (cmdchar == 'V' || cmdchar == 'v')
+ {
+ State = VREPLACE;
+ replaceState = VREPLACE;
+ orig_line_count = curbuf->b_ml.ml_line_count;
+ vr_lines_changed = 1;
+ }
+#endif
+ else
+ State = INSERT;
+
+ stop_insert_mode = FALSE;
+
+ /*
+ * Need to recompute the cursor position, it might move when the cursor is
+ * on a TAB or special character.
+ */
+ curs_columns(TRUE);
+
+ /*
+ * Enable langmap or IME, indicated by 'iminsert'.
+ * Note that IME may enabled/disabled without us noticing here, thus the
+ * 'iminsert' value may not reflect what is actually used. It is updated
+ * when hitting <Esc>.
+ */
+ if (curbuf->b_p_iminsert == B_IMODE_LMAP)
+ State |= LANGMAP;
+#ifdef USE_IM_CONTROL
+ im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);
+#endif
+
+#if defined(FEAT_MBYTE) && defined(MACOS_CLASSIC)
+ KeyScript(previous_script);
+#endif
+
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+#ifdef FEAT_CMDL_INFO
+ clear_showcmd();
+#endif
+#ifdef FEAT_RIGHTLEFT
+ /* there is no reverse replace mode */
+ revins_on = (State == INSERT && p_ri);
+ if (revins_on)
+ undisplay_dollar();
+ revins_chars = 0;
+ revins_legal = 0;
+ revins_scol = -1;
+#endif
+
+ /*
+ * Handle restarting Insert mode.
+ * Don't do this for "CTRL-O ." (repeat an insert): we get here with
+ * restart_edit non-zero, and something in the stuff buffer.
+ */
+ if (restart_edit != 0 && stuff_empty())
+ {
+#ifdef FEAT_MOUSE
+ /*
+ * After a paste we consider text typed to be part of the insert for
+ * the pasted text. You can backspace over the pasted text too.
+ */
+ if (where_paste_started.lnum)
+ arrow_used = FALSE;
+ else
+#endif
+ arrow_used = TRUE;
+ restart_edit = 0;
+
+ /*
+ * If the cursor was after the end-of-line before the CTRL-O and it is
+ * now at the end-of-line, put it after the end-of-line (this is not
+ * correct in very rare cases).
+ * Also do this if curswant is greater than the current virtual
+ * column. Eg after "^O$" or "^O80|".
+ */
+ validate_virtcol();
+ update_curswant();
+ if (((o_eol && curwin->w_cursor.lnum == o_lnum)
+ || curwin->w_curswant > curwin->w_virtcol)
+ && *(ptr = ml_get_curline() + curwin->w_cursor.col) != NUL)
+ {
+ if (ptr[1] == NUL)
+ ++curwin->w_cursor.col;
+#ifdef FEAT_MBYTE
+ else if (has_mbyte)
+ {
+ i = (*mb_ptr2len_check)(ptr);
+ if (ptr[i] == NUL)
+ curwin->w_cursor.col += i;
+ }
+#endif
+ }
+ o_eol = FALSE;
+ }
+ else
+ arrow_used = FALSE;
+
+ /* we are in insert mode now, don't need to start it anymore */
+ need_start_insertmode = FALSE;
+
+ /* Need to save the line for undo before inserting the first char. */
+ ins_need_undo = TRUE;
+
+#ifdef FEAT_MOUSE
+ where_paste_started.lnum = 0;
+#endif
+#ifdef FEAT_CINDENT
+ can_cindent = TRUE;
+#endif
+#ifdef FEAT_FOLDING
+ /* The cursor line is not in a closed fold, unless 'insertmode' is set or
+ * restarting. */
+ if (!p_im && did_restart_edit == 0)
+ foldOpenCursor();
+#endif
+
+ /*
+ * If 'showmode' is set, show the current (insert/replace/..) mode.
+ * A warning message for changing a readonly file is given here, before
+ * actually changing anything. It's put after the mode, if any.
+ */
+ i = 0;
+ if (p_smd)
+ i = showmode();
+
+ if (!p_im && did_restart_edit == 0)
+ change_warning(i + 1);
+
+#ifdef CURSOR_SHAPE
+ ui_cursor_shape(); /* may show different cursor shape */
+#endif
+#ifdef FEAT_DIGRAPHS
+ do_digraph(-1); /* clear digraphs */
+#endif
+
+/*
+ * Get the current length of the redo buffer, those characters have to be
+ * skipped if we want to get to the inserted characters.
+ */
+ ptr = get_inserted();
+ if (ptr == NULL)
+ new_insert_skip = 0;
+ else
+ {
+ new_insert_skip = (int)STRLEN(ptr);
+ vim_free(ptr);
+ }
+
+ old_indent = 0;
+
+ /*
+ * Main loop in Insert mode: repeat until Insert mode is left.
+ */
+ for (;;)
+ {
+#ifdef FEAT_RIGHTLEFT
+ if (!revins_legal)
+ revins_scol = -1; /* reset on illegal motions */
+ else
+ revins_legal = 0;
+#endif
+ if (arrow_used) /* don't repeat insert when arrow key used */
+ count = 0;
+
+ if (stop_insert_mode)
+ {
+ /* ":stopinsert" used or 'insertmode' reset */
+ count = 0;
+ goto doESCkey;
+ }
+
+ /* set curwin->w_curswant for next K_DOWN or K_UP */
+ if (!arrow_used)
+ curwin->w_set_curswant = TRUE;
+
+ /* If there is no typeahead may check for timestamps (e.g., for when a
+ * menu invoked a shell command). */
+ if (stuff_empty())
+ {
+ did_check_timestamps = FALSE;
+ if (need_check_timestamps)
+ check_timestamps(FALSE);
+ }
+
+ /*
+ * When emsg() was called msg_scroll will have been set.
+ */
+ msg_scroll = FALSE;
+
+#ifdef FEAT_GUI
+ /* When 'mousefocus' is set a mouse movement may have taken us to
+ * another window. "need_mouse_correct" may then be set because of an
+ * autocommand. */
+ if (need_mouse_correct)
+ gui_mouse_correct();
+#endif
+
+#ifdef FEAT_FOLDING
+ /* Open fold at the cursor line, according to 'foldopen'. */
+ if (fdo_flags & FDO_INSERT)
+ foldOpenCursor();
+ /* Close folds where the cursor isn't, according to 'foldclose' */
+ if (!char_avail())
+ foldCheckClose();
+#endif
+
+ /*
+ * If we inserted a character at the last position of the last line in
+ * the window, scroll the window one line up. This avoids an extra
+ * redraw.
+ * This is detected when the cursor column is smaller after inserting
+ * something.
+ * Don't do this when the topline changed already, it has
+ * already been adjusted (by insertchar() calling open_line())).
+ */
+ if (curbuf->b_mod_set
+ && curwin->w_p_wrap
+ && !did_backspace
+ && curwin->w_topline == old_topline
+#ifdef FEAT_DIFF
+ && curwin->w_topfill == old_topfill
+#endif
+ )
+ {
+ mincol = curwin->w_wcol;
+ validate_cursor_col();
+
+ if ((int)curwin->w_wcol < (int)mincol - curbuf->b_p_ts
+ && curwin->w_wrow == W_WINROW(curwin)
+ + curwin->w_height - 1 - p_so
+ && (curwin->w_cursor.lnum != curwin->w_topline
+#ifdef FEAT_DIFF
+ || curwin->w_topfill > 0
+#endif
+ ))
+ {
+#ifdef FEAT_DIFF
+ if (curwin->w_topfill > 0)
+ --curwin->w_topfill;
+ else
+#endif
+#ifdef FEAT_FOLDING
+ if (hasFolding(curwin->w_topline, NULL, &old_topline))
+ set_topline(curwin, old_topline + 1);
+ else
+#endif
+ set_topline(curwin, curwin->w_topline + 1);
+ }
+ }
+
+ /* May need to adjust w_topline to show the cursor. */
+ update_topline();
+
+ did_backspace = FALSE;
+
+ validate_cursor(); /* may set must_redraw */
+
+ /*
+ * Redraw the display when no characters are waiting.
+ * Also shows mode, ruler and positions cursor.
+ */
+ ins_redraw();
+
+#ifdef FEAT_SCROLLBIND
+ if (curwin->w_p_scb)
+ do_check_scrollbind(TRUE);
+#endif
+
+ update_curswant();
+ old_topline = curwin->w_topline;
+#ifdef FEAT_DIFF
+ old_topfill = curwin->w_topfill;
+#endif
+
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = FALSE; /* allow scrolling here */
+#endif
+
+ /*
+ * Get a character for Insert mode.
+ */
+ lastc = c; /* remember previous char for CTRL-D */
+ c = safe_vgetc();
+
+#ifdef FEAT_RIGHTLEFT
+ if (p_hkmap && KeyTyped)
+ c = hkmap(c); /* Hebrew mode mapping */
+#endif
+#ifdef FEAT_FKMAP
+ if (p_fkmap && KeyTyped)
+ c = fkmap(c); /* Farsi mode mapping */
+#endif
+
+#ifdef FEAT_INS_EXPAND
+ /* Prepare for or stop CTRL-X mode. This doesn't do completion, but
+ * it does fix up the text when finishing completion. */
+ ins_compl_prep(c);
+#endif
+
+ /* CTRL-\ CTRL-N goes to Normal mode, CTRL-\ CTRL-G goes to mode
+ * selected with 'insertmode'. */
+ if (c == Ctrl_BSL)
+ {
+ /* may need to redraw when no more chars available now */
+ ins_redraw();
+ ++no_mapping;
+ ++allow_keys;
+ c = safe_vgetc();
+ --no_mapping;
+ --allow_keys;
+ if (c != Ctrl_N && c != Ctrl_G) /* it's something else */
+ {
+ vungetc(c);
+ c = Ctrl_BSL;
+ }
+ else if (c == Ctrl_G && p_im)
+ continue;
+ else
+ {
+ count = 0;
+ goto doESCkey;
+ }
+ }
+
+#ifdef FEAT_DIGRAPHS
+ c = do_digraph(c);
+#endif
+
+#ifdef FEAT_INS_EXPAND
+ if ((c == Ctrl_V || c == Ctrl_Q) && ctrl_x_mode == CTRL_X_CMDLINE)
+ goto docomplete;
+#endif
+ if (c == Ctrl_V || c == Ctrl_Q)
+ {
+ ins_ctrl_v();
+ c = Ctrl_V; /* pretend CTRL-V is last typed character */
+ continue;
+ }
+
+#ifdef FEAT_CINDENT
+ if (cindent_on()
+# ifdef FEAT_INS_EXPAND
+ && ctrl_x_mode == 0
+# endif
+ )
+ {
+ /* A key name preceded by a bang means this key is not to be
+ * inserted. Skip ahead to the re-indenting below.
+ * A key name preceded by a star means that indenting has to be
+ * done before inserting the key. */
+ line_is_white = inindent(0);
+ if (in_cinkeys(c, '!', line_is_white))
+ goto force_cindent;
+ if (can_cindent && in_cinkeys(c, '*', line_is_white)
+ && stop_arrow() == OK)
+ do_c_expr_indent();
+ }
+#endif
+
+#ifdef FEAT_RIGHTLEFT
+ if (curwin->w_p_rl)
+ switch (c)
+ {
+ case K_LEFT: c = K_RIGHT; break;
+ case K_S_LEFT: c = K_S_RIGHT; break;
+ case K_C_LEFT: c = K_C_RIGHT; break;
+ case K_RIGHT: c = K_LEFT; break;
+ case K_S_RIGHT: c = K_S_LEFT; break;
+ case K_C_RIGHT: c = K_C_LEFT; break;
+ }
+#endif
+
+#ifdef FEAT_VISUAL
+ /*
+ * If 'keymodel' contains "startsel", may start selection. If it
+ * does, a CTRL-O and c will be stuffed, we need to get these
+ * characters.
+ */
+ if (ins_start_select(c))
+ continue;
+#endif
+
+ /*
+ * The big switch to handle a character in insert mode.
+ */
+ switch (c)
+ {
+ /* toggle insert/replace mode */
+ case K_INS:
+ case K_KINS:
+#ifdef FEAT_FKMAP
+ if (p_fkmap && p_ri)
+ {
+ beep_flush();
+ EMSG(farsi_text_3); /* encoded in Farsi */
+ break;
+ }
+#endif
+ if (State & REPLACE_FLAG)
+ State = INSERT | (State & LANGMAP);
+ else
+ State = replaceState | (State & LANGMAP);
+ AppendCharToRedobuff(K_INS);
+ showmode();
+#ifdef CURSOR_SHAPE
+ ui_cursor_shape(); /* may show different cursor shape */
+#endif
+ break;
+
+#ifdef FEAT_INS_EXPAND
+ /* Enter CTRL-X mode */
+ case Ctrl_X:
+ /* CTRL-X after CTRL-V CTRL-X doesn't do anything, so that CTRL-X
+ * CTRL-V works like CTRL-N */
+ if (ctrl_x_mode != CTRL_X_CMDLINE)
+ {
+ /* if the next ^X<> won't ADD nothing, then reset
+ * continue_status */
+ if (continue_status & CONT_N_ADDS)
+ continue_status = (continue_status | CONT_INTRPT);
+ else
+ continue_status = 0;
+ /* We're not sure which CTRL-X mode it will be yet */
+ ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
+ edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
+ edit_submode_pre = NULL;
+ showmode();
+ }
+ break;
+#endif
+
+ /* end of Select mode mapping - ignore */
+ case K_SELECT:
+ break;
+
+ /* suspend when 'insertmode' set */
+ case Ctrl_Z:
+ if (!p_im)
+ goto normalchar; /* insert CTRL-Z as normal char */
+ stuffReadbuff((char_u *)":st\r");
+ c = Ctrl_O;
+ /*FALLTHROUGH*/
+
+ /* execute one command */
+ case Ctrl_O:
+ if (echeck_abbr(Ctrl_O + ABBR_OFF))
+ break;
+ count = 0;
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ restart_edit = 'V';
+ else
+#endif
+ if (State & REPLACE_FLAG)
+ restart_edit = 'R';
+ else
+ restart_edit = 'I';
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_active())
+ o_eol = FALSE; /* cursor always keeps its column */
+ else
+#endif
+ o_eol = (gchar_cursor() == NUL);
+ goto doESCkey;
+
+#ifdef FEAT_SNIFF
+ case K_SNIFF:
+ stuffcharReadbuff(K_SNIFF);
+ goto doESCkey;
+#endif
+
+ /* Hitting the help key in insert mode is like <ESC> <Help> */
+ case K_HELP:
+ case K_F1:
+ case K_XF1:
+ stuffcharReadbuff(K_HELP);
+ if (p_im)
+ need_start_insertmode = TRUE;
+ goto doESCkey;
+
+#ifdef FEAT_NETBEANS_INTG
+ case K_F21:
+ ++no_mapping; /* don't map the next key hits */
+ i = safe_vgetc();
+ --no_mapping;
+ netbeans_keycommand(i);
+ break;
+#endif
+
+ /* an escape ends input mode */
+ case ESC:
+ if (echeck_abbr(ESC + ABBR_OFF))
+ break;
+ /*FALLTHROUGH*/
+
+ case Ctrl_C:
+#ifdef FEAT_CMDWIN
+ if (c == Ctrl_C && cmdwin_type != 0)
+ {
+ /* Close the cmdline window. */
+ cmdwin_result = K_IGNORE;
+ got_int = FALSE; /* don't stop executing autocommands et al. */
+ goto doESCkey;
+ }
+#endif
+
+#ifdef UNIX
+do_intr:
+#endif
+ /* when 'insertmode' set, and not halfway a mapping, don't leave
+ * Insert mode */
+ if (goto_im())
+ {
+ if (got_int)
+ {
+ (void)vgetc(); /* flush all buffers */
+ got_int = FALSE;
+ }
+ else
+ vim_beep();
+ break;
+ }
+doESCkey:
+ /*
+ * This is the ONLY return from edit()!
+ */
+ /* Always update o_lnum, so that a "CTRL-O ." that adds a line
+ * still puts the cursor back after the inserted text. */
+ if (o_eol && gchar_cursor() == NUL)
+ o_lnum = curwin->w_cursor.lnum;
+
+ if (ins_esc(&count, cmdchar))
+ return (c == Ctrl_O);
+ continue;
+
+ /*
+ * Insert the previously inserted text.
+ * For ^@ the trailing ESC will end the insert, unless there is an
+ * error.
+ */
+ case K_ZERO:
+ case NUL:
+ case Ctrl_A:
+ if (stuff_inserted(NUL, 1L, (c == Ctrl_A)) == FAIL
+ && c != Ctrl_A && !p_im)
+ goto doESCkey; /* quit insert mode */
+ inserted_space = FALSE;
+ break;
+
+ /* insert the contents of a register */
+ case Ctrl_R:
+ ins_reg();
+ auto_format(FALSE, TRUE);
+ inserted_space = FALSE;
+ break;
+
+ case Ctrl_G:
+ ins_ctrl_g();
+ break;
+
+ case Ctrl_HAT:
+ if (map_to_exists_mode((char_u *)"", LANGMAP))
+ {
+ /* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */
+ if (State & LANGMAP)
+ {
+ curbuf->b_p_iminsert = B_IMODE_NONE;
+ State &= ~LANGMAP;
+ }
+ else
+ {
+ curbuf->b_p_iminsert = B_IMODE_LMAP;
+ State |= LANGMAP;
+#ifdef USE_IM_CONTROL
+ im_set_active(FALSE);
+#endif
+ }
+ }
+#ifdef USE_IM_CONTROL
+ else
+ {
+ /* There are no ":lmap" mappings, toggle IM */
+ if (im_get_status())
+ {
+ curbuf->b_p_iminsert = B_IMODE_NONE;
+ im_set_active(FALSE);
+ }
+ else
+ {
+ curbuf->b_p_iminsert = B_IMODE_IM;
+ State &= ~LANGMAP;
+ im_set_active(TRUE);
+ }
+ }
+#endif
+ set_iminsert_global();
+ showmode();
+#ifdef FEAT_GUI
+ /* may show different cursor shape or color */
+ if (gui.in_use)
+ gui_update_cursor(TRUE, FALSE);
+#endif
+#if defined(FEAT_WINDOWS) && defined(FEAT_KEYMAP)
+ /* Show/unshow value of 'keymap' in status lines. */
+ status_redraw_curbuf();
+#endif
+ break;
+
+#ifdef FEAT_RIGHTLEFT
+ case Ctrl__:
+ if (!p_ari)
+ goto normalchar;
+ ins_ctrl_();
+ break;
+#endif
+
+ /* Make indent one shiftwidth smaller. */
+ case Ctrl_D:
+#if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
+ if (ctrl_x_mode == CTRL_X_PATH_DEFINES)
+ goto docomplete;
+#endif
+ /* FALLTHROUGH */
+
+ /* Make indent one shiftwidth greater. */
+ case Ctrl_T:
+# ifdef FEAT_INS_EXPAND
+ if (c == Ctrl_T && ctrl_x_mode == CTRL_X_THESAURUS)
+ {
+ if (*curbuf->b_p_tsr == NUL && *p_tsr == NUL)
+ {
+ ctrl_x_mode = 0;
+ msg_attr((char_u *)_("'thesaurus' option is empty"),
+ hl_attr(HLF_E));
+ if (emsg_silent == 0)
+ {
+ vim_beep();
+ setcursor();
+ out_flush();
+ ui_delay(2000L, FALSE);
+ }
+ break;
+ }
+ goto docomplete;
+ }
+# endif
+ ins_shift(c, lastc);
+ auto_format(FALSE, TRUE);
+ inserted_space = FALSE;
+ break;
+
+ /* delete character under the cursor */
+ case K_DEL:
+ case K_KDEL:
+ ins_del();
+ auto_format(FALSE, TRUE);
+ break;
+
+ /* delete character before the cursor */
+ case K_BS:
+ case Ctrl_H:
+ did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space);
+ auto_format(FALSE, TRUE);
+ break;
+
+ /* delete word before the cursor */
+ case Ctrl_W:
+ did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space);
+ auto_format(FALSE, TRUE);
+ break;
+
+ /* delete all inserted text in current line */
+ case Ctrl_U:
+ did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space);
+ auto_format(FALSE, TRUE);
+ inserted_space = FALSE;
+ break;
+
+#ifdef FEAT_MOUSE
+ case K_LEFTMOUSE:
+ case K_LEFTMOUSE_NM:
+ case K_LEFTDRAG:
+ case K_LEFTRELEASE:
+ case K_LEFTRELEASE_NM:
+ case K_MIDDLEMOUSE:
+ case K_MIDDLEDRAG:
+ case K_MIDDLERELEASE:
+ case K_RIGHTMOUSE:
+ case K_RIGHTDRAG:
+ case K_RIGHTRELEASE:
+ case K_X1MOUSE:
+ case K_X1DRAG:
+ case K_X1RELEASE:
+ case K_X2MOUSE:
+ case K_X2DRAG:
+ case K_X2RELEASE:
+ ins_mouse(c);
+ break;
+
+ /* Default action for scroll wheel up: scroll up */
+ case K_MOUSEDOWN:
+ ins_mousescroll(FALSE);
+ break;
+
+ /* Default action for scroll wheel down: scroll down */
+ case K_MOUSEUP:
+ ins_mousescroll(TRUE);
+ break;
+#endif
+
+ case K_IGNORE:
+ break;
+
+#ifdef FEAT_GUI
+ case K_VER_SCROLLBAR:
+ ins_scroll();
+ break;
+
+ case K_HOR_SCROLLBAR:
+ ins_horscroll();
+ break;
+#endif
+
+ case K_HOME:
+ case K_KHOME:
+ case K_XHOME:
+ case K_S_HOME:
+ case K_C_HOME:
+ ins_home(c);
+ break;
+
+ case K_END:
+ case K_KEND:
+ case K_XEND:
+ case K_S_END:
+ case K_C_END:
+ ins_end(c);
+ break;
+
+ case K_LEFT:
+ ins_left();
+ break;
+
+ case K_S_LEFT:
+ case K_C_LEFT:
+ ins_s_left();
+ break;
+
+ case K_RIGHT:
+ ins_right();
+ break;
+
+ case K_S_RIGHT:
+ case K_C_RIGHT:
+ ins_s_right();
+ break;
+
+ case K_UP:
+ ins_up(FALSE);
+ break;
+
+ case K_S_UP:
+ case K_PAGEUP:
+ case K_KPAGEUP:
+ ins_pageup();
+ break;
+
+ case K_DOWN:
+ ins_down(FALSE);
+ break;
+
+ case K_S_DOWN:
+ case K_PAGEDOWN:
+ case K_KPAGEDOWN:
+ ins_pagedown();
+ break;
+
+#ifdef FEAT_DND
+ case K_DROP:
+ ins_drop();
+ break;
+#endif
+
+ /* When <S-Tab> isn't mapped, use it like a normal TAB */
+ case K_S_TAB:
+ c = TAB;
+ /* FALLTHROUGH */
+
+ /* TAB or Complete patterns along path */
+ case TAB:
+#if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
+ if (ctrl_x_mode == CTRL_X_PATH_PATTERNS)
+ goto docomplete;
+#endif
+ inserted_space = FALSE;
+ if (ins_tab())
+ goto normalchar; /* insert TAB as a normal char */
+ auto_format(FALSE, TRUE);
+ break;
+
+ case K_KENTER:
+ c = CAR;
+ /* FALLTHROUGH */
+ case CAR:
+ case NL:
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ /* In a quickfix window a <CR> jumps to the error under the
+ * cursor. */
+ if (bt_quickfix(curbuf) && c == CAR)
+ {
+ do_cmdline_cmd((char_u *)".cc");
+ break;
+ }
+#endif
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ {
+ /* Execute the command in the cmdline window. */
+ cmdwin_result = CAR;
+ goto doESCkey;
+ }
+#endif
+ if (ins_eol(c) && !p_im)
+ goto doESCkey; /* out of memory */
+ auto_format(FALSE, FALSE);
+ inserted_space = FALSE;
+ break;
+
+#if defined(FEAT_DIGRAPHS) || defined (FEAT_INS_EXPAND)
+ case Ctrl_K:
+# ifdef FEAT_INS_EXPAND
+ if (ctrl_x_mode == CTRL_X_DICTIONARY)
+ {
+ if (*curbuf->b_p_dict == NUL && *p_dict == NUL)
+ {
+ ctrl_x_mode = 0;
+ msg_attr((char_u *)_("'dictionary' option is empty"),
+ hl_attr(HLF_E));
+ if (emsg_silent == 0)
+ {
+ vim_beep();
+ setcursor();
+ out_flush();
+ ui_delay(2000L, FALSE);
+ }
+ break;
+ }
+ goto docomplete;
+ }
+# endif
+# ifdef FEAT_DIGRAPHS
+ c = ins_digraph();
+ if (c == NUL)
+ break;
+# endif
+ goto normalchar;
+#endif /* FEAT_DIGRAPHS || FEAT_INS_EXPAND */
+
+#ifdef FEAT_INS_EXPAND
+ case Ctrl_RSB: /* Tag name completion after ^X */
+ if (ctrl_x_mode != CTRL_X_TAGS)
+ goto normalchar;
+ goto docomplete;
+
+ case Ctrl_F: /* File name completion after ^X */
+ if (ctrl_x_mode != CTRL_X_FILES)
+ goto normalchar;
+ goto docomplete;
+#endif
+
+ case Ctrl_L: /* Whole line completion after ^X */
+#ifdef FEAT_INS_EXPAND
+ if (ctrl_x_mode != CTRL_X_WHOLE_LINE)
+#endif
+ {
+ /* CTRL-L with 'insertmode' set: Leave Insert mode */
+ if (p_im)
+ {
+ if (echeck_abbr(Ctrl_L + ABBR_OFF))
+ break;
+ goto doESCkey;
+ }
+ goto normalchar;
+ }
+#ifdef FEAT_INS_EXPAND
+ /* FALLTHROUGH */
+
+ /* Do previous/next pattern completion */
+ case Ctrl_P:
+ case Ctrl_N:
+ /* if 'complete' is empty then plain ^P is no longer special,
+ * but it is under other ^X modes */
+ if (*curbuf->b_p_cpt == NUL
+ && ctrl_x_mode != 0
+ && !(continue_status & CONT_LOCAL))
+ goto normalchar;
+
+docomplete:
+ if (ins_complete(c) == FAIL)
+ continue_status = 0;
+ break;
+#endif /* FEAT_INS_EXPAND */
+
+ case Ctrl_Y: /* copy from previous line or scroll down */
+ case Ctrl_E: /* copy from next line or scroll up */
+#ifdef FEAT_INS_EXPAND
+ if (ctrl_x_mode == CTRL_X_SCROLL)
+ {
+ if (c == Ctrl_Y)
+ scrolldown_clamp();
+ else
+ scrollup_clamp();
+ redraw_later(VALID);
+ }
+ else
+#endif
+ {
+ c = ins_copychar(curwin->w_cursor.lnum
+ + (c == Ctrl_Y ? -1 : 1));
+ if (c != NUL)
+ {
+ long tw_save;
+
+ /* The character must be taken literally, insert like it
+ * was typed after a CTRL-V, and pretend 'textwidth'
+ * wasn't set. Digits, 'o' and 'x' are special after a
+ * CTRL-V, don't use it for these. */
+ if (c < 256 && !isalnum(c))
+ AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */
+ tw_save = curbuf->b_p_tw;
+ curbuf->b_p_tw = -1;
+ insert_special(c, TRUE, FALSE);
+ curbuf->b_p_tw = tw_save;
+#ifdef FEAT_RIGHTLEFT
+ revins_chars++;
+ revins_legal++;
+#endif
+ c = Ctrl_V; /* pretend CTRL-V is last character */
+ auto_format(FALSE, TRUE);
+ }
+ }
+ break;
+
+ default:
+#ifdef UNIX
+ if (c == intr_char) /* special interrupt char */
+ goto do_intr;
+#endif
+
+ /*
+ * Insert a nomal character.
+ */
+normalchar:
+#ifdef FEAT_SMARTINDENT
+ /* Try to perform smart-indenting. */
+ ins_try_si(c);
+#endif
+
+ if (c == ' ')
+ {
+ inserted_space = TRUE;
+#ifdef FEAT_CINDENT
+ if (inindent(0))
+ can_cindent = FALSE;
+#endif
+ if (Insstart_blank_vcol == MAXCOL
+ && curwin->w_cursor.lnum == Insstart.lnum)
+ Insstart_blank_vcol = get_nolist_virtcol();
+ }
+
+ if (vim_iswordc(c) || !echeck_abbr(
+#ifdef FEAT_MBYTE
+ /* Add ABBR_OFF for characters above 0x100, this is
+ * what check_abbr() expects. */
+ (has_mbyte && c >= 0x100) ? (c + ABBR_OFF) :
+#endif
+ c))
+ {
+ insert_special(c, FALSE, FALSE);
+#ifdef FEAT_RIGHTLEFT
+ revins_legal++;
+ revins_chars++;
+#endif
+ }
+
+ auto_format(FALSE, TRUE);
+
+#ifdef FEAT_FOLDING
+ /* When inserting a character the cursor line must never be in a
+ * closed fold. */
+ foldOpenCursor();
+#endif
+ break;
+ } /* end of switch (c) */
+
+ /* If the cursor was moved we didn't just insert a space */
+ if (arrow_used)
+ inserted_space = FALSE;
+
+#ifdef FEAT_CINDENT
+ if (can_cindent && cindent_on()
+# ifdef FEAT_INS_EXPAND
+ && ctrl_x_mode == 0
+# endif
+ )
+ {
+force_cindent:
+ /*
+ * Indent now if a key was typed that is in 'cinkeys'.
+ */
+ if (in_cinkeys(c, ' ', line_is_white))
+ {
+ if (stop_arrow() == OK)
+ /* re-indent the current line */
+ do_c_expr_indent();
+ }
+ }
+#endif /* FEAT_CINDENT */
+
+ } /* for (;;) */
+ /* NOTREACHED */
+}
+
+/*
+ * Redraw for Insert mode.
+ * This is postponed until getting the next character to make '$' in the 'cpo'
+ * option work correctly.
+ * Only redraw when there are no characters available. This speeds up
+ * inserting sequences of characters (e.g., for CTRL-R).
+ */
+ static void
+ins_redraw()
+{
+ if (!char_avail())
+ {
+ if (must_redraw)
+ update_screen(0);
+ else if (clear_cmdline || redraw_cmdline)
+ showmode(); /* clear cmdline and show mode */
+ showruler(FALSE);
+ setcursor();
+ emsg_on_display = FALSE; /* may remove error message now */
+ }
+}
+
+/*
+ * Handle a CTRL-V or CTRL-Q typed in Insert mode.
+ */
+ static void
+ins_ctrl_v()
+{
+ int c;
+
+ /* may need to redraw when no more chars available now */
+ ins_redraw();
+
+ if (redrawing() && !char_avail())
+ edit_putchar('^', TRUE);
+ AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */
+
+#ifdef FEAT_CMDL_INFO
+ add_to_showcmd_c(Ctrl_V);
+#endif
+
+ c = get_literal();
+#ifdef FEAT_CMDL_INFO
+ clear_showcmd();
+#endif
+ insert_special(c, FALSE, TRUE);
+#ifdef FEAT_RIGHTLEFT
+ revins_chars++;
+ revins_legal++;
+#endif
+}
+
+/*
+ * Put a character directly onto the screen. It's not stored in a buffer.
+ * Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
+ */
+static int pc_status;
+#define PC_STATUS_UNSET 0 /* pc_bytes was not set */
+#define PC_STATUS_RIGHT 1 /* right halve of double-wide char */
+#define PC_STATUS_LEFT 2 /* left halve of double-wide char */
+#define PC_STATUS_SET 3 /* pc_bytes was filled */
+#ifdef FEAT_MBYTE
+static char_u pc_bytes[MB_MAXBYTES + 1]; /* saved bytes */
+#else
+static char_u pc_bytes[2]; /* saved bytes */
+#endif
+static int pc_attr;
+static int pc_row;
+static int pc_col;
+
+ void
+edit_putchar(c, highlight)
+ int c;
+ int highlight;
+{
+ int attr;
+
+ if (ScreenLines != NULL)
+ {
+ update_topline(); /* just in case w_topline isn't valid */
+ validate_cursor();
+ if (highlight)
+ attr = hl_attr(HLF_8);
+ else
+ attr = 0;
+ pc_row = W_WINROW(curwin) + curwin->w_wrow;
+ pc_col = W_WINCOL(curwin);
+#if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE)
+ pc_status = PC_STATUS_UNSET;
+#endif
+#ifdef FEAT_RIGHTLEFT
+ if (curwin->w_p_rl)
+ {
+ pc_col += W_WIDTH(curwin) - 1 - curwin->w_wcol;
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int fix_col = mb_fix_col(pc_col, pc_row);
+
+ if (fix_col != pc_col)
+ {
+ screen_putchar(' ', pc_row, fix_col, attr);
+ --curwin->w_wcol;
+ pc_status = PC_STATUS_RIGHT;
+ }
+ }
+# endif
+ }
+ else
+#endif
+ {
+ pc_col += curwin->w_wcol;
+#ifdef FEAT_MBYTE
+ if (mb_lefthalve(pc_row, pc_col))
+ pc_status = PC_STATUS_LEFT;
+#endif
+ }
+
+ /* save the character to be able to put it back */
+#if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE)
+ if (pc_status == PC_STATUS_UNSET)
+#endif
+ {
+ screen_getbytes(pc_row, pc_col, pc_bytes, &pc_attr);
+ pc_status = PC_STATUS_SET;
+ }
+ screen_putchar(c, pc_row, pc_col, attr);
+ }
+}
+
+/*
+ * Undo the previous edit_putchar().
+ */
+ void
+edit_unputchar()
+{
+ if (pc_status != PC_STATUS_UNSET && pc_row >= msg_scrolled)
+ {
+#if defined(FEAT_MBYTE)
+ if (pc_status == PC_STATUS_RIGHT)
+ ++curwin->w_wcol;
+ if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT)
+ redrawWinline(curwin->w_cursor.lnum, FALSE);
+ else
+#endif
+ screen_puts(pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr);
+ }
+}
+
+/*
+ * Called when p_dollar is set: display a '$' at the end of the changed text
+ * Only works when cursor is in the line that changes.
+ */
+ void
+display_dollar(col)
+ colnr_T col;
+{
+ colnr_T save_col;
+
+ if (!redrawing())
+ return;
+
+ cursor_off();
+ save_col = curwin->w_cursor.col;
+ curwin->w_cursor.col = col;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ char_u *p;
+
+ /* If on the last byte of a multi-byte move to the first byte. */
+ p = ml_get_curline();
+ curwin->w_cursor.col -= (*mb_head_off)(p, p + col);
+ }
+#endif
+ curs_columns(FALSE); /* recompute w_wrow and w_wcol */
+ if (curwin->w_wcol < W_WIDTH(curwin))
+ {
+ edit_putchar('$', FALSE);
+ dollar_vcol = curwin->w_virtcol;
+ }
+ curwin->w_cursor.col = save_col;
+}
+
+/*
+ * Call this function before moving the cursor from the normal insert position
+ * in insert mode.
+ */
+ static void
+undisplay_dollar()
+{
+ if (dollar_vcol)
+ {
+ dollar_vcol = 0;
+ redrawWinline(curwin->w_cursor.lnum, FALSE);
+ }
+}
+
+/*
+ * Insert an indent (for <Tab> or CTRL-T) or delete an indent (for CTRL-D).
+ * Keep the cursor on the same character.
+ * type == INDENT_INC increase indent (for CTRL-T or <Tab>)
+ * type == INDENT_DEC decrease indent (for CTRL-D)
+ * type == INDENT_SET set indent to "amount"
+ * if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec).
+ */
+ void
+change_indent(type, amount, round, replaced)
+ int type;
+ int amount;
+ int round;
+ int replaced; /* replaced character, put on replace stack */
+{
+ int vcol;
+ int last_vcol;
+ int insstart_less; /* reduction for Insstart.col */
+ int new_cursor_col;
+ int i;
+ char_u *ptr;
+ int save_p_list;
+ int start_col;
+ colnr_T vc;
+#ifdef FEAT_VREPLACE
+ colnr_T orig_col = 0; /* init for GCC */
+ char_u *new_line, *orig_line = NULL; /* init for GCC */
+
+ /* VREPLACE mode needs to know what the line was like before changing */
+ if (State & VREPLACE_FLAG)
+ {
+ orig_line = vim_strsave(ml_get_curline()); /* Deal with NULL below */
+ orig_col = curwin->w_cursor.col;
+ }
+#endif
+
+ /* for the following tricks we don't want list mode */
+ save_p_list = curwin->w_p_list;
+ curwin->w_p_list = FALSE;
+ vc = getvcol_nolist(&curwin->w_cursor);
+ vcol = vc;
+
+ /*
+ * For Replace mode we need to fix the replace stack later, which is only
+ * possible when the cursor is in the indent. Remember the number of
+ * characters before the cursor if it's possible.
+ */
+ start_col = curwin->w_cursor.col;
+
+ /* determine offset from first non-blank */
+ new_cursor_col = curwin->w_cursor.col;
+ beginline(BL_WHITE);
+ new_cursor_col -= curwin->w_cursor.col;
+
+ insstart_less = curwin->w_cursor.col;
+
+ /*
+ * If the cursor is in the indent, compute how many screen columns the
+ * cursor is to the left of the first non-blank.
+ */
+ if (new_cursor_col < 0)
+ vcol = get_indent() - vcol;
+
+ if (new_cursor_col > 0) /* can't fix replace stack */
+ start_col = -1;
+
+ /*
+ * Set the new indent. The cursor will be put on the first non-blank.
+ */
+ if (type == INDENT_SET)
+ (void)set_indent(amount, SIN_CHANGED);
+ else
+ {
+#ifdef FEAT_VREPLACE
+ int save_State = State;
+
+ /* Avoid being called recursively. */
+ if (State & VREPLACE_FLAG)
+ State = INSERT;
+#endif
+ shift_line(type == INDENT_DEC, round, 1);
+#ifdef FEAT_VREPLACE
+ State = save_State;
+#endif
+ }
+ insstart_less -= curwin->w_cursor.col;
+
+ /*
+ * Try to put cursor on same character.
+ * If the cursor is at or after the first non-blank in the line,
+ * compute the cursor column relative to the column of the first
+ * non-blank character.
+ * If we are not in insert mode, leave the cursor on the first non-blank.
+ * If the cursor is before the first non-blank, position it relative
+ * to the first non-blank, counted in screen columns.
+ */
+ if (new_cursor_col >= 0)
+ {
+ /*
+ * When changing the indent while the cursor is touching it, reset
+ * Insstart_col to 0.
+ */
+ if (new_cursor_col == 0)
+ insstart_less = MAXCOL;
+ new_cursor_col += curwin->w_cursor.col;
+ }
+ else if (!(State & INSERT))
+ new_cursor_col = curwin->w_cursor.col;
+ else
+ {
+ /*
+ * Compute the screen column where the cursor should be.
+ */
+ vcol = get_indent() - vcol;
+ curwin->w_virtcol = (vcol < 0) ? 0 : vcol;
+
+ /*
+ * Advance the cursor until we reach the right screen column.
+ */
+ vcol = last_vcol = 0;
+ new_cursor_col = -1;
+ ptr = ml_get_curline();
+ while (vcol <= (int)curwin->w_virtcol)
+ {
+ last_vcol = vcol;
+#ifdef FEAT_MBYTE
+ if (has_mbyte && new_cursor_col >= 0)
+ new_cursor_col += (*mb_ptr2len_check)(ptr + new_cursor_col);
+ else
+#endif
+ ++new_cursor_col;
+ vcol += lbr_chartabsize(ptr + new_cursor_col, (colnr_T)vcol);
+ }
+ vcol = last_vcol;
+
+ /*
+ * May need to insert spaces to be able to position the cursor on
+ * the right screen column.
+ */
+ if (vcol != (int)curwin->w_virtcol)
+ {
+ curwin->w_cursor.col = new_cursor_col;
+ i = (int)curwin->w_virtcol - vcol;
+ ptr = alloc(i + 1);
+ if (ptr != NULL)
+ {
+ new_cursor_col += i;
+ ptr[i] = NUL;
+ while (--i >= 0)
+ ptr[i] = ' ';
+ ins_str(ptr);
+ vim_free(ptr);
+ }
+ }
+
+ /*
+ * When changing the indent while the cursor is in it, reset
+ * Insstart_col to 0.
+ */
+ insstart_less = MAXCOL;
+ }
+
+ curwin->w_p_list = save_p_list;
+
+ if (new_cursor_col <= 0)
+ curwin->w_cursor.col = 0;
+ else
+ curwin->w_cursor.col = new_cursor_col;
+ curwin->w_set_curswant = TRUE;
+ changed_cline_bef_curs();
+
+ /*
+ * May have to adjust the start of the insert.
+ */
+ if (State & INSERT)
+ {
+ if (curwin->w_cursor.lnum == Insstart.lnum && Insstart.col != 0)
+ {
+ if ((int)Insstart.col <= insstart_less)
+ Insstart.col = 0;
+ else
+ Insstart.col -= insstart_less;
+ }
+ if ((int)ai_col <= insstart_less)
+ ai_col = 0;
+ else
+ ai_col -= insstart_less;
+ }
+
+ /*
+ * For REPLACE mode, may have to fix the replace stack, if it's possible.
+ * If the number of characters before the cursor decreased, need to pop a
+ * few characters from the replace stack.
+ * If the number of characters before the cursor increased, need to push a
+ * few NULs onto the replace stack.
+ */
+ if (REPLACE_NORMAL(State) && start_col >= 0)
+ {
+ while (start_col > (int)curwin->w_cursor.col)
+ {
+ replace_join(0); /* remove a NUL from the replace stack */
+ --start_col;
+ }
+ while (start_col < (int)curwin->w_cursor.col || replaced)
+ {
+ replace_push(NUL);
+ if (replaced)
+ {
+ replace_push(replaced);
+ replaced = NUL;
+ }
+ ++start_col;
+ }
+ }
+
+#ifdef FEAT_VREPLACE
+ /*
+ * For VREPLACE mode, we also have to fix the replace stack. In this case
+ * it is always possible because we backspace over the whole line and then
+ * put it back again the way we wanted it.
+ */
+ if (State & VREPLACE_FLAG)
+ {
+ /* If orig_line didn't allocate, just return. At least we did the job,
+ * even if you can't backspace. */
+ if (orig_line == NULL)
+ return;
+
+ /* Save new line */
+ new_line = vim_strsave(ml_get_curline());
+ if (new_line == NULL)
+ return;
+
+ /* We only put back the new line up to the cursor */
+ new_line[curwin->w_cursor.col] = NUL;
+
+ /* Put back original line */
+ ml_replace(curwin->w_cursor.lnum, orig_line, FALSE);
+ curwin->w_cursor.col = orig_col;
+
+ /* Backspace from cursor to start of line */
+ backspace_until_column(0);
+
+ /* Insert new stuff into line again */
+ ins_bytes(new_line);
+
+ vim_free(new_line);
+ }
+#endif
+}
+
+/*
+ * Truncate the space at the end of a line. This is to be used only in an
+ * insert mode. It handles fixing the replace stack for REPLACE and VREPLACE
+ * modes.
+ */
+ void
+truncate_spaces(line)
+ char_u *line;
+{
+ int i;
+
+ /* find start of trailing white space */
+ for (i = (int)STRLEN(line) - 1; i >= 0 && vim_iswhite(line[i]); i--)
+ {
+ if (State & REPLACE_FLAG)
+ replace_join(0); /* remove a NUL from the replace stack */
+ }
+ line[i + 1] = NUL;
+}
+
+#if defined(FEAT_VREPLACE) || defined(FEAT_INS_EXPAND) \
+ || defined(FEAT_COMMENTS) || defined(PROTO)
+/*
+ * Backspace the cursor until the given column. Handles REPLACE and VREPLACE
+ * modes correctly. May also be used when not in insert mode at all.
+ */
+ void
+backspace_until_column(col)
+ int col;
+{
+ while ((int)curwin->w_cursor.col > col)
+ {
+ curwin->w_cursor.col--;
+ if (State & REPLACE_FLAG)
+ replace_do_bs();
+ else
+ (void)del_char(FALSE);
+ }
+}
+#endif
+
+#if defined(FEAT_INS_EXPAND) || defined(PROTO)
+/*
+ * Is the character 'c' a valid key to go to or keep us in CTRL-X mode?
+ * This depends on the current mode.
+ */
+ int
+vim_is_ctrl_x_key(c)
+ int c;
+{
+ /* Always allow ^R - let it's results then be checked */
+ if (c == Ctrl_R)
+ return TRUE;
+
+ switch (ctrl_x_mode)
+ {
+ case 0: /* Not in any CTRL-X mode */
+ return (c == Ctrl_N || c == Ctrl_P || c == Ctrl_X);
+ case CTRL_X_NOT_DEFINED_YET:
+ return ( c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E
+ || c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB
+ || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P
+ || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V
+ || c == Ctrl_Q);
+ case CTRL_X_SCROLL:
+ return (c == Ctrl_Y || c == Ctrl_E);
+ case CTRL_X_WHOLE_LINE:
+ return (c == Ctrl_L || c == Ctrl_P || c == Ctrl_N);
+ case CTRL_X_FILES:
+ return (c == Ctrl_F || c == Ctrl_P || c == Ctrl_N);
+ case CTRL_X_DICTIONARY:
+ return (c == Ctrl_K || c == Ctrl_P || c == Ctrl_N);
+ case CTRL_X_THESAURUS:
+ return (c == Ctrl_T || c == Ctrl_P || c == Ctrl_N);
+ case CTRL_X_TAGS:
+ return (c == Ctrl_RSB || c == Ctrl_P || c == Ctrl_N);
+#ifdef FEAT_FIND_ID
+ case CTRL_X_PATH_PATTERNS:
+ return (c == Ctrl_P || c == Ctrl_N);
+ case CTRL_X_PATH_DEFINES:
+ return (c == Ctrl_D || c == Ctrl_P || c == Ctrl_N);
+#endif
+ case CTRL_X_CMDLINE:
+ return (c == Ctrl_V || c == Ctrl_Q || c == Ctrl_P || c == Ctrl_N
+ || c == Ctrl_X);
+ }
+ EMSG(_(e_internal));
+ return FALSE;
+}
+
+/*
+ * This is like ins_compl_add(), but if ic and inf are set, then the
+ * case of the originally typed text is used, and the case of the completed
+ * text is infered, ie this tries to work out what case you probably wanted
+ * the rest of the word to be in -- webb
+ */
+ int
+ins_compl_add_infercase(str, len, fname, dir, reuse)
+ char_u *str;
+ int len;
+ char_u *fname;
+ int dir;
+ int reuse;
+{
+ int has_lower = FALSE;
+ int was_letter = FALSE;
+ int idx;
+
+ if (p_ic && curbuf->b_p_inf && len < IOSIZE)
+ {
+ /* Infer case of completed part -- webb */
+ /* Use IObuff, str would change text in buffer! */
+ STRNCPY(IObuff, str, len);
+ IObuff[len] = NUL;
+
+ /* Rule 1: Were any chars converted to lower? */
+ for (idx = 0; idx < completion_length; ++idx)
+ {
+ if (islower(original_text[idx]))
+ {
+ has_lower = TRUE;
+ if (isupper(IObuff[idx]))
+ {
+ /* Rule 1 is satisfied */
+ for (idx = completion_length; idx < len; ++idx)
+ IObuff[idx] = TOLOWER_LOC(IObuff[idx]);
+ break;
+ }
+ }
+ }
+
+ /*
+ * Rule 2: No lower case, 2nd consecutive letter converted to
+ * upper case.
+ */
+ if (!has_lower)
+ {
+ for (idx = 0; idx < completion_length; ++idx)
+ {
+ if (was_letter && isupper(original_text[idx])
+ && islower(IObuff[idx]))
+ {
+ /* Rule 2 is satisfied */
+ for (idx = completion_length; idx < len; ++idx)
+ IObuff[idx] = TOUPPER_LOC(IObuff[idx]);
+ break;
+ }
+ was_letter = isalpha(original_text[idx]);
+ }
+ }
+
+ /* Copy the original case of the part we typed */
+ STRNCPY(IObuff, original_text, completion_length);
+
+ return ins_compl_add(IObuff, len, fname, dir, reuse);
+ }
+ return ins_compl_add(str, len, fname, dir, reuse);
+}
+
+/*
+ * Add a match to the list of matches.
+ * If the given string is already in the list of completions, then return
+ * FAIL, otherwise add it to the list and return OK. If there is an error,
+ * maybe because alloc returns NULL, then RET_ERROR is returned -- webb.
+ */
+ static int
+ins_compl_add(str, len, fname, dir, reuse)
+ char_u *str;
+ int len;
+ char_u *fname;
+ int dir;
+ int reuse;
+{
+ struct Completion *match;
+
+ ui_breakcheck();
+ if (got_int)
+ return RET_ERROR;
+ if (len < 0)
+ len = (int)STRLEN(str);
+
+ /*
+ * If the same match is already present, don't add it.
+ */
+ if (first_match != NULL)
+ {
+ match = first_match;
+ do
+ {
+ if ( !(match->original & ORIGINAL_TEXT)
+ && STRNCMP(match->str, str, (size_t)len) == 0
+ && match->str[len] == NUL)
+ return FAIL;
+ match = match->next;
+ } while (match != NULL && match != first_match);
+ }
+
+ /*
+ * Allocate a new match structure.
+ * Copy the values to the new match structure.
+ */
+ match = (struct Completion *)alloc((unsigned)sizeof(struct Completion));
+ if (match == NULL)
+ return RET_ERROR;
+ match->number = -1;
+ if (reuse & ORIGINAL_TEXT)
+ {
+ match->number = 0;
+ match->str = original_text;
+ }
+ else if ((match->str = vim_strnsave(str, len)) == NULL)
+ {
+ vim_free(match);
+ return RET_ERROR;
+ }
+ /* match-fname is:
+ * - curr_match->fname if it is a string equal to fname.
+ * - a copy of fname, FREE_FNAME is set to free later THE allocated mem.
+ * - NULL otherwise. --Acevedo */
+ if (fname && curr_match && curr_match->fname
+ && STRCMP(fname, curr_match->fname) == 0)
+ match->fname = curr_match->fname;
+ else if (fname && (match->fname = vim_strsave(fname)) != NULL)
+ reuse |= FREE_FNAME;
+ else
+ match->fname = NULL;
+ match->original = reuse;
+
+ /*
+ * Link the new match structure in the list of matches.
+ */
+ if (first_match == NULL)
+ match->next = match->prev = NULL;
+ else if (dir == FORWARD)
+ {
+ match->next = curr_match->next;
+ match->prev = curr_match;
+ }
+ else /* BACKWARD */
+ {
+ match->next = curr_match;
+ match->prev = curr_match->prev;
+ }
+ if (match->next)
+ match->next->prev = match;
+ if (match->prev)
+ match->prev->next = match;
+ else /* if there's nothing before, it is the first match */
+ first_match = match;
+ curr_match = match;
+
+ return OK;
+}
+
+/*
+ * Add an array of matches to the list of matches.
+ * Frees matches[].
+ */
+ static void
+ins_compl_add_matches(num_matches, matches, dir)
+ int num_matches;
+ char_u **matches;
+ int dir;
+{
+ int i;
+ int add_r = OK;
+ int ldir = dir;
+
+ for (i = 0; i < num_matches && add_r != RET_ERROR; i++)
+ if ((add_r = ins_compl_add(matches[i], -1, NULL, ldir, 0)) == OK)
+ /* if dir was BACKWARD then honor it just once */
+ ldir = FORWARD;
+ FreeWild(num_matches, matches);
+}
+
+/* Make the completion list cyclic.
+ * Return the number of matches (excluding the original).
+ */
+ static int
+ins_compl_make_cyclic()
+{
+ struct Completion *match;
+ int count = 0;
+
+ if (first_match != NULL)
+ {
+ /*
+ * Find the end of the list.
+ */
+ match = first_match;
+ /* there's always an entry for the original_text, it doesn't count. */
+ while (match->next != NULL && match->next != first_match)
+ {
+ match = match->next;
+ ++count;
+ }
+ match->next = first_match;
+ first_match->prev = match;
+ }
+ return count;
+}
+
+#define DICT_FIRST (1) /* use just first element in "dict" */
+#define DICT_EXACT (2) /* "dict" is the exact name of a file */
+/*
+ * Add any identifiers that match the given pattern to the list of
+ * completions.
+ */
+ static void
+ins_compl_dictionaries(dict, pat, dir, flags, thesaurus)
+ char_u *dict;
+ char_u *pat;
+ int dir;
+ int flags;
+ int thesaurus;
+{
+ char_u *ptr;
+ char_u *buf;
+ FILE *fp;
+ regmatch_T regmatch;
+ int add_r;
+ char_u **files;
+ int count;
+ int i;
+ int save_p_scs;
+
+ buf = alloc(LSIZE);
+ /* If 'infercase' is set, don't use 'smartcase' here */
+ save_p_scs = p_scs;
+ if (curbuf->b_p_inf)
+ p_scs = FALSE;
+ regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
+ /* ignore case depends on 'ignorecase', 'smartcase' and "pat" */
+ regmatch.rm_ic = ignorecase(pat);
+ while (buf != NULL && regmatch.regprog != NULL && *dict != NUL
+ && !got_int && !completion_interrupted)
+ {
+ /* copy one dictionary file name into buf */
+ if (flags == DICT_EXACT)
+ {
+ count = 1;
+ files = &dict;
+ }
+ else
+ {
+ /* Expand wildcards in the dictionary name, but do not allow
+ * backticks (for security, the 'dict' option may have been set in
+ * a modeline). */
+ copy_option_part(&dict, buf, LSIZE, ",");
+ if (vim_strchr(buf, '`') != NULL
+ || expand_wildcards(1, &buf, &count, &files,
+ EW_FILE|EW_SILENT) != OK)
+ count = 0;
+ }
+
+ for (i = 0; i < count && !got_int && !completion_interrupted; i++)
+ {
+ fp = mch_fopen((char *)files[i], "r"); /* open dictionary file */
+ if (flags != DICT_EXACT)
+ {
+ sprintf((char*)IObuff, _("Scanning dictionary: %s"),
+ (char *)files[i]);
+ msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
+ }
+
+ if (fp != NULL)
+ {
+ /*
+ * Read dictionary file line by line.
+ * Check each line for a match.
+ */
+ while (!got_int && !completion_interrupted
+ && !vim_fgets(buf, LSIZE, fp))
+ {
+ ptr = buf;
+ while (vim_regexec(&regmatch, buf, (colnr_T)(ptr - buf)))
+ {
+ ptr = regmatch.startp[0];
+ ptr = find_word_end(ptr);
+ add_r = ins_compl_add_infercase(regmatch.startp[0],
+ (int)(ptr - regmatch.startp[0]),
+ files[i], dir, 0);
+ if (thesaurus)
+ {
+ char_u *wstart;
+
+ /*
+ * Add the other matches on the line
+ */
+ while (!got_int)
+ {
+ /* Find start of the next word. Skip white
+ * space and punctuation. */
+ ptr = find_word_start(ptr);
+ if (*ptr == NUL || *ptr == NL)
+ break;
+ wstart = ptr;
+
+ /* Find end of the word and add it. */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ /* Japanese words may have characters in
+ * different classes, only separate words
+ * with single-byte non-word characters. */
+ while (*ptr != NUL)
+ {
+ int l = (*mb_ptr2len_check)(ptr);
+
+ if (l < 2 && !vim_iswordc(*ptr))
+ break;
+ ptr += l;
+ }
+ else
+#endif
+ ptr = find_word_end(ptr);
+ add_r = ins_compl_add_infercase(wstart,
+ (int)(ptr - wstart), files[i], dir, 0);
+ }
+ }
+ if (add_r == OK)
+ /* if dir was BACKWARD then honor it just once */
+ dir = FORWARD;
+ else if (add_r == RET_ERROR)
+ break;
+ /* avoid expensive call to vim_regexec() when at end
+ * of line */
+ if (*ptr == '\n' || got_int)
+ break;
+ }
+ line_breakcheck();
+ ins_compl_check_keys();
+ }
+ fclose(fp);
+ }
+ }
+ if (flags != DICT_EXACT)
+ FreeWild(count, files);
+ if (flags)
+ break;
+ }
+ p_scs = save_p_scs;
+ vim_free(regmatch.regprog);
+ vim_free(buf);
+}
+
+/*
+ * Find the start of the next word.
+ * Returns a pointer to the first char of the word. Also stops at a NUL.
+ */
+ char_u *
+find_word_start(ptr)
+ char_u *ptr;
+{
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ while (*ptr != NUL && *ptr != '\n' && mb_get_class(ptr) <= 1)
+ ptr += (*mb_ptr2len_check)(ptr);
+ else
+#endif
+ while (*ptr != NUL && *ptr != '\n' && !vim_iswordc(*ptr))
+ ++ptr;
+ return ptr;
+}
+
+/*
+ * Find the end of the word. Assumes it starts inside a word.
+ * Returns a pointer to just after the word.
+ */
+ char_u *
+find_word_end(ptr)
+ char_u *ptr;
+{
+#ifdef FEAT_MBYTE
+ int start_class;
+
+ if (has_mbyte)
+ {
+ start_class = mb_get_class(ptr);
+ if (start_class > 1)
+ while (*ptr != NUL)
+ {
+ ptr += (*mb_ptr2len_check)(ptr);
+ if (mb_get_class(ptr) != start_class)
+ break;
+ }
+ }
+ else
+#endif
+ while (vim_iswordc(*ptr))
+ ++ptr;
+ return ptr;
+}
+
+/*
+ * Free the list of completions
+ */
+ static void
+ins_compl_free()
+{
+ struct Completion *match;
+
+ vim_free(complete_pat);
+ complete_pat = NULL;
+
+ if (first_match == NULL)
+ return;
+ curr_match = first_match;
+ do
+ {
+ match = curr_match;
+ curr_match = curr_match->next;
+ vim_free(match->str);
+ /* several entries may use the same fname, free it just once. */
+ if (match->original & FREE_FNAME)
+ vim_free(match->fname);
+ vim_free(match);
+ } while (curr_match != NULL && curr_match != first_match);
+ first_match = curr_match = NULL;
+}
+
+ static void
+ins_compl_clear()
+{
+ continue_status = 0;
+ started_completion = FALSE;
+ completion_matches = 0;
+ vim_free(complete_pat);
+ complete_pat = NULL;
+ save_sm = -1;
+ edit_submode_extra = NULL;
+}
+
+/*
+ * Prepare for Insert mode completion, or stop it.
+ */
+ static void
+ins_compl_prep(c)
+ int c;
+{
+ char_u *ptr;
+ char_u *tmp_ptr;
+ int temp;
+ int want_cindent;
+
+ /* Forget any previous 'special' messages if this is actually
+ * a ^X mode key - bar ^R, in which case we wait to see what it gives us.
+ */
+ if (c != Ctrl_R && vim_is_ctrl_x_key(c))
+ edit_submode_extra = NULL;
+
+ /* Ignore end of Select mode mapping */
+ if (c == K_SELECT)
+ return;
+
+ if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET)
+ {
+ /*
+ * We have just typed CTRL-X and aren't quite sure which CTRL-X mode
+ * it will be yet. Now we decide.
+ */
+ switch (c)
+ {
+ case Ctrl_E:
+ case Ctrl_Y:
+ ctrl_x_mode = CTRL_X_SCROLL;
+ if (!(State & REPLACE_FLAG))
+ edit_submode = (char_u *)_(" (insert) Scroll (^E/^Y)");
+ else
+ edit_submode = (char_u *)_(" (replace) Scroll (^E/^Y)");
+ edit_submode_pre = NULL;
+ showmode();
+ break;
+ case Ctrl_L:
+ ctrl_x_mode = CTRL_X_WHOLE_LINE;
+ break;
+ case Ctrl_F:
+ ctrl_x_mode = CTRL_X_FILES;
+ break;
+ case Ctrl_K:
+ ctrl_x_mode = CTRL_X_DICTIONARY;
+ break;
+ case Ctrl_R:
+ /* Simply allow ^R to happen without affecting ^X mode */
+ break;
+ case Ctrl_T:
+ ctrl_x_mode = CTRL_X_THESAURUS;
+ break;
+ case Ctrl_RSB:
+ ctrl_x_mode = CTRL_X_TAGS;
+ break;
+#ifdef FEAT_FIND_ID
+ case Ctrl_I:
+ case K_S_TAB:
+ ctrl_x_mode = CTRL_X_PATH_PATTERNS;
+ break;
+ case Ctrl_D:
+ ctrl_x_mode = CTRL_X_PATH_DEFINES;
+ break;
+#endif
+ case Ctrl_V:
+ case Ctrl_Q:
+ ctrl_x_mode = CTRL_X_CMDLINE;
+ break;
+ case Ctrl_P:
+ case Ctrl_N:
+ /* ^X^P means LOCAL expansion if nothing interrupted (eg we
+ * just started ^X mode, or there were enough ^X's to cancel
+ * the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below)
+ * do normal expansion when interrupting a different mode (say
+ * ^X^F^X^P or ^P^X^X^P, see below)
+ * nothing changes if interrupting mode 0, (eg, the flag
+ * doesn't change when going to ADDING mode -- Acevedo */
+ if (!(continue_status & CONT_INTRPT))
+ continue_status |= CONT_LOCAL;
+ else if (continue_mode != 0)
+ continue_status &= ~CONT_LOCAL;
+ /* FALLTHROUGH */
+ default:
+ /* if we have typed at least 2 ^X's... for modes != 0, we set
+ * continue_status = 0 (eg, as if we had just started ^X mode)
+ * for mode 0, we set continue_mode to an impossible value, in
+ * both cases ^X^X can be used to restart the same mode
+ * (avoiding ADDING mode). Undocumented feature:
+ * In a mode != 0 ^X^P and ^X^X^P start 'complete' and local
+ * ^P expansions respectively. In mode 0 an extra ^X is
+ * needed since ^X^P goes to ADDING mode -- Acevedo */
+ if (c == Ctrl_X)
+ {
+ if (continue_mode != 0)
+ continue_status = 0;
+ else
+ continue_mode = CTRL_X_NOT_DEFINED_YET;
+ }
+ ctrl_x_mode = 0;
+ edit_submode = NULL;
+ showmode();
+ break;
+ }
+ }
+ else if (ctrl_x_mode != 0)
+ {
+ /* We're already in CTRL-X mode, do we stay in it? */
+ if (!vim_is_ctrl_x_key(c))
+ {
+ if (ctrl_x_mode == CTRL_X_SCROLL)
+ ctrl_x_mode = 0;
+ else
+ ctrl_x_mode = CTRL_X_FINISHED;
+ edit_submode = NULL;
+ }
+ showmode();
+ }
+
+ if (started_completion || ctrl_x_mode == CTRL_X_FINISHED)
+ {
+ /* Show error message from attempted keyword completion (probably
+ * 'Pattern not found') until another key is hit, then go back to
+ * showing what mode we are in.
+ */
+ showmode();
+ if ((ctrl_x_mode == 0 && c != Ctrl_N && c != Ctrl_P && c != Ctrl_R)
+ || ctrl_x_mode == CTRL_X_FINISHED)
+ {
+ /* Get here when we have finished typing a sequence of ^N and
+ * ^P or other completion characters in CTRL-X mode. Free up
+ * memory that was used, and make sure we can redo the insert.
+ */
+ if (curr_match != NULL)
+ {
+ /*
+ * If any of the original typed text has been changed,
+ * eg when ignorecase is set, we must add back-spaces to
+ * the redo buffer. We add as few as necessary to delete
+ * just the part of the original text that has changed.
+ */
+ ptr = curr_match->str;
+ tmp_ptr = original_text;
+ while (*tmp_ptr && *tmp_ptr == *ptr)
+ {
+ ++tmp_ptr;
+ ++ptr;
+ }
+ for (temp = 0; tmp_ptr[temp]; ++temp)
+ AppendCharToRedobuff(K_BS);
+ AppendToRedobuffLit(ptr);
+ }
+
+#ifdef FEAT_CINDENT
+ want_cindent = (can_cindent && cindent_on());
+#endif
+ /*
+ * When completing whole lines: fix indent for 'cindent'.
+ * Otherwise, break line if it's too long.
+ */
+ if (continue_mode == CTRL_X_WHOLE_LINE)
+ {
+#ifdef FEAT_CINDENT
+ /* re-indent the current line */
+ if (want_cindent)
+ {
+ do_c_expr_indent();
+ want_cindent = FALSE; /* don't do it again */
+ }
+#endif
+ }
+ else
+ {
+ /* put the cursor on the last char, for 'tw' formatting */
+ curwin->w_cursor.col--;
+ if (stop_arrow() == OK)
+ insertchar(NUL, 0, -1);
+ curwin->w_cursor.col++;
+ }
+
+ auto_format(FALSE, TRUE);
+
+ ins_compl_free();
+ started_completion = FALSE;
+ completion_matches = 0;
+ msg_clr_cmdline(); /* necessary for "noshowmode" */
+ ctrl_x_mode = 0;
+ p_sm = save_sm;
+ if (edit_submode != NULL)
+ {
+ edit_submode = NULL;
+ showmode();
+ }
+
+#ifdef FEAT_CINDENT
+ /*
+ * Indent now if a key was typed that is in 'cinkeys'.
+ */
+ if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0)))
+ do_c_expr_indent();
+#endif
+ }
+ }
+
+ /* reset continue_* if we left expansion-mode, if we stay they'll be
+ * (re)set properly in ins_complete() */
+ if (!vim_is_ctrl_x_key(c))
+ {
+ continue_status = 0;
+ continue_mode = 0;
+ }
+}
+
+/*
+ * Loops through the list of windows, loaded-buffers or non-loaded-buffers
+ * (depending on flag) starting from buf and looking for a non-scanned
+ * buffer (other than curbuf). curbuf is special, if it is called with
+ * buf=curbuf then it has to be the first call for a given flag/expansion.
+ *
+ * Returns the buffer to scan, if any, otherwise returns curbuf -- Acevedo
+ */
+ static buf_T *
+ins_compl_next_buf(buf, flag)
+ buf_T *buf;
+ int flag;
+{
+#ifdef FEAT_WINDOWS
+ static win_T *wp;
+#endif
+
+ if (flag == 'w') /* just windows */
+ {
+#ifdef FEAT_WINDOWS
+ if (buf == curbuf) /* first call for this flag/expansion */
+ wp = curwin;
+ while ((wp = wp->w_next != NULL ? wp->w_next : firstwin) != curwin
+ && wp->w_buffer->b_scanned)
+ ;
+ buf = wp->w_buffer;
+#else
+ buf = curbuf;
+#endif
+ }
+ else
+ /* 'b' (just loaded buffers), 'u' (just non-loaded buffers) or 'U'
+ * (unlisted buffers)
+ * When completing whole lines skip unloaded buffers. */
+ while ((buf = buf->b_next != NULL ? buf->b_next : firstbuf) != curbuf
+ && ((flag == 'U'
+ ? buf->b_p_bl
+ : (!buf->b_p_bl
+ || (buf->b_ml.ml_mfp == NULL) != (flag == 'u')))
+ || buf->b_scanned
+ || (buf->b_ml.ml_mfp == NULL
+ && ctrl_x_mode == CTRL_X_WHOLE_LINE)))
+ ;
+ return buf;
+}
+
+/*
+ * Get the next expansion(s) for the text starting at the initial curbuf
+ * position "ini" and in the direction dir.
+ * Return the total of matches or -1 if still unknown -- Acevedo
+ */
+ static int
+ins_compl_get_exp(ini, dir)
+ pos_T *ini;
+ int dir;
+{
+ static pos_T first_match_pos;
+ static pos_T last_match_pos;
+ static char_u *e_cpt = (char_u *)""; /* curr. entry in 'complete' */
+ static int found_all = FALSE; /* Found all matches. */
+ static buf_T *ins_buf = NULL;
+
+ pos_T *pos;
+ char_u **matches;
+ int save_p_scs;
+ int save_p_ws;
+ int save_p_ic;
+ int i;
+ int num_matches;
+ int len;
+ int found_new_match;
+ int type = ctrl_x_mode;
+ char_u *ptr;
+ char_u *tmp_ptr;
+ char_u *dict = NULL;
+ int dict_f = 0;
+ struct Completion *old_match;
+
+ if (!started_completion)
+ {
+ for (ins_buf = firstbuf; ins_buf != NULL; ins_buf = ins_buf->b_next)
+ ins_buf->b_scanned = 0;
+ found_all = FALSE;
+ ins_buf = curbuf;
+ e_cpt = continue_status & CONT_LOCAL ? (char_u *)"." : curbuf->b_p_cpt;
+ last_match_pos = first_match_pos = *ini;
+ }
+
+ old_match = curr_match; /* remember the last current match */
+ pos = (dir == FORWARD) ? &last_match_pos : &first_match_pos;
+ /* For ^N/^P loop over all the flags/windows/buffers in 'complete' */
+ for (;;)
+ {
+ found_new_match = FAIL;
+
+ /* For ^N/^P pick a new entry from e_cpt if started_completion is off,
+ * or if found_all says this entry is done. For ^X^L only use the
+ * entries from 'complete' that look in loaded buffers. */
+ if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE)
+ && (!started_completion || found_all))
+ {
+ found_all = FALSE;
+ while (*e_cpt == ',' || *e_cpt == ' ')
+ e_cpt++;
+ if (*e_cpt == '.' && !curbuf->b_scanned)
+ {
+ ins_buf = curbuf;
+ first_match_pos = *ini;
+ /* So that ^N can match word immediately after cursor */
+ if (ctrl_x_mode == 0)
+ dec(&first_match_pos);
+ last_match_pos = first_match_pos;
+ type = 0;
+ }
+ else if (vim_strchr((char_u *)"buwU", *e_cpt) != NULL
+ && (ins_buf = ins_compl_next_buf(ins_buf, *e_cpt)) != curbuf)
+ {
+ /* Scan a buffer, but not the current one. */
+ if (ins_buf->b_ml.ml_mfp != NULL) /* loaded buffer */
+ {
+ started_completion = TRUE;
+ first_match_pos.col = last_match_pos.col = 0;
+ first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1;
+ last_match_pos.lnum = 0;
+ type = 0;
+ }
+ else /* unloaded buffer, scan like dictionary */
+ {
+ found_all = TRUE;
+ if (ins_buf->b_fname == NULL)
+ continue;
+ type = CTRL_X_DICTIONARY;
+ dict = ins_buf->b_fname;
+ dict_f = DICT_EXACT;
+ }
+ sprintf((char *)IObuff, _("Scanning: %s"),
+ ins_buf->b_fname == NULL
+ ? buf_spname(ins_buf)
+ : ins_buf->b_sfname == NULL
+ ? (char *)ins_buf->b_fname
+ : (char *)ins_buf->b_sfname);
+ msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
+ }
+ else if (*e_cpt == NUL)
+ break;
+ else
+ {
+ if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
+ type = -1;
+ else if (*e_cpt == 'k' || *e_cpt == 's')
+ {
+ if (*e_cpt == 'k')
+ type = CTRL_X_DICTIONARY;
+ else
+ type = CTRL_X_THESAURUS;
+ if (*++e_cpt != ',' && *e_cpt != NUL)
+ {
+ dict = e_cpt;
+ dict_f = DICT_FIRST;
+ }
+ }
+#ifdef FEAT_FIND_ID
+ else if (*e_cpt == 'i')
+ type = CTRL_X_PATH_PATTERNS;
+ else if (*e_cpt == 'd')
+ type = CTRL_X_PATH_DEFINES;
+#endif
+ else if (*e_cpt == ']' || *e_cpt == 't')
+ {
+ type = CTRL_X_TAGS;
+ sprintf((char*)IObuff, _("Scanning tags."));
+ msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
+ }
+ else
+ type = -1;
+
+ /* in any case e_cpt is advanced to the next entry */
+ (void)copy_option_part(&e_cpt, IObuff, IOSIZE, ",");
+
+ found_all = TRUE;
+ if (type == -1)
+ continue;
+ }
+ }
+
+ switch (type)
+ {
+ case -1:
+ break;
+#ifdef FEAT_FIND_ID
+ case CTRL_X_PATH_PATTERNS:
+ case CTRL_X_PATH_DEFINES:
+ find_pattern_in_path(complete_pat, dir,
+ (int)STRLEN(complete_pat), FALSE, FALSE,
+ (type == CTRL_X_PATH_DEFINES
+ && !(continue_status & CONT_SOL))
+ ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
+ (linenr_T)1, (linenr_T)MAXLNUM);
+ break;
+#endif
+
+ case CTRL_X_DICTIONARY:
+ case CTRL_X_THESAURUS:
+ ins_compl_dictionaries(
+ dict ? dict
+ : (type == CTRL_X_THESAURUS
+ ? (*curbuf->b_p_tsr == NUL
+ ? p_tsr
+ : curbuf->b_p_tsr)
+ : (*curbuf->b_p_dict == NUL
+ ? p_dict
+ : curbuf->b_p_dict)),
+ complete_pat, dir,
+ dict ? dict_f : 0, type == CTRL_X_THESAURUS);
+ dict = NULL;
+ break;
+
+ case CTRL_X_TAGS:
+ /* set p_ic according to p_ic, p_scs and pat for find_tags(). */
+ save_p_ic = p_ic;
+ p_ic = ignorecase(complete_pat);
+
+ /* Find up to TAG_MANY matches. Avoids that an enourmous number
+ * of matches is found when complete_pat is empty */
+ if (find_tags(complete_pat, &num_matches, &matches,
+ TAG_REGEXP | TAG_NAMES | TAG_NOIC |
+ TAG_INS_COMP | (ctrl_x_mode ? TAG_VERBOSE : 0),
+ TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0)
+ {
+ ins_compl_add_matches(num_matches, matches, dir);
+ }
+ p_ic = save_p_ic;
+ break;
+
+ case CTRL_X_FILES:
+ if (expand_wildcards(1, &complete_pat, &num_matches, &matches,
+ EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK)
+ {
+
+ /* May change home directory back to "~". */
+ tilde_replace(complete_pat, num_matches, matches);
+ ins_compl_add_matches(num_matches, matches, dir);
+ }
+ break;
+
+ case CTRL_X_CMDLINE:
+ if (expand_cmdline(&complete_xp, complete_pat,
+ (int)STRLEN(complete_pat),
+ &num_matches, &matches) == EXPAND_OK)
+ ins_compl_add_matches(num_matches, matches, dir);
+ break;
+
+ default: /* normal ^P/^N and ^X^L */
+ /*
+ * If 'infercase' is set, don't use 'smartcase' here
+ */
+ save_p_scs = p_scs;
+ if (ins_buf->b_p_inf)
+ p_scs = FALSE;
+ /* buffers other than curbuf are scanned from the beginning or the
+ * end but never from the middle, thus setting nowrapscan in this
+ * buffers is a good idea, on the other hand, we always set
+ * wrapscan for curbuf to avoid missing matches -- Acevedo,Webb */
+ save_p_ws = p_ws;
+ if (ins_buf != curbuf)
+ p_ws = FALSE;
+ else if (*e_cpt == '.')
+ p_ws = TRUE;
+ for (;;)
+ {
+ int reuse = 0;
+
+ /* ctrl_x_mode == CTRL_X_WHOLE_LINE || word-wise search that has
+ * added a word that was at the beginning of the line */
+ if ( ctrl_x_mode == CTRL_X_WHOLE_LINE
+ || (continue_status & CONT_SOL))
+ found_new_match = search_for_exact_line(ins_buf, pos,
+ dir, complete_pat);
+ else
+ found_new_match = searchit(NULL, ins_buf, pos, dir,
+ complete_pat, 1L, SEARCH_KEEP + SEARCH_NFMSG,
+ RE_LAST);
+ if (!started_completion)
+ {
+ /* set started_completion even on fail */
+ started_completion = TRUE;
+ first_match_pos = *pos;
+ last_match_pos = *pos;
+ }
+ else if (first_match_pos.lnum == last_match_pos.lnum
+ && first_match_pos.col == last_match_pos.col)
+ found_new_match = FAIL;
+ if (found_new_match == FAIL)
+ {
+ if (ins_buf == curbuf)
+ found_all = TRUE;
+ break;
+ }
+
+ /* when ADDING, the text before the cursor matches, skip it */
+ if ( (continue_status & CONT_ADDING) && ins_buf == curbuf
+ && ini->lnum == pos->lnum
+ && ini->col == pos->col)
+ continue;
+ ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col;
+ if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
+ {
+ if (continue_status & CONT_ADDING)
+ {
+ if (pos->lnum >= ins_buf->b_ml.ml_line_count)
+ continue;
+ ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
+ if (!p_paste)
+ ptr = skipwhite(ptr);
+ }
+ len = (int)STRLEN(ptr);
+ }
+ else
+ {
+ tmp_ptr = ptr;
+ if (continue_status & CONT_ADDING)
+ {
+ tmp_ptr += completion_length;
+ /* Skip if already inside a word. */
+ if (vim_iswordp(tmp_ptr))
+ continue;
+ /* Find start of next word. */
+ tmp_ptr = find_word_start(tmp_ptr);
+ }
+ /* Find end of this word. */
+ tmp_ptr = find_word_end(tmp_ptr);
+ len = (int)(tmp_ptr - ptr);
+
+ if ((continue_status & CONT_ADDING)
+ && len == completion_length)
+ {
+ if (pos->lnum < ins_buf->b_ml.ml_line_count)
+ {
+ /* Try next line, if any. the new word will be
+ * "join" as if the normal command "J" was used.
+ * IOSIZE is always greater than
+ * completion_length, so the next STRNCPY always
+ * works -- Acevedo */
+ STRNCPY(IObuff, ptr, len);
+ ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
+ tmp_ptr = ptr = skipwhite(ptr);
+ /* Find start of next word. */
+ tmp_ptr = find_word_start(tmp_ptr);
+ /* Find end of next word. */
+ tmp_ptr = find_word_end(tmp_ptr);
+ if (tmp_ptr > ptr)
+ {
+ if (*ptr != ')' && IObuff[len-1] != TAB)
+ {
+ if (IObuff[len-1] != ' ')
+ IObuff[len++] = ' ';
+ /* IObuf =~ "\k.* ", thus len >= 2 */
+ if (p_js
+ && (IObuff[len-2] == '.'
+ || (vim_strchr(p_cpo, CPO_JOINSP)
+ == NULL
+ && (IObuff[len-2] == '?'
+ || IObuff[len-2] == '!'))))
+ IObuff[len++] = ' ';
+ }
+ /* copy as much as posible of the new word */
+ if (tmp_ptr - ptr >= IOSIZE - len)
+ tmp_ptr = ptr + IOSIZE - len - 1;
+ STRNCPY(IObuff + len, ptr, tmp_ptr - ptr);
+ len += (int)(tmp_ptr - ptr);
+ reuse |= CONT_S_IPOS;
+ }
+ IObuff[len] = NUL;
+ ptr = IObuff;
+ }
+ if (len == completion_length)
+ continue;
+ }
+ }
+ if (ins_compl_add_infercase(ptr, len,
+ ins_buf == curbuf ? NULL : ins_buf->b_sfname,
+ dir, reuse) != FAIL)
+ {
+ found_new_match = OK;
+ break;
+ }
+ }
+ p_scs = save_p_scs;
+ p_ws = save_p_ws;
+ }
+ /* check if curr_match has changed, (e.g. other type of expansion
+ * added somenthing) */
+ if (curr_match != old_match)
+ found_new_match = OK;
+
+ /* break the loop for specialized modes (use 'complete' just for the
+ * generic ctrl_x_mode == 0) or when we've found a new match */
+ if ((ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE)
+ || found_new_match != FAIL)
+ break;
+
+ /* Mark a buffer scanned when it has been scanned completely */
+ if (type == 0 || type == CTRL_X_PATH_PATTERNS)
+ ins_buf->b_scanned = TRUE;
+
+ started_completion = FALSE;
+ }
+ started_completion = TRUE;
+
+ if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE)
+ && *e_cpt == NUL) /* Got to end of 'complete' */
+ found_new_match = FAIL;
+
+ i = -1; /* total of matches, unknown */
+ if (found_new_match == FAIL
+ || (ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE))
+ i = ins_compl_make_cyclic();
+
+ /* If several matches were added (FORWARD) or the search failed and has
+ * just been made cyclic then we have to move curr_match to the next or
+ * previous entry (if any) -- Acevedo */
+ curr_match = dir == FORWARD ? old_match->next : old_match->prev;
+ if (curr_match == NULL)
+ curr_match = old_match;
+ return i;
+}
+
+/* Delete the old text being completed. */
+ static void
+ins_compl_delete()
+{
+ int i;
+
+ /*
+ * In insert mode: Delete the typed part.
+ * In replace mode: Put the old characters back, if any.
+ */
+ i = complete_col + (continue_status & CONT_ADDING ? completion_length : 0);
+ backspace_until_column(i);
+ changed_cline_bef_curs();
+}
+
+/* Insert the new text being completed. */
+ static void
+ins_compl_insert()
+{
+ ins_bytes(shown_match->str + curwin->w_cursor.col - complete_col);
+}
+
+/*
+ * Fill in the next completion in the current direction.
+ * If allow_get_expansion is TRUE, then we may call ins_compl_get_exp() to get
+ * more completions. If it is FALSE, then we just do nothing when there are
+ * no more completions in a given direction. The latter case is used when we
+ * are still in the middle of finding completions, to allow browsing through
+ * the ones found so far.
+ * Return the total number of matches, or -1 if still unknown -- webb.
+ *
+ * curr_match is currently being used by ins_compl_get_exp(), so we use
+ * shown_match here.
+ *
+ * Note that this function may be called recursively once only. First with
+ * allow_get_expansion TRUE, which calls ins_compl_get_exp(), which in turn
+ * calls this function with allow_get_expansion FALSE.
+ */
+ static int
+ins_compl_next(allow_get_expansion)
+ int allow_get_expansion;
+{
+ int num_matches = -1;
+ int i;
+
+ if (allow_get_expansion)
+ {
+ /* Delete old text to be replaced */
+ ins_compl_delete();
+ }
+ completion_pending = FALSE;
+ if (shown_direction == FORWARD && shown_match->next != NULL)
+ shown_match = shown_match->next;
+ else if (shown_direction == BACKWARD && shown_match->prev != NULL)
+ shown_match = shown_match->prev;
+ else
+ {
+ completion_pending = TRUE;
+ if (allow_get_expansion)
+ {
+ num_matches = ins_compl_get_exp(&initial_pos, complete_direction);
+ if (completion_pending)
+ {
+ if (complete_direction == shown_direction)
+ shown_match = curr_match;
+ }
+ }
+ else
+ return -1;
+ }
+
+ /* Insert the text of the new completion */
+ ins_compl_insert();
+
+ if (!allow_get_expansion)
+ {
+ /* Display the current match. */
+ update_screen(0);
+
+ /* Delete old text to be replaced, since we're still searching and
+ * don't want to match ourselves! */
+ ins_compl_delete();
+ }
+
+ /*
+ * Show the file name for the match (if any)
+ * Truncate the file name to avoid a wait for return.
+ */
+ if (shown_match->fname != NULL)
+ {
+ STRCPY(IObuff, "match in file ");
+ i = (vim_strsize(shown_match->fname) + 16) - sc_col;
+ if (i <= 0)
+ i = 0;
+ else
+ STRCAT(IObuff, "<");
+ STRCAT(IObuff, shown_match->fname + i);
+ msg(IObuff);
+ redraw_cmdline = FALSE; /* don't overwrite! */
+ }
+
+ return num_matches;
+}
+
+/*
+ * Call this while finding completions, to check whether the user has hit a key
+ * that should change the currently displayed completion, or exit completion
+ * mode. Also, when completion_pending is TRUE, show a completion as soon as
+ * possible. -- webb
+ */
+ void
+ins_compl_check_keys()
+{
+ static int count = 0;
+
+ int c;
+
+ /* Don't check when reading keys from a script. That would break the test
+ * scripts */
+ if (using_script())
+ return;
+
+ /* Only do this at regular intervals */
+ if (++count < CHECK_KEYS_TIME)
+ return;
+ count = 0;
+
+ ++no_mapping;
+ c = vpeekc_any();
+ --no_mapping;
+ if (c != NUL)
+ {
+ if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R)
+ {
+ c = safe_vgetc(); /* Eat the character */
+ if (c == Ctrl_P || c == Ctrl_L)
+ shown_direction = BACKWARD;
+ else
+ shown_direction = FORWARD;
+ (void)ins_compl_next(FALSE);
+ }
+ else if (c != Ctrl_R)
+ completion_interrupted = TRUE;
+ }
+ if (completion_pending && !got_int)
+ (void)ins_compl_next(FALSE);
+}
+
+/*
+ * Do Insert mode completion.
+ * Called when character "c" was typed, which has a meaning for completion.
+ * Returns OK if completion was done, FAIL if something failed (out of mem).
+ */
+ static int
+ins_complete(c)
+ int c;
+{
+ char_u *line;
+ char_u *tmp_ptr = NULL; /* init for gcc */
+ int temp = 0;
+
+ if (c == Ctrl_P || c == Ctrl_L)
+ complete_direction = BACKWARD;
+ else
+ complete_direction = FORWARD;
+ if (!started_completion)
+ {
+ /* First time we hit ^N or ^P (in a row, I mean) */
+
+ /* Turn off 'sm' so we don't show matches with ^X^L */
+ save_sm = p_sm;
+ p_sm = FALSE;
+
+ did_ai = FALSE;
+#ifdef FEAT_SMARTINDENT
+ did_si = FALSE;
+ can_si = FALSE;
+ can_si_back = FALSE;
+#endif
+ if (stop_arrow() == FAIL)
+ return FAIL;
+
+ line = ml_get(curwin->w_cursor.lnum);
+ complete_col = curwin->w_cursor.col;
+
+ /* if this same ctrl_x_mode has been interrupted use the text from
+ * "initial_pos" to the cursor as a pattern to add a new word instead
+ * of expand the one before the cursor, in word-wise if "initial_pos"
+ * is not in the same line as the cursor then fix it (the line has
+ * been split because it was longer than 'tw'). if SOL is set then
+ * skip the previous pattern, a word at the beginning of the line has
+ * been inserted, we'll look for that -- Acevedo. */
+ if ((continue_status & CONT_INTRPT) && continue_mode == ctrl_x_mode)
+ {
+ /*
+ * it is a continued search
+ */
+ continue_status &= ~CONT_INTRPT; /* remove INTRPT */
+ if (ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_PATH_PATTERNS
+ || ctrl_x_mode == CTRL_X_PATH_DEFINES)
+ {
+ if (initial_pos.lnum != curwin->w_cursor.lnum)
+ {
+ /* line (probably) wrapped, set initial_pos to the first
+ * non_blank in the line, if it is not a wordchar include
+ * it to get a better pattern, but then we don't want the
+ * "\\<" prefix, check it bellow */
+ tmp_ptr = skipwhite(line);
+ initial_pos.col = (colnr_T) (tmp_ptr - line);
+ initial_pos.lnum = curwin->w_cursor.lnum;
+ continue_status &= ~CONT_SOL; /* clear SOL if present */
+ }
+ else
+ {
+ /* S_IPOS was set when we inserted a word that was at the
+ * beginning of the line, which means that we'll go to SOL
+ * mode but first we need to redefine initial_pos */
+ if (continue_status & CONT_S_IPOS)
+ {
+ continue_status |= CONT_SOL;
+ initial_pos.col = (colnr_T) (skipwhite(line + completion_length +
+ initial_pos.col) - line);
+ }
+ tmp_ptr = line + initial_pos.col;
+ }
+ temp = curwin->w_cursor.col - (int)(tmp_ptr - line);
+ /* IObuf is used to add a "word from the next line" would we
+ * have enough space? just being paranoic */
+#define MIN_SPACE 75
+ if (temp > (IOSIZE - MIN_SPACE))
+ {
+ continue_status &= ~CONT_SOL;
+ temp = (IOSIZE - MIN_SPACE);
+ tmp_ptr = line + curwin->w_cursor.col - temp;
+ }
+ continue_status |= CONT_ADDING | CONT_N_ADDS;
+ if (temp < 1)
+ continue_status &= CONT_LOCAL;
+ }
+ else if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
+ continue_status = CONT_ADDING | CONT_N_ADDS;
+ else
+ continue_status = 0;
+ }
+ else
+ continue_status &= CONT_LOCAL;
+
+ if (!(continue_status & CONT_ADDING)) /* normal expansion */
+ {
+ continue_mode = ctrl_x_mode;
+ if (ctrl_x_mode != 0) /* Remove LOCAL if ctrl_x_mode != 0 */
+ continue_status = 0;
+ continue_status |= CONT_N_ADDS;
+ initial_pos = curwin->w_cursor;
+ temp = (int)complete_col;
+ tmp_ptr = line;
+ }
+
+ /* Work out completion pattern and original text -- webb */
+ if (ctrl_x_mode == 0 || (ctrl_x_mode & CTRL_X_WANT_IDENT))
+ {
+ if ( (continue_status & CONT_SOL)
+ || ctrl_x_mode == CTRL_X_PATH_DEFINES)
+ {
+ if (!(continue_status & CONT_ADDING))
+ {
+ while (--temp >= 0 && vim_isIDc(line[temp]))
+ ;
+ tmp_ptr += ++temp;
+ temp = complete_col - temp;
+ }
+ if (p_ic)
+ complete_pat = str_foldcase(tmp_ptr, temp);
+ else
+ complete_pat = vim_strnsave(tmp_ptr, temp);
+ if (complete_pat == NULL)
+ return FAIL;
+ }
+ else if (continue_status & CONT_ADDING)
+ {
+ char_u *prefix = (char_u *)"\\<";
+
+ /* we need 3 extra chars, 1 for the NUL and
+ * 2 >= strlen(prefix) -- Acevedo */
+ complete_pat = alloc(quote_meta(NULL, tmp_ptr, temp) + 3);
+ if (complete_pat == NULL)
+ return FAIL;
+ if (!vim_iswordp(tmp_ptr)
+ || (tmp_ptr > line
+ && (
+#ifdef FEAT_MBYTE
+ vim_iswordp(mb_prevptr(line, tmp_ptr))
+#else
+ vim_iswordc(*(tmp_ptr - 1))
+#endif
+ )))
+ prefix = (char_u *)"";
+ STRCPY((char *)complete_pat, prefix);
+ (void)quote_meta(complete_pat + STRLEN(prefix), tmp_ptr, temp);
+ }
+ else if (
+#ifdef FEAT_MBYTE
+ --temp < 0 || !vim_iswordp(mb_prevptr(line,
+ line + temp + 1))
+#else
+ --temp < 0 || !vim_iswordc(line[temp])
+#endif
+ )
+ {
+ /* Match any word of at least two chars */
+ complete_pat = vim_strsave((char_u *)"\\<\\k\\k");
+ if (complete_pat == NULL)
+ return FAIL;
+ tmp_ptr += complete_col;
+ temp = 0;
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ /* Search the point of change class of multibyte character
+ * or not a word single byte character backward. */
+ if (has_mbyte)
+ {
+ int base_class;
+ int head_off;
+
+ temp -= (*mb_head_off)(line, line + temp);
+ base_class = mb_get_class(line + temp);
+ while (--temp >= 0)
+ {
+ head_off = (*mb_head_off)(line, line + temp);
+ if (base_class != mb_get_class(line + temp - head_off))
+ break;
+ temp -= head_off;
+ }
+ }
+ else
+#endif
+ while (--temp >= 0 && vim_iswordc(line[temp]))
+ ;
+ tmp_ptr += ++temp;
+ if ((temp = (int)complete_col - temp) == 1)
+ {
+ /* Only match word with at least two chars -- webb
+ * there's no need to call quote_meta,
+ * alloc(7) is enough -- Acevedo
+ */
+ complete_pat = alloc(7);
+ if (complete_pat == NULL)
+ return FAIL;
+ STRCPY((char *)complete_pat, "\\<");
+ (void)quote_meta(complete_pat + 2, tmp_ptr, 1);
+ STRCAT((char *)complete_pat, "\\k");
+ }
+ else
+ {
+ complete_pat = alloc(quote_meta(NULL, tmp_ptr, temp) + 3);
+ if (complete_pat == NULL)
+ return FAIL;
+ STRCPY((char *)complete_pat, "\\<");
+ (void)quote_meta(complete_pat + 2, tmp_ptr, temp);
+ }
+ }
+ }
+ else if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
+ {
+ tmp_ptr = skipwhite(line);
+ temp = (int)complete_col - (int)(tmp_ptr - line);
+ if (temp < 0) /* cursor in indent: empty pattern */
+ temp = 0;
+ if (p_ic)
+ complete_pat = str_foldcase(tmp_ptr, temp);
+ else
+ complete_pat = vim_strnsave(tmp_ptr, temp);
+ if (complete_pat == NULL)
+ return FAIL;
+ }
+ else if (ctrl_x_mode == CTRL_X_FILES)
+ {
+ while (--temp >= 0 && vim_isfilec(line[temp]))
+ ;
+ tmp_ptr += ++temp;
+ temp = (int)complete_col - temp;
+ complete_pat = addstar(tmp_ptr, temp, EXPAND_FILES);
+ if (complete_pat == NULL)
+ return FAIL;
+ }
+ else if (ctrl_x_mode == CTRL_X_CMDLINE)
+ {
+ complete_pat = vim_strnsave(line, complete_col);
+ if (complete_pat == NULL)
+ return FAIL;
+ set_cmd_context(&complete_xp, complete_pat,
+ (int)STRLEN(complete_pat), complete_col);
+ if (complete_xp.xp_context == EXPAND_UNSUCCESSFUL
+ || complete_xp.xp_context == EXPAND_NOTHING)
+ return FAIL;
+ temp = (int)(complete_xp.xp_pattern - complete_pat);
+ tmp_ptr = line + temp;
+ temp = complete_col - temp;
+ }
+ complete_col = (colnr_T) (tmp_ptr - line);
+
+ if (continue_status & CONT_ADDING)
+ {
+ edit_submode_pre = (char_u *)_(" Adding");
+ if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
+ {
+ /* Insert a new line, keep indentation but ignore 'comments' */
+#ifdef FEAT_COMMENTS
+ char_u *old = curbuf->b_p_com;
+
+ curbuf->b_p_com = (char_u *)"";
+#endif
+ initial_pos.lnum = curwin->w_cursor.lnum;
+ initial_pos.col = complete_col;
+ ins_eol('\r');
+#ifdef FEAT_COMMENTS
+ curbuf->b_p_com = old;
+#endif
+ tmp_ptr = (char_u *)"";
+ temp = 0;
+ complete_col = curwin->w_cursor.col;
+ }
+ }
+ else
+ {
+ edit_submode_pre = NULL;
+ initial_pos.col = complete_col;
+ }
+
+ if (continue_status & CONT_LOCAL)
+ edit_submode = (char_u *)_(ctrl_x_msgs[2]);
+ else
+ edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
+
+ completion_length = temp;
+
+ /* Always add completion for the original text. Note that
+ * "original_text" itself (not a copy) is added, it will be freed when
+ * the list of matches is freed. */
+ if ((original_text = vim_strnsave(tmp_ptr, temp)) == NULL
+ || ins_compl_add(original_text, -1, NULL, 0, ORIGINAL_TEXT) != OK)
+ {
+ vim_free(complete_pat);
+ complete_pat = NULL;
+ vim_free(original_text);
+ return FAIL;
+ }
+
+ /* showmode might reset the internal line pointers, so it must
+ * be called before line = ml_get(), or when this address is no
+ * longer needed. -- Acevedo.
+ */
+ edit_submode_extra = (char_u *)_("-- Searching...");
+ edit_submode_highl = HLF_COUNT;
+ showmode();
+ edit_submode_extra = NULL;
+ out_flush();
+ }
+
+ shown_match = curr_match;
+ shown_direction = complete_direction;
+
+ /*
+ * Find next match.
+ */
+ temp = ins_compl_next(TRUE);
+
+ if (temp > 1) /* all matches have been found */
+ completion_matches = temp;
+ curr_match = shown_match;
+ complete_direction = shown_direction;
+ completion_interrupted = FALSE;
+
+ /* eat the ESC to avoid leaving insert mode */
+ if (got_int && !global_busy)
+ {
+ (void)vgetc();
+ got_int = FALSE;
+ }
+
+ /* we found no match if the list has only the original_text-entry */
+ if (first_match == first_match->next)
+ {
+ edit_submode_extra = (continue_status & CONT_ADDING)
+ && completion_length > 1
+ ? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf);
+ edit_submode_highl = HLF_E;
+ /* remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
+ * because we couldn't expand anything at first place, but if we used
+ * ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
+ * (such as M in M'exico) if not tried already. -- Acevedo */
+ if ( completion_length > 1
+ || (continue_status & CONT_ADDING)
+ || (ctrl_x_mode != 0
+ && ctrl_x_mode != CTRL_X_PATH_PATTERNS
+ && ctrl_x_mode != CTRL_X_PATH_DEFINES))
+ continue_status &= ~CONT_N_ADDS;
+ }
+
+ if (curr_match->original & CONT_S_IPOS)
+ continue_status |= CONT_S_IPOS;
+ else
+ continue_status &= ~CONT_S_IPOS;
+
+ if (edit_submode_extra == NULL)
+ {
+ if (curr_match->original & ORIGINAL_TEXT)
+ {
+ edit_submode_extra = (char_u *)_("Back at original");
+ edit_submode_highl = HLF_W;
+ }
+ else if (continue_status & CONT_S_IPOS)
+ {
+ edit_submode_extra = (char_u *)_("Word from other line");
+ edit_submode_highl = HLF_COUNT;
+ }
+ else if (curr_match->next == curr_match->prev)
+ {
+ edit_submode_extra = (char_u *)_("The only match");
+ edit_submode_highl = HLF_COUNT;
+ }
+ else
+ {
+ /* Update completion sequence number when needed. */
+ if (curr_match->number == -1)
+ {
+ int number = 0;
+ struct Completion *match;
+
+ if (complete_direction == FORWARD)
+ {
+ /* search backwards for the first valid (!= -1) number.
+ * This should normally succeed already at the first loop
+ * cycle, so it's fast! */
+ for (match = curr_match->prev; match != NULL
+ && match != first_match; match = match->prev)
+ if (match->number != -1)
+ {
+ number = match->number;
+ break;
+ }
+ if (match != NULL)
+ /* go up and assign all numbers which are not assigned
+ * yet */
+ for (match = match->next; match
+ && match->number == -1; match = match->next)
+ match->number = ++number;
+ }
+ else /* BACKWARD */
+ {
+ /* search forwards (upwards) for the first valid (!= -1)
+ * number. This should normally succeed already at the
+ * first loop cycle, so it's fast! */
+ for (match = curr_match->next; match != NULL
+ && match != first_match; match = match->next)
+ if (match->number != -1)
+ {
+ number = match->number;
+ break;
+ }
+ if (match != NULL)
+ /* go down and assign all numbers which are not
+ * assigned yet */
+ for (match = match->prev; match
+ && match->number == -1; match = match->prev)
+ match->number = ++number;
+ }
+ }
+
+ /* The match should always have a sequnce number now, this is just
+ * a safety check. */
+ if (curr_match->number != -1)
+ {
+ /* Space for 10 text chars. + 2x10-digit no.s */
+ static char_u match_ref[31];
+
+ if (completion_matches > 0)
+ sprintf((char *)IObuff, _("match %d of %d"),
+ curr_match->number, completion_matches);
+ else
+ sprintf((char *)IObuff, _("match %d"), curr_match->number);
+ STRNCPY(match_ref, IObuff, 30 );
+ match_ref[30] = '\0';
+ edit_submode_extra = match_ref;
+ edit_submode_highl = HLF_R;
+ if (dollar_vcol)
+ curs_columns(FALSE);
+ }
+ }
+ }
+
+ /* Show a message about what (completion) mode we're in. */
+ showmode();
+ if (edit_submode_extra != NULL)
+ {
+ if (!p_smd)
+ msg_attr(edit_submode_extra,
+ edit_submode_highl < HLF_COUNT
+ ? hl_attr(edit_submode_highl) : 0);
+ }
+ else
+ msg_clr_cmdline(); /* necessary for "noshowmode" */
+
+ return OK;
+}
+
+/*
+ * Looks in the first "len" chars. of "src" for search-metachars.
+ * If dest is not NULL the chars. are copied there quoting (with
+ * a backslash) the metachars, and dest would be NUL terminated.
+ * Returns the length (needed) of dest
+ */
+ static int
+quote_meta(dest, src, len)
+ char_u *dest;
+ char_u *src;
+ int len;
+{
+ int m;
+
+ for (m = len; --len >= 0; src++)
+ {
+ switch (*src)
+ {
+ case '.':
+ case '*':
+ case '[':
+ if (ctrl_x_mode == CTRL_X_DICTIONARY
+ || ctrl_x_mode == CTRL_X_THESAURUS)
+ break;
+ case '~':
+ if (!p_magic) /* quote these only if magic is set */
+ break;
+ case '\\':
+ if (ctrl_x_mode == CTRL_X_DICTIONARY
+ || ctrl_x_mode == CTRL_X_THESAURUS)
+ break;
+ case '^': /* currently it's not needed. */
+ case '$':
+ m++;
+ if (dest != NULL)
+ *dest++ = '\\';
+ break;
+ }
+ if (dest != NULL)
+ *dest++ = *src;
+#ifdef FEAT_MBYTE
+ /* Copy remaining bytes of a multibyte character. */
+ if (has_mbyte)
+ {
+ int i, mb_len;
+
+ mb_len = (*mb_ptr2len_check)(src) - 1;
+ if (mb_len > 0 && len >= mb_len)
+ for (i = 0; i < mb_len; ++i)
+ {
+ --len;
+ ++src;
+ if (dest != NULL)
+ *dest++ = *src;
+ }
+ }
+#endif
+ }
+ if (dest != NULL)
+ *dest = NUL;
+
+ return m;
+}
+#endif /* FEAT_INS_EXPAND */
+
+/*
+ * Next character is interpreted literally.
+ * A one, two or three digit decimal number is interpreted as its byte value.
+ * If one or two digits are entered, the next character is given to vungetc().
+ * For Unicode a character > 255 may be returned.
+ */
+ int
+get_literal()
+{
+ int cc;
+ int nc;
+ int i;
+ int hex = FALSE;
+ int octal = FALSE;
+#ifdef FEAT_MBYTE
+ int unicode = 0;
+#endif
+
+ if (got_int)
+ return Ctrl_C;
+
+#ifdef FEAT_GUI
+ /*
+ * In GUI there is no point inserting the internal code for a special key.
+ * It is more useful to insert the string "<KEY>" instead. This would
+ * probably be useful in a text window too, but it would not be
+ * vi-compatible (maybe there should be an option for it?) -- webb
+ */
+ if (gui.in_use)
+ ++allow_keys;
+#endif
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = TRUE; /* disallow scrolling here */
+#endif
+ ++no_mapping; /* don't map the next key hits */
+ cc = 0;
+ i = 0;
+ for (;;)
+ {
+ do
+ nc = safe_vgetc();
+ while (nc == K_IGNORE || nc == K_VER_SCROLLBAR
+ || nc == K_HOR_SCROLLBAR);
+#ifdef FEAT_CMDL_INFO
+ if (!(State & CMDLINE)
+# ifdef FEAT_MBYTE
+ && MB_BYTE2LEN_CHECK(nc) == 1
+# endif
+ )
+ add_to_showcmd(nc);
+#endif
+ if (nc == 'x' || nc == 'X')
+ hex = TRUE;
+ else if (nc == 'o' || nc == 'O')
+ octal = TRUE;
+#ifdef FEAT_MBYTE
+ else if (nc == 'u' || nc == 'U')
+ unicode = nc;
+#endif
+ else
+ {
+ if (hex
+#ifdef FEAT_MBYTE
+ || unicode != 0
+#endif
+ )
+ {
+ if (!vim_isxdigit(nc))
+ break;
+ cc = cc * 16 + hex2nr(nc);
+ }
+ else if (octal)
+ {
+ if (nc < '0' || nc > '7')
+ break;
+ cc = cc * 8 + nc - '0';
+ }
+ else
+ {
+ if (!VIM_ISDIGIT(nc))
+ break;
+ cc = cc * 10 + nc - '0';
+ }
+
+ ++i;
+ }
+
+ if (cc > 255
+#ifdef FEAT_MBYTE
+ && unicode == 0
+#endif
+ )
+ cc = 255; /* limit range to 0-255 */
+ nc = 0;
+
+ if (hex) /* hex: up to two chars */
+ {
+ if (i >= 2)
+ break;
+ }
+#ifdef FEAT_MBYTE
+ else if (unicode) /* Unicode: up to four or eight chars */
+ {
+ if ((unicode == 'u' && i >= 4) || (unicode == 'U' && i >= 8))
+ break;
+ }
+#endif
+ else if (i >= 3) /* decimal or octal: up to three chars */
+ break;
+ }
+ if (i == 0) /* no number entered */
+ {
+ if (nc == K_ZERO) /* NUL is stored as NL */
+ {
+ cc = '\n';
+ nc = 0;
+ }
+ else
+ {
+ cc = nc;
+ nc = 0;
+ }
+ }
+
+ if (cc == 0) /* NUL is stored as NL */
+ cc = '\n';
+
+ --no_mapping;
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ --allow_keys;
+#endif
+ if (nc)
+ vungetc(nc);
+ got_int = FALSE; /* CTRL-C typed after CTRL-V is not an interrupt */
+ return cc;
+}
+
+/*
+ * Insert character, taking care of special keys and mod_mask
+ */
+ static void
+insert_special(c, allow_modmask, ctrlv)
+ int c;
+ int allow_modmask;
+ int ctrlv; /* c was typed after CTRL-V */
+{
+ char_u *p;
+ int len;
+
+ /*
+ * Special function key, translate into "<Key>". Up to the last '>' is
+ * inserted with ins_str(), so as not to replace characters in replace
+ * mode.
+ * Only use mod_mask for special keys, to avoid things like <S-Space>,
+ * unless 'allow_modmask' is TRUE.
+ */
+#ifdef MACOS
+ /* Command-key never produces a normal key */
+ if (mod_mask & MOD_MASK_CMD)
+ allow_modmask = TRUE;
+#endif
+ if (IS_SPECIAL(c) || (mod_mask && allow_modmask))
+ {
+ p = get_special_key_name(c, mod_mask);
+ len = (int)STRLEN(p);
+ c = p[len - 1];
+ if (len > 2)
+ {
+ if (stop_arrow() == FAIL)
+ return;
+ p[len - 1] = NUL;
+ ins_str(p);
+ AppendToRedobuffLit(p);
+ ctrlv = FALSE;
+ }
+ }
+ if (stop_arrow() == OK)
+ insertchar(c, ctrlv ? INSCHAR_CTRLV : 0, -1);
+}
+
+/*
+ * Special characters in this context are those that need processing other
+ * than the simple insertion that can be performed here. This includes ESC
+ * which terminates the insert, and CR/NL which need special processing to
+ * open up a new line. This routine tries to optimize insertions performed by
+ * the "redo", "undo" or "put" commands, so it needs to know when it should
+ * stop and defer processing to the "normal" mechanism.
+ * '0' and '^' are special, because they can be followed by CTRL-D.
+ */
+#ifdef EBCDIC
+# define ISSPECIAL(c) ((c) < ' ' || (c) == '0' || (c) == '^')
+#else
+# define ISSPECIAL(c) ((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^')
+#endif
+
+#ifdef FEAT_MBYTE
+# define WHITECHAR(cc) (vim_iswhite(cc) && (!enc_utf8 || !utf_iscomposing(utf_ptr2char(ml_get_cursor() + 1))))
+#else
+# define WHITECHAR(cc) vim_iswhite(cc)
+#endif
+
+ void
+insertchar(c, flags, second_indent)
+ int c; /* character to insert or NUL */
+ int flags; /* INSCHAR_FORMAT, etc. */
+ int second_indent; /* indent for second line if >= 0 */
+{
+ int haveto_redraw = FALSE;
+ int textwidth;
+#ifdef FEAT_COMMENTS
+ colnr_T leader_len;
+ char_u *p;
+ int no_leader = FALSE;
+ int do_comments = (flags & INSCHAR_DO_COM);
+#endif
+ int fo_white_par;
+ int first_line = TRUE;
+ int fo_ins_blank;
+#ifdef FEAT_MBYTE
+ int fo_multibyte;
+#endif
+ int save_char = NUL;
+ int cc;
+
+ textwidth = comp_textwidth(flags & INSCHAR_FORMAT);
+ fo_ins_blank = has_format_option(FO_INS_BLANK);
+#ifdef FEAT_MBYTE
+ fo_multibyte = has_format_option(FO_MBYTE_BREAK);
+#endif
+ fo_white_par = has_format_option(FO_WHITE_PAR);
+
+ /*
+ * Try to break the line in two or more pieces when:
+ * - Always do this if we have been called to do formatting only.
+ * - Always do this when 'formatoptions' has the 'a' flag and the line
+ * ends in white space.
+ * - Otherwise:
+ * - Don't do this if inserting a blank
+ * - Don't do this if an existing character is being replaced, unless
+ * we're in VREPLACE mode.
+ * - Do this if the cursor is not on the line where insert started
+ * or - 'formatoptions' doesn't have 'l' or the line was not too long
+ * before the insert.
+ * - 'formatoptions' doesn't have 'b' or a blank was inserted at or
+ * before 'textwidth'
+ */
+ if (textwidth
+ && ((flags & INSCHAR_FORMAT)
+ || (!vim_iswhite(c)
+ && !((State & REPLACE_FLAG)
+#ifdef FEAT_VREPLACE
+ && !(State & VREPLACE_FLAG)
+#endif
+ && *ml_get_cursor() != NUL)
+ && (curwin->w_cursor.lnum != Insstart.lnum
+ || ((!has_format_option(FO_INS_LONG)
+ || Insstart_textlen <= (colnr_T)textwidth)
+ && (!fo_ins_blank
+ || Insstart_blank_vcol <= (colnr_T)textwidth
+ ))))))
+ {
+ /*
+ * When 'ai' is off we don't want a space under the cursor to be
+ * deleted. Replace it with an 'x' temporarily.
+ */
+ if (!curbuf->b_p_ai)
+ {
+ cc = gchar_cursor();
+ if (vim_iswhite(cc))
+ {
+ save_char = cc;
+ pchar_cursor('x');
+ }
+ }
+
+ /*
+ * Repeat breaking lines, until the current line is not too long.
+ */
+ while (!got_int)
+ {
+ int startcol; /* Cursor column at entry */
+ int wantcol; /* column at textwidth border */
+ int foundcol; /* column for start of spaces */
+ int end_foundcol = 0; /* column for start of word */
+ colnr_T len;
+ colnr_T virtcol;
+#ifdef FEAT_VREPLACE
+ int orig_col = 0;
+ char_u *saved_text = NULL;
+#endif
+ colnr_T col;
+
+ virtcol = get_nolist_virtcol();
+ if (virtcol < (colnr_T)textwidth)
+ break;
+
+#ifdef FEAT_COMMENTS
+ if (no_leader)
+ do_comments = FALSE;
+ else if (!(flags & INSCHAR_FORMAT)
+ && has_format_option(FO_WRAP_COMS))
+ do_comments = TRUE;
+
+ /* Don't break until after the comment leader */
+ if (do_comments)
+ leader_len = get_leader_len(ml_get_curline(), NULL, FALSE);
+ else
+ leader_len = 0;
+
+ /* If the line doesn't start with a comment leader, then don't
+ * start one in a following broken line. Avoids that a %word
+ * moved to the start of the next line causes all following lines
+ * to start with %. */
+ if (leader_len == 0)
+ no_leader = TRUE;
+#endif
+ if (!(flags & INSCHAR_FORMAT)
+#ifdef FEAT_COMMENTS
+ && leader_len == 0
+#endif
+ && !has_format_option(FO_WRAP))
+
+ {
+ textwidth = 0;
+ break;
+ }
+ if ((startcol = curwin->w_cursor.col) == 0)
+ break;
+
+ /* find column of textwidth border */
+ coladvance((colnr_T)textwidth);
+ wantcol = curwin->w_cursor.col;
+
+ curwin->w_cursor.col = startcol - 1;
+#ifdef FEAT_MBYTE
+ /* Correct cursor for multi-byte character. */
+ if (has_mbyte)
+ mb_adjust_cursor();
+#endif
+ foundcol = 0;
+
+ /*
+ * Find position to break at.
+ * Stop at first entered white when 'formatoptions' has 'v'
+ */
+ while ((!fo_ins_blank && !has_format_option(FO_INS_VI))
+ || curwin->w_cursor.lnum != Insstart.lnum
+ || curwin->w_cursor.col >= Insstart.col)
+ {
+ cc = gchar_cursor();
+ if (WHITECHAR(cc))
+ {
+ /* remember position of blank just before text */
+ end_foundcol = curwin->w_cursor.col;
+
+ /* find start of sequence of blanks */
+ while (curwin->w_cursor.col > 0 && WHITECHAR(cc))
+ {
+ dec_cursor();
+ cc = gchar_cursor();
+ }
+ if (curwin->w_cursor.col == 0 && WHITECHAR(cc))
+ break; /* only spaces in front of text */
+#ifdef FEAT_COMMENTS
+ /* Don't break until after the comment leader */
+ if (curwin->w_cursor.col < leader_len)
+ break;
+#endif
+ if (has_format_option(FO_ONE_LETTER))
+ {
+ /* do not break after one-letter words */
+ if (curwin->w_cursor.col == 0)
+ break; /* one-letter word at begin */
+
+ col = curwin->w_cursor.col;
+ dec_cursor();
+ cc = gchar_cursor();
+
+ if (WHITECHAR(cc))
+ continue; /* one-letter, continue */
+ curwin->w_cursor.col = col;
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ foundcol = curwin->w_cursor.col
+ + (*mb_ptr2len_check)(ml_get_cursor());
+ else
+#endif
+ foundcol = curwin->w_cursor.col + 1;
+ if (curwin->w_cursor.col < (colnr_T)wantcol)
+ break;
+ }
+#ifdef FEAT_MBYTE
+ else if (cc >= 0x100 && fo_multibyte
+ && curwin->w_cursor.col <= (colnr_T)wantcol)
+ {
+ /* Break after or before a multi-byte character. */
+ foundcol = curwin->w_cursor.col;
+ if (curwin->w_cursor.col < (colnr_T)wantcol)
+ foundcol += (*mb_char2len)(cc);
+ end_foundcol = foundcol;
+ break;
+ }
+#endif
+ if (curwin->w_cursor.col == 0)
+ break;
+ dec_cursor();
+ }
+
+ if (foundcol == 0) /* no spaces, cannot break line */
+ {
+ curwin->w_cursor.col = startcol;
+ break;
+ }
+
+ /* Going to break the line, remove any "$" now. */
+ undisplay_dollar();
+
+ /*
+ * Offset between cursor position and line break is used by replace
+ * stack functions. VREPLACE does not use this, and backspaces
+ * over the text instead.
+ */
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ orig_col = startcol; /* Will start backspacing from here */
+ else
+#endif
+ replace_offset = startcol - end_foundcol - 1;
+
+ /*
+ * adjust startcol for spaces that will be deleted and
+ * characters that will remain on top line
+ */
+ curwin->w_cursor.col = foundcol;
+ while (cc = gchar_cursor(), WHITECHAR(cc))
+ inc_cursor();
+ startcol -= curwin->w_cursor.col;
+ if (startcol < 0)
+ startcol = 0;
+
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ {
+ /*
+ * In VREPLACE mode, we will backspace over the text to be
+ * wrapped, so save a copy now to put on the next line.
+ */
+ saved_text = vim_strsave(ml_get_cursor());
+ curwin->w_cursor.col = orig_col;
+ if (saved_text == NULL)
+ break; /* Can't do it, out of memory */
+ saved_text[startcol] = NUL;
+
+ /* Backspace over characters that will move to the next line */
+ if (!fo_white_par)
+ backspace_until_column(foundcol);
+ }
+ else
+#endif
+ {
+ /* put cursor after pos. to break line */
+ if (!fo_white_par)
+ curwin->w_cursor.col = foundcol;
+ }
+
+ /*
+ * Split the line just before the margin.
+ * Only insert/delete lines, but don't really redraw the window.
+ */
+ open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX
+ + (fo_white_par ? OPENLINE_KEEPTRAIL : 0)
+#ifdef FEAT_COMMENTS
+ + (do_comments ? OPENLINE_DO_COM : 0)
+#endif
+ , old_indent);
+ old_indent = 0;
+
+ replace_offset = 0;
+ if (first_line)
+ {
+ if (second_indent < 0 && has_format_option(FO_Q_NUMBER))
+ second_indent = get_number_indent(curwin->w_cursor.lnum -1);
+ if (second_indent >= 0)
+ {
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ change_indent(INDENT_SET, second_indent, FALSE, NUL);
+ else
+#endif
+ (void)set_indent(second_indent, SIN_CHANGED);
+ }
+ first_line = FALSE;
+ }
+
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ {
+ /*
+ * In VREPLACE mode we have backspaced over the text to be
+ * moved, now we re-insert it into the new line.
+ */
+ ins_bytes(saved_text);
+ vim_free(saved_text);
+ }
+ else
+#endif
+ {
+ /*
+ * Check if cursor is not past the NUL off the line, cindent
+ * may have added or removed indent.
+ */
+ curwin->w_cursor.col += startcol;
+ len = (colnr_T)STRLEN(ml_get_curline());
+ if (curwin->w_cursor.col > len)
+ curwin->w_cursor.col = len;
+ }
+
+ haveto_redraw = TRUE;
+#ifdef FEAT_CINDENT
+ can_cindent = TRUE;
+#endif
+ /* moved the cursor, don't autoindent or cindent now */
+ did_ai = FALSE;
+#ifdef FEAT_SMARTINDENT
+ did_si = FALSE;
+ can_si = FALSE;
+ can_si_back = FALSE;
+#endif
+ line_breakcheck();
+ }
+
+ if (save_char) /* put back space after cursor */
+ pchar_cursor(save_char);
+
+ if (c == NUL) /* formatting only */
+ return;
+ if (haveto_redraw)
+ {
+ update_topline();
+ redraw_curbuf_later(VALID);
+ }
+ }
+ if (c == NUL) /* only formatting was wanted */
+ return;
+
+#ifdef FEAT_COMMENTS
+ /* Check whether this character should end a comment. */
+ if (did_ai && (int)c == end_comment_pending)
+ {
+ char_u *line;
+ char_u lead_end[COM_MAX_LEN]; /* end-comment string */
+ int middle_len, end_len;
+ int i;
+
+ /*
+ * Need to remove existing (middle) comment leader and insert end
+ * comment leader. First, check what comment leader we can find.
+ */
+ i = get_leader_len(line = ml_get_curline(), &p, FALSE);
+ if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL) /* Just checking */
+ {
+ /* Skip middle-comment string */
+ while (*p && p[-1] != ':') /* find end of middle flags */
+ ++p;
+ middle_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
+ /* Don't count trailing white space for middle_len */
+ while (middle_len > 0 && vim_iswhite(lead_end[middle_len - 1]))
+ --middle_len;
+
+ /* Find the end-comment string */
+ while (*p && p[-1] != ':') /* find end of end flags */
+ ++p;
+ end_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
+
+ /* Skip white space before the cursor */
+ i = curwin->w_cursor.col;
+ while (--i >= 0 && vim_iswhite(line[i]))
+ ;
+ i++;
+
+ /* Skip to before the middle leader */
+ i -= middle_len;
+
+ /* Check some expected things before we go on */
+ if (i >= 0 && lead_end[end_len - 1] == end_comment_pending)
+ {
+ /* Backspace over all the stuff we want to replace */
+ backspace_until_column(i);
+
+ /*
+ * Insert the end-comment string, except for the last
+ * character, which will get inserted as normal later.
+ */
+ ins_bytes_len(lead_end, end_len - 1);
+ }
+ }
+ }
+ end_comment_pending = NUL;
+#endif
+
+ did_ai = FALSE;
+#ifdef FEAT_SMARTINDENT
+ did_si = FALSE;
+ can_si = FALSE;
+ can_si_back = FALSE;
+#endif
+
+ /*
+ * If there's any pending input, grab up to INPUT_BUFLEN at once.
+ * This speeds up normal text input considerably.
+ * Don't do this when 'cindent' or 'indentexpr' is set, because we might
+ * need to re-indent at a ':', or any other character (but not what
+ * 'paste' is set)..
+ */
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = FALSE; /* allow scrolling here */
+#endif
+
+ if ( !ISSPECIAL(c)
+#ifdef FEAT_MBYTE
+ && (!has_mbyte || (*mb_char2len)(c) == 1)
+#endif
+ && vpeekc() != NUL
+ && !(State & REPLACE_FLAG)
+#ifdef FEAT_CINDENT
+ && !cindent_on()
+#endif
+#ifdef FEAT_RIGHTLEFT
+ && !p_ri
+#endif
+ )
+ {
+#define INPUT_BUFLEN 100
+ char_u buf[INPUT_BUFLEN + 1];
+ int i;
+ colnr_T virtcol = 0;
+
+ buf[0] = c;
+ i = 1;
+ if (textwidth)
+ virtcol = get_nolist_virtcol();
+ /*
+ * Stop the string when:
+ * - no more chars available
+ * - finding a special character (command key)
+ * - buffer is full
+ * - running into the 'textwidth' boundary
+ * - need to check for abbreviation: A non-word char after a word-char
+ */
+ while ( (c = vpeekc()) != NUL
+ && !ISSPECIAL(c)
+#ifdef FEAT_MBYTE
+ && (!has_mbyte || MB_BYTE2LEN_CHECK(c) == 1)
+#endif
+ && i < INPUT_BUFLEN
+ && (textwidth == 0
+ || (virtcol += byte2cells(buf[i - 1])) < (colnr_T)textwidth)
+ && !(!no_abbr && !vim_iswordc(c) && vim_iswordc(buf[i - 1])))
+ {
+#ifdef FEAT_RIGHTLEFT
+ c = vgetc();
+ if (p_hkmap && KeyTyped)
+ c = hkmap(c); /* Hebrew mode mapping */
+# ifdef FEAT_FKMAP
+ if (p_fkmap && KeyTyped)
+ c = fkmap(c); /* Farsi mode mapping */
+# endif
+ buf[i++] = c;
+#else
+ buf[i++] = vgetc();
+#endif
+ }
+
+#ifdef FEAT_DIGRAPHS
+ do_digraph(-1); /* clear digraphs */
+ do_digraph(buf[i-1]); /* may be the start of a digraph */
+#endif
+ buf[i] = NUL;
+ ins_str(buf);
+ if (flags & INSCHAR_CTRLV)
+ {
+ redo_literal(*buf);
+ i = 1;
+ }
+ else
+ i = 0;
+ if (buf[i] != NUL)
+ AppendToRedobuffLit(buf + i);
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (cc = (*mb_char2len)(c)) > 1)
+ {
+ char_u buf[MB_MAXBYTES + 1];
+
+ (*mb_char2bytes)(c, buf);
+ buf[cc] = NUL;
+ ins_char_bytes(buf, cc);
+ AppendCharToRedobuff(c);
+ }
+ else
+#endif
+ {
+ ins_char(c);
+ if (flags & INSCHAR_CTRLV)
+ redo_literal(c);
+ else
+ AppendCharToRedobuff(c);
+ }
+ }
+}
+
+/*
+ * Called after inserting or deleting text: When 'formatoptions' includes the
+ * 'a' flag format from the current line until the end of the paragraph.
+ * Keep the cursor at the same position relative to the text.
+ * The caller must have saved the cursor line for undo, following ones will be
+ * saved here.
+ */
+ void
+auto_format(trailblank, prev_line)
+ int trailblank; /* when TRUE also format with trailing blank */
+ int prev_line; /* may start in previous line */
+{
+ pos_T pos;
+ colnr_T len;
+ char_u *old;
+ char_u *new, *pnew;
+ int wasatend;
+
+ if (!has_format_option(FO_AUTO))
+ return;
+
+ pos = curwin->w_cursor;
+ old = ml_get_curline();
+
+ /* may remove added space */
+ check_auto_format(FALSE);
+
+ /* Don't format in Insert mode when the cursor is on a trailing blank, the
+ * user might insert normal text next. Also skip formatting when "1" is
+ * in 'formatoptions' and there is a single character before the cursor.
+ * Otherwise the line would be broken and when typing another non-white
+ * next they are not joined back together. */
+ wasatend = (pos.col == STRLEN(old));
+ if (*old != NUL && !trailblank && wasatend)
+ {
+ dec_cursor();
+ if (!WHITECHAR(gchar_cursor())
+ && curwin->w_cursor.col > 0
+ && has_format_option(FO_ONE_LETTER))
+ dec_cursor();
+ if (WHITECHAR(gchar_cursor()))
+ {
+ curwin->w_cursor = pos;
+ return;
+ }
+ curwin->w_cursor = pos;
+ }
+
+#ifdef FEAT_COMMENTS
+ /* With the 'c' flag in 'formatoptions' and 't' missing: only format
+ * comments. */
+ if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP)
+ && get_leader_len(old, NULL, FALSE) == 0)
+ return;
+#endif
+
+ /*
+ * May start formatting in a previous line, so that after "x" a word is
+ * moved to the previous line if it fits there now. Only when this is not
+ * the start of a paragraph.
+ */
+ if (prev_line && !paragraph_start(curwin->w_cursor.lnum))
+ {
+ --curwin->w_cursor.lnum;
+ if (u_save_cursor() == FAIL)
+ return;
+ }
+
+ /*
+ * Do the formatting and restore the cursor position. "saved_cursor" will
+ * be adjusted for the text formatting.
+ */
+ saved_cursor = pos;
+ format_lines((linenr_T)-1);
+ curwin->w_cursor = saved_cursor;
+ saved_cursor.lnum = 0;
+
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
+ {
+ /* "cannot happen" */
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ coladvance((colnr_T)MAXCOL);
+ }
+ else
+ check_cursor_col();
+
+ /* Insert mode: If the cursor is now after the end of the line while it
+ * previously wasn't, the line was broken. Because of the rule above we
+ * need to add a space when 'w' is in 'formatoptions' to keep a paragraph
+ * formatted. */
+ if (!wasatend && has_format_option(FO_WHITE_PAR))
+ {
+ new = ml_get_curline();
+ len = STRLEN(new);
+ if (curwin->w_cursor.col == len)
+ {
+ pnew = vim_strnsave(new, len + 2);
+ pnew[len] = ' ';
+ pnew[len + 1] = NUL;
+ ml_replace(curwin->w_cursor.lnum, pnew, FALSE);
+ /* remove the space later */
+ did_add_space = TRUE;
+ }
+ else
+ /* may remove added space */
+ check_auto_format(FALSE);
+ }
+
+ check_cursor();
+}
+
+/*
+ * When an extra space was added to continue a paragraph for auto-formatting,
+ * delete it now. The space must be under the cursor, just after the insert
+ * position.
+ */
+ static void
+check_auto_format(end_insert)
+ int end_insert; /* TRUE when ending Insert mode */
+{
+ int c = ' ';
+
+ if (did_add_space)
+ {
+ if (!WHITECHAR(gchar_cursor()))
+ /* Somehow the space was removed already. */
+ did_add_space = FALSE;
+ else
+ {
+ if (!end_insert)
+ {
+ inc_cursor();
+ c = gchar_cursor();
+ dec_cursor();
+ }
+ if (c != NUL)
+ {
+ /* The space is no longer at the end of the line, delete it. */
+ del_char(FALSE);
+ did_add_space = FALSE;
+ }
+ }
+ }
+}
+
+/*
+ * Find out textwidth to be used for formatting:
+ * if 'textwidth' option is set, use it
+ * else if 'wrapmargin' option is set, use W_WIDTH(curwin) - 'wrapmargin'
+ * if invalid value, use 0.
+ * Set default to window width (maximum 79) for "gq" operator.
+ */
+ int
+comp_textwidth(ff)
+ int ff; /* force formatting (for "Q" command) */
+{
+ int textwidth;
+
+ textwidth = curbuf->b_p_tw;
+ if (textwidth == 0 && curbuf->b_p_wm)
+ {
+ /* The width is the window width minus 'wrapmargin' minus all the
+ * things that add to the margin. */
+ textwidth = W_WIDTH(curwin) - curbuf->b_p_wm;
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ textwidth -= 1;
+#endif
+#ifdef FEAT_FOLDING
+ textwidth -= curwin->w_p_fdc;
+#endif
+#ifdef FEAT_SIGNS
+ if (curwin->w_buffer->b_signlist != NULL
+# ifdef FEAT_NETBEANS_INTG
+ || usingNetbeans
+# endif
+ )
+ textwidth -= 1;
+#endif
+ if (curwin->w_p_nu)
+ textwidth -= 8;
+ }
+ if (textwidth < 0)
+ textwidth = 0;
+ if (ff && textwidth == 0)
+ {
+ textwidth = W_WIDTH(curwin) - 1;
+ if (textwidth > 79)
+ textwidth = 79;
+ }
+ return textwidth;
+}
+
+/*
+ * Put a character in the redo buffer, for when just after a CTRL-V.
+ */
+ static void
+redo_literal(c)
+ int c;
+{
+ char_u buf[10];
+
+ /* Only digits need special treatment. Translate them into a string of
+ * three digits. */
+ if (VIM_ISDIGIT(c))
+ {
+ sprintf((char *)buf, "%03d", c);
+ AppendToRedobuff(buf);
+ }
+ else
+ AppendCharToRedobuff(c);
+}
+
+/*
+ * start_arrow() is called when an arrow key is used in insert mode.
+ * It resembles hitting the <ESC> key.
+ */
+ static void
+start_arrow(end_insert_pos)
+ pos_T *end_insert_pos;
+{
+ if (!arrow_used) /* something has been inserted */
+ {
+ AppendToRedobuff(ESC_STR);
+ stop_insert(end_insert_pos, FALSE);
+ arrow_used = TRUE; /* this means we stopped the current insert */
+ }
+}
+
+/*
+ * stop_arrow() is called before a change is made in insert mode.
+ * If an arrow key has been used, start a new insertion.
+ * Returns FAIL if undo is impossible, shouldn't insert then.
+ */
+ int
+stop_arrow()
+{
+ if (arrow_used)
+ {
+ if (u_save_cursor() == OK)
+ {
+ arrow_used = FALSE;
+ ins_need_undo = FALSE;
+ }
+ Insstart = curwin->w_cursor; /* new insertion starts here */
+ Insstart_textlen = linetabsize(ml_get_curline());
+ ai_col = 0;
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ {
+ orig_line_count = curbuf->b_ml.ml_line_count;
+ vr_lines_changed = 1;
+ }
+#endif
+ ResetRedobuff();
+ AppendToRedobuff((char_u *)"1i"); /* pretend we start an insertion */
+ }
+ else if (ins_need_undo)
+ {
+ if (u_save_cursor() == OK)
+ ins_need_undo = FALSE;
+ }
+
+#ifdef FEAT_FOLDING
+ /* Always open fold at the cursor line when inserting something. */
+ foldOpenCursor();
+#endif
+
+ return (arrow_used || ins_need_undo ? FAIL : OK);
+}
+
+/*
+ * do a few things to stop inserting
+ */
+ static void
+stop_insert(end_insert_pos, esc)
+ pos_T *end_insert_pos; /* where insert ended */
+ int esc; /* called by ins_esc() */
+{
+ int cc;
+
+ stop_redo_ins();
+ replace_flush(); /* abandon replace stack */
+
+ /*
+ * save the inserted text for later redo with ^@
+ */
+ vim_free(last_insert);
+ last_insert = get_inserted();
+ last_insert_skip = new_insert_skip;
+
+ if (!arrow_used)
+ {
+ /* Auto-format now. It may seem strange to do this when stopping an
+ * insertion (or moving the cursor), but it's required when appending
+ * a line and having it end in a space. But only do it when something
+ * was actually inserted, otherwise undo won't work. */
+ if (!ins_need_undo)
+ {
+ /* When the cursor is at the end of the line after a space the
+ * formatting will move it to the following word. Avoid that by
+ * moving the cursor onto the space. */
+ cc = 'x';
+ if (curwin->w_cursor.col > 0 && gchar_cursor() == NUL)
+ {
+ dec_cursor();
+ cc = gchar_cursor();
+ if (!vim_iswhite(cc))
+ inc_cursor();
+ }
+
+ auto_format(TRUE, FALSE);
+
+ if (vim_iswhite(cc) && gchar_cursor() != NUL)
+ inc_cursor();
+ }
+
+ /* If a space was inserted for auto-formatting, remove it now. */
+ check_auto_format(TRUE);
+
+ /* If we just did an auto-indent, remove the white space from the end
+ * of the line, and put the cursor back. */
+ if (did_ai && esc)
+ {
+ if (gchar_cursor() == NUL && curwin->w_cursor.col > 0)
+ --curwin->w_cursor.col;
+ while (cc = gchar_cursor(), vim_iswhite(cc))
+ (void)del_char(TRUE);
+ if (cc != NUL)
+ ++curwin->w_cursor.col; /* put cursor back on the NUL */
+
+#ifdef FEAT_VISUAL
+ /* <C-S-Right> may have started Visual mode, adjust the position for
+ * deleted characters. */
+ if (VIsual_active && VIsual.lnum == curwin->w_cursor.lnum)
+ {
+ cc = STRLEN(ml_get_curline());
+ if (VIsual.col > (colnr_T)cc)
+ {
+ VIsual.col = cc;
+# ifdef FEAT_VIRTUALEDIT
+ VIsual.coladd = 0;
+# endif
+ }
+ }
+#endif
+ }
+ }
+ did_ai = FALSE;
+#ifdef FEAT_SMARTINDENT
+ did_si = FALSE;
+ can_si = FALSE;
+ can_si_back = FALSE;
+#endif
+
+ /* set '[ and '] to the inserted text */
+ curbuf->b_op_start = Insstart;
+ curbuf->b_op_end = *end_insert_pos;
+}
+
+/*
+ * Set the last inserted text to a single character.
+ * Used for the replace command.
+ */
+ void
+set_last_insert(c)
+ int c;
+{
+ char_u *s;
+
+ vim_free(last_insert);
+#ifdef FEAT_MBYTE
+ last_insert = alloc(MB_MAXBYTES * 3 + 5);
+#else
+ last_insert = alloc(6);
+#endif
+ if (last_insert != NULL)
+ {
+ s = last_insert;
+ /* Use the CTRL-V only when entering a special char */
+ if (c < ' ' || c == DEL)
+ *s++ = Ctrl_V;
+ s = add_char2buf(c, s);
+ *s++ = ESC;
+ *s++ = NUL;
+ last_insert_skip = 0;
+ }
+}
+
+/*
+ * Add character "c" to buffer "s". Escape the special meaning of K_SPECIAL
+ * and CSI. Handle multi-byte characters.
+ * Returns a pointer to after the added bytes.
+ */
+ char_u *
+add_char2buf(c, s)
+ int c;
+ char_u *s;
+{
+#ifdef FEAT_MBYTE
+ char_u temp[MB_MAXBYTES];
+ int i;
+ int len;
+
+ len = (*mb_char2bytes)(c, temp);
+ for (i = 0; i < len; ++i)
+ {
+ c = temp[i];
+#endif
+ /* Need to escape K_SPECIAL and CSI like in the typeahead buffer. */
+ if (c == K_SPECIAL)
+ {
+ *s++ = K_SPECIAL;
+ *s++ = KS_SPECIAL;
+ *s++ = KE_FILLER;
+ }
+#ifdef FEAT_GUI
+ else if (c == CSI)
+ {
+ *s++ = CSI;
+ *s++ = KS_EXTRA;
+ *s++ = (int)KE_CSI;
+ }
+#endif
+ else
+ *s++ = c;
+#ifdef FEAT_MBYTE
+ }
+#endif
+ return s;
+}
+
+/*
+ * move cursor to start of line
+ * if flags & BL_WHITE move to first non-white
+ * if flags & BL_SOL move to first non-white if startofline is set,
+ * otherwise keep "curswant" column
+ * if flags & BL_FIX don't leave the cursor on a NUL.
+ */
+ void
+beginline(flags)
+ int flags;
+{
+ if ((flags & BL_SOL) && !p_sol)
+ coladvance(curwin->w_curswant);
+ else
+ {
+ curwin->w_cursor.col = 0;
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+
+ if (flags & (BL_WHITE | BL_SOL))
+ {
+ char_u *ptr;
+
+ for (ptr = ml_get_curline(); vim_iswhite(*ptr)
+ && !((flags & BL_FIX) && ptr[1] == NUL); ++ptr)
+ ++curwin->w_cursor.col;
+ }
+ curwin->w_set_curswant = TRUE;
+ }
+}
+
+/*
+ * oneright oneleft cursor_down cursor_up
+ *
+ * Move one char {right,left,down,up}.
+ * Doesn't move onto the NUL past the end of the line.
+ * Return OK when successful, FAIL when we hit a line of file boundary.
+ */
+
+ int
+oneright()
+{
+ char_u *ptr;
+#ifdef FEAT_MBYTE
+ int l;
+#endif
+
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_active())
+ {
+ pos_T prevpos = curwin->w_cursor;
+
+ /* Adjust for multi-wide char (excluding TAB) */
+ ptr = ml_get_cursor();
+ coladvance(getviscol() + ((*ptr != TAB && vim_isprintc(
+#ifdef FEAT_MBYTE
+ (*mb_ptr2char)(ptr)
+#else
+ *ptr
+#endif
+ ))
+ ? ptr2cells(ptr) : 1));
+ curwin->w_set_curswant = TRUE;
+ /* Return OK if the cursor moved, FAIL otherwise (at window edge). */
+ return (prevpos.col != curwin->w_cursor.col
+ || prevpos.coladd != curwin->w_cursor.coladd) ? OK : FAIL;
+ }
+#endif
+
+ ptr = ml_get_cursor();
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (l = (*mb_ptr2len_check)(ptr)) > 1)
+ {
+ /* The character under the cursor is a multi-byte character, move
+ * several bytes right, but don't end up on the NUL. */
+ if (ptr[l] == NUL)
+ return FAIL;
+ curwin->w_cursor.col += l;
+ }
+ else
+#endif
+ {
+ if (*ptr++ == NUL || *ptr == NUL)
+ return FAIL;
+ ++curwin->w_cursor.col;
+ }
+
+ curwin->w_set_curswant = TRUE;
+ return OK;
+}
+
+ int
+oneleft()
+{
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_active())
+ {
+ int width;
+ int v = getviscol();
+
+ if (v == 0)
+ return FAIL;
+
+# ifdef FEAT_LINEBREAK
+ /* We might get stuck on 'showbreak', skip over it. */
+ width = 1;
+ for (;;)
+ {
+ coladvance(v - width);
+ /* getviscol() is slow, skip it when 'showbreak' is empty and
+ * there are no multi-byte characters */
+ if ((*p_sbr == NUL
+# ifdef FEAT_MBYTE
+ && !has_mbyte
+# endif
+ ) || getviscol() < v)
+ break;
+ ++width;
+ }
+# else
+ coladvance(v - 1);
+# endif
+
+ if (curwin->w_cursor.coladd == 1)
+ {
+ char_u *ptr;
+
+ /* Adjust for multi-wide char (not a TAB) */
+ ptr = ml_get_cursor();
+ if (*ptr != TAB && vim_isprintc(
+# ifdef FEAT_MBYTE
+ (*mb_ptr2char)(ptr)
+# else
+ *ptr
+# endif
+ ) && ptr2cells(ptr) > 1)
+ curwin->w_cursor.coladd = 0;
+ }
+
+ curwin->w_set_curswant = TRUE;
+ return OK;
+ }
+#endif
+
+ if (curwin->w_cursor.col == 0)
+ return FAIL;
+
+ curwin->w_set_curswant = TRUE;
+ --curwin->w_cursor.col;
+
+#ifdef FEAT_MBYTE
+ /* if the character on the left of the current cursor is a multi-byte
+ * character, move to its first byte */
+ if (has_mbyte)
+ mb_adjust_cursor();
+#endif
+ return OK;
+}
+
+ int
+cursor_up(n, upd_topline)
+ long n;
+ int upd_topline; /* When TRUE: update topline */
+{
+ linenr_T lnum;
+
+ if (n > 0)
+ {
+ lnum = curwin->w_cursor.lnum;
+ if (lnum <= 1)
+ return FAIL;
+ if (n >= lnum)
+ lnum = 1;
+ else
+#ifdef FEAT_FOLDING
+ if (hasAnyFolding(curwin))
+ {
+ /*
+ * Count each sequence of folded lines as one logical line.
+ */
+ /* go to the the start of the current fold */
+ (void)hasFolding(lnum, &lnum, NULL);
+
+ while (n--)
+ {
+ /* move up one line */
+ --lnum;
+ if (lnum <= 1)
+ break;
+ /* If we entered a fold, move to the beginning, unless in
+ * Insert mode or when 'foldopen' contains "all": it will open
+ * in a moment. */
+ if (n > 0 || !((State & INSERT) || (fdo_flags & FDO_ALL)))
+ (void)hasFolding(lnum, &lnum, NULL);
+ }
+ if (lnum < 1)
+ lnum = 1;
+ }
+ else
+#endif
+ lnum -= n;
+ curwin->w_cursor.lnum = lnum;
+ }
+
+ /* try to advance to the column we want to be at */
+ coladvance(curwin->w_curswant);
+
+ if (upd_topline)
+ update_topline(); /* make sure curwin->w_topline is valid */
+
+ return OK;
+}
+
+/*
+ * Cursor down a number of logical lines.
+ */
+ int
+cursor_down(n, upd_topline)
+ long n;
+ int upd_topline; /* When TRUE: update topline */
+{
+ linenr_T lnum;
+
+ if (n > 0)
+ {
+ lnum = curwin->w_cursor.lnum;
+#ifdef FEAT_FOLDING
+ /* Move to last line of fold, will fail if it's the end-of-file. */
+ (void)hasFolding(lnum, NULL, &lnum);
+#endif
+ if (lnum >= curbuf->b_ml.ml_line_count)
+ return FAIL;
+ if (lnum + n >= curbuf->b_ml.ml_line_count)
+ lnum = curbuf->b_ml.ml_line_count;
+ else
+#ifdef FEAT_FOLDING
+ if (hasAnyFolding(curwin))
+ {
+ linenr_T last;
+
+ /* count each sequence of folded lines as one logical line */
+ while (n--)
+ {
+ if (hasFolding(lnum, NULL, &last))
+ lnum = last + 1;
+ else
+ ++lnum;
+ if (lnum >= curbuf->b_ml.ml_line_count)
+ break;
+ }
+ if (lnum > curbuf->b_ml.ml_line_count)
+ lnum = curbuf->b_ml.ml_line_count;
+ }
+ else
+#endif
+ lnum += n;
+ curwin->w_cursor.lnum = lnum;
+ }
+
+ /* try to advance to the column we want to be at */
+ coladvance(curwin->w_curswant);
+
+ if (upd_topline)
+ update_topline(); /* make sure curwin->w_topline is valid */
+
+ return OK;
+}
+
+/*
+ * Stuff the last inserted text in the read buffer.
+ * Last_insert actually is a copy of the redo buffer, so we
+ * first have to remove the command.
+ */
+ int
+stuff_inserted(c, count, no_esc)
+ int c; /* Command character to be inserted */
+ long count; /* Repeat this many times */
+ int no_esc; /* Don't add an ESC at the end */
+{
+ char_u *esc_ptr;
+ char_u *ptr;
+ char_u *last_ptr;
+ char_u last = NUL;
+
+ ptr = get_last_insert();
+ if (ptr == NULL)
+ {
+ EMSG(_(e_noinstext));
+ return FAIL;
+ }
+
+ /* may want to stuff the command character, to start Insert mode */
+ if (c != NUL)
+ stuffcharReadbuff(c);
+ if ((esc_ptr = (char_u *)vim_strrchr(ptr, ESC)) != NULL)
+ *esc_ptr = NUL; /* remove the ESC */
+
+ /* when the last char is either "0" or "^" it will be quoted if no ESC
+ * comes after it OR if it will inserted more than once and "ptr"
+ * starts with ^D. -- Acevedo
+ */
+ last_ptr = (esc_ptr ? esc_ptr : ptr + STRLEN(ptr)) - 1;
+ if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^')
+ && (no_esc || (*ptr == Ctrl_D && count > 1)))
+ {
+ last = *last_ptr;
+ *last_ptr = NUL;
+ }
+
+ do
+ {
+ stuffReadbuff(ptr);
+ /* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */
+ if (last)
+ stuffReadbuff((char_u *)(last == '0'
+ ? IF_EB("\026\060\064\070", CTRL_V_STR "xf0")
+ : IF_EB("\026^", CTRL_V_STR "^")));
+ }
+ while (--count > 0);
+
+ if (last)
+ *last_ptr = last;
+
+ if (esc_ptr != NULL)
+ *esc_ptr = ESC; /* put the ESC back */
+
+ /* may want to stuff a trailing ESC, to get out of Insert mode */
+ if (!no_esc)
+ stuffcharReadbuff(ESC);
+
+ return OK;
+}
+
+ char_u *
+get_last_insert()
+{
+ if (last_insert == NULL)
+ return NULL;
+ return last_insert + last_insert_skip;
+}
+
+/*
+ * Get last inserted string, and remove trailing <Esc>.
+ * Returns pointer to allocated memory (must be freed) or NULL.
+ */
+ char_u *
+get_last_insert_save()
+{
+ char_u *s;
+ int len;
+
+ if (last_insert == NULL)
+ return NULL;
+ s = vim_strsave(last_insert + last_insert_skip);
+ if (s != NULL)
+ {
+ len = (int)STRLEN(s);
+ if (len > 0 && s[len - 1] == ESC) /* remove trailing ESC */
+ s[len - 1] = NUL;
+ }
+ return s;
+}
+
+/*
+ * Check the word in front of the cursor for an abbreviation.
+ * Called when the non-id character "c" has been entered.
+ * When an abbreviation is recognized it is removed from the text and
+ * the replacement string is inserted in typebuf.tb_buf[], followed by "c".
+ */
+ static int
+echeck_abbr(c)
+ int c;
+{
+ /* Don't check for abbreviation in paste mode, when disabled and just
+ * after moving around with cursor keys. */
+ if (p_paste || no_abbr || arrow_used)
+ return FALSE;
+
+ return check_abbr(c, ml_get_curline(), curwin->w_cursor.col,
+ curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0);
+}
+
+/*
+ * replace-stack functions
+ *
+ * When replacing characters, the replaced characters are remembered for each
+ * new character. This is used to re-insert the old text when backspacing.
+ *
+ * There is a NUL headed list of characters for each character that is
+ * currently in the file after the insertion point. When BS is used, one NUL
+ * headed list is put back for the deleted character.
+ *
+ * For a newline, there are two NUL headed lists. One contains the characters
+ * that the NL replaced. The extra one stores the characters after the cursor
+ * that were deleted (always white space).
+ *
+ * Replace_offset is normally 0, in which case replace_push will add a new
+ * character at the end of the stack. If replace_offset is not 0, that many
+ * characters will be left on the stack above the newly inserted character.
+ */
+
+char_u *replace_stack = NULL;
+long replace_stack_nr = 0; /* next entry in replace stack */
+long replace_stack_len = 0; /* max. number of entries */
+
+ void
+replace_push(c)
+ int c; /* character that is replaced (NUL is none) */
+{
+ char_u *p;
+
+ if (replace_stack_nr < replace_offset) /* nothing to do */
+ return;
+ if (replace_stack_len <= replace_stack_nr)
+ {
+ replace_stack_len += 50;
+ p = lalloc(sizeof(char_u) * replace_stack_len, TRUE);
+ if (p == NULL) /* out of memory */
+ {
+ replace_stack_len -= 50;
+ return;
+ }
+ if (replace_stack != NULL)
+ {
+ mch_memmove(p, replace_stack,
+ (size_t)(replace_stack_nr * sizeof(char_u)));
+ vim_free(replace_stack);
+ }
+ replace_stack = p;
+ }
+ p = replace_stack + replace_stack_nr - replace_offset;
+ if (replace_offset)
+ mch_memmove(p + 1, p, (size_t)(replace_offset * sizeof(char_u)));
+ *p = c;
+ ++replace_stack_nr;
+}
+
+/*
+ * call replace_push(c) with replace_offset set to the first NUL.
+ */
+ static void
+replace_push_off(c)
+ int c;
+{
+ char_u *p;
+
+ p = replace_stack + replace_stack_nr;
+ for (replace_offset = 1; replace_offset < replace_stack_nr;
+ ++replace_offset)
+ if (*--p == NUL)
+ break;
+ replace_push(c);
+ replace_offset = 0;
+}
+
+/*
+ * Pop one item from the replace stack.
+ * return -1 if stack empty
+ * return replaced character or NUL otherwise
+ */
+ static int
+replace_pop()
+{
+ if (replace_stack_nr == 0)
+ return -1;
+ return (int)replace_stack[--replace_stack_nr];
+}
+
+/*
+ * Join the top two items on the replace stack. This removes to "off"'th NUL
+ * encountered.
+ */
+ static void
+replace_join(off)
+ int off; /* offset for which NUL to remove */
+{
+ int i;
+
+ for (i = replace_stack_nr; --i >= 0; )
+ if (replace_stack[i] == NUL && off-- <= 0)
+ {
+ --replace_stack_nr;
+ mch_memmove(replace_stack + i, replace_stack + i + 1,
+ (size_t)(replace_stack_nr - i));
+ return;
+ }
+}
+
+/*
+ * Pop bytes from the replace stack until a NUL is found, and insert them
+ * before the cursor. Can only be used in REPLACE or VREPLACE mode.
+ */
+ static void
+replace_pop_ins()
+{
+ int cc;
+ int oldState = State;
+
+ State = NORMAL; /* don't want REPLACE here */
+ while ((cc = replace_pop()) > 0)
+ {
+#ifdef FEAT_MBYTE
+ mb_replace_pop_ins(cc);
+#else
+ ins_char(cc);
+#endif
+ dec_cursor();
+ }
+ State = oldState;
+}
+
+#ifdef FEAT_MBYTE
+/*
+ * Insert bytes popped from the replace stack. "cc" is the first byte. If it
+ * indicates a multi-byte char, pop the other bytes too.
+ */
+ static void
+mb_replace_pop_ins(cc)
+ int cc;
+{
+ int n;
+ char_u buf[MB_MAXBYTES];
+ int i;
+ int c;
+
+ if (has_mbyte && (n = MB_BYTE2LEN(cc)) > 1)
+ {
+ buf[0] = cc;
+ for (i = 1; i < n; ++i)
+ buf[i] = replace_pop();
+ ins_bytes_len(buf, n);
+ }
+ else
+ ins_char(cc);
+
+ if (enc_utf8)
+ /* Handle composing chars. */
+ for (;;)
+ {
+ c = replace_pop();
+ if (c == -1) /* stack empty */
+ break;
+ if ((n = MB_BYTE2LEN(c)) == 1)
+ {
+ /* Not a multi-byte char, put it back. */
+ replace_push(c);
+ break;
+ }
+ else
+ {
+ buf[0] = c;
+ for (i = 1; i < n; ++i)
+ buf[i] = replace_pop();
+ if (utf_iscomposing(utf_ptr2char(buf)))
+ ins_bytes_len(buf, n);
+ else
+ {
+ /* Not a composing char, put it back. */
+ for (i = n - 1; i >= 0; --i)
+ replace_push(buf[i]);
+ break;
+ }
+ }
+ }
+}
+#endif
+
+/*
+ * make the replace stack empty
+ * (called when exiting replace mode)
+ */
+ static void
+replace_flush()
+{
+ vim_free(replace_stack);
+ replace_stack = NULL;
+ replace_stack_len = 0;
+ replace_stack_nr = 0;
+}
+
+/*
+ * Handle doing a BS for one character.
+ * cc < 0: replace stack empty, just move cursor
+ * cc == 0: character was inserted, delete it
+ * cc > 0: character was replaced, put cc (first byte of original char) back
+ * and check for more characters to be put back
+ */
+ static void
+replace_do_bs()
+{
+ int cc;
+#ifdef FEAT_VREPLACE
+ int orig_len = 0;
+ int ins_len;
+ int orig_vcols = 0;
+ colnr_T start_vcol;
+ char_u *p;
+ int i;
+ int vcol;
+#endif
+
+ cc = replace_pop();
+ if (cc > 0)
+ {
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ {
+ /* Get the number of screen cells used by the character we are
+ * going to delete. */
+ getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
+ orig_vcols = chartabsize(ml_get_cursor(), start_vcol);
+ }
+#endif
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ del_char(FALSE);
+# ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ orig_len = STRLEN(ml_get_cursor());
+# endif
+ replace_push(cc);
+ }
+ else
+#endif
+ {
+ pchar_cursor(cc);
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ orig_len = STRLEN(ml_get_cursor()) - 1;
+#endif
+ }
+ replace_pop_ins();
+
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ {
+ /* Get the number of screen cells used by the inserted characters */
+ p = ml_get_cursor();
+ ins_len = STRLEN(p) - orig_len;
+ vcol = start_vcol;
+ for (i = 0; i < ins_len; ++i)
+ {
+ vcol += chartabsize(p + i, vcol);
+#ifdef FEAT_MBYTE
+ i += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ vcol -= start_vcol;
+
+ /* Delete spaces that were inserted after the cursor to keep the
+ * text aligned. */
+ curwin->w_cursor.col += ins_len;
+ while (vcol > orig_vcols && gchar_cursor() == ' ')
+ {
+ del_char(FALSE);
+ ++orig_vcols;
+ }
+ curwin->w_cursor.col -= ins_len;
+ }
+#endif
+
+ /* mark the buffer as changed and prepare for displaying */
+ changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
+ }
+ else if (cc == 0)
+ (void)del_char(FALSE);
+}
+
+#ifdef FEAT_CINDENT
+/*
+ * Return TRUE if C-indenting is on.
+ */
+ static int
+cindent_on()
+{
+ return (!p_paste && (curbuf->b_p_cin
+# ifdef FEAT_EVAL
+ || *curbuf->b_p_inde != NUL
+# endif
+ ));
+}
+#endif
+
+#if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(PROTO)
+/*
+ * Re-indent the current line, based on the current contents of it and the
+ * surrounding lines. Fixing the cursor position seems really easy -- I'm very
+ * confused what all the part that handles Control-T is doing that I'm not.
+ * "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent.
+ */
+
+ void
+fixthisline(get_the_indent)
+ int (*get_the_indent) __ARGS((void));
+{
+ change_indent(INDENT_SET, get_the_indent(), FALSE, 0);
+ if (linewhite(curwin->w_cursor.lnum))
+ did_ai = TRUE; /* delete the indent if the line stays empty */
+}
+
+ void
+fix_indent()
+{
+ if (p_paste)
+ return;
+# ifdef FEAT_LISP
+ if (curbuf->b_p_lisp && curbuf->b_p_ai)
+ fixthisline(get_lisp_indent);
+# endif
+# if defined(FEAT_LISP) && defined(FEAT_CINDENT)
+ else
+# endif
+# ifdef FEAT_CINDENT
+ if (cindent_on())
+ do_c_expr_indent();
+# endif
+}
+
+#endif
+
+#ifdef FEAT_CINDENT
+/*
+ * return TRUE if 'cinkeys' contains the key "keytyped",
+ * when == '*': Only if key is preceded with '*' (indent before insert)
+ * when == '!': Only if key is prededed with '!' (don't insert)
+ * when == ' ': Only if key is not preceded with '*'(indent afterwards)
+ *
+ * "keytyped" can have a few special values:
+ * KEY_OPEN_FORW
+ * KEY_OPEN_BACK
+ * KEY_COMPLETE just finished completion.
+ *
+ * If line_is_empty is TRUE accept keys with '0' before them.
+ */
+ int
+in_cinkeys(keytyped, when, line_is_empty)
+ int keytyped;
+ int when;
+ int line_is_empty;
+{
+ char_u *look;
+ int try_match;
+ int try_match_word;
+ char_u *p;
+ char_u *line;
+ int icase;
+ int i;
+
+#ifdef FEAT_EVAL
+ if (*curbuf->b_p_inde != NUL)
+ look = curbuf->b_p_indk; /* 'indentexpr' set: use 'indentkeys' */
+ else
+#endif
+ look = curbuf->b_p_cink; /* 'indentexpr' empty: use 'cinkeys' */
+ while (*look)
+ {
+ /*
+ * Find out if we want to try a match with this key, depending on
+ * 'when' and a '*' or '!' before the key.
+ */
+ switch (when)
+ {
+ case '*': try_match = (*look == '*'); break;
+ case '!': try_match = (*look == '!'); break;
+ default: try_match = (*look != '*'); break;
+ }
+ if (*look == '*' || *look == '!')
+ ++look;
+
+ /*
+ * If there is a '0', only accept a match if the line is empty.
+ * But may still match when typing last char of a word.
+ */
+ if (*look == '0')
+ {
+ try_match_word = try_match;
+ if (!line_is_empty)
+ try_match = FALSE;
+ ++look;
+ }
+ else
+ try_match_word = FALSE;
+
+ /*
+ * does it look like a control character?
+ */
+ if (*look == '^'
+#ifdef EBCDIC
+ && (Ctrl_chr(look[1]) != 0)
+#else
+ && look[1] >= '?' && look[1] <= '_'
+#endif
+ )
+ {
+ if (try_match && keytyped == Ctrl_chr(look[1]))
+ return TRUE;
+ look += 2;
+ }
+ /*
+ * 'o' means "o" command, open forward.
+ * 'O' means "O" command, open backward.
+ */
+ else if (*look == 'o')
+ {
+ if (try_match && keytyped == KEY_OPEN_FORW)
+ return TRUE;
+ ++look;
+ }
+ else if (*look == 'O')
+ {
+ if (try_match && keytyped == KEY_OPEN_BACK)
+ return TRUE;
+ ++look;
+ }
+
+ /*
+ * 'e' means to check for "else" at start of line and just before the
+ * cursor.
+ */
+ else if (*look == 'e')
+ {
+ if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4)
+ {
+ p = ml_get_curline();
+ if (skipwhite(p) == p + curwin->w_cursor.col - 4 &&
+ STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0)
+ return TRUE;
+ }
+ ++look;
+ }
+
+ /*
+ * ':' only causes an indent if it is at the end of a label or case
+ * statement, or when it was before typing the ':' (to fix
+ * class::method for C++).
+ */
+ else if (*look == ':')
+ {
+ if (try_match && keytyped == ':')
+ {
+ p = ml_get_curline();
+ if (cin_iscase(p) || cin_isscopedecl(p) || cin_islabel(30))
+ return TRUE;
+ if (curwin->w_cursor.col > 2
+ && p[curwin->w_cursor.col - 1] == ':'
+ && p[curwin->w_cursor.col - 2] == ':')
+ {
+ p[curwin->w_cursor.col - 1] = ' ';
+ i = (cin_iscase(p) || cin_isscopedecl(p)
+ || cin_islabel(30));
+ p = ml_get_curline();
+ p[curwin->w_cursor.col - 1] = ':';
+ if (i)
+ return TRUE;
+ }
+ }
+ ++look;
+ }
+
+
+ /*
+ * Is it a key in <>, maybe?
+ */
+ else if (*look == '<')
+ {
+ if (try_match)
+ {
+ /*
+ * make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>,
+ * <:> and <!> so that people can re-indent on o, O, e, 0, <,
+ * >, *, : and ! keys if they really really want to.
+ */
+ if (vim_strchr((char_u *)"<>!*oOe0:", look[1]) != NULL
+ && keytyped == look[1])
+ return TRUE;
+
+ if (keytyped == get_special_key_code(look + 1))
+ return TRUE;
+ }
+ while (*look && *look != '>')
+ look++;
+ while (*look == '>')
+ look++;
+ }
+
+ /*
+ * Is it a word: "=word"?
+ */
+ else if (*look == '=' && look[1] != ',' && look[1] != NUL)
+ {
+ ++look;
+ if (*look == '~')
+ {
+ icase = TRUE;
+ ++look;
+ }
+ else
+ icase = FALSE;
+ p = vim_strchr(look, ',');
+ if (p == NULL)
+ p = look + STRLEN(look);
+ if ((try_match || try_match_word)
+ && curwin->w_cursor.col >= (colnr_T)(p - look))
+ {
+ int match = FALSE;
+
+#ifdef FEAT_INS_EXPAND
+ if (keytyped == KEY_COMPLETE)
+ {
+ char_u *s;
+
+ /* Just completed a word, check if it starts with "look".
+ * search back for the start of a word. */
+ line = ml_get_curline();
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ char_u *n;
+
+ for (s = line + curwin->w_cursor.col; s > line; s = n)
+ {
+ n = mb_prevptr(line, s);
+ if (!vim_iswordp(n))
+ break;
+ }
+ }
+ else
+# endif
+ for (s = line + curwin->w_cursor.col; s > line; --s)
+ if (!vim_iswordc(s[-1]))
+ break;
+ if (s + (p - look) <= line + curwin->w_cursor.col
+ && (icase
+ ? MB_STRNICMP(s, look, p - look)
+ : STRNCMP(s, look, p - look)) == 0)
+ match = TRUE;
+ }
+ else
+#endif
+ /* TODO: multi-byte */
+ if (keytyped == (int)p[-1] || (icase && keytyped < 256
+ && TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1])))
+ {
+ line = ml_get_cursor();
+ if ((curwin->w_cursor.col == (colnr_T)(p - look)
+ || !vim_iswordc(line[-(p - look) - 1]))
+ && (icase
+ ? MB_STRNICMP(line - (p - look), look, p - look)
+ : STRNCMP(line - (p - look), look, p - look))
+ == 0)
+ match = TRUE;
+ }
+ if (match && try_match_word && !try_match)
+ {
+ /* "0=word": Check if there are only blanks before the
+ * word. */
+ line = ml_get_curline();
+ if ((int)(skipwhite(line) - line) !=
+ (int)(curwin->w_cursor.col - (p - look)))
+ match = FALSE;
+ }
+ if (match)
+ return TRUE;
+ }
+ look = p;
+ }
+
+ /*
+ * ok, it's a boring generic character.
+ */
+ else
+ {
+ if (try_match && *look == keytyped)
+ return TRUE;
+ ++look;
+ }
+
+ /*
+ * Skip over ", ".
+ */
+ look = skip_to_option_part(look);
+ }
+ return FALSE;
+}
+#endif /* FEAT_CINDENT */
+
+#if defined(FEAT_RIGHTLEFT) || defined(PROTO)
+/*
+ * Map Hebrew keyboard when in hkmap mode.
+ */
+ int
+hkmap(c)
+ int c;
+{
+ if (p_hkmapp) /* phonetic mapping, by Ilya Dogolazky */
+ {
+ enum {hALEF=0, BET, GIMEL, DALET, HEI, VAV, ZAIN, HET, TET, IUD,
+ KAFsofit, hKAF, LAMED, MEMsofit, MEM, NUNsofit, NUN, SAMEH, AIN,
+ PEIsofit, PEI, ZADIsofit, ZADI, KOF, RESH, hSHIN, TAV};
+ static char_u map[26] =
+ {(char_u)hALEF/*a*/, (char_u)BET /*b*/, (char_u)hKAF /*c*/,
+ (char_u)DALET/*d*/, (char_u)-1 /*e*/, (char_u)PEIsofit/*f*/,
+ (char_u)GIMEL/*g*/, (char_u)HEI /*h*/, (char_u)IUD /*i*/,
+ (char_u)HET /*j*/, (char_u)KOF /*k*/, (char_u)LAMED /*l*/,
+ (char_u)MEM /*m*/, (char_u)NUN /*n*/, (char_u)SAMEH /*o*/,
+ (char_u)PEI /*p*/, (char_u)-1 /*q*/, (char_u)RESH /*r*/,
+ (char_u)ZAIN /*s*/, (char_u)TAV /*t*/, (char_u)TET /*u*/,
+ (char_u)VAV /*v*/, (char_u)hSHIN/*w*/, (char_u)-1 /*x*/,
+ (char_u)AIN /*y*/, (char_u)ZADI /*z*/};
+
+ if (c == 'N' || c == 'M' || c == 'P' || c == 'C' || c == 'Z')
+ return (int)(map[CharOrd(c)] - 1 + p_aleph);
+ /* '-1'='sofit' */
+ else if (c == 'x')
+ return 'X';
+ else if (c == 'q')
+ return '\''; /* {geresh}={'} */
+ else if (c == 246)
+ return ' '; /* \"o --> ' ' for a german keyboard */
+ else if (c == 228)
+ return ' '; /* \"a --> ' ' -- / -- */
+ else if (c == 252)
+ return ' '; /* \"u --> ' ' -- / -- */
+#ifdef EBCDIC
+ else if (islower(c))
+#else
+ /* NOTE: islower() does not do the right thing for us on Linux so we
+ * do this the same was as 5.7 and previous, so it works correctly on
+ * all systems. Specifically, the e.g. Delete and Arrow keys are
+ * munged and won't work if e.g. searching for Hebrew text.
+ */
+ else if (c >= 'a' && c <= 'z')
+#endif
+ return (int)(map[CharOrdLow(c)] + p_aleph);
+ else
+ return c;
+ }
+ else
+ {
+ switch (c)
+ {
+ case '`': return ';';
+ case '/': return '.';
+ case '\'': return ',';
+ case 'q': return '/';
+ case 'w': return '\'';
+
+ /* Hebrew letters - set offset from 'a' */
+ case ',': c = '{'; break;
+ case '.': c = 'v'; break;
+ case ';': c = 't'; break;
+ default: {
+ static char str[] = "zqbcxlsjphmkwonu ydafe rig";
+
+#ifdef EBCDIC
+ /* see note about islower() above */
+ if (!islower(c))
+#else
+ if (c < 'a' || c > 'z')
+#endif
+ return c;
+ c = str[CharOrdLow(c)];
+ break;
+ }
+ }
+
+ return (int)(CharOrdLow(c) + p_aleph);
+ }
+}
+#endif
+
+ static void
+ins_reg()
+{
+ int need_redraw = FALSE;
+ int regname;
+ int literally = 0;
+
+ /*
+ * If we are going to wait for a character, show a '"'.
+ */
+ pc_status = PC_STATUS_UNSET;
+ if (redrawing() && !char_avail())
+ {
+ /* may need to redraw when no more chars available now */
+ ins_redraw();
+
+ edit_putchar('"', TRUE);
+#ifdef FEAT_CMDL_INFO
+ add_to_showcmd_c(Ctrl_R);
+#endif
+ }
+
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = TRUE; /* disallow scrolling here */
+#endif
+
+ /*
+ * Don't map the register name. This also prevents the mode message to be
+ * deleted when ESC is hit.
+ */
+ ++no_mapping;
+ regname = safe_vgetc();
+#ifdef FEAT_LANGMAP
+ LANGMAP_ADJUST(regname, TRUE);
+#endif
+ if (regname == Ctrl_R || regname == Ctrl_O || regname == Ctrl_P)
+ {
+ /* Get a third key for literal register insertion */
+ literally = regname;
+#ifdef FEAT_CMDL_INFO
+ add_to_showcmd_c(literally);
+#endif
+ regname = safe_vgetc();
+#ifdef FEAT_LANGMAP
+ LANGMAP_ADJUST(regname, TRUE);
+#endif
+ }
+ --no_mapping;
+
+#ifdef FEAT_EVAL
+ /*
+ * Don't call u_sync() while getting the expression,
+ * evaluating it or giving an error message for it!
+ */
+ ++no_u_sync;
+ if (regname == '=')
+ {
+#ifdef USE_IM_CONTROL
+ int im_on = im_get_status();
+#endif
+ regname = get_expr_register();
+#ifdef USE_IM_CONTROL
+ /* Restore the Input Method. */
+ if (im_on)
+ im_set_active(TRUE);
+#endif
+ }
+ if (regname == NUL)
+ need_redraw = TRUE; /* remove the '"' */
+ else
+ {
+#endif
+ if (literally == Ctrl_O || literally == Ctrl_P)
+ {
+ /* Append the command to the redo buffer. */
+ AppendCharToRedobuff(Ctrl_R);
+ AppendCharToRedobuff(literally);
+ AppendCharToRedobuff(regname);
+
+ do_put(regname, BACKWARD, 1L,
+ (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND);
+ }
+ else if (insert_reg(regname, literally) == FAIL)
+ {
+ vim_beep();
+ need_redraw = TRUE; /* remove the '"' */
+ }
+#ifdef FEAT_EVAL
+ }
+ --no_u_sync;
+#endif
+#ifdef FEAT_CMDL_INFO
+ clear_showcmd();
+#endif
+
+ /* If the inserted register is empty, we need to remove the '"' */
+ if (need_redraw || stuff_empty())
+ edit_unputchar();
+}
+
+/*
+ * CTRL-G commands in Insert mode.
+ */
+ static void
+ins_ctrl_g()
+{
+ int c;
+
+#ifdef FEAT_INS_EXPAND
+ /* Right after CTRL-X the cursor will be after the ruler. */
+ setcursor();
+#endif
+
+ /*
+ * Don't map the second key. This also prevents the mode message to be
+ * deleted when ESC is hit.
+ */
+ ++no_mapping;
+ c = safe_vgetc();
+ --no_mapping;
+ switch (c)
+ {
+ /* CTRL-G k and CTRL-G <Up>: cursor up to Insstart.col */
+ case K_UP:
+ case Ctrl_K:
+ case 'k': ins_up(TRUE);
+ break;
+
+ /* CTRL-G j and CTRL-G <Down>: cursor down to Insstart.col */
+ case K_DOWN:
+ case Ctrl_J:
+ case 'j': ins_down(TRUE);
+ break;
+
+ /* CTRL-G u: start new undoable edit */
+ case 'u': u_sync();
+ ins_need_undo = TRUE;
+ break;
+
+ /* Unknown CTRL-G command, reserved for future expansion. */
+ default: vim_beep();
+ }
+}
+
+/*
+ * Handle ESC in insert mode.
+ * Returns TRUE when leaving insert mode, FALSE when going to repeat the
+ * insert.
+ */
+ static int
+ins_esc(count, cmdchar)
+ long *count;
+ int cmdchar;
+{
+ int temp;
+ static int disabled_redraw = FALSE;
+
+#if defined(FEAT_HANGULIN)
+# if defined(ESC_CHG_TO_ENG_MODE)
+ hangul_input_state_set(0);
+# endif
+ if (composing_hangul)
+ {
+ push_raw_key(composing_hangul_buffer, 2);
+ composing_hangul = 0;
+ }
+#endif
+#if defined(FEAT_MBYTE) && defined(MACOS_CLASSIC)
+ previous_script = GetScriptManagerVariable(smKeyScript);
+ KeyScript(smKeyRoman); /* or smKeySysScript */
+#endif
+
+ temp = curwin->w_cursor.col;
+ if (disabled_redraw)
+ {
+ --RedrawingDisabled;
+ disabled_redraw = FALSE;
+ }
+ if (!arrow_used)
+ {
+ /*
+ * Don't append the ESC for "r<CR>" and "grx".
+ */
+ if (cmdchar != 'r' && cmdchar != 'v')
+ AppendToRedobuff(ESC_STR);
+
+ /*
+ * Repeating insert may take a long time. Check for
+ * interrupt now and then.
+ */
+ if (*count > 0)
+ {
+ line_breakcheck();
+ if (got_int)
+ *count = 0;
+ }
+
+ if (--*count > 0) /* repeat what was typed */
+ {
+ (void)start_redo_ins();
+ if (cmdchar == 'r' || cmdchar == 'v')
+ stuffReadbuff(ESC_STR); /* no ESC in redo buffer */
+ ++RedrawingDisabled;
+ disabled_redraw = TRUE;
+ return FALSE; /* repeat the insert */
+ }
+ stop_insert(&curwin->w_cursor, TRUE);
+ undisplay_dollar();
+ }
+
+ /* When an autoindent was removed, curswant stays after the
+ * indent */
+ if (restart_edit == NUL && (colnr_T)temp == curwin->w_cursor.col)
+ curwin->w_set_curswant = TRUE;
+
+ /* Remember the last Insert position in the '^ mark. */
+ if (!cmdmod.keepjumps)
+ curbuf->b_last_insert = curwin->w_cursor;
+
+ /*
+ * The cursor should end up on the last inserted character.
+ */
+ if ((curwin->w_cursor.col != 0
+#ifdef FEAT_VIRTUALEDIT
+ || curwin->w_cursor.coladd > 0
+#endif
+ ) && (restart_edit == NUL
+ || (gchar_cursor() == NUL
+#ifdef FEAT_VISUAL
+ && !VIsual_active
+#endif
+ ))
+#ifdef FEAT_RIGHTLEFT
+ && !revins_on
+#endif
+ )
+ {
+#ifdef FEAT_VIRTUALEDIT
+ if (curwin->w_cursor.coladd > 0 || ve_flags == VE_ALL)
+ {
+ oneleft();
+ if (restart_edit != NUL)
+ ++curwin->w_cursor.coladd;
+ }
+ else
+#endif
+ {
+ --curwin->w_cursor.col;
+#ifdef FEAT_MBYTE
+ /* Correct cursor for multi-byte character. */
+ if (has_mbyte)
+ mb_adjust_cursor();
+#endif
+ }
+ }
+
+#ifdef USE_IM_CONTROL
+ /* Disable IM to allow typing English directly for Normal mode commands.
+ * When ":lmap" is enabled don't change 'iminsert' (IM can be enabled as
+ * well). */
+ if (!(State & LANGMAP))
+ im_save_status(&curbuf->b_p_iminsert);
+ im_set_active(FALSE);
+#endif
+
+ State = NORMAL;
+ /* need to position cursor again (e.g. when on a TAB ) */
+ changed_cline_bef_curs();
+
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+#ifdef CURSOR_SHAPE
+ ui_cursor_shape(); /* may show different cursor shape */
+#endif
+
+ /*
+ * When recording or for CTRL-O, need to display the new mode.
+ * Otherwise remove the mode message.
+ */
+ if (Recording || restart_edit != NUL)
+ showmode();
+ else if (p_smd)
+ MSG("");
+
+ return TRUE; /* exit Insert mode */
+}
+
+#ifdef FEAT_RIGHTLEFT
+/*
+ * Toggle language: hkmap and revins_on.
+ * Move to end of reverse inserted text.
+ */
+ static void
+ins_ctrl_()
+{
+ if (revins_on && revins_chars && revins_scol >= 0)
+ {
+ while (gchar_cursor() != NUL && revins_chars--)
+ ++curwin->w_cursor.col;
+ }
+ p_ri = !p_ri;
+ revins_on = (State == INSERT && p_ri);
+ if (revins_on)
+ {
+ revins_scol = curwin->w_cursor.col;
+ revins_legal++;
+ revins_chars = 0;
+ undisplay_dollar();
+ }
+ else
+ revins_scol = -1;
+#ifdef FEAT_FKMAP
+ if (p_altkeymap)
+ {
+ /*
+ * to be consistent also for redo command, using '.'
+ * set arrow_used to true and stop it - causing to redo
+ * characters entered in one mode (normal/reverse insert).
+ */
+ arrow_used = TRUE;
+ (void)stop_arrow();
+ p_fkmap = curwin->w_p_rl ^ p_ri;
+ if (p_fkmap && p_ri)
+ State = INSERT;
+ }
+ else
+#endif
+ p_hkmap = curwin->w_p_rl ^ p_ri; /* be consistent! */
+ showmode();
+}
+#endif
+
+#ifdef FEAT_VISUAL
+/*
+ * If 'keymodel' contains "startsel", may start selection.
+ * Returns TRUE when a CTRL-O and other keys stuffed.
+ */
+ static int
+ins_start_select(c)
+ int c;
+{
+ if (km_startsel)
+ switch (c)
+ {
+ case K_KHOME:
+ case K_XHOME:
+ case K_KEND:
+ case K_XEND:
+ case K_PAGEUP:
+ case K_KPAGEUP:
+ case K_PAGEDOWN:
+ case K_KPAGEDOWN:
+# ifdef MACOS
+ case K_LEFT:
+ case K_RIGHT:
+ case K_UP:
+ case K_DOWN:
+ case K_END:
+ case K_HOME:
+# endif
+ if (!(mod_mask & MOD_MASK_SHIFT))
+ break;
+ /* FALLTHROUGH */
+ case K_S_LEFT:
+ case K_S_RIGHT:
+ case K_S_UP:
+ case K_S_DOWN:
+ case K_S_END:
+ case K_S_HOME:
+ /* Start selection right away, the cursor can move with
+ * CTRL-O when beyond the end of the line. */
+ start_selection();
+
+ /* Execute the key in (insert) Select mode. */
+ stuffcharReadbuff(Ctrl_O);
+ if (mod_mask)
+ {
+ char_u buf[4];
+
+ buf[0] = K_SPECIAL;
+ buf[1] = KS_MODIFIER;
+ buf[2] = mod_mask;
+ buf[3] = NUL;
+ stuffReadbuff(buf);
+ }
+ stuffcharReadbuff(c);
+ return TRUE;
+ }
+ return FALSE;
+}
+#endif
+
+/*
+ * If the cursor is on an indent, ^T/^D insert/delete one
+ * shiftwidth. Otherwise ^T/^D behave like a "<<" or ">>".
+ * Always round the indent to 'shiftwith', this is compatible
+ * with vi. But vi only supports ^T and ^D after an
+ * autoindent, we support it everywhere.
+ */
+ static void
+ins_shift(c, lastc)
+ int c;
+ int lastc;
+{
+ if (stop_arrow() == FAIL)
+ return;
+ AppendCharToRedobuff(c);
+
+ /*
+ * 0^D and ^^D: remove all indent.
+ */
+ if ((lastc == '0' || lastc == '^') && curwin->w_cursor.col)
+ {
+ --curwin->w_cursor.col;
+ (void)del_char(FALSE); /* delete the '^' or '0' */
+ /* In Replace mode, restore the characters that '^' or '0' replaced. */
+ if (State & REPLACE_FLAG)
+ replace_pop_ins();
+ if (lastc == '^')
+ old_indent = get_indent(); /* remember curr. indent */
+ change_indent(INDENT_SET, 0, TRUE, 0);
+ }
+ else
+ change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0);
+
+ if (did_ai && *skipwhite(ml_get_curline()) != NUL)
+ did_ai = FALSE;
+#ifdef FEAT_SMARTINDENT
+ did_si = FALSE;
+ can_si = FALSE;
+ can_si_back = FALSE;
+#endif
+#ifdef FEAT_CINDENT
+ can_cindent = FALSE; /* no cindenting after ^D or ^T */
+#endif
+}
+
+ static void
+ins_del()
+{
+ int temp;
+
+ if (stop_arrow() == FAIL)
+ return;
+ if (gchar_cursor() == NUL) /* delete newline */
+ {
+ temp = curwin->w_cursor.col;
+ if (!can_bs(BS_EOL) /* only if "eol" included */
+ || u_save((linenr_T)(curwin->w_cursor.lnum - 1),
+ (linenr_T)(curwin->w_cursor.lnum + 2)) == FAIL
+ || do_join(FALSE) == FAIL)
+ vim_beep();
+ else
+ curwin->w_cursor.col = temp;
+ }
+ else if (del_char(FALSE) == FAIL) /* delete char under cursor */
+ vim_beep();
+ did_ai = FALSE;
+#ifdef FEAT_SMARTINDENT
+ did_si = FALSE;
+ can_si = FALSE;
+ can_si_back = FALSE;
+#endif
+ AppendCharToRedobuff(K_DEL);
+}
+
+/*
+ * Handle Backspace, delete-word and delete-line in Insert mode.
+ * Return TRUE when backspace was actually used.
+ */
+ static int
+ins_bs(c, mode, inserted_space_p)
+ int c;
+ int mode;
+ int *inserted_space_p;
+{
+ linenr_T lnum;
+ int cc;
+ int temp = 0; /* init for GCC */
+ colnr_T mincol;
+ int did_backspace = FALSE;
+ int in_indent;
+ int oldState;
+#ifdef FEAT_MBYTE
+ int p1, p2;
+#endif
+
+ /*
+ * can't delete anything in an empty file
+ * can't backup past first character in buffer
+ * can't backup past starting point unless 'backspace' > 1
+ * can backup to a previous line if 'backspace' == 0
+ */
+ if ( bufempty()
+ || (
+#ifdef FEAT_RIGHTLEFT
+ !revins_on &&
+#endif
+ ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col == 0)
+ || (!can_bs(BS_START)
+ && (arrow_used
+ || (curwin->w_cursor.lnum == Insstart.lnum
+ && curwin->w_cursor.col <= Insstart.col)))
+ || (!can_bs(BS_INDENT) && !arrow_used && ai_col > 0
+ && curwin->w_cursor.col <= ai_col)
+ || (!can_bs(BS_EOL) && curwin->w_cursor.col == 0))))
+ {
+ vim_beep();
+ return FALSE;
+ }
+
+ if (stop_arrow() == FAIL)
+ return FALSE;
+ in_indent = inindent(0);
+#ifdef FEAT_CINDENT
+ if (in_indent)
+ can_cindent = FALSE;
+#endif
+#ifdef FEAT_COMMENTS
+ end_comment_pending = NUL; /* After BS, don't auto-end comment */
+#endif
+#ifdef FEAT_RIGHTLEFT
+ if (revins_on) /* put cursor after last inserted char */
+ inc_cursor();
+#endif
+
+#ifdef FEAT_VIRTUALEDIT
+ /* Virtualedit:
+ * BACKSPACE_CHAR eats a virtual space
+ * BACKSPACE_WORD eats all coladd
+ * BACKSPACE_LINE eats all coladd and keeps going
+ */
+ if (curwin->w_cursor.coladd > 0)
+ {
+ if (mode == BACKSPACE_CHAR)
+ {
+ --curwin->w_cursor.coladd;
+ return TRUE;
+ }
+ if (mode == BACKSPACE_WORD)
+ {
+ curwin->w_cursor.coladd = 0;
+ return TRUE;
+ }
+ curwin->w_cursor.coladd = 0;
+ }
+#endif
+
+ /*
+ * delete newline!
+ */
+ if (curwin->w_cursor.col == 0)
+ {
+ lnum = Insstart.lnum;
+ if (curwin->w_cursor.lnum == Insstart.lnum
+#ifdef FEAT_RIGHTLEFT
+ || revins_on
+#endif
+ )
+ {
+ if (u_save((linenr_T)(curwin->w_cursor.lnum - 2),
+ (linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL)
+ return FALSE;
+ --Insstart.lnum;
+ Insstart.col = MAXCOL;
+ }
+ /*
+ * In replace mode:
+ * cc < 0: NL was inserted, delete it
+ * cc >= 0: NL was replaced, put original characters back
+ */
+ cc = -1;
+ if (State & REPLACE_FLAG)
+ cc = replace_pop(); /* returns -1 if NL was inserted */
+ /*
+ * In replace mode, in the line we started replacing, we only move the
+ * cursor.
+ */
+ if ((State & REPLACE_FLAG) && curwin->w_cursor.lnum <= lnum)
+ {
+ dec_cursor();
+ }
+ else
+ {
+#ifdef FEAT_VREPLACE
+ if (!(State & VREPLACE_FLAG)
+ || curwin->w_cursor.lnum > orig_line_count)
+#endif
+ {
+ temp = gchar_cursor(); /* remember current char */
+ --curwin->w_cursor.lnum;
+ (void)do_join(FALSE);
+ if (temp == NUL && gchar_cursor() != NUL)
+ inc_cursor();
+ }
+#ifdef FEAT_VREPLACE
+ else
+ dec_cursor();
+#endif
+
+ /*
+ * In REPLACE mode we have to put back the text that was replaced
+ * by the NL. On the replace stack is first a NUL-terminated
+ * sequence of characters that were deleted and then the
+ * characters that NL replaced.
+ */
+ if (State & REPLACE_FLAG)
+ {
+ /*
+ * Do the next ins_char() in NORMAL state, to
+ * prevent ins_char() from replacing characters and
+ * avoiding showmatch().
+ */
+ oldState = State;
+ State = NORMAL;
+ /*
+ * restore characters (blanks) deleted after cursor
+ */
+ while (cc > 0)
+ {
+ temp = curwin->w_cursor.col;
+#ifdef FEAT_MBYTE
+ mb_replace_pop_ins(cc);
+#else
+ ins_char(cc);
+#endif
+ curwin->w_cursor.col = temp;
+ cc = replace_pop();
+ }
+ /* restore the characters that NL replaced */
+ replace_pop_ins();
+ State = oldState;
+ }
+ }
+ did_ai = FALSE;
+ }
+ else
+ {
+ /*
+ * Delete character(s) before the cursor.
+ */
+#ifdef FEAT_RIGHTLEFT
+ if (revins_on) /* put cursor on last inserted char */
+ dec_cursor();
+#endif
+ mincol = 0;
+ /* keep indent */
+ if (mode == BACKSPACE_LINE && curbuf->b_p_ai
+#ifdef FEAT_RIGHTLEFT
+ && !revins_on
+#endif
+ )
+ {
+ temp = curwin->w_cursor.col;
+ beginline(BL_WHITE);
+ if (curwin->w_cursor.col < (colnr_T)temp)
+ mincol = curwin->w_cursor.col;
+ curwin->w_cursor.col = temp;
+ }
+
+ /*
+ * Handle deleting one 'shiftwidth' or 'softtabstop'.
+ */
+ if ( mode == BACKSPACE_CHAR
+ && ((p_sta && in_indent)
+ || (curbuf->b_p_sts
+ && (*(ml_get_cursor() - 1) == TAB
+ || (*(ml_get_cursor() - 1) == ' '
+ && (!*inserted_space_p
+ || arrow_used))))))
+ {
+ int ts;
+ colnr_T vcol;
+ colnr_T want_vcol;
+ int extra = 0;
+
+ *inserted_space_p = FALSE;
+ if (p_sta)
+ ts = curbuf->b_p_sw;
+ else
+ ts = curbuf->b_p_sts;
+ /* Compute the virtual column where we want to be. Since
+ * 'showbreak' may get in the way, need to get the last column of
+ * the previous character. */
+ getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
+ dec_cursor();
+ getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol);
+ inc_cursor();
+ want_vcol = (want_vcol / ts) * ts;
+
+ /* delete characters until we are at or before want_vcol */
+ while (vcol > want_vcol
+ && (cc = *(ml_get_cursor() - 1), vim_iswhite(cc)))
+ {
+ dec_cursor();
+ getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
+ if (State & REPLACE_FLAG)
+ {
+ /* Don't delete characters before the insert point when in
+ * Replace mode */
+ if (curwin->w_cursor.lnum != Insstart.lnum
+ || curwin->w_cursor.col >= Insstart.col)
+ {
+#if 0 /* what was this for? It causes problems when sw != ts. */
+ if (State == REPLACE && (int)vcol < want_vcol)
+ {
+ (void)del_char(FALSE);
+ extra = 2; /* don't pop too much */
+ }
+ else
+#endif
+ replace_do_bs();
+ }
+ }
+ else
+ (void)del_char(FALSE);
+ }
+
+ /* insert extra spaces until we are at want_vcol */
+ while (vcol < want_vcol)
+ {
+ /* Remember the first char we inserted */
+ if (curwin->w_cursor.lnum == Insstart.lnum
+ && curwin->w_cursor.col < Insstart.col)
+ Insstart.col = curwin->w_cursor.col;
+
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ ins_char(' ');
+ else
+#endif
+ {
+ ins_str((char_u *)" ");
+ if ((State & REPLACE_FLAG) && extra <= 1)
+ {
+ if (extra)
+ replace_push_off(NUL);
+ else
+ replace_push(NUL);
+ }
+ if (extra == 2)
+ extra = 1;
+ }
+ getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
+ }
+ }
+
+ /*
+ * Delete upto starting point, start of line or previous word.
+ */
+ else do
+ {
+#ifdef FEAT_RIGHTLEFT
+ if (!revins_on) /* put cursor on char to be deleted */
+#endif
+ dec_cursor();
+
+ /* start of word? */
+ if (mode == BACKSPACE_WORD && !vim_isspace(gchar_cursor()))
+ {
+ mode = BACKSPACE_WORD_NOT_SPACE;
+ temp = vim_iswordc(gchar_cursor());
+ }
+ /* end of word? */
+ else if (mode == BACKSPACE_WORD_NOT_SPACE
+ && (vim_isspace(cc = gchar_cursor())
+ || vim_iswordc(cc) != temp))
+ {
+#ifdef FEAT_RIGHTLEFT
+ if (!revins_on)
+#endif
+ inc_cursor();
+#ifdef FEAT_RIGHTLEFT
+ else if (State & REPLACE_FLAG)
+ dec_cursor();
+#endif
+ break;
+ }
+ if (State & REPLACE_FLAG)
+ replace_do_bs();
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (enc_utf8 && p_deco)
+ (void)utfc_ptr2char(ml_get_cursor(), &p1, &p2);
+#endif
+ (void)del_char(FALSE);
+#ifdef FEAT_MBYTE
+ /*
+ * If p1 or p2 is non-zero, there are combining characters we
+ * need to take account of. Don't back up before the base
+ * character.
+ */
+ if (enc_utf8 && p_deco && (p1 != NUL || p2 != NUL))
+ inc_cursor();
+#endif
+#ifdef FEAT_RIGHTLEFT
+ if (revins_chars)
+ {
+ revins_chars--;
+ revins_legal++;
+ }
+ if (revins_on && gchar_cursor() == NUL)
+ break;
+#endif
+ }
+ /* Just a single backspace?: */
+ if (mode == BACKSPACE_CHAR)
+ break;
+ } while (
+#ifdef FEAT_RIGHTLEFT
+ revins_on ||
+#endif
+ (curwin->w_cursor.col > mincol
+ && (curwin->w_cursor.lnum != Insstart.lnum
+ || curwin->w_cursor.col != Insstart.col)));
+ did_backspace = TRUE;
+ }
+#ifdef FEAT_SMARTINDENT
+ did_si = FALSE;
+ can_si = FALSE;
+ can_si_back = FALSE;
+#endif
+ if (curwin->w_cursor.col <= 1)
+ did_ai = FALSE;
+ /*
+ * It's a little strange to put backspaces into the redo
+ * buffer, but it makes auto-indent a lot easier to deal
+ * with.
+ */
+ AppendCharToRedobuff(c);
+
+ /* If deleted before the insertion point, adjust it */
+ if (curwin->w_cursor.lnum == Insstart.lnum
+ && curwin->w_cursor.col < Insstart.col)
+ Insstart.col = curwin->w_cursor.col;
+
+ /* vi behaviour: the cursor moves backward but the character that
+ * was there remains visible
+ * Vim behaviour: the cursor moves backward and the character that
+ * was there is erased from the screen.
+ * We can emulate the vi behaviour by pretending there is a dollar
+ * displayed even when there isn't.
+ * --pkv Sun Jan 19 01:56:40 EST 2003 */
+ if (vim_strchr(p_cpo, CPO_BACKSPACE) != NULL && dollar_vcol == 0)
+ dollar_vcol = curwin->w_virtcol;
+
+ return did_backspace;
+}
+
+#ifdef FEAT_MOUSE
+ static void
+ins_mouse(c)
+ int c;
+{
+ pos_T tpos;
+
+# ifdef FEAT_GUI
+ /* When GUI is active, also move/paste when 'mouse' is empty */
+ if (!gui.in_use)
+# endif
+ if (!mouse_has(MOUSE_INSERT))
+ return;
+
+ undisplay_dollar();
+ tpos = curwin->w_cursor;
+ if (do_mouse(NULL, c, BACKWARD, 1L, 0))
+ {
+ start_arrow(&tpos);
+# ifdef FEAT_CINDENT
+ can_cindent = TRUE;
+# endif
+ }
+
+#ifdef FEAT_WINDOWS
+ /* redraw status lines (in case another window became active) */
+ redraw_statuslines();
+#endif
+}
+
+ static void
+ins_mousescroll(up)
+ int up;
+{
+ pos_T tpos;
+# if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
+ win_T *old_curwin;
+# endif
+
+ tpos = curwin->w_cursor;
+
+# if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
+ old_curwin = curwin;
+
+ /* Currently the mouse coordinates are only known in the GUI. */
+ if (gui.in_use && mouse_row >= 0 && mouse_col >= 0)
+ {
+ int row, col;
+
+ row = mouse_row;
+ col = mouse_col;
+
+ /* find the window at the pointer coordinates */
+ curwin = mouse_find_win(&row, &col);
+ curbuf = curwin->w_buffer;
+ }
+ if (curwin == old_curwin)
+# endif
+ undisplay_dollar();
+
+ if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
+ scroll_redraw(up, (long)(curwin->w_botline - curwin->w_topline));
+ else
+ scroll_redraw(up, 3L);
+
+# if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
+ curwin->w_redr_status = TRUE;
+
+ curwin = old_curwin;
+ curbuf = curwin->w_buffer;
+# endif
+
+ if (!equalpos(curwin->w_cursor, tpos))
+ {
+ start_arrow(&tpos);
+# ifdef FEAT_CINDENT
+ can_cindent = TRUE;
+# endif
+ }
+}
+#endif
+
+#ifdef FEAT_GUI
+ void
+ins_scroll()
+{
+ pos_T tpos;
+
+ undisplay_dollar();
+ tpos = curwin->w_cursor;
+ if (gui_do_scroll())
+ {
+ start_arrow(&tpos);
+# ifdef FEAT_CINDENT
+ can_cindent = TRUE;
+# endif
+ }
+}
+
+ void
+ins_horscroll()
+{
+ pos_T tpos;
+
+ undisplay_dollar();
+ tpos = curwin->w_cursor;
+ if (gui_do_horiz_scroll())
+ {
+ start_arrow(&tpos);
+# ifdef FEAT_CINDENT
+ can_cindent = TRUE;
+# endif
+ }
+}
+#endif
+
+ static void
+ins_left()
+{
+ pos_T tpos;
+
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_HOR) && KeyTyped)
+ foldOpenCursor();
+#endif
+ undisplay_dollar();
+ tpos = curwin->w_cursor;
+ if (oneleft() == OK)
+ {
+ start_arrow(&tpos);
+#ifdef FEAT_RIGHTLEFT
+ /* If exit reversed string, position is fixed */
+ if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol)
+ revins_legal++;
+ revins_chars++;
+#endif
+ }
+
+ /*
+ * if 'whichwrap' set for cursor in insert mode may go to
+ * previous line
+ */
+ else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1)
+ {
+ start_arrow(&tpos);
+ --(curwin->w_cursor.lnum);
+ coladvance((colnr_T)MAXCOL);
+ curwin->w_set_curswant = TRUE; /* so we stay at the end */
+ }
+ else
+ vim_beep();
+}
+
+ static void
+ins_home(c)
+ int c;
+{
+ pos_T tpos;
+
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_HOR) && KeyTyped)
+ foldOpenCursor();
+#endif
+ undisplay_dollar();
+ tpos = curwin->w_cursor;
+ if (c == K_C_HOME)
+ curwin->w_cursor.lnum = 1;
+ curwin->w_cursor.col = 0;
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ curwin->w_curswant = 0;
+ start_arrow(&tpos);
+}
+
+ static void
+ins_end(c)
+ int c;
+{
+ pos_T tpos;
+
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_HOR) && KeyTyped)
+ foldOpenCursor();
+#endif
+ undisplay_dollar();
+ tpos = curwin->w_cursor;
+ if (c == K_C_END)
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ coladvance((colnr_T)MAXCOL);
+ curwin->w_curswant = MAXCOL;
+
+ start_arrow(&tpos);
+}
+
+ static void
+ins_s_left()
+{
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_HOR) && KeyTyped)
+ foldOpenCursor();
+#endif
+ undisplay_dollar();
+ if (curwin->w_cursor.lnum > 1 || curwin->w_cursor.col > 0)
+ {
+ start_arrow(&curwin->w_cursor);
+ (void)bck_word(1L, FALSE, FALSE);
+ curwin->w_set_curswant = TRUE;
+ }
+ else
+ vim_beep();
+}
+
+ static void
+ins_right()
+{
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_HOR) && KeyTyped)
+ foldOpenCursor();
+#endif
+ undisplay_dollar();
+ if (gchar_cursor() != NUL || virtual_active()
+ )
+ {
+ start_arrow(&curwin->w_cursor);
+ curwin->w_set_curswant = TRUE;
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_active())
+ oneright();
+ else
+#endif
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ curwin->w_cursor.col += (*mb_ptr2len_check)(ml_get_cursor());
+ else
+#endif
+ ++curwin->w_cursor.col;
+ }
+
+#ifdef FEAT_RIGHTLEFT
+ revins_legal++;
+ if (revins_chars)
+ revins_chars--;
+#endif
+ }
+ /* if 'whichwrap' set for cursor in insert mode, may move the
+ * cursor to the next line */
+ else if (vim_strchr(p_ww, ']') != NULL
+ && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
+ {
+ start_arrow(&curwin->w_cursor);
+ curwin->w_set_curswant = TRUE;
+ ++curwin->w_cursor.lnum;
+ curwin->w_cursor.col = 0;
+ }
+ else
+ vim_beep();
+}
+
+ static void
+ins_s_right()
+{
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_HOR) && KeyTyped)
+ foldOpenCursor();
+#endif
+ undisplay_dollar();
+ if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
+ || gchar_cursor() != NUL)
+ {
+ start_arrow(&curwin->w_cursor);
+ (void)fwd_word(1L, FALSE, 0);
+ curwin->w_set_curswant = TRUE;
+ }
+ else
+ vim_beep();
+}
+
+ static void
+ins_up(startcol)
+ int startcol; /* when TRUE move to Insstart.col */
+{
+ pos_T tpos;
+ linenr_T old_topline = curwin->w_topline;
+#ifdef FEAT_DIFF
+ int old_topfill = curwin->w_topfill;
+#endif
+
+ undisplay_dollar();
+ tpos = curwin->w_cursor;
+ if (cursor_up(1L, TRUE) == OK)
+ {
+ if (startcol)
+ coladvance(getvcol_nolist(&Insstart));
+ if (old_topline != curwin->w_topline
+#ifdef FEAT_DIFF
+ || old_topfill != curwin->w_topfill
+#endif
+ )
+ redraw_later(VALID);
+ start_arrow(&tpos);
+#ifdef FEAT_CINDENT
+ can_cindent = TRUE;
+#endif
+ }
+ else
+ vim_beep();
+}
+
+ static void
+ins_pageup()
+{
+ pos_T tpos;
+
+ undisplay_dollar();
+ tpos = curwin->w_cursor;
+ if (onepage(BACKWARD, 1L) == OK)
+ {
+ start_arrow(&tpos);
+#ifdef FEAT_CINDENT
+ can_cindent = TRUE;
+#endif
+ }
+ else
+ vim_beep();
+}
+
+ static void
+ins_down(startcol)
+ int startcol; /* when TRUE move to Insstart.col */
+{
+ pos_T tpos;
+ linenr_T old_topline = curwin->w_topline;
+#ifdef FEAT_DIFF
+ int old_topfill = curwin->w_topfill;
+#endif
+
+ undisplay_dollar();
+ tpos = curwin->w_cursor;
+ if (cursor_down(1L, TRUE) == OK)
+ {
+ if (startcol)
+ coladvance(getvcol_nolist(&Insstart));
+ if (old_topline != curwin->w_topline
+#ifdef FEAT_DIFF
+ || old_topfill != curwin->w_topfill
+#endif
+ )
+ redraw_later(VALID);
+ start_arrow(&tpos);
+#ifdef FEAT_CINDENT
+ can_cindent = TRUE;
+#endif
+ }
+ else
+ vim_beep();
+}
+
+ static void
+ins_pagedown()
+{
+ pos_T tpos;
+
+ undisplay_dollar();
+ tpos = curwin->w_cursor;
+ if (onepage(FORWARD, 1L) == OK)
+ {
+ start_arrow(&tpos);
+#ifdef FEAT_CINDENT
+ can_cindent = TRUE;
+#endif
+ }
+ else
+ vim_beep();
+}
+
+#ifdef FEAT_DND
+ static void
+ins_drop()
+{
+ do_put('~', BACKWARD, 1L, PUT_CURSEND);
+}
+#endif
+
+/*
+ * Handle TAB in Insert or Replace mode.
+ * Return TRUE when the TAB needs to be inserted like a normal character.
+ */
+ static int
+ins_tab()
+{
+ int ind;
+ int i;
+ int temp;
+
+ if (Insstart_blank_vcol == MAXCOL && curwin->w_cursor.lnum == Insstart.lnum)
+ Insstart_blank_vcol = get_nolist_virtcol();
+ if (echeck_abbr(TAB + ABBR_OFF))
+ return FALSE;
+
+ ind = inindent(0);
+#ifdef FEAT_CINDENT
+ if (ind)
+ can_cindent = FALSE;
+#endif
+
+ /*
+ * When nothing special, insert TAB like a normal character
+ */
+ if (!curbuf->b_p_et
+ && !(p_sta && ind && curbuf->b_p_ts != curbuf->b_p_sw)
+ && curbuf->b_p_sts == 0)
+ return TRUE;
+
+ if (stop_arrow() == FAIL)
+ return TRUE;
+
+ did_ai = FALSE;
+#ifdef FEAT_SMARTINDENT
+ did_si = FALSE;
+ can_si = FALSE;
+ can_si_back = FALSE;
+#endif
+ AppendToRedobuff((char_u *)"\t");
+
+ if (p_sta && ind) /* insert tab in indent, use 'shiftwidth' */
+ temp = (int)curbuf->b_p_sw;
+ else if (curbuf->b_p_sts > 0) /* use 'softtabstop' when set */
+ temp = (int)curbuf->b_p_sts;
+ else /* otherwise use 'tabstop' */
+ temp = (int)curbuf->b_p_ts;
+ temp -= get_nolist_virtcol() % temp;
+
+ /*
+ * Insert the first space with ins_char(). It will delete one char in
+ * replace mode. Insert the rest with ins_str(); it will not delete any
+ * chars. For VREPLACE mode, we use ins_char() for all characters.
+ */
+ ins_char(' ');
+ while (--temp > 0)
+ {
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ ins_char(' ');
+ else
+#endif
+ {
+ ins_str((char_u *)" ");
+ if (State & REPLACE_FLAG) /* no char replaced */
+ replace_push(NUL);
+ }
+ }
+
+ /*
+ * When 'expandtab' not set: Replace spaces by TABs where possible.
+ */
+ if (!curbuf->b_p_et && (curbuf->b_p_sts || (p_sta && ind)))
+ {
+ char_u *ptr;
+#ifdef FEAT_VREPLACE
+ char_u *saved_line = NULL; /* init for GCC */
+ pos_T pos;
+#endif
+ pos_T fpos;
+ pos_T *cursor;
+ colnr_T want_vcol, vcol;
+ int change_col = -1;
+ int save_list = curwin->w_p_list;
+
+ /*
+ * Get the current line. For VREPLACE mode, don't make real changes
+ * yet, just work on a copy of the line.
+ */
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ {
+ pos = curwin->w_cursor;
+ cursor = &pos;
+ saved_line = vim_strsave(ml_get_curline());
+ if (saved_line == NULL)
+ return FALSE;
+ ptr = saved_line + pos.col;
+ }
+ else
+#endif
+ {
+ ptr = ml_get_cursor();
+ cursor = &curwin->w_cursor;
+ }
+
+ /* When 'L' is not in 'cpoptions' a tab always takes up 'ts' spaces. */
+ if (vim_strchr(p_cpo, CPO_LISTWM) == NULL)
+ curwin->w_p_list = FALSE;
+
+ /* Find first white before the cursor */
+ fpos = curwin->w_cursor;
+ while (fpos.col > 0 && vim_iswhite(ptr[-1]))
+ {
+ --fpos.col;
+ --ptr;
+ }
+
+ /* In Replace mode, don't change characters before the insert point. */
+ if ((State & REPLACE_FLAG)
+ && fpos.lnum == Insstart.lnum
+ && fpos.col < Insstart.col)
+ {
+ ptr += Insstart.col - fpos.col;
+ fpos.col = Insstart.col;
+ }
+
+ /* compute virtual column numbers of first white and cursor */
+ getvcol(curwin, &fpos, &vcol, NULL, NULL);
+ getvcol(curwin, cursor, &want_vcol, NULL, NULL);
+
+ /* Use as many TABs as possible. Beware of 'showbreak' and
+ * 'linebreak' adding extra virtual columns. */
+ while (vim_iswhite(*ptr))
+ {
+ i = lbr_chartabsize((char_u *)"\t", vcol);
+ if (vcol + i > want_vcol)
+ break;
+ if (*ptr != TAB)
+ {
+ *ptr = TAB;
+ if (change_col < 0)
+ {
+ change_col = fpos.col; /* Column of first change */
+ /* May have to adjust Insstart */
+ if (fpos.lnum == Insstart.lnum && fpos.col < Insstart.col)
+ Insstart.col = fpos.col;
+ }
+ }
+ ++fpos.col;
+ ++ptr;
+ vcol += i;
+ }
+
+ if (change_col >= 0)
+ {
+ int repl_off = 0;
+
+ /* Skip over the spaces we need. */
+ while (vcol < want_vcol && *ptr == ' ')
+ {
+ vcol += lbr_chartabsize(ptr, vcol);
+ ++ptr;
+ ++repl_off;
+ }
+ if (vcol > want_vcol)
+ {
+ /* Must have a char with 'showbreak' just before it. */
+ --ptr;
+ --repl_off;
+ }
+ fpos.col += repl_off;
+
+ /* Delete following spaces. */
+ i = cursor->col - fpos.col;
+ if (i > 0)
+ {
+ mch_memmove(ptr, ptr + i, STRLEN(ptr + i) + 1);
+ /* correct replace stack. */
+ if ((State & REPLACE_FLAG)
+#ifdef FEAT_VREPLACE
+ && !(State & VREPLACE_FLAG)
+#endif
+ )
+ for (temp = i; --temp >= 0; )
+ replace_join(repl_off);
+ }
+ cursor->col -= i;
+
+#ifdef FEAT_VREPLACE
+ /*
+ * In VREPLACE mode, we haven't changed anything yet. Do it now by
+ * backspacing over the changed spacing and then inserting the new
+ * spacing.
+ */
+ if (State & VREPLACE_FLAG)
+ {
+ /* Backspace from real cursor to change_col */
+ backspace_until_column(change_col);
+
+ /* Insert each char in saved_line from changed_col to
+ * ptr-cursor */
+ ins_bytes_len(saved_line + change_col,
+ cursor->col - change_col);
+ }
+#endif
+ }
+
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ vim_free(saved_line);
+#endif
+ curwin->w_p_list = save_list;
+ }
+
+ return FALSE;
+}
+
+/*
+ * Handle CR or NL in insert mode.
+ * Return TRUE when out of memory or can't undo.
+ */
+ static int
+ins_eol(c)
+ int c;
+{
+ int i;
+
+ if (echeck_abbr(c + ABBR_OFF))
+ return FALSE;
+ if (stop_arrow() == FAIL)
+ return TRUE;
+ undisplay_dollar();
+
+ /*
+ * Strange Vi behaviour: In Replace mode, typing a NL will not delete the
+ * character under the cursor. Only push a NUL on the replace stack,
+ * nothing to put back when the NL is deleted.
+ */
+ if ((State & REPLACE_FLAG)
+#ifdef FEAT_VREPLACE
+ && !(State & VREPLACE_FLAG)
+#endif
+ )
+ replace_push(NUL);
+
+ /*
+ * In VREPLACE mode, a NL replaces the rest of the line, and starts
+ * replacing the next line, so we push all of the characters left on the
+ * line onto the replace stack. This is not done here though, it is done
+ * in open_line().
+ */
+
+#ifdef FEAT_RIGHTLEFT
+# ifdef FEAT_FKMAP
+ if (p_altkeymap && p_fkmap)
+ fkmap(NL);
+# endif
+ /* NL in reverse insert will always start in the end of
+ * current line. */
+ if (revins_on)
+ curwin->w_cursor.col += (colnr_T)STRLEN(ml_get_cursor());
+#endif
+
+ AppendToRedobuff(NL_STR);
+ i = open_line(FORWARD,
+#ifdef FEAT_COMMENTS
+ has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM :
+#endif
+ 0, old_indent);
+ old_indent = 0;
+#ifdef FEAT_CINDENT
+ can_cindent = TRUE;
+#endif
+
+ return (!i);
+}
+
+#ifdef FEAT_DIGRAPHS
+/*
+ * Handle digraph in insert mode.
+ * Returns character still to be inserted, or NUL when nothing remaining to be
+ * done.
+ */
+ static int
+ins_digraph()
+{
+ int c;
+ int cc;
+
+ pc_status = PC_STATUS_UNSET;
+ if (redrawing() && !char_avail())
+ {
+ /* may need to redraw when no more chars available now */
+ ins_redraw();
+
+ edit_putchar('?', TRUE);
+#ifdef FEAT_CMDL_INFO
+ add_to_showcmd_c(Ctrl_K);
+#endif
+ }
+
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = TRUE; /* disallow scrolling here */
+#endif
+
+ /* don't map the digraph chars. This also prevents the
+ * mode message to be deleted when ESC is hit */
+ ++no_mapping;
+ ++allow_keys;
+ c = safe_vgetc();
+ --no_mapping;
+ --allow_keys;
+ if (IS_SPECIAL(c) || mod_mask) /* special key */
+ {
+#ifdef FEAT_CMDL_INFO
+ clear_showcmd();
+#endif
+ insert_special(c, TRUE, FALSE);
+ return NUL;
+ }
+ if (c != ESC)
+ {
+ if (redrawing() && !char_avail())
+ {
+ /* may need to redraw when no more chars available now */
+ ins_redraw();
+
+ if (char2cells(c) == 1)
+ {
+ /* first remove the '?', otherwise it's restored when typing
+ * an ESC next */
+ edit_unputchar();
+ ins_redraw();
+ edit_putchar(c, TRUE);
+ }
+#ifdef FEAT_CMDL_INFO
+ add_to_showcmd_c(c);
+#endif
+ }
+ ++no_mapping;
+ ++allow_keys;
+ cc = safe_vgetc();
+ --no_mapping;
+ --allow_keys;
+ if (cc != ESC)
+ {
+ AppendToRedobuff((char_u *)CTRL_V_STR);
+ c = getdigraph(c, cc, TRUE);
+#ifdef FEAT_CMDL_INFO
+ clear_showcmd();
+#endif
+ return c;
+ }
+ }
+ edit_unputchar();
+#ifdef FEAT_CMDL_INFO
+ clear_showcmd();
+#endif
+ return NUL;
+}
+#endif
+
+/*
+ * Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line.
+ * Returns the char to be inserted, or NUL if none found.
+ */
+ static int
+ins_copychar(lnum)
+ linenr_T lnum;
+{
+ int c;
+ int temp;
+ char_u *ptr, *prev_ptr;
+
+ if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
+ {
+ vim_beep();
+ return NUL;
+ }
+
+ /* try to advance to the cursor column */
+ temp = 0;
+ ptr = ml_get(lnum);
+ prev_ptr = ptr;
+ validate_virtcol();
+ while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL)
+ {
+ prev_ptr = ptr;
+ temp += lbr_chartabsize_adv(&ptr, (colnr_T)temp);
+ }
+ if ((colnr_T)temp > curwin->w_virtcol)
+ ptr = prev_ptr;
+
+#ifdef FEAT_MBYTE
+ c = (*mb_ptr2char)(ptr);
+#else
+ c = *ptr;
+#endif
+ if (c == NUL)
+ vim_beep();
+ return c;
+}
+
+#ifdef FEAT_SMARTINDENT
+/*
+ * Try to do some very smart auto-indenting.
+ * Used when inserting a "normal" character.
+ */
+ static void
+ins_try_si(c)
+ int c;
+{
+ pos_T *pos, old_pos;
+ char_u *ptr;
+ int i;
+ int temp;
+
+ /*
+ * do some very smart indenting when entering '{' or '}'
+ */
+ if (((did_si || can_si_back) && c == '{') || (can_si && c == '}'))
+ {
+ /*
+ * for '}' set indent equal to indent of line containing matching '{'
+ */
+ if (c == '}' && (pos = findmatch(NULL, '{')) != NULL)
+ {
+ old_pos = curwin->w_cursor;
+ /*
+ * If the matching '{' has a ')' immediately before it (ignoring
+ * white-space), then line up with the start of the line
+ * containing the matching '(' if there is one. This handles the
+ * case where an "if (..\n..) {" statement continues over multiple
+ * lines -- webb
+ */
+ ptr = ml_get(pos->lnum);
+ i = pos->col;
+ if (i > 0) /* skip blanks before '{' */
+ while (--i > 0 && vim_iswhite(ptr[i]))
+ ;
+ curwin->w_cursor.lnum = pos->lnum;
+ curwin->w_cursor.col = i;
+ if (ptr[i] == ')' && (pos = findmatch(NULL, '(')) != NULL)
+ curwin->w_cursor = *pos;
+ i = get_indent();
+ curwin->w_cursor = old_pos;
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ change_indent(INDENT_SET, i, FALSE, NUL);
+ else
+#endif
+ (void)set_indent(i, SIN_CHANGED);
+ }
+ else if (curwin->w_cursor.col > 0)
+ {
+ /*
+ * when inserting '{' after "O" reduce indent, but not
+ * more than indent of previous line
+ */
+ temp = TRUE;
+ if (c == '{' && can_si_back && curwin->w_cursor.lnum > 1)
+ {
+ old_pos = curwin->w_cursor;
+ i = get_indent();
+ while (curwin->w_cursor.lnum > 1)
+ {
+ ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum)));
+
+ /* ignore empty lines and lines starting with '#'. */
+ if (*ptr != '#' && *ptr != NUL)
+ break;
+ }
+ if (get_indent() >= i)
+ temp = FALSE;
+ curwin->w_cursor = old_pos;
+ }
+ if (temp)
+ shift_line(TRUE, FALSE, 1);
+ }
+ }
+
+ /*
+ * set indent of '#' always to 0
+ */
+ if (curwin->w_cursor.col > 0 && can_si && c == '#')
+ {
+ /* remember current indent for next line */
+ old_indent = get_indent();
+ (void)set_indent(0, SIN_CHANGED);
+ }
+
+ /* Adjust ai_col, the char at this position can be deleted. */
+ if (ai_col > curwin->w_cursor.col)
+ ai_col = curwin->w_cursor.col;
+}
+#endif
+
+/*
+ * Get the value that w_virtcol would have when 'list' is off.
+ * Unless 'cpo' contains the 'L' flag.
+ */
+ static colnr_T
+get_nolist_virtcol()
+{
+ if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL)
+ return getvcol_nolist(&curwin->w_cursor);
+ validate_virtcol();
+ return curwin->w_virtcol;
+}
diff --git a/src/eval.c b/src/eval.c
new file mode 100644
index 000000000..2e339e6d0
--- /dev/null
+++ b/src/eval.c
@@ -0,0 +1,10682 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * eval.c: Expression evaluation.
+ */
+#if defined(MSDOS) || defined(MSWIN)
+# include <io.h> /* for mch_open(), must be before vim.h */
+#endif
+
+#include "vim.h"
+
+#ifdef AMIGA
+# include <time.h> /* for strftime() */
+#endif
+
+#ifdef MACOS
+# include <time.h> /* for time_t */
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+
+#if SIZEOF_INT <= 3 /* use long if int is smaller than 32 bits */
+typedef long varnumber_T;
+#else
+typedef int varnumber_T;
+#endif
+
+/*
+ * Structure to hold an internal variable.
+ */
+typedef struct
+{
+ char_u *var_name; /* name of variable */
+ char var_type; /* VAR_NUMBER or VAR_STRING */
+ union
+ {
+ varnumber_T var_number; /* number value */
+ char_u *var_string; /* string value (Careful: can be NULL!) */
+ } var_val;
+} var;
+
+#define VAR_UNKNOWN 0
+#define VAR_NUMBER 1
+#define VAR_STRING 2
+
+typedef var * VAR;
+
+/*
+ * All user-defined global variables are stored in "variables".
+ */
+garray_T variables = {0, 0, sizeof(var), 4, NULL};
+
+/*
+ * Array to hold an array with variables local to each sourced script.
+ */
+static garray_T ga_scripts = {0, 0, sizeof(garray_T), 4, NULL};
+#define SCRIPT_VARS(id) (((garray_T *)ga_scripts.ga_data)[(id) - 1])
+
+
+#define VAR_ENTRY(idx) (((VAR)(variables.ga_data))[idx])
+#define VAR_GAP_ENTRY(idx, gap) (((VAR)(gap->ga_data))[idx])
+#define BVAR_ENTRY(idx) (((VAR)(curbuf->b_vars.ga_data))[idx])
+#define WVAR_ENTRY(idx) (((VAR)(curwin->w_vars.ga_data))[idx])
+
+static int echo_attr = 0; /* attributes used for ":echo" */
+
+/*
+ * Structure to hold info for a user function.
+ */
+typedef struct ufunc ufunc_T;
+
+struct ufunc
+{
+ ufunc_T *next; /* next function in list */
+ char_u *name; /* name of function; can start with <SNR>123_
+ (<SNR> is K_SPECIAL KS_EXTRA KE_SNR) */
+ int varargs; /* variable nr of arguments */
+ int flags;
+ int calls; /* nr of active calls */
+ garray_T args; /* arguments */
+ garray_T lines; /* function lines */
+ scid_T script_ID; /* ID of script where function was defined,
+ used for s: variables */
+};
+
+/* function flags */
+#define FC_ABORT 1 /* abort function on error */
+#define FC_RANGE 2 /* function accepts range */
+
+/*
+ * All user-defined functions are found in the forward-linked function list.
+ * The first function is pointed at by firstfunc.
+ */
+ufunc_T *firstfunc = NULL;
+
+#define FUNCARG(fp, j) ((char_u **)(fp->args.ga_data))[j]
+#define FUNCLINE(fp, j) ((char_u **)(fp->lines.ga_data))[j]
+
+/* structure to hold info for a function that is currently being executed. */
+struct funccall
+{
+ ufunc_T *func; /* function being called */
+ int linenr; /* next line to be executed */
+ int returned; /* ":return" used */
+ int argcount; /* nr of arguments */
+ VAR argvars; /* arguments */
+ var a0_var; /* "a:0" variable */
+ var firstline; /* "a:firstline" variable */
+ var lastline; /* "a:lastline" variable */
+ garray_T l_vars; /* local function variables */
+ VAR retvar; /* return value variable */
+ linenr_T breakpoint; /* next line with breakpoint or zero */
+ int dbg_tick; /* debug_tick when breakpoint was set */
+ int level; /* top nesting level of executed function */
+};
+
+/*
+ * Return the name of the executed function.
+ */
+ char_u *
+func_name(cookie)
+ void *cookie;
+{
+ return ((struct funccall *)cookie)->func->name;
+}
+
+/*
+ * Return the address holding the next breakpoint line for a funccall cookie.
+ */
+ linenr_T *
+func_breakpoint(cookie)
+ void *cookie;
+{
+ return &((struct funccall *)cookie)->breakpoint;
+}
+
+/*
+ * Return the address holding the debug tick for a funccall cookie.
+ */
+ int *
+func_dbg_tick(cookie)
+ void *cookie;
+{
+ return &((struct funccall *)cookie)->dbg_tick;
+}
+
+/*
+ * Return the nesting level for a funccall cookie.
+ */
+ int
+func_level(cookie)
+ void *cookie;
+{
+ return ((struct funccall *)cookie)->level;
+}
+
+/* pointer to funccal for currently active function */
+struct funccall *current_funccal = NULL;
+
+/*
+ * Return TRUE when a function was ended by a ":return" command.
+ */
+ int
+current_func_returned()
+{
+ return current_funccal->returned;
+}
+
+
+/*
+ * Array to hold the value of v: variables.
+ */
+#include "version.h"
+
+/* values for flags: */
+#define VV_COMPAT 1 /* compatible, also used without "v:" */
+#define VV_RO 2 /* read-only */
+
+struct vimvar
+{
+ char *name; /* name of variable, without v: */
+ int len; /* length of name */
+ char_u *val; /* current value (can also be a number!) */
+ char type; /* VAR_NUMBER or VAR_STRING */
+ char flags; /* VV_COMPAT and VV_RO */
+} vimvars[VV_LEN] =
+{ /* The order here must match the VV_ defines in vim.h! */
+ {"count", sizeof("count") - 1, NULL, VAR_NUMBER, VV_COMPAT+VV_RO},
+ {"count1", sizeof("count1") - 1, NULL, VAR_NUMBER, VV_RO},
+ {"prevcount", sizeof("prevcount") - 1, NULL, VAR_NUMBER, VV_RO},
+ {"errmsg", sizeof("errmsg") - 1, NULL, VAR_STRING, VV_COMPAT},
+ {"warningmsg", sizeof("warningmsg") - 1, NULL, VAR_STRING, 0},
+ {"statusmsg", sizeof("statusmsg") - 1, NULL, VAR_STRING, 0},
+ {"shell_error", sizeof("shell_error") - 1, NULL, VAR_NUMBER,
+ VV_COMPAT+VV_RO},
+ {"this_session", sizeof("this_session") - 1, NULL, VAR_STRING, VV_COMPAT},
+ {"version", sizeof("version") - 1, (char_u *)VIM_VERSION_100,
+ VAR_NUMBER, VV_COMPAT+VV_RO},
+ {"lnum", sizeof("lnum") - 1, NULL, VAR_NUMBER, VV_RO},
+ {"termresponse", sizeof("termresponse") - 1, NULL, VAR_STRING, VV_RO},
+ {"fname", sizeof("fname") - 1, NULL, VAR_STRING, VV_RO},
+ {"lang", sizeof("lang") - 1, NULL, VAR_STRING, VV_RO},
+ {"lc_time", sizeof("lc_time") - 1, NULL, VAR_STRING, VV_RO},
+ {"ctype", sizeof("ctype") - 1, NULL, VAR_STRING, VV_RO},
+ {"charconvert_from", sizeof("charconvert_from") - 1, NULL, VAR_STRING, VV_RO},
+ {"charconvert_to", sizeof("charconvert_to") - 1, NULL, VAR_STRING, VV_RO},
+ {"fname_in", sizeof("fname_in") - 1, NULL, VAR_STRING, VV_RO},
+ {"fname_out", sizeof("fname_out") - 1, NULL, VAR_STRING, VV_RO},
+ {"fname_new", sizeof("fname_new") - 1, NULL, VAR_STRING, VV_RO},
+ {"fname_diff", sizeof("fname_diff") - 1, NULL, VAR_STRING, VV_RO},
+ {"cmdarg", sizeof("cmdarg") - 1, NULL, VAR_STRING, VV_RO},
+ {"foldstart", sizeof("foldstart") - 1, NULL, VAR_NUMBER, VV_RO},
+ {"foldend", sizeof("foldend") - 1, NULL, VAR_NUMBER, VV_RO},
+ {"folddashes", sizeof("folddashes") - 1, NULL, VAR_STRING, VV_RO},
+ {"foldlevel", sizeof("foldlevel") - 1, NULL, VAR_NUMBER, VV_RO},
+ {"progname", sizeof("progname") - 1, NULL, VAR_STRING, VV_RO},
+ {"servername", sizeof("servername") - 1, NULL, VAR_STRING, VV_RO},
+ {"dying", sizeof("dying") - 1, NULL, VAR_NUMBER, VV_RO},
+ {"exception", sizeof("exception") - 1, NULL, VAR_STRING, VV_RO},
+ {"throwpoint", sizeof("throwpoint") - 1, NULL, VAR_STRING, VV_RO},
+ {"register", sizeof("register") - 1, NULL, VAR_STRING, VV_RO},
+ {"cmdbang", sizeof("cmdbang") - 1, NULL, VAR_NUMBER, VV_RO},
+};
+
+static int eval0 __ARGS((char_u *arg, VAR retvar, char_u **nextcmd, int evaluate));
+static int eval1 __ARGS((char_u **arg, VAR retvar, int evaluate));
+static int eval2 __ARGS((char_u **arg, VAR retvar, int evaluate));
+static int eval3 __ARGS((char_u **arg, VAR retvar, int evaluate));
+static int eval4 __ARGS((char_u **arg, VAR retvar, int evaluate));
+static int eval5 __ARGS((char_u **arg, VAR retvar, int evaluate));
+static int eval6 __ARGS((char_u **arg, VAR retvar, int evaluate));
+static int eval7 __ARGS((char_u **arg, VAR retvar, int evaluate));
+static int get_option_var __ARGS((char_u **arg, VAR retvar, int evaluate));
+static int get_string_var __ARGS((char_u **arg, VAR retvar, int evaluate));
+static int get_lit_string_var __ARGS((char_u **arg, VAR retvar, int evaluate));
+static int get_env_var __ARGS((char_u **arg, VAR retvar, int evaluate));
+static int find_internal_func __ARGS((char_u *name));
+static int get_func_var __ARGS((char_u *name, int len, VAR retvar, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate));
+static int call_func __ARGS((char_u *name, int len, VAR retvar, int argcount, VAR argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate));
+static void f_append __ARGS((VAR argvars, VAR retvar));
+static void f_argc __ARGS((VAR argvars, VAR retvar));
+static void f_argidx __ARGS((VAR argvars, VAR retvar));
+static void f_argv __ARGS((VAR argvars, VAR retvar));
+static void f_browse __ARGS((VAR argvars, VAR retvar));
+static buf_T *find_buffer __ARGS((VAR avar));
+static void f_bufexists __ARGS((VAR argvars, VAR retvar));
+static void f_buflisted __ARGS((VAR argvars, VAR retvar));
+static void f_bufloaded __ARGS((VAR argvars, VAR retvar));
+static buf_T *get_buf_var __ARGS((VAR avar));
+static void f_bufname __ARGS((VAR argvars, VAR retvar));
+static void f_bufnr __ARGS((VAR argvars, VAR retvar));
+static void f_bufwinnr __ARGS((VAR argvars, VAR retvar));
+static void f_byte2line __ARGS((VAR argvars, VAR retvar));
+static void f_char2nr __ARGS((VAR argvars, VAR retvar));
+static void f_cindent __ARGS((VAR argvars, VAR retvar));
+static void f_col __ARGS((VAR argvars, VAR retvar));
+static void f_confirm __ARGS((VAR argvars, VAR retvar));
+static void f_cscope_connection __ARGS((VAR argvars, VAR retvar));
+static void f_cursor __ARGS((VAR argsvars, VAR retvar));
+static void f_delete __ARGS((VAR argvars, VAR retvar));
+static void f_did_filetype __ARGS((VAR argvars, VAR retvar));
+static void f_escape __ARGS((VAR argvars, VAR retvar));
+static void f_eventhandler __ARGS((VAR argvars, VAR retvar));
+static void f_executable __ARGS((VAR argvars, VAR retvar));
+static void f_exists __ARGS((VAR argvars, VAR retvar));
+static void f_expand __ARGS((VAR argvars, VAR retvar));
+static void f_filereadable __ARGS((VAR argvars, VAR retvar));
+static void f_filewritable __ARGS((VAR argvars, VAR retvar));
+static void f_fnamemodify __ARGS((VAR argvars, VAR retvar));
+static void f_foldclosed __ARGS((VAR argvars, VAR retvar));
+static void f_foldclosedend __ARGS((VAR argvars, VAR retvar));
+static void foldclosed_both __ARGS((VAR argvars, VAR retvar, int end));
+static void f_foldlevel __ARGS((VAR argvars, VAR retvar));
+static void f_foldtext __ARGS((VAR argvars, VAR retvar));
+static void f_foreground __ARGS((VAR argvars, VAR retvar));
+static void f_getbufvar __ARGS((VAR argvars, VAR retvar));
+static void f_getchar __ARGS((VAR argvars, VAR retvar));
+static void f_getcharmod __ARGS((VAR argvars, VAR retvar));
+static void f_getcmdline __ARGS((VAR argvars, VAR retvar));
+static void f_getcmdpos __ARGS((VAR argvars, VAR retvar));
+static void f_getcwd __ARGS((VAR argvars, VAR retvar));
+static void f_getfsize __ARGS((VAR argvars, VAR retvar));
+static void f_getftime __ARGS((VAR argvars, VAR retvar));
+static void f_getline __ARGS((VAR argvars, VAR retvar));
+static void f_getreg __ARGS((VAR argvars, VAR retvar));
+static void f_getregtype __ARGS((VAR argvars, VAR retvar));
+static void f_getwinposx __ARGS((VAR argvars, VAR retvar));
+static void f_getwinposy __ARGS((VAR argvars, VAR retvar));
+static void f_getwinvar __ARGS((VAR argvars, VAR retvar));
+static void f_glob __ARGS((VAR argvars, VAR retvar));
+static void f_globpath __ARGS((VAR argvars, VAR retvar));
+static void f_has __ARGS((VAR argvars, VAR retvar));
+static void f_hasmapto __ARGS((VAR argvars, VAR retvar));
+static void f_histadd __ARGS((VAR argvars, VAR retvar));
+static void f_histdel __ARGS((VAR argvars, VAR retvar));
+static void f_histget __ARGS((VAR argvars, VAR retvar));
+static void f_histnr __ARGS((VAR argvars, VAR retvar));
+static void f_hlexists __ARGS((VAR argvars, VAR retvar));
+static void f_hlID __ARGS((VAR argvars, VAR retvar));
+static void f_hostname __ARGS((VAR argvars, VAR retvar));
+static void f_iconv __ARGS((VAR argvars, VAR retvar));
+static void f_indent __ARGS((VAR argvars, VAR retvar));
+static void f_isdirectory __ARGS((VAR argvars, VAR retvar));
+static void f_input __ARGS((VAR argvars, VAR retvar));
+static void f_inputdialog __ARGS((VAR argvars, VAR retvar));
+static void f_inputrestore __ARGS((VAR argvars, VAR retvar));
+static void f_inputsave __ARGS((VAR argvars, VAR retvar));
+static void f_inputsecret __ARGS((VAR argvars, VAR retvar));
+static void f_last_buffer_nr __ARGS((VAR argvars, VAR retvar));
+static void f_libcall __ARGS((VAR argvars, VAR retvar));
+static void f_libcallnr __ARGS((VAR argvars, VAR retvar));
+static void libcall_common __ARGS((VAR argvars, VAR retvar, int type));
+static void f_line __ARGS((VAR argvars, VAR retvar));
+static void f_line2byte __ARGS((VAR argvars, VAR retvar));
+static void f_lispindent __ARGS((VAR argvars, VAR retvar));
+static void f_localtime __ARGS((VAR argvars, VAR retvar));
+static void f_maparg __ARGS((VAR argvars, VAR retvar));
+static void f_mapcheck __ARGS((VAR argvars, VAR retvar));
+static void get_maparg __ARGS((VAR argvars, VAR retvar, int exact));
+static void f_match __ARGS((VAR argvars, VAR retvar));
+static void f_matchend __ARGS((VAR argvars, VAR retvar));
+static void f_matchstr __ARGS((VAR argvars, VAR retvar));
+static void f_mode __ARGS((VAR argvars, VAR retvar));
+static void f_nextnonblank __ARGS((VAR argvars, VAR retvar));
+static void f_nr2char __ARGS((VAR argvars, VAR retvar));
+static void f_prevnonblank __ARGS((VAR argvars, VAR retvar));
+static void f_setbufvar __ARGS((VAR argvars, VAR retvar));
+static void f_setcmdpos __ARGS((VAR argvars, VAR retvar));
+static void f_setwinvar __ARGS((VAR argvars, VAR retvar));
+static void f_rename __ARGS((VAR argvars, VAR retvar));
+static void f_resolve __ARGS((VAR argvars, VAR retvar));
+static void f_search __ARGS((VAR argvars, VAR retvar));
+static void f_searchpair __ARGS((VAR argvars, VAR retvar));
+static int get_search_arg __ARGS((VAR varp, int *flagsp));
+static void f_remote_expr __ARGS((VAR argvars, VAR retvar));
+static void f_remote_foreground __ARGS((VAR argvars, VAR retvar));
+static void f_remote_peek __ARGS((VAR argvars, VAR retvar));
+static void f_remote_read __ARGS((VAR argvars, VAR retvar));
+static void f_remote_send __ARGS((VAR argvars, VAR retvar));
+static void f_server2client __ARGS((VAR argvars, VAR retvar));
+static void f_serverlist __ARGS((VAR argvars, VAR retvar));
+static void f_setline __ARGS((VAR argvars, VAR retvar));
+static void f_setreg __ARGS((VAR argvars, VAR retvar));
+static void f_simplify __ARGS((VAR argvars, VAR retvar));
+static void find_some_match __ARGS((VAR argvars, VAR retvar, int start));
+static void f_strftime __ARGS((VAR argvars, VAR retvar));
+static void f_stridx __ARGS((VAR argvars, VAR retvar));
+static void f_strlen __ARGS((VAR argvars, VAR retvar));
+static void f_strpart __ARGS((VAR argvars, VAR retvar));
+static void f_strridx __ARGS((VAR argvars, VAR retvar));
+static void f_strtrans __ARGS((VAR argvars, VAR retvar));
+static void f_synID __ARGS((VAR argvars, VAR retvar));
+static void f_synIDattr __ARGS((VAR argvars, VAR retvar));
+static void f_synIDtrans __ARGS((VAR argvars, VAR retvar));
+static void f_system __ARGS((VAR argvars, VAR retvar));
+static void f_submatch __ARGS((VAR argvars, VAR retvar));
+static void f_substitute __ARGS((VAR argvars, VAR retvar));
+static void f_tempname __ARGS((VAR argvars, VAR retvar));
+static void f_tolower __ARGS((VAR argvars, VAR retvar));
+static void f_toupper __ARGS((VAR argvars, VAR retvar));
+static void f_type __ARGS((VAR argvars, VAR retvar));
+static void f_virtcol __ARGS((VAR argvars, VAR retvar));
+static void f_visualmode __ARGS((VAR argvars, VAR retvar));
+static void f_winbufnr __ARGS((VAR argvars, VAR retvar));
+static void f_wincol __ARGS((VAR argvars, VAR retvar));
+static void f_winheight __ARGS((VAR argvars, VAR retvar));
+static void f_winline __ARGS((VAR argvars, VAR retvar));
+static void f_winnr __ARGS((VAR argvars, VAR retvar));
+static void f_winrestcmd __ARGS((VAR argvars, VAR retvar));
+static void f_winwidth __ARGS((VAR argvars, VAR retvar));
+static win_T *find_win_by_nr __ARGS((VAR vp));
+static pos_T *var2fpos __ARGS((VAR varp, int lnum));
+static int get_env_len __ARGS((char_u **arg));
+static int get_id_len __ARGS((char_u **arg));
+static int get_func_len __ARGS((char_u **arg, char_u **alias, int evaluate));
+static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end));
+static int eval_isnamec __ARGS((int c));
+static int find_vim_var __ARGS((char_u *name, int len));
+static int get_var_var __ARGS((char_u *name, int len, VAR retvar));
+static VAR alloc_var __ARGS((void));
+static VAR alloc_string_var __ARGS((char_u *string));
+static void free_var __ARGS((VAR varp));
+static void clear_var __ARGS((VAR varp));
+static long get_var_number __ARGS((VAR varp));
+static linenr_T get_var_lnum __ARGS((VAR argvars));
+static char_u *get_var_string __ARGS((VAR varp));
+static char_u *get_var_string_buf __ARGS((VAR varp, char_u *buf));
+static VAR find_var __ARGS((char_u *name, int writing));
+static VAR find_var_in_ga __ARGS((garray_T *gap, char_u *varname));
+static garray_T *find_var_ga __ARGS((char_u *name, char_u **varname));
+static void var_free_one __ARGS((VAR v));
+static void list_one_var __ARGS((VAR v, char_u *prefix));
+static void list_vim_var __ARGS((int i));
+static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
+static void set_var __ARGS((char_u *name, VAR varp));
+static void copy_var __ARGS((VAR from, VAR to));
+static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
+static char_u *trans_function_name __ARGS((char_u **pp, int skip, int internal));
+static int eval_fname_script __ARGS((char_u *p));
+static int eval_fname_sid __ARGS((char_u *p));
+static void list_func_head __ARGS((ufunc_T *fp, int indent));
+static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
+static ufunc_T *find_func __ARGS((char_u *name));
+static void call_user_func __ARGS((ufunc_T *fp, int argcount, VAR argvars, VAR retvar, linenr_T firstline, linenr_T lastline));
+
+/* Magic braces are always enabled, otherwise Vim scripts would not be
+ * portable. */
+#define FEAT_MAGIC_BRACES
+
+#ifdef FEAT_MAGIC_BRACES
+static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end));
+#endif
+
+/*
+ * Set an internal variable to a string value. Creates the variable if it does
+ * not already exist.
+ */
+ void
+set_internal_string_var(name, value)
+ char_u *name;
+ char_u *value;
+{
+ char_u *val;
+ VAR varp;
+
+ val = vim_strsave(value);
+ if (val != NULL)
+ {
+ varp = alloc_string_var(val);
+ if (varp != NULL)
+ {
+ set_var(name, varp);
+ free_var(varp);
+ }
+ }
+}
+
+# if defined(FEAT_MBYTE) || defined(PROTO)
+ int
+eval_charconvert(enc_from, enc_to, fname_from, fname_to)
+ char_u *enc_from;
+ char_u *enc_to;
+ char_u *fname_from;
+ char_u *fname_to;
+{
+ int err = FALSE;
+
+ set_vim_var_string(VV_CC_FROM, enc_from, -1);
+ set_vim_var_string(VV_CC_TO, enc_to, -1);
+ set_vim_var_string(VV_FNAME_IN, fname_from, -1);
+ set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
+ if (eval_to_bool(p_ccv, &err, NULL, FALSE))
+ err = TRUE;
+ set_vim_var_string(VV_CC_FROM, NULL, -1);
+ set_vim_var_string(VV_CC_TO, NULL, -1);
+ set_vim_var_string(VV_FNAME_IN, NULL, -1);
+ set_vim_var_string(VV_FNAME_OUT, NULL, -1);
+
+ if (err)
+ return FAIL;
+ return OK;
+}
+# endif
+
+# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
+ int
+eval_printexpr(fname, args)
+ char_u *fname;
+ char_u *args;
+{
+ int err = FALSE;
+
+ set_vim_var_string(VV_FNAME_IN, fname, -1);
+ set_vim_var_string(VV_CMDARG, args, -1);
+ if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
+ err = TRUE;
+ set_vim_var_string(VV_FNAME_IN, NULL, -1);
+ set_vim_var_string(VV_CMDARG, NULL, -1);
+
+ if (err)
+ {
+ mch_remove(fname);
+ return FAIL;
+ }
+ return OK;
+}
+# endif
+
+# if defined(FEAT_DIFF) || defined(PROTO)
+ void
+eval_diff(origfile, newfile, outfile)
+ char_u *origfile;
+ char_u *newfile;
+ char_u *outfile;
+{
+ int err = FALSE;
+
+ set_vim_var_string(VV_FNAME_IN, origfile, -1);
+ set_vim_var_string(VV_FNAME_NEW, newfile, -1);
+ set_vim_var_string(VV_FNAME_OUT, outfile, -1);
+ (void)eval_to_bool(p_dex, &err, NULL, FALSE);
+ set_vim_var_string(VV_FNAME_IN, NULL, -1);
+ set_vim_var_string(VV_FNAME_NEW, NULL, -1);
+ set_vim_var_string(VV_FNAME_OUT, NULL, -1);
+}
+
+ void
+eval_patch(origfile, difffile, outfile)
+ char_u *origfile;
+ char_u *difffile;
+ char_u *outfile;
+{
+ int err;
+
+ set_vim_var_string(VV_FNAME_IN, origfile, -1);
+ set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
+ set_vim_var_string(VV_FNAME_OUT, outfile, -1);
+ (void)eval_to_bool(p_pex, &err, NULL, FALSE);
+ set_vim_var_string(VV_FNAME_IN, NULL, -1);
+ set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
+ set_vim_var_string(VV_FNAME_OUT, NULL, -1);
+}
+# endif
+
+/*
+ * Top level evaluation function, returning a boolean.
+ * Sets "error" to TRUE if there was an error.
+ * Return TRUE or FALSE.
+ */
+ int
+eval_to_bool(arg, error, nextcmd, skip)
+ char_u *arg;
+ int *error;
+ char_u **nextcmd;
+ int skip; /* only parse, don't execute */
+{
+ var retvar;
+ int retval = FALSE;
+
+ if (skip)
+ ++emsg_skip;
+ if (eval0(arg, &retvar, nextcmd, !skip) == FAIL)
+ {
+ *error = TRUE;
+ }
+ else
+ {
+ *error = FALSE;
+ if (!skip)
+ {
+ retval = (get_var_number(&retvar) != 0);
+ clear_var(&retvar);
+ }
+ }
+ if (skip)
+ --emsg_skip;
+
+ return retval;
+}
+
+/*
+ * Top level evaluation function, returning a string. If "skip" is TRUE,
+ * only parsing to "nextcmd" is done, without reporting errors. Return
+ * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
+ */
+ char_u *
+eval_to_string_skip(arg, nextcmd, skip)
+ char_u *arg;
+ char_u **nextcmd;
+ int skip; /* only parse, don't execute */
+{
+ var retvar;
+ char_u *retval;
+
+ if (skip)
+ ++emsg_skip;
+ if (eval0(arg, &retvar, nextcmd, !skip) == FAIL || skip)
+ retval = NULL;
+ else
+ {
+ retval = vim_strsave(get_var_string(&retvar));
+ clear_var(&retvar);
+ }
+ if (skip)
+ --emsg_skip;
+
+ return retval;
+}
+
+/*
+ * Top level evaluation function, returning a string.
+ * Return pointer to allocated memory, or NULL for failure.
+ */
+ char_u *
+eval_to_string(arg, nextcmd)
+ char_u *arg;
+ char_u **nextcmd;
+{
+ var retvar;
+ char_u *retval;
+
+ if (eval0(arg, &retvar, nextcmd, TRUE) == FAIL)
+ retval = NULL;
+ else
+ {
+ retval = vim_strsave(get_var_string(&retvar));
+ clear_var(&retvar);
+ }
+
+ return retval;
+}
+
+/*
+ * Call eval_to_string() with "sandbox" set and not using local variables.
+ */
+ char_u *
+eval_to_string_safe(arg, nextcmd)
+ char_u *arg;
+ char_u **nextcmd;
+{
+ char_u *retval;
+ void *save_funccalp;
+
+ save_funccalp = save_funccal();
+ ++sandbox;
+ retval = eval_to_string(arg, nextcmd);
+ --sandbox;
+ restore_funccal(save_funccalp);
+ return retval;
+}
+
+#if 0 /* not used */
+/*
+ * Top level evaluation function, returning a string.
+ * Advances "arg" to the first non-blank after the evaluated expression.
+ * Return pointer to allocated memory, or NULL for failure.
+ * Doesn't give error messages.
+ */
+ char_u *
+eval_arg_to_string(arg)
+ char_u **arg;
+{
+ var retvar;
+ char_u *retval;
+ int ret;
+
+ ++emsg_off;
+
+ ret = eval1(arg, &retvar, TRUE);
+ if (ret == FAIL)
+ retval = NULL;
+ else
+ {
+ retval = vim_strsave(get_var_string(&retvar));
+ clear_var(&retvar);
+ }
+
+ --emsg_off;
+
+ return retval;
+}
+#endif
+
+/*
+ * Top level evaluation function, returning a number.
+ * Evaluates "expr" silently.
+ * Returns -1 for an error.
+ */
+ int
+eval_to_number(expr)
+ char_u *expr;
+{
+ var retvar;
+ int retval;
+ char_u *p = expr;
+
+ ++emsg_off;
+
+ if (eval1(&p, &retvar, TRUE) == FAIL)
+ retval = -1;
+ else
+ {
+ retval = get_var_number(&retvar);
+ clear_var(&retvar);
+ }
+ --emsg_off;
+
+ return retval;
+}
+
+#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
+/*
+ * Call some vimL function and return the result as a string
+ * Uses argv[argc] for the function arguments.
+ */
+ char_u *
+call_vim_function(func, argc, argv, safe)
+ char_u *func;
+ int argc;
+ char_u **argv;
+ int safe; /* use the sandbox */
+{
+ char_u *retval = NULL;
+ var retvar;
+ VAR argvars;
+ long n;
+ int len;
+ int i;
+ int doesrange;
+ void *save_funccalp = NULL;
+
+ argvars = (VAR)alloc((unsigned)(argc * sizeof(var)));
+ if (argvars == NULL)
+ return NULL;
+
+ for (i = 0; i < argc; i++)
+ {
+ /* Recognize a number argument, the others must be strings. */
+ vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
+ if (len != 0 && len == (int)STRLEN(argv[i]))
+ {
+ argvars[i].var_type = VAR_NUMBER;
+ argvars[i].var_val.var_number = n;
+ }
+ else
+ {
+ argvars[i].var_type = VAR_STRING;
+ argvars[i].var_val.var_string = argv[i];
+ }
+ }
+
+ if (safe)
+ {
+ save_funccalp = save_funccal();
+ ++sandbox;
+ }
+
+ retvar.var_type = VAR_UNKNOWN; /* clear_var() uses this */
+ if (call_func(func, (int)STRLEN(func), &retvar, argc, argvars,
+ curwin->w_cursor.lnum, curwin->w_cursor.lnum,
+ &doesrange, TRUE) == OK)
+ retval = vim_strsave(get_var_string(&retvar));
+
+ clear_var(&retvar);
+ vim_free(argvars);
+
+ if (safe)
+ {
+ --sandbox;
+ restore_funccal(save_funccalp);
+ }
+ return retval;
+}
+#endif
+
+/*
+ * Save the current function call pointer, and set it to NULL.
+ * Used when executing autocommands and for ":source".
+ */
+ void *
+save_funccal()
+{
+ struct funccall *fc;
+
+ fc = current_funccal;
+ current_funccal = NULL;
+ return (void *)fc;
+}
+
+ void
+restore_funccal(fc)
+ void *fc;
+{
+ current_funccal = (struct funccall *)fc;
+}
+
+#ifdef FEAT_FOLDING
+/*
+ * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
+ * it in "*cp". Doesn't give error messages.
+ */
+ int
+eval_foldexpr(arg, cp)
+ char_u *arg;
+ int *cp;
+{
+ var retvar;
+ int retval;
+ char_u *s;
+
+ ++emsg_off;
+ ++sandbox;
+ *cp = NUL;
+ if (eval0(arg, &retvar, NULL, TRUE) == FAIL)
+ retval = 0;
+ else
+ {
+ /* If the result is a number, just return the number. */
+ if (retvar.var_type == VAR_NUMBER)
+ retval = retvar.var_val.var_number;
+ else if (retvar.var_type == VAR_UNKNOWN
+ || retvar.var_val.var_string == NULL)
+ retval = 0;
+ else
+ {
+ /* If the result is a string, check if there is a non-digit before
+ * the number. */
+ s = retvar.var_val.var_string;
+ if (!VIM_ISDIGIT(*s) && *s != '-')
+ *cp = *s++;
+ retval = atol((char *)s);
+ }
+ clear_var(&retvar);
+ }
+ --emsg_off;
+ --sandbox;
+
+ return retval;
+}
+#endif
+
+#ifdef FEAT_MAGIC_BRACES
+/*
+ * Expands out the 'magic' {}'s in a variable/function name.
+ * Note that this can call itself recursively, to deal with
+ * constructs like foo{bar}{baz}{bam}
+ * The four pointer arguments point to "foo{expre}ss{ion}bar"
+ * "in_start" ^
+ * "expr_start" ^
+ * "expr_end" ^
+ * "in_end" ^
+ *
+ * Returns a new allocated string, which the caller must free.
+ * Returns NULL for failure.
+ */
+ static char_u *
+make_expanded_name(in_start, expr_start, expr_end, in_end)
+ char_u *in_start;
+ char_u *expr_start;
+ char_u *expr_end;
+ char_u *in_end;
+{
+ char_u c1;
+ char_u *retval = NULL;
+ char_u *temp_result;
+ char_u *nextcmd = NULL;
+
+ if (expr_end == NULL || in_end == NULL)
+ return NULL;
+ *expr_start = NUL;
+ *expr_end = NUL;
+ c1 = *in_end;
+ *in_end = NUL;
+
+ temp_result = eval_to_string(expr_start + 1, &nextcmd);
+ if (temp_result != NULL && nextcmd == NULL)
+ {
+ retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
+ + (in_end - expr_end) + 1));
+
+ if (retval != NULL)
+ {
+ STRCPY(retval, in_start);
+ STRCAT(retval, temp_result);
+ STRCAT(retval, expr_end + 1);
+ }
+ }
+ vim_free(temp_result);
+
+ *in_end = c1; /* put char back for error messages */
+ *expr_start = '{';
+ *expr_end = '}';
+
+ if (retval != NULL)
+ {
+ temp_result = find_name_end(retval, &expr_start, &expr_end);
+ if (expr_start != NULL)
+ {
+ /* Further expansion! */
+ temp_result = make_expanded_name(retval, expr_start,
+ expr_end, temp_result);
+ vim_free(retval);
+ retval = temp_result;
+ }
+ }
+
+ return retval;
+
+}
+#endif /* FEAT_MAGIC_BRACES */
+
+/*
+ * ":let var = expr" assignment command.
+ * ":let var" list one variable value
+ * ":let" list all variable values
+ */
+ void
+ex_let(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+ char_u *expr;
+ char_u *name;
+ VAR varp;
+ var retvar;
+ char_u *p;
+ int c1 = 0, c2;
+ int i;
+ char_u *expr_start;
+ char_u *expr_end;
+ char_u *name_end;
+
+ name_end = find_name_end(arg, &expr_start, &expr_end);
+ expr = vim_strchr(name_end, '=');
+ if (expr == NULL)
+ {
+ if (ends_excmd(*arg))
+ {
+ if (!eap->skip)
+ {
+ /*
+ * List all variables.
+ */
+ for (i = 0; i < variables.ga_len && !got_int; ++i)
+ if (VAR_ENTRY(i).var_name != NULL)
+ list_one_var(&VAR_ENTRY(i), (char_u *)"");
+ for (i = 0; i < curbuf->b_vars.ga_len && !got_int; ++i)
+ if (BVAR_ENTRY(i).var_name != NULL)
+ list_one_var(&BVAR_ENTRY(i), (char_u *)"b:");
+ for (i = 0; i < curwin->w_vars.ga_len && !got_int; ++i)
+ if (WVAR_ENTRY(i).var_name != NULL)
+ list_one_var(&WVAR_ENTRY(i), (char_u *)"w:");
+ for (i = 0; i < VV_LEN && !got_int; ++i)
+ if (vimvars[i].type == VAR_NUMBER || vimvars[i].val != NULL)
+ list_vim_var(i);
+ }
+ }
+ else
+ {
+ int error = FALSE;
+
+ /*
+ * List variables.
+ */
+ while (!ends_excmd(*arg) && !got_int)
+ {
+ char_u *temp_string = NULL;
+ int arg_len;
+
+ /* Find the end of the name. */
+ name_end = find_name_end(arg, &expr_start, &expr_end);
+
+ if (!vim_iswhite(*name_end) && !ends_excmd(*name_end))
+ {
+ emsg_severe = TRUE;
+ EMSG(_(e_trailing));
+ break;
+ }
+ if (!error && !eap->skip)
+ {
+#ifdef FEAT_MAGIC_BRACES
+ if (expr_start != NULL)
+ {
+ temp_string = make_expanded_name(arg, expr_start,
+ expr_end, name_end);
+ if (temp_string == NULL)
+ {
+ /*
+ * Report an invalid expression in braces, unless
+ * the expression evaluation has been cancelled due
+ * to an aborting error, an interrupt, or an
+ * exception.
+ */
+ if (!aborting())
+ {
+ emsg_severe = TRUE;
+ EMSG2(_(e_invarg2), arg);
+ break;
+ }
+ error = TRUE;
+ arg = skipwhite(name_end);
+ continue;
+ }
+ arg = temp_string;
+ arg_len = STRLEN(temp_string);
+ }
+ else
+#endif
+ {
+ c1 = *name_end;
+ *name_end = NUL;
+ arg_len = (int)(name_end - arg);
+ }
+ i = find_vim_var(arg, arg_len);
+ if (i >= 0)
+ list_vim_var(i);
+ else if (STRCMP("b:changedtick", arg) == 0)
+ {
+ char_u numbuf[NUMBUFLEN];
+
+ sprintf((char *)numbuf, "%ld",
+ (long)curbuf->b_changedtick);
+ list_one_var_a((char_u *)"b:", (char_u *)"changedtick",
+ VAR_NUMBER, numbuf);
+ }
+ else
+ {
+ varp = find_var(arg, FALSE);
+ if (varp == NULL)
+ {
+ /* Skip further arguments but do continue to
+ * search for a trailing command. */
+ EMSG2(_("E106: Unknown variable: \"%s\""), arg);
+ error = TRUE;
+ }
+ else
+ {
+ name = vim_strchr(arg, ':');
+ if (name != NULL)
+ {
+ /* "a:" vars have no name stored, use whole
+ * arg */
+ if (arg[0] == 'a' && arg[1] == ':')
+ c2 = NUL;
+ else
+ {
+ c2 = *++name;
+ *name = NUL;
+ }
+ list_one_var(varp, arg);
+ if (c2 != NUL)
+ *name = c2;
+ }
+ else
+ list_one_var(varp, (char_u *)"");
+ }
+ }
+#ifdef FEAT_MAGIC_BRACES
+ if (expr_start != NULL)
+ vim_free(temp_string);
+ else
+#endif
+ *name_end = c1;
+ }
+ arg = skipwhite(name_end);
+ }
+ }
+ eap->nextcmd = check_nextcmd(arg);
+ }
+ else
+ {
+ if (eap->skip)
+ ++emsg_skip;
+ i = eval0(expr + 1, &retvar, &eap->nextcmd, !eap->skip);
+ if (eap->skip)
+ {
+ if (i != FAIL)
+ clear_var(&retvar);
+ --emsg_skip;
+ }
+ else if (i != FAIL)
+ {
+ /*
+ * ":let $VAR = expr": Set environment variable.
+ */
+ if (*arg == '$')
+ {
+ int len;
+ int cc;
+
+ /* Find the end of the name. */
+ ++arg;
+ name = arg;
+ len = get_env_len(&arg);
+ if (len == 0)
+ EMSG2(_(e_invarg2), name - 1);
+ else
+ {
+ if (*skipwhite(arg) != '=')
+ EMSG(_(e_letunexp));
+ else
+ {
+ cc = name[len];
+ name[len] = NUL;
+ p = get_var_string(&retvar);
+ vim_setenv(name, p);
+ if (STRICMP(name, "HOME") == 0)
+ init_homedir();
+ else if (didset_vim && STRICMP(name, "VIM") == 0)
+ didset_vim = FALSE;
+ else if (didset_vimruntime
+ && STRICMP(name, "VIMRUNTIME") == 0)
+ didset_vimruntime = FALSE;
+ name[len] = cc;
+ }
+ }
+ }
+
+ /*
+ * ":let &option = expr": Set option value.
+ * ":let &l:option = expr": Set local option value.
+ * ":let &g:option = expr": Set global option value.
+ */
+ else if (*arg == '&')
+ {
+ int opt_flags;
+
+ /*
+ * Find the end of the name;
+ */
+ p = find_option_end(&arg, &opt_flags);
+ if (p == NULL || *skipwhite(p) != '=')
+ EMSG(_(e_letunexp));
+ else
+ {
+ c1 = *p;
+ *p = NUL;
+ set_option_value(arg, get_var_number(&retvar),
+ get_var_string(&retvar), opt_flags);
+ *p = c1; /* put back for error messages */
+ }
+ }
+
+ /*
+ * ":let @r = expr": Set register contents.
+ */
+ else if (*arg == '@')
+ {
+ ++arg;
+ if (*skipwhite(arg + 1) != '=')
+ EMSG(_(e_letunexp));
+ else
+ write_reg_contents(*arg == '@' ? '"' : *arg,
+ get_var_string(&retvar), -1, FALSE);
+ }
+
+ /*
+ * ":let var = expr": Set internal variable.
+ */
+ else if (eval_isnamec(*arg) && !VIM_ISDIGIT(*arg))
+ {
+ /* Find the end of the name. */
+ p = find_name_end(arg, &expr_start, &expr_end);
+
+ if (*skipwhite(p) != '=')
+ EMSG(_(e_letunexp));
+ else if (p - arg == 13
+ && STRNCMP(arg, "b:changedtick", 13) == 0)
+ EMSG2(_(e_readonlyvar), arg);
+#ifdef FEAT_MAGIC_BRACES
+ else if (expr_start != NULL)
+ {
+ char_u *temp_string;
+
+ temp_string = make_expanded_name(arg, expr_start,
+ expr_end, p);
+ if (temp_string == NULL)
+ {
+ /*
+ * Report an invalid expression in braces, unless the
+ * expression evaluation has been cancelled due to an
+ * aborting error, an interrupt, or an exception.
+ */
+ if (!aborting())
+ EMSG2(_(e_invarg2), arg);
+ }
+ else
+ {
+ set_var(temp_string, &retvar);
+ vim_free(temp_string);
+ }
+ }
+#endif
+ else
+ {
+ c1 = *p;
+ *p = NUL;
+ set_var(arg, &retvar);
+ *p = c1; /* put char back for error messages */
+ }
+ }
+
+ else
+ {
+ EMSG2(_(e_invarg2), arg);
+ }
+
+ clear_var(&retvar);
+ }
+ }
+}
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+
+ void
+set_context_for_expression(xp, arg, cmdidx)
+ expand_T *xp;
+ char_u *arg;
+ cmdidx_T cmdidx;
+{
+ int got_eq = FALSE;
+ int c;
+
+ xp->xp_context = cmdidx == CMD_let ? EXPAND_USER_VARS
+ : cmdidx == CMD_call ? EXPAND_FUNCTIONS
+ : EXPAND_EXPRESSION;
+ while ((xp->xp_pattern = vim_strpbrk(arg,
+ (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
+ {
+ c = *xp->xp_pattern;
+ if (c == '&')
+ {
+ c = xp->xp_pattern[1];
+ if (c == '&')
+ {
+ ++xp->xp_pattern;
+ xp->xp_context = cmdidx != CMD_let || got_eq
+ ? EXPAND_EXPRESSION : EXPAND_NOTHING;
+ }
+ else if (c != ' ')
+ xp->xp_context = EXPAND_SETTINGS;
+ }
+ else if (c == '$')
+ {
+ /* environment variable */
+ xp->xp_context = EXPAND_ENV_VARS;
+ }
+ else if (c == '=')
+ {
+ got_eq = TRUE;
+ xp->xp_context = EXPAND_EXPRESSION;
+ }
+ else if (c == '<'
+ && xp->xp_context == EXPAND_FUNCTIONS
+ && vim_strchr(xp->xp_pattern, '(') == NULL)
+ {
+ /* Function name can start with "<SNR>" */
+ break;
+ }
+ else if (cmdidx != CMD_let || got_eq)
+ {
+ if (c == '"') /* string */
+ {
+ while ((c = *++xp->xp_pattern) != NUL && c != '"')
+ if (c == '\\' && xp->xp_pattern[1] != NUL)
+ ++xp->xp_pattern;
+ xp->xp_context = EXPAND_NOTHING;
+ }
+ else if (c == '\'') /* literal string */
+ {
+ while ((c = *++xp->xp_pattern) != NUL && c != '\'')
+ /* skip */ ;
+ xp->xp_context = EXPAND_NOTHING;
+ }
+ else if (c == '|')
+ {
+ if (xp->xp_pattern[1] == '|')
+ {
+ ++xp->xp_pattern;
+ xp->xp_context = EXPAND_EXPRESSION;
+ }
+ else
+ xp->xp_context = EXPAND_COMMANDS;
+ }
+ else
+ xp->xp_context = EXPAND_EXPRESSION;
+ }
+ else
+ xp->xp_context = EXPAND_NOTHING;
+ arg = xp->xp_pattern;
+ if (*arg != NUL)
+ while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
+ /* skip */ ;
+ }
+ xp->xp_pattern = arg;
+}
+
+#endif /* FEAT_CMDL_COMPL */
+
+/*
+ * ":1,25call func(arg1, arg2)" function call.
+ */
+ void
+ex_call(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+ char_u *startarg;
+ char_u *alias;
+ char_u *name;
+ var retvar;
+ int len;
+ linenr_T lnum;
+ int doesrange;
+ int failed = FALSE;
+
+ name = arg;
+ len = get_func_len(&arg, &alias, !eap->skip);
+ if (len == 0)
+ goto end;
+ if (alias != NULL)
+ name = alias;
+
+ startarg = arg;
+ retvar.var_type = VAR_UNKNOWN; /* clear_var() uses this */
+
+ if (*startarg != '(')
+ {
+ EMSG2(_("E107: Missing braces: %s"), name);
+ goto end;
+ }
+
+ /*
+ * When skipping, evaluate the function once, to find the end of the
+ * arguments.
+ * When the function takes a range, this is discovered after the first
+ * call, and the loop is broken.
+ */
+ if (eap->skip)
+ {
+ ++emsg_skip;
+ lnum = eap->line2; /* do it once, also with an invalid range */
+ }
+ else
+ lnum = eap->line1;
+ for ( ; lnum <= eap->line2; ++lnum)
+ {
+ if (!eap->skip && eap->addr_count > 0)
+ {
+ curwin->w_cursor.lnum = lnum;
+ curwin->w_cursor.col = 0;
+ }
+ arg = startarg;
+ if (get_func_var(name, len, &retvar, &arg,
+ eap->line1, eap->line2, &doesrange, !eap->skip) == FAIL)
+ {
+ failed = TRUE;
+ break;
+ }
+ clear_var(&retvar);
+ if (doesrange || eap->skip)
+ break;
+ /* Stop when immediately aborting on error, or when an interrupt
+ * occurred or an exception was thrown but not caught. get_func_var()
+ * returned OK, so that the check for trailing characters below is
+ * executed. */
+ if (aborting())
+ break;
+ }
+ if (eap->skip)
+ --emsg_skip;
+
+ if (!failed)
+ {
+ /* Check for trailing illegal characters and a following command. */
+ if (!ends_excmd(*arg))
+ {
+ emsg_severe = TRUE;
+ EMSG(_(e_trailing));
+ }
+ else
+ eap->nextcmd = check_nextcmd(arg);
+ }
+
+end:
+ if (alias != NULL)
+ vim_free(alias);
+}
+
+/*
+ * ":unlet[!] var1 ... " command.
+ */
+ void
+ex_unlet(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+ char_u *name_end;
+ char_u cc;
+ char_u *expr_start;
+ char_u *expr_end;
+ int error = FALSE;
+
+ do
+ {
+ /* Find the end of the name. */
+ name_end = find_name_end(arg, &expr_start, &expr_end);
+
+ if (!vim_iswhite(*name_end) && !ends_excmd(*name_end))
+ {
+ emsg_severe = TRUE;
+ EMSG(_(e_trailing));
+ break;
+ }
+
+ if (!error && !eap->skip)
+ {
+#ifdef FEAT_MAGIC_BRACES
+ if (expr_start != NULL)
+ {
+ char_u *temp_string;
+
+ temp_string = make_expanded_name(arg, expr_start,
+ expr_end, name_end);
+ if (temp_string == NULL)
+ {
+ /*
+ * Report an invalid expression in braces, unless the
+ * expression evaluation has been cancelled due to an
+ * aborting error, an interrupt, or an exception.
+ */
+ if (!aborting())
+ {
+ emsg_severe = TRUE;
+ EMSG2(_(e_invarg2), arg);
+ break;
+ }
+ error = TRUE;
+ }
+ else
+ {
+ if (do_unlet(temp_string) == FAIL && !eap->forceit)
+ {
+ EMSG2(_("E108: No such variable: \"%s\""), temp_string);
+ error = TRUE;
+ }
+ vim_free(temp_string);
+ }
+ }
+ else
+#endif
+ {
+ cc = *name_end;
+ *name_end = NUL;
+
+ if (do_unlet(arg) == FAIL && !eap->forceit)
+ {
+ EMSG2(_("E108: No such variable: \"%s\""), arg);
+ error = TRUE;
+ }
+
+ *name_end = cc;
+ }
+ }
+ arg = skipwhite(name_end);
+ } while (!ends_excmd(*arg));
+
+ eap->nextcmd = check_nextcmd(arg);
+}
+
+/*
+ * "unlet" a variable. Return OK if it existed, FAIL if not.
+ */
+ int
+do_unlet(name)
+ char_u *name;
+{
+ VAR v;
+
+ v = find_var(name, TRUE);
+ if (v != NULL)
+ {
+ var_free_one(v);
+ return OK;
+ }
+ return FAIL;
+}
+
+#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
+/*
+ * Delete all "menutrans_" variables.
+ */
+ void
+del_menutrans_vars()
+{
+ int i;
+
+ for (i = 0; i < variables.ga_len; ++i)
+ if (VAR_ENTRY(i).var_name != NULL
+ && STRNCMP(VAR_ENTRY(i).var_name, "menutrans_", 10) == 0)
+ var_free_one(&VAR_ENTRY(i));
+}
+#endif
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+
+/*
+ * Local string buffer for the next two functions to store a variable name
+ * with its prefix. Allocated in cat_prefix_varname(), freed later in
+ * get_user_var_name().
+ */
+
+static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name));
+
+static char_u *varnamebuf = NULL;
+static int varnamebuflen = 0;
+
+/*
+ * Function to concatenate a prefix and a variable name.
+ */
+ static char_u *
+cat_prefix_varname(prefix, name)
+ int prefix;
+ char_u *name;
+{
+ int len;
+
+ len = (int)STRLEN(name) + 3;
+ if (len > varnamebuflen)
+ {
+ vim_free(varnamebuf);
+ len += 10; /* some additional space */
+ varnamebuf = alloc(len);
+ if (varnamebuf == NULL)
+ {
+ varnamebuflen = 0;
+ return NULL;
+ }
+ varnamebuflen = len;
+ }
+ *varnamebuf = prefix;
+ varnamebuf[1] = ':';
+ STRCPY(varnamebuf + 2, name);
+ return varnamebuf;
+}
+
+/*
+ * Function given to ExpandGeneric() to obtain the list of user defined
+ * (global/buffer/window/built-in) variable names.
+ */
+/*ARGSUSED*/
+ char_u *
+get_user_var_name(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ static int gidx;
+ static int bidx;
+ static int widx;
+ static int vidx;
+ char_u *name;
+
+ if (idx == 0)
+ gidx = bidx = widx = vidx = 0;
+ if (gidx < variables.ga_len) /* Global variables */
+ {
+ while ((name = VAR_ENTRY(gidx++).var_name) == NULL
+ && gidx < variables.ga_len)
+ /* skip */;
+ if (name != NULL)
+ {
+ if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
+ return cat_prefix_varname('g', name);
+ else
+ return name;
+ }
+ }
+ if (bidx < curbuf->b_vars.ga_len) /* Current buffer variables */
+ {
+ while ((name = BVAR_ENTRY(bidx++).var_name) == NULL
+ && bidx < curbuf->b_vars.ga_len)
+ /* skip */;
+ if (name != NULL)
+ return cat_prefix_varname('b', name);
+ }
+ if (bidx == curbuf->b_vars.ga_len)
+ {
+ ++bidx;
+ return (char_u *)"b:changedtick";
+ }
+ if (widx < curwin->w_vars.ga_len) /* Current window variables */
+ {
+ while ((name = WVAR_ENTRY(widx++).var_name) == NULL
+ && widx < curwin->w_vars.ga_len)
+ /* skip */;
+ if (name != NULL)
+ return cat_prefix_varname('w', name);
+ }
+ if (vidx < VV_LEN) /* Built-in variables */
+ return cat_prefix_varname('v', (char_u *)vimvars[vidx++].name);
+
+ vim_free(varnamebuf);
+ varnamebuf = NULL;
+ varnamebuflen = 0;
+ return NULL;
+}
+
+#endif /* FEAT_CMDL_COMPL */
+
+/*
+ * types for expressions.
+ */
+typedef enum
+{
+ TYPE_UNKNOWN = 0
+ , TYPE_EQUAL /* == */
+ , TYPE_NEQUAL /* != */
+ , TYPE_GREATER /* > */
+ , TYPE_GEQUAL /* >= */
+ , TYPE_SMALLER /* < */
+ , TYPE_SEQUAL /* <= */
+ , TYPE_MATCH /* =~ */
+ , TYPE_NOMATCH /* !~ */
+} exptype_T;
+
+/*
+ * The "evaluate" argument: When FALSE, the argument is only parsed but not
+ * executed. The function may return OK, but the retvar will be of type
+ * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
+ */
+
+/*
+ * Handle zero level expression.
+ * This calls eval1() and handles error message and nextcmd.
+ * Return OK or FAIL.
+ */
+ static int
+eval0(arg, retvar, nextcmd, evaluate)
+ char_u *arg;
+ VAR retvar;
+ char_u **nextcmd;
+ int evaluate;
+{
+ int ret;
+ char_u *p;
+
+ p = skipwhite(arg);
+ ret = eval1(&p, retvar, evaluate);
+ if (ret == FAIL || !ends_excmd(*p))
+ {
+ if (ret != FAIL)
+ clear_var(retvar);
+ /*
+ * Report the invalid expression unless the expression evaluation has
+ * been cancelled due to an aborting error, an interrupt, or an
+ * exception.
+ */
+ if (!aborting())
+ EMSG2(_(e_invexpr2), arg);
+ ret = FAIL;
+ }
+ if (nextcmd != NULL)
+ *nextcmd = check_nextcmd(p);
+
+ return ret;
+}
+
+/*
+ * Handle top level expression:
+ * expr1 ? expr0 : expr0
+ *
+ * "arg" must point to the first non-white of the expression.
+ * "arg" is advanced to the next non-white after the recognized expression.
+ *
+ * Return OK or FAIL.
+ */
+ static int
+eval1(arg, retvar, evaluate)
+ char_u **arg;
+ VAR retvar;
+ int evaluate;
+{
+ int result;
+ var var2;
+
+ /*
+ * Get the first variable.
+ */
+ if (eval2(arg, retvar, evaluate) == FAIL)
+ return FAIL;
+
+ if ((*arg)[0] == '?')
+ {
+ result = FALSE;
+ if (evaluate)
+ {
+ if (get_var_number(retvar) != 0)
+ result = TRUE;
+ clear_var(retvar);
+ }
+
+ /*
+ * Get the second variable.
+ */
+ *arg = skipwhite(*arg + 1);
+ if (eval1(arg, retvar, evaluate && result) == FAIL) /* recursive! */
+ return FAIL;
+
+ /*
+ * Check for the ":".
+ */
+ if ((*arg)[0] != ':')
+ {
+ EMSG(_("E109: Missing ':' after '?'"));
+ if (evaluate && result)
+ clear_var(retvar);
+ return FAIL;
+ }
+
+ /*
+ * Get the third variable.
+ */
+ *arg = skipwhite(*arg + 1);
+ if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
+ {
+ if (evaluate && result)
+ clear_var(retvar);
+ return FAIL;
+ }
+ if (evaluate && !result)
+ *retvar = var2;
+ }
+
+ return OK;
+}
+
+/*
+ * Handle first level expression:
+ * expr2 || expr2 || expr2 logical OR
+ *
+ * "arg" must point to the first non-white of the expression.
+ * "arg" is advanced to the next non-white after the recognized expression.
+ *
+ * Return OK or FAIL.
+ */
+ static int
+eval2(arg, retvar, evaluate)
+ char_u **arg;
+ VAR retvar;
+ int evaluate;
+{
+ var var2;
+ long result;
+ int first;
+
+ /*
+ * Get the first variable.
+ */
+ if (eval3(arg, retvar, evaluate) == FAIL)
+ return FAIL;
+
+ /*
+ * Repeat until there is no following "||".
+ */
+ first = TRUE;
+ result = FALSE;
+ while ((*arg)[0] == '|' && (*arg)[1] == '|')
+ {
+ if (evaluate && first)
+ {
+ if (get_var_number(retvar) != 0)
+ result = TRUE;
+ clear_var(retvar);
+ first = FALSE;
+ }
+
+ /*
+ * Get the second variable.
+ */
+ *arg = skipwhite(*arg + 2);
+ if (eval3(arg, &var2, evaluate && !result) == FAIL)
+ return FAIL;
+
+ /*
+ * Compute the result.
+ */
+ if (evaluate && !result)
+ {
+ if (get_var_number(&var2) != 0)
+ result = TRUE;
+ clear_var(&var2);
+ }
+ if (evaluate)
+ {
+ retvar->var_type = VAR_NUMBER;
+ retvar->var_val.var_number = result;
+ }
+ }
+
+ return OK;
+}
+
+/*
+ * Handle second level expression:
+ * expr3 && expr3 && expr3 logical AND
+ *
+ * "arg" must point to the first non-white of the expression.
+ * "arg" is advanced to the next non-white after the recognized expression.
+ *
+ * Return OK or FAIL.
+ */
+ static int
+eval3(arg, retvar, evaluate)
+ char_u **arg;
+ VAR retvar;
+ int evaluate;
+{
+ var var2;
+ long result;
+ int first;
+
+ /*
+ * Get the first variable.
+ */
+ if (eval4(arg, retvar, evaluate) == FAIL)
+ return FAIL;
+
+ /*
+ * Repeat until there is no following "&&".
+ */
+ first = TRUE;
+ result = TRUE;
+ while ((*arg)[0] == '&' && (*arg)[1] == '&')
+ {
+ if (evaluate && first)
+ {
+ if (get_var_number(retvar) == 0)
+ result = FALSE;
+ clear_var(retvar);
+ first = FALSE;
+ }
+
+ /*
+ * Get the second variable.
+ */
+ *arg = skipwhite(*arg + 2);
+ if (eval4(arg, &var2, evaluate && result) == FAIL)
+ return FAIL;
+
+ /*
+ * Compute the result.
+ */
+ if (evaluate && result)
+ {
+ if (get_var_number(&var2) == 0)
+ result = FALSE;
+ clear_var(&var2);
+ }
+ if (evaluate)
+ {
+ retvar->var_type = VAR_NUMBER;
+ retvar->var_val.var_number = result;
+ }
+ }
+
+ return OK;
+}
+
+/*
+ * Handle third level expression:
+ * var1 == var2
+ * var1 =~ var2
+ * var1 != var2
+ * var1 !~ var2
+ * var1 > var2
+ * var1 >= var2
+ * var1 < var2
+ * var1 <= var2
+ *
+ * "arg" must point to the first non-white of the expression.
+ * "arg" is advanced to the next non-white after the recognized expression.
+ *
+ * Return OK or FAIL.
+ */
+ static int
+eval4(arg, retvar, evaluate)
+ char_u **arg;
+ VAR retvar;
+ int evaluate;
+{
+ var var2;
+ char_u *p;
+ int i;
+ exptype_T type = TYPE_UNKNOWN;
+ int len = 2;
+ long n1, n2;
+ char_u *s1, *s2;
+ char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
+ regmatch_T regmatch;
+ int ic;
+ char_u *save_cpo;
+
+ /*
+ * Get the first variable.
+ */
+ if (eval5(arg, retvar, evaluate) == FAIL)
+ return FAIL;
+
+ p = *arg;
+ switch (p[0])
+ {
+ case '=': if (p[1] == '=')
+ type = TYPE_EQUAL;
+ else if (p[1] == '~')
+ type = TYPE_MATCH;
+ break;
+ case '!': if (p[1] == '=')
+ type = TYPE_NEQUAL;
+ else if (p[1] == '~')
+ type = TYPE_NOMATCH;
+ break;
+ case '>': if (p[1] != '=')
+ {
+ type = TYPE_GREATER;
+ len = 1;
+ }
+ else
+ type = TYPE_GEQUAL;
+ break;
+ case '<': if (p[1] != '=')
+ {
+ type = TYPE_SMALLER;
+ len = 1;
+ }
+ else
+ type = TYPE_SEQUAL;
+ break;
+ }
+
+ /*
+ * If there is a comparitive operator, use it.
+ */
+ if (type != TYPE_UNKNOWN)
+ {
+ /* extra question mark appended: ignore case */
+ if (p[len] == '?')
+ {
+ ic = TRUE;
+ ++len;
+ }
+ /* extra '#' appended: match case */
+ else if (p[len] == '#')
+ {
+ ic = FALSE;
+ ++len;
+ }
+ /* nothing appened: use 'ignorecase' */
+ else
+ ic = p_ic;
+
+ /*
+ * Get the second variable.
+ */
+ *arg = skipwhite(p + len);
+ if (eval5(arg, &var2, evaluate) == FAIL)
+ {
+ clear_var(retvar);
+ return FAIL;
+ }
+
+ if (evaluate)
+ {
+ /*
+ * If one of the two variables is a number, compare as a number.
+ * When using "=~" or "!~", always compare as string.
+ */
+ if ((retvar->var_type == VAR_NUMBER || var2.var_type == VAR_NUMBER)
+ && type != TYPE_MATCH && type != TYPE_NOMATCH)
+ {
+ n1 = get_var_number(retvar);
+ n2 = get_var_number(&var2);
+ switch (type)
+ {
+ case TYPE_EQUAL: n1 = (n1 == n2); break;
+ case TYPE_NEQUAL: n1 = (n1 != n2); break;
+ case TYPE_GREATER: n1 = (n1 > n2); break;
+ case TYPE_GEQUAL: n1 = (n1 >= n2); break;
+ case TYPE_SMALLER: n1 = (n1 < n2); break;
+ case TYPE_SEQUAL: n1 = (n1 <= n2); break;
+ case TYPE_UNKNOWN:
+ case TYPE_MATCH:
+ case TYPE_NOMATCH: break; /* avoid gcc warning */
+ }
+ }
+ else
+ {
+ s1 = get_var_string_buf(retvar, buf1);
+ s2 = get_var_string_buf(&var2, buf2);
+ if (type != TYPE_MATCH && type != TYPE_NOMATCH)
+ i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
+ else
+ i = 0;
+ n1 = FALSE;
+ switch (type)
+ {
+ case TYPE_EQUAL: n1 = (i == 0); break;
+ case TYPE_NEQUAL: n1 = (i != 0); break;
+ case TYPE_GREATER: n1 = (i > 0); break;
+ case TYPE_GEQUAL: n1 = (i >= 0); break;
+ case TYPE_SMALLER: n1 = (i < 0); break;
+ case TYPE_SEQUAL: n1 = (i <= 0); break;
+
+ case TYPE_MATCH:
+ case TYPE_NOMATCH:
+ /* avoid 'l' flag in 'cpoptions' */
+ save_cpo = p_cpo;
+ p_cpo = (char_u *)"";
+ regmatch.regprog = vim_regcomp(s2,
+ RE_MAGIC + RE_STRING);
+ regmatch.rm_ic = ic;
+ if (regmatch.regprog != NULL)
+ {
+ n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
+ vim_free(regmatch.regprog);
+ if (type == TYPE_NOMATCH)
+ n1 = !n1;
+ }
+ p_cpo = save_cpo;
+ break;
+
+ case TYPE_UNKNOWN: break; /* avoid gcc warning */
+ }
+ }
+ clear_var(retvar);
+ clear_var(&var2);
+ retvar->var_type = VAR_NUMBER;
+ retvar->var_val.var_number = n1;
+ }
+ }
+
+ return OK;
+}
+
+/*
+ * Handle fourth level expression:
+ * + number addition
+ * - number subtraction
+ * . string concatenation
+ *
+ * "arg" must point to the first non-white of the expression.
+ * "arg" is advanced to the next non-white after the recognized expression.
+ *
+ * Return OK or FAIL.
+ */
+ static int
+eval5(arg, retvar, evaluate)
+ char_u **arg;
+ VAR retvar;
+ int evaluate;
+{
+ var var2;
+ int op;
+ long n1, n2;
+ char_u *s1, *s2;
+ char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
+ char_u *p;
+
+ /*
+ * Get the first variable.
+ */
+ if (eval6(arg, retvar, evaluate) == FAIL)
+ return FAIL;
+
+ /*
+ * Repeat computing, until no '+', '-' or '.' is following.
+ */
+ for (;;)
+ {
+ op = **arg;
+ if (op != '+' && op != '-' && op != '.')
+ break;
+
+ /*
+ * Get the second variable.
+ */
+ *arg = skipwhite(*arg + 1);
+ if (eval6(arg, &var2, evaluate) == FAIL)
+ {
+ clear_var(retvar);
+ return FAIL;
+ }
+
+ if (evaluate)
+ {
+ /*
+ * Compute the result.
+ */
+ if (op == '.')
+ {
+ s1 = get_var_string_buf(retvar, buf1);
+ s2 = get_var_string_buf(&var2, buf2);
+ op = (int)STRLEN(s1);
+ p = alloc((unsigned)(op + STRLEN(s2) + 1));
+ if (p != NULL)
+ {
+ STRCPY(p, s1);
+ STRCPY(p + op, s2);
+ }
+ clear_var(retvar);
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = p;
+ }
+ else
+ {
+ n1 = get_var_number(retvar);
+ n2 = get_var_number(&var2);
+ clear_var(retvar);
+ if (op == '+')
+ n1 = n1 + n2;
+ else
+ n1 = n1 - n2;
+ retvar->var_type = VAR_NUMBER;
+ retvar->var_val.var_number = n1;
+ }
+ clear_var(&var2);
+ }
+ }
+ return OK;
+}
+
+/*
+ * Handle fifth level expression:
+ * * number multiplication
+ * / number division
+ * % number modulo
+ *
+ * "arg" must point to the first non-white of the expression.
+ * "arg" is advanced to the next non-white after the recognized expression.
+ *
+ * Return OK or FAIL.
+ */
+ static int
+eval6(arg, retvar, evaluate)
+ char_u **arg;
+ VAR retvar;
+ int evaluate;
+{
+ var var2;
+ int op;
+ long n1, n2;
+
+ /*
+ * Get the first variable.
+ */
+ if (eval7(arg, retvar, evaluate) == FAIL)
+ return FAIL;
+
+ /*
+ * Repeat computing, until no '*', '/' or '%' is following.
+ */
+ for (;;)
+ {
+ op = **arg;
+ if (op != '*' && op != '/' && op != '%')
+ break;
+
+ if (evaluate)
+ {
+ n1 = get_var_number(retvar);
+ clear_var(retvar);
+ }
+ else
+ n1 = 0;
+
+ /*
+ * Get the second variable.
+ */
+ *arg = skipwhite(*arg + 1);
+ if (eval7(arg, &var2, evaluate) == FAIL)
+ return FAIL;
+
+ if (evaluate)
+ {
+ n2 = get_var_number(&var2);
+ clear_var(&var2);
+
+ /*
+ * Compute the result.
+ */
+ if (op == '*')
+ n1 = n1 * n2;
+ else if (op == '/')
+ {
+ if (n2 == 0) /* give an error message? */
+ n1 = 0x7fffffffL;
+ else
+ n1 = n1 / n2;
+ }
+ else
+ {
+ if (n2 == 0) /* give an error message? */
+ n1 = 0;
+ else
+ n1 = n1 % n2;
+ }
+ retvar->var_type = VAR_NUMBER;
+ retvar->var_val.var_number = n1;
+ }
+ }
+
+ return OK;
+}
+
+/*
+ * Handle sixth level expression:
+ * number number constant
+ * "string" string contstant
+ * 'string' literal string contstant
+ * &option-name option value
+ * @r register contents
+ * identifier variable value
+ * function() function call
+ * $VAR environment variable
+ * (expression) nested expression
+ *
+ * Also handle:
+ * ! in front logical NOT
+ * - in front unary minus
+ * + in front unary plus (ignored)
+ * trailing [] subscript in String
+ *
+ * "arg" must point to the first non-white of the expression.
+ * "arg" is advanced to the next non-white after the recognized expression.
+ *
+ * Return OK or FAIL.
+ */
+ static int
+eval7(arg, retvar, evaluate)
+ char_u **arg;
+ VAR retvar;
+ int evaluate;
+{
+ var var2;
+ long n;
+ int len;
+ char_u *s;
+ int val;
+ char_u *start_leader, *end_leader;
+ int ret = OK;
+ char_u *alias;
+
+ /*
+ * Initialise variable so that clear_var() can't mistake this for a string
+ * and free a string that isn't there.
+ */
+ retvar->var_type = VAR_UNKNOWN;
+
+ /*
+ * Skip '!' and '-' characters. They are handled later.
+ */
+ start_leader = *arg;
+ while (**arg == '!' || **arg == '-' || **arg == '+')
+ *arg = skipwhite(*arg + 1);
+ end_leader = *arg;
+
+ switch (**arg)
+ {
+ /*
+ * Number constant.
+ */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
+ *arg += len;
+ if (evaluate)
+ {
+ retvar->var_type = VAR_NUMBER;
+ retvar->var_val.var_number = n;
+ }
+ break;
+
+ /*
+ * String constant: "string".
+ */
+ case '"': ret = get_string_var(arg, retvar, evaluate);
+ break;
+
+ /*
+ * Literal string constant: 'string'.
+ */
+ case '\'': ret = get_lit_string_var(arg, retvar, evaluate);
+ break;
+
+ /*
+ * Option value: &name
+ */
+ case '&': ret = get_option_var(arg, retvar, evaluate);
+ break;
+
+ /*
+ * Environment variable: $VAR.
+ */
+ case '$': ret = get_env_var(arg, retvar, evaluate);
+ break;
+
+ /*
+ * Register contents: @r.
+ */
+ case '@': ++*arg;
+ if (evaluate)
+ {
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = get_reg_contents(**arg, FALSE);
+ }
+ if (**arg != NUL)
+ ++*arg;
+ break;
+
+ /*
+ * nested expression: (expression).
+ */
+ case '(': *arg = skipwhite(*arg + 1);
+ ret = eval1(arg, retvar, evaluate); /* recursive! */
+ if (**arg == ')')
+ ++*arg;
+ else if (ret == OK)
+ {
+ EMSG(_("E110: Missing ')'"));
+ clear_var(retvar);
+ ret = FAIL;
+ }
+ break;
+
+ /*
+ * Must be a variable or function name then.
+ */
+ default: s = *arg;
+ len = get_func_len(arg, &alias, evaluate);
+ if (alias != NULL)
+ s = alias;
+
+ if (len == 0)
+ ret = FAIL;
+ else
+ {
+ if (**arg == '(') /* recursive! */
+ {
+ ret = get_func_var(s, len, retvar, arg,
+ curwin->w_cursor.lnum, curwin->w_cursor.lnum,
+ &len, evaluate);
+ /* Stop the expression evaluation when immediately
+ * aborting on error, or when an interrupt occurred or
+ * an exception was thrown but not caught. */
+ if (aborting())
+ {
+ if (ret == OK)
+ clear_var(retvar);
+ ret = FAIL;
+ }
+ }
+ else if (evaluate)
+ ret = get_var_var(s, len, retvar);
+ }
+
+ if (alias != NULL)
+ vim_free(alias);
+
+ break;
+ }
+ *arg = skipwhite(*arg);
+
+ /*
+ * Handle expr[expr] subscript.
+ */
+ if (**arg == '[' && ret == OK)
+ {
+ /*
+ * Get the variable from inside the [].
+ */
+ *arg = skipwhite(*arg + 1);
+ if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
+ {
+ clear_var(retvar);
+ return FAIL;
+ }
+
+ /* Check for the ']'. */
+ if (**arg != ']')
+ {
+ EMSG(_("E111: Missing ']'"));
+ clear_var(retvar);
+ clear_var(&var2);
+ return FAIL;
+ }
+
+ if (evaluate)
+ {
+ n = get_var_number(&var2);
+ clear_var(&var2);
+
+ /*
+ * The resulting variable is a string of a single character.
+ * If the index is too big or negative, the result is empty.
+ */
+ s = get_var_string(retvar);
+ if (n >= (long)STRLEN(s) || n < 0)
+ s = NULL;
+ else
+ s = vim_strnsave(s + n, 1);
+ clear_var(retvar);
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = s;
+ }
+ *arg = skipwhite(*arg + 1); /* skip the ']' */
+ }
+
+ /*
+ * Apply logical NOT and unary '-', from right to left, ignore '+'.
+ */
+ if (ret == OK && evaluate && end_leader > start_leader)
+ {
+ val = get_var_number(retvar);
+ while (end_leader > start_leader)
+ {
+ --end_leader;
+ if (*end_leader == '!')
+ val = !val;
+ else if (*end_leader == '-')
+ val = -val;
+ }
+ clear_var(retvar);
+ retvar->var_type = VAR_NUMBER;
+ retvar->var_val.var_number = val;
+ }
+
+ return ret;
+}
+
+/*
+ * Get an option value.
+ * "arg" points to the '&' or '+' before the option name.
+ * "arg" is advanced to character after the option name.
+ * Return OK or FAIL.
+ */
+ static int
+get_option_var(arg, retvar, evaluate)
+ char_u **arg;
+ VAR retvar; /* when NULL, only check if option exists */
+ int evaluate;
+{
+ char_u *option_end;
+ long numval;
+ char_u *stringval;
+ int opt_type;
+ int c;
+ int working = (**arg == '+'); /* has("+option") */
+ int ret = OK;
+ int opt_flags;
+
+ /*
+ * Isolate the option name and find its value.
+ */
+ option_end = find_option_end(arg, &opt_flags);
+ if (option_end == NULL)
+ {
+ if (retvar != NULL)
+ EMSG2(_("E112: Option name missing: %s"), *arg);
+ return FAIL;
+ }
+
+ if (!evaluate)
+ {
+ *arg = option_end;
+ return OK;
+ }
+
+ c = *option_end;
+ *option_end = NUL;
+ opt_type = get_option_value(*arg, &numval,
+ retvar == NULL ? NULL : &stringval, opt_flags);
+
+ if (opt_type == -3) /* invalid name */
+ {
+ if (retvar != NULL)
+ EMSG2(_("E113: Unknown option: %s"), *arg);
+ ret = FAIL;
+ }
+ else if (retvar != NULL)
+ {
+ if (opt_type == -2) /* hidden string option */
+ {
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = NULL;
+ }
+ else if (opt_type == -1) /* hidden number option */
+ {
+ retvar->var_type = VAR_NUMBER;
+ retvar->var_val.var_number = 0;
+ }
+ else if (opt_type == 1) /* number option */
+ {
+ retvar->var_type = VAR_NUMBER;
+ retvar->var_val.var_number = numval;
+ }
+ else /* string option */
+ {
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = stringval;
+ }
+ }
+ else if (working && (opt_type == -2 || opt_type == -1))
+ ret = FAIL;
+
+ *option_end = c; /* put back for error messages */
+ *arg = option_end;
+
+ return ret;
+}
+
+/*
+ * Allocate a variable for a string constant.
+ * Return OK or FAIL.
+ */
+ static int
+get_string_var(arg, retvar, evaluate)
+ char_u **arg;
+ VAR retvar;
+ int evaluate;
+{
+ char_u *p;
+ char_u *name;
+ int i;
+ int extra = 0;
+
+ /*
+ * Find the end of the string, skipping backslashed characters.
+ */
+ for (p = *arg + 1; *p && *p != '"'; ++p)
+ {
+ if (*p == '\\' && p[1] != NUL)
+ {
+ ++p;
+ /* A "\<x>" form occupies at least 4 characters, and produces up
+ * to 6 characters: reserve space for 2 extra */
+ if (*p == '<')
+ extra += 2;
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+
+ if (*p != '"')
+ {
+ EMSG2(_("E114: Missing quote: %s"), *arg);
+ return FAIL;
+ }
+
+ /* If only parsing, set *arg and return here */
+ if (!evaluate)
+ {
+ *arg = p + 1;
+ return OK;
+ }
+
+ /*
+ * Copy the string into allocated memory, handling backslashed
+ * characters.
+ */
+ name = alloc((unsigned)(p - *arg + extra));
+ if (name == NULL)
+ return FAIL;
+
+ i = 0;
+ for (p = *arg + 1; *p && *p != '"'; ++p)
+ {
+ if (*p == '\\')
+ {
+ switch (*++p)
+ {
+ case 'b': name[i++] = BS; break;
+ case 'e': name[i++] = ESC; break;
+ case 'f': name[i++] = FF; break;
+ case 'n': name[i++] = NL; break;
+ case 'r': name[i++] = CAR; break;
+ case 't': name[i++] = TAB; break;
+
+ case 'X': /* hex: "\x1", "\x12" */
+ case 'x':
+ case 'u': /* Unicode: "\u0023" */
+ case 'U':
+ if (vim_isxdigit(p[1]))
+ {
+ int n, nr;
+ int c = toupper(*p);
+
+ if (c == 'X')
+ n = 2;
+ else
+ n = 4;
+ nr = 0;
+ while (--n >= 0 && vim_isxdigit(p[1]))
+ {
+ ++p;
+ nr = (nr << 4) + hex2nr(*p);
+ }
+#ifdef FEAT_MBYTE
+ /* For "\u" store the number according to
+ * 'encoding'. */
+ if (c != 'X')
+ i += (*mb_char2bytes)(nr, name + i);
+ else
+#endif
+ name[i++] = nr;
+ }
+ else
+ name[i++] = *p;
+ break;
+
+ /* octal: "\1", "\12", "\123" */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': name[i] = *p - '0';
+ if (p[1] >= '0' && p[1] <= '7')
+ {
+ ++p;
+ name[i] = (name[i] << 3) + *p - '0';
+ if (p[1] >= '0' && p[1] <= '7')
+ {
+ ++p;
+ name[i] = (name[i] << 3) + *p - '0';
+ }
+ }
+ ++i;
+ break;
+
+ /* Special key, e.g.: "\<C-W>" */
+ case '<': extra = trans_special(&p, name + i, TRUE);
+ if (extra != 0)
+ {
+ i += extra;
+ --p;
+ break;
+ }
+ /* FALLTHROUGH */
+
+ default: name[i++] = *p;
+ break;
+ }
+ }
+ else
+ name[i++] = *p;
+
+#ifdef FEAT_MBYTE
+ /* For a multi-byte character copy the bytes after the first one. */
+ if (has_mbyte)
+ {
+ int l = (*mb_ptr2len_check)(p);
+
+ while (--l > 0)
+ name[i++] = *++p;
+ }
+#endif
+ }
+ name[i] = NUL;
+ *arg = p + 1;
+
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = name;
+
+ return OK;
+}
+
+/*
+ * Allocate a variable for an backtick-string constant.
+ * Return OK or FAIL.
+ */
+ static int
+get_lit_string_var(arg, retvar, evaluate)
+ char_u **arg;
+ VAR retvar;
+ int evaluate;
+{
+ char_u *p;
+ char_u *name;
+
+ /*
+ * Find the end of the string.
+ */
+ p = vim_strchr(*arg + 1, '\'');
+ if (p == NULL)
+ {
+ EMSG2(_("E115: Missing quote: %s"), *arg);
+ return FAIL;
+ }
+
+ if (evaluate)
+ {
+ /*
+ * Copy the string into allocated memory.
+ */
+ name = vim_strnsave(*arg + 1, (int)(p - (*arg + 1)));
+ if (name == NULL)
+ return FAIL;
+
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = name;
+ }
+
+ *arg = p + 1;
+
+ return OK;
+}
+
+/*
+ * Get the value of an environment variable.
+ * "arg" is pointing to the '$'. It is advanced to after the name.
+ * If the environment variable was not set, silently assume it is empty.
+ * Always return OK.
+ */
+ static int
+get_env_var(arg, retvar, evaluate)
+ char_u **arg;
+ VAR retvar;
+ int evaluate;
+{
+ char_u *string = NULL;
+ int len;
+ int cc;
+ char_u *name;
+
+ ++*arg;
+ name = *arg;
+ len = get_env_len(arg);
+ if (evaluate)
+ {
+ if (len != 0)
+ {
+ cc = name[len];
+ name[len] = NUL;
+ /* first try mch_getenv(), fast for normal environment vars */
+ string = mch_getenv(name);
+ if (string != NULL && *string != NUL)
+ string = vim_strsave(string);
+ else
+ {
+ /* next try expanding things like $VIM and ${HOME} */
+ string = expand_env_save(name - 1);
+ if (string != NULL && *string == '$')
+ {
+ vim_free(string);
+ string = NULL;
+ }
+ }
+ name[len] = cc;
+ }
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = string;
+ }
+
+ return OK;
+}
+
+/*
+ * Array with names and number of arguments of all internal functions
+ * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
+ */
+static struct fst
+{
+ char *f_name; /* function name */
+ char f_min_argc; /* minimal number of arguments */
+ char f_max_argc; /* maximal number of arguments */
+ void (*f_func) __ARGS((VAR args, VAR rvar)); /* impl. function */
+} functions[] =
+{
+ {"append", 2, 2, f_append},
+ {"argc", 0, 0, f_argc},
+ {"argidx", 0, 0, f_argidx},
+ {"argv", 1, 1, f_argv},
+ {"browse", 4, 4, f_browse},
+ {"bufexists", 1, 1, f_bufexists},
+ {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
+ {"buffer_name", 1, 1, f_bufname}, /* obsolete */
+ {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
+ {"buflisted", 1, 1, f_buflisted},
+ {"bufloaded", 1, 1, f_bufloaded},
+ {"bufname", 1, 1, f_bufname},
+ {"bufnr", 1, 1, f_bufnr},
+ {"bufwinnr", 1, 1, f_bufwinnr},
+ {"byte2line", 1, 1, f_byte2line},
+ {"char2nr", 1, 1, f_char2nr},
+ {"cindent", 1, 1, f_cindent},
+ {"col", 1, 1, f_col},
+ {"confirm", 1, 4, f_confirm},
+ {"cscope_connection",0,3, f_cscope_connection},
+ {"cursor", 2, 2, f_cursor},
+ {"delete", 1, 1, f_delete},
+ {"did_filetype", 0, 0, f_did_filetype},
+ {"escape", 2, 2, f_escape},
+ {"eventhandler", 0, 0, f_eventhandler},
+ {"executable", 1, 1, f_executable},
+ {"exists", 1, 1, f_exists},
+ {"expand", 1, 2, f_expand},
+ {"file_readable", 1, 1, f_filereadable}, /* obsolete */
+ {"filereadable", 1, 1, f_filereadable},
+ {"filewritable", 1, 1, f_filewritable},
+ {"fnamemodify", 2, 2, f_fnamemodify},
+ {"foldclosed", 1, 1, f_foldclosed},
+ {"foldclosedend", 1, 1, f_foldclosedend},
+ {"foldlevel", 1, 1, f_foldlevel},
+ {"foldtext", 0, 0, f_foldtext},
+ {"foreground", 0, 0, f_foreground},
+ {"getbufvar", 2, 2, f_getbufvar},
+ {"getchar", 0, 1, f_getchar},
+ {"getcharmod", 0, 0, f_getcharmod},
+ {"getcmdline", 0, 0, f_getcmdline},
+ {"getcmdpos", 0, 0, f_getcmdpos},
+ {"getcwd", 0, 0, f_getcwd},
+ {"getfsize", 1, 1, f_getfsize},
+ {"getftime", 1, 1, f_getftime},
+ {"getline", 1, 1, f_getline},
+ {"getreg", 0, 1, f_getreg},
+ {"getregtype", 0, 1, f_getregtype},
+ {"getwinposx", 0, 0, f_getwinposx},
+ {"getwinposy", 0, 0, f_getwinposy},
+ {"getwinvar", 2, 2, f_getwinvar},
+ {"glob", 1, 1, f_glob},
+ {"globpath", 2, 2, f_globpath},
+ {"has", 1, 1, f_has},
+ {"hasmapto", 1, 2, f_hasmapto},
+ {"highlightID", 1, 1, f_hlID}, /* obsolete */
+ {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
+ {"histadd", 2, 2, f_histadd},
+ {"histdel", 1, 2, f_histdel},
+ {"histget", 1, 2, f_histget},
+ {"histnr", 1, 1, f_histnr},
+ {"hlID", 1, 1, f_hlID},
+ {"hlexists", 1, 1, f_hlexists},
+ {"hostname", 0, 0, f_hostname},
+ {"iconv", 3, 3, f_iconv},
+ {"indent", 1, 1, f_indent},
+ {"input", 1, 2, f_input},
+ {"inputdialog", 1, 3, f_inputdialog},
+ {"inputrestore", 0, 0, f_inputrestore},
+ {"inputsave", 0, 0, f_inputsave},
+ {"inputsecret", 1, 2, f_inputsecret},
+ {"isdirectory", 1, 1, f_isdirectory},
+ {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
+ {"libcall", 3, 3, f_libcall},
+ {"libcallnr", 3, 3, f_libcallnr},
+ {"line", 1, 1, f_line},
+ {"line2byte", 1, 1, f_line2byte},
+ {"lispindent", 1, 1, f_lispindent},
+ {"localtime", 0, 0, f_localtime},
+ {"maparg", 1, 2, f_maparg},
+ {"mapcheck", 1, 2, f_mapcheck},
+ {"match", 2, 3, f_match},
+ {"matchend", 2, 3, f_matchend},
+ {"matchstr", 2, 3, f_matchstr},
+ {"mode", 0, 0, f_mode},
+ {"nextnonblank", 1, 1, f_nextnonblank},
+ {"nr2char", 1, 1, f_nr2char},
+ {"prevnonblank", 1, 1, f_prevnonblank},
+ {"remote_expr", 2, 3, f_remote_expr},
+ {"remote_foreground", 1, 1, f_remote_foreground},
+ {"remote_peek", 1, 2, f_remote_peek},
+ {"remote_read", 1, 1, f_remote_read},
+ {"remote_send", 2, 3, f_remote_send},
+ {"rename", 2, 2, f_rename},
+ {"resolve", 1, 1, f_resolve},
+ {"search", 1, 2, f_search},
+ {"searchpair", 3, 5, f_searchpair},
+ {"server2client", 2, 2, f_server2client},
+ {"serverlist", 0, 0, f_serverlist},
+ {"setbufvar", 3, 3, f_setbufvar},
+ {"setcmdpos", 1, 1, f_setcmdpos},
+ {"setline", 2, 2, f_setline},
+ {"setreg", 2, 3, f_setreg},
+ {"setwinvar", 3, 3, f_setwinvar},
+ {"simplify", 1, 1, f_simplify},
+#ifdef HAVE_STRFTIME
+ {"strftime", 1, 2, f_strftime},
+#endif
+ {"stridx", 2, 2, f_stridx},
+ {"strlen", 1, 1, f_strlen},
+ {"strpart", 2, 3, f_strpart},
+ {"strridx", 2, 2, f_strridx},
+ {"strtrans", 1, 1, f_strtrans},
+ {"submatch", 1, 1, f_submatch},
+ {"substitute", 4, 4, f_substitute},
+ {"synID", 3, 3, f_synID},
+ {"synIDattr", 2, 3, f_synIDattr},
+ {"synIDtrans", 1, 1, f_synIDtrans},
+ {"system", 1, 1, f_system},
+ {"tempname", 0, 0, f_tempname},
+ {"tolower", 1, 1, f_tolower},
+ {"toupper", 1, 1, f_toupper},
+ {"type", 1, 1, f_type},
+ {"virtcol", 1, 1, f_virtcol},
+ {"visualmode", 0, 1, f_visualmode},
+ {"winbufnr", 1, 1, f_winbufnr},
+ {"wincol", 0, 0, f_wincol},
+ {"winheight", 1, 1, f_winheight},
+ {"winline", 0, 0, f_winline},
+ {"winnr", 0, 0, f_winnr},
+ {"winrestcmd", 0, 0, f_winrestcmd},
+ {"winwidth", 1, 1, f_winwidth},
+};
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+
+/*
+ * Function given to ExpandGeneric() to obtain the list of internal
+ * or user defined function names.
+ */
+ char_u *
+get_function_name(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ static int intidx = -1;
+ char_u *name;
+
+ if (idx == 0)
+ intidx = -1;
+ if (intidx < 0)
+ {
+ name = get_user_func_name(xp, idx);
+ if (name != NULL)
+ return name;
+ }
+ if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
+ {
+ STRCPY(IObuff, functions[intidx].f_name);
+ STRCAT(IObuff, "(");
+ if (functions[intidx].f_max_argc == 0)
+ STRCAT(IObuff, ")");
+ return IObuff;
+ }
+
+ return NULL;
+}
+
+/*
+ * Function given to ExpandGeneric() to obtain the list of internal or
+ * user defined variable or function names.
+ */
+/*ARGSUSED*/
+ char_u *
+get_expr_name(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ static int intidx = -1;
+ char_u *name;
+
+ if (idx == 0)
+ intidx = -1;
+ if (intidx < 0)
+ {
+ name = get_function_name(xp, idx);
+ if (name != NULL)
+ return name;
+ }
+ return get_user_var_name(xp, ++intidx);
+}
+
+#endif /* FEAT_CMDL_COMPL */
+
+/*
+ * Find internal function in table above.
+ * Return index, or -1 if not found
+ */
+ static int
+find_internal_func(name)
+ char_u *name; /* name of the function */
+{
+ int first = 0;
+ int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
+ int cmp;
+ int x;
+
+ /*
+ * Find the function name in the table. Binary search.
+ */
+ while (first <= last)
+ {
+ x = first + ((unsigned)(last - first) >> 1);
+ cmp = STRCMP(name, functions[x].f_name);
+ if (cmp < 0)
+ last = x - 1;
+ else if (cmp > 0)
+ first = x + 1;
+ else
+ return x;
+ }
+ return -1;
+}
+
+/*
+ * Allocate a variable for the result of a function.
+ * Return OK or FAIL.
+ */
+ static int
+get_func_var(name, len, retvar, arg, firstline, lastline, doesrange, evaluate)
+ char_u *name; /* name of the function */
+ int len; /* length of "name" */
+ VAR retvar;
+ char_u **arg; /* argument, pointing to the '(' */
+ linenr_T firstline; /* first line of range */
+ linenr_T lastline; /* last line of range */
+ int *doesrange; /* return: function handled range */
+ int evaluate;
+{
+ char_u *argp;
+ int ret = OK;
+#define MAX_FUNC_ARGS 20
+ var argvars[MAX_FUNC_ARGS]; /* vars for arguments */
+ int argcount = 0; /* number of arguments found */
+
+ /*
+ * Get the arguments.
+ */
+ argp = *arg;
+ while (argcount < MAX_FUNC_ARGS)
+ {
+ argp = skipwhite(argp + 1); /* skip the '(' or ',' */
+ if (*argp == ')' || *argp == ',' || *argp == NUL)
+ break;
+ argvars[argcount].var_name = NULL; /* the name is not stored */
+ if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
+ {
+ ret = FAIL;
+ break;
+ }
+ ++argcount;
+ if (*argp != ',')
+ break;
+ }
+ if (*argp == ')')
+ ++argp;
+ else
+ ret = FAIL;
+
+ if (ret == OK)
+ ret = call_func(name, len, retvar, argcount, argvars,
+ firstline, lastline, doesrange, evaluate);
+ else if (!aborting())
+ EMSG2(_("E116: Invalid arguments for function %s"), name);
+
+ while (--argcount >= 0)
+ clear_var(&argvars[argcount]);
+
+ *arg = skipwhite(argp);
+ return ret;
+}
+
+
+/*
+ * Call a function with its resolved parameters
+ * Return OK or FAIL.
+ */
+ static int
+call_func(name, len, retvar, argcount, argvars, firstline, lastline,
+ doesrange, evaluate)
+ char_u *name; /* name of the function */
+ int len; /* length of "name" */
+ VAR retvar; /* return value goes here */
+ int argcount; /* number of "argvars" */
+ VAR argvars; /* vars for arguments */
+ linenr_T firstline; /* first line of range */
+ linenr_T lastline; /* last line of range */
+ int *doesrange; /* return: function handled range */
+ int evaluate;
+{
+ int ret = FAIL;
+ static char *errors[] =
+ {N_("E117: Unknown function: %s"),
+ N_("E118: Too many arguments for function: %s"),
+ N_("E119: Not enough arguments for function: %s"),
+ N_("E120: Using <SID> not in a script context: %s"),
+ };
+#define ERROR_UNKNOWN 0
+#define ERROR_TOOMANY 1
+#define ERROR_TOOFEW 2
+#define ERROR_SCRIPT 3
+#define ERROR_NONE 4
+#define ERROR_OTHER 5
+ int error = ERROR_NONE;
+ int i;
+ int llen;
+ ufunc_T *fp;
+ int cc;
+#define FLEN_FIXED 40
+ char_u fname_buf[FLEN_FIXED + 1];
+ char_u *fname;
+
+ /*
+ * In a script change <SID>name() and s:name() to K_SNR 123_name().
+ * Change <SNR>123_name() to K_SNR 123_name().
+ * Use fname_buf[] when it fits, otherwise allocate memory (slow).
+ */
+ cc = name[len];
+ name[len] = NUL;
+ llen = eval_fname_script(name);
+ if (llen > 0)
+ {
+ fname_buf[0] = K_SPECIAL;
+ fname_buf[1] = KS_EXTRA;
+ fname_buf[2] = (int)KE_SNR;
+ i = 3;
+ if (eval_fname_sid(name)) /* "<SID>" or "s:" */
+ {
+ if (current_SID <= 0)
+ error = ERROR_SCRIPT;
+ else
+ {
+ sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
+ i = (int)STRLEN(fname_buf);
+ }
+ }
+ if (i + STRLEN(name + llen) < FLEN_FIXED)
+ {
+ STRCPY(fname_buf + i, name + llen);
+ fname = fname_buf;
+ }
+ else
+ {
+ fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
+ if (fname == NULL)
+ error = ERROR_OTHER;
+ else
+ {
+ mch_memmove(fname, fname_buf, (size_t)i);
+ STRCPY(fname + i, name + llen);
+ }
+ }
+ }
+ else
+ fname = name;
+
+ *doesrange = FALSE;
+
+
+ /* execute the function if no errors detected and executing */
+ if (evaluate && error == ERROR_NONE)
+ {
+ retvar->var_type = VAR_NUMBER; /* default is number retvar */
+ error = ERROR_UNKNOWN;
+
+ if (!ASCII_ISLOWER(fname[0]))
+ {
+ /*
+ * User defined function.
+ */
+ fp = find_func(fname);
+#ifdef FEAT_AUTOCMD
+ if (fp == NULL && apply_autocmds(EVENT_FUNCUNDEFINED,
+ fname, fname, TRUE, NULL)
+#ifdef FEAT_EVAL
+ && !aborting()
+#endif
+ )
+ {
+ /* executed an autocommand, search for function again */
+ fp = find_func(fname);
+ }
+#endif
+ if (fp != NULL)
+ {
+ if (fp->flags & FC_RANGE)
+ *doesrange = TRUE;
+ if (argcount < fp->args.ga_len)
+ error = ERROR_TOOFEW;
+ else if (!fp->varargs && argcount > fp->args.ga_len)
+ error = ERROR_TOOMANY;
+ else
+ {
+ /*
+ * Call the user function.
+ * Save and restore search patterns, script variables and
+ * redo buffer.
+ */
+ save_search_patterns();
+ saveRedobuff();
+ ++fp->calls;
+ call_user_func(fp, argcount, argvars, retvar,
+ firstline, lastline);
+ --fp->calls;
+ restoreRedobuff();
+ restore_search_patterns();
+ error = ERROR_NONE;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Find the function name in the table, call its implementation.
+ */
+ i = find_internal_func(fname);
+ if (i >= 0)
+ {
+ if (argcount < functions[i].f_min_argc)
+ error = ERROR_TOOFEW;
+ else if (argcount > functions[i].f_max_argc)
+ error = ERROR_TOOMANY;
+ else
+ {
+ argvars[argcount].var_type = VAR_UNKNOWN;
+ functions[i].f_func(argvars, retvar);
+ error = ERROR_NONE;
+ }
+ }
+ }
+ /*
+ * The function call (or "FuncUndefined" autocommand sequence) might
+ * have been aborted by an error, an interrupt, or an explicitly thrown
+ * exception that has not been caught so far. This situation can be
+ * tested for by calling aborting(). For an error in an internal
+ * function or for the "E132" error in call_user_func(), however, the
+ * throw point at which the "force_abort" flag (temporarily reset by
+ * emsg()) is normally updated has not been reached yet. We need to
+ * update that flag first to make aborting() reliable.
+ */
+ update_force_abort();
+ }
+ if (error == ERROR_NONE)
+ ret = OK;
+
+ /*
+ * Report an error unless the argument evaluation or function call has been
+ * cancelled due to an aborting error, an interrupt, or an exception.
+ */
+ if (error < ERROR_NONE && !aborting())
+ EMSG2((char_u *)_(errors[error]), name);
+
+ name[len] = cc;
+ if (fname != name && fname != fname_buf)
+ vim_free(fname);
+
+ return ret;
+}
+
+/*********************************************
+ * Implementation of the built-in functions
+ */
+
+/*
+ * "append(lnum, string)" function
+ */
+ static void
+f_append(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ long lnum;
+
+ lnum = get_var_lnum(argvars);
+ retvar->var_val.var_number = 1; /* Default: Failed */
+
+ if (lnum >= 0
+ && lnum <= curbuf->b_ml.ml_line_count
+ && u_save(lnum, lnum + 1) == OK)
+ {
+ ml_append(lnum, get_var_string(&argvars[1]), (colnr_T)0, FALSE);
+ if (curwin->w_cursor.lnum > lnum)
+ ++curwin->w_cursor.lnum;
+ appended_lines_mark(lnum, 1L);
+ retvar->var_val.var_number = 0;
+ }
+}
+
+/*
+ * "argc()" function
+ */
+/* ARGSUSED */
+ static void
+f_argc(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = ARGCOUNT;
+}
+
+/*
+ * "argidx()" function
+ */
+/* ARGSUSED */
+ static void
+f_argidx(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = curwin->w_arg_idx;
+}
+
+/*
+ * "argv(nr)" function
+ */
+ static void
+f_argv(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ int idx;
+
+ idx = get_var_number(&argvars[0]);
+ if (idx >= 0 && idx < ARGCOUNT)
+ retvar->var_val.var_string = vim_strsave(alist_name(&ARGLIST[idx]));
+ else
+ retvar->var_val.var_string = NULL;
+ retvar->var_type = VAR_STRING;
+}
+
+/*
+ * "browse(save, title, initdir, default)" function
+ */
+/* ARGSUSED */
+ static void
+f_browse(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_BROWSE
+ int save;
+ char_u *title;
+ char_u *initdir;
+ char_u *defname;
+ char_u buf[NUMBUFLEN];
+ char_u buf2[NUMBUFLEN];
+
+ save = get_var_number(&argvars[0]);
+ title = get_var_string(&argvars[1]);
+ initdir = get_var_string_buf(&argvars[2], buf);
+ defname = get_var_string_buf(&argvars[3], buf2);
+
+ retvar->var_val.var_string =
+ do_browse(save, title, defname, NULL, initdir, NULL, curbuf);
+#else
+ retvar->var_val.var_string = NULL;
+#endif
+ retvar->var_type = VAR_STRING;
+}
+
+/*
+ * Find a buffer by number or exact name.
+ */
+ static buf_T *
+find_buffer(avar)
+ VAR avar;
+{
+ buf_T *buf = NULL;
+ char_u *name;
+
+ if (avar->var_type == VAR_NUMBER)
+ buf = buflist_findnr((int)avar->var_val.var_number);
+ else if (avar->var_val.var_string != NULL)
+ {
+ /* First make the name into a full path name */
+ name = FullName_save(avar->var_val.var_string,
+#ifdef UNIX
+ TRUE /* force expansion, get rid of symbolic links */
+#else
+ FALSE
+#endif
+ );
+ if (name != NULL)
+ {
+ buf = buflist_findname(name);
+ vim_free(name);
+ }
+ }
+ return buf;
+}
+
+/*
+ * "bufexists(expr)" function
+ */
+ static void
+f_bufexists(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = (find_buffer(&argvars[0]) != NULL);
+}
+
+/*
+ * "buflisted(expr)" function
+ */
+ static void
+f_buflisted(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ buf_T *buf;
+
+ buf = find_buffer(&argvars[0]);
+ retvar->var_val.var_number = (buf != NULL && buf->b_p_bl);
+}
+
+/*
+ * "bufloaded(expr)" function
+ */
+ static void
+f_bufloaded(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ buf_T *buf;
+
+ buf = find_buffer(&argvars[0]);
+ retvar->var_val.var_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
+}
+
+/*
+ * Get buffer by number or pattern.
+ */
+ static buf_T *
+get_buf_var(avar)
+ VAR avar;
+{
+ char_u *name = avar->var_val.var_string;
+ int save_magic;
+ char_u *save_cpo;
+ buf_T *buf;
+
+ if (avar->var_type == VAR_NUMBER)
+ return buflist_findnr((int)avar->var_val.var_number);
+ if (name == NULL || *name == NUL)
+ return curbuf;
+ if (name[0] == '$' && name[1] == NUL)
+ return lastbuf;
+
+ /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
+ save_magic = p_magic;
+ p_magic = TRUE;
+ save_cpo = p_cpo;
+ p_cpo = (char_u *)"";
+
+ buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
+ TRUE, FALSE));
+
+ p_magic = save_magic;
+ p_cpo = save_cpo;
+
+ /* If not found, try expanding the name, like done for bufexists(). */
+ if (buf == NULL)
+ buf = find_buffer(avar);
+
+ return buf;
+}
+
+/*
+ * "bufname(expr)" function
+ */
+ static void
+f_bufname(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ buf_T *buf;
+
+ ++emsg_off;
+ buf = get_buf_var(&argvars[0]);
+ retvar->var_type = VAR_STRING;
+ if (buf != NULL && buf->b_fname != NULL)
+ retvar->var_val.var_string = vim_strsave(buf->b_fname);
+ else
+ retvar->var_val.var_string = NULL;
+ --emsg_off;
+}
+
+/*
+ * "bufnr(expr)" function
+ */
+ static void
+f_bufnr(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ buf_T *buf;
+
+ ++emsg_off;
+ buf = get_buf_var(&argvars[0]);
+ if (buf != NULL)
+ retvar->var_val.var_number = buf->b_fnum;
+ else
+ retvar->var_val.var_number = -1;
+ --emsg_off;
+}
+
+/*
+ * "bufwinnr(nr)" function
+ */
+ static void
+f_bufwinnr(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_WINDOWS
+ win_T *wp;
+ int winnr = 0;
+#endif
+ buf_T *buf;
+
+ ++emsg_off;
+ buf = get_buf_var(&argvars[0]);
+#ifdef FEAT_WINDOWS
+ for (wp = firstwin; wp; wp = wp->w_next)
+ {
+ ++winnr;
+ if (wp->w_buffer == buf)
+ break;
+ }
+ retvar->var_val.var_number = (wp != NULL ? winnr : -1);
+#else
+ retvar->var_val.var_number = (curwin->w_buffer == buf ? 1 : -1);
+#endif
+ --emsg_off;
+}
+
+/*
+ * "byte2line(byte)" function
+ */
+/*ARGSUSED*/
+ static void
+f_byte2line(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifndef FEAT_BYTEOFF
+ retvar->var_val.var_number = -1;
+#else
+ long boff = 0;
+
+ boff = get_var_number(&argvars[0]) - 1;
+ if (boff < 0)
+ retvar->var_val.var_number = -1;
+ else
+ retvar->var_val.var_number = ml_find_line_or_offset(curbuf,
+ (linenr_T)0, &boff);
+#endif
+}
+
+/*
+ * "char2nr(string)" function
+ */
+ static void
+f_char2nr(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ retvar->var_val.var_number =
+ (*mb_ptr2char)(get_var_string(&argvars[0]));
+ else
+#endif
+ retvar->var_val.var_number = get_var_string(&argvars[0])[0];
+}
+
+/*
+ * "cindent(lnum)" function
+ */
+ static void
+f_cindent(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_CINDENT
+ pos_T pos;
+ linenr_T lnum;
+
+ pos = curwin->w_cursor;
+ lnum = get_var_lnum(argvars);
+ if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
+ {
+ curwin->w_cursor.lnum = lnum;
+ retvar->var_val.var_number = get_c_indent();
+ curwin->w_cursor = pos;
+ }
+ else
+#endif
+ retvar->var_val.var_number = -1;
+}
+
+/*
+ * "col(string)" function
+ */
+ static void
+f_col(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ colnr_T col = 0;
+ pos_T *fp;
+
+ fp = var2fpos(&argvars[0], FALSE);
+ if (fp != NULL)
+ {
+ if (fp->col == MAXCOL)
+ {
+ /* '> can be MAXCOL, get the length of the line then */
+ if (fp->lnum <= curbuf->b_ml.ml_line_count)
+ col = STRLEN(ml_get(fp->lnum)) + 1;
+ else
+ col = MAXCOL;
+ }
+ else
+ {
+ col = fp->col + 1;
+#ifdef FEAT_VIRTUALEDIT
+ /* col(".") when the cursor is on the NUL at the end of the line
+ * because of "coladd" can be seen as an extra column. */
+ if (virtual_active() && fp == &curwin->w_cursor)
+ {
+ char_u *p = ml_get_cursor();
+
+ if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
+ curwin->w_virtcol - curwin->w_cursor.coladd))
+ {
+# ifdef FEAT_MBYTE
+ int l;
+
+ if (*p != NUL && p[(l = (*mb_ptr2len_check)(p))] == NUL)
+ col += l;
+# else
+ if (*p != NUL && p[1] == NUL)
+ ++col;
+# endif
+ }
+ }
+#endif
+ }
+ }
+ retvar->var_val.var_number = col;
+}
+
+/*
+ * "confirm(message, buttons[, default [, type]])" function
+ */
+/*ARGSUSED*/
+ static void
+f_confirm(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ char_u *message;
+ char_u *buttons = NULL;
+ char_u buf[NUMBUFLEN];
+ char_u buf2[NUMBUFLEN];
+ int def = 1;
+ int type = VIM_GENERIC;
+ int c;
+
+ message = get_var_string(&argvars[0]);
+ if (argvars[1].var_type != VAR_UNKNOWN)
+ {
+ buttons = get_var_string_buf(&argvars[1], buf);
+ if (argvars[2].var_type != VAR_UNKNOWN)
+ {
+ def = get_var_number(&argvars[2]);
+ if (argvars[3].var_type != VAR_UNKNOWN)
+ {
+ /* avoid that TOUPPER_ASC calls get_var_string_buf() twice */
+ c = *get_var_string_buf(&argvars[3], buf2);
+ switch (TOUPPER_ASC(c))
+ {
+ case 'E': type = VIM_ERROR; break;
+ case 'Q': type = VIM_QUESTION; break;
+ case 'I': type = VIM_INFO; break;
+ case 'W': type = VIM_WARNING; break;
+ case 'G': type = VIM_GENERIC; break;
+ }
+ }
+ }
+ }
+
+ if (buttons == NULL || *buttons == NUL)
+ buttons = (char_u *)_("&Ok");
+
+ retvar->var_val.var_number = do_dialog(type, NULL, message, buttons,
+ def, NULL);
+#else
+ retvar->var_val.var_number = 0;
+#endif
+}
+
+
+/*
+ * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
+ *
+ * Checks the existence of a cscope connection.
+ */
+/*ARGSUSED*/
+ static void
+f_cscope_connection(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_CSCOPE
+ int num = 0;
+ char_u *dbpath = NULL;
+ char_u *prepend = NULL;
+ char_u buf[NUMBUFLEN];
+
+ if (argvars[0].var_type != VAR_UNKNOWN
+ && argvars[1].var_type != VAR_UNKNOWN)
+ {
+ num = (int)get_var_number(&argvars[0]);
+ dbpath = get_var_string(&argvars[1]);
+ if (argvars[2].var_type != VAR_UNKNOWN)
+ prepend = get_var_string_buf(&argvars[2], buf);
+ }
+
+ retvar->var_val.var_number = cs_connection(num, dbpath, prepend);
+#else
+ retvar->var_val.var_number = 0;
+#endif
+}
+
+/*
+ * "cursor(lnum, col)" function
+ *
+ * Moves the cursor to the specified line and column
+ */
+/*ARGSUSED*/
+ static void
+f_cursor(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ long line, col;
+
+ line = get_var_lnum(argvars);
+ if (line > 0)
+ curwin->w_cursor.lnum = line;
+ col = get_var_number(&argvars[1]);
+ if (col > 0)
+ curwin->w_cursor.col = col - 1;
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+
+ /* Make sure the cursor is in a valid position. */
+ check_cursor();
+#ifdef FEAT_MBYTE
+ /* Correct cursor for multi-byte character. */
+ if (has_mbyte)
+ mb_adjust_cursor();
+#endif
+}
+
+/*
+ * "libcall()" function
+ */
+ static void
+f_libcall(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ libcall_common(argvars, retvar, VAR_STRING);
+}
+
+/*
+ * "libcallnr()" function
+ */
+ static void
+f_libcallnr(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ libcall_common(argvars, retvar, VAR_NUMBER);
+}
+
+ static void
+libcall_common(argvars, retvar, type)
+ VAR argvars;
+ VAR retvar;
+ int type;
+{
+#ifdef FEAT_LIBCALL
+ char_u *string_in;
+ char_u **string_result;
+ int nr_result;
+#endif
+
+ retvar->var_type = type;
+ if (type == VAR_NUMBER)
+ retvar->var_val.var_number = 0;
+ else
+ retvar->var_val.var_string = NULL;
+
+ if (check_restricted() || check_secure())
+ return;
+
+#ifdef FEAT_LIBCALL
+ /* The first two args must be strings, otherwise its meaningless */
+ if (argvars[0].var_type == VAR_STRING && argvars[1].var_type == VAR_STRING)
+ {
+ if (argvars[2].var_type == VAR_NUMBER)
+ string_in = NULL;
+ else
+ string_in = argvars[2].var_val.var_string;
+ if (type == VAR_NUMBER)
+ string_result = NULL;
+ else
+ string_result = &retvar->var_val.var_string;
+ if (mch_libcall(argvars[0].var_val.var_string,
+ argvars[1].var_val.var_string,
+ string_in,
+ argvars[2].var_val.var_number,
+ string_result,
+ &nr_result) == OK
+ && type == VAR_NUMBER)
+ retvar->var_val.var_number = nr_result;
+ }
+#endif
+}
+
+/*
+ * "delete()" function
+ */
+ static void
+f_delete(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ if (check_restricted() || check_secure())
+ retvar->var_val.var_number = -1;
+ else
+ retvar->var_val.var_number = mch_remove(get_var_string(&argvars[0]));
+}
+
+/*
+ * "did_filetype()" function
+ */
+/*ARGSUSED*/
+ static void
+f_did_filetype(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_AUTOCMD
+ retvar->var_val.var_number = did_filetype;
+#else
+ retvar->var_val.var_number = 0;
+#endif
+}
+
+/*
+ * "escape({string}, {chars})" function
+ */
+ static void
+f_escape(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u buf[NUMBUFLEN];
+
+ retvar->var_val.var_string =
+ vim_strsave_escaped(get_var_string(&argvars[0]),
+ get_var_string_buf(&argvars[1], buf));
+ retvar->var_type = VAR_STRING;
+}
+
+/*
+ * "eventhandler()" function
+ */
+/*ARGSUSED*/
+ static void
+f_eventhandler(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = vgetc_busy;
+}
+
+/*
+ * "executable()" function
+ */
+ static void
+f_executable(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = mch_can_exe(get_var_string(&argvars[0]));
+}
+
+/*
+ * "exists()" function
+ */
+ static void
+f_exists(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *p;
+ char_u *name;
+ int n = FALSE;
+ int len = 0;
+
+ p = get_var_string(&argvars[0]);
+ if (*p == '$') /* environment variable */
+ {
+ /* first try "normal" environment variables (fast) */
+ if (mch_getenv(p + 1) != NULL)
+ n = TRUE;
+ else
+ {
+ /* try expanding things like $VIM and ${HOME} */
+ p = expand_env_save(p);
+ if (p != NULL && *p != '$')
+ n = TRUE;
+ vim_free(p);
+ }
+ }
+ else if (*p == '&' || *p == '+') /* option */
+ n = (get_option_var(&p, NULL, TRUE) == OK);
+ else if (*p == '*') /* internal or user defined function */
+ {
+ ++p;
+ p = trans_function_name(&p, FALSE, TRUE);
+ if (p != NULL)
+ {
+ if (ASCII_ISUPPER(*p) || p[0] == K_SPECIAL)
+ n = (find_func(p) != NULL);
+ else if (ASCII_ISLOWER(*p))
+ n = (find_internal_func(p) >= 0);
+ vim_free(p);
+ }
+ }
+ else if (*p == ':')
+ {
+ n = cmd_exists(p + 1);
+ }
+ else if (*p == '#')
+ {
+#ifdef FEAT_AUTOCMD
+ name = p + 1;
+ p = vim_strchr(name, '#');
+ if (p != NULL)
+ n = au_exists(name, p, p + 1);
+ else
+ n = au_exists(name, name + STRLEN(name), NULL);
+#endif
+ }
+ else /* internal variable */
+ {
+#ifdef FEAT_MAGIC_BRACES
+ char_u *expr_start;
+ char_u *expr_end;
+ char_u *temp_string = NULL;
+ char_u *s;
+#endif
+ name = p;
+
+#ifdef FEAT_MAGIC_BRACES
+ /* Find the end of the name. */
+ s = find_name_end(name, &expr_start, &expr_end);
+ if (expr_start != NULL)
+ {
+ temp_string = make_expanded_name(name, expr_start, expr_end, s);
+ if (temp_string != NULL)
+ {
+ len = STRLEN(temp_string);
+ name = temp_string;
+ }
+ }
+#endif
+ if (len == 0)
+ len = get_id_len(&p);
+ if (len != 0)
+ n = (get_var_var(name, len, NULL) == OK);
+
+#ifdef FEAT_MAGIC_BRACES
+ vim_free(temp_string);
+#endif
+ }
+
+ retvar->var_val.var_number = n;
+}
+
+/*
+ * "expand()" function
+ */
+ static void
+f_expand(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *s;
+ int len;
+ char_u *errormsg;
+ int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
+ expand_T xpc;
+
+ retvar->var_type = VAR_STRING;
+ s = get_var_string(&argvars[0]);
+ if (*s == '%' || *s == '#' || *s == '<')
+ {
+ ++emsg_off;
+ retvar->var_val.var_string = eval_vars(s, &len, NULL, &errormsg, s);
+ --emsg_off;
+ }
+ else
+ {
+ /* When the optional second argument is non-zero, don't remove matches
+ * for 'suffixes' and 'wildignore' */
+ if (argvars[1].var_type != VAR_UNKNOWN && get_var_number(&argvars[1]))
+ flags |= WILD_KEEP_ALL;
+ ExpandInit(&xpc);
+ xpc.xp_context = EXPAND_FILES;
+ retvar->var_val.var_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL);
+ ExpandCleanup(&xpc);
+ }
+}
+
+/*
+ * "filereadable()" function
+ */
+ static void
+f_filereadable(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ FILE *fd;
+ char_u *p;
+ int n;
+
+ p = get_var_string(&argvars[0]);
+ if (*p && !mch_isdir(p) && (fd = mch_fopen((char *)p, "r")) != NULL)
+ {
+ n = TRUE;
+ fclose(fd);
+ }
+ else
+ n = FALSE;
+
+ retvar->var_val.var_number = n;
+}
+
+/*
+ * return 0 for not writable, 1 for writable file, 2 for a dir which we have
+ * rights to write into.
+ */
+ static void
+f_filewritable(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *p;
+ int retval = 0;
+#if defined(UNIX) || defined(VMS)
+ int perm = 0;
+#endif
+
+ p = get_var_string(&argvars[0]);
+#if defined(UNIX) || defined(VMS)
+ perm = mch_getperm(p);
+#endif
+#ifndef MACOS_CLASSIC /* TODO: get either mch_writable or mch_access */
+ if (
+# ifdef WIN3264
+ mch_writable(p) &&
+# else
+# if defined(UNIX) || defined(VMS)
+ (perm & 0222) &&
+# endif
+# endif
+ mch_access((char *)p, W_OK) == 0
+ )
+#endif
+ {
+ ++retval;
+ if (mch_isdir(p))
+ ++retval;
+ }
+ retvar->var_val.var_number = retval;
+}
+
+/*
+ * "fnamemodify({fname}, {mods})" function
+ */
+ static void
+f_fnamemodify(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *fname;
+ char_u *mods;
+ int usedlen = 0;
+ int len;
+ char_u *fbuf = NULL;
+ char_u buf[NUMBUFLEN];
+
+ fname = get_var_string(&argvars[0]);
+ mods = get_var_string_buf(&argvars[1], buf);
+ len = (int)STRLEN(fname);
+
+ (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
+
+ retvar->var_type = VAR_STRING;
+ if (fname == NULL)
+ retvar->var_val.var_string = NULL;
+ else
+ retvar->var_val.var_string = vim_strnsave(fname, len);
+ vim_free(fbuf);
+}
+
+/*
+ * "foldclosed()" function
+ */
+ static void
+f_foldclosed(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ foldclosed_both(argvars, retvar, FALSE);
+}
+
+/*
+ * "foldclosedend()" function
+ */
+ static void
+f_foldclosedend(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ foldclosed_both(argvars, retvar, TRUE);
+}
+
+/*
+ * "foldclosed()" function
+ */
+ static void
+foldclosed_both(argvars, retvar, end)
+ VAR argvars;
+ VAR retvar;
+ int end;
+{
+#ifdef FEAT_FOLDING
+ linenr_T lnum;
+ linenr_T first, last;
+
+ lnum = get_var_lnum(argvars);
+ if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
+ {
+ if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
+ {
+ if (end)
+ retvar->var_val.var_number = (varnumber_T)last;
+ else
+ retvar->var_val.var_number = (varnumber_T)first;
+ return;
+ }
+ }
+#endif
+ retvar->var_val.var_number = -1;
+}
+
+/*
+ * "foldlevel()" function
+ */
+ static void
+f_foldlevel(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_FOLDING
+ linenr_T lnum;
+
+ lnum = get_var_lnum(argvars);
+ if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
+ retvar->var_val.var_number = foldLevel(lnum);
+ else
+#endif
+ retvar->var_val.var_number = 0;
+}
+
+/*
+ * "foldtext()" function
+ */
+/*ARGSUSED*/
+ static void
+f_foldtext(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_FOLDING
+ linenr_T lnum;
+ char_u *s;
+ char_u *r;
+ int len;
+ char *txt;
+#endif
+
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = NULL;
+#ifdef FEAT_FOLDING
+ if ((linenr_T)vimvars[VV_FOLDSTART].val > 0
+ && (linenr_T)vimvars[VV_FOLDEND].val <= curbuf->b_ml.ml_line_count
+ && vimvars[VV_FOLDDASHES].val != NULL)
+ {
+ /* Find first non-empty line in the fold. */
+ lnum = (linenr_T)vimvars[VV_FOLDSTART].val;
+ while (lnum < (linenr_T)vimvars[VV_FOLDEND].val)
+ {
+ if (!linewhite(lnum))
+ break;
+ ++lnum;
+ }
+
+ /* Find interesting text in this line. */
+ s = skipwhite(ml_get(lnum));
+ /* skip C comment-start */
+ if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
+ s = skipwhite(s + 2);
+ txt = _("+-%s%3ld lines: ");
+ r = alloc((unsigned)(STRLEN(txt)
+ + STRLEN(vimvars[VV_FOLDDASHES].val) /* for %s */
+ + 20 /* for %3ld */
+ + STRLEN(s))); /* concatenated */
+ if (r != NULL)
+ {
+ sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].val,
+ (long)((linenr_T)vimvars[VV_FOLDEND].val
+ - (linenr_T)vimvars[VV_FOLDSTART].val + 1));
+ len = (int)STRLEN(r);
+ STRCAT(r, s);
+ /* remove 'foldmarker' and 'commentstring' */
+ foldtext_cleanup(r + len);
+ retvar->var_val.var_string = r;
+ }
+ }
+#endif
+}
+
+/*
+ * "foreground()" function
+ */
+/*ARGSUSED*/
+ static void
+f_foreground(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = 0;
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_mch_set_foreground();
+#else
+# ifdef WIN32
+ win32_set_foreground();
+# endif
+#endif
+}
+
+/*
+ * "getchar()" function
+ */
+ static void
+f_getchar(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ varnumber_T n;
+
+ ++no_mapping;
+ ++allow_keys;
+ if (argvars[0].var_type == VAR_UNKNOWN)
+ /* getchar(): blocking wait. */
+ n = safe_vgetc();
+ else if (get_var_number(&argvars[0]) == 1)
+ /* getchar(1): only check if char avail */
+ n = vpeekc();
+ else if (vpeekc() == NUL)
+ /* getchar(0) and no char avail: return zero */
+ n = 0;
+ else
+ /* getchar(0) and char avail: return char */
+ n = safe_vgetc();
+ --no_mapping;
+ --allow_keys;
+
+ retvar->var_val.var_number = n;
+ if (IS_SPECIAL(n) || mod_mask != 0)
+ {
+ char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
+ int i = 0;
+
+ /* Turn a special key into three bytes, plus modifier. */
+ if (mod_mask != 0)
+ {
+ temp[i++] = K_SPECIAL;
+ temp[i++] = KS_MODIFIER;
+ temp[i++] = mod_mask;
+ }
+ if (IS_SPECIAL(n))
+ {
+ temp[i++] = K_SPECIAL;
+ temp[i++] = K_SECOND(n);
+ temp[i++] = K_THIRD(n);
+ }
+#ifdef FEAT_MBYTE
+ else if (has_mbyte)
+ i += (*mb_char2bytes)(n, temp + i);
+#endif
+ else
+ temp[i++] = n;
+ temp[i++] = NUL;
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = vim_strsave(temp);
+ }
+}
+
+/*
+ * "getcharmod()" function
+ */
+/*ARGSUSED*/
+ static void
+f_getcharmod(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = mod_mask;
+}
+
+/*
+ * "getcmdline()" function
+ */
+/*ARGSUSED*/
+ static void
+f_getcmdline(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = get_cmdline_str();
+}
+
+/*
+ * "getcmdpos()" function
+ */
+/*ARGSUSED*/
+ static void
+f_getcmdpos(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = get_cmdline_pos() + 1;
+}
+
+/*
+ * "getbufvar()" function
+ */
+ static void
+f_getbufvar(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ buf_T *buf;
+ buf_T *save_curbuf;
+ char_u *varname;
+ VAR v;
+
+ ++emsg_off;
+ buf = get_buf_var(&argvars[0]);
+ varname = get_var_string(&argvars[1]);
+
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = NULL;
+
+ if (buf != NULL && varname != NULL)
+ {
+ if (*varname == '&') /* buffer-local-option */
+ {
+ /* set curbuf to be our buf, temporarily */
+ save_curbuf = curbuf;
+ curbuf = buf;
+
+ get_option_var(&varname, retvar, TRUE);
+
+ /* restore previous notion of curbuf */
+ curbuf = save_curbuf;
+ }
+ else
+ {
+ /* look up the variable */
+ v = find_var_in_ga(&buf->b_vars, varname);
+ if (v != NULL)
+ copy_var(v, retvar);
+ }
+ }
+
+ --emsg_off;
+}
+
+/*
+ * "getcwd()" function
+ */
+/*ARGSUSED*/
+ static void
+f_getcwd(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u cwd[MAXPATHL];
+
+ retvar->var_type = VAR_STRING;
+ if (mch_dirname(cwd, MAXPATHL) == FAIL)
+ retvar->var_val.var_string = NULL;
+ else
+ {
+ retvar->var_val.var_string = vim_strsave(cwd);
+#ifdef BACKSLASH_IN_FILENAME
+ slash_adjust(retvar->var_val.var_string);
+#endif
+ }
+}
+
+/*
+ * "getfsize({fname})" function
+ */
+ static void
+f_getfsize(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *fname;
+ struct stat st;
+
+ fname = get_var_string(&argvars[0]);
+
+ retvar->var_type = VAR_NUMBER;
+
+ if (mch_stat((char *)fname, &st) >= 0)
+ {
+ if (mch_isdir(fname))
+ retvar->var_val.var_number = 0;
+ else
+ retvar->var_val.var_number = (varnumber_T)st.st_size;
+ }
+ else
+ retvar->var_val.var_number = -1;
+}
+
+/*
+ * "getftime({fname})" function
+ */
+ static void
+f_getftime(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *fname;
+ struct stat st;
+
+ fname = get_var_string(&argvars[0]);
+
+ if (mch_stat((char *)fname, &st) >= 0)
+ retvar->var_val.var_number = (varnumber_T)st.st_mtime;
+ else
+ retvar->var_val.var_number = -1;
+}
+
+/*
+ * "getreg()" function
+ */
+ static void
+f_getreg(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *strregname;
+ int regname;
+
+ if (argvars[0].var_type != VAR_UNKNOWN)
+ strregname = get_var_string(&argvars[0]);
+ else
+ strregname = vimvars[VV_REG].val;
+ regname = (strregname == NULL ? '"' : *strregname);
+ if (regname == 0)
+ regname = '"';
+
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = get_reg_contents(regname, TRUE);
+}
+
+/*
+ * "getregtype()" function
+ */
+ static void
+f_getregtype(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *strregname;
+ int regname;
+ char_u buf[NUMBUFLEN + 2];
+ long reglen = 0;
+
+ if (argvars[0].var_type != VAR_UNKNOWN)
+ strregname = get_var_string(&argvars[0]);
+ else
+ /* Default to v:register */
+ strregname = vimvars[VV_REG].val;
+
+ regname = (strregname == NULL ? '"' : *strregname);
+ if (regname == 0)
+ regname = '"';
+
+ buf[0] = NUL;
+ buf[1] = NUL;
+ switch (get_reg_type(regname, &reglen))
+ {
+ case MLINE: buf[0] = 'V'; break;
+ case MCHAR: buf[0] = 'v'; break;
+#ifdef FEAT_VISUAL
+ case MBLOCK:
+ buf[0] = Ctrl_V;
+ sprintf((char *)buf + 1, "%ld", reglen + 1);
+ break;
+#endif
+ }
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = vim_strsave(buf);
+}
+
+/*
+ * "getline(lnum)" function
+ */
+ static void
+f_getline(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ linenr_T lnum;
+ char_u *p;
+
+ lnum = get_var_lnum(argvars);
+
+ if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
+ p = ml_get(lnum);
+ else
+ p = (char_u *)"";
+
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = vim_strsave(p);
+}
+
+/*
+ * "getwinposx()" function
+ */
+/*ARGSUSED*/
+ static void
+f_getwinposx(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = -1;
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ int x, y;
+
+ if (gui_mch_get_winpos(&x, &y) == OK)
+ retvar->var_val.var_number = x;
+ }
+#endif
+}
+
+/*
+ * "getwinposy()" function
+ */
+/*ARGSUSED*/
+ static void
+f_getwinposy(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = -1;
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ int x, y;
+
+ if (gui_mch_get_winpos(&x, &y) == OK)
+ retvar->var_val.var_number = y;
+ }
+#endif
+}
+
+/*
+ * "getwinvar()" function
+ */
+ static void
+f_getwinvar(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ win_T *win, *oldcurwin;
+ char_u *varname;
+ VAR v;
+
+ ++emsg_off;
+ win = find_win_by_nr(&argvars[0]);
+ varname = get_var_string(&argvars[1]);
+
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = NULL;
+
+ if (win != NULL && varname != NULL)
+ {
+ if (*varname == '&') /* window-local-option */
+ {
+ /* set curwin to be our win, temporarily */
+ oldcurwin = curwin;
+ curwin = win;
+
+ get_option_var(&varname, retvar , 1);
+
+ /* restore previous notion of curwin */
+ curwin = oldcurwin;
+ }
+ else
+ {
+ /* look up the variable */
+ v = find_var_in_ga(&win->w_vars, varname);
+ if (v != NULL)
+ copy_var(v, retvar);
+ }
+ }
+
+ --emsg_off;
+}
+
+/*
+ * "glob()" function
+ */
+ static void
+f_glob(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ expand_T xpc;
+
+ ExpandInit(&xpc);
+ xpc.xp_context = EXPAND_FILES;
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = ExpandOne(&xpc, get_var_string(&argvars[0]),
+ NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL);
+ ExpandCleanup(&xpc);
+}
+
+/*
+ * "globpath()" function
+ */
+ static void
+f_globpath(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u buf1[NUMBUFLEN];
+
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = globpath(get_var_string(&argvars[0]),
+ get_var_string_buf(&argvars[1], buf1));
+}
+
+/*
+ * "has()" function
+ */
+ static void
+f_has(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ int i;
+ char_u *name;
+ int n = FALSE;
+ static char *(has_list[]) =
+ {
+#ifdef AMIGA
+ "amiga",
+# ifdef FEAT_ARP
+ "arp",
+# endif
+#endif
+#ifdef __BEOS__
+ "beos",
+#endif
+#ifdef MSDOS
+# ifdef DJGPP
+ "dos32",
+# else
+ "dos16",
+# endif
+#endif
+#ifdef MACOS /* TODO: Should we add MACOS_CLASSIC, MACOS_X? (Dany) */
+ "mac",
+#endif
+#if defined(MACOS_X_UNIX)
+ "macunix",
+#endif
+#ifdef OS2
+ "os2",
+#endif
+#ifdef __QNX__
+ "qnx",
+#endif
+#ifdef RISCOS
+ "riscos",
+#endif
+#ifdef UNIX
+ "unix",
+#endif
+#ifdef VMS
+ "vms",
+#endif
+#ifdef WIN16
+ "win16",
+#endif
+#ifdef WIN32
+ "win32",
+#endif
+#if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
+ "win32unix",
+#endif
+#ifdef WIN64
+ "win64",
+#endif
+#ifdef EBCDIC
+ "ebcdic",
+#endif
+#ifndef CASE_INSENSITIVE_FILENAME
+ "fname_case",
+#endif
+#ifdef FEAT_ARABIC
+ "arabic",
+#endif
+#ifdef FEAT_AUTOCMD
+ "autocmd",
+#endif
+#ifdef FEAT_BEVAL
+ "balloon_eval",
+#endif
+#if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
+ "builtin_terms",
+# ifdef ALL_BUILTIN_TCAPS
+ "all_builtin_terms",
+# endif
+#endif
+#ifdef FEAT_BYTEOFF
+ "byte_offset",
+#endif
+#ifdef FEAT_CINDENT
+ "cindent",
+#endif
+#ifdef FEAT_CLIENTSERVER
+ "clientserver",
+#endif
+#ifdef FEAT_CLIPBOARD
+ "clipboard",
+#endif
+#ifdef FEAT_CMDL_COMPL
+ "cmdline_compl",
+#endif
+#ifdef FEAT_CMDHIST
+ "cmdline_hist",
+#endif
+#ifdef FEAT_COMMENTS
+ "comments",
+#endif
+#ifdef FEAT_CRYPT
+ "cryptv",
+#endif
+#ifdef FEAT_CSCOPE
+ "cscope",
+#endif
+#ifdef DEBUG
+ "debug",
+#endif
+#ifdef FEAT_CON_DIALOG
+ "dialog_con",
+#endif
+#ifdef FEAT_GUI_DIALOG
+ "dialog_gui",
+#endif
+#ifdef FEAT_DIFF
+ "diff",
+#endif
+#ifdef FEAT_DIGRAPHS
+ "digraphs",
+#endif
+#ifdef FEAT_DND
+ "dnd",
+#endif
+#ifdef FEAT_EMACS_TAGS
+ "emacs_tags",
+#endif
+ "eval", /* always present, of course! */
+#ifdef FEAT_EX_EXTRA
+ "ex_extra",
+#endif
+#ifdef FEAT_SEARCH_EXTRA
+ "extra_search",
+#endif
+#ifdef FEAT_FKMAP
+ "farsi",
+#endif
+#ifdef FEAT_SEARCHPATH
+ "file_in_path",
+#endif
+#ifdef FEAT_FIND_ID
+ "find_in_path",
+#endif
+#ifdef FEAT_FOLDING
+ "folding",
+#endif
+#ifdef FEAT_FOOTER
+ "footer",
+#endif
+#if !defined(USE_SYSTEM) && defined(UNIX)
+ "fork",
+#endif
+#ifdef FEAT_GETTEXT
+ "gettext",
+#endif
+#ifdef FEAT_GUI
+ "gui",
+#endif
+#ifdef FEAT_GUI_ATHENA
+# ifdef FEAT_GUI_NEXTAW
+ "gui_neXtaw",
+# else
+ "gui_athena",
+# endif
+#endif
+#ifdef FEAT_GUI_BEOS
+ "gui_beos",
+#endif
+#ifdef FEAT_GUI_GTK
+ "gui_gtk",
+# ifdef HAVE_GTK2
+ "gui_gtk2",
+# endif
+#endif
+#ifdef FEAT_GUI_MAC
+ "gui_mac",
+#endif
+#ifdef FEAT_GUI_MOTIF
+ "gui_motif",
+#endif
+#ifdef FEAT_GUI_PHOTON
+ "gui_photon",
+#endif
+#ifdef FEAT_GUI_W16
+ "gui_win16",
+#endif
+#ifdef FEAT_GUI_W32
+ "gui_win32",
+#endif
+#ifdef FEAT_HANGULIN
+ "hangul_input",
+#endif
+#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
+ "iconv",
+#endif
+#ifdef FEAT_INS_EXPAND
+ "insert_expand",
+#endif
+#ifdef FEAT_JUMPLIST
+ "jumplist",
+#endif
+#ifdef FEAT_KEYMAP
+ "keymap",
+#endif
+#ifdef FEAT_LANGMAP
+ "langmap",
+#endif
+#ifdef FEAT_LIBCALL
+ "libcall",
+#endif
+#ifdef FEAT_LINEBREAK
+ "linebreak",
+#endif
+#ifdef FEAT_LISP
+ "lispindent",
+#endif
+#ifdef FEAT_LISTCMDS
+ "listcmds",
+#endif
+#ifdef FEAT_LOCALMAP
+ "localmap",
+#endif
+#ifdef FEAT_MENU
+ "menu",
+#endif
+#ifdef FEAT_SESSION
+ "mksession",
+#endif
+#ifdef FEAT_MODIFY_FNAME
+ "modify_fname",
+#endif
+#ifdef FEAT_MOUSE
+ "mouse",
+#endif
+#ifdef FEAT_MOUSESHAPE
+ "mouseshape",
+#endif
+#if defined(UNIX) || defined(VMS)
+# ifdef FEAT_MOUSE_DEC
+ "mouse_dec",
+# endif
+# ifdef FEAT_MOUSE_GPM
+ "mouse_gpm",
+# endif
+# ifdef FEAT_MOUSE_JSB
+ "mouse_jsbterm",
+# endif
+# ifdef FEAT_MOUSE_NET
+ "mouse_netterm",
+# endif
+# ifdef FEAT_MOUSE_PTERM
+ "mouse_pterm",
+# endif
+# ifdef FEAT_MOUSE_XTERM
+ "mouse_xterm",
+# endif
+#endif
+#ifdef FEAT_MBYTE
+ "multi_byte",
+#endif
+#ifdef FEAT_MBYTE_IME
+ "multi_byte_ime",
+#endif
+#ifdef FEAT_MULTI_LANG
+ "multi_lang",
+#endif
+#ifdef FEAT_OLE
+ "ole",
+#endif
+#ifdef FEAT_OSFILETYPE
+ "osfiletype",
+#endif
+#ifdef FEAT_PATH_EXTRA
+ "path_extra",
+#endif
+#ifdef FEAT_PERL
+#ifndef DYNAMIC_PERL
+ "perl",
+#endif
+#endif
+#ifdef FEAT_PYTHON
+#ifndef DYNAMIC_PYTHON
+ "python",
+#endif
+#endif
+#ifdef FEAT_POSTSCRIPT
+ "postscript",
+#endif
+#ifdef FEAT_PRINTER
+ "printer",
+#endif
+#ifdef FEAT_QUICKFIX
+ "quickfix",
+#endif
+#ifdef FEAT_RIGHTLEFT
+ "rightleft",
+#endif
+#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
+ "ruby",
+#endif
+#ifdef FEAT_SCROLLBIND
+ "scrollbind",
+#endif
+#ifdef FEAT_CMDL_INFO
+ "showcmd",
+ "cmdline_info",
+#endif
+#ifdef FEAT_SIGNS
+ "signs",
+#endif
+#ifdef FEAT_SMARTINDENT
+ "smartindent",
+#endif
+#ifdef FEAT_SNIFF
+ "sniff",
+#endif
+#ifdef FEAT_STL_OPT
+ "statusline",
+#endif
+#ifdef FEAT_SUN_WORKSHOP
+ "sun_workshop",
+#endif
+#ifdef FEAT_NETBEANS_INTG
+ "netbeans_intg",
+#endif
+#ifdef FEAT_SYN_HL
+ "syntax",
+#endif
+#if defined(USE_SYSTEM) || !defined(UNIX)
+ "system",
+#endif
+#ifdef FEAT_TAG_BINS
+ "tag_binary",
+#endif
+#ifdef FEAT_TAG_OLDSTATIC
+ "tag_old_static",
+#endif
+#ifdef FEAT_TAG_ANYWHITE
+ "tag_any_white",
+#endif
+#ifdef FEAT_TCL
+# ifndef DYNAMIC_TCL
+ "tcl",
+# endif
+#endif
+#ifdef TERMINFO
+ "terminfo",
+#endif
+#ifdef FEAT_TERMRESPONSE
+ "termresponse",
+#endif
+#ifdef FEAT_TEXTOBJ
+ "textobjects",
+#endif
+#ifdef HAVE_TGETENT
+ "tgetent",
+#endif
+#ifdef FEAT_TITLE
+ "title",
+#endif
+#ifdef FEAT_TOOLBAR
+ "toolbar",
+#endif
+#ifdef FEAT_USR_CMDS
+ "user-commands", /* was accidentally included in 5.4 */
+ "user_commands",
+#endif
+#ifdef FEAT_VIMINFO
+ "viminfo",
+#endif
+#ifdef FEAT_VERTSPLIT
+ "vertsplit",
+#endif
+#ifdef FEAT_VIRTUALEDIT
+ "virtualedit",
+#endif
+#ifdef FEAT_VISUAL
+ "visual",
+#endif
+#ifdef FEAT_VISUALEXTRA
+ "visualextra",
+#endif
+#ifdef FEAT_VREPLACE
+ "vreplace",
+#endif
+#ifdef FEAT_WILDIGN
+ "wildignore",
+#endif
+#ifdef FEAT_WILDMENU
+ "wildmenu",
+#endif
+#ifdef FEAT_WINDOWS
+ "windows",
+#endif
+#ifdef FEAT_WAK
+ "winaltkeys",
+#endif
+#ifdef FEAT_WRITEBACKUP
+ "writebackup",
+#endif
+#ifdef FEAT_XIM
+ "xim",
+#endif
+#ifdef FEAT_XFONTSET
+ "xfontset",
+#endif
+#ifdef USE_XSMP
+ "xsmp",
+#endif
+#ifdef USE_XSMP_INTERACT
+ "xsmp_interact",
+#endif
+#ifdef FEAT_XCLIPBOARD
+ "xterm_clipboard",
+#endif
+#ifdef FEAT_XTERM_SAVE
+ "xterm_save",
+#endif
+#if defined(UNIX) && defined(FEAT_X11)
+ "X11",
+#endif
+ NULL
+ };
+
+ name = get_var_string(&argvars[0]);
+ for (i = 0; has_list[i] != NULL; ++i)
+ if (STRICMP(name, has_list[i]) == 0)
+ {
+ n = TRUE;
+ break;
+ }
+
+ if (n == FALSE)
+ {
+ if (STRNICMP(name, "patch", 5) == 0)
+ n = has_patch(atoi((char *)name + 5));
+ else if (STRICMP(name, "vim_starting") == 0)
+ n = (starting != 0);
+#ifdef DYNAMIC_TCL
+ else if (STRICMP(name, "tcl") == 0)
+ n = tcl_enabled(FALSE);
+#endif
+#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
+ else if (STRICMP(name, "iconv") == 0)
+ n = iconv_enabled(FALSE);
+#endif
+#ifdef DYNAMIC_RUBY
+ else if (STRICMP(name, "ruby") == 0)
+ n = ruby_enabled(FALSE);
+#endif
+#ifdef DYNAMIC_PYTHON
+ else if (STRICMP(name, "python") == 0)
+ n = python_enabled(FALSE);
+#endif
+#ifdef DYNAMIC_PERL
+ else if (STRICMP(name, "perl") == 0)
+ n = perl_enabled(FALSE);
+#endif
+#ifdef FEAT_GUI
+ else if (STRICMP(name, "gui_running") == 0)
+ n = (gui.in_use || gui.starting);
+# ifdef FEAT_GUI_W32
+ else if (STRICMP(name, "gui_win32s") == 0)
+ n = gui_is_win32s();
+# endif
+# ifdef FEAT_BROWSE
+ else if (STRICMP(name, "browse") == 0)
+ n = gui.in_use; /* gui_mch_browse() works when GUI is running */
+# endif
+#endif
+#ifdef FEAT_SYN_HL
+ else if (STRICMP(name, "syntax_items") == 0)
+ n = syntax_present(curbuf);
+#endif
+#if defined(WIN3264)
+ else if (STRICMP(name, "win95") == 0)
+ n = mch_windows95();
+#endif
+ }
+
+ retvar->var_val.var_number = n;
+}
+
+/*
+ * "hasmapto()" function
+ */
+ static void
+f_hasmapto(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *name;
+ char_u *mode;
+ char_u buf[NUMBUFLEN];
+
+ name = get_var_string(&argvars[0]);
+ if (argvars[1].var_type == VAR_UNKNOWN)
+ mode = (char_u *)"nvo";
+ else
+ mode = get_var_string_buf(&argvars[1], buf);
+
+ if (map_to_exists(name, mode))
+ retvar->var_val.var_number = TRUE;
+ else
+ retvar->var_val.var_number = FALSE;
+}
+
+/*
+ * "histadd()" function
+ */
+/*ARGSUSED*/
+ static void
+f_histadd(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_CMDHIST
+ int histype;
+ char_u *str;
+ char_u buf[NUMBUFLEN];
+#endif
+
+ retvar->var_val.var_number = FALSE;
+ if (check_restricted() || check_secure())
+ return;
+#ifdef FEAT_CMDHIST
+ histype = get_histtype(get_var_string(&argvars[0]));
+ if (histype >= 0)
+ {
+ str = get_var_string_buf(&argvars[1], buf);
+ if (*str != NUL)
+ {
+ add_to_history(histype, str, FALSE, NUL);
+ retvar->var_val.var_number = TRUE;
+ return;
+ }
+ }
+#endif
+}
+
+/*
+ * "histdel()" function
+ */
+/*ARGSUSED*/
+ static void
+f_histdel(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_CMDHIST
+ int n;
+ char_u buf[NUMBUFLEN];
+
+ if (argvars[1].var_type == VAR_UNKNOWN)
+ /* only one argument: clear entire history */
+ n = clr_history(get_histtype(get_var_string(&argvars[0])));
+ else if (argvars[1].var_type == VAR_NUMBER)
+ /* index given: remove that entry */
+ n = del_history_idx(get_histtype(get_var_string(&argvars[0])),
+ (int)get_var_number(&argvars[1]));
+ else
+ /* string given: remove all matching entries */
+ n = del_history_entry(get_histtype(get_var_string(&argvars[0])),
+ get_var_string_buf(&argvars[1], buf));
+ retvar->var_val.var_number = n;
+#else
+ retvar->var_val.var_number = 0;
+#endif
+}
+
+/*
+ * "histget()" function
+ */
+/*ARGSUSED*/
+ static void
+f_histget(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_CMDHIST
+ int type;
+ int idx;
+
+ type = get_histtype(get_var_string(&argvars[0]));
+ if (argvars[1].var_type == VAR_UNKNOWN)
+ idx = get_history_idx(type);
+ else
+ idx = (int)get_var_number(&argvars[1]);
+ retvar->var_val.var_string = vim_strsave(get_history_entry(type, idx));
+#else
+ retvar->var_val.var_string = NULL;
+#endif
+ retvar->var_type = VAR_STRING;
+}
+
+/*
+ * "histnr()" function
+ */
+/*ARGSUSED*/
+ static void
+f_histnr(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ int i;
+
+#ifdef FEAT_CMDHIST
+ i = get_histtype(get_var_string(&argvars[0]));
+ if (i >= HIST_CMD && i < HIST_COUNT)
+ i = get_history_idx(i);
+ else
+#endif
+ i = -1;
+ retvar->var_val.var_number = i;
+}
+
+/*
+ * "highlight_exists()" function
+ */
+ static void
+f_hlexists(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = highlight_exists(get_var_string(&argvars[0]));
+}
+
+/*
+ * "highlightID(name)" function
+ */
+ static void
+f_hlID(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = syn_name2id(get_var_string(&argvars[0]));
+}
+
+/*
+ * "hostname()" function
+ */
+/*ARGSUSED*/
+ static void
+f_hostname(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u hostname[256];
+
+ mch_get_host_name(hostname, 256);
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = vim_strsave(hostname);
+}
+
+/*
+ * iconv() function
+ */
+/*ARGSUSED*/
+ static void
+f_iconv(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_MBYTE
+ char_u buf1[NUMBUFLEN];
+ char_u buf2[NUMBUFLEN];
+ char_u *from, *to, *str;
+ vimconv_T vimconv;
+#endif
+
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = NULL;
+
+#ifdef FEAT_MBYTE
+ str = get_var_string(&argvars[0]);
+ from = enc_canonize(enc_skip(get_var_string_buf(&argvars[1], buf1)));
+ to = enc_canonize(enc_skip(get_var_string_buf(&argvars[2], buf2)));
+ vimconv.vc_type = CONV_NONE;
+ convert_setup(&vimconv, from, to);
+
+ /* If the encodings are equal, no conversion needed. */
+ if (vimconv.vc_type == CONV_NONE)
+ retvar->var_val.var_string = vim_strsave(str);
+ else
+ retvar->var_val.var_string = string_convert(&vimconv, str, NULL);
+
+ convert_setup(&vimconv, NULL, NULL);
+ vim_free(from);
+ vim_free(to);
+#endif
+}
+
+/*
+ * "indent()" function
+ */
+ static void
+f_indent(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ linenr_T lnum;
+
+ lnum = get_var_lnum(argvars);
+ if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
+ retvar->var_val.var_number = get_indent_lnum(lnum);
+ else
+ retvar->var_val.var_number = -1;
+}
+
+static int inputsecret_flag = 0;
+
+/*
+ * "input()" function
+ * Also handles inputsecret() when inputsecret is set.
+ */
+ static void
+f_input(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *prompt = get_var_string(&argvars[0]);
+ char_u *p = NULL;
+ int c;
+ char_u buf[NUMBUFLEN];
+ int cmd_silent_save = cmd_silent;
+
+ retvar->var_type = VAR_STRING;
+
+#ifdef NO_CONSOLE_INPUT
+ /* While starting up, there is no place to enter text. */
+ if (no_console_input())
+ {
+ retvar->var_val.var_string = NULL;
+ return;
+ }
+#endif
+
+ cmd_silent = FALSE; /* Want to see the prompt. */
+ if (prompt != NULL)
+ {
+ /* Only the part of the message after the last NL is considered as
+ * prompt for the command line */
+ p = vim_strrchr(prompt, '\n');
+ if (p == NULL)
+ p = prompt;
+ else
+ {
+ ++p;
+ c = *p;
+ *p = NUL;
+ msg_start();
+ msg_clr_eos();
+ msg_puts_attr(prompt, echo_attr);
+ msg_didout = FALSE;
+ msg_starthere();
+ *p = c;
+ }
+ cmdline_row = msg_row;
+ }
+
+ if (argvars[1].var_type != VAR_UNKNOWN)
+ stuffReadbuffSpec(get_var_string_buf(&argvars[1], buf));
+
+ retvar->var_val.var_string =
+ getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr);
+
+ /* since the user typed this, no need to wait for return */
+ need_wait_return = FALSE;
+ msg_didout = FALSE;
+ cmd_silent = cmd_silent_save;
+}
+
+/*
+ * "inputdialog()" function
+ */
+ static void
+f_inputdialog(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#if defined(FEAT_GUI_TEXTDIALOG)
+ /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
+ if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
+ {
+ char_u *message;
+ char_u buf[NUMBUFLEN];
+
+ message = get_var_string(&argvars[0]);
+ if (argvars[1].var_type != VAR_UNKNOWN)
+ {
+ STRNCPY(IObuff, get_var_string_buf(&argvars[1], buf), IOSIZE);
+ IObuff[IOSIZE - 1] = NUL;
+ }
+ else
+ IObuff[0] = NUL;
+ if (do_dialog(VIM_QUESTION, NULL, message, (char_u *)_("&OK\n&Cancel"),
+ 1, IObuff) == 1)
+ retvar->var_val.var_string = vim_strsave(IObuff);
+ else
+ {
+ if (argvars[1].var_type != VAR_UNKNOWN
+ && argvars[2].var_type != VAR_UNKNOWN)
+ retvar->var_val.var_string = vim_strsave(
+ get_var_string_buf(&argvars[2], buf));
+ else
+ retvar->var_val.var_string = NULL;
+ }
+ retvar->var_type = VAR_STRING;
+ }
+ else
+#endif
+ f_input(argvars, retvar);
+}
+
+static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
+
+/*
+ * "inputrestore()" function
+ */
+/*ARGSUSED*/
+ static void
+f_inputrestore(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ if (ga_userinput.ga_len > 0)
+ {
+ --ga_userinput.ga_len;
+ ++ga_userinput.ga_room;
+ restore_typeahead((tasave_T *)(ga_userinput.ga_data)
+ + ga_userinput.ga_len);
+ retvar->var_val.var_number = 0; /* OK */
+ }
+ else if (p_verbose > 1)
+ {
+ msg((char_u *)_("called inputrestore() more often than inputsave()"));
+ retvar->var_val.var_number = 1; /* Failed */
+ }
+}
+
+/*
+ * "inputsave()" function
+ */
+/*ARGSUSED*/
+ static void
+f_inputsave(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ /* Add an entry to the stack of typehead storage. */
+ if (ga_grow(&ga_userinput, 1) == OK)
+ {
+ save_typeahead((tasave_T *)(ga_userinput.ga_data)
+ + ga_userinput.ga_len);
+ ++ga_userinput.ga_len;
+ --ga_userinput.ga_room;
+ retvar->var_val.var_number = 0; /* OK */
+ }
+ else
+ retvar->var_val.var_number = 1; /* Failed */
+}
+
+/*
+ * "inputsecret()" function
+ */
+ static void
+f_inputsecret(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ ++cmdline_star;
+ ++inputsecret_flag;
+ f_input(argvars, retvar);
+ --cmdline_star;
+ --inputsecret_flag;
+}
+
+/*
+ * "isdirectory()" function
+ */
+ static void
+f_isdirectory(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = mch_isdir(get_var_string(&argvars[0]));
+}
+
+/*
+ * "last_buffer_nr()" function.
+ */
+/*ARGSUSED*/
+ static void
+f_last_buffer_nr(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ int n = 0;
+ buf_T *buf;
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (n < buf->b_fnum)
+ n = buf->b_fnum;
+
+ retvar->var_val.var_number = n;
+}
+
+/*
+ * "line(string)" function
+ */
+ static void
+f_line(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ linenr_T lnum = 0;
+ pos_T *fp;
+
+ fp = var2fpos(&argvars[0], TRUE);
+ if (fp != NULL)
+ lnum = fp->lnum;
+ retvar->var_val.var_number = lnum;
+}
+
+/*
+ * "line2byte(lnum)" function
+ */
+/*ARGSUSED*/
+ static void
+f_line2byte(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifndef FEAT_BYTEOFF
+ retvar->var_val.var_number = -1;
+#else
+ linenr_T lnum;
+
+ lnum = get_var_lnum(argvars);
+ if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
+ retvar->var_val.var_number = -1;
+ else
+ retvar->var_val.var_number = ml_find_line_or_offset(curbuf, lnum, NULL);
+ if (retvar->var_val.var_number >= 0)
+ ++retvar->var_val.var_number;
+#endif
+}
+
+/*
+ * "lispindent(lnum)" function
+ */
+ static void
+f_lispindent(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_LISP
+ pos_T pos;
+ linenr_T lnum;
+
+ pos = curwin->w_cursor;
+ lnum = get_var_lnum(argvars);
+ if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
+ {
+ curwin->w_cursor.lnum = lnum;
+ retvar->var_val.var_number = get_lisp_indent();
+ curwin->w_cursor = pos;
+ }
+ else
+#endif
+ retvar->var_val.var_number = -1;
+}
+
+/*
+ * "localtime()" function
+ */
+/*ARGSUSED*/
+ static void
+f_localtime(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = (varnumber_T)time(NULL);
+}
+
+/*
+ * "maparg()" function
+ */
+ static void
+f_maparg(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ get_maparg(argvars, retvar, TRUE);
+}
+
+/*
+ * "mapcheck()" function
+ */
+ static void
+f_mapcheck(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ get_maparg(argvars, retvar, FALSE);
+}
+
+ static void
+get_maparg(argvars, retvar, exact)
+ VAR argvars;
+ VAR retvar;
+ int exact;
+{
+ char_u *keys;
+ char_u *which;
+ char_u buf[NUMBUFLEN];
+ char_u *keys_buf = NULL;
+ char_u *rhs;
+ int mode;
+ garray_T ga;
+
+ /* return empty string for failure */
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = NULL;
+
+ keys = get_var_string(&argvars[0]);
+ if (*keys == NUL)
+ return;
+
+ if (argvars[1].var_type != VAR_UNKNOWN)
+ which = get_var_string_buf(&argvars[1], buf);
+ else
+ which = (char_u *)"";
+ mode = get_map_mode(&which, 0);
+
+ keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
+ rhs = check_map(keys, mode, exact);
+ vim_free(keys_buf);
+ if (rhs != NULL)
+ {
+ ga_init(&ga);
+ ga.ga_itemsize = 1;
+ ga.ga_growsize = 40;
+
+ while (*rhs != NUL)
+ ga_concat(&ga, str2special(&rhs, FALSE));
+
+ ga_append(&ga, NUL);
+ retvar->var_val.var_string = (char_u *)ga.ga_data;
+ }
+}
+
+/*
+ * "match()" function
+ */
+ static void
+f_match(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ find_some_match(argvars, retvar, 1);
+}
+
+/*
+ * "matchend()" function
+ */
+ static void
+f_matchend(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ find_some_match(argvars, retvar, 0);
+}
+
+/*
+ * "matchstr()" function
+ */
+ static void
+f_matchstr(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ find_some_match(argvars, retvar, 2);
+}
+
+ static void
+find_some_match(argvars, retvar, type)
+ VAR argvars;
+ VAR retvar;
+ int type;
+{
+ char_u *str;
+ char_u *pat;
+ regmatch_T regmatch;
+ char_u patbuf[NUMBUFLEN];
+ char_u *save_cpo;
+ long start = 0;
+
+ /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
+ save_cpo = p_cpo;
+ p_cpo = (char_u *)"";
+
+ str = get_var_string(&argvars[0]);
+ pat = get_var_string_buf(&argvars[1], patbuf);
+
+ if (type == 2)
+ {
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = NULL;
+ }
+ else
+ retvar->var_val.var_number = -1;
+
+ if (argvars[2].var_type != VAR_UNKNOWN)
+ {
+ start = get_var_number(&argvars[2]);
+ if (start < 0)
+ start = 0;
+ if (start > (long)STRLEN(str))
+ goto theend;
+ str += start;
+ }
+
+ regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
+ if (regmatch.regprog != NULL)
+ {
+ regmatch.rm_ic = p_ic;
+ if (vim_regexec_nl(&regmatch, str, (colnr_T)0))
+ {
+ if (type == 2)
+ retvar->var_val.var_string = vim_strnsave(regmatch.startp[0],
+ (int)(regmatch.endp[0] - regmatch.startp[0]));
+ else
+ {
+ if (type != 0)
+ retvar->var_val.var_number =
+ (varnumber_T)(regmatch.startp[0] - str);
+ else
+ retvar->var_val.var_number =
+ (varnumber_T)(regmatch.endp[0] - str);
+ retvar->var_val.var_number += start;
+ }
+ }
+ vim_free(regmatch.regprog);
+ }
+
+theend:
+ p_cpo = save_cpo;
+}
+
+/*
+ * "mode()" function
+ */
+/*ARGSUSED*/
+ static void
+f_mode(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u buf[2];
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ if (VIsual_select)
+ buf[0] = VIsual_mode + 's' - 'v';
+ else
+ buf[0] = VIsual_mode;
+ }
+ else
+#endif
+ if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
+ buf[0] = 'r';
+ else if (State & INSERT)
+ {
+ if (State & REPLACE_FLAG)
+ buf[0] = 'R';
+ else
+ buf[0] = 'i';
+ }
+ else if (State & CMDLINE)
+ buf[0] = 'c';
+ else
+ buf[0] = 'n';
+
+ buf[1] = NUL;
+ retvar->var_val.var_string = vim_strsave(buf);
+ retvar->var_type = VAR_STRING;
+}
+
+/*
+ * "nr2char()" function
+ */
+ static void
+f_nr2char(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u buf[NUMBUFLEN];
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ buf[(*mb_char2bytes)((int)get_var_number(&argvars[0]), buf)] = NUL;
+ else
+#endif
+ {
+ buf[0] = (char_u)get_var_number(&argvars[0]);
+ buf[1] = NUL;
+ }
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = vim_strsave(buf);
+}
+
+/*
+ * "rename({from}, {to})" function
+ */
+ static void
+f_rename(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u buf[NUMBUFLEN];
+
+ if (check_restricted() || check_secure())
+ retvar->var_val.var_number = -1;
+ else
+ retvar->var_val.var_number = vim_rename(get_var_string(&argvars[0]),
+ get_var_string_buf(&argvars[1], buf));
+}
+
+/*
+ * "resolve()" function
+ */
+ static void
+f_resolve(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *p;
+
+ p = get_var_string(&argvars[0]);
+#ifdef FEAT_SHORTCUT
+ {
+ char_u *v = NULL;
+
+ v = mch_resolve_shortcut(p);
+ if (v != NULL)
+ retvar->var_val.var_string = v;
+ else
+ retvar->var_val.var_string = vim_strsave(p);
+ }
+#else
+# ifdef HAVE_READLINK
+ {
+ char_u buf[MAXPATHL + 1];
+ char_u *cpy;
+ int len;
+ char_u *remain = NULL;
+ char_u *q;
+ int is_relative_to_current = FALSE;
+ int has_trailing_pathsep = FALSE;
+ int limit = 100;
+
+ p = vim_strsave(p);
+
+ if (p[0] == '.' && (vim_ispathsep(p[1])
+ || (p[1] == '.' && (vim_ispathsep(p[2])))))
+ is_relative_to_current = TRUE;
+
+ len = STRLEN(p);
+ if (len > 0 && vim_ispathsep(p[len-1]))
+ has_trailing_pathsep = TRUE;
+
+ q = getnextcomp(p);
+ if (*q != NUL)
+ {
+ /* Separate the first path component in "p", and keep the
+ * remainder (beginning with the path separator). */
+ remain = vim_strsave(q - 1);
+ q[-1] = NUL;
+ }
+
+ for (;;)
+ {
+ for (;;)
+ {
+ len = readlink((char *)p, (char *)buf, MAXPATHL);
+ if (len <= 0)
+ break;
+ buf[len] = NUL;
+
+ if (limit-- == 0)
+ {
+ vim_free(p);
+ vim_free(remain);
+ EMSG(_("E655: Too many symbolic links (cycle?)"));
+ retvar->var_val.var_string = NULL;
+ goto fail;
+ }
+
+ /* Ensure that the result will have a trailing path separator
+ * if the argument has one. */
+ if (remain == NULL && has_trailing_pathsep)
+ add_pathsep(buf);
+
+ /* Separate the first path component in the link value and
+ * concatenate the remainders. */
+ q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
+ if (*q != NUL)
+ {
+ if (remain == NULL)
+ remain = vim_strsave(q - 1);
+ else
+ {
+ cpy = vim_strnsave(q-1, STRLEN(q-1)+STRLEN(remain));
+ if (cpy != NULL)
+ {
+ STRCAT(cpy, remain);
+ vim_free(remain);
+ remain = cpy;
+ }
+ }
+ q[-1] = NUL;
+ }
+
+ q = gettail(p);
+ if (q > p && *q == NUL)
+ {
+ /* Ignore trailing path separator. */
+ q[-1] = NUL;
+ q = gettail(p);
+ }
+ if (q > p && !mch_isFullName(buf))
+ {
+ /* symlink is relative to directory of argument */
+ cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
+ if (cpy != NULL)
+ {
+ STRCPY(cpy, p);
+ STRCPY(gettail(cpy), buf);
+ vim_free(p);
+ p = cpy;
+ }
+ }
+ else
+ {
+ vim_free(p);
+ p = vim_strsave(buf);
+ }
+ }
+
+ if (remain == NULL)
+ break;
+
+ /* Append the first path component of "remain" to "p". */
+ q = getnextcomp(remain + 1);
+ len = q - remain - (*q != NUL);
+ cpy = vim_strnsave(p, STRLEN(p) + len);
+ if (cpy != NULL)
+ {
+ STRNCAT(cpy, remain, len);
+ vim_free(p);
+ p = cpy;
+ }
+ /* Shorten "remain". */
+ if (*q != NUL)
+ STRCPY(remain, q - 1);
+ else
+ {
+ vim_free(remain);
+ remain = NULL;
+ }
+ }
+
+ /* If the result is a relative path name, make it explicitly relative to
+ * the current directory if and only if the argument had this form. */
+ if (!vim_ispathsep(*p))
+ {
+ if (is_relative_to_current
+ && *p != NUL
+ && !(p[0] == '.'
+ && (p[1] == NUL
+ || vim_ispathsep(p[1])
+ || (p[1] == '.'
+ && (p[2] == NUL
+ || vim_ispathsep(p[2]))))))
+ {
+ /* Prepend "./". */
+ cpy = vim_strnsave((char_u *)"./", 2 + STRLEN(p));
+ if (cpy != NULL)
+ {
+ STRCAT(cpy, p);
+ vim_free(p);
+ p = cpy;
+ }
+ }
+ else if (!is_relative_to_current)
+ {
+ /* Strip leading "./". */
+ q = p;
+ while (q[0] == '.' && vim_ispathsep(q[1]))
+ q += 2;
+ if (q > p)
+ mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
+ }
+ }
+
+ /* Ensure that the result will have no trailing path separator
+ * if the argument had none. But keep "/" or "//". */
+ if (!has_trailing_pathsep)
+ {
+ q = p + STRLEN(p);
+ while ((q > p + 2 || (q == p + 2 && !vim_ispathsep(*p)))
+ && vim_ispathsep(q[-1]))
+ --q;
+ *q = NUL;
+ }
+
+ retvar->var_val.var_string = p;
+ }
+# else
+ retvar->var_val.var_string = vim_strsave(p);
+# endif
+#endif
+
+ simplify_filename(retvar->var_val.var_string);
+
+#ifdef HAVE_READLINK
+fail:
+#endif
+ retvar->var_type = VAR_STRING;
+}
+
+/*
+ * "simplify()" function
+ */
+ static void
+f_simplify(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *p;
+
+ p = get_var_string(&argvars[0]);
+ retvar->var_val.var_string = vim_strsave(p);
+ simplify_filename(retvar->var_val.var_string); /* simplify in place */
+ retvar->var_type = VAR_STRING;
+}
+
+/*
+ * "search()" function
+ */
+ static void
+f_search(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *pat;
+ pos_T pos;
+ int save_p_ws = p_ws;
+ int dir;
+
+ pat = get_var_string(&argvars[0]);
+ dir = get_search_arg(&argvars[1], NULL); /* may set p_ws */
+
+ pos = curwin->w_cursor;
+ if (searchit(curwin, curbuf, &pos, dir, pat, 1L,
+ SEARCH_KEEP, RE_SEARCH) != FAIL)
+ {
+ retvar->var_val.var_number = pos.lnum;
+ curwin->w_cursor = pos;
+ /* "/$" will put the cursor after the end of the line, may need to
+ * correct that here */
+ check_cursor();
+ }
+ else
+ retvar->var_val.var_number = 0;
+ p_ws = save_p_ws;
+}
+
+#define SP_NOMOVE 1 /* don't move cursor */
+#define SP_REPEAT 2 /* repeat to find outer pair */
+#define SP_RETCOUNT 4 /* return matchcount */
+
+/*
+ * "searchpair()" function
+ */
+ static void
+f_searchpair(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *spat, *mpat, *epat;
+ char_u *skip;
+ char_u *pat, *pat2, *pat3;
+ pos_T pos;
+ pos_T firstpos;
+ pos_T save_cursor;
+ pos_T save_pos;
+ int save_p_ws = p_ws;
+ char_u *save_cpo;
+ int dir;
+ int flags = 0;
+ char_u nbuf1[NUMBUFLEN];
+ char_u nbuf2[NUMBUFLEN];
+ char_u nbuf3[NUMBUFLEN];
+ int n;
+ int r;
+ int nest = 1;
+ int err;
+
+ retvar->var_val.var_number = 0; /* default: FAIL */
+
+ /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
+ save_cpo = p_cpo;
+ p_cpo = (char_u *)"";
+
+ /* Get the three pattern arguments: start, middle, end. */
+ spat = get_var_string(&argvars[0]);
+ mpat = get_var_string_buf(&argvars[1], nbuf1);
+ epat = get_var_string_buf(&argvars[2], nbuf2);
+
+ /* Make two search patterns: start/end (pat2, for in nested pairs) and
+ * start/middle/end (pat3, for the top pair). */
+ pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
+ pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
+ if (pat2 == NULL || pat3 == NULL)
+ goto theend;
+ sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
+ if (*mpat == NUL)
+ STRCPY(pat3, pat2);
+ else
+ sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
+ spat, epat, mpat);
+
+ /* Handle the optional fourth argument: flags */
+ dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
+
+ /* Optional fifth argument: skip expresion */
+ if (argvars[3].var_type == VAR_UNKNOWN
+ || argvars[4].var_type == VAR_UNKNOWN)
+ skip = (char_u *)"";
+ else
+ skip = get_var_string_buf(&argvars[4], nbuf3);
+
+ save_cursor = curwin->w_cursor;
+ pos = curwin->w_cursor;
+ firstpos.lnum = 0;
+ pat = pat3;
+ for (;;)
+ {
+ n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
+ SEARCH_KEEP, RE_SEARCH);
+ if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
+ /* didn't find it or found the first match again: FAIL */
+ break;
+
+ if (firstpos.lnum == 0)
+ firstpos = pos;
+
+ /* If the skip pattern matches, ignore this match. */
+ if (*skip != NUL)
+ {
+ save_pos = curwin->w_cursor;
+ curwin->w_cursor = pos;
+ r = eval_to_bool(skip, &err, NULL, FALSE);
+ curwin->w_cursor = save_pos;
+ if (err)
+ {
+ /* Evaluating {skip} caused an error, break here. */
+ curwin->w_cursor = save_cursor;
+ retvar->var_val.var_number = -1;
+ break;
+ }
+ if (r)
+ continue;
+ }
+
+ if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
+ {
+ /* Found end when searching backwards or start when searching
+ * forward: nested pair. */
+ ++nest;
+ pat = pat2; /* nested, don't search for middle */
+ }
+ else
+ {
+ /* Found end when searching forward or start when searching
+ * backward: end of (nested) pair; or found middle in outer pair. */
+ if (--nest == 1)
+ pat = pat3; /* outer level, search for middle */
+ }
+
+ if (nest == 0)
+ {
+ /* Found the match: return matchcount or line number. */
+ if (flags & SP_RETCOUNT)
+ ++retvar->var_val.var_number;
+ else
+ retvar->var_val.var_number = pos.lnum;
+ curwin->w_cursor = pos;
+ if (!(flags & SP_REPEAT))
+ break;
+ nest = 1; /* search for next unmatched */
+ }
+ }
+
+ /* If 'n' flag is used or search failed: restore cursor position. */
+ if ((flags & SP_NOMOVE) || retvar->var_val.var_number == 0)
+ curwin->w_cursor = save_cursor;
+
+theend:
+ vim_free(pat2);
+ vim_free(pat3);
+ p_ws = save_p_ws;
+ p_cpo = save_cpo;
+}
+
+ static int
+get_search_arg(varp, flagsp)
+ VAR varp;
+ int *flagsp;
+{
+ int dir = FORWARD;
+ char_u *flags;
+ char_u nbuf[NUMBUFLEN];
+
+ if (varp->var_type != VAR_UNKNOWN)
+ {
+ flags = get_var_string_buf(varp, nbuf);
+ if (vim_strchr(flags, 'b') != NULL)
+ dir = BACKWARD;
+ if (vim_strchr(flags, 'w') != NULL)
+ p_ws = TRUE;
+ if (vim_strchr(flags, 'W') != NULL)
+ p_ws = FALSE;
+ if (flagsp != NULL)
+ {
+ if (vim_strchr(flags, 'n') != NULL)
+ *flagsp |= SP_NOMOVE;
+ if (vim_strchr(flags, 'r') != NULL)
+ *flagsp |= SP_REPEAT;
+ if (vim_strchr(flags, 'm') != NULL)
+ *flagsp |= SP_RETCOUNT;
+ }
+ }
+ return dir;
+}
+
+/*
+ * "setbufvar()" function
+ */
+/*ARGSUSED*/
+ static void
+f_setbufvar(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ buf_T *buf;
+#ifdef FEAT_AUTOCMD
+ aco_save_T aco;
+#else
+ buf_T *save_curbuf;
+#endif
+ char_u *varname, *bufvarname;
+ VAR varp;
+ char_u nbuf[NUMBUFLEN];
+
+ if (check_restricted() || check_secure())
+ return;
+ ++emsg_off;
+ buf = get_buf_var(&argvars[0]);
+ varname = get_var_string(&argvars[1]);
+ varp = &argvars[2];
+
+ if (buf != NULL && varname != NULL && varp != NULL)
+ {
+ /* set curbuf to be our buf, temporarily */
+#ifdef FEAT_AUTOCMD
+ aucmd_prepbuf(&aco, buf);
+#else
+ save_curbuf = curbuf;
+ curbuf = buf;
+#endif
+
+ if (*varname == '&')
+ {
+ ++varname;
+ set_option_value(varname, get_var_number(varp),
+ get_var_string_buf(varp, nbuf), OPT_LOCAL);
+ }
+ else
+ {
+ bufvarname = alloc((unsigned)STRLEN(varname) + 3);
+ if (bufvarname != NULL)
+ {
+ STRCPY(bufvarname, "b:");
+ STRCPY(bufvarname + 2, varname);
+ set_var(bufvarname, varp);
+ vim_free(bufvarname);
+ }
+ }
+
+ /* reset notion of buffer */
+#ifdef FEAT_AUTOCMD
+ aucmd_restbuf(&aco);
+#else
+ curbuf = save_curbuf;
+#endif
+ }
+ --emsg_off;
+}
+
+/*
+ * "setcmdpos()" function
+ */
+ static void
+f_setcmdpos(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = set_cmdline_pos(
+ (int)get_var_number(&argvars[0]) - 1);
+}
+
+/*
+ * "setline()" function
+ */
+ static void
+f_setline(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ linenr_T lnum;
+ char_u *line;
+
+ lnum = get_var_lnum(argvars);
+ line = get_var_string(&argvars[1]);
+ retvar->var_val.var_number = 1; /* FAIL is default */
+
+ if (lnum >= 1
+ && lnum <= curbuf->b_ml.ml_line_count
+ && u_savesub(lnum) == OK
+ && ml_replace(lnum, line, TRUE) == OK)
+ {
+ changed_bytes(lnum, 0);
+ check_cursor_col();
+ retvar->var_val.var_number = 0;
+ }
+}
+
+/*
+ * "setreg()" function
+ */
+ static void
+f_setreg(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ int regname;
+ char_u *strregname;
+ char_u *stropt;
+ int append;
+ char_u yank_type;
+ long block_len;
+
+ block_len = -1;
+ yank_type = MAUTO;
+ append = FALSE;
+
+ strregname = get_var_string(argvars);
+ retvar->var_val.var_number = 1; /* FAIL is default */
+
+ regname = (strregname == NULL ? '"' : *strregname);
+ if (regname == 0 || regname == '@')
+ regname = '"';
+ else if (regname == '=')
+ return;
+
+ if (argvars[2].var_type != VAR_UNKNOWN)
+ {
+ for (stropt = get_var_string(&argvars[2]); *stropt != NUL; ++stropt)
+ switch (*stropt)
+ {
+ case 'a': case 'A': /* append */
+ append = TRUE;
+ break;
+ case 'v': case 'c': /* character-wise selection */
+ yank_type = MCHAR;
+ break;
+ case 'V': case 'l': /* line-wise selection */
+ yank_type = MLINE;
+ break;
+#ifdef FEAT_VISUAL
+ case 'b': case Ctrl_V: /* block-wise selection */
+ yank_type = MBLOCK;
+ if (VIM_ISDIGIT(stropt[1]))
+ {
+ ++stropt;
+ block_len = getdigits(&stropt) - 1;
+ --stropt;
+ }
+ break;
+#endif
+ }
+ }
+
+ write_reg_contents_ex(regname, get_var_string(&argvars[1]), -1,
+ append, yank_type, block_len);
+ retvar->var_val.var_number = 0;
+}
+
+
+/*
+ * "setwinvar(expr)" function
+ */
+/*ARGSUSED*/
+ static void
+f_setwinvar(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ win_T *win;
+#ifdef FEAT_WINDOWS
+ win_T *save_curwin;
+#endif
+ char_u *varname, *winvarname;
+ VAR varp;
+ char_u nbuf[NUMBUFLEN];
+
+ if (check_restricted() || check_secure())
+ return;
+ ++emsg_off;
+ win = find_win_by_nr(&argvars[0]);
+ varname = get_var_string(&argvars[1]);
+ varp = &argvars[2];
+
+ if (win != NULL && varname != NULL && varp != NULL)
+ {
+#ifdef FEAT_WINDOWS
+ /* set curwin to be our win, temporarily */
+ save_curwin = curwin;
+ curwin = win;
+ curbuf = curwin->w_buffer;
+#endif
+
+ if (*varname == '&')
+ {
+ ++varname;
+ set_option_value(varname, get_var_number(varp),
+ get_var_string_buf(varp, nbuf), OPT_LOCAL);
+ }
+ else
+ {
+ winvarname = alloc((unsigned)STRLEN(varname) + 3);
+ if (winvarname != NULL)
+ {
+ STRCPY(winvarname, "w:");
+ STRCPY(winvarname + 2, varname);
+ set_var(winvarname, varp);
+ vim_free(winvarname);
+ }
+ }
+
+#ifdef FEAT_WINDOWS
+ /* Restore current window, if it's still valid (autocomands can make
+ * it invalid). */
+ if (win_valid(save_curwin))
+ {
+ curwin = save_curwin;
+ curbuf = curwin->w_buffer;
+ }
+#endif
+ }
+ --emsg_off;
+}
+
+/*
+ * "nextnonblank()" function
+ */
+ static void
+f_nextnonblank(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ linenr_T lnum;
+
+ for (lnum = get_var_lnum(argvars); ; ++lnum)
+ {
+ if (lnum > curbuf->b_ml.ml_line_count)
+ {
+ lnum = 0;
+ break;
+ }
+ if (*skipwhite(ml_get(lnum)) != NUL)
+ break;
+ }
+ retvar->var_val.var_number = lnum;
+}
+
+/*
+ * "prevnonblank()" function
+ */
+ static void
+f_prevnonblank(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ linenr_T lnum;
+
+ lnum = get_var_lnum(argvars);
+ if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
+ lnum = 0;
+ else
+ while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
+ --lnum;
+ retvar->var_val.var_number = lnum;
+}
+
+#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
+static void make_connection __ARGS((void));
+static int check_connection __ARGS((void));
+
+ static void
+make_connection()
+{
+ if (X_DISPLAY == NULL
+# ifdef FEAT_GUI
+ && !gui.in_use
+# endif
+ )
+ {
+ x_force_connect = TRUE;
+ setup_term_clip();
+ x_force_connect = FALSE;
+ }
+}
+
+ static int
+check_connection()
+{
+ make_connection();
+ if (X_DISPLAY == NULL)
+ {
+ EMSG(_("E240: No connection to Vim server"));
+ return FAIL;
+ }
+ return OK;
+}
+#endif
+
+/*ARGSUSED*/
+ static void
+f_serverlist(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *r = NULL;
+
+#ifdef FEAT_CLIENTSERVER
+# ifdef WIN32
+ r = serverGetVimNames();
+# else
+ make_connection();
+ if (X_DISPLAY != NULL)
+ r = serverGetVimNames(X_DISPLAY);
+# endif
+#endif
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = r;
+}
+
+/*ARGSUSED*/
+ static void
+f_remote_peek(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_CLIENTSERVER
+ var v;
+ char_u *s = NULL;
+# ifdef WIN32
+ int n = 0;
+# endif
+
+ if (check_restricted() || check_secure())
+ {
+ retvar->var_val.var_number = -1;
+ return;
+ }
+# ifdef WIN32
+ sscanf(get_var_string(&argvars[0]), "%x", &n);
+ if (n == 0)
+ retvar->var_val.var_number = -1;
+ else
+ {
+ s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
+ retvar->var_val.var_number = (s != NULL);
+ }
+# else
+ retvar->var_val.var_number = 0;
+ if (check_connection() == FAIL)
+ return;
+
+ retvar->var_val.var_number = serverPeekReply(X_DISPLAY,
+ serverStrToWin(get_var_string(&argvars[0])), &s);
+# endif
+
+ if (argvars[1].var_type != VAR_UNKNOWN && retvar->var_val.var_number > 0)
+ {
+ v.var_type = VAR_STRING;
+ v.var_val.var_string = vim_strsave(s);
+ set_var(get_var_string(&argvars[1]), &v);
+ }
+#else
+ retvar->var_val.var_number = -1;
+#endif
+}
+
+/*ARGSUSED*/
+ static void
+f_remote_read(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *r = NULL;
+
+#ifdef FEAT_CLIENTSERVER
+ if (!check_restricted() && !check_secure())
+ {
+# ifdef WIN32
+ /* The server's HWND is encoded in the 'id' parameter */
+ int n = 0;
+
+ sscanf(get_var_string(&argvars[0]), "%x", &n);
+ if (n != 0)
+ r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
+ if (r == NULL)
+# else
+ if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
+ serverStrToWin(get_var_string(&argvars[0])), &r, FALSE) < 0)
+# endif
+ EMSG(_("E277: Unable to read a server reply"));
+ }
+#endif
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = r;
+}
+
+/*ARGSUSED*/
+ static void
+f_server2client(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_CLIENTSERVER
+ char_u buf[NUMBUFLEN];
+ char_u *server = get_var_string(&argvars[0]);
+ char_u *reply = get_var_string_buf(&argvars[1], buf);
+
+ retvar->var_val.var_number = -1;
+ if (check_restricted() || check_secure())
+ return;
+# ifdef FEAT_X11
+ if (check_connection() == FAIL)
+ return;
+# endif
+
+ if (serverSendReply(server, reply) < 0)
+ {
+ EMSG(_("E258: Unable to send to client"));
+ return;
+ }
+ retvar->var_val.var_number = 0;
+#else
+ retvar->var_val.var_number = -1;
+#endif
+}
+
+#ifdef FEAT_CLIENTSERVER
+static void remote_common __ARGS((VAR argvars, VAR retvar, int expr));
+
+ static void
+remote_common(argvars, retvar, expr)
+ VAR argvars;
+ VAR retvar;
+ int expr;
+{
+ char_u *server_name;
+ char_u *keys;
+ char_u *r = NULL;
+ char_u buf[NUMBUFLEN];
+# ifdef WIN32
+ HWND w;
+# else
+ Window w;
+# endif
+
+ if (check_restricted() || check_secure())
+ return;
+
+# ifdef FEAT_X11
+ if (check_connection() == FAIL)
+ return;
+# endif
+
+ server_name = get_var_string(&argvars[0]);
+ keys = get_var_string_buf(&argvars[1], buf);
+# ifdef WIN32
+ if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
+# else
+ if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
+ < 0)
+# endif
+ {
+ if (r != NULL)
+ EMSG(r); /* sending worked but evaluation failed */
+ else
+ EMSG2(_("E241: Unable to send to %s"), server_name);
+ return;
+ }
+
+ retvar->var_val.var_string = r;
+
+ if (argvars[2].var_type != VAR_UNKNOWN)
+ {
+ var v;
+ char_u str[30];
+
+ sprintf((char *)str, "0x%x", (unsigned int)w);
+ v.var_type = VAR_STRING;
+ v.var_val.var_string = vim_strsave(str);
+ set_var(get_var_string(&argvars[2]), &v);
+ }
+}
+#endif
+
+/*
+ * "remote_expr()" function
+ */
+/*ARGSUSED*/
+ static void
+f_remote_expr(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = NULL;
+#ifdef FEAT_CLIENTSERVER
+ remote_common(argvars, retvar, TRUE);
+#endif
+}
+
+/*
+ * "remote_send()" function
+ */
+/*ARGSUSED*/
+ static void
+f_remote_send(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = NULL;
+#ifdef FEAT_CLIENTSERVER
+ remote_common(argvars, retvar, FALSE);
+#endif
+}
+
+/*
+ * "remote_foreground()" function
+ */
+/*ARGSUSED*/
+ static void
+f_remote_foreground(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = 0;
+#ifdef FEAT_CLIENTSERVER
+# ifdef WIN32
+ /* On Win32 it's done in this application. */
+ serverForeground(get_var_string(&argvars[0]));
+# else
+ /* Send a foreground() expression to the server. */
+ argvars[1].var_type = VAR_STRING;
+ argvars[1].var_val.var_string = vim_strsave((char_u *)"foreground()");
+ argvars[2].var_type = VAR_UNKNOWN;
+ remote_common(argvars, retvar, TRUE);
+ vim_free(argvars[1].var_val.var_string);
+# endif
+#endif
+}
+
+#ifdef HAVE_STRFTIME
+/*
+ * "strftime({format}[, {time}])" function
+ */
+ static void
+f_strftime(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u result_buf[256];
+ struct tm *curtime;
+ time_t seconds;
+ char_u *p;
+
+ retvar->var_type = VAR_STRING;
+
+ p = get_var_string(&argvars[0]);
+ if (argvars[1].var_type == VAR_UNKNOWN)
+ seconds = time(NULL);
+ else
+ seconds = (time_t)get_var_number(&argvars[1]);
+ curtime = localtime(&seconds);
+ /* MSVC returns NULL for an invalid value of seconds. */
+ if (curtime == NULL)
+ retvar->var_val.var_string = vim_strsave((char_u *)_("(Invalid)"));
+ else
+ {
+# ifdef FEAT_MBYTE
+ vimconv_T conv;
+ char_u *enc;
+
+ conv.vc_type = CONV_NONE;
+ enc = enc_locale();
+ convert_setup(&conv, p_enc, enc);
+ if (conv.vc_type != CONV_NONE)
+ p = string_convert(&conv, p, NULL);
+# endif
+ if (p != NULL)
+ (void)strftime((char *)result_buf, sizeof(result_buf),
+ (char *)p, curtime);
+ else
+ result_buf[0] = NUL;
+
+# ifdef FEAT_MBYTE
+ if (conv.vc_type != CONV_NONE)
+ vim_free(p);
+ convert_setup(&conv, enc, p_enc);
+ if (conv.vc_type != CONV_NONE)
+ retvar->var_val.var_string =
+ string_convert(&conv, result_buf, NULL);
+ else
+# endif
+ retvar->var_val.var_string = vim_strsave(result_buf);
+
+# ifdef FEAT_MBYTE
+ /* Release conversion descriptors */
+ convert_setup(&conv, NULL, NULL);
+ vim_free(enc);
+# endif
+ }
+}
+#endif
+
+/*
+ * "stridx()" function
+ */
+ static void
+f_stridx(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u buf[NUMBUFLEN];
+ char_u *needle;
+ char_u *haystack;
+ char_u *pos;
+
+ needle = get_var_string(&argvars[1]);
+ haystack = get_var_string_buf(&argvars[0], buf);
+ pos = (char_u *)strstr((char *)haystack, (char *)needle);
+
+ if (pos == NULL)
+ retvar->var_val.var_number = -1;
+ else
+ retvar->var_val.var_number = (varnumber_T) (pos - haystack);
+}
+
+/*
+ * "strridx()" function
+ */
+ static void
+f_strridx(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u buf[NUMBUFLEN];
+ char_u *needle;
+ char_u *haystack;
+ char_u *rest;
+ char_u *lastmatch = NULL;
+
+ needle = get_var_string(&argvars[1]);
+ haystack = get_var_string_buf(&argvars[0], buf);
+ rest = haystack;
+ while (*haystack != '\0')
+ {
+ rest = (char_u *)strstr((char *)rest, (char *)needle);
+ if (rest == NULL)
+ break;
+ lastmatch = rest++;
+ }
+
+ if (lastmatch == NULL)
+ retvar->var_val.var_number = -1;
+ else
+ retvar->var_val.var_number = (varnumber_T) (lastmatch - haystack);
+}
+
+/*
+ * "strlen()" function
+ */
+ static void
+f_strlen(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_val.var_number = (varnumber_T) (STRLEN(get_var_string(&argvars[0])));
+}
+
+/*
+ * "strpart()" function
+ */
+ static void
+f_strpart(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *p;
+ int n;
+ int len;
+ int slen;
+
+ p = get_var_string(&argvars[0]);
+ slen = (int)STRLEN(p);
+
+ n = get_var_number(&argvars[1]);
+ if (argvars[2].var_type != VAR_UNKNOWN)
+ len = get_var_number(&argvars[2]);
+ else
+ len = slen - n; /* default len: all bytes that are available. */
+
+ /*
+ * Only return the overlap between the specified part and the actual
+ * string.
+ */
+ if (n < 0)
+ {
+ len += n;
+ n = 0;
+ }
+ else if (n > slen)
+ n = slen;
+ if (len < 0)
+ len = 0;
+ else if (n + len > slen)
+ len = slen - n;
+
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = vim_strnsave(p + n, len);
+}
+
+/*
+ * "strtrans()" function
+ */
+ static void
+f_strtrans(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = transstr(get_var_string(&argvars[0]));
+}
+
+/*
+ * "synID(line, col, trans)" function
+ */
+/*ARGSUSED*/
+ static void
+f_synID(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ int id = 0;
+#ifdef FEAT_SYN_HL
+ long line;
+ long col;
+ int trans;
+
+ line = get_var_lnum(argvars);
+ col = get_var_number(&argvars[1]) - 1;
+ trans = get_var_number(&argvars[2]);
+
+ if (line >= 1 && line <= curbuf->b_ml.ml_line_count
+ && col >= 0 && col < (long)STRLEN(ml_get(line)))
+ id = syn_get_id(line, col, trans);
+#endif
+
+ retvar->var_val.var_number = id;
+}
+
+/*
+ * "synIDattr(id, what [, mode])" function
+ */
+/*ARGSUSED*/
+ static void
+f_synIDattr(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *p = NULL;
+#ifdef FEAT_SYN_HL
+ int id;
+ char_u *what;
+ char_u *mode;
+ char_u modebuf[NUMBUFLEN];
+ int modec;
+
+ id = get_var_number(&argvars[0]);
+ what = get_var_string(&argvars[1]);
+ if (argvars[2].var_type != VAR_UNKNOWN)
+ {
+ mode = get_var_string_buf(&argvars[2], modebuf);
+ modec = TOLOWER_ASC(mode[0]);
+ if (modec != 't' && modec != 'c'
+#ifdef FEAT_GUI
+ && modec != 'g'
+#endif
+ )
+ modec = 0; /* replace invalid with current */
+ }
+ else
+ {
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ modec = 'g';
+ else
+#endif
+ if (t_colors > 1)
+ modec = 'c';
+ else
+ modec = 't';
+ }
+
+
+ switch (TOLOWER_ASC(what[0]))
+ {
+ case 'b':
+ if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
+ p = highlight_color(id, what, modec);
+ else /* bold */
+ p = highlight_has_attr(id, HL_BOLD, modec);
+ break;
+
+ case 'f': /* fg[#] */
+ p = highlight_color(id, what, modec);
+ break;
+
+ case 'i':
+ if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
+ p = highlight_has_attr(id, HL_INVERSE, modec);
+ else /* italic */
+ p = highlight_has_attr(id, HL_ITALIC, modec);
+ break;
+
+ case 'n': /* name */
+ p = get_highlight_name(NULL, id - 1);
+ break;
+
+ case 'r': /* reverse */
+ p = highlight_has_attr(id, HL_INVERSE, modec);
+ break;
+
+ case 's': /* standout */
+ p = highlight_has_attr(id, HL_STANDOUT, modec);
+ break;
+
+ case 'u': /* underline */
+ p = highlight_has_attr(id, HL_UNDERLINE, modec);
+ break;
+ }
+
+ if (p != NULL)
+ p = vim_strsave(p);
+#endif
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = p;
+}
+
+/*
+ * "synIDtrans(id)" function
+ */
+/*ARGSUSED*/
+ static void
+f_synIDtrans(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ int id;
+
+#ifdef FEAT_SYN_HL
+ id = get_var_number(&argvars[0]);
+
+ if (id > 0)
+ id = syn_get_final_id(id);
+ else
+#endif
+ id = 0;
+
+ retvar->var_val.var_number = id;
+}
+
+/*
+ * "system()" function
+ */
+ static void
+f_system(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *p;
+
+ p = get_cmd_output(get_var_string(&argvars[0]), SHELL_SILENT);
+#ifdef USE_CR
+ /* translate <CR> into <NL> */
+ if (p != NULL)
+ {
+ char_u *s;
+
+ for (s = p; *s; ++s)
+ {
+ if (*s == CAR)
+ *s = NL;
+ }
+ }
+#else
+# ifdef USE_CRNL
+ /* translate <CR><NL> into <NL> */
+ if (p != NULL)
+ {
+ char_u *s, *d;
+
+ d = p;
+ for (s = p; *s; ++s)
+ {
+ if (s[0] == CAR && s[1] == NL)
+ ++s;
+ *d++ = *s;
+ }
+ *d = NUL;
+ }
+# endif
+#endif
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = p;
+}
+
+/*
+ * "submatch()" function
+ */
+ static void
+f_submatch(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = reg_submatch((int)get_var_number(&argvars[0]));
+}
+
+/*
+ * "substitute()" function
+ */
+ static void
+f_substitute(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u patbuf[NUMBUFLEN];
+ char_u subbuf[NUMBUFLEN];
+ char_u flagsbuf[NUMBUFLEN];
+
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = do_string_sub(
+ get_var_string(&argvars[0]),
+ get_var_string_buf(&argvars[1], patbuf),
+ get_var_string_buf(&argvars[2], subbuf),
+ get_var_string_buf(&argvars[3], flagsbuf));
+}
+
+/*
+ * "tempname()" function
+ */
+/*ARGSUSED*/
+ static void
+f_tempname(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ static int x = 'A';
+
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = vim_tempname(x);
+
+ /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
+ * names. Skip 'I' and 'O', they are used for shell redirection. */
+ do
+ {
+ if (x == 'Z')
+ x = '0';
+ else if (x == '9')
+ x = 'A';
+ else
+ {
+#ifdef EBCDIC
+ if (x == 'I')
+ x = 'J';
+ else if (x == 'R')
+ x = 'S';
+ else
+#endif
+ ++x;
+ }
+ } while (x == 'I' || x == 'O');
+}
+
+/*
+ * "tolower(string)" function
+ */
+ static void
+f_tolower(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *p;
+
+ p = vim_strsave(get_var_string(&argvars[0]));
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = p;
+
+ if (p != NULL)
+ while (*p != NUL)
+ {
+#ifdef FEAT_MBYTE
+ int l;
+
+ if (enc_utf8)
+ {
+ int c, lc;
+
+ c = utf_ptr2char(p);
+ lc = utf_tolower(c);
+ l = utf_ptr2len_check(p);
+ /* TODO: reallocate string when byte count changes. */
+ if (utf_char2len(lc) == l)
+ utf_char2bytes(lc, p);
+ p += l;
+ }
+ else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
+ p += l; /* skip multi-byte character */
+ else
+#endif
+ {
+ *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
+ ++p;
+ }
+ }
+}
+
+/*
+ * "toupper(string)" function
+ */
+ static void
+f_toupper(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ char_u *p;
+
+ p = vim_strsave(get_var_string(&argvars[0]));
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = p;
+
+ if (p != NULL)
+ while (*p != NUL)
+ {
+#ifdef FEAT_MBYTE
+ int l;
+
+ if (enc_utf8)
+ {
+ int c, uc;
+
+ c = utf_ptr2char(p);
+ uc = utf_toupper(c);
+ l = utf_ptr2len_check(p);
+ /* TODO: reallocate string when byte count changes. */
+ if (utf_char2len(uc) == l)
+ utf_char2bytes(uc, p);
+ p += l;
+ }
+ else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
+ p += l; /* skip multi-byte character */
+ else
+#endif
+ {
+ *p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */
+ p++;
+ }
+ }
+}
+
+/*
+ * "type(expr)" function
+ */
+ static void
+f_type(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ if (argvars[0].var_type == VAR_NUMBER)
+ retvar->var_val.var_number = 0;
+ else
+ retvar->var_val.var_number = 1;
+}
+
+/*
+ * "virtcol(string)" function
+ */
+ static void
+f_virtcol(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ colnr_T vcol = 0;
+ pos_T *fp;
+
+ fp = var2fpos(&argvars[0], FALSE);
+ if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count)
+ {
+ getvvcol(curwin, fp, NULL, NULL, &vcol);
+ ++vcol;
+ }
+
+ retvar->var_val.var_number = vcol;
+}
+
+/*
+ * "visualmode()" function
+ */
+/*ARGSUSED*/
+ static void
+f_visualmode(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_VISUAL
+ char_u str[2];
+
+ retvar->var_type = VAR_STRING;
+ str[0] = curbuf->b_visual_mode_eval;
+ str[1] = NUL;
+ retvar->var_val.var_string = vim_strsave(str);
+
+ /* A non-zero number or non-empty string argument: reset mode. */
+ if ((argvars[0].var_type == VAR_NUMBER
+ && argvars[0].var_val.var_number != 0)
+ || (argvars[0].var_type == VAR_STRING
+ && *get_var_string(&argvars[0]) != NUL))
+ curbuf->b_visual_mode_eval = NUL;
+#else
+ retvar->var_val.var_number = 0; /* return anything, it won't work anyway */
+#endif
+}
+
+/*
+ * "winbufnr(nr)" function
+ */
+ static void
+f_winbufnr(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ win_T *wp;
+
+ wp = find_win_by_nr(&argvars[0]);
+ if (wp == NULL)
+ retvar->var_val.var_number = -1;
+ else
+ retvar->var_val.var_number = wp->w_buffer->b_fnum;
+}
+
+/*
+ * "wincol()" function
+ */
+/*ARGSUSED*/
+ static void
+f_wincol(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ validate_cursor();
+ retvar->var_val.var_number = curwin->w_wcol + 1;
+}
+
+/*
+ * "winheight(nr)" function
+ */
+ static void
+f_winheight(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ win_T *wp;
+
+ wp = find_win_by_nr(&argvars[0]);
+ if (wp == NULL)
+ retvar->var_val.var_number = -1;
+ else
+ retvar->var_val.var_number = wp->w_height;
+}
+
+/*
+ * "winline()" function
+ */
+/*ARGSUSED*/
+ static void
+f_winline(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ validate_cursor();
+ retvar->var_val.var_number = curwin->w_wrow + 1;
+}
+
+/*
+ * "winnr()" function
+ */
+/* ARGSUSED */
+ static void
+f_winnr(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ int nr = 1;
+#ifdef FEAT_WINDOWS
+ win_T *wp;
+
+ for (wp = firstwin; wp != curwin; wp = wp->w_next)
+ ++nr;
+#endif
+ retvar->var_val.var_number = nr;
+}
+
+/*
+ * "winrestcmd()" function
+ */
+/* ARGSUSED */
+ static void
+f_winrestcmd(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+#ifdef FEAT_WINDOWS
+ win_T *wp;
+ int winnr = 1;
+ garray_T ga;
+ char_u buf[50];
+
+ ga_init2(&ga, (int)sizeof(char), 70);
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ {
+ sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
+ ga_concat(&ga, buf);
+# ifdef FEAT_VERTSPLIT
+ sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
+ ga_concat(&ga, buf);
+# endif
+ ++winnr;
+ }
+
+ retvar->var_val.var_string = ga.ga_data;
+#else
+ retvar->var_val.var_string = NULL;
+#endif
+ retvar->var_type = VAR_STRING;
+}
+
+/*
+ * "winwidth(nr)" function
+ */
+ static void
+f_winwidth(argvars, retvar)
+ VAR argvars;
+ VAR retvar;
+{
+ win_T *wp;
+
+ wp = find_win_by_nr(&argvars[0]);
+ if (wp == NULL)
+ retvar->var_val.var_number = -1;
+ else
+#ifdef FEAT_VERTSPLIT
+ retvar->var_val.var_number = wp->w_width;
+#else
+ retvar->var_val.var_number = Columns;
+#endif
+}
+
+ static win_T *
+find_win_by_nr(vp)
+ VAR vp;
+{
+#ifdef FEAT_WINDOWS
+ win_T *wp;
+#endif
+ int nr;
+
+ nr = get_var_number(vp);
+
+#ifdef FEAT_WINDOWS
+ if (nr == 0)
+ return curwin;
+
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (--nr <= 0)
+ break;
+ return wp;
+#else
+ if (nr == 0 || nr == 1)
+ return curwin;
+ return NULL;
+#endif
+}
+
+/*
+ * Translate a String variable into a position.
+ */
+ static pos_T *
+var2fpos(varp, lnum)
+ VAR varp;
+ int lnum; /* TRUE when $ is last line */
+{
+ char_u *name;
+ static pos_T pos;
+ pos_T *pp;
+
+ name = get_var_string(varp);
+ if (name[0] == '.') /* cursor */
+ return &curwin->w_cursor;
+ if (name[0] == '\'') /* mark */
+ {
+ pp = getmark(name[1], FALSE);
+ if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
+ return NULL;
+ return pp;
+ }
+ if (name[0] == '$') /* last column or line */
+ {
+ if (lnum)
+ {
+ pos.lnum = curbuf->b_ml.ml_line_count;
+ pos.col = 0;
+ }
+ else
+ {
+ pos.lnum = curwin->w_cursor.lnum;
+ pos.col = (colnr_T)STRLEN(ml_get_curline());
+ }
+ return &pos;
+ }
+ return NULL;
+}
+
+/*
+ * Get the length of an environment variable name.
+ * Advance "arg" to the first character after the name.
+ * Return 0 for error.
+ */
+ static int
+get_env_len(arg)
+ char_u **arg;
+{
+ char_u *p;
+ int len;
+
+ for (p = *arg; vim_isIDc(*p); ++p)
+ ;
+ if (p == *arg) /* no name found */
+ return 0;
+
+ len = (int)(p - *arg);
+ *arg = p;
+ return len;
+}
+
+/*
+ * Get the length of the name of a function or internal variable.
+ * "arg" is advanced to the first non-white character after the name.
+ * Return 0 if something is wrong.
+ */
+ static int
+get_id_len(arg)
+ char_u **arg;
+{
+ char_u *p;
+ int len;
+
+ /* Find the end of the name. */
+ for (p = *arg; eval_isnamec(*p); ++p)
+ ;
+ if (p == *arg) /* no name found */
+ return 0;
+
+ len = (int)(p - *arg);
+ *arg = skipwhite(p);
+
+ return len;
+}
+
+/*
+ * Get the length of the name of a function.
+ * "arg" is advanced to the first non-white character after the name.
+ * Return 0 if something is wrong.
+ * If the name contains 'magic' {}'s, expand them and return the
+ * expanded name in an allocated string via 'alias' - caller must free.
+ */
+ static int
+get_func_len(arg, alias, evaluate)
+ char_u **arg;
+ char_u **alias;
+ int evaluate;
+{
+ int len;
+#ifdef FEAT_MAGIC_BRACES
+ char_u *p;
+ char_u *expr_start;
+ char_u *expr_end;
+#endif
+
+ *alias = NULL; /* default to no alias */
+
+ if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
+ && (*arg)[2] == (int)KE_SNR)
+ {
+ /* hard coded <SNR>, already translated */
+ *arg += 3;
+ return get_id_len(arg) + 3;
+ }
+ len = eval_fname_script(*arg);
+ if (len > 0)
+ {
+ /* literal "<SID>", "s:" or "<SNR>" */
+ *arg += len;
+ }
+
+#ifdef FEAT_MAGIC_BRACES
+ /*
+ * Find the end of the name;
+ */
+ p = find_name_end(*arg, &expr_start, &expr_end);
+ /* check for {} construction */
+ if (expr_start != NULL)
+ {
+ char_u *temp_string;
+
+ if (!evaluate)
+ {
+ len += (int)(p - *arg);
+ *arg = skipwhite(p);
+ return len;
+ }
+
+ /*
+ * Include any <SID> etc in the expanded string:
+ * Thus the -len here.
+ */
+ temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
+ if (temp_string == NULL)
+ return 0;
+ *alias = temp_string;
+ *arg = skipwhite(p);
+ return (int)STRLEN(temp_string);
+ }
+#endif
+
+ len += get_id_len(arg);
+ if (len == 0)
+ EMSG2(_(e_invexpr2), *arg);
+
+ return len;
+}
+
+ static char_u *
+find_name_end(arg, expr_start, expr_end)
+ char_u *arg;
+ char_u **expr_start;
+ char_u **expr_end;
+{
+ int nesting = 0;
+ char_u *p;
+
+ *expr_start = NULL;
+ *expr_end = NULL;
+
+ for (p = arg; (*p != NUL && (eval_isnamec(*p) || nesting != 0)); ++p)
+ {
+#ifdef FEAT_MAGIC_BRACES
+ if (*p == '{')
+ {
+ nesting++;
+ if (*expr_start == NULL)
+ *expr_start = p;
+ }
+ else if (*p == '}')
+ {
+ nesting--;
+ if (nesting == 0 && *expr_end == NULL)
+ *expr_end = p;
+ }
+#endif
+ }
+
+ return p;
+}
+
+/*
+ * Return TRUE if character "c" can be used in a variable or function name.
+ */
+ static int
+eval_isnamec(c)
+ int c;
+{
+ return (ASCII_ISALNUM(c) || c == '_' || c == ':'
+#ifdef FEAT_MAGIC_BRACES
+ || c == '{' || c == '}'
+#endif
+ );
+}
+
+/*
+ * Find a v: variable.
+ * Return it's index, or -1 if not found.
+ */
+ static int
+find_vim_var(name, len)
+ char_u *name;
+ int len; /* length of "name" */
+{
+ char_u *vname;
+ int vlen;
+ int i;
+
+ /*
+ * Ignore "v:" for old built-in variables, require it for new ones.
+ */
+ if (name[0] == 'v' && name[1] == ':')
+ {
+ vname = name + 2;
+ vlen = len - 2;
+ }
+ else
+ {
+ vname = name;
+ vlen = len;
+ }
+ for (i = 0; i < VV_LEN; ++i)
+ if (vlen == vimvars[i].len && STRCMP(vname, vimvars[i].name) == 0
+ && ((vimvars[i].flags & VV_COMPAT) || vname != name))
+ return i;
+ return -1;
+}
+
+/*
+ * Set number v: variable to "val".
+ */
+ void
+set_vim_var_nr(idx, val)
+ int idx;
+ long val;
+{
+ vimvars[idx].val = (char_u *)val;
+}
+
+/*
+ * Get number v: variable value;
+ */
+ long
+get_vim_var_nr(idx)
+ int idx;
+{
+ return (long)vimvars[idx].val;
+}
+
+/*
+ * Set v:count, v:count1 and v:prevcount.
+ */
+ void
+set_vcount(count, count1)
+ long count;
+ long count1;
+{
+ vimvars[VV_PREVCOUNT].val = vimvars[VV_COUNT].val;
+ vimvars[VV_COUNT].val = (char_u *)count;
+ vimvars[VV_COUNT1].val = (char_u *)count1;
+}
+
+/*
+ * Set string v: variable to a copy of "val".
+ */
+ void
+set_vim_var_string(idx, val, len)
+ int idx;
+ char_u *val;
+ int len; /* length of "val" to use or -1 (whole string) */
+{
+ vim_free(vimvars[idx].val);
+ if (val == NULL)
+ vimvars[idx].val = NULL;
+ else if (len == -1)
+ vimvars[idx].val = vim_strsave(val);
+ else
+ vimvars[idx].val = vim_strnsave(val, len);
+}
+
+/*
+ * Set v:register if needed.
+ */
+ void
+set_reg_var(c)
+ int c;
+{
+ char_u regname;
+
+ if (c == 0 || c == ' ')
+ regname = '"';
+ else
+ regname = c;
+ /* Avoid free/alloc when the value is already right. */
+ if (vimvars[VV_REG].val == NULL || vimvars[VV_REG].val[0] != c)
+ set_vim_var_string(VV_REG, &regname, 1);
+}
+
+/*
+ * Get or set v:exception. If "oldval" == NULL, return the current value.
+ * Otherwise, restore the value to "oldval" and return NULL.
+ * Must always be called in pairs to save and restore v:exception! Does not
+ * take care of memory allocations.
+ */
+ char_u *
+v_exception(oldval)
+ char_u *oldval;
+{
+ if (oldval == NULL)
+ return vimvars[VV_EXCEPTION].val;
+
+ vimvars[VV_EXCEPTION].val = oldval;
+ return NULL;
+}
+
+/*
+ * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
+ * Otherwise, restore the value to "oldval" and return NULL.
+ * Must always be called in pairs to save and restore v:throwpoint! Does not
+ * take care of memory allocations.
+ */
+ char_u *
+v_throwpoint(oldval)
+ char_u *oldval;
+{
+ if (oldval == NULL)
+ return vimvars[VV_THROWPOINT].val;
+
+ vimvars[VV_THROWPOINT].val = oldval;
+ return NULL;
+}
+
+#if defined(FEAT_AUTOCMD) || defined(PROTO)
+/*
+ * Set v:cmdarg.
+ * If "eap" != NULL, use "eap" to generate the value and return the old value.
+ * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
+ * Must always be called in pairs!
+ */
+ char_u *
+set_cmdarg(eap, oldarg)
+ exarg_T *eap;
+ char_u *oldarg;
+{
+ char_u *oldval;
+ char_u *newval;
+ unsigned len;
+
+ oldval = vimvars[VV_CMDARG].val;
+ if (eap != NULL)
+ {
+ if (eap->force_bin == FORCE_BIN)
+ len = 6;
+ else if (eap->force_bin == FORCE_NOBIN)
+ len = 8;
+ else
+ len = 0;
+ if (eap->force_ff != 0)
+ len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
+# ifdef FEAT_MBYTE
+ if (eap->force_enc != 0)
+ len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
+# endif
+
+ newval = alloc(len + 1);
+ if (newval == NULL)
+ return NULL;
+
+ if (eap->force_bin == FORCE_BIN)
+ sprintf((char *)newval, " ++bin");
+ else if (eap->force_bin == FORCE_NOBIN)
+ sprintf((char *)newval, " ++nobin");
+ else
+ *newval = NUL;
+ if (eap->force_ff != 0)
+ sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
+ eap->cmd + eap->force_ff);
+# ifdef FEAT_MBYTE
+ if (eap->force_enc != 0)
+ sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
+ eap->cmd + eap->force_enc);
+# endif
+ vimvars[VV_CMDARG].val = newval;
+ return oldval;
+ }
+
+ vim_free(oldval);
+ vimvars[VV_CMDARG].val = oldarg;
+ return NULL;
+}
+#endif
+
+/*
+ * Get the value of internal variable "name".
+ * Return OK or FAIL.
+ */
+ static int
+get_var_var(name, len, retvar)
+ char_u *name;
+ int len; /* length of "name" */
+ VAR retvar; /* NULL when only checking existence */
+{
+ int ret = OK;
+ int type = VAR_UNKNOWN;
+ long number = 1;
+ char_u *string = NULL;
+ VAR v;
+ int cc;
+ int i;
+
+ /* truncate the name, so that we can use strcmp() */
+ cc = name[len];
+ name[len] = NUL;
+
+ /*
+ * Check for "b:changedtick".
+ */
+ if (STRCMP(name, "b:changedtick") == 0)
+ {
+ type = VAR_NUMBER;
+ number = curbuf->b_changedtick;
+ }
+
+ /*
+ * Check for built-in v: variables.
+ */
+ else if ((i = find_vim_var(name, len)) >= 0)
+ {
+ type = vimvars[i].type;
+ number = (long)vimvars[i].val;
+ string = vimvars[i].val;
+ }
+
+ /*
+ * Check for user-defined variables.
+ */
+ else
+ {
+ v = find_var(name, FALSE);
+ if (v != NULL)
+ {
+ type = v->var_type;
+ number = v->var_val.var_number;
+ string = v->var_val.var_string;
+ }
+ }
+
+ if (type == VAR_UNKNOWN)
+ {
+ if (retvar != NULL)
+ EMSG2(_("E121: Undefined variable: %s"), name);
+ ret = FAIL;
+ }
+ else if (retvar != NULL)
+ {
+ retvar->var_type = type;
+ if (type == VAR_NUMBER)
+ retvar->var_val.var_number = number;
+ else if (type == VAR_STRING)
+ {
+ if (string != NULL)
+ string = vim_strsave(string);
+ retvar->var_val.var_string = string;
+ }
+ }
+
+ name[len] = cc;
+
+ return ret;
+}
+
+/*
+ * Allocate memory for a variable, and make it emtpy (0 or NULL value).
+ */
+ static VAR
+alloc_var()
+{
+ return (VAR)alloc_clear((unsigned)sizeof(var));
+}
+
+/*
+ * Allocate memory for a variable, and assign a string to it.
+ * The string "s" must have been allocated, it is consumed.
+ * Return NULL for out of memory, the variable otherwise.
+ */
+ static VAR
+alloc_string_var(s)
+ char_u *s;
+{
+ VAR retvar;
+
+ retvar = alloc_var();
+ if (retvar != NULL)
+ {
+ retvar->var_type = VAR_STRING;
+ retvar->var_val.var_string = s;
+ }
+ else
+ vim_free(s);
+ return retvar;
+}
+
+/*
+ * Free the memory for a variable.
+ */
+ static void
+free_var(varp)
+ VAR varp;
+{
+ if (varp != NULL)
+ {
+ if (varp->var_type == VAR_STRING)
+ vim_free(varp->var_val.var_string);
+ vim_free(varp->var_name);
+ vim_free(varp);
+ }
+}
+
+/*
+ * Free the memory for a variable value and set the value to NULL or 0.
+ */
+ static void
+clear_var(varp)
+ VAR varp;
+{
+ if (varp != NULL)
+ {
+ if (varp->var_type == VAR_STRING)
+ {
+ vim_free(varp->var_val.var_string);
+ varp->var_val.var_string = NULL;
+ }
+ else
+ varp->var_val.var_number = 0;
+ }
+}
+
+/*
+ * Get the number value of a variable.
+ * If it is a String variable, uses vim_str2nr().
+ */
+ static long
+get_var_number(varp)
+ VAR varp;
+{
+ long n;
+
+ if (varp->var_type == VAR_NUMBER)
+ return (long)(varp->var_val.var_number);
+ else if (varp->var_type == VAR_UNKNOWN || varp->var_val.var_string == NULL)
+ return 0L;
+ else
+ {
+ vim_str2nr(varp->var_val.var_string, NULL, NULL, TRUE, TRUE, &n, NULL);
+ return n;
+ }
+}
+
+/*
+ * Get the lnum from the first argument. Also accepts ".", "$", etc.
+ */
+ static linenr_T
+get_var_lnum(argvars)
+ VAR argvars;
+{
+ var retvar;
+ linenr_T lnum;
+
+ lnum = get_var_number(&argvars[0]);
+ if (lnum == 0) /* no valid number, try using line() */
+ {
+ retvar.var_type = VAR_NUMBER;
+ f_line(argvars, &retvar);
+ lnum = retvar.var_val.var_number;
+ clear_var(&retvar);
+ }
+ return lnum;
+}
+
+/*
+ * Get the string value of a variable.
+ * If it is a Number variable, the number is converted into a string.
+ * get_var_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
+ * get_var_string_buf() uses a given buffer.
+ * If the String variable has never been set, return an empty string.
+ * Never returns NULL;
+ */
+ static char_u *
+get_var_string(varp)
+ VAR varp;
+{
+ static char_u mybuf[NUMBUFLEN];
+
+ return get_var_string_buf(varp, mybuf);
+}
+
+ static char_u *
+get_var_string_buf(varp, buf)
+ VAR varp;
+ char_u *buf;
+{
+ if (varp->var_type == VAR_NUMBER)
+ {
+ sprintf((char *)buf, "%ld", (long)varp->var_val.var_number);
+ return buf;
+ }
+ else if (varp->var_val.var_string == NULL)
+ return (char_u *)"";
+ else
+ return varp->var_val.var_string;
+}
+
+/*
+ * Find variable "name" in the list of variables.
+ * Return a pointer to it if found, NULL if not found.
+ */
+ static VAR
+find_var(name, writing)
+ char_u *name;
+ int writing;
+{
+ int i;
+ char_u *varname;
+ garray_T *gap;
+
+ /* Check for function arguments "a:" */
+ if (name[0] == 'a' && name[1] == ':')
+ {
+ if (writing)
+ {
+ EMSG2(_(e_readonlyvar), name);
+ return NULL;
+ }
+ name += 2;
+ if (current_funccal == NULL)
+ return NULL;
+ if (VIM_ISDIGIT(*name))
+ {
+ i = atol((char *)name);
+ if (i == 0) /* a:0 */
+ return &current_funccal->a0_var;
+ i += current_funccal->func->args.ga_len;
+ if (i > current_funccal->argcount) /* a:999 */
+ return NULL;
+ return &(current_funccal->argvars[i - 1]); /* a:1, a:2, etc. */
+ }
+ if (STRCMP(name, "firstline") == 0)
+ return &(current_funccal->firstline);
+ if (STRCMP(name, "lastline") == 0)
+ return &(current_funccal->lastline);
+ for (i = 0; i < current_funccal->func->args.ga_len; ++i)
+ if (STRCMP(name, ((char_u **)
+ (current_funccal->func->args.ga_data))[i]) == 0)
+ return &(current_funccal->argvars[i]); /* a:name */
+ return NULL;
+ }
+
+ gap = find_var_ga(name, &varname);
+ if (gap == NULL)
+ return NULL;
+ return find_var_in_ga(gap, varname);
+}
+
+ static VAR
+find_var_in_ga(gap, varname)
+ garray_T *gap;
+ char_u *varname;
+{
+ int i;
+
+ for (i = gap->ga_len; --i >= 0; )
+ if (VAR_GAP_ENTRY(i, gap).var_name != NULL
+ && STRCMP(VAR_GAP_ENTRY(i, gap).var_name, varname) == 0)
+ break;
+ if (i < 0)
+ return NULL;
+ return &VAR_GAP_ENTRY(i, gap);
+}
+
+/*
+ * Find the growarray and start of name without ':' for a variable name.
+ */
+ static garray_T *
+find_var_ga(name, varname)
+ char_u *name;
+ char_u **varname;
+{
+ if (name[1] != ':')
+ {
+ /* If not "x:name" there must not be any ":" in the name. */
+ if (vim_strchr(name, ':') != NULL)
+ return NULL;
+ *varname = name;
+ if (current_funccal == NULL)
+ return &variables; /* global variable */
+ return &current_funccal->l_vars; /* local function variable */
+ }
+ *varname = name + 2;
+ if (*name == 'b') /* buffer variable */
+ return &curbuf->b_vars;
+ if (*name == 'w') /* window variable */
+ return &curwin->w_vars;
+ if (*name == 'g') /* global variable */
+ return &variables;
+ if (*name == 'l' && current_funccal != NULL)/* local function variable */
+ return &current_funccal->l_vars;
+ if (*name == 's' /* script variable */
+ && current_SID > 0 && current_SID <= ga_scripts.ga_len)
+ return &SCRIPT_VARS(current_SID);
+ return NULL;
+}
+
+/*
+ * Get the string value of a (global/local) variable.
+ * Returns NULL when it doesn't exist.
+ */
+ char_u *
+get_var_value(name)
+ char_u *name;
+{
+ VAR v;
+
+ v = find_var(name, FALSE);
+ if (v == NULL)
+ return NULL;
+ return get_var_string(v);
+}
+
+/*
+ * Allocate a new growarry for a sourced script. It will be used while
+ * sourcing this script and when executing functions defined in the script.
+ */
+ void
+new_script_vars(id)
+ scid_T id;
+{
+ if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
+ {
+ while (ga_scripts.ga_len < id)
+ {
+ var_init(&SCRIPT_VARS(ga_scripts.ga_len + 1));
+ ++ga_scripts.ga_len;
+ --ga_scripts.ga_room;
+ }
+ }
+}
+
+/*
+ * Initialize internal variables for use.
+ */
+ void
+var_init(gap)
+ garray_T *gap;
+{
+ ga_init2(gap, (int)sizeof(var), 4);
+}
+
+/*
+ * Clean up a list of internal variables.
+ */
+ void
+var_clear(gap)
+ garray_T *gap;
+{
+ int i;
+
+ for (i = gap->ga_len; --i >= 0; )
+ var_free_one(&VAR_GAP_ENTRY(i, gap));
+ ga_clear(gap);
+}
+
+ static void
+var_free_one(v)
+ VAR v;
+{
+ vim_free(v->var_name);
+ v->var_name = NULL;
+ if (v->var_type == VAR_STRING)
+ vim_free(v->var_val.var_string);
+ v->var_val.var_string = NULL;
+}
+
+/*
+ * List the value of one internal variable.
+ */
+ static void
+list_one_var(v, prefix)
+ VAR v;
+ char_u *prefix;
+{
+ list_one_var_a(prefix, v->var_name, v->var_type, get_var_string(v));
+}
+
+/*
+ * List the value of one "v:" variable.
+ */
+ static void
+list_vim_var(i)
+ int i; /* index in vimvars[] */
+{
+ char_u *p;
+ char_u numbuf[NUMBUFLEN];
+
+ if (vimvars[i].type == VAR_NUMBER)
+ {
+ p = numbuf;
+ sprintf((char *)p, "%ld", (long)vimvars[i].val);
+ }
+ else if (vimvars[i].val == NULL)
+ p = (char_u *)"";
+ else
+ p = vimvars[i].val;
+ list_one_var_a((char_u *)"v:", (char_u *)vimvars[i].name,
+ vimvars[i].type, p);
+}
+
+ static void
+list_one_var_a(prefix, name, type, string)
+ char_u *prefix;
+ char_u *name;
+ int type;
+ char_u *string;
+{
+ msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */
+ if (name != NULL) /* "a:" vars don't have a name stored */
+ msg_puts(name);
+ msg_putchar(' ');
+ msg_advance(22);
+ if (type == VAR_NUMBER)
+ msg_putchar('#');
+ else
+ msg_putchar(' ');
+ msg_outtrans(string);
+}
+
+/*
+ * Set variable "name" to value in "varp".
+ * If the variable already exists, the value is updated.
+ * Otherwise the variable is created.
+ */
+ static void
+set_var(name, varp)
+ char_u *name;
+ VAR varp;
+{
+ int i;
+ VAR v;
+ char_u *varname;
+ garray_T *gap;
+
+ /*
+ * Handle setting internal v: variables.
+ */
+ i = find_vim_var(name, (int)STRLEN(name));
+ if (i >= 0)
+ {
+ if (vimvars[i].flags & VV_RO)
+ EMSG2(_(e_readonlyvar), name);
+ else
+ {
+ if (vimvars[i].type == VAR_STRING)
+ {
+ vim_free(vimvars[i].val);
+ vimvars[i].val = vim_strsave(get_var_string(varp));
+ }
+ else
+ vimvars[i].val = (char_u *)(long)varp->var_val.var_number;
+ }
+ return;
+ }
+
+ v = find_var(name, TRUE);
+ if (v != NULL) /* existing variable, only need to free string */
+ {
+ if (v->var_type == VAR_STRING)
+ vim_free(v->var_val.var_string);
+ }
+ else /* add a new variable */
+ {
+ gap = find_var_ga(name, &varname);
+ if (gap == NULL) /* illegal name */
+ {
+ EMSG2(_("E461: Illegal variable name: %s"), name);
+ return;
+ }
+
+ /* Try to use an empty entry */
+ for (i = gap->ga_len; --i >= 0; )
+ if (VAR_GAP_ENTRY(i, gap).var_name == NULL)
+ break;
+ if (i < 0) /* need to allocate more room */
+ {
+ if (ga_grow(gap, 1) == FAIL)
+ return;
+ i = gap->ga_len;
+ }
+ v = &VAR_GAP_ENTRY(i, gap);
+ if ((v->var_name = vim_strsave(varname)) == NULL)
+ return;
+ if (i == gap->ga_len)
+ {
+ ++gap->ga_len;
+ --gap->ga_room;
+ }
+ }
+ copy_var(varp, v);
+}
+
+ static void
+copy_var(from, to)
+ VAR from;
+ VAR to;
+{
+ to->var_type = from->var_type;
+ if (from->var_type == VAR_STRING)
+ to->var_val.var_string = vim_strsave(get_var_string(from));
+ else
+ to->var_val.var_number = from->var_val.var_number;
+}
+
+/*
+ * ":echo expr1 ..." print each argument separated with a space, add a
+ * newline at the end.
+ * ":echon expr1 ..." print each argument plain.
+ */
+ void
+ex_echo(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+ var retvar;
+ char_u *p;
+ int needclr = TRUE;
+ int atstart = TRUE;
+
+ if (eap->skip)
+ ++emsg_skip;
+ while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
+ {
+ p = arg;
+ if (eval1(&arg, &retvar, !eap->skip) == FAIL)
+ {
+ /*
+ * Report the invalid expression unless the expression evaluation
+ * has been cancelled due to an aborting error, an interrupt, or an
+ * exception.
+ */
+ if (!aborting())
+ EMSG2(_(e_invexpr2), p);
+ break;
+ }
+ if (!eap->skip)
+ {
+ if (atstart)
+ {
+ atstart = FALSE;
+ /* Call msg_start() after eval1(), evaluating the expression
+ * may cause a message to appear. */
+ if (eap->cmdidx == CMD_echo)
+ msg_start();
+ }
+ else if (eap->cmdidx == CMD_echo)
+ msg_puts_attr((char_u *)" ", echo_attr);
+ for (p = get_var_string(&retvar); *p != NUL && !got_int; ++p)
+ if (*p == '\n' || *p == '\r' || *p == TAB)
+ {
+ if (*p != TAB && needclr)
+ {
+ /* remove any text still there from the command */
+ msg_clr_eos();
+ needclr = FALSE;
+ }
+ msg_putchar_attr(*p, echo_attr);
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int i = (*mb_ptr2len_check)(p);
+
+ (void)msg_outtrans_len_attr(p, i, echo_attr);
+ p += i - 1;
+ }
+ else
+#endif
+ (void)msg_outtrans_len_attr(p, 1, echo_attr);
+ }
+ }
+ clear_var(&retvar);
+ arg = skipwhite(arg);
+ }
+ eap->nextcmd = check_nextcmd(arg);
+
+ if (eap->skip)
+ --emsg_skip;
+ else
+ {
+ /* remove text that may still be there from the command */
+ if (needclr)
+ msg_clr_eos();
+ if (eap->cmdidx == CMD_echo)
+ msg_end();
+ }
+}
+
+/*
+ * ":echohl {name}".
+ */
+ void
+ex_echohl(eap)
+ exarg_T *eap;
+{
+ int id;
+
+ id = syn_name2id(eap->arg);
+ if (id == 0)
+ echo_attr = 0;
+ else
+ echo_attr = syn_id2attr(id);
+}
+
+/*
+ * ":execute expr1 ..." execute the result of an expression.
+ * ":echomsg expr1 ..." Print a message
+ * ":echoerr expr1 ..." Print an error
+ * Each gets spaces around each argument and a newline at the end for
+ * echo commands
+ */
+ void
+ex_execute(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+ var retvar;
+ int ret = OK;
+ char_u *p;
+ garray_T ga;
+ int len;
+ int save_did_emsg;
+
+ ga_init2(&ga, 1, 80);
+
+ if (eap->skip)
+ ++emsg_skip;
+ while (*arg != NUL && *arg != '|' && *arg != '\n')
+ {
+ p = arg;
+ if (eval1(&arg, &retvar, !eap->skip) == FAIL)
+ {
+ /*
+ * Report the invalid expression unless the expression evaluation
+ * has been cancelled due to an aborting error, an interrupt, or an
+ * exception.
+ */
+ if (!aborting())
+ EMSG2(_(e_invexpr2), p);
+ ret = FAIL;
+ break;
+ }
+
+ if (!eap->skip)
+ {
+ p = get_var_string(&retvar);
+ len = (int)STRLEN(p);
+ if (ga_grow(&ga, len + 2) == FAIL)
+ {
+ clear_var(&retvar);
+ ret = FAIL;
+ break;
+ }
+ if (ga.ga_len)
+ {
+ ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
+ --ga.ga_room;
+ }
+ STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
+ ga.ga_room -= len;
+ ga.ga_len += len;
+ }
+
+ clear_var(&retvar);
+ arg = skipwhite(arg);
+ }
+
+ if (ret != FAIL && ga.ga_data != NULL)
+ {
+ if (eap->cmdidx == CMD_echomsg)
+ MSG_ATTR(ga.ga_data, echo_attr);
+ else if (eap->cmdidx == CMD_echoerr)
+ {
+ /* We don't want to abort following commands, restore did_emsg. */
+ save_did_emsg = did_emsg;
+ EMSG((char_u *)ga.ga_data);
+ if (!force_abort)
+ did_emsg = save_did_emsg;
+ }
+ else if (eap->cmdidx == CMD_execute)
+ do_cmdline((char_u *)ga.ga_data,
+ eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
+ }
+
+ ga_clear(&ga);
+
+ if (eap->skip)
+ --emsg_skip;
+
+ eap->nextcmd = check_nextcmd(arg);
+}
+
+/*
+ * Skip over the name of an option: "&option", "&g:option" or "&l:option".
+ * "arg" points to the "&" or '+' when called, to "option" when returning.
+ * Returns NULL when no option name found. Otherwise pointer to the char
+ * after the option name.
+ */
+ static char_u *
+find_option_end(arg, opt_flags)
+ char_u **arg;
+ int *opt_flags;
+{
+ char_u *p = *arg;
+
+ ++p;
+ if (*p == 'g' && p[1] == ':')
+ {
+ *opt_flags = OPT_GLOBAL;
+ p += 2;
+ }
+ else if (*p == 'l' && p[1] == ':')
+ {
+ *opt_flags = OPT_LOCAL;
+ p += 2;
+ }
+ else
+ *opt_flags = 0;
+
+ if (!ASCII_ISALPHA(*p))
+ return NULL;
+ *arg = p;
+
+ if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
+ p += 4; /* termcap option */
+ else
+ while (ASCII_ISALPHA(*p))
+ ++p;
+ return p;
+}
+
+/*
+ * ":function"
+ */
+ void
+ex_function(eap)
+ exarg_T *eap;
+{
+ char_u *theline;
+ int j;
+ int c;
+#ifdef FEAT_MAGIC_BRACES
+ int saved_did_emsg;
+#endif
+ char_u *name = NULL;
+ char_u *p;
+ char_u *arg;
+ garray_T newargs;
+ garray_T newlines;
+ int varargs = FALSE;
+ int mustend = FALSE;
+ int flags = 0;
+ ufunc_T *fp;
+ int indent;
+ int nesting;
+ char_u *skip_until = NULL;
+ static char_u e_funcexts[] = N_("E122: Function %s already exists, add ! to replace it");
+
+ /*
+ * ":function" without argument: list functions.
+ */
+ if (ends_excmd(*eap->arg))
+ {
+ if (!eap->skip)
+ for (fp = firstfunc; fp != NULL && !got_int; fp = fp->next)
+ list_func_head(fp, FALSE);
+ eap->nextcmd = check_nextcmd(eap->arg);
+ return;
+ }
+
+ p = eap->arg;
+ name = trans_function_name(&p, eap->skip, FALSE);
+ if (name == NULL && !eap->skip)
+ {
+ /*
+ * Return on an invalid expression in braces, unless the expression
+ * evaluation has been cancelled due to an aborting error, an
+ * interrupt, or an exception.
+ */
+ if (!aborting())
+ return;
+ else
+ eap->skip = TRUE;
+ }
+#ifdef FEAT_MAGIC_BRACES
+ /* An error in a function call during evaluation of an expression in magic
+ * braces should not cause the function not to be defined. */
+ saved_did_emsg = did_emsg;
+ did_emsg = FALSE;
+#endif
+
+ /*
+ * ":function func" with only function name: list function.
+ */
+ if (vim_strchr(p, '(') == NULL)
+ {
+ if (!ends_excmd(*skipwhite(p)))
+ {
+ EMSG(_(e_trailing));
+ goto erret_name;
+ }
+ eap->nextcmd = check_nextcmd(p);
+ if (eap->nextcmd != NULL)
+ *p = NUL;
+ if (!eap->skip && !got_int)
+ {
+ fp = find_func(name);
+ if (fp != NULL)
+ {
+ list_func_head(fp, TRUE);
+ for (j = 0; j < fp->lines.ga_len && !got_int; ++j)
+ {
+ msg_putchar('\n');
+ msg_outnum((long)(j + 1));
+ if (j < 9)
+ msg_putchar(' ');
+ if (j < 99)
+ msg_putchar(' ');
+ msg_prt_line(FUNCLINE(fp, j));
+ out_flush(); /* show a line at a time */
+ ui_breakcheck();
+ }
+ if (!got_int)
+ {
+ msg_putchar('\n');
+ msg_puts((char_u *)" endfunction");
+ }
+ }
+ else
+ EMSG2(_("E123: Undefined function: %s"), eap->arg);
+ }
+ goto erret_name;
+ }
+
+ /*
+ * ":function name(arg1, arg2)" Define function.
+ */
+ p = skipwhite(p);
+ if (*p != '(')
+ {
+ if (!eap->skip)
+ {
+ EMSG2(_("E124: Missing '(': %s"), eap->arg);
+ goto erret_name;
+ }
+ /* attempt to continue by skipping some text */
+ if (vim_strchr(p, '(') != NULL)
+ p = vim_strchr(p, '(');
+ }
+ p = skipwhite(p + 1);
+
+ ga_init2(&newargs, (int)sizeof(char_u *), 3);
+ ga_init2(&newlines, (int)sizeof(char_u *), 3);
+
+ /*
+ * Isolate the arguments: "arg1, arg2, ...)"
+ */
+ while (*p != ')')
+ {
+ if (p[0] == '.' && p[1] == '.' && p[2] == '.')
+ {
+ varargs = TRUE;
+ p += 3;
+ mustend = TRUE;
+ }
+ else
+ {
+ arg = p;
+ while (ASCII_ISALNUM(*p) || *p == '_')
+ ++p;
+ if (arg == p || isdigit(*arg)
+ || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
+ || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
+ {
+ if (!eap->skip)
+ EMSG2(_("E125: Illegal argument: %s"), arg);
+ break;
+ }
+ if (ga_grow(&newargs, 1) == FAIL)
+ goto erret;
+ c = *p;
+ *p = NUL;
+ arg = vim_strsave(arg);
+ if (arg == NULL)
+ goto erret;
+ ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
+ *p = c;
+ newargs.ga_len++;
+ newargs.ga_room--;
+ if (*p == ',')
+ ++p;
+ else
+ mustend = TRUE;
+ }
+ p = skipwhite(p);
+ if (mustend && *p != ')')
+ {
+ if (!eap->skip)
+ EMSG2(_(e_invarg2), eap->arg);
+ break;
+ }
+ }
+ ++p; /* skip the ')' */
+
+ /* find extra arguments "range" and "abort" */
+ for (;;)
+ {
+ p = skipwhite(p);
+ if (STRNCMP(p, "range", 5) == 0)
+ {
+ flags |= FC_RANGE;
+ p += 5;
+ }
+ else if (STRNCMP(p, "abort", 5) == 0)
+ {
+ flags |= FC_ABORT;
+ p += 5;
+ }
+ else
+ break;
+ }
+
+ if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg)
+ EMSG(_(e_trailing));
+
+ /*
+ * Read the body of the function, until ":endfunction" is found.
+ */
+ if (KeyTyped)
+ {
+ /* Check if the function already exists, don't let the user type the
+ * whole function before telling him it doesn't work! For a script we
+ * need to skip the body to be able to find what follows. */
+ if (!eap->skip && !eap->forceit && find_func(name) != NULL)
+ EMSG2(_(e_funcexts), name);
+
+ msg_putchar('\n'); /* don't overwrite the function name */
+ cmdline_row = msg_row;
+ }
+
+ indent = 2;
+ nesting = 0;
+ for (;;)
+ {
+ msg_scroll = TRUE;
+ need_wait_return = FALSE;
+ if (eap->getline == NULL)
+ theline = getcmdline(':', 0L, indent);
+ else
+ theline = eap->getline(':', eap->cookie, indent);
+ if (KeyTyped)
+ lines_left = Rows - 1;
+ if (theline == NULL)
+ {
+ EMSG(_("E126: Missing :endfunction"));
+ goto erret;
+ }
+
+ if (skip_until != NULL)
+ {
+ /* between ":append" and "." and between ":python <<EOF" and "EOF"
+ * don't check for ":endfunc". */
+ if (STRCMP(theline, skip_until) == 0)
+ {
+ vim_free(skip_until);
+ skip_until = NULL;
+ }
+ }
+ else
+ {
+ /* skip ':' and blanks*/
+ for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
+ ;
+
+ /* Check for "endfunction" (should be more strict...). */
+ if (STRNCMP(p, "endf", 4) == 0 && nesting-- == 0)
+ {
+ vim_free(theline);
+ break;
+ }
+
+ /* Increase indent inside "if", "while", and "try", decrease
+ * at "end". */
+ if (indent > 2 && STRNCMP(p, "end", 3) == 0)
+ indent -= 2;
+ else if (STRNCMP(p, "if", 2) == 0 || STRNCMP(p, "wh", 2) == 0
+ || STRNCMP(p, "try", 3) == 0)
+ indent += 2;
+
+ /* Check for defining a function inside this function. */
+ if (STRNCMP(p, "fu", 2) == 0)
+ {
+ p = skipwhite(skiptowhite(p));
+ p += eval_fname_script(p);
+ if (ASCII_ISALPHA(*p))
+ {
+ vim_free(trans_function_name(&p, TRUE, FALSE));
+ if (*skipwhite(p) == '(')
+ {
+ ++nesting;
+ indent += 2;
+ }
+ }
+ }
+
+ /* Check for ":append" or ":insert". */
+ p = skip_range(p, NULL);
+ if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
+ || (p[0] == 'i'
+ && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
+ && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
+ skip_until = vim_strsave((char_u *)".");
+
+ /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
+ arg = skipwhite(skiptowhite(p));
+ if (arg[0] == '<' && arg[1] =='<'
+ && ((p[0] == 'p' && p[1] == 'y'
+ && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
+ || (p[0] == 'p' && p[1] == 'e'
+ && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
+ || (p[0] == 't' && p[1] == 'c'
+ && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
+ || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
+ && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
+ ))
+ {
+ /* ":python <<" continues until a dot, like ":append" */
+ p = skipwhite(arg + 2);
+ if (*p == NUL)
+ skip_until = vim_strsave((char_u *)".");
+ else
+ skip_until = vim_strsave(p);
+ }
+ }
+
+ /* Add the line to the function. */
+ if (ga_grow(&newlines, 1) == FAIL)
+ goto erret;
+ ((char_u **)(newlines.ga_data))[newlines.ga_len] = theline;
+ newlines.ga_len++;
+ newlines.ga_room--;
+ }
+
+ /* Don't define the function when skipping commands or when an error was
+ * detected. */
+ if (eap->skip || did_emsg)
+ goto erret;
+
+ /*
+ * If there are no errors, add the function
+ */
+ fp = find_func(name);
+ if (fp != NULL)
+ {
+ if (!eap->forceit)
+ {
+ EMSG2(_(e_funcexts), name);
+ goto erret;
+ }
+ if (fp->calls)
+ {
+ EMSG2(_("E127: Cannot redefine function %s: It is in use"), name);
+ goto erret;
+ }
+ /* redefine existing function */
+ ga_clear_strings(&(fp->args));
+ ga_clear_strings(&(fp->lines));
+ vim_free(name);
+ }
+ else
+ {
+ fp = (ufunc_T *)alloc((unsigned)sizeof(ufunc_T));
+ if (fp == NULL)
+ goto erret;
+ /* insert the new function in the function list */
+ fp->next = firstfunc;
+ firstfunc = fp;
+ fp->name = name;
+ }
+ fp->args = newargs;
+ fp->lines = newlines;
+ fp->varargs = varargs;
+ fp->flags = flags;
+ fp->calls = 0;
+ fp->script_ID = current_SID;
+#ifdef FEAT_MAGIC_BRACES
+ did_emsg |= saved_did_emsg;
+#endif
+ vim_free(skip_until);
+ return;
+
+erret:
+ vim_free(skip_until);
+ ga_clear_strings(&newargs);
+ ga_clear_strings(&newlines);
+erret_name:
+ vim_free(name);
+#ifdef FEAT_MAGIC_BRACES
+ did_emsg |= saved_did_emsg;
+#endif
+}
+
+/*
+ * Get a function name, translating "<SID>" and "<SNR>".
+ * Returns the function name in allocated memory, or NULL for failure.
+ * Advances "pp" to just after the function name (if no error).
+ */
+ static char_u *
+trans_function_name(pp, skip, internal)
+ char_u **pp;
+ int skip; /* only find the end, don't evaluate */
+ int internal; /* TRUE if internal function name OK */
+{
+ char_u *name;
+ char_u *start;
+ char_u *end;
+ int lead;
+ char_u sid_buf[20];
+ char_u *temp_string = NULL;
+ char_u *expr_start, *expr_end;
+ int len;
+
+ /* A name starting with "<SID>" or "<SNR>" is local to a script. */
+ start = *pp;
+ lead = eval_fname_script(start);
+ if (lead > 0)
+ start += lead;
+ end = find_name_end(start, &expr_start, &expr_end);
+ if (end == start)
+ {
+ if (!skip)
+ EMSG(_("E129: Function name required"));
+ return NULL;
+ }
+#ifdef FEAT_MAGIC_BRACES
+ if (expr_start != NULL && !skip)
+ {
+ /* expand magic curlies */
+ temp_string = make_expanded_name(start, expr_start, expr_end, end);
+ if (temp_string == NULL)
+ {
+ /*
+ * Report an invalid expression in braces, unless the expression
+ * evaluation has been cancelled due to an aborting error, an
+ * interrupt, or an exception.
+ */
+ if (!aborting())
+ EMSG2(_(e_invarg2), start);
+ else
+ *pp = end;
+ return NULL;
+ }
+ start = temp_string;
+ len = (int)STRLEN(temp_string);
+ }
+ else
+#endif
+ len = (int)(end - start);
+
+ /*
+ * Copy the function name to allocated memory.
+ * Accept <SID>name() inside a script, translate into <SNR>123_name().
+ * Accept <SNR>123_name() outside a script.
+ */
+ if (skip)
+ lead = 0; /* do nothing */
+ else if (lead > 0)
+ {
+ lead = 3;
+ if (eval_fname_sid(*pp)) /* If it's "<SID>" */
+ {
+ if (current_SID <= 0)
+ {
+ EMSG(_(e_usingsid));
+ return NULL;
+ }
+ sprintf((char *)sid_buf, "%ld_", (long)current_SID);
+ lead += (int)STRLEN(sid_buf);
+ }
+ }
+ else if (!internal && !ASCII_ISUPPER(*start))
+ {
+ EMSG2(_("E128: Function name must start with a capital: %s"), start);
+ return NULL;
+ }
+ name = alloc((unsigned)(len + lead + 1));
+ if (name != NULL)
+ {
+ if (lead > 0)
+ {
+ name[0] = K_SPECIAL;
+ name[1] = KS_EXTRA;
+ name[2] = (int)KE_SNR;
+ if (eval_fname_sid(*pp)) /* If it's "<SID>" */
+ STRCPY(name + 3, sid_buf);
+ }
+ mch_memmove(name + lead, start, (size_t)len);
+ name[len + lead] = NUL;
+ }
+ *pp = end;
+
+ vim_free(temp_string);
+ return name;
+}
+
+/*
+ * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
+ * Return 2 if "p" starts with "s:".
+ * Return 0 otherwise.
+ */
+ static int
+eval_fname_script(p)
+ char_u *p;
+{
+ if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
+ || STRNICMP(p + 1, "SNR>", 4) == 0))
+ return 5;
+ if (p[0] == 's' && p[1] == ':')
+ return 2;
+ return 0;
+}
+
+/*
+ * Return TRUE if "p" starts with "<SID>" or "s:".
+ * Only works if eval_fname_script() returned non-zero for "p"!
+ */
+ static int
+eval_fname_sid(p)
+ char_u *p;
+{
+ return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
+}
+
+/*
+ * List the head of the function: "name(arg1, arg2)".
+ */
+ static void
+list_func_head(fp, indent)
+ ufunc_T *fp;
+ int indent;
+{
+ int j;
+
+ msg_start();
+ if (indent)
+ MSG_PUTS(" ");
+ MSG_PUTS("function ");
+ if (fp->name[0] == K_SPECIAL)
+ {
+ MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
+ msg_puts(fp->name + 3);
+ }
+ else
+ msg_puts(fp->name);
+ msg_putchar('(');
+ for (j = 0; j < fp->args.ga_len; ++j)
+ {
+ if (j)
+ MSG_PUTS(", ");
+ msg_puts(FUNCARG(fp, j));
+ }
+ if (fp->varargs)
+ {
+ if (j)
+ MSG_PUTS(", ");
+ MSG_PUTS("...");
+ }
+ msg_putchar(')');
+}
+
+/*
+ * Find a function by name, return pointer to it in ufuncs.
+ * Return NULL for unknown function.
+ */
+ static ufunc_T *
+find_func(name)
+ char_u *name;
+{
+ ufunc_T *fp;
+
+ for (fp = firstfunc; fp != NULL; fp = fp->next)
+ if (STRCMP(name, fp->name) == 0)
+ break;
+ return fp;
+}
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+
+/*
+ * Function given to ExpandGeneric() to obtain the list of user defined
+ * function names.
+ */
+ char_u *
+get_user_func_name(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ static ufunc_T *fp = NULL;
+
+ if (idx == 0)
+ fp = firstfunc;
+ if (fp != NULL)
+ {
+ if (STRLEN(fp->name) + 4 >= IOSIZE)
+ return fp->name; /* prevents overflow */
+
+ cat_func_name(IObuff, fp);
+ if (xp->xp_context != EXPAND_USER_FUNC)
+ {
+ STRCAT(IObuff, "(");
+ if (!fp->varargs && fp->args.ga_len == 0)
+ STRCAT(IObuff, ")");
+ }
+
+ fp = fp->next;
+ return IObuff;
+ }
+ return NULL;
+}
+
+#endif /* FEAT_CMDL_COMPL */
+
+/*
+ * Copy the function name of "fp" to buffer "buf".
+ * "buf" must be able to hold the function name plus three bytes.
+ * Takes care of script-local function names.
+ */
+ static void
+cat_func_name(buf, fp)
+ char_u *buf;
+ ufunc_T *fp;
+{
+ if (fp->name[0] == K_SPECIAL)
+ {
+ STRCPY(buf, "<SNR>");
+ STRCAT(buf, fp->name + 3);
+ }
+ else
+ STRCPY(buf, fp->name);
+}
+
+/*
+ * ":delfunction {name}"
+ */
+ void
+ex_delfunction(eap)
+ exarg_T *eap;
+{
+ ufunc_T *fp = NULL, *pfp;
+ char_u *p;
+ char_u *name;
+
+ p = eap->arg;
+ name = trans_function_name(&p, eap->skip, FALSE);
+ if (name == NULL)
+ return;
+ if (!ends_excmd(*skipwhite(p)))
+ {
+ vim_free(name);
+ EMSG(_(e_trailing));
+ return;
+ }
+ eap->nextcmd = check_nextcmd(p);
+ if (eap->nextcmd != NULL)
+ *p = NUL;
+
+ if (!eap->skip)
+ fp = find_func(name);
+ vim_free(name);
+
+ if (!eap->skip)
+ {
+ if (fp == NULL)
+ {
+ EMSG2(_("E130: Undefined function: %s"), eap->arg);
+ return;
+ }
+ if (fp->calls)
+ {
+ EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
+ return;
+ }
+
+ /* clear this function */
+ vim_free(fp->name);
+ ga_clear_strings(&(fp->args));
+ ga_clear_strings(&(fp->lines));
+
+ /* remove the function from the function list */
+ if (firstfunc == fp)
+ firstfunc = fp->next;
+ else
+ {
+ for (pfp = firstfunc; pfp != NULL; pfp = pfp->next)
+ if (pfp->next == fp)
+ {
+ pfp->next = fp->next;
+ break;
+ }
+ }
+ vim_free(fp);
+ }
+}
+
+/*
+ * Call a user function.
+ */
+ static void
+call_user_func(fp, argcount, argvars, retvar, firstline, lastline)
+ ufunc_T *fp; /* pointer to function */
+ int argcount; /* nr of args */
+ VAR argvars; /* arguments */
+ VAR retvar; /* return value */
+ linenr_T firstline; /* first line of range */
+ linenr_T lastline; /* last line of range */
+{
+ char_u *save_sourcing_name;
+ linenr_T save_sourcing_lnum;
+ scid_T save_current_SID;
+ struct funccall fc;
+ struct funccall *save_fcp = current_funccal;
+ int save_did_emsg;
+ static int depth = 0;
+
+ /* If depth of calling is getting too high, don't execute the function */
+ if (depth >= p_mfd)
+ {
+ EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
+ retvar->var_type = VAR_NUMBER;
+ retvar->var_val.var_number = -1;
+ return;
+ }
+ ++depth;
+
+ line_breakcheck(); /* check for CTRL-C hit */
+
+ /* set local variables */
+ var_init(&fc.l_vars);
+ fc.func = fp;
+ fc.argcount = argcount;
+ fc.argvars = argvars;
+ fc.retvar = retvar;
+ retvar->var_val.var_number = 0;
+ fc.linenr = 0;
+ fc.returned = FALSE;
+ fc.level = ex_nesting_level;
+ fc.a0_var.var_type = VAR_NUMBER;
+ fc.a0_var.var_val.var_number = argcount - fp->args.ga_len;
+ fc.a0_var.var_name = NULL;
+ current_funccal = &fc;
+ fc.firstline.var_type = VAR_NUMBER;
+ fc.firstline.var_val.var_number = firstline;
+ fc.firstline.var_name = NULL;
+ fc.lastline.var_type = VAR_NUMBER;
+ fc.lastline.var_val.var_number = lastline;
+ fc.lastline.var_name = NULL;
+ /* Check if this function has a breakpoint. */
+ fc.breakpoint = dbg_find_breakpoint(FALSE, fp->name, (linenr_T)0);
+ fc.dbg_tick = debug_tick;
+
+ /* Don't redraw while executing the function. */
+ ++RedrawingDisabled;
+ save_sourcing_name = sourcing_name;
+ save_sourcing_lnum = sourcing_lnum;
+ sourcing_lnum = 1;
+ sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
+ : STRLEN(save_sourcing_name)) + STRLEN(fp->name) + 13));
+ if (sourcing_name != NULL)
+ {
+ if (save_sourcing_name != NULL
+ && STRNCMP(save_sourcing_name, "function ", 9) == 0)
+ sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
+ else
+ STRCPY(sourcing_name, "function ");
+ cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
+
+ if (p_verbose >= 12)
+ {
+ ++no_wait_return;
+ msg_scroll = TRUE; /* always scroll up, don't overwrite */
+ msg_str((char_u *)_("calling %s"), sourcing_name);
+ if (p_verbose >= 14)
+ {
+ int i;
+ char_u buf[MSG_BUF_LEN];
+
+ msg_puts((char_u *)"(");
+ for (i = 0; i < argcount; ++i)
+ {
+ if (i > 0)
+ msg_puts((char_u *)", ");
+ if (argvars[i].var_type == VAR_NUMBER)
+ msg_outnum((long)argvars[i].var_val.var_number);
+ else
+ {
+ trunc_string(get_var_string(&argvars[i]),
+ buf, MSG_BUF_LEN);
+ msg_puts((char_u *)"\"");
+ msg_puts(buf);
+ msg_puts((char_u *)"\"");
+ }
+ }
+ msg_puts((char_u *)")");
+ }
+ msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ cmdline_row = msg_row;
+ --no_wait_return;
+ }
+ }
+ save_current_SID = current_SID;
+ current_SID = fp->script_ID;
+ save_did_emsg = did_emsg;
+ did_emsg = FALSE;
+
+ /* call do_cmdline() to execute the lines */
+ do_cmdline(NULL, get_func_line, (void *)&fc,
+ DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
+
+ --RedrawingDisabled;
+
+ /* when the function was aborted because of an error, return -1 */
+ if ((did_emsg && (fp->flags & FC_ABORT)) || retvar->var_type == VAR_UNKNOWN)
+ {
+ clear_var(retvar);
+ retvar->var_type = VAR_NUMBER;
+ retvar->var_val.var_number = -1;
+ }
+
+ /* when being verbose, mention the return value */
+ if (p_verbose >= 12)
+ {
+ char_u *sn, *val;
+
+ ++no_wait_return;
+ msg_scroll = TRUE; /* always scroll up, don't overwrite */
+
+ /* Make sure the output fits in IObuff. */
+ sn = sourcing_name;
+ if (STRLEN(sourcing_name) > IOSIZE / 2 - 50)
+ sn = sourcing_name + STRLEN(sourcing_name) - (IOSIZE / 2 - 50);
+
+ if (aborting())
+ smsg((char_u *)_("%s aborted"), sn);
+ else if (fc.retvar->var_type == VAR_NUMBER)
+ smsg((char_u *)_("%s returning #%ld"), sn,
+ (long)fc.retvar->var_val.var_number);
+ else if (fc.retvar->var_type == VAR_STRING)
+ {
+ val = get_var_string(fc.retvar);
+ if (STRLEN(val) > IOSIZE / 2 - 50)
+ val = val + STRLEN(val) - (IOSIZE / 2 - 50);
+ smsg((char_u *)_("%s returning \"%s\""), sn, val);
+ }
+ msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ cmdline_row = msg_row;
+ --no_wait_return;
+ }
+
+ vim_free(sourcing_name);
+ sourcing_name = save_sourcing_name;
+ sourcing_lnum = save_sourcing_lnum;
+ current_SID = save_current_SID;
+
+ if (p_verbose >= 12 && sourcing_name != NULL)
+ {
+ ++no_wait_return;
+ msg_scroll = TRUE; /* always scroll up, don't overwrite */
+ msg_str((char_u *)_("continuing in %s"), sourcing_name);
+ msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ cmdline_row = msg_row;
+ --no_wait_return;
+ }
+
+ did_emsg |= save_did_emsg;
+ current_funccal = save_fcp;
+
+ var_clear(&fc.l_vars); /* free all local variables */
+ --depth;
+}
+
+/*
+ * ":return [expr]"
+ */
+ void
+ex_return(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+ var retvar;
+ int returning = FALSE;
+
+ if (current_funccal == NULL)
+ {
+ EMSG(_("E133: :return not inside a function"));
+ return;
+ }
+
+ if (eap->skip)
+ ++emsg_skip;
+
+ eap->nextcmd = NULL;
+ if ((*arg != NUL && *arg != '|' && *arg != '\n')
+ && eval0(arg, &retvar, &eap->nextcmd, !eap->skip) != FAIL)
+ {
+ if (!eap->skip)
+ returning = do_return(eap, FALSE, TRUE, &retvar);
+ else
+ clear_var(&retvar);
+ }
+ /* It's safer to return also on error. */
+ else if (!eap->skip)
+ {
+ /*
+ * Return unless the expression evaluation has been cancelled due to an
+ * aborting error, an interrupt, or an exception.
+ */
+ if (!aborting())
+ returning = do_return(eap, FALSE, TRUE, NULL);
+ }
+
+ /* When skipping or the return gets pending, advance to the next command
+ * in this line (!returning). Otherwise, ignore the rest of the line.
+ * Following lines will be ignored by get_func_line(). */
+ if (returning)
+ eap->nextcmd = NULL;
+ else if (eap->nextcmd == NULL) /* no argument */
+ eap->nextcmd = check_nextcmd(arg);
+
+ if (eap->skip)
+ --emsg_skip;
+}
+
+/*
+ * Return from a function. Possibly makes the return pending. Also called
+ * for a pending return at the ":endtry" or after returning from an extra
+ * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
+ * when called due to a ":return" command. "value" may point to a variable
+ * with the return value. Returns TRUE when the return can be carried out,
+ * FALSE when the return gets pending.
+ */
+ int
+do_return(eap, reanimate, is_cmd, value)
+ exarg_T *eap;
+ int reanimate;
+ int is_cmd;
+ void *value;
+{
+ int idx;
+ struct condstack *cstack = eap->cstack;
+
+ if (reanimate)
+ /* Undo the return. */
+ current_funccal->returned = FALSE;
+
+ /*
+ * Cleanup (and inactivate) conditionals, but stop when a try conditional
+ * not in its finally clause (which then is to be executed next) is found.
+ * In this case, make the ":return" pending for execution at the ":endtry".
+ * Otherwise, return normally.
+ */
+ idx = cleanup_conditionals(eap->cstack, 0, TRUE);
+ if (idx >= 0)
+ {
+ cstack->cs_pending[idx] = CSTP_RETURN;
+
+ if (!is_cmd && !reanimate)
+ /* A pending return again gets pending. "value" points to an
+ * allocated variable with the value of the original ":return"'s
+ * argument if present or is NULL else. */
+ cstack->cs_retvar[idx] = value;
+ else
+ {
+ /* When undoing a return in order to make it pending, get the stored
+ * return value. */
+ if (reanimate)
+ value = current_funccal->retvar;
+
+ if (value != NULL)
+ {
+ /* Store the value of the pending return. */
+ if ((cstack->cs_retvar[idx] = alloc_var()) != NULL)
+ *(VAR)cstack->cs_retvar[idx] = *(VAR)value;
+ else
+ EMSG(_(e_outofmem));
+ }
+ else
+ cstack->cs_retvar[idx] = NULL;
+
+ if (reanimate)
+ {
+ /* The pending return value could be overwritten by a ":return"
+ * without argument in a finally clause; reset the default
+ * return value. */
+ current_funccal->retvar->var_type = VAR_NUMBER;
+ current_funccal->retvar->var_val.var_number = 0;
+ }
+ }
+ report_make_pending(CSTP_RETURN, value);
+ }
+ else
+ {
+ current_funccal->returned = TRUE;
+
+ /* If the return is carried out now, store the return value. For
+ * a return immediately after reanimation, the value is already
+ * there. */
+ if (!reanimate && value != NULL)
+ {
+ clear_var(current_funccal->retvar);
+ *current_funccal->retvar = *(VAR)value;
+ if (!is_cmd)
+ vim_free(value);
+ }
+ }
+
+ return idx < 0;
+}
+
+/*
+ * Free the variable with a pending return value.
+ */
+ void
+discard_pending_return(retvar)
+ void *retvar;
+{
+ /* The variable was copied from one with an undefined var_name. So we can't
+ * use free_var() to clear and free it. */
+ clear_var((VAR)retvar);
+ vim_free(retvar);
+}
+
+/*
+ * Generate a return command for producing the value of "retvar". The result
+ * is an allocated string. Used by report_pending() for verbose messages.
+ */
+ char_u *
+get_return_cmd(retvar)
+ void *retvar;
+{
+ char_u *s = IObuff;
+
+ if (retvar == NULL || ((VAR)retvar)->var_type == VAR_UNKNOWN)
+ s = (char_u *)":return";
+ else if (((VAR)retvar)->var_type == VAR_STRING)
+ sprintf((char *)IObuff, ":return \"%s\"",
+ ((VAR)retvar)->var_val.var_string);
+ else
+ sprintf((char *)IObuff, ":return %ld",
+ (long)(((VAR)retvar)->var_val.var_number));
+ return vim_strsave(s);
+}
+
+/*
+ * Get next function line.
+ * Called by do_cmdline() to get the next line.
+ * Returns allocated string, or NULL for end of function.
+ */
+/* ARGSUSED */
+ char_u *
+get_func_line(c, cookie, indent)
+ int c; /* not used */
+ void *cookie;
+ int indent; /* not used */
+{
+ struct funccall *fcp = (struct funccall *)cookie;
+ char_u *retval;
+ garray_T *gap; /* growarray with function lines */
+
+ /* If breakpoints have been added/deleted need to check for it. */
+ if (fcp->dbg_tick != debug_tick)
+ {
+ fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
+ sourcing_lnum);
+ fcp->dbg_tick = debug_tick;
+ }
+
+ gap = &fcp->func->lines;
+ if ((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
+ retval = NULL;
+ else if (fcp->returned || fcp->linenr >= gap->ga_len)
+ retval = NULL;
+ else
+ {
+ retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
+ sourcing_lnum = fcp->linenr;
+ }
+
+ /* Did we encounter a breakpoint? */
+ if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
+ {
+ dbg_breakpoint(fcp->func->name, sourcing_lnum);
+ /* Find next breakpoint. */
+ fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
+ sourcing_lnum);
+ fcp->dbg_tick = debug_tick;
+ }
+
+ return retval;
+}
+
+/*
+ * Return TRUE if the currently active function should be ended, because a
+ * return was encountered or an error occured. Used inside a ":while".
+ */
+ int
+func_has_ended(cookie)
+ void *cookie;
+{
+ struct funccall *fcp = (struct funccall *)cookie;
+
+ /* Ignore the "abort" flag if the abortion behavior has been changed due to
+ * an error inside a try conditional. */
+ return (((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
+ || fcp->returned);
+}
+
+/*
+ * return TRUE if cookie indicates a function which "abort"s on errors.
+ */
+ int
+func_has_abort(cookie)
+ void *cookie;
+{
+ return ((struct funccall *)cookie)->func->flags & FC_ABORT;
+}
+
+#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
+typedef enum
+{
+ VAR_FLAVOUR_DEFAULT,
+ VAR_FLAVOUR_SESSION,
+ VAR_FLAVOUR_VIMINFO
+} var_flavour_T;
+
+static var_flavour_T var_flavour __ARGS((char_u *varname));
+
+ static var_flavour_T
+var_flavour(varname)
+ char_u *varname;
+{
+ char_u *p = varname;
+
+ if (ASCII_ISUPPER(*p))
+ {
+ while (*(++p))
+ if (ASCII_ISLOWER(*p))
+ return VAR_FLAVOUR_SESSION;
+ return VAR_FLAVOUR_VIMINFO;
+ }
+ else
+ return VAR_FLAVOUR_DEFAULT;
+}
+#endif
+
+#if defined(FEAT_VIMINFO) || defined(PROTO)
+/*
+ * Restore global vars that start with a capital from the viminfo file
+ */
+ int
+read_viminfo_varlist(virp, writing)
+ vir_T *virp;
+ int writing;
+{
+ char_u *tab;
+ int is_string = FALSE;
+ VAR varp = NULL;
+ char_u *val;
+
+ if (!writing && (find_viminfo_parameter('!') != NULL))
+ {
+ tab = vim_strchr(virp->vir_line + 1, '\t');
+ if (tab != NULL)
+ {
+ *tab++ = '\0'; /* isolate the variable name */
+ if (*tab == 'S') /* string var */
+ is_string = TRUE;
+
+ tab = vim_strchr(tab, '\t');
+ if (tab != NULL)
+ {
+ /* create a nameless variable to hold the value */
+ if (is_string)
+ {
+ val = viminfo_readstring(virp,
+ (int)(tab - virp->vir_line + 1), TRUE);
+ if (val != NULL)
+ varp = alloc_string_var(val);
+ }
+ else
+ {
+ varp = alloc_var();
+ if (varp != NULL)
+ {
+ varp->var_type = VAR_NUMBER;
+ varp->var_val.var_number = atol((char *)tab + 1);
+ }
+ }
+ /* assign the value to the variable */
+ if (varp != NULL)
+ {
+ set_var(virp->vir_line + 1, varp);
+ free_var(varp);
+ }
+ }
+ }
+ }
+
+ return viminfo_readline(virp);
+}
+
+/*
+ * Write global vars that start with a capital to the viminfo file
+ */
+ void
+write_viminfo_varlist(fp)
+ FILE *fp;
+{
+ garray_T *gap = &variables; /* global variable */
+ VAR this_var;
+ int i;
+
+ if (find_viminfo_parameter('!') == NULL)
+ return;
+
+ fprintf(fp, _("\n# global variables:\n"));
+ for (i = gap->ga_len; --i >= 0; )
+ {
+ this_var = &VAR_GAP_ENTRY(i, gap);
+ if (this_var->var_name != NULL
+ && var_flavour(this_var->var_name) == VAR_FLAVOUR_VIMINFO)
+ {
+ fprintf(fp, "!%s\t%s\t", this_var->var_name,
+ (this_var->var_type == VAR_STRING) ? "STR" : "NUM");
+ viminfo_writestring(fp, get_var_string(this_var));
+ }
+ }
+}
+#endif
+
+#if defined(FEAT_SESSION) || defined(PROTO)
+ int
+store_session_globals(fd)
+ FILE *fd;
+{
+ garray_T *gap = &variables; /* global variable */
+ VAR this_var;
+ int i;
+ char_u *p, *t;
+
+ for (i = gap->ga_len; --i >= 0; )
+ {
+ this_var = &VAR_GAP_ENTRY(i, gap);
+ if (this_var->var_name != NULL)
+ {
+ if (var_flavour(this_var->var_name) == VAR_FLAVOUR_SESSION)
+ {
+ /* Escapse special characters with a backslash. Turn a LF and
+ * CR into \n and \r. */
+ p = vim_strsave_escaped(get_var_string(this_var),
+ (char_u *)"\\\"\n\r");
+ if (p == NULL) /* out of memory */
+ continue;
+ for (t = p; *t != NUL; ++t)
+ if (*t == '\n')
+ *t = 'n';
+ else if (*t == '\r')
+ *t = 'r';
+ if ((fprintf(fd, "let %s = %c%s%c",
+ this_var->var_name,
+ (this_var->var_type == VAR_STRING) ? '"' : ' ',
+ p,
+ (this_var->var_type == VAR_STRING) ? '"' : ' ') < 0)
+ || put_eol(fd) == FAIL)
+ {
+ vim_free(p);
+ return FAIL;
+ }
+ vim_free(p);
+ }
+
+ }
+ }
+ return OK;
+}
+#endif
+
+#endif /* FEAT_EVAL */
+
+#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
+
+
+#ifdef WIN3264
+/*
+ * Functions for ":8" filename modifier: get 8.3 version of a filename.
+ */
+static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
+static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
+static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
+
+/*
+ * Get the short pathname of a file.
+ * Returns 1 on success. *fnamelen is 0 for nonexistant path.
+ */
+ static int
+get_short_pathname(fnamep, bufp, fnamelen)
+ char_u **fnamep;
+ char_u **bufp;
+ int *fnamelen;
+{
+ int l,len;
+ char_u *newbuf;
+
+ len = *fnamelen;
+
+ l = GetShortPathName(*fnamep, *fnamep, len);
+ if (l > len - 1)
+ {
+ /* If that doesn't work (not enough space), then save the string
+ * and try again with a new buffer big enough
+ */
+ newbuf = vim_strnsave(*fnamep, l);
+ if (newbuf == NULL)
+ return 0;
+
+ vim_free(*bufp);
+ *fnamep = *bufp = newbuf;
+
+ l = GetShortPathName(*fnamep,*fnamep,l+1);
+
+ /* Really should always succeed, as the buffer is big enough */
+ }
+
+ *fnamelen = l;
+ return 1;
+}
+
+/*
+ * Create a short path name. Returns the length of the buffer it needs.
+ * Doesn't copy over the end of the buffer passed in.
+ */
+ static int
+shortpath_for_invalid_fname(fname, bufp, fnamelen)
+ char_u **fname;
+ char_u **bufp;
+ int *fnamelen;
+{
+ char_u *s, *p, *pbuf2, *pbuf3;
+ char_u ch;
+ int l,len,len2,plen,slen;
+
+ /* Make a copy */
+ len2 = *fnamelen;
+ pbuf2 = vim_strnsave(*fname, len2);
+ pbuf3 = NULL;
+
+ s = pbuf2 + len2 - 1; /* Find the end */
+ slen = 1;
+ plen = len2;
+
+ l = 0;
+ if (vim_ispathsep(*s))
+ {
+ --s;
+ ++slen;
+ --plen;
+ }
+
+ do
+ {
+ /* Go back one path-seperator */
+ while (s > pbuf2 && !vim_ispathsep(*s))
+ {
+ --s;
+ ++slen;
+ --plen;
+ }
+ if (s <= pbuf2)
+ break;
+
+ /* Remeber the character that is about to be blatted */
+ ch = *s;
+ *s = 0; /* get_short_pathname requires a null-terminated string */
+
+ /* Try it in situ */
+ p = pbuf2;
+ if (!get_short_pathname(&p, &pbuf3, &plen))
+ {
+ vim_free(pbuf2);
+ return -1;
+ }
+ *s = ch; /* Preserve the string */
+ } while (plen == 0);
+
+ if (plen > 0)
+ {
+ /* Remeber the length of the new string. */
+ *fnamelen = len = plen + slen;
+ vim_free(*bufp);
+ if (len > len2)
+ {
+ /* If there's not enough space in the currently allocated string,
+ * then copy it to a buffer big enough.
+ */
+ *fname= *bufp = vim_strnsave(p, len);
+ if (*fname == NULL)
+ return -1;
+ }
+ else
+ {
+ /* Transfer pbuf2 to being the main buffer (it's big enough) */
+ *fname = *bufp = pbuf2;
+ if (p != pbuf2)
+ strncpy(*fname, p, plen);
+ pbuf2 = NULL;
+ }
+ /* Concat the next bit */
+ strncpy(*fname + plen, s, slen);
+ (*fname)[len] = '\0';
+ }
+ vim_free(pbuf3);
+ vim_free(pbuf2);
+ return 0;
+}
+
+/*
+ * Get a pathname for a partial path.
+ */
+ static int
+shortpath_for_partial(fnamep, bufp, fnamelen)
+ char_u **fnamep;
+ char_u **bufp;
+ int *fnamelen;
+{
+ int sepcount, len, tflen;
+ char_u *p;
+ char_u *pbuf, *tfname;
+ int hasTilde;
+
+ /* Count up the path seperators from the RHS.. so we know which part
+ * of the path to return.
+ */
+ sepcount = 0;
+ for (p = *fnamep + *fnamelen - 1; p >= *fnamep; --p)
+ if (vim_ispathsep(*p))
+ ++sepcount;
+
+ /* Need full path first (use expand_env() to remove a "~/") */
+ hasTilde = (**fnamep == '~');
+ if (hasTilde)
+ pbuf = tfname = expand_env_save(*fnamep);
+ else
+ pbuf = tfname = FullName_save(*fnamep, FALSE);
+
+ len = tflen = STRLEN(tfname);
+
+ if (!get_short_pathname(&tfname, &pbuf, &len))
+ return -1;
+
+ if (len == 0)
+ {
+ /* Don't have a valid filename, so shorten the rest of the
+ * path if we can. This CAN give us invalid 8.3 filenames, but
+ * there's not a lot of point in guessing what it might be.
+ */
+ len = tflen;
+ if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
+ return -1;
+ }
+
+ /* Count the paths backward to find the beginning of the desired string. */
+ for (p = tfname + len - 1; p >= tfname; --p)
+ if (vim_ispathsep(*p))
+ {
+ if (sepcount == 0 || (hasTilde && sepcount == 1))
+ break;
+ else
+ sepcount --;
+ }
+ if (hasTilde)
+ {
+ --p;
+ if (p >= tfname)
+ *p = '~';
+ else
+ return -1;
+ }
+ else
+ ++p;
+
+ /* Copy in the string - p indexes into tfname - allocated at pbuf */
+ vim_free(*bufp);
+ *fnamelen = (int)STRLEN(p);
+ *bufp = pbuf;
+ *fnamep = p;
+
+ return 0;
+}
+#endif /* WIN3264 */
+
+/*
+ * Adjust a filename, according to a string of modifiers.
+ * *fnamep must be NUL terminated when called. When returning, the length is
+ * determined by *fnamelen.
+ * Returns valid flags.
+ * When there is an error, *fnamep is set to NULL.
+ */
+ int
+modify_fname(src, usedlen, fnamep, bufp, fnamelen)
+ char_u *src; /* string with modifiers */
+ int *usedlen; /* characters after src that are used */
+ char_u **fnamep; /* file name so far */
+ char_u **bufp; /* buffer for allocated file name or NULL */
+ int *fnamelen; /* length of fnamep */
+{
+ int valid = 0;
+ char_u *tail;
+ char_u *s, *p, *pbuf;
+ char_u dirname[MAXPATHL];
+ int c;
+ int has_fullname = 0;
+#ifdef WIN3264
+ int has_shortname = 0;
+#endif
+
+repeat:
+ /* ":p" - full path/file_name */
+ if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
+ {
+ has_fullname = 1;
+
+ valid |= VALID_PATH;
+ *usedlen += 2;
+
+ /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
+ if ((*fnamep)[0] == '~'
+#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
+ && ((*fnamep)[1] == '/'
+# ifdef BACKSLASH_IN_FILENAME
+ || (*fnamep)[1] == '\\'
+# endif
+ || (*fnamep)[1] == NUL)
+
+#endif
+ )
+ {
+ *fnamep = expand_env_save(*fnamep);
+ vim_free(*bufp); /* free any allocated file name */
+ *bufp = *fnamep;
+ if (*fnamep == NULL)
+ return -1;
+ }
+
+ /* When "/." or "/.." is used: force expansion to get rid of it. */
+ for (p = *fnamep; *p != NUL; ++p)
+ {
+ if (vim_ispathsep(*p)
+ && p[1] == '.'
+ && (p[2] == NUL
+ || vim_ispathsep(p[2])
+ || (p[2] == '.'
+ && (p[3] == NUL || vim_ispathsep(p[3])))))
+ break;
+ }
+
+ /* FullName_save() is slow, don't use it when not needed. */
+ if (*p != NUL || !vim_isAbsName(*fnamep))
+ {
+ *fnamep = FullName_save(*fnamep, *p != NUL);
+ vim_free(*bufp); /* free any allocated file name */
+ *bufp = *fnamep;
+ if (*fnamep == NULL)
+ return -1;
+ }
+
+ /* Append a path separator to a directory. */
+ if (mch_isdir(*fnamep))
+ {
+ /* Make room for one or two extra characters. */
+ *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
+ vim_free(*bufp); /* free any allocated file name */
+ *bufp = *fnamep;
+ if (*fnamep == NULL)
+ return -1;
+ add_pathsep(*fnamep);
+ }
+ }
+
+ /* ":." - path relative to the current directory */
+ /* ":~" - path relative to the home directory */
+ /* ":8" - shortname path - postponed till after */
+ while (src[*usedlen] == ':'
+ && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
+ {
+ *usedlen += 2;
+ if (c == '8')
+ {
+#ifdef WIN3264
+ has_shortname = 1; /* Postpone this. */
+#endif
+ continue;
+ }
+ pbuf = NULL;
+ /* Need full path first (use expand_env() to remove a "~/") */
+ if (!has_fullname)
+ {
+ if (c == '.' && **fnamep == '~')
+ p = pbuf = expand_env_save(*fnamep);
+ else
+ p = pbuf = FullName_save(*fnamep, FALSE);
+ }
+ else
+ p = *fnamep;
+
+ has_fullname = 0;
+
+ if (p != NULL)
+ {
+ if (c == '.')
+ {
+ mch_dirname(dirname, MAXPATHL);
+ s = shorten_fname(p, dirname);
+ if (s != NULL)
+ {
+ *fnamep = s;
+ if (pbuf != NULL)
+ {
+ vim_free(*bufp); /* free any allocated file name */
+ *bufp = pbuf;
+ pbuf = NULL;
+ }
+ }
+ }
+ else
+ {
+ home_replace(NULL, p, dirname, MAXPATHL, TRUE);
+ /* Only replace it when it starts with '~' */
+ if (*dirname == '~')
+ {
+ s = vim_strsave(dirname);
+ if (s != NULL)
+ {
+ *fnamep = s;
+ vim_free(*bufp);
+ *bufp = s;
+ }
+ }
+ }
+ vim_free(pbuf);
+ }
+ }
+
+ tail = gettail(*fnamep);
+ *fnamelen = (int)STRLEN(*fnamep);
+
+ /* ":h" - head, remove "/file_name", can be repeated */
+ /* Don't remove the first "/" or "c:\" */
+ while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
+ {
+ valid |= VALID_HEAD;
+ *usedlen += 2;
+ s = get_past_head(*fnamep);
+ while (tail > s && vim_ispathsep(tail[-1]))
+ --tail;
+ *fnamelen = (int)(tail - *fnamep);
+#ifdef VMS
+ if (*fnamelen > 0)
+ *fnamelen += 1; /* the path separator is part of the path */
+#endif
+ while (tail > s && !vim_ispathsep(tail[-1]))
+ --tail;
+ }
+
+ /* ":8" - shortname */
+ if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
+ {
+ *usedlen += 2;
+#ifdef WIN3264
+ has_shortname = 1;
+#endif
+ }
+
+#ifdef WIN3264
+ /* Check shortname after we have done 'heads' and before we do 'tails'
+ */
+ if (has_shortname)
+ {
+ pbuf = NULL;
+ /* Copy the string if it is shortened by :h */
+ if (*fnamelen < (int)STRLEN(*fnamep))
+ {
+ p = vim_strnsave(*fnamep, *fnamelen);
+ if (p == 0)
+ return -1;
+ vim_free(*bufp);
+ *bufp = *fnamep = p;
+ }
+
+ /* Split into two implementations - makes it easier. First is where
+ * there isn't a full name already, second is where there is.
+ */
+ if (!has_fullname && !vim_isAbsName(*fnamep))
+ {
+ if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
+ return -1;
+ }
+ else
+ {
+ int l;
+
+ /* Simple case, already have the full-name
+ * Nearly always shorter, so try first time. */
+ l = *fnamelen;
+ if (!get_short_pathname(fnamep, bufp, &l))
+ return -1;
+
+ if (l == 0)
+ {
+ /* Couldn't find the filename.. search the paths.
+ */
+ l = *fnamelen;
+ if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
+ return -1;
+ }
+ *fnamelen = l;
+ }
+ }
+#endif /* WIN3264 */
+
+ /* ":t" - tail, just the basename */
+ if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
+ {
+ *usedlen += 2;
+ *fnamelen -= (int)(tail - *fnamep);
+ *fnamep = tail;
+ }
+
+ /* ":e" - extension, can be repeated */
+ /* ":r" - root, without extension, can be repeated */
+ while (src[*usedlen] == ':'
+ && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
+ {
+ /* find a '.' in the tail:
+ * - for second :e: before the current fname
+ * - otherwise: The last '.'
+ */
+ if (src[*usedlen + 1] == 'e' && *fnamep > tail)
+ s = *fnamep - 2;
+ else
+ s = *fnamep + *fnamelen - 1;
+ for ( ; s > tail; --s)
+ if (s[0] == '.')
+ break;
+ if (src[*usedlen + 1] == 'e') /* :e */
+ {
+ if (s > tail)
+ {
+ *fnamelen += (int)(*fnamep - (s + 1));
+ *fnamep = s + 1;
+#ifdef VMS
+ /* cut version from the extension */
+ s = *fnamep + *fnamelen - 1;
+ for ( ; s > *fnamep; --s)
+ if (s[0] == ';')
+ break;
+ if (s > *fnamep)
+ *fnamelen = s - *fnamep;
+#endif
+ }
+ else if (*fnamep <= tail)
+ *fnamelen = 0;
+ }
+ else /* :r */
+ {
+ if (s > tail) /* remove one extension */
+ *fnamelen = (int)(s - *fnamep);
+ }
+ *usedlen += 2;
+ }
+
+ /* ":s?pat?foo?" - substitute */
+ /* ":gs?pat?foo?" - global substitute */
+ if (src[*usedlen] == ':'
+ && (src[*usedlen + 1] == 's'
+ || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
+ {
+ char_u *str;
+ char_u *pat;
+ char_u *sub;
+ int sep;
+ char_u *flags;
+ int didit = FALSE;
+
+ flags = (char_u *)"";
+ s = src + *usedlen + 2;
+ if (src[*usedlen + 1] == 'g')
+ {
+ flags = (char_u *)"g";
+ ++s;
+ }
+
+ sep = *s++;
+ if (sep)
+ {
+ /* find end of pattern */
+ p = vim_strchr(s, sep);
+ if (p != NULL)
+ {
+ pat = vim_strnsave(s, (int)(p - s));
+ if (pat != NULL)
+ {
+ s = p + 1;
+ /* find end of substitution */
+ p = vim_strchr(s, sep);
+ if (p != NULL)
+ {
+ sub = vim_strnsave(s, (int)(p - s));
+ str = vim_strnsave(*fnamep, *fnamelen);
+ if (sub != NULL && str != NULL)
+ {
+ *usedlen = (int)(p + 1 - src);
+ s = do_string_sub(str, pat, sub, flags);
+ if (s != NULL)
+ {
+ *fnamep = s;
+ *fnamelen = (int)STRLEN(s);
+ vim_free(*bufp);
+ *bufp = s;
+ didit = TRUE;
+ }
+ }
+ vim_free(sub);
+ vim_free(str);
+ }
+ vim_free(pat);
+ }
+ }
+ /* after using ":s", repeat all the modifiers */
+ if (didit)
+ goto repeat;
+ }
+ }
+
+ return valid;
+}
+
+/*
+ * Perform a substitution on "str" with pattern "pat" and substitute "sub".
+ * "flags" can be "g" to do a global substitute.
+ * Returns an allocated string, NULL for error.
+ */
+ char_u *
+do_string_sub(str, pat, sub, flags)
+ char_u *str;
+ char_u *pat;
+ char_u *sub;
+ char_u *flags;
+{
+ int sublen;
+ regmatch_T regmatch;
+ int i;
+ int do_all;
+ char_u *tail;
+ garray_T ga;
+ char_u *ret;
+ char_u *save_cpo;
+
+ /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
+ save_cpo = p_cpo;
+ p_cpo = (char_u *)"";
+
+ ga_init2(&ga, 1, 200);
+
+ do_all = (flags[0] == 'g');
+
+ regmatch.rm_ic = p_ic;
+ regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
+ if (regmatch.regprog != NULL)
+ {
+ tail = str;
+ while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
+ {
+ /*
+ * Get some space for a temporary buffer to do the substitution
+ * into. It will contain:
+ * - The text up to where the match is.
+ * - The substituted text.
+ * - The text after the match.
+ */
+ sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
+ if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
+ (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
+ {
+ ga_clear(&ga);
+ break;
+ }
+
+ /* copy the text up to where the match is */
+ i = (int)(regmatch.startp[0] - tail);
+ mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
+ /* add the substituted text */
+ (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
+ + ga.ga_len + i, TRUE, TRUE, FALSE);
+ ga.ga_len += i + sublen - 1;
+ ga.ga_room -= i + sublen - 1;
+ /* avoid getting stuck on a match with an empty string */
+ if (tail == regmatch.endp[0])
+ {
+ if (*tail == NUL)
+ break;
+ *((char_u *)ga.ga_data + ga.ga_len) = *tail++;
+ ++ga.ga_len;
+ --ga.ga_room;
+ }
+ else
+ {
+ tail = regmatch.endp[0];
+ if (*tail == NUL)
+ break;
+ }
+ if (!do_all)
+ break;
+ }
+
+ if (ga.ga_data != NULL)
+ STRCPY((char *)ga.ga_data + ga.ga_len, tail);
+
+ vim_free(regmatch.regprog);
+ }
+
+ ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
+ ga_clear(&ga);
+ p_cpo = save_cpo;
+
+ return ret;
+}
+
+#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
new file mode 100644
index 000000000..e6036ca34
--- /dev/null
+++ b/src/ex_cmds.c
@@ -0,0 +1,6198 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * ex_cmds.c: some functions for command line commands
+ */
+
+#include "vim.h"
+#include "version.h"
+
+#ifdef FEAT_EX_EXTRA
+static int linelen __ARGS((int *has_tab));
+#endif
+static void do_filter __ARGS((linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, int do_in, int do_out));
+#ifdef FEAT_VIMINFO
+static char_u *viminfo_filename __ARGS((char_u *));
+static void do_viminfo __ARGS((FILE *fp_in, FILE *fp_out, int want_info, int want_marks, int force_read));
+static int viminfo_encoding __ARGS((vir_T *virp));
+static int read_viminfo_up_to_marks __ARGS((vir_T *virp, int forceit, int writing));
+#endif
+
+static int check_overwrite __ARGS((exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int other));
+static int check_readonly __ARGS((int *forceit, buf_T *buf));
+#ifdef FEAT_AUTOCMD
+static void delbuf_msg __ARGS((char_u *name));
+#endif
+static int do_sub_msg __ARGS((void));
+static int
+#ifdef __BORLANDC__
+ _RTLENTRYF
+#endif
+ help_compare __ARGS((const void *s1, const void *s2));
+
+/*
+ * ":ascii" and "ga".
+ */
+/*ARGSUSED*/
+ void
+do_ascii(eap)
+ exarg_T *eap;
+{
+ int c;
+ char buf1[20];
+ char buf2[20];
+ char_u buf3[7];
+#ifdef FEAT_MBYTE
+ int c1 = 0;
+ int c2 = 0;
+ int len;
+
+ if (enc_utf8)
+ c = utfc_ptr2char(ml_get_cursor(), &c1, &c2);
+ else
+#endif
+ c = gchar_cursor();
+ if (c == NUL)
+ {
+ MSG("NUL");
+ return;
+ }
+
+#ifdef FEAT_MBYTE
+ IObuff[0] = NUL;
+ if (!has_mbyte || (enc_dbcs != 0 && c < 0x100) || c < 0x80)
+#endif
+ {
+ if (c == NL) /* NUL is stored as NL */
+ c = NUL;
+ if (vim_isprintc_strict(c) && (c < ' '
+#ifndef EBCDIC
+ || c > '~'
+#endif
+ ))
+ {
+ transchar_nonprint(buf3, c);
+ sprintf(buf1, " <%s>", (char *)buf3);
+ }
+ else
+ buf1[0] = NUL;
+#ifndef EBCDIC
+ if (c >= 0x80)
+ sprintf(buf2, " <M-%s>", transchar(c & 0x7f));
+ else
+#endif
+ buf2[0] = NUL;
+ sprintf((char *)IObuff, _("<%s>%s%s %d, Hex %02x, Octal %03o"),
+ transchar(c), buf1, buf2, c, c, c);
+#ifdef FEAT_MBYTE
+ c = c1;
+ c1 = c2;
+ c2 = 0;
+#endif
+ }
+
+#ifdef FEAT_MBYTE
+ /* Repeat for combining characters. */
+ while (has_mbyte && (c >= 0x100 || (enc_utf8 && c >= 0x80)))
+ {
+ len = (int)STRLEN(IObuff);
+ /* This assumes every multi-byte char is printable... */
+ if (len > 0)
+ IObuff[len++] = ' ';
+ IObuff[len++] = '<';
+ if (utf_iscomposing(c)
+#ifdef USE_GUI
+ && !gui.in_use
+#endif
+ )
+ IObuff[len++] = ' '; /* draw composing char on top of a space */
+ IObuff[len + (*mb_char2bytes)(c, IObuff + len)] = NUL;
+ sprintf((char *)IObuff + STRLEN(IObuff),
+ c < 0x10000 ? _("> %d, Hex %04x, Octal %o")
+ : _("> %d, Hex %08x, Octal %o"), c, c, c);
+ c = c1;
+ c1 = c2;
+ c2 = 0;
+ }
+#endif
+
+ msg(IObuff);
+}
+
+#if defined(FEAT_EX_EXTRA) || defined(PROTO)
+/*
+ * ":left", ":center" and ":right": align text.
+ */
+ void
+ex_align(eap)
+ exarg_T *eap;
+{
+ pos_T save_curpos;
+ int len;
+ int indent = 0;
+ int new_indent;
+ int has_tab;
+ int width;
+
+#ifdef FEAT_RIGHTLEFT
+ if (curwin->w_p_rl)
+ {
+ /* switch left and right aligning */
+ if (eap->cmdidx == CMD_right)
+ eap->cmdidx = CMD_left;
+ else if (eap->cmdidx == CMD_left)
+ eap->cmdidx = CMD_right;
+ }
+#endif
+
+ width = atoi((char *)eap->arg);
+ save_curpos = curwin->w_cursor;
+ if (eap->cmdidx == CMD_left) /* width is used for new indent */
+ {
+ if (width >= 0)
+ indent = width;
+ }
+ else
+ {
+ /*
+ * if 'textwidth' set, use it
+ * else if 'wrapmargin' set, use it
+ * if invalid value, use 80
+ */
+ if (width <= 0)
+ width = curbuf->b_p_tw;
+ if (width == 0 && curbuf->b_p_wm > 0)
+ width = W_WIDTH(curwin) - curbuf->b_p_wm;
+ if (width <= 0)
+ width = 80;
+ }
+
+ if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL)
+ return;
+
+ for (curwin->w_cursor.lnum = eap->line1;
+ curwin->w_cursor.lnum <= eap->line2; ++curwin->w_cursor.lnum)
+ {
+ if (eap->cmdidx == CMD_left) /* left align */
+ new_indent = indent;
+ else
+ {
+ len = linelen(eap->cmdidx == CMD_right ? &has_tab
+ : NULL) - get_indent();
+
+ if (len <= 0) /* skip blank lines */
+ continue;
+
+ if (eap->cmdidx == CMD_center)
+ new_indent = (width - len) / 2;
+ else
+ {
+ new_indent = width - len; /* right align */
+
+ /*
+ * Make sure that embedded TABs don't make the text go too far
+ * to the right.
+ */
+ if (has_tab)
+ while (new_indent > 0)
+ {
+ (void)set_indent(new_indent, 0);
+ if (linelen(NULL) <= width)
+ {
+ /*
+ * Now try to move the line as much as possible to
+ * the right. Stop when it moves too far.
+ */
+ do
+ (void)set_indent(++new_indent, 0);
+ while (linelen(NULL) <= width);
+ --new_indent;
+ break;
+ }
+ --new_indent;
+ }
+ }
+ }
+ if (new_indent < 0)
+ new_indent = 0;
+ (void)set_indent(new_indent, 0); /* set indent */
+ }
+ changed_lines(eap->line1, 0, eap->line2 + 1, 0L);
+ curwin->w_cursor = save_curpos;
+ beginline(BL_WHITE | BL_FIX);
+}
+
+/*
+ * Get the length of the current line, excluding trailing white space.
+ */
+ static int
+linelen(has_tab)
+ int *has_tab;
+{
+ char_u *line;
+ char_u *first;
+ char_u *last;
+ int save;
+ int len;
+
+ /* find the first non-blank character */
+ line = ml_get_curline();
+ first = skipwhite(line);
+
+ /* find the character after the last non-blank character */
+ for (last = first + STRLEN(first);
+ last > first && vim_iswhite(last[-1]); --last)
+ ;
+ save = *last;
+ *last = NUL;
+ len = linetabsize(line); /* get line length */
+ if (has_tab != NULL) /* check for embedded TAB */
+ *has_tab = (vim_strrchr(first, TAB) != NULL);
+ *last = save;
+
+ return len;
+}
+
+/*
+ * ":retab".
+ */
+ void
+ex_retab(eap)
+ exarg_T *eap;
+{
+ linenr_T lnum;
+ int got_tab = FALSE;
+ long num_spaces = 0;
+ long num_tabs;
+ long len;
+ long col;
+ long vcol;
+ long start_col = 0; /* For start of white-space string */
+ long start_vcol = 0; /* For start of white-space string */
+ int temp;
+ long old_len;
+ char_u *ptr;
+ char_u *new_line = (char_u *)1; /* init to non-NULL */
+ int did_undo; /* called u_save for current line */
+ int new_ts;
+ int save_list;
+ linenr_T first_line = 0; /* first changed line */
+ linenr_T last_line = 0; /* last changed line */
+
+ save_list = curwin->w_p_list;
+ curwin->w_p_list = 0; /* don't want list mode here */
+
+ new_ts = getdigits(&(eap->arg));
+ if (new_ts < 0)
+ {
+ EMSG(_(e_positive));
+ return;
+ }
+ if (new_ts == 0)
+ new_ts = curbuf->b_p_ts;
+ for (lnum = eap->line1; !got_int && lnum <= eap->line2; ++lnum)
+ {
+ ptr = ml_get(lnum);
+ col = 0;
+ vcol = 0;
+ did_undo = FALSE;
+ for (;;)
+ {
+ if (vim_iswhite(ptr[col]))
+ {
+ if (!got_tab && num_spaces == 0)
+ {
+ /* First consecutive white-space */
+ start_vcol = vcol;
+ start_col = col;
+ }
+ if (ptr[col] == ' ')
+ num_spaces++;
+ else
+ got_tab = TRUE;
+ }
+ else
+ {
+ if (got_tab || (eap->forceit && num_spaces > 1))
+ {
+ /* Retabulate this string of white-space */
+
+ /* len is virtual length of white string */
+ len = num_spaces = vcol - start_vcol;
+ num_tabs = 0;
+ if (!curbuf->b_p_et)
+ {
+ temp = new_ts - (start_vcol % new_ts);
+ if (num_spaces >= temp)
+ {
+ num_spaces -= temp;
+ num_tabs++;
+ }
+ num_tabs += num_spaces / new_ts;
+ num_spaces -= (num_spaces / new_ts) * new_ts;
+ }
+ if (curbuf->b_p_et || got_tab ||
+ (num_spaces + num_tabs < len))
+ {
+ if (did_undo == FALSE)
+ {
+ did_undo = TRUE;
+ if (u_save((linenr_T)(lnum - 1),
+ (linenr_T)(lnum + 1)) == FAIL)
+ {
+ new_line = NULL; /* flag out-of-memory */
+ break;
+ }
+ }
+
+ /* len is actual number of white characters used */
+ len = num_spaces + num_tabs;
+ old_len = (long)STRLEN(ptr);
+ new_line = lalloc(old_len - col + start_col + len + 1,
+ TRUE);
+ if (new_line == NULL)
+ break;
+ if (start_col > 0)
+ mch_memmove(new_line, ptr, (size_t)start_col);
+ mch_memmove(new_line + start_col + len,
+ ptr + col, (size_t)(old_len - col + 1));
+ ptr = new_line + start_col;
+ for (col = 0; col < len; col++)
+ ptr[col] = (col < num_tabs) ? '\t' : ' ';
+ ml_replace(lnum, new_line, FALSE);
+ if (first_line == 0)
+ first_line = lnum;
+ last_line = lnum;
+ ptr = new_line;
+ col = start_col + len;
+ }
+ }
+ got_tab = FALSE;
+ num_spaces = 0;
+ }
+ if (ptr[col] == NUL)
+ break;
+ vcol += chartabsize(ptr + col, (colnr_T)vcol);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ col += (*mb_ptr2len_check)(ptr + col);
+ else
+#endif
+ ++col;
+ }
+ if (new_line == NULL) /* out of memory */
+ break;
+ line_breakcheck();
+ }
+ if (got_int)
+ EMSG(_(e_interr));
+
+ if (curbuf->b_p_ts != new_ts)
+ redraw_curbuf_later(NOT_VALID);
+ if (first_line != 0)
+ changed_lines(first_line, 0, last_line + 1, 0L);
+
+ curwin->w_p_list = save_list; /* restore 'list' */
+
+ curbuf->b_p_ts = new_ts;
+ coladvance(curwin->w_curswant);
+
+ u_clearline();
+}
+#endif
+
+/*
+ * :move command - move lines line1-line2 to line dest
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+do_move(line1, line2, dest)
+ linenr_T line1;
+ linenr_T line2;
+ linenr_T dest;
+{
+ char_u *str;
+ linenr_T l;
+ linenr_T extra; /* Num lines added before line1 */
+ linenr_T num_lines; /* Num lines moved */
+ linenr_T last_line; /* Last line in file after adding new text */
+
+ if (dest >= line1 && dest < line2)
+ {
+ EMSG(_("E134: Move lines into themselves"));
+ return FAIL;
+ }
+
+ num_lines = line2 - line1 + 1;
+
+ /*
+ * First we copy the old text to its new location -- webb
+ * Also copy the flag that ":global" command uses.
+ */
+ if (u_save(dest, dest + 1) == FAIL)
+ return FAIL;
+ for (extra = 0, l = line1; l <= line2; l++)
+ {
+ str = vim_strsave(ml_get(l + extra));
+ if (str != NULL)
+ {
+ ml_append(dest + l - line1, str, (colnr_T)0, FALSE);
+ vim_free(str);
+ if (dest < line1)
+ extra++;
+ }
+ }
+
+ /*
+ * Now we must be careful adjusting our marks so that we don't overlap our
+ * mark_adjust() calls.
+ *
+ * We adjust the marks within the old text so that they refer to the
+ * last lines of the file (temporarily), because we know no other marks
+ * will be set there since these line numbers did not exist until we added
+ * our new lines.
+ *
+ * Then we adjust the marks on lines between the old and new text positions
+ * (either forwards or backwards).
+ *
+ * And Finally we adjust the marks we put at the end of the file back to
+ * their final destination at the new text position -- webb
+ */
+ last_line = curbuf->b_ml.ml_line_count;
+ mark_adjust(line1, line2, last_line - line2, 0L);
+ if (dest >= line2)
+ {
+ mark_adjust(line2 + 1, dest, -num_lines, 0L);
+ curbuf->b_op_start.lnum = dest - num_lines + 1;
+ curbuf->b_op_end.lnum = dest;
+ }
+ else
+ {
+ mark_adjust(dest + 1, line1 - 1, num_lines, 0L);
+ curbuf->b_op_start.lnum = dest + 1;
+ curbuf->b_op_end.lnum = dest + num_lines;
+ }
+ curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+ mark_adjust(last_line - num_lines + 1, last_line,
+ -(last_line - dest - extra), 0L);
+
+ /*
+ * Now we delete the original text -- webb
+ */
+ if (u_save(line1 + extra - 1, line2 + extra + 1) == FAIL)
+ return FAIL;
+
+ for (l = line1; l <= line2; l++)
+ ml_delete(line1 + extra, TRUE);
+
+ if (!global_busy && num_lines > p_report)
+ {
+ if (num_lines == 1)
+ MSG(_("1 line moved"));
+ else
+ smsg((char_u *)_("%ld lines moved"), num_lines);
+ }
+
+ /*
+ * Leave the cursor on the last of the moved lines.
+ */
+ if (dest >= line1)
+ curwin->w_cursor.lnum = dest;
+ else
+ curwin->w_cursor.lnum = dest + (line2 - line1) + 1;
+
+ if (line1 < dest)
+ changed_lines(line1, 0, dest + num_lines + 1, 0L);
+ else
+ changed_lines(dest + 1, 0, line1 + num_lines, 0L);
+
+ return OK;
+}
+
+/*
+ * ":copy"
+ */
+ void
+ex_copy(line1, line2, n)
+ linenr_T line1;
+ linenr_T line2;
+ linenr_T n;
+{
+ linenr_T count;
+ char_u *p;
+
+ count = line2 - line1 + 1;
+ curbuf->b_op_start.lnum = n + 1;
+ curbuf->b_op_end.lnum = n + count;
+ curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+
+ /*
+ * there are three situations:
+ * 1. destination is above line1
+ * 2. destination is between line1 and line2
+ * 3. destination is below line2
+ *
+ * n = destination (when starting)
+ * curwin->w_cursor.lnum = destination (while copying)
+ * line1 = start of source (while copying)
+ * line2 = end of source (while copying)
+ */
+ if (u_save(n, n + 1) == FAIL)
+ return;
+
+ curwin->w_cursor.lnum = n;
+ while (line1 <= line2)
+ {
+ /* need to use vim_strsave() because the line will be unlocked within
+ * ml_append() */
+ p = vim_strsave(ml_get(line1));
+ if (p != NULL)
+ {
+ ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, FALSE);
+ vim_free(p);
+ }
+ /* situation 2: skip already copied lines */
+ if (line1 == n)
+ line1 = curwin->w_cursor.lnum;
+ ++line1;
+ if (curwin->w_cursor.lnum < line1)
+ ++line1;
+ if (curwin->w_cursor.lnum < line2)
+ ++line2;
+ ++curwin->w_cursor.lnum;
+ }
+
+ appended_lines_mark(n, count);
+
+ msgmore((long)count);
+}
+
+/*
+ * Handle the ":!cmd" command. Also for ":r !cmd" and ":w !cmd"
+ * Bangs in the argument are replaced with the previously entered command.
+ * Remember the argument.
+ *
+ * RISCOS: Bangs only replaced when followed by a space, since many
+ * pathnames contain one.
+ */
+ void
+do_bang(addr_count, eap, forceit, do_in, do_out)
+ int addr_count;
+ exarg_T *eap;
+ int forceit;
+ int do_in, do_out;
+{
+ char_u *arg = eap->arg; /* command */
+ linenr_T line1 = eap->line1; /* start of range */
+ linenr_T line2 = eap->line2; /* end of range */
+ static char_u *prevcmd = NULL; /* the previous command */
+ char_u *newcmd = NULL; /* the new command */
+ int free_newcmd = FALSE; /* need to free() newcmd */
+ int ins_prevcmd;
+ char_u *t;
+ char_u *p;
+ char_u *trailarg;
+ int len;
+ int scroll_save = msg_scroll;
+
+ /*
+ * Disallow shell commands for "rvim".
+ * Disallow shell commands from .exrc and .vimrc in current directory for
+ * security reasons.
+ */
+ if (check_restricted() || check_secure())
+ return;
+
+ if (addr_count == 0) /* :! */
+ {
+ msg_scroll = FALSE; /* don't scroll here */
+ autowrite_all();
+ msg_scroll = scroll_save;
+ }
+
+ /*
+ * Try to find an embedded bang, like in :!<cmd> ! [args]
+ * (:!! is indicated by the 'forceit' variable)
+ */
+ ins_prevcmd = forceit;
+ trailarg = arg;
+ do
+ {
+ len = (int)STRLEN(trailarg) + 1;
+ if (newcmd != NULL)
+ len += (int)STRLEN(newcmd);
+ if (ins_prevcmd)
+ {
+ if (prevcmd == NULL)
+ {
+ EMSG(_(e_noprev));
+ vim_free(newcmd);
+ return;
+ }
+ len += (int)STRLEN(prevcmd);
+ }
+ if ((t = alloc(len)) == NULL)
+ {
+ vim_free(newcmd);
+ return;
+ }
+ *t = NUL;
+ if (newcmd != NULL)
+ STRCAT(t, newcmd);
+ if (ins_prevcmd)
+ STRCAT(t, prevcmd);
+ p = t + STRLEN(t);
+ STRCAT(t, trailarg);
+ vim_free(newcmd);
+ newcmd = t;
+
+ /*
+ * Scan the rest of the argument for '!', which is replaced by the
+ * previous command. "\!" is replaced by "!" (this is vi compatible).
+ */
+ trailarg = NULL;
+ while (*p)
+ {
+ if (*p == '!'
+#ifdef RISCOS
+ && (p[1] == ' ' || p[1] == NUL)
+#endif
+ )
+ {
+ if (p > newcmd && p[-1] == '\\')
+ mch_memmove(p - 1, p, (size_t)(STRLEN(p) + 1));
+ else
+ {
+ trailarg = p;
+ *trailarg++ = NUL;
+ ins_prevcmd = TRUE;
+ break;
+ }
+ }
+ ++p;
+ }
+ } while (trailarg != NULL);
+
+ vim_free(prevcmd);
+ prevcmd = newcmd;
+
+ if (bangredo) /* put cmd in redo buffer for ! command */
+ {
+ AppendToRedobuffLit(prevcmd);
+ AppendToRedobuff((char_u *)"\n");
+ bangredo = FALSE;
+ }
+ /*
+ * Add quotes around the command, for shells that need them.
+ */
+ if (*p_shq != NUL)
+ {
+ newcmd = alloc((unsigned)(STRLEN(prevcmd) + 2 * STRLEN(p_shq) + 1));
+ if (newcmd == NULL)
+ return;
+ STRCPY(newcmd, p_shq);
+ STRCAT(newcmd, prevcmd);
+ STRCAT(newcmd, p_shq);
+ free_newcmd = TRUE;
+ }
+ if (addr_count == 0) /* :! */
+ {
+ /* echo the command */
+ msg_start();
+ msg_putchar(':');
+ msg_putchar('!');
+ msg_outtrans(newcmd);
+ msg_clr_eos();
+ windgoto(msg_row, msg_col);
+
+ do_shell(newcmd, 0);
+ }
+ else /* :range! */
+ /* Careful: This may recursively call do_bang() again! (because of
+ * autocommands) */
+ do_filter(line1, line2, eap, newcmd, do_in, do_out);
+ if (free_newcmd)
+ vim_free(newcmd);
+}
+
+/*
+ * do_filter: filter lines through a command given by the user
+ *
+ * We use temp files and the call_shell() routine here. This would normally
+ * be done using pipes on a UNIX machine, but this is more portable to
+ * non-unix machines. The call_shell() routine needs to be able
+ * to deal with redirection somehow, and should handle things like looking
+ * at the PATH env. variable, and adding reasonable extensions to the
+ * command name given by the user. All reasonable versions of call_shell()
+ * do this.
+ * We use input redirection if do_in is TRUE.
+ * We use output redirection if do_out is TRUE.
+ */
+ static void
+do_filter(line1, line2, eap, cmd, do_in, do_out)
+ linenr_T line1, line2;
+ exarg_T *eap; /* for forced 'ff' and 'fenc' */
+ char_u *cmd;
+ int do_in, do_out;
+{
+ char_u *itmp = NULL;
+ char_u *otmp = NULL;
+ linenr_T linecount;
+ linenr_T read_linecount;
+ pos_T cursor_save;
+ char_u *cmd_buf;
+#ifdef FEAT_AUTOCMD
+ buf_T *old_curbuf = curbuf;
+#endif
+
+ if (*cmd == NUL) /* no filter command */
+ return;
+
+#ifdef WIN3264
+ /*
+ * Check if external commands are allowed now.
+ */
+ if (can_end_termcap_mode(TRUE) == FALSE)
+ return;
+#endif
+
+ cursor_save = curwin->w_cursor;
+ linecount = line2 - line1 + 1;
+ curwin->w_cursor.lnum = line1;
+ curwin->w_cursor.col = 0;
+ changed_line_abv_curs();
+ invalidate_botline();
+
+ /*
+ * 1. Form temp file names
+ * 2. Write the lines to a temp file
+ * 3. Run the filter command on the temp file
+ * 4. Read the output of the command into the buffer
+ * 5. Delete the original lines to be filtered
+ * 6. Remove the temp files
+ */
+
+ if ((do_in && (itmp = vim_tempname('i')) == NULL)
+ || (do_out && (otmp = vim_tempname('o')) == NULL))
+ {
+ EMSG(_(e_notmp));
+ goto filterend;
+ }
+
+/*
+ * The writing and reading of temp files will not be shown.
+ * Vi also doesn't do this and the messages are not very informative.
+ */
+ ++no_wait_return; /* don't call wait_return() while busy */
+ if (do_in && buf_write(curbuf, itmp, NULL, line1, line2, eap,
+ FALSE, FALSE, FALSE, TRUE) == FAIL)
+ {
+ msg_putchar('\n'); /* keep message from buf_write() */
+ --no_wait_return;
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+ if (!aborting())
+#endif
+ (void)EMSG2(_(e_notcreate), itmp); /* will call wait_return */
+ goto filterend;
+ }
+#ifdef FEAT_AUTOCMD
+ if (curbuf != old_curbuf)
+ goto filterend;
+#endif
+
+ if (!do_out)
+ msg_putchar('\n');
+
+ cmd_buf = make_filter_cmd(cmd, itmp, otmp);
+ if (cmd_buf == NULL)
+ goto filterend;
+
+ windgoto((int)Rows - 1, 0);
+ cursor_on();
+
+ /*
+ * When not redirecting the output the command can write anything to the
+ * screen. If 'shellredir' is equal to ">", screen may be messed up by
+ * stderr output of external command. Clear the screen later.
+ * If do_in is FALSE, this could be something like ":r !cat", which may
+ * also mess up the screen, clear it later.
+ */
+ if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in)
+ redraw_later_clear();
+
+ /*
+ * When call_shell() fails wait_return() is called to give the user a
+ * chance to read the error messages. Otherwise errors are ignored, so you
+ * can see the error messages from the command that appear on stdout; use
+ * 'u' to fix the text
+ * Switch to cooked mode when not redirecting stdin, avoids that something
+ * like ":r !cat" hangs.
+ * Pass on the SHELL_DOOUT flag when the output is being redirected.
+ */
+ if (call_shell(cmd_buf, SHELL_FILTER | SHELL_COOKED
+ | (do_out ? SHELL_DOOUT : 0)))
+ {
+ redraw_later_clear();
+ wait_return(FALSE);
+ }
+ vim_free(cmd_buf);
+
+ did_check_timestamps = FALSE;
+ need_check_timestamps = TRUE;
+
+ /* When interrupting the shell command, it may still have produced some
+ * useful output. Reset got_int here, so that readfile() won't cancel
+ * reading. */
+ ui_breakcheck();
+ got_int = FALSE;
+
+ if (do_out)
+ {
+ if (u_save((linenr_T)(line2), (linenr_T)(line2 + 1)) == FAIL)
+ goto error;
+ redraw_curbuf_later(VALID);
+ read_linecount = curbuf->b_ml.ml_line_count;
+ if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, eap,
+ READ_FILTER) == FAIL)
+ {
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+ if (!aborting())
+#endif
+ {
+ msg_putchar('\n');
+ EMSG2(_(e_notread), otmp);
+ }
+ goto error;
+ }
+#ifdef FEAT_AUTOCMD
+ if (curbuf != old_curbuf)
+ goto filterend;
+#endif
+
+ if (do_in)
+ {
+ if (cmdmod.keepmarks || vim_strchr(p_cpo, CPO_REMMARK) == NULL)
+ {
+ read_linecount = curbuf->b_ml.ml_line_count - read_linecount;
+ if (read_linecount >= linecount)
+ /* move all marks from old lines to new lines */
+ mark_adjust(line1, line2, linecount, 0L);
+ else
+ {
+ /* move marks from old lines to new lines, delete marks
+ * that are in deleted lines */
+ mark_adjust(line1, line1 + read_linecount - 1,
+ linecount, 0L);
+ mark_adjust(line1 + read_linecount, line2, MAXLNUM, 0L);
+ }
+ }
+
+ /*
+ * Put cursor on first filtered line for ":range!cmd".
+ * Adjust '[ and '] (set by buf_write()).
+ */
+ curwin->w_cursor.lnum = line1;
+ del_lines(linecount, TRUE);
+ curbuf->b_op_start.lnum -= linecount; /* adjust '[ */
+ curbuf->b_op_end.lnum -= linecount; /* adjust '] */
+ write_lnum_adjust(-linecount); /* adjust last line
+ for next write */
+ }
+ else
+ {
+ /*
+ * Put cursor on last new line for ":r !cmd".
+ */
+ curwin->w_cursor.lnum = curbuf->b_op_end.lnum;
+ linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1;
+ }
+ beginline(BL_WHITE | BL_FIX); /* cursor on first non-blank */
+ --no_wait_return;
+
+ if (linecount > p_report)
+ {
+ if (do_in)
+ {
+ sprintf((char *)msg_buf, _("%ld lines filtered"),
+ (long)linecount);
+ if (msg(msg_buf) && !msg_scroll)
+ {
+ /* save message to display it after redraw */
+ set_keep_msg(msg_buf);
+ keep_msg_attr = 0;
+ }
+ }
+ else
+ msgmore((long)linecount);
+ }
+ }
+ else
+ {
+error:
+ /* put cursor back in same position for ":w !cmd" */
+ curwin->w_cursor = cursor_save;
+ --no_wait_return;
+ wait_return(FALSE);
+ }
+
+filterend:
+
+#ifdef FEAT_AUTOCMD
+ if (curbuf != old_curbuf)
+ {
+ --no_wait_return;
+ EMSG(_("E135: *Filter* Autocommands must not change current buffer"));
+ }
+#endif
+ if (itmp != NULL)
+ mch_remove(itmp);
+ if (otmp != NULL)
+ mch_remove(otmp);
+ vim_free(itmp);
+ vim_free(otmp);
+}
+
+/*
+ * Call a shell to execute a command.
+ * When "cmd" is NULL start an interactive shell.
+ */
+ void
+do_shell(cmd, flags)
+ char_u *cmd;
+ int flags; /* may be SHELL_DOOUT when output is redirected */
+{
+ buf_T *buf;
+#ifndef FEAT_GUI_MSWIN
+ int save_nwr;
+#endif
+#ifdef MSWIN
+ int winstart = FALSE;
+#endif
+
+ /*
+ * Disallow shell commands for "rvim".
+ * Disallow shell commands from .exrc and .vimrc in current directory for
+ * security reasons.
+ */
+ if (check_restricted() || check_secure())
+ {
+ msg_end();
+ return;
+ }
+
+#ifdef MSWIN
+ /*
+ * Check if external commands are allowed now.
+ */
+ if (can_end_termcap_mode(TRUE) == FALSE)
+ return;
+
+ /*
+ * Check if ":!start" is used.
+ */
+ if (cmd != NULL)
+ winstart = (STRNICMP(cmd, "start ", 6) == 0);
+#endif
+
+ /*
+ * For autocommands we want to get the output on the current screen, to
+ * avoid having to type return below.
+ */
+ msg_putchar('\r'); /* put cursor at start of line */
+#ifdef FEAT_AUTOCMD
+ if (!autocmd_busy)
+#endif
+ {
+#ifdef MSWIN
+ if (!winstart)
+#endif
+ stoptermcap();
+ }
+#ifdef MSWIN
+ if (!winstart)
+#endif
+ msg_putchar('\n'); /* may shift screen one line up */
+
+ /* warning message before calling the shell */
+ if (p_warn
+#ifdef FEAT_AUTOCMD
+ && !autocmd_busy
+#endif
+ && msg_silent == 0)
+ for (buf = firstbuf; buf; buf = buf->b_next)
+ if (bufIsChanged(buf))
+ {
+#ifdef FEAT_GUI_MSWIN
+ if (!winstart)
+ starttermcap(); /* don't want a message box here */
+#endif
+ MSG_PUTS(_("[No write since last change]\n"));
+#ifdef FEAT_GUI_MSWIN
+ if (!winstart)
+ stoptermcap();
+#endif
+ break;
+ }
+
+ /* This windgoto is required for when the '\n' resulted in a "delete line
+ * 1" command to the terminal. */
+ if (!swapping_screen())
+ windgoto(msg_row, msg_col);
+ cursor_on();
+ (void)call_shell(cmd, SHELL_COOKED | flags);
+ did_check_timestamps = FALSE;
+ need_check_timestamps = TRUE;
+
+ /*
+ * put the message cursor at the end of the screen, avoids wait_return()
+ * to overwrite the text that the external command showed
+ */
+ if (!swapping_screen())
+ {
+ msg_row = Rows - 1;
+ msg_col = 0;
+ }
+
+#ifdef FEAT_AUTOCMD
+ if (autocmd_busy)
+ {
+ if (msg_silent == 0)
+ redraw_later_clear();
+ }
+ else
+#endif
+ {
+ /*
+ * For ":sh" there is no need to call wait_return(), just redraw.
+ * Also for the Win32 GUI (the output is in a console window).
+ * Otherwise there is probably text on the screen that the user wants
+ * to read before redrawing, so call wait_return().
+ */
+#ifndef FEAT_GUI_MSWIN
+ if (cmd == NULL
+# ifdef WIN3264
+ || (winstart && !need_wait_return)
+# endif
+ )
+ {
+ if (msg_silent == 0)
+ redraw_later_clear();
+ need_wait_return = FALSE;
+ }
+ else
+ {
+ /*
+ * If we switch screens when starttermcap() is called, we really
+ * want to wait for "hit return to continue".
+ */
+ save_nwr = no_wait_return;
+ if (swapping_screen())
+ no_wait_return = FALSE;
+# ifdef AMIGA
+ wait_return(term_console ? -1 : msg_silent == 0); /* see below */
+# else
+ wait_return(msg_silent == 0);
+# endif
+ no_wait_return = save_nwr;
+ }
+#endif /* FEAT_GUI_W32 */
+
+#ifdef MSWIN
+ if (!winstart) /* if winstart==TRUE, never stopped termcap! */
+#endif
+ starttermcap(); /* start termcap if not done by wait_return() */
+
+ /*
+ * In an Amiga window redrawing is caused by asking the window size.
+ * If we got an interrupt this will not work. The chance that the
+ * window size is wrong is very small, but we need to redraw the
+ * screen. Don't do this if ':' hit in wait_return(). THIS IS UGLY
+ * but it saves an extra redraw.
+ */
+#ifdef AMIGA
+ if (skip_redraw) /* ':' hit in wait_return() */
+ {
+ if (msg_silent == 0)
+ redraw_later_clear();
+ }
+ else if (term_console)
+ {
+ OUT_STR(IF_EB("\033[0 q", ESC_STR "[0 q")); /* get window size */
+ if (got_int && msg_silent == 0)
+ redraw_later_clear(); /* if got_int is TRUE, redraw needed */
+ else
+ must_redraw = 0; /* no extra redraw needed */
+ }
+#endif
+ }
+
+ /* display any error messages now */
+ display_errors();
+}
+
+/*
+ * Create a shell command from a command string, input redirection file and
+ * output redirection file.
+ * Returns an allocated string with the shell command, or NULL for failure.
+ */
+ char_u *
+make_filter_cmd(cmd, itmp, otmp)
+ char_u *cmd; /* command */
+ char_u *itmp; /* NULL or name of input file */
+ char_u *otmp; /* NULL or name of output file */
+{
+ char_u *buf;
+ long_u len;
+
+ len = (long_u)STRLEN(cmd) + 3; /* "()" + NUL */
+ if (itmp != NULL)
+ len += (long_u)STRLEN(itmp) + 9; /* " { < " + " } " */
+ if (otmp != NULL)
+ len += (long_u)STRLEN(otmp) + (long_u)STRLEN(p_srr) + 2; /* " " */
+ buf = lalloc(len, TRUE);
+ if (buf == NULL)
+ return NULL;
+
+#if (defined(UNIX) && !defined(ARCHIE)) || defined(OS2)
+ /*
+ * put braces around the command (for concatenated commands)
+ */
+ sprintf((char *)buf, "(%s)", (char *)cmd);
+ if (itmp != NULL)
+ {
+ STRCAT(buf, " < ");
+ STRCAT(buf, itmp);
+ }
+#else
+ /*
+ * for shells that don't understand braces around commands, at least allow
+ * the use of commands in a pipe.
+ */
+ STRCPY(buf, cmd);
+ if (itmp != NULL)
+ {
+ char_u *p;
+
+ /*
+ * If there is a pipe, we have to put the '<' in front of it.
+ * Don't do this when 'shellquote' is not empty, otherwise the
+ * redirection would be inside the quotes.
+ */
+ if (*p_shq == NUL)
+ {
+ p = vim_strchr(buf, '|');
+ if (p != NULL)
+ *p = NUL;
+ }
+# ifdef RISCOS
+ STRCAT(buf, " { < "); /* Use RISC OS notation for input. */
+ STRCAT(buf, itmp);
+ STRCAT(buf, " } ");
+# else
+ STRCAT(buf, " <"); /* " < " causes problems on Amiga */
+ STRCAT(buf, itmp);
+# endif
+ if (*p_shq == NUL)
+ {
+ p = vim_strchr(cmd, '|');
+ if (p != NULL)
+ {
+ STRCAT(buf, " "); /* insert a space before the '|' for DOS */
+ STRCAT(buf, p);
+ }
+ }
+ }
+#endif
+ if (otmp != NULL)
+ append_redir(buf, p_srr, otmp);
+
+ return buf;
+}
+
+/*
+ * Append output redirection for file "fname" to the end of string buffer "buf"
+ * Works with the 'shellredir' and 'shellpipe' options.
+ * The caller should make sure that there is enough room:
+ * STRLEN(opt) + STRLEN(fname) + 3
+ */
+ void
+append_redir(buf, opt, fname)
+ char_u *buf;
+ char_u *opt;
+ char_u *fname;
+{
+ char_u *p;
+
+ buf += STRLEN(buf);
+ /* find "%s", skipping "%%" */
+ for (p = opt; (p = vim_strchr(p, '%')) != NULL; ++p)
+ if (p[1] == 's')
+ break;
+ if (p != NULL)
+ {
+ *buf = ' '; /* not really needed? Not with sh, ksh or bash */
+ sprintf((char *)buf + 1, (char *)opt, (char *)fname);
+ }
+ else
+ sprintf((char *)buf,
+#ifdef FEAT_QUICKFIX
+# ifndef RISCOS
+ opt != p_sp ? " %s%s" :
+# endif
+ " %s %s",
+#else
+# ifndef RISCOS
+ " %s%s", /* " > %s" causes problems on Amiga */
+# else
+ " %s %s", /* But is needed for 'shellpipe' and RISC OS */
+# endif
+#endif
+ (char *)opt, (char *)fname);
+}
+
+#ifdef FEAT_VIMINFO
+
+static int no_viminfo __ARGS((void));
+static int viminfo_errcnt;
+
+ static int
+no_viminfo()
+{
+ /* "vim -i NONE" does not read or write a viminfo file */
+ return (use_viminfo != NULL && STRCMP(use_viminfo, "NONE") == 0);
+}
+
+/*
+ * Report an error for reading a viminfo file.
+ * Count the number of errors. When there are more than 10, return TRUE.
+ */
+ int
+viminfo_error(errnum, message, line)
+ char *errnum;
+ char *message;
+ char_u *line;
+{
+ sprintf((char *)IObuff, _("%sviminfo: %s in line: "), errnum, message);
+ STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff));
+ emsg(IObuff);
+ if (++viminfo_errcnt >= 10)
+ {
+ EMSG(_("E136: viminfo: Too many errors, skipping rest of file"));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * read_viminfo() -- Read the viminfo file. Registers etc. which are already
+ * set are not over-written unless force is TRUE. -- webb
+ */
+ int
+read_viminfo(file, want_info, want_marks, forceit)
+ char_u *file;
+ int want_info;
+ int want_marks;
+ int forceit;
+{
+ FILE *fp;
+ char_u *fname;
+
+ if (no_viminfo())
+ return FAIL;
+
+ fname = viminfo_filename(file); /* may set to default if NULL */
+ if (fname == NULL)
+ return FAIL;
+ fp = mch_fopen((char *)fname, READBIN);
+
+ if (p_verbose > 0)
+ {
+ char_u *s;
+
+ s = fname;
+ if (STRLEN(fname) > IOSIZE - 100)
+ s = fname + STRLEN(fname) - (IOSIZE - 100);
+ smsg((char_u *)_("Reading viminfo file \"%s\"%s%s%s"), s,
+ want_info ? _(" info") : "",
+ want_marks ? _(" marks") : "",
+ fp == NULL ? _(" FAILED") : "");
+ }
+
+ vim_free(fname);
+ if (fp == NULL)
+ return FAIL;
+
+ viminfo_errcnt = 0;
+ do_viminfo(fp, NULL, want_info, want_marks, forceit);
+
+ fclose(fp);
+
+ return OK;
+}
+
+/*
+ * write_viminfo() -- Write the viminfo file. The old one is read in first so
+ * that effectively a merge of current info and old info is done. This allows
+ * multiple vims to run simultaneously, without losing any marks etc. If
+ * forceit is TRUE, then the old file is not read in, and only internal info is
+ * written to the file. -- webb
+ */
+ void
+write_viminfo(file, forceit)
+ char_u *file;
+ int forceit;
+{
+ char_u *fname;
+ FILE *fp_in = NULL; /* input viminfo file, if any */
+ FILE *fp_out = NULL; /* output viminfo file */
+ char_u *tempname = NULL; /* name of temp viminfo file */
+ struct stat st_new; /* mch_stat() of potential new file */
+ char_u *wp;
+#if defined(UNIX) || defined(VMS)
+ mode_t umask_save;
+#endif
+#ifdef UNIX
+ int shortname = FALSE; /* use 8.3 file name */
+ struct stat st_old; /* mch_stat() of existing viminfo file */
+#endif
+
+ if (no_viminfo())
+ return;
+
+ fname = viminfo_filename(file); /* may set to default if NULL */
+ if (fname == NULL)
+ return;
+
+ fp_in = mch_fopen((char *)fname, READBIN);
+ if (fp_in == NULL)
+ {
+ /* if it does exist, but we can't read it, don't try writing */
+ if (mch_stat((char *)fname, &st_new) == 0)
+ goto end;
+#if defined(UNIX) || defined(VMS)
+ /*
+ * For Unix we create the .viminfo non-accessible for others,
+ * because it may contain text from non-accessible documents.
+ */
+ umask_save = umask(077);
+#endif
+ fp_out = mch_fopen((char *)fname, WRITEBIN);
+#if defined(UNIX) || defined(VMS)
+ (void)umask(umask_save);
+#endif
+ }
+ else
+ {
+ /*
+ * There is an existing viminfo file. Create a temporary file to
+ * write the new viminfo into, in the same directory as the
+ * existing viminfo file, which will be renamed later.
+ */
+#ifdef UNIX
+ /*
+ * For Unix we check the owner of the file. It's not very nice to
+ * overwrite a user's viminfo file after a "su root", with a
+ * viminfo file that the user can't read.
+ */
+ st_old.st_dev = st_old.st_ino = 0;
+ st_old.st_mode = 0600;
+ if (mch_stat((char *)fname, &st_old) == 0 && getuid() &&
+ !(st_old.st_uid == getuid()
+ ? (st_old.st_mode & 0200)
+ : (st_old.st_gid == getgid()
+ ? (st_old.st_mode & 0020)
+ : (st_old.st_mode & 0002))))
+ {
+ int tt;
+
+ /* avoid a wait_return for this message, it's annoying */
+ tt = msg_didany;
+ EMSG2(_("E137: Viminfo file is not writable: %s"), fname);
+ msg_didany = tt;
+ goto end;
+ }
+#endif
+
+ /*
+ * Make tempname.
+ * May try twice: Once normal and once with shortname set, just in
+ * case somebody puts his viminfo file in an 8.3 filesystem.
+ */
+ for (;;)
+ {
+ tempname = buf_modname(
+#ifdef UNIX
+ shortname,
+#else
+# ifdef SHORT_FNAME
+ TRUE,
+# else
+# ifdef FEAT_GUI_W32
+ gui_is_win32s(),
+# else
+ FALSE,
+# endif
+# endif
+#endif
+ fname,
+#ifdef VMS
+ (char_u *)"-tmp",
+#else
+# ifdef RISCOS
+ (char_u *)"/tmp",
+# else
+ (char_u *)".tmp",
+# endif
+#endif
+ FALSE);
+ if (tempname == NULL) /* out of memory */
+ break;
+
+ /*
+ * Check if tempfile already exists. Never overwrite an
+ * existing file!
+ */
+ if (mch_stat((char *)tempname, &st_new) == 0)
+ {
+#ifdef UNIX
+ /*
+ * Check if tempfile is same as original file. May happen
+ * when modname() gave the same file back. E.g. silly
+ * link, or file name-length reached. Try again with
+ * shortname set.
+ */
+ if (!shortname && st_new.st_dev == st_old.st_dev &&
+ st_new.st_ino == st_old.st_ino)
+ {
+ vim_free(tempname);
+ tempname = NULL;
+ shortname = TRUE;
+ continue;
+ }
+#endif
+ /*
+ * Try another name. Change one character, just before
+ * the extension. This should also work for an 8.3
+ * file name, when after adding the extension it still is
+ * the same file as the original.
+ */
+ wp = tempname + STRLEN(tempname) - 5;
+ if (wp < gettail(tempname)) /* empty file name? */
+ wp = gettail(tempname);
+ for (*wp = 'z'; mch_stat((char *)tempname, &st_new) == 0;
+ --*wp)
+ {
+ /*
+ * They all exist? Must be something wrong! Don't
+ * write the viminfo file then.
+ */
+ if (*wp == 'a')
+ {
+ vim_free(tempname);
+ tempname = NULL;
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ if (tempname != NULL)
+ {
+ fp_out = mch_fopen((char *)tempname, WRITEBIN);
+
+ /*
+ * If we can't create in the same directory, try creating a
+ * "normal" temp file.
+ */
+ if (fp_out == NULL)
+ {
+ vim_free(tempname);
+ if ((tempname = vim_tempname('o')) != NULL)
+ fp_out = mch_fopen((char *)tempname, WRITEBIN);
+ }
+#ifdef UNIX
+ /*
+ * Set file protection same as original file, but strip s-bit
+ * and make sure the owner can read/write it.
+ */
+ if (fp_out != NULL)
+ {
+ (void)mch_setperm(tempname,
+ (long)((st_old.st_mode & 0777) | 0600));
+ /* this only works for root: */
+ (void)chown((char *)tempname, st_old.st_uid, st_old.st_gid);
+ }
+#endif
+ }
+ }
+
+ /*
+ * Check if the new viminfo file can be written to.
+ */
+ if (fp_out == NULL)
+ {
+ EMSG2(_("E138: Can't write viminfo file %s!"),
+ (fp_in == NULL || tempname == NUL) ? fname : tempname);
+ if (fp_in != NULL)
+ fclose(fp_in);
+ goto end;
+ }
+
+ if (p_verbose > 0)
+ msg_str((char_u *)_("Writing viminfo file \"%s\""), fname);
+
+ viminfo_errcnt = 0;
+ do_viminfo(fp_in, fp_out, !forceit, !forceit, FALSE);
+
+ fclose(fp_out); /* errors are ignored !? */
+ if (fp_in != NULL)
+ {
+ fclose(fp_in);
+ /*
+ * In case of an error, don't overwrite the original viminfo file.
+ */
+ if (viminfo_errcnt || vim_rename(tempname, fname) == -1)
+ mch_remove(tempname);
+ }
+end:
+ vim_free(fname);
+ vim_free(tempname);
+}
+
+/*
+ * Get the viminfo file name to use.
+ * If "file" is given and not empty, use it (has already been expanded by
+ * cmdline functions).
+ * Otherwise use "-i file_name", value from 'viminfo' or the default, and
+ * expand environment variables.
+ * Returns an allocated string. NULL when out of memory.
+ */
+ static char_u *
+viminfo_filename(file)
+ char_u *file;
+{
+ if (file == NULL || *file == NUL)
+ {
+ if (use_viminfo != NULL)
+ file = use_viminfo;
+ else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL)
+ {
+#ifdef VIMINFO_FILE2
+ /* don't use $HOME when not defined (turned into "c:/"!). */
+# ifdef VMS
+ if (mch_getenv((char_u *)"SYS$LOGIN") == NULL)
+# else
+ if (mch_getenv((char_u *)"HOME") == NULL)
+# endif
+ {
+ /* don't use $VIM when not available. */
+ expand_env((char_u *)"$VIM", NameBuff, MAXPATHL);
+ if (STRCMP("$VIM", NameBuff) != 0) /* $VIM was expanded */
+ file = (char_u *)VIMINFO_FILE2;
+ else
+ file = (char_u *)VIMINFO_FILE;
+ }
+ else
+#endif
+ file = (char_u *)VIMINFO_FILE;
+ }
+ expand_env(file, NameBuff, MAXPATHL);
+ file = NameBuff;
+ }
+ return vim_strsave(file);
+}
+
+/*
+ * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
+ */
+ static void
+do_viminfo(fp_in, fp_out, want_info, want_marks, force_read)
+ FILE *fp_in;
+ FILE *fp_out;
+ int want_info;
+ int want_marks;
+ int force_read;
+{
+ int count = 0;
+ int eof = FALSE;
+ vir_T vir;
+
+ if ((vir.vir_line = alloc(LSIZE)) == NULL)
+ return;
+ vir.vir_fd = fp_in;
+#ifdef FEAT_MBYTE
+ vir.vir_conv.vc_type = CONV_NONE;
+#endif
+
+ if (fp_in != NULL)
+ {
+ if (want_info)
+ eof = read_viminfo_up_to_marks(&vir, force_read, fp_out != NULL);
+ else
+ /* Skip info, find start of marks */
+ while (!(eof = viminfo_readline(&vir))
+ && vir.vir_line[0] != '>')
+ ;
+ }
+ if (fp_out != NULL)
+ {
+ /* Write the info: */
+ fprintf(fp_out, _("# This viminfo file was generated by Vim %s.\n"),
+ VIM_VERSION_MEDIUM);
+ fprintf(fp_out, _("# You may edit it if you're careful!\n\n"));
+#ifdef FEAT_MBYTE
+ fprintf(fp_out, _("# Value of 'encoding' when this file was written\n"));
+ fprintf(fp_out, "*encoding=%s\n\n", p_enc);
+#endif
+ write_viminfo_search_pattern(fp_out);
+ write_viminfo_sub_string(fp_out);
+#ifdef FEAT_CMDHIST
+ write_viminfo_history(fp_out);
+#endif
+ write_viminfo_registers(fp_out);
+#ifdef FEAT_EVAL
+ write_viminfo_varlist(fp_out);
+#endif
+ write_viminfo_filemarks(fp_out);
+ write_viminfo_bufferlist(fp_out);
+ count = write_viminfo_marks(fp_out);
+ }
+ if (fp_in != NULL && want_marks)
+ copy_viminfo_marks(&vir, fp_out, count, eof);
+
+ vim_free(vir.vir_line);
+#ifdef FEAT_MBYTE
+ if (vir.vir_conv.vc_type != CONV_NONE)
+ convert_setup(&vir.vir_conv, NULL, NULL);
+#endif
+}
+
+/*
+ * read_viminfo_up_to_marks() -- Only called from do_viminfo(). Reads in the
+ * first part of the viminfo file which contains everything but the marks that
+ * are local to a file. Returns TRUE when end-of-file is reached. -- webb
+ */
+ static int
+read_viminfo_up_to_marks(virp, forceit, writing)
+ vir_T *virp;
+ int forceit;
+ int writing;
+{
+ int eof;
+ buf_T *buf;
+
+#ifdef FEAT_CMDHIST
+ prepare_viminfo_history(forceit ? 9999 : 0);
+#endif
+ eof = viminfo_readline(virp);
+ while (!eof && virp->vir_line[0] != '>')
+ {
+ switch (virp->vir_line[0])
+ {
+ /* Characters reserved for future expansion, ignored now */
+ case '+': /* "+40 /path/dir file", for running vim without args */
+ case '|': /* to be defined */
+ case '^': /* to be defined */
+ case '<': /* long line - ignored */
+ /* A comment or empty line. */
+ case NUL:
+ case '\r':
+ case '\n':
+ case '#':
+ eof = viminfo_readline(virp);
+ break;
+ case '*': /* "*encoding=value" */
+ eof = viminfo_encoding(virp);
+ break;
+ case '!': /* global variable */
+#ifdef FEAT_EVAL
+ eof = read_viminfo_varlist(virp, writing);
+#else
+ eof = viminfo_readline(virp);
+#endif
+ break;
+ case '%': /* entry for buffer list */
+ eof = read_viminfo_bufferlist(virp, writing);
+ break;
+ case '"':
+ eof = read_viminfo_register(virp, forceit);
+ break;
+ case '/': /* Search string */
+ case '&': /* Substitute search string */
+ case '~': /* Last search string, followed by '/' or '&' */
+ eof = read_viminfo_search_pattern(virp, forceit);
+ break;
+ case '$':
+ eof = read_viminfo_sub_string(virp, forceit);
+ break;
+ case ':':
+ case '?':
+ case '=':
+ case '@':
+#ifdef FEAT_CMDHIST
+ eof = read_viminfo_history(virp);
+#else
+ eof = viminfo_readline(virp);
+#endif
+ break;
+ case '-':
+ case '\'':
+ eof = read_viminfo_filemark(virp, forceit);
+ break;
+ default:
+ if (viminfo_error("E575: ", _("Illegal starting char"),
+ virp->vir_line))
+ eof = TRUE;
+ else
+ eof = viminfo_readline(virp);
+ break;
+ }
+ }
+
+#ifdef FEAT_CMDHIST
+ /* Finish reading history items. */
+ finish_viminfo_history();
+#endif
+
+ /* Change file names to buffer numbers for fmarks. */
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ fmarks_check_names(buf);
+
+ return eof;
+}
+
+/*
+ * Compare the 'encoding' value in the viminfo file with the current value of
+ * 'encoding'. If different and the 'c' flag is in 'viminfo', setup for
+ * conversion of text with iconv() in viminfo_readstring().
+ */
+ static int
+viminfo_encoding(virp)
+ vir_T *virp;
+{
+#ifdef FEAT_MBYTE
+ char_u *p;
+ int i;
+
+ if (get_viminfo_parameter('c') != 0)
+ {
+ p = vim_strchr(virp->vir_line, '=');
+ if (p != NULL)
+ {
+ /* remove trailing newline */
+ ++p;
+ for (i = 0; vim_isprintc(p[i]); ++i)
+ ;
+ p[i] = NUL;
+
+ convert_setup(&virp->vir_conv, p, p_enc);
+ }
+ }
+#endif
+ return viminfo_readline(virp);
+}
+
+/*
+ * Read a line from the viminfo file.
+ * Returns TRUE for end-of-file;
+ */
+ int
+viminfo_readline(virp)
+ vir_T *virp;
+{
+ return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
+}
+
+/*
+ * check string read from viminfo file
+ * remove '\n' at the end of the line
+ * - replace CTRL-V CTRL-V with CTRL-V
+ * - replace CTRL-V 'n' with '\n'
+ *
+ * Check for a long line as written by viminfo_writestring().
+ *
+ * Return the string in allocated memory (NULL when out of memory).
+ */
+/*ARGSUSED*/
+ char_u *
+viminfo_readstring(virp, off, convert)
+ vir_T *virp;
+ int off; /* offset for virp->vir_line */
+ int convert; /* convert the string */
+{
+ char_u *retval;
+ char_u *s, *d;
+ long len;
+
+ if (virp->vir_line[off] == Ctrl_V && vim_isdigit(virp->vir_line[off + 1]))
+ {
+ len = atol((char *)virp->vir_line + off + 1);
+ retval = lalloc(len, TRUE);
+ if (retval == NULL)
+ {
+ /* Line too long? File messed up? Skip next line. */
+ (void)vim_fgets(virp->vir_line, 10, virp->vir_fd);
+ return NULL;
+ }
+ (void)vim_fgets(retval, (int)len, virp->vir_fd);
+ s = retval + 1; /* Skip the leading '<' */
+ }
+ else
+ {
+ retval = vim_strsave(virp->vir_line + off);
+ if (retval == NULL)
+ return NULL;
+ s = retval;
+ }
+
+ /* Change CTRL-V CTRL-V to CTRL-V and CTRL-V n to \n in-place. */
+ d = retval;
+ while (*s != NUL && *s != '\n')
+ {
+ if (s[0] == Ctrl_V && s[1] != NUL)
+ {
+ if (s[1] == 'n')
+ *d++ = '\n';
+ else
+ *d++ = Ctrl_V;
+ s += 2;
+ }
+ else
+ *d++ = *s++;
+ }
+ *d = NUL;
+
+#ifdef FEAT_MBYTE
+ if (convert && virp->vir_conv.vc_type != CONV_NONE && *retval != NUL)
+ {
+ d = string_convert(&virp->vir_conv, retval, NULL);
+ if (d != NULL)
+ {
+ vim_free(retval);
+ retval = d;
+ }
+ }
+#endif
+
+ return retval;
+}
+
+/*
+ * write string to viminfo file
+ * - replace CTRL-V with CTRL-V CTRL-V
+ * - replace '\n' with CTRL-V 'n'
+ * - add a '\n' at the end
+ *
+ * For a long line:
+ * - write " CTRL-V <length> \n " in first line
+ * - write " < <string> \n " in second line
+ */
+ void
+viminfo_writestring(fd, p)
+ FILE *fd;
+ char_u *p;
+{
+ int c;
+ char_u *s;
+ int len = 0;
+
+ for (s = p; *s != NUL; ++s)
+ {
+ if (*s == Ctrl_V || *s == '\n')
+ ++len;
+ ++len;
+ }
+
+ /* If the string will be too long, write its length and put it in the next
+ * line. Take into account that some room is needed for what comes before
+ * the string (e.g., variable name). Add something to the length for the
+ * '<', NL and trailing NUL. */
+ if (len > LSIZE / 2)
+ fprintf(fd, IF_EB("\026%d\n<", CTRL_V_STR "%d\n<"), len + 3);
+
+ while ((c = *p++) != NUL)
+ {
+ if (c == Ctrl_V || c == '\n')
+ {
+ putc(Ctrl_V, fd);
+ if (c == '\n')
+ c = 'n';
+ }
+ putc(c, fd);
+ }
+ putc('\n', fd);
+}
+#endif /* FEAT_VIMINFO */
+
+/*
+ * Implementation of ":fixdel", also used by get_stty().
+ * <BS> resulting <Del>
+ * ^? ^H
+ * not ^? ^?
+ */
+/*ARGSUSED*/
+ void
+do_fixdel(eap)
+ exarg_T *eap;
+{
+ char_u *p;
+
+ p = find_termcode((char_u *)"kb");
+ add_termcode((char_u *)"kD", p != NULL
+ && *p == DEL ? (char_u *)CTRL_H_STR : DEL_STR, FALSE);
+}
+
+ void
+print_line_no_prefix(lnum, use_number)
+ linenr_T lnum;
+ int use_number;
+{
+ char_u numbuf[20];
+
+ if (curwin->w_p_nu || use_number)
+ {
+ sprintf((char *)numbuf, "%7ld ", (long)lnum);
+ msg_puts_attr(numbuf, hl_attr(HLF_N)); /* Highlight line nrs */
+ }
+ msg_prt_line(ml_get(lnum));
+}
+
+/*
+ * Print a text line. Also in silent mode ("ex -s").
+ */
+ void
+print_line(lnum, use_number)
+ linenr_T lnum;
+ int use_number;
+{
+ int save_silent = silent_mode;
+
+ silent_mode = FALSE;
+ msg_start();
+ print_line_no_prefix(lnum, use_number);
+ if (save_silent)
+ {
+ msg_putchar('\n');
+ cursor_on(); /* msg_start() switches it off */
+ out_flush();
+ silent_mode = save_silent;
+ }
+}
+
+/*
+ * ":file[!] [fname]".
+ */
+ void
+ex_file(eap)
+ exarg_T *eap;
+{
+ char_u *fname, *sfname, *xfname;
+ buf_T *buf;
+
+ if (*eap->arg != NUL)
+ {
+#ifdef FEAT_AUTOCMD
+ buf = curbuf;
+ apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
+ /* buffer changed, don't change name now */
+ if (buf != curbuf)
+ return;
+# ifdef FEAT_EVAL
+ if (aborting()) /* autocmds may abort script processing */
+ return;
+# endif
+#endif
+ /*
+ * The name of the current buffer will be changed.
+ * A new (unlisted) buffer entry needs to be made to hold the old file
+ * name, which will become the alternate file name.
+ */
+ fname = curbuf->b_ffname;
+ sfname = curbuf->b_sfname;
+ xfname = curbuf->b_fname;
+ curbuf->b_ffname = NULL;
+ curbuf->b_sfname = NULL;
+ if (setfname(curbuf, eap->arg, NULL, TRUE) == FAIL)
+ {
+ curbuf->b_ffname = fname;
+ curbuf->b_sfname = sfname;
+ return;
+ }
+ curbuf->b_flags |= BF_NOTEDITED;
+ buf = buflist_new(fname, xfname, curwin->w_cursor.lnum, 0);
+ if (buf != NULL)
+ curwin->w_alt_fnum = buf->b_fnum;
+ vim_free(fname);
+ vim_free(sfname);
+#ifdef FEAT_AUTOCMD
+ apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
+#endif
+ }
+ /* print full file name if :cd used */
+ fileinfo(FALSE, FALSE, eap->forceit);
+}
+
+/*
+ * ":update".
+ */
+ void
+ex_update(eap)
+ exarg_T *eap;
+{
+ if (curbufIsChanged())
+ (void)do_write(eap);
+}
+
+/*
+ * ":write" and ":saveas".
+ */
+ void
+ex_write(eap)
+ exarg_T *eap;
+{
+ if (eap->usefilter) /* input lines to shell command */
+ do_bang(1, eap, FALSE, TRUE, FALSE);
+ else
+ (void)do_write(eap);
+}
+
+/*
+ * write current buffer to file 'eap->arg'
+ * if 'eap->append' is TRUE, append to the file
+ *
+ * if *eap->arg == NUL write to current file
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+do_write(eap)
+ exarg_T *eap;
+{
+ int other;
+ char_u *fname = NULL; /* init to shut up gcc */
+ char_u *ffname;
+ int retval = FAIL;
+ char_u *free_fname = NULL;
+#ifdef FEAT_BROWSE
+ char_u *browse_file = NULL;
+#endif
+ buf_T *alt_buf = NULL;
+
+ if (not_writing()) /* check 'write' option */
+ return FAIL;
+
+ ffname = eap->arg;
+#ifdef FEAT_BROWSE
+ if (cmdmod.browse)
+ {
+ browse_file = do_browse(TRUE, (char_u *)_("Save As"), ffname,
+ NULL, NULL, NULL, curbuf);
+ if (browse_file == NULL)
+ goto theend;
+ ffname = browse_file;
+ }
+#endif
+ if (*ffname == NUL)
+ {
+ if (eap->cmdidx == CMD_saveas)
+ {
+ EMSG(_(e_argreq));
+ goto theend;
+ }
+ other = FALSE;
+ }
+ else
+ {
+ fname = ffname;
+ free_fname = fix_fname(ffname);
+ /*
+ * When out-of-memory, keep unexpanded file name, because we MUST be
+ * able to write the file in this situation.
+ */
+ if (free_fname != NULL)
+ ffname = free_fname;
+ other = otherfile(ffname);
+ }
+
+ /*
+ * If we have a new file, put its name in the list of alternate file names.
+ */
+ if (other)
+ {
+ if (vim_strchr(p_cpo, CPO_ALTWRITE) != NULL
+ || eap->cmdidx == CMD_saveas)
+ alt_buf = setaltfname(ffname, fname, (linenr_T)1);
+ else
+ alt_buf = buflist_findname(ffname);
+ if (alt_buf != NULL && alt_buf->b_ml.ml_mfp != NULL)
+ {
+ /* Overwriting a file that is loaded in another buffer is not a
+ * good idea. */
+ EMSG(_("E139: File is loaded in another buffer"));
+ goto theend;
+ }
+ }
+
+ /*
+ * Writing to the current file is not allowed in readonly mode
+ * and a file name is required.
+ * "nofile" and "nowrite" buffers cannot be written implicitly either.
+ */
+ if (!other && (
+#ifdef FEAT_QUICKFIX
+ bt_dontwrite_msg(curbuf) ||
+#endif
+ check_fname() == FAIL || check_readonly(&eap->forceit, curbuf)))
+ goto theend;
+
+ if (!other)
+ {
+ ffname = curbuf->b_ffname;
+ fname = curbuf->b_fname;
+ /*
+ * Not writing the whole file is only allowed with '!'.
+ */
+ if ( (eap->line1 != 1
+ || eap->line2 != curbuf->b_ml.ml_line_count)
+ && !eap->forceit
+ && !eap->append
+ && !p_wa)
+ {
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if (p_confirm || cmdmod.confirm)
+ {
+ if (vim_dialog_yesno(VIM_QUESTION, NULL,
+ (char_u *)_("Write partial file?"), 2) != VIM_YES)
+ goto theend;
+ eap->forceit = TRUE;
+ }
+ else
+#endif
+ {
+ EMSG(_("E140: Use ! to write partial buffer"));
+ goto theend;
+ }
+ }
+ }
+
+ if (check_overwrite(eap, curbuf, fname, ffname, other) == OK)
+ {
+ if (eap->cmdidx == CMD_saveas && alt_buf != NULL)
+ {
+#ifdef FEAT_AUTOCMD
+ buf_T *was_curbuf = curbuf;
+
+ apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
+# ifdef FEAT_EVAL
+ if (curbuf != was_curbuf || aborting())
+# else
+ if (curbuf != was_curbuf)
+# endif
+ {
+ /* buffer changed, don't change name now */
+ retval = FAIL;
+ goto theend;
+ }
+#endif
+ /* Exchange the file names for the current and the alternate
+ * buffer. This makes it look like we are now editing the buffer
+ * under the new name. Must be done before buf_write(), because
+ * if there is no file name and 'cpo' contains 'F', it will set
+ * the file name. */
+ fname = alt_buf->b_fname;
+ alt_buf->b_fname = curbuf->b_fname;
+ curbuf->b_fname = fname;
+ fname = alt_buf->b_ffname;
+ alt_buf->b_ffname = curbuf->b_ffname;
+ curbuf->b_ffname = fname;
+ fname = alt_buf->b_sfname;
+ alt_buf->b_sfname = curbuf->b_sfname;
+ curbuf->b_sfname = fname;
+ buf_name_changed(curbuf);
+#ifdef FEAT_AUTOCMD
+ apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
+ if (!alt_buf->b_p_bl)
+ {
+ alt_buf->b_p_bl = TRUE;
+ apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, alt_buf);
+ }
+# ifdef FEAT_EVAL
+ if (curbuf != was_curbuf || aborting())
+# else
+ if (curbuf != was_curbuf)
+# endif
+ {
+ /* buffer changed, don't write the file */
+ retval = FAIL;
+ goto theend;
+ }
+#endif
+ }
+
+ retval = buf_write(curbuf, ffname, fname, eap->line1, eap->line2,
+ eap, eap->append, eap->forceit, TRUE, FALSE);
+ }
+
+theend:
+#ifdef FEAT_BROWSE
+ vim_free(browse_file);
+#endif
+ vim_free(free_fname);
+ return retval;
+}
+
+/*
+ * Check if it is allowed to overwrite a file. If b_flags has BF_NOTEDITED,
+ * BF_NEW or BF_READERR, check for overwriting current file.
+ * May set eap->forceit if a dialog says it's OK to overwrite.
+ * Return OK if it's OK, FAIL if it is not.
+ */
+/*ARGSUSED*/
+ static int
+check_overwrite(eap, buf, fname, ffname, other)
+ exarg_T *eap;
+ buf_T *buf;
+ char_u *fname; /* file name to be used (can differ from
+ buf->ffname) */
+ char_u *ffname; /* full path version of fname */
+ int other; /* writing under other name */
+{
+ /*
+ * write to other file or b_flags set or not writing the whole file:
+ * overwriting only allowed with '!'
+ */
+ if ( (other
+ || (buf->b_flags & BF_NOTEDITED)
+ || ((buf->b_flags & BF_NEW)
+ && vim_strchr(p_cpo, CPO_OVERNEW) == NULL)
+ || (buf->b_flags & BF_READERR))
+ && !eap->forceit
+ && !eap->append
+ && !p_wa
+ && vim_fexists(ffname))
+ {
+#ifdef UNIX
+ /* with UNIX it is possible to open a directory */
+ if (mch_isdir(ffname))
+ {
+ EMSG2(_(e_isadir2), ffname);
+ return FAIL;
+ }
+#endif
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if (p_confirm || cmdmod.confirm)
+ {
+ char_u buff[IOSIZE];
+
+ dialog_msg(buff, _("Overwrite existing file \"%.*s\"?"), fname);
+ if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) != VIM_YES)
+ return FAIL;
+ eap->forceit = TRUE;
+ }
+ else
+#endif
+ {
+ EMSG(_(e_exists));
+ return FAIL;
+ }
+ }
+ return OK;
+}
+
+/*
+ * Handle ":wnext", ":wNext" and ":wprevious" commands.
+ */
+ void
+ex_wnext(eap)
+ exarg_T *eap;
+{
+ int i;
+
+ if (eap->cmd[1] == 'n')
+ i = curwin->w_arg_idx + (int)eap->line2;
+ else
+ i = curwin->w_arg_idx - (int)eap->line2;
+ eap->line1 = 1;
+ eap->line2 = curbuf->b_ml.ml_line_count;
+ if (do_write(eap) != FAIL)
+ do_argfile(eap, i);
+}
+
+/*
+ * ":wall", ":wqall" and ":xall": Write all changed files (and exit).
+ */
+ void
+do_wqall(eap)
+ exarg_T *eap;
+{
+ buf_T *buf;
+ int error = 0;
+ int save_forceit = eap->forceit;
+
+ if (eap->cmdidx == CMD_xall || eap->cmdidx == CMD_wqall)
+ exiting = TRUE;
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ if (bufIsChanged(buf))
+ {
+ /*
+ * Check if there is a reason the buffer cannot be written:
+ * 1. if the 'write' option is set
+ * 2. if there is no file name (even after browsing)
+ * 3. if the 'readonly' is set (even after a dialog)
+ * 4. if overwriting is allowed (even after a dialog)
+ */
+ if (not_writing())
+ {
+ ++error;
+ break;
+ }
+#ifdef FEAT_BROWSE
+ /* ":browse wall": ask for file name if there isn't one */
+ if (buf->b_ffname == NULL && cmdmod.browse)
+ browse_save_fname(buf);
+#endif
+ if (buf->b_ffname == NULL)
+ {
+ EMSGN(_("E141: No file name for buffer %ld"), (long)buf->b_fnum);
+ ++error;
+ }
+ else if (check_readonly(&eap->forceit, buf)
+ || check_overwrite(eap, buf, buf->b_fname, buf->b_ffname,
+ FALSE) == FAIL)
+ {
+ ++error;
+ }
+ else
+ {
+ if (buf_write_all(buf, eap->forceit) == FAIL)
+ ++error;
+#ifdef FEAT_AUTOCMD
+ /* an autocommand may have deleted the buffer */
+ if (!buf_valid(buf))
+ buf = firstbuf;
+#endif
+ }
+ eap->forceit = save_forceit; /* check_overwrite() may set it */
+ }
+ }
+ if (exiting)
+ {
+ if (!error)
+ getout(0); /* exit Vim */
+ not_exiting();
+ }
+}
+
+/*
+ * Check the 'write' option.
+ * Return TRUE and give a message when it's not st.
+ */
+ int
+not_writing()
+{
+ if (p_write)
+ return FALSE;
+ EMSG(_("E142: File not written: Writing is disabled by 'write' option"));
+ return TRUE;
+}
+
+/*
+ * Check if a buffer is read-only. Ask for overruling in a dialog.
+ * Return TRUE and give an error message when the buffer is readonly.
+ */
+ static int
+check_readonly(forceit, buf)
+ int *forceit;
+ buf_T *buf;
+{
+ if (!*forceit && buf->b_p_ro)
+ {
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if ((p_confirm || cmdmod.confirm) && buf->b_fname != NULL)
+ {
+ char_u buff[IOSIZE];
+
+ dialog_msg(buff, _("'readonly' option is set for \"%.*s\".\nDo you wish to write anyway?"),
+ buf->b_fname);
+
+ if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) == VIM_YES)
+ {
+ /* Set forceit, to force the writing of a readonly file */
+ *forceit = TRUE;
+ return FALSE;
+ }
+ else
+ return TRUE;
+ }
+ else
+#endif
+ EMSG(_(e_readonly));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * try to abandon current file and edit a new or existing file
+ * 'fnum' is the number of the file, if zero use ffname/sfname
+ *
+ * return 1 for "normal" error, 2 for "not written" error, 0 for success
+ * -1 for succesfully opening another file
+ * 'lnum' is the line number for the cursor in the new file (if non-zero).
+ */
+ int
+getfile(fnum, ffname, sfname, setpm, lnum, forceit)
+ int fnum;
+ char_u *ffname;
+ char_u *sfname;
+ int setpm;
+ linenr_T lnum;
+ int forceit;
+{
+ int other;
+ int retval;
+ char_u *free_me = NULL;
+
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ return 1;
+#endif
+
+ if (fnum == 0)
+ {
+ /* make ffname full path, set sfname */
+ fname_expand(curbuf, &ffname, &sfname);
+ other = otherfile(ffname);
+ free_me = ffname; /* has been allocated, free() later */
+ }
+ else
+ other = (fnum != curbuf->b_fnum);
+
+ if (other)
+ ++no_wait_return; /* don't wait for autowrite message */
+ if (other && !forceit && curbuf->b_nwindows == 1 && !P_HID(curbuf)
+ && curbufIsChanged() && autowrite(curbuf, forceit) == FAIL)
+ {
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if (p_confirm && p_write)
+ dialog_changed(curbuf, FALSE);
+ if (curbufIsChanged())
+#endif
+ {
+ if (other)
+ --no_wait_return;
+ EMSG(_(e_nowrtmsg));
+ retval = 2; /* file has been changed */
+ goto theend;
+ }
+ }
+ if (other)
+ --no_wait_return;
+ if (setpm)
+ setpcmark();
+ if (!other)
+ {
+ if (lnum != 0)
+ curwin->w_cursor.lnum = lnum;
+ check_cursor_lnum();
+ beginline(BL_SOL | BL_FIX);
+ retval = 0; /* it's in the same file */
+ }
+ else if (do_ecmd(fnum, ffname, sfname, NULL, lnum,
+ (P_HID(curbuf) ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0)) == OK)
+ retval = -1; /* opened another file */
+ else
+ retval = 1; /* error encountered */
+
+theend:
+ vim_free(free_me);
+ return retval;
+}
+
+/*
+ * start editing a new file
+ *
+ * fnum: file number; if zero use ffname/sfname
+ * ffname: the file name
+ * - full path if sfname used,
+ * - any file name if sfname is NULL
+ * - empty string to re-edit with the same file name (but may be
+ * in a different directory)
+ * - NULL to start an empty buffer
+ * sfname: the short file name (or NULL)
+ * eap: contains the command to be executed after loading the file and
+ * forced 'ff' and 'fenc'
+ * newlnum: if > 0: put cursor on this line number (if possible)
+ * if ECMD_LASTL: use last position in loaded file
+ * if ECMD_LAST: use last position in all files
+ * if ECMD_ONE: use first line
+ * flags:
+ * ECMD_HIDE: if TRUE don't free the current buffer
+ * ECMD_SET_HELP: set b_help flag of (new) buffer before opening file
+ * ECMD_OLDBUF: use existing buffer if it exists
+ * ECMD_FORCEIT: ! used for Ex command
+ * ECMD_ADDBUF: don't edit, just add to buffer list
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+do_ecmd(fnum, ffname, sfname, eap, newlnum, flags)
+ int fnum;
+ char_u *ffname;
+ char_u *sfname;
+ exarg_T *eap; /* can be NULL! */
+ linenr_T newlnum;
+ int flags;
+{
+ int other_file; /* TRUE if editing another file */
+ int oldbuf; /* TRUE if using existing buffer */
+#ifdef FEAT_AUTOCMD
+ int auto_buf = FALSE; /* TRUE if autocommands brought us
+ into the buffer unexpectedly */
+ char_u *new_name = NULL;
+#endif
+ buf_T *buf;
+#if defined(FEAT_AUTOCMD) || defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ buf_T *old_curbuf = curbuf;
+#endif
+ char_u *free_fname = NULL;
+#ifdef FEAT_BROWSE
+ char_u *browse_file = NULL;
+#endif
+ int retval = FAIL;
+ long n;
+ linenr_T lnum;
+ linenr_T topline = 0;
+ int newcol = -1;
+ int solcol = -1;
+ pos_T *pos;
+#ifdef FEAT_SUN_WORKSHOP
+ char_u *cp;
+#endif
+ char_u *command = NULL;
+
+ if (eap != NULL)
+ command = eap->do_ecmd_cmd;
+
+ if (fnum != 0)
+ {
+ if (fnum == curbuf->b_fnum) /* file is already being edited */
+ return OK; /* nothing to do */
+ other_file = TRUE;
+ }
+ else
+ {
+#ifdef FEAT_BROWSE
+ if (cmdmod.browse)
+ {
+ browse_file = do_browse(FALSE, (char_u *)_("Edit File"), ffname,
+ NULL, NULL, NULL, curbuf);
+ if (browse_file == NULL)
+ goto theend;
+ ffname = browse_file;
+ }
+#endif
+ /* if no short name given, use ffname for short name */
+ if (sfname == NULL)
+ sfname = ffname;
+#ifdef USE_FNAME_CASE
+# ifdef USE_LONG_FNAME
+ if (USE_LONG_FNAME)
+# endif
+ fname_case(sfname, 0); /* set correct case for short file name */
+#endif
+
+#ifdef FEAT_LISTCMDS
+ if ((flags & ECMD_ADDBUF) && (ffname == NULL || *ffname == NUL))
+ goto theend;
+#endif
+
+ if (ffname == NULL)
+ other_file = TRUE;
+ /* there is no file name */
+ else if (*ffname == NUL && curbuf->b_ffname == NULL)
+ other_file = FALSE;
+ else
+ {
+ if (*ffname == NUL) /* re-edit with same file name */
+ {
+ ffname = curbuf->b_ffname;
+ sfname = curbuf->b_fname;
+ }
+ free_fname = fix_fname(ffname); /* may expand to full path name */
+ if (free_fname != NULL)
+ ffname = free_fname;
+ other_file = otherfile(ffname);
+#ifdef FEAT_SUN_WORKSHOP
+ if (usingSunWorkShop && p_acd
+ && (cp = vim_strrchr(sfname, '/')) != NULL)
+ sfname = ++cp;
+#endif
+ }
+ }
+
+ /*
+ * if the file was changed we may not be allowed to abandon it
+ * - if we are going to re-edit the same file
+ * - or if we are the only window on this file and if ECMD_HIDE is FALSE
+ */
+ if ( ((!other_file && !(flags & ECMD_OLDBUF))
+ || (curbuf->b_nwindows == 1
+ && !(flags & (ECMD_HIDE | ECMD_ADDBUF))))
+ && check_changed(curbuf, p_awa, !other_file,
+ (flags & ECMD_FORCEIT), FALSE))
+ {
+ if (fnum == 0 && other_file && ffname != NULL)
+ (void)setaltfname(ffname, sfname, newlnum < 0 ? 0 : newlnum);
+ goto theend;
+ }
+
+#ifdef FEAT_VISUAL
+ /*
+ * End Visual mode before switching to another buffer, so the text can be
+ * copied into the GUI selection buffer.
+ */
+ reset_VIsual();
+#endif
+
+ /*
+ * If we are starting to edit another file, open a (new) buffer.
+ * Otherwise we re-use the current buffer.
+ */
+ if (other_file)
+ {
+#ifdef FEAT_LISTCMDS
+ if (!(flags & ECMD_ADDBUF))
+#endif
+ {
+ curwin->w_alt_fnum = curbuf->b_fnum;
+ buflist_altfpos();
+ }
+
+ if (fnum)
+ buf = buflist_findnr(fnum);
+ else
+ {
+#ifdef FEAT_LISTCMDS
+ if (flags & ECMD_ADDBUF)
+ {
+ linenr_T tlnum = 1L;
+
+ if (command != NULL)
+ {
+ tlnum = atol((char *)command);
+ if (tlnum <= 0)
+ tlnum = 1L;
+ }
+ (void)buflist_new(ffname, sfname, tlnum, BLN_LISTED);
+ goto theend;
+ }
+#endif
+ buf = buflist_new(ffname, sfname, 0L,
+ BLN_CURBUF | ((flags & ECMD_SET_HELP) ? 0 : BLN_LISTED));
+ }
+ if (buf == NULL)
+ goto theend;
+ if (buf->b_ml.ml_mfp == NULL) /* no memfile yet */
+ {
+ oldbuf = FALSE;
+ buf->b_nwindows = 0;
+ }
+ else /* existing memfile */
+ {
+ oldbuf = TRUE;
+ (void)buf_check_timestamp(buf, FALSE);
+ /* Check if autocommands made buffer invalid or changed the current
+ * buffer. */
+ if (!buf_valid(buf)
+#ifdef FEAT_AUTOCMD
+ || curbuf != old_curbuf
+#endif
+ )
+ goto theend;
+#ifdef FEAT_EVAL
+ if (aborting()) /* autocmds may abort script processing */
+ goto theend;
+#endif
+ }
+
+ /* May jump to last used line number for a loaded buffer or when asked
+ * for explicitly */
+ if ((oldbuf && newlnum == ECMD_LASTL) || newlnum == ECMD_LAST)
+ {
+ pos = buflist_findfpos(buf);
+ newlnum = pos->lnum;
+ solcol = pos->col;
+ }
+
+ /*
+ * Make the (new) buffer the one used by the current window.
+ * If the old buffer becomes unused, free it if ECMD_HIDE is FALSE.
+ * If the current buffer was empty and has no file name, curbuf
+ * is returned by buflist_new().
+ */
+ if (buf != curbuf)
+ {
+#ifdef FEAT_AUTOCMD
+ /*
+ * Be careful: The autocommands may delete any buffer and change
+ * the current buffer.
+ * - If the buffer we are going to edit is deleted, give up.
+ * - If the current buffer is deleted, prefer to load the new
+ * buffer when loading a buffer is required. This avoids
+ * loading another buffer which then must be closed again.
+ * - If we ended up in the new buffer already, need to skip a few
+ * things, set auto_buf.
+ */
+ if (buf->b_fname != NULL)
+ new_name = vim_strsave(buf->b_fname);
+ au_new_curbuf = buf;
+ apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
+ if (!buf_valid(buf)) /* new buffer has been deleted */
+ {
+ delbuf_msg(new_name); /* frees new_name */
+ goto theend;
+ }
+# ifdef FEAT_EVAL
+ if (aborting()) /* autocmds may abort script processing */
+ {
+ vim_free(new_name);
+ goto theend;
+ }
+# endif
+ if (buf == curbuf) /* already in new buffer */
+ auto_buf = TRUE;
+ else
+ {
+ if (curbuf == old_curbuf)
+#endif
+ buf_copy_options(buf, BCO_ENTER);
+
+ /* close the link to the current buffer */
+ close_buffer(curwin, curbuf,
+ (flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD);
+
+#ifdef FEAT_AUTOCMD
+# ifdef FEAT_EVAL
+ if (aborting()) /* autocmds may abort script processing */
+ {
+ vim_free(new_name);
+ goto theend;
+ }
+# endif
+ /* Be careful again, like above. */
+ if (!buf_valid(buf)) /* new buffer has been deleted */
+ {
+ delbuf_msg(new_name); /* frees new_name */
+ goto theend;
+ }
+ if (buf == curbuf) /* already in new buffer */
+ auto_buf = TRUE;
+ else
+#endif
+ {
+ curwin->w_buffer = buf;
+ curbuf = buf;
+ ++curbuf->b_nwindows;
+ /* set 'fileformat' */
+ if (*p_ffs && !oldbuf)
+ set_fileformat(default_fileformat(), OPT_LOCAL);
+ }
+
+ /* May get the window options from the last time this buffer
+ * was in this window (or another window). If not used
+ * before, reset the local window options to the global
+ * values. Also restores old folding stuff. */
+ get_winopts(buf);
+
+#ifdef FEAT_AUTOCMD
+ }
+ vim_free(new_name);
+ au_new_curbuf = NULL;
+#endif
+ }
+ else
+ ++curbuf->b_nwindows;
+
+ curwin->w_pcmark.lnum = 1;
+ curwin->w_pcmark.col = 0;
+ }
+ else /* !other_file */
+ {
+ if (
+#ifdef FEAT_LISTCMDS
+ (flags & ECMD_ADDBUF) ||
+#endif
+ check_fname() == FAIL)
+ goto theend;
+ oldbuf = (flags & ECMD_OLDBUF);
+ }
+
+ if ((flags & ECMD_SET_HELP) || keep_help_flag)
+ {
+ char_u *p;
+
+ curbuf->b_help = TRUE;
+#ifdef FEAT_QUICKFIX
+ set_string_option_direct((char_u *)"buftype", -1,
+ (char_u *)"help", OPT_FREE|OPT_LOCAL);
+#endif
+
+ /*
+ * Always set these options after jumping to a help tag, because the
+ * user may have an autocommand that gets in the way.
+ * Accept all ASCII chars for keywords, except ' ', '*', '"', '|', and
+ * latin1 word characters (for translated help files).
+ * Only set it when needed, buf_init_chartab() is some work.
+ */
+ p =
+#ifdef EBCDIC
+ (char_u *)"65-255,^*,^|,^\"";
+#else
+ (char_u *)"!-~,^*,^|,^\",192-255";
+#endif
+ if (STRCMP(curbuf->b_p_isk, p) != 0)
+ {
+ set_string_option_direct((char_u *)"isk", -1, p,
+ OPT_FREE|OPT_LOCAL);
+ check_buf_options(curbuf);
+ (void)buf_init_chartab(curbuf, FALSE);
+ }
+
+ curbuf->b_p_ts = 8; /* 'tabstop' is 8 */
+ curwin->w_p_list = FALSE; /* no list mode */
+
+ curbuf->b_p_ma = FALSE; /* not modifiable */
+ curbuf->b_p_bin = FALSE; /* reset 'bin' before reading file */
+ curwin->w_p_nu = 0; /* no line numbers */
+#ifdef FEAT_SCROLLBIND
+ curwin->w_p_scb = FALSE; /* no scroll binding */
+#endif
+#ifdef FEAT_ARABIC
+ curwin->w_p_arab = FALSE; /* no arabic mode */
+#endif
+#ifdef FEAT_RIGHTLEFT
+ curwin->w_p_rl = FALSE; /* help window is left-to-right */
+#endif
+#ifdef FEAT_FOLDING
+ curwin->w_p_fen = FALSE; /* No folding in the help window */
+#endif
+#ifdef FEAT_DIFF
+ curwin->w_p_diff = FALSE; /* No 'diff' */
+#endif
+
+#ifdef FEAT_AUTOCMD
+ buf = curbuf;
+#endif
+ set_buflisted(FALSE);
+ }
+ else
+ {
+#ifdef FEAT_AUTOCMD
+ buf = curbuf;
+#endif
+ /* Don't make a buffer listed if it's a help buffer. Useful when
+ * using CTRL-O to go back to a help file. */
+ if (!curbuf->b_help)
+ set_buflisted(TRUE);
+ }
+
+#ifdef FEAT_AUTOCMD
+ /* If autocommands change buffers under our fingers, forget about
+ * editing the file. */
+ if (buf != curbuf)
+ goto theend;
+# ifdef FEAT_EVAL
+ if (aborting()) /* autocmds may abort script processing */
+ goto theend;
+# endif
+
+ /* Since we are starting to edit a file, consider the filetype to be
+ * unset. Helps for when an autocommand changes files and expects syntax
+ * highlighting to work in the other file. */
+ did_filetype = FALSE;
+#endif
+
+/*
+ * other_file oldbuf
+ * FALSE FALSE re-edit same file, buffer is re-used
+ * FALSE TRUE re-edit same file, nothing changes
+ * TRUE FALSE start editing new file, new buffer
+ * TRUE TRUE start editing in existing buffer (nothing to do)
+ */
+ if (!other_file && !oldbuf) /* re-use the buffer */
+ {
+ set_last_cursor(curwin); /* may set b_last_cursor */
+ if (newlnum == ECMD_LAST || newlnum == ECMD_LASTL)
+ {
+ newlnum = curwin->w_cursor.lnum;
+ solcol = curwin->w_cursor.col;
+ }
+#ifdef FEAT_AUTOCMD
+ buf = curbuf;
+ if (buf->b_fname != NULL)
+ new_name = vim_strsave(buf->b_fname);
+ else
+ new_name = NULL;
+#endif
+ buf_freeall(curbuf, FALSE, FALSE); /* free all things for buffer */
+#ifdef FEAT_AUTOCMD
+ /* If autocommands deleted the buffer we were going to re-edit, give
+ * up and jump to the end. */
+ if (!buf_valid(buf))
+ {
+ delbuf_msg(new_name); /* frees new_name */
+ goto theend;
+ }
+ vim_free(new_name);
+
+ /* If autocommands change buffers under our fingers, forget about
+ * re-editing the file. Should do the buf_clear_file(), but perhaps
+ * the autocommands changed the buffer... */
+ if (buf != curbuf)
+ goto theend;
+# ifdef FEAT_EVAL
+ if (aborting()) /* autocmds may abort script processing */
+ goto theend;
+# endif
+#endif
+ buf_clear_file(curbuf);
+ curbuf->b_op_start.lnum = 0; /* clear '[ and '] marks */
+ curbuf->b_op_end.lnum = 0;
+ }
+
+/*
+ * If we get here we are sure to start editing
+ */
+ /* don't redraw until the cursor is in the right line */
+ ++RedrawingDisabled;
+
+ /* Assume success now */
+ retval = OK;
+
+ /*
+ * Reset cursor position, could be used by autocommands.
+ */
+ check_cursor();
+
+ /*
+ * Check if we are editing the w_arg_idx file in the argument list.
+ */
+ check_arg_idx(curwin);
+
+#ifdef FEAT_AUTOCMD
+ if (!auto_buf)
+#endif
+ {
+ /*
+ * Set cursor and init window before reading the file and executing
+ * autocommands. This allows for the autocommands to position the
+ * cursor.
+ */
+ win_init(curwin);
+
+#ifdef FEAT_FOLDING
+ /* It's like all lines in the buffer changed. Need to update
+ * automatic folding. */
+ foldUpdateAll(curwin);
+#endif
+
+#if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG)
+ if (p_acd && curbuf->b_ffname != NULL
+ && vim_chdirfile(curbuf->b_ffname) == OK)
+ shorten_fnames(TRUE);
+#endif
+ /*
+ * Careful: open_buffer() and apply_autocmds() may change the current
+ * buffer and window.
+ */
+ lnum = curwin->w_cursor.lnum;
+ topline = curwin->w_topline;
+ if (!oldbuf) /* need to read the file */
+ {
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ swap_exists_action = SEA_DIALOG;
+#endif
+ curbuf->b_flags |= BF_CHECK_RO; /* set/reset 'ro' flag */
+
+ /*
+ * Open the buffer and read the file.
+ */
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+ if (should_abort(open_buffer(FALSE, eap)))
+ retval = FAIL;
+#else
+ (void)open_buffer(FALSE, eap);
+#endif
+
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if (swap_exists_action == SEA_QUIT)
+ retval = FAIL;
+ handle_swap_exists(old_curbuf);
+#endif
+ }
+#ifdef FEAT_AUTOCMD
+ else
+ {
+ apply_autocmds_retval(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf,
+ &retval);
+ apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf,
+ &retval);
+ }
+ check_arg_idx(curwin);
+#endif
+
+ /*
+ * If autocommands change the cursor position or topline, we should
+ * keep it.
+ */
+ if (curwin->w_cursor.lnum != lnum)
+ {
+ newlnum = curwin->w_cursor.lnum;
+ newcol = curwin->w_cursor.col;
+ }
+ if (curwin->w_topline == topline)
+ topline = 0;
+
+ /* Even when cursor didn't move we need to recompute topline. */
+ changed_line_abv_curs();
+
+#ifdef FEAT_TITLE
+ maketitle();
+#endif
+ }
+
+#ifdef FEAT_DIFF
+ /* Tell the diff stuff that this buffer is new and/or needs updating.
+ * Also needed when re-editing the same buffer, because unloading will
+ * have removed it as a diff buffer. */
+ diff_new_buffer();
+ diff_invalidate();
+#endif
+
+ if (command == NULL)
+ {
+ if (newcol >= 0) /* position set by autocommands */
+ {
+ curwin->w_cursor.lnum = newlnum;
+ curwin->w_cursor.col = newcol;
+ check_cursor();
+ }
+ else if (newlnum > 0) /* line number from caller or old position */
+ {
+ curwin->w_cursor.lnum = newlnum;
+ check_cursor_lnum();
+ if (solcol >= 0 && !p_sol)
+ {
+ /* 'sol' is off: Use last known column. */
+ curwin->w_cursor.col = solcol;
+ check_cursor_col();
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ curwin->w_set_curswant = TRUE;
+ }
+ else
+ beginline(BL_SOL | BL_FIX);
+ }
+ else /* no line number, go to last line in Ex mode */
+ {
+ if (exmode_active)
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ beginline(BL_WHITE | BL_FIX);
+ }
+ }
+
+#ifdef FEAT_WINDOWS
+ /* Check if cursors in other windows on the same buffer are still valid */
+ check_lnums(FALSE);
+#endif
+
+ /*
+ * Did not read the file, need to show some info about the file.
+ * Do this after setting the cursor.
+ */
+ if (oldbuf
+#ifdef FEAT_AUTOCMD
+ && !auto_buf
+#endif
+ )
+ {
+ int msg_scroll_save = msg_scroll;
+
+ /* Obey the 'O' flag in 'cpoptions': overwrite any previous file
+ * message. */
+ if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
+ msg_scroll = FALSE;
+ if (!msg_scroll) /* wait a bit when overwriting an error msg */
+ check_for_delay(FALSE);
+ msg_start();
+ msg_scroll = msg_scroll_save;
+ msg_scrolled_ign = TRUE;
+
+ fileinfo(FALSE, TRUE, FALSE);
+
+ msg_scrolled_ign = FALSE;
+ }
+
+ if (command != NULL)
+ do_cmdline(command, NULL, NULL, DOCMD_VERBOSE);
+
+#ifdef FEAT_KEYMAP
+ if (curbuf->b_kmap_state & KEYMAP_INIT)
+ keymap_init();
+#endif
+
+ --RedrawingDisabled;
+ if (!skip_redraw)
+ {
+ n = p_so;
+ if (topline == 0 && command == NULL)
+ p_so = 999; /* force cursor halfway the window */
+ update_topline();
+#ifdef FEAT_SCROLLBIND
+ curwin->w_scbind_pos = curwin->w_topline;
+#endif
+ p_so = n;
+ redraw_curbuf_later(NOT_VALID); /* redraw this buffer later */
+ }
+
+ if (p_im)
+ need_start_insertmode = TRUE;
+
+#if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG)
+ /* Change directories when the acd option is set on. */
+ if (p_acd && curbuf->b_ffname != NULL
+ && vim_chdirfile(curbuf->b_ffname) == OK)
+ shorten_fnames(TRUE);
+
+ if (gui.in_use && curbuf->b_ffname != NULL)
+ {
+# ifdef FEAT_SUN_WORKSHOP
+ if (usingSunWorkShop)
+ workshop_file_opened((char *)curbuf->b_ffname, curbuf->b_p_ro);
+# endif
+# ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ netbeans_file_opened((char *)curbuf->b_ffname);
+# endif
+ }
+#endif
+
+theend:
+#ifdef FEAT_BROWSE
+ vim_free(browse_file);
+#endif
+ vim_free(free_fname);
+ return retval;
+}
+
+#ifdef FEAT_AUTOCMD
+ static void
+delbuf_msg(name)
+ char_u *name;
+{
+ EMSG2(_("E143: Autocommands unexpectedly deleted new buffer %s"),
+ name == NULL ? (char_u *)"" : name);
+ vim_free(name);
+ au_new_curbuf = NULL;
+}
+#endif
+
+/*
+ * ":insert" and ":append", also used by ":change"
+ */
+ void
+ex_append(eap)
+ exarg_T *eap;
+{
+ char_u *theline;
+ int did_undo = FALSE;
+ linenr_T lnum = eap->line2;
+
+ if (eap->cmdidx != CMD_append)
+ --lnum;
+
+ State = INSERT; /* behave like in Insert mode */
+ if (curbuf->b_p_iminsert == B_IMODE_LMAP)
+ State |= LANGMAP;
+ while (1)
+ {
+ msg_scroll = TRUE;
+ need_wait_return = FALSE;
+ if (eap->getline == NULL)
+ theline = getcmdline(
+#ifdef FEAT_EVAL
+ eap->cstack->cs_whilelevel > 0 ? -1 :
+#endif
+ NUL, 0L, 0);
+ else
+ theline = eap->getline(
+#ifdef FEAT_EVAL
+ eap->cstack->cs_whilelevel > 0 ? -1 :
+#endif
+ NUL, eap->cookie, 0);
+ lines_left = Rows - 1;
+ if (theline == NULL || (theline[0] == '.' && theline[1] == NUL)
+ || (!did_undo && u_save(lnum, lnum + 1) == FAIL))
+ {
+ vim_free(theline);
+ break;
+ }
+
+ did_undo = TRUE;
+ ml_append(lnum, theline, (colnr_T)0, FALSE);
+ appended_lines_mark(lnum, 1L);
+
+ vim_free(theline);
+ ++lnum;
+ msg_didout = TRUE; /* also scroll for empty line */
+ }
+ State = NORMAL;
+
+ /* "start" is set to eap->line2+1 unless that position is invalid (when
+ * eap->line2 pointed to the end of the buffer and nothig was appended)
+ * "end" is set to lnum when something has been appended, otherwise
+ * it is the same than "start" -- Acevedo */
+ curbuf->b_op_start.lnum = (eap->line2 < curbuf->b_ml.ml_line_count) ?
+ eap->line2 + 1 : curbuf->b_ml.ml_line_count;
+ if (eap->cmdidx != CMD_append)
+ --curbuf->b_op_start.lnum;
+ curbuf->b_op_end.lnum = (eap->line2 < lnum)
+ ? lnum : curbuf->b_op_start.lnum;
+ curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+ curwin->w_cursor.lnum = lnum;
+ check_cursor_lnum();
+ beginline(BL_SOL | BL_FIX);
+
+ need_wait_return = FALSE; /* don't use wait_return() now */
+ ex_no_reprint = TRUE;
+}
+
+/*
+ * ":change"
+ */
+ void
+ex_change(eap)
+ exarg_T *eap;
+{
+ linenr_T lnum;
+
+ if (eap->line2 >= eap->line1
+ && u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
+ return;
+
+ for (lnum = eap->line2; lnum >= eap->line1; --lnum)
+ {
+ if (curbuf->b_ml.ml_flags & ML_EMPTY) /* nothing to delete */
+ break;
+ ml_delete(eap->line1, FALSE);
+ }
+ deleted_lines_mark(eap->line1, (long)(eap->line2 - lnum));
+
+ /* ":append" on the line above the deleted lines. */
+ eap->line2 = eap->line1;
+ ex_append(eap);
+}
+
+ void
+ex_z(eap)
+ exarg_T *eap;
+{
+ char_u *x;
+ int bigness = curwin->w_height - 3;
+ char_u kind;
+ int numbered = FALSE;
+ int minus = 0;
+ linenr_T start, end, curs, i;
+ int j;
+ linenr_T lnum = eap->line2;
+
+ if (bigness < 1)
+ bigness = 1;
+
+ x = eap->arg;
+ if (*x == '#')
+ {
+ numbered = TRUE;
+ ++x;
+ }
+
+ kind = *x;
+ if (kind == '-' || kind == '+' || kind == '=' || kind == '^' || kind == '.')
+ ++x;
+
+ if (*x != 0)
+ {
+ if (!VIM_ISDIGIT(*x))
+ {
+ EMSG(_("E144: non-numeric argument to :z"));
+ return;
+ }
+ else
+ bigness = atoi((char *)x);
+ }
+
+ switch (kind)
+ {
+ case '-':
+ start = lnum - bigness;
+ end = lnum;
+ curs = lnum;
+ break;
+
+ case '=':
+ start = lnum - bigness / 2 + 1;
+ end = lnum + bigness / 2 - 1;
+ curs = lnum;
+ minus = 1;
+ break;
+
+ case '^':
+ start = lnum - bigness * 2;
+ end = lnum - bigness;
+ curs = lnum - bigness;
+ break;
+
+ case '.':
+ start = lnum - bigness / 2;
+ end = lnum + bigness / 2;
+ curs = end;
+ break;
+
+ default: /* '+' */
+ start = lnum;
+ end = lnum + bigness;
+ curs = end;
+ break;
+ }
+
+ if (start < 1)
+ start = 1;
+
+ if (end > curbuf->b_ml.ml_line_count)
+ end = curbuf->b_ml.ml_line_count;
+
+ if (curs > curbuf->b_ml.ml_line_count)
+ curs = curbuf->b_ml.ml_line_count;
+
+ for (i = start; i <= end; i++)
+ {
+ if (minus && i == lnum)
+ {
+ msg_putchar('\n');
+
+ for (j = 1; j < Columns; j++)
+ msg_putchar('-');
+ }
+
+ print_line(i, numbered);
+
+ if (minus && i == lnum)
+ {
+ msg_putchar('\n');
+
+ for (j = 1; j < Columns; j++)
+ msg_putchar('-');
+ }
+ }
+
+ curwin->w_cursor.lnum = curs;
+ ex_no_reprint = TRUE;
+}
+
+/*
+ * Check if the restricted flag is set.
+ * If so, give an error message and return TRUE.
+ * Otherwise, return FALSE.
+ */
+ int
+check_restricted()
+{
+ if (restricted)
+ {
+ EMSG(_("E145: Shell commands not allowed in rvim"));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Check if the secure flag is set (.exrc or .vimrc in current directory).
+ * If so, give an error message and return TRUE.
+ * Otherwise, return FALSE.
+ */
+ int
+check_secure()
+{
+ if (secure)
+ {
+ secure = 2;
+ EMSG(_(e_curdir));
+ return TRUE;
+ }
+#ifdef HAVE_SANDBOX
+ /*
+ * In the sandbox more things are not allowed, including the things
+ * disallowed in secure mode.
+ */
+ if (sandbox != 0)
+ {
+ EMSG(_(e_sandbox));
+ return TRUE;
+ }
+#endif
+ return FALSE;
+}
+
+static char_u *old_sub = NULL; /* previous substitute pattern */
+static int global_need_beginline; /* call beginline() after ":g" */
+
+/*
+ * When ":global" is used to number of substitutions and changed lines is
+ * accumulated until it's finished.
+ */
+static long sub_nsubs; /* total number of substitutions */
+static linenr_T sub_nlines; /* total number of lines changed */
+
+/* do_sub()
+ *
+ * Perform a substitution from line eap->line1 to line eap->line2 using the
+ * command pointed to by eap->arg which should be of the form:
+ *
+ * /pattern/substitution/{flags}
+ *
+ * The usual escapes are supported as described in the regexp docs.
+ */
+ void
+do_sub(eap)
+ exarg_T *eap;
+{
+ linenr_T lnum;
+ long i = 0;
+ regmmatch_T regmatch;
+ static int do_all = FALSE; /* do multiple substitutions per line */
+ static int do_ask = FALSE; /* ask for confirmation */
+ static int do_error = TRUE; /* if false, ignore errors */
+ static int do_print = FALSE; /* print last line with subs. */
+ static int do_ic = 0; /* ignore case flag */
+ char_u *pat = NULL, *sub = NULL; /* init for GCC */
+ int delimiter;
+ int sublen;
+ int got_quit = FALSE;
+ int got_match = FALSE;
+ int temp;
+ int which_pat;
+ char_u *cmd;
+ int save_State;
+ linenr_T first_line = 0; /* first changed line */
+ linenr_T last_line= 0; /* below last changed line AFTER the
+ * change */
+ linenr_T old_line_count = curbuf->b_ml.ml_line_count;
+ linenr_T line2;
+ long nmatch; /* number of lines in match */
+ linenr_T sub_firstlnum; /* nr of first sub line */
+ char_u *sub_firstline; /* allocated copy of first sub line */
+
+ cmd = eap->arg;
+ if (!global_busy)
+ {
+ sub_nsubs = 0;
+ sub_nlines = 0;
+ }
+
+#ifdef FEAT_FKMAP /* reverse the flow of the Farsi characters */
+ if (p_altkeymap && curwin->w_p_rl)
+ lrF_sub(cmd);
+#endif
+
+ if (eap->cmdidx == CMD_tilde)
+ which_pat = RE_LAST; /* use last used regexp */
+ else
+ which_pat = RE_SUBST; /* use last substitute regexp */
+
+ /* new pattern and substitution */
+ if (eap->cmd[0] == 's' && *cmd != NUL && !vim_iswhite(*cmd)
+ && vim_strchr((char_u *)"0123456789cegriIp|\"", *cmd) == NULL)
+ {
+ /* don't accept alphanumeric for separator */
+ if (isalpha(*cmd))
+ {
+ EMSG(_("E146: Regular expressions can't be delimited by letters"));
+ return;
+ }
+ /*
+ * undocumented vi feature:
+ * "\/sub/" and "\?sub?" use last used search pattern (almost like
+ * //sub/r). "\&sub&" use last substitute pattern (like //sub/).
+ */
+ if (*cmd == '\\')
+ {
+ ++cmd;
+ if (vim_strchr((char_u *)"/?&", *cmd) == NULL)
+ {
+ EMSG(_(e_backslash));
+ return;
+ }
+ if (*cmd != '&')
+ which_pat = RE_SEARCH; /* use last '/' pattern */
+ pat = (char_u *)""; /* empty search pattern */
+ delimiter = *cmd++; /* remember delimiter character */
+ }
+ else /* find the end of the regexp */
+ {
+ which_pat = RE_LAST; /* use last used regexp */
+ delimiter = *cmd++; /* remember delimiter character */
+ pat = cmd; /* remember start of search pat */
+ cmd = skip_regexp(cmd, delimiter, p_magic, &eap->arg);
+ if (cmd[0] == delimiter) /* end delimiter found */
+ *cmd++ = NUL; /* replace it with a NUL */
+ }
+
+ /*
+ * Small incompatibility: vi sees '\n' as end of the command, but in
+ * Vim we want to use '\n' to find/substitute a NUL.
+ */
+ sub = cmd; /* remember the start of the substitution */
+
+ while (cmd[0])
+ {
+ if (cmd[0] == delimiter) /* end delimiter found */
+ {
+ *cmd++ = NUL; /* replace it with a NUL */
+ break;
+ }
+ if (cmd[0] == '\\' && cmd[1] != 0) /* skip escaped characters */
+ ++cmd;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ cmd += (*mb_ptr2len_check)(cmd);
+ else
+#endif
+ ++cmd;
+ }
+
+ if (!eap->skip)
+ {
+ vim_free(old_sub);
+ old_sub = vim_strsave(sub);
+ }
+ }
+ else if (!eap->skip) /* use previous pattern and substitution */
+ {
+ if (old_sub == NULL) /* there is no previous command */
+ {
+ EMSG(_(e_nopresub));
+ return;
+ }
+ pat = NULL; /* search_regcomp() will use previous pattern */
+ sub = old_sub;
+ }
+
+ /*
+ * Find trailing options. When '&' is used, keep old options.
+ */
+ if (*cmd == '&')
+ ++cmd;
+ else
+ {
+ if (!p_ed)
+ {
+ if (p_gd) /* default is global on */
+ do_all = TRUE;
+ else
+ do_all = FALSE;
+ do_ask = FALSE;
+ }
+ do_error = TRUE;
+ do_print = FALSE;
+ do_ic = 0;
+ }
+ while (*cmd)
+ {
+ /*
+ * Note that 'g' and 'c' are always inverted, also when p_ed is off.
+ * 'r' is never inverted.
+ */
+ if (*cmd == 'g')
+ do_all = !do_all;
+ else if (*cmd == 'c')
+ do_ask = !do_ask;
+ else if (*cmd == 'e')
+ do_error = !do_error;
+ else if (*cmd == 'r') /* use last used regexp */
+ which_pat = RE_LAST;
+ else if (*cmd == 'p')
+ do_print = TRUE;
+ else if (*cmd == 'i') /* ignore case */
+ do_ic = 'i';
+ else if (*cmd == 'I') /* don't ignore case */
+ do_ic = 'I';
+ else
+ break;
+ ++cmd;
+ }
+
+ /*
+ * check for a trailing count
+ */
+ cmd = skipwhite(cmd);
+ if (VIM_ISDIGIT(*cmd))
+ {
+ i = getdigits(&cmd);
+ if (i <= 0 && !eap->skip && do_error)
+ {
+ EMSG(_(e_zerocount));
+ return;
+ }
+ eap->line1 = eap->line2;
+ eap->line2 += i - 1;
+ if (eap->line2 > curbuf->b_ml.ml_line_count)
+ eap->line2 = curbuf->b_ml.ml_line_count;
+ }
+
+ /*
+ * check for trailing command or garbage
+ */
+ cmd = skipwhite(cmd);
+ if (*cmd && *cmd != '"') /* if not end-of-line or comment */
+ {
+ eap->nextcmd = check_nextcmd(cmd);
+ if (eap->nextcmd == NULL)
+ {
+ EMSG(_(e_trailing));
+ return;
+ }
+ }
+
+ if (eap->skip) /* not executing commands, only parsing */
+ return;
+
+ if (search_regcomp(pat, RE_SUBST, which_pat, SEARCH_HIS, &regmatch) == FAIL)
+ {
+ if (do_error)
+ EMSG(_(e_invcmd));
+ return;
+ }
+
+ /* the 'i' or 'I' flag overrules 'ignorecase' and 'smartcase' */
+ if (do_ic == 'i')
+ regmatch.rmm_ic = TRUE;
+ else if (do_ic == 'I')
+ regmatch.rmm_ic = FALSE;
+
+ sub_firstline = NULL;
+
+ /*
+ * ~ in the substitute pattern is replaced with the old pattern.
+ * We do it here once to avoid it to be replaced over and over again.
+ * But don't do it when it starts with "\=", then it's an expression.
+ */
+ if (!(sub[0] == '\\' && sub[1] == '='))
+ sub = regtilde(sub, p_magic);
+
+ /*
+ * Check for a match on each line.
+ */
+ line2 = eap->line2;
+ for (lnum = eap->line1; lnum <= line2 && !(got_quit
+#if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
+ || aborting()
+#endif
+ ); ++lnum)
+ {
+ sub_firstlnum = lnum;
+ nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, lnum, (colnr_T)0);
+ if (nmatch)
+ {
+ colnr_T copycol;
+ colnr_T matchcol;
+ colnr_T prev_matchcol = MAXCOL;
+ char_u *new_end, *new_start = NULL;
+ unsigned new_start_len = 0;
+ char_u *p1;
+ int did_sub = FALSE;
+ int lastone;
+ unsigned len, needed_len;
+ long nmatch_tl = 0; /* nr of lines matched below lnum */
+ int do_again; /* do it again after joining lines */
+
+ /*
+ * The new text is build up step by step, to avoid too much
+ * copying. There are these pieces:
+ * sub_firstline The old text, unmodifed.
+ * copycol Column in the old text where we started
+ * looking for a match; from here old text still
+ * needs to be copied to the new text.
+ * matchcol Column number of the old text where to look
+ * for the next match. It's just after the
+ * previous match or one further.
+ * prev_matchcol Column just after the previous match (if any).
+ * Mostly equal to matchcol, except for the first
+ * match and after skipping an empty match.
+ * regmatch.*pos Where the pattern matched in the old text.
+ * new_start The new text, all that has been produced so
+ * far.
+ * new_end The new text, where to append new text.
+ *
+ * lnum The line number where we were looking for the
+ * first match in the old line.
+ * sub_firstlnum The line number in the buffer where to look
+ * for a match. Can be different from "lnum"
+ * when the pattern or substitute string contains
+ * line breaks.
+ *
+ * Special situations:
+ * - When the substitute string contains a line break, the part up
+ * to the line break is inserted in the text, but the copy of
+ * the original line is kept. "sub_firstlnum" is adjusted for
+ * the inserted lines.
+ * - When the matched pattern contains a line break, the old line
+ * is taken from the line at the end of the pattern. The lines
+ * in the match are deleted later, "sub_firstlnum" is adjusted
+ * accordingly.
+ *
+ * The new text is built up in new_start[]. It has some extra
+ * room to avoid using alloc()/free() too often. new_start_len is
+ * the lenght of the allocated memory at new_start.
+ *
+ * Make a copy of the old line, so it won't be taken away when
+ * updating the screen or handling a multi-line match. The "old_"
+ * pointers point into this copy.
+ */
+ sub_firstline = vim_strsave(ml_get(sub_firstlnum));
+ if (sub_firstline == NULL)
+ {
+ vim_free(new_start);
+ goto outofmem;
+ }
+ copycol = 0;
+ matchcol = 0;
+
+ /* At first match, remember current cursor position. */
+ if (!got_match)
+ {
+ setpcmark();
+ got_match = TRUE;
+ }
+
+ /*
+ * Loop until nothing more to replace in this line.
+ * 1. Handle match with empty string.
+ * 2. If do_ask is set, ask for confirmation.
+ * 3. substitute the string.
+ * 4. if do_all is set, find next match
+ * 5. break if there isn't another match in this line
+ */
+ for (;;)
+ {
+ /* Save the line number of the last change for the final
+ * cursor position (just like Vi). */
+ curwin->w_cursor.lnum = lnum;
+ do_again = FALSE;
+
+ /*
+ * 1. Match empty string does not count, except for first
+ * match. This reproduces the strange vi behaviour.
+ * This also catches endless loops.
+ */
+ if (matchcol == prev_matchcol
+ && regmatch.endpos[0].lnum == 0
+ && matchcol == regmatch.endpos[0].col)
+ {
+ ++matchcol; /* search for a match at next column */
+ goto skip;
+ }
+
+ /* Normally we continue searching for a match just after the
+ * previous match. */
+ matchcol = regmatch.endpos[0].col;
+ prev_matchcol = matchcol;
+
+ /*
+ * 2. If do_ask is set, ask for confirmation.
+ */
+ if (do_ask)
+ {
+ /* change State to CONFIRM, so that the mouse works
+ * properly */
+ save_State = State;
+ State = CONFIRM;
+#ifdef FEAT_MOUSE
+ setmouse(); /* disable mouse in xterm */
+#endif
+ curwin->w_cursor.col = regmatch.startpos[0].col;
+
+ /* When 'cpoptions' contains "u" don't sync undo when
+ * asking for confirmation. */
+ if (vim_strchr(p_cpo, CPO_UNDO) != NULL)
+ ++no_u_sync;
+
+ /*
+ * Loop until 'y', 'n', 'q', CTRL-E or CTRL-Y typed.
+ */
+ while (do_ask)
+ {
+#ifdef FEAT_FOLDING
+ int save_p_fen = curwin->w_p_fen;
+
+ curwin->w_p_fen = FALSE;
+#endif
+ /* Invert the matched string.
+ * Remove the inversion afterwards. */
+ temp = RedrawingDisabled;
+ RedrawingDisabled = 0;
+
+ search_match_lines = regmatch.endpos[0].lnum;
+ search_match_endcol = regmatch.endpos[0].col;
+ highlight_match = TRUE;
+
+ update_topline();
+ validate_cursor();
+ update_screen(NOT_VALID);
+ highlight_match = FALSE;
+ redraw_later(NOT_VALID);
+
+#ifdef FEAT_FOLDING
+ curwin->w_p_fen = save_p_fen;
+#endif
+ if (msg_row == Rows - 1)
+ msg_didout = FALSE; /* avoid a scroll-up */
+ msg_starthere();
+ i = msg_scroll;
+ msg_scroll = 0; /* truncate msg when needed */
+ msg_no_more = TRUE;
+ /* write message same highlighting as for wait_return */
+ smsg_attr(hl_attr(HLF_R),
+ (char_u *)_("replace with %s (y/n/a/q/l/^E/^Y)?"),
+ sub);
+ msg_no_more = FALSE;
+ msg_scroll = i;
+ showruler(TRUE);
+ windgoto(msg_row, msg_col);
+ RedrawingDisabled = temp;
+
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = FALSE; /* allow scrolling here */
+#endif
+ ++no_mapping; /* don't map this key */
+ ++allow_keys; /* allow special keys */
+ i = safe_vgetc();
+ --allow_keys;
+ --no_mapping;
+
+ /* clear the question */
+ msg_didout = FALSE; /* don't scroll up */
+ msg_col = 0;
+ gotocmdline(TRUE);
+ need_wait_return = FALSE; /* no hit-return prompt */
+ if (i == 'q' || i == ESC || i == Ctrl_C
+#ifdef UNIX
+ || i == intr_char
+#endif
+ )
+ {
+ got_quit = TRUE;
+ break;
+ }
+ if (i == 'n')
+ break;
+ if (i == 'y')
+ break;
+ if (i == 'l')
+ {
+ /* last: replace and then stop */
+ do_all = FALSE;
+ line2 = lnum;
+ break;
+ }
+ if (i == 'a')
+ {
+ do_ask = FALSE;
+ break;
+ }
+#ifdef FEAT_INS_EXPAND
+ if (i == Ctrl_E)
+ scrollup_clamp();
+ else if (i == Ctrl_Y)
+ scrolldown_clamp();
+#endif
+ }
+ State = save_State;
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+ if (vim_strchr(p_cpo, CPO_UNDO) != NULL)
+ --no_u_sync;
+
+ if (i == 'n')
+ {
+ /* For a multi-line match, put matchcol at the NUL at
+ * the end of the line and set nmatch to one, so that
+ * we continue looking for a match on the next line.
+ * Avoids that ":s/\nB\@=//gc" get stuck. */
+ if (nmatch > 1)
+ {
+ matchcol = STRLEN(sub_firstline);
+ nmatch = 1;
+ }
+ goto skip;
+ }
+ if (got_quit)
+ break;
+ }
+
+ /* Move the cursor to the start of the match, so that we can
+ * use "\=col("."). */
+ curwin->w_cursor.col = regmatch.startpos[0].col;
+
+ /*
+ * 3. substitute the string.
+ */
+ /* get length of substitution part */
+ sublen = vim_regsub_multi(&regmatch, sub_firstlnum,
+ sub, sub_firstline, FALSE, p_magic, TRUE);
+
+ /* Need room for:
+ * - result so far in new_start (not for first sub in line)
+ * - original text up to match
+ * - length of substituted part
+ * - original text after match
+ */
+ if (nmatch == 1)
+ p1 = sub_firstline;
+ else
+ {
+ p1 = ml_get(sub_firstlnum + nmatch - 1);
+ nmatch_tl += nmatch - 1;
+ }
+ i = regmatch.startpos[0].col - copycol;
+ needed_len = i + ((unsigned)STRLEN(p1) - regmatch.endpos[0].col)
+ + sublen + 1;
+ if (new_start == NULL)
+ {
+ /*
+ * Get some space for a temporary buffer to do the
+ * substitution into (and some extra space to avoid
+ * too many calls to alloc()/free()).
+ */
+ new_start_len = needed_len + 50;
+ if ((new_start = alloc_check(new_start_len)) == NULL)
+ goto outofmem;
+ *new_start = NUL;
+ new_end = new_start;
+ }
+ else
+ {
+ /*
+ * Check if the temporary buffer is long enough to do the
+ * substitution into. If not, make it larger (with a bit
+ * extra to avoid too many calls to alloc()/free()).
+ */
+ len = (unsigned)STRLEN(new_start);
+ needed_len += len;
+ if (needed_len > new_start_len)
+ {
+ new_start_len = needed_len + 50;
+ if ((p1 = alloc_check(new_start_len)) == NULL)
+ {
+ vim_free(new_start);
+ goto outofmem;
+ }
+ mch_memmove(p1, new_start, (size_t)(len + 1));
+ vim_free(new_start);
+ new_start = p1;
+ }
+ new_end = new_start + len;
+ }
+
+ /*
+ * copy the text up to the part that matched
+ */
+ mch_memmove(new_end, sub_firstline + copycol, (size_t)i);
+ new_end += i;
+
+ (void)vim_regsub_multi(&regmatch, sub_firstlnum,
+ sub, new_end, TRUE, p_magic, TRUE);
+ sub_nsubs++;
+ did_sub = TRUE;
+
+ /* Move the cursor to the start of the line, to avoid that it
+ * is beyond the end of the line after the substitution. */
+ curwin->w_cursor.col = 0;
+
+ /* For a multi-line match, make a copy of the last matched
+ * line and continue in that one. */
+ if (nmatch > 1)
+ {
+ sub_firstlnum += nmatch - 1;
+ vim_free(sub_firstline);
+ sub_firstline = vim_strsave(ml_get(sub_firstlnum));
+ /* When going beyond the last line, stop substituting. */
+ if (sub_firstlnum <= line2)
+ do_again = TRUE;
+ else
+ do_all = FALSE;
+ }
+
+ /* Remember next character to be copied. */
+ copycol = regmatch.endpos[0].col;
+
+ /*
+ * Now the trick is to replace CTRL-M chars with a real line
+ * break. This would make it impossible to insert a CTRL-M in
+ * the text. The line break can be avoided by preceding the
+ * CTRL-M with a backslash. To be able to insert a backslash,
+ * they must be doubled in the string and are halved here.
+ * That is Vi compatible.
+ */
+ for (p1 = new_end; *p1; ++p1)
+ {
+ if (p1[0] == '\\' && p1[1] != NUL) /* remove backslash */
+ mch_memmove(p1, p1 + 1, STRLEN(p1));
+ else if (*p1 == CAR)
+ {
+ if (u_inssub(lnum) == OK) /* prepare for undo */
+ {
+ *p1 = NUL; /* truncate up to the CR */
+ ml_append(lnum - 1, new_start,
+ (colnr_T)(p1 - new_start + 1), FALSE);
+ mark_adjust(lnum + 1, (linenr_T)MAXLNUM, 1L, 0L);
+ if (do_ask)
+ appended_lines(lnum - 1, 1L);
+ else
+ {
+ if (first_line == 0)
+ first_line = lnum;
+ last_line = lnum + 1;
+ }
+ /* All line numbers increase. */
+ ++sub_firstlnum;
+ ++lnum;
+ ++line2;
+ /* move the cursor to the new line, like Vi */
+ ++curwin->w_cursor.lnum;
+ STRCPY(new_start, p1 + 1); /* copy the rest */
+ p1 = new_start - 1;
+ }
+ }
+#ifdef FEAT_MBYTE
+ else if (has_mbyte)
+ p1 += (*mb_ptr2len_check)(p1) - 1;
+#endif
+ }
+
+ /*
+ * 4. If do_all is set, find next match.
+ * Prevent endless loop with patterns that match empty
+ * strings, e.g. :s/$/pat/g or :s/[a-z]* /(&)/g.
+ * But ":s/\n/#/" is OK.
+ */
+skip:
+ /* We already know that we did the last subst when we are at
+ * the end of the line, except that a pattern like
+ * "bar\|\nfoo" may match at the NUL. */
+ lastone = ((sub_firstline[matchcol] == NUL && nmatch <= 1
+ && !re_multiline(regmatch.regprog))
+ || got_int || got_quit || !(do_all || do_again));
+ nmatch = -1;
+
+ /*
+ * Replace the line in the buffer when needed. This is
+ * skipped when there are more matches.
+ * The check for nmatch_tl is needed for when multi-line
+ * matching must replace the lines before trying to do another
+ * match, otherwise "\@<=" won't work.
+ * When asking the user we like to show the already replaced
+ * text, but don't do it when "\<@=" or "\<@!" is used, it
+ * changes what matches.
+ */
+ if (lastone
+ || (do_ask && !re_lookbehind(regmatch.regprog))
+ || nmatch_tl > 0
+ || (nmatch = vim_regexec_multi(&regmatch, curwin,
+ curbuf, sub_firstlnum, matchcol)) == 0)
+ {
+ if (new_start != NULL)
+ {
+ /*
+ * Copy the rest of the line, that didn't match.
+ * "matchcol" has to be adjusted, we use the end of
+ * the line as reference, because the substitute may
+ * have changed the number of characters. Same for
+ * "prev_matchcol".
+ */
+ STRCAT(new_start, sub_firstline + copycol);
+ matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol;
+ prev_matchcol = (colnr_T)STRLEN(sub_firstline)
+ - prev_matchcol;
+
+ if (u_savesub(lnum) != OK)
+ break;
+ ml_replace(lnum, new_start, TRUE);
+
+ if (nmatch_tl > 0)
+ {
+ /*
+ * Matched lines have now been substituted and are
+ * useless, delete them. The part after the match
+ * has been appended to new_start, we don't need
+ * it in the buffer.
+ */
+ ++lnum;
+ if (u_savedel(lnum, nmatch_tl) != OK)
+ break;
+ for (i = 0; i < nmatch_tl; ++i)
+ ml_delete(lnum, (int)FALSE);
+ mark_adjust(lnum, lnum + nmatch_tl - 1,
+ (long)MAXLNUM, -nmatch_tl);
+ if (do_ask)
+ deleted_lines(lnum, nmatch_tl);
+ --lnum;
+ line2 -= nmatch_tl; /* nr of lines decreases */
+ nmatch_tl = 0;
+ }
+
+ /* When asking, undo is saved each time, must also set
+ * changed flag each time. */
+ if (do_ask)
+ changed_bytes(lnum, 0);
+ else
+ {
+ if (first_line == 0)
+ first_line = lnum;
+ last_line = lnum + 1;
+ }
+
+ sub_firstlnum = lnum;
+ vim_free(sub_firstline); /* free the temp buffer */
+ sub_firstline = new_start;
+ new_start = NULL;
+ matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol;
+ prev_matchcol = (colnr_T)STRLEN(sub_firstline)
+ - prev_matchcol;
+ copycol = 0;
+ }
+ if (nmatch == -1 && !lastone)
+ nmatch = vim_regexec_multi(&regmatch, curwin, curbuf,
+ sub_firstlnum, matchcol);
+
+ /*
+ * 5. break if there isn't another match in this line
+ */
+ if (nmatch <= 0)
+ break;
+ }
+
+ line_breakcheck();
+ }
+
+ if (did_sub)
+ ++sub_nlines;
+ vim_free(sub_firstline); /* free the copy of the original line */
+ sub_firstline = NULL;
+ }
+
+ line_breakcheck();
+ }
+
+ if (first_line != 0)
+ {
+ /* Need to subtract the number of added lines from "last_line" to get
+ * the line number before the change (same as adding the number of
+ * deleted lines). */
+ i = curbuf->b_ml.ml_line_count - old_line_count;
+ changed_lines(first_line, 0, last_line - i, i);
+ }
+
+outofmem:
+ vim_free(sub_firstline); /* may have to free allocated copy of the line */
+ if (sub_nsubs)
+ {
+ /* Set the '[ and '] marks. */
+ curbuf->b_op_start.lnum = eap->line1;
+ curbuf->b_op_end.lnum = line2;
+ curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+
+ if (!global_busy)
+ {
+ beginline(BL_WHITE | BL_FIX);
+ if (!do_sub_msg() && do_ask)
+ MSG("");
+ }
+ else
+ global_need_beginline = TRUE;
+ if (do_print)
+ print_line(curwin->w_cursor.lnum, FALSE);
+ }
+ else if (!global_busy)
+ {
+ if (got_int) /* interrupted */
+ EMSG(_(e_interr));
+ else if (got_match) /* did find something but nothing substituted */
+ MSG("");
+ else if (do_error) /* nothing found */
+ EMSG2(_(e_patnotf2), get_search_pat());
+ }
+
+ vim_free(regmatch.regprog);
+}
+
+/*
+ * Give message for number of substitutions.
+ * Can also be used after a ":global" command.
+ * Return TRUE if a message was given.
+ */
+ static int
+do_sub_msg()
+{
+ /*
+ * Only report substitutions when:
+ * - more than 'report' substitutions
+ * - command was typed by user, or number of changed lines > 'report'
+ * - giving messages is not disabled by 'lazyredraw'
+ */
+ if (sub_nsubs > p_report
+ && (KeyTyped || sub_nlines > 1 || p_report < 1)
+ && messaging())
+ {
+ if (got_int)
+ STRCPY(msg_buf, _("(Interrupted) "));
+ else
+ msg_buf[0] = NUL;
+ if (sub_nsubs == 1)
+ STRCAT(msg_buf, _("1 substitution"));
+ else
+ sprintf((char *)msg_buf + STRLEN(msg_buf), _("%ld substitutions"),
+ sub_nsubs);
+ if (sub_nlines == 1)
+ STRCAT(msg_buf, _(" on 1 line"));
+ else
+ sprintf((char *)msg_buf + STRLEN(msg_buf), _(" on %ld lines"),
+ (long)sub_nlines);
+ if (msg(msg_buf))
+ {
+ /* save message to display it after redraw */
+ set_keep_msg(msg_buf);
+ keep_msg_attr = 0;
+ }
+ return TRUE;
+ }
+ if (got_int)
+ {
+ EMSG(_(e_interr));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Execute a global command of the form:
+ *
+ * g/pattern/X : execute X on all lines where pattern matches
+ * v/pattern/X : execute X on all lines where pattern does not match
+ *
+ * where 'X' is an EX command
+ *
+ * The command character (as well as the trailing slash) is optional, and
+ * is assumed to be 'p' if missing.
+ *
+ * This is implemented in two passes: first we scan the file for the pattern and
+ * set a mark for each line that (not) matches. secondly we execute the command
+ * for each line that has a mark. This is required because after deleting
+ * lines we do not know where to search for the next match.
+ */
+ void
+ex_global(eap)
+ exarg_T *eap;
+{
+ linenr_T lnum; /* line number according to old situation */
+ int ndone;
+ int type; /* first char of cmd: 'v' or 'g' */
+ char_u *cmd; /* command argument */
+
+ char_u delim; /* delimiter, normally '/' */
+ char_u *pat;
+ regmmatch_T regmatch;
+ int match;
+ int which_pat;
+
+ if (global_busy)
+ {
+ EMSG(_("E147: Cannot do :global recursive")); /* will increment global_busy */
+ return;
+ }
+
+ if (eap->forceit) /* ":global!" is like ":vglobal" */
+ type = 'v';
+ else
+ type = *eap->cmd;
+ cmd = eap->arg;
+ which_pat = RE_LAST; /* default: use last used regexp */
+ sub_nsubs = 0;
+ sub_nlines = 0;
+
+ /*
+ * undocumented vi feature:
+ * "\/" and "\?": use previous search pattern.
+ * "\&": use previous substitute pattern.
+ */
+ if (*cmd == '\\')
+ {
+ ++cmd;
+ if (vim_strchr((char_u *)"/?&", *cmd) == NULL)
+ {
+ EMSG(_(e_backslash));
+ return;
+ }
+ if (*cmd == '&')
+ which_pat = RE_SUBST; /* use previous substitute pattern */
+ else
+ which_pat = RE_SEARCH; /* use previous search pattern */
+ ++cmd;
+ pat = (char_u *)"";
+ }
+ else if (*cmd == NUL)
+ {
+ EMSG(_("E148: Regular expression missing from global"));
+ return;
+ }
+ else
+ {
+ delim = *cmd; /* get the delimiter */
+ if (delim)
+ ++cmd; /* skip delimiter if there is one */
+ pat = cmd; /* remember start of pattern */
+ cmd = skip_regexp(cmd, delim, p_magic, &eap->arg);
+ if (cmd[0] == delim) /* end delimiter found */
+ *cmd++ = NUL; /* replace it with a NUL */
+ }
+
+#ifdef FEAT_FKMAP /* when in Farsi mode, reverse the character flow */
+ if (p_altkeymap && curwin->w_p_rl)
+ lrFswap(pat,0);
+#endif
+
+ if (search_regcomp(pat, RE_BOTH, which_pat, SEARCH_HIS, &regmatch) == FAIL)
+ {
+ EMSG(_(e_invcmd));
+ return;
+ }
+
+ /*
+ * pass 1: set marks for each (not) matching line
+ */
+ ndone = 0;
+ for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum)
+ {
+ /* a match on this line? */
+ match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum, (colnr_T)0);
+ if ((type == 'g' && match) || (type == 'v' && !match))
+ {
+ ml_setmarked(lnum);
+ ndone++;
+ }
+ line_breakcheck();
+ }
+
+ /*
+ * pass 2: execute the command for each line that has been marked
+ */
+ if (got_int)
+ MSG(_(e_interr));
+ else if (ndone == 0)
+ {
+ if (type == 'v')
+ msg_str((char_u *)_("Pattern found in every line: %s"), pat);
+ else
+ msg_str((char_u *)_(e_patnotf2), pat);
+ }
+ else
+ global_exe(cmd);
+
+ ml_clearmarked(); /* clear rest of the marks */
+ vim_free(regmatch.regprog);
+}
+
+/*
+ * Execute "cmd" on lines marked with ml_setmarked().
+ */
+ void
+global_exe(cmd)
+ char_u *cmd;
+{
+ linenr_T old_lcount; /* b_ml.ml_line_count before the command */
+ linenr_T lnum; /* line number according to old situation */
+
+ /*
+ * Set current position only once for a global command.
+ * If global_busy is set, setpcmark() will not do anything.
+ * If there is an error, global_busy will be incremented.
+ */
+ setpcmark();
+
+ /* When the command writes a message, don't overwrite the command. */
+ msg_didout = TRUE;
+
+ global_need_beginline = FALSE;
+ global_busy = 1;
+ old_lcount = curbuf->b_ml.ml_line_count;
+ while (!got_int && (lnum = ml_firstmarked()) != 0 && global_busy == 1)
+ {
+ curwin->w_cursor.lnum = lnum;
+ curwin->w_cursor.col = 0;
+ if (*cmd == NUL || *cmd == '\n')
+ do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT);
+ else
+ do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT);
+ ui_breakcheck();
+ }
+
+ global_busy = 0;
+ if (global_need_beginline)
+ beginline(BL_WHITE | BL_FIX);
+ else
+ check_cursor(); /* cursor may be beyond the end of the line */
+
+ /* If it looks like no message was written, allow overwriting the
+ * command with the report for number of changes. */
+ if (msg_col == 0 && msg_scrolled == 0)
+ msg_didout = FALSE;
+
+ /* If subsitutes done, report number of substitues, otherwise report
+ * number of extra or deleted lines. */
+ if (!do_sub_msg())
+ msgmore(curbuf->b_ml.ml_line_count - old_lcount);
+}
+
+#ifdef FEAT_VIMINFO
+ int
+read_viminfo_sub_string(virp, force)
+ vir_T *virp;
+ int force;
+{
+ if (old_sub != NULL && force)
+ vim_free(old_sub);
+ if (force || old_sub == NULL)
+ old_sub = viminfo_readstring(virp, 1, TRUE);
+ return viminfo_readline(virp);
+}
+
+ void
+write_viminfo_sub_string(fp)
+ FILE *fp;
+{
+ if (get_viminfo_parameter('/') != 0 && old_sub != NULL)
+ {
+ fprintf(fp, _("\n# Last Substitute String:\n$"));
+ viminfo_writestring(fp, old_sub);
+ }
+}
+#endif /* FEAT_VIMINFO */
+
+#if (defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)) || defined(PROTO)
+/*
+ * Set up for a tagpreview.
+ */
+ void
+prepare_tagpreview()
+{
+ win_T *wp;
+
+# ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+# endif
+
+ /*
+ * If there is already a preview window open, use that one.
+ */
+ if (!curwin->w_p_pvw)
+ {
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_p_pvw)
+ break;
+ if (wp != NULL)
+ win_enter(wp, TRUE);
+ else
+ {
+ /*
+ * There is no preview window open yet. Create one.
+ */
+ if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0)
+ == FAIL)
+ return;
+ curwin->w_p_pvw = TRUE;
+ curwin->w_p_wfh = TRUE;
+# ifdef FEAT_SCROLLBIND
+ curwin->w_p_scb = FALSE; /* don't take over 'scrollbind' */
+# endif
+# ifdef FEAT_DIFF
+ curwin->w_p_diff = FALSE; /* no 'diff' */
+# endif
+# ifdef FEAT_FOLDING
+ curwin->w_p_fdc = 0; /* no 'foldcolumn' */
+# endif
+ }
+ }
+}
+
+#endif
+
+
+/*
+ * ":help": open a read-only window on a help file
+ */
+ void
+ex_help(eap)
+ exarg_T *eap;
+{
+ char_u *arg;
+ char_u *tag;
+ FILE *helpfd; /* file descriptor of help file */
+ int n;
+ int i;
+#ifdef FEAT_WINDOWS
+ win_T *wp;
+#endif
+ int num_matches;
+ char_u **matches;
+ char_u *p;
+ int empty_fnum = 0;
+ int alt_fnum = 0;
+ buf_T *buf;
+#ifdef FEAT_MULTI_LANG
+ int len;
+ char_u *lang = NULL;
+#endif
+
+ if (eap != NULL)
+ {
+ /*
+ * A ":help" command ends at the first LF, or at a '|' that is
+ * followed by some text. Set nextcmd to the following command.
+ */
+ for (arg = eap->arg; *arg; ++arg)
+ {
+ if (*arg == '\n' || *arg == '\r'
+ || (*arg == '|' && arg[1] != NUL && arg[1] != '|'))
+ {
+ *arg++ = NUL;
+ eap->nextcmd = arg;
+ break;
+ }
+ }
+ arg = eap->arg;
+
+ if (eap->forceit && *arg == NUL)
+ {
+ EMSG(_("E478: Don't panic!"));
+ return;
+ }
+
+ if (eap->skip) /* not executing commands */
+ return;
+ }
+ else
+ arg = (char_u *)"";
+
+ /* remove trailing blanks */
+ p = arg + STRLEN(arg) - 1;
+ while (p > arg && vim_iswhite(*p) && p[-1] != '\\')
+ *p-- = NUL;
+
+#ifdef FEAT_MULTI_LANG
+ /* Check for a specified language */
+ len = STRLEN(arg);
+ if (len >= 3 && arg[len - 3] == '@' && ASCII_ISALPHA(arg[len - 2])
+ && ASCII_ISALPHA(arg[len - 1]))
+ {
+ lang = arg + len - 2;
+ lang[-1] = NUL; /* remove the '@' */
+ }
+#endif
+
+ /* When no argument given go to the index. */
+ if (*arg == NUL)
+ arg = (char_u *)"help.txt";
+
+ /*
+ * Check if there is a match for the argument.
+ */
+ n = find_help_tags(arg, &num_matches, &matches,
+ eap != NULL && eap->forceit);
+
+ i = 0;
+#ifdef FEAT_MULTI_LANG
+ if (n != FAIL && lang != NULL)
+ /* Find first item with the requested language. */
+ for (i = 0; i < num_matches; ++i)
+ {
+ len = STRLEN(matches[i]);
+ if (len > 3 && matches[i][len - 3] == '@'
+ && STRICMP(matches[i] + len - 2, lang) == 0)
+ break;
+ }
+#endif
+ if (i >= num_matches || n == FAIL)
+ {
+#ifdef FEAT_MULTI_LANG
+ if (lang != NULL)
+ EMSG3(_("E661: Sorry, no '%s' help for %s"), lang, arg);
+ else
+#endif
+ EMSG2(_("E149: Sorry, no help for %s"), arg);
+ if (n != FAIL)
+ FreeWild(num_matches, matches);
+ return;
+ }
+
+ /* The first match (in the requested language) is the best match. */
+ tag = vim_strsave(matches[i]);
+ FreeWild(num_matches, matches);
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+
+ /*
+ * Re-use an existing help window or open a new one.
+ */
+ if (!curwin->w_buffer->b_help)
+ {
+#ifdef FEAT_WINDOWS
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_buffer != NULL && wp->w_buffer->b_help)
+ break;
+ if (wp != NULL && wp->w_buffer->b_nwindows > 0)
+ win_enter(wp, TRUE);
+ else
+#endif
+ {
+ /*
+ * There is no help window yet.
+ * Try to open the file specified by the "helpfile" option.
+ */
+ if ((helpfd = mch_fopen((char *)p_hf, READBIN)) == NULL)
+ {
+ msg_str((char_u *)_("Sorry, help file \"%s\" not found"),
+ p_hf);
+ goto erret;
+ }
+ fclose(helpfd);
+
+#ifdef FEAT_WINDOWS
+ /* Split off help window; put it at far top if no position
+ * specified, the current window is vertically split and narrow. */
+ n = WSP_HELP;
+# ifdef FEAT_VERTSPLIT
+ if (cmdmod.split == 0 && curwin->w_width != Columns
+ && curwin->w_width < 80)
+ n |= WSP_TOP;
+# endif
+ if (win_split(0, n) == FAIL)
+#else
+ /* use current window */
+ if (!can_abandon(curbuf, FALSE))
+#endif
+ goto erret;
+
+#ifdef FEAT_WINDOWS
+ if (curwin->w_height < p_hh)
+ win_setheight((int)p_hh);
+#endif
+
+ /*
+ * Open help file (do_ecmd() will set b_help flag, readfile() will
+ * set b_p_ro flag).
+ * Set the alternate file to the previously edited file.
+ */
+ alt_fnum = curbuf->b_fnum;
+ (void)do_ecmd(0, NULL, NULL, NULL, ECMD_LASTL,
+ ECMD_HIDE + ECMD_SET_HELP);
+ curwin->w_alt_fnum = alt_fnum;
+ empty_fnum = curbuf->b_fnum;
+ }
+ }
+
+ if (!p_im)
+ restart_edit = 0; /* don't want insert mode in help file */
+
+ if (tag != NULL)
+ do_tag(tag, DT_HELP, 1, FALSE, TRUE);
+
+ /* Delete the empty buffer if we're not using it. */
+ if (empty_fnum != 0 && curbuf->b_fnum != empty_fnum)
+ {
+ buf = buflist_findnr(empty_fnum);
+ if (buf != NULL)
+ wipe_buffer(buf, TRUE);
+ }
+
+ /* keep the previous alternate file */
+ if (alt_fnum != 0 && curwin->w_alt_fnum == empty_fnum)
+ curwin->w_alt_fnum = alt_fnum;
+
+erret:
+ vim_free(tag);
+}
+
+
+/*
+ * Return a heuristic indicating how well the given string matches. The
+ * smaller the number, the better the match. This is the order of priorities,
+ * from best match to worst match:
+ * - Match with least alpha-numeric characters is better.
+ * - Match with least total characters is better.
+ * - Match towards the start is better.
+ * - Match starting with "+" is worse (feature instead of command)
+ * Assumption is made that the matched_string passed has already been found to
+ * match some string for which help is requested. webb.
+ */
+ int
+help_heuristic(matched_string, offset, wrong_case)
+ char_u *matched_string;
+ int offset; /* offset for match */
+ int wrong_case; /* no matching case */
+{
+ int num_letters;
+ char_u *p;
+
+ num_letters = 0;
+ for (p = matched_string; *p; p++)
+ if (ASCII_ISALNUM(*p))
+ num_letters++;
+
+ /*
+ * Multiply the number of letters by 100 to give it a much bigger
+ * weighting than the number of characters.
+ * If there only is a match while ignoring case, add 5000.
+ * If the match starts in the middle of a word, add 10000 to put it
+ * somewhere in the last half.
+ * If the match is more than 2 chars from the start, multiply by 200 to
+ * put it after matches at the start.
+ */
+ if (ASCII_ISALNUM(matched_string[offset]) && offset > 0
+ && ASCII_ISALNUM(matched_string[offset - 1]))
+ offset += 10000;
+ else if (offset > 2)
+ offset *= 200;
+ if (wrong_case)
+ offset += 5000;
+ /* Features are less interesting than the subjects themselves, but "+"
+ * alone is not a feature. */
+ if (matched_string[0] == '+' && matched_string[1] != NUL)
+ offset += 100;
+ return (int)(100 * num_letters + STRLEN(matched_string) + offset);
+}
+
+/*
+ * Compare functions for qsort() below, that checks the help heuristics number
+ * that has been put after the tagname by find_tags().
+ */
+ static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+help_compare(s1, s2)
+ const void *s1;
+ const void *s2;
+{
+ char *p1;
+ char *p2;
+
+ p1 = *(char **)s1 + strlen(*(char **)s1) + 1;
+ p2 = *(char **)s2 + strlen(*(char **)s2) + 1;
+ return strcmp(p1, p2);
+}
+
+/*
+ * Find all help tags matching "arg", sort them and return in matches[], with
+ * the number of matches in num_matches.
+ * The matches will be sorted with a "best" match algorithm.
+ * When "keep_lang" is TRUE try keeping the language of the current buffer.
+ */
+ int
+find_help_tags(arg, num_matches, matches, keep_lang)
+ char_u *arg;
+ int *num_matches;
+ char_u ***matches;
+ int keep_lang;
+{
+ char_u *s, *d;
+ int i;
+ static char *(mtable[]) = {"*", "g*", "[*", "]*", ":*",
+ "/*", "/\\*", "\"*", "/\\(\\)",
+ "?", ":?", "?<CR>", "g?", "g?g?", "g??",
+ "/\\?", "/\\z(\\)",
+ "[count]", "[quotex]", "[range]",
+ "[pattern]", "\\|", "\\%$"};
+ static char *(rtable[]) = {"star", "gstar", "[star", "]star", ":star",
+ "/star", "/\\\\star", "quotestar", "/\\\\(\\\\)",
+ "?", ":?", "?<CR>", "g?", "g?g?", "g??",
+ "/\\\\?", "/\\\\z(\\\\)",
+ "\\[count]", "\\[quotex]", "\\[range]",
+ "\\[pattern]", "\\\\bar", "/\\\\%\\$"};
+ int flags;
+
+ d = IObuff; /* assume IObuff is long enough! */
+
+ /*
+ * Recognize a few exceptions to the rule. Some strings that contain '*'
+ * with "star". Otherwise '*' is recognized as a wildcard.
+ */
+ for (i = sizeof(mtable) / sizeof(char *); --i >= 0; )
+ if (STRCMP(arg, mtable[i]) == 0)
+ {
+ STRCPY(d, rtable[i]);
+ break;
+ }
+
+ if (i < 0) /* no match in table */
+ {
+ /* Replace "\S" with "/\\S", etc. Otherwise every tag is matched.
+ * Also replace "\%^" and "\%(", they match every tag too.
+ * Also "\zs", "\z1", etc.
+ * Also "\@<", "\@=", "\@<=", etc.
+ * And also "\_$" and "\_^". */
+ if (arg[0] == '\\'
+ && ((arg[1] != NUL && arg[2] == NUL)
+ || (vim_strchr((char_u *)"%_z@", arg[1]) != NULL
+ && arg[2] != NUL)))
+ {
+ STRCPY(d, "/\\\\");
+ STRCPY(d + 3, arg + 1);
+ /* Check for "/\\_$", should be "/\\_\$" */
+ if (d[3] == '_' && d[4] == '$')
+ STRCPY(d + 4, "\\$");
+ }
+ else
+ {
+ /* replace "[:...:]" with "\[:...:]"; "[+...]" with "\[++...]" */
+ if (arg[0] == '[' && (arg[1] == ':'
+ || (arg[1] == '+' && arg[2] == '+')))
+ *d++ = '\\';
+
+ for (s = arg; *s; ++s)
+ {
+ /*
+ * Replace "|" with "bar" and '"' with "quote" to match the name of
+ * the tags for these commands.
+ * Replace "*" with ".*" and "?" with "." to match command line
+ * completion.
+ * Insert a backslash before '~', '$' and '.' to avoid their
+ * special meaning.
+ */
+ if (d - IObuff > IOSIZE - 10) /* getting too long!? */
+ break;
+ switch (*s)
+ {
+ case '|': STRCPY(d, "bar");
+ d += 3;
+ continue;
+ case '"': STRCPY(d, "quote");
+ d += 5;
+ continue;
+ case '*': *d++ = '.';
+ break;
+ case '?': *d++ = '.';
+ continue;
+ case '$':
+ case '.':
+ case '~': *d++ = '\\';
+ break;
+ }
+
+ /*
+ * Replace "^x" by "CTRL-X". Don't do this for "^_" to make
+ * ":help i_^_CTRL-D" work.
+ * Insert '-' before and after "CTRL-X" when applicable.
+ */
+ if (*s < ' ' || (*s == '^' && s[1] && (ASCII_ISALPHA(s[1])
+ || vim_strchr((char_u *)"?@[\\]^", s[1]) != NULL)))
+ {
+ if (d > IObuff && d[-1] != '_')
+ *d++ = '_'; /* prepend a '_' */
+ STRCPY(d, "CTRL-");
+ d += 5;
+ if (*s < ' ')
+ {
+#ifdef EBCDIC
+ *d++ = CtrlChar(*s);
+#else
+ *d++ = *s + '@';
+#endif
+ if (d[-1] == '\\')
+ *d++ = '\\'; /* double a backslash */
+ }
+ else
+ *d++ = *++s;
+ if (s[1] != NUL && s[1] != '_')
+ *d++ = '_'; /* append a '_' */
+ continue;
+ }
+ else if (*s == '^') /* "^" or "CTRL-^" or "^_" */
+ *d++ = '\\';
+
+ /*
+ * Insert a backslash before a backslash after a slash, for search
+ * pattern tags: "/\|" --> "/\\|".
+ */
+ else if (s[0] == '\\' && s[1] != '\\'
+ && *arg == '/' && s == arg + 1)
+ *d++ = '\\';
+
+ /* "CTRL-\_" -> "CTRL-\\_" to avoid the special meaning of "\_" in
+ * "CTRL-\_CTRL-N" */
+ if (STRNICMP(s, "CTRL-\\_", 7) == 0)
+ {
+ STRCPY(d, "CTRL-\\\\");
+ d += 7;
+ s += 6;
+ }
+
+ *d++ = *s;
+
+ /*
+ * If tag starts with ', toss everything after a second '. Fixes
+ * CTRL-] on 'option'. (would include the trailing '.').
+ */
+ if (*s == '\'' && s > arg && *arg == '\'')
+ break;
+ }
+ *d = NUL;
+ }
+ }
+
+ *matches = (char_u **)"";
+ *num_matches = 0;
+ flags = TAG_HELP | TAG_REGEXP | TAG_NAMES | TAG_VERBOSE;
+ if (keep_lang)
+ flags |= TAG_KEEP_LANG;
+ if (find_tags(IObuff, num_matches, matches, flags, (int)MAXCOL, NULL) == OK
+ && *num_matches > 0)
+ /* Sort the matches found on the heuristic number that is after the
+ * tag name. */
+ qsort((void *)*matches, (size_t)*num_matches,
+ sizeof(char_u *), help_compare);
+ return OK;
+}
+
+/*
+ * After reading a help file: May cleanup a help buffer when syntax
+ * highlighting is not used.
+ */
+ void
+fix_help_buffer()
+{
+ linenr_T lnum;
+ char_u *line;
+ int in_example = FALSE;
+ int len;
+ char_u *p;
+ char_u *rt;
+ int mustfree;
+
+ /* set filetype to "help". */
+ set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL);
+
+#ifdef FEAT_SYN_HL
+ if (!syntax_present(curbuf))
+#endif
+ {
+ for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
+ {
+ line = ml_get_buf(curbuf, lnum, FALSE);
+ len = (int)STRLEN(line);
+ if (in_example && len > 0 && !vim_iswhite(line[0]))
+ {
+ /* End of example: non-white or '<' in first column. */
+ if (line[0] == '<')
+ {
+ /* blank-out a '<' in the first column */
+ line = ml_get_buf(curbuf, lnum, TRUE);
+ line[0] = ' ';
+ }
+ in_example = FALSE;
+ }
+ if (!in_example && len > 0)
+ {
+ if (line[len - 1] == '>' && (len == 1 || line[len - 2] == ' '))
+ {
+ /* blank-out a '>' in the last column (start of example) */
+ line = ml_get_buf(curbuf, lnum, TRUE);
+ line[len - 1] = ' ';
+ in_example = TRUE;
+ }
+ else if (line[len - 1] == '~')
+ {
+ /* blank-out a '~' at the end of line (header marker) */
+ line = ml_get_buf(curbuf, lnum, TRUE);
+ line[len - 1] = ' ';
+ }
+ }
+ }
+ }
+
+ /*
+ * In the "help.txt" file, add the locally added help files.
+ * This uses the very first line in the help file.
+ */
+ if (fnamecmp(gettail(curbuf->b_fname), "help.txt") == 0)
+ {
+ for (lnum = 1; lnum < curbuf->b_ml.ml_line_count; ++lnum)
+ {
+ line = ml_get_buf(curbuf, lnum, FALSE);
+ if (strstr((char *)line, "*local-additions*") != NULL)
+ {
+ /* Go through all directories in 'runtimepath', skipping
+ * $VIMRUNTIME. */
+ p = p_rtp;
+ while (*p != NUL)
+ {
+ copy_option_part(&p, NameBuff, MAXPATHL, ",");
+ mustfree = FALSE;
+ rt = vim_getenv((char_u *)"VIMRUNTIME", &mustfree);
+ if (fullpathcmp(rt, NameBuff, FALSE) != FPC_SAME)
+ {
+ int fcount;
+ char_u **fnames;
+ FILE *fd;
+ char_u *s;
+ int fi;
+#ifdef FEAT_MBYTE
+ vimconv_T vc;
+ char_u *cp;
+#endif
+
+ /* Find all "doc/ *.txt" files in this directory. */
+ add_pathsep(NameBuff);
+ STRCAT(NameBuff, "doc/*.txt");
+ if (gen_expand_wildcards(1, &NameBuff, &fcount,
+ &fnames, EW_FILE|EW_SILENT) == OK
+ && fcount > 0)
+ {
+ for (fi = 0; fi < fcount; ++fi)
+ {
+ fd = fopen((char *)fnames[fi], "r");
+ if (fd != NULL)
+ {
+ vim_fgets(IObuff, IOSIZE, fd);
+ if (IObuff[0] == '*'
+ && (s = vim_strchr(IObuff + 1, '*'))
+ != NULL)
+ {
+#ifdef FEAT_MBYTE
+ int this_utf = MAYBE;
+#endif
+ /* Change tag definition to a
+ * reference and remove <CR>/<NL>. */
+ IObuff[0] = '|';
+ *s = '|';
+ while (*s != NUL)
+ {
+ if (*s == '\r' || *s == '\n')
+ *s = NUL;
+#ifdef FEAT_MBYTE
+ /* The text is utf-8 when a byte
+ * above 127 is found and no
+ * illegal byte sequence is found.
+ */
+ if (*s >= 0x80 && this_utf != FALSE)
+ {
+ int l;
+
+ this_utf = TRUE;
+ l = utf_ptr2len_check(s);
+ if (l == 1)
+ this_utf = FALSE;
+ s += l - 1;
+ }
+#endif
+ ++s;
+ }
+#ifdef FEAT_MBYTE
+ /* The help file is latin1 or utf-8;
+ * conversion to the current
+ * 'encoding' may be required. */
+ vc.vc_type = CONV_NONE;
+ convert_setup(&vc, (char_u *)(
+ this_utf == TRUE ? "utf-8"
+ : "latin1"), p_enc);
+ if (vc.vc_type == CONV_NONE)
+ /* No conversion needed. */
+ cp = IObuff;
+ else
+ {
+ /* Do the conversion. If it fails
+ * use the unconverted text. */
+ cp = string_convert(&vc, IObuff,
+ NULL);
+ if (cp == NULL)
+ cp = IObuff;
+ }
+ convert_setup(&vc, NULL, NULL);
+
+ ml_append(lnum, cp, (colnr_T)0, FALSE);
+ if (cp != IObuff)
+ vim_free(cp);
+#else
+ ml_append(lnum, IObuff, (colnr_T)0,
+ FALSE);
+#endif
+ ++lnum;
+ }
+ fclose(fd);
+ }
+ }
+ FreeWild(fcount, fnames);
+ }
+ }
+ if (mustfree)
+ vim_free(rt);
+ }
+ break;
+ }
+ }
+ }
+}
+
+#if defined(FEAT_EX_EXTRA) || defined(PROTO)
+static void helptags_one __ARGS((char_u *dir, char_u *ext, char_u *lang));
+
+/*
+ * ":helptags"
+ */
+ void
+ex_helptags(eap)
+ exarg_T *eap;
+{
+ garray_T ga;
+ int i, j;
+ int len;
+ char_u lang[2];
+ char_u ext[5];
+ char_u fname[8];
+ int filecount;
+ char_u **files;
+
+ if (!mch_isdir(eap->arg))
+ {
+ EMSG2(_("E150: Not a directory: %s"), eap->arg);
+ return;
+ }
+
+#ifdef FEAT_MULTI_LANG
+ /* Get a list of all files in the directory. */
+ STRCPY(NameBuff, eap->arg);
+ add_pathsep(NameBuff);
+ STRCAT(NameBuff, "*");
+ if (gen_expand_wildcards(1, &NameBuff, &filecount, &files,
+ EW_FILE|EW_SILENT) == FAIL
+ || filecount == 0)
+ {
+ EMSG2("E151: No match: %s", NameBuff);
+ return;
+ }
+
+ /* Go over all files in the directory to find out what languages are
+ * present. */
+ ga_init2(&ga, 1, 10);
+ for (i = 0; i < filecount; ++i)
+ {
+ len = STRLEN(files[i]);
+ if (len > 4)
+ {
+ if (STRICMP(files[i] + len - 4, ".txt") == 0)
+ {
+ /* ".txt" -> language "en" */
+ lang[0] = 'e';
+ lang[1] = 'n';
+ }
+ else if (files[i][len - 4] == '.'
+ && ASCII_ISALPHA(files[i][len - 3])
+ && ASCII_ISALPHA(files[i][len - 2])
+ && TOLOWER_ASC(files[i][len - 1]) == 'x')
+ {
+ /* ".abx" -> language "ab" */
+ lang[0] = TOLOWER_ASC(files[i][len - 3]);
+ lang[1] = TOLOWER_ASC(files[i][len - 2]);
+ }
+ else
+ continue;
+
+ /* Did we find this language already? */
+ for (j = 0; j < ga.ga_len; j += 2)
+ if (STRNCMP(lang, ((char_u *)ga.ga_data) + j, 2) == 0)
+ break;
+ if (j == ga.ga_len)
+ {
+ /* New language, add it. */
+ if (ga_grow(&ga, 2) == FAIL)
+ break;
+ ((char_u *)ga.ga_data)[ga.ga_len++] = lang[0];
+ ((char_u *)ga.ga_data)[ga.ga_len++] = lang[1];
+ ga.ga_room -= 2;
+ }
+ }
+ }
+
+ /*
+ * Loop over the found languages to generate a tags file for each one.
+ */
+ for (j = 0; j < ga.ga_len; j += 2)
+ {
+ STRCPY(fname, "tags-xx");
+ fname[5] = ((char_u *)ga.ga_data)[j];
+ fname[6] = ((char_u *)ga.ga_data)[j + 1];
+ if (fname[5] == 'e' && fname[6] == 'n')
+ {
+ /* English is an exception: use ".txt" and "tags". */
+ fname[4] = NUL;
+ STRCPY(ext, ".txt");
+ }
+ else
+ {
+ /* Language "ab" uses ".abx" and "tags-ab". */
+ STRCPY(ext, ".xxx");
+ ext[1] = fname[5];
+ ext[2] = fname[6];
+ }
+ helptags_one(eap->arg, ext, fname);
+ }
+
+ ga_clear(&ga);
+ FreeWild(filecount, files);
+
+#else
+ /* No language support, just use "*.txt" and "tags". */
+ helptags_one(eap->arg, (char_u *)".txt", (char_u *)"tags");
+#endif
+}
+
+ static void
+helptags_one(dir, ext, tagfname)
+ char_u *dir; /* doc directory */
+ char_u *ext; /* suffix, ".txt", ".itx", ".frx", etc. */
+ char_u *tagfname; /* "tags" for English, "tags-it" for Italian. */
+{
+ FILE *fd_tags;
+ FILE *fd;
+ garray_T ga;
+ int filecount;
+ char_u **files;
+ char_u *p1, *p2;
+ int fi;
+ char_u *s;
+ int i;
+ char_u *fname;
+# ifdef FEAT_MBYTE
+ int utf8 = MAYBE;
+ int this_utf8;
+ int firstline;
+ int mix = FALSE; /* detected mixed encodings */
+# endif
+
+ /*
+ * Find all *.txt files.
+ */
+ STRCPY(NameBuff, dir);
+ add_pathsep(NameBuff);
+ STRCAT(NameBuff, "*");
+ STRCAT(NameBuff, ext);
+ if (gen_expand_wildcards(1, &NameBuff, &filecount, &files,
+ EW_FILE|EW_SILENT) == FAIL
+ || filecount == 0)
+ {
+ if (!got_int)
+ EMSG2("E151: No match: %s", NameBuff);
+ return;
+ }
+
+ /*
+ * Open the tags file for writing.
+ * Do this before scanning through all the files.
+ */
+ STRCPY(NameBuff, dir);
+ add_pathsep(NameBuff);
+ STRCAT(NameBuff, tagfname);
+ fd_tags = fopen((char *)NameBuff, "w");
+ if (fd_tags == NULL)
+ {
+ EMSG2(_("E152: Cannot open %s for writing"), NameBuff);
+ FreeWild(filecount, files);
+ return;
+ }
+
+ /*
+ * If generating tags for "$VIMRUNTIME/doc" add the "help-tags" tag.
+ */
+ ga_init2(&ga, (int)sizeof(char_u *), 100);
+ if (fullpathcmp((char_u *)"$VIMRUNTIME/doc", dir, FALSE) == FPC_SAME)
+ {
+ if (ga_grow(&ga, 1) == FAIL)
+ got_int = TRUE;
+ else
+ {
+ s = alloc(30);
+ if (s == NULL)
+ got_int = TRUE;
+ else
+ {
+ sprintf((char *)s, "help-tags\t%s\t1\n", tagfname);
+ ((char_u **)ga.ga_data)[ga.ga_len] = s;
+ ++ga.ga_len;
+ --ga.ga_room;
+ }
+ }
+ }
+
+ /*
+ * Go over all the files and extract the tags.
+ */
+ for (fi = 0; fi < filecount && !got_int; ++fi)
+ {
+ fd = fopen((char *)files[fi], "r");
+ if (fd == NULL)
+ {
+ EMSG2(_("E153: Unable to open %s for reading"), files[fi]);
+ continue;
+ }
+ fname = gettail(files[fi]);
+
+# ifdef FEAT_MBYTE
+ firstline = TRUE;
+# endif
+ while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int)
+ {
+# ifdef FEAT_MBYTE
+ if (firstline)
+ {
+ /* Detect utf-8 file by a non-ASCII char in the first line. */
+ this_utf8 = MAYBE;
+ for (s = IObuff; *s != NUL; ++s)
+ if (*s >= 0x80)
+ {
+ int l;
+
+ this_utf8 = TRUE;
+ l = utf_ptr2len_check(s);
+ if (l == 1)
+ {
+ /* Illegal UTF-8 byte sequence. */
+ this_utf8 = FALSE;
+ break;
+ }
+ s += l - 1;
+ }
+ if (this_utf8 == MAYBE) /* only ASCII characters found */
+ this_utf8 = FALSE;
+ if (utf8 == MAYBE) /* first file */
+ utf8 = this_utf8;
+ else if (utf8 != this_utf8)
+ {
+ EMSG2(_("E670: Mix of help file encodings within a language: %s"), files[fi]);
+ mix = !got_int;
+ got_int = TRUE;
+ }
+ firstline = FALSE;
+ }
+# endif
+ p1 = vim_strchr(IObuff, '*'); /* find first '*' */
+ while (p1 != NULL)
+ {
+ p2 = vim_strchr(p1 + 1, '*'); /* find second '*' */
+ if (p2 != NULL && p2 > p1 + 1) /* skip "*" and "**" */
+ {
+ for (s = p1 + 1; s < p2; ++s)
+ if (*s == ' ' || *s == '\t' || *s == '|')
+ break;
+
+ /*
+ * Only accept a *tag* when it consists of valid
+ * characters, there is white space before it and is
+ * followed by a white character or end-of-line.
+ */
+ if (s == p2
+ && (p1 == IObuff || p1[-1] == ' ' || p1[-1] == '\t')
+ && (vim_strchr((char_u *)" \t\n\r", s[1]) != NULL
+ || s[1] == '\0'))
+ {
+ *p2 = '\0';
+ ++p1;
+ if (ga_grow(&ga, 1) == FAIL)
+ {
+ got_int = TRUE;
+ break;
+ }
+ s = alloc((unsigned)(p2 - p1 + STRLEN(fname) + 2));
+ if (s == NULL)
+ {
+ got_int = TRUE;
+ break;
+ }
+ ((char_u **)ga.ga_data)[ga.ga_len] = s;
+ ++ga.ga_len;
+ --ga.ga_room;
+ sprintf((char *)s, "%s\t%s", p1, fname);
+
+ /* find next '*' */
+ p2 = vim_strchr(p2 + 1, '*');
+ }
+ }
+ p1 = p2;
+ }
+ line_breakcheck();
+ }
+
+ fclose(fd);
+ }
+
+ FreeWild(filecount, files);
+
+ if (!got_int)
+ {
+ /*
+ * Sort the tags.
+ */
+ sort_strings((char_u **)ga.ga_data, ga.ga_len);
+
+ /*
+ * Check for duplicates.
+ */
+ for (i = 1; i < ga.ga_len; ++i)
+ {
+ p1 = ((char_u **)ga.ga_data)[i - 1];
+ p2 = ((char_u **)ga.ga_data)[i];
+ while (*p1 == *p2)
+ {
+ if (*p2 == '\t')
+ {
+ *p2 = NUL;
+ sprintf((char *)NameBuff,
+ _("E154: Duplicate tag \"%s\" in file %s/%s"),
+ ((char_u **)ga.ga_data)[i], dir, p2 + 1);
+ EMSG(NameBuff);
+ *p2 = '\t';
+ break;
+ }
+ ++p1;
+ ++p2;
+ }
+ }
+
+# ifdef FEAT_MBYTE
+ if (utf8 == TRUE)
+ fprintf(fd_tags, "!_TAG_FILE_ENCODING\tutf-8\t//\n");
+# endif
+
+ /*
+ * Write the tags into the file.
+ */
+ for (i = 0; i < ga.ga_len; ++i)
+ {
+ s = ((char_u **)ga.ga_data)[i];
+ if (STRNCMP(s, "help-tags", 9) == 0)
+ /* help-tags entry was added in formatted form */
+ fprintf(fd_tags, (char *)s);
+ else
+ {
+ fprintf(fd_tags, "%s\t/*", s);
+ for (p1 = s; *p1 != '\t'; ++p1)
+ {
+ /* insert backslash before '\\' and '/' */
+ if (*p1 == '\\' || *p1 == '/')
+ putc('\\', fd_tags);
+ putc(*p1, fd_tags);
+ }
+ fprintf(fd_tags, "*\n");
+ }
+ }
+ }
+#ifdef FEAT_MBYTE
+ if (mix)
+ got_int = FALSE; /* continue with other languages */
+#endif
+
+ for (i = 0; i < ga.ga_len; ++i)
+ vim_free(((char_u **)ga.ga_data)[i]);
+ ga_clear(&ga);
+ fclose(fd_tags); /* there is no check for an error... */
+}
+#endif
+
+#if defined(FEAT_SIGNS) || defined(PROTO)
+
+/*
+ * Struct to hold the sign properties.
+ */
+typedef struct sign sign_T;
+
+struct sign
+{
+ sign_T *sn_next; /* next sign in list */
+ int sn_typenr; /* type number of sign (negative if not equal
+ to name) */
+ char_u *sn_name; /* name of sign */
+ char_u *sn_icon; /* name of pixmap */
+#ifdef FEAT_SIGN_ICONS
+ void *sn_image; /* icon image */
+#endif
+ char_u *sn_text; /* text used instead of pixmap */
+ int sn_line_hl; /* highlight ID for line */
+ int sn_text_hl; /* highlight ID for text */
+};
+
+#define MAX_TYPENR 255 /* depends on sattr_T */
+static sign_T *first_sign = NULL;
+static int last_sign_typenr = MAX_TYPENR; /* is decremented */
+
+static void sign_list_defined __ARGS((sign_T *sp));
+
+/*
+ * ":sign" command
+ */
+ void
+ex_sign(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+ char_u *p;
+ int idx;
+ sign_T *sp;
+ sign_T *sp_prev;
+ buf_T *buf;
+ static char *cmds[] = {
+ "define",
+#define SIGNCMD_DEFINE 0
+ "undefine",
+#define SIGNCMD_UNDEFINE 1
+ "list",
+#define SIGNCMD_LIST 2
+ "place",
+#define SIGNCMD_PLACE 3
+ "unplace",
+#define SIGNCMD_UNPLACE 4
+ "jump",
+#define SIGNCMD_JUMP 5
+#define SIGNCMD_LAST 6
+ };
+
+ /* Parse the subcommand. */
+ p = skiptowhite(arg);
+ if (*p != NUL)
+ *p++ = NUL;
+ for (idx = 0; ; ++idx)
+ {
+ if (idx == SIGNCMD_LAST)
+ {
+ EMSG2(_("E160: Unknown sign command: %s"), arg);
+ return;
+ }
+ if (STRCMP(arg, cmds[idx]) == 0)
+ break;
+ }
+ arg = skipwhite(p);
+
+ if (idx <= SIGNCMD_LIST)
+ {
+ /*
+ * Define, undefine or list signs.
+ */
+ if (idx == SIGNCMD_LIST && *arg == NUL)
+ {
+ /* ":sign list": list all defined signs */
+ for (sp = first_sign; sp != NULL; sp = sp->sn_next)
+ sign_list_defined(sp);
+ }
+ else if (*arg == NUL)
+ EMSG(_("E156: Missing sign name"));
+ else
+ {
+ p = skiptowhite(arg);
+ if (*p != NUL)
+ *p++ = NUL;
+ sp_prev = NULL;
+ for (sp = first_sign; sp != NULL; sp = sp->sn_next)
+ {
+ if (STRCMP(sp->sn_name, arg) == 0)
+ break;
+ sp_prev = sp;
+ }
+ if (idx == SIGNCMD_DEFINE)
+ {
+ /* ":sign define {name} ...": define a sign */
+ if (sp == NULL)
+ {
+ /* Allocate a new sign. */
+ sp = (sign_T *)alloc_clear((unsigned)sizeof(sign_T));
+ if (sp == NULL)
+ return;
+ if (sp_prev == NULL)
+ first_sign = sp;
+ else
+ sp_prev->sn_next = sp;
+ sp->sn_name = vim_strnsave(arg, (int)(p - arg));
+
+ /* If the name is a number use that for the typenr,
+ * otherwise use a negative number. */
+ if (VIM_ISDIGIT(*arg))
+ sp->sn_typenr = atoi((char *)arg);
+ else
+ {
+ sign_T *lp;
+ int start = last_sign_typenr;
+
+ for (lp = first_sign; lp != NULL; lp = lp->sn_next)
+ {
+ if (lp->sn_typenr == last_sign_typenr)
+ {
+ --last_sign_typenr;
+ if (last_sign_typenr == 0)
+ last_sign_typenr = MAX_TYPENR;
+ if (last_sign_typenr == start)
+ {
+ EMSG(_("E612: Too many signs defined"));
+ return;
+ }
+ lp = first_sign;
+ continue;
+ }
+ }
+
+ sp->sn_typenr = last_sign_typenr--;
+ if (last_sign_typenr == 0)
+ last_sign_typenr = MAX_TYPENR; /* wrap around */
+ }
+ }
+
+ /* set values for a defined sign. */
+ for (;;)
+ {
+ arg = skipwhite(p);
+ if (*arg == NUL)
+ break;
+ p = skiptowhite_esc(arg);
+ if (STRNCMP(arg, "icon=", 5) == 0)
+ {
+ arg += 5;
+ vim_free(sp->sn_icon);
+ sp->sn_icon = vim_strnsave(arg, (int)(p - arg));
+ backslash_halve(sp->sn_icon);
+#ifdef FEAT_SIGN_ICONS
+ if (gui.in_use)
+ {
+ out_flush();
+ if (sp->sn_image != NULL)
+ gui_mch_destroy_sign(sp->sn_image);
+ sp->sn_image = gui_mch_register_sign(sp->sn_icon);
+ }
+#endif
+ }
+ else if (STRNCMP(arg, "text=", 5) == 0)
+ {
+ char_u *s;
+ int cells;
+ int len;
+
+ arg += 5;
+#ifdef FEAT_MBYTE
+ /* Count cells and check for non-printable chars */
+ if (has_mbyte)
+ {
+ cells = 0;
+ for (s = arg; s < p; s += (*mb_ptr2len_check)(s))
+ {
+ if (!vim_isprintc((*mb_ptr2char)(s)))
+ break;
+ cells += (*mb_ptr2cells)(s);
+ }
+ }
+ else
+#endif
+ {
+ for (s = arg; s < p; ++s)
+ if (!vim_isprintc(*s))
+ break;
+ cells = s - arg;
+ }
+ /* Currently must be one or two display cells */
+ if (s != p || cells < 1 || cells > 2)
+ {
+ *p = NUL;
+ EMSG2(_("E239: Invalid sign text: %s"), arg);
+ return;
+ }
+
+ vim_free(sp->sn_text);
+ /* Allocate one byte more if we need to pad up
+ * with a space. */
+ len = p - arg + ((cells == 1) ? 1 : 0);
+ sp->sn_text = vim_strnsave(arg, len);
+
+ if (sp->sn_text != NULL && cells == 1)
+ STRCPY(sp->sn_text + len - 1, " ");
+ }
+ else if (STRNCMP(arg, "linehl=", 7) == 0)
+ {
+ arg += 7;
+ sp->sn_line_hl = syn_check_group(arg, (int)(p - arg));
+ }
+ else if (STRNCMP(arg, "texthl=", 7) == 0)
+ {
+ arg += 7;
+ sp->sn_text_hl = syn_check_group(arg, (int)(p - arg));
+ }
+ else
+ {
+ EMSG2(_(e_invarg2), arg);
+ return;
+ }
+ }
+ }
+ else if (sp == NULL)
+ EMSG2(_("E155: Unknown sign: %s"), arg);
+ else if (idx == SIGNCMD_LIST)
+ /* ":sign list {name}" */
+ sign_list_defined(sp);
+ else
+ {
+ /* ":sign undefine {name}" */
+ vim_free(sp->sn_name);
+ vim_free(sp->sn_icon);
+#ifdef FEAT_SIGN_ICONS
+ if (sp->sn_image != NULL)
+ {
+ out_flush();
+ gui_mch_destroy_sign(sp->sn_image);
+ }
+#endif
+ vim_free(sp->sn_text);
+ if (sp_prev == NULL)
+ first_sign = sp->sn_next;
+ else
+ sp_prev->sn_next = sp->sn_next;
+ vim_free(sp);
+ }
+ }
+ }
+ else
+ {
+ int id = -1;
+ linenr_T lnum = -1;
+ char_u *sign_name = NULL;
+ char_u *arg1;
+
+ if (*arg == NUL)
+ {
+ if (idx == SIGNCMD_PLACE)
+ {
+ /* ":sign place": list placed signs in all buffers */
+ sign_list_placed(NULL);
+ }
+ else if (idx == SIGNCMD_UNPLACE)
+ {
+ /* ":sign unplace": remove placed sign at cursor */
+ id = buf_findsign_id(curwin->w_buffer, curwin->w_cursor.lnum);
+ if (id > 0)
+ {
+ buf_delsign(curwin->w_buffer, id);
+ update_debug_sign(curwin->w_buffer, curwin->w_cursor.lnum);
+ }
+ else
+ EMSG(_("E159: Missing sign number"));
+ }
+ else
+ EMSG(_(e_argreq));
+ return;
+ }
+
+ if (idx == SIGNCMD_UNPLACE && arg[0] == '*' && arg[1] == NUL)
+ {
+ /* ":sign unplace *": remove all placed signs */
+ buf_delete_all_signs();
+ return;
+ }
+
+ /* first arg could be placed sign id */
+ arg1 = arg;
+ if (VIM_ISDIGIT(*arg))
+ {
+ id = getdigits(&arg);
+ if (!vim_iswhite(*arg) && *arg != NUL)
+ {
+ id = -1;
+ arg = arg1;
+ }
+ else
+ {
+ arg = skipwhite(arg);
+ if (idx == SIGNCMD_UNPLACE && *arg == NUL)
+ {
+ /* ":sign unplace {id}": remove placed sign by number */
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if ((lnum = buf_delsign(buf, id)) != 0)
+ update_debug_sign(buf, lnum);
+ return;
+ }
+ }
+ }
+
+ /*
+ * Check for line={lnum} name={name} and file={fname} or buffer={nr}.
+ * Leave "arg" pointing to {fname}.
+ */
+ for (;;)
+ {
+ if (STRNCMP(arg, "line=", 5) == 0)
+ {
+ arg += 5;
+ lnum = atoi((char *)arg);
+ arg = skiptowhite(arg);
+ }
+ else if (STRNCMP(arg, "name=", 5) == 0)
+ {
+ arg += 5;
+ sign_name = arg;
+ arg = skiptowhite(arg);
+ if (*arg != NUL)
+ *arg++ = NUL;
+ }
+ else if (STRNCMP(arg, "file=", 5) == 0)
+ {
+ arg += 5;
+ buf = buflist_findname(arg);
+ break;
+ }
+ else if (STRNCMP(arg, "buffer=", 7) == 0)
+ {
+ arg += 7;
+ buf = buflist_findnr((int)getdigits(&arg));
+ if (*skipwhite(arg) != NUL)
+ EMSG(_(e_trailing));
+ break;
+ }
+ else
+ {
+ EMSG(_(e_invarg));
+ return;
+ }
+ arg = skipwhite(arg);
+ }
+
+ if (buf == NULL)
+ {
+ EMSG2(_("E158: Invalid buffer name: %s"), arg);
+ }
+ else if (id <= 0)
+ {
+ if (lnum >= 0 || sign_name != NULL)
+ EMSG(_(e_invarg));
+ else
+ /* ":sign place file={fname}": list placed signs in one file */
+ sign_list_placed(buf);
+ }
+ else if (idx == SIGNCMD_JUMP)
+ {
+ /* ":sign jump {id} file={fname}" */
+ if (lnum >= 0 || sign_name != NULL)
+ EMSG(_(e_invarg));
+ else if ((lnum = buf_findsign(buf, id)) > 0)
+ { /* goto a sign ... */
+ if (buf_jump_open_win(buf) != NULL)
+ { /* ... in a current window */
+ curwin->w_cursor.lnum = lnum;
+ check_cursor_lnum();
+ beginline(BL_WHITE);
+ }
+ else
+ { /* ... not currently in a window */
+ char_u *cmd;
+
+ cmd = alloc((unsigned)STRLEN(buf->b_fname) + 25);
+ if (cmd == NULL)
+ return;
+ sprintf((char *)cmd, "e +%ld %s", (long)lnum, buf->b_fname);
+ do_cmdline_cmd(cmd);
+ vim_free(cmd);
+ }
+#ifdef FEAT_FOLDING
+ foldOpenCursor();
+#endif
+ }
+ else
+ EMSGN(_("E157: Invalid sign ID: %ld"), id);
+ }
+ else if (idx == SIGNCMD_UNPLACE)
+ {
+ /* ":sign unplace {id} file={fname}" */
+ if (lnum >= 0 || sign_name != NULL)
+ EMSG(_(e_invarg));
+ else
+ {
+ lnum = buf_delsign(buf, id);
+ update_debug_sign(buf, lnum);
+ }
+ }
+ /* idx == SIGNCMD_PLACE */
+ else if (sign_name != NULL)
+ {
+ for (sp = first_sign; sp != NULL; sp = sp->sn_next)
+ if (STRCMP(sp->sn_name, sign_name) == 0)
+ break;
+ if (sp == NULL)
+ {
+ EMSG2(_("E155: Unknown sign: %s"), sign_name);
+ return;
+ }
+ if (lnum > 0)
+ /* ":sign place {id} line={lnum} name={name} file={fname}":
+ * place a sign */
+ buf_addsign(buf, id, lnum, sp->sn_typenr);
+ else
+ /* ":sign place {id} file={fname}": change sign type */
+ lnum = buf_change_sign_type(buf, id, sp->sn_typenr);
+ update_debug_sign(buf, lnum);
+ }
+ else
+ EMSG(_(e_invarg));
+ }
+}
+
+#if defined(FEAT_SIGN_ICONS) || defined(PROTO)
+/*
+ * Allocate the icons. Called when the GUI has started. Allows defining
+ * signs before it starts.
+ */
+ void
+sign_gui_started()
+{
+ sign_T *sp;
+
+ for (sp = first_sign; sp != NULL; sp = sp->sn_next)
+ if (sp->sn_icon != NULL)
+ sp->sn_image = gui_mch_register_sign(sp->sn_icon);
+}
+#endif
+
+/*
+ * List one sign.
+ */
+ static void
+sign_list_defined(sp)
+ sign_T *sp;
+{
+ char_u *p;
+
+ smsg((char_u *)"sign %s", sp->sn_name);
+ if (sp->sn_icon != NULL)
+ {
+ MSG_PUTS(" icon=");
+ msg_outtrans(sp->sn_icon);
+#ifdef FEAT_SIGN_ICONS
+ if (sp->sn_image == NULL)
+ MSG_PUTS(_(" (NOT FOUND)"));
+#else
+ MSG_PUTS(_(" (not supported)"));
+#endif
+ }
+ if (sp->sn_text != NULL)
+ {
+ MSG_PUTS(" text=");
+ msg_outtrans(sp->sn_text);
+ }
+ if (sp->sn_line_hl > 0)
+ {
+ MSG_PUTS(" linehl=");
+ p = get_highlight_name(NULL, sp->sn_line_hl - 1);
+ if (p == NULL)
+ MSG_PUTS("NONE");
+ else
+ msg_puts(p);
+ }
+ if (sp->sn_text_hl > 0)
+ {
+ MSG_PUTS(" texthl=");
+ p = get_highlight_name(NULL, sp->sn_text_hl - 1);
+ if (p == NULL)
+ MSG_PUTS("NONE");
+ else
+ msg_puts(p);
+ }
+}
+
+/*
+ * Get highlighting attribute for sign "typenr".
+ * If "line" is TRUE: line highl, if FALSE: text highl.
+ */
+ int
+sign_get_attr(typenr, line)
+ int typenr;
+ int line;
+{
+ sign_T *sp;
+
+ for (sp = first_sign; sp != NULL; sp = sp->sn_next)
+ if (sp->sn_typenr == typenr)
+ {
+ if (line)
+ {
+ if (sp->sn_line_hl > 0)
+ return syn_id2attr(sp->sn_line_hl);
+ }
+ else
+ {
+ if (sp->sn_text_hl > 0)
+ return syn_id2attr(sp->sn_text_hl);
+ }
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Get text mark for sign "typenr".
+ * Returns NULL if there isn't one.
+ */
+ char_u *
+sign_get_text(typenr)
+ int typenr;
+{
+ sign_T *sp;
+
+ for (sp = first_sign; sp != NULL; sp = sp->sn_next)
+ if (sp->sn_typenr == typenr)
+ return sp->sn_text;
+ return NULL;
+}
+
+#if defined(FEAT_SIGN_ICONS) || defined(PROTO)
+ void *
+sign_get_image(typenr)
+ int typenr; /* the attribute which may have a sign */
+{
+ sign_T *sp;
+
+ for (sp = first_sign; sp != NULL; sp = sp->sn_next)
+ if (sp->sn_typenr == typenr)
+ return sp->sn_image;
+ return NULL;
+}
+#endif
+
+/*
+ * Get the name of a sign by its typenr.
+ */
+ char_u *
+sign_typenr2name(typenr)
+ int typenr;
+{
+ sign_T *sp;
+
+ for (sp = first_sign; sp != NULL; sp = sp->sn_next)
+ if (sp->sn_typenr == typenr)
+ return sp->sn_name;
+ return (char_u *)_("[Deleted]");
+}
+
+#endif
+
+#if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
+/*
+ * ":drop"
+ * Opens the first argument in a window. When there are two or more arguments
+ * the argument list is redefined.
+ */
+ void
+ex_drop(eap)
+ exarg_T *eap;
+{
+ int split = FALSE;
+ int incurwin = FALSE;
+ char_u *arg;
+ char_u *first = NULL;
+ win_T *wp;
+ buf_T *buf;
+
+ /*
+ * Check if the first argument is already being edited in a window. If
+ * so, jump to that window.
+ * We would actually need to check all arguments, but that's complicated
+ * and mostly only one file is dropped.
+ * This also ignores wildcards, since it is very unlikely the user is
+ * editing a file name with a wildcard character.
+ */
+ arg = vim_strsave(eap->arg);
+ if (arg != NULL)
+ {
+ /* Get the first argument, remove quotes, make it a full path. */
+ first = fix_fname(arg);
+ if (first != NULL)
+ {
+ buf = buflist_findname(first);
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_buffer == buf)
+ {
+ incurwin = TRUE;
+# ifdef FEAT_WINDOWS
+ win_enter(wp, TRUE);
+ break;
+# endif
+ }
+ }
+ vim_free(first);
+
+ if (incurwin)
+ {
+ /* Already editing the file. Redefine the argument list. */
+ set_arglist(eap->arg);
+ curwin->w_arg_idx = 0;
+ vim_free(arg);
+ return;
+ }
+ }
+ vim_free(arg);
+ }
+
+ /*
+ * Check whether the current buffer is changed. If so, we will need
+ * to split the current window or data could be lost.
+ * Skip the check if the 'hidden' option is set, as in this case the
+ * buffer won't be lost.
+ */
+ if (!P_HID(curbuf))
+ {
+# ifdef FEAT_WINDOWS
+ ++emsg_off;
+# endif
+ split = check_changed(curbuf, TRUE, FALSE, FALSE, FALSE);
+# ifdef FEAT_WINDOWS
+ --emsg_off;
+# else
+ if (split)
+ return;
+# endif
+ }
+
+ /* Fake a ":snext" or ":next" command, redefine the arglist. */
+ if (split)
+ {
+ eap->cmdidx = CMD_snext;
+ eap->cmd[0] = 's';
+ }
+ else
+ eap->cmdidx = CMD_next;
+ ex_next(eap);
+}
+#endif
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
new file mode 100644
index 000000000..8ffeadf01
--- /dev/null
+++ b/src/ex_cmds.h
@@ -0,0 +1,961 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * This file defines the Ex commands.
+ * When DO_DECLARE_EXCMD is defined, the table with ex command names and
+ * options results.
+ * When DO_DECLARE_EXCMD is NOT defined, the enum with all the Ex commands
+ * results.
+ * This clever trick was invented by Ron Aaron.
+ */
+
+/*
+ * When adding an Ex command:
+ * 1. Add an entry in the table below. Keep it sorted on the shortest
+ * version of the command name that works. If it doesn't start with a
+ * lower case letter, add it at the end.
+ * 2. Add a "case: CMD_xxx" in the big switch in ex_docmd.c.
+ * 3. Add an entry in the index for Ex commands at ":help ex-cmd-index".
+ * 4. Add documentation in ../doc/xxx.txt. Add a tag for both the short and
+ * long name of the command.
+ */
+
+#ifdef RANGE
+# undef RANGE /* SASC on Amiga defines it */
+#endif
+
+#define RANGE 0x001 /* allow a linespecs */
+#define BANG 0x002 /* allow a ! after the command name */
+#define EXTRA 0x004 /* allow extra args after command name */
+#define XFILE 0x008 /* expand wildcards in extra part */
+#define NOSPC 0x010 /* no spaces allowed in the extra part */
+#define DFLALL 0x020 /* default file range is 1,$ */
+#define WHOLEFOLD 0x040 /* extend range to include whole fold also
+ when less than two numbers given */
+#define NEEDARG 0x080 /* argument required */
+#define TRLBAR 0x100 /* check for trailing vertical bar */
+#define REGSTR 0x200 /* allow "x for register designation */
+#define COUNT 0x400 /* allow count in argument, after command */
+#define NOTRLCOM 0x800 /* no trailing comment allowed */
+#define ZEROR 0x1000 /* zero line number allowed */
+#define USECTRLV 0x2000 /* do not remove CTRL-V from argument */
+#define NOTADR 0x4000 /* number before command is not an address */
+#define EDITCMD 0x8000 /* allow "+command" argument */
+#define BUFNAME 0x10000L /* accepts buffer name */
+#define BUFUNL 0x20000L /* accepts unlisted buffer too */
+#define ARGOPT 0x40000L /* allow "++opt=val" argument */
+#define SBOXOK 0x80000L /* allowed in the sandbox */
+#define CMDWIN 0x100000L /* allowed in cmdline window */
+#define MODIFY 0x200000L /* forbidden in non-'modifiable' buffer */
+#define FILES (XFILE | EXTRA) /* multiple extra files allowed */
+#define WORD1 (EXTRA | NOSPC) /* one extra word allowed */
+#define FILE1 (FILES | NOSPC) /* 1 file allowed, defaults to current file */
+
+#ifndef DO_DECLARE_EXCMD
+typedef struct exarg exarg_T;
+#endif
+
+/*
+ * This array maps ex command names to command codes.
+ * The order in which command names are listed below is significant --
+ * ambiguous abbreviations are always resolved to be the first possible match
+ * (e.g. "r" is taken to mean "read", not "rewind", because "read" comes
+ * before "rewind").
+ * Not supported commands are included to avoid ambiguities.
+ */
+#ifdef EX
+# undef EX /* just in case */
+#endif
+#ifdef DO_DECLARE_EXCMD
+# define EX(a, b, c, d) {(char_u *)b, c, d}
+
+typedef void (*ex_func_T) __ARGS((exarg_T *eap));
+
+static struct cmdname
+{
+ char_u *cmd_name; /* name of the command */
+ ex_func_T cmd_func; /* function for this command */
+ long_u cmd_argt; /* flags declared above */
+}
+# if defined(FEAT_GUI_W16)
+_far
+# endif
+cmdnames[] =
+#else
+# define EX(a, b, c, d) a
+enum CMD_index
+#endif
+{
+EX(CMD_append, "append", ex_append,
+ BANG|RANGE|ZEROR|TRLBAR|CMDWIN|MODIFY),
+EX(CMD_abbreviate, "abbreviate", ex_abbreviate,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_abclear, "abclear", ex_abclear,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_aboveleft, "aboveleft", ex_wrongmodifier,
+ NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_all, "all", ex_all,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_amenu, "amenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_anoremenu, "anoremenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_args, "args", ex_args,
+ BANG|FILES|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_argadd, "argadd", ex_argadd,
+ BANG|NEEDARG|RANGE|NOTADR|COUNT|FILES|TRLBAR),
+EX(CMD_argdelete, "argdelete", ex_argdelete,
+ BANG|RANGE|NOTADR|COUNT|FILES|TRLBAR),
+EX(CMD_argdo, "argdo", ex_listdo,
+ BANG|NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_argedit, "argedit", ex_argedit,
+ BANG|NEEDARG|RANGE|NOTADR|COUNT|FILE1|EDITCMD|TRLBAR),
+EX(CMD_argglobal, "argglobal", ex_args,
+ BANG|FILES|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_arglocal, "arglocal", ex_args,
+ BANG|FILES|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_argument, "argument", ex_argument,
+ BANG|RANGE|NOTADR|COUNT|EXTRA|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_ascii, "ascii", do_ascii,
+ TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_autocmd, "autocmd", ex_autocmd,
+ BANG|EXTRA|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_augroup, "augroup", ex_autocmd,
+ BANG|WORD1|TRLBAR|CMDWIN),
+EX(CMD_aunmenu, "aunmenu", ex_menu,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_buffer, "buffer", ex_buffer,
+ BANG|RANGE|NOTADR|BUFNAME|BUFUNL|COUNT|EXTRA|TRLBAR),
+EX(CMD_bNext, "bNext", ex_bprevious,
+ BANG|RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_ball, "ball", ex_buffer_all,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_badd, "badd", ex_edit,
+ NEEDARG|FILE1|EDITCMD|TRLBAR|CMDWIN),
+EX(CMD_bdelete, "bdelete", ex_bunload,
+ BANG|RANGE|NOTADR|BUFNAME|COUNT|EXTRA|TRLBAR),
+EX(CMD_behave, "behave", ex_behave,
+ NEEDARG|WORD1|TRLBAR|CMDWIN),
+EX(CMD_belowright, "belowright", ex_wrongmodifier,
+ NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_bfirst, "bfirst", ex_brewind,
+ BANG|RANGE|NOTADR|TRLBAR),
+EX(CMD_blast, "blast", ex_blast,
+ BANG|RANGE|NOTADR|TRLBAR),
+EX(CMD_bmodified, "bmodified", ex_bmodified,
+ BANG|RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_bnext, "bnext", ex_bnext,
+ BANG|RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_botright, "botright", ex_wrongmodifier,
+ NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_bprevious, "bprevious", ex_bprevious,
+ BANG|RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_brewind, "brewind", ex_brewind,
+ BANG|RANGE|NOTADR|TRLBAR),
+EX(CMD_break, "break", ex_break,
+ TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_breakadd, "breakadd", ex_breakadd,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_breakdel, "breakdel", ex_breakdel,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_breaklist, "breaklist", ex_breaklist,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_browse, "browse", ex_wrongmodifier,
+ NEEDARG|EXTRA|NOTRLCOM|CMDWIN),
+EX(CMD_buffers, "buffers", buflist_list,
+ BANG|TRLBAR|CMDWIN),
+EX(CMD_bufdo, "bufdo", ex_listdo,
+ BANG|NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_bunload, "bunload", ex_bunload,
+ BANG|RANGE|NOTADR|BUFNAME|COUNT|EXTRA|TRLBAR),
+EX(CMD_bwipeout, "bwipeout", ex_bunload,
+ BANG|RANGE|NOTADR|BUFNAME|BUFUNL|COUNT|EXTRA|TRLBAR),
+EX(CMD_change, "change", ex_change,
+ BANG|WHOLEFOLD|RANGE|COUNT|TRLBAR|CMDWIN|MODIFY),
+EX(CMD_cNext, "cNext", ex_cnext,
+ RANGE|NOTADR|COUNT|TRLBAR|BANG),
+EX(CMD_cNfile, "cNfile", ex_cnext,
+ RANGE|NOTADR|COUNT|TRLBAR|BANG),
+EX(CMD_cabbrev, "cabbrev", ex_abbreviate,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_cabclear, "cabclear", ex_abclear,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_call, "call", ex_call,
+ RANGE|NEEDARG|EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_catch, "catch", ex_catch,
+ EXTRA|SBOXOK|CMDWIN),
+EX(CMD_cc, "cc", ex_cc,
+ RANGE|NOTADR|COUNT|TRLBAR|BANG),
+EX(CMD_cclose, "cclose", ex_cclose,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_cd, "cd", ex_cd,
+ FILE1|TRLBAR|CMDWIN),
+EX(CMD_center, "center", ex_align,
+ TRLBAR|RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
+EX(CMD_cfile, "cfile", ex_cfile,
+ TRLBAR|FILE1|BANG),
+EX(CMD_cfirst, "cfirst", ex_cc,
+ RANGE|NOTADR|COUNT|TRLBAR|BANG),
+EX(CMD_cgetfile, "cgetfile", ex_cfile,
+ TRLBAR|FILE1|BANG),
+EX(CMD_chdir, "chdir", ex_cd,
+ FILE1|TRLBAR|CMDWIN),
+EX(CMD_changes, "changes", ex_changes,
+ TRLBAR|CMDWIN),
+EX(CMD_checkpath, "checkpath", ex_checkpath,
+ TRLBAR|BANG|CMDWIN),
+EX(CMD_checktime, "checktime", ex_checktime,
+ RANGE|NOTADR|BUFNAME|COUNT|EXTRA|TRLBAR),
+EX(CMD_clist, "clist", qf_list,
+ BANG|EXTRA|TRLBAR|CMDWIN),
+EX(CMD_clast, "clast", ex_cc,
+ RANGE|NOTADR|COUNT|TRLBAR|BANG),
+EX(CMD_close, "close", ex_close,
+ BANG|TRLBAR|CMDWIN),
+EX(CMD_cmap, "cmap", ex_map,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_cmapclear, "cmapclear", ex_mapclear,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_cmenu, "cmenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_cnext, "cnext", ex_cnext,
+ RANGE|NOTADR|COUNT|TRLBAR|BANG),
+EX(CMD_cnewer, "cnewer", qf_age,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_cnfile, "cnfile", ex_cnext,
+ RANGE|NOTADR|COUNT|TRLBAR|BANG),
+EX(CMD_cnoremap, "cnoremap", ex_map,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_cnoreabbrev, "cnoreabbrev", ex_abbreviate,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_cnoremenu, "cnoremenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_copy, "copy", ex_copymove,
+ RANGE|WHOLEFOLD|EXTRA|TRLBAR|CMDWIN|MODIFY),
+EX(CMD_colder, "colder", qf_age,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_colorscheme, "colorscheme", ex_colorscheme,
+ NEEDARG|WORD1|TRLBAR|CMDWIN),
+EX(CMD_command, "command", ex_command,
+ EXTRA|BANG|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_comclear, "comclear", ex_comclear,
+ TRLBAR|CMDWIN),
+EX(CMD_compiler, "compiler", ex_compiler,
+ BANG|TRLBAR|WORD1),
+EX(CMD_continue, "continue", ex_continue,
+ TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_confirm, "confirm", ex_wrongmodifier,
+ NEEDARG|EXTRA|NOTRLCOM|CMDWIN),
+EX(CMD_copen, "copen", ex_copen,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_cprevious, "cprevious", ex_cnext,
+ RANGE|NOTADR|COUNT|TRLBAR|BANG),
+EX(CMD_cpfile, "cpfile", ex_cnext,
+ RANGE|NOTADR|COUNT|TRLBAR|BANG),
+EX(CMD_cquit, "cquit", ex_cquit,
+ TRLBAR|BANG),
+EX(CMD_crewind, "crewind", ex_cc,
+ RANGE|NOTADR|COUNT|TRLBAR|BANG),
+EX(CMD_cscope, "cscope", do_cscope,
+ EXTRA|NOTRLCOM|SBOXOK|XFILE),
+EX(CMD_cstag, "cstag", do_cstag,
+ BANG|TRLBAR|WORD1),
+EX(CMD_cunmap, "cunmap", ex_unmap,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_cunabbrev, "cunabbrev", ex_abbreviate,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_cunmenu, "cunmenu", ex_menu,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_cwindow, "cwindow", ex_cwindow,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_delete, "delete", ex_operators,
+ RANGE|WHOLEFOLD|REGSTR|COUNT|TRLBAR|CMDWIN|MODIFY),
+EX(CMD_debug, "debug", ex_debug,
+ NEEDARG|EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_debuggreedy, "debuggreedy", ex_debuggreedy,
+ RANGE|NOTADR|ZEROR|TRLBAR|CMDWIN),
+EX(CMD_delcommand, "delcommand", ex_delcommand,
+ NEEDARG|WORD1|TRLBAR|CMDWIN),
+EX(CMD_delfunction, "delfunction", ex_delfunction,
+ NEEDARG|WORD1|CMDWIN),
+EX(CMD_display, "display", ex_display,
+ EXTRA|NOTRLCOM|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_diffupdate, "diffupdate", ex_diffupdate,
+ TRLBAR),
+EX(CMD_diffget, "diffget", ex_diffgetput,
+ RANGE|EXTRA|TRLBAR|MODIFY),
+EX(CMD_diffpatch, "diffpatch", ex_diffpatch,
+ EXTRA|FILE1|TRLBAR|MODIFY),
+EX(CMD_diffput, "diffput", ex_diffgetput,
+ RANGE|EXTRA|TRLBAR),
+EX(CMD_diffsplit, "diffsplit", ex_diffsplit,
+ EXTRA|FILE1|TRLBAR),
+EX(CMD_diffthis, "diffthis", ex_diffthis,
+ TRLBAR),
+EX(CMD_digraphs, "digraphs", ex_digraphs,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_djump, "djump", ex_findpat,
+ BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA),
+EX(CMD_dlist, "dlist", ex_findpat,
+ BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA|CMDWIN),
+EX(CMD_doautocmd, "doautocmd", ex_doautocmd,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_doautoall, "doautoall", ex_doautoall,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_drop, "drop", ex_drop,
+ FILES|EDITCMD|NEEDARG|ARGOPT|TRLBAR),
+EX(CMD_dsearch, "dsearch", ex_findpat,
+ BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA|CMDWIN),
+EX(CMD_dsplit, "dsplit", ex_findpat,
+ BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA),
+EX(CMD_edit, "edit", ex_edit,
+ BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_echo, "echo", ex_echo,
+ EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_echoerr, "echoerr", ex_execute,
+ EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_echohl, "echohl", ex_echohl,
+ EXTRA|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_echomsg, "echomsg", ex_execute,
+ EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_echon, "echon", ex_echo,
+ EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_else, "else", ex_else,
+ TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_elseif, "elseif", ex_else,
+ EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_emenu, "emenu", ex_emenu,
+ NEEDARG|EXTRA|TRLBAR|NOTRLCOM|RANGE|NOTADR|CMDWIN),
+EX(CMD_endif, "endif", ex_endif,
+ TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_endfunction, "endfunction", ex_endfunction,
+ TRLBAR|CMDWIN),
+EX(CMD_endtry, "endtry", ex_endtry,
+ TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_endwhile, "endwhile", ex_endwhile,
+ TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_enew, "enew", ex_edit,
+ BANG|TRLBAR),
+EX(CMD_ex, "ex", ex_edit,
+ BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_execute, "execute", ex_execute,
+ EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_exit, "exit", ex_exit,
+ RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR|CMDWIN),
+EX(CMD_file, "file", ex_file,
+ BANG|FILE1|TRLBAR),
+EX(CMD_files, "files", buflist_list,
+ BANG|TRLBAR|CMDWIN),
+EX(CMD_filetype, "filetype", ex_filetype,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_find, "find", ex_find,
+ RANGE|NOTADR|BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_finally, "finally", ex_finally,
+ TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_finish, "finish", ex_finish,
+ TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_first, "first", ex_rewind,
+ EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_fixdel, "fixdel", do_fixdel,
+ TRLBAR|CMDWIN),
+EX(CMD_fold, "fold", ex_fold,
+ RANGE|WHOLEFOLD|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_foldclose, "foldclose", ex_foldopen,
+ RANGE|BANG|WHOLEFOLD|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_folddoopen, "folddoopen", ex_folddo,
+ RANGE|DFLALL|NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_folddoclosed, "folddoclosed", ex_folddo,
+ RANGE|DFLALL|NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_foldopen, "foldopen", ex_foldopen,
+ RANGE|BANG|WHOLEFOLD|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_function, "function", ex_function,
+ EXTRA|BANG|CMDWIN),
+EX(CMD_global, "global", ex_global,
+ RANGE|WHOLEFOLD|BANG|EXTRA|DFLALL|CMDWIN),
+EX(CMD_goto, "goto", ex_goto,
+ RANGE|NOTADR|COUNT|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_grep, "grep", ex_make,
+ BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE),
+EX(CMD_grepadd, "grepadd", ex_make,
+ BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE),
+EX(CMD_gui, "gui", ex_gui,
+ BANG|FILES|EDITCMD|ARGOPT|TRLBAR|CMDWIN),
+EX(CMD_gvim, "gvim", ex_gui,
+ BANG|FILES|EDITCMD|ARGOPT|TRLBAR|CMDWIN),
+EX(CMD_help, "help", ex_help,
+ BANG|EXTRA|NOTRLCOM),
+EX(CMD_helpfind, "helpfind", ex_helpfind,
+ EXTRA|NOTRLCOM),
+EX(CMD_helpgrep, "helpgrep", ex_helpgrep,
+ EXTRA|NOTRLCOM|NEEDARG),
+EX(CMD_helptags, "helptags", ex_helptags,
+ NEEDARG|FILE1|TRLBAR|CMDWIN),
+EX(CMD_hardcopy, "hardcopy", ex_hardcopy,
+ RANGE|COUNT|EXTRA|TRLBAR|DFLALL|BANG),
+EX(CMD_highlight, "highlight", ex_highlight,
+ BANG|EXTRA|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_hide, "hide", ex_hide,
+ BANG|EXTRA|NOTRLCOM),
+EX(CMD_history, "history", ex_history,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_insert, "insert", ex_append,
+ BANG|RANGE|TRLBAR|CMDWIN|MODIFY),
+EX(CMD_iabbrev, "iabbrev", ex_abbreviate,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_iabclear, "iabclear", ex_abclear,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_if, "if", ex_if,
+ EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_ijump, "ijump", ex_findpat,
+ BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA),
+EX(CMD_ilist, "ilist", ex_findpat,
+ BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA|CMDWIN),
+EX(CMD_imap, "imap", ex_map,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_imapclear, "imapclear", ex_mapclear,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_imenu, "imenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_inoremap, "inoremap", ex_map,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_inoreabbrev, "inoreabbrev", ex_abbreviate,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_inoremenu, "inoremenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_intro, "intro", ex_intro,
+ TRLBAR|CMDWIN),
+EX(CMD_isearch, "isearch", ex_findpat,
+ BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA|CMDWIN),
+EX(CMD_isplit, "isplit", ex_findpat,
+ BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA),
+EX(CMD_iunmap, "iunmap", ex_unmap,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_iunabbrev, "iunabbrev", ex_abbreviate,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_iunmenu, "iunmenu", ex_menu,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_join, "join", ex_join,
+ BANG|RANGE|WHOLEFOLD|COUNT|TRLBAR|CMDWIN|MODIFY),
+EX(CMD_jumps, "jumps", ex_jumps,
+ TRLBAR|CMDWIN),
+EX(CMD_k, "k", ex_mark,
+ RANGE|WORD1|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_keepmarks, "keepmarks", ex_wrongmodifier,
+ NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_keepjumps, "keepjumps", ex_wrongmodifier,
+ NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_list, "list", ex_print,
+ RANGE|WHOLEFOLD|COUNT|TRLBAR|CMDWIN),
+EX(CMD_last, "last", ex_last,
+ EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_language, "language", ex_language,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_lcd, "lcd", ex_cd,
+ FILE1|TRLBAR|CMDWIN),
+EX(CMD_lchdir, "lchdir", ex_cd,
+ FILE1|TRLBAR|CMDWIN),
+EX(CMD_left, "left", ex_align,
+ TRLBAR|RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
+EX(CMD_leftabove, "leftabove", ex_wrongmodifier,
+ NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_let, "let", ex_let,
+ EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_lmap, "lmap", ex_map,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_lmapclear, "lmapclear", ex_mapclear,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_lnoremap, "lnoremap", ex_map,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_loadview, "loadview", ex_loadview,
+ FILE1|TRLBAR),
+EX(CMD_loadkeymap, "loadkeymap", ex_loadkeymap,
+ CMDWIN),
+EX(CMD_lockmarks, "lockmarks", ex_wrongmodifier,
+ NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_lunmap, "lunmap", ex_unmap,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_ls, "ls", buflist_list,
+ BANG|TRLBAR|CMDWIN),
+EX(CMD_move, "move", ex_copymove,
+ RANGE|WHOLEFOLD|EXTRA|TRLBAR|CMDWIN|MODIFY),
+EX(CMD_mark, "mark", ex_mark,
+ RANGE|WORD1|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_make, "make", ex_make,
+ BANG|EXTRA|NOTRLCOM|TRLBAR|XFILE),
+EX(CMD_map, "map", ex_map,
+ BANG|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_mapclear, "mapclear", ex_mapclear,
+ EXTRA|BANG|TRLBAR|CMDWIN),
+EX(CMD_marks, "marks", do_marks,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_match, "match", ex_match,
+ EXTRA|CMDWIN),
+EX(CMD_menu, "menu", ex_menu,
+ RANGE|NOTADR|ZEROR|BANG|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_menutranslate, "menutranslate", ex_menutranslate,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_messages, "messages", ex_messages,
+ TRLBAR|CMDWIN),
+EX(CMD_mkexrc, "mkexrc", ex_mkrc,
+ BANG|FILE1|TRLBAR|CMDWIN),
+EX(CMD_mksession, "mksession", ex_mkrc,
+ BANG|FILE1|TRLBAR),
+EX(CMD_mkvimrc, "mkvimrc", ex_mkrc,
+ BANG|FILE1|TRLBAR|CMDWIN),
+EX(CMD_mkview, "mkview", ex_mkrc,
+ BANG|FILE1|TRLBAR),
+EX(CMD_mode, "mode", ex_mode,
+ WORD1|TRLBAR|CMDWIN),
+EX(CMD_next, "next", ex_next,
+ RANGE|NOTADR|BANG|FILES|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_new, "new", ex_splitview,
+ BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_nmap, "nmap", ex_map,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_nmapclear, "nmapclear", ex_mapclear,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_nmenu, "nmenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_nnoremap, "nnoremap", ex_map,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_nnoremenu, "nnoremenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_noremap, "noremap", ex_map,
+ BANG|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_nohlsearch, "nohlsearch", ex_nohlsearch,
+ TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_noreabbrev, "noreabbrev", ex_abbreviate,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_noremenu, "noremenu", ex_menu,
+ RANGE|NOTADR|ZEROR|BANG|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_normal, "normal", ex_normal,
+ RANGE|BANG|EXTRA|NEEDARG|NOTRLCOM|USECTRLV|SBOXOK|CMDWIN),
+EX(CMD_number, "number", ex_print,
+ RANGE|WHOLEFOLD|COUNT|TRLBAR|CMDWIN),
+EX(CMD_nunmap, "nunmap", ex_unmap,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_nunmenu, "nunmenu", ex_menu,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_open, "open", ex_ni,
+ TRLBAR), /* not supported */
+EX(CMD_omap, "omap", ex_map,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_omapclear, "omapclear", ex_mapclear,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_omenu, "omenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_only, "only", ex_only,
+ BANG|TRLBAR),
+EX(CMD_onoremap, "onoremap", ex_map,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_onoremenu, "onoremenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_options, "options", ex_options,
+ TRLBAR),
+EX(CMD_ounmap, "ounmap", ex_unmap,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_ounmenu, "ounmenu", ex_menu,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_print, "print", ex_print,
+ RANGE|WHOLEFOLD|COUNT|TRLBAR|CMDWIN),
+EX(CMD_pclose, "pclose", ex_pclose,
+ BANG|TRLBAR),
+EX(CMD_perl, "perl", ex_perl,
+ RANGE|EXTRA|DFLALL|NEEDARG|SBOXOK|CMDWIN),
+EX(CMD_perldo, "perldo", ex_perldo,
+ RANGE|EXTRA|DFLALL|NEEDARG|CMDWIN),
+EX(CMD_pedit, "pedit", ex_pedit,
+ BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_pop, "pop", ex_tag,
+ RANGE|NOTADR|BANG|COUNT|TRLBAR|ZEROR),
+EX(CMD_popup, "popup", ex_popup,
+ NEEDARG|EXTRA|TRLBAR|NOTRLCOM|CMDWIN),
+EX(CMD_ppop, "ppop", ex_ptag,
+ RANGE|NOTADR|BANG|COUNT|TRLBAR|ZEROR),
+EX(CMD_preserve, "preserve", ex_preserve,
+ TRLBAR),
+EX(CMD_previous, "previous", ex_previous,
+ EXTRA|RANGE|NOTADR|COUNT|BANG|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_promptfind, "promptfind", gui_mch_find_dialog,
+ EXTRA|NOTRLCOM|CMDWIN),
+EX(CMD_promptrepl, "promptrepl", gui_mch_replace_dialog,
+ EXTRA|NOTRLCOM|CMDWIN),
+EX(CMD_psearch, "psearch", ex_psearch,
+ BANG|RANGE|WHOLEFOLD|DFLALL|EXTRA),
+EX(CMD_ptag, "ptag", ex_ptag,
+ RANGE|NOTADR|BANG|WORD1|TRLBAR|ZEROR),
+EX(CMD_ptNext, "ptNext", ex_ptag,
+ RANGE|NOTADR|BANG|TRLBAR|ZEROR),
+EX(CMD_ptfirst, "ptfirst", ex_ptag,
+ RANGE|NOTADR|BANG|TRLBAR|ZEROR),
+EX(CMD_ptjump, "ptjump", ex_ptag,
+ BANG|TRLBAR|WORD1),
+EX(CMD_ptlast, "ptlast", ex_ptag,
+ BANG|TRLBAR),
+EX(CMD_ptnext, "ptnext", ex_ptag,
+ RANGE|NOTADR|BANG|TRLBAR|ZEROR),
+EX(CMD_ptprevious, "ptprevious", ex_ptag,
+ RANGE|NOTADR|BANG|TRLBAR|ZEROR),
+EX(CMD_ptrewind, "ptrewind", ex_ptag,
+ RANGE|NOTADR|BANG|TRLBAR|ZEROR),
+EX(CMD_ptselect, "ptselect", ex_ptag,
+ BANG|TRLBAR|WORD1),
+EX(CMD_put, "put", ex_put,
+ RANGE|WHOLEFOLD|BANG|REGSTR|TRLBAR|ZEROR|CMDWIN|MODIFY),
+EX(CMD_pwd, "pwd", ex_pwd,
+ TRLBAR|CMDWIN),
+EX(CMD_python, "python", ex_python,
+ RANGE|EXTRA|NEEDARG|CMDWIN),
+EX(CMD_pyfile, "pyfile", ex_pyfile,
+ RANGE|FILE1|NEEDARG|CMDWIN),
+EX(CMD_quit, "quit", ex_quit,
+ BANG|TRLBAR|CMDWIN),
+EX(CMD_quitall, "quitall", ex_quit_all,
+ BANG|TRLBAR),
+EX(CMD_qall, "qall", ex_quit_all,
+ BANG|TRLBAR|CMDWIN),
+EX(CMD_read, "read", ex_read,
+ BANG|RANGE|WHOLEFOLD|FILE1|ARGOPT|TRLBAR|ZEROR|CMDWIN|MODIFY),
+EX(CMD_recover, "recover", ex_recover,
+ BANG|FILE1|TRLBAR),
+EX(CMD_redo, "redo", ex_redo,
+ TRLBAR|CMDWIN),
+EX(CMD_redir, "redir", ex_redir,
+ BANG|FILES|TRLBAR|CMDWIN),
+EX(CMD_redraw, "redraw", ex_redraw,
+ BANG|TRLBAR|CMDWIN),
+EX(CMD_redrawstatus, "redrawstatus", ex_redrawstatus,
+ BANG|TRLBAR|CMDWIN),
+EX(CMD_registers, "registers", ex_display,
+ EXTRA|NOTRLCOM|TRLBAR|CMDWIN),
+EX(CMD_resize, "resize", ex_resize,
+ RANGE|NOTADR|TRLBAR|WORD1),
+EX(CMD_retab, "retab", ex_retab,
+ TRLBAR|RANGE|WHOLEFOLD|DFLALL|BANG|WORD1|CMDWIN|MODIFY),
+EX(CMD_return, "return", ex_return,
+ EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_rewind, "rewind", ex_rewind,
+ EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_right, "right", ex_align,
+ TRLBAR|RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
+EX(CMD_rightbelow, "rightbelow", ex_wrongmodifier,
+ NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_runtime, "runtime", ex_runtime,
+ BANG|NEEDARG|FILES|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_ruby, "ruby", ex_ruby,
+ RANGE|EXTRA|NEEDARG|CMDWIN),
+EX(CMD_rubydo, "rubydo", ex_rubydo,
+ RANGE|DFLALL|EXTRA|NEEDARG|CMDWIN),
+EX(CMD_rubyfile, "rubyfile", ex_rubyfile,
+ RANGE|FILE1|NEEDARG|CMDWIN),
+EX(CMD_rviminfo, "rviminfo", ex_viminfo,
+ BANG|FILE1|TRLBAR|CMDWIN),
+EX(CMD_substitute, "substitute", do_sub,
+ RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
+EX(CMD_sNext, "sNext", ex_previous,
+ EXTRA|RANGE|NOTADR|COUNT|BANG|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_sargument, "sargument", ex_argument,
+ BANG|RANGE|NOTADR|COUNT|EXTRA|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_sall, "sall", ex_all,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_saveas, "saveas", ex_write,
+ BANG|DFLALL|FILE1|ARGOPT|CMDWIN|TRLBAR),
+EX(CMD_sbuffer, "sbuffer", ex_buffer,
+ BANG|RANGE|NOTADR|BUFNAME|BUFUNL|COUNT|EXTRA|TRLBAR),
+EX(CMD_sbNext, "sbNext", ex_bprevious,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_sball, "sball", ex_buffer_all,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_sbfirst, "sbfirst", ex_brewind,
+ TRLBAR),
+EX(CMD_sblast, "sblast", ex_blast,
+ TRLBAR),
+EX(CMD_sbmodified, "sbmodified", ex_bmodified,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_sbnext, "sbnext", ex_bnext,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_sbprevious, "sbprevious", ex_bprevious,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_sbrewind, "sbrewind", ex_brewind,
+ TRLBAR),
+EX(CMD_scriptnames, "scriptnames", ex_scriptnames,
+ TRLBAR|CMDWIN),
+EX(CMD_scriptencoding, "scriptencoding", ex_scriptencoding,
+ WORD1|TRLBAR|CMDWIN),
+EX(CMD_scscope, "scscope", do_scscope,
+ EXTRA|NOTRLCOM|SBOXOK),
+EX(CMD_set, "set", ex_set,
+ TRLBAR|EXTRA|CMDWIN|SBOXOK),
+EX(CMD_setfiletype, "setfiletype", ex_setfiletype,
+ TRLBAR|EXTRA|NEEDARG|CMDWIN),
+EX(CMD_setglobal, "setglobal", ex_set,
+ TRLBAR|EXTRA|CMDWIN),
+EX(CMD_setlocal, "setlocal", ex_set,
+ TRLBAR|EXTRA|CMDWIN),
+EX(CMD_sfind, "sfind", ex_splitview,
+ BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_sfirst, "sfirst", ex_rewind,
+ EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_shell, "shell", ex_shell,
+ TRLBAR|CMDWIN),
+EX(CMD_simalt, "simalt", ex_simalt,
+ NEEDARG|WORD1|TRLBAR|CMDWIN),
+EX(CMD_sign, "sign", ex_sign,
+ NEEDARG|RANGE|NOTADR|EXTRA|CMDWIN),
+EX(CMD_silent, "silent", ex_wrongmodifier,
+ NEEDARG|EXTRA|BANG|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_sleep, "sleep", ex_sleep,
+ RANGE|NOTADR|COUNT|EXTRA|TRLBAR|CMDWIN),
+EX(CMD_slast, "slast", ex_last,
+ EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_smagic, "smagic", ex_submagic,
+ RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
+EX(CMD_snext, "snext", ex_next,
+ RANGE|NOTADR|BANG|FILES|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_sniff, "sniff", ex_sniff,
+ EXTRA|TRLBAR),
+EX(CMD_snomagic, "snomagic", ex_submagic,
+ RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
+EX(CMD_source, "source", ex_source,
+ BANG|FILE1|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_split, "split", ex_splitview,
+ BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_sprevious, "sprevious", ex_previous,
+ EXTRA|RANGE|NOTADR|COUNT|BANG|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_srewind, "srewind", ex_rewind,
+ EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_stop, "stop", ex_stop,
+ TRLBAR|BANG|CMDWIN),
+EX(CMD_stag, "stag", ex_stag,
+ RANGE|NOTADR|BANG|WORD1|TRLBAR|ZEROR),
+EX(CMD_startinsert, "startinsert", ex_startinsert,
+ BANG|TRLBAR|CMDWIN),
+EX(CMD_stopinsert, "stopinsert", ex_stopinsert,
+ BANG|TRLBAR|CMDWIN),
+EX(CMD_stjump, "stjump", ex_stag,
+ BANG|TRLBAR|WORD1),
+EX(CMD_stselect, "stselect", ex_stag,
+ BANG|TRLBAR|WORD1),
+EX(CMD_sunhide, "sunhide", ex_buffer_all,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_suspend, "suspend", ex_stop,
+ TRLBAR|BANG|CMDWIN),
+EX(CMD_sview, "sview", ex_splitview,
+ NEEDARG|RANGE|NOTADR|BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_swapname, "swapname", ex_swapname,
+ TRLBAR|CMDWIN),
+EX(CMD_syntax, "syntax", ex_syntax,
+ EXTRA|NOTRLCOM|CMDWIN),
+EX(CMD_syncbind, "syncbind", ex_syncbind,
+ TRLBAR),
+EX(CMD_t, "t", ex_copymove,
+ RANGE|WHOLEFOLD|EXTRA|TRLBAR|CMDWIN|MODIFY),
+EX(CMD_tNext, "tNext", ex_tag,
+ RANGE|NOTADR|BANG|TRLBAR|ZEROR),
+EX(CMD_tag, "tag", ex_tag,
+ RANGE|NOTADR|BANG|WORD1|TRLBAR|ZEROR),
+EX(CMD_tags, "tags", do_tags,
+ TRLBAR|CMDWIN),
+EX(CMD_tcl, "tcl", ex_tcl,
+ RANGE|EXTRA|NEEDARG|CMDWIN),
+EX(CMD_tcldo, "tcldo", ex_tcldo,
+ RANGE|DFLALL|EXTRA|NEEDARG|CMDWIN),
+EX(CMD_tclfile, "tclfile", ex_tclfile,
+ RANGE|FILE1|NEEDARG|CMDWIN),
+EX(CMD_tearoff, "tearoff", ex_tearoff,
+ NEEDARG|EXTRA|TRLBAR|NOTRLCOM|CMDWIN),
+EX(CMD_tfirst, "tfirst", ex_tag,
+ RANGE|NOTADR|BANG|TRLBAR|ZEROR),
+EX(CMD_throw, "throw", ex_throw,
+ EXTRA|NEEDARG|SBOXOK|CMDWIN),
+EX(CMD_tjump, "tjump", ex_tag,
+ BANG|TRLBAR|WORD1),
+EX(CMD_tlast, "tlast", ex_tag,
+ BANG|TRLBAR),
+EX(CMD_tmenu, "tmenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_tnext, "tnext", ex_tag,
+ RANGE|NOTADR|BANG|TRLBAR|ZEROR),
+EX(CMD_topleft, "topleft", ex_wrongmodifier,
+ NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_tprevious, "tprevious", ex_tag,
+ RANGE|NOTADR|BANG|TRLBAR|ZEROR),
+EX(CMD_trewind, "trewind", ex_tag,
+ RANGE|NOTADR|BANG|TRLBAR|ZEROR),
+EX(CMD_try, "try", ex_try,
+ TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_tselect, "tselect", ex_tag,
+ BANG|TRLBAR|WORD1),
+EX(CMD_tunmenu, "tunmenu", ex_menu,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_undo, "undo", ex_undo,
+ TRLBAR|CMDWIN),
+EX(CMD_unabbreviate, "unabbreviate", ex_abbreviate,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_unhide, "unhide", ex_buffer_all,
+ RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_unlet, "unlet", ex_unlet,
+ BANG|EXTRA|NEEDARG|SBOXOK|CMDWIN),
+EX(CMD_unmap, "unmap", ex_unmap,
+ BANG|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_unmenu, "unmenu", ex_menu,
+ BANG|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_update, "update", ex_update,
+ RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR),
+EX(CMD_vglobal, "vglobal", ex_global,
+ RANGE|WHOLEFOLD|EXTRA|DFLALL|CMDWIN),
+EX(CMD_version, "version", ex_version,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_verbose, "verbose", ex_wrongmodifier,
+ NEEDARG|RANGE|NOTADR|EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_vertical, "vertical", ex_wrongmodifier,
+ NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_visual, "visual", ex_edit,
+ BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_view, "view", ex_edit,
+ BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_vmap, "vmap", ex_map,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_vmapclear, "vmapclear", ex_mapclear,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_vmenu, "vmenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_vnoremap, "vnoremap", ex_map,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_vnew, "vnew", ex_splitview,
+ BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_vnoremenu, "vnoremenu", ex_menu,
+ RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_vsplit, "vsplit", ex_splitview,
+ BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_vunmap, "vunmap", ex_unmap,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_vunmenu, "vunmenu", ex_menu,
+ EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
+EX(CMD_write, "write", ex_write,
+ RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR|CMDWIN),
+EX(CMD_wNext, "wNext", ex_wnext,
+ RANGE|WHOLEFOLD|NOTADR|BANG|FILE1|ARGOPT|TRLBAR),
+EX(CMD_wall, "wall", do_wqall,
+ BANG|TRLBAR|CMDWIN),
+EX(CMD_while, "while", ex_while,
+ EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
+EX(CMD_winsize, "winsize", ex_winsize,
+ EXTRA|NEEDARG|TRLBAR),
+EX(CMD_wincmd, "wincmd", ex_wincmd,
+ NEEDARG|WORD1|RANGE|NOTADR),
+EX(CMD_windo, "windo", ex_listdo,
+ BANG|NEEDARG|EXTRA|NOTRLCOM),
+EX(CMD_winpos, "winpos", ex_winpos,
+ EXTRA|TRLBAR|CMDWIN),
+EX(CMD_wnext, "wnext", ex_wnext,
+ RANGE|NOTADR|BANG|FILE1|ARGOPT|TRLBAR),
+EX(CMD_wprevious, "wprevious", ex_wnext,
+ RANGE|NOTADR|BANG|FILE1|ARGOPT|TRLBAR),
+EX(CMD_wq, "wq", ex_exit,
+ RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR),
+EX(CMD_wqall, "wqall", do_wqall,
+ BANG|FILE1|ARGOPT|DFLALL|TRLBAR),
+EX(CMD_wsverb, "wsverb", ex_wsverb,
+ EXTRA|NOTADR|NEEDARG),
+EX(CMD_wviminfo, "wviminfo", ex_viminfo,
+ BANG|FILE1|TRLBAR|CMDWIN),
+EX(CMD_xit, "xit", ex_exit,
+ RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR|CMDWIN),
+EX(CMD_xall, "xall", do_wqall,
+ BANG|TRLBAR),
+EX(CMD_yank, "yank", ex_operators,
+ RANGE|WHOLEFOLD|REGSTR|COUNT|TRLBAR|CMDWIN),
+EX(CMD_z, "z", ex_z,
+ RANGE|WHOLEFOLD|EXTRA|TRLBAR|CMDWIN),
+
+/* commands that don't start with a lowercase letter */
+EX(CMD_bang, "!", ex_bang,
+ RANGE|WHOLEFOLD|BANG|FILES|CMDWIN),
+EX(CMD_pound, "#", ex_print,
+ RANGE|WHOLEFOLD|COUNT|TRLBAR|CMDWIN),
+EX(CMD_and, "&", do_sub,
+ RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
+EX(CMD_star, "*", ex_at,
+ RANGE|WHOLEFOLD|EXTRA|TRLBAR|CMDWIN),
+EX(CMD_lshift, "<", ex_operators,
+ RANGE|WHOLEFOLD|COUNT|TRLBAR|CMDWIN|MODIFY),
+EX(CMD_equal, "=", ex_equal,
+ RANGE|TRLBAR|DFLALL|CMDWIN),
+EX(CMD_rshift, ">", ex_operators,
+ RANGE|WHOLEFOLD|COUNT|TRLBAR|CMDWIN|MODIFY),
+EX(CMD_at, "@", ex_at,
+ RANGE|WHOLEFOLD|EXTRA|TRLBAR|CMDWIN),
+EX(CMD_Next, "Next", ex_previous,
+ EXTRA|RANGE|NOTADR|COUNT|BANG|EDITCMD|ARGOPT|TRLBAR),
+EX(CMD_Print, "Print", ex_print,
+ RANGE|WHOLEFOLD|COUNT|TRLBAR|CMDWIN),
+EX(CMD_X, "X", ex_X,
+ TRLBAR),
+EX(CMD_tilde, "~", do_sub,
+ RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
+
+#ifndef DO_DECLARE_EXCMD
+#ifdef FEAT_USR_CMDS
+ CMD_SIZE, /* MUST be after all real commands! */
+ CMD_USER = -1, /* User-defined command */
+ CMD_USER_BUF = -2 /* User-defined command local to buffer */
+#else
+ CMD_SIZE /* MUST be the last one! */
+#endif
+#endif
+};
+
+#define USER_CMDIDX(idx) ((int)(idx) < 0)
+
+#ifndef DO_DECLARE_EXCMD
+typedef enum CMD_index cmdidx_T;
+
+/*
+ * Arguments used for Ex commands.
+ */
+struct exarg
+{
+ char_u *arg; /* argument of the command */
+ char_u *nextcmd; /* next command (NULL if none) */
+ char_u *cmd; /* the name of the command (except for :make) */
+ char_u **cmdlinep; /* pointer to pointer of allocated cmdline */
+ cmdidx_T cmdidx; /* the index for the command */
+ long argt; /* flags for the command */
+ int skip; /* don't execute the command, only parse it */
+ int forceit; /* TRUE if ! present */
+ int addr_count; /* the number of addresses given */
+ linenr_T line1; /* the first line number */
+ linenr_T line2; /* the second line number or count */
+ char_u *do_ecmd_cmd; /* +command arg to be used in edited file */
+ linenr_T do_ecmd_lnum; /* the line number in an edited file */
+ int append; /* TRUE with ":w >>file" command */
+ int usefilter; /* TRUE with ":w !command" and ":r!command" */
+ int amount; /* number of '>' or '<' for shift command */
+ int regname; /* register name (NUL if none) */
+ int force_bin; /* 0, FORCE_BIN or FORCE_NOBIN */
+ int force_ff; /* forced 'fileformat' (index in cmd[]) */
+#ifdef FEAT_MBYTE
+ int force_enc; /* forced 'encoding' (index in cmd[]) */
+#endif
+#ifdef FEAT_USR_CMDS
+ int useridx; /* user command index */
+#endif
+ char_u *errmsg; /* returned error message */
+ char_u *(*getline) __ARGS((int, void *, int));
+ void *cookie; /* argument for getline() */
+#ifdef FEAT_EVAL
+ struct condstack *cstack; /* condition stack for ":if" etc. */
+#endif
+};
+
+#define FORCE_BIN 1 /* ":edit ++bin file" */
+#define FORCE_NOBIN 2 /* ":edit ++nobin file" */
+
+#endif
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c
new file mode 100644
index 000000000..8ec8be71a
--- /dev/null
+++ b/src/ex_cmds2.c
@@ -0,0 +1,5711 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * ex_cmds2.c: some more functions for command line commands
+ */
+
+#if defined(WIN32) && defined(FEAT_CSCOPE)
+# include <io.h>
+#endif
+
+#include "vim.h"
+
+#if defined(WIN32) && defined(FEAT_CSCOPE)
+# include <fcntl.h>
+#endif
+
+#include "version.h"
+
+static void cmd_source __ARGS((char_u *fname, exarg_T *eap));
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+static int debug_greedy = FALSE; /* batch mode debugging: don't save
+ and restore typeahead. */
+
+/*
+ * do_debug(): Debug mode.
+ * Repeatedly get Ex commands, until told to continue normal execution.
+ */
+ void
+do_debug(cmd)
+ char_u *cmd;
+{
+ int save_msg_scroll = msg_scroll;
+ int save_State = State;
+ int save_did_emsg = did_emsg;
+ int save_cmd_silent = cmd_silent;
+ int save_msg_silent = msg_silent;
+ int save_emsg_silent = emsg_silent;
+ int save_redir_off = redir_off;
+ tasave_T typeaheadbuf;
+# ifdef FEAT_EX_EXTRA
+ int save_ex_normal_busy;
+# endif
+ int n;
+ char_u *cmdline = NULL;
+ char_u *p;
+ char *tail = NULL;
+ static int last_cmd = 0;
+#define CMD_CONT 1
+#define CMD_NEXT 2
+#define CMD_STEP 3
+#define CMD_FINISH 4
+#define CMD_QUIT 5
+#define CMD_INTERRUPT 6
+
+#ifdef ALWAYS_USE_GUI
+ /* Can't do this when there is no terminal for input/output. */
+ if (!gui.in_use)
+ {
+ /* Break as soon as possible. */
+ debug_break_level = 9999;
+ return;
+ }
+#endif
+
+ /* Make sure we are in raw mode and start termcap mode. Might have side
+ * effects... */
+ settmode(TMODE_RAW);
+ starttermcap();
+
+ ++RedrawingDisabled; /* don't redisplay the window */
+ ++no_wait_return; /* don't wait for return */
+ did_emsg = FALSE; /* don't use error from debugged stuff */
+ cmd_silent = FALSE; /* display commands */
+ msg_silent = FALSE; /* display messages */
+ emsg_silent = FALSE; /* display error messages */
+ redir_off = TRUE; /* don't redirect debug commands */
+
+ State = NORMAL;
+#ifdef FEAT_SNIFF
+ want_sniff_request = 0; /* No K_SNIFF wanted */
+#endif
+
+ if (!debug_did_msg)
+ MSG(_("Entering Debug mode. Type \"cont\" to continue."));
+ if (sourcing_name != NULL)
+ msg(sourcing_name);
+ if (sourcing_lnum != 0)
+ smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd);
+ else
+ msg_str((char_u *)_("cmd: %s"), cmd);
+
+ /*
+ * Repeat getting a command and executing it.
+ */
+ for (;;)
+ {
+ msg_scroll = TRUE;
+ need_wait_return = FALSE;
+#ifdef FEAT_SNIFF
+ ProcessSniffRequests();
+#endif
+ /* Save the current typeahead buffer and replace it with an empty one.
+ * This makes sure we get input from the user here and don't interfere
+ * with the commands being executed. Reset "ex_normal_busy" to avoid
+ * the side effects of using ":normal". Save the stuff buffer and make
+ * it empty. */
+# ifdef FEAT_EX_EXTRA
+ save_ex_normal_busy = ex_normal_busy;
+ ex_normal_busy = 0;
+# endif
+ if (!debug_greedy)
+ save_typeahead(&typeaheadbuf);
+
+ cmdline = getcmdline_prompt('>', NULL, 0);
+
+ if (!debug_greedy)
+ restore_typeahead(&typeaheadbuf);
+# ifdef FEAT_EX_EXTRA
+ ex_normal_busy = save_ex_normal_busy;
+# endif
+
+ cmdline_row = msg_row;
+ if (cmdline != NULL)
+ {
+ /* If this is a debug command, set "last_cmd".
+ * If not, reset "last_cmd".
+ * For a blank line use previous command. */
+ p = skipwhite(cmdline);
+ if (*p != NUL)
+ {
+ switch (*p)
+ {
+ case 'c': last_cmd = CMD_CONT;
+ tail = "ont";
+ break;
+ case 'n': last_cmd = CMD_NEXT;
+ tail = "ext";
+ break;
+ case 's': last_cmd = CMD_STEP;
+ tail = "tep";
+ break;
+ case 'f': last_cmd = CMD_FINISH;
+ tail = "inish";
+ break;
+ case 'q': last_cmd = CMD_QUIT;
+ tail = "uit";
+ break;
+ case 'i': last_cmd = CMD_INTERRUPT;
+ tail = "nterrupt";
+ break;
+ default: last_cmd = 0;
+ }
+ if (last_cmd != 0)
+ {
+ /* Check that the tail matches. */
+ ++p;
+ while (*p != NUL && *p == *tail)
+ {
+ ++p;
+ ++tail;
+ }
+ if (ASCII_ISALPHA(*p))
+ last_cmd = 0;
+ }
+ }
+
+ if (last_cmd != 0)
+ {
+ /* Execute debug command: decided where to break next and
+ * return. */
+ switch (last_cmd)
+ {
+ case CMD_CONT:
+ debug_break_level = -1;
+ break;
+ case CMD_NEXT:
+ debug_break_level = ex_nesting_level;
+ break;
+ case CMD_STEP:
+ debug_break_level = 9999;
+ break;
+ case CMD_FINISH:
+ debug_break_level = ex_nesting_level - 1;
+ break;
+ case CMD_QUIT:
+ got_int = TRUE;
+ debug_break_level = -1;
+ break;
+ case CMD_INTERRUPT:
+ got_int = TRUE;
+ debug_break_level = 9999;
+ /* Do not repeat ">interrupt" cmd, continue stepping. */
+ last_cmd = CMD_STEP;
+ break;
+ }
+ break;
+ }
+
+ /* don't debug this command */
+ n = debug_break_level;
+ debug_break_level = -1;
+ (void)do_cmdline(cmdline, getexline, NULL,
+ DOCMD_VERBOSE|DOCMD_EXCRESET);
+ debug_break_level = n;
+
+ vim_free(cmdline);
+ }
+ lines_left = Rows - 1;
+ }
+ vim_free(cmdline);
+
+ --RedrawingDisabled;
+ --no_wait_return;
+ redraw_all_later(NOT_VALID);
+ need_wait_return = FALSE;
+ msg_scroll = save_msg_scroll;
+ lines_left = Rows - 1;
+ State = save_State;
+ did_emsg = save_did_emsg;
+ cmd_silent = save_cmd_silent;
+ msg_silent = save_msg_silent;
+ emsg_silent = save_emsg_silent;
+ redir_off = save_redir_off;
+
+ /* Only print the message again when typing a command before coming back
+ * here. */
+ debug_did_msg = TRUE;
+}
+
+/*
+ * ":debug".
+ */
+ void
+ex_debug(eap)
+ exarg_T *eap;
+{
+ int debug_break_level_save = debug_break_level;
+
+ debug_break_level = 9999;
+ do_cmdline_cmd(eap->arg);
+ debug_break_level = debug_break_level_save;
+}
+
+static char_u *debug_breakpoint_name = NULL;
+static linenr_T debug_breakpoint_lnum;
+
+/*
+ * When debugging or a breakpoint is set on a skipped command, no debug prompt
+ * is shown by do_one_cmd(). This situation is indicated by debug_skipped, and
+ * debug_skipped_name is then set to the source name in the breakpoint case. If
+ * a skipped command decides itself that a debug prompt should be displayed, it
+ * can do so by calling dbg_check_skipped().
+ */
+static int debug_skipped;
+static char_u *debug_skipped_name;
+
+/*
+ * Go to debug mode when a breakpoint was encountered or "ex_nesting_level" is
+ * at or below the break level. But only when the line is actually
+ * executed. Return TRUE and set breakpoint_name for skipped commands that
+ * decide to execute something themselves.
+ * Called from do_one_cmd() before executing a command.
+ */
+ void
+dbg_check_breakpoint(eap)
+ exarg_T *eap;
+{
+ char_u *p;
+
+ debug_skipped = FALSE;
+ if (debug_breakpoint_name != NULL)
+ {
+ if (!eap->skip)
+ {
+ /* replace K_SNR with "<SNR>" */
+ if (debug_breakpoint_name[0] == K_SPECIAL
+ && debug_breakpoint_name[1] == KS_EXTRA
+ && debug_breakpoint_name[2] == (int)KE_SNR)
+ p = (char_u *)"<SNR>";
+ else
+ p = (char_u *)"";
+ smsg((char_u *)_("Breakpoint in \"%s%s\" line %ld"), p,
+ debug_breakpoint_name + (*p == NUL ? 0 : 3),
+ (long)debug_breakpoint_lnum);
+ debug_breakpoint_name = NULL;
+ do_debug(eap->cmd);
+ }
+ else
+ {
+ debug_skipped = TRUE;
+ debug_skipped_name = debug_breakpoint_name;
+ debug_breakpoint_name = NULL;
+ }
+ }
+ else if (ex_nesting_level <= debug_break_level)
+ {
+ if (!eap->skip)
+ do_debug(eap->cmd);
+ else
+ {
+ debug_skipped = TRUE;
+ debug_skipped_name = NULL;
+ }
+ }
+}
+
+/*
+ * Go to debug mode if skipped by dbg_check_breakpoint() because eap->skip was
+ * set. Return TRUE when the debug mode is entered this time.
+ */
+ int
+dbg_check_skipped(eap)
+ exarg_T *eap;
+{
+ int prev_got_int;
+
+ if (debug_skipped)
+ {
+ /*
+ * Save the value of got_int and reset it. We don't want a previous
+ * interruption cause flushing the input buffer.
+ */
+ prev_got_int = got_int;
+ got_int = FALSE;
+ debug_breakpoint_name = debug_skipped_name;
+ /* eap->skip is TRUE */
+ eap->skip = FALSE;
+ (void)dbg_check_breakpoint(eap);
+ eap->skip = TRUE;
+ got_int |= prev_got_int;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * The list of breakpoints: dbg_breakp.
+ * This is a grow-array of structs.
+ */
+struct debuggy
+{
+ int dbg_nr; /* breakpoint number */
+ int dbg_type; /* DBG_FUNC or DBG_FILE */
+ char_u *dbg_name; /* function or file name */
+ regprog_T *dbg_prog; /* regexp program */
+ linenr_T dbg_lnum; /* line number in function or file */
+};
+
+static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL};
+#define BREAKP(idx) (((struct debuggy *)dbg_breakp.ga_data)[idx])
+static int last_breakp = 0; /* nr of last defined breakpoint */
+
+#define DBG_FUNC 1
+#define DBG_FILE 2
+
+static int dbg_parsearg __ARGS((char_u *arg));
+
+/*
+ * Parse the arguments of ":breakadd" or ":breakdel" and put them in the entry
+ * just after the last one in dbg_breakp. Note that "dbg_name" is allocated.
+ * Returns FAIL for failure.
+ */
+ static int
+dbg_parsearg(arg)
+ char_u *arg;
+{
+ char_u *p = arg;
+ char_u *q;
+ struct debuggy *bp;
+
+ if (ga_grow(&dbg_breakp, 1) == FAIL)
+ return FAIL;
+ bp = &BREAKP(dbg_breakp.ga_len);
+
+ /* Find "func" or "file". */
+ if (STRNCMP(p, "func", 4) == 0)
+ bp->dbg_type = DBG_FUNC;
+ else if (STRNCMP(p, "file", 4) == 0)
+ bp->dbg_type = DBG_FILE;
+ else
+ {
+ EMSG2(_(e_invarg2), p);
+ return FAIL;
+ }
+ p = skipwhite(p + 4);
+
+ /* Find optional line number. */
+ if (VIM_ISDIGIT(*p))
+ {
+ bp->dbg_lnum = getdigits(&p);
+ p = skipwhite(p);
+ }
+ else
+ bp->dbg_lnum = 0;
+
+ /* Find the function or file name. Don't accept a function name with (). */
+ if (*p == NUL
+ || (bp->dbg_type == DBG_FUNC && strstr((char *)p, "()") != NULL))
+ {
+ EMSG2(_(e_invarg2), arg);
+ return FAIL;
+ }
+
+ if (bp->dbg_type == DBG_FUNC)
+ bp->dbg_name = vim_strsave(p);
+ else
+ {
+ /* Expand the file name in the same way as do_source(). This means
+ * doing it twice, so that $DIR/file gets expanded when $DIR is
+ * "~/dir". */
+#ifdef RISCOS
+ q = mch_munge_fname(p);
+#else
+ q = expand_env_save(p);
+#endif
+ if (q == NULL)
+ return FAIL;
+#ifdef RISCOS
+ p = mch_munge_fname(q);
+#else
+ p = expand_env_save(q);
+#endif
+ vim_free(q);
+ if (p == NULL)
+ return FAIL;
+ bp->dbg_name = fix_fname(p);
+ vim_free(p);
+#ifdef MACOS_CLASSIC
+ if (bp->dbg_name != NULL)
+ slash_n_colon_adjust(bp->dbg_name);
+#endif
+ }
+
+ if (bp->dbg_name == NULL)
+ return FAIL;
+ return OK;
+}
+
+/*
+ * ":breakadd".
+ */
+ void
+ex_breakadd(eap)
+ exarg_T *eap;
+{
+ struct debuggy *bp;
+ char_u *pat;
+
+ if (dbg_parsearg(eap->arg) == OK)
+ {
+ bp = &BREAKP(dbg_breakp.ga_len);
+ pat = file_pat_to_reg_pat(bp->dbg_name, NULL, NULL, FALSE);
+ if (pat != NULL)
+ {
+ bp->dbg_prog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
+ vim_free(pat);
+ }
+ if (pat == NULL || bp->dbg_prog == NULL)
+ vim_free(bp->dbg_name);
+ else
+ {
+ if (bp->dbg_lnum == 0) /* default line number is 1 */
+ bp->dbg_lnum = 1;
+ BREAKP(dbg_breakp.ga_len++).dbg_nr = ++last_breakp;
+ --dbg_breakp.ga_room;
+ ++debug_tick;
+ }
+ }
+}
+
+/*
+ * ":debuggreedy".
+ */
+ void
+ex_debuggreedy(eap)
+ exarg_T *eap;
+{
+ if (eap->addr_count == 0 || eap->line2 != 0)
+ debug_greedy = TRUE;
+ else
+ debug_greedy = FALSE;
+}
+
+/*
+ * ":breakdel".
+ */
+ void
+ex_breakdel(eap)
+ exarg_T *eap;
+{
+ struct debuggy *bp, *bpi;
+ int nr;
+ int todel = -1;
+ int i;
+ linenr_T best_lnum = 0;
+
+ if (vim_isdigit(*eap->arg))
+ {
+ /* ":breakdel {nr}" */
+ nr = atol((char *)eap->arg);
+ for (i = 0; i < dbg_breakp.ga_len; ++i)
+ if (BREAKP(i).dbg_nr == nr)
+ {
+ todel = i;
+ break;
+ }
+ }
+ else
+ {
+ /* ":breakdel {func|file} [lnum] {name}" */
+ if (dbg_parsearg(eap->arg) == FAIL)
+ return;
+ bp = &BREAKP(dbg_breakp.ga_len);
+ for (i = 0; i < dbg_breakp.ga_len; ++i)
+ {
+ bpi = &BREAKP(i);
+ if (bp->dbg_type == bpi->dbg_type
+ && STRCMP(bp->dbg_name, bpi->dbg_name) == 0
+ && (bp->dbg_lnum == bpi->dbg_lnum
+ || (bp->dbg_lnum == 0
+ && (best_lnum == 0
+ || bpi->dbg_lnum < best_lnum))))
+ {
+ todel = i;
+ best_lnum = bpi->dbg_lnum;
+ }
+ }
+ vim_free(bp->dbg_name);
+ }
+
+ if (todel < 0)
+ EMSG2(_("E161: Breakpoint not found: %s"), eap->arg);
+ else
+ {
+ vim_free(BREAKP(todel).dbg_name);
+ vim_free(BREAKP(todel).dbg_prog);
+ --dbg_breakp.ga_len;
+ ++dbg_breakp.ga_room;
+ if (todel < dbg_breakp.ga_len)
+ mch_memmove(&BREAKP(todel), &BREAKP(todel + 1),
+ (dbg_breakp.ga_len - todel) * sizeof(struct debuggy));
+ ++debug_tick;
+ }
+}
+
+/*
+ * ":breaklist".
+ */
+/*ARGSUSED*/
+ void
+ex_breaklist(eap)
+ exarg_T *eap;
+{
+ struct debuggy *bp;
+ int i;
+
+ if (dbg_breakp.ga_len == 0)
+ MSG(_("No breakpoints defined"));
+ else
+ for (i = 0; i < dbg_breakp.ga_len; ++i)
+ {
+ bp = &BREAKP(i);
+ smsg((char_u *)_("%3d %s %s line %ld"),
+ bp->dbg_nr,
+ bp->dbg_type == DBG_FUNC ? "func" : "file",
+ bp->dbg_name,
+ (long)bp->dbg_lnum);
+ }
+}
+
+/*
+ * Find a breakpoint for a function or sourced file.
+ * Returns line number at which to break; zero when no matching breakpoint.
+ */
+ linenr_T
+dbg_find_breakpoint(file, fname, after)
+ int file; /* TRUE for a file, FALSE for a function */
+ char_u *fname; /* file or function name */
+ linenr_T after; /* after this line number */
+{
+ struct debuggy *bp;
+ int i;
+ linenr_T lnum = 0;
+ regmatch_T regmatch;
+ char_u *name = fname;
+ int prev_got_int;
+
+ /* Replace K_SNR in function name with "<SNR>". */
+ if (!file && fname[0] == K_SPECIAL)
+ {
+ name = alloc((unsigned)STRLEN(fname) + 3);
+ if (name == NULL)
+ name = fname;
+ else
+ {
+ STRCPY(name, "<SNR>");
+ STRCPY(name + 5, fname + 3);
+ }
+ }
+
+ for (i = 0; i < dbg_breakp.ga_len; ++i)
+ {
+ /* skip entries that are not useful or are for a line that is beyond
+ * an already found breakpoint */
+ bp = &BREAKP(i);
+ if ((bp->dbg_type == DBG_FILE) == file
+ && bp->dbg_lnum > after
+ && (lnum == 0 || bp->dbg_lnum < lnum))
+ {
+ regmatch.regprog = bp->dbg_prog;
+ regmatch.rm_ic = FALSE;
+ /*
+ * Save the value of got_int and reset it. We don't want a previous
+ * interruption cancel matching, only hitting CTRL-C while matching
+ * should abort it.
+ */
+ prev_got_int = got_int;
+ got_int = FALSE;
+ if (vim_regexec(&regmatch, name, (colnr_T)0))
+ lnum = bp->dbg_lnum;
+ got_int |= prev_got_int;
+ }
+ }
+ if (name != fname)
+ vim_free(name);
+
+ return lnum;
+}
+
+/*
+ * Called when a breakpoint was encountered.
+ */
+ void
+dbg_breakpoint(name, lnum)
+ char_u *name;
+ linenr_T lnum;
+{
+ /* We need to check if this line is actually executed in do_one_cmd() */
+ debug_breakpoint_name = name;
+ debug_breakpoint_lnum = lnum;
+}
+#endif
+
+/*
+ * If 'autowrite' option set, try to write the file.
+ * Careful: autocommands may make "buf" invalid!
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+autowrite(buf, forceit)
+ buf_T *buf;
+ int forceit;
+{
+ if (!(p_aw || p_awa) || !p_write
+#ifdef FEAT_QUICKFIX
+ /* never autowrite a "nofile" or "nowrite" buffer */
+ || bt_dontwrite(buf)
+#endif
+ || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
+ return FAIL;
+ return buf_write_all(buf, forceit);
+}
+
+/*
+ * flush all buffers, except the ones that are readonly
+ */
+ void
+autowrite_all()
+{
+ buf_T *buf;
+
+ if (!(p_aw || p_awa) || !p_write)
+ return;
+ for (buf = firstbuf; buf; buf = buf->b_next)
+ if (bufIsChanged(buf) && !buf->b_p_ro)
+ {
+ (void)buf_write_all(buf, FALSE);
+#ifdef FEAT_AUTOCMD
+ /* an autocommand may have deleted the buffer */
+ if (!buf_valid(buf))
+ buf = firstbuf;
+#endif
+ }
+}
+
+/*
+ * return TRUE if buffer was changed and cannot be abandoned.
+ */
+/*ARGSUSED*/
+ int
+check_changed(buf, checkaw, mult_win, forceit, allbuf)
+ buf_T *buf;
+ int checkaw; /* do autowrite if buffer was changed */
+ int mult_win; /* check also when several wins for the buf */
+ int forceit;
+ int allbuf; /* may write all buffers */
+{
+ if ( !forceit
+ && bufIsChanged(buf)
+ && (mult_win || buf->b_nwindows <= 1)
+ && (!checkaw || autowrite(buf, forceit) == FAIL))
+ {
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if ((p_confirm || cmdmod.confirm) && p_write)
+ {
+ buf_T *buf2;
+ int count = 0;
+
+ if (allbuf)
+ for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
+ if (bufIsChanged(buf2)
+ && (buf2->b_ffname != NULL
+# ifdef FEAT_BROWSE
+ || cmdmod.browse
+# endif
+ ))
+ ++count;
+# ifdef FEAT_AUTOCMD
+ if (!buf_valid(buf))
+ /* Autocommand deleted buffer, oops! It's not changed now. */
+ return FALSE;
+# endif
+ dialog_changed(buf, count > 1);
+# ifdef FEAT_AUTOCMD
+ if (!buf_valid(buf))
+ /* Autocommand deleted buffer, oops! It's not changed now. */
+ return FALSE;
+# endif
+ return bufIsChanged(buf);
+ }
+#endif
+ EMSG(_(e_nowrtmsg));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
+
+#if defined(FEAT_BROWSE) || defined(PROTO)
+/*
+ * When wanting to write a file without a file name, ask the user for a name.
+ */
+ void
+browse_save_fname(buf)
+ buf_T *buf;
+{
+ if (buf->b_fname == NULL)
+ {
+ char_u *fname;
+
+ fname = do_browse(TRUE, (char_u *)_("Save As"), NULL, NULL, NULL,
+ NULL, buf);
+ if (fname != NULL)
+ {
+ if (setfname(buf, fname, NULL, TRUE) == OK)
+ buf->b_flags |= BF_NOTEDITED;
+ vim_free(fname);
+ }
+ }
+}
+#endif
+
+/*
+ * Ask the user what to do when abondoning a changed buffer.
+ * Must check 'write' option first!
+ */
+ void
+dialog_changed(buf, checkall)
+ buf_T *buf;
+ int checkall; /* may abandon all changed buffers */
+{
+ char_u buff[IOSIZE];
+ int ret;
+ buf_T *buf2;
+
+ dialog_msg(buff, _("Save changes to \"%.*s\"?"),
+ (buf->b_fname != NULL) ?
+ buf->b_fname : (char_u *)_("Untitled"));
+ if (checkall)
+ ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
+ else
+ ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
+
+ if (ret == VIM_YES)
+ {
+#ifdef FEAT_BROWSE
+ /* May get file name, when there is none */
+ browse_save_fname(buf);
+#endif
+ if (buf->b_fname != NULL) /* didn't hit Cancel */
+ (void)buf_write_all(buf, FALSE);
+ }
+ else if (ret == VIM_NO)
+ {
+ unchanged(buf, TRUE);
+ }
+ else if (ret == VIM_ALL)
+ {
+ /*
+ * Write all modified files that can be written.
+ * Skip readonly buffers, these need to be confirmed
+ * individually.
+ */
+ for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
+ {
+ if (bufIsChanged(buf2)
+ && (buf2->b_ffname != NULL
+#ifdef FEAT_BROWSE
+ || cmdmod.browse
+#endif
+ )
+ && !buf2->b_p_ro)
+ {
+#ifdef FEAT_BROWSE
+ /* May get file name, when there is none */
+ browse_save_fname(buf2);
+#endif
+ if (buf2->b_fname != NULL) /* didn't hit Cancel */
+ (void)buf_write_all(buf2, FALSE);
+#ifdef FEAT_AUTOCMD
+ /* an autocommand may have deleted the buffer */
+ if (!buf_valid(buf2))
+ buf2 = firstbuf;
+#endif
+ }
+ }
+ }
+ else if (ret == VIM_DISCARDALL)
+ {
+ /*
+ * mark all buffers as unchanged
+ */
+ for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
+ unchanged(buf2, TRUE);
+ }
+}
+#endif
+
+/*
+ * Return TRUE if the buffer "buf" can be abandoned, either by making it
+ * hidden, autowriting it or unloading it.
+ */
+ int
+can_abandon(buf, forceit)
+ buf_T *buf;
+ int forceit;
+{
+ return ( P_HID(buf)
+ || !bufIsChanged(buf)
+ || buf->b_nwindows > 1
+ || autowrite(buf, forceit) == OK
+ || forceit);
+}
+
+/*
+ * Return TRUE if any buffer was changed and cannot be abandoned.
+ * That changed buffer becomes the current buffer.
+ */
+ int
+check_changed_any(hidden)
+ int hidden; /* Only check hidden buffers */
+{
+ buf_T *buf;
+ int save;
+#ifdef FEAT_WINDOWS
+ win_T *wp;
+#endif
+
+ for (;;)
+ {
+ /* check curbuf first: if it was changed we can't abandon it */
+ if (!hidden && curbufIsChanged())
+ buf = curbuf;
+ else
+ {
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
+ break;
+ }
+ if (buf == NULL) /* No buffers changed */
+ return FALSE;
+
+ if (check_changed(buf, p_awa, TRUE, FALSE, TRUE) && buf_valid(buf))
+ break; /* didn't save - still changes */
+ }
+
+ exiting = FALSE;
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ /*
+ * When ":confirm" used, don't give an error message.
+ */
+ if (!(p_confirm || cmdmod.confirm))
+#endif
+ {
+ /* There must be a wait_return for this message, do_buffer()
+ * may cause a redraw. But wait_return() is a no-op when vgetc()
+ * is busy (Quit used from window menu), then make sure we don't
+ * cause a scroll up. */
+ if (vgetc_busy)
+ {
+ msg_row = cmdline_row;
+ msg_col = 0;
+ msg_didout = FALSE;
+ }
+ if (EMSG2(_("E162: No write since last change for buffer \"%s\""),
+ buf_spname(buf) != NULL ? (char_u *)buf_spname(buf) :
+ buf->b_fname))
+ {
+ save = no_wait_return;
+ no_wait_return = FALSE;
+ wait_return(FALSE);
+ no_wait_return = save;
+ }
+ }
+
+#ifdef FEAT_WINDOWS
+ /* Try to find a window that contains the buffer. */
+ if (buf != curbuf)
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_buffer == buf)
+ {
+ win_goto(wp);
+# ifdef FEAT_AUTOCMD
+ /* Paranoia: did autocms wipe out the buffer with changes? */
+ if (!buf_valid(buf))
+ return TRUE;
+# endif
+ break;
+ }
+#endif
+
+ /* Open the changed buffer in the current window. */
+ if (buf != curbuf)
+ set_curbuf(buf, DOBUF_GOTO);
+
+ return TRUE;
+}
+
+/*
+ * return FAIL if there is no file name, OK if there is one
+ * give error message for FAIL
+ */
+ int
+check_fname()
+{
+ if (curbuf->b_ffname == NULL)
+ {
+ EMSG(_(e_noname));
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
+ * flush the contents of a buffer, unless it has no file name
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+buf_write_all(buf, forceit)
+ buf_T *buf;
+ int forceit;
+{
+ int retval;
+#ifdef FEAT_AUTOCMD
+ buf_T *old_curbuf = curbuf;
+#endif
+
+ retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
+ (linenr_T)1, buf->b_ml.ml_line_count, NULL,
+ FALSE, forceit, TRUE, FALSE));
+#ifdef FEAT_AUTOCMD
+ if (curbuf != old_curbuf)
+ MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
+#endif
+ return retval;
+}
+
+/*
+ * Code to handle the argument list.
+ */
+
+/*
+ * Isolate one argument, taking quotes and backticks.
+ * Changes the argument in-place, puts a NUL after it.
+ * Quotes are removed, backticks remain.
+ * Return a pointer to the start of the next argument.
+ */
+ char_u *
+do_one_arg(str)
+ char_u *str;
+{
+ char_u *p;
+ int inquote;
+ int inbacktick;
+
+ inquote = FALSE;
+ inbacktick = FALSE;
+ for (p = str; *str; ++str)
+ {
+ /*
+ * for MSDOS et.al. a backslash is part of a file name.
+ * Only skip ", space and tab.
+ */
+ if (rem_backslash(str))
+ {
+ *p++ = *str++;
+ *p++ = *str;
+ }
+ else
+ {
+ /* An item ends at a space not in quotes or backticks */
+ if (!inquote && !inbacktick && vim_isspace(*str))
+ break;
+ if (!inquote && *str == '`')
+ inbacktick ^= TRUE;
+ if (!inbacktick && *str == '"')
+ inquote ^= TRUE;
+ else
+ *p++ = *str;
+ }
+ }
+ str = skipwhite(str);
+ *p = NUL;
+
+ return str;
+}
+
+static int do_arglist __ARGS((char_u *str, int what, int after));
+static void alist_check_arg_idx __ARGS((void));
+#ifdef FEAT_LISTCMDS
+static int alist_add_list __ARGS((int count, char_u **files, int after));
+#endif
+#define AL_SET 1
+#define AL_ADD 2
+#define AL_DEL 3
+
+#if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
+/*
+ * Redefine the argument list.
+ */
+ void
+set_arglist(str)
+ char_u *str;
+{
+ do_arglist(str, AL_SET, 0);
+}
+#endif
+
+/*
+ * "what" == AL_SET: Redefine the argument list to 'str'.
+ * "what" == AL_ADD: add files in 'str' to the argument list after "after".
+ * "what" == AL_DEL: remove files in 'str' from the argument list.
+ *
+ * Return FAIL for failure, OK otherwise.
+ */
+/*ARGSUSED*/
+ static int
+do_arglist(str, what, after)
+ char_u *str;
+ int what;
+ int after; /* 0 means before first one */
+{
+ garray_T new_ga;
+ int exp_count;
+ char_u **exp_files;
+ int i;
+#ifdef FEAT_LISTCMDS
+ char_u *p;
+ int match;
+#endif
+
+ /*
+ * Collect all file name arguments in "new_ga".
+ */
+ ga_init2(&new_ga, (int)sizeof(char_u *), 20);
+ while (*str)
+ {
+ if (ga_grow(&new_ga, 1) == FAIL)
+ {
+ ga_clear(&new_ga);
+ return FAIL;
+ }
+ ((char_u **)new_ga.ga_data)[new_ga.ga_len++] = str;
+ --new_ga.ga_room;
+
+ /* Isolate one argument, change it in-place, put a NUL after it. */
+ str = do_one_arg(str);
+ }
+
+#ifdef FEAT_LISTCMDS
+ if (what == AL_DEL)
+ {
+ regmatch_T regmatch;
+ int didone;
+
+ /*
+ * Delete the items: use each item as a regexp and find a match in the
+ * argument list.
+ */
+#ifdef CASE_INSENSITIVE_FILENAME
+ regmatch.rm_ic = TRUE; /* Always ignore case */
+#else
+ regmatch.rm_ic = FALSE; /* Never ignore case */
+#endif
+ for (i = 0; i < new_ga.ga_len && !got_int; ++i)
+ {
+ p = ((char_u **)new_ga.ga_data)[i];
+ p = file_pat_to_reg_pat(p, NULL, NULL, FALSE);
+ if (p == NULL)
+ break;
+ regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
+ if (regmatch.regprog == NULL)
+ {
+ vim_free(p);
+ break;
+ }
+
+ didone = FALSE;
+ for (match = 0; match < ARGCOUNT; ++match)
+ if (vim_regexec(&regmatch, alist_name(&ARGLIST[match]),
+ (colnr_T)0))
+ {
+ didone = TRUE;
+ vim_free(ARGLIST[match].ae_fname);
+ mch_memmove(ARGLIST + match, ARGLIST + match + 1,
+ (ARGCOUNT - match - 1) * sizeof(aentry_T));
+ --ALIST(curwin)->al_ga.ga_len;
+ ++ALIST(curwin)->al_ga.ga_room;
+ if (curwin->w_arg_idx > match)
+ --curwin->w_arg_idx;
+ --match;
+ }
+
+ vim_free(regmatch.regprog);
+ vim_free(p);
+ if (!didone)
+ EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]);
+ }
+ ga_clear(&new_ga);
+ }
+ else
+#endif
+ {
+ i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data,
+ &exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND);
+ ga_clear(&new_ga);
+ if (i == FAIL)
+ return FAIL;
+ if (exp_count == 0)
+ {
+ EMSG(_(e_nomatch));
+ return FAIL;
+ }
+
+#ifdef FEAT_LISTCMDS
+ if (what == AL_ADD)
+ {
+ (void)alist_add_list(exp_count, exp_files, after);
+ vim_free(exp_files);
+ }
+ else /* what == AL_SET */
+#endif
+ alist_set(ALIST(curwin), exp_count, exp_files, FALSE);
+ }
+
+ alist_check_arg_idx();
+
+ return OK;
+}
+
+/*
+ * Check the validity of the arg_idx for each other window.
+ */
+ static void
+alist_check_arg_idx()
+{
+#ifdef FEAT_WINDOWS
+ win_T *win;
+
+ for (win = firstwin; win != NULL; win = win->w_next)
+ if (win->w_alist == curwin->w_alist)
+ check_arg_idx(win);
+#else
+ check_arg_idx(curwin);
+#endif
+}
+
+/*
+ * Check if window "win" is editing the w_arg_idx file in its argument list.
+ */
+ void
+check_arg_idx(win)
+ win_T *win;
+{
+ if (WARGCOUNT(win) > 1
+ && (win->w_arg_idx >= WARGCOUNT(win)
+ || (win->w_buffer->b_fnum
+ != WARGLIST(win)[win->w_arg_idx].ae_fnum
+ && (win->w_buffer->b_ffname == NULL
+ || !(fullpathcmp(
+ alist_name(&WARGLIST(win)[win->w_arg_idx]),
+ win->w_buffer->b_ffname, TRUE) & FPC_SAME)))))
+ {
+ /* We are not editing the current entry in the argument list.
+ * Set "arg_had_last" if we are editing the last one. */
+ win->w_arg_idx_invalid = TRUE;
+ if (win->w_arg_idx != WARGCOUNT(win) - 1
+ && arg_had_last == FALSE
+#ifdef FEAT_WINDOWS
+ && ALIST(win) == &global_alist
+#endif
+ && GARGCOUNT > 0
+ && win->w_arg_idx < GARGCOUNT
+ && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum
+ || (win->w_buffer->b_ffname != NULL
+ && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]),
+ win->w_buffer->b_ffname, TRUE) & FPC_SAME))))
+ arg_had_last = TRUE;
+ }
+ else
+ {
+ /* We are editing the current entry in the argument list.
+ * Set "arg_had_last" if it's also the last one */
+ win->w_arg_idx_invalid = FALSE;
+ if (win->w_arg_idx == WARGCOUNT(win) - 1
+#ifdef FEAT_WINDOWS
+ && win->w_alist == &global_alist
+#endif
+ )
+ arg_had_last = TRUE;
+ }
+}
+
+/*
+ * ":args", ":argslocal" and ":argsglobal".
+ */
+ void
+ex_args(eap)
+ exarg_T *eap;
+{
+ int i;
+
+ if (eap->cmdidx != CMD_args)
+ {
+#if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
+ alist_unlink(ALIST(curwin));
+ if (eap->cmdidx == CMD_argglobal)
+ ALIST(curwin) = &global_alist;
+ else /* eap->cmdidx == CMD_arglocal */
+ alist_new();
+#else
+ ex_ni(eap);
+ return;
+#endif
+ }
+
+ if (!ends_excmd(*eap->arg))
+ {
+ /*
+ * ":args file ..": define new argument list, handle like ":next"
+ * Also for ":argslocal file .." and ":argsglobal file ..".
+ */
+ ex_next(eap);
+ }
+ else
+#if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
+ if (eap->cmdidx == CMD_args)
+#endif
+ {
+ /*
+ * ":args": list arguments.
+ */
+ if (ARGCOUNT > 0)
+ {
+ /* Overwrite the command, for a short list there is no scrolling
+ * required and no wait_return(). */
+ gotocmdline(TRUE);
+ for (i = 0; i < ARGCOUNT; ++i)
+ {
+ if (i == curwin->w_arg_idx)
+ msg_putchar('[');
+ msg_outtrans(alist_name(&ARGLIST[i]));
+ if (i == curwin->w_arg_idx)
+ msg_putchar(']');
+ msg_putchar(' ');
+ }
+ }
+ }
+#if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
+ else if (eap->cmdidx == CMD_arglocal)
+ {
+ garray_T *gap = &curwin->w_alist->al_ga;
+
+ /*
+ * ":argslocal": make a local copy of the global argument list.
+ */
+ if (ga_grow(gap, GARGCOUNT) == OK)
+ for (i = 0; i < GARGCOUNT; ++i)
+ if (GARGLIST[i].ae_fname != NULL)
+ {
+ AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname =
+ vim_strsave(GARGLIST[i].ae_fname);
+ AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum =
+ GARGLIST[i].ae_fnum;
+ ++gap->ga_len;
+ --gap->ga_room;
+ }
+ }
+#endif
+}
+
+/*
+ * ":previous", ":sprevious", ":Next" and ":sNext".
+ */
+ void
+ex_previous(eap)
+ exarg_T *eap;
+{
+ /* If past the last one already, go to the last one. */
+ if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT)
+ do_argfile(eap, ARGCOUNT - 1);
+ else
+ do_argfile(eap, curwin->w_arg_idx - (int)eap->line2);
+}
+
+/*
+ * ":rewind", ":first", ":sfirst" and ":srewind".
+ */
+ void
+ex_rewind(eap)
+ exarg_T *eap;
+{
+ do_argfile(eap, 0);
+}
+
+/*
+ * ":last" and ":slast".
+ */
+ void
+ex_last(eap)
+ exarg_T *eap;
+{
+ do_argfile(eap, ARGCOUNT - 1);
+}
+
+/*
+ * ":argument" and ":sargument".
+ */
+ void
+ex_argument(eap)
+ exarg_T *eap;
+{
+ int i;
+
+ if (eap->addr_count > 0)
+ i = eap->line2 - 1;
+ else
+ i = curwin->w_arg_idx;
+ do_argfile(eap, i);
+}
+
+/*
+ * Edit file "argn" of the argument lists.
+ */
+ void
+do_argfile(eap, argn)
+ exarg_T *eap;
+ int argn;
+{
+ int other;
+ char_u *p;
+
+ if (argn < 0 || argn >= ARGCOUNT)
+ {
+ if (ARGCOUNT <= 1)
+ EMSG(_("E163: There is only one file to edit"));
+ else if (argn < 0)
+ EMSG(_("E164: Cannot go before first file"));
+ else
+ EMSG(_("E165: Cannot go beyond last file"));
+ }
+ else
+ {
+ setpcmark();
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+
+#ifdef FEAT_WINDOWS
+ if (*eap->cmd == 's') /* split window first */
+ {
+ if (win_split(0, 0) == FAIL)
+ return;
+# ifdef FEAT_SCROLLBIND
+ curwin->w_p_scb = FALSE;
+# endif
+ }
+ else
+#endif
+ {
+ /*
+ * if 'hidden' set, only check for changed file when re-editing
+ * the same buffer
+ */
+ other = TRUE;
+ if (P_HID(curbuf))
+ {
+ p = fix_fname(alist_name(&ARGLIST[argn]));
+ other = otherfile(p);
+ vim_free(p);
+ }
+ if ((!P_HID(curbuf) || !other)
+ && check_changed(curbuf, TRUE, !other, eap->forceit, FALSE))
+ return;
+ }
+
+ curwin->w_arg_idx = argn;
+ if (argn == ARGCOUNT - 1
+#ifdef FEAT_WINDOWS
+ && curwin->w_alist == &global_alist
+#endif
+ )
+ arg_had_last = TRUE;
+
+ /* Edit the file; always use the last known line number. */
+ (void)do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
+ eap, ECMD_LAST,
+ (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0) +
+ (eap->forceit ? ECMD_FORCEIT : 0));
+
+ /* like Vi: set the mark where the cursor is in the file. */
+ if (eap->cmdidx != CMD_argdo)
+ setmark('\'');
+ }
+}
+
+/*
+ * ":next", and commands that behave like it.
+ */
+ void
+ex_next(eap)
+ exarg_T *eap;
+{
+ int i;
+
+ /*
+ * check for changed buffer now, if this fails the argument list is not
+ * redefined.
+ */
+ if ( P_HID(curbuf)
+ || eap->cmdidx == CMD_snext
+ || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
+ {
+ if (*eap->arg != NUL) /* redefine file list */
+ {
+ if (do_arglist(eap->arg, AL_SET, 0) == FAIL)
+ return;
+ i = 0;
+ }
+ else
+ i = curwin->w_arg_idx + (int)eap->line2;
+ do_argfile(eap, i);
+ }
+}
+
+#ifdef FEAT_LISTCMDS
+/*
+ * ":argedit"
+ */
+ void
+ex_argedit(eap)
+ exarg_T *eap;
+{
+ int fnum;
+ int i;
+ char_u *s;
+
+ /* Add the argument to the buffer list and get the buffer number. */
+ fnum = buflist_add(eap->arg, BLN_LISTED);
+
+ /* Check if this argument is already in the argument list. */
+ for (i = 0; i < ARGCOUNT; ++i)
+ if (ARGLIST[i].ae_fnum == fnum)
+ break;
+ if (i == ARGCOUNT)
+ {
+ /* Can't find it, add it to the argument list. */
+ s = vim_strsave(eap->arg);
+ if (s == NULL)
+ return;
+ i = alist_add_list(1, &s,
+ eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
+ if (i < 0)
+ return;
+ curwin->w_arg_idx = i;
+ }
+
+ alist_check_arg_idx();
+
+ /* Edit the argument. */
+ do_argfile(eap, i);
+}
+
+/*
+ * ":argadd"
+ */
+ void
+ex_argadd(eap)
+ exarg_T *eap;
+{
+ do_arglist(eap->arg, AL_ADD,
+ eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
+#ifdef FEAT_TITLE
+ maketitle();
+#endif
+}
+
+/*
+ * ":argdelete"
+ */
+ void
+ex_argdelete(eap)
+ exarg_T *eap;
+{
+ int i;
+ int n;
+
+ if (eap->addr_count > 0)
+ {
+ /* ":1,4argdel": Delete all arguments in the range. */
+ if (eap->line2 > ARGCOUNT)
+ eap->line2 = ARGCOUNT;
+ n = eap->line2 - eap->line1 + 1;
+ if (*eap->arg != NUL || n <= 0)
+ EMSG(_(e_invarg));
+ else
+ {
+ for (i = eap->line1; i <= eap->line2; ++i)
+ vim_free(ARGLIST[i - 1].ae_fname);
+ mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
+ (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
+ ALIST(curwin)->al_ga.ga_len -= n;
+ ALIST(curwin)->al_ga.ga_room += n;
+ if (curwin->w_arg_idx >= eap->line2)
+ curwin->w_arg_idx -= n;
+ else if (curwin->w_arg_idx > eap->line1)
+ curwin->w_arg_idx = eap->line1;
+ }
+ }
+ else if (*eap->arg == NUL)
+ EMSG(_(e_argreq));
+ else
+ do_arglist(eap->arg, AL_DEL, 0);
+#ifdef FEAT_TITLE
+ maketitle();
+#endif
+}
+
+/*
+ * ":argdo", ":windo", ":bufdo"
+ */
+ void
+ex_listdo(eap)
+ exarg_T *eap;
+{
+ int i;
+#ifdef FEAT_WINDOWS
+ win_T *win;
+#endif
+ buf_T *buf;
+ int next_fnum = 0;
+#if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
+ char_u *save_ei = NULL;
+ char_u *new_ei;
+#endif
+
+#ifndef FEAT_WINDOWS
+ if (eap->cmdidx == CMD_windo)
+ {
+ ex_ni(eap);
+ return;
+ }
+#endif
+
+#if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
+ if (eap->cmdidx != CMD_windo)
+ {
+ /* Add "Syntax" to 'eventignore' to skip loading syntax highlighting
+ * for every buffer loaded into the window. A considerable speed
+ * improvement. */
+ save_ei = vim_strsave(p_ei);
+ if (save_ei != NULL)
+ {
+ new_ei = vim_strnsave(p_ei, (int)STRLEN(p_ei) + 8);
+ if (new_ei != NULL)
+ {
+ STRCAT(new_ei, ",Syntax");
+ set_string_option_direct((char_u *)"ei", -1, new_ei, OPT_FREE);
+ vim_free(new_ei);
+ }
+ }
+ }
+#endif
+
+ if (eap->cmdidx == CMD_windo
+ || P_HID(curbuf)
+ || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
+ {
+ /* start at the first argument/window/buffer */
+ i = 0;
+#ifdef FEAT_WINDOWS
+ win = firstwin;
+#endif
+ /* set pcmark now */
+ if (eap->cmdidx == CMD_bufdo)
+ goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
+ else
+ setpcmark();
+ listcmd_busy = TRUE; /* avoids setting pcmark below */
+
+ while (!got_int)
+ {
+ if (eap->cmdidx == CMD_argdo)
+ {
+ /* go to argument "i" */
+ if (i == ARGCOUNT)
+ break;
+ /* Don't call do_argfile() when already there, it will try
+ * reloading the file. */
+ if (curwin->w_arg_idx != i)
+ do_argfile(eap, i);
+ if (curwin->w_arg_idx != i)
+ break;
+ ++i;
+ }
+#ifdef FEAT_WINDOWS
+ else if (eap->cmdidx == CMD_windo)
+ {
+ /* go to window "win" */
+ if (!win_valid(win))
+ break;
+ win_goto(win);
+ win = win->w_next;
+ }
+#endif
+ else if (eap->cmdidx == CMD_bufdo)
+ {
+ /* Remember the number of the next listed buffer, in case
+ * ":bwipe" is used or autocommands do something strange. */
+ next_fnum = -1;
+ for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
+ if (buf->b_p_bl)
+ {
+ next_fnum = buf->b_fnum;
+ break;
+ }
+ }
+
+ /* execute the command */
+ do_cmdline(eap->arg, eap->getline, eap->cookie,
+ DOCMD_VERBOSE + DOCMD_NOWAIT);
+
+ if (eap->cmdidx == CMD_bufdo)
+ {
+ /* Done? */
+ if (next_fnum < 0)
+ break;
+ /* Check if the buffer still exists. */
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (buf->b_fnum == next_fnum)
+ break;
+ if (buf == NULL)
+ break;
+ goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
+ /* If autocommands took us elsewhere, quit here */
+ if (curbuf->b_fnum != next_fnum)
+ break;
+ }
+
+ if (eap->cmdidx == CMD_windo)
+ {
+ validate_cursor(); /* cursor may have moved */
+#ifdef FEAT_SCROLLBIND
+ /* required when 'scrollbind' has been set */
+ if (curwin->w_p_scb)
+ do_check_scrollbind(TRUE);
+#endif
+ }
+ }
+ listcmd_busy = FALSE;
+ }
+
+#if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
+ if (save_ei != NULL)
+ {
+ set_string_option_direct((char_u *)"ei", -1, save_ei, OPT_FREE);
+ apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
+ curbuf->b_fname, TRUE, curbuf);
+ vim_free(save_ei);
+ }
+#endif
+}
+
+/*
+ * Add files[count] to the arglist of the current window after arg "after".
+ * The file names in files[count] must have been allocated and are taken over.
+ * Files[] itself is not taken over.
+ * Returns index of first added argument. Returns -1 when failed (out of mem).
+ */
+ static int
+alist_add_list(count, files, after)
+ int count;
+ char_u **files;
+ int after; /* where to add: 0 = before first one */
+{
+ int i;
+
+ if (ga_grow(&ALIST(curwin)->al_ga, count) == OK)
+ {
+ if (after < 0)
+ after = 0;
+ if (after > ARGCOUNT)
+ after = ARGCOUNT;
+ if (after < ARGCOUNT)
+ mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
+ (ARGCOUNT - after) * sizeof(aentry_T));
+ for (i = 0; i < count; ++i)
+ {
+ ARGLIST[after + i].ae_fname = files[i];
+ ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED);
+ }
+ ALIST(curwin)->al_ga.ga_len += count;
+ ALIST(curwin)->al_ga.ga_room -= count;
+ if (curwin->w_arg_idx >= after)
+ ++curwin->w_arg_idx;
+ return after;
+ }
+
+ for (i = 0; i < count; ++i)
+ vim_free(files[i]);
+ return -1;
+}
+
+#endif /* FEAT_LISTCMDS */
+
+#ifdef FEAT_EVAL
+/*
+ * ":compiler[!] {name}"
+ */
+ void
+ex_compiler(eap)
+ exarg_T *eap;
+{
+ char_u *buf;
+ char_u *old_cur_comp = NULL;
+ char_u *p;
+
+ if (*eap->arg == NUL)
+ {
+ /* List all compiler scripts. */
+ do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
+ /* ) keep the indenter happy... */
+ }
+ else
+ {
+ buf = alloc((unsigned)(STRLEN(eap->arg) + 14));
+ if (buf != NULL)
+ {
+ if (eap->forceit)
+ {
+ /* ":compiler! {name}" sets global options */
+ do_cmdline_cmd((char_u *)
+ "command -nargs=* CompilerSet set <args>");
+ }
+ else
+ {
+ /* ":compiler! {name}" sets local options.
+ * To remain backwards compatible "current_compiler" is always
+ * used. A user's compiler plugin may set it, the distributed
+ * plugin will then skip the settings. Afterwards set
+ * "b:current_compiler" and restore "current_compiler". */
+ old_cur_comp = get_var_value((char_u *)"current_compiler");
+ if (old_cur_comp != NULL)
+ old_cur_comp = vim_strsave(old_cur_comp);
+ do_cmdline_cmd((char_u *)
+ "command -nargs=* CompilerSet setlocal <args>");
+ }
+ do_unlet((char_u *)"current_compiler");
+ do_unlet((char_u *)"b:current_compiler");
+
+ sprintf((char *)buf, "compiler/%s.vim", eap->arg);
+ if (cmd_runtime(buf, TRUE) == FAIL)
+ EMSG2(_("E666: compiler not supported: %s"), eap->arg);
+ vim_free(buf);
+
+ do_cmdline_cmd((char_u *)":delcommand CompilerSet");
+
+ /* Set "b:current_compiler" from "current_compiler". */
+ p = get_var_value((char_u *)"current_compiler");
+ if (p != NULL)
+ set_internal_string_var((char_u *)"b:current_compiler", p);
+
+ /* Restore "current_compiler" for ":compiler {name}". */
+ if (!eap->forceit)
+ {
+ if (old_cur_comp != NULL)
+ {
+ set_internal_string_var((char_u *)"current_compiler",
+ old_cur_comp);
+ vim_free(old_cur_comp);
+ }
+ else
+ do_unlet((char_u *)"current_compiler");
+ }
+ }
+ }
+}
+#endif
+
+/*
+ * ":runtime {name}"
+ */
+ void
+ex_runtime(eap)
+ exarg_T *eap;
+{
+ cmd_runtime(eap->arg, eap->forceit);
+}
+
+static void source_callback __ARGS((char_u *fname));
+
+ static void
+source_callback(fname)
+ char_u *fname;
+{
+ (void)do_source(fname, FALSE, FALSE);
+}
+
+/*
+ * Source the file "name" from all directories in 'runtimepath'.
+ * "name" can contain wildcards.
+ * When "all" is TRUE, source all files, otherwise only the first one.
+ * return FAIL when no file could be sourced, OK otherwise.
+ */
+ int
+cmd_runtime(name, all)
+ char_u *name;
+ int all;
+{
+ return do_in_runtimepath(name, all, source_callback);
+}
+
+/*
+ * Find "name" in 'runtimepath'. When found, call the "callback" function for
+ * it.
+ * When "all" is TRUE repeat for all matches, otherwise only the first one is
+ * used.
+ * Returns OK when at least one match found, FAIL otherwise.
+ */
+ int
+do_in_runtimepath(name, all, callback)
+ char_u *name;
+ int all;
+ void (*callback)__ARGS((char_u *fname));
+{
+ char_u *rtp;
+ char_u *np;
+ char_u *buf;
+ char_u *rtp_copy;
+ char_u *tail;
+ int num_files;
+ char_u **files;
+ int i;
+ int did_one = FALSE;
+#ifdef AMIGA
+ struct Process *proc = (struct Process *)FindTask(0L);
+ APTR save_winptr = proc->pr_WindowPtr;
+
+ /* Avoid a requester here for a volume that doesn't exist. */
+ proc->pr_WindowPtr = (APTR)-1L;
+#endif
+
+ /* Make a copy of 'runtimepath'. Invoking the callback may change the
+ * value. */
+ rtp_copy = vim_strsave(p_rtp);
+ buf = alloc(MAXPATHL);
+ if (buf != NULL && rtp_copy != NULL)
+ {
+ if (p_verbose > 1)
+ smsg((char_u *)_("Searching for \"%s\" in \"%s\""),
+ (char *)name, (char *)p_rtp);
+ /* Loop over all entries in 'runtimepath'. */
+ rtp = rtp_copy;
+ while (*rtp != NUL && (all || !did_one))
+ {
+ /* Copy the path from 'runtimepath' to buf[]. */
+ copy_option_part(&rtp, buf, MAXPATHL, ",");
+ if (STRLEN(buf) + STRLEN(name) + 2 < MAXPATHL)
+ {
+ add_pathsep(buf);
+ tail = buf + STRLEN(buf);
+
+ /* Loop over all patterns in "name" */
+ np = name;
+ while (*np != NUL && (all || !did_one))
+ {
+ /* Append the pattern from "name" to buf[]. */
+ copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)),
+ "\t ");
+
+ if (p_verbose > 2)
+ msg_str((char_u *)_("Searching for \"%s\""), buf);
+
+ /* Expand wildcards, invoke the callback for each match. */
+ if (gen_expand_wildcards(1, &buf, &num_files, &files,
+ EW_FILE) == OK)
+ {
+ for (i = 0; i < num_files; ++i)
+ {
+ (*callback)(files[i]);
+ did_one = TRUE;
+ if (!all)
+ break;
+ }
+ FreeWild(num_files, files);
+ }
+ }
+ }
+ }
+ }
+ vim_free(buf);
+ vim_free(rtp_copy);
+ if (p_verbose > 0 && !did_one)
+ msg_str((char_u *)_("not found in 'runtimepath': \"%s\""), name);
+
+#ifdef AMIGA
+ proc->pr_WindowPtr = save_winptr;
+#endif
+
+ return did_one ? OK : FAIL;
+}
+
+#if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
+/*
+ * ":options"
+ */
+/*ARGSUSED*/
+ void
+ex_options(eap)
+ exarg_T *eap;
+{
+ cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
+}
+#endif
+
+/*
+ * ":source {fname}"
+ */
+ void
+ex_source(eap)
+ exarg_T *eap;
+{
+#ifdef FEAT_BROWSE
+ if (cmdmod.browse)
+ {
+ char_u *fname = NULL;
+
+ fname = do_browse(FALSE, (char_u *)_("Source Vim script"), eap->arg,
+ NULL, NULL, BROWSE_FILTER_MACROS, NULL);
+ if (fname != NULL)
+ {
+ cmd_source(fname, eap);
+ vim_free(fname);
+ }
+ }
+ else
+#endif
+ cmd_source(eap->arg, eap);
+}
+
+ static void
+cmd_source(fname, eap)
+ char_u *fname;
+ exarg_T *eap;
+{
+ if (*fname == NUL)
+ EMSG(_(e_argreq));
+
+ /* ":source!" read vi commands */
+ else if (eap != NULL && eap->forceit)
+ /* Need to execute the commands directly when:
+ * - ":g" command busy
+ * - after ":argdo", ":windo" or ":bufdo"
+ * - another command follows
+ * - inside a loop
+ */
+ openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL
+#ifdef FEAT_EVAL
+ || eap->cstack->cs_idx >= 0
+#endif
+ );
+
+ /* ":source" read ex commands */
+ else if (do_source(fname, FALSE, FALSE) == FAIL)
+ EMSG2(_(e_notopen), fname);
+}
+
+/*
+ * ":source" and associated commands.
+ */
+/*
+ * Structure used to store info for each sourced file.
+ * It is shared between do_source() and getsourceline().
+ * This is required, because it needs to be handed to do_cmdline() and
+ * sourcing can be done recursively.
+ */
+struct source_cookie
+{
+ FILE *fp; /* opened file for sourcing */
+ char_u *nextline; /* if not NULL: line that was read ahead */
+ int finished; /* ":finish" used */
+#if defined (USE_CRNL) || defined (USE_CR)
+ int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
+ int error; /* TRUE if LF found after CR-LF */
+#endif
+#ifdef FEAT_EVAL
+ linenr_T breakpoint; /* next line with breakpoint or zero */
+ char_u *fname; /* name of sourced file */
+ int dbg_tick; /* debug_tick when breakpoint was set */
+ int level; /* top nesting level of sourced file */
+#endif
+#ifdef FEAT_MBYTE
+ vimconv_T conv; /* type of conversion */
+#endif
+};
+
+#ifdef FEAT_EVAL
+/*
+ * Return the address holding the next breakpoint line for a source cookie.
+ */
+ linenr_T *
+source_breakpoint(cookie)
+ void *cookie;
+{
+ return &((struct source_cookie *)cookie)->breakpoint;
+}
+
+/*
+ * Return the address holding the debug tick for a source cookie.
+ */
+ int *
+source_dbg_tick(cookie)
+ void *cookie;
+{
+ return &((struct source_cookie *)cookie)->dbg_tick;
+}
+
+/*
+ * Return the nesting level for a source cookie.
+ */
+ int
+source_level(cookie)
+ void *cookie;
+{
+ return ((struct source_cookie *)cookie)->level;
+}
+#endif
+
+static char_u *get_one_sourceline __ARGS((struct source_cookie *sp));
+
+#ifdef FEAT_EVAL
+/* Growarray to store the names of sourced scripts.
+ * For Unix also store the dev/ino, so that we don't have to stat() each
+ * script when going through the list. */
+struct scriptstuff
+{
+ char_u *name;
+# ifdef UNIX
+ int dev;
+ ino_t ino;
+# endif
+};
+static garray_T script_names = {0, 0, sizeof(struct scriptstuff), 4, NULL};
+#define SCRIPT_NAME(id) (((struct scriptstuff *)script_names.ga_data)[(id) - 1].name)
+#define SCRIPT_DEV(id) (((struct scriptstuff *)script_names.ga_data)[(id) - 1].dev)
+#define SCRIPT_INO(id) (((struct scriptstuff *)script_names.ga_data)[(id) - 1].ino)
+#endif
+
+#if defined(WIN32) && defined(FEAT_CSCOPE)
+static FILE *fopen_noinh_readbin __ARGS((char *filename));
+
+/*
+ * Special function to open a file without handle inheritance.
+ */
+ static FILE *
+fopen_noinh_readbin(filename)
+ char *filename;
+{
+ int fd_tmp = open(filename, O_RDONLY | O_BINARY | O_NOINHERIT);
+
+ if (fd_tmp == -1)
+ return NULL;
+ return fdopen(fd_tmp, READBIN);
+}
+#endif
+
+
+/*
+ * do_source: Read the file "fname" and execute its lines as EX commands.
+ *
+ * This function may be called recursively!
+ *
+ * return FAIL if file could not be opened, OK otherwise
+ */
+ int
+do_source(fname, check_other, is_vimrc)
+ char_u *fname;
+ int check_other; /* check for .vimrc and _vimrc */
+ int is_vimrc; /* call vimrc_found() when file exists */
+{
+ struct source_cookie cookie;
+ char_u *save_sourcing_name;
+ linenr_T save_sourcing_lnum;
+ char_u *p;
+ char_u *fname_exp;
+ int retval = FAIL;
+#ifdef FEAT_EVAL
+ scid_T save_current_SID;
+ static scid_T last_current_SID = 0;
+ void *save_funccalp;
+ int save_debug_break_level = debug_break_level;
+# ifdef UNIX
+ struct stat st;
+ int stat_ok;
+# endif
+#endif
+#ifdef STARTUPTIME
+ struct timeval tv_rel;
+ struct timeval tv_start;
+#endif
+
+#ifdef RISCOS
+ p = mch_munge_fname(fname);
+#else
+ p = expand_env_save(fname);
+#endif
+ if (p == NULL)
+ return retval;
+ fname_exp = fix_fname(p);
+ vim_free(p);
+ if (fname_exp == NULL)
+ return retval;
+#ifdef MACOS_CLASSIC
+ slash_n_colon_adjust(fname_exp);
+#endif
+ if (mch_isdir(fname_exp))
+ {
+ msg_str((char_u *)_("Cannot source a directory: \"%s\""), fname);
+ goto theend;
+ }
+
+#if defined(WIN32) && defined(FEAT_CSCOPE)
+ cookie.fp = fopen_noinh_readbin((char *)fname_exp);
+#else
+ cookie.fp = mch_fopen((char *)fname_exp, READBIN);
+#endif
+ if (cookie.fp == NULL && check_other)
+ {
+ /*
+ * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
+ * and ".exrc" by "_exrc" or vice versa.
+ */
+ p = gettail(fname_exp);
+ if ((*p == '.' || *p == '_')
+ && (STRICMP(p + 1, "vimrc") == 0
+ || STRICMP(p + 1, "gvimrc") == 0
+ || STRICMP(p + 1, "exrc") == 0))
+ {
+ if (*p == '_')
+ *p = '.';
+ else
+ *p = '_';
+#if defined(WIN32) && defined(FEAT_CSCOPE)
+ cookie.fp = fopen_noinh_readbin((char *)fname_exp);
+#else
+ cookie.fp = mch_fopen((char *)fname_exp, READBIN);
+#endif
+ }
+ }
+
+ if (cookie.fp == NULL)
+ {
+ if (p_verbose > 0)
+ {
+ if (sourcing_name == NULL)
+ msg_str((char_u *)_("could not source \"%s\""), fname);
+ else
+ smsg((char_u *)_("line %ld: could not source \"%s\""),
+ sourcing_lnum, fname);
+ }
+ goto theend;
+ }
+
+ /*
+ * The file exists.
+ * - In verbose mode, give a message.
+ * - For a vimrc file, may want to set 'compatible', call vimrc_found().
+ */
+ if (p_verbose > 1)
+ {
+ if (sourcing_name == NULL)
+ msg_str((char_u *)_("sourcing \"%s\""), fname);
+ else
+ smsg((char_u *)_("line %ld: sourcing \"%s\""),
+ sourcing_lnum, fname);
+ }
+ if (is_vimrc)
+ vimrc_found();
+
+#ifdef USE_CRNL
+ /* If no automatic file format: Set default to CR-NL. */
+ if (*p_ffs == NUL)
+ cookie.fileformat = EOL_DOS;
+ else
+ cookie.fileformat = EOL_UNKNOWN;
+ cookie.error = FALSE;
+#endif
+
+#ifdef USE_CR
+ /* If no automatic file format: Set default to CR. */
+ if (*p_ffs == NUL)
+ cookie.fileformat = EOL_MAC;
+ else
+ cookie.fileformat = EOL_UNKNOWN;
+ cookie.error = FALSE;
+#endif
+
+ cookie.nextline = NULL;
+ cookie.finished = FALSE;
+
+#ifdef FEAT_EVAL
+ /*
+ * Check if this script has a breakpoint.
+ */
+ cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0);
+ cookie.fname = fname_exp;
+ cookie.dbg_tick = debug_tick;
+
+ cookie.level = ex_nesting_level;
+#endif
+#ifdef FEAT_MBYTE
+ cookie.conv.vc_type = CONV_NONE; /* no conversion */
+
+ /* Try reading the first few bytes to check for a UTF-8 BOM. */
+ {
+ char_u buf[3];
+
+ if (fread((char *)buf, sizeof(char_u), (size_t)3, cookie.fp)
+ == (size_t)3
+ && buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf)
+ /* Found BOM, setup conversion and skip over it. */
+ convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
+ else
+ /* No BOM found, rewind. */
+ fseek(cookie.fp, 0L, SEEK_SET);
+ }
+#endif
+
+ /*
+ * Keep the sourcing name/lnum, for recursive calls.
+ */
+ save_sourcing_name = sourcing_name;
+ sourcing_name = fname_exp;
+ save_sourcing_lnum = sourcing_lnum;
+ sourcing_lnum = 0;
+
+#ifdef STARTUPTIME
+ time_push(&tv_rel, &tv_start);
+#endif
+
+#ifdef FEAT_EVAL
+ /*
+ * Check if this script was sourced before to finds its SID.
+ * If it's new, generate a new SID.
+ */
+ save_current_SID = current_SID;
+# ifdef UNIX
+ stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
+# endif
+ for (current_SID = script_names.ga_len; current_SID > 0; --current_SID)
+ if (SCRIPT_NAME(current_SID) != NULL
+ && (
+# ifdef UNIX
+ /* compare dev/ino when possible, it catches symbolic
+ * links */
+ (stat_ok && SCRIPT_DEV(current_SID) != -1)
+ ? (SCRIPT_DEV(current_SID) == st.st_dev
+ && SCRIPT_INO(current_SID) == st.st_ino) :
+# endif
+ fnamecmp(SCRIPT_NAME(current_SID), fname_exp) == 0))
+ break;
+ if (current_SID == 0)
+ {
+ current_SID = ++last_current_SID;
+ if (ga_grow(&script_names, (int)(current_SID - script_names.ga_len))
+ == OK)
+ {
+ while (script_names.ga_len < current_SID)
+ {
+ SCRIPT_NAME(script_names.ga_len + 1) = NULL;
+ ++script_names.ga_len;
+ --script_names.ga_room;
+ }
+ SCRIPT_NAME(current_SID) = fname_exp;
+# ifdef UNIX
+ if (stat_ok)
+ {
+ SCRIPT_DEV(current_SID) = st.st_dev;
+ SCRIPT_INO(current_SID) = st.st_ino;
+ }
+ else
+ SCRIPT_DEV(current_SID) = -1;
+# endif
+ fname_exp = NULL;
+ }
+ /* Allocate the local script variables to use for this script. */
+ new_script_vars(current_SID);
+ }
+
+ /* Don't use local function variables, if called from a function */
+ save_funccalp = save_funccal();
+#endif
+
+ /*
+ * Call do_cmdline, which will call getsourceline() to get the lines.
+ */
+ do_cmdline(NULL, getsourceline, (void *)&cookie,
+ DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
+
+ retval = OK;
+ fclose(cookie.fp);
+ vim_free(cookie.nextline);
+#ifdef FEAT_MBYTE
+ convert_setup(&cookie.conv, NULL, NULL);
+#endif
+
+ if (got_int)
+ EMSG(_(e_interr));
+ sourcing_name = save_sourcing_name;
+ sourcing_lnum = save_sourcing_lnum;
+#ifdef FEAT_EVAL
+ current_SID = save_current_SID;
+ restore_funccal(save_funccalp);
+#endif
+ if (p_verbose > 1)
+ {
+ msg_str((char_u *)_("finished sourcing %s"), fname);
+ if (sourcing_name != NULL)
+ msg_str((char_u *)_("continuing in %s"), sourcing_name);
+ }
+#ifdef STARTUPTIME
+# ifdef HAVE_SNPRINTF
+ snprintf(IObuff, IOSIZE, "sourcing %s", fname);
+# else
+ sprintf(IObuff, "sourcing %s", fname);
+# endif
+ time_msg(IObuff, &tv_start);
+ time_pop(&tv_rel);
+#endif
+
+#ifdef FEAT_EVAL
+ /*
+ * After a "finish" in debug mode, need to break at first command of next
+ * sourced file.
+ */
+ if (save_debug_break_level > ex_nesting_level
+ && debug_break_level == ex_nesting_level)
+ ++debug_break_level;
+#endif
+
+theend:
+ vim_free(fname_exp);
+ return retval;
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * ":scriptnames"
+ */
+/*ARGSUSED*/
+ void
+ex_scriptnames(eap)
+ exarg_T *eap;
+{
+ int i;
+
+ for (i = 1; i <= script_names.ga_len && !got_int; ++i)
+ if (SCRIPT_NAME(i) != NULL)
+ smsg((char_u *)"%3d: %s", i, SCRIPT_NAME(i));
+}
+
+# if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
+/*
+ * Fix slashes in the list of script names for 'shellslash'.
+ */
+ void
+scriptnames_slash_adjust()
+{
+ int i;
+
+ for (i = 1; i <= script_names.ga_len; ++i)
+ if (SCRIPT_NAME(i) != NULL)
+ slash_adjust(SCRIPT_NAME(i));
+}
+# endif
+
+/*
+ * Get a pointer to a script name. Used for ":verbose set".
+ */
+ char_u *
+get_scriptname(id)
+ scid_T id;
+{
+ if (id == SID_MODELINE)
+ return (char_u *)"modeline";
+ if (id == SID_CMDARG)
+ return (char_u *)"--cmd argument";
+ if (id == SID_CARG)
+ return (char_u *)"-c argument";
+ if (id == SID_ENV)
+ return (char_u *)"environment variable";
+ return SCRIPT_NAME(id);
+}
+#endif
+
+#if defined(USE_CR) || defined(PROTO)
+
+# if defined(__MSL__) && (__MSL__ >= 22)
+/*
+ * Newer version of the Metrowerks library handle DOS and UNIX files
+ * without help.
+ * Test with earlier versions, MSL 2.2 is the library supplied with
+ * Codewarrior Pro 2.
+ */
+ char *
+fgets_cr(s, n, stream)
+ char *s;
+ int n;
+ FILE *stream;
+{
+ return fgets(s, n, stream);
+}
+# else
+/*
+ * Version of fgets() which also works for lines ending in a <CR> only
+ * (Macintosh format).
+ * For older versions of the Metrowerks library.
+ * At least CodeWarrior 9 needed this code.
+ */
+ char *
+fgets_cr(s, n, stream)
+ char *s;
+ int n;
+ FILE *stream;
+{
+ int c = 0;
+ int char_read = 0;
+
+ while (!feof(stream) && c != '\r' && c != '\n' && char_read < n - 1)
+ {
+ c = fgetc(stream);
+ s[char_read++] = c;
+ /* If the file is in DOS format, we need to skip a NL after a CR. I
+ * thought it was the other way around, but this appears to work... */
+ if (c == '\n')
+ {
+ c = fgetc(stream);
+ if (c != '\r')
+ ungetc(c, stream);
+ }
+ }
+
+ s[char_read] = 0;
+ if (char_read == 0)
+ return NULL;
+
+ if (feof(stream) && char_read == 1)
+ return NULL;
+
+ return s;
+}
+# endif
+#endif
+
+/*
+ * Get one full line from a sourced file.
+ * Called by do_cmdline() when it's called from do_source().
+ *
+ * Return a pointer to the line in allocated memory.
+ * Return NULL for end-of-file or some error.
+ */
+/* ARGSUSED */
+ char_u *
+getsourceline(c, cookie, indent)
+ int c; /* not used */
+ void *cookie;
+ int indent; /* not used */
+{
+ struct source_cookie *sp = (struct source_cookie *)cookie;
+ char_u *line;
+ char_u *p, *s;
+
+#ifdef FEAT_EVAL
+ /* If breakpoints have been added/deleted need to check for it. */
+ if (sp->dbg_tick < debug_tick)
+ {
+ sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
+ sp->dbg_tick = debug_tick;
+ }
+#endif
+ /*
+ * Get current line. If there is a read-ahead line, use it, otherwise get
+ * one now.
+ */
+ if (sp->finished)
+ line = NULL;
+ else if (sp->nextline == NULL)
+ line = get_one_sourceline(sp);
+ else
+ {
+ line = sp->nextline;
+ sp->nextline = NULL;
+ ++sourcing_lnum;
+ }
+
+ /* Only concatenate lines starting with a \ when 'cpoptions' doesn't
+ * contain the 'C' flag. */
+ if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL))
+ {
+ /* compensate for the one line read-ahead */
+ --sourcing_lnum;
+ for (;;)
+ {
+ sp->nextline = get_one_sourceline(sp);
+ if (sp->nextline == NULL)
+ break;
+ p = skipwhite(sp->nextline);
+ if (*p != '\\')
+ break;
+ s = alloc((int)(STRLEN(line) + STRLEN(p)));
+ if (s == NULL) /* out of memory */
+ break;
+ STRCPY(s, line);
+ STRCAT(s, p + 1);
+ vim_free(line);
+ line = s;
+ vim_free(sp->nextline);
+ }
+ }
+
+#ifdef FEAT_MBYTE
+ if (line != NULL && sp->conv.vc_type != CONV_NONE)
+ {
+ /* Convert the encoding of the script line. */
+ s = string_convert(&sp->conv, line, NULL);
+ if (s != NULL)
+ {
+ vim_free(line);
+ line = s;
+ }
+ }
+#endif
+
+#ifdef FEAT_EVAL
+ /* Did we encounter a breakpoint? */
+ if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum)
+ {
+ dbg_breakpoint(sp->fname, sourcing_lnum);
+ /* Find next breakpoint. */
+ sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
+ sp->dbg_tick = debug_tick;
+ }
+#endif
+
+ return line;
+}
+
+ static char_u *
+get_one_sourceline(sp)
+ struct source_cookie *sp;
+{
+ garray_T ga;
+ int len;
+ int c;
+ char_u *buf;
+#ifdef USE_CRNL
+ int has_cr; /* CR-LF found */
+#endif
+#ifdef USE_CR
+ char_u *scan;
+#endif
+ int have_read = FALSE;
+
+ /* use a growarray to store the sourced line */
+ ga_init2(&ga, 1, 200);
+
+ /*
+ * Loop until there is a finished line (or end-of-file).
+ */
+ sourcing_lnum++;
+ for (;;)
+ {
+ /* make room to read at least 80 (more) characters */
+ if (ga_grow(&ga, 80) == FAIL)
+ break;
+ buf = (char_u *)ga.ga_data;
+
+#ifdef USE_CR
+ if (sp->fileformat == EOL_MAC)
+ {
+ if (fgets_cr((char *)buf + ga.ga_len, ga.ga_room, sp->fp) == NULL)
+ break;
+ }
+ else
+#endif
+ if (fgets((char *)buf + ga.ga_len, ga.ga_room, sp->fp) == NULL)
+ break;
+ len = (int)STRLEN(buf);
+#ifdef USE_CRNL
+ /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
+ * CTRL-Z by its own, or after a NL. */
+ if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n'))
+ && sp->fileformat == EOL_DOS
+ && buf[len - 1] == Ctrl_Z)
+ {
+ buf[len - 1] = NUL;
+ break;
+ }
+#endif
+
+#ifdef USE_CR
+ /* If the read doesn't stop on a new line, and there's
+ * some CR then we assume a Mac format */
+ if (sp->fileformat == EOL_UNKNOWN)
+ {
+ if (buf[len - 1] != '\n' && vim_strchr(buf, '\r') != NULL)
+ sp->fileformat = EOL_MAC;
+ else
+ sp->fileformat = EOL_UNIX;
+ }
+
+ if (sp->fileformat == EOL_MAC)
+ {
+ scan = vim_strchr(buf, '\r');
+
+ if (scan != NULL)
+ {
+ *scan = '\n';
+ if (*(scan + 1) != 0)
+ {
+ *(scan + 1) = 0;
+ fseek(sp->fp, (long)(scan - buf - len + 1), SEEK_CUR);
+ }
+ }
+ len = STRLEN(buf);
+ }
+#endif
+
+ have_read = TRUE;
+ ga.ga_room -= len - ga.ga_len;
+ ga.ga_len = len;
+
+ /* If the line was longer than the buffer, read more. */
+ if (ga.ga_room == 1 && buf[len - 1] != '\n')
+ continue;
+
+ if (len >= 1 && buf[len - 1] == '\n') /* remove trailing NL */
+ {
+#ifdef USE_CRNL
+ has_cr = (len >= 2 && buf[len - 2] == '\r');
+ if (sp->fileformat == EOL_UNKNOWN)
+ {
+ if (has_cr)
+ sp->fileformat = EOL_DOS;
+ else
+ sp->fileformat = EOL_UNIX;
+ }
+
+ if (sp->fileformat == EOL_DOS)
+ {
+ if (has_cr) /* replace trailing CR */
+ {
+ buf[len - 2] = '\n';
+ --len;
+ --ga.ga_len;
+ ++ga.ga_room;
+ }
+ else /* lines like ":map xx yy^M" will have failed */
+ {
+ if (!sp->error)
+ EMSG(_("W15: Warning: Wrong line separator, ^M may be missing"));
+ sp->error = TRUE;
+ sp->fileformat = EOL_UNIX;
+ }
+ }
+#endif
+ /* The '\n' is escaped if there is an odd number of ^V's just
+ * before it, first set "c" just before the 'V's and then check
+ * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
+ for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--)
+ ;
+ if ((len & 1) != (c & 1)) /* escaped NL, read more */
+ {
+ sourcing_lnum++;
+ continue;
+ }
+
+ buf[len - 1] = NUL; /* remove the NL */
+ }
+
+ /*
+ * Check for ^C here now and then, so recursive :so can be broken.
+ */
+ line_breakcheck();
+ break;
+ }
+
+ if (have_read)
+ return (char_u *)ga.ga_data;
+
+ vim_free(ga.ga_data);
+ return NULL;
+}
+
+/*
+ * ":scriptencoding": Set encoding conversion for a sourced script.
+ * Without the multi-byte feature it's simply ignored.
+ */
+/*ARGSUSED*/
+ void
+ex_scriptencoding(eap)
+ exarg_T *eap;
+{
+#ifdef FEAT_MBYTE
+ struct source_cookie *sp;
+ char_u *name;
+
+ if (!getline_equal(eap->getline, eap->cookie, getsourceline))
+ {
+ EMSG(_("E167: :scriptencoding used outside of a sourced file"));
+ return;
+ }
+
+ if (*eap->arg != NUL)
+ {
+ name = enc_canonize(eap->arg);
+ if (name == NULL) /* out of memory */
+ return;
+ }
+ else
+ name = eap->arg;
+
+ /* Setup for conversion from the specified encoding to 'encoding'. */
+ sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie);
+ convert_setup(&sp->conv, name, p_enc);
+
+ if (name != eap->arg)
+ vim_free(name);
+#endif
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * ":finish": Mark a sourced file as finished.
+ */
+ void
+ex_finish(eap)
+ exarg_T *eap;
+{
+ if (getline_equal(eap->getline, eap->cookie, getsourceline))
+ do_finish(eap, FALSE);
+ else
+ EMSG(_("E168: :finish used outside of a sourced file"));
+}
+
+/*
+ * Mark a sourced file as finished. Possibly makes the ":finish" pending.
+ * Also called for a pending finish at the ":endtry" or after returning from
+ * an extra do_cmdline(). "reanimate" is used in the latter case.
+ */
+ void
+do_finish(eap, reanimate)
+ exarg_T *eap;
+ int reanimate;
+{
+ int idx;
+
+ if (reanimate)
+ ((struct source_cookie *)getline_cookie(eap->getline,
+ eap->cookie))->finished = FALSE;
+
+ /*
+ * Cleanup (and inactivate) conditionals, but stop when a try conditional
+ * not in its finally clause (which then is to be executed next) is found.
+ * In this case, make the ":finish" pending for execution at the ":endtry".
+ * Otherwise, finish normally.
+ */
+ idx = cleanup_conditionals(eap->cstack, 0, TRUE);
+ if (idx >= 0)
+ {
+ eap->cstack->cs_pending[idx] = CSTP_FINISH;
+ report_make_pending(CSTP_FINISH, NULL);
+ }
+ else
+ ((struct source_cookie *)getline_cookie(eap->getline,
+ eap->cookie))->finished = TRUE;
+}
+
+
+/*
+ * Return TRUE when a sourced file had the ":finish" command: Don't give error
+ * message for missing ":endif".
+ * Return FALSE when not sourcing a file.
+ */
+ int
+source_finished(getline, cookie)
+ char_u *(*getline) __ARGS((int, void *, int));
+ void *cookie;
+{
+ return (getline_equal(getline, cookie, getsourceline)
+ && ((struct source_cookie *)getline_cookie(
+ getline, cookie))->finished);
+}
+#endif
+
+#if defined(FEAT_LISTCMDS) || defined(PROTO)
+/*
+ * ":checktime [buffer]"
+ */
+ void
+ex_checktime(eap)
+ exarg_T *eap;
+{
+ buf_T *buf;
+ int save_no_check_timestamps = no_check_timestamps;
+
+ no_check_timestamps = 0;
+ if (eap->addr_count == 0) /* default is all buffers */
+ check_timestamps(FALSE);
+ else
+ {
+ buf = buflist_findnr((int)eap->line2);
+ if (buf != NULL) /* cannot happen? */
+ (void)buf_check_timestamp(buf, FALSE);
+ }
+ no_check_timestamps = save_no_check_timestamps;
+}
+#endif
+
+#if defined(FEAT_PRINTER) || defined(PROTO)
+/*
+ * Printing code (Machine-independent.)
+ * To implement printing on a platform, the following functions must be
+ * defined:
+ *
+ * int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
+ * Called once. Code should display printer dialogue (if appropriate) and
+ * determine printer font and margin settings. Reset has_color if the printer
+ * doesn't support colors at all.
+ * Returns FAIL to abort.
+ *
+ * int mch_print_begin(prt_settings_T *settings)
+ * Called to start the print job.
+ * Return FALSE to abort.
+ *
+ * int mch_print_begin_page(char_u *msg)
+ * Called at the start of each page.
+ * "msg" indicates the progress of the print job, can be NULL.
+ * Return FALSE to abort.
+ *
+ * int mch_print_end_page()
+ * Called at the end of each page.
+ * Return FALSE to abort.
+ *
+ * int mch_print_blank_page()
+ * Called to generate a blank page for collated, duplex, multiple copy
+ * document. Return FALSE to abort.
+ *
+ * void mch_print_end(prt_settings_T *psettings)
+ * Called at normal end of print job.
+ *
+ * void mch_print_cleanup()
+ * Called if print job ends normally or is abandoned. Free any memory, close
+ * devices and handles. Also called when mch_print_begin() fails, but not
+ * when mch_print_init() fails.
+ *
+ * void mch_print_set_font(int Bold, int Italic, int Underline);
+ * Called whenever the font style changes.
+ *
+ * void mch_print_set_bg(long bgcol);
+ * Called to set the background color for the following text. Parameter is an
+ * RGB value.
+ *
+ * void mch_print_set_fg(long fgcol);
+ * Called to set the foreground color for the following text. Parameter is an
+ * RGB value.
+ *
+ * mch_print_start_line(int margin, int page_line)
+ * Sets the current position at the start of line "page_line".
+ * If margin is TRUE start in the left margin (for header and line number).
+ *
+ * int mch_print_text_out(char_u *p, int len);
+ * Output one character of text p[len] at the current position.
+ * Return TRUE if there is no room for another character in the same line.
+ *
+ * Note that the generic code has no idea of margins. The machine code should
+ * simply make the page look smaller! The header and the line numbers are
+ * printed in the margin.
+ */
+
+#ifdef FEAT_SYN_HL
+static const long_u cterm_color_8[8] =
+{
+ (long_u)0x000000L, (long_u)0xff0000L, (long_u)0x00ff00L, (long_u)0xffff00L,
+ (long_u)0x0000ffL, (long_u)0xff00ffL, (long_u)0x00ffffL, (long_u)0xffffffL
+};
+
+static const long_u cterm_color_16[16] =
+{
+ (long_u)0x000000L, (long_u)0x0000c0L, (long_u)0x008000L, (long_u)0x004080L,
+ (long_u)0xc00000L, (long_u)0xc000c0L, (long_u)0x808000L, (long_u)0xc0c0c0L,
+ (long_u)0x808080L, (long_u)0x6060ffL, (long_u)0x00ff00L, (long_u)0x00ffffL,
+ (long_u)0xff8080L, (long_u)0xff40ffL, (long_u)0xffff00L, (long_u)0xffffffL
+};
+
+static int current_syn_id;
+#endif
+
+#define PRCOLOR_BLACK (long_u)0
+#define PRCOLOR_WHITE (long_u)0xFFFFFFL
+
+static int curr_italic;
+static int curr_bold;
+static int curr_underline;
+static long_u curr_bg;
+static long_u curr_fg;
+static int page_count;
+
+/*
+ * These values determine the print position on a page.
+ */
+typedef struct
+{
+ int lead_spaces; /* remaining spaces for a TAB */
+ int print_pos; /* virtual column for computing TABs */
+ colnr_T column; /* byte column */
+ linenr_T file_line; /* line nr in the buffer */
+ long_u bytes_printed; /* bytes printed so far */
+ int ff; /* seen form feed character */
+} prt_pos_T;
+
+#ifdef FEAT_SYN_HL
+static long_u darken_rgb __ARGS((long_u rgb));
+static long_u prt_get_term_color __ARGS((int colorindex));
+#endif
+static void prt_set_fg __ARGS((long_u fg));
+static void prt_set_bg __ARGS((long_u bg));
+static void prt_set_font __ARGS((int bold, int italic, int underline));
+static void prt_line_number __ARGS((prt_settings_T *psettings, int page_line, linenr_T lnum));
+static void prt_header __ARGS((prt_settings_T *psettings, int pagenum, linenr_T lnum));
+static void prt_message __ARGS((char_u *s));
+static colnr_T hardcopy_line __ARGS((prt_settings_T *psettings, int page_line, prt_pos_T *ppos));
+static void prt_get_attr __ARGS((int hl_id, prt_text_attr_T* pattr, int modec));
+
+#ifdef FEAT_SYN_HL
+/*
+ * If using a dark background, the colors will probably be too bright to show
+ * up well on white paper, so reduce their brightness.
+ */
+ static long_u
+darken_rgb(rgb)
+ long_u rgb;
+{
+ return ((rgb >> 17) << 16)
+ + (((rgb & 0xff00) >> 9) << 8)
+ + ((rgb & 0xff) >> 1);
+}
+
+ static long_u
+prt_get_term_color(colorindex)
+ int colorindex;
+{
+ /* TODO: Should check for xterm with 88 or 256 colors. */
+ if (t_colors > 8)
+ return cterm_color_16[colorindex % 16];
+ return cterm_color_8[colorindex % 8];
+}
+
+ static void
+prt_get_attr(hl_id, pattr, modec)
+ int hl_id;
+ prt_text_attr_T* pattr;
+ int modec;
+{
+ int colorindex;
+ long_u fg_color;
+ long_u bg_color;
+ char *color;
+
+ pattr->bold = (highlight_has_attr(hl_id, HL_BOLD, modec) != NULL);
+ pattr->italic = (highlight_has_attr(hl_id, HL_ITALIC, modec) != NULL);
+ pattr->underline = (highlight_has_attr(hl_id, HL_UNDERLINE, modec) != NULL);
+
+# ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ bg_color = highlight_gui_color_rgb(hl_id, FALSE);
+ if (bg_color == PRCOLOR_BLACK)
+ bg_color = PRCOLOR_WHITE;
+
+ fg_color = highlight_gui_color_rgb(hl_id, TRUE);
+ }
+ else
+# endif
+ {
+ bg_color = PRCOLOR_WHITE;
+
+ color = (char *)highlight_color(hl_id, (char_u *)"fg", modec);
+ if (color == NULL)
+ colorindex = 0;
+ else
+ colorindex = atoi(color);
+
+ if (colorindex >= 0 && colorindex < t_colors)
+ fg_color = prt_get_term_color(colorindex);
+ else
+ fg_color = PRCOLOR_BLACK;
+ }
+
+ if (fg_color == PRCOLOR_WHITE)
+ fg_color = PRCOLOR_BLACK;
+ else if (*p_bg == 'd')
+ fg_color = darken_rgb(fg_color);
+
+ pattr->fg_color = fg_color;
+ pattr->bg_color = bg_color;
+}
+#endif /* FEAT_SYN_HL */
+
+ static void
+prt_set_fg(fg)
+ long_u fg;
+{
+ if (fg != curr_fg)
+ {
+ curr_fg = fg;
+ mch_print_set_fg(fg);
+ }
+}
+
+ static void
+prt_set_bg(bg)
+ long_u bg;
+{
+ if (bg != curr_bg)
+ {
+ curr_bg = bg;
+ mch_print_set_bg(bg);
+ }
+}
+
+ static void
+prt_set_font(bold, italic, underline)
+ int bold;
+ int italic;
+ int underline;
+{
+ if (curr_bold != bold
+ || curr_italic != italic
+ || curr_underline != underline)
+ {
+ curr_underline = underline;
+ curr_italic = italic;
+ curr_bold = bold;
+ mch_print_set_font(bold, italic, underline);
+ }
+}
+
+/*
+ * Print the line number in the left margin.
+ */
+ static void
+prt_line_number(psettings, page_line, lnum)
+ prt_settings_T *psettings;
+ int page_line;
+ linenr_T lnum;
+{
+ int i;
+ char_u tbuf[20];
+
+ prt_set_fg(psettings->number.fg_color);
+ prt_set_bg(psettings->number.bg_color);
+ prt_set_font(psettings->number.bold, psettings->number.italic, psettings->number.underline);
+ mch_print_start_line(TRUE, page_line);
+
+ /* Leave two spaces between the number and the text; depends on
+ * PRINT_NUMBER_WIDTH. */
+ sprintf((char *)tbuf, "%6ld", (long)lnum);
+ for (i = 0; i < 6; i++)
+ (void)mch_print_text_out(&tbuf[i], 1);
+
+#ifdef FEAT_SYN_HL
+ if (psettings->do_syntax)
+ /* Set colors for next character. */
+ current_syn_id = -1;
+ else
+#endif
+ {
+ /* Set colors and font back to normal. */
+ prt_set_fg(PRCOLOR_BLACK);
+ prt_set_bg(PRCOLOR_WHITE);
+ prt_set_font(FALSE, FALSE, FALSE);
+ }
+}
+
+static linenr_T printer_page_num;
+
+ int
+get_printer_page_num()
+{
+ return printer_page_num;
+}
+
+/*
+ * Get the currently effective header height.
+ */
+ int
+prt_header_height()
+{
+ if (printer_opts[OPT_PRINT_HEADERHEIGHT].present)
+ return printer_opts[OPT_PRINT_HEADERHEIGHT].number;
+ return 2;
+}
+
+/*
+ * Return TRUE if using a line number for printing.
+ */
+ int
+prt_use_number()
+{
+ return (printer_opts[OPT_PRINT_NUMBER].present
+ && TOLOWER_ASC(printer_opts[OPT_PRINT_NUMBER].string[0]) == 'y');
+}
+
+/*
+ * Return the unit used in a margin item in 'printoptions'.
+ * Returns PRT_UNIT_NONE if not recognized.
+ */
+ int
+prt_get_unit(idx)
+ int idx;
+{
+ int u = PRT_UNIT_NONE;
+ int i;
+ static char *(units[4]) = PRT_UNIT_NAMES;
+
+ if (printer_opts[idx].present)
+ for (i = 0; i < 4; ++i)
+ if (STRNICMP(printer_opts[idx].string, units[i], 2) == 0)
+ {
+ u = i;
+ break;
+ }
+ return u;
+}
+
+/*
+ * Print the page header.
+ */
+/*ARGSUSED*/
+ static void
+prt_header(psettings, pagenum, lnum)
+ prt_settings_T *psettings;
+ int pagenum;
+ linenr_T lnum;
+{
+ int width = psettings->chars_per_line;
+ int page_line;
+ char_u *tbuf;
+ char_u *p;
+#ifdef FEAT_MBYTE
+ int l;
+#endif
+
+ /* Also use the space for the line number. */
+ if (prt_use_number())
+ width += PRINT_NUMBER_WIDTH;
+
+ tbuf = alloc(width + IOSIZE);
+ if (tbuf == NULL)
+ return;
+
+#ifdef FEAT_STL_OPT
+ if (*p_header != NUL)
+ {
+ linenr_T tmp_lnum, tmp_topline, tmp_botline;
+
+ /*
+ * Need to (temporarily) set current line number and first/last line
+ * number on the 'window'. Since we don't know how long the page is,
+ * set the first and current line number to the top line, and guess
+ * that the page length is 64.
+ */
+ tmp_lnum = curwin->w_cursor.lnum;
+ tmp_topline = curwin->w_topline;
+ tmp_botline = curwin->w_botline;
+ curwin->w_cursor.lnum = lnum;
+ curwin->w_topline = lnum;
+ curwin->w_botline = lnum + 63;
+ printer_page_num = pagenum;
+
+ build_stl_str_hl(curwin, tbuf, (size_t)(width + IOSIZE),
+ p_header, ' ', width, NULL);
+
+ /* Reset line numbers */
+ curwin->w_cursor.lnum = tmp_lnum;
+ curwin->w_topline = tmp_topline;
+ curwin->w_botline = tmp_botline;
+ }
+ else
+#endif
+ sprintf((char *)tbuf, _("Page %d"), pagenum);
+
+ prt_set_fg(PRCOLOR_BLACK);
+ prt_set_bg(PRCOLOR_WHITE);
+ prt_set_font(TRUE, FALSE, FALSE);
+
+ /* Use a negative line number to indicate printing in the top margin. */
+ page_line = 0 - prt_header_height();
+ mch_print_start_line(TRUE, page_line);
+ for (p = tbuf; *p != NUL; )
+ {
+ if (mch_print_text_out(p,
+#ifdef FEAT_MBYTE
+ (l = (*mb_ptr2len_check)(p))
+#else
+ 1
+#endif
+ ))
+ {
+ ++page_line;
+ if (page_line >= 0) /* out of room in header */
+ break;
+ mch_print_start_line(TRUE, page_line);
+ }
+#ifdef FEAT_MBYTE
+ p += l;
+#else
+ p++;
+#endif
+ }
+
+ vim_free(tbuf);
+
+#ifdef FEAT_SYN_HL
+ if (psettings->do_syntax)
+ /* Set colors for next character. */
+ current_syn_id = -1;
+ else
+#endif
+ {
+ /* Set colors and font back to normal. */
+ prt_set_fg(PRCOLOR_BLACK);
+ prt_set_bg(PRCOLOR_WHITE);
+ prt_set_font(FALSE, FALSE, FALSE);
+ }
+}
+
+/*
+ * Display a print status message.
+ */
+ static void
+prt_message(s)
+ char_u *s;
+{
+ screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
+ screen_puts(s, (int)Rows - 1, 0, hl_attr(HLF_R));
+ out_flush();
+}
+
+ void
+ex_hardcopy(eap)
+ exarg_T *eap;
+{
+ linenr_T lnum;
+ int collated_copies, uncollated_copies;
+ prt_settings_T settings;
+ long_u bytes_to_print = 0;
+ int page_line;
+ int jobsplit;
+ int id;
+
+ memset(&settings, 0, sizeof(prt_settings_T));
+ settings.has_color = TRUE;
+
+# ifdef FEAT_POSTSCRIPT
+ if (*eap->arg == '>')
+ {
+ char_u *errormsg = NULL;
+
+ /* Expand things like "%.ps". */
+ if (expand_filename(eap, eap->cmdlinep, &errormsg) == FAIL)
+ {
+ if (errormsg != NULL)
+ EMSG(errormsg);
+ return;
+ }
+ settings.outfile = skipwhite(eap->arg + 1);
+ }
+ else if (*eap->arg != NUL)
+ settings.arguments = eap->arg;
+# endif
+
+ /*
+ * Initialise for printing. Ask the user for settings, unless forceit is
+ * set.
+ * The mch_print_init() code should set up margins if applicable. (It may
+ * not be a real printer - for example the engine might generate HTML or
+ * PS.)
+ */
+ if (mch_print_init(&settings,
+ curbuf->b_fname == NULL
+ ? (char_u *)buf_spname(curbuf)
+ : curbuf->b_sfname == NULL
+ ? curbuf->b_fname
+ : curbuf->b_sfname,
+ eap->forceit) == FAIL)
+ return;
+
+#ifdef FEAT_SYN_HL
+# ifdef FEAT_GUI
+ if (gui.in_use)
+ settings.modec = 'g';
+ else
+# endif
+ if (t_colors > 1)
+ settings.modec = 'c';
+ else
+ settings.modec = 't';
+
+ if (!syntax_present(curbuf))
+ settings.do_syntax = FALSE;
+ else if (printer_opts[OPT_PRINT_SYNTAX].present
+ && TOLOWER_ASC(printer_opts[OPT_PRINT_SYNTAX].string[0]) != 'a')
+ settings.do_syntax =
+ (TOLOWER_ASC(printer_opts[OPT_PRINT_SYNTAX].string[0]) == 'y');
+ else
+ settings.do_syntax = settings.has_color;
+#endif
+
+ /* Set up printing attributes for line numbers */
+ settings.number.fg_color = PRCOLOR_BLACK;
+ settings.number.bg_color = PRCOLOR_WHITE;
+ settings.number.bold = FALSE;
+ settings.number.italic = TRUE;
+ settings.number.underline = FALSE;
+#ifdef FEAT_SYN_HL
+ /*
+ * Syntax highlighting of line numbers.
+ */
+ if (prt_use_number() && settings.do_syntax)
+ {
+ id = syn_name2id((char_u *)"LineNr");
+ if (id > 0)
+ id = syn_get_final_id(id);
+
+ prt_get_attr(id, &settings.number, settings.modec);
+ }
+#endif /* FEAT_SYN_HL */
+
+ /*
+ * Estimate the total lines to be printed
+ */
+ for (lnum = eap->line1; lnum <= eap->line2; lnum++)
+ bytes_to_print += (long_u)STRLEN(skipwhite(ml_get(lnum)));
+ if (bytes_to_print == 0)
+ {
+ MSG(_("No text to be printed"));
+ goto print_fail_no_begin;
+ }
+
+ /* Set colors and font to normal. */
+ curr_bg = (long_u)0xffffffffL;
+ curr_fg = (long_u)0xffffffffL;
+ curr_italic = MAYBE;
+ curr_bold = MAYBE;
+ curr_underline = MAYBE;
+
+ prt_set_fg(PRCOLOR_BLACK);
+ prt_set_bg(PRCOLOR_WHITE);
+ prt_set_font(FALSE, FALSE, FALSE);
+#ifdef FEAT_SYN_HL
+ current_syn_id = -1;
+#endif
+
+ jobsplit = (printer_opts[OPT_PRINT_JOBSPLIT].present
+ && TOLOWER_ASC(printer_opts[OPT_PRINT_JOBSPLIT].string[0]) == 'y');
+
+ if (!mch_print_begin(&settings))
+ goto print_fail_no_begin;
+
+ /*
+ * Loop over collated copies: 1 2 3, 1 2 3, ...
+ */
+ page_count = 0;
+ for (collated_copies = 0;
+ collated_copies < settings.n_collated_copies;
+ collated_copies++)
+ {
+ prt_pos_T prtpos; /* current print position */
+ prt_pos_T page_prtpos; /* print position at page start */
+ int side;
+
+ memset(&page_prtpos, 0, sizeof(prt_pos_T));
+ page_prtpos.file_line = eap->line1;
+ prtpos = page_prtpos;
+
+ if (jobsplit && collated_copies > 0)
+ {
+ /* Splitting jobs: Stop a previous job and start a new one. */
+ mch_print_end(&settings);
+ if (!mch_print_begin(&settings))
+ goto print_fail_no_begin;
+ }
+
+ /*
+ * Loop over all pages in the print job: 1 2 3 ...
+ */
+ for (page_count = 0; prtpos.file_line <= eap->line2; ++page_count)
+ {
+ /*
+ * Loop over uncollated copies: 1 1 1, 2 2 2, 3 3 3, ...
+ * For duplex: 12 12 12 34 34 34, ...
+ */
+ for (uncollated_copies = 0;
+ uncollated_copies < settings.n_uncollated_copies;
+ uncollated_copies++)
+ {
+ /* Set the print position to the start of this page. */
+ prtpos = page_prtpos;
+
+ /*
+ * Do front and rear side of a page.
+ */
+ for (side = 0; side <= settings.duplex; ++side)
+ {
+ /*
+ * Print one page.
+ */
+
+ /* Check for interrupt character every page. */
+ ui_breakcheck();
+ if (got_int || settings.user_abort)
+ goto print_fail;
+
+ sprintf((char *)IObuff, _("Printing page %d (%d%%)"),
+ page_count + 1 + side,
+ prtpos.bytes_printed > 1000000
+ ? (int)(prtpos.bytes_printed /
+ (bytes_to_print / 100))
+ : (int)((prtpos.bytes_printed * 100)
+ / bytes_to_print));
+ if (!mch_print_begin_page(IObuff))
+ goto print_fail;
+
+ if (settings.n_collated_copies > 1)
+ sprintf((char *)IObuff + STRLEN(IObuff),
+ _(" Copy %d of %d"),
+ collated_copies + 1,
+ settings.n_collated_copies);
+ prt_message(IObuff);
+
+ /*
+ * Output header if required
+ */
+ if (prt_header_height() > 0)
+ prt_header(&settings, page_count + 1 + side,
+ prtpos.file_line);
+
+ for (page_line = 0; page_line < settings.lines_per_page;
+ ++page_line)
+ {
+ prtpos.column = hardcopy_line(&settings,
+ page_line, &prtpos);
+ if (prtpos.column == 0)
+ {
+ /* finished a file line */
+ prtpos.bytes_printed +=
+ STRLEN(skipwhite(ml_get(prtpos.file_line)));
+ if (++prtpos.file_line > eap->line2)
+ break; /* reached the end */
+ }
+ else if (prtpos.ff)
+ {
+ /* Line had a formfeed in it - start new page but
+ * stay on the current line */
+ break;
+ }
+ }
+
+ if (!mch_print_end_page())
+ goto print_fail;
+ if (prtpos.file_line > eap->line2)
+ break; /* reached the end */
+ }
+
+ /*
+ * Extra blank page for duplexing with odd number of pages and
+ * more copies to come.
+ */
+ if (prtpos.file_line > eap->line2 && settings.duplex
+ && side == 0
+ && uncollated_copies + 1 < settings.n_uncollated_copies)
+ {
+ if (!mch_print_blank_page())
+ goto print_fail;
+ }
+ }
+ if (settings.duplex && prtpos.file_line <= eap->line2)
+ ++page_count;
+
+ /* Remember the position where the next page starts. */
+ page_prtpos = prtpos;
+ }
+
+ sprintf((char *)IObuff, _("Printed: %s"), settings.jobname);
+ prt_message(IObuff);
+ }
+
+print_fail:
+ if (got_int || settings.user_abort)
+ {
+ sprintf((char *)IObuff, _("Printing aborted"));
+ prt_message(IObuff);
+ }
+ mch_print_end(&settings);
+
+print_fail_no_begin:
+ mch_print_cleanup();
+}
+
+/*
+ * Print one page line.
+ * Return the next column to print, or zero if the line is finished.
+ */
+ static colnr_T
+hardcopy_line(psettings, page_line, ppos)
+ prt_settings_T *psettings;
+ int page_line;
+ prt_pos_T *ppos;
+{
+ colnr_T col;
+ char_u *line;
+ int need_break = FALSE;
+ int outputlen;
+ int tab_spaces;
+ long_u print_pos;
+#ifdef FEAT_SYN_HL
+ prt_text_attr_T attr;
+ int id;
+#endif
+
+ if (ppos->column == 0 || ppos->ff)
+ {
+ print_pos = 0;
+ tab_spaces = 0;
+ if (!ppos->ff && prt_use_number())
+ prt_line_number(psettings, page_line, ppos->file_line);
+ ppos->ff = FALSE;
+ }
+ else
+ {
+ /* left over from wrap halfway a tab */
+ print_pos = ppos->print_pos;
+ tab_spaces = ppos->lead_spaces;
+ }
+
+ mch_print_start_line(0, page_line);
+ line = ml_get(ppos->file_line);
+
+ /*
+ * Loop over the columns until the end of the file line or right margin.
+ */
+ for (col = ppos->column; line[col] != NUL && !need_break; col += outputlen)
+ {
+ outputlen = 1;
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (outputlen = (*mb_ptr2len_check)(line + col)) < 1)
+ outputlen = 1;
+#endif
+#ifdef FEAT_SYN_HL
+ /*
+ * syntax highlighting stuff.
+ */
+ if (psettings->do_syntax)
+ {
+ id = syn_get_id(ppos->file_line, (long)col, 1);
+ if (id > 0)
+ id = syn_get_final_id(id);
+ else
+ id = 0;
+ /* Get the line again, a multi-line regexp may invalidate it. */
+ line = ml_get(ppos->file_line);
+
+ if (id != current_syn_id)
+ {
+ current_syn_id = id;
+ prt_get_attr(id, &attr, psettings->modec);
+ prt_set_font(attr.bold, attr.italic, attr.underline);
+ prt_set_fg(attr.fg_color);
+ prt_set_bg(attr.bg_color);
+ }
+ }
+#endif /* FEAT_SYN_HL */
+
+ /*
+ * Appropriately expand any tabs to spaces.
+ */
+ if (line[col] == TAB || tab_spaces != 0)
+ {
+ if (tab_spaces == 0)
+ tab_spaces = curbuf->b_p_ts - (print_pos % curbuf->b_p_ts);
+
+ while (tab_spaces > 0)
+ {
+ need_break = mch_print_text_out((char_u *)" ", 1);
+ print_pos++;
+ tab_spaces--;
+ if (need_break)
+ break;
+ }
+ /* Keep the TAB if we didn't finish it. */
+ if (need_break && tab_spaces > 0)
+ break;
+ }
+ else if (line[col] == FF
+ && printer_opts[OPT_PRINT_FORMFEED].present
+ && TOLOWER_ASC(printer_opts[OPT_PRINT_FORMFEED].string[0])
+ == 'y')
+ {
+ ppos->ff = TRUE;
+ need_break = 1;
+ }
+ else
+ {
+ need_break = mch_print_text_out(line + col, outputlen);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ print_pos += (*mb_ptr2cells)(line + col);
+ else
+#endif
+ print_pos++;
+ }
+ }
+
+ ppos->lead_spaces = tab_spaces;
+ ppos->print_pos = print_pos;
+
+ /*
+ * Start next line of file if we clip lines, or have reached end of the
+ * line, unless we are doing a formfeed.
+ */
+ if (!ppos->ff
+ && (line[col] == NUL
+ || (printer_opts[OPT_PRINT_WRAP].present
+ && TOLOWER_ASC(printer_opts[OPT_PRINT_WRAP].string[0])
+ == 'n')))
+ return 0;
+ return col;
+}
+
+# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
+
+/*
+ * PS printer stuff.
+ *
+ * Sources of information to help maintain the PS printing code:
+ *
+ * 1. PostScript Language Reference, 3rd Edition,
+ * Addison-Wesley, 1999, ISBN 0-201-37922-8
+ * 2. PostScript Language Program Design,
+ * Addison-Wesley, 1988, ISBN 0-201-14396-8
+ * 3. PostScript Tutorial and Cookbook,
+ * Addison Wesley, 1985, ISBN 0-201-10179-3
+ * 4. PostScript Language Document Structuring Conventions Specification,
+ * version 3.0,
+ * Adobe Technote 5001, 25th September 1992
+ * 5. PostScript Printer Description File Format Specification, Version 4.3,
+ * Adobe technote 5003, 9th February 1996
+ * 6. Adobe Font Metrics File Format Specification, Version 4.1,
+ * Adobe Technote 5007, 7th October 1998
+ *
+ * Some of these documents can be found in PDF form on Adobe's web site -
+ * http://www.adobe.com
+ */
+
+#define PRT_PS_DEFAULT_DPI (72) /* Default user space resolution */
+#define PRT_PS_DEFAULT_FONTSIZE (10)
+#define PRT_PS_DEFAULT_BUFFER_SIZE (80)
+
+struct prt_mediasize_S
+{
+ char *name;
+ float width; /* width and height in points for portrait */
+ float height;
+};
+
+#define PRT_MEDIASIZE_LEN (sizeof(prt_mediasize) / sizeof(struct prt_mediasize_S))
+
+static struct prt_mediasize_S prt_mediasize[] =
+{
+ {"A4", 595.0, 842.0},
+ {"letter", 612.0, 792.0},
+ {"10x14", 720.0, 1008.0},
+ {"A3", 842.0, 1191.0},
+ {"A5", 420.0, 595.0},
+ {"B4", 729.0, 1032.0},
+ {"B5", 516.0, 729.0},
+ {"executive", 522.0, 756.0},
+ {"folio", 595.0, 935.0},
+ {"ledger", 1224.0, 792.0}, /* Yes, it is wider than taller! */
+ {"legal", 612.0, 1008.0},
+ {"quarto", 610.0, 780.0},
+ {"statement", 396.0, 612.0},
+ {"tabloid", 792.0, 1224.0}
+};
+
+/* PS font names, must be in Roman, Bold, Italic, Bold-Italic order */
+struct prt_ps_font_S
+{
+ int wx;
+ int uline_offset;
+ int uline_width;
+ int bbox_min_y;
+ int bbox_max_y;
+ char *(ps_fontname[4]);
+};
+
+#define PRT_PS_FONT_ROMAN (0)
+#define PRT_PS_FONT_BOLD (1)
+#define PRT_PS_FONT_OBLIQUE (2)
+#define PRT_PS_FONT_BOLDOBLIQUE (3)
+
+static struct prt_ps_font_S prt_ps_font =
+{
+ 600,
+ -100, 50,
+ -250, 805,
+ {"Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique"}
+};
+
+struct prt_ps_resource_S
+{
+ char_u name[64];
+ char_u filename[MAXPATHL + 1];
+ int type;
+ char_u title[256];
+ char_u version[256];
+};
+
+/* Types of PS resource file currently used */
+#define PRT_RESOURCE_TYPE_PROCSET (0)
+#define PRT_RESOURCE_TYPE_ENCODING (1)
+
+/* The PS prolog file version number has to match - if the prolog file is
+ * updated, increment the number in the file and here. Version checking was
+ * added as of VIM 6.2.
+ * Table of VIM and prolog versions:
+ *
+ * VIM Prolog
+ * 6.2 1.3
+ */
+#define PRT_PROLOG_VERSION ((char_u *)"1.3")
+
+/* String versions of PS resource types - indexed by constants above so don't
+ * re-order!
+ */
+static char *resource_types[] =
+{
+ "procset",
+ "encoding"
+};
+
+/* Strings to look for in a PS resource file */
+#define PRT_RESOURCE_HEADER "%!PS-Adobe-"
+#define PRT_RESOURCE_RESOURCE "Resource-"
+#define PRT_RESOURCE_PROCSET "ProcSet"
+#define PRT_RESOURCE_ENCODING "Encoding"
+#define PRT_RESOURCE_TITLE "%%Title:"
+#define PRT_RESOURCE_VERSION "%%Version:"
+
+static void prt_write_file_raw_len __ARGS((char_u *buffer, int bytes));
+static void prt_write_file __ARGS((char_u *buffer));
+static void prt_write_file_len __ARGS((char_u *buffer, int bytes));
+static void prt_write_string __ARGS((char *s));
+static void prt_write_int __ARGS((int i));
+static void prt_write_boolean __ARGS((int b));
+static void prt_def_font __ARGS((char *new_name, char *encoding, int height, char *font));
+static void prt_real_bits __ARGS((double real, int precision, int *pinteger, int *pfraction));
+static void prt_write_real __ARGS((double val, int prec));
+static void prt_def_var __ARGS((char *name, double value, int prec));
+static void prt_flush_buffer __ARGS((void));
+static void prt_resource_name __ARGS((char_u *filename));
+static int prt_find_resource __ARGS((char *name, struct prt_ps_resource_S *resource));
+static int prt_open_resource __ARGS((struct prt_ps_resource_S *resource));
+static int prt_check_resource __ARGS((struct prt_ps_resource_S *resource, char_u *version));
+static void prt_dsc_start __ARGS((void));
+static void prt_dsc_noarg __ARGS((char *comment));
+static void prt_dsc_textline __ARGS((char *comment, char *text));
+static void prt_dsc_text __ARGS((char *comment, char *text));
+static void prt_dsc_ints __ARGS((char *comment, int count, int *ints));
+static void prt_dsc_requirements __ARGS((int duplex, int tumble, int collate, int color, int num_copies));
+static void prt_dsc_docmedia __ARGS((char *paper_name, double width, double height, double weight, char *colour, char *type));
+static void prt_dsc_resources __ARGS((char *comment, char *type, int count, char **strings));
+static float to_device_units __ARGS((int idx, double physsize, int def_number));
+static void prt_page_margins __ARGS((double width, double height, double *left, double *right, double *top, double *bottom));
+static void prt_font_metrics __ARGS((int font_scale));
+static int prt_get_cpl __ARGS((void));
+static int prt_get_lpp __ARGS((void));
+static int prt_add_resource __ARGS((struct prt_ps_resource_S *resource));
+
+/*
+ * Variables for the output PostScript file.
+ */
+static FILE *prt_ps_fd;
+static int prt_file_error;
+static char_u *prt_ps_file_name = NULL;
+
+/*
+ * Various offsets and dimensions in default PostScript user space (points).
+ * Used for text positioning calculations
+ */
+static float prt_page_width;
+static float prt_page_height;
+static float prt_left_margin;
+static float prt_right_margin;
+static float prt_top_margin;
+static float prt_bottom_margin;
+static float prt_line_height;
+static float prt_first_line_height;
+static float prt_char_width;
+static float prt_number_width;
+static float prt_bgcol_offset;
+static float prt_pos_x_moveto = 0.0;
+static float prt_pos_y_moveto = 0.0;
+
+/*
+ * Various control variables used to decide when and how to change the
+ * PostScript graphics state.
+ */
+static int prt_need_moveto;
+static int prt_do_moveto;
+static int prt_need_font;
+static int prt_font;
+static int prt_need_underline;
+static int prt_underline;
+static int prt_do_underline;
+static int prt_need_fgcol;
+static int prt_fgcol;
+static int prt_need_bgcol;
+static int prt_do_bgcol;
+static int prt_bgcol;
+static int prt_new_bgcol;
+static int prt_attribute_change;
+static int prt_text_count;
+static int prt_page_num;
+
+/*
+ * Variables controlling physical printing.
+ */
+static int prt_media;
+static int prt_portrait;
+static int prt_num_copies;
+static int prt_duplex;
+static int prt_tumble;
+static int prt_collate;
+
+/*
+ * Buffers used when generating PostScript output
+ */
+static char_u prt_line_buffer[257];
+static garray_T prt_ps_buffer;
+
+# ifdef FEAT_MBYTE
+static int prt_do_conv;
+static vimconv_T prt_conv;
+# endif
+
+ static void
+prt_write_file_raw_len(buffer, bytes)
+ char_u *buffer;
+ int bytes;
+{
+ if (!prt_file_error
+ && fwrite(buffer, sizeof(char_u), bytes, prt_ps_fd)
+ != (size_t)bytes)
+ {
+ EMSG(_("E455: Error writing to PostScript output file"));
+ prt_file_error = TRUE;
+ }
+}
+
+ static void
+prt_write_file(buffer)
+ char_u *buffer;
+{
+ prt_write_file_len(buffer, STRLEN(buffer));
+}
+
+ static void
+prt_write_file_len(buffer, bytes)
+ char_u *buffer;
+ int bytes;
+{
+#ifdef EBCDIC
+ ebcdic2ascii(buffer, bytes);
+#endif
+ prt_write_file_raw_len(buffer, bytes);
+}
+
+/*
+ * Write a string.
+ */
+ static void
+prt_write_string(s)
+ char *s;
+{
+ sprintf((char *)prt_line_buffer, "%s", s);
+ prt_write_file(prt_line_buffer);
+}
+
+/*
+ * Write an int and a space.
+ */
+ static void
+prt_write_int(i)
+ int i;
+{
+ sprintf((char *)prt_line_buffer, "%d ", i);
+ prt_write_file(prt_line_buffer);
+}
+
+/*
+ * Write a boolean and a space.
+ */
+ static void
+prt_write_boolean(b)
+ int b;
+{
+ sprintf((char *)prt_line_buffer, "%s ", (b ? "T" : "F"));
+ prt_write_file(prt_line_buffer);
+}
+
+/*
+ * Write a line to define the font.
+ */
+ static void
+prt_def_font(new_name, encoding, height, font)
+ char *new_name;
+ char *encoding;
+ int height;
+ char *font;
+{
+ sprintf((char *)prt_line_buffer, "/_%s /VIM-%s /%s ref\n", new_name, encoding, font);
+ prt_write_file(prt_line_buffer);
+ sprintf((char *)prt_line_buffer, "/%s %d /_%s ffs\n",
+ new_name, height, new_name);
+ prt_write_file(prt_line_buffer);
+}
+
+/*
+ * Convert a real value into an integer and fractional part as integers, with
+ * the fractional part being in the range [0,10^precision). The fractional part
+ * is also rounded based on the precision + 1'th fractional digit.
+ */
+ static void
+prt_real_bits(real, precision, pinteger, pfraction)
+ double real;
+ int precision;
+ int *pinteger;
+ int *pfraction;
+{
+ int i;
+ int integer;
+ float fraction;
+
+ integer = (int)real;
+ fraction = (float)(real - integer);
+ if (real < (double)integer)
+ fraction = -fraction;
+ for (i = 0; i < precision; i++)
+ fraction *= 10.0;
+
+ *pinteger = integer;
+ *pfraction = (int)(fraction + 0.5);
+}
+
+/*
+ * Write a real and a space. Save bytes if real value has no fractional part!
+ * We use prt_real_bits() as %f in sprintf uses the locale setting to decide
+ * what decimal point character to use, but PS always requires a '.'.
+ */
+ static void
+prt_write_real(val, prec)
+ double val;
+ int prec;
+{
+ int integer;
+ int fraction;
+
+ prt_real_bits(val, prec, &integer, &fraction);
+ /* Emit integer part */
+ sprintf((char *)prt_line_buffer, "%d", integer);
+ prt_write_file(prt_line_buffer);
+ /* Only emit fraction if necessary */
+ if (fraction != 0)
+ {
+ /* Remove any trailing zeros */
+ while ((fraction % 10) == 0)
+ {
+ prec--;
+ fraction /= 10;
+ }
+ /* Emit fraction left padded with zeros */
+ sprintf((char *)prt_line_buffer, ".%0*d", prec, fraction);
+ prt_write_file(prt_line_buffer);
+ }
+ sprintf((char *)prt_line_buffer, " ");
+ prt_write_file(prt_line_buffer);
+}
+
+/*
+ * Write a line to define a numeric variable.
+ */
+ static void
+prt_def_var(name, value, prec)
+ char *name;
+ double value;
+ int prec;
+{
+ sprintf((char *)prt_line_buffer, "/%s ", name);
+ prt_write_file(prt_line_buffer);
+ prt_write_real(value, prec);
+ sprintf((char *)prt_line_buffer, "d\n");
+ prt_write_file(prt_line_buffer);
+}
+
+/* Convert size from font space to user space at current font scale */
+#define PRT_PS_FONT_TO_USER(scale, size) ((size) * ((scale)/1000.0))
+
+ static void
+prt_flush_buffer()
+{
+ if (prt_ps_buffer.ga_len > 0)
+ {
+ /* Any background color must be drawn first */
+ if (prt_do_bgcol && (prt_new_bgcol != PRCOLOR_WHITE))
+ {
+ int r, g, b;
+
+ if (prt_do_moveto)
+ {
+ prt_write_real(prt_pos_x_moveto, 2);
+ prt_write_real(prt_pos_y_moveto, 2);
+ prt_write_string("m\n");
+ prt_do_moveto = FALSE;
+ }
+
+ /* Size of rect of background color on which text is printed */
+ prt_write_real(prt_text_count * prt_char_width, 2);
+ prt_write_real(prt_line_height, 2);
+
+ /* Lastly add the color of the background */
+ r = ((unsigned)prt_new_bgcol & 0xff0000) >> 16;
+ g = ((unsigned)prt_new_bgcol & 0xff00) >> 8;
+ b = prt_new_bgcol & 0xff;
+ prt_write_real(r / 255.0, 3);
+ prt_write_real(g / 255.0, 3);
+ prt_write_real(b / 255.0, 3);
+ prt_write_string("bg\n");
+ }
+ /* Draw underlines before the text as it makes it slightly easier to
+ * find the starting point.
+ */
+ if (prt_do_underline)
+ {
+ if (prt_do_moveto)
+ {
+ prt_write_real(prt_pos_x_moveto, 2);
+ prt_write_real(prt_pos_y_moveto, 2);
+ prt_write_string("m\n");
+ prt_do_moveto = FALSE;
+ }
+
+ /* Underlining is easy - just need the number of characters to
+ * print. */
+ prt_write_real(prt_text_count * prt_char_width, 2);
+ prt_write_string("ul\n");
+ }
+ /* Draw the text
+ * Note: we write text out raw - EBCDIC conversion is handled in the
+ * PostScript world via the font encoding vector. */
+ prt_write_string("(");
+ prt_write_file_raw_len(prt_ps_buffer.ga_data, prt_ps_buffer.ga_len);
+ prt_write_string(")");
+ /* Add a moveto if need be and use the appropriate show procedure */
+ if (prt_do_moveto)
+ {
+ prt_write_real(prt_pos_x_moveto, 2);
+ prt_write_real(prt_pos_y_moveto, 2);
+ /* moveto and a show */
+ prt_write_string("ms\n");
+ prt_do_moveto = FALSE;
+ }
+ else /* Simple show */
+ prt_write_string("s\n");
+
+ ga_clear(&prt_ps_buffer);
+ ga_init2(&prt_ps_buffer, (int)sizeof(char), PRT_PS_DEFAULT_BUFFER_SIZE);
+ }
+}
+
+static char_u *resource_filename;
+
+ static void
+prt_resource_name(filename)
+ char_u *filename;
+{
+ if (STRLEN(filename) >= MAXPATHL)
+ *resource_filename = NUL;
+ else
+ STRCPY(resource_filename, filename);
+}
+
+ static int
+prt_find_resource(name, resource)
+ char *name;
+ struct prt_ps_resource_S *resource;
+{
+ char_u buffer[MAXPATHL + 1];
+
+ STRCPY(resource->name, name);
+ /* Look for named resource file in runtimepath */
+ STRCPY(buffer, "print");
+ add_pathsep(buffer);
+ STRCAT(buffer, name);
+ STRCAT(buffer, ".ps");
+ resource_filename = resource->filename;
+ *resource_filename = NUL;
+ return (do_in_runtimepath(buffer, FALSE, prt_resource_name)
+ && resource->filename[0] != NUL);
+}
+
+/* PS CR and LF characters have platform independent values */
+#define PSLF (0x0a)
+#define PSCR (0x0d)
+
+/* Very simple hand crafted parser to get the type, title, and version number of
+ * a PS resource file so the file details can be added to the DSC header
+ * comments. */
+ static int
+prt_open_resource(resource)
+ struct prt_ps_resource_S *resource;
+{
+ FILE *fd_resource;
+ char_u buffer[128];
+ char_u *ch = buffer;
+ char_u *ch2;
+
+ fd_resource = mch_fopen((char *)resource->filename, READBIN);
+ if (fd_resource == NULL)
+ {
+ EMSG2(_("E624: Can't open file \"%s\""), resource->filename);
+ return FALSE;
+ }
+ vim_memset(buffer, NUL, sizeof(buffer));
+
+ /* Parse first line to ensure valid resource file */
+ (void)fread((char *)buffer, sizeof(char_u), sizeof(buffer),
+ fd_resource);
+ if (ferror(fd_resource))
+ {
+ EMSG2(_("E457: Can't read PostScript resource file \"%s\""),
+ resource->filename);
+ fclose(fd_resource);
+ return FALSE;
+ }
+
+ if (STRNCMP(ch, PRT_RESOURCE_HEADER, STRLEN(PRT_RESOURCE_HEADER)) != 0)
+ {
+ EMSG2(_("E618: file \"%s\" is not a PostScript resource file"),
+ resource->filename);
+ fclose(fd_resource);
+ return FALSE;
+ }
+
+ /* Skip over any version numbers and following ws */
+ ch += STRLEN(PRT_RESOURCE_HEADER);
+ while (!isspace(*ch))
+ ch++;
+ while (isspace(*ch))
+ ch++;
+
+ if (STRNCMP(ch, PRT_RESOURCE_RESOURCE, STRLEN(PRT_RESOURCE_RESOURCE)) != 0)
+ {
+ EMSG2(_("E619: file \"%s\" is not a supported PostScript resource file"),
+ resource->filename);
+ fclose(fd_resource);
+ return FALSE;
+ }
+ ch += STRLEN(PRT_RESOURCE_RESOURCE);
+
+ /* Decide type of resource in the file */
+ if (STRNCMP(ch, PRT_RESOURCE_PROCSET, STRLEN(PRT_RESOURCE_PROCSET)) == 0)
+ {
+ resource->type = PRT_RESOURCE_TYPE_PROCSET;
+ ch += STRLEN(PRT_RESOURCE_PROCSET);
+ }
+ else if (STRNCMP(ch, PRT_RESOURCE_ENCODING, STRLEN(PRT_RESOURCE_ENCODING)) == 0)
+ {
+ resource->type = PRT_RESOURCE_TYPE_ENCODING;
+ ch += STRLEN(PRT_RESOURCE_ENCODING);
+ }
+ else
+ {
+ EMSG2(_("E619: file \"%s\" is not a supported PostScript resource file"),
+ resource->filename);
+ fclose(fd_resource);
+ return FALSE;
+ }
+
+ /* Consume up to and including the CR/LF/CR_LF */
+ while (*ch != PSCR && *ch != PSLF)
+ ch++;
+ while (*ch == PSCR || *ch == PSLF)
+ ch++;
+
+ /* Match %%Title: */
+ if (STRNCMP(ch, PRT_RESOURCE_TITLE, STRLEN(PRT_RESOURCE_TITLE)) != 0)
+ {
+ EMSG2(_("E619: file \"%s\" is not a supported PostScript resource file"),
+ resource->filename);
+ fclose(fd_resource);
+ return FALSE;
+ }
+ ch += STRLEN(PRT_RESOURCE_TITLE);
+
+ /* Skip ws after %%Title: */
+ while (isspace(*ch))
+ ch++;
+
+ /* Copy up to the CR/LF/CR_LF */
+ ch2 = resource->title;
+ while (*ch != PSCR && *ch != PSLF)
+ *ch2++ = *ch++;
+ *ch2 = '\0';
+ while (*ch == PSCR || *ch == PSLF)
+ ch++;
+
+ /* Match %%Version: */
+ if (STRNCMP(ch, PRT_RESOURCE_VERSION, STRLEN(PRT_RESOURCE_VERSION)) != 0)
+ {
+ EMSG2(_("E619: file \"%s\" is not a supported PostScript resource file"),
+ resource->filename);
+ fclose(fd_resource);
+ return FALSE;
+ }
+ ch += STRLEN(PRT_RESOURCE_VERSION);
+
+ /* Skip ws after %%Version: */
+ while (isspace(*ch))
+ ch++;
+
+ /* Copy up to the CR/LF/CR_LF */
+ ch2 = resource->version;
+ while (*ch != PSCR && *ch != PSLF)
+ *ch2++ = *ch++;
+ *ch2 = '\0';
+
+ fclose(fd_resource);
+
+ return TRUE;
+}
+
+ static int
+prt_check_resource(resource, version)
+ struct prt_ps_resource_S *resource;
+ char_u *version;
+{
+ /* Version number m.n should match, the revision number does not matter */
+ if (STRNCMP(resource->version, version, STRLEN(version)))
+ {
+ EMSG2(_("E621: \"%s\" resource file has wrong version"),
+ resource->name);
+ return FALSE;
+ }
+
+ /* Other checks to be added as needed */
+ return TRUE;
+}
+
+ static void
+prt_dsc_start()
+{
+ prt_write_string("%!PS-Adobe-3.0\n");
+}
+
+ static void
+prt_dsc_noarg(comment)
+ char *comment;
+{
+ sprintf((char *)prt_line_buffer, "%%%%%s\n", comment);
+ prt_write_file(prt_line_buffer);
+}
+
+ static void
+prt_dsc_textline(comment, text)
+ char *comment;
+ char *text;
+{
+ sprintf((char *)prt_line_buffer, "%%%%%s: %s\n", comment, text);
+ prt_write_file(prt_line_buffer);
+}
+
+ static void
+prt_dsc_text(comment, text)
+ char *comment;
+ char *text;
+{
+ /* TODO - should scan 'text' for any chars needing escaping! */
+ sprintf((char *)prt_line_buffer, "%%%%%s: (%s)\n", comment, text);
+ prt_write_file(prt_line_buffer);
+}
+
+#define prt_dsc_atend(c) prt_dsc_text((c), "atend")
+
+ static void
+prt_dsc_ints(comment, count, ints)
+ char *comment;
+ int count;
+ int *ints;
+{
+ int i;
+
+ sprintf((char *)prt_line_buffer, "%%%%%s:", comment);
+ prt_write_file(prt_line_buffer);
+
+ for (i = 0; i < count; i++)
+ {
+ sprintf((char *)prt_line_buffer, " %d", ints[i]);
+ prt_write_file(prt_line_buffer);
+ }
+
+ prt_write_string("\n");
+}
+
+ static void
+prt_dsc_resources(comment, type, count, strings)
+ char *comment; /* if NULL add to previous */
+ char *type;
+ int count;
+ char **strings;
+{
+ int i;
+
+ if (comment != NULL)
+ sprintf((char *)prt_line_buffer, "%%%%%s: %s", comment, type);
+ else
+ sprintf((char *)prt_line_buffer, "%%%%+ %s", type);
+ prt_write_file(prt_line_buffer);
+
+ for (i = 0; i < count; i++)
+ {
+ sprintf((char *)prt_line_buffer, " %s", strings[i]);
+ prt_write_file(prt_line_buffer);
+ }
+
+ prt_write_string("\n");
+}
+
+ static void
+prt_dsc_requirements(duplex, tumble, collate, color, num_copies)
+ int duplex;
+ int tumble;
+ int collate;
+ int color;
+ int num_copies;
+{
+ /* Only output the comment if we need to.
+ * Note: tumble is ignored if we are not duplexing
+ */
+ if (!(duplex || collate || color || (num_copies > 1)))
+ return;
+
+ sprintf((char *)prt_line_buffer, "%%%%Requirements:");
+ prt_write_file(prt_line_buffer);
+
+ if (duplex)
+ {
+ prt_write_string(" duplex");
+ if (tumble)
+ prt_write_string("(tumble)");
+ }
+ if (collate)
+ prt_write_string(" collate");
+ if (color)
+ prt_write_string(" color");
+ if (num_copies > 1)
+ {
+ prt_write_string(" numcopies(");
+ /* Note: no space wanted so dont use prt_write_int() */
+ sprintf((char *)prt_line_buffer, "%d", num_copies);
+ prt_write_file(prt_line_buffer);
+ prt_write_string(")");
+ }
+ prt_write_string("\n");
+}
+
+ static void
+prt_dsc_docmedia(paper_name, width, height, weight, colour, type)
+ char *paper_name;
+ double width;
+ double height;
+ double weight;
+ char *colour;
+ char *type;
+{
+ sprintf((char *)prt_line_buffer, "%%%%DocumentMedia: %s ", paper_name);
+ prt_write_file(prt_line_buffer);
+ prt_write_real(width, 2);
+ prt_write_real(height, 2);
+ prt_write_real(weight, 2);
+ if (colour == NULL)
+ prt_write_string("()");
+ else
+ prt_write_string(colour);
+ prt_write_string(" ");
+ if (type == NULL)
+ prt_write_string("()");
+ else
+ prt_write_string(type);
+ prt_write_string("\n");
+}
+
+ void
+mch_print_cleanup()
+{
+#ifdef FEAT_MBYTE
+ if (prt_do_conv)
+ {
+ convert_setup(&prt_conv, NULL, NULL);
+ prt_do_conv = FALSE;
+ }
+#endif
+ if (prt_ps_fd != NULL)
+ {
+ fclose(prt_ps_fd);
+ prt_ps_fd = NULL;
+ prt_file_error = FALSE;
+ }
+ if (prt_ps_file_name != NULL)
+ {
+ vim_free(prt_ps_file_name);
+ prt_ps_file_name = NULL;
+ }
+}
+
+ static float
+to_device_units(idx, physsize, def_number)
+ int idx;
+ double physsize;
+ int def_number;
+{
+ float ret;
+ int u;
+ int nr;
+
+ u = prt_get_unit(idx);
+ if (u == PRT_UNIT_NONE)
+ {
+ u = PRT_UNIT_PERC;
+ nr = def_number;
+ }
+ else
+ nr = printer_opts[idx].number;
+
+ switch (u)
+ {
+ case PRT_UNIT_INCH:
+ ret = (float)(nr * PRT_PS_DEFAULT_DPI);
+ break;
+ case PRT_UNIT_MM:
+ ret = (float)(nr * PRT_PS_DEFAULT_DPI) / (float)25.4;
+ break;
+ case PRT_UNIT_POINT:
+ ret = (float)nr;
+ break;
+ case PRT_UNIT_PERC:
+ default:
+ ret = (float)(physsize * nr) / 100;
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Calculate margins for given width and height from printoptions settings.
+ */
+ static void
+prt_page_margins(width, height, left, right, top, bottom)
+ double width;
+ double height;
+ double *left;
+ double *right;
+ double *top;
+ double *bottom;
+{
+ *left = to_device_units(OPT_PRINT_LEFT, width, 10);
+ *right = width - to_device_units(OPT_PRINT_RIGHT, width, 5);
+ *top = height - to_device_units(OPT_PRINT_TOP, height, 5);
+ *bottom = to_device_units(OPT_PRINT_BOT, height, 5);
+}
+
+ static void
+prt_font_metrics(font_scale)
+ int font_scale;
+{
+ prt_line_height = (float)font_scale;
+ prt_char_width = (float)PRT_PS_FONT_TO_USER(font_scale, prt_ps_font.wx);
+}
+
+
+ static int
+prt_get_cpl()
+{
+ if (prt_use_number())
+ {
+ prt_number_width = PRINT_NUMBER_WIDTH * prt_char_width;
+ prt_left_margin += prt_number_width;
+ }
+ else
+ prt_number_width = 0.0;
+
+ return (int)((prt_right_margin - prt_left_margin) / prt_char_width);
+}
+
+/*
+ * Get number of lines of text that fit on a page (excluding the header).
+ */
+ static int
+prt_get_lpp()
+{
+ int lpp;
+
+ /*
+ * Calculate offset to lower left corner of background rect based on actual
+ * font height (based on its bounding box) and the line height, handling the
+ * case where the font height can exceed the line height.
+ */
+ prt_bgcol_offset = (float)PRT_PS_FONT_TO_USER(prt_line_height,
+ prt_ps_font.bbox_min_y);
+ if ((prt_ps_font.bbox_max_y - prt_ps_font.bbox_min_y) < 1000.0)
+ {
+ prt_bgcol_offset -= (float)PRT_PS_FONT_TO_USER(prt_line_height,
+ (1000.0 - (prt_ps_font.bbox_max_y -
+ prt_ps_font.bbox_min_y)) / 2);
+ }
+
+ /* Get height for topmost line based on background rect offset. */
+ prt_first_line_height = prt_line_height + prt_bgcol_offset;
+
+ /* Calculate lpp */
+ lpp = (int)((prt_top_margin - prt_bottom_margin) / prt_line_height);
+
+ /* Adjust top margin if there is a header */
+ prt_top_margin -= prt_line_height * prt_header_height();
+
+ return lpp - prt_header_height();
+}
+
+/*ARGSUSED*/
+ int
+mch_print_init(psettings, jobname, forceit)
+ prt_settings_T *psettings;
+ char_u *jobname;
+ int forceit;
+{
+ int i;
+ char *paper_name;
+ int paper_strlen;
+ int fontsize;
+ char_u *p;
+ double left;
+ double right;
+ double top;
+ double bottom;
+
+#if 0
+ /*
+ * TODO:
+ * If "forceit" is false: pop up a dialog to select:
+ * - printer name
+ * - copies
+ * - collated/uncollated
+ * - duplex off/long side/short side
+ * - paper size
+ * - portrait/landscape
+ * - font size
+ *
+ * If "forceit" is true: use the default printer and settings
+ */
+ if (forceit)
+ s_pd.Flags |= PD_RETURNDEFAULT;
+#endif
+
+ /*
+ * Find the size of the paper and set the margins.
+ */
+ prt_portrait = (!printer_opts[OPT_PRINT_PORTRAIT].present
+ || TOLOWER_ASC(printer_opts[OPT_PRINT_PORTRAIT].string[0]) == 'y');
+ if (printer_opts[OPT_PRINT_PAPER].present)
+ {
+ paper_name = (char *)printer_opts[OPT_PRINT_PAPER].string;
+ paper_strlen = printer_opts[OPT_PRINT_PAPER].strlen;
+ }
+ else
+ {
+ paper_name = "A4";
+ paper_strlen = 2;
+ }
+ for (i = 0; i < PRT_MEDIASIZE_LEN; ++i)
+ if (STRLEN(prt_mediasize[i].name) == (unsigned)paper_strlen
+ && STRNICMP(prt_mediasize[i].name, paper_name,
+ paper_strlen) == 0)
+ break;
+ if (i == PRT_MEDIASIZE_LEN)
+ i = 0;
+ prt_media = i;
+
+ /*
+ * Set PS pagesize based on media dimensions and print orientation.
+ * Note: Media and page sizes have defined meanings in PostScript and should
+ * be kept distinct. Media is the paper (or transparency, or ...) that is
+ * printed on, whereas the page size is the area that the PostScript
+ * interpreter renders into.
+ */
+ if (prt_portrait)
+ {
+ prt_page_width = prt_mediasize[i].width;
+ prt_page_height = prt_mediasize[i].height;
+ }
+ else
+ {
+ prt_page_width = prt_mediasize[i].height;
+ prt_page_height = prt_mediasize[i].width;
+ }
+
+ /*
+ * Set PS page margins based on the PS pagesize, not the mediasize - this
+ * needs to be done before the cpl and lpp are calculated.
+ */
+ prt_page_margins(prt_page_width, prt_page_height, &left, &right, &top,
+ &bottom);
+ prt_left_margin = (float)left;
+ prt_right_margin = (float)right;
+ prt_top_margin = (float)top;
+ prt_bottom_margin = (float)bottom;
+
+ /*
+ * Set up the font size.
+ */
+ fontsize = PRT_PS_DEFAULT_FONTSIZE;
+ for (p = p_pfn; (p = vim_strchr(p, ':')) != NULL; ++p)
+ if (p[1] == 'h' && VIM_ISDIGIT(p[2]))
+ fontsize = atoi((char *)p + 2);
+ prt_font_metrics(fontsize);
+
+ /*
+ * Return the number of characters per line, and lines per page for the
+ * generic print code.
+ */
+ psettings->chars_per_line = prt_get_cpl();
+ psettings->lines_per_page = prt_get_lpp();
+
+ /* Catch margin settings that leave no space for output! */
+ if (psettings->chars_per_line <= 0 || psettings->lines_per_page <= 0)
+ return FAIL;
+
+ /*
+ * Sort out the number of copies to be printed. PS by default will do
+ * uncollated copies for you, so once we know how many uncollated copies are
+ * wanted cache it away and lie to the generic code that we only want one
+ * uncollated copy.
+ */
+ psettings->n_collated_copies = 1;
+ psettings->n_uncollated_copies = 1;
+ prt_num_copies = 1;
+ prt_collate = (!printer_opts[OPT_PRINT_COLLATE].present
+ || TOLOWER_ASC(printer_opts[OPT_PRINT_COLLATE].string[0]) == 'y');
+ if (prt_collate)
+ {
+ /* TODO: Get number of collated copies wanted. */
+ psettings->n_collated_copies = 1;
+ }
+ else
+ {
+ /* TODO: Get number of uncollated copies wanted and update the cached
+ * count.
+ */
+ prt_num_copies = 1;
+ }
+
+ psettings->jobname = jobname;
+
+ /*
+ * Set up printer duplex and tumble based on Duplex option setting - default
+ * is long sided duplex printing (i.e. no tumble).
+ */
+ prt_duplex = TRUE;
+ prt_tumble = FALSE;
+ psettings->duplex = 1;
+ if (printer_opts[OPT_PRINT_DUPLEX].present)
+ {
+ if (STRNICMP(printer_opts[OPT_PRINT_DUPLEX].string, "off", 3) == 0)
+ {
+ prt_duplex = FALSE;
+ psettings->duplex = 0;
+ }
+ else if (STRNICMP(printer_opts[OPT_PRINT_DUPLEX].string, "short", 5)
+ == 0)
+ prt_tumble = TRUE;
+ }
+
+ /* For now user abort not supported */
+ psettings->user_abort = 0;
+
+ /* If the user didn't specify a file name, use a temp file. */
+ if (psettings->outfile == NULL)
+ {
+ prt_ps_file_name = vim_tempname('p');
+ if (prt_ps_file_name == NULL)
+ {
+ EMSG(_(e_notmp));
+ return FAIL;
+ }
+ prt_ps_fd = mch_fopen((char *)prt_ps_file_name, WRITEBIN);
+ }
+ else
+ {
+ p = expand_env_save(psettings->outfile);
+ if (p != NULL)
+ {
+ prt_ps_fd = mch_fopen((char *)p, WRITEBIN);
+ vim_free(p);
+ }
+ }
+ if (prt_ps_fd == NULL)
+ {
+ EMSG(_("E324: Can't open PostScript output file"));
+ mch_print_cleanup();
+ return FAIL;
+ }
+
+ ga_init2(&prt_ps_buffer, (int)sizeof(char), PRT_PS_DEFAULT_BUFFER_SIZE);
+
+ prt_page_num = 0;
+
+ prt_attribute_change = FALSE;
+ prt_need_moveto = FALSE;
+ prt_need_font = FALSE;
+ prt_need_fgcol = FALSE;
+ prt_need_bgcol = FALSE;
+ prt_need_underline = FALSE;
+
+ prt_file_error = FALSE;
+
+ return OK;
+}
+
+ static int
+prt_add_resource(resource)
+ struct prt_ps_resource_S *resource;
+{
+ FILE* fd_resource;
+ char_u resource_buffer[512];
+ char *resource_name[1];
+ size_t bytes_read;
+
+ fd_resource = mch_fopen((char *)resource->filename, READBIN);
+ if (fd_resource == NULL)
+ {
+ EMSG2(_("E456: Can't open file \"%s\""), resource->filename);
+ return FALSE;
+ }
+ resource_name[0] = (char *)resource->title;
+ prt_dsc_resources("BeginResource",
+ resource_types[resource->type], 1, resource_name);
+
+ prt_dsc_textline("BeginDocument", (char *)resource->filename);
+
+ for (;;)
+ {
+ bytes_read = fread((char *)resource_buffer, sizeof(char_u),
+ sizeof(resource_buffer), fd_resource);
+ if (ferror(fd_resource))
+ {
+ EMSG2(_("E457: Can't read PostScript resource file \"%s\""),
+ resource->filename);
+ fclose(fd_resource);
+ return FALSE;
+ }
+ if (bytes_read == 0)
+ break;
+ prt_write_file_raw_len(resource_buffer, bytes_read);
+ if (prt_file_error)
+ {
+ fclose(fd_resource);
+ return FALSE;
+ }
+ }
+ fclose(fd_resource);
+
+ prt_dsc_noarg("EndDocument");
+
+ prt_dsc_noarg("EndResource");
+
+ return TRUE;
+}
+
+ int
+mch_print_begin(psettings)
+ prt_settings_T *psettings;
+{
+ time_t now;
+ int bbox[4];
+ char *p_time;
+ char *resource[1];
+ double left;
+ double right;
+ double top;
+ double bottom;
+ struct prt_ps_resource_S res_prolog;
+ struct prt_ps_resource_S res_encoding;
+ char_u buffer[256];
+ char_u *p_encoding;
+#ifdef FEAT_MBYTE
+ int props;
+#endif
+
+ /*
+ * PS DSC Header comments - no PS code!
+ */
+ prt_dsc_start();
+ prt_dsc_textline("Title", (char *)psettings->jobname);
+ /* TODO - platform dependent user name retrieval */
+ prt_dsc_textline("For", "Unknown");
+ prt_dsc_textline("Creator", VIM_VERSION_LONG);
+ /* Note: to ensure Clean8bit I don't think we can use LC_TIME */
+ now = time(NULL);
+ p_time = ctime(&now);
+ /* Note: ctime() adds a \n so we have to remove it :-( */
+ *(vim_strchr((char_u *)p_time, '\n')) = '\0';
+ prt_dsc_textline("CreationDate", p_time);
+ prt_dsc_textline("DocumentData", "Clean8Bit");
+ prt_dsc_textline("Orientation", "Portrait");
+ prt_dsc_atend("Pages");
+ prt_dsc_textline("PageOrder", "Ascend");
+ /* The bbox does not change with orientation - it is always in the default
+ * user coordinate system! We have to recalculate right and bottom
+ * coordinates based on the font metrics for the bbox to be accurate. */
+ prt_page_margins(prt_mediasize[prt_media].width,
+ prt_mediasize[prt_media].height,
+ &left, &right, &top, &bottom);
+ bbox[0] = (int)left;
+ if (prt_portrait)
+ {
+ /* In portrait printing the fixed point is the top left corner so we
+ * derive the bbox from that point. We have the expected cpl chars
+ * across the media and lpp lines down the media.
+ */
+ bbox[1] = (int)(top - (psettings->lines_per_page + prt_header_height())
+ * prt_line_height);
+ bbox[2] = (int)(left + psettings->chars_per_line * prt_char_width
+ + 0.5);
+ bbox[3] = (int)(top + 0.5);
+ }
+ else
+ {
+ /* In landscape printing the fixed point is the bottom left corner so we
+ * derive the bbox from that point. We have lpp chars across the media
+ * and cpl lines up the media.
+ */
+ bbox[1] = (int)bottom;
+ bbox[2] = (int)(left + ((psettings->lines_per_page
+ + prt_header_height()) * prt_line_height) + 0.5);
+ bbox[3] = (int)(bottom + psettings->chars_per_line * prt_char_width
+ + 0.5);
+ }
+ prt_dsc_ints("BoundingBox", 4, bbox);
+ /* The media width and height does not change with landscape printing! */
+ prt_dsc_docmedia(prt_mediasize[prt_media].name,
+ prt_mediasize[prt_media].width,
+ prt_mediasize[prt_media].height,
+ (double)0, NULL, NULL);
+ prt_dsc_resources("DocumentNeededResources", "font", 4,
+ prt_ps_font.ps_fontname);
+
+ /* Search for external resources we supply */
+ if (!prt_find_resource("prolog", &res_prolog))
+ {
+ EMSG(_("E456: Can't find PostScript resource file \"prolog.ps\""));
+ return FALSE;
+ }
+ if (!prt_open_resource(&res_prolog))
+ return FALSE;
+ if (!prt_check_resource(&res_prolog, PRT_PROLOG_VERSION))
+ return FALSE;
+ /* Find an encoding to use for printing.
+ * Check 'printencoding'. If not set or not found, then use 'encoding'. If
+ * that cannot be found then default to "latin1".
+ * Note: VIM specific encoding header is always skipped.
+ */
+#ifdef FEAT_MBYTE
+ props = enc_canon_props(p_enc);
+#endif
+ p_encoding = enc_skip(p_penc);
+ if (*p_encoding == NUL
+ || !prt_find_resource((char *)p_encoding, &res_encoding))
+ {
+ /* 'printencoding' not set or not supported - find alternate */
+#ifdef FEAT_MBYTE
+ p_encoding = enc_skip(p_enc);
+ if (!(props & ENC_8BIT)
+ || !prt_find_resource((char *)p_encoding, &res_encoding))
+ {
+ /* 8-bit 'encoding' is not supported */
+#endif
+ /* Use latin1 as default printing encoding */
+ p_encoding = (char_u *)"latin1";
+ if (!prt_find_resource((char *)p_encoding, &res_encoding))
+ {
+ EMSG2(_("E456: Can't find PostScript resource file \"%s.ps\""),
+ p_encoding);
+ return FALSE;
+ }
+#ifdef FEAT_MBYTE
+ }
+#endif
+ }
+ if (!prt_open_resource(&res_encoding))
+ return FALSE;
+ /* For the moment there are no checks on encoding resource files to perform */
+#ifdef FEAT_MBYTE
+ /* Set up encoding conversion if starting from multi-byte */
+ props = enc_canon_props(p_enc);
+ if (!(props & ENC_8BIT))
+ {
+ if (FAIL == convert_setup(&prt_conv, p_enc, p_encoding))
+ {
+ EMSG2(_("E620: Unable to convert from multi-byte to \"%s\" encoding"),
+ p_encoding);
+ return FALSE;
+ }
+ prt_do_conv = TRUE;
+ }
+#endif
+
+ /* List resources supplied */
+ resource[0] = (char *)buffer;
+ STRCPY(buffer, res_prolog.title);
+ STRCAT(buffer, " ");
+ STRCAT(buffer, res_prolog.version);
+ prt_dsc_resources("DocumentSuppliedResources", "procset", 1, resource);
+ STRCPY(buffer, res_encoding.title);
+ STRCAT(buffer, " ");
+ STRCAT(buffer, res_encoding.version);
+ prt_dsc_resources(NULL, "encoding", 1, resource);
+ prt_dsc_requirements(prt_duplex, prt_tumble, prt_collate,
+#ifdef FEAT_SYN_HL
+ psettings->do_syntax
+#else
+ 0
+#endif
+ , prt_num_copies);
+ prt_dsc_noarg("EndComments");
+
+ /*
+ * PS Document page defaults
+ */
+ prt_dsc_noarg("BeginDefaults");
+
+ /* List font resources most likely common to all pages */
+ prt_dsc_resources("PageResources", "font", 4, prt_ps_font.ps_fontname);
+ /* Paper will be used for all pages */
+ prt_dsc_textline("PageMedia", prt_mediasize[prt_media].name);
+
+ prt_dsc_noarg("EndDefaults");
+
+ /*
+ * PS Document prolog inclusion - all required procsets.
+ */
+ prt_dsc_noarg("BeginProlog");
+
+ /* For now there is just the one procset to be included in the PS file. */
+ if (!prt_add_resource(&res_prolog))
+ return FALSE;
+
+ /* There will be only one font encoding to be included in the PS file. */
+ if (!prt_add_resource(&res_encoding))
+ return FALSE;
+
+ prt_dsc_noarg("EndProlog");
+
+ /*
+ * PS Document setup - must appear after the prolog
+ */
+ prt_dsc_noarg("BeginSetup");
+
+ /* Device setup - page size and number of uncollated copies */
+ prt_write_int((int)prt_mediasize[prt_media].width);
+ prt_write_int((int)prt_mediasize[prt_media].height);
+ prt_write_int(0);
+ prt_write_string("sps\n");
+ prt_write_int(prt_num_copies);
+ prt_write_string("nc\n");
+ prt_write_boolean(prt_duplex);
+ prt_write_boolean(prt_tumble);
+ prt_write_string("dt\n");
+ prt_write_boolean(prt_collate);
+ prt_write_string("c\n");
+
+ /* Font resource inclusion and definition */
+ prt_dsc_resources("IncludeResource", "font", 1,
+ &prt_ps_font.ps_fontname[PRT_PS_FONT_ROMAN]);
+ prt_def_font("F0", (char *)p_encoding, (int)prt_line_height,
+ prt_ps_font.ps_fontname[PRT_PS_FONT_ROMAN]);
+ prt_dsc_resources("IncludeResource", "font", 1,
+ &prt_ps_font.ps_fontname[PRT_PS_FONT_BOLD]);
+ prt_def_font("F1", (char *)p_encoding, (int)prt_line_height,
+ prt_ps_font.ps_fontname[PRT_PS_FONT_BOLD]);
+ prt_dsc_resources("IncludeResource", "font", 1,
+ &prt_ps_font.ps_fontname[PRT_PS_FONT_OBLIQUE]);
+ prt_def_font("F2", (char *)p_encoding, (int)prt_line_height,
+ prt_ps_font.ps_fontname[PRT_PS_FONT_OBLIQUE]);
+ prt_dsc_resources("IncludeResource", "font", 1,
+ &prt_ps_font.ps_fontname[PRT_PS_FONT_BOLDOBLIQUE]);
+ prt_def_font("F3", (char *)p_encoding, (int)prt_line_height,
+ prt_ps_font.ps_fontname[PRT_PS_FONT_BOLDOBLIQUE]);
+
+ /* Misc constant vars used for underlining and background rects */
+ prt_def_var("UO", PRT_PS_FONT_TO_USER(prt_line_height,
+ prt_ps_font.uline_offset), 2);
+ prt_def_var("UW", PRT_PS_FONT_TO_USER(prt_line_height,
+ prt_ps_font.uline_width), 2);
+ prt_def_var("BO", prt_bgcol_offset, 2);
+
+ prt_dsc_noarg("EndSetup");
+
+ /* Fail if any problems writing out to the PS file */
+ return !prt_file_error;
+}
+
+ void
+mch_print_end(psettings)
+ prt_settings_T *psettings;
+{
+ prt_dsc_noarg("Trailer");
+
+ /*
+ * Output any info we don't know in toto until we finish
+ */
+ prt_dsc_ints("Pages", 1, &prt_page_num);
+
+ prt_dsc_noarg("EOF");
+
+ if (!prt_file_error && psettings->outfile == NULL
+ && !got_int && !psettings->user_abort)
+ {
+ /* Close the file first. */
+ if (prt_ps_fd != NULL)
+ {
+ fclose(prt_ps_fd);
+ prt_ps_fd = NULL;
+ }
+ prt_message((char_u *)_("Sending to printer..."));
+
+ /* Not printing to a file: use 'printexpr' to print the file. */
+ if (eval_printexpr(prt_ps_file_name, psettings->arguments) == FAIL)
+ EMSG(_("E365: Failed to print PostScript file"));
+ else
+ prt_message((char_u *)_("Print job sent."));
+ }
+
+ mch_print_cleanup();
+}
+
+ int
+mch_print_end_page()
+{
+ prt_flush_buffer();
+
+ prt_write_string("re sp\n");
+
+ prt_dsc_noarg("PageTrailer");
+
+ return !prt_file_error;
+}
+
+/*ARGSUSED*/
+ int
+mch_print_begin_page(str)
+ char_u *str;
+{
+ int page_num[2];
+
+ prt_page_num++;
+
+ page_num[0] = page_num[1] = prt_page_num;
+ prt_dsc_ints("Page", 2, page_num);
+
+ prt_dsc_noarg("BeginPageSetup");
+
+ prt_write_string("sv\n0 g\nF0 sf\n");
+ prt_fgcol = PRCOLOR_BLACK;
+ prt_bgcol = PRCOLOR_WHITE;
+ prt_font = PRT_PS_FONT_ROMAN;
+
+ /* Set up page transformation for landscape printing. */
+ if (!prt_portrait)
+ {
+ prt_write_int(-((int)prt_mediasize[prt_media].width));
+ prt_write_string("sl\n");
+ }
+
+ prt_dsc_noarg("EndPageSetup");
+
+ /* We have reset the font attributes, force setting them again. */
+ curr_bg = (long_u)0xffffffff;
+ curr_fg = (long_u)0xffffffff;
+ curr_bold = MAYBE;
+
+ return !prt_file_error;
+}
+
+ int
+mch_print_blank_page()
+{
+ return (mch_print_begin_page(NULL) ? (mch_print_end_page()) : FALSE);
+}
+
+static float prt_pos_x = 0;
+static float prt_pos_y = 0;
+
+ void
+mch_print_start_line(margin, page_line)
+ int margin;
+ int page_line;
+{
+ prt_pos_x = prt_left_margin;
+ if (margin)
+ prt_pos_x -= prt_number_width;
+
+ prt_pos_y = prt_top_margin - prt_first_line_height -
+ page_line * prt_line_height;
+
+ prt_attribute_change = TRUE;
+ prt_need_moveto = TRUE;
+}
+
+/*ARGSUSED*/
+ int
+mch_print_text_out(p, len)
+ char_u *p;
+ int len;
+{
+ int need_break;
+ char_u ch;
+ char_u ch_buff[8];
+
+ /* Output any required changes to the graphics state, after flushing any
+ * text buffered so far.
+ */
+ if (prt_attribute_change)
+ {
+ prt_flush_buffer();
+ /* Reset count of number of chars that will be printed */
+ prt_text_count = 0;
+
+ if (prt_need_moveto)
+ {
+ prt_pos_x_moveto = prt_pos_x;
+ prt_pos_y_moveto = prt_pos_y;
+ prt_do_moveto = TRUE;
+
+ prt_need_moveto = FALSE;
+ }
+ if (prt_need_font)
+ {
+ prt_write_string("F");
+ prt_write_int(prt_font);
+ prt_write_string("sf\n");
+ prt_need_font = FALSE;
+ }
+ if (prt_need_fgcol)
+ {
+ int r, g, b;
+ r = ((unsigned)prt_fgcol & 0xff0000) >> 16;
+ g = ((unsigned)prt_fgcol & 0xff00) >> 8;
+ b = prt_fgcol & 0xff;
+
+ prt_write_real(r / 255.0, 3);
+ if (r == g && g == b)
+ {
+ prt_write_string("g\n");
+ }
+ else
+ {
+ prt_write_real(g / 255.0, 3);
+ prt_write_real(b / 255.0, 3);
+ prt_write_string("r\n");
+ }
+ prt_need_fgcol = FALSE;
+ }
+
+ if (prt_bgcol != PRCOLOR_WHITE)
+ {
+ prt_new_bgcol = prt_bgcol;
+ if (prt_need_bgcol)
+ prt_do_bgcol = TRUE;
+ }
+ else
+ prt_do_bgcol = FALSE;
+ prt_need_bgcol = FALSE;
+
+ if (prt_need_underline)
+ prt_do_underline = prt_underline;
+ prt_need_underline = FALSE;
+
+ prt_attribute_change = FALSE;
+ }
+
+#ifdef FEAT_MBYTE
+ if (prt_do_conv)
+ {
+ /* Convert from multi-byte to 8-bit encoding */
+ p = string_convert(&prt_conv, p, &len);
+ if (p == NULL)
+ p = (char_u *)"";
+ }
+#endif
+ /* Add next character to buffer of characters to output.
+ * Note: One printed character may require several PS characters to
+ * represent it, but we only count them as one printed character.
+ */
+ ch = *p;
+ if (ch < 32 || ch == '(' || ch == ')' || ch == '\\')
+ {
+ /* Convert non-printing characters to either their escape or octal
+ * sequence, ensures PS sent over a serial line does not interfere with
+ * the comms protocol.
+ * Note: For EBCDIC we need to write out the escape sequences as ASCII
+ * codes!
+ * Note 2: Char codes < 32 are identical in EBCDIC and ASCII AFAIK!
+ */
+ ga_append(&prt_ps_buffer, IF_EB('\\', 0134));
+ switch (ch)
+ {
+ case BS: ga_append(&prt_ps_buffer, IF_EB('b', 0142)); break;
+ case TAB: ga_append(&prt_ps_buffer, IF_EB('t', 0164)); break;
+ case NL: ga_append(&prt_ps_buffer, IF_EB('n', 0156)); break;
+ case FF: ga_append(&prt_ps_buffer, IF_EB('f', 0146)); break;
+ case CAR: ga_append(&prt_ps_buffer, IF_EB('r', 0162)); break;
+ case '(': ga_append(&prt_ps_buffer, IF_EB('(', 0050)); break;
+ case ')': ga_append(&prt_ps_buffer, IF_EB(')', 0051)); break;
+ case '\\': ga_append(&prt_ps_buffer, IF_EB('\\', 0134)); break;
+
+ default:
+ sprintf((char *)ch_buff, "%03o", (unsigned int)ch);
+#ifdef EBCDIC
+ ebcdic2ascii(ch_buff, 3);
+#endif
+ ga_append(&prt_ps_buffer, ch_buff[0]);
+ ga_append(&prt_ps_buffer, ch_buff[1]);
+ ga_append(&prt_ps_buffer, ch_buff[2]);
+ break;
+ }
+ }
+ else
+ ga_append(&prt_ps_buffer, ch);
+
+#ifdef FEAT_MBYTE
+ /* Need to free any translated characters */
+ if (prt_do_conv && (*p != NUL))
+ vim_free(p);
+#endif
+
+ prt_text_count++;
+ prt_pos_x += prt_char_width;
+
+ /* The downside of fp - need a little tolerance in the right margin check */
+ need_break = (prt_pos_x + prt_char_width > (prt_right_margin + 0.01));
+
+ if (need_break)
+ prt_flush_buffer();
+
+ return need_break;
+}
+
+ void
+mch_print_set_font(iBold, iItalic, iUnderline)
+ int iBold;
+ int iItalic;
+ int iUnderline;
+{
+ int font = 0;
+
+ if (iBold)
+ font |= 0x01;
+ if (iItalic)
+ font |= 0x02;
+
+ if (font != prt_font)
+ {
+ prt_font = font;
+ prt_attribute_change = TRUE;
+ prt_need_font = TRUE;
+ }
+ if (prt_underline != iUnderline)
+ {
+ prt_underline = iUnderline;
+ prt_attribute_change = TRUE;
+ prt_need_underline = TRUE;
+ }
+}
+
+ void
+mch_print_set_bg(bgcol)
+ long_u bgcol;
+{
+ prt_bgcol = bgcol;
+ prt_attribute_change = TRUE;
+ prt_need_bgcol = TRUE;
+}
+
+ void
+mch_print_set_fg(fgcol)
+ long_u fgcol;
+{
+ if (fgcol != (long_u)prt_fgcol)
+ {
+ prt_fgcol = fgcol;
+ prt_attribute_change = TRUE;
+ prt_need_fgcol = TRUE;
+ }
+}
+
+# endif /*FEAT_POSTSCRIPT*/
+#endif /*FEAT_PRINTER*/
+
+#if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
+ && (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG))
+static char *get_locale_val __ARGS((int what));
+
+ static char *
+get_locale_val(what)
+ int what;
+{
+ char *loc;
+
+ /* Obtain the locale value from the libraries. For DJGPP this is
+ * redefined and it doesn't use the arguments. */
+ loc = setlocale(what, NULL);
+
+# if defined(__BORLANDC__)
+ if (loc != NULL)
+ {
+ char_u *p;
+
+ /* Borland returns something like "LC_CTYPE=<name>\n"
+ * Let's try to fix that bug here... */
+ p = vim_strchr(loc, '=');
+ if (p != NULL)
+ {
+ loc = ++p;
+ while (*p != NUL) /* remove trailing newline */
+ {
+ if (*p < ' ')
+ {
+ *p = NUL;
+ break;
+ }
+ ++p;
+ }
+ }
+ }
+# endif
+
+ return loc;
+}
+#endif
+
+
+#ifdef WIN32
+/*
+ * On MS-Windows locale names are strings like "German_Germany.1252", but
+ * gettext expects "de". Try to translate one into another here for a few
+ * supported languages.
+ */
+ static char_u *
+gettext_lang(char_u *name)
+{
+ int i;
+ static char *(mtable[]) = {
+ "afrikaans", "af",
+ "czech", "cs",
+ "dutch", "nl",
+ "german", "de",
+ "english_united kingdom", "en_GB",
+ "spanish", "es",
+ "french", "fr",
+ "italian", "it",
+ "japanese", "ja",
+ "korean", "ko",
+ "norwegian", "no",
+ "polish", "pl",
+ "russian", "ru",
+ "slovak", "sk",
+ "swedish", "sv",
+ "ukrainian", "uk",
+ "chinese_china", "zh_CN",
+ "chinese_taiwan", "zh_TW",
+ NULL};
+
+ for (i = 0; mtable[i] != NULL; i += 2)
+ if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0)
+ return mtable[i + 1];
+ return name;
+}
+#endif
+
+#if defined(FEAT_MULTI_LANG) || defined(PROTO)
+/*
+ * Obtain the current messages language. Used to set the default for
+ * 'helplang'. May return NULL or an empty string.
+ */
+ char_u *
+get_mess_lang()
+{
+ char_u *p;
+
+# if (defined(HAVE_LOCALE_H) || defined(X_LOCALE))
+# if defined(LC_MESSAGES)
+ p = (char_u *)get_locale_val(LC_MESSAGES);
+# else
+ /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
+ * may be set to the LCID number. */
+ p = (char_u *)get_locale_val(LC_ALL);
+# endif
+# else
+ p = mch_getenv((char_u *)"LC_ALL");
+ if (p == NULL || *p == NUL)
+ {
+ p = mch_getenv((char_u *)"LC_MESSAGES");
+ if (p == NULL || *p == NUL)
+ p = mch_getenv((char_u *)"LANG");
+ }
+# endif
+# ifdef WIN32
+ p = gettext_lang(p);
+# endif
+ return p;
+}
+#endif
+
+#if !defined(LC_MESSAGES) \
+ && (((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
+ && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))) \
+ || defined(FEAT_EVAL))
+static char_u *get_mess_env __ARGS((void));
+
+/*
+ * Get the language used for messages from the environment.
+ */
+ static char_u *
+get_mess_env()
+{
+ char_u *p;
+
+ p = mch_getenv((char_u *)"LC_ALL");
+ if (p == NULL || *p == NUL)
+ {
+ p = mch_getenv((char_u *)"LC_MESSAGES");
+ if (p == NULL || *p == NUL)
+ {
+ p = mch_getenv((char_u *)"LANG");
+ if (p != NULL && VIM_ISDIGIT(*p))
+ p = NULL; /* ignore something like "1043" */
+# if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+ if (p == NULL || *p == NUL)
+ p = (char_u *)get_locale_val(LC_CTYPE);
+# endif
+ }
+ }
+ return p;
+}
+#endif
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+
+/*
+ * Set the "v:lang" variable according to the current locale setting.
+ * Also do "v:lc_time"and "v:ctype".
+ */
+ void
+set_lang_var()
+{
+ char_u *loc;
+
+# if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+ loc = (char_u *)get_locale_val(LC_CTYPE);
+# else
+ /* setlocale() not supported: use the default value */
+ loc = (char_u *)"C";
+# endif
+ set_vim_var_string(VV_CTYPE, loc, -1);
+
+ /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
+ * back to LC_CTYPE if it's empty. */
+# if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) && defined(LC_MESSAGES)
+ loc = (char_u *)get_locale_val(LC_MESSAGES);
+# else
+ loc = get_mess_env();
+# endif
+ set_vim_var_string(VV_LANG, loc, -1);
+
+# if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+ loc = (char_u *)get_locale_val(LC_TIME);
+# endif
+ set_vim_var_string(VV_LC_TIME, loc, -1);
+}
+#endif
+
+#if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
+ && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
+/*
+ * ":language": Set the language (locale).
+ */
+ void
+ex_language(eap)
+ exarg_T *eap;
+{
+ char *loc;
+ char_u *p;
+ char_u *name;
+ int what = LC_ALL;
+ char *whatstr = "";
+#ifdef LC_MESSAGES
+# define VIM_LC_MESSAGES LC_MESSAGES
+#else
+# define VIM_LC_MESSAGES 6789
+#endif
+
+ name = eap->arg;
+
+ /* Check for "messages {name}", "ctype {name}" or "time {name}" argument.
+ * Allow abbreviation, but require at least 3 characters to avoid
+ * confusion with a two letter language name "me" or "ct". */
+ p = skiptowhite(eap->arg);
+ if ((*p == NUL || vim_iswhite(*p)) && p - eap->arg >= 3)
+ {
+ if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0)
+ {
+ what = VIM_LC_MESSAGES;
+ name = skipwhite(p);
+ whatstr = "messages ";
+ }
+ else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0)
+ {
+ what = LC_CTYPE;
+ name = skipwhite(p);
+ whatstr = "ctype ";
+ }
+ else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0)
+ {
+ what = LC_TIME;
+ name = skipwhite(p);
+ whatstr = "time ";
+ }
+ }
+
+ if (*name == NUL)
+ {
+#ifndef LC_MESSAGES
+ if (what == VIM_LC_MESSAGES)
+ p = get_mess_env();
+ else
+#endif
+ p = (char_u *)setlocale(what, NULL);
+ if (p == NULL || *p == NUL)
+ p = (char_u *)"Unknown";
+ smsg((char_u *)_("Current %slanguage: \"%s\""), whatstr, p);
+ }
+ else
+ {
+#ifndef LC_MESSAGES
+ if (what == VIM_LC_MESSAGES)
+ loc = "";
+ else
+#endif
+ loc = setlocale(what, (char *)name);
+ if (loc == NULL)
+ EMSG2(_("E197: Cannot set language to \"%s\""), name);
+ else
+ {
+#ifdef HAVE_NL_MSG_CAT_CNTR
+ /* Need to do this for GNU gettext, otherwise cached translations
+ * will be used again. */
+ extern int _nl_msg_cat_cntr;
+
+ ++_nl_msg_cat_cntr;
+#endif
+ /* Reset $LC_ALL, otherwise it would overrule everyting. */
+ vim_setenv((char_u *)"LC_ALL", (char_u *)"");
+
+ if (what != LC_TIME)
+ {
+ /* Tell gettext() what to translate to. It apparently doesn't
+ * use the currently effective locale. Also do this when
+ * FEAT_GETTEXT isn't defined, so that shell commands use this
+ * value. */
+ if (what == LC_ALL)
+ vim_setenv((char_u *)"LANG", name);
+ if (what != LC_CTYPE)
+ {
+ char_u *mname;
+#ifdef WIN32
+ mname = gettext_lang(name);
+#else
+ mname = name;
+#endif
+ vim_setenv((char_u *)"LC_MESSAGES", mname);
+#ifdef FEAT_MULTI_LANG
+ set_helplang_default(mname);
+#endif
+ }
+
+ /* Set $LC_CTYPE, because it overrules $LANG, and
+ * gtk_set_locale() calls setlocale() again. gnome_init()
+ * sets $LC_CTYPE to "en_US" (that's a bug!). */
+ if (what != VIM_LC_MESSAGES)
+ vim_setenv((char_u *)"LC_CTYPE", name);
+# ifdef FEAT_GUI_GTK
+ /* Let GTK know what locale we're using. Not sure this is
+ * really needed... */
+ if (gui.in_use)
+ (void)gtk_set_locale();
+# endif
+ }
+
+# ifdef FEAT_EVAL
+ /* Set v:lang, v:lc_time and v:ctype to the final result. */
+ set_lang_var();
+# endif
+ }
+ }
+}
+
+# if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+/*
+ * Function given to ExpandGeneric() to obtain the possible arguments of the
+ * ":language" command.
+ */
+/*ARGSUSED*/
+ char_u *
+get_lang_arg(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ if (idx == 0)
+ return (char_u *)"messages";
+ if (idx == 1)
+ return (char_u *)"ctype";
+ if (idx == 2)
+ return (char_u *)"time";
+ return NULL;
+}
+# endif
+
+#endif
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
new file mode 100644
index 000000000..f1331e918
--- /dev/null
+++ b/src/ex_docmd.c
@@ -0,0 +1,9711 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * ex_docmd.c: functions for executing an Ex command line.
+ */
+
+#include "vim.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h> /* for chdir() */
+#endif
+
+static int quitmore = 0;
+static int ex_pressedreturn = FALSE;
+#ifndef FEAT_PRINTER
+# define ex_hardcopy ex_ni
+#endif
+
+#ifdef FEAT_USR_CMDS
+typedef struct ucmd
+{
+ char_u *uc_name; /* The command name */
+ long_u uc_argt; /* The argument type */
+ char_u *uc_rep; /* The command's replacement string */
+ long uc_def; /* The default value for a range/count */
+ scid_T uc_scriptID; /* SID where the command was defined */
+ int uc_compl; /* completion type */
+# if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
+ char_u *uc_compl_arg; /* completion argument if any */
+# endif
+} ucmd_T;
+
+#define UC_BUFFER 1 /* -buffer: local to current buffer */
+
+garray_T ucmds = {0, 0, sizeof(ucmd_T), 4, NULL};
+
+#define USER_CMD(i) (&((ucmd_T *)(ucmds.ga_data))[i])
+#define USER_CMD_GA(gap, i) (&((ucmd_T *)((gap)->ga_data))[i])
+
+static void do_ucmd __ARGS((exarg_T *eap));
+static void ex_command __ARGS((exarg_T *eap));
+static void ex_comclear __ARGS((exarg_T *eap));
+static void ex_delcommand __ARGS((exarg_T *eap));
+# ifdef FEAT_CMDL_COMPL
+static char_u *get_user_command_name __ARGS((int idx));
+# endif
+
+#else
+# define ex_command ex_ni
+# define ex_comclear ex_ni
+# define ex_delcommand ex_ni
+#endif
+
+#ifdef FEAT_EVAL
+static char_u *do_one_cmd __ARGS((char_u **, int, struct condstack *, char_u *(*getline)(int, void *, int), void *cookie));
+#else
+static char_u *do_one_cmd __ARGS((char_u **, int, char_u *(*getline)(int, void *, int), void *cookie));
+static int if_level = 0; /* depth in :if */
+#endif
+static int checkforcmd __ARGS((char_u **pp, char *cmd, int len));
+static char_u *find_command __ARGS((exarg_T *eap, int *full));
+
+static void ex_abbreviate __ARGS((exarg_T *eap));
+static void ex_map __ARGS((exarg_T *eap));
+static void ex_unmap __ARGS((exarg_T *eap));
+static void ex_mapclear __ARGS((exarg_T *eap));
+static void ex_abclear __ARGS((exarg_T *eap));
+#ifndef FEAT_MENU
+# define ex_emenu ex_ni
+# define ex_menu ex_ni
+# define ex_menutranslate ex_ni
+#endif
+#ifdef FEAT_AUTOCMD
+static void ex_autocmd __ARGS((exarg_T *eap));
+static void ex_doautocmd __ARGS((exarg_T *eap));
+#else
+# define ex_autocmd ex_ni
+# define ex_doautocmd ex_ni
+# define ex_doautoall ex_ni
+#endif
+#ifdef FEAT_LISTCMDS
+static void ex_bunload __ARGS((exarg_T *eap));
+static void ex_buffer __ARGS((exarg_T *eap));
+static void ex_bmodified __ARGS((exarg_T *eap));
+static void ex_bnext __ARGS((exarg_T *eap));
+static void ex_bprevious __ARGS((exarg_T *eap));
+static void ex_brewind __ARGS((exarg_T *eap));
+static void ex_blast __ARGS((exarg_T *eap));
+#else
+# define ex_bunload ex_ni
+# define ex_buffer ex_ni
+# define ex_bmodified ex_ni
+# define ex_bnext ex_ni
+# define ex_bprevious ex_ni
+# define ex_brewind ex_ni
+# define ex_blast ex_ni
+# define buflist_list ex_ni
+# define ex_checktime ex_ni
+#endif
+#if !defined(FEAT_LISTCMDS) || !defined(FEAT_WINDOWS)
+# define ex_buffer_all ex_ni
+#endif
+static char_u *getargcmd __ARGS((char_u **));
+static char_u *skip_cmd_arg __ARGS((char_u *p, int rembs));
+static int getargopt __ARGS((exarg_T *eap));
+#ifndef FEAT_QUICKFIX
+# define ex_make ex_ni
+# define ex_cc ex_ni
+# define ex_cnext ex_ni
+# define ex_cfile ex_ni
+# define qf_list ex_ni
+# define qf_age ex_ni
+# define ex_helpgrep ex_ni
+#endif
+#if !defined(FEAT_QUICKFIX) || !defined(FEAT_WINDOWS)
+# define ex_cclose ex_ni
+# define ex_copen ex_ni
+# define ex_cwindow ex_ni
+#endif
+
+static int check_more __ARGS((int, int));
+static linenr_T get_address __ARGS((char_u **, int skip, int to_other_file));
+#if !defined(FEAT_PERL) || !defined(FEAT_PYTHON) || !defined(FEAT_TCL) \
+ || !defined(FEAT_RUBY)
+static void ex_script_ni __ARGS((exarg_T *eap));
+#endif
+static char_u *invalid_range __ARGS((exarg_T *eap));
+static void correct_range __ARGS((exarg_T *eap));
+static char_u *repl_cmdline __ARGS((exarg_T *eap, char_u *src, int srclen, char_u *repl, char_u **cmdlinep));
+static void ex_highlight __ARGS((exarg_T *eap));
+static void ex_colorscheme __ARGS((exarg_T *eap));
+static void ex_quit __ARGS((exarg_T *eap));
+static void ex_cquit __ARGS((exarg_T *eap));
+static void ex_quit_all __ARGS((exarg_T *eap));
+#ifdef FEAT_WINDOWS
+static void ex_close __ARGS((exarg_T *eap));
+static void ex_win_close __ARGS((exarg_T *eap, win_T *win));
+static void ex_only __ARGS((exarg_T *eap));
+static void ex_all __ARGS((exarg_T *eap));
+static void ex_resize __ARGS((exarg_T *eap));
+static void ex_stag __ARGS((exarg_T *eap));
+#else
+# define ex_close ex_ni
+# define ex_only ex_ni
+# define ex_all ex_ni
+# define ex_resize ex_ni
+# define ex_splitview ex_ni
+# define ex_stag ex_ni
+#endif
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+static void ex_pclose __ARGS((exarg_T *eap));
+static void ex_ptag __ARGS((exarg_T *eap));
+static void ex_pedit __ARGS((exarg_T *eap));
+#else
+# define ex_pclose ex_ni
+# define ex_ptag ex_ni
+# define ex_pedit ex_ni
+#endif
+static void ex_hide __ARGS((exarg_T *eap));
+static void ex_stop __ARGS((exarg_T *eap));
+static void ex_exit __ARGS((exarg_T *eap));
+static void ex_print __ARGS((exarg_T *eap));
+#ifdef FEAT_BYTEOFF
+static void ex_goto __ARGS((exarg_T *eap));
+#else
+# define ex_goto ex_ni
+#endif
+static void ex_shell __ARGS((exarg_T *eap));
+static void ex_preserve __ARGS((exarg_T *eap));
+static void ex_recover __ARGS((exarg_T *eap));
+#ifndef FEAT_LISTCMDS
+# define ex_argedit ex_ni
+# define ex_argadd ex_ni
+# define ex_argdelete ex_ni
+# define ex_listdo ex_ni
+#endif
+static void ex_mode __ARGS((exarg_T *eap));
+static void ex_wrongmodifier __ARGS((exarg_T *eap));
+static void ex_find __ARGS((exarg_T *eap));
+static void ex_edit __ARGS((exarg_T *eap));
+#if !defined(FEAT_GUI) && !defined(FEAT_CLIENTSERVER)
+# define ex_drop ex_ni
+#endif
+#ifndef FEAT_GUI
+# define ex_gui ex_nogui
+static void ex_nogui __ARGS((exarg_T *eap));
+#endif
+#if defined(FEAT_GUI_W32) && defined(FEAT_MENU) && defined(FEAT_TEAROFF)
+static void ex_tearoff __ARGS((exarg_T *eap));
+#else
+# define ex_tearoff ex_ni
+#endif
+#if (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK)) && defined(FEAT_MENU)
+static void ex_popup __ARGS((exarg_T *eap));
+#else
+# define ex_popup ex_ni
+#endif
+#ifndef FEAT_GUI_MSWIN
+# define ex_simalt ex_ni
+#endif
+#if !defined(FEAT_GUI_MSWIN) && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MOTIF)
+# define gui_mch_find_dialog ex_ni
+# define gui_mch_replace_dialog ex_ni
+#endif
+#ifndef FEAT_GUI_GTK
+# define ex_helpfind ex_ni
+#endif
+#ifndef FEAT_CSCOPE
+# define do_cscope ex_ni
+# define do_scscope ex_ni
+# define do_cstag ex_ni
+#endif
+#ifndef FEAT_SYN_HL
+# define ex_syntax ex_ni
+#endif
+#ifndef FEAT_PERL
+# define ex_perl ex_script_ni
+# define ex_perldo ex_ni
+#endif
+#ifndef FEAT_PYTHON
+# define ex_python ex_script_ni
+# define ex_pyfile ex_ni
+#endif
+#ifndef FEAT_TCL
+# define ex_tcl ex_script_ni
+# define ex_tcldo ex_ni
+# define ex_tclfile ex_ni
+#endif
+#ifndef FEAT_RUBY
+# define ex_ruby ex_script_ni
+# define ex_rubydo ex_ni
+# define ex_rubyfile ex_ni
+#endif
+#ifndef FEAT_SNIFF
+# define ex_sniff ex_ni
+#endif
+#ifndef FEAT_KEYMAP
+# define ex_loadkeymap ex_ni
+#endif
+static void ex_swapname __ARGS((exarg_T *eap));
+static void ex_syncbind __ARGS((exarg_T *eap));
+static void ex_read __ARGS((exarg_T *eap));
+static void ex_cd __ARGS((exarg_T *eap));
+static void ex_pwd __ARGS((exarg_T *eap));
+static void ex_equal __ARGS((exarg_T *eap));
+static void ex_sleep __ARGS((exarg_T *eap));
+static void do_exmap __ARGS((exarg_T *eap, int isabbrev));
+static void ex_winsize __ARGS((exarg_T *eap));
+#ifdef FEAT_WINDOWS
+static void ex_wincmd __ARGS((exarg_T *eap));
+#else
+# define ex_wincmd ex_ni
+#endif
+#if defined(FEAT_GUI) || defined(UNIX) || defined(VMS)
+static void ex_winpos __ARGS((exarg_T *eap));
+#else
+# define ex_winpos ex_ni
+#endif
+static void ex_operators __ARGS((exarg_T *eap));
+static void ex_put __ARGS((exarg_T *eap));
+static void ex_copymove __ARGS((exarg_T *eap));
+static void ex_submagic __ARGS((exarg_T *eap));
+static void ex_join __ARGS((exarg_T *eap));
+static void ex_at __ARGS((exarg_T *eap));
+static void ex_bang __ARGS((exarg_T *eap));
+static void ex_undo __ARGS((exarg_T *eap));
+static void ex_redo __ARGS((exarg_T *eap));
+static void ex_redir __ARGS((exarg_T *eap));
+static void ex_redraw __ARGS((exarg_T *eap));
+static void ex_redrawstatus __ARGS((exarg_T *eap));
+static void close_redir __ARGS((void));
+static void ex_mkrc __ARGS((exarg_T *eap));
+static void ex_mark __ARGS((exarg_T *eap));
+#ifdef FEAT_USR_CMDS
+static char_u *uc_fun_cmd __ARGS((void));
+#endif
+#ifdef FEAT_EX_EXTRA
+static void ex_normal __ARGS((exarg_T *eap));
+static void ex_startinsert __ARGS((exarg_T *eap));
+static void ex_stopinsert __ARGS((exarg_T *eap));
+#else
+# define ex_normal ex_ni
+# define ex_align ex_ni
+# define ex_retab ex_ni
+# define ex_startinsert ex_ni
+# define ex_stopinsert ex_ni
+# define ex_helptags ex_ni
+#endif
+#ifdef FEAT_FIND_ID
+static void ex_checkpath __ARGS((exarg_T *eap));
+static void ex_findpat __ARGS((exarg_T *eap));
+#else
+# define ex_findpat ex_ni
+# define ex_checkpath ex_ni
+#endif
+#if defined(FEAT_FIND_ID) && defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+static void ex_psearch __ARGS((exarg_T *eap));
+#else
+# define ex_psearch ex_ni
+#endif
+static void ex_tag __ARGS((exarg_T *eap));
+static void ex_tag_cmd __ARGS((exarg_T *eap, char_u *name));
+#ifndef FEAT_EVAL
+# define ex_scriptnames ex_ni
+# define ex_finish ex_ni
+# define ex_echo ex_ni
+# define ex_echohl ex_ni
+# define ex_execute ex_ni
+# define ex_call ex_ni
+# define ex_if ex_ni
+# define ex_endif ex_ni
+# define ex_else ex_ni
+# define ex_while ex_ni
+# define ex_continue ex_ni
+# define ex_break ex_ni
+# define ex_endwhile ex_ni
+# define ex_throw ex_ni
+# define ex_try ex_ni
+# define ex_catch ex_ni
+# define ex_finally ex_ni
+# define ex_endtry ex_ni
+# define ex_endfunction ex_ni
+# define ex_let ex_ni
+# define ex_unlet ex_ni
+# define ex_function ex_ni
+# define ex_delfunction ex_ni
+# define ex_return ex_ni
+#endif
+static char_u *arg_all __ARGS((void));
+#ifdef FEAT_SESSION
+static int makeopens __ARGS((FILE *fd, char_u *dirnow));
+static int put_view __ARGS((FILE *fd, win_T *wp, int add_edit, unsigned *flagp));
+static void ex_loadview __ARGS((exarg_T *eap));
+static char_u *get_view_file __ARGS((int c));
+#else
+# define ex_loadview ex_ni
+#endif
+#ifndef FEAT_EVAL
+# define ex_compiler ex_ni
+#endif
+#ifdef FEAT_VIMINFO
+static void ex_viminfo __ARGS((exarg_T *eap));
+#else
+# define ex_viminfo ex_ni
+#endif
+static void ex_behave __ARGS((exarg_T *eap));
+#ifdef FEAT_AUTOCMD
+static void ex_filetype __ARGS((exarg_T *eap));
+static void ex_setfiletype __ARGS((exarg_T *eap));
+#else
+# define ex_filetype ex_ni
+# define ex_setfiletype ex_ni
+#endif
+#ifndef FEAT_DIFF
+# define ex_diffpatch ex_ni
+# define ex_diffgetput ex_ni
+# define ex_diffsplit ex_ni
+# define ex_diffthis ex_ni
+# define ex_diffupdate ex_ni
+#endif
+static void ex_digraphs __ARGS((exarg_T *eap));
+static void ex_set __ARGS((exarg_T *eap));
+#if !defined(FEAT_EVAL) || !defined(FEAT_AUTOCMD)
+# define ex_options ex_ni
+#endif
+#ifdef FEAT_SEARCH_EXTRA
+static void ex_nohlsearch __ARGS((exarg_T *eap));
+static void ex_match __ARGS((exarg_T *eap));
+#else
+# define ex_nohlsearch ex_ni
+# define ex_match ex_ni
+#endif
+#ifdef FEAT_CRYPT
+static void ex_X __ARGS((exarg_T *eap));
+#else
+# define ex_X ex_ni
+#endif
+#ifdef FEAT_FOLDING
+static void ex_fold __ARGS((exarg_T *eap));
+static void ex_foldopen __ARGS((exarg_T *eap));
+static void ex_folddo __ARGS((exarg_T *eap));
+#else
+# define ex_fold ex_ni
+# define ex_foldopen ex_ni
+# define ex_folddo ex_ni
+#endif
+#if !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
+ && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)))
+# define ex_language ex_ni
+#endif
+#ifndef FEAT_SIGNS
+# define ex_sign ex_ni
+#endif
+#ifndef FEAT_SUN_WORKSHOP
+# define ex_wsverb ex_ni
+#endif
+
+#ifndef FEAT_EVAL
+# define ex_debug ex_ni
+# define ex_breakadd ex_ni
+# define ex_debuggreedy ex_ni
+# define ex_breakdel ex_ni
+# define ex_breaklist ex_ni
+#endif
+
+#ifndef FEAT_CMDHIST
+# define ex_history ex_ni
+#endif
+#ifndef FEAT_JUMPLIST
+# define ex_jumps ex_ni
+# define ex_changes ex_ni
+#endif
+
+/*
+ * Declare cmdnames[].
+ */
+#define DO_DECLARE_EXCMD
+#include "ex_cmds.h"
+
+/*
+ * Table used to quickly search for a command, based on its first character.
+ */
+cmdidx_T cmdidxs[27] =
+{
+ CMD_append,
+ CMD_buffer,
+ CMD_change,
+ CMD_delete,
+ CMD_edit,
+ CMD_file,
+ CMD_global,
+ CMD_help,
+ CMD_insert,
+ CMD_join,
+ CMD_k,
+ CMD_list,
+ CMD_move,
+ CMD_next,
+ CMD_open,
+ CMD_print,
+ CMD_quit,
+ CMD_read,
+ CMD_substitute,
+ CMD_t,
+ CMD_undo,
+ CMD_vglobal,
+ CMD_write,
+ CMD_xit,
+ CMD_yank,
+ CMD_z,
+ CMD_bang
+};
+
+static char_u dollar_command[2] = {'$', 0};
+
+
+#ifdef FEAT_EVAL
+/* Struct for storing a line inside a while loop */
+typedef struct
+{
+ char_u *line; /* command line */
+ linenr_T lnum; /* sourcing_lnum of the line */
+} wcmd_T;
+
+/*
+ * Structure used to store info for line position in a while loop.
+ * This is required, because do_one_cmd() may invoke ex_function(), which
+ * reads more lines that may come from the while loop.
+ */
+struct while_cookie
+{
+ garray_T *lines_gap; /* growarray with line info */
+ int current_line; /* last read line from growarray */
+ int repeating; /* TRUE when looping a second time */
+ /* When "repeating" is FALSE use "getline" and "cookie" to get lines */
+ char_u *(*getline) __ARGS((int, void *, int));
+ void *cookie;
+};
+
+static char_u *get_while_line __ARGS((int c, void *cookie, int indent));
+static int store_while_line __ARGS((garray_T *gap, char_u *line));
+static void free_cmdlines __ARGS((garray_T *gap));
+#endif
+
+
+/*
+ * do_exmode(): Repeatedly get commands for the "Ex" mode, until the ":vi"
+ * command is given.
+ */
+ void
+do_exmode(improved)
+ int improved; /* TRUE for "improved Ex" mode */
+{
+ int save_msg_scroll;
+ int prev_msg_row;
+ linenr_T prev_line;
+
+ save_msg_scroll = msg_scroll;
+ ++RedrawingDisabled; /* don't redisplay the window */
+ ++no_wait_return; /* don't wait for return */
+ if (improved)
+ exmode_active = EXMODE_VIM;
+ else
+ {
+ settmode(TMODE_COOK);
+ exmode_active = EXMODE_NORMAL;
+ }
+
+ State = NORMAL;
+#ifdef FEAT_GUI
+ /* Ignore scrollbar and mouse events in Ex mode */
+ ++hold_gui_events;
+#endif
+#ifdef FEAT_SNIFF
+ want_sniff_request = 0; /* No K_SNIFF wanted */
+#endif
+
+ MSG(_("Entering Ex mode. Type \"visual\" to go to Normal mode."));
+ while (exmode_active)
+ {
+ msg_scroll = TRUE;
+ need_wait_return = FALSE;
+ ex_pressedreturn = FALSE;
+ ex_no_reprint = FALSE;
+ prev_msg_row = msg_row;
+ prev_line = curwin->w_cursor.lnum;
+#ifdef FEAT_SNIFF
+ ProcessSniffRequests();
+#endif
+ if (improved)
+ {
+ cmdline_row = msg_row;
+ do_cmdline(NULL, getexline, NULL, 0);
+ }
+ else
+ do_cmdline(NULL, getexmodeline, NULL, DOCMD_NOWAIT);
+ lines_left = Rows - 1;
+
+ if (prev_line != curwin->w_cursor.lnum && !ex_no_reprint)
+ {
+ if (ex_pressedreturn)
+ {
+ /* go up one line, to overwrite the ":<CR>" line, so the
+ * output doensn't contain empty lines. */
+ msg_row = prev_msg_row;
+ if (prev_msg_row == Rows - 1)
+ msg_row--;
+ }
+ msg_col = 0;
+ print_line_no_prefix(curwin->w_cursor.lnum, FALSE);
+ msg_clr_eos();
+ }
+ else if (ex_pressedreturn) /* must be at EOF */
+ EMSG(_("E501: At end-of-file"));
+ }
+
+#ifdef FEAT_GUI
+ --hold_gui_events;
+#endif
+ if (!improved)
+ settmode(TMODE_RAW);
+ --RedrawingDisabled;
+ --no_wait_return;
+ update_screen(CLEAR);
+ need_wait_return = FALSE;
+ msg_scroll = save_msg_scroll;
+}
+
+/*
+ * Execute a simple command line. Used for translated commands like "*".
+ */
+ int
+do_cmdline_cmd(cmd)
+ char_u *cmd;
+{
+ return do_cmdline(cmd, NULL, NULL,
+ DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
+}
+
+/*
+ * do_cmdline(): execute one Ex command line
+ *
+ * 1. Execute "cmdline" when it is not NULL.
+ * If "cmdline" is NULL, or more lines are needed, getline() is used.
+ * 2. Split up in parts separated with '|'.
+ *
+ * This function can be called recursively!
+ *
+ * flags:
+ * DOCMD_VERBOSE - The command will be included in the error message.
+ * DOCMD_NOWAIT - Don't call wait_return() and friends.
+ * DOCMD_REPEAT - Repeat execution until getline() returns NULL.
+ * DOCMD_KEYTYPED - Don't reset KeyTyped.
+ * DOCMD_EXCRESET - Reset the exception environment (used for debugging).
+ * DOCMD_KEEPLINE - Store first typed line (for repeating with ".").
+ *
+ * return FAIL if cmdline could not be executed, OK otherwise
+ */
+ int
+do_cmdline(cmdline, getline, cookie, flags)
+ char_u *cmdline;
+ char_u *(*getline) __ARGS((int, void *, int));
+ void *cookie; /* argument for getline() */
+ int flags;
+{
+ char_u *next_cmdline; /* next cmd to execute */
+ char_u *cmdline_copy = NULL; /* copy of cmd line */
+ int used_getline = FALSE; /* used "getline" to obtain command */
+ static int recursive = 0; /* recursive depth */
+ int msg_didout_before_start = 0;
+ int count = 0; /* line number count */
+ int did_inc = FALSE; /* incremented RedrawingDisabled */
+ int retval = OK;
+#ifdef FEAT_EVAL
+ struct condstack cstack; /* conditional stack */
+ garray_T lines_ga; /* keep lines for ":while" */
+ int current_line = 0; /* active line in lines_ga */
+ char_u *fname = NULL; /* function or script name */
+ linenr_T *breakpoint = NULL; /* ptr to breakpoint field in cookie */
+ int *dbg_tick = NULL; /* ptr to dbg_tick field in cookie */
+ int saved_trylevel = 0;
+ int saved_force_abort = 0;
+ except_T *saved_caught_stack = NULL;
+ char_u *saved_vv_exception = NULL;
+ char_u *saved_vv_throwpoint = NULL;
+ int saved_did_emsg = 0;
+ int saved_got_int = 0;
+ int saved_did_throw = 0;
+ int saved_need_rethrow = 0;
+ int saved_check_cstack = 0;
+ except_T *saved_current_exception = NULL;
+ int initial_trylevel;
+ struct msglist **saved_msg_list = NULL;
+ struct msglist *private_msg_list;
+
+ /* "getline" and "cookie" passed to do_one_cmd() */
+ char_u *(*cmd_getline) __ARGS((int, void *, int));
+ void *cmd_cookie;
+ struct while_cookie cmd_while_cookie;
+ void *real_cookie;
+#else
+# define cmd_getline getline
+# define cmd_cookie cookie
+#endif
+ static int call_depth = 0; /* recursiveness */
+
+#ifdef FEAT_EVAL
+ /* For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory
+ * location for storing error messages to be converted to an exception.
+ * This ensures that the do_errthrow() call in do_one_cmd() does not combine
+ * the messages stored by an earlier invocation of do_one_cmd() with the
+ * command name of the later one. This would happen when BufWritePost
+ * autocommands are executed after a write error. */
+ saved_msg_list = msg_list;
+ msg_list = &private_msg_list;
+ private_msg_list = NULL;
+#endif
+
+ /* It's possible to create an endless loop with ":execute", catch that
+ * here. The value of 200 allows nested function calls, ":source", etc. */
+ if (call_depth == 200)
+ {
+ EMSG(_("E169: Command too recursive"));
+#ifdef FEAT_EVAL
+ /* When converting to an exception, we do not include the command name
+ * since this is not an error of the specific command. */
+ do_errthrow((struct condstack *)NULL, (char_u *)NULL);
+ msg_list = saved_msg_list;
+#endif
+ return FAIL;
+ }
+ ++call_depth;
+
+#ifdef FEAT_EVAL
+ cstack.cs_idx = -1;
+ cstack.cs_whilelevel = 0;
+ cstack.cs_trylevel = 0;
+ cstack.cs_emsg_silent_list = NULL;
+ cstack.cs_had_while = FALSE;
+ cstack.cs_had_endwhile = FALSE;
+ cstack.cs_had_continue = FALSE;
+ cstack.cs_had_finally = FALSE;
+ ga_init2(&lines_ga, (int)sizeof(wcmd_T), 10);
+
+ real_cookie = getline_cookie(getline, cookie);
+
+ /* Inside a function use a higher nesting level. */
+ if (getline_equal(getline, cookie, get_func_line)
+ && ex_nesting_level == func_level(real_cookie))
+ ++ex_nesting_level;
+
+ /* Get the function or script name and the address where the next breakpoint
+ * line and the debug tick for a function or script are stored. */
+ if (getline_equal(getline, cookie, get_func_line))
+ {
+ fname = func_name(real_cookie);
+ breakpoint = func_breakpoint(real_cookie);
+ dbg_tick = func_dbg_tick(real_cookie);
+ }
+ else if (getline_equal(getline, cookie, getsourceline))
+ {
+ fname = sourcing_name;
+ breakpoint = source_breakpoint(real_cookie);
+ dbg_tick = source_dbg_tick(real_cookie);
+ }
+
+ /*
+ * Initialize "force_abort" and "suppress_errthrow" at the top level.
+ */
+ if (!recursive)
+ {
+ force_abort = FALSE;
+ suppress_errthrow = FALSE;
+ }
+
+ /*
+ * If requested, store and reset the global values controlling the
+ * exception handling (used when debugging).
+ */
+ else if (flags & DOCMD_EXCRESET)
+ {
+ saved_trylevel = trylevel; trylevel = 0;
+ saved_force_abort = force_abort; force_abort = FALSE;
+ saved_caught_stack = caught_stack; caught_stack = NULL;
+ saved_vv_exception = v_exception(NULL);
+ saved_vv_throwpoint = v_throwpoint(NULL);
+ /* Necessary for debugging an inactive ":catch", ":finally", or
+ * ":endtry": */
+ saved_did_emsg = did_emsg, did_emsg = FALSE;
+ saved_got_int = got_int, got_int = FALSE;
+ saved_did_throw = did_throw, did_throw = FALSE;
+ saved_need_rethrow = need_rethrow, need_rethrow = FALSE;
+ saved_check_cstack = check_cstack, check_cstack = FALSE;
+ saved_current_exception = current_exception; current_exception=NULL;
+ }
+
+ initial_trylevel = trylevel;
+
+ /*
+ * "did_throw" will be set to TRUE when an exception is being thrown.
+ */
+ did_throw = FALSE;
+#endif
+ /*
+ * "did_emsg" will be set to TRUE when emsg() is used, in which case we
+ * cancel the whole command line, and any if/endif while/endwhile loop.
+ * If force_abort is set, we cancel everything.
+ */
+ did_emsg = FALSE;
+
+ /*
+ * KeyTyped is only set when calling vgetc(). Reset it here when not
+ * calling vgetc() (sourced command lines).
+ */
+ if (!(flags & DOCMD_KEYTYPED) && !getline_equal(getline, cookie, getexline))
+ KeyTyped = FALSE;
+
+ /*
+ * Continue executing command lines:
+ * - when inside an ":if" or ":while"
+ * - for multiple commands on one line, separated with '|'
+ * - when repeating until there are no more lines (for ":source")
+ */
+ next_cmdline = cmdline;
+ do
+ {
+ /* stop skipping cmds for an error msg after all endifs and endwhiles */
+ if (next_cmdline == NULL
+#ifdef FEAT_EVAL
+ && !force_abort
+ && cstack.cs_idx < 0
+ && !(getline_equal(getline, cookie, get_func_line)
+ && func_has_abort(real_cookie))
+#endif
+ )
+ did_emsg = FALSE;
+
+ /*
+ * 1. If repeating a line with ":while", get a line from lines_ga.
+ * 2. If no line given: Get an allocated line with getline().
+ * 3. If a line is given: Make a copy, so we can mess with it.
+ */
+
+#ifdef FEAT_EVAL
+ /* 1. If repeating, get a previous line from lines_ga. */
+ if (cstack.cs_whilelevel && current_line < lines_ga.ga_len)
+ {
+ /* Each '|' separated command is stored separately in lines_ga, to
+ * be able to jump to it. Don't use next_cmdline now. */
+ vim_free(cmdline_copy);
+ cmdline_copy = NULL;
+
+ /* Check if a function has returned or, unless it has an unclosed
+ * try conditional, aborted. */
+ if (getline_equal(getline, cookie, get_func_line)
+ && func_has_ended(real_cookie))
+ {
+ retval = FAIL;
+ break;
+ }
+
+ /* Check if a sourced file hit a ":finish" command. */
+ if (source_finished(getline, cookie))
+ {
+ retval = FAIL;
+ break;
+ }
+
+ /* If breakpoints have been added/deleted need to check for it. */
+ if (breakpoint != NULL && dbg_tick != NULL
+ && *dbg_tick != debug_tick)
+ {
+ *breakpoint = dbg_find_breakpoint(
+ getline_equal(getline, cookie, getsourceline),
+ fname, sourcing_lnum);
+ *dbg_tick = debug_tick;
+ }
+
+ next_cmdline = ((wcmd_T *)(lines_ga.ga_data))[current_line].line;
+ sourcing_lnum = ((wcmd_T *)(lines_ga.ga_data))[current_line].lnum;
+
+ /* Did we encounter a breakpoint? */
+ if (breakpoint != NULL && *breakpoint != 0
+ && *breakpoint <= sourcing_lnum)
+ {
+ dbg_breakpoint(fname, sourcing_lnum);
+ /* Find next breakpoint. */
+ *breakpoint = dbg_find_breakpoint(
+ getline_equal(getline, cookie, getsourceline),
+ fname, sourcing_lnum);
+ *dbg_tick = debug_tick;
+ }
+ }
+
+ if (cstack.cs_whilelevel)
+ {
+ /* Inside a while loop we need to store the lines and use them
+ * again. Pass a different "getline" function to do_one_cmd()
+ * below, so that it stores lines in or reads them from
+ * "lines_ga". Makes it possible to define a function inside a
+ * while loop. */
+ cmd_getline = get_while_line;
+ cmd_cookie = (void *)&cmd_while_cookie;
+ cmd_while_cookie.lines_gap = &lines_ga;
+ cmd_while_cookie.current_line = current_line;
+ cmd_while_cookie.getline = getline;
+ cmd_while_cookie.cookie = cookie;
+ cmd_while_cookie.repeating = (current_line < lines_ga.ga_len);
+ }
+ else
+ {
+ cmd_getline = getline;
+ cmd_cookie = cookie;
+ }
+#endif
+
+ /* 2. If no line given, get an allocated line with getline(). */
+ if (next_cmdline == NULL)
+ {
+ /*
+ * Need to set msg_didout for the first line after an ":if",
+ * otherwise the ":if" will be overwritten.
+ */
+ if (count == 1 && getline_equal(getline, cookie, getexline))
+ msg_didout = TRUE;
+ if (getline == NULL || (next_cmdline = getline(':', cookie,
+#ifdef FEAT_EVAL
+ cstack.cs_idx < 0 ? 0 : (cstack.cs_idx + 1) * 2
+#else
+ 0
+#endif
+ )) == NULL)
+ {
+ /* Don't call wait_return for aborted command line. The NULL
+ * returned for the end of a sourced file or executed function
+ * doesn't do this. */
+ if (KeyTyped && !(flags & DOCMD_REPEAT))
+ need_wait_return = FALSE;
+ retval = FAIL;
+ break;
+ }
+ used_getline = TRUE;
+
+ /*
+ * Keep the first typed line. Clear it when more lines are typed.
+ */
+ if (flags & DOCMD_KEEPLINE)
+ {
+ vim_free(repeat_cmdline);
+ if (count == 0)
+ repeat_cmdline = vim_strsave(next_cmdline);
+ else
+ repeat_cmdline = NULL;
+ }
+ }
+
+ /* 3. Make a copy of the command so we can mess with it. */
+ else if (cmdline_copy == NULL)
+ {
+ next_cmdline = vim_strsave(next_cmdline);
+ if (next_cmdline == NULL)
+ {
+ EMSG(_(e_outofmem));
+ retval = FAIL;
+ break;
+ }
+ }
+ cmdline_copy = next_cmdline;
+
+#ifdef FEAT_EVAL
+ /*
+ * Save the current line when inside a ":while", and when the command
+ * looks like a ":while", because we may need it later.
+ * When there is a '|' and another command, it is stored separately,
+ * because we need to be able to jump back to it from an :endwhile.
+ */
+ if ( current_line == lines_ga.ga_len
+ && (cstack.cs_whilelevel || has_while_cmd(next_cmdline)))
+ {
+ if (store_while_line(&lines_ga, next_cmdline) == FAIL)
+ {
+ retval = FAIL;
+ break;
+ }
+ }
+ did_endif = FALSE;
+#endif
+
+ if (count++ == 0)
+ {
+ /*
+ * All output from the commands is put below each other, without
+ * waiting for a return. Don't do this when executing commands
+ * from a script or when being called recursive (e.g. for ":e
+ * +command file").
+ */
+ if (!(flags & DOCMD_NOWAIT) && !recursive)
+ {
+ msg_didout_before_start = msg_didout;
+ msg_didany = FALSE; /* no output yet */
+ msg_start();
+ msg_scroll = TRUE; /* put messages below each other */
+ ++no_wait_return; /* dont wait for return until finished */
+ ++RedrawingDisabled;
+ did_inc = TRUE;
+ }
+ }
+
+ if (p_verbose >= 15 && sourcing_name != NULL)
+ {
+ int c = -1;
+
+ ++no_wait_return;
+ msg_scroll = TRUE; /* always scroll up, don't overwrite */
+ /* Truncate long lines, smsg() can't handle that. */
+ if (STRLEN(cmdline_copy) > 200)
+ {
+ c = cmdline_copy[200];
+ cmdline_copy[200] = NUL;
+ }
+ smsg((char_u *)_("line %ld: %s"),
+ (long)sourcing_lnum, cmdline_copy);
+ msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ if (c >= 0)
+ cmdline_copy[200] = c;
+ cmdline_row = msg_row;
+ --no_wait_return;
+ }
+
+ /*
+ * 2. Execute one '|' separated command.
+ * do_one_cmd() will return NULL if there is no trailing '|'.
+ * "cmdline_copy" can change, e.g. for '%' and '#' expansion.
+ */
+ ++recursive;
+ next_cmdline = do_one_cmd(&cmdline_copy, flags & DOCMD_VERBOSE,
+#ifdef FEAT_EVAL
+ &cstack,
+#endif
+ cmd_getline, cmd_cookie);
+ --recursive;
+
+#ifdef FEAT_EVAL
+ if (cmd_cookie == (void *)&cmd_while_cookie)
+ /* Use "current_line" from "cmd_while_cookie", it may have been
+ * incremented when defining a function. */
+ current_line = cmd_while_cookie.current_line;
+#endif
+
+ if (next_cmdline == NULL)
+ {
+ vim_free(cmdline_copy);
+ cmdline_copy = NULL;
+#ifdef FEAT_CMDHIST
+ /*
+ * If the command was typed, remember it for the ':' register.
+ * Do this AFTER executing the command to make :@: work.
+ */
+ if (getline_equal(getline, cookie, getexline)
+ && new_last_cmdline != NULL)
+ {
+ vim_free(last_cmdline);
+ last_cmdline = new_last_cmdline;
+ new_last_cmdline = NULL;
+ }
+#endif
+ }
+ else
+ {
+ /* need to copy the command after the '|' to cmdline_copy, for the
+ * next do_one_cmd() */
+ mch_memmove(cmdline_copy, next_cmdline, STRLEN(next_cmdline) + 1);
+ next_cmdline = cmdline_copy;
+ }
+
+
+#ifdef FEAT_EVAL
+ /* reset did_emsg for a function that is not aborted by an error */
+ if (did_emsg && !force_abort
+ && getline_equal(getline, cookie, get_func_line)
+ && !func_has_abort(real_cookie))
+ did_emsg = FALSE;
+
+ if (cstack.cs_whilelevel)
+ {
+ ++current_line;
+
+ /*
+ * An ":endwhile" and ":continue" is handled here.
+ * If we were executing commands, jump back to the ":while".
+ * If we were not executing commands, decrement whilelevel.
+ */
+ if (cstack.cs_had_endwhile || cstack.cs_had_continue)
+ {
+ if (cstack.cs_had_endwhile)
+ cstack.cs_had_endwhile = FALSE;
+ else
+ cstack.cs_had_continue = FALSE;
+
+ /* Jump back to the matching ":while". Be careful not to use
+ * a cs_line[] from an entry that isn't a ":while": It would
+ * make "current_line" invalid and can cause a crash. */
+ if (!did_emsg && !got_int && !did_throw
+ && cstack.cs_idx >= 0
+ && (cstack.cs_flags[cstack.cs_idx] & CSF_WHILE)
+ && cstack.cs_line[cstack.cs_idx] >= 0
+ && (cstack.cs_flags[cstack.cs_idx] & CSF_ACTIVE))
+ {
+ current_line = cstack.cs_line[cstack.cs_idx];
+ cstack.cs_had_while = TRUE; /* note we jumped there */
+ line_breakcheck(); /* check if CTRL-C typed */
+
+ /* Check for the next breakpoint at or after the ":while".*/
+ if (breakpoint != NULL)
+ {
+ *breakpoint = dbg_find_breakpoint(
+ getline_equal(getline, cookie, getsourceline),
+ fname,
+ ((wcmd_T *)lines_ga.ga_data)[current_line].lnum-1);
+ *dbg_tick = debug_tick;
+ }
+ }
+ else /* can only get here with ":endwhile" */
+ {
+ --cstack.cs_whilelevel;
+ if (cstack.cs_idx >= 0)
+ --cstack.cs_idx;
+ }
+ }
+
+ /*
+ * For a ":while" we need to remember the line number.
+ */
+ else if (cstack.cs_had_while)
+ {
+ cstack.cs_had_while = FALSE;
+ cstack.cs_line[cstack.cs_idx] = current_line - 1;
+ }
+ }
+
+ /*
+ * When not inside any ":while" loop, clear remembered lines.
+ */
+ if (!cstack.cs_whilelevel)
+ {
+ if (lines_ga.ga_len > 0)
+ {
+ sourcing_lnum =
+ ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum;
+ free_cmdlines(&lines_ga);
+ }
+ current_line = 0;
+ }
+
+ /*
+ * A ":finally" makes did_emsg, got_int, and did_throw pending for being
+ * restored at the ":endtry". Reset them here and set the ACTIVE and
+ * FINALLY flags, so that the finally clause gets executed. This
+ * includes the case where a missing ":endif" or ":endwhile" was
+ * detected by the ":finally" itself.
+ */
+ if (cstack.cs_had_finally)
+ {
+ cstack.cs_had_finally = FALSE;
+ report_make_pending(cstack.cs_pending[cstack.cs_idx] &
+ (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW),
+ did_throw ? (void *)current_exception : NULL);
+ did_emsg = got_int = did_throw = FALSE;
+ cstack.cs_flags[cstack.cs_idx] |= CSF_ACTIVE | CSF_FINALLY;
+ }
+
+ /* Update global "trylevel" for recursive calls to do_cmdline() from
+ * within this loop. */
+ trylevel = initial_trylevel + cstack.cs_trylevel;
+
+ /*
+ * If the outermost try conditional (accross function calls and sourced
+ * files) is aborted because of an error, an interrupt, or an uncaught
+ * exception, cancel everything. If it is left normally, reset
+ * force_abort to get the non-EH compatible abortion behavior for
+ * the rest of the script.
+ */
+ if (trylevel == 0 && !did_emsg && !got_int && !did_throw)
+ force_abort = FALSE;
+
+ /* Convert an interrupt to an exception if appropriate. */
+ (void)do_intthrow(&cstack);
+#endif /* FEAT_EVAL */
+
+ }
+ /*
+ * Continue executing command lines when:
+ * - no CTRL-C typed, no aborting error, no exception thrown or try
+ * conditionals need to be checked for executing finally clauses or
+ * catching an interrupt exception
+ * - didn't get an error message or lines are not typed
+ * - there is a command after '|', inside a :if, :while, or :try, or
+ * looping for ":source" command or function call.
+ */
+ while (!((got_int
+#ifdef FEAT_EVAL
+ || (did_emsg && force_abort) || did_throw
+#endif
+ )
+#ifdef FEAT_EVAL
+ && cstack.cs_trylevel == 0
+#endif
+ )
+ && !(did_emsg && used_getline
+ && (getline_equal(getline, cookie, getexmodeline)
+ || getline_equal(getline, cookie, getexline)))
+ && (next_cmdline != NULL
+#ifdef FEAT_EVAL
+ || cstack.cs_idx >= 0
+#endif
+ || (flags & DOCMD_REPEAT)));
+
+ vim_free(cmdline_copy);
+#ifdef FEAT_EVAL
+ free_cmdlines(&lines_ga);
+ ga_clear(&lines_ga);
+
+ if (cstack.cs_idx >= 0)
+ {
+ /*
+ * If a sourced file or executed function ran to its end, report the
+ * unclosed conditional.
+ */
+ if (!got_int && !did_throw
+ && ((getline_equal(getline, cookie, getsourceline)
+ && !source_finished(getline, cookie))
+ || (getline_equal(getline, cookie, get_func_line)
+ && !func_has_ended(real_cookie))))
+ {
+ if (cstack.cs_flags[cstack.cs_idx] & CSF_TRY)
+ EMSG(_(e_endtry));
+ else if (cstack.cs_flags[cstack.cs_idx] & CSF_WHILE)
+ EMSG(_(e_endwhile));
+ else
+ EMSG(_(e_endif));
+ }
+
+ /*
+ * Reset "trylevel" in case of a ":finish" or ":return" or a missing
+ * ":endtry" in a sourced file or executed function. If the try
+ * conditional is in its finally clause, ignore anything pending.
+ * If it is in a catch clause, finish the caught exception.
+ */
+ do
+ cstack.cs_idx = cleanup_conditionals(&cstack, 0, TRUE);
+ while (--cstack.cs_idx >= 0);
+ trylevel = initial_trylevel;
+ }
+
+ /* If a missing ":endtry", ":endwhile", or ":endif" or a memory lack
+ * was reported above and the error message is to be converted to an
+ * exception, do this now after rewinding the cstack. */
+ do_errthrow(&cstack, getline_equal(getline, cookie, get_func_line)
+ ? (char_u *)"endfunction" : (char_u *)NULL);
+
+ if (trylevel == 0)
+ {
+ /*
+ * When an exception is being thrown out of the outermost try
+ * conditional, discard the uncaught exception, disable the conversion
+ * of interrupts or errors to exceptions, and ensure that no more
+ * commands are executed.
+ */
+ if (did_throw)
+ {
+ void *p = NULL;
+ char_u *saved_sourcing_name;
+ int saved_sourcing_lnum;
+ struct msglist *messages = NULL, *next;
+
+ /*
+ * If the uncaught exception is a user exception, report it as an
+ * error. If it is an error exception, display the saved error
+ * message now. For an interrupt exception, do nothing; the
+ * interrupt message is given elsewhere.
+ */
+ switch (current_exception->type)
+ {
+ case ET_USER:
+ sprintf((char *)IObuff, _("E605: Exception not caught: %s"),
+ current_exception->value);
+ p = vim_strsave(IObuff);
+ break;
+ case ET_ERROR:
+ messages = current_exception->messages;
+ current_exception->messages = NULL;
+ break;
+ case ET_INTERRUPT:
+ break;
+ default:
+ p = vim_strsave((char_u *)_(e_internal));
+ }
+
+ saved_sourcing_name = sourcing_name;
+ saved_sourcing_lnum = sourcing_lnum;
+ sourcing_name = current_exception->throw_name;
+ sourcing_lnum = current_exception->throw_lnum;
+ current_exception->throw_name = NULL;
+
+ discard_current_exception(); /* uses IObuff if 'verbose' */
+ suppress_errthrow = TRUE;
+ force_abort = TRUE;
+
+ if (messages != NULL)
+ {
+ do
+ {
+ next = messages->next;
+ emsg(messages->msg);
+ vim_free(messages->msg);
+ vim_free(messages);
+ messages = next;
+ }
+ while (messages != NULL);
+ }
+ else if (p != NULL)
+ {
+ emsg(p);
+ vim_free(p);
+ }
+ vim_free(sourcing_name);
+ sourcing_name = saved_sourcing_name;
+ sourcing_lnum = saved_sourcing_lnum;
+ }
+
+ /*
+ * On an interrupt or an aborting error not converted to an exception,
+ * disable the conversion of errors to exceptions. (Interrupts are not
+ * converted any more, here.) This enables also the interrupt message
+ * when force_abort is set and did_emsg unset in case of an interrupt
+ * from a finally clause after an error.
+ */
+ else if (got_int || (did_emsg && force_abort))
+ suppress_errthrow = TRUE;
+ }
+
+ /*
+ * The current cstack will be freed when do_cmdline() returns. An uncaught
+ * exception will have to be rethrown in the previous cstack. If a function
+ * has just returned or a script file was just finished and the previous
+ * cstack belongs to the same function or, respectively, script file, it
+ * will have to be checked for finally clauses to be executed due to the
+ * ":return" or ":finish". This is done in do_one_cmd().
+ */
+ if (did_throw)
+ need_rethrow = TRUE;
+ if ((getline_equal(getline, cookie, getsourceline)
+ && ex_nesting_level > source_level(real_cookie))
+ || (getline_equal(getline, cookie, get_func_line)
+ && ex_nesting_level > func_level(real_cookie) + 1))
+ {
+ if (!did_throw)
+ check_cstack = TRUE;
+ }
+ else
+ {
+ /* When leaving a function, reduce nesting level. */
+ if (getline_equal(getline, cookie, get_func_line))
+ --ex_nesting_level;
+ /*
+ * Go to debug mode when returning from a function in which we are
+ * single-stepping.
+ */
+ if ((getline_equal(getline, cookie, getsourceline)
+ || getline_equal(getline, cookie, get_func_line))
+ && ex_nesting_level + 1 <= debug_break_level)
+ do_debug(getline_equal(getline, cookie, getsourceline)
+ ? (char_u *)_("End of sourced file")
+ : (char_u *)_("End of function"));
+ }
+
+ /*
+ * Restore the exception environment (done after returning from the
+ * debugger).
+ */
+ if (flags & DOCMD_EXCRESET)
+ {
+ suppress_errthrow = FALSE;
+ trylevel = saved_trylevel;
+ force_abort = saved_force_abort;
+ caught_stack = saved_caught_stack;
+ (void)v_exception(saved_vv_exception);
+ (void)v_throwpoint(saved_vv_throwpoint);
+ /* Necessary for debugging an inactive ":catch", ":finally", or
+ * ":endtry": */
+ did_emsg = saved_did_emsg;
+ got_int = saved_got_int;
+ did_throw = saved_did_throw;
+ need_rethrow = saved_need_rethrow;
+ check_cstack = saved_check_cstack;
+ current_exception = saved_current_exception;
+ }
+
+ msg_list = saved_msg_list;
+#endif /* FEAT_EVAL */
+
+ /*
+ * If there was too much output to fit on the command line, ask the user to
+ * hit return before redrawing the screen. With the ":global" command we do
+ * this only once after the command is finished.
+ */
+ if (did_inc)
+ {
+ --RedrawingDisabled;
+ --no_wait_return;
+ msg_scroll = FALSE;
+
+ /*
+ * When just finished an ":if"-":else" which was typed, no need to
+ * wait for hit-return. Also for an error situation.
+ */
+ if (retval == FAIL
+#ifdef FEAT_EVAL
+ || (did_endif && KeyTyped && !did_emsg)
+#endif
+ )
+ {
+ need_wait_return = FALSE;
+ msg_didany = FALSE; /* don't wait when restarting edit */
+ }
+ else if (need_wait_return)
+ {
+ /*
+ * The msg_start() above clears msg_didout. The wait_return we do
+ * here should not overwrite the command that may be shown before
+ * doing that.
+ */
+ msg_didout |= msg_didout_before_start;
+ wait_return(FALSE);
+ }
+ }
+
+#ifndef FEAT_EVAL
+ /*
+ * Reset if_level, in case a sourced script file contains more ":if" than
+ * ":endif" (could be ":if x | foo | endif").
+ */
+ if_level = 0;
+#endif
+
+ --call_depth;
+ return retval;
+}
+
+#ifdef FEAT_EVAL
+/*
+ * Obtain a line when inside a ":while" loop.
+ */
+ static char_u *
+get_while_line(c, cookie, indent)
+ int c;
+ void *cookie;
+ int indent;
+{
+ struct while_cookie *cp = (struct while_cookie *)cookie;
+ wcmd_T *wp;
+ char_u *line;
+
+ if (cp->current_line + 1 >= cp->lines_gap->ga_len)
+ {
+ if (cp->repeating)
+ return NULL; /* trying to read past the ":endwhile" */
+
+ /* First time inside the ":while": get line normally. */
+ if (cp->getline == NULL)
+ line = getcmdline(c, 0L, indent);
+ else
+ line = cp->getline(c, cp->cookie, indent);
+ if (store_while_line(cp->lines_gap, line) == OK)
+ ++cp->current_line;
+
+ return line;
+ }
+
+ KeyTyped = FALSE;
+ ++cp->current_line;
+ wp = (wcmd_T *)(cp->lines_gap->ga_data) + cp->current_line;
+ sourcing_lnum = wp->lnum;
+ return vim_strsave(wp->line);
+}
+
+/*
+ * Store a line in "gap" so that a ":while" loop can execute it again.
+ */
+ static int
+store_while_line(gap, line)
+ garray_T *gap;
+ char_u *line;
+{
+ if (ga_grow(gap, 1) == FAIL)
+ return FAIL;
+ ((wcmd_T *)(gap->ga_data))[gap->ga_len].line = vim_strsave(line);
+ ((wcmd_T *)(gap->ga_data))[gap->ga_len].lnum = sourcing_lnum;
+ ++gap->ga_len;
+ --gap->ga_room;
+ return OK;
+}
+
+/*
+ * Free the lines stored for a ":while" loop.
+ */
+ static void
+free_cmdlines(gap)
+ garray_T *gap;
+{
+ while (gap->ga_len > 0)
+ {
+ vim_free(((wcmd_T *)(gap->ga_data))[gap->ga_len - 1].line);
+ --gap->ga_len;
+ ++gap->ga_room;
+ }
+}
+#endif
+
+/*
+ * If "getline" is get_while_line(), return TRUE if the getline it uses equals
+ * "func". * Otherwise return TRUE when "getline" equals "func".
+ */
+/*ARGSUSED*/
+ int
+getline_equal(getline, cookie, func)
+ char_u *(*getline) __ARGS((int, void *, int));
+ void *cookie; /* argument for getline() */
+ char_u *(*func) __ARGS((int, void *, int));
+{
+#ifdef FEAT_EVAL
+ char_u *(*gp) __ARGS((int, void *, int));
+ struct while_cookie *cp;
+
+ /* When "getline" is "get_while_line()" use the "cookie" to find the
+ * function that's orignally used to obtain the lines. This may be nested
+ * several levels. */
+ gp = getline;
+ cp = (struct while_cookie *)cookie;
+ while (gp == get_while_line)
+ {
+ gp = cp->getline;
+ cp = cp->cookie;
+ }
+ return gp == func;
+#else
+ return getline == func;
+#endif
+}
+
+#if defined(FEAT_EVAL) || defined(FEAT_MBYTE) || defined(PROTO)
+/*
+ * If "getline" is get_while_line(), return the cookie used by the original
+ * getline function. Otherwise return "cookie".
+ */
+/*ARGSUSED*/
+ void *
+getline_cookie(getline, cookie)
+ char_u *(*getline) __ARGS((int, void *, int));
+ void *cookie; /* argument for getline() */
+{
+# ifdef FEAT_EVAL
+ char_u *(*gp) __ARGS((int, void *, int));
+ struct while_cookie *cp;
+
+ /* When "getline" is "get_while_line()" use the "cookie" to find the
+ * cookie that's orignally used to obtain the lines. This may be nested
+ * several levels. */
+ gp = getline;
+ cp = (struct while_cookie *)cookie;
+ while (gp == get_while_line)
+ {
+ gp = cp->getline;
+ cp = cp->cookie;
+ }
+ return cp;
+# else
+ return cookie;
+# endif
+}
+#endif
+
+/*
+ * Execute one Ex command.
+ *
+ * If 'sourcing' is TRUE, the command will be included in the error message.
+ *
+ * 1. skip comment lines and leading space
+ * 2. handle command modifiers
+ * 3. parse range
+ * 4. parse command
+ * 5. parse arguments
+ * 6. switch on command name
+ *
+ * Note: "getline" can be NULL.
+ *
+ * This function may be called recursively!
+ */
+#if (_MSC_VER == 1200)
+/*
+ * Optimisation bug in VC++ version 6.0
+ * TODO: check this is still present after each service pack
+ */
+# pragma optimize( "g", off )
+#endif
+ static char_u *
+do_one_cmd(cmdlinep, sourcing,
+#ifdef FEAT_EVAL
+ cstack,
+#endif
+ getline, cookie)
+ char_u **cmdlinep;
+ int sourcing;
+#ifdef FEAT_EVAL
+ struct condstack *cstack;
+#endif
+ char_u *(*getline) __ARGS((int, void *, int));
+ void *cookie; /* argument for getline() */
+{
+ char_u *p;
+ linenr_T lnum;
+ long n;
+ char_u *errormsg = NULL; /* error message */
+ exarg_T ea; /* Ex command arguments */
+ long verbose_save = -1;
+ int save_msg_scroll = 0;
+ int did_silent = 0;
+ int did_esilent = 0;
+ cmdmod_T save_cmdmod;
+ int ni; /* set when Not Implemented */
+
+ vim_memset(&ea, 0, sizeof(ea));
+ ea.line1 = 1;
+ ea.line2 = 1;
+#ifdef FEAT_EVAL
+ ++ex_nesting_level;
+#endif
+
+ /* when not editing the last file :q has to be typed twice */
+ if (quitmore
+#ifdef FEAT_EVAL
+ /* avoid that a function call in 'statusline' does this */
+ && !getline_equal(getline, cookie, get_func_line)
+#endif
+ )
+ --quitmore;
+
+ /*
+ * Reset browse, confirm, etc.. They are restored when returning, for
+ * recursive calls.
+ */
+ save_cmdmod = cmdmod;
+ vim_memset(&cmdmod, 0, sizeof(cmdmod));
+
+ /*
+ * Repeat until no more command modifiers are found.
+ */
+ ea.cmd = *cmdlinep;
+ for (;;)
+ {
+/*
+ * 1. skip comment lines and leading white space and colons
+ */
+ while (*ea.cmd == ' ' || *ea.cmd == '\t' || *ea.cmd == ':')
+ ++ea.cmd;
+
+ /* in ex mode, an empty line works like :+ */
+ if (*ea.cmd == NUL && exmode_active
+ && (getline_equal(getline, cookie, getexmodeline)
+ || getline_equal(getline, cookie, getexline)))
+ {
+ ea.cmd = (char_u *)"+";
+ ex_pressedreturn = TRUE;
+ }
+
+ /* ignore comment and empty lines */
+ if (*ea.cmd == '"' || *ea.cmd == NUL)
+ goto doend;
+
+/*
+ * 2. handle command modifiers.
+ */
+ p = ea.cmd;
+ if (VIM_ISDIGIT(*ea.cmd))
+ p = skipwhite(skipdigits(ea.cmd));
+ switch (*p)
+ {
+ /* When adding an entry, also modify cmd_exists(). */
+ case 'a': if (!checkforcmd(&ea.cmd, "aboveleft", 3))
+ break;
+#ifdef FEAT_WINDOWS
+ cmdmod.split |= WSP_ABOVE;
+#endif
+ continue;
+
+ case 'b': if (checkforcmd(&ea.cmd, "belowright", 3))
+ {
+#ifdef FEAT_WINDOWS
+ cmdmod.split |= WSP_BELOW;
+#endif
+ continue;
+ }
+ if (checkforcmd(&ea.cmd, "browse", 3))
+ {
+#ifdef FEAT_BROWSE
+ cmdmod.browse = TRUE;
+#endif
+ continue;
+ }
+ if (!checkforcmd(&ea.cmd, "botright", 2))
+ break;
+#ifdef FEAT_WINDOWS
+ cmdmod.split |= WSP_BOT;
+#endif
+ continue;
+
+ case 'c': if (!checkforcmd(&ea.cmd, "confirm", 4))
+ break;
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ cmdmod.confirm = TRUE;
+#endif
+ continue;
+
+ case 'k': if (checkforcmd(&ea.cmd, "keepmarks", 3))
+ {
+ cmdmod.keepmarks = TRUE;
+ continue;
+ }
+ if (!checkforcmd(&ea.cmd, "keepjumps", 5))
+ break;
+ cmdmod.keepjumps = TRUE;
+ continue;
+
+ /* ":hide" and ":hide | cmd" are not modifiers */
+ case 'h': if (p != ea.cmd || !checkforcmd(&p, "hide", 3)
+ || *p == NUL || ends_excmd(*p))
+ break;
+ ea.cmd = p;
+ cmdmod.hide = TRUE;
+ continue;
+
+ case 'l': if (checkforcmd(&ea.cmd, "lockmarks", 3))
+ {
+ cmdmod.lockmarks = TRUE;
+ continue;
+ }
+
+ if (!checkforcmd(&ea.cmd, "leftabove", 5))
+ break;
+#ifdef FEAT_WINDOWS
+ cmdmod.split |= WSP_ABOVE;
+#endif
+ continue;
+
+ case 'r': if (!checkforcmd(&ea.cmd, "rightbelow", 6))
+ break;
+#ifdef FEAT_WINDOWS
+ cmdmod.split |= WSP_BELOW;
+#endif
+ continue;
+
+ case 's': if (!checkforcmd(&ea.cmd, "silent", 3))
+ break;
+ ++did_silent;
+ ++msg_silent;
+ save_msg_scroll = msg_scroll;
+ if (*ea.cmd == '!' && !vim_iswhite(ea.cmd[-1]))
+ {
+ /* ":silent!", but not "silent !cmd" */
+ ea.cmd = skipwhite(ea.cmd + 1);
+ ++emsg_silent;
+ ++did_esilent;
+ }
+ continue;
+
+ case 't': if (!checkforcmd(&ea.cmd, "topleft", 2))
+ break;
+#ifdef FEAT_WINDOWS
+ cmdmod.split |= WSP_TOP;
+#endif
+ continue;
+
+ case 'v': if (checkforcmd(&ea.cmd, "vertical", 4))
+ {
+#ifdef FEAT_VERTSPLIT
+ cmdmod.split |= WSP_VERT;
+#endif
+ continue;
+ }
+ if (!checkforcmd(&p, "verbose", 4))
+ break;
+ if (verbose_save < 0)
+ verbose_save = p_verbose;
+ p_verbose = atoi((char *)ea.cmd);
+ if (p_verbose == 0)
+ p_verbose = 1;
+ ea.cmd = p;
+ continue;
+ }
+ break;
+ }
+
+#ifdef FEAT_EVAL
+ ea.skip = did_emsg || got_int || did_throw || (cstack->cs_idx >= 0
+ && !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE));
+#else
+ ea.skip = (if_level > 0);
+#endif
+
+#ifdef FEAT_EVAL
+ /* May go to debug mode. If this happens and the ">quit" debug command is
+ * used, throw an interrupt exception and skip the next command. */
+ dbg_check_breakpoint(&ea);
+ if (!ea.skip && got_int)
+ {
+ ea.skip = TRUE;
+ (void)do_intthrow(cstack);
+ }
+#endif
+
+/*
+ * 3. parse a range specifier of the form: addr [,addr] [;addr] ..
+ *
+ * where 'addr' is:
+ *
+ * % (entire file)
+ * $ [+-NUM]
+ * 'x [+-NUM] (where x denotes a currently defined mark)
+ * . [+-NUM]
+ * [+-NUM]..
+ * NUM
+ *
+ * The ea.cmd pointer is updated to point to the first character following the
+ * range spec. If an initial address is found, but no second, the upper bound
+ * is equal to the lower.
+ */
+
+ /* repeat for all ',' or ';' separated addresses */
+ for (;;)
+ {
+ ea.line1 = ea.line2;
+ ea.line2 = curwin->w_cursor.lnum; /* default is current line number */
+ ea.cmd = skipwhite(ea.cmd);
+ lnum = get_address(&ea.cmd, ea.skip, ea.addr_count == 0);
+ if (ea.cmd == NULL) /* error detected */
+ goto doend;
+ if (lnum == MAXLNUM)
+ {
+ if (*ea.cmd == '%') /* '%' - all lines */
+ {
+ ++ea.cmd;
+ ea.line1 = 1;
+ ea.line2 = curbuf->b_ml.ml_line_count;
+ ++ea.addr_count;
+ }
+ /* '*' - visual area */
+ else if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
+ {
+ pos_T *fp;
+
+ ++ea.cmd;
+ if (!ea.skip)
+ {
+ fp = getmark('<', FALSE);
+ if (check_mark(fp) == FAIL)
+ goto doend;
+ ea.line1 = fp->lnum;
+ fp = getmark('>', FALSE);
+ if (check_mark(fp) == FAIL)
+ goto doend;
+ ea.line2 = fp->lnum;
+ ++ea.addr_count;
+ }
+ }
+ }
+ else
+ ea.line2 = lnum;
+ ea.addr_count++;
+
+ if (*ea.cmd == ';')
+ {
+ if (!ea.skip)
+ curwin->w_cursor.lnum = ea.line2;
+ }
+ else if (*ea.cmd != ',')
+ break;
+ ++ea.cmd;
+ }
+
+ /* One address given: set start and end lines */
+ if (ea.addr_count == 1)
+ {
+ ea.line1 = ea.line2;
+ /* ... but only implicit: really no address given */
+ if (lnum == MAXLNUM)
+ ea.addr_count = 0;
+ }
+
+ /* Don't leave the cursor on an illegal line (caused by ';') */
+ check_cursor_lnum();
+
+/*
+ * 4. parse command
+ */
+
+ /*
+ * Skip ':' and any white space
+ */
+ ea.cmd = skipwhite(ea.cmd);
+ while (*ea.cmd == ':')
+ ea.cmd = skipwhite(ea.cmd + 1);
+
+ /*
+ * If we got a line, but no command, then go to the line.
+ * If we find a '|' or '\n' we set ea.nextcmd.
+ */
+ if (*ea.cmd == NUL || *ea.cmd == '"' ||
+ (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL)
+ {
+ /*
+ * strange vi behaviour:
+ * ":3" jumps to line 3
+ * ":3|..." prints line 3
+ * ":|" prints current line
+ */
+ if (ea.skip) /* skip this if inside :if */
+ goto doend;
+ if (*ea.cmd == '|')
+ {
+ ea.cmdidx = CMD_print;
+ ea.argt = RANGE+COUNT+TRLBAR;
+ if ((errormsg = invalid_range(&ea)) == NULL)
+ {
+ correct_range(&ea);
+ ex_print(&ea);
+ }
+ }
+ else if (ea.addr_count != 0)
+ {
+ if (ea.line2 < 0)
+ errormsg = invalid_range(&ea);
+ else
+ {
+ if (ea.line2 == 0)
+ curwin->w_cursor.lnum = 1;
+ else if (ea.line2 > curbuf->b_ml.ml_line_count)
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ else
+ curwin->w_cursor.lnum = ea.line2;
+ beginline(BL_SOL | BL_FIX);
+ }
+ }
+ goto doend;
+ }
+
+ /* Find the command and let "p" point to after it. */
+ p = find_command(&ea, NULL);
+
+#ifdef FEAT_USR_CMDS
+ if (p == NULL)
+ {
+ if (!ea.skip)
+ errormsg = (char_u *)_("E464: Ambiguous use of user-defined command");
+ goto doend;
+ }
+ /* Check for wrong commands. */
+ if (*p == '!' && ea.cmd[1] == 0151 && ea.cmd[0] == 78)
+ {
+ errormsg = uc_fun_cmd();
+ goto doend;
+ }
+#endif
+ if (ea.cmdidx == CMD_SIZE)
+ {
+ if (!ea.skip)
+ {
+ STRCPY(IObuff, _("E492: Not an editor command"));
+ if (!sourcing)
+ {
+ STRCAT(IObuff, ": ");
+ STRNCAT(IObuff, *cmdlinep, 40);
+ }
+ errormsg = IObuff;
+ }
+ goto doend;
+ }
+
+ ni = (
+#ifdef FEAT_USR_CMDS
+ !USER_CMDIDX(ea.cmdidx) &&
+#endif
+ cmdnames[ea.cmdidx].cmd_func == ex_ni);
+
+#ifndef FEAT_EVAL
+ /*
+ * When the expression evaluation is disabled, recognize the ":if" and
+ * ":endif" commands and ignore everything in between it.
+ */
+ if (ea.cmdidx == CMD_if)
+ ++if_level;
+ if (if_level)
+ {
+ if (ea.cmdidx == CMD_endif)
+ --if_level;
+ goto doend;
+ }
+
+#endif
+
+ if (*p == '!' && ea.cmdidx != CMD_substitute) /* forced commands */
+ {
+ ++p;
+ ea.forceit = TRUE;
+ }
+ else
+ ea.forceit = FALSE;
+
+/*
+ * 5. parse arguments
+ */
+#ifdef FEAT_USR_CMDS
+ if (!USER_CMDIDX(ea.cmdidx))
+#endif
+ ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt;
+
+ if (!ea.skip)
+ {
+#ifdef HAVE_SANDBOX
+ if (sandbox != 0 && !(ea.argt & SBOXOK))
+ {
+ /* Command not allowed in sandbox. */
+ errormsg = (char_u *)_(e_sandbox);
+ goto doend;
+ }
+#endif
+ if (!curbuf->b_p_ma && (ea.argt & MODIFY))
+ {
+ /* Command not allowed in non-'modifiable' buffer */
+ errormsg = (char_u *)_(e_modifiable);
+ goto doend;
+ }
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0 && !(ea.argt & CMDWIN)
+# ifdef FEAT_USR_CMDS
+ && !USER_CMDIDX(ea.cmdidx)
+# endif
+ )
+ {
+ /* Command not allowed in cmdline window. */
+ errormsg = (char_u *)_(e_cmdwin);
+ goto doend;
+ }
+#endif
+
+ if (!ni && !(ea.argt & RANGE) && ea.addr_count > 0)
+ {
+ /* no range allowed */
+ errormsg = (char_u *)_(e_norange);
+ goto doend;
+ }
+ }
+
+ if (!ni && !(ea.argt & BANG) && ea.forceit) /* no <!> allowed */
+ {
+ errormsg = (char_u *)_(e_nobang);
+ goto doend;
+ }
+
+ /*
+ * Don't complain about the range if it is not used
+ * (could happen if line_count is accidentally set to 0).
+ */
+ if (!ea.skip && !ni)
+ {
+ /*
+ * If the range is backwards, ask for confirmation and, if given, swap
+ * ea.line1 & ea.line2 so it's forwards again.
+ * When global command is busy, don't ask, will fail below.
+ */
+ if (!global_busy && ea.line1 > ea.line2)
+ {
+ if (sourcing)
+ {
+ errormsg = (char_u *)_("E493: Backwards range given");
+ goto doend;
+ }
+ else
+ {
+ int msg_silent_save = msg_silent;
+
+ msg_silent = 0;
+ if (ask_yesno((char_u *)
+ _("Backwards range given, OK to swap"), FALSE) != 'y')
+ goto doend;
+ msg_silent = msg_silent_save;
+ }
+ lnum = ea.line1;
+ ea.line1 = ea.line2;
+ ea.line2 = lnum;
+ }
+ if ((errormsg = invalid_range(&ea)) != NULL)
+ goto doend;
+ }
+
+ if ((ea.argt & NOTADR) && ea.addr_count == 0) /* default is 1, not cursor */
+ ea.line2 = 1;
+
+ correct_range(&ea);
+
+#ifdef FEAT_FOLDING
+ if (((ea.argt & WHOLEFOLD) || ea.addr_count >= 2) && !global_busy)
+ {
+ /* Put the first line at the start of a closed fold, put the last line
+ * at the end of a closed fold. */
+ (void)hasFolding(ea.line1, &ea.line1, NULL);
+ (void)hasFolding(ea.line2, NULL, &ea.line2);
+ }
+#endif
+
+#ifdef FEAT_QUICKFIX
+ /*
+ * For the :make and :grep commands we insert the 'makeprg'/'grepprg'
+ * option here, so things like % get expanded.
+ */
+ if (ea.cmdidx == CMD_make || ea.cmdidx == CMD_grep
+ || ea.cmdidx == CMD_grepadd)
+ {
+ char_u *new_cmdline;
+ char_u *program;
+ char_u *pos;
+ char_u *ptr;
+ int len;
+ int i;
+
+ if (ea.cmdidx == CMD_grep || ea.cmdidx == CMD_grepadd)
+ {
+ if (*curbuf->b_p_gp == NUL)
+ program = p_gp;
+ else
+ program = curbuf->b_p_gp;
+ }
+ else
+ {
+ if (*curbuf->b_p_mp == NUL)
+ program = p_mp;
+ else
+ program = curbuf->b_p_mp;
+ }
+
+ p = skipwhite(p);
+
+ if ((pos = (char_u *)strstr((char *)program, "$*")) != NULL)
+ { /* replace $* by given arguments */
+ i = 1;
+ while ((pos = (char_u *)strstr((char *)pos + 2, "$*")) != NULL)
+ ++i;
+ len = (int)STRLEN(p);
+ new_cmdline = alloc((int)(STRLEN(program) + i * (len - 2) + 1));
+ if (new_cmdline == NULL)
+ goto doend; /* out of memory */
+ ptr = new_cmdline;
+ while ((pos = (char_u *)strstr((char *)program, "$*")) != NULL)
+ {
+ i = (int)(pos - program);
+ STRNCPY(ptr, program, i);
+ STRCPY(ptr += i, p);
+ ptr += len;
+ program = pos + 2;
+ }
+ STRCPY(ptr, program);
+ }
+ else
+ {
+ new_cmdline = alloc((int)(STRLEN(program) + STRLEN(p) + 2));
+ if (new_cmdline == NULL)
+ goto doend; /* out of memory */
+ STRCPY(new_cmdline, program);
+ STRCAT(new_cmdline, " ");
+ STRCAT(new_cmdline, p);
+ }
+ msg_make(p);
+ /* 'ea.cmd' is not set here, because it is not used at CMD_make */
+ vim_free(*cmdlinep);
+ *cmdlinep = new_cmdline;
+ p = new_cmdline;
+ }
+#endif
+
+ /*
+ * Skip to start of argument.
+ * Don't do this for the ":!" command, because ":!! -l" needs the space.
+ */
+ if (ea.cmdidx == CMD_bang)
+ ea.arg = p;
+ else
+ ea.arg = skipwhite(p);
+
+ /*
+ * Check for "++opt=val" argument.
+ * Must be first, allow ":w ++enc=utf8 !cmd"
+ */
+ if (ea.argt & ARGOPT)
+ while (ea.arg[0] == '+' && ea.arg[1] == '+')
+ if (getargopt(&ea) == FAIL && !ni)
+ {
+ errormsg = (char_u *)_(e_invarg);
+ goto doend;
+ }
+
+ if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update)
+ {
+ if (*ea.arg == '>') /* append */
+ {
+ if (*++ea.arg != '>') /* typed wrong */
+ {
+ errormsg = (char_u *)_("E494: Use w or w>>");
+ goto doend;
+ }
+ ea.arg = skipwhite(ea.arg + 1);
+ ea.append = TRUE;
+ }
+ else if (*ea.arg == '!' && ea.cmdidx == CMD_write) /* :w !filter */
+ {
+ ++ea.arg;
+ ea.usefilter = TRUE;
+ }
+ }
+
+ if (ea.cmdidx == CMD_read)
+ {
+ if (ea.forceit)
+ {
+ ea.usefilter = TRUE; /* :r! filter if ea.forceit */
+ ea.forceit = FALSE;
+ }
+ else if (*ea.arg == '!') /* :r !filter */
+ {
+ ++ea.arg;
+ ea.usefilter = TRUE;
+ }
+ }
+
+ if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift)
+ {
+ ea.amount = 1;
+ while (*ea.arg == *ea.cmd) /* count number of '>' or '<' */
+ {
+ ++ea.arg;
+ ++ea.amount;
+ }
+ ea.arg = skipwhite(ea.arg);
+ }
+
+ /*
+ * Check for "+command" argument, before checking for next command.
+ * Don't do this for ":read !cmd" and ":write !cmd".
+ */
+ if ((ea.argt & EDITCMD) && !ea.usefilter)
+ ea.do_ecmd_cmd = getargcmd(&ea.arg);
+
+ /*
+ * Check for '|' to separate commands and '"' to start comments.
+ * Don't do this for ":read !cmd" and ":write !cmd".
+ */
+ if ((ea.argt & TRLBAR) && !ea.usefilter)
+ separate_nextcmd(&ea);
+
+ /*
+ * Check for <newline> to end a shell command.
+ * Also do this for ":read !cmd" and ":write !cmd".
+ */
+ else if (ea.cmdidx == CMD_bang || ea.usefilter)
+ {
+ for (p = ea.arg; *p; ++p)
+ {
+ /* Remove one backslash before a newline, so that it's possible to
+ * pass a newline to the shell and also a newline that is preceded
+ * with a backslash. This makes it impossible to end a shell
+ * command in a backslash, but that doesn't appear useful.
+ * Halving the number of backslashes is incompatible with previous
+ * versions. */
+ if (*p == '\\' && p[1] == '\n')
+ mch_memmove(p, p + 1, STRLEN(p));
+ else if (*p == '\n')
+ {
+ ea.nextcmd = p + 1;
+ *p = NUL;
+ break;
+ }
+ }
+ }
+
+ if ((ea.argt & DFLALL) && ea.addr_count == 0)
+ {
+ ea.line1 = 1;
+ ea.line2 = curbuf->b_ml.ml_line_count;
+ }
+
+ /* accept numbered register only when no count allowed (:put) */
+ if ( (ea.argt & REGSTR)
+ && *ea.arg != NUL
+#ifdef FEAT_USR_CMDS
+ && valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put
+ && USER_CMDIDX(ea.cmdidx)))
+ /* Do not allow register = for user commands */
+ && (!USER_CMDIDX(ea.cmdidx) || *ea.arg != '=')
+#else
+ && valid_yank_reg(*ea.arg, ea.cmdidx != CMD_put)
+#endif
+ && !((ea.argt & COUNT) && VIM_ISDIGIT(*ea.arg)))
+ {
+ ea.regname = *ea.arg++;
+#ifdef FEAT_EVAL
+ /* for '=' register: accept the rest of the line as an expression */
+ if (ea.arg[-1] == '=' && ea.arg[0] != NUL)
+ {
+ set_expr_line(vim_strsave(ea.arg));
+ ea.arg += STRLEN(ea.arg);
+ }
+#endif
+ ea.arg = skipwhite(ea.arg);
+ }
+
+ /*
+ * Check for a count. When accepting a BUFNAME, don't use "123foo" as a
+ * count, it's a buffer name.
+ */
+ if ((ea.argt & COUNT) && VIM_ISDIGIT(*ea.arg)
+ && (!(ea.argt & BUFNAME) || *(p = skipdigits(ea.arg)) == NUL
+ || vim_iswhite(*p)))
+ {
+ n = getdigits(&ea.arg);
+ ea.arg = skipwhite(ea.arg);
+ if (n <= 0 && !ni)
+ {
+ errormsg = (char_u *)_(e_zerocount);
+ goto doend;
+ }
+ if (ea.argt & NOTADR) /* e.g. :buffer 2, :sleep 3 */
+ {
+ ea.line2 = n;
+ if (ea.addr_count == 0)
+ ea.addr_count = 1;
+ }
+ else
+ {
+ ea.line1 = ea.line2;
+ ea.line2 += n - 1;
+ ++ea.addr_count;
+ /*
+ * Be vi compatible: no error message for out of range.
+ */
+ if (ea.line2 > curbuf->b_ml.ml_line_count)
+ ea.line2 = curbuf->b_ml.ml_line_count;
+ }
+ }
+ /* no arguments allowed */
+ if (!ni && !(ea.argt & EXTRA) && *ea.arg != NUL &&
+ vim_strchr((char_u *)"|\"", *ea.arg) == NULL)
+ {
+ errormsg = (char_u *)_(e_trailing);
+ goto doend;
+ }
+
+ if (!ni && (ea.argt & NEEDARG) && *ea.arg == NUL)
+ {
+ errormsg = (char_u *)_(e_argreq);
+ goto doend;
+ }
+
+#ifdef FEAT_EVAL
+ /*
+ * Skip the command when it's not going to be executed.
+ * The commands like :if, :endif, etc. always need to be executed.
+ * Also make an exception for commands that handle a trailing command
+ * themselves.
+ */
+ if (ea.skip)
+ {
+ switch (ea.cmdidx)
+ {
+ /* commands that need evaluation */
+ case CMD_while:
+ case CMD_endwhile:
+ case CMD_if:
+ case CMD_elseif:
+ case CMD_else:
+ case CMD_endif:
+ case CMD_try:
+ case CMD_catch:
+ case CMD_finally:
+ case CMD_endtry:
+ case CMD_function:
+ break;
+
+ /* Commands that handle '|' themselves. Check: A command should
+ * either have the TRLBAR flag, appear in this list or appear in
+ * the list at ":help :bar". */
+ case CMD_aboveleft:
+ case CMD_and:
+ case CMD_belowright:
+ case CMD_botright:
+ case CMD_browse:
+ case CMD_call:
+ case CMD_confirm:
+ case CMD_delfunction:
+ case CMD_djump:
+ case CMD_dlist:
+ case CMD_dsearch:
+ case CMD_dsplit:
+ case CMD_echo:
+ case CMD_echoerr:
+ case CMD_echomsg:
+ case CMD_echon:
+ case CMD_execute:
+ case CMD_help:
+ case CMD_hide:
+ case CMD_ijump:
+ case CMD_ilist:
+ case CMD_isearch:
+ case CMD_isplit:
+ case CMD_keepjumps:
+ case CMD_keepmarks:
+ case CMD_leftabove:
+ case CMD_let:
+ case CMD_lockmarks:
+ case CMD_match:
+ case CMD_perl:
+ case CMD_psearch:
+ case CMD_python:
+ case CMD_return:
+ case CMD_rightbelow:
+ case CMD_ruby:
+ case CMD_silent:
+ case CMD_smagic:
+ case CMD_snomagic:
+ case CMD_substitute:
+ case CMD_syntax:
+ case CMD_tcl:
+ case CMD_throw:
+ case CMD_tilde:
+ case CMD_topleft:
+ case CMD_unlet:
+ case CMD_verbose:
+ case CMD_vertical:
+ break;
+
+ default: goto doend;
+ }
+ }
+#endif
+
+ if (ea.argt & XFILE)
+ {
+ if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL)
+ goto doend;
+ }
+
+#ifdef FEAT_LISTCMDS
+ /*
+ * Accept buffer name. Cannot be used at the same time with a buffer
+ * number. Don't do this for a user command.
+ */
+ if ((ea.argt & BUFNAME) && *ea.arg != NUL && ea.addr_count == 0
+# ifdef FEAT_USR_CMDS
+ && !USER_CMDIDX(ea.cmdidx)
+# endif
+ )
+ {
+ /*
+ * :bdelete, :bwipeout and :bunload take several arguments, separated
+ * by spaces: find next space (skipping over escaped characters).
+ * The others take one argument: ignore trailing spaces.
+ */
+ if (ea.cmdidx == CMD_bdelete || ea.cmdidx == CMD_bwipeout
+ || ea.cmdidx == CMD_bunload)
+ p = skiptowhite_esc(ea.arg);
+ else
+ {
+ p = ea.arg + STRLEN(ea.arg);
+ while (p > ea.arg && vim_iswhite(p[-1]))
+ --p;
+ }
+ ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & BUFUNL) != 0, FALSE);
+ if (ea.line2 < 0) /* failed */
+ goto doend;
+ ea.addr_count = 1;
+ ea.arg = skipwhite(p);
+ }
+#endif
+
+/*
+ * 6. switch on command name
+ *
+ * The "ea" structure holds the arguments that can be used.
+ */
+ ea.cmdlinep = cmdlinep;
+ ea.getline = getline;
+ ea.cookie = cookie;
+#ifdef FEAT_EVAL
+ ea.cstack = cstack;
+#endif
+
+#ifdef FEAT_USR_CMDS
+ if (USER_CMDIDX(ea.cmdidx))
+ {
+ /*
+ * Execute a user-defined command.
+ */
+ do_ucmd(&ea);
+ }
+ else
+#endif
+ {
+ /*
+ * Call the function to execute the command.
+ */
+ ea.errmsg = NULL;
+ (cmdnames[ea.cmdidx].cmd_func)(&ea);
+ if (ea.errmsg != NULL)
+ errormsg = (char_u *)_(ea.errmsg);
+ }
+
+#ifdef FEAT_EVAL
+ /*
+ * If the command just executed called do_cmdline(), any throw or ":return"
+ * or ":finish" encountered there must also check the cstack of the still
+ * active do_cmdline() that called this do_one_cmd(). Rethrow an uncaught
+ * exception, or reanimate a returned function or finished script file and
+ * return or finish it again.
+ */
+ if (need_rethrow)
+ do_throw(cstack);
+ else if (check_cstack)
+ {
+ if (source_finished(getline, cookie))
+ do_finish(&ea, TRUE);
+ else if (getline_equal(getline, cookie, get_func_line)
+ && current_func_returned())
+ do_return(&ea, TRUE, FALSE, NULL);
+ }
+ need_rethrow = check_cstack = FALSE;
+#endif
+
+doend:
+ if (curwin->w_cursor.lnum == 0) /* can happen with zero line number */
+ curwin->w_cursor.lnum = 1;
+
+ if (errormsg != NULL && *errormsg != NUL && !did_emsg)
+ {
+ if (sourcing)
+ {
+ if (errormsg != IObuff)
+ {
+ STRCPY(IObuff, errormsg);
+ errormsg = IObuff;
+ }
+ STRCAT(errormsg, ": ");
+ STRNCAT(errormsg, *cmdlinep, IOSIZE - STRLEN(IObuff));
+ }
+ emsg(errormsg);
+ }
+#ifdef FEAT_EVAL
+ do_errthrow(cstack,
+ (ea.cmdidx != CMD_SIZE
+# ifdef FEAT_USR_CMDS
+ && !USER_CMDIDX(ea.cmdidx)
+# endif
+ ) ? cmdnames[(int)ea.cmdidx].cmd_name : (char_u *)NULL);
+#endif
+
+ if (verbose_save >= 0)
+ p_verbose = verbose_save;
+
+ cmdmod = save_cmdmod;
+
+ if (did_silent > 0)
+ {
+ /* messages could be enabled for a serious error, need to check if the
+ * counters don't become negative */
+ msg_silent -= did_silent;
+ if (msg_silent < 0)
+ msg_silent = 0;
+ emsg_silent -= did_esilent;
+ if (emsg_silent < 0)
+ emsg_silent = 0;
+ /* Restore msg_scroll, it's set by file I/O commands, even when no
+ * message is actually displayed. */
+ msg_scroll = save_msg_scroll;
+ }
+
+ if (ea.nextcmd && *ea.nextcmd == NUL) /* not really a next command */
+ ea.nextcmd = NULL;
+
+#ifdef FEAT_EVAL
+ --ex_nesting_level;
+#endif
+
+ return ea.nextcmd;
+}
+#if (_MSC_VER == 1200)
+# pragma optimize( "", on )
+#endif
+
+/*
+ * Check for a command modifier command with optional tail.
+ * If there is a match advance "pp" to the argument and return TRUE.
+ */
+ static int
+checkforcmd(pp, cmd, len)
+ char_u **pp; /* start of command line */
+ char *cmd; /* name of command */
+ int len; /* required length */
+{
+ int i;
+
+ for (i = 0; cmd[i] != NUL; ++i)
+ if (cmd[i] != (*pp)[i])
+ break;
+ if (i >= len && !isalpha((*pp)[i]))
+ {
+ *pp = skipwhite(*pp + i);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Find an Ex command by its name, either built-in or user.
+ * Name can be found at eap->cmd.
+ * Returns pointer to char after the command name.
+ * Returns NULL for an ambiguous user command.
+ */
+/*ARGSUSED*/
+ static char_u *
+find_command(eap, full)
+ exarg_T *eap;
+ int *full;
+{
+ int len;
+ char_u *p;
+
+ /*
+ * Isolate the command and search for it in the command table.
+ * Exeptions:
+ * - the 'k' command can directly be followed by any character.
+ * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
+ * but :sre[wind] is another command, as are :scrip[tnames],
+ * :scs[cope], :sim[alt], :sig[ns] and :sil[ent].
+ */
+ p = eap->cmd;
+ if (*p == 'k')
+ {
+ eap->cmdidx = CMD_k;
+ ++p;
+ }
+ else if (p[0] == 's'
+ && ((p[1] == 'c' && p[2] != 's' && p[2] != 'r' && p[3] != 'i' && p[4] != 'p')
+ || p[1] == 'g'
+ || (p[1] == 'i' && p[2] != 'm' && p[2] != 'l' && p[2] != 'g')
+ || p[1] == 'I'
+ || (p[1] == 'r' && p[2] != 'e')))
+ {
+ eap->cmdidx = CMD_substitute;
+ ++p;
+ }
+ else
+ {
+ while (ASCII_ISALPHA(*p))
+ ++p;
+ /* check for non-alpha command */
+ if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL)
+ ++p;
+ len = (int)(p - eap->cmd);
+
+ if (ASCII_ISLOWER(*eap->cmd))
+ eap->cmdidx = cmdidxs[CharOrdLow(*eap->cmd)];
+ else
+ eap->cmdidx = cmdidxs[26];
+
+ for ( ; (int)eap->cmdidx < (int)CMD_SIZE;
+ eap->cmdidx = (cmdidx_T)((int)eap->cmdidx + 1))
+ if (STRNCMP(cmdnames[(int)eap->cmdidx].cmd_name, (char *)eap->cmd,
+ (size_t)len) == 0)
+ {
+#ifdef FEAT_EVAL
+ if (full != NULL
+ && cmdnames[(int)eap->cmdidx].cmd_name[len] == NUL)
+ *full = TRUE;
+#endif
+ break;
+ }
+
+#ifdef FEAT_USR_CMDS
+ /* Look for a user defined command as a last resort */
+ if (eap->cmdidx == CMD_SIZE && *eap->cmd >= 'A' && *eap->cmd <= 'Z')
+ {
+ ucmd_T *cmd;
+ int j, k, matchlen = 0;
+ int found = FALSE, possible = FALSE;
+ char_u *cp, *np; /* Point into typed cmd and test name */
+ garray_T *gap;
+ int amb_local = FALSE; /* Found ambiguous buffer-local
+ command, only full match global
+ is accepted. */
+
+ /* User defined commands may contain numbers */
+ while (ASCII_ISALNUM(*p))
+ ++p;
+ len = (int)(p - eap->cmd);
+
+ /*
+ * Look for buffer-local user commands first, then global ones.
+ */
+ gap = &curbuf->b_ucmds;
+ for (;;)
+ {
+ for (j = 0; j < gap->ga_len; ++j)
+ {
+ cmd = USER_CMD_GA(gap, j);
+ cp = eap->cmd;
+ np = cmd->uc_name;
+ k = 0;
+ while (k < len && *np != NUL && *cp++ == *np++)
+ k++;
+ if (k == len || (*np == NUL && vim_isdigit(eap->cmd[k])))
+ {
+ /* If finding a second match, the command is
+ * ambiguous. But not if a buffer-local command
+ * wasn't a full match and a global command is a full
+ * match. */
+ if (k == len && found && *np != NUL)
+ {
+ if (gap == &ucmds)
+ return NULL;
+ amb_local = TRUE;
+ }
+
+ if (!found || (k == len && *np == NUL))
+ {
+ /* If we matched up to a digit, then there could
+ * be another command including the digit that we
+ * should use instead.
+ */
+ if (k == len)
+ found = TRUE;
+ else
+ possible = TRUE;
+
+ if (gap == &ucmds)
+ eap->cmdidx = CMD_USER;
+ else
+ eap->cmdidx = CMD_USER_BUF;
+ eap->argt = cmd->uc_argt;
+ eap->useridx = j;
+
+ /* Do not search for further abbreviations
+ * if this is an exact match. */
+ matchlen = k;
+ if (k == len && *np == NUL)
+ {
+ if (full != NULL)
+ *full = TRUE;
+ amb_local = FALSE;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Stop if we found a full match or searched all. */
+ if (j < gap->ga_len || gap == &ucmds)
+ break;
+ gap = &ucmds;
+ }
+
+ /* Only found ambiguous matches. */
+ if (amb_local)
+ return NULL;
+
+ /* The match we found may be followed immediately by a
+ * number. Move *p back to point to it.
+ */
+ if (found || possible)
+ p += matchlen - len;
+ }
+#endif
+
+ if (len == 0)
+ eap->cmdidx = CMD_SIZE;
+ }
+
+ return p;
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return > 0 if an Ex command "name" exists.
+ * Return 2 if there is an exact match.
+ * Return 3 if there is an ambiguous match.
+ */
+ int
+cmd_exists(name)
+ char_u *name;
+{
+ exarg_T ea;
+ int full = FALSE;
+ int i;
+ int j;
+ static struct cmdmod
+ {
+ char *name;
+ int minlen;
+ } cmdmods[] = {
+ {"aboveleft", 3},
+ {"belowright", 3},
+ {"botright", 2},
+ {"browse", 3},
+ {"confirm", 4},
+ {"hide", 3},
+ {"keepjumps", 5},
+ {"keepmarks", 3},
+ {"leftabove", 5},
+ {"lockmarks", 3},
+ {"rightbelow", 6},
+ {"silent", 3},
+ {"topleft", 2},
+ {"verbose", 4},
+ {"vertical", 4},
+ };
+
+ /* Check command modifiers. */
+ for (i = 0; i < sizeof(cmdmods) / sizeof(struct cmdmod); ++i)
+ {
+ for (j = 0; name[j] != NUL; ++j)
+ if (name[j] != cmdmods[i].name[j])
+ break;
+ if (name[j] == NUL && j >= cmdmods[i].minlen)
+ return (cmdmods[i].name[j] == NUL ? 2 : 1);
+ }
+
+ /* Check built-in commands and user defined commands. */
+ ea.cmd = name;
+ ea.cmdidx = (cmdidx_T)0;
+ if (find_command(&ea, &full) == NULL)
+ return 3;
+ return (ea.cmdidx == CMD_SIZE ? 0 : (full ? 2 : 1));
+}
+#endif
+
+/*
+ * This is all pretty much copied from do_one_cmd(), with all the extra stuff
+ * we don't need/want deleted. Maybe this could be done better if we didn't
+ * repeat all this stuff. The only problem is that they may not stay
+ * perfectly compatible with each other, but then the command line syntax
+ * probably won't change that much -- webb.
+ */
+ char_u *
+set_one_cmd_context(xp, buff)
+ expand_T *xp;
+ char_u *buff; /* buffer for command string */
+{
+ char_u *p;
+ char_u *cmd, *arg;
+ int i = 0;
+ cmdidx_T cmdidx;
+ long_u argt = 0;
+#if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)
+ int compl = EXPAND_NOTHING;
+#endif
+#ifdef FEAT_CMDL_COMPL
+ int delim;
+#endif
+ int forceit = FALSE;
+ int usefilter = FALSE; /* filter instead of file name */
+
+ xp->xp_pattern = buff;
+ xp->xp_context = EXPAND_COMMANDS; /* Default until we get past command */
+ xp->xp_backslash = XP_BS_NONE;
+#if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
+ xp->xp_arg = NULL;
+#endif
+
+/*
+ * 2. skip comment lines and leading space, colons or bars
+ */
+ for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++)
+ ;
+ xp->xp_pattern = cmd;
+
+ if (*cmd == NUL)
+ return NULL;
+ if (*cmd == '"') /* ignore comment lines */
+ {
+ xp->xp_context = EXPAND_NOTHING;
+ return NULL;
+ }
+
+/*
+ * 3. parse a range specifier of the form: addr [,addr] [;addr] ..
+ */
+ cmd = skip_range(cmd, &xp->xp_context);
+
+/*
+ * 4. parse command
+ */
+
+ cmd = skipwhite(cmd);
+ xp->xp_pattern = cmd;
+ if (*cmd == NUL)
+ return NULL;
+ if (*cmd == '"')
+ {
+ xp->xp_context = EXPAND_NOTHING;
+ return NULL;
+ }
+
+ if (*cmd == '|' || *cmd == '\n')
+ return cmd + 1; /* There's another command */
+
+ /*
+ * Isolate the command and search for it in the command table.
+ * Exceptions:
+ * - the 'k' command can directly be followed by any character, but
+ * do accept "keepmarks" and "keepjumps".
+ * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
+ */
+ if (*cmd == 'k' && cmd[1] != 'e')
+ {
+ cmdidx = CMD_k;
+ p = cmd + 1;
+ }
+ else
+ {
+ p = cmd;
+ while (ASCII_ISALPHA(*p) || *p == '*') /* Allow * wild card */
+ ++p;
+ /* check for non-alpha command */
+ if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL)
+ ++p;
+ i = (int)(p - cmd);
+
+ if (i == 0)
+ {
+ xp->xp_context = EXPAND_UNSUCCESSFUL;
+ return NULL;
+ }
+ for (cmdidx = (cmdidx_T)0; (int)cmdidx < (int)CMD_SIZE;
+ cmdidx = (cmdidx_T)((int)cmdidx + 1))
+ if (STRNCMP(cmdnames[(int)cmdidx].cmd_name, cmd, (size_t)i) == 0)
+ break;
+
+#ifdef FEAT_USR_CMDS
+ if (cmd[0] >= 'A' && cmd[0] <= 'Z')
+ {
+ while (ASCII_ISALNUM(*p) || *p == '*') /* Allow * wild card */
+ ++p;
+ i = (int)(p - cmd);
+ }
+#endif
+ }
+
+ /*
+ * If the cursor is touching the command, and it ends in an alpha-numeric
+ * character, complete the command name.
+ */
+ if (*p == NUL && ASCII_ISALNUM(p[-1]))
+ return NULL;
+
+ if (cmdidx == CMD_SIZE)
+ {
+ if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL)
+ {
+ cmdidx = CMD_substitute;
+ p = cmd + 1;
+ }
+#ifdef FEAT_USR_CMDS
+ else if (cmd[0] >= 'A' && cmd[0] <= 'Z')
+ {
+ /* Look for a user defined command as a last resort */
+ ucmd_T *uc;
+ int j, k, matchlen = 0;
+ int found = FALSE, possible = FALSE;
+ char_u *cp, *np; /* Point into typed cmd and test name */
+ garray_T *gap;
+
+ gap = &curbuf->b_ucmds;
+ for (;;)
+ {
+ uc = USER_CMD_GA(gap, 0);
+ for (j = 0; j < gap->ga_len; ++j, ++uc)
+ {
+ cp = cmd;
+ np = uc->uc_name;
+ k = 0;
+ while (k < i && *np != NUL && *cp++ == *np++)
+ k++;
+ if (k == i || (*np == NUL && VIM_ISDIGIT(cmd[k])))
+ {
+ if (k == i && found)
+ {
+ /* Ambiguous abbreviation */
+ xp->xp_context = EXPAND_UNSUCCESSFUL;
+ return NULL;
+ }
+ if (!found)
+ {
+ /* If we matched up to a digit, then there could
+ * be another command including the digit that we
+ * should use instead.
+ */
+ if (k == i)
+ found = TRUE;
+ else
+ possible = TRUE;
+
+ if (gap == &ucmds)
+ cmdidx = CMD_USER;
+ else
+ cmdidx = CMD_USER_BUF;
+ argt = uc->uc_argt;
+#ifdef FEAT_CMDL_COMPL
+ compl = uc->uc_compl;
+# ifdef FEAT_EVAL
+ xp->xp_arg = uc->uc_compl_arg;
+ xp->xp_scriptID = uc->uc_scriptID;
+# endif
+#endif
+ /* Do not search for further abbreviations
+ * if this is an exact match
+ */
+ matchlen = k;
+ if (k == i && *np == NUL)
+ break;
+ }
+ }
+ }
+ if (gap == &ucmds || j < gap->ga_len)
+ break;
+ gap = &ucmds;
+ }
+
+ /* The match we found may be followed immediately by a
+ * number. Move *p back to point to it.
+ */
+ if (found || possible)
+ p += matchlen - i;
+ }
+#endif
+ }
+ if (cmdidx == CMD_SIZE)
+ {
+ /* Not still touching the command and it was an illegal one */
+ xp->xp_context = EXPAND_UNSUCCESSFUL;
+ return NULL;
+ }
+
+ xp->xp_context = EXPAND_NOTHING; /* Default now that we're past command */
+
+ if (*p == '!') /* forced commands */
+ {
+ forceit = TRUE;
+ ++p;
+ }
+
+/*
+ * 5. parse arguments
+ */
+#ifdef FEAT_USR_CMDS
+ if (!USER_CMDIDX(cmdidx))
+#endif
+ argt = cmdnames[(int)cmdidx].cmd_argt;
+
+ arg = skipwhite(p);
+
+ if (cmdidx == CMD_write || cmdidx == CMD_update)
+ {
+ if (*arg == '>') /* append */
+ {
+ if (*++arg == '>')
+ ++arg;
+ arg = skipwhite(arg);
+ }
+ else if (*arg == '!' && cmdidx == CMD_write) /* :w !filter */
+ {
+ ++arg;
+ usefilter = TRUE;
+ }
+ }
+
+ if (cmdidx == CMD_read)
+ {
+ usefilter = forceit; /* :r! filter if forced */
+ if (*arg == '!') /* :r !filter */
+ {
+ ++arg;
+ usefilter = TRUE;
+ }
+ }
+
+ if (cmdidx == CMD_lshift || cmdidx == CMD_rshift)
+ {
+ while (*arg == *cmd) /* allow any number of '>' or '<' */
+ ++arg;
+ arg = skipwhite(arg);
+ }
+
+ /* Does command allow "+command"? */
+ if ((argt & EDITCMD) && !usefilter && *arg == '+')
+ {
+ /* Check if we're in the +command */
+ p = arg + 1;
+ arg = skip_cmd_arg(arg, FALSE);
+
+ /* Still touching the command after '+'? */
+ if (*arg == NUL)
+ return p;
+
+ /* Skip space(s) after +command to get to the real argument */
+ arg = skipwhite(arg);
+ }
+
+ /*
+ * Check for '|' to separate commands and '"' to start comments.
+ * Don't do this for ":read !cmd" and ":write !cmd".
+ */
+ if ((argt & TRLBAR) && !usefilter)
+ {
+ p = arg;
+ /* ":redir @" is not the start of a comment */
+ if (cmdidx == CMD_redir && p[0] == '@' && p[1] == '"')
+ p += 2;
+ while (*p)
+ {
+ if (*p == Ctrl_V)
+ {
+ if (p[1] != NUL)
+ ++p;
+ }
+ else if ( (*p == '"' && !(argt & NOTRLCOM))
+ || *p == '|' || *p == '\n')
+ {
+ if (*(p - 1) != '\\')
+ {
+ if (*p == '|' || *p == '\n')
+ return p + 1;
+ return NULL; /* It's a comment */
+ }
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p);
+ else
+#endif
+ ++p;
+ }
+ }
+
+ /* no arguments allowed */
+ if (!(argt & EXTRA) && *arg != NUL &&
+ vim_strchr((char_u *)"|\"", *arg) == NULL)
+ return NULL;
+
+ /* Find start of last argument (argument just before cursor): */
+ p = buff + STRLEN(buff);
+ while (p != arg && *p != ' ' && *p != TAB)
+ p--;
+ if (*p == ' ' || *p == TAB)
+ p++;
+ xp->xp_pattern = p;
+
+ if (argt & XFILE)
+ {
+ int in_quote = FALSE;
+ char_u *bow = NULL; /* Beginning of word */
+
+ /*
+ * Allow spaces within back-quotes to count as part of the argument
+ * being expanded.
+ */
+ xp->xp_pattern = skipwhite(arg);
+ for (p = xp->xp_pattern; *p; )
+ {
+ if (*p == '\\' && p[1])
+ ++p;
+#ifdef SPACE_IN_FILENAME
+ else if (vim_iswhite(*p) && (!(argt & NOSPC) || usefilter))
+#else
+ else if (vim_iswhite(*p))
+#endif
+ {
+ p = skipwhite(p);
+ if (in_quote)
+ bow = p;
+ else
+ xp->xp_pattern = p;
+ --p;
+ }
+ else if (*p == '`')
+ {
+ if (!in_quote)
+ {
+ xp->xp_pattern = p;
+ bow = p + 1;
+ }
+ in_quote = !in_quote;
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p);
+ else
+#endif
+ ++p;
+ }
+
+ /*
+ * If we are still inside the quotes, and we passed a space, just
+ * expand from there.
+ */
+ if (bow != NULL && in_quote)
+ xp->xp_pattern = bow;
+ xp->xp_context = EXPAND_FILES;
+
+ /* Check for environment variable */
+ if (*xp->xp_pattern == '$'
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
+ || *xp->xp_pattern == '%'
+#endif
+ )
+ {
+ for (p = xp->xp_pattern + 1; *p != NUL; ++p)
+ if (!vim_isIDc(*p))
+ break;
+ if (*p == NUL)
+ {
+ xp->xp_context = EXPAND_ENV_VARS;
+ ++xp->xp_pattern;
+ }
+ }
+ }
+
+/*
+ * 6. switch on command name
+ */
+ switch (cmdidx)
+ {
+ case CMD_cd:
+ case CMD_chdir:
+ case CMD_lcd:
+ case CMD_lchdir:
+ if (xp->xp_context == EXPAND_FILES)
+ xp->xp_context = EXPAND_DIRECTORIES;
+ break;
+ case CMD_help:
+ xp->xp_context = EXPAND_HELP;
+ xp->xp_pattern = arg;
+ break;
+
+ /* Command modifiers: return the argument. */
+ case CMD_aboveleft:
+ case CMD_belowright:
+ case CMD_botright:
+ case CMD_browse:
+ case CMD_confirm:
+ case CMD_folddoclosed:
+ case CMD_folddoopen:
+ case CMD_hide:
+ case CMD_keepjumps:
+ case CMD_keepmarks:
+ case CMD_leftabove:
+ case CMD_lockmarks:
+ case CMD_rightbelow:
+ case CMD_silent:
+ case CMD_topleft:
+ case CMD_verbose:
+ case CMD_vertical:
+ return arg;
+
+#ifdef FEAT_SEARCH_EXTRA
+ case CMD_match:
+ if (*arg == NUL || !ends_excmd(*arg))
+ {
+ /* Dummy call to clear variables. */
+ set_context_in_highlight_cmd(xp, (char_u *)"link n");
+ xp->xp_context = EXPAND_HIGHLIGHT;
+ xp->xp_pattern = arg;
+ arg = skipwhite(skiptowhite(arg));
+ if (*arg != NUL)
+ {
+ xp->xp_context = EXPAND_NOTHING;
+ arg = skip_regexp(arg + 1, *arg, p_magic, NULL);
+ }
+ }
+ return find_nextcmd(arg);
+#endif
+
+#ifdef FEAT_CMDL_COMPL
+/*
+ * All completion for the +cmdline_compl feature goes here.
+ */
+
+# ifdef FEAT_USR_CMDS
+ case CMD_command:
+ /* Check for attributes */
+ while (*arg == '-')
+ {
+ arg++; /* Skip "-" */
+ p = skiptowhite(arg);
+ if (*p == NUL)
+ {
+ /* Cursor is still in the attribute */
+ p = vim_strchr(arg, '=');
+ if (p == NULL)
+ {
+ /* No "=", so complete attribute names */
+ xp->xp_context = EXPAND_USER_CMD_FLAGS;
+ xp->xp_pattern = arg;
+ return NULL;
+ }
+
+ /* For the -complete and -nargs attributes, we complete
+ * their arguments as well.
+ */
+ if (STRNICMP(arg, "complete", p - arg) == 0)
+ {
+ xp->xp_context = EXPAND_USER_COMPLETE;
+ xp->xp_pattern = p + 1;
+ return NULL;
+ }
+ else if (STRNICMP(arg, "nargs", p - arg) == 0)
+ {
+ xp->xp_context = EXPAND_USER_NARGS;
+ xp->xp_pattern = p + 1;
+ return NULL;
+ }
+ return NULL;
+ }
+ arg = skipwhite(p);
+ }
+
+ /* After the attributes comes the new command name */
+ p = skiptowhite(arg);
+ if (*p == NUL)
+ {
+ xp->xp_context = EXPAND_USER_COMMANDS;
+ xp->xp_pattern = arg;
+ break;
+ }
+
+ /* And finally comes a normal command */
+ return skipwhite(p);
+
+ case CMD_delcommand:
+ xp->xp_context = EXPAND_USER_COMMANDS;
+ xp->xp_pattern = arg;
+ break;
+# endif
+
+ case CMD_global:
+ case CMD_vglobal:
+ delim = *arg; /* get the delimiter */
+ if (delim)
+ ++arg; /* skip delimiter if there is one */
+
+ while (arg[0] != NUL && arg[0] != delim)
+ {
+ if (arg[0] == '\\' && arg[1] != NUL)
+ ++arg;
+ ++arg;
+ }
+ if (arg[0] != NUL)
+ return arg + 1;
+ break;
+ case CMD_and:
+ case CMD_substitute:
+ delim = *arg;
+ if (delim)
+ {
+ /* skip "from" part */
+ ++arg;
+ arg = skip_regexp(arg, delim, p_magic, NULL);
+ }
+ /* skip "to" part */
+ while (arg[0] != NUL && arg[0] != delim)
+ {
+ if (arg[0] == '\\' && arg[1] != NUL)
+ ++arg;
+ ++arg;
+ }
+ if (arg[0] != NUL) /* skip delimiter */
+ ++arg;
+ while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL)
+ ++arg;
+ if (arg[0] != NUL)
+ return arg;
+ break;
+ case CMD_isearch:
+ case CMD_dsearch:
+ case CMD_ilist:
+ case CMD_dlist:
+ case CMD_ijump:
+ case CMD_psearch:
+ case CMD_djump:
+ case CMD_isplit:
+ case CMD_dsplit:
+ arg = skipwhite(skipdigits(arg)); /* skip count */
+ if (*arg == '/') /* Match regexp, not just whole words */
+ {
+ for (++arg; *arg && *arg != '/'; arg++)
+ if (*arg == '\\' && arg[1] != NUL)
+ arg++;
+ if (*arg)
+ {
+ arg = skipwhite(arg + 1);
+
+ /* Check for trailing illegal characters */
+ if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL)
+ xp->xp_context = EXPAND_NOTHING;
+ else
+ return arg;
+ }
+ }
+ break;
+#ifdef FEAT_AUTOCMD
+ case CMD_autocmd:
+ return set_context_in_autocmd(xp, arg, FALSE);
+
+ case CMD_doautocmd:
+ return set_context_in_autocmd(xp, arg, TRUE);
+#endif
+ case CMD_set:
+ set_context_in_set_cmd(xp, arg, 0);
+ break;
+ case CMD_setglobal:
+ set_context_in_set_cmd(xp, arg, OPT_GLOBAL);
+ break;
+ case CMD_setlocal:
+ set_context_in_set_cmd(xp, arg, OPT_LOCAL);
+ break;
+ case CMD_tag:
+ case CMD_stag:
+ case CMD_ptag:
+ case CMD_tselect:
+ case CMD_stselect:
+ case CMD_ptselect:
+ case CMD_tjump:
+ case CMD_stjump:
+ case CMD_ptjump:
+ xp->xp_context = EXPAND_TAGS;
+ xp->xp_pattern = arg;
+ break;
+ case CMD_augroup:
+ xp->xp_context = EXPAND_AUGROUP;
+ xp->xp_pattern = arg;
+ break;
+#ifdef FEAT_SYN_HL
+ case CMD_syntax:
+ set_context_in_syntax_cmd(xp, arg);
+ break;
+#endif
+#ifdef FEAT_EVAL
+ case CMD_let:
+ case CMD_if:
+ case CMD_elseif:
+ case CMD_while:
+ case CMD_echo:
+ case CMD_echon:
+ case CMD_execute:
+ case CMD_echomsg:
+ case CMD_echoerr:
+ case CMD_call:
+ case CMD_return:
+ set_context_for_expression(xp, arg, cmdidx);
+ break;
+
+ case CMD_unlet:
+ while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
+ arg = xp->xp_pattern + 1;
+ xp->xp_context = EXPAND_USER_VARS;
+ xp->xp_pattern = arg;
+ break;
+
+ case CMD_function:
+ case CMD_delfunction:
+ xp->xp_context = EXPAND_USER_FUNC;
+ xp->xp_pattern = arg;
+ break;
+
+ case CMD_echohl:
+ xp->xp_context = EXPAND_HIGHLIGHT;
+ xp->xp_pattern = arg;
+ break;
+#endif
+ case CMD_highlight:
+ set_context_in_highlight_cmd(xp, arg);
+ break;
+#ifdef FEAT_LISTCMDS
+ case CMD_bdelete:
+ case CMD_bwipeout:
+ case CMD_bunload:
+ while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
+ arg = xp->xp_pattern + 1;
+ /*FALLTHROUGH*/
+ case CMD_buffer:
+ case CMD_sbuffer:
+ case CMD_checktime:
+ xp->xp_context = EXPAND_BUFFERS;
+ xp->xp_pattern = arg;
+ break;
+#endif
+#ifdef FEAT_USR_CMDS
+ case CMD_USER:
+ case CMD_USER_BUF:
+ if (compl != EXPAND_NOTHING)
+ {
+ /* XFILE: file names are handled above */
+ if (!(argt & XFILE))
+ {
+# ifdef FEAT_MENU
+ if (compl == EXPAND_MENUS)
+ return set_context_in_menu_cmd(xp, cmd, arg, forceit);
+# endif
+ if (compl == EXPAND_COMMANDS)
+ return arg;
+ if (compl == EXPAND_MAPPINGS)
+ return set_context_in_map_cmd(xp, (char_u *)"map",
+ arg, forceit, FALSE, FALSE, CMD_map);
+ while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
+ arg = xp->xp_pattern + 1;
+ xp->xp_pattern = arg;
+ }
+ xp->xp_context = compl;
+ }
+ break;
+#endif
+ case CMD_map: case CMD_noremap:
+ case CMD_nmap: case CMD_nnoremap:
+ case CMD_vmap: case CMD_vnoremap:
+ case CMD_omap: case CMD_onoremap:
+ case CMD_imap: case CMD_inoremap:
+ case CMD_cmap: case CMD_cnoremap:
+ return set_context_in_map_cmd(xp, cmd, arg, forceit,
+ FALSE, FALSE, cmdidx);
+ case CMD_unmap:
+ case CMD_nunmap:
+ case CMD_vunmap:
+ case CMD_ounmap:
+ case CMD_iunmap:
+ case CMD_cunmap:
+ return set_context_in_map_cmd(xp, cmd, arg, forceit,
+ FALSE, TRUE, cmdidx);
+ case CMD_abbreviate: case CMD_noreabbrev:
+ case CMD_cabbrev: case CMD_cnoreabbrev:
+ case CMD_iabbrev: case CMD_inoreabbrev:
+ return set_context_in_map_cmd(xp, cmd, arg, forceit,
+ TRUE, FALSE, cmdidx);
+ case CMD_unabbreviate:
+ case CMD_cunabbrev:
+ case CMD_iunabbrev:
+ return set_context_in_map_cmd(xp, cmd, arg, forceit,
+ TRUE, TRUE, cmdidx);
+#ifdef FEAT_MENU
+ case CMD_menu: case CMD_noremenu: case CMD_unmenu:
+ case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu:
+ case CMD_nmenu: case CMD_nnoremenu: case CMD_nunmenu:
+ case CMD_vmenu: case CMD_vnoremenu: case CMD_vunmenu:
+ case CMD_omenu: case CMD_onoremenu: case CMD_ounmenu:
+ case CMD_imenu: case CMD_inoremenu: case CMD_iunmenu:
+ case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu:
+ case CMD_tmenu: case CMD_tunmenu:
+ case CMD_popup: case CMD_tearoff: case CMD_emenu:
+ return set_context_in_menu_cmd(xp, cmd, arg, forceit);
+#endif
+
+ case CMD_colorscheme:
+ xp->xp_context = EXPAND_COLORS;
+ xp->xp_pattern = arg;
+ break;
+
+ case CMD_compiler:
+ xp->xp_context = EXPAND_COMPILER;
+ xp->xp_pattern = arg;
+ break;
+
+#if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
+ && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
+ case CMD_language:
+ if (*skiptowhite(arg) == NUL)
+ {
+ xp->xp_context = EXPAND_LANGUAGE;
+ xp->xp_pattern = arg;
+ }
+ else
+ xp->xp_context = EXPAND_NOTHING;
+ break;
+#endif
+
+#endif /* FEAT_CMDL_COMPL */
+
+ default:
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * skip a range specifier of the form: addr [,addr] [;addr] ..
+ *
+ * Backslashed delimiters after / or ? will be skipped, and commands will
+ * not be expanded between /'s and ?'s or after "'".
+ *
+ * Returns the "cmd" pointer advanced to beyond the range.
+ */
+ char_u *
+skip_range(cmd, ctx)
+ char_u *cmd;
+ int *ctx; /* pointer to xp_context or NULL */
+{
+ int delim;
+
+ while (*cmd != NUL && (vim_isspace(*cmd) || VIM_ISDIGIT(*cmd) ||
+ vim_strchr((char_u *)".$%'/?-+,;", *cmd) != NULL))
+ {
+ if (*cmd == '\'')
+ {
+ if (*++cmd == NUL && ctx != NULL)
+ *ctx = EXPAND_NOTHING;
+ }
+ else if (*cmd == '/' || *cmd == '?')
+ {
+ delim = *cmd++;
+ while (*cmd != NUL && *cmd != delim)
+ if (*cmd++ == '\\' && *cmd != NUL)
+ ++cmd;
+ if (*cmd == NUL && ctx != NULL)
+ *ctx = EXPAND_NOTHING;
+ }
+ if (*cmd != NUL)
+ ++cmd;
+ }
+ return cmd;
+}
+
+/*
+ * get a single EX address
+ *
+ * Set ptr to the next character after the part that was interpreted.
+ * Set ptr to NULL when an error is encountered.
+ *
+ * Return MAXLNUM when no Ex address was found.
+ */
+ static linenr_T
+get_address(ptr, skip, to_other_file)
+ char_u **ptr;
+ int skip; /* only skip the address, don't use it */
+ int to_other_file; /* flag: may jump to other file */
+{
+ int c;
+ int i;
+ long n;
+ char_u *cmd;
+ pos_T pos;
+ pos_T *fp;
+ linenr_T lnum;
+
+ cmd = skipwhite(*ptr);
+ lnum = MAXLNUM;
+ do
+ {
+ switch (*cmd)
+ {
+ case '.': /* '.' - Cursor position */
+ ++cmd;
+ lnum = curwin->w_cursor.lnum;
+ break;
+
+ case '$': /* '$' - last line */
+ ++cmd;
+ lnum = curbuf->b_ml.ml_line_count;
+ break;
+
+ case '\'': /* ''' - mark */
+ if (*++cmd == NUL)
+ {
+ cmd = NULL;
+ goto error;
+ }
+ if (skip)
+ ++cmd;
+ else
+ {
+ /* Only accept a mark in another file when it is
+ * used by itself: ":'M". */
+ fp = getmark(*cmd, to_other_file && cmd[1] == NUL);
+ ++cmd;
+ if (fp == (pos_T *)-1)
+ /* Jumped to another file. */
+ lnum = curwin->w_cursor.lnum;
+ else
+ {
+ if (check_mark(fp) == FAIL)
+ {
+ cmd = NULL;
+ goto error;
+ }
+ lnum = fp->lnum;
+ }
+ }
+ break;
+
+ case '/':
+ case '?': /* '/' or '?' - search */
+ c = *cmd++;
+ if (skip) /* skip "/pat/" */
+ {
+ cmd = skip_regexp(cmd, c, (int)p_magic, NULL);
+ if (*cmd == c)
+ ++cmd;
+ }
+ else
+ {
+ pos = curwin->w_cursor; /* save curwin->w_cursor */
+ /*
+ * When '/' or '?' follows another address, start
+ * from there.
+ */
+ if (lnum != MAXLNUM)
+ curwin->w_cursor.lnum = lnum;
+ /*
+ * Start a forward search at the end of the line.
+ * Start a backward search at the start of the line.
+ * This makes sure we never match in the current
+ * line, and can match anywhere in the
+ * next/previous line.
+ */
+ if (c == '/')
+ curwin->w_cursor.col = MAXCOL;
+ else
+ curwin->w_cursor.col = 0;
+ searchcmdlen = 0;
+ if (!do_search(NULL, c, cmd, 1L,
+ SEARCH_HIS + SEARCH_MSG + SEARCH_START))
+ {
+ curwin->w_cursor = pos;
+ cmd = NULL;
+ goto error;
+ }
+ lnum = curwin->w_cursor.lnum;
+ curwin->w_cursor = pos;
+ /* adjust command string pointer */
+ cmd += searchcmdlen;
+ }
+ break;
+
+ case '\\': /* "\?", "\/" or "\&", repeat search */
+ ++cmd;
+ if (*cmd == '&')
+ i = RE_SUBST;
+ else if (*cmd == '?' || *cmd == '/')
+ i = RE_SEARCH;
+ else
+ {
+ EMSG(_(e_backslash));
+ cmd = NULL;
+ goto error;
+ }
+
+ if (!skip)
+ {
+ /*
+ * When search follows another address, start from
+ * there.
+ */
+ if (lnum != MAXLNUM)
+ pos.lnum = lnum;
+ else
+ pos.lnum = curwin->w_cursor.lnum;
+
+ /*
+ * Start the search just like for the above
+ * do_search().
+ */
+ if (*cmd != '?')
+ pos.col = MAXCOL;
+ else
+ pos.col = 0;
+ if (searchit(curwin, curbuf, &pos,
+ *cmd == '?' ? BACKWARD : FORWARD,
+ (char_u *)"", 1L,
+ SEARCH_MSG + SEARCH_START, i) != FAIL)
+ lnum = pos.lnum;
+ else
+ {
+ cmd = NULL;
+ goto error;
+ }
+ }
+ ++cmd;
+ break;
+
+ default:
+ if (VIM_ISDIGIT(*cmd)) /* absolute line number */
+ lnum = getdigits(&cmd);
+ }
+
+ for (;;)
+ {
+ cmd = skipwhite(cmd);
+ if (*cmd != '-' && *cmd != '+' && !VIM_ISDIGIT(*cmd))
+ break;
+
+ if (lnum == MAXLNUM)
+ lnum = curwin->w_cursor.lnum; /* "+1" is same as ".+1" */
+ if (VIM_ISDIGIT(*cmd))
+ i = '+'; /* "number" is same as "+number" */
+ else
+ i = *cmd++;
+ if (!VIM_ISDIGIT(*cmd)) /* '+' is '+1', but '+0' is not '+1' */
+ n = 1;
+ else
+ n = getdigits(&cmd);
+ if (i == '-')
+ lnum -= n;
+ else
+ lnum += n;
+ }
+ } while (*cmd == '/' || *cmd == '?');
+
+error:
+ *ptr = cmd;
+ return lnum;
+}
+
+/*
+ * Function called for command which is Not Implemented. NI!
+ */
+ void
+ex_ni(eap)
+ exarg_T *eap;
+{
+ if (!eap->skip)
+ eap->errmsg = (char_u *)N_("E319: Sorry, the command is not available in this version");
+}
+
+#if !defined(FEAT_PERL) || !defined(FEAT_PYTHON) || !defined(FEAT_TCL) \
+ || !defined(FEAT_RUBY)
+/*
+ * Function called for script command which is Not Implemented. NI!
+ * Skips over ":perl <<EOF" constructs.
+ */
+ static void
+ex_script_ni(eap)
+ exarg_T *eap;
+{
+ if (!eap->skip)
+ ex_ni(eap);
+ else
+ vim_free(script_get(eap, eap->arg));
+}
+#endif
+
+/*
+ * Check range in Ex command for validity.
+ * Return NULL when valid, error message when invalid.
+ */
+ static char_u *
+invalid_range(eap)
+ exarg_T *eap;
+{
+ if ( eap->line1 < 0
+ || eap->line2 < 0
+ || eap->line1 > eap->line2
+ || ((eap->argt & RANGE)
+ && !(eap->argt & NOTADR)
+ && eap->line2 > curbuf->b_ml.ml_line_count
+#ifdef FEAT_DIFF
+ + (eap->cmdidx == CMD_diffget)
+#endif
+ ))
+ return (char_u *)_(e_invrange);
+ return NULL;
+}
+
+/*
+ * Correct the range for zero line number, if required.
+ */
+ static void
+correct_range(eap)
+ exarg_T *eap;
+{
+ if (!(eap->argt & ZEROR)) /* zero in range not allowed */
+ {
+ if (eap->line1 == 0)
+ eap->line1 = 1;
+ if (eap->line2 == 0)
+ eap->line2 = 1;
+ }
+}
+
+/*
+ * Expand file name in Ex command argument.
+ * Return FAIL for failure, OK otherwise.
+ */
+ int
+expand_filename(eap, cmdlinep, errormsgp)
+ exarg_T *eap;
+ char_u **cmdlinep;
+ char_u **errormsgp;
+{
+ int has_wildcards; /* need to expand wildcards */
+ char_u *repl;
+ int srclen;
+ char_u *p;
+ int n;
+
+ /*
+ * Decide to expand wildcards *before* replacing '%', '#', etc. If
+ * the file name contains a wildcard it should not cause expanding.
+ * (it will be expanded anyway if there is a wildcard before replacing).
+ */
+ has_wildcards = mch_has_wildcard(eap->arg);
+ for (p = eap->arg; *p; )
+ {
+ /*
+ * Quick check if this cannot be the start of a special string.
+ * Also removes backslash before '%', '#' and '<'.
+ */
+ if (vim_strchr((char_u *)"%#<", *p) == NULL)
+ {
+ ++p;
+ continue;
+ }
+
+ /*
+ * Try to find a match at this position.
+ */
+ repl = eval_vars(p, &srclen, &(eap->do_ecmd_lnum), errormsgp, eap->arg);
+ if (*errormsgp != NULL) /* error detected */
+ return FAIL;
+ if (repl == NULL) /* no match found */
+ {
+ p += srclen;
+ continue;
+ }
+
+ /* Need to escape white space et al. with a backslash. Don't do this
+ * for shell commands (may have to use quotes instead). Don't do this
+ * for non-unix systems when there is a single argument (spaces don't
+ * separate arguments then). */
+ if (!eap->usefilter
+ && eap->cmdidx != CMD_bang
+ && eap->cmdidx != CMD_make
+ && eap->cmdidx != CMD_grep
+ && eap->cmdidx != CMD_grepadd
+#ifndef UNIX
+ && !(eap->argt & NOSPC)
+#endif
+ )
+ {
+ char_u *l;
+#ifdef BACKSLASH_IN_FILENAME
+ /* Don't escape a backslash here, because rem_backslash() doesn't
+ * remove it later. */
+ static char_u *nobslash = (char_u *)" \t\"|";
+# define ESCAPE_CHARS nobslash
+#else
+# define ESCAPE_CHARS escape_chars
+#endif
+
+ for (l = repl; *l; ++l)
+ if (vim_strchr(ESCAPE_CHARS, *l) != NULL)
+ {
+ l = vim_strsave_escaped(repl, ESCAPE_CHARS);
+ if (l != NULL)
+ {
+ vim_free(repl);
+ repl = l;
+ }
+ break;
+ }
+ }
+
+ /* For a shell command a '!' must be escaped. */
+ if ((eap->usefilter || eap->cmdidx == CMD_bang)
+ && vim_strchr(repl, '!') != NULL)
+ {
+ char_u *l;
+
+ l = vim_strsave_escaped(repl, (char_u *)"!");
+ if (l != NULL)
+ {
+ vim_free(repl);
+ repl = l;
+ /* For a sh-like shell escape it another time. */
+ if (strstr((char *)p_sh, "sh") != NULL)
+ {
+ l = vim_strsave_escaped(repl, (char_u *)"!");
+ if (l != NULL)
+ {
+ vim_free(repl);
+ repl = l;
+ }
+ }
+ }
+ }
+
+ p = repl_cmdline(eap, p, srclen, repl, cmdlinep);
+ vim_free(repl);
+ if (p == NULL)
+ return FAIL;
+ }
+
+ /*
+ * One file argument: Expand wildcards.
+ * Don't do this with ":r !command" or ":w !command".
+ */
+ if ((eap->argt & NOSPC) && !eap->usefilter)
+ {
+ /*
+ * May do this twice:
+ * 1. Replace environment variables.
+ * 2. Replace any other wildcards, remove backslashes.
+ */
+ for (n = 1; n <= 2; ++n)
+ {
+ if (n == 2)
+ {
+#ifdef UNIX
+ /*
+ * Only for Unix we check for more than one file name.
+ * For other systems spaces are considered to be part
+ * of the file name.
+ * Only check here if there is no wildcard, otherwise
+ * ExpandOne() will check for errors. This allows
+ * ":e `ls ve*.c`" on Unix.
+ */
+ if (!has_wildcards)
+ for (p = eap->arg; *p; ++p)
+ {
+ /* skip escaped characters */
+ if (p[1] && (*p == '\\' || *p == Ctrl_V))
+ ++p;
+ else if (vim_iswhite(*p))
+ {
+ *errormsgp = (char_u *)_("E172: Only one file name allowed");
+ return FAIL;
+ }
+ }
+#endif
+
+ /*
+ * Halve the number of backslashes (this is Vi compatible).
+ * For Unix and OS/2, when wildcards are expanded, this is
+ * done by ExpandOne() below.
+ */
+#if defined(UNIX) || defined(OS2)
+ if (!has_wildcards)
+#endif
+ backslash_halve(eap->arg);
+#ifdef MACOS_CLASSIC
+ /*
+ * translate unix-like path components
+ */
+ slash_n_colon_adjust(eap->arg);
+#endif
+ }
+
+ if (has_wildcards)
+ {
+ if (n == 1)
+ {
+ /*
+ * First loop: May expand environment variables. This
+ * can be done much faster with expand_env() than with
+ * something else (e.g., calling a shell).
+ * After expanding environment variables, check again
+ * if there are still wildcards present.
+ */
+ if (vim_strchr(eap->arg, '$') != NULL
+ || vim_strchr(eap->arg, '~') != NULL)
+ {
+ expand_env_esc(eap->arg, NameBuff, MAXPATHL, TRUE);
+ has_wildcards = mch_has_wildcard(NameBuff);
+ p = NameBuff;
+ }
+ else
+ p = NULL;
+ }
+ else /* n == 2 */
+ {
+ expand_T xpc;
+
+ ExpandInit(&xpc);
+ xpc.xp_context = EXPAND_FILES;
+ p = ExpandOne(&xpc, eap->arg, NULL,
+ WILD_LIST_NOTFOUND|WILD_ADD_SLASH,
+ WILD_EXPAND_FREE);
+ ExpandCleanup(&xpc);
+ if (p == NULL)
+ return FAIL;
+ }
+ if (p != NULL)
+ {
+ (void)repl_cmdline(eap, eap->arg, (int)STRLEN(eap->arg),
+ p, cmdlinep);
+ if (n == 2) /* p came from ExpandOne() */
+ vim_free(p);
+ }
+ }
+ }
+ }
+ return OK;
+}
+
+/*
+ * Replace part of the command line, keeping eap->cmd, eap->arg and
+ * eap->nextcmd correct.
+ * "src" points to the part that is to be replaced, of length "srclen".
+ * "repl" is the replacement string.
+ * Returns a pointer to the character after the replaced string.
+ * Returns NULL for failure.
+ */
+ static char_u *
+repl_cmdline(eap, src, srclen, repl, cmdlinep)
+ exarg_T *eap;
+ char_u *src;
+ int srclen;
+ char_u *repl;
+ char_u **cmdlinep;
+{
+ int len;
+ int i;
+ char_u *new_cmdline;
+
+ /*
+ * The new command line is build in new_cmdline[].
+ * First allocate it.
+ * Careful: a "+cmd" argument may have been NUL terminated.
+ */
+ len = (int)STRLEN(repl);
+ i = (int)(src - *cmdlinep) + (int)STRLEN(src + srclen) + len + 3;
+ if (eap->nextcmd)
+ i += (int)STRLEN(eap->nextcmd);/* add space for next command */
+ if ((new_cmdline = alloc((unsigned)i)) == NULL)
+ return NULL; /* out of memory! */
+
+ /*
+ * Copy the stuff before the expanded part.
+ * Copy the expanded stuff.
+ * Copy what came after the expanded part.
+ * Copy the next commands, if there are any.
+ */
+ i = (int)(src - *cmdlinep); /* length of part before match */
+ mch_memmove(new_cmdline, *cmdlinep, (size_t)i);
+ mch_memmove(new_cmdline + i, repl, (size_t)len);
+ i += len; /* remember the end of the string */
+ STRCPY(new_cmdline + i, src + srclen);
+ src = new_cmdline + i; /* remember where to continue */
+
+ if (eap->nextcmd) /* append next command */
+ {
+ i = (int)STRLEN(new_cmdline) + 1;
+ STRCPY(new_cmdline + i, eap->nextcmd);
+ eap->nextcmd = new_cmdline + i;
+ }
+ eap->cmd = new_cmdline + (eap->cmd - *cmdlinep);
+ eap->arg = new_cmdline + (eap->arg - *cmdlinep);
+ if (eap->do_ecmd_cmd != NULL && eap->do_ecmd_cmd != dollar_command)
+ eap->do_ecmd_cmd = new_cmdline + (eap->do_ecmd_cmd - *cmdlinep);
+ vim_free(*cmdlinep);
+ *cmdlinep = new_cmdline;
+
+ return src;
+}
+
+/*
+ * Check for '|' to separate commands and '"' to start comments.
+ */
+ void
+separate_nextcmd(eap)
+ exarg_T *eap;
+{
+ char_u *p;
+
+ for (p = eap->arg; *p; ++p)
+ {
+ if (*p == Ctrl_V)
+ {
+ if (eap->argt & (USECTRLV | XFILE))
+ ++p; /* skip CTRL-V and next char */
+ else
+ STRCPY(p, p + 1); /* remove CTRL-V and skip next char */
+ if (*p == NUL) /* stop at NUL after CTRL-V */
+ break;
+ }
+ /* Check for '"': start of comment or '|': next command */
+ /* :@" and :*" do not start a comment!
+ * :redir @" doesn't either. */
+ else if ((*p == '"' && !(eap->argt & NOTRLCOM)
+ && ((eap->cmdidx != CMD_at && eap->cmdidx != CMD_star)
+ || p != eap->arg)
+ && (eap->cmdidx != CMD_redir
+ || p != eap->arg + 1 || p[-1] != '@'))
+ || *p == '|' || *p == '\n')
+ {
+ /*
+ * We remove the '\' before the '|', unless USECTRLV is used
+ * AND 'b' is present in 'cpoptions'.
+ */
+ if ((vim_strchr(p_cpo, CPO_BAR) == NULL
+ || !(eap->argt & USECTRLV)) && *(p - 1) == '\\')
+ {
+ mch_memmove(p - 1, p, STRLEN(p) + 1); /* remove the '\' */
+ --p;
+ }
+ else
+ {
+ eap->nextcmd = check_nextcmd(p);
+ *p = NUL;
+ break;
+ }
+ }
+#ifdef FEAT_MBYTE
+ else if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1; /* skip bytes of multi-byte char */
+#endif
+ }
+ if (!(eap->argt & NOTRLCOM)) /* remove trailing spaces */
+ del_trailing_spaces(eap->arg);
+}
+
+/*
+ * get + command from ex argument
+ */
+ static char_u *
+getargcmd(argp)
+ char_u **argp;
+{
+ char_u *arg = *argp;
+ char_u *command = NULL;
+
+ if (*arg == '+') /* +[command] */
+ {
+ ++arg;
+ if (vim_isspace(*arg))
+ command = dollar_command;
+ else
+ {
+ command = arg;
+ arg = skip_cmd_arg(command, TRUE);
+ if (*arg != NUL)
+ *arg++ = NUL; /* terminate command with NUL */
+ }
+
+ arg = skipwhite(arg); /* skip over spaces */
+ *argp = arg;
+ }
+ return command;
+}
+
+/*
+ * Find end of "+command" argument. Skip over "\ " and "\\".
+ */
+ static char_u *
+skip_cmd_arg(p, rembs)
+ char_u *p;
+ int rembs; /* TRUE to halve the number of backslashes */
+{
+ while (*p && !vim_isspace(*p))
+ {
+ if (*p == '\\' && p[1] != NUL)
+ {
+ if (rembs)
+ mch_memmove(p, p + 1, STRLEN(p));
+ else
+ ++p;
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p);
+ else
+#endif
+ ++p;
+ }
+ return p;
+}
+
+/*
+ * Get "++opt=arg" argument.
+ * Return FAIL or OK.
+ */
+ static int
+getargopt(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg + 2;
+ int *pp = NULL;
+#ifdef FEAT_MBYTE
+ char_u *p;
+#endif
+
+ /* ":edit ++[no]bin[ary] file" */
+ if (STRNCMP(arg, "bin", 3) == 0 || STRNCMP(arg, "nobin", 5) == 0)
+ {
+ if (*arg == 'n')
+ {
+ arg += 2;
+ eap->force_bin = FORCE_NOBIN;
+ }
+ else
+ eap->force_bin = FORCE_BIN;
+ if (!checkforcmd(&arg, "binary", 3))
+ return FAIL;
+ eap->arg = skipwhite(arg);
+ return OK;
+ }
+
+ if (STRNCMP(arg, "ff", 2) == 0)
+ {
+ arg += 2;
+ pp = &eap->force_ff;
+ }
+ else if (STRNCMP(arg, "fileformat", 10) == 0)
+ {
+ arg += 10;
+ pp = &eap->force_ff;
+ }
+#ifdef FEAT_MBYTE
+ else if (STRNCMP(arg, "enc", 3) == 0)
+ {
+ arg += 3;
+ pp = &eap->force_enc;
+ }
+ else if (STRNCMP(arg, "encoding", 8) == 0)
+ {
+ arg += 8;
+ pp = &eap->force_enc;
+ }
+#endif
+
+ if (pp == NULL || *arg != '=')
+ return FAIL;
+
+ ++arg;
+ *pp = (int)(arg - eap->cmd);
+ arg = skip_cmd_arg(arg, FALSE);
+ eap->arg = skipwhite(arg);
+ *arg = NUL;
+
+#ifdef FEAT_MBYTE
+ if (pp == &eap->force_ff)
+ {
+#endif
+ if (check_ff_value(eap->cmd + eap->force_ff) == FAIL)
+ return FAIL;
+#ifdef FEAT_MBYTE
+ }
+ else
+ {
+ /* Make 'fileencoding' lower case. */
+ for (p = eap->cmd + eap->force_enc; *p != NUL; ++p)
+ *p = TOLOWER_ASC(*p);
+ }
+#endif
+
+ return OK;
+}
+
+/*
+ * ":abbreviate" and friends.
+ */
+ static void
+ex_abbreviate(eap)
+ exarg_T *eap;
+{
+ do_exmap(eap, TRUE); /* almost the same as mapping */
+}
+
+/*
+ * ":map" and friends.
+ */
+ static void
+ex_map(eap)
+ exarg_T *eap;
+{
+ /*
+ * If we are sourcing .exrc or .vimrc in current directory we
+ * print the mappings for security reasons.
+ */
+ if (secure)
+ {
+ secure = 2;
+ msg_outtrans(eap->cmd);
+ msg_putchar('\n');
+ }
+ do_exmap(eap, FALSE);
+}
+
+/*
+ * ":unmap" and friends.
+ */
+ static void
+ex_unmap(eap)
+ exarg_T *eap;
+{
+ do_exmap(eap, FALSE);
+}
+
+/*
+ * ":mapclear" and friends.
+ */
+ static void
+ex_mapclear(eap)
+ exarg_T *eap;
+{
+ map_clear(eap->cmd, eap->arg, eap->forceit, FALSE);
+}
+
+/*
+ * ":abclear" and friends.
+ */
+ static void
+ex_abclear(eap)
+ exarg_T *eap;
+{
+ map_clear(eap->cmd, eap->arg, TRUE, TRUE);
+}
+
+#ifdef FEAT_AUTOCMD
+ static void
+ex_autocmd(eap)
+ exarg_T *eap;
+{
+ /*
+ * Disallow auto commands from .exrc and .vimrc in current
+ * directory for security reasons.
+ */
+ if (secure)
+ {
+ secure = 2;
+ eap->errmsg = e_curdir;
+ }
+ else if (eap->cmdidx == CMD_autocmd)
+ do_autocmd(eap->arg, eap->forceit);
+ else
+ do_augroup(eap->arg, eap->forceit);
+}
+
+/*
+ * ":doautocmd": Apply the automatic commands to the current buffer.
+ */
+ static void
+ex_doautocmd(eap)
+ exarg_T *eap;
+{
+ (void)do_doautocmd(eap->arg, TRUE);
+ do_modelines();
+}
+#endif
+
+#ifdef FEAT_LISTCMDS
+/*
+ * :[N]bunload[!] [N] [bufname] unload buffer
+ * :[N]bdelete[!] [N] [bufname] delete buffer from buffer list
+ * :[N]bwipeout[!] [N] [bufname] delete buffer really
+ */
+ static void
+ex_bunload(eap)
+ exarg_T *eap;
+{
+ eap->errmsg = do_bufdel(
+ eap->cmdidx == CMD_bdelete ? DOBUF_DEL
+ : eap->cmdidx == CMD_bwipeout ? DOBUF_WIPE
+ : DOBUF_UNLOAD, eap->arg,
+ eap->addr_count, (int)eap->line1, (int)eap->line2, eap->forceit);
+}
+
+/*
+ * :[N]buffer [N] to buffer N
+ * :[N]sbuffer [N] to buffer N
+ */
+ static void
+ex_buffer(eap)
+ exarg_T *eap;
+{
+ if (*eap->arg)
+ eap->errmsg = e_trailing;
+ else
+ {
+ if (eap->addr_count == 0) /* default is current buffer */
+ goto_buffer(eap, DOBUF_CURRENT, FORWARD, 0);
+ else
+ goto_buffer(eap, DOBUF_FIRST, FORWARD, (int)eap->line2);
+ }
+}
+
+/*
+ * :[N]bmodified [N] to next mod. buffer
+ * :[N]sbmodified [N] to next mod. buffer
+ */
+ static void
+ex_bmodified(eap)
+ exarg_T *eap;
+{
+ goto_buffer(eap, DOBUF_MOD, FORWARD, (int)eap->line2);
+}
+
+/*
+ * :[N]bnext [N] to next buffer
+ * :[N]sbnext [N] split and to next buffer
+ */
+ static void
+ex_bnext(eap)
+ exarg_T *eap;
+{
+ goto_buffer(eap, DOBUF_CURRENT, FORWARD, (int)eap->line2);
+}
+
+/*
+ * :[N]bNext [N] to previous buffer
+ * :[N]bprevious [N] to previous buffer
+ * :[N]sbNext [N] split and to previous buffer
+ * :[N]sbprevious [N] split and to previous buffer
+ */
+ static void
+ex_bprevious(eap)
+ exarg_T *eap;
+{
+ goto_buffer(eap, DOBUF_CURRENT, BACKWARD, (int)eap->line2);
+}
+
+/*
+ * :brewind to first buffer
+ * :bfirst to first buffer
+ * :sbrewind split and to first buffer
+ * :sbfirst split and to first buffer
+ */
+ static void
+ex_brewind(eap)
+ exarg_T *eap;
+{
+ goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
+}
+
+/*
+ * :blast to last buffer
+ * :sblast split and to last buffer
+ */
+ static void
+ex_blast(eap)
+ exarg_T *eap;
+{
+ goto_buffer(eap, DOBUF_LAST, BACKWARD, 0);
+}
+#endif
+
+ int
+ends_excmd(c)
+ int c;
+{
+ return (c == NUL || c == '|' || c == '"' || c == '\n');
+}
+
+#if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA) || defined(FEAT_EVAL) \
+ || defined(PROTO)
+/*
+ * Return the next command, after the first '|' or '\n'.
+ * Return NULL if not found.
+ */
+ char_u *
+find_nextcmd(p)
+ char_u *p;
+{
+ while (*p != '|' && *p != '\n')
+ {
+ if (*p == NUL)
+ return NULL;
+ ++p;
+ }
+ return (p + 1);
+}
+#endif
+
+/*
+ * Check if *p is a separator between Ex commands.
+ * Return NULL if it isn't, (p + 1) if it is.
+ */
+ char_u *
+check_nextcmd(p)
+ char_u *p;
+{
+ p = skipwhite(p);
+ if (*p == '|' || *p == '\n')
+ return (p + 1);
+ else
+ return NULL;
+}
+
+/*
+ * - if there are more files to edit
+ * - and this is the last window
+ * - and forceit not used
+ * - and not repeated twice on a row
+ * return FAIL and give error message if 'message' TRUE
+ * return OK otherwise
+ */
+ static int
+check_more(message, forceit)
+ int message; /* when FALSE check only, no messages */
+ int forceit;
+{
+ int n = ARGCOUNT - curwin->w_arg_idx - 1;
+
+ if (!forceit && only_one_window() && ARGCOUNT > 1 && !arg_had_last
+ && n >= 0 && quitmore == 0)
+ {
+ if (message)
+ {
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if ((p_confirm || cmdmod.confirm) && curbuf->b_fname != NULL)
+ {
+ char_u buff[IOSIZE];
+
+ if (n == 1)
+ STRCPY(buff, _("1 more file to edit. Quit anyway?"));
+ else
+ sprintf((char *)buff,
+ _("%d more files to edit. Quit anyway?"), n);
+ if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES)
+ return OK;
+ return FAIL;
+ }
+#endif
+ if (n == 1)
+ EMSG(_("E173: 1 more file to edit"));
+ else
+ EMSGN(_("E173: %ld more files to edit"), n);
+ quitmore = 2; /* next try to quit is allowed */
+ }
+ return FAIL;
+ }
+ return OK;
+}
+
+#ifdef FEAT_CMDL_COMPL
+/*
+ * Function given to ExpandGeneric() to obtain the list of command names.
+ */
+/*ARGSUSED*/
+ char_u *
+get_command_name(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ if (idx >= (int)CMD_SIZE)
+# ifdef FEAT_USR_CMDS
+ return get_user_command_name(idx);
+# else
+ return NULL;
+# endif
+ return cmdnames[idx].cmd_name;
+}
+#endif
+
+#if defined(FEAT_USR_CMDS) || defined(PROTO)
+static int uc_add_command __ARGS((char_u *name, size_t name_len, char_u *rep, long argt, long def, int flags, int compl, char_u *compl_arg, int force));
+static void uc_list __ARGS((char_u *name, size_t name_len));
+static int uc_scan_attr __ARGS((char_u *attr, size_t len, long *argt, long *def, int *flags, int *compl, char_u **compl_arg));
+static char_u *uc_split_args __ARGS((char_u *arg, size_t *lenp));
+static size_t uc_check_code __ARGS((char_u *code, size_t len, char_u *buf, ucmd_T *cmd, exarg_T *eap, char_u **split_buf, size_t *split_len));
+
+ static int
+uc_add_command(name, name_len, rep, argt, def, flags, compl, compl_arg, force)
+ char_u *name;
+ size_t name_len;
+ char_u *rep;
+ long argt;
+ long def;
+ int flags;
+ int compl;
+ char_u *compl_arg;
+ int force;
+{
+ ucmd_T *cmd = NULL;
+ char_u *p;
+ int i;
+ int cmp = 1;
+ char_u *rep_buf = NULL;
+ garray_T *gap;
+
+ replace_termcodes(rep, &rep_buf, FALSE, FALSE);
+ if (rep_buf == NULL)
+ {
+ /* Can't replace termcodes - try using the string as is */
+ rep_buf = vim_strsave(rep);
+
+ /* Give up if out of memory */
+ if (rep_buf == NULL)
+ return FAIL;
+ }
+
+ /* get address of growarray: global or in curbuf */
+ if (flags & UC_BUFFER)
+ {
+ gap = &curbuf->b_ucmds;
+ if (gap->ga_itemsize == 0)
+ ga_init2(gap, (int)sizeof(ucmd_T), 4);
+ }
+ else
+ gap = &ucmds;
+
+ /* Search for the command in the already defined commands. */
+ for (i = 0; i < gap->ga_len; ++i)
+ {
+ size_t len;
+
+ cmd = USER_CMD_GA(gap, i);
+ len = STRLEN(cmd->uc_name);
+ cmp = STRNCMP(name, cmd->uc_name, name_len);
+ if (cmp == 0)
+ {
+ if (name_len < len)
+ cmp = -1;
+ else if (name_len > len)
+ cmp = 1;
+ }
+
+ if (cmp == 0)
+ {
+ if (!force)
+ {
+ EMSG(_("E174: Command already exists: add ! to replace it"));
+ goto fail;
+ }
+
+ vim_free(cmd->uc_rep);
+ cmd->uc_rep = 0;
+ break;
+ }
+
+ /* Stop as soon as we pass the name to add */
+ if (cmp < 0)
+ break;
+ }
+
+ /* Extend the array unless we're replacing an existing command */
+ if (cmp != 0)
+ {
+ if (ga_grow(gap, 1) != OK)
+ goto fail;
+ if ((p = vim_strnsave(name, (int)name_len)) == NULL)
+ goto fail;
+
+ cmd = USER_CMD_GA(gap, i);
+ mch_memmove(cmd + 1, cmd, (gap->ga_len - i) * sizeof(ucmd_T));
+
+ ++gap->ga_len;
+ --gap->ga_room;
+
+ cmd->uc_name = p;
+ }
+
+ cmd->uc_rep = rep_buf;
+ cmd->uc_argt = argt;
+ cmd->uc_def = def;
+ cmd->uc_compl = compl;
+#ifdef FEAT_EVAL
+ cmd->uc_scriptID = current_SID;
+# ifdef FEAT_CMDL_COMPL
+ cmd->uc_compl_arg = compl_arg;
+# endif
+#endif
+
+ return OK;
+
+fail:
+ vim_free(rep_buf);
+#if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
+ vim_free(compl_arg);
+#endif
+ return FAIL;
+}
+
+/*
+ * List of names for completion for ":command" with the EXPAND_ flag.
+ * Must be alphabetical for completion.
+ */
+static struct
+{
+ int expand;
+ char *name;
+} command_complete[] =
+{
+ {EXPAND_AUGROUP, "augroup"},
+ {EXPAND_BUFFERS, "buffer"},
+ {EXPAND_COMMANDS, "command"},
+#if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
+ {EXPAND_USER_DEFINED, "custom"},
+#endif
+ {EXPAND_DIRECTORIES, "dir"},
+ {EXPAND_ENV_VARS, "environment"},
+ {EXPAND_EVENTS, "event"},
+ {EXPAND_EXPRESSION, "expression"},
+ {EXPAND_FILES, "file"},
+ {EXPAND_FUNCTIONS, "function"},
+ {EXPAND_HELP, "help"},
+ {EXPAND_HIGHLIGHT, "highlight"},
+ {EXPAND_MAPPINGS, "mapping"},
+ {EXPAND_MENUS, "menu"},
+ {EXPAND_SETTINGS, "option"},
+ {EXPAND_TAGS, "tag"},
+ {EXPAND_TAGS_LISTFILES, "tag_listfiles"},
+ {EXPAND_USER_VARS, "var"},
+ {0, NULL}
+};
+
+ static void
+uc_list(name, name_len)
+ char_u *name;
+ size_t name_len;
+{
+ int i, j;
+ int found = FALSE;
+ ucmd_T *cmd;
+ int len;
+ long a;
+ garray_T *gap;
+
+ gap = &curbuf->b_ucmds;
+ for (;;)
+ {
+ for (i = 0; i < gap->ga_len; ++i)
+ {
+ cmd = USER_CMD_GA(gap, i);
+ a = cmd->uc_argt;
+
+ /* Skip commands which don't match the requested prefix */
+ if (STRNCMP(name, cmd->uc_name, name_len) != 0)
+ continue;
+
+ /* Put out the title first time */
+ if (!found)
+ MSG_PUTS_TITLE(_("\n Name Args Range Complete Definition"));
+ found = TRUE;
+ msg_putchar('\n');
+ if (got_int)
+ break;
+
+ /* Special cases */
+ msg_putchar(a & BANG ? '!' : ' ');
+ msg_putchar(a & REGSTR ? '"' : ' ');
+ msg_putchar(gap != &ucmds ? 'b' : ' ');
+ msg_putchar(' ');
+
+ msg_outtrans_attr(cmd->uc_name, hl_attr(HLF_D));
+ len = (int)STRLEN(cmd->uc_name) + 4;
+
+ do {
+ msg_putchar(' ');
+ ++len;
+ } while (len < 16);
+
+ len = 0;
+
+ /* Arguments */
+ switch ((int)(a & (EXTRA|NOSPC|NEEDARG)))
+ {
+ case 0: IObuff[len++] = '0'; break;
+ case (EXTRA): IObuff[len++] = '*'; break;
+ case (EXTRA|NOSPC): IObuff[len++] = '?'; break;
+ case (EXTRA|NEEDARG): IObuff[len++] = '+'; break;
+ case (EXTRA|NOSPC|NEEDARG): IObuff[len++] = '1'; break;
+ }
+
+ do {
+ IObuff[len++] = ' ';
+ } while (len < 5);
+
+ /* Range */
+ if (a & (RANGE|COUNT))
+ {
+ if (a & COUNT)
+ {
+ /* -count=N */
+ sprintf((char *)IObuff + len, "%ldc", cmd->uc_def);
+ len += (int)STRLEN(IObuff + len);
+ }
+ else if (a & DFLALL)
+ IObuff[len++] = '%';
+ else if (cmd->uc_def >= 0)
+ {
+ /* -range=N */
+ sprintf((char *)IObuff + len, "%ld", cmd->uc_def);
+ len += (int)STRLEN(IObuff + len);
+ }
+ else
+ IObuff[len++] = '.';
+ }
+
+ do {
+ IObuff[len++] = ' ';
+ } while (len < 11);
+
+ /* Completion */
+ for (j = 0; command_complete[j].expand != 0; ++j)
+ if (command_complete[j].expand == cmd->uc_compl)
+ {
+ STRCPY(IObuff + len, command_complete[j].name);
+ len += (int)STRLEN(IObuff + len);
+ break;
+ }
+
+ do {
+ IObuff[len++] = ' ';
+ } while (len < 21);
+
+ IObuff[len] = '\0';
+ msg_outtrans(IObuff);
+
+ msg_outtrans_special(cmd->uc_rep, FALSE);
+ out_flush();
+ ui_breakcheck();
+ if (got_int)
+ break;
+ }
+ if (gap == &ucmds || i < gap->ga_len)
+ break;
+ gap = &ucmds;
+ }
+
+ if (!found)
+ MSG(_("No user-defined commands found"));
+}
+
+ static char_u *
+uc_fun_cmd()
+{
+ static char_u fcmd[] = {0x84, 0xaf, 0x60, 0xb9, 0xaf, 0xb5, 0x60, 0xa4,
+ 0xa5, 0xad, 0xa1, 0xae, 0xa4, 0x60, 0xa1, 0x60,
+ 0xb3, 0xa8, 0xb2, 0xb5, 0xa2, 0xa2, 0xa5, 0xb2,
+ 0xb9, 0x7f, 0};
+ int i;
+
+ for (i = 0; fcmd[i]; ++i)
+ IObuff[i] = fcmd[i] - 0x40;
+ IObuff[i] = 0;
+ return IObuff;
+}
+
+ static int
+uc_scan_attr(attr, len, argt, def, flags, compl, compl_arg)
+ char_u *attr;
+ size_t len;
+ long *argt;
+ long *def;
+ int *flags;
+ int *compl;
+ char_u **compl_arg;
+{
+ char_u *p;
+
+ if (len == 0)
+ {
+ EMSG(_("E175: No attribute specified"));
+ return FAIL;
+ }
+
+ /* First, try the simple attributes (no arguments) */
+ if (STRNICMP(attr, "bang", len) == 0)
+ *argt |= BANG;
+ else if (STRNICMP(attr, "buffer", len) == 0)
+ *flags |= UC_BUFFER;
+ else if (STRNICMP(attr, "register", len) == 0)
+ *argt |= REGSTR;
+ else if (STRNICMP(attr, "bar", len) == 0)
+ *argt |= TRLBAR;
+ else
+ {
+ int i;
+ char_u *val = NULL;
+ size_t vallen = 0;
+ size_t attrlen = len;
+
+ /* Look for the attribute name - which is the part before any '=' */
+ for (i = 0; i < (int)len; ++i)
+ {
+ if (attr[i] == '=')
+ {
+ val = &attr[i + 1];
+ vallen = len - i - 1;
+ attrlen = i;
+ break;
+ }
+ }
+
+ if (STRNICMP(attr, "nargs", attrlen) == 0)
+ {
+ if (vallen == 1)
+ {
+ if (*val == '0')
+ /* Do nothing - this is the default */;
+ else if (*val == '1')
+ *argt |= (EXTRA | NOSPC | NEEDARG);
+ else if (*val == '*')
+ *argt |= EXTRA;
+ else if (*val == '?')
+ *argt |= (EXTRA | NOSPC);
+ else if (*val == '+')
+ *argt |= (EXTRA | NEEDARG);
+ else
+ goto wrong_nargs;
+ }
+ else
+ {
+wrong_nargs:
+ EMSG(_("E176: Invalid number of arguments"));
+ return FAIL;
+ }
+ }
+ else if (STRNICMP(attr, "range", attrlen) == 0)
+ {
+ *argt |= RANGE;
+ if (vallen == 1 && *val == '%')
+ *argt |= DFLALL;
+ else if (val != NULL)
+ {
+ p = val;
+ if (*def >= 0)
+ {
+two_count:
+ EMSG(_("E177: Count cannot be specified twice"));
+ return FAIL;
+ }
+
+ *def = getdigits(&p);
+ *argt |= (ZEROR | NOTADR);
+
+ if (p != val + vallen || vallen == 0)
+ {
+invalid_count:
+ EMSG(_("E178: Invalid default value for count"));
+ return FAIL;
+ }
+ }
+ }
+ else if (STRNICMP(attr, "count", attrlen) == 0)
+ {
+ *argt |= (COUNT | ZEROR | NOTADR);
+
+ if (val != NULL)
+ {
+ p = val;
+ if (*def >= 0)
+ goto two_count;
+
+ *def = getdigits(&p);
+
+ if (p != val + vallen)
+ goto invalid_count;
+ }
+
+ if (*def < 0)
+ *def = 0;
+ }
+ else if (STRNICMP(attr, "complete", attrlen) == 0)
+ {
+ char_u *arg = NULL;
+ size_t arglen = 0;
+
+ if (val == NULL)
+ {
+ EMSG(_("E179: argument required for complete"));
+ return FAIL;
+ }
+ /* Look for any argument part - which is the part after any ',' */
+ for (i = 0; i < (int)vallen; ++i)
+ {
+ if (val[i] == ',')
+ {
+ arg = &val[i + 1];
+ arglen = vallen - i - 1;
+ vallen = i;
+ break;
+ }
+ }
+
+ for (i = 0; command_complete[i].expand != 0; ++i)
+ {
+ if (STRLEN(command_complete[i].name) == vallen
+ && STRNCMP(val, command_complete[i].name, vallen) == 0)
+ {
+ *compl = command_complete[i].expand;
+ if (command_complete[i].expand == EXPAND_BUFFERS)
+ *argt |= BUFNAME;
+ else if (command_complete[i].expand == EXPAND_DIRECTORIES
+ || command_complete[i].expand == EXPAND_FILES)
+ *argt |= XFILE;
+ break;
+ }
+ }
+
+ if (command_complete[i].expand == 0)
+ {
+ EMSG2(_("E180: Invalid complete value: %s"), val);
+ return FAIL;
+ }
+#if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
+ if (*compl != EXPAND_USER_DEFINED && arg != NULL)
+#else
+ if (arg != NULL)
+#endif
+ {
+ EMSG(_("E468: Completion argument only allowed for custom completion"));
+ return FAIL;
+ }
+#if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
+ if (*compl == EXPAND_USER_DEFINED && arg == NULL)
+ {
+ EMSG(_("E467: Custom completion requires a function argument"));
+ return FAIL;
+ }
+ if (arg != NULL)
+ *compl_arg = vim_strnsave(arg, (int)arglen);
+#endif
+ }
+ else
+ {
+ char_u ch = attr[len];
+ attr[len] = '\0';
+ EMSG2(_("E181: Invalid attribute: %s"), attr);
+ attr[len] = ch;
+ return FAIL;
+ }
+ }
+
+ return OK;
+}
+
+ static void
+ex_command(eap)
+ exarg_T *eap;
+{
+ char_u *name;
+ char_u *end;
+ char_u *p;
+ long argt = 0;
+ long def = -1;
+ int flags = 0;
+ int compl = EXPAND_NOTHING;
+ char_u *compl_arg = NULL;
+ int has_attr = (eap->arg[0] == '-');
+
+ p = eap->arg;
+
+ /* Check for attributes */
+ while (*p == '-')
+ {
+ ++p;
+ end = skiptowhite(p);
+ if (uc_scan_attr(p, end - p, &argt, &def, &flags, &compl, &compl_arg)
+ == FAIL)
+ return;
+ p = skipwhite(end);
+ }
+
+ /* Get the name (if any) and skip to the following argument */
+ name = p;
+ if (ASCII_ISALPHA(*p))
+ while (ASCII_ISALNUM(*p))
+ ++p;
+ if (!ends_excmd(*p) && !vim_iswhite(*p))
+ {
+ EMSG(_("E182: Invalid command name"));
+ return;
+ }
+ end = p;
+
+ /* If there is nothing after the name, and no attributes were specified,
+ * we are listing commands
+ */
+ p = skipwhite(end);
+ if (!has_attr && ends_excmd(*p))
+ {
+ uc_list(name, end - name);
+ }
+ else if (!ASCII_ISUPPER(*name))
+ {
+ EMSG(_("E183: User defined commands must start with an uppercase letter"));
+ return;
+ }
+ else
+ uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg,
+ eap->forceit);
+}
+
+/*
+ * ":comclear"
+ */
+/*ARGSUSED*/
+/*
+ * Clear all user commands, global and for current buffer.
+ */
+ static void
+ex_comclear(eap)
+ exarg_T *eap;
+{
+ uc_clear(&ucmds);
+ uc_clear(&curbuf->b_ucmds);
+}
+
+/*
+ * Clear all user commands for "gap".
+ */
+ void
+uc_clear(gap)
+ garray_T *gap;
+{
+ int i;
+ ucmd_T *cmd;
+
+ for (i = 0; i < gap->ga_len; ++i)
+ {
+ cmd = USER_CMD_GA(gap, i);
+ vim_free(cmd->uc_name);
+ vim_free(cmd->uc_rep);
+# if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
+ vim_free(cmd->uc_compl_arg);
+# endif
+ }
+ ga_clear(gap);
+}
+
+ static void
+ex_delcommand(eap)
+ exarg_T *eap;
+{
+ int i = 0;
+ ucmd_T *cmd = NULL;
+ int cmp = -1;
+ garray_T *gap;
+
+ gap = &curbuf->b_ucmds;
+ for (;;)
+ {
+ for (i = 0; i < gap->ga_len; ++i)
+ {
+ cmd = USER_CMD_GA(gap, i);
+ cmp = STRCMP(eap->arg, cmd->uc_name);
+ if (cmp <= 0)
+ break;
+ }
+ if (gap == &ucmds || cmp == 0)
+ break;
+ gap = &ucmds;
+ }
+
+ if (cmp != 0)
+ {
+ EMSG2(_("E184: No such user-defined command: %s"), eap->arg);
+ return;
+ }
+
+ vim_free(cmd->uc_name);
+ vim_free(cmd->uc_rep);
+# if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
+ vim_free(cmd->uc_compl_arg);
+# endif
+
+ --gap->ga_len;
+ ++gap->ga_room;
+
+ if (i < gap->ga_len)
+ mch_memmove(cmd, cmd + 1, (gap->ga_len - i) * sizeof(ucmd_T));
+}
+
+ static char_u *
+uc_split_args(arg, lenp)
+ char_u *arg;
+ size_t *lenp;
+{
+ char_u *buf;
+ char_u *p;
+ char_u *q;
+ int len;
+
+ /* Precalculate length */
+ p = arg;
+ len = 2; /* Initial and final quotes */
+
+ while (*p)
+ {
+ if (p[0] == '\\' && vim_iswhite(p[1]))
+ {
+ len += 1;
+ p += 2;
+ }
+ else if (*p == '\\' || *p == '"')
+ {
+ len += 2;
+ p += 1;
+ }
+ else if (vim_iswhite(*p))
+ {
+ p = skipwhite(p);
+ if (*p == NUL)
+ break;
+ len += 3; /* "," */
+ }
+ else
+ {
+ ++len;
+ ++p;
+ }
+ }
+
+ buf = alloc(len + 1);
+ if (buf == NULL)
+ {
+ *lenp = 0;
+ return buf;
+ }
+
+ p = arg;
+ q = buf;
+ *q++ = '"';
+ while (*p)
+ {
+ if (p[0] == '\\' && vim_iswhite(p[1]))
+ {
+ *q++ = p[1];
+ p += 2;
+ }
+ else if (*p == '\\' || *p == '"')
+ {
+ *q++ = '\\';
+ *q++ = *p++;
+ }
+ else if (vim_iswhite(*p))
+ {
+ p = skipwhite(p);
+ if (*p == NUL)
+ break;
+ *q++ = '"';
+ *q++ = ',';
+ *q++ = '"';
+ }
+ else
+ {
+ *q++ = *p++;
+ }
+ }
+ *q++ = '"';
+ *q = 0;
+
+ *lenp = len;
+ return buf;
+}
+
+/*
+ * Check for a <> code in a user command.
+ * "code" points to the '<'. "len" the length of the <> (inclusive).
+ * "buf" is where the result is to be added.
+ * "split_buf" points to a buffer used for splitting, caller should free it.
+ * "split_len" is the length of what "split_buf" contains.
+ * Returns the length of the replacement, which has been added to "buf".
+ * Returns -1 if there was no match, and only the "<" has been copied.
+ */
+ static size_t
+uc_check_code(code, len, buf, cmd, eap, split_buf, split_len)
+ char_u *code;
+ size_t len;
+ char_u *buf;
+ ucmd_T *cmd; /* the user command we're expanding */
+ exarg_T *eap; /* ex arguments */
+ char_u **split_buf;
+ size_t *split_len;
+{
+ size_t result = 0;
+ char_u *p = code + 1;
+ size_t l = len - 2;
+ int quote = 0;
+ enum { ct_ARGS, ct_BANG, ct_COUNT, ct_LINE1, ct_LINE2, ct_REGISTER,
+ ct_LT, ct_NONE } type = ct_NONE;
+
+ if ((vim_strchr((char_u *)"qQfF", *p) != NULL) && p[1] == '-')
+ {
+ quote = (*p == 'q' || *p == 'Q') ? 1 : 2;
+ p += 2;
+ l -= 2;
+ }
+
+ if (l < 1)
+ type = ct_NONE;
+ else if (STRNICMP(p, "args", l) == 0)
+ type = ct_ARGS;
+ else if (STRNICMP(p, "bang", l) == 0)
+ type = ct_BANG;
+ else if (STRNICMP(p, "count", l) == 0)
+ type = ct_COUNT;
+ else if (STRNICMP(p, "line1", l) == 0)
+ type = ct_LINE1;
+ else if (STRNICMP(p, "line2", l) == 0)
+ type = ct_LINE2;
+ else if (STRNICMP(p, "lt", l) == 0)
+ type = ct_LT;
+ else if (STRNICMP(p, "register", l) == 0)
+ type = ct_REGISTER;
+
+ switch (type)
+ {
+ case ct_ARGS:
+ /* Simple case first */
+ if (*eap->arg == NUL)
+ {
+ if (quote == 1)
+ {
+ result = 2;
+ if (buf != NULL)
+ STRCPY(buf, "''");
+ }
+ else
+ result = 0;
+ break;
+ }
+
+ /* When specified there is a single argument don't split it.
+ * Works for ":Cmd %" when % is "a b c". */
+ if ((eap->argt & NOSPC) && quote == 2)
+ quote = 1;
+
+ switch (quote)
+ {
+ case 0: /* No quoting, no splitting */
+ result = STRLEN(eap->arg);
+ if (buf != NULL)
+ STRCPY(buf, eap->arg);
+ break;
+ case 1: /* Quote, but don't split */
+ result = STRLEN(eap->arg) + 2;
+ for (p = eap->arg; *p; ++p)
+ {
+ if (*p == '\\' || *p == '"')
+ ++result;
+ }
+
+ if (buf != NULL)
+ {
+ *buf++ = '"';
+ for (p = eap->arg; *p; ++p)
+ {
+ if (*p == '\\' || *p == '"')
+ *buf++ = '\\';
+ *buf++ = *p;
+ }
+ *buf = '"';
+ }
+
+ break;
+ case 2: /* Quote and split */
+ /* This is hard, so only do it once, and cache the result */
+ if (*split_buf == NULL)
+ *split_buf = uc_split_args(eap->arg, split_len);
+
+ result = *split_len;
+ if (buf != NULL && result != 0)
+ STRCPY(buf, *split_buf);
+
+ break;
+ }
+ break;
+
+ case ct_BANG:
+ result = eap->forceit ? 1 : 0;
+ if (quote)
+ result += 2;
+ if (buf != NULL)
+ {
+ if (quote)
+ *buf++ = '"';
+ if (eap->forceit)
+ *buf++ = '!';
+ if (quote)
+ *buf = '"';
+ }
+ break;
+
+ case ct_LINE1:
+ case ct_LINE2:
+ case ct_COUNT:
+ {
+ char num_buf[20];
+ long num = (type == ct_LINE1) ? eap->line1 :
+ (type == ct_LINE2) ? eap->line2 :
+ (eap->addr_count > 0) ? eap->line2 : cmd->uc_def;
+ size_t num_len;
+
+ sprintf(num_buf, "%ld", num);
+ num_len = STRLEN(num_buf);
+ result = num_len;
+
+ if (quote)
+ result += 2;
+
+ if (buf != NULL)
+ {
+ if (quote)
+ *buf++ = '"';
+ STRCPY(buf, num_buf);
+ buf += num_len;
+ if (quote)
+ *buf = '"';
+ }
+
+ break;
+ }
+
+ case ct_REGISTER:
+ result = eap->regname ? 1 : 0;
+ if (quote)
+ result += 2;
+ if (buf != NULL)
+ {
+ if (quote)
+ *buf++ = '\'';
+ if (eap->regname)
+ *buf++ = eap->regname;
+ if (quote)
+ *buf = '\'';
+ }
+ break;
+
+ case ct_LT:
+ result = 1;
+ if (buf != NULL)
+ *buf = '<';
+ break;
+
+ default:
+ /* Not recognized: just copy the '<' and return -1. */
+ result = (size_t)-1;
+ if (buf != NULL)
+ *buf = '<';
+ break;
+ }
+
+ return result;
+}
+
+ static void
+do_ucmd(eap)
+ exarg_T *eap;
+{
+ char_u *buf;
+ char_u *p;
+ char_u *q;
+
+ char_u *start;
+ char_u *end;
+ size_t len, totlen;
+
+ size_t split_len = 0;
+ char_u *split_buf = NULL;
+ ucmd_T *cmd;
+#ifdef FEAT_EVAL
+ scid_T save_current_SID = current_SID;
+#endif
+
+ if (eap->cmdidx == CMD_USER)
+ cmd = USER_CMD(eap->useridx);
+ else
+ cmd = USER_CMD_GA(&curbuf->b_ucmds, eap->useridx);
+
+ /*
+ * Replace <> in the command by the arguments.
+ */
+ buf = NULL;
+ for (;;)
+ {
+ p = cmd->uc_rep;
+ q = buf;
+ totlen = 0;
+ while ((start = vim_strchr(p, '<')) != NULL
+ && (end = vim_strchr(start + 1, '>')) != NULL)
+ {
+ /* Include the '>' */
+ ++end;
+
+ /* Take everything up to the '<' */
+ len = start - p;
+ if (buf == NULL)
+ totlen += len;
+ else
+ {
+ mch_memmove(q, p, len);
+ q += len;
+ }
+
+ len = uc_check_code(start, end - start, q, cmd, eap,
+ &split_buf, &split_len);
+ if (len == (size_t)-1)
+ {
+ /* no match, continue after '<' */
+ p = start + 1;
+ len = 1;
+ }
+ else
+ p = end;
+ if (buf == NULL)
+ totlen += len;
+ else
+ q += len;
+ }
+ if (buf != NULL) /* second time here, finished */
+ {
+ STRCPY(q, p);
+ break;
+ }
+
+ totlen += STRLEN(p); /* Add on the trailing characters */
+ buf = alloc((unsigned)(totlen + 1));
+ if (buf == NULL)
+ {
+ vim_free(split_buf);
+ return;
+ }
+ }
+
+#ifdef FEAT_EVAL
+ current_SID = cmd->uc_scriptID;
+#endif
+ (void)do_cmdline(buf, eap->getline, eap->cookie,
+ DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
+#ifdef FEAT_EVAL
+ current_SID = save_current_SID;
+#endif
+ vim_free(buf);
+ vim_free(split_buf);
+}
+
+# if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+ static char_u *
+get_user_command_name(idx)
+ int idx;
+{
+ return get_user_commands(NULL, idx - (int)CMD_SIZE);
+}
+
+/*
+ * Function given to ExpandGeneric() to obtain the list of user command names.
+ */
+/*ARGSUSED*/
+ char_u *
+get_user_commands(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ if (idx < curbuf->b_ucmds.ga_len)
+ return USER_CMD_GA(&curbuf->b_ucmds, idx)->uc_name;
+ idx -= curbuf->b_ucmds.ga_len;
+ if (idx < ucmds.ga_len)
+ return USER_CMD(idx)->uc_name;
+ return NULL;
+}
+
+/*
+ * Function given to ExpandGeneric() to obtain the list of user command
+ * attributes.
+ */
+/*ARGSUSED*/
+ char_u *
+get_user_cmd_flags(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ static char *user_cmd_flags[] =
+ {"bang", "bar", "buffer", "complete", "count",
+ "nargs", "range", "register"};
+
+ if (idx >= sizeof(user_cmd_flags) / sizeof(user_cmd_flags[0]))
+ return NULL;
+ return (char_u *)user_cmd_flags[idx];
+}
+
+/*
+ * Function given to ExpandGeneric() to obtain the list of values for -nargs.
+ */
+/*ARGSUSED*/
+ char_u *
+get_user_cmd_nargs(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ static char *user_cmd_nargs[] = {"0", "1", "*", "?", "+"};
+
+ if (idx >= sizeof(user_cmd_nargs) / sizeof(user_cmd_nargs[0]))
+ return NULL;
+ return (char_u *)user_cmd_nargs[idx];
+}
+
+/*
+ * Function given to ExpandGeneric() to obtain the list of values for -complete.
+ */
+/*ARGSUSED*/
+ char_u *
+get_user_cmd_complete(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ return (char_u *)command_complete[idx].name;
+}
+# endif /* FEAT_CMDL_COMPL */
+
+#endif /* FEAT_USR_CMDS */
+
+ static void
+ex_colorscheme(eap)
+ exarg_T *eap;
+{
+ if (load_colors(eap->arg) == FAIL)
+ EMSG2(_("E185: Cannot find color scheme %s"), eap->arg);
+}
+
+ static void
+ex_highlight(eap)
+ exarg_T *eap;
+{
+ if (*eap->arg == NUL && eap->cmd[2] == '!')
+ MSG(_("Greetings, Vim user!"));
+ do_highlight(eap->arg, eap->forceit, FALSE);
+}
+
+
+/*
+ * Call this function if we thought we were going to exit, but we won't
+ * (because of an error). May need to restore the terminal mode.
+ */
+ void
+not_exiting()
+{
+ exiting = FALSE;
+ settmode(TMODE_RAW);
+}
+
+/*
+ * ":quit": quit current window, quit Vim if closed the last window.
+ */
+ static void
+ex_quit(eap)
+ exarg_T *eap;
+{
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ {
+ cmdwin_result = Ctrl_C;
+ return;
+ }
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+ netbeansForcedQuit = eap->forceit;
+#endif
+
+ /*
+ * If there are more files or windows we won't exit.
+ */
+ if (check_more(FALSE, eap->forceit) == OK && only_one_window())
+ exiting = TRUE;
+ if ((!P_HID(curbuf)
+ && check_changed(curbuf, p_awa, FALSE, eap->forceit, FALSE))
+ || check_more(TRUE, eap->forceit) == FAIL
+ || (only_one_window() && check_changed_any(eap->forceit)))
+ {
+ not_exiting();
+ }
+ else
+ {
+#ifdef FEAT_WINDOWS
+ if (only_one_window()) /* quit last window */
+#endif
+ getout(0);
+#ifdef FEAT_WINDOWS
+# ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+# endif
+ /* close window; may free buffer */
+ win_close(curwin, !P_HID(curwin->w_buffer) || eap->forceit);
+#endif
+ }
+}
+
+/*
+ * ":cquit".
+ */
+/*ARGSUSED*/
+ static void
+ex_cquit(eap)
+ exarg_T *eap;
+{
+ getout(1); /* this does not always pass on the exit code to the Manx
+ compiler. why? */
+}
+
+/*
+ * ":qall": try to quit all windows
+ */
+ static void
+ex_quit_all(eap)
+ exarg_T *eap;
+{
+# ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ {
+ if (eap->forceit)
+ cmdwin_result = K_XF1; /* ex_window() takes care of this */
+ else
+ cmdwin_result = K_XF2;
+ return;
+ }
+# endif
+ exiting = TRUE;
+ if (eap->forceit || !check_changed_any(FALSE))
+ getout(0);
+ not_exiting();
+}
+
+#ifdef FEAT_WINDOWS
+/*
+ * ":close": close current window, unless it is the last one
+ */
+ static void
+ex_close(eap)
+ exarg_T *eap;
+{
+# ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ cmdwin_result = K_IGNORE;
+ else
+# endif
+ ex_win_close(eap, curwin);
+}
+
+ static void
+ex_win_close(eap, win)
+ exarg_T *eap;
+ win_T *win;
+{
+ int need_hide;
+ buf_T *buf = win->w_buffer;
+
+ need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1);
+ if (need_hide && !P_HID(buf) && !eap->forceit)
+ {
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if ((p_confirm || cmdmod.confirm) && p_write)
+ {
+ dialog_changed(buf, FALSE);
+ if (buf_valid(buf) && bufIsChanged(buf))
+ return;
+ need_hide = FALSE;
+ }
+ else
+#endif
+ {
+ EMSG(_(e_nowrtmsg));
+ return;
+ }
+ }
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ /* free buffer when not hiding it or when it's a scratch buffer */
+ win_close(win, !need_hide && !P_HID(buf));
+}
+
+#ifdef FEAT_QUICKFIX
+/*
+ * ":pclose": Close any preview window.
+ */
+ static void
+ex_pclose(eap)
+ exarg_T *eap;
+{
+ win_T *win;
+
+ for (win = firstwin; win != NULL; win = win->w_next)
+ if (win->w_p_pvw)
+ {
+ ex_win_close(eap, win);
+ break;
+ }
+}
+#endif
+
+/*
+ * ":only".
+ */
+ static void
+ex_only(eap)
+ exarg_T *eap;
+{
+# ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+# endif
+ close_others(TRUE, eap->forceit);
+}
+
+/*
+ * ":all" and ":sall".
+ */
+ static void
+ex_all(eap)
+ exarg_T *eap;
+{
+ if (eap->addr_count == 0)
+ eap->line2 = 9999;
+ do_arg_all((int)eap->line2, eap->forceit);
+}
+#endif /* FEAT_WINDOWS */
+
+ static void
+ex_hide(eap)
+ exarg_T *eap;
+{
+ if (*eap->arg != NUL && check_nextcmd(eap->arg) == NULL)
+ eap->errmsg = e_invarg;
+ else
+ {
+ /* ":hide" or ":hide | cmd": hide current window */
+ eap->nextcmd = check_nextcmd(eap->arg);
+#ifdef FEAT_WINDOWS
+ if (!eap->skip)
+ {
+# ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+# endif
+ win_close(curwin, FALSE); /* don't free buffer */
+ }
+#endif
+ }
+}
+
+/*
+ * ":stop" and ":suspend": Suspend Vim.
+ */
+ static void
+ex_stop(eap)
+ exarg_T *eap;
+{
+ /*
+ * Disallow suspending for "rvim".
+ */
+ if (!check_restricted()
+#ifdef WIN3264
+ /*
+ * Check if external commands are allowed now.
+ */
+ && can_end_termcap_mode(TRUE)
+#endif
+ )
+ {
+ if (!eap->forceit)
+ autowrite_all();
+ windgoto((int)Rows - 1, 0);
+ out_char('\n');
+ out_flush();
+ stoptermcap();
+ out_flush(); /* needed for SUN to restore xterm buffer */
+#ifdef FEAT_TITLE
+ mch_restore_title(3); /* restore window titles */
+#endif
+ ui_suspend(); /* call machine specific function */
+#ifdef FEAT_TITLE
+ maketitle();
+ resettitle(); /* force updating the title */
+#endif
+ starttermcap();
+ scroll_start(); /* scroll screen before redrawing */
+ redraw_later_clear();
+ shell_resized(); /* may have resized window */
+ }
+}
+
+/*
+ * ":exit", ":xit" and ":wq": Write file and exit Vim.
+ */
+ static void
+ex_exit(eap)
+ exarg_T *eap;
+{
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ {
+ cmdwin_result = Ctrl_C;
+ return;
+ }
+#endif
+
+ /*
+ * if more files or windows we won't exit
+ */
+ if (check_more(FALSE, eap->forceit) == OK && only_one_window())
+ exiting = TRUE;
+ if ( ((eap->cmdidx == CMD_wq
+ || curbufIsChanged())
+ && do_write(eap) == FAIL)
+ || check_more(TRUE, eap->forceit) == FAIL
+ || (only_one_window() && check_changed_any(eap->forceit)))
+ {
+ not_exiting();
+ }
+ else
+ {
+#ifdef FEAT_WINDOWS
+ if (only_one_window()) /* quit last window, exit Vim */
+#endif
+ getout(0);
+#ifdef FEAT_WINDOWS
+# ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+# endif
+ /* quit current window, may free buffer */
+ win_close(curwin, !P_HID(curwin->w_buffer));
+#endif
+ }
+}
+
+/*
+ * ":print", ":list", ":number".
+ */
+ static void
+ex_print(eap)
+ exarg_T *eap;
+{
+ int save_list = 0; /* init for GCC */
+
+ if (eap->cmdidx == CMD_list)
+ {
+ save_list = curwin->w_p_list;
+ curwin->w_p_list = 1;
+ }
+
+ for ( ;!got_int; ui_breakcheck())
+ {
+ print_line(eap->line1,
+ (eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound));
+ if (++eap->line1 > eap->line2)
+ break;
+ out_flush(); /* show one line at a time */
+ }
+ setpcmark();
+ /* put cursor at last line */
+ curwin->w_cursor.lnum = eap->line2;
+ beginline(BL_SOL | BL_FIX);
+
+ ex_no_reprint = TRUE;
+
+ if (eap->cmdidx == CMD_list)
+ curwin->w_p_list = save_list;
+}
+
+#ifdef FEAT_BYTEOFF
+ static void
+ex_goto(eap)
+ exarg_T *eap;
+{
+ goto_byte(eap->line2);
+}
+#endif
+
+/*
+ * ":shell".
+ */
+/*ARGSUSED*/
+ static void
+ex_shell(eap)
+ exarg_T *eap;
+{
+ do_shell(NULL, 0);
+}
+
+#if (defined(FEAT_WINDOWS) && defined(HAVE_DROP_FILE)) \
+ || (defined(FEAT_GUI_GTK) && defined(FEAT_DND)) \
+ || defined(PROTO)
+
+/*
+ * Handle a file drop. The code is here because a drop is *nearly* like an
+ * :args command, but not quite (we have a list of exact filenames, so we
+ * don't want to (a) parse a command line, or (b) expand wildcards. So the
+ * code is very similar to :args and hence needs access to a lot of the static
+ * functions in this file.
+ *
+ * The list should be allocated using alloc(), as should each item in the
+ * list. This function takes over responsibility for freeing the list.
+ *
+ * XXX The list is made into the arggument list. This is freed using
+ * FreeWild(), which does a series of vim_free() calls, unless the two defines
+ * __EMX__ and __ALWAYS_HAS_TRAILING_NUL_POINTER are set. In this case, a
+ * routine _fnexplodefree() is used. This may cause problems, but as the drop
+ * file functionality is (currently) not in EMX this is not presently a
+ * problem.
+ */
+ void
+handle_drop(filec, filev, split)
+ int filec; /* the number of files dropped */
+ char_u **filev; /* the list of files dropped */
+ int split; /* force splitting the window */
+{
+ exarg_T ea;
+ int save_msg_scroll = msg_scroll;
+
+# ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ return;
+# endif
+
+ /* Check whether the current buffer is changed. If so, we will need
+ * to split the current window or data could be lost.
+ * We don't need to check if the 'hidden' option is set, as in this
+ * case the buffer won't be lost.
+ */
+ if (!P_HID(curbuf) && !split)
+ {
+ ++emsg_off;
+ split = check_changed(curbuf, TRUE, FALSE, FALSE, FALSE);
+ --emsg_off;
+ }
+ if (split)
+ {
+# ifdef FEAT_WINDOWS
+ if (win_split(0, 0) == FAIL)
+ return;
+# ifdef FEAT_SCROLLBIND
+ curwin->w_p_scb = FALSE;
+# endif
+
+ /* When splitting the window, create a new alist. Otherwise the
+ * existing one is overwritten. */
+ alist_unlink(curwin->w_alist);
+ alist_new();
+# else
+ return; /* can't split, always fail */
+# endif
+ }
+
+ /*
+ * Set up the new argument list.
+ */
+ alist_set(ALIST(curwin), filec, filev, FALSE);
+
+ /*
+ * Move to the first file.
+ */
+ /* Fake up a minimal "next" command for do_argfile() */
+ vim_memset(&ea, 0, sizeof(ea));
+ ea.cmd = (char_u *)"next";
+ do_argfile(&ea, 0);
+
+ /* do_ecmd() may set need_start_insertmode, but since we never left Insert
+ * mode that is not needed here. */
+ need_start_insertmode = FALSE;
+
+ /* Restore msg_scroll, otherwise a following command may cause scrolling
+ * unexpectedly. The screen will be redrawn by the caller, thus
+ * msg_scroll being set by displaying a message is irrelevant. */
+ msg_scroll = save_msg_scroll;
+}
+#endif
+
+static void alist_clear __ARGS((alist_T *al));
+/*
+ * Clear an argument list: free all file names and reset it to zero entries.
+ */
+ static void
+alist_clear(al)
+ alist_T *al;
+{
+ while (--al->al_ga.ga_len >= 0)
+ vim_free(AARGLIST(al)[al->al_ga.ga_len].ae_fname);
+ ga_clear(&al->al_ga);
+}
+
+/*
+ * Init an argument list.
+ */
+ void
+alist_init(al)
+ alist_T *al;
+{
+ ga_init2(&al->al_ga, (int)sizeof(aentry_T), 5);
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+
+/*
+ * Remove a reference from an argument list.
+ * Ignored when the argument list is the global one.
+ * If the argument list is no longer used by any window, free it.
+ */
+ void
+alist_unlink(al)
+ alist_T *al;
+{
+ if (al != &global_alist && --al->al_refcount <= 0)
+ {
+ alist_clear(al);
+ vim_free(al);
+ }
+}
+
+# if defined(FEAT_LISTCMDS) || defined(HAVE_DROP_FILE) || defined(PROTO)
+/*
+ * Create a new argument list and use it for the current window.
+ */
+ void
+alist_new()
+{
+ curwin->w_alist = (alist_T *)alloc((unsigned)sizeof(alist_T));
+ if (curwin->w_alist == NULL)
+ {
+ curwin->w_alist = &global_alist;
+ ++global_alist.al_refcount;
+ }
+ else
+ {
+ curwin->w_alist->al_refcount = 1;
+ alist_init(curwin->w_alist);
+ }
+}
+# endif
+#endif
+
+#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE) || defined(PROTO)
+/*
+ * Expand the file names in the global argument list.
+ */
+ void
+alist_expand()
+{
+ char_u **old_arg_files;
+ char_u **new_arg_files;
+ int new_arg_file_count;
+ char_u *save_p_su = p_su;
+ int i;
+
+ /* Don't use 'suffixes' here. This should work like the shell did the
+ * expansion. Also, the vimrc file isn't read yet, thus the user
+ * can't set the options. */
+ p_su = empty_option;
+ old_arg_files = (char_u **)alloc((unsigned)(sizeof(char_u *) * GARGCOUNT));
+ if (old_arg_files != NULL)
+ {
+ for (i = 0; i < GARGCOUNT; ++i)
+ old_arg_files[i] = GARGLIST[i].ae_fname;
+ if (expand_wildcards(GARGCOUNT, old_arg_files,
+ &new_arg_file_count, &new_arg_files,
+ EW_FILE|EW_NOTFOUND|EW_ADDSLASH) == OK
+ && new_arg_file_count > 0)
+ {
+ alist_set(&global_alist, new_arg_file_count, new_arg_files, TRUE);
+ }
+ vim_free(old_arg_files);
+ }
+ p_su = save_p_su;
+}
+#endif
+
+/*
+ * Set the argument list for the current window.
+ * Takes over the allocated files[] and the allocated fnames in it.
+ */
+ void
+alist_set(al, count, files, use_curbuf)
+ alist_T *al;
+ int count;
+ char_u **files;
+ int use_curbuf;
+{
+ int i;
+
+ alist_clear(al);
+ if (ga_grow(&al->al_ga, count) == OK)
+ {
+ for (i = 0; i < count; ++i)
+ alist_add(al, files[i], use_curbuf ? 2 : 1);
+ vim_free(files);
+ }
+ else
+ FreeWild(count, files);
+#ifdef FEAT_WINDOWS
+ if (al == &global_alist)
+#endif
+ arg_had_last = FALSE;
+}
+
+/*
+ * Add file "fname" to argument list "al".
+ * "fname" must have been allocated and "al" must have been checked for room.
+ */
+ void
+alist_add(al, fname, set_fnum)
+ alist_T *al;
+ char_u *fname;
+ int set_fnum; /* 1: set buffer number; 2: re-use curbuf */
+{
+ if (fname == NULL) /* don't add NULL file names */
+ return;
+#ifdef BACKSLASH_IN_FILENAME
+ slash_adjust(fname);
+#endif
+ AARGLIST(al)[al->al_ga.ga_len].ae_fname = fname;
+ if (set_fnum > 0)
+ AARGLIST(al)[al->al_ga.ga_len].ae_fnum =
+ buflist_add(fname, BLN_LISTED | (set_fnum == 2 ? BLN_CURBUF : 0));
+ ++al->al_ga.ga_len;
+ --al->al_ga.ga_room;
+}
+
+#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
+/*
+ * Adjust slashes in file names. Called after 'shellslash' was set.
+ */
+ void
+alist_slash_adjust()
+{
+ int i;
+# ifdef FEAT_WINDOWS
+ win_T *wp;
+# endif
+
+ for (i = 0; i < GARGCOUNT; ++i)
+ if (GARGLIST[i].ae_fname != NULL)
+ slash_adjust(GARGLIST[i].ae_fname);
+# ifdef FEAT_WINDOWS
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_alist != &global_alist)
+ for (i = 0; i < WARGCOUNT(wp); ++i)
+ if (WARGLIST(wp)[i].ae_fname != NULL)
+ slash_adjust(WARGLIST(wp)[i].ae_fname);
+# endif
+}
+#endif
+
+/*
+ * ":preserve".
+ */
+/*ARGSUSED*/
+ static void
+ex_preserve(eap)
+ exarg_T *eap;
+{
+ ml_preserve(curbuf, TRUE);
+}
+
+/*
+ * ":recover".
+ */
+ static void
+ex_recover(eap)
+ exarg_T *eap;
+{
+ /* Set recoverymode right away to avoid the ATTENTION prompt. */
+ recoverymode = TRUE;
+ if (!check_changed(curbuf, p_awa, TRUE, eap->forceit, FALSE)
+ && (*eap->arg == NUL
+ || setfname(curbuf, eap->arg, NULL, TRUE) == OK))
+ ml_recover();
+ recoverymode = FALSE;
+}
+
+/*
+ * Command modifier used in a wrong way.
+ */
+ static void
+ex_wrongmodifier(eap)
+ exarg_T *eap;
+{
+ eap->errmsg = e_invcmd;
+}
+
+#ifdef FEAT_WINDOWS
+/*
+ * :sview [+command] file split window with new file, read-only
+ * :split [[+command] file] split window with current or new file
+ * :vsplit [[+command] file] split window vertically with current or new file
+ * :new [[+command] file] split window with no or new file
+ * :vnew [[+command] file] split vertically window with no or new file
+ * :sfind [+command] file split window with file in 'path'
+ */
+ void
+ex_splitview(eap)
+ exarg_T *eap;
+{
+ win_T *old_curwin;
+#if defined(FEAT_SEARCHPATH) || defined(FEAT_BROWSE)
+ char_u *fname = NULL;
+#endif
+#ifdef FEAT_BROWSE
+ int browse_flag = cmdmod.browse;
+#endif
+
+#ifndef FEAT_VERTSPLIT
+ if (eap->cmdidx == CMD_vsplit || eap->cmdidx == CMD_vnew)
+ {
+ ex_ni(eap);
+ return;
+ }
+#endif
+
+ old_curwin = curwin;
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+
+#ifdef FEAT_QUICKFIX
+ /* A ":split" in the quickfix window works like ":new". Don't want two
+ * quickfix windows. */
+ if (bt_quickfix(curbuf))
+ {
+ if (eap->cmdidx == CMD_split)
+ eap->cmdidx = CMD_new;
+# ifdef FEAT_VERTSPLIT
+ if (eap->cmdidx == CMD_vsplit)
+ eap->cmdidx = CMD_vnew;
+# endif
+ }
+#endif
+
+#ifdef FEAT_SEARCHPATH
+ if (eap->cmdidx == CMD_sfind)
+ {
+ fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg),
+ FNAME_MESS, TRUE, curbuf->b_ffname);
+ if (fname == NULL)
+ goto theend;
+ eap->arg = fname;
+ }
+# ifdef FEAT_BROWSE
+ else
+# endif
+#endif
+#ifdef FEAT_BROWSE
+ if (cmdmod.browse
+# ifdef FEAT_VERTSPLIT
+ && eap->cmdidx != CMD_vnew
+#endif
+ && eap->cmdidx != CMD_new)
+ {
+ fname = do_browse(FALSE, (char_u *)_("Edit File in new window"),
+ eap->arg, NULL, NULL, NULL, curbuf);
+ if (fname == NULL)
+ goto theend;
+ eap->arg = fname;
+ }
+ cmdmod.browse = FALSE; /* Don't browse again in do_ecmd(). */
+#endif
+
+ if (win_split(eap->addr_count > 0 ? (int)eap->line2 : 0,
+ *eap->cmd == 'v' ? WSP_VERT : 0) != FAIL)
+ {
+#ifdef FEAT_SCROLLBIND
+ /* Reset 'scrollbind' when editing another file, but keep it when
+ * doing ":split" without arguments. */
+ if (*eap->arg != NUL
+#ifdef FEAT_BROWSE
+ || cmdmod.browse
+#endif
+ )
+ curwin->w_p_scb = FALSE;
+ else
+ do_check_scrollbind(FALSE);
+#endif
+ do_exedit(eap, old_curwin);
+ }
+
+#ifdef FEAT_BROWSE
+ cmdmod.browse = browse_flag;
+#endif
+
+#if defined(FEAT_SEARCHPATH) || defined(FEAT_BROWSE)
+theend:
+ vim_free(fname);
+#endif
+}
+#endif
+
+/*
+ * ":mode": Set screen mode.
+ * If no argument given, just get the screen size and redraw.
+ */
+ static void
+ex_mode(eap)
+ exarg_T *eap;
+{
+ if (*eap->arg == NUL)
+ shell_resized();
+ else
+ mch_screenmode(eap->arg);
+}
+
+#ifdef FEAT_WINDOWS
+/*
+ * ":resize".
+ * set, increment or decrement current window height
+ */
+ static void
+ex_resize(eap)
+ exarg_T *eap;
+{
+ int n;
+ win_T *wp = curwin;
+
+ if (eap->addr_count > 0)
+ {
+ n = eap->line2;
+ for (wp = firstwin; wp->w_next != NULL && --n > 0; wp = wp->w_next)
+ ;
+ }
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ n = atol((char *)eap->arg);
+#ifdef FEAT_VERTSPLIT
+ if (cmdmod.split & WSP_VERT)
+ {
+ if (*eap->arg == '-' || *eap->arg == '+')
+ n += W_WIDTH(curwin);
+ else if (n == 0 && eap->arg[0] == NUL) /* default is very wide */
+ n = 9999;
+ win_setwidth_win((int)n, wp);
+ }
+ else
+#endif
+ {
+ if (*eap->arg == '-' || *eap->arg == '+')
+ n += curwin->w_height;
+ else if (n == 0 && eap->arg[0] == NUL) /* default is very wide */
+ n = 9999;
+ win_setheight_win((int)n, wp);
+ }
+}
+#endif
+
+/*
+ * ":find [+command] <file>" command.
+ */
+ static void
+ex_find(eap)
+ exarg_T *eap;
+{
+#ifdef FEAT_SEARCHPATH
+ char_u *fname;
+ int count;
+
+ fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg), FNAME_MESS,
+ TRUE, curbuf->b_ffname);
+ if (eap->addr_count > 0)
+ {
+ /* Repeat finding the file "count" times. This matters when it
+ * appears several times in the path. */
+ count = eap->line2;
+ while (fname != NULL && --count > 0)
+ {
+ vim_free(fname);
+ fname = find_file_in_path(NULL, 0, FNAME_MESS,
+ FALSE, curbuf->b_ffname);
+ }
+ }
+
+ if (fname != NULL)
+ {
+ eap->arg = fname;
+#endif
+ do_exedit(eap, NULL);
+#ifdef FEAT_SEARCHPATH
+ vim_free(fname);
+ }
+#endif
+}
+
+/*
+ * ":edit", ":badd".
+ */
+ static void
+ex_edit(eap)
+ exarg_T *eap;
+{
+ do_exedit(eap, NULL);
+}
+
+/*
+ * ":edit <file>" command and alikes.
+ */
+/*ARGSUSED*/
+ void
+do_exedit(eap, old_curwin)
+ exarg_T *eap;
+ win_T *old_curwin; /* curwin before doing a split or NULL */
+{
+ int n;
+#ifdef FEAT_WINDOWS
+ int need_hide;
+#endif
+
+ /*
+ * ":vi" command ends Ex mode.
+ */
+ if (exmode_active && (eap->cmdidx == CMD_visual
+ || eap->cmdidx == CMD_view))
+ {
+ exmode_active = FALSE;
+ if (*eap->arg == NUL)
+ return;
+ }
+
+ if ((eap->cmdidx == CMD_new
+#ifdef FEAT_VERTSPLIT
+ || eap->cmdidx == CMD_vnew
+#endif
+ ) && *eap->arg == NUL)
+ {
+ /* ":new" without argument: edit an new empty buffer */
+ setpcmark();
+ (void)do_ecmd(0, NULL, NULL, eap, ECMD_ONE,
+ ECMD_HIDE + (eap->forceit ? ECMD_FORCEIT : 0));
+ }
+ else if ((eap->cmdidx != CMD_split
+#ifdef FEAT_VERTSPLIT
+ && eap->cmdidx != CMD_vsplit
+#endif
+ )
+ || *eap->arg != NUL
+#ifdef FEAT_BROWSE
+ || cmdmod.browse
+#endif
+ )
+ {
+ n = readonlymode;
+ if (eap->cmdidx == CMD_view || eap->cmdidx == CMD_sview)
+ readonlymode = TRUE;
+ else if (eap->cmdidx == CMD_enew)
+ readonlymode = FALSE; /* 'readonly' doesn't make sense in an
+ empty buffer */
+ setpcmark();
+ if (do_ecmd(0, (eap->cmdidx == CMD_enew ? NULL : eap->arg),
+ NULL, eap,
+ /* ":edit" goes to first line if Vi compatible */
+ (*eap->arg == NUL && eap->do_ecmd_lnum == 0
+ && vim_strchr(p_cpo, CPO_GOTO1) != NULL)
+ ? ECMD_ONE : eap->do_ecmd_lnum,
+ (P_HID(curbuf) ? ECMD_HIDE : 0)
+ + (eap->forceit ? ECMD_FORCEIT : 0)
+#ifdef FEAT_LISTCMDS
+ + (eap->cmdidx == CMD_badd ? ECMD_ADDBUF : 0 )
+#endif
+ ) == FAIL)
+ {
+ /* Editing the file failed. If the window was split, close it. */
+#ifdef FEAT_WINDOWS
+ if (old_curwin != NULL)
+ {
+ need_hide = (curbufIsChanged() && curbuf->b_nwindows <= 1);
+ if (!need_hide || P_HID(curbuf))
+ {
+# ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+# endif
+ win_close(curwin, !need_hide && !P_HID(curbuf));
+ }
+ }
+#endif
+ }
+ else if (readonlymode && curbuf->b_nwindows == 1)
+ {
+ /* When editing an already visited buffer, 'readonly' won't be set
+ * but the previous value is kept. With ":view" and ":sview" we
+ * want the file to be readonly, except when another window is
+ * editing the same buffer. */
+ curbuf->b_p_ro = TRUE;
+ }
+ readonlymode = n;
+ }
+ else
+ {
+ if (eap->do_ecmd_cmd != NULL)
+ do_cmdline_cmd(eap->do_ecmd_cmd);
+#ifdef FEAT_TITLE
+ n = curwin->w_arg_idx_invalid;
+#endif
+ check_arg_idx(curwin);
+#ifdef FEAT_TITLE
+ if (n != curwin->w_arg_idx_invalid)
+ maketitle();
+#endif
+ }
+
+#ifdef FEAT_WINDOWS
+ /*
+ * if ":split file" worked, set alternate file name in old window to new
+ * file
+ */
+ if (old_curwin != NULL
+ && *eap->arg != NUL
+ && curwin != old_curwin
+ && win_valid(old_curwin)
+ && old_curwin->w_buffer != curbuf)
+ old_curwin->w_alt_fnum = curbuf->b_fnum;
+#endif
+
+ ex_no_reprint = TRUE;
+}
+
+#ifndef FEAT_GUI
+/*
+ * ":gui" and ":gvim" when there is no GUI.
+ */
+ static void
+ex_nogui(eap)
+ exarg_T *eap;
+{
+ eap->errmsg = e_nogvim;
+}
+#endif
+
+#if defined(FEAT_GUI_W32) && defined(FEAT_MENU) && defined(FEAT_TEAROFF)
+ static void
+ex_tearoff(eap)
+ exarg_T *eap;
+{
+ gui_make_tearoff(eap->arg);
+}
+#endif
+
+#if (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK)) && defined(FEAT_MENU)
+ static void
+ex_popup(eap)
+ exarg_T *eap;
+{
+ gui_make_popup(eap->arg);
+}
+#endif
+
+/*ARGSUSED*/
+ static void
+ex_swapname(eap)
+ exarg_T *eap;
+{
+ if (curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_mfp->mf_fname == NULL)
+ MSG(_("No swap file"));
+ else
+ msg(curbuf->b_ml.ml_mfp->mf_fname);
+}
+
+/*
+ * ":syncbind" forces all 'scrollbind' windows to have the same relative
+ * offset.
+ * (1998-11-02 16:21:01 R. Edward Ralston <eralston@computer.org>)
+ */
+/*ARGSUSED*/
+ static void
+ex_syncbind(eap)
+ exarg_T *eap;
+{
+#ifdef FEAT_SCROLLBIND
+ win_T *wp;
+ long topline;
+ long y;
+ linenr_T old_linenr = curwin->w_cursor.lnum;
+
+ setpcmark();
+
+ /*
+ * determine max topline
+ */
+ if (curwin->w_p_scb)
+ {
+ topline = curwin->w_topline;
+ for (wp = firstwin; wp; wp = wp->w_next)
+ {
+ if (wp->w_p_scb && wp->w_buffer)
+ {
+ y = wp->w_buffer->b_ml.ml_line_count - p_so;
+ if (topline > y)
+ topline = y;
+ }
+ }
+ if (topline < 1)
+ topline = 1;
+ }
+ else
+ {
+ topline = 1;
+ }
+
+
+ /*
+ * set all scrollbind windows to the same topline
+ */
+ wp = curwin;
+ for (curwin = firstwin; curwin; curwin = curwin->w_next)
+ {
+ if (curwin->w_p_scb)
+ {
+ y = topline - curwin->w_topline;
+ if (y > 0)
+ scrollup(y, TRUE);
+ else
+ scrolldown(-y, TRUE);
+ curwin->w_scbind_pos = topline;
+ redraw_later(VALID);
+ cursor_correct();
+#ifdef FEAT_WINDOWS
+ curwin->w_redr_status = TRUE;
+#endif
+ }
+ }
+ curwin = wp;
+ if (curwin->w_p_scb)
+ {
+ did_syncbind = TRUE;
+ checkpcmark();
+ if (old_linenr != curwin->w_cursor.lnum)
+ {
+ char_u ctrl_o[2];
+
+ ctrl_o[0] = Ctrl_O;
+ ctrl_o[1] = 0;
+ ins_typebuf(ctrl_o, REMAP_NONE, 0, TRUE, FALSE);
+ }
+ }
+#endif
+}
+
+
+ static void
+ex_read(eap)
+ exarg_T *eap;
+{
+ int i;
+
+ if (eap->usefilter) /* :r!cmd */
+ do_bang(1, eap, FALSE, FALSE, TRUE);
+ else
+ {
+ if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL)
+ return;
+
+#ifdef FEAT_BROWSE
+ if (cmdmod.browse)
+ {
+ char_u *browseFile;
+
+ browseFile = do_browse(FALSE, (char_u *)_("Append File"), eap->arg,
+ NULL, NULL, NULL, curbuf);
+ if (browseFile != NULL)
+ {
+ i = readfile(browseFile, NULL,
+ eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
+ vim_free(browseFile);
+ }
+ else
+ i = OK;
+ }
+ else
+#endif
+ if (*eap->arg == NUL)
+ {
+ if (check_fname() == FAIL) /* check for no file name */
+ return;
+ i = readfile(curbuf->b_ffname, curbuf->b_fname,
+ eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
+ }
+ else
+ {
+ if (vim_strchr(p_cpo, CPO_ALTREAD) != NULL)
+ (void)setaltfname(eap->arg, eap->arg, (linenr_T)1);
+ i = readfile(eap->arg, NULL,
+ eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
+
+ }
+ if (i == FAIL)
+ {
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+ if (!aborting())
+#endif
+ EMSG2(_(e_notopen), eap->arg);
+ }
+ else
+ redraw_curbuf_later(VALID);
+ }
+}
+
+/*
+ * ":cd", ":lcd", ":chdir" and ":lchdir".
+ */
+ static void
+ex_cd(eap)
+ exarg_T *eap;
+{
+ static char_u *prev_dir = NULL;
+ char_u *new_dir;
+ char_u *tofree;
+
+ new_dir = eap->arg;
+#if !defined(UNIX) && !defined(VMS)
+ /* for non-UNIX ":cd" means: print current directory */
+ if (*new_dir == NUL)
+ ex_pwd(NULL);
+ else
+#endif
+ {
+ /* ":cd -": Change to previous directory */
+ if (STRCMP(new_dir, "-") == 0)
+ {
+ if (prev_dir == NULL)
+ {
+ EMSG(_("E186: No previous directory"));
+ return;
+ }
+ new_dir = prev_dir;
+ }
+
+ /* Save current directory for next ":cd -" */
+ tofree = prev_dir;
+ if (mch_dirname(NameBuff, MAXPATHL) == OK)
+ prev_dir = vim_strsave(NameBuff);
+ else
+ prev_dir = NULL;
+
+#if defined(UNIX) || defined(VMS)
+ /* for UNIX ":cd" means: go to home directory */
+ if (*new_dir == NUL)
+ {
+ /* use NameBuff for home directory name */
+# ifdef VMS
+ char_u *p;
+
+ p = mch_getenv((char_u *)"SYS$LOGIN");
+ if (p == NULL || *p == NUL) /* empty is the same as not set */
+ NameBuff[0] = NUL;
+ else
+ STRNCPY(NameBuff, p, MAXPATHL);
+# else
+ expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
+# endif
+ new_dir = NameBuff;
+ }
+#endif
+ if (new_dir == NULL || vim_chdir(new_dir))
+ EMSG(_(e_failed));
+ else
+ {
+ vim_free(curwin->w_localdir);
+ if (eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir)
+ {
+ /* If still in global directory, need to remember current
+ * directory as global directory. */
+ if (globaldir == NULL && prev_dir != NULL)
+ globaldir = vim_strsave(prev_dir);
+ /* Remember this local directory for the window. */
+ if (mch_dirname(NameBuff, MAXPATHL) == OK)
+ curwin->w_localdir = vim_strsave(NameBuff);
+ }
+ else
+ {
+ /* We are now in the global directory, no need to remember its
+ * name. */
+ vim_free(globaldir);
+ globaldir = NULL;
+ curwin->w_localdir = NULL;
+ }
+
+ shorten_fnames(TRUE);
+
+ /* Echo the new current directory if the command was typed. */
+ if (KeyTyped)
+ ex_pwd(eap);
+ }
+ vim_free(tofree);
+ }
+}
+
+/*
+ * ":pwd".
+ */
+/*ARGSUSED*/
+ static void
+ex_pwd(eap)
+ exarg_T *eap;
+{
+ if (mch_dirname(NameBuff, MAXPATHL) == OK)
+ {
+#ifdef BACKSLASH_IN_FILENAME
+ slash_adjust(NameBuff);
+#endif
+ msg(NameBuff);
+ }
+ else
+ EMSG(_("E187: Unknown"));
+}
+
+/*
+ * ":=".
+ */
+ static void
+ex_equal(eap)
+ exarg_T *eap;
+{
+ smsg((char_u *)"%ld", (long)eap->line2);
+}
+
+ static void
+ex_sleep(eap)
+ exarg_T *eap;
+{
+ int n;
+
+ if (cursor_valid())
+ {
+ n = W_WINROW(curwin) + curwin->w_wrow - msg_scrolled;
+ if (n >= 0)
+ windgoto((int)n, curwin->w_wcol);
+ }
+ do_sleep(eap->line2 * (*eap->arg == 'm' ? 1L : 1000L));
+}
+
+/*
+ * Sleep for "msec" milliseconds, but keep checking for a CTRL-C every second.
+ */
+ void
+do_sleep(msec)
+ long msec;
+{
+ long done;
+
+ cursor_on();
+ out_flush();
+ for (done = 0; !got_int && done < msec; done += 1000L)
+ {
+ ui_delay(msec - done > 1000L ? 1000L : msec - done, TRUE);
+ ui_breakcheck();
+ }
+}
+
+ static void
+do_exmap(eap, isabbrev)
+ exarg_T *eap;
+ int isabbrev;
+{
+ int mode;
+ char_u *cmdp;
+
+ cmdp = eap->cmd;
+ mode = get_map_mode(&cmdp, eap->forceit || isabbrev);
+
+ switch (do_map((*cmdp == 'n') ? 2 : (*cmdp == 'u'),
+ eap->arg, mode, isabbrev))
+ {
+ case 1: EMSG(_(e_invarg));
+ break;
+ case 2: EMSG(isabbrev ? _(e_noabbr) : _(e_nomap));
+ break;
+ }
+}
+
+/*
+ * ":winsize" command (obsolete).
+ */
+ static void
+ex_winsize(eap)
+ exarg_T *eap;
+{
+ int w, h;
+ char_u *arg = eap->arg;
+ char_u *p;
+
+ w = getdigits(&arg);
+ arg = skipwhite(arg);
+ p = arg;
+ h = getdigits(&arg);
+ if (*p != NUL && *arg == NUL)
+ set_shellsize(w, h, TRUE);
+ else
+ EMSG(_("E465: :winsize requires two number arguments"));
+}
+
+#ifdef FEAT_WINDOWS
+ static void
+ex_wincmd(eap)
+ exarg_T *eap;
+{
+ int xchar = NUL;
+ char_u *p;
+
+ if (*eap->arg == 'g' || *eap->arg == Ctrl_G)
+ {
+ /* CTRL-W g and CTRL-W CTRL-G have an extra command character */
+ if (eap->arg[1] == NUL)
+ {
+ EMSG(_(e_invarg));
+ return;
+ }
+ xchar = eap->arg[1];
+ p = eap->arg + 2;
+ }
+ else
+ p = eap->arg + 1;
+
+ eap->nextcmd = check_nextcmd(p);
+ p = skipwhite(p);
+ if (*p != NUL && *p != '"' && eap->nextcmd == NULL)
+ EMSG(_(e_invarg));
+ else
+ {
+ /* Pass flags on for ":vertical wincmd ]". */
+ postponed_split_flags = cmdmod.split;
+ do_window(*eap->arg, eap->addr_count > 0 ? eap->line2 : 0L, xchar);
+ postponed_split_flags = 0;
+ }
+}
+#endif
+
+#if defined(FEAT_GUI) || defined(UNIX) || defined(VMS)
+/*
+ * ":winpos".
+ */
+ static void
+ex_winpos(eap)
+ exarg_T *eap;
+{
+ int x, y;
+ char_u *arg = eap->arg;
+ char_u *p;
+
+ if (*arg == NUL)
+ {
+# ifdef FEAT_GUI
+ if (gui.in_use && gui_mch_get_winpos(&x, &y) != FAIL)
+ {
+ sprintf((char *)IObuff, _("Window position: X %d, Y %d"), x, y);
+ msg(IObuff);
+ }
+ else
+# endif
+ EMSG(_("E188: Obtaining window position not implemented for this platform"));
+ }
+ else
+ {
+ x = getdigits(&arg);
+ arg = skipwhite(arg);
+ p = arg;
+ y = getdigits(&arg);
+ if (*p == NUL || *arg != NUL)
+ {
+ EMSG(_("E466: :winpos requires two number arguments"));
+ return;
+ }
+# ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_mch_set_winpos(x, y);
+ else if (gui.starting)
+ {
+ /* Remember the coordinates for when the window is opened. */
+ gui_win_x = x;
+ gui_win_y = y;
+ }
+# ifdef HAVE_TGETENT
+ else
+# endif
+# endif
+# ifdef HAVE_TGETENT
+ if (*T_CWP)
+ term_set_winpos(x, y);
+# endif
+ }
+}
+#endif
+
+/*
+ * Handle command that work like operators: ":delete", ":yank", ":>" and ":<".
+ */
+ static void
+ex_operators(eap)
+ exarg_T *eap;
+{
+ oparg_T oa;
+
+ clear_oparg(&oa);
+ oa.regname = eap->regname;
+ oa.start.lnum = eap->line1;
+ oa.end.lnum = eap->line2;
+ oa.line_count = eap->line2 - eap->line1 + 1;
+ oa.motion_type = MLINE;
+#ifdef FEAT_VIRTUALEDIT
+ virtual_op = FALSE;
+#endif
+ if (eap->cmdidx != CMD_yank) /* position cursor for undo */
+ {
+ setpcmark();
+ curwin->w_cursor.lnum = eap->line1;
+ beginline(BL_SOL | BL_FIX);
+ }
+
+ switch (eap->cmdidx)
+ {
+ case CMD_delete:
+ oa.op_type = OP_DELETE;
+ op_delete(&oa);
+ break;
+
+ case CMD_yank:
+ oa.op_type = OP_YANK;
+ (void)op_yank(&oa, FALSE, TRUE);
+ break;
+
+ default: /* CMD_rshift or CMD_lshift */
+ if ((eap->cmdidx == CMD_rshift)
+#ifdef FEAT_RIGHTLEFT
+ ^ curwin->w_p_rl
+#endif
+ )
+ oa.op_type = OP_RSHIFT;
+ else
+ oa.op_type = OP_LSHIFT;
+ op_shift(&oa, FALSE, eap->amount);
+ break;
+ }
+#ifdef FEAT_VIRTUALEDIT
+ virtual_op = MAYBE;
+#endif
+}
+
+/*
+ * ":put".
+ */
+ static void
+ex_put(eap)
+ exarg_T *eap;
+{
+ /* ":0put" works like ":1put!". */
+ if (eap->line2 == 0)
+ {
+ eap->line2 = 1;
+ eap->forceit = TRUE;
+ }
+ curwin->w_cursor.lnum = eap->line2;
+ do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L, PUT_LINE);
+}
+
+/*
+ * Handle ":copy" and ":move".
+ */
+ static void
+ex_copymove(eap)
+ exarg_T *eap;
+{
+ long n;
+
+ n = get_address(&eap->arg, FALSE, FALSE);
+ if (eap->arg == NULL) /* error detected */
+ {
+ eap->nextcmd = NULL;
+ return;
+ }
+
+ /*
+ * move or copy lines from 'eap->line1'-'eap->line2' to below line 'n'
+ */
+ if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count)
+ {
+ EMSG(_(e_invaddr));
+ return;
+ }
+
+ if (eap->cmdidx == CMD_move)
+ {
+ if (do_move(eap->line1, eap->line2, n) == FAIL)
+ return;
+ }
+ else
+ ex_copy(eap->line1, eap->line2, n);
+ u_clearline();
+ beginline(BL_SOL | BL_FIX);
+}
+
+/*
+ * ":smagic" and ":snomagic".
+ */
+ static void
+ex_submagic(eap)
+ exarg_T *eap;
+{
+ int magic_save = p_magic;
+
+ p_magic = (eap->cmdidx == CMD_smagic);
+ do_sub(eap);
+ p_magic = magic_save;
+}
+
+/*
+ * ":join".
+ */
+ static void
+ex_join(eap)
+ exarg_T *eap;
+{
+ curwin->w_cursor.lnum = eap->line1;
+ if (eap->line1 == eap->line2)
+ {
+ if (eap->addr_count >= 2) /* :2,2join does nothing */
+ return;
+ if (eap->line2 == curbuf->b_ml.ml_line_count)
+ {
+ beep_flush();
+ return;
+ }
+ ++eap->line2;
+ }
+ do_do_join(eap->line2 - eap->line1 + 1, !eap->forceit);
+ beginline(BL_WHITE | BL_FIX);
+}
+
+/*
+ * ":[addr]@r" or ":[addr]*r": execute register
+ */
+ static void
+ex_at(eap)
+ exarg_T *eap;
+{
+ int c;
+
+ curwin->w_cursor.lnum = eap->line2;
+
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = TRUE; /* disallow scrolling here */
+#endif
+
+ /* get the register name. No name means to use the previous one */
+ c = *eap->arg;
+ if (c == NUL || (c == '*' && *eap->cmd == '*'))
+ c = '@';
+ /* put the register in mapbuf */
+ if (do_execreg(c, TRUE, vim_strchr(p_cpo, CPO_EXECBUF) != NULL) == FAIL)
+ beep_flush();
+ else
+ {
+ int save_efr = exec_from_reg;
+
+ exec_from_reg = TRUE;
+
+ /*
+ * Execute from the typeahead buffer.
+ * Originally this didn't check for the typeahead buffer to be empty,
+ * thus could read more Ex commands from stdin. It's not clear why,
+ * it is certainly unexpected.
+ */
+ while ((!stuff_empty() || typebuf.tb_len > 0) && vpeekc() == ':')
+ (void)do_cmdline(NULL, getexline, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE);
+
+ exec_from_reg = save_efr;
+ }
+}
+
+/*
+ * ":!".
+ */
+ static void
+ex_bang(eap)
+ exarg_T *eap;
+{
+ do_bang(eap->addr_count, eap, eap->forceit, TRUE, TRUE);
+}
+
+/*
+ * ":undo".
+ */
+/*ARGSUSED*/
+ static void
+ex_undo(eap)
+ exarg_T *eap;
+{
+ u_undo(1);
+}
+
+/*
+ * ":redo".
+ */
+/*ARGSUSED*/
+ static void
+ex_redo(eap)
+ exarg_T *eap;
+{
+ u_redo(1);
+}
+
+/*
+ * ":redir": start/stop redirection.
+ */
+ static void
+ex_redir(eap)
+ exarg_T *eap;
+{
+ char *mode;
+ char_u *fname;
+
+ if (STRICMP(eap->arg, "END") == 0)
+ close_redir();
+ else
+ {
+ if (*eap->arg == '>')
+ {
+ ++eap->arg;
+ if (*eap->arg == '>')
+ {
+ ++eap->arg;
+ mode = "a";
+ }
+ else
+ mode = "w";
+ eap->arg = skipwhite(eap->arg);
+
+ close_redir();
+
+ /* Expand environment variables and "~/". */
+ fname = expand_env_save(eap->arg);
+ if (fname == NULL)
+ return;
+#ifdef FEAT_BROWSE
+ if (cmdmod.browse)
+ {
+ char_u *browseFile;
+
+ browseFile = do_browse(TRUE, (char_u *)_("Save Redirection"),
+ fname, NULL, NULL, BROWSE_FILTER_ALL_FILES, curbuf);
+ if (browseFile == NULL)
+ return; /* operation cancelled */
+ vim_free(fname);
+ fname = browseFile;
+ eap->forceit = TRUE; /* since dialog already asked */
+ }
+#endif
+
+ redir_fd = open_exfile(fname, eap->forceit, mode);
+ vim_free(fname);
+ }
+#ifdef FEAT_EVAL
+ else if (*eap->arg == '@')
+ {
+ /* redirect to a register a-z (resp. A-Z for appending) */
+ close_redir();
+ ++eap->arg;
+ if (ASCII_ISALPHA(*eap->arg)
+# ifdef FEAT_CLIPBOARD
+ || *eap->arg == '*'
+# endif
+ || *eap->arg == '"')
+ {
+ redir_reg = *eap->arg;
+ if (islower(redir_reg)
+# ifdef FEAT_CLIPBOARD
+ || redir_reg == '*'
+# endif
+ || redir_reg == '"')
+ {
+ /* make register empty */
+ write_reg_contents(redir_reg, (char_u *)"", -1, FALSE);
+ }
+ }
+ else
+ EMSG(_(e_invarg));
+ }
+#endif
+
+ /* TODO: redirect to a buffer */
+
+ /* TODO: redirect to an internal variable */
+
+ else
+ EMSG(_(e_invarg));
+ }
+}
+
+/*
+ * ":redraw": force redraw
+ */
+ static void
+ex_redraw(eap)
+ exarg_T *eap;
+{
+ int r = RedrawingDisabled;
+ int p = p_lz;
+
+ RedrawingDisabled = 0;
+ p_lz = FALSE;
+ update_topline();
+ update_screen(eap->forceit ? CLEAR :
+#ifdef FEAT_VISUAL
+ VIsual_active ? INVERTED :
+#endif
+ 0);
+#ifdef FEAT_TITLE
+ if (need_maketitle)
+ maketitle();
+#endif
+ RedrawingDisabled = r;
+ p_lz = p;
+
+ /* Reset msg_didout, so that a message that's there is overwritten. */
+ msg_didout = FALSE;
+ msg_col = 0;
+
+ out_flush();
+}
+
+/*
+ * ":redrawstatus": force redraw of status line(s)
+ */
+/*ARGSUSED*/
+ static void
+ex_redrawstatus(eap)
+ exarg_T *eap;
+{
+#if defined(FEAT_WINDOWS)
+ int r = RedrawingDisabled;
+ int p = p_lz;
+
+ RedrawingDisabled = 0;
+ p_lz = FALSE;
+ if (eap->forceit)
+ status_redraw_all();
+ else
+ status_redraw_curbuf();
+ update_screen(
+# ifdef FEAT_VISUAL
+ VIsual_active ? INVERTED :
+# endif
+ 0);
+ RedrawingDisabled = r;
+ p_lz = p;
+ out_flush();
+#endif
+}
+
+ static void
+close_redir()
+{
+ if (redir_fd != NULL)
+ {
+ fclose(redir_fd);
+ redir_fd = NULL;
+ }
+#ifdef FEAT_EVAL
+ redir_reg = 0;
+#endif
+}
+
+#if defined(FEAT_SESSION) && defined(USE_CRNL)
+# define MKSESSION_NL
+static int mksession_nl = FALSE; /* use NL only in put_eol() */
+#endif
+
+/*
+ * ":mkexrc", ":mkvimrc", ":mkview" and ":mksession".
+ */
+ static void
+ex_mkrc(eap)
+ exarg_T *eap;
+{
+ FILE *fd;
+ int failed = FALSE;
+ char_u *fname;
+#ifdef FEAT_BROWSE
+ char_u *browseFile = NULL;
+#endif
+#ifdef FEAT_SESSION
+ int view_session = FALSE;
+ int using_vdir = FALSE; /* using 'viewdir'? */
+ char_u *viewFile = NULL;
+ unsigned *flagp;
+#endif
+
+ if (eap->cmdidx == CMD_mksession || eap->cmdidx == CMD_mkview)
+ {
+#ifdef FEAT_SESSION
+ view_session = TRUE;
+#else
+ ex_ni(eap);
+ return;
+#endif
+ }
+
+#ifdef FEAT_SESSION
+ /* ":mkview" or ":mkview 9": generate file name with 'viewdir' */
+ if (eap->cmdidx == CMD_mkview
+ && (*eap->arg == NUL
+ || (vim_isdigit(*eap->arg) && eap->arg[1] == NUL)))
+ {
+ eap->forceit = TRUE;
+ fname = get_view_file(*eap->arg);
+ if (fname == NULL)
+ return;
+ viewFile = fname;
+ using_vdir = TRUE;
+ }
+ else
+#endif
+ if (*eap->arg != NUL)
+ fname = eap->arg;
+ else if (eap->cmdidx == CMD_mkvimrc)
+ fname = (char_u *)VIMRC_FILE;
+#ifdef FEAT_SESSION
+ else if (eap->cmdidx == CMD_mksession)
+ fname = (char_u *)SESSION_FILE;
+#endif
+ else
+ fname = (char_u *)EXRC_FILE;
+
+#ifdef FEAT_BROWSE
+ if (cmdmod.browse)
+ {
+ browseFile = do_browse(TRUE,
+# ifdef FEAT_SESSION
+ eap->cmdidx == CMD_mkview ? (char_u *)_("Save View") :
+ eap->cmdidx == CMD_mksession ? (char_u *)_("Save Session") :
+# endif
+ (char_u *)_("Save Setup"),
+ fname, (char_u *)"vim", NULL, BROWSE_FILTER_MACROS, NULL);
+ if (browseFile == NULL)
+ goto theend;
+ fname = browseFile;
+ eap->forceit = TRUE; /* since dialog already asked */
+ }
+#endif
+
+#if defined(FEAT_SESSION) && defined(vim_mkdir)
+ /* When using 'viewdir' may have to create the directory. */
+ if (using_vdir && !mch_isdir(p_vdir))
+ vim_mkdir(p_vdir, 0755); /* ignore errors, open_exfile() will fail */
+#endif
+
+ fd = open_exfile(fname, eap->forceit, WRITEBIN);
+ if (fd != NULL)
+ {
+#ifdef FEAT_SESSION
+ if (eap->cmdidx == CMD_mkview)
+ flagp = &vop_flags;
+ else
+ flagp = &ssop_flags;
+#endif
+
+#ifdef MKSESSION_NL
+ /* "unix" in 'sessionoptions': use NL line separator */
+ if (view_session && (*flagp & SSOP_UNIX))
+ mksession_nl = TRUE;
+#endif
+
+ /* Write the version command for :mkvimrc */
+ if (eap->cmdidx == CMD_mkvimrc)
+ (void)put_line(fd, "version 6.0");
+
+#ifdef FEAT_SESSION
+ if (eap->cmdidx != CMD_mkview)
+#endif
+ {
+ /* Write setting 'compatible' first, because it has side effects.
+ * For that same reason only do it when needed. */
+ if (p_cp)
+ (void)put_line(fd, "if !&cp | set cp | endif");
+ else
+ (void)put_line(fd, "if &cp | set nocp | endif");
+ }
+
+#ifdef FEAT_SESSION
+ if (!view_session
+ || (eap->cmdidx == CMD_mksession
+ && (*flagp & SSOP_OPTIONS)))
+#endif
+ failed |= (makemap(fd, NULL) == FAIL
+ || makeset(fd, OPT_GLOBAL, FALSE) == FAIL);
+
+#ifdef FEAT_SESSION
+ if (!failed && view_session)
+ {
+ if (put_line(fd, "let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0") == FAIL)
+ failed = TRUE;
+ if (eap->cmdidx == CMD_mksession)
+ {
+ char_u dirnow[MAXPATHL]; /* current directory */
+
+ /*
+ * Change to session file's dir.
+ */
+ if (mch_dirname(dirnow, MAXPATHL) == FAIL
+ || mch_chdir((char *)dirnow) != 0)
+ *dirnow = NUL;
+ if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR))
+ {
+ if (vim_chdirfile(fname) == OK)
+ shorten_fnames(TRUE);
+ }
+ else if (*dirnow != NUL
+ && (ssop_flags & SSOP_CURDIR) && globaldir != NULL)
+ {
+ (void)mch_chdir((char *)globaldir);
+ shorten_fnames(TRUE);
+ }
+
+ failed |= (makeopens(fd, dirnow) == FAIL);
+
+ /* restore original dir */
+ if (*dirnow != NUL && ((ssop_flags & SSOP_SESDIR)
+ || ((ssop_flags & SSOP_CURDIR) && globaldir != NULL)))
+ {
+ if (mch_chdir((char *)dirnow) != 0)
+ EMSG(_(e_prev_dir));
+ shorten_fnames(TRUE);
+ }
+ }
+ else
+ {
+ failed |= (put_view(fd, curwin, !using_vdir, flagp) == FAIL);
+ }
+ if (put_line(fd, "let &so = s:so_save | let &siso = s:siso_save")
+ == FAIL)
+ failed = TRUE;
+ }
+#endif
+ failed |= fclose(fd);
+
+ if (failed)
+ EMSG(_(e_write));
+#if defined(FEAT_EVAL) && defined(FEAT_SESSION)
+ else if (eap->cmdidx == CMD_mksession)
+ {
+ /* successful session write - set this_session var */
+ char_u tbuf[MAXPATHL];
+
+ if (vim_FullName(fname, tbuf, MAXPATHL, FALSE) == OK)
+ set_vim_var_string(VV_THIS_SESSION, tbuf, -1);
+ }
+#endif
+#ifdef MKSESSION_NL
+ mksession_nl = FALSE;
+#endif
+ }
+
+#ifdef FEAT_BROWSE
+theend:
+ vim_free(browseFile);
+#endif
+#ifdef FEAT_SESSION
+ vim_free(viewFile);
+#endif
+}
+
+/*
+ * Open a file for writing for an Ex command, with some checks.
+ * Return file descriptor, or NULL on failure.
+ */
+ FILE *
+open_exfile(fname, forceit, mode)
+ char_u *fname;
+ int forceit;
+ char *mode; /* "w" for create new file or "a" for append */
+{
+ FILE *fd;
+
+#ifdef UNIX
+ /* with Unix it is possible to open a directory */
+ if (mch_isdir(fname))
+ {
+ EMSG2(_(e_isadir2), fname);
+ return NULL;
+ }
+#endif
+ if (!forceit && *mode != 'a' && vim_fexists(fname))
+ {
+ EMSG2(_("E189: \"%s\" exists (add ! to override)"), fname);
+ return NULL;
+ }
+
+ if ((fd = mch_fopen((char *)fname, mode)) == NULL)
+ EMSG2(_("E190: Cannot open \"%s\" for writing"), fname);
+
+ return fd;
+}
+
+/*
+ * ":mark" and ":k".
+ */
+ static void
+ex_mark(eap)
+ exarg_T *eap;
+{
+ pos_T pos;
+
+ if (*eap->arg == NUL) /* No argument? */
+ EMSG(_(e_argreq));
+ else if (eap->arg[1] != NUL) /* more than one character? */
+ EMSG(_(e_trailing));
+ else
+ {
+ pos = curwin->w_cursor; /* save curwin->w_cursor */
+ curwin->w_cursor.lnum = eap->line2;
+ beginline(BL_WHITE | BL_FIX);
+ if (setmark(*eap->arg) == FAIL) /* set mark */
+ EMSG(_("E191: Argument must be a letter or forward/backward quote"));
+ curwin->w_cursor = pos; /* restore curwin->w_cursor */
+ }
+}
+
+/*
+ * Update w_topline, w_leftcol and the cursor position.
+ */
+ void
+update_topline_cursor()
+{
+ check_cursor(); /* put cursor on valid line */
+ update_topline();
+ if (!curwin->w_p_wrap)
+ validate_cursor();
+ update_curswant();
+}
+
+#ifdef FEAT_EX_EXTRA
+/*
+ * ":normal[!] {commands}": Execute normal mode commands.
+ */
+ static void
+ex_normal(eap)
+ exarg_T *eap;
+{
+ oparg_T oa;
+ int save_msg_scroll = msg_scroll;
+ int save_restart_edit = restart_edit;
+ int save_msg_didout = msg_didout;
+ int save_State = State;
+ tasave_T tabuf;
+ int save_insertmode = p_im;
+ int save_finish_op = finish_op;
+#ifdef FEAT_MBYTE
+ char_u *arg = NULL;
+ int l;
+ char_u *p;
+#endif
+
+ if (ex_normal_busy >= p_mmd)
+ {
+ EMSG(_("E192: Recursive use of :normal too deep"));
+ return;
+ }
+ ++ex_normal_busy;
+
+ msg_scroll = FALSE; /* no msg scrolling in Normal mode */
+ restart_edit = 0; /* don't go to Insert mode */
+ p_im = FALSE; /* don't use 'insertmode' */
+
+#ifdef FEAT_MBYTE
+ /*
+ * vgetc() expects a CSI and K_SPECIAL to have been escaped. Don't do
+ * this for the K_SPECIAL leading byte, otherwise special keys will not
+ * work.
+ */
+ if (has_mbyte)
+ {
+ int len = 0;
+
+ /* Count the number of characters to be escaped. */
+ for (p = eap->arg; *p != NUL; ++p)
+ {
+# ifdef FEAT_GUI
+ if (*p == CSI) /* leadbyte CSI */
+ len += 2;
+# endif
+ for (l = (*mb_ptr2len_check)(p) - 1; l > 0; --l)
+ if (*++p == K_SPECIAL /* trailbyte K_SPECIAL or CSI */
+# ifdef FEAT_GUI
+ || *p == CSI
+# endif
+ )
+ len += 2;
+ }
+ if (len > 0)
+ {
+ arg = alloc((unsigned)(STRLEN(eap->arg) + len + 1));
+ if (arg != NULL)
+ {
+ len = 0;
+ for (p = eap->arg; *p != NUL; ++p)
+ {
+ arg[len++] = *p;
+# ifdef FEAT_GUI
+ if (*p == CSI)
+ {
+ arg[len++] = KS_EXTRA;
+ arg[len++] = (int)KE_CSI;
+ }
+# endif
+ for (l = (*mb_ptr2len_check)(p) - 1; l > 0; --l)
+ {
+ arg[len++] = *++p;
+ if (*p == K_SPECIAL)
+ {
+ arg[len++] = KS_SPECIAL;
+ arg[len++] = KE_FILLER;
+ }
+# ifdef FEAT_GUI
+ else if (*p == CSI)
+ {
+ arg[len++] = KS_EXTRA;
+ arg[len++] = (int)KE_CSI;
+ }
+# endif
+ }
+ arg[len] = NUL;
+ }
+ }
+ }
+ }
+#endif
+
+ /*
+ * Save the current typeahead. This is required to allow using ":normal"
+ * from an event handler and makes sure we don't hang when the argument
+ * ends with half a command.
+ */
+ save_typeahead(&tabuf);
+ if (tabuf.typebuf_valid)
+ {
+ /*
+ * Repeat the :normal command for each line in the range. When no
+ * range given, execute it just once, without positioning the cursor
+ * first.
+ */
+ do
+ {
+ clear_oparg(&oa);
+ finish_op = FALSE;
+ if (eap->addr_count != 0)
+ {
+ curwin->w_cursor.lnum = eap->line1++;
+ curwin->w_cursor.col = 0;
+ }
+
+ /*
+ * Stuff the argument into the typeahead buffer.
+ * Execute normal_cmd() until there is no typeahead left.
+ */
+ ins_typebuf(
+#ifdef FEAT_MBYTE
+ arg != NULL ? arg :
+#endif
+ eap->arg, eap->forceit ? REMAP_NONE : REMAP_YES, 0,
+ TRUE, FALSE);
+ while ((!stuff_empty() || (!typebuf_typed() && typebuf.tb_len > 0))
+ && !got_int)
+ {
+ update_topline_cursor();
+ normal_cmd(&oa, FALSE); /* execute a Normal mode cmd */
+ }
+ }
+ while (eap->addr_count > 0 && eap->line1 <= eap->line2 && !got_int);
+ }
+
+ /* Might not return to the main loop when in an event handler. */
+ update_topline_cursor();
+
+ /* Restore the previous typeahead. */
+ restore_typeahead(&tabuf);
+
+ --ex_normal_busy;
+ msg_scroll = save_msg_scroll;
+ restart_edit = save_restart_edit;
+ p_im = save_insertmode;
+ finish_op = save_finish_op;
+ msg_didout |= save_msg_didout; /* don't reset msg_didout now */
+
+ /* Restore the state (needed when called from a function executed for
+ * 'indentexpr'). */
+ State = save_State;
+#ifdef FEAT_MBYTE
+ vim_free(arg);
+#endif
+}
+
+/*
+ * ":startinsert"
+ */
+ static void
+ex_startinsert(eap)
+ exarg_T *eap;
+{
+ if (eap->forceit)
+ {
+ coladvance((colnr_T)MAXCOL);
+ curwin->w_curswant = MAXCOL;
+ curwin->w_set_curswant = FALSE;
+ restart_edit = 'a';
+ }
+ else
+ {
+ restart_edit = 'i';
+ curwin->w_curswant = 0; /* avoid MAXCOL */
+ }
+}
+
+/*
+ * ":stopinsert"
+ */
+/*ARGSUSED*/
+ static void
+ex_stopinsert(eap)
+ exarg_T *eap;
+{
+ restart_edit = 0;
+ stop_insert_mode = TRUE;
+}
+#endif
+
+#ifdef FEAT_FIND_ID
+ static void
+ex_checkpath(eap)
+ exarg_T *eap;
+{
+ find_pattern_in_path(NULL, 0, 0, FALSE, FALSE, CHECK_PATH, 1L,
+ eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW,
+ (linenr_T)1, (linenr_T)MAXLNUM);
+}
+
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+/*
+ * ":psearch"
+ */
+ static void
+ex_psearch(eap)
+ exarg_T *eap;
+{
+ g_do_tagpreview = p_pvh;
+ ex_findpat(eap);
+ g_do_tagpreview = 0;
+}
+#endif
+
+ static void
+ex_findpat(eap)
+ exarg_T *eap;
+{
+ int whole = TRUE;
+ long n;
+ char_u *p;
+ int action;
+
+ switch (cmdnames[eap->cmdidx].cmd_name[2])
+ {
+ case 'e': /* ":psearch", ":isearch" and ":dsearch" */
+ if (cmdnames[eap->cmdidx].cmd_name[0] == 'p')
+ action = ACTION_GOTO;
+ else
+ action = ACTION_SHOW;
+ break;
+ case 'i': /* ":ilist" and ":dlist" */
+ action = ACTION_SHOW_ALL;
+ break;
+ case 'u': /* ":ijump" and ":djump" */
+ action = ACTION_GOTO;
+ break;
+ default: /* ":isplit" and ":dsplit" */
+ action = ACTION_SPLIT;
+ break;
+ }
+
+ n = 1;
+ if (vim_isdigit(*eap->arg)) /* get count */
+ {
+ n = getdigits(&eap->arg);
+ eap->arg = skipwhite(eap->arg);
+ }
+ if (*eap->arg == '/') /* Match regexp, not just whole words */
+ {
+ whole = FALSE;
+ ++eap->arg;
+ p = skip_regexp(eap->arg, '/', p_magic, NULL);
+ if (*p)
+ {
+ *p++ = NUL;
+ p = skipwhite(p);
+
+ /* Check for trailing illegal characters */
+ if (!ends_excmd(*p))
+ eap->errmsg = e_trailing;
+ else
+ eap->nextcmd = check_nextcmd(p);
+ }
+ }
+ if (!eap->skip)
+ find_pattern_in_path(eap->arg, 0, (int)STRLEN(eap->arg),
+ whole, !eap->forceit,
+ *eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY,
+ n, action, eap->line1, eap->line2);
+}
+#endif
+
+#ifdef FEAT_WINDOWS
+
+# ifdef FEAT_QUICKFIX
+/*
+ * ":ptag", ":ptselect", ":ptjump", ":ptnext", etc.
+ */
+ static void
+ex_ptag(eap)
+ exarg_T *eap;
+{
+ g_do_tagpreview = p_pvh;
+ ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name + 1);
+}
+
+/*
+ * ":pedit"
+ */
+ static void
+ex_pedit(eap)
+ exarg_T *eap;
+{
+ win_T *curwin_save = curwin;
+
+ g_do_tagpreview = p_pvh;
+ prepare_tagpreview();
+ keep_help_flag = curwin_save->w_buffer->b_help;
+ do_exedit(eap, NULL);
+ keep_help_flag = FALSE;
+ if (curwin != curwin_save && win_valid(curwin_save))
+ {
+ /* Return cursor to where we were */
+ validate_cursor();
+ redraw_later(VALID);
+ win_enter(curwin_save, TRUE);
+ }
+ g_do_tagpreview = 0;
+}
+# endif
+
+/*
+ * ":stag", ":stselect" and ":stjump".
+ */
+ static void
+ex_stag(eap)
+ exarg_T *eap;
+{
+ postponed_split = -1;
+ postponed_split_flags = cmdmod.split;
+ ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name + 1);
+ postponed_split_flags = 0;
+}
+#endif
+
+/*
+ * ":tag", ":tselect", ":tjump", ":tnext", etc.
+ */
+ static void
+ex_tag(eap)
+ exarg_T *eap;
+{
+ ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name);
+}
+
+ static void
+ex_tag_cmd(eap, name)
+ exarg_T *eap;
+ char_u *name;
+{
+ int cmd;
+
+ switch (name[1])
+ {
+ case 'j': cmd = DT_JUMP; /* ":tjump" */
+ break;
+ case 's': cmd = DT_SELECT; /* ":tselect" */
+ break;
+ case 'p': cmd = DT_PREV; /* ":tprevious" */
+ break;
+ case 'N': cmd = DT_PREV; /* ":tNext" */
+ break;
+ case 'n': cmd = DT_NEXT; /* ":tnext" */
+ break;
+ case 'o': cmd = DT_POP; /* ":pop" */
+ break;
+ case 'f': /* ":tfirst" */
+ case 'r': cmd = DT_FIRST; /* ":trewind" */
+ break;
+ case 'l': cmd = DT_LAST; /* ":tlast" */
+ break;
+ default: /* ":tag" */
+#ifdef FEAT_CSCOPE
+ if (p_cst)
+ {
+ do_cstag(eap);
+ return;
+ }
+#endif
+ cmd = DT_TAG;
+ break;
+ }
+
+ do_tag(eap->arg, cmd, eap->addr_count > 0 ? (int)eap->line2 : 1,
+ eap->forceit, TRUE);
+}
+
+/*
+ * Evaluate cmdline variables.
+ *
+ * change '%' to curbuf->b_ffname
+ * '#' to curwin->w_altfile
+ * '<cword>' to word under the cursor
+ * '<cWORD>' to WORD under the cursor
+ * '<cfile>' to path name under the cursor
+ * '<sfile>' to sourced file name
+ * '<afile>' to file name for autocommand
+ * '<abuf>' to buffer number for autocommand
+ * '<amatch>' to matching name for autocommand
+ *
+ * When an error is detected, "errormsg" is set to a non-NULL pointer (may be
+ * "" for error without a message) and NULL is returned.
+ * Returns an allocated string if a valid match was found.
+ * Returns NULL if no match was found. "usedlen" then still contains the
+ * number of characters to skip.
+ */
+ char_u *
+eval_vars(src, usedlen, lnump, errormsg, srcstart)
+ char_u *src; /* pointer into commandline */
+ int *usedlen; /* characters after src that are used */
+ linenr_T *lnump; /* line number for :e command, or NULL */
+ char_u **errormsg; /* pointer to error message */
+ char_u *srcstart; /* beginning of valid memory for src */
+{
+ int i;
+ char_u *s;
+ char_u *result;
+ char_u *resultbuf = NULL;
+ int resultlen;
+ buf_T *buf;
+ int valid = VALID_HEAD + VALID_PATH; /* assume valid result */
+ int spec_idx;
+#ifdef FEAT_MODIFY_FNAME
+ int skip_mod = FALSE;
+#endif
+ static char *(spec_str[]) =
+ {
+ "%",
+#define SPEC_PERC 0
+ "#",
+#define SPEC_HASH 1
+ "<cword>", /* cursor word */
+#define SPEC_CWORD 2
+ "<cWORD>", /* cursor WORD */
+#define SPEC_CCWORD 3
+ "<cfile>", /* cursor path name */
+#define SPEC_CFILE 4
+ "<sfile>", /* ":so" file name */
+#define SPEC_SFILE 5
+#ifdef FEAT_AUTOCMD
+ "<afile>", /* autocommand file name */
+# define SPEC_AFILE 6
+ "<abuf>", /* autocommand buffer number */
+# define SPEC_ABUF 7
+ "<amatch>", /* autocommand match name */
+# define SPEC_AMATCH 8
+#endif
+#ifdef FEAT_CLIENTSERVER
+ "<client>"
+# define SPEC_CLIENT 9
+#endif
+ };
+#define SPEC_COUNT (sizeof(spec_str) / sizeof(char *))
+
+#if defined(FEAT_AUTOCMD) || defined(FEAT_CLIENTSERVER)
+ char_u strbuf[30];
+#endif
+
+ *errormsg = NULL;
+
+ /*
+ * Check if there is something to do.
+ */
+ for (spec_idx = 0; spec_idx < SPEC_COUNT; ++spec_idx)
+ {
+ *usedlen = (int)STRLEN(spec_str[spec_idx]);
+ if (STRNCMP(src, spec_str[spec_idx], *usedlen) == 0)
+ break;
+ }
+ if (spec_idx == SPEC_COUNT) /* no match */
+ {
+ *usedlen = 1;
+ return NULL;
+ }
+
+ /*
+ * Skip when preceded with a backslash "\%" and "\#".
+ * Note: In "\\%" the % is also not recognized!
+ */
+ if (src > srcstart && src[-1] == '\\')
+ {
+ *usedlen = 0;
+ STRCPY(src - 1, src); /* remove backslash */
+ return NULL;
+ }
+
+ /*
+ * word or WORD under cursor
+ */
+ if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD)
+ {
+ resultlen = find_ident_under_cursor(&result, spec_idx == SPEC_CWORD ?
+ (FIND_IDENT|FIND_STRING) : FIND_STRING);
+ if (resultlen == 0)
+ {
+ *errormsg = (char_u *)"";
+ return NULL;
+ }
+ }
+
+ /*
+ * '#': Alternate file name
+ * '%': Current file name
+ * File name under the cursor
+ * File name for autocommand
+ * and following modifiers
+ */
+ else
+ {
+ switch (spec_idx)
+ {
+ case SPEC_PERC: /* '%': current file */
+ if (curbuf->b_fname == NULL)
+ {
+ result = (char_u *)"";
+ valid = 0; /* Must have ":p:h" to be valid */
+ }
+ else
+#ifdef RISCOS
+ /* Always use the full path for RISC OS if possible. */
+ result = curbuf->b_ffname;
+ if (result == NULL)
+ result = curbuf->b_fname;
+#else
+ result = curbuf->b_fname;
+#endif
+ break;
+
+ case SPEC_HASH: /* '#' or "#99": alternate file */
+ if (src[1] == '#') /* "##": the argument list */
+ {
+ result = arg_all();
+ resultbuf = result;
+ *usedlen = 2;
+#ifdef FEAT_MODIFY_FNAME
+ skip_mod = TRUE;
+#endif
+ break;
+ }
+ s = src + 1;
+ i = (int)getdigits(&s);
+ *usedlen = (int)(s - src); /* length of what we expand */
+
+ buf = buflist_findnr(i);
+ if (buf == NULL)
+ {
+ *errormsg = (char_u *)_("E194: No alternate file name to substitute for '#'");
+ return NULL;
+ }
+ if (lnump != NULL)
+ *lnump = ECMD_LAST;
+ if (buf->b_fname == NULL)
+ {
+ result = (char_u *)"";
+ valid = 0; /* Must have ":p:h" to be valid */
+ }
+ else
+ result = buf->b_fname;
+ break;
+
+#ifdef FEAT_SEARCHPATH
+ case SPEC_CFILE: /* file name under cursor */
+ result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L);
+ if (result == NULL)
+ {
+ *errormsg = (char_u *)"";
+ return NULL;
+ }
+ resultbuf = result; /* remember allocated string */
+ break;
+#endif
+
+#ifdef FEAT_AUTOCMD
+ case SPEC_AFILE: /* file name for autocommand */
+ result = autocmd_fname;
+ if (result == NULL)
+ {
+ *errormsg = (char_u *)_("E495: no autocommand file name to substitute for \"<afile>\"");
+ return NULL;
+ }
+ break;
+
+ case SPEC_ABUF: /* buffer number for autocommand */
+ if (autocmd_bufnr <= 0)
+ {
+ *errormsg = (char_u *)_("E496: no autocommand buffer number to substitute for \"<abuf>\"");
+ return NULL;
+ }
+ sprintf((char *)strbuf, "%d", autocmd_bufnr);
+ result = strbuf;
+ break;
+
+ case SPEC_AMATCH: /* match name for autocommand */
+ result = autocmd_match;
+ if (result == NULL)
+ {
+ *errormsg = (char_u *)_("E497: no autocommand match name to substitute for \"<amatch>\"");
+ return NULL;
+ }
+ break;
+
+#endif
+ case SPEC_SFILE: /* file name for ":so" command */
+ result = sourcing_name;
+ if (result == NULL)
+ {
+ *errormsg = (char_u *)_("E498: no :source file name to substitute for \"<sfile>\"");
+ return NULL;
+ }
+ break;
+#if defined(FEAT_CLIENTSERVER)
+ case SPEC_CLIENT: /* Source of last submitted input */
+ sprintf((char *)strbuf, "0x%x", (unsigned int)clientWindow);
+ result = strbuf;
+ break;
+#endif
+ }
+
+ resultlen = (int)STRLEN(result); /* length of new string */
+ if (src[*usedlen] == '<') /* remove the file name extension */
+ {
+ ++*usedlen;
+#ifdef RISCOS
+ if ((s = vim_strrchr(result, '/')) != NULL && s >= gettail(result))
+#else
+ if ((s = vim_strrchr(result, '.')) != NULL && s >= gettail(result))
+#endif
+ resultlen = (int)(s - result);
+ }
+#ifdef FEAT_MODIFY_FNAME
+ else if (!skip_mod)
+ {
+ valid |= modify_fname(src, usedlen, &result, &resultbuf,
+ &resultlen);
+ if (result == NULL)
+ {
+ *errormsg = (char_u *)"";
+ return NULL;
+ }
+ }
+#endif
+ }
+
+ if (resultlen == 0 || valid != VALID_HEAD + VALID_PATH)
+ {
+ if (valid != VALID_HEAD + VALID_PATH)
+ /* xgettext:no-c-format */
+ *errormsg = (char_u *)_("E499: Empty file name for '%' or '#', only works with \":p:h\"");
+ else
+ *errormsg = (char_u *)_("E500: Evaluates to an empty string");
+ result = NULL;
+ }
+ else
+ result = vim_strnsave(result, resultlen);
+ vim_free(resultbuf);
+ return result;
+}
+
+/*
+ * Concatenate all files in the argument list, separated by spaces, and return
+ * it in one allocated string.
+ * Spaces and backslashes in the file names are escaped with a backslash.
+ * Returns NULL when out of memory.
+ */
+ static char_u *
+arg_all()
+{
+ int len;
+ int idx;
+ char_u *retval = NULL;
+ char_u *p;
+
+ /*
+ * Do this loop two times:
+ * first time: compute the total length
+ * second time: concatenate the names
+ */
+ for (;;)
+ {
+ len = 0;
+ for (idx = 0; idx < ARGCOUNT; ++idx)
+ {
+ p = alist_name(&ARGLIST[idx]);
+ if (p != NULL)
+ {
+ if (len > 0)
+ {
+ /* insert a space in between names */
+ if (retval != NULL)
+ retval[len] = ' ';
+ ++len;
+ }
+ for ( ; *p != NUL; ++p)
+ {
+ if (*p == ' ' || *p == '\\')
+ {
+ /* insert a backslash */
+ if (retval != NULL)
+ retval[len] = '\\';
+ ++len;
+ }
+ if (retval != NULL)
+ retval[len] = *p;
+ ++len;
+ }
+ }
+ }
+
+ /* second time: break here */
+ if (retval != NULL)
+ {
+ retval[len] = NUL;
+ break;
+ }
+
+ /* allocate memory */
+ retval = alloc(len + 1);
+ if (retval == NULL)
+ break;
+ }
+
+ return retval;
+}
+
+#if defined(FEAT_AUTOCMD) || defined(PROTO)
+/*
+ * Expand the <sfile> string in "arg".
+ *
+ * Returns an allocated string, or NULL for any error.
+ */
+ char_u *
+expand_sfile(arg)
+ char_u *arg;
+{
+ char_u *errormsg;
+ int len;
+ char_u *result;
+ char_u *newres;
+ char_u *repl;
+ int srclen;
+ char_u *p;
+
+ result = vim_strsave(arg);
+ if (result == NULL)
+ return NULL;
+
+ for (p = result; *p; )
+ {
+ if (STRNCMP(p, "<sfile>", 7) != 0)
+ ++p;
+ else
+ {
+ /* replace "<sfile>" with the sourced file name, and do ":" stuff */
+ repl = eval_vars(p, &srclen, NULL, &errormsg, result);
+ if (errormsg != NULL)
+ {
+ if (*errormsg)
+ emsg(errormsg);
+ vim_free(result);
+ return NULL;
+ }
+ if (repl == NULL) /* no match (cannot happen) */
+ {
+ p += srclen;
+ continue;
+ }
+ len = (int)STRLEN(result) - srclen + (int)STRLEN(repl) + 1;
+ newres = alloc(len);
+ if (newres == NULL)
+ {
+ vim_free(repl);
+ vim_free(result);
+ return NULL;
+ }
+ mch_memmove(newres, result, (size_t)(p - result));
+ STRCPY(newres + (p - result), repl);
+ len = (int)STRLEN(newres);
+ STRCAT(newres, p + srclen);
+ vim_free(repl);
+ vim_free(result);
+ result = newres;
+ p = newres + len; /* continue after the match */
+ }
+ }
+
+ return result;
+}
+#endif
+
+#ifdef FEAT_SESSION
+static int ses_winsizes __ARGS((FILE *fd, int restore_size));
+static int ses_win_rec __ARGS((FILE *fd, frame_T *fr));
+static frame_T *ses_skipframe __ARGS((frame_T *fr));
+static int ses_do_frame __ARGS((frame_T *fr));
+static int ses_do_win __ARGS((win_T *wp));
+static int ses_arglist __ARGS((FILE *fd, char *cmd, garray_T *gap, int fullname, unsigned *flagp));
+static int ses_put_fname __ARGS((FILE *fd, char_u *name, unsigned *flagp));
+static int ses_fname __ARGS((FILE *fd, buf_T *buf, unsigned *flagp));
+
+/*
+ * Write openfile commands for the current buffers to an .exrc file.
+ * Return FAIL on error, OK otherwise.
+ */
+ static int
+makeopens(fd, dirnow)
+ FILE *fd;
+ char_u *dirnow; /* Current directory name */
+{
+ buf_T *buf;
+ int only_save_windows = TRUE;
+ int nr;
+ int cnr = 1;
+ int restore_size = TRUE;
+ win_T *wp;
+ char_u *sname;
+ win_T *edited_win = NULL;
+
+ if (ssop_flags & SSOP_BUFFERS)
+ only_save_windows = FALSE; /* Save ALL buffers */
+
+ /*
+ * Begin by setting the this_session variable, and then other
+ * sessionable variables.
+ */
+#ifdef FEAT_EVAL
+ if (put_line(fd, "let v:this_session=expand(\"<sfile>:p\")") == FAIL)
+ return FAIL;
+ if (ssop_flags & SSOP_GLOBALS)
+ if (store_session_globals(fd) == FAIL)
+ return FAIL;
+#endif
+
+ /*
+ * Close all windows but one.
+ */
+ if (put_line(fd, "silent only") == FAIL)
+ return FAIL;
+
+ /*
+ * Now a :cd command to the session directory or the current directory
+ */
+ if (ssop_flags & SSOP_SESDIR)
+ {
+ if (put_line(fd, "exe \"cd \" . expand(\"<sfile>:p:h\")") == FAIL)
+ return FAIL;
+ }
+ else if (ssop_flags & SSOP_CURDIR)
+ {
+ sname = home_replace_save(NULL, globaldir != NULL ? globaldir : dirnow);
+ if (sname == NULL
+ || fprintf(fd, "cd %s", sname) < 0 || put_eol(fd) == FAIL)
+ return FAIL;
+ vim_free(sname);
+ }
+
+ /*
+ * Now save the current files, current buffer first.
+ */
+ if (put_line(fd, "set shortmess=aoO") == FAIL)
+ return FAIL;
+
+ /* Now put the other buffers into the buffer list */
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ if (!(only_save_windows && buf->b_nwindows == 0)
+ && !(buf->b_help && !(ssop_flags & SSOP_HELP))
+ && buf->b_fname != NULL
+ && buf->b_p_bl)
+ {
+ if (fprintf(fd, "badd +%ld ", buf->b_wininfo == NULL ? 1L
+ : buf->b_wininfo->wi_fpos.lnum) < 0
+ || ses_fname(fd, buf, &ssop_flags) == FAIL)
+ return FAIL;
+ }
+ }
+
+ /* the global argument list */
+ if (ses_arglist(fd, "args", &global_alist.al_ga,
+ !(ssop_flags & SSOP_CURDIR), &ssop_flags) == FAIL)
+ return FAIL;
+
+ if (ssop_flags & SSOP_RESIZE)
+ {
+ /* Note: after the restore we still check it worked!*/
+ if (fprintf(fd, "set lines=%ld columns=%ld" , Rows, Columns) < 0
+ || put_eol(fd) == FAIL)
+ return FAIL;
+ }
+
+#ifdef FEAT_GUI
+ if (gui.in_use && (ssop_flags & SSOP_WINPOS))
+ {
+ int x, y;
+
+ if (gui_mch_get_winpos(&x, &y) == OK)
+ {
+ /* Note: after the restore we still check it worked!*/
+ if (fprintf(fd, "winpos %d %d", x, y) < 0 || put_eol(fd) == FAIL)
+ return FAIL;
+ }
+ }
+#endif
+
+ /*
+ * Before creating the window layout, try loading one file. If this is
+ * aborted we don't end up with a number of useless windows.
+ * This may have side effects! (e.g., compressed or network file).
+ */
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ {
+ if (ses_do_win(wp)
+ && wp->w_buffer->b_ffname != NULL
+ && !wp->w_buffer->b_help
+#ifdef FEAT_QUICKFIX
+ && !bt_nofile(wp->w_buffer)
+#endif
+ )
+ {
+ if (fputs("edit ", fd) < 0
+ || ses_fname(fd, wp->w_buffer, &ssop_flags) == FAIL)
+ return FAIL;
+ if (!wp->w_arg_idx_invalid)
+ edited_win = wp;
+ break;
+ }
+ }
+
+ /*
+ * Save current window layout.
+ */
+ if (put_line(fd, "set splitbelow splitright") == FAIL)
+ return FAIL;
+ if (ses_win_rec(fd, topframe) == FAIL)
+ return FAIL;
+ if (!p_sb && put_line(fd, "set nosplitbelow") == FAIL)
+ return FAIL;
+ if (!p_spr && put_line(fd, "set nosplitright") == FAIL)
+ return FAIL;
+
+ /*
+ * Check if window sizes can be restored (no windows omitted).
+ * Remember the window number of the current window after restoring.
+ */
+ nr = 0;
+ for (wp = firstwin; wp != NULL; wp = W_NEXT(wp))
+ {
+ if (ses_do_win(wp))
+ ++nr;
+ else
+ restore_size = FALSE;
+ if (curwin == wp)
+ cnr = nr;
+ }
+
+ /* Go to the first window. */
+ if (put_line(fd, "wincmd t") == FAIL)
+ return FAIL;
+
+ /*
+ * If more than one window, see if sizes can be restored.
+ * First set 'winheight' and 'winwidth' to 1 to avoid the windows being
+ * resized when moving between windows.
+ * Do this before restoring the view, so that the topline and the cursor
+ * can be set. This is done again below.
+ */
+ if (put_line(fd, "set winheight=1 winwidth=1") == FAIL)
+ return FAIL;
+ if (nr > 1 && ses_winsizes(fd, restore_size) == FAIL)
+ return FAIL;
+
+ /*
+ * Restore the view of the window (options, file, cursor, etc.).
+ */
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ {
+ if (!ses_do_win(wp))
+ continue;
+ if (put_view(fd, wp, wp != edited_win, &ssop_flags) == FAIL)
+ return FAIL;
+ if (nr > 1 && put_line(fd, "wincmd w") == FAIL)
+ return FAIL;
+ }
+
+ /*
+ * Restore cursor to the current window if it's not the first one.
+ */
+ if (cnr > 1 && (fprintf(fd, "%dwincmd w", cnr) < 0 || put_eol(fd) == FAIL))
+ return FAIL;
+
+ /*
+ * Restore window sizes again after jumping around in windows, because the
+ * current window has a minimum size while others may not.
+ */
+ if (nr > 1 && ses_winsizes(fd, restore_size) == FAIL)
+ return FAIL;
+
+ /* Re-apply 'winheight', 'winwidth' and 'shortmess'. */
+ if (fprintf(fd, "set winheight=%ld winwidth=%ld shortmess=%s",
+ p_wh, p_wiw, p_shm) < 0 || put_eol(fd) == FAIL)
+ return FAIL;
+
+ /*
+ * Lastly, execute the x.vim file if it exists.
+ */
+ if (put_line(fd, "let s:sx = expand(\"<sfile>:p:r\").\"x.vim\"") == FAIL
+ || put_line(fd, "if file_readable(s:sx)") == FAIL
+ || put_line(fd, " exe \"source \" . s:sx") == FAIL
+ || put_line(fd, "endif") == FAIL)
+ return FAIL;
+
+ return OK;
+}
+
+ static int
+ses_winsizes(fd, restore_size)
+ FILE *fd;
+ int restore_size;
+{
+ int n = 0;
+ win_T *wp;
+
+ if (restore_size && (ssop_flags & SSOP_WINSIZE))
+ {
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ {
+ if (!ses_do_win(wp))
+ continue;
+ ++n;
+
+ /* restore height when not full height */
+ if (wp->w_height + wp->w_status_height < topframe->fr_height
+ && (fprintf(fd,
+ "exe '%dresize ' . ((&lines * %ld + %ld) / %ld)",
+ n, (long)wp->w_height, Rows / 2, Rows) < 0
+ || put_eol(fd) == FAIL))
+ return FAIL;
+
+ /* restore width when not full width */
+ if (wp->w_width < Columns && (fprintf(fd,
+ "exe 'vert %dresize ' . ((&columns * %ld + %ld) / %ld)",
+ n, (long)wp->w_width, Columns / 2, Columns) < 0
+ || put_eol(fd) == FAIL))
+ return FAIL;
+ }
+ }
+ else
+ {
+ /* Just equalise window sizes */
+ if (put_line(fd, "wincmd =") == FAIL)
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
+ * Write commands to "fd" to recursively create windows for frame "fr",
+ * horizontally and vertically split.
+ * After the commands the last window in the frame is the current window.
+ * Returns FAIL when writing the commands to "fd" fails.
+ */
+ static int
+ses_win_rec(fd, fr)
+ FILE *fd;
+ frame_T *fr;
+{
+ frame_T *frc;
+ int count = 0;
+
+ if (fr->fr_layout != FR_LEAF)
+ {
+ /* Find first frame that's not skipped and then create a window for
+ * each following one (first frame is already there). */
+ frc = ses_skipframe(fr->fr_child);
+ if (frc != NULL)
+ while ((frc = ses_skipframe(frc->fr_next)) != NULL)
+ {
+ /* Make window as big as possible so that we have lots of room
+ * to split. */
+ if (put_line(fd, "wincmd _ | wincmd |") == FAIL
+ || put_line(fd, fr->fr_layout == FR_COL
+ ? "split" : "vsplit") == FAIL)
+ return FAIL;
+ ++count;
+ }
+
+ /* Go back to the first window. */
+ if (count > 0 && (fprintf(fd, fr->fr_layout == FR_COL
+ ? "%dwincmd k" : "%dwincmd h", count) < 0
+ || put_eol(fd) == FAIL))
+ return FAIL;
+
+ /* Recursively create frames/windows in each window of this column or
+ * row. */
+ frc = ses_skipframe(fr->fr_child);
+ while (frc != NULL)
+ {
+ ses_win_rec(fd, frc);
+ frc = ses_skipframe(frc->fr_next);
+ /* Go to next window. */
+ if (frc != NULL && put_line(fd, "wincmd w") == FAIL)
+ return FAIL;
+ }
+ }
+ return OK;
+}
+
+/*
+ * Skip frames that don't contain windows we want to save in the Session.
+ * Returns NULL when there none.
+ */
+ static frame_T *
+ses_skipframe(fr)
+ frame_T *fr;
+{
+ frame_T *frc;
+
+ for (frc = fr; frc != NULL; frc = frc->fr_next)
+ if (ses_do_frame(frc))
+ break;
+ return frc;
+}
+
+/*
+ * Return TRUE if frame "fr" has a window somewhere that we want to save in
+ * the Session.
+ */
+ static int
+ses_do_frame(fr)
+ frame_T *fr;
+{
+ frame_T *frc;
+
+ if (fr->fr_layout == FR_LEAF)
+ return ses_do_win(fr->fr_win);
+ for (frc = fr->fr_child; frc != NULL; frc = frc->fr_next)
+ if (ses_do_frame(frc))
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Return non-zero if window "wp" is to be stored in the Session.
+ */
+ static int
+ses_do_win(wp)
+ win_T *wp;
+{
+ if (wp->w_buffer->b_fname == NULL
+#ifdef FEAT_QUICKFIX
+ /* When 'buftype' is "nofile" can't restore the window contents. */
+ || bt_nofile(wp->w_buffer)
+#endif
+ )
+ return (ssop_flags & SSOP_BLANK);
+ if (wp->w_buffer->b_help)
+ return (ssop_flags & SSOP_HELP);
+ return TRUE;
+}
+
+/*
+ * Write commands to "fd" to restore the view of a window.
+ * Caller must make sure 'scrolloff' is zero.
+ */
+ static int
+put_view(fd, wp, add_edit, flagp)
+ FILE *fd;
+ win_T *wp;
+ int add_edit; /* add ":edit" command to view */
+ unsigned *flagp; /* vop_flags or ssop_flags */
+{
+ win_T *save_curwin;
+ int f;
+ int do_cursor;
+
+ /* Always restore cursor position for ":mksession". For ":mkview" only
+ * when 'viewoptions' contains "cursor". */
+ do_cursor = (flagp == &ssop_flags || *flagp & SSOP_CURSOR);
+
+ /*
+ * Local argument list.
+ */
+ if (wp->w_alist == &global_alist)
+ {
+ if (put_line(fd, "argglobal") == FAIL)
+ return FAIL;
+ }
+ else
+ {
+ if (ses_arglist(fd, "arglocal", &wp->w_alist->al_ga,
+ flagp == &vop_flags
+ || !(*flagp & SSOP_CURDIR)
+ || wp->w_localdir != NULL, flagp) == FAIL)
+ return FAIL;
+ }
+
+ /* Only when part of a session: restore the argument index. */
+ if (wp->w_arg_idx != 0 && flagp == &ssop_flags)
+ {
+ if (fprintf(fd, "%ldnext", (long)wp->w_arg_idx) < 0
+ || put_eol(fd) == FAIL)
+ return FAIL;
+ }
+
+ /* Edit the file. Skip this when ":next" already did it. */
+ if (add_edit && (wp->w_arg_idx == 0 || flagp != &ssop_flags
+ || wp->w_arg_idx_invalid))
+ {
+ /*
+ * Load the file.
+ */
+ if (wp->w_buffer->b_ffname != NULL
+#ifdef FEAT_QUICKFIX
+ && !bt_nofile(wp->w_buffer)
+#endif
+ )
+ {
+ /*
+ * Editing a file in this buffer: use ":edit file".
+ * This may have side effects! (e.g., compressed or network file).
+ */
+ if (fputs("edit ", fd) < 0
+ || ses_fname(fd, wp->w_buffer, flagp) == FAIL)
+ return FAIL;
+ }
+ else
+ {
+ /* No file in this buffer, just make it empty. */
+ if (put_line(fd, "enew") == FAIL)
+ return FAIL;
+#ifdef FEAT_QUICKFIX
+ if (wp->w_buffer->b_ffname != NULL)
+ {
+ /* The buffer does have a name, but it's not a file name. */
+ if (fputs("file ", fd) < 0
+ || ses_fname(fd, wp->w_buffer, flagp) == FAIL)
+ return FAIL;
+ }
+#endif
+ do_cursor = FALSE;
+ }
+ }
+
+ /*
+ * Local mappings and abbreviations.
+ */
+ if ((*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS))
+ && makemap(fd, wp->w_buffer) == FAIL)
+ return FAIL;
+
+ /*
+ * Local options. Need to go to the window temporarily.
+ * Store only local values when using ":mkview" and when ":mksession" is
+ * used and 'sessionoptions' doesn't include "options".
+ * Some folding options are always stored when "folds" is included,
+ * otherwise the folds would not be restored correctly.
+ */
+ save_curwin = curwin;
+ curwin = wp;
+ curbuf = curwin->w_buffer;
+ if (*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS))
+ f = makeset(fd, OPT_LOCAL,
+ flagp == &vop_flags || !(*flagp & SSOP_OPTIONS));
+#ifdef FEAT_FOLDING
+ else if (*flagp & SSOP_FOLDS)
+ f = makefoldset(fd);
+#endif
+ else
+ f = OK;
+ curwin = save_curwin;
+ curbuf = curwin->w_buffer;
+ if (f == FAIL)
+ return FAIL;
+
+#ifdef FEAT_FOLDING
+ /*
+ * Save Folds when 'buftype' is empty and for help files.
+ */
+ if ((*flagp & SSOP_FOLDS)
+ && wp->w_buffer->b_ffname != NULL
+ && (*wp->w_buffer->b_p_bt == NUL || wp->w_buffer->b_help))
+ {
+ if (put_folds(fd, wp) == FAIL)
+ return FAIL;
+ }
+#endif
+
+ /*
+ * Set the cursor after creating folds, since that moves the cursor.
+ */
+ if (do_cursor)
+ {
+
+ /* Restore the cursor line in the file and relatively in the
+ * window. Don't use "G", it changes the jumplist. */
+ if (fprintf(fd, "let s:l = %ld - ((%ld * winheight(0) + %ld) / %ld)",
+ (long)wp->w_cursor.lnum,
+ (long)(wp->w_cursor.lnum - wp->w_topline),
+ (long)wp->w_height / 2, (long)wp->w_height) < 0
+ || put_eol(fd) == FAIL
+ || put_line(fd, "if s:l < 1 | let s:l = 1 | endif") == FAIL
+ || put_line(fd, "exe s:l") == FAIL
+ || put_line(fd, "normal! zt") == FAIL
+ || fprintf(fd, "%ld", (long)wp->w_cursor.lnum) < 0
+ || put_eol(fd) == FAIL)
+ return FAIL;
+ /* Restore the cursor column and left offset when not wrapping. */
+ if (wp->w_cursor.col == 0)
+ {
+ if (put_line(fd, "normal! 0") == FAIL)
+ return FAIL;
+ }
+ else
+ {
+ if (!wp->w_p_wrap && wp->w_leftcol > 0 && wp->w_width > 0)
+ {
+ if (fprintf(fd,
+ "let s:c = %ld - ((%ld * winwidth(0) + %ld) / %ld)",
+ (long)wp->w_cursor.col,
+ (long)(wp->w_cursor.col - wp->w_leftcol),
+ (long)wp->w_width / 2, (long)wp->w_width) < 0
+ || put_eol(fd) == FAIL
+ || put_line(fd, "if s:c > 0") == FAIL
+ || fprintf(fd,
+ " exe 'normal! 0' . s:c . 'lzs' . (%ld - s:c) . 'l'",
+ (long)wp->w_cursor.col) < 0
+ || put_eol(fd) == FAIL
+ || put_line(fd, "else") == FAIL
+ || fprintf(fd, " normal! 0%dl", wp->w_cursor.col) < 0
+ || put_eol(fd) == FAIL
+ || put_line(fd, "endif") == FAIL)
+ return FAIL;
+ }
+ else
+ {
+ if (fprintf(fd, "normal! 0%dl", wp->w_cursor.col) < 0
+ || put_eol(fd) == FAIL)
+ return FAIL;
+ }
+ }
+ }
+
+ /*
+ * Local directory.
+ */
+ if (wp->w_localdir != NULL)
+ {
+ if (fputs("lcd ", fd) < 0
+ || ses_put_fname(fd, wp->w_localdir, flagp) == FAIL
+ || put_eol(fd) == FAIL)
+ return FAIL;
+ }
+
+ return OK;
+}
+
+/*
+ * Write an argument list to the session file.
+ * Returns FAIL if writing fails.
+ */
+ static int
+ses_arglist(fd, cmd, gap, fullname, flagp)
+ FILE *fd;
+ char *cmd;
+ garray_T *gap;
+ int fullname; /* TRUE: use full path name */
+ unsigned *flagp;
+{
+ int i;
+ char_u buf[MAXPATHL];
+ char_u *s;
+
+ if (gap->ga_len == 0)
+ return put_line(fd, "silent! argdel *");
+ if (fputs(cmd, fd) < 0)
+ return FAIL;
+ for (i = 0; i < gap->ga_len; ++i)
+ {
+ /* NULL file names are skipped (only happens when out of memory). */
+ s = alist_name(&((aentry_T *)gap->ga_data)[i]);
+ if (s != NULL)
+ {
+ if (fullname)
+ {
+ (void)vim_FullName(s, buf, MAXPATHL, FALSE);
+ s = buf;
+ }
+ if (fputs(" ", fd) < 0 || ses_put_fname(fd, s, flagp) == FAIL)
+ return FAIL;
+ }
+ }
+ return put_eol(fd);
+}
+
+/*
+ * Write a buffer name to the session file.
+ * Also ends the line.
+ * Returns FAIL if writing fails.
+ */
+ static int
+ses_fname(fd, buf, flagp)
+ FILE *fd;
+ buf_T *buf;
+ unsigned *flagp;
+{
+ char_u *name;
+
+ /* Use the short file name if the current directory is known at the time
+ * the session file will be sourced. Don't do this for ":mkview", we
+ * don't know the current directory. */
+ if (buf->b_sfname != NULL
+ && flagp == &ssop_flags
+ && (ssop_flags & (SSOP_CURDIR | SSOP_SESDIR)))
+ name = buf->b_sfname;
+ else
+ name = buf->b_ffname;
+ if (ses_put_fname(fd, name, flagp) == FAIL || put_eol(fd) == FAIL)
+ return FAIL;
+ return OK;
+}
+
+/*
+ * Write a file name to the session file.
+ * Takes care of the "slash" option in 'sessionoptions' and escapes special
+ * characters.
+ * Returns FAIL if writing fails.
+ */
+ static int
+ses_put_fname(fd, name, flagp)
+ FILE *fd;
+ char_u *name;
+ unsigned *flagp;
+{
+ char_u *sname;
+ int retval = OK;
+ int c;
+
+ sname = home_replace_save(NULL, name);
+ if (sname != NULL)
+ name = sname;
+ while (*name != NUL)
+ {
+#ifdef FEAT_MBYTE
+ {
+ int l;
+
+ if (has_mbyte && (l = (*mb_ptr2len_check)(name)) > 1)
+ {
+ /* copy a multibyte char */
+ while (--l >= 0)
+ {
+ if (putc(*name, fd) != *name)
+ retval = FAIL;
+ ++name;
+ }
+ continue;
+ }
+ }
+#endif
+ c = *name++;
+ if (c == '\\' && (*flagp & SSOP_SLASH))
+ /* change a backslash to a forward slash */
+ c = '/';
+ else if ((vim_strchr(escape_chars, c) != NULL
+#ifdef BACKSLASH_IN_FILENAME
+ && c != '\\'
+#endif
+ ) || c == '#' || c == '%')
+ {
+ /* escape a special character with a backslash */
+ if (putc('\\', fd) != '\\')
+ retval = FAIL;
+ }
+ if (putc(c, fd) != c)
+ retval = FAIL;
+ }
+ vim_free(sname);
+ return retval;
+}
+
+/*
+ * ":loadview [nr]"
+ */
+ static void
+ex_loadview(eap)
+ exarg_T *eap;
+{
+ char_u *fname;
+
+ fname = get_view_file(*eap->arg);
+ if (fname != NULL)
+ {
+ do_source(fname, FALSE, FALSE);
+ vim_free(fname);
+ }
+}
+
+/*
+ * Get the name of the view file for the current buffer.
+ */
+ static char_u *
+get_view_file(c)
+ int c;
+{
+ int len = 0;
+ char_u *p, *s;
+ char_u *retval;
+ char_u *sname;
+
+ if (curbuf->b_ffname == NULL)
+ {
+ EMSG(_(e_noname));
+ return NULL;
+ }
+ sname = home_replace_save(NULL, curbuf->b_ffname);
+ if (sname == NULL)
+ return NULL;
+
+ /*
+ * We want a file name without separators, because we're not going to make
+ * a directory.
+ * "normal" path separator -> "=+"
+ * "=" -> "=="
+ * ":" path separator -> "=-"
+ */
+ for (p = sname; *p; ++p)
+ if (*p == '=' || vim_ispathsep(*p))
+ ++len;
+ retval = alloc((unsigned)(STRLEN(sname) + len + STRLEN(p_vdir) + 9));
+ if (retval != NULL)
+ {
+ STRCPY(retval, p_vdir);
+ add_pathsep(retval);
+ s = retval + STRLEN(retval);
+ for (p = sname; *p; ++p)
+ {
+ if (*p == '=')
+ {
+ *s++ = '=';
+ *s++ = '=';
+ }
+ else if (vim_ispathsep(*p))
+ {
+ *s++ = '=';
+#ifdef MACOS_CLASSIC /* TODO: Is it also needed for MACOS_X? (Dany) */
+ *s++ = '+';
+#else
+# if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA) || defined(RISCOS) \
+ || defined(VMS)
+ if (*p == ':')
+ *s++ = '-';
+ else
+# endif
+ *s++ = '+';
+#endif
+ }
+ else
+ *s++ = *p;
+ }
+ *s++ = '=';
+ *s++ = c;
+ STRCPY(s, ".vim");
+ }
+
+ vim_free(sname);
+ return retval;
+}
+
+#endif /* FEAT_SESSION */
+
+/*
+ * Write end-of-line character(s) for ":mkexrc", ":mkvimrc" and ":mksession".
+ * Return FAIL for a write error.
+ */
+ int
+put_eol(fd)
+ FILE *fd;
+{
+ if (
+#ifdef USE_CRNL
+ (
+# ifdef MKSESSION_NL
+ !mksession_nl &&
+# endif
+ (putc('\r', fd) < 0)) ||
+#endif
+ (putc('\n', fd) < 0))
+ return FAIL;
+ return OK;
+}
+
+/*
+ * Write a line to "fd".
+ * Return FAIL for a write error.
+ */
+ int
+put_line(fd, s)
+ FILE *fd;
+ char *s;
+{
+ if (fputs(s, fd) < 0 || put_eol(fd) == FAIL)
+ return FAIL;
+ return OK;
+}
+
+#ifdef FEAT_VIMINFO
+/*
+ * ":rviminfo" and ":wviminfo".
+ */
+ static void
+ex_viminfo(eap)
+ exarg_T *eap;
+{
+ char_u *save_viminfo;
+
+ save_viminfo = p_viminfo;
+ if (*p_viminfo == NUL)
+ p_viminfo = (char_u *)"'100";
+ if (eap->cmdidx == CMD_rviminfo)
+ {
+ if (read_viminfo(eap->arg, TRUE, TRUE, eap->forceit) == FAIL)
+ EMSG(_("E195: Cannot open viminfo file for reading"));
+ }
+ else
+ write_viminfo(eap->arg, eap->forceit);
+ p_viminfo = save_viminfo;
+}
+#endif
+
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
+ void
+dialog_msg(buff, format, fname)
+ char_u *buff;
+ char *format;
+ char_u *fname;
+{
+ int len;
+
+ if (fname == NULL)
+ fname = (char_u *)_("Untitled");
+ len = (int)STRLEN(format) + (int)STRLEN(fname);
+ if (len >= IOSIZE)
+ sprintf((char *)buff, format, (int)(IOSIZE - STRLEN(format)), fname);
+ else
+ sprintf((char *)buff, format, (int)STRLEN(fname), fname);
+}
+#endif
+
+/*
+ * ":behave {mswin,xterm}"
+ */
+ static void
+ex_behave(eap)
+ exarg_T *eap;
+{
+ if (STRCMP(eap->arg, "mswin") == 0)
+ {
+ set_option_value((char_u *)"selection", 0L, (char_u *)"exclusive", 0);
+ set_option_value((char_u *)"selectmode", 0L, (char_u *)"mouse,key", 0);
+ set_option_value((char_u *)"mousemodel", 0L, (char_u *)"popup", 0);
+ set_option_value((char_u *)"keymodel", 0L,
+ (char_u *)"startsel,stopsel", 0);
+ }
+ else if (STRCMP(eap->arg, "xterm") == 0)
+ {
+ set_option_value((char_u *)"selection", 0L, (char_u *)"inclusive", 0);
+ set_option_value((char_u *)"selectmode", 0L, (char_u *)"", 0);
+ set_option_value((char_u *)"mousemodel", 0L, (char_u *)"extend", 0);
+ set_option_value((char_u *)"keymodel", 0L, (char_u *)"", 0);
+ }
+ else
+ EMSG2(_(e_invarg2), eap->arg);
+}
+
+#ifdef FEAT_AUTOCMD
+static int filetype_detect = FALSE;
+static int filetype_plugin = FALSE;
+static int filetype_indent = FALSE;
+
+/*
+ * ":filetype [plugin] [indent] {on,off,detect}"
+ * on: Load the filetype.vim file to install autocommands for file types.
+ * off: Load the ftoff.vim file to remove all autocommands for file types.
+ * plugin on: load filetype.vim and ftplugin.vim
+ * plugin off: load ftplugof.vim
+ * indent on: load filetype.vim and indent.vim
+ * indent off: load indoff.vim
+ */
+ static void
+ex_filetype(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+ int plugin = FALSE;
+ int indent = FALSE;
+
+ if (*eap->arg == NUL)
+ {
+ /* Print current status. */
+ smsg((char_u *)"filetype detection:%s plugin:%s indent:%s",
+ filetype_detect ? "ON" : "OFF",
+ filetype_plugin ? (filetype_detect ? "ON" : "(on)") : "OFF",
+ filetype_indent ? (filetype_detect ? "ON" : "(on)") : "OFF");
+ return;
+ }
+
+ /* Accept "plugin" and "indent" in any order. */
+ for (;;)
+ {
+ if (STRNCMP(arg, "plugin", 6) == 0)
+ {
+ plugin = TRUE;
+ arg = skipwhite(arg + 6);
+ continue;
+ }
+ if (STRNCMP(arg, "indent", 6) == 0)
+ {
+ indent = TRUE;
+ arg = skipwhite(arg + 6);
+ continue;
+ }
+ break;
+ }
+ if (STRCMP(arg, "on") == 0 || STRCMP(arg, "detect") == 0)
+ {
+ if (*arg == 'o' || !filetype_detect)
+ {
+ cmd_runtime((char_u *)FILETYPE_FILE, TRUE);
+ filetype_detect = TRUE;
+ if (plugin)
+ {
+ cmd_runtime((char_u *)FTPLUGIN_FILE, TRUE);
+ filetype_plugin = TRUE;
+ }
+ if (indent)
+ {
+ cmd_runtime((char_u *)INDENT_FILE, TRUE);
+ filetype_indent = TRUE;
+ }
+ }
+ if (*arg == 'd')
+ {
+ (void)do_doautocmd((char_u *)"filetypedetect BufRead", TRUE);
+ do_modelines();
+ }
+ }
+ else if (STRCMP(arg, "off") == 0)
+ {
+ if (plugin || indent)
+ {
+ if (plugin)
+ {
+ cmd_runtime((char_u *)FTPLUGOF_FILE, TRUE);
+ filetype_plugin = FALSE;
+ }
+ if (indent)
+ {
+ cmd_runtime((char_u *)INDOFF_FILE, TRUE);
+ filetype_indent = FALSE;
+ }
+ }
+ else
+ {
+ cmd_runtime((char_u *)FTOFF_FILE, TRUE);
+ filetype_detect = FALSE;
+ }
+ }
+ else
+ EMSG2(_(e_invarg2), arg);
+}
+
+/*
+ * ":setfiletype {name}"
+ */
+ static void
+ex_setfiletype(eap)
+ exarg_T *eap;
+{
+ if (!did_filetype)
+ set_option_value((char_u *)"filetype", 0L, eap->arg, OPT_LOCAL);
+}
+#endif
+
+/*ARGSUSED*/
+ static void
+ex_digraphs(eap)
+ exarg_T *eap;
+{
+#ifdef FEAT_DIGRAPHS
+ if (*eap->arg != NUL)
+ putdigraph(eap->arg);
+ else
+ listdigraphs();
+#else
+ EMSG(_("E196: No digraphs in this version"));
+#endif
+}
+
+ static void
+ex_set(eap)
+ exarg_T *eap;
+{
+ int flags = 0;
+
+ if (eap->cmdidx == CMD_setlocal)
+ flags = OPT_LOCAL;
+ else if (eap->cmdidx == CMD_setglobal)
+ flags = OPT_GLOBAL;
+#if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD) && defined(FEAT_BROWSE)
+ if (cmdmod.browse && flags == 0)
+ ex_options(eap);
+ else
+#endif
+ (void)do_set(eap->arg, flags);
+}
+
+#ifdef FEAT_SEARCH_EXTRA
+/*
+ * ":nohlsearch"
+ */
+/*ARGSUSED*/
+ static void
+ex_nohlsearch(eap)
+ exarg_T *eap;
+{
+ no_hlsearch = TRUE;
+ redraw_all_later(NOT_VALID);
+}
+
+/*
+ * ":match {group} {pattern}"
+ * Sets nextcmd to the start of the next command, if any. Also called when
+ * skipping commands to find the next command.
+ */
+ static void
+ex_match(eap)
+ exarg_T *eap;
+{
+ char_u *p;
+ char_u *end;
+ int c;
+
+ /* First clear any old pattern. */
+ if (!eap->skip)
+ {
+ vim_free(curwin->w_match.regprog);
+ curwin->w_match.regprog = NULL;
+ redraw_later(NOT_VALID); /* always need a redraw */
+ }
+
+ if (ends_excmd(*eap->arg))
+ end = eap->arg;
+ else if ((STRNICMP(eap->arg, "none", 4) == 0
+ && (vim_iswhite(eap->arg[4]) || ends_excmd(eap->arg[4]))))
+ end = eap->arg + 4;
+ else
+ {
+ p = skiptowhite(eap->arg);
+ if (!eap->skip)
+ {
+ curwin->w_match_id = syn_namen2id(eap->arg, (int)(p - eap->arg));
+ if (curwin->w_match_id == 0)
+ {
+ EMSG2(_(e_nogroup), eap->arg);
+ return;
+ }
+ }
+ p = skipwhite(p);
+ if (*p == NUL)
+ {
+ /* There must be two arguments. */
+ EMSG2(_(e_invarg2), eap->arg);
+ return;
+ }
+ end = skip_regexp(p + 1, *p, TRUE, NULL);
+ if (!eap->skip)
+ {
+ if (*end != NUL && !ends_excmd(*skipwhite(end + 1)))
+ {
+ eap->errmsg = e_trailing;
+ return;
+ }
+
+ c = *end;
+ *end = NUL;
+ curwin->w_match.regprog = vim_regcomp(p + 1, RE_MAGIC);
+ *end = c;
+ if (curwin->w_match.regprog == NULL)
+ {
+ EMSG2(_(e_invarg2), p);
+ return;
+ }
+ }
+ }
+ eap->nextcmd = find_nextcmd(end);
+}
+#endif
+
+#ifdef FEAT_CRYPT
+/*
+ * ":X": Get crypt key
+ */
+/*ARGSUSED*/
+ static void
+ex_X(eap)
+ exarg_T *eap;
+{
+ (void)get_crypt_key(TRUE, TRUE);
+}
+#endif
+
+#ifdef FEAT_FOLDING
+ static void
+ex_fold(eap)
+ exarg_T *eap;
+{
+ if (foldManualAllowed(TRUE))
+ foldCreate(eap->line1, eap->line2);
+}
+
+ static void
+ex_foldopen(eap)
+ exarg_T *eap;
+{
+ opFoldRange(eap->line1, eap->line2, eap->cmdidx == CMD_foldopen,
+ eap->forceit, FALSE);
+}
+
+ static void
+ex_folddo(eap)
+ exarg_T *eap;
+{
+ linenr_T lnum;
+
+ /* First set the marks for all lines closed/open. */
+ for (lnum = eap->line1; lnum <= eap->line2; ++lnum)
+ if (hasFolding(lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed))
+ ml_setmarked(lnum);
+
+ /* Execute the command on the marked lines. */
+ global_exe(eap->arg);
+ ml_clearmarked(); /* clear rest of the marks */
+}
+#endif
diff --git a/src/ex_eval.c b/src/ex_eval.c
new file mode 100644
index 000000000..921d60867
--- /dev/null
+++ b/src/ex_eval.c
@@ -0,0 +1,2004 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * ex_eval.c: functions for Ex command line for the +eval feature.
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+
+static void free_msglist __ARGS((struct msglist *l));
+static int throw_exception __ARGS((void *, int, char_u *));
+static void rewind_conditionals __ARGS((struct condstack *,
+ int, int, int *));
+
+/*
+ * Exception handling terms:
+ *
+ * :try ":try" command \
+ * ... try block |
+ * :catch RE ":catch" command |
+ * ... catch clause |- try conditional
+ * :finally ":finally" command |
+ * ... finally clause |
+ * :endtry ":endtry" command /
+ *
+ * The try conditional may have any number of catch clauses and at most one
+ * finally clause. A ":throw" command can be inside the try block, a catch
+ * clause, the finally clause, or in a function called or script sourced from
+ * there or even outside the try conditional. Try conditionals may be nested.
+ */
+
+/*
+ * Configuration whether an exception is thrown on error or interrupt. When
+ * the preprocessor macros below evaluate to FALSE, an error (did_emsg) or
+ * interrupt (got_int) under an active try conditional terminates the script
+ * after the non-active finally clauses of all active try conditionals have been
+ * executed. Otherwise, errors and/or interrupts are converted into catchable
+ * exceptions (did_throw additionally set), which terminate the script only if
+ * not caught. For user exceptions, only did_throw is set. (Note: got_int can
+ * be set asyncronously afterwards by a SIGINT, so did_throw && got_int is not
+ * a reliant test that the exception currently being thrown is an interrupt
+ * exception. Similarly, did_emsg can be set afterwards on an error in an
+ * (unskipped) conditional command inside an inactive conditional, so did_throw
+ * && did_emsg is not a reliant test that the exception currently being thrown
+ * is an error exception.) - The macros can be defined as expressions checking
+ * for a variable that is allowed to be changed during execution of a script.
+ */
+#if 0
+/* Expressions used for testing during the development phase. */
+# define THROW_ON_ERROR (!eval_to_number("$VIMNOERRTHROW"))
+# define THROW_ON_INTERRUPT (!eval_to_number("$VIMNOINTTHROW"))
+# define THROW_TEST
+#else
+/* Values used for the Vim release. */
+# define THROW_ON_ERROR TRUE
+# define THROW_ON_INTERRUPT TRUE
+#endif
+
+static void catch_exception __ARGS((except_T *excp));
+static void finish_exception __ARGS((except_T *excp));
+static void discard_exception __ARGS((except_T *excp, int was_finished));
+static void report_pending __ARGS((int action, int pending, void *value));
+
+/*
+ * When several errors appear in a row, setting "force_abort" is delayed until
+ * the failing command returned. "cause_abort" is set to TRUE meanwhile, in
+ * order to indicate that situation. This is useful when "force_abort" was set
+ * during execution of a function call from an expression: the aborting of the
+ * expression evaluation is done without producing any error messages, but all
+ * error messages on parsing errors during the expression evaluation are given
+ * (even if a try conditional is active).
+ */
+static int cause_abort = FALSE;
+
+/*
+ * Return TRUE when immdediately aborting on error, or when an interrupt
+ * occurred or an exception was thrown but not caught. Use for ":{range}call"
+ * to check whether an aborted function that does not handle a range itself
+ * should be called again for the next line in the range. Also used for
+ * cancelling expression evaluation after a function call caused an immediate
+ * abort. Note that the first emsg() call temporarily resets "force_abort"
+ * until the throw point for error messages has been reached. That is, during
+ * cancellation of an expression evaluation after an aborting function call or
+ * due to a parsing error, aborting() always returns the same value.
+ */
+ int
+aborting()
+{
+ return (did_emsg && force_abort) || got_int || did_throw;
+}
+
+/*
+ * The value of "force_abort" is temporarily reset by the first emsg() call
+ * during an expression evaluation, and "cause_abort" is used instead. It might
+ * be necessary to restore "force_abort" even before the throw point for the
+ * error message has been reached. update_force_abort() should be called then.
+ */
+ void
+update_force_abort()
+{
+ if (cause_abort)
+ force_abort = TRUE;
+}
+
+/*
+ * Return TRUE if a command with a subcommand resulting in "retcode" should
+ * abort the script processing. Can be used to suppress an autocommand after
+ * execution of a failing subcommand as long as the error message has not been
+ * displayed and actually caused the abortion.
+ */
+ int
+should_abort(retcode)
+ int retcode;
+{
+ return ((retcode == FAIL && trylevel != 0 && !emsg_silent) || aborting());
+}
+
+/*
+ * Return TRUE if a function with the "abort" flag should not be considered
+ * ended on an error. This means that parsing commands is continued in order
+ * to find finally clauses to be executed, and that some errors in skipped
+ * commands are still reported.
+ */
+ int
+aborted_in_try()
+{
+ /* This function is only called after an error. In this case, "force_abort"
+ * determines whether searching for finally clauses is necessary. */
+ return force_abort;
+}
+
+/*
+ * cause_errthrow(): Cause a throw of an error exception if appropriate.
+ * Return TRUE if the error message should not be displayed by emsg().
+ * Sets "ignore", if the emsg() call should be ignored completely.
+ *
+ * When several messages appear in the same command, the first is usually the
+ * most specific one and used as the exception value. The "severe" flag can be
+ * set to TRUE, if a later but severer message should be used instead.
+ */
+ int
+cause_errthrow(mesg, severe, ignore)
+ char_u *mesg;
+ int severe;
+ int *ignore;
+{
+ struct msglist *elem;
+ struct msglist **plist;
+
+ /*
+ * Do nothing when displaying the interrupt message or reporting an uncaught
+ * exception (which has already been discarded then) at the top level. Also
+ * when no exception can be thrown. The message will be displayed by
+ * emsg().
+ */
+ if (suppress_errthrow)
+ return FALSE;
+
+ /*
+ * If emsg() has not been called previously, temporarily reset "force_abort"
+ * until the throw point for error messages has been reached. This ensures
+ * that aborting() returns the same value for all errors that appear in the
+ * same command. This means particularly that for parsing errors during
+ * expression evaluation emsg() will be called multiply, even when the
+ * expression is evaluated from a finally clause that was activated due to
+ * an aborting error, interrupt, or exception.
+ */
+ if (!did_emsg)
+ {
+ cause_abort = force_abort;
+ force_abort = FALSE;
+ }
+
+ /*
+ * If no try conditional is active and no exception is being thrown and
+ * there has not been an error in a try conditional or a throw so far, do
+ * nothing (for compatibility of non-EH scripts). The message will then be
+ * displayed by emsg(). When ":silent!" was used and we are not currently
+ * throwing an exception, do nothing. The message text will then be stored
+ * to v:errmsg by emsg() without displaying it.
+ */
+ if (((trylevel == 0 && !cause_abort) || emsg_silent) && !did_throw)
+ return FALSE;
+
+ /*
+ * Ignore an interrupt message when inside a try conditional or when an
+ * exception is being thrown or when an error in a try conditional or throw
+ * has been detected previously. This is important in order that an
+ * interrupt exception is catchable by the innermost try conditional and
+ * not replaced by an interrupt message error exception.
+ */
+ if (mesg == (char_u *)_(e_interr))
+ {
+ *ignore = TRUE;
+ return TRUE;
+ }
+
+ /*
+ * Ensure that all commands in nested function calls and sourced files
+ * are aborted immediately.
+ */
+ cause_abort = TRUE;
+
+ /*
+ * When an exception is being thrown, some commands (like conditionals) are
+ * not skipped. Errors in those commands may affect what of the subsequent
+ * commands are regarded part of catch and finally clauses. Catching the
+ * exception would then cause execution of commands not intended by the
+ * user, who wouldn't even get aware of the problem. Therefor, discard the
+ * exception currently being thrown to prevent it from being caught. Just
+ * execute finally clauses and terminate.
+ */
+ if (did_throw)
+ {
+ /* When discarding an interrupt exception, reset got_int to prevent the
+ * same interrupt being converted to an exception again and discarding
+ * the error exception we are about to throw here. */
+ if (current_exception->type == ET_INTERRUPT)
+ got_int = FALSE;
+ discard_current_exception();
+ }
+
+#ifdef THROW_TEST
+ if (!THROW_ON_ERROR)
+ {
+ /*
+ * Print error message immediately without searching for a matching
+ * catch clause; just finally clauses are executed before the script
+ * is terminated.
+ */
+ return FALSE;
+ }
+ else
+#endif
+ {
+ /*
+ * Prepare the throw of an error exception, so that everything will
+ * be aborted (except for executing finally clauses), until the error
+ * exception is caught; if still uncaught at the top level, the error
+ * message will be displayed and the script processing terminated
+ * then. - This function has no access to the conditional stack.
+ * Thus, the actual throw is made after the failing command has
+ * returned. - Throw only the first of several errors in a row, except
+ * a severe error is following.
+ */
+ if (msg_list != NULL)
+ {
+ plist = msg_list;
+ while (*plist != NULL)
+ plist = &(*plist)->next;
+
+ elem = (struct msglist *)alloc((unsigned)sizeof(struct msglist));
+ if (elem == NULL)
+ {
+ suppress_errthrow = TRUE;
+ EMSG(_(e_outofmem));
+ }
+ else
+ {
+ elem->msg = vim_strsave(mesg);
+ if (elem->msg == NULL)
+ {
+ vim_free(elem);
+ suppress_errthrow = TRUE;
+ EMSG(_(e_outofmem));
+ }
+ else
+ {
+ elem->next = NULL;
+ elem->throw_msg = NULL;
+ *plist = elem;
+ if (plist == msg_list || severe)
+ {
+ char_u *tmsg;
+
+ /* Skip the extra "Vim " prefix for message "E458". */
+ tmsg = elem->msg;
+ if (STRNCMP(tmsg, "Vim E", 5) == 0
+ && VIM_ISDIGIT(tmsg[5])
+ && VIM_ISDIGIT(tmsg[6])
+ && VIM_ISDIGIT(tmsg[7])
+ && tmsg[8] == ':'
+ && tmsg[9] == ' ')
+ (*msg_list)->throw_msg = &tmsg[4];
+ else
+ (*msg_list)->throw_msg = tmsg;
+ }
+ }
+ }
+ }
+ return TRUE;
+ }
+}
+
+/*
+ * Free a "msg_list" and the messages it contains.
+ */
+ static void
+free_msglist(l)
+ struct msglist *l;
+{
+ struct msglist *messages, *next;
+
+ messages = l;
+ while (messages != NULL)
+ {
+ next = messages->next;
+ vim_free(messages->msg);
+ vim_free(messages);
+ messages = next;
+ }
+}
+
+/*
+ * Throw the message specified in the call to cause_errthrow() above as an
+ * error exception. If cstack is NULL, postpone the throw until do_cmdline()
+ * has returned (see do_one_cmd()).
+ */
+ void
+do_errthrow(cstack, cmdname)
+ struct condstack *cstack;
+ char_u *cmdname;
+{
+ /*
+ * Ensure that all commands in nested function calls and sourced files
+ * are aborted immediately.
+ */
+ if (cause_abort)
+ {
+ cause_abort = FALSE;
+ force_abort = TRUE;
+ }
+
+ /* If no exception is to be thrown or the conversion should be done after
+ * returning to a previous invocation of do_one_cmd(), do nothing. */
+ if (*msg_list == NULL)
+ return;
+
+ if (throw_exception(*msg_list, ET_ERROR, cmdname) == FAIL)
+ free_msglist(*msg_list);
+ else
+ {
+ if (cstack != NULL)
+ do_throw(cstack);
+ else
+ need_rethrow = TRUE;
+ }
+ *msg_list = NULL;
+}
+
+/*
+ * do_intthrow(): Replace the current exception by an interrupt or interrupt
+ * exception if appropriate. Return TRUE if the current exception is discarded,
+ * FALSE otherwise.
+ */
+ int
+do_intthrow(cstack)
+ struct condstack *cstack;
+{
+ /*
+ * If no interrupt occurred or no try conditional is active and no exception
+ * is being thrown, do nothing (for compatibility of non-EH scripts).
+ */
+ if (!got_int || (trylevel == 0 && !did_throw))
+ return FALSE;
+
+#ifdef THROW_TEST /* avoid warning for condition always true */
+ if (!THROW_ON_INTERRUPT)
+ {
+ /*
+ * The interrupt aborts everything except for executing finally clauses.
+ * Discard any user or error or interrupt exception currently being
+ * thrown.
+ */
+ if (did_throw)
+ discard_current_exception();
+ }
+ else
+#endif
+ {
+ /*
+ * Throw an interrupt exception, so that everything will be aborted
+ * (except for executing finally clauses), until the interrupt exception
+ * is caught; if still uncaught at the top level, the script processing
+ * will be terminated then. - If an interrupt exception is already
+ * being thrown, do nothing.
+ *
+ */
+ if (did_throw)
+ {
+ if (current_exception->type == ET_INTERRUPT)
+ return FALSE;
+
+ /* An interrupt exception replaces any user or error exception. */
+ discard_current_exception();
+ }
+ if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) != FAIL)
+ do_throw(cstack);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Throw a new exception. Return FAIL when out of memory or it was tried to
+ * throw an illegal user exception. "value" is the exception string for a user
+ * or interrupt exception, or points to a message list in case of an error
+ * exception.
+ */
+ static int
+throw_exception(value, type, cmdname)
+ void *value;
+ int type;
+ char_u *cmdname;
+{
+ except_T *excp;
+ char_u *p, *mesg, *val;
+ int cmdlen;
+
+ /*
+ * Disallow faking Interrupt or error exceptions as user exceptions. They
+ * would be treated differently from real interrupt or error exceptions when
+ * no active try block is found, see do_cmdline().
+ */
+ if (type == ET_USER)
+ {
+ if (STRNCMP((char_u *)value, "Vim", 3) == 0 &&
+ (((char_u *)value)[3] == NUL || ((char_u *)value)[3] == ':' ||
+ ((char_u *)value)[3] == '('))
+ {
+ EMSG(_("E608: Cannot :throw exceptions with 'Vim' prefix"));
+ goto fail;
+ }
+ }
+
+ excp = (except_T *)alloc((unsigned)sizeof(except_T));
+ if (excp == NULL)
+ goto nomem;
+
+ if (type == ET_ERROR)
+ {
+ /* Store the original message and prefix the exception value with
+ * "Vim:" or, if a command name is given, "Vim(cmdname):". */
+ excp->messages = (struct msglist *)value;
+ mesg = excp->messages->throw_msg;
+ if (cmdname != NULL && *cmdname != NUL)
+ {
+ cmdlen = STRLEN(cmdname);
+ excp->value = vim_strnsave((char_u *)"Vim(",
+ 4 + cmdlen + 2 + (int)STRLEN(mesg));
+ if (excp->value == NULL)
+ goto nomem;
+ STRCPY(&excp->value[4], cmdname);
+ STRCPY(&excp->value[4 + cmdlen], "):");
+ val = excp->value + 4 + cmdlen + 2;
+ }
+ else
+ {
+ excp->value = vim_strnsave((char_u *)"Vim:", 4 + (int)STRLEN(mesg));
+ if (excp->value == NULL)
+ goto nomem;
+ val = excp->value + 4;
+ }
+
+ /* msg_add_fname may have been used to prefix the message with a file
+ * name in quotes. In the exception value, put the file name in
+ * parentheses and move it to the end. */
+ for (p = mesg; ; p++)
+ {
+ if (*p == NUL
+ || (*p == 'E'
+ && VIM_ISDIGIT(p[1])
+ && (p[2] == ':'
+ || (VIM_ISDIGIT(p[2])
+ && (p[3] == ':'
+ || (VIM_ISDIGIT(p[3])
+ && p[4] == ':'))))))
+ {
+ if (*p == NUL || p == mesg) /* 'E123' missing or at beginning */
+ STRCAT(val, mesg);
+ else
+ {
+ /* '"filename" E123: message text' */
+ if (mesg[0] != '"' || p-2 < &mesg[1] ||
+ p[-2] != '"' || p[-1] != ' ')
+ /* "E123:" is part of the file name. */
+ continue;
+
+ STRCAT(val, p);
+ p[-2] = NUL;
+ sprintf((char *)(val + STRLEN(p)), " (%s)", &mesg[1]);
+ p[-2] = '"';
+ }
+ break;
+ }
+ }
+ }
+ else
+ excp->value = value;
+
+ excp->type = type;
+ excp->throw_name = vim_strsave(sourcing_name == NULL
+ ? (char_u *)"" : sourcing_name);
+ if (excp->throw_name == NULL)
+ {
+ if (type == ET_ERROR)
+ vim_free(excp->value);
+ goto nomem;
+ }
+ excp->throw_lnum = sourcing_lnum;
+
+ if (p_verbose >= 13 || debug_break_level > 0)
+ {
+ int save_msg_silent = msg_silent;
+
+ if (debug_break_level > 0)
+ msg_silent = FALSE; /* display messages */
+ ++no_wait_return;
+ msg_scroll = TRUE; /* always scroll up, don't overwrite */
+ msg_str((char_u *)_("Exception thrown: %s"), excp->value);
+ msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ cmdline_row = msg_row;
+ --no_wait_return;
+ if (debug_break_level > 0)
+ msg_silent = save_msg_silent;
+ }
+
+ current_exception = excp;
+ return OK;
+
+nomem:
+ vim_free(excp);
+ suppress_errthrow = TRUE;
+ EMSG(_(e_outofmem));
+fail:
+ current_exception = NULL;
+ return FAIL;
+}
+
+/*
+ * Discard an exception. "was_finished" is set when the exception has been
+ * caught and the catch clause has been ended normally.
+ */
+ static void
+discard_exception(excp, was_finished)
+ except_T *excp;
+ int was_finished;
+{
+ char_u *saved_IObuff;
+
+ if (excp == NULL)
+ {
+ EMSG(_(e_internal));
+ return;
+ }
+
+ if (p_verbose >= 13 || debug_break_level > 0)
+ {
+ int save_msg_silent = msg_silent;
+
+ saved_IObuff = vim_strsave(IObuff);
+ if (debug_break_level > 0)
+ msg_silent = FALSE; /* display messages */
+ ++no_wait_return;
+ msg_scroll = TRUE; /* always scroll up, don't overwrite */
+ msg_str(was_finished
+ ? (char_u *)_("Exception finished: %s")
+ : (char_u *)_("Exception discarded: %s"),
+ excp->value);
+ msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ cmdline_row = msg_row;
+ --no_wait_return;
+ if (debug_break_level > 0)
+ msg_silent = save_msg_silent;
+ STRCPY(IObuff, saved_IObuff);
+ vim_free(saved_IObuff);
+ }
+ if (excp->type != ET_INTERRUPT)
+ vim_free(excp->value);
+ if (excp->type == ET_ERROR)
+ free_msglist(excp->messages);
+ vim_free(excp->throw_name);
+ vim_free(excp);
+}
+
+/*
+ * Discard the exception currently being thrown.
+ */
+ void
+discard_current_exception()
+{
+ discard_exception(current_exception, FALSE);
+ current_exception = NULL;
+ did_throw = FALSE;
+ need_rethrow = FALSE;
+}
+
+/*
+ * Put an exception on the caught stack.
+ */
+ static void
+catch_exception(excp)
+ except_T *excp;
+{
+ excp->caught = caught_stack;
+ caught_stack = excp;
+ set_vim_var_string(VV_EXCEPTION, excp->value, -1);
+ if (*excp->throw_name != NUL)
+ {
+ if (excp->throw_lnum != 0)
+ sprintf((char *)IObuff, _("%s, line %ld"), excp->throw_name,
+ (long)excp->throw_lnum);
+ else
+ STRCPY(IObuff, excp->throw_name);
+ set_vim_var_string(VV_THROWPOINT, IObuff, -1);
+ }
+ else
+ /* throw_name not set on an exception from a command that was typed. */
+ set_vim_var_string(VV_THROWPOINT, NULL, -1);
+
+ if (p_verbose >= 13 || debug_break_level > 0)
+ {
+ int save_msg_silent = msg_silent;
+
+ if (debug_break_level > 0)
+ msg_silent = FALSE; /* display messages */
+ ++no_wait_return;
+ msg_scroll = TRUE; /* always scroll up, don't overwrite */
+ msg_str((char_u *)_("Exception caught: %s"), excp->value);
+ msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ cmdline_row = msg_row;
+ --no_wait_return;
+ if (debug_break_level > 0)
+ msg_silent = save_msg_silent;
+ }
+}
+
+/*
+ * Remove an exception from the caught stack.
+ */
+ static void
+finish_exception(excp)
+ except_T *excp;
+{
+ if (excp != caught_stack)
+ EMSG(_(e_internal));
+ caught_stack = caught_stack->caught;
+ if (caught_stack != NULL)
+ {
+ set_vim_var_string(VV_EXCEPTION, caught_stack->value, -1);
+ if (*caught_stack->throw_name != NUL)
+ {
+ if (caught_stack->throw_lnum != 0)
+ sprintf((char *)IObuff,
+ _("%s, line %ld"), caught_stack->throw_name,
+ (long)caught_stack->throw_lnum);
+ else
+ STRCPY(IObuff, caught_stack->throw_name);
+ set_vim_var_string(VV_THROWPOINT, IObuff, -1);
+ }
+ else
+ /* throw_name not set on an exception from a command that was
+ * typed. */
+ set_vim_var_string(VV_THROWPOINT, NULL, -1);
+ }
+ else
+ {
+ set_vim_var_string(VV_EXCEPTION, NULL, -1);
+ set_vim_var_string(VV_THROWPOINT, NULL, -1);
+ }
+
+ /* Discard the exception, but use the finish message for 'verbose'. */
+ discard_exception(excp, TRUE);
+}
+
+/*
+ * Flags specifying the message displayed by report_pending.
+ */
+#define RP_MAKE 0
+#define RP_RESUME 1
+#define RP_DISCARD 2
+
+/*
+ * Report information about something pending in a finally clause if required by
+ * the 'verbose' option or when debugging. "action" tells whether something is
+ * made pending or something pending is resumed or discarded. "pending" tells
+ * what is pending. "value" specifies the return value for a pending ":return"
+ * or the exception value for a pending exception.
+ */
+ static void
+report_pending(action, pending, value)
+ int action;
+ int pending;
+ void *value;
+{
+ char_u *mesg;
+ char *s;
+ int save_msg_silent;
+
+
+ switch (action)
+ {
+ case RP_MAKE:
+ mesg = (char_u *)_("%s made pending");
+ break;
+ case RP_RESUME:
+ mesg = (char_u *)_("%s resumed");
+ break;
+ /* case RP_DISCARD: */
+ default:
+ mesg = (char_u *)_("%s discarded");
+ break;
+ }
+
+ switch (pending)
+ {
+ case CSTP_NONE:
+ return;
+
+ case CSTP_CONTINUE:
+ s = ":continue";
+ break;
+ case CSTP_BREAK:
+ s = ":break";
+ break;
+ case CSTP_FINISH:
+ s = ":finish";
+ break;
+ case CSTP_RETURN:
+ /* ":return" command producing value, allocated */
+ s = (char *)get_return_cmd(value);
+ break;
+
+ default:
+ if (pending & CSTP_THROW)
+ {
+ sprintf((char *)IObuff, (char *)mesg, _("Exception"));
+ mesg = vim_strnsave(IObuff, (int)STRLEN(IObuff) + 4);
+ STRCAT(mesg, ": %s");
+ s = (char *)((except_T *)value)->value;
+ }
+ else if ((pending & CSTP_ERROR) && (pending & CSTP_INTERRUPT))
+ s = _("Error and interrupt");
+ else if (pending & CSTP_ERROR)
+ s = _("Error");
+ else /* if (pending & CSTP_INTERRUPT) */
+ s = _("Interrupt");
+ }
+
+ save_msg_silent = msg_silent;
+ if (debug_break_level > 0)
+ msg_silent = FALSE; /* display messages */
+ ++no_wait_return;
+ msg_scroll = TRUE; /* always scroll up, don't overwrite */
+ msg_str(mesg, (char_u *)s);
+ msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ cmdline_row = msg_row;
+ --no_wait_return;
+ if (debug_break_level > 0)
+ msg_silent = save_msg_silent;
+
+ if (pending == CSTP_RETURN)
+ vim_free(s);
+ else if (pending & CSTP_THROW)
+ vim_free(mesg);
+}
+
+/*
+ * If something is made pending in a finally clause, report it if required by
+ * the 'verbose' option or when debugging.
+ */
+ void
+report_make_pending(pending, value)
+ int pending;
+ void *value;
+{
+ if (p_verbose >= 14 || debug_break_level > 0)
+ report_pending(RP_MAKE, pending, value);
+}
+
+/*
+ * If something pending in a finally clause is resumed at the ":endtry", report
+ * it if required by the 'verbose' option or when debugging.
+ */
+ void
+report_resume_pending(pending, value)
+ int pending;
+ void *value;
+{
+ if (p_verbose >= 14 || debug_break_level > 0)
+ report_pending(RP_RESUME, pending, value);
+}
+
+/*
+ * If something pending in a finally clause is discarded, report it if required
+ * by the 'verbose' option or when debugging.
+ */
+ void
+report_discard_pending(pending, value)
+ int pending;
+ void *value;
+{
+ if (p_verbose >= 14 || debug_break_level > 0)
+ report_pending(RP_DISCARD, pending, value);
+}
+
+
+/*
+ * ":if".
+ */
+ void
+ex_if(eap)
+ exarg_T *eap;
+{
+ int error;
+ int skip;
+ int result;
+ struct condstack *cstack = eap->cstack;
+
+ if (cstack->cs_idx == CSTACK_LEN - 1)
+ eap->errmsg = (char_u *)N_("E579: :if nesting too deep");
+ else
+ {
+ ++cstack->cs_idx;
+ cstack->cs_flags[cstack->cs_idx] = 0;
+
+ /*
+ * Don't do something after an error, interrupt, or throw, or when there
+ * is a surrounding conditional and it was not active.
+ */
+ skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0
+ && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
+
+ result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
+
+ if (!skip && !error)
+ {
+ if (result)
+ cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE | CSF_TRUE;
+ }
+ else
+ /* set TRUE, so this conditional will never get active */
+ cstack->cs_flags[cstack->cs_idx] = CSF_TRUE;
+ }
+}
+
+/*
+ * ":endif".
+ */
+ void
+ex_endif(eap)
+ exarg_T *eap;
+{
+ did_endif = TRUE;
+ if (eap->cstack->cs_idx < 0
+ || (eap->cstack->cs_flags[eap->cstack->cs_idx] &
+ (CSF_WHILE | CSF_TRY)))
+ eap->errmsg = (char_u *)N_("E580: :endif without :if");
+ else
+ {
+ /*
+ * When debugging or a breakpoint was encountered, display the debug
+ * prompt (if not already done). This shows the user that an ":endif"
+ * is executed when the ":if" or a previous ":elseif" was not TRUE.
+ * Handle a ">quit" debug command as if an interrupt had occurred before
+ * the ":endif". That is, throw an interrupt exception if appropriate.
+ * Doing this here prevents an exception for a parsing error being
+ * discarded by throwing the interrupt exception later on.
+ */
+ if (!(eap->cstack->cs_flags[eap->cstack->cs_idx] & CSF_TRUE) &&
+ dbg_check_skipped(eap))
+ (void)do_intthrow(eap->cstack);
+
+ --eap->cstack->cs_idx;
+ }
+}
+
+/*
+ * ":else" and ":elseif".
+ */
+ void
+ex_else(eap)
+ exarg_T *eap;
+{
+ int error;
+ int skip;
+ int result;
+ struct condstack *cstack = eap->cstack;
+
+ /*
+ * Don't do something after an error, interrupt, or throw, or when there is
+ * a surrounding conditional and it was not active.
+ */
+ skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0
+ && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
+
+ if (cstack->cs_idx < 0
+ || (cstack->cs_flags[cstack->cs_idx] & (CSF_WHILE | CSF_TRY)))
+ {
+ if (eap->cmdidx == CMD_else)
+ {
+ eap->errmsg = (char_u *)N_("E581: :else without :if");
+ return;
+ }
+ eap->errmsg = (char_u *)N_("E582: :elseif without :if");
+ skip = TRUE;
+ }
+ else if (cstack->cs_flags[cstack->cs_idx] & CSF_ELSE)
+ {
+ if (eap->cmdidx == CMD_else)
+ {
+ eap->errmsg = (char_u *)N_("E583: multiple :else");
+ return;
+ }
+ eap->errmsg = (char_u *)N_("E584: :elseif after :else");
+ skip = TRUE;
+ }
+
+ /* if skipping or the ":if" was TRUE, reset ACTIVE, otherwise set it */
+ if (skip || cstack->cs_flags[cstack->cs_idx] & CSF_TRUE)
+ {
+ if (eap->errmsg == NULL)
+ cstack->cs_flags[cstack->cs_idx] = CSF_TRUE;
+ skip = TRUE; /* don't evaluate an ":elseif" */
+ }
+ else
+ cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE;
+
+ /*
+ * When debugging or a breakpoint was encountered, display the debug prompt
+ * (if not already done). This shows the user that an ":else" or ":elseif"
+ * is executed when the ":if" or previous ":elseif" was not TRUE. Handle
+ * a ">quit" debug command as if an interrupt had occurred before the
+ * ":else" or ":elseif". That is, set "skip" and throw an interrupt
+ * exception if appropriate. Doing this here prevents that an exception
+ * for a parsing errors is discarded when throwing the interrupt exception
+ * later on.
+ */
+ if (!skip && dbg_check_skipped(eap) && got_int)
+ {
+ (void)do_intthrow(cstack);
+ skip = TRUE;
+ }
+
+ if (eap->cmdidx == CMD_elseif)
+ {
+ result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
+ /* When throwing error exceptions, we want to throw always the first
+ * of several errors in a row. This is what actually happens when
+ * a conditional error was detected above and there is another failure
+ * when parsing the expression. Since the skip flag is set in this
+ * case, the parsing error will be ignored by emsg(). */
+
+ if (!skip && !error)
+ {
+ if (result)
+ cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE | CSF_TRUE;
+ else
+ cstack->cs_flags[cstack->cs_idx] = 0;
+ }
+ else if (eap->errmsg == NULL)
+ /* set TRUE, so this conditional will never get active */
+ cstack->cs_flags[cstack->cs_idx] = CSF_TRUE;
+ }
+ else
+ cstack->cs_flags[cstack->cs_idx] |= CSF_ELSE;
+}
+
+/*
+ * Handle ":while".
+ */
+ void
+ex_while(eap)
+ exarg_T *eap;
+{
+ int error;
+ int skip;
+ int result;
+ struct condstack *cstack = eap->cstack;
+
+ if (cstack->cs_idx == CSTACK_LEN - 1)
+ eap->errmsg = (char_u *)N_("E585: :while nesting too deep");
+ else
+ {
+ /*
+ * cs_had_while is set when we have jumped back from the matching
+ * ":endwhile". When not set, need to initialise this cstack entry.
+ */
+ if (!cstack->cs_had_while)
+ {
+ ++cstack->cs_idx;
+ ++cstack->cs_whilelevel;
+ cstack->cs_line[cstack->cs_idx] = -1;
+ }
+ cstack->cs_flags[cstack->cs_idx] = CSF_WHILE;
+
+ /*
+ * Don't do something after an error, interrupt, or throw, or when there
+ * is a surrounding conditional and it was not active.
+ */
+ skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0
+ && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
+ result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
+
+ /*
+ * If this cstack entry was just initialised and is active, set
+ * cs_had_while flag, so do_cmdline() will set the line number
+ * in cs_line[].
+ */
+ if (!skip && !error && result)
+ {
+ cstack->cs_flags[cstack->cs_idx] |= CSF_ACTIVE | CSF_TRUE;
+ cstack->cs_had_while = !cstack->cs_had_while;
+ }
+ else
+ {
+ cstack->cs_had_while = FALSE;
+ /* If the ":while" evaluates to FALSE, show the debug prompt at the
+ * ":endwhile" as if there was a ":break" in a ":while" evaluating
+ * to TRUE. */
+ if (!skip && !error)
+ cstack->cs_flags[cstack->cs_idx] |= CSF_TRUE;
+ }
+ }
+}
+
+/*
+ * ":continue"
+ */
+ void
+ex_continue(eap)
+ exarg_T *eap;
+{
+ int idx;
+ struct condstack *cstack = eap->cstack;
+
+ if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0)
+ eap->errmsg = (char_u *)N_("E586: :continue without :while");
+ else
+ {
+ /* Try to find the matching ":while". This might stop at a try
+ * conditional not in its finally clause (which is then to be executed
+ * next). Therefor, inactivate all conditionals except the ":while"
+ * itself (if reached). */
+ idx = cleanup_conditionals(cstack, CSF_WHILE, FALSE);
+ if ((cstack->cs_flags[idx] & CSF_WHILE))
+ {
+ if (cstack->cs_idx > idx)
+ rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel);
+
+ /*
+ * Set cs_had_continue, so do_cmdline() will jump back to the
+ * matching ":while".
+ */
+ cstack->cs_had_continue = TRUE; /* let do_cmdline() handle it */
+ }
+ else
+ {
+ /* If a try conditional not in its finally clause is reached first,
+ * make the ":continue" pending for execution at the ":endtry". */
+ cstack->cs_pending[idx] = CSTP_CONTINUE;
+ report_make_pending(CSTP_CONTINUE, NULL);
+ }
+ }
+}
+
+/*
+ * ":break"
+ */
+ void
+ex_break(eap)
+ exarg_T *eap;
+{
+ int idx;
+ struct condstack *cstack = eap->cstack;
+
+ if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0)
+ eap->errmsg = (char_u *)N_("E587: :break without :while");
+ else
+ {
+ /* Inactivate conditionals until the matching ":while" or a try
+ * conditional not in its finally clause (which is then to be
+ * executed next) is found. In the latter case, make the ":break"
+ * pending for execution at the ":endtry". */
+ idx = cleanup_conditionals(cstack, CSF_WHILE, TRUE);
+ if (!(cstack->cs_flags[idx] & CSF_WHILE))
+ {
+ cstack->cs_pending[idx] = CSTP_BREAK;
+ report_make_pending(CSTP_BREAK, NULL);
+ }
+ }
+}
+
+/*
+ * ":endwhile"
+ */
+ void
+ex_endwhile(eap)
+ exarg_T *eap;
+{
+ struct condstack *cstack = eap->cstack;
+ int idx;
+
+ if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0)
+ eap->errmsg = e_while;
+ else
+ {
+ if (!(cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
+ {
+ /* Try to find the matching ":while" and report what's missing. */
+ if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
+ eap->errmsg = e_endif;
+ else if (cstack->cs_flags[cstack->cs_idx] & CSF_FINALLY)
+ eap->errmsg = e_endtry;
+ for (idx = cstack->cs_idx; idx > 0; --idx)
+ {
+ if ((cstack->cs_flags[idx] & CSF_TRY)
+ && !(cstack->cs_flags[idx] & CSF_FINALLY))
+ {
+ /* Give up at a try conditional not in its finally clause.
+ * Ignore the ":endwhile". */
+ eap->errmsg = e_while;
+ return;
+ }
+ if (cstack->cs_flags[idx] & CSF_WHILE)
+ break;
+ }
+ /* Cleanup and rewind all contained (and unclosed) conditionals. */
+ (void)cleanup_conditionals(cstack, CSF_WHILE, FALSE);
+ rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel);
+ }
+
+ /*
+ * When debugging or a breakpoint was encountered, display the debug
+ * prompt (if not already done). This shows the user that an
+ * ":enwhile" is executed when the ":while" was not TRUE or after
+ * a ":break". Handle a ">quit" debug command as if an interrupt
+ * had occurred before the ":endwhile". That is, throw an interrupt
+ * exception if appropriate. Doing this here prevents that an
+ * exception for a parsing error is discarded when throwing the
+ * interrupt exception later on.
+ */
+ else if (cstack->cs_flags[cstack->cs_idx] & CSF_TRUE
+ && !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE)
+ && dbg_check_skipped(eap))
+ (void)do_intthrow(cstack);
+
+ /*
+ * Set cs_had_endwhile, so do_cmdline() will jump back to the matching
+ * ":while".
+ */
+ cstack->cs_had_endwhile = TRUE;
+ }
+}
+
+
+/*
+ * ":throw expr"
+ */
+ void
+ex_throw(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+ char_u *value;
+
+ if (*arg != NUL && *arg != '|' && *arg != '\n')
+ value = eval_to_string_skip(arg, &eap->nextcmd, eap->skip);
+ else
+ {
+ EMSG(_(e_argreq));
+ value = NULL;
+ }
+
+ /* On error or when an exception is thrown during argument evaluation, do
+ * not throw. */
+ if (!eap->skip && value != NULL)
+ {
+ if (throw_exception(value, ET_USER, NULL) == FAIL)
+ vim_free(value);
+ else
+ do_throw(eap->cstack);
+ }
+}
+
+/*
+ * Throw the current exception through the specified cstack. Common routine for
+ * ":throw" (user exception) and error and interrupt exceptions. Also used for
+ * rethrowing an uncaught exception.
+ */
+ void
+do_throw(cstack)
+ struct condstack *cstack;
+{
+ int idx;
+ int inactivate_try = FALSE;
+
+ /*
+ * Cleanup and inactivate up to the next surrounding try conditional that
+ * is not in its finally clause. Normally, do not inactivate the try
+ * conditional itself, so that its ACTIVE flag can be tested below. But
+ * if a previous error or interrupt has not been converted to an exception,
+ * inactivate the try conditional, too, as if the conversion had been done,
+ * and reset the did_emsg or got_int flag, so this won't happen again at the
+ * next surrounding try conditional.
+ */
+ if (did_emsg && !THROW_ON_ERROR)
+ {
+ inactivate_try = TRUE;
+ did_emsg = FALSE;
+ }
+ if (got_int && !THROW_ON_INTERRUPT)
+ {
+ inactivate_try = TRUE;
+ got_int = FALSE;
+ }
+ idx = cleanup_conditionals(cstack, 0, inactivate_try);
+ if (idx >= 0)
+ {
+ /*
+ * If this try conditional is active and we are before its first
+ * ":catch", set THROWN so that the ":catch" commands will check whether
+ * the exception matches. When the exception came from any of the
+ * catch clauses, it will be made pending at the ":finally" (if present)
+ * and rethrown at the ":endtry". This will also happen if the try
+ * conditional is inactive. This is the case when we are throwing an
+ * exception due to an error or interrupt on the way from a preceding
+ * ":continue", ":break", ":return", ":finish", error or interrupt (not
+ * converted to an exception) to the finally clause or from a preceding
+ * throw of a user or error or interrupt exception to the matching catch
+ * clause or the finally clause.
+ */
+ if (!(cstack->cs_flags[idx] & CSF_CAUGHT))
+ {
+ if (cstack->cs_flags[idx] & CSF_ACTIVE)
+ cstack->cs_flags[idx] |= CSF_THROWN;
+ else
+ /* THROWN may have already been set for a catchable exception
+ * that has been discarded. Ensure it is reset for the new
+ * exception. */
+ cstack->cs_flags[idx] &= ~CSF_THROWN;
+ }
+ cstack->cs_flags[idx] &= ~CSF_ACTIVE;
+ cstack->cs_exception[idx] = current_exception;
+ }
+#if 0
+ /* TODO: Add optimization below. Not yet done because of interface problems
+ * to eval.c and ex_cmds2.c. (Servatius) */
+ else
+ {
+ /*
+ * There are no catch clauses to check or finally clauses to execute.
+ * End the current script or function. The exception will be rethrown
+ * in the caller.
+ */
+ if (getline_equal(eap->getline, eap->cookie, get_func_line))
+ current_funccal->returned = TRUE;
+ elseif (eap->get_func_line == getsourceline)
+ ((struct source_cookie *)eap->cookie)->finished = TRUE;
+ }
+#endif
+
+ did_throw = TRUE;
+}
+
+/*
+ * ":try"
+ */
+ void
+ex_try(eap)
+ exarg_T *eap;
+{
+ int skip;
+ struct condstack *cstack = eap->cstack;
+
+ if (cstack->cs_idx == CSTACK_LEN - 1)
+ eap->errmsg = (char_u *)N_("E601: :try nesting too deep");
+ else
+ {
+ ++cstack->cs_idx;
+ ++cstack->cs_trylevel;
+ cstack->cs_flags[cstack->cs_idx] = CSF_TRY;
+ cstack->cs_pending[cstack->cs_idx] = CSTP_NONE;
+
+ /*
+ * Don't do something after an error, interrupt, or throw, or when there
+ * is a surrounding conditional and it was not active.
+ */
+ skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0
+ && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
+
+ if (!skip)
+ {
+ /* Set ACTIVE and TRUE. TRUE means that the corresponding ":catch"
+ * commands should check for a match if an exception is thrown and
+ * that the finally clause needs to be executed. */
+ cstack->cs_flags[cstack->cs_idx] |= CSF_ACTIVE | CSF_TRUE;
+
+ /*
+ * ":silent!", even when used in a try conditional, disables
+ * displaying of error messages and conversion of errors to
+ * exceptions. When the silent commands again open a try
+ * conditional, save "emsg_silent" and reset it so that errors are
+ * again converted to exceptions. The value is restored when that
+ * try conditional is left. If it is left normally, the commands
+ * following the ":endtry" are again silent. If it is left by
+ * a ":continue", ":break", ":return", or ":finish", the commands
+ * executed next are again silent. If it is left due to an
+ * aborting error, an interrupt, or an exception, restoring
+ * "emsg_silent" does not matter since we are already in the
+ * aborting state and/or the exception has already been thrown.
+ * The effect is then just freeing the memory that was allocated
+ * to save the value.
+ */
+ if (emsg_silent)
+ {
+ eslist_T *elem;
+
+ elem = (eslist_T *)alloc((unsigned)sizeof(struct eslist_elem));
+ if (elem == NULL)
+ EMSG(_(e_outofmem));
+ else
+ {
+ elem->saved_emsg_silent = emsg_silent;
+ elem->next = cstack->cs_emsg_silent_list;
+ cstack->cs_emsg_silent_list = elem;
+ cstack->cs_flags[cstack->cs_idx] |= CSF_SILENT;
+ emsg_silent = 0;
+ }
+ }
+ }
+
+ }
+}
+
+/*
+ * ":catch /{pattern}/" and ":catch"
+ */
+ void
+ex_catch(eap)
+ exarg_T *eap;
+{
+ int idx = 0;
+ int give_up = FALSE;
+ int skip = FALSE;
+ int caught = FALSE;
+ char_u *end;
+ int save_char = 0;
+ char_u *save_cpo;
+ regmatch_T regmatch;
+ int prev_got_int;
+ struct condstack *cstack = eap->cstack;
+ char_u *pat;
+
+ if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
+ {
+ eap->errmsg = (char_u *)N_("E603: :catch without :try");
+ give_up = TRUE;
+ }
+ else
+ {
+ if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
+ {
+ /* Report what's missing if the matching ":try" is not in its
+ * finally clause. */
+ if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE)
+ eap->errmsg = e_endwhile;
+ else
+ eap->errmsg = e_endif;
+ skip = TRUE;
+ }
+ for (idx = cstack->cs_idx; idx > 0; --idx)
+ if (cstack->cs_flags[idx] & CSF_TRY)
+ break;
+ if (cstack->cs_flags[idx] & CSF_FINALLY)
+ {
+ /* Give up for a ":catch" after ":finally" and ignore it.
+ * Just parse. */
+ eap->errmsg = (char_u *)N_("E604: :catch after :finally");
+ give_up = TRUE;
+ }
+ else if (cstack->cs_idx > idx)
+ rewind_conditionals(cstack, idx, CSF_WHILE, &cstack->cs_whilelevel);
+ }
+
+ if (ends_excmd(*eap->arg)) /* no argument, catch all errors */
+ {
+ pat = (char_u *)".*";
+ end = NULL;
+ eap->nextcmd = find_nextcmd(eap->arg);
+ }
+ else
+ {
+ pat = eap->arg + 1;
+ end = skip_regexp(pat, *eap->arg, TRUE, NULL);
+ }
+
+ if (!give_up)
+ {
+ /*
+ * Don't do something when no exception has been thrown or when the
+ * corresponding try block never got active (because of an inactive
+ * surrounding conditional or after an error or interrupt or throw).
+ */
+ if (!did_throw || !(cstack->cs_flags[idx] & CSF_TRUE))
+ skip = TRUE;
+
+ /*
+ * Check for a match only if an exception is thrown but not caught by
+ * a previous ":catch". An exception that has replaced a discarded
+ * exception is not checked (THROWN is not set then).
+ */
+ if (!skip && (cstack->cs_flags[idx] & CSF_THROWN)
+ && !(cstack->cs_flags[idx] & CSF_CAUGHT))
+ {
+ if (end != NULL && *end != NUL && !ends_excmd(*skipwhite(end + 1)))
+ {
+ EMSG(_(e_trailing));
+ return;
+ }
+
+ /* When debugging or a breakpoint was encountered, display the
+ * debug prompt (if not already done) before checking for a match.
+ * This is a helpful hint for the user when the regular expression
+ * matching fails. Handle a ">quit" debug command as if an
+ * interrupt had occurred before the ":catch". That is, discard
+ * the original exception, replace it by an interrupt exception,
+ * and don't catch it in this try block. */
+ if (!dbg_check_skipped(eap) || !do_intthrow(cstack))
+ {
+ /* Terminate the pattern and avoid the 'l' flag in 'cpoptions'
+ * while compiling it. */
+ if (end != NULL)
+ {
+ save_char = *end;
+ *end = NUL;
+ }
+ save_cpo = p_cpo;
+ p_cpo = (char_u *)"";
+ regmatch.regprog = vim_regcomp(pat, TRUE);
+ regmatch.rm_ic = FALSE;
+ if (end != NULL)
+ *end = save_char;
+ p_cpo = save_cpo;
+ if (regmatch.regprog == NULL)
+ EMSG2(_(e_invarg2), pat);
+ else
+ {
+ /*
+ * Save the value of got_int and reset it. We don't want
+ * a previous interruption cancel matching, only hitting
+ * CTRL-C while matching should abort it.
+ */
+ prev_got_int = got_int;
+ got_int = FALSE;
+ caught = vim_regexec_nl(&regmatch, current_exception->value,
+ (colnr_T)0);
+ got_int |= prev_got_int;
+ vim_free(regmatch.regprog);
+ }
+ }
+ }
+
+ if (caught)
+ {
+ /* Make this ":catch" clause active and reset did_emsg, got_int,
+ * and did_throw. Put the exception on the caught stack. */
+ cstack->cs_flags[idx] |= CSF_ACTIVE | CSF_CAUGHT;
+ did_emsg = got_int = did_throw = FALSE;
+ catch_exception((except_T *)cstack->cs_exception[idx]);
+ /* It's mandatory that the current exception is stored in the cstack
+ * so that it can be discarded at the next ":catch", ":finally", or
+ * ":endtry" or when the catch clause is left by a ":continue",
+ * ":break", ":return", ":finish", error, interrupt, or another
+ * exception. */
+ if (cstack->cs_exception[cstack->cs_idx] != current_exception)
+ EMSG(_(e_internal));
+ }
+ else
+ {
+ /*
+ * If there is a preceding catch clause and it caught the exception,
+ * finish the exception now. This happens also after errors except
+ * when this ":catch" was after the ":finally" or not within
+ * a ":try". Make the try conditional inactive so that the
+ * following catch clauses are skipped. On an error or interrupt
+ * after the preceding try block or catch clause was left by
+ * a ":continue", ":break", ":return", or ":finish", discard the
+ * pending action.
+ */
+ cleanup_conditionals(cstack, CSF_TRY, TRUE);
+ }
+ }
+
+ if (end != NULL)
+ eap->nextcmd = find_nextcmd(end);
+}
+
+/*
+ * ":finally"
+ */
+ void
+ex_finally(eap)
+ exarg_T *eap;
+{
+ int idx;
+ int skip = FALSE;
+ int pending = CSTP_NONE;
+ struct condstack *cstack = eap->cstack;
+
+ if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
+ eap->errmsg = (char_u *)N_("E606: :finally without :try");
+ else
+ {
+ if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
+ {
+ /* Find the matching ":try" and report what's missing. */
+ if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE)
+ eap->errmsg = e_endwhile;
+ else
+ eap->errmsg = e_endif;
+ for (idx = cstack->cs_idx - 1; idx > 0; --idx)
+ if (cstack->cs_flags[idx] & CSF_TRY)
+ break;
+ /* Make this error pending, so that the commands in the following
+ * finally clause can be executed. This overrules also a pending
+ * ":continue", ":break", ":return", or ":finish". */
+ pending = CSTP_ERROR;
+ }
+ else
+ idx = cstack->cs_idx;
+
+ if (cstack->cs_flags[idx] & CSF_FINALLY)
+ {
+ /* Give up for a multiple ":finally" and ignore it. */
+ eap->errmsg = (char_u *)N_("E607: multiple :finally");
+ return;
+ }
+ if (cstack->cs_idx > idx)
+ rewind_conditionals(cstack, idx, CSF_WHILE, &cstack->cs_whilelevel);
+
+ /*
+ * Don't do something when the corresponding try block never got active
+ * (because of an inactive surrounding conditional or after an error or
+ * interrupt or throw) or for a ":finally" without ":try" or a multiple
+ * ":finally". After every other error (did_emsg or the conditional
+ * errors detected above) or after an interrupt (got_int) or an
+ * exception (did_throw), the finally clause must be executed.
+ */
+ skip = !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
+
+ if (!skip)
+ {
+ /* When debugging or a breakpoint was encountered, display the
+ * debug prompt (if not already done). The user then knows that the
+ * finally clause is executed. */
+ if (dbg_check_skipped(eap))
+ {
+ /* Handle a ">quit" debug command as if an interrupt had
+ * occurred before the ":finally". That is, discard the
+ * original exception and replace it by an interrupt
+ * exception. */
+ (void)do_intthrow(cstack);
+ }
+
+ /*
+ * If there is a preceding catch clause and it caught the exception,
+ * finish the exception now. This happens also after errors except
+ * when this is a multiple ":finally" or one not within a ":try".
+ * After an error or interrupt, this also discards a pending
+ * ":continue", ":break", ":finish", or ":return" from the preceding
+ * try block or catch clause.
+ */
+ cleanup_conditionals(cstack, CSF_TRY, FALSE);
+
+ /*
+ * Make did_emsg, got_int, did_throw pending. If set, they overrule
+ * a pending ":continue", ":break", ":return", or ":finish". Then
+ * we have particularly to discard a pending return value (as done
+ * by the call to cleanup_conditionals() above when did_emsg or
+ * got_int is set). The pending values are restored by the
+ * ":endtry", except if there is a new error, interrupt, exception,
+ * ":continue", ":break", ":return", or ":finish" in the following
+ * finally clause. A missing ":endwhile" or ":endif" detected here
+ * is treated as if did_emsg and did_throw had already been set,
+ * respectively in case that the error is not converted to an
+ * exception, did_throw had already been unset. We must not set
+ * did_emsg here since that would suppress the error message.
+ */
+ if (pending == CSTP_ERROR || did_emsg || got_int || did_throw)
+ {
+ if (cstack->cs_pending[cstack->cs_idx] == CSTP_RETURN)
+ {
+ report_discard_pending(CSTP_RETURN,
+ cstack->cs_retvar[cstack->cs_idx]);
+ discard_pending_return(cstack->cs_retvar[cstack->cs_idx]);
+ }
+ if (pending == CSTP_ERROR && !did_emsg)
+ pending |= (THROW_ON_ERROR) ? CSTP_THROW : 0;
+ else
+ pending |= did_throw ? CSTP_THROW : 0;
+ pending |= did_emsg ? CSTP_ERROR : 0;
+ pending |= got_int ? CSTP_INTERRUPT : 0;
+ cstack->cs_pending[cstack->cs_idx] = pending;
+
+ /* It's mandatory that the current exception is stored in the
+ * cstack so that it can be rethrown at the ":endtry" or be
+ * discarded if the finally clause is left by a ":continue",
+ * ":break", ":return", ":finish", error, interrupt, or another
+ * exception. When emsg() is called for a missing ":endif" or
+ * a missing ":endwhile" detected here, the exception will be
+ * discarded. */
+ if (did_throw && cstack->cs_exception[cstack->cs_idx] !=
+ current_exception)
+ EMSG(_(e_internal));
+ }
+
+ /*
+ * Set cs_had_finally, so do_cmdline() will reset did_emsg, got_int,
+ * and did_throw and make the finally clause active. This will
+ * happen after emsg() has been called for a missing ":endif" or
+ * a missing ":endwhile" detected here, so that the following
+ * finally clause will be executed even then.
+ */
+ cstack->cs_had_finally = TRUE;
+ }
+ }
+}
+
+/*
+ * ":endtry"
+ */
+ void
+ex_endtry(eap)
+ exarg_T *eap;
+{
+ int idx;
+ int skip;
+ int rethrow = FALSE;
+ int pending = CSTP_NONE;
+ void *retvar = NULL;
+ struct condstack *cstack = eap->cstack;
+
+ if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
+ eap->errmsg = (char_u *)N_("E602: :endtry without :try");
+ else
+ {
+ /*
+ * Don't do something after an error, interrupt or throw in the try
+ * block, catch clause, or finally clause preceding this ":endtry" or
+ * when an error or interrupt occurred after a ":continue", ":break",
+ * ":return", or ":finish" in a try block or catch clause preceding this
+ * ":endtry" or when the try block never got active (because of an
+ * inactive surrounding conditional or after an error or interrupt or
+ * throw) or when there is a surrounding conditional and it has been
+ * made inactive by a ":continue", ":break", ":return", or ":finish" in
+ * the finally clause. The latter case need not be tested since then
+ * anything pending has already been discarded. */
+ skip = did_emsg || got_int || did_throw ||
+ !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
+
+ if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
+ {
+ /* Find the matching ":try" and report what's missing. */
+ if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE)
+ eap->errmsg = e_endwhile;
+ else
+ eap->errmsg = e_endif;
+ idx = cstack->cs_idx;
+ do
+ --idx;
+ while (idx > 0 && !(cstack->cs_flags[idx] & CSF_TRY));
+ rewind_conditionals(cstack, idx, CSF_WHILE, &cstack->cs_whilelevel);
+ skip = TRUE;
+
+ /*
+ * If an exception is being thrown, discard it to prevent it from
+ * being rethrown at the end of this function. It would be
+ * discarded by the error message, anyway. Resets did_throw.
+ * This does not affect the script termination due to the error
+ * since "trylevel" is decremented after emsg() has been called.
+ */
+ if (did_throw)
+ discard_current_exception();
+ }
+ else
+ {
+ idx = cstack->cs_idx;
+
+ /*
+ * If we stopped with the exception currently being thrown at this
+ * try conditional since we didn't know that it doesn't have
+ * a finally clause, we need to rethrow it after closing the try
+ * conditional.
+ */
+ if (did_throw && (cstack->cs_flags[idx] & CSF_TRUE)
+ && !(cstack->cs_flags[idx] & CSF_FINALLY))
+ rethrow = TRUE;
+ }
+
+ /* If there was no finally clause, show the user when debugging or
+ * a breakpoint was encountered that the end of the try conditional has
+ * been reached: display the debug prompt (if not already done). Do
+ * this on normal control flow or when an exception was thrown, but not
+ * on an interrupt or error not converted to an exception or when
+ * a ":break", ":continue", ":return", or ":finish" is pending. These
+ * actions are carried out immediately.
+ */
+ if ((rethrow || (!skip
+ && !(cstack->cs_flags[idx] & CSF_FINALLY)
+ && !cstack->cs_pending[idx]))
+ && dbg_check_skipped(eap))
+ {
+ /* Handle a ">quit" debug command as if an interrupt had occurred
+ * before the ":endtry". That is, throw an interrupt exception and
+ * set "skip" and "rethrow". */
+ if (got_int)
+ {
+ skip = TRUE;
+ (void)do_intthrow(cstack);
+ /* The do_intthrow() call may have reset did_throw or
+ * cstack->cs_pending[idx].*/
+ rethrow = FALSE;
+ if (did_throw && !(cstack->cs_flags[idx] & CSF_FINALLY))
+ rethrow = TRUE;
+ }
+ }
+
+ /*
+ * If a ":return" is pending, we need to resume it after closing the
+ * try conditional; remember the return value. If there was a finally
+ * clause making an exception pending, we need to rethrow it. Make it
+ * the exception currently being thrown.
+ */
+ if (!skip)
+ {
+ pending = cstack->cs_pending[idx];
+ cstack->cs_pending[idx] = CSTP_NONE;
+ if (pending == CSTP_RETURN)
+ retvar = cstack->cs_retvar[idx];
+ else if (pending & CSTP_THROW)
+ current_exception = cstack->cs_exception[idx];
+ }
+
+ /*
+ * Discard anything pending on an error, interrupt, or throw in the
+ * finally clause. If there was no ":finally", discard a pending
+ * ":continue", ":break", ":return", or ":finish" if an error or
+ * interrupt occurred afterwards, but before the ":endtry" was reached.
+ * If an exception was caught by the last of the catch clauses and there
+ * was no finally clause, finish the exception now. This happens also
+ * after errors except when this ":endtry" is not within a ":try".
+ * Restore "emsg_silent" if it has been reset by this try conditional.
+ */
+ cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE);
+
+ --cstack->cs_idx;
+ --cstack->cs_trylevel;
+
+ if (!skip)
+ {
+ report_resume_pending(pending,
+ (pending == CSTP_RETURN) ? retvar :
+ (pending & CSTP_THROW) ? (void *)current_exception : NULL);
+ switch (pending)
+ {
+ case CSTP_NONE:
+ break;
+
+ /* Reactivate a pending ":continue", ":break", ":return",
+ * ":finish" from the try block or a catch clause of this try
+ * conditional. This is skipped, if there was an error in an
+ * (unskipped) conditional command or an interrupt afterwards
+ * or if the finally clause is present and executed a new error,
+ * interrupt, throw, ":continue", ":break", ":return", or
+ * ":finish". */
+ case CSTP_CONTINUE:
+ ex_continue(eap);
+ break;
+ case CSTP_BREAK:
+ ex_break(eap);
+ break;
+ case CSTP_RETURN:
+ do_return(eap, FALSE, FALSE, retvar);
+ break;
+ case CSTP_FINISH:
+ do_finish(eap, FALSE);
+ break;
+
+ /* When the finally clause was entered due to an error,
+ * interrupt or throw (as opposed to a ":continue", ":break",
+ * ":return", or ":finish"), restore the pending values of
+ * did_emsg, got_int, and did_throw. This is skipped, if there
+ * was a new error, interrupt, throw, ":continue", ":break",
+ * ":return", or ":finish". in the finally clause. */
+ default:
+ if (pending & CSTP_ERROR)
+ did_emsg = TRUE;
+ if (pending & CSTP_INTERRUPT)
+ got_int = TRUE;
+ if (pending & CSTP_THROW)
+ rethrow = TRUE;
+ break;
+ }
+ }
+
+ if (rethrow)
+ /* Rethrow the current exception (within this cstack). */
+ do_throw(cstack);
+ }
+}
+
+/*
+ * Make conditionals inactive and discard what's pending in finally clauses
+ * until the conditional type searched for or a try conditional not in its
+ * finally clause is reached. If this is in an active catch clause, finish the
+ * caught exception. Return the cstack index where the search stopped. Values
+ * used for "searched_cond" are CSF_WHILE or CSF_TRY or 0, the latter meaning
+ * the innermost try conditional not in its finally clause. "inclusive" tells
+ * whether the conditional searched for should be made inactive itself (a try
+ * conditional not in its finally claused possibly find before is always made
+ * inactive). If "inclusive" is TRUE and "searched_cond" is CSF_TRY|CSF_SILENT,
+ * the saved former value of "emsg_silent", if reset when the try conditional
+ * finally reached was entered, is restored (unsed by ex_endtry()). This is
+ * normally done only when such a try conditional is left.
+ */
+ int
+cleanup_conditionals(cstack, searched_cond, inclusive)
+ struct condstack *cstack;
+ int searched_cond;
+ int inclusive;
+{
+ int idx;
+ int stop = FALSE;
+
+ for (idx = cstack->cs_idx; idx >= 0; --idx)
+ {
+ if (cstack->cs_flags[idx] & CSF_TRY)
+ {
+ /*
+ * Discard anything pending in a finally clause and continue the
+ * search. There may also be a pending ":continue", ":break",
+ * ":return", or ":finish" before the finally clause. We must not
+ * discard it, unless an error or interrupt occurred afterwards.
+ */
+ if (did_emsg || got_int ||
+ (cstack->cs_flags[idx] & CSF_FINALLY))
+ {
+ switch (cstack->cs_pending[idx])
+ {
+ case CSTP_NONE:
+ break;
+
+ case CSTP_CONTINUE:
+ case CSTP_BREAK:
+ case CSTP_FINISH:
+ report_discard_pending(cstack->cs_pending[idx], NULL);
+ cstack->cs_pending[idx] = CSTP_NONE;
+ break;
+
+ case CSTP_RETURN:
+ report_discard_pending(CSTP_RETURN,
+ cstack->cs_retvar[idx]);
+ discard_pending_return(cstack->cs_retvar[idx]);
+ cstack->cs_pending[idx] = CSTP_NONE;
+ break;
+
+ default:
+ if (cstack->cs_flags[idx] & CSF_FINALLY)
+ {
+ if (cstack->cs_pending[idx] & CSTP_THROW)
+ {
+ /* Cancel the pending exception. This is in the
+ * finally clause, so that the stack of the
+ * caught exceptions is not involved. */
+ discard_exception((except_T *)
+ cstack->cs_exception[idx],
+ FALSE);
+ }
+ else
+ report_discard_pending(cstack->cs_pending[idx],
+ NULL);
+ cstack->cs_pending[idx] = CSTP_NONE;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Stop at a try conditional not in its finally clause. If this try
+ * conditional is in an active catch clause, finish the caught
+ * exception.
+ */
+ if (!(cstack->cs_flags[idx] & CSF_FINALLY))
+ {
+ if ((cstack->cs_flags[idx] & CSF_ACTIVE)
+ && (cstack->cs_flags[idx] & CSF_CAUGHT))
+ finish_exception((except_T *)cstack->cs_exception[idx]);
+ /* Stop at this try conditional - except the try block never
+ * got active (because of an inactive surrounding conditional
+ * or when the ":try" appeared after an error or interrupt or
+ * throw). */
+ if (cstack->cs_flags[idx] & CSF_TRUE)
+ {
+ if (searched_cond == 0 && !inclusive)
+ break;
+ stop = TRUE;
+ }
+ }
+ }
+
+ /* Stop on the searched conditional type (even when the surrounding
+ * conditional is not active or something has been made pending).
+ * If "inclusive" is TRUE and "searched_cond" is CSF_TRY|CSF_SILENT,
+ * check first whether "emsg_silent" needs to be restored. */
+ if (cstack->cs_flags[idx] & searched_cond)
+ {
+ if (!inclusive)
+ break;
+ stop = TRUE;
+ }
+ cstack->cs_flags[idx] &= ~CSF_ACTIVE;
+ if (stop && searched_cond != (CSF_TRY | CSF_SILENT))
+ break;
+
+ /*
+ * When leaving a try conditinal that reset "emsg_silent" on its entry
+ * after saving the original value, restore that value here and free the
+ * memory used to store it.
+ */
+ if ((cstack->cs_flags[idx] & CSF_TRY)
+ && (cstack->cs_flags[idx] & CSF_SILENT))
+ {
+ eslist_T *elem;
+
+ elem = cstack->cs_emsg_silent_list;
+ cstack->cs_emsg_silent_list = elem->next;
+ emsg_silent = elem->saved_emsg_silent;
+ vim_free(elem);
+ cstack->cs_flags[idx] &= ~CSF_SILENT;
+ }
+ if (stop)
+ break;
+ }
+ return idx;
+}
+
+/*
+ * Rewind conditionals until index "idx" is reached. "cond_type" and
+ * "cond_level" specify a conditional type and the address of a level variable
+ * which is to be decremented with each skipped conditional of the specified
+ * type.
+ */
+ static void
+rewind_conditionals(cstack, idx, cond_type, cond_level)
+ struct condstack *cstack;
+ int idx;
+ int cond_type;
+ int *cond_level;
+{
+ while (cstack->cs_idx > idx)
+ {
+ if (cstack->cs_flags[cstack->cs_idx] & cond_type)
+ --*cond_level;
+ --cstack->cs_idx;
+ }
+}
+
+/*
+ * ":endfunction" when not after a ":function"
+ */
+/*ARGSUSED*/
+ void
+ex_endfunction(eap)
+ exarg_T *eap;
+{
+ EMSG(_("E193: :endfunction not inside a function"));
+}
+
+/*
+ * Return TRUE if the string "p" looks like a ":while" command.
+ */
+ int
+has_while_cmd(p)
+ char_u *p;
+{
+ p = skipwhite(p);
+ while (*p == ':')
+ p = skipwhite(p + 1);
+ if (p[0] == 'w' && p[1] == 'h')
+ return TRUE;
+ return FALSE;
+}
+
+#endif /* FEAT_EVAL */
diff --git a/src/ex_getln.c b/src/ex_getln.c
new file mode 100644
index 000000000..3c242816b
--- /dev/null
+++ b/src/ex_getln.c
@@ -0,0 +1,5371 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * ex_getln.c: Functions for entering and editing an Ex command line.
+ */
+
+#include "vim.h"
+
+/*
+ * Variables shared between getcmdline(), redrawcmdline() and others.
+ * These need to be saved when using CTRL-R |, that's why they are in a
+ * structure.
+ */
+struct cmdline_info
+{
+ char_u *cmdbuff; /* pointer to command line buffer */
+ int cmdbufflen; /* length of cmdbuff */
+ int cmdlen; /* number of chars in command line */
+ int cmdpos; /* current cursor position */
+ int cmdspos; /* cursor column on screen */
+ int cmdfirstc; /* ':', '/', '?', '=' or NUL */
+ int cmdindent; /* number of spaces before cmdline */
+ char_u *cmdprompt; /* message in front of cmdline */
+ int cmdattr; /* attributes for prompt */
+ int overstrike; /* Typing mode on the command line. Shared by
+ getcmdline() and put_on_cmdline(). */
+};
+
+static struct cmdline_info ccline; /* current cmdline_info */
+
+static int cmd_showtail; /* Only show path tail in lists ? */
+
+#ifdef FEAT_EVAL
+static int new_cmdpos; /* position set by set_cmdline_pos() */
+#endif
+
+#ifdef FEAT_CMDHIST
+typedef struct hist_entry
+{
+ int hisnum; /* identifying number */
+ char_u *hisstr; /* actual entry, separator char after the NUL */
+} histentry_T;
+
+static histentry_T *(history[HIST_COUNT]) = {NULL, NULL, NULL, NULL, NULL};
+static int hisidx[HIST_COUNT] = {-1, -1, -1, -1, -1}; /* lastused entry */
+static int hisnum[HIST_COUNT] = {0, 0, 0, 0, 0};
+ /* identifying (unique) number of newest history entry */
+static int hislen = 0; /* actual length of history tables */
+
+static int hist_char2type __ARGS((int c));
+static void init_history __ARGS((void));
+
+static int in_history __ARGS((int, char_u *, int));
+# ifdef FEAT_EVAL
+static int calc_hist_idx __ARGS((int histype, int num));
+# endif
+#endif
+
+#ifdef FEAT_RIGHTLEFT
+static int cmd_hkmap = 0; /* Hebrew mapping during command line */
+#endif
+
+#ifdef FEAT_FKMAP
+static int cmd_fkmap = 0; /* Farsi mapping during command line */
+#endif
+
+static int cmdline_charsize __ARGS((int idx));
+static void set_cmdspos __ARGS((void));
+static void set_cmdspos_cursor __ARGS((void));
+#ifdef FEAT_MBYTE
+static void correct_cmdspos __ARGS((int idx, int cells));
+#endif
+static void alloc_cmdbuff __ARGS((int len));
+static int realloc_cmdbuff __ARGS((int len));
+static void draw_cmdline __ARGS((int start, int len));
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+static void redrawcmd_preedit __ARGS((void));
+#endif
+#ifdef FEAT_WILDMENU
+static void cmdline_del __ARGS((int from));
+#endif
+static void redrawcmdprompt __ARGS((void));
+static void cursorcmd __ARGS((void));
+static int ccheck_abbr __ARGS((int));
+static int nextwild __ARGS((expand_T *xp, int type, int options));
+static int showmatches __ARGS((expand_T *xp, int wildmenu));
+static void set_expand_context __ARGS((expand_T *xp));
+static int ExpandFromContext __ARGS((expand_T *xp, char_u *, int *, char_u ***, int));
+static int expand_showtail __ARGS((expand_T *xp));
+#ifdef FEAT_CMDL_COMPL
+static int ExpandRTDir __ARGS((char_u *pat, int *num_file, char_u ***file, char *dirname));
+# if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
+static int ExpandUserDefined __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file));
+# endif
+#endif
+
+#ifdef FEAT_CMDWIN
+static int ex_window __ARGS((void));
+#endif
+
+/*
+ * getcmdline() - accept a command line starting with firstc.
+ *
+ * firstc == ':' get ":" command line.
+ * firstc == '/' or '?' get search pattern
+ * firstc == '=' get expression
+ * firstc == '@' get text for input() function
+ * firstc == '>' get text for debug mode
+ * firstc == NUL get text for :insert command
+ * firstc == -1 like NUL, and break on CTRL-C
+ *
+ * The line is collected in ccline.cmdbuff, which is reallocated to fit the
+ * command line.
+ *
+ * Careful: getcmdline() can be called recursively!
+ *
+ * Return pointer to allocated string if there is a commandline, NULL
+ * otherwise.
+ */
+/*ARGSUSED*/
+ char_u *
+getcmdline(firstc, count, indent)
+ int firstc;
+ long count; /* only used for incremental search */
+ int indent; /* indent for inside conditionals */
+{
+ int c;
+ int i;
+ int j;
+ int gotesc = FALSE; /* TRUE when <ESC> just typed */
+ int do_abbr; /* when TRUE check for abbr. */
+#ifdef FEAT_CMDHIST
+ char_u *lookfor = NULL; /* string to match */
+ int hiscnt; /* current history line in use */
+ int histype; /* history type to be used */
+#endif
+#ifdef FEAT_SEARCH_EXTRA
+ pos_T old_cursor;
+ colnr_T old_curswant;
+ colnr_T old_leftcol;
+ linenr_T old_topline;
+# ifdef FEAT_DIFF
+ int old_topfill;
+# endif
+ linenr_T old_botline;
+ int did_incsearch = FALSE;
+ int incsearch_postponed = FALSE;
+#endif
+ int did_wild_list = FALSE; /* did wild_list() recently */
+ int wim_index = 0; /* index in wim_flags[] */
+ int res;
+ int save_msg_scroll = msg_scroll;
+ int save_State = State; /* remember State when called */
+ int some_key_typed = FALSE; /* one of the keys was typed */
+#ifdef FEAT_MOUSE
+ /* mouse drag and release events are ignored, unless they are
+ * preceded with a mouse down event */
+ int ignore_drag_release = TRUE;
+#endif
+#ifdef FEAT_EVAL
+ int break_ctrl_c = FALSE;
+#endif
+ expand_T xpc;
+ long *b_im_ptr = NULL;
+
+#ifdef FEAT_SNIFF
+ want_sniff_request = 0;
+#endif
+#ifdef FEAT_EVAL
+ if (firstc == -1)
+ {
+ firstc = NUL;
+ break_ctrl_c = TRUE;
+ }
+#endif
+#ifdef FEAT_RIGHTLEFT
+ /* start without Hebrew mapping for a command line */
+ if (firstc == ':' || firstc == '=' || firstc == '>')
+ cmd_hkmap = 0;
+#endif
+
+ ccline.overstrike = FALSE; /* always start in insert mode */
+#ifdef FEAT_SEARCH_EXTRA
+ old_cursor = curwin->w_cursor; /* needs to be restored later */
+ old_curswant = curwin->w_curswant;
+ old_leftcol = curwin->w_leftcol;
+ old_topline = curwin->w_topline;
+# ifdef FEAT_DIFF
+ old_topfill = curwin->w_topfill;
+# endif
+ old_botline = curwin->w_botline;
+#endif
+
+ /*
+ * set some variables for redrawcmd()
+ */
+ ccline.cmdfirstc = (firstc == '@' ? 0 : firstc);
+ ccline.cmdindent = indent;
+ alloc_cmdbuff(exmode_active ? 250 : 0); /* alloc initial ccline.cmdbuff */
+ if (ccline.cmdbuff == NULL)
+ return NULL; /* out of memory */
+ ccline.cmdlen = ccline.cmdpos = 0;
+ ccline.cmdbuff[0] = NUL;
+
+ ExpandInit(&xpc);
+
+#ifdef FEAT_RIGHTLEFT
+ if (curwin->w_p_rl && *curwin->w_p_rlc == 's'
+ && (firstc == '/' || firstc == '?'))
+ cmdmsg_rl = TRUE;
+ else
+ cmdmsg_rl = FALSE;
+#endif
+
+ redir_off = TRUE; /* don't redirect the typed command */
+ if (!cmd_silent)
+ {
+ i = msg_scrolled;
+ msg_scrolled = 0; /* avoid wait_return message */
+ gotocmdline(TRUE);
+ msg_scrolled += i;
+ redrawcmdprompt(); /* draw prompt or indent */
+ set_cmdspos();
+ }
+ xpc.xp_context = EXPAND_NOTHING;
+ xpc.xp_backslash = XP_BS_NONE;
+
+ /*
+ * Avoid scrolling when called by a recursive do_cmdline(), e.g. when
+ * doing ":@0" when register 0 doesn't contain a CR.
+ */
+ msg_scroll = FALSE;
+
+ State = CMDLINE;
+
+ if (firstc == '/' || firstc == '?' || firstc == '@')
+ {
+ /* Use ":lmap" mappings for search pattern and input(). */
+ if (curbuf->b_p_imsearch == B_IMODE_USE_INSERT)
+ b_im_ptr = &curbuf->b_p_iminsert;
+ else
+ b_im_ptr = &curbuf->b_p_imsearch;
+ if (*b_im_ptr == B_IMODE_LMAP)
+ State |= LANGMAP;
+#ifdef USE_IM_CONTROL
+ im_set_active(*b_im_ptr == B_IMODE_IM);
+#endif
+ }
+#ifdef USE_IM_CONTROL
+ else if (p_imcmdline)
+ im_set_active(TRUE);
+#endif
+
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+#ifdef CURSOR_SHAPE
+ ui_cursor_shape(); /* may show different cursor shape */
+#endif
+
+#ifdef FEAT_CMDHIST
+ init_history();
+ hiscnt = hislen; /* set hiscnt to impossible history value */
+ histype = hist_char2type(firstc);
+#endif
+
+#ifdef FEAT_DIGRAPHS
+ do_digraph(-1); /* init digraph typahead */
+#endif
+
+ /*
+ * Collect the command string, handling editing keys.
+ */
+ for (;;)
+ {
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = FALSE; /* allow scrolling here */
+#endif
+ quit_more = FALSE; /* reset after CTRL-D which had a more-prompt */
+
+ cursorcmd(); /* set the cursor on the right spot */
+ c = safe_vgetc();
+ if (KeyTyped)
+ {
+ some_key_typed = TRUE;
+#ifdef FEAT_RIGHTLEFT
+ if (cmd_hkmap)
+ c = hkmap(c);
+# ifdef FEAT_FKMAP
+ if (cmd_fkmap)
+ c = cmdl_fkmap(c);
+# endif
+ if (cmdmsg_rl && !KeyStuffed)
+ {
+ /* Invert horizontal movements and operations. Only when
+ * typed by the user directly, not when the result of a
+ * mapping. */
+ switch (c)
+ {
+ case K_RIGHT: c = K_LEFT; break;
+ case K_S_RIGHT: c = K_S_LEFT; break;
+ case K_C_RIGHT: c = K_C_LEFT; break;
+ case K_LEFT: c = K_RIGHT; break;
+ case K_S_LEFT: c = K_S_RIGHT; break;
+ case K_C_LEFT: c = K_C_RIGHT; break;
+ }
+ }
+#endif
+ }
+
+ /*
+ * Ignore got_int when CTRL-C was typed here.
+ * Don't ignore it in :global, we really need to break then, e.g., for
+ * ":g/pat/normal /pat" (without the <CR>).
+ * Don't ignore it for the input() function.
+ */
+ if ((c == Ctrl_C
+#ifdef UNIX
+ || c == intr_char
+#endif
+ )
+#if defined(FEAT_EVAL) || defined(FEAT_CRYPT)
+ && firstc != '@'
+#endif
+#ifdef FEAT_EVAL
+ && !break_ctrl_c
+#endif
+ && !global_busy)
+ got_int = FALSE;
+
+#ifdef FEAT_CMDHIST
+ /* free old command line when finished moving around in the history
+ * list */
+ if (lookfor != NULL
+ && c != K_S_DOWN && c != K_S_UP && c != K_DOWN && c != K_UP
+ && c != K_PAGEDOWN && c != K_PAGEUP
+ && c != K_KPAGEDOWN && c != K_KPAGEUP
+ && c != K_LEFT && c != K_RIGHT
+ && (xpc.xp_numfiles > 0 || (c != Ctrl_P && c != Ctrl_N)))
+ {
+ vim_free(lookfor);
+ lookfor = NULL;
+ }
+#endif
+
+ /*
+ * <S-Tab> works like CTRL-P (unless 'wc' is <S-Tab>).
+ */
+ if (c != p_wc && c == K_S_TAB && xpc.xp_numfiles != -1)
+ c = Ctrl_P;
+
+#ifdef FEAT_WILDMENU
+ /* Special translations for 'wildmenu' */
+ if (did_wild_list && p_wmnu)
+ {
+ if (c == K_LEFT)
+ c = Ctrl_P;
+ else if (c == K_RIGHT)
+ c = Ctrl_N;
+ }
+ /* Hitting CR after "emenu Name.": complete submenu */
+ if (xpc.xp_context == EXPAND_MENUNAMES && p_wmnu
+ && ccline.cmdpos > 1
+ && ccline.cmdbuff[ccline.cmdpos - 1] == '.'
+ && ccline.cmdbuff[ccline.cmdpos - 2] != '\\'
+ && (c == '\n' || c == '\r' || c == K_KENTER))
+ c = K_DOWN;
+#endif
+
+ /* free expanded names when finished walking through matches */
+ if (xpc.xp_numfiles != -1
+ && !(c == p_wc && KeyTyped) && c != p_wcm
+ && c != Ctrl_N && c != Ctrl_P && c != Ctrl_A
+ && c != Ctrl_L)
+ {
+ (void)ExpandOne(&xpc, NULL, NULL, 0, WILD_FREE);
+ did_wild_list = FALSE;
+#ifdef FEAT_WILDMENU
+ if (!p_wmnu || (c != K_UP && c != K_DOWN))
+#endif
+ xpc.xp_context = EXPAND_NOTHING;
+ wim_index = 0;
+#ifdef FEAT_WILDMENU
+ if (p_wmnu && wild_menu_showing != 0)
+ {
+ int skt = KeyTyped;
+
+ if (wild_menu_showing == WM_SCROLLED)
+ {
+ /* Entered command line, move it up */
+ cmdline_row--;
+ redrawcmd();
+ }
+ else if (save_p_ls != -1)
+ {
+ /* restore 'laststatus' and 'winminheight' */
+ p_ls = save_p_ls;
+ p_wmh = save_p_wmh;
+ last_status(FALSE);
+ update_screen(VALID); /* redraw the screen NOW */
+ redrawcmd();
+ save_p_ls = -1;
+ }
+ else
+ {
+# ifdef FEAT_VERTSPLIT
+ win_redraw_last_status(topframe);
+# else
+ lastwin->w_redr_status = TRUE;
+# endif
+ redraw_statuslines();
+ }
+ KeyTyped = skt;
+ wild_menu_showing = 0;
+ }
+#endif
+ }
+
+#ifdef FEAT_WILDMENU
+ /* Special translations for 'wildmenu' */
+ if (xpc.xp_context == EXPAND_MENUNAMES && p_wmnu)
+ {
+ /* Hitting <Down> after "emenu Name.": complete submenu */
+ if (ccline.cmdbuff[ccline.cmdpos - 1] == '.' && c == K_DOWN)
+ c = p_wc;
+ else if (c == K_UP)
+ {
+ /* Hitting <Up>: Remove one submenu name in front of the
+ * cursor */
+ int found = FALSE;
+
+ j = (int)(xpc.xp_pattern - ccline.cmdbuff);
+ i = 0;
+ while (--j > 0)
+ {
+ /* check for start of menu name */
+ if (ccline.cmdbuff[j] == ' '
+ && ccline.cmdbuff[j - 1] != '\\')
+ {
+ i = j + 1;
+ break;
+ }
+ /* check for start of submenu name */
+ if (ccline.cmdbuff[j] == '.'
+ && ccline.cmdbuff[j - 1] != '\\')
+ {
+ if (found)
+ {
+ i = j + 1;
+ break;
+ }
+ else
+ found = TRUE;
+ }
+ }
+ if (i > 0)
+ cmdline_del(i);
+ c = p_wc;
+ xpc.xp_context = EXPAND_NOTHING;
+ }
+ }
+ if (xpc.xp_context == EXPAND_FILES && p_wmnu)
+ {
+ char_u upseg[5];
+
+ upseg[0] = PATHSEP;
+ upseg[1] = '.';
+ upseg[2] = '.';
+ upseg[3] = PATHSEP;
+ upseg[4] = NUL;
+
+ if (ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP
+ && c == K_DOWN
+ && (ccline.cmdbuff[ccline.cmdpos - 2] != '.'
+ || ccline.cmdbuff[ccline.cmdpos - 3] != '.'))
+ {
+ /* go down a directory */
+ c = p_wc;
+ }
+ else if (STRNCMP(xpc.xp_pattern, upseg + 1, 3) == 0 && c == K_DOWN)
+ {
+ /* If in a direct ancestor, strip off one ../ to go down */
+ int found = FALSE;
+
+ j = ccline.cmdpos;
+ i = (int)(xpc.xp_pattern - ccline.cmdbuff);
+ while (--j > i)
+ {
+ if (vim_ispathsep(ccline.cmdbuff[j]))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found
+ && ccline.cmdbuff[j - 1] == '.'
+ && ccline.cmdbuff[j - 2] == '.'
+ && (vim_ispathsep(ccline.cmdbuff[j - 3]) || j == i + 2))
+ {
+ cmdline_del(j - 2);
+ c = p_wc;
+ }
+ }
+ else if (c == K_UP)
+ {
+ /* go up a directory */
+ int found = FALSE;
+
+ j = ccline.cmdpos - 1;
+ i = (int)(xpc.xp_pattern - ccline.cmdbuff);
+ while (--j > i)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ j -= (*mb_head_off)(ccline.cmdbuff, ccline.cmdbuff + j);
+#endif
+ if (vim_ispathsep(ccline.cmdbuff[j])
+#ifdef BACKSLASH_IN_FILENAME
+ && vim_strchr(" *?[{`$%#", ccline.cmdbuff[j + 1])
+ == NULL
+#endif
+ )
+ {
+ if (found)
+ {
+ i = j + 1;
+ break;
+ }
+ else
+ found = TRUE;
+ }
+ }
+
+ if (!found)
+ j = i;
+ else if (STRNCMP(ccline.cmdbuff + j, upseg, 4) == 0)
+ j += 4;
+ else if (STRNCMP(ccline.cmdbuff + j, upseg + 1, 3) == 0
+ && j == i)
+ j += 3;
+ else
+ j = 0;
+ if (j > 0)
+ {
+ /* TODO this is only for DOS/UNIX systems - need to put in
+ * machine-specific stuff here and in upseg init */
+ cmdline_del(j);
+ put_on_cmdline(upseg + 1, 3, FALSE);
+ }
+ else if (ccline.cmdpos > i)
+ cmdline_del(i);
+ c = p_wc;
+ }
+ }
+#if 0 /* If enabled <Down> on a file takes you _completely_ out of wildmenu */
+ if (p_wmnu
+ && (xpc.xp_context == EXPAND_FILES
+ || xpc.xp_context == EXPAND_MENUNAMES)
+ && (c == K_UP || c == K_DOWN))
+ xpc.xp_context = EXPAND_NOTHING;
+#endif
+
+#endif /* FEAT_WILDMENU */
+
+ /* CTRL-\ CTRL-N goes to Normal mode, CTRL-\ CTRL-G goes to Insert
+ * mode when 'insertmode' is set, CTRL-\ e prompts for an expression. */
+ if (c == Ctrl_BSL)
+ {
+ ++no_mapping;
+ ++allow_keys;
+ c = safe_vgetc();
+ --no_mapping;
+ --allow_keys;
+ /* CTRL-\ e doesn't work when obtaining an expression. */
+ if (c != Ctrl_N && c != Ctrl_G
+ && (c != 'e' || ccline.cmdfirstc == '='))
+ {
+ vungetc(c);
+ c = Ctrl_BSL;
+ }
+#ifdef FEAT_EVAL
+ else if (c == 'e')
+ {
+ struct cmdline_info save_ccline;
+ char_u *p;
+
+ /*
+ * Replace the command line with the result of an expression.
+ * Need to save the current command line, to be able to enter
+ * a new one...
+ */
+ if (ccline.cmdpos == ccline.cmdlen)
+ new_cmdpos = 99999; /* keep it at the end */
+ else
+ new_cmdpos = ccline.cmdpos;
+ save_ccline = ccline;
+ ccline.cmdbuff = NULL;
+ ccline.cmdprompt = NULL;
+ c = get_expr_register();
+ ccline = save_ccline;
+ if (c == '=')
+ {
+ p = get_expr_line();
+ if (p != NULL
+ && realloc_cmdbuff((int)STRLEN(p) + 1) == OK)
+ {
+ ccline.cmdlen = STRLEN(p);
+ STRCPY(ccline.cmdbuff, p);
+ vim_free(p);
+
+ /* Restore the cursor or use the position set with
+ * set_cmdline_pos(). */
+ if (new_cmdpos > ccline.cmdlen)
+ ccline.cmdpos = ccline.cmdlen;
+ else
+ ccline.cmdpos = new_cmdpos;
+
+ KeyTyped = FALSE; /* Don't do p_wc completion. */
+ redrawcmd();
+ goto cmdline_changed;
+ }
+ }
+ beep_flush();
+ c = ESC;
+ }
+#endif
+ else
+ {
+ if (c == Ctrl_G && p_im && restart_edit == 0)
+ restart_edit = 'a';
+ gotesc = TRUE; /* will free ccline.cmdbuff after putting it
+ in history */
+ goto returncmd; /* back to Normal mode */
+ }
+ }
+
+#ifdef FEAT_CMDWIN
+ if (c == cedit_key || c == K_CMDWIN)
+ {
+ /*
+ * Open a window to edit the command line (and history).
+ */
+ c = ex_window();
+ some_key_typed = TRUE;
+ }
+# ifdef FEAT_DIGRAPHS
+ else
+# endif
+#endif
+#ifdef FEAT_DIGRAPHS
+ c = do_digraph(c);
+#endif
+
+ if (c == '\n' || c == '\r' || c == K_KENTER || (c == ESC
+ && (!KeyTyped || vim_strchr(p_cpo, CPO_ESC) != NULL)))
+ {
+ gotesc = FALSE; /* Might have typed ESC previously, don't
+ truncate the cmdline now. */
+ if (ccheck_abbr(c + ABBR_OFF))
+ goto cmdline_changed;
+ if (!cmd_silent)
+ {
+ windgoto(msg_row, 0);
+ out_flush();
+ }
+ break;
+ }
+
+ /*
+ * Completion for 'wildchar' or 'wildcharm' key.
+ * - hitting <ESC> twice means: abandon command line.
+ * - wildcard expansion is only done when the 'wildchar' key is really
+ * typed, not when it comes from a macro
+ */
+ if ((c == p_wc && !gotesc && KeyTyped) || c == p_wcm)
+ {
+ if (xpc.xp_numfiles > 0) /* typed p_wc at least twice */
+ {
+ /* if 'wildmode' contains "list" may still need to list */
+ if (xpc.xp_numfiles > 1
+ && !did_wild_list
+ && (wim_flags[wim_index] & WIM_LIST))
+ {
+ (void)showmatches(&xpc, FALSE);
+ redrawcmd();
+ did_wild_list = TRUE;
+ }
+ if (wim_flags[wim_index] & WIM_LONGEST)
+ res = nextwild(&xpc, WILD_LONGEST, WILD_NO_BEEP);
+ else if (wim_flags[wim_index] & WIM_FULL)
+ res = nextwild(&xpc, WILD_NEXT, WILD_NO_BEEP);
+ else
+ res = OK; /* don't insert 'wildchar' now */
+ }
+ else /* typed p_wc first time */
+ {
+ wim_index = 0;
+ j = ccline.cmdpos;
+ /* if 'wildmode' first contains "longest", get longest
+ * common part */
+ if (wim_flags[0] & WIM_LONGEST)
+ res = nextwild(&xpc, WILD_LONGEST, WILD_NO_BEEP);
+ else
+ res = nextwild(&xpc, WILD_EXPAND_KEEP, WILD_NO_BEEP);
+
+ /* if interrupted while completing, behave like it failed */
+ if (got_int)
+ {
+ (void)vpeekc(); /* remove <C-C> from input stream */
+ got_int = FALSE; /* don't abandon the command line */
+ (void)ExpandOne(&xpc, NULL, NULL, 0, WILD_FREE);
+#ifdef FEAT_WILDMENU
+ xpc.xp_context = EXPAND_NOTHING;
+#endif
+ goto cmdline_changed;
+ }
+
+ /* when more than one match, and 'wildmode' first contains
+ * "list", or no change and 'wildmode' contains "longest,list",
+ * list all matches */
+ if (res == OK && xpc.xp_numfiles > 1)
+ {
+ /* a "longest" that didn't do anything is skipped (but not
+ * "list:longest") */
+ if (wim_flags[0] == WIM_LONGEST && ccline.cmdpos == j)
+ wim_index = 1;
+ if ((wim_flags[wim_index] & WIM_LIST)
+#ifdef FEAT_WILDMENU
+ || (p_wmnu && (wim_flags[wim_index] & WIM_FULL) != 0)
+#endif
+ )
+ {
+ if (!(wim_flags[0] & WIM_LONGEST))
+ {
+#ifdef FEAT_WILDMENU
+ int p_wmnu_save = p_wmnu;
+ p_wmnu = 0;
+#endif
+ nextwild(&xpc, WILD_PREV, 0); /* remove match */
+#ifdef FEAT_WILDMENU
+ p_wmnu = p_wmnu_save;
+#endif
+ }
+#ifdef FEAT_WILDMENU
+ (void)showmatches(&xpc, p_wmnu
+ && ((wim_flags[wim_index] & WIM_LIST) == 0));
+#else
+ (void)showmatches(&xpc, FALSE);
+#endif
+ redrawcmd();
+ did_wild_list = TRUE;
+ if (wim_flags[wim_index] & WIM_LONGEST)
+ nextwild(&xpc, WILD_LONGEST, WILD_NO_BEEP);
+ else if (wim_flags[wim_index] & WIM_FULL)
+ nextwild(&xpc, WILD_NEXT, WILD_NO_BEEP);
+ }
+ else
+ vim_beep();
+ }
+#ifdef FEAT_WILDMENU
+ else if (xpc.xp_numfiles == -1)
+ xpc.xp_context = EXPAND_NOTHING;
+#endif
+ }
+ if (wim_index < 3)
+ ++wim_index;
+ if (c == ESC)
+ gotesc = TRUE;
+ if (res == OK)
+ goto cmdline_changed;
+ }
+
+ gotesc = FALSE;
+
+ /* <S-Tab> goes to last match, in a clumsy way */
+ if (c == K_S_TAB && KeyTyped)
+ {
+ if (nextwild(&xpc, WILD_EXPAND_KEEP, 0) == OK
+ && nextwild(&xpc, WILD_PREV, 0) == OK
+ && nextwild(&xpc, WILD_PREV, 0) == OK)
+ goto cmdline_changed;
+ }
+
+ if (c == NUL || c == K_ZERO) /* NUL is stored as NL */
+ c = NL;
+
+ do_abbr = TRUE; /* default: check for abbreviation */
+
+ /*
+ * Big switch for a typed command line character.
+ */
+ switch (c)
+ {
+ case K_BS:
+ case Ctrl_H:
+ case K_DEL:
+ case K_KDEL:
+ case Ctrl_W:
+#ifdef FEAT_FKMAP
+ if (cmd_fkmap && c == K_BS)
+ c = K_DEL;
+#endif
+ if (c == K_KDEL)
+ c = K_DEL;
+
+ /*
+ * delete current character is the same as backspace on next
+ * character, except at end of line
+ */
+ if (c == K_DEL && ccline.cmdpos != ccline.cmdlen)
+ ++ccline.cmdpos;
+#ifdef FEAT_MBYTE
+ if (has_mbyte && c == K_DEL)
+ ccline.cmdpos += mb_off_next(ccline.cmdbuff,
+ ccline.cmdbuff + ccline.cmdpos);
+#endif
+ if (ccline.cmdpos > 0)
+ {
+ char_u *p;
+
+ j = ccline.cmdpos;
+ p = ccline.cmdbuff + j;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ p = mb_prevptr(ccline.cmdbuff, p);
+ if (c == Ctrl_W)
+ {
+ while (p > ccline.cmdbuff && vim_isspace(*p))
+ p = mb_prevptr(ccline.cmdbuff, p);
+ i = mb_get_class(p);
+ while (p > ccline.cmdbuff && mb_get_class(p) == i)
+ p = mb_prevptr(ccline.cmdbuff, p);
+ if (mb_get_class(p) != i)
+ p += (*mb_ptr2len_check)(p);
+ }
+ }
+ else
+#endif
+ if (c == Ctrl_W)
+ {
+ while (p > ccline.cmdbuff && vim_isspace(p[-1]))
+ --p;
+ i = vim_iswordc(p[-1]);
+ while (p > ccline.cmdbuff && !vim_isspace(p[-1])
+ && vim_iswordc(p[-1]) == i)
+ --p;
+ }
+ else
+ --p;
+ ccline.cmdpos = (int)(p - ccline.cmdbuff);
+ ccline.cmdlen -= j - ccline.cmdpos;
+ i = ccline.cmdpos;
+ while (i < ccline.cmdlen)
+ ccline.cmdbuff[i++] = ccline.cmdbuff[j++];
+
+ /* Truncate at the end, required for multi-byte chars. */
+ ccline.cmdbuff[ccline.cmdlen] = NUL;
+ redrawcmd();
+ }
+ else if (ccline.cmdlen == 0 && c != Ctrl_W
+ && ccline.cmdprompt == NULL && indent == 0)
+ {
+ /* In ex and debug mode it doesn't make sense to return. */
+ if (exmode_active
+#ifdef FEAT_EVAL
+ || ccline.cmdfirstc == '>'
+#endif
+ )
+ goto cmdline_not_changed;
+
+ vim_free(ccline.cmdbuff); /* no commandline to return */
+ ccline.cmdbuff = NULL;
+ if (!cmd_silent)
+ {
+#ifdef FEAT_RIGHTLEFT
+ if (cmdmsg_rl)
+ msg_col = Columns;
+ else
+#endif
+ msg_col = 0;
+ msg_putchar(' '); /* delete ':' */
+ }
+ redraw_cmdline = TRUE;
+ goto returncmd; /* back to cmd mode */
+ }
+ goto cmdline_changed;
+
+ case K_INS:
+ case K_KINS:
+#ifdef FEAT_FKMAP
+ /* if Farsi mode set, we are in reverse insert mode -
+ Do not change the mode */
+ if (cmd_fkmap)
+ beep_flush();
+ else
+#endif
+ ccline.overstrike = !ccline.overstrike;
+#ifdef CURSOR_SHAPE
+ ui_cursor_shape(); /* may show different cursor shape */
+#endif
+ goto cmdline_not_changed;
+
+ case Ctrl_HAT:
+ if (map_to_exists_mode((char_u *)"", LANGMAP))
+ {
+ /* ":lmap" mappings exists, toggle use of mappings. */
+ State ^= LANGMAP;
+#ifdef USE_IM_CONTROL
+ im_set_active(FALSE); /* Disable input method */
+#endif
+ if (b_im_ptr != NULL)
+ {
+ if (State & LANGMAP)
+ *b_im_ptr = B_IMODE_LMAP;
+ else
+ *b_im_ptr = B_IMODE_NONE;
+ }
+ }
+#ifdef USE_IM_CONTROL
+ else
+ {
+ /* There are no ":lmap" mappings, toggle IM. When
+ * 'imdisable' is set don't try getting the status, it's
+ * always off. */
+ if ((p_imdisable && b_im_ptr != NULL)
+ ? *b_im_ptr == B_IMODE_IM : im_get_status())
+ {
+ im_set_active(FALSE); /* Disable input method */
+ if (b_im_ptr != NULL)
+ *b_im_ptr = B_IMODE_NONE;
+ }
+ else
+ {
+ im_set_active(TRUE); /* Enable input method */
+ if (b_im_ptr != NULL)
+ *b_im_ptr = B_IMODE_IM;
+ }
+ }
+#endif
+ if (b_im_ptr != NULL)
+ {
+ if (b_im_ptr == &curbuf->b_p_iminsert)
+ set_iminsert_global();
+ else
+ set_imsearch_global();
+ }
+#ifdef CURSOR_SHAPE
+ ui_cursor_shape(); /* may show different cursor shape */
+#endif
+#if defined(FEAT_WINDOWS) && defined(FEAT_KEYMAP)
+ /* Show/unshow value of 'keymap' in status lines later. */
+ status_redraw_curbuf();
+#endif
+ goto cmdline_not_changed;
+
+/* case '@': only in very old vi */
+ case Ctrl_U:
+ /* delete all characters left of the cursor */
+ j = ccline.cmdpos;
+ ccline.cmdlen -= j;
+ i = ccline.cmdpos = 0;
+ while (i < ccline.cmdlen)
+ ccline.cmdbuff[i++] = ccline.cmdbuff[j++];
+ /* Truncate at the end, required for multi-byte chars. */
+ ccline.cmdbuff[ccline.cmdlen] = NUL;
+ redrawcmd();
+ goto cmdline_changed;
+
+#ifdef FEAT_CLIPBOARD
+ case Ctrl_Y:
+ /* Copy the modeless selection, if there is one. */
+ if (clip_star.state != SELECT_CLEARED)
+ {
+ if (clip_star.state == SELECT_DONE)
+ clip_copy_modeless_selection(TRUE);
+ goto cmdline_not_changed;
+ }
+ break;
+#endif
+
+ case ESC: /* get here if p_wc != ESC or when ESC typed twice */
+ case Ctrl_C:
+ /* In exmode it doesn't make sense to return. */
+ if (exmode_active)
+ goto cmdline_not_changed;
+
+ gotesc = TRUE; /* will free ccline.cmdbuff after
+ putting it in history */
+ goto returncmd; /* back to cmd mode */
+
+ case Ctrl_R: /* insert register */
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = TRUE; /* disallow scrolling here */
+#endif
+ putcmdline('"', TRUE);
+ ++no_mapping;
+ i = c = safe_vgetc(); /* CTRL-R <char> */
+ if (i == Ctrl_O)
+ i = Ctrl_R; /* CTRL-R CTRL-O == CTRL-R CTRL-R */
+ if (i == Ctrl_R)
+ c = safe_vgetc(); /* CTRL-R CTRL-R <char> */
+ --no_mapping;
+#ifdef FEAT_EVAL
+ /*
+ * Insert the result of an expression.
+ * Need to save the current command line, to be able to enter
+ * a new one...
+ */
+ new_cmdpos = -1;
+ if (c == '=')
+ {
+ struct cmdline_info save_ccline;
+
+ if (ccline.cmdfirstc == '=')/* can't do this recursively */
+ {
+ beep_flush();
+ c = ESC;
+ }
+ else
+ {
+ save_ccline = ccline;
+ ccline.cmdbuff = NULL;
+ ccline.cmdprompt = NULL;
+ c = get_expr_register();
+ ccline = save_ccline;
+ }
+ }
+#endif
+ if (c != ESC) /* use ESC to cancel inserting register */
+ {
+ cmdline_paste(c, i == Ctrl_R);
+ KeyTyped = FALSE; /* Don't do p_wc completion. */
+#ifdef FEAT_EVAL
+ if (new_cmdpos >= 0)
+ {
+ /* set_cmdline_pos() was used */
+ if (new_cmdpos > ccline.cmdlen)
+ ccline.cmdpos = ccline.cmdlen;
+ else
+ ccline.cmdpos = new_cmdpos;
+ }
+#endif
+ }
+ redrawcmd();
+ goto cmdline_changed;
+
+ case Ctrl_D:
+ if (showmatches(&xpc, FALSE) == EXPAND_NOTHING)
+ break; /* Use ^D as normal char instead */
+
+ redrawcmd();
+ continue; /* don't do incremental search now */
+
+ case K_RIGHT:
+ case K_S_RIGHT:
+ case K_C_RIGHT:
+ do
+ {
+ if (ccline.cmdpos >= ccline.cmdlen)
+ break;
+ i = cmdline_charsize(ccline.cmdpos);
+ if (KeyTyped && ccline.cmdspos + i >= Columns * Rows)
+ break;
+ ccline.cmdspos += i;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ ccline.cmdpos += (*mb_ptr2len_check)(ccline.cmdbuff
+ + ccline.cmdpos);
+ else
+#endif
+ ++ccline.cmdpos;
+ }
+ while ((c == K_S_RIGHT || c == K_C_RIGHT)
+ && ccline.cmdbuff[ccline.cmdpos] != ' ');
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ set_cmdspos_cursor();
+#endif
+ goto cmdline_not_changed;
+
+ case K_LEFT:
+ case K_S_LEFT:
+ case K_C_LEFT:
+ do
+ {
+ if (ccline.cmdpos == 0)
+ break;
+ --ccline.cmdpos;
+#ifdef FEAT_MBYTE
+ if (has_mbyte) /* move to first byte of char */
+ ccline.cmdpos -= (*mb_head_off)(ccline.cmdbuff,
+ ccline.cmdbuff + ccline.cmdpos);
+#endif
+ ccline.cmdspos -= cmdline_charsize(ccline.cmdpos);
+ }
+ while ((c == K_S_LEFT || c == K_C_LEFT)
+ && ccline.cmdbuff[ccline.cmdpos - 1] != ' ');
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ set_cmdspos_cursor();
+#endif
+ goto cmdline_not_changed;
+
+ case K_IGNORE:
+ goto cmdline_not_changed; /* Ignore mouse */
+
+#ifdef FEAT_MOUSE
+ case K_MIDDLEDRAG:
+ case K_MIDDLERELEASE:
+ goto cmdline_not_changed; /* Ignore mouse */
+
+ case K_MIDDLEMOUSE:
+# ifdef FEAT_GUI
+ /* When GUI is active, also paste when 'mouse' is empty */
+ if (!gui.in_use)
+# endif
+ if (!mouse_has(MOUSE_COMMAND))
+ goto cmdline_not_changed; /* Ignore mouse */
+#ifdef FEAT_CLIPBOARD
+ if (clip_star.available)
+ cmdline_paste('*', TRUE);
+ else
+#endif
+ cmdline_paste(0, TRUE);
+ redrawcmd();
+ goto cmdline_changed;
+
+#ifdef FEAT_DND
+ case K_DROP:
+ cmdline_paste('~', TRUE);
+ redrawcmd();
+ goto cmdline_changed;
+#endif
+
+ case K_LEFTDRAG:
+ case K_LEFTRELEASE:
+ case K_RIGHTDRAG:
+ case K_RIGHTRELEASE:
+ /* Ignore drag and release events when the button-down wasn't
+ * seen before. */
+ if (ignore_drag_release)
+ goto cmdline_not_changed;
+ /* FALLTHROUGH */
+ case K_LEFTMOUSE:
+ case K_RIGHTMOUSE:
+ if (c == K_LEFTRELEASE || c == K_RIGHTRELEASE)
+ ignore_drag_release = TRUE;
+ else
+ ignore_drag_release = FALSE;
+# ifdef FEAT_GUI
+ /* When GUI is active, also move when 'mouse' is empty */
+ if (!gui.in_use)
+# endif
+ if (!mouse_has(MOUSE_COMMAND))
+ goto cmdline_not_changed; /* Ignore mouse */
+# ifdef FEAT_CLIPBOARD
+ if (mouse_row < cmdline_row && clip_star.available)
+ {
+ int button, is_click, is_drag;
+
+ /*
+ * Handle modeless selection.
+ */
+ button = get_mouse_button(KEY2TERMCAP1(c),
+ &is_click, &is_drag);
+ if (mouse_model_popup() && button == MOUSE_LEFT
+ && (mod_mask & MOD_MASK_SHIFT))
+ {
+ /* Translate shift-left to right button. */
+ button = MOUSE_RIGHT;
+ mod_mask &= ~MOD_MASK_SHIFT;
+ }
+ clip_modeless(button, is_click, is_drag);
+ goto cmdline_not_changed;
+ }
+# endif
+
+ set_cmdspos();
+ for (ccline.cmdpos = 0; ccline.cmdpos < ccline.cmdlen;
+ ++ccline.cmdpos)
+ {
+ i = cmdline_charsize(ccline.cmdpos);
+ if (mouse_row <= cmdline_row + ccline.cmdspos / Columns
+ && mouse_col < ccline.cmdspos % Columns + i)
+ break;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ /* Count ">" for double-wide char that doesn't fit. */
+ correct_cmdspos(ccline.cmdpos, i);
+ ccline.cmdpos += (*mb_ptr2len_check)(ccline.cmdbuff
+ + ccline.cmdpos) - 1;
+ }
+#endif
+ ccline.cmdspos += i;
+ }
+ goto cmdline_not_changed;
+
+ /* Mouse scroll wheel: ignored here */
+ case K_MOUSEDOWN:
+ case K_MOUSEUP:
+ /* Alternate buttons ignored here */
+ case K_X1MOUSE:
+ case K_X1DRAG:
+ case K_X1RELEASE:
+ case K_X2MOUSE:
+ case K_X2DRAG:
+ case K_X2RELEASE:
+ goto cmdline_not_changed;
+
+#endif /* FEAT_MOUSE */
+
+#ifdef FEAT_GUI
+ case K_LEFTMOUSE_NM: /* mousefocus click, ignored */
+ case K_LEFTRELEASE_NM:
+ goto cmdline_not_changed;
+
+ case K_VER_SCROLLBAR:
+ if (!msg_scrolled)
+ {
+ gui_do_scroll();
+ redrawcmd();
+ }
+ goto cmdline_not_changed;
+
+ case K_HOR_SCROLLBAR:
+ if (!msg_scrolled)
+ {
+ gui_do_horiz_scroll();
+ redrawcmd();
+ }
+ goto cmdline_not_changed;
+#endif
+ case K_SELECT: /* end of Select mode mapping - ignore */
+ goto cmdline_not_changed;
+
+ case Ctrl_B: /* begin of command line */
+ case K_HOME:
+ case K_KHOME:
+ case K_XHOME:
+ case K_S_HOME:
+ case K_C_HOME:
+ ccline.cmdpos = 0;
+ set_cmdspos();
+ goto cmdline_not_changed;
+
+ case Ctrl_E: /* end of command line */
+ case K_END:
+ case K_KEND:
+ case K_XEND:
+ case K_S_END:
+ case K_C_END:
+ ccline.cmdpos = ccline.cmdlen;
+ set_cmdspos_cursor();
+ goto cmdline_not_changed;
+
+ case Ctrl_A: /* all matches */
+ if (nextwild(&xpc, WILD_ALL, 0) == FAIL)
+ break;
+ goto cmdline_changed;
+
+ case Ctrl_L: /* longest common part */
+ if (nextwild(&xpc, WILD_LONGEST, 0) == FAIL)
+ break;
+ goto cmdline_changed;
+
+ case Ctrl_N: /* next match */
+ case Ctrl_P: /* previous match */
+ if (xpc.xp_numfiles > 0)
+ {
+ if (nextwild(&xpc, (c == Ctrl_P) ? WILD_PREV : WILD_NEXT, 0)
+ == FAIL)
+ break;
+ goto cmdline_changed;
+ }
+
+#ifdef FEAT_CMDHIST
+ case K_UP:
+ case K_DOWN:
+ case K_S_UP:
+ case K_S_DOWN:
+ case K_PAGEUP:
+ case K_KPAGEUP:
+ case K_PAGEDOWN:
+ case K_KPAGEDOWN:
+ if (hislen == 0 || firstc == NUL) /* no history */
+ goto cmdline_not_changed;
+
+ i = hiscnt;
+
+ /* save current command string so it can be restored later */
+ if (lookfor == NULL)
+ {
+ if ((lookfor = vim_strsave(ccline.cmdbuff)) == NULL)
+ goto cmdline_not_changed;
+ lookfor[ccline.cmdpos] = NUL;
+ }
+
+ j = (int)STRLEN(lookfor);
+ for (;;)
+ {
+ /* one step backwards */
+ if (c == K_UP || c == K_S_UP || c == Ctrl_P ||
+ c == K_PAGEUP || c == K_KPAGEUP)
+ {
+ if (hiscnt == hislen) /* first time */
+ hiscnt = hisidx[histype];
+ else if (hiscnt == 0 && hisidx[histype] != hislen - 1)
+ hiscnt = hislen - 1;
+ else if (hiscnt != hisidx[histype] + 1)
+ --hiscnt;
+ else /* at top of list */
+ {
+ hiscnt = i;
+ break;
+ }
+ }
+ else /* one step forwards */
+ {
+ /* on last entry, clear the line */
+ if (hiscnt == hisidx[histype])
+ {
+ hiscnt = hislen;
+ break;
+ }
+
+ /* not on a history line, nothing to do */
+ if (hiscnt == hislen)
+ break;
+ if (hiscnt == hislen - 1) /* wrap around */
+ hiscnt = 0;
+ else
+ ++hiscnt;
+ }
+ if (hiscnt < 0 || history[histype][hiscnt].hisstr == NULL)
+ {
+ hiscnt = i;
+ break;
+ }
+ if ((c != K_UP && c != K_DOWN) || hiscnt == i
+ || STRNCMP(history[histype][hiscnt].hisstr,
+ lookfor, (size_t)j) == 0)
+ break;
+ }
+
+ if (hiscnt != i) /* jumped to other entry */
+ {
+ char_u *p;
+ int len;
+ int old_firstc;
+
+ vim_free(ccline.cmdbuff);
+ if (hiscnt == hislen)
+ p = lookfor; /* back to the old one */
+ else
+ p = history[histype][hiscnt].hisstr;
+
+ if (histype == HIST_SEARCH
+ && p != lookfor
+ && (old_firstc = p[STRLEN(p) + 1]) != firstc)
+ {
+ /* Correct for the separator character used when
+ * adding the history entry vs the one used now.
+ * First loop: count length.
+ * Second loop: copy the characters. */
+ for (i = 0; i <= 1; ++i)
+ {
+ len = 0;
+ for (j = 0; p[j] != NUL; ++j)
+ {
+ /* Replace old sep with new sep, unless it is
+ * escaped. */
+ if (p[j] == old_firstc
+ && (j == 0 || p[j - 1] != '\\'))
+ {
+ if (i > 0)
+ ccline.cmdbuff[len] = firstc;
+ }
+ else
+ {
+ /* Escape new sep, unless it is already
+ * escaped. */
+ if (p[j] == firstc
+ && (j == 0 || p[j - 1] != '\\'))
+ {
+ if (i > 0)
+ ccline.cmdbuff[len] = '\\';
+ ++len;
+ }
+ if (i > 0)
+ ccline.cmdbuff[len] = p[j];
+ }
+ ++len;
+ }
+ if (i == 0)
+ {
+ alloc_cmdbuff(len);
+ if (ccline.cmdbuff == NULL)
+ goto returncmd;
+ }
+ }
+ ccline.cmdbuff[len] = NUL;
+ }
+ else
+ {
+ alloc_cmdbuff((int)STRLEN(p));
+ if (ccline.cmdbuff == NULL)
+ goto returncmd;
+ STRCPY(ccline.cmdbuff, p);
+ }
+
+ ccline.cmdpos = ccline.cmdlen = (int)STRLEN(ccline.cmdbuff);
+ redrawcmd();
+ goto cmdline_changed;
+ }
+ beep_flush();
+ goto cmdline_not_changed;
+#endif
+
+ case Ctrl_V:
+ case Ctrl_Q:
+#ifdef FEAT_MOUSE
+ ignore_drag_release = TRUE;
+#endif
+ putcmdline('^', TRUE);
+ c = get_literal(); /* get next (two) character(s) */
+ do_abbr = FALSE; /* don't do abbreviation now */
+#ifdef FEAT_MBYTE
+ /* may need to remove ^ when composing char was typed */
+ if (enc_utf8 && utf_iscomposing(c) && !cmd_silent)
+ {
+ draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos);
+ msg_putchar(' ');
+ cursorcmd();
+ }
+#endif
+ break;
+
+#ifdef FEAT_DIGRAPHS
+ case Ctrl_K:
+#ifdef FEAT_MOUSE
+ ignore_drag_release = TRUE;
+#endif
+ putcmdline('?', TRUE);
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = TRUE; /* disallow scrolling here */
+#endif
+ c = get_digraph(TRUE);
+ if (c != NUL)
+ break;
+
+ redrawcmd();
+ goto cmdline_not_changed;
+#endif /* FEAT_DIGRAPHS */
+
+#ifdef FEAT_RIGHTLEFT
+ case Ctrl__: /* CTRL-_: switch language mode */
+ if (!p_ari)
+ break;
+#ifdef FEAT_FKMAP
+ if (p_altkeymap)
+ {
+ cmd_fkmap = !cmd_fkmap;
+ if (cmd_fkmap) /* in Farsi always in Insert mode */
+ ccline.overstrike = FALSE;
+ }
+ else /* Hebrew is default */
+#endif
+ cmd_hkmap = !cmd_hkmap;
+ goto cmdline_not_changed;
+#endif
+
+ default:
+#ifdef UNIX
+ if (c == intr_char)
+ {
+ gotesc = TRUE; /* will free ccline.cmdbuff after
+ putting it in history */
+ goto returncmd; /* back to Normal mode */
+ }
+#endif
+ /*
+ * Normal character with no special meaning. Just set mod_mask
+ * to 0x0 so that typing Shift-Space in the GUI doesn't enter
+ * the string <S-Space>. This should only happen after ^V.
+ */
+ if (!IS_SPECIAL(c))
+ mod_mask = 0x0;
+ break;
+ }
+ /*
+ * End of switch on command line character.
+ * We come here if we have a normal character.
+ */
+
+ if (do_abbr && (IS_SPECIAL(c) || !vim_iswordc(c)) && ccheck_abbr(
+#ifdef FEAT_MBYTE
+ /* Add ABBR_OFF for characters above 0x100, this is
+ * what check_abbr() expects. */
+ (has_mbyte && c >= 0x100) ? (c + ABBR_OFF) :
+#endif
+ c))
+ goto cmdline_changed;
+
+ /*
+ * put the character in the command line
+ */
+ if (IS_SPECIAL(c) || mod_mask != 0)
+ put_on_cmdline(get_special_key_name(c, mod_mask), -1, TRUE);
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ j = (*mb_char2bytes)(c, IObuff);
+ IObuff[j] = NUL; /* exclude composing chars */
+ put_on_cmdline(IObuff, j, TRUE);
+ }
+ else
+#endif
+ {
+ IObuff[0] = c;
+ put_on_cmdline(IObuff, 1, TRUE);
+ }
+ }
+ goto cmdline_changed;
+
+/*
+ * This part implements incremental searches for "/" and "?"
+ * Jump to cmdline_not_changed when a character has been read but the command
+ * line did not change. Then we only search and redraw if something changed in
+ * the past.
+ * Jump to cmdline_changed when the command line did change.
+ * (Sorry for the goto's, I know it is ugly).
+ */
+cmdline_not_changed:
+#ifdef FEAT_SEARCH_EXTRA
+ if (!incsearch_postponed)
+ continue;
+#endif
+
+cmdline_changed:
+#ifdef FEAT_SEARCH_EXTRA
+ /*
+ * 'incsearch' highlighting.
+ */
+ if (p_is && !cmd_silent && (firstc == '/' || firstc == '?'))
+ {
+ /* if there is a character waiting, search and redraw later */
+ if (char_avail())
+ {
+ incsearch_postponed = TRUE;
+ continue;
+ }
+ incsearch_postponed = FALSE;
+ curwin->w_cursor = old_cursor; /* start at old position */
+
+ /* If there is no command line, don't do anything */
+ if (ccline.cmdlen == 0)
+ i = 0;
+ else
+ {
+ cursor_off(); /* so the user knows we're busy */
+ out_flush();
+ ++emsg_off; /* So it doesn't beep if bad expr */
+ i = do_search(NULL, firstc, ccline.cmdbuff, count,
+ SEARCH_KEEP + SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK);
+ --emsg_off;
+ /* if interrupted while searching, behave like it failed */
+ if (got_int)
+ {
+ (void)vpeekc(); /* remove <C-C> from input stream */
+ got_int = FALSE; /* don't abandon the command line */
+ i = 0;
+ }
+ else if (char_avail())
+ /* cancelled searching because a char was typed */
+ incsearch_postponed = TRUE;
+ }
+ if (i)
+ highlight_match = TRUE; /* highlight position */
+ else
+ highlight_match = FALSE; /* remove highlight */
+
+ /* first restore the old curwin values, so the screen is
+ * positioned in the same way as the actual search command */
+ curwin->w_leftcol = old_leftcol;
+ curwin->w_topline = old_topline;
+# ifdef FEAT_DIFF
+ curwin->w_topfill = old_topfill;
+# endif
+ curwin->w_botline = old_botline;
+ changed_cline_bef_curs();
+ update_topline();
+
+ if (i != 0)
+ {
+ /*
+ * First move cursor to end of match, then to start. This
+ * moves the whole match onto the screen when 'nowrap' is set.
+ */
+ i = curwin->w_cursor.col;
+ curwin->w_cursor.lnum += search_match_lines;
+ curwin->w_cursor.col = search_match_endcol;
+ validate_cursor();
+ curwin->w_cursor.lnum -= search_match_lines;
+ curwin->w_cursor.col = i;
+ }
+ validate_cursor();
+
+ update_screen(NOT_VALID);
+ msg_starthere();
+ redrawcmdline();
+ did_incsearch = TRUE;
+ }
+#else /* FEAT_SEARCH_EXTRA */
+ ;
+#endif
+
+#ifdef FEAT_RIGHTLEFT
+ if (cmdmsg_rl
+# ifdef FEAT_ARABIC
+ || p_arshape
+# endif
+ )
+ /* Always redraw the whole command line to fix shaping and
+ * right-left typing. Not efficient, but it works. */
+ redrawcmd();
+#endif
+ }
+
+returncmd:
+
+#ifdef FEAT_RIGHTLEFT
+ cmdmsg_rl = FALSE;
+#endif
+
+#ifdef FEAT_FKMAP
+ cmd_fkmap = 0;
+#endif
+
+ ExpandCleanup(&xpc);
+
+#ifdef FEAT_SEARCH_EXTRA
+ if (did_incsearch)
+ {
+ curwin->w_cursor = old_cursor;
+ curwin->w_curswant = old_curswant;
+ curwin->w_leftcol = old_leftcol;
+ curwin->w_topline = old_topline;
+# ifdef FEAT_DIFF
+ curwin->w_topfill = old_topfill;
+# endif
+ curwin->w_botline = old_botline;
+ highlight_match = FALSE;
+ validate_cursor(); /* needed for TAB */
+ redraw_later(NOT_VALID);
+ }
+#endif
+
+ if (ccline.cmdbuff != NULL)
+ {
+ /*
+ * Put line in history buffer (":" and "=" only when it was typed).
+ */
+#ifdef FEAT_CMDHIST
+ if (ccline.cmdlen && firstc != NUL
+ && (some_key_typed || histype == HIST_SEARCH))
+ {
+ add_to_history(histype, ccline.cmdbuff, TRUE,
+ histype == HIST_SEARCH ? firstc : NUL);
+ if (firstc == ':')
+ {
+ vim_free(new_last_cmdline);
+ new_last_cmdline = vim_strsave(ccline.cmdbuff);
+ }
+ }
+#endif
+
+ if (gotesc) /* abandon command line */
+ {
+ vim_free(ccline.cmdbuff);
+ ccline.cmdbuff = NULL;
+ if (msg_scrolled == 0)
+ compute_cmdrow();
+ MSG("");
+ redraw_cmdline = TRUE;
+ }
+ }
+
+ /*
+ * If the screen was shifted up, redraw the whole screen (later).
+ * If the line is too long, clear it, so ruler and shown command do
+ * not get printed in the middle of it.
+ */
+ msg_check();
+ msg_scroll = save_msg_scroll;
+ redir_off = FALSE;
+
+ /* When the command line was typed, no need for a wait-return prompt. */
+ if (some_key_typed)
+ need_wait_return = FALSE;
+
+ State = save_State;
+#ifdef USE_IM_CONTROL
+ if (b_im_ptr != NULL && *b_im_ptr != B_IMODE_LMAP)
+ im_save_status(b_im_ptr);
+ im_set_active(FALSE);
+#endif
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+#ifdef CURSOR_SHAPE
+ ui_cursor_shape(); /* may show different cursor shape */
+#endif
+
+ return ccline.cmdbuff;
+}
+
+#if (defined(FEAT_CRYPT) || defined(FEAT_EVAL)) || defined(PROTO)
+/*
+ * Get a command line with a prompt.
+ * This is prepared to be called recursively from getcmdline() (e.g. by
+ * f_input() when evaluating an expression from CTRL-R =).
+ * Returns the command line in allocated memory, or NULL.
+ */
+ char_u *
+getcmdline_prompt(firstc, prompt, attr)
+ int firstc;
+ char_u *prompt; /* command line prompt */
+ int attr; /* attributes for prompt */
+{
+ char_u *s;
+ struct cmdline_info save_ccline;
+ int msg_col_save = msg_col;
+
+ save_ccline = ccline;
+ ccline.cmdbuff = NULL;
+ ccline.cmdprompt = prompt;
+ ccline.cmdattr = attr;
+ s = getcmdline(firstc, 1L, 0);
+ ccline = save_ccline;
+ /* Restore msg_col, the prompt from input() may have changed it. */
+ msg_col = msg_col_save;
+
+ return s;
+}
+#endif
+
+ static int
+cmdline_charsize(idx)
+ int idx;
+{
+#if defined(FEAT_CRYPT) || defined(FEAT_EVAL)
+ if (cmdline_star > 0) /* showing '*', always 1 position */
+ return 1;
+#endif
+ return ptr2cells(ccline.cmdbuff + idx);
+}
+
+/*
+ * Compute the offset of the cursor on the command line for the prompt and
+ * indent.
+ */
+ static void
+set_cmdspos()
+{
+ if (ccline.cmdfirstc)
+ ccline.cmdspos = 1 + ccline.cmdindent;
+ else
+ ccline.cmdspos = 0 + ccline.cmdindent;
+}
+
+/*
+ * Compute the screen position for the cursor on the command line.
+ */
+ static void
+set_cmdspos_cursor()
+{
+ int i, m, c;
+
+ set_cmdspos();
+ if (KeyTyped)
+ m = Columns * Rows;
+ else
+ m = MAXCOL;
+ for (i = 0; i < ccline.cmdlen && i < ccline.cmdpos; ++i)
+ {
+ c = cmdline_charsize(i);
+#ifdef FEAT_MBYTE
+ /* Count ">" for double-wide multi-byte char that doesn't fit. */
+ if (has_mbyte)
+ correct_cmdspos(i, c);
+#endif
+ /* If the cmdline doesn't fit, put cursor on last visible char. */
+ if ((ccline.cmdspos += c) >= m)
+ {
+ ccline.cmdpos = i - 1;
+ ccline.cmdspos -= c;
+ break;
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ i += (*mb_ptr2len_check)(ccline.cmdbuff + i) - 1;
+#endif
+ }
+}
+
+#ifdef FEAT_MBYTE
+/*
+ * Check if the character at "idx", which is "cells" wide, is a multi-byte
+ * character that doesn't fit, so that a ">" must be displayed.
+ */
+ static void
+correct_cmdspos(idx, cells)
+ int idx;
+ int cells;
+{
+ if ((*mb_ptr2len_check)(ccline.cmdbuff + idx) > 1
+ && (*mb_ptr2cells)(ccline.cmdbuff + idx) > 1
+ && ccline.cmdspos % Columns + cells > Columns)
+ ccline.cmdspos++;
+}
+#endif
+
+/*
+ * Get an Ex command line for the ":" command.
+ */
+/* ARGSUSED */
+ char_u *
+getexline(c, dummy, indent)
+ int c; /* normally ':', NUL for ":append" */
+ void *dummy; /* cookie not used */
+ int indent; /* indent for inside conditionals */
+{
+ /* When executing a register, remove ':' that's in front of each line. */
+ if (exec_from_reg && vpeekc() == ':')
+ (void)vgetc();
+ return getcmdline(c, 1L, indent);
+}
+
+/*
+ * Get an Ex command line for Ex mode.
+ * In Ex mode we only use the OS supplied line editing features and no
+ * mappings or abbreviations.
+ */
+/* ARGSUSED */
+ char_u *
+getexmodeline(c, dummy, indent)
+ int c; /* normally ':', NUL for ":append" */
+ void *dummy; /* cookie not used */
+ int indent; /* indent for inside conditionals */
+{
+ garray_T line_ga;
+ int len;
+ int off = 0;
+ char_u *p;
+ int finished = FALSE;
+#if defined(FEAT_GUI) || defined(NO_COOKED_INPUT)
+ int startcol = 0;
+ int c1;
+ int escaped = FALSE; /* CTRL-V typed */
+ int vcol = 0;
+#endif
+
+ /* Switch cursor on now. This avoids that it happens after the "\n", which
+ * confuses the system function that computes tabstops. */
+ cursor_on();
+
+ /* always start in column 0; write a newline if necessary */
+ compute_cmdrow();
+ if (msg_col)
+ msg_putchar('\n');
+ if (c == ':')
+ {
+ msg_putchar(':');
+ while (indent-- > 0)
+ msg_putchar(' ');
+#if defined(FEAT_GUI) || defined(NO_COOKED_INPUT)
+ startcol = msg_col;
+#endif
+ }
+
+ ga_init2(&line_ga, 1, 30);
+
+ /*
+ * Get the line, one character at a time.
+ */
+ got_int = FALSE;
+ while (!got_int && !finished)
+ {
+ if (ga_grow(&line_ga, 40) == FAIL)
+ break;
+ p = (char_u *)line_ga.ga_data + line_ga.ga_len;
+
+ /* Get one character (inchar gets a third of maxlen characters!) */
+ len = inchar(p + off, 3, -1L, 0);
+ if (len < 0)
+ continue; /* end of input script reached */
+ /* for a special character, we need at least three characters */
+ if ((*p == K_SPECIAL || *p == CSI) && off + len < 3)
+ {
+ off += len;
+ continue;
+ }
+ len += off;
+ off = 0;
+
+ /*
+ * When using the GUI, and for systems that don't have cooked input,
+ * handle line editing here.
+ */
+#if defined(FEAT_GUI) || defined(NO_COOKED_INPUT)
+# ifndef NO_COOKED_INPUT
+ if (gui.in_use)
+# endif
+ {
+ if (got_int)
+ {
+ msg_putchar('\n');
+ break;
+ }
+
+ while (len > 0)
+ {
+ c1 = *p++;
+ --len;
+ if ((c1 == K_SPECIAL
+# if !defined(NO_COOKED_INPUT) || defined(FEAT_GUI)
+ || c1 == CSI
+# endif
+ ) && len >= 2)
+ {
+ c1 = TO_SPECIAL(p[0], p[1]);
+ p += 2;
+ len -= 2;
+ }
+
+ if (!escaped)
+ {
+ /* CR typed means "enter", which is NL */
+ if (c1 == '\r')
+ c1 = '\n';
+
+ if (c1 == BS || c1 == K_BS
+ || c1 == DEL || c1 == K_DEL || c1 == K_KDEL)
+ {
+ if (line_ga.ga_len > 0)
+ {
+ int i, v;
+ char_u *q;
+
+ --line_ga.ga_len;
+ ++line_ga.ga_room;
+ /* compute column that cursor should be in */
+ v = 0;
+ q = ((char_u *)line_ga.ga_data);
+ for (i = 0; i < line_ga.ga_len; ++i)
+ {
+ if (*q == TAB)
+ v += 8 - v % 8;
+ else
+ v += ptr2cells(q);
+ ++q;
+ }
+ /* erase characters to position cursor */
+ while (vcol > v)
+ {
+ msg_putchar('\b');
+ msg_putchar(' ');
+ msg_putchar('\b');
+ --vcol;
+ }
+ }
+ continue;
+ }
+
+ if (c1 == Ctrl_U)
+ {
+ msg_col = startcol;
+ msg_clr_eos();
+ line_ga.ga_room += line_ga.ga_len;
+ line_ga.ga_len = 0;
+ continue;
+ }
+
+ if (c1 == Ctrl_V)
+ {
+ escaped = TRUE;
+ continue;
+ }
+ }
+
+ if (IS_SPECIAL(c1))
+ c1 = '?';
+ ((char_u *)line_ga.ga_data)[line_ga.ga_len] = c1;
+ if (c1 == '\n')
+ msg_putchar('\n');
+ else if (c1 == TAB)
+ {
+ /* Don't use chartabsize(), 'ts' can be different */
+ do
+ {
+ msg_putchar(' ');
+ } while (++vcol % 8);
+ }
+ else
+ {
+ msg_outtrans_len(
+ ((char_u *)line_ga.ga_data) + line_ga.ga_len, 1);
+ vcol += char2cells(c1);
+ }
+ ++line_ga.ga_len;
+ --line_ga.ga_room;
+ escaped = FALSE;
+ }
+ windgoto(msg_row, msg_col);
+ }
+# ifndef NO_COOKED_INPUT
+ else
+# endif
+#endif
+#ifndef NO_COOKED_INPUT
+ {
+ line_ga.ga_len += len;
+ line_ga.ga_room -= len;
+ }
+#endif
+ p = (char_u *)(line_ga.ga_data) + line_ga.ga_len;
+ if (line_ga.ga_len && p[-1] == '\n')
+ {
+ finished = TRUE;
+ --line_ga.ga_len;
+ --p;
+ *p = NUL;
+ }
+ }
+
+ /* note that cursor has moved, because of the echoed <CR> */
+ screen_down();
+ /* make following messages go to the next line */
+ msg_didout = FALSE;
+ msg_col = 0;
+ if (msg_row < Rows - 1)
+ ++msg_row;
+ emsg_on_display = FALSE; /* don't want ui_delay() */
+
+ if (got_int)
+ ga_clear(&line_ga);
+
+ return (char_u *)line_ga.ga_data;
+}
+
+#ifdef CURSOR_SHAPE
+/*
+ * Return TRUE if ccline.overstrike is on.
+ */
+ int
+cmdline_overstrike()
+{
+ return ccline.overstrike;
+}
+
+/*
+ * Return TRUE if the cursor is at the end of the cmdline.
+ */
+ int
+cmdline_at_end()
+{
+ return (ccline.cmdpos >= ccline.cmdlen);
+}
+#endif
+
+#if (defined(FEAT_XIM) && defined(FEAT_GUI_GTK)) || defined(PROTO)
+/*
+ * Return the virtual column number at the current cursor position.
+ * This is used by the IM code to obtain the start of the preedit string.
+ */
+ colnr_T
+cmdline_getvcol_cursor()
+{
+ if (ccline.cmdbuff == NULL || ccline.cmdpos > ccline.cmdlen)
+ return MAXCOL;
+
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ colnr_T col;
+ int i = 0;
+
+ for (col = 0; i < ccline.cmdpos; ++col)
+ i += (*mb_ptr2len_check)(ccline.cmdbuff + i);
+
+ return col;
+ }
+ else
+# endif
+ return ccline.cmdpos;
+}
+#endif
+
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+/*
+ * If part of the command line is an IM preedit string, redraw it with
+ * IM feedback attributes. The cursor position is restored after drawing.
+ */
+ static void
+redrawcmd_preedit()
+{
+ if ((State & CMDLINE)
+ && xic != NULL
+ && im_get_status()
+ && !p_imdisable
+ && im_is_preediting())
+ {
+ int cmdpos = 0;
+ int cmdspos;
+ int old_row;
+ int old_col;
+ colnr_T col;
+
+ old_row = msg_row;
+ old_col = msg_col;
+ cmdspos = ((ccline.cmdfirstc) ? 1 : 0) + ccline.cmdindent;
+
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ for (col = 0; col < preedit_start_col
+ && cmdpos < ccline.cmdlen; ++col)
+ {
+ cmdspos += (*mb_ptr2cells)(ccline.cmdbuff + cmdpos);
+ cmdpos += (*mb_ptr2len_check)(ccline.cmdbuff + cmdpos);
+ }
+ }
+ else
+# endif
+ {
+ cmdspos += preedit_start_col;
+ cmdpos += preedit_start_col;
+ }
+
+ msg_row = cmdline_row + (cmdspos / (int)Columns);
+ msg_col = cmdspos % (int)Columns;
+ if (msg_row >= Rows)
+ msg_row = Rows - 1;
+
+ for (col = 0; cmdpos < ccline.cmdlen; ++col)
+ {
+ int char_len;
+ int char_attr;
+
+ char_attr = im_get_feedback_attr(col);
+ if (char_attr < 0)
+ break; /* end of preedit string */
+
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ char_len = (*mb_ptr2len_check)(ccline.cmdbuff + cmdpos);
+ else
+# endif
+ char_len = 1;
+
+ msg_outtrans_len_attr(ccline.cmdbuff + cmdpos, char_len, char_attr);
+ cmdpos += char_len;
+ }
+
+ msg_row = old_row;
+ msg_col = old_col;
+ }
+}
+#endif /* FEAT_XIM && FEAT_GUI_GTK */
+
+/*
+ * Allocate a new command line buffer.
+ * Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen.
+ * Returns the new value of ccline.cmdbuff and ccline.cmdbufflen.
+ */
+ static void
+alloc_cmdbuff(len)
+ int len;
+{
+ /*
+ * give some extra space to avoid having to allocate all the time
+ */
+ if (len < 80)
+ len = 100;
+ else
+ len += 20;
+
+ ccline.cmdbuff = alloc(len); /* caller should check for out-of-memory */
+ ccline.cmdbufflen = len;
+}
+
+/*
+ * Re-allocate the command line to length len + something extra.
+ * return FAIL for failure, OK otherwise
+ */
+ static int
+realloc_cmdbuff(len)
+ int len;
+{
+ char_u *p;
+
+ p = ccline.cmdbuff;
+ alloc_cmdbuff(len); /* will get some more */
+ if (ccline.cmdbuff == NULL) /* out of memory */
+ {
+ ccline.cmdbuff = p; /* keep the old one */
+ return FAIL;
+ }
+ mch_memmove(ccline.cmdbuff, p, (size_t)ccline.cmdlen + 1);
+ vim_free(p);
+ return OK;
+}
+
+/*
+ * Draw part of the cmdline at the current cursor position. But draw stars
+ * when cmdline_star is TRUE.
+ */
+ static void
+draw_cmdline(start, len)
+ int start;
+ int len;
+{
+#if defined(FEAT_CRYPT) || defined(FEAT_EVAL)
+ int i;
+
+ if (cmdline_star > 0)
+ for (i = 0; i < len; ++i)
+ {
+ msg_putchar('*');
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ i += (*mb_ptr2len_check)(ccline.cmdbuff + start + i) - 1;
+# endif
+ }
+ else
+#endif
+#ifdef FEAT_ARABIC
+ if (p_arshape && !p_tbidi && enc_utf8 && len > 0)
+ {
+ static char_u *buf;
+ static int buflen = 0;
+ char_u *p;
+ int j;
+ int newlen = 0;
+ int mb_l;
+ int pc, pc1;
+ int prev_c = 0;
+ int prev_c1 = 0;
+ int u8c, u8c_c1, u8c_c2;
+ int nc = 0;
+ int dummy;
+
+ /*
+ * Do arabic shaping into a temporary buffer. This is very
+ * inefficient!
+ */
+ if (len * 2 > buflen)
+ {
+ /* Re-allocate the buffer. We keep it around to avoid a lot of
+ * alloc()/free() calls. */
+ vim_free(buf);
+ buflen = len * 2;
+ buf = alloc(buflen);
+ if (buf == NULL)
+ return; /* out of memory */
+ }
+
+ for (j = start; j < start + len; j += mb_l)
+ {
+ p = ccline.cmdbuff + j;
+ u8c = utfc_ptr2char_len(p, &u8c_c1, &u8c_c2, start + len - j);
+ mb_l = utfc_ptr2len_check_len(p, start + len - j);
+ if (ARABIC_CHAR(u8c))
+ {
+ /* Do Arabic shaping. */
+ if (cmdmsg_rl)
+ {
+ /* displaying from right to left */
+ pc = prev_c;
+ pc1 = prev_c1;
+ prev_c1 = u8c_c1;
+ if (j + mb_l >= start + len)
+ nc = NUL;
+ else
+ nc = utf_ptr2char(p + mb_l);
+ }
+ else
+ {
+ /* displaying from left to right */
+ if (j + mb_l >= start + len)
+ pc = NUL;
+ else
+ pc = utfc_ptr2char_len(p + mb_l, &pc1, &dummy,
+ start + len - j - mb_l);
+ nc = prev_c;
+ }
+ prev_c = u8c;
+
+ u8c = arabic_shape(u8c, NULL, &u8c_c1, pc, pc1, nc);
+
+ newlen += (*mb_char2bytes)(u8c, buf + newlen);
+ if (u8c_c1 != 0)
+ {
+ newlen += (*mb_char2bytes)(u8c_c1, buf + newlen);
+ if (u8c_c2 != 0)
+ newlen += (*mb_char2bytes)(u8c_c2, buf + newlen);
+ }
+ }
+ else
+ {
+ prev_c = u8c;
+ mch_memmove(buf + newlen, p, mb_l);
+ newlen += mb_l;
+ }
+ }
+
+ msg_outtrans_len(buf, newlen);
+ }
+ else
+#endif
+ msg_outtrans_len(ccline.cmdbuff + start, len);
+}
+
+/*
+ * Put a character on the command line. Shifts the following text to the
+ * right when "shift" is TRUE. Used for CTRL-V, CTRL-K, etc.
+ * "c" must be printable (fit in one display cell)!
+ */
+ void
+putcmdline(c, shift)
+ int c;
+ int shift;
+{
+ if (cmd_silent)
+ return;
+ msg_no_more = TRUE;
+ msg_putchar(c);
+ if (shift)
+ draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos);
+ msg_no_more = FALSE;
+ cursorcmd();
+}
+
+/*
+ * Undo a putcmdline(c, FALSE).
+ */
+ void
+unputcmdline()
+{
+ if (cmd_silent)
+ return;
+ msg_no_more = TRUE;
+ if (ccline.cmdlen == ccline.cmdpos)
+ msg_putchar(' ');
+ else
+ draw_cmdline(ccline.cmdpos, 1);
+ msg_no_more = FALSE;
+ cursorcmd();
+}
+
+/*
+ * Put the given string, of the given length, onto the command line.
+ * If len is -1, then STRLEN() is used to calculate the length.
+ * If 'redraw' is TRUE then the new part of the command line, and the remaining
+ * part will be redrawn, otherwise it will not. If this function is called
+ * twice in a row, then 'redraw' should be FALSE and redrawcmd() should be
+ * called afterwards.
+ */
+ int
+put_on_cmdline(str, len, redraw)
+ char_u *str;
+ int len;
+ int redraw;
+{
+ int retval;
+ int i;
+ int m;
+ int c;
+
+ if (len < 0)
+ len = (int)STRLEN(str);
+
+ /* Check if ccline.cmdbuff needs to be longer */
+ if (ccline.cmdlen + len + 1 >= ccline.cmdbufflen)
+ retval = realloc_cmdbuff(ccline.cmdlen + len);
+ else
+ retval = OK;
+ if (retval == OK)
+ {
+ if (!ccline.overstrike)
+ {
+ mch_memmove(ccline.cmdbuff + ccline.cmdpos + len,
+ ccline.cmdbuff + ccline.cmdpos,
+ (size_t)(ccline.cmdlen - ccline.cmdpos));
+ ccline.cmdlen += len;
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ /* Count nr of characters in the new string. */
+ m = 0;
+ for (i = 0; i < len; i += (*mb_ptr2len_check)(str + i))
+ ++m;
+ /* Count nr of bytes in cmdline that are overwritten by these
+ * characters. */
+ for (i = ccline.cmdpos; i < ccline.cmdlen && m > 0;
+ i += (*mb_ptr2len_check)(ccline.cmdbuff + i))
+ --m;
+ if (i < ccline.cmdlen)
+ {
+ mch_memmove(ccline.cmdbuff + ccline.cmdpos + len,
+ ccline.cmdbuff + i, (size_t)(ccline.cmdlen - i));
+ ccline.cmdlen += ccline.cmdpos + len - i;
+ }
+ else
+ ccline.cmdlen = ccline.cmdpos + len;
+ }
+ else
+#endif
+ if (ccline.cmdpos + len > ccline.cmdlen)
+ ccline.cmdlen = ccline.cmdpos + len;
+ }
+ mch_memmove(ccline.cmdbuff + ccline.cmdpos, str, (size_t)len);
+ ccline.cmdbuff[ccline.cmdlen] = NUL;
+
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ {
+ /* When the inserted text starts with a composing character,
+ * backup to the character before it. There could be two of them.
+ */
+ i = 0;
+ c = utf_ptr2char(ccline.cmdbuff + ccline.cmdpos);
+ while (ccline.cmdpos > 0 && utf_iscomposing(c))
+ {
+ i = (*mb_head_off)(ccline.cmdbuff,
+ ccline.cmdbuff + ccline.cmdpos - 1) + 1;
+ ccline.cmdpos -= i;
+ len += i;
+ c = utf_ptr2char(ccline.cmdbuff + ccline.cmdpos);
+ }
+# ifdef FEAT_ARABIC
+ if (i == 0 && ccline.cmdpos > 0 && arabic_maycombine(c))
+ {
+ /* Check the previous character for Arabic combining pair. */
+ i = (*mb_head_off)(ccline.cmdbuff,
+ ccline.cmdbuff + ccline.cmdpos - 1) + 1;
+ if (arabic_combine(utf_ptr2char(ccline.cmdbuff
+ + ccline.cmdpos - i), c))
+ {
+ ccline.cmdpos -= i;
+ len += i;
+ }
+ else
+ i = 0;
+ }
+# endif
+ if (i != 0)
+ {
+ /* Also backup the cursor position. */
+ i = ptr2cells(ccline.cmdbuff + ccline.cmdpos);
+ ccline.cmdspos -= i;
+ msg_col -= i;
+ if (msg_col < 0)
+ {
+ msg_col += Columns;
+ --msg_row;
+ }
+ }
+ }
+#endif
+
+ if (redraw && !cmd_silent)
+ {
+ msg_no_more = TRUE;
+ i = cmdline_row;
+ draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos);
+ /* Avoid clearing the rest of the line too often. */
+ if (cmdline_row != i || ccline.overstrike)
+ msg_clr_eos();
+ msg_no_more = FALSE;
+ }
+#ifdef FEAT_FKMAP
+ /*
+ * If we are in Farsi command mode, the character input must be in
+ * Insert mode. So do not advance the cmdpos.
+ */
+ if (!cmd_fkmap)
+#endif
+ {
+ if (KeyTyped)
+ m = Columns * Rows;
+ else
+ m = MAXCOL;
+ for (i = 0; i < len; ++i)
+ {
+ c = cmdline_charsize(ccline.cmdpos);
+#ifdef FEAT_MBYTE
+ /* count ">" for a double-wide char that doesn't fit. */
+ if (has_mbyte)
+ correct_cmdspos(ccline.cmdpos, c);
+#endif
+ /* Stop cursor at the end of the screen */
+ if (ccline.cmdspos + c >= m)
+ break;
+ ccline.cmdspos += c;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ c = (*mb_ptr2len_check)(ccline.cmdbuff + ccline.cmdpos) - 1;
+ if (c > len - i - 1)
+ c = len - i - 1;
+ ccline.cmdpos += c;
+ i += c;
+ }
+#endif
+ ++ccline.cmdpos;
+ }
+ }
+ }
+ if (redraw)
+ msg_check();
+ return retval;
+}
+
+#ifdef FEAT_WILDMENU
+/*
+ * Delete characters on the command line, from "from" to the current
+ * position.
+ */
+ static void
+cmdline_del(from)
+ int from;
+{
+ mch_memmove(ccline.cmdbuff + from, ccline.cmdbuff + ccline.cmdpos,
+ (size_t)(ccline.cmdlen - ccline.cmdpos + 1));
+ ccline.cmdlen -= ccline.cmdpos - from;
+ ccline.cmdpos = from;
+}
+#endif
+
+/*
+ * this fuction is called when the screen size changes and with incremental
+ * search
+ */
+ void
+redrawcmdline()
+{
+ if (cmd_silent)
+ return;
+ need_wait_return = FALSE;
+ compute_cmdrow();
+ redrawcmd();
+ cursorcmd();
+}
+
+ static void
+redrawcmdprompt()
+{
+ int i;
+
+ if (cmd_silent)
+ return;
+ if (ccline.cmdfirstc)
+ msg_putchar(ccline.cmdfirstc);
+ if (ccline.cmdprompt != NULL)
+ {
+ msg_puts_attr(ccline.cmdprompt, ccline.cmdattr);
+ ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns;
+ /* do the reverse of set_cmdspos() */
+ if (ccline.cmdfirstc)
+ --ccline.cmdindent;
+ }
+ else
+ for (i = ccline.cmdindent; i > 0; --i)
+ msg_putchar(' ');
+}
+
+/*
+ * Redraw what is currently on the command line.
+ */
+ void
+redrawcmd()
+{
+ if (cmd_silent)
+ return;
+
+ msg_start();
+ redrawcmdprompt();
+
+ /* Don't use more prompt, truncate the cmdline if it doesn't fit. */
+ msg_no_more = TRUE;
+ draw_cmdline(0, ccline.cmdlen);
+ msg_clr_eos();
+ msg_no_more = FALSE;
+
+ set_cmdspos_cursor();
+
+ /*
+ * An emsg() before may have set msg_scroll. This is used in normal mode,
+ * in cmdline mode we can reset them now.
+ */
+ msg_scroll = FALSE; /* next message overwrites cmdline */
+
+ /* Typing ':' at the more prompt may set skip_redraw. We don't want this
+ * in cmdline mode */
+ skip_redraw = FALSE;
+}
+
+ void
+compute_cmdrow()
+{
+ if (exmode_active || msg_scrolled)
+ cmdline_row = Rows - 1;
+ else
+ cmdline_row = W_WINROW(lastwin) + lastwin->w_height
+ + W_STATUS_HEIGHT(lastwin);
+}
+
+ static void
+cursorcmd()
+{
+ if (cmd_silent)
+ return;
+
+#ifdef FEAT_RIGHTLEFT
+ if (cmdmsg_rl)
+ {
+ msg_row = cmdline_row + (ccline.cmdspos / (int)(Columns - 1));
+ msg_col = (int)Columns - (ccline.cmdspos % (int)(Columns - 1)) - 1;
+ if (msg_row <= 0)
+ msg_row = Rows - 1;
+ }
+ else
+#endif
+ {
+ msg_row = cmdline_row + (ccline.cmdspos / (int)Columns);
+ msg_col = ccline.cmdspos % (int)Columns;
+ if (msg_row >= Rows)
+ msg_row = Rows - 1;
+ }
+
+ windgoto(msg_row, msg_col);
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+ redrawcmd_preedit();
+#endif
+#ifdef MCH_CURSOR_SHAPE
+ mch_update_cursor();
+#endif
+}
+
+ void
+gotocmdline(clr)
+ int clr;
+{
+ msg_start();
+#ifdef FEAT_RIGHTLEFT
+ if (cmdmsg_rl)
+ msg_col = Columns - 1;
+ else
+#endif
+ msg_col = 0; /* always start in column 0 */
+ if (clr) /* clear the bottom line(s) */
+ msg_clr_eos(); /* will reset clear_cmdline */
+ windgoto(cmdline_row, 0);
+}
+
+/*
+ * Check the word in front of the cursor for an abbreviation.
+ * Called when the non-id character "c" has been entered.
+ * When an abbreviation is recognized it is removed from the text with
+ * backspaces and the replacement string is inserted, followed by "c".
+ */
+ static int
+ccheck_abbr(c)
+ int c;
+{
+ if (p_paste || no_abbr) /* no abbreviations or in paste mode */
+ return FALSE;
+
+ return check_abbr(c, ccline.cmdbuff, ccline.cmdpos, 0);
+}
+
+/*
+ * Return FAIL if this is not an appropriate context in which to do
+ * completion of anything, return OK if it is (even if there are no matches).
+ * For the caller, this means that the character is just passed through like a
+ * normal character (instead of being expanded). This allows :s/^I^D etc.
+ */
+ static int
+nextwild(xp, type, options)
+ expand_T *xp;
+ int type;
+ int options; /* extra options for ExpandOne() */
+{
+ int i, j;
+ char_u *p1;
+ char_u *p2;
+ int oldlen;
+ int difflen;
+ int v;
+
+ if (xp->xp_numfiles == -1)
+ {
+ set_expand_context(xp);
+ cmd_showtail = expand_showtail(xp);
+ }
+
+ if (xp->xp_context == EXPAND_UNSUCCESSFUL)
+ {
+ beep_flush();
+ return OK; /* Something illegal on command line */
+ }
+ if (xp->xp_context == EXPAND_NOTHING)
+ {
+ /* Caller can use the character as a normal char instead */
+ return FAIL;
+ }
+
+ MSG_PUTS("..."); /* show that we are busy */
+ out_flush();
+
+ i = (int)(xp->xp_pattern - ccline.cmdbuff);
+ oldlen = ccline.cmdpos - i;
+
+ if (type == WILD_NEXT || type == WILD_PREV)
+ {
+ /*
+ * Get next/previous match for a previous expanded pattern.
+ */
+ p2 = ExpandOne(xp, NULL, NULL, 0, type);
+ }
+ else
+ {
+ /*
+ * Translate string into pattern and expand it.
+ */
+ if ((p1 = addstar(&ccline.cmdbuff[i], oldlen, xp->xp_context)) == NULL)
+ p2 = NULL;
+ else
+ {
+ p2 = ExpandOne(xp, p1, vim_strnsave(&ccline.cmdbuff[i], oldlen),
+ WILD_HOME_REPLACE|WILD_ADD_SLASH|WILD_SILENT|WILD_ESCAPE
+ |options, type);
+ vim_free(p1);
+ /* longest match: make sure it is not shorter (happens with :help */
+ if (p2 != NULL && type == WILD_LONGEST)
+ {
+ for (j = 0; j < oldlen; ++j)
+ if (ccline.cmdbuff[i + j] == '*'
+ || ccline.cmdbuff[i + j] == '?')
+ break;
+ if ((int)STRLEN(p2) < j)
+ {
+ vim_free(p2);
+ p2 = NULL;
+ }
+ }
+ }
+ }
+
+ if (p2 != NULL && !got_int)
+ {
+ difflen = (int)STRLEN(p2) - oldlen;
+ if (ccline.cmdlen + difflen > ccline.cmdbufflen - 4)
+ {
+ v = realloc_cmdbuff(ccline.cmdlen + difflen);
+ xp->xp_pattern = ccline.cmdbuff + i;
+ }
+ else
+ v = OK;
+ if (v == OK)
+ {
+ vim_strncpy(&ccline.cmdbuff[ccline.cmdpos + difflen],
+ &ccline.cmdbuff[ccline.cmdpos],
+ ccline.cmdlen - ccline.cmdpos + 1);
+ STRNCPY(&ccline.cmdbuff[i], p2, STRLEN(p2));
+ ccline.cmdlen += difflen;
+ ccline.cmdpos += difflen;
+ }
+ }
+ vim_free(p2);
+
+ redrawcmd();
+
+ /* When expanding a ":map" command and no matches are found, assume that
+ * the key is supposed to be inserted literally */
+ if (xp->xp_context == EXPAND_MAPPINGS && p2 == NULL)
+ return FAIL;
+
+ if (xp->xp_numfiles <= 0 && p2 == NULL)
+ beep_flush();
+ else if (xp->xp_numfiles == 1)
+ /* free expanded pattern */
+ (void)ExpandOne(xp, NULL, NULL, 0, WILD_FREE);
+
+ return OK;
+}
+
+/*
+ * Do wildcard expansion on the string 'str'.
+ * Chars that should not be expanded must be preceded with a backslash.
+ * Return a pointer to alloced memory containing the new string.
+ * Return NULL for failure.
+ *
+ * Results are cached in xp->xp_files and xp->xp_numfiles.
+ *
+ * mode = WILD_FREE: just free previously expanded matches
+ * mode = WILD_EXPAND_FREE: normal expansion, do not keep matches
+ * mode = WILD_EXPAND_KEEP: normal expansion, keep matches
+ * mode = WILD_NEXT: use next match in multiple match, wrap to first
+ * mode = WILD_PREV: use previous match in multiple match, wrap to first
+ * mode = WILD_ALL: return all matches concatenated
+ * mode = WILD_LONGEST: return longest matched part
+ *
+ * options = WILD_LIST_NOTFOUND: list entries without a match
+ * options = WILD_HOME_REPLACE: do home_replace() for buffer names
+ * options = WILD_USE_NL: Use '\n' for WILD_ALL
+ * options = WILD_NO_BEEP: Don't beep for multiple matches
+ * options = WILD_ADD_SLASH: add a slash after directory names
+ * options = WILD_KEEP_ALL: don't remove 'wildignore' entries
+ * options = WILD_SILENT: don't print warning messages
+ * options = WILD_ESCAPE: put backslash before special chars
+ *
+ * The variables xp->xp_context and xp->xp_backslash must have been set!
+ */
+ char_u *
+ExpandOne(xp, str, orig, options, mode)
+ expand_T *xp;
+ char_u *str;
+ char_u *orig; /* allocated copy of original of expanded string */
+ int options;
+ int mode;
+{
+ char_u *ss = NULL;
+ static int findex;
+ static char_u *orig_save = NULL; /* kept value of orig */
+ int i;
+ long_u len;
+ int non_suf_match; /* number without matching suffix */
+
+ /*
+ * first handle the case of using an old match
+ */
+ if (mode == WILD_NEXT || mode == WILD_PREV)
+ {
+ if (xp->xp_numfiles > 0)
+ {
+ if (mode == WILD_PREV)
+ {
+ if (findex == -1)
+ findex = xp->xp_numfiles;
+ --findex;
+ }
+ else /* mode == WILD_NEXT */
+ ++findex;
+
+ /*
+ * When wrapping around, return the original string, set findex to
+ * -1.
+ */
+ if (findex < 0)
+ {
+ if (orig_save == NULL)
+ findex = xp->xp_numfiles - 1;
+ else
+ findex = -1;
+ }
+ if (findex >= xp->xp_numfiles)
+ {
+ if (orig_save == NULL)
+ findex = 0;
+ else
+ findex = -1;
+ }
+#ifdef FEAT_WILDMENU
+ if (p_wmnu)
+ win_redr_status_matches(xp, xp->xp_numfiles, xp->xp_files,
+ findex, cmd_showtail);
+#endif
+ if (findex == -1)
+ return vim_strsave(orig_save);
+ return vim_strsave(xp->xp_files[findex]);
+ }
+ else
+ return NULL;
+ }
+
+/* free old names */
+ if (xp->xp_numfiles != -1 && mode != WILD_ALL && mode != WILD_LONGEST)
+ {
+ FreeWild(xp->xp_numfiles, xp->xp_files);
+ xp->xp_numfiles = -1;
+ vim_free(orig_save);
+ orig_save = NULL;
+ }
+ findex = 0;
+
+ if (mode == WILD_FREE) /* only release file name */
+ return NULL;
+
+ if (xp->xp_numfiles == -1)
+ {
+ vim_free(orig_save);
+ orig_save = orig;
+
+ /*
+ * Do the expansion.
+ */
+ if (ExpandFromContext(xp, str, &xp->xp_numfiles, &xp->xp_files,
+ options) == FAIL)
+ {
+#ifdef FNAME_ILLEGAL
+ /* Illegal file name has been silently skipped. But when there
+ * are wildcards, the real problem is that there was no match,
+ * causing the pattern to be added, which has illegal characters.
+ */
+ if (!(options & WILD_SILENT) && (options & WILD_LIST_NOTFOUND))
+ EMSG2(_(e_nomatch2), str);
+#endif
+ }
+ else if (xp->xp_numfiles == 0)
+ {
+ if (!(options & WILD_SILENT))
+ EMSG2(_(e_nomatch2), str);
+ }
+ else
+ {
+ /* Escape the matches for use on the command line. */
+ ExpandEscape(xp, str, xp->xp_numfiles, xp->xp_files, options);
+
+ /*
+ * Check for matching suffixes in file names.
+ */
+ if (mode != WILD_ALL && mode != WILD_LONGEST)
+ {
+ if (xp->xp_numfiles)
+ non_suf_match = xp->xp_numfiles;
+ else
+ non_suf_match = 1;
+ if ((xp->xp_context == EXPAND_FILES
+ || xp->xp_context == EXPAND_DIRECTORIES)
+ && xp->xp_numfiles > 1)
+ {
+ /*
+ * More than one match; check suffix.
+ * The files will have been sorted on matching suffix in
+ * expand_wildcards, only need to check the first two.
+ */
+ non_suf_match = 0;
+ for (i = 0; i < 2; ++i)
+ if (match_suffix(xp->xp_files[i]))
+ ++non_suf_match;
+ }
+ if (non_suf_match != 1)
+ {
+ /* Can we ever get here unless it's while expanding
+ * interactively? If not, we can get rid of this all
+ * together. Don't really want to wait for this message
+ * (and possibly have to hit return to continue!).
+ */
+ if (!(options & WILD_SILENT))
+ EMSG(_(e_toomany));
+ else if (!(options & WILD_NO_BEEP))
+ beep_flush();
+ }
+ if (!(non_suf_match != 1 && mode == WILD_EXPAND_FREE))
+ ss = vim_strsave(xp->xp_files[0]);
+ }
+ }
+ }
+
+ /* Find longest common part */
+ if (mode == WILD_LONGEST && xp->xp_numfiles > 0)
+ {
+ for (len = 0; xp->xp_files[0][len]; ++len)
+ {
+ for (i = 0; i < xp->xp_numfiles; ++i)
+ {
+#ifdef CASE_INSENSITIVE_FILENAME
+ if (xp->xp_context == EXPAND_DIRECTORIES
+ || xp->xp_context == EXPAND_FILES
+ || xp->xp_context == EXPAND_BUFFERS)
+ {
+ if (TOLOWER_LOC(xp->xp_files[i][len]) !=
+ TOLOWER_LOC(xp->xp_files[0][len]))
+ break;
+ }
+ else
+#endif
+ if (xp->xp_files[i][len] != xp->xp_files[0][len])
+ break;
+ }
+ if (i < xp->xp_numfiles)
+ {
+ if (!(options & WILD_NO_BEEP))
+ vim_beep();
+ break;
+ }
+ }
+ ss = alloc((unsigned)len + 1);
+ if (ss)
+ {
+ STRNCPY(ss, xp->xp_files[0], len);
+ ss[len] = NUL;
+ }
+ findex = -1; /* next p_wc gets first one */
+ }
+
+ /* Concatenate all matching names */
+ if (mode == WILD_ALL && xp->xp_numfiles > 0)
+ {
+ len = 0;
+ for (i = 0; i < xp->xp_numfiles; ++i)
+ len += (long_u)STRLEN(xp->xp_files[i]) + 1;
+ ss = lalloc(len, TRUE);
+ if (ss != NULL)
+ {
+ *ss = NUL;
+ for (i = 0; i < xp->xp_numfiles; ++i)
+ {
+ STRCAT(ss, xp->xp_files[i]);
+ if (i != xp->xp_numfiles - 1)
+ STRCAT(ss, (options & WILD_USE_NL) ? "\n" : " ");
+ }
+ }
+ }
+
+ if (mode == WILD_EXPAND_FREE || mode == WILD_ALL)
+ ExpandCleanup(xp);
+
+ return ss;
+}
+
+/*
+ * Prepare an expand structure for use.
+ */
+ void
+ExpandInit(xp)
+ expand_T *xp;
+{
+ xp->xp_backslash = XP_BS_NONE;
+ xp->xp_numfiles = -1;
+ xp->xp_files = NULL;
+}
+
+/*
+ * Cleanup an expand structure after use.
+ */
+ void
+ExpandCleanup(xp)
+ expand_T *xp;
+{
+ if (xp->xp_numfiles >= 0)
+ {
+ FreeWild(xp->xp_numfiles, xp->xp_files);
+ xp->xp_numfiles = -1;
+ }
+}
+
+ void
+ExpandEscape(xp, str, numfiles, files, options)
+ expand_T *xp;
+ char_u *str;
+ int numfiles;
+ char_u **files;
+ int options;
+{
+ int i;
+ char_u *p;
+
+ /*
+ * May change home directory back to "~"
+ */
+ if (options & WILD_HOME_REPLACE)
+ tilde_replace(str, numfiles, files);
+
+ if (options & WILD_ESCAPE)
+ {
+ if (xp->xp_context == EXPAND_FILES
+ || xp->xp_context == EXPAND_BUFFERS
+ || xp->xp_context == EXPAND_DIRECTORIES)
+ {
+ /*
+ * Insert a backslash into a file name before a space, \, %, #
+ * and wildmatch characters, except '~'.
+ */
+ for (i = 0; i < numfiles; ++i)
+ {
+ /* for ":set path=" we need to escape spaces twice */
+ if (xp->xp_backslash == XP_BS_THREE)
+ {
+ p = vim_strsave_escaped(files[i], (char_u *)" ");
+ if (p != NULL)
+ {
+ vim_free(files[i]);
+ files[i] = p;
+#if defined(BACKSLASH_IN_FILENAME) || defined(COLON_AS_PATHSEP)
+ p = vim_strsave_escaped(files[i], (char_u *)" ");
+ if (p != NULL)
+ {
+ vim_free(files[i]);
+ files[i] = p;
+ }
+#endif
+ }
+ }
+#ifdef BACKSLASH_IN_FILENAME
+ {
+ char_u buf[20];
+ int j = 0;
+
+ /* Don't escape '[' and '{' if they are in 'isfname'. */
+ for (p = PATH_ESC_CHARS; *p != NUL; ++p)
+ if ((*p != '[' && *p != '{') || !vim_isfilec(*p))
+ buf[j++] = *p;
+ buf[j] = NUL;
+ p = vim_strsave_escaped(files[i], buf);
+ }
+#else
+ p = vim_strsave_escaped(files[i], PATH_ESC_CHARS);
+#endif
+ if (p != NULL)
+ {
+ vim_free(files[i]);
+ files[i] = p;
+ }
+
+ /* If 'str' starts with "\~", replace "~" at start of
+ * files[i] with "\~". */
+ if (str[0] == '\\' && str[1] == '~' && files[i][0] == '~')
+ {
+ p = alloc((unsigned)(STRLEN(files[i]) + 2));
+ if (p != NULL)
+ {
+ p[0] = '\\';
+ STRCPY(p + 1, files[i]);
+ vim_free(files[i]);
+ files[i] = p;
+ }
+ }
+ }
+ xp->xp_backslash = XP_BS_NONE;
+ }
+ else if (xp->xp_context == EXPAND_TAGS)
+ {
+ /*
+ * Insert a backslash before characters in a tag name that
+ * would terminate the ":tag" command.
+ */
+ for (i = 0; i < numfiles; ++i)
+ {
+ p = vim_strsave_escaped(files[i], (char_u *)"\\|\"");
+ if (p != NULL)
+ {
+ vim_free(files[i]);
+ files[i] = p;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * For each file name in files[num_files]:
+ * If 'orig_pat' starts with "~/", replace the home directory with "~".
+ */
+ void
+tilde_replace(orig_pat, num_files, files)
+ char_u *orig_pat;
+ int num_files;
+ char_u **files;
+{
+ int i;
+ char_u *p;
+
+ if (orig_pat[0] == '~' && vim_ispathsep(orig_pat[1]))
+ {
+ for (i = 0; i < num_files; ++i)
+ {
+ p = home_replace_save(NULL, files[i]);
+ if (p != NULL)
+ {
+ vim_free(files[i]);
+ files[i] = p;
+ }
+ }
+ }
+}
+
+/*
+ * Show all matches for completion on the command line.
+ * Returns EXPAND_NOTHING when the character that triggered expansion should
+ * be inserted like a normal character.
+ */
+/*ARGSUSED*/
+ static int
+showmatches(xp, wildmenu)
+ expand_T *xp;
+ int wildmenu;
+{
+#define L_SHOWFILE(m) (showtail ? sm_gettail(files_found[m]) : files_found[m])
+ int num_files;
+ char_u **files_found;
+ int i, j, k;
+ int maxlen;
+ int lines;
+ int columns;
+ char_u *p;
+ int lastlen;
+ int attr;
+ int showtail;
+
+ if (xp->xp_numfiles == -1)
+ {
+ set_expand_context(xp);
+ i = expand_cmdline(xp, ccline.cmdbuff, ccline.cmdpos,
+ &num_files, &files_found);
+ showtail = expand_showtail(xp);
+ if (i != EXPAND_OK)
+ return i;
+
+ }
+ else
+ {
+ num_files = xp->xp_numfiles;
+ files_found = xp->xp_files;
+ showtail = cmd_showtail;
+ }
+
+#ifdef FEAT_WILDMENU
+ if (!wildmenu)
+ {
+#endif
+ msg_didany = FALSE; /* lines_left will be set */
+ msg_start(); /* prepare for paging */
+ msg_putchar('\n');
+ out_flush();
+ cmdline_row = msg_row;
+ msg_didany = FALSE; /* lines_left will be set again */
+ msg_start(); /* prepare for paging */
+#ifdef FEAT_WILDMENU
+ }
+#endif
+
+ if (got_int)
+ got_int = FALSE; /* only int. the completion, not the cmd line */
+#ifdef FEAT_WILDMENU
+ else if (wildmenu)
+ win_redr_status_matches(xp, num_files, files_found, 0, showtail);
+#endif
+ else
+ {
+ /* find the length of the longest file name */
+ maxlen = 0;
+ for (i = 0; i < num_files; ++i)
+ {
+ if (!showtail && (xp->xp_context == EXPAND_FILES
+ || xp->xp_context == EXPAND_BUFFERS))
+ {
+ home_replace(NULL, files_found[i], NameBuff, MAXPATHL, TRUE);
+ j = vim_strsize(NameBuff);
+ }
+ else
+ j = vim_strsize(L_SHOWFILE(i));
+ if (j > maxlen)
+ maxlen = j;
+ }
+
+ if (xp->xp_context == EXPAND_TAGS_LISTFILES)
+ lines = num_files;
+ else
+ {
+ /* compute the number of columns and lines for the listing */
+ maxlen += 2; /* two spaces between file names */
+ columns = ((int)Columns + 2) / maxlen;
+ if (columns < 1)
+ columns = 1;
+ lines = (num_files + columns - 1) / columns;
+ }
+
+ attr = hl_attr(HLF_D); /* find out highlighting for directories */
+
+ if (xp->xp_context == EXPAND_TAGS_LISTFILES)
+ {
+ MSG_PUTS_ATTR(_("tagname"), hl_attr(HLF_T));
+ msg_clr_eos();
+ msg_advance(maxlen - 3);
+ MSG_PUTS_ATTR(_(" kind file\n"), hl_attr(HLF_T));
+ }
+
+ /* list the files line by line */
+ for (i = 0; i < lines; ++i)
+ {
+ lastlen = 999;
+ for (k = i; k < num_files; k += lines)
+ {
+ if (xp->xp_context == EXPAND_TAGS_LISTFILES)
+ {
+ msg_outtrans_attr(files_found[k], hl_attr(HLF_D));
+ p = files_found[k] + STRLEN(files_found[k]) + 1;
+ msg_advance(maxlen + 1);
+ msg_puts(p);
+ msg_advance(maxlen + 3);
+ msg_puts_long_attr(p + 2, hl_attr(HLF_D));
+ break;
+ }
+ for (j = maxlen - lastlen; --j >= 0; )
+ msg_putchar(' ');
+ if (xp->xp_context == EXPAND_FILES
+ || xp->xp_context == EXPAND_BUFFERS)
+ {
+ /* highlight directories */
+ j = (mch_isdir(files_found[k]));
+ if (showtail)
+ p = L_SHOWFILE(k);
+ else
+ {
+ home_replace(NULL, files_found[k], NameBuff, MAXPATHL,
+ TRUE);
+ p = NameBuff;
+ }
+ }
+ else
+ {
+ j = FALSE;
+ p = L_SHOWFILE(k);
+ }
+ lastlen = msg_outtrans_attr(p, j ? attr : 0);
+ }
+ if (msg_col > 0) /* when not wrapped around */
+ {
+ msg_clr_eos();
+ msg_putchar('\n');
+ }
+ out_flush(); /* show one line at a time */
+ if (got_int)
+ {
+ got_int = FALSE;
+ break;
+ }
+ }
+
+ /*
+ * we redraw the command below the lines that we have just listed
+ * This is a bit tricky, but it saves a lot of screen updating.
+ */
+ cmdline_row = msg_row; /* will put it back later */
+ }
+
+ if (xp->xp_numfiles == -1)
+ FreeWild(num_files, files_found);
+
+ return EXPAND_OK;
+}
+
+/*
+ * Private gettail for showmatches() (and win_redr_status_matches()):
+ * Find tail of file name path, but ignore trailing "/".
+ */
+ char_u *
+sm_gettail(s)
+ char_u *s;
+{
+ char_u *p;
+ char_u *t = s;
+ int had_sep = FALSE;
+
+ for (p = s; *p != NUL; )
+ {
+ if (vim_ispathsep(*p)
+#ifdef BACKSLASH_IN_FILENAME
+ && !rem_backslash(p)
+#endif
+ )
+ had_sep = TRUE;
+ else if (had_sep)
+ {
+ t = p;
+ had_sep = FALSE;
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p);
+ else
+#endif
+ ++p;
+ }
+ return t;
+}
+
+/*
+ * Return TRUE if we only need to show the tail of completion matches.
+ * When not completing file names or there is a wildcard in the path FALSE is
+ * returned.
+ */
+ static int
+expand_showtail(xp)
+ expand_T *xp;
+{
+ char_u *s;
+ char_u *end;
+
+ /* When not completing file names a "/" may mean something different. */
+ if (xp->xp_context != EXPAND_FILES && xp->xp_context != EXPAND_DIRECTORIES)
+ return FALSE;
+
+ end = gettail(xp->xp_pattern);
+ if (end == xp->xp_pattern) /* there is no path separator */
+ return FALSE;
+
+ for (s = xp->xp_pattern; s < end; s++)
+ {
+ /* Skip escaped wildcards. Only when the backslash is not a path
+ * separator, on DOS the '*' "path\*\file" must not be skipped. */
+ if (rem_backslash(s))
+ ++s;
+ else if (vim_strchr((char_u *)"*?[", *s) != NULL)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Prepare a string for expansion.
+ * When expanding file names: The string will be used with expand_wildcards().
+ * Copy the file name into allocated memory and add a '*' at the end.
+ * When expanding other names: The string will be used with regcomp(). Copy
+ * the name into allocated memory and prepend "^".
+ */
+ char_u *
+addstar(fname, len, context)
+ char_u *fname;
+ int len;
+ int context; /* EXPAND_FILES etc. */
+{
+ char_u *retval;
+ int i, j;
+ int new_len;
+ char_u *tail;
+
+ if (context != EXPAND_FILES && context != EXPAND_DIRECTORIES)
+ {
+ /*
+ * Matching will be done internally (on something other than files).
+ * So we convert the file-matching-type wildcards into our kind for
+ * use with vim_regcomp(). First work out how long it will be:
+ */
+
+ /* For help tags the translation is done in find_help_tags().
+ * For a tag pattern starting with "/" no translation is needed. */
+ if (context == EXPAND_HELP
+ || context == EXPAND_COLORS
+ || context == EXPAND_COMPILER
+ || (context == EXPAND_TAGS && fname[0] == '/'))
+ retval = vim_strnsave(fname, len);
+ else
+ {
+ new_len = len + 2; /* +2 for '^' at start, NUL at end */
+ for (i = 0; i < len; i++)
+ {
+ if (fname[i] == '*' || fname[i] == '~')
+ new_len++; /* '*' needs to be replaced by ".*"
+ '~' needs to be replaced by "\~" */
+
+ /* Buffer names are like file names. "." should be literal */
+ if (context == EXPAND_BUFFERS && fname[i] == '.')
+ new_len++; /* "." becomes "\." */
+
+ /* Custom expansion takes care of special things, match
+ * backslashes literally (perhaps also for other types?) */
+ if (context == EXPAND_USER_DEFINED && fname[i] == '\\')
+ new_len++; /* '\' becomes "\\" */
+ }
+ retval = alloc(new_len);
+ if (retval != NULL)
+ {
+ retval[0] = '^';
+ j = 1;
+ for (i = 0; i < len; i++, j++)
+ {
+ /* Skip backslash. But why? At least keep it for custom
+ * expansion. */
+ if (context != EXPAND_USER_DEFINED
+ && fname[i] == '\\' && ++i == len)
+ break;
+
+ switch (fname[i])
+ {
+ case '*': retval[j++] = '.';
+ break;
+ case '~': retval[j++] = '\\';
+ break;
+ case '?': retval[j] = '.';
+ continue;
+ case '.': if (context == EXPAND_BUFFERS)
+ retval[j++] = '\\';
+ break;
+ case '\\': if (context == EXPAND_USER_DEFINED)
+ retval[j++] = '\\';
+ break;
+ }
+ retval[j] = fname[i];
+ }
+ retval[j] = NUL;
+ }
+ }
+ }
+ else
+ {
+ retval = alloc(len + 4);
+ if (retval != NULL)
+ {
+ STRNCPY(retval, fname, len);
+ retval[len] = NUL;
+
+ /*
+ * Don't add a star to ~, ~user, $var or `cmd`.
+ * ~ would be at the start of the file name, but not the tail.
+ * $ could be anywhere in the tail.
+ * ` could be anywhere in the file name.
+ */
+ tail = gettail(retval);
+ if ((*retval != '~' || tail != retval)
+ && vim_strchr(tail, '$') == NULL
+ && vim_strchr(retval, '`') == NULL)
+ retval[len++] = '*';
+ retval[len] = NUL;
+ }
+ }
+ return retval;
+}
+
+/*
+ * Must parse the command line so far to work out what context we are in.
+ * Completion can then be done based on that context.
+ * This routine sets the variables:
+ * xp->xp_pattern The start of the pattern to be expanded within
+ * the command line (ends at the cursor).
+ * xp->xp_context The type of thing to expand. Will be one of:
+ *
+ * EXPAND_UNSUCCESSFUL Used sometimes when there is something illegal on
+ * the command line, like an unknown command. Caller
+ * should beep.
+ * EXPAND_NOTHING Unrecognised context for completion, use char like
+ * a normal char, rather than for completion. eg
+ * :s/^I/
+ * EXPAND_COMMANDS Cursor is still touching the command, so complete
+ * it.
+ * EXPAND_BUFFERS Complete file names for :buf and :sbuf commands.
+ * EXPAND_FILES After command with XFILE set, or after setting
+ * with P_EXPAND set. eg :e ^I, :w>>^I
+ * EXPAND_DIRECTORIES In some cases this is used instead of the latter
+ * when we know only directories are of interest. eg
+ * :set dir=^I
+ * EXPAND_SETTINGS Complete variable names. eg :set d^I
+ * EXPAND_BOOL_SETTINGS Complete boolean variables only, eg :set no^I
+ * EXPAND_TAGS Complete tags from the files in p_tags. eg :ta a^I
+ * EXPAND_TAGS_LISTFILES As above, but list filenames on ^D, after :tselect
+ * EXPAND_HELP Complete tags from the file 'helpfile'/tags
+ * EXPAND_EVENTS Complete event names
+ * EXPAND_SYNTAX Complete :syntax command arguments
+ * EXPAND_HIGHLIGHT Complete highlight (syntax) group names
+ * EXPAND_AUGROUP Complete autocommand group names
+ * EXPAND_USER_VARS Complete user defined variable names, eg :unlet a^I
+ * EXPAND_MAPPINGS Complete mapping and abbreviation names,
+ * eg :unmap a^I , :cunab x^I
+ * EXPAND_FUNCTIONS Complete internal or user defined function names,
+ * eg :call sub^I
+ * EXPAND_USER_FUNC Complete user defined function names, eg :delf F^I
+ * EXPAND_EXPRESSION Complete internal or user defined function/variable
+ * names in expressions, eg :while s^I
+ * EXPAND_ENV_VARS Complete environment variable names
+ */
+ static void
+set_expand_context(xp)
+ expand_T *xp;
+{
+ /* only expansion for ':' and '>' commands */
+ if (ccline.cmdfirstc != ':'
+#ifdef FEAT_EVAL
+ && ccline.cmdfirstc != '>'
+#endif
+ )
+ {
+ xp->xp_context = EXPAND_NOTHING;
+ return;
+ }
+ set_cmd_context(xp, ccline.cmdbuff, ccline.cmdlen, ccline.cmdpos);
+}
+
+ void
+set_cmd_context(xp, str, len, col)
+ expand_T *xp;
+ char_u *str; /* start of command line */
+ int len; /* length of command line (excl. NUL) */
+ int col; /* position of cursor */
+{
+ int old_char = NUL;
+ char_u *nextcomm;
+
+ /*
+ * Avoid a UMR warning from Purify, only save the character if it has been
+ * written before.
+ */
+ if (col < len)
+ old_char = str[col];
+ str[col] = NUL;
+ nextcomm = str;
+ while (nextcomm != NULL)
+ nextcomm = set_one_cmd_context(xp, nextcomm);
+ str[col] = old_char;
+}
+
+/*
+ * Expand the command line "str" from context "xp".
+ * "xp" must have been set by set_cmd_context().
+ * xp->xp_pattern points into "str", to where the text that is to be expanded
+ * starts.
+ * Returns EXPAND_UNSUCCESSFUL when there is something illegal before the
+ * cursor.
+ * Returns EXPAND_NOTHING when there is nothing to expand, might insert the
+ * key that triggered expansion literally.
+ * Returns EXPAND_OK otherwise.
+ */
+ int
+expand_cmdline(xp, str, col, matchcount, matches)
+ expand_T *xp;
+ char_u *str; /* start of command line */
+ int col; /* position of cursor */
+ int *matchcount; /* return: nr of matches */
+ char_u ***matches; /* return: array of pointers to matches */
+{
+ char_u *file_str = NULL;
+
+ if (xp->xp_context == EXPAND_UNSUCCESSFUL)
+ {
+ beep_flush();
+ return EXPAND_UNSUCCESSFUL; /* Something illegal on command line */
+ }
+ if (xp->xp_context == EXPAND_NOTHING)
+ {
+ /* Caller can use the character as a normal char instead */
+ return EXPAND_NOTHING;
+ }
+
+ /* add star to file name, or convert to regexp if not exp. files. */
+ file_str = addstar(xp->xp_pattern,
+ (int)(str + col - xp->xp_pattern), xp->xp_context);
+ if (file_str == NULL)
+ return EXPAND_UNSUCCESSFUL;
+
+ /* find all files that match the description */
+ if (ExpandFromContext(xp, file_str, matchcount, matches,
+ WILD_ADD_SLASH|WILD_SILENT) == FAIL)
+ {
+ *matchcount = 0;
+ *matches = NULL;
+ }
+ vim_free(file_str);
+
+ return EXPAND_OK;
+}
+
+#ifdef FEAT_MULTI_LANG
+/*
+ * Cleanup matches for help tags: remove "@en" if "en" is the only language.
+ */
+static void cleanup_help_tags __ARGS((int num_file, char_u **file));
+
+ static void
+cleanup_help_tags(num_file, file)
+ int num_file;
+ char_u **file;
+{
+ int i, j;
+ int len;
+
+ for (i = 0; i < num_file; ++i)
+ {
+ len = (int)STRLEN(file[i]) - 3;
+ if (len > 0 && STRCMP(file[i] + len, "@en") == 0)
+ {
+ /* Sorting on priority means the same item in another language may
+ * be anywhere. Search all items for a match up to the "@en". */
+ for (j = 0; j < num_file; ++j)
+ if (j != i
+ && (int)STRLEN(file[j]) == len + 3
+ && STRNCMP(file[i], file[j], len + 1) == 0)
+ break;
+ if (j == num_file)
+ file[i][len] = NUL;
+ }
+ }
+}
+#endif
+
+/*
+ * Do the expansion based on xp->xp_context and "pat".
+ */
+ static int
+ExpandFromContext(xp, pat, num_file, file, options)
+ expand_T *xp;
+ char_u *pat;
+ int *num_file;
+ char_u ***file;
+ int options;
+{
+#ifdef FEAT_CMDL_COMPL
+ regmatch_T regmatch;
+#endif
+ int ret;
+ int flags;
+
+ flags = EW_DIR; /* include directories */
+ if (options & WILD_LIST_NOTFOUND)
+ flags |= EW_NOTFOUND;
+ if (options & WILD_ADD_SLASH)
+ flags |= EW_ADDSLASH;
+ if (options & WILD_KEEP_ALL)
+ flags |= EW_KEEPALL;
+ if (options & WILD_SILENT)
+ flags |= EW_SILENT;
+
+ if (xp->xp_context == EXPAND_FILES || xp->xp_context == EXPAND_DIRECTORIES)
+ {
+ /*
+ * Expand file or directory names.
+ */
+ int free_pat = FALSE;
+ int i;
+
+ /* for ":set path=" and ":set tags=" halve backslashes for escaped
+ * space */
+ if (xp->xp_backslash != XP_BS_NONE)
+ {
+ free_pat = TRUE;
+ pat = vim_strsave(pat);
+ for (i = 0; pat[i]; ++i)
+ if (pat[i] == '\\')
+ {
+ if (xp->xp_backslash == XP_BS_THREE
+ && pat[i + 1] == '\\'
+ && pat[i + 2] == '\\'
+ && pat[i + 3] == ' ')
+ STRCPY(pat + i, pat + i + 3);
+ if (xp->xp_backslash == XP_BS_ONE
+ && pat[i + 1] == ' ')
+ STRCPY(pat + i, pat + i + 1);
+ }
+ }
+
+ if (xp->xp_context == EXPAND_FILES)
+ flags |= EW_FILE;
+ else
+ flags = (flags | EW_DIR) & ~EW_FILE;
+ ret = expand_wildcards(1, &pat, num_file, file, flags);
+ if (free_pat)
+ vim_free(pat);
+ return ret;
+ }
+
+ *file = (char_u **)"";
+ *num_file = 0;
+ if (xp->xp_context == EXPAND_HELP)
+ {
+ if (find_help_tags(pat, num_file, file, FALSE) == OK)
+ {
+#ifdef FEAT_MULTI_LANG
+ cleanup_help_tags(*num_file, *file);
+#endif
+ return OK;
+ }
+ return FAIL;
+ }
+
+#ifndef FEAT_CMDL_COMPL
+ return FAIL;
+#else
+ if (xp->xp_context == EXPAND_OLD_SETTING)
+ return ExpandOldSetting(num_file, file);
+ if (xp->xp_context == EXPAND_BUFFERS)
+ return ExpandBufnames(pat, num_file, file, options);
+ if (xp->xp_context == EXPAND_TAGS
+ || xp->xp_context == EXPAND_TAGS_LISTFILES)
+ return expand_tags(xp->xp_context == EXPAND_TAGS, pat, num_file, file);
+ if (xp->xp_context == EXPAND_COLORS)
+ return ExpandRTDir(pat, num_file, file, "colors");
+ if (xp->xp_context == EXPAND_COMPILER)
+ return ExpandRTDir(pat, num_file, file, "compiler");
+
+ regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
+ if (regmatch.regprog == NULL)
+ return FAIL;
+
+ /* set ignore-case according to p_ic, p_scs and pat */
+ regmatch.rm_ic = ignorecase(pat);
+
+ if (xp->xp_context == EXPAND_SETTINGS
+ || xp->xp_context == EXPAND_BOOL_SETTINGS)
+ ret = ExpandSettings(xp, &regmatch, num_file, file);
+ else if (xp->xp_context == EXPAND_MAPPINGS)
+ ret = ExpandMappings(&regmatch, num_file, file);
+# if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
+ else if (xp->xp_context == EXPAND_USER_DEFINED)
+ ret = ExpandUserDefined(xp, &regmatch, num_file, file);
+# endif
+ else
+ {
+ static struct expgen
+ {
+ int context;
+ char_u *((*func)__ARGS((expand_T *, int)));
+ int ic;
+ } tab[] =
+ {
+ {EXPAND_COMMANDS, get_command_name, FALSE},
+#ifdef FEAT_USR_CMDS
+ {EXPAND_USER_COMMANDS, get_user_commands, FALSE},
+ {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE},
+ {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE},
+ {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE},
+#endif
+#ifdef FEAT_EVAL
+ {EXPAND_USER_VARS, get_user_var_name, FALSE},
+ {EXPAND_FUNCTIONS, get_function_name, FALSE},
+ {EXPAND_USER_FUNC, get_user_func_name, FALSE},
+ {EXPAND_EXPRESSION, get_expr_name, FALSE},
+#endif
+#ifdef FEAT_MENU
+ {EXPAND_MENUS, get_menu_name, FALSE},
+ {EXPAND_MENUNAMES, get_menu_names, FALSE},
+#endif
+#ifdef FEAT_SYN_HL
+ {EXPAND_SYNTAX, get_syntax_name, TRUE},
+#endif
+ {EXPAND_HIGHLIGHT, get_highlight_name, TRUE},
+#ifdef FEAT_AUTOCMD
+ {EXPAND_EVENTS, get_event_name, TRUE},
+ {EXPAND_AUGROUP, get_augroup_name, TRUE},
+#endif
+#if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
+ && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
+ {EXPAND_LANGUAGE, get_lang_arg, TRUE},
+#endif
+ {EXPAND_ENV_VARS, get_env_name, TRUE},
+ };
+ int i;
+
+ /*
+ * Find a context in the table and call the ExpandGeneric() with the
+ * right function to do the expansion.
+ */
+ ret = FAIL;
+ for (i = 0; i < sizeof(tab) / sizeof(struct expgen); ++i)
+ if (xp->xp_context == tab[i].context)
+ {
+ if (tab[i].ic)
+ regmatch.rm_ic = TRUE;
+ ret = ExpandGeneric(xp, &regmatch, num_file, file, tab[i].func);
+ break;
+ }
+ }
+
+ vim_free(regmatch.regprog);
+
+ return ret;
+#endif /* FEAT_CMDL_COMPL */
+}
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+/*
+ * Expand a list of names.
+ *
+ * Generic function for command line completion. It calls a function to
+ * obtain strings, one by one. The strings are matched against a regexp
+ * program. Matching strings are copied into an array, which is returned.
+ *
+ * Returns OK when no problems encountered, FAIL for error (out of memory).
+ */
+ int
+ExpandGeneric(xp, regmatch, num_file, file, func)
+ expand_T *xp;
+ regmatch_T *regmatch;
+ int *num_file;
+ char_u ***file;
+ char_u *((*func)__ARGS((expand_T *, int)));
+ /* returns a string from the list */
+{
+ int i;
+ int count = 0;
+ int loop;
+ char_u *str;
+
+ /* do this loop twice:
+ * loop == 0: count the number of matching names
+ * loop == 1: copy the matching names into allocated memory
+ */
+ for (loop = 0; loop <= 1; ++loop)
+ {
+ for (i = 0; ; ++i)
+ {
+ str = (*func)(xp, i);
+ if (str == NULL) /* end of list */
+ break;
+ if (*str == NUL) /* skip empty strings */
+ continue;
+
+ if (vim_regexec(regmatch, str, (colnr_T)0))
+ {
+ if (loop)
+ {
+ str = vim_strsave_escaped(str, (char_u *)" \t\\.");
+ (*file)[count] = str;
+#ifdef FEAT_MENU
+ if (func == get_menu_names && str != NULL)
+ {
+ /* test for separator added by get_menu_names() */
+ str += STRLEN(str) - 1;
+ if (*str == '\001')
+ *str = '.';
+ }
+#endif
+ }
+ ++count;
+ }
+ }
+ if (loop == 0)
+ {
+ if (count == 0)
+ return OK;
+ *num_file = count;
+ *file = (char_u **)alloc((unsigned)(count * sizeof(char_u *)));
+ if (*file == NULL)
+ {
+ *file = (char_u **)"";
+ return FAIL;
+ }
+ count = 0;
+ }
+ }
+ return OK;
+}
+
+# if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
+/*
+ * Expand names with a function defined by the user.
+ */
+ static int
+ExpandUserDefined(xp, regmatch, num_file, file)
+ expand_T *xp;
+ regmatch_T *regmatch;
+ int *num_file;
+ char_u ***file;
+{
+ char_u *args[3];
+ char_u *all;
+ char_u *s;
+ char_u *e;
+ char_u keep;
+ char_u num[50];
+ garray_T ga;
+ int save_current_SID = current_SID;
+
+ if (xp->xp_arg == NULL || xp->xp_arg[0] == '\0')
+ return FAIL;
+ *num_file = 0;
+ *file = NULL;
+
+ keep = ccline.cmdbuff[ccline.cmdlen];
+ ccline.cmdbuff[ccline.cmdlen] = 0;
+ sprintf((char *)num, "%d", ccline.cmdpos);
+ args[0] = xp->xp_pattern;
+ args[1] = ccline.cmdbuff;
+ args[2] = num;
+
+ current_SID = xp->xp_scriptID;
+ all = call_vim_function(xp->xp_arg, 3, args, FALSE);
+ current_SID = save_current_SID;
+ ccline.cmdbuff[ccline.cmdlen] = keep;
+ if (all == NULL)
+ return FAIL;
+
+ ga_init2(&ga, (int)sizeof(char *), 3);
+ for (s = all; *s != NUL; s = e)
+ {
+ e = vim_strchr(s, '\n');
+ if (e == NULL)
+ e = s + STRLEN(s);
+ keep = *e;
+ *e = 0;
+
+ if (xp->xp_pattern[0] && vim_regexec(regmatch, s, (colnr_T)0) == 0)
+ {
+ *e = keep;
+ if (*e != NUL)
+ ++e;
+ continue;
+ }
+
+ if (ga_grow(&ga, 1) == FAIL)
+ break;
+
+ ((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, (int)(e - s));
+ ++ga.ga_len;
+ --ga.ga_room;
+
+ *e = keep;
+ if (*e != NUL)
+ ++e;
+ }
+ vim_free(all);
+ *file = ga.ga_data;
+ *num_file = ga.ga_len;
+ return OK;
+}
+#endif
+
+/*
+ * Expand color scheme names: 'runtimepath'/colors/{pat}.vim
+ * or compiler names.
+ */
+ static int
+ExpandRTDir(pat, num_file, file, dirname)
+ char_u *pat;
+ int *num_file;
+ char_u ***file;
+ char *dirname; /* "colors" or "compiler" */
+{
+ char_u *all;
+ char_u *s;
+ char_u *e;
+ garray_T ga;
+
+ *num_file = 0;
+ *file = NULL;
+ s = alloc((unsigned)(STRLEN(pat) + STRLEN(dirname) + 7));
+ if (s == NULL)
+ return FAIL;
+ sprintf((char *)s, "%s/%s*.vim", dirname, pat);
+ all = globpath(p_rtp, s);
+ vim_free(s);
+ if (all == NULL)
+ return FAIL;
+
+ ga_init2(&ga, (int)sizeof(char *), 3);
+ for (s = all; *s != NUL; s = e)
+ {
+ e = vim_strchr(s, '\n');
+ if (e == NULL)
+ e = s + STRLEN(s);
+ if (ga_grow(&ga, 1) == FAIL)
+ break;
+ if (e - 4 > s && STRNICMP(e - 4, ".vim", 4) == 0)
+ {
+ for (s = e - 4; s > all; --s)
+ if (*s == '\n' || vim_ispathsep(*s))
+ break;
+ ++s;
+ ((char_u **)ga.ga_data)[ga.ga_len] =
+ vim_strnsave(s, (int)(e - s - 4));
+ ++ga.ga_len;
+ --ga.ga_room;
+ }
+ if (*e != NUL)
+ ++e;
+ }
+ vim_free(all);
+ *file = ga.ga_data;
+ *num_file = ga.ga_len;
+ return OK;
+}
+
+#endif
+
+#if defined(FEAT_CMDL_COMPL) || defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Expand "file" for all comma-separated directories in "path".
+ * Returns an allocated string with all matches concatenated, separated by
+ * newlines. Returns NULL for an error or no matches.
+ */
+ char_u *
+globpath(path, file)
+ char_u *path;
+ char_u *file;
+{
+ expand_T xpc;
+ char_u *buf;
+ garray_T ga;
+ int i;
+ int len;
+ int num_p;
+ char_u **p;
+ char_u *cur = NULL;
+
+ buf = alloc(MAXPATHL);
+ if (buf == NULL)
+ return NULL;
+
+ xpc.xp_context = EXPAND_FILES;
+ xpc.xp_backslash = XP_BS_NONE;
+ ga_init2(&ga, 1, 100);
+
+ /* Loop over all entries in {path}. */
+ while (*path != NUL)
+ {
+ /* Copy one item of the path to buf[] and concatenate the file name. */
+ copy_option_part(&path, buf, MAXPATHL, ",");
+ if (STRLEN(buf) + STRLEN(file) + 2 < MAXPATHL)
+ {
+ add_pathsep(buf);
+ STRCAT(buf, file);
+ if (ExpandFromContext(&xpc, buf, &num_p, &p, WILD_SILENT) != FAIL
+ && num_p > 0)
+ {
+ ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT);
+ for (len = 0, i = 0; i < num_p; ++i)
+ len += (long_u)STRLEN(p[i]) + 1;
+
+ /* Concatenate new results to previous ones. */
+ if (ga_grow(&ga, len) == OK)
+ {
+ cur = (char_u *)ga.ga_data + ga.ga_len;
+ for (i = 0; i < num_p; ++i)
+ {
+ STRCPY(cur, p[i]);
+ cur += STRLEN(p[i]);
+ *cur++ = '\n';
+ }
+ ga.ga_len += len;
+ ga.ga_room -= len;
+ }
+ FreeWild(num_p, p);
+ }
+ }
+ }
+ if (cur != NULL)
+ *--cur = 0; /* Replace trailing newline with NUL */
+
+ vim_free(buf);
+ return (char_u *)ga.ga_data;
+}
+
+#endif
+
+#if defined(FEAT_CMDHIST) || defined(PROTO)
+
+/*********************************
+ * Command line history stuff *
+ *********************************/
+
+/*
+ * Translate a history character to the associated type number.
+ */
+ static int
+hist_char2type(c)
+ int c;
+{
+ if (c == ':')
+ return HIST_CMD;
+ if (c == '=')
+ return HIST_EXPR;
+ if (c == '@')
+ return HIST_INPUT;
+ if (c == '>')
+ return HIST_DEBUG;
+ return HIST_SEARCH; /* must be '?' or '/' */
+}
+
+/*
+ * Table of history names.
+ * These names are used in :history and various hist...() functions.
+ * It is sufficient to give the significant prefix of a history name.
+ */
+
+static char *(history_names[]) =
+{
+ "cmd",
+ "search",
+ "expr",
+ "input",
+ "debug",
+ NULL
+};
+
+/*
+ * init_history() - Initialize the command line history.
+ * Also used to re-allocate the history when the size changes.
+ */
+ static void
+init_history()
+{
+ int newlen; /* new length of history table */
+ histentry_T *temp;
+ int i;
+ int j;
+ int type;
+
+ /*
+ * If size of history table changed, reallocate it
+ */
+ newlen = (int)p_hi;
+ if (newlen != hislen) /* history length changed */
+ {
+ for (type = 0; type < HIST_COUNT; ++type) /* adjust the tables */
+ {
+ if (newlen)
+ {
+ temp = (histentry_T *)lalloc(
+ (long_u)(newlen * sizeof(histentry_T)), TRUE);
+ if (temp == NULL) /* out of memory! */
+ {
+ if (type == 0) /* first one: just keep the old length */
+ {
+ newlen = hislen;
+ break;
+ }
+ /* Already changed one table, now we can only have zero
+ * length for all tables. */
+ newlen = 0;
+ type = -1;
+ continue;
+ }
+ }
+ else
+ temp = NULL;
+ if (newlen == 0 || temp != NULL)
+ {
+ if (hisidx[type] < 0) /* there are no entries yet */
+ {
+ for (i = 0; i < newlen; ++i)
+ {
+ temp[i].hisnum = 0;
+ temp[i].hisstr = NULL;
+ }
+ }
+ else if (newlen > hislen) /* array becomes bigger */
+ {
+ for (i = 0; i <= hisidx[type]; ++i)
+ temp[i] = history[type][i];
+ j = i;
+ for ( ; i <= newlen - (hislen - hisidx[type]); ++i)
+ {
+ temp[i].hisnum = 0;
+ temp[i].hisstr = NULL;
+ }
+ for ( ; j < hislen; ++i, ++j)
+ temp[i] = history[type][j];
+ }
+ else /* array becomes smaller or 0 */
+ {
+ j = hisidx[type];
+ for (i = newlen - 1; ; --i)
+ {
+ if (i >= 0) /* copy newest entries */
+ temp[i] = history[type][j];
+ else /* remove older entries */
+ vim_free(history[type][j].hisstr);
+ if (--j < 0)
+ j = hislen - 1;
+ if (j == hisidx[type])
+ break;
+ }
+ hisidx[type] = newlen - 1;
+ }
+ vim_free(history[type]);
+ history[type] = temp;
+ }
+ }
+ hislen = newlen;
+ }
+}
+
+/*
+ * Check if command line 'str' is already in history.
+ * If 'move_to_front' is TRUE, matching entry is moved to end of history.
+ */
+ static int
+in_history(type, str, move_to_front)
+ int type;
+ char_u *str;
+ int move_to_front; /* Move the entry to the front if it exists */
+{
+ int i;
+ int last_i = -1;
+
+ if (hisidx[type] < 0)
+ return FALSE;
+ i = hisidx[type];
+ do
+ {
+ if (history[type][i].hisstr == NULL)
+ return FALSE;
+ if (STRCMP(str, history[type][i].hisstr) == 0)
+ {
+ if (!move_to_front)
+ return TRUE;
+ last_i = i;
+ break;
+ }
+ if (--i < 0)
+ i = hislen - 1;
+ } while (i != hisidx[type]);
+
+ if (last_i >= 0)
+ {
+ str = history[type][i].hisstr;
+ while (i != hisidx[type])
+ {
+ if (++i >= hislen)
+ i = 0;
+ history[type][last_i] = history[type][i];
+ last_i = i;
+ }
+ history[type][i].hisstr = str;
+ history[type][i].hisnum = ++hisnum[type];
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Convert history name (from table above) to its HIST_ equivalent.
+ * When "name" is empty, return "cmd" history.
+ * Returns -1 for unknown history name.
+ */
+ int
+get_histtype(name)
+ char_u *name;
+{
+ int i;
+ int len = (int)STRLEN(name);
+
+ /* No argument: use current history. */
+ if (len == 0)
+ return hist_char2type(ccline.cmdfirstc);
+
+ for (i = 0; history_names[i] != NULL; ++i)
+ if (STRNICMP(name, history_names[i], len) == 0)
+ return i;
+
+ if (vim_strchr((char_u *)":=@>?/", name[0]) != NULL && name[1] == NUL)
+ return hist_char2type(name[0]);
+
+ return -1;
+}
+
+static int last_maptick = -1; /* last seen maptick */
+
+/*
+ * Add the given string to the given history. If the string is already in the
+ * history then it is moved to the front. "histype" may be one of he HIST_
+ * values.
+ */
+ void
+add_to_history(histype, new_entry, in_map, sep)
+ int histype;
+ char_u *new_entry;
+ int in_map; /* consider maptick when inside a mapping */
+ int sep; /* separator character used (search hist) */
+{
+ histentry_T *hisptr;
+ int len;
+
+ if (hislen == 0) /* no history */
+ return;
+
+ /*
+ * Searches inside the same mapping overwrite each other, so that only
+ * the last line is kept. Be careful not to remove a line that was moved
+ * down, only lines that were added.
+ */
+ if (histype == HIST_SEARCH && in_map)
+ {
+ if (maptick == last_maptick)
+ {
+ /* Current line is from the same mapping, remove it */
+ hisptr = &history[HIST_SEARCH][hisidx[HIST_SEARCH]];
+ vim_free(hisptr->hisstr);
+ hisptr->hisstr = NULL;
+ hisptr->hisnum = 0;
+ --hisnum[histype];
+ if (--hisidx[HIST_SEARCH] < 0)
+ hisidx[HIST_SEARCH] = hislen - 1;
+ }
+ last_maptick = -1;
+ }
+ if (!in_history(histype, new_entry, TRUE))
+ {
+ if (++hisidx[histype] == hislen)
+ hisidx[histype] = 0;
+ hisptr = &history[histype][hisidx[histype]];
+ vim_free(hisptr->hisstr);
+
+ /* Store the separator after the NUL of the string. */
+ len = STRLEN(new_entry);
+ hisptr->hisstr = vim_strnsave(new_entry, len + 2);
+ if (hisptr->hisstr != NULL)
+ hisptr->hisstr[len + 1] = sep;
+
+ hisptr->hisnum = ++hisnum[histype];
+ if (histype == HIST_SEARCH && in_map)
+ last_maptick = maptick;
+ }
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+
+/*
+ * Get identifier of newest history entry.
+ * "histype" may be one of the HIST_ values.
+ */
+ int
+get_history_idx(histype)
+ int histype;
+{
+ if (hislen == 0 || histype < 0 || histype >= HIST_COUNT
+ || hisidx[histype] < 0)
+ return -1;
+
+ return history[histype][hisidx[histype]].hisnum;
+}
+
+/*
+ * Get the current command line in allocated memory.
+ * Only works when the command line is being edited.
+ * Returns NULL when something is wrong.
+ */
+ char_u *
+get_cmdline_str()
+{
+ if (ccline.cmdbuff == NULL || (State & CMDLINE) == 0)
+ return NULL;
+ return vim_strnsave(ccline.cmdbuff, ccline.cmdlen);
+}
+
+/*
+ * Get the current command line position, counted in bytes.
+ * Zero is the first position.
+ * Only works when the command line is being edited.
+ * Returns -1 when something is wrong.
+ */
+ int
+get_cmdline_pos()
+{
+ if (ccline.cmdbuff == NULL || (State & CMDLINE) == 0)
+ return -1;
+ return ccline.cmdpos;
+}
+
+/*
+ * Set the command line byte position to "pos". Zero is the first position.
+ * Only works when the command line is being edited.
+ * Returns 1 when failed, 0 when OK.
+ */
+ int
+set_cmdline_pos(pos)
+ int pos;
+{
+ if (ccline.cmdbuff == NULL || (State & CMDLINE) == 0)
+ return 1;
+
+ /* The position is not set directly but after CTRL-\ e or CTRL-R = has
+ * changed the command line. */
+ if (pos < 0)
+ new_cmdpos = 0;
+ else
+ new_cmdpos = pos;
+ return 0;
+}
+
+/*
+ * Calculate history index from a number:
+ * num > 0: seen as identifying number of a history entry
+ * num < 0: relative position in history wrt newest entry
+ * "histype" may be one of the HIST_ values.
+ */
+ static int
+calc_hist_idx(histype, num)
+ int histype;
+ int num;
+{
+ int i;
+ histentry_T *hist;
+ int wrapped = FALSE;
+
+ if (hislen == 0 || histype < 0 || histype >= HIST_COUNT
+ || (i = hisidx[histype]) < 0 || num == 0)
+ return -1;
+
+ hist = history[histype];
+ if (num > 0)
+ {
+ while (hist[i].hisnum > num)
+ if (--i < 0)
+ {
+ if (wrapped)
+ break;
+ i += hislen;
+ wrapped = TRUE;
+ }
+ if (hist[i].hisnum == num && hist[i].hisstr != NULL)
+ return i;
+ }
+ else if (-num <= hislen)
+ {
+ i += num + 1;
+ if (i < 0)
+ i += hislen;
+ if (hist[i].hisstr != NULL)
+ return i;
+ }
+ return -1;
+}
+
+/*
+ * Get a history entry by its index.
+ * "histype" may be one of the HIST_ values.
+ */
+ char_u *
+get_history_entry(histype, idx)
+ int histype;
+ int idx;
+{
+ idx = calc_hist_idx(histype, idx);
+ if (idx >= 0)
+ return history[histype][idx].hisstr;
+ else
+ return (char_u *)"";
+}
+
+/*
+ * Clear all entries of a history.
+ * "histype" may be one of the HIST_ values.
+ */
+ int
+clr_history(histype)
+ int histype;
+{
+ int i;
+ histentry_T *hisptr;
+
+ if (hislen != 0 && histype >= 0 && histype < HIST_COUNT)
+ {
+ hisptr = history[histype];
+ for (i = hislen; i--;)
+ {
+ vim_free(hisptr->hisstr);
+ hisptr->hisnum = 0;
+ hisptr++->hisstr = NULL;
+ }
+ hisidx[histype] = -1; /* mark history as cleared */
+ hisnum[histype] = 0; /* reset identifier counter */
+ return OK;
+ }
+ return FAIL;
+}
+
+/*
+ * Remove all entries matching {str} from a history.
+ * "histype" may be one of the HIST_ values.
+ */
+ int
+del_history_entry(histype, str)
+ int histype;
+ char_u *str;
+{
+ regmatch_T regmatch;
+ histentry_T *hisptr;
+ int idx;
+ int i;
+ int last;
+ int found = FALSE;
+
+ regmatch.regprog = NULL;
+ regmatch.rm_ic = FALSE; /* always match case */
+ if (hislen != 0
+ && histype >= 0
+ && histype < HIST_COUNT
+ && *str != NUL
+ && (idx = hisidx[histype]) >= 0
+ && (regmatch.regprog = vim_regcomp(str, RE_MAGIC + RE_STRING))
+ != NULL)
+ {
+ i = last = idx;
+ do
+ {
+ hisptr = &history[histype][i];
+ if (hisptr->hisstr == NULL)
+ break;
+ if (vim_regexec(&regmatch, hisptr->hisstr, (colnr_T)0))
+ {
+ found = TRUE;
+ vim_free(hisptr->hisstr);
+ hisptr->hisstr = NULL;
+ hisptr->hisnum = 0;
+ }
+ else
+ {
+ if (i != last)
+ {
+ history[histype][last] = *hisptr;
+ hisptr->hisstr = NULL;
+ hisptr->hisnum = 0;
+ }
+ if (--last < 0)
+ last += hislen;
+ }
+ if (--i < 0)
+ i += hislen;
+ } while (i != idx);
+ if (history[histype][idx].hisstr == NULL)
+ hisidx[histype] = -1;
+ }
+ vim_free(regmatch.regprog);
+ return found;
+}
+
+/*
+ * Remove an indexed entry from a history.
+ * "histype" may be one of the HIST_ values.
+ */
+ int
+del_history_idx(histype, idx)
+ int histype;
+ int idx;
+{
+ int i, j;
+
+ i = calc_hist_idx(histype, idx);
+ if (i < 0)
+ return FALSE;
+ idx = hisidx[histype];
+ vim_free(history[histype][i].hisstr);
+
+ /* When deleting the last added search string in a mapping, reset
+ * last_maptick, so that the last added search string isn't deleted again.
+ */
+ if (histype == HIST_SEARCH && maptick == last_maptick && i == idx)
+ last_maptick = -1;
+
+ while (i != idx)
+ {
+ j = (i + 1) % hislen;
+ history[histype][i] = history[histype][j];
+ i = j;
+ }
+ history[histype][i].hisstr = NULL;
+ history[histype][i].hisnum = 0;
+ if (--i < 0)
+ i += hislen;
+ hisidx[histype] = i;
+ return TRUE;
+}
+
+#endif /* FEAT_EVAL */
+
+#if defined(FEAT_CRYPT) || defined(PROTO)
+/*
+ * Very specific function to remove the value in ":set key=val" from the
+ * history.
+ */
+ void
+remove_key_from_history()
+{
+ char_u *p;
+ int i;
+
+ i = hisidx[HIST_CMD];
+ if (i < 0)
+ return;
+ p = history[HIST_CMD][i].hisstr;
+ if (p != NULL)
+ for ( ; *p; ++p)
+ if (STRNCMP(p, "key", 3) == 0 && !isalpha(p[3]))
+ {
+ p = vim_strchr(p + 3, '=');
+ if (p == NULL)
+ break;
+ ++p;
+ for (i = 0; p[i] && !vim_iswhite(p[i]); ++i)
+ if (p[i] == '\\' && p[i + 1])
+ ++i;
+ mch_memmove(p, p + i, STRLEN(p + i) + 1);
+ --p;
+ }
+}
+#endif
+
+#endif /* FEAT_CMDHIST */
+
+#if defined(FEAT_QUICKFIX) || defined(FEAT_CMDHIST) || defined(PROTO)
+/*
+ * Get indices "num1,num2" that specify a range within a list (not a range of
+ * text lines in a buffer!) from a string. Used for ":history" and ":clist".
+ * Returns OK if parsed successfully, otherwise FAIL.
+ */
+ int
+get_list_range(str, num1, num2)
+ char_u **str;
+ int *num1;
+ int *num2;
+{
+ int len;
+ int first = FALSE;
+ long num;
+
+ *str = skipwhite(*str);
+ if (**str == '-' || vim_isdigit(**str)) /* parse "from" part of range */
+ {
+ vim_str2nr(*str, NULL, &len, FALSE, FALSE, &num, NULL);
+ *str += len;
+ *num1 = (int)num;
+ first = TRUE;
+ }
+ *str = skipwhite(*str);
+ if (**str == ',') /* parse "to" part of range */
+ {
+ *str = skipwhite(*str + 1);
+ vim_str2nr(*str, NULL, &len, FALSE, FALSE, &num, NULL);
+ if (len > 0)
+ {
+ *num2 = (int)num;
+ *str = skipwhite(*str + len);
+ }
+ else if (!first) /* no number given at all */
+ return FAIL;
+ }
+ else if (first) /* only one number given */
+ *num2 = *num1;
+ return OK;
+}
+#endif
+
+#if defined(FEAT_CMDHIST) || defined(PROTO)
+/*
+ * :history command - print a history
+ */
+ void
+ex_history(eap)
+ exarg_T *eap;
+{
+ histentry_T *hist;
+ int histype1 = HIST_CMD;
+ int histype2 = HIST_CMD;
+ int hisidx1 = 1;
+ int hisidx2 = -1;
+ int idx;
+ int i, j, k;
+ char_u *end;
+ char_u *arg = eap->arg;
+
+ if (hislen == 0)
+ {
+ MSG(_("'history' option is zero"));
+ return;
+ }
+
+ if (!(VIM_ISDIGIT(*arg) || *arg == '-' || *arg == ','))
+ {
+ end = arg;
+ while (ASCII_ISALPHA(*end)
+ || vim_strchr((char_u *)":=@>/?", *end) != NULL)
+ end++;
+ i = *end;
+ *end = NUL;
+ histype1 = get_histtype(arg);
+ if (histype1 == -1)
+ {
+ if (STRICMP(arg, "all") == 0)
+ {
+ histype1 = 0;
+ histype2 = HIST_COUNT-1;
+ }
+ else
+ {
+ *end = i;
+ EMSG(_(e_trailing));
+ return;
+ }
+ }
+ else
+ histype2 = histype1;
+ *end = i;
+ }
+ else
+ end = arg;
+ if (!get_list_range(&end, &hisidx1, &hisidx2) || *end != NUL)
+ {
+ EMSG(_(e_trailing));
+ return;
+ }
+
+ for (; !got_int && histype1 <= histype2; ++histype1)
+ {
+ STRCPY(IObuff, "\n # ");
+ STRCAT(STRCAT(IObuff, history_names[histype1]), " history");
+ MSG_PUTS_TITLE(IObuff);
+ idx = hisidx[histype1];
+ hist = history[histype1];
+ j = hisidx1;
+ k = hisidx2;
+ if (j < 0)
+ j = (-j > hislen) ? 0 : hist[(hislen+j+idx+1) % hislen].hisnum;
+ if (k < 0)
+ k = (-k > hislen) ? 0 : hist[(hislen+k+idx+1) % hislen].hisnum;
+ if (idx >= 0 && j <= k)
+ for (i = idx + 1; !got_int; ++i)
+ {
+ if (i == hislen)
+ i = 0;
+ if (hist[i].hisstr != NULL
+ && hist[i].hisnum >= j && hist[i].hisnum <= k)
+ {
+ msg_putchar('\n');
+ sprintf((char *)IObuff, "%c%6d ", i == idx ? '>' : ' ',
+ hist[i].hisnum);
+ if (vim_strsize(hist[i].hisstr) > (int)Columns - 10)
+ trunc_string(hist[i].hisstr, IObuff + STRLEN(IObuff),
+ (int)Columns - 10);
+ else
+ STRCAT(IObuff, hist[i].hisstr);
+ msg_outtrans(IObuff);
+ out_flush();
+ }
+ if (i == idx)
+ break;
+ }
+ }
+}
+#endif
+
+#if (defined(FEAT_VIMINFO) && defined(FEAT_CMDHIST)) || defined(PROTO)
+static char_u **viminfo_history[HIST_COUNT] = {NULL, NULL, NULL, NULL};
+static int viminfo_hisidx[HIST_COUNT] = {0, 0, 0, 0};
+static int viminfo_hislen[HIST_COUNT] = {0, 0, 0, 0};
+static int viminfo_add_at_front = FALSE;
+
+static int hist_type2char __ARGS((int type, int use_question));
+
+/*
+ * Translate a history type number to the associated character.
+ */
+ static int
+hist_type2char(type, use_question)
+ int type;
+ int use_question; /* use '?' instead of '/' */
+{
+ if (type == HIST_CMD)
+ return ':';
+ if (type == HIST_SEARCH)
+ {
+ if (use_question)
+ return '?';
+ else
+ return '/';
+ }
+ if (type == HIST_EXPR)
+ return '=';
+ return '@';
+}
+
+/*
+ * Prepare for reading the history from the viminfo file.
+ * This allocates history arrays to store the read history lines.
+ */
+ void
+prepare_viminfo_history(asklen)
+ int asklen;
+{
+ int i;
+ int num;
+ int type;
+ int len;
+
+ init_history();
+ viminfo_add_at_front = (asklen != 0);
+ if (asklen > hislen)
+ asklen = hislen;
+
+ for (type = 0; type < HIST_COUNT; ++type)
+ {
+ /*
+ * Count the number of empty spaces in the history list. If there are
+ * more spaces available than we request, then fill them up.
+ */
+ for (i = 0, num = 0; i < hislen; i++)
+ if (history[type][i].hisstr == NULL)
+ num++;
+ len = asklen;
+ if (num > len)
+ len = num;
+ if (len <= 0)
+ viminfo_history[type] = NULL;
+ else
+ viminfo_history[type] =
+ (char_u **)lalloc((long_u)(len * sizeof(char_u *)), FALSE);
+ if (viminfo_history[type] == NULL)
+ len = 0;
+ viminfo_hislen[type] = len;
+ viminfo_hisidx[type] = 0;
+ }
+}
+
+/*
+ * Accept a line from the viminfo, store it in the history array when it's
+ * new.
+ */
+ int
+read_viminfo_history(virp)
+ vir_T *virp;
+{
+ int type;
+ long_u len;
+ char_u *val;
+ char_u *p;
+
+ type = hist_char2type(virp->vir_line[0]);
+ if (viminfo_hisidx[type] < viminfo_hislen[type])
+ {
+ val = viminfo_readstring(virp, 1, TRUE);
+ if (val != NULL && *val != NUL)
+ {
+ if (!in_history(type, val + (type == HIST_SEARCH),
+ viminfo_add_at_front))
+ {
+ /* Need to re-allocate to append the separator byte. */
+ len = STRLEN(val);
+ p = lalloc(len + 2, TRUE);
+ if (p != NULL)
+ {
+ if (type == HIST_SEARCH)
+ {
+ /* Search entry: Move the separator from the first
+ * column to after the NUL. */
+ mch_memmove(p, val + 1, (size_t)len);
+ p[len] = (*val == ' ' ? NUL : *val);
+ }
+ else
+ {
+ /* Not a search entry: No separator in the viminfo
+ * file, add a NUL separator. */
+ mch_memmove(p, val, (size_t)len + 1);
+ p[len + 1] = NUL;
+ }
+ viminfo_history[type][viminfo_hisidx[type]++] = p;
+ }
+ }
+ }
+ vim_free(val);
+ }
+ return viminfo_readline(virp);
+}
+
+ void
+finish_viminfo_history()
+{
+ int idx;
+ int i;
+ int type;
+
+ for (type = 0; type < HIST_COUNT; ++type)
+ {
+ if (history[type] == NULL)
+ return;
+ idx = hisidx[type] + viminfo_hisidx[type];
+ if (idx >= hislen)
+ idx -= hislen;
+ else if (idx < 0)
+ idx = hislen - 1;
+ if (viminfo_add_at_front)
+ hisidx[type] = idx;
+ else
+ {
+ if (hisidx[type] == -1)
+ hisidx[type] = hislen - 1;
+ do
+ {
+ if (history[type][idx].hisstr != NULL)
+ break;
+ if (++idx == hislen)
+ idx = 0;
+ } while (idx != hisidx[type]);
+ if (idx != hisidx[type] && --idx < 0)
+ idx = hislen - 1;
+ }
+ for (i = 0; i < viminfo_hisidx[type]; i++)
+ {
+ vim_free(history[type][idx].hisstr);
+ history[type][idx].hisstr = viminfo_history[type][i];
+ if (--idx < 0)
+ idx = hislen - 1;
+ }
+ idx += 1;
+ idx %= hislen;
+ for (i = 0; i < viminfo_hisidx[type]; i++)
+ {
+ history[type][idx++].hisnum = ++hisnum[type];
+ idx %= hislen;
+ }
+ vim_free(viminfo_history[type]);
+ viminfo_history[type] = NULL;
+ }
+}
+
+ void
+write_viminfo_history(fp)
+ FILE *fp;
+{
+ int i;
+ int type;
+ int num_saved;
+ char_u *p;
+ int c;
+
+ init_history();
+ if (hislen == 0)
+ return;
+ for (type = 0; type < HIST_COUNT; ++type)
+ {
+ num_saved = get_viminfo_parameter(hist_type2char(type, FALSE));
+ if (num_saved == 0)
+ continue;
+ if (num_saved < 0) /* Use default */
+ num_saved = hislen;
+ fprintf(fp, _("\n# %s History (newest to oldest):\n"),
+ type == HIST_CMD ? _("Command Line") :
+ type == HIST_SEARCH ? _("Search String") :
+ type == HIST_EXPR ? _("Expression") :
+ _("Input Line"));
+ if (num_saved > hislen)
+ num_saved = hislen;
+ i = hisidx[type];
+ if (i >= 0)
+ while (num_saved--)
+ {
+ p = history[type][i].hisstr;
+ if (p != NULL)
+ {
+ putc(hist_type2char(type, TRUE), fp);
+ /* For the search history: put the separator in the second
+ * column; use a space if there isn't one. */
+ if (type == HIST_SEARCH)
+ {
+ c = p[STRLEN(p) + 1];
+ putc(c == NUL ? ' ' : c, fp);
+ }
+ viminfo_writestring(fp, p);
+ }
+ if (--i < 0)
+ i = hislen - 1;
+ }
+ }
+}
+#endif /* FEAT_VIMINFO */
+
+#if defined(FEAT_FKMAP) || defined(PROTO)
+/*
+ * Write a character at the current cursor+offset position.
+ * It is directly written into the command buffer block.
+ */
+ void
+cmd_pchar(c, offset)
+ int c, offset;
+{
+ if (ccline.cmdpos + offset >= ccline.cmdlen || ccline.cmdpos + offset < 0)
+ {
+ EMSG(_("E198: cmd_pchar beyond the command length"));
+ return;
+ }
+ ccline.cmdbuff[ccline.cmdpos + offset] = (char_u)c;
+ ccline.cmdbuff[ccline.cmdlen] = NUL;
+}
+
+ int
+cmd_gchar(offset)
+ int offset;
+{
+ if (ccline.cmdpos + offset >= ccline.cmdlen || ccline.cmdpos + offset < 0)
+ {
+ /* EMSG(_("cmd_gchar beyond the command length")); */
+ return NUL;
+ }
+ return (int)ccline.cmdbuff[ccline.cmdpos + offset];
+}
+#endif
+
+#if defined(FEAT_CMDWIN) || defined(PROTO)
+/*
+ * Open a window on the current command line and history. Allow editing in
+ * the window. Returns when the window is closed.
+ * Returns:
+ * CR if the command is to be executed
+ * Ctrl_C if it is to be abandoned
+ * K_IGNORE if editing continues
+ */
+ static int
+ex_window()
+{
+ struct cmdline_info save_ccline;
+ buf_T *old_curbuf = curbuf;
+ win_T *old_curwin = curwin;
+ buf_T *bp;
+ win_T *wp;
+ int i;
+ linenr_T lnum;
+ int histtype;
+ garray_T winsizes;
+ char_u typestr[2];
+ int save_restart_edit = restart_edit;
+ int save_State = State;
+ int save_exmode = exmode_active;
+
+ /* Can't do this recursively. Can't do it when typing a password. */
+ if (cmdwin_type != 0
+# if defined(FEAT_CRYPT) || defined(FEAT_EVAL)
+ || cmdline_star > 0
+# endif
+ )
+ {
+ beep_flush();
+ return K_IGNORE;
+ }
+
+ /* Save current window sizes. */
+ win_size_save(&winsizes);
+
+# ifdef FEAT_AUTOCMD
+ /* Don't execute autocommands while creating the window. */
+ ++autocmd_block;
+# endif
+ /* Create a window for the command-line buffer. */
+ if (win_split((int)p_cwh, WSP_BOT) == FAIL)
+ {
+ beep_flush();
+ return K_IGNORE;
+ }
+ cmdwin_type = ccline.cmdfirstc;
+ if (cmdwin_type == NUL)
+ cmdwin_type = '-';
+
+ /* Create the command-line buffer empty. */
+ (void)do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE);
+ (void)setfname(curbuf, (char_u *)"command-line", NULL, TRUE);
+ set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL);
+ set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
+ curbuf->b_p_ma = TRUE;
+# ifdef FEAT_RIGHTLEFT
+ curwin->w_p_rl = FALSE;
+# endif
+# ifdef FEAT_SCROLLBIND
+ curwin->w_p_scb = FALSE;
+# endif
+
+# ifdef FEAT_AUTOCMD
+ /* Do execute autocommands for setting the filetype (load syntax). */
+ --autocmd_block;
+# endif
+
+ histtype = hist_char2type(ccline.cmdfirstc);
+ if (histtype == HIST_CMD || histtype == HIST_DEBUG)
+ {
+ if (p_wc == TAB)
+ {
+ add_map((char_u *)"<buffer> <Tab> <C-X><C-V>", INSERT);
+ add_map((char_u *)"<buffer> <Tab> a<C-X><C-V>", NORMAL);
+ }
+ set_option_value((char_u *)"ft", 0L, (char_u *)"vim", OPT_LOCAL);
+ }
+
+ /* Fill the buffer with the history. */
+ init_history();
+ if (hislen > 0)
+ {
+ i = hisidx[histtype];
+ if (i >= 0)
+ {
+ lnum = 0;
+ do
+ {
+ if (++i == hislen)
+ i = 0;
+ if (history[histtype][i].hisstr != NULL)
+ ml_append(lnum++, history[histtype][i].hisstr,
+ (colnr_T)0, FALSE);
+ }
+ while (i != hisidx[histtype]);
+ }
+ }
+
+ /* Replace the empty last line with the current command-line and put the
+ * cursor there. */
+ ml_replace(curbuf->b_ml.ml_line_count, ccline.cmdbuff, TRUE);
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ curwin->w_cursor.col = ccline.cmdpos;
+ redraw_later(NOT_VALID);
+
+ /* Save the command line info, can be used recursively. */
+ save_ccline = ccline;
+ ccline.cmdbuff = NULL;
+ ccline.cmdprompt = NULL;
+
+ /* No Ex mode here! */
+ exmode_active = 0;
+
+ State = NORMAL;
+# ifdef FEAT_MOUSE
+ setmouse();
+# endif
+
+# ifdef FEAT_AUTOCMD
+ /* Trigger CmdwinEnter autocommands. */
+ typestr[0] = cmdwin_type;
+ typestr[1] = NUL;
+ apply_autocmds(EVENT_CMDWINENTER, typestr, typestr, FALSE, curbuf);
+# endif
+
+ i = RedrawingDisabled;
+ RedrawingDisabled = 0;
+
+ /*
+ * Call the main loop until <CR> or CTRL-C is typed.
+ */
+ cmdwin_result = 0;
+ main_loop(TRUE);
+
+ RedrawingDisabled = i;
+
+# ifdef FEAT_AUTOCMD
+ /* Trigger CmdwinLeave autocommands. */
+ apply_autocmds(EVENT_CMDWINLEAVE, typestr, typestr, FALSE, curbuf);
+# endif
+
+ /* Restore the comand line info. */
+ ccline = save_ccline;
+ cmdwin_type = 0;
+
+ exmode_active = save_exmode;
+
+ /* Safety check: The old window or buffer was deleted: It's a a bug when
+ * this happens! */
+ if (!win_valid(old_curwin) || !buf_valid(old_curbuf))
+ {
+ cmdwin_result = Ctrl_C;
+ EMSG(_("E199: Active window or buffer deleted"));
+ }
+ else
+ {
+# if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+ /* autocmds may abort script processing */
+ if (aborting() && cmdwin_result != K_IGNORE)
+ cmdwin_result = Ctrl_C;
+# endif
+ /* Set the new command line from the cmdline buffer. */
+ vim_free(ccline.cmdbuff);
+ if (cmdwin_result == K_XF1) /* :qa! typed */
+ {
+ ccline.cmdbuff = vim_strsave((char_u *)"qa!");
+ cmdwin_result = CAR;
+ }
+ else if (cmdwin_result == K_XF2) /* :qa typed */
+ {
+ ccline.cmdbuff = vim_strsave((char_u *)"qa");
+ cmdwin_result = CAR;
+ }
+ else
+ ccline.cmdbuff = vim_strsave(ml_get_curline());
+ if (ccline.cmdbuff == NULL)
+ cmdwin_result = Ctrl_C;
+ else
+ {
+ ccline.cmdlen = (int)STRLEN(ccline.cmdbuff);
+ ccline.cmdbufflen = ccline.cmdlen + 1;
+ ccline.cmdpos = curwin->w_cursor.col;
+ if (ccline.cmdpos > ccline.cmdlen)
+ ccline.cmdpos = ccline.cmdlen;
+ if (cmdwin_result == K_IGNORE)
+ {
+ set_cmdspos_cursor();
+ redrawcmd();
+ }
+ }
+
+# ifdef FEAT_AUTOCMD
+ /* Don't execute autocommands while deleting the window. */
+ ++autocmd_block;
+# endif
+ wp = curwin;
+ bp = curbuf;
+ win_goto(old_curwin);
+ win_close(wp, TRUE);
+ close_buffer(NULL, bp, DOBUF_WIPE);
+
+ /* Restore window sizes. */
+ win_size_restore(&winsizes);
+
+# ifdef FEAT_AUTOCMD
+ --autocmd_block;
+# endif
+ }
+
+ ga_clear(&winsizes);
+ restart_edit = save_restart_edit;
+
+ State = save_State;
+# ifdef FEAT_MOUSE
+ setmouse();
+# endif
+
+ return cmdwin_result;
+}
+#endif /* FEAT_CMDWIN */
+
+/*
+ * Used for commands that either take a simple command string argument, or:
+ * cmd << endmarker
+ * {script}
+ * endmarker
+ * Returns a pointer to allocated memory with {script} or NULL.
+ */
+ char_u *
+script_get(eap, cmd)
+ exarg_T *eap;
+ char_u *cmd;
+{
+ char_u *theline;
+ char *end_pattern = NULL;
+ char dot[] = ".";
+ garray_T ga;
+
+ if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL)
+ return NULL;
+
+ ga_init2(&ga, 1, 0x400);
+
+ if (cmd[2] != NUL)
+ end_pattern = (char *)skipwhite(cmd + 2);
+ else
+ end_pattern = dot;
+
+ for (;;)
+ {
+ theline = eap->getline(
+#ifdef FEAT_EVAL
+ eap->cstack->cs_whilelevel > 0 ? -1 :
+#endif
+ NUL, eap->cookie, 0);
+
+ if (theline == NULL || STRCMP(end_pattern, theline) == 0)
+ break;
+
+ ga_concat(&ga, theline);
+ ga_append(&ga, '\n');
+ vim_free(theline);
+ }
+
+ return (char_u *)ga.ga_data;
+}
diff --git a/src/farsi.c b/src/farsi.c
new file mode 100644
index 000000000..f74447f76
--- /dev/null
+++ b/src/farsi.c
@@ -0,0 +1,2312 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * farsi.c: functions for Farsi language
+ *
+ * Included by main.c, when FEAT_FKMAP is defined.
+ */
+
+static int toF_Xor_X_ __ARGS((int c));
+static int F_is_TyE __ARGS((int c));
+static int F_is_TyC_TyD __ARGS((int c));
+static int F_is_TyB_TyC_TyD __ARGS((int src, int offset));
+static int toF_TyB __ARGS((int c));
+static void put_curr_and_l_to_X __ARGS((int c));
+static void put_and_redo __ARGS((int c));
+static void chg_c_toX_orX __ARGS((void));
+static void chg_c_to_X_orX_ __ARGS((void));
+static void chg_c_to_X_or_X __ARGS((void));
+static void chg_l_to_X_orX_ __ARGS((void));
+static void chg_l_toXor_X __ARGS((void));
+static void chg_r_to_Xor_X_ __ARGS((void));
+static int toF_leading __ARGS((int c));
+static int toF_Rjoin __ARGS((int c));
+static int canF_Ljoin __ARGS((int c));
+static int canF_Rjoin __ARGS((int c));
+static int F_isterm __ARGS((int c));
+static int toF_ending __ARGS((int c));
+static void lrswapbuf __ARGS((char_u *buf, int len));
+
+/*
+** Convert the given Farsi character into a _X or _X_ type
+*/
+ static int
+toF_Xor_X_(c)
+ int c;
+{
+ int tempc;
+
+ switch (c)
+ {
+ case BE:
+ return _BE;
+ case PE:
+ return _PE;
+ case TE:
+ return _TE;
+ case SE:
+ return _SE;
+ case JIM:
+ return _JIM;
+ case CHE:
+ return _CHE;
+ case HE_J:
+ return _HE_J;
+ case XE:
+ return _XE;
+ case SIN:
+ return _SIN;
+ case SHIN:
+ return _SHIN;
+ case SAD:
+ return _SAD;
+ case ZAD:
+ return _ZAD;
+ case AYN:
+ return _AYN;
+ case AYN_:
+ return _AYN_;
+ case GHAYN:
+ return _GHAYN;
+ case GHAYN_:
+ return _GHAYN_;
+ case FE:
+ return _FE;
+ case GHAF:
+ return _GHAF;
+ case KAF:
+ return _KAF;
+ case GAF:
+ return _GAF;
+ case LAM:
+ return _LAM;
+ case MIM:
+ return _MIM;
+ case NOON:
+ return _NOON;
+ case YE:
+ case YE_:
+ return _YE;
+ case YEE:
+ case YEE_:
+ return _YEE;
+ case IE:
+ case IE_:
+ return _IE;
+ case F_HE:
+ tempc = _HE;
+
+ if (p_ri && (curwin->w_cursor.col+1 < STRLEN(ml_get_curline())))
+ {
+ inc_cursor();
+
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ tempc = _HE_;
+
+ dec_cursor();
+ }
+ if (!p_ri && STRLEN(ml_get_curline()))
+ {
+ dec_cursor();
+
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ tempc = _HE_;
+
+ inc_cursor();
+ }
+
+ return tempc;
+ }
+ return 0;
+}
+
+/*
+** Convert the given Farsi character into Farsi capital character .
+*/
+ int
+toF_TyA(c)
+ int c ;
+{
+ switch (c)
+ {
+ case ALEF_:
+ return ALEF;
+ case ALEF_U_H_:
+ return ALEF_U_H;
+ case _BE:
+ return BE;
+ case _PE:
+ return PE;
+ case _TE:
+ return TE;
+ case _SE:
+ return SE;
+ case _JIM:
+ return JIM;
+ case _CHE:
+ return CHE;
+ case _HE_J:
+ return HE_J;
+ case _XE:
+ return XE;
+ case _SIN:
+ return SIN;
+ case _SHIN:
+ return SHIN;
+ case _SAD:
+ return SAD;
+ case _ZAD:
+ return ZAD;
+ case _AYN:
+ case AYN_:
+ case _AYN_:
+ return AYN;
+ case _GHAYN:
+ case GHAYN_:
+ case _GHAYN_:
+ return GHAYN;
+ case _FE:
+ return FE;
+ case _GHAF:
+ return GHAF;
+/* I am not sure what it is !!! case _KAF_H: */
+ case _KAF:
+ return KAF;
+ case _GAF:
+ return GAF;
+ case _LAM:
+ return LAM;
+ case _MIM:
+ return MIM;
+ case _NOON:
+ return NOON;
+ case _YE:
+ case YE_:
+ return YE;
+ case _YEE:
+ case YEE_:
+ return YEE;
+ case TEE_:
+ return TEE;
+ case _IE:
+ case IE_:
+ return IE;
+ case _HE:
+ case _HE_:
+ return F_HE;
+ }
+ return c;
+}
+
+/*
+** Is the character under the cursor+offset in the given buffer a join type.
+** That is a character that is combined with the others.
+** Note: the offset is used only for command line buffer.
+*/
+ static int
+F_is_TyB_TyC_TyD(src, offset)
+ int src, offset;
+{
+ int c;
+
+ if (src == SRC_EDT)
+ c = gchar_cursor();
+ else
+ c = cmd_gchar(AT_CURSOR+offset);
+
+ switch (c)
+ {
+ case _LAM:
+ case _BE:
+ case _PE:
+ case _TE:
+ case _SE:
+ case _JIM:
+ case _CHE:
+ case _HE_J:
+ case _XE:
+ case _SIN:
+ case _SHIN:
+ case _SAD:
+ case _ZAD:
+ case _TA:
+ case _ZA:
+ case _AYN:
+ case _AYN_:
+ case _GHAYN:
+ case _GHAYN_:
+ case _FE:
+ case _GHAF:
+ case _KAF:
+ case _KAF_H:
+ case _GAF:
+ case _MIM:
+ case _NOON:
+ case _YE:
+ case _YEE:
+ case _IE:
+ case _HE_:
+ case _HE:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+** Is the Farsi character one of the terminating only type.
+*/
+ static int
+F_is_TyE(c)
+ int c;
+{
+ switch (c)
+ {
+ case ALEF_A:
+ case ALEF_D_H:
+ case DAL:
+ case ZAL:
+ case RE:
+ case ZE:
+ case JE:
+ case WAW:
+ case WAW_H:
+ case HAMZE:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+** Is the Farsi character one of the none leading type.
+*/
+ static int
+F_is_TyC_TyD(c)
+ int c;
+{
+ switch (c)
+ {
+ case ALEF_:
+ case ALEF_U_H_:
+ case _AYN_:
+ case AYN_:
+ case _GHAYN_:
+ case GHAYN_:
+ case _HE_:
+ case YE_:
+ case IE_:
+ case TEE_:
+ case YEE_:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+** Convert a none leading Farsi char into a leading type.
+*/
+ static int
+toF_TyB(c)
+ int c;
+{
+ switch (c)
+ {
+ case ALEF_: return ALEF;
+ case ALEF_U_H_: return ALEF_U_H;
+ case _AYN_: return _AYN;
+ case AYN_: return AYN; /* exception - there are many of them */
+ case _GHAYN_: return _GHAYN;
+ case GHAYN_: return GHAYN; /* exception - there are many of them */
+ case _HE_: return _HE;
+ case YE_: return YE;
+ case IE_: return IE;
+ case TEE_: return TEE;
+ case YEE_: return YEE;
+ }
+ return c;
+}
+
+/*
+** Overwrite the current redo and cursor characters + left adjust
+*/
+ static void
+put_curr_and_l_to_X(c)
+ int c;
+{
+ int tempc;
+
+ if (curwin->w_p_rl && p_ri)
+ return;
+
+ if ( (curwin->w_cursor.col < STRLEN(ml_get_curline())))
+ {
+ if ((p_ri && curwin->w_cursor.col) || !p_ri)
+ {
+ if (p_ri)
+ dec_cursor();
+ else
+ inc_cursor();
+
+ if (F_is_TyC_TyD((tempc = gchar_cursor())))
+ {
+ pchar_cursor(toF_TyB(tempc));
+ AppendCharToRedobuff(K_BS);
+ AppendCharToRedobuff(tempc);
+ }
+
+ if (p_ri)
+ inc_cursor();
+ else
+ dec_cursor();
+ }
+ }
+
+ put_and_redo(c);
+}
+
+ static void
+put_and_redo(c)
+ int c;
+{
+ pchar_cursor(c);
+ AppendCharToRedobuff(K_BS);
+ AppendCharToRedobuff(c);
+}
+
+/*
+** Change the char. under the cursor to a X_ or X type
+*/
+ static void
+chg_c_toX_orX()
+{
+ int tempc, curc;
+
+ switch ((curc = gchar_cursor()))
+ {
+ case _BE:
+ tempc = BE;
+ break;
+ case _PE:
+ tempc = PE;
+ break;
+ case _TE:
+ tempc = TE;
+ break;
+ case _SE:
+ tempc = SE;
+ break;
+ case _JIM:
+ tempc = JIM;
+ break;
+ case _CHE:
+ tempc = CHE;
+ break;
+ case _HE_J:
+ tempc = HE_J;
+ break;
+ case _XE:
+ tempc = XE;
+ break;
+ case _SIN:
+ tempc = SIN;
+ break;
+ case _SHIN:
+ tempc = SHIN;
+ break;
+ case _SAD:
+ tempc = SAD;
+ break;
+ case _ZAD:
+ tempc = ZAD;
+ break;
+ case _FE:
+ tempc = FE;
+ break;
+ case _GHAF:
+ tempc = GHAF;
+ break;
+ case _KAF_H:
+ case _KAF:
+ tempc = KAF;
+ break;
+ case _GAF:
+ tempc = GAF;
+ break;
+ case _AYN:
+ tempc = AYN;
+ break;
+ case _AYN_:
+ tempc = AYN_;
+ break;
+ case _GHAYN:
+ tempc = GHAYN;
+ break;
+ case _GHAYN_:
+ tempc = GHAYN_;
+ break;
+ case _LAM:
+ tempc = LAM;
+ break;
+ case _MIM:
+ tempc = MIM;
+ break;
+ case _NOON:
+ tempc = NOON;
+ break;
+ case _HE:
+ case _HE_:
+ tempc = F_HE;
+ break;
+ case _YE:
+ case _IE:
+ case _YEE:
+ if (p_ri)
+ {
+ inc_cursor();
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ tempc = (curc == _YE ? YE_ :
+ (curc == _IE ? IE_ : YEE_));
+ else
+ tempc = (curc == _YE ? YE :
+ (curc == _IE ? IE : YEE));
+ dec_cursor();
+ }
+ else
+ {
+ if (curwin->w_cursor.col)
+ {
+ dec_cursor();
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ tempc = (curc == _YE ? YE_ :
+ (curc == _IE ? IE_ : YEE_));
+ else
+ tempc = (curc == _YE ? YE :
+ (curc == _IE ? IE : YEE));
+ inc_cursor();
+ }
+ else
+ tempc = (curc == _YE ? YE :
+ (curc == _IE ? IE : YEE));
+ }
+ break;
+ default:
+ tempc = 0;
+ }
+
+ if (tempc)
+ put_and_redo(tempc);
+}
+
+/*
+** Change the char. under the cursor to a _X_ or X_ type
+*/
+
+ static void
+chg_c_to_X_orX_()
+{
+ int tempc;
+
+ switch (gchar_cursor())
+ {
+ case ALEF:
+ tempc = ALEF_;
+ break;
+ case ALEF_U_H:
+ tempc = ALEF_U_H_;
+ break;
+ case _AYN:
+ tempc = _AYN_;
+ break;
+ case AYN:
+ tempc = AYN_;
+ break;
+ case _GHAYN:
+ tempc = _GHAYN_;
+ break;
+ case GHAYN:
+ tempc = GHAYN_;
+ break;
+ case _HE:
+ tempc = _HE_;
+ break;
+ case YE:
+ tempc = YE_;
+ break;
+ case IE:
+ tempc = IE_;
+ break;
+ case TEE:
+ tempc = TEE_;
+ break;
+ case YEE:
+ tempc = YEE_;
+ break;
+ default:
+ tempc = 0;
+ }
+
+ if (tempc)
+ put_and_redo(tempc);
+}
+
+/*
+** Change the char. under the cursor to a _X_ or _X type
+*/
+ static void
+chg_c_to_X_or_X ()
+{
+ int tempc;
+
+ tempc = gchar_cursor();
+
+ if (curwin->w_cursor.col+1 < STRLEN(ml_get_curline()))
+ {
+ inc_cursor();
+
+ if ((tempc == F_HE) && (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)))
+ {
+ tempc = _HE_;
+
+ dec_cursor();
+
+ put_and_redo(tempc);
+ return;
+ }
+
+ dec_cursor();
+ }
+
+ if ((tempc = toF_Xor_X_(tempc)) != 0)
+ put_and_redo(tempc);
+}
+
+/*
+** Change the character left to the cursor to a _X_ or X_ type
+*/
+ static void
+chg_l_to_X_orX_ ()
+{
+ int tempc;
+
+ if (!curwin->w_cursor.col &&
+ (curwin->w_cursor.col+1 == STRLEN(ml_get_curline())))
+ return;
+
+ if (!curwin->w_cursor.col && p_ri)
+ return;
+
+ if (p_ri)
+ dec_cursor();
+ else
+ inc_cursor();
+
+ switch (gchar_cursor())
+ {
+ case ALEF:
+ tempc = ALEF_;
+ break;
+ case ALEF_U_H:
+ tempc = ALEF_U_H_;
+ break;
+ case _AYN:
+ tempc = _AYN_;
+ break;
+ case AYN:
+ tempc = AYN_;
+ break;
+ case _GHAYN:
+ tempc = _GHAYN_;
+ break;
+ case GHAYN:
+ tempc = GHAYN_;
+ break;
+ case _HE:
+ tempc = _HE_;
+ break;
+ case YE:
+ tempc = YE_;
+ break;
+ case IE:
+ tempc = IE_;
+ break;
+ case TEE:
+ tempc = TEE_;
+ break;
+ case YEE:
+ tempc = YEE_;
+ break;
+ default:
+ tempc = 0;
+ }
+
+ if (tempc)
+ put_and_redo(tempc);
+
+ if (p_ri)
+ inc_cursor();
+ else
+ dec_cursor();
+}
+
+/*
+** Change the charcter left to the cursor to a X or _X type
+*/
+
+ static void
+chg_l_toXor_X ()
+{
+ int tempc;
+
+ if (!curwin->w_cursor.col &&
+ (curwin->w_cursor.col+1 == STRLEN(ml_get_curline())))
+ return;
+
+ if (!curwin->w_cursor.col && p_ri)
+ return;
+
+ if (p_ri)
+ dec_cursor();
+ else
+ inc_cursor();
+
+ switch (gchar_cursor())
+ {
+ case ALEF_:
+ tempc = ALEF;
+ break;
+ case ALEF_U_H_:
+ tempc = ALEF_U_H;
+ break;
+ case _AYN_:
+ tempc = _AYN;
+ break;
+ case AYN_:
+ tempc = AYN;
+ break;
+ case _GHAYN_:
+ tempc = _GHAYN;
+ break;
+ case GHAYN_:
+ tempc = GHAYN;
+ break;
+ case _HE_:
+ tempc = _HE;
+ break;
+ case YE_:
+ tempc = YE;
+ break;
+ case IE_:
+ tempc = IE;
+ break;
+ case TEE_:
+ tempc = TEE;
+ break;
+ case YEE_:
+ tempc = YEE;
+ break;
+ default:
+ tempc = 0;
+ }
+
+ if (tempc)
+ put_and_redo(tempc);
+
+ if (p_ri)
+ inc_cursor();
+ else
+ dec_cursor();
+}
+
+/*
+** Change the charcter right to the cursor to a _X or _X_ type
+*/
+
+ static void
+chg_r_to_Xor_X_()
+{
+ int tempc, c;
+
+ if (curwin->w_cursor.col)
+ {
+ if (!p_ri)
+ dec_cursor();
+
+ tempc = gchar_cursor();
+
+ if ((c = toF_Xor_X_(tempc)) != 0)
+ put_and_redo(c);
+
+ if (!p_ri)
+ inc_cursor();
+
+ }
+}
+
+/*
+** Map Farsi keyboard when in fkmap mode.
+*/
+
+ int
+fkmap(c)
+ int c;
+{
+ int tempc;
+ static int revins;
+
+ if (IS_SPECIAL(c))
+ return c;
+
+ if (VIM_ISDIGIT(c) || ((c == '.' || c == '+' || c == '-' ||
+ c == '^' || c == '%' || c == '#' || c == '=') && revins))
+ {
+ if (!revins)
+ {
+ if (curwin->w_cursor.col)
+ {
+ if (!p_ri)
+ dec_cursor();
+
+ chg_c_toX_orX ();
+ chg_l_toXor_X ();
+
+ if (!p_ri)
+ inc_cursor();
+ }
+ }
+
+ arrow_used = TRUE;
+ (void)stop_arrow();
+
+ if (!curwin->w_p_rl && revins)
+ inc_cursor();
+
+ ++revins;
+ p_ri=1;
+ }
+ else
+ {
+ if (revins)
+ {
+ arrow_used = TRUE;
+ (void)stop_arrow();
+
+ revins = 0;
+ if (curwin->w_p_rl)
+ {
+ while ((F_isdigit(gchar_cursor())
+ || (gchar_cursor() == F_PERIOD
+ || gchar_cursor() == F_PLUS
+ || gchar_cursor() == F_MINUS
+ || gchar_cursor() == F_MUL
+ || gchar_cursor() == F_DIVIDE
+ || gchar_cursor() == F_PERCENT
+ || gchar_cursor() == F_EQUALS))
+ && gchar_cursor() != NUL)
+ ++curwin->w_cursor.col;
+ }
+ else
+ {
+ if (curwin->w_cursor.col)
+ while ((F_isdigit(gchar_cursor())
+ || (gchar_cursor() == F_PERIOD
+ || gchar_cursor() == F_PLUS
+ || gchar_cursor() == F_MINUS
+ || gchar_cursor() == F_MUL
+ || gchar_cursor() == F_DIVIDE
+ || gchar_cursor() == F_PERCENT
+ || gchar_cursor() == F_EQUALS))
+ && --curwin->w_cursor.col)
+ ;
+
+ if (!F_isdigit(gchar_cursor()))
+ ++curwin->w_cursor.col;
+ }
+ }
+ }
+
+ if (!revins)
+ {
+ if (curwin->w_p_rl)
+ p_ri=0;
+ if (!curwin->w_p_rl)
+ p_ri=1;
+ }
+
+ if ((c < 0x100) && (isalpha(c) || c == '&' || c == '^' || c == ';' ||
+ c == '\''|| c == ',' || c == '[' ||
+ c == ']' || c == '{' || c == '}' ))
+ chg_r_to_Xor_X_();
+
+ tempc = 0;
+
+ switch (c)
+ {
+ case '`':
+ case ' ':
+ case '.':
+ case '!':
+ case '"':
+ case '$':
+ case '%':
+ case '^':
+ case '&':
+ case '/':
+ case '(':
+ case ')':
+ case '=':
+ case '\\':
+ case '?':
+ case '+':
+ case '-':
+ case '_':
+ case '*':
+ case ':':
+ case '#':
+ case '~':
+ case '@':
+ case '<':
+ case '>':
+ case '{':
+ case '}':
+ case '|':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'B':
+ case 'E':
+ case 'F':
+ case 'H':
+ case 'I':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'T':
+ case 'U':
+ case 'W':
+ case 'Y':
+ case NL:
+ case TAB:
+
+ if (p_ri && c == NL && curwin->w_cursor.col)
+ {
+ /*
+ ** If the char before the cursor is _X_ or X_ do not change
+ ** the one under the cursor with X type.
+ */
+
+ dec_cursor();
+
+ if (F_isalpha(gchar_cursor()))
+ {
+ inc_cursor();
+ return NL;
+ }
+
+ inc_cursor();
+ }
+
+ if (!p_ri)
+ if (!curwin->w_cursor.col)
+ {
+ switch (c)
+ {
+ case '0': return FARSI_0;
+ case '1': return FARSI_1;
+ case '2': return FARSI_2;
+ case '3': return FARSI_3;
+ case '4': return FARSI_4;
+ case '5': return FARSI_5;
+ case '6': return FARSI_6;
+ case '7': return FARSI_7;
+ case '8': return FARSI_8;
+ case '9': return FARSI_9;
+ case 'B': return F_PSP;
+ case 'E': return JAZR_N;
+ case 'F': return ALEF_D_H;
+ case 'H': return ALEF_A;
+ case 'I': return TASH;
+ case 'K': return F_LQUOT;
+ case 'L': return F_RQUOT;
+ case 'M': return HAMZE;
+ case 'O': return '[';
+ case 'P': return ']';
+ case 'Q': return OO;
+ case 'R': return MAD_N;
+ case 'T': return OW;
+ case 'U': return MAD;
+ case 'W': return OW_OW;
+ case 'Y': return JAZR;
+ case '`': return F_PCN;
+ case '!': return F_EXCL;
+ case '@': return F_COMMA;
+ case '#': return F_DIVIDE;
+ case '$': return F_CURRENCY;
+ case '%': return F_PERCENT;
+ case '^': return F_MUL;
+ case '&': return F_BCOMMA;
+ case '*': return F_STAR;
+ case '(': return F_LPARENT;
+ case ')': return F_RPARENT;
+ case '-': return F_MINUS;
+ case '_': return F_UNDERLINE;
+ case '=': return F_EQUALS;
+ case '+': return F_PLUS;
+ case '\\': return F_BSLASH;
+ case '|': return F_PIPE;
+ case ':': return F_DCOLON;
+ case '"': return F_SEMICOLON;
+ case '.': return F_PERIOD;
+ case '/': return F_SLASH;
+ case '<': return F_LESS;
+ case '>': return F_GREATER;
+ case '?': return F_QUESTION;
+ case ' ': return F_BLANK;
+ }
+ break;
+ }
+ if (!p_ri)
+ dec_cursor();
+
+ switch ((tempc = gchar_cursor()))
+ {
+ case _BE:
+ case _PE:
+ case _TE:
+ case _SE:
+ case _JIM:
+ case _CHE:
+ case _HE_J:
+ case _XE:
+ case _SIN:
+ case _SHIN:
+ case _SAD:
+ case _ZAD:
+ case _FE:
+ case _GHAF:
+ case _KAF:
+ case _KAF_H:
+ case _GAF:
+ case _LAM:
+ case _MIM:
+ case _NOON:
+ case _HE:
+ case _HE_:
+ case _TA:
+ case _ZA:
+ put_curr_and_l_to_X(toF_TyA(tempc));
+ break;
+ case _AYN:
+ case _AYN_:
+
+ if (!p_ri)
+ if (!curwin->w_cursor.col)
+ {
+ put_curr_and_l_to_X(AYN);
+ break;
+ }
+
+ if (p_ri)
+ inc_cursor();
+ else
+ dec_cursor();
+
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ tempc = AYN_;
+ else
+ tempc = AYN;
+
+ if (p_ri)
+ dec_cursor();
+ else
+ inc_cursor();
+
+ put_curr_and_l_to_X(tempc);
+
+ break;
+ case _GHAYN:
+ case _GHAYN_:
+
+ if (!p_ri)
+ if (!curwin->w_cursor.col)
+ {
+ put_curr_and_l_to_X(GHAYN);
+ break;
+ }
+
+ if (p_ri)
+ inc_cursor();
+ else
+ dec_cursor();
+
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ tempc = GHAYN_;
+ else
+ tempc = GHAYN;
+
+ if (p_ri)
+ dec_cursor();
+ else
+ inc_cursor();
+
+ put_curr_and_l_to_X(tempc);
+ break;
+ case _YE:
+ case _IE:
+ case _YEE:
+ if (!p_ri)
+ if (!curwin->w_cursor.col)
+ {
+ put_curr_and_l_to_X((tempc == _YE ? YE :
+ (tempc == _IE ? IE : YEE)));
+ break;
+ }
+
+ if (p_ri)
+ inc_cursor();
+ else
+ dec_cursor();
+
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ tempc = (tempc == _YE ? YE_ :
+ (tempc == _IE ? IE_ : YEE_));
+ else
+ tempc = (tempc == _YE ? YE :
+ (tempc == _IE ? IE : YEE));
+
+ if (p_ri)
+ dec_cursor();
+ else
+ inc_cursor();
+
+ put_curr_and_l_to_X(tempc);
+ break;
+ }
+
+ if (!p_ri)
+ inc_cursor();
+
+ tempc = 0;
+
+ switch (c)
+ {
+ case '0': return FARSI_0;
+ case '1': return FARSI_1;
+ case '2': return FARSI_2;
+ case '3': return FARSI_3;
+ case '4': return FARSI_4;
+ case '5': return FARSI_5;
+ case '6': return FARSI_6;
+ case '7': return FARSI_7;
+ case '8': return FARSI_8;
+ case '9': return FARSI_9;
+ case 'B': return F_PSP;
+ case 'E': return JAZR_N;
+ case 'F': return ALEF_D_H;
+ case 'H': return ALEF_A;
+ case 'I': return TASH;
+ case 'K': return F_LQUOT;
+ case 'L': return F_RQUOT;
+ case 'M': return HAMZE;
+ case 'O': return '[';
+ case 'P': return ']';
+ case 'Q': return OO;
+ case 'R': return MAD_N;
+ case 'T': return OW;
+ case 'U': return MAD;
+ case 'W': return OW_OW;
+ case 'Y': return JAZR;
+ case '`': return F_PCN;
+ case '!': return F_EXCL;
+ case '@': return F_COMMA;
+ case '#': return F_DIVIDE;
+ case '$': return F_CURRENCY;
+ case '%': return F_PERCENT;
+ case '^': return F_MUL;
+ case '&': return F_BCOMMA;
+ case '*': return F_STAR;
+ case '(': return F_LPARENT;
+ case ')': return F_RPARENT;
+ case '-': return F_MINUS;
+ case '_': return F_UNDERLINE;
+ case '=': return F_EQUALS;
+ case '+': return F_PLUS;
+ case '\\': return F_BSLASH;
+ case '|': return F_PIPE;
+ case ':': return F_DCOLON;
+ case '"': return F_SEMICOLON;
+ case '.': return F_PERIOD;
+ case '/': return F_SLASH;
+ case '<': return F_LESS;
+ case '>': return F_GREATER;
+ case '?': return F_QUESTION;
+ case ' ': return F_BLANK;
+ }
+ break;
+
+ case 'a':
+ tempc = _SHIN;
+ break;
+ case 'A':
+ tempc = WAW_H;
+ break;
+ case 'b':
+ tempc = ZAL;
+ break;
+ case 'c':
+ tempc = ZE;
+ break;
+ case 'C':
+ tempc = JE;
+ break;
+ case 'd':
+ tempc = _YE;
+ break;
+ case 'D':
+ tempc = _YEE;
+ break;
+ case 'e':
+ tempc = _SE;
+ break;
+ case 'f':
+ tempc = _BE;
+ break;
+ case 'g':
+ tempc = _LAM;
+ break;
+ case 'G':
+ if (!curwin->w_cursor.col && STRLEN(ml_get_curline()))
+ {
+
+ if (gchar_cursor() == _LAM)
+ chg_c_toX_orX ();
+ else
+ if (p_ri)
+ chg_c_to_X_or_X ();
+ }
+
+ if (!p_ri)
+ if (!curwin->w_cursor.col)
+ return ALEF_U_H;
+
+ if (!p_ri)
+ dec_cursor();
+
+ if (gchar_cursor() == _LAM)
+ {
+ chg_c_toX_orX ();
+ chg_l_toXor_X ();
+ tempc = ALEF_U_H;
+ }
+ else
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ {
+ tempc = ALEF_U_H_;
+ chg_l_toXor_X ();
+ }
+ else
+ tempc = ALEF_U_H;
+
+ if (!p_ri)
+ inc_cursor();
+
+ return tempc;
+ case 'h':
+ if (!curwin->w_cursor.col && STRLEN(ml_get_curline()))
+ {
+ if (p_ri)
+ chg_c_to_X_or_X ();
+
+ }
+
+ if (!p_ri)
+ if (!curwin->w_cursor.col)
+ return ALEF;
+
+ if (!p_ri)
+ dec_cursor();
+
+ if (gchar_cursor() == _LAM)
+ {
+ chg_l_toXor_X();
+ del_char(FALSE);
+ AppendCharToRedobuff(K_BS);
+
+ if (!p_ri)
+ dec_cursor();
+
+ tempc = LA;
+ }
+ else
+ {
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ {
+ tempc = ALEF_;
+ chg_l_toXor_X ();
+ }
+ else
+ tempc = ALEF;
+ }
+
+ if (!p_ri)
+ inc_cursor();
+
+ return tempc;
+ case 'i':
+ if (!curwin->w_cursor.col && STRLEN(ml_get_curline()))
+ {
+ if (!p_ri && !F_is_TyE(tempc))
+ chg_c_to_X_orX_ ();
+ if (p_ri)
+ chg_c_to_X_or_X ();
+
+ }
+
+ if (!p_ri && !curwin->w_cursor.col)
+ return _HE;
+
+ if (!p_ri)
+ dec_cursor();
+
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ tempc = _HE_;
+ else
+ tempc = _HE;
+
+ if (!p_ri)
+ inc_cursor();
+ break;
+ case 'j':
+ tempc = _TE;
+ break;
+ case 'J':
+ if (!curwin->w_cursor.col && STRLEN(ml_get_curline()))
+ {
+ if (p_ri)
+ chg_c_to_X_or_X ();
+
+ }
+
+ if (!p_ri)
+ if (!curwin->w_cursor.col)
+ return TEE;
+
+ if (!p_ri)
+ dec_cursor();
+
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ {
+ tempc = TEE_;
+ chg_l_toXor_X ();
+ }
+ else
+ tempc = TEE;
+
+ if (!p_ri)
+ inc_cursor();
+
+ return tempc;
+ case 'k':
+ tempc = _NOON;
+ break;
+ case 'l':
+ tempc = _MIM;
+ break;
+ case 'm':
+ tempc = _PE;
+ break;
+ case 'n':
+ case 'N':
+ tempc = DAL;
+ break;
+ case 'o':
+ tempc = _XE;
+ break;
+ case 'p':
+ tempc = _HE_J;
+ break;
+ case 'q':
+ tempc = _ZAD;
+ break;
+ case 'r':
+ tempc = _GHAF;
+ break;
+ case 's':
+ tempc = _SIN;
+ break;
+ case 'S':
+ tempc = _IE;
+ break;
+ case 't':
+ tempc = _FE;
+ break;
+ case 'u':
+ if (!curwin->w_cursor.col && STRLEN(ml_get_curline()))
+ {
+ if (!p_ri && !F_is_TyE(tempc))
+ chg_c_to_X_orX_ ();
+ if (p_ri)
+ chg_c_to_X_or_X ();
+
+ }
+
+ if (!p_ri && !curwin->w_cursor.col)
+ return _AYN;
+
+ if (!p_ri)
+ dec_cursor();
+
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ tempc = _AYN_;
+ else
+ tempc = _AYN;
+
+ if (!p_ri)
+ inc_cursor();
+ break;
+ case 'v':
+ case 'V':
+ tempc = RE;
+ break;
+ case 'w':
+ tempc = _SAD;
+ break;
+ case 'x':
+ case 'X':
+ tempc = _TA;
+ break;
+ case 'y':
+ if (!curwin->w_cursor.col && STRLEN(ml_get_curline()))
+ {
+ if (!p_ri && !F_is_TyE(tempc))
+ chg_c_to_X_orX_ ();
+ if (p_ri)
+ chg_c_to_X_or_X ();
+
+ }
+
+ if (!p_ri && !curwin->w_cursor.col)
+ return _GHAYN;
+
+ if (!p_ri)
+ dec_cursor();
+
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+ tempc = _GHAYN_;
+ else
+ tempc = _GHAYN;
+
+ if (!p_ri)
+ inc_cursor();
+
+ break;
+ case 'z':
+ tempc = _ZA;
+ break;
+ case 'Z':
+ tempc = _KAF_H;
+ break;
+ case ';':
+ tempc = _KAF;
+ break;
+ case '\'':
+ tempc = _GAF;
+ break;
+ case ',':
+ tempc = WAW;
+ break;
+ case '[':
+ tempc = _JIM;
+ break;
+ case ']':
+ tempc = _CHE;
+ break;
+ }
+
+ if ((F_isalpha(tempc) || F_isdigit(tempc)))
+ {
+ if (!curwin->w_cursor.col && STRLEN(ml_get_curline()))
+ {
+ if (!p_ri && !F_is_TyE(tempc))
+ chg_c_to_X_orX_ ();
+ if (p_ri)
+ chg_c_to_X_or_X ();
+ }
+
+ if (curwin->w_cursor.col)
+ {
+ if (!p_ri)
+ dec_cursor();
+
+ if (F_is_TyE(tempc))
+ chg_l_toXor_X ();
+ else
+ chg_l_to_X_orX_ ();
+
+ if (!p_ri)
+ inc_cursor();
+ }
+ }
+ if (tempc)
+ return tempc;
+ return c;
+}
+
+/*
+** Convert a none leading Farsi char into a leading type.
+*/
+ static int
+toF_leading(c)
+ int c;
+{
+ switch (c)
+ {
+ case ALEF_: return ALEF;
+ case ALEF_U_H_: return ALEF_U_H;
+ case BE: return _BE;
+ case PE: return _PE;
+ case TE: return _TE;
+ case SE: return _SE;
+ case JIM: return _JIM;
+ case CHE: return _CHE;
+ case HE_J: return _HE_J;
+ case XE: return _XE;
+ case SIN: return _SIN;
+ case SHIN: return _SHIN;
+ case SAD: return _SAD;
+ case ZAD: return _ZAD;
+
+ case AYN:
+ case AYN_:
+ case _AYN_: return _AYN;
+
+ case GHAYN:
+ case GHAYN_:
+ case _GHAYN_: return _GHAYN;
+
+ case FE: return _FE;
+ case GHAF: return _GHAF;
+ case KAF: return _KAF;
+ case GAF: return _GAF;
+ case LAM: return _LAM;
+ case MIM: return _MIM;
+ case NOON: return _NOON;
+
+ case _HE_:
+ case F_HE: return _HE;
+
+ case YE:
+ case YE_: return _YE;
+
+ case IE_:
+ case IE: return _IE;
+
+ case YEE:
+ case YEE_: return _YEE;
+ }
+ return c;
+}
+
+/*
+** Convert a given Farsi char into right joining type.
+*/
+ static int
+toF_Rjoin(c)
+ int c;
+{
+ switch (c)
+ {
+ case ALEF: return ALEF_;
+ case ALEF_U_H: return ALEF_U_H_;
+ case BE: return _BE;
+ case PE: return _PE;
+ case TE: return _TE;
+ case SE: return _SE;
+ case JIM: return _JIM;
+ case CHE: return _CHE;
+ case HE_J: return _HE_J;
+ case XE: return _XE;
+ case SIN: return _SIN;
+ case SHIN: return _SHIN;
+ case SAD: return _SAD;
+ case ZAD: return _ZAD;
+
+ case AYN:
+ case AYN_:
+ case _AYN: return _AYN_;
+
+ case GHAYN:
+ case GHAYN_:
+ case _GHAYN_: return _GHAYN_;
+
+ case FE: return _FE;
+ case GHAF: return _GHAF;
+ case KAF: return _KAF;
+ case GAF: return _GAF;
+ case LAM: return _LAM;
+ case MIM: return _MIM;
+ case NOON: return _NOON;
+
+ case _HE:
+ case F_HE: return _HE_;
+
+ case YE:
+ case YE_: return _YE;
+
+ case IE_:
+ case IE: return _IE;
+
+ case TEE: return TEE_;
+
+ case YEE:
+ case YEE_: return _YEE;
+ }
+ return c;
+}
+
+/*
+** Can a given Farsi character join via its left edj.
+*/
+ static int
+canF_Ljoin(c)
+ int c;
+{
+ switch (c)
+ {
+ case _BE:
+ case BE:
+ case PE:
+ case _PE:
+ case TE:
+ case _TE:
+ case SE:
+ case _SE:
+ case JIM:
+ case _JIM:
+ case CHE:
+ case _CHE:
+ case HE_J:
+ case _HE_J:
+ case XE:
+ case _XE:
+ case SIN:
+ case _SIN:
+ case SHIN:
+ case _SHIN:
+ case SAD:
+ case _SAD:
+ case ZAD:
+ case _ZAD:
+ case _TA:
+ case _ZA:
+ case AYN:
+ case _AYN:
+ case _AYN_:
+ case AYN_:
+ case GHAYN:
+ case GHAYN_:
+ case _GHAYN_:
+ case _GHAYN:
+ case FE:
+ case _FE:
+ case GHAF:
+ case _GHAF:
+ case _KAF_H:
+ case KAF:
+ case _KAF:
+ case GAF:
+ case _GAF:
+ case LAM:
+ case _LAM:
+ case MIM:
+ case _MIM:
+ case NOON:
+ case _NOON:
+ case IE:
+ case _IE:
+ case IE_:
+ case YE:
+ case _YE:
+ case YE_:
+ case YEE:
+ case _YEE:
+ case YEE_:
+ case F_HE:
+ case _HE:
+ case _HE_:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+** Can a given Farsi character join via its right edj.
+*/
+ static int
+canF_Rjoin(c)
+ int c;
+{
+ switch (c)
+ {
+ case ALEF:
+ case ALEF_:
+ case ALEF_U_H:
+ case ALEF_U_H_:
+ case DAL:
+ case ZAL:
+ case RE:
+ case JE:
+ case ZE:
+ case TEE:
+ case TEE_:
+ case WAW:
+ case WAW_H:
+ return TRUE;
+ }
+
+ return canF_Ljoin(c);
+
+}
+
+/*
+** is a given Farsi character a terminating type.
+*/
+ static int
+F_isterm(c)
+ int c;
+{
+ switch (c)
+ {
+ case ALEF:
+ case ALEF_:
+ case ALEF_U_H:
+ case ALEF_U_H_:
+ case DAL:
+ case ZAL:
+ case RE:
+ case JE:
+ case ZE:
+ case WAW:
+ case WAW_H:
+ case TEE:
+ case TEE_:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+** Convert the given Farsi character into a ending type .
+*/
+ static int
+toF_ending(c)
+ int c;
+{
+
+ switch (c)
+ {
+ case _BE:
+ return BE;
+ case _PE:
+ return PE;
+ case _TE:
+ return TE;
+ case _SE:
+ return SE;
+ case _JIM:
+ return JIM;
+ case _CHE:
+ return CHE;
+ case _HE_J:
+ return HE_J;
+ case _XE:
+ return XE;
+ case _SIN:
+ return SIN;
+ case _SHIN:
+ return SHIN;
+ case _SAD:
+ return SAD;
+ case _ZAD:
+ return ZAD;
+ case _AYN:
+ return AYN;
+ case _AYN_:
+ return AYN_;
+ case _GHAYN:
+ return GHAYN;
+ case _GHAYN_:
+ return GHAYN_;
+ case _FE:
+ return FE;
+ case _GHAF:
+ return GHAF;
+ case _KAF_H:
+ case _KAF:
+ return KAF;
+ case _GAF:
+ return GAF;
+ case _LAM:
+ return LAM;
+ case _MIM:
+ return MIM;
+ case _NOON:
+ return NOON;
+ case _YE:
+ return YE_;
+ case YE_:
+ return YE;
+ case _YEE:
+ return YEE_;
+ case YEE_:
+ return YEE;
+ case TEE:
+ return TEE_;
+ case _IE:
+ return IE_;
+ case IE_:
+ return IE;
+ case _HE:
+ case _HE_:
+ return F_HE;
+ }
+ return c;
+}
+
+/*
+** Convert the Farsi 3342 standard into Farsi VIM.
+*/
+ void
+conv_to_pvim()
+{
+ char_u *ptr;
+ int lnum, llen, i;
+
+ for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
+ {
+ ptr = ml_get((linenr_T)lnum);
+
+ llen = (int)STRLEN(ptr);
+
+ for ( i = 0; i < llen-1; i++)
+ {
+ if (canF_Ljoin(ptr[i]) && canF_Rjoin(ptr[i+1]))
+ {
+ ptr[i] = toF_leading(ptr[i]);
+ ++i;
+
+ while(canF_Rjoin(ptr[i]) && (i < llen))
+ {
+ ptr[i] = toF_Rjoin(ptr[i]);
+ if (F_isterm(ptr[i]) || !F_isalpha(ptr[i]))
+ break;
+ ++i;
+ }
+ if (!F_isalpha(ptr[i]) || !canF_Rjoin(ptr[i]))
+ ptr[i-1] = toF_ending(ptr[i-1]);
+ }
+ else
+ ptr[i] = toF_TyA(ptr[i]);
+ }
+ }
+
+ /*
+ * Following lines contains Farsi encoded character.
+ */
+
+ do_cmdline_cmd((char_u *)"%s/\202\231/\232/g");
+ do_cmdline_cmd((char_u *)"%s/\201\231/\370\334/g");
+
+ /* Assume the screen has been messed up: clear it and redraw. */
+ redraw_later(CLEAR);
+ MSG_ATTR(farsi_text_1, hl_attr(HLF_S));
+}
+
+/*
+ * Convert the Farsi VIM into Farsi 3342 standad.
+ */
+ void
+conv_to_pstd()
+{
+ char_u *ptr;
+ int lnum, llen, i;
+
+ /*
+ * Following line contains Farsi encoded character.
+ */
+
+ do_cmdline_cmd((char_u *)"%s/\232/\202\231/g");
+
+ for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
+ {
+ ptr = ml_get((linenr_T)lnum);
+
+ llen = (int)STRLEN(ptr);
+
+ for ( i = 0; i < llen; i++)
+ {
+ ptr[i] = toF_TyA(ptr[i]);
+
+ }
+ }
+
+ /* Assume the screen has been messed up: clear it and redraw. */
+ redraw_later(CLEAR);
+ MSG_ATTR(farsi_text_2, hl_attr(HLF_S));
+}
+
+/*
+ * left-right swap the characters in buf[len].
+ */
+ static void
+lrswapbuf(buf, len)
+ char_u *buf;
+ int len;
+{
+ char_u *s, *e;
+ int c;
+
+ s = buf;
+ e = buf + len - 1;
+
+ while (e > s)
+ {
+ c = *s;
+ *s = *e;
+ *e = c;
+ ++s;
+ --e;
+ }
+}
+
+/*
+ * swap all the characters in reverse direction
+ */
+ char_u *
+lrswap(ibuf)
+ char_u *ibuf;
+{
+ if (ibuf != NULL && *ibuf != NUL)
+ lrswapbuf(ibuf, (int)STRLEN(ibuf));
+ return ibuf;
+}
+
+/*
+ * swap all the Farsi characters in reverse direction
+ */
+ char_u *
+lrFswap(cmdbuf, len)
+ char_u *cmdbuf;
+ int len;
+{
+ int i, cnt;
+
+ if (cmdbuf == NULL)
+ return cmdbuf;
+
+ if (len == 0 && (len = (int)STRLEN(cmdbuf)) == 0)
+ return cmdbuf;
+
+ for (i = 0; i < len; i++)
+ {
+ for (cnt = 0; i + cnt < len
+ && (F_isalpha(cmdbuf[i + cnt])
+ || F_isdigit(cmdbuf[i + cnt])
+ || cmdbuf[i + cnt] == ' '); ++cnt)
+ ;
+
+ lrswapbuf(cmdbuf + i, cnt);
+ i += cnt;
+ }
+ return cmdbuf;
+}
+
+/*
+ * Reverse the characters in the seach path and substitude section accordingly
+ */
+ char_u *
+lrF_sub(ibuf)
+ char_u *ibuf;
+{
+ char_u *p, *ep;
+ int i, cnt;
+
+ p = ibuf;
+
+ /* Find the boundry of the search path */
+ while (((p = vim_strchr(++p, '/')) != NULL) && p[-1] == '\\')
+ ;
+
+ if (p == NULL)
+ return ibuf;
+
+ /* Reverse the Farsi characters in the search path. */
+ lrFswap(ibuf, (int)(p-ibuf));
+
+ /* Now find the boundry of the substitute section */
+ if ((ep = (char_u *)strrchr((char *)++p, '/')) != NULL)
+ cnt = (int)(ep - p);
+ else
+ cnt = (int)STRLEN(p);
+
+ /* Reverse the characters in the substitute section and take care of '\' */
+ for (i = 0; i < cnt-1; i++)
+ if (p[i] == '\\')
+ {
+ p[i] = p[i+1] ;
+ p[++i] = '\\';
+ }
+
+ lrswapbuf(p, cnt);
+
+ return ibuf;
+}
+
+/*
+ * Map Farsi keyboard when in cmd_fkmap mode.
+ */
+ int
+cmdl_fkmap(c)
+ int c;
+{
+ int tempc;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '`':
+ case ' ':
+ case '.':
+ case '!':
+ case '"':
+ case '$':
+ case '%':
+ case '^':
+ case '&':
+ case '/':
+ case '(':
+ case ')':
+ case '=':
+ case '\\':
+ case '?':
+ case '+':
+ case '-':
+ case '_':
+ case '*':
+ case ':':
+ case '#':
+ case '~':
+ case '@':
+ case '<':
+ case '>':
+ case '{':
+ case '}':
+ case '|':
+ case 'B':
+ case 'E':
+ case 'F':
+ case 'H':
+ case 'I':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'T':
+ case 'U':
+ case 'W':
+ case 'Y':
+ case NL:
+ case TAB:
+
+ switch ((tempc = cmd_gchar(AT_CURSOR)))
+ {
+ case _BE:
+ case _PE:
+ case _TE:
+ case _SE:
+ case _JIM:
+ case _CHE:
+ case _HE_J:
+ case _XE:
+ case _SIN:
+ case _SHIN:
+ case _SAD:
+ case _ZAD:
+ case _AYN:
+ case _GHAYN:
+ case _FE:
+ case _GHAF:
+ case _KAF:
+ case _GAF:
+ case _LAM:
+ case _MIM:
+ case _NOON:
+ case _HE:
+ case _HE_:
+ cmd_pchar(toF_TyA(tempc), AT_CURSOR);
+ break;
+ case _AYN_:
+ cmd_pchar(AYN_, AT_CURSOR);
+ break;
+ case _GHAYN_:
+ cmd_pchar(GHAYN_, AT_CURSOR);
+ break;
+ case _IE:
+ if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1))
+ cmd_pchar(IE_, AT_CURSOR);
+ else
+ cmd_pchar(IE, AT_CURSOR);
+ break;
+ case _YEE:
+ if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1))
+ cmd_pchar(YEE_, AT_CURSOR);
+ else
+ cmd_pchar(YEE, AT_CURSOR);
+ break;
+ case _YE:
+ if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1))
+ cmd_pchar(YE_, AT_CURSOR);
+ else
+ cmd_pchar(YE, AT_CURSOR);
+ }
+
+ switch (c)
+ {
+ case '0': return FARSI_0;
+ case '1': return FARSI_1;
+ case '2': return FARSI_2;
+ case '3': return FARSI_3;
+ case '4': return FARSI_4;
+ case '5': return FARSI_5;
+ case '6': return FARSI_6;
+ case '7': return FARSI_7;
+ case '8': return FARSI_8;
+ case '9': return FARSI_9;
+ case 'B': return F_PSP;
+ case 'E': return JAZR_N;
+ case 'F': return ALEF_D_H;
+ case 'H': return ALEF_A;
+ case 'I': return TASH;
+ case 'K': return F_LQUOT;
+ case 'L': return F_RQUOT;
+ case 'M': return HAMZE;
+ case 'O': return '[';
+ case 'P': return ']';
+ case 'Q': return OO;
+ case 'R': return MAD_N;
+ case 'T': return OW;
+ case 'U': return MAD;
+ case 'W': return OW_OW;
+ case 'Y': return JAZR;
+ case '`': return F_PCN;
+ case '!': return F_EXCL;
+ case '@': return F_COMMA;
+ case '#': return F_DIVIDE;
+ case '$': return F_CURRENCY;
+ case '%': return F_PERCENT;
+ case '^': return F_MUL;
+ case '&': return F_BCOMMA;
+ case '*': return F_STAR;
+ case '(': return F_LPARENT;
+ case ')': return F_RPARENT;
+ case '-': return F_MINUS;
+ case '_': return F_UNDERLINE;
+ case '=': return F_EQUALS;
+ case '+': return F_PLUS;
+ case '\\': return F_BSLASH;
+ case '|': return F_PIPE;
+ case ':': return F_DCOLON;
+ case '"': return F_SEMICOLON;
+ case '.': return F_PERIOD;
+ case '/': return F_SLASH;
+ case '<': return F_LESS;
+ case '>': return F_GREATER;
+ case '?': return F_QUESTION;
+ case ' ': return F_BLANK;
+ }
+
+ break;
+
+ case 'a': return _SHIN;
+ case 'A': return WAW_H;
+ case 'b': return ZAL;
+ case 'c': return ZE;
+ case 'C': return JE;
+ case 'd': return _YE;
+ case 'D': return _YEE;
+ case 'e': return _SE;
+ case 'f': return _BE;
+ case 'g': return _LAM;
+ case 'G':
+ if (cmd_gchar(AT_CURSOR) == _LAM )
+ {
+ cmd_pchar(LAM, AT_CURSOR);
+ return ALEF_U_H;
+ }
+
+ if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
+ return ALEF_U_H_;
+ else
+ return ALEF_U_H;
+ case 'h':
+ if (cmd_gchar(AT_CURSOR) == _LAM )
+ {
+ cmd_pchar(LA, AT_CURSOR);
+ redrawcmdline();
+ return K_IGNORE;
+ }
+
+ if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
+ return ALEF_;
+ else
+ return ALEF;
+ case 'i':
+ if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
+ return _HE_;
+ else
+ return _HE;
+ case 'j': return _TE;
+ case 'J':
+ if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
+ return TEE_;
+ else
+ return TEE;
+ case 'k': return _NOON;
+ case 'l': return _MIM;
+ case 'm': return _PE;
+ case 'n':
+ case 'N': return DAL;
+ case 'o': return _XE;
+ case 'p': return _HE_J;
+ case 'q': return _ZAD;
+ case 'r': return _GHAF;
+ case 's': return _SIN;
+ case 'S': return _IE;
+ case 't': return _FE;
+ case 'u':
+ if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
+ return _AYN_;
+ else
+ return _AYN;
+ case 'v':
+ case 'V': return RE;
+ case 'w': return _SAD;
+ case 'x':
+ case 'X': return _TA;
+ case 'y':
+ if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
+ return _GHAYN_;
+ else
+ return _GHAYN;
+ case 'z':
+ case 'Z': return _ZA;
+ case ';': return _KAF;
+ case '\'': return _GAF;
+ case ',': return WAW;
+ case '[': return _JIM;
+ case ']': return _CHE;
+ }
+
+ return c;
+}
+
+/*
+ * F_isalpha returns TRUE if 'c' is a Farsi alphabet
+ */
+ int
+F_isalpha(c)
+ int c;
+{
+ return (( c >= TEE_ && c <= _YE)
+ || (c >= ALEF_A && c <= YE)
+ || (c >= _IE && c <= YE_));
+}
+
+/*
+ * F_isdigit returns TRUE if 'c' is a Farsi digit
+ */
+ int
+F_isdigit(c)
+ int c;
+{
+ return (c >= FARSI_0 && c <= FARSI_9);
+}
+
+/*
+ * F_ischar returns TRUE if 'c' is a Farsi character.
+ */
+ int
+F_ischar(c)
+ int c;
+{
+ return (c >= TEE_ && c <= YE_);
+}
+
+ void
+farsi_fkey(cap)
+ cmdarg_T *cap;
+{
+ int c = cap->cmdchar;
+
+ if (c == K_F8)
+ {
+ if (p_altkeymap)
+ {
+ if (curwin->w_farsi & W_R_L)
+ {
+ p_fkmap = 0;
+ do_cmdline_cmd((char_u *)"set norl");
+ MSG("");
+ }
+ else
+ {
+ p_fkmap = 1;
+ do_cmdline_cmd((char_u *)"set rl");
+ MSG("");
+ }
+
+ curwin->w_farsi = curwin->w_farsi ^ W_R_L;
+ }
+ }
+
+ if (c == K_F9)
+ {
+ if (p_altkeymap && curwin->w_p_rl)
+ {
+ curwin->w_farsi = curwin->w_farsi ^ W_CONV;
+ if (curwin->w_farsi & W_CONV)
+ conv_to_pvim();
+ else
+ conv_to_pstd();
+ }
+ }
+}
diff --git a/src/farsi.h b/src/farsi.h
new file mode 100644
index 000000000..8dea422cd
--- /dev/null
+++ b/src/farsi.h
@@ -0,0 +1,234 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * Farsi characters are catagorized into following types:
+ *
+ * TyA (for capital letter representation)
+ * TyB (for types that look like _X e.g. AYN)
+ * TyC (for types that look like X_ e.g. YE_)
+ * TyD (for types that look like _X_ e.g. _AYN_)
+ * TyE (for types that look like X e.g. RE)
+ */
+
+/*
+ * Farsi character set definition
+ */
+
+/*
+ * Begin of the non-standard part
+ */
+
+#define TEE_ 0x80
+#define ALEF_U_H_ 0x81
+#define ALEF_ 0x82
+#define _BE 0x83
+#define _PE 0x84
+#define _TE 0x85
+#define _SE 0x86
+#define _JIM 0x87
+#define _CHE 0x88
+#define _HE_J 0x89
+#define _XE 0x8a
+#define _SIN 0x8b
+#define _SHIN 0x8c
+#define _SAD 0x8d
+#define _ZAD 0x8e
+#define _AYN 0x8f
+#define _AYN_ 0x90
+#define AYN_ 0x91
+#define _GHAYN 0x92
+#define _GHAYN_ 0x93
+#define GHAYN_ 0x94
+#define _FE 0x95
+#define _GHAF 0x96
+#define _KAF 0x97
+#define _GAF 0x98
+#define _LAM 0x99
+#define LA 0x9a
+#define _MIM 0x9b
+#define _NOON 0x9c
+#define _HE 0x9d
+#define _HE_ 0x9e
+#define _YE 0x9f
+#define _IE 0xec
+#define IE_ 0xed
+#define IE 0xfb
+#define _YEE 0xee
+#define YEE_ 0xef
+#define YE_ 0xff
+
+/*
+ * End of the non-standard part
+ */
+
+/*
+ * Standard part
+ */
+
+#define F_BLANK 0xa0 /* Farsi ' ' (SP) character */
+#define F_PSP 0xa1 /* PSP for capitalizing of a character */
+#define F_PCN 0xa2 /* PCN for redefining of the hamye meaning */
+#define F_EXCL 0xa3 /* Farsi ! character */
+#define F_CURRENCY 0xa4 /* Farsi Rial character */
+#define F_PERCENT 0xa5 /* Farsi % character */
+#define F_PERIOD 0xa6 /* Farsi '.' character */
+#define F_COMMA 0xa7 /* Farsi ',' character */
+#define F_LPARENT 0xa8 /* Farsi '(' character */
+#define F_RPARENT 0xa9 /* Farsi ')' character */
+#define F_MUL 0xaa /* Farsi 'x' character */
+#define F_PLUS 0xab /* Farsi '+' character */
+#define F_BCOMMA 0xac /* Farsi comma character */
+#define F_MINUS 0xad /* Farsi '-' character */
+#define F_DIVIDE 0xae /* Farsi divide (/) character */
+#define F_SLASH 0xaf /* Farsi '/' character */
+
+#define FARSI_0 0xb0
+#define FARSI_1 0xb1
+#define FARSI_2 0xb2
+#define FARSI_3 0xb3
+#define FARSI_4 0xb4
+#define FARSI_5 0xb5
+#define FARSI_6 0xb6
+#define FARSI_7 0xb7
+#define FARSI_8 0xb8
+#define FARSI_9 0xb9
+
+#define F_DCOLON 0xba /* Farsi ':' character */
+#define F_SEMICOLON 0xbb /* Farsi ';' character */
+#define F_GREATER 0xbc /* Farsi '>' character */
+#define F_EQUALS 0xbd /* Farsi '=' character */
+#define F_LESS 0xbe /* Farsi '<' character */
+#define F_QUESTION 0xbf /* Farsi ? character */
+
+#define ALEF_A 0xc0
+#define ALEF 0xc1
+#define HAMZE 0xc2
+#define BE 0xc3
+#define PE 0xc4
+#define TE 0xc5
+#define SE 0xc6
+#define JIM 0xc7
+#define CHE 0xc8
+#define HE_J 0xc9
+#define XE 0xca
+#define DAL 0xcb
+#define ZAL 0xcc
+#define RE 0xcd
+#define ZE 0xce
+#define JE 0xcf
+#define SIN 0xd0
+#define SHIN 0xd1
+#define SAD 0xd2
+#define ZAD 0xd3
+#define _TA 0xd4
+#define _ZA 0xd5
+#define AYN 0xd6
+#define GHAYN 0xd7
+#define FE 0xd8
+#define GHAF 0xd9
+#define KAF 0xda
+#define GAF 0xdb
+#define LAM 0xdc
+#define MIM 0xdd
+#define NOON 0xde
+#define WAW 0xdf
+#define F_HE 0xe0 /* F_ added for name clash with Perl */
+#define YE 0xe1
+#define TEE 0xfc
+#define _KAF_H 0xfd
+#define YEE 0xfe
+
+#define F_LBRACK 0xe2 /* Farsi '[' character */
+#define F_RBRACK 0xe3 /* Farsi ']' character */
+#define F_LBRACE 0xe4 /* Farsi '{' character */
+#define F_RBRACE 0xe5 /* Farsi '}' character */
+#define F_LQUOT 0xe6 /* Farsi left quotation character */
+#define F_RQUOT 0xe7 /* Farsi right quotation character */
+#define F_STAR 0xe8 /* Farsi '*' character */
+#define F_UNDERLINE 0xe9 /* Farsi '_' character */
+#define F_PIPE 0xea /* Farsi '|' character */
+#define F_BSLASH 0xeb /* Farsi '\' character */
+
+#define MAD 0xf0
+#define JAZR 0xf1
+#define OW 0xf2
+#define MAD_N 0xf3
+#define JAZR_N 0xf4
+#define OW_OW 0xf5
+#define TASH 0xf6
+#define OO 0xf7
+#define ALEF_U_H 0xf8
+#define WAW_H 0xf9
+#define ALEF_D_H 0xfa
+
+/*
+ * global definitions
+ * ==================
+ */
+
+#define SRC_EDT 0
+#define SRC_CMD 1
+
+#define AT_CURSOR 0
+
+/*
+ * definitions for the window dependent functions (w_farsi).
+ */
+#define W_CONV 0x1
+#define W_R_L 0x2
+
+
+/* special Farsi text messages */
+
+EXTERN char_u farsi_text_1[]
+#ifdef DO_INIT
+ = { YE_, _SIN, RE, ALEF_, _FE, ' ', 'V', 'I', 'M',
+ ' ', F_HE, _BE, ' ', SHIN, RE, _GAF, DAL,' ', NOON,
+ ALEF_, _YE, ALEF_, _PE, '\0'}
+#endif
+ ;
+
+EXTERN char_u farsi_text_2[]
+#ifdef DO_INIT
+ = { YE_, _SIN, RE, ALEF_, _FE, ' ', FARSI_3, FARSI_3,
+ FARSI_4, FARSI_2, ' ', DAL, RE, ALEF, DAL, _NOON,
+ ALEF_, _TE, _SIN, ALEF, ' ', F_HE, _BE, ' ', SHIN,
+ RE, _GAF, DAL, ' ', NOON, ALEF_, _YE, ALEF_, _PE, '\0'}
+#endif
+ ;
+
+EXTERN char_u farsi_text_3[]
+#ifdef DO_INIT
+ = { DAL, WAW, _SHIN, _YE, _MIM, _NOON, ' ', YE_, _NOON,
+ ALEF_,_BE, _YE, _TE, _SHIN, _PE, ' ', 'R','E','P','L',
+ 'A','C','E', ' ', NOON, ALEF_, _MIM, RE, _FE, ZE, ALEF,
+ ' ', 'R', 'E', 'V', 'E', 'R', 'S', 'E', ' ', 'I', 'N',
+ 'S', 'E', 'R', 'T', ' ', SHIN, WAW, RE, ' ', ALEF_, _BE,
+ ' ', YE_, _SIN, RE, ALEF_, _FE, ' ', RE, DAL, ' ', RE,
+ ALEF_, _KAF,' ', MIM, ALEF_, _GAF, _NOON, _HE, '\0'}
+#endif
+ ;
+
+#if 0 /* not used */
+EXTERN char_u farsi_text_4[]
+#ifdef DO_INIT
+ = { DAL, WAW, _SHIN, _YE, _MIM, _NOON, ' ', YE_, _NOON,
+ ALEF_, _BE, _YE, _TE, _SHIN, _PE, ' ', '<', 'C','T','R',
+ 'L','-','B','>', ' ', NOON, ALEF_, _MIM, RE, _FE, ZE,
+ ALEF, ' ', YE_, _SIN, RE, ALEF_, _FE, ' ', RE, DAL, ' ',
+ RE, ALEF_, _KAF,' ', MIM, ALEF_, _GAF, _NOON, _HE, '\0'}
+#endif
+ ;
+#endif
+
+EXTERN char_u farsi_text_5[]
+#ifdef DO_INIT
+ = { ' ', YE_, _SIN, RE, ALEF_, _FE, '\0'}
+#endif
+ ;
diff --git a/src/feature.h b/src/feature.h
new file mode 100644
index 000000000..725c0710a
--- /dev/null
+++ b/src/feature.h
@@ -0,0 +1,1184 @@
+/* vi:set ts=8 sts=0 sw=8:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+/*
+ * feature.h: Defines for optional code and preferences
+ *
+ * Edit this file to include/exclude parts of Vim, before compiling.
+ * The only other file that may be edited is Makefile, it contains machine
+ * specific options.
+ *
+ * To include specific options, change the "#if*" and "#endif" into comments,
+ * or uncomment the "#define".
+ * To exclude specific options, change the "#define" into a comment.
+ */
+
+/*
+ * When adding a new feature:
+ * - Add a #define below.
+ * - Add a message in the table above ex_version().
+ * - Add a string to f_has().
+ * - Add a feature to ":help feature-list" in doc/eval.txt.
+ * - Add feature to ":help +feature-list" in doc/various.txt.
+ * - Add comment for the documentation of commands that use the feature.
+ */
+
+/*
+ * Basic choices:
+ * ==============
+ *
+ * +tiny almost no features enabled, not even multiple windows
+ * +small few features enabled, as basic as possible
+ * +normal A default selection of features enabled
+ * +big many features enabled, as rich as possible.
+ * +huge all possible featues enabled.
+ *
+ * When +small is used, +tiny is also included. +normal implies +small, etc.
+ */
+
+/*
+ * Uncomment one of these to override the default. For unix use a configure
+ * argument, see Makefile.
+ */
+#if !defined(FEAT_TINY) && !defined(FEAT_SMALL) && !defined(FEAT_NORMAL) \
+ && !defined(FEAT_BIG) && !defined(FEAT_HUGE)
+/* #define FEAT_TINY */
+/* #define FEAT_SMALL */
+/* #define FEAT_NORMAL */
+/* #define FEAT_BIG */
+/* #define FEAT_HUGE */
+#endif
+
+/*
+ * These executables are made available with the +big feature, because they
+ * are supposed to have enough RAM: Win32 (console & GUI), dos32, OS/2 and VMS.
+ * The dos16 version has very little RAM available, use +small.
+ */
+#if !defined(FEAT_TINY) && !defined(FEAT_SMALL) && !defined(FEAT_NORMAL) \
+ && !defined(FEAT_BIG) && !defined(FEAT_HUGE)
+# if defined(MSWIN) || defined(DJGPP) || defined(OS2) || defined(VMS) || defined(MACOS) || defined(AMIGA)
+# define FEAT_BIG
+# else
+# ifdef MSDOS
+# define FEAT_SMALL
+# else
+# define FEAT_NORMAL
+# endif
+# endif
+#endif
+
+/*
+ * Each feature implies including the "smaller" ones.
+ */
+#ifdef FEAT_HUGE
+# define FEAT_BIG
+#endif
+#ifdef FEAT_BIG
+# define FEAT_NORMAL
+#endif
+#ifdef FEAT_NORMAL
+# define FEAT_SMALL
+#endif
+#ifdef FEAT_SMALL
+# define FEAT_TINY
+#endif
+
+/*
+ * Optional code (see ":help +feature-list")
+ * =============
+ */
+
+/*
+ * +windows Multiple windows. Without this there is no help
+ * window and no status lines.
+ */
+#ifdef FEAT_SMALL
+# define FEAT_WINDOWS
+#endif
+
+/*
+ * +listcmds Vim commands for the buffer list and the argument
+ * list. Without this there is no ":buffer" ":bnext",
+ * ":bdel", ":argdelete", etc.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_LISTCMDS
+#endif
+
+/*
+ * +vertsplit Vertically split windows.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_VERTSPLIT
+#endif
+#if defined(FEAT_VERTSPLIT) && !defined(FEAT_WINDOWS)
+# define FEAT_WINDOWS
+#endif
+
+/*
+ * +cmdhist Command line history.
+ */
+#ifdef FEAT_SMALL
+# define FEAT_CMDHIST
+#endif
+
+/*
+ * +jumplist Jumplist, CTRL-O and CTRL-I commands.
+ */
+#ifdef FEAT_SMALL
+# define FEAT_JUMPLIST
+#endif
+
+/* the cmdline-window requires FEAT_VERTSPLIT and FEAT_CMDHIST */
+#if defined(FEAT_VERTSPLIT) && defined(FEAT_CMDHIST)
+# define FEAT_CMDWIN
+#endif
+
+/*
+ * +folding Fold lines.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_FOLDING
+#endif
+
+/*
+ * +digraphs Digraphs.
+ * In insert mode and on the command line you will be
+ * able to use digraphs. The CTRL-K command will work.
+ * Define OLD_DIGRAPHS to get digraphs compatible with
+ * Vim 5.x. The new ones are from RFC 1345.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_DIGRAPHS
+/* #define OLD_DIGRAPHS */
+#endif
+
+/*
+ * +langmap 'langmap' option. Only useful when you put your
+ * keyboard in a special language mode, e.g. for typing
+ * greek.
+ */
+#ifdef FEAT_BIG
+# define FEAT_LANGMAP
+#endif
+
+/*
+ * +keymap 'keymap' option. Allows you to map typed keys in
+ * Insert mode for a special language.
+ */
+#ifdef FEAT_BIG
+# define FEAT_KEYMAP
+#endif
+
+/*
+ * +localmap Mappings and abbreviations local to a buffer.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_LOCALMAP
+#endif
+
+/*
+ * +insert_expand CTRL-N/CTRL-P/CTRL-X in insert mode. Takes about
+ * 4Kbyte of code.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_INS_EXPAND
+#endif
+
+/*
+ * +cmdline_compl completion of mappings/abbreviations in cmdline mode.
+ * Takes a few Kbyte of code.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_CMDL_COMPL
+#endif
+
+#ifdef FEAT_NORMAL
+# define VIM_BACKTICK /* internal backtick expansion */
+#endif
+
+/*
+ * +textobjects Text objects: "vaw", "das", etc.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_TEXTOBJ
+#endif
+
+/*
+ * +visual Visual mode.
+ * +visualextra Extra features for Visual mode (mostly block operators).
+ */
+#ifdef FEAT_SMALL
+# define FEAT_VISUAL
+# ifdef FEAT_NORMAL
+# define FEAT_VISUALEXTRA
+# endif
+#else
+# ifdef FEAT_CLIPBOARD
+# undef FEAT_CLIPBOARD /* can't use clipboard without Visual mode */
+# endif
+#endif
+
+/*
+ * +virtualedit 'virtualedit' option and its implementation
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_VIRTUALEDIT
+#endif
+
+/*
+ * +vreplace "gR" and "gr" commands.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_VREPLACE
+#endif
+
+/*
+ * +cmdline_info 'showcmd' and 'ruler' options.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_CMDL_INFO
+#endif
+
+/*
+ * +linebreak 'showbreak', 'breakat' and 'linebreak' options.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_LINEBREAK
+#endif
+
+/*
+ * +ex_extra ":retab", ":right", ":left", ":center", ":normal".
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_EX_EXTRA
+#endif
+
+/*
+ * +extra_search 'hlsearch' and 'incsearch' options.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_SEARCH_EXTRA
+#endif
+
+/*
+ * +quickfix Quickfix commands.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_QUICKFIX
+#endif
+
+/*
+ * +file_in_path "gf" and "<cfile>" commands.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_SEARCHPATH
+#endif
+
+/*
+ * +find_in_path "[I" ":isearch" "^W^I", ":checkpath", etc.
+ */
+#ifdef FEAT_NORMAL
+# ifdef FEAT_SEARCHPATH /* FEAT_SEARCHPATH is required */
+# define FEAT_FIND_ID
+# endif
+#endif
+
+/*
+ * +path_extra up/downwards searching in 'path' and 'tags'.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_PATH_EXTRA
+#endif
+
+/*
+ * +rightleft Right-to-left editing/typing support.
+ */
+#ifdef FEAT_BIG
+# define FEAT_RIGHTLEFT
+#endif
+
+/*
+ * +farsi Farsi (Persian language) Keymap support.
+ * Requires FEAT_RIGHTLEFT.
+ */
+#ifdef FEAT_BIG
+# define FEAT_FKMAP
+#endif
+#ifdef FEAT_FKMAP
+# ifndef FEAT_RIGHTLEFT
+# define FEAT_RIGHTLEFT
+# endif
+#endif
+
+/*
+ * +arabic Arabic keymap and shaping support.
+ * Requires FEAT_RIGHTLEFT and FEAT_MBYTE.
+ */
+#if defined(FEAT_BIG) && !defined(WIN16) && SIZEOF_INT >= 4 && !defined(EBCDIC)
+# define FEAT_ARABIC
+#endif
+#ifdef FEAT_ARABIC
+# ifndef FEAT_RIGHTLEFT
+# define FEAT_RIGHTLEFT
+# endif
+#endif
+
+/*
+ * +emacs_tags When FEAT_EMACS_TAGS defined: Include support for
+ * emacs style TAGS file.
+ */
+#ifdef FEAT_BIG
+# define FEAT_EMACS_TAGS
+#endif
+
+/*
+ * +tag_binary Can use a binary search for the tags file.
+ *
+ * Disabled for EBCDIC:
+ * On OS/390 Unix we have the problem that /bin/sort sorts ASCII instead of
+ * EBCDIC. With this binary search doesn't work, as VIM expects a tag file
+ * sorted by character values. I'm not sure how to fix this. Should we really
+ * do a EBCDIC to ASCII conversion for this??
+ */
+#if defined(FEAT_NORMAL) && !defined(EBCDIC)
+# define FEAT_TAG_BINS
+#endif
+
+/*
+ * +tag_old_static Old style static tags: "file:tag file ..". Slows
+ * down tag searching a bit.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_TAG_OLDSTATIC
+#endif
+
+/*
+ * +tag_any_white Allow any white space to separate the fields in a tags
+ * file. When not defined, only a TAB is allowed.
+ */
+/* #define FEAT_TAG_ANYWHITE */
+
+/*
+ * +cscope Unix only: Cscope support.
+ */
+#if defined(UNIX) && defined(FEAT_BIG) && !defined(FEAT_CSCOPE) && !defined(MACOS_X)
+# define FEAT_CSCOPE
+#endif
+
+/*
+ * +eval Built-in script language and expression evaluation,
+ * ":let", ":if", etc.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_EVAL
+#endif
+
+/*
+ * +user_commands Allow the user to define his own commands.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_USR_CMDS
+#endif
+
+/*
+ * +printer ":hardcopy" command
+ * +postscript Printing uses PostScript file output.
+ */
+#if defined(FEAT_NORMAL) && (defined(MSWIN) || defined(FEAT_EVAL)) \
+ && !defined(AMIGA)
+# define FEAT_PRINTER
+#endif
+#if defined(FEAT_PRINTER) && ((defined(MSWIN) && defined(MSWINPS)) \
+ || (!defined(MSWIN) && defined(FEAT_EVAL)))
+# define FEAT_POSTSCRIPT
+#endif
+
+/*
+ * +modify_fname modifiers for file name. E.g., "%:p:h".
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_MODIFY_FNAME
+#endif
+
+/*
+ * +autocmd ":autocmd" command
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_AUTOCMD
+#endif
+
+/*
+ * +diff Displaying diffs in a nice way.
+ * Requires +windows and +autocmd.
+ */
+#if defined(FEAT_NORMAL) && defined(FEAT_WINDOWS) && defined(FEAT_AUTOCMD)
+# define FEAT_DIFF
+#endif
+
+/*
+ * +title 'title' and 'icon' options
+ * +statusline 'statusline', 'rulerformat' and special format of
+ * 'titlestring' and 'iconstring' options.
+ * +byte_offset '%o' in 'statusline' and builtin functions line2byte()
+ * and byte2line().
+ * Note: Required for Macintosh.
+ */
+#if defined(FEAT_NORMAL) && !defined(MSDOS)
+# define FEAT_TITLE
+#endif
+
+#ifdef FEAT_NORMAL
+# define FEAT_STL_OPT
+# ifndef FEAT_CMDL_INFO
+# define FEAT_CMDL_INFO /* 'ruler' is required for 'statusline' */
+# endif
+#endif
+
+#ifdef FEAT_NORMAL
+# define FEAT_BYTEOFF
+#endif
+
+/*
+ * +wildignore 'wildignore' and 'backupskip' options
+ * Needed for Unix to make "crontab -e" work.
+ */
+#if defined(FEAT_NORMAL) || defined(UNIX)
+# define FEAT_WILDIGN
+#endif
+
+/*
+ * +wildmenu 'wildmenu' option
+ */
+#if defined(FEAT_NORMAL) && defined(FEAT_WINDOWS)
+# define FEAT_WILDMENU
+#endif
+
+/*
+ * +osfiletype filetype checking in autocommand patterns.
+ * Only on systems that support filetypes (RISC OS).
+ */
+#if 0
+# define FEAT_OSFILETYPE
+# define DFLT_OFT "Text"
+#endif
+
+/*
+ * +viminfo reading/writing the viminfo file. Takes about 8Kbyte
+ * of code.
+ * VIMINFO_FILE Location of user .viminfo file (should start with $).
+ * VIMINFO_FILE2 Location of alternate user .viminfo file.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_VIMINFO
+/* #define VIMINFO_FILE "$HOME/foo/.viminfo" */
+/* #define VIMINFO_FILE2 "~/bar/.viminfo" */
+#endif
+
+/*
+ * +syntax syntax highlighting. When using this, it's a good
+ * idea to have +autocmd and +eval too.
+ */
+#if defined(FEAT_NORMAL) || defined(PROTO)
+# define FEAT_SYN_HL
+#endif
+
+/*
+ * +builtin_terms Choose one out of the following four:
+ *
+ * NO_BUILTIN_TCAPS Do not include any builtin termcap entries (used only
+ * with HAVE_TGETENT defined).
+ *
+ * (nothing) Machine specific termcap entries will be included.
+ * This is default for win16 to save static data.
+ *
+ * SOME_BUILTIN_TCAPS Include most useful builtin termcap entries (used only
+ * with NO_BUILTIN_TCAPS not defined).
+ * This is the default.
+ *
+ * ALL_BUILTIN_TCAPS Include all builtin termcap entries
+ * (used only with NO_BUILTIN_TCAPS not defined).
+ */
+#ifdef HAVE_TGETENT
+/* #define NO_BUILTIN_TCAPS */
+#endif
+
+#if !defined(NO_BUILTIN_TCAPS) && !defined(FEAT_GUI_W16)
+# ifdef FEAT_BIG
+# define ALL_BUILTIN_TCAPS
+# else
+# define SOME_BUILTIN_TCAPS /* default */
+# endif
+#endif
+
+/*
+ * +lispindent lisp indenting (From Eric Fischer).
+ * +cindent C code indenting (From Eric Fischer).
+ * +smartindent smart C code indenting when the 'si' option is set.
+ *
+ * These two need to be defined when making prototypes.
+ */
+#if defined(FEAT_NORMAL) || defined(PROTO)
+# define FEAT_LISP
+#endif
+
+#if defined(FEAT_NORMAL) || defined(PROTO)
+# define FEAT_CINDENT
+#endif
+
+#ifdef FEAT_NORMAL
+# define FEAT_SMARTINDENT
+#endif
+
+/*
+ * +comments 'comments' option.
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_COMMENTS
+#endif
+
+/*
+ * +cryptv Encryption (by Mohsin Ahmed <mosh@sasi.com>).
+ */
+#if defined(FEAT_NORMAL) || defined(PROTO)
+# define FEAT_CRYPT
+#endif
+
+/*
+ * +mksession ":mksession" command.
+ * Requires +windows and +vertsplit.
+ */
+#if defined(FEAT_NORMAL) && defined(FEAT_WINDOWS) && defined(FEAT_VERTSPLIT)
+# define FEAT_SESSION
+#endif
+
+/*
+ * +multi_lang Multi language support. ":menutrans", ":language", etc.
+ * +gettext Message translations (requires +multi_lang)
+ * (only when "lang" archive unpacked)
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_MULTI_LANG
+#endif
+#if defined(HAVE_GETTEXT) && defined(FEAT_MULTI_LANG) \
+ && (defined(HAVE_LOCALE_H) || defined(X_LOCALE))
+# define FEAT_GETTEXT
+#endif
+
+/*
+ * +multi_byte Generic multi-byte character handling. Doesn't work
+ * with 16 bit ints. Required for GTK+ 2.
+ *
+ * Disabled for EBCDIC:
+ * Multibyte support doesn't work on OS390 Unix currently.
+ */
+#if (defined(FEAT_BIG) || defined(HAVE_GTK2) || defined(FEAT_ARABIC)) \
+ && !defined(FEAT_MBYTE) && !defined(WIN16) \
+ && SIZEOF_INT >= 4 && !defined(EBCDIC)
+# define FEAT_MBYTE
+#endif
+
+/*
+ * +multi_byte_ime Win32 IME input method. Requires +multi_byte.
+ * Only for far-east Windows, so IME can be used to input
+ * chars. Not tested much!
+ */
+#if defined(FEAT_GUI_W32) && !defined(FEAT_MBYTE_IME)
+/* #define FEAT_MBYTE_IME */
+# endif
+
+#if defined(FEAT_MBYTE_IME) && !defined(FEAT_MBYTE)
+# define FEAT_MBYTE
+#endif
+
+#if defined(FEAT_MBYTE) && SIZEOF_INT < 4 && !defined(PROTO)
+ Error: Can only handle multi-byte feature with 32 bit int or larger
+#endif
+
+/* Use iconv() when it's available. */
+#if defined(FEAT_MBYTE) && ((defined(HAVE_ICONV_H) && defined(HAVE_ICONV)) \
+ || defined(DYNAMIC_ICONV))
+# define USE_ICONV
+#endif
+
+/*
+ * +xim X Input Method. For entering special languages like
+ * chinese and Japanese.
+ * +hangul_input Internal Hangul input method. Must be included
+ * through configure: "--enable-hangulin"
+ * Both are for Unix and VMS only.
+ */
+#ifndef FEAT_XIM
+/* #define FEAT_XIM */
+#endif
+
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+# define USE_XIM 1 /* needed for GTK include files */
+#endif
+
+#ifdef FEAT_HANGULIN
+# define HANGUL_DEFAULT_KEYBOARD 2 /* 2 or 3 bulsik keyboard */
+# define ESC_CHG_TO_ENG_MODE /* if defined, when ESC pressed,
+ * turn to english mode
+ */
+# if !defined(FEAT_XFONTSET) && defined(HAVE_X11)
+# define FEAT_XFONTSET /* Hangul input requires xfontset */
+# endif
+# if defined(FEAT_XIM) && !defined(LINT)
+ Error: You should select only ONE of XIM and HANGUL INPUT
+# endif
+#endif
+#if defined(FEAT_HANGULIN) || defined(FEAT_XIM)
+/* # define X_LOCALE */ /* for OS with incomplete locale
+ support, like old linux versions. */
+/* # define SLOW_XSERVER */ /* for extremely slow X server */
+#endif
+
+/*
+ * +xfontset X fontset support. For outputting wide characters.
+ */
+#ifndef FEAT_XFONTSET
+# if defined(FEAT_MBYTE) && defined(HAVE_X11) && !defined(HAVE_GTK2)
+# define FEAT_XFONTSET
+# else
+/* # define FEAT_XFONTSET */
+# endif
+#endif
+
+/*
+ * +libcall libcall() function
+ */
+/* Using dlopen() also requires dlsym() to be available. */
+#if defined(HAVE_DLOPEN) && defined(HAVE_DLSYM)
+# define USE_DLOPEN
+#endif
+#if defined(FEAT_EVAL) && (defined(WIN3264) || ((defined(UNIX) || defined(VMS)) \
+ && (defined(USE_DLOPEN) || defined(HAVE_SHL_LOAD))))
+# define FEAT_LIBCALL
+#endif
+
+/*
+ * +scrollbind synchronization of split windows
+ */
+#if defined(FEAT_NORMAL) && defined(FEAT_WINDOWS)
+# define FEAT_SCROLLBIND
+#endif
+
+/*
+ * +menu ":menu" command
+ */
+#ifdef FEAT_NORMAL
+# define FEAT_MENU
+# ifdef FEAT_GUI_W32
+# define FEAT_TEAROFF
+# endif
+#endif
+
+/* There are two ways to use XPM. */
+#if (defined(HAVE_XM_XPMP_H) && defined(FEAT_GUI_MOTIF)) \
+ || defined(HAVE_X11_XPM_H)
+# define HAVE_XPM 1
+#endif
+
+/*
+ * +toolbar Include code for a toolbar (for the Win32 GUI, GTK
+ * always has it). But only if menus are enabled.
+ */
+#if defined(FEAT_NORMAL) && defined(FEAT_MENU) \
+ && (defined(FEAT_GUI_GTK) \
+ || defined(FEAT_GUI_MSWIN) \
+ || ((defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) \
+ && defined(HAVE_XPM)) \
+ || defined(FEAT_GUI_PHOTON))
+# define FEAT_TOOLBAR
+#endif
+#if defined(FEAT_TOOLBAR) && !defined(FEAT_MENU)
+# define FEAT_MENU
+#endif
+
+/*
+ * +browse ":browse" command.
+ *
+ * BROWSE_CURRBUF Open file browser in the directory of the current
+ * buffer, instead of the current directory.
+ */
+#if defined(FEAT_NORMAL) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC))
+# define FEAT_BROWSE
+#endif
+#if defined(FEAT_NORMAL) && defined(FEAT_GUI_MSWIN)
+# define BROWSE_CURRBUF
+#endif
+
+/*
+ * +dialog_gui Use GUI dialog.
+ * +dialog_con May use Console dialog.
+ * When none of these defined there is no dialog support.
+ */
+#ifdef FEAT_NORMAL
+# if ((defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF)) \
+ && defined(HAVE_X11_XPM_H)) \
+ || defined(FEAT_GUI_GTK) \
+ || defined(FEAT_GUI_PHOTON) \
+ || defined(FEAT_GUI_MSWIN) \
+ || defined(FEAT_GUI_MAC)
+# define FEAT_CON_DIALOG
+# define FEAT_GUI_DIALOG
+# else
+# define FEAT_CON_DIALOG
+# endif
+#endif
+#if !defined(FEAT_GUI_DIALOG) && (defined(FEAT_GUI_MOTIF) \
+ || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK))
+/* need a dialog to show error messages when starting from the desktop */
+# define FEAT_GUI_DIALOG
+#endif
+#if defined(FEAT_GUI_DIALOG) && \
+ (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \
+ || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN) \
+ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC))
+# define FEAT_GUI_TEXTDIALOG
+#endif
+
+/* Mac specific thing: Codewarrior interface. */
+#ifdef FEAT_GUI_MAC
+# define FEAT_CW_EDITOR
+#endif
+
+/*
+ * Preferences:
+ * ============
+ */
+
+/*
+ * +writebackup 'writebackup' is default on:
+ * Use a backup file while overwriting a file. But it's
+ * deleted again when 'backup' is not set. Changing this
+ * is strongly discouraged: You can loose all your
+ * changes when the computer crashes while writing the
+ * file.
+ * VMS note: It does work on VMS as well, but because of
+ * version handling it does not have any purpose.
+ * Overwrite will write to the new version.
+ */
+#ifndef VMS
+# define FEAT_WRITEBACKUP
+#endif
+
+/*
+ * +xterm_save The t_ti and t_te entries for the builtin xterm will
+ * be set to save the screen when starting Vim and
+ * restoring it when exiting.
+ */
+/* #define FEAT_XTERM_SAVE */
+
+/*
+ * DEBUG Output a lot of debugging garbage.
+ */
+/* #define DEBUG */
+
+/*
+ * STARTUPTIME Time the startup process. Writes a "vimstartup" file
+ * with timestamps.
+ */
+/* #define STARTUPTIME "vimstartup" */
+
+/*
+ * MEM_PROFILE Debugging of memory allocation and freeing.
+ */
+/* #define MEM_PROFILE */
+
+/*
+ * VIMRC_FILE Name of the .vimrc file in current dir.
+ */
+/* #define VIMRC_FILE ".vimrc" */
+
+/*
+ * EXRC_FILE Name of the .exrc file in current dir.
+ */
+/* #define EXRC_FILE ".exrc" */
+
+/*
+ * GVIMRC_FILE Name of the .gvimrc file in current dir.
+ */
+/* #define GVIMRC_FILE ".gvimrc" */
+
+/*
+ * VIEW_FILE Name of the default ":mkview" file.
+ */
+#define VIEW_FILE "View.vim"
+
+/*
+ * SESSION_FILE Name of the default ":mksession" file.
+ */
+#define SESSION_FILE "Session.vim"
+
+/*
+ * USR_VIMRC_FILE Name of the user .vimrc file.
+ * USR_VIMRC_FILE2 Name of alternate user .vimrc file.
+ * USR_VIMRC_FILE3 Name of alternate user .vimrc file.
+ */
+/* #define USR_VIMRC_FILE "~/foo/.vimrc" */
+/* #define USR_VIMRC_FILE2 "~/bar/.vimrc" */
+/* #define USR_VIMRC_FILE3 "$VIM/.vimrc" */
+
+/*
+ * EVIM_FILE Name of the evim.vim script file
+ */
+/* #define EVIM_FILE "$VIMRUNTIME/evim.vim" */
+
+/*
+ * USR_EXRC_FILE Name of the user .exrc file.
+ * USR_EXRC_FILE2 Name of the alternate user .exrc file.
+ */
+/* #define USR_EXRC_FILE "~/foo/.exrc" */
+/* #define USR_EXRC_FILE2 "~/bar/.exrc" */
+
+/*
+ * USR_GVIMRC_FILE Name of the user .gvimrc file.
+ * USR_GVIMRC_FILE2 Name of the alternate user .gvimrc file.
+ */
+/* #define USR_GVIMRC_FILE "~/foo/.gvimrc" */
+/* #define USR_GVIMRC_FILE2 "~/bar/.gvimrc" */
+/* #define USR_GVIMRC_FILE3 "$VIM/.gvimrc" */
+
+/*
+ * SYS_VIMRC_FILE Name of the system-wide .vimrc file.
+ */
+/* #define SYS_VIMRC_FILE "/etc/vimrc" */
+
+/*
+ * SYS_GVIMRC_FILE Name of the system-wide .gvimrc file.
+ */
+/* #define SYS_GVIMRC_FILE "/etc/gvimrc" */
+
+/*
+ * DFLT_HELPFILE Name of the help file.
+ */
+/* # define DFLT_HELPFILE "$VIMRUNTIME/doc/help.txt.gz" */
+
+/*
+ * File names for:
+ * FILETYPE_FILE switch on file type detection
+ * FTPLUGIN_FILE switch on loading filetype plugin files
+ * INDENT_FILE switch on loading indent files
+ * FTOFF_FILE switch off file type detection
+ * FTPLUGOF_FILE switch off loading settings files
+ * INDOFF_FILE switch off loading indent files
+ */
+/* # define FILETYPE_FILE "filetype.vim" */
+/* # define FTPLUGIN_FILE "ftplugin.vim" */
+/* # define INDENT_FILE "indent.vim" */
+/* # define FTOFF_FILE "ftoff.vim" */
+/* # define FTPLUGOF_FILE "ftplugof.vim" */
+/* # define INDOFF_FILE "indoff.vim" */
+
+/*
+ * SYS_MENU_FILE Name of the default menu.vim file.
+ */
+/* # define SYS_MENU_FILE "$VIMRUNTIME/menu.vim" */
+
+/*
+ * SYS_OPTWIN_FILE Name of the default optwin.vim file.
+ */
+#ifndef SYS_OPTWIN_FILE
+# define SYS_OPTWIN_FILE "$VIMRUNTIME/optwin.vim"
+#endif
+
+/*
+ * SYNTAX_FNAME Name of a syntax file, where %s is the syntax name.
+ */
+/* #define SYNTAX_FNAME "/foo/%s.vim" */
+
+/*
+ * RUNTIME_DIRNAME Generic name for the directory of the runtime files.
+ */
+#ifndef RUNTIME_DIRNAME
+# define RUNTIME_DIRNAME "runtime"
+#endif
+
+/*
+ * RUNTIME_GLOBAL Directory name for global Vim runtime directory.
+ * Don't define this if the preprocessor can't handle
+ * string concatenation.
+ * Also set by "--with-global-runtime" configure argument.
+ */
+/* #define RUNTIME_GLOBAL "/etc/vim" */
+
+/*
+ * MODIFIED_BY Name of who modified Vim. Required when distributing
+ * a modifed version of Vim.
+ * Also from the "--with-modified-by" configure argument.
+ */
+/* #define MODIFIED_BY "John Doe" */
+
+/*
+ * Machine dependent:
+ * ==================
+ */
+
+/*
+ * +fork Unix only: fork() support (detected by configure)
+ * +system Use system() instead of fork/exec for starting a
+ * shell. Doesn't work for the GUI!
+ */
+/* #define USE_SYSTEM */
+
+/*
+ * +X11 Unix only. Include code for xterm title saving and X
+ * clipboard. Only works if HAVE_X11 is also defined.
+ */
+#if defined(FEAT_NORMAL) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)
+# define WANT_X11
+#endif
+
+/*
+ * XSMP - X11 Session Management Protocol
+ * It may be preferred to disable this if the GUI supports it (e.g.,
+ * GNOME/KDE) and implement save-yourself etc. through that, but it may also
+ * be cleaner to have all SM-aware vims do the same thing (libSM does not
+ * depend upon X11).
+ * If your GUI wants to support SM itself, change this ifdef.
+ * I'm assuming that any X11 implementation will cope with this for now.
+ */
+#if defined(HAVE_X11) && defined(WANT_X11) && defined(HAVE_X11_SM_SMLIB_H)
+# define USE_XSMP
+#endif
+#if defined(USE_XSMP_INTERACT) && !defined(USE_XSMP)
+# undef USE_XSMP_INTERACT
+#endif
+
+/*
+ * +mouse_xterm Unix only: Include code for xterm mouse handling.
+ * +mouse_dec idem, for Dec mouse handling.
+ * +mouse_jsbterm idem, for Jsbterm mouse handling.
+ * +mouse_netterm idem, for Netterm mouse handling.
+ * (none) MS-DOS mouse support.
+ * +mouse_gpm Unix only: Include code for Linux console mouse
+ * handling.
+ * +mouse_pterm PTerm mouse support for QNX
+ * +mouse Any mouse support (any of the above enabled).
+ */
+/* OS/2 and Amiga console have no mouse support */
+#if (!defined(AMIGA) && !defined(OS2) && !defined(MACOS)) || defined(FEAT_GUI_AMIGA)
+# ifdef FEAT_NORMAL
+# define FEAT_MOUSE_XTERM
+# endif
+# ifdef FEAT_BIG
+# define FEAT_MOUSE_NET
+# endif
+# ifdef FEAT_BIG
+# define FEAT_MOUSE_DEC
+# endif
+# if defined(FEAT_NORMAL) && (defined(MSDOS) || defined(WIN3264))
+# define DOS_MOUSE
+# endif
+# if defined(FEAT_NORMAL) && defined(__QNX__)
+# define FEAT_MOUSE_PTERM
+# endif
+#endif
+
+#if defined(FEAT_NORMAL) && defined(HAVE_GPM)
+# define FEAT_MOUSE_GPM
+#endif
+/* Define FEAT_MOUSE when any of the above is defined or FEAT_GUI. */
+#if !defined(FEAT_MOUSE_TTY) && (defined(FEAT_MOUSE_XTERM) \
+ || defined(FEAT_MOUSE_NET) || defined(FEAT_MOUSE_DEC) \
+ || defined(DOS_MOUSE) || defined(FEAT_MOUSE_GPM) \
+ || defined(FEAT_MOUSE_JSB) || defined(FEAT_MOUSE_PTERM))
+# define FEAT_MOUSE_TTY /* include non-GUI mouse support */
+#endif
+#if !defined(FEAT_MOUSE) && (defined(FEAT_MOUSE_TTY) || defined(FEAT_GUI))
+# define FEAT_MOUSE /* include generic mouse support */
+#endif
+
+/*
+ * +clipboard Clipboard support. Always used for the GUI.
+ * +xterm_clipboard Unix only: Include code for handling the clipboard
+ * in an xterm like in the GUI.
+ */
+#ifdef FEAT_GUI
+# ifndef FEAT_CLIPBOARD
+# define FEAT_CLIPBOARD
+# ifndef FEAT_VISUAL
+# define FEAT_VISUAL
+# endif
+# endif
+#endif
+
+#if defined(FEAT_NORMAL) && defined(FEAT_VISUAL) \
+ && (defined(UNIX) || defined(VMS)) \
+ && defined(WANT_X11) && defined(HAVE_X11)
+# define FEAT_XCLIPBOARD
+# ifndef FEAT_CLIPBOARD
+# define FEAT_CLIPBOARD
+# endif
+#endif
+
+/*
+ * +dnd Drag'n'drop support. Always used for the GTK+ GUI.
+ */
+#if defined(FEAT_CLIPBOARD) && defined(FEAT_GUI_GTK)
+# define FEAT_DND
+#endif
+
+#if defined(FEAT_GUI_MSWIN) && defined(FEAT_SMALL)
+# define MSWIN_FIND_REPLACE /* include code for find/replace dialog */
+# define MSWIN_FR_BUFSIZE 256
+#endif
+
+/*
+ * +clientserver Remote control via the remote_send() function
+ * and the --remote argument
+ */
+#if (defined(WIN32) || defined(FEAT_XCLIPBOARD)) && defined(FEAT_EVAL)
+# define FEAT_CLIENTSERVER
+#endif
+
+/*
+ * +termresponse send t_RV to obtain terminal response. Used for xterm
+ * to check if mouse dragging can be used and if term
+ * codes can be obtaind.
+ */
+#if (defined(FEAT_NORMAL) || defined(FEAT_MOUSE)) && defined(HAVE_TGETENT)
+# define FEAT_TERMRESPONSE
+#endif
+
+/*
+ * cursor shape Adjust the shape of the cursor to the mode.
+ * mouse shape Adjust the shape of the mouse pointer to the mode.
+ */
+#ifdef FEAT_NORMAL
+/* MS-DOS console and Win32 console can change cursor shape */
+# if defined(MSDOS) || (defined(WIN3264) && !defined(FEAT_GUI_W32))
+# define MCH_CURSOR_SHAPE
+# endif
+# if defined(FEAT_GUI_W32) || defined(FEAT_GUI_W16) || defined(FEAT_GUI_MOTIF) \
+ || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK) \
+ || defined(FEAT_GUI_PHOTON)
+# define FEAT_MOUSESHAPE
+# endif
+#endif
+
+/* GUI and some consoles can change the shape of the cursor. The code is also
+ * needed for the 'mouseshape' option. */
+#if defined(FEAT_GUI) || defined(MCH_CURSOR_SHAPE) || defined(FEAT_MOUSESHAPE)
+# define CURSOR_SHAPE
+#endif
+
+/*
+ * +ARP Amiga only. Use arp.library, DOS 2.0 is not required.
+ */
+#ifndef NO_ARP
+# define FEAT_ARP
+#endif
+
+/*
+ * +GUI_Athena To compile Vim with or without the GUI (gvim) you have
+ * +GUI_BeOS to edit the Makefile.
+ * +GUI_Motif
+ */
+
+/*
+ * +ole Win32 OLE automation: Use Makefile.ovc.
+ */
+
+/*
+ * These features can only be included by using a configure argument. See the
+ * Makefile for a line to uncomment.
+ * +perl Perl interface: "--enable-perlinterp"
+ * +python Python interface: "--enable-pythoninterp"
+ * +tcl TCL interface: "--enable-tclinterp"
+ * +sniff Sniff interface: "--enable-sniff"
+ * +sun_workshop Sun Workshop integegration
+ * +netbeans_intg Netbeans integration
+ */
+
+/*
+ * These features are automatically detected:
+ * +terminfo
+ * +tgetent
+ */
+
+/*
+ * The Sun Workshop features currently only work with Motif.
+ */
+#if !defined(FEAT_GUI_MOTIF) && defined(FEAT_SUN_WORKSHOP)
+# undef FEAT_SUN_WORKSHOP
+#endif
+
+/*
+ * The Netbeans features currently only work with Motif and GTK and Win32.
+ * It also requires +listcmds and +eval.
+ */
+#if ((!defined(FEAT_GUI_MOTIF) && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_W32)) \
+ || !defined(FEAT_LISTCMDS) || !defined(FEAT_EVAL)) \
+ && defined(FEAT_NETBEANS_INTG)
+# undef FEAT_NETBEANS_INTG
+#endif
+
+/*
+ * +signs Allow signs to be displayed to the left of text lines.
+ * Adds the ":sign" command.
+ */
+#if defined(FEAT_BIG) || defined(FEAT_SUN_WORKSHOP) \
+ || defined(FEAT_NETBEANS_INTG)
+# define FEAT_SIGNS
+# if ((defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) \
+ && defined(HAVE_X11_XPM_H)) \
+ || defined(FEAT_GUI_GTK) \
+ || (defined(WIN32) && defined(FEAT_GUI))
+# define FEAT_SIGN_ICONS
+# endif
+#endif
+
+/*
+ * +balloon_eval Allow balloon expression evaluation. Used with a
+ * debugger and for tooltips.
+ * Only for GUIs where it was implemented.
+ */
+#if (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \
+ || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32)) \
+ && ( (defined(FEAT_TOOLBAR) \
+ && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_W32)) \
+ || defined(FEAT_SUN_WORKSHOP) \
+ || defined(FEAT_NETBEANS_INTG))
+# define FEAT_BEVAL
+# if !defined(FEAT_XFONTSET) && !defined(FEAT_GUI_GTK) \
+ && !defined(FEAT_GUI_W32)
+# define FEAT_XFONTSET
+# endif
+#endif
+
+#if defined(FEAT_BEVAL) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA))
+# define FEAT_BEVAL_TIP /* balloon eval used for toolbar tooltip */
+#endif
+
+#if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG)
+/*
+ * The following features are (currently) only used by Sun Visual WorkShop 6
+ * and NetBeans. These features could be used with other integrations with
+ * debuggers so I've used separate feature defines.
+ */
+# if !defined(FEAT_MENU)
+# define FEAT_MENU
+# endif
+#endif
+
+#if defined(FEAT_SUN_WORKSHOP)
+/*
+ * Use an alternative method of X input for a secondary
+ * command input.
+ */
+# define ALT_X_INPUT
+
+/*
+ * +footer Motif only: Add a message area at the bottom of the
+ * main window area.
+ */
+# define FEAT_FOOTER
+
+#endif
diff --git a/src/fileio.c b/src/fileio.c
new file mode 100644
index 000000000..22339bf8e
--- /dev/null
+++ b/src/fileio.c
@@ -0,0 +1,8750 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * fileio.c: read from and write to a file
+ */
+
+#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64)
+# include <io.h> /* for lseek(), must be before vim.h */
+#endif
+
+#if defined __EMX__
+# include <io.h> /* for mktemp(), CJW 1997-12-03 */
+#endif
+
+#include "vim.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef __TANDEM
+# include <limits.h> /* for SSIZE_MAX */
+#endif
+
+#if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
+# include <utime.h> /* for struct utimbuf */
+#endif
+
+#define BUFSIZE 8192 /* size of normal write buffer */
+#define SMBUFSIZE 256 /* size of emergency write buffer */
+
+#ifdef FEAT_CRYPT
+# define CRYPT_MAGIC "VimCrypt~01!" /* "01" is the version nr */
+# define CRYPT_MAGIC_LEN 12 /* must be multiple of 4! */
+#endif
+
+/* Is there any system that doesn't have access()? */
+#ifndef MACOS_CLASSIC /* Not available on MacOS 9 */
+# define USE_MCH_ACCESS
+#endif
+
+#ifdef FEAT_MBYTE
+static char_u *next_fenc __ARGS((char_u **pp));
+# ifdef FEAT_EVAL
+static char_u *readfile_charconvert __ARGS((char_u *fname, char_u *fenc, int *fdp));
+# endif
+#endif
+#ifdef FEAT_VIMINFO
+static void check_marks_read __ARGS((void));
+#endif
+#ifdef FEAT_CRYPT
+static char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, long *filesizep, int newfile));
+#endif
+#ifdef UNIX
+static void set_file_time __ARGS((char_u *fname, time_t atime, time_t mtime));
+#endif
+static void msg_add_fname __ARGS((buf_T *, char_u *));
+static int msg_add_fileformat __ARGS((int eol_type));
+static void msg_add_lines __ARGS((int, long, long));
+static void msg_add_eol __ARGS((void));
+static int check_mtime __ARGS((buf_T *buf, struct stat *s));
+static int time_differs __ARGS((long t1, long t2));
+#ifdef FEAT_AUTOCMD
+static int apply_autocmds_exarg __ARGS((EVENT_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, exarg_T *eap));
+#endif
+
+#if defined(FEAT_CRYPT) || defined(FEAT_MBYTE)
+# define HAS_BW_FLAGS
+# define FIO_LATIN1 0x01 /* convert Latin1 */
+# define FIO_UTF8 0x02 /* convert UTF-8 */
+# define FIO_UCS2 0x04 /* convert UCS-2 */
+# define FIO_UCS4 0x08 /* convert UCS-4 */
+# define FIO_UTF16 0x10 /* convert UTF-16 */
+# ifdef WIN3264
+# define FIO_CODEPAGE 0x20 /* convert MS-Windows codepage */
+# define FIO_PUT_CP(x) (((x) & 0xffff) << 16) /* put codepage in top word */
+# define FIO_GET_CP(x) (((x)>>16) & 0xffff) /* get codepage from top word */
+# endif
+# ifdef MACOS_X
+# define FIO_MACROMAN 0x20 /* convert MacRoman */
+# endif
+# define FIO_ENDIAN_L 0x80 /* little endian */
+# define FIO_ENCRYPTED 0x1000 /* encrypt written bytes */
+# define FIO_NOCONVERT 0x2000 /* skip encoding conversion */
+# define FIO_UCSBOM 0x4000 /* check for BOM at start of file */
+# define FIO_ALL -1 /* allow all formats */
+#endif
+
+/* When converting, a read() or write() may leave some bytes to be converted
+ * for the next call. The value is guessed... */
+#define CONV_RESTLEN 30
+
+/* We have to guess how much a sequence of bytes may expand when converting
+ * with iconv() to be able to allocate a buffer. */
+#define ICONV_MULT 8
+
+/*
+ * Structure to pass arguments from buf_write() to buf_write_bytes().
+ */
+struct bw_info
+{
+ int bw_fd; /* file descriptor */
+ char_u *bw_buf; /* buffer with data to be written */
+ int bw_len; /* lenght of data */
+#ifdef HAS_BW_FLAGS
+ int bw_flags; /* FIO_ flags */
+#endif
+#ifdef FEAT_MBYTE
+ char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */
+ int bw_restlen; /* nr of bytes in bw_rest[] */
+ int bw_first; /* first write call */
+ char_u *bw_conv_buf; /* buffer for writing converted chars */
+ int bw_conv_buflen; /* size of bw_conv_buf */
+ int bw_conv_error; /* set for conversion error */
+# ifdef USE_ICONV
+ iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */
+# endif
+#endif
+};
+
+static int buf_write_bytes __ARGS((struct bw_info *ip));
+
+#ifdef FEAT_MBYTE
+static int ucs2bytes __ARGS((unsigned c, char_u **pp, int flags));
+static int same_encoding __ARGS((char_u *a, char_u *b));
+static int get_fio_flags __ARGS((char_u *ptr));
+static char_u *check_for_bom __ARGS((char_u *p, long size, int *lenp, int flags));
+static int make_bom __ARGS((char_u *buf, char_u *name));
+# ifdef WIN3264
+static int get_win_fio_flags __ARGS((char_u *ptr));
+# endif
+# ifdef MACOS_X
+static int get_mac_fio_flags __ARGS((char_u *ptr));
+# endif
+#endif
+static int move_lines __ARGS((buf_T *frombuf, buf_T *tobuf));
+
+static linenr_T write_no_eol_lnum = 0; /* non-zero lnum when last line of
+ next binary write should not have
+ an end-of-line */
+
+ void
+filemess(buf, name, s, attr)
+ buf_T *buf;
+ char_u *name;
+ char_u *s;
+ int attr;
+{
+ int msg_scroll_save;
+
+ if (msg_silent != 0)
+ return;
+ msg_add_fname(buf, name); /* put file name in IObuff with quotes */
+ /* If it's extremely long, truncate it. */
+ if (STRLEN(IObuff) > IOSIZE - 80)
+ IObuff[IOSIZE - 80] = NUL;
+ STRCAT(IObuff, s);
+ /*
+ * For the first message may have to start a new line.
+ * For further ones overwrite the previous one, reset msg_scroll before
+ * calling filemess().
+ */
+ msg_scroll_save = msg_scroll;
+ if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
+ msg_scroll = FALSE;
+ if (!msg_scroll) /* wait a bit when overwriting an error msg */
+ check_for_delay(FALSE);
+ msg_start();
+ msg_scroll = msg_scroll_save;
+ msg_scrolled_ign = TRUE;
+ /* may truncate the message to avoid a hit-return prompt */
+ msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr);
+ msg_clr_eos();
+ out_flush();
+ msg_scrolled_ign = FALSE;
+}
+
+/*
+ * Read lines from file "fname" into the buffer after line "from".
+ *
+ * 1. We allocate blocks with lalloc, as big as possible.
+ * 2. Each block is filled with characters from the file with a single read().
+ * 3. The lines are inserted in the buffer with ml_append().
+ *
+ * (caller must check that fname != NULL, unless READ_STDIN is used)
+ *
+ * "lines_to_skip" is the number of lines that must be skipped
+ * "lines_to_read" is the number of lines that are appended
+ * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM.
+ *
+ * flags:
+ * READ_NEW starting to edit a new buffer
+ * READ_FILTER reading filter output
+ * READ_STDIN read from stdin instead of a file
+ * READ_BUFFER read from curbuf instead of a file (converting after reading
+ * stdin)
+ * READ_DUMMY read into a dummy buffer (to check if file contents changed)
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+readfile(fname, sfname, from, lines_to_skip, lines_to_read, eap, flags)
+ char_u *fname;
+ char_u *sfname;
+ linenr_T from;
+ linenr_T lines_to_skip;
+ linenr_T lines_to_read;
+ exarg_T *eap; /* can be NULL! */
+ int flags;
+{
+ int fd = 0;
+ int newfile = (flags & READ_NEW);
+ int check_readonly;
+ int filtering = (flags & READ_FILTER);
+ int read_stdin = (flags & READ_STDIN);
+ int read_buffer = (flags & READ_BUFFER);
+ linenr_T read_buf_lnum = 1; /* next line to read from curbuf */
+ colnr_T read_buf_col = 0; /* next char to read from this line */
+ char_u c;
+ linenr_T lnum = from;
+ char_u *ptr = NULL; /* pointer into read buffer */
+ char_u *buffer = NULL; /* read buffer */
+ char_u *new_buffer = NULL; /* init to shut up gcc */
+ char_u *line_start = NULL; /* init to shut up gcc */
+ int wasempty; /* buffer was empty before reading */
+ colnr_T len;
+ long size = 0;
+ char_u *p;
+ long filesize = 0;
+ int skip_read = FALSE;
+#ifdef FEAT_CRYPT
+ char_u *cryptkey = NULL;
+#endif
+ int split = 0; /* number of split lines */
+#define UNKNOWN 0x0fffffff /* file size is unknown */
+ linenr_T linecnt;
+ int error = FALSE; /* errors encountered */
+ int ff_error = EOL_UNKNOWN; /* file format with errors */
+ long linerest = 0; /* remaining chars in line */
+#ifdef UNIX
+ int perm = 0;
+ int swap_mode = -1; /* protection bits for swap file */
+#else
+ int perm;
+#endif
+ int fileformat = 0; /* end-of-line format */
+ int keep_fileformat = FALSE;
+ struct stat st;
+ int file_readonly;
+ linenr_T skip_count = 0;
+ linenr_T read_count = 0;
+ int msg_save = msg_scroll;
+ linenr_T read_no_eol_lnum = 0; /* non-zero lnum when last line of
+ * last read was missing the eol */
+ int try_mac = (vim_strchr(p_ffs, 'm') != NULL);
+ int try_dos = (vim_strchr(p_ffs, 'd') != NULL);
+ int try_unix = (vim_strchr(p_ffs, 'x') != NULL);
+ int file_rewind = FALSE;
+#ifdef FEAT_MBYTE
+ int can_retry;
+ int conv_error = FALSE; /* conversion error detected */
+ int keep_dest_enc = FALSE; /* don't retry when char doesn't fit
+ in destination encoding */
+ linenr_T illegal_byte = 0; /* line nr with illegal byte */
+ char_u *tmpname = NULL; /* name of 'charconvert' output file */
+ int fio_flags = 0;
+ char_u *fenc; /* fileencoding to use */
+ int fenc_alloced; /* fenc_next is in allocated memory */
+ char_u *fenc_next = NULL; /* next item in 'fencs' or NULL */
+ int advance_fenc = FALSE;
+ long real_size = 0;
+# ifdef USE_ICONV
+ iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */
+# ifdef FEAT_EVAL
+ int did_iconv = FALSE; /* TRUE when iconv() failed and trying
+ 'charconvert' next */
+# endif
+# endif
+ int converted = FALSE; /* TRUE if conversion done */
+ int notconverted = FALSE; /* TRUE if conversion wanted but it
+ wasn't possible */
+ char_u conv_rest[CONV_RESTLEN];
+ int conv_restlen = 0; /* nr of bytes in conv_rest[] */
+#endif
+
+#ifdef FEAT_AUTOCMD
+ write_no_eol_lnum = 0; /* in case it was set by the previous read */
+#endif
+
+ /*
+ * If there is no file name yet, use the one for the read file.
+ * BF_NOTEDITED is set to reflect this.
+ * Don't do this for a read from a filter.
+ * Only do this when 'cpoptions' contains the 'f' flag.
+ */
+ if (curbuf->b_ffname == NULL
+ && !filtering
+ && fname != NULL
+ && vim_strchr(p_cpo, CPO_FNAMER) != NULL
+ && !(flags & READ_DUMMY))
+ {
+ if (setfname(curbuf, fname, sfname, FALSE) == OK)
+ curbuf->b_flags |= BF_NOTEDITED;
+ }
+
+ /*
+ * For Unix: Use the short file name whenever possible.
+ * Avoids problems with networks and when directory names are changed.
+ * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
+ * another directory, which we don't detect.
+ */
+ if (sfname == NULL)
+ sfname = fname;
+#if defined(UNIX) || defined(__EMX__)
+ fname = sfname;
+#endif
+
+#ifdef FEAT_AUTOCMD
+ /*
+ * The BufReadCmd and FileReadCmd events intercept the reading process by
+ * executing the associated commands instead.
+ */
+ if (!filtering && !read_stdin && !read_buffer)
+ {
+ pos_T pos;
+
+ pos = curbuf->b_op_start;
+
+ /* Set '[ mark to the line above where the lines go (line 1 if zero). */
+ curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
+ curbuf->b_op_start.col = 0;
+
+ if (newfile)
+ {
+ if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname,
+ FALSE, curbuf, eap))
+#ifdef FEAT_EVAL
+ return aborting() ? FAIL : OK;
+#else
+ return OK;
+#endif
+ }
+ else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname,
+ FALSE, NULL, eap))
+#ifdef FEAT_EVAL
+ return aborting() ? FAIL : OK;
+#else
+ return OK;
+#endif
+
+ curbuf->b_op_start = pos;
+ }
+#endif
+
+ if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
+ msg_scroll = FALSE; /* overwrite previous file message */
+ else
+ msg_scroll = TRUE; /* don't overwrite previous file message */
+
+ /*
+ * If the name ends in a path separator, we can't open it. Check here,
+ * because reading the file may actually work, but then creating the swap
+ * file may destroy it! Reported on MS-DOS and Win 95.
+ * If the name is too long we might crash further on, quit here.
+ */
+ if (fname != NULL
+ && *fname != NUL
+ && (vim_ispathsep(*(fname + STRLEN(fname) - 1))
+ || STRLEN(fname) >= MAXPATHL))
+ {
+ filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
+ msg_end();
+ msg_scroll = msg_save;
+ return FAIL;
+ }
+
+#ifdef UNIX
+ /*
+ * On Unix it is possible to read a directory, so we have to
+ * check for it before the mch_open().
+ */
+ if (!read_stdin && !read_buffer)
+ {
+ perm = mch_getperm(fname);
+ if (perm >= 0 && !S_ISREG(perm) /* not a regular file ... */
+# ifdef S_ISFIFO
+ && !S_ISFIFO(perm) /* ... or fifo */
+# endif
+# ifdef S_ISSOCK
+ && !S_ISSOCK(perm) /* ... or socket */
+# endif
+ )
+ {
+ if (S_ISDIR(perm))
+ filemess(curbuf, fname, (char_u *)_("is a directory"), 0);
+ else
+ filemess(curbuf, fname, (char_u *)_("is not a file"), 0);
+ msg_end();
+ msg_scroll = msg_save;
+ return FAIL;
+ }
+ }
+#endif
+
+ /* set default 'fileformat' */
+ if (newfile)
+ {
+ if (eap != NULL && eap->force_ff != 0)
+ set_fileformat(get_fileformat_force(curbuf, eap), OPT_LOCAL);
+ else if (*p_ffs != NUL)
+ set_fileformat(default_fileformat(), OPT_LOCAL);
+ }
+
+ /* set or reset 'binary' */
+ if (eap != NULL && eap->force_bin != 0)
+ {
+ int oldval = curbuf->b_p_bin;
+
+ curbuf->b_p_bin = (eap->force_bin == FORCE_BIN);
+ set_options_bin(oldval, curbuf->b_p_bin, OPT_LOCAL);
+ }
+
+ /*
+ * When opening a new file we take the readonly flag from the file.
+ * Default is r/w, can be set to r/o below.
+ * Don't reset it when in readonly mode
+ * Only set/reset b_p_ro when BF_CHECK_RO is set.
+ */
+ check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO));
+ if (check_readonly && !readonlymode) /* default: set file not readonly */
+ curbuf->b_p_ro = FALSE;
+
+ if (newfile && !read_stdin && !read_buffer)
+ {
+ /* Remember time of file.
+ * For RISCOS, also remember the filetype.
+ */
+ if (mch_stat((char *)fname, &st) >= 0)
+ {
+ buf_store_time(curbuf, &st, fname);
+ curbuf->b_mtime_read = curbuf->b_mtime;
+
+#if defined(RISCOS) && defined(FEAT_OSFILETYPE)
+ /* Read the filetype into the buffer local filetype option. */
+ mch_read_filetype(fname);
+#endif
+#ifdef UNIX
+ /*
+ * Use the protection bits of the original file for the swap file.
+ * This makes it possible for others to read the name of the
+ * edited file from the swapfile, but only if they can read the
+ * edited file.
+ * Remove the "write" and "execute" bits for group and others
+ * (they must not write the swapfile).
+ * Add the "read" and "write" bits for the user, otherwise we may
+ * not be able to write to the file ourselves.
+ * Setting the bits is done below, after creating the swap file.
+ */
+ swap_mode = (st.st_mode & 0644) | 0600;
+#endif
+#ifdef FEAT_CW_EDITOR
+ /* Get the FSSpec on MacOS
+ * TODO: Update it properly when the buffer name changes
+ */
+ (void)GetFSSpecFromPath(curbuf->b_ffname, &curbuf->b_FSSpec);
+#endif
+#ifdef VMS
+ curbuf->b_fab_rfm = st.st_fab_rfm;
+#endif
+ }
+ else
+ {
+ curbuf->b_mtime = 0;
+ curbuf->b_mtime_read = 0;
+ curbuf->b_orig_size = 0;
+ curbuf->b_orig_mode = 0;
+ }
+
+ /* Reset the "new file" flag. It will be set again below when the
+ * file doesn't exist. */
+ curbuf->b_flags &= ~(BF_NEW | BF_NEW_W);
+ }
+
+/*
+ * for UNIX: check readonly with perm and mch_access()
+ * for RISCOS: same as Unix, otherwise file gets re-datestamped!
+ * for MSDOS and Amiga: check readonly by trying to open the file for writing
+ */
+ file_readonly = FALSE;
+ if (read_stdin)
+ {
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
+ /* Force binary I/O on stdin to avoid CR-LF -> LF conversion. */
+ setmode(0, O_BINARY);
+#endif
+ }
+ else if (!read_buffer)
+ {
+#ifdef USE_MCH_ACCESS
+ if (
+# ifdef UNIX
+ !(perm & 0222) ||
+# endif
+ mch_access((char *)fname, W_OK))
+ file_readonly = TRUE;
+ fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
+#else
+ if (!newfile
+ || readonlymode
+ || (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0)
+ {
+ file_readonly = TRUE;
+ /* try to open ro */
+ fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
+ }
+#endif
+ }
+
+ if (fd < 0) /* cannot open at all */
+ {
+#ifndef UNIX
+ int isdir_f;
+#endif
+ msg_scroll = msg_save;
+#ifndef UNIX
+ /*
+ * On MSDOS and Amiga we can't open a directory, check here.
+ */
+ isdir_f = (mch_isdir(fname));
+ perm = mch_getperm(fname); /* check if the file exists */
+ if (isdir_f)
+ {
+ filemess(curbuf, sfname, (char_u *)_("is a directory"), 0);
+ curbuf->b_p_ro = TRUE; /* must use "w!" now */
+ }
+ else
+#endif
+ if (newfile)
+ {
+ if (perm < 0)
+ {
+ /*
+ * Set the 'new-file' flag, so that when the file has
+ * been created by someone else, a ":w" will complain.
+ */
+ curbuf->b_flags |= BF_NEW;
+
+ /* Create a swap file now, so that other Vims are warned
+ * that we are editing this file. Don't do this for a
+ * "nofile" or "nowrite" buffer type. */
+#ifdef FEAT_QUICKFIX
+ if (!bt_dontwrite(curbuf))
+#endif
+ check_need_swap(newfile);
+ filemess(curbuf, sfname, (char_u *)_("[New File]"), 0);
+#ifdef FEAT_VIMINFO
+ /* Even though this is a new file, it might have been
+ * edited before and deleted. Get the old marks. */
+ check_marks_read();
+#endif
+#ifdef FEAT_MBYTE
+ if (eap != NULL && eap->force_enc != 0)
+ {
+ /* set forced 'fileencoding' */
+ fenc = enc_canonize(eap->cmd + eap->force_enc);
+ if (fenc != NULL)
+ set_string_option_direct((char_u *)"fenc", -1,
+ fenc, OPT_FREE|OPT_LOCAL);
+ vim_free(fenc);
+ }
+#endif
+#ifdef FEAT_AUTOCMD
+ apply_autocmds_exarg(EVENT_BUFNEWFILE, sfname, sfname,
+ FALSE, curbuf, eap);
+#endif
+ /* remember the current fileformat */
+ save_file_ff(curbuf);
+
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+ if (aborting()) /* autocmds may abort script processing */
+ return FAIL;
+#endif
+ return OK; /* a new file is not an error */
+ }
+ else
+ {
+ filemess(curbuf, sfname,
+ (char_u *)_("[Permission Denied]"), 0);
+ curbuf->b_p_ro = TRUE; /* must use "w!" now */
+ }
+ }
+
+ return FAIL;
+ }
+
+ /*
+ * Only set the 'ro' flag for readonly files the first time they are
+ * loaded. Help files always get readonly mode
+ */
+ if ((check_readonly && file_readonly) || curbuf->b_help)
+ curbuf->b_p_ro = TRUE;
+
+ if (newfile)
+ {
+ curbuf->b_p_eol = TRUE;
+ curbuf->b_start_eol = TRUE;
+#ifdef FEAT_MBYTE
+ curbuf->b_p_bomb = FALSE;
+#endif
+ }
+
+ /* Create a swap file now, so that other Vims are warned that we are
+ * editing this file.
+ * Don't do this for a "nofile" or "nowrite" buffer type. */
+#ifdef FEAT_QUICKFIX
+ if (!bt_dontwrite(curbuf))
+#endif
+ {
+ check_need_swap(newfile);
+#ifdef UNIX
+ /* Set swap file protection bits after creating it. */
+ if (swap_mode > 0 && curbuf->b_ml.ml_mfp->mf_fname != NULL)
+ (void)mch_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode);
+#endif
+ }
+
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ /* If "Quit" selected at ATTENTION dialog, don't load the file */
+ if (swap_exists_action == SEA_QUIT)
+ {
+ if (!read_buffer && !read_stdin)
+ close(fd);
+ return FAIL;
+ }
+#endif
+
+ ++no_wait_return; /* don't wait for return yet */
+
+ /*
+ * Set '[ mark to the line above where the lines go (line 1 if zero).
+ */
+ curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
+ curbuf->b_op_start.col = 0;
+
+#ifdef FEAT_AUTOCMD
+ if (!read_buffer)
+ {
+ int m = msg_scroll;
+ int n = msg_scrolled;
+ buf_T *old_curbuf = curbuf;
+
+ /*
+ * The file must be closed again, the autocommands may want to change
+ * the file before reading it.
+ */
+ if (!read_stdin)
+ close(fd); /* ignore errors */
+
+ /*
+ * The output from the autocommands should not overwrite anything and
+ * should not be overwritten: Set msg_scroll, restore its value if no
+ * output was done.
+ */
+ msg_scroll = TRUE;
+ if (filtering)
+ apply_autocmds_exarg(EVENT_FILTERREADPRE, NULL, sfname,
+ FALSE, curbuf, eap);
+ else if (read_stdin)
+ apply_autocmds_exarg(EVENT_STDINREADPRE, NULL, sfname,
+ FALSE, curbuf, eap);
+ else if (newfile)
+ apply_autocmds_exarg(EVENT_BUFREADPRE, NULL, sfname,
+ FALSE, curbuf, eap);
+ else
+ apply_autocmds_exarg(EVENT_FILEREADPRE, sfname, sfname,
+ FALSE, NULL, eap);
+ if (msg_scrolled == n)
+ msg_scroll = m;
+
+#ifdef FEAT_EVAL
+ if (aborting()) /* autocmds may abort script processing */
+ {
+ --no_wait_return;
+ msg_scroll = msg_save;
+ curbuf->b_p_ro = TRUE; /* must use "w!" now */
+ return FAIL;
+ }
+#endif
+ /*
+ * Don't allow the autocommands to change the current buffer.
+ * Try to re-open the file.
+ */
+ if (!read_stdin && (curbuf != old_curbuf
+ || (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) < 0))
+ {
+ --no_wait_return;
+ msg_scroll = msg_save;
+ if (fd < 0)
+ EMSG(_("E200: *ReadPre autocommands made the file unreadable"));
+ else
+ EMSG(_("E201: *ReadPre autocommands must not change current buffer"));
+ curbuf->b_p_ro = TRUE; /* must use "w!" now */
+ return FAIL;
+ }
+ }
+#endif /* FEAT_AUTOCMD */
+
+ /* Autocommands may add lines to the file, need to check if it is empty */
+ wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY);
+
+ if (!recoverymode && !filtering && !(flags & READ_DUMMY))
+ {
+ /*
+ * Show the user that we are busy reading the input. Sometimes this
+ * may take a while. When reading from stdin another program may
+ * still be running, don't move the cursor to the last line, unless
+ * always using the GUI.
+ */
+ if (read_stdin)
+ {
+#ifndef ALWAYS_USE_GUI
+ mch_msg(_("Vim: Reading from stdin...\n"));
+#endif
+#ifdef FEAT_GUI
+ /* Also write a message in the GUI window, if there is one. */
+ if (gui.in_use && !gui.dying && !gui.starting)
+ {
+ p = (char_u *)_("Reading from stdin...");
+ gui_write(p, (int)STRLEN(p));
+ }
+#endif
+ }
+ else if (!read_buffer)
+ filemess(curbuf, sfname, (char_u *)"", 0);
+ }
+
+ msg_scroll = FALSE; /* overwrite the file message */
+
+ /*
+ * Set linecnt now, before the "retry" caused by a wrong guess for
+ * fileformat, and after the autocommands, which may change them.
+ */
+ linecnt = curbuf->b_ml.ml_line_count;
+
+#ifdef FEAT_MBYTE
+ /*
+ * Decide which 'encoding' to use first.
+ */
+ if (eap != NULL && eap->force_enc != 0)
+ {
+ fenc = enc_canonize(eap->cmd + eap->force_enc);
+ fenc_alloced = TRUE;
+ }
+ else if (curbuf->b_p_bin)
+ {
+ fenc = (char_u *)""; /* binary: don't convert */
+ fenc_alloced = FALSE;
+ }
+ else if (curbuf->b_help)
+ {
+ char_u firstline[80];
+
+ /* Help files are either utf-8 or latin1. Try utf-8 first, if this
+ * fails it must be latin1.
+ * Always do this when 'encoding' is "utf-8". Otherwise only do
+ * this when needed to avoid [converted] remarks all the time.
+ * It is needed when the first line contains non-ASCII characters.
+ * That is only in *.??x files. */
+ fenc = (char_u *)"latin1";
+ c = enc_utf8;
+ if (!c && !read_stdin && TOLOWER_ASC(fname[STRLEN(fname) - 1]) == 'x')
+ {
+ /* Read the first line (and a bit more). Immediately rewind to
+ * the start of the file. If the read() fails "len" is -1. */
+ len = vim_read(fd, firstline, 80);
+ lseek(fd, (off_t)0L, SEEK_SET);
+ for (p = firstline; p < firstline + len; ++p)
+ if (*p >= 0x80)
+ {
+ c = TRUE;
+ break;
+ }
+ }
+
+ if (c)
+ {
+ fenc_next = fenc;
+ fenc = (char_u *)"utf-8";
+
+ /* When the file is utf-8 but a character doesn't fit in
+ * 'encoding' don't retry. In help text editing utf-8 bytes
+ * doesn't make sense. */
+ keep_dest_enc = TRUE;
+ }
+ fenc_alloced = FALSE;
+ }
+ else if (*p_fencs == NUL)
+ {
+ fenc = curbuf->b_p_fenc; /* use format from buffer */
+ fenc_alloced = FALSE;
+ }
+ else
+ {
+ fenc_next = p_fencs; /* try items in 'fileencodings' */
+ fenc = next_fenc(&fenc_next);
+ fenc_alloced = TRUE;
+ }
+#endif
+
+ /*
+ * Jump back here to retry reading the file in different ways.
+ * Reasons to retry:
+ * - encoding conversion failed: try another one from "fenc_next"
+ * - BOM detected and fenc was set, need to setup conversion
+ * - "fileformat" check failed: try another
+ *
+ * Variables set for special retry actions:
+ * "file_rewind" Rewind the file to start reading it again.
+ * "advance_fenc" Advance "fenc" using "fenc_next".
+ * "skip_read" Re-use already read bytes (BOM detected).
+ * "did_iconv" iconv() conversion failed, try 'charconvert'.
+ * "keep_fileformat" Don't reset "fileformat".
+ *
+ * Other status indicators:
+ * "tmpname" When != NULL did conversion with 'charconvert'.
+ * Output file has to be deleted afterwards.
+ * "iconv_fd" When != -1 did conversion with iconv().
+ */
+retry:
+
+ if (file_rewind)
+ {
+ if (read_buffer)
+ {
+ read_buf_lnum = 1;
+ read_buf_col = 0;
+ }
+ else if (read_stdin || lseek(fd, (off_t)0L, SEEK_SET) != 0)
+ {
+ /* Can't rewind the file, give up. */
+ error = TRUE;
+ goto failed;
+ }
+ /* Delete the previously read lines. */
+ while (lnum > from)
+ ml_delete(lnum--, FALSE);
+ file_rewind = FALSE;
+#ifdef FEAT_MBYTE
+ if (newfile)
+ curbuf->b_p_bomb = FALSE;
+ conv_error = FALSE;
+#endif
+ }
+
+ /*
+ * When retrying with another "fenc" and the first time "fileformat"
+ * will be reset.
+ */
+ if (keep_fileformat)
+ keep_fileformat = FALSE;
+ else
+ {
+ if (eap != NULL && eap->force_ff != 0)
+ fileformat = get_fileformat_force(curbuf, eap);
+ else if (curbuf->b_p_bin)
+ fileformat = EOL_UNIX; /* binary: use Unix format */
+ else if (*p_ffs == NUL)
+ fileformat = get_fileformat(curbuf);/* use format from buffer */
+ else
+ fileformat = EOL_UNKNOWN; /* detect from file */
+ }
+
+#ifdef FEAT_MBYTE
+# ifdef USE_ICONV
+ if (iconv_fd != (iconv_t)-1)
+ {
+ /* aborted conversion with iconv(), close the descriptor */
+ iconv_close(iconv_fd);
+ iconv_fd = (iconv_t)-1;
+ }
+# endif
+
+ if (advance_fenc)
+ {
+ /*
+ * Try the next entry in 'fileencodings'.
+ */
+ advance_fenc = FALSE;
+
+ if (eap != NULL && eap->force_enc != 0)
+ {
+ /* Conversion given with "++cc=" wasn't possible, read
+ * without conversion. */
+ notconverted = TRUE;
+ conv_error = FALSE;
+ if (fenc_alloced)
+ vim_free(fenc);
+ fenc = (char_u *)"";
+ fenc_alloced = FALSE;
+ }
+ else
+ {
+ if (fenc_alloced)
+ vim_free(fenc);
+ if (fenc_next != NULL)
+ {
+ fenc = next_fenc(&fenc_next);
+ fenc_alloced = (fenc_next != NULL);
+ }
+ else
+ {
+ fenc = (char_u *)"";
+ fenc_alloced = FALSE;
+ }
+ }
+ if (tmpname != NULL)
+ {
+ mch_remove(tmpname); /* delete converted file */
+ vim_free(tmpname);
+ tmpname = NULL;
+ }
+ }
+
+ /*
+ * Conversion is required when the encoding of the file is different
+ * from 'encoding' or 'encoding' is UTF-16, UCS-2 or UCS-4 (requires
+ * conversion to UTF-8).
+ */
+ fio_flags = 0;
+ converted = (*fenc != NUL && !same_encoding(p_enc, fenc));
+ if (converted || enc_unicode != 0)
+ {
+
+ /* "ucs-bom" means we need to check the first bytes of the file
+ * for a BOM. */
+ if (STRCMP(fenc, ENC_UCSBOM) == 0)
+ fio_flags = FIO_UCSBOM;
+
+ /*
+ * Check if UCS-2/4 or Latin1 to UTF-8 conversion needs to be
+ * done. This is handled below after read(). Prepare the
+ * fio_flags to avoid having to parse the string each time.
+ * Also check for Unicode to Latin1 conversion, because iconv()
+ * appears not to handle this correctly. This works just like
+ * conversion to UTF-8 except how the resulting character is put in
+ * the buffer.
+ */
+ else if (enc_utf8 || STRCMP(p_enc, "latin1") == 0)
+ fio_flags = get_fio_flags(fenc);
+
+# ifdef WIN3264
+ /*
+ * Conversion from an MS-Windows codepage to UTF-8 or another codepage
+ * is handled with MultiByteToWideChar().
+ */
+ if (fio_flags == 0)
+ fio_flags = get_win_fio_flags(fenc);
+# endif
+
+# ifdef MACOS_X
+ /* Conversion from Apple MacRoman to latin1 or UTF-8 */
+ if (fio_flags == 0)
+ fio_flags = get_mac_fio_flags(fenc);
+# endif
+
+# ifdef USE_ICONV
+ /*
+ * Try using iconv() if we can't convert internally.
+ */
+ if (fio_flags == 0
+# ifdef FEAT_EVAL
+ && !did_iconv
+# endif
+ )
+ iconv_fd = (iconv_t)my_iconv_open(
+ enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc);
+# endif
+
+# ifdef FEAT_EVAL
+ /*
+ * Use the 'charconvert' expression when conversion is required
+ * and we can't do it internally or with iconv().
+ */
+ if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
+# ifdef USE_ICONV
+ && iconv_fd == (iconv_t)-1
+# endif
+ )
+ {
+# ifdef USE_ICONV
+ did_iconv = FALSE;
+# endif
+ /* Skip conversion when it's already done (retry for wrong
+ * "fileformat"). */
+ if (tmpname == NULL)
+ {
+ tmpname = readfile_charconvert(fname, fenc, &fd);
+ if (tmpname == NULL)
+ {
+ /* Conversion failed. Try another one. */
+ advance_fenc = TRUE;
+ if (fd < 0)
+ {
+ /* Re-opening the original file failed! */
+ EMSG(_("E202: Conversion made file unreadable!"));
+ error = TRUE;
+ goto failed;
+ }
+ goto retry;
+ }
+ }
+ }
+ else
+# endif
+ {
+ if (fio_flags == 0
+# ifdef USE_ICONV
+ && iconv_fd == (iconv_t)-1
+# endif
+ )
+ {
+ /* Conversion wanted but we can't.
+ * Try the next conversion in 'fileencodings' */
+ advance_fenc = TRUE;
+ goto retry;
+ }
+ }
+ }
+
+ /* Set can_retry when it's possible to rewind the file and try with
+ * another "fenc" value. It's FALSE when no other "fenc" to try, reading
+ * stdin or "fenc" was specified with "++enc=". */
+ can_retry = (*fenc != NUL && !read_stdin
+ && (eap == NULL || eap->force_enc == 0));
+#endif
+
+ if (!skip_read)
+ {
+ linerest = 0;
+ filesize = 0;
+ skip_count = lines_to_skip;
+ read_count = lines_to_read;
+#ifdef FEAT_MBYTE
+ conv_restlen = 0;
+#endif
+ }
+
+ while (!error && !got_int)
+ {
+ /*
+ * We allocate as much space for the file as we can get, plus
+ * space for the old line plus room for one terminating NUL.
+ * The amount is limited by the fact that read() only can read
+ * upto max_unsigned characters (and other things).
+ */
+#if SIZEOF_INT <= 2
+ if (linerest >= 0x7ff0)
+ {
+ ++split;
+ *ptr = NL; /* split line by inserting a NL */
+ size = 1;
+ }
+ else
+#endif
+ {
+ if (!skip_read)
+ {
+#if SIZEOF_INT > 2
+# ifdef __TANDEM
+ size = SSIZE_MAX; /* use max I/O size, 52K */
+# else
+ size = 0x10000L; /* use buffer >= 64K */
+# endif
+#else
+ size = 0x7ff0L - linerest; /* limit buffer to 32K */
+#endif
+
+ for ( ; size >= 10; size = (long_u)size >> 1)
+ {
+ if ((new_buffer = lalloc((long_u)(size + linerest + 1),
+ FALSE)) != NULL)
+ break;
+ }
+ if (new_buffer == NULL)
+ {
+ do_outofmem_msg((long_u)(size * 2 + linerest + 1));
+ error = TRUE;
+ break;
+ }
+ if (linerest) /* copy characters from the previous buffer */
+ mch_memmove(new_buffer, ptr - linerest, (size_t)linerest);
+ vim_free(buffer);
+ buffer = new_buffer;
+ ptr = buffer + linerest;
+ line_start = buffer;
+
+#ifdef FEAT_MBYTE
+ /* May need room to translate into.
+ * For iconv() we don't really know the required space, use a
+ * factor ICONV_MULT.
+ * latin1 to utf-8: 1 byte becomes up to 2 bytes
+ * utf-16 to utf-8: 2 bytes become up to 3 bytes, 4 bytes
+ * become up to 4 bytes, size must be multiple of 2
+ * ucs-2 to utf-8: 2 bytes become up to 3 bytes, size must be
+ * multiple of 2
+ * ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
+ * multiple of 4 */
+ real_size = size;
+# ifdef USE_ICONV
+ if (iconv_fd != (iconv_t)-1)
+ size = size / ICONV_MULT;
+ else
+# endif
+ if (fio_flags & FIO_LATIN1)
+ size = size / 2;
+ else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
+ size = (size * 2 / 3) & ~1;
+ else if (fio_flags & FIO_UCS4)
+ size = (size * 2 / 3) & ~3;
+ else if (fio_flags == FIO_UCSBOM)
+ size = size / ICONV_MULT; /* worst case */
+# ifdef WIN3264
+ else if (fio_flags & FIO_CODEPAGE)
+ size = size / ICONV_MULT; /* also worst case */
+# endif
+# ifdef MACOS_X
+ else if (fio_flags & FIO_MACROMAN)
+ size = size / ICONV_MULT; /* also worst case */
+# endif
+#endif
+
+#ifdef FEAT_MBYTE
+ if (conv_restlen > 0)
+ {
+ /* Insert unconverted bytes from previous line. */
+ mch_memmove(ptr, conv_rest, conv_restlen);
+ ptr += conv_restlen;
+ size -= conv_restlen;
+ }
+#endif
+
+ if (read_buffer)
+ {
+ /*
+ * Read bytes from curbuf. Used for converting text read
+ * from stdin.
+ */
+ if (read_buf_lnum > from)
+ size = 0;
+ else
+ {
+ int n, ni;
+ long tlen;
+
+ tlen = 0;
+ for (;;)
+ {
+ p = ml_get(read_buf_lnum) + read_buf_col;
+ n = (int)STRLEN(p);
+ if ((int)tlen + n + 1 > size)
+ {
+ /* Filled up to "size", append partial line.
+ * Change NL to NUL to reverse the effect done
+ * below. */
+ n = size - tlen;
+ for (ni = 0; ni < n; ++ni)
+ {
+ if (p[ni] == NL)
+ ptr[tlen++] = NUL;
+ else
+ ptr[tlen++] = p[ni];
+ }
+ read_buf_col += n;
+ break;
+ }
+ else
+ {
+ /* Append whole line and new-line. Change NL
+ * to NUL to reverse the effect done below. */
+ for (ni = 0; ni < n; ++ni)
+ {
+ if (p[ni] == NL)
+ ptr[tlen++] = NUL;
+ else
+ ptr[tlen++] = p[ni];
+ }
+ ptr[tlen++] = NL;
+ read_buf_col = 0;
+ if (++read_buf_lnum > from)
+ {
+ /* When the last line didn't have an
+ * end-of-line don't add it now either. */
+ if (!curbuf->b_p_eol)
+ --tlen;
+ size = tlen;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Read bytes from the file.
+ */
+ size = vim_read(fd, ptr, size);
+ }
+
+ if (size <= 0)
+ {
+ if (size < 0) /* read error */
+ error = TRUE;
+#ifdef FEAT_MBYTE
+ else if (conv_restlen > 0)
+ /* some trailing bytes unconverted */
+ conv_error = TRUE;
+#endif
+ }
+
+#ifdef FEAT_CRYPT
+ /*
+ * At start of file: Check for magic number of encryption.
+ */
+ if (filesize == 0)
+ cryptkey = check_for_cryptkey(cryptkey, ptr, &size,
+ &filesize, newfile);
+ /*
+ * Decrypt the read bytes.
+ */
+ if (cryptkey != NULL && size > 0)
+ for (p = ptr; p < ptr + size; ++p)
+ ZDECODE(*p);
+#endif
+ }
+ skip_read = FALSE;
+
+#ifdef FEAT_MBYTE
+ /*
+ * At start of file (or after crypt magic number): Check for BOM.
+ * Also check for a BOM for other Unicode encodings, but not after
+ * converting with 'charconvert' or when a BOM has already been
+ * found.
+ */
+ if ((filesize == 0
+# ifdef FEAT_CRYPT
+ || (filesize == CRYPT_MAGIC_LEN && cryptkey != NULL)
+# endif
+ )
+ && (fio_flags == FIO_UCSBOM
+ || (!curbuf->b_p_bomb
+ && tmpname == NULL
+ && (*fenc == 'u' || (*fenc == NUL && enc_utf8)))))
+ {
+ char_u *ccname;
+ int blen;
+
+ /* no BOM detection in a short file or in binary mode */
+ if (size < 2 || curbuf->b_p_bin)
+ ccname = NULL;
+ else
+ ccname = check_for_bom(ptr, size, &blen,
+ fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags(fenc));
+ if (ccname != NULL)
+ {
+ /* Remove BOM from the text */
+ filesize += blen;
+ size -= blen;
+ mch_memmove(ptr, ptr + blen, (size_t)size);
+ if (newfile)
+ curbuf->b_p_bomb = TRUE;
+ }
+
+ if (fio_flags == FIO_UCSBOM)
+ {
+ if (ccname == NULL)
+ {
+ /* No BOM detected: retry with next encoding. */
+ advance_fenc = TRUE;
+ }
+ else
+ {
+ /* BOM detected: set "fenc" and jump back */
+ if (fenc_alloced)
+ vim_free(fenc);
+ fenc = ccname;
+ fenc_alloced = FALSE;
+ }
+ /* retry reading without getting new bytes or rewinding */
+ skip_read = TRUE;
+ goto retry;
+ }
+ }
+#endif
+ /*
+ * Break here for a read error or end-of-file.
+ */
+ if (size <= 0)
+ break;
+
+#ifdef FEAT_MBYTE
+
+ /* Include not converted bytes. */
+ ptr -= conv_restlen;
+ size += conv_restlen;
+ conv_restlen = 0;
+
+# ifdef USE_ICONV
+ if (iconv_fd != (iconv_t)-1)
+ {
+ /*
+ * Attempt conversion of the read bytes to 'encoding' using
+ * iconv().
+ */
+ const char *fromp;
+ char *top;
+ size_t from_size;
+ size_t to_size;
+
+ fromp = (char *)ptr;
+ from_size = size;
+ ptr += size;
+ top = (char *)ptr;
+ to_size = real_size - size;
+
+ /*
+ * If there is conversion error or not enough room try using
+ * another conversion.
+ */
+ if ((iconv(iconv_fd, (void *)&fromp, &from_size, &top, &to_size)
+ == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
+ || from_size > CONV_RESTLEN)
+ goto rewind_retry;
+
+ if (from_size > 0)
+ {
+ /* Some remaining characters, keep them for the next
+ * round. */
+ mch_memmove(conv_rest, (char_u *)fromp, from_size);
+ conv_restlen = (int)from_size;
+ }
+
+ /* move the linerest to before the converted characters */
+ line_start = ptr - linerest;
+ mch_memmove(line_start, buffer, (size_t)linerest);
+ size = (long)((char_u *)top - ptr);
+ }
+# endif
+
+# ifdef WIN3264
+ if (fio_flags & FIO_CODEPAGE)
+ {
+ /*
+ * Conversion from an MS-Windows codepage or UTF-8 to UTF-8 or
+ * a codepage, using standard MS-Windows functions.
+ * 1. find out how many ucs-2 characters there are.
+ * 2. convert from 'fileencoding' to ucs-2
+ * 3. convert from ucs-2 to 'encoding'
+ */
+ char_u *ucsp;
+ size_t from_size = size;
+ int needed;
+ char_u *p;
+ int u8c;
+
+ /*
+ * 1. find out how many ucs-2 characters there are.
+ */
+# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
+ if (FIO_GET_CP(fio_flags) == CP_UTF8)
+ {
+ int l, flen;
+
+ /* Handle CP_UTF8 ourselves to be able to handle trailing
+ * bytes properly. First find out the number of
+ * characters and check for trailing bytes. */
+ needed = 0;
+ p = ptr;
+ for (flen = from_size; flen > 0; flen -= l)
+ {
+ l = utf_ptr2len_check_len(p, flen);
+ if (l > flen) /* incomplete char */
+ {
+ if (l > CONV_RESTLEN)
+ /* weird overlong byte sequence */
+ goto rewind_retry;
+ mch_memmove(conv_rest, p, flen);
+ conv_restlen = flen;
+ from_size -= flen;
+ break;
+ }
+ if (l == 1 && *p >= 0x80) /* illegal byte */
+ goto rewind_retry;
+ ++needed;
+ p += l;
+ }
+ }
+ else
+# endif
+ {
+ /* We can't tell if the last byte of an MBCS string is
+ * valid and MultiByteToWideChar() returns zero if it
+ * isn't. Try the whole string, and if that fails, bump
+ * the last byte into conv_rest and try again. */
+ needed = MultiByteToWideChar(FIO_GET_CP(fio_flags),
+ MB_ERR_INVALID_CHARS, (LPCSTR)ptr, from_size,
+ NULL, 0);
+ if (needed == 0)
+ {
+ conv_rest[0] = ptr[from_size - 1];
+ conv_restlen = 1;
+ --from_size;
+ needed = MultiByteToWideChar(FIO_GET_CP(fio_flags),
+ MB_ERR_INVALID_CHARS, (LPCSTR)ptr, from_size,
+ NULL, 0);
+ }
+
+ /* If there really is a conversion error, try using another
+ * conversion. */
+ if (needed == 0)
+ goto rewind_retry;
+ }
+
+ /*
+ * 2. convert from 'fileencoding' to ucs-2
+ *
+ * Put the result of conversion to UCS-2 at the end of the
+ * buffer, then convert from UCS-2 to UTF-8 or "enc_codepage"
+ * into the start of the buffer. If there is not enough space
+ * just fail, there is probably something wrong.
+ */
+ ucsp = ptr + real_size - (needed * sizeof(WCHAR));
+ if (ucsp < ptr + size)
+ goto rewind_retry;
+
+# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
+ if (FIO_GET_CP(fio_flags) == CP_UTF8)
+ {
+ int l, flen;
+
+ /* Convert from utf-8 to ucs-2. */
+ needed = 0;
+ p = ptr;
+ for (flen = from_size; flen > 0; flen -= l)
+ {
+ l = utf_ptr2len_check_len(p, flen);
+ u8c = utf_ptr2char(p);
+ ucsp[needed * 2] = (u8c & 0xff);
+ ucsp[needed * 2 + 1] = (u8c >> 8);
+ ++needed;
+ p += l;
+ }
+ }
+ else
+# endif
+ needed = MultiByteToWideChar(FIO_GET_CP(fio_flags),
+ MB_ERR_INVALID_CHARS, (LPCSTR)ptr,
+ from_size, (LPWSTR)ucsp, needed);
+
+ /*
+ * 3. convert from ucs-2 to 'encoding'
+ */
+ if (enc_utf8)
+ {
+ /* From UCS-2 to UTF-8. Cannot fail. */
+ p = ptr;
+ for (; needed > 0; --needed)
+ {
+ u8c = *ucsp++;
+ u8c += (*ucsp++ << 8);
+ p += utf_char2bytes(u8c, p);
+ }
+ size = p - ptr;
+ }
+ else
+ {
+ BOOL bad = FALSE;
+
+ /* From UCS-2 to "enc_codepage". If the conversion uses
+ * the default character "?", the data doesn't fit in this
+ * encoding, so fail (unless forced). */
+ size = WideCharToMultiByte(enc_codepage, 0,
+ (LPCWSTR)ucsp, needed,
+ (LPSTR)ptr, real_size, "?", &bad);
+ if (bad && !keep_dest_enc)
+ goto rewind_retry;
+ }
+ }
+ else
+# endif
+# ifdef MACOS_X
+ if (fio_flags & FIO_MACROMAN)
+ {
+ /*
+ * Conversion from Apple MacRoman char encoding to UTF-8 or
+ * latin1, using standard Carbon framework.
+ */
+ CFStringRef cfstr;
+ CFRange r;
+ CFIndex len = size;
+
+ /* MacRoman is an 8-bit encoding, no need to move bytes to
+ * conv_rest[]. */
+ cfstr = CFStringCreateWithBytes(NULL, ptr, len,
+ kCFStringEncodingMacRoman, 0);
+ /*
+ * If there is a conversion error, try using another
+ * conversion.
+ */
+ if (cfstr == NULL)
+ goto rewind_retry;
+
+ r.location = 0;
+ r.length = CFStringGetLength(cfstr);
+ if (r.length != CFStringGetBytes(cfstr, r,
+ (enc_utf8) ? kCFStringEncodingUTF8
+ : kCFStringEncodingISOLatin1,
+ 0, /* no lossy conversion */
+ 0, /* not external representation */
+ ptr + size, real_size - size, &len))
+ {
+ CFRelease(cfstr);
+ goto rewind_retry;
+ }
+ CFRelease(cfstr);
+ mch_memmove(ptr, ptr + size, len);
+ size = len;
+ }
+ else
+# endif
+ if (fio_flags != 0)
+ {
+ int u8c;
+ char_u *dest;
+ char_u *tail = NULL;
+
+ /*
+ * "enc_utf8" set: Convert Unicode or Latin1 to UTF-8.
+ * "enc_utf8" not set: Convert Unicode to Latin1.
+ * Go from end to start through the buffer, because the number
+ * of bytes may increase.
+ * "dest" points to after where the UTF-8 bytes go, "p" points
+ * to after the next character to convert.
+ */
+ dest = ptr + real_size;
+ if (fio_flags == FIO_LATIN1 || fio_flags == FIO_UTF8)
+ {
+ p = ptr + size;
+ if (fio_flags == FIO_UTF8)
+ {
+ /* Check for a trailing incomplete UTF-8 sequence */
+ tail = ptr + size - 1;
+ while (tail > ptr && (*tail & 0xc0) == 0x80)
+ --tail;
+ if (tail + utf_byte2len(*tail) <= ptr + size)
+ tail = NULL;
+ else
+ p = tail;
+ }
+ }
+ else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
+ {
+ /* Check for a trailing byte */
+ p = ptr + (size & ~1);
+ if (size & 1)
+ tail = p;
+ if ((fio_flags & FIO_UTF16) && p > ptr)
+ {
+ /* Check for a trailing leading word */
+ if (fio_flags & FIO_ENDIAN_L)
+ {
+ u8c = (*--p << 8);
+ u8c += *--p;
+ }
+ else
+ {
+ u8c = *--p;
+ u8c += (*--p << 8);
+ }
+ if (u8c >= 0xd800 && u8c <= 0xdbff)
+ tail = p;
+ else
+ p += 2;
+ }
+ }
+ else /* FIO_UCS4 */
+ {
+ /* Check for trailing 1, 2 or 3 bytes */
+ p = ptr + (size & ~3);
+ if (size & 3)
+ tail = p;
+ }
+
+ /* If there is a trailing incomplete sequence move it to
+ * conv_rest[]. */
+ if (tail != NULL)
+ {
+ conv_restlen = (int)((ptr + size) - tail);
+ mch_memmove(conv_rest, (char_u *)tail, conv_restlen);
+ size -= conv_restlen;
+ }
+
+
+ while (p > ptr)
+ {
+ if (fio_flags & FIO_LATIN1)
+ u8c = *--p;
+ else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
+ {
+ if (fio_flags & FIO_ENDIAN_L)
+ {
+ u8c = (*--p << 8);
+ u8c += *--p;
+ }
+ else
+ {
+ u8c = *--p;
+ u8c += (*--p << 8);
+ }
+ if ((fio_flags & FIO_UTF16)
+ && u8c >= 0xdc00 && u8c <= 0xdfff)
+ {
+ int u16c;
+
+ if (p == ptr)
+ {
+ /* Missing leading word. */
+ if (can_retry)
+ goto rewind_retry;
+ conv_error = TRUE;
+ }
+
+ /* found second word of double-word, get the first
+ * word and compute the resulting character */
+ if (fio_flags & FIO_ENDIAN_L)
+ {
+ u16c = (*--p << 8);
+ u16c += *--p;
+ }
+ else
+ {
+ u16c = *--p;
+ u16c += (*--p << 8);
+ }
+ /* Check if the word is indeed a leading word. */
+ if (u16c < 0xd800 || u16c > 0xdbff)
+ {
+ if (can_retry)
+ goto rewind_retry;
+ conv_error = TRUE;
+ }
+ u8c = 0x10000 + ((u16c & 0x3ff) << 10)
+ + (u8c & 0x3ff);
+ }
+ }
+ else if (fio_flags & FIO_UCS4)
+ {
+ if (fio_flags & FIO_ENDIAN_L)
+ {
+ u8c = (*--p << 24);
+ u8c += (*--p << 16);
+ u8c += (*--p << 8);
+ u8c += *--p;
+ }
+ else /* big endian */
+ {
+ u8c = *--p;
+ u8c += (*--p << 8);
+ u8c += (*--p << 16);
+ u8c += (*--p << 24);
+ }
+ }
+ else /* UTF-8 */
+ {
+ if (*--p < 0x80)
+ u8c = *p;
+ else
+ {
+ len = utf_head_off(ptr, p);
+ if (len == 0)
+ {
+ /* Not a valid UTF-8 character, retry with
+ * another fenc when possible, otherwise just
+ * report the error. */
+ if (can_retry)
+ goto rewind_retry;
+ conv_error = TRUE;
+ }
+ p -= len;
+ u8c = utf_ptr2char(p);
+ }
+ }
+ if (enc_utf8) /* produce UTF-8 */
+ {
+ dest -= utf_char2len(u8c);
+ (void)utf_char2bytes(u8c, dest);
+ }
+ else /* produce Latin1 */
+ {
+ --dest;
+ if (u8c >= 0x100)
+ {
+ /* character doesn't fit in latin1, retry with
+ * another fenc when possible, otherwise just
+ * report the error. */
+ if (can_retry && !keep_dest_enc)
+ goto rewind_retry;
+ *dest = 0xBF;
+ conv_error = TRUE;
+ }
+ else
+ *dest = u8c;
+ }
+ }
+
+ /* move the linerest to before the converted characters */
+ line_start = dest - linerest;
+ mch_memmove(line_start, buffer, (size_t)linerest);
+ size = (long)((ptr + real_size) - dest);
+ ptr = dest;
+ }
+ else if (enc_utf8 && !conv_error && !curbuf->b_p_bin)
+ {
+ /* Reading UTF-8: Check if the bytes are valid UTF-8.
+ * Need to start before "ptr" when part of the character was
+ * read in the previous read() call. */
+ for (p = ptr - utf_head_off(buffer, ptr); p < ptr + size; ++p)
+ {
+ if (*p >= 0x80)
+ {
+ len = utf_ptr2len_check(p);
+ /* A length of 1 means it's an illegal byte. Accept
+ * an incomplete character at the end though, the next
+ * read() will get the next bytes, we'll check it
+ * then. */
+ if (len == 1)
+ {
+ p += utf_byte2len(*p) - 1;
+ break;
+ }
+ p += len - 1;
+ }
+ }
+ if (p < ptr + size)
+ {
+ /* Detected a UTF-8 error. */
+ if (can_retry)
+ {
+rewind_retry:
+ /* Retry reading with another conversion. */
+# if defined(FEAT_EVAL) && defined(USE_ICONV)
+ if (*p_ccv != NUL && iconv_fd != (iconv_t)-1)
+ /* iconv() failed, try 'charconvert' */
+ did_iconv = TRUE;
+ else
+# endif
+ /* use next item from 'fileencodings' */
+ advance_fenc = TRUE;
+ file_rewind = TRUE;
+ goto retry;
+ }
+
+ /* There is no alternative fenc, just report the error. */
+# ifdef USE_ICONV
+ if (iconv_fd != (iconv_t)-1)
+ conv_error = TRUE;
+ else
+# endif
+ {
+ char_u *s;
+
+ /* Estimate the line number. */
+ illegal_byte = curbuf->b_ml.ml_line_count - linecnt + 1;
+ for (s = ptr; s < p; ++s)
+ if (*s == '\n')
+ ++illegal_byte;
+ }
+ }
+ }
+#endif
+
+ /* count the number of characters (after conversion!) */
+ filesize += size;
+
+ /*
+ * when reading the first part of a file: guess EOL type
+ */
+ if (fileformat == EOL_UNKNOWN)
+ {
+ /* First try finding a NL, for Dos and Unix */
+ if (try_dos || try_unix)
+ {
+ for (p = ptr; p < ptr + size; ++p)
+ {
+ if (*p == NL)
+ {
+ if (!try_unix
+ || (try_dos && p > ptr && p[-1] == CAR))
+ fileformat = EOL_DOS;
+ else
+ fileformat = EOL_UNIX;
+ break;
+ }
+ }
+
+ /* Don't give in to EOL_UNIX if EOL_MAC is more likely */
+ if (fileformat == EOL_UNIX && try_mac)
+ {
+ /* Need to reset the counters when retrying fenc. */
+ try_mac = 1;
+ try_unix = 1;
+ for (; p >= ptr && *p != CAR; p--)
+ ;
+ if (p >= ptr)
+ {
+ for (p = ptr; p < ptr + size; ++p)
+ {
+ if (*p == NL)
+ try_unix++;
+ else if (*p == CAR)
+ try_mac++;
+ }
+ if (try_mac > try_unix)
+ fileformat = EOL_MAC;
+ }
+ }
+ }
+
+ /* No NL found: may use Mac format */
+ if (fileformat == EOL_UNKNOWN && try_mac)
+ fileformat = EOL_MAC;
+
+ /* Still nothing found? Use first format in 'ffs' */
+ if (fileformat == EOL_UNKNOWN)
+ fileformat = default_fileformat();
+
+ /* if editing a new file: may set p_tx and p_ff */
+ if (newfile)
+ set_fileformat(fileformat, OPT_LOCAL);
+ }
+ }
+
+ /*
+ * This loop is executed once for every character read.
+ * Keep it fast!
+ */
+ if (fileformat == EOL_MAC)
+ {
+ --ptr;
+ while (++ptr, --size >= 0)
+ {
+ /* catch most common case first */
+ if ((c = *ptr) != NUL && c != CAR && c != NL)
+ continue;
+ if (c == NUL)
+ *ptr = NL; /* NULs are replaced by newlines! */
+ else if (c == NL)
+ *ptr = CAR; /* NLs are replaced by CRs! */
+ else
+ {
+ if (skip_count == 0)
+ {
+ *ptr = NUL; /* end of line */
+ len = (colnr_T) (ptr - line_start + 1);
+ if (ml_append(lnum, line_start, len, newfile) == FAIL)
+ {
+ error = TRUE;
+ break;
+ }
+ ++lnum;
+ if (--read_count == 0)
+ {
+ error = TRUE; /* break loop */
+ line_start = ptr; /* nothing left to write */
+ break;
+ }
+ }
+ else
+ --skip_count;
+ line_start = ptr + 1;
+ }
+ }
+ }
+ else
+ {
+ --ptr;
+ while (++ptr, --size >= 0)
+ {
+ if ((c = *ptr) != NUL && c != NL) /* catch most common case */
+ continue;
+ if (c == NUL)
+ *ptr = NL; /* NULs are replaced by newlines! */
+ else
+ {
+ if (skip_count == 0)
+ {
+ *ptr = NUL; /* end of line */
+ len = (colnr_T)(ptr - line_start + 1);
+ if (fileformat == EOL_DOS)
+ {
+ if (ptr[-1] == CAR) /* remove CR */
+ {
+ ptr[-1] = NUL;
+ --len;
+ }
+ /*
+ * Reading in Dos format, but no CR-LF found!
+ * When 'fileformats' includes "unix", delete all
+ * the lines read so far and start all over again.
+ * Otherwise give an error message later.
+ */
+ else if (ff_error != EOL_DOS)
+ {
+ if ( try_unix
+ && !read_stdin
+ && (read_buffer
+ || lseek(fd, (off_t)0L, SEEK_SET) == 0))
+ {
+ fileformat = EOL_UNIX;
+ if (newfile)
+ set_fileformat(EOL_UNIX, OPT_LOCAL);
+ file_rewind = TRUE;
+ keep_fileformat = TRUE;
+ goto retry;
+ }
+ ff_error = EOL_DOS;
+ }
+ }
+ if (ml_append(lnum, line_start, len, newfile) == FAIL)
+ {
+ error = TRUE;
+ break;
+ }
+ ++lnum;
+ if (--read_count == 0)
+ {
+ error = TRUE; /* break loop */
+ line_start = ptr; /* nothing left to write */
+ break;
+ }
+ }
+ else
+ --skip_count;
+ line_start = ptr + 1;
+ }
+ }
+ }
+ linerest = (long)(ptr - line_start);
+ ui_breakcheck();
+ }
+
+failed:
+ /* not an error, max. number of lines reached */
+ if (error && read_count == 0)
+ error = FALSE;
+
+ /*
+ * If we get EOF in the middle of a line, note the fact and
+ * complete the line ourselves.
+ * In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
+ */
+ if (!error
+ && !got_int
+ && linerest != 0
+ && !(!curbuf->b_p_bin
+ && fileformat == EOL_DOS
+ && *line_start == Ctrl_Z
+ && ptr == line_start + 1))
+ {
+ if (newfile) /* remember for when writing */
+ curbuf->b_p_eol = FALSE;
+ *ptr = NUL;
+ if (ml_append(lnum, line_start,
+ (colnr_T)(ptr - line_start + 1), newfile) == FAIL)
+ error = TRUE;
+ else
+ read_no_eol_lnum = ++lnum;
+ }
+
+ if (newfile)
+ save_file_ff(curbuf); /* remember the current file format */
+
+#ifdef FEAT_CRYPT
+ if (cryptkey != curbuf->b_p_key)
+ vim_free(cryptkey);
+#endif
+
+#ifdef FEAT_MBYTE
+ /* If editing a new file: set 'fenc' for the current buffer. */
+ if (newfile)
+ set_string_option_direct((char_u *)"fenc", -1, fenc,
+ OPT_FREE|OPT_LOCAL);
+ if (fenc_alloced)
+ vim_free(fenc);
+# ifdef USE_ICONV
+ if (iconv_fd != (iconv_t)-1)
+ {
+ iconv_close(iconv_fd);
+ iconv_fd = (iconv_t)-1;
+ }
+# endif
+#endif
+
+ if (!read_buffer && !read_stdin)
+ close(fd); /* errors are ignored */
+ vim_free(buffer);
+
+#ifdef HAVE_DUP
+ if (read_stdin)
+ {
+ /* Use stderr for stdin, makes shell commands work. */
+ close(0);
+ dup(2);
+ }
+#endif
+
+#ifdef FEAT_MBYTE
+ if (tmpname != NULL)
+ {
+ mch_remove(tmpname); /* delete converted file */
+ vim_free(tmpname);
+ }
+#endif
+ --no_wait_return; /* may wait for return now */
+
+ /*
+ * In recovery mode everything but autocommands is skipped.
+ */
+ if (!recoverymode)
+ {
+ /* need to delete the last line, which comes from the empty buffer */
+ if (newfile && wasempty && !(curbuf->b_ml.ml_flags & ML_EMPTY))
+ {
+#ifdef FEAT_NETBEANS_INTG
+ netbeansFireChanges = 0;
+#endif
+ ml_delete(curbuf->b_ml.ml_line_count, FALSE);
+#ifdef FEAT_NETBEANS_INTG
+ netbeansFireChanges = 1;
+#endif
+ --linecnt;
+ }
+ linecnt = curbuf->b_ml.ml_line_count - linecnt;
+ if (filesize == 0)
+ linecnt = 0;
+ if (newfile || read_buffer)
+ redraw_curbuf_later(NOT_VALID);
+ else if (linecnt) /* appended at least one line */
+ appended_lines_mark(from, linecnt);
+
+#ifdef FEAT_DIFF
+ /* After reading the text into the buffer the diff info needs to be
+ * updated. */
+ if ((newfile || read_buffer))
+ diff_invalidate();
+#endif
+#ifndef ALWAYS_USE_GUI
+ /*
+ * If we were reading from the same terminal as where messages go,
+ * the screen will have been messed up.
+ * Switch on raw mode now and clear the screen.
+ */
+ if (read_stdin)
+ {
+ settmode(TMODE_RAW); /* set to raw mode */
+ starttermcap();
+ screenclear();
+ }
+#endif
+
+ if (got_int)
+ {
+ if (!(flags & READ_DUMMY))
+ {
+ filemess(curbuf, sfname, (char_u *)_(e_interr), 0);
+ if (newfile)
+ curbuf->b_p_ro = TRUE; /* must use "w!" now */
+ }
+ msg_scroll = msg_save;
+#ifdef FEAT_VIMINFO
+ check_marks_read();
+#endif
+ return OK; /* an interrupt isn't really an error */
+ }
+
+ if (!filtering && !(flags & READ_DUMMY))
+ {
+ msg_add_fname(curbuf, sfname); /* fname in IObuff with quotes */
+ c = FALSE;
+
+#ifdef UNIX
+# ifdef S_ISFIFO
+ if (S_ISFIFO(perm)) /* fifo or socket */
+ {
+ STRCAT(IObuff, _("[fifo/socket]"));
+ c = TRUE;
+ }
+# else
+# ifdef S_IFIFO
+ if ((perm & S_IFMT) == S_IFIFO) /* fifo */
+ {
+ STRCAT(IObuff, _("[fifo]"));
+ c = TRUE;
+ }
+# endif
+# ifdef S_IFSOCK
+ if ((perm & S_IFMT) == S_IFSOCK) /* or socket */
+ {
+ STRCAT(IObuff, _("[socket]"));
+ c = TRUE;
+ }
+# endif
+# endif
+#endif
+ if (curbuf->b_p_ro)
+ {
+ STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
+ c = TRUE;
+ }
+ if (read_no_eol_lnum)
+ {
+ msg_add_eol();
+ c = TRUE;
+ }
+ if (ff_error == EOL_DOS)
+ {
+ STRCAT(IObuff, _("[CR missing]"));
+ c = TRUE;
+ }
+ if (ff_error == EOL_MAC)
+ {
+ STRCAT(IObuff, _("[NL found]"));
+ c = TRUE;
+ }
+ if (split)
+ {
+ STRCAT(IObuff, _("[long lines split]"));
+ c = TRUE;
+ }
+#ifdef FEAT_MBYTE
+ if (notconverted)
+ {
+ STRCAT(IObuff, _("[NOT converted]"));
+ c = TRUE;
+ }
+ else if (converted)
+ {
+ STRCAT(IObuff, _("[converted]"));
+ c = TRUE;
+ }
+#endif
+#ifdef FEAT_CRYPT
+ if (cryptkey != NULL)
+ {
+ STRCAT(IObuff, _("[crypted]"));
+ c = TRUE;
+ }
+#endif
+#ifdef FEAT_MBYTE
+ if (conv_error)
+ {
+ STRCAT(IObuff, _("[CONVERSION ERROR]"));
+ c = TRUE;
+ }
+ else if (illegal_byte > 0)
+ {
+ sprintf((char *)IObuff + STRLEN(IObuff),
+ _("[ILLEGAL BYTE in line %ld]"), (long)illegal_byte);
+ c = TRUE;
+ }
+ else
+#endif
+ if (error)
+ {
+ STRCAT(IObuff, _("[READ ERRORS]"));
+ c = TRUE;
+ }
+ if (msg_add_fileformat(fileformat))
+ c = TRUE;
+#ifdef FEAT_CRYPT
+ if (cryptkey != NULL)
+ msg_add_lines(c, (long)linecnt, filesize - CRYPT_MAGIC_LEN);
+ else
+#endif
+ msg_add_lines(c, (long)linecnt, filesize);
+
+ vim_free(keep_msg);
+ keep_msg = NULL;
+ msg_scrolled_ign = TRUE;
+#ifdef ALWAYS_USE_GUI
+ /* Don't show the message when reading stdin, it would end up in a
+ * message box (which might be shown when exiting!) */
+ if (read_stdin || read_buffer)
+ p = msg_may_trunc(FALSE, IObuff);
+ else
+#endif
+ p = msg_trunc_attr(IObuff, FALSE, 0);
+ if (read_stdin || read_buffer || restart_edit != 0
+ || (msg_scrolled && !need_wait_return))
+ {
+ /* Need to repeat the message after redrawing when:
+ * - When reading from stdin (the screen will be cleared next).
+ * - When restart_edit is set (otherwise there will be a delay
+ * before redrawing).
+ * - When the screen was scrolled but there is no wait-return
+ * prompt. */
+ set_keep_msg(p);
+ keep_msg_attr = 0;
+ }
+ msg_scrolled_ign = FALSE;
+ }
+
+ /* with errors writing the file requires ":w!" */
+ if (newfile && (error
+#ifdef FEAT_MBYTE
+ || conv_error
+#endif
+ ))
+ curbuf->b_p_ro = TRUE;
+
+ u_clearline(); /* cannot use "U" command after adding lines */
+
+ /*
+ * In Ex mode: cursor at last new line.
+ * Otherwise: cursor at first new line.
+ */
+ if (exmode_active)
+ curwin->w_cursor.lnum = from + linecnt;
+ else
+ curwin->w_cursor.lnum = from + 1;
+ check_cursor_lnum();
+ beginline(BL_WHITE | BL_FIX); /* on first non-blank */
+
+ /*
+ * Set '[ and '] marks to the newly read lines.
+ */
+ curbuf->b_op_start.lnum = from + 1;
+ curbuf->b_op_start.col = 0;
+ curbuf->b_op_end.lnum = from + linecnt;
+ curbuf->b_op_end.col = 0;
+ }
+ msg_scroll = msg_save;
+
+#ifdef FEAT_VIMINFO
+ /*
+ * Get the marks before executing autocommands, so they can be used there.
+ */
+ check_marks_read();
+#endif
+
+#ifdef FEAT_AUTOCMD
+ /*
+ * Trick: We remember if the last line of the read didn't have
+ * an eol for when writing it again. This is required for
+ * ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
+ */
+ write_no_eol_lnum = read_no_eol_lnum;
+
+ if (!read_stdin && !read_buffer)
+ {
+ int m = msg_scroll;
+ int n = msg_scrolled;
+
+ /* Save the fileformat now, otherwise the buffer will be considered
+ * modified if the format/encoding was automatically detected. */
+ if (newfile)
+ save_file_ff(curbuf);
+
+ /*
+ * The output from the autocommands should not overwrite anything and
+ * should not be overwritten: Set msg_scroll, restore its value if no
+ * output was done.
+ */
+ msg_scroll = TRUE;
+ if (filtering)
+ apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,
+ FALSE, curbuf, eap);
+ else if (newfile)
+ apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
+ FALSE, curbuf, eap);
+ else
+ apply_autocmds_exarg(EVENT_FILEREADPOST, sfname, sfname,
+ FALSE, NULL, eap);
+ if (msg_scrolled == n)
+ msg_scroll = m;
+#ifdef FEAT_EVAL
+ if (aborting()) /* autocmds may abort script processing */
+ return FAIL;
+#endif
+ }
+#endif
+
+ if (recoverymode && error)
+ return FAIL;
+ return OK;
+}
+
+/*
+ * Fill "*eap" to force the 'fileencoding' and 'fileformat' to be equal to the
+ * buffer "buf". Used for calling readfile().
+ * Returns OK or FAIL.
+ */
+ int
+prep_exarg(eap, buf)
+ exarg_T *eap;
+ buf_T *buf;
+{
+ eap->cmd = alloc((unsigned)(STRLEN(buf->b_p_ff)
+#ifdef FEAT_MBYTE
+ + STRLEN(buf->b_p_fenc)
+#endif
+ + 15));
+ if (eap->cmd == NULL)
+ return FAIL;
+
+#ifdef FEAT_MBYTE
+ sprintf((char *)eap->cmd, "e ++ff=%s ++enc=%s", buf->b_p_ff, buf->b_p_fenc);
+ eap->force_enc = 14 + (int)STRLEN(buf->b_p_ff);
+#else
+ sprintf((char *)eap->cmd, "e ++ff=%s", buf->b_p_ff);
+#endif
+ eap->force_ff = 7;
+ return OK;
+}
+
+#ifdef FEAT_MBYTE
+/*
+ * Find next fileencoding to use from 'fileencodings'.
+ * "pp" points to fenc_next. It's advanced to the next item.
+ * When there are no more items, an empty string is returned and *pp is set to
+ * NULL.
+ * When *pp is not set to NULL, the result is in allocated memory.
+ */
+ static char_u *
+next_fenc(pp)
+ char_u **pp;
+{
+ char_u *p;
+ char_u *r;
+
+ if (**pp == NUL)
+ {
+ *pp = NULL;
+ return (char_u *)"";
+ }
+ p = vim_strchr(*pp, ',');
+ if (p == NULL)
+ {
+ r = enc_canonize(*pp);
+ *pp += STRLEN(*pp);
+ }
+ else
+ {
+ r = vim_strnsave(*pp, (int)(p - *pp));
+ *pp = p + 1;
+ if (r != NULL)
+ {
+ p = enc_canonize(r);
+ vim_free(r);
+ r = p;
+ }
+ }
+ if (r == NULL) /* out of memory */
+ {
+ r = (char_u *)"";
+ *pp = NULL;
+ }
+ return r;
+}
+
+# ifdef FEAT_EVAL
+/*
+ * Convert a file with the 'charconvert' expression.
+ * This closes the file which is to be read, converts it and opens the
+ * resulting file for reading.
+ * Returns name of the resulting converted file (the caller should delete it
+ * after reading it).
+ * Returns NULL if the conversion failed ("*fdp" is not set) .
+ */
+ static char_u *
+readfile_charconvert(fname, fenc, fdp)
+ char_u *fname; /* name of input file */
+ char_u *fenc; /* converted from */
+ int *fdp; /* in/out: file descriptor of file */
+{
+ char_u *tmpname;
+ char_u *errmsg = NULL;
+
+ tmpname = vim_tempname('r');
+ if (tmpname == NULL)
+ errmsg = (char_u *)_("Can't find temp file for conversion");
+ else
+ {
+ close(*fdp); /* close the input file, ignore errors */
+ *fdp = -1;
+ if (eval_charconvert(fenc, enc_utf8 ? (char_u *)"utf-8" : p_enc,
+ fname, tmpname) == FAIL)
+ errmsg = (char_u *)_("Conversion with 'charconvert' failed");
+ if (errmsg == NULL && (*fdp = mch_open((char *)tmpname,
+ O_RDONLY | O_EXTRA, 0)) < 0)
+ errmsg = (char_u *)_("can't read output of 'charconvert'");
+ }
+
+ if (errmsg != NULL)
+ {
+ /* Don't use emsg(), it breaks mappings, the retry with
+ * another type of conversion might still work. */
+ MSG(errmsg);
+ if (tmpname != NULL)
+ {
+ mch_remove(tmpname); /* delete converted file */
+ vim_free(tmpname);
+ tmpname = NULL;
+ }
+ }
+
+ /* If the input file is closed, open it (caller should check for error). */
+ if (*fdp < 0)
+ *fdp = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
+
+ return tmpname;
+}
+# endif
+
+#endif
+
+#ifdef FEAT_VIMINFO
+/*
+ * Read marks for the current buffer from the viminfo file, when we support
+ * buffer marks and the buffer has a name.
+ */
+ static void
+check_marks_read()
+{
+ if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0
+ && curbuf->b_ffname != NULL)
+ read_viminfo(NULL, FALSE, TRUE, FALSE);
+
+ /* Always set b_marks_read; needed when 'viminfo' is changed to include
+ * the ' parameter after opening a buffer. */
+ curbuf->b_marks_read = TRUE;
+}
+#endif
+
+#ifdef FEAT_CRYPT
+/*
+ * Check for magic number used for encryption.
+ * If found, the magic number is removed from ptr[*sizep] and *sizep and
+ * *filesizep are updated.
+ * Return the (new) encryption key, NULL for no encryption.
+ */
+ static char_u *
+check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile)
+ char_u *cryptkey; /* previous encryption key or NULL */
+ char_u *ptr; /* pointer to read bytes */
+ long *sizep; /* length of read bytes */
+ long *filesizep; /* nr of bytes used from file */
+ int newfile; /* editing a new buffer */
+{
+ if (*sizep >= CRYPT_MAGIC_LEN
+ && STRNCMP(ptr, CRYPT_MAGIC, CRYPT_MAGIC_LEN) == 0)
+ {
+ if (cryptkey == NULL)
+ {
+ if (*curbuf->b_p_key)
+ cryptkey = curbuf->b_p_key;
+ else
+ {
+ /* When newfile is TRUE, store the typed key
+ * in the 'key' option and don't free it. */
+ cryptkey = get_crypt_key(newfile, FALSE);
+ /* check if empty key entered */
+ if (cryptkey != NULL && *cryptkey == NUL)
+ {
+ if (cryptkey != curbuf->b_p_key)
+ vim_free(cryptkey);
+ cryptkey = NULL;
+ }
+ }
+ }
+
+ if (cryptkey != NULL)
+ {
+ crypt_init_keys(cryptkey);
+
+ /* Remove magic number from the text */
+ *filesizep += CRYPT_MAGIC_LEN;
+ *sizep -= CRYPT_MAGIC_LEN;
+ mch_memmove(ptr, ptr + CRYPT_MAGIC_LEN, (size_t)*sizep);
+ }
+ }
+ /* When starting to edit a new file which does not have
+ * encryption, clear the 'key' option, except when
+ * starting up (called with -x argument) */
+ else if (newfile && *curbuf->b_p_key && !starting)
+ set_option_value((char_u *)"key", 0L, (char_u *)"", OPT_LOCAL);
+
+ return cryptkey;
+}
+#endif
+
+#ifdef UNIX
+ static void
+set_file_time(fname, atime, mtime)
+ char_u *fname;
+ time_t atime; /* access time */
+ time_t mtime; /* modification time */
+{
+# if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
+ struct utimbuf buf;
+
+ buf.actime = atime;
+ buf.modtime = mtime;
+ (void)utime((char *)fname, &buf);
+# else
+# if defined(HAVE_UTIMES)
+ struct timeval tvp[2];
+
+ tvp[0].tv_sec = atime;
+ tvp[0].tv_usec = 0;
+ tvp[1].tv_sec = mtime;
+ tvp[1].tv_usec = 0;
+# ifdef NeXT
+ (void)utimes((char *)fname, tvp);
+# else
+ (void)utimes((char *)fname, (const struct timeval *)&tvp);
+# endif
+# endif
+# endif
+}
+#endif /* UNIX */
+
+/*
+ * buf_write() - write to file 'fname' lines 'start' through 'end'
+ *
+ * We do our own buffering here because fwrite() is so slow.
+ *
+ * If forceit is true, we don't care for errors when attempting backups (jw).
+ * In case of an error everything possible is done to restore the original file.
+ * But when forceit is TRUE, we risk loosing it.
+ * When reset_changed is TRUE and start == 1 and end ==
+ * curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
+ *
+ * This function must NOT use NameBuff (because it's called by autowrite()).
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+buf_write(buf, fname, sfname, start, end, eap, append, forceit,
+ reset_changed, filtering)
+ buf_T *buf;
+ char_u *fname;
+ char_u *sfname;
+ linenr_T start, end;
+ exarg_T *eap; /* for forced 'ff' and 'fenc', can be
+ NULL! */
+ int append;
+ int forceit;
+ int reset_changed;
+ int filtering;
+{
+ int fd;
+ char_u *backup = NULL;
+ int backup_copy = FALSE; /* copy the original file? */
+ int dobackup;
+ char_u *ffname;
+ char_u *wfname = NULL; /* name of file to write to */
+ char_u *s;
+ char_u *ptr;
+ char_u c;
+ int len;
+ linenr_T lnum;
+ long nchars;
+ char_u *errmsg = NULL;
+ char_u *errnum = NULL;
+ char_u *buffer;
+ char_u smallbuf[SMBUFSIZE];
+ char_u *backup_ext;
+ int bufsize;
+ long perm; /* file permissions */
+ int retval = OK;
+ int newfile = FALSE; /* TRUE if file doesn't exist yet */
+ int msg_save = msg_scroll;
+ int overwriting; /* TRUE if writing over original */
+ int no_eol = FALSE; /* no end-of-line written */
+ int device = FALSE; /* writing to a device */
+ struct stat st_old;
+ int prev_got_int = got_int;
+ int file_readonly = FALSE; /* overwritten file is read-only */
+ static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
+#if defined(UNIX) || defined(__EMX__XX) /*XXX fix me sometime? */
+ int made_writable = FALSE; /* 'w' bit has been set */
+#endif
+ /* writing everything */
+ int whole = (start == 1 && end == buf->b_ml.ml_line_count);
+#ifdef FEAT_AUTOCMD
+ linenr_T old_line_count = buf->b_ml.ml_line_count;
+#endif
+ int attr;
+ int fileformat;
+ int write_bin;
+ struct bw_info write_info; /* info for buf_write_bytes() */
+#ifdef FEAT_MBYTE
+ int converted = FALSE;
+ int notconverted = FALSE;
+ char_u *fenc; /* effective 'fileencoding' */
+ char_u *fenc_tofree = NULL; /* allocated "fenc" */
+#endif
+#ifdef HAS_BW_FLAGS
+ int wb_flags = 0;
+#endif
+#ifdef HAVE_ACL
+ vim_acl_T acl = NULL; /* ACL copied from original file to
+ backup or new file */
+#endif
+
+ if (fname == NULL || *fname == NUL) /* safety check */
+ return FAIL;
+
+ /*
+ * Disallow writing from .exrc and .vimrc in current directory for
+ * security reasons.
+ */
+ if (check_secure())
+ return FAIL;
+
+ /* Avoid a crash for a long name. */
+ if (STRLEN(fname) >= MAXPATHL)
+ {
+ EMSG(_(e_longname));
+ return FAIL;
+ }
+
+#ifdef FEAT_MBYTE
+ /* must init bw_conv_buf and bw_iconv_fd before jumping to "fail" */
+ write_info.bw_conv_buf = NULL;
+ write_info.bw_conv_error = FALSE;
+ write_info.bw_restlen = 0;
+# ifdef USE_ICONV
+ write_info.bw_iconv_fd = (iconv_t)-1;
+# endif
+#endif
+
+ /*
+ * If there is no file name yet, use the one for the written file.
+ * BF_NOTEDITED is set to reflect this (in case the write fails).
+ * Don't do this when the write is for a filter command.
+ * Only do this when 'cpoptions' contains the 'f' flag.
+ */
+ if (reset_changed
+ && whole
+ && buf == curbuf
+ && curbuf->b_ffname == NULL
+ && !filtering
+ && vim_strchr(p_cpo, CPO_FNAMEW) != NULL)
+ {
+#ifdef FEAT_AUTOCMD
+ /* It's like the unnamed buffer is deleted.... */
+ if (curbuf->b_p_bl)
+ apply_autocmds(EVENT_BUFDELETE, NULL, NULL, FALSE, curbuf);
+ apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, FALSE, curbuf);
+#ifdef FEAT_EVAL
+ if (aborting()) /* autocmds may abort script processing */
+ return FAIL;
+#endif
+#endif
+ if (setfname(curbuf, fname, sfname, FALSE) == OK)
+ curbuf->b_flags |= BF_NOTEDITED;
+#ifdef FEAT_AUTOCMD
+ /* ....and a new named one is created */
+ apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, curbuf);
+ if (curbuf->b_p_bl)
+ apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, curbuf);
+#endif
+ }
+
+ if (sfname == NULL)
+ sfname = fname;
+ /*
+ * For Unix: Use the short file name whenever possible.
+ * Avoids problems with networks and when directory names are changed.
+ * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
+ * another directory, which we don't detect
+ */
+ ffname = fname; /* remember full fname */
+#ifdef UNIX
+ fname = sfname;
+#endif
+
+ if (buf->b_ffname != NULL && fnamecmp(ffname, buf->b_ffname) == 0)
+ overwriting = TRUE;
+ else
+ overwriting = FALSE;
+
+ if (exiting)
+ settmode(TMODE_COOK); /* when exiting allow typahead now */
+
+ ++no_wait_return; /* don't wait for return yet */
+
+ /*
+ * Set '[ and '] marks to the lines to be written.
+ */
+ buf->b_op_start.lnum = start;
+ buf->b_op_start.col = 0;
+ buf->b_op_end.lnum = end;
+ buf->b_op_end.col = 0;
+
+#ifdef FEAT_AUTOCMD
+ {
+ aco_save_T aco;
+ int buf_ffname = FALSE;
+ int buf_sfname = FALSE;
+ int buf_fname_f = FALSE;
+ int buf_fname_s = FALSE;
+ int did_cmd = FALSE;
+
+ /*
+ * Apply PRE aucocommands.
+ * Set curbuf to the buffer to be written.
+ * Careful: The autocommands may call buf_write() recursively!
+ */
+ if (ffname == buf->b_ffname)
+ buf_ffname = TRUE;
+ if (sfname == buf->b_sfname)
+ buf_sfname = TRUE;
+ if (fname == buf->b_ffname)
+ buf_fname_f = TRUE;
+ if (fname == buf->b_sfname)
+ buf_fname_s = TRUE;
+
+ /* set curwin/curbuf to buf and save a few things */
+ aucmd_prepbuf(&aco, buf);
+
+ if (append)
+ {
+ if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD,
+ sfname, sfname, FALSE, curbuf, eap)))
+ apply_autocmds_exarg(EVENT_FILEAPPENDPRE,
+ sfname, sfname, FALSE, curbuf, eap);
+ }
+ else if (filtering)
+ {
+ apply_autocmds_exarg(EVENT_FILTERWRITEPRE,
+ NULL, sfname, FALSE, curbuf, eap);
+ }
+ else if (reset_changed && whole)
+ {
+ if (!(did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD,
+ sfname, sfname, FALSE, curbuf, eap)))
+ apply_autocmds_exarg(EVENT_BUFWRITEPRE,
+ sfname, sfname, FALSE, curbuf, eap);
+ }
+ else
+ {
+ if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD,
+ sfname, sfname, FALSE, curbuf, eap)))
+ apply_autocmds_exarg(EVENT_FILEWRITEPRE,
+ sfname, sfname, FALSE, curbuf, eap);
+ }
+
+ /* restore curwin/curbuf and a few other things */
+ aucmd_restbuf(&aco);
+
+ /*
+ * In three situations we return here and don't write the file:
+ * 1. the autocommands deleted or unloaded the buffer.
+ * 2. The autocommands abort script processing.
+ * 3. If one of the "Cmd" autocommands was executed.
+ */
+ if (!buf_valid(buf))
+ buf = NULL;
+ if (buf == NULL || buf->b_ml.ml_mfp == NULL || did_cmd || aborting())
+ {
+ --no_wait_return;
+ msg_scroll = msg_save;
+ if (aborting())
+ /* An aborting error, interrupt or exception in the
+ * autocommands. */
+ return FAIL;
+ if (did_cmd)
+ {
+ if (buf == NULL)
+ /* The buffer was deleted. We assume it was written
+ * (can't retry anyway). */
+ return OK;
+ if (overwriting)
+ {
+ /* Assume the buffer was written, update the timestamp. */
+ ml_timestamp(buf);
+ buf->b_flags &= ~BF_WRITE_MASK;
+ }
+ if (reset_changed && buf->b_changed)
+ /* Buffer still changed, the autocommands didn't work
+ * properly. */
+ return FAIL;
+ return OK;
+ }
+#ifdef FEAT_EVAL
+ if (!aborting())
+#endif
+ EMSG(_("E203: Autocommands deleted or unloaded buffer to be written"));
+ return FAIL;
+ }
+
+ /*
+ * The autocommands may have changed the number of lines in the file.
+ * When writing the whole file, adjust the end.
+ * When writing part of the file, assume that the autocommands only
+ * changed the number of lines that are to be written (tricky!).
+ */
+ if (buf->b_ml.ml_line_count != old_line_count)
+ {
+ if (whole) /* write all */
+ end = buf->b_ml.ml_line_count;
+ else if (buf->b_ml.ml_line_count > old_line_count) /* more lines */
+ end += buf->b_ml.ml_line_count - old_line_count;
+ else /* less lines */
+ {
+ end -= old_line_count - buf->b_ml.ml_line_count;
+ if (end < start)
+ {
+ --no_wait_return;
+ msg_scroll = msg_save;
+ EMSG(_("E204: Autocommand changed number of lines in unexpected way"));
+ return FAIL;
+ }
+ }
+ }
+
+ /*
+ * The autocommands may have changed the name of the buffer, which may
+ * be kept in fname, ffname and sfname.
+ */
+ if (buf_ffname)
+ ffname = buf->b_ffname;
+ if (buf_sfname)
+ sfname = buf->b_sfname;
+ if (buf_fname_f)
+ fname = buf->b_ffname;
+ if (buf_fname_s)
+ fname = buf->b_sfname;
+ }
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans && isNetbeansBuffer(buf))
+ {
+ if (whole)
+ {
+ /*
+ * b_changed can be 0 after an undo, but we still need to write
+ * the buffer to NetBeans.
+ */
+ if (buf->b_changed || isNetbeansModified(buf))
+ {
+ netbeans_save_buffer(buf);
+ return retval;
+ }
+ else
+ {
+ errnum = (char_u *)"E656: ";
+ errmsg = (char_u *)_("NetBeans dissallows writes of unmodified buffers");
+ buffer = NULL;
+ goto fail;
+ }
+ }
+ else
+ {
+ errnum = (char_u *)"E657: ";
+ errmsg = (char_u *)_("Partial writes disallowed for NetBeans buffers");
+ buffer = NULL;
+ goto fail;
+ }
+ }
+#endif
+
+ if (shortmess(SHM_OVER) && !exiting)
+ msg_scroll = FALSE; /* overwrite previous file message */
+ else
+ msg_scroll = TRUE; /* don't overwrite previous file message */
+ if (!filtering)
+ filemess(buf,
+#ifndef UNIX
+ sfname,
+#else
+ fname,
+#endif
+ (char_u *)"", 0); /* show that we are busy */
+ msg_scroll = FALSE; /* always overwrite the file message now */
+
+ buffer = alloc(BUFSIZE);
+ if (buffer == NULL) /* can't allocate big buffer, use small
+ * one (to be able to write when out of
+ * memory) */
+ {
+ buffer = smallbuf;
+ bufsize = SMBUFSIZE;
+ }
+ else
+ bufsize = BUFSIZE;
+
+ /*
+ * Get information about original file (if there is one).
+ */
+#if defined(UNIX) && !defined(ARCHIE)
+ st_old.st_dev = st_old.st_ino = 0;
+ perm = -1;
+ if (mch_stat((char *)fname, &st_old) < 0)
+ newfile = TRUE;
+ else
+ {
+ perm = st_old.st_mode;
+ if (!S_ISREG(st_old.st_mode)) /* not a file */
+ {
+ if (S_ISDIR(st_old.st_mode))
+ {
+ errnum = (char_u *)"E502: ";
+ errmsg = (char_u *)_("is a directory");
+ goto fail;
+ }
+ if (mch_nodetype(fname) != NODE_WRITABLE)
+ {
+ errnum = (char_u *)"E503: ";
+ errmsg = (char_u *)_("is not a file or writable device");
+ goto fail;
+ }
+ /* It's a device of some kind (or a fifo) which we can write to
+ * but for which we can't make a backup. */
+ device = TRUE;
+ newfile = TRUE;
+ perm = -1;
+ }
+ }
+#else /* !UNIX */
+ /*
+ * Check for a writable device name.
+ */
+ c = mch_nodetype(fname);
+ if (c == NODE_OTHER)
+ {
+ errnum = (char_u *)"E503: ";
+ errmsg = (char_u *)_("is not a file or writable device");
+ goto fail;
+ }
+ if (c == NODE_WRITABLE)
+ {
+ device = TRUE;
+ newfile = TRUE;
+ perm = -1;
+ }
+ else
+ {
+ perm = mch_getperm(fname);
+ if (perm < 0)
+ newfile = TRUE;
+ else if (mch_isdir(fname))
+ {
+ errnum = (char_u *)"E502: ";
+ errmsg = (char_u *)_("is a directory");
+ goto fail;
+ }
+ if (overwriting)
+ (void)mch_stat((char *)fname, &st_old);
+ }
+#endif /* !UNIX */
+
+ if (!device && !newfile)
+ {
+ /*
+ * Check if the file is really writable (when renaming the file to
+ * make a backup we won't discover it later).
+ */
+ file_readonly = (
+# ifdef USE_MCH_ACCESS
+# ifdef UNIX
+ (perm & 0222) == 0 ||
+# endif
+ mch_access((char *)fname, W_OK)
+# else
+ (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0
+ ? TRUE : (close(fd), FALSE)
+# endif
+ );
+ if (!forceit && file_readonly)
+ {
+ if (vim_strchr(p_cpo, CPO_FWRITE) != NULL)
+ {
+ errnum = (char_u *)"E504: ";
+ errmsg = (char_u *)_(err_readonly);
+ }
+ else
+ {
+ errnum = (char_u *)"E505: ";
+ errmsg = (char_u *)_("is read-only (add ! to override)");
+ }
+ goto fail;
+ }
+
+ /*
+ * Check if the timestamp hasn't changed since reading the file.
+ */
+ if (overwriting)
+ {
+ retval = check_mtime(buf, &st_old);
+ if (retval == FAIL)
+ goto fail;
+ }
+ }
+
+#ifdef HAVE_ACL
+ /*
+ * For systems that support ACL: get the ACL from the original file.
+ */
+ if (!newfile)
+ acl = mch_get_acl(fname);
+#endif
+
+ /*
+ * If 'backupskip' is not empty, don't make a backup for some files.
+ */
+ dobackup = (p_wb || p_bk || *p_pm != NUL);
+#ifdef FEAT_WILDIGN
+ if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname))
+ dobackup = FALSE;
+#endif
+
+ /*
+ * Save the value of got_int and reset it. We don't want a previous
+ * interruption cancel writing, only hitting CTRL-C while writing should
+ * abort it.
+ */
+ prev_got_int = got_int;
+ got_int = FALSE;
+
+ /* Mark the buffer as 'being saved' to prevent changed buffer warnings */
+ buf->b_saving = TRUE;
+
+ /*
+ * If we are not appending or filtering, the file exists, and the
+ * 'writebackup', 'backup' or 'patchmode' option is set, need a backup.
+ * When 'patchmode' is set also make a backup when appending.
+ *
+ * Do not make any backup, if 'writebackup' and 'backup' are both switched
+ * off. This helps when editing large files on almost-full disks.
+ */
+ if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup)
+ {
+#if defined(UNIX) || defined(WIN32)
+ struct stat st;
+#endif
+
+ if ((bkc_flags & BKC_YES) || append) /* "yes" */
+ backup_copy = TRUE;
+#if defined(UNIX) || defined(WIN32)
+ else if ((bkc_flags & BKC_AUTO)) /* "auto" */
+ {
+ int i;
+
+# ifdef UNIX
+ /*
+ * Don't rename the file when:
+ * - it's a hard link
+ * - it's a symbolic link
+ * - we don't have write permission in the directory
+ * - we can't set the owner/group of the new file
+ */
+ if (st_old.st_nlink > 1
+ || mch_lstat((char *)fname, &st) < 0
+ || st.st_dev != st_old.st_dev
+ || st.st_ino != st_old.st_ino)
+ backup_copy = TRUE;
+ else
+# endif
+ {
+ /*
+ * Check if we can create a file and set the owner/group to
+ * the ones from the original file.
+ * First find a file name that doesn't exist yet (use some
+ * arbitrary numbers).
+ */
+ STRCPY(IObuff, fname);
+ for (i = 4913; ; i += 123)
+ {
+ sprintf((char *)gettail(IObuff), "%d", i);
+ if (mch_stat((char *)IObuff, &st) < 0)
+ break;
+ }
+ fd = mch_open((char *)IObuff, O_CREAT|O_WRONLY|O_EXCL, perm);
+ close(fd);
+ if (fd < 0) /* can't write in directory */
+ backup_copy = TRUE;
+ else
+ {
+# ifdef UNIX
+ chown((char *)IObuff, st_old.st_uid, st_old.st_gid);
+ (void)mch_setperm(IObuff, perm);
+ if (mch_stat((char *)IObuff, &st) < 0
+ || st.st_uid != st_old.st_uid
+ || st.st_gid != st_old.st_gid
+ || st.st_mode != perm)
+ backup_copy = TRUE;
+# endif
+ mch_remove(IObuff);
+ }
+ }
+ }
+
+# ifdef UNIX
+ /*
+ * Break symlinks and/or hardlinks if we've been asked to.
+ */
+ if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK))
+ {
+ int lstat_res;
+
+ lstat_res = mch_lstat((char *)fname, &st);
+
+ /* Symlinks. */
+ if ((bkc_flags & BKC_BREAKSYMLINK)
+ && lstat_res == 0
+ && st.st_ino != st_old.st_ino)
+ backup_copy = FALSE;
+
+ /* Hardlinks. */
+ if ((bkc_flags & BKC_BREAKHARDLINK)
+ && st_old.st_nlink > 1
+ && (lstat_res != 0 || st.st_ino == st_old.st_ino))
+ backup_copy = FALSE;
+ }
+#endif
+
+#endif
+
+ /* make sure we have a valid backup extension to use */
+ if (*p_bex == NUL)
+ {
+#ifdef RISCOS
+ backup_ext = (char_u *)"/bak";
+#else
+ backup_ext = (char_u *)".bak";
+#endif
+ }
+ else
+ backup_ext = p_bex;
+
+ if (backup_copy
+ && (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0)
+ {
+ int bfd;
+ char_u *copybuf, *wp;
+ int some_error = FALSE;
+ struct stat st_new;
+ char_u *dirp;
+ char_u *rootname;
+#ifndef SHORT_FNAME
+ int did_set_shortname;
+#endif
+
+ copybuf = alloc(BUFSIZE + 1);
+ if (copybuf == NULL)
+ {
+ some_error = TRUE; /* out of memory */
+ goto nobackup;
+ }
+
+ /*
+ * Try to make the backup in each directory in the 'bdir' option.
+ *
+ * Unix semantics has it, that we may have a writable file,
+ * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
+ * - the directory is not writable,
+ * - the file may be a symbolic link,
+ * - the file may belong to another user/group, etc.
+ *
+ * For these reasons, the existing writable file must be truncated
+ * and reused. Creation of a backup COPY will be attempted.
+ */
+ dirp = p_bdir;
+ while (*dirp)
+ {
+#ifdef UNIX
+ st_new.st_ino = 0;
+ st_new.st_dev = 0;
+ st_new.st_gid = 0;
+#endif
+
+ /*
+ * Isolate one directory name, using an entry in 'bdir'.
+ */
+ (void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
+ rootname = get_file_in_dir(fname, copybuf);
+ if (rootname == NULL)
+ {
+ some_error = TRUE; /* out of memory */
+ goto nobackup;
+ }
+
+#ifndef SHORT_FNAME
+ did_set_shortname = FALSE;
+#endif
+
+ /*
+ * May try twice if 'shortname' not set.
+ */
+ for (;;)
+ {
+ /*
+ * Make backup file name.
+ */
+ backup = buf_modname(
+#ifdef SHORT_FNAME
+ TRUE,
+#else
+ (buf->b_p_sn || buf->b_shortname),
+#endif
+ rootname, backup_ext, FALSE);
+ if (backup == NULL)
+ {
+ vim_free(rootname);
+ some_error = TRUE; /* out of memory */
+ goto nobackup;
+ }
+
+ /*
+ * Check if backup file already exists.
+ */
+ if (mch_stat((char *)backup, &st_new) >= 0)
+ {
+#ifdef UNIX
+ /*
+ * Check if backup file is same as original file.
+ * May happen when modname() gave the same file back.
+ * E.g. silly link, or file name-length reached.
+ * If we don't check here, we either ruin the file
+ * when copying or erase it after writing. jw.
+ */
+ if (st_new.st_dev == st_old.st_dev
+ && st_new.st_ino == st_old.st_ino)
+ {
+ vim_free(backup);
+ backup = NULL; /* no backup file to delete */
+# ifndef SHORT_FNAME
+ /*
+ * may try again with 'shortname' set
+ */
+ if (!(buf->b_shortname || buf->b_p_sn))
+ {
+ buf->b_shortname = TRUE;
+ did_set_shortname = TRUE;
+ continue;
+ }
+ /* setting shortname didn't help */
+ if (did_set_shortname)
+ buf->b_shortname = FALSE;
+# endif
+ break;
+ }
+#endif
+
+ /*
+ * If we are not going to keep the backup file, don't
+ * delete an existing one, try to use another name.
+ * Change one character, just before the extension.
+ */
+ if (!p_bk)
+ {
+ wp = backup + STRLEN(backup) - 1
+ - STRLEN(backup_ext);
+ if (wp < backup) /* empty file name ??? */
+ wp = backup;
+ *wp = 'z';
+ while (*wp > 'a'
+ && mch_stat((char *)backup, &st_new) >= 0)
+ --*wp;
+ /* They all exist??? Must be something wrong. */
+ if (*wp == 'a')
+ {
+ vim_free(backup);
+ backup = NULL;
+ }
+ }
+ }
+ break;
+ }
+ vim_free(rootname);
+
+ /*
+ * Try to create the backup file
+ */
+ if (backup != NULL)
+ {
+ /* remove old backup, if present */
+ mch_remove(backup);
+ /* Open with O_EXCL to avoid the file being created while
+ * we were sleeping (symlink hacker attack?) */
+ bfd = mch_open((char *)backup,
+ O_WRONLY|O_CREAT|O_EXTRA|O_EXCL, 0666);
+ if (bfd < 0)
+ {
+ vim_free(backup);
+ backup = NULL;
+ }
+ else
+ {
+ /* set file protection same as original file, but
+ * strip s-bit */
+ (void)mch_setperm(backup, perm & 0777);
+
+#ifdef UNIX
+ /*
+ * Try to set the group of the backup same as the
+ * original file. If this fails, set the protection
+ * bits for the group same as the protection bits for
+ * others.
+ */
+ if (st_new.st_gid != st_old.st_gid &&
+# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */
+ fchown(bfd, (uid_t)-1, st_old.st_gid) != 0
+# else
+ chown((char *)backup, (uid_t)-1, st_old.st_gid) != 0
+# endif
+ )
+ mch_setperm(backup,
+ (perm & 0707) | ((perm & 07) << 3));
+#endif
+
+ /*
+ * copy the file.
+ */
+ write_info.bw_fd = bfd;
+ write_info.bw_buf = copybuf;
+#ifdef HAS_BW_FLAGS
+ write_info.bw_flags = FIO_NOCONVERT;
+#endif
+ while ((write_info.bw_len = vim_read(fd, copybuf,
+ BUFSIZE)) > 0)
+ {
+ if (buf_write_bytes(&write_info) == FAIL)
+ {
+ errmsg = (char_u *)_("E506: Can't write to backup file (add ! to override)");
+ break;
+ }
+ ui_breakcheck();
+ if (got_int)
+ {
+ errmsg = (char_u *)_(e_interr);
+ break;
+ }
+ }
+
+ if (close(bfd) < 0 && errmsg == NULL)
+ errmsg = (char_u *)_("E507: Close error for backup file (add ! to override)");
+ if (write_info.bw_len < 0)
+ errmsg = (char_u *)_("E508: Can't read file for backup (add ! to override)");
+#ifdef UNIX
+ set_file_time(backup, st_old.st_atime, st_old.st_mtime);
+#endif
+#ifdef HAVE_ACL
+ mch_set_acl(backup, acl);
+#endif
+ break;
+ }
+ }
+ }
+ nobackup:
+ close(fd); /* ignore errors for closing read file */
+ vim_free(copybuf);
+
+ if (backup == NULL && errmsg == NULL)
+ errmsg = (char_u *)_("E509: Cannot create backup file (add ! to override)");
+ /* ignore errors when forceit is TRUE */
+ if ((some_error || errmsg != NULL) && !forceit)
+ {
+ retval = FAIL;
+ goto fail;
+ }
+ errmsg = NULL;
+ }
+ else
+ {
+ char_u *dirp;
+ char_u *p;
+ char_u *rootname;
+
+ /*
+ * Make a backup by renaming the original file.
+ */
+ /*
+ * If 'cpoptions' includes the "W" flag, we don't want to
+ * overwrite a read-only file. But rename may be possible
+ * anyway, thus we need an extra check here.
+ */
+ if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL)
+ {
+ errnum = (char_u *)"E504: ";
+ errmsg = (char_u *)_(err_readonly);
+ goto fail;
+ }
+
+ /*
+ *
+ * Form the backup file name - change path/fo.o.h to
+ * path/fo.o.h.bak Try all directories in 'backupdir', first one
+ * that works is used.
+ */
+ dirp = p_bdir;
+ while (*dirp)
+ {
+ /*
+ * Isolate one directory name and make the backup file name.
+ */
+ (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
+ rootname = get_file_in_dir(fname, IObuff);
+ if (rootname == NULL)
+ backup = NULL;
+ else
+ {
+ backup = buf_modname(
+#ifdef SHORT_FNAME
+ TRUE,
+#else
+ (buf->b_p_sn || buf->b_shortname),
+#endif
+ rootname, backup_ext, FALSE);
+ vim_free(rootname);
+ }
+
+ if (backup != NULL)
+ {
+ /*
+ * If we are not going to keep the backup file, don't
+ * delete an existing one, try to use another name.
+ * Change one character, just before the extension.
+ */
+ if (!p_bk && mch_getperm(backup) >= 0)
+ {
+ p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
+ if (p < backup) /* empty file name ??? */
+ p = backup;
+ *p = 'z';
+ while (*p > 'a' && mch_getperm(backup) >= 0)
+ --*p;
+ /* They all exist??? Must be something wrong! */
+ if (*p == 'a')
+ {
+ vim_free(backup);
+ backup = NULL;
+ }
+ }
+ }
+ if (backup != NULL)
+ {
+
+ /*
+ * Delete any existing backup and move the current version to
+ * the backup. For safety, we don't remove the backup until
+ * the write has finished successfully. And if the 'backup'
+ * option is set, leave it around.
+ */
+ /*
+ * If the renaming of the original file to the backup file
+ * works, quit here.
+ */
+ if (vim_rename(fname, backup) == 0)
+ break;
+
+ vim_free(backup); /* don't do the rename below */
+ backup = NULL;
+ }
+ }
+ if (backup == NULL && !forceit)
+ {
+ errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)");
+ goto fail;
+ }
+ }
+ }
+
+#if defined(UNIX) && !defined(ARCHIE)
+ /* When using ":w!" and the file was read-only: make it writable */
+ if (forceit && perm >= 0 && !(perm & 0200) && st_old.st_uid == getuid()
+ && vim_strchr(p_cpo, CPO_FWRITE) == NULL)
+ {
+ perm |= 0200;
+ (void)mch_setperm(fname, perm);
+ made_writable = TRUE;
+ }
+#endif
+
+ /* When using ":w!" and writing to the current file, readonly makes no
+ * sense, reset it */
+ if (forceit && overwriting)
+ {
+ buf->b_p_ro = FALSE;
+#ifdef FEAT_TITLE
+ need_maketitle = TRUE; /* set window title later */
+#endif
+#ifdef FEAT_WINDOWS
+ status_redraw_all(); /* redraw status lines later */
+#endif
+ }
+
+ if (end > buf->b_ml.ml_line_count)
+ end = buf->b_ml.ml_line_count;
+ if (buf->b_ml.ml_flags & ML_EMPTY)
+ start = end + 1;
+
+ /*
+ * If the original file is being overwritten, there is a small chance that
+ * we crash in the middle of writing. Therefore the file is preserved now.
+ * This makes all block numbers positive so that recovery does not need
+ * the original file.
+ * Don't do this if there is a backup file and we are exiting.
+ */
+ if (reset_changed && !newfile && !otherfile(ffname)
+ && !(exiting && backup != NULL))
+ {
+ ml_preserve(buf, FALSE);
+ if (got_int)
+ {
+ errmsg = (char_u *)_(e_interr);
+ goto restore_backup;
+ }
+ }
+
+#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
+ /*
+ * Before risking to lose the original file verify if there's
+ * a resource fork to preserve, and if cannot be done warn
+ * the users. This happens when overwriting without backups.
+ */
+ if (backup == NULL && overwriting && !append)
+ if (mch_has_resource_fork(fname))
+ {
+ errmsg = (char_u *)_("E460: The resource fork would be lost (add ! to override)");
+ goto restore_backup;
+ }
+#endif
+
+#ifdef VMS
+ vms_remove_version(fname); /* remove version */
+#endif
+ /* Default: write the the file directly. May write to a temp file for
+ * multi-byte conversion. */
+ wfname = fname;
+
+#ifdef FEAT_MBYTE
+ /* Check for forced 'fileencoding' from "++opt=val" argument. */
+ if (eap != NULL && eap->force_enc != 0)
+ {
+ fenc = eap->cmd + eap->force_enc;
+ fenc = enc_canonize(fenc);
+ fenc_tofree = fenc;
+ }
+ else
+ fenc = buf->b_p_fenc;
+
+ /*
+ * The file needs to be converted when 'fileencoding' is set and
+ * 'fileencoding' differs from 'encoding'.
+ */
+ converted = (*fenc != NUL && !same_encoding(p_enc, fenc));
+
+ /*
+ * Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
+ * Latin1 to Unicode conversion. This is handled in buf_write_bytes().
+ * Prepare the flags for it and allocate bw_conv_buf when needed.
+ */
+ if (converted && (enc_utf8 || STRCMP(p_enc, "latin1") == 0))
+ {
+ wb_flags = get_fio_flags(fenc);
+ if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8))
+ {
+ /* Need to allocate a buffer to translate into. */
+ if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8))
+ write_info.bw_conv_buflen = bufsize * 2;
+ else /* FIO_UCS4 */
+ write_info.bw_conv_buflen = bufsize * 4;
+ write_info.bw_conv_buf
+ = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
+ if (write_info.bw_conv_buf == NULL)
+ end = 0;
+ }
+ }
+
+# ifdef WIN3264
+ if (converted && wb_flags == 0 && (wb_flags = get_win_fio_flags(fenc)) != 0)
+ {
+ /* Convert UTF-8 -> UCS-2 and UCS-2 -> DBCS. Worst-case * 4: */
+ write_info.bw_conv_buflen = bufsize * 4;
+ write_info.bw_conv_buf
+ = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
+ if (write_info.bw_conv_buf == NULL)
+ end = 0;
+ }
+# endif
+
+# ifdef MACOS_X
+ if (converted && wb_flags == 0 && (wb_flags = get_mac_fio_flags(fenc)) != 0)
+ {
+ write_info.bw_conv_buflen = bufsize * 3;
+ write_info.bw_conv_buf
+ = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
+ if (write_info.bw_conv_buf == NULL)
+ end = 0;
+ }
+# endif
+
+# if defined(FEAT_EVAL) || defined(USE_ICONV)
+ if (converted && wb_flags == 0)
+ {
+# ifdef USE_ICONV
+ /*
+ * Use iconv() conversion when conversion is needed and it's not done
+ * internally.
+ */
+ write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
+ enc_utf8 ? (char_u *)"utf-8" : p_enc);
+ if (write_info.bw_iconv_fd != (iconv_t)-1)
+ {
+ /* We're going to use iconv(), allocate a buffer to convert in. */
+ write_info.bw_conv_buflen = bufsize * ICONV_MULT;
+ write_info.bw_conv_buf
+ = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
+ if (write_info.bw_conv_buf == NULL)
+ end = 0;
+ write_info.bw_first = TRUE;
+ }
+# ifdef FEAT_EVAL
+ else
+# endif
+# endif
+
+# ifdef FEAT_EVAL
+ /*
+ * When the file needs to be converted with 'charconvert' after
+ * writing, write to a temp file instead and let the conversion
+ * overwrite the original file.
+ */
+ if (*p_ccv != NUL)
+ {
+ wfname = vim_tempname('w');
+ if (wfname == NULL) /* Can't write without a tempfile! */
+ {
+ errmsg = (char_u *)_("E214: Can't find temp file for writing");
+ goto restore_backup;
+ }
+ }
+# endif
+ }
+# endif
+ if (converted && wb_flags == 0
+# ifdef USE_ICONV
+ && write_info.bw_iconv_fd == (iconv_t)-1
+# endif
+# ifdef FEAT_EVAL
+ && wfname == fname
+# endif
+ )
+ {
+ if (!forceit)
+ {
+ errmsg = (char_u *)_("E213: Cannot convert (add ! to write without conversion)");
+ goto restore_backup;
+ }
+ notconverted = TRUE;
+ }
+#endif
+
+ /*
+ * Open the file "wfname" for writing.
+ * We may try to open the file twice: If we can't write to the
+ * file and forceit is TRUE we delete the existing file and try to create
+ * a new one. If this still fails we may have lost the original file!
+ * (this may happen when the user reached his quotum for number of files).
+ * Appending will fail if the file does not exist and forceit is FALSE.
+ */
+ while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
+ ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
+ : (O_CREAT | O_TRUNC))
+ , 0666)) < 0)
+ {
+ /*
+ * A forced write will try to create a new file if the old one is
+ * still readonly. This may also happen when the directory is
+ * read-only. In that case the mch_remove() will fail.
+ */
+ if (errmsg == NULL)
+ {
+#ifdef UNIX
+ struct stat st;
+
+ /* Don't delete the file when it's a hard or symbolic link. */
+ if ((!newfile && st_old.st_nlink > 1)
+ || (mch_lstat((char *)fname, &st) == 0
+ && (st.st_dev != st_old.st_dev
+ || st.st_ino != st_old.st_ino)))
+ errmsg = (char_u *)_("E166: Can't open linked file for writing");
+ else
+#endif
+ {
+ errmsg = (char_u *)_("E212: Can't open file for writing");
+ if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
+ && perm >= 0)
+ {
+#ifdef UNIX
+ /* we write to the file, thus it should be marked
+ writable after all */
+ if (!(perm & 0200))
+ made_writable = TRUE;
+ perm |= 0200;
+ if (st_old.st_uid != getuid() || st_old.st_gid != getgid())
+ perm &= 0777;
+#endif
+ if (!append) /* don't remove when appending */
+ mch_remove(wfname);
+ continue;
+ }
+ }
+ }
+
+restore_backup:
+ {
+ struct stat st;
+
+ /*
+ * If we failed to open the file, we don't need a backup. Throw it
+ * away. If we moved or removed the original file try to put the
+ * backup in its place.
+ */
+ if (backup != NULL && wfname == fname)
+ {
+ if (backup_copy)
+ {
+ /*
+ * There is a small chance that we removed the original,
+ * try to move the copy in its place.
+ * This may not work if the vim_rename() fails.
+ * In that case we leave the copy around.
+ */
+ /* If file does not exist, put the copy in its place */
+ if (mch_stat((char *)fname, &st) < 0)
+ vim_rename(backup, fname);
+ /* if original file does exist throw away the copy */
+ if (mch_stat((char *)fname, &st) >= 0)
+ mch_remove(backup);
+ }
+ else
+ {
+ /* try to put the original file back */
+ vim_rename(backup, fname);
+ }
+ }
+
+ /* if original file no longer exists give an extra warning */
+ if (!newfile && mch_stat((char *)fname, &st) < 0)
+ end = 0;
+ }
+
+#ifdef FEAT_MBYTE
+ if (wfname != fname)
+ vim_free(wfname);
+#endif
+ goto fail;
+ }
+ errmsg = NULL;
+
+#if defined(MACOS_CLASSIC) || defined(WIN3264)
+ /* TODO: Is it need for MACOS_X? (Dany) */
+ /*
+ * On macintosh copy the original files attributes (i.e. the backup)
+ * This is done in order to preserve the ressource fork and the
+ * Finder attribute (label, comments, custom icons, file creatore)
+ */
+ if (backup != NULL && overwriting && !append)
+ {
+ if (backup_copy)
+ (void)mch_copy_file_attribute(wfname, backup);
+ else
+ (void)mch_copy_file_attribute(backup, wfname);
+ }
+
+ if (!overwriting && !append)
+ {
+ if (buf->b_ffname != NULL)
+ (void)mch_copy_file_attribute(buf->b_ffname, wfname);
+ /* Should copy ressource fork */
+ }
+#endif
+
+ write_info.bw_fd = fd;
+
+#ifdef FEAT_CRYPT
+ if (*buf->b_p_key && !filtering)
+ {
+ crypt_init_keys(buf->b_p_key);
+ /* Write magic number, so that Vim knows that this file is encrypted
+ * when reading it again. This also undergoes utf-8 to ucs-2/4
+ * conversion when needed. */
+ write_info.bw_buf = (char_u *)CRYPT_MAGIC;
+ write_info.bw_len = CRYPT_MAGIC_LEN;
+ write_info.bw_flags = FIO_NOCONVERT;
+ if (buf_write_bytes(&write_info) == FAIL)
+ end = 0;
+ wb_flags |= FIO_ENCRYPTED;
+ }
+#endif
+
+ write_info.bw_buf = buffer;
+ nchars = 0;
+
+ /* use "++bin", "++nobin" or 'binary' */
+ if (eap != NULL && eap->force_bin != 0)
+ write_bin = (eap->force_bin == FORCE_BIN);
+ else
+ write_bin = buf->b_p_bin;
+
+#ifdef FEAT_MBYTE
+ /*
+ * The BOM is written just after the encryption magic number.
+ */
+ if (buf->b_p_bomb && !write_bin)
+ {
+ write_info.bw_len = make_bom(buffer, fenc);
+ if (write_info.bw_len > 0)
+ {
+ /* don't convert, do encryption */
+ write_info.bw_flags = FIO_NOCONVERT | wb_flags;
+ if (buf_write_bytes(&write_info) == FAIL)
+ end = 0;
+ else
+ nchars += write_info.bw_len;
+ }
+ }
+#endif
+
+ write_info.bw_len = bufsize;
+#ifdef HAS_BW_FLAGS
+ write_info.bw_flags = wb_flags;
+#endif
+ fileformat = get_fileformat_force(buf, eap);
+ s = buffer;
+ len = 0;
+ for (lnum = start; lnum <= end; ++lnum)
+ {
+ /*
+ * The next while loop is done once for each character written.
+ * Keep it fast!
+ */
+ ptr = ml_get_buf(buf, lnum, FALSE) - 1;
+ while ((c = *++ptr) != NUL)
+ {
+ if (c == NL)
+ *s = NUL; /* replace newlines with NULs */
+ else if (c == CAR && fileformat == EOL_MAC)
+ *s = NL; /* Mac: replace CRs with NLs */
+ else
+ *s = c;
+ ++s;
+ if (++len != bufsize)
+ continue;
+ if (buf_write_bytes(&write_info) == FAIL)
+ {
+ end = 0; /* write error: break loop */
+ break;
+ }
+ nchars += bufsize;
+ s = buffer;
+ len = 0;
+ }
+ /* write failed or last line has no EOL: stop here */
+ if (end == 0
+ || (lnum == end
+ && write_bin
+ && (lnum == write_no_eol_lnum
+ || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))))
+ {
+ ++lnum; /* written the line, count it */
+ no_eol = TRUE;
+ break;
+ }
+ if (fileformat == EOL_UNIX)
+ *s++ = NL;
+ else
+ {
+ *s++ = CAR; /* EOL_MAC or EOL_DOS: write CR */
+ if (fileformat == EOL_DOS) /* write CR-NL */
+ {
+ if (++len == bufsize)
+ {
+ if (buf_write_bytes(&write_info) == FAIL)
+ {
+ end = 0; /* write error: break loop */
+ break;
+ }
+ nchars += bufsize;
+ s = buffer;
+ len = 0;
+ }
+ *s++ = NL;
+ }
+ }
+ if (++len == bufsize && end)
+ {
+ if (buf_write_bytes(&write_info) == FAIL)
+ {
+ end = 0; /* write error: break loop */
+ break;
+ }
+ nchars += bufsize;
+ s = buffer;
+ len = 0;
+
+ ui_breakcheck();
+ if (got_int)
+ {
+ end = 0; /* Interrupted, break loop */
+ break;
+ }
+ }
+#ifdef VMS
+ /*
+ * On VMS there is a problem: newlines get added when writing blocks
+ * at a time. Fix it by writing a line at a time.
+ * This is much slower!
+ * Explanation: Vim can not handle, so far, variable record format.
+ * With $analize/rms filename you can get the rms file structure, and
+ * if the Record format filed is variable, CR will be added after
+ * every written buffer. In other cases it works without this fix.
+ * From other side read is about 5 times slower for "variable record
+ * format" files.
+ */
+ if (buf->b_fab_rfm == FAB$C_VAR)
+ {
+ write_info.bw_len = len;
+ if (buf_write_bytes(&write_info) == FAIL)
+ {
+ end = 0; /* write error: break loop */
+ break;
+ }
+ write_info.bw_len = bufsize;
+ nchars += len;
+ s = buffer;
+ len = 0;
+ }
+#endif
+ }
+ if (len > 0 && end > 0)
+ {
+ write_info.bw_len = len;
+ if (buf_write_bytes(&write_info) == FAIL)
+ end = 0; /* write error */
+ nchars += len;
+ }
+
+#if defined(UNIX) && defined(HAVE_FSYNC)
+ /* On many journalling file systems there is a bug that causes both the
+ * original and the backup file to be lost when halting the system right
+ * after writing the file. That's because only the meta-data is
+ * journalled. Syncing the file slows down the system, but assures it has
+ * been written to disk and we don't lose it. */
+ if (fsync(fd) != 0)
+ {
+ errmsg = (char_u *)_("E667: Fsync failed");
+ end = 0;
+ }
+#endif
+
+ if (close(fd) != 0)
+ {
+ errmsg = (char_u *)_("E512: Close failed");
+ end = 0;
+ }
+
+#ifdef UNIX
+ if (made_writable)
+ perm &= ~0200; /* reset 'w' bit for security reasons */
+#endif
+ if (perm >= 0) /* set perm. of new file same as old file */
+ (void)mch_setperm(wfname, perm);
+#ifdef RISCOS
+ if (!append && !filtering)
+ /* Set the filetype after writing the file. */
+ mch_set_filetype(wfname, buf->b_p_oft);
+#endif
+#ifdef HAVE_ACL
+ /* Probably need to set the ACL before changing the user (can't set the
+ * ACL on a file the user doesn't own). */
+ if (!backup_copy)
+ mch_set_acl(wfname, acl);
+#endif
+
+#ifdef UNIX
+ /* When creating a new file, set its owner/group to that of the original
+ * file. Get the new device and inode number. */
+ if (backup != NULL && !backup_copy)
+ {
+ struct stat st;
+
+ /* don't change the owner when it's already OK, some systems remove
+ * permission or ACL stuff */
+ if (mch_stat((char *)wfname, &st) < 0
+ || st.st_uid != st_old.st_uid
+ || st.st_gid != st_old.st_gid)
+ {
+ chown((char *)wfname, st_old.st_uid, st_old.st_gid);
+ if (perm >= 0) /* set permission again, may have changed */
+ (void)mch_setperm(wfname, perm);
+ }
+ buf_setino(buf);
+ }
+#endif
+
+
+#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
+ if (wfname != fname)
+ {
+ /*
+ * The file was written to a temp file, now it needs to be converted
+ * with 'charconvert' to (overwrite) the output file.
+ */
+ if (end != 0)
+ {
+ if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc,
+ wfname, fname) == FAIL)
+ {
+ write_info.bw_conv_error = TRUE;
+ end = 0;
+ }
+ }
+ mch_remove(wfname);
+ vim_free(wfname);
+ }
+#endif
+
+ if (end == 0)
+ {
+ if (errmsg == NULL)
+ {
+#ifdef FEAT_MBYTE
+ if (write_info.bw_conv_error)
+ errmsg = (char_u *)_("E513: write error, conversion failed");
+ else
+#endif
+ if (got_int)
+ errmsg = (char_u *)_(e_interr);
+ else
+ errmsg = (char_u *)_("E514: write error (file system full?)");
+ }
+
+ /*
+ * If we have a backup file, try to put it in place of the new file,
+ * because the new file is probably corrupt. This avoids loosing the
+ * original file when trying to make a backup when writing the file a
+ * second time.
+ * When "backup_copy" is set we need to copy the backup over the new
+ * file. Otherwise rename the backup file.
+ * If this is OK, don't give the extra warning message.
+ */
+ if (backup != NULL)
+ {
+ if (backup_copy)
+ {
+ /* This may take a while, if we were interrupted let the user
+ * know we got the message. */
+ if (got_int)
+ {
+ MSG(_(e_interr));
+ out_flush();
+ }
+ if ((fd = mch_open((char *)backup, O_RDONLY | O_EXTRA, 0)) >= 0)
+ {
+ if ((write_info.bw_fd = mch_open((char *)fname,
+ O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA, 0666)) >= 0)
+ {
+ /* copy the file. */
+ write_info.bw_buf = smallbuf;
+#ifdef HAS_BW_FLAGS
+ write_info.bw_flags = FIO_NOCONVERT;
+#endif
+ while ((write_info.bw_len = vim_read(fd, smallbuf,
+ SMBUFSIZE)) > 0)
+ if (buf_write_bytes(&write_info) == FAIL)
+ break;
+
+ if (close(write_info.bw_fd) >= 0
+ && write_info.bw_len == 0)
+ end = 1; /* success */
+ }
+ close(fd); /* ignore errors for closing read file */
+ }
+ }
+ else
+ {
+ if (vim_rename(backup, fname) == 0)
+ end = 1;
+ }
+ }
+ goto fail;
+ }
+
+ lnum -= start; /* compute number of written lines */
+ --no_wait_return; /* may wait for return now */
+
+#if !(defined(UNIX) || defined(VMS))
+ fname = sfname; /* use shortname now, for the messages */
+#endif
+ if (!filtering)
+ {
+ msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
+ c = FALSE;
+#ifdef FEAT_MBYTE
+ if (write_info.bw_conv_error)
+ {
+ STRCAT(IObuff, _(" CONVERSION ERROR"));
+ c = TRUE;
+ }
+ else if (notconverted)
+ {
+ STRCAT(IObuff, _("[NOT converted]"));
+ c = TRUE;
+ }
+ else if (converted)
+ {
+ STRCAT(IObuff, _("[converted]"));
+ c = TRUE;
+ }
+#endif
+ if (device)
+ {
+ STRCAT(IObuff, _("[Device]"));
+ c = TRUE;
+ }
+ else if (newfile)
+ {
+ STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]"));
+ c = TRUE;
+ }
+ if (no_eol)
+ {
+ msg_add_eol();
+ c = TRUE;
+ }
+ /* may add [unix/dos/mac] */
+ if (msg_add_fileformat(fileformat))
+ c = TRUE;
+#ifdef FEAT_CRYPT
+ if (wb_flags & FIO_ENCRYPTED)
+ {
+ STRCAT(IObuff, _("[crypted]"));
+ c = TRUE;
+ }
+#endif
+ msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
+ if (!shortmess(SHM_WRITE))
+ {
+ if (append)
+ STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
+ else
+ STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
+ }
+
+ set_keep_msg(msg_trunc_attr(IObuff, FALSE, 0));
+ keep_msg_attr = 0;
+ }
+
+ if (reset_changed && whole
+#ifdef FEAT_MBYTE
+ && !write_info.bw_conv_error
+#endif
+ ) /* when written everything correctly */
+ {
+ unchanged(buf, TRUE);
+ u_unchanged(buf);
+ }
+
+ /*
+ * If written to the current file, update the timestamp of the swap file
+ * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
+ */
+ if (overwriting)
+ {
+ ml_timestamp(buf);
+ buf->b_flags &= ~BF_WRITE_MASK;
+ }
+
+ /*
+ * If we kept a backup until now, and we are in patch mode, then we make
+ * the backup file our 'original' file.
+ */
+ if (*p_pm && dobackup)
+ {
+ char *org = (char *)buf_modname(
+#ifdef SHORT_FNAME
+ TRUE,
+#else
+ (buf->b_p_sn || buf->b_shortname),
+#endif
+ fname, p_pm, FALSE);
+
+ if (backup != NULL)
+ {
+ struct stat st;
+
+ /*
+ * If the original file does not exist yet
+ * the current backup file becomes the original file
+ */
+ if (org == NULL)
+ EMSG(_("E205: Patchmode: can't save original file"));
+ else if (mch_stat(org, &st) < 0)
+ {
+ vim_rename(backup, (char_u *)org);
+ vim_free(backup); /* don't delete the file */
+ backup = NULL;
+#ifdef UNIX
+ set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime);
+#endif
+ }
+ }
+ /*
+ * If there is no backup file, remember that a (new) file was
+ * created.
+ */
+ else
+ {
+ int empty_fd;
+
+ if (org == NULL
+ || (empty_fd = mch_open(org, O_CREAT | O_EXTRA | O_EXCL,
+ 0666)) < 0)
+ EMSG(_("E206: patchmode: can't touch empty original file"));
+ else
+ close(empty_fd);
+ }
+ if (org != NULL)
+ {
+ mch_setperm((char_u *)org, mch_getperm(fname) & 0777);
+ vim_free(org);
+ }
+ }
+
+ /*
+ * Remove the backup unless 'backup' option is set
+ */
+ if (!p_bk && backup != NULL && mch_remove(backup) != 0)
+ EMSG(_("E207: Can't delete backup file"));
+
+#ifdef FEAT_SUN_WORKSHOP
+ if (usingSunWorkShop)
+ workshop_file_saved((char *) ffname);
+#endif
+
+ goto nofail;
+
+ /*
+ * Finish up. We get here either after failure or success.
+ */
+fail:
+ --no_wait_return; /* may wait for return now */
+nofail:
+
+ /* Done saving, we accept changed buffer warnings again */
+ buf->b_saving = FALSE;
+
+ vim_free(backup);
+ if (buffer != smallbuf)
+ vim_free(buffer);
+#ifdef FEAT_MBYTE
+ vim_free(fenc_tofree);
+ vim_free(write_info.bw_conv_buf);
+# ifdef USE_ICONV
+ if (write_info.bw_iconv_fd != (iconv_t)-1)
+ {
+ iconv_close(write_info.bw_iconv_fd);
+ write_info.bw_iconv_fd = (iconv_t)-1;
+ }
+# endif
+#endif
+#ifdef HAVE_ACL
+ mch_free_acl(acl);
+#endif
+
+ if (errmsg != NULL)
+ {
+ int numlen = errnum != NULL ? STRLEN(errnum) : 0;
+
+ attr = hl_attr(HLF_E); /* set highlight for error messages */
+ msg_add_fname(buf,
+#ifndef UNIX
+ sfname
+#else
+ fname
+#endif
+ ); /* put file name in IObuff with quotes */
+ if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
+ IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
+ /* If the error message has the form "is ...", put the error number in
+ * front of the file name. */
+ if (errnum != NULL)
+ {
+ mch_memmove(IObuff + numlen, IObuff, STRLEN(IObuff) + 1);
+ mch_memmove(IObuff, errnum, (size_t)numlen);
+ }
+ STRCAT(IObuff, errmsg);
+ emsg(IObuff);
+
+ retval = FAIL;
+ if (end == 0)
+ {
+ MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
+ attr | MSG_HIST);
+ MSG_PUTS_ATTR(_("don't quit the editor until the file is successfully written!"),
+ attr | MSG_HIST);
+
+ /* Update the timestamp to avoid an "overwrite changed file"
+ * prompt when writing again. */
+ if (mch_stat((char *)fname, &st_old) >= 0)
+ {
+ buf_store_time(buf, &st_old, fname);
+ buf->b_mtime_read = buf->b_mtime;
+ }
+ }
+ }
+ msg_scroll = msg_save;
+
+#ifdef FEAT_AUTOCMD
+#ifdef FEAT_EVAL
+ if (!should_abort(retval))
+#else
+ if (!got_int)
+#endif
+ {
+ aco_save_T aco;
+
+ write_no_eol_lnum = 0; /* in case it was set by the previous read */
+
+ /*
+ * Apply POST autocommands.
+ * Careful: The autocommands may call buf_write() recursively!
+ */
+ aucmd_prepbuf(&aco, buf);
+
+ if (append)
+ apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
+ FALSE, curbuf, eap);
+ else if (filtering)
+ apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
+ FALSE, curbuf, eap);
+ else if (reset_changed && whole)
+ apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
+ FALSE, curbuf, eap);
+ else
+ apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
+ FALSE, curbuf, eap);
+
+ /* restore curwin/curbuf and a few other things */
+ aucmd_restbuf(&aco);
+
+#ifdef FEAT_EVAL
+ if (aborting()) /* autocmds may abort script processing */
+ retval = FALSE;
+#endif
+ }
+#endif
+
+ got_int |= prev_got_int;
+
+#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
+ /* Update machine specific information. */
+ mch_post_buffer_write(buf);
+#endif
+ return retval;
+}
+
+/*
+ * Put file name into IObuff with quotes.
+ */
+ static void
+msg_add_fname(buf, fname)
+ buf_T *buf;
+ char_u *fname;
+{
+ if (fname == NULL)
+ fname = (char_u *)"-stdin-";
+ home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
+ IObuff[0] = '"';
+ STRCAT(IObuff, "\" ");
+}
+
+/*
+ * Append message for text mode to IObuff.
+ * Return TRUE if something appended.
+ */
+ static int
+msg_add_fileformat(eol_type)
+ int eol_type;
+{
+#ifndef USE_CRNL
+ if (eol_type == EOL_DOS)
+ {
+ STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
+ return TRUE;
+ }
+#endif
+#ifndef USE_CR
+ if (eol_type == EOL_MAC)
+ {
+ STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
+ return TRUE;
+ }
+#endif
+#if defined(USE_CRNL) || defined(USE_CR)
+ if (eol_type == EOL_UNIX)
+ {
+ STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
+ return TRUE;
+ }
+#endif
+ return FALSE;
+}
+
+/*
+ * Append line and character count to IObuff.
+ */
+ static void
+msg_add_lines(insert_space, lnum, nchars)
+ int insert_space;
+ long lnum;
+ long nchars;
+{
+ char_u *p;
+
+ p = IObuff + STRLEN(IObuff);
+
+ if (insert_space)
+ *p++ = ' ';
+ if (shortmess(SHM_LINES))
+ sprintf((char *)p, "%ldL, %ldC", lnum, nchars);
+ else
+ {
+ if (lnum == 1)
+ STRCPY(p, _("1 line, "));
+ else
+ sprintf((char *)p, _("%ld lines, "), lnum);
+ p += STRLEN(p);
+ if (nchars == 1)
+ STRCPY(p, _("1 character"));
+ else
+ sprintf((char *)p, _("%ld characters"), nchars);
+ }
+}
+
+/*
+ * Append message for missing line separator to IObuff.
+ */
+ static void
+msg_add_eol()
+{
+ STRCAT(IObuff, shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
+}
+
+/*
+ * Check modification time of file, before writing to it.
+ * The size isn't checked, because using a tool like "gzip" takes care of
+ * using the same timestamp but can't set the size.
+ */
+ static int
+check_mtime(buf, st)
+ buf_T *buf;
+ struct stat *st;
+{
+ if (buf->b_mtime_read != 0
+ && time_differs((long)st->st_mtime, buf->b_mtime_read))
+ {
+ msg_scroll = TRUE; /* don't overwrite messages here */
+ msg_silent = 0; /* must give this prompt */
+ /* don't use emsg() here, don't want to flush the buffers */
+ MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"),
+ hl_attr(HLF_E));
+ if (ask_yesno((char_u *)_("Do you really want to write to it"),
+ TRUE) == 'n')
+ return FAIL;
+ msg_scroll = FALSE; /* always overwrite the file message now */
+ }
+ return OK;
+}
+
+ static int
+time_differs(t1, t2)
+ long t1, t2;
+{
+#if defined(__linux__) || defined(MSDOS) || defined(MSWIN)
+ /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store
+ * the seconds. Since the roundoff is done when flushing the inode, the
+ * time may change unexpectedly by one second!!! */
+ return (t1 - t2 > 1 || t2 - t1 > 1);
+#else
+ return (t1 != t2);
+#endif
+}
+
+/*
+ * Call write() to write a number of bytes to the file.
+ * Also handles encryption and 'encoding' conversion.
+ *
+ * Return FAIL for failure, OK otherwise.
+ */
+ static int
+buf_write_bytes(ip)
+ struct bw_info *ip;
+{
+ int wlen;
+ char_u *buf = ip->bw_buf; /* data to write */
+ int len = ip->bw_len; /* length of data */
+#ifdef HAS_BW_FLAGS
+ int flags = ip->bw_flags; /* extra flags */
+#endif
+
+#ifdef FEAT_MBYTE
+ /*
+ * Skip conversion when writing the crypt magic number or the BOM.
+ */
+ if (!(flags & FIO_NOCONVERT))
+ {
+ char_u *p;
+ unsigned c;
+ int n;
+
+ if (flags & FIO_UTF8)
+ {
+ /*
+ * Convert latin1 in the buffer to UTF-8 in the file.
+ */
+ p = ip->bw_conv_buf; /* translate to buffer */
+ for (wlen = 0; wlen < len; ++wlen)
+ p += utf_char2bytes(buf[wlen], p);
+ buf = ip->bw_conv_buf;
+ len = (int)(p - ip->bw_conv_buf);
+ }
+ else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1))
+ {
+ /*
+ * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
+ * Latin1 chars in the file.
+ */
+ if (flags & FIO_LATIN1)
+ p = buf; /* translate in-place (can only get shorter) */
+ else
+ p = ip->bw_conv_buf; /* translate to buffer */
+ for (wlen = 0; wlen < len; wlen += n)
+ {
+ if (wlen == 0 && ip->bw_restlen != 0)
+ {
+ int l;
+
+ /* Use remainder of previous call. Append the start of
+ * buf[] to get a full sequence. Might still be too
+ * short! */
+ l = CONV_RESTLEN - ip->bw_restlen;
+ if (l > len)
+ l = len;
+ mch_memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
+ n = utf_ptr2len_check_len(ip->bw_rest, ip->bw_restlen + l);
+ if (n > ip->bw_restlen + len)
+ {
+ /* We have an incomplete byte sequence at the end to
+ * be written. We can't convert it without the
+ * remaining bytes. Keep them for the next call. */
+ if (ip->bw_restlen + len > CONV_RESTLEN)
+ return FAIL;
+ ip->bw_restlen += len;
+ break;
+ }
+ if (n > 1)
+ c = utf_ptr2char(ip->bw_rest);
+ else
+ c = ip->bw_rest[0];
+ if (n >= ip->bw_restlen)
+ {
+ n -= ip->bw_restlen;
+ ip->bw_restlen = 0;
+ }
+ else
+ {
+ ip->bw_restlen -= n;
+ mch_memmove(ip->bw_rest, ip->bw_rest + n,
+ (size_t)ip->bw_restlen);
+ n = 0;
+ }
+ }
+ else
+ {
+ n = utf_ptr2len_check_len(buf + wlen, len - wlen);
+ if (n > len - wlen)
+ {
+ /* We have an incomplete byte sequence at the end to
+ * be written. We can't convert it without the
+ * remaining bytes. Keep them for the next call. */
+ if (len - wlen > CONV_RESTLEN)
+ return FAIL;
+ ip->bw_restlen = len - wlen;
+ mch_memmove(ip->bw_rest, buf + wlen,
+ (size_t)ip->bw_restlen);
+ break;
+ }
+ if (n > 1)
+ c = utf_ptr2char(buf + wlen);
+ else
+ c = buf[wlen];
+ }
+
+ ip->bw_conv_error |= ucs2bytes(c, &p, flags);
+ }
+ if (flags & FIO_LATIN1)
+ len = (int)(p - buf);
+ else
+ {
+ buf = ip->bw_conv_buf;
+ len = (int)(p - ip->bw_conv_buf);
+ }
+ }
+
+# ifdef WIN3264
+ else if (flags & FIO_CODEPAGE)
+ {
+ /*
+ * Convert UTF-8 or codepage to UCS-2 and then to MS-Windows
+ * codepage.
+ */
+ char_u *from;
+ size_t fromlen;
+ char_u *to;
+ int u8c;
+ BOOL bad = FALSE;
+ int needed;
+
+ if (ip->bw_restlen > 0)
+ {
+ /* Need to concatenate the remainder of the previous call and
+ * the bytes of the current call. Use the end of the
+ * conversion buffer for this. */
+ fromlen = len + ip->bw_restlen;
+ from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
+ mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
+ mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
+ }
+ else
+ {
+ from = buf;
+ fromlen = len;
+ }
+
+ to = ip->bw_conv_buf;
+ if (enc_utf8)
+ {
+ /* Convert from UTF-8 to UCS-2, to the start of the buffer.
+ * The buffer has been allocated to be big enough. */
+ while (fromlen > 0)
+ {
+ n = utf_ptr2len_check_len(from, fromlen);
+ if (n > (int)fromlen) /* incomplete byte sequence */
+ break;
+ u8c = utf_ptr2char(from);
+ *to++ = (u8c & 0xff);
+ *to++ = (u8c >> 8);
+ fromlen -= n;
+ from += n;
+ }
+
+ /* Copy remainder to ip->bw_rest[] to be used for the next
+ * call. */
+ if (fromlen > CONV_RESTLEN)
+ {
+ /* weird overlong sequence */
+ ip->bw_conv_error = TRUE;
+ return FAIL;
+ }
+ mch_memmove(ip->bw_rest, from, fromlen);
+ ip->bw_restlen = fromlen;
+ }
+ else
+ {
+ /* Convert from enc_codepage to UCS-2, to the start of the
+ * buffer. The buffer has been allocated to be big enough. */
+ ip->bw_restlen = 0;
+ needed = MultiByteToWideChar(enc_codepage,
+ MB_ERR_INVALID_CHARS, (LPCSTR)from, fromlen,
+ NULL, 0);
+ if (needed == 0)
+ {
+ /* When conversion fails there may be a trailing byte. */
+ needed = MultiByteToWideChar(enc_codepage,
+ MB_ERR_INVALID_CHARS, (LPCSTR)from, fromlen - 1,
+ NULL, 0);
+ if (needed == 0)
+ {
+ /* Conversion doesn't work. */
+ ip->bw_conv_error = TRUE;
+ return FAIL;
+ }
+ /* Save the trailing byte for the next call. */
+ ip->bw_rest[0] = from[fromlen - 1];
+ ip->bw_restlen = 1;
+ }
+ needed = MultiByteToWideChar(enc_codepage, MB_ERR_INVALID_CHARS,
+ (LPCSTR)from, fromlen - ip->bw_restlen,
+ (LPWSTR)to, needed);
+ if (needed == 0)
+ {
+ /* Safety check: Conversion doesn't work. */
+ ip->bw_conv_error = TRUE;
+ return FAIL;
+ }
+ to += needed * 2;
+ }
+
+ fromlen = to - ip->bw_conv_buf;
+ buf = to;
+# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
+ if (FIO_GET_CP(flags) == CP_UTF8)
+ {
+ /* Convert from UCS-2 to UTF-8, using the remainder of the
+ * conversion buffer. Fails when out of space. */
+ for (from = ip->bw_conv_buf; fromlen > 1; fromlen -= 2)
+ {
+ u8c = *from++;
+ u8c += (*from++ << 8);
+ to += utf_char2bytes(u8c, to);
+ if (to + 6 >= ip->bw_conv_buf + ip->bw_conv_buflen)
+ {
+ ip->bw_conv_error = TRUE;
+ return FAIL;
+ }
+ }
+ len = to - buf;
+ }
+ else
+#endif
+ {
+ /* Convert from UCS-2 to the codepage, using the remainder of
+ * the conversion buffer. If the conversion uses the default
+ * character "0", the data doesn't fit in this encoding, so
+ * fail. */
+ len = WideCharToMultiByte(FIO_GET_CP(flags), 0,
+ (LPCWSTR)ip->bw_conv_buf, (int)fromlen / sizeof(WCHAR),
+ (LPSTR)to, ip->bw_conv_buflen - fromlen, 0, &bad);
+ if (bad)
+ {
+ ip->bw_conv_error = TRUE;
+ return FAIL;
+ }
+ }
+ }
+# endif
+
+# ifdef MACOS_X
+ else if (flags & FIO_MACROMAN)
+ {
+ /*
+ * Convert UTF-8 or latin1 to Apple MacRoman.
+ */
+ CFStringRef cfstr;
+ CFRange r;
+ CFIndex l;
+ char_u *from;
+ size_t fromlen;
+
+ if (ip->bw_restlen > 0)
+ {
+ /* Need to concatenate the remainder of the previous call and
+ * the bytes of the current call. Use the end of the
+ * conversion buffer for this. */
+ fromlen = len + ip->bw_restlen;
+ from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
+ mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
+ mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
+ }
+ else
+ {
+ from = buf;
+ fromlen = len;
+ }
+
+ ip->bw_restlen = 0;
+ cfstr = CFStringCreateWithBytes(NULL, from, fromlen,
+ (enc_utf8) ?
+ kCFStringEncodingUTF8 : kCFStringEncodingISOLatin1,
+ 0);
+ while (cfstr == NULL && ip->bw_restlen < 3 && fromlen > 1)
+ {
+ ip->bw_rest[ip->bw_restlen++] = from[--fromlen];
+ cfstr = CFStringCreateWithBytes(NULL, from, fromlen,
+ (enc_utf8) ?
+ kCFStringEncodingUTF8 : kCFStringEncodingISOLatin1,
+ 0);
+ }
+ if (cfstr == NULL)
+ {
+ ip->bw_conv_error = TRUE;
+ return FAIL;
+ }
+
+ r.location = 0;
+ r.length = CFStringGetLength(cfstr);
+ if (r.length != CFStringGetBytes(cfstr, r,
+ kCFStringEncodingMacRoman,
+ 0, /* no lossy conversion */
+ 0, /* not external representation (since vim
+ * handles this internally */
+ ip->bw_conv_buf, ip->bw_conv_buflen, &l))
+ {
+ CFRelease(cfstr);
+ ip->bw_conv_error = TRUE;
+ return FAIL;
+ }
+ CFRelease(cfstr);
+ buf = ip->bw_conv_buf;
+ len = l;
+ }
+# endif
+
+# ifdef USE_ICONV
+ if (ip->bw_iconv_fd != (iconv_t)-1)
+ {
+ const char *from;
+ size_t fromlen;
+ char *to;
+ size_t tolen;
+
+ /* Convert with iconv(). */
+ if (ip->bw_restlen > 0)
+ {
+ /* Need to concatenate the remainder of the previous call and
+ * the bytes of the current call. Use the end of the
+ * conversion buffer for this. */
+ fromlen = len + ip->bw_restlen;
+ from = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
+ mch_memmove((void *)from, ip->bw_rest, (size_t)ip->bw_restlen);
+ mch_memmove((void *)(from + ip->bw_restlen), buf, (size_t)len);
+ tolen = ip->bw_conv_buflen - fromlen;
+ }
+ else
+ {
+ from = (const char *)buf;
+ fromlen = len;
+ tolen = ip->bw_conv_buflen;
+ }
+ to = (char *)ip->bw_conv_buf;
+
+ if (ip->bw_first)
+ {
+ size_t save_len = tolen;
+
+ /* output the initial shift state sequence */
+ (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
+
+ /* There is a bug in iconv() on Linux (which appears to be
+ * wide-spread) which sets "to" to NULL and messes up "tolen".
+ */
+ if (to == NULL)
+ {
+ to = (char *)ip->bw_conv_buf;
+ tolen = save_len;
+ }
+ ip->bw_first = FALSE;
+ }
+
+ /*
+ * If iconv() has an error or there is not enough room, fail.
+ */
+ if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
+ == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
+ || fromlen > CONV_RESTLEN)
+ {
+ ip->bw_conv_error = TRUE;
+ return FAIL;
+ }
+
+ /* copy remainder to ip->bw_rest[] to be used for the next call. */
+ if (fromlen > 0)
+ mch_memmove(ip->bw_rest, (void *)from, fromlen);
+ ip->bw_restlen = (int)fromlen;
+
+ buf = ip->bw_conv_buf;
+ len = (int)((char_u *)to - ip->bw_conv_buf);
+ }
+# endif
+ }
+#endif /* FEAT_MBYTE */
+
+#ifdef FEAT_CRYPT
+ if (flags & FIO_ENCRYPTED) /* encrypt the data */
+ {
+ int ztemp, t, i;
+
+ for (i = 0; i < len; i++)
+ {
+ ztemp = buf[i];
+ buf[i] = ZENCODE(ztemp, t);
+ }
+ }
+#endif
+
+ /* Repeat the write(), it may be interrupted by a signal. */
+ while (len)
+ {
+ wlen = vim_write(ip->bw_fd, buf, len);
+ if (wlen <= 0) /* error! */
+ return FAIL;
+ len -= wlen;
+ buf += wlen;
+ }
+ return OK;
+}
+
+#ifdef FEAT_MBYTE
+/*
+ * Convert a Unicode character to bytes.
+ */
+ static int
+ucs2bytes(c, pp, flags)
+ unsigned c; /* in: character */
+ char_u **pp; /* in/out: pointer to result */
+ int flags; /* FIO_ flags */
+{
+ char_u *p = *pp;
+ int error = FALSE;
+ int cc;
+
+
+ if (flags & FIO_UCS4)
+ {
+ if (flags & FIO_ENDIAN_L)
+ {
+ *p++ = c;
+ *p++ = (c >> 8);
+ *p++ = (c >> 16);
+ *p++ = (c >> 24);
+ }
+ else
+ {
+ *p++ = (c >> 24);
+ *p++ = (c >> 16);
+ *p++ = (c >> 8);
+ *p++ = c;
+ }
+ }
+ else if (flags & (FIO_UCS2 | FIO_UTF16))
+ {
+ if (c >= 0x10000)
+ {
+ if (flags & FIO_UTF16)
+ {
+ /* Make two words, ten bits of the character in each. First
+ * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
+ c -= 0x10000;
+ if (c >= 0x100000)
+ error = TRUE;
+ cc = ((c >> 10) & 0x3ff) + 0xd800;
+ if (flags & FIO_ENDIAN_L)
+ {
+ *p++ = cc;
+ *p++ = ((unsigned)cc >> 8);
+ }
+ else
+ {
+ *p++ = ((unsigned)cc >> 8);
+ *p++ = cc;
+ }
+ c = (c & 0x3ff) + 0xdc00;
+ }
+ else
+ error = TRUE;
+ }
+ if (flags & FIO_ENDIAN_L)
+ {
+ *p++ = c;
+ *p++ = (c >> 8);
+ }
+ else
+ {
+ *p++ = (c >> 8);
+ *p++ = c;
+ }
+ }
+ else /* Latin1 */
+ {
+ if (c >= 0x100)
+ {
+ error = TRUE;
+ *p++ = 0xBF;
+ }
+ else
+ *p++ = c;
+ }
+
+ *pp = p;
+ return error;
+}
+
+/*
+ * Return TRUE if "a" and "b" are the same 'encoding'.
+ * Ignores difference between "ansi" and "latin1", "ucs-4" and "ucs-4be", etc.
+ */
+ static int
+same_encoding(a, b)
+ char_u *a;
+ char_u *b;
+{
+ int f;
+
+ if (STRCMP(a, b) == 0)
+ return TRUE;
+ f = get_fio_flags(a);
+ return (f != 0 && get_fio_flags(b) == f);
+}
+
+/*
+ * Check "ptr" for a unicode encoding and return the FIO_ flags needed for the
+ * internal conversion.
+ * if "ptr" is an empty string, use 'encoding'.
+ */
+ static int
+get_fio_flags(ptr)
+ char_u *ptr;
+{
+ int prop;
+
+ if (*ptr == NUL)
+ ptr = p_enc;
+
+ prop = enc_canon_props(ptr);
+ if (prop & ENC_UNICODE)
+ {
+ if (prop & ENC_2BYTE)
+ {
+ if (prop & ENC_ENDIAN_L)
+ return FIO_UCS2 | FIO_ENDIAN_L;
+ return FIO_UCS2;
+ }
+ if (prop & ENC_4BYTE)
+ {
+ if (prop & ENC_ENDIAN_L)
+ return FIO_UCS4 | FIO_ENDIAN_L;
+ return FIO_UCS4;
+ }
+ if (prop & ENC_2WORD)
+ {
+ if (prop & ENC_ENDIAN_L)
+ return FIO_UTF16 | FIO_ENDIAN_L;
+ return FIO_UTF16;
+ }
+ return FIO_UTF8;
+ }
+ if (prop & ENC_LATIN1)
+ return FIO_LATIN1;
+ /* must be ENC_DBCS, requires iconv() */
+ return 0;
+}
+
+#ifdef WIN3264
+/*
+ * Check "ptr" for a MS-Windows codepage name and return the FIO_ flags needed
+ * for the conversion MS-Windows can do for us. Also accept "utf-8".
+ * Used for conversion between 'encoding' and 'fileencoding'.
+ */
+ static int
+get_win_fio_flags(ptr)
+ char_u *ptr;
+{
+ int cp;
+
+ /* Cannot do this when 'encoding' is not utf-8 and not a codepage. */
+ if (!enc_utf8 && enc_codepage <= 0)
+ return 0;
+
+ cp = encname2codepage(ptr);
+ if (cp == 0)
+ {
+# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
+ if (STRCMP(ptr, "utf-8") == 0)
+ cp = CP_UTF8;
+ else
+# endif
+ return 0;
+ }
+ return FIO_PUT_CP(cp) | FIO_CODEPAGE;
+}
+#endif
+
+#ifdef MACOS_X
+/*
+ * Check "ptr" for a Carbon supported encoding and return the FIO_ flags
+ * needed for the internal conversion to/from utf-8 or latin1.
+ */
+ static int
+get_mac_fio_flags(ptr)
+ char_u *ptr;
+{
+ if ((enc_utf8 || STRCMP(p_enc, "latin1") == 0)
+ && (enc_canon_props(ptr) & ENC_MACROMAN))
+ return FIO_MACROMAN;
+ return 0;
+}
+#endif
+
+/*
+ * Check for a Unicode BOM (Byte Order Mark) at the start of p[size].
+ * "size" must be at least 2.
+ * Return the name of the encoding and set "*lenp" to the length.
+ * Returns NULL when no BOM found.
+ */
+ static char_u *
+check_for_bom(p, size, lenp, flags)
+ char_u *p;
+ long size;
+ int *lenp;
+ int flags;
+{
+ char *name = NULL;
+ int len = 2;
+
+ if (p[0] == 0xef && p[1] == 0xbb && size >= 3 && p[2] == 0xbf
+ && (flags == FIO_ALL || flags == 0))
+ {
+ name = "utf-8"; /* EF BB BF */
+ len = 3;
+ }
+ else if (p[0] == 0xff && p[1] == 0xfe)
+ {
+ if (size >= 4 && p[2] == 0 && p[3] == 0
+ && (flags == FIO_ALL || flags == (FIO_UCS4 | FIO_ENDIAN_L)))
+ {
+ name = "ucs-4le"; /* FF FE 00 00 */
+ len = 4;
+ }
+ else if (flags == FIO_ALL || flags == (FIO_UCS2 | FIO_ENDIAN_L))
+ name = "ucs-2le"; /* FF FE */
+ else if (flags == (FIO_UTF16 | FIO_ENDIAN_L))
+ name = "utf-16le"; /* FF FE */
+ }
+ else if (p[0] == 0xfe && p[1] == 0xff
+ && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16))
+ {
+ if (flags == FIO_UTF16)
+ name = "utf-16"; /* FE FF */
+ else
+ name = "ucs-2"; /* FE FF */
+ }
+ else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
+ && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4))
+ {
+ name = "ucs-4"; /* 00 00 FE FF */
+ len = 4;
+ }
+
+ *lenp = len;
+ return (char_u *)name;
+}
+
+/*
+ * Generate a BOM in "buf[4]" for encoding "name".
+ * Return the length of the BOM (zero when no BOM).
+ */
+ static int
+make_bom(buf, name)
+ char_u *buf;
+ char_u *name;
+{
+ int flags;
+ char_u *p;
+
+ flags = get_fio_flags(name);
+
+ /* Can't put a BOM in a non-Unicode file. */
+ if (flags == FIO_LATIN1 || flags == 0)
+ return 0;
+
+ if (flags == FIO_UTF8) /* UTF-8 */
+ {
+ buf[0] = 0xef;
+ buf[1] = 0xbb;
+ buf[2] = 0xbf;
+ return 3;
+ }
+ p = buf;
+ (void)ucs2bytes(0xfeff, &p, flags);
+ return (int)(p - buf);
+}
+#endif
+
+/*
+ * Try to find a shortname by comparing the fullname with the current
+ * directory.
+ * Returns NULL if not shorter name possible, pointer into "full_path"
+ * otherwise.
+ */
+ char_u *
+shorten_fname(full_path, dir_name)
+ char_u *full_path;
+ char_u *dir_name;
+{
+ int len;
+ char_u *p;
+
+ if (full_path == NULL)
+ return NULL;
+ len = (int)STRLEN(dir_name);
+ if (fnamencmp(dir_name, full_path, len) == 0)
+ {
+ p = full_path + len;
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
+ /*
+ * MSDOS: when a file is in the root directory, dir_name will end in a
+ * slash, since C: by itself does not define a specific dir. In this
+ * case p may already be correct. <negri>
+ */
+ if (!((len > 2) && (*(p - 2) == ':')))
+#endif
+ {
+ if (vim_ispathsep(*p))
+ ++p;
+#ifndef VMS /* the path separator is always part of the path */
+ else
+ p = NULL;
+#endif
+ }
+ }
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
+ /*
+ * When using a file in the current drive, remove the drive name:
+ * "A:\dir\file" -> "\dir\file". This helps when moving a session file on
+ * a floppy from "A:\dir" to "B:\dir".
+ */
+ else if (len > 3
+ && TOUPPER_LOC(full_path[0]) == TOUPPER_LOC(dir_name[0])
+ && full_path[1] == ':'
+ && vim_ispathsep(full_path[2]))
+ p = full_path + 2;
+#endif
+ else
+ p = NULL;
+ return p;
+}
+
+/*
+ * Shorten filenames for all buffers.
+ * When "force" is TRUE: Use full path from now on for files currently being
+ * edited, both for file name and swap file name. Try to shorten the file
+ * names a bit, if safe to do so.
+ * When "force" is FALSE: Only try to shorten absolute file names.
+ * For buffers that have buftype "nofile" or "scratch": never change the file
+ * name.
+ */
+ void
+shorten_fnames(force)
+ int force;
+{
+ char_u dirname[MAXPATHL];
+ buf_T *buf;
+ char_u *p;
+
+ mch_dirname(dirname, MAXPATHL);
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ if (buf->b_fname != NULL
+#ifdef FEAT_QUICKFIX
+ && !bt_nofile(buf)
+#endif
+ && !path_with_url(buf->b_fname)
+ && (force
+ || buf->b_sfname == NULL
+ || mch_isFullName(buf->b_sfname)))
+ {
+ vim_free(buf->b_sfname);
+ buf->b_sfname = NULL;
+ p = shorten_fname(buf->b_ffname, dirname);
+ if (p != NULL)
+ {
+ buf->b_sfname = vim_strsave(p);
+ buf->b_fname = buf->b_sfname;
+ }
+ if (p == NULL || buf->b_fname == NULL)
+ buf->b_fname = buf->b_ffname;
+ mf_fullname(buf->b_ml.ml_mfp);
+ }
+ }
+#ifdef FEAT_WINDOWS
+ status_redraw_all();
+#endif
+}
+
+#if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
+ || defined(FEAT_GUI_MSWIN) \
+ || defined(FEAT_GUI_MAC) \
+ || defined(PROTO)
+/*
+ * Shorten all filenames in "fnames[count]" by current directory.
+ */
+ void
+shorten_filenames(fnames, count)
+ char_u **fnames;
+ int count;
+{
+ int i;
+ char_u dirname[MAXPATHL];
+ char_u *p;
+
+ if (fnames == NULL || count < 1)
+ return;
+ mch_dirname(dirname, sizeof(dirname));
+ for (i = 0; i < count; ++i)
+ {
+ if ((p = shorten_fname(fnames[i], dirname)) != NULL)
+ {
+ /* shorten_fname() returns pointer in given "fnames[i]". If free
+ * "fnames[i]" first, "p" becomes invalid. So we need to copy
+ * "p" first then free fnames[i]. */
+ p = vim_strsave(p);
+ vim_free(fnames[i]);
+ fnames[i] = p;
+ }
+ }
+}
+#endif
+
+/*
+ * add extention to file name - change path/fo.o.h to path/fo.o.h.ext or
+ * fo_o_h.ext for MSDOS or when shortname option set.
+ *
+ * Assumed that fname is a valid name found in the filesystem we assure that
+ * the return value is a different name and ends in 'ext'.
+ * "ext" MUST be at most 4 characters long if it starts with a dot, 3
+ * characters otherwise.
+ * Space for the returned name is allocated, must be freed later.
+ * Returns NULL when out of memory.
+ */
+ char_u *
+modname(fname, ext, prepend_dot)
+ char_u *fname, *ext;
+ int prepend_dot; /* may prepend a '.' to file name */
+{
+ return buf_modname(
+#ifdef SHORT_FNAME
+ TRUE,
+#else
+ (curbuf->b_p_sn || curbuf->b_shortname),
+#endif
+ fname, ext, prepend_dot);
+}
+
+ char_u *
+buf_modname(shortname, fname, ext, prepend_dot)
+ int shortname; /* use 8.3 file name */
+ char_u *fname, *ext;
+ int prepend_dot; /* may prepend a '.' to file name */
+{
+ char_u *retval;
+ char_u *s;
+ char_u *e;
+ char_u *ptr;
+ int fnamelen, extlen;
+
+ extlen = (int)STRLEN(ext);
+
+ /*
+ * If there is no file name we must get the name of the current directory
+ * (we need the full path in case :cd is used).
+ */
+ if (fname == NULL || *fname == NUL)
+ {
+ retval = alloc((unsigned)(MAXPATHL + extlen + 3));
+ if (retval == NULL)
+ return NULL;
+ if (mch_dirname(retval, MAXPATHL) == FAIL ||
+ (fnamelen = (int)STRLEN(retval)) == 0)
+ {
+ vim_free(retval);
+ return NULL;
+ }
+ if (!vim_ispathsep(retval[fnamelen - 1]))
+ {
+ retval[fnamelen++] = PATHSEP;
+ retval[fnamelen] = NUL;
+ }
+#ifndef SHORT_FNAME
+ prepend_dot = FALSE; /* nothing to prepend a dot to */
+#endif
+ }
+ else
+ {
+ fnamelen = (int)STRLEN(fname);
+ retval = alloc((unsigned)(fnamelen + extlen + 3));
+ if (retval == NULL)
+ return NULL;
+ STRCPY(retval, fname);
+#ifdef VMS
+ vms_remove_version(retval); /* we do not need versions here */
+#endif
+ }
+
+ /*
+ * search backwards until we hit a '/', '\' or ':' replacing all '.'
+ * by '_' for MSDOS or when shortname option set and ext starts with a dot.
+ * Then truncate what is after the '/', '\' or ':' to 8 characters for
+ * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
+ */
+ for (ptr = retval + fnamelen; ptr >= retval; ptr--)
+ {
+#ifndef RISCOS
+ if (*ext == '.'
+#ifdef USE_LONG_FNAME
+ && (!USE_LONG_FNAME || shortname)
+#else
+# ifndef SHORT_FNAME
+ && shortname
+# endif
+#endif
+ )
+ if (*ptr == '.') /* replace '.' by '_' */
+ *ptr = '_';
+#endif /* RISCOS */
+ if (vim_ispathsep(*ptr))
+ break;
+ }
+ ptr++;
+
+ /* the file name has at most BASENAMELEN characters. */
+#ifndef SHORT_FNAME
+ if (STRLEN(ptr) > (unsigned)BASENAMELEN)
+ ptr[BASENAMELEN] = '\0';
+#endif
+
+ s = ptr + STRLEN(ptr);
+
+ /*
+ * For 8.3 file names we may have to reduce the length.
+ */
+#ifdef USE_LONG_FNAME
+ if (!USE_LONG_FNAME || shortname)
+#else
+# ifndef SHORT_FNAME
+ if (shortname)
+# endif
+#endif
+ {
+ /*
+ * If there is no file name, or the file name ends in '/', and the
+ * extension starts with '.', put a '_' before the dot, because just
+ * ".ext" is invalid.
+ */
+ if (fname == NULL || *fname == NUL
+ || vim_ispathsep(fname[STRLEN(fname) - 1]))
+ {
+#ifdef RISCOS
+ if (*ext == '/')
+#else
+ if (*ext == '.')
+#endif
+ *s++ = '_';
+ }
+ /*
+ * If the extension starts with '.', truncate the base name at 8
+ * characters
+ */
+#ifdef RISCOS
+ /* We normally use '/', but swap files are '_' */
+ else if (*ext == '/' || *ext == '_')
+#else
+ else if (*ext == '.')
+#endif
+ {
+ if (s - ptr > (size_t)8)
+ {
+ s = ptr + 8;
+ *s = '\0';
+ }
+ }
+ /*
+ * If the extension doesn't start with '.', and the file name
+ * doesn't have an extension yet, append a '.'
+ */
+#ifdef RISCOS
+ else if ((e = vim_strchr(ptr, '/')) == NULL)
+ *s++ = '/';
+#else
+ else if ((e = vim_strchr(ptr, '.')) == NULL)
+ *s++ = '.';
+#endif
+ /*
+ * If the extension doesn't start with '.', and there already is an
+ * extension, it may need to be tructated
+ */
+ else if ((int)STRLEN(e) + extlen > 4)
+ s = e + 4 - extlen;
+ }
+#if defined(OS2) || defined(USE_LONG_FNAME) || defined(WIN3264)
+ /*
+ * If there is no file name, and the extension starts with '.', put a
+ * '_' before the dot, because just ".ext" may be invalid if it's on a
+ * FAT partition, and on HPFS it doesn't matter.
+ */
+ else if ((fname == NULL || *fname == NUL) && *ext == '.')
+ *s++ = '_';
+#endif
+
+ /*
+ * Append the extention.
+ * ext can start with '.' and cannot exceed 3 more characters.
+ */
+ STRCPY(s, ext);
+
+#ifndef SHORT_FNAME
+ /*
+ * Prepend the dot.
+ */
+ if (prepend_dot && !shortname && *(e = gettail(retval)) !=
+#ifdef RISCOS
+ '/'
+#else
+ '.'
+#endif
+#ifdef USE_LONG_FNAME
+ && USE_LONG_FNAME
+#endif
+ )
+ {
+ mch_memmove(e + 1, e, STRLEN(e) + 1);
+#ifdef RISCOS
+ *e = '/';
+#else
+ *e = '.';
+#endif
+ }
+#endif
+
+ /*
+ * Check that, after appending the extension, the file name is really
+ * different.
+ */
+ if (fname != NULL && STRCMP(fname, retval) == 0)
+ {
+ /* we search for a character that can be replaced by '_' */
+ while (--s >= ptr)
+ {
+ if (*s != '_')
+ {
+ *s = '_';
+ break;
+ }
+ }
+ if (s < ptr) /* fname was "________.<ext>", how tricky! */
+ *ptr = 'v';
+ }
+ return retval;
+}
+
+/*
+ * Like fgets(), but if the file line is too long, it is truncated and the
+ * rest of the line is thrown away. Returns TRUE for end-of-file.
+ */
+ int
+vim_fgets(buf, size, fp)
+ char_u *buf;
+ int size;
+ FILE *fp;
+{
+ char *eof;
+#define FGETS_SIZE 200
+ char tbuf[FGETS_SIZE];
+
+ buf[size - 2] = NUL;
+#ifdef USE_CR
+ eof = fgets_cr((char *)buf, size, fp);
+#else
+ eof = fgets((char *)buf, size, fp);
+#endif
+ if (buf[size - 2] != NUL && buf[size - 2] != '\n')
+ {
+ buf[size - 1] = NUL; /* Truncate the line */
+
+ /* Now throw away the rest of the line: */
+ do
+ {
+ tbuf[FGETS_SIZE - 2] = NUL;
+#ifdef USE_CR
+ fgets_cr((char *)tbuf, FGETS_SIZE, fp);
+#else
+ fgets((char *)tbuf, FGETS_SIZE, fp);
+#endif
+ } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n');
+ }
+ return (eof == NULL);
+}
+
+#if defined(USE_CR) || defined(PROTO)
+/*
+ * Like vim_fgets(), but accept any line terminator: CR, CR-LF or LF.
+ * Returns TRUE for end-of-file.
+ * Only used for the Mac, because it's much slower than vim_fgets().
+ */
+ int
+tag_fgets(buf, size, fp)
+ char_u *buf;
+ int size;
+ FILE *fp;
+{
+ int i = 0;
+ int c;
+ int eof = FALSE;
+
+ for (;;)
+ {
+ c = fgetc(fp);
+ if (c == EOF)
+ {
+ eof = TRUE;
+ break;
+ }
+ if (c == '\r')
+ {
+ /* Always store a NL for end-of-line. */
+ if (i < size - 1)
+ buf[i++] = '\n';
+ c = fgetc(fp);
+ if (c != '\n') /* Macintosh format: single CR. */
+ ungetc(c, fp);
+ break;
+ }
+ if (i < size - 1)
+ buf[i++] = c;
+ if (c == '\n')
+ break;
+ }
+ buf[i] = NUL;
+ return eof;
+}
+#endif
+
+/*
+ * rename() only works if both files are on the same file system, this
+ * function will (attempts to?) copy the file across if rename fails -- webb
+ * Return -1 for failure, 0 for success.
+ */
+ int
+vim_rename(from, to)
+ char_u *from;
+ char_u *to;
+{
+ int fd_in;
+ int fd_out;
+ int n;
+ char *errmsg = NULL;
+ char *buffer;
+#ifdef AMIGA
+ BPTR flock;
+#endif
+ struct stat st;
+
+ /*
+ * When the names are identical, there is nothing to do.
+ */
+ if (fnamecmp(from, to) == 0)
+ return 0;
+
+ /*
+ * Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
+ */
+ if (mch_stat((char *)from, &st) < 0)
+ return -1;
+
+ /*
+ * Delete the "to" file, this is required on some systems to make the
+ * mch_rename() work, on other systems it makes sure that we don't have
+ * two files when the mch_rename() fails.
+ */
+
+#ifdef AMIGA
+ /*
+ * With MSDOS-compatible filesystems (crossdos, messydos) it is possible
+ * that the name of the "to" file is the same as the "from" file, even
+ * though the names are different. To avoid the chance of accidently
+ * deleting the "from" file (horror!) we lock it during the remove.
+ *
+ * When used for making a backup before writing the file: This should not
+ * happen with ":w", because startscript() should detect this problem and
+ * set buf->b_shortname, causing modname() to return a correct ".bak" file
+ * name. This problem does exist with ":w filename", but then the
+ * original file will be somewhere else so the backup isn't really
+ * important. If autoscripting is off the rename may fail.
+ */
+ flock = Lock((UBYTE *)from, (long)ACCESS_READ);
+#endif
+ mch_remove(to);
+#ifdef AMIGA
+ if (flock)
+ UnLock(flock);
+#endif
+
+ /*
+ * First try a normal rename, return if it works.
+ */
+ if (mch_rename((char *)from, (char *)to) == 0)
+ return 0;
+
+ /*
+ * Rename() failed, try copying the file.
+ */
+ fd_in = mch_open((char *)from, O_RDONLY|O_EXTRA, 0);
+ if (fd_in == -1)
+ return -1;
+ fd_out = mch_open((char *)to, O_CREAT|O_EXCL|O_WRONLY|O_EXTRA, 0666);
+ if (fd_out == -1)
+ {
+ close(fd_in);
+ return -1;
+ }
+
+ buffer = (char *)alloc(BUFSIZE);
+ if (buffer == NULL)
+ {
+ close(fd_in);
+ close(fd_out);
+ return -1;
+ }
+
+ while ((n = vim_read(fd_in, buffer, BUFSIZE)) > 0)
+ if (vim_write(fd_out, buffer, n) != n)
+ {
+ errmsg = _("E208: Error writing to \"%s\"");
+ break;
+ }
+
+ vim_free(buffer);
+ close(fd_in);
+ if (close(fd_out) < 0)
+ errmsg = _("E209: Error closing \"%s\"");
+ if (n < 0)
+ {
+ errmsg = _("E210: Error reading \"%s\"");
+ to = from;
+ }
+ if (errmsg != NULL)
+ {
+ EMSG2(errmsg, to);
+ return -1;
+ }
+ mch_remove(from);
+ return 0;
+}
+
+static int already_warned = FALSE;
+
+/*
+ * Check if any not hidden buffer has been changed.
+ * Postpone the check if there are characters in the stuff buffer, a global
+ * command is being executed, a mapping is being executed or an autocommand is
+ * busy.
+ * Returns TRUE if some message was written (screen should be redrawn and
+ * cursor positioned).
+ */
+ int
+check_timestamps(focus)
+ int focus; /* called for GUI focus event */
+{
+ buf_T *buf;
+ int didit = 0;
+ int n;
+
+ /* Don't check timestamps while system() or another low-level function may
+ * cause us to lose and gain focus. */
+ if (no_check_timestamps > 0)
+ return FALSE;
+
+ /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
+ * event and we would keep on checking if the file is steadily growing.
+ * Do check again after typing something. */
+ if (focus && did_check_timestamps)
+ {
+ need_check_timestamps = TRUE;
+ return FALSE;
+ }
+
+ if (!stuff_empty() || global_busy || !typebuf_typed()
+#ifdef FEAT_AUTOCMD
+ || autocmd_busy
+#endif
+ )
+ need_check_timestamps = TRUE; /* check later */
+ else
+ {
+ ++no_wait_return;
+ did_check_timestamps = TRUE;
+ already_warned = FALSE;
+ for (buf = firstbuf; buf != NULL; )
+ {
+ /* Only check buffers in a window. */
+ if (buf->b_nwindows > 0)
+ {
+ n = buf_check_timestamp(buf, focus);
+ if (didit < n)
+ didit = n;
+ if (n > 0 && !buf_valid(buf))
+ {
+ /* Autocommands have removed the buffer, start at the
+ * first one again. */
+ buf = firstbuf;
+ continue;
+ }
+ }
+ buf = buf->b_next;
+ }
+ --no_wait_return;
+ need_check_timestamps = FALSE;
+ if (need_wait_return && didit == 2)
+ {
+ /* make sure msg isn't overwritten */
+ msg_puts((char_u *)"\n");
+ out_flush();
+ }
+ }
+ return didit;
+}
+
+/*
+ * Move all the lines from buffer "frombuf" to buffer "tobuf".
+ * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
+ * empty.
+ */
+ static int
+move_lines(frombuf, tobuf)
+ buf_T *frombuf;
+ buf_T *tobuf;
+{
+ buf_T *tbuf = curbuf;
+ int retval = OK;
+ linenr_T lnum;
+ char_u *p;
+
+ /* Copy the lines in "frombuf" to "tobuf". */
+ curbuf = tobuf;
+ for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
+ {
+ p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
+ if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
+ {
+ vim_free(p);
+ retval = FAIL;
+ break;
+ }
+ vim_free(p);
+ }
+
+ /* Delete all the lines in "frombuf". */
+ if (retval != FAIL)
+ {
+ curbuf = frombuf;
+ while (!bufempty())
+ if (ml_delete(curbuf->b_ml.ml_line_count, FALSE) == FAIL)
+ {
+ /* Oops! We could try putting back the saved lines, but that
+ * might fail again... */
+ retval = FAIL;
+ break;
+ }
+ }
+
+ curbuf = tbuf;
+ return retval;
+}
+
+/*
+ * Check if buffer "buf" has been changed.
+ * Also check if the file for a new buffer unexpectedly appeared.
+ * return 1 if a changed buffer was found.
+ * return 2 if a message has been displayed.
+ * return 0 otherwise.
+ */
+/*ARGSUSED*/
+ int
+buf_check_timestamp(buf, focus)
+ buf_T *buf;
+ int focus; /* called for GUI focus event */
+{
+ struct stat st;
+ int stat_res;
+ int retval = 0;
+ char_u *path;
+ char_u *tbuf;
+ char *mesg = NULL;
+ char *mesg2;
+ int helpmesg = FALSE;
+ int reload = FALSE;
+#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
+ int can_reload = FALSE;
+#endif
+ size_t orig_size = buf->b_orig_size;
+ int orig_mode = buf->b_orig_mode;
+#ifdef FEAT_GUI
+ int save_mouse_correct = need_mouse_correct;
+#endif
+#ifdef FEAT_AUTOCMD
+ static int busy = FALSE;
+#endif
+
+ /* If there is no file name, the buffer is not loaded, 'buftype' is
+ * set, we are in the middle of a save or being called recursively: ignore
+ * this buffer. */
+ if (buf->b_ffname == NULL
+ || buf->b_ml.ml_mfp == NULL
+#if defined(FEAT_QUICKFIX)
+ || *buf->b_p_bt != NUL
+#endif
+ || buf->b_saving
+#ifdef FEAT_AUTOCMD
+ || busy
+#endif
+ )
+ return 0;
+
+ if ( !(buf->b_flags & BF_NOTEDITED)
+ && buf->b_mtime != 0
+ && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
+ || time_differs((long)st.st_mtime, buf->b_mtime)
+#ifdef HAVE_ST_MODE
+ || (int)st.st_mode != buf->b_orig_mode
+#else
+ || mch_getperm(buf->b_ffname) != buf->b_orig_mode
+#endif
+ ))
+ {
+ retval = 1;
+
+ /* set b_mtime to stop further warnings */
+ if (stat_res < 0)
+ {
+ buf->b_mtime = 0;
+ buf->b_orig_size = 0;
+ buf->b_orig_mode = 0;
+ }
+ else
+ buf_store_time(buf, &st, buf->b_ffname);
+
+ /* Don't do anything for a directory. Might contain the file
+ * explorer. */
+ if (mch_isdir(buf->b_fname))
+ ;
+
+ /*
+ * If 'autoread' is set, the buffer has no changes and the file still
+ * exists, reload the buffer. Use the buffer-local option value if it
+ * was set, the global option value otherwise.
+ */
+ else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
+ && !bufIsChanged(buf) && stat_res >= 0)
+ reload = TRUE;
+ else
+ {
+#ifdef FEAT_AUTOCMD
+ int n;
+
+ /*
+ * Only give the warning if there are no FileChangedShell
+ * autocommands.
+ * Avoid being called recursively by setting "busy".
+ */
+ busy = TRUE;
+ n = apply_autocmds(EVENT_FILECHANGEDSHELL,
+ buf->b_fname, buf->b_fname, FALSE, buf);
+ busy = FALSE;
+ if (n)
+ {
+ if (!buf_valid(buf))
+ EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
+ return 2;
+ }
+ else
+#endif
+ {
+ if (stat_res < 0)
+ mesg = _("E211: Warning: File \"%s\" no longer available");
+ else
+ {
+ helpmesg = TRUE;
+#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
+ can_reload = TRUE;
+#endif
+ /*
+ * Check if the file contents really changed to avoid
+ * giving a warning when only the timestamp was set (e.g.,
+ * checked out of CVS). Always warn when the buffer was
+ * changed.
+ */
+ if (bufIsChanged(buf))
+ mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
+ else if (orig_size != buf->b_orig_size
+ || buf_contents_changed(buf))
+ mesg = _("W11: Warning: File \"%s\" has changed since editing started");
+ else if (orig_mode != buf->b_orig_mode)
+ mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
+ }
+ }
+ }
+
+ }
+ else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
+ && vim_fexists(buf->b_ffname))
+ {
+ retval = 1;
+ mesg = _("W13: Warning: File \"%s\" has been created after editing started");
+ buf->b_flags |= BF_NEW_W;
+#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
+ can_reload = TRUE;
+#endif
+ }
+
+ if (mesg != NULL)
+ {
+ path = home_replace_save(buf, buf->b_fname);
+ if (path != NULL)
+ {
+ if (helpmesg)
+ mesg2 = _("See \":help W11\" for more info.");
+ else
+ mesg2 = "";
+ tbuf = alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
+ + STRLEN(mesg2) + 2));
+ sprintf((char *)tbuf, mesg, path);
+#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
+ if (can_reload)
+ {
+ if (*mesg2 != NUL)
+ {
+ STRCAT(tbuf, "\n");
+ STRCAT(tbuf, mesg2);
+ }
+ if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
+ (char_u *)_("&OK\n&Load File"), 1, NULL) == 2)
+ reload = TRUE;
+ }
+ else
+#endif
+ if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
+ {
+ if (*mesg2 != NUL)
+ {
+ STRCAT(tbuf, "; ");
+ STRCAT(tbuf, mesg2);
+ }
+ EMSG(tbuf);
+ retval = 2;
+ }
+ else
+ {
+# ifdef VIMBUDDY
+ VimBuddyText(tbuf + 9, 2);
+# else
+# ifdef FEAT_AUTOCMD
+ if (!autocmd_busy)
+# endif
+ {
+ msg_start();
+ msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
+ if (*mesg2 != NUL)
+ msg_puts_attr((char_u *)mesg2,
+ hl_attr(HLF_W) + MSG_HIST);
+ msg_clr_eos();
+ (void)msg_end();
+ if (emsg_silent == 0)
+ {
+ out_flush();
+# ifdef FEAT_GUI
+ if (!focus)
+# endif
+ /* give the user some time to think about it */
+ ui_delay(1000L, TRUE);
+
+ /* don't redraw and erase the message */
+ redraw_cmdline = FALSE;
+ }
+ }
+ already_warned = TRUE;
+# endif
+ }
+
+ vim_free(path);
+ vim_free(tbuf);
+ }
+ }
+
+ if (reload)
+ {
+ exarg_T ea;
+ pos_T old_cursor;
+ linenr_T old_topline;
+ int old_ro = buf->b_p_ro;
+ buf_T *savebuf;
+ int saved = OK;
+#ifdef FEAT_AUTOCMD
+ aco_save_T aco;
+
+ /* set curwin/curbuf for "buf" and save some things */
+ aucmd_prepbuf(&aco, buf);
+#else
+ buf_T *save_curbuf = curbuf;
+
+ curbuf = buf;
+ curwin->w_buffer = buf;
+#endif
+
+ /* We only want to read the text from the file, not reset the syntax
+ * highlighting, clear marks, diff status, etc. Force the fileformat
+ * and encoding to be the same. */
+ if (prep_exarg(&ea, buf) == OK)
+ {
+ old_cursor = curwin->w_cursor;
+ old_topline = curwin->w_topline;
+
+ /*
+ * To behave like when a new file is edited (matters for
+ * BufReadPost autocommands) we first need to delete the current
+ * buffer contents. But if reading the file fails we should keep
+ * the old contents. Can't use memory only, the file might be
+ * too big. Use a hidden buffer to move the buffer contents to.
+ */
+ if (bufempty())
+ savebuf = NULL;
+ else
+ {
+ /* Allocate a buffer without putting it in the buffer list. */
+ savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
+ if (savebuf != NULL)
+ {
+ /* Open the memline. */
+ curbuf = savebuf;
+ curwin->w_buffer = savebuf;
+ saved = ml_open();
+ curbuf = buf;
+ curwin->w_buffer = buf;
+ }
+ if (savebuf == NULL || saved == FAIL
+ || move_lines(buf, savebuf) == FAIL)
+ {
+ EMSG2(_("E462: Could not prepare for reloading \"%s\""),
+ buf->b_fname);
+ saved = FAIL;
+ }
+ }
+
+ if (saved == OK)
+ {
+ curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
+#ifdef FEAT_AUTOCMD
+ keep_filetype = TRUE; /* don't detect 'filetype' */
+#endif
+ if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
+ (linenr_T)0,
+ (linenr_T)MAXLNUM, &ea, READ_NEW) == FAIL)
+ {
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+ if (!aborting())
+#endif
+ EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
+ if (savebuf != NULL)
+ {
+ /* Put the text back from the save buffer. First
+ * delete any lines that readfile() added. */
+ while (!bufempty())
+ if (ml_delete(curbuf->b_ml.ml_line_count, FALSE)
+ == FAIL)
+ break;
+ (void)move_lines(savebuf, buf);
+ }
+ }
+ else
+ {
+ /* Mark the buffer as unmodified and free undo info. */
+ unchanged(buf, TRUE);
+ u_blockfree(buf);
+ u_clearall(buf);
+ }
+ }
+ vim_free(ea.cmd);
+
+ if (savebuf != NULL)
+ wipe_buffer(savebuf, FALSE);
+
+#ifdef FEAT_DIFF
+ /* Invalidate diff info if necessary. */
+ diff_invalidate();
+#endif
+
+ /* Restore the topline and cursor position and check it (lines may
+ * have been removed). */
+ if (old_topline > curbuf->b_ml.ml_line_count)
+ curwin->w_topline = curbuf->b_ml.ml_line_count;
+ else
+ curwin->w_topline = old_topline;
+ curwin->w_cursor = old_cursor;
+ check_cursor();
+ update_topline();
+#ifdef FEAT_AUTOCMD
+ keep_filetype = FALSE;
+#endif
+#ifdef FEAT_FOLDING
+ {
+ win_T *wp;
+
+ /* Update folds unless they are defined manually. */
+ FOR_ALL_WINDOWS(wp)
+ if (wp->w_buffer == curwin->w_buffer
+ && !foldmethodIsManual(wp))
+ foldUpdateAll(wp);
+ }
+#endif
+ /* If the mode didn't change and 'readonly' was set, keep the old
+ * value; the user probably used the ":view" command. But don't
+ * reset it, might have had a read error. */
+ if (orig_mode == curbuf->b_orig_mode)
+ curbuf->b_p_ro |= old_ro;
+ }
+
+#ifdef FEAT_AUTOCMD
+ /* restore curwin/curbuf and a few other things */
+ aucmd_restbuf(&aco);
+ /* Careful: autocommands may have made "buf" invalid! */
+#else
+ curwin->w_buffer = save_curbuf;
+ curbuf = save_curbuf;
+#endif
+ }
+
+#ifdef FEAT_GUI
+ /* restore this in case an autocommand has set it; it would break
+ * 'mousefocus' */
+ need_mouse_correct = save_mouse_correct;
+#endif
+
+ return retval;
+}
+
+/*ARGSUSED*/
+ void
+buf_store_time(buf, st, fname)
+ buf_T *buf;
+ struct stat *st;
+ char_u *fname;
+{
+ buf->b_mtime = (long)st->st_mtime;
+ buf->b_orig_size = (size_t)st->st_size;
+#ifdef HAVE_ST_MODE
+ buf->b_orig_mode = (int)st->st_mode;
+#else
+ buf->b_orig_mode = mch_getperm(fname);
+#endif
+}
+
+/*
+ * Adjust the line with missing eol, used for the next write.
+ * Used for do_filter(), when the input lines for the filter are deleted.
+ */
+ void
+write_lnum_adjust(offset)
+ linenr_T offset;
+{
+ if (write_no_eol_lnum) /* only if there is a missing eol */
+ write_no_eol_lnum += offset;
+}
+
+#if defined(TEMPDIRNAMES) || defined(PROTO)
+static long temp_count = 0; /* Temp filename counter. */
+
+/*
+ * Delete the temp directory and all files it contains.
+ */
+ void
+vim_deltempdir()
+{
+ char_u **files;
+ int file_count;
+ int i;
+
+ if (vim_tempdir != NULL)
+ {
+ sprintf((char *)NameBuff, "%s*", vim_tempdir);
+ if (gen_expand_wildcards(1, &NameBuff, &file_count, &files,
+ EW_DIR|EW_FILE|EW_SILENT) == OK)
+ {
+ for (i = 0; i < file_count; ++i)
+ mch_remove(files[i]);
+ FreeWild(file_count, files);
+ }
+ gettail(NameBuff)[-1] = NUL;
+ (void)mch_rmdir(NameBuff);
+
+ vim_free(vim_tempdir);
+ vim_tempdir = NULL;
+ }
+}
+#endif
+
+/*
+ * vim_tempname(): Return a unique name that can be used for a temp file.
+ *
+ * The temp file is NOT created.
+ *
+ * The returned pointer is to allocated memory.
+ * The returned pointer is NULL if no valid name was found.
+ */
+/*ARGSUSED*/
+ char_u *
+vim_tempname(extra_char)
+ int extra_char; /* character to use in the name instead of '?' */
+{
+#ifdef USE_TMPNAM
+ char_u itmp[L_tmpnam]; /* use tmpnam() */
+#else
+ char_u itmp[TEMPNAMELEN];
+#endif
+
+#ifdef TEMPDIRNAMES
+ static char *(tempdirs[]) = {TEMPDIRNAMES};
+ int i;
+ long nr;
+ long off;
+# ifndef EEXIST
+ struct stat st;
+# endif
+
+ /*
+ * This will create a directory for private use by this instance of Vim.
+ * This is done once, and the same directory is used for all temp files.
+ * This method avoids security problems because of symlink attacks et al.
+ * It's also a bit faster, because we only need to check for an existing
+ * file when creating the directory and not for each temp file.
+ */
+ if (vim_tempdir == NULL)
+ {
+ /*
+ * Try the entries in TEMPDIRNAMES to create the temp directory.
+ */
+ for (i = 0; i < sizeof(tempdirs) / sizeof(char *); ++i)
+ {
+ /* expand $TMP, leave room for "/v1100000/999999999" */
+ expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
+ if (mch_isdir(itmp)) /* directory exists */
+ {
+# ifdef __EMX__
+ /* If $TMP contains a forward slash (perhaps using bash or
+ * tcsh), don't add a backslash, use a forward slash!
+ * Adding 2 backslashes didn't work. */
+ if (vim_strchr(itmp, '/') != NULL)
+ STRCAT(itmp, "/");
+ else
+# endif
+ add_pathsep(itmp);
+
+ /* Get an arbitrary number of up to 6 digits. When it's
+ * unlikely that it already exists it will be faster,
+ * otherwise it doesn't matter. The use of mkdir() avoids any
+ * security problems because of the predictable number. */
+ nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
+
+ /* Try up to 10000 different values until we find a name that
+ * doesn't exist. */
+ for (off = 0; off < 10000L; ++off)
+ {
+ int r;
+#if defined(UNIX) || defined(VMS)
+ mode_t umask_save;
+#endif
+
+ sprintf((char *)itmp + STRLEN(itmp), "v%ld", nr + off);
+# ifndef EEXIST
+ /* If mkdir() does not set errno to EEXIST, check for
+ * existing file here. There is a race condition then,
+ * although it's fail-safe. */
+ if (mch_stat((char *)itmp, &st) >= 0)
+ continue;
+# endif
+#if defined(UNIX) || defined(VMS)
+ /* Make sure the umask doesn't remove the executable bit.
+ * "repl" has been reported to use "177". */
+ umask_save = umask(077);
+#endif
+ r = vim_mkdir(itmp, 0700);
+#if defined(UNIX) || defined(VMS)
+ (void)umask(umask_save);
+#endif
+ if (r == 0)
+ {
+ char_u *buf;
+
+ /* Directory was created, use this name.
+ * Expand to full path; When using the current
+ * directory a ":cd" would confuse us. */
+ buf = alloc((unsigned)MAXPATHL + 1);
+ if (buf != NULL)
+ {
+ if (vim_FullName(itmp, buf, MAXPATHL, FALSE)
+ == FAIL)
+ STRCPY(buf, itmp);
+# ifdef __EMX__
+ if (vim_strchr(buf, '/') != NULL)
+ STRCAT(buf, "/");
+ else
+# endif
+ add_pathsep(buf);
+ vim_tempdir = vim_strsave(buf);
+ vim_free(buf);
+ }
+ break;
+ }
+# ifdef EEXIST
+ /* If the mkdir() didn't fail because the file/dir exists,
+ * we probably can't create any dir here, try another
+ * place. */
+ if (errno != EEXIST)
+# endif
+ break;
+ }
+ if (vim_tempdir != NULL)
+ break;
+ }
+ }
+ }
+
+ if (vim_tempdir != NULL)
+ {
+ /* There is no need to check if the file exists, because we own the
+ * directory and nobody else creates a file in it. */
+ sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
+ return vim_strsave(itmp);
+ }
+
+ return NULL;
+
+#else /* TEMPDIRNAMES */
+
+# ifdef WIN3264
+ char szTempFile[_MAX_PATH + 1];
+ char buf4[4];
+ char_u *retval;
+ char_u *p;
+
+ STRCPY(itmp, "");
+ if (GetTempPath(_MAX_PATH, szTempFile) == 0)
+ szTempFile[0] = NUL; /* GetTempPath() failed, use current dir */
+ strcpy(buf4, "VIM");
+ buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
+ if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0)
+ return NULL;
+ /* GetTempFileName() will create the file, we don't want that */
+ (void)DeleteFile(itmp);
+
+ /* Backslashes in a temp file name cause problems when filtering with
+ * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
+ * didn't set 'shellslash'. */
+ retval = vim_strsave(itmp);
+ if (*p_shcf == '-' || p_ssl)
+ for (p = retval; *p; ++p)
+ if (*p == '\\')
+ *p = '/';
+ return retval;
+
+# else /* WIN3264 */
+
+# ifdef USE_TMPNAM
+ /* tmpnam() will make its own name */
+ if (*tmpnam((char *)itmp) == NUL)
+ return NULL;
+# else
+ char_u *p;
+
+# ifdef VMS_TEMPNAM
+ /* mktemp() is not working on VMS. It seems to be
+ * a do-nothing function. Therefore we use tempnam().
+ */
+ sprintf((char *)itmp, "VIM%c", extra_char);
+ p = (char_u *)tempnam("tmp:", (char *)itmp);
+ if (p != NULL)
+ {
+ /* VMS will use '.LOG' if we don't explicitly specify an extension,
+ * and VIM will then be unable to find the file later */
+ STRCPY(itmp, p);
+ STRCAT(itmp, ".txt");
+ free(p);
+ }
+ else
+ return NULL;
+# else
+ STRCPY(itmp, TEMPNAME);
+ if ((p = vim_strchr(itmp, '?')) != NULL)
+ *p = extra_char;
+ if (mktemp((char *)itmp) == NULL)
+ return NULL;
+# endif
+# endif
+
+ return vim_strsave(itmp);
+# endif /* WIN3264 */
+#endif /* TEMPDIRNAMES */
+}
+
+#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
+/*
+ * Convert all backslashes in fname to forward slashes in-place.
+ */
+ void
+forward_slash(fname)
+ char_u *fname;
+{
+ char_u *p;
+
+ for (p = fname; *p != NUL; ++p)
+# ifdef FEAT_MBYTE
+ /* The Big5 encoding can have '\' in the trail byte. */
+ if (enc_dbcs != 0 && (*mb_ptr2len_check)(p) > 1)
+ ++p;
+ else
+# endif
+ if (*p == '\\')
+ *p = '/';
+}
+#endif
+
+
+/*
+ * Code for automatic commands.
+ *
+ * Only included when "FEAT_AUTOCMD" has been defined.
+ */
+
+#if defined(FEAT_AUTOCMD) || defined(PROTO)
+
+/*
+ * The autocommands are stored in a list for each event.
+ * Autocommands for the same pattern, that are consecutive, are joined
+ * together, to avoid having to match the pattern too often.
+ * The result is an array of Autopat lists, which point to AutoCmd lists:
+ *
+ * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
+ * Autopat.cmds Autopat.cmds
+ * | |
+ * V V
+ * AutoCmd.next AutoCmd.next
+ * | |
+ * V V
+ * AutoCmd.next NULL
+ * |
+ * V
+ * NULL
+ *
+ * first_autopat[1] --> Autopat.next --> NULL
+ * Autopat.cmds
+ * |
+ * V
+ * AutoCmd.next
+ * |
+ * V
+ * NULL
+ * etc.
+ *
+ * The order of AutoCmds is important, this is the order in which they were
+ * defined and will have to be executed.
+ */
+typedef struct AutoCmd
+{
+ char_u *cmd; /* The command to be executed (NULL
+ when command has been removed) */
+ char nested; /* If autocommands nest here */
+ char last; /* last command in list */
+#ifdef FEAT_EVAL
+ scid_T scriptID; /* script ID where defined */
+#endif
+ struct AutoCmd *next; /* Next AutoCmd in list */
+} AutoCmd;
+
+typedef struct AutoPat
+{
+ int group; /* group ID */
+ char_u *pat; /* pattern as typed (NULL when pattern
+ has been removed) */
+ int patlen; /* strlen() of pat */
+ char_u *reg_pat; /* pattern converted to regexp */
+ char allow_dirs; /* Pattern may match whole path */
+ char last; /* last pattern for apply_autocmds() */
+ AutoCmd *cmds; /* list of commands to do */
+ struct AutoPat *next; /* next AutoPat in AutoPat list */
+} AutoPat;
+
+static struct event_name
+{
+ char *name; /* event name */
+ EVENT_T event; /* event number */
+} event_names[] =
+{
+ {"BufAdd", EVENT_BUFADD},
+ {"BufCreate", EVENT_BUFADD},
+ {"BufDelete", EVENT_BUFDELETE},
+ {"BufEnter", EVENT_BUFENTER},
+ {"BufFilePost", EVENT_BUFFILEPOST},
+ {"BufFilePre", EVENT_BUFFILEPRE},
+ {"BufHidden", EVENT_BUFHIDDEN},
+ {"BufLeave", EVENT_BUFLEAVE},
+ {"BufNew", EVENT_BUFNEW},
+ {"BufNewFile", EVENT_BUFNEWFILE},
+ {"BufRead", EVENT_BUFREADPOST},
+ {"BufReadCmd", EVENT_BUFREADCMD},
+ {"BufReadPost", EVENT_BUFREADPOST},
+ {"BufReadPre", EVENT_BUFREADPRE},
+ {"BufUnload", EVENT_BUFUNLOAD},
+ {"BufWinEnter", EVENT_BUFWINENTER},
+ {"BufWinLeave", EVENT_BUFWINLEAVE},
+ {"BufWipeout", EVENT_BUFWIPEOUT},
+ {"BufWrite", EVENT_BUFWRITEPRE},
+ {"BufWritePost", EVENT_BUFWRITEPOST},
+ {"BufWritePre", EVENT_BUFWRITEPRE},
+ {"BufWriteCmd", EVENT_BUFWRITECMD},
+ {"CmdwinEnter", EVENT_CMDWINENTER},
+ {"CmdwinLeave", EVENT_CMDWINLEAVE},
+ {"EncodingChanged", EVENT_ENCODINGCHANGED},
+ {"FileEncoding", EVENT_ENCODINGCHANGED},
+ {"CursorHold", EVENT_CURSORHOLD},
+ {"FileAppendPost", EVENT_FILEAPPENDPOST},
+ {"FileAppendPre", EVENT_FILEAPPENDPRE},
+ {"FileAppendCmd", EVENT_FILEAPPENDCMD},
+ {"FileChangedShell",EVENT_FILECHANGEDSHELL},
+ {"FileChangedRO", EVENT_FILECHANGEDRO},
+ {"FileReadPost", EVENT_FILEREADPOST},
+ {"FileReadPre", EVENT_FILEREADPRE},
+ {"FileReadCmd", EVENT_FILEREADCMD},
+ {"FileType", EVENT_FILETYPE},
+ {"FileWritePost", EVENT_FILEWRITEPOST},
+ {"FileWritePre", EVENT_FILEWRITEPRE},
+ {"FileWriteCmd", EVENT_FILEWRITECMD},
+ {"FilterReadPost", EVENT_FILTERREADPOST},
+ {"FilterReadPre", EVENT_FILTERREADPRE},
+ {"FilterWritePost", EVENT_FILTERWRITEPOST},
+ {"FilterWritePre", EVENT_FILTERWRITEPRE},
+ {"FocusGained", EVENT_FOCUSGAINED},
+ {"FocusLost", EVENT_FOCUSLOST},
+ {"FuncUndefined", EVENT_FUNCUNDEFINED},
+ {"GUIEnter", EVENT_GUIENTER},
+ {"RemoteReply", EVENT_REMOTEREPLY},
+ {"StdinReadPost", EVENT_STDINREADPOST},
+ {"StdinReadPre", EVENT_STDINREADPRE},
+ {"Syntax", EVENT_SYNTAX},
+ {"TermChanged", EVENT_TERMCHANGED},
+ {"TermResponse", EVENT_TERMRESPONSE},
+ {"User", EVENT_USER},
+ {"VimEnter", EVENT_VIMENTER},
+ {"VimLeave", EVENT_VIMLEAVE},
+ {"VimLeavePre", EVENT_VIMLEAVEPRE},
+ {"WinEnter", EVENT_WINENTER},
+ {"WinLeave", EVENT_WINLEAVE},
+ {NULL, (EVENT_T)0}
+};
+
+static AutoPat *first_autopat[NUM_EVENTS] =
+{
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+/*
+ * struct used to keep status while executing autocommands for an event.
+ */
+typedef struct AutoPatCmd
+{
+ AutoPat *curpat; /* next AutoPat to examine */
+ AutoCmd *nextcmd; /* next AutoCmd to execute */
+ int group; /* group being used */
+ char_u *fname; /* fname to match with */
+ char_u *sfname; /* sfname to match with */
+ char_u *tail; /* tail of fname */
+ EVENT_T event; /* current event */
+} AutoPatCmd;
+
+/*
+ * augroups stores a list of autocmd group names.
+ */
+garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
+#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
+
+/*
+ * The ID of the current group. Group 0 is the default one.
+ */
+#define AUGROUP_DEFAULT -1 /* default autocmd group */
+#define AUGROUP_ERROR -2 /* errornouse autocmd group */
+#define AUGROUP_ALL -3 /* all autocmd groups */
+static int current_augroup = AUGROUP_DEFAULT;
+
+static int au_need_clean = FALSE; /* need to delete marked patterns */
+
+static void show_autocmd __ARGS((AutoPat *ap, EVENT_T event));
+static void au_remove_pat __ARGS((AutoPat *ap));
+static void au_remove_cmds __ARGS((AutoPat *ap));
+static void au_cleanup __ARGS((void));
+static int au_new_group __ARGS((char_u *name));
+static void au_del_group __ARGS((char_u *name));
+static int au_find_group __ARGS((char_u *name));
+static EVENT_T event_name2nr __ARGS((char_u *start, char_u **end));
+static char_u *event_nr2name __ARGS((EVENT_T event));
+static char_u *find_end_event __ARGS((char_u *arg, int have_group));
+static int event_ignored __ARGS((EVENT_T event));
+static int au_get_grouparg __ARGS((char_u **argp));
+static int do_autocmd_event __ARGS((EVENT_T event, char_u *pat, int nested, char_u *cmd, int forceit, int group));
+static char_u *getnextac __ARGS((int c, void *cookie, int indent));
+static int apply_autocmds_group __ARGS((EVENT_T event, char_u *fname, char_u *fname_io, int force, int group, buf_T *buf, exarg_T *eap));
+static void auto_next_pat __ARGS((AutoPatCmd *apc, int stop_at_last));
+
+static EVENT_T last_event;
+static int last_group;
+
+/*
+ * Show the autocommands for one AutoPat.
+ */
+ static void
+show_autocmd(ap, event)
+ AutoPat *ap;
+ EVENT_T event;
+{
+ AutoCmd *ac;
+
+ /* Check for "got_int" (here and at various places below), which is set
+ * when "q" has been hit for the "--more--" prompt */
+ if (got_int)
+ return;
+ if (ap->pat == NULL) /* pattern has been removed */
+ return;
+
+ msg_putchar('\n');
+ if (got_int)
+ return;
+ if (event != last_event || ap->group != last_group)
+ {
+ if (ap->group != AUGROUP_DEFAULT)
+ {
+ if (AUGROUP_NAME(ap->group) == NULL)
+ msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
+ else
+ msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
+ msg_puts((char_u *)" ");
+ }
+ msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
+ last_event = event;
+ last_group = ap->group;
+ msg_putchar('\n');
+ if (got_int)
+ return;
+ }
+ msg_col = 4;
+ msg_outtrans(ap->pat);
+
+ for (ac = ap->cmds; ac != NULL; ac = ac->next)
+ {
+ if (ac->cmd != NULL) /* skip removed commands */
+ {
+ if (msg_col >= 14)
+ msg_putchar('\n');
+ msg_col = 14;
+ if (got_int)
+ return;
+ msg_outtrans(ac->cmd);
+ if (got_int)
+ return;
+ if (ac->next != NULL)
+ {
+ msg_putchar('\n');
+ if (got_int)
+ return;
+ }
+ }
+ }
+}
+
+/*
+ * Mark an autocommand pattern for deletion.
+ */
+ static void
+au_remove_pat(ap)
+ AutoPat *ap;
+{
+ vim_free(ap->pat);
+ ap->pat = NULL;
+ au_need_clean = TRUE;
+}
+
+/*
+ * Mark all commands for a pattern for deletion.
+ */
+ static void
+au_remove_cmds(ap)
+ AutoPat *ap;
+{
+ AutoCmd *ac;
+
+ for (ac = ap->cmds; ac != NULL; ac = ac->next)
+ {
+ vim_free(ac->cmd);
+ ac->cmd = NULL;
+ }
+ au_need_clean = TRUE;
+}
+
+/*
+ * Cleanup autocommands and patterns that have been deleted.
+ * This is only done when not executing autocommands.
+ */
+ static void
+au_cleanup()
+{
+ AutoPat *ap, **prev_ap;
+ AutoCmd *ac, **prev_ac;
+ EVENT_T event;
+
+ if (autocmd_busy || !au_need_clean)
+ return;
+
+ /* loop over all events */
+ for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
+ event = (EVENT_T)((int)event + 1))
+ {
+ /* loop over all autocommand patterns */
+ prev_ap = &(first_autopat[(int)event]);
+ for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
+ {
+ /* loop over all commands for this pattern */
+ prev_ac = &(ap->cmds);
+ for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
+ {
+ /* remove the command if the pattern is to be deleted or when
+ * the command has been marked for deletion */
+ if (ap->pat == NULL || ac->cmd == NULL)
+ {
+ *prev_ac = ac->next;
+ vim_free(ac->cmd);
+ vim_free(ac);
+ }
+ else
+ prev_ac = &(ac->next);
+ }
+
+ /* remove the pattern if it has been marked for deletion */
+ if (ap->pat == NULL)
+ {
+ *prev_ap = ap->next;
+ vim_free(ap->reg_pat);
+ vim_free(ap);
+ }
+ else
+ prev_ap = &(ap->next);
+ }
+ }
+
+ au_need_clean = FALSE;
+}
+
+/*
+ * Add an autocmd group name.
+ * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
+ */
+ static int
+au_new_group(name)
+ char_u *name;
+{
+ int i;
+
+ i = au_find_group(name);
+ if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
+ {
+ /* First try using a free entry. */
+ for (i = 0; i < augroups.ga_len; ++i)
+ if (AUGROUP_NAME(i) == NULL)
+ break;
+ if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
+ return AUGROUP_ERROR;
+
+ AUGROUP_NAME(i) = vim_strsave(name);
+ if (AUGROUP_NAME(i) == NULL)
+ return AUGROUP_ERROR;
+ if (i == augroups.ga_len)
+ {
+ ++augroups.ga_len;
+ --augroups.ga_room;
+ }
+ }
+
+ return i;
+}
+
+ static void
+au_del_group(name)
+ char_u *name;
+{
+ int i;
+
+ i = au_find_group(name);
+ if (i == AUGROUP_ERROR) /* the group doesn't exist */
+ EMSG2(_("E367: No such group: \"%s\""), name);
+ else
+ {
+ vim_free(AUGROUP_NAME(i));
+ AUGROUP_NAME(i) = NULL;
+ }
+}
+
+/*
+ * Find the ID of an autocmd group name.
+ * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
+ */
+ static int
+au_find_group(name)
+ char_u *name;
+{
+ int i;
+
+ for (i = 0; i < augroups.ga_len; ++i)
+ if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0)
+ return i;
+ return AUGROUP_ERROR;
+}
+
+/*
+ * ":augroup {name}".
+ */
+ void
+do_augroup(arg, del_group)
+ char_u *arg;
+ int del_group;
+{
+ int i;
+
+ if (del_group)
+ {
+ if (*arg == NUL)
+ EMSG(_(e_argreq));
+ else
+ au_del_group(arg);
+ }
+ else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
+ current_augroup = AUGROUP_DEFAULT;
+ else if (*arg) /* ":aug xxx": switch to group xxx */
+ {
+ i = au_new_group(arg);
+ if (i != AUGROUP_ERROR)
+ current_augroup = i;
+ }
+ else /* ":aug": list the group names */
+ {
+ msg_start();
+ for (i = 0; i < augroups.ga_len; ++i)
+ {
+ if (AUGROUP_NAME(i) != NULL)
+ {
+ msg_puts(AUGROUP_NAME(i));
+ msg_puts((char_u *)" ");
+ }
+ }
+ msg_clr_eos();
+ msg_end();
+ }
+}
+
+/*
+ * Return the event number for event name "start".
+ * Return NUM_EVENTS if the event name was not found.
+ * Return a pointer to the next event name in "end".
+ */
+ static EVENT_T
+event_name2nr(start, end)
+ char_u *start;
+ char_u **end;
+{
+ char_u *p;
+ int i;
+ int len;
+
+ /* the event name ends with end of line, a blank or a comma */
+ for (p = start; *p && !vim_iswhite(*p) && *p != ','; ++p)
+ ;
+ for (i = 0; event_names[i].name != NULL; ++i)
+ {
+ len = (int)STRLEN(event_names[i].name);
+ if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
+ break;
+ }
+ if (*p == ',')
+ ++p;
+ *end = p;
+ if (event_names[i].name == NULL)
+ return NUM_EVENTS;
+ return event_names[i].event;
+}
+
+/*
+ * Return the name for event "event".
+ */
+ static char_u *
+event_nr2name(event)
+ EVENT_T event;
+{
+ int i;
+
+ for (i = 0; event_names[i].name != NULL; ++i)
+ if (event_names[i].event == event)
+ return (char_u *)event_names[i].name;
+ return (char_u *)"Unknown";
+}
+
+/*
+ * Scan over the events. "*" stands for all events.
+ */
+ static char_u *
+find_end_event(arg, have_group)
+ char_u *arg;
+ int have_group; /* TRUE when group name was found */
+{
+ char_u *pat;
+ char_u *p;
+
+ if (*arg == '*')
+ {
+ if (arg[1] && !vim_iswhite(arg[1]))
+ {
+ EMSG2(_("E215: Illegal character after *: %s"), arg);
+ return NULL;
+ }
+ pat = arg + 1;
+ }
+ else
+ {
+ for (pat = arg; *pat && !vim_iswhite(*pat); pat = p)
+ {
+ if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
+ {
+ if (have_group)
+ EMSG2(_("E216: No such event: %s"), pat);
+ else
+ EMSG2(_("E216: No such group or event: %s"), pat);
+ return NULL;
+ }
+ }
+ }
+ return pat;
+}
+
+/*
+ * Return TRUE if "event" is included in 'eventignore'.
+ */
+ static int
+event_ignored(event)
+ EVENT_T event;
+{
+ char_u *p = p_ei;
+
+ if (STRICMP(p_ei, "all") == 0)
+ return TRUE;
+
+ while (*p)
+ if (event_name2nr(p, &p) == event)
+ return TRUE;
+
+ return FALSE;
+}
+
+/*
+ * Return OK when the contents of p_ei is valid, FAIL otherwise.
+ */
+ int
+check_ei()
+{
+ char_u *p = p_ei;
+
+ if (STRICMP(p_ei, "all") == 0)
+ return OK;
+
+ while (*p)
+ if (event_name2nr(p, &p) == NUM_EVENTS)
+ return FAIL;
+
+ return OK;
+}
+
+/*
+ * do_autocmd() -- implements the :autocmd command. Can be used in the
+ * following ways:
+ *
+ * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
+ * will be automatically executed for <event>
+ * when editing a file matching <pat>, in
+ * the current group.
+ * :autocmd <event> <pat> Show the auto-commands associated with
+ * <event> and <pat>.
+ * :autocmd <event> Show the auto-commands associated with
+ * <event>.
+ * :autocmd Show all auto-commands.
+ * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
+ * <event> and <pat>, and add the command
+ * <cmd>, for the current group.
+ * :autocmd! <event> <pat> Remove all auto-commands associated with
+ * <event> and <pat> for the current group.
+ * :autocmd! <event> Remove all auto-commands associated with
+ * <event> for the current group.
+ * :autocmd! Remove ALL auto-commands for the current
+ * group.
+ *
+ * Multiple events and patterns may be given separated by commas. Here are
+ * some examples:
+ * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
+ * :autocmd bufleave * set tw=79 nosmartindent ic infercase
+ *
+ * :autocmd * *.c show all autocommands for *.c files.
+ */
+ void
+do_autocmd(arg, forceit)
+ char_u *arg;
+ int forceit;
+{
+ char_u *pat;
+ char_u *envpat = NULL;
+ char_u *cmd;
+ EVENT_T event;
+ int need_free = FALSE;
+ int nested = FALSE;
+ int group;
+
+ /*
+ * Check for a legal group name. If not, use AUGROUP_ALL.
+ */
+ group = au_get_grouparg(&arg);
+ if (arg == NULL) /* out of memory */
+ return;
+
+ /*
+ * Scan over the events.
+ * If we find an illegal name, return here, don't do anything.
+ */
+ pat = find_end_event(arg, group != AUGROUP_ALL);
+ if (pat == NULL)
+ return;
+
+ /*
+ * Scan over the pattern. Put a NUL at the end.
+ */
+ pat = skipwhite(pat);
+ cmd = pat;
+ while (*cmd && (!vim_iswhite(*cmd) || cmd[-1] == '\\'))
+ cmd++;
+ if (*cmd)
+ *cmd++ = NUL;
+
+ /* Expand environment variables in the pattern. Set 'shellslash', we want
+ * forward slashes here. */
+ if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
+ {
+#ifdef BACKSLASH_IN_FILENAME
+ int p_ssl_save = p_ssl;
+
+ p_ssl = TRUE;
+#endif
+ envpat = expand_env_save(pat);
+#ifdef BACKSLASH_IN_FILENAME
+ p_ssl = p_ssl_save;
+#endif
+ if (envpat != NULL)
+ pat = envpat;
+ }
+
+ /*
+ * Check for "nested" flag.
+ */
+ cmd = skipwhite(cmd);
+ if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && vim_iswhite(cmd[6]))
+ {
+ nested = TRUE;
+ cmd = skipwhite(cmd + 6);
+ }
+
+ /*
+ * Find the start of the commands.
+ * Expand <sfile> in it.
+ */
+ if (*cmd != NUL)
+ {
+ cmd = expand_sfile(cmd);
+ if (cmd == NULL) /* some error */
+ return;
+ need_free = TRUE;
+ }
+
+ /*
+ * Print header when showing autocommands.
+ */
+ if (!forceit && *cmd == NUL)
+ {
+ /* Highlight title */
+ MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
+ }
+
+ /*
+ * Loop over the events.
+ */
+ last_event = (EVENT_T)-1; /* for listing the event name */
+ last_group = AUGROUP_ERROR; /* for listing the group name */
+ if (*arg == '*' || *arg == NUL)
+ {
+ for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
+ event = (EVENT_T)((int)event + 1))
+ if (do_autocmd_event(event, pat,
+ nested, cmd, forceit, group) == FAIL)
+ break;
+ }
+ else
+ {
+ while (*arg && !vim_iswhite(*arg))
+ if (do_autocmd_event(event_name2nr(arg, &arg), pat,
+ nested, cmd, forceit, group) == FAIL)
+ break;
+ }
+
+ if (need_free)
+ vim_free(cmd);
+ vim_free(envpat);
+}
+
+/*
+ * Find the group ID in a ":autocmd" or ":doautocmd" argument.
+ * The "argp" argument is advanced to the following argument.
+ *
+ * Returns the group ID, AUGROUP_ERROR for error (out of memory).
+ */
+ static int
+au_get_grouparg(argp)
+ char_u **argp;
+{
+ char_u *group_name;
+ char_u *p;
+ char_u *arg = *argp;
+ int group = AUGROUP_ALL;
+
+ p = skiptowhite(arg);
+ if (p > arg)
+ {
+ group_name = vim_strnsave(arg, (int)(p - arg));
+ if (group_name == NULL) /* out of memory */
+ return AUGROUP_ERROR;
+ group = au_find_group(group_name);
+ if (group == AUGROUP_ERROR)
+ group = AUGROUP_ALL; /* no match, use all groups */
+ else
+ *argp = skipwhite(p); /* match, skip over group name */
+ vim_free(group_name);
+ }
+ return group;
+}
+
+/*
+ * do_autocmd() for one event.
+ * If *pat == NUL do for all patterns.
+ * If *cmd == NUL show entries.
+ * If forceit == TRUE delete entries.
+ * If group is not AUGROUP_ALL, only use this group.
+ */
+ static int
+do_autocmd_event(event, pat, nested, cmd, forceit, group)
+ EVENT_T event;
+ char_u *pat;
+ int nested;
+ char_u *cmd;
+ int forceit;
+ int group;
+{
+ AutoPat *ap;
+ AutoPat **prev_ap;
+ AutoCmd *ac;
+ AutoCmd **prev_ac;
+ int brace_level;
+ char_u *endpat;
+ int findgroup;
+ int allgroups;
+ int patlen;
+
+ if (group == AUGROUP_ALL)
+ findgroup = current_augroup;
+ else
+ findgroup = group;
+ allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
+
+ /*
+ * Show or delete all patterns for an event.
+ */
+ if (*pat == NUL)
+ {
+ for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
+ {
+ if (forceit) /* delete the AutoPat, if it's in the current group */
+ {
+ if (ap->group == findgroup)
+ au_remove_pat(ap);
+ }
+ else if (group == AUGROUP_ALL || ap->group == group)
+ show_autocmd(ap, event);
+ }
+ }
+
+ /*
+ * Loop through all the specified patterns.
+ */
+ for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
+ {
+ /*
+ * Find end of the pattern.
+ * Watch out for a comma in braces, like "*.\{obj,o\}".
+ */
+ brace_level = 0;
+ for (endpat = pat; *endpat && (*endpat != ',' || brace_level
+ || endpat[-1] == '\\'); ++endpat)
+ {
+ if (*endpat == '{')
+ brace_level++;
+ else if (*endpat == '}')
+ brace_level--;
+ }
+ if (pat == endpat) /* ignore single comma */
+ continue;
+ patlen = (int)(endpat - pat);
+
+ /*
+ * Find AutoPat entries with this pattern.
+ */
+ prev_ap = &first_autopat[(int)event];
+ while ((ap = *prev_ap) != NULL)
+ {
+ if (ap->pat != NULL)
+ {
+ /* Accept a pattern when:
+ * - a group was specified and it's that group, or a group was
+ * not specified and it's the current group, or a group was
+ * not specified and we are listing
+ * - the length of the pattern matches
+ * - the pattern matches
+ */
+ if ((allgroups || ap->group == findgroup)
+ && ap->patlen == patlen
+ && STRNCMP(pat, ap->pat, patlen) == 0)
+ {
+ /*
+ * Remove existing autocommands.
+ * If adding any new autocmd's for this AutoPat, don't
+ * delete the pattern from the autopat list, append to
+ * this list.
+ */
+ if (forceit)
+ {
+ if (*cmd != NUL && ap->next == NULL)
+ {
+ au_remove_cmds(ap);
+ break;
+ }
+ au_remove_pat(ap);
+ }
+
+ /*
+ * Show autocmd's for this autopat
+ */
+ else if (*cmd == NUL)
+ show_autocmd(ap, event);
+
+ /*
+ * Add autocmd to this autopat, if it's the last one.
+ */
+ else if (ap->next == NULL)
+ break;
+ }
+ }
+ prev_ap = &ap->next;
+ }
+
+ /*
+ * Add a new command.
+ */
+ if (*cmd != NUL)
+ {
+ /*
+ * If the pattern we want to add a command to does appear at the
+ * end of the list (or not is not in the list at all), add the
+ * pattern at the end of the list.
+ */
+ if (ap == NULL)
+ {
+ ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
+ if (ap == NULL)
+ return FAIL;
+ ap->pat = vim_strnsave(pat, patlen);
+ ap->patlen = patlen;
+ if (ap->pat == NULL)
+ {
+ vim_free(ap);
+ return FAIL;
+ }
+ ap->reg_pat = file_pat_to_reg_pat(pat, endpat,
+ &ap->allow_dirs, TRUE);
+ if (ap->reg_pat == NULL)
+ {
+ vim_free(ap->pat);
+ vim_free(ap);
+ return FAIL;
+ }
+ ap->cmds = NULL;
+ *prev_ap = ap;
+ ap->next = NULL;
+ if (group == AUGROUP_ALL)
+ ap->group = current_augroup;
+ else
+ ap->group = group;
+ }
+
+ /*
+ * Add the autocmd at the end of the AutoCmd list.
+ */
+ prev_ac = &(ap->cmds);
+ while ((ac = *prev_ac) != NULL)
+ prev_ac = &ac->next;
+ ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
+ if (ac == NULL)
+ return FAIL;
+ ac->cmd = vim_strsave(cmd);
+#ifdef FEAT_EVAL
+ ac->scriptID = current_SID;
+#endif
+ if (ac->cmd == NULL)
+ {
+ vim_free(ac);
+ return FAIL;
+ }
+ ac->next = NULL;
+ *prev_ac = ac;
+ ac->nested = nested;
+ }
+ }
+
+ au_cleanup(); /* may really delete removed patterns/commands now */
+ return OK;
+}
+
+/*
+ * Implementation of ":doautocmd [group] event [fname]".
+ * Return OK for success, FAIL for failure;
+ */
+ int
+do_doautocmd(arg, do_msg)
+ char_u *arg;
+ int do_msg; /* give message for no matching autocmds? */
+{
+ char_u *fname;
+ int nothing_done = TRUE;
+ int group;
+
+ /*
+ * Check for a legal group name. If not, use AUGROUP_ALL.
+ */
+ group = au_get_grouparg(&arg);
+ if (arg == NULL) /* out of memory */
+ return FAIL;
+
+ if (*arg == '*')
+ {
+ EMSG(_("E217: Can't execute autocommands for ALL events"));
+ return FAIL;
+ }
+
+ /*
+ * Scan over the events.
+ * If we find an illegal name, return here, don't do anything.
+ */
+ fname = find_end_event(arg, group != AUGROUP_ALL);
+ if (fname == NULL)
+ return FAIL;
+
+ fname = skipwhite(fname);
+
+ /*
+ * Loop over the events.
+ */
+ while (*arg && !vim_iswhite(*arg))
+ if (apply_autocmds_group(event_name2nr(arg, &arg),
+ fname, NULL, TRUE, group, curbuf, NULL))
+ nothing_done = FALSE;
+
+ if (nothing_done && do_msg)
+ MSG(_("No matching autocommands"));
+
+#ifdef FEAT_EVAL
+ return aborting() ? FAIL : OK;
+#else
+ return OK;
+#endif
+}
+
+/*
+ * ":doautoall": execute autocommands for each loaded buffer.
+ */
+ void
+ex_doautoall(eap)
+ exarg_T *eap;
+{
+ int retval;
+ aco_save_T aco;
+ buf_T *buf;
+
+ /*
+ * This is a bit tricky: For some commands curwin->w_buffer needs to be
+ * equal to curbuf, but for some buffers there may not be a window.
+ * So we change the buffer for the current window for a moment. This
+ * gives problems when the autocommands make changes to the list of
+ * buffers or windows...
+ */
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ if (curbuf->b_ml.ml_mfp != NULL)
+ {
+ /* find a window for this buffer and save some values */
+ aucmd_prepbuf(&aco, buf);
+
+ /* execute the autocommands for this buffer */
+ retval = do_doautocmd(eap->arg, FALSE);
+ do_modelines();
+
+ /* restore the current window */
+ aucmd_restbuf(&aco);
+
+ /* stop if there is some error or buffer was deleted */
+ if (retval == FAIL || !buf_valid(buf))
+ break;
+ }
+ }
+
+ check_cursor(); /* just in case lines got deleted */
+}
+
+/*
+ * Prepare for executing autocommands for (hidden) buffer "buf".
+ * Search a window for the current buffer. Save the cursor position and
+ * screen offset.
+ * Set "curbuf" and "curwin" to match "buf".
+ */
+ void
+aucmd_prepbuf(aco, buf)
+ aco_save_T *aco; /* structure to save values in */
+ buf_T *buf; /* new curbuf */
+{
+ win_T *win;
+
+ aco->new_curbuf = buf;
+
+ /* Find a window that is for the new buffer */
+ if (buf == curbuf) /* be quick when buf is curbuf */
+ win = curwin;
+ else
+#ifdef FEAT_WINDOWS
+ for (win = firstwin; win != NULL; win = win->w_next)
+ if (win->w_buffer == buf)
+ break;
+#else
+ win = NULL;
+#endif
+
+ /*
+ * Prefer to use an existing window for the buffer, it has the least side
+ * effects (esp. if "buf" is curbuf).
+ * Otherwise, use curwin for "buf". It might make some items in the
+ * window invalid. At least save the cursor and topline.
+ */
+ if (win != NULL)
+ {
+ /* there is a window for "buf", make it the curwin */
+ aco->save_curwin = curwin;
+ curwin = win;
+ aco->save_buf = win->w_buffer;
+ aco->new_curwin = win;
+ }
+ else
+ {
+ /* there is no window for "buf", use curwin */
+ aco->save_curwin = NULL;
+ aco->save_buf = curbuf;
+ --curbuf->b_nwindows;
+ curwin->w_buffer = buf;
+ ++buf->b_nwindows;
+
+ /* save cursor and topline, set them to safe values */
+ aco->save_cursor = curwin->w_cursor;
+ curwin->w_cursor.lnum = 1;
+ curwin->w_cursor.col = 0;
+ aco->save_topline = curwin->w_topline;
+ curwin->w_topline = 1;
+#ifdef FEAT_DIFF
+ aco->save_topfill = curwin->w_topfill;
+ curwin->w_topfill = 0;
+#endif
+ }
+
+ curbuf = buf;
+}
+
+/*
+ * Cleanup after executing autocommands for a (hidden) buffer.
+ * Restore the window as it was (if possible).
+ */
+ void
+aucmd_restbuf(aco)
+ aco_save_T *aco; /* structure holding saved values */
+{
+ if (aco->save_curwin != NULL)
+ {
+ /* restore curwin */
+#ifdef FEAT_WINDOWS
+ if (win_valid(aco->save_curwin))
+#endif
+ {
+ /* restore the buffer which was previously edited by curwin, if
+ * it's still the same window and it's valid */
+ if (curwin == aco->new_curwin
+ && buf_valid(aco->save_buf)
+ && aco->save_buf->b_ml.ml_mfp != NULL)
+ {
+ --curbuf->b_nwindows;
+ curbuf = aco->save_buf;
+ curwin->w_buffer = curbuf;
+ ++curbuf->b_nwindows;
+ }
+
+ curwin = aco->save_curwin;
+ curbuf = curwin->w_buffer;
+ }
+ }
+ else
+ {
+ /* restore buffer for curwin if it still exists and is loaded */
+ if (buf_valid(aco->save_buf) && aco->save_buf->b_ml.ml_mfp != NULL)
+ {
+ --curbuf->b_nwindows;
+ curbuf = aco->save_buf;
+ curwin->w_buffer = curbuf;
+ ++curbuf->b_nwindows;
+ curwin->w_cursor = aco->save_cursor;
+ check_cursor();
+ /* check topline < line_count, in case lines got deleted */
+ if (aco->save_topline <= curbuf->b_ml.ml_line_count)
+ {
+ curwin->w_topline = aco->save_topline;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = aco->save_topfill;
+#endif
+ }
+ else
+ {
+ curwin->w_topline = curbuf->b_ml.ml_line_count;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = 0;
+#endif
+ }
+ }
+ }
+}
+
+static int autocmd_nested = FALSE;
+
+/*
+ * Execute autocommands for "event" and file name "fname".
+ * Return TRUE if some commands were executed.
+ */
+ int
+apply_autocmds(event, fname, fname_io, force, buf)
+ EVENT_T event;
+ char_u *fname; /* NULL or empty means use actual file name */
+ char_u *fname_io; /* fname to use for <afile> on cmdline */
+ int force; /* when TRUE, ignore autocmd_busy */
+ buf_T *buf; /* buffer for <abuf> */
+{
+ return apply_autocmds_group(event, fname, fname_io, force,
+ AUGROUP_ALL, buf, NULL);
+}
+
+/*
+ * Like apply_autocmds(), but with extra "eap" argument. This takes care of
+ * setting v:filearg.
+ */
+ static int
+apply_autocmds_exarg(event, fname, fname_io, force, buf, eap)
+ EVENT_T event;
+ char_u *fname;
+ char_u *fname_io;
+ int force;
+ buf_T *buf;
+ exarg_T *eap;
+{
+ return apply_autocmds_group(event, fname, fname_io, force,
+ AUGROUP_ALL, buf, eap);
+}
+
+/*
+ * Like apply_autocmds(), but handles the caller's retval. If the script
+ * processing is being aborted or if retval is FAIL when inside a try
+ * conditional, no autocommands are executed. If otherwise the autocommands
+ * cause the script to be aborted, retval is set to FAIL.
+ */
+ int
+apply_autocmds_retval(event, fname, fname_io, force, buf, retval)
+ EVENT_T event;
+ char_u *fname; /* NULL or empty means use actual file name */
+ char_u *fname_io; /* fname to use for <afile> on cmdline */
+ int force; /* when TRUE, ignore autocmd_busy */
+ buf_T *buf; /* buffer for <abuf> */
+ int *retval; /* pointer to caller's retval */
+{
+ int did_cmd;
+
+ if (should_abort(*retval))
+ return FALSE;
+
+ did_cmd = apply_autocmds_group(event, fname, fname_io, force,
+ AUGROUP_ALL, buf, NULL);
+ if (did_cmd && aborting())
+ *retval = FAIL;
+ return did_cmd;
+}
+
+#if defined(FEAT_AUTOCMD) || defined(PROTO)
+ int
+has_cursorhold()
+{
+ return (first_autopat[(int)EVENT_CURSORHOLD] != NULL);
+}
+#endif
+
+ static int
+apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
+ EVENT_T event;
+ char_u *fname; /* NULL or empty means use actual file name */
+ char_u *fname_io; /* fname to use for <afile> on cmdline, NULL means
+ use fname */
+ int force; /* when TRUE, ignore autocmd_busy */
+ int group; /* group ID, or AUGROUP_ALL */
+ buf_T *buf; /* buffer for <abuf> */
+ exarg_T *eap; /* command arguments */
+{
+ char_u *sfname = NULL; /* short file name */
+ char_u *tail;
+ int save_changed;
+ buf_T *old_curbuf;
+ int retval = FALSE;
+ char_u *save_sourcing_name;
+ linenr_T save_sourcing_lnum;
+ char_u *save_autocmd_fname;
+ int save_autocmd_bufnr;
+ char_u *save_autocmd_match;
+ int save_autocmd_busy;
+ int save_autocmd_nested;
+ static int nesting = 0;
+ AutoPatCmd patcmd;
+ AutoPat *ap;
+#ifdef FEAT_EVAL
+ scid_T save_current_SID;
+ void *save_funccalp;
+ char_u *save_cmdarg;
+ long save_cmdbang;
+#endif
+ static int filechangeshell_busy = FALSE;
+
+ /*
+ * Quickly return if there are no autocommands for this event or
+ * autocommands are blocked.
+ */
+ if (first_autopat[(int)event] == NULL || autocmd_block > 0)
+ return retval;
+
+ /*
+ * When autocommands are busy, new autocommands are only executed when
+ * explicitly enabled with the "nested" flag.
+ */
+ if (autocmd_busy && !(force || autocmd_nested))
+ return retval;
+
+#ifdef FEAT_EVAL
+ /*
+ * Quickly return when immdediately aborting on error, or when an interrupt
+ * occurred or an exception was thrown but not caught.
+ */
+ if (aborting())
+ return retval;
+#endif
+
+ /*
+ * FileChangedShell never nests, because it can create an endless loop.
+ */
+ if (filechangeshell_busy && event == EVENT_FILECHANGEDSHELL)
+ return retval;
+
+ /*
+ * Ignore events in 'eventignore'.
+ */
+ if (event_ignored(event))
+ return retval;
+
+ /*
+ * Allow nesting of autocommands, but restrict the depth, because it's
+ * possible to create an endless loop.
+ */
+ if (nesting == 10)
+ {
+ EMSG(_("E218: autocommand nesting too deep"));
+ return retval;
+ }
+
+ /*
+ * Check if these autocommands are disabled. Used when doing ":all" or
+ * ":ball".
+ */
+ if ( (autocmd_no_enter
+ && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
+ || (autocmd_no_leave
+ && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
+ return retval;
+
+ /*
+ * Save the autocmd_* variables and info about the current buffer.
+ */
+ save_autocmd_fname = autocmd_fname;
+ save_autocmd_bufnr = autocmd_bufnr;
+ save_autocmd_match = autocmd_match;
+ save_autocmd_busy = autocmd_busy;
+ save_autocmd_nested = autocmd_nested;
+ save_changed = curbuf->b_changed;
+ old_curbuf = curbuf;
+
+ /*
+ * Set the file name to be used for <afile>.
+ */
+ if (fname_io == NULL)
+ {
+ if (fname != NULL && *fname != NUL)
+ autocmd_fname = fname;
+ else if (buf != NULL)
+ autocmd_fname = buf->b_fname;
+ else
+ autocmd_fname = NULL;
+ }
+ else
+ autocmd_fname = fname_io;
+
+ /*
+ * Set the buffer number to be used for <abuf>.
+ */
+ if (buf == NULL)
+ autocmd_bufnr = 0;
+ else
+ autocmd_bufnr = buf->b_fnum;
+
+ /*
+ * When the file name is NULL or empty, use the file name of buffer "buf".
+ * Always use the full path of the file name to match with, in case
+ * "allow_dirs" is set.
+ */
+ if (fname == NULL || *fname == NUL)
+ {
+ if (buf == NULL)
+ fname = NULL;
+ else
+ {
+#ifdef FEAT_SYN_HL
+ if (event == EVENT_SYNTAX)
+ fname = buf->b_p_syn;
+ else
+#endif
+ if (event == EVENT_FILETYPE)
+ fname = buf->b_p_ft;
+ else
+ {
+ if (buf->b_sfname != NULL)
+ sfname = vim_strsave(buf->b_sfname);
+ fname = buf->b_ffname;
+ }
+ }
+ if (fname == NULL)
+ fname = (char_u *)"";
+ fname = vim_strsave(fname); /* make a copy, so we can change it */
+ }
+ else
+ {
+ sfname = vim_strsave(fname);
+ /* Don't try expanding FileType, Syntax or WindowID. */
+ if (event == EVENT_FILETYPE || event == EVENT_SYNTAX
+ || event == EVENT_REMOTEREPLY)
+ fname = vim_strsave(fname);
+ else
+ fname = FullName_save(fname, FALSE);
+ }
+ if (fname == NULL) /* out of memory */
+ {
+ vim_free(sfname);
+ return FALSE;
+ }
+
+#ifdef BACKSLASH_IN_FILENAME
+ /*
+ * Replace all backslashes with forward slashes. This makes the
+ * autocommand patterns portable between Unix and MS-DOS.
+ */
+ if (sfname != NULL)
+ forward_slash(sfname);
+ forward_slash(fname);
+#endif
+
+#ifdef VMS
+ /* remove version for correct match */
+ if (sfname != NULL)
+ vms_remove_version(sfname);
+ vms_remove_version(fname);
+#endif
+
+ /*
+ * Set the name to be used for <amatch>.
+ */
+ autocmd_match = fname;
+
+
+ /* Don't redraw while doing auto commands. */
+ ++RedrawingDisabled;
+ save_sourcing_name = sourcing_name;
+ sourcing_name = NULL; /* don't free this one */
+ save_sourcing_lnum = sourcing_lnum;
+ sourcing_lnum = 0; /* no line number here */
+
+#ifdef FEAT_EVAL
+ save_current_SID = current_SID;
+
+ /* Don't use local function variables, if called from a function */
+ save_funccalp = save_funccal();
+#endif
+
+ /*
+ * When starting to execute autocommands, save the search patterns.
+ */
+ if (!autocmd_busy)
+ {
+ save_search_patterns();
+ saveRedobuff();
+ did_filetype = keep_filetype;
+ }
+
+ /*
+ * Note that we are applying autocmds. Some commands need to know.
+ */
+ autocmd_busy = TRUE;
+ filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
+ ++nesting; /* see matching decrement below */
+
+ /* Remember that FileType was triggered. Used for did_filetype(). */
+ if (event == EVENT_FILETYPE)
+ did_filetype = TRUE;
+
+ tail = gettail(fname);
+
+ /* Find first autocommand that matches */
+ patcmd.curpat = first_autopat[(int)event];
+ patcmd.nextcmd = NULL;
+ patcmd.group = group;
+ patcmd.fname = fname;
+ patcmd.sfname = sfname;
+ patcmd.tail = tail;
+ patcmd.event = event;
+ auto_next_pat(&patcmd, FALSE);
+
+ /* found one, start executing the autocommands */
+ if (patcmd.curpat != NULL)
+ {
+#ifdef FEAT_EVAL
+ /* set v:cmdarg (only when there is a matching pattern) */
+ save_cmdbang = get_vim_var_nr(VV_CMDBANG);
+ if (eap != NULL)
+ {
+ save_cmdarg = set_cmdarg(eap, NULL);
+ set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
+ }
+ else
+ save_cmdarg = NULL; /* avoid gcc warning */
+#endif
+ retval = TRUE;
+ /* mark the last pattern, to avoid an endless loop when more patterns
+ * are added when executing autocommands */
+ for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
+ ap->last = FALSE;
+ ap->last = TRUE;
+ check_lnums(TRUE); /* make sure cursor and topline are valid */
+ do_cmdline(NULL, getnextac, (void *)&patcmd,
+ DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
+#ifdef FEAT_EVAL
+ if (eap != NULL)
+ {
+ (void)set_cmdarg(NULL, save_cmdarg);
+ set_vim_var_nr(VV_CMDBANG, save_cmdbang);
+ }
+#endif
+ }
+
+ --RedrawingDisabled;
+ autocmd_busy = save_autocmd_busy;
+ filechangeshell_busy = FALSE;
+ autocmd_nested = save_autocmd_nested;
+ vim_free(sourcing_name);
+ sourcing_name = save_sourcing_name;
+ sourcing_lnum = save_sourcing_lnum;
+ autocmd_fname = save_autocmd_fname;
+ autocmd_bufnr = save_autocmd_bufnr;
+ autocmd_match = save_autocmd_match;
+#ifdef FEAT_EVAL
+ current_SID = save_current_SID;
+ restore_funccal(save_funccalp);
+#endif
+ vim_free(fname);
+ vim_free(sfname);
+ --nesting; /* see matching increment above */
+
+ /*
+ * When stopping to execute autocommands, restore the search patterns and
+ * the redo buffer.
+ */
+ if (!autocmd_busy)
+ {
+ restore_search_patterns();
+ restoreRedobuff();
+ did_filetype = FALSE;
+ }
+
+ /*
+ * Some events don't set or reset the Changed flag.
+ * Check if still in the same buffer!
+ */
+ if (curbuf == old_curbuf
+ && (event == EVENT_BUFREADPOST
+ || event == EVENT_BUFWRITEPOST
+ || event == EVENT_FILEAPPENDPOST
+ || event == EVENT_VIMLEAVE
+ || event == EVENT_VIMLEAVEPRE))
+ {
+#ifdef FEAT_TITLE
+ if (curbuf->b_changed != save_changed)
+ need_maketitle = TRUE;
+#endif
+ curbuf->b_changed = save_changed;
+ }
+
+ au_cleanup(); /* may really delete removed patterns/commands now */
+ return retval;
+}
+
+/*
+ * Find next autocommand pattern that matches.
+ */
+ static void
+auto_next_pat(apc, stop_at_last)
+ AutoPatCmd *apc;
+ int stop_at_last; /* stop when 'last' flag is set */
+{
+ AutoPat *ap;
+ AutoCmd *cp;
+ char_u *name;
+ char *s;
+
+ vim_free(sourcing_name);
+ sourcing_name = NULL;
+
+ for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
+ {
+ apc->curpat = NULL;
+
+ /* only use a pattern when it has not been removed, has commands and
+ * the group matches */
+ if (ap->pat != NULL && ap->cmds != NULL
+ && (apc->group == AUGROUP_ALL || apc->group == ap->group))
+ {
+ if (match_file_pat(ap->reg_pat, apc->fname, apc->sfname, apc->tail,
+ ap->allow_dirs))
+ {
+ name = event_nr2name(apc->event);
+ s = _("%s Auto commands for \"%s\"");
+ sourcing_name = alloc((unsigned)(STRLEN(s)
+ + STRLEN(name) + ap->patlen + 1));
+ if (sourcing_name != NULL)
+ {
+ sprintf((char *)sourcing_name, s,
+ (char *)name, (char *)ap->pat);
+ if (p_verbose >= 8)
+ msg_str((char_u *)_("Executing %s"), sourcing_name);
+ }
+
+ apc->curpat = ap;
+ apc->nextcmd = ap->cmds;
+ /* mark last command */
+ for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
+ cp->last = FALSE;
+ cp->last = TRUE;
+ }
+ line_breakcheck();
+ if (apc->curpat != NULL) /* found a match */
+ break;
+ }
+ if (stop_at_last && ap->last)
+ break;
+ }
+}
+
+/*
+ * Get next autocommand command.
+ * Called by do_cmdline() to get the next line for ":if".
+ * Returns allocated string, or NULL for end of autocommands.
+ */
+/* ARGSUSED */
+ static char_u *
+getnextac(c, cookie, indent)
+ int c; /* not used */
+ void *cookie;
+ int indent; /* not used */
+{
+ AutoPatCmd *acp = (AutoPatCmd *)cookie;
+ char_u *retval;
+ AutoCmd *ac;
+
+ /* Can be called again after returning the last line. */
+ if (acp->curpat == NULL)
+ return NULL;
+
+ /* repeat until we find an autocommand to execute */
+ for (;;)
+ {
+ /* skip removed commands */
+ while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
+ if (acp->nextcmd->last)
+ acp->nextcmd = NULL;
+ else
+ acp->nextcmd = acp->nextcmd->next;
+
+ if (acp->nextcmd != NULL)
+ break;
+
+ /* at end of commands, find next pattern that matches */
+ if (acp->curpat->last)
+ acp->curpat = NULL;
+ else
+ acp->curpat = acp->curpat->next;
+ if (acp->curpat != NULL)
+ auto_next_pat(acp, TRUE);
+ if (acp->curpat == NULL)
+ return NULL;
+ }
+
+ ac = acp->nextcmd;
+
+ if (p_verbose >= 9)
+ {
+ msg_scroll = TRUE; /* always scroll up, don't overwrite */
+ msg_str((char_u *)_("autocommand %s"), ac->cmd);
+ msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ cmdline_row = msg_row;
+ }
+ retval = vim_strsave(ac->cmd);
+ autocmd_nested = ac->nested;
+#ifdef FEAT_EVAL
+ current_SID = ac->scriptID;
+#endif
+ if (ac->last)
+ acp->nextcmd = NULL;
+ else
+ acp->nextcmd = ac->next;
+ return retval;
+}
+
+/*
+ * Return TRUE if there is a matching autocommand for "fname".
+ */
+ int
+has_autocmd(event, sfname)
+ EVENT_T event;
+ char_u *sfname;
+{
+ AutoPat *ap;
+ char_u *fname;
+ char_u *tail = gettail(sfname);
+ int retval = FALSE;
+
+ fname = FullName_save(sfname, FALSE);
+ if (fname == NULL)
+ return FALSE;
+
+#ifdef BACKSLASH_IN_FILENAME
+ /*
+ * Replace all backslashes with forward slashes. This makes the
+ * autocommand patterns portable between Unix and MS-DOS.
+ */
+ sfname = vim_strsave(sfname);
+ if (sfname != NULL)
+ forward_slash(sfname);
+ forward_slash(fname);
+#endif
+
+ for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
+ if (ap->pat != NULL && ap->cmds != NULL
+ && match_file_pat(ap->reg_pat, fname, sfname, tail,
+ ap->allow_dirs))
+ {
+ retval = TRUE;
+ break;
+ }
+
+ vim_free(fname);
+#ifdef BACKSLASH_IN_FILENAME
+ vim_free(sfname);
+#endif
+
+ return retval;
+}
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+/*
+ * Function given to ExpandGeneric() to obtain the list of autocommand group
+ * names.
+ */
+/*ARGSUSED*/
+ char_u *
+get_augroup_name(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ if (idx == augroups.ga_len) /* add "END" add the end */
+ return (char_u *)"END";
+ if (idx >= augroups.ga_len) /* end of list */
+ return NULL;
+ if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
+ return (char_u *)"";
+ return AUGROUP_NAME(idx); /* return a name */
+}
+
+static int include_groups = FALSE;
+
+ char_u *
+set_context_in_autocmd(xp, arg, doautocmd)
+ expand_T *xp;
+ char_u *arg;
+ int doautocmd; /* TRUE for :doautocmd, FALSE for :autocmd */
+{
+ char_u *p;
+ int group;
+
+ /* check for a group name, skip it if present */
+ include_groups = FALSE;
+ p = arg;
+ group = au_get_grouparg(&arg);
+ if (group == AUGROUP_ERROR)
+ return NULL;
+ /* If there only is a group name that's what we expand. */
+ if (*arg == NUL && group != AUGROUP_ALL && !vim_iswhite(arg[-1]))
+ {
+ arg = p;
+ group = AUGROUP_ALL;
+ }
+
+ /* skip over event name */
+ for (p = arg; *p != NUL && !vim_iswhite(*p); ++p)
+ if (*p == ',')
+ arg = p + 1;
+ if (*p == NUL)
+ {
+ if (group == AUGROUP_ALL)
+ include_groups = TRUE;
+ xp->xp_context = EXPAND_EVENTS; /* expand event name */
+ xp->xp_pattern = arg;
+ return NULL;
+ }
+
+ /* skip over pattern */
+ arg = skipwhite(p);
+ while (*arg && (!vim_iswhite(*arg) || arg[-1] == '\\'))
+ arg++;
+ if (*arg)
+ return arg; /* expand (next) command */
+
+ if (doautocmd)
+ xp->xp_context = EXPAND_FILES; /* expand file names */
+ else
+ xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
+ return NULL;
+}
+
+/*
+ * Function given to ExpandGeneric() to obtain the list of event names.
+ */
+/*ARGSUSED*/
+ char_u *
+get_event_name(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ if (idx < augroups.ga_len) /* First list group names, if wanted */
+ {
+ if (!include_groups || AUGROUP_NAME(idx) == NULL)
+ return (char_u *)""; /* skip deleted entries */
+ return AUGROUP_NAME(idx); /* return a name */
+ }
+ return (char_u *)event_names[idx - augroups.ga_len].name;
+}
+
+#endif /* FEAT_CMDL_COMPL */
+
+/*
+ * Return TRUE if an autocommand is defined for "event" and "pattern".
+ * "pattern" can be NULL to accept any pattern.
+ */
+ int
+au_exists(name, name_end, pattern)
+ char_u *name;
+ char_u *name_end;
+ char_u *pattern;
+{
+ char_u *event_name;
+ char_u *p;
+ EVENT_T event;
+ AutoPat *ap;
+
+ /* find the index (enum) for the event name */
+ event_name = vim_strnsave(name, (int)(name_end - name));
+ if (event_name == NULL)
+ return FALSE;
+ event = event_name2nr(event_name, &p);
+ vim_free(event_name);
+
+ /* return FALSE if the event name is not recognized */
+ if (event == NUM_EVENTS) /* unknown event name */
+ return FALSE;
+
+ /* Find the first autocommand for this event.
+ * If there isn't any, return FALSE;
+ * If there is one and no pattern given, return TRUE; */
+ ap = first_autopat[(int)event];
+ if (ap == NULL)
+ return FALSE;
+ if (pattern == NULL)
+ return TRUE;
+
+ /* Check if there is an autocommand with the given pattern. */
+ for ( ; ap != NULL; ap = ap->next)
+ /* only use a pattern when it has not been removed and has commands */
+ if (ap->pat != NULL && ap->cmds != NULL
+ && fnamecmp(ap->pat, pattern) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+#endif /* FEAT_AUTOCMD */
+
+#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
+/*
+ * Try matching a filename with a pattern.
+ * Used for autocommands and 'wildignore'.
+ * Returns TRUE if there is a match, FALSE otherwise.
+ */
+ int
+match_file_pat(pattern, fname, sfname, tail, allow_dirs)
+ char_u *pattern; /* pattern to match with */
+ char_u *fname; /* full path of file name */
+ char_u *sfname; /* short file name or NULL */
+ char_u *tail; /* tail of path */
+ int allow_dirs; /* allow matching with dir */
+{
+ regmatch_T regmatch;
+ int result = FALSE;
+#ifdef FEAT_OSFILETYPE
+ int no_pattern = FALSE; /* TRUE if check is filetype only */
+ char_u *type_start;
+ char_u c;
+ int match = FALSE;
+#endif
+
+#ifdef CASE_INSENSITIVE_FILENAME
+ regmatch.rm_ic = TRUE; /* Always ignore case */
+#else
+ regmatch.rm_ic = FALSE; /* Don't ever ignore case */
+#endif
+#ifdef FEAT_OSFILETYPE
+ if (*pattern == '<')
+ {
+ /* There is a filetype condition specified with this pattern.
+ * Check the filetype matches first. If not, don't bother with the
+ * pattern (set regprog to NULL).
+ * Always use magic for the regexp.
+ */
+
+ for (type_start = pattern + 1; (c = *pattern); pattern++)
+ {
+ if ((c == ';' || c == '>') && match == FALSE)
+ {
+ *pattern = NUL; /* Terminate the string */
+ match = mch_check_filetype(fname, type_start);
+ *pattern = c; /* Restore the terminator */
+ type_start = pattern + 1;
+ }
+ if (c == '>')
+ break;
+ }
+
+ /* (c should never be NUL, but check anyway) */
+ if (match == FALSE || c == NUL)
+ regmatch.regprog = NULL; /* Doesn't match - don't check pat. */
+ else if (*pattern == NUL)
+ {
+ regmatch.regprog = NULL; /* Vim will try to free regprog later */
+ no_pattern = TRUE; /* Always matches - don't check pat. */
+ }
+ else
+ regmatch.regprog = vim_regcomp(pattern + 1, RE_MAGIC);
+ }
+ else
+#endif
+ regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
+
+ /*
+ * Try for a match with the pattern with:
+ * 1. the full file name, when the pattern has a '/'.
+ * 2. the short file name, when the pattern has a '/'.
+ * 3. the tail of the file name, when the pattern has no '/'.
+ */
+ if (
+#ifdef FEAT_OSFILETYPE
+ /* If the check is for a filetype only and we don't care
+ * about the path then skip all the regexp stuff.
+ */
+ no_pattern ||
+#endif
+ (regmatch.regprog != NULL
+ && ((allow_dirs
+ && (vim_regexec(&regmatch, fname, (colnr_T)0)
+ || (sfname != NULL
+ && vim_regexec(&regmatch, sfname, (colnr_T)0))))
+ || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
+ result = TRUE;
+
+ vim_free(regmatch.regprog);
+ return result;
+}
+#endif
+
+#if defined(FEAT_WILDIGN) || defined(PROTO)
+/*
+ * Return TRUE if a file matches with a pattern in "list".
+ * "list" is a comma-separated list of patterns, like 'wildignore'.
+ * "sfname" is the short file name or NULL, "ffname" the long file name.
+ */
+ int
+match_file_list(list, sfname, ffname)
+ char_u *list;
+ char_u *sfname;
+ char_u *ffname;
+{
+ char_u buf[100];
+ char_u *tail;
+ char_u *regpat;
+ char allow_dirs;
+ int match;
+ char_u *p;
+
+ tail = gettail(sfname);
+
+ /* try all patterns in 'wildignore' */
+ p = list;
+ while (*p)
+ {
+ copy_option_part(&p, buf, 100, ",");
+ regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
+ if (regpat == NULL)
+ break;
+ match = match_file_pat(regpat, ffname, sfname, tail, (int)allow_dirs);
+ vim_free(regpat);
+ if (match)
+ return TRUE;
+ }
+ return FALSE;
+}
+#endif
+
+/*
+ * Convert the given pattern "pat" which has shell style wildcards in it, into
+ * a regular expression, and return the result in allocated memory. If there
+ * is a directory path separator to be matched, then TRUE is put in
+ * allow_dirs, otherwise FALSE is put there -- webb.
+ * Handle backslashes before special characters, like "\*" and "\ ".
+ *
+ * If FEAT_OSFILETYPE defined then pass initial <type> through unchanged. Eg:
+ * '<html>myfile' becomes '<html>^myfile$' -- leonard.
+ *
+ * Returns NULL when out of memory.
+ */
+/*ARGSUSED*/
+ char_u *
+file_pat_to_reg_pat(pat, pat_end, allow_dirs, no_bslash)
+ char_u *pat;
+ char_u *pat_end; /* first char after pattern or NULL */
+ char *allow_dirs; /* Result passed back out in here */
+ int no_bslash; /* Don't use a backward slash as pathsep */
+{
+ int size;
+ char_u *endp;
+ char_u *reg_pat;
+ char_u *p;
+ int i;
+ int nested = 0;
+ int add_dollar = TRUE;
+#ifdef FEAT_OSFILETYPE
+ int check_length = 0;
+#endif
+
+ if (allow_dirs != NULL)
+ *allow_dirs = FALSE;
+ if (pat_end == NULL)
+ pat_end = pat + STRLEN(pat);
+
+#ifdef FEAT_OSFILETYPE
+ /* Find out how much of the string is the filetype check */
+ if (*pat == '<')
+ {
+ /* Count chars until the next '>' */
+ for (p = pat + 1; p < pat_end && *p != '>'; p++)
+ ;
+ if (p < pat_end)
+ {
+ /* Pattern is of the form <.*>.* */
+ check_length = p - pat + 1;
+ if (p + 1 >= pat_end)
+ {
+ /* The 'pattern' is a filetype check ONLY */
+ reg_pat = (char_u *)alloc(check_length + 1);
+ if (reg_pat != NULL)
+ {
+ mch_memmove(reg_pat, pat, (size_t)check_length);
+ reg_pat[check_length] = NUL;
+ }
+ return reg_pat;
+ }
+ }
+ /* else: there was no closing '>' - assume it was a normal pattern */
+
+ }
+ pat += check_length;
+ size = 2 + check_length;
+#else
+ size = 2; /* '^' at start, '$' at end */
+#endif
+
+ for (p = pat; p < pat_end; p++)
+ {
+ switch (*p)
+ {
+ case '*':
+ case '.':
+ case ',':
+ case '{':
+ case '}':
+ case '~':
+ size += 2; /* extra backslash */
+ break;
+#ifdef BACKSLASH_IN_FILENAME
+ case '\\':
+ case '/':
+ size += 4; /* could become "[\/]" */
+ break;
+#endif
+ default:
+ size++;
+# ifdef FEAT_MBYTE
+ if (enc_dbcs != 0 && (*mb_ptr2len_check)(p) > 1)
+ {
+ ++p;
+ ++size;
+ }
+# endif
+ break;
+ }
+ }
+ reg_pat = alloc(size + 1);
+ if (reg_pat == NULL)
+ return NULL;
+
+#ifdef FEAT_OSFILETYPE
+ /* Copy the type check in to the start. */
+ if (check_length)
+ mch_memmove(reg_pat, pat - check_length, (size_t)check_length);
+ i = check_length;
+#else
+ i = 0;
+#endif
+
+ if (pat[0] == '*')
+ while (pat[0] == '*' && pat < pat_end - 1)
+ pat++;
+ else
+ reg_pat[i++] = '^';
+ endp = pat_end - 1;
+ if (*endp == '*')
+ {
+ while (endp - pat > 0 && *endp == '*')
+ endp--;
+ add_dollar = FALSE;
+ }
+ for (p = pat; *p && nested >= 0 && p <= endp; p++)
+ {
+ switch (*p)
+ {
+ case '*':
+ reg_pat[i++] = '.';
+ reg_pat[i++] = '*';
+ break;
+ case '.':
+#ifdef RISCOS
+ if (allow_dirs != NULL)
+ *allow_dirs = TRUE;
+ /* FALLTHROUGH */
+#endif
+ case '~':
+ reg_pat[i++] = '\\';
+ reg_pat[i++] = *p;
+ break;
+ case '?':
+#ifdef RISCOS
+ case '#':
+#endif
+ reg_pat[i++] = '.';
+ break;
+ case '\\':
+ if (p[1] == NUL)
+ break;
+#ifdef BACKSLASH_IN_FILENAME
+ if (!no_bslash)
+ {
+ /* translate:
+ * "\x" to "\\x" e.g., "dir\file"
+ * "\*" to "\\.*" e.g., "dir\*.c"
+ * "\?" to "\\." e.g., "dir\??.c"
+ * "\+" to "\+" e.g., "fileX\+.c"
+ */
+ if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
+ && p[1] != '+')
+ {
+ reg_pat[i++] = '[';
+ reg_pat[i++] = '\\';
+ reg_pat[i++] = '/';
+ reg_pat[i++] = ']';
+ if (allow_dirs != NULL)
+ *allow_dirs = TRUE;
+ break;
+ }
+ }
+#endif
+ if (*++p == '?'
+#ifdef BACKSLASH_IN_FILENAME
+ && no_bslash
+#endif
+ )
+ reg_pat[i++] = '?';
+ else
+ if (*p == ',')
+ reg_pat[i++] = ',';
+ else
+ {
+ if (allow_dirs != NULL && vim_ispathsep(*p)
+#ifdef BACKSLASH_IN_FILENAME
+ && (!no_bslash || *p != '\\')
+#endif
+ )
+ *allow_dirs = TRUE;
+ reg_pat[i++] = '\\';
+ reg_pat[i++] = *p;
+ }
+ break;
+#ifdef BACKSLASH_IN_FILENAME
+ case '/':
+ reg_pat[i++] = '[';
+ reg_pat[i++] = '\\';
+ reg_pat[i++] = '/';
+ reg_pat[i++] = ']';
+ if (allow_dirs != NULL)
+ *allow_dirs = TRUE;
+ break;
+#endif
+ case '{':
+ reg_pat[i++] = '\\';
+ reg_pat[i++] = '(';
+ nested++;
+ break;
+ case '}':
+ reg_pat[i++] = '\\';
+ reg_pat[i++] = ')';
+ --nested;
+ break;
+ case ',':
+ if (nested)
+ {
+ reg_pat[i++] = '\\';
+ reg_pat[i++] = '|';
+ }
+ else
+ reg_pat[i++] = ',';
+ break;
+ default:
+# ifdef FEAT_MBYTE
+ if (enc_dbcs != 0 && (*mb_ptr2len_check)(p) > 1)
+ reg_pat[i++] = *p++;
+ else
+# endif
+ if (allow_dirs != NULL && vim_ispathsep(*p))
+ *allow_dirs = TRUE;
+ reg_pat[i++] = *p;
+ break;
+ }
+ }
+ if (add_dollar)
+ reg_pat[i++] = '$';
+ reg_pat[i] = NUL;
+ if (nested != 0)
+ {
+ if (nested < 0)
+ EMSG(_("E219: Missing {."));
+ else
+ EMSG(_("E220: Missing }."));
+ vim_free(reg_pat);
+ reg_pat = NULL;
+ }
+ return reg_pat;
+}
diff --git a/src/fold.c b/src/fold.c
new file mode 100644
index 000000000..ceac00bbf
--- /dev/null
+++ b/src/fold.c
@@ -0,0 +1,3250 @@
+/* vim:set ts=8 sts=4 sw=4:
+ * vim600:fdm=marker fdl=1 fdc=3:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * fold.c: code for folding
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_FOLDING) || defined(PROTO)
+
+/* local declarations. {{{1 */
+/* typedef fold_T {{{2 */
+/*
+ * The toplevel folds for each window are stored in the w_folds growarray.
+ * Each toplevel fold can contain an array of second level folds in the
+ * fd_nested growarray.
+ * The info stored in both growarrays is the same: An array of fold_T.
+ */
+typedef struct
+{
+ linenr_T fd_top; /* first line of fold; for nested fold
+ * relative to parent */
+ linenr_T fd_len; /* number of lines in the fold */
+ garray_T fd_nested; /* array of nested folds */
+ char fd_flags; /* see below */
+ char fd_small; /* TRUE, FALSE or MAYBE: fold smaller than
+ 'foldminlines'; MAYBE applies to nested
+ folds too */
+} fold_T;
+
+#define FD_OPEN 0 /* fold is open (nested ones can be closed) */
+#define FD_CLOSED 1 /* fold is closed */
+#define FD_LEVEL 2 /* depends on 'foldlevel' (nested folds too) */
+
+#define MAX_LEVEL 20 /* maximum fold depth */
+
+/* static functions {{{2 */
+static void newFoldLevelWin __ARGS((win_T *wp));
+static int checkCloseRec __ARGS((garray_T *gap, linenr_T lnum, int level));
+static int foldFind __ARGS((garray_T *gap, linenr_T lnum, fold_T **fpp));
+static int foldLevelWin __ARGS((win_T *wp, linenr_T lnum));
+static void checkupdate __ARGS((win_T *wp));
+static void setFoldRepeat __ARGS((linenr_T lnum, long count, int open));
+static linenr_T setManualFold __ARGS((linenr_T lnum, int opening, int recurse, int *donep));
+static linenr_T setManualFoldWin __ARGS((win_T *wp, linenr_T lnum, int opening, int recurse, int *donep));
+static void foldOpenNested __ARGS((fold_T *fpr));
+static void deleteFoldEntry __ARGS((garray_T *gap, int idx, int recursive));
+static void foldMarkAdjustRecurse __ARGS((garray_T *gap, linenr_T line1, linenr_T line2, long amount, long amount_after));
+static int getDeepestNestingRecurse __ARGS((garray_T *gap));
+static int check_closed __ARGS((win_T *win, fold_T *fp, int *use_levelp, int level, int *maybe_smallp, linenr_T lnum_off));
+static void checkSmall __ARGS((win_T *wp, fold_T *fp, linenr_T lnum_off));
+static void setSmallMaybe __ARGS((garray_T *gap));
+static void foldCreateMarkers __ARGS((linenr_T start, linenr_T end));
+static void foldAddMarker __ARGS((linenr_T lnum, char_u *marker, int markerlen));
+static void deleteFoldMarkers __ARGS((fold_T *fp, int recursive, linenr_T lnum_off));
+static void foldDelMarker __ARGS((linenr_T lnum, char_u *marker, int markerlen));
+static void foldUpdateIEMS __ARGS((win_T *wp, linenr_T top, linenr_T bot));
+static void parseMarker __ARGS((win_T *wp));
+
+static char *e_nofold = N_("E490: No fold found");
+
+/*
+ * While updating the folds lines between invalid_top and invalid_bot have an
+ * undefined fold level. Only used for the window currently being updated.
+ */
+static linenr_T invalid_top = (linenr_T)0;
+static linenr_T invalid_bot = (linenr_T)0;
+
+/*
+ * When using 'foldexpr' we sometimes get the level of the next line, which
+ * calls foldlevel() to get the level of the current line, which hasn't been
+ * stored yet. To get around this chicken-egg problem the level of the
+ * previous line is stored here when available. prev_lnum is zero when the
+ * level is not available.
+ */
+static linenr_T prev_lnum = 0;
+static int prev_lnum_lvl = -1;
+
+/* Flags used for "done" argument of setManualFold. */
+#define DONE_NOTHING 0
+#define DONE_ACTION 1 /* did close or open a fold */
+#define DONE_FOLD 2 /* did find a fold */
+
+static int foldstartmarkerlen;
+static char_u *foldendmarker;
+static int foldendmarkerlen;
+
+/* Exported folding functions. {{{1 */
+/* copyFoldingState() {{{2 */
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * Copy that folding state from window "wp_from" to window "wp_to".
+ */
+ void
+copyFoldingState(wp_from, wp_to)
+ win_T *wp_from;
+ win_T *wp_to;
+{
+ wp_to->w_fold_manual = wp_from->w_fold_manual;
+ wp_to->w_foldinvalid = wp_from->w_foldinvalid;
+ cloneFoldGrowArray(&wp_from->w_folds, &wp_to->w_folds);
+}
+#endif
+
+/* hasAnyFolding() {{{2 */
+/*
+ * Return TRUE if there may be folded lines in the current window.
+ */
+ int
+hasAnyFolding(win)
+ win_T *win;
+{
+ /* very simple now, but can become more complex later */
+ return (win->w_p_fen
+ && (!foldmethodIsManual(win) || win->w_folds.ga_len > 0));
+}
+
+/* hasFolding() {{{2 */
+/*
+ * Return TRUE if line "lnum" in the current window is part of a closed
+ * fold.
+ * When returning TRUE, *firstp and *lastp are set to the first and last
+ * lnum of the sequence of folded lines (skipped when NULL).
+ */
+ int
+hasFolding(lnum, firstp, lastp)
+ linenr_T lnum;
+ linenr_T *firstp;
+ linenr_T *lastp;
+{
+ return hasFoldingWin(curwin, lnum, firstp, lastp, TRUE, NULL);
+}
+
+/* hasFoldingWin() {{{2 */
+ int
+hasFoldingWin(win, lnum, firstp, lastp, cache, infop)
+ win_T *win;
+ linenr_T lnum;
+ linenr_T *firstp;
+ linenr_T *lastp;
+ int cache; /* when TRUE: use cached values of window */
+ foldinfo_T *infop; /* where to store fold info */
+{
+ int had_folded = FALSE;
+ linenr_T first = 0;
+ linenr_T last = 0;
+ linenr_T lnum_rel = lnum;
+ int x;
+ fold_T *fp;
+ int level = 0;
+ int use_level = FALSE;
+ int maybe_small = FALSE;
+ garray_T *gap;
+ int low_level = 0;;
+
+ checkupdate(win);
+ /*
+ * Return quickly when there is no folding at all in this window.
+ */
+ if (!hasAnyFolding(win))
+ {
+ if (infop != NULL)
+ infop->fi_level = 0;
+ return FALSE;
+ }
+
+ if (cache)
+ {
+ /*
+ * First look in cached info for displayed lines. This is probably
+ * the fastest, but it can only be used if the entry is still valid.
+ */
+ x = find_wl_entry(win, lnum);
+ if (x >= 0)
+ {
+ first = win->w_lines[x].wl_lnum;
+ last = win->w_lines[x].wl_lastlnum;
+ had_folded = win->w_lines[x].wl_folded;
+ }
+ }
+
+ if (first == 0)
+ {
+ /*
+ * Recursively search for a fold that contains "lnum".
+ */
+ gap = &win->w_folds;
+ for (;;)
+ {
+ if (!foldFind(gap, lnum_rel, &fp))
+ break;
+
+ /* Remember lowest level of fold that starts in "lnum". */
+ if (lnum_rel == fp->fd_top && low_level == 0)
+ low_level = level + 1;
+
+ first += fp->fd_top;
+ last += fp->fd_top;
+
+ /* is this fold closed? */
+ had_folded = check_closed(win, fp, &use_level, level,
+ &maybe_small, lnum - lnum_rel);
+ if (had_folded)
+ {
+ /* Fold closed: Set last and quit loop. */
+ last += fp->fd_len - 1;
+ break;
+ }
+
+ /* Fold found, but it's open: Check nested folds. Line number is
+ * relative to containing fold. */
+ gap = &fp->fd_nested;
+ lnum_rel -= fp->fd_top;
+ ++level;
+ }
+ }
+
+ if (!had_folded)
+ {
+ if (infop != NULL)
+ {
+ infop->fi_level = level;
+ infop->fi_lnum = lnum - lnum_rel;
+ infop->fi_low_level = low_level == 0 ? level : low_level;
+ }
+ return FALSE;
+ }
+
+ if (lastp != NULL)
+ *lastp = last;
+ if (firstp != NULL)
+ *firstp = first;
+ if (infop != NULL)
+ {
+ infop->fi_level = level + 1;
+ infop->fi_lnum = first;
+ infop->fi_low_level = low_level == 0 ? level + 1 : low_level;
+ }
+ return TRUE;
+}
+
+/* foldLevel() {{{2 */
+/*
+ * Return fold level at line number "lnum" in the current window.
+ */
+ int
+foldLevel(lnum)
+ linenr_T lnum;
+{
+ /* While updating the folds lines between invalid_top and invalid_bot have
+ * an undefined fold level. Otherwise update the folds first. */
+ if (invalid_top == (linenr_T)0)
+ checkupdate(curwin);
+ else if (lnum == prev_lnum && prev_lnum_lvl >= 0)
+ return prev_lnum_lvl;
+ else if (lnum >= invalid_top && lnum <= invalid_bot)
+ return -1;
+
+ /* Return quickly when there is no folding at all in this window. */
+ if (!hasAnyFolding(curwin))
+ return 0;
+
+ return foldLevelWin(curwin, lnum);
+}
+
+/* lineFolded() {{{2 */
+/*
+ * Low level function to check if a line is folded. Doesn't use any caching.
+ * Return TRUE if line is folded.
+ * Return FALSE if line is not folded.
+ * Return MAYBE if the line is folded when next to a folded line.
+ */
+ int
+lineFolded(win, lnum)
+ win_T *win;
+ linenr_T lnum;
+{
+ return foldedCount(win, lnum, NULL) != 0;
+}
+
+/* foldedCount() {{{2 */
+/*
+ * Count the number of lines that are folded at line number "lnum".
+ * Normally "lnum" is the first line of a possible fold, and the returned
+ * number is the number of lines in the fold.
+ * Doesn't use caching from the displayed window.
+ * Returns number of folded lines from "lnum", or 0 if line is not folded.
+ * When "infop" is not NULL, fills *infop with the fold level info.
+ */
+ long
+foldedCount(win, lnum, infop)
+ win_T *win;
+ linenr_T lnum;
+ foldinfo_T *infop;
+{
+ linenr_T last;
+
+ if (hasFoldingWin(win, lnum, NULL, &last, FALSE, infop))
+ return (long)(last - lnum + 1);
+ return 0;
+}
+
+/* foldmethodIsManual() {{{2 */
+/*
+ * Return TRUE if 'foldmethod' is "manual"
+ */
+ int
+foldmethodIsManual(wp)
+ win_T *wp;
+{
+ return (wp->w_p_fdm[3] == 'u');
+}
+
+/* foldmethodIsIndent() {{{2 */
+/*
+ * Return TRUE if 'foldmethod' is "indent"
+ */
+ int
+foldmethodIsIndent(wp)
+ win_T *wp;
+{
+ return (wp->w_p_fdm[0] == 'i');
+}
+
+/* foldmethodIsExpr() {{{2 */
+/*
+ * Return TRUE if 'foldmethod' is "expr"
+ */
+ int
+foldmethodIsExpr(wp)
+ win_T *wp;
+{
+ return (wp->w_p_fdm[1] == 'x');
+}
+
+/* foldmethodIsMarker() {{{2 */
+/*
+ * Return TRUE if 'foldmethod' is "marker"
+ */
+ int
+foldmethodIsMarker(wp)
+ win_T *wp;
+{
+ return (wp->w_p_fdm[2] == 'r');
+}
+
+/* foldmethodIsSyntax() {{{2 */
+/*
+ * Return TRUE if 'foldmethod' is "syntax"
+ */
+ int
+foldmethodIsSyntax(wp)
+ win_T *wp;
+{
+ return (wp->w_p_fdm[0] == 's');
+}
+
+/* foldmethodIsDiff() {{{2 */
+/*
+ * Return TRUE if 'foldmethod' is "diff"
+ */
+ int
+foldmethodIsDiff(wp)
+ win_T *wp;
+{
+ return (wp->w_p_fdm[0] == 'd');
+}
+
+/* closeFold() {{{2 */
+/*
+ * Close fold for current window at line "lnum".
+ * Repeat "count" times.
+ */
+ void
+closeFold(lnum, count)
+ linenr_T lnum;
+ long count;
+{
+ setFoldRepeat(lnum, count, FALSE);
+}
+
+/* closeFoldRecurse() {{{2 */
+/*
+ * Close fold for current window at line "lnum" recursively.
+ */
+ void
+closeFoldRecurse(lnum)
+ linenr_T lnum;
+{
+ (void)setManualFold(lnum, FALSE, TRUE, NULL);
+}
+
+/* opFoldRange() {{{2 */
+/*
+ * Open or Close folds for current window in lines "first" to "last".
+ * Used for "zo", "zO", "zc" and "zC" in Visual mode.
+ */
+ void
+opFoldRange(first, last, opening, recurse, had_visual)
+ linenr_T first;
+ linenr_T last;
+ int opening; /* TRUE to open, FALSE to close */
+ int recurse; /* TRUE to do it recursively */
+ int had_visual; /* TRUE when Visual selection used */
+{
+ int done = DONE_NOTHING; /* avoid error messages */
+ linenr_T lnum;
+ linenr_T lnum_next;
+
+ for (lnum = first; lnum <= last; lnum = lnum_next + 1)
+ {
+ lnum_next = lnum;
+ /* Opening one level only: next fold to open is after the one going to
+ * be opened. */
+ if (opening && !recurse)
+ (void)hasFolding(lnum, NULL, &lnum_next);
+ (void)setManualFold(lnum, opening, recurse, &done);
+ /* Closing one level only: next line to close a fold is after just
+ * closed fold. */
+ if (!opening && !recurse)
+ (void)hasFolding(lnum, NULL, &lnum_next);
+ }
+ if (done == DONE_NOTHING)
+ EMSG(_(e_nofold));
+#ifdef FEAT_VISUAL
+ /* Force a redraw to remove the Visual highlighting. */
+ if (had_visual)
+ redraw_curbuf_later(INVERTED);
+#endif
+}
+
+/* openFold() {{{2 */
+/*
+ * Open fold for current window at line "lnum".
+ * Repeat "count" times.
+ */
+ void
+openFold(lnum, count)
+ linenr_T lnum;
+ long count;
+{
+ setFoldRepeat(lnum, count, TRUE);
+}
+
+/* openFoldRecurse() {{{2 */
+/*
+ * Open fold for current window at line "lnum" recursively.
+ */
+ void
+openFoldRecurse(lnum)
+ linenr_T lnum;
+{
+ (void)setManualFold(lnum, TRUE, TRUE, NULL);
+}
+
+/* foldOpenCursor() {{{2 */
+/*
+ * Open folds until the cursor line is not in a closed fold.
+ */
+ void
+foldOpenCursor()
+{
+ int done;
+
+ checkupdate(curwin);
+ if (hasAnyFolding(curwin))
+ for (;;)
+ {
+ done = DONE_NOTHING;
+ (void)setManualFold(curwin->w_cursor.lnum, TRUE, FALSE, &done);
+ if (!(done & DONE_ACTION))
+ break;
+ }
+}
+
+/* newFoldLevel() {{{2 */
+/*
+ * Set new foldlevel for current window.
+ */
+ void
+newFoldLevel()
+{
+ newFoldLevelWin(curwin);
+
+#ifdef FEAT_DIFF
+ if (foldmethodIsDiff(curwin) && curwin->w_p_scb)
+ {
+ win_T *wp;
+
+ /*
+ * Set the same foldlevel in other windows in diff mode.
+ */
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp != curwin && foldmethodIsDiff(wp) && wp->w_p_scb)
+ {
+ wp->w_p_fdl = curwin->w_p_fdl;
+ newFoldLevelWin(wp);
+ }
+ }
+ }
+#endif
+}
+
+ static void
+newFoldLevelWin(wp)
+ win_T *wp;
+{
+ fold_T *fp;
+ int i;
+
+ checkupdate(wp);
+ if (wp->w_fold_manual)
+ {
+ /* Set all flags for the first level of folds to FD_LEVEL. Following
+ * manual open/close will then change the flags to FD_OPEN or
+ * FD_CLOSED for those folds that don't use 'foldlevel'. */
+ fp = (fold_T *)wp->w_folds.ga_data;
+ for (i = 0; i < wp->w_folds.ga_len; ++i)
+ fp[i].fd_flags = FD_LEVEL;
+ wp->w_fold_manual = FALSE;
+ }
+ changed_window_setting_win(wp);
+}
+
+/* foldCheckClose() {{{2 */
+/*
+ * Apply 'foldlevel' to all folds that don't contain the cursor.
+ */
+ void
+foldCheckClose()
+{
+ if (*p_fcl != NUL) /* can only be "all" right now */
+ {
+ checkupdate(curwin);
+ if (checkCloseRec(&curwin->w_folds, curwin->w_cursor.lnum,
+ (int)curwin->w_p_fdl))
+ changed_window_setting();
+ }
+}
+
+/* checkCloseRec() {{{2 */
+ static int
+checkCloseRec(gap, lnum, level)
+ garray_T *gap;
+ linenr_T lnum;
+ int level;
+{
+ fold_T *fp;
+ int retval = FALSE;
+ int i;
+
+ fp = (fold_T *)gap->ga_data;
+ for (i = 0; i < gap->ga_len; ++i)
+ {
+ /* Only manually opened folds may need to be closed. */
+ if (fp[i].fd_flags == FD_OPEN)
+ {
+ if (level <= 0 && (lnum < fp[i].fd_top
+ || lnum >= fp[i].fd_top + fp[i].fd_len))
+ {
+ fp[i].fd_flags = FD_LEVEL;
+ retval = TRUE;
+ }
+ else
+ retval |= checkCloseRec(&fp[i].fd_nested, lnum - fp[i].fd_top,
+ level - 1);
+ }
+ }
+ return retval;
+}
+
+/* foldCreateAllowed() {{{2 */
+/*
+ * Return TRUE if it's allowed to manually create or delete a fold.
+ * Give an error message and return FALSE if not.
+ */
+ int
+foldManualAllowed(create)
+ int create;
+{
+ if (foldmethodIsManual(curwin) || foldmethodIsMarker(curwin))
+ return TRUE;
+ if (create)
+ EMSG(_("E350: Cannot create fold with current 'foldmethod'"));
+ else
+ EMSG(_("E351: Cannot delete fold with current 'foldmethod'"));
+ return FALSE;
+}
+
+/* foldCreate() {{{2 */
+/*
+ * Create a fold from line "start" to line "end" (inclusive) in the current
+ * window.
+ */
+ void
+foldCreate(start, end)
+ linenr_T start;
+ linenr_T end;
+{
+ fold_T *fp;
+ garray_T *gap;
+ garray_T fold_ga;
+ int i, j;
+ int cont;
+ int use_level = FALSE;
+ int closed = FALSE;
+ int level = 0;
+ linenr_T start_rel = start;
+ linenr_T end_rel = end;
+
+ if (start > end)
+ {
+ /* reverse the range */
+ end = start_rel;
+ start = end_rel;
+ start_rel = start;
+ end_rel = end;
+ }
+
+ /* When 'foldmethod' is "marker" add markers, which creates the folds. */
+ if (foldmethodIsMarker(curwin))
+ {
+ foldCreateMarkers(start, end);
+ return;
+ }
+
+ checkupdate(curwin);
+
+ /* Find the place to insert the new fold. */
+ gap = &curwin->w_folds;
+ for (;;)
+ {
+ if (!foldFind(gap, start_rel, &fp))
+ break;
+ if (fp->fd_top + fp->fd_len > end_rel)
+ {
+ /* New fold is completely inside this fold: Go one level deeper. */
+ gap = &fp->fd_nested;
+ start_rel -= fp->fd_top;
+ end_rel -= fp->fd_top;
+ if (use_level || fp->fd_flags == FD_LEVEL)
+ {
+ use_level = TRUE;
+ if (level >= curwin->w_p_fdl)
+ closed = TRUE;
+ }
+ else if (fp->fd_flags == FD_CLOSED)
+ closed = TRUE;
+ ++level;
+ }
+ else
+ {
+ /* This fold and new fold overlap: Insert here and move some folds
+ * inside the new fold. */
+ break;
+ }
+ }
+
+ i = (int)(fp - (fold_T *)gap->ga_data);
+ if (ga_grow(gap, 1) == OK)
+ {
+ fp = (fold_T *)gap->ga_data + i;
+ ga_init2(&fold_ga, (int)sizeof(fold_T), 10);
+
+ /* Count number of folds that will be contained in the new fold. */
+ for (cont = 0; i + cont < gap->ga_len; ++cont)
+ if (fp[cont].fd_top > end_rel)
+ break;
+ if (cont > 0 && ga_grow(&fold_ga, cont) == OK)
+ {
+ /* If the first fold starts before the new fold, let the new fold
+ * start there. Otherwise the existing fold would change. */
+ if (start_rel > fp->fd_top)
+ start_rel = fp->fd_top;
+
+ /* When last contained fold isn't completely contained, adjust end
+ * of new fold. */
+ if (end_rel < fp[cont - 1].fd_top + fp[cont - 1].fd_len - 1)
+ end_rel = fp[cont - 1].fd_top + fp[cont - 1].fd_len - 1;
+ /* Move contained folds to inside new fold. */
+ mch_memmove(fold_ga.ga_data, fp, sizeof(fold_T) * cont);
+ fold_ga.ga_len += cont;
+ fold_ga.ga_room -= cont;
+ i += cont;
+
+ /* Adjust line numbers in contained folds to be relative to the
+ * new fold. */
+ for (j = 0; j < cont; ++j)
+ ((fold_T *)fold_ga.ga_data)[j].fd_top -= start_rel;
+ }
+ /* Move remaining entries to after the new fold. */
+ if (i < gap->ga_len)
+ mch_memmove(fp + 1, (fold_T *)gap->ga_data + i,
+ sizeof(fold_T) * (gap->ga_len - i));
+ gap->ga_len = gap->ga_len + 1 - cont;
+ gap->ga_room = gap->ga_room - 1 + cont;
+
+ /* insert new fold */
+ fp->fd_nested = fold_ga;
+ fp->fd_top = start_rel;
+ fp->fd_len = end_rel - start_rel + 1;
+
+ /* We want the new fold to be closed. If it would remain open because
+ * of using 'foldlevel', need to adjust fd_flags of containing folds.
+ */
+ if (use_level && !closed && level < curwin->w_p_fdl)
+ closeFold(start, 1L);
+ if (!use_level)
+ curwin->w_fold_manual = TRUE;
+ fp->fd_flags = FD_CLOSED;
+ fp->fd_small = MAYBE;
+
+ /* redraw */
+ changed_window_setting();
+ }
+}
+
+/* deleteFold() {{{2 */
+/*
+ * Delete a fold at line "start" in the current window.
+ * When "end" is not 0, delete all folds from "start" to "end".
+ * When "recursive" is TRUE delete recursively.
+ */
+ void
+deleteFold(start, end, recursive, had_visual)
+ linenr_T start;
+ linenr_T end;
+ int recursive;
+ int had_visual; /* TRUE when Visual selection used */
+{
+ garray_T *gap;
+ fold_T *fp;
+ garray_T *found_ga;
+ fold_T *found_fp = NULL;
+ linenr_T found_off = 0;
+ int use_level = FALSE;
+ int maybe_small = FALSE;
+ int level = 0;
+ linenr_T lnum = start;
+ linenr_T lnum_off;
+ int did_one = FALSE;
+ linenr_T first_lnum = MAXLNUM;
+ linenr_T last_lnum = 0;
+
+ checkupdate(curwin);
+
+ while (lnum <= end)
+ {
+ /* Find the deepest fold for "start". */
+ gap = &curwin->w_folds;
+ found_ga = NULL;
+ lnum_off = 0;
+ for (;;)
+ {
+ if (!foldFind(gap, lnum - lnum_off, &fp))
+ break;
+ /* lnum is inside this fold, remember info */
+ found_ga = gap;
+ found_fp = fp;
+ found_off = lnum_off;
+
+ /* if "lnum" is folded, don't check nesting */
+ if (check_closed(curwin, fp, &use_level, level,
+ &maybe_small, lnum_off))
+ break;
+
+ /* check nested folds */
+ gap = &fp->fd_nested;
+ lnum_off += fp->fd_top;
+ ++level;
+ }
+ if (found_ga == NULL)
+ {
+ ++lnum;
+ }
+ else
+ {
+ lnum = found_fp->fd_top + found_fp->fd_len + found_off;
+ did_one = TRUE;
+
+ if (foldmethodIsManual(curwin))
+ deleteFoldEntry(found_ga,
+ (int)(found_fp - (fold_T *)found_ga->ga_data), recursive);
+ else
+ {
+ if (found_fp->fd_top + found_off < first_lnum)
+ first_lnum = found_fp->fd_top;
+ if (lnum > last_lnum)
+ last_lnum = lnum;
+ parseMarker(curwin);
+ deleteFoldMarkers(found_fp, recursive, found_off);
+ }
+
+ /* redraw window */
+ changed_window_setting();
+ }
+ }
+ if (!did_one)
+ {
+ EMSG(_(e_nofold));
+#ifdef FEAT_VISUAL
+ /* Force a redraw to remove the Visual highlighting. */
+ if (had_visual)
+ redraw_curbuf_later(INVERTED);
+#endif
+ }
+ if (last_lnum > 0)
+ changed_lines(first_lnum, (colnr_T)0, last_lnum, 0L);
+}
+
+/* clearFolding() {{{2 */
+/*
+ * Remove all folding for window "win".
+ */
+ void
+clearFolding(win)
+ win_T *win;
+{
+ deleteFoldRecurse(&win->w_folds);
+ win->w_foldinvalid = FALSE;
+}
+
+/* foldUpdate() {{{2 */
+/*
+ * Update folds for changes in the buffer of a window.
+ * Note that inserted/deleted lines must have already been taken care of by
+ * calling foldMarkAdjust().
+ * The changes in lines from top to bot (inclusive).
+ */
+ void
+foldUpdate(wp, top, bot)
+ win_T *wp;
+ linenr_T top;
+ linenr_T bot;
+{
+ fold_T *fp;
+
+ /* Mark all folds from top to bot as maybe-small. */
+ (void)foldFind(&curwin->w_folds, curwin->w_cursor.lnum, &fp);
+ while (fp < (fold_T *)curwin->w_folds.ga_data + curwin->w_folds.ga_len
+ && fp->fd_top < bot)
+ {
+ fp->fd_small = MAYBE;
+ ++fp;
+ }
+
+ if (foldmethodIsIndent(wp)
+ || foldmethodIsExpr(wp)
+ || foldmethodIsMarker(wp)
+#ifdef FEAT_DIFF
+ || foldmethodIsDiff(wp)
+#endif
+ || foldmethodIsSyntax(wp))
+ foldUpdateIEMS(wp, top, bot);
+}
+
+/* foldUpdateAll() {{{2 */
+/*
+ * Update all lines in a window for folding.
+ * Used when a fold setting changes or after reloading the buffer.
+ * The actual updating is postponed until fold info is used, to avoid doing
+ * every time a setting is changed or a syntax item is added.
+ */
+ void
+foldUpdateAll(win)
+ win_T *win;
+{
+ win->w_foldinvalid = TRUE;
+ redraw_win_later(win, NOT_VALID);
+}
+
+/* foldMoveTo() {{{2 */
+/*
+ * If "updown" is FALSE: Move to the start or end of the fold.
+ * If "updown" is TRUE: move to fold at the same level.
+ * If not moved return FAIL.
+ */
+ int
+foldMoveTo(updown, dir, count)
+ int updown;
+ int dir; /* FORWARD or BACKWARD */
+ long count;
+{
+ long n;
+ int retval = FAIL;
+ linenr_T lnum_off;
+ linenr_T lnum_found;
+ linenr_T lnum;
+ int use_level;
+ int maybe_small;
+ garray_T *gap;
+ fold_T *fp;
+ int level;
+ int last;
+
+ /* Repeat "count" times. */
+ for (n = 0; n < count; ++n)
+ {
+ /* Find nested folds. Stop when a fold is closed. The deepest fold
+ * that moves the cursor is used. */
+ lnum_off = 0;
+ gap = &curwin->w_folds;
+ use_level = FALSE;
+ maybe_small = FALSE;
+ lnum_found = curwin->w_cursor.lnum;
+ level = 0;
+ last = FALSE;
+ for (;;)
+ {
+ if (!foldFind(gap, curwin->w_cursor.lnum - lnum_off, &fp))
+ {
+ if (!updown)
+ break;
+
+ /* When moving up, consider a fold above the cursor; when
+ * moving down consider a fold below the cursor. */
+ if (dir == FORWARD)
+ {
+ if (fp - (fold_T *)gap->ga_data >= gap->ga_len)
+ break;
+ --fp;
+ }
+ else
+ {
+ if (fp == (fold_T *)gap->ga_data)
+ break;
+ }
+ /* don't look for contained folds, they will always move
+ * the cursor too far. */
+ last = TRUE;
+ }
+
+ if (!last)
+ {
+ /* Check if this fold is closed. */
+ if (check_closed(curwin, fp, &use_level, level,
+ &maybe_small, lnum_off))
+ last = TRUE;
+
+ /* "[z" and "]z" stop at closed fold */
+ if (last && !updown)
+ break;
+ }
+
+ if (updown)
+ {
+ if (dir == FORWARD)
+ {
+ /* to start of next fold if there is one */
+ if (fp + 1 - (fold_T *)gap->ga_data < gap->ga_len)
+ {
+ lnum = fp[1].fd_top + lnum_off;
+ if (lnum > curwin->w_cursor.lnum)
+ lnum_found = lnum;
+ }
+ }
+ else
+ {
+ /* to end of previous fold if there is one */
+ if (fp > (fold_T *)gap->ga_data)
+ {
+ lnum = fp[-1].fd_top + lnum_off + fp[-1].fd_len - 1;
+ if (lnum < curwin->w_cursor.lnum)
+ lnum_found = lnum;
+ }
+ }
+ }
+ else
+ {
+ /* Open fold found, set cursor to its start/end and then check
+ * nested folds. */
+ if (dir == FORWARD)
+ {
+ lnum = fp->fd_top + lnum_off + fp->fd_len - 1;
+ if (lnum > curwin->w_cursor.lnum)
+ lnum_found = lnum;
+ }
+ else
+ {
+ lnum = fp->fd_top + lnum_off;
+ if (lnum < curwin->w_cursor.lnum)
+ lnum_found = lnum;
+ }
+ }
+
+ if (last)
+ break;
+
+ /* Check nested folds (if any). */
+ gap = &fp->fd_nested;
+ lnum_off += fp->fd_top;
+ ++level;
+ }
+ if (lnum_found != curwin->w_cursor.lnum)
+ {
+ if (retval == FAIL)
+ setpcmark();
+ curwin->w_cursor.lnum = lnum_found;
+ curwin->w_cursor.col = 0;
+ retval = OK;
+ }
+ else
+ break;
+ }
+
+ return retval;
+}
+
+/* foldInitWin() {{{2 */
+/*
+ * Init the fold info in a new window.
+ */
+ void
+foldInitWin(newwin)
+ win_T *newwin;
+{
+ ga_init2(&newwin->w_folds, (int)sizeof(fold_T), 10);
+}
+
+/* find_wl_entry() {{{2 */
+/*
+ * Find an entry in the win->w_lines[] array for buffer line "lnum".
+ * Only valid entries are considered (for entries where wl_valid is FALSE the
+ * line number can be wrong).
+ * Returns index of entry or -1 if not found.
+ */
+ int
+find_wl_entry(win, lnum)
+ win_T *win;
+ linenr_T lnum;
+{
+ int i;
+
+ if (win->w_lines_valid > 0)
+ for (i = 0; i < win->w_lines_valid; ++i)
+ if (win->w_lines[i].wl_valid)
+ {
+ if (lnum < win->w_lines[i].wl_lnum)
+ return -1;
+ if (lnum <= win->w_lines[i].wl_lastlnum)
+ return i;
+ }
+ return -1;
+}
+
+/* foldAdjustVisual() {{{2 */
+#ifdef FEAT_VISUAL
+/*
+ * Adjust the Visual area to include any fold at the start or end completely.
+ */
+ void
+foldAdjustVisual()
+{
+ pos_T *start, *end;
+ char_u *ptr;
+
+ if (!VIsual_active || !hasAnyFolding(curwin))
+ return;
+
+ if (ltoreq(VIsual, curwin->w_cursor))
+ {
+ start = &VIsual;
+ end = &curwin->w_cursor;
+ }
+ else
+ {
+ start = &curwin->w_cursor;
+ end = &VIsual;
+ }
+ if (hasFolding(start->lnum, &start->lnum, NULL))
+ start->col = 0;
+ if (hasFolding(end->lnum, NULL, &end->lnum))
+ {
+ ptr = ml_get(end->lnum);
+ end->col = (colnr_T)STRLEN(ptr);
+ if (end->col > 0 && *p_sel == 'o')
+ --end->col;
+#ifdef FEAT_MBYTE
+ /* prevent cursor from moving on the trail byte */
+ if (has_mbyte)
+ mb_adjust_cursor();
+#endif
+ }
+}
+#endif
+
+/* cursor_foldstart() {{{2 */
+/*
+ * Move the cursor to the first line of a closed fold.
+ */
+ void
+foldAdjustCursor()
+{
+ (void)hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL);
+}
+
+/* Internal functions for "fold_T" {{{1 */
+/* cloneFoldGrowArray() {{{2 */
+/*
+ * Will "clone" (i.e deep copy) a garray_T of folds.
+ *
+ * Return FAIL if the operation cannot be completed, otherwise OK.
+ */
+ void
+cloneFoldGrowArray(from, to)
+ garray_T *from;
+ garray_T *to;
+{
+ int i;
+ fold_T *from_p;
+ fold_T *to_p;
+
+ ga_init2(to, from->ga_itemsize, from->ga_growsize);
+ if (from->ga_len == 0 || ga_grow(to, from->ga_len) == FAIL)
+ return;
+
+ from_p = (fold_T *)from->ga_data;
+ to_p = (fold_T *)to->ga_data;
+
+ for (i = 0; i < from->ga_len; i++)
+ {
+ to_p->fd_top = from_p->fd_top;
+ to_p->fd_len = from_p->fd_len;
+ to_p->fd_flags = from_p->fd_flags;
+ to_p->fd_small = from_p->fd_small;
+ cloneFoldGrowArray(&from_p->fd_nested, &to_p->fd_nested);
+ ++to->ga_len;
+ --to->ga_room;
+ ++from_p;
+ ++to_p;
+ }
+}
+
+/* foldFind() {{{2 */
+/*
+ * Search for line "lnum" in folds of growarray "gap".
+ * Set *fpp to the fold struct for the fold that contains "lnum" or
+ * the first fold below it (careful: it can be beyond the end of the array!).
+ * Returns FALSE when there is no fold that contains "lnum".
+ */
+ static int
+foldFind(gap, lnum, fpp)
+ garray_T *gap;
+ linenr_T lnum;
+ fold_T **fpp;
+{
+ linenr_T low, high;
+ fold_T *fp;
+ int i;
+
+ /*
+ * Perform a binary search.
+ * "low" is lowest index of possible match.
+ * "high" is highest index of possible match.
+ */
+ fp = (fold_T *)gap->ga_data;
+ low = 0;
+ high = gap->ga_len - 1;
+ while (low <= high)
+ {
+ i = (low + high) / 2;
+ if (fp[i].fd_top > lnum)
+ /* fold below lnum, adjust high */
+ high = i - 1;
+ else if (fp[i].fd_top + fp[i].fd_len <= lnum)
+ /* fold above lnum, adjust low */
+ low = i + 1;
+ else
+ {
+ /* lnum is inside this fold */
+ *fpp = fp + i;
+ return TRUE;
+ }
+ }
+ *fpp = fp + low;
+ return FALSE;
+}
+
+/* foldLevelWin() {{{2 */
+/*
+ * Return fold level at line number "lnum" in window "wp".
+ */
+ static int
+foldLevelWin(wp, lnum)
+ win_T *wp;
+ linenr_T lnum;
+{
+ fold_T *fp;
+ linenr_T lnum_rel = lnum;
+ int level = 0;
+ garray_T *gap;
+
+ /* Recursively search for a fold that contains "lnum". */
+ gap = &wp->w_folds;
+ for (;;)
+ {
+ if (!foldFind(gap, lnum_rel, &fp))
+ break;
+ /* Check nested folds. Line number is relative to containing fold. */
+ gap = &fp->fd_nested;
+ lnum_rel -= fp->fd_top;
+ ++level;
+ }
+
+ return level;
+}
+
+/* checkupdate() {{{2 */
+/*
+ * Check if the folds in window "wp" are invalid and update them if needed.
+ */
+ static void
+checkupdate(wp)
+ win_T *wp;
+{
+ if (wp->w_foldinvalid)
+ {
+ foldUpdate(wp, (linenr_T)1, (linenr_T)MAXLNUM); /* will update all */
+ wp->w_foldinvalid = FALSE;
+ }
+}
+
+/* setFoldRepeat() {{{2 */
+/*
+ * Open or close fold for current window at line "lnum".
+ * Repeat "count" times.
+ */
+ static void
+setFoldRepeat(lnum, count, open)
+ linenr_T lnum;
+ long count;
+ int open;
+{
+ int done;
+ long n;
+
+ for (n = 0; n < count; ++n)
+ {
+ done = DONE_NOTHING;
+ (void)setManualFold(lnum, open, FALSE, &done);
+ if (!(done & DONE_ACTION))
+ {
+ /* Only give an error message when no fold could be opened. */
+ if (n == 0 && !(done & DONE_FOLD))
+ EMSG(_(e_nofold));
+ break;
+ }
+ }
+}
+
+/* setManualFold() {{{2 */
+/*
+ * Open or close the fold in the current window which contains "lnum".
+ * Also does this for other windows in diff mode when needed.
+ */
+ static linenr_T
+setManualFold(lnum, opening, recurse, donep)
+ linenr_T lnum;
+ int opening; /* TRUE when opening, FALSE when closing */
+ int recurse; /* TRUE when closing/opening recursive */
+ int *donep;
+{
+#ifdef FEAT_DIFF
+ if (foldmethodIsDiff(curwin) && curwin->w_p_scb)
+ {
+ win_T *wp;
+ linenr_T dlnum;
+
+ /*
+ * Do the same operation in other windows in diff mode. Calculate the
+ * line number from the diffs.
+ */
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp != curwin && foldmethodIsDiff(wp) && wp->w_p_scb)
+ {
+ dlnum = diff_lnum_win(curwin->w_cursor.lnum, wp);
+ if (dlnum != 0)
+ (void)setManualFoldWin(wp, dlnum, opening, recurse, NULL);
+ }
+ }
+ }
+#endif
+
+ return setManualFoldWin(curwin, lnum, opening, recurse, donep);
+}
+
+/* setManualFoldWin() {{{2 */
+/*
+ * Open or close the fold in window "wp" which contains "lnum".
+ * "donep", when not NULL, points to flag that is set to DONE_FOLD when some
+ * fold was found and to DONE_ACTION when some fold was opened or closed.
+ * When "donep" is NULL give an error message when no fold was found for
+ * "lnum", but only if "wp" is "curwin".
+ * Return the line number of the next line that could be closed.
+ * It's only valid when "opening" is TRUE!
+ */
+ static linenr_T
+setManualFoldWin(wp, lnum, opening, recurse, donep)
+ win_T *wp;
+ linenr_T lnum;
+ int opening; /* TRUE when opening, FALSE when closing */
+ int recurse; /* TRUE when closing/opening recursive */
+ int *donep;
+{
+ fold_T *fp;
+ fold_T *fp2;
+ fold_T *found = NULL;
+ int j;
+ int level = 0;
+ int use_level = FALSE;
+ int found_fold = FALSE;
+ garray_T *gap;
+ linenr_T next = MAXLNUM;
+ linenr_T off = 0;
+ int done = 0;
+
+ checkupdate(wp);
+
+ /*
+ * Find the fold, open or close it.
+ */
+ gap = &wp->w_folds;
+ for (;;)
+ {
+ if (!foldFind(gap, lnum, &fp))
+ {
+ /* If there is a following fold, continue there next time. */
+ if (fp < (fold_T *)gap->ga_data + gap->ga_len)
+ next = fp->fd_top + off;
+ break;
+ }
+
+ /* lnum is inside this fold */
+ found_fold = TRUE;
+
+ /* If there is a following fold, continue there next time. */
+ if (fp + 1 < (fold_T *)gap->ga_data + gap->ga_len)
+ next = fp[1].fd_top + off;
+
+ /* Change from level-dependent folding to manual. */
+ if (use_level || fp->fd_flags == FD_LEVEL)
+ {
+ use_level = TRUE;
+ if (level >= wp->w_p_fdl)
+ fp->fd_flags = FD_CLOSED;
+ else
+ fp->fd_flags = FD_OPEN;
+ fp2 = (fold_T *)fp->fd_nested.ga_data;
+ for (j = 0; j < fp->fd_nested.ga_len; ++j)
+ fp2[j].fd_flags = FD_LEVEL;
+ }
+
+ /* Simple case: Close recursively means closing the fold. */
+ if (!opening && recurse)
+ {
+ if (fp->fd_flags != FD_CLOSED)
+ {
+ done |= DONE_ACTION;
+ fp->fd_flags = FD_CLOSED;
+ }
+ }
+ else if (fp->fd_flags == FD_CLOSED)
+ {
+ /* When opening, open topmost closed fold. */
+ if (opening)
+ {
+ fp->fd_flags = FD_OPEN;
+ done |= DONE_ACTION;
+ if (recurse)
+ foldOpenNested(fp);
+ }
+ break;
+ }
+
+ /* fold is open, check nested folds */
+ found = fp;
+ gap = &fp->fd_nested;
+ lnum -= fp->fd_top;
+ off += fp->fd_top;
+ ++level;
+ }
+ if (found_fold)
+ {
+ /* When closing and not recurse, close deepest open fold. */
+ if (!opening && found != NULL)
+ {
+ found->fd_flags = FD_CLOSED;
+ done |= DONE_ACTION;
+ }
+ wp->w_fold_manual = TRUE;
+ if (done & DONE_ACTION)
+ changed_window_setting_win(wp);
+ done |= DONE_FOLD;
+ }
+ else if (donep == NULL && wp == curwin)
+ EMSG(_(e_nofold));
+
+ if (donep != NULL)
+ *donep |= done;
+
+ return next;
+}
+
+/* foldOpenNested() {{{2 */
+/*
+ * Open all nested folds in fold "fpr" recursively.
+ */
+ static void
+foldOpenNested(fpr)
+ fold_T *fpr;
+{
+ int i;
+ fold_T *fp;
+
+ fp = (fold_T *)fpr->fd_nested.ga_data;
+ for (i = 0; i < fpr->fd_nested.ga_len; ++i)
+ {
+ foldOpenNested(&fp[i]);
+ fp[i].fd_flags = FD_OPEN;
+ }
+}
+
+/* deleteFoldEntry() {{{2 */
+/*
+ * Delete fold "idx" from growarray "gap".
+ * When "recursive" is TRUE also delete all the folds contained in it.
+ * When "recursive" is FALSE contained folds are moved one level up.
+ */
+ static void
+deleteFoldEntry(gap, idx, recursive)
+ garray_T *gap;
+ int idx;
+ int recursive;
+{
+ fold_T *fp;
+ int i;
+ long moved;
+ fold_T *nfp;
+
+ fp = (fold_T *)gap->ga_data + idx;
+ if (recursive || fp->fd_nested.ga_len == 0)
+ {
+ /* recursively delete the contained folds */
+ deleteFoldRecurse(&fp->fd_nested);
+ --gap->ga_len;
+ ++gap->ga_room;
+ if (idx < gap->ga_len)
+ mch_memmove(fp, fp + 1, sizeof(fold_T) * (gap->ga_len - idx));
+ }
+ else
+ {
+ /* move nested folds one level up, to overwrite the fold that is
+ * deleted. */
+ moved = fp->fd_nested.ga_len;
+ if (ga_grow(gap, (int)(moved - 1)) == OK)
+ {
+ /* adjust fd_top and fd_flags for the moved folds */
+ nfp = (fold_T *)fp->fd_nested.ga_data;
+ for (i = 0; i < moved; ++i)
+ {
+ nfp[i].fd_top += fp->fd_top;
+ if (fp->fd_flags == FD_LEVEL)
+ nfp[i].fd_flags = FD_LEVEL;
+ if (fp->fd_small == MAYBE)
+ nfp[i].fd_small = MAYBE;
+ }
+
+ /* move the existing folds down to make room */
+ if (idx < gap->ga_len)
+ mch_memmove(fp + moved, fp + 1,
+ sizeof(fold_T) * (gap->ga_len - idx));
+ /* move the contained folds one level up */
+ mch_memmove(fp, nfp, (size_t)(sizeof(fold_T) * moved));
+ vim_free(nfp);
+ gap->ga_len += moved - 1;
+ gap->ga_room -= moved - 1;
+ }
+ }
+}
+
+/* deleteFoldRecurse() {{{2 */
+/*
+ * Delete nested folds in a fold.
+ */
+ void
+deleteFoldRecurse(gap)
+ garray_T *gap;
+{
+ int i;
+
+ for (i = 0; i < gap->ga_len; ++i)
+ deleteFoldRecurse(&(((fold_T *)(gap->ga_data))[i].fd_nested));
+ ga_clear(gap);
+}
+
+/* foldMarkAdjust() {{{2 */
+/*
+ * Update line numbers of folds for inserted/deleted lines.
+ */
+ void
+foldMarkAdjust(wp, line1, line2, amount, amount_after)
+ win_T *wp;
+ linenr_T line1;
+ linenr_T line2;
+ long amount;
+ long amount_after;
+{
+ /* If deleting marks from line1 to line2, but not deleting all those
+ * lines, set line2 so that only deleted lines have their folds removed. */
+ if (amount == MAXLNUM && line2 >= line1 && line2 - line1 >= -amount_after)
+ line2 = line1 - amount_after - 1;
+ /* If appending a line in Insert mode, it should be included in the fold
+ * just above the line. */
+ if ((State & INSERT) && amount == (linenr_T)1 && line2 == MAXLNUM)
+ --line1;
+ foldMarkAdjustRecurse(&wp->w_folds, line1, line2, amount, amount_after);
+}
+
+/* foldMarkAdjustRecurse() {{{2 */
+ static void
+foldMarkAdjustRecurse(gap, line1, line2, amount, amount_after)
+ garray_T *gap;
+ linenr_T line1;
+ linenr_T line2;
+ long amount;
+ long amount_after;
+{
+ fold_T *fp;
+ int i;
+ linenr_T last;
+ linenr_T top;
+
+ /* In Insert mode an inserted line at the top of a fold is considered part
+ * of the fold, otherwise it isn't. */
+ if ((State & INSERT) && amount == (linenr_T)1 && line2 == MAXLNUM)
+ top = line1 + 1;
+ else
+ top = line1;
+
+ /* Find the fold containing or just below "line1". */
+ (void)foldFind(gap, line1, &fp);
+
+ /*
+ * Adjust all folds below "line1" that are affected.
+ */
+ for (i = (int)(fp - (fold_T *)gap->ga_data); i < gap->ga_len; ++i, ++fp)
+ {
+ /*
+ * Check for these situations:
+ * 1 2 3
+ * 1 2 3
+ * line1 2 3 4 5
+ * 2 3 4 5
+ * 2 3 4 5
+ * line2 2 3 4 5
+ * 3 5 6
+ * 3 5 6
+ */
+
+ last = fp->fd_top + fp->fd_len - 1; /* last line of fold */
+
+ /* 1. fold completely above line1: nothing to do */
+ if (last < line1)
+ continue;
+
+ /* 6. fold below line2: only adjust for amount_after */
+ if (fp->fd_top > line2)
+ {
+ if (amount_after == 0)
+ break;
+ fp->fd_top += amount_after;
+ }
+ else
+ {
+ if (fp->fd_top >= top && last <= line2)
+ {
+ /* 4. fold completely contained in range */
+ if (amount == MAXLNUM)
+ {
+ /* Deleting lines: delete the fold completely */
+ deleteFoldEntry(gap, i, TRUE);
+ --i; /* adjust index for deletion */
+ --fp;
+ }
+ else
+ fp->fd_top += amount;
+ }
+ else
+ {
+ /* 2, 3, or 5: need to correct nested folds too */
+ foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top,
+ line2 - fp->fd_top, amount, amount_after);
+ if (fp->fd_top < top)
+ {
+ if (last <= line2)
+ {
+ /* 2. fold contains line1, line2 is below fold */
+ if (amount == MAXLNUM)
+ fp->fd_len = line1 - fp->fd_top;
+ else
+ fp->fd_len += amount;
+ }
+ else
+ {
+ /* 3. fold contains line1 and line2 */
+ fp->fd_len += amount_after;
+ }
+ }
+ else
+ {
+ /* 5. fold is below line1 and contains line2 */
+ if (amount == MAXLNUM)
+ {
+ fp->fd_len -= line2 - fp->fd_top + 1;
+ fp->fd_top = line1;
+ }
+ else
+ {
+ fp->fd_len += amount_after - amount;
+ fp->fd_top += amount;
+ }
+ }
+ }
+ }
+ }
+}
+
+/* getDeepestNesting() {{{2 */
+/*
+ * Get the lowest 'foldlevel' value that makes the deepest nested fold in the
+ * current window open.
+ */
+ int
+getDeepestNesting()
+{
+ checkupdate(curwin);
+ return getDeepestNestingRecurse(&curwin->w_folds);
+}
+
+ static int
+getDeepestNestingRecurse(gap)
+ garray_T *gap;
+{
+ int i;
+ int level;
+ int maxlevel = 0;
+ fold_T *fp;
+
+ fp = (fold_T *)gap->ga_data;
+ for (i = 0; i < gap->ga_len; ++i)
+ {
+ level = getDeepestNestingRecurse(&fp[i].fd_nested) + 1;
+ if (level > maxlevel)
+ maxlevel = level;
+ }
+
+ return maxlevel;
+}
+
+/* check_closed() {{{2 */
+/*
+ * Check if a fold is closed and update the info needed to check nested folds.
+ */
+ static int
+check_closed(win, fp, use_levelp, level, maybe_smallp, lnum_off)
+ win_T *win;
+ fold_T *fp;
+ int *use_levelp; /* TRUE: outer fold had FD_LEVEL */
+ int level; /* folding depth */
+ int *maybe_smallp; /* TRUE: outer this had fd_small == MAYBE */
+ linenr_T lnum_off; /* line number offset for fp->fd_top */
+{
+ int closed = FALSE;
+
+ /* Check if this fold is closed. If the flag is FD_LEVEL this
+ * fold and all folds it contains depend on 'foldlevel'. */
+ if (*use_levelp || fp->fd_flags == FD_LEVEL)
+ {
+ *use_levelp = TRUE;
+ if (level >= win->w_p_fdl)
+ closed = TRUE;
+ }
+ else if (fp->fd_flags == FD_CLOSED)
+ closed = TRUE;
+
+ /* Small fold isn't closed anyway. */
+ if (fp->fd_small == MAYBE)
+ *maybe_smallp = TRUE;
+ if (closed)
+ {
+ if (*maybe_smallp)
+ fp->fd_small = MAYBE;
+ checkSmall(win, fp, lnum_off);
+ if (fp->fd_small == TRUE)
+ closed = FALSE;
+ }
+ return closed;
+}
+
+/* checkSmall() {{{2 */
+/*
+ * Update fd_small field of fold "fp".
+ */
+ static void
+checkSmall(wp, fp, lnum_off)
+ win_T *wp;
+ fold_T *fp;
+ linenr_T lnum_off; /* offset for fp->fd_top */
+{
+ int count;
+ int n;
+
+ if (fp->fd_small == MAYBE)
+ {
+ /* Mark any nested folds to maybe-small */
+ setSmallMaybe(&fp->fd_nested);
+
+ if (fp->fd_len > curwin->w_p_fml)
+ fp->fd_small = FALSE;
+ else
+ {
+ count = 0;
+ for (n = 0; n < fp->fd_len; ++n)
+ {
+ count += plines_win_nofold(wp, fp->fd_top + lnum_off + n);
+ if (count > curwin->w_p_fml)
+ {
+ fp->fd_small = FALSE;
+ return;
+ }
+ }
+ fp->fd_small = TRUE;
+ }
+ }
+}
+
+/* setSmallMaybe() {{{2 */
+/*
+ * Set small flags in "gap" to MAYBE.
+ */
+ static void
+setSmallMaybe(gap)
+ garray_T *gap;
+{
+ int i;
+ fold_T *fp;
+
+ fp = (fold_T *)gap->ga_data;
+ for (i = 0; i < gap->ga_len; ++i)
+ fp[i].fd_small = MAYBE;
+}
+
+/* foldCreateMarkers() {{{2 */
+/*
+ * Create a fold from line "start" to line "end" (inclusive) in the current
+ * window by adding markers.
+ */
+ static void
+foldCreateMarkers(start, end)
+ linenr_T start;
+ linenr_T end;
+{
+ if (!curbuf->b_p_ma)
+ {
+ EMSG(_(e_modifiable));
+ return;
+ }
+ parseMarker(curwin);
+
+ foldAddMarker(start, curwin->w_p_fmr, foldstartmarkerlen);
+ foldAddMarker(end, foldendmarker, foldendmarkerlen);
+
+ /* Update both changes here, to avoid all folds after the start are
+ * changed when the start marker is inserted and the end isn't. */
+ changed_lines(start, (colnr_T)0, end, 0L);
+}
+
+/* foldAddMarker() {{{2 */
+/*
+ * Add "marker[markerlen]" in 'commentstring' to line "lnum".
+ */
+ static void
+foldAddMarker(lnum, marker, markerlen)
+ linenr_T lnum;
+ char_u *marker;
+ int markerlen;
+{
+ char_u *cms = curbuf->b_p_cms;
+ char_u *line;
+ int line_len;
+ char_u *newline;
+ char_u *p = (char_u *)strstr((char *)curbuf->b_p_cms, "%s");
+
+ /* Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end */
+ line = ml_get(lnum);
+ line_len = (int)STRLEN(line);
+
+ if (u_save(lnum - 1, lnum + 1) == OK)
+ {
+ newline = alloc((unsigned)(line_len + markerlen + STRLEN(cms) + 1));
+ if (newline == NULL)
+ return;
+ STRCPY(newline, line);
+ if (p == NULL)
+ {
+ STRNCPY(newline + line_len, marker, markerlen);
+ newline[line_len + markerlen] = NUL;
+ }
+ else
+ {
+ STRCPY(newline + line_len, cms);
+ STRNCPY(newline + line_len + (p - cms), marker, markerlen);
+ STRCPY(newline + line_len + (p - cms) + markerlen, p + 2);
+ }
+
+ ml_replace(lnum, newline, FALSE);
+ }
+}
+
+/* deleteFoldMarkers() {{{2 */
+/*
+ * Delete the markers for a fold, causing it to be deleted.
+ */
+ static void
+deleteFoldMarkers(fp, recursive, lnum_off)
+ fold_T *fp;
+ int recursive;
+ linenr_T lnum_off; /* offset for fp->fd_top */
+{
+ int i;
+
+ if (recursive)
+ for (i = 0; i < fp->fd_nested.ga_len; ++i)
+ deleteFoldMarkers((fold_T *)fp->fd_nested.ga_data + i, TRUE,
+ lnum_off + fp->fd_top);
+ foldDelMarker(fp->fd_top + lnum_off, curwin->w_p_fmr, foldstartmarkerlen);
+ foldDelMarker(fp->fd_top + lnum_off + fp->fd_len - 1,
+ foldendmarker, foldendmarkerlen);
+}
+
+/* foldDelMarker() {{{2 */
+/*
+ * Delete marker "marker[markerlen]" at the end of line "lnum".
+ * Delete 'commentstring' if it matches.
+ * If the marker is not found, there is no error message. Could a missing
+ * close-marker.
+ */
+ static void
+foldDelMarker(lnum, marker, markerlen)
+ linenr_T lnum;
+ char_u *marker;
+ int markerlen;
+{
+ char_u *line;
+ char_u *newline;
+ char_u *p;
+ int len;
+ char_u *cms = curbuf->b_p_cms;
+ char_u *cms2;
+
+ line = ml_get(lnum);
+ for (p = line; *p != NUL; ++p)
+ if (STRNCMP(p, marker, markerlen) == 0)
+ {
+ /* Found the marker, include a digit if it's there. */
+ len = markerlen;
+ if (VIM_ISDIGIT(p[len]))
+ ++len;
+ if (*cms != NUL)
+ {
+ /* Also delete 'commentstring' if it matches. */
+ cms2 = (char_u *)strstr((char *)cms, "%s");
+ if (p - line >= cms2 - cms
+ && STRNCMP(p - (cms2 - cms), cms, cms2 - cms) == 0
+ && STRNCMP(p + len, cms2 + 2, STRLEN(cms2 + 2)) == 0)
+ {
+ p -= cms2 - cms;
+ len += (int)STRLEN(cms) - 2;
+ }
+ }
+ if (u_save(lnum - 1, lnum + 1) == OK)
+ {
+ /* Make new line: text-before-marker + text-after-marker */
+ newline = alloc((unsigned)(STRLEN(line) - len + 1));
+ if (newline != NULL)
+ {
+ STRNCPY(newline, line, p - line);
+ STRCPY(newline + (p - line), p + len);
+ ml_replace(lnum, newline, FALSE);
+ }
+ }
+ break;
+ }
+}
+
+/* foldtext_cleanup() {{{2 */
+/*
+ * Remove 'foldmarker' and 'commentstring' from "str" (in-place).
+ */
+ void
+foldtext_cleanup(str)
+ char_u *str;
+{
+ char_u *cms_start; /* first part or the whole comment */
+ int cms_slen = 0; /* length of cms_start */
+ char_u *cms_end; /* last part of the comment or NULL */
+ int cms_elen = 0; /* length of cms_end */
+ char_u *s;
+ int len;
+ int did1 = FALSE;
+ int did2 = FALSE;
+
+ /* Ignore leading and trailing white space in 'commentstring'. */
+ cms_start = skipwhite(curbuf->b_p_cms);
+ cms_slen = STRLEN(cms_start);
+ while (cms_slen > 0 && vim_iswhite(cms_start[cms_slen - 1]))
+ --cms_slen;
+
+ /* locate "%s" in 'commentstring', use the part before and after it. */
+ cms_end = (char_u *)strstr((char *)cms_start, "%s");
+ if (cms_end != NULL)
+ {
+ cms_elen = cms_slen - (cms_end - cms_start);
+ cms_slen = cms_end - cms_start;
+
+ /* exclude white space before "%s" */
+ while (cms_slen > 0 && vim_iswhite(cms_start[cms_slen - 1]))
+ --cms_slen;
+
+ /* skip "%s" and white space after it */
+ s = skipwhite(cms_end + 2);
+ cms_elen -= s - cms_end;
+ cms_end = s;
+ }
+ parseMarker(curwin);
+
+ for (s = str; *s != NUL; )
+ {
+ len = 0;
+ if (STRNCMP(s, curwin->w_p_fmr, foldstartmarkerlen) == 0)
+ {
+ len = foldstartmarkerlen;
+ if (VIM_ISDIGIT(s[len]))
+ ++len;
+ }
+ else if (STRNCMP(s, foldendmarker, foldendmarkerlen) == 0)
+ {
+ len = foldendmarkerlen;
+ if (VIM_ISDIGIT(s[len]))
+ ++len;
+ }
+ else if (cms_end != NULL)
+ {
+ if (!did1 && STRNCMP(s, cms_start, cms_slen) == 0)
+ {
+ len = cms_slen;
+ did1 = TRUE;
+ }
+ else if (!did2 && STRNCMP(s, cms_end, cms_elen) == 0)
+ {
+ len = cms_elen;
+ did2 = TRUE;
+ }
+ }
+ if (len != 0)
+ {
+ while (vim_iswhite(s[len]))
+ ++len;
+ mch_memmove(s, s + len, STRLEN(s + len) + 1);
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ s += (*mb_ptr2len_check)(s);
+ else
+#endif
+ ++s;
+ }
+ }
+}
+
+/* Folding by indent, expr, marker and syntax. {{{1 */
+/* Define "fline_T", passed to get fold level for a line. {{{2 */
+typedef struct
+{
+ win_T *wp; /* window */
+ linenr_T lnum; /* current line number */
+ linenr_T off; /* offset between lnum and real line number */
+ linenr_T lnum_save; /* line nr used by foldUpdateIEMSRecurse() */
+ int lvl; /* current level (-1 for undefined) */
+ int lvl_next; /* level used for next line */
+ int start; /* number of folds that are forced to start at
+ this line. */
+ int end; /* level of fold that is forced to end below
+ this line */
+ int had_end; /* level of fold that is forced to end above
+ this line (copy of "end" of prev. line) */
+} fline_T;
+
+/* Flag is set when redrawing is needed. */
+static int fold_changed;
+
+/* Function declarations. {{{2 */
+static linenr_T foldUpdateIEMSRecurse __ARGS((garray_T *gap, int level, linenr_T startlnum, fline_T *flp, void (*getlevel)__ARGS((fline_T *)), linenr_T bot, int topflags));
+static int foldInsert __ARGS((garray_T *gap, int i));
+static void foldSplit __ARGS((garray_T *gap, int i, linenr_T top, linenr_T bot));
+static void foldRemove __ARGS((garray_T *gap, linenr_T top, linenr_T bot));
+static void foldMerge __ARGS((fold_T *fp1, garray_T *gap, fold_T *fp2));
+static void foldlevelIndent __ARGS((fline_T *flp));
+#ifdef FEAT_DIFF
+static void foldlevelDiff __ARGS((fline_T *flp));
+#endif
+static void foldlevelExpr __ARGS((fline_T *flp));
+static void foldlevelMarker __ARGS((fline_T *flp));
+static void foldlevelSyntax __ARGS((fline_T *flp));
+
+/* foldUpdateIEMS() {{{2 */
+/*
+ * Update the folding for window "wp", at least from lines "top" to "bot".
+ * Return TRUE if any folds did change.
+ */
+ static void
+foldUpdateIEMS(wp, top, bot)
+ win_T *wp;
+ linenr_T top;
+ linenr_T bot;
+{
+ linenr_T start;
+ linenr_T end;
+ fline_T fline;
+ void (*getlevel)__ARGS((fline_T *));
+ int level;
+ fold_T *fp;
+
+ /* Avoid problems when being called recursively. */
+ if (invalid_top != (linenr_T)0)
+ return;
+
+ if (wp->w_foldinvalid)
+ {
+ /* Need to update all folds. */
+ top = 1;
+ bot = wp->w_buffer->b_ml.ml_line_count;
+ wp->w_foldinvalid = FALSE;
+
+ /* Mark all folds a maybe-small. */
+ setSmallMaybe(&wp->w_folds);
+ }
+
+#ifdef FEAT_DIFF
+ /* add the context for "diff" folding */
+ if (foldmethodIsDiff(wp))
+ {
+ if (top > diff_context)
+ top -= diff_context;
+ else
+ top = 1;
+ bot += diff_context;
+ }
+#endif
+
+ /* When deleting lines at the end of the buffer "top" can be past the end
+ * of the buffer. */
+ if (top > wp->w_buffer->b_ml.ml_line_count)
+ top = wp->w_buffer->b_ml.ml_line_count;
+
+ fold_changed = FALSE;
+ fline.wp = wp;
+ fline.off = 0;
+ fline.lvl = 0;
+ fline.lvl_next = -1;
+ fline.start = 0;
+ fline.end = MAX_LEVEL + 1;
+ fline.had_end = MAX_LEVEL + 1;
+
+ invalid_top = top;
+ invalid_bot = bot;
+
+ if (foldmethodIsMarker(wp))
+ {
+ getlevel = foldlevelMarker;
+
+ /* Init marker variables to speed up foldlevelMarker(). */
+ parseMarker(wp);
+
+ /* Need to get the level of the line above top, it is used if there is
+ * no marker at the top. */
+ if (top > 1)
+ {
+ /* Get the fold level at top - 1. */
+ level = foldLevelWin(wp, top - 1);
+
+ /* The fold may end just above the top, check for that. */
+ fline.lnum = top - 1;
+ fline.lvl = level;
+ getlevel(&fline);
+
+ /* If a fold started here, we already had the level, if it stops
+ * here, we need to use lvl_next. Could also start and end a fold
+ * in the same line. */
+ if (fline.lvl > level)
+ fline.lvl = level - (fline.lvl - fline.lvl_next);
+ else
+ fline.lvl = fline.lvl_next;
+ }
+ fline.lnum = top;
+ getlevel(&fline);
+ }
+ else
+ {
+ fline.lnum = top;
+ if (foldmethodIsExpr(wp))
+ {
+ getlevel = foldlevelExpr;
+ /* start one line back, because a "<1" may indicate the end of a
+ * fold in the topline */
+ if (top > 1)
+ --fline.lnum;
+ }
+ else if (foldmethodIsSyntax(wp))
+ getlevel = foldlevelSyntax;
+#ifdef FEAT_DIFF
+ else if (foldmethodIsDiff(wp))
+ getlevel = foldlevelDiff;
+#endif
+ else
+ getlevel = foldlevelIndent;
+
+ /* Backup to a line for which the fold level is defined. Since it's
+ * always defined for line one, we will stop there. */
+ fline.lvl = -1;
+ for ( ; !got_int; --fline.lnum)
+ {
+ /* Reset lvl_next each time, because it will be set to a value for
+ * the next line, but we search backwards here. */
+ fline.lvl_next = -1;
+ getlevel(&fline);
+ if (fline.lvl >= 0)
+ break;
+ }
+ }
+
+ start = fline.lnum;
+ end = bot;
+ /* Do at least one line. */
+ if (start > end && end < wp->w_buffer->b_ml.ml_line_count)
+ end = start;
+ while (!got_int)
+ {
+ /* Always stop at the end of the file ("end" can be past the end of
+ * the file). */
+ if (fline.lnum > wp->w_buffer->b_ml.ml_line_count)
+ break;
+ if (fline.lnum > end)
+ {
+ /* For "marker", "expr" and "syntax" methods: If a change caused
+ * a fold to be removed, we need to continue at least until where
+ * it ended. */
+ if (getlevel != foldlevelMarker
+ && getlevel != foldlevelSyntax
+ && getlevel != foldlevelExpr)
+ break;
+ if ((start <= end
+ && foldFind(&wp->w_folds, end, &fp)
+ && fp->fd_top + fp->fd_len - 1 > end)
+ || (fline.lvl == 0
+ && foldFind(&wp->w_folds, fline.lnum, &fp)
+ && fp->fd_top < fline.lnum))
+ end = fp->fd_top + fp->fd_len - 1;
+ else if (getlevel == foldlevelSyntax
+ && foldLevelWin(wp, fline.lnum) != fline.lvl)
+ /* For "syntax" method: Compare the foldlevel that the syntax
+ * tells us to the foldlevel from the existing folds. If they
+ * don't match continue updating folds. */
+ end = fline.lnum;
+ else
+ break;
+ }
+
+ /* A level 1 fold starts at a line with foldlevel > 0. */
+ if (fline.lvl > 0)
+ {
+ invalid_top = fline.lnum;
+ invalid_bot = end;
+ end = foldUpdateIEMSRecurse(&wp->w_folds,
+ 1, start, &fline, getlevel, end, FD_LEVEL);
+ start = fline.lnum;
+ }
+ else
+ {
+ if (fline.lnum == wp->w_buffer->b_ml.ml_line_count)
+ break;
+ ++fline.lnum;
+ fline.lvl = fline.lvl_next;
+ getlevel(&fline);
+ }
+ }
+
+ /* There can't be any folds from start until end now. */
+ foldRemove(&wp->w_folds, start, end);
+
+ /* If some fold changed, need to redraw and position cursor. */
+ if (fold_changed && wp->w_p_fen)
+ changed_window_setting();
+
+ /* If we updated folds past "bot", need to redraw more lines. Don't do
+ * this in other situations, the changed lines will be redrawn anyway and
+ * this method can cause the whole window to be updated. */
+ if (end != bot)
+ {
+ if (wp->w_redraw_top == 0 || wp->w_redraw_top > top)
+ wp->w_redraw_top = top;
+ if (wp->w_redraw_bot < end)
+ wp->w_redraw_bot = end;
+ }
+
+ invalid_top = (linenr_T)0;
+}
+
+/* foldUpdateIEMSRecurse() {{{2 */
+/*
+ * Update a fold that starts at "flp->lnum". At this line there is always a
+ * valid foldlevel, and its level >= "level".
+ * "flp" is valid for "flp->lnum" when called and it's valid when returning.
+ * "flp->lnum" is set to the lnum just below the fold, if it ends before
+ * "bot", it's "bot" plus one if the fold continues and it's bigger when using
+ * the marker method and a text change made following folds to change.
+ * When returning, "flp->lnum_save" is the line number that was used to get
+ * the level when the level at "flp->lnum" is invalid.
+ * Remove any folds from "startlnum" up to here at this level.
+ * Recursively update nested folds.
+ * Below line "bot" there are no changes in the text.
+ * "flp->lnum", "flp->lnum_save" and "bot" are relative to the start of the
+ * outer fold.
+ * "flp->off" is the offset to the real line number in the buffer.
+ *
+ * All this would be a lot simpler if all folds in the range would be deleted
+ * and then created again. But we would loose all information about the
+ * folds, even when making changes that don't affect the folding (e.g. "vj~").
+ *
+ * Returns bot, which may have been increased for lines that also need to be
+ * updated as a result of a detected change in the fold.
+ */
+ static linenr_T
+foldUpdateIEMSRecurse(gap, level, startlnum, flp, getlevel, bot, topflags)
+ garray_T *gap;
+ int level;
+ linenr_T startlnum;
+ fline_T *flp;
+ void (*getlevel)__ARGS((fline_T *));
+ linenr_T bot;
+ int topflags; /* flags used by containing fold */
+{
+ linenr_T ll;
+ fold_T *fp = NULL;
+ fold_T *fp2;
+ int lvl = level;
+ linenr_T startlnum2 = startlnum;
+ linenr_T firstlnum = flp->lnum; /* first lnum we got */
+ int i;
+ int finish = FALSE;
+ linenr_T linecount = flp->wp->w_buffer->b_ml.ml_line_count - flp->off;
+ int concat;
+
+ /*
+ * If using the marker method, the start line is not the start of a fold
+ * at the level we're dealing with and the level is non-zero, we must use
+ * the previous fold. But ignore a fold that starts at or below
+ * startlnum, it must be deleted.
+ */
+ if (getlevel == foldlevelMarker && flp->start <= flp->lvl - level
+ && flp->lvl > 0)
+ {
+ foldFind(gap, startlnum - 1, &fp);
+ if (fp >= ((fold_T *)gap->ga_data) + gap->ga_len
+ || fp->fd_top >= startlnum)
+ fp = NULL;
+ }
+
+ /*
+ * Loop over all lines in this fold, or until "bot" is hit.
+ * Handle nested folds inside of this fold.
+ * "flp->lnum" is the current line. When finding the end of the fold, it
+ * is just below the end of the fold.
+ * "*flp" contains the level of the line "flp->lnum" or a following one if
+ * there are lines with an invalid fold level. "flp->lnum_save" is the
+ * line number that was used to get the fold level (below "flp->lnum" when
+ * it has an invalid fold level). When called the fold level is always
+ * valid, thus "flp->lnum_save" is equal to "flp->lnum".
+ */
+ flp->lnum_save = flp->lnum;
+ while (!got_int)
+ {
+ /* Updating folds can be slow, check for CTRL-C. */
+ line_breakcheck();
+
+ /* Set "lvl" to the level of line "flp->lnum". When flp->start is set
+ * and after the first line of the fold, set the level to zero to
+ * force the fold to end. Do the same when had_end is set: Previous
+ * line was marked as end of a fold. */
+ lvl = flp->lvl;
+ if (lvl > MAX_LEVEL)
+ lvl = MAX_LEVEL;
+ if (flp->lnum > firstlnum
+ && (level > lvl - flp->start || level >= flp->had_end))
+ lvl = 0;
+
+ if (flp->lnum > bot && !finish && fp != NULL)
+ {
+ /* For "marker" and "syntax" methods:
+ * - If a change caused a nested fold to be removed, we need to
+ * delete it and continue at least until where it ended.
+ * - If a change caused a nested fold to be created, or this fold
+ * to continue below its original end, need to finish this fold.
+ */
+ if (getlevel != foldlevelMarker
+ && getlevel != foldlevelExpr
+ && getlevel != foldlevelSyntax)
+ break;
+ i = 0;
+ fp2 = fp;
+ if (lvl >= level)
+ {
+ /* Compute how deep the folds currently are, if it's deeper
+ * than "lvl" then some must be deleted, need to update
+ * at least one nested fold. */
+ ll = flp->lnum - fp->fd_top;
+ while (foldFind(&fp2->fd_nested, ll, &fp2))
+ {
+ ++i;
+ ll -= fp2->fd_top;
+ }
+ }
+ if (lvl < level + i)
+ {
+ foldFind(&fp->fd_nested, flp->lnum - fp->fd_top, &fp2);
+ if (fp2 != NULL)
+ bot = fp2->fd_top + fp2->fd_len - 1 + fp->fd_top;
+ }
+ else if (fp->fd_top + fp->fd_len <= flp->lnum && lvl >= level)
+ finish = TRUE;
+ else
+ break;
+ }
+
+ /* At the start of the first nested fold and at the end of the current
+ * fold: check if existing folds at this level, before the current
+ * one, need to be deleted or truncated. */
+ if (fp == NULL
+ && (lvl != level
+ || flp->lnum_save >= bot
+ || flp->start != 0
+ || flp->had_end <= MAX_LEVEL
+ || flp->lnum == linecount))
+ {
+ /*
+ * Remove or update folds that have lines between startlnum and
+ * firstlnum.
+ */
+ while (!got_int)
+ {
+ /* set concat to 1 if it's allowed to concatenated this fold
+ * with a previous one that touches it. */
+ if (flp->start != 0 || flp->had_end <= MAX_LEVEL)
+ concat = 0;
+ else
+ concat = 1;
+
+ /* Find an existing fold to re-use. Preferably one that
+ * includes startlnum, otherwise one that ends just before
+ * startlnum or starts after it. */
+ if (foldFind(gap, startlnum, &fp)
+ || (fp < ((fold_T *)gap->ga_data) + gap->ga_len
+ && fp->fd_top <= firstlnum)
+ || foldFind(gap, firstlnum - concat, &fp)
+ || (fp < ((fold_T *)gap->ga_data) + gap->ga_len
+ && ((lvl < level && fp->fd_top < flp->lnum)
+ || (lvl >= level
+ && fp->fd_top <= flp->lnum_save))))
+ {
+ if (fp->fd_top + fp->fd_len + concat > firstlnum)
+ {
+ /* Use existing fold for the new fold. If it starts
+ * before where we started looking, extend it. If it
+ * starts at another line, update nested folds to keep
+ * their position, compensating for the new fd_top. */
+ if (fp->fd_top >= startlnum && fp->fd_top != firstlnum)
+ {
+ if (fp->fd_top > firstlnum)
+ /* like lines are inserted */
+ foldMarkAdjustRecurse(&fp->fd_nested,
+ (linenr_T)0, (linenr_T)MAXLNUM,
+ (long)(fp->fd_top - firstlnum), 0L);
+ else
+ /* like lines are deleted */
+ foldMarkAdjustRecurse(&fp->fd_nested,
+ (linenr_T)0,
+ (long)(firstlnum - fp->fd_top - 1),
+ (linenr_T)MAXLNUM,
+ (long)(fp->fd_top - firstlnum));
+ fp->fd_len += fp->fd_top - firstlnum;
+ fp->fd_top = firstlnum;
+ fold_changed = TRUE;
+ }
+ else if (flp->start != 0 && lvl == level
+ && fp->fd_top != firstlnum)
+ {
+ /* Existing fold that includes startlnum must stop
+ * if we find the start of a new fold at the same
+ * level. Split it. Delete contained folds at
+ * this point to split them too. */
+ foldRemove(&fp->fd_nested, flp->lnum - fp->fd_top,
+ flp->lnum - fp->fd_top);
+ i = (int)(fp - (fold_T *)gap->ga_data);
+ foldSplit(gap, i, flp->lnum, flp->lnum - 1);
+ fp = (fold_T *)gap->ga_data + i + 1;
+ /* If using the "marker" or "syntax" method, we
+ * need to continue until the end of the fold is
+ * found. */
+ if (getlevel == foldlevelMarker
+ || getlevel == foldlevelExpr
+ || getlevel == foldlevelSyntax)
+ finish = TRUE;
+ }
+ break;
+ }
+ if (fp->fd_top >= startlnum)
+ {
+ /* A fold that starts at or after startlnum and stops
+ * before the new fold must be deleted. Continue
+ * looking for the next one. */
+ deleteFoldEntry(gap,
+ (int)(fp - (fold_T *)gap->ga_data), TRUE);
+ }
+ else
+ {
+ /* A fold has some lines above startlnum, truncate it
+ * to stop just above startlnum. */
+ fp->fd_len = startlnum - fp->fd_top;
+ foldMarkAdjustRecurse(&fp->fd_nested,
+ (linenr_T)fp->fd_len, (linenr_T)MAXLNUM,
+ (linenr_T)MAXLNUM, 0L);
+ fold_changed = TRUE;
+ }
+ }
+ else
+ {
+ /* Insert new fold. Careful: ga_data may be NULL and it
+ * may change! */
+ i = (int)(fp - (fold_T *)gap->ga_data);
+ if (foldInsert(gap, i) != OK)
+ return bot;
+ fp = (fold_T *)gap->ga_data + i;
+ /* The new fold continues until bot, unless we find the
+ * end earlier. */
+ fp->fd_top = firstlnum;
+ fp->fd_len = bot - firstlnum + 1;
+ /* When the containing fold is open, the new fold is open.
+ * The new fold is closed if the fold above it is closed.
+ * The first fold depends on the containing fold. */
+ if (topflags == FD_OPEN)
+ {
+ flp->wp->w_fold_manual = TRUE;
+ fp->fd_flags = FD_OPEN;
+ }
+ else if (i <= 0)
+ {
+ fp->fd_flags = topflags;
+ if (topflags != FD_LEVEL)
+ flp->wp->w_fold_manual = TRUE;
+ }
+ else
+ fp->fd_flags = (fp - 1)->fd_flags;
+ fp->fd_small = MAYBE;
+ /* If using the "marker", "expr" or "syntax" method, we
+ * need to continue until the end of the fold is found. */
+ if (getlevel == foldlevelMarker
+ || getlevel == foldlevelExpr
+ || getlevel == foldlevelSyntax)
+ finish = TRUE;
+ fold_changed = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (lvl < level || flp->lnum > linecount)
+ {
+ /*
+ * Found a line with a lower foldlevel, this fold ends just above
+ * "flp->lnum".
+ */
+ break;
+ }
+
+ /*
+ * The fold includes the line "flp->lnum" and "flp->lnum_save".
+ */
+ if (lvl > level)
+ {
+ /*
+ * There is a nested fold, handle it recursively.
+ */
+ /* At least do one line (can happen when finish is TRUE). */
+ if (bot < flp->lnum)
+ bot = flp->lnum;
+
+ /* Line numbers in the nested fold are relative to the start of
+ * this fold. */
+ flp->lnum = flp->lnum_save - fp->fd_top;
+ flp->off += fp->fd_top;
+ i = (int)(fp - (fold_T *)gap->ga_data);
+ bot = foldUpdateIEMSRecurse(&fp->fd_nested, level + 1,
+ startlnum2 - fp->fd_top, flp, getlevel,
+ bot - fp->fd_top, fp->fd_flags);
+ fp = (fold_T *)gap->ga_data + i;
+ flp->lnum += fp->fd_top;
+ flp->lnum_save += fp->fd_top;
+ flp->off -= fp->fd_top;
+ bot += fp->fd_top;
+ startlnum2 = flp->lnum;
+
+ /* This fold may end at the same line, don't incr. flp->lnum. */
+ }
+ else
+ {
+ /*
+ * Get the level of the next line, then continue the loop to check
+ * if it ends there.
+ * Skip over undefined lines, to find the foldlevel after it.
+ * For the last line in the file the foldlevel is always valid.
+ */
+ flp->lnum = flp->lnum_save;
+ ll = flp->lnum + 1;
+ while (!got_int)
+ {
+ /* Make the previous level available to foldlevel(). */
+ prev_lnum = flp->lnum;
+ prev_lnum_lvl = flp->lvl;
+
+ if (++flp->lnum > linecount)
+ break;
+ flp->lvl = flp->lvl_next;
+ getlevel(flp);
+ if (flp->lvl >= 0 || flp->had_end <= MAX_LEVEL)
+ break;
+ }
+ prev_lnum = 0;
+ if (flp->lnum > linecount)
+ break;
+
+ /* leave flp->lnum_save to lnum of the line that was used to get
+ * the level, flp->lnum to the lnum of the next line. */
+ flp->lnum_save = flp->lnum;
+ flp->lnum = ll;
+ }
+ }
+
+ if (fp == NULL) /* only happens when got_int is set */
+ return bot;
+
+ /*
+ * Get here when:
+ * lvl < level: the folds ends just above "flp->lnum"
+ * lvl >= level: fold continues below "bot"
+ */
+
+ /* Current fold at least extends until lnum. */
+ if (fp->fd_len < flp->lnum - fp->fd_top)
+ {
+ fp->fd_len = flp->lnum - fp->fd_top;
+ fold_changed = TRUE;
+ }
+
+ /* Delete contained folds from the end of the last one found until where
+ * we stopped looking. */
+ foldRemove(&fp->fd_nested, startlnum2 - fp->fd_top,
+ flp->lnum - 1 - fp->fd_top);
+
+ if (lvl < level)
+ {
+ /* End of fold found, update the length when it got shorter. */
+ if (fp->fd_len != flp->lnum - fp->fd_top)
+ {
+ if (fp->fd_top + fp->fd_len > bot + 1)
+ {
+ /* fold coninued below bot */
+ if (getlevel == foldlevelMarker
+ || getlevel == foldlevelExpr
+ || getlevel == foldlevelSyntax)
+ {
+ /* marker method: truncate the fold and make sure the
+ * previously included lines are processed again */
+ bot = fp->fd_top + fp->fd_len - 1;
+ fp->fd_len = flp->lnum - fp->fd_top;
+ }
+ else
+ {
+ /* indent or expr method: split fold to create a new one
+ * below bot */
+ i = (int)(fp - (fold_T *)gap->ga_data);
+ foldSplit(gap, i, flp->lnum, bot);
+ fp = (fold_T *)gap->ga_data + i;
+ }
+ }
+ else
+ fp->fd_len = flp->lnum - fp->fd_top;
+ fold_changed = TRUE;
+ }
+ }
+
+ /* delete following folds that end before the current line */
+ for (;;)
+ {
+ fp2 = fp + 1;
+ if (fp2 >= (fold_T *)gap->ga_data + gap->ga_len
+ || fp2->fd_top > flp->lnum)
+ break;
+ if (fp2->fd_top + fp2->fd_len > flp->lnum)
+ {
+ if (fp2->fd_top < flp->lnum)
+ {
+ /* Make fold that includes lnum start at lnum. */
+ foldMarkAdjustRecurse(&fp2->fd_nested,
+ (linenr_T)0, (long)(flp->lnum - fp2->fd_top - 1),
+ (linenr_T)MAXLNUM, (long)(fp2->fd_top - flp->lnum));
+ fp2->fd_len -= flp->lnum - fp2->fd_top;
+ fp2->fd_top = flp->lnum;
+ fold_changed = TRUE;
+ }
+
+ if (lvl >= level)
+ {
+ /* merge new fold with existing fold that follows */
+ foldMerge(fp, gap, fp2);
+ }
+ break;
+ }
+ fold_changed = TRUE;
+ deleteFoldEntry(gap, (int)(fp2 - (fold_T *)gap->ga_data), TRUE);
+ }
+
+ /* Need to redraw the lines we inspected, which might be further down than
+ * was asked for. */
+ if (bot < flp->lnum - 1)
+ bot = flp->lnum - 1;
+
+ return bot;
+}
+
+/* foldInsert() {{{2 */
+/*
+ * Insert a new fold in "gap" at position "i".
+ * Returns OK for success, FAIL for failure.
+ */
+ static int
+foldInsert(gap, i)
+ garray_T *gap;
+ int i;
+{
+ fold_T *fp;
+
+ if (ga_grow(gap, 1) != OK)
+ return FAIL;
+ fp = (fold_T *)gap->ga_data + i;
+ if (i < gap->ga_len)
+ mch_memmove(fp + 1, fp, sizeof(fold_T) * (gap->ga_len - i));
+ ++gap->ga_len;
+ --gap->ga_room;
+ ga_init2(&fp->fd_nested, (int)sizeof(fold_T), 10);
+ return OK;
+}
+
+/* foldSplit() {{{2 */
+/*
+ * Split the "i"th fold in "gap", which starts before "top" and ends below
+ * "bot" in two pieces, one ending above "top" and the other starting below
+ * "bot".
+ * The caller must first have taken care of any nested folds from "top" to
+ * "bot"!
+ */
+ static void
+foldSplit(gap, i, top, bot)
+ garray_T *gap;
+ int i;
+ linenr_T top;
+ linenr_T bot;
+{
+ fold_T *fp;
+ fold_T *fp2;
+ garray_T *gap1;
+ garray_T *gap2;
+ int idx;
+ int len;
+
+ /* The fold continues below bot, need to split it. */
+ if (foldInsert(gap, i + 1) == FAIL)
+ return;
+ fp = (fold_T *)gap->ga_data + i;
+ fp[1].fd_top = bot + 1;
+ fp[1].fd_len = fp->fd_len - (fp[1].fd_top - fp->fd_top);
+ fp[1].fd_flags = fp->fd_flags;
+
+ /* Move nested folds below bot to new fold. There can't be
+ * any between top and bot, they have been removed by the caller. */
+ gap1 = &fp->fd_nested;
+ gap2 = &fp[1].fd_nested;
+ (void)(foldFind(gap1, bot + 1 - fp->fd_top, &fp2));
+ len = (int)((fold_T *)gap1->ga_data + gap1->ga_len - fp2);
+ if (len > 0 && ga_grow(gap2, len) == OK)
+ {
+ for (idx = 0; idx < len; ++idx)
+ {
+ ((fold_T *)gap2->ga_data)[idx] = fp2[idx];
+ ((fold_T *)gap2->ga_data)[idx].fd_top
+ -= fp[1].fd_top - fp->fd_top;
+ }
+ gap2->ga_len = len;
+ gap2->ga_room -= len;
+ gap1->ga_len -= len;
+ gap1->ga_room += len;
+ }
+ fp->fd_len = top - fp->fd_top;
+ fold_changed = TRUE;
+}
+
+/* foldRemove() {{{2 */
+/*
+ * Remove folds within the range "top" to and including "bot".
+ * Check for these situations:
+ * 1 2 3
+ * 1 2 3
+ * top 2 3 4 5
+ * 2 3 4 5
+ * bot 2 3 4 5
+ * 3 5 6
+ * 3 5 6
+ *
+ * 1: not changed
+ * 2: trunate to stop above "top"
+ * 3: split in two parts, one stops above "top", other starts below "bot".
+ * 4: deleted
+ * 5: made to start below "bot".
+ * 6: not changed
+ */
+ static void
+foldRemove(gap, top, bot)
+ garray_T *gap;
+ linenr_T top;
+ linenr_T bot;
+{
+ fold_T *fp = NULL;
+
+ if (bot < top)
+ return; /* nothing to do */
+
+ for (;;)
+ {
+ /* Find fold that includes top or a following one. */
+ if (foldFind(gap, top, &fp) && fp->fd_top < top)
+ {
+ /* 2: or 3: need to delete nested folds */
+ foldRemove(&fp->fd_nested, top - fp->fd_top, bot - fp->fd_top);
+ if (fp->fd_top + fp->fd_len > bot + 1)
+ {
+ /* 3: need to split it. */
+ foldSplit(gap, (int)(fp - (fold_T *)gap->ga_data), top, bot);
+ }
+ else
+ {
+ /* 2: truncate fold at "top". */
+ fp->fd_len = top - fp->fd_top;
+ }
+ fold_changed = TRUE;
+ continue;
+ }
+ if (fp >= (fold_T *)(gap->ga_data) + gap->ga_len
+ || fp->fd_top > bot)
+ {
+ /* 6: Found a fold below bot, can stop looking. */
+ break;
+ }
+ if (fp->fd_top >= top)
+ {
+ /* Found an entry below top. */
+ fold_changed = TRUE;
+ if (fp->fd_top + fp->fd_len > bot)
+ {
+ /* 5: Make fold that includes bot start below bot. */
+ foldMarkAdjustRecurse(&fp->fd_nested,
+ (linenr_T)0, (long)(bot - fp->fd_top),
+ (linenr_T)MAXLNUM, (long)(fp->fd_top - bot - 1));
+ fp->fd_len -= bot - fp->fd_top + 1;
+ fp->fd_top = bot + 1;
+ break;
+ }
+
+ /* 4: Delete completely contained fold. */
+ deleteFoldEntry(gap, (int)(fp - (fold_T *)gap->ga_data), TRUE);
+ }
+ }
+}
+
+/* foldMerge() {{{2 */
+/*
+ * Merge two adjecent folds (and the nested ones in them).
+ * This only works correctly when the folds are really adjecent! Thus "fp1"
+ * must end just above "fp2".
+ * The resulting fold is "fp1", nested folds are moved from "fp2" to "fp1".
+ * Fold entry "fp2" in "gap" is deleted.
+ */
+ static void
+foldMerge(fp1, gap, fp2)
+ fold_T *fp1;
+ garray_T *gap;
+ fold_T *fp2;
+{
+ fold_T *fp3;
+ fold_T *fp4;
+ int idx;
+ garray_T *gap1 = &fp1->fd_nested;
+ garray_T *gap2 = &fp2->fd_nested;
+
+ /* If the last nested fold in fp1 touches the first nested fold in fp2,
+ * merge them recursively. */
+ if (foldFind(gap1, fp1->fd_len - 1L, &fp3) && foldFind(gap2, 0L, &fp4))
+ foldMerge(fp3, gap2, fp4);
+
+ /* Move nested folds in fp2 to the end of fp1. */
+ if (gap2->ga_len > 0 && ga_grow(gap1, gap2->ga_len) == OK)
+ {
+ for (idx = 0; idx < gap2->ga_len; ++idx)
+ {
+ ((fold_T *)gap1->ga_data)[gap1->ga_len]
+ = ((fold_T *)gap2->ga_data)[idx];
+ ((fold_T *)gap1->ga_data)[gap1->ga_len].fd_top += fp1->fd_len;
+ ++gap1->ga_len;
+ --gap1->ga_room;
+ }
+ gap2->ga_len = 0;
+ /* fp2->fd_nested.ga_room isn't updated, we delete it below */
+ }
+
+ fp1->fd_len += fp2->fd_len;
+ deleteFoldEntry(gap, (int)(fp2 - (fold_T *)gap->ga_data), TRUE);
+ fold_changed = TRUE;
+}
+
+/* foldlevelIndent() {{{2 */
+/*
+ * Low level function to get the foldlevel for the "indent" method.
+ * Doesn't use any caching.
+ * Returns a level of -1 if the foldlevel depends on surrounding lines.
+ */
+ static void
+foldlevelIndent(flp)
+ fline_T *flp;
+{
+ char_u *s;
+ buf_T *buf;
+ linenr_T lnum = flp->lnum + flp->off;
+
+ buf = flp->wp->w_buffer;
+ s = skipwhite(ml_get_buf(buf, lnum, FALSE));
+
+ /* empty line or lines starting with a character in 'foldignore': level
+ * depends on surrounding lines */
+ if (*s == NUL || vim_strchr(flp->wp->w_p_fdi, *s) != NULL)
+ {
+ /* first and last line can't be undefined, use level 0 */
+ if (lnum == 1 || lnum == buf->b_ml.ml_line_count)
+ flp->lvl = 0;
+ else
+ flp->lvl = -1;
+ }
+ else
+ flp->lvl = get_indent_buf(buf, lnum) / buf->b_p_sw;
+ if (flp->lvl > flp->wp->w_p_fdn)
+ flp->lvl = flp->wp->w_p_fdn;
+}
+
+/* foldlevelDiff() {{{2 */
+#ifdef FEAT_DIFF
+/*
+ * Low level function to get the foldlevel for the "diff" method.
+ * Doesn't use any caching.
+ */
+ static void
+foldlevelDiff(flp)
+ fline_T *flp;
+{
+ if (diff_infold(flp->wp, flp->lnum + flp->off))
+ flp->lvl = 1;
+ else
+ flp->lvl = 0;
+}
+#endif
+
+/* foldlevelExpr() {{{2 */
+/*
+ * Low level function to get the foldlevel for the "expr" method.
+ * Doesn't use any caching.
+ * Returns a level of -1 if the foldlevel depends on surrounding lines.
+ */
+ static void
+foldlevelExpr(flp)
+ fline_T *flp;
+{
+#ifndef FEAT_EVAL
+ flp->start = FALSE;
+ flp->lvl = 0;
+#else
+ win_T *win;
+ int n;
+ int c;
+ linenr_T lnum = flp->lnum + flp->off;
+ int save_keytyped;
+
+ win = curwin;
+ curwin = flp->wp;
+ curbuf = flp->wp->w_buffer;
+ set_vim_var_nr(VV_LNUM, lnum);
+
+ flp->start = 0;
+ flp->had_end = flp->end;
+ flp->end = MAX_LEVEL + 1;
+ if (lnum <= 1)
+ flp->lvl = 0;
+
+ /* KeyTyped may be reset to 0 when calling a function which invokes
+ * do_cmdline(). To make 'foldopen' work correctly restore KeyTyped. */
+ save_keytyped = KeyTyped;
+ n = eval_foldexpr(flp->wp->w_p_fde, &c);
+ KeyTyped = save_keytyped;
+
+ switch (c)
+ {
+ /* "a1", "a2", .. : add to the fold level */
+ case 'a': if (flp->lvl >= 0)
+ {
+ flp->lvl += n;
+ flp->lvl_next = flp->lvl;
+ }
+ flp->start = n;
+ break;
+
+ /* "s1", "s2", .. : subtract from the fold level */
+ case 's': if (flp->lvl >= 0)
+ {
+ if (n > flp->lvl)
+ flp->lvl_next = 0;
+ else
+ flp->lvl_next = flp->lvl - n;
+ flp->end = flp->lvl_next + 1;
+ }
+ break;
+
+ /* ">1", ">2", .. : start a fold with a certain level */
+ case '>': flp->lvl = n;
+ flp->lvl_next = n;
+ flp->start = 1;
+ break;
+
+ /* "<1", "<2", .. : end a fold with a certain level */
+ case '<': flp->lvl_next = n - 1;
+ flp->end = n;
+ break;
+
+ /* "=": No change in level */
+ case '=': flp->lvl_next = flp->lvl;
+ break;
+
+ /* "-1", "0", "1", ..: set fold level */
+ default: if (n < 0)
+ /* Use the current level for the next line, so that "a1"
+ * will work there. */
+ flp->lvl_next = flp->lvl;
+ else
+ flp->lvl_next = n;
+ flp->lvl = n;
+ break;
+ }
+
+ /* If the level is unknown for the first or the last line in the file, use
+ * level 0. */
+ if (flp->lvl < 0)
+ {
+ if (lnum <= 1)
+ {
+ flp->lvl = 0;
+ flp->lvl_next = 0;
+ }
+ if (lnum == curbuf->b_ml.ml_line_count)
+ flp->lvl_next = 0;
+ }
+
+ curwin = win;
+ curbuf = curwin->w_buffer;
+#endif
+}
+
+/* parseMarker() {{{2 */
+/*
+ * Parse 'foldmarker' and set "foldendmarker", "foldstartmarkerlen" and
+ * "foldendmarkerlen".
+ * Relies on the option value to have been checked for correctness already.
+ */
+ static void
+parseMarker(wp)
+ win_T *wp;
+{
+ foldendmarker = vim_strchr(wp->w_p_fmr, ',');
+ foldstartmarkerlen = (int)(foldendmarker++ - wp->w_p_fmr);
+ foldendmarkerlen = (int)STRLEN(foldendmarker);
+}
+
+/* foldlevelMarker() {{{2 */
+/*
+ * Low level function to get the foldlevel for the "marker" method.
+ * "foldendmarker", "foldstartmarkerlen" and "foldendmarkerlen" must have been
+ * set before calling this.
+ * Requires that flp->lvl is set to the fold level of the previous line!
+ * Careful: This means you can't call this function twice on the same line.
+ * Doesn't use any caching.
+ * Sets flp->start when a start marker was found.
+ */
+ static void
+foldlevelMarker(flp)
+ fline_T *flp;
+{
+ char_u *startmarker;
+ int cstart;
+ int cend;
+ int start_lvl = flp->lvl;
+ char_u *s;
+ int n;
+
+ /* cache a few values for speed */
+ startmarker = flp->wp->w_p_fmr;
+ cstart = *startmarker;
+ ++startmarker;
+ cend = *foldendmarker;
+
+ /* Default: no start found, next level is same as current level */
+ flp->start = 0;
+ flp->lvl_next = flp->lvl;
+
+ s = ml_get_buf(flp->wp->w_buffer, flp->lnum + flp->off, FALSE);
+ while (*s)
+ {
+ if (*s == cstart
+ && STRNCMP(s + 1, startmarker, foldstartmarkerlen - 1) == 0)
+ {
+ /* found startmarker: set flp->lvl */
+ s += foldstartmarkerlen;
+ if (VIM_ISDIGIT(*s))
+ {
+ n = atoi((char *)s);
+ if (n > 0)
+ {
+ flp->lvl = n;
+ flp->lvl_next = n;
+ if (n <= start_lvl)
+ flp->start = 1;
+ else
+ flp->start = n - start_lvl;
+ }
+ }
+ else
+ {
+ ++flp->lvl;
+ ++flp->lvl_next;
+ ++flp->start;
+ }
+ }
+ else if (*s == cend
+ && STRNCMP(s + 1, foldendmarker + 1, foldendmarkerlen - 1) == 0)
+ {
+ /* found endmarker: set flp->lvl_next */
+ s += foldendmarkerlen;
+ if (VIM_ISDIGIT(*s))
+ {
+ n = atoi((char *)s);
+ if (n > 0)
+ {
+ flp->lvl = n;
+ flp->lvl_next = n - 1;
+ /* never start a fold with an end marker */
+ if (flp->lvl_next > flp->lvl)
+ flp->lvl_next = flp->lvl;
+ }
+ }
+ else
+ --flp->lvl_next;
+ }
+ else
+ ++s;
+ }
+
+ /* The level can't go negative, must be missing a start marker. */
+ if (flp->lvl_next < 0)
+ flp->lvl_next = 0;
+}
+
+/* foldlevelSyntax() {{{2 */
+/*
+ * Low level function to get the foldlevel for the "syntax" method.
+ * Doesn't use any caching.
+ */
+ static void
+foldlevelSyntax(flp)
+ fline_T *flp;
+{
+#ifndef FEAT_SYN_HL
+ flp->start = 0;
+ flp->lvl = 0;
+#else
+ linenr_T lnum = flp->lnum + flp->off;
+ int n;
+
+ /* Use the maximum fold level at the start of this line and the next. */
+ flp->lvl = syn_get_foldlevel(flp->wp, lnum);
+ flp->start = 0;
+ if (lnum < flp->wp->w_buffer->b_ml.ml_line_count)
+ {
+ n = syn_get_foldlevel(flp->wp, lnum + 1);
+ if (n > flp->lvl)
+ {
+ flp->start = n - flp->lvl; /* fold(s) start here */
+ flp->lvl = n;
+ }
+ }
+#endif
+}
+
+/* functions for storing the fold state in a View {{{1 */
+/* put_folds() {{{2 */
+#if defined(FEAT_SESSION) || defined(PROTO)
+static int put_folds_recurse __ARGS((FILE *fd, garray_T *gap, linenr_T off));
+static int put_foldopen_recurse __ARGS((FILE *fd, garray_T *gap, linenr_T off));
+
+/*
+ * Write commands to "fd" to restore the manual folds in window "wp".
+ * Return FAIL if writing fails.
+ */
+ int
+put_folds(fd, wp)
+ FILE *fd;
+ win_T *wp;
+{
+ if (foldmethodIsManual(wp))
+ {
+ if (put_line(fd, "silent! normal! zE") == FAIL
+ || put_folds_recurse(fd, &wp->w_folds, (linenr_T)0) == FAIL)
+ return FAIL;
+ }
+
+ /* If some folds are manually opened/closed, need to restore that. */
+ if (wp->w_fold_manual)
+ return put_foldopen_recurse(fd, &wp->w_folds, (linenr_T)0);
+
+ return OK;
+}
+
+/* put_folds_recurse() {{{2 */
+/*
+ * Write commands to "fd" to recreate manually created folds.
+ * Returns FAIL when writing failed.
+ */
+ static int
+put_folds_recurse(fd, gap, off)
+ FILE *fd;
+ garray_T *gap;
+ linenr_T off;
+{
+ int i;
+ fold_T *fp;
+
+ fp = (fold_T *)gap->ga_data;
+ for (i = 0; i < gap->ga_len; i++)
+ {
+ /* Do nested folds first, they will be created closed. */
+ if (put_folds_recurse(fd, &fp->fd_nested, off + fp->fd_top) == FAIL)
+ return FAIL;
+ if (fprintf(fd, "%ld,%ldfold", fp->fd_top + off,
+ fp->fd_top + off + fp->fd_len - 1) < 0
+ || put_eol(fd) == FAIL)
+ return FAIL;
+ ++fp;
+ }
+ return OK;
+}
+
+/* put_foldopen_recurse() {{{2 */
+/*
+ * Write commands to "fd" to open and close manually opened/closed folds.
+ * Returns FAIL when writing failed.
+ */
+ static int
+put_foldopen_recurse(fd, gap, off)
+ FILE *fd;
+ garray_T *gap;
+ linenr_T off;
+{
+ int i;
+ fold_T *fp;
+
+ fp = (fold_T *)gap->ga_data;
+ for (i = 0; i < gap->ga_len; i++)
+ {
+ if (fp->fd_flags != FD_LEVEL)
+ {
+ if (fp->fd_nested.ga_len > 0)
+ {
+ /* open/close nested folds while this fold is open */
+ if (fprintf(fd, "%ld", fp->fd_top + off) < 0
+ || put_eol(fd) == FAIL
+ || put_line(fd, "normal zo") == FAIL)
+ return FAIL;
+ if (put_foldopen_recurse(fd, &fp->fd_nested, off + fp->fd_top)
+ == FAIL)
+ return FAIL;
+ }
+ if (fprintf(fd, "%ld", fp->fd_top + off) < 0
+ || put_eol(fd) == FAIL
+ || fprintf(fd, "normal z%c",
+ fp->fd_flags == FD_CLOSED ? 'c' : 'o') < 0
+ || put_eol(fd) == FAIL)
+ return FAIL;
+ }
+ ++fp;
+ }
+
+ return OK;
+}
+#endif /* FEAT_SESSION */
+
+/* }}}1 */
+#endif /* defined(FEAT_FOLDING) || defined(PROTO) */
diff --git a/src/getchar.c b/src/getchar.c
new file mode 100644
index 000000000..3a8438357
--- /dev/null
+++ b/src/getchar.c
@@ -0,0 +1,4636 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * getchar.c
+ *
+ * functions related with getting a character from the user/mapping/redo/...
+ *
+ * manipulations with redo buffer and stuff buffer
+ * mappings and abbreviations
+ */
+
+#include "vim.h"
+
+/*
+ * These buffers are used for storing:
+ * - stuffed characters: A command that is translated into another command.
+ * - redo characters: will redo the last change.
+ * - recorded chracters: for the "q" command.
+ *
+ * The bytes are stored like in the typeahead buffer:
+ * - K_SPECIAL introduces a special key (two more bytes follow). A literal
+ * K_SPECIAL is stored as K_SPECIAL KS_SPECIAL KE_FILLER.
+ * - CSI introduces a GUI termcap code (also when gui.in_use is FALSE,
+ * otherwise switching the GUI on would make mappings invalid).
+ * A literal CSI is stored as CSI KS_EXTRA KE_CSI.
+ * These translations are also done on multi-byte characters!
+ *
+ * Escaping CSI bytes is done by the system-specific input functions, called
+ * by ui_inchar().
+ * Escaping K_SPECIAL is done by inchar().
+ * Un-escaping is done by vgetc().
+ */
+
+#define MINIMAL_SIZE 20 /* minimal size for b_str */
+
+static struct buffheader redobuff = {{NULL, {NUL}}, NULL, 0, 0};
+static struct buffheader old_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
+#if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO)
+static struct buffheader save_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
+static struct buffheader save_old_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
+#endif
+static struct buffheader recordbuff = {{NULL, {NUL}}, NULL, 0, 0};
+
+static int typeahead_char = 0; /* typeahead char that's not flushed */
+
+/*
+ * when block_redo is TRUE redo buffer will not be changed
+ * used by edit() to repeat insertions and 'V' command for redoing
+ */
+static int block_redo = FALSE;
+
+/*
+ * Make a hash value for a mapping.
+ * "mode" is the lower 4 bits of the State for the mapping.
+ * "c1" is the first character of the "lhs".
+ * Returns a value between 0 and 255, index in maphash.
+ * Put Normal/Visual mode mappings mostly separately from Insert/Cmdline mode.
+ */
+#define MAP_HASH(mode, c1) (((mode) & (NORMAL + VISUAL + OP_PENDING)) ? (c1) : ((c1) ^ 0x80))
+
+/*
+ * Each mapping is put in one of the 256 hash lists, to speed up finding it.
+ */
+static mapblock_T *(maphash[256]);
+static int maphash_valid = FALSE;
+
+/*
+ * List used for abbreviations.
+ */
+static mapblock_T *first_abbr = NULL; /* first entry in abbrlist */
+
+static int KeyNoremap = FALSE; /* remapping disabled */
+
+/*
+ * variables used by vgetorpeek() and flush_buffers()
+ *
+ * typebuf.tb_buf[] contains all characters that are not consumed yet.
+ * typebuf.tb_buf[typebuf.tb_off] is the first valid character.
+ * typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len - 1] is the last valid char.
+ * typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len] must be NUL.
+ * The head of the buffer may contain the result of mappings, abbreviations
+ * and @a commands. The length of this part is typebuf.tb_maplen.
+ * typebuf.tb_silent is the part where <silent> applies.
+ * After the head are characters that come from the terminal.
+ * typebuf.tb_no_abbr_cnt is the number of characters in typebuf.tb_buf that
+ * should not be considered for abbreviations.
+ * Some parts of typebuf.tb_buf may not be mapped. These parts are remembered
+ * in typebuf.tb_noremap[], which is the same length as typebuf.tb_buf and
+ * contains RM_NONE for the characters that are not to be remapped.
+ * typebuf.tb_noremap[typebuf.tb_off] is the first valid flag.
+ * (typebuf has been put in globals.h, because check_termcode() needs it).
+ */
+#define RM_YES 0 /* tb_noremap: remap */
+#define RM_NONE 1 /* tb_noremap: don't remap */
+#define RM_SCRIPT 2 /* tb_noremap: remap local script mappings */
+
+/* typebuf.tb_buf has three parts: room in front (for result of mappings), the
+ * middle for typeahead and room for new characters (which needs to be 3 *
+ * MAXMAPLEN) for the Amiga).
+ */
+#define TYPELEN_INIT (5 * (MAXMAPLEN + 3))
+static char_u typebuf_init[TYPELEN_INIT]; /* initial typebuf.tb_buf */
+static char_u noremapbuf_init[TYPELEN_INIT]; /* initial typebuf.tb_noremap */
+
+static int last_recorded_len = 0; /* number of last recorded chars */
+
+static char_u *get_buffcont __ARGS((struct buffheader *, int));
+static void add_buff __ARGS((struct buffheader *, char_u *, long n));
+static void add_num_buff __ARGS((struct buffheader *, long));
+static void add_char_buff __ARGS((struct buffheader *, int));
+static int read_stuff __ARGS((int advance));
+static void start_stuff __ARGS((void));
+static int read_redo __ARGS((int, int));
+static void copy_redo __ARGS((int));
+static void init_typebuf __ARGS((void));
+static void gotchars __ARGS((char_u *, int));
+static void may_sync_undo __ARGS((void));
+static void closescript __ARGS((void));
+static int vgetorpeek __ARGS((int));
+static void map_free __ARGS((mapblock_T **));
+static void validate_maphash __ARGS((void));
+static void showmap __ARGS((mapblock_T *mp, int local));
+
+/*
+ * Free and clear a buffer.
+ */
+ void
+free_buff(buf)
+ struct buffheader *buf;
+{
+ struct buffblock *p, *np;
+
+ for (p = buf->bh_first.b_next; p != NULL; p = np)
+ {
+ np = p->b_next;
+ vim_free(p);
+ }
+ buf->bh_first.b_next = NULL;
+}
+
+/*
+ * Return the contents of a buffer as a single string.
+ * K_SPECIAL and CSI in the returned string are escaped.
+ */
+ static char_u *
+get_buffcont(buffer, dozero)
+ struct buffheader *buffer;
+ int dozero; /* count == zero is not an error */
+{
+ long_u count = 0;
+ char_u *p = NULL;
+ char_u *p2;
+ char_u *str;
+ struct buffblock *bp;
+
+ /* compute the total length of the string */
+ for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
+ count += (long_u)STRLEN(bp->b_str);
+
+ if ((count || dozero) && (p = lalloc(count + 1, TRUE)) != NULL)
+ {
+ p2 = p;
+ for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
+ for (str = bp->b_str; *str; )
+ *p2++ = *str++;
+ *p2 = NUL;
+ }
+ return (p);
+}
+
+/*
+ * Return the contents of the record buffer as a single string
+ * and clear the record buffer.
+ * K_SPECIAL and CSI in the returned string are escaped.
+ */
+ char_u *
+get_recorded()
+{
+ char_u *p;
+ size_t len;
+
+ p = get_buffcont(&recordbuff, TRUE);
+ free_buff(&recordbuff);
+
+ /*
+ * Remove the characters that were added the last time, these must be the
+ * (possibly mapped) characters that stopped the recording.
+ */
+ len = STRLEN(p);
+ if ((int)len >= last_recorded_len)
+ {
+ len -= last_recorded_len;
+ p[len] = NUL;
+ }
+
+ /*
+ * When stopping recording from Insert mode with CTRL-O q, also remove the
+ * CTRL-O.
+ */
+ if (len > 0 && restart_edit != 0 && p[len - 1] == Ctrl_O)
+ p[len - 1] = NUL;
+
+ return (p);
+}
+
+/*
+ * Return the contents of the redo buffer as a single string.
+ * K_SPECIAL and CSI in the returned string are escaped.
+ */
+ char_u *
+get_inserted()
+{
+ return(get_buffcont(&redobuff, FALSE));
+}
+
+/*
+ * add string "s" after the current block of buffer "buf"
+ * K_SPECIAL and CSI should have been escaped already.
+ */
+ static void
+add_buff(buf, s, slen)
+ struct buffheader *buf;
+ char_u *s;
+ long slen; /* length of "s" or -1 */
+{
+ struct buffblock *p;
+ long_u len;
+
+ if (slen < 0)
+ slen = (long)STRLEN(s);
+ if (slen == 0) /* don't add empty strings */
+ return;
+
+ if (buf->bh_first.b_next == NULL) /* first add to list */
+ {
+ buf->bh_space = 0;
+ buf->bh_curr = &(buf->bh_first);
+ }
+ else if (buf->bh_curr == NULL) /* buffer has already been read */
+ {
+ EMSG(_("E222: Add to read buffer"));
+ return;
+ }
+ else if (buf->bh_index != 0)
+ STRCPY(buf->bh_first.b_next->b_str,
+ buf->bh_first.b_next->b_str + buf->bh_index);
+ buf->bh_index = 0;
+
+ if (buf->bh_space >= (int)slen)
+ {
+ len = (long_u)STRLEN(buf->bh_curr->b_str);
+ STRNCPY(buf->bh_curr->b_str + len, s, slen);
+ buf->bh_curr->b_str[len + slen] = NUL;
+ buf->bh_space -= slen;
+ }
+ else
+ {
+ if (slen < MINIMAL_SIZE)
+ len = MINIMAL_SIZE;
+ else
+ len = slen;
+ p = (struct buffblock *)lalloc((long_u)(sizeof(struct buffblock) + len),
+ TRUE);
+ if (p == NULL)
+ return; /* no space, just forget it */
+ buf->bh_space = len - slen;
+ STRNCPY(p->b_str, s, slen);
+ p->b_str[slen] = NUL;
+
+ p->b_next = buf->bh_curr->b_next;
+ buf->bh_curr->b_next = p;
+ buf->bh_curr = p;
+ }
+ return;
+}
+
+/*
+ * Add number "n" to buffer "buf".
+ */
+ static void
+add_num_buff(buf, n)
+ struct buffheader *buf;
+ long n;
+{
+ char_u number[32];
+
+ sprintf((char *)number, "%ld", n);
+ add_buff(buf, number, -1L);
+}
+
+/*
+ * Add character 'c' to buffer "buf".
+ * Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters.
+ */
+ static void
+add_char_buff(buf, c)
+ struct buffheader *buf;
+ int c;
+{
+#ifdef FEAT_MBYTE
+ char_u bytes[MB_MAXBYTES + 1];
+ int len;
+ int i;
+#endif
+ char_u temp[4];
+
+#ifdef FEAT_MBYTE
+ if (IS_SPECIAL(c))
+ len = 1;
+ else
+ len = (*mb_char2bytes)(c, bytes);
+ for (i = 0; i < len; ++i)
+ {
+ if (!IS_SPECIAL(c))
+ c = bytes[i];
+#endif
+
+ if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL)
+ {
+ /* translate special key code into three byte sequence */
+ temp[0] = K_SPECIAL;
+ temp[1] = K_SECOND(c);
+ temp[2] = K_THIRD(c);
+ temp[3] = NUL;
+ }
+#ifdef FEAT_GUI
+ else if (c == CSI)
+ {
+ /* Translate a CSI to a CSI - KS_EXTRA - KE_CSI sequence */
+ temp[0] = CSI;
+ temp[1] = KS_EXTRA;
+ temp[2] = (int)KE_CSI;
+ temp[3] = NUL;
+ }
+#endif
+ else
+ {
+ temp[0] = c;
+ temp[1] = NUL;
+ }
+ add_buff(buf, temp, -1L);
+#ifdef FEAT_MBYTE
+ }
+#endif
+}
+
+/*
+ * Get one byte from the stuff buffer.
+ * If advance == TRUE go to the next char.
+ * No translation is done K_SPECIAL and CSI are escaped.
+ */
+ static int
+read_stuff(advance)
+ int advance;
+{
+ char_u c;
+ struct buffblock *curr;
+
+ if (stuffbuff.bh_first.b_next == NULL) /* buffer is empty */
+ return NUL;
+
+ curr = stuffbuff.bh_first.b_next;
+ c = curr->b_str[stuffbuff.bh_index];
+
+ if (advance)
+ {
+ if (curr->b_str[++stuffbuff.bh_index] == NUL)
+ {
+ stuffbuff.bh_first.b_next = curr->b_next;
+ vim_free(curr);
+ stuffbuff.bh_index = 0;
+ }
+ }
+ return c;
+}
+
+/*
+ * Prepare the stuff buffer for reading (if it contains something).
+ */
+ static void
+start_stuff()
+{
+ if (stuffbuff.bh_first.b_next != NULL)
+ {
+ stuffbuff.bh_curr = &(stuffbuff.bh_first);
+ stuffbuff.bh_space = 0;
+ }
+}
+
+/*
+ * Return TRUE if the stuff buffer is empty.
+ */
+ int
+stuff_empty()
+{
+ return (stuffbuff.bh_first.b_next == NULL);
+}
+
+/*
+ * Set a typeahead character that won't be flushed.
+ */
+ void
+typeahead_noflush(c)
+ int c;
+{
+ typeahead_char = c;
+}
+
+/*
+ * Remove the contents of the stuff buffer and the mapped characters in the
+ * typeahead buffer (used in case of an error). If 'typeahead' is true,
+ * flush all typeahead characters (used when interrupted by a CTRL-C).
+ */
+ void
+flush_buffers(typeahead)
+ int typeahead;
+{
+ init_typebuf();
+
+ start_stuff();
+ while (read_stuff(TRUE) != NUL)
+ ;
+
+ if (typeahead) /* remove all typeahead */
+ {
+ /*
+ * We have to get all characters, because we may delete the first part
+ * of an escape sequence.
+ * In an xterm we get one char at a time and we have to get them all.
+ */
+ while (inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 10L,
+ typebuf.tb_change_cnt) != 0)
+ ;
+ typebuf.tb_off = MAXMAPLEN;
+ typebuf.tb_len = 0;
+ }
+ else /* remove mapped characters only */
+ {
+ typebuf.tb_off += typebuf.tb_maplen;
+ typebuf.tb_len -= typebuf.tb_maplen;
+ }
+ typebuf.tb_maplen = 0;
+ typebuf.tb_silent = 0;
+ cmd_silent = FALSE;
+ typebuf.tb_no_abbr_cnt = 0;
+}
+
+/*
+ * The previous contents of the redo buffer is kept in old_redobuffer.
+ * This is used for the CTRL-O <.> command in insert mode.
+ */
+ void
+ResetRedobuff()
+{
+ if (!block_redo)
+ {
+ free_buff(&old_redobuff);
+ old_redobuff = redobuff;
+ redobuff.bh_first.b_next = NULL;
+ }
+}
+
+#if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Save redobuff and old_redobuff to save_redobuff and save_old_redobuff.
+ * Used before executing autocommands and user functions.
+ */
+static int save_level = 0;
+
+ void
+saveRedobuff()
+{
+ char_u *s;
+
+ if (save_level++ == 0)
+ {
+ save_redobuff = redobuff;
+ redobuff.bh_first.b_next = NULL;
+ save_old_redobuff = old_redobuff;
+ old_redobuff.bh_first.b_next = NULL;
+
+ /* Make a copy, so that ":normal ." in a function works. */
+ s = get_buffcont(&save_redobuff, FALSE);
+ if (s != NULL)
+ {
+ add_buff(&redobuff, s, -1L);
+ vim_free(s);
+ }
+ }
+}
+
+/*
+ * Restore redobuff and old_redobuff from save_redobuff and save_old_redobuff.
+ * Used after executing autocommands and user functions.
+ */
+ void
+restoreRedobuff()
+{
+ if (--save_level == 0)
+ {
+ free_buff(&redobuff);
+ redobuff = save_redobuff;
+ free_buff(&old_redobuff);
+ old_redobuff = save_old_redobuff;
+ }
+}
+#endif
+
+/*
+ * Append "s" to the redo buffer.
+ * K_SPECIAL and CSI should already have been escaped.
+ */
+ void
+AppendToRedobuff(s)
+ char_u *s;
+{
+ if (!block_redo)
+ add_buff(&redobuff, s, -1L);
+}
+
+/*
+ * Append to Redo buffer literally, escaping special characters with CTRL-V.
+ * K_SPECIAL and CSI are escaped as well.
+ */
+ void
+AppendToRedobuffLit(s)
+ char_u *s;
+{
+ int c;
+ char_u *start;
+
+ if (block_redo)
+ return;
+
+ while (*s != NUL)
+ {
+ /* Put a string of normal characters in the redo buffer (that's
+ * faster). */
+ start = s;
+ while (*s >= ' '
+#ifndef EBCDIC
+ && *s < DEL /* EBCDIC: all chars above space are normal */
+#endif
+ )
+ ++s;
+
+ /* Don't put '0' or '^' as last character, just in case a CTRL-D is
+ * typed next. */
+ if (*s == NUL && (s[-1] == '0' || s[-1] == '^'))
+ --s;
+ if (s > start)
+ add_buff(&redobuff, start, (long)(s - start));
+
+ if (*s != NUL)
+ {
+ /* Handle a special or multibyte character. */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ c = (*mb_ptr2char)(s);
+ if (enc_utf8)
+ /* Handle composing chars as well. */
+ s += utf_ptr2len_check(s);
+ else
+ s += (*mb_ptr2len_check)(s);
+ }
+ else
+#endif
+ c = *s++;
+ if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^')))
+ add_char_buff(&redobuff, Ctrl_V);
+
+ /* CTRL-V '0' must be inserted as CTRL-V 048 (EBCDIC: xf0) */
+ if (*s == NUL && c == '0')
+#ifdef EBCDIC
+ add_buff(&redobuff, (char_u *)"xf0", 3L);
+#else
+ add_buff(&redobuff, (char_u *)"048", 3L);
+#endif
+ else
+ add_char_buff(&redobuff, c);
+ }
+ }
+}
+
+/*
+ * Append a character to the redo buffer.
+ * Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters.
+ */
+ void
+AppendCharToRedobuff(c)
+ int c;
+{
+ if (!block_redo)
+ add_char_buff(&redobuff, c);
+}
+
+/*
+ * Append a number to the redo buffer.
+ */
+ void
+AppendNumberToRedobuff(n)
+ long n;
+{
+ if (!block_redo)
+ add_num_buff(&redobuff, n);
+}
+
+/*
+ * Append string "s" to the stuff buffer.
+ * CSI and K_SPECIAL must already have been escaped.
+ */
+ void
+stuffReadbuff(s)
+ char_u *s;
+{
+ add_buff(&stuffbuff, s, -1L);
+}
+
+ void
+stuffReadbuffLen(s, len)
+ char_u *s;
+ long len;
+{
+ add_buff(&stuffbuff, s, len);
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Stuff "s" into the stuff buffer, leaving special key codes unmodified and
+ * escaping other K_SPECIAL and CSI bytes.
+ */
+ void
+stuffReadbuffSpec(s)
+ char_u *s;
+{
+ while (*s != NUL)
+ {
+ if (*s == K_SPECIAL && s[1] != NUL && s[2] != NUL)
+ {
+ /* Insert special key literally. */
+ stuffReadbuffLen(s, 3L);
+ s += 3;
+ }
+ else
+#ifdef FEAT_MBYTE
+ stuffcharReadbuff(mb_ptr2char_adv(&s));
+#else
+ stuffcharReadbuff(*s++);
+#endif
+ }
+}
+#endif
+
+/*
+ * Append a character to the stuff buffer.
+ * Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters.
+ */
+ void
+stuffcharReadbuff(c)
+ int c;
+{
+ add_char_buff(&stuffbuff, c);
+}
+
+/*
+ * Append a number to the stuff buffer.
+ */
+ void
+stuffnumReadbuff(n)
+ long n;
+{
+ add_num_buff(&stuffbuff, n);
+}
+
+/*
+ * Read a character from the redo buffer. Translates K_SPECIAL, CSI and
+ * multibyte characters.
+ * The redo buffer is left as it is.
+ * if init is TRUE, prepare for redo, return FAIL if nothing to redo, OK
+ * otherwise
+ * if old is TRUE, use old_redobuff instead of redobuff
+ */
+ static int
+read_redo(init, old_redo)
+ int init;
+ int old_redo;
+{
+ static struct buffblock *bp;
+ static char_u *p;
+ int c;
+#ifdef FEAT_MBYTE
+ int n;
+ char_u buf[MB_MAXBYTES];
+ int i;
+#endif
+
+ if (init)
+ {
+ if (old_redo)
+ bp = old_redobuff.bh_first.b_next;
+ else
+ bp = redobuff.bh_first.b_next;
+ if (bp == NULL)
+ return FAIL;
+ p = bp->b_str;
+ return OK;
+ }
+ if ((c = *p) != NUL)
+ {
+ /* Reverse the conversion done by add_char_buff() */
+#ifdef FEAT_MBYTE
+ /* For a multi-byte character get all the bytes and return the
+ * converted character. */
+ if (has_mbyte && (c != K_SPECIAL || p[1] == KS_SPECIAL))
+ n = MB_BYTE2LEN_CHECK(c);
+ else
+ n = 1;
+ for (i = 0; ; ++i)
+#endif
+ {
+ if (c == K_SPECIAL) /* special key or escaped K_SPECIAL */
+ {
+ c = TO_SPECIAL(p[1], p[2]);
+ p += 2;
+ }
+#ifdef FEAT_GUI
+ if (c == CSI) /* escaped CSI */
+ p += 2;
+#endif
+ if (*++p == NUL && bp->b_next != NULL)
+ {
+ bp = bp->b_next;
+ p = bp->b_str;
+ }
+#ifdef FEAT_MBYTE
+ buf[i] = c;
+ if (i == n - 1) /* last byte of a character */
+ {
+ if (n != 1)
+ c = (*mb_ptr2char)(buf);
+ break;
+ }
+ c = *p;
+ if (c == NUL) /* cannot happen? */
+ break;
+#endif
+ }
+ }
+
+ return c;
+}
+
+/*
+ * Copy the rest of the redo buffer into the stuff buffer (in a slow way).
+ * If old_redo is TRUE, use old_redobuff instead of redobuff.
+ * The escaped K_SPECIAL and CSI are copied without translation.
+ */
+ static void
+copy_redo(old_redo)
+ int old_redo;
+{
+ int c;
+
+ while ((c = read_redo(FALSE, old_redo)) != NUL)
+ stuffcharReadbuff(c);
+}
+
+/*
+ * Stuff the redo buffer into the stuffbuff.
+ * Insert the redo count into the command.
+ * If "old_redo" is TRUE, the last but one command is repeated
+ * instead of the last command (inserting text). This is used for
+ * CTRL-O <.> in insert mode
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+start_redo(count, old_redo)
+ long count;
+ int old_redo;
+{
+ int c;
+
+ /* init the pointers; return if nothing to redo */
+ if (read_redo(TRUE, old_redo) == FAIL)
+ return FAIL;
+
+ c = read_redo(FALSE, old_redo);
+
+ /* copy the buffer name, if present */
+ if (c == '"')
+ {
+ add_buff(&stuffbuff, (char_u *)"\"", 1L);
+ c = read_redo(FALSE, old_redo);
+
+ /* if a numbered buffer is used, increment the number */
+ if (c >= '1' && c < '9')
+ ++c;
+ add_char_buff(&stuffbuff, c);
+ c = read_redo(FALSE, old_redo);
+ }
+
+#ifdef FEAT_VISUAL
+ if (c == 'v') /* redo Visual */
+ {
+ VIsual = curwin->w_cursor;
+ VIsual_active = TRUE;
+ VIsual_select = FALSE;
+ VIsual_reselect = TRUE;
+ redo_VIsual_busy = TRUE;
+ c = read_redo(FALSE, old_redo);
+ }
+#endif
+
+ /* try to enter the count (in place of a previous count) */
+ if (count)
+ {
+ while (VIM_ISDIGIT(c)) /* skip "old" count */
+ c = read_redo(FALSE, old_redo);
+ add_num_buff(&stuffbuff, count);
+ }
+
+ /* copy from the redo buffer into the stuff buffer */
+ add_char_buff(&stuffbuff, c);
+ copy_redo(old_redo);
+ return OK;
+}
+
+/*
+ * Repeat the last insert (R, o, O, a, A, i or I command) by stuffing
+ * the redo buffer into the stuffbuff.
+ * return FAIL for failure, OK otherwise
+ */
+ int
+start_redo_ins()
+{
+ int c;
+
+ if (read_redo(TRUE, FALSE) == FAIL)
+ return FAIL;
+ start_stuff();
+
+ /* skip the count and the command character */
+ while ((c = read_redo(FALSE, FALSE)) != NUL)
+ {
+ if (vim_strchr((char_u *)"AaIiRrOo", c) != NULL)
+ {
+ if (c == 'O' || c == 'o')
+ stuffReadbuff(NL_STR);
+ break;
+ }
+ }
+
+ /* copy the typed text from the redo buffer into the stuff buffer */
+ copy_redo(FALSE);
+ block_redo = TRUE;
+ return OK;
+}
+
+ void
+stop_redo_ins()
+{
+ block_redo = FALSE;
+}
+
+/*
+ * Initialize typebuf.tb_buf to point to typebuf_init.
+ * alloc() cannot be used here: In out-of-memory situations it would
+ * be impossible to type anything.
+ */
+ static void
+init_typebuf()
+{
+ if (typebuf.tb_buf == NULL)
+ {
+ typebuf.tb_buf = typebuf_init;
+ typebuf.tb_noremap = noremapbuf_init;
+ typebuf.tb_buflen = TYPELEN_INIT;
+ typebuf.tb_len = 0;
+ typebuf.tb_off = 0;
+ typebuf.tb_change_cnt = 1;
+ }
+}
+
+/*
+ * insert a string in position 'offset' in the typeahead buffer (for "@r"
+ * and ":normal" command, vgetorpeek() and check_termcode())
+ *
+ * If noremap is REMAP_YES, new string can be mapped again.
+ * If noremap is REMAP_NONE, new string cannot be mapped again.
+ * If noremap is REMAP_SCRIPT, new string cannot be mapped again, except for
+ * script-local mappings.
+ * If noremap is > 0, that many characters of the new string cannot be mapped.
+ *
+ * If nottyped is TRUE, the string does not return KeyTyped (don't use when
+ * offset is non-zero!).
+ *
+ * If silent is TRUE, cmd_silent is set when the characters are obtained.
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+ins_typebuf(str, noremap, offset, nottyped, silent)
+ char_u *str;
+ int noremap;
+ int offset;
+ int nottyped;
+ int silent;
+{
+ char_u *s1, *s2;
+ int newlen;
+ int addlen;
+ int i;
+ int newoff;
+ int val;
+ int nrm;
+
+ init_typebuf();
+ if (++typebuf.tb_change_cnt == 0)
+ typebuf.tb_change_cnt = 1;
+
+ addlen = (int)STRLEN(str);
+ /*
+ * Easy case: there is room in front of typebuf.tb_buf[typebuf.tb_off]
+ */
+ if (offset == 0 && addlen <= typebuf.tb_off)
+ {
+ typebuf.tb_off -= addlen;
+ mch_memmove(typebuf.tb_buf + typebuf.tb_off, str, (size_t)addlen);
+ }
+ /*
+ * Need to allocate new buffer.
+ * In typebuf.tb_buf there must always be room for 3 * MAXMAPLEN + 4
+ * characters. We add some extra room to avoid having to allocate too
+ * often.
+ */
+ else
+ {
+ newoff = MAXMAPLEN + 4;
+ newlen = typebuf.tb_len + addlen + newoff + 4 * (MAXMAPLEN + 4);
+ if (newlen < 0) /* string is getting too long */
+ {
+ EMSG(_(e_toocompl)); /* also calls flush_buffers */
+ setcursor();
+ return FAIL;
+ }
+ s1 = alloc(newlen);
+ if (s1 == NULL) /* out of memory */
+ return FAIL;
+ s2 = alloc(newlen);
+ if (s2 == NULL) /* out of memory */
+ {
+ vim_free(s1);
+ return FAIL;
+ }
+ typebuf.tb_buflen = newlen;
+
+ /* copy the old chars, before the insertion point */
+ mch_memmove(s1 + newoff, typebuf.tb_buf + typebuf.tb_off,
+ (size_t)offset);
+ /* copy the new chars */
+ mch_memmove(s1 + newoff + offset, str, (size_t)addlen);
+ /* copy the old chars, after the insertion point, including the NUL at
+ * the end */
+ mch_memmove(s1 + newoff + offset + addlen,
+ typebuf.tb_buf + typebuf.tb_off + offset,
+ (size_t)(typebuf.tb_len - offset + 1));
+ if (typebuf.tb_buf != typebuf_init)
+ vim_free(typebuf.tb_buf);
+ typebuf.tb_buf = s1;
+
+ mch_memmove(s2 + newoff, typebuf.tb_noremap + typebuf.tb_off,
+ (size_t)offset);
+ mch_memmove(s2 + newoff + offset + addlen,
+ typebuf.tb_noremap + typebuf.tb_off + offset,
+ (size_t)(typebuf.tb_len - offset));
+ if (typebuf.tb_noremap != noremapbuf_init)
+ vim_free(typebuf.tb_noremap);
+ typebuf.tb_noremap = s2;
+
+ typebuf.tb_off = newoff;
+ }
+ typebuf.tb_len += addlen;
+
+ /* If noremap == REMAP_SCRIPT: do remap script-local mappings. */
+ if (noremap == REMAP_SCRIPT)
+ val = RM_SCRIPT;
+ else
+ val = RM_NONE;
+
+ /*
+ * Adjust typebuf.tb_noremap[] for the new characters:
+ * If noremap == REMAP_NONE or REMAP_SCRIPT: new characters are
+ * (sometimes) not remappable
+ * If noremap == REMAP_YES: all the new characters are mappable
+ * If noremap > 0: "noremap" characters are not remappable, the rest
+ * mappable
+ */
+ if (noremap < 0)
+ nrm = addlen;
+ else
+ nrm = noremap;
+ for (i = 0; i < addlen; ++i)
+ typebuf.tb_noremap[typebuf.tb_off + i + offset] =
+ (--nrm >= 0) ? val : RM_YES;
+
+ /* tb_maplen and tb_silent only remember the length of mapped and/or
+ * silent mappings at the start of the buffer, assuming that a mapped
+ * sequence doesn't result in typed characters. */
+ if (nottyped || typebuf.tb_maplen > offset)
+ typebuf.tb_maplen += addlen;
+ if (silent || typebuf.tb_silent > offset)
+ {
+ typebuf.tb_silent += addlen;
+ cmd_silent = TRUE;
+ }
+ if (typebuf.tb_no_abbr_cnt && offset == 0) /* and not used for abbrev.s */
+ typebuf.tb_no_abbr_cnt += addlen;
+
+ return OK;
+}
+
+/*
+ * Return TRUE if the typeahead buffer was changed (while waiting for a
+ * character to arrive). Happens when a message was received from a client.
+ * But check in a more generic way to avoid trouble: When "typebuf.tb_buf"
+ * changed it was reallocated and the old pointer can no longer be used.
+ * Or "typebuf.tb_off" may have been changed and we would overwrite characters
+ * that was just added.
+ */
+ int
+typebuf_changed(tb_change_cnt)
+ int tb_change_cnt; /* old value of typebuf.tb_change_cnt */
+{
+ return (tb_change_cnt != 0 && (typebuf.tb_change_cnt != tb_change_cnt
+#ifdef FEAT_CLIENTSERVER
+ || received_from_client
+#endif
+ ));
+}
+
+/*
+ * Return TRUE if there are no characters in the typeahead buffer that have
+ * not been typed (result from a mapping or come from ":normal").
+ */
+ int
+typebuf_typed()
+{
+ return typebuf.tb_maplen == 0;
+}
+
+/*
+ * Return the number of characters that are mapped (or not typed).
+ */
+ int
+typebuf_maplen()
+{
+ return typebuf.tb_maplen;
+}
+
+/*
+ * remove "len" characters from typebuf.tb_buf[typebuf.tb_off + offset]
+ */
+ void
+del_typebuf(len, offset)
+ int len;
+ int offset;
+{
+ int i;
+
+ if (len == 0)
+ return; /* nothing to do */
+
+ typebuf.tb_len -= len;
+
+ /*
+ * Easy case: Just increase typebuf.tb_off.
+ */
+ if (offset == 0 && typebuf.tb_buflen - (typebuf.tb_off + len)
+ >= 3 * MAXMAPLEN + 3)
+ typebuf.tb_off += len;
+ /*
+ * Have to move the characters in typebuf.tb_buf[] and typebuf.tb_noremap[]
+ */
+ else
+ {
+ i = typebuf.tb_off + offset;
+ /*
+ * Leave some extra room at the end to avoid reallocation.
+ */
+ if (typebuf.tb_off > MAXMAPLEN)
+ {
+ mch_memmove(typebuf.tb_buf + MAXMAPLEN,
+ typebuf.tb_buf + typebuf.tb_off, (size_t)offset);
+ mch_memmove(typebuf.tb_noremap + MAXMAPLEN,
+ typebuf.tb_noremap + typebuf.tb_off, (size_t)offset);
+ typebuf.tb_off = MAXMAPLEN;
+ }
+ /* adjust typebuf.tb_buf (include the NUL at the end) */
+ mch_memmove(typebuf.tb_buf + typebuf.tb_off + offset,
+ typebuf.tb_buf + i + len,
+ (size_t)(typebuf.tb_len - offset + 1));
+ /* adjust typebuf.tb_noremap[] */
+ mch_memmove(typebuf.tb_noremap + typebuf.tb_off + offset,
+ typebuf.tb_noremap + i + len,
+ (size_t)(typebuf.tb_len - offset));
+ }
+
+ if (typebuf.tb_maplen > offset) /* adjust tb_maplen */
+ {
+ if (typebuf.tb_maplen < offset + len)
+ typebuf.tb_maplen = offset;
+ else
+ typebuf.tb_maplen -= len;
+ }
+ if (typebuf.tb_silent > offset) /* adjust tb_silent */
+ {
+ if (typebuf.tb_silent < offset + len)
+ typebuf.tb_silent = offset;
+ else
+ typebuf.tb_silent -= len;
+ }
+ if (typebuf.tb_no_abbr_cnt > offset) /* adjust tb_no_abbr_cnt */
+ {
+ if (typebuf.tb_no_abbr_cnt < offset + len)
+ typebuf.tb_no_abbr_cnt = offset;
+ else
+ typebuf.tb_no_abbr_cnt -= len;
+ }
+
+#ifdef FEAT_CLIENTSERVER
+ /* Reset the flag that text received from a client was inserted in the
+ * typeahead buffer. */
+ received_from_client = FALSE;
+#endif
+ if (++typebuf.tb_change_cnt == 0)
+ typebuf.tb_change_cnt = 1;
+}
+
+/*
+ * Write typed characters to script file.
+ * If recording is on put the character in the recordbuffer.
+ */
+ static void
+gotchars(s, len)
+ char_u *s;
+ int len;
+{
+ int c;
+ char_u buf[2];
+
+ /* remember how many chars were last recorded */
+ if (Recording)
+ last_recorded_len += len;
+
+ buf[1] = NUL;
+ while (len--)
+ {
+ /* Handle one byte at a time; no translation to be done. */
+ c = *s++;
+ updatescript(c);
+
+ if (Recording)
+ {
+ buf[0] = c;
+ add_buff(&recordbuff, buf, 1L);
+ }
+ }
+ may_sync_undo();
+
+#ifdef FEAT_EVAL
+ /* output "debug mode" message next time in debug mode */
+ debug_did_msg = FALSE;
+#endif
+
+ /* Since characters have been typed, consider the following to be in
+ * another mapping. Search string will be kept in history. */
+ ++maptick;
+}
+
+/*
+ * Sync undo. Called when typed characters are obtained from the typeahead
+ * buffer, or when a menu is used.
+ * Do not sync:
+ * - In Insert mode, unless cursor key has been used.
+ * - While reading a script file.
+ * - When no_u_sync is non-zero.
+ */
+ static void
+may_sync_undo()
+{
+ if ((!(State & (INSERT + CMDLINE)) || arrow_used)
+ && scriptin[curscript] == NULL && no_u_sync == 0)
+ u_sync();
+}
+
+/*
+ * Make "typebuf" empty and allocate new buffers.
+ * Returns FAIL when out of memory.
+ */
+ int
+alloc_typebuf()
+{
+ typebuf.tb_buf = alloc(TYPELEN_INIT);
+ typebuf.tb_noremap = alloc(TYPELEN_INIT);
+ if (typebuf.tb_buf == NULL || typebuf.tb_noremap == NULL)
+ {
+ free_typebuf();
+ return FAIL;
+ }
+ typebuf.tb_buflen = TYPELEN_INIT;
+ typebuf.tb_off = 0;
+ typebuf.tb_len = 0;
+ typebuf.tb_maplen = 0;
+ typebuf.tb_silent = 0;
+ typebuf.tb_no_abbr_cnt = 0;
+ if (++typebuf.tb_change_cnt == 0)
+ typebuf.tb_change_cnt = 1;
+ return OK;
+}
+
+/*
+ * Free the buffers of "typebuf".
+ */
+ void
+free_typebuf()
+{
+ vim_free(typebuf.tb_buf);
+ vim_free(typebuf.tb_noremap);
+}
+
+/*
+ * When doing ":so! file", the current typeahead needs to be saved, and
+ * restored when "file" has been read completely.
+ */
+static typebuf_T saved_typebuf[NSCRIPT];
+
+ int
+save_typebuf()
+{
+ init_typebuf();
+ saved_typebuf[curscript] = typebuf;
+ /* If out of memory: restore typebuf and close file. */
+ if (alloc_typebuf() == FAIL)
+ {
+ closescript();
+ return FAIL;
+ }
+ return OK;
+}
+
+#if defined(FEAT_EVAL) || defined(FEAT_EX_EXTRA) || defined(PROTO)
+
+/*
+ * Save all three kinds of typeahead, so that the user must type at a prompt.
+ */
+ void
+save_typeahead(tp)
+ tasave_T *tp;
+{
+ tp->save_typebuf = typebuf;
+ tp->typebuf_valid = (alloc_typebuf() == OK);
+ if (!tp->typebuf_valid)
+ typebuf = tp->save_typebuf;
+
+ tp->save_stuffbuff = stuffbuff;
+ stuffbuff.bh_first.b_next = NULL;
+# ifdef USE_INPUT_BUF
+ tp->save_inputbuf = get_input_buf();
+# endif
+}
+
+/*
+ * Restore the typeahead to what it was before calling save_typeahead().
+ * The allocated memory is freed, can only be called once!
+ */
+ void
+restore_typeahead(tp)
+ tasave_T *tp;
+{
+ if (tp->typebuf_valid)
+ {
+ free_typebuf();
+ typebuf = tp->save_typebuf;
+ }
+
+ free_buff(&stuffbuff);
+ stuffbuff = tp->save_stuffbuff;
+# ifdef USE_INPUT_BUF
+ set_input_buf(tp->save_inputbuf);
+# endif
+}
+#endif
+
+/*
+ * Open a new script file for the ":source!" command.
+ */
+ void
+openscript(name, directly)
+ char_u *name;
+ int directly; /* when TRUE execute directly */
+{
+ if (curscript + 1 == NSCRIPT)
+ {
+ EMSG(_(e_nesting));
+ return;
+ }
+
+ if (scriptin[curscript] != NULL) /* already reading script */
+ ++curscript;
+ /* use NameBuff for expanded name */
+ expand_env(name, NameBuff, MAXPATHL);
+ if ((scriptin[curscript] = mch_fopen((char *)NameBuff, READBIN)) == NULL)
+ {
+ EMSG2(_(e_notopen), name);
+ if (curscript)
+ --curscript;
+ return;
+ }
+ if (save_typebuf() == FAIL)
+ return;
+
+ /*
+ * Execute the commands from the file right now when using ":source!"
+ * after ":global" or ":argdo" or in a loop. Also when another command
+ * follows. This means the display won't be updated. Don't do this
+ * always, "make test" would fail.
+ */
+ if (directly)
+ {
+ oparg_T oa;
+ int oldcurscript;
+ int save_State = State;
+ int save_restart_edit = restart_edit;
+ int save_insertmode = p_im;
+ int save_finish_op = finish_op;
+ int save_msg_scroll = msg_scroll;
+
+ State = NORMAL;
+ msg_scroll = FALSE; /* no msg scrolling in Normal mode */
+ restart_edit = 0; /* don't go to Insert mode */
+ p_im = FALSE; /* don't use 'insertmode' */
+ clear_oparg(&oa);
+ finish_op = FALSE;
+
+ oldcurscript = curscript;
+ do
+ {
+ update_topline_cursor(); /* update cursor position and topline */
+ normal_cmd(&oa, FALSE); /* execute one command */
+ vpeekc(); /* check for end of file */
+ }
+ while (scriptin[oldcurscript] != NULL);
+
+ State = save_State;
+ msg_scroll = save_msg_scroll;
+ restart_edit = save_restart_edit;
+ p_im = save_insertmode;
+ finish_op = save_finish_op;
+ }
+}
+
+/*
+ * Close the currently active input script.
+ */
+ static void
+closescript()
+{
+ free_typebuf();
+ typebuf = saved_typebuf[curscript];
+
+ fclose(scriptin[curscript]);
+ scriptin[curscript] = NULL;
+ if (curscript > 0)
+ --curscript;
+}
+
+#if defined(FEAT_INS_EXPAND) || defined(PROTO)
+/*
+ * Return TRUE when reading keys from a script file.
+ */
+ int
+using_script()
+{
+ return scriptin[curscript] != NULL;
+}
+#endif
+
+/*
+ * updatescipt() is called when a character can be written into the script file
+ * or when we have waited some time for a character (c == 0)
+ *
+ * All the changed memfiles are synced if c == 0 or when the number of typed
+ * characters reaches 'updatecount' and 'updatecount' is non-zero.
+ */
+ void
+updatescript(c)
+ int c;
+{
+ static int count = 0;
+
+ if (c && scriptout)
+ putc(c, scriptout);
+ if (c == 0 || (p_uc > 0 && ++count >= p_uc))
+ {
+ ml_sync_all(c == 0, TRUE);
+ count = 0;
+ }
+}
+
+#define KL_PART_KEY -1 /* keylen value for incomplete key-code */
+#define KL_PART_MAP -2 /* keylen value for incomplete mapping */
+
+static int old_char = -1; /* character put back by vungetc() */
+static int old_mod_mask; /* mod_mask for ungotten character */
+
+/*
+ * Get the next input character.
+ * Can return a special key or a multi-byte character.
+ * Can return NUL when called recursively, use safe_vgetc() if that's not
+ * wanted.
+ * This translates escaped K_SPECIAL and CSI bytes to a K_SPECIAL or CSI byte.
+ * Collects the bytes of a multibyte character into the whole character.
+ * Returns the modifers in the global "mod_mask".
+ */
+ int
+vgetc()
+{
+ int c, c2;
+#ifdef FEAT_MBYTE
+ int n;
+ char_u buf[MB_MAXBYTES];
+ int i;
+#endif
+
+ /*
+ * If a character was put back with vungetc, it was already processed.
+ * Return it directly.
+ */
+ if (old_char != -1)
+ {
+ c = old_char;
+ old_char = -1;
+ mod_mask = old_mod_mask;
+ return c;
+ }
+
+ mod_mask = 0x0;
+ last_recorded_len = 0;
+ for (;;) /* this is done twice if there are modifiers */
+ {
+ if (mod_mask) /* no mapping after modifier has been read */
+ {
+ ++no_mapping;
+ ++allow_keys;
+ }
+ c = vgetorpeek(TRUE);
+ if (mod_mask)
+ {
+ --no_mapping;
+ --allow_keys;
+ }
+
+ /* Get two extra bytes for special keys */
+ if (c == K_SPECIAL
+#ifdef FEAT_GUI
+ || c == CSI
+#endif
+ )
+ {
+ ++no_mapping;
+ c2 = vgetorpeek(TRUE); /* no mapping for these chars */
+ c = vgetorpeek(TRUE);
+ --no_mapping;
+ if (c2 == KS_MODIFIER)
+ {
+ mod_mask = c;
+ continue;
+ }
+ c = TO_SPECIAL(c2, c);
+
+#if defined(FEAT_GUI_W32) && defined(FEAT_MENU) && defined(FEAT_TEAROFF)
+ /* Handle K_TEAROFF here, the caller of vgetc() doesn't need to
+ * know that a menu was torn off */
+ if (c == K_TEAROFF)
+ {
+ char_u name[200];
+ int i;
+
+ /* get menu path, it ends with a <CR> */
+ for (i = 0; (c = vgetorpeek(TRUE)) != '\r'; )
+ {
+ name[i] = c;
+ if (i < 199)
+ ++i;
+ }
+ name[i] = NUL;
+ gui_make_tearoff(name);
+ continue;
+ }
+#endif
+#ifdef FEAT_GUI
+ /* Translate K_CSI to CSI. The special key is only used to avoid
+ * it being recognized as the start of a special key. */
+ if (c == K_CSI)
+ c = CSI;
+#endif
+ }
+#ifdef MSDOS
+ /*
+ * If K_NUL was typed, it is replaced by K_NUL, 3 in mch_inchar().
+ * Delete the 3 here.
+ */
+ else if (c == K_NUL && vpeekc() == 3)
+ (void)vgetorpeek(TRUE);
+#endif
+
+ if (c >= FIRST_KEYPAD && c <= LAST_KEYPAD)
+ {
+ /* a keypad key was not mapped, use it like its ASCII equivalent */
+ switch (c)
+ {
+ case K_KPLUS: c = '+'; break;
+ case K_KMINUS: c = '-'; break;
+ case K_KDIVIDE: c = '/'; break;
+ case K_KMULTIPLY: c = '*'; break;
+ case K_KENTER: c = CAR; break;
+ case K_KPOINT: c = '.'; break;
+ case K_K0: c = '0'; break;
+ case K_K1: c = '1'; break;
+ case K_K2: c = '2'; break;
+ case K_K3: c = '3'; break;
+ case K_K4: c = '4'; break;
+ case K_K5: c = '5'; break;
+ case K_K6: c = '6'; break;
+ case K_K7: c = '7'; break;
+ case K_K8: c = '8'; break;
+ case K_K9: c = '9'; break;
+ }
+ }
+
+#ifdef FEAT_MBYTE
+ /* For a multi-byte character get all the bytes and return the
+ * converted character.
+ * Note: This will loop until enough bytes are received!
+ */
+ if (has_mbyte && (n = MB_BYTE2LEN_CHECK(c)) > 1)
+ {
+ ++no_mapping;
+ buf[0] = c;
+ for (i = 1; i < n; ++i)
+ {
+ buf[i] = vgetorpeek(TRUE);
+ if (buf[i] == K_SPECIAL
+#ifdef FEAT_GUI
+ || buf[i] == CSI
+#endif
+ )
+ {
+ /* Must be a K_SPECIAL - KS_SPECIAL - KE_FILLER sequence,
+ * which represents a K_SPECIAL (0x80),
+ * or a CSI - KS_EXTRA - KE_CSI sequence, which represents
+ * a CSI (0x9B),
+ * of a K_SPECIAL - KS_EXTRA - KE_CSI, which is CSI too. */
+ c = vgetorpeek(TRUE);
+ if (vgetorpeek(TRUE) == (int)KE_CSI && c == KS_EXTRA)
+ buf[i] = CSI;
+ }
+ }
+ --no_mapping;
+ c = (*mb_ptr2char)(buf);
+ }
+#endif
+
+ return c;
+ }
+}
+
+/*
+ * Like vgetc(), but never return a NUL when called recursively, get a key
+ * directly from the user (ignoring typeahead).
+ */
+ int
+safe_vgetc()
+{
+ int c;
+
+ c = vgetc();
+ if (c == NUL)
+ c = get_keystroke();
+ return c;
+}
+
+/*
+ * Check if a character is available, such that vgetc() will not block.
+ * If the next character is a special character or multi-byte, the returned
+ * character is not valid!.
+ */
+ int
+vpeekc()
+{
+ if (old_char != -1)
+ return old_char;
+ return vgetorpeek(FALSE);
+}
+
+#if defined(FEAT_TERMRESPONSE) || defined(PROTO)
+/*
+ * Like vpeekc(), but don't allow mapping. Do allow checking for terminal
+ * codes.
+ */
+ int
+vpeekc_nomap()
+{
+ int c;
+
+ ++no_mapping;
+ ++allow_keys;
+ c = vpeekc();
+ --no_mapping;
+ --allow_keys;
+ return c;
+}
+#endif
+
+#if defined(FEAT_INS_EXPAND) || defined(PROTO)
+/*
+ * Check if any character is available, also half an escape sequence.
+ * Trick: when no typeahead found, but there is something in the typeahead
+ * buffer, it must be an ESC that is recognized as the start of a key code.
+ */
+ int
+vpeekc_any()
+{
+ int c;
+
+ c = vpeekc();
+ if (c == NUL && typebuf.tb_len > 0)
+ c = ESC;
+ return c;
+}
+#endif
+
+/*
+ * Call vpeekc() without causing anything to be mapped.
+ * Return TRUE if a character is available, FALSE otherwise.
+ */
+ int
+char_avail()
+{
+ int retval;
+
+ ++no_mapping;
+ retval = vpeekc();
+ --no_mapping;
+ return (retval != NUL);
+}
+
+ void
+vungetc(c) /* unget one character (can only be done once!) */
+ int c;
+{
+ old_char = c;
+ old_mod_mask = mod_mask;
+}
+
+/*
+ * get a character:
+ * 1. from the stuffbuffer
+ * This is used for abbreviated commands like "D" -> "d$".
+ * Also used to redo a command for ".".
+ * 2. from the typeahead buffer
+ * Stores text obtained previously but not used yet.
+ * Also stores the result of mappings.
+ * Also used for the ":normal" command.
+ * 3. from the user
+ * This may do a blocking wait if "advance" is TRUE.
+ *
+ * if "advance" is TRUE (vgetc()):
+ * really get the character.
+ * KeyTyped is set to TRUE in the case the user typed the key.
+ * KeyStuffed is TRUE if the character comes from the stuff buffer.
+ * if "advance" is FALSE (vpeekc()):
+ * just look whether there is a character available.
+ *
+ * When "no_mapping" is zero, checks for mappings in the current mode.
+ * Only returns one byte (of a multi-byte character).
+ * K_SPECIAL and CSI may be escaped, need to get two more bytes then.
+ */
+ static int
+vgetorpeek(advance)
+ int advance;
+{
+ int c, c1;
+ int keylen;
+ char_u *s;
+ mapblock_T *mp;
+#ifdef FEAT_LOCALMAP
+ mapblock_T *mp2;
+#endif
+ mapblock_T *mp_match;
+ int mp_match_len = 0;
+ int timedout = FALSE; /* waited for more than 1 second
+ for mapping to complete */
+ int mapdepth = 0; /* check for recursive mapping */
+ int mode_deleted = FALSE; /* set when mode has been deleted */
+ int local_State;
+ int mlen;
+ int max_mlen;
+#ifdef FEAT_CMDL_INFO
+ int i;
+ int new_wcol, new_wrow;
+#endif
+#ifdef FEAT_GUI
+# ifdef FEAT_MENU
+ int idx;
+# endif
+ int shape_changed = FALSE; /* adjusted cursor shape */
+#endif
+ int n;
+#ifdef FEAT_LANGMAP
+ int nolmaplen;
+#endif
+ int old_wcol, old_wrow;
+
+ /*
+ * This function doesn't work very well when called recursively. This may
+ * happen though, because of:
+ * 1. The call to add_to_showcmd(). char_avail() is then used to check if
+ * there is a character available, which calls this function. In that
+ * case we must return NUL, to indicate no character is available.
+ * 2. A GUI callback function writes to the screen, causing a
+ * wait_return().
+ * Using ":normal" can also do this, but it saves the typeahead buffer,
+ * thus it should be OK. But don't get a key from the user then.
+ */
+ if (vgetc_busy
+#ifdef FEAT_EX_EXTRA
+ && ex_normal_busy == 0
+#endif
+ )
+ return NUL;
+
+ local_State = get_real_state();
+
+ vgetc_busy = TRUE;
+
+ if (advance)
+ KeyStuffed = FALSE;
+
+ init_typebuf();
+ start_stuff();
+ if (advance && typebuf.tb_maplen == 0)
+ Exec_reg = FALSE;
+ do
+ {
+/*
+ * get a character: 1. from the stuffbuffer
+ */
+ if (typeahead_char != 0)
+ {
+ c = typeahead_char;
+ if (advance)
+ typeahead_char = 0;
+ }
+ else
+ c = read_stuff(advance);
+ if (c != NUL && !got_int)
+ {
+ if (advance)
+ {
+ /* KeyTyped = FALSE; When the command that stuffed something
+ * was typed, behave like the stuffed command was typed.
+ * needed for CTRL-W CTRl-] to open a fold, for example. */
+ KeyStuffed = TRUE;
+ }
+ if (typebuf.tb_no_abbr_cnt == 0)
+ typebuf.tb_no_abbr_cnt = 1; /* no abbreviations now */
+ }
+ else
+ {
+ /*
+ * Loop until we either find a matching mapped key, or we
+ * are sure that it is not a mapped key.
+ * If a mapped key sequence is found we go back to the start to
+ * try re-mapping.
+ */
+ for (;;)
+ {
+ /*
+ * ui_breakcheck() is slow, don't use it too often when
+ * inside a mapping. But call it each time for typed
+ * characters.
+ */
+ if (typebuf.tb_maplen)
+ line_breakcheck();
+ else
+ ui_breakcheck(); /* check for CTRL-C */
+ keylen = 0;
+ if (got_int)
+ {
+ /* flush all input */
+ c = inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 0L,
+ typebuf.tb_change_cnt);
+ /*
+ * If inchar() returns TRUE (script file was active) or we
+ * are inside a mapping, get out of insert mode.
+ * Otherwise we behave like having gotten a CTRL-C.
+ * As a result typing CTRL-C in insert mode will
+ * really insert a CTRL-C.
+ */
+ if ((c || typebuf.tb_maplen)
+ && (State & (INSERT + CMDLINE)))
+ c = ESC;
+ else
+ c = Ctrl_C;
+ flush_buffers(TRUE); /* flush all typeahead */
+
+ /* Also record this character, it might be needed to
+ * get out of Insert mode. */
+ *typebuf.tb_buf = c;
+ gotchars(typebuf.tb_buf, 1);
+ cmd_silent = FALSE;
+
+ break;
+ }
+ else if (typebuf.tb_len > 0)
+ {
+ /*
+ * Check for a mappable key sequence.
+ * Walk through one maphash[] list until we find an
+ * entry that matches.
+ *
+ * Don't look for mappings if:
+ * - no_mapping set: mapping disabled (e.g. for CTRL-V)
+ * - maphash_valid not set: no mappings present.
+ * - typebuf.tb_buf[typebuf.tb_off] should not be remapped
+ * - in insert or cmdline mode and 'paste' option set
+ * - waiting for "hit return to continue" and CR or SPACE
+ * typed
+ * - waiting for a char with --more--
+ * - in Ctrl-X mode, and we get a valid char for that mode
+ */
+ mp = NULL;
+ max_mlen = 0;
+ c1 = typebuf.tb_buf[typebuf.tb_off];
+ if (no_mapping == 0 && maphash_valid
+ && (no_zero_mapping == 0 || c1 != '0')
+ && (typebuf.tb_maplen == 0
+ || (p_remap
+ && typebuf.tb_noremap[typebuf.tb_off]
+ != RM_NONE))
+ && !(p_paste && (State & (INSERT + CMDLINE)))
+ && !(State == HITRETURN && (c1 == CAR || c1 == ' '))
+ && State != ASKMORE
+ && State != CONFIRM
+#ifdef FEAT_INS_EXPAND
+ && !((ctrl_x_mode != 0 && vim_is_ctrl_x_key(c1))
+ || ((continue_status & CONT_LOCAL)
+ && (c1 == Ctrl_N || c1 == Ctrl_P)))
+#endif
+ )
+ {
+#ifdef FEAT_LANGMAP
+ if (c1 == K_SPECIAL)
+ nolmaplen = 2;
+ else
+ {
+ LANGMAP_ADJUST(c1, TRUE);
+ nolmaplen = 0;
+ }
+#endif
+#ifdef FEAT_LOCALMAP
+ /* First try buffer-local mappings. */
+ mp = curbuf->b_maphash[MAP_HASH(local_State, c1)];
+ mp2 = maphash[MAP_HASH(local_State, c1)];
+ if (mp == NULL)
+ {
+ mp = mp2;
+ mp2 = NULL;
+ }
+#else
+ mp = maphash[MAP_HASH(local_State, c1)];
+#endif
+ /*
+ * Loop until a partly matching mapping is found or
+ * all (local) mappings have been checked.
+ * The longest full match is remembered in "mp_match".
+ * A full match is only accepted if there is no partly
+ * match, so "aa" and "aaa" can both be mapped.
+ */
+ mp_match = NULL;
+ mp_match_len = 0;
+ for ( ; mp != NULL;
+#ifdef FEAT_LOCALMAP
+ mp->m_next == NULL ? (mp = mp2, mp2 = NULL) :
+#endif
+ (mp = mp->m_next))
+ {
+ /*
+ * Only consider an entry if the first character
+ * matches and it is for the current state.
+ * Skip ":lmap" mappings if keys were mapped.
+ */
+ if (mp->m_keys[0] == c1
+ && (mp->m_mode & local_State)
+ && ((mp->m_mode & LANGMAP) == 0
+ || typebuf.tb_maplen == 0))
+ {
+#ifdef FEAT_LANGMAP
+ int nomap = nolmaplen;
+ int c2;
+#endif
+ /* find the match length of this mapping */
+ for (mlen = 1; mlen < typebuf.tb_len; ++mlen)
+ {
+#ifdef FEAT_LANGMAP
+ c2 = typebuf.tb_buf[typebuf.tb_off + mlen];
+ if (nomap > 0)
+ --nomap;
+ else if (c2 == K_SPECIAL)
+ nomap = 2;
+ else
+ LANGMAP_ADJUST(c2, TRUE);
+ if (mp->m_keys[mlen] != c2)
+#else
+ if (mp->m_keys[mlen] !=
+ typebuf.tb_buf[typebuf.tb_off + mlen])
+#endif
+ break;
+ }
+
+#ifdef FEAT_MBYTE
+ /* Don't allow mapping the first byte(s) of a
+ * multi-byte char. Happens when mapping
+ * <M-a> and then changing 'encoding'. */
+ if (has_mbyte && MB_BYTE2LEN(c1)
+ > (*mb_ptr2len_check)(mp->m_keys))
+ mlen = 0;
+#endif
+ /*
+ * Check an entry whether it matches.
+ * - Full match: mlen == keylen
+ * - Partly match: mlen == typebuf.tb_len
+ */
+ keylen = mp->m_keylen;
+ if (mlen == keylen
+ || (mlen == typebuf.tb_len
+ && typebuf.tb_len < keylen))
+ {
+ /*
+ * If only script-local mappings are
+ * allowed, check if the mapping starts
+ * with K_SNR.
+ */
+ s = typebuf.tb_noremap + typebuf.tb_off;
+ if (*s == RM_SCRIPT
+ && (mp->m_keys[0] != K_SPECIAL
+ || mp->m_keys[1] != KS_EXTRA
+ || mp->m_keys[2]
+ != (int)KE_SNR))
+ continue;
+ /*
+ * If one of the typed keys cannot be
+ * remapped, skip the entry.
+ */
+ for (n = mlen; --n >= 0; )
+ if (*s++ == RM_NONE)
+ break;
+ if (n >= 0)
+ continue;
+
+ if (keylen > typebuf.tb_len)
+ {
+ if (!timedout)
+ {
+ /* break at a partly match */
+ keylen = KL_PART_MAP;
+ break;
+ }
+ }
+ else if (keylen > mp_match_len)
+ {
+ /* found a longer match */
+ mp_match = mp;
+ mp_match_len = keylen;
+ }
+ }
+ else
+ /* No match; may have to check for
+ * termcode at next character. */
+ if (max_mlen < mlen)
+ max_mlen = mlen;
+ }
+ }
+
+ /* If no partly match found, use the longest full
+ * match. */
+ if (keylen != KL_PART_MAP)
+ {
+ mp = mp_match;
+ keylen = mp_match_len;
+ }
+ }
+
+ /* Check for match with 'pastetoggle' */
+ if (*p_pt != NUL && mp == NULL && (State & (INSERT|NORMAL)))
+ {
+ for (mlen = 0; mlen < typebuf.tb_len && p_pt[mlen];
+ ++mlen)
+ if (p_pt[mlen] != typebuf.tb_buf[typebuf.tb_off
+ + mlen])
+ break;
+ if (p_pt[mlen] == NUL) /* match */
+ {
+ /* write chars to script file(s) */
+ if (mlen > typebuf.tb_maplen)
+ gotchars(typebuf.tb_buf + typebuf.tb_off
+ + typebuf.tb_maplen,
+ mlen - typebuf.tb_maplen);
+
+ del_typebuf(mlen, 0); /* remove the chars */
+ set_option_value((char_u *)"paste",
+ (long)!p_paste, NULL, 0);
+ if (!(State & INSERT))
+ {
+ msg_col = 0;
+ msg_row = Rows - 1;
+ msg_clr_eos(); /* clear ruler */
+ }
+ showmode();
+ setcursor();
+ continue;
+ }
+ /* Need more chars for partly match. */
+ if (mlen == typebuf.tb_len)
+ keylen = KL_PART_MAP;
+ else if (max_mlen < mlen)
+ /* no match, may have to check for termcode at
+ * next character */
+ max_mlen = mlen + 1;
+ }
+
+ if ((mp == NULL || max_mlen >= mp_match_len)
+ && keylen != KL_PART_MAP)
+ {
+ /*
+ * When no matching mapping found or found a
+ * non-matching mapping that matches at least what the
+ * matching mapping matched:
+ * Check if we have a terminal code, when:
+ * mapping is allowed,
+ * keys have not been mapped,
+ * and not an ESC sequence, not in insert mode or
+ * p_ek is on,
+ * and when not timed out,
+ */
+ if ((no_mapping == 0 || allow_keys != 0)
+ && (typebuf.tb_maplen == 0
+ || (p_remap && typebuf.tb_noremap[
+ typebuf.tb_off] == RM_YES))
+ && !timedout)
+ {
+ keylen = check_termcode(max_mlen + 1, NULL, 0);
+
+ /*
+ * When getting a partial match, but the last
+ * characters were not typed, don't wait for a
+ * typed character to complete the termcode.
+ * This helps a lot when a ":normal" command ends
+ * in an ESC.
+ */
+ if (keylen < 0
+ && typebuf.tb_len == typebuf.tb_maplen)
+ keylen = 0;
+ }
+ else
+ keylen = 0;
+ if (keylen == 0) /* no matching terminal code */
+ {
+#ifdef AMIGA /* check for window bounds report */
+ if (typebuf.tb_maplen == 0 && (typebuf.tb_buf[
+ typebuf.tb_off] & 0xff) == CSI)
+ {
+ for (s = typebuf.tb_buf + typebuf.tb_off + 1;
+ s < typebuf.tb_buf + typebuf.tb_off
+ + typebuf.tb_len
+ && (VIM_ISDIGIT(*s) || *s == ';'
+ || *s == ' ');
+ ++s)
+ ;
+ if (*s == 'r' || *s == '|') /* found one */
+ {
+ del_typebuf((int)(s + 1 -
+ (typebuf.tb_buf + typebuf.tb_off)), 0);
+ /* get size and redraw screen */
+ shell_resized();
+ continue;
+ }
+ if (*s == NUL) /* need more characters */
+ keylen = KL_PART_KEY;
+ }
+ if (keylen >= 0)
+#endif
+ /* When there was a matching mapping and no
+ * termcode could be replaced after another one,
+ * use that mapping. */
+ if (mp == NULL)
+ {
+/*
+ * get a character: 2. from the typeahead buffer
+ */
+ c = typebuf.tb_buf[typebuf.tb_off] & 255;
+ if (advance) /* remove chars from tb_buf */
+ {
+ cmd_silent = (typebuf.tb_silent > 0);
+ if (typebuf.tb_maplen > 0)
+ KeyTyped = FALSE;
+ else
+ {
+ KeyTyped = TRUE;
+ /* write char to script file(s) */
+ gotchars(typebuf.tb_buf
+ + typebuf.tb_off, 1);
+ }
+ KeyNoremap = (typebuf.tb_noremap[
+ typebuf.tb_off] != REMAP_YES);
+ del_typebuf(1, 0);
+ }
+ break; /* got character, break for loop */
+ }
+ }
+ if (keylen > 0) /* full matching terminal code */
+ {
+#if defined(FEAT_GUI) && defined(FEAT_MENU)
+ if (typebuf.tb_buf[typebuf.tb_off] == K_SPECIAL
+ && typebuf.tb_buf[typebuf.tb_off + 1]
+ == KS_MENU)
+ {
+ /*
+ * Using a menu may cause a break in undo!
+ * It's like using gotchars(), but without
+ * recording or writing to a script file.
+ */
+ may_sync_undo();
+ del_typebuf(3, 0);
+ idx = get_menu_index(current_menu, local_State);
+ if (idx != MENU_INDEX_INVALID)
+ {
+# ifdef FEAT_VISUAL
+ /*
+ * In Select mode, a Visual mode menu is
+ * used. Switch to Visual mode
+ * temporarily. Append K_SELECT to switch
+ * back to Select mode.
+ */
+ if (VIsual_active && VIsual_select)
+ {
+ VIsual_select = FALSE;
+ (void)ins_typebuf(K_SELECT_STRING,
+ REMAP_NONE, 0, TRUE, FALSE);
+ }
+# endif
+ ins_typebuf(current_menu->strings[idx],
+ current_menu->noremap[idx],
+ 0, TRUE,
+ current_menu->silent[idx]);
+ }
+ }
+#endif /* FEAT_GUI */
+ continue; /* try mapping again */
+ }
+
+ /* Partial match: get some more characters. When a
+ * matching mapping was found use that one. */
+ if (mp == NULL || keylen < 0)
+ keylen = KL_PART_KEY;
+ else
+ keylen = mp_match_len;
+ }
+
+ /* complete match */
+ if (keylen >= 0 && keylen <= typebuf.tb_len)
+ {
+ /* write chars to script file(s) */
+ if (keylen > typebuf.tb_maplen)
+ gotchars(typebuf.tb_buf + typebuf.tb_off
+ + typebuf.tb_maplen,
+ keylen - typebuf.tb_maplen);
+
+ cmd_silent = (typebuf.tb_silent > 0);
+ del_typebuf(keylen, 0); /* remove the mapped keys */
+
+ /*
+ * Put the replacement string in front of mapstr.
+ * The depth check catches ":map x y" and ":map y x".
+ */
+ if (++mapdepth >= p_mmd)
+ {
+ EMSG(_("E223: recursive mapping"));
+ if (State & CMDLINE)
+ redrawcmdline();
+ else
+ setcursor();
+ flush_buffers(FALSE);
+ mapdepth = 0; /* for next one */
+ c = -1;
+ break;
+ }
+
+#ifdef FEAT_VISUAL
+ /*
+ * In Select mode, a Visual mode mapping is used.
+ * Switch to Visual mode temporarily. Append K_SELECT
+ * to switch back to Select mode.
+ */
+ if (VIsual_active && VIsual_select)
+ {
+ VIsual_select = FALSE;
+ (void)ins_typebuf(K_SELECT_STRING, REMAP_NONE,
+ 0, TRUE, FALSE);
+ }
+#endif
+
+ /*
+ * Insert the 'to' part in the typebuf.tb_buf.
+ * If 'from' field is the same as the start of the
+ * 'to' field, don't remap the first character.
+ * If m_noremap is set, don't remap the whole 'to'
+ * part.
+ */
+ if (ins_typebuf(mp->m_str,
+ mp->m_noremap != REMAP_YES
+ ? mp->m_noremap
+ : STRNCMP(mp->m_str, mp->m_keys,
+ (size_t)keylen)
+ ? REMAP_YES : 1,
+ 0, TRUE, cmd_silent || mp->m_silent) == FAIL)
+ {
+ c = -1;
+ break;
+ }
+ continue;
+ }
+ }
+
+/*
+ * get a character: 3. from the user - handle <Esc> in Insert mode
+ */
+ /*
+ * special case: if we get an <ESC> in insert mode and there
+ * are no more characters at once, we pretend to go out of
+ * insert mode. This prevents the one second delay after
+ * typing an <ESC>. If we get something after all, we may
+ * have to redisplay the mode. That the cursor is in the wrong
+ * place does not matter.
+ */
+ c = 0;
+#ifdef FEAT_CMDL_INFO
+ new_wcol = curwin->w_wcol;
+ new_wrow = curwin->w_wrow;
+#endif
+ if ( advance
+ && typebuf.tb_len == 1
+ && typebuf.tb_buf[typebuf.tb_off] == ESC
+ && !no_mapping
+#ifdef FEAT_EX_EXTRA
+ && ex_normal_busy == 0
+#endif
+ && typebuf.tb_maplen == 0
+ && (State & INSERT)
+ && (p_timeout || (keylen == KL_PART_KEY && p_ttimeout))
+ && (c = inchar(typebuf.tb_buf + typebuf.tb_off
+ + typebuf.tb_len, 3, 25L,
+ typebuf.tb_change_cnt)) == 0)
+ {
+ colnr_T col = 0, vcol;
+ char_u *ptr;
+
+ if (p_smd)
+ {
+ unshowmode(TRUE);
+ mode_deleted = TRUE;
+ }
+#ifdef FEAT_GUI
+ /* may show different cursor shape */
+ if (gui.in_use)
+ {
+ int save_State;
+
+ save_State = State;
+ State = NORMAL;
+ gui_update_cursor(TRUE, FALSE);
+ State = save_State;
+ shape_changed = TRUE;
+ }
+#endif
+ validate_cursor();
+ old_wcol = curwin->w_wcol;
+ old_wrow = curwin->w_wrow;
+
+ /* move cursor left, if possible */
+ if (curwin->w_cursor.col != 0)
+ {
+ if (curwin->w_wcol > 0)
+ {
+ if (did_ai)
+ {
+ /*
+ * We are expecting to truncate the trailing
+ * white-space, so find the last non-white
+ * character -- webb
+ */
+ col = vcol = curwin->w_wcol = 0;
+ ptr = ml_get_curline();
+ while (col < curwin->w_cursor.col)
+ {
+ if (!vim_iswhite(ptr[col]))
+ curwin->w_wcol = vcol;
+ vcol += lbr_chartabsize(ptr + col,
+ (colnr_T)vcol);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ col += (*mb_ptr2len_check)(ptr + col);
+ else
+#endif
+ ++col;
+ }
+ curwin->w_wrow = curwin->w_cline_row
+ + curwin->w_wcol / W_WIDTH(curwin);
+ curwin->w_wcol %= W_WIDTH(curwin);
+ curwin->w_wcol += curwin_col_off();
+#ifdef FEAT_MBYTE
+ col = 0; /* no correction needed */
+#endif
+ }
+ else
+ {
+ --curwin->w_wcol;
+#ifdef FEAT_MBYTE
+ col = curwin->w_cursor.col - 1;
+#endif
+ }
+ }
+ else if (curwin->w_p_wrap && curwin->w_wrow)
+ {
+ --curwin->w_wrow;
+ curwin->w_wcol = W_WIDTH(curwin) - 1;
+#ifdef FEAT_MBYTE
+ col = curwin->w_cursor.col - 1;
+#endif
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte && col > 0 && curwin->w_wcol > 0)
+ {
+ /* Correct when the cursor is on the right halve
+ * of a double-wide character. */
+ ptr = ml_get_curline();
+ col -= (*mb_head_off)(ptr, ptr + col);
+ if ((*mb_ptr2cells)(ptr + col) > 1)
+ --curwin->w_wcol;
+ }
+#endif
+ }
+ setcursor();
+ out_flush();
+#ifdef FEAT_CMDL_INFO
+ new_wcol = curwin->w_wcol;
+ new_wrow = curwin->w_wrow;
+#endif
+ curwin->w_wcol = old_wcol;
+ curwin->w_wrow = old_wrow;
+ }
+ if (c < 0)
+ continue; /* end of input script reached */
+ typebuf.tb_len += c;
+
+ /* buffer full, don't map */
+ if (typebuf.tb_len >= typebuf.tb_maplen + MAXMAPLEN)
+ {
+ timedout = TRUE;
+ continue;
+ }
+
+#ifdef FEAT_EX_EXTRA
+ if (ex_normal_busy > 0)
+ {
+# ifdef FEAT_CMDWIN
+ static int tc = 0;
+# endif
+
+ /* No typeahead left and inside ":normal". Must return
+ * something to avoid getting stuck. When an incomplete
+ * mapping is present, behave like it timed out. */
+ if (typebuf.tb_len > 0)
+ {
+ timedout = TRUE;
+ continue;
+ }
+ /* When 'insertmode' is set, ESC just beeps in Insert
+ * mode. Use CTRL-L to make edit() return.
+ * For the command line only CTRL-C always breaks it.
+ * For the cmdline window: Alternate between ESC and
+ * CTRL-C: ESC for most situations and CTRL-C to close the
+ * cmdline window. */
+ if (p_im && (State & INSERT))
+ c = Ctrl_L;
+ else if ((State & CMDLINE)
+# ifdef FEAT_CMDWIN
+ || (cmdwin_type > 0 && tc == ESC)
+# endif
+ )
+ c = Ctrl_C;
+ else
+ c = ESC;
+# ifdef FEAT_CMDWIN
+ tc = c;
+# endif
+ break;
+ }
+#endif
+
+/*
+ * get a character: 3. from the user - update display
+ */
+ /* In insert mode a screen update is skipped when characters
+ * are still available. But when those available characters
+ * are part of a mapping, and we are going to do a blocking
+ * wait here. Need to update the screen to display the
+ * changed text so far. */
+ if ((State & INSERT) && advance && must_redraw != 0)
+ {
+ update_screen(0);
+ setcursor(); /* put cursor back where it belongs */
+ }
+
+ /*
+ * If we have a partial match (and are going to wait for more
+ * input from the user), show the partially matched characters
+ * to the user with showcmd.
+ */
+#ifdef FEAT_CMDL_INFO
+ i = 0;
+#endif
+ c1 = 0;
+ if (typebuf.tb_len > 0 && advance && !exmode_active)
+ {
+ if (((State & (NORMAL | INSERT)) || State == LANGMAP)
+ && State != HITRETURN)
+ {
+ /* this looks nice when typing a dead character map */
+ if (State & INSERT
+ && ptr2cells(typebuf.tb_buf + typebuf.tb_off
+ + typebuf.tb_len - 1) == 1)
+ {
+ edit_putchar(typebuf.tb_buf[typebuf.tb_off
+ + typebuf.tb_len - 1], FALSE);
+ setcursor(); /* put cursor back where it belongs */
+ c1 = 1;
+ }
+#ifdef FEAT_CMDL_INFO
+ /* need to use the col and row from above here */
+ old_wcol = curwin->w_wcol;
+ old_wrow = curwin->w_wrow;
+ curwin->w_wcol = new_wcol;
+ curwin->w_wrow = new_wrow;
+ push_showcmd();
+ if (typebuf.tb_len > SHOWCMD_COLS)
+ i = typebuf.tb_len - SHOWCMD_COLS;
+ while (i < typebuf.tb_len)
+ (void)add_to_showcmd(typebuf.tb_buf[typebuf.tb_off
+ + i++]);
+ curwin->w_wcol = old_wcol;
+ curwin->w_wrow = old_wrow;
+#endif
+ }
+
+ /* this looks nice when typing a dead character map */
+ if ((State & CMDLINE)
+#if defined(FEAT_CRYPT) || defined(FEAT_EVAL)
+ && cmdline_star == 0
+#endif
+ && ptr2cells(typebuf.tb_buf + typebuf.tb_off
+ + typebuf.tb_len - 1) == 1)
+ {
+ putcmdline(typebuf.tb_buf[typebuf.tb_off
+ + typebuf.tb_len - 1], FALSE);
+ c1 = 1;
+ }
+ }
+
+/*
+ * get a character: 3. from the user - get it
+ */
+ c = inchar(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len,
+ typebuf.tb_buflen - typebuf.tb_off - typebuf.tb_len - 1,
+ !advance
+ ? 0
+ : ((typebuf.tb_len == 0
+ || !(p_timeout || (p_ttimeout
+ && keylen == KL_PART_KEY)))
+ ? -1L
+ : ((keylen == KL_PART_KEY && p_ttm >= 0)
+ ? p_ttm
+ : p_tm)), typebuf.tb_change_cnt);
+
+#ifdef FEAT_CMDL_INFO
+ if (i != 0)
+ pop_showcmd();
+#endif
+ if (c1 == 1)
+ {
+ if (State & INSERT)
+ edit_unputchar();
+ if (State & CMDLINE)
+ unputcmdline();
+ setcursor(); /* put cursor back where it belongs */
+ }
+
+ if (c < 0)
+ continue; /* end of input script reached */
+ if (c == NUL) /* no character available */
+ {
+ if (!advance)
+ break;
+ if (typebuf.tb_len > 0) /* timed out */
+ {
+ timedout = TRUE;
+ continue;
+ }
+ }
+ else
+ { /* allow mapping for just typed characters */
+ while (typebuf.tb_buf[typebuf.tb_off
+ + typebuf.tb_len] != NUL)
+ typebuf.tb_noremap[typebuf.tb_off
+ + typebuf.tb_len++] = RM_YES;
+#ifdef USE_IM_CONTROL
+ /* Get IM status right after getting keys, not after the
+ * timeout for a mapping (focus may be lost by then). */
+ vgetc_im_active = im_get_status();
+#endif
+ }
+ } /* for (;;) */
+ } /* if (!character from stuffbuf) */
+
+ /* if advance is FALSE don't loop on NULs */
+ } while (c < 0 || (advance && c == NUL));
+
+ /*
+ * The "INSERT" message is taken care of here:
+ * if we return an ESC to exit insert mode, the message is deleted
+ * if we don't return an ESC but deleted the message before, redisplay it
+ */
+ if (advance && p_smd && (State & INSERT))
+ {
+ if (c == ESC && !mode_deleted && !no_mapping)
+ {
+ if (typebuf.tb_len && !KeyTyped)
+ redraw_cmdline = TRUE; /* delete mode later */
+ else
+ unshowmode(FALSE);
+ }
+ else if (c != ESC && mode_deleted)
+ {
+ if (typebuf.tb_len && !KeyTyped)
+ redraw_cmdline = TRUE; /* show mode later */
+ else
+ showmode();
+ }
+ }
+#ifdef FEAT_GUI
+ /* may unshow different cursor shape */
+ if (gui.in_use && shape_changed)
+ gui_update_cursor(TRUE, FALSE);
+#endif
+
+ vgetc_busy = FALSE;
+
+ return c;
+}
+
+/*
+ * inchar() - get one character from
+ * 1. a scriptfile
+ * 2. the keyboard
+ *
+ * As much characters as we can get (upto 'maxlen') are put in "buf" and
+ * NUL terminated (buffer length must be 'maxlen' + 1).
+ * Minimum for "maxlen" is 3!!!!
+ *
+ * "tb_change_cnt" is the value of typebuf.tb_change_cnt if "buf" points into
+ * it. When typebuf.tb_change_cnt changes (e.g., when a message is received
+ * from a remote client) "buf" can no longer be used. "tb_change_cnt" is 0
+ * otherwise.
+ *
+ * If we got an interrupt all input is read until none is available.
+ *
+ * If wait_time == 0 there is no waiting for the char.
+ * If wait_time == n we wait for n msec for a character to arrive.
+ * If wait_time == -1 we wait forever for a character to arrive.
+ *
+ * Return the number of obtained characters.
+ * Return -1 when end of input script reached.
+ */
+ int
+inchar(buf, maxlen, wait_time, tb_change_cnt)
+ char_u *buf;
+ int maxlen;
+ long wait_time; /* milli seconds */
+ int tb_change_cnt;
+{
+ int len = 0; /* init for GCC */
+ int retesc = FALSE; /* return ESC with gotint */
+ int script_char;
+
+ if (wait_time == -1L || wait_time > 100L) /* flush output before waiting */
+ {
+ cursor_on();
+ out_flush();
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ gui_update_cursor(FALSE, FALSE);
+# ifdef FEAT_MOUSESHAPE
+ if (postponed_mouseshape)
+ update_mouseshape(-1);
+# endif
+ }
+#endif
+ }
+
+ /*
+ * Don't reset these when at the hit-return prompt, otherwise a endless
+ * recursive loop may result (write error in swapfile, hit-return, timeout
+ * on char wait, flush swapfile, write error....).
+ */
+ if (State != HITRETURN)
+ {
+ did_outofmem_msg = FALSE; /* display out of memory message (again) */
+ did_swapwrite_msg = FALSE; /* display swap file write error again */
+ }
+ undo_off = FALSE; /* restart undo now */
+
+ /*
+ * first try script file
+ * If interrupted: Stop reading script files.
+ */
+ script_char = -1;
+ while (scriptin[curscript] != NULL && script_char < 0)
+ {
+ if (got_int || (script_char = getc(scriptin[curscript])) < 0)
+ {
+ /* Reached EOF.
+ * Careful: closescript() frees typebuf.tb_buf[] and buf[] may
+ * point inside typebuf.tb_buf[]. Don't use buf[] after this! */
+ closescript();
+ /*
+ * When reading script file is interrupted, return an ESC to get
+ * back to normal mode.
+ * Otherwise return -1, because typebuf.tb_buf[] has changed.
+ */
+ if (got_int)
+ retesc = TRUE;
+ else
+ return -1;
+ }
+ else
+ {
+ buf[0] = script_char;
+ len = 1;
+ }
+ }
+
+ if (script_char < 0) /* did not get a character from script */
+ {
+ /*
+ * If we got an interrupt, skip all previously typed characters and
+ * return TRUE if quit reading script file.
+ * Stop reading typeahead when a single CTRL-C was read,
+ * fill_input_buf() returns this when not able to read from stdin.
+ * Don't use buf[] here, closescript() may have freed typebuf.tb_buf[]
+ * and buf may be pointing inside typebuf.tb_buf[].
+ */
+ if (got_int)
+ {
+#define DUM_LEN MAXMAPLEN * 3 + 3
+ char_u dum[DUM_LEN + 1];
+
+ for (;;)
+ {
+ len = ui_inchar(dum, DUM_LEN, 0L, 0);
+ if (len == 0 || (len == 1 && dum[0] == 3))
+ break;
+ }
+ return retesc;
+ }
+
+ /*
+ * Always flush the output characters when getting input characters
+ * from the user.
+ */
+ out_flush();
+
+ /*
+ * Fill up to a third of the buffer, because each character may be
+ * tripled below.
+ */
+ len = ui_inchar(buf, maxlen / 3, wait_time, tb_change_cnt);
+ }
+
+ if (typebuf_changed(tb_change_cnt))
+ return 0;
+
+ return fix_input_buffer(buf, len, script_char >= 0);
+}
+
+/*
+ * Fix typed characters for use by vgetc() and check_termcode().
+ * buf[] must have room to triple the number of bytes!
+ * Returns the new length.
+ */
+ int
+fix_input_buffer(buf, len, script)
+ char_u *buf;
+ int len;
+ int script; /* TRUE when reading from a script */
+{
+ int i;
+ char_u *p = buf;
+
+ /*
+ * Two characters are special: NUL and K_SPECIAL.
+ * When compiled With the GUI CSI is also special.
+ * Replace NUL by K_SPECIAL KS_ZERO KE_FILLER
+ * Replace K_SPECIAL by K_SPECIAL KS_SPECIAL KE_FILLER
+ * Replace CSI by K_SPECIAL KS_EXTRA KE_CSI
+ * Don't replace K_SPECIAL when reading a script file.
+ */
+ for (i = len; --i >= 0; ++p)
+ {
+#ifdef FEAT_GUI
+ /* When the GUI is used any character can come after a CSI, don't
+ * escape it. */
+ if (gui.in_use && p[0] == CSI && i >= 2)
+ {
+ p += 2;
+ i -= 2;
+ }
+ /* When the GUI is not used CSI needs to be escaped. */
+ else if (!gui.in_use && p[0] == CSI)
+ {
+ mch_memmove(p + 3, p + 1, (size_t)i);
+ *p++ = K_SPECIAL;
+ *p++ = KS_EXTRA;
+ *p = (int)KE_CSI;
+ len += 2;
+ }
+ else
+#endif
+ if (p[0] == NUL || (p[0] == K_SPECIAL && !script
+#if defined(WIN3264) && !defined(FEAT_GUI)
+ /* Win32 console passes modifiers */
+ && (i < 2 || p[1] != KS_MODIFIER)
+#endif
+ ))
+ {
+ mch_memmove(p + 3, p + 1, (size_t)i);
+ p[2] = K_THIRD(p[0]);
+ p[1] = K_SECOND(p[0]);
+ p[0] = K_SPECIAL;
+ p += 2;
+ len += 2;
+ }
+ }
+ *p = NUL; /* add trailing NUL */
+ return len;
+}
+
+#if defined(USE_INPUT_BUF) || defined(PROTO)
+/*
+ * Return TRUE when bytes are in the input buffer or in the typeahead buffer.
+ * Normally the input buffer would be sufficient, but the server_to_input_buf()
+ * may insert characters in the typeahead buffer while we are waiting for
+ * input to arrive.
+ */
+ int
+input_available()
+{
+ return (!vim_is_input_buf_empty()
+# ifdef FEAT_CLIENTSERVER
+ || received_from_client
+# endif
+ );
+}
+#endif
+
+/*
+ * map[!] : show all key mappings
+ * map[!] {lhs} : show key mapping for {lhs}
+ * map[!] {lhs} {rhs} : set key mapping for {lhs} to {rhs}
+ * noremap[!] {lhs} {rhs} : same, but no remapping for {rhs}
+ * unmap[!] {lhs} : remove key mapping for {lhs}
+ * abbr : show all abbreviations
+ * abbr {lhs} : show abbreviations for {lhs}
+ * abbr {lhs} {rhs} : set abbreviation for {lhs} to {rhs}
+ * noreabbr {lhs} {rhs} : same, but no remapping for {rhs}
+ * unabbr {lhs} : remove abbreviation for {lhs}
+ *
+ * maptype: 0 for :map, 1 for :unmap, 2 for noremap.
+ *
+ * arg is pointer to any arguments. Note: arg cannot be a read-only string,
+ * it will be modified.
+ *
+ * for :map mode is NORMAL + VISUAL + OP_PENDING
+ * for :map! mode is INSERT + CMDLINE
+ * for :cmap mode is CMDLINE
+ * for :imap mode is INSERT
+ * for :lmap mode is LANGMAP
+ * for :nmap mode is NORMAL
+ * for :vmap mode is VISUAL
+ * for :omap mode is OP_PENDING
+ *
+ * for :abbr mode is INSERT + CMDLINE
+ * for :iabbr mode is INSERT
+ * for :cabbr mode is CMDLINE
+ *
+ * Return 0 for success
+ * 1 for invalid arguments
+ * 2 for no match
+ * 4 for out of mem
+ * 5 for entry not unique
+ */
+ int
+do_map(maptype, arg, mode, abbrev)
+ int maptype;
+ char_u *arg;
+ int mode;
+ int abbrev; /* not a mapping but an abbreviation */
+{
+ char_u *keys;
+ mapblock_T *mp, **mpp;
+ char_u *rhs;
+ char_u *p;
+ int n;
+ int len = 0; /* init for GCC */
+ char_u *newstr;
+ int hasarg;
+ int haskey;
+ int did_it = FALSE;
+#ifdef FEAT_LOCALMAP
+ int did_local = FALSE;
+#endif
+ int round;
+ char_u *keys_buf = NULL;
+ char_u *arg_buf = NULL;
+ int retval = 0;
+ int do_backslash;
+ int hash;
+ int new_hash;
+ mapblock_T **abbr_table;
+ mapblock_T **map_table;
+ int unique = FALSE;
+ int silent = FALSE;
+ int noremap;
+
+ keys = arg;
+ map_table = maphash;
+ abbr_table = &first_abbr;
+
+ /* For ":noremap" don't remap, otherwise do remap. */
+ if (maptype == 2)
+ noremap = REMAP_NONE;
+ else
+ noremap = REMAP_YES;
+
+ /* Accept <buffer>, <silent>, <script> and <unique> in any order. */
+ for (;;)
+ {
+#ifdef FEAT_LOCALMAP
+ /*
+ * Check for "<buffer>": mapping local to buffer.
+ */
+ if (STRNCMP(keys, "<buffer>", 8) == 0)
+ {
+ keys = skipwhite(keys + 8);
+ map_table = curbuf->b_maphash;
+ abbr_table = &curbuf->b_first_abbr;
+ continue;
+ }
+#endif
+
+ /*
+ * Check for "<silent>": don't echo commands.
+ */
+ if (STRNCMP(keys, "<silent>", 8) == 0)
+ {
+ keys = skipwhite(keys + 8);
+ silent = TRUE;
+ continue;
+ }
+
+#ifdef FEAT_EVAL
+ /*
+ * Check for "<script>": remap script-local mappings only
+ */
+ if (STRNCMP(keys, "<script>", 8) == 0)
+ {
+ keys = skipwhite(keys + 8);
+ noremap = REMAP_SCRIPT;
+ continue;
+ }
+#endif
+ /*
+ * Check for "<unique>": don't overwrite an existing mapping.
+ */
+ if (STRNCMP(keys, "<unique>", 8) == 0)
+ {
+ keys = skipwhite(keys + 8);
+ unique = TRUE;
+ continue;
+ }
+ break;
+ }
+
+ validate_maphash();
+
+ /*
+ * find end of keys and skip CTRL-Vs (and backslashes) in it
+ * Accept backslash like CTRL-V when 'cpoptions' does not contain 'B'.
+ * with :unmap white space is included in the keys, no argument possible
+ */
+ p = keys;
+ do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
+ while (*p && (maptype == 1 || !vim_iswhite(*p)))
+ {
+ if ((p[0] == Ctrl_V || (do_backslash && p[0] == '\\')) &&
+ p[1] != NUL)
+ ++p; /* skip CTRL-V or backslash */
+ ++p;
+ }
+ if (*p != NUL)
+ *p++ = NUL;
+ p = skipwhite(p);
+ rhs = p;
+ hasarg = (*rhs != NUL);
+ haskey = (*keys != NUL);
+
+ /* check for :unmap without argument */
+ if (maptype == 1 && !haskey)
+ {
+ retval = 1;
+ goto theend;
+ }
+
+ /*
+ * If mapping has been given as ^V<C_UP> say, then replace the term codes
+ * with the appropriate two bytes. If it is a shifted special key, unshift
+ * it too, giving another two bytes.
+ * replace_termcodes() may move the result to allocated memory, which
+ * needs to be freed later (*keys_buf and *arg_buf).
+ * replace_termcodes() also removes CTRL-Vs and sometimes backslashes.
+ */
+ if (haskey)
+ keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
+ if (hasarg)
+ {
+ if (STRICMP(rhs, "<nop>") == 0) /* "<Nop>" means nothing */
+ rhs = (char_u *)"";
+ else
+ rhs = replace_termcodes(rhs, &arg_buf, FALSE, TRUE);
+ }
+
+#ifdef FEAT_FKMAP
+ /*
+ * when in right-to-left mode and alternate keymap option set,
+ * reverse the character flow in the rhs in Farsi.
+ */
+ if (p_altkeymap && curwin->w_p_rl)
+ lrswap(rhs);
+#endif
+
+ /*
+ * check arguments and translate function keys
+ */
+ if (haskey)
+ {
+ len = (int)STRLEN(keys);
+ if (len > MAXMAPLEN) /* maximum length of MAXMAPLEN chars */
+ {
+ retval = 1;
+ goto theend;
+ }
+
+ if (abbrev && maptype != 1)
+ {
+ /*
+ * If an abbreviation ends in a keyword character, the
+ * rest must be all keyword-char or all non-keyword-char.
+ * Otherwise we won't be able to find the start of it in a
+ * vi-compatible way.
+ */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int first, last;
+ int same = -1;
+
+ first = vim_iswordp(keys);
+ last = first;
+ p = keys + mb_ptr2len_check(keys);
+ n = 1;
+ while (p < keys + len)
+ {
+ ++n; /* nr of (multi-byte) chars */
+ last = vim_iswordp(p); /* type of last char */
+ if (same == -1 && last != first)
+ same = n - 1; /* count of same char type */
+ p += mb_ptr2len_check(p);
+ }
+ if (last && n > 2 && same >= 0 && same < n - 1)
+ {
+ retval = 1;
+ goto theend;
+ }
+ }
+ else
+#endif
+ if (vim_iswordc(keys[len - 1])) /* ends in keyword char */
+ for (n = 0; n < len - 2; ++n)
+ if (vim_iswordc(keys[n]) != vim_iswordc(keys[len - 2]))
+ {
+ retval = 1;
+ goto theend;
+ }
+ /* An abbrevation cannot contain white space. */
+ for (n = 0; n < len; ++n)
+ if (vim_iswhite(keys[n]))
+ {
+ retval = 1;
+ goto theend;
+ }
+ }
+ }
+
+ if (haskey && hasarg && abbrev) /* if we will add an abbreviation */
+ no_abbr = FALSE; /* reset flag that indicates there are
+ no abbreviations */
+
+ if (!haskey || (maptype != 1 && !hasarg))
+ msg_start();
+
+#ifdef FEAT_LOCALMAP
+ /*
+ * Check if a new local mapping wasn't already defined globally.
+ */
+ if (map_table == curbuf->b_maphash && haskey && hasarg && maptype != 1)
+ {
+ /* need to loop over all global hash lists */
+ for (hash = 0; hash < 256 && !got_int; ++hash)
+ {
+ if (abbrev)
+ {
+ if (hash != 0) /* there is only one abbreviation list */
+ break;
+ mp = first_abbr;
+ }
+ else
+ mp = maphash[hash];
+ for ( ; mp != NULL && !got_int; mp = mp->m_next)
+ {
+ /* check entries with the same mode */
+ if ((mp->m_mode & mode) != 0
+ && mp->m_keylen == len
+ && unique
+ && STRNCMP(mp->m_keys, keys, (size_t)len) == 0)
+ {
+ if (abbrev)
+ EMSG2(_("E224: global abbreviation already exists for %s"),
+ mp->m_keys);
+ else
+ EMSG2(_("E225: global mapping already exists for %s"),
+ mp->m_keys);
+ retval = 5;
+ goto theend;
+ }
+ }
+ }
+ }
+
+ /*
+ * When listing global mappings, also list buffer-local ones here.
+ */
+ if (map_table != curbuf->b_maphash && !hasarg && maptype != 1)
+ {
+ /* need to loop over all global hash lists */
+ for (hash = 0; hash < 256 && !got_int; ++hash)
+ {
+ if (abbrev)
+ {
+ if (hash != 0) /* there is only one abbreviation list */
+ break;
+ mp = curbuf->b_first_abbr;
+ }
+ else
+ mp = curbuf->b_maphash[hash];
+ for ( ; mp != NULL && !got_int; mp = mp->m_next)
+ {
+ /* check entries with the same mode */
+ if ((mp->m_mode & mode) != 0)
+ {
+ if (!haskey) /* show all entries */
+ {
+ showmap(mp, TRUE);
+ did_local = TRUE;
+ }
+ else
+ {
+ n = mp->m_keylen;
+ if (STRNCMP(mp->m_keys, keys,
+ (size_t)(n < len ? n : len)) == 0)
+ {
+ showmap(mp, TRUE);
+ did_local = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ /*
+ * Find an entry in the maphash[] list that matches.
+ * For :unmap we may loop two times: once to try to unmap an entry with a
+ * matching 'from' part, a second time, if the first fails, to unmap an
+ * entry with a matching 'to' part. This was done to allow ":ab foo bar"
+ * to be unmapped by typing ":unab foo", where "foo" will be replaced by
+ * "bar" because of the abbreviation.
+ */
+ for (round = 0; (round == 0 || maptype == 1) && round <= 1
+ && !did_it && !got_int; ++round)
+ {
+ /* need to loop over all hash lists */
+ for (hash = 0; hash < 256 && !got_int; ++hash)
+ {
+ if (abbrev)
+ {
+ if (hash != 0) /* there is only one abbreviation list */
+ break;
+ mpp = abbr_table;
+ }
+ else
+ mpp = &(map_table[hash]);
+ for (mp = *mpp; mp != NULL && !got_int; mp = *mpp)
+ {
+
+ if (!(mp->m_mode & mode)) /* skip entries with wrong mode */
+ {
+ mpp = &(mp->m_next);
+ continue;
+ }
+ if (!haskey) /* show all entries */
+ {
+ showmap(mp, map_table != maphash);
+ did_it = TRUE;
+ }
+ else /* do we have a match? */
+ {
+ if (round) /* second round: Try unmap "rhs" string */
+ {
+ n = (int)STRLEN(mp->m_str);
+ p = mp->m_str;
+ }
+ else
+ {
+ n = mp->m_keylen;
+ p = mp->m_keys;
+ }
+ if (STRNCMP(p, keys, (size_t)(n < len ? n : len)) == 0)
+ {
+ if (maptype == 1) /* delete entry */
+ {
+ /* Only accept a full match. For abbreviations we
+ * ignore trailing space when matching with the
+ * "lhs", since an abbreviation can't have
+ * trailing space. */
+ if (n != len && (!abbrev || round || n > len
+ || *skipwhite(keys + n) != NUL))
+ {
+ mpp = &(mp->m_next);
+ continue;
+ }
+ /*
+ * We reset the indicated mode bits. If nothing is
+ * left the entry is deleted below.
+ */
+ mp->m_mode &= ~mode;
+ did_it = TRUE; /* remember we did something */
+ }
+ else if (!hasarg) /* show matching entry */
+ {
+ showmap(mp, map_table != maphash);
+ did_it = TRUE;
+ }
+ else if (n != len) /* new entry is ambigious */
+ {
+ mpp = &(mp->m_next);
+ continue;
+ }
+ else if (unique)
+ {
+ if (abbrev)
+ EMSG2(_("E226: abbreviation already exists for %s"),
+ p);
+ else
+ EMSG2(_("E227: mapping already exists for %s"), p);
+ retval = 5;
+ goto theend;
+ }
+ else /* new rhs for existing entry */
+ {
+ mp->m_mode &= ~mode; /* remove mode bits */
+ if (mp->m_mode == 0 && !did_it) /* reuse entry */
+ {
+ newstr = vim_strsave(rhs);
+ if (newstr == NULL)
+ {
+ retval = 4; /* no mem */
+ goto theend;
+ }
+ vim_free(mp->m_str);
+ mp->m_str = newstr;
+ mp->m_noremap = noremap;
+ mp->m_silent = silent;
+ mp->m_mode = mode;
+ did_it = TRUE;
+ }
+ }
+ if (mp->m_mode == 0) /* entry can be deleted */
+ {
+ map_free(mpp);
+ continue; /* continue with *mpp */
+ }
+
+ /*
+ * May need to put this entry into another hash list.
+ */
+ new_hash = MAP_HASH(mp->m_mode, mp->m_keys[0]);
+ if (!abbrev && new_hash != hash)
+ {
+ *mpp = mp->m_next;
+ mp->m_next = map_table[new_hash];
+ map_table[new_hash] = mp;
+
+ continue; /* continue with *mpp */
+ }
+ }
+ }
+ mpp = &(mp->m_next);
+ }
+ }
+ }
+
+ if (maptype == 1) /* delete entry */
+ {
+ if (!did_it)
+ retval = 2; /* no match */
+ goto theend;
+ }
+
+ if (!haskey || !hasarg) /* print entries */
+ {
+ if (!did_it
+#ifdef FEAT_LOCALMAP
+ && !did_local
+#endif
+ )
+ {
+ if (abbrev)
+ MSG(_("No abbreviation found"));
+ else
+ MSG(_("No mapping found"));
+ }
+ goto theend; /* listing finished */
+ }
+
+ if (did_it) /* have added the new entry already */
+ goto theend;
+
+ /*
+ * Get here when adding a new entry to the maphash[] list or abbrlist.
+ */
+ mp = (mapblock_T *)alloc((unsigned)sizeof(mapblock_T));
+ if (mp == NULL)
+ {
+ retval = 4; /* no mem */
+ goto theend;
+ }
+
+ /* If CTRL-C has been mapped, don't always use it for Interrupting */
+ if (*keys == Ctrl_C)
+ mapped_ctrl_c = TRUE;
+
+ mp->m_keys = vim_strsave(keys);
+ mp->m_str = vim_strsave(rhs);
+ if (mp->m_keys == NULL || mp->m_str == NULL)
+ {
+ vim_free(mp->m_keys);
+ vim_free(mp->m_str);
+ vim_free(mp);
+ retval = 4; /* no mem */
+ goto theend;
+ }
+ mp->m_keylen = (int)STRLEN(mp->m_keys);
+ mp->m_noremap = noremap;
+ mp->m_silent = silent;
+ mp->m_mode = mode;
+
+ /* add the new entry in front of the abbrlist or maphash[] list */
+ if (abbrev)
+ {
+ mp->m_next = *abbr_table;
+ *abbr_table = mp;
+ }
+ else
+ {
+ n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
+ mp->m_next = map_table[n];
+ map_table[n] = mp;
+ }
+
+theend:
+ vim_free(keys_buf);
+ vim_free(arg_buf);
+ return retval;
+}
+
+/*
+ * Delete one entry from the abbrlist or maphash[].
+ * "mpp" is a pointer to the m_next field of the PREVIOUS entry!
+ */
+ static void
+map_free(mpp)
+ mapblock_T **mpp;
+{
+ mapblock_T *mp;
+
+ mp = *mpp;
+ vim_free(mp->m_keys);
+ vim_free(mp->m_str);
+ *mpp = mp->m_next;
+ vim_free(mp);
+}
+
+/*
+ * Initialize maphash[] for first use.
+ */
+ static void
+validate_maphash()
+{
+ if (!maphash_valid)
+ {
+ vim_memset(maphash, 0, sizeof(maphash));
+ maphash_valid = TRUE;
+ }
+}
+
+/*
+ * Get the mapping mode from the command name.
+ */
+ int
+get_map_mode(cmdp, forceit)
+ char_u **cmdp;
+ int forceit;
+{
+ char_u *p;
+ int modec;
+ int mode;
+
+ p = *cmdp;
+ modec = *p++;
+ if (modec == 'i')
+ mode = INSERT; /* :imap */
+ else if (modec == 'l')
+ mode = LANGMAP; /* :lmap */
+ else if (modec == 'c')
+ mode = CMDLINE; /* :cmap */
+ else if (modec == 'n' && *p != 'o') /* avoid :noremap */
+ mode = NORMAL; /* :nmap */
+ else if (modec == 'v')
+ mode = VISUAL; /* :vmap */
+ else if (modec == 'o')
+ mode = OP_PENDING; /* :omap */
+ else
+ {
+ --p;
+ if (forceit)
+ mode = INSERT + CMDLINE; /* :map ! */
+ else
+ mode = VISUAL + NORMAL + OP_PENDING;/* :map */
+ }
+
+ *cmdp = p;
+ return mode;
+}
+
+/*
+ * Clear all mappings or abbreviations.
+ * 'abbr' should be FALSE for mappings, TRUE for abbreviations.
+ */
+/*ARGSUSED*/
+ void
+map_clear(cmdp, arg, forceit, abbr)
+ char_u *cmdp;
+ char_u *arg;
+ int forceit;
+ int abbr;
+{
+ int mode;
+#ifdef FEAT_LOCALMAP
+ int local;
+
+ local = (STRCMP(arg, "<buffer>") == 0);
+ if (!local && *arg != NUL)
+ {
+ EMSG(_(e_invarg));
+ return;
+ }
+#endif
+
+ mode = get_map_mode(&cmdp, forceit);
+ map_clear_int(curbuf, mode,
+#ifdef FEAT_LOCALMAP
+ local,
+#else
+ FALSE,
+#endif
+ abbr);
+}
+
+/*
+ * Clear all mappings in "mode".
+ */
+/*ARGSUSED*/
+ void
+map_clear_int(buf, mode, local, abbr)
+ buf_T *buf; /* buffer for local mappings */
+ int mode; /* mode in which to delete */
+ int local; /* TRUE for buffer-local mappings */
+ int abbr; /* TRUE for abbreviations */
+{
+ mapblock_T *mp, **mpp;
+ int hash;
+ int new_hash;
+
+ validate_maphash();
+
+ for (hash = 0; hash < 256; ++hash)
+ {
+ if (abbr)
+ {
+ if (hash) /* there is only one abbrlist */
+ break;
+#ifdef FEAT_LOCALMAP
+ if (local)
+ mpp = &buf->b_first_abbr;
+ else
+#endif
+ mpp = &first_abbr;
+ }
+ else
+ {
+#ifdef FEAT_LOCALMAP
+ if (local)
+ mpp = &buf->b_maphash[hash];
+ else
+#endif
+ mpp = &maphash[hash];
+ }
+ while (*mpp != NULL)
+ {
+ mp = *mpp;
+ if (mp->m_mode & mode)
+ {
+ mp->m_mode &= ~mode;
+ if (mp->m_mode == 0) /* entry can be deleted */
+ {
+ map_free(mpp);
+ continue;
+ }
+ /*
+ * May need to put this entry into another hash list.
+ */
+ new_hash = MAP_HASH(mp->m_mode, mp->m_keys[0]);
+ if (!abbr && new_hash != hash)
+ {
+ *mpp = mp->m_next;
+#ifdef FEAT_LOCALMAP
+ if (local)
+ {
+ mp->m_next = buf->b_maphash[new_hash];
+ buf->b_maphash[new_hash] = mp;
+ }
+ else
+#endif
+ {
+ mp->m_next = maphash[new_hash];
+ maphash[new_hash] = mp;
+ }
+ continue; /* continue with *mpp */
+ }
+ }
+ mpp = &(mp->m_next);
+ }
+ }
+}
+
+ static void
+showmap(mp, local)
+ mapblock_T *mp;
+ int local; /* TRUE for buffer-local map */
+{
+ int len = 1;
+
+ if (msg_didout || msg_silent != 0)
+ msg_putchar('\n');
+ if ((mp->m_mode & (INSERT + CMDLINE)) == INSERT + CMDLINE)
+ msg_putchar('!'); /* :map! */
+ else if (mp->m_mode & INSERT)
+ msg_putchar('i'); /* :imap */
+ else if (mp->m_mode & LANGMAP)
+ msg_putchar('l'); /* :lmap */
+ else if (mp->m_mode & CMDLINE)
+ msg_putchar('c'); /* :cmap */
+ else if ((mp->m_mode & (NORMAL + VISUAL + OP_PENDING))
+ == NORMAL + VISUAL + OP_PENDING)
+ msg_putchar(' '); /* :map */
+ else
+ {
+ len = 0;
+ if (mp->m_mode & NORMAL)
+ {
+ msg_putchar('n'); /* :nmap */
+ ++len;
+ }
+ if (mp->m_mode & OP_PENDING)
+ {
+ msg_putchar('o'); /* :omap */
+ ++len;
+ }
+ if (mp->m_mode & VISUAL)
+ {
+ msg_putchar('v'); /* :vmap */
+ ++len;
+ }
+ }
+ while (++len <= 3)
+ msg_putchar(' ');
+
+ /* Get length of what we write */
+ len = msg_outtrans_special(mp->m_keys, TRUE);
+ do
+ {
+ msg_putchar(' '); /* padd with blanks */
+ ++len;
+ } while (len < 12);
+
+ if (mp->m_noremap == REMAP_NONE)
+ msg_puts_attr((char_u *)"*", hl_attr(HLF_8));
+ else if (mp->m_noremap == REMAP_SCRIPT)
+ msg_puts_attr((char_u *)"&", hl_attr(HLF_8));
+ else
+ msg_putchar(' ');
+
+ if (local)
+ msg_putchar('@');
+ else
+ msg_putchar(' ');
+
+ /* Use FALSE below if we only want things like <Up> to show up as such on
+ * the rhs, and not M-x etc, TRUE gets both -- webb
+ */
+ if (*mp->m_str == NUL)
+ msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8));
+ else
+ msg_outtrans_special(mp->m_str, FALSE);
+ out_flush(); /* show one line at a time */
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return TRUE if a map exists that has "str" in the rhs for mode "modechars".
+ * Recognize termcap codes in "str".
+ * Also checks mappings local to the current buffer.
+ */
+ int
+map_to_exists(str, modechars)
+ char_u *str;
+ char_u *modechars;
+{
+ int mode = 0;
+ char_u *rhs;
+ char_u *buf;
+ int retval;
+
+ rhs = replace_termcodes(str, &buf, FALSE, TRUE);
+
+ if (vim_strchr(modechars, 'n') != NULL)
+ mode |= NORMAL;
+ if (vim_strchr(modechars, 'v') != NULL)
+ mode |= VISUAL;
+ if (vim_strchr(modechars, 'o') != NULL)
+ mode |= OP_PENDING;
+ if (vim_strchr(modechars, 'i') != NULL)
+ mode |= INSERT;
+ if (vim_strchr(modechars, 'l') != NULL)
+ mode |= LANGMAP;
+ if (vim_strchr(modechars, 'c') != NULL)
+ mode |= CMDLINE;
+
+ retval = map_to_exists_mode(rhs, mode);
+ vim_free(buf);
+
+ return retval;
+}
+#endif
+
+/*
+ * Return TRUE if a map exists that has "str" in the rhs for mode "mode".
+ * Also checks mappings local to the current buffer.
+ */
+ int
+map_to_exists_mode(rhs, mode)
+ char_u *rhs;
+ int mode;
+{
+ mapblock_T *mp;
+ int hash;
+# ifdef FEAT_LOCALMAP
+ int expand_buffer = FALSE;
+
+ validate_maphash();
+
+ /* Do it twice: once for global maps and once for local maps. */
+ for (;;)
+ {
+# endif
+ for (hash = 0; hash < 256; ++hash)
+ {
+# ifdef FEAT_LOCALMAP
+ if (expand_buffer)
+ mp = curbuf->b_maphash[hash];
+ else
+# endif
+ mp = maphash[hash];
+ for (; mp; mp = mp->m_next)
+ {
+ if ((mp->m_mode & mode)
+ && strstr((char *)mp->m_str, (char *)rhs) != NULL)
+ return TRUE;
+ }
+ }
+# ifdef FEAT_LOCALMAP
+ if (expand_buffer)
+ break;
+ expand_buffer = TRUE;
+ }
+# endif
+
+ return FALSE;
+}
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+/*
+ * Used below when expanding mapping/abbreviation names.
+ */
+static int expand_mapmodes = 0;
+static int expand_isabbrev = 0;
+#ifdef FEAT_LOCALMAP
+static int expand_buffer = FALSE;
+#endif
+
+/*
+ * Work out what to complete when doing command line completion of mapping
+ * or abbreviation names.
+ */
+ char_u *
+set_context_in_map_cmd(xp, cmd, arg, forceit, isabbrev, isunmap, cmdidx)
+ expand_T *xp;
+ char_u *cmd;
+ char_u *arg;
+ int forceit; /* TRUE if '!' given */
+ int isabbrev; /* TRUE if abbreviation */
+ int isunmap; /* TRUE if unmap/unabbrev command */
+ cmdidx_T cmdidx;
+{
+ if (forceit && cmdidx != CMD_map && cmdidx != CMD_unmap)
+ xp->xp_context = EXPAND_NOTHING;
+ else
+ {
+ if (isunmap)
+ expand_mapmodes = get_map_mode(&cmd, forceit || isabbrev);
+ else
+ {
+ expand_mapmodes = INSERT + CMDLINE;
+ if (!isabbrev)
+ expand_mapmodes += VISUAL + NORMAL + OP_PENDING;
+ }
+ expand_isabbrev = isabbrev;
+ xp->xp_context = EXPAND_MAPPINGS;
+#ifdef FEAT_LOCALMAP
+ expand_buffer = FALSE;
+#endif
+ for (;;)
+ {
+#ifdef FEAT_LOCALMAP
+ if (STRNCMP(arg, "<buffer>", 8) == 0)
+ {
+ expand_buffer = TRUE;
+ arg = skipwhite(arg + 8);
+ continue;
+ }
+#endif
+ if (STRNCMP(arg, "<unique>", 8) == 0)
+ {
+ arg = skipwhite(arg + 8);
+ continue;
+ }
+ if (STRNCMP(arg, "<silent>", 8) == 0)
+ {
+ arg = skipwhite(arg + 8);
+ continue;
+ }
+ if (STRNCMP(arg, "<script>", 8) == 0)
+ {
+ arg = skipwhite(arg + 8);
+ continue;
+ }
+ break;
+ }
+ xp->xp_pattern = arg;
+ }
+
+ return NULL;
+}
+
+/*
+ * Find all mapping/abbreviation names that match regexp 'prog'.
+ * For command line expansion of ":[un]map" and ":[un]abbrev" in all modes.
+ * Return OK if matches found, FAIL otherwise.
+ */
+ int
+ExpandMappings(regmatch, num_file, file)
+ regmatch_T *regmatch;
+ int *num_file;
+ char_u ***file;
+{
+ mapblock_T *mp;
+ int hash;
+ int count;
+ int round;
+ char_u *p;
+ int i;
+
+ validate_maphash();
+
+ *num_file = 0; /* return values in case of FAIL */
+ *file = NULL;
+
+ /*
+ * round == 1: Count the matches.
+ * round == 2: Build the array to keep the matches.
+ */
+ for (round = 1; round <= 2; ++round)
+ {
+ count = 0;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == 0)
+ p = (char_u *)"<silent>";
+ else if (i == 1)
+ p = (char_u *)"<unique>";
+#ifdef FEAT_EVAL
+ else if (i == 2)
+ p = (char_u *)"<script>";
+#endif
+#ifdef FEAT_LOCALMAP
+ else if (i == 3 && !expand_buffer)
+ p = (char_u *)"<buffer>";
+#endif
+ else
+ continue;
+
+ if (vim_regexec(regmatch, p, (colnr_T)0))
+ {
+ if (round == 1)
+ ++count;
+ else
+ (*file)[count++] = vim_strsave(p);
+ }
+ }
+
+ for (hash = 0; hash < 256; ++hash)
+ {
+ if (expand_isabbrev)
+ {
+ if (hash) /* only one abbrev list */
+ break; /* for (hash) */
+ mp = first_abbr;
+ }
+#ifdef FEAT_LOCALMAP
+ else if (expand_buffer)
+ mp = curbuf->b_maphash[hash];
+#endif
+ else
+ mp = maphash[hash];
+ for (; mp; mp = mp->m_next)
+ {
+ if (mp->m_mode & expand_mapmodes)
+ {
+ p = translate_mapping(mp->m_keys, TRUE);
+ if (p != NULL && vim_regexec(regmatch, p, (colnr_T)0))
+ {
+ if (round == 1)
+ ++count;
+ else
+ {
+ (*file)[count++] = p;
+ p = NULL;
+ }
+ }
+ vim_free(p);
+ }
+ } /* for (mp) */
+ } /* for (hash) */
+
+ if (count == 0) /* no match found */
+ break; /* for (round) */
+
+ if (round == 1)
+ {
+ *file = (char_u **)alloc((unsigned)(count * sizeof(char_u *)));
+ if (*file == NULL)
+ return FAIL;
+ }
+ } /* for (round) */
+
+ /* Sort the matches */
+ sort_strings(*file, count);
+
+ /* Remove multiple entries */
+ {
+ char_u **ptr1 = *file;
+ char_u **ptr2 = ptr1 + 1;
+ char_u **ptr3 = ptr1 + count;
+
+ while (ptr2 < ptr3)
+ {
+ if (STRCMP(*ptr1, *ptr2))
+ *++ptr1 = *ptr2++;
+ else
+ {
+ vim_free(*ptr2++);
+ count--;
+ }
+ }
+ }
+
+ *num_file = count;
+ return (count == 0 ? FAIL : OK);
+}
+#endif /* FEAT_CMDL_COMPL */
+
+/*
+ * Check for an abbreviation.
+ * Cursor is at ptr[col]. When inserting, mincol is where insert started.
+ * "c" is the character typed before check_abbr was called. It may have
+ * ABBR_OFF added to avoid prepending a CTRL-V to it.
+ *
+ * Historic vi practice: The last character of an abbreviation must be an id
+ * character ([a-zA-Z0-9_]). The characters in front of it must be all id
+ * characters or all non-id characters. This allows for abbr. "#i" to
+ * "#include".
+ *
+ * Vim addition: Allow for abbreviations that end in a non-keyword character.
+ * Then there must be white space before the abbr.
+ *
+ * return TRUE if there is an abbreviation, FALSE if not
+ */
+ int
+check_abbr(c, ptr, col, mincol)
+ int c;
+ char_u *ptr;
+ int col;
+ int mincol;
+{
+ int len;
+ int scol; /* starting column of the abbr. */
+ int j;
+#ifdef FEAT_MBYTE
+ char_u tb[MB_MAXBYTES + 4];
+#else
+ char_u tb[4];
+#endif
+ mapblock_T *mp;
+#ifdef FEAT_LOCALMAP
+ mapblock_T *mp2;
+#endif
+#ifdef FEAT_MBYTE
+ int clen = 0; /* length in characters */
+#endif
+ int is_id = TRUE;
+ int vim_abbr;
+
+ if (typebuf.tb_no_abbr_cnt) /* abbrev. are not recursive */
+ return FALSE;
+ if (KeyNoremap) /* no remapping implies no abbreviation */
+ return FALSE;
+
+ /*
+ * Check for word before the cursor: If it ends in a keyword char all
+ * chars before it must be al keyword chars or non-keyword chars, but not
+ * white space. If it ends in a non-keyword char we accept any characters
+ * before it except white space.
+ */
+ if (col == 0) /* cannot be an abbr. */
+ return FALSE;
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ char_u *p;
+
+ p = mb_prevptr(ptr, ptr + col);
+ if (!vim_iswordp(p))
+ vim_abbr = TRUE; /* Vim added abbr. */
+ else
+ {
+ vim_abbr = FALSE; /* vi compatible abbr. */
+ if (p > ptr)
+ is_id = vim_iswordp(mb_prevptr(ptr, p));
+ }
+ clen = 1;
+ while (p > ptr + mincol)
+ {
+ p = mb_prevptr(ptr, p);
+ if (vim_isspace(*p) || (!vim_abbr && is_id != vim_iswordp(p)))
+ {
+ p += (*mb_ptr2len_check)(p);
+ break;
+ }
+ ++clen;
+ }
+ scol = (int)(p - ptr);
+ }
+ else
+#endif
+ {
+ if (!vim_iswordc(ptr[col - 1]))
+ vim_abbr = TRUE; /* Vim added abbr. */
+ else
+ {
+ vim_abbr = FALSE; /* vi compatible abbr. */
+ if (col > 1)
+ is_id = vim_iswordc(ptr[col - 2]);
+ }
+ for (scol = col - 1; scol > 0 && !vim_isspace(ptr[scol - 1])
+ && (vim_abbr || is_id == vim_iswordc(ptr[scol - 1])); --scol)
+ ;
+ }
+
+ if (scol < mincol)
+ scol = mincol;
+ if (scol < col) /* there is a word in front of the cursor */
+ {
+ ptr += scol;
+ len = col - scol;
+#ifdef FEAT_LOCALMAP
+ mp = curbuf->b_first_abbr;
+ mp2 = first_abbr;
+ if (mp == NULL)
+ {
+ mp = mp2;
+ mp2 = NULL;
+ }
+#else
+ mp = first_abbr;
+#endif
+ for ( ; mp;
+#ifdef FEAT_LOCALMAP
+ mp->m_next == NULL ? (mp = mp2, mp2 = NULL) :
+#endif
+ (mp = mp->m_next))
+ {
+ /* find entries with right mode and keys */
+ if ( (mp->m_mode & State)
+ && mp->m_keylen == len
+ && !STRNCMP(mp->m_keys, ptr, (size_t)len))
+ break;
+ }
+ if (mp != NULL)
+ {
+ /*
+ * Found a match:
+ * Insert the rest of the abbreviation in typebuf.tb_buf[].
+ * This goes from end to start.
+ *
+ * Characters 0x000 - 0x100: normal chars, may need CTRL-V,
+ * except K_SPECIAL: Becomes K_SPECIAL KS_SPECIAL KE_FILLER
+ * Characters where IS_SPECIAL() == TRUE: key codes, need
+ * K_SPECIAL. Other characters (with ABBR_OFF): don't use CTRL-V.
+ *
+ * Character CTRL-] is treated specially - it completes the
+ * abbreviation, but is not inserted into the input stream.
+ */
+ j = 0;
+ /* special key code, split up */
+ if (c != Ctrl_RSB)
+ {
+ if (IS_SPECIAL(c) || c == K_SPECIAL)
+ {
+ tb[j++] = K_SPECIAL;
+ tb[j++] = K_SECOND(c);
+ tb[j++] = K_THIRD(c);
+ }
+ else
+ {
+ if (c < ABBR_OFF && (c < ' ' || c > '~'))
+ tb[j++] = Ctrl_V; /* special char needs CTRL-V */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ /* if ABBR_OFF has been added, remove it here */
+ if (c >= ABBR_OFF)
+ c -= ABBR_OFF;
+ j += (*mb_char2bytes)(c, tb + j);
+ }
+ else
+#endif
+ tb[j++] = c;
+ }
+ tb[j] = NUL;
+ /* insert the last typed char */
+ (void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent);
+ }
+ /* insert the to string */
+ (void)ins_typebuf(mp->m_str, mp->m_noremap, 0, TRUE, mp->m_silent);
+ /* no abbrev. for these chars */
+ typebuf.tb_no_abbr_cnt += (int)STRLEN(mp->m_str) + j + 1;
+
+ tb[0] = Ctrl_H;
+ tb[1] = NUL;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ len = clen; /* Delete characters instead of bytes */
+#endif
+ while (len-- > 0) /* delete the from string */
+ (void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * Write map commands for the current mappings to an .exrc file.
+ * Return FAIL on error, OK otherwise.
+ */
+ int
+makemap(fd, buf)
+ FILE *fd;
+ buf_T *buf; /* buffer for local mappings or NULL */
+{
+ mapblock_T *mp;
+ char_u c1, c2;
+ char_u *p;
+ char *cmd;
+ int abbr;
+ int hash;
+ int did_cpo = FALSE;
+ int i;
+
+ validate_maphash();
+
+ /*
+ * Do the loop twice: Once for mappings, once for abbreviations.
+ * Then loop over all map hash lists.
+ */
+ for (abbr = 0; abbr < 2; ++abbr)
+ for (hash = 0; hash < 256; ++hash)
+ {
+ if (abbr)
+ {
+ if (hash) /* there is only one abbr list */
+ break;
+#ifdef FEAT_LOCALMAP
+ if (buf != NULL)
+ mp = buf->b_first_abbr;
+ else
+#endif
+ mp = first_abbr;
+ }
+ else
+ {
+#ifdef FEAT_LOCALMAP
+ if (buf != NULL)
+ mp = buf->b_maphash[hash];
+ else
+#endif
+ mp = maphash[hash];
+ }
+
+ for ( ; mp; mp = mp->m_next)
+ {
+ /* skip script-local mappings */
+ if (mp->m_noremap == REMAP_SCRIPT)
+ continue;
+
+ /* skip mappings that contain a <SNR> (script-local thing),
+ * they probably don't work when loaded again */
+ for (p = mp->m_str; *p != NUL; ++p)
+ if (p[0] == K_SPECIAL && p[1] == KS_EXTRA
+ && p[2] == (int)KE_SNR)
+ break;
+ if (*p != NUL)
+ continue;
+
+ c1 = NUL;
+ c2 = NUL;
+ if (abbr)
+ cmd = "abbr";
+ else
+ cmd = "map";
+ switch (mp->m_mode)
+ {
+ case NORMAL + VISUAL + OP_PENDING:
+ break;
+ case NORMAL:
+ c1 = 'n';
+ break;
+ case VISUAL:
+ c1 = 'v';
+ break;
+ case OP_PENDING:
+ c1 = 'o';
+ break;
+ case NORMAL + VISUAL:
+ c1 = 'n';
+ c2 = 'v';
+ break;
+ case VISUAL + OP_PENDING:
+ c1 = 'v';
+ c2 = 'o';
+ break;
+ case NORMAL + OP_PENDING:
+ c1 = 'n';
+ c2 = 'o';
+ break;
+ case CMDLINE + INSERT:
+ if (!abbr)
+ cmd = "map!";
+ break;
+ case CMDLINE:
+ c1 = 'c';
+ break;
+ case INSERT:
+ c1 = 'i';
+ break;
+ case LANGMAP:
+ c1 = 'l';
+ break;
+ default:
+ EMSG(_("E228: makemap: Illegal mode"));
+ return FAIL;
+ }
+ do /* may do this twice if c2 is set */
+ {
+ /* When outputting <> form, need to make sure that 'cpo'
+ * is set to the Vim default. */
+ if (!did_cpo)
+ {
+ if (*mp->m_str == NUL) /* will use <Nop> */
+ did_cpo = TRUE;
+ else
+ for (i = 0; i < 2; ++i)
+ for (p = (i ? mp->m_str : mp->m_keys); *p; ++p)
+ if (*p == K_SPECIAL || *p == NL)
+ did_cpo = TRUE;
+ if (did_cpo)
+ {
+ if (fprintf(fd, "let s:cpo_save=&cpo") < 0
+ || put_eol(fd) < 0
+ || fprintf(fd, "set cpo&vim") < 0
+ || put_eol(fd) < 0)
+ return FAIL;
+ }
+ }
+ if (c1 && putc(c1, fd) < 0)
+ return FAIL;
+ if (mp->m_noremap != REMAP_YES && fprintf(fd, "nore") < 0)
+ return FAIL;
+ if (fprintf(fd, cmd) < 0)
+ return FAIL;
+ if (buf != NULL && fputs(" <buffer>", fd) < 0)
+ return FAIL;
+ if (mp->m_silent && fputs(" <silent>", fd) < 0)
+ return FAIL;
+
+ if ( putc(' ', fd) < 0
+ || put_escstr(fd, mp->m_keys, 0) == FAIL
+ || putc(' ', fd) < 0
+ || put_escstr(fd, mp->m_str, 1) == FAIL
+ || put_eol(fd) < 0)
+ return FAIL;
+ c1 = c2;
+ c2 = NUL;
+ }
+ while (c1);
+ }
+ }
+
+ if (did_cpo)
+ if (fprintf(fd, "let &cpo=s:cpo_save") < 0
+ || put_eol(fd) < 0
+ || fprintf(fd, "unlet s:cpo_save") < 0
+ || put_eol(fd) < 0)
+ return FAIL;
+ return OK;
+}
+
+/*
+ * write escape string to file
+ * "what": 0 for :map lhs, 1 for :map rhs, 2 for :set
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+put_escstr(fd, strstart, what)
+ FILE *fd;
+ char_u *strstart;
+ int what;
+{
+ char_u *str = strstart;
+ int c;
+ int modifiers;
+
+ /* :map xx <Nop> */
+ if (*str == NUL && what == 1)
+ {
+ if (fprintf(fd, "<Nop>") < 0)
+ return FAIL;
+ return OK;
+ }
+
+ for ( ; *str != NUL; ++str)
+ {
+#ifdef FEAT_MBYTE
+ char_u *p;
+
+ /* Check for a multi-byte character, which may contain escaped
+ * K_SPECIAL and CSI bytes */
+ p = mb_unescape(&str);
+ if (p != NULL)
+ {
+ while (*p != NUL)
+ if (putc(*p++, fd) < 0)
+ return FAIL;
+ --str;
+ continue;
+ }
+#endif
+
+ c = *str;
+ /*
+ * Special key codes have to be translated to be able to make sense
+ * when they are read back.
+ */
+ if (c == K_SPECIAL && what != 2)
+ {
+ modifiers = 0x0;
+ if (str[1] == KS_MODIFIER)
+ {
+ modifiers = str[2];
+ str += 3;
+ c = *str;
+ }
+ if (c == K_SPECIAL)
+ {
+ c = TO_SPECIAL(str[1], str[2]);
+ str += 2;
+ }
+ if (IS_SPECIAL(c) || modifiers) /* special key */
+ {
+ if (fprintf(fd, (char *)get_special_key_name(c, modifiers)) < 0)
+ return FAIL;
+ continue;
+ }
+ }
+
+ /*
+ * A '\n' in a map command should be written as <NL>.
+ * A '\n' in a set command should be written as \^V^J.
+ */
+ if (c == NL)
+ {
+ if (what == 2)
+ {
+ if (fprintf(fd, IF_EB("\\\026\n", "\\" CTRL_V_STR "\n")) < 0)
+ return FAIL;
+ }
+ else
+ {
+ if (fprintf(fd, "<NL>") < 0)
+ return FAIL;
+ }
+ continue;
+ }
+
+ /*
+ * Some characters have to be escaped with CTRL-V to
+ * prevent them from misinterpreted in DoOneCmd().
+ * A space, Tab and '"' has to be escaped with a backslash to
+ * prevent it to be misinterpreted in do_set().
+ * A space has to be escaped with a CTRL-V when it's at the start of a
+ * ":map" rhs.
+ * A '<' has to be escaped with a CTRL-V to prevent it being
+ * interpreted as the start of a special key name.
+ * A space in the lhs of a :map needs a CTRL-V.
+ */
+ if (what == 2 && (vim_iswhite(c) || c == '"' || c == '\\'))
+ {
+ if (putc('\\', fd) < 0)
+ return FAIL;
+ }
+ else if (c < ' ' || c > '~' || c == '|'
+ || (what == 0 && c == ' ')
+ || (what == 1 && str == strstart && c == ' ')
+ || (what != 2 && c == '<'))
+ {
+ if (putc(Ctrl_V, fd) < 0)
+ return FAIL;
+ }
+ if (putc(c, fd) < 0)
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
+ * Check all mappings for the presence of special key codes.
+ * Used after ":set term=xxx".
+ */
+ void
+check_map_keycodes()
+{
+ mapblock_T *mp;
+ char_u *p;
+ int i;
+ char_u buf[3];
+ char_u *save_name;
+ int abbr;
+ int hash;
+#ifdef FEAT_LOCALMAP
+ buf_T *bp;
+#endif
+
+ validate_maphash();
+ save_name = sourcing_name;
+ sourcing_name = (char_u *)"mappings"; /* avoids giving error messages */
+
+#ifdef FEAT_LOCALMAP
+ /* This this once for each buffer, and then once for global
+ * mappings/abbreviations with bp == NULL */
+ for (bp = firstbuf; ; bp = bp->b_next)
+ {
+#endif
+ /*
+ * Do the loop twice: Once for mappings, once for abbreviations.
+ * Then loop over all map hash lists.
+ */
+ for (abbr = 0; abbr <= 1; ++abbr)
+ for (hash = 0; hash < 256; ++hash)
+ {
+ if (abbr)
+ {
+ if (hash) /* there is only one abbr list */
+ break;
+#ifdef FEAT_LOCALMAP
+ if (bp != NULL)
+ mp = bp->b_first_abbr;
+ else
+#endif
+ mp = first_abbr;
+ }
+ else
+ {
+#ifdef FEAT_LOCALMAP
+ if (bp != NULL)
+ mp = bp->b_maphash[hash];
+ else
+#endif
+ mp = maphash[hash];
+ }
+ for ( ; mp != NULL; mp = mp->m_next)
+ {
+ for (i = 0; i <= 1; ++i) /* do this twice */
+ {
+ if (i == 0)
+ p = mp->m_keys; /* once for the "from" part */
+ else
+ p = mp->m_str; /* and once for the "to" part */
+ while (*p)
+ {
+ if (*p == K_SPECIAL)
+ {
+ ++p;
+ if (*p < 128) /* for "normal" tcap entries */
+ {
+ buf[0] = p[0];
+ buf[1] = p[1];
+ buf[2] = NUL;
+ (void)add_termcap_entry(buf, FALSE);
+ }
+ ++p;
+ }
+ ++p;
+ }
+ }
+ }
+ }
+#ifdef FEAT_LOCALMAP
+ if (bp == NULL)
+ break;
+ }
+#endif
+ sourcing_name = save_name;
+}
+
+#ifdef FEAT_EVAL
+/*
+ * Check the string "keys" against the lhs of all mappings
+ * Return pointer to rhs of mapping (mapblock->m_str)
+ * NULL otherwise
+ */
+ char_u *
+check_map(keys, mode, exact)
+ char_u *keys;
+ int mode;
+ int exact; /* require exact match */
+{
+ int hash;
+ int len, minlen;
+ mapblock_T *mp;
+#ifdef FEAT_LOCALMAP
+ int local;
+#endif
+
+ validate_maphash();
+
+ len = (int)STRLEN(keys);
+#ifdef FEAT_LOCALMAP
+ for (local = 1; local >= 0; --local)
+#endif
+ /* loop over all hash lists */
+ for (hash = 0; hash < 256; ++hash)
+ {
+#ifdef FEAT_LOCALMAP
+ if (local)
+ mp = curbuf->b_maphash[hash];
+ else
+#endif
+ mp = maphash[hash];
+ for ( ; mp != NULL; mp = mp->m_next)
+ {
+ /* skip entries with wrong mode, wrong length and not matching
+ * ones */
+ if (mp->m_keylen < len)
+ minlen = mp->m_keylen;
+ else
+ minlen = len;
+ if ((mp->m_mode & mode)
+ && (!exact || mp->m_keylen == len)
+ && STRNCMP(mp->m_keys, keys, minlen) == 0)
+ return mp->m_str;
+ }
+ }
+
+ return NULL;
+}
+#endif
+
+/*
+ * Default mappings for some often used keys.
+ */
+static struct initmap
+{
+ char_u *arg;
+ int mode;
+} initmappings[] =
+{
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
+ /* Use the Windows (CUA) keybindings. */
+# ifdef FEAT_GUI
+ {(char_u *)"<C-PageUp> H", NORMAL+VISUAL},
+ {(char_u *)"<C-PageUp> <C-O>H",INSERT},
+ {(char_u *)"<C-PageDown> L$", NORMAL+VISUAL},
+ {(char_u *)"<C-PageDown> <C-O>L<C-O>$", INSERT},
+
+ /* paste, copy and cut */
+ {(char_u *)"<S-Insert> \"*P", NORMAL},
+ {(char_u *)"<S-Insert> \"-d\"*P", VISUAL},
+ {(char_u *)"<S-Insert> <C-R><C-O>*", INSERT+CMDLINE},
+ {(char_u *)"<C-Insert> \"*y", VISUAL},
+ {(char_u *)"<S-Del> \"*d", VISUAL},
+ {(char_u *)"<C-Del> \"*d", VISUAL},
+ {(char_u *)"<C-X> \"*d", VISUAL},
+ /* Missing: CTRL-C (cancel) and CTRL-V (block selection) */
+# else
+ {(char_u *)"\316\204 H", NORMAL+VISUAL}, /* CTRL-PageUp is "H" */
+ {(char_u *)"\316\204 \017H",INSERT}, /* CTRL-PageUp is "^OH"*/
+ {(char_u *)"\316v L$", NORMAL+VISUAL}, /* CTRL-PageDown is "L$" */
+ {(char_u *)"\316v \017L\017$", INSERT}, /* CTRL-PageDown ="^OL^O$"*/
+ {(char_u *)"\316w <C-Home>", NORMAL+VISUAL},
+ {(char_u *)"\316w <C-Home>", INSERT+CMDLINE},
+ {(char_u *)"\316u <C-End>", NORMAL+VISUAL},
+ {(char_u *)"\316u <C-End>", INSERT+CMDLINE},
+
+ /* paste, copy and cut */
+# ifdef FEAT_CLIPBOARD
+# ifdef DJGPP
+ {(char_u *)"\316\122 \"*P", NORMAL}, /* SHIFT-Insert is "*P */
+ {(char_u *)"\316\122 \"-d\"*P", VISUAL}, /* SHIFT-Insert is "-d"*P */
+ {(char_u *)"\316\122 \022\017*", INSERT}, /* SHIFT-Insert is ^R^O* */
+ {(char_u *)"\316\222 \"*y", VISUAL}, /* CTRL-Insert is "*y */
+# if 0 /* Shift-Del produces the same code as Del */
+ {(char_u *)"\316\123 \"*d", VISUAL}, /* SHIFT-Del is "*d */
+# endif
+ {(char_u *)"\316\223 \"*d", VISUAL}, /* CTRL-Del is "*d */
+ {(char_u *)"\030 \"-d", VISUAL}, /* CTRL-X is "-d */
+# else
+ {(char_u *)"\316\324 \"*P", NORMAL}, /* SHIFT-Insert is "*P */
+ {(char_u *)"\316\324 \"-d\"*P", VISUAL}, /* SHIFT-Insert is "-d"*P */
+ {(char_u *)"\316\324 \022\017*", INSERT}, /* SHIFT-Insert is ^R^O* */
+ {(char_u *)"\316\325 \"*y", VISUAL}, /* CTRL-Insert is "*y */
+ {(char_u *)"\316\327 \"*d", VISUAL}, /* SHIFT-Del is "*d */
+ {(char_u *)"\316\330 \"*d", VISUAL}, /* CTRL-Del is "*d */
+ {(char_u *)"\030 \"-d", VISUAL}, /* CTRL-X is "-d */
+# endif
+# else
+ {(char_u *)"\316\324 P", NORMAL}, /* SHIFT-Insert is P */
+ {(char_u *)"\316\324 \"-dP", VISUAL}, /* SHIFT-Insert is "-dP */
+ {(char_u *)"\316\324 \022\017\"", INSERT}, /* SHIFT-Insert is ^R^O" */
+ {(char_u *)"\316\325 y", VISUAL}, /* CTRL-Insert is y */
+ {(char_u *)"\316\327 d", VISUAL}, /* SHIFT-Del is d */
+ {(char_u *)"\316\330 d", VISUAL}, /* CTRL-Del is d */
+# endif
+# endif
+#endif
+
+#if defined(MACOS)
+ /* Use the Standard MacOS binding. */
+ /* paste, copy and cut */
+ {(char_u *)"<D-v> \"*P", NORMAL},
+ {(char_u *)"<D-v> \"-d\"*P", VISUAL},
+ {(char_u *)"<D-v> <C-R>*", INSERT+CMDLINE},
+ {(char_u *)"<D-c> \"*y", VISUAL},
+ {(char_u *)"<D-x> \"*d", VISUAL},
+ {(char_u *)"<Backspace> \"-d", VISUAL},
+#endif
+
+ /* Map extra keys to their normal equivalents. */
+ {(char_u *)"<xF1> <F1>", NORMAL+VISUAL+OP_PENDING},
+ {(char_u *)"<xF1> <F1>", INSERT+CMDLINE},
+ {(char_u *)"<xF2> <F2>", NORMAL+VISUAL+OP_PENDING},
+ {(char_u *)"<xF2> <F2>", INSERT+CMDLINE},
+ {(char_u *)"<xF3> <F3>", NORMAL+VISUAL+OP_PENDING},
+ {(char_u *)"<xF3> <F3>", INSERT+CMDLINE},
+ {(char_u *)"<xF4> <F4>", NORMAL+VISUAL+OP_PENDING},
+ {(char_u *)"<xF4> <F4>", INSERT+CMDLINE},
+ {(char_u *)"<S-xF1> <S-F1>", NORMAL+VISUAL+OP_PENDING},
+ {(char_u *)"<S-xF1> <S-F1>", INSERT+CMDLINE},
+ {(char_u *)"<S-xF2> <S-F2>", NORMAL+VISUAL+OP_PENDING},
+ {(char_u *)"<S-xF2> <S-F2>", INSERT+CMDLINE},
+ {(char_u *)"<S-xF3> <S-F3>", NORMAL+VISUAL+OP_PENDING},
+ {(char_u *)"<S-xF3> <S-F3>", INSERT+CMDLINE},
+ {(char_u *)"<S-xF4> <S-F4>", NORMAL+VISUAL+OP_PENDING},
+ {(char_u *)"<S-xF4> <S-F4>", INSERT+CMDLINE},
+ {(char_u *)"<xEND> <END>", NORMAL+VISUAL+OP_PENDING},
+ {(char_u *)"<xEND> <END>", INSERT+CMDLINE},
+ {(char_u *)"<xHOME> <HOME>", NORMAL+VISUAL+OP_PENDING},
+ {(char_u *)"<xHOME> <HOME>", INSERT+CMDLINE},
+};
+
+/*
+ * Set up default mappings.
+ */
+ void
+init_mappings()
+{
+ int i;
+
+ for (i = 0; i < sizeof(initmappings) / sizeof(struct initmap); ++i)
+ add_map(initmappings[i].arg, initmappings[i].mode);
+}
+
+/*
+ * Add a mapping "map" for mode "mode".
+ * Need to put string in allocated memory, because do_map() will modify it.
+ */
+ void
+add_map(map, mode)
+ char_u *map;
+ int mode;
+{
+ char_u *s;
+ char_u *cpo_save = p_cpo;
+
+ p_cpo = (char_u *)""; /* Allow <> notation */
+ s = vim_strsave(map);
+ if (s != NULL)
+ {
+ (void)do_map(0, s, mode, FALSE);
+ vim_free(s);
+ }
+ p_cpo = cpo_save;
+}
diff --git a/src/glbl_ime.cpp b/src/glbl_ime.cpp
new file mode 100644
index 000000000..f42a218fc
--- /dev/null
+++ b/src/glbl_ime.cpp
@@ -0,0 +1,261 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * DESCRIPTION:
+ * This module produces Global IME for Vim, on Windows with Internet
+ * Explorer 5.01 or higher. You need three files "dimm.idl", "dimm.h", and
+ * "dimm_i.c" when compile this module at your self. "dimm.h", and
+ * "dimm_i.c" are generated from "dimm.idl" by using MIDL.EXE as like
+ * "if_ole.h". You can get "dimm.idl" in MSDN web site. I got it below
+ * URL.
+ *
+ * WHAT IS THE GLOBAL IME?:
+ * Global IME makes capability input Chinese, Japanese, and Korean text into
+ * Vim buffer on any language version of Windows 98, Windows 95, and Windows
+ * NT 4.0. See below URL for detail of Global IME. You can also find
+ * various laguage version of Global IME at same place.
+ *
+ * RUNTIME REQUIREMENTS:
+ * - Internet Exproler 5.01 or higher.
+ * - Global IME (with language pack?).
+ * - Of course Vim for Windows.
+ *
+ * URLS:
+ * - Where you can probably get "dimm.idl".
+ * http://msdn.microsoft.com/downloads/samples/internet/libraries/ie5_lib/sample.asp
+ * - Global IME detailed information.
+ * http://www.microsoft.com/windows/ie/features/ime.asp
+ */
+
+#ifdef GLOBAL_IME
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <objbase.h>
+extern "C" {
+#include "vim.h"
+}
+#include "dimm.h"
+#include "glbl_ime.h"
+
+static IActiveIMMApp *pIApp = NULL;
+static IActiveIMMMessagePumpOwner *pIMsg = NULL;
+static HWND s_hWnd = NULL;
+static BOOL s_bStatus = FALSE; /* for evacuate */
+
+/*
+ * Initialize Global IME.
+ * "atom" must be return value of RegisterClass(Ex).
+ */
+ void
+global_ime_init(ATOM atom, HWND hWnd)
+{
+ IUnknown *pI;
+ HRESULT hr;
+
+ if (pIApp != NULL || pIMsg != NULL)
+ return;
+ OleInitialize(NULL);
+
+ /*
+ * Get interface IUnknown
+ */
+ hr = CoCreateInstance(CLSID_CActiveIMM, NULL, CLSCTX_SERVER,
+ IID_IUnknown, (void**)&pI);
+ if (FAILED(hr) || !pI)
+ return;
+
+ /*
+ * Get interface IActiveIMMApp
+ */
+ hr = pI->QueryInterface(IID_IActiveIMMApp, (void**)&pIApp);
+ if (FAILED(hr))
+ pIApp = NULL;
+
+ /*
+ * Get interface IActiveIMMMessagePumpOwner
+ */
+ hr = pI->QueryInterface(IID_IActiveIMMMessagePumpOwner, (void**)&pIMsg);
+ if (FAILED(hr))
+ pIMsg = NULL;
+
+ if (pIApp != NULL)
+ {
+ pIApp->Activate(TRUE);
+ pIApp->FilterClientWindows(&atom, 1);
+ }
+ if (pIMsg != NULL)
+ pIMsg->Start();
+
+ pI->Release();
+ s_hWnd = hWnd;
+}
+
+/*
+ * Reset and clear Global IME.
+ */
+ void
+global_ime_end()
+{
+ if (pIApp != NULL)
+ {
+ IActiveIMMApp *p = pIApp;
+
+ pIApp = NULL;
+ p->FilterClientWindows(NULL, 0);
+ p->Deactivate();
+ p->Release();
+ }
+ if (pIMsg != NULL)
+ {
+ IActiveIMMMessagePumpOwner *p = pIMsg;
+
+ pIMsg = NULL;
+ p->End();
+ p->Release();
+ }
+ OleUninitialize();
+}
+
+/*
+ * Replacement for DefWindowProc().
+ */
+ LRESULT WINAPI
+global_ime_DefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT lResult;
+
+ if (pIApp == NULL || pIApp->OnDefWindowProc(hWnd, Msg,
+ wParam, lParam, &lResult) != S_OK)
+ {
+#if defined(WIN3264) && defined(FEAT_MBYTE)
+ if (wide_WindowProc)
+ lResult = DefWindowProcW(hwnd, Msg, wParam, lParam);
+ else
+#endif
+ lResult = DefWindowProc(hWnd, Msg, wParam, lParam);
+ }
+ return lResult;
+}
+
+/*
+ * Replace with TranslateMessage()
+ */
+ BOOL WINAPI
+global_ime_TranslateMessage(CONST MSG *lpMsg)
+{
+ if (pIMsg == NULL || pIMsg->OnTranslateMessage(lpMsg) == S_FALSE)
+ return TranslateMessage(lpMsg);
+ return TRUE;
+}
+
+/*
+ * Set position of IME compotision window.
+ *
+ * You have to call this before starting composition. If once composition
+ * started, this can take no effect until that composition have finised. So
+ * you should handle WM_IME_STARTCOMPOSITION and call this function.
+ */
+ void WINAPI
+global_ime_set_position(POINT *pPoint)
+{
+ HIMC hImc = NULL;
+
+ if (pIApp == NULL || pPoint == NULL)
+ return;
+
+ if (SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
+ {
+ COMPOSITIONFORM CompForm;
+
+ CompForm.dwStyle = CFS_POINT;
+ CompForm.ptCurrentPos = *pPoint;
+ pIApp->SetCompositionWindow(hImc, &CompForm);
+ pIApp->ReleaseContext(s_hWnd, hImc);
+ }
+}
+
+/*
+ * Set font to Global IME
+ */
+/* GIME_TEST */
+ void WINAPI
+global_ime_set_font(LOGFONT *pFont)
+{
+ HIMC hImc = NULL;
+
+ if (pIApp == NULL || pFont == NULL)
+ return;
+
+ if (SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
+ {
+ pIApp->SetCompositionFontA(hImc, pFont);
+ pIApp->ReleaseContext(s_hWnd, hImc);
+ }
+}
+
+/*
+ * for IME control. Save current status of IME, and set force new-status to
+ * Engllish (turn off).
+ */
+ void WINAPI
+global_ime_status_evacuate()
+{
+ HIMC hImc;
+
+ if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
+ {
+ s_bStatus = (pIApp->GetOpenStatus(hImc) == 0) ? TRUE : FALSE;
+ pIApp->SetOpenStatus(hImc, FALSE);
+ pIApp->ReleaseContext(s_hWnd, hImc);
+ }
+}
+
+/*
+ * for IME control. Change IME status to last saved one.
+ */
+ void WINAPI
+global_ime_status_restore()
+{
+ HIMC hImc;
+
+ if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
+ {
+ pIApp->SetOpenStatus(hImc, s_bStatus);
+ pIApp->ReleaseContext(s_hWnd, hImc);
+ }
+}
+
+ void WINAPI
+global_ime_set_status(int status)
+{
+ HIMC hImc;
+
+ if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
+ {
+ pIApp->SetOpenStatus(hImc, status ? TRUE : FALSE);
+ pIApp->ReleaseContext(s_hWnd, hImc);
+ }
+}
+
+ int WINAPI
+global_ime_get_status()
+{
+ int status = 0;
+ HIMC hImc;
+
+ if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
+ {
+ status = pIApp->GetOpenStatus(hImc) ? 1 : 0;
+ pIApp->ReleaseContext(s_hWnd, hImc);
+ }
+ return status;
+}
+
+#endif /* GLOBAL_IME */
diff --git a/src/glbl_ime.h b/src/glbl_ime.h
new file mode 100644
index 000000000..85088366f
--- /dev/null
+++ b/src/glbl_ime.h
@@ -0,0 +1,31 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+#ifdef GLOBAL_IME
+#ifndef _INC_GLOBAL_IME
+#define _INC_GLOBAL_IME
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+ void global_ime_init(ATOM, HWND);
+ void global_ime_end();
+ LRESULT WINAPI global_ime_DefWindowProc(HWND, UINT, WPARAM, LPARAM);
+ BOOL WINAPI global_ime_TranslateMessage(CONST MSG *);
+ void WINAPI global_ime_set_position(POINT*);
+ void WINAPI global_ime_set_font(LOGFONT*);
+ void WINAPI global_ime_status_evacuate();
+ void WINAPI global_ime_status_restore();
+ void WINAPI global_ime_set_status(int status);
+ int WINAPI global_ime_get_status();
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _INC_GLOBAL_IME */
+#endif /* GLOBAL_IME */
diff --git a/src/globals.h b/src/globals.h
new file mode 100644
index 000000000..6f53317a6
--- /dev/null
+++ b/src/globals.h
@@ -0,0 +1,1381 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * definition of global variables
+ */
+
+/*
+ * Number of Rows and Columns in the screen.
+ * Must be long to be able to use them as options in option.c.
+ * Note: Use screen_Rows and screen_Columns to access items in ScreenLines[].
+ * They may have different values when the screen wasn't (re)allocated yet
+ * after setting Rows or Columns (e.g., when starting up).
+ */
+EXTERN long Rows /* nr of rows in the screen */
+#ifdef DO_INIT
+# if defined(MSDOS) || defined(WIN3264) || defined(OS2)
+ = 25L
+# else
+ = 24L
+# endif
+#endif
+ ;
+EXTERN long Columns INIT(= 80); /* nr of columns in the screen */
+
+/*
+ * The characters that are currently on the screen are kept in ScreenLines[].
+ * It is a single block of characters, the size of the screen plus one line.
+ * The attributes for those characters are kept in ScreenAttrs[].
+ *
+ * "LineOffset[n]" is the offset from ScreenLines[] for the start of line 'n'.
+ * The same value is used for ScreenLinesUC[] and ScreenAttrs[].
+ */
+EXTERN schar_T *ScreenLines INIT(= NULL);
+EXTERN sattr_T *ScreenAttrs INIT(= NULL);
+EXTERN unsigned *LineOffset INIT(= NULL);
+EXTERN char_u *LineWraps INIT(= NULL);
+
+#ifdef FEAT_MBYTE
+/*
+ * When using Unicode characters (in UTF-8 encoding) the character in
+ * ScreenLinesUC[] contains the Unicode for the character at this position, or
+ * NUL when the character in ScreenLines[] is to be used (ASCII char).
+ * The composing characters are to be drawn on top of the original character.
+ * Note: These three are only allocated when enc_utf8 is set!
+ */
+EXTERN u8char_T *ScreenLinesUC INIT(= NULL); /* decoded UTF-8 characters */
+EXTERN u8char_T *ScreenLinesC1 INIT(= NULL); /* first composing char */
+EXTERN u8char_T *ScreenLinesC2 INIT(= NULL); /* second composing char */
+
+/* Only used for euc-jp: Second byte of a character that starts with 0x8e.
+ * These are single-width. */
+EXTERN schar_T *ScreenLines2 INIT(= NULL);
+#endif
+
+EXTERN int screen_Rows INIT(= 0); /* actual size of ScreenLines[] */
+EXTERN int screen_Columns INIT(= 0); /* actual size of ScreenLines[] */
+
+/*
+ * When vgetc() is called, it sets mod_mask to the set of modifiers that are
+ * held down based on the KSMOD_* symbols that are read first.
+ */
+EXTERN int mod_mask INIT(= 0x0); /* current key modifiers */
+
+/*
+ * Cmdline_row is the row where the command line starts, just below the
+ * last window.
+ * When the cmdline gets longer than the available space the screen gets
+ * scrolled up. After a CTRL-D (show matches), after hitting ':' after
+ * "hit return", and for the :global command, the command line is
+ * temporarily moved. The old position is restored with the next call to
+ * update_screen().
+ */
+EXTERN int cmdline_row;
+
+EXTERN int redraw_cmdline INIT(= FALSE); /* cmdline must be redrawn */
+EXTERN int clear_cmdline INIT(= FALSE); /* cmdline must be cleared */
+#if defined(FEAT_CRYPT) || defined(FEAT_EVAL)
+EXTERN int cmdline_star INIT(= FALSE); /* cmdline is crypted */
+#endif
+EXTERN int exec_from_reg INIT(= FALSE); /* executing register */
+
+EXTERN int global_changedtick INIT(= 0); /* incremented for each
+ change, also for undo */
+EXTERN int screen_cleared INIT(= FALSE); /* screen has been cleared */
+
+/*
+ * When '$' is included in 'cpoptions' option set:
+ * When a change command is given that deletes only part of a line, a dollar
+ * is put at the end of the changed text. dollar_vcol is set to the virtual
+ * column of this '$'.
+ */
+EXTERN colnr_T dollar_vcol INIT(= 0);
+
+#ifdef FEAT_INS_EXPAND
+/*
+ * used for Insert mode completion
+ */
+EXTERN int completion_length INIT(= 0);
+EXTERN int continue_status INIT(= 0);
+EXTERN int completion_interrupted INIT(= FALSE);
+
+/* flags for continue_status */
+#define CONT_ADDING 1 /* "normal" or "adding" expansion */
+#define CONT_INTRPT (2 + 4) /* a ^X interrupted the current expansion */
+ /* it's set only iff N_ADDS is set */
+#define CONT_N_ADDS 4 /* next ^X<> will add-new or expand-current */
+#define CONT_S_IPOS 8 /* next ^X<> will set initial_pos?
+ * if so, word-wise-expansion will set SOL */
+#define CONT_SOL 16 /* pattern includes start of line, just for
+ * word-wise expansion, not set for ^X^L */
+#define CONT_LOCAL 32 /* for ctrl_x_mode 0, ^X^P/^X^N do a local
+ * expansion, (eg use complete=.) */
+#endif
+
+/*
+ * Functions for putting characters in the command line,
+ * while keeping ScreenLines[] updated.
+ */
+#ifdef FEAT_RIGHTLEFT
+EXTERN int cmdmsg_rl INIT(= FALSE); /* cmdline is drawn right to left */
+#endif
+EXTERN int msg_col;
+EXTERN int msg_row;
+EXTERN int msg_scrolled; /* Number of screen lines that windows have
+ * scrolled because of printing messages. */
+EXTERN int msg_scrolled_ign INIT(= FALSE);
+ /* when TRUE don't set need_wait_return in
+ msg_puts_attr() when msg_scrolled is
+ non-zero */
+
+EXTERN char_u *keep_msg INIT(= NULL); /* msg to be shown after redraw */
+EXTERN int keep_msg_attr INIT(= 0); /* highlight attr for keep_msg */
+EXTERN int need_fileinfo INIT(= FALSE);/* do fileinfo() after redraw */
+EXTERN int msg_scroll INIT(= FALSE); /* msg_start() will scroll */
+EXTERN int msg_didout INIT(= FALSE); /* msg_outstr() was used in line */
+EXTERN int msg_didany INIT(= FALSE); /* msg_outstr() was used at all */
+EXTERN int msg_nowait INIT(= FALSE); /* don't wait for this msg */
+EXTERN int emsg_off INIT(= 0); /* don't display errors for now,
+ unless 'debug' is set. */
+EXTERN int info_message INIT(= FALSE); /* printing informative message */
+#ifdef FEAT_EVAL
+EXTERN int emsg_skip INIT(= 0); /* don't display errors for
+ expression that is skipped */
+EXTERN int emsg_severe INIT(=FALSE); /* use message of next of several
+ emsg() calls for throw */
+EXTERN int did_endif INIT(= FALSE); /* just had ":endif" */
+#endif
+EXTERN int did_emsg; /* set by emsg() when the message
+ is displayed or thrown */
+EXTERN int called_emsg; /* always set by emsg() */
+EXTERN int emsg_on_display INIT(= FALSE); /* there is an error message */
+EXTERN int rc_did_emsg INIT(= FALSE); /* vim_regcomp() called emsg() */
+
+EXTERN int no_wait_return INIT(= 0); /* don't wait for return for now */
+EXTERN int need_wait_return INIT(= 0); /* need to wait for return later */
+EXTERN int did_wait_return INIT(= FALSE); /* wait_return() was used and
+ nothing written since then */
+#ifdef FEAT_TITLE
+EXTERN int need_maketitle INIT(= TRUE); /* call maketitle() soon */
+#endif
+
+EXTERN int quit_more INIT(= FALSE); /* 'q' hit at "--more--" msg */
+EXTERN int more_back INIT(= 0); /* 'b' or 'u' at "--more--" msg */
+EXTERN int more_back_used INIT(= FALSE); /* using more_back */
+#if defined(UNIX) || defined(__EMX__) || defined(VMS) || defined(MACOS_X)
+EXTERN int newline_on_exit INIT(= FALSE); /* did msg in altern. screen */
+EXTERN int intr_char INIT(= 0); /* extra interrupt character */
+#endif
+#if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11)
+EXTERN int x_no_connect INIT(= FALSE); /* don't connect to X server */
+# if defined(FEAT_CLIENTSERVER)
+EXTERN int x_force_connect INIT(= FALSE); /* Do connect to X server.
+ Overrules x_no_connect and
+ "exclude" in 'clipboard'. */
+# endif
+#endif
+EXTERN int vgetc_busy INIT(= FALSE); /* inside vgetc() now */
+
+EXTERN int didset_vim INIT(= FALSE); /* did set $VIM ourselves */
+EXTERN int didset_vimruntime INIT(= FALSE); /* idem for $VIMRUNTIME */
+
+/*
+ * Lines left before a "more" message. Ex mode needs to be able to reset this
+ * after you type something.
+ */
+EXTERN int lines_left INIT(= -1); /* lines left for listing */
+EXTERN int msg_no_more INIT(= FALSE); /* don't use more prompt, truncate
+ messages */
+
+EXTERN char_u *sourcing_name INIT( = NULL);/* name of error message source */
+EXTERN linenr_T sourcing_lnum INIT(= 0); /* line number of the source file */
+
+#ifdef FEAT_EVAL
+EXTERN int ex_nesting_level INIT(= 0); /* nesting level */
+EXTERN int debug_break_level INIT(= -1); /* break below this level */
+EXTERN int debug_did_msg INIT(= FALSE); /* did "debug mode" message */
+EXTERN int debug_tick INIT(= 0); /* breakpoint change count */
+
+/*
+ * The exception currently being thrown. Used to pass an exception to
+ * a different cstack. Also used for discarding an exception before it is
+ * caught or made pending. Only valid when did_throw is TRUE.
+ */
+EXTERN except_T *current_exception;
+
+/*
+ * did_throw: An exception is being thrown. Reset when the exception is caught
+ * or as long as it is pending in a finally clause.
+ */
+EXTERN int did_throw INIT(= FALSE);
+
+/*
+ * need_rethrow: set to TRUE when a throw that cannot be handled in do_cmdline()
+ * must be propagated to the cstack of the previously called do_cmdline().
+ */
+EXTERN int need_rethrow INIT(= FALSE);
+
+/*
+ * check_cstack: set to TRUE when a ":finish" or ":return" that cannot be
+ * handled in do_cmdline() must be propagated to the cstack of the previously
+ * called do_cmdline().
+ */
+EXTERN int check_cstack INIT(= FALSE);
+
+/*
+ * Number of nested try conditionals (across function calls and ":source"
+ * commands).
+ */
+EXTERN int trylevel INIT(= 0);
+
+/*
+ * When "force_abort" is TRUE, always skip commands after an error message,
+ * even after the outermost ":endif" or ":endwhile" or for a function whithout
+ * the "abort" flag. It is set to TRUE when "trylevel" is non-zero (and
+ * ":silent!" was not used) or an exception is being thrown at the time an
+ * error is detected. It is set to FALSE when "trylevel" gets zero again and
+ * there was no error or interrupt or throw.
+ *
+ */
+EXTERN int force_abort INIT(= FALSE);
+
+/*
+ * "msg_list" points to a variable in the stack of do_cmdline() which keeps the
+ * list of arguments of several emsg() calls, one of which is to be converted to
+ * an error exception immediately after the failing command returns. The
+ * message to be used for the exception value is pointed to by the "throw_msg"
+ * field of the first element in the list. It is usually the same as the "msg"
+ * field of that element, but can be identical to the "msg" field of a later
+ * list element, when the "emsg_severe" flag was set when the emsg() call was
+ * made.
+ */
+EXTERN struct msglist **msg_list INIT(= NULL);
+
+/*
+ * suppress_errthrow: When TRUE, don't convert an error to an exception. Used
+ * when displaying the interrupt message or reporting an exception that is still
+ * uncaught at the top level (which has already been discarded then). Also used
+ * for the error message when no exception can be thrown.
+ */
+EXTERN int suppress_errthrow INIT(= FALSE);
+
+/*
+ * The stack of all caught and not finished exceptions. The exception on the
+ * top of the stack is the one got by evaluation of v:exception. The complete
+ * stack of all caught and pending exceptions is embedded in the various
+ * cstacks; the pending exceptions, however, are not on the caught stack.
+ */
+EXTERN except_T *caught_stack INIT(= NULL);
+
+#endif
+
+#ifdef FEAT_EVAL
+EXTERN scid_T current_SID INIT(= 0); /* ID of script being sourced or
+ was sourced to define the
+ current function. */
+#endif
+EXTERN int scroll_region INIT(= FALSE); /* term supports scroll region */
+EXTERN int t_colors INIT(= 0); /* int value of T_CCO */
+
+/*
+ * When highlight_match is TRUE, highlight a match, starting at the cursor
+ * position. Search_match_lines is the number of lines after the match (0 for
+ * a match within one line), search_match_endcol the column number of the
+ * character just after the match in the last line.
+ */
+EXTERN int highlight_match INIT(= FALSE); /* show search match pos */
+EXTERN linenr_T search_match_lines; /* lines of of matched string */
+EXTERN colnr_T search_match_endcol; /* col nr of match end */
+
+EXTERN int no_smartcase INIT(= FALSE); /* don't use 'smartcase' once */
+
+EXTERN int need_check_timestamps INIT(= FALSE); /* need to check file
+ timestamps asap */
+EXTERN int did_check_timestamps INIT(= FALSE); /* did check timestamps
+ recently */
+EXTERN int no_check_timestamps INIT(= 0); /* Don't check timestamps */
+
+EXTERN int highlight_attr[HLF_COUNT]; /* Highl. attr for each context. */
+#ifdef FEAT_STL_OPT
+# define USER_HIGHLIGHT
+#endif
+#ifdef USER_HIGHLIGHT
+EXTERN int highlight_user[9]; /* User[1-9] attributes */
+# ifdef FEAT_STL_OPT
+EXTERN int highlight_stlnc[9]; /* On top of user */
+# endif
+#endif
+#ifdef FEAT_GUI
+EXTERN char_u *use_gvimrc INIT(= NULL); /* "-U" cmdline argument */
+#endif
+EXTERN int cterm_normal_fg_color INIT(= 0);
+EXTERN int cterm_normal_fg_bold INIT(= 0);
+EXTERN int cterm_normal_bg_color INIT(= 0);
+
+#ifdef FEAT_AUTOCMD
+EXTERN int autocmd_busy INIT(= FALSE); /* Is apply_autocmds() busy? */
+EXTERN int autocmd_no_enter INIT(= FALSE); /* *Enter autocmds disabled */
+EXTERN int autocmd_no_leave INIT(= FALSE); /* *Leave autocmds disabled */
+EXTERN int autocmd_block INIT(= 0); /* block all autocmds */
+EXTERN int modified_was_set; /* did ":set modified" */
+EXTERN int did_filetype INIT(= FALSE); /* FileType event found */
+EXTERN int keep_filetype INIT(= FALSE); /* value for did_filetype when
+ starting to execute
+ autocommands */
+
+/* When deleting the current buffer, another one must be loaded. If we know
+ * which one is preferred, au_new_curbuf is set to it */
+EXTERN buf_T *au_new_curbuf INIT(= NULL);
+#endif
+
+#ifdef FEAT_MOUSE
+/*
+ * Mouse coordinates, set by check_termcode()
+ */
+EXTERN int mouse_row;
+EXTERN int mouse_col;
+EXTERN int mouse_past_bottom INIT(= FALSE);/* mouse below last line */
+EXTERN int mouse_past_eol INIT(= FALSE); /* mouse right of line */
+EXTERN int mouse_dragging INIT(= 0); /* extending Visual area with
+ mouse dragging */
+# if defined(FEAT_MOUSE_DEC)
+/*
+ * When the DEC mouse has been pressed but not yet released we enable
+ * automatic querys for the mouse position.
+ */
+EXTERN int WantQueryMouse INIT(= 0);
+# endif
+
+# ifdef FEAT_GUI
+/* When the window layout is about to be changed, need_mouse_correct is set,
+ * so that gui_mouse_correct() is called afterwards, to correct the mouse
+ * pointer when focus-follow-mouse is being used. */
+EXTERN int need_mouse_correct INIT(= FALSE);
+
+/* When double clicking, topline must be the same */
+EXTERN linenr_T gui_prev_topline INIT(= 0);
+# ifdef FEAT_DIFF
+EXTERN int gui_prev_topfill INIT(= 0);
+# endif
+# endif
+
+# ifdef FEAT_MOUSESHAPE
+EXTERN int drag_status_line INIT(= FALSE); /* dragging the status line */
+EXTERN int postponed_mouseshape INIT(= FALSE); /* postponed updating the
+ mouse pointer shape */
+# ifdef FEAT_VERTSPLIT
+EXTERN int drag_sep_line INIT(= FALSE); /* dragging vert separator */
+# endif
+# endif
+
+#endif
+
+#ifdef FEAT_DIFF
+/* Value set from 'diffopt'. */
+EXTERN int diff_context INIT(= 6); /* context for folds */
+#endif
+
+#ifdef FEAT_MENU
+/* The root of the menu hierarchy. */
+EXTERN vimmenu_T *root_menu INIT(= NULL);
+/*
+ * While defining the system menu, sys_menu is TRUE. This avoids
+ * overruling of menus that the user already defined.
+ */
+EXTERN int sys_menu INIT(= FALSE);
+#endif
+
+/* While redrawing the screen this flag is set. It means the screen size
+ * ('lines' and 'rows') must not be changed. */
+EXTERN int updating_screen INIT(= FALSE);
+
+#ifdef FEAT_GUI
+# ifdef FEAT_MENU
+/* Menu item just selected, set by check_termcode() */
+EXTERN vimmenu_T *current_menu;
+
+/* Set to TRUE after adding/removing menus to ensure they are updated */
+EXTERN int force_menu_update INIT(= FALSE);
+# endif
+
+/* Scrollbar moved and new value, set by check_termcode() */
+EXTERN int current_scrollbar;
+EXTERN long_u scrollbar_value;
+
+/* found "-rv" or "-reverse" in command line args */
+EXTERN int found_reverse_arg INIT(= FALSE);
+
+/* "-fn" or "-font" command line argument */
+EXTERN char *font_argument INIT(= NULL);
+
+# ifdef FEAT_GUI_GTK
+/* "-bg" or "-background" command line argument */
+EXTERN char *background_argument INIT(= NULL);
+
+/* "-fg" or "-foreground" command line argument */
+EXTERN char *foreground_argument INIT(= NULL);
+# endif
+
+/*
+ * While executing external commands or in Ex mode, should not insert GUI
+ * events in the input buffer: Set hold_gui_events to non-zero.
+ */
+EXTERN int hold_gui_events INIT(= 0);
+
+/*
+ * When resizing the shell is postponed, remember the new size, and call
+ * gui_resize_shell() later.
+ */
+EXTERN int new_pixel_width INIT(= 0);
+EXTERN int new_pixel_height INIT(= 0);
+
+/* Window position from ":winpos", to be used when opening the GUI window. */
+EXTERN int gui_win_x INIT(= -1);
+EXTERN int gui_win_y INIT(= -1);
+#endif
+
+#ifdef FEAT_CLIPBOARD
+EXTERN VimClipboard clip_star; /* PRIMARY selection in X11 */
+# ifdef FEAT_X11
+EXTERN VimClipboard clip_plus; /* CLIPBOARD selection in X11 */
+# else
+# define clip_plus clip_star /* there is only one clipboard */
+# endif
+#endif
+
+/*
+ * All windows are linked in a list. firstwin points to the first entry,
+ * lastwin to the last entry (can be the same as firstwin) and curwin to the
+ * currently active window.
+ * Without the FEAT_WINDOWS they are all equal.
+ */
+#ifdef FEAT_WINDOWS
+EXTERN win_T *firstwin; /* first window */
+EXTERN win_T *lastwin; /* last window */
+EXTERN win_T *prevwin INIT(= NULL); /* previous window */
+# define W_NEXT(wp) ((wp)->w_next)
+# define FOR_ALL_WINDOWS(wp) for (wp = firstwin; wp != NULL; wp = wp->w_next)
+#else
+# define firstwin curwin
+# define lastwin curwin
+# define W_NEXT(wp) NULL
+# define FOR_ALL_WINDOWS(wp) wp = curwin;
+#endif
+EXTERN win_T *curwin; /* currently active window */
+
+/*
+ * The window layout is kept in a tree of frames. topframe points to the top
+ * of the tree.
+ */
+EXTERN frame_T *topframe; /* top of the window frame tree */
+
+/*
+ * All buffers are linked in a list. 'firstbuf' points to the first entry,
+ * 'lastbuf' to the last entry and 'curbuf' to the currently active buffer.
+ */
+EXTERN buf_T *firstbuf INIT(= NULL); /* first buffer */
+EXTERN buf_T *lastbuf INIT(= NULL); /* last buffer */
+EXTERN buf_T *curbuf INIT(= NULL); /* currently active buffer */
+
+/*
+ * List of files being edited (global argument list). curwin->w_alist points
+ * to this when the window is using the global argument list.
+ */
+EXTERN alist_T global_alist; /* global argument list */
+EXTERN int arg_had_last INIT(= FALSE); /* accessed last file in
+ global_alist */
+
+EXTERN int ru_col; /* column for ruler */
+#ifdef FEAT_STL_OPT
+EXTERN int ru_wid; /* 'rulerfmt' width of ruler when non-zero */
+#endif
+EXTERN int sc_col; /* column for shown command */
+
+#ifdef TEMPDIRNAMES
+EXTERN char_u *vim_tempdir INIT(= NULL); /* Name of Vim's own temp dir.
+ Ends in a slash. */
+#endif
+
+/*
+ * When starting or exiting some things are done differently (e.g. screen
+ * updating).
+ */
+EXTERN int starting INIT(= NO_SCREEN);
+ /* first NO_SCREEN, then NO_BUFFERS and then
+ * set to 0 when starting up finished */
+EXTERN int exiting INIT(= FALSE);
+ /* TRUE when abandoning Vim */
+EXTERN int full_screen INIT(= FALSE);
+ /* TRUE when doing full-screen output
+ * otherwise only writing some messages */
+
+EXTERN int restricted INIT(= FALSE);
+ /* TRUE when started as "rvim" */
+EXTERN int secure INIT(= FALSE);
+ /* non-zero when only "safe" commands are
+ * allowed, e.g. when sourcing .exrc or .vimrc
+ * in current directory */
+
+#ifdef FEAT_EVAL
+# define HAVE_SANDBOX
+EXTERN int sandbox INIT(= 0);
+ /* non-zero when evaluating an expression in a
+ * "sandbox". Not allowed to change the
+ * buffer. */
+#endif
+
+EXTERN int silent_mode INIT(= FALSE);
+ /* set to TRUE when "-s" commandline argument
+ * used for ex */
+
+#ifdef FEAT_VISUAL
+EXTERN pos_T VIsual; /* start position of active Visual selection */
+EXTERN int VIsual_active INIT(= FALSE);
+ /* whether Visual mode is active */
+EXTERN int VIsual_select INIT(= FALSE);
+ /* whether Select mode is active */
+EXTERN int VIsual_reselect;
+ /* whether to restart the selection after a
+ * Select mode mapping or menu */
+
+EXTERN int VIsual_mode INIT(= 'v');
+ /* type of Visual mode */
+
+EXTERN int redo_VIsual_busy INIT(= FALSE);
+ /* TRUE when redoing Visual */
+#endif
+
+#ifdef FEAT_MOUSE
+/*
+ * When pasting text with the middle mouse button in visual mode with
+ * restart_edit set, remember where it started so we can set Insstart.
+ */
+EXTERN pos_T where_paste_started;
+#endif
+
+/*
+ * This flag is used to make auto-indent work right on lines where only a
+ * <RETURN> or <ESC> is typed. It is set when an auto-indent is done, and
+ * reset when any other editing is done on the line. If an <ESC> or <RETURN>
+ * is received, and did_ai is TRUE, the line is truncated.
+ */
+EXTERN int did_ai INIT(= FALSE);
+
+/*
+ * Column of first char after autoindent. 0 when no autoindent done. Used
+ * when 'backspace' is 0, to avoid backspacing over autoindent.
+ */
+EXTERN colnr_T ai_col INIT(= 0);
+
+#ifdef FEAT_COMMENTS
+/*
+ * This is a character which will end a start-middle-end comment when typed as
+ * the first character on a new line. It is taken from the last character of
+ * the "end" comment leader when the COM_AUTO_END flag is given for that
+ * comment end in 'comments'. It is only valid when did_ai is TRUE.
+ */
+EXTERN int end_comment_pending INIT(= NUL);
+#endif
+
+#ifdef FEAT_SCROLLBIND
+/*
+ * This flag is set after a ":syncbind" to let the check_scrollbind() function
+ * know that it should not attempt to perform scrollbinding due to the scroll
+ * that was a result of the ":syncbind." (Otherwise, check_scrollbind() will
+ * undo some of the work done by ":syncbind.") -ralston
+ */
+EXTERN int did_syncbind INIT(= FALSE);
+#endif
+
+#ifdef FEAT_SMARTINDENT
+/*
+ * This flag is set when a smart indent has been performed. When the next typed
+ * character is a '{' the inserted tab will be deleted again.
+ */
+EXTERN int did_si INIT(= FALSE);
+
+/*
+ * This flag is set after an auto indent. If the next typed character is a '}'
+ * one indent will be removed.
+ */
+EXTERN int can_si INIT(= FALSE);
+
+/*
+ * This flag is set after an "O" command. If the next typed character is a '{'
+ * one indent will be removed.
+ */
+EXTERN int can_si_back INIT(= FALSE);
+#endif
+
+EXTERN pos_T saved_cursor /* w_cursor before formatting text. */
+# ifdef DO_INIT
+ = INIT_POS_T
+# endif
+ ;
+
+/*
+ * Stuff for insert mode.
+ */
+EXTERN pos_T Insstart; /* This is where the latest
+ * insert/append mode started. */
+#ifdef FEAT_VREPLACE
+/*
+ * Stuff for VREPLACE mode.
+ */
+EXTERN int orig_line_count INIT(= 0); /* Line count when "gR" started */
+EXTERN int vr_lines_changed INIT(= 0); /* #Lines changed by "gR" so far */
+#endif
+
+#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
+/* argument to SETJMP() for handling X IO errors */
+EXTERN JMP_BUF x_jump_env;
+#endif
+
+#if defined(HAVE_SETJMP_H)
+/*
+ * Stuff for setjmp() and longjmp().
+ * Used to protect areas where we could crash.
+ */
+EXTERN JMP_BUF lc_jump_env; /* argument to SETJMP() */
+#ifdef SIGHASARG
+EXTERN int lc_signal; /* catched signal number, 0 when no was signal
+ catched; used for mch_libcall() */
+#endif
+EXTERN int lc_active INIT(= FALSE); /* TRUE when lc_jump_env is valid. */
+#endif
+
+#if defined(FEAT_MBYTE) || defined(FEAT_POSTSCRIPT)
+/*
+ * These flags are set based upon 'fileencoding'.
+ * Note that "enc_utf8" is also set for "unicode", because the characters are
+ * internally stored as UTF-8 (to avoid trouble with NUL bytes).
+ */
+# define DBCS_JPN 932 /* japan */
+# define DBCS_JPNU 9932 /* euc-jp */
+# define DBCS_KOR 949 /* korea */
+# define DBCS_KORU 9949 /* euc-kr */
+# define DBCS_CHS 936 /* chinese */
+# define DBCS_CHSU 9936 /* euc-cn */
+# define DBCS_CHT 950 /* taiwan */
+# define DBCS_CHTU 9950 /* euc-tw */
+# define DBCS_2BYTE 1 /* 2byte- */
+# define DBCS_DEBUG -1
+#endif
+
+#ifdef FEAT_MBYTE
+EXTERN int enc_dbcs INIT(= 0); /* One of DBCS_xxx values if
+ DBCS encoding */
+EXTERN int enc_unicode INIT(= 0); /* 2: UCS-2 or UTF-16, 4: UCS-4 */
+EXTERN int enc_utf8 INIT(= FALSE); /* UTF-8 encoded Unicode */
+# ifdef WIN3264
+/* Codepage nr of 'encoding'. Negative means it's not been set yet, zero
+ * means 'encoding' is not a valid codepage. */
+EXTERN int enc_codepage INIT(= -1);
+# endif
+EXTERN int has_mbyte INIT(= 0); /* any multi-byte encoding */
+
+#if defined(WIN3264) && defined(FEAT_MBYTE)
+EXTERN int wide_WindowProc INIT(= FALSE); /* use wide WindowProc() */
+#endif
+
+/*
+ * To speed up BYTELEN() we fill a table with the byte lengths whenever
+ * enc_utf8 or enc_dbcs changes.
+ */
+EXTERN char mb_bytelen_tab[256];
+
+/* Variables that tell what conversion is used for keyboard input and display
+ * output. */
+EXTERN vimconv_T input_conv; /* type of input conversion */
+EXTERN vimconv_T output_conv; /* type of output conversion */
+
+/*
+ * Function pointers, used to quickly get to the right function. Each has
+ * three possible values: latin_ (8-bit), utfc_ or utf_ (utf-8) and dbcs_
+ * (DBCS).
+ * The value is set in mb_init();
+ */
+EXTERN int (*mb_ptr2len_check) __ARGS((char_u *p)) INIT(= latin_ptr2len_check);
+EXTERN int (*mb_char2len) __ARGS((int c)) INIT(= latin_char2len);
+EXTERN int (*mb_char2bytes) __ARGS((int c, char_u *buf)) INIT(= latin_char2bytes);
+EXTERN int (*mb_ptr2cells) __ARGS((char_u *p)) INIT(= latin_ptr2cells);
+EXTERN int (*mb_char2cells) __ARGS((int c)) INIT(= latin_char2cells);
+EXTERN int (*mb_off2cells) __ARGS((unsigned off)) INIT(= latin_off2cells);
+EXTERN int (*mb_ptr2char) __ARGS((char_u *p)) INIT(= latin_ptr2char);
+EXTERN int (*mb_head_off) __ARGS((char_u *base, char_u *p)) INIT(= latin_head_off);
+
+# if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
+/* Pointers to functions and variables to be loaded at runtime */
+EXTERN size_t (*iconv) (iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
+EXTERN iconv_t (*iconv_open) (const char *tocode, const char *fromcode);
+EXTERN int (*iconv_close) (iconv_t cd);
+EXTERN int (*iconvctl) (iconv_t cd, int request, void *argument);
+EXTERN int* (*iconv_errno) (void);
+# endif
+
+#endif /* FEAT_MBYTE */
+
+#ifdef FEAT_XIM
+# ifdef FEAT_GUI_GTK
+# ifdef HAVE_GTK2
+EXTERN GtkIMContext *xic INIT(= NULL);
+# else
+EXTERN GdkICAttr *xic_attr INIT(= NULL);
+EXTERN GdkIC *xic INIT(= NULL);
+EXTERN char *draw_feedback INIT(= NULL);
+# endif
+/*
+ * Start and end column of the preedit area in virtual columns from the start
+ * of the text line. When there is no preedit area they are set to MAXCOL.
+ * "preedit_end_col" is needed for coloring the preedited string. Drawing the
+ * color between "preedit_start_col" and curpos did not work, because some XIM
+ * set the cursor position to the first char of the string.
+ */
+EXTERN colnr_T preedit_start_col INIT(= MAXCOL);
+EXTERN colnr_T preedit_end_col INIT(= MAXCOL);
+
+/* "xim_changed_while_preediting" is set when changed() can set the 'modified'
+ * flag even while preediting. */
+EXTERN int xim_changed_while_preediting INIT(= FALSE);
+# else
+EXTERN XIC xic INIT(= NULL);
+# endif
+EXTERN guicolor_T xim_fg_color INIT(= INVALCOLOR);
+EXTERN guicolor_T xim_bg_color INIT(= INVALCOLOR);
+#endif
+
+#ifdef FEAT_HANGULIN
+EXTERN int composing_hangul INIT(= 0);
+EXTERN char_u composing_hangul_buffer[5];
+#endif
+
+/*
+ * "State" is the main state of Vim.
+ * There are other variables that modify the state:
+ * "Visual_mode" When State is NORMAL or INSERT.
+ * "finish_op" When State is NORMAL, after typing the operator and before
+ * typing the motion command.
+ */
+EXTERN int State INIT(= NORMAL); /* This is the current state of the
+ * command interpreter. */
+
+EXTERN int finish_op INIT(= FALSE);/* TRUE while an operator is pending */
+
+/*
+ * ex mode (Q) state
+ */
+EXTERN int exmode_active INIT(= 0); /* zero, EXMODE_NORMAL or EXMODE_VIM */
+EXTERN int ex_no_reprint INIT(= FALSE); /* no need to print after z or p */
+
+EXTERN int Recording INIT(= FALSE);/* TRUE when recording into a reg. */
+EXTERN int Exec_reg INIT(= FALSE); /* TRUE when executing a register */
+
+EXTERN int no_mapping INIT(= FALSE); /* currently no mapping allowed */
+EXTERN int no_zero_mapping INIT(= 0); /* mapping zero not allowed */
+EXTERN int allow_keys INIT(= FALSE); /* allow key codes when no_mapping
+ * is set */
+EXTERN int no_u_sync INIT(= 0); /* Don't call u_sync() */
+
+EXTERN int restart_edit INIT(= 0); /* call edit when next cmd finished */
+EXTERN int arrow_used; /* Normally FALSE, set to TRUE after
+ * hitting cursor key in insert mode.
+ * Used by vgetorpeek() to decide when
+ * to call u_sync() */
+#ifdef FEAT_INS_EXPAND
+EXTERN char_u *edit_submode INIT(= NULL); /* msg for CTRL-X submode */
+EXTERN char_u *edit_submode_pre INIT(= NULL); /* prepended to edit_submode */
+EXTERN char_u *edit_submode_extra INIT(= NULL);/* appended to edit_submode */
+EXTERN enum hlf_value edit_submode_highl; /* highl. method for extra info */
+EXTERN int ctrl_x_mode INIT(= 0); /* Which Ctrl-X mode are we in? */
+#endif
+
+EXTERN int no_abbr INIT(= TRUE); /* TRUE when no abbreviations loaded */
+#ifdef MSDOS
+EXTERN int beep_count INIT(= 0); /* nr of beeps since last char typed */
+#endif
+
+#ifdef USE_EXE_NAME
+EXTERN char_u *exe_name; /* the name of the executable */
+#endif
+
+#ifdef USE_ON_FLY_SCROLL
+EXTERN int dont_scroll INIT(= FALSE);/* don't use scrollbars when TRUE */
+#endif
+EXTERN int mapped_ctrl_c INIT(= FALSE); /* CTRL-C is mapped */
+EXTERN int ctrl_c_interrupts INIT(= TRUE); /* CTRL-C sets got_int */
+
+EXTERN cmdmod_T cmdmod; /* Ex command modifiers */
+
+EXTERN int msg_silent INIT(= 0); /* don't print messages */
+EXTERN int emsg_silent INIT(= 0); /* don't print error messages */
+EXTERN int cmd_silent INIT(= FALSE); /* don't echo the command line */
+
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+EXTERN int swap_exists_action INIT(= 0); /* use dialog when swap file
+ already exists */
+#endif
+
+EXTERN char_u *IObuff; /* sprintf's are done in this buffer,
+ size is IOSIZE */
+EXTERN char_u *NameBuff; /* file names are expanded in this
+ * buffer, size is MAXPATHL */
+EXTERN char_u msg_buf[MSG_BUF_LEN]; /* small buffer for messages */
+
+/* When non-zero, postpone redrawing. */
+EXTERN int RedrawingDisabled INIT(= 0);
+
+EXTERN int readonlymode INIT(= FALSE); /* Set to TRUE for "view" */
+EXTERN int recoverymode INIT(= FALSE); /* Set to TRUE for "-r" option */
+
+EXTERN struct buffheader stuffbuff /* stuff buffer */
+#ifdef DO_INIT
+ = {{NULL, {NUL}}, NULL, 0, 0}
+#endif
+ ;
+EXTERN typebuf_T typebuf /* typeahead buffer */
+#ifdef DO_INIT
+ = {NULL, NULL}
+#endif
+ ;
+#ifdef FEAT_EX_EXTRA
+EXTERN int ex_normal_busy INIT(= 0); /* recursivenes of ex_normal() */
+#endif
+EXTERN int stop_insert_mode; /* for ":stopinsert" and 'insertmode' */
+
+EXTERN int KeyTyped; /* TRUE if user typed current char */
+EXTERN int KeyStuffed; /* TRUE if current char from stuffbuf */
+#ifdef USE_IM_CONTROL
+EXTERN int vgetc_im_active; /* Input Method was active for last
+ character obtained from vgetc() */
+#endif
+EXTERN int maptick INIT(= 0); /* tick for each non-mapped char */
+
+EXTERN char_u chartab[256]; /* table used in charset.c; See
+ init_chartab() for explanation */
+
+EXTERN int must_redraw INIT(= 0); /* type of redraw necessary */
+EXTERN int skip_redraw INIT(= FALSE); /* skip redraw once */
+EXTERN int do_redraw INIT(= FALSE); /* extra redraw once */
+
+EXTERN int need_highlight_changed INIT(= TRUE);
+EXTERN char_u *use_viminfo INIT(= NULL); /* name of viminfo file to use */
+
+#define NSCRIPT 15
+EXTERN FILE *scriptin[NSCRIPT]; /* streams to read script from */
+EXTERN int curscript INIT(= 0); /* index in scriptin[] */
+EXTERN FILE *scriptout INIT(= NULL); /* stream to write script to */
+EXTERN int read_cmd_fd INIT(= 0); /* fd to read commands from */
+
+EXTERN int got_int INIT(= FALSE); /* set to TRUE when interrupt
+ signal occurred */
+#ifdef USE_TERM_CONSOLE
+EXTERN int term_console INIT(= FALSE); /* set to TRUE when console used */
+#endif
+EXTERN int termcap_active INIT(= FALSE); /* set by starttermcap() */
+EXTERN int cur_tmode INIT(= TMODE_COOK); /* input terminal mode */
+EXTERN int bangredo INIT(= FALSE); /* set to TRUE whith ! command */
+EXTERN int searchcmdlen; /* length of previous search cmd */
+EXTERN int reg_syn INIT(= 0); /* vim_regexec() used for syntax */
+#ifdef FEAT_SYN_HL
+EXTERN int reg_do_extmatch INIT(= 0); /* Used when compiling regexp:
+ * REX_SET to allow \z\(...\),
+ * REX_USE to allow \z\1 et al. */
+EXTERN reg_extmatch_T *re_extmatch_in INIT(= NULL); /* Used by vim_regexec():
+ * strings for \z\1...\z\9 */
+EXTERN reg_extmatch_T *re_extmatch_out INIT(= NULL); /* Set by vim_regexec()
+ * to store \z\(...\) matches */
+#endif
+
+EXTERN int did_outofmem_msg INIT(= FALSE);
+ /* set after out of memory msg */
+EXTERN int did_swapwrite_msg INIT(= FALSE);
+ /* set after swap write error msg */
+EXTERN int undo_off INIT(= FALSE); /* undo switched off for now */
+EXTERN int global_busy INIT(= 0); /* set when :global is executing */
+EXTERN int listcmd_busy INIT(= FALSE); /* set when :argdo, :windo or
+ :bufdo is executing */
+EXTERN int need_start_insertmode INIT(= FALSE);
+ /* start insert mode soon */
+EXTERN char_u *last_cmdline INIT(= NULL); /* last command line (for ":) */
+EXTERN char_u *repeat_cmdline INIT(= NULL); /* command line for "." */
+#ifdef FEAT_CMDHIST
+EXTERN char_u *new_last_cmdline INIT(= NULL); /* new value for last_cmdline */
+#endif
+#ifdef FEAT_AUTOCMD
+EXTERN char_u *autocmd_fname INIT(= NULL); /* fname for <afile> on cmdline */
+EXTERN int autocmd_bufnr INIT(= 0); /* fnum for <abuf> on cmdline */
+EXTERN char_u *autocmd_match INIT(= NULL); /* name for <amatch> on cmdline */
+#endif
+
+#ifdef FEAT_WINDOWS
+EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */
+EXTERN int postponed_split_flags INIT(= 0); /* args for win_split() */
+# ifdef FEAT_QUICKFIX
+EXTERN int g_do_tagpreview INIT(= 0); /* for tag preview commands:
+ height of preview window */
+# endif
+#endif
+EXTERN int replace_offset INIT(= 0); /* offset for replace_push() */
+
+EXTERN char_u *escape_chars INIT(= (char_u *)" \t\\\"|");
+ /* need backslash in cmd line */
+
+EXTERN int keep_help_flag INIT(= FALSE); /* doing :ta from help file */
+
+/*
+ * When a string option is NULL (which only happens in out-of-memory
+ * situations), it is set to empty_option, to avoid having to check for NULL
+ * everywhere.
+ */
+EXTERN char_u *empty_option INIT(= (char_u *)"");
+
+#ifdef DEBUG
+EXTERN FILE *debugfp INIT(= NULL);
+#endif
+
+EXTERN int redir_off INIT(= FALSE); /* no redirection for a moment */
+EXTERN FILE *redir_fd INIT(= NULL); /* message redirection file */
+#ifdef FEAT_EVAL
+EXTERN int redir_reg INIT(= 0); /* message redirection register */
+#endif
+
+#ifdef FEAT_LANGMAP
+EXTERN char_u langmap_mapchar[256]; /* mapping for language keys */
+#endif
+
+#ifdef FEAT_WILDMENU
+EXTERN int save_p_ls INIT(= -1); /* Save 'laststatus' setting */
+EXTERN int save_p_wmh INIT(= -1); /* Save 'winminheight' setting */
+EXTERN int wild_menu_showing INIT(= 0);
+#define WM_SHOWN 1 /* wildmenu showing */
+#define WM_SCROLLED 2 /* wildmenu showing with scroll */
+#endif
+
+#ifdef MSWIN
+EXTERN char_u toupper_tab[256]; /* table for toupper() */
+EXTERN char_u tolower_tab[256]; /* table for tolower() */
+#endif
+
+#ifdef FEAT_LINEBREAK
+EXTERN char breakat_flags[256]; /* which characters are in 'breakat' */
+#endif
+
+/* these are in version.c */
+extern char *Version;
+extern char *mediumVersion;
+#if defined(HAVE_DATE_TIME) && defined(VMS) && defined(VAXC)
+extern char longVersion[];
+#else
+extern char *longVersion;
+#endif
+
+/*
+ * Some file names are stored in pathdef.c, which is generated from the
+ * Makefile to make their value depend on the Makefile.
+ */
+#ifdef HAVE_PATHDEF
+extern char_u *default_vim_dir;
+extern char_u *default_vimruntime_dir;
+extern char_u *all_cflags;
+extern char_u *all_lflags;
+# ifdef VMS
+extern char_u *compiler_version;
+# endif
+extern char_u *compiled_user;
+extern char_u *compiled_sys;
+#endif
+
+/* When a window has a local directory, the absolute path of the global
+ * current directory is stored here (in allocated memory). If the current
+ * directory is not a local directory, globaldir is NULL. */
+EXTERN char_u *globaldir INIT(= NULL);
+
+/* Characters from 'listchars' option */
+EXTERN int lcs_eol INIT(= '$');
+EXTERN int lcs_ext INIT(= NUL);
+EXTERN int lcs_prec INIT(= NUL);
+EXTERN int lcs_tab1 INIT(= NUL);
+EXTERN int lcs_tab2 INIT(= NUL);
+EXTERN int lcs_trail INIT(= NUL);
+
+#if defined(FEAT_WINDOWS) || defined(FEAT_WILDMENU) || defined(FEAT_STL_OPT) \
+ || defined(FEAT_FOLDING)
+/* Characters from 'fillchars' option */
+EXTERN int fill_stl INIT(= ' ');
+EXTERN int fill_stlnc INIT(= ' ');
+#endif
+#if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING)
+EXTERN int fill_vert INIT(= ' ');
+EXTERN int fill_fold INIT(= '-');
+EXTERN int fill_diff INIT(= '-');
+#endif
+
+#ifdef FEAT_VISUAL
+/* Whether 'keymodel' contains "stopsel" and "startsel". */
+EXTERN int km_stopsel INIT(= FALSE);
+EXTERN int km_startsel INIT(= FALSE);
+#endif
+
+#ifdef FEAT_CMDWIN
+EXTERN int cedit_key INIT(= -1); /* key value of 'cedit' option */
+EXTERN int cmdwin_type INIT(= 0); /* type of cmdline window or 0 */
+EXTERN int cmdwin_result INIT(= 0); /* result of cmdline window or 0 */
+#endif
+
+EXTERN char_u no_lines_msg[] INIT(= N_("--No lines in buffer--"));
+
+/* table to store parsed 'wildmode' */
+EXTERN char_u wim_flags[4];
+
+#if defined(FEAT_TITLE) && defined(FEAT_STL_OPT)
+/* whether titlestring and iconstring contains statusline syntax */
+# define STL_IN_ICON 1
+# define STL_IN_TITLE 2
+EXTERN int stl_syntax INIT(= 0);
+#endif
+
+#ifdef FEAT_SEARCH_EXTRA
+/* don't use 'hlsearch' temporarily */
+EXTERN int no_hlsearch INIT(= FALSE);
+#endif
+
+#ifdef CURSOR_SHAPE
+/* the table is in misc2.c, because of initializations */
+extern cursorentry_T shape_table[SHAPE_IDX_COUNT];
+#endif
+
+#ifdef FEAT_PRINTER
+# define OPT_PRINT_TOP 0
+# define OPT_PRINT_BOT 1
+# define OPT_PRINT_LEFT 2
+# define OPT_PRINT_RIGHT 3
+# define OPT_PRINT_HEADERHEIGHT 4
+# define OPT_PRINT_SYNTAX 5
+# define OPT_PRINT_NUMBER 6
+# define OPT_PRINT_WRAP 7
+# define OPT_PRINT_DUPLEX 8
+# define OPT_PRINT_PORTRAIT 9
+# define OPT_PRINT_PAPER 10
+# define OPT_PRINT_COLLATE 11
+# define OPT_PRINT_JOBSPLIT 12
+# define OPT_PRINT_FORMFEED 13
+
+# define OPT_PRINT_NUM_OPTIONS 14
+
+EXTERN option_table_T printer_opts[OPT_PRINT_NUM_OPTIONS]
+# ifdef DO_INIT
+ =
+{
+ {"top", TRUE, 0, NULL, 0, FALSE},
+ {"bottom", TRUE, 0, NULL, 0, FALSE},
+ {"left", TRUE, 0, NULL, 0, FALSE},
+ {"right", TRUE, 0, NULL, 0, FALSE},
+ {"header", TRUE, 0, NULL, 0, FALSE},
+ {"syntax", FALSE, 0, NULL, 0, FALSE},
+ {"number", FALSE, 0, NULL, 0, FALSE},
+ {"wrap", FALSE, 0, NULL, 0, FALSE},
+ {"duplex", FALSE, 0, NULL, 0, FALSE},
+ {"portrait", FALSE, 0, NULL, 0, FALSE},
+ {"paper", FALSE, 0, NULL, 0, FALSE},
+ {"collate", FALSE, 0, NULL, 0, FALSE},
+ {"jobsplit", FALSE, 0, NULL, 0, FALSE},
+ {"formfeed", FALSE, 0, NULL, 0, FALSE},
+}
+# endif
+;
+
+/* For prt_get_unit(). */
+# define PRT_UNIT_NONE -1
+# define PRT_UNIT_PERC 0
+# define PRT_UNIT_INCH 1
+# define PRT_UNIT_MM 2
+# define PRT_UNIT_POINT 3
+# define PRT_UNIT_NAMES {"pc", "in", "mm", "pt"}
+#endif
+
+#ifdef FEAT_XCLIPBOARD
+EXTERN char *xterm_display INIT(= NULL); /* xterm display name */
+EXTERN Display *xterm_dpy INIT(= NULL); /* xterm display pointer */
+#endif
+#if defined(FEAT_XCLIPBOARD) || defined(FEAT_GUI_X11)
+EXTERN XtAppContext app_context INIT(= (XtAppContext)NULL);
+#endif
+
+#ifdef FEAT_GUI_GTK
+EXTERN guint32 gtk_socket_id INIT(= 0);
+EXTERN int echo_wid_arg INIT(= FALSE); /* --echo-wid argument */
+#endif
+
+#ifdef FEAT_CLIENTSERVER
+EXTERN char_u *serverName INIT(= NULL); /* name of the server */
+EXTERN int received_from_client INIT(= FALSE); /* received text from
+ client */
+# ifdef FEAT_X11
+EXTERN Window commWindow INIT(= None);
+EXTERN Window clientWindow INIT(= None);
+EXTERN Atom commProperty INIT(= None);
+EXTERN char_u *serverDelayedStartName INIT(= NULL);
+# else
+# ifdef PROTO
+typedef int HWND;
+# endif
+EXTERN HWND clientWindow INIT(= 0);
+# endif
+#endif
+
+#if defined(UNIX) || defined(VMS)
+EXTERN int term_is_xterm INIT(= FALSE); /* xterm-like 'term' */
+#endif
+
+#ifdef BACKSLASH_IN_FILENAME
+EXTERN char psepc INIT(= '\\'); /* normal path separator character */
+EXTERN char psepcN INIT(= '/'); /* abnormal path separator character */
+EXTERN char pseps[2] /* normal path separator string */
+# ifdef DO_INIT
+ = {'\\', 0}
+# endif
+ ;
+EXTERN char psepsN[2] /* abnormal path separator string */
+# ifdef DO_INIT
+ = {'/', 0}
+# endif
+ ;
+#endif
+
+#ifdef FEAT_VIRTUALEDIT
+/* Set to TRUE when an operator is being executed with virtual editing, MAYBE
+ * when no operator is being executed, FALSE otherwise. */
+EXTERN int virtual_op INIT(= MAYBE);
+#endif
+
+#ifdef FEAT_SYN_HL
+/* Display tick, incremented for each call to update_screen() */
+EXTERN disptick_T display_tick INIT(= 0);
+#endif
+
+#ifdef ALT_X_INPUT
+/* we need to be able to go into the displatch loop while processing a command
+ * recevied via alternate input. However, we don't want to process another
+ * command until the first is completed.
+ */
+EXTERN int suppress_alternate_input INIT(= FALSE);
+#endif
+
+#ifdef USE_MCH_ERRMSG
+/* Grow array to collect error messages in until they can be displayed. */
+EXTERN garray_T error_ga
+# ifdef DO_INIT
+ = {0, 0, 0, 0, NULL}
+# endif
+ ;
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+EXTERN char *netbeansArg INIT(= NULL); /* the -nb[:host:port:passwd] arg */
+EXTERN int netbeansCloseFile INIT(= 0); /* send killed if != 0 */
+EXTERN int netbeansFireChanges INIT(= 1); /* send buffer changes if != 0 */
+EXTERN int netbeansForcedQuit INIT(= 0);/* don't write modified files */
+EXTERN int netbeansOpenFile INIT(= 1); /* send fileOpened if != 0 */
+EXTERN int netbeansReadFile INIT(= 1); /* OK to read from disk if != 0 */
+EXTERN int netbeansSuppressNoLines INIT(= 0); /* skip "No lines in buffer" */
+EXTERN int usingNetbeans INIT(= 0); /* set if -nb flag is used */
+#endif
+
+/*
+ * The error messages that can be shared are included here.
+ * Excluded are errors that are only used once and debugging messages.
+ */
+EXTERN char_u e_abort[] INIT(=N_("E470: Command aborted"));
+EXTERN char_u e_argreq[] INIT(=N_("E471: Argument required"));
+EXTERN char_u e_backslash[] INIT(=N_("E10: \\ should be followed by /, ? or &"));
+#ifdef FEAT_CMDWIN
+EXTERN char_u e_cmdwin[] INIT(=N_("E11: Invalid in command-line window; <CR> executes, CTRL-C quits"));
+#endif
+EXTERN char_u e_curdir[] INIT(=N_("E12: Command not allowed from exrc/vimrc in current dir or tag search"));
+#ifdef FEAT_EVAL
+EXTERN char_u e_endif[] INIT(=N_("E171: Missing :endif"));
+EXTERN char_u e_endtry[] INIT(=N_("E600: Missing :endtry"));
+EXTERN char_u e_endwhile[] INIT(=N_("E170: Missing :endwhile"));
+EXTERN char_u e_while[] INIT(=N_("E588: :endwhile without :while"));
+#endif
+EXTERN char_u e_exists[] INIT(=N_("E13: File exists (add ! to override)"));
+EXTERN char_u e_failed[] INIT(=N_("E472: Command failed"));
+#if defined(FEAT_GUI) && defined(FEAT_XFONTSET)
+EXTERN char_u e_fontset[] INIT(=N_("E234: Unknown fontset: %s"));
+#endif
+#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(MACOS) \
+ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MSWIN)
+EXTERN char_u e_font[] INIT(=N_("E235: Unknown font: %s"));
+#endif
+#if (defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)) && !defined(HAVE_GTK2)
+EXTERN char_u e_fontwidth[] INIT(=N_("E236: Font \"%s\" is not fixed-width"));
+#endif
+EXTERN char_u e_internal[] INIT(=N_("E473: Internal error"));
+EXTERN char_u e_interr[] INIT(=N_("Interrupted"));
+EXTERN char_u e_invaddr[] INIT(=N_("E14: Invalid address"));
+EXTERN char_u e_invarg[] INIT(=N_("E474: Invalid argument"));
+EXTERN char_u e_invarg2[] INIT(=N_("E475: Invalid argument: %s"));
+#ifdef FEAT_EVAL
+EXTERN char_u e_invexpr2[] INIT(=N_("E15: Invalid expression: %s"));
+#endif
+EXTERN char_u e_invrange[] INIT(=N_("E16: Invalid range"));
+EXTERN char_u e_invcmd[] INIT(=N_("E476: Invalid command"));
+#ifdef UNIX
+EXTERN char_u e_isadir2[] INIT(=N_("E17: \"%s\" is a directory"));
+#endif
+#ifdef FEAT_EVAL
+EXTERN char_u e_letunexp[] INIT(=N_("E18: Unexpected characters before '='"));
+#endif
+#ifdef FEAT_LIBCALL
+EXTERN char_u e_libcall[] INIT(=N_("E364: Library call failed for \"%s()\""));
+#endif
+#if defined(DYNAMIC_PERL) || defined(DYNAMIC_PYTHON) || defined(DYNAMIC_RUBY) \
+ || defined(DYNAMIC_TCL) || defined(DYNAMIC_ICONV) \
+ || defined(DYNAMIC_GETTEXT)
+EXTERN char_u e_loadlib[] INIT(=N_("E370: Could not load library %s"));
+EXTERN char_u e_loadfunc[] INIT(=N_("E448: Could not load library function %s"));
+#endif
+EXTERN char_u e_markinval[] INIT(=N_("E19: Mark has invalid line number"));
+EXTERN char_u e_marknotset[] INIT(=N_("E20: Mark not set"));
+EXTERN char_u e_modifiable[] INIT(=N_("E21: Cannot make changes, 'modifiable' is off"));
+EXTERN char_u e_nesting[] INIT(=N_("E22: Scripts nested too deep"));
+EXTERN char_u e_noalt[] INIT(=N_("E23: No alternate file"));
+EXTERN char_u e_noabbr[] INIT(=N_("E24: No such abbreviation"));
+EXTERN char_u e_nobang[] INIT(=N_("E477: No ! allowed"));
+#ifndef FEAT_GUI
+EXTERN char_u e_nogvim[] INIT(=N_("E25: GUI cannot be used: Not enabled at compile time"));
+#endif
+#ifndef FEAT_RIGHTLEFT
+EXTERN char_u e_nohebrew[] INIT(=N_("E26: Hebrew cannot be used: Not enabled at compile time\n"));
+#endif
+#ifndef FEAT_FKMAP
+EXTERN char_u e_nofarsi[] INIT(=N_("E27: Farsi cannot be used: Not enabled at compile time\n"));
+#endif
+#ifndef FEAT_ARABIC
+EXTERN char_u e_noarabic[] INIT(=N_("E800: Arabic cannot be used: Not enabled at compile time\n"));
+#endif
+#if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_SYN_HL)
+EXTERN char_u e_nogroup[] INIT(=N_("E28: No such highlight group name: %s"));
+#endif
+EXTERN char_u e_noinstext[] INIT(=N_("E29: No inserted text yet"));
+EXTERN char_u e_nolastcmd[] INIT(=N_("E30: No previous command line"));
+EXTERN char_u e_nomap[] INIT(=N_("E31: No such mapping"));
+EXTERN char_u e_nomatch[] INIT(=N_("E479: No match"));
+EXTERN char_u e_nomatch2[] INIT(=N_("E480: No match: %s"));
+EXTERN char_u e_noname[] INIT(=N_("E32: No file name"));
+EXTERN char_u e_nopresub[] INIT(=N_("E33: No previous substitute regular expression"));
+EXTERN char_u e_noprev[] INIT(=N_("E34: No previous command"));
+EXTERN char_u e_noprevre[] INIT(=N_("E35: No previous regular expression"));
+EXTERN char_u e_norange[] INIT(=N_("E481: No range allowed"));
+#ifdef FEAT_WINDOWS
+EXTERN char_u e_noroom[] INIT(=N_("E36: Not enough room"));
+#endif
+#ifdef FEAT_CLIENTSERVER
+EXTERN char_u e_noserver[] INIT(=N_("E247: no registered server named \"%s\""));
+#endif
+EXTERN char_u e_notcreate[] INIT(=N_("E482: Can't create file %s"));
+EXTERN char_u e_notmp[] INIT(=N_("E483: Can't get temp file name"));
+EXTERN char_u e_notopen[] INIT(=N_("E484: Can't open file %s"));
+EXTERN char_u e_notread[] INIT(=N_("E485: Can't read file %s"));
+EXTERN char_u e_nowrtmsg[] INIT(=N_("E37: No write since last change (add ! to override)"));
+EXTERN char_u e_null[] INIT(=N_("E38: Null argument"));
+#ifdef FEAT_DIGRAPHS
+EXTERN char_u e_number_exp[] INIT(=N_("E39: Number expected"));
+#endif
+#ifdef FEAT_QUICKFIX
+EXTERN char_u e_openerrf[] INIT(=N_("E40: Can't open errorfile %s"));
+#endif
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11)
+EXTERN char_u e_opendisp[] INIT(=N_("E233: cannot open display"));
+#endif
+EXTERN char_u e_outofmem[] INIT(=N_("E41: Out of memory!"));
+#ifdef FEAT_INS_EXPAND
+EXTERN char_u e_patnotf[] INIT(=N_("Pattern not found"));
+#endif
+EXTERN char_u e_patnotf2[] INIT(=N_("E486: Pattern not found: %s"));
+EXTERN char_u e_positive[] INIT(=N_("E487: Argument must be positive"));
+#if defined(UNIX) || defined(FEAT_SESSION)
+EXTERN char_u e_prev_dir[] INIT(=N_("E459: Cannot go back to previous directory"));
+#endif
+
+#ifdef FEAT_QUICKFIX
+EXTERN char_u e_quickfix[] INIT(=N_("E42: No Errors"));
+#endif
+EXTERN char_u e_re_damg[] INIT(=N_("E43: Damaged match string"));
+EXTERN char_u e_re_corr[] INIT(=N_("E44: Corrupted regexp program"));
+EXTERN char_u e_readonly[] INIT(=N_("E45: 'readonly' option is set (add ! to override)"));
+#ifdef FEAT_EVAL
+EXTERN char_u e_readonlyvar[] INIT(=N_("E46: Cannot set read-only variable \"%s\""));
+#endif
+#ifdef FEAT_QUICKFIX
+EXTERN char_u e_readerrf[] INIT(=N_("E47: Error while reading errorfile"));
+#endif
+#ifdef HAVE_SANDBOX
+EXTERN char_u e_sandbox[] INIT(=N_("E48: Not allowed in sandbox"));
+#endif
+EXTERN char_u e_secure[] INIT(=N_("E523: Not allowed here"));
+#if defined(AMIGA) || defined(MACOS) || defined(MSWIN) || defined(RISCOS) \
+ || defined(UNIX) || defined(VMS)
+EXTERN char_u e_screenmode[] INIT(=N_("E359: Screen mode setting not supported"));
+#endif
+EXTERN char_u e_scroll[] INIT(=N_("E49: Invalid scroll size"));
+EXTERN char_u e_shellempty[] INIT(=N_("E91: 'shell' option is empty"));
+#if defined(FEAT_SIGN_ICONS) && !defined(HAVE_GTK2)
+EXTERN char_u e_signdata[] INIT(=N_("E255: Couldn't read in sign data!"));
+#endif
+EXTERN char_u e_swapclose[] INIT(=N_("E72: Close error on swap file"));
+EXTERN char_u e_tagstack[] INIT(=N_("E73: tag stack empty"));
+EXTERN char_u e_toocompl[] INIT(=N_("E74: Command too complex"));
+EXTERN char_u e_longname[] INIT(=N_("E75: Name too long"));
+EXTERN char_u e_toomsbra[] INIT(=N_("E76: Too many ["));
+EXTERN char_u e_toomany[] INIT(=N_("E77: Too many file names"));
+EXTERN char_u e_trailing[] INIT(=N_("E488: Trailing characters"));
+EXTERN char_u e_umark[] INIT(=N_("E78: Unknown mark"));
+EXTERN char_u e_wildexpand[] INIT(=N_("E79: Cannot expand wildcards"));
+#ifdef FEAT_WINDOWS
+EXTERN char_u e_winheight[] INIT(=N_("E591: 'winheight' cannot be smaller than 'winminheight'"));
+# ifdef FEAT_VERTSPLIT
+EXTERN char_u e_winwidth[] INIT(=N_("E592: 'winwidth' cannot be smaller than 'winminwidth'"));
+# endif
+#endif
+EXTERN char_u e_write[] INIT(=N_("E80: Error while writing"));
+EXTERN char_u e_zerocount[] INIT(=N_("Zero count"));
+#ifdef FEAT_EVAL
+EXTERN char_u e_usingsid[] INIT(=N_("E81: Using <SID> not in a script context"));
+#endif
+#ifdef FEAT_CLIENTSERVER
+EXTERN char_u e_invexprmsg[] INIT(=N_("E449: Invalid expression received"));
+#endif
+#ifdef FEAT_NETBEANS_INTG
+EXTERN char_u e_guarded[] INIT(=N_("E463: Region is guarded, cannot modify"));
+#endif
+#ifdef MACOS_X_UNIX
+EXTERN short disallow_gui INIT(= FALSE);
+#endif
+
+/*
+ * Comms. with the session manager (XSMP)
+ */
+#ifdef USE_XSMP
+EXTERN int xsmp_icefd INIT(= -1); /* The actual connection */
+#endif
+
+/*
+ * Optional Farsi support. Include it here, so EXTERN and INIT are defined.
+ */
+#ifdef FEAT_FKMAP
+# include "farsi.h"
+#endif
+
+/*
+ * Optional Arabic support. Include it here, so EXTERN and INIT are defined.
+ */
+#ifdef FEAT_ARABIC
+# include "arabic.h"
+#endif
diff --git a/src/gui.c b/src/gui.c
new file mode 100644
index 000000000..3ffa2257d
--- /dev/null
+++ b/src/gui.c
@@ -0,0 +1,4740 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI/Motif support by Robert Webb
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+
+/* Structure containing all the GUI information */
+gui_T gui;
+
+#if defined(FEAT_MBYTE) && !defined(HAVE_GTK2)
+static void set_guifontwide __ARGS((char_u *font_name));
+#endif
+static void gui_check_pos __ARGS((void));
+static void gui_position_components __ARGS((int));
+static void gui_outstr __ARGS((char_u *, int));
+static int gui_screenchar __ARGS((int off, int flags, guicolor_T fg, guicolor_T bg, int back));
+#ifdef HAVE_GTK2
+static int gui_screenstr __ARGS((int off, int len, int flags, guicolor_T fg, guicolor_T bg, int back));
+#endif
+static void gui_delete_lines __ARGS((int row, int count));
+static void gui_insert_lines __ARGS((int row, int count));
+static void fill_mouse_coord __ARGS((char_u *p, int col, int row));
+static void gui_do_scrollbar __ARGS((win_T *wp, int which, int enable));
+static colnr_T scroll_line_len __ARGS((linenr_T lnum));
+static void gui_update_horiz_scrollbar __ARGS((int));
+static win_T *xy2win __ARGS((int x, int y));
+
+static int can_update_cursor = TRUE; /* can display the cursor */
+
+/*
+ * The Athena scrollbars can move the thumb to after the end of the scrollbar,
+ * this makes the thumb indicate the part of the text that is shown. Motif
+ * can't do this.
+ */
+#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MAC)
+# define SCROLL_PAST_END
+#endif
+
+/*
+ * gui_start -- Called when user wants to start the GUI.
+ *
+ * Careful: This function can be called recursively when there is a ":gui"
+ * command in the .gvimrc file. Only the first call should fork, not the
+ * recursive call.
+ */
+ void
+gui_start()
+{
+ char_u *old_term;
+#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOS_X)
+# define MAY_FORK
+ int dofork = TRUE;
+#endif
+ static int recursive = 0;
+
+ old_term = vim_strsave(T_NAME);
+
+ /*
+ * Set_termname() will call gui_init() to start the GUI.
+ * Set the "starting" flag, to indicate that the GUI will start.
+ *
+ * We don't want to open the GUI shell until after we've read .gvimrc,
+ * otherwise we don't know what font we will use, and hence we don't know
+ * what size the shell should be. So if there are errors in the .gvimrc
+ * file, they will have to go to the terminal: Set full_screen to FALSE.
+ * full_screen will be set to TRUE again by a successful termcapinit().
+ */
+ settmode(TMODE_COOK); /* stop RAW mode */
+ if (full_screen)
+ cursor_on(); /* needed for ":gui" in .vimrc */
+ gui.starting = TRUE;
+ full_screen = FALSE;
+
+#ifdef MAY_FORK
+ if (!gui.dofork || vim_strchr(p_go, GO_FORG) || recursive)
+ dofork = FALSE;
+#endif
+ ++recursive;
+
+ termcapinit((char_u *)"builtin_gui");
+ gui.starting = recursive - 1;
+
+ if (!gui.in_use) /* failed to start GUI */
+ {
+ termcapinit(old_term); /* back to old term settings */
+ settmode(TMODE_RAW); /* restart RAW mode */
+#ifdef FEAT_TITLE
+ set_title_defaults(); /* set 'title' and 'icon' again */
+#endif
+ }
+
+ vim_free(old_term);
+
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11)
+ if (gui.in_use)
+ /* Display error messages in a dialog now. */
+ display_errors();
+#endif
+
+#if defined(MAY_FORK) && !defined(__QNXNTO__)
+ /*
+ * Quit the current process and continue in the child.
+ * Makes "gvim file" disconnect from the shell it was started in.
+ * Don't do this when Vim was started with "-f" or the 'f' flag is present
+ * in 'guioptions'.
+ */
+ if (gui.in_use && dofork)
+ {
+ int pipefd[2]; /* pipe between parent and child */
+ int pipe_error;
+ char dummy;
+ pid_t pid = -1;
+
+ /* Setup a pipe between the child and the parent, so that the parent
+ * knows when the child has done the setsid() call and is allowed to
+ * exit. */
+ pipe_error = (pipe(pipefd) < 0);
+ pid = fork();
+ if (pid > 0) /* Parent */
+ {
+ /* Give the child some time to do the setsid(), otherwise the
+ * exit() may kill the child too (when starting gvim from inside a
+ * gvim). */
+ if (pipe_error)
+ ui_delay(300L, TRUE);
+ else
+ {
+ /* The read returns when the child closes the pipe (or when
+ * the child dies for some reason). */
+ close(pipefd[1]);
+ (void)read(pipefd[0], &dummy, (size_t)1);
+ close(pipefd[0]);
+ }
+
+ /* When swapping screens we may need to go to the next line, e.g.,
+ * after a hit-enter prompt and using ":gui". */
+ if (newline_on_exit)
+ mch_errmsg("\r\n");
+
+ /*
+ * The parent must skip the normal exit() processing, the child
+ * will do it. For example, GTK messes up signals when exiting.
+ */
+ _exit(0);
+ }
+
+# if defined(HAVE_SETSID) || defined(HAVE_SETPGID)
+ /*
+ * Change our process group. On some systems/shells a CTRL-C in the
+ * shell where Vim was started would otherwise kill gvim!
+ */
+ if (pid == 0) /* child */
+# if defined(HAVE_SETSID)
+ (void)setsid();
+# else
+ (void)setpgid(0, 0);
+# endif
+# endif
+ if (!pipe_error)
+ {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ }
+
+# if defined(FEAT_GUI_GNOME) && defined(FEAT_SESSION)
+ /* Tell the session manager our new PID */
+ gui_mch_forked();
+# endif
+ }
+#else
+# if defined(__QNXNTO__)
+ if (gui.in_use && dofork)
+ procmgr_daemon(0, PROCMGR_DAEMON_KEEPUMASK | PROCMGR_DAEMON_NOCHDIR |
+ PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL);
+# endif
+#endif
+
+#ifdef FEAT_AUTOCMD
+ /* If the GUI started successfully, trigger the GUIEnter event */
+ if (gui.in_use)
+ apply_autocmds(EVENT_GUIENTER, NULL, NULL, FALSE, curbuf);
+#endif
+
+ --recursive;
+}
+
+/*
+ * Call this when vim starts up, whether or not the GUI is started
+ */
+ void
+gui_prepare(argc, argv)
+ int *argc;
+ char **argv;
+{
+ gui.in_use = FALSE; /* No GUI yet (maybe later) */
+ gui.starting = FALSE; /* No GUI yet (maybe later) */
+ gui_mch_prepare(argc, argv);
+}
+
+/*
+ * Try initializing the GUI and check if it can be started.
+ * Used from main() to check early if "vim -g" can start the GUI.
+ * Used from gui_init() to prepare for starting the GUI.
+ * Returns FAIL or OK.
+ */
+ int
+gui_init_check()
+{
+ static int result = MAYBE;
+
+ if (result != MAYBE)
+ {
+ if (result == FAIL)
+ EMSG(_("E229: Cannot start the GUI"));
+ return result;
+ }
+
+ gui.shell_created = FALSE;
+ gui.dying = FALSE;
+ gui.in_focus = TRUE; /* so the guicursor setting works */
+ gui.dragged_sb = SBAR_NONE;
+ gui.dragged_wp = NULL;
+ gui.pointer_hidden = FALSE;
+ gui.col = 0;
+ gui.row = 0;
+ gui.num_cols = Columns;
+ gui.num_rows = Rows;
+
+ gui.cursor_is_valid = FALSE;
+ gui.scroll_region_top = 0;
+ gui.scroll_region_bot = Rows - 1;
+ gui.scroll_region_left = 0;
+ gui.scroll_region_right = Columns - 1;
+ gui.highlight_mask = HL_NORMAL;
+ gui.char_width = 1;
+ gui.char_height = 1;
+ gui.char_ascent = 0;
+ gui.border_width = 0;
+
+ gui.norm_font = NOFONT;
+#ifndef HAVE_GTK2
+ gui.bold_font = NOFONT;
+ gui.ital_font = NOFONT;
+ gui.boldital_font = NOFONT;
+# ifdef FEAT_XFONTSET
+ gui.fontset = NOFONTSET;
+# endif
+#endif
+
+#ifdef FEAT_MENU
+# ifndef HAVE_GTK2
+# ifdef FONTSET_ALWAYS
+ gui.menu_fontset = NOFONTSET;
+# else
+ gui.menu_font = NOFONT;
+# endif
+# endif
+ gui.menu_is_active = TRUE; /* default: include menu */
+# ifndef FEAT_GUI_GTK
+ gui.menu_height = MENU_DEFAULT_HEIGHT;
+ gui.menu_width = 0;
+# endif
+#endif
+#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA))
+ gui.toolbar_height = 0;
+#endif
+#if defined(FEAT_FOOTER) && defined(FEAT_GUI_MOTIF)
+ gui.footer_height = 0;
+#endif
+#ifdef FEAT_BEVAL_TIP
+ gui.tooltip_fontset = NOFONTSET;
+#endif
+
+ gui.scrollbar_width = gui.scrollbar_height = SB_DEFAULT_WIDTH;
+ gui.prev_wrap = -1;
+
+#ifdef ALWAYS_USE_GUI
+ result = OK;
+#else
+ result = gui_mch_init_check();
+#endif
+ return result;
+}
+
+/*
+ * This is the call which starts the GUI.
+ */
+ void
+gui_init()
+{
+ win_T *wp;
+ static int recursive = 0;
+
+ /*
+ * It's possible to use ":gui" in a .gvimrc file. The first halve of this
+ * function will then be executed at the first call, the rest by the
+ * recursive call. This allow the shell to be opened halfway reading a
+ * gvimrc file.
+ */
+ if (!recursive)
+ {
+ ++recursive;
+
+ clip_init(TRUE);
+
+ /* If can't initialize, don't try doing the rest */
+ if (gui_init_check() == FAIL)
+ {
+ --recursive;
+ clip_init(FALSE);
+ return;
+ }
+
+ /*
+ * Set up system-wide default menus.
+ */
+#if defined(SYS_MENU_FILE) && defined(FEAT_MENU)
+ if (vim_strchr(p_go, GO_NOSYSMENU) == NULL)
+ {
+ sys_menu = TRUE;
+ do_source((char_u *)SYS_MENU_FILE, FALSE, FALSE);
+ sys_menu = FALSE;
+ }
+#endif
+
+ /*
+ * Switch on the mouse by default, unless the user changed it already.
+ * This can then be changed in the .gvimrc.
+ */
+ if (!option_was_set((char_u *)"mouse"))
+ set_string_option_direct((char_u *)"mouse", -1,
+ (char_u *)"a", OPT_FREE);
+
+ /*
+ * If -U option given, use only the initializations from that file and
+ * nothing else. Skip all initializations for "-U NONE" or "-u NORC".
+ */
+ if (use_gvimrc != NULL)
+ {
+ if (STRCMP(use_gvimrc, "NONE") != 0
+ && STRCMP(use_gvimrc, "NORC") != 0
+ && do_source(use_gvimrc, FALSE, FALSE) != OK)
+ EMSG2(_("E230: Cannot read from \"%s\""), use_gvimrc);
+ }
+ else
+ {
+ /*
+ * Get system wide defaults for gvim, only when file name defined.
+ */
+#ifdef SYS_GVIMRC_FILE
+ do_source((char_u *)SYS_GVIMRC_FILE, FALSE, FALSE);
+#endif
+
+ /*
+ * Try to read GUI initialization commands from the following
+ * places:
+ * - environment variable GVIMINIT
+ * - the user gvimrc file (~/.gvimrc)
+ * - the second user gvimrc file ($VIM/.gvimrc for Dos)
+ * - the third user gvimrc file ($VIM/.gvimrc for Amiga)
+ * The first that exists is used, the rest is ignored.
+ */
+ if (process_env((char_u *)"GVIMINIT", FALSE) == FAIL
+ && do_source((char_u *)USR_GVIMRC_FILE, TRUE, FALSE) == FAIL
+#ifdef USR_GVIMRC_FILE2
+ && do_source((char_u *)USR_GVIMRC_FILE2, TRUE, FALSE) == FAIL
+#endif
+ )
+ {
+#ifdef USR_GVIMRC_FILE3
+ (void)do_source((char_u *)USR_GVIMRC_FILE3, TRUE, FALSE);
+#endif
+ }
+
+ /*
+ * Read initialization commands from ".gvimrc" in current
+ * directory. This is only done if the 'exrc' option is set.
+ * Because of security reasons we disallow shell and write
+ * commands now, except for unix if the file is owned by the user
+ * or 'secure' option has been reset in environment of global
+ * ".gvimrc".
+ * Only do this if GVIMRC_FILE is not the same as USR_GVIMRC_FILE,
+ * USR_GVIMRC_FILE2, USR_GVIMRC_FILE3 or SYS_GVIMRC_FILE.
+ */
+ if (p_exrc)
+ {
+#ifdef UNIX
+ {
+ struct stat s;
+
+ /* if ".gvimrc" file is not owned by user, set 'secure'
+ * mode */
+ if (mch_stat(GVIMRC_FILE, &s) || s.st_uid != getuid())
+ secure = p_secure;
+ }
+#else
+ secure = p_secure;
+#endif
+
+ if ( fullpathcmp((char_u *)USR_GVIMRC_FILE,
+ (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME
+#ifdef SYS_GVIMRC_FILE
+ && fullpathcmp((char_u *)SYS_GVIMRC_FILE,
+ (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME
+#endif
+#ifdef USR_GVIMRC_FILE2
+ && fullpathcmp((char_u *)USR_GVIMRC_FILE2,
+ (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME
+#endif
+#ifdef USR_GVIMRC_FILE3
+ && fullpathcmp((char_u *)USR_GVIMRC_FILE3,
+ (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME
+#endif
+ )
+ do_source((char_u *)GVIMRC_FILE, TRUE, FALSE);
+
+ if (secure == 2)
+ need_wait_return = TRUE;
+ secure = 0;
+ }
+ }
+
+ if (need_wait_return || msg_didany)
+ wait_return(TRUE);
+
+ --recursive;
+ }
+
+ /* If recursive call opened the shell, return here from the first call */
+ if (gui.in_use)
+ return;
+
+ /*
+ * Create the GUI shell.
+ */
+ gui.in_use = TRUE; /* Must be set after menus have been set up */
+ if (gui_mch_init() == FAIL)
+ goto error;
+
+ /* Avoid a delay for an error message that was printed in the terminal
+ * where Vim was started. */
+ emsg_on_display = FALSE;
+ msg_scrolled = 0;
+ need_wait_return = FALSE;
+ msg_didany = FALSE;
+
+ /*
+ * Check validity of any generic resources that may have been loaded.
+ */
+ if (gui.border_width < 0)
+ gui.border_width = 0;
+
+ /*
+ * Set up the fonts. First use a font specified with "-fn" or "-font".
+ */
+ if (font_argument != NULL)
+ set_option_value((char_u *)"gfn", 0L, (char_u *)font_argument, 0);
+ if (
+#ifdef FEAT_XFONTSET
+ (*p_guifontset == NUL
+ || gui_init_font(p_guifontset, TRUE) == FAIL) &&
+#endif
+ gui_init_font(*p_guifont == NUL ? hl_get_font_name()
+ : p_guifont, FALSE) == FAIL)
+ {
+ EMSG(_("E665: Cannot start GUI, no valid font found"));
+ goto error2;
+ }
+#ifdef FEAT_MBYTE
+ if (gui_get_wide_font() == FAIL)
+ EMSG(_("E231: 'guifontwide' invalid"));
+#endif
+
+ gui.num_cols = Columns;
+ gui.num_rows = Rows;
+ gui_reset_scroll_region();
+
+ /* Create initial scrollbars */
+ FOR_ALL_WINDOWS(wp)
+ {
+ gui_create_scrollbar(&wp->w_scrollbars[SBAR_LEFT], SBAR_LEFT, wp);
+ gui_create_scrollbar(&wp->w_scrollbars[SBAR_RIGHT], SBAR_RIGHT, wp);
+ }
+ gui_create_scrollbar(&gui.bottom_sbar, SBAR_BOTTOM, NULL);
+
+#ifdef FEAT_MENU
+ gui_create_initial_menus(root_menu);
+#endif
+#ifdef FEAT_SUN_WORKSHOP
+ if (usingSunWorkShop)
+ workshop_init();
+#endif
+#ifdef FEAT_SIGN_ICONS
+ sign_gui_started();
+#endif
+
+ /* Configure the desired menu and scrollbars */
+ gui_init_which_components(NULL);
+
+ /* All components of the GUI have been created now */
+ gui.shell_created = TRUE;
+
+#ifndef FEAT_GUI_GTK
+ /* Set the shell size, adjusted for the screen size. For GTK this only
+ * works after the shell has been opened, thus it is further down. */
+ gui_set_shellsize(FALSE, TRUE);
+#endif
+#if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU)
+ /* Need to set the size of the menubar after all the menus have been
+ * created. */
+ gui_mch_compute_menu_height((Widget)0);
+#endif
+
+ /*
+ * Actually open the GUI shell.
+ */
+ if (gui_mch_open() != FAIL)
+ {
+#ifdef FEAT_TITLE
+ maketitle();
+ resettitle();
+#endif
+ init_gui_options();
+#ifdef FEAT_ARABIC
+ /* Our GUI can't do bidi. */
+ p_tbidi = FALSE;
+#endif
+#ifdef FEAT_GUI_GTK
+ /* Give GTK+ a chance to put all widget's into place. */
+ gui_mch_update();
+ /* Now make sure the shell fits on the screen. */
+ gui_set_shellsize(FALSE, TRUE);
+#endif
+#ifdef FEAT_NETBEANS_INTG
+ if (starting == 0 && usingNetbeans)
+ /* Tell the client that it can start sending commands. */
+ netbeans_startup_done();
+#endif
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+ if (!im_xim_isvalid_imactivate())
+ EMSG(_("E599: Value of 'imactivatekey' is invalid"));
+#endif
+
+ return;
+ }
+
+error2:
+#ifdef FEAT_GUI_X11
+ /* undo gui_mch_init() */
+ gui_mch_uninit();
+#endif
+
+error:
+ gui.in_use = FALSE;
+ clip_init(FALSE);
+}
+
+
+ void
+gui_exit(rc)
+ int rc;
+{
+#ifndef __BEOS__
+ /* don't free the fonts, it leads to a BUS error
+ * richard@whitequeen.com Jul 99 */
+ free_highlight_fonts();
+#endif
+ gui.in_use = FALSE;
+ gui_mch_exit(rc);
+}
+
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_MSWIN) \
+ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(PROTO)
+/*
+ * Called when the GUI shell is closed by the user. If there are no changed
+ * files Vim exits, otherwise there will be a dialog to ask the user what to
+ * do.
+ * When this function returns, Vim should NOT exit!
+ */
+ void
+gui_shell_closed()
+{
+ cmdmod_T save_cmdmod;
+
+ save_cmdmod = cmdmod;
+
+ /* Only exit when there are no changed files */
+ exiting = TRUE;
+# ifdef FEAT_BROWSE
+ cmdmod.browse = TRUE;
+# endif
+# if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ cmdmod.confirm = TRUE;
+# endif
+ /* If there are changed buffers, present the user with a dialog if
+ * possible, otherwise give an error message. */
+ if (!check_changed_any(FALSE))
+ getout(0);
+
+ exiting = FALSE;
+ cmdmod = save_cmdmod;
+ setcursor(); /* position cursor */
+ out_flush();
+}
+#endif
+
+/*
+ * Set the font. "font_list" is a a comma separated list of font names. The
+ * first font name that works is used. If none is found, use the default
+ * font.
+ * If "fontset" is TRUE, the "font_list" is used as one name for the fontset.
+ * Return OK when able to set the font. When it failed FAIL is returned and
+ * the fonts are unchanged.
+ */
+/*ARGSUSED*/
+ int
+gui_init_font(font_list, fontset)
+ char_u *font_list;
+ int fontset;
+{
+#define FONTLEN 320
+ char_u font_name[FONTLEN];
+ int font_list_empty = FALSE;
+ int ret = FAIL;
+
+ if (!gui.in_use)
+ return FAIL;
+
+ font_name[0] = NUL;
+ if (*font_list == NUL)
+ font_list_empty = TRUE;
+ else
+ {
+#ifdef FEAT_XFONTSET
+ /* When using a fontset, the whole list of fonts is one name. */
+ if (fontset)
+ ret = gui_mch_init_font(font_list, TRUE);
+ else
+#endif
+ while (*font_list != NUL)
+ {
+ /* Isolate one comma separated font name. */
+ (void)copy_option_part(&font_list, font_name, FONTLEN, ",");
+
+ /* Careful!!! The Win32 version of gui_mch_init_font(), when
+ * called with "*" will change p_guifont to the selected font
+ * name, which frees the old value. This makes font_list
+ * invalid. Thus when OK is returned here, font_list must no
+ * longer be used! */
+ if (gui_mch_init_font(font_name, FALSE) == OK)
+ {
+#if defined(FEAT_MBYTE) && !defined(HAVE_GTK2)
+ /* If it's a Unicode font, try setting 'guifontwide' to a
+ * similar double-width font. */
+ if ((p_guifontwide == NULL || *p_guifontwide == NUL)
+ && strstr((char *)font_name, "10646") != NULL)
+ set_guifontwide(font_name);
+#endif
+ ret = OK;
+ break;
+ }
+ }
+ }
+
+ if (ret != OK
+ && STRCMP(font_list, "*") != 0
+ && (font_list_empty || gui.norm_font == NOFONT))
+ {
+ /*
+ * Couldn't load any font in 'font_list', keep the current font if
+ * there is one. If 'font_list' is empty, or if there is no current
+ * font, tell gui_mch_init_font() to try to find a font we can load.
+ */
+ ret = gui_mch_init_font(NULL, FALSE);
+ }
+
+ if (ret == OK)
+ {
+#ifndef HAVE_GTK2
+ /* Set normal font as current font */
+# ifdef FEAT_XFONTSET
+ if (gui.fontset != NOFONTSET)
+ gui_mch_set_fontset(gui.fontset);
+ else
+# endif
+ gui_mch_set_font(gui.norm_font);
+#endif
+ gui_set_shellsize(FALSE,
+#ifdef MSWIN
+ TRUE
+#else
+ FALSE
+#endif
+ );
+ }
+
+ return ret;
+}
+
+#if defined(FEAT_MBYTE) || defined(PROTO)
+# ifndef HAVE_GTK2
+/*
+ * Try setting 'guifontwide' to a font twice as wide as "name".
+ */
+ static void
+set_guifontwide(name)
+ char_u *name;
+{
+ int i = 0;
+ char_u wide_name[FONTLEN + 10]; /* room for 2 * width and '*' */
+ char_u *wp = NULL;
+ char_u *p;
+ GuiFont font;
+
+ wp = wide_name;
+ for (p = name; *p != NUL; ++p)
+ {
+ *wp++ = *p;
+ if (*p == '-')
+ {
+ ++i;
+ if (i == 6) /* font type: change "--" to "-*-" */
+ {
+ if (p[1] == '-')
+ *wp++ = '*';
+ }
+ else if (i == 12) /* found the width */
+ {
+ ++p;
+ i = getdigits(&p);
+ if (i != 0)
+ {
+ /* Double the width specification. */
+ sprintf((char *)wp, "%d%s", i * 2, p);
+ font = gui_mch_get_font(wide_name, FALSE);
+ if (font != NOFONT)
+ {
+ gui.wide_font = font;
+ set_string_option_direct((char_u *)"gfw", -1,
+ wide_name, OPT_FREE);
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+# endif /* !HAVE_GTK2 */
+
+/*
+ * Get the font for 'guifontwide'.
+ * Return FAIL for an invalid font name.
+ */
+ int
+gui_get_wide_font()
+{
+ GuiFont font = NOFONT;
+ char_u font_name[FONTLEN];
+ char_u *p;
+
+ if (!gui.in_use) /* Can't allocate font yet, assume it's OK. */
+ return OK; /* Will give an error message later. */
+
+ if (p_guifontwide != NULL && *p_guifontwide != NUL)
+ {
+ for (p = p_guifontwide; *p != NUL; )
+ {
+ /* Isolate one comma separated font name. */
+ (void)copy_option_part(&p, font_name, FONTLEN, ",");
+ font = gui_mch_get_font(font_name, FALSE);
+ if (font != NOFONT)
+ break;
+ }
+ if (font == NOFONT)
+ return FAIL;
+ }
+
+ gui_mch_free_font(gui.wide_font);
+#ifdef HAVE_GTK2
+ /* Avoid unnecessary overhead if 'guifontwide' is equal to 'guifont'. */
+ if (font != NOFONT && gui.norm_font != NOFONT
+ && pango_font_description_equal(font, gui.norm_font))
+ {
+ gui.wide_font = NOFONT;
+ gui_mch_free_font(font);
+ }
+ else
+#endif
+ gui.wide_font = font;
+ return OK;
+}
+#endif
+
+ void
+gui_set_cursor(row, col)
+ int row;
+ int col;
+{
+ gui.row = row;
+ gui.col = col;
+}
+
+/*
+ * gui_check_pos - check if the cursor is on the screen.
+ */
+ static void
+gui_check_pos()
+{
+ if (gui.row >= screen_Rows)
+ gui.row = screen_Rows - 1;
+ if (gui.col >= screen_Columns)
+ gui.col = screen_Columns - 1;
+ if (gui.cursor_row >= screen_Rows || gui.cursor_col >= screen_Columns)
+ gui.cursor_is_valid = FALSE;
+}
+
+/*
+ * Redraw the cursor if necessary or when forced.
+ * Careful: The contents of ScreenLines[] must match what is on the screen,
+ * otherwise this goes wrong. May need to call out_flush() first.
+ */
+ void
+gui_update_cursor(force, clear_selection)
+ int force; /* when TRUE, update even when not moved */
+ int clear_selection;/* clear selection under cursor */
+{
+ int cur_width = 0;
+ int cur_height = 0;
+ int old_hl_mask;
+ int idx;
+ int id;
+ guicolor_T cfg, cbg, cc; /* cursor fore-/background color */
+ int cattr; /* cursor attributes */
+ int attr;
+ attrentry_T *aep = NULL;
+
+ /* Don't update the cursor when halfway busy scrolling.
+ * ScreenLines[] isn't valid then. */
+ if (!can_update_cursor)
+ return;
+
+ gui_check_pos();
+ if (!gui.cursor_is_valid || force
+ || gui.row != gui.cursor_row || gui.col != gui.cursor_col)
+ {
+ gui_undraw_cursor();
+ if (gui.row < 0)
+ return;
+#ifdef USE_IM_CONTROL
+ if (gui.row != gui.cursor_row || gui.col != gui.cursor_col)
+ im_set_position(gui.row, gui.col);
+#endif
+ gui.cursor_row = gui.row;
+ gui.cursor_col = gui.col;
+
+ /* Only write to the screen after ScreenLines[] has been initialized */
+ if (!screen_cleared || ScreenLines == NULL)
+ return;
+
+ /* Clear the selection if we are about to write over it */
+ if (clear_selection)
+ clip_may_clear_selection(gui.row, gui.row);
+ /* Check that the cursor is inside the shell (resizing may have made
+ * it invalid) */
+ if (gui.row >= screen_Rows || gui.col >= screen_Columns)
+ return;
+
+ gui.cursor_is_valid = TRUE;
+
+ /*
+ * How the cursor is drawn depends on the current mode.
+ */
+ idx = get_shape_idx(FALSE);
+ if (State & LANGMAP)
+ id = shape_table[idx].id_lm;
+ else
+ id = shape_table[idx].id;
+
+ /* get the colors and attributes for the cursor. Default is inverted */
+ cfg = INVALCOLOR;
+ cbg = INVALCOLOR;
+ cattr = HL_INVERSE;
+ gui_mch_set_blinking(shape_table[idx].blinkwait,
+ shape_table[idx].blinkon,
+ shape_table[idx].blinkoff);
+ if (id > 0)
+ {
+ cattr = syn_id2colors(id, &cfg, &cbg);
+#if defined(USE_IM_CONTROL) || defined(FEAT_HANGULIN)
+ {
+ static int iid;
+ guicolor_T fg, bg;
+
+ if (im_get_status())
+ {
+ iid = syn_name2id((char_u *)"CursorIM");
+ if (iid > 0)
+ {
+ syn_id2colors(iid, &fg, &bg);
+ if (bg != INVALCOLOR)
+ cbg = bg;
+ if (fg != INVALCOLOR)
+ cfg = fg;
+ }
+ }
+ }
+#endif
+ }
+
+ /*
+ * Get the attributes for the character under the cursor.
+ * When no cursor color was given, use the character color.
+ */
+ attr = ScreenAttrs[LineOffset[gui.row] + gui.col];
+ if (attr > HL_ALL)
+ aep = syn_gui_attr2entry(attr);
+ if (aep != NULL)
+ {
+ attr = aep->ae_attr;
+ if (cfg == INVALCOLOR)
+ cfg = ((attr & HL_INVERSE) ? aep->ae_u.gui.bg_color
+ : aep->ae_u.gui.fg_color);
+ if (cbg == INVALCOLOR)
+ cbg = ((attr & HL_INVERSE) ? aep->ae_u.gui.fg_color
+ : aep->ae_u.gui.bg_color);
+ }
+ if (cfg == INVALCOLOR)
+ cfg = (attr & HL_INVERSE) ? gui.back_pixel : gui.norm_pixel;
+ if (cbg == INVALCOLOR)
+ cbg = (attr & HL_INVERSE) ? gui.norm_pixel : gui.back_pixel;
+
+#ifdef FEAT_XIM
+ if (aep != NULL)
+ {
+ xim_bg_color = ((attr & HL_INVERSE) ? aep->ae_u.gui.fg_color
+ : aep->ae_u.gui.bg_color);
+ xim_fg_color = ((attr & HL_INVERSE) ? aep->ae_u.gui.bg_color
+ : aep->ae_u.gui.fg_color);
+ if (xim_bg_color == INVALCOLOR)
+ xim_bg_color = (attr & HL_INVERSE) ? gui.norm_pixel
+ : gui.back_pixel;
+ if (xim_fg_color == INVALCOLOR)
+ xim_fg_color = (attr & HL_INVERSE) ? gui.back_pixel
+ : gui.norm_pixel;
+ }
+ else
+ {
+ xim_bg_color = (attr & HL_INVERSE) ? gui.norm_pixel
+ : gui.back_pixel;
+ xim_fg_color = (attr & HL_INVERSE) ? gui.back_pixel
+ : gui.norm_pixel;
+ }
+#endif
+
+ attr &= ~HL_INVERSE;
+ if (cattr & HL_INVERSE)
+ {
+ cc = cbg;
+ cbg = cfg;
+ cfg = cc;
+ }
+ cattr &= ~HL_INVERSE;
+
+ /*
+ * When we don't have window focus, draw a hollow cursor.
+ */
+ if (!gui.in_focus)
+ {
+ gui_mch_draw_hollow_cursor(cbg);
+ return;
+ }
+
+ old_hl_mask = gui.highlight_mask;
+ if (shape_table[idx].shape == SHAPE_BLOCK
+#ifdef FEAT_HANGULIN
+ || composing_hangul
+#endif
+ )
+ {
+ /*
+ * Draw the text character with the cursor colors. Use the
+ * character attributes plus the cursor attributes.
+ */
+ gui.highlight_mask = (cattr | attr);
+#ifdef FEAT_HANGULIN
+ if (composing_hangul)
+ (void)gui_outstr_nowrap(composing_hangul_buffer, 2,
+ GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, cfg, cbg, 0);
+ else
+#endif
+ (void)gui_screenchar(LineOffset[gui.row] + gui.col,
+ GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, cfg, cbg, 0);
+ }
+ else
+ {
+#if defined(FEAT_MBYTE) && defined(FEAT_RIGHTLEFT)
+ int col_off = FALSE;
+#endif
+ /*
+ * First draw the partial cursor, then overwrite with the text
+ * character, using a transparent background.
+ */
+ if (shape_table[idx].shape == SHAPE_VER)
+ {
+ cur_height = gui.char_height;
+ cur_width = (gui.char_width * shape_table[idx].percentage
+ + 99) / 100;
+ }
+ else
+ {
+ cur_height = (gui.char_height * shape_table[idx].percentage
+ + 99) / 100;
+ cur_width = gui.char_width;
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (*mb_off2cells)(LineOffset[gui.row] + gui.col) > 1)
+ {
+ /* Double wide character. */
+ if (shape_table[idx].shape != SHAPE_VER)
+ cur_width += gui.char_width;
+# ifdef FEAT_RIGHTLEFT
+ if (CURSOR_BAR_RIGHT)
+ {
+ /* gui.col points to the left halve of the character but
+ * the vertical line needs to be on the right halve.
+ * A double-wide horizontal line is also drawn from the
+ * right halve in gui_mch_draw_part_cursor(). */
+ col_off = TRUE;
+ ++gui.col;
+ }
+# endif
+ }
+#endif
+ gui_mch_draw_part_cursor(cur_width, cur_height, cbg);
+#if defined(FEAT_MBYTE) && defined(FEAT_RIGHTLEFT)
+ if (col_off)
+ --gui.col;
+#endif
+
+#ifndef FEAT_GUI_MSWIN /* doesn't seem to work for MSWindows */
+ gui.highlight_mask = ScreenAttrs[LineOffset[gui.row] + gui.col];
+ (void)gui_screenchar(LineOffset[gui.row] + gui.col,
+ GUI_MON_TRS_CURSOR | GUI_MON_NOCLEAR,
+ (guicolor_T)0, (guicolor_T)0, 0);
+#endif
+ }
+ gui.highlight_mask = old_hl_mask;
+ }
+}
+
+#if defined(FEAT_MENU) || defined(PROTO)
+ void
+gui_position_menu()
+{
+# if !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MOTIF)
+ if (gui.menu_is_active && gui.in_use)
+ gui_mch_set_menu_pos(0, 0, gui.menu_width, gui.menu_height);
+# endif
+}
+#endif
+
+/*
+ * Position the various GUI components (text area, menu). The vertical
+ * scrollbars are NOT handled here. See gui_update_scrollbars().
+ */
+/*ARGSUSED*/
+ static void
+gui_position_components(total_width)
+ int total_width;
+{
+ int text_area_x;
+ int text_area_y;
+ int text_area_width;
+ int text_area_height;
+
+ /* avoid that moving components around generates events */
+ ++hold_gui_events;
+
+ text_area_x = 0;
+ if (gui.which_scrollbars[SBAR_LEFT])
+ text_area_x += gui.scrollbar_width;
+
+ text_area_y = 0;
+#if defined(FEAT_MENU) && !(defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON))
+ gui.menu_width = total_width;
+ if (gui.menu_is_active)
+ text_area_y += gui.menu_height;
+#endif
+#if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_MSWIN)
+ if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
+ text_area_y = TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT;
+#endif
+
+#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA))
+ if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
+ {
+# ifdef FEAT_GUI_ATHENA
+ gui_mch_set_toolbar_pos(0, text_area_y,
+ gui.menu_width, gui.toolbar_height);
+# endif
+ text_area_y += gui.toolbar_height;
+ }
+#endif
+
+ text_area_width = gui.num_cols * gui.char_width + gui.border_offset * 2;
+ text_area_height = gui.num_rows * gui.char_height + gui.border_offset * 2;
+
+ gui_mch_set_text_area_pos(text_area_x,
+ text_area_y,
+ text_area_width,
+ text_area_height
+#if defined(FEAT_XIM) && !defined(HAVE_GTK2)
+ + xim_get_status_area_height()
+#endif
+ );
+#ifdef FEAT_MENU
+ gui_position_menu();
+#endif
+ if (gui.which_scrollbars[SBAR_BOTTOM])
+ gui_mch_set_scrollbar_pos(&gui.bottom_sbar,
+ text_area_x,
+ text_area_y + text_area_height,
+ text_area_width,
+ gui.scrollbar_height);
+ gui.left_sbar_x = 0;
+ gui.right_sbar_x = text_area_x + text_area_width;
+
+ --hold_gui_events;
+}
+
+ int
+gui_get_base_width()
+{
+ int base_width;
+
+ base_width = 2 * gui.border_offset;
+ if (gui.which_scrollbars[SBAR_LEFT])
+ base_width += gui.scrollbar_width;
+ if (gui.which_scrollbars[SBAR_RIGHT])
+ base_width += gui.scrollbar_width;
+ return base_width;
+}
+
+ int
+gui_get_base_height()
+{
+ int base_height;
+
+ base_height = 2 * gui.border_offset;
+ if (gui.which_scrollbars[SBAR_BOTTOM])
+ base_height += gui.scrollbar_height;
+#ifdef FEAT_GUI_GTK
+ /* We can't take the sizes properly into account until anything is
+ * realized. Therefore we recalculate all the values here just before
+ * setting the size. (--mdcki) */
+#else
+# ifdef FEAT_MENU
+ if (gui.menu_is_active)
+ base_height += gui.menu_height;
+# endif
+# ifdef FEAT_TOOLBAR
+ if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
+# if defined(FEAT_GUI_MSWIN) && defined(FEAT_TOOLBAR)
+ base_height += (TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT);
+# else
+ base_height += gui.toolbar_height;
+# endif
+# endif
+# ifdef FEAT_FOOTER
+ if (vim_strchr(p_go, GO_FOOTER) != NULL)
+ base_height += gui.footer_height;
+# endif
+# if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU)
+ base_height += gui_mch_text_area_extra_height();
+# endif
+#endif
+ return base_height;
+}
+
+/*
+ * Should be called after the GUI shell has been resized. Its arguments are
+ * the new width and height of the shell in pixels.
+ */
+ void
+gui_resize_shell(pixel_width, pixel_height)
+ int pixel_width;
+ int pixel_height;
+{
+ static int busy = FALSE;
+
+ if (!gui.shell_created) /* ignore when still initializing */
+ return;
+
+ /*
+ * Can't resize the screen while it is being redrawn. Remember the new
+ * size and handle it later.
+ */
+ if (updating_screen || busy)
+ {
+ new_pixel_width = pixel_width;
+ new_pixel_height = pixel_height;
+ return;
+ }
+
+again:
+ busy = TRUE;
+
+#ifdef FEAT_GUI_BEOS
+ vim_lock_screen();
+#endif
+
+ /* Flush pending output before redrawing */
+ out_flush();
+
+ gui.num_cols = (pixel_width - gui_get_base_width()) / gui.char_width;
+ gui.num_rows = (pixel_height - gui_get_base_height()
+#if !defined(FEAT_GUI_PHOTON) && !defined(FEAT_GUI_MSWIN)
+ + (gui.char_height / 2)
+#endif
+ ) / gui.char_height;
+
+ gui_position_components(pixel_width);
+
+ gui_reset_scroll_region();
+ /*
+ * At the "more" and ":confirm" prompt there is no redraw, put the cursor
+ * at the last line here (why does it have to be one row too low?).
+ */
+ if (State == ASKMORE || State == CONFIRM)
+ gui.row = gui.num_rows;
+
+ /* Only comparing Rows and Columns may be sufficient, but let's stay on
+ * the safe side. */
+ if (gui.num_rows != screen_Rows || gui.num_cols != screen_Columns
+ || gui.num_rows != Rows || gui.num_cols != Columns)
+ shell_resized();
+
+#ifdef FEAT_GUI_BEOS
+ vim_unlock_screen();
+#endif
+
+ gui_update_scrollbars(TRUE);
+ gui_update_cursor(FALSE, TRUE);
+#if defined(FEAT_XIM) && !defined(HAVE_GTK2)
+ xim_set_status_area();
+#endif
+
+ busy = FALSE;
+ /*
+ * We could have been called again while redrawing the screen.
+ * Need to do it all again with the latest size then.
+ */
+ if (new_pixel_height)
+ {
+ pixel_width = new_pixel_width;
+ pixel_height = new_pixel_height;
+ new_pixel_width = 0;
+ new_pixel_height = 0;
+ goto again;
+ }
+}
+
+/*
+ * Check if gui_resize_shell() must be called.
+ */
+ void
+gui_may_resize_shell()
+{
+ int h, w;
+
+ if (new_pixel_height)
+ {
+ /* careful: gui_resize_shell() may postpone the resize again if we
+ * were called indirectly by it */
+ w = new_pixel_width;
+ h = new_pixel_height;
+ new_pixel_width = 0;
+ new_pixel_height = 0;
+ gui_resize_shell(w, h);
+ }
+}
+
+ int
+gui_get_shellsize()
+{
+ Rows = gui.num_rows;
+ Columns = gui.num_cols;
+ return OK;
+}
+
+/*
+ * Set the size of the Vim shell according to Rows and Columns.
+ */
+/*ARGSUSED*/
+ void
+gui_set_shellsize(mustset, fit_to_display)
+ int mustset; /* set by the user */
+ int fit_to_display;
+{
+ int base_width;
+ int base_height;
+ int width;
+ int height;
+ int min_width;
+ int min_height;
+ int screen_w;
+ int screen_h;
+
+ if (!gui.shell_created)
+ return;
+
+#ifdef MSWIN
+ /* If not setting to a user specified size and maximized, calculate the
+ * number of characters that fit in the maximized window. */
+ if (!mustset && gui_mch_maximized())
+ {
+ gui_mch_newfont();
+ return;
+ }
+#endif
+
+ base_width = gui_get_base_width();
+ base_height = gui_get_base_height();
+#ifdef USE_SUN_WORKSHOP
+ if (!mustset && usingSunWorkShop
+ && workshop_get_width_height(&width, &height))
+ {
+ Columns = (width - base_width + gui.char_width - 1) / gui.char_width;
+ Rows = (height - base_height + gui.char_height - 1) / gui.char_height;
+ }
+ else
+#endif
+ {
+ width = Columns * gui.char_width + base_width;
+ height = Rows * gui.char_height + base_height;
+ }
+
+ if (fit_to_display)
+ {
+ gui_mch_get_screen_dimensions(&screen_w, &screen_h);
+ if (width > screen_w)
+ {
+ Columns = (screen_w - base_width) / gui.char_width;
+ if (Columns < MIN_COLUMNS)
+ Columns = MIN_COLUMNS;
+ width = Columns * gui.char_width + base_width;
+ }
+ if (height > screen_h)
+ {
+ Rows = (screen_h - base_height) / gui.char_height;
+ check_shellsize();
+ height = Rows * gui.char_height + base_height;
+ }
+ }
+ gui.num_cols = Columns;
+ gui.num_rows = Rows;
+
+ min_width = base_width + MIN_COLUMNS * gui.char_width;
+ min_height = base_height + MIN_LINES * gui.char_height;
+
+ gui_mch_set_shellsize(width, height, min_width, min_height,
+ base_width, base_height);
+ if (fit_to_display)
+ {
+ int x, y;
+
+ /* Some window managers put the Vim window left of/above the screen. */
+ gui_mch_update();
+ if (gui_mch_get_winpos(&x, &y) == OK && (x < 0 || y < 0))
+ gui_mch_set_winpos(x < 0 ? 0 : x, y < 0 ? 0 : y);
+ }
+
+ gui_position_components(width);
+ gui_update_scrollbars(TRUE);
+ gui_reset_scroll_region();
+}
+
+/*
+ * Called when Rows and/or Columns has changed.
+ */
+ void
+gui_new_shellsize()
+{
+ gui_reset_scroll_region();
+}
+
+/*
+ * Make scroll region cover whole screen.
+ */
+ void
+gui_reset_scroll_region()
+{
+ gui.scroll_region_top = 0;
+ gui.scroll_region_bot = gui.num_rows - 1;
+ gui.scroll_region_left = 0;
+ gui.scroll_region_right = gui.num_cols - 1;
+}
+
+ void
+gui_start_highlight(mask)
+ int mask;
+{
+ if (mask > HL_ALL) /* highlight code */
+ gui.highlight_mask = mask;
+ else /* mask */
+ gui.highlight_mask |= mask;
+}
+
+ void
+gui_stop_highlight(mask)
+ int mask;
+{
+ if (mask > HL_ALL) /* highlight code */
+ gui.highlight_mask = HL_NORMAL;
+ else /* mask */
+ gui.highlight_mask &= ~mask;
+}
+
+/*
+ * Clear a rectangular region of the screen from text pos (row1, col1) to
+ * (row2, col2) inclusive.
+ */
+ void
+gui_clear_block(row1, col1, row2, col2)
+ int row1;
+ int col1;
+ int row2;
+ int col2;
+{
+ /* Clear the selection if we are about to write over it */
+ clip_may_clear_selection(row1, row2);
+
+ gui_mch_clear_block(row1, col1, row2, col2);
+
+ /* Invalidate cursor if it was in this block */
+ if ( gui.cursor_row >= row1 && gui.cursor_row <= row2
+ && gui.cursor_col >= col1 && gui.cursor_col <= col2)
+ gui.cursor_is_valid = FALSE;
+}
+
+/*
+ * Write code to update the cursor later. This avoids the need to flush the
+ * output buffer before calling gui_update_cursor().
+ */
+ void
+gui_update_cursor_later()
+{
+ OUT_STR(IF_EB("\033|s", ESC_STR "|s"));
+}
+
+ void
+gui_write(s, len)
+ char_u *s;
+ int len;
+{
+ char_u *p;
+ int arg1 = 0, arg2 = 0;
+ /* this doesn't make sense, disabled until someone can explain why it
+ * would be needed */
+#if 0 && (defined(RISCOS) || defined(WIN16))
+ int force_cursor = TRUE; /* JK230798, stop Vim being smart or
+ our redraw speed will suffer */
+#else
+ int force_cursor = FALSE; /* force cursor update */
+#endif
+ int force_scrollbar = FALSE;
+ static win_T *old_curwin = NULL;
+
+/* #define DEBUG_GUI_WRITE */
+#ifdef DEBUG_GUI_WRITE
+ {
+ int i;
+ char_u *str;
+
+ printf("gui_write(%d):\n ", len);
+ for (i = 0; i < len; i++)
+ if (s[i] == ESC)
+ {
+ if (i != 0)
+ printf("\n ");
+ printf("<ESC>");
+ }
+ else
+ {
+ str = transchar_byte(s[i]);
+ if (str[0] && str[1])
+ printf("<%s>", (char *)str);
+ else
+ printf("%s", (char *)str);
+ }
+ printf("\n");
+ }
+#endif
+ while (len)
+ {
+ if (s[0] == ESC && s[1] == '|')
+ {
+ p = s + 2;
+ if (VIM_ISDIGIT(*p))
+ {
+ arg1 = getdigits(&p);
+ if (p > s + len)
+ break;
+ if (*p == ';')
+ {
+ ++p;
+ arg2 = getdigits(&p);
+ if (p > s + len)
+ break;
+ }
+ }
+ switch (*p)
+ {
+ case 'C': /* Clear screen */
+ clip_scroll_selection(9999);
+ gui_mch_clear_all();
+ gui.cursor_is_valid = FALSE;
+ force_scrollbar = TRUE;
+ break;
+ case 'M': /* Move cursor */
+ gui_set_cursor(arg1, arg2);
+ break;
+ case 's': /* force cursor (shape) update */
+ force_cursor = TRUE;
+ break;
+ case 'R': /* Set scroll region */
+ if (arg1 < arg2)
+ {
+ gui.scroll_region_top = arg1;
+ gui.scroll_region_bot = arg2;
+ }
+ else
+ {
+ gui.scroll_region_top = arg2;
+ gui.scroll_region_bot = arg1;
+ }
+ break;
+#ifdef FEAT_VERTSPLIT
+ case 'V': /* Set vertical scroll region */
+ if (arg1 < arg2)
+ {
+ gui.scroll_region_left = arg1;
+ gui.scroll_region_right = arg2;
+ }
+ else
+ {
+ gui.scroll_region_left = arg2;
+ gui.scroll_region_right = arg1;
+ }
+ break;
+#endif
+ case 'd': /* Delete line */
+ gui_delete_lines(gui.row, 1);
+ break;
+ case 'D': /* Delete lines */
+ gui_delete_lines(gui.row, arg1);
+ break;
+ case 'i': /* Insert line */
+ gui_insert_lines(gui.row, 1);
+ break;
+ case 'I': /* Insert lines */
+ gui_insert_lines(gui.row, arg1);
+ break;
+ case '$': /* Clear to end-of-line */
+ gui_clear_block(gui.row, gui.col, gui.row,
+ (int)Columns - 1);
+ break;
+ case 'h': /* Turn on highlighting */
+ gui_start_highlight(arg1);
+ break;
+ case 'H': /* Turn off highlighting */
+ gui_stop_highlight(arg1);
+ break;
+ case 'f': /* flash the window (visual bell) */
+ gui_mch_flash(arg1 == 0 ? 20 : arg1);
+ break;
+ default:
+ p = s + 1; /* Skip the ESC */
+ break;
+ }
+ len -= (int)(++p - s);
+ s = p;
+ }
+ else if (
+#ifdef EBCDIC
+ CtrlChar(s[0]) != 0 /* Ctrl character */
+#else
+ s[0] < 0x20 /* Ctrl character */
+#endif
+#ifdef FEAT_SIGN_ICONS
+ && s[0] != SIGN_BYTE
+# ifdef FEAT_NETBEANS_INTG
+ && s[0] != MULTISIGN_BYTE
+# endif
+#endif
+ )
+ {
+ if (s[0] == '\n') /* NL */
+ {
+ gui.col = 0;
+ if (gui.row < gui.scroll_region_bot)
+ gui.row++;
+ else
+ gui_delete_lines(gui.scroll_region_top, 1);
+ }
+ else if (s[0] == '\r') /* CR */
+ {
+ gui.col = 0;
+ }
+ else if (s[0] == '\b') /* Backspace */
+ {
+ if (gui.col)
+ --gui.col;
+ }
+ else if (s[0] == Ctrl_L) /* cursor-right */
+ {
+ ++gui.col;
+ }
+ else if (s[0] == Ctrl_G) /* Beep */
+ {
+ gui_mch_beep();
+ }
+ /* Other Ctrl character: shouldn't happen! */
+
+ --len; /* Skip this char */
+ ++s;
+ }
+ else
+ {
+ p = s;
+ while (len > 0 && (
+#ifdef EBCDIC
+ CtrlChar(*p) == 0
+#else
+ *p >= 0x20
+#endif
+#ifdef FEAT_SIGN_ICONS
+ || *p == SIGN_BYTE
+# ifdef FEAT_NETBEANS_INTG
+ || *p == MULTISIGN_BYTE
+# endif
+#endif
+ ))
+ {
+ len--;
+ p++;
+ }
+ gui_outstr(s, (int)(p - s));
+ s = p;
+ }
+ }
+
+ /* Postponed update of the cursor (won't work if "can_update_cursor" isn't
+ * set). */
+ if (force_cursor)
+ gui_update_cursor(TRUE, TRUE);
+
+ /* When switching to another window the dragging must have stopped.
+ * Required for GTK, dragged_sb isn't reset. */
+ if (old_curwin != curwin)
+ gui.dragged_sb = SBAR_NONE;
+
+ /* Update the scrollbars after clearing the screen or when switched
+ * to another window.
+ * Update the horizontal scrollbar always, it's difficult to check all
+ * situations where it might change. */
+ if (force_scrollbar || old_curwin != curwin)
+ gui_update_scrollbars(force_scrollbar);
+ else
+ gui_update_horiz_scrollbar(FALSE);
+ old_curwin = curwin;
+
+ /*
+ * We need to make sure this is cleared since Athena doesn't tell us when
+ * he is done dragging. Do the same for GTK.
+ */
+#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK)
+ gui.dragged_sb = SBAR_NONE;
+#endif
+
+ gui_mch_flush(); /* In case vim decides to take a nap */
+}
+
+/*
+ * When ScreenLines[] is invalid, updating the cursor should not be done, it
+ * produces wrong results. Call gui_dont_update_cursor() before that code and
+ * gui_can_update_cursor() afterwards.
+ */
+ void
+gui_dont_update_cursor()
+{
+ if (gui.in_use)
+ {
+ /* Undraw the cursor now, we probably can't do it after the change. */
+ gui_undraw_cursor();
+ can_update_cursor = FALSE;
+ }
+}
+
+ void
+gui_can_update_cursor()
+{
+ can_update_cursor = TRUE;
+ /* No need to update the cursor right now, there is always more output
+ * after scrolling. */
+}
+
+ static void
+gui_outstr(s, len)
+ char_u *s;
+ int len;
+{
+ int this_len;
+#ifdef FEAT_MBYTE
+ int cells;
+#endif
+
+ if (len == 0)
+ return;
+
+ if (len < 0)
+ len = (int)STRLEN(s);
+
+ while (len > 0)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ /* Find out how many chars fit in the current line. */
+ cells = 0;
+ for (this_len = 0; this_len < len; )
+ {
+ cells += (*mb_ptr2cells)(s + this_len);
+ if (gui.col + cells > Columns)
+ break;
+ this_len += (*mb_ptr2len_check)(s + this_len);
+ }
+ if (this_len > len)
+ this_len = len; /* don't include following composing char */
+ }
+ else
+#endif
+ if (gui.col + len > Columns)
+ this_len = Columns - gui.col;
+ else
+ this_len = len;
+
+ (void)gui_outstr_nowrap(s, this_len,
+ 0, (guicolor_T)0, (guicolor_T)0, 0);
+ s += this_len;
+ len -= this_len;
+#ifdef FEAT_MBYTE
+ /* fill up for a double-width char that doesn't fit. */
+ if (len > 0 && gui.col < Columns)
+ (void)gui_outstr_nowrap((char_u *)" ", 1,
+ 0, (guicolor_T)0, (guicolor_T)0, 0);
+#endif
+ /* The cursor may wrap to the next line. */
+ if (gui.col >= Columns)
+ {
+ gui.col = 0;
+ gui.row++;
+ }
+ }
+}
+
+/*
+ * Output one character (may be one or two display cells).
+ * Caller must check for valid "off".
+ * Returns FAIL or OK, just like gui_outstr_nowrap().
+ */
+ static int
+gui_screenchar(off, flags, fg, bg, back)
+ int off; /* Offset from start of screen */
+ int flags;
+ guicolor_T fg, bg; /* colors for cursor */
+ int back; /* backup this many chars when using bold trick */
+{
+#ifdef FEAT_MBYTE
+ char_u buf[MB_MAXBYTES + 1];
+
+ /* Don't draw right halve of a double-width UTF-8 char. "cannot happen" */
+ if (enc_utf8 && ScreenLines[off] == 0)
+ return OK;
+
+ if (enc_utf8 && ScreenLinesUC[off] != 0)
+ /* Draw UTF-8 multi-byte character. */
+ return gui_outstr_nowrap(buf, utfc_char2bytes(off, buf),
+ flags, fg, bg, back);
+
+ if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e)
+ {
+ buf[0] = ScreenLines[off];
+ buf[1] = ScreenLines2[off];
+ return gui_outstr_nowrap(buf, 2, flags, fg, bg, back);
+ }
+
+ /* Draw non-multi-byte character or DBCS character. */
+ return gui_outstr_nowrap(ScreenLines + off,
+ enc_dbcs ? (*mb_ptr2len_check)(ScreenLines + off) : 1,
+ flags, fg, bg, back);
+#else
+ return gui_outstr_nowrap(ScreenLines + off, 1, flags, fg, bg, back);
+#endif
+}
+
+#ifdef HAVE_GTK2
+/*
+ * Output the string at the given screen position. This is used in place
+ * of gui_screenchar() where possible because Pango needs as much context
+ * as possible to work nicely. It's a lot faster as well.
+ */
+ static int
+gui_screenstr(off, len, flags, fg, bg, back)
+ int off; /* Offset from start of screen */
+ int len; /* string length in screen cells */
+ int flags;
+ guicolor_T fg, bg; /* colors for cursor */
+ int back; /* backup this many chars when using bold trick */
+{
+ char_u *buf;
+ int outlen = 0;
+ int i;
+ int retval;
+
+ if (len <= 0) /* "cannot happen"? */
+ return OK;
+
+ if (enc_utf8)
+ {
+ buf = alloc((unsigned)(len * MB_MAXBYTES + 1));
+ if (buf == NULL)
+ return OK; /* not much we could do here... */
+
+ for (i = off; i < off + len; ++i)
+ {
+ if (ScreenLines[i] == 0)
+ continue; /* skip second half of double-width char */
+
+ if (ScreenLinesUC[i] == 0)
+ buf[outlen++] = ScreenLines[i];
+ else
+ outlen += utfc_char2bytes(i, buf + outlen);
+ }
+
+ buf[outlen] = NUL; /* only to aid debugging */
+ retval = gui_outstr_nowrap(buf, outlen, flags, fg, bg, back);
+ vim_free(buf);
+
+ return retval;
+ }
+ else if (enc_dbcs == DBCS_JPNU)
+ {
+ buf = alloc((unsigned)(len * 2 + 1));
+ if (buf == NULL)
+ return OK; /* not much we could do here... */
+
+ for (i = off; i < off + len; ++i)
+ {
+ buf[outlen++] = ScreenLines[i];
+
+ /* handle double-byte single-width char */
+ if (ScreenLines[i] == 0x8e)
+ buf[outlen++] = ScreenLines2[i];
+ else if (MB_BYTE2LEN(ScreenLines[i]) == 2)
+ buf[outlen++] = ScreenLines[++i];
+ }
+
+ buf[outlen] = NUL; /* only to aid debugging */
+ retval = gui_outstr_nowrap(buf, outlen, flags, fg, bg, back);
+ vim_free(buf);
+
+ return retval;
+ }
+ else
+ {
+ return gui_outstr_nowrap(&ScreenLines[off], len,
+ flags, fg, bg, back);
+ }
+}
+#endif /* HAVE_GTK2 */
+
+/*
+ * Output the given string at the current cursor position. If the string is
+ * too long to fit on the line, then it is truncated.
+ * "flags":
+ * GUI_MON_IS_CURSOR should only be used when this function is being called to
+ * actually draw (an inverted) cursor.
+ * GUI_MON_TRS_CURSOR is used to draw the cursor text with a transparant
+ * background.
+ * GUI_MON_NOCLEAR is used to avoid clearing the selection when drawing over
+ * it.
+ * Returns OK, unless "back" is non-zero and using the bold trick, then return
+ * FAIL (the caller should start drawing "back" chars back).
+ */
+ int
+gui_outstr_nowrap(s, len, flags, fg, bg, back)
+ char_u *s;
+ int len;
+ int flags;
+ guicolor_T fg, bg; /* colors for cursor */
+ int back; /* backup this many chars when using bold trick */
+{
+ long_u highlight_mask;
+ long_u hl_mask_todo;
+ guicolor_T fg_color;
+ guicolor_T bg_color;
+#if !defined(MSWIN16_FASTTEXT) && !defined(HAVE_GTK2)
+ GuiFont font = NOFONT;
+# ifdef FEAT_XFONTSET
+ GuiFontset fontset = NOFONTSET;
+# endif
+#endif
+ attrentry_T *aep = NULL;
+ int draw_flags;
+ int col = gui.col;
+#ifdef FEAT_SIGN_ICONS
+ int draw_sign = FALSE;
+# ifdef FEAT_NETBEANS_INTG
+ int multi_sign = FALSE;
+# endif
+#endif
+
+ if (len < 0)
+ len = (int)STRLEN(s);
+ if (len == 0)
+ return OK;
+
+#ifdef FEAT_SIGN_ICONS
+ if (*s == SIGN_BYTE
+# ifdef FEAT_NETBEANS_INTG
+ || *s == MULTISIGN_BYTE
+# endif
+ )
+ {
+# ifdef FEAT_NETBEANS_INTG
+ if (*s == MULTISIGN_BYTE)
+ multi_sign = TRUE;
+# endif
+ /* draw spaces instead */
+ s = (char_u *)" ";
+ if (len == 1 && col > 0)
+ --col;
+ len = 2;
+ draw_sign = TRUE;
+ highlight_mask = 0;
+ }
+ else
+#endif
+ if (gui.highlight_mask > HL_ALL)
+ {
+ aep = syn_gui_attr2entry(gui.highlight_mask);
+ if (aep == NULL) /* highlighting not set */
+ highlight_mask = 0;
+ else
+ highlight_mask = aep->ae_attr;
+ }
+ else
+ highlight_mask = gui.highlight_mask;
+ hl_mask_todo = highlight_mask;
+
+#if !defined(MSWIN16_FASTTEXT) && !defined(HAVE_GTK2)
+ /* Set the font */
+ if (aep != NULL && aep->ae_u.gui.font != NOFONT)
+ font = aep->ae_u.gui.font;
+# ifdef FEAT_XFONTSET
+ else if (aep != NULL && aep->ae_u.gui.fontset != NOFONTSET)
+ fontset = aep->ae_u.gui.fontset;
+# endif
+ else
+ {
+# ifdef FEAT_XFONTSET
+ if (gui.fontset != NOFONTSET)
+ fontset = gui.fontset;
+ else
+# endif
+ if (hl_mask_todo & (HL_BOLD | HL_STANDOUT))
+ {
+ if ((hl_mask_todo & HL_ITALIC) && gui.boldital_font != NOFONT)
+ {
+ font = gui.boldital_font;
+ hl_mask_todo &= ~(HL_BOLD | HL_STANDOUT | HL_ITALIC);
+ }
+ else if (gui.bold_font != NOFONT)
+ {
+ font = gui.bold_font;
+ hl_mask_todo &= ~(HL_BOLD | HL_STANDOUT);
+ }
+ else
+ font = gui.norm_font;
+ }
+ else if ((hl_mask_todo & HL_ITALIC) && gui.ital_font != NOFONT)
+ {
+ font = gui.ital_font;
+ hl_mask_todo &= ~HL_ITALIC;
+ }
+ else
+ font = gui.norm_font;
+ }
+# ifdef FEAT_XFONTSET
+ if (fontset != NOFONTSET)
+ gui_mch_set_fontset(fontset);
+ else
+# endif
+ gui_mch_set_font(font);
+#endif
+
+ draw_flags = 0;
+
+ /* Set the color */
+ bg_color = gui.back_pixel;
+ if ((flags & GUI_MON_IS_CURSOR) && gui.in_focus)
+ {
+ draw_flags |= DRAW_CURSOR;
+ fg_color = fg;
+ bg_color = bg;
+ }
+ else if (aep != NULL)
+ {
+ fg_color = aep->ae_u.gui.fg_color;
+ if (fg_color == INVALCOLOR)
+ fg_color = gui.norm_pixel;
+ bg_color = aep->ae_u.gui.bg_color;
+ if (bg_color == INVALCOLOR)
+ bg_color = gui.back_pixel;
+ }
+ else
+ fg_color = gui.norm_pixel;
+
+ if (highlight_mask & (HL_INVERSE | HL_STANDOUT))
+ {
+#if defined(AMIGA) || defined(RISCOS)
+ gui_mch_set_colors(bg_color, fg_color);
+#else
+ gui_mch_set_fg_color(bg_color);
+ gui_mch_set_bg_color(fg_color);
+#endif
+ }
+ else
+ {
+#if defined(AMIGA) || defined(RISCOS)
+ gui_mch_set_colors(fg_color, bg_color);
+#else
+ gui_mch_set_fg_color(fg_color);
+ gui_mch_set_bg_color(bg_color);
+#endif
+ }
+
+ /* Clear the selection if we are about to write over it */
+ if (!(flags & GUI_MON_NOCLEAR))
+ clip_may_clear_selection(gui.row, gui.row);
+
+
+#ifndef MSWIN16_FASTTEXT
+ /* If there's no bold font, then fake it */
+ if (hl_mask_todo & (HL_BOLD | HL_STANDOUT))
+ draw_flags |= DRAW_BOLD;
+#endif
+
+ /*
+ * When drawing bold or italic characters the spill-over from the left
+ * neighbor may be destroyed. Let the caller backup to start redrawing
+ * just after a blank.
+ */
+ if (back != 0 && ((draw_flags & DRAW_BOLD) || (highlight_mask & HL_ITALIC)))
+ return FAIL;
+
+#if defined(RISCOS) || defined(HAVE_GTK2)
+ /* If there's no italic font, then fake it.
+ * For GTK2, we don't need a different font for italic style. */
+ if (hl_mask_todo & HL_ITALIC)
+ draw_flags |= DRAW_ITALIC;
+
+ /* Do we underline the text? */
+ if (hl_mask_todo & HL_UNDERLINE)
+ draw_flags |= DRAW_UNDERL;
+#else
+ /* Do we underline the text? */
+ if ((hl_mask_todo & HL_UNDERLINE)
+# ifndef MSWIN16_FASTTEXT
+ || (hl_mask_todo & HL_ITALIC)
+# endif
+ )
+ draw_flags |= DRAW_UNDERL;
+#endif
+
+ /* Do we draw transparantly? */
+ if (flags & GUI_MON_TRS_CURSOR)
+ draw_flags |= DRAW_TRANSP;
+
+ /*
+ * Draw the text.
+ */
+#ifdef HAVE_GTK2
+ /* The value returned is the length in display cells */
+ len = gui_gtk2_draw_string(gui.row, col, s, len, draw_flags);
+#else
+# ifdef FEAT_MBYTE
+ if (enc_utf8)
+ {
+ int start; /* index of bytes to be drawn */
+ int cells; /* cellwidth of bytes to be drawn */
+ int thislen; /* length of bytes to be drawin */
+ int cn; /* cellwidth of current char */
+ int i; /* index of current char */
+ int c; /* current char value */
+ int cl; /* byte length of current char */
+ int comping; /* current char is composing */
+ int scol = col; /* screen column */
+ int dowide; /* use 'guifontwide' */
+
+ /* Break the string at a composing character, it has to be drawn on
+ * top of the previous character. */
+ start = 0;
+ cells = 0;
+ for (i = 0; i < len; i += cl)
+ {
+ c = utf_ptr2char(s + i);
+ cn = utf_char2cells(c);
+ if (cn > 1
+# ifdef FEAT_XFONTSET
+ && fontset == NOFONTSET
+# endif
+ && gui.wide_font != NOFONT)
+ dowide = TRUE;
+ else
+ dowide = FALSE;
+ comping = utf_iscomposing(c);
+ if (!comping) /* count cells from non-composing chars */
+ cells += cn;
+ cl = utf_ptr2len_check(s + i);
+ if (cl == 0) /* hit end of string */
+ len = i + cl; /* len must be wrong "cannot happen" */
+
+ /* print the string so far if it's the last character or there is
+ * a composing character. */
+ if (i + cl >= len || (comping && i > start) || dowide
+# if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
+ || (cn > 1
+# ifdef FEAT_XFONTSET
+ /* No fontset: At least draw char after wide char at
+ * right position. */
+ && fontset == NOFONTSET
+# endif
+ )
+# endif
+ )
+ {
+ if (comping || dowide)
+ thislen = i - start;
+ else
+ thislen = i - start + cl;
+ if (thislen > 0)
+ {
+ gui_mch_draw_string(gui.row, scol, s + start, thislen,
+ draw_flags);
+ start += thislen;
+ }
+ scol += cells;
+ cells = 0;
+ if (dowide)
+ {
+ gui_mch_set_font(gui.wide_font);
+ gui_mch_draw_string(gui.row, scol - cn,
+ s + start, cl, draw_flags);
+ gui_mch_set_font(font);
+ start += cl;
+ }
+
+# if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
+ /* No fontset: draw a space to fill the gap after a wide char */
+ if (cn > 1 && (draw_flags & DRAW_TRANSP) == 0
+# ifdef FEAT_XFONTSET
+ && fontset == NOFONTSET
+# endif
+ && !dowide)
+ gui_mch_draw_string(gui.row, scol - 1, (char_u *)" ",
+ 1, draw_flags);
+# endif
+ }
+ /* Draw a composing char on top of the previous char. */
+ if (comping)
+ {
+ gui_mch_draw_string(gui.row, scol - cn, s + i, cl,
+ draw_flags | DRAW_TRANSP);
+ start = i + cl;
+ }
+ }
+ /* The stuff below assumes "len" is the length in screen columns. */
+ len = scol - col;
+ }
+ else
+# endif
+ {
+ gui_mch_draw_string(gui.row, col, s, len, draw_flags);
+# ifdef FEAT_MBYTE
+ if (enc_dbcs == DBCS_JPNU)
+ {
+ int clen = 0;
+ int i;
+
+ /* Get the length in display cells, this can be different from the
+ * number of bytes for "euc-jp". */
+ for (i = 0; i < len; i += (*mb_ptr2len_check)(s + i))
+ clen += (*mb_ptr2cells)(s + i);
+ len = clen;
+ }
+# endif
+ }
+#endif /* !HAVE_GTK2 */
+
+ if (!(flags & (GUI_MON_IS_CURSOR | GUI_MON_TRS_CURSOR)))
+ gui.col = col + len;
+
+ /* May need to invert it when it's part of the selection. */
+ if (flags & GUI_MON_NOCLEAR)
+ clip_may_redraw_selection(gui.row, col, len);
+
+ if (!(flags & (GUI_MON_IS_CURSOR | GUI_MON_TRS_CURSOR)))
+ {
+ /* Invalidate the old physical cursor position if we wrote over it */
+ if (gui.cursor_row == gui.row
+ && gui.cursor_col >= col
+ && gui.cursor_col < col + len)
+ gui.cursor_is_valid = FALSE;
+ }
+
+#ifdef FEAT_SIGN_ICONS
+ if (draw_sign)
+ /* Draw the sign on top of the spaces. */
+ gui_mch_drawsign(gui.row, col, gui.highlight_mask);
+# ifdef FEAT_NETBEANS_INTG
+ if (multi_sign)
+ netbeans_draw_multisign_indicator(gui.row);
+# endif
+#endif
+
+ return OK;
+}
+
+/*
+ * Un-draw the cursor. Actually this just redraws the character at the given
+ * position. The character just before it too, for when it was in bold.
+ */
+ void
+gui_undraw_cursor()
+{
+ if (gui.cursor_is_valid)
+ {
+#ifdef FEAT_HANGULIN
+ if (composing_hangul
+ && gui.col == gui.cursor_col && gui.row == gui.cursor_row)
+ (void)gui_outstr_nowrap(composing_hangul_buffer, 2,
+ GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR,
+ gui.norm_pixel, gui.back_pixel, 0);
+ else
+ {
+#endif
+ if (gui_redraw_block(gui.cursor_row, gui.cursor_col,
+ gui.cursor_row, gui.cursor_col, GUI_MON_NOCLEAR)
+ && gui.cursor_col > 0)
+ (void)gui_redraw_block(gui.cursor_row, gui.cursor_col - 1,
+ gui.cursor_row, gui.cursor_col - 1, GUI_MON_NOCLEAR);
+#ifdef FEAT_HANGULIN
+ if (composing_hangul)
+ (void)gui_redraw_block(gui.cursor_row, gui.cursor_col + 1,
+ gui.cursor_row, gui.cursor_col + 1, GUI_MON_NOCLEAR);
+ }
+#endif
+ /* Cursor_is_valid is reset when the cursor is undrawn, also reset it
+ * here in case it wasn't needed to undraw it. */
+ gui.cursor_is_valid = FALSE;
+ }
+}
+
+ void
+gui_redraw(x, y, w, h)
+ int x;
+ int y;
+ int w;
+ int h;
+{
+ int row1, col1, row2, col2;
+
+ row1 = Y_2_ROW(y);
+ col1 = X_2_COL(x);
+ row2 = Y_2_ROW(y + h - 1);
+ col2 = X_2_COL(x + w - 1);
+
+ (void)gui_redraw_block(row1, col1, row2, col2, GUI_MON_NOCLEAR);
+
+ /*
+ * We may need to redraw the cursor, but don't take it upon us to change
+ * its location after a scroll.
+ * (maybe be more strict even and test col too?)
+ * These things may be outside the update/clipping region and reality may
+ * not reflect Vims internal ideas if these operations are clipped away.
+ */
+ if (gui.row == gui.cursor_row)
+ gui_update_cursor(TRUE, TRUE);
+}
+
+/*
+ * Draw a rectangular block of characters, from row1 to row2 (inclusive) and
+ * from col1 to col2 (inclusive).
+ * Return TRUE when the character before the first drawn character has
+ * different attributes (may have to be redrawn too).
+ */
+ int
+gui_redraw_block(row1, col1, row2, col2, flags)
+ int row1;
+ int col1;
+ int row2;
+ int col2;
+ int flags; /* flags for gui_outstr_nowrap() */
+{
+ int old_row, old_col;
+ long_u old_hl_mask;
+ int off;
+ char_u first_attr;
+ int idx, len;
+ int back, nback;
+ int retval = FALSE;
+#ifdef FEAT_MBYTE
+ int orig_col1, orig_col2;
+#endif
+
+ /* Don't try to update when ScreenLines is not valid */
+ if (!screen_cleared || ScreenLines == NULL)
+ return retval;
+
+ /* Don't try to draw outside the shell! */
+ /* Check everything, strange values may be caused by a big border width */
+ col1 = check_col(col1);
+ col2 = check_col(col2);
+ row1 = check_row(row1);
+ row2 = check_row(row2);
+
+ /* Remember where our cursor was */
+ old_row = gui.row;
+ old_col = gui.col;
+ old_hl_mask = gui.highlight_mask;
+#ifdef FEAT_MBYTE
+ orig_col1 = col1;
+ orig_col2 = col2;
+#endif
+
+ for (gui.row = row1; gui.row <= row2; gui.row++)
+ {
+#ifdef FEAT_MBYTE
+ /* When only half of a double-wide character is in the block, include
+ * the other half. */
+ col1 = orig_col1;
+ col2 = orig_col2;
+ off = LineOffset[gui.row];
+ if (enc_dbcs != 0)
+ {
+ if (col1 > 0)
+ col1 -= dbcs_screen_head_off(ScreenLines + off,
+ ScreenLines + off + col1);
+ col2 += dbcs_screen_tail_off(ScreenLines + off,
+ ScreenLines + off + col2);
+ }
+ else if (enc_utf8)
+ {
+ if (ScreenLines[off + col1] == 0)
+ --col1;
+# ifdef HAVE_GTK2
+ if (col2 + 1 < Columns && ScreenLines[off + col2 + 1] == 0)
+ ++col2;
+# endif
+ }
+#endif
+ gui.col = col1;
+ off = LineOffset[gui.row] + gui.col;
+ len = col2 - col1 + 1;
+
+ /* Find how many chars back this highlighting starts, or where a space
+ * is. Needed for when the bold trick is used */
+ for (back = 0; back < col1; ++back)
+ if (ScreenAttrs[off - 1 - back] != ScreenAttrs[off]
+ || ScreenLines[off - 1 - back] == ' ')
+ break;
+ retval = (col1 > 0 && ScreenAttrs[off - 1] != 0 && back == 0
+ && ScreenLines[off - 1] != ' ');
+
+ /* Break it up in strings of characters with the same attributes. */
+ /* Print UTF-8 characters individually. */
+ while (len > 0)
+ {
+ first_attr = ScreenAttrs[off];
+ gui.highlight_mask = first_attr;
+#if defined(FEAT_MBYTE) && !defined(HAVE_GTK2)
+ if (enc_utf8 && ScreenLinesUC[off] != 0)
+ {
+ /* output multi-byte character separately */
+ nback = gui_screenchar(off, flags,
+ (guicolor_T)0, (guicolor_T)0, back);
+ if (gui.col < Columns && ScreenLines[off + 1] == 0)
+ idx = 2;
+ else
+ idx = 1;
+ }
+ else if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e)
+ {
+ /* output double-byte, single-width character separately */
+ nback = gui_screenchar(off, flags,
+ (guicolor_T)0, (guicolor_T)0, back);
+ idx = 1;
+ }
+ else
+#endif
+ {
+#ifdef HAVE_GTK2
+ for (idx = 0; idx < len; ++idx)
+ {
+ if (enc_utf8 && ScreenLines[off + idx] == 0)
+ continue; /* skip second half of double-width char */
+ if (ScreenAttrs[off + idx] != first_attr)
+ break;
+ }
+ /* gui_screenstr() takes care of multibyte chars */
+ nback = gui_screenstr(off, idx, flags,
+ (guicolor_T)0, (guicolor_T)0, back);
+#else
+ for (idx = 0; idx < len && ScreenAttrs[off + idx] == first_attr;
+ idx++)
+ {
+# ifdef FEAT_MBYTE
+ /* Stop at a multi-byte Unicode character. */
+ if (enc_utf8 && ScreenLinesUC[off + idx] != 0)
+ break;
+ if (enc_dbcs == DBCS_JPNU)
+ {
+ /* Stop at a double-byte single-width char. */
+ if (ScreenLines[off + idx] == 0x8e)
+ break;
+ if (len > 1 && (*mb_ptr2len_check)(ScreenLines
+ + off + idx) == 2)
+ ++idx; /* skip second byte of double-byte char */
+ }
+# endif
+ }
+ nback = gui_outstr_nowrap(ScreenLines + off, idx, flags,
+ (guicolor_T)0, (guicolor_T)0, back);
+#endif
+ }
+ if (nback == FAIL)
+ {
+ /* Must back up to start drawing where a bold or italic word
+ * starts. */
+ off -= back;
+ len += back;
+ gui.col -= back;
+ }
+ else
+ {
+ off += idx;
+ len -= idx;
+ }
+ back = 0;
+ }
+ }
+
+ /* Put the cursor back where it was */
+ gui.row = old_row;
+ gui.col = old_col;
+ gui.highlight_mask = old_hl_mask;
+
+ return retval;
+}
+
+ static void
+gui_delete_lines(row, count)
+ int row;
+ int count;
+{
+ if (count <= 0)
+ return;
+
+ if (row + count > gui.scroll_region_bot)
+ /* Scrolled out of region, just blank the lines out */
+ gui_clear_block(row, gui.scroll_region_left,
+ gui.scroll_region_bot, gui.scroll_region_right);
+ else
+ {
+ gui_mch_delete_lines(row, count);
+
+ /* If the cursor was in the deleted lines it's now gone. If the
+ * cursor was in the scrolled lines adjust its position. */
+ if (gui.cursor_row >= row
+ && gui.cursor_col >= gui.scroll_region_left
+ && gui.cursor_col <= gui.scroll_region_right)
+ {
+ if (gui.cursor_row < row + count)
+ gui.cursor_is_valid = FALSE;
+ else if (gui.cursor_row <= gui.scroll_region_bot)
+ gui.cursor_row -= count;
+ }
+ }
+}
+
+ static void
+gui_insert_lines(row, count)
+ int row;
+ int count;
+{
+ if (count <= 0)
+ return;
+
+ if (row + count > gui.scroll_region_bot)
+ /* Scrolled out of region, just blank the lines out */
+ gui_clear_block(row, gui.scroll_region_left,
+ gui.scroll_region_bot, gui.scroll_region_right);
+ else
+ {
+ gui_mch_insert_lines(row, count);
+
+ if (gui.cursor_row >= gui.row
+ && gui.cursor_col >= gui.scroll_region_left
+ && gui.cursor_col <= gui.scroll_region_right)
+ {
+ if (gui.cursor_row <= gui.scroll_region_bot - count)
+ gui.cursor_row += count;
+ else if (gui.cursor_row <= gui.scroll_region_bot)
+ gui.cursor_is_valid = FALSE;
+ }
+ }
+}
+
+/*
+ * The main GUI input routine. Waits for a character from the keyboard.
+ * wtime == -1 Wait forever.
+ * wtime == 0 Don't wait.
+ * wtime > 0 Wait wtime milliseconds for a character.
+ * Returns OK if a character was found to be available within the given time,
+ * or FAIL otherwise.
+ */
+ int
+gui_wait_for_chars(wtime)
+ long wtime;
+{
+ int retval;
+#ifdef FEAT_AUTOCMD
+ static int once_already = 0;
+#endif
+
+ /*
+ * If we're going to wait a bit, update the menus and mouse shape for the
+ * current State.
+ */
+ if (wtime != 0)
+ {
+#ifdef FEAT_MENU
+ gui_update_menus(0);
+#endif
+ }
+
+ gui_mch_update();
+ if (input_available()) /* Got char, return immediately */
+ {
+#ifdef FEAT_AUTOCMD
+ once_already = 0;
+#endif
+ return OK;
+ }
+ if (wtime == 0) /* Don't wait for char */
+ {
+#ifdef FEAT_AUTOCMD
+ once_already = 0;
+#endif
+ return FAIL;
+ }
+
+ /* Before waiting, flush any output to the screen. */
+ gui_mch_flush();
+
+ if (wtime > 0)
+ {
+ /* Blink when waiting for a character. Probably only does something
+ * for showmatch() */
+ gui_mch_start_blink();
+ retval = gui_mch_wait_for_chars(wtime);
+ gui_mch_stop_blink();
+#ifdef FEAT_AUTOCMD
+ once_already = 0;
+#endif
+ return retval;
+ }
+
+ /*
+ * While we are waiting indefenitely for a character, blink the cursor.
+ */
+ gui_mch_start_blink();
+
+
+#ifdef FEAT_AUTOCMD
+ /* If there is no character available within 2 seconds (default),
+ * write the autoscript file to disk */
+ if (once_already == 2)
+ {
+ updatescript(0);
+ retval = gui_mch_wait_for_chars(-1L);
+ once_already = 0;
+ }
+ else if (once_already == 1)
+ {
+ setcursor();
+ once_already = 2;
+ retval = 0;
+ }
+ else
+#endif
+ if (gui_mch_wait_for_chars(p_ut) != OK)
+ {
+#ifdef FEAT_AUTOCMD
+ if (has_cursorhold() && get_real_state() == NORMAL_BUSY)
+ {
+ apply_autocmds(EVENT_CURSORHOLD, NULL, NULL, FALSE, curbuf);
+ update_screen(VALID);
+ showruler(FALSE);
+ setcursor();
+
+ once_already = 1;
+ retval = 0;
+ }
+ else
+#endif
+ {
+ updatescript(0);
+ retval = gui_mch_wait_for_chars(-1L);
+#ifdef FEAT_AUTOCMD
+ once_already = 0;
+#endif
+ }
+ }
+ else
+ retval = OK;
+
+ gui_mch_stop_blink();
+ return retval;
+}
+
+/*
+ * Fill buffer with mouse coordinates encoded for check_termcode().
+ */
+ static void
+fill_mouse_coord(p, col, row)
+ char_u *p;
+ int col;
+ int row;
+{
+ p[0] = (char_u)(col / 128 + ' ' + 1);
+ p[1] = (char_u)(col % 128 + ' ' + 1);
+ p[2] = (char_u)(row / 128 + ' ' + 1);
+ p[3] = (char_u)(row % 128 + ' ' + 1);
+}
+
+/*
+ * Generic mouse support function. Add a mouse event to the input buffer with
+ * the given properties.
+ * button --- may be any of MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT,
+ * MOUSE_X1, MOUSE_X2
+ * MOUSE_DRAG, or MOUSE_RELEASE.
+ * MOUSE_4 and MOUSE_5 are used for a scroll wheel.
+ * x, y --- Coordinates of mouse in pixels.
+ * repeated_click --- TRUE if this click comes only a short time after a
+ * previous click.
+ * modifiers --- Bit field which may be any of the following modifiers
+ * or'ed together: MOUSE_SHIFT | MOUSE_CTRL | MOUSE_ALT.
+ * This function will ignore drag events where the mouse has not moved to a new
+ * character.
+ */
+ void
+gui_send_mouse_event(button, x, y, repeated_click, modifiers)
+ int button;
+ int x;
+ int y;
+ int repeated_click;
+ int_u modifiers;
+{
+ static int prev_row = 0, prev_col = 0;
+ static int prev_button = -1;
+ static int num_clicks = 1;
+ char_u string[10];
+ enum key_extra button_char;
+ int row, col;
+#ifdef FEAT_CLIPBOARD
+ int checkfor;
+ int did_clip = FALSE;
+#endif
+
+ /*
+ * Scrolling may happen at any time, also while a selection is present.
+ */
+ switch (button)
+ {
+ case MOUSE_X1:
+ button_char = KE_X1MOUSE;
+ goto button_set;
+ case MOUSE_X2:
+ button_char = KE_X2MOUSE;
+ goto button_set;
+ case MOUSE_4:
+ button_char = KE_MOUSEDOWN;
+ goto button_set;
+ case MOUSE_5:
+ button_char = KE_MOUSEUP;
+button_set:
+ {
+ /* Don't put events in the input queue now. */
+ if (hold_gui_events)
+ return;
+
+ string[3] = CSI;
+ string[4] = KS_EXTRA;
+ string[5] = (int)button_char;
+
+ /* Pass the pointer coordinates of the scroll event so that we
+ * know which window to scroll. */
+ row = gui_xy2colrow(x, y, &col);
+ string[6] = (char_u)(col / 128 + ' ' + 1);
+ string[7] = (char_u)(col % 128 + ' ' + 1);
+ string[8] = (char_u)(row / 128 + ' ' + 1);
+ string[9] = (char_u)(row % 128 + ' ' + 1);
+
+ if (modifiers == 0)
+ add_to_input_buf(string + 3, 7);
+ else
+ {
+ string[0] = CSI;
+ string[1] = KS_MODIFIER;
+ string[2] = 0;
+ if (modifiers & MOUSE_SHIFT)
+ string[2] |= MOD_MASK_SHIFT;
+ if (modifiers & MOUSE_CTRL)
+ string[2] |= MOD_MASK_CTRL;
+ if (modifiers & MOUSE_ALT)
+ string[2] |= MOD_MASK_ALT;
+ add_to_input_buf(string, 10);
+ }
+ return;
+ }
+ }
+
+#ifdef FEAT_CLIPBOARD
+ /* If a clipboard selection is in progress, handle it */
+ if (clip_star.state == SELECT_IN_PROGRESS)
+ {
+ clip_process_selection(button, X_2_COL(x), Y_2_ROW(y), repeated_click);
+ return;
+ }
+
+ /* Determine which mouse settings to look for based on the current mode */
+ switch (get_real_state())
+ {
+ case NORMAL_BUSY:
+ case OP_PENDING:
+ case NORMAL: checkfor = MOUSE_NORMAL; break;
+ case VISUAL: checkfor = MOUSE_VISUAL; break;
+ case REPLACE:
+ case REPLACE+LANGMAP:
+#ifdef FEAT_VREPLACE
+ case VREPLACE:
+ case VREPLACE+LANGMAP:
+#endif
+ case INSERT:
+ case INSERT+LANGMAP: checkfor = MOUSE_INSERT; break;
+ case ASKMORE:
+ case HITRETURN: /* At the more- and hit-enter prompt pass the
+ mouse event for a click on or below the
+ message line. */
+ if (Y_2_ROW(y) >= msg_row)
+ checkfor = MOUSE_NORMAL;
+ else
+ checkfor = MOUSE_RETURN;
+ break;
+
+ /*
+ * On the command line, use the clipboard selection on all lines
+ * but the command line. But not when pasting.
+ */
+ case CMDLINE:
+ case CMDLINE+LANGMAP:
+ if (Y_2_ROW(y) < cmdline_row && button != MOUSE_MIDDLE)
+ checkfor = MOUSE_NONE;
+ else
+ checkfor = MOUSE_COMMAND;
+ break;
+
+ default:
+ checkfor = MOUSE_NONE;
+ break;
+ };
+
+ /*
+ * Allow clipboard selection of text on the command line in "normal"
+ * modes. Don't do this when dragging the status line, or extending a
+ * Visual selection.
+ */
+ if ((State == NORMAL || State == NORMAL_BUSY || (State & INSERT))
+ && Y_2_ROW(y) >= topframe->fr_height
+ && button != MOUSE_DRAG
+# ifdef FEAT_MOUSESHAPE
+ && !drag_status_line
+# ifdef FEAT_VERTSPLIT
+ && !drag_sep_line
+# endif
+# endif
+ )
+ checkfor = MOUSE_NONE;
+
+ /*
+ * Use modeless selection when holding CTRL and SHIFT pressed.
+ */
+ if ((modifiers & MOUSE_CTRL) && (modifiers & MOUSE_SHIFT))
+ checkfor = MOUSE_NONEF;
+
+ /*
+ * In Ex mode, always use modeless selection.
+ */
+ if (exmode_active)
+ checkfor = MOUSE_NONE;
+
+ /*
+ * If the mouse settings say to not use the mouse, use the modeless
+ * selection. But if Visual is active, assume that only the Visual area
+ * will be selected.
+ * Exception: On the command line, both the selection is used and a mouse
+ * key is send.
+ */
+ if (!mouse_has(checkfor) || checkfor == MOUSE_COMMAND)
+ {
+#ifdef FEAT_VISUAL
+ /* Don't do modeless selection in Visual mode. */
+ if (checkfor != MOUSE_NONEF && VIsual_active && (State & NORMAL))
+ return;
+#endif
+
+ /*
+ * When 'mousemodel' is "popup", shift-left is translated to right.
+ * But not when also using Ctrl.
+ */
+ if (mouse_model_popup() && button == MOUSE_LEFT
+ && (modifiers & MOUSE_SHIFT) && !(modifiers & MOUSE_CTRL))
+ {
+ button = MOUSE_RIGHT;
+ modifiers &= ~ MOUSE_SHIFT;
+ }
+
+ /* If the selection is done, allow the right button to extend it.
+ * If the selection is cleared, allow the right button to start it
+ * from the cursor position. */
+ if (button == MOUSE_RIGHT)
+ {
+ if (clip_star.state == SELECT_CLEARED)
+ {
+ if (State & CMDLINE)
+ {
+ col = msg_col;
+ row = msg_row;
+ }
+ else
+ {
+ col = curwin->w_wcol;
+ row = curwin->w_wrow + W_WINROW(curwin);
+ }
+ clip_start_selection(col, row, FALSE);
+ }
+ clip_process_selection(button, X_2_COL(x), Y_2_ROW(y),
+ repeated_click);
+ did_clip = TRUE;
+ }
+ /* Allow the left button to start the selection */
+ else if (button ==
+# ifdef RISCOS
+ /* Only start a drag on a drag event. Otherwise
+ * we don't get a release event. */
+ MOUSE_DRAG
+# else
+ MOUSE_LEFT
+# endif
+ )
+ {
+ clip_start_selection(X_2_COL(x), Y_2_ROW(y), repeated_click);
+ did_clip = TRUE;
+ }
+# ifdef RISCOS
+ else if (button == MOUSE_LEFT)
+ {
+ clip_clear_selection();
+ did_clip = TRUE;
+ }
+# endif
+
+ /* Always allow pasting */
+ if (button != MOUSE_MIDDLE)
+ {
+ if (!mouse_has(checkfor) || button == MOUSE_RELEASE)
+ return;
+ if (checkfor != MOUSE_COMMAND)
+ button = MOUSE_LEFT;
+ }
+ repeated_click = FALSE;
+ }
+
+ if (clip_star.state != SELECT_CLEARED && !did_clip)
+ clip_clear_selection();
+#endif
+
+ /* Don't put events in the input queue now. */
+ if (hold_gui_events)
+ return;
+
+ row = gui_xy2colrow(x, y, &col);
+
+ /*
+ * If we are dragging and the mouse hasn't moved far enough to be on a
+ * different character, then don't send an event to vim.
+ */
+ if (button == MOUSE_DRAG)
+ {
+ if (row == prev_row && col == prev_col)
+ return;
+ /* Dragging above the window, set "row" to -1 to cause a scroll. */
+ if (y < 0)
+ row = -1;
+ }
+
+ /*
+ * If topline has changed (window scrolled) since the last click, reset
+ * repeated_click, because we don't want starting Visual mode when
+ * clicking on a different character in the text.
+ */
+ if (curwin->w_topline != gui_prev_topline
+#ifdef FEAT_DIFF
+ || curwin->w_topfill != gui_prev_topfill
+#endif
+ )
+ repeated_click = FALSE;
+
+ string[0] = CSI; /* this sequence is recognized by check_termcode() */
+ string[1] = KS_MOUSE;
+ string[2] = KE_FILLER;
+ if (button != MOUSE_DRAG && button != MOUSE_RELEASE)
+ {
+ if (repeated_click)
+ {
+ /*
+ * Handle multiple clicks. They only count if the mouse is still
+ * pointing at the same character.
+ */
+ if (button != prev_button || row != prev_row || col != prev_col)
+ num_clicks = 1;
+ else if (++num_clicks > 4)
+ num_clicks = 1;
+ }
+ else
+ num_clicks = 1;
+ prev_button = button;
+ gui_prev_topline = curwin->w_topline;
+#ifdef FEAT_DIFF
+ gui_prev_topfill = curwin->w_topfill;
+#endif
+
+ string[3] = (char_u)(button | 0x20);
+ SET_NUM_MOUSE_CLICKS(string[3], num_clicks);
+ }
+ else
+ string[3] = (char_u)button;
+
+ string[3] |= modifiers;
+ fill_mouse_coord(string + 4, col, row);
+ add_to_input_buf(string, 8);
+
+ if (row < 0)
+ prev_row = 0;
+ else
+ prev_row = row;
+ prev_col = col;
+
+ /*
+ * We need to make sure this is cleared since Athena doesn't tell us when
+ * he is done dragging. Neither does GTK+ 2 -- at least for now.
+ */
+#if defined(FEAT_GUI_ATHENA) || defined(HAVE_GTK2)
+ gui.dragged_sb = SBAR_NONE;
+#endif
+}
+
+/*
+ * Convert x and y coordinate to column and row in text window.
+ * Corrects for multi-byte character.
+ * returns column in "*colp" and row as return value;
+ */
+ int
+gui_xy2colrow(x, y, colp)
+ int x;
+ int y;
+ int *colp;
+{
+ int col = check_col(X_2_COL(x));
+ int row = check_row(Y_2_ROW(y));
+
+#ifdef FEAT_MBYTE
+ *colp = mb_fix_col(col, row);
+#else
+ *colp = col;
+#endif
+ return row;
+}
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Callback function for when a menu entry has been selected.
+ */
+ void
+gui_menu_cb(menu)
+ vimmenu_T *menu;
+{
+ char_u bytes[3 + sizeof(long_u)];
+
+ /* Don't put events in the input queue now. */
+ if (hold_gui_events)
+ return;
+
+ bytes[0] = CSI;
+ bytes[1] = KS_MENU;
+ bytes[2] = KE_FILLER;
+ add_long_to_buf((long_u)menu, bytes + 3);
+ add_to_input_buf(bytes, 3 + sizeof(long_u));
+}
+#endif
+
+/*
+ * Set which components are present.
+ * If "oldval" is not NULL, "oldval" is the previous value, the new * value is
+ * in p_go.
+ */
+/*ARGSUSED*/
+ void
+gui_init_which_components(oldval)
+ char_u *oldval;
+{
+ static int prev_which_scrollbars[3] = {-1, -1, -1};
+#ifdef FEAT_MENU
+ static int prev_menu_is_active = -1;
+#endif
+#ifdef FEAT_TOOLBAR
+ static int prev_toolbar = -1;
+ int using_toolbar = FALSE;
+#endif
+#ifdef FEAT_FOOTER
+ static int prev_footer = -1;
+ int using_footer = FALSE;
+#endif
+#if defined(FEAT_MENU) && !defined(WIN16)
+ static int prev_tearoff = -1;
+ int using_tearoff = FALSE;
+#endif
+
+ char_u *p;
+ int i;
+#ifdef FEAT_MENU
+ int grey_old, grey_new;
+ char_u *temp;
+#endif
+ win_T *wp;
+ int need_set_size;
+ int fix_size;
+
+#ifdef FEAT_MENU
+ if (oldval != NULL && gui.in_use)
+ {
+ /*
+ * Check if the menu's go from grey to non-grey or vise versa.
+ */
+ grey_old = (vim_strchr(oldval, GO_GREY) != NULL);
+ grey_new = (vim_strchr(p_go, GO_GREY) != NULL);
+ if (grey_old != grey_new)
+ {
+ temp = p_go;
+ p_go = oldval;
+ gui_update_menus(MENU_ALL_MODES);
+ p_go = temp;
+ }
+ }
+ gui.menu_is_active = FALSE;
+#endif
+
+ for (i = 0; i < 3; i++)
+ gui.which_scrollbars[i] = FALSE;
+ for (p = p_go; *p; p++)
+ switch (*p)
+ {
+ case GO_LEFT:
+ gui.which_scrollbars[SBAR_LEFT] = TRUE;
+ break;
+ case GO_RIGHT:
+ gui.which_scrollbars[SBAR_RIGHT] = TRUE;
+ break;
+#ifdef FEAT_VERTSPLIT
+ case GO_VLEFT:
+ if (win_hasvertsplit())
+ gui.which_scrollbars[SBAR_LEFT] = TRUE;
+ break;
+ case GO_VRIGHT:
+ if (win_hasvertsplit())
+ gui.which_scrollbars[SBAR_RIGHT] = TRUE;
+ break;
+#endif
+ case GO_BOT:
+ gui.which_scrollbars[SBAR_BOTTOM] = TRUE;
+ break;
+#ifdef FEAT_MENU
+ case GO_MENUS:
+ gui.menu_is_active = TRUE;
+ break;
+#endif
+ case GO_GREY:
+ /* make menu's have grey items, ignored here */
+ break;
+#ifdef FEAT_TOOLBAR
+ case GO_TOOLBAR:
+ using_toolbar = TRUE;
+ break;
+#endif
+#ifdef FEAT_FOOTER
+ case GO_FOOTER:
+ using_footer = TRUE;
+ break;
+#endif
+ case GO_TEAROFF:
+#if defined(FEAT_MENU) && !defined(WIN16)
+ using_tearoff = TRUE;
+#endif
+ break;
+ default:
+ /* Ignore options that are not supported */
+ break;
+ }
+ if (gui.in_use)
+ {
+ need_set_size = FALSE;
+ fix_size = FALSE;
+ for (i = 0; i < 3; i++)
+ {
+ if (gui.which_scrollbars[i] != prev_which_scrollbars[i])
+ {
+ if (i == SBAR_BOTTOM)
+ gui_mch_enable_scrollbar(&gui.bottom_sbar,
+ gui.which_scrollbars[i]);
+ else
+ {
+ FOR_ALL_WINDOWS(wp)
+ {
+ gui_do_scrollbar(wp, i, gui.which_scrollbars[i]);
+ }
+ }
+ need_set_size = TRUE;
+ if (gui.which_scrollbars[i])
+ fix_size = TRUE;
+ }
+ prev_which_scrollbars[i] = gui.which_scrollbars[i];
+ }
+
+#ifdef FEAT_MENU
+ if (gui.menu_is_active != prev_menu_is_active)
+ {
+ /* We don't want a resize event change "Rows" here, save and
+ * restore it. Resizing is handled below. */
+ i = Rows;
+ gui_mch_enable_menu(gui.menu_is_active);
+ Rows = i;
+ prev_menu_is_active = gui.menu_is_active;
+ need_set_size = TRUE;
+ if (gui.menu_is_active)
+ fix_size = TRUE;
+ }
+#endif
+
+#ifdef FEAT_TOOLBAR
+ if (using_toolbar != prev_toolbar)
+ {
+ gui_mch_show_toolbar(using_toolbar);
+ prev_toolbar = using_toolbar;
+ need_set_size = TRUE;
+ if (using_toolbar)
+ fix_size = TRUE;
+ }
+#endif
+#ifdef FEAT_FOOTER
+ if (using_footer != prev_footer)
+ {
+ gui_mch_enable_footer(using_footer);
+ prev_footer = using_footer;
+ need_set_size = TRUE;
+ if (using_footer)
+ fix_size = TRUE;
+ }
+#endif
+#if defined(FEAT_MENU) && !defined(WIN16) && !(defined(WIN3264) && !defined(FEAT_TEAROFF))
+ if (using_tearoff != prev_tearoff)
+ {
+ gui_mch_toggle_tearoffs(using_tearoff);
+ prev_tearoff = using_tearoff;
+ }
+#endif
+ if (need_set_size)
+ /* Adjust the size of the window to make the text area keep the
+ * same size and to avoid that part of our window is off-screen
+ * and a scrollbar can't be used, for example. */
+ gui_set_shellsize(FALSE, fix_size);
+ }
+}
+
+
+/*
+ * Scrollbar stuff:
+ */
+
+ void
+gui_create_scrollbar(sb, type, wp)
+ scrollbar_T *sb;
+ int type;
+ win_T *wp;
+{
+ static int sbar_ident = 0;
+
+ sb->ident = sbar_ident++; /* No check for too big, but would it happen? */
+ sb->wp = wp;
+ sb->type = type;
+ sb->value = 0;
+#ifdef FEAT_GUI_ATHENA
+ sb->pixval = 0;
+#endif
+ sb->size = 1;
+ sb->max = 1;
+ sb->top = 0;
+ sb->height = 0;
+#ifdef FEAT_VERTSPLIT
+ sb->width = 0;
+#endif
+ sb->status_height = 0;
+ gui_mch_create_scrollbar(sb, (wp == NULL) ? SBAR_HORIZ : SBAR_VERT);
+}
+
+/*
+ * Find the scrollbar with the given index.
+ */
+ scrollbar_T *
+gui_find_scrollbar(ident)
+ long ident;
+{
+ win_T *wp;
+
+ if (gui.bottom_sbar.ident == ident)
+ return &gui.bottom_sbar;
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_scrollbars[SBAR_LEFT].ident == ident)
+ return &wp->w_scrollbars[SBAR_LEFT];
+ if (wp->w_scrollbars[SBAR_RIGHT].ident == ident)
+ return &wp->w_scrollbars[SBAR_RIGHT];
+ }
+ return NULL;
+}
+
+/*
+ * For most systems: Put a code in the input buffer for a dragged scrollbar.
+ *
+ * For Win32, Macintosh and GTK+ 2:
+ * Scrollbars seem to grab focus and vim doesn't read the input queue until
+ * you stop dragging the scrollbar. We get here each time the scrollbar is
+ * dragged another pixel, but as far as the rest of vim goes, it thinks
+ * we're just hanging in the call to DispatchMessage() in
+ * process_message(). The DispatchMessage() call that hangs was passed a
+ * mouse button click event in the scrollbar window. -- webb.
+ *
+ * Solution: Do the scrolling right here. But only when allowed.
+ * Ignore the scrollbars while executing an external command or when there
+ * are still characters to be processed.
+ */
+ void
+gui_drag_scrollbar(sb, value, still_dragging)
+ scrollbar_T *sb;
+ long value;
+ int still_dragging;
+{
+#ifdef FEAT_WINDOWS
+ win_T *wp;
+#endif
+ int sb_num;
+#ifdef USE_ON_FLY_SCROLL
+ colnr_T old_leftcol = curwin->w_leftcol;
+# ifdef FEAT_SCROLLBIND
+ linenr_T old_topline = curwin->w_topline;
+# endif
+# ifdef FEAT_DIFF
+ int old_topfill = curwin->w_topfill;
+# endif
+#else
+ char_u bytes[4 + sizeof(long_u)];
+ int byte_count;
+#endif
+
+ if (sb == NULL)
+ return;
+
+ /* Don't put events in the input queue now. */
+ if (hold_gui_events)
+ return;
+
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0 && sb->wp != curwin)
+ return;
+#endif
+
+ if (still_dragging)
+ {
+ if (sb->wp == NULL)
+ gui.dragged_sb = SBAR_BOTTOM;
+ else if (sb == &sb->wp->w_scrollbars[SBAR_LEFT])
+ gui.dragged_sb = SBAR_LEFT;
+ else
+ gui.dragged_sb = SBAR_RIGHT;
+ gui.dragged_wp = sb->wp;
+ }
+ else
+ {
+ gui.dragged_sb = SBAR_NONE;
+#ifdef HAVE_GTK2
+ /* Keep the "dragged_wp" value until after the scrolling, for when the
+ * moust button is released. GTK2 doesn't send the button-up event. */
+ gui.dragged_wp = NULL;
+#endif
+ }
+
+ /* Vertical sbar info is kept in the first sbar (the left one) */
+ if (sb->wp != NULL)
+ sb = &sb->wp->w_scrollbars[0];
+
+ /*
+ * Check validity of value
+ */
+ if (value < 0)
+ value = 0;
+#ifdef SCROLL_PAST_END
+ else if (value > sb->max)
+ value = sb->max;
+#else
+ if (value > sb->max - sb->size + 1)
+ value = sb->max - sb->size + 1;
+#endif
+
+ sb->value = value;
+
+#ifdef USE_ON_FLY_SCROLL
+ /* When not allowed to do the scrolling right now, return. */
+ if (dont_scroll || input_available())
+ return;
+#endif
+
+#ifdef FEAT_RIGHTLEFT
+ if (sb->wp == NULL && curwin->w_p_rl)
+ {
+ value = sb->max + 1 - sb->size - value;
+ if (value < 0)
+ value = 0;
+ }
+#endif
+
+ if (sb->wp != NULL) /* vertical scrollbar */
+ {
+ sb_num = 0;
+#ifdef FEAT_WINDOWS
+ for (wp = firstwin; wp != sb->wp && wp != NULL; wp = wp->w_next)
+ sb_num++;
+ if (wp == NULL)
+ return;
+#else
+ if (sb->wp != curwin)
+ return;
+#endif
+
+#ifdef USE_ON_FLY_SCROLL
+ current_scrollbar = sb_num;
+ scrollbar_value = value;
+ if (State & NORMAL)
+ {
+ gui_do_scroll();
+ setcursor();
+ }
+ else if (State & INSERT)
+ {
+ ins_scroll();
+ setcursor();
+ }
+ else if (State & CMDLINE)
+ {
+ if (msg_scrolled == 0)
+ {
+ gui_do_scroll();
+ redrawcmdline();
+ }
+ }
+# ifdef FEAT_FOLDING
+ /* Value may have been changed for closed fold. */
+ sb->value = sb->wp->w_topline - 1;
+# endif
+#else
+ bytes[0] = CSI;
+ bytes[1] = KS_VER_SCROLLBAR;
+ bytes[2] = KE_FILLER;
+ bytes[3] = (char_u)sb_num;
+ byte_count = 4;
+#endif
+ }
+ else
+ {
+#ifdef USE_ON_FLY_SCROLL
+ scrollbar_value = value;
+
+ if (State & NORMAL)
+ gui_do_horiz_scroll();
+ else if (State & INSERT)
+ ins_horscroll();
+ else if (State & CMDLINE)
+ {
+ if (!msg_scrolled)
+ {
+ gui_do_horiz_scroll();
+ redrawcmdline();
+ }
+ }
+ if (old_leftcol != curwin->w_leftcol)
+ {
+ updateWindow(curwin); /* update window, status and cmdline */
+ setcursor();
+ }
+#else
+ bytes[0] = CSI;
+ bytes[1] = KS_HOR_SCROLLBAR;
+ bytes[2] = KE_FILLER;
+ byte_count = 3;
+#endif
+ }
+
+#ifdef USE_ON_FLY_SCROLL
+# ifdef FEAT_SCROLLBIND
+ /*
+ * synchronize other windows, as necessary according to 'scrollbind'
+ */
+ if (curwin->w_p_scb
+ && ((sb->wp == NULL && curwin->w_leftcol != old_leftcol)
+ || (sb->wp == curwin && (curwin->w_topline != old_topline
+# ifdef FEAT_DIFF
+ || curwin->w_topfill != old_topfill
+# endif
+ ))))
+ {
+ do_check_scrollbind(TRUE);
+ /* need to update the window right here */
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_redr_type > 0)
+ updateWindow(wp);
+ setcursor();
+ }
+# endif
+ out_flush();
+ gui_update_cursor(FALSE, TRUE);
+#else
+ add_long_to_buf((long)value, bytes + byte_count);
+ add_to_input_buf(bytes, byte_count + sizeof(long_u));
+#endif
+}
+
+/*
+ * Scrollbar stuff:
+ */
+
+ void
+gui_update_scrollbars(force)
+ int force; /* Force all scrollbars to get updated */
+{
+ win_T *wp;
+ scrollbar_T *sb;
+ long val, size, max; /* need 32 bits here */
+ int which_sb;
+ int h, y;
+#ifdef FEAT_VERTSPLIT
+ static win_T *prev_curwin = NULL;
+#endif
+
+ /* Update the horizontal scrollbar */
+ gui_update_horiz_scrollbar(force);
+
+#ifndef WIN3264
+ /* Return straight away if there is neither a left nor right scrollbar.
+ * On MS-Windows this is required anyway for scrollwheel messages. */
+ if (!gui.which_scrollbars[SBAR_LEFT] && !gui.which_scrollbars[SBAR_RIGHT])
+ return;
+#endif
+
+ /*
+ * Don't want to update a scrollbar while we're dragging it. But if we
+ * have both a left and right scrollbar, and we drag one of them, we still
+ * need to update the other one.
+ */
+ if ( (gui.dragged_sb == SBAR_LEFT
+ || gui.dragged_sb == SBAR_RIGHT)
+ && (!gui.which_scrollbars[SBAR_LEFT]
+ || !gui.which_scrollbars[SBAR_RIGHT])
+ && !force)
+ return;
+
+ if (!force && (gui.dragged_sb == SBAR_LEFT || gui.dragged_sb == SBAR_RIGHT))
+ {
+ /*
+ * If we have two scrollbars and one of them is being dragged, just
+ * copy the scrollbar position from the dragged one to the other one.
+ */
+ which_sb = SBAR_LEFT + SBAR_RIGHT - gui.dragged_sb;
+ if (gui.dragged_wp != NULL)
+ gui_mch_set_scrollbar_thumb(
+ &gui.dragged_wp->w_scrollbars[which_sb],
+ gui.dragged_wp->w_scrollbars[0].value,
+ gui.dragged_wp->w_scrollbars[0].size,
+ gui.dragged_wp->w_scrollbars[0].max);
+ return;
+ }
+
+ /* avoid that moving components around generates events */
+ ++hold_gui_events;
+
+ for (wp = firstwin; wp != NULL; wp = W_NEXT(wp))
+ {
+ if (wp->w_buffer == NULL) /* just in case */
+ continue;
+#ifdef SCROLL_PAST_END
+ max = wp->w_buffer->b_ml.ml_line_count - 1;
+#else
+ max = wp->w_buffer->b_ml.ml_line_count + wp->w_height - 2;
+#endif
+ if (max < 0) /* empty buffer */
+ max = 0;
+ val = wp->w_topline - 1;
+ size = wp->w_height;
+#ifdef SCROLL_PAST_END
+ if (val > max) /* just in case */
+ val = max;
+#else
+ if (size > max + 1) /* just in case */
+ size = max + 1;
+ if (val > max - size + 1)
+ val = max - size + 1;
+#endif
+ if (val < 0) /* minimal value is 0 */
+ val = 0;
+
+ /*
+ * Scrollbar at index 0 (the left one) contains all the information.
+ * It would be the same info for left and right so we just store it for
+ * one of them.
+ */
+ sb = &wp->w_scrollbars[0];
+
+ /*
+ * Note: no check for valid w_botline. If it's not valid the
+ * scrollbars will be updated later anyway.
+ */
+ if (size < 1 || wp->w_botline - 2 > max)
+ {
+ /*
+ * This can happen during changing files. Just don't update the
+ * scrollbar for now.
+ */
+ sb->height = 0; /* Force update next time */
+ if (gui.which_scrollbars[SBAR_LEFT])
+ gui_do_scrollbar(wp, SBAR_LEFT, FALSE);
+ if (gui.which_scrollbars[SBAR_RIGHT])
+ gui_do_scrollbar(wp, SBAR_RIGHT, FALSE);
+ continue;
+ }
+ if (force || sb->height != wp->w_height
+#ifdef FEAT_WINDOWS
+ || sb->top != wp->w_winrow
+ || sb->status_height != wp->w_status_height
+# ifdef FEAT_VERTSPLIT
+ || sb->width != wp->w_width
+ || prev_curwin != curwin
+# endif
+#endif
+ )
+ {
+ /* Height, width or position of scrollbar has changed. For
+ * vertical split: curwin changed. */
+ sb->height = wp->w_height;
+#ifdef FEAT_WINDOWS
+ sb->top = wp->w_winrow;
+ sb->status_height = wp->w_status_height;
+# ifdef FEAT_VERTSPLIT
+ sb->width = wp->w_width;
+# endif
+#endif
+
+ /* Calculate height and position in pixels */
+ h = (sb->height + sb->status_height) * gui.char_height;
+ y = sb->top * gui.char_height + gui.border_offset;
+#if defined(FEAT_MENU) && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MOTIF) && !defined(FEAT_GUI_PHOTON)
+ if (gui.menu_is_active)
+ y += gui.menu_height;
+#endif
+
+#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA))
+ if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
+# ifdef FEAT_GUI_ATHENA
+ y += gui.toolbar_height;
+# else
+# ifdef FEAT_GUI_MSWIN
+ y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT;
+# endif
+# endif
+#endif
+
+#ifdef FEAT_WINDOWS
+ if (wp->w_winrow == 0)
+#endif
+ {
+ /* Height of top scrollbar includes width of top border */
+ h += gui.border_offset;
+ y -= gui.border_offset;
+ }
+ if (gui.which_scrollbars[SBAR_LEFT])
+ {
+ gui_mch_set_scrollbar_pos(&wp->w_scrollbars[SBAR_LEFT],
+ gui.left_sbar_x, y,
+ gui.scrollbar_width, h);
+ gui_do_scrollbar(wp, SBAR_LEFT, TRUE);
+ }
+ if (gui.which_scrollbars[SBAR_RIGHT])
+ {
+ gui_mch_set_scrollbar_pos(&wp->w_scrollbars[SBAR_RIGHT],
+ gui.right_sbar_x, y,
+ gui.scrollbar_width, h);
+ gui_do_scrollbar(wp, SBAR_RIGHT, TRUE);
+ }
+ }
+
+ /* Reduce the number of calls to gui_mch_set_scrollbar_thumb() by
+ * checking if the thumb moved at least a pixel. Only do this for
+ * Athena, most other GUIs require the update anyway to make the
+ * arrows work. */
+#ifdef FEAT_GUI_ATHENA
+ if (max == 0)
+ y = 0;
+ else
+ y = (val * (sb->height + 2) * gui.char_height + max / 2) / max;
+ if (force || sb->pixval != y || sb->size != size || sb->max != max)
+#else
+ if (force || sb->value != val || sb->size != size || sb->max != max)
+#endif
+ {
+ /* Thumb of scrollbar has moved */
+ sb->value = val;
+#ifdef FEAT_GUI_ATHENA
+ sb->pixval = y;
+#endif
+ sb->size = size;
+ sb->max = max;
+ if (gui.which_scrollbars[SBAR_LEFT] && gui.dragged_sb != SBAR_LEFT)
+ gui_mch_set_scrollbar_thumb(&wp->w_scrollbars[SBAR_LEFT],
+ val, size, max);
+ if (gui.which_scrollbars[SBAR_RIGHT]
+ && gui.dragged_sb != SBAR_RIGHT)
+ gui_mch_set_scrollbar_thumb(&wp->w_scrollbars[SBAR_RIGHT],
+ val, size, max);
+ }
+ }
+#ifdef FEAT_VERTSPLIT
+ prev_curwin = curwin;
+#endif
+ --hold_gui_events;
+}
+
+/*
+ * Enable or disable a scrollbar.
+ * Check for scrollbars for vertically split windows which are not enabled
+ * sometimes.
+ */
+ static void
+gui_do_scrollbar(wp, which, enable)
+ win_T *wp;
+ int which; /* SBAR_LEFT or SBAR_RIGHT */
+ int enable; /* TRUE to enable scrollbar */
+{
+#ifdef FEAT_VERTSPLIT
+ int midcol = curwin->w_wincol + curwin->w_width / 2;
+ int has_midcol = (wp->w_wincol <= midcol
+ && wp->w_wincol + wp->w_width >= midcol);
+
+ /* Only enable scrollbars that contain the middle column of the current
+ * window. */
+ if (gui.which_scrollbars[SBAR_RIGHT] != gui.which_scrollbars[SBAR_LEFT])
+ {
+ /* Scrollbars only on one side. Don't enable scrollbars that don't
+ * contain the middle column of the current window. */
+ if (!has_midcol)
+ enable = FALSE;
+ }
+ else
+ {
+ /* Scrollbars on both sides. Don't enable scrollbars that neither
+ * contain the middle column of the current window nor are on the far
+ * side. */
+ if (midcol > Columns / 2)
+ {
+ if (which == SBAR_LEFT ? wp->w_wincol != 0 : !has_midcol)
+ enable = FALSE;
+ }
+ else
+ {
+ if (which == SBAR_RIGHT ? wp->w_wincol + wp->w_width != Columns
+ : !has_midcol)
+ enable = FALSE;
+ }
+ }
+#endif
+ gui_mch_enable_scrollbar(&wp->w_scrollbars[which], enable);
+}
+
+/*
+ * Scroll a window according to the values set in the globals current_scrollbar
+ * and scrollbar_value. Return TRUE if the cursor in the current window moved
+ * or FALSE otherwise.
+ */
+ int
+gui_do_scroll()
+{
+ win_T *wp, *save_wp;
+ int i;
+ long nlines;
+ pos_T old_cursor;
+ linenr_T old_topline;
+#ifdef FEAT_DIFF
+ int old_topfill;
+#endif
+
+ for (wp = firstwin, i = 0; i < current_scrollbar; wp = W_NEXT(wp), i++)
+ if (wp == NULL)
+ break;
+ if (wp == NULL)
+ /* Couldn't find window */
+ return FALSE;
+
+ /*
+ * Compute number of lines to scroll. If zero, nothing to do.
+ */
+ nlines = (long)scrollbar_value + 1 - (long)wp->w_topline;
+ if (nlines == 0)
+ return FALSE;
+
+ save_wp = curwin;
+ old_topline = wp->w_topline;
+#ifdef FEAT_DIFF
+ old_topfill = wp->w_topfill;
+#endif
+ old_cursor = wp->w_cursor;
+ curwin = wp;
+ curbuf = wp->w_buffer;
+ if (nlines < 0)
+ scrolldown(-nlines, gui.dragged_wp == NULL);
+ else
+ scrollup(nlines, gui.dragged_wp == NULL);
+ /* Reset dragged_wp after using it. "dragged_sb" will have been reset for
+ * the mouse-up event already, but we still want it to behave like when
+ * dragging. But not the next click in an arrow. */
+ if (gui.dragged_sb == SBAR_NONE)
+ gui.dragged_wp = NULL;
+
+ if (old_topline != wp->w_topline
+#ifdef FEAT_DIFF
+ || old_topfill != wp->w_topfill
+#endif
+ )
+ {
+ if (p_so != 0)
+ {
+ cursor_correct(); /* fix window for 'so' */
+ update_topline(); /* avoid up/down jump */
+ }
+ if (old_cursor.lnum != wp->w_cursor.lnum)
+ coladvance(wp->w_curswant);
+#ifdef FEAT_SCROLLBIND
+ wp->w_scbind_pos = wp->w_topline;
+#endif
+ }
+
+ curwin = save_wp;
+ curbuf = save_wp->w_buffer;
+
+ /*
+ * Don't call updateWindow() when nothing has changed (it will overwrite
+ * the status line!).
+ */
+ if (old_topline != wp->w_topline
+#ifdef FEAT_DIFF
+ || old_topfill != wp->w_topfill
+#endif
+ )
+ {
+ redraw_win_later(wp, VALID);
+ updateWindow(wp); /* update window, status line, and cmdline */
+ }
+
+ return (wp == curwin && !equalpos(curwin->w_cursor, old_cursor));
+}
+
+
+/*
+ * Horizontal scrollbar stuff:
+ */
+
+/*
+ * Return length of line "lnum" for horizontal scrolling.
+ */
+ static colnr_T
+scroll_line_len(lnum)
+ linenr_T lnum;
+{
+ char_u *p;
+ colnr_T col;
+ int w;
+
+ p = ml_get(lnum);
+ col = 0;
+ if (*p != NUL)
+ for (;;)
+ {
+ w = chartabsize(p, col);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p);
+ else
+#endif
+ ++p;
+ if (*p == NUL) /* don't count the last character */
+ break;
+ col += w;
+ }
+ return col;
+}
+
+/* Remember which line is currently the longest, so that we don't have to
+ * search for it when scrolling horizontally. */
+static linenr_T longest_lnum = 0;
+
+ static void
+gui_update_horiz_scrollbar(force)
+ int force;
+{
+ long value, size, max; /* need 32 bit ints here */
+
+ if (!gui.which_scrollbars[SBAR_BOTTOM])
+ return;
+
+ if (!force && gui.dragged_sb == SBAR_BOTTOM)
+ return;
+
+ if (!force && curwin->w_p_wrap && gui.prev_wrap)
+ return;
+
+ /*
+ * It is possible for the cursor to be invalid if we're in the middle of
+ * something (like changing files). If so, don't do anything for now.
+ */
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
+ {
+ gui.bottom_sbar.value = -1;
+ return;
+ }
+
+ size = W_WIDTH(curwin);
+ if (curwin->w_p_wrap)
+ {
+ value = 0;
+#ifdef SCROLL_PAST_END
+ max = 0;
+#else
+ max = W_WIDTH(curwin) - 1;
+#endif
+ }
+ else
+ {
+ value = curwin->w_leftcol;
+
+ /* Calculate maximum for horizontal scrollbar. Check for reasonable
+ * line numbers, topline and botline can be invalid when displaying is
+ * postponed. */
+ if (vim_strchr(p_go, GO_HORSCROLL) == NULL
+ && curwin->w_topline <= curwin->w_cursor.lnum
+ && curwin->w_botline > curwin->w_cursor.lnum
+ && curwin->w_botline <= curbuf->b_ml.ml_line_count + 1)
+ {
+ linenr_T lnum;
+ colnr_T n;
+
+ /* Use maximum of all visible lines. Remember the lnum of the
+ * longest line, clostest to the cursor line. Used when scrolling
+ * below. */
+ max = 0;
+ for (lnum = curwin->w_topline; lnum < curwin->w_botline; ++lnum)
+ {
+ n = scroll_line_len(lnum);
+ if (n > (colnr_T)max)
+ {
+ max = n;
+ longest_lnum = lnum;
+ }
+ else if (n == (colnr_T)max
+ && abs((int)(lnum - curwin->w_cursor.lnum))
+ < abs((int)(longest_lnum - curwin->w_cursor.lnum)))
+ longest_lnum = lnum;
+ }
+ }
+ else
+ /* Use cursor line only. */
+ max = scroll_line_len(curwin->w_cursor.lnum);
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_active())
+ {
+ /* May move the cursor even further to the right. */
+ if (curwin->w_virtcol >= (colnr_T)max)
+ max = curwin->w_virtcol;
+ }
+#endif
+
+#ifndef SCROLL_PAST_END
+ max += W_WIDTH(curwin) - 1;
+#endif
+ /* The line number isn't scrolled, thus there is less space when
+ * 'number' is set (also for 'foldcolumn'). */
+ size -= curwin_col_off();
+#ifndef SCROLL_PAST_END
+ max -= curwin_col_off();
+#endif
+ }
+
+#ifndef SCROLL_PAST_END
+ if (value > max - size + 1)
+ value = max - size + 1; /* limit the value to allowable range */
+#endif
+
+#ifdef FEAT_RIGHTLEFT
+ if (curwin->w_p_rl)
+ {
+ value = max + 1 - size - value;
+ if (value < 0)
+ {
+ size += value;
+ value = 0;
+ }
+ }
+#endif
+ if (!force && value == gui.bottom_sbar.value && size == gui.bottom_sbar.size
+ && max == gui.bottom_sbar.max)
+ return;
+
+ gui.bottom_sbar.value = value;
+ gui.bottom_sbar.size = size;
+ gui.bottom_sbar.max = max;
+ gui.prev_wrap = curwin->w_p_wrap;
+
+ gui_mch_set_scrollbar_thumb(&gui.bottom_sbar, value, size, max);
+}
+
+/*
+ * Do a horizontal scroll. Return TRUE if the cursor moved, FALSE otherwise.
+ */
+ int
+gui_do_horiz_scroll()
+{
+ /* no wrapping, no scrolling */
+ if (curwin->w_p_wrap)
+ return FALSE;
+
+ if (curwin->w_leftcol == scrollbar_value)
+ return FALSE;
+
+ curwin->w_leftcol = scrollbar_value;
+
+ /* When the line of the cursor is too short, move the cursor to the
+ * longest visible line. Do a sanity check on "longest_lnum", just in
+ * case. */
+ if (vim_strchr(p_go, GO_HORSCROLL) == NULL
+ && longest_lnum >= curwin->w_topline
+ && longest_lnum < curwin->w_botline
+ && !virtual_active())
+ {
+ if (scrollbar_value > scroll_line_len(curwin->w_cursor.lnum))
+ {
+ curwin->w_cursor.lnum = longest_lnum;
+ curwin->w_cursor.col = 0;
+ }
+ }
+
+ return leftcol_changed();
+}
+
+/*
+ * Check that none of the colors are the same as the background color
+ */
+ void
+gui_check_colors()
+{
+ if (gui.norm_pixel == gui.back_pixel || gui.norm_pixel == INVALCOLOR)
+ {
+ gui_set_bg_color((char_u *)"White");
+ if (gui.norm_pixel == gui.back_pixel || gui.norm_pixel == INVALCOLOR)
+ gui_set_fg_color((char_u *)"Black");
+ }
+}
+
+ void
+gui_set_fg_color(name)
+ char_u *name;
+{
+ gui.norm_pixel = gui_get_color(name);
+ hl_set_fg_color_name(vim_strsave(name));
+}
+
+ void
+gui_set_bg_color(name)
+ char_u *name;
+{
+ gui.back_pixel = gui_get_color(name);
+ hl_set_bg_color_name(vim_strsave(name));
+}
+
+/*
+ * Allocate a color by name.
+ * Returns INVALCOLOR and gives an error message when failed.
+ */
+ guicolor_T
+gui_get_color(name)
+ char_u *name;
+{
+ guicolor_T t;
+
+ if (*name == NUL)
+ return INVALCOLOR;
+ t = gui_mch_get_color(name);
+ if (t == INVALCOLOR
+#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
+ && gui.in_use
+#endif
+ )
+ EMSG2(_("E254: Cannot allocate color %s"), name);
+ return t;
+}
+
+/*
+ * Return the grey value of a color (range 0-255).
+ */
+ int
+gui_get_lightness(pixel)
+ guicolor_T pixel;
+{
+ long_u rgb = gui_mch_get_rgb(pixel);
+
+ return ( (((rgb >> 16) & 0xff) * 299)
+ + (((rgb >> 8) & 0xff) * 587)
+ + ((rgb & 0xff) * 114)) / 1000;
+}
+
+#if defined(FEAT_GUI_X11) || defined(PROTO)
+ void
+gui_new_scrollbar_colors()
+{
+ win_T *wp;
+
+ /* Nothing to do if GUI hasn't started yet. */
+ if (!gui.in_use)
+ return;
+
+ FOR_ALL_WINDOWS(wp)
+ {
+ gui_mch_set_scrollbar_colors(&(wp->w_scrollbars[SBAR_LEFT]));
+ gui_mch_set_scrollbar_colors(&(wp->w_scrollbars[SBAR_RIGHT]));
+ }
+ gui_mch_set_scrollbar_colors(&gui.bottom_sbar);
+}
+#endif
+
+/*
+ * Call this when focus has changed.
+ */
+ void
+gui_focus_change(in_focus)
+ int in_focus;
+{
+/*
+ * Skip this code to avoid drawing the cursor when debugging and switching
+ * between the debugger window and gvim.
+ */
+#if 1
+ gui.in_focus = in_focus;
+ out_flush(); /* make sure output has been written */
+ gui_update_cursor(TRUE, FALSE);
+
+# ifdef FEAT_XIM
+ xim_set_focus(in_focus);
+# endif
+
+ ui_focus_change(in_focus);
+#endif
+}
+
+/*
+ * Called when the mouse moved (but not when dragging).
+ */
+ void
+gui_mouse_moved(x, y)
+ int x;
+ int y;
+{
+ win_T *wp;
+ char_u st[6];
+
+#ifdef FEAT_MOUSESHAPE
+ /* Get window pointer, and update mouse shape as well. */
+ wp = xy2win(x, y);
+#endif
+
+ /* Only handle this when 'mousefocus' set and ... */
+ if (p_mousef
+ && !hold_gui_events /* not holding events */
+ && (State & (NORMAL|INSERT))/* Normal/Visual/Insert mode */
+ && State != HITRETURN /* but not hit-return prompt */
+ && msg_scrolled == 0 /* no scrolled message */
+ && !need_mouse_correct /* not moving the pointer */
+ && gui.in_focus) /* gvim in focus */
+ {
+ /* Don't move the mouse when it's left or right of the Vim window */
+ if (x < 0 || x > Columns * gui.char_width)
+ return;
+#ifndef FEAT_MOUSESHAPE
+ wp = xy2win(x, y);
+#endif
+ if (wp == curwin || wp == NULL)
+ return; /* still in the same old window, or none at all */
+
+ /*
+ * format a mouse click on status line input
+ * ala gui_send_mouse_event(0, x, y, 0, 0);
+ * Trick: Use a column of -1, so that check_termcode will generate a
+ * K_LEFTMOUSE_NM key code.
+ */
+ if (finish_op)
+ {
+ /* abort the current operator first */
+ st[0] = ESC;
+ add_to_input_buf(st, 1);
+ }
+ st[0] = CSI;
+ st[1] = KS_MOUSE;
+ st[2] = KE_FILLER;
+ st[3] = (char_u)MOUSE_LEFT;
+ fill_mouse_coord(st + 4,
+#ifdef FEAT_VERTSPLIT
+ W_WINCOL(wp),
+#else
+ -1,
+#endif
+ wp->w_height + W_WINROW(wp));
+
+ add_to_input_buf(st, 8);
+ st[3] = (char_u)MOUSE_RELEASE;
+ add_to_input_buf(st, 8);
+
+#ifdef FEAT_GUI_GTK
+ /* Need to wake up the main loop */
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+#endif
+ }
+}
+
+/*
+ * Called when mouse should be moved to window with focus.
+ */
+ void
+gui_mouse_correct()
+{
+ int x, y;
+ win_T *wp = NULL;
+
+ need_mouse_correct = FALSE;
+ if (gui.in_use && p_mousef)
+ {
+ x = gui_mch_get_mouse_x();
+ /* Don't move the mouse when it's left or right of the Vim window */
+ if (x < 0 || x > Columns * gui.char_width)
+ return;
+ y = gui_mch_get_mouse_y();
+ if (y >= 0)
+ wp = xy2win(x, y);
+ if (wp != curwin && wp != NULL) /* If in other than current window */
+ {
+ validate_cline_row();
+ gui_mch_setmouse((int)W_ENDCOL(curwin) * gui.char_width - 3,
+ (W_WINROW(curwin) + curwin->w_wrow) * gui.char_height
+ + (gui.char_height) / 2);
+ }
+ }
+}
+
+/*
+ * Find window where the mouse pointer "y" coordinate is in.
+ */
+/*ARGSUSED*/
+ static win_T *
+xy2win(x, y)
+ int x;
+ int y;
+{
+#ifdef FEAT_WINDOWS
+ int row;
+ int col;
+ win_T *wp;
+
+ row = Y_2_ROW(y);
+ col = X_2_COL(x);
+ if (row < 0 || col < 0) /* before first window */
+ return NULL;
+ wp = mouse_find_win(&row, &col);
+# ifdef FEAT_MOUSESHAPE
+ if (State == HITRETURN || State == ASKMORE)
+ {
+ if (Y_2_ROW(y) >= msg_row)
+ update_mouseshape(SHAPE_IDX_MOREL);
+ else
+ update_mouseshape(SHAPE_IDX_MORE);
+ }
+ else if (row > wp->w_height) /* below status line */
+ update_mouseshape(SHAPE_IDX_CLINE);
+# ifdef FEAT_VERTSPLIT
+ else if (!(State & CMDLINE) && W_VSEP_WIDTH(wp) > 0 && col == wp->w_width
+ && (row != wp->w_height || !stl_connected(wp)))
+ update_mouseshape(SHAPE_IDX_VSEP);
+# endif
+ else if (!(State & CMDLINE) && W_STATUS_HEIGHT(wp) > 0
+ && row == wp->w_height)
+ update_mouseshape(SHAPE_IDX_STATUS);
+ else
+ update_mouseshape(-2);
+# endif
+ return wp;
+#else
+ return firstwin;
+#endif
+}
+
+/*
+ * ":gui" and ":gvim": Change from the terminal version to the GUI version.
+ * File names may be given to redefine the args list.
+ */
+ void
+ex_gui(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+
+ /*
+ * Check for "-f" argument: foreground, don't fork.
+ * Also don't fork when started with "gvim -f".
+ * Do fork when using "gui -b".
+ */
+ if (arg[0] == '-'
+ && (arg[1] == 'f' || arg[1] == 'b')
+ && (arg[2] == NUL || vim_iswhite(arg[2])))
+ {
+ gui.dofork = (arg[1] == 'b');
+ eap->arg = skipwhite(eap->arg + 2);
+ }
+ if (!gui.in_use)
+ {
+ /* Clear the command. Needed for when forking+exiting, to avoid part
+ * of the argument ending up after the shell prompt. */
+ msg_clr_eos_force();
+ gui_start();
+ }
+ if (!ends_excmd(*eap->arg))
+ ex_next(eap);
+}
+
+#if ((defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32) \
+ || defined(FEAT_GUI_PHOTON)) && defined(FEAT_TOOLBAR)) || defined(PROTO)
+/*
+ * This is shared between Athena, Motif and GTK.
+ */
+static char_u *gfp_buffer;
+
+static void gfp_setname __ARGS((char_u *fname));
+
+/*
+ * Callback function for do_in_runtimepath().
+ */
+ static void
+gfp_setname(fname)
+ char_u *fname;
+{
+ if (STRLEN(fname) >= MAXPATHL)
+ *gfp_buffer = NUL;
+ else
+ STRCPY(gfp_buffer, fname);
+}
+
+/*
+ * Find the path of bitmap "name" with extension "ext" in 'runtimepath'.
+ * Return FAIL for failure and OK if buffer[MAXPATHL] contains the result.
+ */
+ int
+gui_find_bitmap(name, buffer, ext)
+ char_u *name;
+ char_u *buffer;
+ char *ext;
+{
+ if (STRLEN(name) > MAXPATHL - 14)
+ return FAIL;
+ sprintf((char *)buffer, "bitmaps/%s.%s", name, ext);
+ gfp_buffer = buffer;
+ if (do_in_runtimepath(buffer, FALSE, gfp_setname) == FAIL || *buffer == NUL)
+ return FAIL;
+ return OK;
+}
+
+# if !defined(HAVE_GTK2) || defined(PROTO)
+/*
+ * Given the name of the "icon=" argument, try finding the bitmap file for the
+ * icon. If it is an absolute path name, use it as it is. Otherwise append
+ * "ext" and search for it in 'runtimepath'.
+ * The result is put in "buffer[MAXPATHL]". If something fails "buffer"
+ * contains "name".
+ */
+ void
+gui_find_iconfile(name, buffer, ext)
+ char_u *name;
+ char_u *buffer;
+ char *ext;
+{
+ char_u buf[MAXPATHL + 1];
+
+ expand_env(name, buffer, MAXPATHL);
+ if (!mch_isFullName(buffer) && gui_find_bitmap(buffer, buf, ext) == OK)
+ STRCPY(buffer, buf);
+}
+# endif
+#endif
+
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11) || defined(PROTO)
+ void
+display_errors()
+{
+ char_u *p;
+
+ if (isatty(2))
+ fflush(stderr);
+ else if (error_ga.ga_data != NULL)
+ {
+ /* avoid putting up a message box with blanks only */
+ for (p = (char_u *)error_ga.ga_data; *p != NUL; ++p)
+ if (!isspace(*p))
+ {
+ /* Truncate a very long message, it will go off-screen. */
+ if (STRLEN(p) > 2000)
+ STRCPY(p + 2000 - 14, "...(truncated)");
+ (void)do_dialog(VIM_ERROR, (char_u *)_("Error"),
+ p, (char_u *)_("&Ok"), 1, NULL);
+ break;
+ }
+ ga_clear(&error_ga);
+ }
+}
+#endif
+
+#if defined(NO_CONSOLE_INPUT) || defined(PROTO)
+/*
+ * Return TRUE if still starting up and there is no place to enter text.
+ * For GTK and X11 we check if stderr is not a tty, which means we were
+ * (probably) started from the desktop. Also check stdin, "vim >& file" does
+ * allow typing on stdin.
+ */
+ int
+no_console_input()
+{
+ return ((!gui.in_use || gui.starting)
+# ifndef NO_CONSOLE
+ && !isatty(0) && !isatty(2)
+# endif
+ );
+}
+#endif
+
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MOTIF) \
+ || defined(MSWIN_FIND_REPLACE) || defined(FEAT_SUN_WORKSHOP) \
+ || defined(PROTO)
+/*
+ * Update the current window and the screen.
+ */
+ void
+gui_update_screen()
+{
+ update_topline();
+ validate_cursor();
+ update_screen(0); /* may need to update the screen */
+ setcursor();
+ out_flush(); /* make sure output has been written */
+ gui_update_cursor(TRUE, FALSE);
+ gui_mch_flush();
+}
+#endif
+
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MOTIF) \
+ || defined(MSWIN_FIND_REPLACE) || defined(PROTO)
+static void concat_esc __ARGS((garray_T *gap, char_u *text, int what));
+
+/*
+ * Get the text to use in a find/replace dialog. Uses the last search pattern
+ * if the argument is empty.
+ * Returns an allocated string.
+ */
+ char_u *
+get_find_dialog_text(arg, wwordp, mcasep)
+ char_u *arg;
+ int *wwordp; /* return: TRUE if \< \> found */
+ int *mcasep; /* return: TRUE if \C found */
+{
+ char_u *text;
+
+ if (*arg == NUL)
+ text = last_search_pat();
+ else
+ text = arg;
+ if (text != NULL)
+ {
+ text = vim_strsave(text);
+ if (text != NULL)
+ {
+ int len = STRLEN(text);
+ int i;
+
+ /* Remove "\V" */
+ if (len >= 2 && STRNCMP(text, "\\V", 2) == 0)
+ {
+ mch_memmove(text, text + 2, (size_t)(len - 1));
+ len -= 2;
+ }
+
+ /* Recognize "\c" and "\C" and remove. */
+ if (len >= 2 && *text == '\\' && (text[1] == 'c' || text[1] == 'C'))
+ {
+ *mcasep = (text[1] == 'C');
+ mch_memmove(text, text + 2, (size_t)(len - 1));
+ len -= 2;
+ }
+
+ /* Recognize "\<text\>" and remove. */
+ if (len >= 4
+ && STRNCMP(text, "\\<", 2) == 0
+ && STRNCMP(text + len - 2, "\\>", 2) == 0)
+ {
+ *wwordp = TRUE;
+ mch_memmove(text, text + 2, (size_t)(len - 4));
+ text[len - 4] = NUL;
+ }
+
+ /* Recognize "\/" or "\?" and remove. */
+ for (i = 0; i + 1 < len; ++i)
+ if (text[i] == '\\' && (text[i + 1] == '/'
+ || text[i + 1] == '?'))
+ {
+ mch_memmove(text + i, text + i + 1, (size_t)(len - i));
+ --len;
+ }
+ }
+ }
+ return text;
+}
+
+/*
+ * Concatenate "text" to grow array "gap", escaping "what" with a backslash.
+ */
+ static void
+concat_esc(gap, text, what)
+ garray_T *gap;
+ char_u *text;
+ int what;
+{
+ while (*text != NUL)
+ {
+#ifdef FEAT_MBYTE
+ int l = (*mb_ptr2len_check)(text);
+ if (l > 1)
+ {
+ while (--l >= 0)
+ ga_append(gap, *text++);
+ continue;
+ }
+#endif
+ if (*text == what)
+ ga_append(gap, '\\');
+ ga_append(gap, *text);
+ ++text;
+ }
+}
+
+/*
+ * Handle the press of a button in the find-replace dialog.
+ * Return TRUE when something was added to the input buffer.
+ */
+ int
+gui_do_findrepl(flags, find_text, repl_text, down)
+ int flags; /* one of FRD_REPLACE, FRD_FINDNEXT, etc. */
+ char_u *find_text;
+ char_u *repl_text;
+ int down; /* Search downwards. */
+{
+ garray_T ga;
+ int i;
+ int type = (flags & FRD_TYPE_MASK);
+ char_u *p;
+
+ ga_init2(&ga, 1, 100);
+
+ if (type == FRD_REPLACE)
+ {
+ /* Do the replacement when the text under the cursor matches. */
+ i = STRLEN(find_text);
+ p = ml_get_cursor();
+ if (((flags & FRD_MATCH_CASE)
+ ? STRNCMP(p, find_text, i) == 0
+ : STRNICMP(p, find_text, i) == 0)
+ && u_save_cursor() == OK)
+ {
+ /* A button was pressed thus undo should be synced. */
+ if (no_u_sync == 0)
+ u_sync();
+
+ del_bytes((long)i, FALSE);
+ ins_str(repl_text);
+ }
+ }
+ else if (type == FRD_REPLACEALL)
+ ga_concat(&ga, (char_u *)"%s/");
+
+ ga_concat(&ga, (char_u *)"\\V");
+ if (flags & FRD_MATCH_CASE)
+ ga_concat(&ga, (char_u *)"\\C");
+ else
+ ga_concat(&ga, (char_u *)"\\c");
+ if (flags & FRD_WHOLE_WORD)
+ ga_concat(&ga, (char_u *)"\\<");
+ if (type == FRD_REPLACEALL || down)
+ concat_esc(&ga, find_text, '/'); /* escape slashes */
+ else
+ concat_esc(&ga, find_text, '?'); /* escape '?' */
+ if (flags & FRD_WHOLE_WORD)
+ ga_concat(&ga, (char_u *)"\\>");
+
+ if (type == FRD_REPLACEALL)
+ {
+ /* A button was pressed, thus undo should be synced. */
+ if (no_u_sync == 0)
+ u_sync();
+
+ ga_concat(&ga, (char_u *)"/");
+ concat_esc(&ga, repl_text, '/'); /* escape slashes */
+ ga_concat(&ga, (char_u *)"/g");
+ do_cmdline_cmd(ga.ga_data);
+ }
+ else
+ {
+ /* Search for the next match. */
+ i = msg_scroll;
+ do_search(NULL, down ? '/' : '?', ga.ga_data, 1L,
+ SEARCH_MSG + SEARCH_MARK);
+ msg_scroll = i; /* don't let an error message set msg_scroll */
+ }
+
+ if (State & (NORMAL | INSERT))
+ {
+ gui_update_screen(); /* update the screen */
+ msg_didout = 0; /* overwrite any message */
+ need_wait_return = FALSE; /* don't wait for return */
+ }
+
+ vim_free(ga.ga_data);
+ return (ga.ga_len > 0);
+}
+
+#endif
+
+#if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
+ || defined(FEAT_GUI_MSWIN) \
+ || defined(FEAT_GUI_MAC) \
+ || defined(PROTO)
+
+#ifdef FEAT_WINDOWS
+static void gui_wingoto_xy __ARGS((int x, int y));
+
+/*
+ * Jump to the window at specified point (x, y).
+ */
+ static void
+gui_wingoto_xy(x, y)
+ int x;
+ int y;
+{
+ int row = Y_2_ROW(y);
+ int col = X_2_COL(x);
+ win_T *wp;
+
+ if (row >= 0 && col >= 0)
+ {
+ wp = mouse_find_win(&row, &col);
+ if (wp != NULL && wp != curwin)
+ win_goto(wp);
+ }
+}
+#endif
+
+/*
+ * Process file drop. Mouse cursor position, key modifiers, name of files
+ * and count of files are given. Argument "fnames[count]" has full pathnames
+ * of dropped files, they will be freed in this function, and caller can't use
+ * fnames after call this function.
+ */
+/*ARGSUSED*/
+ void
+gui_handle_drop(x, y, modifiers, fnames, count)
+ int x;
+ int y;
+ int_u modifiers;
+ char_u **fnames;
+ int count;
+{
+ int i;
+ char_u *p;
+
+ /*
+ * When the cursor is at the command line, add the file names to the
+ * command line, don't edit the files.
+ */
+ if (State & CMDLINE)
+ {
+ shorten_filenames(fnames, count);
+ for (i = 0; i < count; ++i)
+ {
+ if (fnames[i] != NULL)
+ {
+ if (i > 0)
+ add_to_input_buf((char_u*)" ", 1);
+
+ /* We don't know what command is used thus we can't be sure
+ * about which characters need to be escaped. Only escape the
+ * most common ones. */
+# ifdef BACKSLASH_IN_FILENAME
+ p = vim_strsave_escaped(fnames[i], (char_u *)" \t\"|");
+# else
+ p = vim_strsave_escaped(fnames[i], (char_u *)"\\ \t\"|");
+# endif
+ if (p != NULL)
+ add_to_input_buf(p, (int)STRLEN(p));
+ vim_free(p);
+ vim_free(fnames[i]);
+ }
+ }
+ vim_free(fnames);
+ }
+ else
+ {
+ /* Go to the window under mouse cursor, then shorten given "fnames" by
+ * current window, because a window can have local current dir. */
+# ifdef FEAT_WINDOWS
+ gui_wingoto_xy(x, y);
+# endif
+ shorten_filenames(fnames, count);
+
+ /* If Shift held down, remember the first item. */
+ if ((modifiers & MOUSE_SHIFT) != 0)
+ p = vim_strsave(fnames[0]);
+ else
+ p = NULL;
+
+ /* Handle the drop, :edit or :split to get to the file. This also
+ * frees fnames[]. Skip this if there is only one item it's a
+ * directory and Shift is held down. */
+ if (count == 1 && (modifiers & MOUSE_SHIFT) != 0
+ && mch_isdir(fnames[0]))
+ {
+ vim_free(fnames[0]);
+ vim_free(fnames);
+ }
+ else
+ handle_drop(count, fnames, (modifiers & MOUSE_CTRL) != 0);
+
+ /* If Shift held down, change to first file's directory. If the first
+ * item is a directory, change to that directory (and let the explorer
+ * plugin show the contents). */
+ if (p != NULL)
+ {
+ if (mch_isdir(p))
+ {
+ if (mch_chdir((char *)p) == 0)
+ shorten_fnames(TRUE);
+ }
+ else if (vim_chdirfile(p) == OK)
+ shorten_fnames(TRUE);
+ vim_free(p);
+ }
+
+ /* Update the screen display */
+ update_screen(NOT_VALID);
+# ifdef FEAT_MENU
+ gui_update_menus(0);
+# endif
+ setcursor();
+ out_flush();
+ gui_update_cursor(FALSE, FALSE);
+ gui_mch_flush();
+ }
+}
+#endif
diff --git a/src/gui.h b/src/gui.h
new file mode 100644
index 000000000..4357c46aa
--- /dev/null
+++ b/src/gui.h
@@ -0,0 +1,525 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Motif support by Robert Webb
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/* For debugging */
+/* #define D(x) printf x; */
+#define D(x)
+
+#if defined(FEAT_GUI_AMIGA)
+# include <intuition/intuition.h>
+#endif
+
+#ifdef FEAT_GUI_MOTIF
+# define FEAT_GUI_X11
+# include <Xm/Xm.h>
+#endif
+
+#ifdef FEAT_GUI_ATHENA
+# define FEAT_GUI_X11
+# include <X11/Intrinsic.h>
+# include <X11/StringDefs.h>
+#endif
+
+#ifdef FEAT_BEVAL
+# include "gui_beval.h"
+#endif
+
+#ifdef FEAT_GUI_GTK
+# include <X11/Intrinsic.h>
+# include <gtk/gtk.h>
+#endif
+
+#ifdef FEAT_GUI_BEOS
+# include "gui_beos.h"
+#endif
+
+#ifdef FEAT_GUI_MAC
+# include <Types.h>
+/*# include <Memory.h>*/
+# include <Quickdraw.h>
+# include <Fonts.h>
+# include <Events.h>
+# include <Menus.h>
+# if !(defined (TARGET_API_MAC_CARBON) && (TARGET_API_MAC_CARBON))
+# include <Windows.h>
+# endif
+# include <Controls.h>
+/*# include <TextEdit.h>*/
+# include <Dialogs.h>
+# include <OSUtils.h>
+/*
+# include <ToolUtils.h>
+# include <SegLoad.h>*/
+#endif
+
+#ifdef RISCOS
+# include "gui_riscos.h"
+#endif
+
+#ifdef FEAT_GUI_PHOTON
+# include <Ph.h>
+# include <Pt.h>
+# include "photon/PxProto.h"
+#endif
+
+/*
+ * On some systems, when we compile with the GUI, we always use it. On Mac
+ * there is no terminal version, and on Windows we can't figure out how to
+ * fork one off with :gui.
+ */
+#if defined(FEAT_GUI_MSWIN) || (defined(FEAT_GUI_MAC) && !defined(MACOS_X_UNIX))
+# define ALWAYS_USE_GUI
+#endif
+
+#if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MAC) || defined(HAVE_GTK2)
+# define USE_ON_FLY_SCROLL
+#endif
+
+/*
+ * GUIs that support dropping files on a running Vim.
+ */
+#if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MAC) \
+ || defined(FEAT_GUI_BEOS) || defined(FEAT_GUI_GTK)
+# define HAVE_DROP_FILE
+#endif
+
+/*
+ * This define makes menus always use a fontset.
+ * We're not sure if this code always works, thus it can be disabled.
+ */
+#ifdef FEAT_XFONTSET
+# define FONTSET_ALWAYS
+#endif
+
+/*
+ * These macros convert between character row/column and pixel coordinates.
+ * TEXT_X - Convert character column into X pixel coord for drawing strings.
+ * TEXT_Y - Convert character row into Y pixel coord for drawing strings.
+ * FILL_X - Convert character column into X pixel coord for filling the area
+ * under the character.
+ * FILL_Y - Convert character row into Y pixel coord for filling the area
+ * under the character.
+ * X_2_COL - Convert X pixel coord into character column.
+ * Y_2_ROW - Convert Y pixel coord into character row.
+ */
+#ifdef FEAT_GUI_W32
+# define TEXT_X(col) ((col) * gui.char_width)
+# define TEXT_Y(row) ((row) * gui.char_height + gui.char_ascent)
+# define FILL_X(col) ((col) * gui.char_width)
+# define FILL_Y(row) ((row) * gui.char_height)
+# define X_2_COL(x) ((x) / gui.char_width)
+# define Y_2_ROW(y) ((y) / gui.char_height)
+#else
+# define TEXT_X(col) ((col) * gui.char_width + gui.border_offset)
+# define FILL_X(col) ((col) * gui.char_width + gui.border_offset)
+# define X_2_COL(x) (((x) - gui.border_offset) / gui.char_width)
+# define TEXT_Y(row) ((row) * gui.char_height + gui.char_ascent \
+ + gui.border_offset)
+# define FILL_Y(row) ((row) * gui.char_height + gui.border_offset)
+# define Y_2_ROW(y) (((y) - gui.border_offset) / gui.char_height)
+#endif
+
+/* Indices for arrays of scrollbars */
+#define SBAR_NONE -1
+#define SBAR_LEFT 0
+#define SBAR_RIGHT 1
+#define SBAR_BOTTOM 2
+
+/* Orientations for scrollbars */
+#define SBAR_VERT 0
+#define SBAR_HORIZ 1
+
+/* Default size of scrollbar */
+#define SB_DEFAULT_WIDTH 16
+
+/* Default height of the menu bar */
+#define MENU_DEFAULT_HEIGHT 1 /* figure it out at runtime */
+
+/* Flags for gui_mch_outstr_nowrap() */
+#define GUI_MON_WRAP_CURSOR 0x01 /* wrap cursor at end of line */
+#define GUI_MON_INVERT 0x02 /* invert the characters */
+#define GUI_MON_IS_CURSOR 0x04 /* drawing cursor */
+#define GUI_MON_TRS_CURSOR 0x08 /* drawing transparent cursor */
+#define GUI_MON_NOCLEAR 0x10 /* don't clear selection */
+
+/* Flags for gui_mch_draw_string() */
+#define DRAW_TRANSP 0x01 /* draw with transparant bg */
+#define DRAW_BOLD 0x02 /* draw bold text */
+#define DRAW_UNDERL 0x04 /* draw underline text */
+#if defined(RISCOS) || defined(HAVE_GTK2)
+# define DRAW_ITALIC 0x08 /* draw italic text */
+#endif
+#define DRAW_CURSOR 0x10 /* drawing block cursor (win32) */
+
+/* For our own tearoff menu item */
+#define TEAR_STRING "-->Detach"
+#define TEAR_LEN (9) /* length of above string */
+
+/* for the toolbar */
+#ifdef FEAT_GUI_W16
+# define TOOLBAR_BUTTON_HEIGHT 15
+# define TOOLBAR_BUTTON_WIDTH 16
+#else
+# define TOOLBAR_BUTTON_HEIGHT 18
+# define TOOLBAR_BUTTON_WIDTH 18
+#endif
+#define TOOLBAR_BORDER_HEIGHT 12 /* room above+below buttons for MSWindows */
+
+#if defined(NO_CONSOLE) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11)
+# define NO_CONSOLE_INPUT /* use no_console_input() to check if there
+ is no console input possible */
+#endif
+
+typedef struct GuiScrollbar
+{
+ long ident; /* Unique identifier for each scrollbar */
+ struct window *wp; /* Scrollbar's window, NULL for bottom */
+ int type; /* one of SBAR_{LEFT,RIGHT,BOTTOM} */
+ long value; /* Represents top line number visible */
+#ifdef FEAT_GUI_ATHENA
+ int pixval; /* pixel count of value */
+#endif
+ long size; /* Size of scrollbar thumb */
+ long max; /* Number of lines in buffer */
+
+ /* Values measured in characters: */
+ int top; /* Top of scroll bar (chars from row 0) */
+ int height; /* Current height of scroll bar in rows */
+#ifdef FEAT_VERTSPLIT
+ int width; /* Current width of scroll bar in cols */
+#endif
+ int status_height; /* Height of status line */
+#ifdef FEAT_GUI_X11
+ Widget id; /* Id of real scroll bar */
+#endif
+#ifdef FEAT_GUI_GTK
+ GtkWidget *id; /* Id of real scroll bar */
+ unsigned long handler_id; /* Id of "value_changed" signal handler */
+#endif
+
+#ifdef FEAT_GUI_MSWIN
+ HWND id; /* Id of real scroll bar */
+ int scroll_shift; /* The scrollbar stuff can handle only up to
+ 32767 lines. When the file is longer,
+ scroll_shift is set to the number of shifts
+ to reduce the count. */
+#endif
+#if FEAT_GUI_BEOS
+ VimScrollBar *id; /* Pointer to real scroll bar */
+#endif
+#ifdef FEAT_GUI_MAC
+ ControlHandle id; /* A handle to the scrollbar */
+#endif
+#ifdef RISCOS
+ int id; /* Window handle of scrollbar window */
+#endif
+#ifdef FEAT_GUI_PHOTON
+ PtWidget_t *id;
+#endif
+} scrollbar_T;
+
+typedef long guicolor_T; /* handle for a GUI color; for X11 this should
+ be "Pixel", but that's an unsigned and we
+ need a signed value */
+#define INVALCOLOR (guicolor_T)-11111 /* number for invalid color; on 32 bit
+ displays there is a tiny chance this is an
+ actual color */
+
+#ifdef FEAT_GUI_GTK
+# ifdef HAVE_GTK2
+ typedef PangoFontDescription *GuiFont; /* handle for a GUI font */
+ typedef PangoFontDescription *GuiFontset; /* handle for a GUI fontset */
+# else
+ typedef GdkFont *GuiFont; /* handle for a GUI font */
+ typedef GdkFont *GuiFontset; /* handle for a GUI fontset */
+# endif
+# define NOFONT (GuiFont)NULL
+# define NOFONTSET (GuiFontset)NULL
+#else
+# ifdef FEAT_GUI_PHOTON
+ typedef char *GuiFont;
+ typedef char *GuiFontset;
+# define NOFONT (GuiFont)NULL
+# define NOFONTSET (GuiFontset)NULL
+# else
+# ifdef FEAT_GUI_X11
+ typedef XFontStruct *GuiFont; /* handle for a GUI font */
+ typedef XFontSet GuiFontset; /* handle for a GUI fontset */
+# define NOFONT (GuiFont)0
+# define NOFONTSET (GuiFontset)0
+# else
+ typedef long_u GuiFont; /* handle for a GUI font */
+ typedef long_u GuiFontset; /* handle for a GUI fontset */
+# define NOFONT (GuiFont)0
+# define NOFONTSET (GuiFontset)0
+# endif
+# endif
+#endif
+
+typedef struct Gui
+{
+ int in_focus; /* Vim has input focus */
+ int in_use; /* Is the GUI being used? */
+ int starting; /* GUI will start in a little while */
+ int shell_created; /* Has the shell been created yet? */
+ int dying; /* Is vim dying? Then output to terminal */
+ int dofork; /* Use fork() when GUI is starting */
+ int dragged_sb; /* Which scrollbar being dragged, if any? */
+ win_T *dragged_wp; /* Which WIN's sb being dragged, if any? */
+ int pointer_hidden; /* Is the mouse pointer hidden? */
+ int col; /* Current cursor column in GUI display */
+ int row; /* Current cursor row in GUI display */
+ int cursor_col; /* Physical cursor column in GUI display */
+ int cursor_row; /* Physical cursor row in GUI display */
+ char cursor_is_valid; /* There is a cursor at cursor_row/col */
+ int num_cols; /* Number of columns */
+ int num_rows; /* Number of rows */
+ int scroll_region_top; /* Top (first) line of scroll region */
+ int scroll_region_bot; /* Bottom (last) line of scroll region */
+ int scroll_region_left; /* Left (first) column of scroll region */
+ int scroll_region_right; /* Right (last) col. of scroll region */
+ int highlight_mask; /* Highlight attribute mask */
+ int scrollbar_width; /* Width of vertical scrollbars */
+ int scrollbar_height; /* Height of horizontal scrollbar */
+ int left_sbar_x; /* Calculated x coord for left scrollbar */
+ int right_sbar_x; /* Calculated x coord for right scrollbar */
+
+#ifdef FEAT_MENU
+# ifndef FEAT_GUI_GTK
+ int menu_height; /* Height of the menu bar */
+ int menu_width; /* Width of the menu bar */
+# endif
+ char menu_is_active; /* TRUE if menu is present */
+# ifdef FEAT_GUI_ATHENA
+ char menu_height_fixed; /* TRUE if menu height fixed */
+# endif
+#endif
+
+ scrollbar_T bottom_sbar; /* Bottom scrollbar */
+ int which_scrollbars[3];/* Which scrollbar boxes are active? */
+ int prev_wrap; /* For updating the horizontal scrollbar */
+ int char_width; /* Width of char in pixels */
+ int char_height; /* Height of char in pixels + 'linespace' */
+ int char_ascent; /* Ascent of char in pixels */
+ int border_width; /* Width of our border around text area */
+ int border_offset; /* Total pixel offset for all borders */
+
+ GuiFont norm_font; /* Normal font */
+#ifndef HAVE_GTK2
+ GuiFont bold_font; /* Bold font */
+ GuiFont ital_font; /* Italic font */
+ GuiFont boldital_font; /* Bold-Italic font */
+#else
+ int font_can_bold; /* Whether norm_font supports bold weight.
+ * The styled font variants are not used. */
+#endif
+
+#if defined(FEAT_MENU) && !defined(HAVE_GTK2)
+# ifdef FONTSET_ALWAYS
+ GuiFontset menu_fontset; /* set of fonts for multi-byte chars */
+# else
+ GuiFont menu_font; /* menu item font */
+# endif
+#endif
+#ifdef FEAT_MBYTE
+ GuiFont wide_font; /* 'guifontwide' font */
+#endif
+#ifdef FEAT_XFONTSET
+ GuiFontset fontset; /* set of fonts for multi-byte chars */
+#endif
+ guicolor_T back_pixel; /* Color of background */
+ guicolor_T norm_pixel; /* Color of normal text */
+ guicolor_T def_back_pixel; /* default Color of background */
+ guicolor_T def_norm_pixel; /* default Color of normal text */
+
+#ifdef FEAT_GUI_X11
+ char *rsrc_menu_fg_name; /* Color of menu and dialog foregound */
+ guicolor_T menu_fg_pixel; /* Same in Pixel format */
+ char *rsrc_menu_bg_name; /* Color of menu and dialog backgound */
+ guicolor_T menu_bg_pixel; /* Same in Pixel format */
+ char *rsrc_scroll_fg_name; /* Color of scrollbar foreground */
+ guicolor_T scroll_fg_pixel; /* Same in Pixel format */
+ char *rsrc_scroll_bg_name; /* Color of scrollbar background */
+ guicolor_T scroll_bg_pixel; /* Same in Pixel format */
+
+# ifdef FEAT_GUI_MOTIF
+ guicolor_T menu_def_fg_pixel; /* Default menu foreground */
+ guicolor_T menu_def_bg_pixel; /* Default menu background */
+ guicolor_T scroll_def_fg_pixel; /* Default scrollbar foreground */
+ guicolor_T scroll_def_bg_pixel; /* Default scrollbar background */
+# endif
+ Display *dpy; /* X display */
+ Window wid; /* Window id of text area */
+ int visibility; /* Is shell partially/fully obscured? */
+ GC text_gc;
+ GC back_gc;
+ GC invert_gc;
+ Cursor blank_pointer; /* Blank pointer */
+
+ /* X Resources */
+ char_u *rsrc_font_name; /* Resource font name, used if 'guifont'
+ not set */
+ char_u *rsrc_bold_font_name; /* Resource bold font name */
+ char_u *rsrc_ital_font_name; /* Resource italic font name */
+ char_u *rsrc_boldital_font_name; /* Resource bold-italic font name */
+ char_u *rsrc_menu_font_name; /* Resource menu Font name */
+ Bool rsrc_rev_video; /* Use reverse video? */
+
+ char_u *geom; /* Geometry, eg "80x24" */
+ Bool color_approx; /* Some color was approximated */
+#endif
+
+#ifdef FEAT_GUI_GTK
+ int visibility; /* Is shell partially/fully obscured? */
+ GdkCursor *blank_pointer; /* Blank pointer */
+
+ /* X Resources */
+ char_u *geom; /* Geometry, eg "80x24" */
+
+ GtkWidget *mainwin; /* top level GTK window */
+ GtkWidget *formwin; /* manages all the windows below */
+ GtkWidget *drawarea; /* the "text" area */
+# ifdef FEAT_MENU
+ GtkWidget *menubar; /* menubar */
+# endif
+# ifdef FEAT_TOOLBAR
+ GtkWidget *toolbar; /* toolbar */
+# endif
+# ifdef FEAT_GUI_GNOME
+ GtkWidget *menubar_h; /* menubar handle */
+ GtkWidget *toolbar_h; /* toolbar handle */
+# endif
+ GdkColor *fgcolor; /* GDK-styled foreground color */
+ GdkColor *bgcolor; /* GDK-styled background color */
+# ifndef HAVE_GTK2
+ GuiFont current_font;
+# endif
+ GdkGC *text_gc; /* cached GC for normal text */
+# ifdef HAVE_GTK2
+ PangoContext *text_context; /* the context used for all text */
+ PangoFont *ascii_font; /* cached font for ASCII strings */
+ PangoGlyphString *ascii_glyphs; /* cached code point -> glyph map */
+# endif
+
+ GtkAccelGroup *accel_group;
+# ifndef HAVE_GTK2
+ GtkWidget *fontdlg; /* font selection dialog window */
+ char_u *fontname; /* font name from font selection dialog */
+# endif
+ GtkWidget *filedlg; /* file selection dialog */
+ char_u *browse_fname; /* file name from filedlg */
+#endif /* FEAT_GUI_GTK */
+
+#ifdef FEAT_FOOTER
+ int footer_height; /* height of the message footer */
+#endif
+
+#if defined(FEAT_TOOLBAR) \
+ && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF))
+ int toolbar_height; /* height of the toolbar */
+#endif
+
+#ifdef FEAT_BEVAL_TIP
+ /* Tooltip properties; also used for balloon evaluation */
+ char_u *rsrc_tooltip_font_name; /* tooltip font name */
+ char *rsrc_tooltip_fg_name; /* tooltip foreground color name */
+ char *rsrc_tooltip_bg_name; /* tooltip background color name */
+ guicolor_T tooltip_fg_pixel; /* tooltip foreground color */
+ guicolor_T tooltip_bg_pixel; /* tooltip background color */
+ XFontSet tooltip_fontset; /* tooltip fontset */
+#endif
+
+#ifdef FEAT_GUI_MSWIN
+ GuiFont currFont; /* Current font */
+ guicolor_T currFgColor; /* Current foreground text color */
+ guicolor_T currBgColor; /* Current background text color */
+#endif
+
+#ifdef FEAT_GUI_BEOS
+ VimApp *vimApp;
+ VimWindow *vimWindow;
+ VimFormView *vimForm;
+ VimTextAreaView *vimTextArea;
+ int vdcmp; /* Vim Direct Communication Message Port */
+#endif
+
+#ifdef FEAT_GUI_MAC
+ WindowPtr VimWindow;
+ MenuHandle MacOSHelpMenu; /* Help menu provided by the MacOS */
+ int MacOSHelpItems; /* Nr of help-items supplied by MacOS */
+ int MacOSHaveCntxMenu; /* Contextual menu available */
+ WindowPtr wid; /* Window id of text area */
+ int visibility; /* Is window partially/fully obscured? */
+#endif
+
+#if defined(FEAT_GUI_AMIGA)
+ struct Window *window; /* a handle to the amiga window */
+ struct Menu *menu; /* a pointer to the first menu */
+ struct TextFont *textfont; /* a pointer to the font structure */
+#endif
+
+#ifdef RISCOS
+ int window_handle;
+ char_u *window_title;
+ int window_title_size;
+ int fg_colour; /* in 0xBBGGRR format */
+ int bg_colour;
+#endif
+
+#ifdef FEAT_GUI_PHOTON
+ PtWidget_t *vimWindow; /* PtWindow */
+ PtWidget_t *vimTextArea; /* PtRaw */
+ PtWidget_t *vimContainer; /* PtPanel */
+# if defined(FEAT_MENU) || defined(FEAT_TOOLBAR)
+ PtWidget_t *vimToolBarGroup;
+# endif
+# ifdef FEAT_MENU
+ PtWidget_t *vimMenuBar;
+# endif
+# ifdef FEAT_TOOLBAR
+ PtWidget_t *vimToolBar;
+ int toolbar_height;
+# endif
+ PhEvent_t *event_buffer;
+#endif
+
+#ifdef FEAT_XIM
+ char *rsrc_input_method;
+ char *rsrc_preedit_type_name;
+#endif
+} gui_T;
+
+extern gui_T gui; /* this is defined in gui.c */
+
+/* definitions of available window positionings for gui_*_position_in_parent()
+ */
+typedef enum
+{
+ VW_POS_MOUSE,
+ VW_POS_CENTER,
+ VW_POS_TOP_CENTER
+}
+gui_win_pos_T;
+
+#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
+ || defined(MSWIN_FIND_REPLACE)
+/*
+ * Flags used to distinguish the different contexts in which the
+ * find/replace callback may be called.
+ */
+# define FRD_FINDNEXT 1 /* Find next in find dialog */
+# define FRD_R_FINDNEXT 2 /* Find next in repl dialog */
+# define FRD_REPLACE 3 /* Replace once */
+# define FRD_REPLACEALL 4 /* Replace remaining matches */
+# define FRD_UNDO 5 /* Undo replaced text */
+# define FRD_TYPE_MASK 7 /* Mask for the callback type */
+/* Flags which change the way searching is done. */
+# define FRD_WHOLE_WORD 0x08 /* match whole word only */
+# define FRD_MATCH_CASE 0x10 /* match case */
+#endif
diff --git a/src/gui_amiga.c b/src/gui_amiga.c
new file mode 100644
index 000000000..28786aa6f
--- /dev/null
+++ b/src/gui_amiga.c
@@ -0,0 +1,1795 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Amiga GUI support by Michael Nielsen
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <exec/types.h>
+#include <intuition/intuition.h>
+#include <utility/tagitem.h>
+#include <graphics/text.h>
+#include <graphics/rastport.h>
+#include <graphics/layers.h>
+#include <proto/intuition.h>
+#include <proto/graphics.h>
+#include <proto/layers.h>
+#include <devices/timer.h>
+#include <assert.h>
+#include "vim.h"
+#include "gui_amiga.h"
+#include <math.h>
+#include <limits.h>
+
+#ifdef __AROS__
+#include <aros/debug.h>
+#endif
+
+#include "version.h"
+
+#if defined(FEAT_GUI_AMIGA) || defined(PROTO)
+
+#define KEYUP 76
+#define KEYDOWN 77
+#define KEYRIGHT 78
+#define KEYLEFT 79
+#define KEYBACKSPACE 0x41
+#define KEYDELETE 0x46
+#define KEYINSERT 0x47
+#define KEYHOME 0x70
+#define KEYEND 0x71
+#define KEYWHEELUP 0x7A
+#define KEYWHEELDOWN 0x7B
+
+/* When generating prototypes on Unix, these need to be defined */
+#ifdef PROTO
+# define STRPTR char *
+# define BOOL int
+# define UBYTE int
+#endif
+
+static struct PropInfo Gadget2SInfo = { AUTOKNOB+PROPBORDERLESS+FREEVERT+PROPNEWLOOK, 0, 0, MAXBODY, MAXBODY, };
+//static struct Image Image1 = { 0, 0, 10, 397, 0, NULL, 0x0000, 0x0000, NULL };
+static struct Gadget propGadget = { NULL, -12, 15, 10, -28,
+ GFLG_RELRIGHT+GFLG_RELHEIGHT,
+ GACT_RELVERIFY+GACT_RIGHTBORDER+GACT_IMMEDIATE,
+ GTYP_PROPGADGET+GTYP_GZZGADGET,
+ NULL, NULL,
+ NULL, NULL, (APTR)&Gadget2SInfo, NULL, NULL };
+
+static struct timerequest *TimerIO;
+static struct MsgPort *TimerMP;
+static BOOL TimerSent;
+
+struct GFXBase *gfxBase;
+struct ExecBase *execBase;
+struct LayersBase *layersBase;
+
+struct MyColor
+{
+ WORD pen;
+ BOOL alloced;
+};
+
+struct MyColor MyColorTable[256];
+
+struct TagItem tags[] =
+{
+ {WA_Left, 0},
+ {WA_Top, 0},
+ {WA_Width, 400},
+ {WA_Height, 400},
+ {WA_Title, (ULONG)VIM_VERSION_SHORT},
+ {WA_ScreenTitle, (ULONG)VIM_VERSION_LONG},
+ {WA_DragBar, TRUE}, /* enable dragging of the window */
+ {WA_DepthGadget, TRUE}, /* enable the depth gadget */
+ {WA_CloseGadget, TRUE}, /* enable the close gadget*/
+ {WA_SizeGadget, TRUE}, /* enable the size gadget */
+ {WA_SizeBBottom, TRUE}, /* sizegadget contained in bottom border */
+ {WA_SmartRefresh, TRUE}, /* choose smart refresh, saves us doing a lot of work */
+ {WA_ReportMouse, TRUE}, /* Report the position of the mouse */
+ {WA_GimmeZeroZero, TRUE},
+ {WA_Activate, TRUE}, /* Activate window on startup */
+ {WA_Activate, TRUE}, /* Activate window on startup */
+ {WA_NoCareRefresh, TRUE}, /* Refresh screen, don't tell us */
+ {WA_NewLookMenus, TRUE}, /* use the new options for the menu */
+ {WA_AutoAdjust, TRUE}, /* If window is too big for screen adjust size*/
+ {WA_NoCareRefresh, TRUE}, /* If window is too big for screen adjust size*/
+ {WA_MouseQueue, 1}, /* Limit number of pending mouse movement*/
+ {WA_RptQueue, 10}, /* Limit number of pending keystrokes*/
+ {WA_IDCMP, /* IDCMP, what events interest us */
+ IDCMP_NEWSIZE /* Notify us about size change of window*/
+ |IDCMP_REFRESHWINDOW /* Notify us when the window needs refreshing */
+ |IDCMP_MOUSEBUTTONS /* Notify us when the mouse buttons have been used */
+ |IDCMP_MOUSEMOVE /* Notify us when the mouse is moving */
+ |IDCMP_GADGETDOWN /* Notify us when a gadget has been selected */
+ |IDCMP_GADGETUP /* Notify us when a gadget has been released */
+ |IDCMP_MENUPICK /* Notify us when a menu has been picked */
+ |IDCMP_CLOSEWINDOW /* Notify us when the user tries to close the window */
+ |IDCMP_VANILLAKEY /* Notify us about keystrokes */
+ |IDCMP_RAWKEY /* Notify us when raw key events have been used, ie cursor*/
+ |IDCMP_INTUITICKS /* Simpler timer for the blink option */
+ |IDCMP_MENUHELP /* Allow the help key to be used during menu events */
+ |IDCMP_GADGETHELP /* Allow the help key to be used during gadget events */
+ |IDCMP_INACTIVEWINDOW /* notify of inactive window */
+ |IDCMP_ACTIVEWINDOW /* notify of inactive window */
+ },
+ {TAG_DONE, NULL}
+};
+
+#if defined(D)
+#undef D
+#endif
+
+/*#define D(_msg) fprintf(stderr, "%s\n", _msg)*/
+
+#define D(_A)
+#define kprintf(s, ...)
+
+static void AmigaError(const char *string);
+
+void HandleEvent(unsigned long * object);
+static UBYTE getrealcolor(guicolor_T i);
+
+static struct NewWindow vimNewWindow =
+{
+ 0, 0, /* window XY origin relative to TopLeft of screen */
+ 0, 0, /* window width and height */
+ 0, 1, /* detail and block pens */
+ NULL, /* IDCMP flags */
+ NULL, /* other window flags */
+ &propGadget, /* first gadget in gadget list */
+ NULL, /* custom CHECKMARK imagery */
+ "Amiga Vim gui", /* window title */
+ NULL, /* custom screen pointer */
+ NULL, /* custom bitmap */
+ 50, 50, /* minimum width and height */
+ (unsigned short)-1, (unsigned short)-1, /* maximum width and height */
+ WBENCHSCREEN /* destination screen type */
+};
+
+static struct
+{
+ unsigned int key_sym;
+ char_u vim_code0;
+ char_u vim_code1;
+} special_keys[] =
+{
+ {0, 0, 0}
+};
+
+#if 0
+ /* not used? */
+ static int
+hex_digit(int c)
+{
+ if (isdigit(c))
+ return c - '0';
+ c = TOLOWER_ASC(c);
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return -1000;
+}
+#endif
+
+static int characterWidth = -1;
+static int characterHeight = -1;
+static struct
+{
+ BOOL active;
+ enum
+ {
+ CursorOff,
+ CursorOn,
+ CursorWait
+ } state;
+ int onTime;
+ int offTime;
+ int waitTime;
+ int current;
+} cursor =
+{
+ TRUE,
+ CursorWait,
+ 10,
+ 10,
+ 7,
+ 0
+};
+
+enum DrawBoxMode
+{
+ DB_Filled,
+ DB_NotFilled
+};
+
+ static void
+TextDimensions(void)
+{
+ struct TextExtent textExt;
+
+ TextExtent(gui.window->RPort, "s", 1, &textExt);
+
+ characterWidth = textExt.te_Width;
+ characterHeight = textExt.te_Height;
+}
+
+ static int
+posWidthCharToPoint(int width)
+{
+ return (width)*characterWidth;
+}
+
+ static int
+posHeightCharToPoint(int height)
+{
+ return (int)(height)*characterHeight;
+}
+
+ static int
+posWidthPointToChar(int width)
+{
+ //return (int)floor((float)width/(float)characterWidth)-1;
+ return width /characterWidth;
+}
+
+ static int
+posHeightPointToChar(int height)
+{
+ //return (int)floor((float)height/(float)characterHeight)-2;
+ return height / characterHeight;
+}
+
+ static int
+widthCharToPoint(int width)
+{
+ return (width)*(characterWidth);
+}
+
+ static int
+heightCharToPoint(int height)
+{
+ return (height)*characterHeight;
+}
+
+ static int
+widthPointToChar(int width)
+{
+ return (width)/characterWidth;
+}
+
+ static int
+heightPointToChar(int height)
+{
+ return (height)/characterHeight;
+}
+
+ static void
+refreshBorder(void)
+{
+ /*WaitBOVP(gui.window->);*/
+ RefreshWindowFrame(gui.window);
+}
+
+ static void
+drawBox(enum DrawBoxMode mode, unsigned short col, unsigned short row, int w, int h, guicolor_T color)
+{
+ LONG apen = GetAPen(gui.window->RPort);
+ LONG x1, y1, x2, y2;
+
+kprintf(" drawbox %d,%d color %d\n", col, row, color);
+
+ SetAPen(gui.window->RPort, getrealcolor(color));
+
+ x1 = posWidthCharToPoint(col);
+ y1 = posHeightCharToPoint(row + 1) - h;
+ x2 = x1 + w - 1;
+ y2 = posHeightCharToPoint(row + 1) - 1;
+
+ switch(mode)
+ {
+ case DB_Filled:
+ RectFill(gui.window->RPort, x1, y1, x2, y2);
+ break;
+
+ case DB_NotFilled:
+ Move(gui.window->RPort, x1, y1);
+ Draw(gui.window->RPort, x2, y1);
+ Draw(gui.window->RPort, x2, y2);
+ Draw(gui.window->RPort, x1, y2);
+ Draw(gui.window->RPort, x1, y1);
+ break;
+ }
+
+ SetAPen(gui.window->RPort, apen);
+
+}
+
+ static enum event
+EventHandler(void)
+{
+ struct IntuiMessage *msg;
+ enum event returnEvent = ev_Ignore;
+ int class, code;
+ static int dragging = 0;
+ static int mouseX, mouseY;
+ char_u string[40];
+ BOOL quit_request = FALSE;
+
+ msg = (struct IntuiMessage *)GetMsg(gui.window->UserPort);
+
+ if (!msg)
+ {
+ returnEvent = ev_NullEvent;
+ }
+ else
+ {
+
+ class = msg->Class;
+ code = msg->Code;
+
+ switch(class)
+ {
+ case IDCMP_INTUITICKS:
+ /*
+ if (cursor.active)
+ {
+ cursor.current ++;
+ if (cursor.state == CursorOff)
+ {
+ printf("cursor turned on\n");
+ if (cursor.offTime < cursor.current)
+ {
+ gui_undraw_cursor();
+ cursor.state = CursorOn;
+ cursor.current = 0;
+ }
+ }
+ else if (cursor.state == CursorOn)
+ {
+ printf("cursor turned off\n");
+ if (cursor.onTime < cursor.current)
+ {
+ cursor.state = CursorOff;
+ gui_update_cursor(FALSE);
+ cursor.current = 0;
+ }
+ }
+ else if (cursor.state == CursorWait)
+ {
+ printf("cursor turned Wait\n");
+ if (cursor.waitTime < cursor.current)
+ {
+ cursor.state = CursorOn;
+ cursor.current = 0;
+ }
+ }
+ }
+ else
+ {
+ }
+ returnEvent = ev_IntuiTicks;
+ */
+ break;
+
+ case IDCMP_MOUSEBUTTONS:
+ {
+ int vim_modifiers=0;
+ D("Mouse button event detected");
+ switch (msg->Qualifier )
+ {
+ case IEQUALIFIER_LALT:
+ case IEQUALIFIER_RALT:
+ D("detected a Alt key");
+ vim_modifiers|=MOUSE_ALT;
+ break;
+
+ case IEQUALIFIER_LSHIFT:
+ case IEQUALIFIER_RSHIFT:
+ D("detected a Shift key");
+ vim_modifiers|=MOUSE_SHIFT;
+ break;
+ case IEQUALIFIER_CONTROL:
+ D("detected a Control key");
+ vim_modifiers |= MOUSE_CTRL;
+ break;
+ }
+ if (code == SELECTDOWN)
+ {
+ D("Select Down detected\n");
+ dragging = 1;
+ gui_send_mouse_event(MOUSE_LEFT,
+ mouseX = msg->MouseX - gui.window->BorderLeft,
+ mouseY = msg->MouseY - gui.window->BorderTop,
+ FALSE,
+ vim_modifiers);
+ /*gui_start_highlight(HL_ALL);*/
+ }
+ else if (code == SELECTUP)
+ {
+ D("Select UP detected\n");
+ dragging = 0;
+ gui_send_mouse_event(MOUSE_RELEASE,
+ msg->MouseX - gui.window->BorderLeft,
+ msg->MouseY - gui.window->BorderTop,
+ FALSE, vim_modifiers);
+ /*gui_stop_highlight(mask);*/
+ }
+ returnEvent = ev_MouseButtons;
+ break;
+ }
+ case IDCMP_MOUSEMOVE:
+ if ((abs(mouseX-(msg->MouseX - gui.window->BorderLeft)) > characterWidth) ||
+ (abs(mouseY-(msg->MouseY - gui.window->BorderTop))>characterHeight))
+ {
+ int vim_modifiers=0;
+
+ switch (msg->Qualifier )
+ {
+ case IEQUALIFIER_LALT:
+ case IEQUALIFIER_RALT:
+ D("detected a Alt key");
+ vim_modifiers|=MOUSE_ALT;
+ break;
+
+ case IEQUALIFIER_LSHIFT:
+ case IEQUALIFIER_RSHIFT:
+ D("detected a Shift key");
+ vim_modifiers|=MOUSE_SHIFT;
+ break;
+ case IEQUALIFIER_CONTROL:
+ D("detected a Control key");
+ vim_modifiers |= MOUSE_CTRL;
+ break;
+ }
+
+ mouseX = msg->MouseX - gui.window->BorderLeft;
+ mouseY = msg->MouseY - gui.window->BorderTop;
+ if (!dragging)
+ {
+ gui_send_mouse_event(MOUSE_SETPOS, mouseX, mouseY, FALSE, vim_modifiers);
+ break;
+ }
+ else
+ {
+ D("dragging\n");
+ gui_send_mouse_event(MOUSE_DRAG, mouseX, mouseY, FALSE, vim_modifiers);
+ }
+ }
+ returnEvent = ev_MouseMove;
+ break;
+ case IDCMP_VANILLAKEY:
+kprintf("===vanillakey %d\n", code);
+ {
+ string[0] = (char_u)code;
+ if (code == CSI)
+ {
+ /* Insert CSI as K_CSI. Untested! */
+ string[1] = KS_EXTRA;
+ string[2] = (int)KE_CSI;
+ add_to_input_buf(string, 3);
+ }
+ else if (code == 8)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'b';
+ add_to_input_buf(string, 3);
+ }
+ else if (code == 127)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'D';
+ add_to_input_buf(string, 3);
+ }
+ else
+ {
+ int len = 1;
+
+ if (input_conv.vc_type != CONV_NONE)
+ len = convert_input(string, 1, sizeof(string));
+ add_to_input_buf(string, len);
+ }
+ returnEvent = ev_KeyStroke;
+ break;
+
+ case IDCMP_RAWKEY:
+ if (msg->Qualifier & IEQUALIFIER_LSHIFT)
+ {
+ }
+ else if (msg->Qualifier & IEQUALIFIER_RSHIFT)
+ {
+ }
+ else if (msg->Qualifier & IEQUALIFIER_CONTROL)
+ {
+ if (code == 33)
+ {
+ trash_input_buf();
+ }
+ }
+ else if (msg->Code == KEYUP)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'u';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYLEFT)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'l';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYRIGHT)
+ {
+kprintf("## keyright");
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'r';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYDOWN)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'd';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYBACKSPACE)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'b';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYDELETE)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'D';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYINSERT)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'I';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYHOME)
+ {
+ string[0] = CSI;
+ string[1] = 'k';
+ string[2] = 'h';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYEND)
+ {
+ string[0] = CSI;
+ string[1] = '@';
+ string[2] = '7';
+ add_to_input_buf(string, 3);
+ }
+ else if (msg->Code == KEYWHEELUP)
+ {
+ int vim_modifiers=0;
+
+ switch (msg->Qualifier )
+ {
+ case IEQUALIFIER_LALT:
+ case IEQUALIFIER_RALT:
+ D("detected a Alt key");
+ vim_modifiers|=MOUSE_ALT;
+ break;
+
+ case IEQUALIFIER_LSHIFT:
+ case IEQUALIFIER_RSHIFT:
+ D("detected a Shift key");
+ vim_modifiers|=MOUSE_SHIFT;
+ break;
+ case IEQUALIFIER_CONTROL:
+ D("detected a Control key");
+ vim_modifiers |= MOUSE_CTRL;
+ break;
+ }
+ gui_send_mouse_event(MOUSE_4, 0, 1, FALSE, vim_modifiers);
+
+ }
+ else if (msg->Code == KEYWHEELDOWN)
+ {
+ int vim_modifiers=0;
+
+ switch (msg->Qualifier )
+ {
+ case IEQUALIFIER_LALT:
+ case IEQUALIFIER_RALT:
+ D("detected a Alt key");
+ vim_modifiers|=MOUSE_ALT;
+ break;
+
+ case IEQUALIFIER_LSHIFT:
+ case IEQUALIFIER_RSHIFT:
+ D("detected a Shift key");
+ vim_modifiers|=MOUSE_SHIFT;
+ break;
+ case IEQUALIFIER_CONTROL:
+ D("detected a Control key");
+ vim_modifiers |= MOUSE_CTRL;
+ break;
+ }
+ gui_send_mouse_event(MOUSE_5, 0, 1, FALSE, vim_modifiers);
+ }
+
+ returnEvent = ev_KeyStroke;
+ break;
+ }
+ case IDCMP_MENUVERIFY:
+ returnEvent = ev_MenuVerify;
+ /* Menu verification requested */
+ switch (code)
+ {
+ case MENUWAITING:
+ /*
+ ** It's not for us, the user is accessing another
+ ** programs menu, this is a good time to do some
+ ** cleanup etc
+ */
+ break;
+ case MENUHOT:
+ /*
+ ** It is our menu that is going hot, we have kontrol
+ ** Menu action can be cancelled by
+ ** msg->Code = MENUCANCEL;
+ */
+ break;
+ default:
+ break;
+ }
+ break;
+ case IDCMP_MENUPICK:
+ returnEvent = ev_MenuPick;
+ {
+ /*
+ ** one of our menu's have been selected, let's find out which
+ */
+ union myMenuItemUnion *item;
+ int menuNumber;
+
+ menuNumber = code;
+
+ item = (union myMenuItemUnion *) ItemAddress(gui.menu, menuNumber);
+
+
+ if (item)
+ {
+ gui_menu_cb(item->myMenuItem.guiMenu);
+ }
+ }
+ break;
+ case IDCMP_CLOSEWINDOW:
+ quit_request = TRUE;
+ break;
+
+ case IDCMP_NEWSIZE:
+ {
+ int cx, cy;
+ //cx = widthPointToChar(gui.window->GZZWidth);
+ //cy = heightPointToChar(gui.window->GZZHeight);
+
+ cx = gui.window->GZZWidth;
+ cy = gui.window->GZZHeight - characterHeight;
+
+ gui_resize_shell(cx, cy);
+
+ returnEvent = ev_NewSize;
+ break;
+ }
+ case IDCMP_REFRESHWINDOW:
+ refreshBorder();
+ returnEvent = ev_RefreshWindow;
+ break;
+ case IDCMP_GADGETDOWN:
+ returnEvent = ev_GadgetDown;
+ break;
+ case IDCMP_GADGETUP:
+ returnEvent = ev_GadgetUp;
+ break;
+ case IDCMP_MENUHELP:
+ returnEvent = ev_MenuHelp;
+ break;
+ case IDCMP_GADGETHELP:
+ returnEvent = ev_GadgetHelp;
+ break;
+ case IDCMP_INACTIVEWINDOW:
+ gui.in_focus = FALSE;
+ gui_update_cursor(TRUE, FALSE);
+ break;
+
+ case IDCMP_ACTIVEWINDOW:
+ gui.in_focus = TRUE;
+ gui_update_cursor(TRUE, FALSE);
+ break;
+ default:
+ break;
+ }
+ ReplyMsg((struct Message*)msg);
+ }
+
+ if (quit_request)
+ {
+ getout(0); // gui_mch_exit(1);
+ }
+
+ return returnEvent;
+ /* mouse positin gui.window->MoseY, gui.window->MouseX) */
+}
+
+ static int
+checkEventHandler(void)
+{
+ enum event happened;
+
+ do
+ {
+ happened = EventHandler() ;
+ }
+ while (happened != ev_NullEvent);
+
+ return OK;
+}
+
+ static int
+charEventHandler(int wtime)
+{
+ enum event happened;
+ int rc;
+
+ do
+ {
+ Wait(1<<gui.window->UserPort->mp_SigBit);
+
+ happened = EventHandler() ;
+ }
+ while ((happened != ev_IntuiTicks) && (happened != ev_KeyStroke) && (happened != ev_MenuPick) && (happened != ev_MouseMove) &&(happened != ev_MouseButtons) );
+
+ if (happened == ev_KeyStroke || happened == ev_MenuPick)
+ rc = OK;
+ else
+ rc = FAIL;
+
+ return rc;
+}
+
+
+/*
+ * add primary menu
+ */
+ void
+gui_mch_add_menu_item(vimmenu_T *menu, int idx)
+{
+ union myMenuItemUnion *menuItemUnion = NULL;
+ struct IntuiText *menutext = NULL;
+ vimmenu_T *parent;
+
+ assert(menu != NULL);
+ assert(menu->parent != NULL);
+ parent = menu->parent;
+
+ /* Don't add menu separator */
+ if (menu_is_separator(menu->name))
+ return;
+
+ if (parent->menuItemPtr == NULL)
+ return;
+
+ /* TODO: use menu->mnemonic and menu->actext */
+ menutext = (struct IntuiText *) malloc(sizeof(struct IntuiText));
+
+ SetAttrib(menutext, FrontPen, 3);
+ SetAttrib(menutext, BackPen, 1);
+ SetAttrib(menutext, DrawMode, COMPLEMENT);
+ SetAttrib(menutext, LeftEdge, 0);
+ SetAttrib(menutext, TopEdge, 0);
+ SetAttrib(menutext, ITextFont, NULL);
+ SetAttrib(menutext, NextText, NULL);
+
+ menuItemUnion = malloc(sizeof(*menuItemUnion));
+
+ SetAttrib(&menuItemUnion->menuItem, NextItem, parent->menuItemPtr);
+ SetAttrib(&menuItemUnion->menuItem, LeftEdge, 0);
+ SetAttrib(&menuItemUnion->menuItem, Width, characterWidth*strlen(menu->dname));
+ SetAttrib(&menuItemUnion->menuItem, Height, characterHeight+2);
+ SetAttrib(&menuItemUnion->menuItem, Flags, ITEMTEXT+ITEMENABLED+HIGHCOMP);
+ SetAttrib(&menuItemUnion->menuItem, MutualExclude, 0);
+ SetAttrib(&menuItemUnion->menuItem, ItemFill, (APTR)menutext);
+ SetAttrib(&menuItemUnion->menuItem, SelectFill, NULL);
+ SetAttrib(&menuItemUnion->menuItem, Command, NULL);
+ SetAttrib(&menuItemUnion->menuItem, SubItem, NULL);
+ SetAttrib(&menuItemUnion->menuItem, NextSelect, MENUNULL);
+
+ menutext->IText = malloc(strlen(menu->dname) + 1);
+
+ strcpy(menutext->IText, menu->dname);
+
+ menuItemUnion->menuItem.NextItem = NULL;
+
+
+ if (parent)
+ {
+ if (!parent->menuItemPtr)
+ {
+ D("Adding first subElement");
+ SetAttrib(&menuItemUnion->menuItem, TopEdge, 0);
+ parent->menuPtr->FirstItem = &menuItemUnion->menuItem;
+ parent->menuItemPtr = &menuItemUnion->menuItem;
+ }
+ else
+ {
+ struct MenuItem *tmpMenuItem;
+ tmpMenuItem = parent->menuItemPtr;
+ while (tmpMenuItem->NextItem)
+ {
+ tmpMenuItem = tmpMenuItem->NextItem;
+ }
+ tmpMenuItem->NextItem = &menuItemUnion->menuItem;
+ SetAttrib(&menuItemUnion->menuItem, TopEdge, tmpMenuItem->TopEdge+tmpMenuItem->Height);
+ }
+ }
+ menu->menuPtr= NULL;
+ menu->menuItemPtr = &menuItemUnion->menuItem;
+ menuItemUnion->myMenuItem.guiMenu = menu;
+}
+
+
+ static struct Menu *
+getMenu(struct RastPort *rast, int left, STRPTR name)
+{
+ struct Menu *menu;
+ struct TextExtent textExt;
+
+ menu = malloc(sizeof(*menu));
+ menu->NextMenu = NULL;
+ menu->LeftEdge = left;
+
+ TextExtent(rast, name, strlen(name), &textExt);
+
+ menu->TopEdge = 0;
+ menu->Width = textExt.te_Width;
+ menu->Height = textExt.te_Height;
+ menu->Flags = ITEMTEXT+HIGHCOMP+MENUENABLED;
+ menu->MenuName = name;
+ menu->FirstItem = NULL;
+
+ return menu;
+}
+
+/*
+ * add 1st level submenu item
+ */
+ void
+gui_mch_add_menu(vimmenu_T *menu, int idx)
+{
+ struct Menu *newMenu;
+ int pos = 0;
+
+ if (!menu_is_menubar(menu->name))
+ return;
+
+ menu->menuPtr = newMenu = getMenu(gui.window->RPort, 0, menu->dname);
+ menu->menuItemPtr = NULL;
+ newMenu->NextMenu = NULL;
+
+ if (!gui.menu)
+ {
+ D("Adding head menu");
+ gui.menu = newMenu ;
+ }
+ else
+ {
+ struct Menu *tmpMenu;
+
+ tmpMenu = gui.menu;
+ while (tmpMenu->NextMenu)
+ tmpMenu = tmpMenu->NextMenu;
+ tmpMenu->NextMenu = newMenu;
+ pos = tmpMenu->LeftEdge +
+ TextLength(gui.window->RPort, tmpMenu->MenuName,
+ strlen(tmpMenu->MenuName));
+ newMenu->LeftEdge = pos;
+ }
+}
+
+ void
+gui_mch_toggle_tearoffs(enable)
+ int enable;
+{
+ /* no tearoff menus */
+}
+
+ int
+gui_mch_set_blinking(long wait, long on, long off)
+{
+ cursor.waitTime = wait/100;
+ cursor.onTime = on/100;
+ cursor.offTime = off/100;
+ return OK;
+}
+
+ void
+gui_mch_prepare(int *argc, char **argv)
+{
+ D("gui_mch_prepare");
+
+ execBase = (struct ExecBase *)OpenLibrary("exec.library", NULL);
+ gfxBase = (struct GFXBase *)OpenLibrary("graphics.library", NULL);
+ layersBase = (struct LayersBase *)OpenLibrary("layers.library", NULL);
+
+ if (!execBase)
+ {
+ D("Cannot open exec.library, aborting");
+ }
+ if (!gfxBase)
+ {
+ D("Cannot open graphics.library, aborting");
+ }
+ if (!layersBase)
+ {
+ D("Cannot open graphics.library, aborting");
+ }
+ D("gui_mch_prepare done ");
+}
+
+ void
+atexitDoThis(void)
+{
+kprintf("atexitdothis###\n");
+ gui_mch_exit(-1);
+}
+
+/*
+ * Check if the GUI can be started. Called before gvimrc is sourced.
+ * Return OK or FAIL.
+ */
+ int
+gui_mch_init_check(void)
+{
+ if (execBase && gfxBase && layersBase)
+ return OK;
+ return FAIL;
+}
+
+ int
+gui_mch_init(void)
+{
+ int returnCode = FAIL; /* assume failure*/
+
+ TimerMP = CreateMsgPort();
+ if (!TimerMP) return FAIL;
+
+ TimerIO = (struct timerequest *)CreateIORequest(TimerMP, sizeof(*TimerIO));
+ if (!TimerIO) return FAIL;
+
+ if (OpenDevice("timer.device", UNIT_VBLANK, &TimerIO->tr_node, 0)) return FAIL;
+
+ gui.window = OpenWindowTagList(&vimNewWindow, tags);
+ if (gui.window)
+ {
+ gui.in_use = TRUE;
+ gui.in_focus=TRUE;
+ gui.norm_pixel = gui.def_norm_pixel = 1;
+ gui.back_pixel = gui.def_back_pixel = 0;
+
+ set_normal_colors();
+ gui_check_colors();
+
+ SetDrMd(gui.window->RPort, JAM2);
+ gui_mch_set_colors(gui.norm_pixel, gui.back_pixel);
+
+ atexit(atexitDoThis);
+
+ TextDimensions();
+ returnCode = OK; /* we've had success */
+ if (gui_win_x != -1 && gui_win_y != -1)
+ gui_mch_set_winpos(gui_win_x, gui_win_y);
+
+ gui_mch_clear_all();
+
+ }
+ gui.menu = NULL;
+
+ return returnCode;
+}
+
+ void
+gui_mch_new_colors(void)
+{
+kprintf("### gui_mch_new_colors\n");
+ SetAPen(gui.window->RPort, getrealcolor(gui.norm_pixel));
+ SetBPen(gui.window->RPort, getrealcolor(gui.back_pixel));
+
+ D("gui_mch_new_colors");
+}
+
+ int
+gui_mch_open(void)
+{
+ D("gui_mch_open");
+
+ highlight_gui_started();
+ return OK;
+}
+
+ void
+gui_mch_exit(int returnCode)
+{
+kprintf("###gui_mch_exit\n");
+ D("****gui_mch_exit");
+
+ if (TimerSent)
+ {
+ if (!CheckIO(&TimerIO->tr_node)) AbortIO(&TimerIO->tr_node);
+ WaitIO(&TimerIO->tr_node);
+ TimerSent = FALSE;
+ }
+
+ if (TimerIO)
+ {
+ CloseDevice(&TimerIO->tr_node);
+ DeleteIORequest(&TimerIO->tr_node);
+ TimerIO = NULL;
+ }
+
+ if (TimerMP)
+ {
+ DeleteMsgPort(TimerMP);
+ TimerMP = NULL;
+ }
+
+ if (gui.window)
+ {
+ int i;
+
+ for(i = 0; i < sizeof(MyColorTable) / sizeof(MyColorTable[0]); i++)
+ {
+ if (MyColorTable[i].alloced)
+ {
+ ReleasePen(gui.window->WScreen->ViewPort.ColorMap, MyColorTable[i].pen);
+ MyColorTable[i].alloced = FALSE;
+ }
+ }
+
+ D("Closeing window ");
+ CloseWindow(gui.window);
+ CloseLibrary((struct Library*)execBase);
+ CloseLibrary((struct Library*)gfxBase);
+ gui.window = NULL;
+ gui.in_use = FALSE;
+ //getout(1);
+ }
+}
+
+/*
+ * Get the position of the top left corner of the window.
+ */
+ int
+gui_mch_get_winpos(int *x, int *y)
+{
+ if (gui.window)
+ {
+ *x = gui.window->LeftEdge;
+ *y = gui.window->TopEdge;
+ }
+ else
+ {
+ return FAIL;
+ }
+
+ return OK;
+}
+
+/*
+ * Set the position of the top left corner of the window to the given
+ * coordinates.
+ */
+ void
+gui_mch_set_winpos(int x, int y)
+{
+ if (gui.window)
+ {
+ ChangeWindowBox(gui.window, x, y, gui.window->Width, gui.window->Height);
+ }
+}
+
+ void
+gui_mch_set_shellsize(int width, int height,
+ int min_width, int min_height, int base_width, int base_height)
+{
+ D("gui_mch_set_shellsize");
+
+ ChangeWindowBox(gui.window, gui.window->LeftEdge,
+ gui.window->TopEdge, widthCharToPoint(width) + gui.window->BorderLeft + gui.window->BorderRight,
+ heightCharToPoint(height) + gui.window->BorderTop + gui.window->BorderBottom);
+ checkEventHandler();
+}
+
+ void
+gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
+{
+// *screen_w = widthPointToChar(gui.window->GZZWidth);
+// *screen_h = heightPointToChar(gui.window->GZZHeight);
+ *screen_w = gui.window->GZZWidth;
+ *screen_h = gui.window->GZZHeight - characterHeight;
+
+
+kprintf("=== get_screen_dimensions: screen %d,%d character %d,%d console %d,%d\n",
+gui.window->GZZWidth,
+gui.window->GZZHeight,
+characterWidth,
+characterHeight,
+*screen_w,
+*screen_h);
+
+}
+
+ void
+gui_mch_set_text_area_pos(int x, int y, int w, int h)
+{
+ D("gui_mch_set_text_area_pos");
+}
+
+ void
+gui_mch_enable_scrollbar(scrollbar_T *sb, int flag)
+{
+ /* done by default */
+ /* TODO: disable scrollbar when it's too small */
+}
+
+ void
+gui_mch_set_scrollbar_thumb(scrollbar_T *sb, long val, long size, long max)
+{
+ ULONG total = max;
+ ULONG visible = size;
+ ULONG top = val;
+ ULONG hidden;
+ ULONG overlap = 0;
+ UWORD body, pot;
+
+kprintf("__set_scrollbar_thumb val %d size %d max %d\n", val, size, max);
+
+ if (total > visible)
+ hidden = total - visible;
+ else
+ hidden = 0;
+
+ if (top > hidden)
+ top = hidden;
+
+ body = (hidden > 0) ?
+ (UWORD)(((ULONG)(visible - overlap) * MAXBODY) / (total - overlap)) :
+ MAXBODY;
+
+ pot = (hidden > 0) ? (UWORD)(((ULONG) top * MAXPOT) / hidden) : 0;
+
+kprintf("__pot %x body %x\n", pot, body);
+
+ NewModifyProp(&propGadget, gui.window, NULL,
+ Gadget2SInfo.Flags,
+ MAXPOT, pot,
+ MAXBODY, body,
+ 1);
+ return;
+
+}
+
+ void
+gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h)
+{
+ D("gui_mch_set_scrollbar_pos");
+ /*NewModifyProp(&propGadget, gui.window, NULL, MAXPOT, MAXPOT/sb->max*y, MAXPOT, MAXBODY/sb->max/sb->size, 1);*/
+}
+
+ void
+gui_mch_create_scrollbar(scrollbar_T *sb, int orient)
+{
+ /* this is done by default */
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+ void
+gui_mch_destroy_scrollbar(scrollbar_T *sb)
+{
+ /* this is done by default */
+}
+#endif
+
+int gui_mch_init_font(char_u *font_name, int fontset)
+{
+ /*D("gui_mch_init_font");*/
+
+ gui.char_width = characterWidth;
+ gui.char_height = characterHeight;
+ gui.char_ascent = gui.window->RPort->TxBaseline;
+
+ return OK;
+}
+
+ int
+gui_mch_adjust_charsize()
+{
+ return FAIL;
+}
+
+ GuiFont
+gui_mch_get_font( char_u *name, int giveErrorIfMissing)
+{
+ /*D("gui_mch_get_font");*/
+ return NULL;
+}
+
+ void
+gui_mch_set_font(GuiFont font)
+{
+ /*D("gui_mch_set_font");*/
+}
+
+#if 0 /* not used */
+ int
+gui_mch_same_font(GuiFont f1, GuiFont f2)
+{
+ D("gui_mch_same_font");
+}
+#endif
+
+ void
+gui_mch_free_font(GuiFont font)
+{
+ if (font)
+ D("gui_mch_free_font");
+}
+
+#define RGB(a, b, c) ((a && 0xff) * 0x10000 + (b * 0xff) * 0x100 + (c & 0xff))
+
+/*
+ * Get color handle for color "name".
+ * Return INVALCOLOR when not possible.
+ */
+
+ typedef struct guicolor_tTable
+ {
+ char *name;
+ unsigned long color;
+ UBYTE red;
+ UBYTE green;
+ UBYTE blue;
+ } guicolor_tTable;
+
+ static guicolor_tTable table[] =
+ {
+ {"Grey", 0, 190,190,190},
+ {"Black", 1, 0, 0, 0},
+ {"DarkBlue", 2, 0, 0, 139},
+ {"DarkGreen", 3, 0, 100, 0},
+ {"DarkCyan", 4, 0, 139, 139},
+ {"DarkRed", 5, 139, 0, 0},
+ {"DarkMagenta", 6, 139, 0, 139},
+ {"Brown", 7, 165, 42, 42},
+ {"Gray", 8, 190, 190, 190},
+ {"Grey", 9, 190, 190, 190},
+ {"LightGray", 10, 211, 211, 211},
+ {"LightGrey", 11, 211, 211, 211},
+ {"DarkGray", 12, 169, 169, 169},
+ {"DarkGrey", 13, 169, 169, 169},
+ {"Blue", 14, 0, 0, 255},
+ {"LightBlue", 15, 173, 216, 230},
+ {"Green", 16, 0, 255, 0},
+ {"LightGreen", 17, 144, 238, 144},
+ {"Cyan", 18, 0, 255, 255},
+ {"LightCyan", 19, 224, 255, 255},
+ {"Red", 20, 255, 0, 0},
+ {"LightRed", 21, 255, 0, 0}, /*?*/
+ {"Magenta", 22, 255, 0, 255},
+ {"LightMagenta",23, 255, 0, 255}, /*?*/
+ {"Yellow", 24, 255, 255, 0},
+ {"LightYellow", 25, 255, 255, 224}, /* TODO: add DarkYellow */
+ {"White", 26, 255, 255, 255},
+ {"SeaGreen", 27, 46, 139, 87},
+ {"Orange", 28, 255, 165, 0},
+ {"Purple", 30, 160, 32, 240},
+ {"SlateBlue", 31, 106, 90, 205},
+ {"grey90", 32, 229, 229, 229},
+ {"grey95", 33, 242, 242, 242},
+ {"grey80", 34, 204, 204, 204},
+ {NULL, NULL},
+ };
+
+ guicolor_T
+gui_mch_get_color(char_u *name)
+{
+
+ guicolor_T color = INVALCOLOR;
+
+ int i;
+
+ for (i = 0; table[i].name != NULL;i++)
+ {
+ if (stricmp(name, table[i].name) == 0)
+ {
+ //color = table[i].color;
+ color = i;
+ }
+ }
+
+#if 0
+ if (color == INVALCOLOR)
+ {
+ char *looky = NULL;
+
+ color = strtol((char*)name, &looky, 10);
+ if (*looky != NUL)
+ color = INVALCOLOR;
+ }
+#endif
+
+ kprintf("gui_mch_get_color[%s] = %s\n", name, table[color].name);
+
+ return color;
+}
+
+static UBYTE getrealcolor(guicolor_T i)
+{
+ if (!MyColorTable[i].alloced)
+ {
+ MyColorTable[i].pen = ObtainBestPen(gui.window->WScreen->ViewPort.ColorMap,
+ table[i].red * 0x01010101,
+ table[i].green * 0x01010101,
+ table[i].blue * 0x01010101,
+ OBP_FailIfBad, FALSE,
+ OBP_Precision, PRECISION_GUI,
+ TAG_DONE);
+ if (MyColorTable[i].pen != -1)
+ {
+ MyColorTable[i].alloced = TRUE;
+ }
+ }
+
+ return MyColorTable[i].pen;
+}
+
+
+ void
+gui_mch_set_colors(guicolor_T fg, guicolor_T bg)
+{
+#if 0
+ if (fg == 0)
+ {
+ fg = 1;
+ }
+#endif
+ SetABPenDrMd(gui.window->RPort, getrealcolor(fg), getrealcolor(bg), JAM2);
+
+kprintf("gui_mch_set_colors %s,%s\n", table[fg].name, table[bg].name);
+}
+
+ void
+gui_mch_set_fg_color(guicolor_T color)
+{
+#if 0
+ if (color == 0)
+ {
+ color = 1; /* vim sends 0 as default color which is ALWAYS the
+ background on the amiga scrolling with colours as the
+ background is a very bad idea on slow machines*/
+ }
+#endif
+ SetAPen(gui.window->RPort, getrealcolor(color));
+ SetDrMd(gui.window->RPort, JAM2);
+
+kprintf("gui_mch_set_fg_color %s\n", table[color].name);
+
+}
+
+ void
+gui_mch_set_bg_color(guicolor_T color)
+{
+ SetBPen(gui.window->RPort, getrealcolor(color));
+kprintf("gui_mch_set_bg_color %s\n", table[color].name);
+
+}
+
+ void
+gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
+{
+#if 1
+ char tempstring[300];
+
+ memcpy(tempstring, s, len);
+ tempstring[len] = '\0';
+
+ kprintf("gui_mch_draw_string(%s) flags %x\n", tempstring, flags);
+#endif
+
+ if (flags & DRAW_TRANSP)
+ {
+ SetDrMd(gui.window->RPort, JAM1);
+ Move(gui.window->RPort, posWidthCharToPoint(col), posHeightCharToPoint(row) + gui.window->RPort->TxBaseline);
+ Text(gui.window->RPort, s, len);
+ }
+ else
+ {
+ SetDrMd(gui.window->RPort, JAM2);
+ Move(gui.window->RPort, posWidthCharToPoint(col), posHeightCharToPoint(row) + gui.window->RPort->TxBaseline);
+ Text(gui.window->RPort, s, len);
+ }
+
+ if (flags & DRAW_BOLD)
+ {
+ SetDrMd(gui.window->RPort, JAM1);
+ Move(gui.window->RPort, posWidthCharToPoint(col)+1, posHeightCharToPoint(row) + gui.window->RPort->TxBaseline);
+ Text(gui.window->RPort, s, len);
+ }
+
+ if (flags & DRAW_UNDERL)
+ {
+ Move(gui.window->RPort, posWidthCharToPoint(col), posHeightCharToPoint(row + 1) - 1);
+ Draw(gui.window->RPort, posWidthCharToPoint(col+len) - 1, posHeightCharToPoint(row + 1) - 1);
+ }
+
+ SetDrMd(gui.window->RPort, JAM2);
+}
+
+ int
+gui_mch_haskey(char_u *name)
+{
+ int i;
+
+ D("gui_mch_haskey");
+
+ for (i = 0; special_keys[i].vim_code1 != NUL; i++)
+ if (name[0] == special_keys[i].vim_code0 &&
+ name[1] == special_keys[i].vim_code1)
+ return OK;
+ return FAIL;
+}
+
+ void
+gui_mch_beep(void)
+{
+ D("gui_mch_beep");
+}
+
+ void
+gui_mch_flash(int msec)
+{
+ D("gui_mch_flash");
+
+ SetDrMd(gui.window->RPort, COMPLEMENT);
+ RectFill(gui.window->RPort, 0, 0, gui.window->GZZWidth - 1, gui.window->GZZHeight - 1);
+ Delay(msec * 50 / 1000);
+ RectFill(gui.window->RPort, 0, 0, gui.window->GZZWidth - 1, gui.window->GZZHeight - 1);
+ SetDrMd(gui.window->RPort, JAM2);
+}
+
+ void
+gui_mch_invert_rectangle( int r, int c, int nr, int nc)
+{
+ printf("gui_mch_invert_rectangle %d %d %d %d\n", r, c, nr, nc);
+}
+
+ void
+gui_mch_iconify(void)
+{
+ D("gui_mch_iconify");
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Bring the Vim window to the foreground.
+ */
+ void
+gui_mch_set_foreground()
+{
+ WindowToFront(gui.window);
+ D("gui_mch_set_foreground");
+}
+#endif
+
+ void
+gui_mch_settitle(char_u *title, char_u *icon)
+{
+ SetWindowTitles(gui.window, title, (STRPTR)~0);
+ D("gui_mch_settitle");
+}
+
+ void
+gui_mch_stop_blink(void)
+{
+ gui_undraw_cursor();
+ D("gui_mch_stop_blink");
+}
+
+ void
+gui_mch_start_blink(void)
+{
+ gui_update_cursor(FALSE, FALSE);
+ D("gui_mch_start_blink");
+}
+
+ void
+gui_mch_draw_hollow_cursor(guicolor_T color)
+{
+ drawBox(DB_NotFilled, gui.col, gui.row, characterWidth, characterHeight, color);
+}
+
+ void
+gui_mch_draw_part_cursor( int w, int h, guicolor_T color)
+{
+ D("gui_mch_part_cursor");
+ drawBox(DB_Filled, gui.col, gui.row, w, h, color);
+}
+
+ void
+gui_mch_update(void)
+{
+ checkEventHandler();
+ return ;
+}
+
+ int
+gui_mch_wait_for_chars(int wtime)
+{
+ ULONG timermask = 1L << TimerMP->mp_SigBit;
+ ULONG winmask = 1L << gui.window->UserPort->mp_SigBit;
+ int retval = FAIL;
+
+ kprintf("========== gui_mch_wait_for_chars %d\n", wtime);
+
+ if (wtime == -1) wtime = 1000000000;
+ if (wtime < 20) wtime = 20;
+
+ SetSignal(0, timermask);
+ TimerIO->tr_node.io_Command = TR_ADDREQUEST;
+ TimerIO->tr_time.tv_secs = wtime / 1000;
+ TimerIO->tr_time.tv_micro = (wtime % 1000) * 1000;
+ SendIO(&TimerIO->tr_node);
+ TimerSent = TRUE;
+
+ for(;;)
+ {
+ ULONG sigs = Wait(winmask | timermask);
+
+ if (sigs & winmask)
+ {
+ checkEventHandler();
+ if (!vim_is_input_buf_empty())
+ {
+ retval = OK;
+ if (!CheckIO(&TimerIO->tr_node)) AbortIO(&TimerIO->tr_node);
+ WaitIO(&TimerIO->tr_node);
+ TimerSent = FALSE;
+ break;
+ }
+ }
+
+ if (sigs & timermask)
+ {
+ struct Message *msg;
+
+ if ((msg = GetMsg(TimerMP)))
+ {
+ ReplyMsg(msg);
+ TimerSent = FALSE;
+ retval = FAIL;
+ break;
+ }
+ }
+ }
+
+ return retval;
+
+// assert(wtime != 0);
+// return charEventHandler(wtime);
+}
+
+ void
+gui_mch_flush(void)
+{
+}
+
+ void
+gui_mch_clear_block(int row1, int col1, int row2, int col2)
+{
+ UBYTE apen = GetAPen(gui.window->RPort);
+
+ SetAPen(gui.window->RPort, getrealcolor(gui.back_pixel));
+ RectFill(gui.window->RPort,
+ posWidthCharToPoint(col1),
+ posHeightCharToPoint(row1),
+ posWidthCharToPoint(col2 + 1) - 1,
+ posHeightCharToPoint(row2 + 1) - 1);
+ SetAPen(gui.window->RPort, apen);
+
+}
+
+ void
+gui_mch_clear_all(void)
+{
+ SetRast(gui.window->RPort, GetBPen(gui.window->RPort));
+ refreshBorder();
+ D("gui_mch_clear_all");
+}
+
+ void
+gui_mch_delete_lines(int row, int num_lines)
+{
+ ScrollWindowRaster(gui.window,
+ 0,
+ characterHeight * num_lines,
+ posWidthCharToPoint(gui.scroll_region_left),
+ posHeightCharToPoint(row),
+ posWidthCharToPoint(gui.scroll_region_right + 1) - 1,
+ posHeightCharToPoint(gui.scroll_region_bot + 1) - 1);
+
+ gui_clear_block(gui.scroll_region_bot - num_lines + 1,
+ gui.scroll_region_left,
+ gui.scroll_region_bot,
+ gui.scroll_region_right);
+
+}
+
+ void
+gui_mch_insert_lines(int row, int num_lines)
+{
+ ScrollWindowRaster(gui.window,
+ 0,
+ -characterHeight*num_lines,
+ posWidthCharToPoint(gui.scroll_region_left),
+ posHeightCharToPoint(row),
+ posWidthCharToPoint(gui.scroll_region_right + 1) - 1,
+ posHeightCharToPoint(gui.scroll_region_bot +1 ) - 1);
+
+ gui_clear_block(row, gui.scroll_region_left,
+ row + num_lines - 1, gui.scroll_region_right);
+
+}
+
+ void
+gui_mch_enable_menu(int flag)
+{
+ D("gui_mch_enable_menu");
+}
+
+ void
+gui_mch_set_menu_pos(int x, int y, int w, int h)
+{
+ D("gui_mch_set_menu_pos");
+}
+
+ void
+gui_mch_destroy_menu(vimmenu_T *menu)
+{
+ D("gui_mch_destroy_menu");
+ ClearMenuStrip(gui.window);
+}
+
+ void
+gui_mch_menu_grey(vimmenu_T *menu, int grey)
+{
+ D("gui_mch_menu_grey");
+}
+
+ void
+gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
+{
+ D("gui_mch_menu_hidden");
+ ClearMenuStrip(gui.window);
+}
+
+ void
+gui_mch_draw_menubar(void)
+{
+ D("gui_mch_draw_menubar");
+ SetMenuStrip(gui.window, gui.menu);
+}
+
+ static void
+AmigaError(const char *string)
+{
+ static struct IntuiText pos = { 3, 0, JAM2, 17, 5, NULL, "Cancel", NULL} ;
+ static struct IntuiText neg = { 3, 0, JAM2, 17, 5, NULL, "Cancel", NULL} ;
+ static struct IntuiText message = { 3, 0, JAM2, 17, 5, NULL, NULL, NULL} ;
+ static char *strptr = 0;
+
+ if (strptr)
+ free(strptr);
+ strptr = malloc(strlen(string)+1);
+
+ message.IText = strptr;
+ strcpy(strptr, string);
+
+ AutoRequest(NULL, &message, &pos, &neg, 0, 0, 300, 300);
+}
+
+ int
+clip_mch_own_selection(VimClipboard *cbd)
+{
+ D("clib_mch_own_selection");
+ return OK;
+}
+
+ void
+mch_setmouse(int on)
+{
+}
+
+/*
+ * Get current y mouse coordinate in text window.
+ * Return -1 when unknown.
+ */
+ int
+gui_mch_get_mouse_x()
+{
+ return gui.window->GZZMouseX;
+}
+
+ int
+gui_mch_get_mouse_y()
+{
+ return gui.window->GZZMouseY;
+}
+
+ void
+gui_mch_setmouse(x, y)
+ int x;
+ int y;
+{
+ /* TODO */
+}
+
+ void
+gui_mch_show_popupmenu(vimmenu_T *menu)
+{
+ /* TODO */
+}
+
+ void
+clip_mch_lose_selection(VimClipboard *cbd)
+{
+ D("clip_mch_lose_selecction");
+}
+
+ void
+clip_mch_request_selection(VimClipboard *cbd)
+{
+ D("clip_mch_requst_selection");
+}
+
+ void
+clip_mch_set_selection(VimClipboard *cbd)
+{
+}
+
+ long_u
+gui_mch_get_rgb(guicolor_T pixel)
+{
+ ULONG coltable[3], color;
+
+ GetRGB32(gui.window->WScreen->ViewPort.ColorMap,
+ getrealcolor(pixel),
+ 1,
+ coltable);
+
+ color = ((coltable[0] & 0xFF000000) >> 8) |
+ ((coltable[1] & 0xFF000000) >> 16) |
+ ((coltable[2] & 0xFF000000) >> 24);
+
+ return color;
+}
+
+#endif /* USE_AMIGA_GUI*/
diff --git a/src/gui_amiga.h b/src/gui_amiga.h
new file mode 100644
index 000000000..f70122d75
--- /dev/null
+++ b/src/gui_amiga.h
@@ -0,0 +1,52 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Amiga GUI support by Michael Nielsen
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ *
+ * Amiga GUI header file.
+ */
+
+#if !defined(__GUI_AMIGA__H)
+#define __GUI_AMIGA__H
+
+#define SetAttrib(_ptr,_attrib,_value) ((_ptr)->_attrib=(_value))
+
+#if defined(FEAT_GUI_AMIGA)
+
+#include <intuition/intuition.h>
+
+enum event {
+ ev_NullEvent,
+ ev_MenuVerify,
+ ev_MenuPick,
+ ev_CloseWindow,
+ ev_NewSize,
+ ev_RefreshWindow,
+ ev_MouseButtons,
+ ev_MouseMove,
+ ev_GadgetDown,
+ ev_GadgetUp,
+ ev_KeyStroke,
+ ev_IntuiTicks,
+ ev_MenuHelp,
+ ev_GadgetHelp,
+
+ ev_Ignore
+};
+
+struct MyMenuItem {
+ struct MenuItem menuItem;
+ vimmenu_T *guiMenu;
+};
+
+union myMenuItemUnion {
+ struct MenuItem menuItem;
+ struct MyMenuItem myMenuItem;
+};
+
+#endif /* FEAT_GUI_AMIGA*/
+#endif /* __GUI_AMIGA__H */
+
diff --git a/src/gui_at_fs.c b/src/gui_at_fs.c
new file mode 100644
index 000000000..474967ecb
--- /dev/null
+++ b/src/gui_at_fs.c
@@ -0,0 +1,2880 @@
+/* vi:set ts=8 sts=4 sw=4: */
+
+/*
+ * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Software Research Associates not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Software Research Associates
+ * makes no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Erik M. van der Poel
+ * Software Research Associates, Inc., Tokyo, Japan
+ * erik@sra.co.jp
+ */
+/*
+ * Author's addresses:
+ * erik@sra.co.jp
+ * erik%sra.co.jp@uunet.uu.net
+ * erik%sra.co.jp@mcvax.uucp
+ * try junet instead of co.jp
+ * Erik M. van der Poel
+ * Software Research Associates, Inc.
+ * 1-1-1 Hirakawa-cho, Chiyoda-ku
+ * Tokyo 102 Japan. TEL +81-3-234-2692
+ */
+
+/*
+ * Heavely modified for Vim by Bram Moolenaar
+ */
+
+#include "vim.h"
+
+/* Only include this when using the file browser */
+
+#ifdef FEAT_BROWSE
+
+/* Weird complication: for "make lint" Text.h doesn't combine with Xm.h */
+#if defined(FEAT_GUI_MOTIF) && defined(FMT8BIT)
+# undef FMT8BIT
+#endif
+
+#ifndef FEAT_GUI_NEXTAW
+# include "gui_at_sb.h"
+#endif
+
+/***************** SFinternal.h */
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xos.h>
+#ifdef FEAT_GUI_NEXTAW
+# include <X11/neXtaw/Text.h>
+# include <X11/neXtaw/AsciiText.h>
+# include <X11/neXtaw/Scrollbar.h>
+#else
+# include <X11/Xaw/Text.h>
+# include <X11/Xaw/AsciiText.h>
+#endif
+
+#define SEL_FILE_CANCEL -1
+#define SEL_FILE_OK 0
+#define SEL_FILE_NULL 1
+#define SEL_FILE_TEXT 2
+
+#define SF_DO_SCROLL 1
+#define SF_DO_NOT_SCROLL 0
+
+typedef struct
+{
+ int statDone;
+ char *real;
+ char *shown;
+} SFEntry;
+
+typedef struct
+{
+ char *dir;
+ char *path;
+ SFEntry *entries;
+ int nEntries;
+ int vOrigin;
+ int nChars;
+ int hOrigin;
+ int changed;
+ int beginSelection;
+ int endSelection;
+ time_t mtime;
+} SFDir;
+
+static char SFstartDir[MAXPATHL],
+ SFcurrentPath[MAXPATHL],
+ SFcurrentDir[MAXPATHL];
+
+static Widget selFile,
+ selFileField,
+ selFileForm,
+ selFileHScroll,
+ selFileHScrolls[3],
+ selFileLists[3],
+ selFileOK,
+ selFileCancel,
+ selFilePrompt,
+ selFileVScrolls[3];
+
+static Display *SFdisplay;
+
+static int SFcharWidth, SFcharAscent, SFcharHeight;
+
+static SFDir *SFdirs = NULL;
+
+static int SFdirEnd;
+static int SFdirPtr;
+
+static Pixel SFfore, SFback;
+
+static Atom SFwmDeleteWindow;
+
+static XSegment SFsegs[2], SFcompletionSegs[2];
+
+static XawTextPosition SFtextPos;
+
+static int SFupperX, SFlowerY, SFupperY;
+
+static int SFtextX, SFtextYoffset;
+
+static int SFentryWidth, SFentryHeight;
+
+static int SFlineToTextH = 3;
+static int SFlineToTextV = 3;
+
+static int SFbesideText = 3;
+static int SFaboveAndBelowText = 2;
+
+static int SFcharsPerEntry = 15;
+
+static int SFlistSize = 10;
+
+static int SFcurrentInvert[3] = { -1, -1, -1 };
+
+static int SFworkProcAdded = 0;
+
+static XtAppContext SFapp;
+
+static int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
+
+#ifdef FEAT_XFONTSET
+static char SFtextBuffer[MAXPATHL*sizeof(wchar_t)];
+#else
+static char SFtextBuffer[MAXPATHL];
+#endif
+
+static int SFbuttonPressed = 0;
+
+static XtIntervalId SFdirModTimerId;
+
+static int (*SFfunc)();
+
+static int SFstatus = SEL_FILE_NULL;
+
+/***************** static functions */
+
+static void SFsetText __ARGS((char *path));
+static void SFtextChanged __ARGS((void));
+static char *SFgetText __ARGS((void));
+static void SFupdatePath __ARGS((void));
+static int SFgetDir __ARGS((SFDir *dir));
+static void SFdrawLists __ARGS((int doScroll));
+static void SFdrawList __ARGS((int n, int doScroll));
+static void SFclearList __ARGS((int n, int doScroll));
+static void SFbuttonPressList __ARGS((Widget w, int n, XButtonPressedEvent *event));
+static void SFbuttonReleaseList __ARGS((Widget w, int n, XButtonReleasedEvent *event));
+static void SFdirModTimer __ARGS((XtPointer cl, XtIntervalId *id));
+static char SFstatChar __ARGS((struct stat *statBuf));
+static void SFdrawStrings __ARGS((Window w, SFDir *dir, int from, int to));
+static int SFnewInvertEntry __ARGS((int n, XMotionEvent *event));
+static void SFinvertEntry __ARGS((int n));
+static void SFenterList __ARGS((Widget w, int n, XEnterWindowEvent *event));
+static void SFleaveList __ARGS((Widget w, int n, XEvent *event));
+static void SFmotionList __ARGS((Widget w, int n, XMotionEvent *event));
+static void SFvFloatSliderMovedCallback __ARGS((Widget w, XtPointer n, XtPointer fnew));
+static void SFvSliderMovedCallback __ARGS((Widget w, int n, int nw));
+static void SFvAreaSelectedCallback __ARGS((Widget w, XtPointer n, XtPointer pnew));
+static void SFhSliderMovedCallback __ARGS((Widget w, XtPointer n, XtPointer nw));
+static void SFhAreaSelectedCallback __ARGS((Widget w, XtPointer n, XtPointer pnew));
+static void SFpathSliderMovedCallback __ARGS((Widget w, XtPointer client_data, XtPointer nw));
+static void SFpathAreaSelectedCallback __ARGS((Widget w, XtPointer client_data, XtPointer pnew));
+static Boolean SFworkProc __ARGS((void));
+static int SFcompareEntries __ARGS((const void *p, const void *q));
+static void SFprepareToReturn __ARGS((void));
+static void SFcreateWidgets __ARGS((Widget toplevel, char *prompt, char *ok, char *cancel));
+static void SFsetColors __ARGS((guicolor_T bg, guicolor_T fg, guicolor_T scroll_bg, guicolor_T scrollfg));
+
+/***************** xstat.h */
+
+#ifndef S_IXUSR
+# define S_IXUSR 0100
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0010
+#endif
+#ifndef S_IXOTH
+# define S_IXOTH 0001
+#endif
+
+#define S_ISXXX(m) ((m) & (S_IXUSR | S_IXGRP | S_IXOTH))
+
+/***************** Path.c */
+
+#include <pwd.h>
+
+typedef struct
+{
+ char *name;
+ char *dir;
+} SFLogin;
+
+static int SFdoNotTouchDirPtr = 0;
+
+static int SFdoNotTouchVorigin = 0;
+
+static SFDir SFrootDir, SFhomeDir;
+
+static SFLogin *SFlogins;
+
+static int SFtwiddle = 0;
+
+static int SFchdir __ARGS((char *path));
+
+ static int
+SFchdir(path)
+ char *path;
+{
+ int result;
+
+ result = 0;
+
+ if (strcmp(path, SFcurrentDir))
+ {
+ result = mch_chdir(path);
+ if (!result)
+ (void) strcpy(SFcurrentDir, path);
+ }
+
+ return result;
+}
+
+static void SFfree __ARGS((int i));
+
+ static void
+SFfree(i)
+ int i;
+{
+ SFDir *dir;
+ int j;
+
+ dir = &(SFdirs[i]);
+
+ for (j = dir->nEntries - 1; j >= 0; j--)
+ {
+ if (dir->entries[j].shown != dir->entries[j].real)
+ XtFree(dir->entries[j].shown);
+ XtFree(dir->entries[j].real);
+ }
+
+ XtFree((char *)dir->entries);
+ XtFree(dir->dir);
+
+ dir->dir = NULL;
+}
+
+static void SFstrdup __ARGS((char **s1, char *s2));
+
+ static void
+SFstrdup(s1, s2)
+ char **s1;
+ char *s2;
+{
+ *s1 = strcpy(XtMalloc((unsigned)(strlen(s2) + 1)), s2);
+}
+
+static void SFunreadableDir __ARGS((SFDir *dir));
+
+ static void
+SFunreadableDir(dir)
+ SFDir *dir;
+{
+ char *cannotOpen = _("<cannot open> ");
+
+ dir->entries = (SFEntry *) XtMalloc(sizeof(SFEntry));
+ dir->entries[0].statDone = 1;
+ SFstrdup(&dir->entries[0].real, cannotOpen);
+ dir->entries[0].shown = dir->entries[0].real;
+ dir->nEntries = 1;
+ dir->nChars = strlen(cannotOpen);
+}
+
+static void SFreplaceText __ARGS((SFDir *dir, char *str));
+
+ static void
+SFreplaceText(dir, str)
+ SFDir *dir;
+ char *str;
+{
+ int len;
+
+ *(dir->path) = 0;
+ len = strlen(str);
+ if (str[len - 1] == '/')
+ (void) strcat(SFcurrentPath, str);
+ else
+ (void) strncat(SFcurrentPath, str, len - 1);
+ if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
+ SFsetText(SFcurrentPath);
+ else
+ SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
+
+ SFtextChanged();
+}
+
+static void SFexpand __ARGS((char *str));
+
+ static void
+SFexpand(str)
+ char *str;
+{
+ int len;
+ int cmp;
+ char *name, *growing;
+ SFDir *dir;
+ SFEntry *entry, *max;
+
+ len = strlen(str);
+
+ dir = &(SFdirs[SFdirEnd - 1]);
+
+ if (dir->beginSelection == -1)
+ {
+ SFstrdup(&str, str);
+ SFreplaceText(dir, str);
+ XtFree(str);
+ return;
+ }
+ else if (dir->beginSelection == dir->endSelection)
+ {
+ SFreplaceText(dir, dir->entries[dir->beginSelection].shown);
+ return;
+ }
+
+ max = &(dir->entries[dir->endSelection + 1]);
+
+ name = dir->entries[dir->beginSelection].shown;
+ SFstrdup(&growing, name);
+
+ cmp = 0;
+ while (!cmp)
+ {
+ entry = &(dir->entries[dir->beginSelection]);
+ while (entry < max)
+ {
+ if ((cmp = strncmp(growing, entry->shown, len)))
+ break;
+ entry++;
+ }
+ len++;
+ }
+
+ /*
+ * SFreplaceText() expects filename
+ */
+ growing[len - 2] = ' ';
+
+ growing[len - 1] = 0;
+ SFreplaceText(dir, growing);
+ XtFree(growing);
+}
+
+static int SFfindFile __ARGS((SFDir *dir, char *str));
+
+ static int
+SFfindFile(dir, str)
+ SFDir *dir;
+ char *str;
+{
+ int i, last, max;
+ char *name, save;
+ SFEntry *entries;
+ int len;
+ int begin, end;
+ int result;
+
+ len = strlen(str);
+
+ if (str[len - 1] == ' ')
+ {
+ SFexpand(str);
+ return 1;
+ }
+ else if (str[len - 1] == '/')
+ len--;
+
+ max = dir->nEntries;
+
+ entries = dir->entries;
+
+ i = 0;
+ while (i < max)
+ {
+ name = entries[i].shown;
+ last = strlen(name) - 1;
+ save = name[last];
+ name[last] = 0;
+
+ result = strncmp(str, name, len);
+
+ name[last] = save;
+ if (result <= 0)
+ break;
+ i++;
+ }
+ begin = i;
+ while (i < max)
+ {
+ name = entries[i].shown;
+ last = strlen(name) - 1;
+ save = name[last];
+ name[last] = 0;
+
+ result = strncmp(str, name, len);
+
+ name[last] = save;
+ if (result)
+ break;
+ i++;
+ }
+ end = i;
+
+ if (begin != end)
+ {
+ if ((dir->beginSelection != begin) || (dir->endSelection != end - 1))
+ {
+ dir->changed = 1;
+ dir->beginSelection = begin;
+ if (str[strlen(str) - 1] == '/')
+ dir->endSelection = begin;
+ else
+ dir->endSelection = end - 1;
+ }
+ }
+ else if (dir->beginSelection != -1)
+ {
+ dir->changed = 1;
+ dir->beginSelection = -1;
+ dir->endSelection = -1;
+ }
+
+ if (SFdoNotTouchVorigin
+ || ((begin > dir->vOrigin) && (end < dir->vOrigin + SFlistSize)))
+ {
+ SFdoNotTouchVorigin = 0;
+ return 0;
+ }
+
+ i = begin - 1;
+ if (i > max - SFlistSize)
+ i = max - SFlistSize;
+ if (i < 0)
+ i = 0;
+
+ if (dir->vOrigin != i)
+ {
+ dir->vOrigin = i;
+ dir->changed = 1;
+ }
+
+ return 0;
+}
+
+static void SFunselect __ARGS((void));
+
+ static void
+SFunselect()
+{
+ SFDir *dir;
+
+ dir = &(SFdirs[SFdirEnd - 1]);
+ if (dir->beginSelection != -1)
+ dir->changed = 1;
+ dir->beginSelection = -1;
+ dir->endSelection = -1;
+}
+
+static int SFcompareLogins __ARGS((const void *p, const void *q));
+
+ static int
+SFcompareLogins(p, q)
+ const void *p, *q;
+{
+ return strcmp(((SFLogin *)p)->name, ((SFLogin *)q)->name);
+}
+
+static void SFgetHomeDirs __ARGS((void));
+
+ static void
+SFgetHomeDirs()
+{
+ struct passwd *pw;
+ int Alloc;
+ int i;
+ SFEntry *entries = NULL;
+ int len;
+ int maxChars;
+
+ Alloc = 1;
+ i = 1;
+ entries = (SFEntry *)XtMalloc(sizeof(SFEntry));
+ SFlogins = (SFLogin *)XtMalloc(sizeof(SFLogin));
+ entries[0].real = XtMalloc(3);
+ (void) strcpy(entries[0].real, "~");
+ entries[0].shown = entries[0].real;
+ entries[0].statDone = 1;
+ SFlogins[0].name = "";
+ pw = getpwuid((int) getuid());
+ SFstrdup(&SFlogins[0].dir, pw ? pw->pw_dir : "/");
+ maxChars = 0;
+
+ (void) setpwent();
+
+ while ((pw = getpwent()) && (*(pw->pw_name)))
+ {
+ if (i >= Alloc)
+ {
+ Alloc *= 2;
+ entries = (SFEntry *) XtRealloc((char *)entries,
+ (unsigned)(Alloc * sizeof(SFEntry)));
+ SFlogins = (SFLogin *) XtRealloc((char *)SFlogins,
+ (unsigned)(Alloc * sizeof(SFLogin)));
+ }
+ len = strlen(pw->pw_name);
+ entries[i].real = XtMalloc((unsigned) (len + 3));
+ (void) strcat(strcpy(entries[i].real, "~"), pw->pw_name);
+ entries[i].shown = entries[i].real;
+ entries[i].statDone = 1;
+ if (len > maxChars)
+ maxChars = len;
+ SFstrdup(&SFlogins[i].name, pw->pw_name);
+ SFstrdup(&SFlogins[i].dir, pw->pw_dir);
+ i++;
+ }
+
+ SFhomeDir.dir = XtMalloc(1);
+ SFhomeDir.dir[0] = 0;
+ SFhomeDir.path = SFcurrentPath;
+ SFhomeDir.entries = entries;
+ SFhomeDir.nEntries = i;
+ SFhomeDir.vOrigin = 0; /* :-) */
+ SFhomeDir.nChars = maxChars + 2;
+ SFhomeDir.hOrigin = 0;
+ SFhomeDir.changed = 1;
+ SFhomeDir.beginSelection = -1;
+ SFhomeDir.endSelection = -1;
+
+ qsort((char *)entries, (size_t)i, sizeof(SFEntry), SFcompareEntries);
+ qsort((char *)SFlogins, (size_t)i, sizeof(SFLogin), SFcompareLogins);
+
+ for (i--; i >= 0; i--)
+ (void)strcat(entries[i].real, "/");
+}
+
+static int SFfindHomeDir __ARGS((char *begin, char *end));
+
+ static int
+SFfindHomeDir(begin, end)
+ char *begin, *end;
+{
+ char save;
+ char *theRest;
+ int i;
+
+ save = *end;
+ *end = 0;
+
+ for (i = SFhomeDir.nEntries - 1; i >= 0; i--)
+ {
+ if (!strcmp(SFhomeDir.entries[i].real, begin))
+ {
+ *end = save;
+ SFstrdup(&theRest, end);
+ (void) strcat(strcat(strcpy(SFcurrentPath,
+ SFlogins[i].dir), "/"), theRest);
+ XtFree(theRest);
+ SFsetText(SFcurrentPath);
+ SFtextChanged();
+ return 1;
+ }
+ }
+
+ *end = save;
+
+ return 0;
+}
+
+ static void
+SFupdatePath()
+{
+ static int Alloc;
+ static int wasTwiddle = 0;
+ char *begin, *end;
+ int i, j;
+ int prevChange;
+ int SFdirPtrSave, SFdirEndSave;
+ SFDir *dir;
+
+ if (!SFdirs)
+ {
+ SFdirs = (SFDir *) XtMalloc((Alloc = 10) * sizeof(SFDir));
+ dir = &(SFdirs[0]);
+ SFstrdup(&dir->dir, "/");
+ (void) SFchdir("/");
+ (void) SFgetDir(dir);
+ for (j = 1; j < Alloc; j++)
+ SFdirs[j].dir = NULL;
+ dir->path = SFcurrentPath + 1;
+ dir->vOrigin = 0;
+ dir->hOrigin = 0;
+ dir->changed = 1;
+ dir->beginSelection = -1;
+ dir->endSelection = -1;
+ SFhomeDir.dir = NULL;
+ }
+
+ SFdirEndSave = SFdirEnd;
+ SFdirEnd = 1;
+
+ SFdirPtrSave = SFdirPtr;
+ SFdirPtr = 0;
+
+ begin = NULL;
+
+ if (SFcurrentPath[0] == '~')
+ {
+ if (!SFtwiddle)
+ {
+ SFtwiddle = 1;
+ dir = &(SFdirs[0]);
+ SFrootDir = *dir;
+ if (!SFhomeDir.dir)
+ SFgetHomeDirs();
+ *dir = SFhomeDir;
+ dir->changed = 1;
+ }
+ end = SFcurrentPath;
+ SFdoNotTouchDirPtr = 1;
+ wasTwiddle = 1;
+ }
+ else
+ {
+ if (SFtwiddle)
+ {
+ SFtwiddle = 0;
+ dir = &(SFdirs[0]);
+ *dir = SFrootDir;
+ dir->changed = 1;
+ }
+ end = SFcurrentPath + 1;
+ }
+
+ i = 0;
+
+ prevChange = 0;
+
+ while (*end)
+ {
+ while (*end++ == '/')
+ ;
+ end--;
+ begin = end;
+ while ((*end) && (*end++ != '/'))
+ ;
+ if ((end - SFcurrentPath <= SFtextPos) && (*(end - 1) == '/'))
+ {
+ SFdirPtr = i - 1;
+ if (SFdirPtr < 0)
+ SFdirPtr = 0;
+ }
+ if (*begin)
+ {
+ if (*(end - 1) == '/')
+ {
+ char save = *end;
+
+ if (SFtwiddle)
+ {
+ if (SFfindHomeDir(begin, end))
+ return;
+ }
+ *end = 0;
+ i++;
+ SFdirEnd++;
+ if (i >= Alloc)
+ {
+ SFdirs = (SFDir *) XtRealloc((char *) SFdirs,
+ (unsigned)((Alloc *= 2) * sizeof(SFDir)));
+ for (j = Alloc / 2; j < Alloc; j++)
+ SFdirs[j].dir = NULL;
+ }
+ dir = &(SFdirs[i]);
+ if ((!(dir->dir)) || prevChange || strcmp(dir->dir, begin))
+ {
+ if (dir->dir)
+ SFfree(i);
+ prevChange = 1;
+ SFstrdup(&dir->dir, begin);
+ dir->path = end;
+ dir->vOrigin = 0;
+ dir->hOrigin = 0;
+ dir->changed = 1;
+ dir->beginSelection = -1;
+ dir->endSelection = -1;
+ (void)SFfindFile(dir - 1, begin);
+ if (SFchdir(SFcurrentPath) || SFgetDir(dir))
+ {
+ SFunreadableDir(dir);
+ break;
+ }
+ }
+ *end = save;
+ if (!save)
+ SFunselect();
+ }
+ else
+ {
+ if (SFfindFile(&(SFdirs[SFdirEnd-1]), begin))
+ return;
+ }
+ }
+ else
+ SFunselect();
+ }
+
+ if ((end == SFcurrentPath + 1) && (!SFtwiddle))
+ SFunselect();
+
+ for (i = SFdirEnd; i < Alloc; i++)
+ if (SFdirs[i].dir)
+ SFfree(i);
+
+ if (SFdoNotTouchDirPtr)
+ {
+ if (wasTwiddle)
+ {
+ wasTwiddle = 0;
+ SFdirPtr = SFdirEnd - 2;
+ if (SFdirPtr < 0)
+ SFdirPtr = 0;
+ }
+ else
+ SFdirPtr = SFdirPtrSave;
+ SFdoNotTouchDirPtr = 0;
+ }
+
+ if ((SFdirPtr != SFdirPtrSave) || (SFdirEnd != SFdirEndSave))
+ {
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb( selFileHScroll,
+ (float) (((double) SFdirPtr) / SFdirEnd),
+ (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
+ SFdirEnd));
+#else
+ vim_XawScrollbarSetThumb( selFileHScroll,
+ (float) (((double) SFdirPtr) / SFdirEnd),
+ (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
+ SFdirEnd),
+ (double)SFdirEnd);
+#endif
+ }
+
+ if (SFdirPtr != SFdirPtrSave)
+ SFdrawLists(SF_DO_SCROLL);
+ else
+ for (i = 0; i < 3; i++)
+ {
+ if (SFdirPtr + i < SFdirEnd)
+ {
+ if (SFdirs[SFdirPtr + i].changed)
+ {
+ SFdirs[SFdirPtr + i].changed = 0;
+ SFdrawList(i, SF_DO_SCROLL);
+ }
+ }
+ else
+ SFclearList(i, SF_DO_SCROLL);
+ }
+}
+
+#ifdef XtNinternational
+ static int
+WcsLen(p)
+ wchar_t *p;
+{
+ int i = 0;
+ while (*p++ != 0)
+ i++;
+ return i;
+}
+#endif
+
+ static void
+SFsetText(path)
+ char *path;
+{
+ XawTextBlock text;
+
+ text.firstPos = 0;
+ text.length = strlen(path);
+ text.ptr = path;
+ text.format = FMT8BIT;
+
+#ifdef XtNinternational
+ if (_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
+ {
+ XawTextReplace(selFileField, (XawTextPosition)0,
+ (XawTextPosition)WcsLen((wchar_t *)&SFtextBuffer[0]), &text);
+ XawTextSetInsertionPoint(selFileField,
+ (XawTextPosition)WcsLen((wchar_t *)&SFtextBuffer[0]));
+ }
+ else
+ {
+ XawTextReplace(selFileField, (XawTextPosition)0,
+ (XawTextPosition)strlen(SFtextBuffer), &text);
+ XawTextSetInsertionPoint(selFileField,
+ (XawTextPosition)strlen(SFtextBuffer));
+ }
+#else
+ XawTextReplace(selFileField, (XawTextPosition)0,
+ (XawTextPosition)strlen(SFtextBuffer), &text);
+ XawTextSetInsertionPoint(selFileField,
+ (XawTextPosition)strlen(SFtextBuffer));
+#endif
+}
+
+/* ARGSUSED */
+ static void
+SFbuttonPressList(w, n, event)
+ Widget w;
+ int n;
+ XButtonPressedEvent *event;
+{
+ SFbuttonPressed = 1;
+}
+
+/* ARGSUSED */
+ static void
+SFbuttonReleaseList(w, n, event)
+ Widget w;
+ int n;
+ XButtonReleasedEvent *event;
+{
+ SFDir *dir;
+
+ SFbuttonPressed = 0;
+
+ if (SFcurrentInvert[n] != -1)
+ {
+ if (n < 2)
+ SFdoNotTouchDirPtr = 1;
+ SFdoNotTouchVorigin = 1;
+ dir = &(SFdirs[SFdirPtr + n]);
+ SFreplaceText(dir,
+ dir->entries[dir->vOrigin + SFcurrentInvert[n]].shown);
+ SFmotionList(w, n, (XMotionEvent *) event);
+ }
+}
+
+static int SFcheckDir __ARGS((int n, SFDir *dir));
+
+ static int
+SFcheckDir(n, dir)
+ int n;
+ SFDir *dir;
+{
+ struct stat statBuf;
+ int i;
+
+ if ((!mch_stat(".", &statBuf)) && (statBuf.st_mtime != dir->mtime))
+ {
+ /*
+ * If the pointer is currently in the window that we are about
+ * to update, we must warp it to prevent the user from
+ * accidentally selecting the wrong file.
+ */
+ if (SFcurrentInvert[n] != -1)
+ {
+ XWarpPointer(
+ SFdisplay,
+ None,
+ XtWindow(selFileLists[n]),
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0);
+ }
+
+ for (i = dir->nEntries - 1; i >= 0; i--)
+ {
+ if (dir->entries[i].shown != dir->entries[i].real)
+ XtFree(dir->entries[i].shown);
+ XtFree(dir->entries[i].real);
+ }
+ XtFree((char *) dir->entries);
+ if (SFgetDir(dir))
+ SFunreadableDir(dir);
+ if (dir->vOrigin > dir->nEntries - SFlistSize)
+ dir->vOrigin = dir->nEntries - SFlistSize;
+ if (dir->vOrigin < 0)
+ dir->vOrigin = 0;
+ if (dir->hOrigin > dir->nChars - SFcharsPerEntry)
+ dir->hOrigin = dir->nChars - SFcharsPerEntry;
+ if (dir->hOrigin < 0)
+ dir->hOrigin = 0;
+ dir->beginSelection = -1;
+ dir->endSelection = -1;
+ SFdoNotTouchVorigin = 1;
+ if ((dir + 1)->dir)
+ (void) SFfindFile(dir, (dir + 1)->dir);
+ else
+ (void) SFfindFile(dir, dir->path);
+
+ if (!SFworkProcAdded)
+ {
+ (void) XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
+ SFworkProcAdded = 1;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+static int SFcheckFiles __ARGS((SFDir *dir));
+
+ static int
+SFcheckFiles(dir)
+ SFDir *dir;
+{
+ int from, to;
+ int result;
+ char oldc, newc;
+ int i;
+ char *str;
+ int last;
+ struct stat statBuf;
+
+ result = 0;
+
+ from = dir->vOrigin;
+ to = dir->vOrigin + SFlistSize;
+ if (to > dir->nEntries)
+ to = dir->nEntries;
+
+ for (i = from; i < to; i++)
+ {
+ str = dir->entries[i].real;
+ last = strlen(str) - 1;
+ oldc = str[last];
+ str[last] = 0;
+ if (mch_stat(str, &statBuf))
+ newc = ' ';
+ else
+ newc = SFstatChar(&statBuf);
+ str[last] = newc;
+ if (newc != oldc)
+ result = 1;
+ }
+
+ return result;
+}
+
+/* ARGSUSED */
+ static void
+SFdirModTimer(cl, id)
+ XtPointer cl;
+ XtIntervalId *id;
+{
+ static int n = -1;
+ static int f = 0;
+ char save;
+ SFDir *dir;
+
+ if ((!SFtwiddle) && (SFdirPtr < SFdirEnd))
+ {
+ n++;
+ if ((n > 2) || (SFdirPtr + n >= SFdirEnd))
+ {
+ n = 0;
+ f++;
+ if ((f > 2) || (SFdirPtr + f >= SFdirEnd))
+ f = 0;
+ }
+ dir = &(SFdirs[SFdirPtr + n]);
+ save = *(dir->path);
+ *(dir->path) = 0;
+ if (SFchdir(SFcurrentPath))
+ {
+ *(dir->path) = save;
+
+ /*
+ * force a re-read
+ */
+ *(dir->dir) = 0;
+
+ SFupdatePath();
+ }
+ else
+ {
+ *(dir->path) = save;
+ if (SFcheckDir(n, dir) || ((f == n) && SFcheckFiles(dir)))
+ SFdrawList(n, SF_DO_SCROLL);
+ }
+ }
+
+ SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
+ SFdirModTimer, (XtPointer) NULL);
+}
+
+/* Return a single character describing what kind of file STATBUF is. */
+
+ static char
+SFstatChar(statBuf)
+ struct stat *statBuf;
+{
+ if (S_ISDIR (statBuf->st_mode))
+ return '/';
+ if (S_ISREG (statBuf->st_mode))
+ return S_ISXXX (statBuf->st_mode) ? '*' : ' ';
+#ifdef S_ISSOCK
+ if (S_ISSOCK (statBuf->st_mode))
+ return '=';
+#endif /* S_ISSOCK */
+ return ' ';
+}
+
+/***************** Draw.c */
+
+#ifdef FEAT_GUI_NEXTAW
+# include <X11/neXtaw/Cardinals.h>
+#else
+# include <X11/Xaw/Cardinals.h>
+#endif
+
+#ifdef FEAT_XFONTSET
+# define SF_DEFAULT_FONT "-misc-fixed-medium-r-normal--14-*"
+#else
+# define SF_DEFAULT_FONT "9x15"
+#endif
+
+#ifdef ABS
+# undef ABS
+#endif
+#define ABS(x) (((x) < 0) ? (-(x)) : (x))
+
+typedef struct
+{
+ char *fontname;
+} TextData;
+
+static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
+
+static XtResource textResources[] =
+{
+#ifdef FEAT_XFONTSET
+ {XtNfontSet, XtCFontSet, XtRString, sizeof (char *),
+ XtOffsetOf(TextData, fontname), XtRString, SF_DEFAULT_FONT},
+#else
+ {XtNfont, XtCFont, XtRString, sizeof (char *),
+ XtOffsetOf(TextData, fontname), XtRString, SF_DEFAULT_FONT},
+#endif
+};
+
+#ifdef FEAT_XFONTSET
+static XFontSet SFfont;
+#else
+static XFontStruct *SFfont;
+#endif
+
+static int SFcurrentListY;
+
+static XtIntervalId SFscrollTimerId;
+
+static void SFinitFont __ARGS((void));
+
+ static void
+SFinitFont()
+{
+ TextData *data;
+#ifdef FEAT_XFONTSET
+ XFontSetExtents *extents;
+ char **missing, *def_str;
+ int num_missing;
+#endif
+
+ data = XtNew(TextData);
+
+ XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
+ XtNumber(textResources), (Arg *) NULL, ZERO);
+
+#ifdef FEAT_XFONTSET
+ SFfont = XCreateFontSet(SFdisplay, data->fontname,
+ &missing, &num_missing, &def_str);
+#else
+ SFfont = XLoadQueryFont(SFdisplay, data->fontname);
+#endif
+ if (!SFfont)
+ {
+#ifdef FEAT_XFONTSET
+ SFfont = XCreateFontSet(SFdisplay, SF_DEFAULT_FONT,
+ &missing, &num_missing, &def_str);
+#else
+ SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
+#endif
+ if (!SFfont)
+ {
+ EMSG2(_("E616: vim_SelFile: can't get font %s"), SF_DEFAULT_FONT);
+ SFstatus = SEL_FILE_CANCEL;
+ return;
+ }
+ }
+
+#ifdef FEAT_XFONTSET
+ extents = XExtentsOfFontSet(SFfont);
+ SFcharWidth = extents->max_logical_extent.width;
+ SFcharAscent = -extents->max_logical_extent.y;
+ SFcharHeight = extents->max_logical_extent.height;
+#else
+ SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
+ SFcharAscent = SFfont->max_bounds.ascent;
+ SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
+#endif
+}
+
+static void SFcreateGC __ARGS((void));
+
+ static void
+SFcreateGC()
+{
+ XGCValues gcValues;
+ XRectangle rectangles[1];
+
+ gcValues.foreground = SFfore;
+
+ SFlineGC = XtGetGC(
+ selFileLists[0],
+ (XtGCMask)GCForeground,
+ &gcValues);
+
+ SFscrollGC = XtGetGC(
+ selFileLists[0],
+ (XtGCMask)0,
+ &gcValues);
+
+ gcValues.function = GXxor;
+ gcValues.foreground = SFfore ^ SFback;
+ gcValues.background = SFfore ^ SFback;
+
+ SFinvertGC = XtGetGC(
+ selFileLists[0],
+ (XtGCMask)GCFunction | GCForeground | GCBackground,
+ &gcValues);
+
+ gcValues.foreground = SFfore;
+ gcValues.background = SFback;
+#ifndef FEAT_XFONTSET
+ gcValues.font = SFfont->fid;
+#endif
+
+ SFtextGC = XCreateGC(
+ SFdisplay,
+ XtWindow(selFileLists[0]),
+#ifdef FEAT_XFONTSET
+ (unsigned long)GCForeground | GCBackground,
+#else
+ (unsigned long)GCForeground | GCBackground | GCFont,
+#endif
+ &gcValues);
+
+ rectangles[0].x = SFlineToTextH + SFbesideText;
+ rectangles[0].y = 0;
+ rectangles[0].width = SFcharsPerEntry * SFcharWidth;
+ rectangles[0].height = SFupperY + 1;
+
+ XSetClipRectangles(
+ SFdisplay,
+ SFtextGC,
+ 0,
+ 0,
+ rectangles,
+ 1,
+ Unsorted);
+}
+
+ static void
+SFclearList(n, doScroll)
+ int n;
+ int doScroll;
+{
+ SFDir *dir;
+
+ SFcurrentInvert[n] = -1;
+
+ XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
+
+ XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs, 2);
+
+ if (doScroll)
+ {
+ dir = &(SFdirs[SFdirPtr + n]);
+
+ if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars)
+ {
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb(
+ selFileVScrolls[n],
+ (float) (((double) dir->vOrigin) /
+ dir->nEntries),
+ (float) (((double) ((dir->nEntries < SFlistSize)
+ ? dir->nEntries : SFlistSize)) /
+ dir->nEntries));
+#else
+ vim_XawScrollbarSetThumb(
+ selFileVScrolls[n],
+ (float) (((double) dir->vOrigin) /
+ dir->nEntries),
+ (float) (((double) ((dir->nEntries < SFlistSize)
+ ? dir->nEntries : SFlistSize)) /
+ dir->nEntries),
+ (double)dir->nEntries);
+#endif
+
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb(
+ selFileHScrolls[n],
+ (float) (((double) dir->hOrigin) / dir->nChars),
+ (float) (((double) ((dir->nChars <
+ SFcharsPerEntry) ? dir->nChars :
+ SFcharsPerEntry)) / dir->nChars));
+#else
+ vim_XawScrollbarSetThumb(
+ selFileHScrolls[n],
+ (float) (((double) dir->hOrigin) / dir->nChars),
+ (float) (((double) ((dir->nChars <
+ SFcharsPerEntry) ? dir->nChars :
+ SFcharsPerEntry)) / dir->nChars),
+ (double)dir->nChars);
+#endif
+ }
+ else
+ {
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
+ (float) 1.0);
+#else
+ vim_XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
+ (float) 1.0, 1.0);
+#endif
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
+ (float) 1.0);
+#else
+ vim_XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
+ (float) 1.0, 1.0);
+#endif
+ }
+ }
+}
+
+static void SFdeleteEntry __ARGS((SFDir *dir, SFEntry *entry));
+
+ static void
+SFdeleteEntry(dir, entry)
+ SFDir *dir;
+ SFEntry *entry;
+{
+ SFEntry *e;
+ SFEntry *end;
+ int n;
+ int idx;
+
+ idx = entry - dir->entries;
+
+ if (idx < dir->beginSelection)
+ dir->beginSelection--;
+ if (idx <= dir->endSelection)
+ dir->endSelection--;
+ if (dir->beginSelection > dir->endSelection)
+ dir->beginSelection = dir->endSelection = -1;
+
+ if (idx < dir->vOrigin)
+ dir->vOrigin--;
+
+ XtFree(entry->real);
+
+ end = &(dir->entries[dir->nEntries - 1]);
+
+ for (e = entry; e < end; e++)
+ *e = *(e + 1);
+
+ if (!(--dir->nEntries))
+ return;
+
+ n = dir - &(SFdirs[SFdirPtr]);
+ if ((n < 0) || (n > 2))
+ return;
+
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb(
+ selFileVScrolls[n],
+ (float) (((double) dir->vOrigin) / dir->nEntries),
+ (float) (((double) ((dir->nEntries < SFlistSize) ?
+ dir->nEntries : SFlistSize)) / dir->nEntries));
+#else
+ vim_XawScrollbarSetThumb(
+ selFileVScrolls[n],
+ (float) (((double) dir->vOrigin) / dir->nEntries),
+ (float) (((double) ((dir->nEntries < SFlistSize) ?
+ dir->nEntries : SFlistSize)) / dir->nEntries),
+ (double)dir->nEntries);
+#endif
+}
+
+static void SFwriteStatChar __ARGS((char *name, int last, struct stat *statBuf));
+
+ static void
+SFwriteStatChar(name, last, statBuf)
+ char *name;
+ int last;
+ struct stat *statBuf;
+{
+ name[last] = SFstatChar(statBuf);
+}
+
+static int SFstatAndCheck __ARGS((SFDir *dir, SFEntry *entry));
+
+ static int
+SFstatAndCheck(dir, entry)
+ SFDir *dir;
+ SFEntry *entry;
+{
+ struct stat statBuf;
+ char save;
+ int last;
+
+ /*
+ * must be restored before returning
+ */
+ save = *(dir->path);
+ *(dir->path) = 0;
+
+ if (!SFchdir(SFcurrentPath))
+ {
+ last = strlen(entry->real) - 1;
+ entry->real[last] = 0;
+ entry->statDone = 1;
+ if ((!mch_stat(entry->real, &statBuf))
+#ifdef S_IFLNK
+ || (!mch_lstat(entry->real, &statBuf))
+#endif
+ )
+ {
+ if (SFfunc)
+ {
+ char *shown;
+
+ shown = NULL;
+ if (SFfunc(entry->real, &shown, &statBuf))
+ {
+ if (shown)
+ {
+ int len;
+
+ len = strlen(shown);
+ entry->shown = XtMalloc((unsigned) (len + 2));
+ (void) strcpy(entry->shown, shown);
+ SFwriteStatChar(entry->shown, len, &statBuf);
+ entry->shown[len + 1] = 0;
+ }
+ }
+ else
+ {
+ SFdeleteEntry(dir, entry);
+
+ *(dir->path) = save;
+ return 1;
+ }
+ }
+ SFwriteStatChar(entry->real, last, &statBuf);
+ }
+ else
+ entry->real[last] = ' ';
+ }
+
+ *(dir->path) = save;
+ return 0;
+}
+
+
+ static void
+SFdrawStrings(w, dir, from, to)
+ Window w;
+ SFDir *dir;
+ int from;
+ int to;
+{
+ int i;
+ SFEntry *entry;
+ int x;
+
+ x = SFtextX - dir->hOrigin * SFcharWidth;
+
+ if (dir->vOrigin + to >= dir->nEntries)
+ to = dir->nEntries - dir->vOrigin - 1;
+ for (i = from; i <= to; i++)
+ {
+ entry = &(dir->entries[dir->vOrigin + i]);
+ if (!(entry->statDone))
+ {
+ if (SFstatAndCheck(dir, entry))
+ {
+ if (dir->vOrigin + to >= dir->nEntries)
+ to = dir->nEntries - dir->vOrigin - 1;
+ i--;
+ continue;
+ }
+ }
+#ifdef FEAT_XFONTSET
+ XmbDrawImageString(
+ SFdisplay,
+ w,
+ SFfont,
+ SFtextGC,
+ x,
+ SFtextYoffset + i * SFentryHeight,
+ entry->shown,
+ strlen(entry->shown));
+#else
+ XDrawImageString(
+ SFdisplay,
+ w,
+ SFtextGC,
+ x,
+ SFtextYoffset + i * SFentryHeight,
+ entry->shown,
+ strlen(entry->shown));
+#endif
+ if (dir->vOrigin + i == dir->beginSelection)
+ {
+ XDrawLine(
+ SFdisplay,
+ w,
+ SFlineGC,
+ SFlineToTextH + 1,
+ SFlowerY + i * SFentryHeight,
+ SFlineToTextH + SFentryWidth - 2,
+ SFlowerY + i * SFentryHeight);
+ }
+ if ((dir->vOrigin + i >= dir->beginSelection) &&
+ (dir->vOrigin + i <= dir->endSelection))
+ {
+ SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
+ SFlowerY + i * SFentryHeight;
+ SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
+ SFlowerY + (i + 1) * SFentryHeight - 1;
+ XDrawSegments(
+ SFdisplay,
+ w,
+ SFlineGC,
+ SFcompletionSegs,
+ 2);
+ }
+ if (dir->vOrigin + i == dir->endSelection)
+ {
+ XDrawLine(
+ SFdisplay,
+ w,
+ SFlineGC,
+ SFlineToTextH + 1,
+ SFlowerY + (i + 1) * SFentryHeight - 1,
+ SFlineToTextH + SFentryWidth - 2,
+ SFlowerY + (i + 1) * SFentryHeight - 1);
+ }
+ }
+}
+
+ static void
+SFdrawList(n, doScroll)
+ int n;
+ int doScroll;
+{
+ SFDir *dir;
+ Window w;
+
+ SFclearList(n, doScroll);
+
+ if (SFdirPtr + n < SFdirEnd)
+ {
+ dir = &(SFdirs[SFdirPtr + n]);
+ w = XtWindow(selFileLists[n]);
+#ifdef FEAT_XFONTSET
+ XmbDrawImageString(
+ SFdisplay,
+ w,
+ SFfont,
+ SFtextGC,
+ SFtextX - dir->hOrigin * SFcharWidth,
+ SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
+ dir->dir,
+ strlen(dir->dir));
+#else
+ XDrawImageString(
+ SFdisplay,
+ w,
+ SFtextGC,
+ SFtextX - dir->hOrigin * SFcharWidth,
+ SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
+ dir->dir,
+ strlen(dir->dir));
+#endif
+ SFdrawStrings(w, dir, 0, SFlistSize - 1);
+ }
+}
+
+ static void
+SFdrawLists(doScroll)
+ int doScroll;
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ SFdrawList(i, doScroll);
+}
+
+ static void
+SFinvertEntry(n)
+ int n;
+{
+ XFillRectangle(
+ SFdisplay,
+ XtWindow(selFileLists[n]),
+ SFinvertGC,
+ SFlineToTextH,
+ SFcurrentInvert[n] * SFentryHeight + SFlowerY,
+ SFentryWidth,
+ SFentryHeight);
+}
+
+static unsigned long SFscrollTimerInterval __ARGS((void));
+
+ static unsigned long
+SFscrollTimerInterval()
+{
+ static int maxVal = 200;
+ static int varyDist = 50;
+ static int minDist = 50;
+ int t;
+ int dist;
+
+ if (SFcurrentListY < SFlowerY)
+ dist = SFlowerY - SFcurrentListY;
+ else if (SFcurrentListY > SFupperY)
+ dist = SFcurrentListY - SFupperY;
+ else
+ return (unsigned long) 1;
+
+ t = maxVal - ((maxVal / varyDist) * (dist - minDist));
+
+ if (t < 1)
+ t = 1;
+
+ if (t > maxVal)
+ t = maxVal;
+
+ return (unsigned long)t;
+}
+
+static void SFscrollTimer __ARGS((XtPointer p, XtIntervalId *id));
+
+/* ARGSUSED */
+ static void
+SFscrollTimer(p, id)
+ XtPointer p;
+ XtIntervalId *id;
+{
+ SFDir *dir;
+ int save;
+ int n;
+
+ n = (long)p;
+
+ dir = &(SFdirs[SFdirPtr + n]);
+ save = dir->vOrigin;
+
+ if (SFcurrentListY < SFlowerY)
+ {
+ if (dir->vOrigin > 0)
+ SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin - 1);
+ }
+ else if (SFcurrentListY > SFupperY)
+ {
+ if (dir->vOrigin < dir->nEntries - SFlistSize)
+ SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin + 1);
+ }
+
+ if (dir->vOrigin != save)
+ {
+ if (dir->nEntries)
+ {
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb(
+ selFileVScrolls[n],
+ (float) (((double) dir->vOrigin) / dir->nEntries),
+ (float) (((double) ((dir->nEntries < SFlistSize) ?
+ dir->nEntries : SFlistSize)) / dir->nEntries));
+#else
+ vim_XawScrollbarSetThumb(
+ selFileVScrolls[n],
+ (float) (((double) dir->vOrigin) / dir->nEntries),
+ (float) (((double) ((dir->nEntries < SFlistSize) ?
+ dir->nEntries : SFlistSize)) / dir->nEntries),
+ (double)dir->nEntries);
+#endif
+ }
+ }
+
+ if (SFbuttonPressed)
+ SFscrollTimerId = XtAppAddTimeOut(SFapp,
+ SFscrollTimerInterval(), SFscrollTimer, (XtPointer) n);
+}
+
+ static int
+SFnewInvertEntry(n, event)
+ int n;
+ XMotionEvent *event;
+{
+ int x, y;
+ int nw;
+ static int SFscrollTimerAdded = 0;
+
+ x = event->x;
+ y = event->y;
+
+ if (SFdirPtr + n >= SFdirEnd)
+ return -1;
+
+ if ((x >= 0) && (x <= SFupperX) && (y >= SFlowerY) && (y <= SFupperY))
+ {
+ SFDir *dir = &(SFdirs[SFdirPtr + n]);
+
+ if (SFscrollTimerAdded)
+ {
+ SFscrollTimerAdded = 0;
+ XtRemoveTimeOut(SFscrollTimerId);
+ }
+
+ nw = (y - SFlowerY) / SFentryHeight;
+ if (dir->vOrigin + nw >= dir->nEntries)
+ return -1;
+ return nw;
+ }
+ else
+ {
+ if (SFbuttonPressed)
+ {
+ SFcurrentListY = y;
+ if (!SFscrollTimerAdded)
+ {
+ SFscrollTimerAdded = 1;
+ SFscrollTimerId = XtAppAddTimeOut(SFapp,
+ SFscrollTimerInterval(), SFscrollTimer,
+ (XtPointer) n);
+ }
+ }
+ return -1;
+ }
+}
+
+/* ARGSUSED */
+ static void
+SFenterList(w, n, event)
+ Widget w;
+ int n;
+ XEnterWindowEvent *event;
+{
+ int nw;
+
+ /* sanity */
+ if (SFcurrentInvert[n] != -1)
+ {
+ SFinvertEntry(n);
+ SFcurrentInvert[n] = -1;
+ }
+
+ nw = SFnewInvertEntry(n, (XMotionEvent *) event);
+ if (nw != -1)
+ {
+ SFcurrentInvert[n] = nw;
+ SFinvertEntry(n);
+ }
+}
+
+/* ARGSUSED */
+ static void
+SFleaveList(w, n, event)
+ Widget w;
+ int n;
+ XEvent *event;
+{
+ if (SFcurrentInvert[n] != -1)
+ {
+ SFinvertEntry(n);
+ SFcurrentInvert[n] = -1;
+ }
+}
+
+/* ARGSUSED */
+ static void
+SFmotionList(w, n, event)
+ Widget w;
+ int n;
+ XMotionEvent *event;
+{
+ int nw;
+
+ nw = SFnewInvertEntry(n, event);
+
+ if (nw != SFcurrentInvert[n])
+ {
+ if (SFcurrentInvert[n] != -1)
+ SFinvertEntry(n);
+ SFcurrentInvert[n] = nw;
+ if (nw != -1)
+ SFinvertEntry(n);
+ }
+}
+
+/* ARGSUSED */
+ static void
+SFvFloatSliderMovedCallback(w, n, fnew)
+ Widget w;
+ XtPointer n;
+ XtPointer fnew;
+{
+ int nw;
+
+ nw = (*(float *)fnew) * SFdirs[SFdirPtr + (int)(long)n].nEntries;
+ SFvSliderMovedCallback(w, (int)(long)n, nw);
+}
+
+/* ARGSUSED */
+ static void
+SFvSliderMovedCallback(w, n, nw)
+ Widget w;
+ int n;
+ int nw;
+{
+ int old;
+ Window win;
+ SFDir *dir;
+
+ dir = &(SFdirs[SFdirPtr + n]);
+
+ old = dir->vOrigin;
+ dir->vOrigin = nw;
+
+ if (old == nw)
+ return;
+
+ win = XtWindow(selFileLists[n]);
+
+ if (ABS(nw - old) < SFlistSize)
+ {
+ if (nw > old)
+ {
+ XCopyArea(
+ SFdisplay,
+ win,
+ win,
+ SFscrollGC,
+ SFlineToTextH,
+ SFlowerY + (nw - old) * SFentryHeight,
+ SFentryWidth + SFlineToTextH,
+ (SFlistSize - (nw - old)) * SFentryHeight,
+ SFlineToTextH,
+ SFlowerY);
+ XClearArea(
+ SFdisplay,
+ win,
+ SFlineToTextH,
+ SFlowerY + (SFlistSize - (nw - old)) *
+ SFentryHeight,
+ SFentryWidth + SFlineToTextH,
+ (nw - old) * SFentryHeight,
+ False);
+ SFdrawStrings(win, dir, SFlistSize - (nw - old),
+ SFlistSize - 1);
+ }
+ else
+ {
+ XCopyArea(
+ SFdisplay,
+ win,
+ win,
+ SFscrollGC,
+ SFlineToTextH,
+ SFlowerY,
+ SFentryWidth + SFlineToTextH,
+ (SFlistSize - (old - nw)) * SFentryHeight,
+ SFlineToTextH,
+ SFlowerY + (old - nw) * SFentryHeight);
+ XClearArea(
+ SFdisplay,
+ win,
+ SFlineToTextH,
+ SFlowerY,
+ SFentryWidth + SFlineToTextH,
+ (old - nw) * SFentryHeight,
+ False);
+ SFdrawStrings(win, dir, 0, old - nw);
+ }
+ }
+ else
+ {
+ XClearArea(
+ SFdisplay,
+ win,
+ SFlineToTextH,
+ SFlowerY,
+ SFentryWidth + SFlineToTextH,
+ SFlistSize * SFentryHeight,
+ False);
+ SFdrawStrings(win, dir, 0, SFlistSize - 1);
+ }
+}
+
+/* ARGSUSED */
+ static void
+SFvAreaSelectedCallback(w, n, pnew)
+ Widget w;
+ XtPointer n;
+ XtPointer pnew;
+{
+ SFDir *dir;
+ int nw;
+
+ dir = &(SFdirs[SFdirPtr + (int)(long)n]);
+
+#ifdef FEAT_GUI_NEXTAW
+ if ((int)(long)pnew < 0)
+ {
+ if ((int)(long)pnew > -SFvScrollHeight)
+ (int)(long)pnew = -1;
+ else
+ (int)(long)pnew = -SFlistSize;
+ }
+ else if ((int)(long)pnew > 0)
+ {
+ if ((int)(long)pnew < SFvScrollHeight)
+ (int)(long)pnew = 1;
+ else
+ (int)(long)pnew = SFlistSize;
+ }
+#endif
+ nw = dir->vOrigin + (int)(long)pnew;
+
+ if (nw > dir->nEntries - SFlistSize)
+ nw = dir->nEntries - SFlistSize;
+
+ if (nw < 0)
+ nw = 0;
+
+ if (dir->nEntries)
+ {
+ float f;
+
+ f = ((double) nw) / dir->nEntries;
+
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb(
+ w,
+ f,
+ (float) (((double) ((dir->nEntries < SFlistSize) ?
+ dir->nEntries : SFlistSize)) / dir->nEntries));
+#else
+ vim_XawScrollbarSetThumb(
+ w,
+ f,
+ (float) (((double) ((dir->nEntries < SFlistSize) ?
+ dir->nEntries : SFlistSize)) / dir->nEntries),
+ (double)dir->nEntries);
+#endif
+ }
+
+ SFvSliderMovedCallback(w, (int)(long)n, nw);
+}
+
+/* ARGSUSED */
+ static void
+SFhSliderMovedCallback(w, n, nw)
+ Widget w;
+ XtPointer n;
+ XtPointer nw;
+{
+ SFDir *dir;
+ int save;
+
+ dir = &(SFdirs[SFdirPtr + (int)(long)n]);
+ save = dir->hOrigin;
+ dir->hOrigin = (*(float *)nw) * dir->nChars;
+ if (dir->hOrigin == save)
+ return;
+
+ SFdrawList((int)(long)n, SF_DO_NOT_SCROLL);
+}
+
+/* ARGSUSED */
+ static void
+SFhAreaSelectedCallback(w, n, pnew)
+ Widget w;
+ XtPointer n;
+ XtPointer pnew;
+{
+ SFDir *dir;
+ int nw;
+
+ dir = &(SFdirs[SFdirPtr + (int)(long)n]);
+
+#ifdef FEAT_GUI_NEXTAW
+ if ((int)(long)pnew < 0)
+ {
+ if ((int)(long)pnew > -SFhScrollWidth)
+ (int)(long)pnew = -1;
+ else
+ (int)(long)pnew = -SFcharsPerEntry;
+ }
+ else if ((int)(long)pnew > 0)
+ {
+ if ((int)(long)pnew < SFhScrollWidth)
+ (int)(long)pnew = 1;
+ else
+ (int)(long)pnew = SFcharsPerEntry;
+ }
+#endif
+ nw = dir->hOrigin + (int)(long)pnew;
+
+ if (nw > dir->nChars - SFcharsPerEntry)
+ nw = dir->nChars - SFcharsPerEntry;
+
+ if (nw < 0)
+ nw = 0;
+
+ if (dir->nChars)
+ {
+ float f;
+
+ f = ((double) nw) / dir->nChars;
+
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb(
+ w,
+ f,
+ (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
+ dir->nChars : SFcharsPerEntry)) / dir->nChars));
+#else
+ vim_XawScrollbarSetThumb(
+ w,
+ f,
+ (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
+ dir->nChars : SFcharsPerEntry)) / dir->nChars),
+ (double)dir->nChars);
+#endif
+
+ SFhSliderMovedCallback(w, n, (XtPointer)&f);
+ }
+}
+
+/* ARGSUSED */
+ static void
+SFpathSliderMovedCallback(w, client_data, nw)
+ Widget w;
+ XtPointer client_data;
+ XtPointer nw;
+{
+ SFDir *dir;
+ int n;
+ XawTextPosition pos;
+ int SFdirPtrSave;
+
+ SFdirPtrSave = SFdirPtr;
+ SFdirPtr = (*(float *)nw) * SFdirEnd;
+ if (SFdirPtr == SFdirPtrSave)
+ return;
+
+ SFdrawLists(SF_DO_SCROLL);
+
+ n = 2;
+ while (SFdirPtr + n >= SFdirEnd)
+ n--;
+
+ dir = &(SFdirs[SFdirPtr + n]);
+
+ pos = dir->path - SFcurrentPath;
+
+ if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
+ {
+ pos -= strlen(SFstartDir);
+ if (pos < 0)
+ pos = 0;
+ }
+
+ XawTextSetInsertionPoint(selFileField, pos);
+}
+
+/* ARGSUSED */
+ static void
+SFpathAreaSelectedCallback(w, client_data, pnew)
+ Widget w;
+ XtPointer client_data;
+ XtPointer pnew;
+{
+ int nw;
+ float f;
+
+#ifdef FEAT_GUI_NEXTAW
+ if ((int)(long)pnew < 0)
+ {
+ if ((int)(long)pnew > -SFpathScrollWidth)
+ (int)(long)pnew = -1;
+ else
+ (int)(long)pnew = -3;
+ }
+ else if ((int)(long)pnew > 0)
+ {
+ if ((int)(long)pnew < SFpathScrollWidth)
+ (int)(long)pnew = 1;
+ else
+ (int)(long)pnew = 3;
+ }
+#endif
+ nw = SFdirPtr + (int)(long)pnew;
+
+ if (nw > SFdirEnd - 3)
+ nw = SFdirEnd - 3;
+
+ if (nw < 0)
+ nw = 0;
+
+ f = ((double) nw) / SFdirEnd;
+
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb(
+ w,
+ f,
+ (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) / SFdirEnd));
+#else
+ vim_XawScrollbarSetThumb(
+ w,
+ f,
+ (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) / SFdirEnd),
+ (double)SFdirEnd);
+#endif
+
+ SFpathSliderMovedCallback(w, (XtPointer) NULL, (XtPointer)&f);
+}
+
+ static Boolean
+SFworkProc()
+{
+ SFDir *dir;
+ SFEntry *entry;
+
+ for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
+ {
+ if (!(dir->nEntries))
+ continue;
+ for (entry = &(dir->entries[dir->nEntries - 1]);
+ entry >= dir->entries;
+ entry--)
+ {
+ if (!(entry->statDone))
+ {
+ (void)SFstatAndCheck(dir, entry);
+ return False;
+ }
+ }
+ }
+
+ SFworkProcAdded = 0;
+
+ return True;
+}
+
+/***************** Dir.c */
+
+ static int
+SFcompareEntries(p, q)
+ const void *p;
+ const void *q;
+{
+ return strcmp(((SFEntry *)p)->real, ((SFEntry *)q)->real);
+}
+
+ static int
+SFgetDir(dir)
+ SFDir *dir;
+{
+ SFEntry *result = NULL;
+ int Alloc = 0;
+ int i;
+ DIR *dirp;
+ struct dirent *dp;
+ char *str;
+ int len;
+ int maxChars;
+ struct stat statBuf;
+
+ maxChars = strlen(dir->dir) - 1;
+
+ dir->entries = NULL;
+ dir->nEntries = 0;
+ dir->nChars = 0;
+
+ result = NULL;
+ i = 0;
+
+ dirp = opendir(".");
+ if (!dirp)
+ return 1;
+
+ (void)mch_stat(".", &statBuf);
+ dir->mtime = statBuf.st_mtime;
+
+ while ((dp = readdir(dirp)))
+ {
+ /* Ignore "." and ".." */
+ if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
+ continue;
+ if (i >= Alloc)
+ {
+ Alloc = 2 * (Alloc + 1);
+ result = (SFEntry *) XtRealloc((char *) result,
+ (unsigned) (Alloc * sizeof(SFEntry)));
+ }
+ result[i].statDone = 0;
+ str = dp->d_name;
+ len = strlen(str);
+ result[i].real = XtMalloc((unsigned) (len + 2));
+ (void) strcat(strcpy(result[i].real, str), " ");
+ if (len > maxChars)
+ maxChars = len;
+ result[i].shown = result[i].real;
+ i++;
+ }
+
+ qsort((char *) result, (size_t) i, sizeof(SFEntry), SFcompareEntries);
+
+ dir->entries = result;
+ dir->nEntries = i;
+ dir->nChars = maxChars + 1;
+
+ closedir(dirp);
+
+ return 0;
+}
+
+/***************** SFinternal.h */
+
+#include <sys/param.h>
+#include <X11/cursorfont.h>
+#include <X11/Composite.h>
+#include <X11/Shell.h>
+#ifdef FEAT_GUI_NEXTAW
+# include <X11/neXtaw/Form.h>
+# include <X11/neXtaw/Command.h>
+# include <X11/neXtaw/Label.h>
+#else
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/Label.h>
+#endif
+
+static char *oneLineTextEditTranslations = "\
+ <Key>Return: redraw-display()\n\
+ Ctrl<Key>M: redraw-display()\n\
+";
+
+static void SFexposeList __ARGS((Widget w, XtPointer n, XEvent *event, Boolean *cont));
+
+/* ARGSUSED */
+ static void
+SFexposeList(w, n, event, cont)
+ Widget w;
+ XtPointer n;
+ XEvent *event;
+ Boolean *cont;
+{
+ if ((event->type == NoExpose) || event->xexpose.count)
+ return;
+
+ SFdrawList((int)(long)n, SF_DO_NOT_SCROLL);
+}
+
+static void SFmodVerifyCallback __ARGS((Widget w, XtPointer client_data, XEvent *event, Boolean *cont));
+
+/* ARGSUSED */
+ static void
+SFmodVerifyCallback(w, client_data, event, cont)
+ Widget w;
+ XtPointer client_data;
+ XEvent *event;
+ Boolean *cont;
+{
+ char buf[2];
+
+ if ((XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
+ ((*buf) == '\r'))
+ SFstatus = SEL_FILE_OK;
+ else
+ SFstatus = SEL_FILE_TEXT;
+}
+
+static void SFokCallback __ARGS((Widget w, XtPointer cl, XtPointer cd));
+
+/* ARGSUSED */
+ static void
+SFokCallback(w, cl, cd)
+ Widget w;
+ XtPointer cl, cd;
+{
+ SFstatus = SEL_FILE_OK;
+}
+
+static XtCallbackRec SFokSelect[] =
+{
+ { SFokCallback, (XtPointer) NULL },
+ { NULL, (XtPointer) NULL },
+};
+
+static void SFcancelCallback __ARGS((Widget w, XtPointer cl, XtPointer cd));
+
+/* ARGSUSED */
+ static void
+SFcancelCallback(w, cl, cd)
+ Widget w;
+ XtPointer cl, cd;
+{
+ SFstatus = SEL_FILE_CANCEL;
+}
+
+static XtCallbackRec SFcancelSelect[] =
+{
+ { SFcancelCallback, (XtPointer) NULL },
+ { NULL, (XtPointer) NULL },
+};
+
+static void SFdismissAction __ARGS((Widget w, XEvent *event, String *params, Cardinal *num_params));
+
+/* ARGSUSED */
+ static void
+SFdismissAction(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ if (event->type == ClientMessage &&
+ event->xclient.data.l[0] != SFwmDeleteWindow)
+ return;
+
+ SFstatus = SEL_FILE_CANCEL;
+}
+
+static char *wmDeleteWindowTranslation = "\
+ <Message>WM_PROTOCOLS: SelFileDismiss()\n\
+";
+
+static XtActionsRec actions[] =
+{
+ {"SelFileDismiss", SFdismissAction},
+};
+
+ static void
+SFsetColors(bg, fg, scroll_bg, scroll_fg)
+ guicolor_T bg;
+ guicolor_T fg;
+ guicolor_T scroll_bg;
+ guicolor_T scroll_fg;
+{
+ if (selFileForm)
+ {
+ XtVaSetValues(selFileForm, XtNbackground, bg,
+ XtNforeground, fg,
+ XtNborderColor, bg,
+ NULL);
+ }
+ {
+ int i;
+
+ for (i = 0; i < 3; ++i)
+ {
+ if (selFileLists[i])
+ {
+ XtVaSetValues(selFileLists[i], XtNbackground, bg,
+ XtNforeground, fg,
+ XtNborderColor, fg,
+ NULL);
+ }
+ }
+ }
+ if (selFileOK)
+ {
+ XtVaSetValues(selFileOK, XtNbackground, bg,
+ XtNforeground, fg,
+ XtNborderColor, fg,
+ NULL);
+ }
+ if (selFileCancel)
+ {
+ XtVaSetValues(selFileCancel, XtNbackground, bg,
+ XtNforeground, fg,
+ XtNborderColor, fg,
+ NULL);
+ }
+ if (selFilePrompt)
+ {
+ XtVaSetValues(selFilePrompt, XtNbackground, bg,
+ XtNforeground, fg,
+ NULL);
+ }
+ if (gui.dpy)
+ {
+ XSetBackground(gui.dpy, SFtextGC, bg);
+ XSetForeground(gui.dpy, SFtextGC, fg);
+ XSetForeground(gui.dpy, SFlineGC, fg);
+
+ /* This is an xor GC, so combine the fg and background */
+ XSetBackground(gui.dpy, SFinvertGC, fg ^ bg);
+ XSetForeground(gui.dpy, SFinvertGC, fg ^ bg);
+ }
+ if (selFileHScroll)
+ {
+ XtVaSetValues(selFileHScroll, XtNbackground, scroll_bg,
+ XtNforeground, scroll_fg,
+ XtNborderColor, fg,
+ NULL);
+ }
+ {
+ int i;
+
+ for (i = 0; i < 3; i++)
+ {
+ XtVaSetValues(selFileVScrolls[i], XtNbackground, scroll_bg,
+ XtNforeground, scroll_fg,
+ XtNborderColor, fg,
+ NULL);
+ XtVaSetValues(selFileHScrolls[i], XtNbackground, scroll_bg,
+ XtNforeground, scroll_fg,
+ XtNborderColor, fg,
+ NULL);
+ }
+ }
+}
+
+ static void
+SFcreateWidgets(toplevel, prompt, ok, cancel)
+ Widget toplevel;
+ char *prompt;
+ char *ok;
+ char *cancel;
+{
+ Cardinal n;
+ int listWidth, listHeight;
+ int listSpacing = 10;
+ int scrollThickness = 15;
+ int hScrollX, hScrollY;
+ int vScrollX, vScrollY;
+
+ selFile = XtVaAppCreateShell("selFile", "SelFile",
+ transientShellWidgetClass, SFdisplay,
+ XtNtransientFor, toplevel,
+ XtNtitle, prompt,
+ NULL);
+
+ /* Add WM_DELETE_WINDOW protocol */
+ XtAppAddActions(XtWidgetToApplicationContext(selFile),
+ actions, XtNumber(actions));
+ XtOverrideTranslations(selFile,
+ XtParseTranslationTable(wmDeleteWindowTranslation));
+
+ selFileForm = XtVaCreateManagedWidget("selFileForm",
+ formWidgetClass, selFile,
+ XtNdefaultDistance, 30,
+ XtNforeground, SFfore,
+ XtNbackground, SFback,
+ XtNborderColor, SFback,
+ NULL);
+
+ selFilePrompt = XtVaCreateManagedWidget("selFilePrompt",
+ labelWidgetClass, selFileForm,
+ XtNlabel, prompt,
+ XtNresizable, True,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainLeft,
+ XtNborderWidth, 0,
+ XtNforeground, SFfore,
+ XtNbackground, SFback,
+ NULL);
+
+ /*
+ XtVaGetValues(selFilePrompt,
+ XtNforeground, &SFfore,
+ XtNbackground, &SFback,
+ NULL);
+ */
+
+ SFinitFont();
+
+ SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth +
+ SFbesideText;
+ SFentryHeight = SFaboveAndBelowText + SFcharHeight +
+ SFaboveAndBelowText;
+
+ listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
+ scrollThickness;
+ listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
+ SFlineToTextV + SFlistSize * SFentryHeight +
+ SFlineToTextV + 1 + scrollThickness;
+
+ SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
+
+ hScrollX = -1;
+ hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
+ SFlineToTextV + SFlistSize * SFentryHeight +
+ SFlineToTextV;
+ SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
+
+ vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
+ vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
+ SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
+ SFlineToTextV;
+
+ SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
+ SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
+ SFlineToTextV;
+ SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
+ SFlineToTextV + SFlistSize * SFentryHeight - 1;
+
+ SFtextX = SFlineToTextH + SFbesideText;
+ SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
+
+ SFsegs[0].x1 = 0;
+ SFsegs[0].y1 = vScrollY;
+ SFsegs[0].x2 = vScrollX - 1;
+ SFsegs[0].y2 = vScrollY;
+ SFsegs[1].x1 = vScrollX;
+ SFsegs[1].y1 = 0;
+ SFsegs[1].x2 = vScrollX;
+ SFsegs[1].y2 = vScrollY - 1;
+
+ SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
+ SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
+ SFlineToTextH + SFentryWidth - 1;
+
+ selFileField = XtVaCreateManagedWidget("selFileField",
+ asciiTextWidgetClass, selFileForm,
+ XtNwidth, 3 * listWidth + 2 * listSpacing + 4,
+ XtNborderColor, SFfore,
+ XtNfromVert, selFilePrompt,
+ XtNvertDistance, 10,
+ XtNresizable, True,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainLeft,
+ XtNstring, SFtextBuffer,
+ XtNlength, MAXPATHL,
+ XtNeditType, XawtextEdit,
+ XtNwrap, XawtextWrapWord,
+ XtNresize, XawtextResizeHeight,
+ XtNuseStringInPlace, True,
+ NULL);
+
+ XtOverrideTranslations(selFileField,
+ XtParseTranslationTable(oneLineTextEditTranslations));
+ XtSetKeyboardFocus(selFileForm, selFileField);
+
+ selFileHScroll = XtVaCreateManagedWidget("selFileHScroll",
+#ifdef FEAT_GUI_NEXTAW
+ scrollbarWidgetClass, selFileForm,
+#else
+ vim_scrollbarWidgetClass, selFileForm,
+#endif
+ XtNorientation, XtorientHorizontal,
+ XtNwidth, SFpathScrollWidth,
+ XtNheight, scrollThickness,
+ XtNborderColor, SFfore,
+ XtNfromVert, selFileField,
+ XtNvertDistance, 30,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainLeft,
+ XtNforeground, gui.scroll_fg_pixel,
+ XtNbackground, gui.scroll_bg_pixel,
+#ifndef FEAT_GUI_NEXTAW
+ XtNlimitThumb, 1,
+#endif
+ NULL);
+
+ XtAddCallback(selFileHScroll, XtNjumpProc,
+ (XtCallbackProc) SFpathSliderMovedCallback, (XtPointer)NULL);
+ XtAddCallback(selFileHScroll, XtNscrollProc,
+ (XtCallbackProc) SFpathAreaSelectedCallback, (XtPointer)NULL);
+
+ selFileLists[0] = XtVaCreateManagedWidget("selFileList1",
+ compositeWidgetClass, selFileForm,
+ XtNwidth, listWidth,
+ XtNheight, listHeight,
+ XtNforeground, SFfore,
+ XtNbackground, SFback,
+ XtNborderColor, SFfore,
+ XtNfromVert, selFileHScroll,
+ XtNvertDistance, 10,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainLeft,
+ NULL);
+
+ selFileLists[1] = XtVaCreateManagedWidget("selFileList2",
+ compositeWidgetClass, selFileForm,
+ XtNwidth, listWidth,
+ XtNheight, listHeight,
+ XtNforeground, SFfore,
+ XtNbackground, SFback,
+ XtNborderColor, SFfore,
+ XtNfromHoriz, selFileLists[0],
+ XtNfromVert, selFileHScroll,
+ XtNhorizDistance, listSpacing,
+ XtNvertDistance, 10,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainLeft,
+ NULL);
+
+ selFileLists[2] = XtVaCreateManagedWidget("selFileList3",
+ compositeWidgetClass, selFileForm,
+ XtNwidth, listWidth,
+ XtNheight, listHeight,
+ XtNforeground, SFfore,
+ XtNbackground, SFback,
+ XtNborderColor, SFfore,
+ XtNfromHoriz, selFileLists[1],
+ XtNfromVert, selFileHScroll,
+ XtNhorizDistance, listSpacing,
+ XtNvertDistance, 10,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainLeft,
+ NULL);
+
+ for (n = 0; n < 3; n++)
+ {
+ selFileVScrolls[n] = XtVaCreateManagedWidget("selFileVScroll",
+#ifdef FEAT_GUI_NEXTAW
+ scrollbarWidgetClass, selFileLists[n],
+#else
+ vim_scrollbarWidgetClass, selFileLists[n],
+#endif
+ XtNx, vScrollX,
+ XtNy, vScrollY,
+ XtNwidth, scrollThickness,
+ XtNheight, SFvScrollHeight,
+ XtNborderColor, SFfore,
+ XtNforeground, gui.scroll_fg_pixel,
+ XtNbackground, gui.scroll_bg_pixel,
+#ifndef FEAT_GUI_NEXTAW
+ XtNlimitThumb, 1,
+#endif
+ NULL);
+
+ XtAddCallback(selFileVScrolls[n], XtNjumpProc,
+ (XtCallbackProc)SFvFloatSliderMovedCallback, (XtPointer)n);
+ XtAddCallback(selFileVScrolls[n], XtNscrollProc,
+ (XtCallbackProc)SFvAreaSelectedCallback, (XtPointer)n);
+
+ selFileHScrolls[n] = XtVaCreateManagedWidget("selFileHScroll",
+#ifdef FEAT_GUI_NEXTAW
+ scrollbarWidgetClass, selFileLists[n],
+#else
+ vim_scrollbarWidgetClass, selFileLists[n],
+#endif
+ XtNorientation, XtorientHorizontal,
+ XtNx, hScrollX,
+ XtNy, hScrollY,
+ XtNwidth, SFhScrollWidth,
+ XtNheight, scrollThickness,
+ XtNborderColor, SFfore,
+ XtNforeground, gui.scroll_fg_pixel,
+ XtNbackground, gui.scroll_bg_pixel,
+#ifndef FEAT_GUI_NEXTAW
+ XtNlimitThumb, 1,
+#endif
+ NULL);
+
+ XtAddCallback(selFileHScrolls[n], XtNjumpProc,
+ (XtCallbackProc)SFhSliderMovedCallback, (XtPointer)n);
+ XtAddCallback(selFileHScrolls[n], XtNscrollProc,
+ (XtCallbackProc)SFhAreaSelectedCallback, (XtPointer)n);
+ }
+
+ selFileOK = XtVaCreateManagedWidget("selFileOK",
+ commandWidgetClass, selFileForm,
+ XtNlabel, ok,
+ XtNresizable, True,
+ XtNcallback, SFokSelect,
+ XtNforeground, SFfore,
+ XtNbackground, SFback,
+ XtNborderColor, SFfore,
+ XtNfromHoriz, selFileLists[0],
+ XtNfromVert, selFileLists[0],
+ XtNvertDistance, 30,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainLeft,
+ NULL);
+
+ selFileCancel = XtVaCreateManagedWidget("selFileCancel",
+ commandWidgetClass, selFileForm,
+ XtNlabel, cancel,
+ XtNresizable, True,
+ XtNcallback, SFcancelSelect,
+ XtNforeground, SFfore,
+ XtNbackground, SFback,
+ XtNborderColor, SFfore,
+ XtNfromHoriz, selFileOK,
+ XtNfromVert, selFileLists[0],
+ XtNhorizDistance, 30,
+ XtNvertDistance, 30,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainLeft,
+ NULL);
+
+ XtSetMappedWhenManaged(selFile, False);
+ XtRealizeWidget(selFile);
+
+ /* Add WM_DELETE_WINDOW protocol */
+ SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
+ XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
+
+ SFcreateGC();
+
+ for (n = 0; n < 3; n++)
+ {
+ XtAddEventHandler(selFileLists[n], ExposureMask, True,
+ (XtEventHandler)SFexposeList, (XtPointer)n);
+ XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
+ (XtEventHandler)SFenterList, (XtPointer)n);
+ XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
+ (XtEventHandler)SFleaveList, (XtPointer)n);
+ XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
+ (XtEventHandler)SFmotionList, (XtPointer)n);
+ XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
+ (XtEventHandler)SFbuttonPressList, (XtPointer)n);
+ XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
+ (XtEventHandler)SFbuttonReleaseList, (XtPointer)n);
+ }
+
+ XtAddEventHandler(selFileField, KeyPressMask, False,
+ SFmodVerifyCallback, (XtPointer)NULL);
+
+ SFapp = XtWidgetToApplicationContext(selFile);
+}
+
+ static void
+SFtextChanged()
+{
+#if defined(FEAT_XFONTSET) && defined(XtNinternational)
+ if (_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
+ {
+ wchar_t *wcbuf=(wchar_t *)SFtextBuffer;
+
+ if ((wcbuf[0] == L'/') || (wcbuf[0] == L'~'))
+ {
+ (void) wcstombs(SFcurrentPath, wcbuf, MAXPATHL);
+ SFtextPos = XawTextGetInsertionPoint(selFileField);
+ }
+ else
+ {
+ strcpy(SFcurrentPath, SFstartDir);
+ (void) wcstombs(SFcurrentPath + strlen(SFcurrentPath), wcbuf, MAXPATHL);
+
+ SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
+ }
+ }
+ else
+#endif
+ if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~'))
+ {
+ (void) strcpy(SFcurrentPath, SFtextBuffer);
+ SFtextPos = XawTextGetInsertionPoint(selFileField);
+ }
+ else
+ {
+ (void) strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
+
+ SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
+ }
+
+ if (!SFworkProcAdded)
+ {
+ (void) XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
+ SFworkProcAdded = 1;
+ }
+
+ SFupdatePath();
+}
+
+ static char *
+SFgetText()
+{
+#if defined(FEAT_XFONTSET) && defined(XtNinternational)
+ char *buf;
+
+ if (_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
+ {
+ wchar_t *wcbuf;
+ int mbslength;
+
+ XtVaGetValues(selFileField,
+ XtNstring, &wcbuf,
+ NULL);
+ mbslength = wcstombs(NULL, wcbuf, 0);
+ /* Hack: some broken wcstombs() returns zero, just get a large buffer */
+ if (mbslength == 0 && wcbuf != NULL && wcbuf[0] != 0)
+ mbslength = MAXPATHL;
+ buf=(char *)XtMalloc(mbslength + 1);
+ wcstombs(buf, wcbuf, mbslength +1);
+ return buf;
+ }
+#endif
+ return (char *)vim_strsave((char_u *)SFtextBuffer);
+}
+
+ static void
+SFprepareToReturn()
+{
+ SFstatus = SEL_FILE_NULL;
+ XtRemoveGrab(selFile);
+ XtUnmapWidget(selFile);
+ XtRemoveTimeOut(SFdirModTimerId);
+ if (SFchdir(SFstartDir))
+ {
+ EMSG(_("E614: vim_SelFile: can't return to current directory"));
+ SFstatus = SEL_FILE_CANCEL;
+ }
+}
+
+ char *
+vim_SelFile(toplevel, prompt, init_path, show_entry, x, y, fg, bg, scroll_fg, scroll_bg)
+ Widget toplevel;
+ char *prompt;
+ char *init_path;
+ int (*show_entry)();
+ int x, y;
+ guicolor_T fg, bg;
+ guicolor_T scroll_fg, scroll_bg; /* The "Scrollbar" group colors */
+{
+ static int firstTime = 1;
+ XEvent event;
+ char *name_return;
+
+ if (prompt == NULL)
+ prompt = _("Pathname:");
+ SFfore = fg;
+ SFback = bg;
+
+ if (mch_dirname((char_u *)SFstartDir, MAXPATHL) == FAIL)
+ {
+ EMSG(_("E615: vim_SelFile: can't get current directory"));
+ return NULL;
+ }
+
+ if (firstTime)
+ {
+ firstTime = 0;
+ SFdisplay = XtDisplay(toplevel);
+ SFcreateWidgets(toplevel, prompt, _("OK"), _("Cancel"));
+ }
+ else
+ {
+ XtVaSetValues(selFilePrompt, XtNlabel, prompt, NULL);
+ XtVaSetValues(selFile, XtNtitle, prompt, NULL);
+ SFsetColors(bg, fg, scroll_bg, scroll_fg);
+ }
+
+ XtVaSetValues(selFile, XtNx, x, XtNy, y, NULL);
+ XtMapWidget(selFile);
+
+ (void)strcat(SFstartDir, "/");
+ (void)strcpy(SFcurrentDir, SFstartDir);
+
+ if (init_path)
+ {
+ if (init_path[0] == '/')
+ {
+ (void)strcpy(SFcurrentPath, init_path);
+ if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
+ SFsetText(SFcurrentPath);
+ else
+ SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
+ }
+ else
+ {
+ (void)strcat(strcpy(SFcurrentPath, SFstartDir), init_path);
+ SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
+ }
+ }
+ else
+ (void)strcpy(SFcurrentPath, SFstartDir);
+
+ SFfunc = show_entry;
+
+ SFtextChanged();
+
+ XtAddGrab(selFile, True, True);
+
+ SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
+ SFdirModTimer, (XtPointer) NULL);
+
+ while (1)
+ {
+ XtAppNextEvent(SFapp, &event);
+ XtDispatchEvent(&event);
+ switch (SFstatus)
+ {
+ case SEL_FILE_TEXT:
+ SFstatus = SEL_FILE_NULL;
+ SFtextChanged();
+ break;
+ case SEL_FILE_OK:
+ name_return = SFgetText();
+ SFprepareToReturn();
+ return name_return;
+ case SEL_FILE_CANCEL:
+ SFprepareToReturn();
+ return NULL;
+ case SEL_FILE_NULL:
+ break;
+ }
+ }
+}
+#endif /* FEAT_BROWSE */
diff --git a/src/gui_at_sb.c b/src/gui_at_sb.c
new file mode 100644
index 000000000..5fe3afbbe
--- /dev/null
+++ b/src/gui_at_sb.c
@@ -0,0 +1,1213 @@
+/* vi:set ts=8 sts=4 sw=4: */
+/*
+ * MODIFIED ATHENA SCROLLBAR (USING ARROWHEADS AT ENDS OF TRAVEL)
+ * Modifications Copyright 1992 by Mitch Trachtenberg
+ * Rights, permissions, and disclaimer of warranty are as in the DEC and MIT
+ * notice below.
+ * $XConsortium: Scrollbar.c,v 1.72 94/04/17 20:12:40 kaleb Exp $
+ */
+
+/*
+ * Modified for Vim by Bill Foster and Bram Moolenaar
+ */
+
+/*
+
+Copyright (c) 1987, 1988, 1994 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X
+CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings in
+this Software without prior written authorization from the X Consortium.
+
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided that
+the above copyright notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting documentation, and that
+the name of Digital not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL
+BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+/* ScrollBar.c */
+/* created by weissman, Mon Jul 7 13:20:03 1986 */
+/* converted by swick, Thu Aug 27 1987 */
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+
+#include <X11/Xaw/XawInit.h>
+#include "vim.h"
+#include "gui_at_sb.h"
+
+#include <X11/Xmu/Drawing.h>
+
+/* Private definitions. */
+
+static char defaultTranslations[] =
+ "<Btn1Down>: NotifyScroll()\n\
+ <Btn2Down>: MoveThumb() NotifyThumb()\n\
+ <Btn3Down>: NotifyScroll()\n\
+ <Btn4Down>: ScrollOneLineUp()\n\
+ Shift<Btn4Down>: ScrollPageUp()\n\
+ <Btn5Down>: ScrollOneLineDown()\n\
+ Shift<Btn5Down>: ScrollPageDown()\n\
+ <Btn1Motion>: HandleThumb()\n\
+ <Btn3Motion>: HandleThumb()\n\
+ <Btn2Motion>: MoveThumb() NotifyThumb()\n\
+ <BtnUp>: EndScroll()";
+
+static float floatZero = 0.0;
+
+#define Offset(field) XtOffsetOf(ScrollbarRec, field)
+
+static XtResource resources[] =
+{
+ {XtNlength, XtCLength, XtRDimension, sizeof(Dimension),
+ Offset(scrollbar.length), XtRImmediate, (XtPointer) 1},
+ {XtNthickness, XtCThickness, XtRDimension, sizeof(Dimension),
+ Offset(scrollbar.thickness), XtRImmediate, (XtPointer) 14},
+ {XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation),
+ Offset(scrollbar.orientation), XtRImmediate, (XtPointer) XtorientVertical},
+ {XtNscrollProc, XtCCallback, XtRCallback, sizeof(XtPointer),
+ Offset(scrollbar.scrollProc), XtRCallback, NULL},
+ {XtNthumbProc, XtCCallback, XtRCallback, sizeof(XtPointer),
+ Offset(scrollbar.thumbProc), XtRCallback, NULL},
+ {XtNjumpProc, XtCCallback, XtRCallback, sizeof(XtPointer),
+ Offset(scrollbar.jumpProc), XtRCallback, NULL},
+ {XtNthumb, XtCThumb, XtRBitmap, sizeof(Pixmap),
+ Offset(scrollbar.thumb), XtRImmediate, (XtPointer) XtUnspecifiedPixmap},
+ {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
+ Offset(scrollbar.foreground), XtRString, XtDefaultForeground},
+ {XtNshown, XtCShown, XtRFloat, sizeof(float),
+ Offset(scrollbar.shown), XtRFloat, (XtPointer)&floatZero},
+ {XtNtopOfThumb, XtCTopOfThumb, XtRFloat, sizeof(float),
+ Offset(scrollbar.top), XtRFloat, (XtPointer)&floatZero},
+ {XtNmaxOfThumb, XtCMaxOfThumb, XtRFloat, sizeof(float),
+ Offset(scrollbar.max), XtRFloat, (XtPointer)&floatZero},
+ {XtNminimumThumb, XtCMinimumThumb, XtRDimension, sizeof(Dimension),
+ Offset(scrollbar.min_thumb), XtRImmediate, (XtPointer) 7},
+ {XtNshadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension),
+ Offset(scrollbar.shadow_width), XtRImmediate, (XtPointer) 1},
+ {XtNtopShadowPixel, XtCTopShadowPixel, XtRPixel, sizeof(Pixel),
+ Offset(scrollbar.top_shadow_pixel), XtRString, XtDefaultBackground},
+ {XtNbottomShadowPixel, XtCBottomShadowPixel, XtRPixel, sizeof(Pixel),
+ Offset(scrollbar.bot_shadow_pixel), XtRString, XtDefaultForeground},
+ {XtNlimitThumb, XtCLimitThumb, XtRBool, sizeof(Bool),
+ Offset(scrollbar.limit_thumb), XtRImmediate, (XtPointer)0}
+};
+#undef Offset
+
+static void ClassInitialize __ARGS((void));
+static void Initialize __ARGS((Widget, Widget, ArgList, Cardinal *));
+static void Destroy __ARGS((Widget));
+static void Realize __ARGS((Widget, Mask *, XSetWindowAttributes *));
+static void Resize __ARGS((Widget));
+static void Redisplay __ARGS((Widget, XEvent *, Region));
+static Boolean SetValues __ARGS((Widget, Widget, Widget, ArgList, Cardinal *));
+
+static void HandleThumb __ARGS((Widget, XEvent *, String *, Cardinal *));
+static void MoveThumb __ARGS((Widget, XEvent *, String *, Cardinal *));
+static void NotifyThumb __ARGS((Widget, XEvent *, String *, Cardinal *));
+static void NotifyScroll __ARGS((Widget, XEvent *, String *, Cardinal *));
+static void EndScroll __ARGS((Widget, XEvent *, String *, Cardinal *));
+static void ScrollOneLineUp __ARGS((Widget, XEvent *, String *, Cardinal *));
+static void ScrollOneLineDown __ARGS((Widget, XEvent *, String *, Cardinal *));
+static void ScrollPageUp __ARGS((Widget, XEvent *, String *, Cardinal *));
+static void ScrollPageDown __ARGS((Widget, XEvent *, String *, Cardinal *));
+static void ScrollSome __ARGS((Widget w, XEvent *event, int call_data));
+static void _Xaw3dDrawShadows __ARGS((Widget, XEvent *, Region, int));
+static void AllocTopShadowGC __ARGS((Widget));
+static void AllocBotShadowGC __ARGS((Widget));
+
+static XtActionsRec actions[] =
+{
+ {"HandleThumb", HandleThumb},
+ {"MoveThumb", MoveThumb},
+ {"NotifyThumb", NotifyThumb},
+ {"NotifyScroll", NotifyScroll},
+ {"EndScroll", EndScroll},
+ {"ScrollOneLineUp", ScrollOneLineUp},
+ {"ScrollOneLineDown", ScrollOneLineDown},
+ {"ScrollPageUp", ScrollPageUp},
+ {"ScrollPageDown", ScrollPageDown}
+};
+
+
+ScrollbarClassRec vim_scrollbarClassRec =
+{
+ { /* core fields */
+ /* superclass */ (WidgetClass) &simpleClassRec,
+ /* class_name */ "Scrollbar",
+ /* size */ sizeof(ScrollbarRec),
+ /* class_initialize */ ClassInitialize,
+ /* class_part_init */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ Realize,
+ /* actions */ actions,
+ /* num_actions */ XtNumber(actions),
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure*/ TRUE,
+ /* compress_enterleave*/ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ Destroy,
+ /* resize */ Resize,
+ /* expose */ Redisplay,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback_private */ NULL,
+ /* tm_table */ defaultTranslations,
+ /* query_geometry */ XtInheritQueryGeometry,
+ /* display_accelerator*/ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+ { /* simple fields */
+ /* change_sensitive */ XtInheritChangeSensitive
+ },
+ { /* scrollbar fields */
+ /* ignore */ 0
+ }
+};
+
+WidgetClass vim_scrollbarWidgetClass = (WidgetClass)&vim_scrollbarClassRec;
+
+#define NoButton -1
+#define PICKLENGTH(widget, x, y) \
+ ((widget->scrollbar.orientation == XtorientHorizontal) ? (x) : (y))
+#define AT_MIN(x,y) ((x) < (y) ? (x) : (y))
+#define AT_MAX(x,y) ((x) > (y) ? (x) : (y))
+
+#define LINE_DELAY 300
+#define PAGE_DELAY 300
+#define LINE_REPEAT 50
+#define PAGE_REPEAT 250
+
+ static void
+ClassInitialize()
+{
+ XawInitializeWidgetSet();
+ XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
+ (XtConvertArgList)NULL, (Cardinal)0 );
+}
+
+#define MARGIN(sbw) (sbw)->scrollbar.thickness + (sbw)->scrollbar.shadow_width
+
+ static void
+FillArea(sbw, top, bottom, fill, draw_shadow)
+ ScrollbarWidget sbw;
+ Position top, bottom;
+ int fill;
+ int draw_shadow;
+{
+ int tlen = bottom - top; /* length of thumb in pixels */
+ int sw, margin, floor;
+ int lx, ly, lw, lh;
+
+ if (bottom <= 0 || bottom <= top)
+ return;
+ if ((sw = sbw->scrollbar.shadow_width) < 0)
+ sw = 0;
+ margin = MARGIN (sbw);
+ floor = sbw->scrollbar.length - margin + 2;
+
+ if (sbw->scrollbar.orientation == XtorientHorizontal)
+ {
+ lx = ((top < margin) ? margin : top);
+ ly = sw;
+ lw = (((top + tlen) > floor) ? floor - top : tlen);
+ lh = sbw->core.height - 2 * sw;
+ }
+ else
+ {
+ lx = sw;
+ ly = ((top < margin) ? margin : top);
+ lw = sbw->core.width - 2 * sw;
+ lh = (((top + tlen) > floor) ? floor - top : tlen);
+ }
+ if (lh <= 0 || lw <= 0)
+ return;
+
+ if (draw_shadow)
+ {
+ if (!(sbw->scrollbar.orientation == XtorientHorizontal))
+ {
+ /* Top border */
+ XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.top_shadow_GC,
+ lx, ly, lx + lw - 1, ly);
+
+ /* Bottom border */
+ XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.bot_shadow_GC,
+ lx, ly + lh - 1, lx + lw - 1, ly + lh - 1);
+ }
+ else
+ {
+ /* Left border */
+ XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.top_shadow_GC,
+ lx, ly, lx, ly + lh - 1);
+
+ /* Right border */
+ XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.bot_shadow_GC,
+ lx + lw - 1, ly, lx + lw - 1, ly + lh - 1);
+ }
+ return;
+ }
+
+ if (fill)
+ {
+ XFillRectangle(XtDisplay((Widget) sbw), XtWindow((Widget) sbw),
+ sbw->scrollbar.gc,
+ lx, ly, (unsigned int) lw, (unsigned int) lh);
+
+ if (!(sbw->scrollbar.orientation == XtorientHorizontal))
+ {
+ /* Left border */
+ XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.top_shadow_GC,
+ lx, ly, lx, ly + lh - 1);
+
+ /* Right border */
+ XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.bot_shadow_GC,
+ lx + lw - 1, ly, lx + lw - 1, ly + lh - 1);
+ }
+ else
+ {
+ /* Top border */
+ XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.top_shadow_GC,
+ lx, ly, lx + lw - 1, ly);
+
+ /* Bottom border */
+ XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.bot_shadow_GC,
+ lx, ly + lh - 1, lx + lw - 1, ly + lh - 1);
+ }
+ }
+ else
+ {
+ XClearArea(XtDisplay((Widget) sbw), XtWindow((Widget) sbw),
+ lx, ly, (unsigned int) lw, (unsigned int) lh, FALSE);
+ }
+}
+
+/* Paint the thumb in the area specified by sbw->top and
+ sbw->shown. The old area is erased. The painting and
+ erasing is done cleverly so that no flickering will occur.
+ */
+
+ static void
+PaintThumb(sbw)
+ ScrollbarWidget sbw;
+{
+ Position oldtop, oldbot, newtop, newbot;
+ Dimension margin, tzl;
+
+ margin = MARGIN (sbw);
+ tzl = sbw->scrollbar.length - 2 * margin;
+ newtop = margin + (int)(tzl * sbw->scrollbar.top);
+ newbot = newtop + (int)(tzl * sbw->scrollbar.shown) + 1;
+ if (newbot < newtop + (int)sbw->scrollbar.min_thumb)
+ newbot = newtop + sbw->scrollbar.min_thumb;
+
+ oldtop = sbw->scrollbar.topLoc;
+ oldbot = oldtop + sbw->scrollbar.shownLength;
+ sbw->scrollbar.topLoc = newtop;
+ sbw->scrollbar.shownLength = newbot - newtop;
+ if (XtIsRealized ((Widget) sbw))
+ {
+ if (newtop < oldtop)
+ FillArea(sbw, newtop, AT_MIN(newbot, oldtop+1),1,0);
+ if (newtop > oldtop)
+ FillArea(sbw, oldtop, AT_MIN(newtop, oldbot ),0,0);
+ if (newbot < oldbot)
+ FillArea(sbw, AT_MAX(newbot, oldtop), oldbot, 0,0);
+ if (newbot > oldbot)
+ FillArea(sbw, AT_MAX(newtop, oldbot-1), newbot, 1,0);
+
+ /* Only draw the missing shadows */
+ FillArea(sbw, newtop, newbot, 0, 1);
+ }
+}
+
+ static void
+PaintArrows(sbw)
+ ScrollbarWidget sbw;
+{
+ XPoint point[6];
+ Dimension thickness = sbw->scrollbar.thickness - 1;
+ Dimension size;
+ Dimension off;
+
+ if (XtIsRealized((Widget) sbw))
+ {
+ if ((int)thickness * 2 > (int)sbw->scrollbar.length)
+ {
+ size = sbw->scrollbar.length / 2;
+ off = (int)(thickness - size) / 2;
+ }
+ else
+ {
+ size = thickness;
+ off = 0;
+ }
+ point[0].x = off + sbw->scrollbar.shadow_width;
+ point[0].y = size;
+ point[1].x = thickness - off - sbw->scrollbar.shadow_width;
+ point[1].y = size;
+ point[2].x = thickness / 2;
+ point[2].y = sbw->scrollbar.shadow_width;
+
+ point[3].x = off + sbw->scrollbar.shadow_width;
+ point[3].y = sbw->scrollbar.length - size;
+ point[4].x = thickness - off - sbw->scrollbar.shadow_width;
+ point[4].y = sbw->scrollbar.length - size;
+ point[5].x = thickness / 2;
+ point[5].y = sbw->scrollbar.length - sbw->scrollbar.shadow_width - 1;
+
+ /* horizontal arrows require that x and y coordinates be swapped */
+ if (sbw->scrollbar.orientation == XtorientHorizontal)
+ {
+ int n;
+ int swap;
+ for (n = 0; n < 6; n++)
+ {
+ swap = point[n].x;
+ point[n].x = point[n].y;
+ point[n].y = swap;
+ }
+ }
+ /* draw the up/left arrow */
+ XFillPolygon (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.gc,
+ point, 3,
+ Convex, CoordModeOrigin);
+ XDrawLines (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.bot_shadow_GC,
+ point, 3,
+ CoordModeOrigin);
+ XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.top_shadow_GC,
+ point[0].x, point[0].y,
+ point[2].x, point[2].y);
+ /* draw the down/right arrow */
+ XFillPolygon (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.gc,
+ point+3, 3,
+ Convex, CoordModeOrigin);
+ XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.top_shadow_GC,
+ point[3].x, point[3].y,
+ point[4].x, point[4].y);
+ XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.top_shadow_GC,
+ point[3].x, point[3].y,
+ point[5].x, point[5].y);
+ XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
+ sbw->scrollbar.bot_shadow_GC,
+ point[4].x, point[4].y,
+ point[5].x, point[5].y);
+ }
+}
+
+ static void
+Destroy(w)
+ Widget w;
+{
+ ScrollbarWidget sbw = (ScrollbarWidget) w;
+ if (sbw->scrollbar.timer_id != (XtIntervalId) 0)
+ XtRemoveTimeOut (sbw->scrollbar.timer_id);
+ XtReleaseGC(w, sbw->scrollbar.gc);
+ XtReleaseGC(w, sbw->scrollbar.top_shadow_GC);
+ XtReleaseGC(w, sbw->scrollbar.bot_shadow_GC);
+}
+
+ static void
+CreateGC(w)
+ Widget w;
+{
+ ScrollbarWidget sbw = (ScrollbarWidget) w;
+ XGCValues gcValues;
+ XtGCMask mask;
+ unsigned int depth = 1;
+
+ if (sbw->scrollbar.thumb == XtUnspecifiedPixmap)
+ {
+ sbw->scrollbar.thumb = XmuCreateStippledPixmap (XtScreen(w),
+ (Pixel) 1, (Pixel) 0, depth);
+ }
+ else if (sbw->scrollbar.thumb != None)
+ {
+ Window root;
+ int x, y;
+ unsigned int width, height, bw;
+
+ if (XGetGeometry (XtDisplay(w), sbw->scrollbar.thumb, &root, &x, &y,
+ &width, &height, &bw, &depth) == 0)
+ EMSG(_("Scrollbar Widget: Could not get geometry of thumb pixmap."));
+ }
+
+ gcValues.foreground = sbw->scrollbar.foreground;
+ gcValues.background = sbw->core.background_pixel;
+ mask = GCForeground | GCBackground;
+
+ if (sbw->scrollbar.thumb != None)
+ {
+ gcValues.fill_style = FillSolid;
+ mask |= GCFillStyle;
+ }
+ /* the creation should be non-caching, because */
+ /* we now set and clear clip masks on the gc returned */
+ sbw->scrollbar.gc = XtGetGC (w, mask, &gcValues);
+}
+
+ static void
+SetDimensions(sbw)
+ ScrollbarWidget sbw;
+{
+ if (sbw->scrollbar.orientation == XtorientVertical)
+ {
+ sbw->scrollbar.length = sbw->core.height;
+ sbw->scrollbar.thickness = sbw->core.width;
+ }
+ else
+ {
+ sbw->scrollbar.length = sbw->core.width;
+ sbw->scrollbar.thickness = sbw->core.height;
+ }
+}
+
+/* ARGSUSED */
+ static void
+Initialize(request, new, args, num_args)
+ Widget request; /* what the client asked for */
+ Widget new; /* what we're going to give him */
+ ArgList args;
+ Cardinal *num_args;
+{
+ ScrollbarWidget sbw = (ScrollbarWidget) new;
+
+ CreateGC(new);
+ AllocTopShadowGC(new);
+ AllocBotShadowGC(new);
+
+ if (sbw->core.width == 0)
+ sbw->core.width = (sbw->scrollbar.orientation == XtorientVertical)
+ ? sbw->scrollbar.thickness : sbw->scrollbar.length;
+
+ if (sbw->core.height == 0)
+ sbw->core.height = (sbw->scrollbar.orientation == XtorientHorizontal)
+ ? sbw->scrollbar.thickness : sbw->scrollbar.length;
+
+ SetDimensions(sbw);
+ sbw->scrollbar.scroll_mode = SMODE_NONE;
+ sbw->scrollbar.timer_id = (XtIntervalId)0;
+ sbw->scrollbar.topLoc = 0;
+ sbw->scrollbar.shownLength = sbw->scrollbar.min_thumb;
+}
+
+ static void
+Realize(w, valueMask, attributes)
+ Widget w;
+ Mask *valueMask;
+ XSetWindowAttributes *attributes;
+{
+ /* The Simple widget actually stuffs the value in the valuemask. */
+ (*vim_scrollbarWidgetClass->core_class.superclass->core_class.realize)
+ (w, valueMask, attributes);
+}
+
+/* ARGSUSED */
+ static Boolean
+SetValues(current, request, desired, args, num_args)
+ Widget current, /* what I am */
+ request, /* what he wants me to be */
+ desired; /* what I will become */
+ ArgList args;
+ Cardinal *num_args;
+{
+ ScrollbarWidget sbw = (ScrollbarWidget) current;
+ ScrollbarWidget dsbw = (ScrollbarWidget) desired;
+ Boolean redraw = FALSE;
+
+/*
+ * If these values are outside the acceptable range ignore them...
+ */
+ if (dsbw->scrollbar.top < 0.0 || dsbw->scrollbar.top > 1.0)
+ dsbw->scrollbar.top = sbw->scrollbar.top;
+
+ if (dsbw->scrollbar.shown < 0.0 || dsbw->scrollbar.shown > 1.0)
+ dsbw->scrollbar.shown = sbw->scrollbar.shown;
+
+/*
+ * Change colors and stuff...
+ */
+ if (XtIsRealized(desired))
+ {
+ if (sbw->scrollbar.foreground != dsbw->scrollbar.foreground ||
+ sbw->core.background_pixel != dsbw->core.background_pixel ||
+ sbw->scrollbar.thumb != dsbw->scrollbar.thumb)
+ {
+ XtReleaseGC(desired, sbw->scrollbar.gc);
+ CreateGC (desired);
+ redraw = TRUE;
+ }
+ if (sbw->scrollbar.top != dsbw->scrollbar.top ||
+ sbw->scrollbar.shown != dsbw->scrollbar.shown)
+ redraw = TRUE;
+ }
+ return redraw;
+}
+
+ static void
+Resize(w)
+ Widget w;
+{
+ /* ForgetGravity has taken care of background, but thumb may
+ * have to move as a result of the new size. */
+ SetDimensions ((ScrollbarWidget) w);
+ Redisplay(w, (XEvent*) NULL, (Region)NULL);
+}
+
+
+/* ARGSUSED */
+ static void
+Redisplay(w, event, region)
+ Widget w;
+ XEvent *event;
+ Region region;
+{
+ ScrollbarWidget sbw = (ScrollbarWidget) w;
+ int x, y;
+ unsigned int width, height;
+
+ _Xaw3dDrawShadows(w, event, region, FALSE);
+
+ if (sbw->scrollbar.orientation == XtorientHorizontal)
+ {
+ x = sbw->scrollbar.topLoc;
+ y = 1;
+ width = sbw->scrollbar.shownLength;
+ height = sbw->core.height - 2;
+ }
+ else
+ {
+ x = 1;
+ y = sbw->scrollbar.topLoc;
+ width = sbw->core.width - 2;
+ height = sbw->scrollbar.shownLength;
+ }
+ if (region == NULL ||
+ XRectInRegion (region, x, y, width, height) != RectangleOut)
+ {
+ /* Forces entire thumb to be painted. */
+ sbw->scrollbar.topLoc = -(sbw->scrollbar.length + 1);
+ PaintThumb (sbw);
+ }
+ /* we'd like to be region aware here!!!! */
+ PaintArrows(sbw);
+}
+
+
+ static Boolean
+CompareEvents(oldEvent, newEvent)
+ XEvent *oldEvent, *newEvent;
+{
+#define Check(field) if (newEvent->field != oldEvent->field) return False;
+
+ Check(xany.display);
+ Check(xany.type);
+ Check(xany.window);
+
+ switch (newEvent->type)
+ {
+ case MotionNotify:
+ Check(xmotion.state);
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ Check(xbutton.state);
+ Check(xbutton.button);
+ break;
+ case KeyPress:
+ case KeyRelease:
+ Check(xkey.state);
+ Check(xkey.keycode);
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ Check(xcrossing.mode);
+ Check(xcrossing.detail);
+ Check(xcrossing.state);
+ break;
+ }
+#undef Check
+
+ return True;
+}
+
+struct EventData
+{
+ XEvent *oldEvent;
+ int count;
+};
+
+ static Bool
+PeekNotifyEvent(dpy, event, args)
+ Display *dpy;
+ XEvent *event;
+ char *args;
+{
+ struct EventData *eventData = (struct EventData*)args;
+
+ return ((++eventData->count == QLength(dpy)) /* since PeekIf blocks */
+ || CompareEvents(event, eventData->oldEvent));
+}
+
+
+ static Boolean
+LookAhead(w, event)
+ Widget w;
+ XEvent *event;
+{
+ XEvent newEvent;
+ struct EventData eventData;
+
+ if (QLength (XtDisplay (w)) == 0)
+ return False;
+
+ eventData.count = 0;
+ eventData.oldEvent = event;
+
+ XPeekIfEvent (XtDisplay (w), &newEvent, PeekNotifyEvent, (char*)&eventData);
+
+ return CompareEvents (event, &newEvent);
+}
+
+
+ static void
+ExtractPosition(event, x, y, state)
+ XEvent *event;
+ Position *x, *y; /* RETURN */
+ unsigned int *state; /* RETURN */
+{
+ switch (event->type)
+ {
+ case MotionNotify:
+ *x = event->xmotion.x;
+ *y = event->xmotion.y;
+ if (state != NULL)
+ *state = event->xmotion.state;
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ *x = event->xbutton.x;
+ *y = event->xbutton.y;
+ if (state != NULL)
+ *state = event->xbutton.state;
+ break;
+ case KeyPress:
+ case KeyRelease:
+ *x = event->xkey.x;
+ *y = event->xkey.y;
+ if (state != NULL)
+ *state = event->xkey.state;
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ *x = event->xcrossing.x;
+ *y = event->xcrossing.y;
+ if (state != NULL)
+ *state = event->xcrossing.state;
+ break;
+ default:
+ *x = 0; *y = 0;
+ if (state != NULL)
+ *state = 0;
+ }
+}
+
+ static void
+HandleThumb(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ Position x, y, loc;
+ ScrollbarWidget sbw = (ScrollbarWidget) w;
+
+ ExtractPosition(event, &x, &y, (unsigned int *)NULL);
+ loc = PICKLENGTH(sbw, x, y);
+ /* if the motion event puts the pointer in thumb, call Move and Notify */
+ /* also call Move and Notify if we're already in continuous scroll mode */
+ if (sbw->scrollbar.scroll_mode == SMODE_CONT ||
+ (loc >= sbw->scrollbar.topLoc &&
+ loc <= sbw->scrollbar.topLoc + (int)sbw->scrollbar.shownLength))
+ {
+ XtCallActionProc(w, "MoveThumb", event, params, *num_params);
+ XtCallActionProc(w, "NotifyThumb", event, params, *num_params);
+ }
+}
+
+/* ARGSUSED */
+ static void
+RepeatNotify(client_data, idp)
+ XtPointer client_data;
+ XtIntervalId *idp;
+{
+ ScrollbarWidget sbw = (ScrollbarWidget) client_data;
+ int call_data;
+ char mode = sbw->scrollbar.scroll_mode;
+ unsigned long rep;
+
+ if (mode == SMODE_NONE || mode == SMODE_CONT)
+ {
+ sbw->scrollbar.timer_id = (XtIntervalId)0;
+ return;
+ }
+
+ if (mode == SMODE_LINE_DOWN || mode == SMODE_LINE_UP)
+ {
+ call_data = ONE_LINE_DATA;
+ rep = LINE_REPEAT;
+ }
+ else
+ {
+ call_data = ONE_PAGE_DATA;
+ rep = PAGE_REPEAT;
+ }
+
+ if (mode == SMODE_PAGE_UP || mode == SMODE_LINE_UP)
+ call_data = -call_data;
+
+ XtCallCallbacks((Widget)sbw, XtNscrollProc, (XtPointer)call_data);
+
+ sbw->scrollbar.timer_id =
+ XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)sbw),
+ rep,
+ RepeatNotify,
+ client_data);
+}
+
+/*
+ * Same as above, but for floating numbers.
+ */
+ static float
+FloatInRange(num, small, big)
+ float num, small, big;
+{
+ return (num < small) ? small : ((num > big) ? big : num);
+}
+
+/* ARGSUSED */
+ static void
+ScrollOneLineUp(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ ScrollSome(w, event, -ONE_LINE_DATA);
+}
+
+/* ARGSUSED */
+ static void
+ScrollOneLineDown(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ ScrollSome(w, event, ONE_LINE_DATA);
+}
+
+/* ARGSUSED */
+ static void
+ScrollPageDown(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ ScrollSome(w, event, ONE_PAGE_DATA);
+}
+
+/* ARGSUSED */
+ static void
+ScrollPageUp(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ ScrollSome(w, event, -ONE_PAGE_DATA);
+}
+
+ static void
+ScrollSome(w, event, call_data)
+ Widget w;
+ XEvent *event;
+ int call_data;
+{
+ ScrollbarWidget sbw = (ScrollbarWidget) w;
+
+ if (sbw->scrollbar.scroll_mode == SMODE_CONT) /* if scroll continuous */
+ return;
+
+ if (LookAhead(w, event))
+ return;
+
+ sbw->scrollbar.scroll_mode = SMODE_LINE_UP;
+ XtCallCallbacks(w, XtNscrollProc, (XtPointer)call_data);
+}
+
+/* ARGSUSED */
+ static void
+NotifyScroll(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ ScrollbarWidget sbw = (ScrollbarWidget) w;
+ Position x, y, loc;
+ Dimension arrow_size;
+ unsigned long delay = 0;
+ int call_data = 0;
+ unsigned int state;
+
+ if (sbw->scrollbar.scroll_mode == SMODE_CONT) /* if scroll continuous */
+ return;
+
+ if (LookAhead (w, event))
+ return;
+
+ ExtractPosition(event, &x, &y, &state);
+ loc = PICKLENGTH(sbw, x, y);
+
+ if ((int)sbw->scrollbar.thickness * 2 > (int)sbw->scrollbar.length)
+ arrow_size = sbw->scrollbar.length / 2;
+ else
+ arrow_size = sbw->scrollbar.thickness;
+
+ /*
+ * handle CTRL modifier
+ */
+ if (state & ControlMask)
+ {
+ if (loc > sbw->scrollbar.topLoc + (Position)sbw->scrollbar.shownLength)
+ call_data = END_PAGE_DATA;
+ else
+ call_data = -END_PAGE_DATA;
+ sbw->scrollbar.scroll_mode = SMODE_NONE;
+ }
+ /*
+ * handle first arrow zone
+ */
+ else if (loc < (Position)arrow_size)
+ {
+ call_data = -ONE_LINE_DATA;
+ sbw->scrollbar.scroll_mode = SMODE_LINE_UP;
+ delay = LINE_DELAY;
+ }
+
+ /*
+ * handle last arrow zone
+ */
+ else if (loc > (Position)(sbw->scrollbar.length - arrow_size))
+ {
+ call_data = ONE_LINE_DATA;
+ sbw->scrollbar.scroll_mode = SMODE_LINE_DOWN;
+ delay = LINE_DELAY;
+ }
+
+ /*
+ * handle zone "above" the thumb
+ */
+ else if (loc < sbw->scrollbar.topLoc)
+ {
+ call_data = -ONE_PAGE_DATA;
+ sbw->scrollbar.scroll_mode = SMODE_PAGE_UP;
+ delay = PAGE_DELAY;
+ }
+
+ /*
+ * handle zone "below" the thumb
+ */
+ else if (loc > sbw->scrollbar.topLoc + (Position)sbw->scrollbar.shownLength)
+ {
+ call_data = ONE_PAGE_DATA;
+ sbw->scrollbar.scroll_mode = SMODE_PAGE_DOWN;
+ delay = PAGE_DELAY;
+ }
+
+ if (call_data)
+ XtCallCallbacks(w, XtNscrollProc, (XtPointer)call_data);
+
+ /* establish autoscroll */
+ if (delay)
+ sbw->scrollbar.timer_id =
+ XtAppAddTimeOut(XtWidgetToApplicationContext(w),
+ delay, RepeatNotify, (XtPointer)w);
+}
+
+/* ARGSUSED */
+ static void
+EndScroll(w, event, params, num_params)
+ Widget w;
+ XEvent *event; /* unused */
+ String *params; /* unused */
+ Cardinal *num_params; /* unused */
+{
+ ScrollbarWidget sbw = (ScrollbarWidget) w;
+
+ sbw->scrollbar.scroll_mode = SMODE_NONE;
+ /* no need to remove any autoscroll timeout; it will no-op */
+ /* because the scroll_mode is SMODE_NONE */
+ /* but be sure to remove timeout in destroy proc */
+}
+
+ static float
+FractionLoc(sbw, x, y)
+ ScrollbarWidget sbw;
+ int x, y;
+{
+ int margin;
+ float height, width;
+
+ margin = MARGIN(sbw);
+ x -= margin;
+ y -= margin;
+ height = (float)sbw->core.height - 2 * margin;
+ width = (float)sbw->core.width - 2 * margin;
+ return PICKLENGTH(sbw, x / width, y / height);
+}
+
+/* ARGSUSED */
+ static void
+MoveThumb(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params; /* unused */
+ Cardinal *num_params; /* unused */
+{
+ ScrollbarWidget sbw = (ScrollbarWidget)w;
+ Position x, y;
+ float top;
+ char old_mode = sbw->scrollbar.scroll_mode;
+
+ sbw->scrollbar.scroll_mode = SMODE_CONT; /* indicate continuous scroll */
+
+ if (LookAhead(w, event))
+ return;
+
+ if (!event->xmotion.same_screen)
+ return;
+
+ ExtractPosition(event, &x, &y, (unsigned int *)NULL);
+
+ top = FractionLoc(sbw, x, y);
+
+ if (old_mode != SMODE_CONT) /* start dragging: set offset */
+ {
+ if (event->xbutton.button == Button2)
+ sbw->scrollbar.scroll_off = sbw->scrollbar.shown / 2.;
+ else
+ sbw->scrollbar.scroll_off = top - sbw->scrollbar.top;
+ }
+
+ top -= sbw->scrollbar.scroll_off;
+ if (sbw->scrollbar.limit_thumb)
+ top = FloatInRange(top, 0.0,
+ sbw->scrollbar.max - sbw->scrollbar.shown + 0.000001);
+ else
+ top = FloatInRange(top, 0.0, sbw->scrollbar.max);
+
+ sbw->scrollbar.top = top;
+ PaintThumb(sbw);
+ XFlush(XtDisplay(w)); /* re-draw it before Notifying */
+}
+
+
+/* ARGSUSED */
+ static void
+NotifyThumb(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params; /* unused */
+ Cardinal *num_params; /* unused */
+{
+ ScrollbarWidget sbw = (ScrollbarWidget)w;
+
+ if (LookAhead(w, event))
+ return;
+
+ /* thumbProc is not pretty, but is necessary for backwards
+ compatibility on those architectures for which it work{s,ed};
+ the intent is to pass a (truncated) float by value. */
+ XtCallCallbacks(w, XtNthumbProc, *(XtPointer*)&sbw->scrollbar.top);
+ XtCallCallbacks(w, XtNjumpProc, (XtPointer)&sbw->scrollbar.top);
+}
+
+/* ARGSUSED */
+ static void
+AllocTopShadowGC(w)
+ Widget w;
+{
+ ScrollbarWidget sbw = (ScrollbarWidget) w;
+ XtGCMask valuemask;
+ XGCValues myXGCV;
+
+ valuemask = GCForeground;
+ myXGCV.foreground = sbw->scrollbar.top_shadow_pixel;
+ sbw->scrollbar.top_shadow_GC = XtGetGC(w, valuemask, &myXGCV);
+}
+
+/* ARGSUSED */
+ static void
+AllocBotShadowGC(w)
+ Widget w;
+{
+ ScrollbarWidget sbw = (ScrollbarWidget) w;
+ XtGCMask valuemask;
+ XGCValues myXGCV;
+
+ valuemask = GCForeground;
+ myXGCV.foreground = sbw->scrollbar.bot_shadow_pixel;
+ sbw->scrollbar.bot_shadow_GC = XtGetGC(w, valuemask, &myXGCV);
+}
+
+/* ARGSUSED */
+ static void
+_Xaw3dDrawShadows(gw, event, region, out)
+ Widget gw;
+ XEvent *event;
+ Region region;
+ int out;
+{
+ XPoint pt[6];
+ ScrollbarWidget sbw = (ScrollbarWidget) gw;
+ Dimension s = sbw->scrollbar.shadow_width;
+ /*
+ * draw the shadows using the core part width and height,
+ * and the scrollbar part shadow_width.
+ *
+ * no point to do anything if the shadow_width is 0 or the
+ * widget has not been realized.
+ */
+ if (s > 0 && XtIsRealized(gw))
+ {
+ Dimension h = sbw->core.height;
+ Dimension w = sbw->core.width;
+ Dimension wms = w - s;
+ Dimension hms = h - s;
+ Display *dpy = XtDisplay (gw);
+ Window win = XtWindow (gw);
+ GC top, bot;
+
+ if (out)
+ {
+ top = sbw->scrollbar.top_shadow_GC;
+ bot = sbw->scrollbar.bot_shadow_GC;
+ }
+ else
+ {
+ top = sbw->scrollbar.bot_shadow_GC;
+ bot = sbw->scrollbar.top_shadow_GC;
+ }
+
+ /* top-left shadow */
+ if ((region == NULL) ||
+ (XRectInRegion (region, 0, 0, w, s) != RectangleOut) ||
+ (XRectInRegion (region, 0, 0, s, h) != RectangleOut))
+ {
+ pt[0].x = 0; pt[0].y = h;
+ pt[1].x = pt[1].y = 0;
+ pt[2].x = w; pt[2].y = 0;
+ pt[3].x = wms; pt[3].y = s;
+ pt[4].x = pt[4].y = s;
+ pt[5].x = s; pt[5].y = hms;
+ XFillPolygon (dpy, win, top, pt, 6, Complex, CoordModeOrigin);
+ }
+
+ /* bottom-right shadow */
+ if ((region == NULL) ||
+ (XRectInRegion (region, 0, hms, w, s) != RectangleOut) ||
+ (XRectInRegion (region, wms, 0, s, h) != RectangleOut))
+ {
+ pt[0].x = 0; pt[0].y = h;
+ pt[1].x = w; pt[1].y = h;
+ pt[2].x = w; pt[2].y = 0;
+ pt[3].x = wms; pt[3].y = s;
+ pt[4].x = wms; pt[4].y = hms;
+ pt[5].x = s; pt[5].y = hms;
+ XFillPolygon (dpy, win, bot, pt, 6, Complex, CoordModeOrigin);
+ }
+ }
+}
+
+
+/*
+ * Set the scroll bar to the given location.
+ */
+ void
+vim_XawScrollbarSetThumb(w, top, shown, max)
+ Widget w;
+ double top, shown, max;
+{
+ ScrollbarWidget sbw = (ScrollbarWidget) w;
+
+ if (sbw->scrollbar.scroll_mode == SMODE_CONT) /* if still thumbing */
+ return;
+
+ sbw->scrollbar.max = (max > 1.0) ? 1.0 :
+ (max >= 0.0) ? max : sbw->scrollbar.max;
+
+ sbw->scrollbar.top = (top > sbw->scrollbar.max) ? sbw->scrollbar.max :
+ (top >= 0.0) ? top : sbw->scrollbar.top;
+
+ sbw->scrollbar.shown = (shown > 1.0) ? 1.0 :
+ (shown >= 0.0) ? shown : sbw->scrollbar.shown;
+
+ PaintThumb(sbw);
+}
diff --git a/src/gui_at_sb.h b/src/gui_at_sb.h
new file mode 100644
index 000000000..0d3d1967b
--- /dev/null
+++ b/src/gui_at_sb.h
@@ -0,0 +1,161 @@
+/* vi:set ts=8 sts=4 sw=4: */
+/* MODIFIED ATHENA SCROLLBAR (USING ARROWHEADS AT ENDS OF TRAVEL) */
+/* Modifications Copyright 1992 by Mitch Trachtenberg */
+/* Rights, permissions, and disclaimer of warranty are as in the */
+/* DEC and MIT notice below. See usage warning in .c file. */
+/*
+ * $XConsortium: ScrollbarP.h,v 1.3 94/04/17 20:12:42 jim Exp $
+ */
+
+
+/***********************************************************
+
+Copyright (c) 1987, 1988 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#ifndef _Scrollbar_h
+#define _Scrollbar_h
+
+/****************************************************************
+ *
+ * Scrollbar Widget
+ *
+ ****************************************************************/
+
+#include <X11/IntrinsicP.h>
+#include <X11/Xaw/SimpleP.h>
+#include <X11/Xmu/Converters.h>
+
+/*
+ * Most things we need are in StringDefs.h
+ */
+#define XtCMinimumThumb "MinimumThumb"
+#define XtCShown "Shown"
+#define XtCTopOfThumb "TopOfThumb"
+#define XtCMaxOfThumb "MaxOfThumb"
+#define XtCShadowWidth "ShadowWidth"
+#define XtCTopShadowPixel "TopShadowPixel"
+#define XtCBottomShadowPixel "BottomShadowPixel"
+#define XtCLimitThumb "LimitThumb"
+
+#define XtNminimumThumb "minimumThumb"
+#define XtNtopOfThumb "topOfThumb"
+#define XtNmaxOfThumb "maxOfThumb"
+#define XtNshadowWidth "shadowWidth"
+#define XtNtopShadowPixel "topShadowPixel"
+#define XtNbottomShadowPixel "bottomShadowPixel"
+#define XtNlimitThumb "limitThumb"
+
+typedef struct _ScrollbarRec *ScrollbarWidget;
+typedef struct _ScrollbarClassRec *ScrollbarWidgetClass;
+
+extern WidgetClass vim_scrollbarWidgetClass;
+
+extern void vim_XawScrollbarSetThumb __ARGS((Widget, double, double, double));
+
+typedef struct
+{
+ /* public */
+ Pixel foreground; /* thumb foreground color */
+ XtOrientation orientation; /* horizontal or vertical */
+ XtCallbackList scrollProc; /* proportional scroll */
+ XtCallbackList thumbProc; /* jump (to position) scroll */
+ XtCallbackList jumpProc; /* same as thumbProc but pass data by ref */
+ Pixmap thumb; /* thumb color */
+ float top; /* What percent is above the win's top */
+ float shown; /* What percent is shown in the win */
+ float max; /* Maximum value for top */
+ Dimension length; /* either height or width */
+ Dimension thickness; /* either width or height */
+ Dimension min_thumb; /* minium size for the thumb. */
+
+ /* private */
+ XtIntervalId timer_id; /* autorepeat timer; remove on destruction */
+ char scroll_mode; /* see below */
+ float scroll_off; /* offset from event to top of thumb */
+ GC gc; /* a (shared) gc */
+ Position topLoc; /* Pixel that corresponds to top */
+ Dimension shownLength; /* Num pixels corresponding to shown */
+
+ /* From 3d widget */
+ Dimension shadow_width;
+ Pixel top_shadow_pixel;
+ Pixel bot_shadow_pixel;
+ Bool limit_thumb; /* limit thumb to inside scrollbar */
+ int top_shadow_contrast;
+ int bot_shadow_contrast;
+ GC top_shadow_GC;
+ GC bot_shadow_GC;
+} ScrollbarPart;
+
+#define SMODE_NONE 0
+#define SMODE_CONT 1
+#define SMODE_PAGE_UP 2
+#define SMODE_PAGE_DOWN 3
+#define SMODE_LINE_UP 4
+#define SMODE_LINE_DOWN 5
+
+#define ONE_LINE_DATA 1
+#define ONE_PAGE_DATA 10
+#define END_PAGE_DATA 9999
+
+typedef struct _ScrollbarRec {
+ CorePart core;
+ SimplePart simple;
+ ScrollbarPart scrollbar;
+} ScrollbarRec;
+
+typedef struct {int empty;} ScrollbarClassPart;
+
+typedef struct _ScrollbarClassRec {
+ CoreClassPart core_class;
+ SimpleClassPart simple_class;
+ ScrollbarClassPart scrollbar_class;
+} ScrollbarClassRec;
+
+extern ScrollbarClassRec vim_scrollbarClassRec;
+
+#endif /* _Scrollbar_h */
diff --git a/src/gui_athena.c b/src/gui_athena.c
new file mode 100644
index 000000000..51977eddc
--- /dev/null
+++ b/src/gui_athena.c
@@ -0,0 +1,2230 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI/Motif support by Robert Webb
+ * Athena port by Bill Foster
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include <X11/StringDefs.h>
+#include <X11/Intrinsic.h>
+#ifdef FEAT_GUI_NEXTAW
+# include <X11/neXtaw/Form.h>
+# include <X11/neXtaw/SimpleMenu.h>
+# include <X11/neXtaw/MenuButton.h>
+# include <X11/neXtaw/SmeBSB.h>
+# include <X11/neXtaw/SmeLine.h>
+# include <X11/neXtaw/Box.h>
+# include <X11/neXtaw/Dialog.h>
+# include <X11/neXtaw/Text.h>
+# include <X11/neXtaw/AsciiText.h>
+# include <X11/neXtaw/Scrollbar.h>
+#else
+# include <X11/Xaw/Form.h>
+# include <X11/Xaw/SimpleMenu.h>
+# include <X11/Xaw/MenuButton.h>
+# include <X11/Xaw/SmeBSB.h>
+# include <X11/Xaw/SmeLine.h>
+# include <X11/Xaw/Box.h>
+# include <X11/Xaw/Dialog.h>
+# include <X11/Xaw/Text.h>
+# include <X11/Xaw/AsciiText.h>
+#endif /* FEAT_GUI_NEXTAW */
+
+#include "vim.h"
+#ifndef FEAT_GUI_NEXTAW
+# include "gui_at_sb.h"
+#endif
+
+extern Widget vimShell;
+
+static Widget vimForm = (Widget)0;
+static Widget textArea = (Widget)0;
+#ifdef FEAT_MENU
+static Widget menuBar = (Widget)0;
+static XtIntervalId timer = 0; /* 0 = expired, otherwise active */
+
+/* Used to figure out menu ordering */
+static vimmenu_T *a_cur_menu = NULL;
+static Cardinal athena_calculate_ins_pos __ARGS((Widget));
+
+static Pixmap gui_athena_create_pullright_pixmap __ARGS((Widget));
+static void gui_athena_menu_timeout __ARGS((XtPointer, XtIntervalId *));
+static void gui_athena_popup_callback __ARGS((Widget, XtPointer, XtPointer));
+static void gui_athena_delayed_arm_action __ARGS((Widget, XEvent *, String *,
+ Cardinal *));
+static void gui_athena_popdown_submenus_action __ARGS((Widget, XEvent *,
+ String *, Cardinal *));
+static XtActionsRec pullAction[2] = {
+ { "menu-delayedpopup", (XtActionProc)gui_athena_delayed_arm_action},
+ { "menu-popdownsubmenus", (XtActionProc)gui_athena_popdown_submenus_action}
+};
+#endif
+
+#ifdef FEAT_TOOLBAR
+static void gui_mch_reset_focus __ARGS((void));
+static Widget toolBar = (Widget)0;
+#endif
+
+static void gui_athena_scroll_cb_jump __ARGS((Widget, XtPointer, XtPointer));
+static void gui_athena_scroll_cb_scroll __ARGS((Widget, XtPointer, XtPointer));
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_MENU)
+static void gui_athena_menu_colors __ARGS((Widget id));
+#endif
+static void gui_athena_scroll_colors __ARGS((Widget id));
+
+#ifdef FEAT_MENU
+static XtTranslations popupTrans, parentTrans, menuTrans, supermenuTrans;
+static Pixmap pullerBitmap = None;
+static int puller_width = 0;
+#endif
+
+/*
+ * Scrollbar callback (XtNjumpProc) for when the scrollbar is dragged with the
+ * left or middle mouse button.
+ */
+/* ARGSUSED */
+ static void
+gui_athena_scroll_cb_jump(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data, call_data;
+{
+ scrollbar_T *sb, *sb_info;
+ long value;
+
+ sb = gui_find_scrollbar((long)client_data);
+
+ if (sb == NULL)
+ return;
+ else if (sb->wp != NULL) /* Left or right scrollbar */
+ {
+ /*
+ * Careful: need to get scrollbar info out of first (left) scrollbar
+ * for window, but keep real scrollbar too because we must pass it to
+ * gui_drag_scrollbar().
+ */
+ sb_info = &sb->wp->w_scrollbars[0];
+ }
+ else /* Bottom scrollbar */
+ sb_info = sb;
+
+ value = (long)(*((float *)call_data) * (float)(sb_info->max + 1) + 0.001);
+ if (value > sb_info->max)
+ value = sb_info->max;
+
+ gui_drag_scrollbar(sb, value, TRUE);
+}
+
+/*
+ * Scrollbar callback (XtNscrollProc) for paging up or down with the left or
+ * right mouse buttons.
+ */
+/* ARGSUSED */
+ static void
+gui_athena_scroll_cb_scroll(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data, call_data;
+{
+ scrollbar_T *sb, *sb_info;
+ long value;
+ int data = (int)(long)call_data;
+ int page;
+
+ sb = gui_find_scrollbar((long)client_data);
+
+ if (sb == NULL)
+ return;
+ if (sb->wp != NULL) /* Left or right scrollbar */
+ {
+ /*
+ * Careful: need to get scrollbar info out of first (left) scrollbar
+ * for window, but keep real scrollbar too because we must pass it to
+ * gui_drag_scrollbar().
+ */
+ sb_info = &sb->wp->w_scrollbars[0];
+
+ if (sb_info->size > 5)
+ page = sb_info->size - 2; /* use two lines of context */
+ else
+ page = sb_info->size;
+#ifdef FEAT_GUI_NEXTAW
+ if (data < 0)
+ {
+ data = (data - gui.char_height + 1) / gui.char_height;
+ if (data > -sb_info->size)
+ data = -1;
+ else
+ data = -page;
+ }
+ else if (data > 0)
+ {
+ data = (data + gui.char_height - 1) / gui.char_height;
+ if (data < sb_info->size)
+ data = 1;
+ else
+ data = page;
+ }
+#else
+ switch (data)
+ {
+ case ONE_LINE_DATA: data = 1; break;
+ case -ONE_LINE_DATA: data = -1; break;
+ case ONE_PAGE_DATA: data = page; break;
+ case -ONE_PAGE_DATA: data = -page; break;
+ case END_PAGE_DATA: data = sb_info->max; break;
+ case -END_PAGE_DATA: data = -sb_info->max; break;
+ default: data = 0; break;
+ }
+#endif
+ }
+ else /* Bottom scrollbar */
+ {
+ sb_info = sb;
+#ifdef FEAT_GUI_NEXTAW
+ if (data < 0)
+ {
+ data = (data - gui.char_width + 1) / gui.char_width;
+ if (data > -sb->size)
+ data = -1;
+ }
+ else if (data > 0)
+ {
+ data = (data + gui.char_width - 1) / gui.char_width;
+ if (data < sb->size)
+ data = 1;
+ }
+#endif
+ if (data < -1) /* page-width left */
+ {
+ if (sb->size > 8)
+ data = -(sb->size - 5);
+ else
+ data = -sb->size;
+ }
+ else if (data > 1) /* page-width right */
+ {
+ if (sb->size > 8)
+ data = (sb->size - 5);
+ else
+ data = sb->size;
+ }
+ }
+
+ value = sb_info->value + data;
+ if (value > sb_info->max)
+ value = sb_info->max;
+ else if (value < 0)
+ value = 0;
+
+ /* Update the bottom scrollbar an extra time (why is this needed?? */
+ if (sb->wp == NULL) /* Bottom scrollbar */
+ gui_mch_set_scrollbar_thumb(sb, value, sb->size, sb->max);
+
+ gui_drag_scrollbar(sb, value, FALSE);
+}
+
+/*
+ * Create all the Athena widgets necessary.
+ */
+ void
+gui_x11_create_widgets()
+{
+ /*
+ * We don't have any borders handled internally by the textArea to worry
+ * about so only skip over the configured border width.
+ */
+ gui.border_offset = gui.border_width;
+
+#if 0 /* not needed? */
+ XtInitializeWidgetClass(formWidgetClass);
+ XtInitializeWidgetClass(boxWidgetClass);
+ XtInitializeWidgetClass(coreWidgetClass);
+#ifdef FEAT_MENU
+ XtInitializeWidgetClass(menuButtonWidgetClass);
+#endif
+ XtInitializeWidgetClass(simpleMenuWidgetClass);
+#ifdef FEAT_GUI_NEXTAW
+ XtInitializeWidgetClass(scrollbarWidgetClass);
+#else
+ XtInitializeWidgetClass(vim_scrollbarWidgetClass);
+#endif
+#endif
+
+ /* The form containing all the other widgets */
+ vimForm = XtVaCreateManagedWidget("vimForm",
+ formWidgetClass, vimShell,
+ XtNborderWidth, 0,
+ NULL);
+ gui_athena_scroll_colors(vimForm);
+
+#ifdef FEAT_MENU
+ /* The top menu bar */
+ menuBar = XtVaCreateManagedWidget("menuBar",
+ boxWidgetClass, vimForm,
+ XtNresizable, True,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainRight,
+ XtNinsertPosition, athena_calculate_ins_pos,
+ NULL);
+ gui_athena_menu_colors(menuBar);
+ if (gui.menu_fg_pixel != INVALCOLOR)
+ XtVaSetValues(menuBar, XtNborderColor, gui.menu_fg_pixel, NULL);
+#endif
+
+#ifdef FEAT_TOOLBAR
+ /* Don't create it Managed, it will be managed when creating the first
+ * item. Otherwise an empty toolbar shows up. */
+ toolBar = XtVaCreateWidget("toolBar",
+ boxWidgetClass, vimForm,
+ XtNresizable, True,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainRight,
+ XtNorientation, XtorientHorizontal,
+ XtNhSpace, 1,
+ XtNvSpace, 3,
+ XtNinsertPosition, athena_calculate_ins_pos,
+ NULL);
+ gui_athena_menu_colors(toolBar);
+#endif
+
+ /* The text area. */
+ textArea = XtVaCreateManagedWidget("textArea",
+ coreWidgetClass, vimForm,
+ XtNresizable, True,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainLeft,
+ XtNbackground, gui.back_pixel,
+ XtNborderWidth, 0,
+ NULL);
+
+ /*
+ * Install the callbacks.
+ */
+ gui_x11_callbacks(textArea, vimForm);
+
+#ifdef FEAT_MENU
+ popupTrans = XtParseTranslationTable(
+ "<EnterWindow>: menu-popdownsubmenus() highlight() menu-delayedpopup()\n"
+ "<LeaveWindow>: unhighlight()\n"
+ "<BtnUp>: menu-popdownsubmenus() XtMenuPopdown() notify() unhighlight()\n"
+ "<Motion>: highlight() menu-delayedpopup()");
+ parentTrans = XtParseTranslationTable("<LeaveWindow>: unhighlight()");
+ menuTrans = XtParseTranslationTable(
+ "<EnterWindow>: menu-popdownsubmenus() highlight() menu-delayedpopup()\n"
+ "<LeaveWindow>: menu-popdownsubmenus() XtMenuPopdown() unhighlight()\n"
+ "<BtnUp>: notify() unhighlight()\n"
+ "<BtnMotion>: highlight() menu-delayedpopup()");
+ supermenuTrans = XtParseTranslationTable(
+ "<EnterWindow>: menu-popdownsubmenus() highlight() menu-delayedpopup()\n"
+ "<LeaveWindow>: unhighlight()\n"
+ "<BtnUp>: menu-popdownsubmenus() XtMenuPopdown() notify() unhighlight()\n"
+ "<BtnMotion>: highlight() menu-delayedpopup()");
+
+ XtAppAddActions(XtWidgetToApplicationContext(vimForm), pullAction,
+ XtNumber(pullAction));
+#endif
+
+ /* Pretend we don't have input focus, we will get an event if we do. */
+ gui.in_focus = FALSE;
+}
+
+#ifdef FEAT_MENU
+/*
+ * Calculates the Pixmap based on the size of the current menu font.
+ */
+ static Pixmap
+gui_athena_create_pullright_pixmap(w)
+ Widget w;
+{
+ Pixmap retval;
+#ifdef FONTSET_ALWAYS
+ XFontSet font = None;
+#else
+ XFontStruct *font = NULL;
+#endif
+
+#ifdef FONTSET_ALWAYS
+ if (gui.menu_fontset == NOFONTSET)
+#else
+ if (gui.menu_font == NOFONT)
+#endif
+ {
+ XrmValue from, to;
+ WidgetList children;
+ Cardinal num_children;
+
+#ifdef FONTSET_ALWAYS
+ from.size = strlen(from.addr = XtDefaultFontSet);
+ to.addr = (XtPointer)&font;
+ to.size = sizeof(XFontSet);
+#else
+ from.size = strlen(from.addr = XtDefaultFont);
+ to.addr = (XtPointer)&font;
+ to.size = sizeof(XFontStruct *);
+#endif
+ /* Assumption: The menuBar children will use the same font as the
+ * pulldown menu items AND they will all be of type
+ * XtNfont.
+ */
+ XtVaGetValues(menuBar, XtNchildren, &children,
+ XtNnumChildren, &num_children,
+ NULL);
+ if (XtConvertAndStore(w ? w :
+ (num_children > 0) ? children[0] : menuBar,
+ XtRString, &from,
+#ifdef FONTSET_ALWAYS
+ XtRFontSet, &to
+#else
+ XtRFontStruct, &to
+#endif
+ ) == False)
+ return None;
+ /* "font" should now contain data */
+ }
+ else
+#ifdef FONTSET_ALWAYS
+ font = (XFontSet)gui.menu_fontset;
+#else
+ font = (XFontStruct *)gui.menu_font;
+#endif
+
+ {
+ int width, height;
+ GC draw_gc, undraw_gc;
+ XGCValues gc_values;
+ XPoint points[3];
+
+#ifdef FONTSET_ALWAYS
+ height = fontset_height2(font);
+#else
+ height = font->max_bounds.ascent + font->max_bounds.descent;
+#endif
+ width = height - 2;
+ puller_width = width + 4;
+ retval = XCreatePixmap(gui.dpy,DefaultRootWindow(gui.dpy),width,
+ height, 1);
+ gc_values.foreground = 1;
+ gc_values.background = 0;
+ draw_gc = XCreateGC(gui.dpy, retval,
+ GCForeground | GCBackground,
+ &gc_values);
+ gc_values.foreground = 0;
+ gc_values.background = 1;
+ undraw_gc = XCreateGC(gui.dpy, retval,
+ GCForeground | GCBackground,
+ &gc_values);
+ points[0].x = 0;
+ points[0].y = 0;
+ points[1].x = width - 1;
+ points[1].y = (height - 1) / 2;
+ points[2].x = 0;
+ points[2].y = height - 1;
+ XFillRectangle(gui.dpy, retval, undraw_gc, 0, 0, height, height);
+ XFillPolygon(gui.dpy, retval, draw_gc, points, XtNumber(points),
+ Convex, CoordModeOrigin);
+ XFreeGC(gui.dpy, draw_gc);
+ XFreeGC(gui.dpy, undraw_gc);
+ }
+ return retval;
+}
+#endif
+
+/*
+ * Called when the GUI is not going to start after all.
+ */
+ void
+gui_x11_destroy_widgets()
+{
+ textArea = NULL;
+#ifdef FEAT_MENU
+ menuBar = NULL;
+#endif
+#ifdef FEAT_TOOLBAR
+ toolBar = NULL;
+#endif
+}
+
+#if defined(FEAT_TOOLBAR) || defined(PROTO)
+ void
+gui_mch_set_toolbar_pos(x, y, w, h)
+ int x;
+ int y;
+ int w;
+ int h;
+{
+ Dimension border;
+ int height;
+
+ if (!XtIsManaged(toolBar)) /* nothing to do */
+ return;
+ XtUnmanageChild(toolBar);
+ XtVaGetValues(toolBar,
+ XtNborderWidth, &border,
+ NULL);
+ height = h - 2 * border;
+ if (height < 0)
+ height = 1;
+ XtVaSetValues(toolBar,
+ XtNhorizDistance, x,
+ XtNvertDistance, y,
+ XtNwidth, w - 2 * border,
+ XtNheight, height,
+ NULL);
+ XtManageChild(toolBar);
+}
+#endif
+
+ void
+gui_mch_set_text_area_pos(x, y, w, h)
+ int x;
+ int y;
+ int w;
+ int h;
+{
+ XtUnmanageChild(textArea);
+ XtVaSetValues(textArea,
+ XtNhorizDistance, x,
+ XtNvertDistance, y,
+ XtNwidth, w,
+ XtNheight, h,
+ NULL);
+ XtManageChild(textArea);
+#ifdef FEAT_TOOLBAR
+ /* Give keyboard focus to the textArea instead of the toolbar. */
+ gui_mch_reset_focus();
+#endif
+}
+
+#ifdef FEAT_TOOLBAR
+/*
+ * A toolbar button has been pushed; now reset the input focus
+ * such that the user can type page up/down etc. and have the
+ * input go to the editor window, not the button
+ */
+ static void
+gui_mch_reset_focus()
+{
+ XtSetKeyboardFocus(vimForm, textArea);
+}
+#endif
+
+
+ void
+gui_x11_set_back_color()
+{
+ if (textArea != NULL)
+ XtVaSetValues(textArea,
+ XtNbackground, gui.back_pixel,
+ NULL);
+}
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Menu stuff.
+ */
+
+static char_u *make_pull_name __ARGS((char_u * name));
+static Widget get_popup_entry __ARGS((Widget w));
+static Widget submenu_widget __ARGS((Widget));
+static Boolean has_submenu __ARGS((Widget));
+static void gui_mch_submenu_change __ARGS((vimmenu_T *mp, int colors));
+static void gui_athena_menu_font __ARGS((Widget id));
+static Boolean gui_athena_menu_has_submenus __ARGS((Widget, Widget));
+
+ void
+gui_mch_enable_menu(flag)
+ int flag;
+{
+ if (flag)
+ {
+ XtManageChild(menuBar);
+# ifdef FEAT_TOOLBAR
+ if (XtIsManaged(toolBar))
+ {
+ XtVaSetValues(toolBar,
+ XtNvertDistance, gui.menu_height,
+ NULL);
+ XtVaSetValues(textArea,
+ XtNvertDistance, gui.menu_height + gui.toolbar_height,
+ NULL);
+ }
+# endif
+ }
+ else
+ {
+ XtUnmanageChild(menuBar);
+# ifdef FEAT_TOOLBAR
+ if (XtIsManaged(toolBar))
+ {
+ XtVaSetValues(toolBar,
+ XtNvertDistance, 0,
+ NULL);
+ }
+# endif
+ }
+}
+
+ void
+gui_mch_set_menu_pos(x, y, w, h)
+ int x;
+ int y;
+ int w;
+ int h;
+{
+ Dimension border;
+ int height;
+
+ XtUnmanageChild(menuBar);
+ XtVaGetValues(menuBar, XtNborderWidth, &border, NULL);
+ /* avoid trouble when there are no menu items, and h is 1 */
+ height = h - 2 * border;
+ if (height < 0)
+ height = 1;
+ XtVaSetValues(menuBar,
+ XtNhorizDistance, x,
+ XtNvertDistance, y,
+ XtNwidth, w - 2 * border,
+ XtNheight, height,
+ NULL);
+ XtManageChild(menuBar);
+}
+
+/*
+ * Used to calculate the insertion position of a widget with respect to its
+ * neighbors.
+ *
+ * Valid range of return values is: 0 (beginning of children) to
+ * numChildren (end of children).
+ */
+ static Cardinal
+athena_calculate_ins_pos(widget)
+ Widget widget;
+{
+ /* Assume that if the parent of the vimmenu_T is NULL, then we can get
+ * to this menu by traversing "next", starting at "root_menu".
+ *
+ * This holds true for popup menus, toolbar, and toplevel menu items.
+ */
+
+ /* Popup menus: "id" is NULL. Only submenu_id is valid */
+
+ /* Menus that are not toplevel: "parent" will be non-NULL, "id" &
+ * "submenu_id" will be non-NULL.
+ */
+
+ /* Toplevel menus: "parent" is NULL, id is the widget of the menu item */
+
+ WidgetList children;
+ Cardinal num_children = 0;
+ int retval;
+ Arg args[2];
+ int n = 0;
+ int i;
+
+ XtSetArg(args[n], XtNchildren, &children); n++;
+ XtSetArg(args[n], XtNnumChildren, &num_children); n++;
+ XtGetValues(XtParent(widget), args, n);
+
+ retval = num_children;
+ for (i = 0; i < num_children; ++i)
+ {
+ Widget current = children[i];
+ vimmenu_T *menu = NULL;
+
+ for (menu = (a_cur_menu->parent == NULL)
+ ? root_menu : a_cur_menu->parent->children;
+ menu != NULL;
+ menu = menu->next)
+ if (current == menu->id
+ && a_cur_menu->priority < menu->priority
+ && i < retval)
+ retval = i;
+ }
+ return retval;
+}
+
+/* ARGSUSED */
+ void
+gui_mch_add_menu(menu, idx)
+ vimmenu_T *menu;
+ int idx;
+{
+ char_u *pullright_name;
+ Dimension height, space, border;
+ vimmenu_T *parent = menu->parent;
+
+ a_cur_menu = menu;
+ if (parent == NULL)
+ {
+ if (menu_is_popup(menu->dname))
+ {
+ menu->submenu_id = XtVaCreatePopupShell((char *)menu->dname,
+ simpleMenuWidgetClass, vimShell,
+ XtNinsertPosition, athena_calculate_ins_pos,
+ XtNtranslations, popupTrans,
+ NULL);
+ gui_athena_menu_colors(menu->submenu_id);
+ }
+ else if (menu_is_menubar(menu->dname))
+ {
+ menu->id = XtVaCreateManagedWidget((char *)menu->dname,
+ menuButtonWidgetClass, menuBar,
+ XtNmenuName, menu->dname,
+#ifdef FONTSET_ALWAYS
+ XtNinternational, True,
+#endif
+ NULL);
+ if (menu->id == (Widget)0)
+ return;
+ gui_athena_menu_colors(menu->id);
+ gui_athena_menu_font(menu->id);
+
+ menu->submenu_id = XtVaCreatePopupShell((char *)menu->dname,
+ simpleMenuWidgetClass, menu->id,
+ XtNinsertPosition, athena_calculate_ins_pos,
+ XtNtranslations, supermenuTrans,
+ NULL);
+ gui_athena_menu_colors(menu->submenu_id);
+ gui_athena_menu_font(menu->submenu_id);
+
+ /* Don't update the menu height when it was set at a fixed value */
+ if (!gui.menu_height_fixed)
+ {
+ /*
+ * When we add a top-level item to the menu bar, we can figure
+ * out how high the menu bar should be.
+ */
+ XtVaGetValues(menuBar,
+ XtNvSpace, &space,
+ XtNborderWidth, &border,
+ NULL);
+ XtVaGetValues(menu->id,
+ XtNheight, &height,
+ NULL);
+ gui.menu_height = height + 2 * (space + border);
+ }
+ }
+ }
+ else if (parent->submenu_id != (Widget)0)
+ {
+ menu->id = XtVaCreateManagedWidget((char *)menu->dname,
+ smeBSBObjectClass, parent->submenu_id,
+ XtNlabel, menu->dname,
+#ifdef FONTSET_ALWAYS
+ XtNinternational, True,
+#endif
+ NULL);
+ if (menu->id == (Widget)0)
+ return;
+ if (pullerBitmap == None)
+ pullerBitmap = gui_athena_create_pullright_pixmap(menu->id);
+
+ XtVaSetValues(menu->id, XtNrightBitmap, pullerBitmap,
+ NULL);
+ /* If there are other menu items that are not pulldown menus,
+ * we need to adjust the right margins of those, too.
+ */
+ {
+ WidgetList children;
+ Cardinal num_children;
+ int i;
+
+ XtVaGetValues(parent->submenu_id, XtNchildren, &children,
+ XtNnumChildren, &num_children,
+ NULL);
+ for (i = 0; i < num_children; ++i)
+ {
+ XtVaSetValues(children[i],
+ XtNrightMargin, puller_width,
+ NULL);
+ }
+ }
+ gui_athena_menu_colors(menu->id);
+ gui_athena_menu_font(menu->id);
+
+ pullright_name = make_pull_name(menu->dname);
+ menu->submenu_id = XtVaCreatePopupShell((char *)pullright_name,
+ simpleMenuWidgetClass, parent->submenu_id,
+ XtNtranslations, menuTrans,
+ NULL);
+ gui_athena_menu_colors(menu->submenu_id);
+ gui_athena_menu_font(menu->submenu_id);
+ vim_free(pullright_name);
+ XtAddCallback(menu->submenu_id, XtNpopupCallback,
+ gui_athena_popup_callback, (XtPointer)menu);
+
+ if (parent->parent != NULL)
+ XtOverrideTranslations(parent->submenu_id, parentTrans);
+ }
+ a_cur_menu = NULL;
+}
+
+/* Used to determine whether a SimpleMenu has pulldown entries.
+ *
+ * "id" is the parent of the menu items.
+ * Ignore widget "ignore" in the pane.
+ */
+ static Boolean
+gui_athena_menu_has_submenus(id, ignore)
+ Widget id;
+ Widget ignore;
+{
+ WidgetList children;
+ Cardinal num_children;
+ int i;
+
+ XtVaGetValues(id, XtNchildren, &children,
+ XtNnumChildren, &num_children,
+ NULL);
+ for (i = 0; i < num_children; ++i)
+ {
+ if (children[i] == ignore)
+ continue;
+ if (has_submenu(children[i]))
+ return True;
+ }
+ return False;
+}
+
+ static void
+gui_athena_menu_font(id)
+ Widget id;
+{
+#ifdef FONTSET_ALWAYS
+ if (gui.menu_fontset != NOFONTSET)
+ {
+ if (XtIsManaged(id))
+ {
+ XtUnmanageChild(id);
+ XtVaSetValues(id, XtNfontSet, gui.menu_fontset, NULL);
+ /* We should force the widget to recalculate it's
+ * geometry now. */
+ XtManageChild(id);
+ }
+ else
+ XtVaSetValues(id, XtNfontSet, gui.menu_fontset, NULL);
+ if (has_submenu(id))
+ XtVaSetValues(id, XtNrightBitmap, pullerBitmap, NULL);
+ }
+#else
+ int managed = FALSE;
+
+ if (gui.menu_font != NOFONT)
+ {
+ if (XtIsManaged(id))
+ {
+ XtUnmanageChild(id);
+ managed = TRUE;
+ }
+
+# ifdef FEAT_XFONTSET
+ if (gui.fontset != NOFONTSET)
+ XtVaSetValues(id, XtNfontSet, gui.menu_font, NULL);
+ else
+# endif
+ XtVaSetValues(id, XtNfont, gui.menu_font, NULL);
+ if (has_submenu(id))
+ XtVaSetValues(id, XtNrightBitmap, pullerBitmap, NULL);
+
+ /* Force the widget to recalculate it's geometry now. */
+ if (managed)
+ XtManageChild(id);
+ }
+#endif
+}
+
+
+ void
+gui_mch_new_menu_font()
+{
+ Pixmap oldpuller = None;
+
+ if (menuBar == (Widget)0)
+ return;
+
+ if (pullerBitmap != None)
+ {
+ oldpuller = pullerBitmap;
+ pullerBitmap = gui_athena_create_pullright_pixmap(NULL);
+ }
+ gui_mch_submenu_change(root_menu, FALSE);
+
+ {
+ /* Iterate through the menubar menu items and get the height of
+ * each one. The menu bar height is set to the maximum of all
+ * the heights.
+ */
+ vimmenu_T *mp;
+ int max_height = 9999;
+
+ for (mp = root_menu; mp != NULL; mp = mp->next)
+ {
+ if (menu_is_menubar(mp->dname))
+ {
+ Dimension height;
+
+ XtVaGetValues(mp->id,
+ XtNheight,(XtArgVal *)&height,
+ NULL);
+ if (height < max_height)
+ max_height = height;
+ }
+ }
+ if (max_height != 9999)
+ {
+ /* Don't update the menu height when it was set at a fixed value */
+ if (!gui.menu_height_fixed)
+ {
+ Dimension space, border;
+
+ XtVaGetValues(menuBar,
+ XtNvSpace, &space,
+ XtNborderWidth, &border,
+ NULL);
+ gui.menu_height = max_height + 2 * (space + border);
+ }
+ }
+ }
+ /* Now, to simulate the window being resized. Only, this
+ * will resize the window to it's current state.
+ *
+ * There has to be a better way, but I do not see one at this time.
+ * (David Harrison)
+ */
+ {
+ Position w, h;
+
+ XtVaGetValues(vimShell,
+ XtNwidth, &w,
+ XtNheight, &h,
+ NULL);
+ gui_resize_shell(w, h
+#ifdef FEAT_XIM
+ - xim_get_status_area_height()
+#endif
+ );
+ }
+ gui_set_shellsize(FALSE, TRUE);
+ ui_new_shellsize();
+ if (oldpuller != None)
+ XFreePixmap(gui.dpy, oldpuller);
+}
+
+#if defined(FEAT_BEVAL) || defined(PROTO)
+ void
+gui_mch_new_tooltip_font()
+{
+# ifdef FEAT_TOOLBAR
+ vimmenu_T *menu;
+
+ if (toolBar == (Widget)0)
+ return;
+
+ menu = gui_find_menu((char_u *)"ToolBar");
+ if (menu != NULL)
+ gui_mch_submenu_change(menu, FALSE);
+# endif
+}
+
+ void
+gui_mch_new_tooltip_colors()
+{
+# ifdef FEAT_TOOLBAR
+ vimmenu_T *menu;
+
+ if (toolBar == (Widget)0)
+ return;
+
+ menu = gui_find_menu((char_u *)"ToolBar");
+ if (menu != NULL)
+ gui_mch_submenu_change(menu, TRUE);
+# endif
+}
+#endif
+
+ static void
+gui_mch_submenu_change(menu, colors)
+ vimmenu_T *menu;
+ int colors; /* TRUE for colors, FALSE for font */
+{
+ vimmenu_T *mp;
+
+ for (mp = menu; mp != NULL; mp = mp->next)
+ {
+ if (mp->id != (Widget)0)
+ {
+ if (colors)
+ {
+ gui_athena_menu_colors(mp->id);
+#ifdef FEAT_TOOLBAR
+ /* For a toolbar item: Free the pixmap and allocate a new one,
+ * so that the background color is right. */
+ if (mp->image != (Pixmap)0)
+ {
+ XFreePixmap(gui.dpy, mp->image);
+ get_toolbar_pixmap(mp, &mp->image, NULL);
+ if (mp->image != (Pixmap)0)
+ XtVaSetValues(mp->id, XtNbitmap, mp->image, NULL);
+ }
+
+# ifdef FEAT_BEVAL
+ /* If we have a tooltip, then we need to change it's colors */
+ if (mp->tip != NULL)
+ {
+ Arg args[2];
+
+ args[0].name = XtNbackground;
+ args[0].value = gui.tooltip_bg_pixel;
+ args[1].name = XtNforeground;
+ args[1].value = gui.tooltip_fg_pixel;
+ XtSetValues(mp->tip->balloonLabel, &args[0], XtNumber(args));
+ }
+# endif
+#endif
+ }
+ else
+ {
+ gui_athena_menu_font(mp->id);
+#ifdef FEAT_BEVAL
+ /* If we have a tooltip, then we need to change it's font */
+ /* Assume XtNinternational == True (in createBalloonEvalWindow)
+ */
+ if (mp->tip != NULL)
+ {
+ Arg args[1];
+
+ args[0].name = XtNfontSet;
+ args[0].value = (XtArgVal)gui.tooltip_fontset;
+ XtSetValues(mp->tip->balloonLabel, &args[0], XtNumber(args));
+ }
+#endif
+ }
+ }
+
+ if (mp->children != NULL)
+ {
+ /* Set the colors/font for the tear off widget */
+ if (mp->submenu_id != (Widget)0)
+ {
+ if (colors)
+ gui_athena_menu_colors(mp->submenu_id);
+ else
+ gui_athena_menu_font(mp->submenu_id);
+ }
+ /* Set the colors for the children */
+ gui_mch_submenu_change(mp->children, colors);
+ }
+ }
+}
+
+/*
+ * Make a submenu name into a pullright name.
+ * Replace '.' by '_', can't include '.' in the submenu name.
+ */
+ static char_u *
+make_pull_name(name)
+ char_u * name;
+{
+ char_u *pname;
+ char_u *p;
+
+ pname = vim_strnsave(name, STRLEN(name) + strlen("-pullright"));
+ if (pname != NULL)
+ {
+ strcat((char *)pname, "-pullright");
+ while ((p = vim_strchr(pname, '.')) != NULL)
+ *p = '_';
+ }
+ return pname;
+}
+
+/* ARGSUSED */
+ void
+gui_mch_add_menu_item(menu, idx)
+ vimmenu_T *menu;
+ int idx;
+{
+ vimmenu_T *parent = menu->parent;
+
+ a_cur_menu = menu;
+# ifdef FEAT_TOOLBAR
+ if (menu_is_toolbar(parent->name))
+ {
+ WidgetClass type;
+ int n;
+ Arg args[21];
+
+ n = 0;
+ if (menu_is_separator(menu->name))
+ {
+ XtSetArg(args[n], XtNlabel, ""); n++;
+ XtSetArg(args[n], XtNborderWidth, 0); n++;
+ }
+ else
+ {
+ get_toolbar_pixmap(menu, &menu->image, NULL);
+ XtSetArg(args[n], XtNlabel, menu->dname); n++;
+ XtSetArg(args[n], XtNinternalHeight, 1); n++;
+ XtSetArg(args[n], XtNinternalWidth, 1); n++;
+ XtSetArg(args[n], XtNborderWidth, 1); n++;
+ if (menu->image != 0)
+ XtSetArg(args[n], XtNbitmap, menu->image); n++;
+ }
+ XtSetArg(args[n], XtNhighlightThickness, 0); n++;
+ type = commandWidgetClass;
+ /* TODO: figure out the position in the toolbar?
+ * This currently works fine for the default toolbar, but
+ * what if we add/remove items during later runtime?
+ */
+
+ /* NOTE: "idx" isn't used here. The position is calculated by
+ * athena_calculate_ins_pos(). The position it calculates
+ * should be equal to "idx".
+ */
+ /* TODO: Could we just store "idx" and use that as the child
+ * placement?
+ */
+
+ if (menu->id == NULL)
+ {
+ menu->id = XtCreateManagedWidget((char *)menu->dname,
+ type, toolBar, args, n);
+ XtAddCallback(menu->id,
+ XtNcallback, gui_x11_menu_cb, menu);
+ }
+ else
+ XtSetValues(menu->id, args, n);
+ gui_athena_menu_colors(menu->id);
+
+#ifdef FEAT_BEVAL
+ gui_mch_menu_set_tip(menu);
+#endif
+
+ menu->parent = parent;
+ menu->submenu_id = NULL;
+ if (!XtIsManaged(toolBar)
+ && vim_strchr(p_go, GO_TOOLBAR) != NULL)
+ gui_mch_show_toolbar(TRUE);
+ gui.toolbar_height = gui_mch_compute_toolbar_height();
+ return;
+ } /* toolbar menu item */
+# endif
+
+ /* Add menu separator */
+ if (menu_is_separator(menu->name))
+ {
+ menu->submenu_id = (Widget)0;
+ menu->id = XtVaCreateManagedWidget((char *)menu->dname,
+ smeLineObjectClass, parent->submenu_id,
+ NULL);
+ if (menu->id == (Widget)0)
+ return;
+ gui_athena_menu_colors(menu->id);
+ }
+ else
+ {
+ if (parent != NULL && parent->submenu_id != (Widget)0)
+ {
+ menu->submenu_id = (Widget)0;
+ menu->id = XtVaCreateManagedWidget((char *)menu->dname,
+ smeBSBObjectClass, parent->submenu_id,
+ XtNlabel, menu->dname,
+#ifdef FONTSET_ALWAYS
+ XtNinternational, True,
+#endif
+ NULL);
+ if (menu->id == (Widget)0)
+ return;
+
+ /* If there are other "pulldown" items in this pane, then adjust
+ * the right margin to accomodate the arrow pixmap, otherwise
+ * the right margin will be the same as the left margin.
+ */
+ {
+ Dimension left_margin;
+
+ XtVaGetValues(menu->id, XtNleftMargin, &left_margin, NULL);
+ XtVaSetValues(menu->id, XtNrightMargin,
+ gui_athena_menu_has_submenus(parent->submenu_id, NULL) ?
+ puller_width :
+ left_margin,
+ NULL);
+ }
+
+ gui_athena_menu_colors(menu->id);
+ gui_athena_menu_font(menu->id);
+ XtAddCallback(menu->id, XtNcallback, gui_x11_menu_cb,
+ (XtPointer)menu);
+ }
+ }
+ a_cur_menu = NULL;
+}
+
+#if defined(FEAT_TOOLBAR) || defined(PROTO)
+ void
+gui_mch_show_toolbar(int showit)
+{
+ Cardinal numChildren; /* how many children toolBar has */
+
+ if (toolBar == (Widget)0)
+ return;
+ XtVaGetValues(toolBar, XtNnumChildren, &numChildren, NULL);
+ if (showit && numChildren > 0)
+ {
+ /* Assume that we want to show the toolbar if p_toolbar contains valid
+ * option settings, therefore p_toolbar must not be NULL.
+ */
+ WidgetList children;
+
+ XtVaGetValues(toolBar, XtNchildren, &children, NULL);
+ {
+ void (*action)(BalloonEval *);
+ int text = 0;
+
+ if (strstr((const char *)p_toolbar, "tooltips"))
+ action = &gui_mch_enable_beval_area;
+ else
+ action = &gui_mch_disable_beval_area;
+ if (strstr((const char *)p_toolbar, "text"))
+ text = 1;
+ else if (strstr((const char *)p_toolbar, "icons"))
+ text = -1;
+ if (text != 0)
+ {
+ vimmenu_T *toolbar;
+ vimmenu_T *cur;
+
+ for (toolbar = root_menu; toolbar; toolbar = toolbar->next)
+ if (menu_is_toolbar(toolbar->dname))
+ break;
+ /* Assumption: toolbar is NULL if there is no toolbar,
+ * otherwise it contains the toolbar menu structure.
+ *
+ * Assumption: "numChildren" == the number of items in the list
+ * of items beginning with toolbar->children.
+ */
+ if (toolbar)
+ {
+ for (cur = toolbar->children; cur; cur = cur->next)
+ {
+ Arg args[2];
+ int n = 0;
+
+ /* Enable/Disable tooltip (OK to enable while currently
+ * enabled)
+ */
+ if (cur->tip != NULL)
+ (*action)(cur->tip);
+ if (text == 1)
+ {
+ XtSetArg(args[n], XtNbitmap, None);
+ n++;
+ XtSetArg(args[n], XtNlabel,
+ menu_is_separator(cur->name) ? "" :
+ (char *)cur->dname);
+ n++;
+ }
+ else
+ {
+ XtSetArg(args[n], XtNbitmap, cur->image);
+ n++;
+ XtSetArg(args[n], XtNlabel, (cur->image == None) ?
+ menu_is_separator(cur->name) ?
+ "" :
+ (char *)cur->dname
+ :
+ (char *)None);
+ n++;
+ }
+ if (cur->id != NULL)
+ {
+ XtUnmanageChild(cur->id);
+ XtSetValues(cur->id, args, n);
+ XtManageChild(cur->id);
+ }
+ }
+ }
+ }
+ }
+ gui.toolbar_height = gui_mch_compute_toolbar_height();
+ XtManageChild(toolBar);
+ if (XtIsManaged(menuBar))
+ {
+ XtVaSetValues(textArea,
+ XtNvertDistance, gui.toolbar_height + gui.menu_height,
+ NULL);
+ XtVaSetValues(toolBar,
+ XtNvertDistance, gui.menu_height,
+ NULL);
+ }
+ else
+ {
+ XtVaSetValues(textArea,
+ XtNvertDistance, gui.toolbar_height,
+ NULL);
+ XtVaSetValues(toolBar,
+ XtNvertDistance, 0,
+ NULL);
+ }
+ }
+ else
+ {
+ gui.toolbar_height = 0;
+ if (XtIsManaged(menuBar))
+ XtVaSetValues(textArea,
+ XtNvertDistance, gui.menu_height,
+ NULL);
+ else
+ XtVaSetValues(textArea,
+ XtNvertDistance, 0,
+ NULL);
+
+ XtUnmanageChild(toolBar);
+ }
+ gui_set_shellsize(FALSE, FALSE);
+}
+
+
+ int
+gui_mch_compute_toolbar_height()
+{
+ Dimension height; /* total Toolbar height */
+ Dimension whgt; /* height of each widget */
+ Dimension marginHeight; /* XmNmarginHeight of toolBar */
+ Dimension shadowThickness; /* thickness of Xtparent(toolBar) */
+ WidgetList children; /* list of toolBar's children */
+ Cardinal numChildren; /* how many children toolBar has */
+ int i;
+
+ height = 0;
+ shadowThickness = 0;
+ marginHeight = 0;
+ if (toolBar != (Widget)0)
+ {
+ XtVaGetValues(toolBar,
+ XtNborderWidth, &shadowThickness,
+ XtNvSpace, &marginHeight,
+ XtNchildren, &children,
+ XtNnumChildren, &numChildren,
+ NULL);
+ for (i = 0; i < numChildren; i++)
+ {
+ whgt = 0;
+
+ XtVaGetValues(children[i], XtNheight, &whgt, NULL);
+ if (height < whgt)
+ height = whgt;
+ }
+ }
+
+ return (int)(height + (marginHeight << 1) + (shadowThickness << 1));
+}
+
+ void
+gui_mch_get_toolbar_colors(bgp, fgp, bsp, tsp, hsp)
+ Pixel *bgp;
+ Pixel *fgp;
+ Pixel *bsp;
+ Pixel *tsp;
+ Pixel *hsp;
+{
+ XtVaGetValues(toolBar, XtNbackground, bgp, XtNborderColor, fgp, NULL);
+ *bsp = *bgp;
+ *tsp = *fgp;
+ *hsp = *tsp;
+}
+#endif
+
+
+/* ARGSUSED */
+ void
+gui_mch_toggle_tearoffs(enable)
+ int enable;
+{
+ /* no tearoff menus */
+}
+
+ void
+gui_mch_new_menu_colors()
+{
+ if (menuBar == (Widget)0)
+ return;
+ if (gui.menu_fg_pixel != INVALCOLOR)
+ XtVaSetValues(menuBar, XtNborderColor, gui.menu_fg_pixel, NULL);
+ gui_athena_menu_colors(menuBar);
+#ifdef FEAT_TOOLBAR
+ gui_athena_menu_colors(toolBar);
+#endif
+
+ gui_mch_submenu_change(root_menu, TRUE);
+}
+
+/*
+ * Destroy the machine specific menu widget.
+ */
+ void
+gui_mch_destroy_menu(menu)
+ vimmenu_T *menu;
+{
+ Widget parent;
+
+ /* There is no item for the toolbar. */
+ if (menu->id == (Widget)0)
+ return;
+
+ parent = XtParent(menu->id);
+
+ /* When removing the last "pulldown" menu item from a pane, adjust the
+ * right margins of the remaining widgets.
+ */
+ if (menu->submenu_id != (Widget)0)
+ {
+ /* Go through the menu items in the parent of this item and
+ * adjust their margins, if necessary.
+ * This takes care of the case when we delete the last menu item in a
+ * pane that has a submenu. In this case, there will be no arrow
+ * pixmaps shown anymore.
+ */
+ {
+ WidgetList children;
+ Cardinal num_children;
+ int i;
+ Dimension right_margin = 0;
+ Boolean get_left_margin = False;
+
+ XtVaGetValues(parent, XtNchildren, &children,
+ XtNnumChildren, &num_children,
+ NULL);
+ if (gui_athena_menu_has_submenus(parent, menu->id))
+ right_margin = puller_width;
+ else
+ get_left_margin = True;
+
+ for (i = 0; i < num_children; ++i)
+ {
+ if (children[i] == menu->id)
+ continue;
+ if (get_left_margin == True)
+ {
+ Dimension left_margin;
+
+ XtVaGetValues(children[i], XtNleftMargin, &left_margin,
+ NULL);
+ XtVaSetValues(children[i], XtNrightMargin, left_margin,
+ NULL);
+ }
+ else
+ XtVaSetValues(children[i], XtNrightMargin, right_margin,
+ NULL);
+ }
+ }
+ }
+ /* Please be sure to destroy the parent widget first (i.e. menu->id).
+ *
+ * This code should be basically identical to that in the file gui_motif.c
+ * because they are both Xt based.
+ */
+ if (menu->id != (Widget)0)
+ {
+ Cardinal num_children;
+ Dimension height, space, border;
+
+ XtVaGetValues(menuBar,
+ XtNvSpace, &space,
+ XtNborderWidth, &border,
+ NULL);
+ XtVaGetValues(menu->id,
+ XtNheight, &height,
+ NULL);
+#if defined(FEAT_TOOLBAR) && defined(FEAT_BEVAL)
+ if (parent == toolBar && menu->tip != NULL)
+ {
+ /* We try to destroy this before the actual menu, because there are
+ * callbacks, etc. that will be unregistered during the tooltip
+ * destruction.
+ *
+ * If you call "gui_mch_destroy_beval_area()" after destroying
+ * menu->id, then the tooltip's window will have already been
+ * deallocated by Xt, and unknown behaviour will ensue (probably
+ * a core dump).
+ */
+ gui_mch_destroy_beval_area(menu->tip);
+ menu->tip = NULL;
+ }
+#endif
+ /*
+ * This is a hack to stop the Athena simpleMenuWidget from getting a
+ * BadValue error when a menu's last child is destroyed. We check to
+ * see if this is the last child and if so, don't delete it. The parent
+ * will be deleted soon anyway, and it will delete it's children like
+ * all good widgets do.
+ */
+ /* NOTE: The cause of the BadValue X Protocol Error is because when the
+ * last child is destroyed, it is first unmanaged, thus causing a
+ * geometry resize request from the parent Shell widget.
+ * Since the Shell widget has no more children, it is resized to have
+ * width/height of 0. XConfigureWindow() is then called with the
+ * width/height of 0, which generates the BadValue.
+ *
+ * This happens in phase two of the widget destruction process.
+ */
+ {
+ if (parent != menuBar
+#ifdef FEAT_TOOLBAR
+ && parent != toolBar
+#endif
+ )
+ {
+ XtVaGetValues(parent, XtNnumChildren, &num_children, NULL);
+ if (num_children > 1)
+ XtDestroyWidget(menu->id);
+ }
+ else
+ XtDestroyWidget(menu->id);
+ menu->id = (Widget)0;
+ }
+
+ if (parent == menuBar)
+ {
+ if (!gui.menu_height_fixed)
+ gui.menu_height = height + 2 * (space + border);
+ }
+#ifdef FEAT_TOOLBAR
+ else if (parent == toolBar)
+ {
+ /* When removing last toolbar item, don't display the toolbar. */
+ XtVaGetValues(toolBar, XtNnumChildren, &num_children, NULL);
+ if (num_children == 0)
+ gui_mch_show_toolbar(FALSE);
+ else
+ gui.toolbar_height = gui_mch_compute_toolbar_height();
+ }
+#endif
+ }
+ if (menu->submenu_id != (Widget)0)
+ {
+ XtDestroyWidget(menu->submenu_id);
+ menu->submenu_id = (Widget)0;
+ }
+}
+
+/*ARGSUSED*/
+ static void
+gui_athena_menu_timeout(client_data, id)
+ XtPointer client_data;
+ XtIntervalId *id;
+{
+ Widget w = (Widget)client_data;
+ Widget popup;
+
+ timer = 0;
+ if (XtIsSubclass(w,smeBSBObjectClass))
+ {
+ Pixmap p;
+
+ XtVaGetValues(w, XtNrightBitmap, &p, NULL);
+ if ((p != None) && (p != XtUnspecifiedPixmap))
+ {
+ /* We are dealing with an item that has a submenu */
+ popup = get_popup_entry(XtParent(w));
+ if (popup == (Widget)0)
+ return;
+ XtPopup(popup, XtGrabNonexclusive);
+ }
+ }
+}
+
+/* This routine is used to calculate the position (in screen coordinates)
+ * where a submenu should appear relative to the menu entry that popped it
+ * up. It should appear even with and just slightly to the left of the
+ * rightmost end of the menu entry that caused the popup.
+ *
+ * This is called when XtPopup() is called.
+ */
+/*ARGSUSED*/
+ static void
+gui_athena_popup_callback(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data;
+ XtPointer call_data;
+{
+ /* Assumption: XtIsSubclass(XtParent(w),simpleMenuWidgetClass) */
+ vimmenu_T *menu = (vimmenu_T *)client_data;
+ Dimension width;
+ Position root_x, root_y;
+
+ /* First, popdown any siblings that may have menus popped up */
+ {
+ vimmenu_T *i;
+
+ for (i = menu->parent->children; i != NULL; i = i->next)
+ {
+ if (i->submenu_id != NULL && XtIsManaged(i->submenu_id))
+ XtPopdown(i->submenu_id);
+ }
+ }
+ XtVaGetValues(XtParent(w),
+ XtNwidth, &width,
+ NULL);
+ /* Assumption: XawSimpleMenuGetActiveEntry(XtParent(w)) == menu->id */
+ /* i.e. This IS the active entry */
+ XtTranslateCoords(menu->id,width - 5, 0, &root_x, &root_y);
+ XtVaSetValues(w, XtNx, root_x,
+ XtNy, root_y,
+ NULL);
+}
+
+/* ARGSUSED */
+ static void
+gui_athena_popdown_submenus_action(w, event, args, nargs)
+ Widget w;
+ XEvent *event;
+ String *args;
+ Cardinal *nargs;
+{
+ WidgetList children;
+ Cardinal num_children;
+
+ XtVaGetValues(w, XtNchildren, &children,
+ XtNnumChildren, &num_children,
+ NULL);
+ for (; num_children > 0; --num_children)
+ {
+ Widget child = children[num_children - 1];
+
+ if (has_submenu(child))
+ {
+ Widget temp_w;
+
+ temp_w = submenu_widget(child);
+ gui_athena_popdown_submenus_action(temp_w,event,args,nargs);
+ XtPopdown(temp_w);
+ }
+ }
+}
+
+/* Used to determine if the given widget has a submenu that can be popped up. */
+ static Boolean
+has_submenu(widget)
+ Widget widget;
+{
+ if ((widget != NULL) && XtIsSubclass(widget,smeBSBObjectClass))
+ {
+ Pixmap p;
+
+ XtVaGetValues(widget, XtNrightBitmap, &p, NULL);
+ if ((p != None) && (p != XtUnspecifiedPixmap))
+ return True;
+ }
+ return False;
+}
+
+/* ARGSUSED */
+ static void
+gui_athena_delayed_arm_action(w, event, args, nargs)
+ Widget w;
+ XEvent *event;
+ String *args;
+ Cardinal *nargs;
+{
+ Dimension width, height;
+
+ if (event->type != MotionNotify)
+ return;
+
+ XtVaGetValues(w,
+ XtNwidth, &width,
+ XtNheight, &height,
+ NULL);
+
+ if (event->xmotion.x >= (int)width || event->xmotion.y >= (int)height)
+ return;
+
+ {
+ static Widget previous_active_widget = NULL;
+ Widget current;
+
+ current = XawSimpleMenuGetActiveEntry(w);
+ if (current != previous_active_widget)
+ {
+ if (timer)
+ {
+ /* If the timeout hasn't been triggered, remove it */
+ XtRemoveTimeOut(timer);
+ }
+ gui_athena_popdown_submenus_action(w,event,args,nargs);
+ if (has_submenu(current))
+ {
+ XtAppAddTimeOut(XtWidgetToApplicationContext(w), 600L,
+ gui_athena_menu_timeout,
+ (XtPointer)current);
+ }
+ previous_active_widget = current;
+ }
+ }
+}
+
+ static Widget
+get_popup_entry(w)
+ Widget w;
+{
+ Widget menuw;
+
+ /* Get the active entry for the current menu */
+ if ((menuw = XawSimpleMenuGetActiveEntry(w)) == (Widget)0)
+ return NULL;
+
+ return submenu_widget(menuw);
+}
+
+/* Given the widget that has been determined to have a submenu, return the submenu widget
+ * that is to be popped up.
+ */
+ static Widget
+submenu_widget(widget)
+ Widget widget;
+{
+ /* Precondition: has_submenu(widget) == True
+ * XtIsSubclass(XtParent(widget),simpleMenuWidgetClass) == True
+ */
+
+ char_u *pullright_name;
+ Widget popup;
+
+ pullright_name = make_pull_name((char_u *)XtName(widget));
+ popup = XtNameToWidget(XtParent(widget), (char *)pullright_name);
+ vim_free(pullright_name);
+
+ return popup;
+ /* Postcondition: (popup != NULL) implies
+ * (XtIsSubclass(popup,simpleMenuWidgetClass) == True) */
+}
+
+/* ARGSUSED */
+ void
+gui_mch_show_popupmenu(menu)
+ vimmenu_T *menu;
+{
+ int rootx, rooty, winx, winy;
+ Window root, child;
+ unsigned int mask;
+
+ if (menu->submenu_id == (Widget)0)
+ return;
+
+ /* Position the popup menu at the pointer */
+ if (XQueryPointer(gui.dpy, XtWindow(vimShell), &root, &child,
+ &rootx, &rooty, &winx, &winy, &mask))
+ {
+ rootx -= 30;
+ if (rootx < 0)
+ rootx = 0;
+ rooty -= 5;
+ if (rooty < 0)
+ rooty = 0;
+ XtVaSetValues(menu->submenu_id,
+ XtNx, rootx,
+ XtNy, rooty,
+ NULL);
+ }
+
+ XtOverrideTranslations(menu->submenu_id, popupTrans);
+ XtPopupSpringLoaded(menu->submenu_id);
+}
+
+#endif /* FEAT_MENU */
+
+/*
+ * Set the menu and scrollbar colors to their default values.
+ */
+ void
+gui_mch_def_colors()
+{
+ /*
+ * Get the colors ourselves. Using the automatic conversion doesn't
+ * handle looking for approximate colors.
+ */
+ if (gui.in_use)
+ {
+ gui.menu_fg_pixel = gui_get_color((char_u *)gui.rsrc_menu_fg_name);
+ gui.menu_bg_pixel = gui_get_color((char_u *)gui.rsrc_menu_bg_name);
+ gui.scroll_fg_pixel = gui_get_color((char_u *)gui.rsrc_scroll_fg_name);
+ gui.scroll_bg_pixel = gui_get_color((char_u *)gui.rsrc_scroll_bg_name);
+#ifdef FEAT_BEVAL
+ gui.tooltip_fg_pixel = gui_get_color((char_u *)gui.rsrc_tooltip_fg_name);
+ gui.tooltip_bg_pixel = gui_get_color((char_u *)gui.rsrc_tooltip_bg_name);
+#endif
+ }
+}
+
+
+/*
+ * Scrollbar stuff.
+ */
+
+ void
+gui_mch_set_scrollbar_thumb(sb, val, size, max)
+ scrollbar_T *sb;
+ long val;
+ long size;
+ long max;
+{
+ double v, s;
+
+ if (sb->id == (Widget)0)
+ return;
+
+ /*
+ * Athena scrollbar must go from 0.0 to 1.0.
+ */
+ if (max == 0)
+ {
+ /* So you can't scroll it at all (normally it scrolls past end) */
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb(sb->id, 0.0, 1.0);
+#else
+ vim_XawScrollbarSetThumb(sb->id, 0.0, 1.0, 0.0);
+#endif
+ }
+ else
+ {
+ v = (double)val / (double)(max + 1);
+ s = (double)size / (double)(max + 1);
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb(sb->id, v, s);
+#else
+ vim_XawScrollbarSetThumb(sb->id, v, s, 1.0);
+#endif
+ }
+}
+
+ void
+gui_mch_set_scrollbar_pos(sb, x, y, w, h)
+ scrollbar_T *sb;
+ int x;
+ int y;
+ int w;
+ int h;
+{
+ if (sb->id == (Widget)0)
+ return;
+
+ XtUnmanageChild(sb->id);
+ XtVaSetValues(sb->id,
+ XtNhorizDistance, x,
+ XtNvertDistance, y,
+ XtNwidth, w,
+ XtNheight, h,
+ NULL);
+ XtManageChild(sb->id);
+}
+
+ void
+gui_mch_enable_scrollbar(sb, flag)
+ scrollbar_T *sb;
+ int flag;
+{
+ if (sb->id != (Widget)0)
+ {
+ if (flag)
+ XtManageChild(sb->id);
+ else
+ XtUnmanageChild(sb->id);
+ }
+}
+
+ void
+gui_mch_create_scrollbar(sb, orient)
+ scrollbar_T *sb;
+ int orient; /* SBAR_VERT or SBAR_HORIZ */
+{
+ sb->id = XtVaCreateWidget("scrollBar",
+#ifdef FEAT_GUI_NEXTAW
+ scrollbarWidgetClass, vimForm,
+#else
+ vim_scrollbarWidgetClass, vimForm,
+#endif
+ XtNresizable, True,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainLeft,
+ XtNborderWidth, 0,
+ XtNorientation, (orient == SBAR_VERT) ? XtorientVertical
+ : XtorientHorizontal,
+ XtNforeground, gui.scroll_fg_pixel,
+ XtNbackground, gui.scroll_bg_pixel,
+ NULL);
+ if (sb->id == (Widget)0)
+ return;
+
+ XtAddCallback(sb->id, XtNjumpProc,
+ gui_athena_scroll_cb_jump, (XtPointer)sb->ident);
+ XtAddCallback(sb->id, XtNscrollProc,
+ gui_athena_scroll_cb_scroll, (XtPointer)sb->ident);
+
+#ifdef FEAT_GUI_NEXTAW
+ XawScrollbarSetThumb(sb->id, 0.0, 1.0);
+#else
+ vim_XawScrollbarSetThumb(sb->id, 0.0, 1.0, 0.0);
+#endif
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+ void
+gui_mch_destroy_scrollbar(sb)
+ scrollbar_T *sb;
+{
+ if (sb->id != (Widget)0)
+ XtDestroyWidget(sb->id);
+}
+#endif
+
+ void
+gui_mch_set_scrollbar_colors(sb)
+ scrollbar_T *sb;
+{
+ if (sb->id != (Widget)0)
+ XtVaSetValues(sb->id,
+ XtNforeground, gui.scroll_fg_pixel,
+ XtNbackground, gui.scroll_bg_pixel,
+ NULL);
+
+ /* This is needed for the rectangle below the vertical scrollbars. */
+ if (sb == &gui.bottom_sbar && vimForm != (Widget)0)
+ gui_athena_scroll_colors(vimForm);
+}
+
+/*
+ * Miscellaneous stuff:
+ */
+ Window
+gui_x11_get_wid()
+{
+ return XtWindow(textArea);
+}
+
+#if defined(FEAT_BROWSE) || defined(PROTO)
+/*
+ * Put up a file requester.
+ * Returns the selected name in allocated memory, or NULL for Cancel.
+ */
+/* ARGSUSED */
+ char_u *
+gui_mch_browse(saving, title, dflt, ext, initdir, filter)
+ int saving; /* select file to write */
+ char_u *title; /* not used (title for the window) */
+ char_u *dflt; /* not used (default name) */
+ char_u *ext; /* not used (extension added) */
+ char_u *initdir; /* initial directory, NULL for current dir */
+ char_u *filter; /* not used (file name filter) */
+{
+ Position x, y;
+ char_u dirbuf[MAXPATHL];
+
+ /* Concatenate "initdir" and "dflt". */
+ if (initdir == NULL || *initdir == NUL)
+ mch_dirname(dirbuf, MAXPATHL);
+ else if (STRLEN(initdir) + 2 < MAXPATHL)
+ STRCPY(dirbuf, initdir);
+ else
+ dirbuf[0] = NUL;
+ if (dflt != NULL && *dflt != NUL
+ && STRLEN(dirbuf) + 2 + STRLEN(dflt) < MAXPATHL)
+ {
+ add_pathsep(dirbuf);
+ STRCAT(dirbuf, dflt);
+ }
+
+ /* Position the file selector just below the menubar */
+ XtTranslateCoords(vimShell, (Position)0, (Position)
+#ifdef FEAT_MENU
+ gui.menu_height
+#else
+ 0
+#endif
+ , &x, &y);
+ return (char_u *)vim_SelFile(vimShell, (char *)title, (char *)dirbuf,
+ NULL, (int)x, (int)y, gui.menu_fg_pixel, gui.menu_bg_pixel,
+ gui.scroll_fg_pixel, gui.scroll_bg_pixel);
+}
+#endif
+
+#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
+
+static int dialogStatus;
+static Atom dialogatom;
+
+static void keyhit_callback __ARGS((Widget w, XtPointer client_data, XEvent *event, Boolean *cont));
+static void butproc __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
+static void dialog_wm_handler __ARGS((Widget w, XtPointer client_data, XEvent *event, Boolean *dum));
+
+/*
+ * Callback function for the textfield. When CR is hit this works like
+ * hitting the "OK" button, ESC like "Cancel".
+ */
+/* ARGSUSED */
+ static void
+keyhit_callback(w, client_data, event, cont)
+ Widget w;
+ XtPointer client_data;
+ XEvent *event;
+ Boolean *cont;
+{
+ char buf[2];
+
+ if (XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1)
+ {
+ if (*buf == CAR)
+ dialogStatus = 1;
+ else if (*buf == ESC)
+ dialogStatus = 0;
+ }
+}
+
+/* ARGSUSED */
+ static void
+butproc(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data;
+ XtPointer call_data;
+{
+ dialogStatus = (int)(long)client_data + 1;
+}
+
+/*
+ * Function called when dialog window closed.
+ */
+/*ARGSUSED*/
+ static void
+dialog_wm_handler(w, client_data, event, dum)
+ Widget w;
+ XtPointer client_data;
+ XEvent *event;
+ Boolean *dum;
+{
+ if (event->type == ClientMessage
+ && ((XClientMessageEvent *)event)->data.l[0] == dialogatom)
+ dialogStatus = 0;
+}
+
+/* ARGSUSED */
+ int
+gui_mch_dialog(type, title, message, buttons, dfltbutton, textfield)
+ int type;
+ char_u *title;
+ char_u *message;
+ char_u *buttons;
+ int dfltbutton;
+ char_u *textfield;
+{
+ char_u *buts;
+ char_u *p, *next;
+ XtAppContext app;
+ XEvent event;
+ Position wd, hd;
+ Position wv, hv;
+ Position x, y;
+ Widget dialog;
+ Widget dialogshell;
+ Widget dialogmessage;
+ Widget dialogtextfield = 0;
+ Widget dialogButton;
+ Widget prev_dialogButton = NULL;
+ int butcount;
+ int vertical;
+
+ if (title == NULL)
+ title = (char_u *)_("Vim dialog");
+ dialogStatus = -1;
+
+ /* if our pointer is currently hidden, then we should show it. */
+ gui_mch_mousehide(FALSE);
+
+ /* Check 'v' flag in 'guioptions': vertical button placement. */
+ vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
+
+ /* The shell is created each time, to make sure it is resized properly */
+ dialogshell = XtVaCreatePopupShell("dialogShell",
+ transientShellWidgetClass, vimShell,
+ XtNtitle, title,
+ NULL);
+ if (dialogshell == (Widget)0)
+ goto error;
+
+ dialog = XtVaCreateManagedWidget("dialog",
+ formWidgetClass, dialogshell,
+ XtNdefaultDistance, 20,
+ NULL);
+ if (dialog == (Widget)0)
+ goto error;
+ gui_athena_menu_colors(dialog);
+ dialogmessage = XtVaCreateManagedWidget("dialogMessage",
+ labelWidgetClass, dialog,
+ XtNlabel, message,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainLeft,
+ XtNresizable, True,
+ XtNborderWidth, 0,
+ NULL);
+ gui_athena_menu_colors(dialogmessage);
+
+ if (textfield != NULL)
+ {
+ dialogtextfield = XtVaCreateManagedWidget("textfield",
+ asciiTextWidgetClass, dialog,
+ XtNwidth, 400,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainTop,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainRight,
+ XtNfromVert, dialogmessage,
+ XtNresizable, True,
+ XtNstring, textfield,
+ XtNlength, IOSIZE,
+ XtNuseStringInPlace, True,
+ XtNeditType, XawtextEdit,
+ XtNwrap, XawtextWrapNever,
+ XtNresize, XawtextResizeHeight,
+ NULL);
+ XtManageChild(dialogtextfield);
+ XtAddEventHandler(dialogtextfield, KeyPressMask, False,
+ (XtEventHandler)keyhit_callback, (XtPointer)NULL);
+ XawTextSetInsertionPoint(dialogtextfield,
+ (XawTextPosition)STRLEN(textfield));
+ XtSetKeyboardFocus(dialog, dialogtextfield);
+ }
+
+ /* make a copy, so that we can insert NULs */
+ buts = vim_strsave(buttons);
+ if (buts == NULL)
+ return -1;
+
+ p = buts;
+ for (butcount = 0; *p; ++butcount)
+ {
+ for (next = p; *next; ++next)
+ {
+ if (*next == DLG_HOTKEY_CHAR)
+ mch_memmove(next, next + 1, STRLEN(next));
+ if (*next == DLG_BUTTON_SEP)
+ {
+ *next++ = NUL;
+ break;
+ }
+ }
+ dialogButton = XtVaCreateManagedWidget("button",
+ commandWidgetClass, dialog,
+ XtNlabel, p,
+ XtNtop, XtChainBottom,
+ XtNbottom, XtChainBottom,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainLeft,
+ XtNfromVert, textfield == NULL ? dialogmessage : dialogtextfield,
+ XtNvertDistance, vertical ? 4 : 20,
+ XtNresizable, False,
+ NULL);
+ gui_athena_menu_colors(dialogButton);
+ if (butcount > 0)
+ XtVaSetValues(dialogButton,
+ vertical ? XtNfromVert : XtNfromHoriz, prev_dialogButton,
+ NULL);
+
+ XtAddCallback(dialogButton, XtNcallback, butproc, (XtPointer)butcount);
+ p = next;
+ prev_dialogButton = dialogButton;
+ }
+ vim_free(buts);
+
+ XtRealizeWidget(dialogshell);
+
+ /* Setup for catching the close-window event, don't let it close Vim! */
+ dialogatom = XInternAtom(gui.dpy, "WM_DELETE_WINDOW", False);
+ XSetWMProtocols(gui.dpy, XtWindow(dialogshell), &dialogatom, 1);
+ XtAddEventHandler(dialogshell, NoEventMask, True, dialog_wm_handler, NULL);
+
+ XtVaGetValues(dialogshell,
+ XtNwidth, &wd,
+ XtNheight, &hd,
+ NULL);
+ XtVaGetValues(vimShell,
+ XtNwidth, &wv,
+ XtNheight, &hv,
+ NULL);
+ XtTranslateCoords(vimShell,
+ (Position)((wv - wd) / 2),
+ (Position)((hv - hd) / 2),
+ &x, &y);
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+ XtVaSetValues(dialogshell, XtNx, x, XtNy, y, NULL);
+
+ /* Position the mouse pointer in the dialog, required for when focus
+ * follows mouse. */
+ XWarpPointer(gui.dpy, (Window)0, XtWindow(dialogshell), 0, 0, 0, 0, 20, 40);
+
+
+ app = XtWidgetToApplicationContext(dialogshell);
+
+ XtPopup(dialogshell, XtGrabNonexclusive);
+
+ while (1)
+ {
+ XtAppNextEvent(app, &event);
+ XtDispatchEvent(&event);
+ if (dialogStatus >= 0)
+ break;
+ }
+
+ XtPopdown(dialogshell);
+
+ if (textfield != NULL && dialogStatus < 0)
+ *textfield = NUL;
+
+error:
+ XtDestroyWidget(dialogshell);
+
+ return dialogStatus;
+}
+#endif
+
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_MENU)
+/*
+ * Set the colors of Widget "id" to the menu colors.
+ */
+ static void
+gui_athena_menu_colors(id)
+ Widget id;
+{
+ if (gui.menu_bg_pixel != INVALCOLOR)
+ XtVaSetValues(id, XtNbackground, gui.menu_bg_pixel, NULL);
+ if (gui.menu_fg_pixel != INVALCOLOR)
+ XtVaSetValues(id, XtNforeground, gui.menu_fg_pixel, NULL);
+}
+#endif
+
+/*
+ * Set the colors of Widget "id" to the scroll colors.
+ */
+ static void
+gui_athena_scroll_colors(id)
+ Widget id;
+{
+ if (gui.scroll_bg_pixel != INVALCOLOR)
+ XtVaSetValues(id, XtNbackground, gui.scroll_bg_pixel, NULL);
+ if (gui.scroll_fg_pixel != INVALCOLOR)
+ XtVaSetValues(id, XtNforeground, gui.scroll_fg_pixel, NULL);
+}
diff --git a/src/gui_beos.cc b/src/gui_beos.cc
new file mode 100644
index 000000000..e2c659848
--- /dev/null
+++ b/src/gui_beos.cc
@@ -0,0 +1,3347 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * BeBox GUI support Copyright 1998 by Olaf Seibert.
+ * All Rights Reserved.
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ *
+ * BeOS GUI.
+ *
+ * GUI support for the Buzzword Enhanced Operating System.
+ *
+ * Ported to R4 by Richard Offer <richard@whitequeen.com> Jul 99
+ *
+ */
+
+/*
+ * Structure of the BeOS GUI code:
+ *
+ * There are 3 threads.
+ * 1. The initial thread. In gui_mch_prepare() this gets to run the
+ * BApplication message loop. But before it starts doing that,
+ * it creates thread 2:
+ * 2. The main() thread. This thread is created in gui_mch_prepare()
+ * and its purpose in life is to call main(argc, argv) again.
+ * This thread is doing the bulk of the work.
+ * 3. Sooner or later, a window is opened by the main() thread. This
+ * causes a second message loop to be created: the window thread.
+ *
+ * == alternatively ===
+ *
+ * #if RUN_BAPPLICATION_IN_NEW_THREAD...
+ *
+ * 1. The initial thread. In gui_mch_prepare() this gets to spawn
+ * thread 2. After doing that, it returns to main() to do the
+ * bulk of the work, being the main() thread.
+ * 2. Runs the BApplication.
+ * 3. The window thread, just like in the first case.
+ *
+ * This second alternative is cleaner from Vim's viewpoint. However,
+ * the BeBook seems to assume everywhere that the BApplication *must*
+ * run in the initial thread. So perhaps doing otherwise is very wrong.
+ *
+ * However, from a B_SINGLE_LAUNCH viewpoint, the first is better.
+ * If Vim is marked "Single Launch" in its application resources,
+ * and a file is dropped on the Vim icon, and another Vim is already
+ * running, the file is passed on to the earlier Vim. This happens
+ * in BApplication::Run(). So we want Vim to terminate if
+ * BApplication::Run() terminates. (See the BeBook, on BApplication.
+ * However, it seems that the second copy of Vim isn't even started
+ * in this case... which is for the better since I wouldn't know how
+ * to detect this case.)
+ *
+ * Communication between these threads occurs mostly by translating
+ * BMessages that come in and posting an appropriate translation on
+ * the VDCMP (Vim Direct Communication Message Port). Therefore the
+ * actions required for keypresses and window resizes, etc, are mostly
+ * performed in the main() thread.
+ *
+ * A notable exception to this is the Draw() event. The redrawing of
+ * the window contents is performed asynchronously from the window
+ * thread. To make this work correctly, a locking protocol is used when
+ * any thread is accessing the essential variables that are used by
+ * the window thread.
+ *
+ * This locking protocol consists of locking Vim's window. This is both
+ * convenient and necessary.
+ */
+extern "C" {
+
+#define new xxx_new_xxx
+
+#include <float.h>
+#include <assert.h>
+#include "vim.h"
+#include "globals.h"
+#include "proto.h"
+#include "option.h"
+
+#undef new
+
+} /* extern "C" */
+
+/* ---------------- start of header part ---------------- */
+
+#include <be/app/MessageQueue.h>
+#include <be/app/Clipboard.h>
+#include <be/kernel/OS.h>
+#include <be/support/Beep.h>
+#include <be/interface/View.h>
+#include <be/interface/Window.h>
+#include <be/interface/MenuBar.h>
+#include <be/interface/MenuItem.h>
+#include <be/interface/ScrollBar.h>
+#include <be/interface/Region.h>
+#include <be/interface/Screen.h>
+#include <be/storage/Path.h>
+#include <be/storage/Directory.h>
+#include <be/storage/Entry.h>
+#include <be/app/Application.h>
+#include <be/support/Debug.h>
+
+/*
+ * The macro B_PIXEL_ALIGNMENT shows us which version
+ * of the header files we're using.
+ */
+#if defined(B_PIXEL_ALIGNMENT)
+#define HAVE_R3_OR_LATER 1
+#else
+#define HAVE_R3_OR_LATER 0
+#endif
+
+class VimApp;
+class VimFormView;
+class VimTextAreaView;
+class VimWindow;
+
+extern key_map *keyMap;
+extern char *keyMapChars;
+
+extern int main(int argc, char **argv);
+
+#ifndef B_MAX_PORT_COUNT
+#define B_MAX_PORT_COUNT 100
+#endif
+
+/*
+ * VimApp seems comparable to the X "vimShell"
+ */
+class VimApp: public BApplication
+{
+ typedef BApplication Inherited;
+public:
+ VimApp(const char *appsig);
+ ~VimApp();
+
+ // callbacks:
+#if 0
+ virtual void DispatchMessage(BMessage *m, BHandler *h)
+ {
+ m->PrintToStream();
+ Inherited::DispatchMessage(m, h);
+ }
+#endif
+ virtual void ReadyToRun();
+ virtual void ArgvReceived(int32 argc, char **argv);
+ virtual void RefsReceived(BMessage *m);
+ virtual bool QuitRequested();
+
+ static void SendRefs(BMessage *m, bool changedir);
+private:
+};
+
+class VimWindow: public BWindow
+{
+ typedef BWindow Inherited;
+public:
+ VimWindow();
+ ~VimWindow();
+
+ virtual void DispatchMessage(BMessage *m, BHandler *h);
+ virtual void WindowActivated(bool active);
+ virtual bool QuitRequested();
+
+ VimFormView *formView;
+
+private:
+ void init();
+
+};
+
+class VimFormView: public BView
+{
+ typedef BView Inherited;
+public:
+ VimFormView(BRect frame);
+ ~VimFormView();
+
+ // callbacks:
+ virtual void AllAttached();
+ virtual void FrameResized(float new_width, float new_height);
+
+#define MENUBAR_MARGIN 1
+ float MenuHeight() const
+ { return menuBar ? menuBar->Frame().Height() + MENUBAR_MARGIN: 0; }
+ BMenuBar *MenuBar() const
+ { return menuBar; }
+
+private:
+ void init(BRect);
+
+ BMenuBar *menuBar;
+ VimTextAreaView *textArea;
+};
+
+class VimTextAreaView: public BView
+{
+ typedef BView Inherited;
+public:
+ VimTextAreaView(BRect frame);
+ ~VimTextAreaView();
+
+ // callbacks:
+ virtual void Draw(BRect updateRect);
+ virtual void KeyDown(const char *bytes, int32 numBytes);
+ virtual void MouseDown(BPoint point);
+ virtual void MouseUp(BPoint point);
+ virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message);
+ virtual void MessageReceived(BMessage *m);
+
+ // own functions:
+ int mchInitFont(char_u *name);
+ void mchDrawString(int row, int col, char_u *s, int len, int flags);
+ void mchClearBlock(int row1, int col1, int row2, int col2);
+ void mchClearAll();
+ void mchDeleteLines(int row, int num_lines);
+ void mchInsertLines(int row, int num_lines);
+
+ static void guiSendMouseEvent(int button, int x, int y, int repeated_click, int_u modifiers);
+ static void guiBlankMouse(bool should_hide);
+ static int_u mouseModifiersToVim(int32 beModifiers);
+
+ int32 mouseDragEventCount;
+
+private:
+ void init(BRect);
+
+ int_u vimMouseButton;
+ int_u vimMouseModifiers;
+};
+
+class VimScrollBar: public BScrollBar
+{
+ typedef BScrollBar Inherited;
+public:
+ VimScrollBar(scrollbar_T *gsb, orientation posture);
+ ~VimScrollBar();
+
+ virtual void ValueChanged(float newValue);
+ virtual void MouseUp(BPoint where);
+ void SetValue(float newval);
+ scrollbar_T *getGsb()
+ { return gsb; }
+
+ int32 scrollEventCount;
+
+private:
+ scrollbar_T *gsb;
+ float ignoreValue;
+};
+
+
+/*
+ * For caching the fonts that are used;
+ * Vim seems rather sloppy in this regard.
+ */
+class VimFont: public BFont
+{
+ typedef BFont Inherited;
+public:
+ VimFont();
+ VimFont(const VimFont *rhs);
+ VimFont(const BFont *rhs);
+ VimFont(const VimFont &rhs);
+ ~VimFont();
+
+ VimFont *next;
+ int refcount;
+ char_u *name;
+
+private:
+ void init();
+};
+
+/* ---------------- end of GUI classes ---------------- */
+
+struct MainArgs {
+ int argc;
+ char **argv;
+};
+
+/*
+ * These messages are copied through the VDCMP.
+ * Therefore they ought not to have anything fancy.
+ * They must be of POD type (Plain Old Data)
+ * as the C++ standard calls them.
+ */
+
+#define KEY_MSG_BUFSIZ 7
+#if KEY_MSG_BUFSIZ < MAX_KEY_CODE_LEN
+#error Increase KEY_MSG_BUFSIZ!
+#endif
+
+struct VimKeyMsg {
+ char_u length;
+ char_u chars[KEY_MSG_BUFSIZ]; /* contains Vim encoding */
+};
+
+struct VimResizeMsg {
+ int width;
+ int height;
+};
+
+struct VimScrollBarMsg {
+ VimScrollBar *sb;
+ long value;
+ int stillDragging;
+};
+
+struct VimMenuMsg {
+ vimmenu_T *guiMenu;
+};
+
+struct VimMouseMsg {
+ int button;
+ int x;
+ int y;
+ int repeated_click;
+ int_u modifiers;
+};
+
+struct VimFocusMsg {
+ bool active;
+};
+
+struct VimRefsMsg {
+ BMessage *message;
+ bool changedir;
+};
+
+struct VimMsg {
+ enum VimMsgType {
+ Key, Resize, ScrollBar, Menu, Mouse, Focus, Refs
+ };
+
+ union {
+ struct VimKeyMsg Key;
+ struct VimResizeMsg NewSize;
+ struct VimScrollBarMsg Scroll;
+ struct VimMenuMsg Menu;
+ struct VimMouseMsg Mouse;
+ struct VimFocusMsg Focus;
+ struct VimRefsMsg Refs;
+ } u;
+};
+
+#define RGB(r, g, b) ((char_u)(r) << 16 | (char_u)(g) << 8 | (char_u)(b) << 0)
+#define GUI_TO_RGB(g) { (g) >> 16, (g) >> 8, (g) >> 0, 255 }
+
+/* ---------------- end of header part ---------------- */
+
+static struct specialkey
+{
+ uint16 BeKeys;
+#define KEY(a,b) ((a)<<8|(b))
+#define K(a) KEY(0,a) // for ASCII codes
+#define F(b) KEY(1,b) // for scancodes
+ char_u vim_code0;
+ char_u vim_code1;
+} special_keys[] =
+{
+ {K(B_UP_ARROW), 'k', 'u'},
+ {K(B_DOWN_ARROW), 'k', 'd'},
+ {K(B_LEFT_ARROW), 'k', 'l'},
+ {K(B_RIGHT_ARROW), 'k', 'r'},
+ {K(B_BACKSPACE), 'k', 'b'},
+ {K(B_INSERT), 'k', 'I'},
+ {K(B_DELETE), 'k', 'D'},
+ {K(B_HOME), 'k', 'h'},
+ {K(B_END), '@', '7'},
+ {K(B_PAGE_UP), 'k', 'P'}, /* XK_Prior */
+ {K(B_PAGE_DOWN), 'k', 'N'}, /* XK_Next, */
+
+#define FIRST_FUNCTION_KEY 11
+ {F(B_F1_KEY), 'k', '1'},
+ {F(B_F2_KEY), 'k', '2'},
+ {F(B_F3_KEY), 'k', '3'},
+ {F(B_F4_KEY), 'k', '4'},
+ {F(B_F5_KEY), 'k', '5'},
+ {F(B_F6_KEY), 'k', '6'},
+ {F(B_F7_KEY), 'k', '7'},
+ {F(B_F8_KEY), 'k', '8'},
+ {F(B_F9_KEY), 'k', '9'},
+ {F(B_F10_KEY), 'k', ';'},
+
+ {F(B_F11_KEY), 'F', '1'},
+ {F(B_F12_KEY), 'F', '2'},
+// {XK_F13, 'F', '3'}, /* would be print screen/ */
+ /* sysreq */
+ {F(0x0F), 'F', '4'}, /* scroll lock */
+ {F(0x10), 'F', '5'}, /* pause/break */
+// {XK_F16, 'F', '6'},
+// {XK_F17, 'F', '7'},
+// {XK_F18, 'F', '8'},
+// {XK_F19, 'F', '9'},
+// {XK_F20, 'F', 'A'},
+//
+// {XK_F21, 'F', 'B'},
+// {XK_F22, 'F', 'C'},
+// {XK_F23, 'F', 'D'},
+// {XK_F24, 'F', 'E'},
+// {XK_F25, 'F', 'F'},
+// {XK_F26, 'F', 'G'},
+// {XK_F27, 'F', 'H'},
+// {XK_F28, 'F', 'I'},
+// {XK_F29, 'F', 'J'},
+// {XK_F30, 'F', 'K'},
+//
+// {XK_F31, 'F', 'L'},
+// {XK_F32, 'F', 'M'},
+// {XK_F33, 'F', 'N'},
+// {XK_F34, 'F', 'O'},
+// {XK_F35, 'F', 'P'}, /* keysymdef.h defines up to F35 */
+
+// {XK_Help, '%', '1'}, /* XK_Help */
+ {F(B_PRINT_KEY), '%', '9'},
+
+#if 0
+ /* Keypad keys: */
+ {F(0x48), 'k', 'l'}, /* XK_KP_Left */
+ {F(0x4A), 'k', 'r'}, /* XK_KP_Right */
+ {F(0x38), 'k', 'u'}, /* XK_KP_Up */
+ {F(0x59), 'k', 'd'}, /* XK_KP_Down */
+ {F(0x64), 'k', 'I'}, /* XK_KP_Insert */
+ {F(0x65), 'k', 'D'}, /* XK_KP_Delete */
+ {F(0x37), 'k', 'h'}, /* XK_KP_Home */
+ {F(0x58), '@', '7'}, /* XK_KP_End */
+ {F(0x39), 'k', 'P'}, /* XK_KP_Prior */
+ {F(0x60), 'k', 'N'}, /* XK_KP_Next */
+ {F(0x49), '&', '8'}, /* XK_Undo, keypad 5 */
+#endif
+
+ /* End of list marker: */
+ {0, 0, 0}
+};
+
+#define NUM_SPECIAL_KEYS (sizeof(special_keys)/sizeof(special_keys[0]))
+
+/* ---------------- VimApp ---------------- */
+
+ static void
+docd(BPath &path)
+{
+ mch_chdir(path.Path());
+ /* Do this to get the side effects of a :cd command */
+ do_cmdline_cmd((char_u *)"cd .");
+}
+
+/*
+ * Really handle dropped files and folders.
+ */
+ static void
+RefsReceived(BMessage *m, bool changedir)
+{
+ uint32 type;
+ int32 count;
+
+ //m->PrintToStream();
+ switch (m->what) {
+ case B_REFS_RECEIVED:
+ case B_SIMPLE_DATA:
+ m->GetInfo("refs", &type, &count);
+ if (type != B_REF_TYPE)
+ goto bad;
+ break;
+ case B_ARGV_RECEIVED:
+ m->GetInfo("argv", &type, &count);
+ if (type != B_STRING_TYPE)
+ goto bad;
+ if (changedir) {
+ char *dirname;
+ if (m->FindString("cwd", (const char **) &dirname) == B_OK) {
+ chdir(dirname);
+ do_cmdline_cmd((char_u *)"cd .");
+ }
+ }
+ break;
+ default:
+ bad:
+ //fprintf(stderr, "bad!\n");
+ delete m;
+ return;
+ }
+
+#ifdef FEAT_VISUAL
+ reset_VIsual();
+#endif
+
+ char_u **fnames;
+ fnames = (char_u **) alloc(count * sizeof(char_u *));
+ int fname_index = 0;
+
+ switch (m->what) {
+ case B_REFS_RECEIVED:
+ case B_SIMPLE_DATA:
+ //fprintf(stderr, "case B_REFS_RECEIVED\n");
+ for (int i = 0; i < count; ++i)
+ {
+ entry_ref ref;
+ if (m->FindRef("refs", i, &ref) == B_OK) {
+ BEntry entry(&ref, false);
+ BPath path;
+ entry.GetPath(&path);
+
+ /* Change to parent directory? */
+ if (changedir) {
+ BPath parentpath;
+ path.GetParent(&parentpath);
+ docd(parentpath);
+ }
+
+ /* Is it a directory? If so, cd into it. */
+ BDirectory bdir(&ref);
+ if (bdir.InitCheck() == B_OK) {
+ /* don't cd if we already did it */
+ if (!changedir)
+ docd(path);
+ } else {
+ mch_dirname(IObuff, IOSIZE);
+ char_u *fname = shorten_fname((char_u *)path.Path(), IObuff);
+ if (fname == NULL)
+ fname = (char_u *)path.Path();
+ fnames[fname_index++] = vim_strsave(fname);
+ //fprintf(stderr, "%s\n", fname);
+ }
+
+ /* Only do it for the first file/dir */
+ changedir = false;
+ }
+ }
+ break;
+ case B_ARGV_RECEIVED:
+ //fprintf(stderr, "case B_ARGV_RECEIVED\n");
+ for (int i = 1; i < count; ++i)
+ {
+ char *fname;
+
+ if (m->FindString("argv", i, (const char **) &fname) == B_OK) {
+ fnames[fname_index++] = vim_strsave((char_u *)fname);
+ }
+ }
+ break;
+ default:
+ //fprintf(stderr, "case default\n");
+ break;
+ }
+
+ delete m;
+
+ /* Handle the drop, :edit to get to the file */
+ if (fname_index > 0) {
+ handle_drop(fname_index, fnames, FALSE);
+
+ /* Update the screen display */
+ update_screen(NOT_VALID);
+ setcursor();
+ out_flush();
+ } else {
+ vim_free(fnames);
+ }
+}
+
+VimApp::VimApp(const char *appsig):
+ BApplication(appsig)
+{
+}
+
+VimApp::~VimApp()
+{
+}
+
+ void
+VimApp::ReadyToRun()
+{
+ /*
+ * Apparently signals are inherited by the created thread -
+ * disable the most annoying ones.
+ */
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+}
+
+ void
+VimApp::ArgvReceived(int32 arg_argc, char **arg_argv)
+{
+ if (!IsLaunching()) {
+ /*
+ * This can happen if we are set to Single or Exclusive
+ * Launch. Be nice and open the file(s).
+ */
+ if (gui.vimWindow)
+ gui.vimWindow->Minimize(false);
+ BMessage *m = CurrentMessage();
+ DetachCurrentMessage();
+ SendRefs(m, true);
+ }
+}
+
+ void
+VimApp::RefsReceived(BMessage *m)
+{
+ /* Horrible hack!!! XXX XXX XXX
+ * The real problem is that b_start_ffc is set too late for
+ * the initial empty buffer. As a result the window will be
+ * split instead of abandoned.
+ */
+ int limit = 15;
+ while (--limit >= 0 && (curbuf == NULL || curbuf->b_start_ffc == 0))
+ snooze(100000); // 0.1 s
+ if (gui.vimWindow)
+ gui.vimWindow->Minimize(false);
+ DetachCurrentMessage();
+ SendRefs(m, true);
+}
+
+/*
+ * Pass a BMessage on to the main() thread.
+ * Caller must have detached the message.
+ */
+ void
+VimApp::SendRefs(BMessage *m, bool changedir)
+{
+ VimRefsMsg rm;
+ rm.message = m;
+ rm.changedir = changedir;
+
+ write_port(gui.vdcmp, VimMsg::Refs, &rm, sizeof(rm));
+ // calls ::RefsReceived
+}
+
+ bool
+VimApp::QuitRequested()
+{
+ (void)Inherited::QuitRequested();
+ return false;
+}
+
+/* ---------------- VimWindow ---------------- */
+
+VimWindow::VimWindow():
+ BWindow(BRect(40, 40, 150, 150),
+ "Vim",
+ B_TITLED_WINDOW,
+ 0,
+ B_CURRENT_WORKSPACE)
+
+{
+ init();
+}
+
+VimWindow::~VimWindow()
+{
+ if (formView) {
+ RemoveChild(formView);
+ delete formView;
+ }
+ gui.vimWindow = NULL;
+}
+
+ void
+VimWindow::init()
+{
+ /* Attach the VimFormView */
+ formView = new VimFormView(Bounds());
+ if (formView != NULL) {
+ AddChild(formView);
+ }
+}
+
+ void
+VimWindow::DispatchMessage(BMessage *m, BHandler *h)
+{
+ /*
+ * Route B_MOUSE_UP messages to MouseUp(), in
+ * a manner that should be compatible with the
+ * intended future system behaviour.
+ */
+ switch (m->what) {
+ case B_MOUSE_UP:
+ // if (!h) h = PreferredHandler();
+// gcc isn't happy without this extra set of braces, complains about
+// jump to case label crosses init of 'class BView * v'
+// richard@whitequeen.com jul 99
+ {
+ BView *v = dynamic_cast<BView *>(h);
+ if (v) {
+ //m->PrintToStream();
+ BPoint where;
+ m->FindPoint("where", &where);
+ v->MouseUp(where);
+ } else {
+ Inherited::DispatchMessage(m, h);
+ }
+ }
+ break;
+ default:
+ Inherited::DispatchMessage(m, h);
+ }
+}
+
+ void
+VimWindow::WindowActivated(bool active)
+{
+ Inherited::WindowActivated(active);
+ /* the textArea gets the keyboard action */
+ if (active && gui.vimTextArea)
+ gui.vimTextArea->MakeFocus(true);
+
+ struct VimFocusMsg fm;
+ fm.active = active;
+
+ write_port(gui.vdcmp, VimMsg::Focus, &fm, sizeof(fm));
+}
+
+ bool
+VimWindow::QuitRequested()
+{
+ struct VimKeyMsg km;
+ km.length = 5;
+ memcpy((char *)km.chars, "\033:qa\r", km.length);
+
+ write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
+
+ return false;
+}
+
+/* ---------------- VimFormView ---------------- */
+
+VimFormView::VimFormView(BRect frame):
+ BView(frame, "VimFormView", B_FOLLOW_ALL_SIDES,
+ B_WILL_DRAW | B_FRAME_EVENTS),
+ menuBar(NULL),
+ textArea(NULL)
+{
+ init(frame);
+}
+
+VimFormView::~VimFormView()
+{
+ if (menuBar) {
+ RemoveChild(menuBar);
+#ifdef never
+ // deleting the menuBar leads to SEGV on exit
+ // richard@whitequeen.com Jul 99
+ delete menuBar;
+#endif
+ }
+ if (textArea) {
+ RemoveChild(textArea);
+ delete textArea;
+ }
+ gui.vimForm = NULL;
+}
+
+ void
+VimFormView::init(BRect frame)
+{
+ menuBar = new BMenuBar(BRect(0,0,-MENUBAR_MARGIN,-MENUBAR_MARGIN),
+ "VimMenuBar");
+
+ AddChild(menuBar);
+
+ BRect remaining = frame;
+ textArea = new VimTextAreaView(remaining);
+ AddChild(textArea);
+ /* The textArea will be resized later when menus are added */
+
+ gui.vimForm = this;
+}
+
+ void
+VimFormView::AllAttached()
+{
+ /*
+ * Apparently signals are inherited by the created thread -
+ * disable the most annoying ones.
+ */
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+
+ if (menuBar && textArea) {
+ /*
+ * Resize the textArea to fill the space left over by the menu.
+ * This is somewhat futile since it will be done again once
+ * menus are added to the menu bar.
+ */
+ BRect remaining = Bounds();
+ remaining.top = MenuHeight();
+ textArea->ResizeTo(remaining.Width(), remaining.Height());
+ textArea->MoveTo(remaining.left, remaining.top);
+
+#ifdef FEAT_MENU
+ menuBar->ResizeTo(remaining.right, remaining.top);
+ gui.menu_height = (int) remaining.top;
+#endif
+ }
+ Inherited::AllAttached();
+}
+
+ void
+VimFormView::FrameResized(float new_width, float new_height)
+{
+ BWindow *w = Window();
+#if 1
+ /*
+ * Look if there are more resize messages in the queue.
+ * If so, ignore this one. The later one will be handled
+ * eventually.
+ */
+ BMessageQueue *q = w->MessageQueue();
+ if (q->FindMessage(B_VIEW_RESIZED, 0) != NULL) {
+ return;
+ }
+#endif
+ new_width += 1; // adjust from width to number of pixels occupied
+ new_height += 1;
+
+#if !HAVE_R3_OR_LATER
+ int adjust_h, adjust_w;
+
+ adjust_w = ((int)new_width - gui_get_base_width()) % gui.char_width;
+ adjust_h = ((int)new_height - gui_get_base_height()) % gui.char_height;
+
+ if (adjust_w > 0 || adjust_h > 0) {
+ /*
+ * This will generate a new FrameResized() message.
+ * If we're running R3 or later, SetWindowAlignment() should make
+ * sure that this does not happen.
+ */
+ w->ResizeBy(-adjust_w, -adjust_h);
+
+ return;
+ }
+#endif
+
+ struct VimResizeMsg sm;
+ sm.width = (int) new_width;
+ sm.height = (int) new_height;
+
+ write_port(gui.vdcmp, VimMsg::Resize, &sm, sizeof(sm));
+ // calls gui_resize_shell(new_width, new_height);
+
+ return;
+
+ /*
+ * The area below the vertical scrollbar is erased to the colour
+ * set with SetViewColor() automatically, because we had set
+ * B_WILL_DRAW. Resizing the window tight around the vertical
+ * scroll bar also helps to avoid debris.
+ */
+}
+
+/* ---------------- VimTextAreaView ---------------- */
+
+VimTextAreaView::VimTextAreaView(BRect frame):
+ BView(frame, "VimTextAreaView", B_FOLLOW_ALL_SIDES,
+ B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
+ mouseDragEventCount(0)
+{
+ init(frame);
+}
+
+VimTextAreaView::~VimTextAreaView()
+{
+ gui.vimTextArea = NULL;
+}
+
+ void
+VimTextAreaView::init(BRect frame)
+{
+ /* set up global var for fast access */
+ gui.vimTextArea = this;
+
+ /*
+ * Tell the app server not to erase the view: we will
+ * fill it in completely by ourselves.
+ * (Does this really work? Even if not, it won't harm either.)
+ */
+ SetViewColor(B_TRANSPARENT_32_BIT);
+#define PEN_WIDTH 1
+ SetPenSize(PEN_WIDTH);
+}
+
+ void
+VimTextAreaView::Draw(BRect updateRect)
+{
+ /*
+ * XXX Other ports call here:
+ * out_flush(); * make sure all output has been processed *
+ * but we can't do that, since it involves too much information
+ * that is owned by other threads...
+ */
+
+ /*
+ * No need to use gui.vimWindow->Lock(): we are locked already.
+ * However, it would not hurt.
+ */
+ gui_redraw((int) updateRect.left, (int) updateRect.top,
+ (int) (updateRect.Width() + PEN_WIDTH), (int) (updateRect.Height() + PEN_WIDTH));
+
+ /* Clear the border areas if needed */
+ rgb_color rgb = GUI_TO_RGB(gui.back_pixel);
+ SetLowColor(rgb);
+
+ if (updateRect.left < FILL_X(0)) // left border
+ FillRect(BRect(updateRect.left, updateRect.top,
+ FILL_X(0)-PEN_WIDTH, updateRect.bottom), B_SOLID_LOW);
+ if (updateRect.top < FILL_Y(0)) // top border
+ FillRect(BRect(updateRect.left, updateRect.top,
+ updateRect.right, FILL_Y(0)-PEN_WIDTH), B_SOLID_LOW);
+ if (updateRect.right >= FILL_X(Columns)) // right border
+ FillRect(BRect(FILL_X((int)Columns), updateRect.top,
+ updateRect.right, updateRect.bottom), B_SOLID_LOW);
+ if (updateRect.bottom >= FILL_Y(Rows)) // bottom border
+ FillRect(BRect(updateRect.left, FILL_Y((int)Rows),
+ updateRect.right, updateRect.bottom), B_SOLID_LOW);
+}
+
+ void
+VimTextAreaView::KeyDown(const char *bytes, int32 numBytes)
+{
+ struct VimKeyMsg km;
+ char_u *dest = km.chars;
+
+ BMessage *msg = Window()->CurrentMessage();
+ assert(msg);
+ //msg->PrintToStream();
+
+ /*
+ * Convert special keys to Vim codes.
+ * I think it is better to do it in the window thread
+ * so we use at least a little bit of the potential
+ * of our 2 CPUs. Besides, due to the fantastic mapping
+ * of special keys to UTF-8, we have quite some work to
+ * do...
+ * TODO: I'm not quite happy with detection of special
+ * keys. Perhaps I should use scan codes after all...
+ */
+ if (numBytes > 1) {
+ /* This cannot be a special key */
+ if (numBytes > KEY_MSG_BUFSIZ)
+ numBytes = KEY_MSG_BUFSIZ; // should never happen... ???
+ km.length = numBytes;
+ memcpy((char *)dest, bytes, numBytes);
+ } else {
+ int32 scancode = 0;
+ msg->FindInt32("key", &scancode);
+
+ int32 beModifiers = 0;
+ msg->FindInt32("modifiers", &beModifiers);
+
+ char_u string[3];
+ int len = 0;
+ km.length = 0;
+
+ bool canHaveVimModifiers = false;
+
+ /*
+ * For normal, printable ASCII characters, don't look them up
+ * to check if they might be a special key. They aren't.
+ */
+ assert(B_BACKSPACE <= 0x20);
+ assert(B_DELETE == 0x7F);
+ if (((char_u)bytes[0] <= 0x20 || (char_u)bytes[0] == 0x7F) &&
+ numBytes == 1) {
+ /*
+ * Due to the great nature of Be's mapping of special keys,
+ * viz. into the range of the control characters,
+ * we can only be sure it is *really* a special key if
+ * if it is special without using ctrl. So, only if ctrl is
+ * used, we need to check it unmodified.
+ */
+ if (beModifiers & B_CONTROL_KEY) {
+ int index = keyMap->normal_map[scancode];
+ int newNumBytes = keyMapChars[index];
+ char_u *newBytes = (char_u *)&keyMapChars[index + 1];
+
+ /*
+ * Check if still special without the control key.
+ * This is needed for BACKSPACE: that key does produce
+ * different values with modifiers (DEL).
+ * Otherwise we could simply have checked for equality.
+ */
+ if (newNumBytes != 1 || (*newBytes > 0x20 &&
+ *newBytes != 0x7F )) {
+ goto notspecial;
+ }
+ bytes = (char *)newBytes;
+ }
+ canHaveVimModifiers = true;
+
+ uint16 beoskey;
+ int first, last;
+
+ /*
+ * If numBytes == 0 that probably always indicates a special key.
+ * (does not happen yet)
+ */
+ if (numBytes == 0 || bytes[0] == B_FUNCTION_KEY) {
+ beoskey = F(scancode);
+ first = FIRST_FUNCTION_KEY;
+ last = NUM_SPECIAL_KEYS;
+ } else if (*bytes == '\n' && scancode == 0x47) {
+ /* remap the (non-keypad) ENTER key from \n to \r. */
+ string[0] = '\r';
+ len = 1;
+ first = last = 0;
+ } else {
+ beoskey = K(bytes[0]);
+ first = 0;
+ last = FIRST_FUNCTION_KEY;
+ }
+
+ for (int i = first; i < last; i++) {
+ if (special_keys[i].BeKeys == beoskey) {
+ string[0] = CSI;
+ string[1] = special_keys[i].vim_code0;
+ string[2] = special_keys[i].vim_code1;
+ len = 3;
+ }
+ }
+ }
+ notspecial:
+ if (len == 0) {
+ string[0] = bytes[0];
+ len = 1;
+ }
+
+ /* Special keys (and a few others) may have modifiers */
+#if 0
+ if (len == 3 ||
+ bytes[0] == B_SPACE || bytes[0] == B_TAB ||
+ bytes[0] == B_RETURN || bytes[0] == '\r' ||
+ bytes[0] == B_ESCAPE)
+#else
+ if (canHaveVimModifiers)
+#endif
+ {
+ int modifiers;
+ modifiers = 0;
+ if (beModifiers & B_SHIFT_KEY)
+ modifiers |= MOD_MASK_SHIFT;
+ if (beModifiers & B_CONTROL_KEY)
+ modifiers |= MOD_MASK_CTRL;
+ if (beModifiers & B_OPTION_KEY)
+ modifiers |= MOD_MASK_ALT;
+
+ /*
+ * For some keys a shift modifier is translated into another key
+ * code. Do we need to handle the case where len != 1 and
+ * string[0] != CSI? (Not for BeOS, since len == 3 implies
+ * string[0] == CSI...)
+ */
+ int key;
+ if (string[0] == CSI && len == 3)
+ key = TO_SPECIAL(string[1], string[2]);
+ else
+ key = string[0];
+ key = simplify_key(key, &modifiers);
+ if (IS_SPECIAL(key))
+ {
+ string[0] = CSI;
+ string[1] = K_SECOND(key);
+ string[2] = K_THIRD(key);
+ len = 3;
+ }
+ else
+ {
+ string[0] = key;
+ len = 1;
+ }
+
+ if (modifiers)
+ {
+ *dest++ = CSI;
+ *dest++ = KS_MODIFIER;
+ *dest++ = modifiers;
+ km.length = 3;
+ }
+ }
+ memcpy((char *)dest, string, len);
+ km.length += len;
+ }
+
+ write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
+
+ /*
+ * blank out the pointer if necessary
+ */
+ if (p_mh && !gui.pointer_hidden)
+ {
+ guiBlankMouse(true);
+ gui.pointer_hidden = TRUE;
+ }
+}
+ void
+VimTextAreaView::guiSendMouseEvent(
+ int button,
+ int x,
+ int y,
+ int repeated_click,
+ int_u modifiers)
+{
+ VimMouseMsg mm;
+
+ mm.button = button;
+ mm.x = x;
+ mm.y = y;
+ mm.repeated_click = repeated_click;
+ mm.modifiers = modifiers;
+
+ write_port(gui.vdcmp, VimMsg::Mouse, &mm, sizeof(mm));
+ // calls gui_send_mouse_event()
+
+ /*
+ * if our pointer is currently hidden, then we should show it.
+ */
+ if (gui.pointer_hidden)
+ {
+ guiBlankMouse(false);
+ gui.pointer_hidden = FALSE;
+ }
+}
+
+ void
+VimTextAreaView::guiBlankMouse(bool should_hide)
+{
+ if (should_hide) {
+ //gui.vimApp->HideCursor();
+ gui.vimApp->ObscureCursor();
+ /*
+ * ObscureCursor() would even be easier, but then
+ * Vim's idea of mouse visibility does not necessarily
+ * correspond to reality.
+ */
+ } else {
+ //gui.vimApp->ShowCursor();
+ }
+}
+
+ int_u
+VimTextAreaView::mouseModifiersToVim(int32 beModifiers)
+{
+ int_u vim_modifiers = 0x0;
+
+ if (beModifiers & B_SHIFT_KEY)
+ vim_modifiers |= MOUSE_SHIFT;
+ if (beModifiers & B_CONTROL_KEY)
+ vim_modifiers |= MOUSE_CTRL;
+ if (beModifiers & B_OPTION_KEY) /* Alt or Meta key */
+ vim_modifiers |= MOUSE_ALT;
+
+ return vim_modifiers;
+}
+
+ void
+VimTextAreaView::MouseDown(BPoint point)
+{
+ BMessage *m = Window()->CurrentMessage();
+ assert(m);
+
+ int32 buttons = 0;
+ m->FindInt32("buttons", &buttons);
+
+ int vimButton;
+
+ if (buttons & B_PRIMARY_MOUSE_BUTTON)
+ vimButton = MOUSE_LEFT;
+ else if (buttons & B_SECONDARY_MOUSE_BUTTON)
+ vimButton = MOUSE_RIGHT;
+ else if (buttons & B_TERTIARY_MOUSE_BUTTON)
+ vimButton = MOUSE_MIDDLE;
+ else
+ return; /* Unknown button */
+
+ vimMouseButton = 1; /* don't care which one */
+
+ /* Handle multiple clicks */
+ int32 clicks = 0;
+ m->FindInt32("clicks", &clicks);
+
+ int32 modifiers = 0;
+ m->FindInt32("modifiers", &modifiers);
+
+ vimMouseModifiers = mouseModifiersToVim(modifiers);
+
+ guiSendMouseEvent(vimButton, point.x, point.y,
+ clicks > 1 /* = repeated_click*/, vimMouseModifiers);
+}
+
+ void
+VimTextAreaView::MouseUp(BPoint point)
+{
+ vimMouseButton = 0;
+
+ BMessage *m = Window()->CurrentMessage();
+ assert(m);
+ //m->PrintToStream();
+
+ int32 modifiers = 0;
+ m->FindInt32("modifiers", &modifiers);
+
+ vimMouseModifiers = mouseModifiersToVim(modifiers);
+
+ guiSendMouseEvent(MOUSE_RELEASE, point.x, point.y,
+ 0 /* = repeated_click*/, vimMouseModifiers);
+
+ Inherited::MouseUp(point);
+}
+
+ void
+VimTextAreaView::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
+{
+ /*
+ * if our pointer is currently hidden, then we should show it.
+ */
+ if (gui.pointer_hidden)
+ {
+ guiBlankMouse(false);
+ gui.pointer_hidden = FALSE;
+ }
+
+ if (!vimMouseButton) /* could also check m->"buttons" */
+ return;
+
+ atomic_add(&mouseDragEventCount, 1);
+
+ /* Don't care much about "transit" */
+ guiSendMouseEvent(MOUSE_DRAG, point.x, point.y, 0, vimMouseModifiers);
+}
+
+ void
+VimTextAreaView::MessageReceived(BMessage *m)
+{
+ switch (m->what) {
+ case 'menu':
+ {
+ VimMenuMsg mm;
+ mm.guiMenu = NULL; /* in case no pointer in msg */
+ m->FindPointer("VimMenu", (void **)&mm.guiMenu);
+
+ write_port(gui.vdcmp, VimMsg::Menu, &mm, sizeof(mm));
+ }
+ break;
+ default:
+ if (m->WasDropped()) {
+ BWindow *w = Window();
+ w->DetachCurrentMessage();
+ w->Minimize(false);
+ VimApp::SendRefs(m, (modifiers() & B_SHIFT_KEY) != 0);
+ } else {
+ Inherited::MessageReceived(m);
+ }
+ break;
+ }
+}
+
+ int
+VimTextAreaView::mchInitFont(char_u *name)
+{
+ VimFont *newFont = (VimFont *)gui_mch_get_font(name, 0);
+
+ gui.norm_font = (GuiFont)newFont;
+ gui_mch_set_font((GuiFont)newFont);
+ if (name)
+ hl_set_font_name(name);
+
+ SetDrawingMode(B_OP_COPY);
+
+ /*
+ * Try to load other fonts for bold, italic, and bold-italic.
+ * We should also try to work out what font to use for these when they are
+ * not specified by X resources, but we don't yet.
+ */
+
+ return OK;
+}
+
+ void
+VimTextAreaView::mchDrawString(int row, int col, char_u *s, int len, int flags)
+{
+ /*
+ * First we must erase the area, because DrawString won't do
+ * that for us. XXX Most of the time this is a waste of effort
+ * since the bachground has been erased already... DRAW_TRANSP
+ * should be set when appropriate!!!
+ * (Rectangles include the bottom and right edge)
+ */
+ if (!(flags & DRAW_TRANSP)) {
+ BRect r(FILL_X(col), FILL_Y(row),
+ FILL_X(col + len) - PEN_WIDTH, FILL_Y(row + 1) - PEN_WIDTH);
+ FillRect(r, B_SOLID_LOW);
+ }
+ BPoint where(TEXT_X(col), TEXT_Y(row));
+ DrawString((char *)s, len, where);
+
+ if (flags & DRAW_BOLD) {
+ where.x += 1.0;
+ SetDrawingMode(B_OP_BLEND);
+ DrawString((char *)s, len, where);
+ SetDrawingMode(B_OP_COPY);
+ }
+ if (flags & DRAW_UNDERL) {
+ BPoint start(FILL_X(col), FILL_Y(row + 1) - PEN_WIDTH);
+ BPoint end(FILL_X(col + len) - PEN_WIDTH, start.y);
+
+ StrokeLine(start, end);
+ }
+}
+
+ void
+VimTextAreaView::mchClearBlock(
+ int row1,
+ int col1,
+ int row2,
+ int col2)
+{
+ BRect r(FILL_X(col1), FILL_Y(row1),
+ FILL_X(col2 + 1) - PEN_WIDTH, FILL_Y(row2 + 1) - PEN_WIDTH);
+ gui_mch_set_bg_color(gui.back_pixel);
+ FillRect(r, B_SOLID_LOW);
+}
+
+ void
+VimTextAreaView::mchClearAll()
+{
+ gui_mch_set_bg_color(gui.back_pixel);
+ FillRect(Bounds(), B_SOLID_LOW);
+}
+
+/*
+ * mchDeleteLines() Lock()s the window by itself.
+ */
+ void
+VimTextAreaView::mchDeleteLines(int row, int num_lines)
+{
+ if (row + num_lines > gui.scroll_region_bot)
+ {
+ /* Scrolled out of region, just blank the lines out */
+ gui_clear_block(row, gui.scroll_region_left,
+ gui.scroll_region_bot, gui.scroll_region_right);
+ }
+ else
+ {
+ /* copy one extra pixel, for when bold has spilled over */
+ int width = gui.char_width * (gui.scroll_region_right
+ - gui.scroll_region_left + 1) + 1 - PEN_WIDTH;
+ int height = gui.char_height *
+ (gui.scroll_region_bot - row - num_lines + 1) - PEN_WIDTH;
+
+ BRect source, dest;
+
+ source.left = FILL_X(gui.scroll_region_left);
+ source.top = FILL_Y(row + num_lines);
+ source.right = source.left + width;
+ source.bottom = source.top + height;
+
+ dest.left = FILL_X(gui.scroll_region_left);
+ dest.top = FILL_Y(row);
+ dest.right = dest.left + width;
+ dest.bottom = dest.top + height;
+
+ /* XXX Attempt at a hack: */
+ gui.vimWindow->UpdateIfNeeded();
+#if 0
+ /* XXX Attempt at a hack: */
+ if (gui.vimWindow->NeedsUpdate()) {
+ fprintf(stderr, "mchDeleteLines: NeedsUpdate!\n");
+ gui.vimWindow->UpdateIfNeeded();
+ while (gui.vimWindow->NeedsUpdate()) {
+ if (false && gui.vimWindow->Lock()) {
+ Sync();
+ gui.vimWindow->Unlock();
+ }
+ snooze(2);
+ }
+ }
+#endif
+
+ if (gui.vimWindow->Lock()) {
+ Sync();
+ CopyBits(source, dest);
+ //Sync();
+
+ /* Update gui.cursor_row if the cursor scrolled or copied over */
+ if (gui.cursor_row >= row
+ && gui.cursor_col >= gui.scroll_region_left
+ && gui.cursor_col <= gui.scroll_region_right)
+ {
+ if (gui.cursor_row < row + num_lines)
+ gui.cursor_is_valid = FALSE;
+ else if (gui.cursor_row <= gui.scroll_region_bot)
+ gui.cursor_row -= num_lines;
+ }
+
+ /* Clear one column more for when bold has spilled over */
+ gui_clear_block(gui.scroll_region_bot - num_lines + 1,
+ gui.scroll_region_left,
+ gui.scroll_region_bot, gui.scroll_region_right);
+
+ gui.vimWindow->Unlock();
+ /*
+ * The Draw() callback will be called now if some of the source
+ * bits were not in the visible region.
+ */
+
+ //gui_x11_check_copy_area();
+ }
+ }
+}
+
+/*
+ * mchInsertLines() Lock()s the window by itself.
+ */
+ void
+VimTextAreaView::mchInsertLines(int row, int num_lines)
+{
+ if (row + num_lines > gui.scroll_region_bot)
+ {
+ /* Scrolled out of region, just blank the lines out */
+ gui_clear_block(row, gui.scroll_region_left,
+ gui.scroll_region_bot, gui.scroll_region_right);
+ }
+ else
+ {
+ /* copy one extra pixel, for when bold has spilled over */
+ int width = gui.char_width * (gui.scroll_region_right
+ - gui.scroll_region_left + 1) + 1 - PEN_WIDTH;
+ int height = gui.char_height *
+ (gui.scroll_region_bot - row - num_lines + 1) - PEN_WIDTH;
+
+ BRect source, dest;
+
+ source.left = FILL_X(gui.scroll_region_left);
+ source.top = FILL_Y(row);
+ source.right = source.left + width;
+ source.bottom = source.top + height;
+
+ dest.left = FILL_X(gui.scroll_region_left);
+ dest.top = FILL_Y(row + num_lines);
+ dest.right = dest.left + width;
+ dest.bottom = dest.top + height;
+
+ /* XXX Attempt at a hack: */
+ gui.vimWindow->UpdateIfNeeded();
+#if 0
+ /* XXX Attempt at a hack: */
+ if (gui.vimWindow->NeedsUpdate())
+ fprintf(stderr, "mchInsertLines: NeedsUpdate!\n");
+ gui.vimWindow->UpdateIfNeeded();
+ while (gui.vimWindow->NeedsUpdate())
+ snooze(2);
+#endif
+
+ if (gui.vimWindow->Lock()) {
+ Sync();
+ CopyBits(source, dest);
+ //Sync();
+
+ /* Update gui.cursor_row if the cursor scrolled or copied over */
+ if (gui.cursor_row >= gui.row
+ && gui.cursor_col >= gui.scroll_region_left
+ && gui.cursor_col <= gui.scroll_region_right)
+ {
+ if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
+ gui.cursor_row += num_lines;
+ else if (gui.cursor_row <= gui.scroll_region_bot)
+ gui.cursor_is_valid = FALSE;
+ }
+ /* Clear one column more for when bold has spilled over */
+ gui_clear_block(row, gui.scroll_region_left,
+ row + num_lines - 1, gui.scroll_region_right);
+
+ gui.vimWindow->Unlock();
+ /*
+ * The Draw() callback will be called now if some of the source
+ * bits were not in the visible region.
+ * However, if we scroll too fast it can't keep up and the
+ * update region gets messed up. This seems to be because copying
+ * un-Draw()n bits does not generate Draw() calls for the copy...
+ * I moved the hack to before the CopyBits() to reduce the
+ * amount of additional waiting needed.
+ */
+
+ //gui_x11_check_copy_area();
+ }
+ }
+
+}
+
+/* ---------------- VimScrollBar ---------------- */
+
+/* BUG: XXX
+ * It seems that BScrollBar determine their direction not from
+ * "posture" but from if they are "tall" or "wide" in shape...
+ *
+ * Also, place them out of sight, because Vim enables them before
+ * they are positioned.
+ */
+VimScrollBar::VimScrollBar(scrollbar_T *g, orientation posture):
+ BScrollBar(posture == B_HORIZONTAL ? BRect(-100,-100,-10,-90) :
+ BRect(-100,-100,-90,-10),
+ "vim scrollbar", (BView *)NULL,
+ 0.0, 10.0, posture),
+ ignoreValue(-1),
+ scrollEventCount(0)
+{
+ gsb = g;
+ SetResizingMode(B_FOLLOW_NONE);
+}
+
+VimScrollBar::~VimScrollBar()
+{
+}
+
+ void
+VimScrollBar::ValueChanged(float newValue)
+{
+ if (ignoreValue >= 0.0 && newValue == ignoreValue) {
+ ignoreValue = -1;
+ return;
+ }
+ ignoreValue = -1;
+ /*
+ * We want to throttle the amount of scroll messages generated.
+ * Normally I presume you won't get a new message before we've
+ * handled the previous one, but because we're passing them on this
+ * happens very quickly. So instead we keep a counter of how many
+ * scroll events there are (or will be) in the VDCMP, and the
+ * throttling happens at the receiving end.
+ */
+ atomic_add(&scrollEventCount, 1);
+
+ struct VimScrollBarMsg sm;
+
+ sm.sb = this;
+ sm.value = (long) newValue;
+ sm.stillDragging = TRUE;
+
+ write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm));
+
+ // calls gui_drag_scrollbar(sb, newValue, TRUE);
+}
+
+/*
+ * When the mouse goes up, report that scrolling has stopped.
+ * MouseUp() is NOT called when the mouse-up occurs outside
+ * the window, even though the thumb does move while the mouse
+ * is outside... This has some funny effects... XXX
+ * So we do special processing when the window de/activates.
+ */
+ void
+VimScrollBar::MouseUp(BPoint where)
+{
+ //BMessage *m = Window()->CurrentMessage();
+ //m->PrintToStream();
+
+ atomic_add(&scrollEventCount, 1);
+
+ struct VimScrollBarMsg sm;
+
+ sm.sb = this;
+ sm.value = (long) Value();
+ sm.stillDragging = FALSE;
+
+ write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm));
+
+ // calls gui_drag_scrollbar(sb, newValue, FALSE);
+
+ Inherited::MouseUp(where);
+}
+
+ void
+VimScrollBar::SetValue(float newValue)
+{
+ if (newValue == Value())
+ return;
+
+ ignoreValue = newValue;
+ Inherited::SetValue(newValue);
+}
+
+/* ---------------- VimFont ---------------- */
+
+VimFont::VimFont(): BFont()
+{
+ init();
+}
+
+VimFont::VimFont(const VimFont *rhs): BFont(rhs)
+{
+ init();
+}
+
+VimFont::VimFont(const BFont *rhs): BFont(rhs)
+{
+ init();
+}
+
+VimFont::VimFont(const VimFont &rhs): BFont(rhs)
+{
+ init();
+}
+
+VimFont::~VimFont()
+{
+}
+
+ void
+VimFont::init()
+{
+ next = NULL;
+ refcount = 1;
+ name = NULL;
+}
+
+/* ---------------- ---------------- */
+
+// some global variables
+static char appsig[] = "application/x-vnd.Rhialto-Vim-5";
+key_map *keyMap;
+char *keyMapChars;
+int main_exitcode = 127;
+
+ status_t
+gui_beos_process_event(bigtime_t timeout)
+{
+ struct VimMsg vm;
+ long what;
+ ssize_t size;
+
+ size = read_port_etc(gui.vdcmp, &what, &vm, sizeof(vm),
+ B_TIMEOUT, timeout);
+
+ if (size >= 0) {
+ switch (what) {
+ case VimMsg::Key:
+ {
+ char_u *string = vm.u.Key.chars;
+ int len = vm.u.Key.length;
+ if (len == 1 && string[0] == Ctrl_chr('C')) {
+ trash_input_buf();
+ got_int = TRUE;
+ }
+ add_to_input_buf(string, len);
+ }
+ break;
+ case VimMsg::Resize:
+ gui_resize_shell(vm.u.NewSize.width, vm.u.NewSize.height);
+ break;
+ case VimMsg::ScrollBar:
+ {
+ /*
+ * If loads of scroll messages queue up, use only the last
+ * one. Always report when the scrollbar stops dragging.
+ * This is not perfect yet anyway: these events are queued
+ * yet again, this time in the keyboard input buffer.
+ */
+ int32 oldCount =
+ atomic_add(&vm.u.Scroll.sb->scrollEventCount, -1);
+ if (oldCount <= 1 || !vm.u.Scroll.stillDragging)
+ gui_drag_scrollbar(vm.u.Scroll.sb->getGsb(),
+ vm.u.Scroll.value, vm.u.Scroll.stillDragging);
+ }
+ break;
+ case VimMsg::Menu:
+ gui_menu_cb(vm.u.Menu.guiMenu);
+ break;
+ case VimMsg::Mouse:
+ {
+ int32 oldCount;
+ if (vm.u.Mouse.button == MOUSE_DRAG)
+ oldCount =
+ atomic_add(&gui.vimTextArea->mouseDragEventCount, -1);
+ else
+ oldCount = 0;
+ if (oldCount <= 1)
+ gui_send_mouse_event(vm.u.Mouse.button, vm.u.Mouse.x,
+ vm.u.Mouse.y, vm.u.Mouse.repeated_click,
+ vm.u.Mouse.modifiers);
+ }
+ break;
+ case VimMsg::Focus:
+ gui.in_focus = vm.u.Focus.active;
+ /* XXX Signal that scrollbar dragging has stopped?
+ * This is needed because we don't get a MouseUp if
+ * that happens while outside the window... :-(
+ */
+ if (gui.dragged_sb) {
+ gui.dragged_sb = SBAR_NONE;
+ }
+ gui_update_cursor(TRUE, FALSE);
+ break;
+ case VimMsg::Refs:
+ ::RefsReceived(vm.u.Refs.message, vm.u.Refs.changedir);
+ break;
+ default:
+ // unrecognised message, ignore it
+ break;
+ }
+ }
+
+ /*
+ * If size < B_OK, it is an error code.
+ */
+ return size;
+}
+
+/*
+ * Here are some functions to protect access to ScreenLines[] and
+ * LineOffset[]. These are used from the window thread to respond
+ * to a Draw() callback. When that occurs, the window is already
+ * locked by the system.
+ *
+ * Other code that needs to lock is any code that changes these
+ * variables. Other read-only access, or access merely to the
+ * contents of the screen buffer, need not be locked.
+ *
+ * If there is no window, don't call Lock() but do succeed.
+ */
+
+ int
+vim_lock_screen()
+{
+ return !gui.vimWindow || gui.vimWindow->Lock();
+}
+
+ void
+vim_unlock_screen()
+{
+ if (gui.vimWindow)
+ gui.vimWindow->Unlock();
+}
+
+#define RUN_BAPPLICATION_IN_NEW_THREAD 0
+
+#if RUN_BAPPLICATION_IN_NEW_THREAD
+
+ int32
+run_vimapp(void *args)
+{
+ VimApp app(appsig);
+
+ gui.vimApp = &app;
+ app.Run(); /* Run until Quit() called */
+
+ return 0;
+}
+
+#else
+
+ int32
+call_main(void *args)
+{
+ struct MainArgs *ma = (MainArgs *)args;
+
+ return main(ma->argc, ma->argv);
+}
+#endif
+
+extern "C" {
+
+/*
+ * Parse the GUI related command-line arguments. Any arguments used are
+ * deleted from argv, and *argc is decremented accordingly. This is called
+ * when vim is started, whether or not the GUI has been started.
+ */
+ void
+gui_mch_prepare(
+ int *argc,
+ char **argv)
+{
+ /*
+ * We don't have any command line arguments for the BeOS GUI yet,
+ * but this is an excellent place to create our Application object.
+ */
+ if (!gui.vimApp) {
+ thread_info tinfo;
+ get_thread_info(find_thread(NULL), &tinfo);
+
+ /* May need the port very early on to process RefsReceived() */
+ gui.vdcmp = create_port(B_MAX_PORT_COUNT, "vim VDCMP");
+
+#if RUN_BAPPLICATION_IN_NEW_THREAD
+ thread_id tid = spawn_thread(run_vimapp, "vim VimApp",
+ tinfo.priority, NULL);
+ if (tid >= B_OK) {
+ resume_thread(tid);
+ } else {
+ getout(1);
+ }
+#else
+ MainArgs ma = { *argc, argv };
+ thread_id tid = spawn_thread(call_main, "vim main()",
+ tinfo.priority, &ma);
+ if (tid >= B_OK) {
+ VimApp app(appsig);
+
+ gui.vimApp = &app;
+ resume_thread(tid);
+ /*
+ * This is rather horrible.
+ * call_main will call main() again...
+ * There will be no infinite recursion since
+ * gui.vimApp is set now.
+ */
+ app.Run(); /* Run until Quit() called */
+ //fprintf(stderr, "app.Run() returned...\n");
+ status_t dummy_exitcode;
+ (void)wait_for_thread(tid, &dummy_exitcode);
+
+ /*
+ * This path should be the normal one taken to exit Vim.
+ * The main() thread calls mch_exit() which calls
+ * gui_mch_exit() which terminates its thread.
+ */
+ exit(main_exitcode);
+ }
+#endif
+ }
+ /* Don't fork() when starting the GUI. Spawned threads are not
+ * duplicated with a fork(). The result is a mess.
+ */
+ gui.dofork = FALSE;
+ /*
+ * XXX Try to determine whether we were started from
+ * the Tracker or the terminal.
+ * It would be nice to have this work, because the Tracker
+ * follows symlinks, so even if you double-click on gvim,
+ * when it is a link to vim it will still pass a command name
+ * of vim...
+ * We try here to see if stdin comes from /dev/null. If so,
+ * (or if there is an error, which should never happen) start the GUI.
+ * This does the wrong thing for vim - </dev/null, and we're
+ * too early to see the command line parsing. Tough.
+ * On the other hand, it starts the gui for vim file & which is nice.
+ */
+ if (!isatty(0)) {
+ struct stat stat_stdin, stat_dev_null;
+
+ if (fstat(0, &stat_stdin) == -1 ||
+ stat("/dev/null", &stat_dev_null) == -1 ||
+ (stat_stdin.st_dev == stat_dev_null.st_dev &&
+ stat_stdin.st_ino == stat_dev_null.st_ino))
+ gui.starting = TRUE;
+ }
+}
+
+/*
+ * Check if the GUI can be started. Called before gvimrc is sourced.
+ * Return OK or FAIL.
+ */
+ int
+gui_mch_init_check(void)
+{
+ return OK; /* TODO: GUI can always be started? */
+}
+
+/*
+ * Initialise the GUI. Create all the windows, set up all the call-backs
+ * etc.
+ */
+ int
+gui_mch_init()
+{
+ gui.def_norm_pixel = RGB(0x00, 0x00, 0x00); // black
+ gui.def_back_pixel = RGB(0xFF, 0xFF, 0xFF); // white
+ gui.norm_pixel = gui.def_norm_pixel;
+ gui.back_pixel = gui.def_back_pixel;
+
+ gui.scrollbar_width = (int) B_V_SCROLL_BAR_WIDTH;
+ gui.scrollbar_height = (int) B_H_SCROLL_BAR_HEIGHT;
+#ifdef FEAT_MENU
+ gui.menu_height = 19; // initial guess -
+ // correct for my default settings
+#endif
+ gui.border_offset = 3; // coordinates are inside window borders
+
+ if (gui.vdcmp < B_OK)
+ return FAIL;
+ get_key_map(&keyMap, &keyMapChars);
+
+ gui.vimWindow = new VimWindow(); /* hidden and locked */
+ if (!gui.vimWindow)
+ return FAIL;
+
+ gui.vimWindow->Run(); /* Run() unlocks but does not show */
+
+ /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
+ * file) */
+ set_normal_colors();
+
+ /*
+ * Check that none of the colors are the same as the background color
+ */
+ gui_check_colors();
+
+ /* Get the colors for the highlight groups (gui_check_colors() might have
+ * changed them) */
+ highlight_gui_started(); /* re-init colors and fonts */
+
+ gui_mch_new_colors(); /* window must exist for this */
+
+ return OK;
+}
+
+/*
+ * Called when the foreground or background color has been changed.
+ */
+ void
+gui_mch_new_colors()
+{
+ rgb_color rgb = GUI_TO_RGB(gui.back_pixel);
+
+ if (gui.vimWindow->Lock()) {
+ gui.vimForm->SetViewColor(rgb);
+ // Does this not have too much effect for those small rectangles?
+ gui.vimForm->Invalidate();
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Open the GUI window which was created by a call to gui_mch_init().
+ */
+ int
+gui_mch_open()
+{
+ if (gui_win_x != -1 && gui_win_y != -1)
+ gui_mch_set_winpos(gui_win_x, gui_win_y);
+
+ /* Actually open the window */
+ if (gui.vimWindow->Lock()) {
+ gui.vimWindow->Show();
+ gui.vimWindow->Unlock();
+
+#if USE_THREAD_FOR_INPUT_WITH_TIMEOUT
+ /* Kill the thread that may have been created for the Terminal */
+ beos_cleanup_read_thread();
+#endif
+
+ return OK;
+ }
+
+ return FAIL;
+}
+
+ void
+gui_mch_exit(int vim_exitcode)
+{
+ if (gui.vimWindow) {
+ thread_id tid = gui.vimWindow->Thread();
+ gui.vimWindow->Lock();
+ gui.vimWindow->Quit();
+ /* Wait until it is truely gone */
+ int32 exitcode;
+ wait_for_thread(tid, &exitcode);
+ }
+ delete_port(gui.vdcmp);
+#if !RUN_BAPPLICATION_IN_NEW_THREAD
+ /*
+ * We are in the main() thread - quit the App thread and
+ * quit ourselves (passing on the exitcode). Use a global since the
+ * value from exit_thread() is only used if wait_for_thread() is
+ * called in time (race condition).
+ */
+#endif
+ if (gui.vimApp) {
+ VimTextAreaView::guiBlankMouse(false);
+
+ main_exitcode = vim_exitcode;
+#if RUN_BAPPLICATION_IN_NEW_THREAD
+ thread_id tid = gui.vimApp->Thread();
+ int32 exitcode;
+ gui.vimApp->Lock();
+ gui.vimApp->Quit();
+ gui.vimApp->Unlock();
+ wait_for_thread(tid, &exitcode);
+#else
+ gui.vimApp->Lock();
+ gui.vimApp->Quit();
+ gui.vimApp->Unlock();
+ /* suicide */
+ exit_thread(vim_exitcode);
+#endif
+ }
+ /* If we are somehow still here, let mch_exit() handle things. */
+}
+
+/*
+ * Get the position of the top left corner of the window.
+ */
+ int
+gui_mch_get_winpos(int *x, int *y)
+{
+ /* TODO */
+ return FAIL;
+}
+
+/*
+ * Set the position of the top left corner of the window to the given
+ * coordinates.
+ */
+ void
+gui_mch_set_winpos(int x, int y)
+{
+ /* TODO */
+}
+
+/*
+ * Set the size of the window to the given width and height in pixels.
+ */
+ void
+gui_mch_set_shellsize(
+ int width,
+ int height,
+ int min_width,
+ int min_height,
+ int base_width,
+ int base_height)
+{
+ /*
+ * We are basically given the size of the VimForm, if I understand
+ * correctly. Since it fills the window completely, this will also
+ * be the size of the window.
+ */
+ if (gui.vimWindow->Lock()) {
+ gui.vimWindow->ResizeTo(width - PEN_WIDTH, height - PEN_WIDTH);
+
+ /* set size limits */
+ float minWidth, maxWidth, minHeight, maxHeight;
+
+ gui.vimWindow->GetSizeLimits(&minWidth, &maxWidth,
+ &minHeight, &maxHeight);
+ gui.vimWindow->SetSizeLimits(min_width, maxWidth,
+ min_height, maxHeight);
+
+#if HAVE_R3_OR_LATER
+ /*
+ * Set the resizing alignment depending on font size.
+ * XXX This is untested, since I don't have R3 yet.
+ */
+ SetWindowAlignment(
+ B_PIXEL_ALIGNMENT, // window_alignment mode,
+ 1, // int32 h,
+ 0, // int32 hOffset = 0,
+ gui.char_width, // int32 width = 0,
+ base_width, // int32 widthOffset = 0,
+ 1, // int32 v = 0,
+ 0, // int32 vOffset = 0,
+ gui.char_height, // int32 height = 0,
+ base_height // int32 heightOffset = 0
+ );
+#else
+ /* don't know what to do with base_{width,height}. */
+#endif
+
+ gui.vimWindow->Unlock();
+ }
+}
+
+ void
+gui_mch_get_screen_dimensions(
+ int *screen_w,
+ int *screen_h)
+{
+ BRect frame;
+
+ {
+ BScreen screen(gui.vimWindow);
+
+ if (screen.IsValid()) {
+ frame = screen.Frame();
+ } else {
+ frame.right = 640;
+ frame.bottom = 480;
+ }
+ }
+
+ /* XXX approximations... */
+ *screen_w = (int) frame.right - 2 * gui.scrollbar_width - 20;
+ *screen_h = (int) frame.bottom - gui.scrollbar_height
+#ifdef FEAT_MENU
+ - gui.menu_height
+#endif
+ - 30;
+}
+
+ void
+gui_mch_set_text_area_pos(
+ int x,
+ int y,
+ int w,
+ int h)
+{
+ if (!gui.vimTextArea)
+ return;
+
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->MoveTo(x, y);
+ gui.vimTextArea->ResizeTo(w - PEN_WIDTH, h - PEN_WIDTH);
+ gui.vimWindow->Unlock();
+ }
+}
+
+
+/*
+ * Scrollbar stuff:
+ */
+
+ void
+gui_mch_enable_scrollbar(
+ scrollbar_T *sb,
+ int flag)
+{
+ VimScrollBar *vsb = sb->id;
+ if (gui.vimWindow->Lock()) {
+ /*
+ * This function is supposed to be idempotent, but Show()/Hide()
+ * is not. Therefore we test if they are needed.
+ */
+ if (flag) {
+ if (vsb->IsHidden()) {
+ vsb->Show();
+ }
+ } else {
+ if (!vsb->IsHidden()) {
+ vsb->Hide();
+ }
+ }
+ gui.vimWindow->Unlock();
+ }
+}
+
+ void
+gui_mch_set_scrollbar_thumb(
+ scrollbar_T *sb,
+ int val,
+ int size,
+ int max)
+{
+ if (gui.vimWindow->Lock()) {
+ VimScrollBar *s = sb->id;
+ if (max == 0) {
+ s->SetValue(0);
+ s->SetRange(0.0, 0.0);
+ } else {
+ s->SetProportion((float)size / (max + 1.0));
+ s->SetSteps(1.0, size > 5 ? size - 2 : size);
+#ifndef SCROLL_PAST_END // really only defined in gui.c...
+ max = max + 1 - size;
+#endif
+ if (max < s->Value()) {
+ /*
+ * If the new maximum is lower than the current value,
+ * setting it would cause the value to be clipped and
+ * therefore a ValueChanged() call.
+ * We avoid this by setting the value first, because
+ * it presumably is <= max.
+ */
+ s->SetValue(val);
+ s->SetRange(0.0, max);
+ } else {
+ /*
+ * In the other case, set the range first, since the
+ * new value might be higher than the current max.
+ */
+ s->SetRange(0.0, max);
+ s->SetValue(val);
+ }
+ }
+ gui.vimWindow->Unlock();
+ }
+}
+
+ void
+gui_mch_set_scrollbar_pos(
+ scrollbar_T *sb,
+ int x,
+ int y,
+ int w,
+ int h)
+{
+ if (gui.vimWindow->Lock()) {
+ VimScrollBar *vsb = sb->id;
+ vsb->MoveTo(x, y);
+ vsb->ResizeTo(w - PEN_WIDTH, h - PEN_WIDTH);
+ gui.vimWindow->Unlock();
+ }
+}
+
+ void
+gui_mch_create_scrollbar(
+ scrollbar_T *sb,
+ int orient) /* SBAR_VERT or SBAR_HORIZ */
+{
+ orientation posture =
+ (orient == SBAR_HORIZ) ? B_HORIZONTAL : B_VERTICAL;
+
+ VimScrollBar *vsb = sb->id = new VimScrollBar(sb, posture);
+ if (gui.vimWindow->Lock()) {
+ vsb->SetTarget(gui.vimTextArea);
+ vsb->Hide();
+ gui.vimForm->AddChild(vsb);
+ gui.vimWindow->Unlock();
+ }
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+ void
+gui_mch_destroy_scrollbar(
+ scrollbar_T *sb)
+{
+ if (gui.vimWindow->Lock()) {
+ sb->id->RemoveSelf();
+ delete sb->id;
+ gui.vimWindow->Unlock();
+ }
+}
+#endif
+
+/*
+ * Cursor blink functions.
+ *
+ * This is a simple state machine:
+ * BLINK_NONE not blinking at all
+ * BLINK_OFF blinking, cursor is not shown
+ * BLINK_ON blinking, cursor is shown
+ */
+
+#define BLINK_NONE 0
+#define BLINK_OFF 1
+#define BLINK_ON 2
+
+static int blink_state = BLINK_NONE;
+static long_u blink_waittime = 700;
+static long_u blink_ontime = 400;
+static long_u blink_offtime = 250;
+static int blink_timer = 0;
+
+ void
+gui_mch_set_blinking(
+ long waittime,
+ long on,
+ long off)
+{
+ /* TODO */
+ blink_waittime = waittime;
+ blink_ontime = on;
+ blink_offtime = off;
+}
+
+/*
+ * Stop the cursor blinking. Show the cursor if it wasn't shown.
+ */
+ void
+gui_mch_stop_blink()
+{
+ /* TODO */
+ if (blink_timer != 0)
+ {
+ //XtRemoveTimeOut(blink_timer);
+ blink_timer = 0;
+ }
+ if (blink_state == BLINK_OFF)
+ gui_update_cursor(TRUE, FALSE);
+ blink_state = BLINK_NONE;
+}
+
+/*
+ * Start the cursor blinking. If it was already blinking, this restarts the
+ * waiting time and shows the cursor.
+ */
+ void
+gui_mch_start_blink()
+{
+ /* TODO */
+ if (blink_timer != 0)
+ ;//XtRemoveTimeOut(blink_timer);
+ /* Only switch blinking on if none of the times is zero */
+ if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
+ {
+ blink_timer = 1; //XtAppAddTimeOut(app_context, blink_waittime,
+ blink_state = BLINK_ON;
+ gui_update_cursor(TRUE, FALSE);
+ }
+}
+
+/*
+ * Initialise vim to use the font with the given name. Return FAIL if the font
+ * could not be loaded, OK otherwise.
+ */
+ int
+gui_mch_init_font(
+ char_u *font_name,
+ int fontset)
+{
+ if (gui.vimWindow->Lock())
+ {
+ int rc = gui.vimTextArea->mchInitFont(font_name);
+ gui.vimWindow->Unlock();
+
+ return rc;
+ }
+
+ return FAIL;
+}
+
+ int
+gui_mch_adjust_charsize()
+{
+ return FAIL;
+}
+
+ GuiFont
+gui_mch_get_font(
+ char_u *name,
+ int giveErrorIfMissing)
+{
+ VimFont *font = 0;
+ static VimFont *fontList = NULL;
+
+ if (!gui.in_use) /* can't do this when GUI not running */
+ return NOFONT;
+
+ if (!name)
+ name = (char_u *)"be_fixed_font";
+
+ VimFont *flp;
+ for (flp = fontList; flp; flp = flp->next) {
+ if (STRCMP(name, flp->name) == 0) {
+ flp->refcount++;
+ return (GuiFont)flp;
+ }
+ }
+
+ font = new VimFont(be_fixed_font);
+
+ /* Set some universal features: */
+ font->SetSpacing(B_FIXED_SPACING);
+ font->SetEncoding(B_ISO_8859_1);
+
+ /* Remember font for later use */
+ font->name = vim_strsave(name);
+ font->next = fontList;
+ fontList = font;
+
+ font_family family;
+ font_style style;
+ int size;
+ int len;
+ char_u *end;
+
+#ifdef never
+ // This leads to SEGV/BUS on R4+
+ // Replace underscores with spaces, and I can't see why ?
+ // richard@whitequeen.com jul 99
+ while (end = (char_u *)strchr((char *)name, '_'))
+ *end = ' ';
+#endif
+ /*
+ * Parse font names as Family/Style/Size.
+ * On errors, just keep the be_fixed_font.
+ */
+ end = (char_u *)strchr((char *)name, '/');
+ if (!end)
+ goto error;
+ strncpy(family, (char *)name, len = end - name);
+ family[len] = '\0';
+
+ name = end + 1;
+ end = (char_u *)strchr((char *)name, '/');
+ if (!end)
+ goto error;
+ strncpy(style, (char *)name, len = end - name);
+ style[len] = '\0';
+
+ name = end + 1;
+ size = atoi((char *)name);
+ if (size <= 0)
+ goto error;
+
+ font->SetFamilyAndStyle(family, style);
+ font->SetSize(size);
+ font->SetSpacing(B_FIXED_SPACING);
+ font->SetEncoding(B_ISO_8859_1);
+ //font->PrintToStream();
+
+ return (GuiFont)font;
+
+error:
+ if (giveErrorIfMissing)
+ EMSG2("(fe0) Unknown font: %s", name);
+
+ return (GuiFont)font;
+}
+
+/*
+ * Set the current text font.
+ */
+ void
+gui_mch_set_font(
+ GuiFont font)
+{
+ if (gui.vimWindow->Lock()) {
+ VimFont *vf = (VimFont *)font;
+
+ gui.vimTextArea->SetFont(vf);
+
+ gui.char_width = (int) vf->StringWidth("n");
+ font_height fh;
+ vf->GetHeight(&fh);
+ gui.char_height = (int)(fh.ascent + 0.9999)
+ + (int)(fh.descent + 0.9999) + (int)(fh.leading + 0.9999);
+ gui.char_ascent = (int)(fh.ascent + 0.9999);
+
+ gui.vimWindow->Unlock();
+ }
+}
+
+#if 0 /* not used */
+/*
+ * Return TRUE if the two fonts given are equivalent.
+ */
+ int
+gui_mch_same_font(
+ GuiFont f1,
+ GuiFont f2)
+{
+ VimFont *vf1 = (VimFont *)f1;
+ VimFont *vf2 = (VimFont *)f2;
+
+ return f1 == f2 ||
+ (vf1->FamilyAndStyle() == vf2->FamilyAndStyle() &&
+ vf1->Size() == vf2->Size());
+}
+#endif
+
+/* XXX TODO This is apparently never called... */
+ void
+gui_mch_free_font(
+ GuiFont font)
+{
+ VimFont *f = (VimFont *)font;
+ if (--f->refcount <= 0) {
+ if (f->refcount < 0)
+ fprintf(stderr, "VimFont: refcount < 0\n");
+ delete f;
+ }
+}
+
+ static int
+hex_digit(int c)
+{
+ if (isdigit(c))
+ return c - '0';
+ c = TOLOWER_ASC(c);
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return -1000;
+}
+
+/*
+ * This function has been lifted from gui_w32.c and extended a bit.
+ *
+ * Return the Pixel value (color) for the given color name.
+ * Return INVALCOLOR for error.
+ */
+ guicolor_T
+gui_mch_get_color(
+ char_u *name)
+{
+ typedef struct GuiColourTable
+ {
+ char *name;
+ guicolor_T colour;
+ } GuiColourTable;
+
+#define NSTATIC_COLOURS 32
+#define NDYNAMIC_COLOURS 33
+#define NCOLOURS (NSTATIC_COLOURS + NDYNAMIC_COLOURS)
+
+ static GuiColourTable table[NCOLOURS] =
+ {
+ {"Black", RGB(0x00, 0x00, 0x00)},
+ {"DarkGray", RGB(0x80, 0x80, 0x80)},
+ {"DarkGrey", RGB(0x80, 0x80, 0x80)},
+ {"Gray", RGB(0xC0, 0xC0, 0xC0)},
+ {"Grey", RGB(0xC0, 0xC0, 0xC0)},
+ {"LightGray", RGB(0xD3, 0xD3, 0xD3)},
+ {"LightGrey", RGB(0xD3, 0xD3, 0xD3)},
+ {"White", RGB(0xFF, 0xFF, 0xFF)},
+ {"DarkRed", RGB(0x80, 0x00, 0x00)},
+ {"Red", RGB(0xFF, 0x00, 0x00)},
+ {"LightRed", RGB(0xFF, 0xA0, 0xA0)},
+ {"DarkBlue", RGB(0x00, 0x00, 0x80)},
+ {"Blue", RGB(0x00, 0x00, 0xFF)},
+ {"LightBlue", RGB(0xA0, 0xA0, 0xFF)},
+ {"DarkGreen", RGB(0x00, 0x80, 0x00)},
+ {"Green", RGB(0x00, 0xFF, 0x00)},
+ {"LightGreen", RGB(0xA0, 0xFF, 0xA0)},
+ {"DarkCyan", RGB(0x00, 0x80, 0x80)},
+ {"Cyan", RGB(0x00, 0xFF, 0xFF)},
+ {"LightCyan", RGB(0xA0, 0xFF, 0xFF)},
+ {"DarkMagenta", RGB(0x80, 0x00, 0x80)},
+ {"Magenta", RGB(0xFF, 0x00, 0xFF)},
+ {"LightMagenta", RGB(0xFF, 0xA0, 0xFF)},
+ {"Brown", RGB(0x80, 0x40, 0x40)},
+ {"Yellow", RGB(0xFF, 0xFF, 0x00)},
+ {"LightYellow", RGB(0xFF, 0xFF, 0xA0)},
+ {"DarkYellow", RGB(0xBB, 0xBB, 0x00)},
+ {"SeaGreen", RGB(0x2E, 0x8B, 0x57)},
+ {"Orange", RGB(0xFF, 0xA5, 0x00)},
+ {"Purple", RGB(0xA0, 0x20, 0xF0)},
+ {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)},
+ {"Violet", RGB(0xEE, 0x82, 0xEE)},
+ };
+
+ static int endColour = NSTATIC_COLOURS;
+ static int newColour = NSTATIC_COLOURS;
+
+ int r, g, b;
+ int i;
+
+ if (name[0] == '#' && STRLEN(name) == 7)
+ {
+ /* Name is in "#rrggbb" format */
+ r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
+ g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
+ b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
+ if (r < 0 || g < 0 || b < 0)
+ return INVALCOLOR;
+ return RGB(r, g, b);
+ }
+ else
+ {
+ /* Check if the name is one of the colours we know */
+ for (i = 0; i < endColour; i++)
+ if (STRICMP(name, table[i].name) == 0)
+ return table[i].colour;
+ }
+
+ /*
+ * Last attempt. Look in the file "$VIM/rgb.txt".
+ */
+ {
+#define LINE_LEN 100
+ FILE *fd;
+ char line[LINE_LEN];
+ char_u *fname;
+
+ fname = expand_env_save((char_u *)"$VIM/rgb.txt");
+ if (fname == NULL)
+ return INVALCOLOR;
+
+ fd = fopen((char *)fname, "rt");
+ vim_free(fname);
+ if (fd == NULL)
+ return INVALCOLOR;
+
+ while (!feof(fd))
+ {
+ int len;
+ int pos;
+ char *colour;
+
+ fgets(line, LINE_LEN, fd);
+ len = strlen(line);
+
+ if (len <= 1 || line[len-1] != '\n')
+ continue;
+
+ line[len-1] = '\0';
+
+ i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
+ if (i != 3)
+ continue;
+
+ colour = line + pos;
+
+ if (STRICMP(colour, name) == 0)
+ {
+ fclose(fd);
+ /*
+ * Now remember this colour in the table.
+ * A LRU scheme might be better but this is simpler.
+ * Or could use a growing array.
+ */
+ guicolor_T gcolour = RGB(r,g,b);
+
+ vim_free(table[newColour].name);
+ table[newColour].name = (char *)vim_strsave((char_u *)colour);
+ table[newColour].colour = gcolour;
+
+ newColour++;
+ if (newColour >= NCOLOURS)
+ newColour = NSTATIC_COLOURS;
+ if (endColour < NCOLOURS)
+ endColour = newColour;
+
+ return gcolour;
+ }
+ }
+
+ fclose(fd);
+ }
+
+ return INVALCOLOR;
+}
+
+/*
+ * Set the current text foreground color.
+ */
+ void
+gui_mch_set_fg_color(
+ guicolor_T color)
+{
+ rgb_color rgb = GUI_TO_RGB(color);
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->SetHighColor(rgb);
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Set the current text background color.
+ */
+ void
+gui_mch_set_bg_color(
+ guicolor_T color)
+{
+ rgb_color rgb = GUI_TO_RGB(color);
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->SetLowColor(rgb);
+ gui.vimWindow->Unlock();
+ }
+}
+
+ void
+gui_mch_draw_string(
+ int row,
+ int col,
+ char_u *s,
+ int len,
+ int flags)
+{
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->mchDrawString(row, col, s, len, flags);
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Return OK if the key with the termcap name "name" is supported.
+ */
+ int
+gui_mch_haskey(
+ char_u *name)
+{
+ int i;
+
+ for (i = 0; special_keys[i].BeKeys != 0; i++)
+ if (name[0] == special_keys[i].vim_code0 &&
+ name[1] == special_keys[i].vim_code1)
+ return OK;
+ return FAIL;
+}
+
+ void
+gui_mch_beep()
+{
+ ::beep();
+}
+
+ void
+gui_mch_flash(int msec)
+{
+ /* Do a visual beep by reversing the foreground and background colors */
+
+ if (gui.vimWindow->Lock()) {
+ BRect rect = gui.vimTextArea->Bounds();
+
+ gui.vimTextArea->SetDrawingMode(B_OP_INVERT);
+ gui.vimTextArea->FillRect(rect);
+ gui.vimTextArea->Sync();
+ snooze(msec * 1000); /* wait for a few msec */
+ gui.vimTextArea->FillRect(rect);
+ gui.vimTextArea->SetDrawingMode(B_OP_COPY);
+ gui.vimTextArea->Flush();
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Invert a rectangle from row r, column c, for nr rows and nc columns.
+ */
+ void
+gui_mch_invert_rectangle(
+ int r,
+ int c,
+ int nr,
+ int nc)
+{
+ BRect rect;
+ rect.left = FILL_X(c);
+ rect.top = FILL_Y(r);
+ rect.right = rect.left + nc * gui.char_width - PEN_WIDTH;
+ rect.bottom = rect.top + nr * gui.char_height - PEN_WIDTH;
+
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->SetDrawingMode(B_OP_INVERT);
+ gui.vimTextArea->FillRect(rect);
+ gui.vimTextArea->SetDrawingMode(B_OP_COPY);
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Iconify the GUI window.
+ */
+ void
+gui_mch_iconify()
+{
+ if (gui.vimWindow->Lock()) {
+ gui.vimWindow->Minimize(true);
+ gui.vimWindow->Unlock();
+ }
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Bring the Vim window to the foreground.
+ */
+ void
+gui_mch_set_foreground()
+{
+ /* TODO */
+}
+#endif
+
+/*
+ * Set the window title
+ */
+ void
+gui_mch_settitle(
+ char_u *title,
+ char_u *icon)
+{
+ if (gui.vimWindow->Lock()) {
+ gui.vimWindow->SetTitle((char *)title);
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Draw a cursor without focus.
+ */
+ void
+gui_mch_draw_hollow_cursor(guicolor_T color)
+{
+ gui_mch_set_fg_color(color);
+
+ BRect r;
+ r.left = FILL_X(gui.col);
+ r.top = FILL_Y(gui.row);
+ r.right = r.left + gui.char_width - PEN_WIDTH;
+ r.bottom = r.top + gui.char_height - PEN_WIDTH;
+
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->StrokeRect(r);
+ gui.vimWindow->Unlock();
+ //gui_mch_flush();
+ }
+}
+
+/*
+ * Draw part of a cursor, only w pixels wide, and h pixels high.
+ */
+ void
+gui_mch_draw_part_cursor(
+ int w,
+ int h,
+ guicolor_T color)
+{
+ gui_mch_set_fg_color(color);
+
+ BRect r;
+ r.left =
+#ifdef FEAT_RIGHTLEFT
+ /* vertical line should be on the right of current point */
+ CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
+#endif
+ FILL_X(gui.col);
+ r.right = r.left + w - PEN_WIDTH;
+ r.bottom = FILL_Y(gui.row + 1) - PEN_WIDTH;
+ r.top = r.bottom - h + PEN_WIDTH;
+
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->FillRect(r);
+ gui.vimWindow->Unlock();
+ //gui_mch_flush();
+ }
+}
+
+/*
+ * Catch up with any queued events. This may put keyboard input into the
+ * input buffer, call resize call-backs, trigger timers etc. If there is
+ * nothing in the event queue (& no timers pending), then we return
+ * immediately.
+ */
+ void
+gui_mch_update()
+{
+ gui_mch_flush();
+ while (port_count(gui.vdcmp) > 0 &&
+ !vim_is_input_buf_full() &&
+ gui_beos_process_event(0) >= B_OK)
+ /* nothing */ ;
+}
+
+/*
+ * GUI input routine called by gui_wait_for_chars(). Waits for a character
+ * from the keyboard.
+ * wtime == -1 Wait forever.
+ * wtime == 0 This should never happen.
+ * wtime > 0 Wait wtime milliseconds for a character.
+ * Returns OK if a character was found to be available within the given time,
+ * or FAIL otherwise.
+ */
+ int
+gui_mch_wait_for_chars(
+ int wtime)
+{
+ int focus;
+ bigtime_t until, timeout;
+ status_t st;
+
+ if (wtime >= 0) {
+ timeout = wtime * 1000;
+ until = system_time() + timeout;
+ } else {
+ timeout = B_INFINITE_TIMEOUT;
+ }
+
+ focus = gui.in_focus;
+ for (;;)
+ {
+ /* Stop or start blinking when focus changes */
+ if (gui.in_focus != focus)
+ {
+ if (gui.in_focus)
+ gui_mch_start_blink();
+ else
+ gui_mch_stop_blink();
+ focus = gui.in_focus;
+ }
+
+ gui_mch_flush();
+ /*
+ * Don't use gui_mch_update() because then we will spin-lock until a
+ * char arrives, instead we use gui_beos_process_event() to hang until
+ * an event arrives. No need to check for input_buf_full because we
+ * are returning as soon as it contains a single char.
+ */
+ st = gui_beos_process_event(timeout);
+
+ if (input_available())
+ return OK;
+ if (st < B_OK) /* includes B_TIMED_OUT */
+ return FAIL;
+
+ /*
+ * Calculate how much longer we're willing to wait for the
+ * next event.
+ */
+ if (wtime >= 0) {
+ timeout = until - system_time();
+ if (timeout < 0)
+ break;
+ }
+ }
+ return FAIL;
+
+}
+
+/*
+ * Output routines.
+ */
+
+/*
+ * Flush any output to the screen. This is typically called before
+ * the app goes to sleep.
+ */
+ void
+gui_mch_flush()
+{
+ // does this need to lock the window? Apparently not but be safe.
+ if (gui.vimWindow->Lock()) {
+ gui.vimWindow->Flush();
+ gui.vimWindow->Unlock();
+ }
+ return;
+}
+
+/*
+ * Clear a rectangular region of the screen from text pos (row1, col1) to
+ * (row2, col2) inclusive.
+ */
+ void
+gui_mch_clear_block(
+ int row1,
+ int col1,
+ int row2,
+ int col2)
+{
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->mchClearBlock(row1, col1, row2, col2);
+ gui.vimWindow->Unlock();
+ }
+}
+
+ void
+gui_mch_clear_all()
+{
+ if (gui.vimWindow->Lock()) {
+ gui.vimTextArea->mchClearAll();
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Delete the given number of lines from the given row, scrolling up any
+ * text further down within the scroll region.
+ */
+ void
+gui_mch_delete_lines(
+ int row,
+ int num_lines)
+{
+ gui.vimTextArea->mchDeleteLines(row, num_lines);
+}
+
+/*
+ * Insert the given number of lines before the given row, scrolling down any
+ * following text within the scroll region.
+ */
+ void
+gui_mch_insert_lines(
+ int row,
+ int num_lines)
+{
+ gui.vimTextArea->mchInsertLines(row, num_lines);
+}
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Menu stuff.
+ */
+
+ void
+gui_mch_enable_menu(
+ int flag)
+{
+ if (gui.vimWindow->Lock())
+ {
+ BMenuBar *menubar = gui.vimForm->MenuBar();
+ menubar->SetEnabled(flag);
+ gui.vimWindow->Unlock();
+ }
+}
+
+ void
+gui_mch_set_menu_pos(
+ int x,
+ int y,
+ int w,
+ int h)
+{
+ /* It will be in the right place anyway */
+}
+
+/*
+ * Add a sub menu to the menu bar.
+ */
+ void
+gui_mch_add_menu(
+ vimmenu_T *menu,
+ int idx)
+{
+ vimmenu_T *parent = menu->parent;
+
+ if (!menu_is_menubar(menu->name)
+ || (parent != NULL && parent->submenu_id == NULL))
+ return;
+
+ if (gui.vimWindow->Lock())
+ {
+/* Major re-write of the menu code, it was failing with memory corruption when
+ * we started loading multiple files (the Buffer menu)
+ *
+ * Note we don't use the preference values yet, all are inserted into the
+ * menubar on a first come-first served basis...
+ *
+ * richard@whitequeen.com jul 99
+ */
+
+ BMenu *tmp;
+
+ if ( parent )
+ tmp = parent->submenu_id;
+ else
+ tmp = gui.vimForm->MenuBar();
+// make sure we don't try and add the same menu twice. The Buffers menu tries to
+// do this and Be starts to crash...
+
+ if ( ! tmp->FindItem((const char *) menu->dname)) {
+
+ BMenu *bmenu = new BMenu((char *)menu->dname);
+
+ menu->submenu_id = bmenu;
+
+// when we add a BMenu to another Menu, it creates the interconnecting BMenuItem
+ tmp->AddItem(bmenu);
+
+// Now its safe to query the menu for the associated MenuItem....
+ menu->id = tmp->FindItem((const char *) menu->dname);
+
+ }
+ gui.vimWindow->Unlock();
+ }
+}
+
+ void
+gui_mch_toggle_tearoffs(int enable)
+{
+ /* no tearoff menus */
+}
+
+ static BMessage *
+MenuMessage(vimmenu_T *menu)
+{
+ BMessage *m = new BMessage('menu');
+ m->AddPointer("VimMenu", (void *)menu);
+
+ return m;
+}
+
+/*
+ * Add a menu item to a menu
+ */
+ void
+gui_mch_add_menu_item(
+ vimmenu_T *menu,
+ int idx)
+{
+ int mnemonic = 0;
+ vimmenu_T *parent = menu->parent;
+
+ if (parent->submenu_id == NULL)
+ return;
+
+#ifdef never
+ /* why not add separators ?
+ * richard
+ */
+ /* Don't add menu separator */
+ if (menu_is_separator(menu->name))
+ return;
+#endif
+
+ /* TODO: use menu->actext */
+ /* This is difficult, since on Be, an accelerator must be a single char
+ * and a lot of Vim ones are the standard VI commands.
+ *
+ * Punt for Now...
+ * richard@whiequeen.com jul 99
+ */
+ if (gui.vimWindow->Lock())
+ {
+ if ( menu_is_separator(menu->name)) {
+ BSeparatorItem *item = new BSeparatorItem();
+ parent->submenu_id->AddItem(item);
+ menu->id = item;
+ menu->submenu_id = NULL;
+ }
+ else {
+ BMenuItem *item = new BMenuItem((char *)menu->dname,
+ MenuMessage(menu));
+ item->SetTarget(gui.vimTextArea);
+ item->SetTrigger((char) menu->mnemonic);
+ parent->submenu_id->AddItem(item);
+ menu->id = item;
+ menu->submenu_id = NULL;
+ }
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Destroy the machine specific menu widget.
+ */
+ void
+gui_mch_destroy_menu(
+ vimmenu_T *menu)
+{
+ if (gui.vimWindow->Lock())
+ {
+ assert(menu->submenu_id == NULL || menu->submenu_id->CountItems() == 0);
+ /*
+ * Detach this menu from its parent, so that it is not deleted
+ * twice once we get to delete that parent.
+ * Deleting a BMenuItem also deletes the associated BMenu, if any
+ * (which does not have any items anymore since they were
+ * removed and deleted before).
+ */
+ BMenu *bmenu = menu->id->Menu();
+ if (bmenu)
+ {
+ bmenu->RemoveItem(menu->id);
+ /*
+ * If we removed the last item from the menu bar,
+ * resize it out of sight.
+ */
+ if (bmenu == gui.vimForm->MenuBar() && bmenu->CountItems() == 0)
+ {
+ bmenu->ResizeTo(-MENUBAR_MARGIN, -MENUBAR_MARGIN);
+ }
+ }
+ delete menu->id;
+ menu->id = NULL;
+ menu->submenu_id = NULL;
+
+ gui.menu_height = (int) gui.vimForm->MenuHeight();
+ gui.vimWindow->Unlock();
+ }
+}
+
+/*
+ * Make a menu either grey or not grey.
+ */
+ void
+gui_mch_menu_grey(
+ vimmenu_T *menu,
+ int grey)
+{
+ if (menu->id != NULL)
+ menu->id->SetEnabled(!grey);
+}
+
+/*
+ * Make menu item hidden or not hidden
+ */
+ void
+gui_mch_menu_hidden(
+ vimmenu_T *menu,
+ int hidden)
+{
+ if (menu->id != NULL)
+ menu->id->SetEnabled(!hidden);
+}
+
+/*
+ * This is called after setting all the menus to grey/hidden or not.
+ */
+ void
+gui_mch_draw_menubar()
+{
+ /* Nothing to do in BeOS */
+}
+
+#endif /* FEAT_MENU */
+
+/* Mouse stuff */
+
+#ifdef FEAT_CLIPBOARD
+/*
+ * Clipboard stuff, for cutting and pasting text to other windows.
+ */
+char textplain[] = "text/plain";
+char vimselectiontype[] = "application/x-vnd.Rhialto-Vim-selectiontype";
+
+/*
+ * Get the current selection and put it in the clipboard register.
+ */
+ void
+clip_mch_request_selection(VimClipboard *cbd)
+{
+ if (be_clipboard->Lock())
+ {
+ BMessage *m = be_clipboard->Data();
+ //m->PrintToStream();
+
+ char_u *string = NULL;
+ ssize_t stringlen = -1;
+
+ if (m->FindData(textplain, B_MIME_TYPE,
+ (const void **)&string, &stringlen) == B_OK
+ || m->FindString("text", (const char **)&string) == B_OK)
+ {
+ if (stringlen == -1)
+ stringlen = STRLEN(string);
+
+ int type;
+ char *seltype;
+ ssize_t seltypelen;
+
+ /*
+ * Try to get the special vim selection type first
+ */
+ if (m->FindData(vimselectiontype, B_MIME_TYPE,
+ (const void **)&seltype, &seltypelen) == B_OK)
+ {
+ switch (*seltype)
+ {
+ default:
+ case 'L': type = MLINE; break;
+ case 'C': type = MCHAR; break;
+#ifdef FEAT_VISUAL
+ case 'B': type = MBLOCK; break;
+#endif
+ }
+ }
+ else
+ {
+ /* Otherwise use heuristic as documented */
+ type = memchr(string, stringlen, '\n') ? MLINE : MCHAR;
+ }
+ clip_yank_selection(type, string, (long)stringlen, cbd);
+ }
+ be_clipboard->Unlock();
+ }
+}
+/*
+ * Make vim the owner of the current selection.
+ */
+ void
+clip_mch_lose_selection(VimClipboard *cbd)
+{
+ /* Nothing needs to be done here */
+}
+
+/*
+ * Make vim the owner of the current selection. Return OK upon success.
+ */
+ int
+clip_mch_own_selection(VimClipboard *cbd)
+{
+ /*
+ * Never actually own the clipboard. If another application sets the
+ * clipboard, we don't want to think that we still own it.
+ */
+ return FAIL;
+}
+
+/*
+ * Send the current selection to the clipboard.
+ */
+ void
+clip_mch_set_selection(VimClipboard *cbd)
+{
+ if (be_clipboard->Lock())
+ {
+ be_clipboard->Clear();
+ BMessage *m = be_clipboard->Data();
+ assert(m);
+
+ /* If the '*' register isn't already filled in, fill it in now */
+ cbd->owned = TRUE;
+ clip_get_selection(cbd);
+ cbd->owned = FALSE;
+
+ char_u *str = NULL;
+ long_u count;
+ int type;
+
+ type = clip_convert_selection(&str, &count, cbd);
+
+ if (type < 0)
+ return;
+
+ m->AddData(textplain, B_MIME_TYPE, (void *)str, count);
+
+ /* Add type of selection */
+ char vtype;
+ switch (type)
+ {
+ default:
+ case MLINE: vtype = 'L'; break;
+ case MCHAR: vtype = 'C'; break;
+#ifdef FEAT_VISUAL
+ case MBLOCK: vtype = 'B'; break;
+#endif
+ }
+ m->AddData(vimselectiontype, B_MIME_TYPE, (void *)&vtype, 1);
+
+ vim_free(str);
+
+ be_clipboard->Commit();
+ be_clipboard->Unlock();
+ }
+}
+
+#endif /* FEAT_CLIPBOARD */
+
+/*
+ * Return the RGB value of a pixel as long.
+ */
+ long_u
+gui_mch_get_rgb(guicolor_T pixel)
+{
+ rgb_color rgb = GUI_TO_RGB(pixel);
+
+ return ((rgb.red & 0xff) << 16) + ((rgb.green & 0xff) << 8)
+ + (rgb.blue & 0xff);
+}
+
+ void
+gui_mch_setmouse(int x, int y)
+{
+ TRACE();
+ /* TODO */
+}
+
+ void
+gui_mch_show_popupmenu(vimmenu_T *menu)
+{
+ TRACE();
+ /* TODO */
+}
+
+int
+gui_mch_get_mouse_x()
+{
+ TRACE();
+ return 0;
+}
+
+
+int
+gui_mch_get_mouse_y()
+{
+ TRACE();
+ return 0;
+}
+
+} /* extern "C" */
diff --git a/src/gui_beos.h b/src/gui_beos.h
new file mode 100644
index 000000000..b2fc45854
--- /dev/null
+++ b/src/gui_beos.h
@@ -0,0 +1,49 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI support by Olaf "Rhialto" Seibert
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ *
+ * BeOS GUI.
+ *
+ * GUI support for the Buzzword Enhanced Operating System for PPC.
+ *
+ */
+
+/*
+ * This file must be acceptable both as C and C++.
+ * The BeOS API is defined in terms of C++, but some classes
+ * should be somewhat known in the common C code.
+ */
+
+/* System classes */
+
+struct BMenu;
+struct BMenuItem;
+
+/* Our own Vim-related classes */
+
+struct VimApp;
+struct VimFormView;
+struct VimTextAreaView;
+struct VimWindow;
+struct VimScrollBar;
+
+/* Locking functions */
+
+extern int vim_lock_screen();
+extern void vim_unlock_screen();
+
+#ifndef __cplusplus
+
+typedef struct BMenu BMenu;
+typedef struct BMenuItem BMenuItem;
+typedef struct VimWindow VimWindow;
+typedef struct VimFormView VimFormView;
+typedef struct VimTextAreaView VimTextAreaView;
+typedef struct VimApp VimApp;
+typedef struct VimScrollBar VimScrollBar;
+
+#endif
diff --git a/src/gui_beval.c b/src/gui_beval.c
new file mode 100644
index 000000000..f19c1e017
--- /dev/null
+++ b/src/gui_beval.c
@@ -0,0 +1,1268 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Visual Workshop integration by Gordon Prieur
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_BEVAL) || defined(PROTO)
+
+/* on Win32 only gui_mch_get_beval_info is required */
+#if !defined(FEAT_GUI_W32) || defined(PROTO)
+
+#ifdef FEAT_GUI_GTK
+# include <gdk/gdkkeysyms.h>
+# include <gtk/gtk.h>
+#else
+# include <X11/keysym.h>
+# ifdef FEAT_GUI_MOTIF
+# include <Xm/PushB.h>
+# include <Xm/Separator.h>
+# include <Xm/List.h>
+# include <Xm/Label.h>
+# include <Xm/AtomMgr.h>
+# include <Xm/Protocols.h>
+# else
+ /* Assume Athena */
+# include <X11/Shell.h>
+# include <X11/Xaw/Label.h>
+# endif
+#endif
+
+#include "gui_beval.h"
+
+#ifndef FEAT_GUI_GTK
+extern Widget vimShell;
+
+/*
+ * Currently, we assume that there can be only one BalloonEval showing
+ * on-screen at any given moment. This variable will hold the currently
+ * showing BalloonEval or NULL if none is showing.
+ */
+static BalloonEval *current_beval = NULL;
+#endif
+
+#ifdef FEAT_GUI_GTK
+static void addEventHandler __ARGS((GtkWidget *, BalloonEval *));
+static void removeEventHandler __ARGS((BalloonEval *));
+static gint target_event_cb __ARGS((GtkWidget *, GdkEvent *, gpointer));
+static gint mainwin_event_cb __ARGS((GtkWidget *, GdkEvent *, gpointer));
+static void pointer_event __ARGS((BalloonEval *, int, int, unsigned));
+static void key_event __ARGS((BalloonEval *, unsigned, int));
+static gint timeout_cb __ARGS((gpointer));
+static gint balloon_expose_event_cb __ARGS((GtkWidget *, GdkEventExpose *, gpointer));
+# ifndef HAVE_GTK2
+static void balloon_draw_cb __ARGS((GtkWidget *, GdkRectangle *, gpointer));
+# endif
+#else
+static void addEventHandler __ARGS((Widget, BalloonEval *));
+static void removeEventHandler __ARGS((BalloonEval *));
+static void pointerEventEH __ARGS((Widget, XtPointer, XEvent *, Boolean *));
+static void pointerEvent __ARGS((BalloonEval *, XEvent *));
+static void timerRoutine __ARGS((XtPointer, XtIntervalId *));
+#endif
+static void cancelBalloon __ARGS((BalloonEval *));
+static void requestBalloon __ARGS((BalloonEval *));
+static void drawBalloon __ARGS((BalloonEval *));
+static void undrawBalloon __ARGS((BalloonEval *beval));
+static void createBalloonEvalWindow __ARGS((BalloonEval *));
+
+
+
+/*
+ * Create a balloon-evaluation area for a Widget.
+ * There can be either a "mesg" for a fixed string or "mesgCB" to generate a
+ * message by calling this callback function.
+ * When "mesg" is not NULL it must remain valid for as long as the balloon is
+ * used. It is not freed here.
+ * Returns a pointer to the resulting object (NULL when out of memory).
+ */
+ BalloonEval *
+gui_mch_create_beval_area(target, mesg, mesgCB, clientData)
+ void *target;
+ char_u *mesg;
+ void (*mesgCB)__ARGS((BalloonEval *, int));
+ void *clientData;
+{
+#ifndef FEAT_GUI_GTK
+ char *display_name; /* get from gui.dpy */
+ int screen_num;
+ char *p;
+#endif
+ BalloonEval *beval;
+
+ if (mesg != NULL && mesgCB != NULL)
+ {
+ EMSG(_("E232: Cannot create BalloonEval with both message and callback"));
+ return NULL;
+ }
+
+ beval = (BalloonEval *)alloc(sizeof(BalloonEval));
+ if (beval != NULL)
+ {
+#ifdef FEAT_GUI_GTK
+ beval->target = GTK_WIDGET(target);
+ beval->balloonShell = NULL;
+ beval->timerID = 0;
+#else
+ beval->target = (Widget)target;
+ beval->balloonShell = NULL;
+ beval->timerID = (XtIntervalId)NULL;
+ beval->appContext = XtWidgetToApplicationContext((Widget)target);
+#endif
+ beval->showState = ShS_NEUTRAL;
+ beval->x = 0;
+ beval->y = 0;
+ beval->msg = mesg;
+ beval->msgCB = mesgCB;
+ beval->clientData = clientData;
+
+ /*
+ * Set up event handler which will keep its eyes on the pointer,
+ * and when the pointer rests in a certain spot for a given time
+ * interval, show the beval.
+ */
+ addEventHandler(beval->target, beval);
+ createBalloonEvalWindow(beval);
+
+#ifndef FEAT_GUI_GTK
+ /*
+ * Now create and save the screen width and height. Used in drawing.
+ */
+ display_name = DisplayString(gui.dpy);
+ p = strrchr(display_name, '.');
+ if (p != NULL)
+ screen_num = atoi(++p);
+ else
+ screen_num = 0;
+ beval->screen_width = DisplayWidth(gui.dpy, screen_num);
+ beval->screen_height = DisplayHeight(gui.dpy, screen_num);
+#endif
+ }
+
+ return beval;
+}
+
+#if defined(FEAT_BEVAL_TIP) || defined(PROTO)
+/*
+ * Destroy a ballon-eval and free its associated memory.
+ */
+ void
+gui_mch_destroy_beval_area(beval)
+ BalloonEval *beval;
+{
+ cancelBalloon(beval);
+ removeEventHandler(beval);
+ /* Children will automatically be destroyed */
+# ifdef FEAT_GUI_GTK
+ gtk_widget_destroy(beval->balloonShell);
+# else
+ XtDestroyWidget(beval->balloonShell);
+# endif
+ vim_free(beval);
+}
+#endif
+
+ void
+gui_mch_enable_beval_area(beval)
+ BalloonEval *beval;
+{
+ if (beval != NULL)
+ addEventHandler(beval->target, beval);
+}
+
+ void
+gui_mch_disable_beval_area(beval)
+ BalloonEval *beval;
+{
+ if (beval != NULL)
+ removeEventHandler(beval);
+}
+
+#if defined(FEAT_BEVAL_TIP) || defined(PROTO)
+/*
+ * This function returns the BalloonEval * associated with the currently
+ * displayed tooltip. Returns NULL if there is no tooltip currently showing.
+ *
+ * Assumption: Only one tooltip can be shown at a time.
+ */
+ BalloonEval *
+gui_mch_currently_showing_beval()
+{
+ return current_beval;
+}
+#endif
+#endif /* !FEAT_GUI_W32 */
+
+#if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) || defined(PROTO)
+/*
+ * Get the text and position to be evaluated for "beval".
+ * When "usingNetbeans" is set the returned text is in allocated memory.
+ * Returns OK or FAIL.
+ */
+ int
+gui_mch_get_beval_info(beval, filename, line, text, idx)
+ BalloonEval *beval;
+ char_u **filename;
+ int *line;
+ char_u **text;
+ int *idx;
+{
+ win_T *wp;
+ int row, col;
+ char_u *lbuf;
+ linenr_T lnum;
+
+ *text = NULL;
+ row = Y_2_ROW(beval->y);
+ col = X_2_COL(beval->x);
+ wp = mouse_find_win(&row, &col);
+ if (wp != NULL && row < wp->w_height && col < W_WIDTH(wp))
+ {
+ /* Found a window and the cursor is in the text. Now find the line
+ * number. */
+ if (!mouse_comp_pos(wp, &row, &col, &lnum))
+ {
+ /* Not past end of the file. */
+ lbuf = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ if (col <= win_linetabsize(wp, lbuf, (colnr_T)MAXCOL))
+ {
+ /* Not past end of line. */
+# ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ {
+ /* For Netbeans we get the relevant part of the line
+ * instead of the whole line. */
+ int len;
+ pos_T *spos = NULL, *epos = NULL;
+
+ if (VIsual_active)
+ {
+ if (lt(VIsual, curwin->w_cursor))
+ {
+ spos = &VIsual;
+ epos = &curwin->w_cursor;
+ }
+ else
+ {
+ spos = &curwin->w_cursor;
+ epos = &VIsual;
+ }
+ }
+
+ col = vcol2col(wp, lnum, col) - 1;
+
+ if (VIsual_active
+ && wp->w_buffer == curwin->w_buffer
+ && (lnum == spos->lnum
+ ? col >= (int)spos->col
+ : lnum > spos->lnum)
+ && (lnum == epos->lnum
+ ? col <= (int)epos->col
+ : lnum < epos->lnum))
+ {
+ /* Visual mode and pointing to the line with the
+ * Visual selection: return selected text, with a
+ * maximum of one line. */
+ if (spos->lnum != epos->lnum || spos->col == epos->col)
+ return FAIL;
+
+ lbuf = ml_get_buf(curwin->w_buffer, VIsual.lnum, FALSE);
+ lbuf = vim_strnsave(lbuf + spos->col,
+ epos->col - spos->col + (*p_sel != 'e'));
+ lnum = spos->lnum;
+ col = spos->col;
+ }
+ else
+ {
+ /* Find the word under the cursor. */
+ ++emsg_off;
+ len = find_ident_at_pos(wp, lnum, (colnr_T)col, &lbuf,
+ FIND_IDENT + FIND_STRING + FIND_EVAL);
+ --emsg_off;
+ if (len == 0)
+ return FAIL;
+ lbuf = vim_strnsave(lbuf, len);
+ }
+ }
+# endif
+ *filename = wp->w_buffer->b_ffname;
+ *line = (int)lnum;
+ *text = lbuf;
+ *idx = col;
+ beval->ts = wp->w_buffer->b_p_ts;
+ return OK;
+ }
+ }
+ }
+
+ return FAIL;
+}
+
+# if !defined(FEAT_GUI_W32) || defined(PROTO)
+
+/*
+ * Show a balloon with "mesg".
+ */
+ void
+gui_mch_post_balloon(beval, mesg)
+ BalloonEval *beval;
+ char_u *mesg;
+{
+ beval->msg = mesg;
+ if (mesg != NULL)
+ drawBalloon(beval);
+ else
+ undrawBalloon(beval);
+}
+# endif /* FEAT_GUI_W32 */
+#endif /* FEAT_SUN_WORKSHOP || FEAT_NETBEANS_INTG || PROTO */
+
+#if !defined(FEAT_GUI_W32) || defined(PROTO)
+#if defined(FEAT_BEVAL_TIP) || defined(PROTO)
+/*
+ * Hide the given balloon.
+ */
+ void
+gui_mch_unpost_balloon(beval)
+ BalloonEval *beval;
+{
+ undrawBalloon(beval);
+}
+#endif
+
+#ifdef FEAT_GUI_GTK
+/*
+ * We can unconditionally use ANSI-style prototypes here since
+ * GTK+ requires an ANSI C compiler anyway.
+ */
+ static void
+addEventHandler(GtkWidget *target, BalloonEval *beval)
+{
+ /*
+ * Connect to the generic "event" signal instead of the individual
+ * signals for each event type, because the former is emitted earlier.
+ * This allows us to catch events independently of the signal handlers
+ * in gui_gtk_x11.c.
+ */
+ /* Should use GTK_OBJECT() here, but that causes a lint warning... */
+ gtk_signal_connect((GtkObject*)(target), "event",
+ GTK_SIGNAL_FUNC(target_event_cb),
+ beval);
+ /*
+ * Nasty: Key press events go to the main window thus the drawing area
+ * will never see them. This means we have to connect to the main window
+ * as well in order to catch those events.
+ */
+ if (gtk_socket_id == 0 && gui.mainwin != NULL
+ && gtk_widget_is_ancestor(target, gui.mainwin))
+ {
+ gtk_signal_connect((GtkObject*)(gui.mainwin), "event",
+ GTK_SIGNAL_FUNC(mainwin_event_cb),
+ beval);
+ }
+}
+
+ static void
+removeEventHandler(BalloonEval *beval)
+{
+ gtk_signal_disconnect_by_func((GtkObject*)(beval->target),
+ GTK_SIGNAL_FUNC(target_event_cb),
+ beval);
+
+ if (gtk_socket_id == 0 && gui.mainwin != NULL
+ && gtk_widget_is_ancestor(beval->target, gui.mainwin))
+ {
+ gtk_signal_disconnect_by_func((GtkObject*)(gui.mainwin),
+ GTK_SIGNAL_FUNC(mainwin_event_cb),
+ beval);
+ }
+}
+
+ static gint
+target_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+ BalloonEval *beval = (BalloonEval *)data;
+
+ switch (event->type)
+ {
+ case GDK_ENTER_NOTIFY:
+ pointer_event(beval, (int)event->crossing.x,
+ (int)event->crossing.y,
+ event->crossing.state);
+ break;
+ case GDK_MOTION_NOTIFY:
+ if (event->motion.is_hint)
+ {
+ int x;
+ int y;
+ GdkModifierType state;
+ /*
+ * GDK_POINTER_MOTION_HINT_MASK is set, thus we cannot obtain
+ * the coordinates from the GdkEventMotion struct directly.
+ */
+ gdk_window_get_pointer(widget->window, &x, &y, &state);
+ pointer_event(beval, x, y, (unsigned int)state);
+ }
+ else
+ {
+ pointer_event(beval, (int)event->motion.x,
+ (int)event->motion.y,
+ event->motion.state);
+ }
+ break;
+ case GDK_LEAVE_NOTIFY:
+ /*
+ * Ignore LeaveNotify events that are not "normal".
+ * Apparently we also get it when somebody else grabs focus.
+ */
+ if (event->crossing.mode == GDK_CROSSING_NORMAL)
+ cancelBalloon(beval);
+ break;
+ case GDK_BUTTON_PRESS:
+# ifdef HAVE_GTK2
+ case GDK_SCROLL:
+# endif
+ cancelBalloon(beval);
+ break;
+ case GDK_KEY_PRESS:
+ key_event(beval, event->key.keyval, TRUE);
+ break;
+ case GDK_KEY_RELEASE:
+ key_event(beval, event->key.keyval, FALSE);
+ break;
+ default:
+ break;
+ }
+
+ return FALSE; /* continue emission */
+}
+
+/*ARGSUSED*/
+ static gint
+mainwin_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+ BalloonEval *beval = (BalloonEval *)data;
+
+ switch (event->type)
+ {
+ case GDK_KEY_PRESS:
+ key_event(beval, event->key.keyval, TRUE);
+ break;
+ case GDK_KEY_RELEASE:
+ key_event(beval, event->key.keyval, FALSE);
+ break;
+ default:
+ break;
+ }
+
+ return FALSE; /* continue emission */
+}
+
+ static void
+pointer_event(BalloonEval *beval, int x, int y, unsigned state)
+{
+ int distance;
+
+ distance = ABS(x - beval->x) + ABS(y - beval->y);
+
+ if (distance > 4)
+ {
+ /*
+ * Moved out of the balloon location: cancel it.
+ * Remember button state
+ */
+ beval->state = state;
+ cancelBalloon(beval);
+
+ /* Mouse buttons are pressed - no balloon now */
+ if (!(state & ((int)GDK_BUTTON1_MASK | (int)GDK_BUTTON2_MASK
+ | (int)GDK_BUTTON3_MASK)))
+ {
+ beval->x = x;
+ beval->y = y;
+
+ if (state & (int)GDK_MOD1_MASK)
+ {
+ /*
+ * Alt is pressed -- enter super-evaluate-mode,
+ * where there is no time delay
+ */
+ if (beval->msgCB != NULL)
+ {
+ beval->showState = ShS_PENDING;
+ (*beval->msgCB)(beval, state);
+ }
+ }
+ else
+ {
+ beval->timerID = gtk_timeout_add((guint32)p_bdlay,
+ &timeout_cb, beval);
+ }
+ }
+ }
+}
+
+ static void
+key_event(BalloonEval *beval, unsigned keyval, int is_keypress)
+{
+ if (beval->showState == ShS_SHOWING && beval->msgCB != NULL)
+ {
+ switch (keyval)
+ {
+ case GDK_Shift_L:
+ case GDK_Shift_R:
+ beval->showState = ShS_UPDATE_PENDING;
+ (*beval->msgCB)(beval, (is_keypress)
+ ? (int)GDK_SHIFT_MASK : 0);
+ break;
+ case GDK_Control_L:
+ case GDK_Control_R:
+ beval->showState = ShS_UPDATE_PENDING;
+ (*beval->msgCB)(beval, (is_keypress)
+ ? (int)GDK_CONTROL_MASK : 0);
+ break;
+ default:
+ cancelBalloon(beval);
+ break;
+ }
+ }
+ else
+ cancelBalloon(beval);
+}
+
+ static gint
+timeout_cb(gpointer data)
+{
+ BalloonEval *beval = (BalloonEval *)data;
+
+ beval->timerID = 0;
+ /*
+ * If the timer event happens then the mouse has stopped long enough for
+ * a request to be started. The request will only send to the debugger if
+ * there the mouse is pointing at real data.
+ */
+ requestBalloon(beval);
+
+ return FALSE; /* don't call me again */
+}
+
+/*ARGSUSED2*/
+ static gint
+balloon_expose_event_cb(GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+ gtk_paint_flat_box(widget->style, widget->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ &event->area, widget, "tooltip",
+ 0, 0, -1, -1);
+
+ return FALSE; /* continue emission */
+}
+
+# ifndef HAVE_GTK2
+/*ARGSUSED2*/
+ static void
+balloon_draw_cb(GtkWidget *widget, GdkRectangle *area, gpointer data)
+{
+ GtkWidget *child;
+ GdkRectangle child_area;
+
+ gtk_paint_flat_box(widget->style, widget->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ area, widget, "tooltip",
+ 0, 0, -1, -1);
+
+ child = GTK_BIN(widget)->child;
+
+ if (gtk_widget_intersect(child, area, &child_area))
+ gtk_widget_draw(child, &child_area);
+}
+# endif
+
+#else /* !FEAT_GUI_GTK */
+
+ static void
+addEventHandler(target, beval)
+ Widget target;
+ BalloonEval *beval;
+{
+ XtAddEventHandler(target,
+ PointerMotionMask | EnterWindowMask |
+ LeaveWindowMask | ButtonPressMask | KeyPressMask |
+ KeyReleaseMask,
+ False,
+ pointerEventEH, (XtPointer)beval);
+}
+
+ static void
+removeEventHandler(beval)
+ BalloonEval *beval;
+{
+ XtRemoveEventHandler(beval->target,
+ PointerMotionMask | EnterWindowMask |
+ LeaveWindowMask | ButtonPressMask | KeyPressMask |
+ KeyReleaseMask,
+ False,
+ pointerEventEH, (XtPointer)beval);
+}
+
+
+/*
+ * The X event handler. All it does is call the real event handler.
+ */
+/*ARGSUSED*/
+ static void
+pointerEventEH(w, client_data, event, unused)
+ Widget w;
+ XtPointer client_data;
+ XEvent *event;
+ Boolean *unused;
+{
+ BalloonEval *beval = (BalloonEval *)client_data;
+ pointerEvent(beval, event);
+}
+
+
+/*
+ * The real event handler. Called by pointerEventEH() whenever an event we are
+ * interested in ocurrs.
+ */
+
+ static void
+pointerEvent(beval, event)
+ BalloonEval *beval;
+ XEvent *event;
+{
+ Position distance; /* a measure of how much the ponter moved */
+ Position delta; /* used to compute distance */
+
+ switch (event->type)
+ {
+ case EnterNotify:
+ case MotionNotify:
+ delta = event->xmotion.x - beval->x;
+ if (delta < 0)
+ delta = -delta;
+ distance = delta;
+ delta = event->xmotion.y - beval->y;
+ if (delta < 0)
+ delta = -delta;
+ distance += delta;
+ if (distance > 4)
+ {
+ /*
+ * Moved out of the balloon location: cancel it.
+ * Remember button state
+ */
+ beval->state = event->xmotion.state;
+ if (beval->state & (Button1Mask|Button2Mask|Button3Mask))
+ {
+ /* Mouse buttons are pressed - no balloon now */
+ cancelBalloon(beval);
+ }
+ else if (beval->state & (Mod1Mask|Mod2Mask|Mod3Mask))
+ {
+ /*
+ * Alt is pressed -- enter super-evaluate-mode,
+ * where there is no time delay
+ */
+ beval->x = event->xmotion.x;
+ beval->y = event->xmotion.y;
+ beval->x_root = event->xmotion.x_root;
+ beval->y_root = event->xmotion.y_root;
+ cancelBalloon(beval);
+ if (beval->msgCB != NULL)
+ {
+ beval->showState = ShS_PENDING;
+ (*beval->msgCB)(beval, beval->state);
+ }
+ }
+ else
+ {
+ beval->x = event->xmotion.x;
+ beval->y = event->xmotion.y;
+ beval->x_root = event->xmotion.x_root;
+ beval->y_root = event->xmotion.y_root;
+ cancelBalloon(beval);
+ beval->timerID = XtAppAddTimeOut( beval->appContext,
+ (long_u)p_bdlay, timerRoutine, beval);
+ }
+ }
+ break;
+
+ /*
+ * Motif and Athena version: Keystrokes will be caught by the
+ * "textArea" widget, and handled in gui_x11_key_hit_cb().
+ */
+ case KeyPress:
+ if (beval->showState == ShS_SHOWING && beval->msgCB != NULL)
+ {
+ Modifiers modifier;
+ KeySym keysym;
+
+ XtTranslateKeycode(gui.dpy,
+ event->xkey.keycode, event->xkey.state,
+ &modifier, &keysym);
+ if (keysym == XK_Shift_L || keysym == XK_Shift_R)
+ {
+ beval->showState = ShS_UPDATE_PENDING;
+ (*beval->msgCB)(beval, ShiftMask);
+ }
+ else if (keysym == XK_Control_L || keysym == XK_Control_R)
+ {
+ beval->showState = ShS_UPDATE_PENDING;
+ (*beval->msgCB)(beval, ControlMask);
+ }
+ else
+ cancelBalloon(beval);
+ }
+ else
+ cancelBalloon(beval);
+ break;
+
+ case KeyRelease:
+ if (beval->showState == ShS_SHOWING && beval->msgCB != NULL)
+ {
+ Modifiers modifier;
+ KeySym keysym;
+
+ XtTranslateKeycode(gui.dpy, event->xkey.keycode,
+ event->xkey.state, &modifier, &keysym);
+ if ((keysym == XK_Shift_L) || (keysym == XK_Shift_R)) {
+ beval->showState = ShS_UPDATE_PENDING;
+ (*beval->msgCB)(beval, 0);
+ }
+ else if ((keysym == XK_Control_L) || (keysym == XK_Control_R))
+ {
+ beval->showState = ShS_UPDATE_PENDING;
+ (*beval->msgCB)(beval, 0);
+ }
+ else
+ cancelBalloon(beval);
+ }
+ else
+ cancelBalloon(beval);
+ break;
+
+ case LeaveNotify:
+ /* Ignore LeaveNotify events that are not "normal".
+ * Apparently we also get it when somebody else grabs focus.
+ * Happens for me every two seconds (some clipboard tool?) */
+ if (event->xcrossing.mode == NotifyNormal)
+ cancelBalloon(beval);
+ break;
+
+ case ButtonPress:
+ cancelBalloon(beval);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*ARGSUSED*/
+ static void
+timerRoutine(dx, id)
+ XtPointer dx;
+ XtIntervalId *id;
+{
+ BalloonEval *beval = (BalloonEval *)dx;
+
+ beval->timerID = (XtIntervalId)NULL;
+
+ /*
+ * If the timer event happens then the mouse has stopped long enough for
+ * a request to be started. The request will only send to the debugger if
+ * there the mouse is pointing at real data.
+ */
+ requestBalloon(beval);
+}
+
+#endif /* !FEAT_GUI_GTK */
+
+ static void
+requestBalloon(beval)
+ BalloonEval *beval;
+{
+ if (beval->showState != ShS_PENDING)
+ {
+ /* Determine the beval to display */
+ if (beval->msgCB != NULL)
+ {
+ beval->showState = ShS_PENDING;
+ (*beval->msgCB)(beval, beval->state);
+ }
+ else if (beval->msg != NULL)
+ drawBalloon(beval);
+ }
+}
+
+#ifdef FEAT_GUI_GTK
+
+# ifdef HAVE_GTK2
+/*
+ * Convert the string to UTF-8 if 'encoding' is not "utf-8".
+ * Replace any non-printable characters and invalid bytes sequences with
+ * "^X" or "<xx>" escapes, and apply SpecialKey highlighting to them.
+ * TAB and NL are passed through unscathed.
+ */
+# define IS_NONPRINTABLE(c) (((c) < 0x20 && (c) != TAB && (c) != NL) \
+ || (c) == DEL)
+ static void
+set_printable_label_text(GtkLabel *label, char_u *msg)
+{
+ char_u *convbuf = NULL;
+ char_u *buf;
+ char_u *p;
+ char_u *pdest;
+ unsigned int len;
+ int charlen;
+ int uc;
+ PangoAttrList *attr_list;
+
+ /* Convert to UTF-8 if it isn't already */
+ if (output_conv.vc_type != CONV_NONE)
+ {
+ convbuf = string_convert(&output_conv, msg, NULL);
+ if (convbuf != NULL)
+ msg = convbuf;
+ }
+
+ /* First let's see how much we need to allocate */
+ len = 0;
+ for (p = msg; *p != NUL; p += charlen)
+ {
+ if ((*p & 0x80) == 0) /* be quick for ASCII */
+ {
+ charlen = 1;
+ len += IS_NONPRINTABLE(*p) ? 2 : 1; /* nonprintable: ^X */
+ }
+ else
+ {
+ charlen = utf_ptr2len_check(p);
+ uc = utf_ptr2char(p);
+
+ if (charlen != utf_char2len(uc))
+ charlen = 1; /* reject overlong sequences */
+
+ if (charlen == 1 || uc < 0xa0) /* illegal byte or */
+ len += 4; /* control char: <xx> */
+ else if (!utf_printable(uc))
+ /* Note: we assume here that utf_printable() doesn't
+ * care about characters outside the BMP. */
+ len += 6; /* nonprintable: <xxxx> */
+ else
+ len += charlen;
+ }
+ }
+
+ attr_list = pango_attr_list_new();
+ buf = alloc(len + 1);
+
+ /* Now go for the real work */
+ if (buf != NULL)
+ {
+ attrentry_T *aep;
+ PangoAttribute *attr;
+ guicolor_T pixel;
+ GdkColor color = { 0, 0, 0, 0 };
+
+ /* Look up the RGB values of the SpecialKey foreground color. */
+ aep = syn_gui_attr2entry(hl_attr(HLF_8));
+ pixel = (aep != NULL) ? aep->ae_u.gui.fg_color : INVALCOLOR;
+ if (pixel != INVALCOLOR)
+ gdk_colormap_query_color(gtk_widget_get_colormap(gui.drawarea),
+ (unsigned long)pixel, &color);
+
+ pdest = buf;
+ p = msg;
+ while (*p != NUL)
+ {
+ /* Be quick for ASCII */
+ if ((*p & 0x80) == 0 && !IS_NONPRINTABLE(*p))
+ {
+ *pdest++ = *p++;
+ }
+ else
+ {
+ charlen = utf_ptr2len_check(p);
+ uc = utf_ptr2char(p);
+
+ if (charlen != utf_char2len(uc))
+ charlen = 1; /* reject overlong sequences */
+
+ if (charlen == 1 || uc < 0xa0 || !utf_printable(uc))
+ {
+ int outlen;
+
+ /* Careful: we can't just use transchar_byte() here,
+ * since 'encoding' is not necessarily set to "utf-8". */
+ if (*p & 0x80 && charlen == 1)
+ {
+ transchar_hex(pdest, *p); /* <xx> */
+ outlen = 4;
+ }
+ else if (uc >= 0x80)
+ {
+ /* Note: we assume here that utf_printable() doesn't
+ * care about characters outside the BMP. */
+ transchar_hex(pdest, uc); /* <xx> or <xxxx> */
+ outlen = (uc < 0x100) ? 4 : 6;
+ }
+ else
+ {
+ transchar_nonprint(pdest, *p); /* ^X */
+ outlen = 2;
+ }
+ if (pixel != INVALCOLOR)
+ {
+ attr = pango_attr_foreground_new(
+ color.red, color.green, color.blue);
+ attr->start_index = pdest - buf;
+ attr->end_index = pdest - buf + outlen;
+ pango_attr_list_insert(attr_list, attr);
+ }
+ pdest += outlen;
+ p += charlen;
+ }
+ else
+ {
+ do
+ *pdest++ = *p++;
+ while (--charlen != 0);
+ }
+ }
+ }
+ *pdest = NUL;
+ }
+
+ vim_free(convbuf);
+
+ gtk_label_set_text(label, (const char *)buf);
+ vim_free(buf);
+
+ gtk_label_set_attributes(label, attr_list);
+ pango_attr_list_unref(attr_list);
+}
+# undef IS_NONPRINTABLE
+# endif /* HAVE_GTK2 */
+
+/*
+ * Draw a balloon.
+ */
+ static void
+drawBalloon(BalloonEval *beval)
+{
+ if (beval->msg != NULL)
+ {
+ GtkRequisition requisition;
+ int screen_w;
+ int screen_h;
+ int x;
+ int y;
+ int x_offset = EVAL_OFFSET_X;
+ int y_offset = EVAL_OFFSET_Y;
+# ifdef HAVE_GTK2
+ PangoLayout *layout;
+# endif
+# ifdef HAVE_GTK_MULTIHEAD
+ GdkScreen *screen;
+
+ screen = gtk_widget_get_screen(beval->target);
+ gtk_window_set_screen(GTK_WINDOW(beval->balloonShell), screen);
+ screen_w = gdk_screen_get_width(screen);
+ screen_h = gdk_screen_get_height(screen);
+# else
+ screen_w = gdk_screen_width();
+ screen_h = gdk_screen_height();
+# endif
+ gtk_widget_ensure_style(beval->balloonShell);
+ gtk_widget_ensure_style(beval->balloonLabel);
+
+# ifdef HAVE_GTK2
+ set_printable_label_text(GTK_LABEL(beval->balloonLabel), beval->msg);
+ /*
+ * Dirty trick: Enable wrapping mode on the label's layout behind its
+ * back. This way GtkLabel won't try to constrain the wrap width to a
+ * builtin maximum value of about 65 Latin characters.
+ */
+ layout = gtk_label_get_layout(GTK_LABEL(beval->balloonLabel));
+# ifdef PANGO_WRAP_WORD_CHAR
+ pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
+# else
+ pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
+# endif
+ pango_layout_set_width(layout,
+ /* try to come up with some reasonable width */
+ PANGO_SCALE * CLAMP(gui.num_cols * gui.char_width,
+ screen_w / 2,
+ MAX(20, screen_w - 20)));
+
+ /* Calculate the balloon's width and height. */
+ gtk_widget_size_request(beval->balloonShell, &requisition);
+# else
+ gtk_label_set_line_wrap(GTK_LABEL(beval->balloonLabel), FALSE);
+ gtk_label_set_text(GTK_LABEL(beval->balloonLabel),
+ (const char *)beval->msg);
+
+ /* Calculate the balloon's width and height. */
+ gtk_widget_size_request(beval->balloonShell, &requisition);
+ /*
+ * Unfortunately, the dirty trick used above to get around the builtin
+ * maximum wrap width of GtkLabel doesn't work with GTK+ 1. Thus if
+ * and only if it's absolutely necessary to avoid drawing off-screen,
+ * do enable wrapping now and recalculate the size request.
+ */
+ if (requisition.width > screen_w)
+ {
+ gtk_label_set_line_wrap(GTK_LABEL(beval->balloonLabel), TRUE);
+ gtk_widget_size_request(beval->balloonShell, &requisition);
+ }
+# endif
+
+ /* Compute position of the balloon area */
+ gdk_window_get_origin(beval->target->window, &x, &y);
+ x += beval->x;
+ y += beval->y;
+
+ /* Get out of the way of the mouse pointer */
+ if (x + x_offset + requisition.width > screen_w)
+ y_offset += 15;
+ if (y + y_offset + requisition.height > screen_h)
+ y_offset = -requisition.height - EVAL_OFFSET_Y;
+
+ /* Sanitize values */
+ x = CLAMP(x + x_offset, 0, MAX(0, screen_w - requisition.width));
+ y = CLAMP(y + y_offset, 0, MAX(0, screen_h - requisition.height));
+
+ /* Show the balloon */
+ gtk_widget_set_uposition(beval->balloonShell, x, y);
+ gtk_widget_show(beval->balloonShell);
+
+ beval->showState = ShS_SHOWING;
+ }
+}
+
+/*
+ * Undraw a balloon.
+ */
+ static void
+undrawBalloon(BalloonEval *beval)
+{
+ if (beval->balloonShell != NULL)
+ gtk_widget_hide(beval->balloonShell);
+ beval->showState = ShS_NEUTRAL;
+}
+
+ static void
+cancelBalloon(BalloonEval *beval)
+{
+ if (beval->showState == ShS_SHOWING
+ || beval->showState == ShS_UPDATE_PENDING)
+ undrawBalloon(beval);
+
+ if (beval->timerID != 0)
+ {
+ gtk_timeout_remove(beval->timerID);
+ beval->timerID = 0;
+ }
+ beval->showState = ShS_NEUTRAL;
+}
+
+ static void
+createBalloonEvalWindow(BalloonEval *beval)
+{
+ beval->balloonShell = gtk_window_new(GTK_WINDOW_POPUP);
+
+ gtk_widget_set_app_paintable(beval->balloonShell, TRUE);
+ gtk_window_set_policy(GTK_WINDOW(beval->balloonShell), FALSE, FALSE, TRUE);
+ gtk_widget_set_name(beval->balloonShell, "gtk-tooltips");
+ gtk_container_border_width(GTK_CONTAINER(beval->balloonShell), 4);
+
+ gtk_signal_connect((GtkObject*)(beval->balloonShell), "expose_event",
+ GTK_SIGNAL_FUNC(balloon_expose_event_cb), NULL);
+# ifndef HAVE_GTK2
+ gtk_signal_connect((GtkObject*)(beval->balloonShell), "draw",
+ GTK_SIGNAL_FUNC(balloon_draw_cb), NULL);
+# endif
+ beval->balloonLabel = gtk_label_new(NULL);
+
+ gtk_label_set_line_wrap(GTK_LABEL(beval->balloonLabel), FALSE);
+ gtk_label_set_justify(GTK_LABEL(beval->balloonLabel), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment(GTK_MISC(beval->balloonLabel), 0.5f, 0.5f);
+ gtk_widget_set_name(beval->balloonLabel, "vim-balloon-label");
+ gtk_widget_show(beval->balloonLabel);
+
+ gtk_container_add(GTK_CONTAINER(beval->balloonShell), beval->balloonLabel);
+}
+
+#else /* !FEAT_GUI_GTK */
+
+/*
+ * Draw a balloon.
+ */
+ static void
+drawBalloon(beval)
+ BalloonEval *beval;
+{
+ Dimension w;
+ Dimension h;
+ Position tx;
+ Position ty;
+
+ if (beval->msg != NULL)
+ {
+ /* Show the Balloon */
+
+ /* Calculate the label's width and height */
+#ifdef FEAT_GUI_MOTIF
+ XmString s;
+
+ /* For the callback function we parse NL characters to create a
+ * multi-line label. This doesn't work for all languages, but
+ * XmStringCreateLocalized() doesn't do multi-line labels... */
+ if (beval->msgCB != NULL)
+ s = XmStringCreateLtoR((char *)beval->msg, XmFONTLIST_DEFAULT_TAG);
+ else
+ s = XmStringCreateLocalized((char *)beval->msg);
+ {
+ XmFontList fl;
+
+ fl = gui_motif_fontset2fontlist(&gui.tooltip_fontset);
+ if (fl != NULL)
+ {
+ XmStringExtent(fl, s, &w, &h);
+ XmFontListFree(fl);
+ }
+ }
+ w += gui.border_offset << 1;
+ h += gui.border_offset << 1;
+ XtVaSetValues(beval->balloonLabel, XmNlabelString, s, NULL);
+ XmStringFree(s);
+#else /* Athena */
+ /* Assume XtNinternational == True */
+ XFontSet fset;
+ XFontSetExtents *ext;
+
+ XtVaGetValues(beval->balloonLabel, XtNfontSet, &fset, NULL);
+ ext = XExtentsOfFontSet(fset);
+ h = ext->max_ink_extent.height;
+ w = XmbTextEscapement(fset,
+ (char *)beval->msg,
+ (int)STRLEN(beval->msg));
+ w += gui.border_offset << 1;
+ h += gui.border_offset << 1;
+ XtVaSetValues(beval->balloonLabel, XtNlabel, beval->msg, NULL);
+#endif
+
+ /* Compute position of the balloon area */
+ tx = beval->x_root + EVAL_OFFSET_X;
+ ty = beval->y_root + EVAL_OFFSET_Y;
+ if ((tx + w) > beval->screen_width)
+ tx = beval->screen_width - w;
+ if ((ty + h) > beval->screen_height)
+ ty = beval->screen_height - h;
+#ifdef FEAT_GUI_MOTIF
+ XtVaSetValues(beval->balloonShell,
+ XmNx, tx,
+ XmNy, ty,
+ NULL);
+#else
+ /* Athena */
+ XtVaSetValues(beval->balloonShell,
+ XtNx, tx,
+ XtNy, ty,
+ NULL);
+#endif
+
+ XtPopup(beval->balloonShell, XtGrabNone);
+
+ beval->showState = ShS_SHOWING;
+
+ current_beval = beval;
+ }
+}
+
+/*
+ * Undraw a balloon.
+ */
+ static void
+undrawBalloon(beval)
+ BalloonEval *beval;
+{
+ if (beval->balloonShell != (Widget)0)
+ XtPopdown(beval->balloonShell);
+ beval->showState = ShS_NEUTRAL;
+
+ current_beval = NULL;
+}
+
+ static void
+cancelBalloon(beval)
+ BalloonEval *beval;
+{
+ if (beval->showState == ShS_SHOWING
+ || beval->showState == ShS_UPDATE_PENDING)
+ undrawBalloon(beval);
+
+ if (beval->timerID != (XtIntervalId)NULL)
+ {
+ XtRemoveTimeOut(beval->timerID);
+ beval->timerID = (XtIntervalId)NULL;
+ }
+ beval->showState = ShS_NEUTRAL;
+}
+
+
+ static void
+createBalloonEvalWindow(beval)
+ BalloonEval *beval;
+{
+ Arg args[12];
+ int n;
+
+ n = 0;
+#ifdef FEAT_GUI_MOTIF
+ XtSetArg(args[n], XmNallowShellResize, True); n++;
+ beval->balloonShell = XtAppCreateShell("balloonEval", "BalloonEval",
+ overrideShellWidgetClass, gui.dpy, args, n);
+#else
+ /* Athena */
+ XtSetArg(args[n], XtNallowShellResize, True); n++;
+ beval->balloonShell = XtAppCreateShell("balloonEval", "BalloonEval",
+ overrideShellWidgetClass, gui.dpy, args, n);
+#endif
+
+ n = 0;
+#ifdef FEAT_GUI_MOTIF
+ {
+ XmFontList fl;
+
+ fl = gui_motif_fontset2fontlist(&gui.tooltip_fontset);
+ XtSetArg(args[n], XmNforeground, gui.tooltip_fg_pixel); n++;
+ XtSetArg(args[n], XmNbackground, gui.tooltip_bg_pixel); n++;
+ XtSetArg(args[n], XmNfontList, fl); n++;
+ XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
+ beval->balloonLabel = XtCreateManagedWidget("balloonLabel",
+ xmLabelWidgetClass, beval->balloonShell, args, n);
+ }
+#else /* FEAT_GUI_ATHENA */
+ XtSetArg(args[n], XtNforeground, gui.tooltip_fg_pixel); n++;
+ XtSetArg(args[n], XtNbackground, gui.tooltip_bg_pixel); n++;
+ XtSetArg(args[n], XtNinternational, True); n++;
+ XtSetArg(args[n], XtNfontSet, gui.tooltip_fontset); n++;
+ beval->balloonLabel = XtCreateManagedWidget("balloonLabel",
+ labelWidgetClass, beval->balloonShell, args, n);
+#endif
+}
+
+#endif /* !FEAT_GUI_GTK */
+#endif /* !FEAT_GUI_W32 */
+
+#endif /* FEAT_BEVAL */
diff --git a/src/gui_beval.h b/src/gui_beval.h
new file mode 100644
index 000000000..75d5a18fc
--- /dev/null
+++ b/src/gui_beval.h
@@ -0,0 +1,76 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Visual Workshop integration by Gordon Prieur
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+#if !defined(GUI_BEVAL_H) && (defined(FEAT_BEVAL) || defined(PROTO))
+#define GUI_BEVAL_H
+
+#ifdef FEAT_GUI_GTK
+# include <gtk/gtkwidget.h>
+#else
+# if defined(FEAT_GUI_X11)
+# include <X11/Intrinsic.h>
+# endif
+#endif
+
+typedef enum
+{
+ ShS_NEUTRAL, /* nothing showing or pending */
+ ShS_PENDING, /* data requested from debugger */
+ ShS_UPDATE_PENDING, /* switching information displayed */
+ ShS_SHOWING /* the balloon is being displayed */
+} BeState;
+
+typedef struct BalloonEvalStruct
+{
+#ifdef FEAT_GUI_GTK
+ GtkWidget *target; /* widget we are monitoring */
+ GtkWidget *balloonShell;
+ GtkWidget *balloonLabel;
+ unsigned int timerID; /* timer for run */
+ BeState showState; /* tells us whats currently going on */
+ int x;
+ int y;
+ unsigned int state; /* Button/Modifier key state */
+#else
+# if !defined(FEAT_GUI_W32)
+ Widget target; /* widget we are monitoring */
+ Widget balloonShell;
+ Widget balloonLabel;
+ XtIntervalId timerID; /* timer for run */
+ BeState showState; /* tells us whats currently going on */
+ XtAppContext appContext; /* used in event handler */
+ Position x;
+ Position y;
+ Position x_root;
+ Position y_root;
+ int state; /* Button/Modifier key state */
+# else
+ HWND target;
+ HWND balloon;
+ int x;
+ int y;
+ BeState showState; /* tells us whats currently going on */
+# endif
+#endif
+ int ts; /* tabstop setting for this buffer */
+ char_u *msg;
+ void (*msgCB)__ARGS((struct BalloonEvalStruct *, int));
+ void *clientData; /* For callback */
+#if !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_W32)
+ Dimension screen_width; /* screen width in pixels */
+ Dimension screen_height; /* screen height in pixels */
+#endif
+} BalloonEval;
+
+#define EVAL_OFFSET_X 15 /* displacement of beval topleft corner from pointer */
+#define EVAL_OFFSET_Y 10
+
+#include "gui_beval.pro"
+
+#endif /* GUI_BEVAL_H and FEAT_BEVAL */
diff --git a/src/gui_gtk.c b/src/gui_gtk.c
new file mode 100644
index 000000000..0d552c05f
--- /dev/null
+++ b/src/gui_gtk.c
@@ -0,0 +1,3035 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * Porting to GTK+ was done by:
+ *
+ * (C) 1998,1999,2000 by Marcin Dalecki <dalecki@evision.ag>
+ *
+ * With GREAT support and continuous encouragements by Andy Kahn and of
+ * course Bram Moolenaar!
+ *
+ * Support for GTK+ 2 was added by:
+ *
+ * (C) 2002,2003 Jason Hildebrand <jason@peaceworks.ca>
+ * Daniel Elstner <daniel.elstner@gmx.net>
+ *
+ * Best supporting actor (He helped somewhat, aesthetically speaking):
+ * Maxime Romano <verbophobe@hotmail.com>
+ */
+
+#ifdef FEAT_GUI_GTK
+# include "gui_gtk_f.h"
+#endif
+
+/* GTK defines MAX and MIN, but some system header files as well. Undefine
+ * them and don't use them. */
+#ifdef MIN
+# undef MIN
+#endif
+#ifdef MAX
+# undef MAX
+#endif
+
+#include "vim.h"
+
+#ifdef FEAT_GUI_GNOME
+/* Gnome redefines _() and N_(). Grrr... */
+# ifdef _
+# undef _
+# endif
+# ifdef N_
+# undef N_
+# endif
+# ifdef textdomain
+# undef textdomain
+# endif
+# ifdef bindtextdomain
+# undef bindtextdomain
+# endif
+# if defined(FEAT_GETTEXT) && !defined(ENABLE_NLS)
+# define ENABLE_NLS /* so the texts in the dialog boxes are translated */
+# endif
+# include <gnome.h>
+#endif
+
+#if defined(FEAT_GUI_DIALOG) && !defined(HAVE_GTK2)
+# include "../pixmaps/alert.xpm"
+# include "../pixmaps/error.xpm"
+# include "../pixmaps/generic.xpm"
+# include "../pixmaps/info.xpm"
+# include "../pixmaps/quest.xpm"
+#endif
+
+#if defined(FEAT_TOOLBAR) && !defined(HAVE_GTK2)
+/*
+ * Icons used by the toolbar code.
+ */
+#include "../pixmaps/tb_new.xpm"
+#include "../pixmaps/tb_open.xpm"
+#include "../pixmaps/tb_close.xpm"
+#include "../pixmaps/tb_save.xpm"
+#include "../pixmaps/tb_print.xpm"
+#include "../pixmaps/tb_cut.xpm"
+#include "../pixmaps/tb_copy.xpm"
+#include "../pixmaps/tb_paste.xpm"
+#include "../pixmaps/tb_find.xpm"
+#include "../pixmaps/tb_find_next.xpm"
+#include "../pixmaps/tb_find_prev.xpm"
+#include "../pixmaps/tb_find_help.xpm"
+#include "../pixmaps/tb_exit.xpm"
+#include "../pixmaps/tb_undo.xpm"
+#include "../pixmaps/tb_redo.xpm"
+#include "../pixmaps/tb_help.xpm"
+#include "../pixmaps/tb_macro.xpm"
+#include "../pixmaps/tb_make.xpm"
+#include "../pixmaps/tb_save_all.xpm"
+#include "../pixmaps/tb_jump.xpm"
+#include "../pixmaps/tb_ctags.xpm"
+#include "../pixmaps/tb_load_session.xpm"
+#include "../pixmaps/tb_save_session.xpm"
+#include "../pixmaps/tb_new_session.xpm"
+#include "../pixmaps/tb_blank.xpm"
+#include "../pixmaps/tb_maximize.xpm"
+#include "../pixmaps/tb_split.xpm"
+#include "../pixmaps/tb_minimize.xpm"
+#include "../pixmaps/tb_shell.xpm"
+#include "../pixmaps/tb_replace.xpm"
+#include "../pixmaps/tb_vsplit.xpm"
+#include "../pixmaps/tb_maxwidth.xpm"
+#include "../pixmaps/tb_minwidth.xpm"
+#endif /* FEAT_TOOLBAR && !HAVE_GTK2 */
+
+#ifdef FEAT_GUI_GTK
+# include <gdk/gdkkeysyms.h>
+# include <gdk/gdk.h>
+# ifdef WIN3264
+# include <gdk/gdkwin32.h>
+# else
+# include <gdk/gdkx.h>
+# endif
+
+# include <gtk/gtk.h>
+#else
+/* define these items to be able to generate prototypes without GTK */
+typedef int GtkWidget;
+# define gpointer int
+# define guint8 int
+# define GdkPixmap int
+# define GdkBitmap int
+# define GtkIconFactory int
+# define GtkToolbar int
+# define GtkAdjustment int
+# define gboolean int
+# define GdkEventKey int
+# define CancelData int
+#endif
+
+#ifdef HAVE_GTK2
+/*
+ * Convenience macros to convert from 'encoding' to 'termencoding' and
+ * vice versa. If no conversion is necessary the passed-in pointer is
+ * returned as is, without allocating any memory. Thus additional _FREE()
+ * macros are provided. The _FREE() macros also set the pointer to NULL,
+ * in order to avoid bugs due to illegal memory access only happening if
+ * 'encoding' != utf-8...
+ *
+ * Defining these macros as pure expressions looks a bit tricky but
+ * avoids depending on the context of the macro expansion. One of the
+ * rare occasions where the comma operator comes in handy :)
+ *
+ * Note: Do NOT keep the result around when handling control back to
+ * the main Vim! The user could change 'encoding' at any time.
+ */
+# define CONVERT_TO_UTF8(String) \
+ ((output_conv.vc_type == CONV_NONE || (String) == NULL) \
+ ? (String) \
+ : string_convert(&output_conv, (String), NULL))
+
+# define CONVERT_TO_UTF8_FREE(String) \
+ ((String) = ((output_conv.vc_type == CONV_NONE) \
+ ? (char_u *)NULL \
+ : (vim_free(String), (char_u *)NULL)))
+
+# define CONVERT_FROM_UTF8(String) \
+ ((input_conv.vc_type == CONV_NONE || (String) == NULL) \
+ ? (String) \
+ : string_convert(&input_conv, (String), NULL))
+
+# define CONVERT_FROM_UTF8_FREE(String) \
+ ((String) = ((input_conv.vc_type == CONV_NONE) \
+ ? (char_u *)NULL \
+ : (vim_free(String), (char_u *)NULL)))
+
+#endif /* HAVE_GTK2 */
+
+static void entry_activate_cb(GtkWidget *widget, gpointer data);
+static void entry_changed_cb(GtkWidget *entry, GtkWidget *dialog);
+static void find_replace_cb(GtkWidget *widget, gpointer data);
+
+#if defined(FEAT_TOOLBAR) && defined(HAVE_GTK2)
+/*
+ * Table from BuiltIn## icon indices to GTK+ stock IDs. Order must exactly
+ * match toolbar_names[] in menu.c! All stock icons including the "vim-*"
+ * ones can be overridden in your gtkrc file.
+ */
+static const char * const menu_stock_ids[] =
+{
+ /* 00 */ GTK_STOCK_NEW,
+ /* 01 */ GTK_STOCK_OPEN,
+ /* 02 */ GTK_STOCK_SAVE,
+ /* 03 */ GTK_STOCK_UNDO,
+ /* 04 */ GTK_STOCK_REDO,
+ /* 05 */ GTK_STOCK_CUT,
+ /* 06 */ GTK_STOCK_COPY,
+ /* 07 */ GTK_STOCK_PASTE,
+ /* 08 */ GTK_STOCK_PRINT,
+ /* 09 */ GTK_STOCK_HELP,
+ /* 10 */ GTK_STOCK_FIND,
+ /* 11 */ "vim-save-all",
+ /* 12 */ "vim-session-save",
+ /* 13 */ "vim-session-new",
+ /* 14 */ "vim-session-load",
+ /* 15 */ GTK_STOCK_EXECUTE,
+ /* 16 */ GTK_STOCK_FIND_AND_REPLACE,
+ /* 17 */ GTK_STOCK_CLOSE, /* FIXME: fuzzy */
+ /* 18 */ "vim-window-maximize",
+ /* 19 */ "vim-window-minimize",
+ /* 20 */ "vim-window-split",
+ /* 21 */ "vim-shell",
+ /* 22 */ GTK_STOCK_GO_BACK,
+ /* 23 */ GTK_STOCK_GO_FORWARD,
+ /* 24 */ "vim-find-help",
+ /* 25 */ GTK_STOCK_CONVERT,
+ /* 26 */ GTK_STOCK_JUMP_TO,
+ /* 27 */ "vim-build-tags",
+ /* 28 */ "vim-window-split-vertical",
+ /* 29 */ "vim-window-maximize-width",
+ /* 30 */ "vim-window-minimize-width",
+ /* 31 */ GTK_STOCK_QUIT
+};
+
+ static void
+add_stock_icon(GtkIconFactory *factory,
+ const char *stock_id,
+ const guint8 *inline_data,
+ int data_length)
+{
+ GdkPixbuf *pixbuf;
+ GtkIconSet *icon_set;
+
+ pixbuf = gdk_pixbuf_new_from_inline(data_length, inline_data, FALSE, NULL);
+ icon_set = gtk_icon_set_new_from_pixbuf(pixbuf);
+
+ gtk_icon_factory_add(factory, stock_id, icon_set);
+
+ gtk_icon_set_unref(icon_set);
+ g_object_unref(pixbuf);
+}
+
+ static int
+lookup_menu_iconfile(char_u *iconfile, char_u *dest)
+{
+ expand_env(iconfile, dest, MAXPATHL);
+
+ if (mch_isFullName(dest))
+ {
+ return vim_fexists(dest);
+ }
+ else
+ {
+ static const char suffixes[][4] = {"png", "xpm", "bmp"};
+ char_u buf[MAXPATHL];
+ unsigned int i;
+
+ for (i = 0; i < G_N_ELEMENTS(suffixes); ++i)
+ if (gui_find_bitmap(dest, buf, (char *)suffixes[i]) == OK)
+ {
+ STRCPY(dest, buf);
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+}
+
+ static GtkWidget *
+load_menu_iconfile(char_u *name, GtkIconSize icon_size)
+{
+ GtkWidget *image = NULL;
+ GtkIconSet *icon_set;
+ GtkIconSource *icon_source;
+
+ /*
+ * Rather than loading the icon directly into a GtkImage, create
+ * a new GtkIconSet and put it in there. This way we can easily
+ * scale the toolbar icons on the fly when needed.
+ */
+ icon_set = gtk_icon_set_new();
+ icon_source = gtk_icon_source_new();
+
+ gtk_icon_source_set_filename(icon_source, (const char *)name);
+ gtk_icon_set_add_source(icon_set, icon_source);
+
+ image = gtk_image_new_from_icon_set(icon_set, icon_size);
+
+ gtk_icon_source_free(icon_source);
+ gtk_icon_set_unref(icon_set);
+
+ return image;
+}
+
+ static GtkWidget *
+create_menu_icon(vimmenu_T *menu, GtkIconSize icon_size)
+{
+ GtkWidget *image = NULL;
+ char_u buf[MAXPATHL];
+
+ /* First use a specified "icon=" argument. */
+ if (menu->iconfile != NULL && lookup_menu_iconfile(menu->iconfile, buf))
+ image = load_menu_iconfile(buf, icon_size);
+
+ /* If not found and not builtin specified try using the menu name. */
+ if (image == NULL && !menu->icon_builtin
+ && lookup_menu_iconfile(menu->name, buf))
+ image = load_menu_iconfile(buf, icon_size);
+
+ /* Still not found? Then use a builtin icon, a blank one as fallback. */
+ if (image == NULL)
+ {
+ const char *stock_id;
+ const int n_ids = G_N_ELEMENTS(menu_stock_ids);
+
+ if (menu->iconidx >= 0 && menu->iconidx < n_ids)
+ stock_id = menu_stock_ids[menu->iconidx];
+ else
+ stock_id = GTK_STOCK_MISSING_IMAGE;
+
+ image = gtk_image_new_from_stock(stock_id, icon_size);
+ }
+
+ return image;
+}
+
+#endif /* FEAT_TOOLBAR && HAVE_GTK2 */
+
+#if (defined(FEAT_TOOLBAR) && defined(HAVE_GTK2)) || defined(PROTO)
+
+ void
+gui_gtk_register_stock_icons(void)
+{
+# include "../pixmaps/stock_icons.h"
+ GtkIconFactory *factory;
+
+ factory = gtk_icon_factory_new();
+# define ADD_ICON(Name, Data) add_stock_icon(factory, Name, Data, (int)sizeof(Data))
+
+ ADD_ICON("vim-build-tags", stock_vim_build_tags);
+ ADD_ICON("vim-find-help", stock_vim_find_help);
+ ADD_ICON("vim-save-all", stock_vim_save_all);
+ ADD_ICON("vim-session-load", stock_vim_session_load);
+ ADD_ICON("vim-session-new", stock_vim_session_new);
+ ADD_ICON("vim-session-save", stock_vim_session_save);
+ ADD_ICON("vim-shell", stock_vim_shell);
+ ADD_ICON("vim-window-maximize", stock_vim_window_maximize);
+ ADD_ICON("vim-window-maximize-width", stock_vim_window_maximize_width);
+ ADD_ICON("vim-window-minimize", stock_vim_window_minimize);
+ ADD_ICON("vim-window-minimize-width", stock_vim_window_minimize_width);
+ ADD_ICON("vim-window-split", stock_vim_window_split);
+ ADD_ICON("vim-window-split-vertical", stock_vim_window_split_vertical);
+
+# undef ADD_ICON
+ gtk_icon_factory_add_default(factory);
+ g_object_unref(factory);
+}
+
+#endif /* FEAT_TOOLBAR && HAVE_GTK2 */
+
+
+/*
+ * Only use accelerators when gtk_menu_ensure_uline_accel_group() is
+ * available, which is in version 1.2.1. That was the first version where
+ * accelerators properly worked (according to the change log).
+ */
+#ifdef GTK_CHECK_VERSION
+# if GTK_CHECK_VERSION(1, 2, 1)
+# define GTK_USE_ACCEL
+# endif
+#endif
+
+#if defined(FEAT_MENU) || defined(PROTO)
+
+/*
+ * Translate Vim's mnemonic tagging to GTK+ style and convert to UTF-8
+ * if necessary. The caller must vim_free() the returned string.
+ *
+ * Input Output
+ * _ __
+ * && &
+ * & _ stripped if use_mnemonic == FALSE
+ * <Tab> end of menu label text
+ */
+ static char_u *
+translate_mnemonic_tag(char_u *name, int use_mnemonic)
+{
+ char_u *buf;
+ char_u *psrc;
+ char_u *pdest;
+ int n_underscores = 0;
+
+# ifdef HAVE_GTK2
+ name = CONVERT_TO_UTF8(name);
+# endif
+ if (name == NULL)
+ return NULL;
+
+ for (psrc = name; *psrc != NUL && *psrc != TAB; ++psrc)
+ if (*psrc == '_')
+ ++n_underscores;
+
+ buf = alloc((unsigned)(psrc - name + n_underscores + 1));
+ if (buf != NULL)
+ {
+ pdest = buf;
+ for (psrc = name; *psrc != NUL && *psrc != TAB; ++psrc)
+ {
+ if (*psrc == '_')
+ {
+ *pdest++ = '_';
+ *pdest++ = '_';
+ }
+ else if (*psrc != '&')
+ {
+ *pdest++ = *psrc;
+ }
+ else if (*(psrc + 1) == '&')
+ {
+ *pdest++ = *psrc++;
+ }
+ else if (use_mnemonic)
+ {
+ *pdest++ = '_';
+ }
+ }
+ *pdest = NUL;
+ }
+
+# ifdef HAVE_GTK2
+ CONVERT_TO_UTF8_FREE(name);
+# endif
+ return buf;
+}
+
+# ifdef HAVE_GTK2
+
+ static void
+menu_item_new(vimmenu_T *menu, GtkWidget *parent_widget)
+{
+ GtkWidget *box;
+ char_u *text;
+ int use_mnemonic;
+
+ /* It would be neat to have image menu items, but that would require major
+ * changes to Vim's menu system. Not to mention that all the translations
+ * had to be updated. */
+ menu->id = gtk_menu_item_new();
+ box = gtk_hbox_new(FALSE, 20);
+
+ use_mnemonic = (p_wak[0] != 'n' || !GTK_IS_MENU_BAR(parent_widget));
+ text = translate_mnemonic_tag(menu->name, use_mnemonic);
+
+ menu->label = gtk_label_new_with_mnemonic((const char *)text);
+ vim_free(text);
+
+ gtk_box_pack_start(GTK_BOX(box), menu->label, FALSE, FALSE, 0);
+
+ if (menu->actext != NULL && menu->actext[0] != NUL)
+ {
+ text = CONVERT_TO_UTF8(menu->actext);
+
+ gtk_box_pack_end(GTK_BOX(box),
+ gtk_label_new((const char *)text),
+ FALSE, FALSE, 0);
+
+ CONVERT_TO_UTF8_FREE(text);
+ }
+
+ gtk_container_add(GTK_CONTAINER(menu->id), box);
+ gtk_widget_show_all(menu->id);
+}
+
+# else /* !HAVE_GTK2 */
+
+/*
+ * Create a highly customized menu item by hand instead of by using:
+ *
+ * gtk_menu_item_new_with_label(menu->dname);
+ *
+ * This is neccessary, since there is no other way in GTK+ 1 to get the
+ * not automatically parsed accellerator stuff right.
+ */
+ static void
+menu_item_new(vimmenu_T *menu, GtkWidget *parent_widget)
+{
+ GtkWidget *widget;
+ GtkWidget *bin;
+ GtkWidget *label;
+ char_u *name;
+ guint accel_key;
+
+ widget = gtk_widget_new(GTK_TYPE_MENU_ITEM,
+ "GtkWidget::visible", TRUE,
+ "GtkWidget::sensitive", TRUE,
+ /* "GtkWidget::parent", parent->submenu_id, */
+ NULL);
+ bin = gtk_widget_new(GTK_TYPE_HBOX,
+ "GtkWidget::visible", TRUE,
+ "GtkWidget::parent", widget,
+ "GtkBox::spacing", 16,
+ NULL);
+ label = gtk_widget_new(GTK_TYPE_ACCEL_LABEL,
+ "GtkWidget::visible", TRUE,
+ "GtkWidget::parent", bin,
+ "GtkAccelLabel::accel_widget", widget,
+ "GtkMisc::xalign", 0.0,
+ NULL);
+ menu->label = label;
+
+ if (menu->actext)
+ gtk_widget_new(GTK_TYPE_LABEL,
+ "GtkWidget::visible", TRUE,
+ "GtkWidget::parent", bin,
+ "GtkLabel::label", menu->actext,
+ "GtkMisc::xalign", 1.0,
+ NULL);
+
+ /*
+ * Translate VIM accelerator tagging into GTK+'s. Note that since GTK uses
+ * underscores as the accelerator key, we need to add an additional under-
+ * score for each understore that appears in the menu name.
+ */
+# ifdef GTK_USE_ACCEL
+ name = translate_mnemonic_tag(menu->name,
+ (p_wak[0] != 'n' || !GTK_IS_MENU_BAR(parent_widget)));
+# else
+ name = translate_mnemonic_tag(menu->name, FALSE);
+# endif
+
+ /* let GTK do its thing */
+ accel_key = gtk_label_parse_uline(GTK_LABEL(label), (const char *)name);
+ vim_free(name);
+
+# ifdef GTK_USE_ACCEL
+ /* Don't add accelator if 'winaltkeys' is "no". */
+ if (accel_key != GDK_VoidSymbol)
+ {
+ if (GTK_IS_MENU_BAR(parent_widget))
+ {
+ if (*p_wak != 'n')
+ gtk_widget_add_accelerator(widget,
+ "activate_item",
+ gui.accel_group,
+ accel_key, GDK_MOD1_MASK,
+ (GtkAccelFlags)0);
+ }
+ else
+ {
+ gtk_widget_add_accelerator(widget,
+ "activate_item",
+ gtk_menu_ensure_uline_accel_group(GTK_MENU(parent_widget)),
+ accel_key, 0,
+ (GtkAccelFlags)0);
+ }
+ }
+# endif /* GTK_USE_ACCEL */
+
+ menu->id = widget;
+}
+
+# endif /* !HAVE_GTK2 */
+
+ void
+gui_mch_add_menu(vimmenu_T *menu, int idx)
+{
+ vimmenu_T *parent;
+ GtkWidget *parent_widget;
+
+ if (menu->name[0] == ']' || menu_is_popup(menu->name))
+ {
+ menu->submenu_id = gtk_menu_new();
+ return;
+ }
+
+ parent = menu->parent;
+
+ if ((parent != NULL && parent->submenu_id == NULL)
+ || !menu_is_menubar(menu->name))
+ return;
+
+ parent_widget = (parent != NULL) ? parent->submenu_id : gui.menubar;
+ menu_item_new(menu, parent_widget);
+
+ /* since the tearoff should always appear first, increment idx */
+ if (parent != NULL && !menu_is_popup(parent->name))
+ ++idx;
+
+ gtk_menu_shell_insert(GTK_MENU_SHELL(parent_widget), menu->id, idx);
+
+#ifndef HAVE_GTK2
+ /*
+ * The "Help" menu is a special case, and should be placed at the far
+ * right hand side of the menu-bar. It's detected by its high priority.
+ *
+ * Right-aligning "Help" is considered bad UI design nowadays.
+ * Thus lets disable this for GTK+ 2 to match the environment.
+ */
+ if (parent == NULL && menu->priority >= 9999)
+ gtk_menu_item_right_justify(GTK_MENU_ITEM(menu->id));
+#endif
+
+ menu->submenu_id = gtk_menu_new();
+
+ gtk_menu_set_accel_group(GTK_MENU(menu->submenu_id), gui.accel_group);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu->id), menu->submenu_id);
+
+ menu->tearoff_handle = gtk_tearoff_menu_item_new();
+ if (vim_strchr(p_go, GO_TEAROFF) != NULL)
+ gtk_widget_show(menu->tearoff_handle);
+ gtk_menu_prepend(GTK_MENU(menu->submenu_id), menu->tearoff_handle);
+}
+
+/*ARGSUSED*/
+ static void
+menu_item_activate(GtkWidget *widget, gpointer data)
+{
+ gui_menu_cb((vimmenu_T *)data);
+
+# ifndef HAVE_GTK2
+ /* Work around a bug in GTK+ 1: we don't seem to get a focus-in
+ * event after clicking a menu item shown via :popup. */
+ if (!gui.in_focus)
+ gui_focus_change(TRUE);
+# endif
+
+ /* make sure the menu action is taken immediately */
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+# if defined(FEAT_TOOLBAR) && !defined(HAVE_GTK2)
+/*
+ * These are the pixmaps used for the default buttons.
+ * Order must exactly match toolbar_names[] in menu.c!
+ */
+static char **(built_in_pixmaps[]) =
+{
+ tb_new_xpm,
+ tb_open_xpm,
+ tb_save_xpm,
+ tb_undo_xpm,
+ tb_redo_xpm,
+ tb_cut_xpm,
+ tb_copy_xpm,
+ tb_paste_xpm,
+ tb_print_xpm,
+ tb_help_xpm,
+ tb_find_xpm,
+ tb_save_all_xpm,
+ tb_save_session_xpm,
+ tb_new_session_xpm,
+ tb_load_session_xpm,
+ tb_macro_xpm,
+ tb_replace_xpm,
+ tb_close_xpm,
+ tb_maximize_xpm,
+ tb_minimize_xpm,
+ tb_split_xpm,
+ tb_shell_xpm,
+ tb_find_prev_xpm,
+ tb_find_next_xpm,
+ tb_find_help_xpm,
+ tb_make_xpm,
+ tb_jump_xpm,
+ tb_ctags_xpm,
+ tb_vsplit_xpm,
+ tb_maxwidth_xpm,
+ tb_minwidth_xpm,
+ tb_exit_xpm
+};
+
+/*
+ * creates a blank pixmap using tb_blank
+ */
+ static void
+pixmap_create_from_xpm(char **xpm, GdkPixmap **pixmap, GdkBitmap **mask)
+{
+ *pixmap = gdk_pixmap_colormap_create_from_xpm_d(
+ NULL,
+ gtk_widget_get_colormap(gui.mainwin),
+ mask,
+ NULL,
+ xpm);
+}
+
+/*
+ * creates a pixmap by using a built-in number
+ */
+ static void
+pixmap_create_by_num(int pixmap_num, GdkPixmap **pixmap, GdkBitmap **mask)
+{
+ if (pixmap_num >= 0 && pixmap_num < (sizeof(built_in_pixmaps)
+ / sizeof(built_in_pixmaps[0])))
+ pixmap_create_from_xpm(built_in_pixmaps[pixmap_num], pixmap, mask);
+}
+
+/*
+ * Creates a pixmap by using the pixmap "name" found in 'runtimepath'/bitmaps/
+ */
+ static void
+pixmap_create_by_dir(char_u *name, GdkPixmap **pixmap, GdkBitmap **mask)
+{
+ char_u full_pathname[MAXPATHL + 1];
+
+ if (gui_find_bitmap(name, full_pathname, "xpm") == OK)
+ *pixmap = gdk_pixmap_colormap_create_from_xpm(
+ NULL,
+ gtk_widget_get_colormap(gui.mainwin),
+ mask,
+ &gui.mainwin->style->bg[GTK_STATE_NORMAL],
+ (const char *)full_pathname);
+}
+
+/*
+ * Creates a pixmap by using the pixmap "fname".
+ */
+ static void
+pixmap_create_from_file(char_u *fname, GdkPixmap **pixmap, GdkBitmap **mask)
+{
+ *pixmap = gdk_pixmap_colormap_create_from_xpm(
+ NULL,
+ gtk_widget_get_colormap(gui.mainwin),
+ mask,
+ &gui.mainwin->style->bg[GTK_STATE_NORMAL],
+ (const char *)fname);
+}
+
+# endif /* FEAT_TOOLBAR && !HAVE_GTK2 */
+
+ void
+gui_mch_add_menu_item(vimmenu_T *menu, int idx)
+{
+ vimmenu_T *parent;
+
+ parent = menu->parent;
+
+# ifdef FEAT_TOOLBAR
+ if (menu_is_toolbar(parent->name))
+ {
+ GtkToolbar *toolbar;
+
+ toolbar = GTK_TOOLBAR(gui.toolbar);
+ menu->submenu_id = NULL;
+
+ if (menu_is_separator(menu->name))
+ {
+ gtk_toolbar_insert_space(toolbar, idx);
+ menu->id = NULL;
+ }
+ else
+ {
+# ifdef HAVE_GTK2
+ char_u *text;
+ char_u *tooltip;
+
+ text = CONVERT_TO_UTF8(menu->dname);
+ tooltip = CONVERT_TO_UTF8(menu->strings[MENU_INDEX_TIP]);
+
+ menu->id = gtk_toolbar_insert_item(
+ toolbar,
+ (const char *)text,
+ (const char *)tooltip,
+ NULL,
+ create_menu_icon(menu, gtk_toolbar_get_icon_size(toolbar)),
+ G_CALLBACK(&menu_item_activate),
+ menu,
+ idx);
+
+ CONVERT_TO_UTF8_FREE(text);
+ CONVERT_TO_UTF8_FREE(tooltip);
+
+# else /* !HAVE_GTK2 */
+
+ GdkPixmap *pixmap = NULL;
+ GdkBitmap *mask = NULL;
+
+ /* First try user specified bitmap, then builtin, the a blank. */
+ if (menu->iconfile != NULL)
+ {
+ char_u buf[MAXPATHL + 1];
+
+ gui_find_iconfile(menu->iconfile, buf, "xpm");
+ pixmap_create_from_file(buf, &pixmap, &mask);
+ }
+ if (pixmap == NULL && !menu->icon_builtin)
+ pixmap_create_by_dir(menu->name, &pixmap, &mask);
+ if (pixmap == NULL && menu->iconidx >= 0)
+ pixmap_create_by_num(menu->iconidx, &pixmap, &mask);
+ if (pixmap == NULL)
+ pixmap_create_from_xpm(tb_blank_xpm, &pixmap, &mask);
+ if (pixmap == NULL)
+ return; /* should at least have blank pixmap, but if not... */
+
+ menu->id = gtk_toolbar_insert_item(
+ toolbar,
+ (char *)(menu->dname),
+ (char *)(menu->strings[MENU_INDEX_TIP]),
+ (char *)(menu->dname),
+ gtk_pixmap_new(pixmap, mask),
+ GTK_SIGNAL_FUNC(menu_item_activate),
+ (gpointer)menu,
+ idx);
+# endif /* !HAVE_GTK2 */
+ }
+ }
+ else
+# endif /* FEAT_TOOLBAR */
+ {
+ /* No parent, must be a non-menubar menu */
+ if (parent->submenu_id == NULL)
+ return;
+
+ /* Make place for the possible tearoff handle item. Not in the popup
+ * menu, it doesn't have a tearoff item. */
+ if (parent != NULL && !menu_is_popup(parent->name))
+ ++idx;
+
+ if (menu_is_separator(menu->name))
+ {
+ /* Separator: Just add it */
+ menu->id = gtk_menu_item_new();
+ gtk_widget_set_sensitive(menu->id, FALSE);
+ gtk_widget_show(menu->id);
+ gtk_menu_insert(GTK_MENU(parent->submenu_id), menu->id, idx);
+
+ return;
+ }
+
+ /* Add textual menu item. */
+ menu_item_new(menu, parent->submenu_id);
+ gtk_widget_show(menu->id);
+ gtk_menu_insert(GTK_MENU(parent->submenu_id), menu->id, idx);
+
+ if (menu->id != NULL)
+ gtk_signal_connect(GTK_OBJECT(menu->id), "activate",
+ GTK_SIGNAL_FUNC(menu_item_activate), menu);
+ }
+}
+#endif /* FEAT_MENU */
+
+
+ void
+gui_mch_set_text_area_pos(int x, int y, int w, int h)
+{
+ gtk_form_move_resize(GTK_FORM(gui.formwin), gui.drawarea, x, y, w, h);
+}
+
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Enable or disable accelators for the toplevel menus.
+ */
+ void
+gui_gtk_set_mnemonics(int enable)
+{
+ vimmenu_T *menu;
+ char_u *name;
+# if !defined(HAVE_GTK2) && defined(GTK_USE_ACCEL)
+ guint accel_key;
+# endif
+
+ for (menu = root_menu; menu != NULL; menu = menu->next)
+ {
+ if (menu->id == NULL)
+ continue;
+
+# if defined(HAVE_GTK2)
+ name = translate_mnemonic_tag(menu->name, enable);
+ gtk_label_set_text_with_mnemonic(GTK_LABEL(menu->label),
+ (const char *)name);
+ vim_free(name);
+# elif defined(GTK_USE_ACCEL)
+ name = translate_mnemonic_tag(menu->name, TRUE);
+ if (name != NULL)
+ {
+ accel_key = gtk_label_parse_uline(GTK_LABEL(menu->label),
+ (const char *)name);
+ if (accel_key != GDK_VoidSymbol)
+ gtk_widget_remove_accelerator(menu->id, gui.accel_group,
+ accel_key, GDK_MOD1_MASK);
+ if (enable && accel_key != GDK_VoidSymbol)
+ gtk_widget_add_accelerator(menu->id, "activate_item",
+ gui.accel_group,
+ accel_key, GDK_MOD1_MASK,
+ (GtkAccelFlags)0);
+ vim_free(name);
+ }
+ if (!enable)
+ {
+ name = translate_mnemonic_tag(menu->name, FALSE);
+ gtk_label_parse_uline(GTK_LABEL(menu->label), (const char *)name);
+ vim_free(name);
+ }
+# endif
+ }
+}
+
+ static void
+recurse_tearoffs(vimmenu_T *menu, int val)
+{
+ for (; menu != NULL; menu = menu->next)
+ {
+ if (menu->submenu_id != NULL && menu->tearoff_handle != NULL
+ && menu->name[0] != ']' && !menu_is_popup(menu->name))
+ {
+ if (val)
+ gtk_widget_show(menu->tearoff_handle);
+ else
+ gtk_widget_hide(menu->tearoff_handle);
+ }
+ recurse_tearoffs(menu->children, val);
+ }
+}
+
+ void
+gui_mch_toggle_tearoffs(int enable)
+{
+ recurse_tearoffs(root_menu, enable);
+}
+#endif /* FEAT_MENU */
+
+
+#if defined(FEAT_TOOLBAR) && !defined(HAVE_GTK2)
+/*
+ * Seems like there's a hole in the GTK Toolbar API: there's no provision for
+ * removing an item from the toolbar. Therefore I need to resort to going
+ * really deeply into the internal widget structures.
+ *
+ * <danielk> I'm not sure the statement above is true -- at least with
+ * GTK+ 2 one can just call gtk_widget_destroy() and be done with it.
+ * It is true though that you couldn't remove space items before GTK+ 2
+ * (without digging into the internals that is). But the code below
+ * doesn't seem to handle those either. Well, it's obsolete anyway.
+ */
+ static void
+toolbar_remove_item_by_text(GtkToolbar *tb, const char *text)
+{
+ GtkContainer *container;
+ GList *childl;
+ GtkToolbarChild *gtbc;
+
+ g_return_if_fail(tb != NULL);
+ g_return_if_fail(GTK_IS_TOOLBAR(tb));
+ container = GTK_CONTAINER(&tb->container);
+
+ for (childl = tb->children; childl; childl = childl->next)
+ {
+ gtbc = (GtkToolbarChild *)childl->data;
+
+ if (gtbc->type != GTK_TOOLBAR_CHILD_SPACE
+ && strcmp(GTK_LABEL(gtbc->label)->label, text) == 0)
+ {
+ gboolean was_visible;
+
+ was_visible = GTK_WIDGET_VISIBLE(gtbc->widget);
+ gtk_widget_unparent(gtbc->widget);
+
+ tb->children = g_list_remove_link(tb->children, childl);
+ g_free(gtbc);
+ g_list_free(childl);
+ tb->num_children--;
+
+ if (was_visible && GTK_WIDGET_VISIBLE(container))
+ gtk_widget_queue_resize(GTK_WIDGET(container));
+
+ break;
+ }
+ }
+}
+#endif /* FEAT_TOOLBAR && !HAVE_GTK2 */
+
+
+#if defined(FEAT_TOOLBAR) && defined(HAVE_GTK2)
+ static int
+get_menu_position(vimmenu_T *menu)
+{
+ vimmenu_T *node;
+ int index = 0;
+
+ for (node = menu->parent->children; node != menu; node = node->next)
+ {
+ g_return_val_if_fail(node != NULL, -1);
+ ++index;
+ }
+
+ return index;
+}
+#endif /* FEAT_TOOLBAR && HAVE_GTK2 */
+
+
+#if defined(FEAT_TOOLBAR) || defined(PROTO)
+ void
+gui_mch_menu_set_tip(vimmenu_T *menu)
+{
+ if (menu->id != NULL && menu->parent != NULL
+ && gui.toolbar != NULL && menu_is_toolbar(menu->parent->name))
+ {
+ char_u *tooltip;
+
+# ifdef HAVE_GTK2
+ tooltip = CONVERT_TO_UTF8(menu->strings[MENU_INDEX_TIP]);
+# else
+ tooltip = menu->strings[MENU_INDEX_TIP];
+# endif
+ gtk_tooltips_set_tip(GTK_TOOLBAR(gui.toolbar)->tooltips,
+ menu->id, (const char *)tooltip, NULL);
+# ifdef HAVE_GTK2
+ CONVERT_TO_UTF8_FREE(tooltip);
+# endif
+ }
+}
+#endif /* FEAT_TOOLBAR */
+
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Destroy the machine specific menu widget.
+ */
+ void
+gui_mch_destroy_menu(vimmenu_T *menu)
+{
+# ifdef FEAT_TOOLBAR
+ if (menu->parent != NULL && menu_is_toolbar(menu->parent->name))
+ {
+# ifdef HAVE_GTK2
+ if (menu_is_separator(menu->name))
+ gtk_toolbar_remove_space(GTK_TOOLBAR(gui.toolbar),
+ get_menu_position(menu));
+ else if (menu->id != NULL)
+ gtk_widget_destroy(menu->id);
+# else
+ toolbar_remove_item_by_text(GTK_TOOLBAR(gui.toolbar),
+ (const char *)menu->dname);
+# endif
+ }
+ else
+# endif /* FEAT_TOOLBAR */
+ {
+ if (menu->submenu_id != NULL)
+ gtk_widget_destroy(menu->submenu_id);
+
+ if (menu->id != NULL)
+ gtk_widget_destroy(menu->id);
+ }
+
+ menu->submenu_id = NULL;
+ menu->id = NULL;
+}
+#endif /* FEAT_MENU */
+
+
+/*
+ * Scrollbar stuff.
+ */
+ void
+gui_mch_set_scrollbar_thumb(scrollbar_T *sb, long val, long size, long max)
+{
+ if (sb->id != NULL)
+ {
+ GtkAdjustment *adjustment;
+
+ adjustment = gtk_range_get_adjustment(GTK_RANGE(sb->id));
+
+ adjustment->lower = 0.0;
+ adjustment->value = val;
+ adjustment->upper = max + 1;
+ adjustment->page_size = size;
+ adjustment->page_increment = size < 3L ? 1L : size - 2L;
+ adjustment->step_increment = 1.0;
+
+#ifdef HAVE_GTK2
+ g_signal_handler_block(GTK_OBJECT(adjustment),
+ (gulong)sb->handler_id);
+#else
+ gtk_signal_handler_block(GTK_OBJECT(adjustment),
+ (guint)sb->handler_id);
+#endif
+ gtk_adjustment_changed(adjustment);
+#ifdef HAVE_GTK2
+ g_signal_handler_unblock(GTK_OBJECT(adjustment),
+ (gulong)sb->handler_id);
+#else
+ gtk_signal_handler_unblock(GTK_OBJECT(adjustment),
+ (guint)sb->handler_id);
+#endif
+ }
+}
+
+ void
+gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h)
+{
+ if (sb->id != NULL)
+ gtk_form_move_resize(GTK_FORM(gui.formwin), sb->id, x, y, w, h);
+}
+
+/*
+ * Take action upon scrollbar dragging.
+ */
+ static void
+adjustment_value_changed(GtkAdjustment *adjustment, gpointer data)
+{
+ scrollbar_T *sb;
+ long value;
+ int dragging = FALSE;
+
+#ifdef FEAT_XIM
+ /* cancel any preediting */
+ if (im_is_preediting())
+ xim_reset();
+#endif
+
+ sb = gui_find_scrollbar((long)data);
+ value = (long)adjustment->value;
+ /*
+ * The dragging argument must be right for the scrollbar to work with
+ * closed folds. This isn't documented, hopefully this will keep on
+ * working in later GTK versions.
+ *
+ * FIXME: Well, it doesn't work in GTK2. :)
+ * HACK: Get the mouse pointer position, if it appears to be on an arrow
+ * button set "dragging" to FALSE. This assumes square buttons!
+ */
+ if (sb != NULL)
+ {
+#ifdef HAVE_GTK2
+ dragging = TRUE;
+
+ if (sb->wp != NULL)
+ {
+ int x;
+ int y;
+ GdkModifierType state;
+ int width;
+ int height;
+
+ /* vertical scrollbar: need to set "dragging" properly in case
+ * there are closed folds. */
+ gdk_window_get_pointer(sb->id->window, &x, &y, &state);
+ gdk_window_get_size(sb->id->window, &width, &height);
+ if (x >= 0 && x < width && y >= 0 && y < height)
+ {
+ if (y < width)
+ {
+ /* up arrow: move one (closed fold) line up */
+ dragging = FALSE;
+ value = sb->wp->w_topline - 2;
+ }
+ else if (y > height - width)
+ {
+ /* down arrow: move one (closed fold) line down */
+ dragging = FALSE;
+ value = sb->wp->w_topline;
+ }
+ }
+ }
+#else
+ dragging = (GTK_RANGE(sb->id)->scroll_type == GTK_SCROLL_NONE);
+#endif
+ }
+
+ gui_drag_scrollbar(sb, value, dragging);
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+/* SBAR_VERT or SBAR_HORIZ */
+ void
+gui_mch_create_scrollbar(scrollbar_T *sb, int orient)
+{
+ if (orient == SBAR_HORIZ)
+ sb->id = gtk_hscrollbar_new(NULL);
+ else if (orient == SBAR_VERT)
+ sb->id = gtk_vscrollbar_new(NULL);
+
+ if (sb->id != NULL)
+ {
+ GtkAdjustment *adjustment;
+
+ GTK_WIDGET_UNSET_FLAGS(sb->id, GTK_CAN_FOCUS);
+ gtk_form_put(GTK_FORM(gui.formwin), sb->id, 0, 0);
+
+ adjustment = gtk_range_get_adjustment(GTK_RANGE(sb->id));
+
+ sb->handler_id = gtk_signal_connect(
+ GTK_OBJECT(adjustment), "value_changed",
+ GTK_SIGNAL_FUNC(adjustment_value_changed),
+ GINT_TO_POINTER(sb->ident));
+ gui_mch_update();
+ }
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+ void
+gui_mch_destroy_scrollbar(scrollbar_T *sb)
+{
+ if (sb->id != NULL)
+ {
+ gtk_widget_destroy(sb->id);
+ sb->id = NULL;
+ }
+ gui_mch_update();
+}
+#endif
+
+#if defined(FEAT_BROWSE) || defined(PROTO)
+/*
+ * Implementation of the file selector related stuff
+ */
+
+/*ARGSUSED*/
+ static void
+browse_ok_cb(GtkWidget *widget, gpointer cbdata)
+{
+ gui_T *vw = (gui_T *)cbdata;
+
+ if (vw->browse_fname != NULL)
+ g_free(vw->browse_fname);
+
+ vw->browse_fname = (char_u *)g_strdup(gtk_file_selection_get_filename(
+ GTK_FILE_SELECTION(vw->filedlg)));
+ gtk_widget_hide(vw->filedlg);
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+/*ARGSUSED*/
+ static void
+browse_cancel_cb(GtkWidget *widget, gpointer cbdata)
+{
+ gui_T *vw = (gui_T *)cbdata;
+
+ if (vw->browse_fname != NULL)
+ {
+ g_free(vw->browse_fname);
+ vw->browse_fname = NULL;
+ }
+ gtk_widget_hide(vw->filedlg);
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+/*ARGSUSED*/
+ static gboolean
+browse_destroy_cb(GtkWidget * widget)
+{
+ if (gui.browse_fname != NULL)
+ {
+ g_free(gui.browse_fname);
+ gui.browse_fname = NULL;
+ }
+ gui.filedlg = NULL;
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+
+ return FALSE;
+}
+
+/*
+ * Put up a file requester.
+ * Returns the selected name in allocated memory, or NULL for Cancel.
+ * saving, select file to write
+ * title title for the window
+ * dflt default name
+ * ext not used (extension added)
+ * initdir initial directory, NULL for current dir
+ * filter not used (file name filter)
+ */
+/*ARGSUSED*/
+ char_u *
+gui_mch_browse(int saving,
+ char_u *title,
+ char_u *dflt,
+ char_u *ext,
+ char_u *initdir,
+ char_u *filter)
+{
+ GtkFileSelection *fs; /* shortcut */
+ char_u dirbuf[MAXPATHL];
+ char_u *p;
+
+# ifdef HAVE_GTK2
+ title = CONVERT_TO_UTF8(title);
+# endif
+
+ if (!gui.filedlg)
+ {
+ gui.filedlg = gtk_file_selection_new((const gchar *)title);
+ gtk_window_set_modal(GTK_WINDOW(gui.filedlg), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(gui.filedlg),
+ GTK_WINDOW(gui.mainwin));
+ fs = GTK_FILE_SELECTION(gui.filedlg);
+
+ gtk_container_border_width(GTK_CONTAINER(fs), 4);
+
+ gtk_signal_connect(GTK_OBJECT(fs->ok_button),
+ "clicked", GTK_SIGNAL_FUNC(browse_ok_cb), &gui);
+ gtk_signal_connect(GTK_OBJECT(fs->cancel_button),
+ "clicked", GTK_SIGNAL_FUNC(browse_cancel_cb), &gui);
+ /* gtk_signal_connect() doesn't work for destroy, it causes a hang */
+ gtk_signal_connect_object(GTK_OBJECT(gui.filedlg),
+ "destroy", GTK_SIGNAL_FUNC(browse_destroy_cb),
+ GTK_OBJECT(gui.filedlg));
+ }
+ else
+ gtk_window_set_title(GTK_WINDOW(gui.filedlg), (const gchar *)title);
+
+# ifdef HAVE_GTK2
+ CONVERT_TO_UTF8_FREE(title);
+# endif
+
+ /* if our pointer is currently hidden, then we should show it. */
+ gui_mch_mousehide(FALSE);
+
+ /* Concatenate "initdir" and "dflt". */
+ if (initdir == NULL || *initdir == NUL)
+ mch_dirname(dirbuf, MAXPATHL);
+ else if (STRLEN(initdir) + 2 < MAXPATHL)
+ STRCPY(dirbuf, initdir);
+ else
+ dirbuf[0] = NUL;
+ /* Always need a trailing slash for a directory. */
+ add_pathsep(dirbuf);
+ if (dflt != NULL && *dflt != NUL
+ && STRLEN(dirbuf) + 2 + STRLEN(dflt) < MAXPATHL)
+ STRCAT(dirbuf, dflt);
+
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(gui.filedlg),
+ (const gchar *)dirbuf);
+# ifndef HAVE_GTK2
+ gui_gtk_position_in_parent(GTK_WIDGET(gui.mainwin),
+ GTK_WIDGET(gui.filedlg), VW_POS_MOUSE);
+# endif
+
+ gtk_widget_show(gui.filedlg);
+ while (gui.filedlg && GTK_WIDGET_DRAWABLE(gui.filedlg))
+ gtk_main_iteration_do(TRUE);
+
+ if (gui.browse_fname == NULL)
+ return NULL;
+
+ /* shorten the file name if possible */
+ mch_dirname(dirbuf, MAXPATHL);
+ p = shorten_fname(gui.browse_fname, dirbuf);
+ if (p == NULL)
+ p = gui.browse_fname;
+ return vim_strsave(p);
+}
+
+#endif /* FEAT_BROWSE */
+
+#if (defined(FEAT_GUI_DIALOG) && !defined(HAVE_GTK2)) || defined(PROTO)
+
+static char_u *dialog_textfield = NULL;
+static GtkWidget *dialog_textentry;
+
+ static void
+dlg_destroy(GtkWidget *dlg)
+{
+ if (dialog_textfield != NULL)
+ {
+ const char *text;
+
+ text = gtk_entry_get_text(GTK_ENTRY(dialog_textentry));
+ STRNCPY(dialog_textfield, text, IOSIZE);
+ dialog_textfield[IOSIZE - 1] = NUL;
+ }
+
+ /* Destroy the dialog, will break the waiting loop. */
+ gtk_widget_destroy(dlg);
+}
+
+# ifdef FEAT_GUI_GNOME
+/* ARGSUSED */
+ static int
+gui_gnome_dialog( int type,
+ char_u *title,
+ char_u *message,
+ char_u *buttons,
+ int dfltbutton,
+ char_u *textfield)
+{
+ GtkWidget *dlg;
+ char *gdtype;
+ char_u *buttons_copy, *p, *next;
+ char **buttons_list;
+ int butcount, cur;
+
+ /* make a copy, so that we can insert NULs */
+ if ((buttons_copy = vim_strsave(buttons)) == NULL)
+ return -1;
+
+ /* determine exact number of buttons and allocate array to hold them */
+ for (butcount = 0, p = buttons; *p; p++)
+ {
+ if (*p == '\n')
+ butcount++;
+ }
+ butcount++;
+ buttons_list = g_new0(char *, butcount + 1);
+
+ /* Add pixmap */
+ switch (type)
+ {
+ case VIM_ERROR:
+ gdtype = GNOME_MESSAGE_BOX_ERROR;
+ break;
+ case VIM_WARNING:
+ gdtype = GNOME_MESSAGE_BOX_WARNING;
+ break;
+ case VIM_INFO:
+ gdtype = GNOME_MESSAGE_BOX_INFO;
+ break;
+ case VIM_QUESTION:
+ gdtype = GNOME_MESSAGE_BOX_QUESTION;
+ break;
+ default:
+ gdtype = GNOME_MESSAGE_BOX_GENERIC;
+ };
+
+ p = buttons_copy;
+ for (cur = 0; cur < butcount; ++cur)
+ {
+ for (next = p; *next; ++next)
+ {
+ if (*next == DLG_HOTKEY_CHAR)
+ mch_memmove(next, next + 1, STRLEN(next));
+ if (*next == DLG_BUTTON_SEP)
+ {
+ *next++ = NUL;
+ break;
+ }
+ }
+
+ /* this should probably go into a table, but oh well */
+ if (g_strcasecmp((char *)p, "Ok") == 0)
+ buttons_list[cur] = g_strdup(GNOME_STOCK_BUTTON_OK);
+ else if (g_strcasecmp((char *)p, "Cancel") == 0)
+ buttons_list[cur] = g_strdup(GNOME_STOCK_BUTTON_CANCEL);
+ else if (g_strcasecmp((char *)p, "Yes") == 0)
+ buttons_list[cur] = g_strdup(GNOME_STOCK_BUTTON_YES);
+ else if (g_strcasecmp((char *)p, "No") == 0)
+ buttons_list[cur] = g_strdup(GNOME_STOCK_BUTTON_NO);
+ else if (g_strcasecmp((char *)p, "Close") == 0)
+ buttons_list[cur] = g_strdup(GNOME_STOCK_BUTTON_CLOSE);
+ else if (g_strcasecmp((char *)p, "Help") == 0)
+ buttons_list[cur] = g_strdup(GNOME_STOCK_BUTTON_HELP);
+ else if (g_strcasecmp((char *)p, "Apply") == 0)
+ buttons_list[cur] = g_strdup(GNOME_STOCK_BUTTON_APPLY);
+#if 0
+ /*
+ * these aren't really used that often anyway, but are listed here as
+ * placeholders in case we need them.
+ */
+ else if (g_strcasecmp((char *)p, "Next") == 0)
+ buttons_list[cur] = g_strdup(GNOME_STOCK_BUTTON_NEXT);
+ else if (g_strcasecmp((char *)p, "Prev") == 0)
+ buttons_list[cur] = g_strdup(GNOME_STOCK_BUTTON_PREV);
+ else if (g_strcasecmp((char *)p, "Up") == 0)
+ buttons_list[cur] = g_strdup(GNOME_STOCK_BUTTON_UP);
+ else if (g_strcasecmp((char *)p, "Down") == 0)
+ buttons_list[cur] = g_strdup(GNOME_STOCK_BUTTON_DOWN);
+ else if (g_strcasecmp((char *)p, "Font") == 0)
+ buttons_list[cur] = g_strdup(GNOME_STOCK_BUTTON_FONT);
+#endif
+ else
+ buttons_list[cur] = g_strdup((char *)p);
+
+ if (*next == NUL)
+ break;
+
+ p = next;
+ }
+ vim_free(buttons_copy);
+
+ dlg = gnome_message_box_newv((const char *)message,
+ (const char *)gdtype,
+ (const char **)buttons_list);
+ for (cur = 0; cur < butcount; ++cur)
+ g_free(buttons_list[cur]);
+ g_free(buttons_list);
+
+ dialog_textfield = textfield;
+ if (textfield != NULL)
+ {
+ /* Add text entry field */
+ dialog_textentry = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dlg)->vbox), dialog_textentry,
+ TRUE, TRUE, 0);
+ gtk_entry_set_text(GTK_ENTRY(dialog_textentry),
+ (const gchar *)textfield);
+ gtk_entry_select_region(GTK_ENTRY(dialog_textentry), 0,
+ STRLEN(textfield));
+ gtk_entry_set_max_length(GTK_ENTRY(dialog_textentry), IOSIZE - 1);
+ gtk_entry_set_position(GTK_ENTRY(dialog_textentry), STRLEN(textfield));
+ gtk_widget_show(dialog_textentry);
+ gtk_window_set_focus(GTK_WINDOW(dlg), dialog_textentry);
+ }
+
+ gtk_signal_connect_object(GTK_OBJECT(dlg), "destroy",
+ GTK_SIGNAL_FUNC(dlg_destroy), GTK_OBJECT(dlg));
+ gnome_dialog_set_default(GNOME_DIALOG(dlg), dfltbutton + 1);
+ gui_gtk_position_in_parent(GTK_WIDGET(gui.mainwin),
+ GTK_WIDGET(dlg), VW_POS_MOUSE);
+
+ return (1 + gnome_dialog_run_and_close(GNOME_DIALOG(dlg)));
+}
+
+# endif /* FEAT_GUI_GNOME */
+
+typedef struct _ButtonData
+{
+ int *status;
+ int index;
+ GtkWidget *dialog;
+} ButtonData;
+
+typedef struct _CancelData
+{
+ int *status;
+ int ignore_enter;
+ GtkWidget *dialog;
+} CancelData;
+
+/* ARGSUSED */
+ static void
+dlg_button_clicked(GtkWidget * widget, ButtonData *data)
+{
+ *(data->status) = data->index + 1;
+ dlg_destroy(data->dialog);
+}
+
+/*
+ * This makes the Escape key equivalent to the cancel button.
+ */
+/*ARGSUSED*/
+ static int
+dlg_key_press_event(GtkWidget * widget, GdkEventKey * event, CancelData *data)
+{
+ /* Ignore hitting Enter when there is no default button. */
+ if (data->ignore_enter && event->keyval == GDK_Return)
+ return TRUE;
+
+ if (event->keyval != GDK_Escape && event->keyval != GDK_Return)
+ return FALSE;
+
+ /* The result value of 0 from a dialog is signaling cancelation.
+ * 1 means OK. */
+ *(data->status) = (event->keyval == GDK_Return);
+ dlg_destroy(data->dialog);
+
+ return TRUE;
+}
+
+/*
+ * Callback function for when the dialog was destroyed by a window manager.
+ */
+ static void
+dlg_destroy_cb(int *p)
+{
+ *p = TRUE; /* set dialog_destroyed to break out of the loop */
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+/* ARGSUSED */
+ int
+gui_mch_dialog( int type, /* type of dialog */
+ char_u *title, /* title of dialog */
+ char_u *message, /* message text */
+ char_u *buttons, /* names of buttons */
+ int def_but, /* default button */
+ char_u *textfield) /* text for textfield or NULL */
+{
+ char_u *names;
+ char_u *p;
+ int i;
+ int butcount;
+ int dialog_status = -1;
+ int dialog_destroyed = FALSE;
+ int vertical;
+
+ GtkWidget *dialog;
+ GtkWidget *frame;
+ GtkWidget *vbox;
+ GtkWidget *table;
+ GtkWidget *dialogmessage;
+ GtkWidget *action_area;
+ GtkWidget *sub_area;
+ GtkWidget *separator;
+ GtkAccelGroup *accel_group;
+ GtkWidget *pixmap;
+ GdkPixmap *icon = NULL;
+ GdkBitmap *mask = NULL;
+ char **icon_data = NULL;
+
+ GtkWidget **button;
+ ButtonData *data;
+ CancelData cancel_data;
+
+ /* if our pointer is currently hidden, then we should show it. */
+ gui_mch_mousehide(FALSE);
+
+# ifdef FEAT_GUI_GNOME
+ /* If Gnome is available, use it for the dialog. */
+ if (gtk_socket_id == 0)
+ return gui_gnome_dialog(type, title, message, buttons, def_but,
+ textfield);
+# endif
+
+ if (title == NULL)
+ title = (char_u *)_("Vim dialog...");
+
+ if ((type < 0) || (type > VIM_LAST_TYPE))
+ type = VIM_GENERIC;
+
+ /* Check 'v' flag in 'guioptions': vertical button placement. */
+ vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
+
+ dialog = gtk_window_new(GTK_WINDOW_DIALOG);
+ gtk_window_set_title(GTK_WINDOW(dialog), (const gchar *)title);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(gui.mainwin));
+ gtk_widget_realize(dialog);
+ gdk_window_set_decorations(dialog->window, GDK_DECOR_BORDER);
+ gdk_window_set_functions(dialog->window, GDK_FUNC_MOVE);
+
+ cancel_data.status = &dialog_status;
+ cancel_data.dialog = dialog;
+ gtk_signal_connect_after(GTK_OBJECT(dialog), "key_press_event",
+ GTK_SIGNAL_FUNC(dlg_key_press_event),
+ (gpointer) &cancel_data);
+ /* Catch the destroy signal, otherwise we don't notice a window manager
+ * destroying the dialog window. */
+ gtk_signal_connect_object(GTK_OBJECT(dialog), "destroy",
+ GTK_SIGNAL_FUNC(dlg_destroy_cb),
+ (gpointer)&dialog_destroyed);
+
+ gtk_grab_add(dialog);
+
+ /* this makes it look beter on Motif style window managers */
+ frame = gtk_frame_new(NULL);
+ gtk_container_add(GTK_CONTAINER(dialog), frame);
+ gtk_widget_show(frame);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+ gtk_widget_show(vbox);
+
+ table = gtk_table_new(1, 3, FALSE);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 4);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 8);
+ gtk_container_border_width(GTK_CONTAINER(table), 4);
+ gtk_box_pack_start(GTK_BOX(vbox), table, 4, 4, 0);
+ gtk_widget_show(table);
+
+ /* Add pixmap */
+ switch (type)
+ {
+ case VIM_GENERIC:
+ icon_data = generic_xpm;
+ break;
+ case VIM_ERROR:
+ icon_data = error_xpm;
+ break;
+ case VIM_WARNING:
+ icon_data = alert_xpm;
+ break;
+ case VIM_INFO:
+ icon_data = info_xpm;
+ break;
+ case VIM_QUESTION:
+ icon_data = quest_xpm;
+ break;
+ default:
+ icon_data = generic_xpm;
+ };
+ icon = gdk_pixmap_colormap_create_from_xpm_d(NULL,
+ gtk_widget_get_colormap(dialog),
+ &mask, NULL, icon_data);
+ if (icon)
+ {
+ pixmap = gtk_pixmap_new(icon, mask);
+ /* gtk_misc_set_alignment(GTK_MISC(pixmap), 0.5, 0.5); */
+ gtk_table_attach_defaults(GTK_TABLE(table), pixmap, 0, 1, 0, 1);
+ gtk_widget_show(pixmap);
+ }
+
+ /* Add label */
+ dialogmessage = gtk_label_new((const gchar *)message);
+ gtk_table_attach_defaults(GTK_TABLE(table), dialogmessage, 1, 2, 0, 1);
+ gtk_widget_show(dialogmessage);
+
+ dialog_textfield = textfield;
+ if (textfield != NULL)
+ {
+ /* Add text entry field */
+ dialog_textentry = gtk_entry_new();
+ gtk_widget_set_usize(dialog_textentry, 400, -2);
+ gtk_box_pack_start(GTK_BOX(vbox), dialog_textentry, TRUE, TRUE, 0);
+ gtk_entry_set_text(GTK_ENTRY(dialog_textentry),
+ (const gchar *)textfield);
+ gtk_entry_select_region(GTK_ENTRY(dialog_textentry), 0,
+ STRLEN(textfield));
+ gtk_entry_set_max_length(GTK_ENTRY(dialog_textentry), IOSIZE - 1);
+ gtk_entry_set_position(GTK_ENTRY(dialog_textentry), STRLEN(textfield));
+ gtk_widget_show(dialog_textentry);
+ }
+
+ /* Add box for buttons */
+ action_area = gtk_hbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(action_area), 4);
+ gtk_box_pack_end(GTK_BOX(vbox), action_area, FALSE, TRUE, 0);
+ gtk_widget_show(action_area);
+
+ /* Add a [vh]box in the hbox to center the buttons in the dialog. */
+ if (vertical)
+ sub_area = gtk_vbox_new(FALSE, 0);
+ else
+ sub_area = gtk_hbox_new(FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(sub_area), 0);
+ gtk_box_pack_start(GTK_BOX(action_area), sub_area, TRUE, FALSE, 0);
+ gtk_widget_show(sub_area);
+
+ /*
+ * Create the buttons.
+ */
+
+ /*
+ * Translate the Vim accelerator character into an underscore for GTK+.
+ * Double underscores to keep them in the label.
+ */
+ /* count the number of underscores */
+ i = 1;
+ for (p = buttons; *p; ++p)
+ if (*p == '_')
+ ++i;
+
+ /* make a copy of "buttons" with the translated characters */
+ names = alloc(STRLEN(buttons) + i);
+ if (names == NULL)
+ return -1;
+
+ p = names;
+ for (i = 0; buttons[i]; ++i)
+ {
+ if (buttons[i] == DLG_HOTKEY_CHAR)
+ *p++ = '_';
+ else
+ {
+ if (buttons[i] == '_')
+ *p++ = '_';
+ *p++ = buttons[i];
+ }
+ }
+ *p = NUL;
+
+ /* Count the number of buttons and allocate button[] and data[]. */
+ butcount = 1;
+ for (p = names; *p; ++p)
+ if (*p == DLG_BUTTON_SEP)
+ ++butcount;
+ button = (GtkWidget **)alloc((unsigned)(butcount * sizeof(GtkWidget *)));
+ data = (ButtonData *)alloc((unsigned)(butcount * sizeof(ButtonData)));
+ if (button == NULL || data == NULL)
+ {
+ vim_free(names);
+ vim_free(button);
+ vim_free(data);
+ return -1;
+ }
+
+ /* Attach the new accelerator group to the window. */
+ accel_group = gtk_accel_group_new();
+ gtk_accel_group_attach(accel_group, GTK_OBJECT(dialog));
+
+ p = names;
+ for (butcount = 0; *p; ++butcount)
+ {
+ char_u *next;
+ GtkWidget *label;
+# ifdef GTK_USE_ACCEL
+ guint accel_key;
+# endif
+
+ /* Chunk out this single button. */
+ for (next = p; *next; ++next)
+ {
+ if (*next == DLG_BUTTON_SEP)
+ {
+ *next++ = NUL;
+ break;
+ }
+ }
+
+ button[butcount] = gtk_button_new();
+ GTK_WIDGET_SET_FLAGS(button[butcount], GTK_CAN_DEFAULT);
+
+ label = gtk_accel_label_new("");
+ gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(label), dialog);
+
+# ifdef GTK_USE_ACCEL
+ accel_key = gtk_label_parse_uline(GTK_LABEL(label), (const gchar *)p);
+ /* Don't add accelator if 'winaltkeys' is "no". */
+ if (accel_key != GDK_VoidSymbol)
+ {
+ gtk_widget_add_accelerator(button[butcount],
+ "clicked",
+ accel_group,
+ accel_key, 0,
+ 0);
+ }
+# else
+ (void)gtk_label_parse_uline(GTK_LABEL(label), (const gchar *)p);
+# endif
+
+ gtk_container_add(GTK_CONTAINER(button[butcount]), label);
+ gtk_widget_show_all(button[butcount]);
+
+ data[butcount].status = &dialog_status;
+ data[butcount].index = butcount;
+ data[butcount].dialog = dialog;
+ gtk_signal_connect(GTK_OBJECT(button[butcount]),
+ (const char *)"clicked",
+ GTK_SIGNAL_FUNC(dlg_button_clicked),
+ (gpointer) &data[butcount]);
+
+ gtk_box_pack_start(GTK_BOX(sub_area), button[butcount],
+ TRUE, FALSE, 0);
+ p = next;
+ }
+
+ vim_free(names);
+
+ cancel_data.ignore_enter = FALSE;
+ if (butcount > 0)
+ {
+ --def_but; /* 1 is first button */
+ if (def_but >= butcount)
+ def_but = -1;
+ if (def_but >= 0)
+ {
+ gtk_widget_grab_focus(button[def_but]);
+ gtk_widget_grab_default(button[def_but]);
+ }
+ else
+ /* No default, ignore hitting Enter. */
+ cancel_data.ignore_enter = TRUE;
+ }
+
+ if (textfield != NULL)
+ gtk_window_set_focus(GTK_WINDOW(dialog), dialog_textentry);
+
+ separator = gtk_hseparator_new();
+ gtk_box_pack_end(GTK_BOX(vbox), separator, FALSE, TRUE, 0);
+ gtk_widget_show(separator);
+
+ dialog_status = -1;
+
+ gui_gtk_position_in_parent(GTK_WIDGET(gui.mainwin),
+ GTK_WIDGET(dialog), VW_POS_MOUSE);
+
+ gtk_widget_show(dialog);
+
+ /* loop here until the dialog goes away */
+ while (dialog_status == -1 && !dialog_destroyed
+ && GTK_WIDGET_DRAWABLE(dialog))
+ gtk_main_iteration_do(TRUE);
+
+ if (dialog_status < 0)
+ dialog_status = 0;
+ if (dialog_status != 1 && textfield != NULL)
+ *textfield = NUL; /* dialog was cancelled */
+
+ /* let the garbage collector know that we don't need it any longer */
+ gtk_accel_group_unref(accel_group);
+
+ vim_free(button);
+ vim_free(data);
+
+ return dialog_status;
+}
+
+#endif /* FEAT_GUI_DIALOG && !HAVE_GTK2 */
+
+
+#if defined(FEAT_GUI_DIALOG) && defined(HAVE_GTK2)
+
+ static GtkWidget *
+create_message_dialog(int type, char_u *title, char_u *message)
+{
+ GtkWidget *dialog;
+ GtkMessageType message_type;
+
+ switch (type)
+ {
+ case VIM_ERROR: message_type = GTK_MESSAGE_ERROR; break;
+ case VIM_WARNING: message_type = GTK_MESSAGE_WARNING; break;
+ case VIM_QUESTION: message_type = GTK_MESSAGE_QUESTION; break;
+ default: message_type = GTK_MESSAGE_INFO; break;
+ }
+
+ message = CONVERT_TO_UTF8(message);
+ dialog = gtk_message_dialog_new(GTK_WINDOW(gui.mainwin),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ message_type,
+ GTK_BUTTONS_NONE,
+ "%s", (const char *)message);
+ CONVERT_TO_UTF8_FREE(message);
+
+ if (title != NULL)
+ {
+ title = CONVERT_TO_UTF8(title);
+ gtk_window_set_title(GTK_WINDOW(dialog), (const char *)title);
+ CONVERT_TO_UTF8_FREE(title);
+ }
+ else if (type == VIM_GENERIC)
+ {
+ gtk_window_set_title(GTK_WINDOW(dialog), "VIM");
+ }
+
+ return dialog;
+}
+
+/*
+ * Split up button_string into individual button labels by inserting
+ * NUL bytes. Also replace the Vim-style mnemonic accelerator prefix
+ * '&' with '_'. button_string must point to allocated memory!
+ * Return an allocated array of pointers into button_string.
+ */
+ static char **
+split_button_string(char_u *button_string, int *n_buttons)
+{
+ char **array;
+ char_u *p;
+ unsigned int count = 1;
+
+ for (p = button_string; *p != NUL; ++p)
+ if (*p == DLG_BUTTON_SEP)
+ ++count;
+
+ array = (char **)alloc((count + 1) * sizeof(char *));
+ count = 0;
+
+ if (array != NULL)
+ {
+ array[count++] = (char *)button_string;
+ for (p = button_string; *p != NUL; ++p)
+ {
+ if (*p == DLG_BUTTON_SEP)
+ {
+ *p = NUL;
+ array[count++] = (char *)p + 1;
+ }
+ else if (*p == DLG_HOTKEY_CHAR)
+ *p = '_';
+#ifdef FEAT_MBYTE
+ else if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ array[count] = NULL; /* currently not relied upon, but doesn't hurt */
+ }
+
+ *n_buttons = count;
+ return array;
+}
+
+ static char **
+split_button_translation(const char *message)
+{
+ char **buttons = NULL;
+ char_u *str;
+ int n_buttons = 0;
+ int n_expected = 1;
+
+ for (str = (char_u *)message; *str != NUL; ++str)
+ if (*str == DLG_BUTTON_SEP)
+ ++n_expected;
+
+ str = (char_u *)_(message);
+ if (str != NULL)
+ {
+ if (output_conv.vc_type != CONV_NONE)
+ str = string_convert(&output_conv, str, NULL);
+ else
+ str = vim_strsave(str);
+
+ if (str != NULL)
+ buttons = split_button_string(str, &n_buttons);
+ }
+ /*
+ * Uh-oh... this should never ever happen. But we don't wanna crash
+ * if the translation is broken, thus fall back to the untranslated
+ * buttons string in case of emergency.
+ */
+ if (buttons == NULL || n_buttons != n_expected)
+ {
+ vim_free(buttons);
+ vim_free(str);
+ buttons = NULL;
+ str = vim_strsave((char_u *)message);
+
+ if (str != NULL)
+ buttons = split_button_string(str, &n_buttons);
+ if (buttons == NULL)
+ vim_free(str);
+ }
+
+ return buttons;
+}
+
+ static int
+button_equal(const char *a, const char *b)
+{
+ while (*a != '\0' && *b != '\0')
+ {
+ if (*a == '_' && *++a == '\0')
+ break;
+ if (*b == '_' && *++b == '\0')
+ break;
+
+ if (g_unichar_tolower(g_utf8_get_char(a))
+ != g_unichar_tolower(g_utf8_get_char(b)))
+ return FALSE;
+
+ a = g_utf8_next_char(a);
+ b = g_utf8_next_char(b);
+ }
+
+ return (*a == '\0' && *b == '\0');
+}
+
+ static void
+dialog_add_buttons(GtkDialog *dialog, char_u *button_string)
+{
+ char **ok;
+ char **ync; /* "yes no cancel" */
+ char **buttons;
+ int n_buttons = 0;
+ int index;
+
+ button_string = vim_strsave(button_string); /* must be writable */
+ if (button_string == NULL)
+ return;
+
+ /* Check 'v' flag in 'guioptions': vertical button placement. */
+ if (vim_strchr(p_go, GO_VERTICAL) != NULL)
+ {
+ GtkWidget *vbutton_box;
+
+ vbutton_box = gtk_vbutton_box_new();
+ gtk_widget_show(vbutton_box);
+ gtk_box_pack_end(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ vbutton_box, TRUE, FALSE, 0);
+ /* Overrule the "action_area" value, hopefully this works... */
+ GTK_DIALOG(dialog)->action_area = vbutton_box;
+ }
+
+ /*
+ * Yes this is ugly, I don't particularly like it either. But doing it
+ * this way has the compelling advantage that translations need not to
+ * be touched at all. See below what 'ok' and 'ync' are used for.
+ */
+ ok = split_button_translation(N_("&Ok"));
+ ync = split_button_translation(N_("&Yes\n&No\n&Cancel"));
+ buttons = split_button_string(button_string, &n_buttons);
+
+ /*
+ * Yes, the buttons are in reversed order to match the GNOME 2 desktop
+ * environment. Don't hit me -- it's all about consistency.
+ * Well, apparently somebody changed his mind: with GTK 2.2.4 it works the
+ * other way around...
+ */
+ for (index = 1; index <= n_buttons; ++index)
+ {
+ char *label;
+ char_u *label8;
+
+ label = buttons[index - 1];
+ /*
+ * Perform some guesswork to find appropriate stock items for the
+ * buttons. We have to compare with a sample of the translated
+ * button string to get things right. Yes, this is hackish :/
+ *
+ * But even the common button labels aren't necessarily translated,
+ * since anyone can create their own dialogs using Vim functions.
+ * Thus we have to check for those too.
+ */
+ if (ok != NULL && ync != NULL) /* almost impossible to fail */
+ {
+ if (button_equal(label, ok[0])) label = GTK_STOCK_OK;
+ else if (button_equal(label, ync[0])) label = GTK_STOCK_YES;
+ else if (button_equal(label, ync[1])) label = GTK_STOCK_NO;
+ else if (button_equal(label, ync[2])) label = GTK_STOCK_CANCEL;
+ else if (button_equal(label, "Ok")) label = GTK_STOCK_OK;
+ else if (button_equal(label, "Yes")) label = GTK_STOCK_YES;
+ else if (button_equal(label, "No")) label = GTK_STOCK_NO;
+ else if (button_equal(label, "Cancel")) label = GTK_STOCK_CANCEL;
+ }
+ label8 = CONVERT_TO_UTF8((char_u *)label);
+ gtk_dialog_add_button(dialog, (const gchar *)label8, index);
+ CONVERT_TO_UTF8_FREE(label8);
+ }
+
+ if (ok != NULL)
+ vim_free(*ok);
+ if (ync != NULL)
+ vim_free(*ync);
+ vim_free(ok);
+ vim_free(ync);
+ vim_free(buttons);
+ vim_free(button_string);
+}
+
+/*
+ * Allow mnemonic accelerators to be activated without pressing <Alt>.
+ * I'm not sure if it's a wise idea to do this. However, the old GTK+ 1.2
+ * GUI used to work this way, and I consider the impact on UI consistency
+ * low enough to justify implementing this as a special Vim feature.
+ */
+typedef struct _DialogInfo
+{
+ int ignore_enter; /* no default button, ignore "Enter" */
+ int noalt; /* accept accelerators without Alt */
+ GtkDialog *dialog; /* Widget of the dialog */
+} DialogInfo;
+
+/*ARGSUSED2*/
+ static gboolean
+dialog_key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ DialogInfo *di = (DialogInfo *)data;
+
+ /* Ignore hitting "Enter" if there is no default button. */
+ if (di->ignore_enter && event->keyval == GDK_Return)
+ return TRUE;
+
+ /* Close the dialog when hitting "Esc". */
+ if (event->keyval == GDK_Escape)
+ {
+ gtk_dialog_response(di->dialog, GTK_RESPONSE_REJECT);
+ return TRUE;
+ }
+
+ if (di->noalt
+ && (event->state & gtk_accelerator_get_default_mod_mask()) == 0)
+ {
+ return gtk_window_mnemonic_activate(
+ GTK_WINDOW(widget), event->keyval,
+ gtk_window_get_mnemonic_modifier(GTK_WINDOW(widget)));
+ }
+
+ return FALSE; /* continue emission */
+}
+
+ int
+gui_mch_dialog(int type, /* type of dialog */
+ char_u *title, /* title of dialog */
+ char_u *message, /* message text */
+ char_u *buttons, /* names of buttons */
+ int def_but, /* default button */
+ char_u *textfield) /* text for textfield or NULL */
+{
+ GtkWidget *dialog;
+ GtkWidget *entry = NULL;
+ char_u *text;
+ int response;
+ DialogInfo dialoginfo;
+
+ dialog = create_message_dialog(type, title, message);
+ dialoginfo.dialog = GTK_DIALOG(dialog);
+ dialog_add_buttons(GTK_DIALOG(dialog), buttons);
+
+ if (textfield != NULL)
+ {
+ GtkWidget *alignment;
+
+ entry = gtk_entry_new();
+ gtk_widget_show(entry);
+
+ text = CONVERT_TO_UTF8(textfield);
+ gtk_entry_set_text(GTK_ENTRY(entry), (const char *)text);
+ CONVERT_TO_UTF8_FREE(text);
+
+ alignment = gtk_alignment_new((float)0.5, (float)0.5,
+ (float)1.0, (float)1.0);
+ gtk_container_add(GTK_CONTAINER(alignment), entry);
+ gtk_container_set_border_width(GTK_CONTAINER(alignment), 5);
+ gtk_widget_show(alignment);
+
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ alignment, TRUE, FALSE, 0);
+ dialoginfo.noalt = FALSE;
+ }
+ else
+ dialoginfo.noalt = TRUE;
+
+ /* Allow activation of mnemonic accelerators without pressing <Alt> when
+ * there is no textfield. Handle pressing Enter and Esc. */
+ g_signal_connect(G_OBJECT(dialog), "key_press_event",
+ G_CALLBACK(&dialog_key_press_event_cb), &dialoginfo);
+
+ if (def_but > 0)
+ {
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog), def_but);
+ dialoginfo.ignore_enter = FALSE;
+ }
+ else
+ /* No default button, ignore pressing Enter. */
+ dialoginfo.ignore_enter = TRUE;
+
+ /* Show the mouse pointer if it's currently hidden. */
+ gui_mch_mousehide(FALSE);
+
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+
+ /* GTK_RESPONSE_NONE means the dialog was programmatically destroyed. */
+ if (response != GTK_RESPONSE_NONE)
+ {
+ if (textfield != NULL)
+ {
+ text = (char_u *)gtk_entry_get_text(GTK_ENTRY(entry));
+ text = CONVERT_FROM_UTF8(text);
+
+ STRNCPY(textfield, text, IOSIZE);
+ textfield[IOSIZE - 1] = NUL;
+
+ CONVERT_FROM_UTF8_FREE(text);
+ }
+ gtk_widget_destroy(dialog);
+ }
+
+ /* Terrible hack: When the text area still has focus when we remove the
+ * dialog, somehow gvim loses window focus. This is with "point to type"
+ * in the KDE 3.1 window manager. Warp the mouse pointer to outside the
+ * window and back to avoid that. */
+ if (!gui.in_focus)
+ {
+ int x, y;
+
+ gdk_window_get_pointer(gui.drawarea->window, &x, &y, NULL);
+ gui_mch_setmouse(-100, -100);
+ gui_mch_setmouse(x, y);
+ }
+
+ return response > 0 ? response : 0;
+}
+
+#endif /* FEAT_GUI_DIALOG && HAVE_GTK2 */
+
+
+#if defined(FEAT_MENU) || defined(PROTO)
+
+ void
+gui_mch_show_popupmenu(vimmenu_T *menu)
+{
+# if defined(FEAT_XIM) && defined(HAVE_GTK2)
+ /*
+ * Append a submenu for selecting an input method. This is
+ * currently the only way to switch input methods at runtime.
+ */
+ if (xic != NULL && g_object_get_data(G_OBJECT(menu->submenu_id),
+ "vim-has-im-menu") == NULL)
+ {
+ GtkWidget *menuitem;
+ GtkWidget *submenu;
+ char_u *name;
+
+ menuitem = gtk_separator_menu_item_new();
+ gtk_widget_show(menuitem);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu->submenu_id), menuitem);
+
+ name = (char_u *)_("Input _Methods");
+ name = CONVERT_TO_UTF8(name);
+ menuitem = gtk_menu_item_new_with_mnemonic((const char *)name);
+ CONVERT_TO_UTF8_FREE(name);
+ gtk_widget_show(menuitem);
+
+ submenu = gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu->submenu_id), menuitem);
+
+ gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(xic),
+ GTK_MENU_SHELL(submenu));
+ g_object_set_data(G_OBJECT(menu->submenu_id),
+ "vim-has-im-menu", GINT_TO_POINTER(TRUE));
+ }
+# endif /* FEAT_XIM && HAVE_GTK2 */
+
+ gtk_menu_popup(GTK_MENU(menu->submenu_id),
+ NULL, NULL,
+ (GtkMenuPositionFunc)NULL, NULL,
+ 3U, (guint32)GDK_CURRENT_TIME);
+}
+
+/*
+ * Menu position callback; used by gui_make_popup() to place the menu
+ * at the current text cursor position.
+ *
+ * Note: The push_in output argument seems to affect scrolling of huge
+ * menus that don't fit on the screen. Leave it at the default for now.
+ */
+/*ARGSUSED0*/
+ static void
+popup_menu_position_func(GtkMenu *menu,
+ gint *x, gint *y,
+# ifdef HAVE_GTK2
+ gboolean *push_in,
+# endif
+ gpointer user_data)
+{
+ if (curwin != NULL && gui.drawarea != NULL && gui.drawarea->window != NULL)
+ {
+ gdk_window_get_origin(gui.drawarea->window, x, y);
+
+ /* Find the cursor position in the current window */
+ *x += FILL_X(W_WINCOL(curwin) + curwin->w_wcol + 1) + 1;
+ *y += FILL_Y(W_WINROW(curwin) + curwin->w_wrow + 1) + 1;
+ }
+}
+
+ void
+gui_make_popup(char_u *path_name)
+{
+ vimmenu_T *menu;
+
+ menu = gui_find_menu(path_name);
+
+ if (menu != NULL && menu->submenu_id != NULL)
+ {
+ gtk_menu_popup(GTK_MENU(menu->submenu_id),
+ NULL, NULL,
+ &popup_menu_position_func, NULL,
+ 0U, (guint32)GDK_CURRENT_TIME);
+ }
+}
+
+#endif /* FEAT_MENU */
+
+
+/*
+ * We don't create it twice.
+ */
+
+typedef struct _SharedFindReplace
+{
+ GtkWidget *dialog; /* the main dialog widget */
+ GtkWidget *wword; /* 'Whole word only' check button */
+ GtkWidget *mcase; /* 'Match case' check button */
+ GtkWidget *up; /* search direction 'Up' radio button */
+ GtkWidget *down; /* search direction 'Down' radio button */
+ GtkWidget *what; /* 'Find what' entry text widget */
+ GtkWidget *with; /* 'Replace with' entry text widget */
+ GtkWidget *find; /* 'Find Next' action button */
+ GtkWidget *replace; /* 'Replace With' action button */
+ GtkWidget *all; /* 'Replace All' action button */
+} SharedFindReplace;
+
+static SharedFindReplace find_widgets = { NULL, };
+static SharedFindReplace repl_widgets = { NULL, };
+
+/* ARGSUSED */
+ static int
+find_key_press_event(
+ GtkWidget *widget,
+ GdkEventKey *event,
+ SharedFindReplace *frdp)
+{
+ /* If the user is holding one of the key modifiers we will just bail out,
+ * thus preserving the possibility of normal focus traversal.
+ */
+ if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
+ return FALSE;
+
+ /* the Escape key synthesizes a cancellation action */
+ if (event->keyval == GDK_Escape)
+ {
+ gtk_widget_hide(frdp->dialog);
+
+ return TRUE;
+ }
+ /*
+ * What the **** is this for? Disabled for GTK+ 2 because due to
+ * gtk_signal_connect_after() it doesn't have any effect anyway.
+ * (Fortunately.)
+ */
+#ifndef HAVE_GTK2
+ /* block traversal resulting from those keys */
+ if (event->keyval == GDK_Left
+ || event->keyval == GDK_Right
+ || event->keyval == GDK_space)
+ return TRUE;
+#endif
+
+ /* It would be delightfull if it where possible to do search history
+ * operations on the K_UP and K_DOWN keys here.
+ */
+
+ return FALSE;
+}
+
+#ifdef HAVE_GTK2
+ static GtkWidget *
+create_image_button(const char *stock_id, const char *label)
+{
+ char_u *text;
+ GtkWidget *box;
+ GtkWidget *alignment;
+ GtkWidget *button;
+
+ text = CONVERT_TO_UTF8((char_u *)label);
+
+ box = gtk_hbox_new(FALSE, 3);
+ gtk_box_pack_start(GTK_BOX(box),
+ gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_BUTTON),
+ FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(box),
+ gtk_label_new((const char *)text),
+ FALSE, FALSE, 0);
+
+ CONVERT_TO_UTF8_FREE(text);
+
+ alignment = gtk_alignment_new((float)0.5, (float)0.5,
+ (float)0.0, (float)0.0);
+ gtk_container_add(GTK_CONTAINER(alignment), box);
+ gtk_widget_show_all(alignment);
+
+ button = gtk_button_new();
+ gtk_container_add(GTK_CONTAINER(button), alignment);
+
+ return button;
+}
+
+/*
+ * This is currently only used by find_replace_dialog_create(), and
+ * I'd really like to keep it at that. In other words: don't spread
+ * this nasty hack all over the code. Think twice.
+ */
+ static const char *
+convert_localized_message(char_u **buffer, const char *message)
+{
+ if (output_conv.vc_type == CONV_NONE)
+ return message;
+
+ vim_free(*buffer);
+ *buffer = string_convert(&output_conv, (char_u *)message, NULL);
+
+ return (const char *)*buffer;
+}
+#endif /* HAVE_GTK2 */
+
+ static void
+find_replace_dialog_create(char_u *arg, int do_replace)
+{
+#ifndef HAVE_GTK2
+ GtkWidget *frame;
+#endif
+ GtkWidget *hbox; /* main top down box */
+ GtkWidget *actionarea;
+ GtkWidget *table;
+ GtkWidget *tmp;
+ GtkWidget *vbox;
+ gboolean sensitive;
+ SharedFindReplace *frdp;
+ char_u *entry_text;
+ int wword = FALSE;
+ int mcase = !p_ic;
+#ifdef HAVE_GTK2
+ char_u *conv_buffer = NULL;
+# define CONV(message) convert_localized_message(&conv_buffer, (message))
+#else
+# define CONV(message) (message)
+#endif
+
+ frdp = (do_replace) ? (&repl_widgets) : (&find_widgets);
+
+ /* Get the search string to use. */
+ entry_text = get_find_dialog_text(arg, &wword, &mcase);
+
+#ifdef HAVE_GTK2
+ if (entry_text != NULL && output_conv.vc_type != CONV_NONE)
+ {
+ char_u *old_text = entry_text;
+ entry_text = string_convert(&output_conv, entry_text, NULL);
+ vim_free(old_text);
+ }
+#endif
+
+ /*
+ * If the dialog already exists, just raise it.
+ */
+ if (frdp->dialog)
+ {
+#ifndef HAVE_GTK2
+ /* always make the dialog appear where you want it even if the mainwin
+ * has moved -- dbv */
+ gui_gtk_position_in_parent(GTK_WIDGET(gui.mainwin),
+ GTK_WIDGET(frdp->dialog), VW_POS_MOUSE);
+ gui_gtk_synch_fonts();
+
+ if (!GTK_WIDGET_VISIBLE(frdp->dialog))
+ {
+ gtk_widget_grab_focus(frdp->what);
+ gtk_widget_show(frdp->dialog);
+ }
+#endif
+ if (entry_text != NULL)
+ {
+ gtk_entry_set_text(GTK_ENTRY(frdp->what), (char *)entry_text);
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->wword),
+ (gboolean)wword);
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->mcase),
+ (gboolean)mcase);
+ }
+#ifdef HAVE_GTK2
+ gtk_window_present(GTK_WINDOW(frdp->dialog));
+#else
+ gdk_window_raise(frdp->dialog->window);
+#endif
+ vim_free(entry_text);
+ return;
+ }
+
+#ifdef HAVE_GTK2
+ frdp->dialog = gtk_dialog_new();
+ gtk_dialog_set_has_separator(GTK_DIALOG(frdp->dialog), FALSE);
+ gtk_window_set_transient_for(GTK_WINDOW(frdp->dialog), GTK_WINDOW(gui.mainwin));
+ gtk_window_set_destroy_with_parent(GTK_WINDOW(frdp->dialog), TRUE);
+#else
+ frdp->dialog = gtk_window_new(GTK_WINDOW_DIALOG);
+#endif
+
+ if (do_replace)
+ {
+#ifndef HAVE_GTK2
+ gtk_window_set_wmclass(GTK_WINDOW(frdp->dialog), "searchrepl", "gvim");
+#endif
+ gtk_window_set_title(GTK_WINDOW(frdp->dialog),
+ CONV(_("VIM - Search and Replace...")));
+ }
+ else
+ {
+#ifndef HAVE_GTK2
+ gtk_window_set_wmclass(GTK_WINDOW(frdp->dialog), "search", "gvim");
+#endif
+ gtk_window_set_title(GTK_WINDOW(frdp->dialog),
+ CONV(_("VIM - Search...")));
+ }
+
+#ifndef HAVE_GTK2 /* Utter crack. Shudder. */
+ gtk_widget_realize(frdp->dialog);
+ gdk_window_set_decorations(frdp->dialog->window,
+ GDK_DECOR_TITLE | GDK_DECOR_BORDER | GDK_DECOR_RESIZEH);
+ gdk_window_set_functions(frdp->dialog->window,
+ GDK_FUNC_RESIZE | GDK_FUNC_MOVE);
+#endif
+
+#ifndef HAVE_GTK2
+ /* this makes it look better on Motif style window managers */
+ frame = gtk_frame_new(NULL);
+ gtk_container_add(GTK_CONTAINER(frdp->dialog), frame);
+#endif
+
+ hbox = gtk_hbox_new(FALSE, 0);
+#ifdef HAVE_GTK2
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(frdp->dialog)->vbox), hbox);
+#else
+ gtk_container_add(GTK_CONTAINER(frame), hbox);
+#endif
+
+ if (do_replace)
+ table = gtk_table_new(1024, 4, FALSE);
+ else
+ table = gtk_table_new(1024, 3, FALSE);
+ gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 0);
+ gtk_container_border_width(GTK_CONTAINER(table), 4);
+
+ tmp = gtk_label_new(CONV(_("Find what:")));
+ gtk_misc_set_alignment(GTK_MISC(tmp), (gfloat)0.0, (gfloat)0.5);
+ gtk_table_attach(GTK_TABLE(table), tmp, 0, 1, 0, 1,
+ GTK_FILL, GTK_EXPAND, 2, 2);
+ frdp->what = gtk_entry_new();
+ sensitive = (entry_text != NULL && entry_text[0] != NUL);
+ if (entry_text != NULL)
+ gtk_entry_set_text(GTK_ENTRY(frdp->what), (char *)entry_text);
+ gtk_signal_connect(GTK_OBJECT(frdp->what), "changed",
+ GTK_SIGNAL_FUNC(entry_changed_cb), frdp->dialog);
+ gtk_signal_connect_after(GTK_OBJECT(frdp->what), "key_press_event",
+ GTK_SIGNAL_FUNC(find_key_press_event),
+ (gpointer) frdp);
+ gtk_table_attach(GTK_TABLE(table), frdp->what, 1, 1024, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND, 2, 2);
+
+ if (do_replace)
+ {
+ tmp = gtk_label_new(CONV(_("Replace with:")));
+ gtk_misc_set_alignment(GTK_MISC(tmp), (gfloat)0.0, (gfloat)0.5);
+ gtk_table_attach(GTK_TABLE(table), tmp, 0, 1, 1, 2,
+ GTK_FILL, GTK_EXPAND, 2, 2);
+ frdp->with = gtk_entry_new();
+ gtk_signal_connect(GTK_OBJECT(frdp->with), "activate",
+ GTK_SIGNAL_FUNC(find_replace_cb),
+ GINT_TO_POINTER(FRD_R_FINDNEXT));
+ gtk_signal_connect_after(GTK_OBJECT(frdp->with), "key_press_event",
+ GTK_SIGNAL_FUNC(find_key_press_event),
+ (gpointer) frdp);
+ gtk_table_attach(GTK_TABLE(table), frdp->with, 1, 1024, 1, 2,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND, 2, 2);
+
+ /*
+ * Make the entry activation only change the input focus onto the
+ * with item.
+ */
+ gtk_signal_connect(GTK_OBJECT(frdp->what), "activate",
+ GTK_SIGNAL_FUNC(entry_activate_cb), frdp->with);
+ }
+ else
+ {
+ /*
+ * Make the entry activation do the search.
+ */
+ gtk_signal_connect(GTK_OBJECT(frdp->what), "activate",
+ GTK_SIGNAL_FUNC(find_replace_cb),
+ GINT_TO_POINTER(FRD_FINDNEXT));
+ }
+
+ /* whole word only button */
+ frdp->wword = gtk_check_button_new_with_label(CONV(_("Match whole word only")));
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->wword),
+ (gboolean)wword);
+ if (do_replace)
+ gtk_table_attach(GTK_TABLE(table), frdp->wword, 0, 1023, 2, 3,
+ GTK_FILL, GTK_EXPAND, 2, 2);
+ else
+ gtk_table_attach(GTK_TABLE(table), frdp->wword, 0, 1023, 1, 2,
+ GTK_FILL, GTK_EXPAND, 2, 2);
+
+ /* match case button */
+ frdp->mcase = gtk_check_button_new_with_label(CONV(_("Match case")));
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->mcase),
+ (gboolean)mcase);
+ if (do_replace)
+ gtk_table_attach(GTK_TABLE(table), frdp->mcase, 0, 1023, 3, 4,
+ GTK_FILL, GTK_EXPAND, 2, 2);
+ else
+ gtk_table_attach(GTK_TABLE(table), frdp->mcase, 0, 1023, 2, 3,
+ GTK_FILL, GTK_EXPAND, 2, 2);
+
+ tmp = gtk_frame_new(CONV(_("Direction")));
+ if (do_replace)
+ gtk_table_attach(GTK_TABLE(table), tmp, 1023, 1024, 2, 4,
+ GTK_FILL, GTK_FILL, 2, 2);
+ else
+ gtk_table_attach(GTK_TABLE(table), tmp, 1023, 1024, 1, 3,
+ GTK_FILL, GTK_FILL, 2, 2);
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 0);
+ gtk_container_add(GTK_CONTAINER(tmp), vbox);
+
+ /* 'Up' and 'Down' buttons */
+ frdp->up = gtk_radio_button_new_with_label(NULL, CONV(_("Up")));
+ gtk_box_pack_start(GTK_BOX(vbox), frdp->up, TRUE, TRUE, 0);
+ frdp->down = gtk_radio_button_new_with_label(
+ gtk_radio_button_group(GTK_RADIO_BUTTON(frdp->up)),
+ CONV(_("Down")));
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->down), TRUE);
+#ifdef HAVE_GTK2
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 2);
+#endif
+ gtk_box_pack_start(GTK_BOX(vbox), frdp->down, TRUE, TRUE, 0);
+
+ /* vbox to hold the action buttons */
+ actionarea = gtk_vbutton_box_new();
+ gtk_container_border_width(GTK_CONTAINER(actionarea), 2);
+#ifndef HAVE_GTK2
+ if (do_replace)
+ {
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(actionarea),
+ GTK_BUTTONBOX_END);
+ gtk_button_box_set_spacing(GTK_BUTTON_BOX(actionarea), 0);
+ }
+#endif
+ gtk_box_pack_end(GTK_BOX(hbox), actionarea, FALSE, FALSE, 0);
+
+ /* 'Find Next' button */
+#ifdef HAVE_GTK2
+ frdp->find = create_image_button(GTK_STOCK_FIND, _("Find Next"));
+#else
+ frdp->find = gtk_button_new_with_label(_("Find Next"));
+#endif
+ gtk_widget_set_sensitive(frdp->find, sensitive);
+
+ gtk_signal_connect(GTK_OBJECT(frdp->find), "clicked",
+ GTK_SIGNAL_FUNC(find_replace_cb),
+ (do_replace) ? GINT_TO_POINTER(FRD_R_FINDNEXT)
+ : GINT_TO_POINTER(FRD_FINDNEXT));
+
+ GTK_WIDGET_SET_FLAGS(frdp->find, GTK_CAN_DEFAULT);
+ gtk_box_pack_start(GTK_BOX(actionarea), frdp->find, FALSE, FALSE, 0);
+ gtk_widget_grab_default(frdp->find);
+
+ if (do_replace)
+ {
+ /* 'Replace' button */
+#ifdef HAVE_GTK2
+ frdp->replace = create_image_button(GTK_STOCK_CONVERT, _("Replace"));
+#else
+ frdp->replace = gtk_button_new_with_label(_("Replace"));
+#endif
+ gtk_widget_set_sensitive(frdp->replace, sensitive);
+ GTK_WIDGET_SET_FLAGS(frdp->replace, GTK_CAN_DEFAULT);
+ gtk_box_pack_start(GTK_BOX(actionarea), frdp->replace, FALSE, FALSE, 0);
+ gtk_signal_connect(GTK_OBJECT(frdp->replace), "clicked",
+ GTK_SIGNAL_FUNC(find_replace_cb),
+ GINT_TO_POINTER(FRD_REPLACE));
+
+ /* 'Replace All' button */
+#ifdef HAVE_GTK2
+ frdp->all = create_image_button(GTK_STOCK_CONVERT, _("Replace All"));
+#else
+ frdp->all = gtk_button_new_with_label(_("Replace All"));
+#endif
+ gtk_widget_set_sensitive(frdp->all, sensitive);
+ GTK_WIDGET_SET_FLAGS(frdp->all, GTK_CAN_DEFAULT);
+ gtk_box_pack_start(GTK_BOX(actionarea), frdp->all, FALSE, FALSE, 0);
+ gtk_signal_connect(GTK_OBJECT(frdp->all), "clicked",
+ GTK_SIGNAL_FUNC(find_replace_cb),
+ GINT_TO_POINTER(FRD_REPLACEALL));
+ }
+
+ /* 'Cancel' button */
+#ifdef HAVE_GTK2
+ tmp = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
+#else
+ tmp = gtk_button_new_with_label(_("Cancel"));
+#endif
+ GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_DEFAULT);
+ gtk_box_pack_end(GTK_BOX(actionarea), tmp, FALSE, FALSE, 0);
+ gtk_signal_connect_object(GTK_OBJECT(tmp),
+ "clicked", GTK_SIGNAL_FUNC(gtk_widget_hide),
+ GTK_OBJECT(frdp->dialog));
+ gtk_signal_connect_object(GTK_OBJECT(frdp->dialog),
+ "delete_event", GTK_SIGNAL_FUNC(gtk_widget_hide_on_delete),
+ GTK_OBJECT(frdp->dialog));
+
+ tmp = gtk_vseparator_new();
+#ifdef HAVE_GTK2
+ gtk_box_pack_end(GTK_BOX(hbox), tmp, FALSE, FALSE, 10);
+#else
+ gtk_box_pack_end(GTK_BOX(hbox), tmp, FALSE, TRUE, 0);
+#endif
+
+#ifndef HAVE_GTK2
+ gtk_widget_grab_focus(frdp->what);
+
+ /* show the frame and realize the frdp->dialog this gives us a window size
+ * request that we'll use to position the window within the boundary of
+ * the mainwin --dbv */
+ gtk_widget_show_all(frame);
+ gui_gtk_position_in_parent(GTK_WIDGET(gui.mainwin),
+ GTK_WIDGET(frdp->dialog), VW_POS_MOUSE);
+ gui_gtk_synch_fonts();
+ gtk_widget_show_all(frdp->dialog);
+#endif
+
+#ifdef HAVE_GTK2
+ /* Suppress automatic show of the unused action area */
+ gtk_widget_hide(GTK_DIALOG(frdp->dialog)->action_area);
+ gtk_widget_show_all(hbox);
+ gtk_widget_show(frdp->dialog);
+#endif
+
+ vim_free(entry_text);
+#ifdef HAVE_GTK2
+ vim_free(conv_buffer);
+#endif
+#undef CONV
+}
+
+ void
+gui_mch_find_dialog(exarg_T *eap)
+{
+ if (gui.in_use)
+ find_replace_dialog_create(eap->arg, FALSE);
+}
+
+ void
+gui_mch_replace_dialog(exarg_T *eap)
+{
+ if (gui.in_use)
+ find_replace_dialog_create(eap->arg, TRUE);
+}
+
+
+#if !defined(HAVE_GTK2) || defined(PROTO)
+/*
+ * Synchronize all gui elements, which are dependant upon the
+ * main text font used. Those are in esp. the find/replace dialogs.
+ * If you don't understand why this should be needed, please try to
+ * search for "pięść" in iso8859-2.
+ *
+ * (<danielk> I converted the comment above to UTF-8 to put
+ * a stopper to the encoding mess. Forgive me :)
+ *
+ * Obsolete with GTK2.
+ */
+ void
+gui_gtk_synch_fonts(void)
+{
+ SharedFindReplace *frdp;
+ int do_replace;
+
+ /* OK this loop is a bit tricky... */
+ for (do_replace = 0; do_replace <= 1; ++do_replace)
+ {
+ frdp = (do_replace) ? (&repl_widgets) : (&find_widgets);
+ if (frdp->dialog)
+ {
+ GtkStyle *style;
+
+ /* synch the font with whats used by the text itself */
+ style = gtk_style_copy(gtk_widget_get_style(frdp->what));
+ gdk_font_unref(style->font);
+# ifdef FEAT_XFONTSET
+ if (gui.fontset != NOFONTSET)
+ style->font = gui.fontset;
+ else
+# endif
+ style->font = gui.norm_font;
+ gdk_font_ref(style->font);
+ gtk_widget_set_style(frdp->what, style);
+ gtk_style_unref(style);
+ if (do_replace)
+ {
+ style = gtk_style_copy(gtk_widget_get_style(frdp->with));
+ gdk_font_unref(style->font);
+# ifdef FEAT_XFONTSET
+ if (gui.fontset != NOFONTSET)
+ style->font = gui.fontset;
+ else
+# endif
+ style->font = gui.norm_font;
+ gdk_font_ref(style->font);
+ gtk_widget_set_style(frdp->with, style);
+ gtk_style_unref(style);
+ }
+ }
+ }
+}
+#endif /* !HAVE_GTK2 */
+
+
+/*
+ * Callback for actions of the find and replace dialogs
+ */
+/*ARGSUSED*/
+ static void
+find_replace_cb(GtkWidget *widget, gpointer data)
+{
+ int flags;
+ char_u *find_text;
+ char_u *repl_text;
+ gboolean direction_down;
+ SharedFindReplace *sfr;
+ int rc;
+
+ flags = (int)(long)data; /* avoid a lint warning here */
+
+ /* Get the search/replace strings from the dialog */
+ if (flags == FRD_FINDNEXT)
+ {
+ repl_text = NULL;
+ sfr = &find_widgets;
+ }
+ else
+ {
+ repl_text = (char_u *)gtk_entry_get_text(GTK_ENTRY(repl_widgets.with));
+ sfr = &repl_widgets;
+ }
+
+ find_text = (char_u *)gtk_entry_get_text(GTK_ENTRY(sfr->what));
+ direction_down = GTK_TOGGLE_BUTTON(sfr->down)->active;
+
+ if (GTK_TOGGLE_BUTTON(sfr->wword)->active)
+ flags |= FRD_WHOLE_WORD;
+ if (GTK_TOGGLE_BUTTON(sfr->mcase)->active)
+ flags |= FRD_MATCH_CASE;
+
+#ifdef HAVE_GTK2
+ repl_text = CONVERT_FROM_UTF8(repl_text);
+ find_text = CONVERT_FROM_UTF8(find_text);
+#endif
+ rc = gui_do_findrepl(flags, find_text, repl_text, direction_down);
+#ifdef HAVE_GTK2
+ CONVERT_FROM_UTF8_FREE(repl_text);
+ CONVERT_FROM_UTF8_FREE(find_text);
+#endif
+
+ if (rc && gtk_main_level() > 0)
+ gtk_main_quit(); /* make sure cmd will be handled immediately */
+}
+
+/* our usual callback function */
+/*ARGSUSED*/
+ static void
+entry_activate_cb(GtkWidget *widget, gpointer data)
+{
+ gtk_widget_grab_focus(GTK_WIDGET(data));
+}
+
+/*
+ * Syncing the find/replace dialogs on the fly is utterly useless crack,
+ * and causes nothing but problems. Please tell me a use case for which
+ * you'd need both a find dialog and a find/replace one at the same time,
+ * without being able to actually use them separately since they're syncing
+ * all the time. I don't think it's worthwhile to fix this nonsense,
+ * particularly evil incarnation of braindeadness, whatever; I'd much rather
+ * see it extinguished from this planet. Thanks for listening. Sorry.
+ */
+ static void
+entry_changed_cb(GtkWidget * entry, GtkWidget * dialog)
+{
+ const gchar *entry_text;
+ gboolean nonempty;
+
+ entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+
+ if (!entry_text)
+ return; /* shouldn't happen */
+
+ nonempty = (entry_text[0] != '\0');
+
+ if (dialog == find_widgets.dialog)
+ {
+ gtk_widget_set_sensitive(find_widgets.find, nonempty);
+ }
+
+ if (dialog == repl_widgets.dialog)
+ {
+ gtk_widget_set_sensitive(repl_widgets.find, nonempty);
+ gtk_widget_set_sensitive(repl_widgets.replace, nonempty);
+ gtk_widget_set_sensitive(repl_widgets.all, nonempty);
+ }
+}
+
+/*
+ * ":helpfind"
+ */
+/*ARGSUSED*/
+ void
+ex_helpfind(eap)
+ exarg_T *eap;
+{
+ /* This will fail when menus are not loaded. Well, it's only for
+ * backwards compatibility anyway. */
+ do_cmdline_cmd((char_u *)"emenu ToolBar.FindHelp");
+}
+
+#if !defined(HAVE_GTK2) || defined(PROTO) /* Crack crack crack. Brrrr. */
+
+/* gui_gtk_position_in_parent
+ *
+ * this function causes a child window to be placed within the boundary of
+ * the parent (mainwin) window.
+ *
+ * you can specify where the window will be positioned by the third argument
+ * (defined in gui.h):
+ * VW_POS_CENTER at center of parent window
+ * VW_POS_MOUSE center of child at mouse position
+ * VW_POS_TOP_CENTER top of child at top of parent centered
+ * horizontally about the mouse.
+ *
+ * NOTE: for this function to act as desired the child window must have a
+ * window size requested. this can be accomplished by packing/placing
+ * child widgets onto a gtk_frame widget rather than the gtk_window
+ * widget...
+ *
+ * brent -- dbv
+ */
+ void
+gui_gtk_position_in_parent(
+ GtkWidget *parent,
+ GtkWidget *child,
+ gui_win_pos_T where)
+{
+ GtkRequisition c_size;
+ gint xPm, yPm;
+ gint xP, yP, wP, hP, pos_x, pos_y;
+
+ /* make sure the child widget is set up then get its size. */
+ gtk_widget_size_request(child, &c_size);
+
+ /* get origin and size of parent window */
+ gdk_window_get_origin((GdkWindow *)(parent->window), &xP, &yP);
+ gdk_window_get_size((GdkWindow *)(parent->window), &wP, &hP);
+
+ if (c_size.width > wP || c_size.height > hP)
+ {
+ /* doh! maybe the user should consider giving gVim a little more
+ * screen real estate */
+ gtk_widget_set_uposition(child , xP + 2 , yP + 2);
+ return;
+ }
+
+ if (where == VW_POS_MOUSE)
+ {
+ /* position window at mouse pointer */
+ gtk_widget_get_pointer(parent, &xPm, &yPm);
+ pos_x = xP + xPm - (c_size.width) / 2;
+ pos_y = yP + yPm - (c_size.height) / 2;
+ }
+ else
+ {
+ /* set child x origin so it is in center of Vim window */
+ pos_x = xP + (wP - c_size.width) / 2;
+
+ if (where == VW_POS_TOP_CENTER)
+ pos_y = yP + 2;
+ else
+ /* where == VW_POS_CENTER */
+ pos_y = yP + (hP - c_size.height) / 2;
+ }
+
+ /* now, make sure the window will be inside the Vim window... */
+ if (pos_x < xP)
+ pos_x = xP + 2;
+ if (pos_y < yP)
+ pos_y = yP + 2;
+ if ((pos_x + c_size.width) > (wP + xP))
+ pos_x = xP + wP - c_size.width - 2;
+ /* Assume 'guiheadroom' indicates the title bar height... */
+ if ((pos_y + c_size.height + p_ghr / 2) > (hP + yP))
+ pos_y = yP + hP - c_size.height - 2 - p_ghr / 2;
+
+ gtk_widget_set_uposition(child, pos_x, pos_y);
+}
+
+#endif /* !HAVE_GTK2 */
+
diff --git a/src/gui_gtk_f.c b/src/gui_gtk_f.c
new file mode 100644
index 000000000..2cb82d646
--- /dev/null
+++ b/src/gui_gtk_f.c
@@ -0,0 +1,942 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * (C) 1998,1999 by Marcin Dalecki <dalecki@cs.net.pl>
+ *
+ * "I'm a one-man software company. If you have anything UNIX, net or
+ * embedded systems related, which seems to cause some serious trouble for
+ * your's in-house developers, maybe we need to talk badly with each other
+ * :-) <dalecki@cs.net.pl> (My native language is polish and I speak
+ * native grade german too. I'm living in Göttingen.de.)
+ * --mdcki"
+ *
+ * Support for GTK+ 2 was added by:
+ *
+ * (C) 2002,2003 Jason Hildebrand <jason@peaceworks.ca>
+ * Daniel Elstner <daniel.elstner@gmx.net>
+ *
+ * This is a special purspose container widget, which manages arbitrary childs
+ * at arbitrary positions width arbitrary sizes. This finally puts an end on
+ * our resizement problems with which we where struggling for such a long time.
+ */
+
+#include "vim.h"
+#include <gtk/gtk.h> /* without this it compiles, but gives errors at
+ runtime! */
+#include "gui_gtk_f.h"
+#include <gtk/gtksignal.h>
+#ifdef WIN3264
+# include <gdk/gdkwin32.h>
+#else
+# include <gdk/gdkx.h>
+#endif
+
+typedef struct _GtkFormChild GtkFormChild;
+
+struct _GtkFormChild
+{
+ GtkWidget *widget;
+ GdkWindow *window;
+ gint x; /* relative subwidget x position */
+ gint y; /* relative subwidget y position */
+ gint mapped;
+};
+
+
+static void gtk_form_class_init(GtkFormClass *klass);
+static void gtk_form_init(GtkForm *form);
+
+static void gtk_form_realize(GtkWidget *widget);
+static void gtk_form_unrealize(GtkWidget *widget);
+static void gtk_form_map(GtkWidget *widget);
+static void gtk_form_size_request(GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_form_size_allocate(GtkWidget *widget,
+ GtkAllocation *allocation);
+#ifndef HAVE_GTK2 /* this isn't needed in gtk2 */
+static void gtk_form_draw(GtkWidget *widget,
+ GdkRectangle *area);
+#endif
+static gint gtk_form_expose(GtkWidget *widget,
+ GdkEventExpose *event);
+
+static void gtk_form_remove(GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_form_forall(GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
+
+static void gtk_form_attach_child_window(GtkForm *form,
+ GtkFormChild *child);
+static void gtk_form_realize_child(GtkForm *form,
+ GtkFormChild *child);
+static void gtk_form_position_child(GtkForm *form,
+ GtkFormChild *child,
+ gboolean force_allocate);
+static void gtk_form_position_children(GtkForm *form);
+
+static GdkFilterReturn gtk_form_filter(GdkXEvent *gdk_xevent,
+ GdkEvent *event,
+ gpointer data);
+static GdkFilterReturn gtk_form_main_filter(GdkXEvent *gdk_xevent,
+ GdkEvent *event,
+ gpointer data);
+
+static void gtk_form_set_static_gravity(GdkWindow *window,
+ gboolean use_static);
+
+static void gtk_form_send_configure(GtkForm *form);
+
+static void gtk_form_child_map(GtkWidget *widget, gpointer user_data);
+static void gtk_form_child_unmap(GtkWidget *widget, gpointer user_data);
+
+static GtkWidgetClass *parent_class = NULL;
+
+/* Public interface
+ */
+
+ GtkWidget *
+gtk_form_new(void)
+{
+ GtkForm *form;
+
+ form = gtk_type_new(gtk_form_get_type());
+
+ return GTK_WIDGET(form);
+}
+
+ void
+gtk_form_put(GtkForm *form,
+ GtkWidget *child_widget,
+ gint x,
+ gint y)
+{
+ GtkFormChild *child;
+
+ g_return_if_fail(GTK_IS_FORM(form));
+
+ child = g_new(GtkFormChild, 1);
+
+ child->widget = child_widget;
+ child->window = NULL;
+ child->x = x;
+ child->y = y;
+ child->widget->requisition.width = 0;
+ child->widget->requisition.height = 0;
+ child->mapped = FALSE;
+
+ form->children = g_list_append(form->children, child);
+
+ /* child->window must be created and attached to the widget _before_
+ * it has been realized, or else things will break with GTK2. Note
+ * that gtk_widget_set_parent() realizes the widget if it's visible
+ * and its parent is mapped.
+ */
+ if (GTK_WIDGET_REALIZED(form))
+ gtk_form_attach_child_window(form, child);
+
+ gtk_widget_set_parent(child_widget, GTK_WIDGET(form));
+ gtk_widget_size_request(child->widget, NULL);
+
+ if (GTK_WIDGET_REALIZED(form) && !GTK_WIDGET_REALIZED(child_widget))
+ gtk_form_realize_child(form, child);
+
+ gtk_form_position_child(form, child, TRUE);
+}
+
+ void
+gtk_form_move(GtkForm *form,
+ GtkWidget *child_widget,
+ gint x,
+ gint y)
+{
+ GList *tmp_list;
+ GtkFormChild *child;
+
+ g_return_if_fail(GTK_IS_FORM(form));
+
+ for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
+ {
+ child = tmp_list->data;
+ if (child->widget == child_widget)
+ {
+ child->x = x;
+ child->y = y;
+
+ gtk_form_position_child(form, child, TRUE);
+ return;
+ }
+ }
+}
+
+ void
+gtk_form_set_size(GtkForm *form, guint width, guint height)
+{
+ g_return_if_fail(GTK_IS_FORM(form));
+
+ /* prevent unneccessary calls */
+ if (form->width == width && form->height == height)
+ return;
+ form->width = width;
+ form->height = height;
+
+ /* signal the change */
+#ifdef HAVE_GTK2
+ gtk_widget_queue_resize(gtk_widget_get_parent(GTK_WIDGET(form)));
+#else
+ gtk_container_queue_resize(GTK_CONTAINER(GTK_WIDGET(form)->parent));
+#endif
+}
+
+ void
+gtk_form_freeze(GtkForm *form)
+{
+ g_return_if_fail(GTK_IS_FORM(form));
+
+ ++form->freeze_count;
+}
+
+ void
+gtk_form_thaw(GtkForm *form)
+{
+ g_return_if_fail(GTK_IS_FORM(form));
+
+ if (form->freeze_count)
+ {
+ if (!(--form->freeze_count))
+ {
+ gtk_form_position_children(form);
+#ifdef HAVE_GTK2
+ gtk_widget_queue_draw(GTK_WIDGET(form));
+#else
+ gtk_widget_draw(GTK_WIDGET(form), NULL);
+#endif
+ }
+ }
+}
+
+/* Basic Object handling procedures
+ */
+ GtkType
+gtk_form_get_type(void)
+{
+ static GtkType form_type = 0;
+
+ if (!form_type)
+ {
+ GtkTypeInfo form_info =
+ {
+ "GtkForm",
+ sizeof(GtkForm),
+ sizeof(GtkFormClass),
+ (GtkClassInitFunc) gtk_form_class_init,
+ (GtkObjectInitFunc) gtk_form_init
+ };
+
+ form_type = gtk_type_unique(GTK_TYPE_CONTAINER, &form_info);
+ }
+ return form_type;
+}
+
+ static void
+gtk_form_class_init(GtkFormClass *klass)
+{
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ widget_class = (GtkWidgetClass *) klass;
+ container_class = (GtkContainerClass *) klass;
+
+ parent_class = gtk_type_class(gtk_container_get_type());
+
+ widget_class->realize = gtk_form_realize;
+ widget_class->unrealize = gtk_form_unrealize;
+ widget_class->map = gtk_form_map;
+ widget_class->size_request = gtk_form_size_request;
+ widget_class->size_allocate = gtk_form_size_allocate;
+#ifndef HAVE_GTK2 /* not needed for GTK2 */
+ widget_class->draw = gtk_form_draw;
+#endif
+ widget_class->expose_event = gtk_form_expose;
+
+ container_class->remove = gtk_form_remove;
+ container_class->forall = gtk_form_forall;
+}
+
+ static void
+gtk_form_init(GtkForm *form)
+{
+ form->children = NULL;
+
+ form->width = 1;
+ form->height = 1;
+
+ form->bin_window = NULL;
+
+ form->configure_serial = 0;
+ form->visibility = GDK_VISIBILITY_PARTIAL;
+
+ form->freeze_count = 0;
+}
+
+/*
+ * Widget methods
+ */
+
+ static void
+gtk_form_realize(GtkWidget *widget)
+{
+ GList *tmp_list;
+ GtkForm *form;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail(GTK_IS_FORM(widget));
+
+ form = GTK_FORM(widget);
+ GTK_WIDGET_SET_FLAGS(form, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual(widget);
+ attributes.colormap = gtk_widget_get_colormap(widget);
+ attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new(gtk_widget_get_parent_window(widget),
+ &attributes, attributes_mask);
+ gdk_window_set_user_data(widget->window, widget);
+
+ attributes.x = 0;
+ attributes.y = 0;
+ attributes.event_mask = gtk_widget_get_events(widget);
+
+ form->bin_window = gdk_window_new(widget->window,
+ &attributes, attributes_mask);
+ gdk_window_set_user_data(form->bin_window, widget);
+
+ gtk_form_set_static_gravity(form->bin_window, TRUE);
+
+ widget->style = gtk_style_attach(widget->style, widget->window);
+ gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL);
+ gtk_style_set_background(widget->style, form->bin_window, GTK_STATE_NORMAL);
+
+ gdk_window_add_filter(widget->window, gtk_form_main_filter, form);
+ gdk_window_add_filter(form->bin_window, gtk_form_filter, form);
+
+ for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
+ {
+ GtkFormChild *child = tmp_list->data;
+
+ gtk_form_attach_child_window(form, child);
+
+ if (GTK_WIDGET_VISIBLE(child->widget))
+ gtk_form_realize_child(form, child);
+ }
+}
+
+
+/* After reading the documentation at
+ * http://developer.gnome.org/doc/API/2.0/gtk/gtk-changes-2-0.html
+ * I think it should be possible to remove this function when compiling
+ * against gtk-2.0. It doesn't seem to cause problems, though.
+ *
+ * Well, I reckon at least the gdk_window_show(form->bin_window)
+ * is necessary. GtkForm is anything but a usual container widget.
+ */
+ static void
+gtk_form_map(GtkWidget *widget)
+{
+ GList *tmp_list;
+ GtkForm *form;
+
+ g_return_if_fail(GTK_IS_FORM(widget));
+
+ form = GTK_FORM(widget);
+
+ GTK_WIDGET_SET_FLAGS(widget, GTK_MAPPED);
+
+ gdk_window_show(widget->window);
+ gdk_window_show(form->bin_window);
+
+ for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
+ {
+ GtkFormChild *child = tmp_list->data;
+
+ if (GTK_WIDGET_VISIBLE(child->widget)
+ && !GTK_WIDGET_MAPPED(child->widget))
+ gtk_widget_map(child->widget);
+ }
+}
+
+ static void
+gtk_form_unrealize(GtkWidget *widget)
+{
+ GList *tmp_list;
+ GtkForm *form;
+
+ g_return_if_fail(GTK_IS_FORM(widget));
+
+ form = GTK_FORM(widget);
+
+ tmp_list = form->children;
+
+ gdk_window_set_user_data(form->bin_window, NULL);
+ gdk_window_destroy(form->bin_window);
+ form->bin_window = NULL;
+
+ while (tmp_list)
+ {
+ GtkFormChild *child = tmp_list->data;
+
+ if (child->window != NULL)
+ {
+ gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
+ GTK_SIGNAL_FUNC(gtk_form_child_map),
+ child);
+ gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
+ GTK_SIGNAL_FUNC(gtk_form_child_unmap),
+ child);
+
+ gdk_window_set_user_data(child->window, NULL);
+ gdk_window_destroy(child->window);
+
+ child->window = NULL;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+#ifndef HAVE_GTK2
+ static void
+gtk_form_draw(GtkWidget *widget, GdkRectangle *area)
+{
+ GtkForm *form;
+ GList *children;
+ GtkFormChild *child;
+ GdkRectangle child_area;
+
+ g_return_if_fail(GTK_IS_FORM(widget));
+
+ if (GTK_WIDGET_DRAWABLE(widget))
+ {
+ form = GTK_FORM(widget);
+
+ children = form->children;
+
+ while (children)
+ {
+ child = children->data;
+
+ if (GTK_WIDGET_DRAWABLE(child->widget)
+ && gtk_widget_intersect(child->widget, area, &child_area))
+ gtk_widget_draw(child->widget, &child_area);
+
+ children = children->next;
+ }
+ }
+}
+#endif /* !HAVE_GTK2 */
+
+ static void
+gtk_form_size_request(GtkWidget *widget, GtkRequisition *requisition)
+{
+ GList *tmp_list;
+ GtkForm *form;
+
+ g_return_if_fail(GTK_IS_FORM(widget));
+
+ form = GTK_FORM(widget);
+
+ requisition->width = form->width;
+ requisition->height = form->height;
+
+ tmp_list = form->children;
+
+ while (tmp_list)
+ {
+ GtkFormChild *child = tmp_list->data;
+ gtk_widget_size_request(child->widget, NULL);
+ tmp_list = tmp_list->next;
+ }
+}
+
+ static void
+gtk_form_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
+{
+ GList *tmp_list;
+ GtkForm *form;
+ gboolean need_reposition;
+
+ g_return_if_fail(GTK_IS_FORM(widget));
+
+ if (widget->allocation.x == allocation->x
+ && widget->allocation.y == allocation->y
+ && widget->allocation.width == allocation->width
+ && widget->allocation.height == allocation->height)
+ return;
+
+ need_reposition = widget->allocation.width != allocation->width
+ || widget->allocation.height != allocation->height;
+ form = GTK_FORM(widget);
+
+ if (need_reposition)
+ {
+ tmp_list = form->children;
+
+ while (tmp_list)
+ {
+ GtkFormChild *child = tmp_list->data;
+ gtk_form_position_child(form, child, TRUE);
+
+ tmp_list = tmp_list->next;
+ }
+ }
+
+ if (GTK_WIDGET_REALIZED(widget))
+ {
+ gdk_window_move_resize(widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+ gdk_window_move_resize(GTK_FORM(widget)->bin_window,
+ 0, 0,
+ allocation->width, allocation->height);
+ }
+ widget->allocation = *allocation;
+ if (need_reposition)
+ gtk_form_send_configure(form);
+}
+
+ static gint
+gtk_form_expose(GtkWidget *widget, GdkEventExpose *event)
+{
+ GList *tmp_list;
+ GtkForm *form;
+
+ g_return_val_if_fail(GTK_IS_FORM(widget), FALSE);
+
+ form = GTK_FORM(widget);
+
+ if (event->window == form->bin_window)
+ return FALSE;
+
+ for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
+ {
+#ifdef HAVE_GTK2
+ GtkFormChild *formchild = tmp_list->data;
+ GtkWidget *child = formchild->widget;
+ /*
+ * The following chunk of code is taken from gtkcontainer.c. The
+ * gtk1.x code synthesized expose events directly on the child widgets,
+ * which can't be done in gtk2
+ */
+ if (GTK_WIDGET_DRAWABLE(child) && GTK_WIDGET_NO_WINDOW(child)
+ && child->window == event->window)
+ {
+ GdkEventExpose child_event;
+ child_event = *event;
+
+ child_event.region = gtk_widget_region_intersect(child, event->region);
+ if (!gdk_region_empty(child_event.region))
+ {
+ gdk_region_get_clipbox(child_event.region, &child_event.area);
+ gtk_widget_send_expose(child, (GdkEvent *)&child_event);
+ }
+ }
+#else /* !HAVE_GTK2 */
+ GtkFormChild *child = tmp_list->data;
+
+ if (event->window == child->window)
+ return gtk_widget_event(child->widget, (GdkEvent *) event);
+#endif /* !HAVE_GTK2 */
+ }
+
+ return FALSE;
+}
+
+/* Container method
+ */
+ static void
+gtk_form_remove(GtkContainer *container, GtkWidget *widget)
+{
+ GList *tmp_list;
+ GtkForm *form;
+ GtkFormChild *child = NULL; /* init for gcc */
+
+ g_return_if_fail(GTK_IS_FORM(container));
+
+ form = GTK_FORM(container);
+
+ tmp_list = form->children;
+ while (tmp_list)
+ {
+ child = tmp_list->data;
+ if (child->widget == widget)
+ break;
+ tmp_list = tmp_list->next;
+ }
+
+ if (tmp_list)
+ {
+ if (child->window)
+ {
+ gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
+ GTK_SIGNAL_FUNC(&gtk_form_child_map), child);
+ gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
+ GTK_SIGNAL_FUNC(&gtk_form_child_unmap), child);
+
+ /* FIXME: This will cause problems for reparenting NO_WINDOW
+ * widgets out of a GtkForm
+ */
+ gdk_window_set_user_data(child->window, NULL);
+ gdk_window_destroy(child->window);
+ }
+ gtk_widget_unparent(widget);
+
+ form->children = g_list_remove_link(form->children, tmp_list);
+ g_list_free_1(tmp_list);
+ g_free(child);
+ }
+}
+
+/*ARGSUSED1*/
+ static void
+gtk_form_forall(GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkForm *form;
+ GtkFormChild *child;
+ GList *tmp_list;
+
+ g_return_if_fail(GTK_IS_FORM(container));
+ g_return_if_fail(callback != NULL);
+
+ form = GTK_FORM(container);
+
+ tmp_list = form->children;
+ while (tmp_list)
+ {
+ child = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ (*callback) (child->widget, callback_data);
+ }
+}
+
+/* Operations on children
+ */
+
+ static void
+gtk_form_attach_child_window(GtkForm *form, GtkFormChild *child)
+{
+ if (child->window != NULL)
+ return; /* been there, done that */
+
+ if (GTK_WIDGET_NO_WINDOW(child->widget))
+ {
+ GtkWidget *widget;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ widget = GTK_WIDGET(form);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = child->x;
+ attributes.y = child->y;
+ attributes.width = child->widget->requisition.width;
+ attributes.height = child->widget->requisition.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual(widget);
+ attributes.colormap = gtk_widget_get_colormap(widget);
+ attributes.event_mask = GDK_EXPOSURE_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ child->window = gdk_window_new(form->bin_window,
+ &attributes, attributes_mask);
+ gdk_window_set_user_data(child->window, widget);
+
+ gtk_style_set_background(widget->style,
+ child->window,
+ GTK_STATE_NORMAL);
+
+ gtk_widget_set_parent_window(child->widget, child->window);
+ gtk_form_set_static_gravity(child->window, TRUE);
+ /*
+ * Install signal handlers to map/unmap child->window
+ * alongside with the actual widget.
+ */
+ gtk_signal_connect(GTK_OBJECT(child->widget), "map",
+ GTK_SIGNAL_FUNC(&gtk_form_child_map), child);
+ gtk_signal_connect(GTK_OBJECT(child->widget), "unmap",
+ GTK_SIGNAL_FUNC(&gtk_form_child_unmap), child);
+ }
+ else if (!GTK_WIDGET_REALIZED(child->widget))
+ {
+ gtk_widget_set_parent_window(child->widget, form->bin_window);
+ }
+}
+
+ static void
+gtk_form_realize_child(GtkForm *form, GtkFormChild *child)
+{
+ gtk_form_attach_child_window(form, child);
+ gtk_widget_realize(child->widget);
+
+ if (child->window == NULL) /* might be already set, see above */
+ gtk_form_set_static_gravity(child->widget->window, TRUE);
+}
+
+ static void
+gtk_form_position_child(GtkForm *form, GtkFormChild *child,
+ gboolean force_allocate)
+{
+ gint x;
+ gint y;
+
+ x = child->x;
+ y = child->y;
+
+ if ((x >= G_MINSHORT) && (x <= G_MAXSHORT) &&
+ (y >= G_MINSHORT) && (y <= G_MAXSHORT))
+ {
+ if (!child->mapped)
+ {
+ if (GTK_WIDGET_MAPPED(form) && GTK_WIDGET_VISIBLE(child->widget))
+ {
+ if (!GTK_WIDGET_MAPPED(child->widget))
+ gtk_widget_map(child->widget);
+
+ child->mapped = TRUE;
+ force_allocate = TRUE;
+ }
+ }
+
+ if (force_allocate)
+ {
+ GtkAllocation allocation;
+
+ if (GTK_WIDGET_NO_WINDOW(child->widget))
+ {
+ if (child->window)
+ {
+ gdk_window_move_resize(child->window,
+ x, y,
+ child->widget->requisition.width,
+ child->widget->requisition.height);
+ }
+
+ allocation.x = 0;
+ allocation.y = 0;
+ }
+ else
+ {
+ allocation.x = x;
+ allocation.y = y;
+ }
+
+ allocation.width = child->widget->requisition.width;
+ allocation.height = child->widget->requisition.height;
+
+ gtk_widget_size_allocate(child->widget, &allocation);
+ }
+ }
+ else
+ {
+ if (child->mapped)
+ {
+ child->mapped = FALSE;
+
+ if (GTK_WIDGET_MAPPED(child->widget))
+ gtk_widget_unmap(child->widget);
+ }
+ }
+}
+
+ static void
+gtk_form_position_children(GtkForm *form)
+{
+ GList *tmp_list;
+
+ for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
+ gtk_form_position_child(form, tmp_list->data, FALSE);
+}
+
+/* Callbacks */
+
+/* The main event filter. Actually, we probably don't really need
+ * to install this as a filter at all, since we are calling it
+ * directly above in the expose-handling hack.
+ *
+ * This routine identifies expose events that are generated when
+ * we've temporarily moved the bin_window_origin, and translates
+ * them or discards them, depending on whether we are obscured
+ * or not.
+ */
+/*ARGSUSED1*/
+ static GdkFilterReturn
+gtk_form_filter(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
+{
+ XEvent *xevent;
+ GtkForm *form;
+
+ xevent = (XEvent *) gdk_xevent;
+ form = GTK_FORM(data);
+
+ switch (xevent->type)
+ {
+ case Expose:
+ if (xevent->xexpose.serial == form->configure_serial)
+ {
+ if (form->visibility == GDK_VISIBILITY_UNOBSCURED)
+ return GDK_FILTER_REMOVE;
+ else
+ break;
+ }
+ break;
+
+ case ConfigureNotify:
+ if ((xevent->xconfigure.x != 0) || (xevent->xconfigure.y != 0))
+ form->configure_serial = xevent->xconfigure.serial;
+ break;
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+/* Although GDK does have a GDK_VISIBILITY_NOTIFY event,
+ * there is no corresponding event in GTK, so we have
+ * to get the events from a filter
+ */
+/*ARGSUSED1*/
+ static GdkFilterReturn
+gtk_form_main_filter(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
+{
+ XEvent *xevent;
+ GtkForm *form;
+
+ xevent = (XEvent *) gdk_xevent;
+ form = GTK_FORM(data);
+
+ if (xevent->type == VisibilityNotify)
+ {
+ switch (xevent->xvisibility.state)
+ {
+ case VisibilityFullyObscured:
+ form->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
+ break;
+
+ case VisibilityPartiallyObscured:
+ form->visibility = GDK_VISIBILITY_PARTIAL;
+ break;
+
+ case VisibilityUnobscured:
+ form->visibility = GDK_VISIBILITY_UNOBSCURED;
+ break;
+ }
+
+ return GDK_FILTER_REMOVE;
+ }
+ return GDK_FILTER_CONTINUE;
+}
+
+/* Routines to set the window gravity, and check whether it is
+ * functional. Extra capabilities need to be added to GDK, so
+ * we don't have to use Xlib here.
+ */
+ static void
+gtk_form_set_static_gravity(GdkWindow *window, gboolean use_static)
+{
+#ifdef HAVE_GTK2
+ gboolean static_gravity_supported;
+
+ static_gravity_supported = gdk_window_set_static_gravities(window,
+ use_static);
+ g_return_if_fail(static_gravity_supported);
+#else
+ XSetWindowAttributes xattributes;
+
+ xattributes.win_gravity = (use_static) ? StaticGravity : NorthWestGravity;
+ xattributes.bit_gravity = (use_static) ? StaticGravity : NorthWestGravity;
+
+ XChangeWindowAttributes(GDK_WINDOW_XDISPLAY(window),
+ GDK_WINDOW_XWINDOW(window),
+ CWBitGravity | CWWinGravity,
+ &xattributes);
+#endif
+}
+
+ void
+gtk_form_move_resize(GtkForm *form, GtkWidget *widget,
+ gint x, gint y, gint w, gint h)
+{
+ widget->requisition.width = w;
+ widget->requisition.height = h;
+
+ gtk_form_move(form, widget, x, y);
+}
+
+ static void
+gtk_form_send_configure(GtkForm *form)
+{
+ GtkWidget *widget;
+ GdkEventConfigure event;
+
+ widget = GTK_WIDGET(form);
+
+ event.type = GDK_CONFIGURE;
+ event.window = widget->window;
+ event.x = widget->allocation.x;
+ event.y = widget->allocation.y;
+ event.width = widget->allocation.width;
+ event.height = widget->allocation.height;
+
+#ifdef HAVE_GTK2
+ gtk_main_do_event((GdkEvent*)&event);
+#else
+ gtk_widget_event(widget, (GdkEvent*)&event);
+#endif
+}
+
+/*ARGSUSED0*/
+ static void
+gtk_form_child_map(GtkWidget *widget, gpointer user_data)
+{
+ GtkFormChild *child;
+
+ child = (GtkFormChild *)user_data;
+
+ child->mapped = TRUE;
+ gdk_window_show(child->window);
+}
+
+/*ARGSUSED0*/
+ static void
+gtk_form_child_unmap(GtkWidget *widget, gpointer user_data)
+{
+ GtkFormChild *child;
+
+ child = (GtkFormChild *)user_data;
+
+ child->mapped = FALSE;
+ gdk_window_hide(child->window);
+}
+
diff --git a/src/gui_gtk_f.h b/src/gui_gtk_f.h
new file mode 100644
index 000000000..06c7ecdf7
--- /dev/null
+++ b/src/gui_gtk_f.h
@@ -0,0 +1,83 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+#ifndef __GTK_FORM_H__
+#define __GTK_FORM_H__
+
+#ifdef VMS
+# include "gui_gtk_vms.h"
+#endif
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GTK_TYPE_FORM (gtk_form_get_type ())
+#define GTK_FORM(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_FORM, GtkForm))
+#define GTK_FORM_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_FORM, GtkFormClass))
+#define GTK_IS_FORM(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_FORM))
+#define GTK_IS_FORM_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FORM))
+
+
+typedef struct _GtkForm GtkForm;
+typedef struct _GtkFormClass GtkFormClass;
+
+struct _GtkForm
+{
+ GtkContainer container;
+
+ GList *children;
+
+ guint width;
+ guint height;
+
+ GdkWindow *bin_window;
+
+ GdkVisibilityState visibility;
+ gulong configure_serial;
+
+ gint freeze_count;
+};
+
+struct _GtkFormClass
+{
+ GtkContainerClass parent_class;
+};
+
+GtkType gtk_form_get_type(void);
+
+GtkWidget *gtk_form_new(void);
+
+void gtk_form_put(GtkForm * form, GtkWidget * widget,
+ gint x, gint y);
+
+void gtk_form_move(GtkForm *form, GtkWidget * widget,
+ gint x, gint y);
+
+void gtk_form_move_resize(GtkForm * form, GtkWidget * widget,
+ gint x, gint y,
+ gint w, gint h);
+void gtk_form_set_size(GtkForm * form, guint width, guint height);
+
+/* These disable and enable moving and repainting respectively. If you
+ * want to update the layout's offsets but do not want it to repaint
+ * itself, you should use these functions.
+ */
+
+void gtk_form_freeze(GtkForm *form);
+void gtk_form_thaw(GtkForm *form);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __GTK_FORM_H__ */
diff --git a/src/gui_gtk_vms.h b/src/gui_gtk_vms.h
new file mode 100644
index 000000000..e88728f98
--- /dev/null
+++ b/src/gui_gtk_vms.h
@@ -0,0 +1,734 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributedi.
+ *
+ * File MOTIF_REDEFINES.H originally delivers together with
+ * OpenVMS Porting Library
+ * http://www.openvms.compaq.com/openvms/products/ips/porting.html
+ *
+ * This file has been modified for Vim development.
+ * Original file contains just defines that GTK for OpenVMS uses,
+ * but not all functions that DECW library has. Therefore it has been expanded
+ * with necessary defines for Vim on OpenVMS with GTK GUI.
+ *
+ * Zoltan Arpadffy <arpadffy@polarhome.com>
+ */
+
+/*
+ *************************************************************************
+ * *
+ * Copyright 2000 Compaq Computer Corporation *
+ * *
+ * COMPAQ Registered in U.S. Patent and Trademark Office. *
+ * *
+ *************************************************************************
+ * IMPORTANT: Carefully read the License Terms below before *
+ * proceeding. By use of these materials you agree to these terms. *
+ * If you do not agree to these terms, you may not use this software or *
+ * the accompanying documentation. *
+ *************************************************************************
+ * LICENSE TERMS *
+ * 1. GRANT *
+ * Compaq Computer Corporation ("COMPAQ") grants you the right to use, *
+ * modify, and distribute the following source code (the "Software") *
+ * on any number of computers. You may use the Software as part of *
+ * creating a software program or product intended for commercial or *
+ * non-commercial distribution in machine-readable source code, binary, *
+ * or executable formats. You may distribute the Software as *
+ * machine-readable source code provided this license is not removed *
+ * from the Software and any modifications are conspicuously indicated. *
+ * 2. COPYRIGHT *
+ * The Software is owned by COMPAQ and its suppliers and is protected by *
+ * copyright laws and international treaties. Your use of the Software *
+ * and associated documentation is subject to the applicable copyright *
+ * laws and the express rights and restrictions of these terms. *
+ * 3. RESTRICTIONS *
+ * You may not remove any copyright, trademark, or other proprietary *
+ * notices from the Software or the associated documentation. *
+ * You are responsible for compliance with all applicable export or *
+ * re-export control laws and regulations if you export the Software. *
+ * This license is governed by and is to be construed under the laws *
+ * of the State of Texas. *
+ * *
+ * DISCLAIMER OF WARRANTY AND LIABILITY *
+ * Compaq shall not be liable for technical or editorial errors or *
+ * omissions contained herein. The information contained herein is *
+ * subject to change without notice. *
+ * *
+ * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. *
+ * THE ENTIRE RISK ARISING OUT OF THE USE OF THIS SOFTWARE REMAINS WITH *
+ * RECIPIENT. IN NO EVENT SHALL COMPAQ BE LIABLE FOR ANY DIRECT, *
+ * CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE OR OTHER DAMAGES *
+ * WHATSOEVER (INCLUDING WITHOUT LIMITATION DAMAGES FOR LOSS OF BUSINESS *
+ * PROFITS, BUSINESS INTERRUPTION, OR LOSS OF BUSINESS INFORMATION), *
+ * EVEN IF COMPAQ HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES *
+ * AND WHETHER IN AN ACTION OF CONTRACT OR TORT INCLUDING NEGLIGENCE. *
+ * *
+ * If you have any questions concerning this license, please contact: *
+ * Compaq Computer Corporation, Software Business Practices, ZKO1-2/D22, *
+ * 110 Spit Brook Road, Nashua, NH. 03062-2698. *
+ * *
+ *************************************************************************
+ */
+
+/* INTRINSIC.H omits proto if XtFree is defined */
+/* VMS_BEGIN_C_PLUS_PLUS */
+extern void XtFree(char*);
+/* VMS_END_C_PLUS_PLUS */
+
+#define _XRegisterFilterByType _XREGISTERFILTERBYTYPE
+
+#define XAllocClassHint XALLOCCLASSHINT
+#define XAllocColor XALLOCCOLOR
+#define XAllocColorCells XALLOCCOLORCELLS
+#define XAllocSizeHints XALLOCSIZEHINTS
+#define XAllocWMHints XALLOCWMHINTS
+#define XAutoRepeatOff XAUTOREPEATOFF
+#define XAutoRepeatOn XAUTOREPEATON
+#define XBaseFontNameListOfFontSet XBASEFONTNAMELISTOFFONTSET
+#define XBell XBELL
+#define XBitmapPad XBITMAPPAD
+#define XChangeActivePointerGrab XCHANGEACTIVEPOINTERGRAB
+#define XChangeGC XCHANGEGC
+#define XChangeProperty XCHANGEPROPERTY
+#define XChangeWindowAttributes XCHANGEWINDOWATTRIBUTES
+#define XCheckIfEvent XCHECKIFEVENT
+#define XCheckMaskEvent XCHECKMASKEVENT
+#define XCheckTypedEvent XCHECKTYPEDEVENT
+#define XCheckTypedWindowEvent XCHECKTYPEDWINDOWEVENT
+#define XCheckWindowEvent XCHECKWINDOWEVENT
+#define XClearArea XCLEARAREA
+#define XClearWindow XCLEARWINDOW
+#define XClipBox XCLIPBOX
+#define XCloseDisplay XCLOSEDISPLAY
+#define XCloseIM XCLOSEIM
+#define XConfigureWindow XCONFIGUREWINDOW
+#define XConvertSelection XCONVERTSELECTION
+#define XCopyArea XCOPYAREA
+#define XCopyGC XCOPYGC
+#define XCopyPlane XCOPYPLANE
+#define XCreateBitmapFromData XCREATEBITMAPFROMDATA
+#define XCreateColormap XCREATECOLORMAP
+#define XCreateFontCursor XCREATEFONTCURSOR
+#define XCreateFontSet XCREATEFONTSET
+#define XCreateGC XCREATEGC
+#define XCreateIC XCREATEIC
+#define XCreateImage XCREATEIMAGE
+#define XCreatePixmap XCREATEPIXMAP
+#define XCreatePixmapCursor XCREATEPIXMAPCURSOR
+#define XCreatePixmapFromBitmapData XCREATEPIXMAPFROMBITMAPDATA
+#define XCreateRegion XCREATEREGION
+#define XCreateSimpleWindow XCREATESIMPLEWINDOW
+#define XCreateWindow XCREATEWINDOW
+#define XDefaultScreenOfDisplay XDEFAULTSCREENOFDISPLAY
+#define XDefineCursor XDEFINECURSOR
+#define XDeleteProperty XDELETEPROPERTY
+#define XDestroyIC XDESTROYIC
+#define XDestroyRegion XDESTROYREGION
+#define XDestroyWindow XDESTROYWINDOW
+#define XDisplayName XDISPLAYNAME
+#define XDisplayOfScreen XDISPLAYOFSCREEN
+#define XDisplayString XDISPLAYSTRING
+#define XDrawArc XDRAWARC
+#define XDrawImageString XDRAWIMAGESTRING
+#define XDrawImageString16 XDRAWIMAGESTRING16
+#define XDrawLine XDRAWLINE
+#define XDrawLines XDRAWLINES
+#define XDrawPoint XDRAWPOINT
+#define XDrawPoints XDRAWPOINTS
+#define XDrawRectangle XDRAWRECTANGLE
+#define XDrawSegments XDRAWSEGMENTS
+#define XDrawString XDRAWSTRING
+#define XDrawString16 XDRAWSTRING16
+#define XEmptyRegion XEMPTYREGION
+#define XEqualRegion XEQUALREGION
+#define XEventsQueued XEVENTSQUEUED
+#define XExtentsOfFontSet XEXTENTSOFFONTSET
+#define XFetchBuffer XFETCHBUFFER
+#define XFillArc XFILLARC
+#define XFillPolygon XFILLPOLYGON
+#define XFillRectangle XFILLRECTANGLE
+#define XFillRectangles XFILLRECTANGLES
+#define XFilterEvent XFILTEREVENT
+#define XFlush XFLUSH
+#define XFontsOfFontSet XFONTSOFFONTSET
+#define XFree XFREE
+#define XFreeColormap XFREECOLORMAP
+#define XFreeColors XFREECOLORS
+#define XFreeCursor XFREECURSOR
+#define XFreeFont XFREEFONT
+#define XFreeFontInfo XFREEFONTINFO
+#define XFreeFontNames XFREEFONTNAMES
+#define XFreeFontSet XFREEFONTSET
+#define XFreeGC XFREEGC
+#define XFreeModifiermap XFREEMODIFIERMAP
+#define XFreePixmap XFREEPIXMAP
+#define XFreeStringList XFREESTRINGLIST
+#define XGetAtomName XGETATOMNAME
+#define XGetDefault XGETDEFAULT
+#define XGetErrorDatabaseText XGETERRORDATABASETEXT
+#define XGetErrorText XGETERRORTEXT
+#define XGetFontProperty XGETFONTPROPERTY
+#define XGetGCValues XGETGCVALUES
+#define XGetGeometry XGETGEOMETRY
+#define XGetIconSizes XGETICONSIZES
+#define XGetICValues XGETICVALUES
+#define XGetIMValues XGETIMVALUES
+#define XGetImage XGETIMAGE
+#define XGetKeyboardControl XGETKEYBOARDCONTROL
+#define XGetModifierMapping XGETMODIFIERMAPPING
+#define XGetMotionEvents XGETMOTIONEVENTS
+#define XGetNormalHints XGETNORMALHINTS
+#define XGetSelectionOwner XGETSELECTIONOWNER
+#define XGetSubImage XGETSUBIMAGE
+#define XGetVisualInfo XGETVISUALINFO
+#define XGetWMColormapWindows XGETWMCOLORMAPWINDOWS
+#define XGetWMProtocols XGETWMPROTOCOLS
+#define XGetWMHints XGETWMHINTS
+#define XGetWMName XGETWMNAME
+#define XGetWMNormalHints XGETWMNORMALHINTS
+#define XGetWindowAttributes XGETWINDOWATTRIBUTES
+#define XGetWindowProperty XGETWINDOWPROPERTY
+#define XGrabKeyboard XGRABKEYBOARD
+#define XGrabPointer XGRABPOINTER
+#define XGrabServer XGRABSERVER
+#define XHeightOfScreen XHEIGHTOFSCREEN
+#define XIconifyWindow XICONIFYWINDOW
+#define XIfEvent XIFEVENT
+#define XInternAtom XINTERNATOM
+#define XIntersectRegion XINTERSECTREGION
+#define XKeycodeToKeysym XKEYCODETOKEYSYM
+#define XKeysymToKeycode XKEYSYMTOKEYCODE
+#define XKeysymToString XKEYSYMTOSTRING
+#define XListFonts XLISTFONTS
+#define XListFontsWithInfo XLISTFONTSWITHINFO
+#define XListPixmapFormats XLISTPIXMAPFORMATS
+#define XListProperties XLISTPROPERTIES
+#define XLoadQueryFont XLOADQUERYFONT
+#define XLookupString XLOOKUPSTRING
+#define XLowerWindow XLOWERWINDOW
+#define XMapRaised XMAPRAISED
+#define XMapWindow XMAPWINDOW
+#define XMatchVisualInfo XMATCHVISUALINFO
+#define XMoveResizeWindow XMOVERESIZEWINDOW
+#define XMoveWindow XMOVEWINDOW
+#define XNextEvent XNEXTEVENT
+#define XOffsetRegion XOFFSETREGION
+#define XOpenDisplay XOPENDISPLAY
+#define XOpenIM XOPENIM
+#define XParseColor XPARSECOLOR
+#define XParseGeometry XPARSEGEOMETRY
+#define XPeekEvent XPEEKEVENT
+#define XPending XPENDING
+#define XPointInRegion XPOINTINREGION
+#define XPolygonRegion XPOLYGONREGION
+#define XPutBackEvent XPUTBACKEVENT
+#define XPutImage XPUTIMAGE
+#define XRootWindow XROOTWINDOW
+#define XQueryColor XQUERYCOLOR
+#define XQueryColors XQUERYCOLORS
+#define XQueryExtension XQUERYEXTENSION
+#define XQueryPointer XQUERYPOINTER
+#define XQueryTree XQUERYTREE
+#define XRaiseWindow XRAISEWINDOW
+#define XReconfigureWMWindow XRECONFIGUREWMWINDOW
+#define XRectInRegion XRECTINREGION
+#define XRefreshKeyboardMapping XREFRESHKEYBOARDMAPPING
+#define XReparentWindow XREPARENTWINDOW
+#define XResizeWindow XRESIZEWINDOW
+#define XRestackWindows XRESTACKWINDOWS
+#define XRootWindowOfScreen XROOTWINDOWOFSCREEN
+#define XScreenNumberOfScreen XSCREENNUMBEROFSCREEN
+#define XSelectAsyncEvent XSELECTASYNCEVENT
+#define XSelectAsyncInput XSELECTASYNCINPUT
+#define XSelectInput XSELECTINPUT
+#define XSendEvent XSENDEVENT
+#define XServerVendor XSERVERVENDOR
+#define XSetBackground XSETBACKGROUND
+#define XSetClassHint XSETCLASSHINT
+#define XSetClipMask XSETCLIPMASK
+#define XSetClipOrigin XSETCLIPORIGIN
+#define XSetClipRectangles XSETCLIPRECTANGLES
+#define XSetCloseDownMode XSETCLOSEDOWNMODE
+#define XSetCommand XSETCOMMAND
+#define XSetDashes XSETDASHES
+#define XSetErrorHandler XSETERRORHANDLER
+#define XSetFillStyle XSETFILLSTYLE
+#define XSetFont XSETFONT
+#define XSetForeground XSETFOREGROUND
+#define XSetFunction XSETFUNCTION
+#define XSetGraphicsExposures XSETGRAPHICSEXPOSURES
+#define XSetICFocus XSETICFOCUS
+#define XSetICValues XSETICVALUES
+#define XSetIOErrorHandler XSETIOERRORHANDLER
+#define XSetInputFocus XSETINPUTFOCUS
+#define XSetLineAttributes XSETLINEATTRIBUTES
+#define XSetLocaleModifiers XSETLOCALEMODIFIERS
+#define XSetNormalHints XSETNORMALHINTS
+#define XSetRegion XSETREGION
+#define XSetSelectionOwner XSETSELECTIONOWNER
+#define XSetStipple XSETSTIPPLE
+#define XSetSubwindowMode XSETSUBWINDOWMODE
+#define XSetTSOrigin XSETTSORIGIN
+#define XSetTile XSETTILE
+#define XSetTransientForHint XSETTRANSIENTFORHINT
+#define XSetWMColormapWindows XSETWMCOLORMAPWINDOWS
+#define XSetWMHints XSETWMHINTS
+#define XSetWMIconName XSETWMICONNAME
+#define XSetWMName XSETWMNAME
+#define XSetWMNormalHints XSETWMNORMALHINTS
+#define XSetWMProperties XSETWMPROPERTIES
+#define XSetWMProtocols XSETWMPROTOCOLS
+#define XSetWindowBackground XSETWINDOWBACKGROUND
+#define XSetWindowBackgroundPixmap XSETWINDOWBACKGROUNDPIXMAP
+#define XSetWindowColormap XSETWINDOWCOLORMAP
+#define XShapeCombineMask XSHAPECOMBINEMASK
+#define XShapeCombineRectangles XSHAPECOMBINERECTANGLES
+#define XShapeGetRectangles XSHAPEGETRECTANGLES
+#define XShrinkRegion XSHRINKREGION
+#define XStoreColor XSTORECOLOR
+#define XStoreColors XSTORECOLORS
+#define XStoreName XSTORENAME
+#define XStringToKeysym XSTRINGTOKEYSYM
+#define XSubtractRegion XSUBTRACTREGION
+#define XSupportsLocale XSUPPORTSLOCALE
+#define XSync XSYNC
+#define XSynchronize XSYNCHRONIZE
+#define XTextExtents XTEXTEXTENTS
+#define XTextExtents16 XTEXTEXTENTS16
+#define XTextWidth XTEXTWIDTH
+#define XTextWidth16 XTEXTWIDTH16
+#define XTranslateCoordinates XTRANSLATECOORDINATES
+#define XUndefineCursor XUNDEFINECURSOR
+#define XUngrabKeyboard XUNGRABKEYBOARD
+#define XUngrabPointer XUNGRABPOINTER
+#define XUngrabServer XUNGRABSERVER
+#define XUnionRectWithRegion XUNIONRECTWITHREGION
+#define XUnionRegion XUNIONREGION
+#define XUnmapWindow XUNMAPWINDOW
+#define _XUnregisterFilter _XUNREGISTERFILTER
+#define XUnsetICFocus XUNSETICFOCUS
+#define XVaCreateNestedList XVACREATENESTEDLIST
+#define XVisualIDFromVisual XVISUALIDFROMVISUAL
+#define XWarpPointer XWARPPOINTER
+#define XWidthOfScreen XWIDTHOFSCREEN
+#define XWindowEvent XWINDOWEVENT
+#define XWithdrawWindow XWITHDRAWWINDOW
+#define XXorRegion XXORREGION
+#define XmAddProtocolCallback XMADDPROTOCOLCALLBACK
+#define XmAddProtocols XMADDPROTOCOLS
+#define XmChangeColor XMCHANGECOLOR
+#define XmClipboardCopy XMCLIPBOARDCOPY
+#define XmClipboardEndCopy XMCLIPBOARDENDCOPY
+#define XmClipboardInquireLength XMCLIPBOARDINQUIRELENGTH
+#define XmClipboardLock XMCLIPBOARDLOCK
+#define XmClipboardRetrieve XMCLIPBOARDRETRIEVE
+#define XmClipboardStartCopy XMCLIPBOARDSTARTCOPY
+#define XmClipboardUnlock XMCLIPBOARDUNLOCK
+#define XmCreateArrowButton XMCREATEARROWBUTTON
+#define XmCreateArrowButtonGadget XMCREATEARROWBUTTONGADGET
+#define XmCreateCascadeButton XMCREATECASCADEBUTTON
+#define XmCreateDialogShell XMCREATEDIALOGSHELL
+#define XmCreateDragIcon XMCREATEDRAGICON
+#define XmCreateDrawingArea XMCREATEDRAWINGAREA
+#define XmCreateDrawnButton XMCREATEDRAWNBUTTON
+#define XmCreateFileSelectionBox XMCREATEFILESELECTIONBOX
+#define XmCreateFileSelectionDialog XMCREATEFILESELECTIONDIALOG
+#define XmCreateForm XMCREATEFORM
+#define XmCreateFormDialog XMCREATEFORMDIALOG
+#define XmCreateFrame XMCREATEFRAME
+#define XmCreateInformationDialog XMCREATEINFORMATIONDIALOG
+#define XmCreateLabelGadget XMCREATELABELGADGET
+#define XmCreateMainWindow XMCREATEMAINWINDOW
+#define XmCreateMenuBar XMCREATEMENUBAR
+#define XmCreateMessageBox XMCREATEMESSAGEBOX
+#define XmCreateMessageDialog XMCREATEMESSAGEDIALOG
+#define XmCreateOptionMenu XMCREATEOPTIONMENU
+#define XmCreatePanedWindow XMCREATEPANEDWINDOW
+#define XmCreatePopupMenu XMCREATEPOPUPMENU
+#define XmCreatePromptDialog XMCREATEPROMPTDIALOG
+#define XmCreatePulldownMenu XMCREATEPULLDOWNMENU
+#define XmCreatePushButton XMCREATEPUSHBUTTON
+#define XmCreatePushButtonGadget XMCREATEPUSHBUTTONGADGET
+#define XmCreateQuestionDialog XMCREATEQUESTIONDIALOG
+#define XmCreateRadioBox XMCREATERADIOBOX
+#define XmCreateRowColumn XMCREATEROWCOLUMN
+#define XmCreateScale XMCREATESCALE
+#define XmCreateScrollBar XMCREATESCROLLBAR
+#define XmCreateScrolledList XMCREATESCROLLEDLIST
+#define XmCreateScrolledText XMCREATESCROLLEDTEXT
+#define XmCreateScrolledWindow XMCREATESCROLLEDWINDOW
+#define XmCreateSelectionDialog XMCREATESELECTIONDIALOG
+#define XmCreateSeparator XMCREATESEPARATOR
+#define XmCreateSeparatorGadget XMCREATESEPARATORGADGET
+#define XmCreateTemplateDialog XMCREATETEMPLATEDIALOG
+#define XmCreateText XMCREATETEXT
+#define XmCreateTextField XMCREATETEXTFIELD
+#define XmCreateToggleButton XMCREATETOGGLEBUTTON
+#define XmCreateToggleButtonGadget XMCREATETOGGLEBUTTONGADGET
+#define XmDragStart XMDRAGSTART
+#define XmDropSiteRegister XMDROPSITEREGISTER
+#define XmDropSiteUnregister XMDROPSITEUNREGISTER
+#define XmDropSiteUpdate XMDROPSITEUPDATE
+#define XmDropTransferStart XMDROPTRANSFERSTART
+#define XmFileSelectionBoxGetChild XMFILESELECTIONBOXGETCHILD
+#define XmFileSelectionDoSearch XMFILESELECTIONDOSEARCH
+#define XmFontListAppendEntry XMFONTLISTAPPENDENTRY
+#define XmFontListCopy XMFONTLISTCOPY
+#define XmFontListCreate XMFONTLISTCREATE
+#define XmFontListEntryCreate XMFONTLISTENTRYCREATE
+#define XmFontListEntryFree XMFONTLISTENTRYFREE
+#define XmFontListEntryGetFont XMFONTLISTENTRYGETFONT
+#define XmFontListEntryGetTag XMFONTLISTENTRYGETTAG
+#define XmFontListEntryLoad XMFONTLISTENTRYLOAD
+#define XmFontListFree XMFONTLISTFREE
+#define XmFontListFreeFontContext XMFONTLISTFREEFONTCONTEXT
+#define XmFontListGetNextFont XMFONTLISTGETNEXTFONT
+#define XmFontListInitFontContext XMFONTLISTINITFONTCONTEXT
+#define XmFontListNextEntry XMFONTLISTNEXTENTRY
+#define XmGetColors XMGETCOLORS
+#define XmGetFocusWidget XMGETFOCUSWIDGET
+#define XmGetMenuCursor XMGETMENUCURSOR
+#define XmGetPixmapByDepth XMGETPIXMAPBYDEPTH
+#define XmGetTearOffControl XMGETTEAROFFCONTROL
+#define XmGetXmDisplay XMGETXMDISPLAY
+#define XmImMbLookupString XMIMMBLOOKUPSTRING
+#define XmImRegister XMIMREGISTER
+#define XmImSetFocusValues XMIMSETFOCUSVALUES
+#define XmImSetValues XMIMSETVALUES
+#define XmImUnregister XMIMUNREGISTER
+#define XmImUnsetFocus XMIMUNSETFOCUS
+#define XmInternAtom XMINTERNATOM
+#define XmIsMotifWMRunning XMISMOTIFWMRUNNING
+#define XmListAddItem XMLISTADDITEM
+#define XmListAddItemUnselected XMLISTADDITEMUNSELECTED
+#define XmListAddItemsUnselected XMLISTADDITEMSUNSELECTED
+#define XmListDeleteAllItems XMLISTDELETEALLITEMS
+#define XmListDeleteItemsPos XMLISTDELETEITEMSPOS
+#define XmListDeletePos XMLISTDELETEPOS
+#define XmListDeselectAllItems XMLISTDESELECTALLITEMS
+#define XmListDeselectPos XMLISTDESELECTPOS
+#define XmListGetKbdItemPos XMLISTGETKBDITEMPOS
+#define XmListGetMatchPos XMLISTGETMATCHPOS
+#define XmListGetSelectedPos XMLISTGETSELECTEDPOS
+#define XmListPosSelected XMLISTPOSSELECTED
+#define XmListSelectItem XMLISTSELECTITEM
+#define XmListSelectPos XMLISTSELECTPOS
+#define XmListSetBottomPos XMLISTSETBOTTOMPOS
+#define XmListSetItem XMLISTSETITEM
+#define XmListSetKbdItemPos XMLISTSETKBDITEMPOS
+#define XmListSetPos XMLISTSETPOS
+#define XmMainWindowSetAreas XMMAINWINDOWSETAREAS
+#define XmMenuPosition XMMENUPOSITION
+#define XmMessageBoxGetChild XMMESSAGEBOXGETCHILD
+#define XmOptionButtonGadget XMOPTIONBUTTONGADGET
+#define XmOptionLabelGadget XMOPTIONLABELGADGET
+#define XmProcessTraversal XMPROCESSTRAVERSAL
+#define XmQmotif XMQMOTIF
+#define XmRemoveProtocolCallback XMREMOVEPROTOCOLCALLBACK
+#define XmRepTypeGetId XMREPTYPEGETID
+#define XmRepTypeGetRecord XMREPTYPEGETRECORD
+#define XmRepTypeRegister XMREPTYPEREGISTER
+#define XmRepTypeValidValue XMREPTYPEVALIDVALUE
+#define XmScrollBarSetValues XMSCROLLBARSETVALUES
+#define XmScrolledWindowSetAreas XMSCROLLEDWINDOWSETAREAS
+#define XmSelectionBoxGetChild XMSELECTIONBOXGETCHILD
+#define XmStringByteCompare XMSTRINGBYTECOMPARE
+#define XmStringCompare XMSTRINGCOMPARE
+#define XmStringConcat XMSTRINGCONCAT
+#define XmStringCopy XMSTRINGCOPY
+#define XmStringCreate XMSTRINGCREATE
+#define XmStringCreateLocalized XMSTRINGCREATELOCALIZED
+#define XmStringCreateLtoR XMSTRINGCREATELTOR
+#define XmStringCreateSimple XMSTRINGCREATESIMPLE
+#define XmStringDraw XMSTRINGDRAW
+#define XmStringDrawUnderline XMSTRINGDRAWUNDERLINE
+#define XmStringExtent XMSTRINGEXTENT
+#define XmStringFree XMSTRINGFREE
+#define XmStringFreeContext XMSTRINGFREECONTEXT
+#define XmStringGetLtoR XMSTRINGGETLTOR
+#define XmStringGetNextComponent XMSTRINGGETNEXTCOMPONENT
+#define XmStringGetNextSegment XMSTRINGGETNEXTSEGMENT
+#define XmStringInitContext XMSTRINGINITCONTEXT
+#define XmStringLength XMSTRINGLENGTH
+#define XmStringLtoRCreate XMSTRINGLTORCREATE
+#define XmStringNConcat XMSTRINGNCONCAT
+#define XmStringSegmentCreate XMSTRINGSEGMENTCREATE
+#define XmStringWidth XMSTRINGWIDTH
+#define XmTextClearSelection XMTEXTCLEARSELECTION
+#define XmTextFieldGetEditable XMTEXTFIELDGETEDITABLE
+#define XmTextFieldGetInsertionPosition XMTEXTFIELDGETINSERTIONPOSITION
+#define XmTextFieldGetLastPosition XMTEXTFIELDGETLASTPOSITION
+#define XmTextFieldGetSelection XMTEXTFIELDGETSELECTION
+#define XmTextFieldGetString XMTEXTFIELDGETSTRING
+#define XmTextFieldInsert XMTEXTFIELDINSERT
+#define XmTextFieldRemove XMTEXTFIELDREMOVE
+#define XmTextFieldSetSelection XMTEXTFIELDSETSELECTION
+#define XmTextFieldSetString XMTEXTFIELDSETSTRING
+#define XmTextGetCursorPosition XMTEXTGETCURSORPOSITION
+#define XmTextGetInsertionPosition XMTEXTGETINSERTIONPOSITION
+#define XmTextGetLastPosition XMTEXTGETLASTPOSITION
+#define XmTextGetMaxLength XMTEXTGETMAXLENGTH
+#define XmTextGetSelection XMTEXTGETSELECTION
+#define XmTextGetSelectionPosition XMTEXTGETSELECTIONPOSITION
+#define XmTextGetString XMTEXTGETSTRING
+#define XmTextInsert XMTEXTINSERT
+#define XmTextRemove XMTEXTREMOVE
+#define XmTextReplace XMTEXTREPLACE
+#define XmTextSetCursorPosition XMTEXTSETCURSORPOSITION
+#define XmTextSetHighlight XMTEXTSETHIGHLIGHT
+#define XmTextSetInsertionPosition XMTEXTSETINSERTIONPOSITION
+#define XmTextSetSelection XMTEXTSETSELECTION
+#define XmTextSetString XMTEXTSETSTRING
+#define XmToggleButtonGadgetGetState XMTOGGLEBUTTONGADGETGETSTATE
+#define XmToggleButtonGadgetSetState XMTOGGLEBUTTONGADGETSETSTATE
+#define XmToggleButtonGetState XMTOGGLEBUTTONGETSTATE
+#define XmToggleButtonSetState XMTOGGLEBUTTONSETSTATE
+#define XmUpdateDisplay XMUPDATEDISPLAY
+#define XmVaCreateSimpleRadioBox XMVACREATESIMPLERADIOBOX
+#define XmbDrawString XMBDRAWSTRING
+#define XmbLookupString XMBLOOKUPSTRING
+#define XmbResetIC XMBRESETIC
+#define XmbSetWMProperties XMBSETWMPROPERTIES
+#define XmbTextEscapement XMBTEXTESCAPEMENT
+#define XmbTextExtents XMBTEXTEXTENTS
+#define XmbTextListToTextProperty XMBTEXTLISTTOTEXTPROPERTY
+#define XmbTextPropertyToTextList XMBTEXTPROPERTYTOTEXTLIST
+#define XmuClientWindow XMUCLIENTWINDOW
+#define XmuPrintDefaultErrorMessage XMUPRINTDEFAULTERRORMESSAGE
+#define XrmGetDatabase XRMGETDATABASE
+#define XrmGetResource XRMGETRESOURCE
+#define XrmPutStringResource XRMPUTSTRINGRESOURCE
+#define XrmQuarkToString XRMQUARKTOSTRING
+#define XrmStringToQuark XRMSTRINGTOQUARK
+#define XtAddCallback XTADDCALLBACK
+#define XtAddCallbacks XTADDCALLBACKS
+#define XtAddEventHandler XTADDEVENTHANDLER
+#define XtAddGrab XTADDGRAB
+#define XtAllocateGC XTALLOCATEGC
+#define XtAppAddActions XTAPPADDACTIONS
+#define XtAppAddInput XTAPPADDINPUT
+#define XtAppAddTimeOut XTAPPADDTIMEOUT
+#define XtAppCreateShell XTAPPCREATESHELL
+#define XtAppInitialize XTAPPINITIALIZE
+#define XtAppNextEvent XTAPPNEXTEVENT
+#define XtAppPeekEvent XTAPPPEEKEVENT
+#define XtAppPending XTAPPPENDING
+#define XtAppProcessEvent XTAPPPROCESSEVENT
+#define XtAppSetErrorHandler XTAPPSETERRORHANDLER
+#define XtAppSetFallbackResources XTAPPSETFALLBACKRESOURCES
+#define XtAppSetWarningHandler XTAPPSETWARNINGHANDLER
+#define XtAppSetWarningMsgHandler XTAPPSETWARNINGMSGHANDLER
+#define XtAppWarning XTAPPWARNING
+#define XtCallActionProc XTCALLACTIONPROC
+#define XtCallCallbackList XTCALLCALLBACKLIST
+#define XtCallCallbacks XTCALLCALLBACKS
+#define XtConfigureWidget XTCONFIGUREWIDGET
+#define XtConvertAndStore XTCONVERTANDSTORE
+#define XtCreateApplicationContext XTCREATEAPPLICATIONCONTEXT
+#define XtCreateManagedWidget XTCREATEMANAGEDWIDGET
+#define XtCreatePopupShell XTCREATEPOPUPSHELL
+#define XtCreateWidget XTCREATEWIDGET
+#define XtDatabase XTDATABASE
+#define XtDestroyWidget XTDESTROYWIDGET
+#define XtDisownSelection XTDISOWNSELECTION
+#define XtDispatchEvent XTDISPATCHEVENT
+#define XtDisplayOfObject XTDISPLAYOFOBJECT
+#define XtDisplayStringConvWarning XTDISPLAYSTRINGCONVWARNING
+#define XtDisplayToApplicationContext XTDISPLAYTOAPPLICATIONCONTEXT
+#define XtFree XTFREE
+#define XtGetActionKeysym XTGETACTIONKEYSYM
+#define XtGetActionList XTGETACTIONLIST
+#define XtGetApplicationNameAndClass XTGETAPPLICATIONNAMEANDCLASS
+#define XtGetApplicationResources XTGETAPPLICATIONRESOURCES
+#define XtGetGC XTGETGC
+#define XtGetMultiClickTime XTGETMULTICLICKTIME
+#define XtGetSelectionValue XTGETSELECTIONVALUE
+#define XtGetSelectionValues XTGETSELECTIONVALUES
+#define XtGetSubresources XTGETSUBRESOURCES
+#define XtGetValues XTGETVALUES
+#define XtGrabKeyboard XTGRABKEYBOARD
+#define XtGrabPointer XTGRABPOINTER
+#define XtHasCallbacks XTHASCALLBACKS
+#define XtInitializeWidgetClass XTINITIALIZEWIDGETCLASS
+#define XtInsertEventHandler XTINSERTEVENTHANDLER
+#define XtIsManaged XTISMANAGED
+#define XtIsObject XTISOBJECT
+#define XtIsSensitive XTISSENSITIVE
+#define XtIsSubclass XTISSUBCLASS
+#define XtLastTimestampProcessed XTLASTTIMESTAMPPROCESSED
+#define XtMakeGeometryRequest XTMAKEGEOMETRYREQUEST
+#define XtMakeResizeRequest XTMAKERESIZEREQUEST
+#define XtMalloc XTMALLOC
+#define XtManageChild XTMANAGECHILD
+#define XtManageChildren XTMANAGECHILDREN
+#define XtMergeArgLists XTMERGEARGLISTS
+#define XtMoveWidget XTMOVEWIDGET
+#define XtName XTNAME
+#define XtNameToWidget XTNAMETOWIDGET
+#define XtOpenDisplay XTOPENDISPLAY
+#define XtOverrideTranslations XTOVERRIDETRANSLATIONS
+#define XtOwnSelection XTOWNSELECTION
+#define XtParent XTPARENT
+#define XtParseTranslationTable XTPARSETRANSLATIONTABLE
+#define XtPopdown XTPOPDOWN
+#define XtPopup XTPOPUP
+#define XtQueryGeometry XTQUERYGEOMETRY
+#define XtRealizeWidget XTREALIZEWIDGET
+#define XtRealloc XTREALLOC
+#define XtReleaseGC XTRELEASEGC
+#define XtRemoveAllCallbacks XTREMOVEALLCALLBACKS
+#define XtRemoveCallback XTREMOVECALLBACK
+#define XtRemoveEventHandler XTREMOVEEVENTHANDLER
+#define XtRemoveGrab XTREMOVEGRAB
+#define XtRemoveInput XTREMOVEINPUT
+#define XtRemoveTimeOut XTREMOVETIMEOUT
+#define XtResizeWidget XTRESIZEWIDGET
+#define XtResolvePathname XTRESOLVEPATHNAME
+#define XtSetKeyboardFocus XTSETKEYBOARDFOCUS
+#define XtSetMappedWhenManaged XTSETMAPPEDWHENMANAGED
+#define XtSetSensitive XTSETSENSITIVE
+#define XtSetTypeConverter XTSETTYPECONVERTER
+#define XtSetValues XTSETVALUES
+#define XtShellStrings XTSHELLSTRINGS
+#define XtStrings XTSTRINGS
+#define XtToolkitInitialize XTTOOLKITINITIALIZE
+#define XtTranslateCoords XTTRANSLATECOORDS
+#define XtTranslateKeycode XTTRANSLATEKEYCODE
+#define XtUngrabKeyboard XTUNGRABKEYBOARD
+#define XtUngrabPointer XTUNGRABPOINTER
+#define XtUnmanageChild XTUNMANAGECHILD
+#define XtUnmanageChildren XTUNMANAGECHILDREN
+#define XtUnrealizeWidget XTUNREALIZEWIDGET
+#define XtVaCreateManagedWidget XTVACREATEMANAGEDWIDGET
+#define XtVaCreateWidget XTVACREATEWIDGET
+#define XtVaGetValues XTVAGETVALUES
+#define XtVaSetValues XTVASETVALUES
+#define XtWarning XTWARNING
+#define XtWidgetToApplicationContext XTWIDGETTOAPPLICATIONCONTEXT
+#define XtWindow XTWINDOW
+#define XtWindowOfObject XTWINDOWOFOBJECT
+#define XtWindowToWidget XTWINDOWTOWIDGET
+#define XwcDrawString XWCDRAWSTRING
+#define XwcFreeStringList XWCFREESTRINGLIST
+#define XwcTextEscapement XWCTEXTESCAPEMENT
+#define XwcTextExtents XWCTEXTEXTENTS
+#define XwcTextListToTextProperty XWCTEXTLISTTOTEXTPROPERTY
+#define XwcTextPropertyToTextList XWCTEXTPROPERTYTOTEXTLIST
+#define _XmBottomShadowColorDefault _XMBOTTOMSHADOWCOLORDEFAULT
+#define _XmClearBorder _XMCLEARBORDER
+#define _XmConfigureObject _XMCONFIGUREOBJECT
+#define _XmDestroyParentCallback _XMDESTROYPARENTCALLBACK
+#define _XmDrawArrow _XMDRAWARROW
+#define _XmDrawShadows _XMDRAWSHADOWS
+#define _XmFontListGetDefaultFont _XMFONTLISTGETDEFAULTFONT
+#define _XmFromHorizontalPixels _XMFROMHORIZONTALPIXELS
+#define _XmFromVerticalPixels _XMFROMVERTICALPIXELS
+#define _XmGetClassExtensionPtr _XMGETCLASSEXTENSIONPTR
+#define _XmGetDefaultFontList _XMGETDEFAULTFONTLIST
+#define _XmGetTextualDragIcon _XMGETTEXTUALDRAGICON
+#define _XmGetWidgetExtData _XMGETWIDGETEXTDATA
+#define _XmGrabKeyboard _XMGRABKEYBOARD
+#define _XmGrabPointer _XMGRABPOINTER
+#define _XmInheritClass _XMINHERITCLASS
+#define _XmInputInGadget _XMINPUTINGADGET
+#define _XmMakeGeometryRequest _XMMAKEGEOMETRYREQUEST
+#define _XmMenuPopDown _XMMENUPOPDOWN
+#define _XmMoveObject _XMMOVEOBJECT
+#define _XmNavigChangeManaged _XMNAVIGCHANGEMANAGED
+#define _XmOSBuildFileList _XMOSBUILDFILELIST
+#define _XmOSFileCompare _XMOSFILECOMPARE
+#define _XmOSFindPatternPart _XMOSFINDPATTERNPART
+#define _XmOSQualifyFileSpec _XMOSQUALIFYFILESPEC
+#define _XmPostPopupMenu _XMPOSTPOPUPMENU
+#define _XmPrimitiveEnter _XMPRIMITIVEENTER
+#define _XmPrimitiveLeave _XMPRIMITIVELEAVE
+#define _XmRedisplayGadgets _XMREDISPLAYGADGETS
+#define _XmShellIsExclusive _XMSHELLISEXCLUSIVE
+#define _XmStringDraw _XMSTRINGDRAW
+#define _XmStringGetTextConcat _XMSTRINGGETTEXTCONCAT
+#define _XmStrings _XMSTRINGS
+#define _XmToHorizontalPixels _XMTOHORIZONTALPIXELS
+#define _XmToVerticalPixels _XMTOVERTICALPIXELS
+#define _XmTopShadowColorDefault _XMTOPSHADOWCOLORDEFAULT
+#define _Xm_fastPtr _XM_FASTPTR
+#define _XtCheckSubclassFlag _XTCHECKSUBCLASSFLAG
+#define _XtInherit _XTINHERIT
+#define _XtInheritTranslations _XTINHERITTRANSLATIONS
+#define applicationShellWidgetClass APPLICATIONSHELLWIDGETCLASS
+#define compositeWidgetClass COMPOSITEWIDGETCLASS
+#define overrideShellWidgetClass OVERRIDESHELLWIDGETCLASS
+#define shellWidgetClass SHELLWIDGETCLASS
+#define topLevelShellClassRec TOPLEVELSHELLCLASSREC
+#define topLevelShellWidgetClass TOPLEVELSHELLWIDGETCLASS
+#define transientShellWidgetClass TRANSIENTSHELLWIDGETCLASS
+#define vendorShellClassRec VENDORSHELLCLASSREC
+#define vendorShellWidgetClass VENDORSHELLWIDGETCLASS
+#define wmShellWidgetClass WMSHELLWIDGETCLASS
+#define xmArrowButtonWidgetClass XMARROWBUTTONWIDGETCLASS
+#define xmCascadeButtonClassRec XMCASCADEBUTTONCLASSREC
+#define xmCascadeButtonGadgetClass XMCASCADEBUTTONGADGETCLASS
+#define xmCascadeButtonWidgetClass XMCASCADEBUTTONWIDGETCLASS
+#define xmDialogShellWidgetClass XMDIALOGSHELLWIDGETCLASS
+#define xmDrawingAreaWidgetClass XMDRAWINGAREAWIDGETCLASS
+#define xmDrawnButtonWidgetClass XMDRAWNBUTTONWIDGETCLASS
+#define xmFileSelectionBoxWidgetClass XMFILESELECTIONBOXWIDGETCLASS
+#define xmFormWidgetClass XMFORMWIDGETCLASS
+#define xmFrameWidgetClass XMFRAMEWIDGETCLASS
+#define xmGadgetClass XMGADGETCLASS
+#define xmLabelGadgetClass XMLABELGADGETCLASS
+#define xmLabelWidgetClass XMLABELWIDGETCLASS
+#define xmListWidgetClass XMLISTWIDGETCLASS
+#define xmMainWindowWidgetClass XMMAINWINDOWWIDGETCLASS
+#define xmManagerClassRec XMMANAGERCLASSREC
+#define xmManagerWidgetClass XMMANAGERWIDGETCLASS
+#define xmMenuShellWidgetClass XMMENUSHELLWIDGETCLASS
+#define xmMessageBoxWidgetClass XMMESSAGEBOXWIDGETCLASS
+#define xmPrimitiveClassRec XMPRIMITIVECLASSREC
+#define xmPrimitiveWidgetClass XMPRIMITIVEWIDGETCLASS
+#define xmPushButtonClassRec XMPUSHBUTTONCLASSREC
+#define xmPushButtonGadgetClass XMPUSHBUTTONGADGETCLASS
+#define xmPushButtonWidgetClass XMPUSHBUTTONWIDGETCLASS
+#define xmRowColumnWidgetClass XMROWCOLUMNWIDGETCLASS
+#define xmSashWidgetClass XMSASHWIDGETCLASS
+#define xmScrollBarWidgetClass XMSCROLLBARWIDGETCLASS
+#define xmScrolledWindowClassRec XMSCROLLEDWINDOWCLASSREC
+#define xmScrolledWindowWidgetClass XMSCROLLEDWINDOWWIDGETCLASS
+#define xmSeparatorGadgetClass XMSEPARATORGADGETCLASS
+#define xmSeparatorWidgetClass XMSEPARATORWIDGETCLASS
+#define xmTextFieldWidgetClass XMTEXTFIELDWIDGETCLASS
+#define xmTextWidgetClass XMTEXTWIDGETCLASS
+#define xmToggleButtonGadgetClass XMTOGGLEBUTTONGADGETCLASS
+#define xmToggleButtonWidgetClass XMTOGGLEBUTTONWIDGETCLASS
+
+/*
+** XtRegisterDrawable and XtUnregisterDrawable don't exist until R6.
+** So we have to fake it for R5 and earlier. It would be real nice to
+** include X11.h here and then test for R6 by checking
+** XlibSpecificationRelease. But including X11.h defines the symbol "None"
+** and there's Mozilla code in gfx/src/gtk that defines an enum element
+** named None. So for now hard code this is R5....
+*/
+#ifndef VMS_X11R6
+/* R5 or earlier */
+#define _XtRegisterWindow _XTREGISTERWINDOW
+#define _XtUnregisterWindow _XTUNREGISTERWINDOW
+/* original code is fixed so we don't need this now */
+#if 0
+#define XtRegisterDrawable(display,drawable,widget) \
+{ extern void _XtRegisterWindow(Window,Widget); \
+ _XtRegisterWindow(drawable,widget); \
+}
+#define XtUnregisterDrawable(display,drawable) \
+{ extern void _XtUnregisterWindow(Window,Widget); \
+ _XtUnregisterWindow(drawable,XtWindowToWidget(display,drawable)); \
+}
+#endif
+#else
+/* R6 or later */
+#define XtRegisterDrawable XTREGISTERDRAWABLE
+#define XtUnregisterDrawable XTUNREGISTERDRAWABLE
+#endif
diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c
new file mode 100644
index 000000000..e36c85827
--- /dev/null
+++ b/src/gui_gtk_x11.c
@@ -0,0 +1,6589 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * Porting to GTK+ was done by:
+ *
+ * (C) 1998,1999,2000 by Marcin Dalecki <dalecki@evision.ag>
+ *
+ * With GREAT support and continuous encouragements by Andy Kahn and of
+ * course Bram Moolenaar!
+ *
+ * Support for GTK+ 2 was added by:
+ *
+ * (C) 2002,2003 Jason Hildebrand <jason@peaceworks.ca>
+ * Daniel Elstner <daniel.elstner@gmx.net>
+ */
+
+#include "vim.h"
+#ifdef FEAT_GUI_GNOME
+/* Gnome redefines _() and N_(). Grrr... */
+# ifdef _
+# undef _
+# endif
+# ifdef N_
+# undef N_
+# endif
+# ifdef textdomain
+# undef textdomain
+# endif
+# ifdef bindtextdomain
+# undef bindtextdomain
+# endif
+# if defined(FEAT_GETTEXT) && !defined(ENABLE_NLS)
+# define ENABLE_NLS /* so the texts in the dialog boxes are translated */
+# endif
+# include <gnome.h>
+# include "version.h"
+#endif
+
+#if !defined(FEAT_GUI_GTK) && defined(PROTO)
+/* When generating prototypes we don't want syntax errors. */
+# define GdkAtom int
+# define GdkEventExpose int
+# define GdkEventFocus int
+# define GdkEventVisibility int
+# define GdkEventProperty int
+# define GtkContainer int
+# define GtkTargetEntry int
+# define GtkType int
+# define GtkWidget int
+# define gint int
+# define gpointer int
+# define guint int
+# define GdkEventKey int
+# define GdkEventSelection int
+# define GtkSelectionData int
+# define GdkEventMotion int
+# define GdkEventButton int
+# define GdkDragContext int
+# define GdkEventConfigure int
+# define GdkEventClient int
+#else
+# include <gdk/gdkkeysyms.h>
+# include <gdk/gdk.h>
+# ifdef WIN3264
+# include <gdk/gdkwin32.h>
+# else
+# include <gdk/gdkx.h>
+# endif
+
+# include <gtk/gtk.h>
+# include "gui_gtk_f.h"
+#endif
+
+#ifdef HAVE_X11_SUNKEYSYM_H
+# include <X11/Sunkeysym.h>
+#endif
+
+/*
+ * Easy-to-use macro for multihead support.
+ */
+#ifdef HAVE_GTK_MULTIHEAD
+# define GET_X_ATOM(atom) gdk_x11_atom_to_xatom_for_display( \
+ gtk_widget_get_display(gui.mainwin), atom)
+#else
+# define GET_X_ATOM(atom) ((Atom)(atom))
+#endif
+
+/* Selection type distinguishers */
+enum
+{
+ TARGET_TYPE_NONE,
+ TARGET_UTF8_STRING,
+ TARGET_STRING,
+ TARGET_COMPOUND_TEXT,
+ TARGET_TEXT,
+ TARGET_TEXT_URI_LIST,
+ TARGET_TEXT_PLAIN,
+ TARGET_VIM,
+ TARGET_VIMENC
+};
+
+/*
+ * Table of selection targets supported by Vim.
+ * Note: Order matters, preferred types should come first.
+ */
+static const GtkTargetEntry selection_targets[] =
+{
+ {VIMENC_ATOM_NAME, 0, TARGET_VIMENC},
+ {VIM_ATOM_NAME, 0, TARGET_VIM},
+#ifdef FEAT_MBYTE
+ {"UTF8_STRING", 0, TARGET_UTF8_STRING},
+#endif
+ {"COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT},
+ {"TEXT", 0, TARGET_TEXT},
+ {"STRING", 0, TARGET_STRING}
+};
+#define N_SELECTION_TARGETS (sizeof(selection_targets) / sizeof(selection_targets[0]))
+
+#ifdef FEAT_DND
+/*
+ * Table of DnD targets supported by Vim.
+ * Note: Order matters, preferred types should come first.
+ */
+static const GtkTargetEntry dnd_targets[] =
+{
+ {"text/uri-list", 0, TARGET_TEXT_URI_LIST},
+# ifdef FEAT_MBYTE
+ {"UTF8_STRING", 0, TARGET_UTF8_STRING},
+# endif
+ {"STRING", 0, TARGET_STRING},
+ {"text/plain", 0, TARGET_TEXT_PLAIN}
+};
+# define N_DND_TARGETS (sizeof(dnd_targets) / sizeof(dnd_targets[0]))
+#endif
+
+
+#ifdef HAVE_GTK2
+/*
+ * "Monospace" is a standard font alias that should be present
+ * on all proper Pango/fontconfig installations.
+ */
+# define DEFAULT_FONT "Monospace 10"
+
+#else /* !HAVE_GTK2 */
+/*
+ * This is the single only fixed width font in X11, which seems to be present
+ * on all servers and available in all the variants we need.
+ */
+# define DEFAULT_FONT "-adobe-courier-medium-r-normal-*-14-*-*-*-m-*-*-*"
+
+#endif /* !HAVE_GTK2 */
+
+#if !(defined(FEAT_GUI_GNOME) && defined(FEAT_SESSION))
+/*
+ * Atoms used to communicate save-yourself from the X11 session manager. There
+ * is no need to move them into the GUI struct, since they should be constant.
+ */
+static GdkAtom wm_protocols_atom = GDK_NONE;
+static GdkAtom save_yourself_atom = GDK_NONE;
+#endif
+
+/*
+ * Atoms used to control/reference X11 selections.
+ */
+#ifdef FEAT_MBYTE
+static GdkAtom utf8_string_atom = GDK_NONE;
+#endif
+#ifndef HAVE_GTK2
+static GdkAtom compound_text_atom = GDK_NONE;
+static GdkAtom text_atom = GDK_NONE;
+#endif
+static GdkAtom vim_atom = GDK_NONE; /* Vim's own special selection format */
+#ifdef FEAT_MBYTE
+static GdkAtom vimenc_atom = GDK_NONE; /* Vim's extended selection format */
+#endif
+
+/*
+ * Keycodes recognized by vim.
+ * NOTE: when changing this, the table in gui_x11.c probably needs the same
+ * change!
+ */
+static struct special_key
+{
+ guint key_sym;
+ char_u code0;
+ char_u code1;
+}
+const special_keys[] =
+{
+ {GDK_Up, 'k', 'u'},
+ {GDK_Down, 'k', 'd'},
+ {GDK_Left, 'k', 'l'},
+ {GDK_Right, 'k', 'r'},
+ {GDK_F1, 'k', '1'},
+ {GDK_F2, 'k', '2'},
+ {GDK_F3, 'k', '3'},
+ {GDK_F4, 'k', '4'},
+ {GDK_F5, 'k', '5'},
+ {GDK_F6, 'k', '6'},
+ {GDK_F7, 'k', '7'},
+ {GDK_F8, 'k', '8'},
+ {GDK_F9, 'k', '9'},
+ {GDK_F10, 'k', ';'},
+ {GDK_F11, 'F', '1'},
+ {GDK_F12, 'F', '2'},
+ {GDK_F13, 'F', '3'},
+ {GDK_F14, 'F', '4'},
+ {GDK_F15, 'F', '5'},
+ {GDK_F16, 'F', '6'},
+ {GDK_F17, 'F', '7'},
+ {GDK_F18, 'F', '8'},
+ {GDK_F19, 'F', '9'},
+ {GDK_F20, 'F', 'A'},
+ {GDK_F21, 'F', 'B'},
+ {GDK_Pause, 'F', 'B'}, /* Pause == F21 according to netbeans.txt */
+ {GDK_F22, 'F', 'C'},
+ {GDK_F23, 'F', 'D'},
+ {GDK_F24, 'F', 'E'},
+ {GDK_F25, 'F', 'F'},
+ {GDK_F26, 'F', 'G'},
+ {GDK_F27, 'F', 'H'},
+ {GDK_F28, 'F', 'I'},
+ {GDK_F29, 'F', 'J'},
+ {GDK_F30, 'F', 'K'},
+ {GDK_F31, 'F', 'L'},
+ {GDK_F32, 'F', 'M'},
+ {GDK_F33, 'F', 'N'},
+ {GDK_F34, 'F', 'O'},
+ {GDK_F35, 'F', 'P'},
+#ifdef SunXK_F36
+ {SunXK_F36, 'F', 'Q'},
+ {SunXK_F37, 'F', 'R'},
+#endif
+ {GDK_Help, '%', '1'},
+ {GDK_Undo, '&', '8'},
+ {GDK_BackSpace, 'k', 'b'},
+ {GDK_Insert, 'k', 'I'},
+ {GDK_Delete, 'k', 'D'},
+ {GDK_3270_BackTab, 'k', 'B'},
+ {GDK_Clear, 'k', 'C'},
+ {GDK_Home, 'k', 'h'},
+ {GDK_End, '@', '7'},
+ {GDK_Prior, 'k', 'P'},
+ {GDK_Next, 'k', 'N'},
+ {GDK_Print, '%', '9'},
+ /* Keypad keys: */
+ {GDK_KP_Left, 'k', 'l'},
+ {GDK_KP_Right, 'k', 'r'},
+ {GDK_KP_Up, 'k', 'u'},
+ {GDK_KP_Down, 'k', 'd'},
+ {GDK_KP_Insert, KS_EXTRA, (char_u)KE_KINS},
+ {GDK_KP_Delete, KS_EXTRA, (char_u)KE_KDEL},
+ {GDK_KP_Home, 'K', '1'},
+ {GDK_KP_End, 'K', '4'},
+ {GDK_KP_Prior, 'K', '3'}, /* page up */
+ {GDK_KP_Next, 'K', '5'}, /* page down */
+
+ {GDK_KP_Add, 'K', '6'},
+ {GDK_KP_Subtract, 'K', '7'},
+ {GDK_KP_Divide, 'K', '8'},
+ {GDK_KP_Multiply, 'K', '9'},
+ {GDK_KP_Enter, 'K', 'A'},
+ {GDK_KP_Decimal, 'K', 'B'},
+
+ {GDK_KP_0, 'K', 'C'},
+ {GDK_KP_1, 'K', 'D'},
+ {GDK_KP_2, 'K', 'E'},
+ {GDK_KP_3, 'K', 'F'},
+ {GDK_KP_4, 'K', 'G'},
+ {GDK_KP_5, 'K', 'H'},
+ {GDK_KP_6, 'K', 'I'},
+ {GDK_KP_7, 'K', 'J'},
+ {GDK_KP_8, 'K', 'K'},
+ {GDK_KP_9, 'K', 'L'},
+
+ /* End of list marker: */
+ {0, 0, 0}
+};
+
+/*
+ * Flags for command line options table below.
+ */
+#define ARG_FONT 1
+#define ARG_GEOMETRY 2
+#define ARG_REVERSE 3
+#define ARG_NOREVERSE 4
+#define ARG_BACKGROUND 5
+#define ARG_FOREGROUND 6
+#define ARG_ICONIC 7
+#define ARG_ROLE 8
+#define ARG_NETBEANS 9
+#define ARG_XRM 10 /* ignored */
+#define ARG_MENUFONT 11 /* ignored */
+#define ARG_INDEX_MASK 0x00ff
+#define ARG_HAS_VALUE 0x0100 /* a value is expected after the argument */
+#define ARG_NEEDS_GUI 0x0200 /* need to initialize the GUI for this */
+#define ARG_FOR_GTK 0x0400 /* argument is handled by GTK+ or GNOME */
+#define ARG_COMPAT_LONG 0x0800 /* accept -foo but substitute with --foo */
+#define ARG_KEEP 0x1000 /* don't remove argument from argv[] */
+
+/*
+ * This table holds all the X GUI command line options allowed. This includes
+ * the standard ones so that we can skip them when Vim is started without the
+ * GUI (but the GUI might start up later).
+ *
+ * When changing this, also update doc/gui_x11.txt and the usage message!!!
+ */
+typedef struct
+{
+ const char *name;
+ unsigned int flags;
+}
+cmdline_option_T;
+
+static const cmdline_option_T cmdline_options[] =
+{
+ /* We handle these options ourselves */
+ {"-fn", ARG_FONT|ARG_HAS_VALUE},
+ {"-font", ARG_FONT|ARG_HAS_VALUE},
+ {"-geom", ARG_GEOMETRY|ARG_HAS_VALUE},
+ {"-geometry", ARG_GEOMETRY|ARG_HAS_VALUE},
+ {"-rv", ARG_REVERSE},
+ {"-reverse", ARG_REVERSE},
+ {"+rv", ARG_NOREVERSE},
+ {"+reverse", ARG_NOREVERSE},
+ {"-bg", ARG_BACKGROUND|ARG_HAS_VALUE},
+ {"-background", ARG_BACKGROUND|ARG_HAS_VALUE},
+ {"-fg", ARG_FOREGROUND|ARG_HAS_VALUE},
+ {"-foreground", ARG_FOREGROUND|ARG_HAS_VALUE},
+ {"-iconic", ARG_ICONIC},
+#ifdef HAVE_GTK2
+ {"--role", ARG_ROLE|ARG_HAS_VALUE},
+#endif
+#ifdef FEAT_NETBEANS_INTG
+ {"-nb", ARG_NETBEANS}, /* non-standard value format */
+ {"-xrm", ARG_XRM|ARG_HAS_VALUE}, /* not implemented */
+ {"-mf", ARG_MENUFONT|ARG_HAS_VALUE}, /* not implemented */
+ {"-menufont", ARG_MENUFONT|ARG_HAS_VALUE}, /* not implemented */
+#endif
+#if 0 /* not implemented; these arguments don't make sense for GTK+ */
+ {"-boldfont", ARG_HAS_VALUE},
+ {"-italicfont", ARG_HAS_VALUE},
+ {"-bw", ARG_HAS_VALUE},
+ {"-borderwidth", ARG_HAS_VALUE},
+ {"-sw", ARG_HAS_VALUE},
+ {"-scrollbarwidth", ARG_HAS_VALUE},
+#endif
+ /* Arguments handled by GTK (and GNOME) internally. */
+ {"--g-fatal-warnings", ARG_FOR_GTK},
+ {"--gdk-debug", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--gdk-no-debug", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--gtk-debug", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--gtk-no-debug", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--gtk-module", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--sync", ARG_FOR_GTK},
+ {"--display", ARG_FOR_GTK|ARG_HAS_VALUE|ARG_COMPAT_LONG},
+ {"--name", ARG_FOR_GTK|ARG_HAS_VALUE|ARG_COMPAT_LONG},
+ {"--class", ARG_FOR_GTK|ARG_HAS_VALUE|ARG_COMPAT_LONG},
+#ifdef HAVE_GTK2
+ {"--screen", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--gxid-host", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--gxid-port", ARG_FOR_GTK|ARG_HAS_VALUE},
+#else /* these don't seem to exist anymore */
+ {"--no-xshm", ARG_FOR_GTK},
+ {"--xim-preedit", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--xim-status", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--gxid_host", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--gxid_port", ARG_FOR_GTK|ARG_HAS_VALUE},
+#endif
+#ifdef FEAT_GUI_GNOME
+ {"--load-modules", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--sm-client-id", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--sm-config-prefix", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--sm-disable", ARG_FOR_GTK},
+ {"--oaf-ior-fd", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--oaf-activate-iid", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"--oaf-private", ARG_FOR_GTK},
+ {"--enable-sound", ARG_FOR_GTK},
+ {"--disable-sound", ARG_FOR_GTK},
+ {"--espeaker", ARG_FOR_GTK|ARG_HAS_VALUE},
+ {"-?", ARG_FOR_GTK|ARG_NEEDS_GUI},
+ {"--help", ARG_FOR_GTK|ARG_NEEDS_GUI|ARG_KEEP},
+ {"--usage", ARG_FOR_GTK|ARG_NEEDS_GUI},
+# if 0 /* conflicts with Vim's own --version argument */
+ {"--version", ARG_FOR_GTK|ARG_NEEDS_GUI},
+# endif
+ {"--disable-crash-dialog", ARG_FOR_GTK},
+#endif
+ {NULL, 0}
+};
+
+static int gui_argc = 0;
+static char **gui_argv = NULL;
+
+#ifdef HAVE_GTK2
+static const char *role_argument = NULL;
+#endif
+#if defined(FEAT_GUI_GNOME) && defined(FEAT_SESSION)
+static const char *restart_command = NULL;
+#endif
+static int found_iconic_arg = FALSE;
+
+#ifdef FEAT_GUI_GNOME
+/*
+ * Can't use Gnome if --socketid given
+ */
+static int using_gnome = 0;
+#else
+# define using_gnome 0
+#endif
+
+/*
+ * Parse the GUI related command-line arguments. Any arguments used are
+ * deleted from argv, and *argc is decremented accordingly. This is called
+ * when vim is started, whether or not the GUI has been started.
+ */
+ void
+gui_mch_prepare(int *argc, char **argv)
+{
+ const cmdline_option_T *option;
+ int i = 0;
+ int len = 0;
+
+#if defined(FEAT_GUI_GNOME) && defined(FEAT_SESSION)
+ /*
+ * Determine the command used to invoke Vim, to be passed as restart
+ * command to the session manager. If argv[0] contains any directory
+ * components try building an absolute path, otherwise leave it as is.
+ */
+ restart_command = argv[0];
+
+ if (strchr(argv[0], G_DIR_SEPARATOR) != NULL)
+ {
+ char_u buf[MAXPATHL];
+
+ if (mch_FullName((char_u *)argv[0], buf, (int)sizeof(buf), TRUE) == OK)
+ /* Tiny leak; doesn't matter, and usually we don't even get here */
+ restart_command = (char *)vim_strsave(buf);
+ }
+#endif
+
+ /*
+ * Move all the entries in argv which are relevant to GTK+ and GNOME
+ * into gui_argv. Freed later in gui_mch_init().
+ */
+ gui_argc = 0;
+ gui_argv = (char **)alloc((unsigned)((*argc + 1) * sizeof(char *)));
+
+ g_return_if_fail(gui_argv != NULL);
+
+ gui_argv[gui_argc++] = argv[i++];
+
+ while (i < *argc)
+ {
+ /* Don't waste CPU cycles on non-option arguments. */
+ if (argv[i][0] != '-' && argv[i][0] != '+')
+ {
+ ++i;
+ continue;
+ }
+
+ /* Look for argv[i] in cmdline_options[] table. */
+ for (option = &cmdline_options[0]; option->name != NULL; ++option)
+ {
+ len = strlen(option->name);
+
+ if (strncmp(argv[i], option->name, len) == 0)
+ {
+ if (argv[i][len] == '\0')
+ break;
+ /* allow --foo=bar style */
+ if (argv[i][len] == '=' && (option->flags & ARG_HAS_VALUE))
+ break;
+#ifdef FEAT_NETBEANS_INTG
+ /* darn, -nb has non-standard syntax */
+ if (vim_strchr((char_u *)":=", argv[i][len]) != NULL
+ && (option->flags & ARG_INDEX_MASK) == ARG_NETBEANS)
+ break;
+#endif
+ }
+ else if ((option->flags & ARG_COMPAT_LONG)
+ && strcmp(argv[i], option->name + 1) == 0)
+ {
+ /* Replace the standard X arguments "-name" and "-display"
+ * with their GNU-style long option counterparts. */
+ argv[i] = (char *)option->name;
+ break;
+ }
+ }
+ if (option->name == NULL) /* no match */
+ {
+ ++i;
+ continue;
+ }
+
+ if (option->flags & ARG_FOR_GTK)
+ {
+ /* Move the argument into gui_argv, which
+ * will later be passed to gtk_init_check() */
+ gui_argv[gui_argc++] = argv[i];
+ }
+ else
+ {
+ char *value = NULL;
+
+ /* Extract the option's value if there is one.
+ * Accept both "--foo bar" and "--foo=bar" style. */
+ if (option->flags & ARG_HAS_VALUE)
+ {
+ if (argv[i][len] == '=')
+ value = &argv[i][len + 1];
+ else if (i + 1 < *argc && strcmp(argv[i + 1], "--") != 0)
+ value = argv[i + 1];
+ }
+
+ /* Check for options handled by Vim itself */
+ switch (option->flags & ARG_INDEX_MASK)
+ {
+ case ARG_REVERSE:
+ found_reverse_arg = TRUE;
+ break;
+ case ARG_NOREVERSE:
+ found_reverse_arg = FALSE;
+ break;
+ case ARG_FONT:
+ font_argument = value;
+ break;
+ case ARG_GEOMETRY:
+ if (value != NULL)
+ gui.geom = vim_strsave((char_u *)value);
+ break;
+ case ARG_BACKGROUND:
+ background_argument = value;
+ break;
+ case ARG_FOREGROUND:
+ foreground_argument = value;
+ break;
+ case ARG_ICONIC:
+ found_iconic_arg = TRUE;
+ break;
+#ifdef HAVE_GTK2
+ case ARG_ROLE:
+ role_argument = value; /* used later in gui_mch_open() */
+ break;
+#endif
+#ifdef FEAT_NETBEANS_INTG
+ case ARG_NETBEANS:
+ ++usingNetbeans;
+ gui.dofork = FALSE; /* don't fork() when starting GUI */
+ netbeansArg = argv[i];
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+
+ /* These arguments make gnome_program_init() print a message and exit.
+ * Must start the GUI for this, otherwise ":gui" will exit later! */
+ if (option->flags & ARG_NEEDS_GUI)
+ gui.starting = TRUE;
+
+ if (option->flags & ARG_KEEP)
+ ++i;
+ else
+ {
+ /* Remove the flag from the argument vector. */
+ if (--*argc > i)
+ {
+ int n_strip = 1;
+
+ /* Move the argument's value as well, if there is one. */
+ if ((option->flags & ARG_HAS_VALUE)
+ && argv[i][len] != '='
+ && strcmp(argv[i + 1], "--") != 0)
+ {
+ ++n_strip;
+ --*argc;
+ if (option->flags & ARG_FOR_GTK)
+ gui_argv[gui_argc++] = argv[i + 1];
+ }
+
+ if (*argc > i)
+ mch_memmove(&argv[i], &argv[i + n_strip],
+ (*argc - i) * sizeof(char *));
+ }
+ argv[*argc] = NULL;
+ }
+ }
+
+ gui_argv[gui_argc] = NULL;
+}
+
+/*
+ * This should be maybe completely removed.
+ * Doesn't seem possible, since check_copy_area() relies on
+ * this information. --danielk
+ */
+/*ARGSUSED*/
+ static gint
+visibility_event(GtkWidget *widget, GdkEventVisibility *event, gpointer data)
+{
+ gui.visibility = event->state;
+ /*
+ * When we do an gdk_window_copy_area(), and the window is partially
+ * obscured, we want to receive an event to tell us whether it worked
+ * or not.
+ */
+ if (gui.text_gc != NULL)
+ gdk_gc_set_exposures(gui.text_gc,
+ gui.visibility != GDK_VISIBILITY_UNOBSCURED);
+ return FALSE;
+}
+
+/*
+ * Redraw the corresponding portions of the screen.
+ */
+/*ARGSUSED*/
+ static gint
+expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+ /* Skip this when the GUI isn't set up yet, will redraw later. */
+ if (gui.starting)
+ return FALSE;
+
+ out_flush(); /* make sure all output has been processed */
+ gui_redraw(event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ /* Clear the border areas if needed */
+ if (event->area.x < FILL_X(0))
+ gdk_window_clear_area(gui.drawarea->window, 0, 0, FILL_X(0), 0);
+ if (event->area.y < FILL_Y(0))
+ gdk_window_clear_area(gui.drawarea->window, 0, 0, 0, FILL_Y(0));
+ if (event->area.x > FILL_X(Columns))
+ gdk_window_clear_area(gui.drawarea->window,
+ FILL_X((int)Columns), 0, 0, 0);
+ if (event->area.y > FILL_Y(Rows))
+ gdk_window_clear_area(gui.drawarea->window, 0, FILL_Y((int)Rows), 0, 0);
+
+ return FALSE;
+}
+
+#ifdef FEAT_CLIENTSERVER
+/*
+ * Handle changes to the "Comm" property
+ */
+/*ARGSUSED2*/
+ static gint
+property_event(GtkWidget *widget, GdkEventProperty *event, gpointer data)
+{
+ if (event->type == GDK_PROPERTY_NOTIFY
+ && event->state == (int)GDK_PROPERTY_NEW_VALUE
+ && GDK_WINDOW_XWINDOW(event->window) == commWindow
+ && GET_X_ATOM(event->atom) == commProperty)
+ {
+ XEvent xev;
+
+ /* Translate to XLib */
+ xev.xproperty.type = PropertyNotify;
+ xev.xproperty.atom = commProperty;
+ xev.xproperty.window = commWindow;
+ xev.xproperty.state = PropertyNewValue;
+ serverEventProc(GDK_WINDOW_XDISPLAY(widget->window), &xev);
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+ }
+ return FALSE;
+}
+#endif
+
+
+/****************************************************************************
+ * Focus handlers:
+ */
+
+
+/*
+ * This is a simple state machine:
+ * BLINK_NONE not blinking at all
+ * BLINK_OFF blinking, cursor is not shown
+ * BLINK_ON blinking, cursor is shown
+ */
+
+#define BLINK_NONE 0
+#define BLINK_OFF 1
+#define BLINK_ON 2
+
+static int blink_state = BLINK_NONE;
+static long_u blink_waittime = 700;
+static long_u blink_ontime = 400;
+static long_u blink_offtime = 250;
+static guint blink_timer = 0;
+
+ void
+gui_mch_set_blinking(long waittime, long on, long off)
+{
+ blink_waittime = waittime;
+ blink_ontime = on;
+ blink_offtime = off;
+}
+
+/*
+ * Stop the cursor blinking. Show the cursor if it wasn't shown.
+ */
+ void
+gui_mch_stop_blink(void)
+{
+ if (blink_timer)
+ {
+ gtk_timeout_remove(blink_timer);
+ blink_timer = 0;
+ }
+ if (blink_state == BLINK_OFF)
+ gui_update_cursor(TRUE, FALSE);
+ blink_state = BLINK_NONE;
+}
+
+/*ARGSUSED*/
+ static gint
+blink_cb(gpointer data)
+{
+ if (blink_state == BLINK_ON)
+ {
+ gui_undraw_cursor();
+ blink_state = BLINK_OFF;
+ blink_timer = gtk_timeout_add((guint32)blink_offtime,
+ (GtkFunction) blink_cb, NULL);
+ }
+ else
+ {
+ gui_update_cursor(TRUE, FALSE);
+ blink_state = BLINK_ON;
+ blink_timer = gtk_timeout_add((guint32)blink_ontime,
+ (GtkFunction) blink_cb, NULL);
+ }
+
+ return FALSE; /* don't happen again */
+}
+
+/*
+ * Start the cursor blinking. If it was already blinking, this restarts the
+ * waiting time and shows the cursor.
+ */
+ void
+gui_mch_start_blink(void)
+{
+ if (blink_timer)
+ gtk_timeout_remove(blink_timer);
+ /* Only switch blinking on if none of the times is zero */
+ if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
+ {
+ blink_timer = gtk_timeout_add((guint32)blink_waittime,
+ (GtkFunction) blink_cb, NULL);
+ blink_state = BLINK_ON;
+ gui_update_cursor(TRUE, FALSE);
+ }
+}
+
+/*ARGSUSED*/
+ static gint
+enter_notify_event(GtkWidget *widget, GdkEventCrossing *event, gpointer data)
+{
+ if (blink_state == BLINK_NONE)
+ gui_mch_start_blink();
+
+ /* make sure keyboard input goes there */
+ if (gtk_socket_id == 0 || !GTK_WIDGET_HAS_FOCUS(gui.drawarea))
+ gtk_widget_grab_focus(gui.drawarea);
+
+ return FALSE;
+}
+
+/*ARGSUSED*/
+ static gint
+leave_notify_event(GtkWidget *widget, GdkEventCrossing *event, gpointer data)
+{
+ if (blink_state != BLINK_NONE)
+ gui_mch_stop_blink();
+
+ return FALSE;
+}
+
+/*ARGSUSED*/
+ static gint
+focus_in_event(GtkWidget *widget, GdkEventFocus *event, gpointer data)
+{
+ gui_focus_change(TRUE);
+
+ if (blink_state == BLINK_NONE)
+ gui_mch_start_blink();
+
+ /* make sure keyboard input goes there */
+ if (gtk_socket_id == 0)
+ gtk_widget_grab_focus(gui.drawarea);
+
+ return TRUE;
+}
+
+/*ARGSUSED*/
+ static gint
+focus_out_event(GtkWidget *widget, GdkEventFocus *event, gpointer data)
+{
+ gui_focus_change(FALSE);
+
+ if (blink_state != BLINK_NONE)
+ gui_mch_stop_blink();
+
+ return TRUE;
+}
+
+
+#ifdef HAVE_GTK2
+/*
+ * Translate a GDK key value to UTF-8 independently of the current locale.
+ * The output is written to string, which must have room for at least 6 bytes
+ * plus the NUL terminator. Returns the length in bytes.
+ *
+ * This function is used in the GTK+ 2 GUI only. The GTK+ 1 code makes use
+ * of GdkEventKey::string instead. But event->string is evil; see here why:
+ * http://developer.gnome.org/doc/API/2.0/gdk/gdk-Event-Structures.html#GdkEventKey
+ */
+ static int
+keyval_to_string(unsigned int keyval, unsigned int state, char_u *string)
+{
+ int len;
+ guint32 uc;
+
+ uc = gdk_keyval_to_unicode(keyval);
+ if (uc != 0)
+ {
+ /* Check for CTRL-foo */
+ if ((state & GDK_CONTROL_MASK) && uc >= 0x20 && uc < 0x80)
+ {
+ /* These mappings look arbitrary at the first glance, but in fact
+ * resemble quite exactly the behaviour of the GTK+ 1.2 GUI on my
+ * machine. The only difference is BS vs. DEL for CTRL-8 (makes
+ * more sense and is consistent with usual terminal behaviour). */
+ if (uc >= '@')
+ string[0] = uc & 0x1F;
+ else if (uc == '2')
+ string[0] = NUL;
+ else if (uc >= '3' && uc <= '7')
+ string[0] = uc ^ 0x28;
+ else if (uc == '8')
+ string[0] = BS;
+ else if (uc == '?')
+ string[0] = DEL;
+ else
+ string[0] = uc;
+ len = 1;
+ }
+ else
+ {
+ /* Translate a normal key to UTF-8. This doesn't work for dead
+ * keys of course, you _have_ to use an input method for that. */
+ len = utf_char2bytes((int)uc, string);
+ }
+ }
+ else
+ {
+ /* Translate keys which are represented by ASCII control codes in Vim.
+ * There are only a few of those; most control keys are translated to
+ * special terminal-like control sequences. */
+ len = 1;
+ switch (keyval)
+ {
+ case GDK_Tab: case GDK_KP_Tab: case GDK_ISO_Left_Tab:
+ string[0] = TAB;
+ break;
+ case GDK_Linefeed:
+ string[0] = NL;
+ break;
+ case GDK_Return: case GDK_ISO_Enter: case GDK_3270_Enter:
+ string[0] = CAR;
+ break;
+ case GDK_Escape:
+ string[0] = ESC;
+ break;
+ default:
+ len = 0;
+ break;
+ }
+ }
+ string[len] = NUL;
+
+ return len;
+}
+#endif /* HAVE_GTK2 */
+
+/*
+ * Main keyboard handler:
+ */
+/*ARGSUSED*/
+ static gint
+key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+#ifdef HAVE_GTK2
+ /* 256 bytes is way over the top, but for safety let's reduce it only
+ * for GTK+ 2 where we know for sure how large the string might get.
+ * (That is, up to 6 bytes + NUL + CSI escapes + safety measure.) */
+ char_u string[32], string2[32];
+#else
+ char_u string[256], string2[256];
+#endif
+ guint key_sym;
+ int len;
+ int i;
+ int modifiers;
+ int key;
+ guint state;
+ char_u *s, *d;
+
+ key_sym = event->keyval;
+ state = event->state;
+#ifndef HAVE_GTK2 /* deprecated */
+ len = event->length;
+ g_assert(len <= sizeof(string));
+#endif
+
+#ifndef HAVE_GTK2
+ /*
+ * It appears as if we always want to consume a key-press (there currently
+ * aren't any 'return FALSE's), so we always do this: when running in a
+ * GtkPlug and not a window, we must prevent emission of the key_press
+ * EVENT from continuing (which is 'beyond' the level of stopping mere
+ * signals by returning FALSE), otherwise things like tab/cursor-keys are
+ * processed by the GtkPlug default handler, which moves input focus away
+ * from us!
+ * Note: This should no longer be necessary with GTK+ 2.
+ */
+ if (gtk_socket_id != 0)
+ gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event");
+#endif
+
+#ifdef FEAT_XIM
+ if (xim_queue_key_press_event(event, TRUE))
+ return TRUE;
+#endif
+
+#ifdef FEAT_HANGULIN
+ if (key_sym == GDK_space && (state & GDK_SHIFT_MASK))
+ {
+ hangul_input_state_toggle();
+ return TRUE;
+ }
+#endif
+
+#ifdef SunXK_F36
+ /*
+ * These keys have bogus lookup strings, and trapping them here is
+ * easier than trying to XRebindKeysym() on them with every possible
+ * combination of modifiers.
+ */
+ if (key_sym == SunXK_F36 || key_sym == SunXK_F37)
+ len = 0;
+ else
+#endif
+ {
+#ifdef HAVE_GTK2
+ len = keyval_to_string(key_sym, state, string2);
+
+ /* Careful: convert_input() doesn't handle the NUL character.
+ * No need to convert pure ASCII anyway, thus the len > 1 check. */
+ if (len > 1 && input_conv.vc_type != CONV_NONE)
+ len = convert_input(string2, len, sizeof(string2));
+
+ s = string2;
+#else
+# ifdef FEAT_MBYTE
+ if (input_conv.vc_type != CONV_NONE)
+ {
+ mch_memmove(string2, event->string, len);
+ len = convert_input(string2, len, sizeof(string2));
+ s = string2;
+ }
+ else
+# endif
+ s = (char_u *)event->string;
+#endif
+
+ d = string;
+ for (i = 0; i < len; ++i)
+ {
+ *d++ = s[i];
+ if (d[-1] == CSI && d + 2 < string + sizeof(string))
+ {
+ /* Turn CSI into K_CSI. */
+ *d++ = KS_EXTRA;
+ *d++ = (int)KE_CSI;
+ }
+ }
+ len = d - string;
+ }
+
+ /* Shift-Tab results in Left_Tab, but we want <S-Tab> */
+ if (key_sym == GDK_ISO_Left_Tab)
+ {
+ key_sym = GDK_Tab;
+ state |= GDK_SHIFT_MASK;
+ }
+
+#ifndef HAVE_GTK2 /* for GTK+ 2, we handle this in keyval_to_string() */
+ if ((key_sym == GDK_2 || key_sym == GDK_at) && (state & GDK_CONTROL_MASK))
+ {
+ string[0] = NUL; /* CTRL-2 and CTRL-@ is NUL */
+ len = 1;
+ }
+ else if (len == 0 && (key_sym == GDK_space || key_sym == GDK_Tab))
+ {
+ /* When there are modifiers, these keys get zero length; we need the
+ * original key here to be able to add a modifier below. */
+ string[0] = (key_sym & 0xff);
+ len = 1;
+ }
+#endif
+
+#ifdef FEAT_MENU
+ /* If there is a menu and 'wak' is "yes", or 'wak' is "menu" and the key
+ * is a menu shortcut, we ignore everything with the ALT modifier. */
+ if ((state & GDK_MOD1_MASK)
+ && gui.menu_is_active
+ && (*p_wak == 'y'
+ || (*p_wak == 'm'
+ && len == 1
+ && gui_is_menu_shortcut(string[0]))))
+# ifdef HAVE_GTK2
+ /* For GTK2 we return false to signify that we haven't handled the
+ * keypress, so that gtk will handle the mnemonic or accelerator. */
+ return FALSE;
+# else
+ return TRUE;
+# endif
+#endif
+
+ /* Check for Alt/Meta key (Mod1Mask), but not for a BS, DEL or character
+ * that already has the 8th bit set.
+ * Don't do this for <S-M-Tab>, that should become K_S_TAB with ALT.
+ * Don't do this for double-byte encodings, it turns the char into a lead
+ * byte. */
+ if (len == 1
+ && (state & GDK_MOD1_MASK)
+ && !(key_sym == GDK_BackSpace || key_sym == GDK_Delete)
+ && (string[0] & 0x80) == 0
+ && !(key_sym == GDK_Tab && (state & GDK_SHIFT_MASK))
+#ifdef FEAT_MBYTE
+ && !enc_dbcs
+#endif
+ )
+ {
+ string[0] |= 0x80;
+ state &= ~GDK_MOD1_MASK; /* don't use it again */
+#ifdef FEAT_MBYTE
+ if (enc_utf8) /* convert to utf-8 */
+ {
+ string[1] = string[0] & 0xbf;
+ string[0] = ((unsigned)string[0] >> 6) + 0xc0;
+ if (string[1] == CSI)
+ {
+ string[2] = KS_EXTRA;
+ string[3] = (int)KE_CSI;
+ len = 4;
+ }
+ else
+ len = 2;
+ }
+#endif
+ }
+
+ /* Check for special keys. Also do this when len == 1 (key has an ASCII
+ * value) to detect backspace, delete and keypad keys. */
+ if (len == 0 || len == 1)
+ {
+ for (i = 0; special_keys[i].key_sym != 0; i++)
+ {
+ if (special_keys[i].key_sym == key_sym)
+ {
+ string[0] = CSI;
+ string[1] = special_keys[i].code0;
+ string[2] = special_keys[i].code1;
+ len = -3;
+ break;
+ }
+ }
+ }
+
+ if (len == 0) /* Unrecognized key */
+ return TRUE;
+
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) && !defined(HAVE_GTK2)
+ /* Cancel or type backspace. For GTK2, im_commit_cb() does the same. */
+ preedit_start_col = MAXCOL;
+ xim_changed_while_preediting = TRUE;
+#endif
+
+ /* Special keys (and a few others) may have modifiers. Also when using a
+ * double-byte encoding (can't set the 8th bit). */
+ if (len == -3 || key_sym == GDK_space || key_sym == GDK_Tab
+ || key_sym == GDK_Return || key_sym == GDK_Linefeed
+ || key_sym == GDK_Escape || key_sym == GDK_KP_Tab
+ || key_sym == GDK_ISO_Enter || key_sym == GDK_3270_Enter
+#ifdef FEAT_MBYTE
+ || (enc_dbcs && len == 1 && (state & GDK_MOD1_MASK))
+#endif
+ )
+ {
+ modifiers = 0;
+ if (state & GDK_SHIFT_MASK)
+ modifiers |= MOD_MASK_SHIFT;
+ if (state & GDK_CONTROL_MASK)
+ modifiers |= MOD_MASK_CTRL;
+ if (state & GDK_MOD1_MASK)
+ modifiers |= MOD_MASK_ALT;
+
+ /*
+ * For some keys a shift modifier is translated into another key
+ * code.
+ */
+ if (len == -3)
+ key = TO_SPECIAL(string[1], string[2]);
+ else
+ key = string[0];
+
+ key = simplify_key(key, &modifiers);
+ if (key == CSI)
+ key = K_CSI;
+ if (IS_SPECIAL(key))
+ {
+ string[0] = CSI;
+ string[1] = K_SECOND(key);
+ string[2] = K_THIRD(key);
+ len = 3;
+ }
+ else
+ {
+ string[0] = key;
+ len = 1;
+ }
+
+ if (modifiers != 0)
+ {
+ string2[0] = CSI;
+ string2[1] = KS_MODIFIER;
+ string2[2] = modifiers;
+ add_to_input_buf(string2, 3);
+ }
+ }
+
+ if (len == 1 && ((string[0] == Ctrl_C && ctrl_c_interrupts)
+ || (string[0] == intr_char && intr_char != Ctrl_C)))
+ {
+ trash_input_buf();
+ got_int = TRUE;
+ }
+
+ add_to_input_buf(string, len);
+
+ /* blank out the pointer if necessary */
+ if (p_mh)
+ gui_mch_mousehide(TRUE);
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+
+ return TRUE;
+}
+
+#if defined(FEAT_XIM) && defined(HAVE_GTK2)
+/*ARGSUSED0*/
+ static gboolean
+key_release_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ /*
+ * GTK+ 2 input methods may do fancy stuff on key release events too.
+ * With the default IM for instance, you can enter any UCS code point
+ * by holding down CTRL-SHIFT and typing hexadecimal digits.
+ */
+ return xim_queue_key_press_event(event, FALSE);
+}
+#endif
+
+
+/****************************************************************************
+ * Selection handlers:
+ */
+
+/*ARGSUSED*/
+ static gint
+selection_clear_event(GtkWidget *widget,
+ GdkEventSelection *event,
+ gpointer user_data)
+{
+ if (event->selection == clip_plus.gtk_sel_atom)
+ clip_lose_selection(&clip_plus);
+ else
+ clip_lose_selection(&clip_star);
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+
+ return TRUE;
+}
+
+#define RS_NONE 0 /* selection_received_cb() not called yet */
+#define RS_OK 1 /* selection_received_cb() called and OK */
+#define RS_FAIL 2 /* selection_received_cb() called and failed */
+static int received_selection = RS_NONE;
+
+/*ARGSUSED*/
+ static void
+selection_received_cb(GtkWidget *widget,
+ GtkSelectionData *data,
+ guint time_,
+ gpointer user_data)
+{
+ VimClipboard *cbd;
+ char_u *text;
+ char_u *tmpbuf = NULL;
+#ifdef HAVE_GTK2
+ guchar *tmpbuf_utf8 = NULL;
+#endif
+ int len;
+ int motion_type;
+
+ if (data->selection == clip_plus.gtk_sel_atom)
+ cbd = &clip_plus;
+ else
+ cbd = &clip_star;
+
+ text = (char_u *)data->data;
+ len = data->length;
+ motion_type = MCHAR;
+
+ if (text == NULL || len <= 0)
+ {
+ received_selection = RS_FAIL;
+ /* clip_free_selection(cbd); ??? */
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+
+ return;
+ }
+
+ if (data->type == vim_atom)
+ {
+ motion_type = *text++;
+ --len;
+ }
+
+#ifdef FEAT_MBYTE
+ else if (data->type == vimenc_atom)
+ {
+ char_u *enc;
+ vimconv_T conv;
+
+ motion_type = *text++;
+ --len;
+
+ enc = text;
+ text += STRLEN(text) + 1;
+ len -= text - enc;
+
+ /* If the encoding of the text is different from 'encoding', attempt
+ * converting it. */
+ conv.vc_type = CONV_NONE;
+ convert_setup(&conv, enc, p_enc);
+ if (conv.vc_type != CONV_NONE)
+ {
+ tmpbuf = string_convert(&conv, text, &len);
+ if (tmpbuf != NULL)
+ text = tmpbuf;
+ convert_setup(&conv, NULL, NULL);
+ }
+ }
+#endif
+
+#ifdef HAVE_GTK2
+ /* gtk_selection_data_get_text() handles all the nasty details
+ * and targets and encodings etc. This rocks so hard. */
+ else
+ {
+ tmpbuf_utf8 = gtk_selection_data_get_text(data);
+ if (tmpbuf_utf8 != NULL)
+ {
+ len = STRLEN(tmpbuf_utf8);
+ if (input_conv.vc_type != CONV_NONE)
+ {
+ tmpbuf = string_convert(&input_conv, tmpbuf_utf8, &len);
+ if (tmpbuf != NULL)
+ text = tmpbuf;
+ }
+ else
+ text = tmpbuf_utf8;
+ }
+ }
+#else /* !HAVE_GTK2 */
+# ifdef FEAT_MBYTE
+ else if (data->type == utf8_string_atom)
+ {
+ vimconv_T conv;
+
+ conv.vc_type = CONV_NONE;
+ convert_setup(&conv, (char_u *)"utf-8", p_enc);
+
+ if (conv.vc_type != CONV_NONE)
+ {
+ tmpbuf = string_convert(&conv, text, &len);
+ convert_setup(&conv, NULL, NULL);
+ }
+ if (tmpbuf != NULL)
+ text = tmpbuf;
+ }
+# endif
+ else if (data->type == compound_text_atom || data->type == text_atom)
+ {
+ char **list = NULL;
+ int count;
+ int i;
+ unsigned tmplen = 0;
+
+ count = gdk_text_property_to_text_list(data->type, data->format,
+ data->data, data->length,
+ &list);
+ for (i = 0; i < count; ++i)
+ tmplen += strlen(list[i]);
+
+ tmpbuf = alloc(tmplen + 1);
+ if (tmpbuf != NULL)
+ {
+ tmpbuf[0] = NUL;
+ for (i = 0; i < count; ++i)
+ STRCAT(tmpbuf, list[i]);
+ text = tmpbuf;
+ len = tmplen;
+ }
+
+ if (list != NULL)
+ gdk_free_text_list(list);
+ }
+#endif /* !HAVE_GTK2 */
+
+ clip_yank_selection(motion_type, text, (long)len, cbd);
+ received_selection = RS_OK;
+ vim_free(tmpbuf);
+#ifdef HAVE_GTK2
+ g_free(tmpbuf_utf8);
+#endif
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+/*
+ * Prepare our selection data for passing it to the external selection
+ * client.
+ */
+/*ARGSUSED*/
+ static void
+selection_get_cb(GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time_,
+ gpointer user_data)
+{
+ char_u *string;
+ char_u *tmpbuf;
+ long_u tmplen;
+ int length;
+ int motion_type;
+ GdkAtom type;
+ VimClipboard *cbd;
+
+ if (selection_data->selection == clip_plus.gtk_sel_atom)
+ cbd = &clip_plus;
+ else
+ cbd = &clip_star;
+
+ if (!cbd->owned)
+ return; /* Shouldn't ever happen */
+
+ if (info != (guint)TARGET_STRING
+#ifdef FEAT_MBYTE
+ && info != (guint)TARGET_UTF8_STRING
+ && info != (guint)TARGET_VIMENC
+#endif
+ && info != (guint)TARGET_VIM
+ && info != (guint)TARGET_COMPOUND_TEXT
+ && info != (guint)TARGET_TEXT)
+ return;
+
+ /* get the selection from the '*'/'+' register */
+ clip_get_selection(cbd);
+
+ motion_type = clip_convert_selection(&string, &tmplen, cbd);
+ if (motion_type < 0 || string == NULL)
+ return;
+ /* Due to int arguments we can't handle more than G_MAXINT. Also
+ * reserve one extra byte for NUL or the motion type; just in case.
+ * (Not that pasting 2G of text is ever going to work, but... ;-) */
+ length = MIN(tmplen, (long_u)(G_MAXINT - 1));
+
+ if (info == (guint)TARGET_VIM)
+ {
+ tmpbuf = alloc((unsigned)length + 1);
+ if (tmpbuf != NULL)
+ {
+ tmpbuf[0] = motion_type;
+ mch_memmove(tmpbuf + 1, string, (size_t)length);
+ }
+ /* For our own format, the first byte contains the motion type */
+ ++length;
+ vim_free(string);
+ string = tmpbuf;
+ type = vim_atom;
+ }
+
+#ifdef FEAT_MBYTE
+ else if (info == (guint)TARGET_VIMENC)
+ {
+ int l = STRLEN(p_enc);
+
+ /* contents: motion_type 'encoding' NUL text */
+ tmpbuf = alloc((unsigned)length + l + 2);
+ if (tmpbuf != NULL)
+ {
+ tmpbuf[0] = motion_type;
+ STRCPY(tmpbuf + 1, p_enc);
+ mch_memmove(tmpbuf + l + 2, string, (size_t)length);
+ }
+ length += l + 2;
+ vim_free(string);
+ string = tmpbuf;
+ type = vimenc_atom;
+ }
+#endif
+
+#ifdef HAVE_GTK2
+ /* gtk_selection_data_set_text() handles everything for us. This is
+ * so easy and simple and cool, it'd be insane not to use it. */
+ else
+ {
+ if (output_conv.vc_type != CONV_NONE)
+ {
+ tmpbuf = string_convert(&output_conv, string, &length);
+ vim_free(string);
+ if (tmpbuf == NULL)
+ return;
+ string = tmpbuf;
+ }
+ /* Validate the string to avoid runtime warnings */
+ if (g_utf8_validate((const char *)string, (gssize)length, NULL))
+ {
+ gtk_selection_data_set_text(selection_data,
+ (const char *)string, length);
+ }
+ vim_free(string);
+ return;
+ }
+#else /* !HAVE_GTK2 */
+# ifdef FEAT_MBYTE
+ else if (info == (guint)TARGET_UTF8_STRING)
+ {
+ vimconv_T conv;
+
+ conv.vc_type = CONV_NONE;
+ convert_setup(&conv, p_enc, (char_u *)"utf-8");
+
+ if (conv.vc_type != CONV_NONE)
+ {
+ tmpbuf = string_convert(&conv, string, &length);
+ convert_setup(&conv, NULL, NULL);
+ vim_free(string);
+ string = tmpbuf;
+ }
+ type = utf8_string_atom;
+ }
+# endif
+ else if (info == (guint)TARGET_COMPOUND_TEXT
+ || info == (guint)TARGET_TEXT)
+ {
+ int format;
+
+ /* Copy the string to ensure NUL-termination */
+ tmpbuf = vim_strnsave(string, length);
+ vim_free(string);
+ if (tmpbuf != NULL)
+ {
+ gdk_string_to_compound_text((const char *)tmpbuf,
+ &type, &format, &string, &length);
+ vim_free(tmpbuf);
+ selection_data->type = type;
+ selection_data->format = format;
+ gtk_selection_data_set(selection_data, type, format, string, length);
+ gdk_free_compound_text(string);
+ }
+ return;
+ }
+ else
+ {
+ type = GDK_TARGET_STRING;
+ }
+#endif /* !HAVE_GTK2 */
+
+ if (string != NULL)
+ {
+ selection_data->type = selection_data->target;
+ selection_data->format = 8; /* 8 bits per char */
+
+ gtk_selection_data_set(selection_data, type, 8, string, length);
+ vim_free(string);
+ }
+}
+
+/*
+ * Check if the GUI can be started. Called before gvimrc is sourced.
+ * Return OK or FAIL.
+ */
+ int
+gui_mch_init_check(void)
+{
+#ifndef HAVE_GTK2
+ /* This is needed to make the locale handling consistant between the GUI
+ * and the rest of VIM. */
+ gtk_set_locale();
+#endif
+
+#ifdef FEAT_GUI_GNOME
+ if (gtk_socket_id == 0)
+ using_gnome = 1;
+#endif
+
+ /* Don't use gtk_init() or gnome_init(), it exits on failure. */
+ if (!gtk_init_check(&gui_argc, &gui_argv))
+ {
+ gui.dying = TRUE;
+ EMSG(_(e_opendisp));
+ return FAIL;
+ }
+
+ return OK;
+}
+
+
+/****************************************************************************
+ * Mouse handling callbacks
+ */
+
+
+static guint mouse_click_timer = 0;
+static int mouse_timed_out = TRUE;
+
+/*
+ * Timer used to recognize multiple clicks of the mouse button
+ */
+ static gint
+mouse_click_timer_cb(gpointer data)
+{
+ /* we don't use this information currently */
+ int *timed_out = (int *) data;
+
+ *timed_out = TRUE;
+ return FALSE; /* don't happen again */
+}
+
+static guint motion_repeat_timer = 0;
+static int motion_repeat_offset = FALSE;
+static gint motion_repeat_timer_cb(gpointer);
+
+ static void
+process_motion_notify(int x, int y, GdkModifierType state)
+{
+ int button;
+ int_u vim_modifiers;
+
+ button = (state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK |
+ GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
+ GDK_BUTTON5_MASK))
+ ? MOUSE_DRAG : ' ';
+
+ /* If our pointer is currently hidden, then we should show it. */
+ gui_mch_mousehide(FALSE);
+
+ /* Just moving the rodent above the drawing area without any button
+ * being pressed. */
+ if (button != MOUSE_DRAG)
+ {
+ gui_mouse_moved(x, y);
+ return;
+ }
+
+ /* translate modifier coding between the main engine and GTK */
+ vim_modifiers = 0x0;
+ if (state & GDK_SHIFT_MASK)
+ vim_modifiers |= MOUSE_SHIFT;
+ if (state & GDK_CONTROL_MASK)
+ vim_modifiers |= MOUSE_CTRL;
+ if (state & GDK_MOD1_MASK)
+ vim_modifiers |= MOUSE_ALT;
+
+ /* inform the editor engine about the occurence of this event */
+ gui_send_mouse_event(button, x, y, FALSE, vim_modifiers);
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+
+ /*
+ * Auto repeat timer handling.
+ */
+ if (x < 0 || y < 0
+ || x >= gui.drawarea->allocation.width
+ || y >= gui.drawarea->allocation.height)
+ {
+
+ int dx;
+ int dy;
+ int offshoot;
+ int delay = 10;
+
+ /* Calculate the maximal distance of the cursor from the drawing area.
+ * (offshoot can't become negative here!).
+ */
+ dx = x < 0 ? -x : x - gui.drawarea->allocation.width;
+ dy = y < 0 ? -y : y - gui.drawarea->allocation.height;
+
+ offshoot = dx > dy ? dx : dy;
+
+ /* Make a linearly declaying timer delay with a threshold of 5 at a
+ * distance of 127 pixels from the main window.
+ *
+ * One could think endlessly about the most ergonomic variant here.
+ * For example it could make sense to calculate the distance from the
+ * drags start instead...
+ *
+ * Maybe a parabolic interpolation would suite us better here too...
+ */
+ if (offshoot > 127)
+ {
+ /* 5 appears to be somehow near to my perceptual limits :-). */
+ delay = 5;
+ }
+ else
+ {
+ delay = (130 * (127 - offshoot)) / 127 + 5;
+ }
+
+ /* shoot again */
+ if (!motion_repeat_timer)
+ motion_repeat_timer = gtk_timeout_add((guint32)delay,
+ motion_repeat_timer_cb, NULL);
+ }
+}
+
+/*
+ * Timer used to recognize multiple clicks of the mouse button.
+ */
+/*ARGSUSED0*/
+ static gint
+motion_repeat_timer_cb(gpointer data)
+{
+ int x;
+ int y;
+ GdkModifierType state;
+
+ gdk_window_get_pointer(gui.drawarea->window, &x, &y, &state);
+
+ if (!(state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK |
+ GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
+ GDK_BUTTON5_MASK)))
+ {
+ motion_repeat_timer = 0;
+ return FALSE;
+ }
+
+ /* If there already is a mouse click in the input buffer, wait another
+ * time (otherwise we would create a backlog of clicks) */
+ if (vim_used_in_input_buf() > 10)
+ return TRUE;
+
+ motion_repeat_timer = 0;
+
+ /*
+ * Fake a motion event.
+ * Trick: Pretend the mouse moved to the next character on every other
+ * event, otherwise drag events will be discarded, because they are still
+ * in the same character.
+ */
+ if (motion_repeat_offset)
+ x += gui.char_width;
+
+ motion_repeat_offset = !motion_repeat_offset;
+ process_motion_notify(x, y, state);
+
+ /* Don't happen again. We will get reinstalled in the synthetic event
+ * if needed -- thus repeating should still work. */
+ return FALSE;
+}
+
+/*ARGSUSED2*/
+ static gint
+motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
+{
+ if (event->is_hint)
+ {
+ int x;
+ int y;
+ GdkModifierType state;
+
+ gdk_window_get_pointer(widget->window, &x, &y, &state);
+ process_motion_notify(x, y, state);
+ }
+ else
+ {
+ process_motion_notify((int)event->x, (int)event->y,
+ (GdkModifierType)event->state);
+ }
+
+ return TRUE; /* handled */
+}
+
+
+/*
+ * Mouse button handling. Note please that we are capturing multiple click's
+ * by our own timeout mechanism instead of the one provided by GTK+ itself.
+ * This is due to the way the generic VIM code is recognizing multiple clicks.
+ */
+/*ARGSUSED2*/
+ static gint
+button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+ int button;
+ int repeated_click = FALSE;
+ int x, y;
+ int_u vim_modifiers;
+
+ /* Make sure we have focus now we've been selected */
+ if (gtk_socket_id != 0 && !GTK_WIDGET_HAS_FOCUS(widget))
+ gtk_widget_grab_focus(widget);
+
+ /*
+ * Don't let additional events about multiple clicks send by GTK to us
+ * after the initial button press event confuse us.
+ */
+ if (event->type != GDK_BUTTON_PRESS)
+ return FALSE;
+
+ x = event->x;
+ y = event->y;
+
+ /* Handle multiple clicks */
+ if (!mouse_timed_out && mouse_click_timer)
+ {
+ gtk_timeout_remove(mouse_click_timer);
+ mouse_click_timer = 0;
+ repeated_click = TRUE;
+ }
+
+ mouse_timed_out = FALSE;
+ mouse_click_timer = gtk_timeout_add((guint32)p_mouset,
+ mouse_click_timer_cb, &mouse_timed_out);
+
+ switch (event->button)
+ {
+ case 1:
+ button = MOUSE_LEFT;
+ break;
+ case 2:
+ button = MOUSE_MIDDLE;
+ break;
+ case 3:
+ button = MOUSE_RIGHT;
+ break;
+#ifndef HAVE_GTK2
+ case 4:
+ button = MOUSE_4;
+ break;
+ case 5:
+ button = MOUSE_5;
+ break;
+#endif
+ default:
+ return FALSE; /* Unknown button */
+ }
+
+#ifdef FEAT_XIM
+ /* cancel any preediting */
+ if (im_is_preediting())
+ xim_reset();
+#endif
+
+ vim_modifiers = 0x0;
+ if (event->state & GDK_SHIFT_MASK)
+ vim_modifiers |= MOUSE_SHIFT;
+ if (event->state & GDK_CONTROL_MASK)
+ vim_modifiers |= MOUSE_CTRL;
+ if (event->state & GDK_MOD1_MASK)
+ vim_modifiers |= MOUSE_ALT;
+
+ gui_send_mouse_event(button, x, y, repeated_click, vim_modifiers);
+ if (gtk_main_level() > 0)
+ gtk_main_quit(); /* make sure the above will be handled immediately */
+
+ return TRUE;
+}
+
+#ifdef HAVE_GTK2
+/*
+ * GTK+ 2 doesn't handle mouse buttons 4, 5, 6 and 7 the same way as GTK+ 1.
+ * Instead, it abstracts scrolling via the new GdkEventScroll.
+ */
+/*ARGSUSED2*/
+ static gboolean
+scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data)
+{
+ int button;
+ int_u vim_modifiers = 0;
+
+ if (gtk_socket_id != 0 && !GTK_WIDGET_HAS_FOCUS(widget))
+ gtk_widget_grab_focus(widget);
+
+ switch (event->direction)
+ {
+ case GDK_SCROLL_UP:
+ button = MOUSE_4;
+ break;
+ case GDK_SCROLL_DOWN:
+ button = MOUSE_5;
+ break;
+ default: /* We don't care about left and right... Yet. */
+ return FALSE;
+ }
+
+# ifdef FEAT_XIM
+ /* cancel any preediting */
+ if (im_is_preediting())
+ xim_reset();
+# endif
+
+ if (event->state & GDK_SHIFT_MASK)
+ vim_modifiers |= MOUSE_SHIFT;
+ if (event->state & GDK_CONTROL_MASK)
+ vim_modifiers |= MOUSE_CTRL;
+ if (event->state & GDK_MOD1_MASK)
+ vim_modifiers |= MOUSE_ALT;
+
+ gui_send_mouse_event(button, (int)event->x, (int)event->y,
+ FALSE, vim_modifiers);
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit(); /* make sure the above will be handled immediately */
+
+ return TRUE;
+}
+#endif /* HAVE_GTK2 */
+
+
+/*ARGSUSED*/
+ static gint
+button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+ int x, y;
+ int_u vim_modifiers;
+
+ /* Remove any motion "machine gun" timers used for automatic further
+ extension of allocation areas if outside of the applications window
+ area .*/
+ if (motion_repeat_timer)
+ {
+ gtk_timeout_remove(motion_repeat_timer);
+ motion_repeat_timer = 0;
+ }
+
+ x = event->x;
+ y = event->y;
+
+ vim_modifiers = 0x0;
+ if (event->state & GDK_SHIFT_MASK)
+ vim_modifiers |= MOUSE_SHIFT;
+ if (event->state & GDK_CONTROL_MASK)
+ vim_modifiers |= MOUSE_CTRL;
+ if (event->state & GDK_MOD1_MASK)
+ vim_modifiers |= MOUSE_ALT;
+
+ gui_send_mouse_event(MOUSE_RELEASE, x, y, FALSE, vim_modifiers);
+ if (gtk_main_level() > 0)
+ gtk_main_quit(); /* make sure it will be handled immediately */
+
+ return TRUE;
+}
+
+
+#ifdef FEAT_DND
+/****************************************************************************
+ * Drag aNd Drop support handlers.
+ */
+
+/*
+ * Count how many items there may be and separate them with a NUL.
+ * Apparently the items are separated with \r\n. This is not documented,
+ * thus be careful not to go past the end. Also allow separation with
+ * NUL characters.
+ */
+ static int
+count_and_decode_uri_list(char_u *out, char_u *raw, int len)
+{
+ int i;
+ char_u *p = out;
+ int count = 0;
+
+ for (i = 0; i < len; ++i)
+ {
+ if (raw[i] == NUL || raw[i] == '\n' || raw[i] == '\r')
+ {
+ if (p > out && p[-1] != NUL)
+ {
+ ++count;
+ *p++ = NUL;
+ }
+ }
+ else if (raw[i] == '%' && i + 2 < len && hexhex2nr(raw + i + 1) > 0)
+ {
+ *p++ = hexhex2nr(raw + i + 1);
+ i += 2;
+ }
+ else
+ *p++ = raw[i];
+ }
+ if (p > out && p[-1] != NUL)
+ {
+ *p = NUL; /* last item didn't have \r or \n */
+ ++count;
+ }
+ return count;
+}
+
+/*
+ * Parse NUL separated "src" strings. Make it an array "outlist" form. On
+ * this process, URI which protocol is not "file:" are removed. Return
+ * length of array (less than "max").
+ */
+ static int
+filter_uri_list(char_u **outlist, int max, char_u *src)
+{
+ int i, j;
+
+ for (i = j = 0; i < max; ++i)
+ {
+ outlist[i] = NULL;
+ if (STRNCMP(src, "file:", 5) == 0)
+ {
+ src += 5;
+ if (STRNCMP(src, "//localhost", 11) == 0)
+ src += 11;
+ while (src[0] == '/' && src[1] == '/')
+ ++src;
+ outlist[j++] = vim_strsave(src);
+ }
+ src += STRLEN(src) + 1;
+ }
+ return j;
+}
+
+ static char_u **
+parse_uri_list(int *count, char_u *data, int len)
+{
+ int n = 0;
+ char_u *tmp = NULL;
+ char_u **array = NULL;;
+
+ if (data != NULL && len > 0 && (tmp = (char_u *)alloc(len + 1)) != NULL)
+ {
+ n = count_and_decode_uri_list(tmp, data, len);
+ if (n > 0 && (array = (char_u **)alloc(n * sizeof(char_u *))) != NULL)
+ n = filter_uri_list(array, n, tmp);
+ }
+ vim_free(tmp);
+ *count = n;
+ return array;
+}
+
+ static void
+drag_handle_uri_list(GdkDragContext *context,
+ GtkSelectionData *data,
+ guint time_,
+ GdkModifierType state,
+ gint x,
+ gint y)
+{
+ char_u **fnames;
+ int nfiles = 0;
+
+ fnames = parse_uri_list(&nfiles, data->data, data->length);
+
+ if (fnames != NULL && nfiles > 0)
+ {
+ int_u modifiers = 0;
+
+ gtk_drag_finish(context, TRUE, FALSE, time_); /* accept */
+
+ if (state & GDK_SHIFT_MASK)
+ modifiers |= MOUSE_SHIFT;
+ if (state & GDK_CONTROL_MASK)
+ modifiers |= MOUSE_CTRL;
+ if (state & GDK_MOD1_MASK)
+ modifiers |= MOUSE_ALT;
+
+ gui_handle_drop(x, y, modifiers, fnames, nfiles);
+ }
+}
+
+ static void
+drag_handle_text(GdkDragContext *context,
+ GtkSelectionData *data,
+ guint time_,
+ GdkModifierType state)
+{
+ char_u dropkey[6] = {CSI, KS_MODIFIER, 0, CSI, KS_EXTRA, (char_u)KE_DROP};
+ char_u *text;
+ int len;
+# ifdef FEAT_MBYTE
+ char_u *tmpbuf = NULL;
+# endif
+
+ text = data->data;
+ len = data->length;
+
+# ifdef FEAT_MBYTE
+ if (data->type == utf8_string_atom)
+ {
+# ifdef HAVE_GTK2
+ if (input_conv.vc_type != CONV_NONE)
+ tmpbuf = string_convert(&input_conv, text, &len);
+# else
+ vimconv_T conv;
+
+ conv.vc_type = CONV_NONE;
+ convert_setup(&conv, (char_u *)"utf-8", p_enc);
+
+ if (conv.vc_type != CONV_NONE)
+ {
+ tmpbuf = string_convert(&conv, text, &len);
+ convert_setup(&conv, NULL, NULL);
+ }
+# endif
+ if (tmpbuf != NULL)
+ text = tmpbuf;
+ }
+# endif /* FEAT_MBYTE */
+
+ dnd_yank_drag_data(text, (long)len);
+ gtk_drag_finish(context, TRUE, FALSE, time_); /* accept */
+# ifdef FEAT_MBYTE
+ vim_free(tmpbuf);
+# endif
+
+ if (state & GDK_SHIFT_MASK)
+ dropkey[2] |= MOD_MASK_SHIFT;
+ if (state & GDK_CONTROL_MASK)
+ dropkey[2] |= MOD_MASK_CTRL;
+ if (state & GDK_MOD1_MASK)
+ dropkey[2] |= MOD_MASK_ALT;
+
+ if (dropkey[2] != 0)
+ add_to_input_buf(dropkey, (int)sizeof(dropkey));
+ else
+ add_to_input_buf(dropkey + 3, (int)(sizeof(dropkey) - 3));
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+/*
+ * DND receiver.
+ */
+/*ARGSUSED2*/
+ static void
+drag_data_received_cb(GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time_,
+ gpointer user_data)
+{
+ GdkModifierType state;
+
+ /* Guard against trash */
+ if (data->data == NULL
+ || data->length <= 0
+ || data->format != 8
+ || data->data[data->length] != '\0')
+ {
+ gtk_drag_finish(context, FALSE, FALSE, time_);
+ return;
+ }
+
+ /* Get the current modifier state for proper distinguishment between
+ * different operations later. */
+ gdk_window_get_pointer(widget->window, NULL, NULL, &state);
+
+ /* Not sure about the role of "text/plain" here... */
+ if (info == (guint)TARGET_TEXT_URI_LIST)
+ drag_handle_uri_list(context, data, time_, state, x, y);
+ else
+ drag_handle_text(context, data, time_, state);
+
+}
+#endif /* FEAT_DND */
+
+
+#if defined(FEAT_GUI_GNOME) && defined(FEAT_SESSION)
+/*
+ * GnomeClient interact callback. Check for unsaved buffers that cannot
+ * be abandoned and pop up a dialog asking the user for confirmation if
+ * necessary.
+ */
+/*ARGSUSED0*/
+ static void
+sm_client_check_changed_any(GnomeClient *client,
+ gint key,
+ GnomeDialogType type,
+ gpointer data)
+{
+ cmdmod_T save_cmdmod;
+ gboolean shutdown_cancelled;
+
+ save_cmdmod = cmdmod;
+
+# ifdef FEAT_BROWSE
+ cmdmod.browse = TRUE;
+# endif
+# if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ cmdmod.confirm = TRUE;
+# endif
+ /*
+ * If there are changed buffers, present the user with
+ * a dialog if possible, otherwise give an error message.
+ */
+ shutdown_cancelled = check_changed_any(FALSE);
+
+ exiting = FALSE;
+ cmdmod = save_cmdmod;
+ setcursor(); /* position the cursor */
+ out_flush();
+ /*
+ * If the user hit the [Cancel] button the whole shutdown
+ * will be cancelled. Wow, quite powerful feature (:
+ */
+ gnome_interaction_key_return(key, shutdown_cancelled);
+}
+
+/*
+ * Generate a script that can be used to restore the current editing session.
+ * Save the value of v:this_session before running :mksession in order to make
+ * automagic session save fully transparent. Return TRUE on success.
+ */
+ static int
+write_session_file(char_u *filename)
+{
+ char_u *escaped_filename;
+ char *mksession_cmdline;
+ unsigned int save_ssop_flags;
+ int failed;
+
+ /*
+ * Build an ex command line to create a script that restores the current
+ * session if executed. Escape the filename to avoid nasty surprises.
+ */
+ escaped_filename = vim_strsave_escaped(filename, escape_chars);
+ if (escaped_filename == NULL)
+ return FALSE;
+ mksession_cmdline = g_strconcat("mksession ", (char *)escaped_filename, NULL);
+ vim_free(escaped_filename);
+ /*
+ * Use a reasonable hardcoded set of 'sessionoptions' flags to avoid
+ * unpredictable effects when the session is saved automatically. Also,
+ * we definitely need SSOP_GLOBALS to be able to restore v:this_session.
+ * Don't use SSOP_BUFFERS to prevent the buffer list from becoming
+ * enormously large if the GNOME session feature is used regularly.
+ */
+ save_ssop_flags = ssop_flags;
+ ssop_flags = (SSOP_BLANK|SSOP_CURDIR|SSOP_FOLDS|SSOP_GLOBALS
+ |SSOP_HELP|SSOP_OPTIONS|SSOP_WINSIZE);
+
+ do_cmdline_cmd((char_u *)"let Save_VV_this_session = v:this_session");
+ failed = (do_cmdline_cmd((char_u *)mksession_cmdline) == FAIL);
+ do_cmdline_cmd((char_u *)"let v:this_session = Save_VV_this_session");
+ do_unlet((char_u *)"Save_VV_this_session");
+
+ ssop_flags = save_ssop_flags;
+ g_free(mksession_cmdline);
+ /*
+ * Reopen the file and append a command to restore v:this_session,
+ * as if this save never happened. This is to avoid conflicts with
+ * the user's own sessions. FIXME: It's probably less hackish to add
+ * a "stealth" flag to 'sessionoptions' -- gotta ask Bram.
+ */
+ if (!failed)
+ {
+ FILE *fd;
+
+ fd = open_exfile(filename, TRUE, APPENDBIN);
+
+ failed = (fd == NULL
+ || put_line(fd, "let v:this_session = Save_VV_this_session") == FAIL
+ || put_line(fd, "unlet Save_VV_this_session") == FAIL);
+
+ if (fd != NULL && fclose(fd) != 0)
+ failed = TRUE;
+
+ if (failed)
+ mch_remove(filename);
+ }
+
+ return !failed;
+}
+
+/*
+ * "save_yourself" signal handler. Initiate an interaction to ask the user
+ * for confirmation if necessary. Save the current editing session and tell
+ * the session manager how to restart Vim.
+ */
+/*ARGSUSED1*/
+ static gboolean
+sm_client_save_yourself(GnomeClient *client,
+ gint phase,
+ GnomeSaveStyle save_style,
+ gboolean shutdown,
+ GnomeInteractStyle interact_style,
+ gboolean fast,
+ gpointer data)
+{
+ static const char suffix[] = "-session.vim";
+ char *session_file;
+ unsigned int len;
+ gboolean success;
+
+ /* Always request an interaction if possible. check_changed_any()
+ * won't actually show a dialog unless any buffers have been modified.
+ * There doesn't seem to be an obvious way to check that without
+ * automatically firing the dialog. Anyway, it works just fine. */
+ if (interact_style == GNOME_INTERACT_ANY)
+ gnome_client_request_interaction(client, GNOME_DIALOG_NORMAL,
+ &sm_client_check_changed_any,
+ NULL);
+ out_flush();
+ ml_sync_all(FALSE, FALSE); /* preserve all swap files */
+
+ /* The path is unique for each session save. We do neither know nor care
+ * which session script will actually be used later. This decision is in
+ * the domain of the session manager. */
+ session_file = gnome_config_get_real_path(
+ gnome_client_get_config_prefix(client));
+ len = strlen(session_file);
+
+ if (len > 0 && session_file[len-1] == G_DIR_SEPARATOR)
+ --len; /* get rid of the superfluous trailing '/' */
+
+ session_file = g_renew(char, session_file, len + sizeof(suffix));
+ memcpy(session_file + len, suffix, sizeof(suffix));
+
+ success = write_session_file((char_u *)session_file);
+
+ if (success)
+ {
+ const char *argv[8];
+ int i;
+
+ /* Tell the session manager how to wipe out the stored session data.
+ * This isn't as dangerous as it looks, don't worry :) session_file
+ * is a unique absolute filename. Usually it'll be something like
+ * `/home/user/.gnome2/vim-XXXXXX-session.vim'. */
+ i = 0;
+ argv[i++] = "rm";
+ argv[i++] = session_file;
+ argv[i] = NULL;
+
+ gnome_client_set_discard_command(client, i, (char **)argv);
+
+ /* Tell the session manager how to restore the just saved session.
+ * This is easily done thanks to Vim's -S option. Pass the -f flag
+ * since there's no need to fork -- it might even cause confusion.
+ * Also pass the window role to give the WM something to match on.
+ * The role is set in gui_mch_open(), thus should _never_ be NULL. */
+ i = 0;
+ argv[i++] = restart_command;
+ argv[i++] = "-f";
+ argv[i++] = "-g";
+# ifdef HAVE_GTK2
+ argv[i++] = "--role";
+ argv[i++] = gtk_window_get_role(GTK_WINDOW(gui.mainwin));
+# endif
+ argv[i++] = "-S";
+ argv[i++] = session_file;
+ argv[i] = NULL;
+
+ gnome_client_set_restart_command(client, i, (char **)argv);
+ gnome_client_set_clone_command(client, 0, NULL);
+ }
+
+ g_free(session_file);
+
+ return success;
+}
+
+/*
+ * Called when the session manager wants us to die. There isn't much to save
+ * here since "save_yourself" has been emitted before (unless serious trouble
+ * is happening).
+ */
+/*ARGSUSED0*/
+ static void
+sm_client_die(GnomeClient *client, gpointer data)
+{
+ /* Don't write messages to the GUI anymore */
+ full_screen = FALSE;
+
+ STRNCPY(IObuff, _("Vim: Received \"die\" request from session manager\n"),
+ IOSIZE);
+ IObuff[IOSIZE - 1] = NUL;
+ preserve_exit();
+}
+
+/*
+ * Connect our signal handlers to be notified on session save and shutdown.
+ */
+ static void
+setup_save_yourself(void)
+{
+ GnomeClient *client;
+
+ client = gnome_master_client();
+
+ if (client != NULL)
+ {
+ /* Must use the deprecated gtk_signal_connect() for compatibility
+ * with GNOME 1. Arrgh, zombies! */
+ gtk_signal_connect(GTK_OBJECT(client), "save_yourself",
+ GTK_SIGNAL_FUNC(&sm_client_save_yourself), NULL);
+ gtk_signal_connect(GTK_OBJECT(client), "die",
+ GTK_SIGNAL_FUNC(&sm_client_die), NULL);
+ }
+}
+
+#else /* !(FEAT_GUI_GNOME && FEAT_SESSION) */
+
+# ifdef USE_XSMP
+/*
+ * GTK tells us that XSMP needs attention
+ */
+/*ARGSUSED*/
+ static gboolean
+local_xsmp_handle_requests(source, condition, data)
+ GIOChannel *source;
+ GIOCondition condition;
+ gpointer data;
+{
+ if (condition == G_IO_IN)
+ {
+ /* Do stuff; maybe close connection */
+ if (xsmp_handle_requests() == FAIL)
+ g_io_channel_unref((GIOChannel *)data);
+ return TRUE;
+ }
+ /* Error */
+ g_io_channel_unref((GIOChannel *)data);
+ xsmp_close();
+ return TRUE;
+}
+# endif /* USE_XSMP */
+
+/*
+ * Setup the WM_PROTOCOLS to indicate we want the WM_SAVE_YOURSELF event.
+ * This is an ugly use of X functions. GTK doesn't offer an alternative.
+ */
+ static void
+setup_save_yourself(void)
+{
+ Atom *existing_atoms = NULL;
+ int count = 0;
+
+#ifdef USE_XSMP
+ if (xsmp_icefd != -1)
+ {
+ /*
+ * Use XSMP is preference to legacy WM_SAVE_YOURSELF;
+ * set up GTK IO monitor
+ */
+ GIOChannel *g_io = g_io_channel_unix_new(xsmp_icefd);
+
+ g_io_add_watch(g_io, G_IO_IN | G_IO_ERR | G_IO_HUP,
+ local_xsmp_handle_requests, (gpointer)g_io);
+ }
+ else
+#endif
+ {
+ /* Fall back to old method */
+
+ /* first get the existing value */
+ if (XGetWMProtocols(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
+ GDK_WINDOW_XWINDOW(gui.mainwin->window),
+ &existing_atoms, &count))
+ {
+ Atom *new_atoms;
+ Atom save_yourself_xatom;
+ int i;
+
+ save_yourself_xatom = GET_X_ATOM(save_yourself_atom);
+
+ /* check if WM_SAVE_YOURSELF isn't there yet */
+ for (i = 0; i < count; ++i)
+ if (existing_atoms[i] == save_yourself_xatom)
+ break;
+
+ if (i == count)
+ {
+ /* allocate an Atoms array which is one item longer */
+ new_atoms = (Atom *)alloc((unsigned)((count + 1)
+ * sizeof(Atom)));
+ if (new_atoms != NULL)
+ {
+ memcpy(new_atoms, existing_atoms, count * sizeof(Atom));
+ new_atoms[count] = save_yourself_xatom;
+ XSetWMProtocols(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
+ GDK_WINDOW_XWINDOW(gui.mainwin->window),
+ new_atoms, count + 1);
+ vim_free(new_atoms);
+ }
+ }
+ XFree(existing_atoms);
+ }
+ }
+}
+
+# ifdef HAVE_GTK2
+/*
+ * Installing a global event filter seems to be the only way to catch
+ * client messages of type WM_PROTOCOLS without overriding GDK's own
+ * client message event filter. Well, that's still better than trying
+ * to guess what the GDK filter had done if it had been invoked instead
+ * (This is what we did for GTK+ 1.2, see below).
+ *
+ * GTK2_FIXME: This doesn't seem to work. For some reason we never
+ * receive WM_SAVE_YOURSELF even though everything is set up correctly.
+ * I have the nasty feeling modern session managers just don't send this
+ * deprecated message anymore. Addition: confirmed by several people.
+ *
+ * The GNOME session support is much cooler anyway. Unlike this ugly
+ * WM_SAVE_YOURSELF hack it actually stores the session... And yes,
+ * it should work with KDE as well.
+ */
+/*ARGSUSED1*/
+ static GdkFilterReturn
+global_event_filter(GdkXEvent *xev, GdkEvent *event, gpointer data)
+{
+ XEvent *xevent = (XEvent *)xev;
+
+ if (xevent != NULL
+ && xevent->type == ClientMessage
+ && xevent->xclient.message_type == GET_X_ATOM(wm_protocols_atom)
+ && xevent->xclient.data.l[0] == GET_X_ATOM(save_yourself_atom))
+ {
+ out_flush();
+ ml_sync_all(FALSE, FALSE); /* preserve all swap files */
+ /*
+ * Set the window's WM_COMMAND property, to let the window manager
+ * know we are done saving ourselves. We don't want to be
+ * restarted, thus set argv to NULL.
+ */
+ XSetCommand(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
+ GDK_WINDOW_XWINDOW(gui.mainwin->window),
+ NULL, 0);
+ return GDK_FILTER_REMOVE;
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+# else /* !HAVE_GTK2 */
+
+/*
+ * GDK handler for X ClientMessage events.
+ */
+/*ARGSUSED2*/
+ static GdkFilterReturn
+gdk_wm_protocols_filter(GdkXEvent *xev, GdkEvent *event, gpointer data)
+{
+ /* From example in gdkevents.c/gdk_wm_protocols_filter */
+ XEvent *xevent = (XEvent *)xev;
+
+ if (xevent != NULL)
+ {
+ if (xevent->xclient.data.l[0] == GET_X_ATOM(save_yourself_atom))
+ {
+ out_flush();
+ ml_sync_all(FALSE, FALSE); /* preserve all swap files */
+
+ /* Set the window's WM_COMMAND property, to let the window manager
+ * know we are done saving ourselves. We don't want to be
+ * restarted, thus set argv to NULL. */
+ XSetCommand(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
+ GDK_WINDOW_XWINDOW(gui.mainwin->window),
+ NULL, 0);
+ }
+ /*
+ * Functionality from gdkevents.c/gdk_wm_protocols_filter;
+ * Registering this filter apparently overrides the default GDK one,
+ * so we need to perform its functionality. There seems no way to
+ * register for WM_PROTOCOLS, and only process the WM_SAVE_YOURSELF
+ * bit; it's all or nothing. Update: No, there is a way -- but it
+ * only works with GTK+ 2 apparently. See above.
+ */
+ else if (xevent->xclient.data.l[0] == GET_X_ATOM(gdk_wm_delete_window))
+ {
+ event->any.type = GDK_DELETE;
+ return GDK_FILTER_TRANSLATE;
+ }
+ }
+
+ return GDK_FILTER_REMOVE;
+}
+# endif /* !HAVE_GTK2 */
+
+#endif /* !(FEAT_GUI_GNOME && FEAT_SESSION) */
+
+
+/*
+ * Setup the window icon & xcmdsrv comm after the main window has been realized.
+ */
+/*ARGSUSED*/
+ static void
+mainwin_realize(GtkWidget *widget, gpointer data)
+{
+/* If you get an error message here, you still need to unpack the runtime
+ * archive! */
+#ifdef magick
+# undef magick
+#endif
+#ifdef HAVE_GTK2
+ /* A bit hackish, but avoids casting later and allows optimization */
+# define static static const
+#endif
+#define magick vim32x32
+#include "../runtime/vim32x32.xpm"
+#undef magick
+#define magick vim16x16
+#include "../runtime/vim16x16.xpm"
+#undef magick
+#define magick vim48x48
+#include "../runtime/vim48x48.xpm"
+#undef magick
+#ifdef HAVE_GTK2
+# undef static
+#endif
+
+ /* When started with "--echo-wid" argument, write window ID on stdout. */
+ if (echo_wid_arg)
+ {
+ printf("WID: %ld\n", (long)GDK_WINDOW_XWINDOW(gui.mainwin->window));
+ fflush(stdout);
+ }
+
+ if (vim_strchr(p_go, GO_ICON) != NULL)
+ {
+ /*
+ * Add an icon to the main window. For fun and convenience of the user.
+ */
+#ifdef HAVE_GTK2
+ GList *icons = NULL;
+
+ icons = g_list_prepend(icons, gdk_pixbuf_new_from_xpm_data(vim16x16));
+ icons = g_list_prepend(icons, gdk_pixbuf_new_from_xpm_data(vim32x32));
+ icons = g_list_prepend(icons, gdk_pixbuf_new_from_xpm_data(vim48x48));
+
+ gtk_window_set_icon_list(GTK_WINDOW(gui.mainwin), icons);
+
+ g_list_foreach(icons, (GFunc)&g_object_unref, NULL);
+ g_list_free(icons);
+
+#else /* !HAVE_GTK2 */
+
+ GdkPixmap *icon;
+ GdkBitmap *icon_mask = NULL;
+ char **magick = vim32x32;
+ Display *xdisplay;
+ Window root_window;
+ XIconSize *size;
+ int number_sizes;
+ /*
+ * Adjust the icon to the preferences of the actual window manager.
+ * This is once again a workaround for a defficiency in GTK+ 1.2.
+ */
+ xdisplay = GDK_WINDOW_XDISPLAY(gui.mainwin->window);
+ root_window = XRootWindow(xdisplay, DefaultScreen(xdisplay));
+ if (XGetIconSizes(xdisplay, root_window, &size, &number_sizes))
+ {
+ if (number_sizes > 0)
+ {
+ if (size->max_height >= 48 && size->max_height >= 48)
+ magick = vim48x48;
+ else if (size->max_height >= 32 && size->max_height >= 32)
+ magick = vim32x32;
+ else if (size->max_height >= 16 && size->max_height >= 16)
+ magick = vim16x16;
+ }
+ XFree(size);
+ }
+ icon = gdk_pixmap_create_from_xpm_d(gui.mainwin->window,
+ &icon_mask, NULL, magick);
+ if (icon != NULL)
+ /* Note: for some reason gdk_window_set_icon() doesn't acquire
+ * a reference on the pixmap, thus we _have_ to leak it. */
+ gdk_window_set_icon(gui.mainwin->window, NULL, icon, icon_mask);
+
+#endif /* !HAVE_GTK2 */
+ }
+
+#if !(defined(FEAT_GUI_GNOME) && defined(FEAT_SESSION))
+ /* Register a handler for WM_SAVE_YOURSELF with GDK's low-level X I/F */
+# ifdef HAVE_GTK2
+ gdk_window_add_filter(NULL, &global_event_filter, NULL);
+# else
+ gdk_add_client_message_filter(wm_protocols_atom,
+ &gdk_wm_protocols_filter, NULL);
+# endif
+#endif
+ /* Setup to indicate to the window manager that we want to catch the
+ * WM_SAVE_YOURSELF event. For GNOME, this connects to the session
+ * manager instead. */
+#if defined(FEAT_GUI_GNOME) && defined(FEAT_SESSION)
+ if (using_gnome)
+#endif
+ setup_save_yourself();
+
+#ifdef FEAT_CLIENTSERVER
+ if (serverName == NULL && serverDelayedStartName != NULL)
+ {
+ /* This is a :gui command in a plain vim with no previous server */
+ commWindow = GDK_WINDOW_XWINDOW(gui.mainwin->window);
+
+ (void)serverRegisterName(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
+ serverDelayedStartName);
+ }
+ else
+ {
+ /*
+ * Cannot handle "XLib-only" windows with gtk event routines, we'll
+ * have to change the "server" registration to that of the main window
+ * If we have not registered a name yet, remember the window
+ */
+ serverChangeRegisteredWindow(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
+ GDK_WINDOW_XWINDOW(gui.mainwin->window));
+ }
+ gtk_widget_add_events(gui.mainwin, GDK_PROPERTY_CHANGE_MASK);
+ gtk_signal_connect(GTK_OBJECT(gui.mainwin), "property_notify_event",
+ GTK_SIGNAL_FUNC(property_event), NULL);
+#endif
+}
+
+ static GdkCursor *
+create_blank_pointer(void)
+{
+ GdkWindow *root_window = NULL;
+ GdkPixmap *blank_mask;
+ GdkCursor *cursor;
+ GdkColor color = { 0, 0, 0, 0 };
+ char blank_data[] = { 0x0 };
+
+#ifdef HAVE_GTK_MULTIHEAD
+ root_window = gtk_widget_get_root_window(gui.mainwin);
+#endif
+
+ /* Create a pseudo blank pointer, which is in fact one pixel by one pixel
+ * in size. */
+ blank_mask = gdk_bitmap_create_from_data(root_window, blank_data, 1, 1);
+ cursor = gdk_cursor_new_from_pixmap(blank_mask, blank_mask,
+ &color, &color, 0, 0);
+ gdk_bitmap_unref(blank_mask);
+
+ return cursor;
+}
+
+#ifdef HAVE_GTK_MULTIHEAD
+/*ARGSUSED1*/
+ static void
+mainwin_screen_changed_cb(GtkWidget *widget,
+ GdkScreen *previous_screen,
+ gpointer data)
+{
+ if (!gtk_widget_has_screen(widget))
+ return;
+
+ /*
+ * Recreate the invisble mouse cursor.
+ */
+ if (gui.blank_pointer != NULL)
+ gdk_cursor_unref(gui.blank_pointer);
+
+ gui.blank_pointer = create_blank_pointer();
+
+ if (gui.pointer_hidden && gui.drawarea->window != NULL)
+ gdk_window_set_cursor(gui.drawarea->window, gui.blank_pointer);
+
+ /*
+ * Create a new PangoContext for this screen, and initialize it
+ * with the current font if necessary.
+ */
+ if (gui.text_context != NULL)
+ g_object_unref(gui.text_context);
+
+ gui.text_context = gtk_widget_create_pango_context(widget);
+ pango_context_set_base_dir(gui.text_context, PANGO_DIRECTION_LTR);
+
+ if (gui.norm_font != NULL)
+ {
+ gui_mch_init_font(p_guifont, 0);
+ gui_set_shellsize(FALSE, FALSE);
+ }
+}
+#endif /* HAVE_GTK_MULTIHEAD */
+
+/*
+ * After the drawing area comes up, we calculate all colors and create the
+ * dummy blank cursor.
+ *
+ * Don't try to set any VIM scrollbar sizes anywhere here. I'm relying on the
+ * fact that the main VIM engine doesn't take them into account anywhere.
+ */
+/*ARGSUSED1*/
+ static void
+drawarea_realize_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWidget *sbar;
+
+#ifdef FEAT_XIM
+ xim_init();
+#endif
+ gui_mch_new_colors();
+ gui.text_gc = gdk_gc_new(gui.drawarea->window);
+
+ gui.blank_pointer = create_blank_pointer();
+ if (gui.pointer_hidden)
+ gdk_window_set_cursor(widget->window, gui.blank_pointer);
+
+ /* get the actual size of the scrollbars, if they are realized */
+ sbar = firstwin->w_scrollbars[SBAR_LEFT].id;
+ if (!sbar || (!gui.which_scrollbars[SBAR_LEFT]
+ && firstwin->w_scrollbars[SBAR_RIGHT].id))
+ sbar = firstwin->w_scrollbars[SBAR_RIGHT].id;
+ if (sbar && GTK_WIDGET_REALIZED(sbar) && sbar->allocation.width)
+ gui.scrollbar_width = sbar->allocation.width;
+
+ sbar = gui.bottom_sbar.id;
+ if (sbar && GTK_WIDGET_REALIZED(sbar) && sbar->allocation.height)
+ gui.scrollbar_height = sbar->allocation.height;
+}
+
+/*
+ * Properly clean up on shutdown.
+ */
+/*ARGSUSED0*/
+ static void
+drawarea_unrealize_cb(GtkWidget *widget, gpointer data)
+{
+ /* Don't write messages to the GUI anymore */
+ full_screen = FALSE;
+
+#ifdef FEAT_XIM
+ im_shutdown();
+#endif
+#ifdef HAVE_GTK2
+ if (gui.ascii_glyphs != NULL)
+ {
+ pango_glyph_string_free(gui.ascii_glyphs);
+ gui.ascii_glyphs = NULL;
+ }
+ if (gui.ascii_font != NULL)
+ {
+ g_object_unref(gui.ascii_font);
+ gui.ascii_font = NULL;
+ }
+ g_object_unref(gui.text_context);
+ gui.text_context = NULL;
+
+ g_object_unref(gui.text_gc);
+ gui.text_gc = NULL;
+
+ gdk_cursor_unref(gui.blank_pointer);
+ gui.blank_pointer = NULL;
+#else
+ gdk_gc_unref(gui.text_gc);
+ gui.text_gc = NULL;
+
+ gdk_cursor_destroy(gui.blank_pointer);
+ gui.blank_pointer = NULL;
+#endif
+}
+
+/*ARGSUSED0*/
+ static void
+drawarea_style_set_cb(GtkWidget *widget,
+ GtkStyle *previous_style,
+ gpointer data)
+{
+ gui_mch_new_colors();
+}
+
+/*
+ * Callback routine for the "delete_event" signal on the toplevel window.
+ * Tries to vim gracefully, or refuses to exit with changed buffers.
+ */
+/*ARGSUSED*/
+ static gint
+delete_event_cb(GtkWidget *widget, GdkEventAny *event, gpointer data)
+{
+ gui_shell_closed();
+ return TRUE;
+}
+
+#ifdef FEAT_TOOLBAR
+
+# ifdef HAVE_GTK2
+/*
+ * This extra effort wouldn't be necessary if we only used stock icons in the
+ * toolbar, as we do for all builtin icons. But user-defined toolbar icons
+ * shouldn't be treated differently, thus we do need this.
+ */
+ static void
+icon_size_changed_foreach(GtkWidget *widget, gpointer user_data)
+{
+ if (GTK_IS_IMAGE(widget))
+ {
+ GtkImage *image = (GtkImage *)widget;
+
+ /* User-defined icons are stored in a GtkIconSet */
+ if (gtk_image_get_storage_type(image) == GTK_IMAGE_ICON_SET)
+ {
+ GtkIconSet *icon_set;
+ GtkIconSize icon_size;
+
+ gtk_image_get_icon_set(image, &icon_set, &icon_size);
+ icon_size = (GtkIconSize)(long)user_data;
+
+ gtk_icon_set_ref(icon_set);
+ gtk_image_set_from_icon_set(image, icon_set, icon_size);
+ gtk_icon_set_unref(icon_set);
+ }
+ }
+ else if (GTK_IS_CONTAINER(widget))
+ {
+ gtk_container_foreach((GtkContainer *)widget,
+ &icon_size_changed_foreach,
+ user_data);
+ }
+}
+# endif /* HAVE_GTK2 */
+
+ static void
+set_toolbar_style(GtkToolbar *toolbar)
+{
+ GtkToolbarStyle style;
+# ifdef HAVE_GTK2
+ GtkIconSize size;
+ GtkIconSize oldsize;
+# endif
+
+# ifdef HAVE_GTK2
+ if ((toolbar_flags & (TOOLBAR_TEXT | TOOLBAR_ICONS | TOOLBAR_HORIZ))
+ == (TOOLBAR_TEXT | TOOLBAR_ICONS | TOOLBAR_HORIZ))
+ style = GTK_TOOLBAR_BOTH_HORIZ;
+ else
+# endif
+ if ((toolbar_flags & (TOOLBAR_TEXT | TOOLBAR_ICONS))
+ == (TOOLBAR_TEXT | TOOLBAR_ICONS))
+ style = GTK_TOOLBAR_BOTH;
+ else if (toolbar_flags & TOOLBAR_TEXT)
+ style = GTK_TOOLBAR_TEXT;
+ else
+ style = GTK_TOOLBAR_ICONS;
+
+ gtk_toolbar_set_style(toolbar, style);
+ gtk_toolbar_set_tooltips(toolbar, (toolbar_flags & TOOLBAR_TOOLTIPS) != 0);
+
+# ifdef HAVE_GTK2
+ switch (tbis_flags)
+ {
+ case TBIS_TINY: size = GTK_ICON_SIZE_MENU; break;
+ case TBIS_SMALL: size = GTK_ICON_SIZE_SMALL_TOOLBAR; break;
+ case TBIS_MEDIUM: size = GTK_ICON_SIZE_BUTTON; break;
+ case TBIS_LARGE: size = GTK_ICON_SIZE_LARGE_TOOLBAR; break;
+ default: size = GTK_ICON_SIZE_INVALID; break;
+ }
+ oldsize = gtk_toolbar_get_icon_size(toolbar);
+
+ if (size == GTK_ICON_SIZE_INVALID)
+ {
+ /* Let global user preferences decide the icon size. */
+ gtk_toolbar_unset_icon_size(toolbar);
+ size = gtk_toolbar_get_icon_size(toolbar);
+ }
+ if (size != oldsize)
+ {
+ gtk_container_foreach(GTK_CONTAINER(toolbar),
+ &icon_size_changed_foreach,
+ GINT_TO_POINTER((int)size));
+ }
+ gtk_toolbar_set_icon_size(toolbar, size);
+# endif
+}
+
+#endif /* FEAT_TOOLBAR */
+
+/*
+ * Initialize the GUI. Create all the windows, set up all the callbacks etc.
+ * Returns OK for success, FAIL when the GUI can't be started.
+ */
+ int
+gui_mch_init(void)
+{
+ GtkWidget *vbox;
+
+#ifdef FEAT_GUI_GNOME
+ /* Initialize the GNOME libraries. gnome_program_init()/gnome_init()
+ * exits on failure, but that's a non-issue because we already called
+ * gtk_init_check() in gui_mch_init_check(). */
+ if (using_gnome)
+# ifdef HAVE_GTK2
+ gnome_program_init(VIMPACKAGE, VIM_VERSION_SHORT,
+ LIBGNOMEUI_MODULE, gui_argc, gui_argv, NULL);
+# else
+ gnome_init(VIMPACKAGE, VIM_VERSION_SHORT, gui_argc, gui_argv);
+# endif
+#endif
+ vim_free(gui_argv);
+ gui_argv = NULL;
+
+#ifdef HAVE_GTK2
+# if GLIB_CHECK_VERSION(2,1,3)
+ /* Set the human-readable application name */
+ g_set_application_name("Vim");
+# endif
+ /*
+ * Force UTF-8 output no matter what the value of 'encoding' is.
+ * did_set_string_option() in option.c prohibits changing 'termencoding'
+ * to something else than UTF-8 if the GUI is in use.
+ */
+ set_option_value((char_u *)"termencoding", 0L, (char_u *)"utf-8", 0);
+
+# ifdef FEAT_TOOLBAR
+ gui_gtk_register_stock_icons();
+# endif
+ /* FIXME: Need to install the classic icons and a gtkrc.classic file.
+ * The hard part is deciding install locations and the Makefile magic. */
+# if 0
+ gtk_rc_parse("gtkrc");
+# endif
+#endif
+
+ /* Initialize values */
+ gui.border_width = 2;
+ gui.scrollbar_width = SB_DEFAULT_WIDTH;
+ gui.scrollbar_height = SB_DEFAULT_WIDTH;
+ gui.fgcolor = g_new0(GdkColor, 1);
+ gui.bgcolor = g_new0(GdkColor, 1);
+
+ /* Initialise atoms */
+#ifdef FEAT_MBYTE
+ utf8_string_atom = gdk_atom_intern("UTF8_STRING", FALSE);
+#endif
+#ifndef HAVE_GTK2
+ compound_text_atom = gdk_atom_intern("COMPOUND_TEXT", FALSE);
+ text_atom = gdk_atom_intern("TEXT", FALSE);
+#endif
+
+ /* Set default foreground and background colors. */
+ gui.norm_pixel = gui.def_norm_pixel;
+ gui.back_pixel = gui.def_back_pixel;
+
+ if (gtk_socket_id != 0)
+ {
+ GtkWidget *plug;
+
+ /* Use GtkSocket from another app. */
+#ifdef HAVE_GTK_MULTIHEAD
+ plug = gtk_plug_new_for_display(gdk_display_get_default(),
+ gtk_socket_id);
+#else
+ plug = gtk_plug_new(gtk_socket_id);
+#endif
+ if (plug != NULL && GTK_PLUG(plug)->socket_window != NULL)
+ {
+ gui.mainwin = plug;
+ }
+ else
+ {
+ g_warning("Connection to GTK+ socket (ID %u) failed",
+ (unsigned int)gtk_socket_id);
+ /* Pretend we never wanted it if it failed (get own window) */
+ gtk_socket_id = 0;
+ }
+ }
+
+ if (gtk_socket_id == 0)
+ {
+#ifdef FEAT_GUI_GNOME
+ if (using_gnome)
+ {
+ gui.mainwin = gnome_app_new("Vim", NULL);
+# ifdef USE_XSMP
+ /* Use the GNOME save-yourself functionality now. */
+ xsmp_close();
+# endif
+ }
+ else
+#endif
+ gui.mainwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ }
+
+ gtk_widget_set_name(gui.mainwin, "vim-main-window");
+
+#ifdef HAVE_GTK2
+ /* Create the PangoContext used for drawing all text. */
+ gui.text_context = gtk_widget_create_pango_context(gui.mainwin);
+ pango_context_set_base_dir(gui.text_context, PANGO_DIRECTION_LTR);
+#endif
+
+#ifndef HAVE_GTK2
+ gtk_window_set_policy(GTK_WINDOW(gui.mainwin), TRUE, TRUE, TRUE);
+#endif
+ gtk_container_border_width(GTK_CONTAINER(gui.mainwin), 0);
+ gtk_widget_add_events(gui.mainwin, GDK_VISIBILITY_NOTIFY_MASK);
+
+ gtk_signal_connect(GTK_OBJECT(gui.mainwin), "delete_event",
+ GTK_SIGNAL_FUNC(&delete_event_cb), NULL);
+
+ gtk_signal_connect(GTK_OBJECT(gui.mainwin), "realize",
+ GTK_SIGNAL_FUNC(&mainwin_realize), NULL);
+#ifdef HAVE_GTK_MULTIHEAD
+ g_signal_connect(G_OBJECT(gui.mainwin), "screen_changed",
+ G_CALLBACK(&mainwin_screen_changed_cb), NULL);
+#endif
+#ifdef HAVE_GTK2
+ gui.accel_group = gtk_accel_group_new();
+ gtk_window_add_accel_group(GTK_WINDOW(gui.mainwin), gui.accel_group);
+#else
+ gui.accel_group = gtk_accel_group_get_default();
+#endif
+
+ vbox = gtk_vbox_new(FALSE, 0);
+
+#ifdef FEAT_GUI_GNOME
+ if (using_gnome)
+ {
+# if defined(HAVE_GTK2) && defined(FEAT_MENU)
+ /* automagically restore menubar/toolbar placement */
+ gnome_app_enable_layout_config(GNOME_APP(gui.mainwin), TRUE);
+# endif
+ gnome_app_set_contents(GNOME_APP(gui.mainwin), vbox);
+ }
+ else
+#endif
+ {
+ gtk_container_add(GTK_CONTAINER(gui.mainwin), vbox);
+ gtk_widget_show(vbox);
+ }
+
+#ifdef FEAT_MENU
+ /*
+ * Create the menubar and handle
+ */
+ gui.menubar = gtk_menu_bar_new();
+ gtk_widget_set_name(gui.menubar, "vim-menubar");
+
+# ifdef FEAT_GUI_GNOME
+ if (using_gnome)
+ {
+# ifdef HAVE_GTK2
+ BonoboDockItem *dockitem;
+
+ gnome_app_set_menus(GNOME_APP(gui.mainwin), GTK_MENU_BAR(gui.menubar));
+ dockitem = gnome_app_get_dock_item_by_name(GNOME_APP(gui.mainwin),
+ GNOME_APP_MENUBAR_NAME);
+ gui.menubar_h = GTK_WIDGET(dockitem);
+# else
+ gui.menubar_h = gnome_dock_item_new("VimMainMenu",
+ GNOME_DOCK_ITEM_BEH_EXCLUSIVE |
+ GNOME_DOCK_ITEM_BEH_NEVER_VERTICAL);
+ gtk_container_add(GTK_CONTAINER(gui.menubar_h), gui.menubar);
+
+ gnome_dock_add_item(GNOME_DOCK(GNOME_APP(gui.mainwin)->dock),
+ GNOME_DOCK_ITEM(gui.menubar_h),
+ GNOME_DOCK_TOP, /* placement */
+ 1, /* band_num */
+ 0, /* band_position */
+ 0, /* offset */
+ TRUE);
+ gtk_widget_show(gui.menubar);
+# endif
+ }
+ else
+# endif /* FEAT_GUI_GNOME */
+ {
+ if (vim_strchr(p_go, GO_MENUS) != NULL)
+ gtk_widget_show(gui.menubar);
+ gtk_box_pack_start(GTK_BOX(vbox), gui.menubar, FALSE, FALSE, 0);
+ }
+#endif /* FEAT_MENU */
+
+#ifdef FEAT_TOOLBAR
+ /*
+ * Create the toolbar and handle
+ */
+# ifdef HAVE_GTK2
+ /* some aesthetics on the toolbar */
+ gtk_rc_parse_string(
+ "style \"vim-toolbar-style\" {\n"
+ " GtkToolbar::button_relief = GTK_RELIEF_NONE\n"
+ "}\n"
+ "widget \"*.vim-toolbar\" style \"vim-toolbar-style\"\n");
+ gui.toolbar = gtk_toolbar_new();
+ gtk_widget_set_name(gui.toolbar, "vim-toolbar");
+# else
+ gui.toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
+ GTK_TOOLBAR_ICONS);
+ gtk_toolbar_set_button_relief(GTK_TOOLBAR(gui.toolbar), GTK_RELIEF_NONE);
+# endif
+ set_toolbar_style(GTK_TOOLBAR(gui.toolbar));
+
+# ifdef FEAT_GUI_GNOME
+ if (using_gnome)
+ {
+# ifdef HAVE_GTK2
+ BonoboDockItem *dockitem;
+
+ gnome_app_set_toolbar(GNOME_APP(gui.mainwin), GTK_TOOLBAR(gui.toolbar));
+ dockitem = gnome_app_get_dock_item_by_name(GNOME_APP(gui.mainwin),
+ GNOME_APP_TOOLBAR_NAME);
+ gui.toolbar_h = GTK_WIDGET(dockitem);
+ gtk_container_set_border_width(GTK_CONTAINER(gui.toolbar), 0);
+# else
+ GtkWidget *dockitem;
+
+ dockitem = gnome_dock_item_new("VimToolBar",
+ GNOME_DOCK_ITEM_BEH_EXCLUSIVE);
+ gtk_container_add(GTK_CONTAINER(dockitem), GTK_WIDGET(gui.toolbar));
+ gui.toolbar_h = dockitem;
+
+ gnome_dock_add_item(GNOME_DOCK(GNOME_APP(gui.mainwin)->dock),
+ GNOME_DOCK_ITEM(dockitem),
+ GNOME_DOCK_TOP, /* placement */
+ 1, /* band_num */
+ 1, /* band_position */
+ 0, /* offset */
+ TRUE);
+ gtk_container_border_width(GTK_CONTAINER(gui.toolbar), 2);
+ gtk_widget_show(gui.toolbar);
+# endif
+ }
+ else
+# endif /* FEAT_GUI_GNOME */
+ {
+# ifndef HAVE_GTK2
+ gtk_container_border_width(GTK_CONTAINER(gui.toolbar), 1);
+# endif
+ if (vim_strchr(p_go, GO_TOOLBAR) != NULL
+ && (toolbar_flags & (TOOLBAR_TEXT | TOOLBAR_ICONS)))
+ gtk_widget_show(gui.toolbar);
+ gtk_box_pack_start(GTK_BOX(vbox), gui.toolbar, FALSE, FALSE, 0);
+ }
+#endif /* FEAT_TOOLBAR */
+
+ gui.formwin = gtk_form_new();
+ gtk_container_border_width(GTK_CONTAINER(gui.formwin), 0);
+ gtk_widget_set_events(gui.formwin, GDK_EXPOSURE_MASK);
+
+ gui.drawarea = gtk_drawing_area_new();
+
+ /* Determine which events we will filter. */
+ gtk_widget_set_events(gui.drawarea,
+ GDK_EXPOSURE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+#ifdef HAVE_GTK2
+ GDK_SCROLL_MASK |
+#endif
+ GDK_KEY_PRESS_MASK |
+ GDK_KEY_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK);
+
+ gtk_widget_show(gui.drawarea);
+ gtk_form_put(GTK_FORM(gui.formwin), gui.drawarea, 0, 0);
+ gtk_widget_show(gui.formwin);
+ gtk_box_pack_start(GTK_BOX(vbox), gui.formwin, TRUE, TRUE, 0);
+
+ /* For GtkSockets, key-presses must go to the focus widget (drawarea)
+ * and not the window. */
+ gtk_signal_connect((gtk_socket_id == 0) ? GTK_OBJECT(gui.mainwin)
+ : GTK_OBJECT(gui.drawarea),
+ "key_press_event",
+ GTK_SIGNAL_FUNC(key_press_event), NULL);
+#if defined(FEAT_XIM) && defined(HAVE_GTK2)
+ /* Also forward key release events for the benefit of GTK+ 2 input
+ * modules. Try CTRL-SHIFT-xdigits to enter a Unicode code point. */
+ g_signal_connect((gtk_socket_id == 0) ? G_OBJECT(gui.mainwin)
+ : G_OBJECT(gui.drawarea),
+ "key_release_event",
+ G_CALLBACK(&key_release_event), NULL);
+#endif
+ gtk_signal_connect(GTK_OBJECT(gui.drawarea), "realize",
+ GTK_SIGNAL_FUNC(drawarea_realize_cb), NULL);
+ gtk_signal_connect(GTK_OBJECT(gui.drawarea), "unrealize",
+ GTK_SIGNAL_FUNC(drawarea_unrealize_cb), NULL);
+
+ gtk_signal_connect_after(GTK_OBJECT(gui.drawarea), "style_set",
+ GTK_SIGNAL_FUNC(&drawarea_style_set_cb), NULL);
+
+ gui.visibility = GDK_VISIBILITY_UNOBSCURED;
+
+#if !(defined(FEAT_GUI_GNOME) && defined(FEAT_SESSION))
+ wm_protocols_atom = gdk_atom_intern("WM_PROTOCOLS", FALSE);
+ save_yourself_atom = gdk_atom_intern("WM_SAVE_YOURSELF", FALSE);
+#endif
+
+ if (gtk_socket_id != 0)
+ /* make sure keybord input can go to the drawarea */
+ GTK_WIDGET_SET_FLAGS(gui.drawarea, GTK_CAN_FOCUS);
+
+ /*
+ * Set clipboard specific atoms
+ */
+ vim_atom = gdk_atom_intern(VIM_ATOM_NAME, FALSE);
+#ifdef FEAT_MBYTE
+ vimenc_atom = gdk_atom_intern(VIMENC_ATOM_NAME, FALSE);
+#endif
+ clip_star.gtk_sel_atom = GDK_SELECTION_PRIMARY;
+ clip_plus.gtk_sel_atom = gdk_atom_intern("CLIPBOARD", FALSE);
+
+ /*
+ * Start out by adding the configured border width into the border offset.
+ */
+ gui.border_offset = gui.border_width;
+
+ gtk_signal_connect(GTK_OBJECT(gui.mainwin), "visibility_notify_event",
+ GTK_SIGNAL_FUNC(visibility_event), NULL);
+ gtk_signal_connect(GTK_OBJECT(gui.drawarea), "expose_event",
+ GTK_SIGNAL_FUNC(expose_event), NULL);
+
+ /*
+ * Only install these enter/leave callbacks when 'p' in 'guioptions'.
+ * Only needed for some window managers.
+ */
+ if (vim_strchr(p_go, GO_POINTER) != NULL)
+ {
+ gtk_signal_connect(GTK_OBJECT(gui.drawarea), "leave_notify_event",
+ GTK_SIGNAL_FUNC(leave_notify_event), NULL);
+ gtk_signal_connect(GTK_OBJECT(gui.drawarea), "enter_notify_event",
+ GTK_SIGNAL_FUNC(enter_notify_event), NULL);
+ }
+
+ gtk_signal_connect(GTK_OBJECT(gui.mainwin), "focus_out_event",
+ GTK_SIGNAL_FUNC(focus_out_event), NULL);
+ gtk_signal_connect(GTK_OBJECT(gui.mainwin), "focus_in_event",
+ GTK_SIGNAL_FUNC(focus_in_event), NULL);
+
+ gtk_signal_connect(GTK_OBJECT(gui.drawarea), "motion_notify_event",
+ GTK_SIGNAL_FUNC(motion_notify_event), NULL);
+ gtk_signal_connect(GTK_OBJECT(gui.drawarea), "button_press_event",
+ GTK_SIGNAL_FUNC(button_press_event), NULL);
+ gtk_signal_connect(GTK_OBJECT(gui.drawarea), "button_release_event",
+ GTK_SIGNAL_FUNC(button_release_event), NULL);
+#ifdef HAVE_GTK2
+ g_signal_connect(G_OBJECT(gui.drawarea), "scroll_event",
+ G_CALLBACK(&scroll_event), NULL);
+#endif
+
+ /*
+ * Add selection handler functions.
+ */
+ gtk_signal_connect(GTK_OBJECT(gui.drawarea), "selection_clear_event",
+ GTK_SIGNAL_FUNC(selection_clear_event), NULL);
+ gtk_signal_connect(GTK_OBJECT(gui.drawarea), "selection_received",
+ GTK_SIGNAL_FUNC(selection_received_cb), NULL);
+
+ /*
+ * Add selection targets for PRIMARY and CLIPBOARD selections.
+ */
+ gtk_selection_add_targets(gui.drawarea,
+ (GdkAtom)GDK_SELECTION_PRIMARY,
+ selection_targets, N_SELECTION_TARGETS);
+ gtk_selection_add_targets(gui.drawarea,
+ (GdkAtom)clip_plus.gtk_sel_atom,
+ selection_targets, N_SELECTION_TARGETS);
+
+ gtk_signal_connect(GTK_OBJECT(gui.drawarea), "selection_get",
+ GTK_SIGNAL_FUNC(selection_get_cb), NULL);
+
+ /* Pretend we don't have input focus, we will get an event if we do. */
+ gui.in_focus = FALSE;
+
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ netbeans_gtk_connect();
+# endif
+
+ return OK;
+}
+
+#if (defined(FEAT_GUI_GNOME) && defined(FEAT_SESSION)) || defined(PROTO)
+/*
+ * This is called from gui_start() after a fork() has been done.
+ * We have to tell the session manager our new PID.
+ */
+ void
+gui_mch_forked(void)
+{
+ if (using_gnome)
+ {
+ GnomeClient *client;
+
+ client = gnome_master_client();
+
+ if (client != NULL)
+ gnome_client_set_process_id(client, getpid());
+ }
+}
+#endif /* FEAT_GUI_GNOME && FEAT_SESSION */
+
+/*
+ * Called when the foreground or background color has been changed.
+ * This used to change the graphics contexts directly but we are
+ * currently manipulating them where desired.
+ */
+ void
+gui_mch_new_colors(void)
+{
+ if (gui.drawarea != NULL && gui.drawarea->window != NULL)
+ {
+ GdkColor color = { 0, 0, 0, 0 };
+
+ color.pixel = gui.back_pixel;
+ gdk_window_set_background(gui.drawarea->window, &color);
+ }
+}
+
+#if defined(FEAT_MENU) || defined(FEAT_TOOLBAR)
+ static int
+get_item_dimensions(GtkWidget *widget, GtkOrientation orientation)
+{
+ GtkOrientation item_orientation = GTK_ORIENTATION_HORIZONTAL;
+
+#ifdef FEAT_GUI_GNOME
+ if (using_gnome && widget != NULL)
+ {
+# ifdef HAVE_GTK2
+ BonoboDockItem *dockitem;
+
+ widget = gtk_widget_get_parent(widget);
+ dockitem = BONOBO_DOCK_ITEM(widget);
+
+ if (dockitem == NULL || dockitem->is_floating)
+ return 0;
+ item_orientation = bonobo_dock_item_get_orientation(dockitem);
+# else
+ GnomeDockItem *dockitem;
+
+ widget = widget->parent;
+ dockitem = GNOME_DOCK_ITEM(widget);
+
+ if (dockitem == NULL || dockitem->is_floating)
+ return 0;
+ item_orientation = gnome_dock_item_get_orientation(dockitem);
+# endif
+ }
+#endif
+ if (widget != NULL
+ && item_orientation == orientation
+ && GTK_WIDGET_REALIZED(widget)
+ && GTK_WIDGET_VISIBLE(widget))
+ {
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ return widget->allocation.height;
+ else
+ return widget->allocation.width;
+ }
+ return 0;
+}
+#endif
+
+ static int
+get_menu_tool_width(void)
+{
+ int width = 0;
+
+#ifdef FEAT_GUI_GNOME /* these are never vertical without GNOME */
+# ifdef FEAT_MENU
+ width += get_item_dimensions(gui.menubar, GTK_ORIENTATION_VERTICAL);
+# endif
+# ifdef FEAT_TOOLBAR
+ width += get_item_dimensions(gui.toolbar, GTK_ORIENTATION_VERTICAL);
+# endif
+#endif
+
+ return width;
+}
+
+ static int
+get_menu_tool_height(void)
+{
+ int height = 0;
+
+#ifdef FEAT_MENU
+ height += get_item_dimensions(gui.menubar, GTK_ORIENTATION_HORIZONTAL);
+#endif
+#ifdef FEAT_TOOLBAR
+ height += get_item_dimensions(gui.toolbar, GTK_ORIENTATION_HORIZONTAL);
+#endif
+
+ return height;
+}
+
+ static void
+update_window_manager_hints(void)
+{
+ static int old_width = 0;
+ static int old_height = 0;
+ static int old_char_width = 0;
+ static int old_char_height = 0;
+
+ int width;
+ int height;
+
+ /* This also needs to be done when the main window isn't there yet,
+ * otherwise the hints don't work. */
+ width = gui_get_base_width();
+ height = gui_get_base_height();
+# ifdef HAVE_GTK2
+ width += get_menu_tool_width();
+ height += get_menu_tool_height();
+# endif
+
+ /* Avoid an expose event when the size didn't change. */
+ if (width != old_width
+ || height != old_height
+ || gui.char_width != old_char_width
+ || gui.char_height != old_char_height)
+ {
+ GdkGeometry geometry;
+ GdkWindowHints geometry_mask;
+
+ geometry.width_inc = gui.char_width;
+ geometry.height_inc = gui.char_height;
+ geometry.base_width = width;
+ geometry.base_height = height;
+ geometry.min_width = width + MIN_COLUMNS * gui.char_width;
+ geometry.min_height = height + MIN_LINES * gui.char_height;
+ geometry_mask = GDK_HINT_BASE_SIZE|GDK_HINT_RESIZE_INC
+ |GDK_HINT_MIN_SIZE;
+# ifdef HAVE_GTK2
+ /* Using gui.formwin as geometry widget doesn't work as expected
+ * with GTK+ 2 -- dunno why. Presumably all the resizing hacks
+ * in Vim confuse GTK+. */
+ gtk_window_set_geometry_hints(GTK_WINDOW(gui.mainwin), gui.mainwin,
+ &geometry, geometry_mask);
+# else
+ gtk_window_set_geometry_hints(GTK_WINDOW(gui.mainwin), gui.formwin,
+ &geometry, geometry_mask);
+# endif
+ old_width = width;
+ old_height = height;
+ old_char_width = gui.char_width;
+ old_char_height = gui.char_height;
+ }
+}
+
+/*
+ * This signal informs us about the need to rearrange our sub-widgets.
+ */
+/*ARGSUSED*/
+ static gint
+form_configure_event(GtkWidget *widget, GdkEventConfigure *event,
+ gpointer data)
+{
+ gtk_form_freeze(GTK_FORM(gui.formwin));
+ gui_resize_shell(event->width, event->height);
+ gtk_form_thaw(GTK_FORM(gui.formwin));
+
+ return TRUE;
+}
+
+/*
+ * Function called when window already closed.
+ * We can't do much more here than to trying to preserve what had been done,
+ * since the window is already inevitably going away.
+ */
+/*ARGSUSED0*/
+ static void
+mainwin_destroy_cb(GtkObject *object, gpointer data)
+{
+ /* Don't write messages to the GUI anymore */
+ full_screen = FALSE;
+
+ gui.mainwin = NULL;
+ gui.drawarea = NULL;
+
+ if (!exiting) /* only do anything if the destroy was unexpected */
+ {
+ STRNCPY(IObuff, _("Vim: Main window unexpectedly destroyed\n"),
+ IOSIZE);
+ IObuff[IOSIZE - 1] = NUL;
+ preserve_exit();
+ }
+}
+
+/*
+ * Open the GUI window which was created by a call to gui_mch_init().
+ */
+ int
+gui_mch_open(void)
+{
+ guicolor_T fg_pixel = INVALCOLOR;
+ guicolor_T bg_pixel = INVALCOLOR;
+
+#ifdef HAVE_GTK2
+ /*
+ * Allow setting a window role on the command line, or invent one
+ * if none was specified. This is mainly useful for GNOME session
+ * support; allowing the WM to restore window placement.
+ */
+ if (role_argument != NULL)
+ {
+ gtk_window_set_role(GTK_WINDOW(gui.mainwin), role_argument);
+ }
+ else
+ {
+ char *role;
+
+ /* Invent a unique-enough ID string for the role */
+ role = g_strdup_printf("vim-%u-%u-%u",
+ (unsigned)mch_get_pid(),
+ (unsigned)g_random_int(),
+ (unsigned)time(NULL));
+
+ gtk_window_set_role(GTK_WINDOW(gui.mainwin), role);
+ g_free(role);
+ }
+#endif
+
+ if (gui_win_x != -1 && gui_win_y != -1)
+#ifdef HAVE_GTK2
+ gtk_window_move(GTK_WINDOW(gui.mainwin), gui_win_x, gui_win_y);
+#else
+ gtk_widget_set_uposition(gui.mainwin, gui_win_x, gui_win_y);
+#endif
+
+ /* Determine user specified geometry, if present. */
+ if (gui.geom != NULL)
+ {
+ int mask;
+ unsigned int w, h;
+ int x = 0;
+ int y = 0;
+
+ mask = XParseGeometry((char *)gui.geom, &x, &y, &w, &h);
+
+ if (mask & WidthValue)
+ Columns = w;
+ if (mask & HeightValue)
+ Rows = h;
+ if (mask & (XValue | YValue))
+#ifdef HAVE_GTK2
+ gtk_window_move(GTK_WINDOW(gui.mainwin), x, y);
+#else
+ gtk_widget_set_uposition(gui.mainwin, x, y);
+#endif
+ vim_free(gui.geom);
+ gui.geom = NULL;
+ }
+
+ gtk_form_set_size(GTK_FORM(gui.formwin),
+ (guint)(gui_get_base_width() + Columns * gui.char_width),
+ (guint)(gui_get_base_height() + Rows * gui.char_height));
+ update_window_manager_hints();
+
+ if (foreground_argument != NULL)
+ fg_pixel = gui_get_color((char_u *)foreground_argument);
+ if (fg_pixel == INVALCOLOR)
+ fg_pixel = gui_get_color((char_u *)"Black");
+
+ if (background_argument != NULL)
+ bg_pixel = gui_get_color((char_u *)background_argument);
+ if (bg_pixel == INVALCOLOR)
+ bg_pixel = gui_get_color((char_u *)"White");
+
+ if (found_reverse_arg)
+ {
+ gui.def_norm_pixel = bg_pixel;
+ gui.def_back_pixel = fg_pixel;
+ }
+ else
+ {
+ gui.def_norm_pixel = fg_pixel;
+ gui.def_back_pixel = bg_pixel;
+ }
+
+ /* Get the colors from the "Normal" and "Menu" group (set in syntax.c or
+ * in a vimrc file) */
+ set_normal_colors();
+
+ /* Check that none of the colors are the same as the background color */
+ gui_check_colors();
+
+ /* Get the colors for the highlight groups (gui_check_colors() might have
+ * changed them). */
+ highlight_gui_started(); /* re-init colors and fonts */
+
+ gtk_signal_connect(GTK_OBJECT(gui.mainwin), "destroy",
+ GTK_SIGNAL_FUNC(mainwin_destroy_cb), NULL);
+
+#ifdef FEAT_HANGULIN
+ hangul_keyboard_set();
+#endif
+
+ /*
+ * Notify the fixed area about the need to resize the contents of the
+ * gui.formwin, which we use for random positioning of the included
+ * components.
+ *
+ * We connect this signal deferred finally after anything is in place,
+ * since this is intended to handle resizements coming from the window
+ * manager upon us and should not interfere with what VIM is requesting
+ * upon startup.
+ */
+ gtk_signal_connect(GTK_OBJECT(gui.formwin), "configure_event",
+ GTK_SIGNAL_FUNC(form_configure_event), NULL);
+
+#ifdef FEAT_DND
+ /*
+ * Set up for receiving DND items.
+ */
+ gtk_drag_dest_set(gui.drawarea,
+ GTK_DEST_DEFAULT_ALL,
+ dnd_targets, N_DND_TARGETS,
+ GDK_ACTION_COPY);
+
+ gtk_signal_connect(GTK_OBJECT(gui.drawarea), "drag_data_received",
+ GTK_SIGNAL_FUNC(drag_data_received_cb), NULL);
+#endif
+
+#ifdef HAVE_GTK2
+ /* With GTK+ 2, we need to iconify the window before calling show()
+ * to avoid mapping the window for a short time. This is just as one
+ * would expect it to work, but it's different in GTK+ 1. The funny
+ * thing is that iconifying after show() _does_ work with GTK+ 1.
+ * (BTW doing this in the "realize" handler makes no difference.) */
+ if (found_iconic_arg && gtk_socket_id == 0)
+ gui_mch_iconify();
+#endif
+
+ {
+#if defined(FEAT_GUI_GNOME) && defined(HAVE_GTK2) && defined(FEAT_MENU)
+ unsigned long menu_handler = 0;
+# ifdef FEAT_TOOLBAR
+ unsigned long tool_handler = 0;
+# endif
+ /*
+ * Urgh hackish :/ For some reason BonoboDockLayout always forces a
+ * show when restoring the saved layout configuration. We can't just
+ * hide the widgets again after gtk_widget_show(gui.mainwin) since it's
+ * a toplevel window and thus will be realized immediately. Instead,
+ * connect signal handlers to hide the widgets just after they've been
+ * marked visible, but before the main window is realized.
+ */
+ if (using_gnome && vim_strchr(p_go, GO_MENUS) == NULL)
+ menu_handler = g_signal_connect_after(gui.menubar_h, "show",
+ G_CALLBACK(&gtk_widget_hide),
+ NULL);
+# ifdef FEAT_TOOLBAR
+ if (using_gnome && vim_strchr(p_go, GO_TOOLBAR) == NULL
+ && (toolbar_flags & (TOOLBAR_TEXT | TOOLBAR_ICONS)))
+ tool_handler = g_signal_connect_after(gui.toolbar_h, "show",
+ G_CALLBACK(&gtk_widget_hide),
+ NULL);
+# endif
+#endif
+ gtk_widget_show(gui.mainwin);
+
+#if defined(FEAT_GUI_GNOME) && defined(HAVE_GTK2) && defined(FEAT_MENU)
+ if (menu_handler != 0)
+ g_signal_handler_disconnect(gui.menubar_h, menu_handler);
+# ifdef FEAT_TOOLBAR
+ if (tool_handler != 0)
+ g_signal_handler_disconnect(gui.toolbar_h, tool_handler);
+# endif
+#endif
+ }
+
+#ifndef HAVE_GTK2
+ /* With GTK+ 1, we need to iconify the window after calling show().
+ * See the comment above for details. */
+ if (found_iconic_arg && gtk_socket_id == 0)
+ gui_mch_iconify();
+#endif
+
+ return OK;
+}
+
+
+/*ARGSUSED0*/
+ void
+gui_mch_exit(int rc)
+{
+ if (gui.mainwin != NULL)
+ gtk_widget_destroy(gui.mainwin);
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+/*
+ * Get the position of the top left corner of the window.
+ */
+ int
+gui_mch_get_winpos(int *x, int *y)
+{
+#ifdef HAVE_GTK2
+ gtk_window_get_position(GTK_WINDOW(gui.mainwin), x, y);
+#else
+ /* For some people this must be gdk_window_get_origin() for a correct
+ * result. Where is the documentation! */
+ gdk_window_get_root_origin(gui.mainwin->window, x, y);
+#endif
+ return OK;
+}
+
+/*
+ * Set the position of the top left corner of the window to the given
+ * coordinates.
+ */
+ void
+gui_mch_set_winpos(int x, int y)
+{
+#ifdef HAVE_GTK2
+ gtk_window_move(GTK_WINDOW(gui.mainwin), x, y);
+#else
+ gdk_window_move(gui.mainwin->window, x, y);
+#endif
+}
+
+#ifdef HAVE_GTK2
+#if 0
+static int resize_idle_installed = FALSE;
+/*
+ * Idle handler to force resize. Used by gui_mch_set_shellsize() to ensure
+ * the shell size doesn't exceed the window size, i.e. if the window manager
+ * ignored our size request. Usually this happens if the window is maximized.
+ *
+ * FIXME: It'd be nice if we could find a little more orthodox solution.
+ * See also the remark below in gui_mch_set_shellsize().
+ *
+ * DISABLED: When doing ":set lines+=1" this function would first invoke
+ * gui_resize_shell() with the old size, then the normal callback would
+ * report the new size through form_configure_event(). That caused the window
+ * layout to be messed up.
+ */
+/*ARGSUSED0*/
+ static gboolean
+force_shell_resize_idle(gpointer data)
+{
+ if (gui.mainwin != NULL
+ && GTK_WIDGET_REALIZED(gui.mainwin)
+ && GTK_WIDGET_VISIBLE(gui.mainwin))
+ {
+ int width;
+ int height;
+
+ gtk_window_get_size(GTK_WINDOW(gui.mainwin), &width, &height);
+
+ width -= get_menu_tool_width();
+ height -= get_menu_tool_height();
+
+ gui_resize_shell(width, height);
+ }
+
+ resize_idle_installed = FALSE;
+ return FALSE; /* don't call me again */
+}
+#endif
+#endif /* HAVE_GTK2 */
+
+/*
+ * Set the windows size.
+ */
+/*ARGSUSED2*/
+ void
+gui_mch_set_shellsize(int width, int height,
+ int min_width, int min_height,
+ int base_width, int base_height)
+{
+#ifndef HAVE_GTK2
+ /* Hack: When the form already is at the desired size, the window might
+ * have been resized with the mouse. Force a resize by setting a
+ * different size first. */
+ if (GTK_FORM(gui.formwin)->width == width
+ && GTK_FORM(gui.formwin)->height == height)
+ {
+ gtk_form_set_size(GTK_FORM(gui.formwin), width + 1, height + 1);
+ gui_mch_update();
+ }
+ gtk_form_set_size(GTK_FORM(gui.formwin), width, height);
+#endif
+
+ /* give GTK+ a chance to put all widget's into place */
+ gui_mch_update();
+
+ /* this will cause the proper resizement to happen too */
+ update_window_manager_hints();
+
+#ifdef HAVE_GTK2
+ /* With GTK+ 2, changing the size of the form widget doesn't resize
+ * the window. So lets do it the other way around and resize the
+ * main window instead. */
+ width += get_menu_tool_width();
+ height += get_menu_tool_height();
+
+ gtk_window_resize(GTK_WINDOW(gui.mainwin), width, height);
+
+#if 0
+ if (!resize_idle_installed)
+ {
+ g_idle_add_full(GDK_PRIORITY_EVENTS + 10,
+ &force_shell_resize_idle, NULL, NULL);
+ resize_idle_installed = TRUE;
+ }
+#endif
+ /*
+ * Wait until all events are processed to prevent a crash because the
+ * real size of the drawing area doesn't reflect Vim's internal ideas.
+ *
+ * This is a bit of a hack, since Vim is a terminal application with a GUI
+ * on top, while the GUI expects to be the boss.
+ */
+ gui_mch_update();
+#endif
+}
+
+
+/*
+ * The screen size is used to make sure the initial window doesn't get bigger
+ * than the screen. This subtracts some room for menubar, toolbar and window
+ * decorations.
+ */
+ void
+gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
+{
+#ifdef HAVE_GTK_MULTIHEAD
+ GdkScreen* screen;
+
+ if (gui.mainwin != NULL && gtk_widget_has_screen(gui.mainwin))
+ screen = gtk_widget_get_screen(gui.mainwin);
+ else
+ screen = gdk_screen_get_default();
+
+ *screen_w = gdk_screen_get_width(screen);
+ *screen_h = gdk_screen_get_height(screen) - p_ghr;
+#else
+ *screen_w = gdk_screen_width();
+ /* Subtract 'guiheadroom' from the height to allow some room for the
+ * window manager (task list and window title bar). */
+ *screen_h = gdk_screen_height() - p_ghr;
+#endif
+
+ /*
+ * FIXME: dirty trick: Because the gui_get_base_height() doesn't include
+ * the toolbar and menubar for GTK, we subtract them from the screen
+ * hight, so that the window size can be made to fit on the screen.
+ * This should be completely changed later.
+ */
+ *screen_w -= get_menu_tool_width();
+ *screen_h -= get_menu_tool_height();
+}
+
+#if defined(FEAT_TITLE) || defined(PROTO)
+/*ARGSUSED*/
+ void
+gui_mch_settitle(char_u *title, char_u *icon)
+{
+# ifdef HAVE_GTK2
+ if (title != NULL && output_conv.vc_type != CONV_NONE)
+ title = string_convert(&output_conv, title, NULL);
+# endif
+
+ gtk_window_set_title(GTK_WINDOW(gui.mainwin), (const char *)title);
+
+# ifdef HAVE_GTK2
+ if (output_conv.vc_type != CONV_NONE)
+ vim_free(title);
+# endif
+}
+#endif /* FEAT_TITLE */
+
+#if defined(FEAT_MENU) || defined(PROTO)
+ void
+gui_mch_enable_menu(int showit)
+{
+ GtkWidget *widget;
+
+# ifdef FEAT_GUI_GNOME
+ if (using_gnome)
+ widget = gui.menubar_h;
+ else
+# endif
+ widget = gui.menubar;
+
+ if (!showit != !GTK_WIDGET_VISIBLE(widget))
+ {
+ if (showit)
+ gtk_widget_show(widget);
+ else
+ gtk_widget_hide(widget);
+
+ update_window_manager_hints();
+ }
+}
+#endif /* FEAT_MENU */
+
+#if defined(FEAT_TOOLBAR) || defined(PROTO)
+ void
+gui_mch_show_toolbar(int showit)
+{
+ GtkWidget *widget;
+
+ if (gui.toolbar == NULL)
+ return;
+
+# ifdef FEAT_GUI_GNOME
+ if (using_gnome)
+ widget = gui.toolbar_h;
+ else
+# endif
+ widget = gui.toolbar;
+
+ if (showit)
+ set_toolbar_style(GTK_TOOLBAR(gui.toolbar));
+
+ if (!showit != !GTK_WIDGET_VISIBLE(widget))
+ {
+ if (showit)
+ gtk_widget_show(widget);
+ else
+ gtk_widget_hide(widget);
+
+ update_window_manager_hints();
+ }
+}
+#endif /* FEAT_TOOLBAR */
+
+#ifndef HAVE_GTK2
+/*
+ * Get a font structure for highlighting.
+ * "cbdata" is a pointer to the global gui structure.
+ */
+/*ARGSUSED*/
+ static void
+font_sel_ok(GtkWidget *wgt, gpointer cbdata)
+{
+ gui_T *vw = (gui_T *)cbdata;
+ GtkFontSelectionDialog *fs = (GtkFontSelectionDialog *)vw->fontdlg;
+
+ if (vw->fontname)
+ g_free(vw->fontname);
+
+ vw->fontname = (char_u *)gtk_font_selection_dialog_get_font_name(fs);
+ gtk_widget_hide(vw->fontdlg);
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+/*ARGSUSED*/
+ static void
+font_sel_cancel(GtkWidget *wgt, gpointer cbdata)
+{
+ gui_T *vw = (gui_T *)cbdata;
+
+ gtk_widget_hide(vw->fontdlg);
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+/*ARGSUSED*/
+ static void
+font_sel_destroy(GtkWidget *wgt, gpointer cbdata)
+{
+ gui_T *vw = (gui_T *)cbdata;
+
+ vw->fontdlg = NULL;
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+#endif /* !HAVE_GTK2 */
+
+#ifdef HAVE_GTK2
+/*
+ * Check if a given font is a CJK font. This is done in a very crude manner. It
+ * just see if U+04E00 for zh and ja and U+AC00 for ko are covered in a given
+ * font. Consequently, this function cannot be used as a general purpose check
+ * for CJK-ness for which fontconfig APIs should be used. This is only used by
+ * gui_mch_init_font() to deal with 'CJK fixed width fonts'.
+ */
+ static int
+is_cjk_font(PangoFontDescription *font_desc)
+{
+ static const char * const cjk_langs[] =
+ {"zh_CN", "zh_TW", "zh_HK", "ja", "ko"};
+
+ PangoFont *font;
+ unsigned i;
+ int is_cjk = FALSE;
+
+ font = pango_context_load_font(gui.text_context, font_desc);
+
+ if (font == NULL)
+ return FALSE;
+
+ for (i = 0; !is_cjk && i < G_N_ELEMENTS(cjk_langs); ++i)
+ {
+ PangoCoverage *coverage;
+ gunichar uc;
+
+ coverage = pango_font_get_coverage(
+ font, pango_language_from_string(cjk_langs[i]));
+
+ if (coverage != NULL)
+ {
+ uc = (cjk_langs[i][0] == 'k') ? 0xAC00 : 0x4E00;
+ is_cjk = (pango_coverage_get(coverage, uc) == PANGO_COVERAGE_EXACT);
+ pango_coverage_unref(coverage);
+ }
+ }
+
+ g_object_unref(font);
+
+ return is_cjk;
+}
+#endif /* HAVE_GTK2 */
+
+ int
+gui_mch_adjust_charsize(void)
+{
+#ifdef HAVE_GTK2
+ PangoFontMetrics *metrics;
+ int ascent;
+ int descent;
+
+ metrics = pango_context_get_metrics(gui.text_context, gui.norm_font,
+ pango_context_get_language(gui.text_context));
+ ascent = pango_font_metrics_get_ascent(metrics);
+ descent = pango_font_metrics_get_descent(metrics);
+
+ pango_font_metrics_unref(metrics);
+
+ gui.char_height = (ascent + descent + PANGO_SCALE - 1) / PANGO_SCALE
+ + p_linespace;
+ gui.char_ascent = PANGO_PIXELS(ascent + p_linespace * PANGO_SCALE / 2);
+
+#else /* !HAVE_GTK2 */
+
+ gui.char_height = gui.current_font->ascent + gui.current_font->descent
+ + p_linespace;
+ gui.char_ascent = gui.current_font->ascent + p_linespace / 2;
+
+#endif /* !HAVE_GTK2 */
+
+ /* A not-positive value of char_height may crash Vim. Only happens
+ * if 'linespace' is negative (which does make sense sometimes). */
+ gui.char_ascent = MAX(gui.char_ascent, 0);
+ gui.char_height = MAX(gui.char_height, gui.char_ascent + 1);
+
+ return OK;
+}
+
+#if defined(FEAT_XFONTSET) || defined(PROTO)
+/*
+ * Try to load the requested fontset.
+ */
+/*ARGSUSED2*/
+ GuiFontset
+gui_mch_get_fontset(char_u *name, int report_error, int fixed_width)
+{
+ GdkFont *font;
+
+ if (!gui.in_use || name == NULL)
+ return NOFONT;
+
+ font = gdk_fontset_load((gchar *)name);
+
+ if (font == NULL)
+ {
+ if (report_error)
+ EMSG2(_(e_fontset), name);
+ return NOFONT;
+ }
+ /* TODO: check if the font is fixed width. */
+
+ /* reference this font as being in use */
+ gdk_font_ref(font);
+
+ return (GuiFontset)font;
+}
+#endif /* FEAT_XFONTSET */
+
+#ifndef HAVE_GTK2
+/*
+ * Put up a font dialog and return the selected font name in allocated memory.
+ * "oldval" is the previous value.
+ * Return NULL when cancelled.
+ */
+ char_u *
+gui_mch_font_dialog(char_u *oldval)
+{
+ char_u *fontname = NULL;
+
+ if (!gui.fontdlg)
+ {
+ GtkFontSelectionDialog *fsd = NULL;
+
+ gui.fontdlg = gtk_font_selection_dialog_new(_("Font Selection"));
+ fsd = GTK_FONT_SELECTION_DIALOG(gui.fontdlg);
+ gtk_window_set_modal(GTK_WINDOW(gui.fontdlg), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(gui.fontdlg),
+ GTK_WINDOW(gui.mainwin));
+ gtk_signal_connect(GTK_OBJECT(gui.fontdlg), "destroy",
+ GTK_SIGNAL_FUNC(font_sel_destroy), &gui);
+ gtk_signal_connect(GTK_OBJECT(fsd->ok_button), "clicked",
+ GTK_SIGNAL_FUNC(font_sel_ok), &gui);
+ gtk_signal_connect(GTK_OBJECT(fsd->cancel_button), "clicked",
+ GTK_SIGNAL_FUNC(font_sel_cancel), &gui);
+ }
+
+ if (oldval != NULL && *oldval != NUL)
+ gtk_font_selection_dialog_set_font_name(
+ GTK_FONT_SELECTION_DIALOG(gui.fontdlg), (char *)oldval);
+
+ if (gui.fontname)
+ {
+ g_free(gui.fontname);
+ gui.fontname = NULL;
+ }
+ gtk_window_position(GTK_WINDOW(gui.fontdlg), GTK_WIN_POS_MOUSE);
+ gtk_widget_show(gui.fontdlg);
+ {
+ static gchar *spacings[] = {"c", "m", NULL};
+
+ /* In GTK 1.2.3 this must be after the gtk_widget_show() call,
+ * otherwise everything is blocked for ten seconds. */
+ gtk_font_selection_dialog_set_filter(
+ GTK_FONT_SELECTION_DIALOG(gui.fontdlg),
+ GTK_FONT_FILTER_BASE,
+ GTK_FONT_ALL, NULL, NULL,
+ NULL, NULL, spacings, NULL);
+ }
+
+ /* Wait for the font dialog to be closed. */
+ while (gui.fontdlg && GTK_WIDGET_DRAWABLE(gui.fontdlg))
+ gtk_main_iteration_do(TRUE);
+
+ if (gui.fontname != NULL)
+ {
+ fontname = vim_strsave(gui.fontname);
+ g_free(gui.fontname);
+ gui.fontname = NULL;
+ }
+ return fontname;
+}
+#endif /* !HAVE_GTK2 */
+
+#ifdef HAVE_GTK2
+/*
+ * Put up a font dialog and return the selected font name in allocated memory.
+ * "oldval" is the previous value. Return NULL when cancelled.
+ * This should probably go into gui_gtk.c. Hmm.
+ * FIXME:
+ * The GTK2 font selection dialog has no filtering API. So we could either
+ * a) implement our own (possibly copying the code from somewhere else) or
+ * b) just live with it.
+ */
+ char_u *
+gui_mch_font_dialog(char_u *oldval)
+{
+ GtkWidget *dialog;
+ int response;
+ char_u *fontname = NULL;
+ char_u *oldname;
+
+ dialog = gtk_font_selection_dialog_new(NULL);
+
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(gui.mainwin));
+ gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE);
+
+ if (oldval != NULL && oldval[0] != NUL)
+ {
+ if (output_conv.vc_type != CONV_NONE)
+ oldname = string_convert(&output_conv, oldval, NULL);
+ else
+ oldname = oldval;
+
+ /* Annoying bug in GTK (or Pango): if the font name does not include a
+ * size, zero is used. Use default point size ten. */
+ if (!vim_isdigit(oldname[STRLEN(oldname) - 1]))
+ {
+ char_u *p = vim_strnsave(oldname, STRLEN(oldname) + 3);
+
+ if (p != NULL)
+ {
+ STRCPY(p + STRLEN(p), " 10");
+ if (oldname != oldval)
+ vim_free(oldname);
+ oldname = p;
+ }
+ }
+
+ gtk_font_selection_dialog_set_font_name(
+ GTK_FONT_SELECTION_DIALOG(dialog), (const char *)oldname);
+
+ if (oldname != oldval)
+ vim_free(oldval);
+ }
+
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+
+ if (response == GTK_RESPONSE_OK)
+ {
+ char *name;
+
+ name = gtk_font_selection_dialog_get_font_name(
+ GTK_FONT_SELECTION_DIALOG(dialog));
+ if (name != NULL)
+ {
+ if (input_conv.vc_type != CONV_NONE)
+ fontname = string_convert(&input_conv, (char_u *)name, NULL);
+ else
+ fontname = vim_strsave((char_u *)name);
+ g_free(name);
+ }
+ }
+
+ if (response != GTK_RESPONSE_NONE)
+ gtk_widget_destroy(dialog);
+
+ return fontname;
+}
+
+/*
+ * Some monospace fonts don't support a bold weight, and fall back
+ * silently to the regular weight. But this is no good since our text
+ * drawing function can emulate bold by overstriking. So let's try
+ * to detect whether bold weight is actually available and emulate it
+ * otherwise.
+ *
+ * Note that we don't need to check for italic style since Xft can
+ * emulate italic on its own, provided you have a proper fontconfig
+ * setup. We wouldn't be able to emulate it in Vim anyway.
+ */
+ static void
+get_styled_font_variants(void)
+{
+ PangoFontDescription *bold_font_desc;
+ PangoFont *plain_font;
+ PangoFont *bold_font;
+
+ gui.font_can_bold = FALSE;
+
+ plain_font = pango_context_load_font(gui.text_context, gui.norm_font);
+
+ if (plain_font == NULL)
+ return;
+
+ bold_font_desc = pango_font_description_copy_static(gui.norm_font);
+ pango_font_description_set_weight(bold_font_desc, PANGO_WEIGHT_BOLD);
+
+ bold_font = pango_context_load_font(gui.text_context, bold_font_desc);
+ /*
+ * The comparison relies on the unique handle nature of a PangoFont*,
+ * i.e. it's assumed that a different PangoFont* won't refer to the
+ * same font. Seems to work, and failing here isn't critical anyway.
+ */
+ if (bold_font != NULL)
+ {
+ gui.font_can_bold = (bold_font != plain_font);
+ g_object_unref(bold_font);
+ }
+
+ pango_font_description_free(bold_font_desc);
+ g_object_unref(plain_font);
+}
+
+#else /* !HAVE_GTK2 */
+
+/*
+ * There is only one excuse I can give for the following attempt to manage font
+ * styles:
+ *
+ * I HATE THE BRAIN DEAD WAY X11 IS HANDLING FONTS (--mdcki)
+ * (Me too. --danielk)
+ */
+ static void
+get_styled_font_variants(char_u * font_name)
+{
+ char *chunk[32];
+ char *sdup;
+ char *tmp;
+ int len, i;
+ GuiFont *styled_font[3];
+
+ styled_font[0] = &gui.bold_font;
+ styled_font[1] = &gui.ital_font;
+ styled_font[2] = &gui.boldital_font;
+
+ /* First free whatever was freviously there. */
+ for (i = 0; i < 3; ++i)
+ if (*styled_font[i])
+ {
+ gdk_font_unref(*styled_font[i]);
+ *styled_font[i] = NULL;
+ }
+
+ if ((sdup = g_strdup((const char *)font_name)) == NULL)
+ return;
+
+ /* split up the whole */
+ i = 0;
+ for (tmp = sdup; *tmp != '\0'; ++tmp)
+ {
+ if (*tmp == '-')
+ {
+ *tmp = '\0';
+
+ if (i == 32)
+ break;
+
+ chunk[i] = tmp + 1;
+ ++i;
+ }
+ }
+
+ if (i == 14)
+ {
+ GdkFont *font = NULL;
+ const char *bold_chunk[3] = { "bold", NULL, "bold" };
+ const char *italic_chunk[3] = { NULL, "o", "o" };
+
+ /* font name was complete */
+ len = strlen((const char *)font_name) + 32;
+
+ for (i = 0; i < 3; ++i)
+ {
+ char *styled_name;
+ int j;
+
+ styled_name = (char *)alloc(len);
+ if (styled_name == NULL)
+ {
+ g_free(sdup);
+ return;
+ }
+
+ *styled_name = '\0';
+
+ for (j = 0; j < 14; ++j)
+ {
+ strcat(styled_name, "-");
+ if (j == 2 && bold_chunk[i] != NULL)
+ strcat(styled_name, bold_chunk[i]);
+ else if (j == 3 && italic_chunk[i] != NULL)
+ strcat(styled_name, italic_chunk[i]);
+ else
+ strcat(styled_name, chunk[j]);
+ }
+
+ font = gui_mch_get_font((char_u *)styled_name, FALSE);
+ if (font != NULL)
+ *styled_font[i] = font;
+
+ vim_free(styled_name);
+ }
+ }
+
+ g_free(sdup);
+}
+#endif /* !HAVE_GTK2 */
+
+#ifdef HAVE_GTK2
+static PangoEngineShape *default_shape_engine = NULL;
+
+/*
+ * Create a map from ASCII characters in the range [32,126] to glyphs
+ * of the current font. This is used by gui_gtk2_draw_string() to skip
+ * the itemize and shaping process for the most common case.
+ */
+ static void
+ascii_glyph_table_init(void)
+{
+ char_u ascii_chars[128];
+ PangoAttrList *attr_list;
+ GList *item_list;
+ int i;
+
+ if (gui.ascii_glyphs != NULL)
+ pango_glyph_string_free(gui.ascii_glyphs);
+ if (gui.ascii_font != NULL)
+ g_object_unref(gui.ascii_font);
+
+ gui.ascii_glyphs = NULL;
+ gui.ascii_font = NULL;
+
+ /* For safety, fill in question marks for the control characters. */
+ for (i = 0; i < 32; ++i)
+ ascii_chars[i] = '?';
+ for (; i < 127; ++i)
+ ascii_chars[i] = i;
+ ascii_chars[i] = '?';
+
+ attr_list = pango_attr_list_new();
+ item_list = pango_itemize(gui.text_context, (const char *)ascii_chars,
+ 0, sizeof(ascii_chars), attr_list, NULL);
+
+ if (item_list != NULL && item_list->next == NULL) /* play safe */
+ {
+ PangoItem *item;
+ int width;
+
+ item = (PangoItem *)item_list->data;
+ width = gui.char_width * PANGO_SCALE;
+
+ /* Remember the shape engine used for ASCII. */
+ default_shape_engine = item->analysis.shape_engine;
+
+ gui.ascii_font = item->analysis.font;
+ g_object_ref(gui.ascii_font);
+
+ gui.ascii_glyphs = pango_glyph_string_new();
+
+ pango_shape((const char *)ascii_chars, sizeof(ascii_chars),
+ &item->analysis, gui.ascii_glyphs);
+
+ g_return_if_fail(gui.ascii_glyphs->num_glyphs == sizeof(ascii_chars));
+
+ for (i = 0; i < gui.ascii_glyphs->num_glyphs; ++i)
+ {
+ PangoGlyphGeometry *geom;
+
+ geom = &gui.ascii_glyphs->glyphs[i].geometry;
+ geom->x_offset += MAX(0, width - geom->width) / 2;
+ geom->width = width;
+ }
+ }
+
+ g_list_foreach(item_list, (GFunc)&pango_item_free, NULL);
+ g_list_free(item_list);
+ pango_attr_list_unref(attr_list);
+}
+#endif /* HAVE_GTK2 */
+
+/*
+ * Initialize Vim to use the font or fontset with the given name.
+ * Return FAIL if the font could not be loaded, OK otherwise.
+ */
+/*ARGSUSED1*/
+ int
+gui_mch_init_font(char_u *font_name, int fontset)
+{
+#ifdef HAVE_GTK2
+ PangoFontDescription *font_desc;
+ PangoLayout *layout;
+ int width;
+
+ /* If font_name is NULL, this means to use the default, which should
+ * be present on all proper Pango/fontconfig installations. */
+ if (font_name == NULL)
+ font_name = (char_u *)DEFAULT_FONT;
+
+ font_desc = gui_mch_get_font(font_name, FALSE);
+
+ if (font_desc == NULL)
+ return FAIL;
+
+ gui_mch_free_font(gui.norm_font);
+ gui.norm_font = font_desc;
+
+ pango_context_set_font_description(gui.text_context, font_desc);
+
+ layout = pango_layout_new(gui.text_context);
+ pango_layout_set_text(layout, "MW", 2);
+ pango_layout_get_size(layout, &width, NULL);
+ /*
+ * Set char_width to half the width obtained from pango_layout_get_size()
+ * for CJK fixed_width/bi-width fonts. An unpatched version of Xft leads
+ * Pango to use the same width for both non-CJK characters (e.g. Latin
+ * letters and numbers) and CJK characters. This results in 's p a c e d
+ * o u t' rendering when a CJK 'fixed width' font is used. To work around
+ * that, divide the width returned by Pango by 2 if cjk_width is equal to
+ * width for CJK fonts.
+ *
+ * For related bugs, see:
+ * http://bugzilla.gnome.org/show_bug.cgi?id=106618
+ * http://bugzilla.gnome.org/show_bug.cgi?id=106624
+ *
+ * With this, for all four of the following cases, Vim works fine:
+ * guifont=CJK_fixed_width_font
+ * guifont=Non_CJK_fixed_font
+ * guifont=Non_CJK_fixed_font,CJK_Fixed_font
+ * guifont=Non_CJK_fixed_font guifontwide=CJK_fixed_font
+ */
+ if (is_cjk_font(gui.norm_font))
+ {
+ int cjk_width;
+
+ /* Measure the text extent of U+4E00 and U+4E8C */
+ pango_layout_set_text(layout, "\344\270\200\344\272\214", -1);
+ pango_layout_get_size(layout, &cjk_width, NULL);
+
+ if (width == cjk_width) /* Xft not patched */
+ width /= 2;
+ }
+ g_object_unref(layout);
+
+ gui.char_width = (width / 2 + PANGO_SCALE - 1) / PANGO_SCALE;
+
+ /* A zero width may cause a crash. Happens for semi-invalid fontsets. */
+ if (gui.char_width <= 0)
+ gui.char_width = 8;
+
+ gui_mch_adjust_charsize();
+
+ /* Set the fontname, which will be used for information purposes */
+ hl_set_font_name(font_name);
+
+ get_styled_font_variants();
+ ascii_glyph_table_init();
+
+ /* Avoid unnecessary overhead if 'guifontwide' is equal to 'guifont'. */
+ if (gui.wide_font != NULL
+ && pango_font_description_equal(gui.norm_font, gui.wide_font))
+ {
+ pango_font_description_free(gui.wide_font);
+ gui.wide_font = NULL;
+ }
+
+#else /* !HAVE_GTK2 */
+
+ GdkFont *font = NULL;
+
+# ifdef FEAT_XFONTSET
+ /* Try loading a fontset. If this fails we try loading a normal font. */
+ if (fontset && font_name != NULL)
+ font = gui_mch_get_fontset(font_name, TRUE, TRUE);
+
+ if (font == NULL)
+# endif
+ {
+ /* If font_name is NULL, this means to use the default, which should
+ * be present on all X11 servers. */
+ if (font_name == NULL)
+ font_name = (char_u *)DEFAULT_FONT;
+ font = gui_mch_get_font(font_name, FALSE);
+ }
+
+ if (font == NULL)
+ return FAIL;
+
+ gui_mch_free_font(gui.norm_font);
+# ifdef FEAT_XFONTSET
+ gui_mch_free_fontset(gui.fontset);
+ if (font->type == GDK_FONT_FONTSET)
+ {
+ gui.norm_font = NOFONT;
+ gui.fontset = (GuiFontset)font;
+ /* Use two bytes, this works around the problem that the result would
+ * be zero if no 8-bit font was found. */
+ gui.char_width = gdk_string_width(font, "xW") / 2;
+ }
+ else
+# endif
+ {
+ gui.norm_font = font;
+# ifdef FEAT_XFONTSET
+ gui.fontset = NOFONTSET;
+# endif
+ gui.char_width = ((XFontStruct *)
+ GDK_FONT_XFONT(font))->max_bounds.width;
+ }
+
+ /* A zero width may cause a crash. Happens for semi-invalid fontsets. */
+ if (gui.char_width <= 0)
+ gui.char_width = 8;
+
+ gui.char_height = font->ascent + font->descent + p_linespace;
+ gui.char_ascent = font->ascent + p_linespace / 2;
+
+ /* A not-positive value of char_height may crash Vim. Only happens
+ * if 'linespace' is negative (which does make sense sometimes). */
+ gui.char_ascent = MAX(gui.char_ascent, 0);
+ gui.char_height = MAX(gui.char_height, gui.char_ascent + 1);
+
+ /* Set the fontname, which will be used for information purposes */
+ hl_set_font_name(font_name);
+
+ if (font->type != GDK_FONT_FONTSET)
+ get_styled_font_variants(font_name);
+
+ /* Synchronize the fonts used in user input dialogs, since otherwise
+ * search/replace will be esp. annoying in case of international font
+ * usage.
+ */
+ gui_gtk_synch_fonts();
+
+# ifdef FEAT_XIM
+ /* Adjust input management behaviour to the capabilities of the new
+ * fontset */
+ xim_decide_input_style();
+ if (xim_get_status_area_height())
+ {
+ /* Status area is required. Just create the empty container so that
+ * mainwin will allocate the extra space for status area. */
+ GtkWidget *alignment = gtk_alignment_new((gfloat)0.5, (gfloat)0.5,
+ (gfloat)1.0, (gfloat)1.0);
+
+ gtk_widget_set_usize(alignment, 20, gui.char_height + 2);
+ gtk_box_pack_end(GTK_BOX(GTK_BIN(gui.mainwin)->child),
+ alignment, FALSE, FALSE, 0);
+ gtk_widget_show(alignment);
+ }
+# endif
+#endif /* !HAVE_GTK2 */
+
+ /* Preserve the logical dimensions of the screen. */
+ update_window_manager_hints();
+
+ return OK;
+}
+
+/*
+ * Get a reference to the font "name".
+ * Return zero for failure.
+ */
+ GuiFont
+gui_mch_get_font(char_u *name, int report_error)
+{
+#ifdef HAVE_GTK2
+ PangoFontDescription *font;
+#else
+ GdkFont *font;
+#endif
+
+ /* can't do this when GUI is not running */
+ if (!gui.in_use || name == NULL)
+ return NULL;
+
+#ifdef HAVE_GTK2
+ if (output_conv.vc_type != CONV_NONE)
+ {
+ char_u *buf;
+
+ buf = string_convert(&output_conv, name, NULL);
+ if (buf != NULL)
+ {
+ font = pango_font_description_from_string((const char *)buf);
+ vim_free(buf);
+ }
+ else
+ font = NULL;
+ }
+ else
+ font = pango_font_description_from_string((const char *)name);
+
+ if (font != NULL)
+ {
+ PangoFont *real_font;
+
+ /* pango_context_load_font() bails out if no font size is set */
+ if (pango_font_description_get_size(font) <= 0)
+ pango_font_description_set_size(font, 10 * PANGO_SCALE);
+
+ real_font = pango_context_load_font(gui.text_context, font);
+
+ if (real_font == NULL)
+ {
+ pango_font_description_free(font);
+ font = NULL;
+ }
+ else
+ g_object_unref(real_font);
+ }
+#else
+ font = gdk_font_load((const gchar *)name);
+#endif
+
+ if (font == NULL)
+ {
+ if (report_error)
+ EMSG2(_(e_font), name);
+ return NULL;
+ }
+
+#ifdef HAVE_GTK2
+ /*
+ * The fixed-width check has been disabled for GTK+ 2. Rationale:
+ *
+ * - The check tends to report false positives, particularly
+ * in non-Latin locales or with old X fonts.
+ * - Thanks to our fixed-width hack in gui_gtk2_draw_string(),
+ * GTK+ 2 Vim is actually capable of displaying variable width
+ * fonts. Those will just be spaced out like in AA xterm.
+ * - Failing here for the default font causes GUI startup to fail
+ * even with wiped out configuration files.
+ * - The font dialog displays all fonts unfiltered, and it's rather
+ * annoying if 95% of the listed fonts produce an error message.
+ */
+# if 0
+ {
+ /* Check that this is a mono-spaced font. Naturally, this is a bit
+ * hackish -- fixed-width isn't really suitable for i18n text :/ */
+ PangoLayout *layout;
+ unsigned int i;
+ int last_width = -1;
+ const char test_chars[] = { 'W', 'i', ',', 'x' }; /* arbitrary */
+
+ layout = pango_layout_new(gui.text_context);
+ pango_layout_set_font_description(layout, font);
+
+ for (i = 0; i < G_N_ELEMENTS(test_chars); ++i)
+ {
+ int width;
+
+ pango_layout_set_text(layout, &test_chars[i], 1);
+ pango_layout_get_size(layout, &width, NULL);
+
+ if (last_width >= 0 && width != last_width)
+ {
+ pango_font_description_free(font);
+ font = NULL;
+ break;
+ }
+
+ last_width = width;
+ }
+
+ g_object_unref(layout);
+ }
+# endif
+#else /* !HAVE_GTK2 */
+ {
+ XFontStruct *xfont;
+
+ /* reference this font as being in use */
+ gdk_font_ref(font);
+
+ /* Check that this is a mono-spaced font.
+ */
+ xfont = (XFontStruct *) GDK_FONT_XFONT(font);
+
+ if (xfont->max_bounds.width != xfont->min_bounds.width)
+ {
+ gdk_font_unref(font);
+ font = NULL;
+ }
+ }
+#endif /* !HAVE_GTK2 */
+
+#if !defined(HAVE_GTK2) || 0 /* disabled for GTK+ 2, see above */
+ if (font == NULL && report_error)
+ EMSG2(_(e_fontwidth), name);
+#endif
+
+ return font;
+}
+
+#if !defined(HAVE_GTK2) || defined(PROTO)
+/*
+ * Set the current text font.
+ * Since we create all GC on demand, we use just gui.current_font to
+ * indicate the desired current font.
+ */
+ void
+gui_mch_set_font(GuiFont font)
+{
+ gui.current_font = font;
+}
+#endif
+
+#if defined(FEAT_XFONTSET) || defined(PROTO)
+/*
+ * Set the current text fontset.
+ */
+ void
+gui_mch_set_fontset(GuiFontset fontset)
+{
+ gui.current_font = fontset;
+}
+#endif
+
+/*
+ * If a font is not going to be used, free its structure.
+ */
+ void
+gui_mch_free_font(GuiFont font)
+{
+ if (font != NOFONT)
+#ifdef HAVE_GTK2
+ pango_font_description_free(font);
+#else
+ gdk_font_unref(font);
+#endif
+}
+
+#if defined(FEAT_XFONTSET) || defined(PROTO)
+/*
+ * If a fontset is not going to be used, free its structure.
+ */
+ void
+gui_mch_free_fontset(GuiFontset fontset)
+{
+ if (fontset != NOFONTSET)
+ gdk_font_unref(fontset);
+}
+#endif
+
+
+/*
+ * Return the Pixel value (color) for the given color name. This routine was
+ * pretty much taken from example code in the Silicon Graphics OSF/Motif
+ * Programmer's Guide.
+ * Return INVALCOLOR for error.
+ */
+ guicolor_T
+gui_mch_get_color(char_u *name)
+{
+ /* A number of colors that some X11 systems don't have */
+ static const char *const vimnames[][2] =
+ {
+ {"LightRed", "#FFBBBB"},
+ {"LightGreen", "#88FF88"},
+ {"LightMagenta", "#FFBBFF"},
+ {"DarkCyan", "#008888"},
+ {"DarkBlue", "#0000BB"},
+ {"DarkRed", "#BB0000"},
+ {"DarkMagenta", "#BB00BB"},
+ {"DarkGrey", "#BBBBBB"},
+ {"DarkYellow", "#BBBB00"},
+ {NULL, NULL}
+ };
+
+ if (!gui.in_use) /* can't do this when GUI not running */
+ return INVALCOLOR;
+
+ while (name != NULL)
+ {
+ GdkColor color;
+ int parsed;
+ int i;
+
+ parsed = gdk_color_parse((const char *)name, &color);
+
+#ifndef HAVE_GTK2 /* ohh, lovely GTK+ 2, eases our pain :) */
+ /*
+ * Since we have already called gtk_set_locale here the bugger
+ * XParseColor will accept only explicit color names in the language
+ * of the current locale. However this will interferre with:
+ * 1. Vim's global startup files
+ * 2. Explicit color names in .vimrc
+ *
+ * Therefore we first try to parse the color in the current locale and
+ * if it fails, we fall back to the portable "C" one.
+ */
+ if (!parsed)
+ {
+ char *current;
+
+ current = setlocale(LC_ALL, NULL);
+ if (current != NULL)
+ {
+ char *saved;
+
+ saved = g_strdup(current);
+ setlocale(LC_ALL, "C");
+
+ parsed = gdk_color_parse((const gchar *)name, &color);
+
+ setlocale(LC_ALL, saved);
+ gtk_set_locale();
+
+ g_free(saved);
+ }
+ }
+#endif /* !HAVE_GTK2 */
+
+ if (parsed)
+ {
+#ifdef HAVE_GTK2
+ gdk_colormap_alloc_color(gtk_widget_get_colormap(gui.drawarea),
+ &color, FALSE, TRUE);
+#else
+ gdk_color_alloc(gtk_widget_get_colormap(gui.drawarea), &color);
+#endif
+ return (guicolor_T)color.pixel;
+ }
+ /* add a few builtin names and try again */
+ for (i = 0; ; ++i)
+ {
+ if (vimnames[i][0] == NULL)
+ {
+ name = NULL;
+ break;
+ }
+ if (STRICMP(name, vimnames[i][0]) == 0)
+ {
+ name = (char_u *)vimnames[i][1];
+ break;
+ }
+ }
+ }
+
+ return INVALCOLOR;
+}
+
+/*
+ * Set the current text foreground color.
+ */
+ void
+gui_mch_set_fg_color(guicolor_T color)
+{
+ gui.fgcolor->pixel = (unsigned long)color;
+}
+
+/*
+ * Set the current text background color.
+ */
+ void
+gui_mch_set_bg_color(guicolor_T color)
+{
+ gui.bgcolor->pixel = (unsigned long)color;
+}
+
+#ifdef HAVE_GTK2
+/*
+ * Function-like convenience macro for the sake of efficiency.
+ */
+#define INSERT_PANGO_ATTR(Attribute, AttrList, Start, End) \
+ G_STMT_START{ \
+ PangoAttribute *tmp_attr_; \
+ tmp_attr_ = (Attribute); \
+ tmp_attr_->start_index = (Start); \
+ tmp_attr_->end_index = (End); \
+ pango_attr_list_insert((AttrList), tmp_attr_); \
+ }G_STMT_END
+
+ static void
+apply_wide_font_attr(char_u *s, int len, PangoAttrList *attr_list)
+{
+ char_u *start = NULL;
+ char_u *p;
+ int uc;
+
+ for (p = s; p < s + len; p += utf_byte2len(*p))
+ {
+ uc = utf_ptr2char(p);
+
+ if (start == NULL)
+ {
+ if (uc >= 0x80 && utf_char2cells(uc) == 2)
+ start = p;
+ }
+ else if (uc < 0x80 /* optimization shortcut */
+ || (utf_char2cells(uc) != 2 && !utf_iscomposing(uc)))
+ {
+ INSERT_PANGO_ATTR(pango_attr_font_desc_new(gui.wide_font),
+ attr_list, start - s, p - s);
+ start = NULL;
+ }
+ }
+
+ if (start != NULL)
+ INSERT_PANGO_ATTR(pango_attr_font_desc_new(gui.wide_font),
+ attr_list, start - s, len);
+}
+
+ static int
+count_cluster_cells(char_u *s, PangoItem *item,
+ PangoGlyphString* glyphs, int i,
+ int *cluster_width,
+ int *last_glyph_rbearing)
+{
+ char_u *p;
+ int next; /* glyph start index of next cluster */
+ int start, end; /* string segment of current cluster */
+ int width; /* real cluster width in Pango units */
+ int uc;
+ int cellcount = 0;
+
+ width = glyphs->glyphs[i].geometry.width;
+
+ for (next = i + 1; next < glyphs->num_glyphs; ++next)
+ {
+ if (glyphs->glyphs[next].attr.is_cluster_start)
+ break;
+ else if (glyphs->glyphs[next].geometry.width > width)
+ width = glyphs->glyphs[next].geometry.width;
+ }
+
+ start = item->offset + glyphs->log_clusters[i];
+ end = item->offset + ((next < glyphs->num_glyphs) ?
+ glyphs->log_clusters[next] : item->length);
+
+ for (p = s + start; p < s + end; p += utf_byte2len(*p))
+ {
+ uc = utf_ptr2char(p);
+ if (uc < 0x80)
+ ++cellcount;
+ else if (!utf_iscomposing(uc))
+ cellcount += utf_char2cells(uc);
+ }
+
+ if (last_glyph_rbearing != NULL
+ && cellcount > 0 && next == glyphs->num_glyphs)
+ {
+ PangoRectangle ink_rect;
+ /*
+ * If a certain combining mark had to be taken from a non-monospace
+ * font, we have to compensate manually by adapting x_offset according
+ * to the ink extents of the previous glyph.
+ */
+ pango_font_get_glyph_extents(item->analysis.font,
+ glyphs->glyphs[i].glyph,
+ &ink_rect, NULL);
+
+ if (PANGO_RBEARING(ink_rect) > 0)
+ *last_glyph_rbearing = PANGO_RBEARING(ink_rect);
+ }
+
+ if (cellcount > 0)
+ *cluster_width = width;
+
+ return cellcount;
+}
+
+/*
+ * If there are only combining characters in the cluster, we cannot just
+ * change the width of the previous glyph since there is none. Therefore
+ * some guesswork is needed.
+ *
+ * If ink_rect.x is negative Pango apparently has taken care of the composing
+ * by itself. Actually setting x_offset = 0 should be sufficient then, but due
+ * to problems with composing from different fonts we still need to fine-tune
+ * x_offset to avoid uglyness.
+ *
+ * If ink_rect.x is not negative, force overstriking by pointing x_offset to
+ * the position of the previous glyph. Apparently this happens only with old
+ * X fonts which don't provide the special combining information needed by
+ * Pango.
+ */
+ static void
+setup_zero_width_cluster(PangoItem *item, PangoGlyphInfo *glyph,
+ int last_cellcount, int last_cluster_width,
+ int last_glyph_rbearing)
+{
+ PangoRectangle ink_rect;
+ PangoRectangle logical_rect;
+ int width;
+
+ width = last_cellcount * gui.char_width * PANGO_SCALE;
+ glyph->geometry.x_offset = -width + MAX(0, width - last_cluster_width) / 2;
+ glyph->geometry.width = 0;
+
+ pango_font_get_glyph_extents(item->analysis.font,
+ glyph->glyph,
+ &ink_rect, &logical_rect);
+ if (ink_rect.x < 0)
+ {
+ glyph->geometry.x_offset += last_glyph_rbearing;
+ glyph->geometry.y_offset = logical_rect.height
+ - (gui.char_height - p_linespace) * PANGO_SCALE;
+ }
+}
+
+ static void
+draw_glyph_string(int row, int col, int num_cells, int flags,
+ PangoFont *font, PangoGlyphString *glyphs)
+{
+ if (!(flags & DRAW_TRANSP))
+ {
+ gdk_gc_set_foreground(gui.text_gc, gui.bgcolor);
+
+ gdk_draw_rectangle(gui.drawarea->window,
+ gui.text_gc,
+ TRUE,
+ FILL_X(col),
+ FILL_Y(row),
+ num_cells * gui.char_width,
+ gui.char_height);
+ }
+
+ gdk_gc_set_foreground(gui.text_gc, gui.fgcolor);
+
+ gdk_draw_glyphs(gui.drawarea->window,
+ gui.text_gc,
+ font,
+ TEXT_X(col),
+ TEXT_Y(row),
+ glyphs);
+
+ /* redraw the contents with an offset of 1 to emulate bold */
+ if ((flags & DRAW_BOLD) && !gui.font_can_bold)
+ gdk_draw_glyphs(gui.drawarea->window,
+ gui.text_gc,
+ font,
+ TEXT_X(col) + 1,
+ TEXT_Y(row),
+ glyphs);
+}
+
+#endif /* HAVE_GTK2 */
+
+#if defined(HAVE_GTK2) || defined(PROTO)
+ int
+gui_gtk2_draw_string(int row, int col, char_u *s, int len, int flags)
+{
+ GdkRectangle area; /* area for clip mask */
+ PangoGlyphString *glyphs; /* glyphs of current item */
+ int column_offset = 0; /* column offset in cells */
+ int i;
+ char_u *conv_buf = NULL; /* result of UTF-8 conversion */
+ char_u *new_conv_buf;
+ int convlen;
+ char_u *sp, *bp;
+ int plen;
+
+ if (gui.text_context == NULL || gui.drawarea->window == NULL)
+ return len;
+
+ if (output_conv.vc_type != CONV_NONE)
+ {
+ /*
+ * Convert characters from 'encoding' to 'termencoding', which is set
+ * to UTF-8 by gui_mch_init(). did_set_string_option() in option.c
+ * prohibits changing this to something else than UTF-8 if the GUI is
+ * in use.
+ */
+ convlen = len;
+ conv_buf = string_convert(&output_conv, s, &convlen);
+ g_return_val_if_fail(conv_buf != NULL, len);
+
+ /* Correct for differences in char width: some chars are
+ * double-wide in 'encoding' but single-wide in utf-8. Add a space to
+ * compensate for that. */
+ for (sp = s, bp = conv_buf; sp < s + len && bp < conv_buf + convlen; )
+ {
+ plen = utf_ptr2len_check(bp);
+ if ((*mb_ptr2cells)(sp) == 2 && utf_ptr2cells(bp) == 1)
+ {
+ new_conv_buf = alloc(convlen + 2);
+ if (new_conv_buf == NULL)
+ return len;
+ plen += bp - conv_buf;
+ mch_memmove(new_conv_buf, conv_buf, plen);
+ new_conv_buf[plen] = ' ';
+ mch_memmove(new_conv_buf + plen + 1, conv_buf + plen,
+ convlen - plen + 1);
+ vim_free(conv_buf);
+ conv_buf = new_conv_buf;
+ ++convlen;
+ bp = conv_buf + plen;
+ plen = 1;
+ }
+ sp += (*mb_ptr2len_check)(sp);
+ bp += plen;
+ }
+ s = conv_buf;
+ len = convlen;
+ }
+
+ /*
+ * Restrict all drawing to the current screen line in order to prevent
+ * fuzzy font lookups from messing up the screen.
+ */
+ area.x = gui.border_offset;
+ area.y = FILL_Y(row);
+ area.width = gui.num_cols * gui.char_width;
+ area.height = gui.char_height;
+
+ gdk_gc_set_clip_origin(gui.text_gc, 0, 0);
+ gdk_gc_set_clip_rectangle(gui.text_gc, &area);
+
+ glyphs = pango_glyph_string_new();
+
+ /*
+ * Optimization hack: If possible, skip the itemize and shaping process
+ * for pure ASCII strings. This optimization is particularly effective
+ * because Vim draws space characters to clear parts of the screen.
+ */
+ if (!(flags & DRAW_ITALIC)
+ && !((flags & DRAW_BOLD) && gui.font_can_bold)
+ && gui.ascii_glyphs != NULL)
+ {
+ char_u *p;
+
+ for (p = s; p < s + len; ++p)
+ if (*p & 0x80)
+ goto not_ascii;
+
+ pango_glyph_string_set_size(glyphs, len);
+
+ for (i = 0; i < len; ++i)
+ {
+ glyphs->glyphs[i] = gui.ascii_glyphs->glyphs[s[i]];
+ glyphs->log_clusters[i] = i;
+ }
+
+ draw_glyph_string(row, col, len, flags, gui.ascii_font, glyphs);
+
+ column_offset = len;
+ }
+ else
+not_ascii:
+ {
+ PangoAttrList *attr_list;
+ GList *item_list;
+ int cluster_width;
+ int last_glyph_rbearing;
+ int cells = 0; /* cells occupied by current cluster */
+
+ /* original width of the current cluster */
+ cluster_width = PANGO_SCALE * gui.char_width;
+
+ /* right bearing of the last non-composing glyph */
+ last_glyph_rbearing = PANGO_SCALE * gui.char_width;
+
+ attr_list = pango_attr_list_new();
+
+ /* If 'guifontwide' is set then use that for double-width characters.
+ * Otherwise just go with 'guifont' and let Pango do its thing. */
+ if (gui.wide_font != NULL)
+ apply_wide_font_attr(s, len, attr_list);
+
+ if ((flags & DRAW_BOLD) && gui.font_can_bold)
+ INSERT_PANGO_ATTR(pango_attr_weight_new(PANGO_WEIGHT_BOLD),
+ attr_list, 0, len);
+ if (flags & DRAW_ITALIC)
+ INSERT_PANGO_ATTR(pango_attr_style_new(PANGO_STYLE_ITALIC),
+ attr_list, 0, len);
+ /*
+ * Break the text into segments with consistent directional level
+ * and shaping engine. Pure Latin text needs only a single segment,
+ * so there's no need to worry about the loop's efficiency. Better
+ * try to optimize elsewhere, e.g. reducing exposes and stuff :)
+ */
+ item_list = pango_itemize(gui.text_context,
+ (const char *)s, 0, len, attr_list, NULL);
+
+ while (item_list != NULL)
+ {
+ PangoItem *item;
+ int item_cells = 0; /* item length in cells */
+
+ item = (PangoItem *)item_list->data;
+ item_list = g_list_delete_link(item_list, item_list);
+ /*
+ * Increment the bidirectional embedding level by 1 if it is not
+ * even. An odd number means the output will be RTL, but we don't
+ * want that since Vim handles right-to-left text on its own. It
+ * would probably be sufficient to just set level = 0, but you can
+ * never know :)
+ *
+ * Unfortunately we can't take advantage of Pango's ability to
+ * render both LTR and RTL at the same time. In order to support
+ * that, Vim's main screen engine would have to make use of Pango
+ * functionality.
+ */
+ item->analysis.level = (item->analysis.level + 1) & (~1U);
+
+ /* HACK: Overrule the shape engine, we don't want shaping to be
+ * done, because drawing the cursor would change the display. */
+ item->analysis.shape_engine = default_shape_engine;
+
+ pango_shape((const char *)s + item->offset, item->length,
+ &item->analysis, glyphs);
+ /*
+ * Fixed-width hack: iterate over the array and assign a fixed
+ * width to each glyph, thus overriding the choice made by the
+ * shaping engine. We use utf_char2cells() to determine the
+ * number of cells needed.
+ *
+ * Also perform all kind of dark magic to get composing
+ * characters right (and pretty too of course).
+ */
+ for (i = 0; i < glyphs->num_glyphs; ++i)
+ {
+ PangoGlyphInfo *glyph;
+
+ glyph = &glyphs->glyphs[i];
+
+ if (glyph->attr.is_cluster_start)
+ {
+ int cellcount;
+
+ cellcount = count_cluster_cells(
+ s, item, glyphs, i, &cluster_width,
+ (item_list != NULL) ? &last_glyph_rbearing : NULL);
+
+ if (cellcount > 0)
+ {
+ int width;
+
+ width = cellcount * gui.char_width * PANGO_SCALE;
+ glyph->geometry.x_offset +=
+ MAX(0, width - cluster_width) / 2;
+ glyph->geometry.width = width;
+ }
+ else
+ {
+ /* If there are only combining characters in the
+ * cluster, we cannot just change the width of the
+ * previous glyph since there is none. Therefore
+ * some guesswork is needed. */
+ setup_zero_width_cluster(item, glyph, cells,
+ cluster_width,
+ last_glyph_rbearing);
+ }
+
+ item_cells += cellcount;
+ cells = cellcount;
+ }
+ else if (i > 0)
+ {
+ int width;
+
+ /* There is a previous glyph, so we deal with combining
+ * characters the canonical way. That is, setting the
+ * width of the previous glyph to 0. */
+ glyphs->glyphs[i - 1].geometry.width = 0;
+
+ width = cells * gui.char_width * PANGO_SCALE;
+ glyph->geometry.x_offset +=
+ MAX(0, width - cluster_width) / 2;
+ glyph->geometry.width = width;
+ }
+ else /* i == 0 "cannot happen" */
+ {
+ glyph->geometry.width = 0;
+ }
+ }
+
+ /*** Aaaaand action! ***/
+ draw_glyph_string(row, col + column_offset, item_cells,
+ flags, item->analysis.font, glyphs);
+
+ pango_item_free(item);
+
+ column_offset += item_cells;
+ }
+
+ pango_attr_list_unref(attr_list);
+ }
+
+ if (flags & DRAW_UNDERL)
+ gdk_draw_line(gui.drawarea->window,
+ gui.text_gc,
+ FILL_X(col),
+ FILL_Y(row + 1) - 1,
+ FILL_X(col + column_offset) - 1,
+ FILL_Y(row + 1) - 1);
+
+ pango_glyph_string_free(glyphs);
+ vim_free(conv_buf);
+
+ gdk_gc_set_clip_rectangle(gui.text_gc, NULL);
+
+ return column_offset;
+}
+#endif /* HAVE_GTK2 */
+
+#if !defined(HAVE_GTK2) || defined(PROTO)
+ void
+gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
+{
+ static XChar2b *buf = NULL;
+ static int buflen = 0;
+ int is_wide;
+ XChar2b *text;
+ int textlen;
+ XFontStruct *xfont;
+ char_u *p;
+# ifdef FEAT_MBYTE
+ unsigned c;
+# endif
+ int width;
+
+ if (gui.current_font == NULL || gui.drawarea->window == NULL)
+ return;
+
+ /*
+ * Yeah yeah apparently the font support in GTK+ 1.2 only cares for either:
+ * asians or 8-bit fonts. It is broken there, but no wonder the whole font
+ * stuff is broken in X11 in first place. And the internationalization API
+ * isn't something you would really like to use.
+ */
+
+ xfont = (XFontStruct *)((GdkFontPrivate*)gui.current_font)->xfont;
+ is_wide = ((xfont->min_byte1 != 0 || xfont->max_byte1 != 0)
+# ifdef FEAT_XFONTSET
+ && gui.fontset == NOFONTSET
+# endif
+ );
+
+ if (is_wide)
+ {
+ /* Convert a byte sequence to 16 bit characters for the Gdk functions.
+ * Need a buffer for the 16 bit characters. Keep it between calls,
+ * because allocating it each time is slow. */
+ if (buflen < len)
+ {
+ XtFree((char *)buf);
+ buf = (XChar2b *)XtMalloc(len * sizeof(XChar2b));
+ buflen = len;
+ }
+
+ p = s;
+ textlen = 0;
+ width = 0;
+ while (p < s + len)
+ {
+# ifdef FEAT_MBYTE
+ if (enc_utf8)
+ {
+ c = utf_ptr2char(p);
+ if (c >= 0x10000) /* show chars > 0xffff as ? */
+ c = 0xbf;
+ buf[textlen].byte1 = c >> 8;
+ buf[textlen].byte2 = c;
+ p += utf_ptr2len_check(p);
+ width += utf_char2cells(c);
+ }
+ else
+# endif
+ {
+ buf[textlen].byte1 = '\0'; /* high eight bits */
+ buf[textlen].byte2 = *p; /* low eight bits */
+ ++p;
+ ++width;
+ }
+ ++textlen;
+ }
+ text = buf;
+ textlen = textlen * 2;
+ }
+ else
+ {
+ text = (XChar2b *)s;
+ textlen = len;
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ width = 0;
+ for (p = s; p < s + len; p += (*mb_ptr2len_check)(p))
+ width += (*mb_ptr2cells)(p);
+ }
+ else
+# endif
+ width = len;
+ }
+
+ if (!(flags & DRAW_TRANSP))
+ {
+ gdk_gc_set_foreground(gui.text_gc, gui.bgcolor);
+ gdk_draw_rectangle(gui.drawarea->window,
+ gui.text_gc,
+ TRUE,
+ FILL_X(col), FILL_Y(row),
+ width * gui.char_width, gui.char_height);
+ }
+ gdk_gc_set_foreground(gui.text_gc, gui.fgcolor);
+ gdk_draw_text(gui.drawarea->window,
+ gui.current_font,
+ gui.text_gc,
+ TEXT_X(col), TEXT_Y(row),
+ (const gchar *)text, textlen);
+
+ /* redraw the contents with an offset of 1 to emulate bold */
+ if (flags & DRAW_BOLD)
+ gdk_draw_text(gui.drawarea->window,
+ gui.current_font,
+ gui.text_gc,
+ TEXT_X(col) + 1, TEXT_Y(row),
+ (const gchar *)text, textlen);
+
+ if (flags & DRAW_UNDERL)
+ {
+ gdk_draw_line(gui.drawarea->window,
+ gui.text_gc, FILL_X(col),
+ FILL_Y(row + 1) - 1, FILL_X(col + width) - 1, FILL_Y(row + 1) - 1);
+ }
+}
+#endif /* !HAVE_GTK2 */
+
+/*
+ * Return OK if the key with the termcap name "name" is supported.
+ */
+ int
+gui_mch_haskey(char_u *name)
+{
+ int i;
+
+ for (i = 0; special_keys[i].key_sym != 0; i++)
+ if (name[0] == special_keys[i].code0
+ && name[1] == special_keys[i].code1)
+ return OK;
+ return FAIL;
+}
+
+#if defined(FEAT_TITLE) \
+ || (defined(FEAT_XIM) && !defined(HAVE_GTK2)) \
+ || defined(PROTO)
+/*
+ * Return the text window-id and display. Only required for X-based GUI's
+ */
+ int
+gui_get_x11_windis(Window *win, Display **dis)
+{
+ if (gui.mainwin != NULL && gui.mainwin->window != NULL)
+ {
+ *dis = GDK_WINDOW_XDISPLAY(gui.mainwin->window);
+ *win = GDK_WINDOW_XWINDOW(gui.mainwin->window);
+ return OK;
+ }
+
+ *dis = NULL;
+ *win = 0;
+ return FAIL;
+}
+#endif
+
+#if defined(FEAT_CLIENTSERVER) \
+ || (defined(FEAT_X11) && defined(FEAT_CLIPBOARD)) || defined(PROTO)
+
+ Display *
+gui_mch_get_display(void)
+{
+ if (gui.mainwin != NULL && gui.mainwin->window != NULL)
+ return GDK_WINDOW_XDISPLAY(gui.mainwin->window);
+ else
+ return NULL;
+}
+#endif
+
+ void
+gui_mch_beep(void)
+{
+#ifdef HAVE_GTK_MULTIHEAD
+ GdkDisplay *display;
+
+ if (gui.mainwin != NULL && GTK_WIDGET_REALIZED(gui.mainwin))
+ display = gtk_widget_get_display(gui.mainwin);
+ else
+ display = gdk_display_get_default();
+
+ if (display != NULL)
+ gdk_display_beep(display);
+#else
+ gdk_beep();
+#endif
+}
+
+ void
+gui_mch_flash(int msec)
+{
+ GdkGCValues values;
+ GdkGC *invert_gc;
+
+ if (gui.drawarea->window == NULL)
+ return;
+
+ values.foreground.pixel = gui.norm_pixel ^ gui.back_pixel;
+ values.background.pixel = gui.norm_pixel ^ gui.back_pixel;
+ values.function = GDK_XOR;
+ invert_gc = gdk_gc_new_with_values(gui.drawarea->window,
+ &values,
+ GDK_GC_FOREGROUND |
+ GDK_GC_BACKGROUND |
+ GDK_GC_FUNCTION);
+ gdk_gc_set_exposures(invert_gc,
+ gui.visibility != GDK_VISIBILITY_UNOBSCURED);
+ /*
+ * Do a visual beep by changing back and forth in some undetermined way,
+ * the foreground and background colors. This is due to the fact that
+ * there can't be really any prediction about the effects of XOR on
+ * arbitrary X11 servers. However this seems to be enough for what we
+ * intend it to do.
+ */
+ gdk_draw_rectangle(gui.drawarea->window, invert_gc,
+ TRUE,
+ 0, 0,
+ FILL_X((int)Columns) + gui.border_offset,
+ FILL_Y((int)Rows) + gui.border_offset);
+
+ gui_mch_flush();
+ ui_delay((long)msec, TRUE); /* wait so many msec */
+
+ gdk_draw_rectangle(gui.drawarea->window, invert_gc,
+ TRUE,
+ 0, 0,
+ FILL_X((int)Columns) + gui.border_offset,
+ FILL_Y((int)Rows) + gui.border_offset);
+
+ gdk_gc_destroy(invert_gc);
+}
+
+/*
+ * Invert a rectangle from row r, column c, for nr rows and nc columns.
+ */
+ void
+gui_mch_invert_rectangle(int r, int c, int nr, int nc)
+{
+ GdkGCValues values;
+ GdkGC *invert_gc;
+ GdkColor foreground;
+ GdkColor background;
+
+ if (gui.drawarea->window == NULL)
+ return;
+
+ foreground.pixel = gui.norm_pixel ^ gui.back_pixel;
+ background.pixel = gui.norm_pixel ^ gui.back_pixel;
+
+ values.foreground = foreground;
+ values.background = background;
+ values.function = GDK_XOR;
+ invert_gc = gdk_gc_new_with_values(gui.drawarea->window,
+ &values,
+ GDK_GC_FOREGROUND |
+ GDK_GC_BACKGROUND |
+ GDK_GC_FUNCTION);
+ gdk_gc_set_exposures(invert_gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
+ gdk_draw_rectangle(gui.drawarea->window, invert_gc,
+ TRUE,
+ FILL_X(c), FILL_Y(r),
+ (nc) * gui.char_width, (nr) * gui.char_height);
+ gdk_gc_destroy(invert_gc);
+}
+
+/*
+ * Iconify the GUI window.
+ */
+ void
+gui_mch_iconify(void)
+{
+#ifdef HAVE_GTK2
+ gtk_window_iconify(GTK_WINDOW(gui.mainwin));
+#else
+ XIconifyWindow(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
+ GDK_WINDOW_XWINDOW(gui.mainwin->window),
+ DefaultScreen(GDK_WINDOW_XDISPLAY(gui.mainwin->window)));
+#endif
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Bring the Vim window to the foreground.
+ */
+ void
+gui_mch_set_foreground(void)
+{
+# ifdef HAVE_GTK2
+ gtk_window_present(GTK_WINDOW(gui.mainwin));
+# else
+ gdk_window_raise(gui.mainwin->window);
+# endif
+}
+#endif
+
+/*
+ * Draw a cursor without focus.
+ */
+ void
+gui_mch_draw_hollow_cursor(guicolor_T color)
+{
+ int i = 1;
+
+ if (gui.drawarea->window == NULL)
+ return;
+
+ gui_mch_set_fg_color(color);
+
+ gdk_gc_set_foreground(gui.text_gc, gui.fgcolor);
+#ifdef FEAT_MBYTE
+ if (mb_lefthalve(gui.row, gui.col))
+ i = 2;
+#endif
+ gdk_draw_rectangle(gui.drawarea->window, gui.text_gc,
+ FALSE,
+ FILL_X(gui.col), FILL_Y(gui.row),
+ i * gui.char_width - 1, gui.char_height - 1);
+}
+
+/*
+ * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using
+ * color "color".
+ */
+ void
+gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
+{
+ if (gui.drawarea->window == NULL)
+ return;
+
+ gui_mch_set_fg_color(color);
+
+ gdk_gc_set_foreground(gui.text_gc, gui.fgcolor);
+ gdk_draw_rectangle(gui.drawarea->window, gui.text_gc,
+ TRUE,
+#ifdef FEAT_RIGHTLEFT
+ /* vertical line should be on the right of current point */
+ CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
+#endif
+ FILL_X(gui.col),
+ FILL_Y(gui.row) + gui.char_height - h,
+ w, h);
+}
+
+
+/*
+ * Catch up with any queued X11 events. This may put keyboard input into the
+ * input buffer, call resize call-backs, trigger timers etc. If there is
+ * nothing in the X11 event queue (& no timers pending), then we return
+ * immediately.
+ */
+ void
+gui_mch_update(void)
+{
+ while (gtk_events_pending() && !vim_is_input_buf_full())
+ gtk_main_iteration_do(FALSE);
+}
+
+ static gint
+input_timer_cb(gpointer data)
+{
+ int *timed_out = (int *) data;
+
+ /* Just inform the caller about the occurence of it */
+ *timed_out = TRUE;
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+
+ return FALSE; /* don't happen again */
+}
+
+#ifdef FEAT_SNIFF
+/*
+ * Callback function, used when data is available on the SNiFF connection.
+ */
+/* ARGSUSED */
+ static void
+sniff_request_cb(
+ gpointer data,
+ gint source_fd,
+ GdkInputCondition condition)
+{
+ static char_u bytes[3] = {CSI, (int)KS_EXTRA, (int)KE_SNIFF};
+
+ add_to_input_buf(bytes, 3);
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+#endif
+
+/*
+ * GUI input routine called by gui_wait_for_chars(). Waits for a character
+ * from the keyboard.
+ * wtime == -1 Wait forever.
+ * wtime == 0 This should never happen.
+ * wtime > 0 Wait wtime milliseconds for a character.
+ * Returns OK if a character was found to be available within the given time,
+ * or FAIL otherwise.
+ */
+ int
+gui_mch_wait_for_chars(long wtime)
+{
+ int focus;
+ guint timer;
+ static int timed_out;
+#ifdef FEAT_SNIFF
+ static int sniff_on = 0;
+ static gint sniff_input_id = 0;
+#endif
+
+#ifdef FEAT_SNIFF
+ if (sniff_on && !want_sniff_request)
+ {
+ if (sniff_input_id)
+ gdk_input_remove(sniff_input_id);
+ sniff_on = 0;
+ }
+ else if (!sniff_on && want_sniff_request)
+ {
+ /* Add fd_from_sniff to watch for available data in main loop. */
+ sniff_input_id = gdk_input_add(fd_from_sniff,
+ GDK_INPUT_READ, sniff_request_cb, NULL);
+ sniff_on = 1;
+ }
+#endif
+
+ timed_out = FALSE;
+
+ /* this timeout makes sure that we will return if no characters arrived in
+ * time */
+
+ if (wtime > 0)
+ timer = gtk_timeout_add((guint32)wtime, input_timer_cb, &timed_out);
+ else
+ timer = 0;
+
+ focus = gui.in_focus;
+
+ do
+ {
+ /* Stop or start blinking when focus changes */
+ if (gui.in_focus != focus)
+ {
+ if (gui.in_focus)
+ gui_mch_start_blink();
+ else
+ gui_mch_stop_blink();
+ focus = gui.in_focus;
+ }
+
+ /*
+ * Loop in GTK+ processing until a timeout or input occurs.
+ */
+ gtk_main();
+
+ /* Got char, return immediately */
+ if (input_available())
+ {
+ if (timer != 0 && !timed_out)
+ gtk_timeout_remove(timer);
+ return OK;
+ }
+ } while (wtime < 0 || !timed_out);
+
+ /*
+ * Flush all eventually pending (drawing) events.
+ */
+ gui_mch_update();
+
+ return FAIL;
+}
+
+
+/****************************************************************************
+ * Output drawing routines.
+ ****************************************************************************/
+
+
+/* Flush any output to the screen */
+ void
+gui_mch_flush(void)
+{
+#ifdef HAVE_GTK_MULTIHEAD
+ if (gui.mainwin != NULL && GTK_WIDGET_REALIZED(gui.mainwin))
+ gdk_display_sync(gtk_widget_get_display(gui.mainwin));
+#else
+ gdk_flush(); /* historical misnomer: calls XSync(), not XFlush() */
+#endif
+#ifdef HAVE_GTK2
+ /* This happens to actually do what gui_mch_flush() is supposed to do,
+ * according to the comment above. */
+ if (gui.drawarea != NULL && gui.drawarea->window != NULL)
+ gdk_window_process_updates(gui.drawarea->window, FALSE);
+#endif
+}
+
+/*
+ * Clear a rectangular region of the screen from text pos (row1, col1) to
+ * (row2, col2) inclusive.
+ */
+ void
+gui_mch_clear_block(int row1, int col1, int row2, int col2)
+{
+ GdkColor color;
+
+ if (gui.drawarea->window == NULL)
+ return;
+
+ color.pixel = gui.back_pixel;
+
+ gdk_gc_set_foreground(gui.text_gc, &color);
+
+ /* Clear one extra pixel at the far right, for when bold characters have
+ * spilled over to the window border. */
+ gdk_draw_rectangle(gui.drawarea->window, gui.text_gc, TRUE,
+ FILL_X(col1), FILL_Y(row1),
+ (col2 - col1 + 1) * gui.char_width
+ + (col2 == Columns - 1),
+ (row2 - row1 + 1) * gui.char_height);
+}
+
+ void
+gui_mch_clear_all(void)
+{
+ if (gui.drawarea->window != NULL)
+ gdk_window_clear(gui.drawarea->window);
+}
+
+/*
+ * Redraw any text revealed by scrolling up/down.
+ */
+ static void
+check_copy_area(void)
+{
+ GdkEvent *event;
+ int expose_count;
+
+ if (gui.visibility != GDK_VISIBILITY_PARTIAL)
+ return;
+
+ /* Avoid redrawing the cursor while scrolling or it'll end up where
+ * we don't want it to be. I'm not sure if it's correct to call
+ * gui_dont_update_cursor() at this point but it works as a quick
+ * fix for now. */
+ gui_dont_update_cursor();
+
+ do
+ {
+ /* Wait to check whether the scroll worked or not. */
+ event = gdk_event_get_graphics_expose(gui.drawarea->window);
+
+ if (event == NULL)
+ break; /* received NoExpose event */
+
+ gui_redraw(event->expose.area.x, event->expose.area.y,
+ event->expose.area.width, event->expose.area.height);
+
+ expose_count = event->expose.count;
+ gdk_event_free(event);
+ }
+ while (expose_count > 0); /* more events follow */
+
+ gui_can_update_cursor();
+}
+
+/*
+ * Delete the given number of lines from the given row, scrolling up any
+ * text further down within the scroll region.
+ */
+ void
+gui_mch_delete_lines(int row, int num_lines)
+{
+ if (gui.visibility == GDK_VISIBILITY_FULLY_OBSCURED)
+ return; /* Can't see the window */
+
+ gdk_gc_set_foreground(gui.text_gc, gui.fgcolor);
+ gdk_gc_set_background(gui.text_gc, gui.bgcolor);
+
+ /* copy one extra pixel, for when bold has spilled over */
+ gdk_window_copy_area(gui.drawarea->window, gui.text_gc,
+ FILL_X(gui.scroll_region_left), FILL_Y(row),
+ gui.drawarea->window,
+ FILL_X(gui.scroll_region_left),
+ FILL_Y(row + num_lines),
+ gui.char_width * (gui.scroll_region_right
+ - gui.scroll_region_left + 1) + 1,
+ gui.char_height * (gui.scroll_region_bot - row - num_lines + 1));
+
+ gui_clear_block(gui.scroll_region_bot - num_lines + 1,
+ gui.scroll_region_left,
+ gui.scroll_region_bot, gui.scroll_region_right);
+ check_copy_area();
+}
+
+/*
+ * Insert the given number of lines before the given row, scrolling down any
+ * following text within the scroll region.
+ */
+ void
+gui_mch_insert_lines(int row, int num_lines)
+{
+ if (gui.visibility == GDK_VISIBILITY_FULLY_OBSCURED)
+ return; /* Can't see the window */
+
+ gdk_gc_set_foreground(gui.text_gc, gui.fgcolor);
+ gdk_gc_set_background(gui.text_gc, gui.bgcolor);
+
+ /* copy one extra pixel, for when bold has spilled over */
+ gdk_window_copy_area(gui.drawarea->window, gui.text_gc,
+ FILL_X(gui.scroll_region_left), FILL_Y(row + num_lines),
+ gui.drawarea->window,
+ FILL_X(gui.scroll_region_left), FILL_Y(row),
+ gui.char_width * (gui.scroll_region_right
+ - gui.scroll_region_left + 1) + 1,
+ gui.char_height * (gui.scroll_region_bot - row - num_lines + 1));
+
+ gui_clear_block(row, gui.scroll_region_left,
+ row + num_lines - 1, gui.scroll_region_right);
+ check_copy_area();
+}
+
+/*
+ * X Selection stuff, for cutting and pasting text to other windows.
+ */
+ void
+clip_mch_request_selection(VimClipboard *cbd)
+{
+ GdkAtom target;
+ unsigned i;
+ int nbytes;
+ char_u *buffer;
+
+ for (i = 0; i < N_SELECTION_TARGETS; ++i)
+ {
+ received_selection = RS_NONE;
+ target = gdk_atom_intern(selection_targets[i].target, FALSE);
+
+ gtk_selection_convert(gui.drawarea,
+ cbd->gtk_sel_atom, target,
+ (guint32)GDK_CURRENT_TIME);
+
+ while (received_selection == RS_NONE)
+ gtk_main(); /* wait for selection_received_cb */
+
+ if (received_selection != RS_FAIL)
+ return;
+ }
+
+ /* Final fallback position - use the X CUT_BUFFER0 store */
+ nbytes = 0;
+ buffer = (char_u *)XFetchBuffer(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
+ &nbytes, 0);
+ if (nbytes > 0)
+ {
+ /* Got something */
+ clip_yank_selection(MCHAR, buffer, (long)nbytes, cbd);
+ if (p_verbose > 0)
+ smsg((char_u *)_("Used CUT_BUFFER0 instead of empty selection"));
+ }
+ if (buffer != NULL)
+ XFree(buffer);
+}
+
+/*
+ * Disown the selection.
+ */
+/*ARGSUSED*/
+ void
+clip_mch_lose_selection(VimClipboard *cbd)
+{
+ /* WEIRD: when using NULL to actually disown the selection, we lose the
+ * selection the first time we own it. */
+ /*
+ gtk_selection_owner_set(NULL, cbd->gtk_sel_atom, (guint32)GDK_CURRENT_TIME);
+ gui_mch_update();
+ */
+}
+
+/*
+ * Own the selection and return OK if it worked.
+ */
+ int
+clip_mch_own_selection(VimClipboard *cbd)
+{
+ int success;
+
+ success = gtk_selection_owner_set(gui.drawarea, cbd->gtk_sel_atom,
+ (guint32)GDK_CURRENT_TIME);
+ gui_mch_update();
+ return (success) ? OK : FAIL;
+}
+
+/*
+ * Send the current selection to the clipboard. Do nothing for X because we
+ * will fill in the selection only when requested by another app.
+ */
+/*ARGSUSED*/
+ void
+clip_mch_set_selection(VimClipboard *cbd)
+{
+}
+
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Make a menu item appear either active or not active (grey or not grey).
+ */
+ void
+gui_mch_menu_grey(vimmenu_T *menu, int grey)
+{
+ if (menu->id == NULL)
+ return;
+
+ if (menu_is_separator(menu->name))
+ grey = TRUE;
+
+ gui_mch_menu_hidden(menu, FALSE);
+ /* Be clever about bitfields versus true booleans here! */
+ if (!GTK_WIDGET_SENSITIVE(menu->id) == !grey)
+ {
+ gtk_widget_set_sensitive(menu->id, !grey);
+ gui_mch_update();
+ }
+}
+
+/*
+ * Make menu item hidden or not hidden.
+ */
+ void
+gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
+{
+ if (menu->id == 0)
+ return;
+
+ if (hidden)
+ {
+ if (GTK_WIDGET_VISIBLE(menu->id))
+ {
+ gtk_widget_hide(menu->id);
+ gui_mch_update();
+ }
+ }
+ else
+ {
+ if (!GTK_WIDGET_VISIBLE(menu->id))
+ {
+ gtk_widget_show(menu->id);
+ gui_mch_update();
+ }
+ }
+}
+
+/*
+ * This is called after setting all the menus to grey/hidden or not.
+ */
+ void
+gui_mch_draw_menubar(void)
+{
+ /* just make sure that the visual changes get effect immediately */
+ gui_mch_update();
+}
+#endif /* FEAT_MENU */
+
+/*
+ * Scrollbar stuff.
+ */
+ void
+gui_mch_enable_scrollbar(scrollbar_T *sb, int flag)
+{
+ if (sb->id == NULL)
+ return;
+
+ if (flag)
+ gtk_widget_show(sb->id);
+ else
+ gtk_widget_hide(sb->id);
+
+ update_window_manager_hints();
+}
+
+
+/*
+ * Return the RGB value of a pixel as long.
+ */
+ long_u
+gui_mch_get_rgb(guicolor_T pixel)
+{
+ GdkColor color;
+#ifndef HAVE_GTK2
+ GdkColorContext *cc;
+
+ cc = gdk_color_context_new(gtk_widget_get_visual(gui.drawarea),
+ gtk_widget_get_colormap(gui.drawarea));
+ color.pixel = pixel;
+ gdk_color_context_query_color(cc, &color);
+
+ gdk_color_context_free(cc);
+#else
+ gdk_colormap_query_color(gtk_widget_get_colormap(gui.drawarea),
+ (unsigned long)pixel, &color);
+#endif
+
+ return (((unsigned)color.red & 0xff00) << 8)
+ | ((unsigned)color.green & 0xff00)
+ | (((unsigned)color.blue & 0xff00) >> 8);
+}
+
+/*
+ * Get current y mouse coordinate in text window.
+ * Return -1 when unknown.
+ */
+ int
+gui_mch_get_mouse_x(void)
+{
+ int win_x;
+
+ gdk_window_get_pointer(gui.drawarea->window, &win_x, NULL, NULL);
+ return win_x;
+}
+
+ int
+gui_mch_get_mouse_y(void)
+{
+ int win_y;
+
+ gdk_window_get_pointer(gui.drawarea->window, NULL, &win_y, NULL);
+ return win_y;
+}
+
+ void
+gui_mch_setmouse(int x, int y)
+{
+ /* Sorry for the Xlib call, but we can't avoid it, since there is no
+ * internal GDK mechanism present to accomplish this. (and for good
+ * reason...) */
+ XWarpPointer(GDK_WINDOW_XDISPLAY(gui.drawarea->window),
+ (Window)0, GDK_WINDOW_XWINDOW(gui.drawarea->window),
+ 0, 0, 0U, 0U, x, y);
+}
+
+
+#ifdef FEAT_MOUSESHAPE
+/* The last set mouse pointer shape is remembered, to be used when it goes
+ * from hidden to not hidden. */
+static int last_shape = 0;
+#endif
+
+/*
+ * Use the blank mouse pointer or not.
+ *
+ * hide: TRUE = use blank ptr, FALSE = use parent ptr
+ */
+ void
+gui_mch_mousehide(int hide)
+{
+ if (gui.pointer_hidden != hide)
+ {
+ gui.pointer_hidden = hide;
+ if (gui.drawarea->window && gui.blank_pointer != NULL)
+ {
+ if (hide)
+ gdk_window_set_cursor(gui.drawarea->window, gui.blank_pointer);
+ else
+#ifdef FEAT_MOUSESHAPE
+ mch_set_mouse_shape(last_shape);
+#else
+ gdk_window_set_cursor(gui.drawarea->window, NULL);
+#endif
+ }
+ }
+}
+
+#if defined(FEAT_MOUSESHAPE) || defined(PROTO)
+
+/* Table for shape IDs. Keep in sync with the mshape_names[] table in
+ * misc2.c! */
+static const int mshape_ids[] =
+{
+ GDK_LEFT_PTR, /* arrow */
+ GDK_CURSOR_IS_PIXMAP, /* blank */
+ GDK_XTERM, /* beam */
+ GDK_SB_V_DOUBLE_ARROW, /* updown */
+ GDK_SIZING, /* udsizing */
+ GDK_SB_H_DOUBLE_ARROW, /* leftright */
+ GDK_SIZING, /* lrsizing */
+ GDK_WATCH, /* busy */
+ GDK_X_CURSOR, /* no */
+ GDK_CROSSHAIR, /* crosshair */
+ GDK_HAND1, /* hand1 */
+ GDK_HAND2, /* hand2 */
+ GDK_PENCIL, /* pencil */
+ GDK_QUESTION_ARROW, /* question */
+ GDK_RIGHT_PTR, /* right-arrow */
+ GDK_CENTER_PTR, /* up-arrow */
+ GDK_LEFT_PTR /* last one */
+};
+
+ void
+mch_set_mouse_shape(int shape)
+{
+ int id;
+ GdkCursor *c;
+
+ if (gui.drawarea->window == NULL)
+ return;
+
+ if (shape == MSHAPE_HIDE || gui.pointer_hidden)
+ gdk_window_set_cursor(gui.drawarea->window, gui.blank_pointer);
+ else
+ {
+ if (shape >= MSHAPE_NUMBERED)
+ {
+ id = shape - MSHAPE_NUMBERED;
+ if (id >= GDK_LAST_CURSOR)
+ id = GDK_LEFT_PTR;
+ else
+ id &= ~1; /* they are always even (why?) */
+ }
+ else
+ id = mshape_ids[shape];
+# ifdef HAVE_GTK_MULTIHEAD
+ c = gdk_cursor_new_for_display(
+ gtk_widget_get_display(gui.drawarea), id);
+# else
+ c = gdk_cursor_new(id);
+# endif
+ gdk_window_set_cursor(gui.drawarea->window, c);
+ gdk_cursor_destroy(c); /* Unref, actually. Bloody GTK+ 1. */
+ }
+ if (shape != MSHAPE_HIDE)
+ last_shape = shape;
+}
+#endif /* FEAT_MOUSESHAPE */
+
+
+#if defined(FEAT_SIGN_ICONS) || defined(PROTO)
+/*
+ * Signs are currently always 2 chars wide. With GTK+ 2, the image will be
+ * scaled down if the current font is not big enough, or scaled up if the image
+ * size is less than 3/4 of the maximum sign size. With GTK+ 1, the pixmap
+ * will be cut off if the current font is not big enough, or centered if it's
+ * too small.
+ */
+# define SIGN_WIDTH (2 * gui.char_width)
+# define SIGN_HEIGHT (gui.char_height)
+# define SIGN_ASPECT ((double)SIGN_HEIGHT / (double)SIGN_WIDTH)
+
+# ifdef HAVE_GTK2
+
+ void
+gui_mch_drawsign(int row, int col, int typenr)
+{
+ GdkPixbuf *sign;
+
+ sign = (GdkPixbuf *)sign_get_image(typenr);
+
+ if (sign != NULL && gui.drawarea != NULL && gui.drawarea->window != NULL)
+ {
+ int width;
+ int height;
+ int xoffset;
+ int yoffset;
+ int need_scale;
+
+ width = gdk_pixbuf_get_width(sign);
+ height = gdk_pixbuf_get_height(sign);
+ /*
+ * Decide whether we need to scale. Allow one pixel of border
+ * width to be cut off, in order to avoid excessive scaling for
+ * tiny differences in font size.
+ */
+ need_scale = (width > SIGN_WIDTH + 2
+ || height > SIGN_HEIGHT + 2
+ || (width < 3 * SIGN_WIDTH / 4
+ && height < 3 * SIGN_HEIGHT / 4));
+ if (need_scale)
+ {
+ double aspect;
+
+ /* Keep the original aspect ratio */
+ aspect = (double)height / (double)width;
+ width = (double)SIGN_WIDTH * SIGN_ASPECT / aspect;
+ width = MIN(width, SIGN_WIDTH);
+ height = (double)width * aspect;
+
+ /* This doesn't seem to be worth caching, and doing so
+ * would complicate the code quite a bit. */
+ sign = gdk_pixbuf_scale_simple(sign, width, height,
+ GDK_INTERP_BILINEAR);
+ if (sign == NULL)
+ return; /* out of memory */
+ }
+
+ /* The origin is the upper-left corner of the pixmap. Therefore
+ * these offset may become negative if the pixmap is smaller than
+ * the 2x1 cells reserved for the sign icon. */
+ xoffset = (width - SIGN_WIDTH) / 2;
+ yoffset = (height - SIGN_HEIGHT) / 2;
+
+ gdk_gc_set_foreground(gui.text_gc, gui.bgcolor);
+
+ gdk_draw_rectangle(gui.drawarea->window,
+ gui.text_gc,
+ TRUE,
+ FILL_X(col),
+ FILL_Y(row),
+ SIGN_WIDTH,
+ SIGN_HEIGHT);
+
+# if GTK_CHECK_VERSION(2,1,1)
+ gdk_draw_pixbuf(gui.drawarea->window,
+ NULL,
+ sign,
+ MAX(0, xoffset),
+ MAX(0, yoffset),
+ FILL_X(col) - MIN(0, xoffset),
+ FILL_Y(row) - MIN(0, yoffset),
+ MIN(width, SIGN_WIDTH),
+ MIN(height, SIGN_HEIGHT),
+ GDK_RGB_DITHER_NORMAL,
+ 0, 0);
+# else
+ gdk_pixbuf_render_to_drawable_alpha(sign,
+ gui.drawarea->window,
+ MAX(0, xoffset),
+ MAX(0, yoffset),
+ FILL_X(col) - MIN(0, xoffset),
+ FILL_Y(row) - MIN(0, yoffset),
+ MIN(width, SIGN_WIDTH),
+ MIN(height, SIGN_HEIGHT),
+ GDK_PIXBUF_ALPHA_BILEVEL,
+ 127,
+ GDK_RGB_DITHER_NORMAL,
+ 0, 0);
+# endif
+ if (need_scale)
+ g_object_unref(sign);
+ }
+}
+
+ void *
+gui_mch_register_sign(char_u *signfile)
+{
+ if (signfile[0] != NUL && signfile[0] != '-' && gui.in_use)
+ {
+ GdkPixbuf *sign;
+ GError *error = NULL;
+ char_u *message;
+
+ sign = gdk_pixbuf_new_from_file((const char *)signfile, &error);
+
+ if (error == NULL)
+ return sign;
+
+ message = (char_u *)error->message;
+
+ if (message != NULL && input_conv.vc_type != CONV_NONE)
+ message = string_convert(&input_conv, message, NULL);
+
+ if (message != NULL)
+ {
+ /* The error message is already translated and will be more
+ * descriptive than anything we could possibly do ourselves. */
+ EMSG2("E255: %s", message);
+
+ if (input_conv.vc_type != CONV_NONE)
+ vim_free(message);
+ }
+ g_error_free(error);
+ }
+
+ return NULL;
+}
+
+ void
+gui_mch_destroy_sign(void *sign)
+{
+ if (sign != NULL)
+ g_object_unref(sign);
+}
+
+# else /* !HAVE_GTK2 */
+
+typedef struct
+{
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+}
+signicon_T;
+
+ void
+gui_mch_drawsign(int row, int col, int typenr)
+{
+ signicon_T *sign;
+
+ sign = (signicon_T *)sign_get_image(typenr);
+
+ if (sign != NULL && sign->pixmap != NULL
+ && gui.drawarea != NULL && gui.drawarea->window != NULL)
+ {
+ int width;
+ int height;
+ int xoffset;
+ int yoffset;
+
+ gdk_window_get_size(sign->pixmap, &width, &height);
+
+ /* The origin is the upper-left corner of the pixmap. Therefore
+ * these offset may become negative if the pixmap is smaller than
+ * the 2x1 cells reserved for the sign icon. */
+ xoffset = (width - SIGN_WIDTH) / 2;
+ yoffset = (height - SIGN_HEIGHT) / 2;
+
+ gdk_gc_set_foreground(gui.text_gc, gui.bgcolor);
+
+ gdk_draw_rectangle(gui.drawarea->window,
+ gui.text_gc,
+ TRUE,
+ FILL_X(col),
+ FILL_Y(row),
+ SIGN_WIDTH,
+ SIGN_HEIGHT);
+
+ /* Set the clip mask for bilevel transparency */
+ if (sign->mask != NULL)
+ {
+ gdk_gc_set_clip_origin(gui.text_gc,
+ FILL_X(col) - xoffset,
+ FILL_Y(row) - yoffset);
+ gdk_gc_set_clip_mask(gui.text_gc, sign->mask);
+ }
+
+ gdk_draw_pixmap(gui.drawarea->window,
+ gui.text_gc,
+ sign->pixmap,
+ MAX(0, xoffset),
+ MAX(0, yoffset),
+ FILL_X(col) - MIN(0, xoffset),
+ FILL_Y(row) - MIN(0, yoffset),
+ MIN(width, SIGN_WIDTH),
+ MIN(height, SIGN_HEIGHT));
+
+ gdk_gc_set_clip_mask(gui.text_gc, NULL);
+ }
+}
+
+ void *
+gui_mch_register_sign(char_u *signfile)
+{
+ signicon_T *sign = NULL;
+
+ if (signfile[0] != NUL && signfile[0] != '-'
+ && gui.drawarea != NULL && gui.drawarea->window != NULL)
+ {
+ sign = (signicon_T *)alloc(sizeof(signicon_T));
+
+ if (sign != NULL) /* NULL == OOM == "cannot really happen" */
+ {
+ sign->mask = NULL;
+ sign->pixmap = gdk_pixmap_colormap_create_from_xpm(
+ gui.drawarea->window, NULL,
+ &sign->mask, NULL,
+ (const char *)signfile);
+
+ if (sign->pixmap == NULL)
+ {
+ vim_free(sign);
+ sign = NULL;
+ EMSG(_(e_signdata));
+ }
+ }
+ }
+ return sign;
+}
+
+ void
+gui_mch_destroy_sign(void *sign)
+{
+ if (sign != NULL)
+ {
+ signicon_T *signicon = (signicon_T *)sign;
+
+ if (signicon->pixmap != NULL)
+ gdk_pixmap_unref(signicon->pixmap);
+ if (signicon->mask != NULL)
+ gdk_bitmap_unref(signicon->mask);
+
+ vim_free(signicon);
+ }
+}
+# endif /* !HAVE_GTK2 */
+
+#endif /* FEAT_SIGN_ICONS */
+
diff --git a/src/gui_mac.c b/src/gui_mac.c
new file mode 100644
index 000000000..2b74c6328
--- /dev/null
+++ b/src/gui_mac.c
@@ -0,0 +1,5820 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI/Motif support by Robert Webb
+ * Macintosh port by Dany St-Amant
+ * and Axel Kielhorn
+ * Port to MPW by Bernhard PrŸmmer
+ * Initial Carbon port by Ammon Skidmore
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * NOTE: Comment mentionning FAQ refer to the book:
+ * "Macworld Mac Programming FAQs" from "IDG Books"
+ */
+
+/*
+ * WARNING: Vim must be able to compile without Carbon
+ * As the desired minimum requirement are circa System 7
+ * (I want to run it on my Mac Classic) (Dany)
+ */
+
+/*
+ * TODO: Change still to merge from the macvim's iDisk
+ *
+ * error_ga, mch_errmsg, Navigation's changes in gui_mch_browse
+ * uses of MenuItemIndex, changes in gui_mch_set_shellsize,
+ * ScrapManager error handling.
+ * Comments about function remaining to Carbonize.
+ *
+ */
+
+/* TODO: find the best place for this (Dany) */
+#if 0
+# if ! TARGET_API_MAC_CARBON
+/* Enable the new API functions even when not compiling for Carbon */
+/* Apple recomends Universal Interface 3.3.2 or later */
+# define OPAQUE_TOOLBOX_STRUCTS 1
+# define ACCESSOR_CALLS_ARE_FUNCTIONS 1
+/* Help Menu not supported by Carbon */
+# define USE_HELPMENU
+# endif
+#endif
+
+#include <Devices.h> /* included first to avoid CR problems */
+#include "vim.h"
+
+/* Enable Contextual Menu Support */
+#if UNIVERSAL_INTERFACES_VERSION >= 0x0320
+# define USE_CTRLCLICKMENU
+#endif
+
+/* Put Vim Help in MacOS Help */
+#define USE_HELPMENU
+
+/* Enable AEVENT */
+#define USE_AEVENT
+
+/* Compile as CodeWarior External Editor */
+#if defined(FEAT_CW_EDITOR) && !defined(USE_AEVENT)
+# define USE_AEVENT /* Need Apple Event Support */
+#endif
+
+/* The VIM creator is CodeWarior specific */
+#if !(defined(__MRC__) || defined(__SC__) || defined(__APPLE_CC__))
+# define USE_VIM_CREATOR_ID
+#else
+# if 0 /* Was this usefull for some compiler? (Dany) */
+static OSType _fcreator = 'VIM!';
+static OSType _ftype = 'TEXT';
+# endif
+#endif
+
+/* CARBON version only tested with Project Builder under MacOS X */
+#undef USE_CARBONIZED
+#if (defined(__APPLE_CC__) || defined(__MRC__)) && defined(TARGET_API_MAC_CARBON)
+# if TARGET_API_MAC_CARBON
+# define USE_CARBONIZED
+# endif
+#endif
+
+#undef USE_MOUSEWHEEL
+#if defined(MACOS_X) && defined(USE_CARBONIZED)
+# define USE_MOUSEWHEEL
+static EventHandlerUPP mouseWheelHandlerUPP = NULL;
+#endif
+
+/* Debugging feature: start Vim window OFFSETed */
+#undef USE_OFFSETED_WINDOW
+
+/* Debugging feature: use CodeWarior SIOUX */
+#undef USE_SIOUX
+
+
+/* Include some file. TODO: move into os_mac.h */
+#include <Menus.h>
+#include <Resources.h>
+#if !TARGET_API_MAC_CARBON
+#include <StandardFile.h>
+#include <Traps.h>
+#endif
+#include <Balloons.h>
+#include <Processes.h>
+#ifdef USE_AEVENT
+# include <AppleEvents.h>
+# include <AERegistry.h>
+#endif
+#ifdef USE_CTRLCLICKMENU
+# include <Gestalt.h>
+#endif
+#ifdef USE_SIOUX
+# include <stdio.h>
+# include <sioux.h>
+# include <console.h>
+#endif
+#if UNIVERSAL_INTERFACES_VERSION >= 0x0330
+# include <ControlDefinitions.h>
+# include <Navigation.h> /* Navigation only part of ?? */
+#endif
+
+#if TARGET_API_MAC_CARBON && 0
+/* New Help Interface for Mac, not implemented yet.*/
+# include <MacHelp.h>
+#endif
+
+/*
+ * Translate new name to old ones
+ * New function only available in MacOS 8.5,
+ * So use old one to be compatible back to System 7
+ */
+#ifndef USE_CARBONIZED
+# undef EnableMenuItem
+# define EnableMenuItem EnableItem
+# undef DisableMenuItem
+# define DisableMenuItem DisableItem
+#endif
+
+/* Carbon does not support the Get/SetControll functions,
+ * use Get/SetControl32Bit instead and rename for non-carbon
+ * systems.
+ */
+
+#ifndef USE_CARBONIZED
+# undef SetControl32BitMaximum
+# define SetControl32BitMaximum SetControlMaximum
+# undef SetControl32BitMinimum
+# define SetControl32BitMinimum SetControlMinimum
+# undef SetControl32BitValue
+# define SetControl32BitValue SetControlValue
+# undef GetControl32BitValue
+# define GetControl32BitValue GetControlValue
+#endif
+
+/*
+ * ???
+ */
+
+#define kNothing 0
+#define kCreateEmpty 2 /*1*/
+#define kCreateRect 2
+#define kDestroy 3
+
+/*
+ * Dany: Don't like those...
+ */
+
+#define topLeft(r) (((Point*)&(r))[0])
+#define botRight(r) (((Point*)&(r))[1])
+
+
+/* Time of last mouse click, to detect double-click */
+static long lastMouseTick = 0;
+
+/* ??? */
+static RgnHandle cursorRgn;
+static RgnHandle dragRgn;
+static Rect dragRect;
+static short dragRectEnbl;
+static short dragRectControl;
+
+/* This variable is set when waiting for an event, which is the only moment
+ * scrollbar dragging can be done directly. It's not allowed while commands
+ * are executed, because it may move the cursor and that may cause unexpected
+ * problems (e.g., while ":s" is working).
+ */
+static int allow_scrollbar = FALSE;
+
+/* Last mouse click caused contextual menu, (to provide proper release) */
+#ifdef USE_CTRLCLICKMENU
+static short clickIsPopup;
+#endif
+
+/* Feedback Action for Scrollbar */
+ControlActionUPP gScrollAction;
+ControlActionUPP gScrollDrag;
+
+/* Keeping track of which scrollbar is being dragged */
+static ControlHandle dragged_sb = NULL;
+
+/*
+ * The Quickdraw global is predefined in CodeWarior
+ * but is not in Apple MPW
+ */
+#if (defined(__MRC__) || defined(__SC__))
+# if !(defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON)
+QDGlobals qd;
+# endif
+#endif
+
+/* Colors Macros */
+#define RGB(r,g,b) ((r) << 16) + ((g) << 8) + (b)
+#define Red(c) ((c & 0x00FF0000) >> 16)
+#define Green(c) ((c & 0x0000FF00) >> 8)
+#define Blue(c) ((c & 0x000000FF) >> 0)
+
+/* Key mapping */
+
+#define vk_Esc 0x35 /* -> 1B */
+
+#define vk_F1 0x7A /* -> 10 */
+#define vk_F2 0x78 /*0x63*/
+#define vk_F3 0x63 /*0x76*/
+#define vk_F4 0x76 /*0x60*/
+#define vk_F5 0x60 /*0x61*/
+#define vk_F6 0x61 /*0x62*/
+#define vk_F7 0x62 /*0x63*/ /*?*/
+#define vk_F8 0x64
+#define vk_F9 0x65
+#define vk_F10 0x6D
+#define vk_F11 0x67
+#define vk_F12 0x6F
+#define vk_F13 0x69
+#define vk_F14 0x6B
+#define vk_F15 0x71
+
+#define vk_Clr 0x47 /* -> 1B (ESC) */
+#define vk_Enter 0x4C /* -> 03 */
+
+#define vk_Space 0x31 /* -> 20 */
+#define vk_Tab 0x30 /* -> 09 */
+#define vk_Return 0x24 /* -> 0D */
+/* This is wrong for OSX, what is it for? */
+#define vk_Delete 0X08 /* -> 08 BackSpace */
+
+#define vk_Help 0x72 /* -> 05 */
+#define vk_Home 0x73 /* -> 01 */
+#define vk_PageUp 0x74 /* -> 0D */
+#define vk_FwdDelete 0x75 /* -> 7F */
+#define vk_End 0x77 /* -> 04 */
+#define vk_PageDown 0x79 /* -> 0C */
+
+#define vk_Up 0x7E /* -> 1E */
+#define vk_Down 0x7D /* -> 1F */
+#define vk_Left 0x7B /* -> 1C */
+#define vk_Right 0x7C /* -> 1D */
+
+#define vk_Undo vk_F1
+#define vk_Cut vk_F2
+#define vk_Copy vk_F3
+#define vk_Paste vk_F4
+#define vk_PrintScreen vk_F13
+#define vk_SCrollLock vk_F14
+#define vk_Pause vk_F15
+#define vk_NumLock vk_Clr
+#define vk_Insert vk_Help
+
+#define KeySym char
+
+static struct
+{
+ KeySym key_sym;
+ char_u vim_code0;
+ char_u vim_code1;
+} special_keys[] =
+{
+ {vk_Up, 'k', 'u'},
+ {vk_Down, 'k', 'd'},
+ {vk_Left, 'k', 'l'},
+ {vk_Right, 'k', 'r'},
+
+ {vk_F1, 'k', '1'},
+ {vk_F2, 'k', '2'},
+ {vk_F3, 'k', '3'},
+ {vk_F4, 'k', '4'},
+ {vk_F5, 'k', '5'},
+ {vk_F6, 'k', '6'},
+ {vk_F7, 'k', '7'},
+ {vk_F8, 'k', '8'},
+ {vk_F9, 'k', '9'},
+ {vk_F10, 'k', ';'},
+
+ {vk_F11, 'F', '1'},
+ {vk_F12, 'F', '2'},
+ {vk_F13, 'F', '3'},
+ {vk_F14, 'F', '4'},
+ {vk_F15, 'F', '5'},
+
+/* {XK_Help, '%', '1'}, */
+/* {XK_Undo, '&', '8'}, */
+/* {XK_BackSpace, 'k', 'b'}, */
+#ifndef MACOS_X
+ {vk_Delete, 'k', 'b'},
+#endif
+ {vk_Insert, 'k', 'I'},
+ {vk_FwdDelete, 'k', 'D'},
+ {vk_Home, 'k', 'h'},
+ {vk_End, '@', '7'},
+/* {XK_Prior, 'k', 'P'}, */
+/* {XK_Next, 'k', 'N'}, */
+/* {XK_Print, '%', '9'}, */
+
+ {vk_PageUp, 'k', 'P'},
+ {vk_PageDown, 'k', 'N'},
+
+ /* End of list marker: */
+ {(KeySym)0, 0, 0}
+};
+
+/*
+ * ------------------------------------------------------------
+ * Forward declaration (for those needed)
+ * ------------------------------------------------------------
+ */
+
+#ifdef USE_AEVENT
+OSErr HandleUnusedParms (const AppleEvent *theAEvent);
+#endif
+
+/*
+ * ------------------------------------------------------------
+ * Conversion Utility
+ * ------------------------------------------------------------
+ */
+
+/*
+ * C2Pascal_save
+ *
+ * Allocate memory and convert the C-String passed in
+ * into a pascal string
+ *
+ */
+
+char_u *C2Pascal_save(char_u *Cstring)
+{
+ char_u *PascalString;
+ int len;
+
+ if (Cstring == NULL)
+ return NULL;
+
+ len = STRLEN(Cstring);
+
+ if (len > 255) /* Truncate if necessary */
+ len = 255;
+
+ PascalString = alloc(len + 1);
+ if (PascalString != NULL)
+ {
+ mch_memmove(PascalString + 1, Cstring, len);
+ PascalString[0] = len;
+ }
+
+ return PascalString;
+}
+
+/*
+ * C2Pascal_save_and_remove_backslash
+ *
+ * Allocate memory and convert the C-String passed in
+ * into a pascal string. Also remove the backslash at the same time
+ *
+ */
+
+char_u *C2Pascal_save_and_remove_backslash(char_u *Cstring)
+{
+ char_u *PascalString;
+ int len;
+ char_u *p, *c;
+
+ len = STRLEN(Cstring);
+
+ if (len > 255) /* Truncate if necessary */
+ len = 255;
+
+ PascalString = alloc(len + 1);
+ if (PascalString != NULL)
+ {
+ for (c = Cstring, p = PascalString+1, len = 0; (*c != 0) && (len < 255); c++)
+ {
+ if ((*c == '\\') && (c[1] != 0))
+ {
+ c++;
+ }
+ *p = *c;
+ p++;
+ len++;
+ }
+ PascalString[0] = len;
+ }
+
+ return PascalString;
+}
+
+/*
+ * Convert the modifiers of an Event into vim's modifiers (mouse)
+ */
+
+ int_u
+EventModifiers2VimMouseModifiers(EventModifiers macModifiers)
+{
+ int_u vimModifiers = 0x00;
+
+ if (macModifiers & (shiftKey | rightShiftKey))
+ vimModifiers |= MOUSE_SHIFT;
+ if (macModifiers & (controlKey | rightControlKey))
+ vimModifiers |= MOUSE_CTRL;
+ if (macModifiers & (optionKey | rightOptionKey))
+ vimModifiers |= MOUSE_ALT;
+#if 0
+ /* Not yet supported */
+ if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
+ vimModifiers |= MOUSE_CMD;
+#endif
+ return (vimModifiers);
+}
+
+/*
+ * Convert the modifiers of an Event into vim's modifiers (keys)
+ */
+
+ static int_u
+EventModifiers2VimModifiers(EventModifiers macModifiers)
+{
+ int_u vimModifiers = 0x00;
+
+ if (macModifiers & (shiftKey | rightShiftKey))
+ vimModifiers |= MOD_MASK_SHIFT;
+ if (macModifiers & (controlKey | rightControlKey))
+ vimModifiers |= MOD_MASK_CTRL;
+ if (macModifiers & (optionKey | rightOptionKey))
+ vimModifiers |= MOD_MASK_ALT;
+#ifdef USE_CMD_KEY
+ if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
+ vimModifiers |= MOD_MASK_CMD;
+#endif
+ return (vimModifiers);
+}
+
+/* Convert a string representing a point size into pixels. The string should
+ * be a positive decimal number, with an optional decimal point (eg, "12", or
+ * "10.5"). The pixel value is returned, and a pointer to the next unconverted
+ * character is stored in *end. The flag "vertical" says whether this
+ * calculation is for a vertical (height) size or a horizontal (width) one.
+ *
+ * From gui_w48.c
+ */
+ static int
+points_to_pixels(char_u *str, char_u **end, int vertical)
+{
+ int pixels;
+ int points = 0;
+ int divisor = 0;
+
+ while (*str)
+ {
+ if (*str == '.' && divisor == 0)
+ {
+ /* Start keeping a divisor, for later */
+ divisor = 1;
+ continue;
+ }
+
+ if (!isdigit(*str))
+ break;
+
+ points *= 10;
+ points += *str - '0';
+ divisor *= 10;
+
+ ++str;
+ }
+
+ if (divisor == 0)
+ divisor = 1;
+
+ pixels = points/divisor;
+ *end = str;
+ return pixels;
+}
+
+/*
+ * Convert a list of FSSpec aliases into a list of fullpathname
+ * character strings.
+ */
+
+char_u **new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error)
+{
+ char_u **fnames = NULL;
+ OSErr newError;
+ long fileCount;
+ FSSpec fileToOpen;
+ long actualSize;
+ AEKeyword dummyKeyword;
+ DescType dummyType;
+
+ /* Get number of files in list */
+ *error = AECountItems(theList, numFiles);
+ if (*error)
+ {
+#ifdef USE_SIOUX
+ printf ("fname_from_AEDesc: AECountItems error: %d\n", error);
+#endif
+ return(fnames);
+ }
+
+ /* Allocate the pointer list */
+ fnames = (char_u **) alloc(*numFiles * sizeof(char_u *));
+
+ /* Empty out the list */
+ for (fileCount = 0; fileCount < *numFiles; fileCount++)
+ fnames[fileCount] = NULL;
+
+ /* Scan the list of FSSpec */
+ for (fileCount = 1; fileCount <= *numFiles; fileCount++)
+ {
+ /* Get the alias for the nth file, convert to an FSSpec */
+ newError = AEGetNthPtr(theList, fileCount, typeFSS,
+ &dummyKeyword, &dummyType,
+ (Ptr) &fileToOpen, sizeof(FSSpec), &actualSize);
+ if (newError)
+ {
+ /* Caller is able to clean up */
+ /* TODO: Should be clean up or not? For safety. */
+#ifdef USE_SIOUX
+ printf ("aevt_odoc: AEGetNthPtr error: %d\n", newError);
+#endif
+ return(fnames);
+ }
+
+ /* Convert the FSSpec to a pathname */
+ fnames[fileCount - 1] = FullPathFromFSSpec_save (fileToOpen);
+ }
+
+ return (fnames);
+}
+
+/*
+ * ------------------------------------------------------------
+ * CodeWarrior External Editor Support
+ * ------------------------------------------------------------
+ */
+#ifdef FEAT_CW_EDITOR
+
+/*
+ * Handle the Window Search event from CodeWarrior
+ *
+ * Description
+ * -----------
+ *
+ * The IDE sends the Window Search AppleEvent to the editor when it
+ * needs to know whether a particular file is open in the editor.
+ *
+ * Event Reply
+ * -----------
+ *
+ * None. Put data in the location specified in the structure received.
+ *
+ * Remarks
+ * -------
+ *
+ * When the editor receives this event, determine whether the specified
+ * file is open. If it is, return the modification date/time for that file
+ * in the appropriate location specified in the structure. If the file is
+ * not opened, put the value fnfErr (file not found) in that location.
+ *
+ */
+
+#if defined(__MWERKS__) /* only in Codewarrior */
+# pragma options align=mac68k
+#endif
+typedef struct WindowSearch WindowSearch;
+struct WindowSearch /* for handling class 'KAHL', event 'SRCH', keyDirectObject typeChar*/
+{
+ FSSpec theFile; // identifies the file
+ long *theDate; // where to put the modification date/time
+};
+#if defined(__MWERKS__) /* only in Codewarrior */
+# pragma options align=reset
+#endif
+
+pascal OSErr Handle_KAHL_SRCH_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
+{
+ OSErr error = noErr;
+ buf_T *buf;
+ int foundFile = false;
+ DescType typeCode;
+ WindowSearch SearchData;
+ Size actualSize;
+
+ error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &SearchData, sizeof(WindowSearch), &actualSize);
+ if (error)
+ {
+#ifdef USE_SIOUX
+ printf ("KAHL_SRCH: AEGetParamPtr error: %d\n", error);
+#endif
+ return(error);
+ }
+
+ error = HandleUnusedParms (theAEvent);
+ if (error)
+ {
+#ifdef USE_SIOUX
+ printf ("KAHL_SRCH: HandleUnusedParms error: %d\n", error);
+#endif
+ return(error);
+ }
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (buf->b_ml.ml_mfp != NULL
+ && SearchData.theFile.parID == buf->b_FSSpec.parID
+ && SearchData.theFile.name[0] == buf->b_FSSpec.name[0]
+ && STRNCMP(SearchData.theFile.name, buf->b_FSSpec.name, buf->b_FSSpec.name[0] + 1) == 0)
+ {
+ foundFile = true;
+ break;
+ }
+
+ if (foundFile == false)
+ *SearchData.theDate = fnfErr;
+ else
+ *SearchData.theDate = buf->b_mtime;
+
+#ifdef USE_SIOUX
+ printf ("KAHL_SRCH: file \"%#s\" {%d}", SearchData.theFile.name,SearchData.theFile.parID);
+ if (foundFile == false)
+ printf (" NOT");
+ printf (" found. [date %lx, %lx]\n", *SearchData.theDate, buf->b_mtime_read);
+#endif
+
+ return error;
+};
+
+/*
+ * Handle the Modified (from IDE to Editor) event from CodeWarrior
+ *
+ * Description
+ * -----------
+ *
+ * The IDE sends this event to the external editor when it wants to
+ * know which files that are open in the editor have been modified.
+ *
+ * Parameters None.
+ * ----------
+ *
+ * Event Reply
+ * -----------
+ * The reply for this event is:
+ *
+ * keyDirectObject typeAEList required
+ * each element in the list is a structure of typeChar
+ *
+ * Remarks
+ * -------
+ *
+ * When building the reply event, include one element in the list for
+ * each open file that has been modified.
+ *
+ */
+
+#if defined(__MWERKS__) /* only in Codewarrior */
+# pragma options align=mac68k
+#endif
+typedef struct ModificationInfo ModificationInfo;
+struct ModificationInfo /* for replying to class 'KAHL', event 'MOD ', keyDirectObject typeAEList*/
+{
+ FSSpec theFile; // identifies the file
+ long theDate; // the date/time the file was last modified
+ short saved; // set this to zero when replying, unused
+};
+#if defined(__MWERKS__) /* only in Codewarrior */
+# pragma options align=reset
+#endif
+
+pascal OSErr Handle_KAHL_MOD_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
+{
+ OSErr error = noErr;
+ AEDescList replyList;
+ long numFiles;
+ ModificationInfo theFile;
+ buf_T *buf;
+
+ theFile.saved = 0;
+
+ error = HandleUnusedParms (theAEvent);
+ if (error)
+ {
+#ifdef USE_SIOUX
+ printf ("KAHL_MOD: HandleUnusedParms error: %d\n", error);
+#endif
+ return(error);
+ }
+
+ /* Send the reply */
+/* replyObject.descriptorType = typeNull;
+ replyObject.dataHandle = nil;*/
+
+/* AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data) */
+ error = AECreateList(nil, 0, false, &replyList);
+ if (error)
+ {
+#ifdef USE_SIOUX
+ printf ("KAHL_MOD: AECreateList error: %d\n", error);
+#endif
+ return(error);
+ }
+
+#if 0
+ error = AECountItems(&replyList, &numFiles);
+#ifdef USE_SIOUX
+ printf ("KAHL_MOD ReplyList: %x %x\n", replyList.descriptorType, replyList.dataHandle);
+ printf ("KAHL_MOD ItemInList: %d\n", numFiles);
+#endif
+
+ /* AEPutKeyDesc (&replyList, keyAEPnject, &aDesc)
+ * AEPutKeyPtr (&replyList, keyAEPosition, typeChar, (Ptr)&theType,
+ * sizeof(DescType))
+ */
+
+ /* AEPutDesc */
+#endif
+
+ numFiles = 0;
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (buf->b_ml.ml_mfp != NULL)
+ {
+ /* Add this file to the list */
+ theFile.theFile = buf->b_FSSpec;
+ theFile.theDate = buf->b_mtime;
+/* theFile.theDate = time (NULL) & (time_t) 0xFFFFFFF0; */
+ error = AEPutPtr (&replyList, numFiles, typeChar, (Ptr) &theFile, sizeof(theFile));
+#ifdef USE_SIOUX
+ if (numFiles == 0)
+ printf ("KAHL_MOD: ");
+ else
+ printf (", ");
+ printf ("\"%#s\" {%d} [date %lx, %lx]", theFile.theFile.name, theFile.theFile.parID, theFile.theDate, buf->b_mtime_read);
+ if (error)
+ printf (" (%d)", error);
+ numFiles++;
+#endif
+ };
+
+#ifdef USE_SIOUX
+ printf ("\n");
+#endif
+
+#if 0
+ error = AECountItems(&replyList, &numFiles);
+#ifdef USE_SIOUX
+ printf ("KAHL_MOD ItemInList: %d\n", numFiles);
+#endif
+#endif
+
+ /* We can add data only if something to reply */
+ error = AEPutParamDesc (theReply, keyDirectObject, &replyList);
+
+#ifdef USE_SIOUX
+ if (error)
+ printf ("KAHL_MOD: AEPutParamDesc error: %d\n", error);
+#endif
+
+ if (replyList.dataHandle)
+ AEDisposeDesc(&replyList);
+
+ return error;
+};
+
+/*
+ * Handle the Get Text event from CodeWarrior
+ *
+ * Description
+ * -----------
+ *
+ * The IDE sends the Get Text AppleEvent to the editor when it needs
+ * the source code from a file. For example, when the user issues a
+ * Check Syntax or Compile command, the compiler needs access to
+ * the source code contained in the file.
+ *
+ * Event Reply
+ * -----------
+ *
+ * None. Put data in locations specified in the structure received.
+ *
+ * Remarks
+ * -------
+ *
+ * When the editor receives this event, it must set the size of the handle
+ * in theText to fit the data in the file. It must then copy the entire
+ * contents of the specified file into the memory location specified in
+ * theText.
+ *
+ */
+
+#if defined(__MWERKS__) /* only in Codewarrior */
+# pragma options align=mac68k
+#endif
+typedef struct CW_GetText CW_GetText;
+struct CW_GetText /* for handling class 'KAHL', event 'GTTX', keyDirectObject typeChar*/
+{
+ FSSpec theFile; /* identifies the file */
+ Handle theText; /* the location where you return the text (must be resized properly) */
+ long *unused; /* 0 (not used) */
+ long *theDate; /* where to put the modification date/time */
+};
+#if defined(__MWERKS__) /* only in Codewarrior */
+# pragma options align=reset
+#endif
+
+pascal OSErr Handle_KAHL_GTTX_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
+{
+ OSErr error = noErr;
+ buf_T *buf;
+ int foundFile = false;
+ DescType typeCode;
+ CW_GetText GetTextData;
+ Size actualSize;
+ char_u *line;
+ char_u *fullbuffer = NULL;
+ long linesize;
+ long lineStart;
+ long BufferSize;
+ long lineno;
+
+ error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &GetTextData, sizeof(GetTextData), &actualSize);
+
+ if (error)
+ {
+#ifdef USE_SIOUX
+ printf ("KAHL_GTTX: AEGetParamPtr error: %d\n", error);
+#endif
+ return(error);
+ }
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (buf->b_ml.ml_mfp != NULL)
+ if (GetTextData.theFile.parID == buf->b_FSSpec.parID)
+ {
+ foundFile = true;
+ break;
+ }
+
+ if (foundFile)
+ {
+ BufferSize = 0; /* GetHandleSize (GetTextData.theText); */
+ for (lineno = 0; lineno <= buf->b_ml.ml_line_count; lineno++)
+ {
+ /* Must use the right buffer */
+ line = ml_get_buf(buf, (linenr_T) lineno, FALSE);
+ linesize = STRLEN(line) + 1;
+ lineStart = BufferSize;
+ BufferSize += linesize;
+ /* Resize handle to linesize+1 to include the linefeed */
+ SetHandleSize (GetTextData.theText, BufferSize);
+ if (GetHandleSize (GetTextData.theText) != BufferSize)
+ {
+ #ifdef USE_SIOUX
+ printf ("KAHL_GTTX: SetHandleSize increase: %d, size %d\n",
+ linesize, BufferSize);
+ #endif
+ break; /* Simple handling for now */
+ }
+ else
+ {
+ HLock (GetTextData.theText);
+ fullbuffer = (char_u *) *GetTextData.theText;
+ STRCPY ((char_u *) (fullbuffer + lineStart), line);
+ fullbuffer[BufferSize-1] = '\r';
+ HUnlock (GetTextData.theText);
+ }
+ }
+ if (fullbuffer != NULL)
+ {
+ HLock (GetTextData.theText);
+ fullbuffer[BufferSize-1] = 0;
+ HUnlock (GetTextData.theText);
+ }
+ if (foundFile == false)
+ *GetTextData.theDate = fnfErr;
+ else
+/* *GetTextData.theDate = time (NULL) & (time_t) 0xFFFFFFF0;*/
+ *GetTextData.theDate = buf->b_mtime;
+ }
+#ifdef USE_SIOUX
+ printf ("KAHL_GTTX: file \"%#s\" {%d} [date %lx, %lx]", GetTextData.theFile.name, GetTextData.theFile.parID, *GetTextData.theDate, buf->b_mtime_read);
+ if (foundFile == false)
+ printf (" NOT");
+ printf (" found. (BufferSize = %d)\n", BufferSize);
+#endif
+
+ error = HandleUnusedParms (theAEvent);
+ if (error)
+ {
+#ifdef USE_SIOUX
+ printf ("KAHL_GTTX: HandleUnusedParms error: %d\n", error);
+#endif
+ return(error);
+ }
+
+ return(error);
+}
+
+/*
+ *
+ */
+
+/* Taken from MoreAppleEvents:ProcessHelpers*/
+pascal OSErr FindProcessBySignature( const OSType targetType,
+ const OSType targetCreator,
+ ProcessSerialNumberPtr psnPtr )
+{
+ OSErr anErr = noErr;
+ Boolean lookingForProcess = true;
+
+ ProcessInfoRec infoRec;
+
+ infoRec.processInfoLength = sizeof( ProcessInfoRec );
+ infoRec.processName = nil;
+ infoRec.processAppSpec = nil;
+
+ psnPtr->lowLongOfPSN = kNoProcess;
+ psnPtr->highLongOfPSN = kNoProcess;
+
+ while ( lookingForProcess )
+ {
+ anErr = GetNextProcess( psnPtr );
+ if ( anErr != noErr )
+ {
+ lookingForProcess = false;
+ }
+ else
+ {
+ anErr = GetProcessInformation( psnPtr, &infoRec );
+ if ( ( anErr == noErr )
+ && ( infoRec.processType == targetType )
+ && ( infoRec.processSignature == targetCreator ) )
+ {
+ lookingForProcess = false;
+ }
+ }
+ }
+
+ return anErr;
+}//end FindProcessBySignature
+
+void Send_KAHL_MOD_AE (buf_T *buf)
+{
+ OSErr anErr = noErr;
+ AEDesc targetAppDesc = { typeNull, nil };
+ ProcessSerialNumber psn = { kNoProcess, kNoProcess };
+ AppleEvent theReply = { typeNull, nil };
+ AESendMode sendMode;
+ AppleEvent theEvent = {typeNull, nil };
+ AEIdleUPP idleProcUPP = nil;
+ ModificationInfo ModData;
+
+
+ anErr = FindProcessBySignature( 'APPL', 'CWIE', &psn );
+#ifdef USE_SIOUX
+ printf ("CodeWarrior is");
+ if (anErr != noErr)
+ printf (" NOT");
+ printf (" running\n");
+#endif
+ if ( anErr == noErr )
+ {
+ anErr = AECreateDesc (typeProcessSerialNumber, &psn,
+ sizeof( ProcessSerialNumber ), &targetAppDesc);
+
+ if ( anErr == noErr )
+ {
+ anErr = AECreateAppleEvent( 'KAHL', 'MOD ', &targetAppDesc,
+ kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
+ }
+
+ AEDisposeDesc( &targetAppDesc );
+
+ /* Add the parms */
+ ModData.theFile = buf->b_FSSpec;
+ ModData.theDate = buf->b_mtime;
+
+ if (anErr == noErr)
+ anErr =AEPutParamPtr (&theEvent, keyDirectObject, typeChar, &ModData, sizeof(ModData));
+
+ if ( idleProcUPP == nil )
+ sendMode = kAENoReply;
+ else
+ sendMode = kAEWaitReply;
+
+ if ( anErr == noErr )
+ anErr = AESend( &theEvent, &theReply, sendMode, kAENormalPriority, kNoTimeOut, idleProcUPP, nil );
+ if ( anErr == noErr && sendMode == kAEWaitReply )
+ {
+#ifdef USE_SIOUX
+ printf ("KAHL_MOD: Send error: %d\n", anErr);
+#endif
+/* anErr = AEHGetHandlerError( &theReply );*/
+ }
+ (void) AEDisposeDesc( &theReply );
+ }
+}
+#endif /* FEAT_CW_EDITOR */
+
+/*
+ * ------------------------------------------------------------
+ * Apple Event Handling procedure
+ * ------------------------------------------------------------
+ */
+#ifdef USE_AEVENT
+
+/*
+ * Handle the Unused parms of an AppleEvent
+ */
+
+OSErr HandleUnusedParms (const AppleEvent *theAEvent)
+{
+ OSErr error;
+ long actualSize;
+ DescType dummyType;
+ AEKeyword missedKeyword;
+
+ /* Get the "missed keyword" attribute from the AppleEvent. */
+ error = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
+ typeKeyword, &dummyType,
+ (Ptr)&missedKeyword, sizeof(missedKeyword),
+ &actualSize);
+
+ /* If the descriptor isn't found, then we got the required parameters. */
+ if (error == errAEDescNotFound)
+ {
+ error = noErr;
+ }
+ else
+ {
+#if 0
+ /* Why is this removed? */
+ error = errAEEventNotHandled;
+#endif
+ }
+
+ return error;
+}
+
+
+/*
+ * Handle the ODoc AppleEvent
+ *
+ * Deals with all files dragged to the application icon.
+ *
+ */
+
+#if defined(__MWERKS__) /* only in Codewarrior */
+# pragma options align=mac68k
+#endif
+typedef struct SelectionRange SelectionRange;
+struct SelectionRange /* for handling kCoreClassEvent:kOpenDocuments:keyAEPosition typeChar */
+{
+ short unused1; // 0 (not used)
+ short lineNum; // line to select (<0 to specify range)
+ long startRange; // start of selection range (if line < 0)
+ long endRange; // end of selection range (if line < 0)
+ long unused2; // 0 (not used)
+ long theDate; // modification date/time
+};
+#if defined(__MWERKS__) /* only in Codewarrior */
+# pragma options align=reset
+#endif
+
+/* The IDE uses the optional keyAEPosition parameter to tell the ed-
+ itor the selection range. If lineNum is zero or greater, scroll the text
+ to the specified line. If lineNum is less than zero, use the values in
+ startRange and endRange to select the specified characters. Scroll
+ the text to display the selection. If lineNum, startRange, and
+ endRange are all negative, there is no selection range specified.
+ */
+
+pascal OSErr HandleODocAE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
+{
+ /*
+ * TODO: Clean up the code with convert the AppleEvent into
+ * a ":args"
+ */
+ OSErr error = noErr;
+// OSErr firstError = noErr;
+// short numErrors = 0;
+ AEDesc theList;
+ DescType typeCode;
+ long numFiles;
+ // long fileCount;
+ char_u **fnames;
+// char_u fname[256];
+ Size actualSize;
+ SelectionRange thePosition;
+ short gotPosition = false;
+ long lnum;
+
+#ifdef USE_SIOUX
+ printf ("aevt_odoc:\n");
+#endif
+
+ /* the direct object parameter is the list of aliases to files (one or more) */
+ error = AEGetParamDesc(theAEvent, keyDirectObject, typeAEList, &theList);
+ if (error)
+ {
+#ifdef USE_SIOUX
+ printf ("aevt_odoc: AEGetParamDesc error: %d\n", error);
+#endif
+ return(error);
+ }
+
+
+ error = AEGetParamPtr(theAEvent, keyAEPosition, typeChar, &typeCode, (Ptr) &thePosition, sizeof(SelectionRange), &actualSize);
+ if (error == noErr)
+ gotPosition = true;
+ if (error == errAEDescNotFound)
+ error = noErr;
+ if (error)
+ {
+#ifdef USE_SIOUX
+ printf ("aevt_odoc: AEGetParamPtr error: %d\n", error);
+#endif
+ return(error);
+ }
+
+#ifdef USE_SIOUX
+ printf ("aevt_odoc: lineNum: %d, startRange %d, endRange %d, [date %lx]\n",
+ thePosition.lineNum, thePosition.startRange, thePosition.endRange,
+ thePosition.theDate);
+#endif
+/*
+ error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition);
+
+ if (^error) then
+ {
+ if (thePosition.lineNum >= 0)
+ {
+ // Goto this line
+ }
+ else
+ {
+ // Set the range char wise
+ }
+ }
+ */
+
+
+#ifdef FEAT_VISUAL
+ reset_VIsual();
+#endif
+
+ fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error);
+
+ if (error)
+ {
+ /* TODO: empty fnames[] first */
+ vim_free(fnames);
+ return (error);
+ }
+
+ if (starting > 0)
+ {
+ int i;
+ char_u *p;
+
+ /* these are the initial files dropped on the Vim icon */
+ for (i = 0 ; i < numFiles; i++)
+ {
+ if (ga_grow(&global_alist.al_ga, 1) == FAIL
+ || (p = vim_strsave(fnames[i])) == NULL)
+ mch_exit(2);
+ else
+ alist_add(&global_alist, p, 2);
+ }
+ goto finished;
+ }
+
+ /* Handle the drop, :edit to get to the file */
+ handle_drop(numFiles, fnames, FALSE);
+
+ /* TODO: Handle the goto/select line more cleanly */
+ if ((numFiles == 1) & (gotPosition))
+ {
+ if (thePosition.lineNum >= 0)
+ {
+ lnum = thePosition.lineNum;
+ /* oap->motion_type = MLINE;
+ setpcmark();*/
+ if (lnum < 1L)
+ lnum = 1L;
+ else if (lnum > curbuf->b_ml.ml_line_count)
+ lnum = curbuf->b_ml.ml_line_count;
+ curwin->w_cursor.lnum = lnum;
+ /* beginline(BL_SOL | BL_FIX);*/
+ }
+ else
+ goto_byte(thePosition.startRange + 1);
+ }
+
+ /* Update the screen display */
+ update_screen(NOT_VALID);
+ setcursor();
+ out_flush();
+
+ finished:
+ AEDisposeDesc(&theList); /* dispose what we allocated */
+
+ error = HandleUnusedParms (theAEvent);
+ if (error)
+ {
+#ifdef USE_SIOUX
+ printf ("aevt_odoc: HandleUnusedParms error: %d\n", error);
+#endif
+ return(error);
+ }
+ return(error);
+}
+
+/*
+ *
+ */
+
+pascal OSErr Handle_aevt_oapp_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
+{
+ OSErr error = noErr;
+
+#ifdef USE_SIOUX
+ printf ("aevt_oapp:\n");
+#endif
+
+ error = HandleUnusedParms (theAEvent);
+ if (error)
+ {
+ return(error);
+ }
+
+ return(error);
+}
+
+/*
+ *
+ */
+
+pascal OSErr Handle_aevt_quit_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
+{
+ OSErr error = noErr;
+
+#ifdef USE_SIOUX
+ printf ("aevt_quit\n");
+#endif
+
+ error = HandleUnusedParms (theAEvent);
+ if (error)
+ {
+ return(error);
+ }
+
+ /* Need to fake a :confirm qa */
+ do_cmdline_cmd((char_u *)"confirm qa");
+
+ return(error);
+}
+
+/*
+ *
+ */
+
+pascal OSErr Handle_aevt_pdoc_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
+{
+ OSErr error = noErr;
+
+#ifdef USE_SIOUX
+ printf ("aevt_pdoc:\n");
+#endif
+
+ error = HandleUnusedParms (theAEvent);
+ if (error)
+ {
+ return(error);
+ }
+
+ return(error);
+}
+
+/*
+ * Handling of unknown AppleEvent
+ *
+ * (Just get rid of all the parms)
+ */
+pascal OSErr Handle_unknown_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
+{
+ OSErr error = noErr;
+
+#ifdef USE_SIOUX
+ printf ("Unknown Event: %x\n", theAEvent->descriptorType);
+#endif
+
+ error = HandleUnusedParms (theAEvent);
+ if (error)
+ {
+ return(error);
+ }
+
+ return(error);
+}
+
+
+
+#if TARGET_API_MAC_CARBON
+# define NewAEEventHandlerProc(x) NewAEEventHandlerUPP(x)
+#endif
+
+/*
+ * Install the various AppleEvent Handlers
+ */
+OSErr InstallAEHandlers (void)
+{
+ OSErr error;
+
+ /* install open application handler */
+ error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
+ NewAEEventHandlerProc(Handle_aevt_oapp_AE), 0, false);
+ if (error)
+ {
+ return error;
+ }
+
+ /* install quit application handler */
+ error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
+ NewAEEventHandlerProc(Handle_aevt_quit_AE), 0, false);
+ if (error)
+ {
+ return error;
+ }
+
+ /* install open document handler */
+ error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
+ NewAEEventHandlerProc(HandleODocAE), 0, false);
+ if (error)
+ {
+ return error;
+ }
+
+ /* install print document handler */
+ error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
+ NewAEEventHandlerProc(Handle_aevt_pdoc_AE), 0, false);
+
+/* Install Core Suite */
+/* error = AEInstallEventHandler(kAECoreSuite, kAEClone,
+ NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
+
+ error = AEInstallEventHandler(kAECoreSuite, kAEClose,
+ NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
+
+ error = AEInstallEventHandler(kAECoreSuite, kAECountElements,
+ NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
+
+ error = AEInstallEventHandler(kAECoreSuite, kAECreateElement,
+ NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
+
+ error = AEInstallEventHandler(kAECoreSuite, kAEDelete,
+ NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
+
+ error = AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist,
+ NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
+
+ error = AEInstallEventHandler(kAECoreSuite, kAEGetData,
+ NewAEEventHandlerProc(Handle_unknown_AE), kAEGetData, false);
+
+ error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize,
+ NewAEEventHandlerProc(Handle_unknown_AE), kAEGetDataSize, false);
+
+ error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo,
+ NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
+
+ error = AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo,
+ NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
+
+ error = AEInstallEventHandler(kAECoreSuite, kAEMove,
+ NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
+
+ error = AEInstallEventHandler(kAECoreSuite, kAESave,
+ NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
+
+ error = AEInstallEventHandler(kAECoreSuite, kAESetData,
+ NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
+*/
+
+#ifdef FEAT_CW_EDITOR
+ /*
+ * Bind codewarrior support handlers
+ */
+ error = AEInstallEventHandler('KAHL', 'GTTX',
+ NewAEEventHandlerProc(Handle_KAHL_GTTX_AE), 0, false);
+ if (error)
+ {
+ return error;
+ }
+ error = AEInstallEventHandler('KAHL', 'SRCH',
+ NewAEEventHandlerProc(Handle_KAHL_SRCH_AE), 0, false);
+ if (error)
+ {
+ return error;
+ }
+ error = AEInstallEventHandler('KAHL', 'MOD ',
+ NewAEEventHandlerProc(Handle_KAHL_MOD_AE), 0, false);
+ if (error)
+ {
+ return error;
+ }
+#endif
+
+ return error;
+
+}
+#endif /* USE_AEVENT */
+
+/*
+ * ------------------------------------------------------------
+ * Unfiled yet
+ * ------------------------------------------------------------
+ */
+
+/*
+ * gui_mac_get_menu_item_index
+ *
+ * Returns the index inside the menu wher
+ */
+ short /* Shoulde we return MenuItemIndex? */
+gui_mac_get_menu_item_index (pMenu)
+ vimmenu_T *pMenu;
+{
+ short index;
+ short itemIndex = -1;
+ vimmenu_T *pBrother;
+
+ /* Only menu without parent are the:
+ * -menu in the menubar
+ * -popup menu
+ * -toolbar (guess)
+ *
+ * Which are not items anyway.
+ */
+ if (pMenu->parent)
+ {
+ /* Start from the Oldest Brother */
+ pBrother = pMenu->parent->children;
+ index = 1;
+ while ((pBrother) && (itemIndex == -1))
+ {
+ if (pBrother == pMenu)
+ itemIndex = index;
+ index++;
+ pBrother = pBrother->next;
+ }
+#ifdef USE_HELPMENU
+ /* Adjust index in help menu (for predefined ones) */
+ if (itemIndex != -1)
+ if (pMenu->parent->submenu_id == kHMHelpMenuID)
+ itemIndex += gui.MacOSHelpItems;
+#endif
+ }
+ return itemIndex;
+}
+
+ static vimmenu_T *
+gui_mac_get_vim_menu (menuID, itemIndex, pMenu)
+ short menuID;
+ short itemIndex;
+ vimmenu_T *pMenu;
+{
+ short index;
+ vimmenu_T *pChildMenu;
+ vimmenu_T *pElder = pMenu->parent;
+
+
+ /* Only menu without parent are the:
+ * -menu in the menubar
+ * -popup menu
+ * -toolbar (guess)
+ *
+ * Which are not items anyway.
+ */
+
+ if ((pElder) && (pElder->submenu_id == menuID))
+ {
+#ifdef USE_HELPMENU
+ if (menuID == kHMHelpMenuID)
+ itemIndex -= gui.MacOSHelpItems;
+#endif
+
+ for (index = 1; (index != itemIndex) && (pMenu != NULL); index++)
+ pMenu = pMenu->next;
+ }
+ else
+ {
+ for (; pMenu != NULL; pMenu = pMenu->next)
+ {
+ if (pMenu->children != NULL)
+ {
+ pChildMenu = gui_mac_get_vim_menu
+ (menuID, itemIndex, pMenu->children);
+ if (pChildMenu)
+ {
+ pMenu = pChildMenu;
+ break;
+ }
+ }
+ }
+ }
+ return pMenu;
+}
+
+/*
+ * ------------------------------------------------------------
+ * MacOS Feedback procedures
+ * ------------------------------------------------------------
+ */
+ pascal
+ void
+gui_mac_drag_thumb (ControlHandle theControl, short partCode)
+{
+ scrollbar_T *sb;
+ int value, dragging;
+ ControlHandle theControlToUse;
+ int dont_scroll_save = dont_scroll;
+
+ theControlToUse = dragged_sb;
+
+ sb = gui_find_scrollbar((long) GetControlReference (theControlToUse));
+
+ if (sb == NULL)
+ return;
+
+ /* Need to find value by diff between Old Poss New Pos */
+ value = GetControl32BitValue (theControlToUse);
+ dragging = (partCode != 0);
+
+ /* When "allow_scrollbar" is FALSE still need to remember the new
+ * position, but don't actually scroll by setting "dont_scroll". */
+ dont_scroll = !allow_scrollbar;
+ gui_drag_scrollbar(sb, value, dragging);
+ dont_scroll = dont_scroll_save;
+}
+
+ pascal
+ void
+gui_mac_scroll_action (ControlHandle theControl, short partCode)
+{
+ /* TODO: have live support */
+ scrollbar_T *sb, *sb_info;
+ long data;
+ long value;
+ int page;
+ int dragging = FALSE;
+ int dont_scroll_save = dont_scroll;
+
+ sb = gui_find_scrollbar((long) GetControlReference (theControl));
+
+ if (sb == NULL)
+ return;
+
+ if (sb->wp != NULL) /* Left or right scrollbar */
+ {
+ /*
+ * Careful: need to get scrollbar info out of first (left) scrollbar
+ * for window, but keep real scrollbar too because we must pass it to
+ * gui_drag_scrollbar().
+ */
+ sb_info = &sb->wp->w_scrollbars[0];
+
+ if (sb_info->size > 5)
+ page = sb_info->size - 2; /* use two lines of context */
+ else
+ page = sb_info->size;
+ }
+ else /* Bottom scrollbar */
+ {
+ sb_info = sb;
+ page = W_WIDTH(curwin) - 5;
+ }
+
+ switch (partCode)
+ {
+ case kControlUpButtonPart: data = -1; break;
+ case kControlDownButtonPart: data = 1; break;
+ case kControlPageDownPart: data = page; break;
+ case kControlPageUpPart: data = -page; break;
+ default: data = 0; break;
+ }
+
+ value = sb_info->value + data;
+/* if (value > sb_info->max)
+ value = sb_info->max;
+ else if (value < 0)
+ value = 0;*/
+
+ /* When "allow_scrollbar" is FALSE still need to remember the new
+ * position, but don't actually scroll by setting "dont_scroll". */
+ dont_scroll = !allow_scrollbar;
+ gui_drag_scrollbar(sb, value, dragging);
+ dont_scroll = dont_scroll_save;
+
+ out_flush();
+ gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
+
+/* if (sb_info->wp != NULL)
+ {
+ win_T *wp;
+ int sb_num;
+
+ sb_num = 0;
+ for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp))
+ sb_num++;
+
+ if (wp != NULL)
+ {
+ current_scrollbar = sb_num;
+ scrollbar_value = value;
+ gui_do_scroll();
+ gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
+ }
+ }*/
+}
+
+/*
+ * ------------------------------------------------------------
+ * MacOS Click Handling procedures
+ * ------------------------------------------------------------
+ */
+
+
+/*
+ * Handle a click inside the window, it may happens in the
+ * scrollbar or the contents.
+ *
+ * TODO: Add support for potential TOOLBAR
+ */
+ void
+gui_mac_doInContentClick (theEvent, whichWindow)
+ EventRecord *theEvent;
+ WindowPtr whichWindow;
+{
+ Point thePoint;
+ int_u vimModifiers;
+ short thePortion;
+ ControlHandle theControl;
+ int vimMouseButton;
+ short dblClick;
+
+ thePoint = theEvent->where;
+ GlobalToLocal (&thePoint);
+ SelectWindow (whichWindow);
+
+ thePortion = FindControl (thePoint, whichWindow, &theControl);
+
+ if (theControl != NUL)
+ {
+ /* We hit a scollbar */
+
+ if (thePortion != kControlIndicatorPart)
+ {
+ dragged_sb = theControl;
+ TrackControl(theControl, thePoint, gScrollAction);
+ dragged_sb = NULL;
+ }
+ else
+ {
+ dragged_sb = theControl;
+#if 1
+ TrackControl(theControl, thePoint, gScrollDrag);
+#else
+ TrackControl(theControl, thePoint, NULL);
+#endif
+ /* pass 0 as the part to tell gui_mac_drag_thumb, that the mouse
+ * button has been released */
+ gui_mac_drag_thumb (theControl, 0); /* Should it be thePortion ? (Dany) */
+ dragged_sb = NULL;
+ }
+ }
+ else
+ {
+ /* We are inside the contents */
+
+ /* Convert the CTRL, OPTION, SHIFT and CMD key */
+ vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
+
+ /* Defaults to MOUSE_LEFT as there's only one mouse button */
+ vimMouseButton = MOUSE_LEFT;
+
+#ifdef USE_CTRLCLICKMENU
+ /* Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT */
+ clickIsPopup = FALSE;
+
+ if ((gui.MacOSHaveCntxMenu) && (mouse_model_popup()))
+ if (IsShowContextualMenuClick(theEvent))
+ {
+ vimMouseButton = MOUSE_RIGHT;
+ vimModifiers &= ~MOUSE_CTRL;
+ clickIsPopup = TRUE;
+ }
+#endif
+
+ /* Is it a double click ? */
+ dblClick = ((theEvent->when - lastMouseTick) < GetDblTime());
+
+ /* Send the mouse clicj to Vim */
+ gui_send_mouse_event(vimMouseButton, thePoint.h,
+ thePoint.v, dblClick, vimModifiers);
+
+ /* Create the rectangle around the cursor to detect
+ * the mouse dragging
+ */
+#ifdef USE_CTRLCLICKMENU
+#if 0
+ /* TODO: Do we need to this even for the contextual menu?
+ * It may be require for popup_setpos, but for popup?
+ */
+ if (vimMouseButton == MOUSE_LEFT)
+#endif
+#endif
+ {
+ SetRect (&dragRect, FILL_X(X_2_COL(thePoint.h)),
+ FILL_Y(Y_2_ROW(thePoint.v)),
+ FILL_X(X_2_COL(thePoint.h)+1),
+ FILL_Y(Y_2_ROW(thePoint.v)+1));
+
+ dragRectEnbl = TRUE;
+ dragRectControl = kCreateRect;
+ }
+ }
+}
+
+/*
+ * Handle the click in the titlebar (to move the window)
+ */
+ void
+gui_mac_doInDragClick (where, whichWindow)
+ Point where;
+ WindowPtr whichWindow;
+{
+ Rect movingLimits;
+ Rect *movingLimitsPtr = &movingLimits;
+
+ /* TODO: may try to prevent move outside screen? */
+#ifdef USE_CARBONIZED
+ movingLimitsPtr = GetRegionBounds ( GetGrayRgn(), &movingLimits );
+#else
+ movingLimitsPtr = &(*GetGrayRgn())->rgnBBox;
+#endif
+ DragWindow (whichWindow, where, movingLimitsPtr);
+}
+
+/*
+ * Handle the click in the grow box
+ */
+ void
+gui_mac_doInGrowClick(where, whichWindow)
+ Point where;
+ WindowPtr whichWindow;
+{
+
+ long newSize;
+ unsigned short newWidth;
+ unsigned short newHeight;
+ Rect resizeLimits;
+ Rect *resizeLimitsPtr = &resizeLimits;
+#ifdef USE_CARBONIZED
+ Rect NewContentRect;
+
+ resizeLimitsPtr = GetRegionBounds ( GetGrayRgn(), &resizeLimits );
+#else
+ resizeLimits = qd.screenBits.bounds;
+#endif
+
+ /* Set the minimun size */
+ /* TODO: Should this come from Vim? */
+ resizeLimits.top = 100;
+ resizeLimits.left = 100;
+
+#ifdef USE_CARBONIZED
+ newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect);
+ newWidth = NewContentRect.right - NewContentRect.left;
+ newHeight = NewContentRect.bottom - NewContentRect.top;
+ gui_resize_shell(newWidth, newHeight);
+ gui_mch_set_bg_color(gui.back_pixel);
+ gui_set_shellsize(TRUE, FALSE);
+#else
+ newSize = GrowWindow(whichWindow, where, &resizeLimits);
+ if (newSize != 0)
+ {
+ newWidth = newSize & 0x0000FFFF;
+ newHeight = (newSize >> 16) & 0x0000FFFF;
+
+ gui_mch_set_bg_color(gui.back_pixel);
+
+ gui_resize_shell(newWidth, newHeight);
+
+ /*
+ * We need to call gui_set_shellsize as the size
+ * used by Vim may be smaller than the size selected
+ * by the user. This cause some overhead
+ * TODO: add a check inside gui_resize_shell?
+ */
+ gui_set_shellsize(TRUE, FALSE);
+
+ /*
+ * Origin of the code below is unknown.
+ * Functionality is unknown.
+ * Time of commented out is unknown.
+ */
+/* SetPort(wp);
+ InvalRect(&wp->portRect);
+ if (isUserWindow(wp)) {
+ DrawingWindowPeek aWindow = (DrawingWindowPeek)wp;
+
+ if (aWindow->toolRoutines.toolWindowResizedProc)
+ CallToolWindowResizedProc(aWindow->toolRoutines.toolWindowResizedProc, wp);
+ }*/
+ };
+#endif
+
+}
+
+/*
+ * Handle the click in the zoom box
+ */
+#ifdef USE_CARBONIZED
+ static void
+gui_mac_doInZoomClick(theEvent, whichWindow)
+ EventRecord *theEvent;
+ WindowPtr whichWindow;
+{
+ Rect r;
+ Point p;
+ short thePart;
+
+ /* ideal width is current */
+ p.h = Columns * gui.char_width + 2 * gui.border_offset;
+ if (gui.which_scrollbars[SBAR_LEFT])
+ p.h += gui.scrollbar_width;
+ if (gui.which_scrollbars[SBAR_RIGHT])
+ p.h += gui.scrollbar_width;
+ /* ideal height is as heigh as we can get */
+ p.v = 15 * 1024;
+
+ thePart = IsWindowInStandardState(whichWindow, &p, &r)
+ ? inZoomIn : inZoomOut;
+
+ if (!TrackBox(whichWindow, theEvent->where, thePart))
+ return;
+
+ /* use returned width */
+ p.h = r.right - r.left;
+ /* adjust returned height */
+ p.v = r.bottom - r.top - 2 * gui.border_offset;
+ if (gui.which_scrollbars[SBAR_BOTTOM])
+ p.v -= gui.scrollbar_height;
+ p.v -= p.v % gui.char_height;
+ p.v += 2 * gui.border_width;
+ if (gui.which_scrollbars[SBAR_BOTTOM]);
+ p.v += gui.scrollbar_height;
+
+ ZoomWindowIdeal(whichWindow, thePart, &p);
+
+ GetWindowBounds(whichWindow, kWindowContentRgn, &r);
+ gui_resize_shell(r.right - r.left, r.bottom - r.top);
+ gui_mch_set_bg_color(gui.back_pixel);
+ gui_set_shellsize(TRUE, FALSE);
+}
+#endif /* defined(USE_CARBONIZED) */
+
+/*
+ * ------------------------------------------------------------
+ * MacOS Event Handling procedure
+ * ------------------------------------------------------------
+ */
+
+/*
+ * Handle the Update Event
+ */
+
+ void
+gui_mac_doUpdateEvent(event)
+ EventRecord *event;
+{
+ WindowPtr whichWindow;
+ GrafPtr savePort;
+ RgnHandle updateRgn;
+#ifdef USE_CARBONIZED
+ Rect updateRect;
+#endif
+ Rect *updateRectPtr;
+ Rect rc;
+ Rect growRect;
+ RgnHandle saveRgn;
+
+
+#ifdef USE_CARBONIZED
+ updateRgn = NewRgn();
+ if (updateRgn == NULL)
+ return;
+#endif
+
+ /* This could be done by the caller as we
+ * don't require anything else out of the event
+ */
+ whichWindow = (WindowPtr) event->message;
+
+ /* Save Current Port */
+ GetPort (&savePort);
+
+ /* Select the Window's Port */
+#ifdef USE_CARBONIZED
+ SetPortWindowPort (whichWindow);
+#else
+ SetPort (whichWindow);
+#endif
+
+ /* Let's update the window */
+ BeginUpdate (whichWindow);
+ /* Redraw the biggest rectangle covering the area
+ * to be updated.
+ */
+#ifdef USE_CARBONIZED
+ GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn);
+# if 0
+ /* Would be more appropriate to use the follwing but doesn't
+ * seem to work under MacOS X (Dany)
+ */
+ GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn);
+# endif
+#else
+ updateRgn = whichWindow->visRgn;
+#endif
+ /* Use the HLock useless in Carbon? Is it harmful?*/
+ HLock ((Handle) updateRgn);
+#ifdef USE_CARBONIZED
+ updateRectPtr = GetRegionBounds ( updateRgn, &updateRect );
+# if 0
+ /* Code from original Carbon Port (using GetWindowRegion.
+ * I believe the UpdateRgn is already in local (Dany)
+ */
+ GlobalToLocal(&topLeft(updateRect)); /* preCarbon? */
+ GlobalToLocal(&botRight(updateRect));
+# endif
+#else
+ updateRectPtr = &(*updateRgn)->rgnBBox;
+#endif
+ /* Update the content (i.e. the text) */
+ gui_redraw(updateRectPtr->left, updateRectPtr->top,
+ updateRectPtr->right - updateRectPtr->left,
+ updateRectPtr->bottom - updateRectPtr->top);
+ /* Clear the border areas if needed */
+ gui_mch_set_bg_color(gui.back_pixel);
+ if (updateRectPtr->left < FILL_X(0))
+ {
+ SetRect (&rc, 0, 0, FILL_X(0), FILL_Y(Rows));
+ EraseRect (&rc);
+ }
+ if (updateRectPtr->top < FILL_Y(0))
+ {
+ SetRect (&rc, 0, 0, FILL_X(Columns), FILL_Y(0));
+ EraseRect (&rc);
+ }
+ if (updateRectPtr->right > FILL_X(Columns))
+ {
+ SetRect (&rc, FILL_X(Columns), 0,
+ FILL_X(Columns) + gui.border_offset, FILL_Y(Rows));
+ EraseRect (&rc);
+ }
+ if (updateRectPtr->bottom > FILL_Y(Rows))
+ {
+ SetRect (&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset,
+ FILL_Y(Rows) + gui.border_offset);
+ EraseRect (&rc);
+ }
+ HUnlock ((Handle) updateRgn);
+#ifdef USE_CARBONIZED
+ DisposeRgn (updateRgn);
+#endif
+
+ /* Update scrollbars */
+ DrawControls (whichWindow);
+
+ /* Update the GrowBox */
+ /* Taken from FAQ 33-27 */
+ saveRgn = NewRgn();
+#ifdef USE_CARBONIZED
+ GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect);
+#else
+ growRect = whichWindow->portRect;
+ growRect.top = growRect.bottom - 15;
+ growRect.left = growRect.right - 15;
+#endif
+ GetClip (saveRgn);
+ ClipRect (&growRect);
+ DrawGrowIcon (whichWindow);
+ SetClip (saveRgn);
+ DisposeRgn (saveRgn);
+ EndUpdate (whichWindow);
+
+ /* Restore original Port */
+ SetPort (savePort);
+}
+
+/*
+ * Handle the activate/deactivate event
+ * (apply to a window)
+ */
+ void
+gui_mac_doActivateEvent(event)
+ EventRecord *event;
+{
+ WindowPtr whichWindow;
+
+ whichWindow = (WindowPtr) event->message;
+ if ((event->modifiers) & activeFlag)
+ /* Activate */
+ gui_focus_change(TRUE);
+ else
+ {
+ /* Deactivate */
+ gui_focus_change(FALSE);
+/* DON'T KNOW what the code below was doing
+ found in the deactivate clause, but the
+ clause writting TRUE into in_focus (BUG)
+ */
+
+#if 0 /* Removed by Dany as per above June 2001 */
+ a_bool = false;
+ SetPreserveGlyph (a_bool);
+ SetOutlinePreferred (a_bool);
+#endif
+ }
+}
+
+
+/*
+ * Handle the suspend/resume event
+ * (apply to the application)
+ */
+ void
+gui_mac_doSuspendEvent(event)
+ EventRecord *event;
+{
+ /* The frontmost application just changed */
+
+ /* NOTE: the suspend may happen before the deactivate
+ * seen on MacOS X
+ */
+
+ /* May not need to change focus as the window will
+ * get an activate/desactivate event
+ */
+ if (event->message & 1)
+ /* Resume */
+ gui_focus_change(TRUE);
+ else
+ /* Suspend */
+ gui_focus_change(FALSE);
+}
+
+/*
+ * Handle the key
+ */
+
+ void
+gui_mac_doKeyEvent(EventRecord *theEvent)
+{
+ /* TODO: add support for COMMAND KEY */
+ long menu;
+ unsigned char string[20];
+ short num, i;
+ short len = 0;
+ KeySym key_sym;
+ int key_char;
+ int modifiers;
+
+ /* Mask the mouse (as per user setting) */
+ if (p_mh)
+ ObscureCursor();
+
+ /* Get the key code and it's ASCII representation */
+ key_sym = ((theEvent->message & keyCodeMask) >> 8);
+ key_char = theEvent->message & charCodeMask;
+ num = 1;
+
+ /* Intercept CTRL-C */
+ if (theEvent->modifiers & controlKey)
+ if (key_char == Ctrl_C && ctrl_c_interrupts)
+ got_int = TRUE;
+
+ /* Intercept CMD-. */
+ if (theEvent->modifiers & cmdKey)
+ if (key_char == '.')
+ got_int = TRUE;
+
+ /* Handle command key as per menu */
+ /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
+ if (theEvent->modifiers & cmdKey)
+ /* Only accept CMD alone or with CAPLOCKS and the mouse button.
+ * Why the mouse button? */
+ if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
+ {
+ menu = MenuKey(key_char);
+ if (HiWord(menu))
+ {
+ gui_mac_handle_menu(menu);
+ return;
+ }
+ }
+
+ /* Convert the modifiers */
+ modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
+
+
+ /* Handle special keys. */
+#if 0
+ /* Why have this been removed? */
+ if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
+#endif
+ {
+ /* Find the special key (for non-printable keyt_char) */
+ if ((key_char < 0x20) || (key_char == 0x7f))
+ for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
+ if (special_keys[i].key_sym == key_sym)
+ {
+# if 0
+ /* We currently don't have not so special key */
+ if (special_keys[i].vim_code1 == NUL)
+ key_char = special_keys[i].vim_code0;
+ else
+# endif
+ key_char = TO_SPECIAL( special_keys[i].vim_code0,
+ special_keys[i].vim_code1 );
+ key_char = simplify_key(key_char,&modifiers);
+ break;
+ }
+ }
+
+
+ /* Add the modifier to the input bu if needed */
+ /* Do not want SHIFT-A or CTRL-A with modifier */
+ if (!IS_SPECIAL(key_char)
+ && key_sym != vk_Space
+ && key_sym != vk_Tab
+ && key_sym != vk_Return
+ && key_sym != vk_Enter
+ && key_sym != vk_Esc)
+ {
+#if 1
+ /* Clear modifiers when only one modifier is set */
+ if( (modifiers == MOD_MASK_SHIFT) ||
+ (modifiers == MOD_MASK_CTRL) ||
+ (modifiers == MOD_MASK_ALT))
+ modifiers = 0;
+#else
+ if( modifiers & MOD_MASK_CTRL)
+ modifiers = modifiers & ~MOD_MASK_CTRL;
+ if( modifiers & MOD_MASK_ALT)
+ modifiers = modifiers & ~MOD_MASK_ALT;
+ if( modifiers & MOD_MASK_SHIFT)
+ modifiers = modifiers & ~MOD_MASK_SHIFT;
+#endif
+ }
+ if( modifiers )
+ {
+ string[ len++ ] = CSI;
+ string[ len++ ] = KS_MODIFIER;
+ string[ len++ ] = modifiers;
+ }
+
+ if( IS_SPECIAL( key_char ) )
+ {
+ string[ len++ ] = CSI;
+ string[ len++ ] = K_SECOND( key_char );
+ string[ len++ ] = K_THIRD( key_char );
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (input_conv.vc_type != CONV_NONE)
+ {
+ char_u from[2], *to;
+ int l;
+
+ from[0] = key_char;
+ from[1] = NUL;
+ l = 1;
+ to = string_convert(&input_conv, from, &l);
+ if (to != NULL)
+ {
+ for (i = 0; i < l && len < 19; i++)
+ {
+ if (to[i] == CSI)
+ {
+ string[len++] = KS_EXTRA;
+ string[len++] = KE_CSI;
+ }
+ else
+ string[len++] = to[i];
+ }
+ vim_free(to);
+ }
+ else
+ string[len++] = key_char;
+ }
+ else
+#endif
+ string[len++] = key_char;
+ }
+
+ if (len == 1 && string[0] == CSI)
+ {
+ /* Turn CSI into K_CSI. */
+ string[ len++ ] = KS_EXTRA;
+ string[ len++ ] = KE_CSI;
+ }
+
+ add_to_input_buf(string, len);
+}
+
+/*
+ * Handle MouseClick
+ */
+ void
+gui_mac_doMouseDownEvent (theEvent)
+ EventRecord *theEvent;
+{
+ short thePart;
+ WindowPtr whichWindow;
+
+ thePart = FindWindow (theEvent->where, &whichWindow);
+
+ switch (thePart)
+ {
+ case (inDesk):
+ /* TODO: what to do? */
+ break;
+
+ case (inMenuBar):
+ gui_mac_handle_menu(MenuSelect (theEvent->where));
+ break;
+
+ case (inContent):
+ gui_mac_doInContentClick (theEvent, whichWindow);
+ break;
+
+ case (inDrag):
+ gui_mac_doInDragClick (theEvent->where, whichWindow);
+ break;
+
+ case (inGrow):
+ gui_mac_doInGrowClick (theEvent->where, whichWindow);
+ break;
+
+ case (inGoAway):
+ if (TrackGoAway(whichWindow, theEvent->where))
+ gui_shell_closed();
+ break;
+
+ case (inZoomIn):
+ case (inZoomOut):
+#ifdef USE_CARBONIZED
+ gui_mac_doInZoomClick(theEvent, whichWindow);
+#endif
+ break;
+ }
+}
+
+/*
+ * Handle MouseMoved
+ * [this event is a moving in and out of a region]
+ */
+ void
+gui_mac_doMouseMovedEvent (event)
+ EventRecord *event;
+{
+ Point thePoint;
+ int_u vimModifiers;
+
+ thePoint = event->where;
+ GlobalToLocal (&thePoint);
+ vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
+
+ if (!Button())
+ gui_mouse_moved (thePoint.h, thePoint.v);
+ else
+#ifdef USE_CTRLCLICKMENU
+ if (!clickIsPopup)
+#endif
+ gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
+ thePoint.v, FALSE, vimModifiers);
+
+ /* Reset the region from which we move in and out */
+ SetRect (&dragRect, FILL_X(X_2_COL(thePoint.h)),
+ FILL_Y(Y_2_ROW(thePoint.v)),
+ FILL_X(X_2_COL(thePoint.h)+1),
+ FILL_Y(Y_2_ROW(thePoint.v)+1));
+
+ if (dragRectEnbl)
+ dragRectControl = kCreateRect;
+
+}
+
+/*
+ * Handle the mouse release
+ */
+ void
+gui_mac_doMouseUpEvent (theEvent)
+ EventRecord *theEvent;
+{
+ Point thePoint;
+ int_u vimModifiers;
+
+ /* TODO: Properly convert the Contextual menu mouse-up */
+ /* Potential source of the double menu */
+ lastMouseTick = theEvent->when;
+ dragRectEnbl = FALSE;
+ dragRectControl = kCreateEmpty;
+ thePoint = theEvent->where;
+ GlobalToLocal (&thePoint);
+
+ vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
+#ifdef USE_CTRLCLICKMENU
+ if (clickIsPopup)
+ {
+ vimModifiers &= ~MOUSE_CTRL;
+ clickIsPopup = FALSE;
+ }
+#endif
+ gui_send_mouse_event
+ (MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
+}
+
+#ifdef USE_MOUSEWHEEL
+ static pascal OSStatus
+gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
+ void *data)
+{
+ EventRef bogusEvent;
+ Point point;
+ Rect bounds;
+ UInt32 mod;
+ SInt32 delta;
+ int_u vim_mod;
+
+ if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
+ typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
+ goto bail;
+ if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
+ typeQDPoint, NULL, sizeof(Point), NULL, &point))
+ goto bail;
+ if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
+ typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
+ goto bail;
+
+ vim_mod = 0;
+ if (mod & shiftKey)
+ vim_mod |= MOUSE_SHIFT;
+ if (mod & controlKey)
+ vim_mod |= MOUSE_CTRL;
+ if (mod & optionKey)
+ vim_mod |= MOUSE_ALT;
+
+ /* post a bogus event to wake up WaitNextEvent */
+ if (noErr != CreateEvent(NULL, kEventClassMouse, kEventMouseMoved, 0,
+ kEventAttributeNone, &bogusEvent))
+ goto bail;
+ if (noErr != PostEventToQueue(GetMainEventQueue(), bogusEvent,
+ kEventPriorityLow))
+ goto bail;
+
+ if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
+ {
+ point.h -= bounds.left;
+ point.v -= bounds.top;
+ }
+
+ gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
+ point.h, point.v, FALSE, vim_mod);
+
+ return noErr;
+
+ bail:
+ /*
+ * when we fail give any additional callback handler a chance to perform
+ * it's actions
+ */
+ return CallNextEventHandler(nextHandler, theEvent);
+}
+#endif /* defined(USE_MOUSEWHEEL) */
+
+#if 0
+
+/*
+ * This would be the normal way of invoking the contextual menu
+ * but the Vim API doesn't seem to a support a request to get
+ * the menu that we should display
+ */
+ void
+gui_mac_handle_contextual_menu(event)
+ EventRecord *event;
+{
+/*
+ * Clone PopUp to use menu
+ * Create a object descriptor for the current selection
+ * Call the procedure
+ */
+
+// Call to Handle Popup
+ OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
+
+ if (status != noErr)
+ return;
+
+ if (CntxType == kCMMenuItemSelected)
+ {
+ /* Handle the menu CntxMenuID, CntxMenuItem */
+ /* The submenu can be handle directly by gui_mac_handle_menu */
+ /* But what about the current menu, is the meny changed by ContextualMenuSelect */
+ gui_mac_handle_menu ((CntxMenuID << 16) + CntxMenuItem);
+ }
+ else if (CntxMenuID == kCMShowHelpSelected)
+ {
+ /* Should come up with the help */
+ }
+
+}
+#endif
+
+/*
+ * Handle menubar selection
+ */
+ void
+gui_mac_handle_menu(menuChoice)
+ long menuChoice;
+{
+ short menu = HiWord(menuChoice);
+ short item = LoWord(menuChoice);
+ vimmenu_T *theVimMenu = root_menu;
+#ifndef USE_CARBONIZED
+ MenuHandle appleMenu;
+ Str255 itemName;
+#endif
+
+ if (menu == 256) /* TODO: use constant or gui.xyz */
+ {
+ if (item == 1)
+ gui_mch_beep(); /* TODO: Popup dialog or do :intro */
+ else
+ {
+#ifndef USE_CARBONIZED
+ /* Desk Accessory doesn't exist in Carbon */
+ appleMenu = GetMenuHandle (menu);
+ GetMenuItemText (appleMenu, item, itemName);
+ (void) OpenDeskAcc (itemName);
+#endif
+ }
+ }
+ else if (item != 0)
+ {
+ theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
+
+ if (theVimMenu)
+ gui_menu_cb(theVimMenu);
+ }
+ HiliteMenu (0);
+}
+
+/*
+ * Dispatch the event to proper handler
+ */
+
+ void
+gui_mac_handle_event (event)
+ EventRecord *event;
+{
+ OSErr error;
+
+ /* Handle contextual menu right now (if needed) */
+#ifdef USE_CTRLCLICKMENU
+ if (gui.MacOSHaveCntxMenu)
+ if (IsShowContextualMenuClick(event))
+ {
+# if 0
+ gui_mac_handle_contextual_menu(event);
+# else
+ gui_mac_doMouseDownEvent(event);
+# endif
+ return;
+ }
+#endif
+
+ /* Handle normal event */
+ switch (event->what)
+ {
+ case (keyDown):
+ case (autoKey):
+ gui_mac_doKeyEvent (event);
+ break;
+
+ case (keyUp):
+ /* We don't care about when the key get release */
+ break;
+
+ case (mouseDown):
+ gui_mac_doMouseDownEvent(event);
+ break;
+
+ case (mouseUp):
+ gui_mac_doMouseUpEvent(event);
+ break;
+
+ case (updateEvt):
+ gui_mac_doUpdateEvent (event);
+ break;
+
+ case (diskEvt):
+ /* We don't need special handling for disk insertion */
+ break;
+
+ case (activateEvt):
+ gui_mac_doActivateEvent (event);
+ break;
+
+ case (osEvt):
+ switch ((event->message >> 24) & 0xFF)
+ {
+ case (0xFA): /* mouseMovedMessage */
+ gui_mac_doMouseMovedEvent (event);
+ break;
+ case (0x01): /* suspendResumeMessage */
+ gui_mac_doSuspendEvent (event);
+ break;
+ }
+ break;
+
+#ifdef USE_AEVENT
+ case (kHighLevelEvent):
+ /* Someone's talking to us, through AppleEvents */
+ error = AEProcessAppleEvent(event); /* TODO: Error Handling */
+ break;
+#endif
+ }
+}
+
+/*
+ * ------------------------------------------------------------
+ * Unknown Stuff
+ * ------------------------------------------------------------
+ */
+
+
+ GuiFont
+gui_mac_find_font (font_name)
+ char_u *font_name;
+{
+ char_u c;
+ char_u *p;
+ char_u pFontName[256];
+ Str255 systemFontname;
+ short font_id;
+ short size=9;
+ GuiFont font;
+#if 0
+ char_u *fontNamePtr;
+#endif
+
+ for (p = font_name; ((*p != 0) && (*p != ':')); p++)
+ ;
+
+ c = *p;
+ *p = 0;
+
+#if 1
+ STRCPY(&pFontName[1], font_name);
+ pFontName[0] = STRLEN(font_name);
+ *p = c;
+
+ GetFNum (pFontName, &font_id);
+#else
+ /* name = C2Pascal_save(menu->dname); */
+ fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
+
+ GetFNum (fontNamePtr, &font_id);
+#endif
+
+
+ if (font_id == 0)
+ {
+ /* Oups, the system font was it the one the user want */
+
+ GetFontName (0, systemFontname);
+ if (!EqualString(pFontName, systemFontname, false, false))
+ return NOFONT;
+ }
+ if (*p == ':')
+ {
+ p++;
+ /* Set the values found after ':' */
+ while (*p)
+ {
+ switch (*p++)
+ {
+ case 'h':
+ size = points_to_pixels(p, &p, TRUE);
+ break;
+ /*
+ * TODO: Maybe accept width and styles
+ */
+ }
+ while (*p == ':')
+ p++;
+ }
+ }
+
+ if (size < 1)
+ size = 1; /* Avoid having a size of 0 with system font */
+
+ font = (size << 16) + ((long) font_id & 0xFFFF);
+
+ return font;
+}
+
+/*
+ * ------------------------------------------------------------
+ * GUI_MCH functionnality
+ * ------------------------------------------------------------
+ */
+
+/*
+ * Parse the GUI related command-line arguments. Any arguments used are
+ * deleted from argv, and *argc is decremented accordingly. This is called
+ * when vim is started, whether or not the GUI has been started.
+ */
+ void
+gui_mch_prepare(argc, argv)
+ int *argc;
+ char **argv;
+{
+ /* TODO: Move most of this stuff toward gui_mch_init */
+#ifdef USE_EXE_NAME
+ FSSpec applDir;
+# ifndef USE_FIND_BUNDLE_PATH
+ short applVRefNum;
+ long applDirID;
+ Str255 volName;
+# else
+ ProcessSerialNumber psn;
+ FSRef applFSRef;
+# endif
+#endif
+
+#ifndef USE_CARBONIZED
+ MaxApplZone(); /* What could replace thos */
+ /* In Carbon, all shared library are automatically load in
+ * there's no need to init them
+ */
+ InitGraf(&qd.thePort);
+ InitFonts();
+ InitWindows();
+ InitMenus();
+ TEInit();
+ InitDialogs(nil);
+#else
+ /* Why did I put that in? (Dany) */
+ MoreMasterPointers (0x40 * 3); /* we love handles */
+#endif
+
+#if 0
+ InitCursor();
+
+#ifdef USE_CARBONIZED
+ RegisterAppearanceClient();
+#endif
+
+#ifdef USE_AEVENT
+ (void) InstallAEHandlers();
+#endif
+
+#ifdef USE_CTRLCLICKMENU
+ if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
+ gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
+ else
+ gui.MacOSHaveCntxMenu = false;
+
+ if (gui.MacOSHaveCntxMenu)
+ gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
+#endif
+
+#ifdef USE_SIOUX
+ SIOUXSettings.standalone = false;
+ SIOUXSettings.initializeTB = false;
+ SIOUXSettings.setupmenus = false;
+ SIOUXSettings.asktosaveonclose = false;
+ SIOUXSettings.showstatusline = true;
+ SIOUXSettings.toppixel = 300;
+ SIOUXSettings.leftpixel = 10;
+ InstallConsole (1); /* fileno(stdout) = 1, on page 430 of MSL C */
+ printf ("Debugging console enabled\n");
+ /* SIOUXSetTitle ((char_u *) "Vim Stdout"); */
+#endif
+
+ pomme = NewMenu (256, "\p\024"); /* 0x14= = Apple Menu */
+
+ AppendMenu (pomme, "\pAbout VIM");
+#ifndef USE_CARBONIZED
+ AppendMenu (pomme, "\p-");
+ AppendResMenu (pomme, 'DRVR');
+#endif
+
+ InsertMenu (pomme, 0);
+
+ DrawMenuBar();
+
+
+#ifndef USE_OFFSETED_WINDOW
+ SetRect (&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
+#else
+ SetRect (&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
+#endif
+
+
+#ifdef USE_CARBONIZED
+ CreateNewWindow(kDocumentWindowClass,
+ kWindowResizableAttribute | kWindowCollapseBoxAttribute,
+ &windRect, &gui.VimWindow );
+ SetPortWindowPort ( gui.VimWindow );
+#else
+ gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true, documentProc,
+ (WindowPtr) -1L, false, 0);
+ SetPort(gui.VimWindow);
+#endif
+
+ gui.char_width = 7;
+ gui.char_height = 11;
+ gui.char_ascent = 6;
+ gui.num_rows = 24;
+ gui.num_cols = 80;
+ gui.in_focus = TRUE; /* For the moment -> syn. of front application */
+
+#if TARGET_API_MAC_CARBON
+ gScrollAction = NewControlActionUPP (gui_mac_scroll_action);
+ gScrollDrag = NewControlActionUPP (gui_mac_drag_thumb);
+#else
+ gScrollAction = NewControlActionProc (gui_mac_scroll_action);
+ gScrollDrag = NewControlActionProc (gui_mac_drag_thumb);
+#endif
+
+ /* Getting a handle to the Help menu */
+#ifdef USE_HELPMENU
+# ifdef USE_CARBONIZED
+ HMGetHelpMenu(&gui.MacOSHelpMenu, NULL);
+# else
+ (void) HMGetHelpMenuHandle(&gui.MacOSHelpMenu);
+# endif
+
+ if (gui.MacOSHelpMenu != nil)
+ gui.MacOSHelpItems = CountMenuItems (gui.MacOSHelpMenu);
+ else
+ gui.MacOSHelpItems = 0;
+#endif
+
+ dragRectEnbl = FALSE;
+ dragRgn = NULL;
+ dragRectControl = kCreateEmpty;
+ cursorRgn = NewRgn();
+#endif
+#ifdef USE_EXE_NAME
+# ifndef USE_FIND_BUNDLE_PATH
+ HGetVol (volName, &applVRefNum, &applDirID);
+ /* TN2015: mention a possible bad VRefNum */
+ FSMakeFSSpec (applVRefNum, applDirID, "\p", &applDir);
+# else
+ /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
+ * of TN2015
+ * This technic remove the ../Contents/MacOS/etc part
+ */
+ (void) GetCurrentProcess(&psn);
+ /* if (err != noErr) return err; */
+
+ (void) GetProcessBundleLocation(&psn, &applFSRef);
+ /* if (err != noErr) return err; */
+
+ (void) FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
+
+ /* This technic return NIL when we disallow_gui */
+# endif
+ exe_name = FullPathFromFSSpec_save (applDir);
+#endif
+
+#ifdef USE_VIM_CREATOR_ID
+ _fcreator = 'VIM!';
+ _ftype = 'TEXT';
+#endif
+}
+
+#ifndef ALWAYS_USE_GUI
+/*
+ * Check if the GUI can be started. Called before gvimrc is sourced.
+ * Return OK or FAIL.
+ */
+ int
+gui_mch_init_check(void)
+{
+ /* TODO: For MacOS X find a way to return FAIL, if the user logged in
+ * using the >console
+ */
+ if (disallow_gui) /* see main.c for reason to disallow */
+ return FAIL;
+ return OK;
+}
+#endif
+
+ static OSErr
+receiveHandler(WindowRef theWindow, void* handlerRefCon, DragRef theDrag)
+{
+ int x, y;
+ int_u modifiers;
+ char_u **fnames = NULL;
+ int count;
+ int i, j;
+
+ /* Get drop position, modifiers and count of items */
+ {
+ Point point;
+ SInt16 mouseUpModifiers;
+ UInt16 countItem;
+
+ GetDragMouse(theDrag, &point, NULL);
+ GlobalToLocal(&point);
+ x = point.h;
+ y = point.v;
+ GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
+ modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
+ CountDragItems(theDrag, &countItem);
+ count = countItem;
+ }
+
+ fnames = (char_u **)alloc(count * sizeof(char_u *));
+ if (fnames == NULL)
+ return dragNotAcceptedErr;
+
+ /* Get file names dropped */
+ for (i = j = 0; i < count; ++i)
+ {
+ DragItemRef item;
+ OSErr err;
+ Size size;
+ FlavorType type = flavorTypeHFS;
+ HFSFlavor hfsFlavor;
+
+ fnames[i] = NULL;
+ GetDragItemReferenceNumber(theDrag, i + 1, &item);
+ err = GetFlavorDataSize(theDrag, item, type, &size);
+ if (err != noErr || size > sizeof(hfsFlavor))
+ continue;
+ err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
+ if (err != noErr)
+ continue;
+ fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
+ }
+ count = j;
+
+ gui_handle_drop(x, y, modifiers, fnames, count);
+ return noErr;
+}
+
+/*
+ * Initialise the GUI. Create all the windows, set up all the call-backs
+ * etc.
+ */
+ int
+gui_mch_init()
+{
+ /* TODO: Move most of this stuff toward gui_mch_init */
+ Rect windRect;
+ MenuHandle pomme;
+#ifdef USE_CTRLCLICKMENU
+ long gestalt_rc;
+#endif
+#ifdef USE_MOUSEWHEEL
+ EventTypeSpec eventTypeSpec;
+ EventHandlerRef mouseWheelHandlerRef;
+#endif
+#if 1
+ InitCursor();
+
+#ifdef USE_CARBONIZED
+ RegisterAppearanceClient();
+#endif
+
+#ifdef USE_AEVENT
+ (void) InstallAEHandlers();
+#endif
+
+#ifdef USE_CTRLCLICKMENU
+ if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
+ gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
+ else
+ gui.MacOSHaveCntxMenu = false;
+
+ if (gui.MacOSHaveCntxMenu)
+ gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
+#endif
+
+#ifdef USE_SIOUX
+ SIOUXSettings.standalone = false;
+ SIOUXSettings.initializeTB = false;
+ SIOUXSettings.setupmenus = false;
+ SIOUXSettings.asktosaveonclose = false;
+ SIOUXSettings.showstatusline = true;
+ SIOUXSettings.toppixel = 300;
+ SIOUXSettings.leftpixel = 10;
+ InstallConsole (1); /* fileno(stdout) = 1, on page 430 of MSL C */
+ printf ("Debugging console enabled\n");
+ /* SIOUXSetTitle ((char_u *) "Vim Stdout"); */
+#endif
+
+ pomme = NewMenu (256, "\p\024"); /* 0x14= = Apple Menu */
+
+ AppendMenu (pomme, "\pAbout VIM");
+#ifndef USE_CARBONIZED
+ AppendMenu (pomme, "\p-");
+ AppendResMenu (pomme, 'DRVR');
+#endif
+
+ InsertMenu (pomme, 0);
+
+ DrawMenuBar();
+
+
+#ifndef USE_OFFSETED_WINDOW
+ SetRect (&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
+#else
+ SetRect (&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
+#endif
+
+ gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
+#ifdef USE_CARBONIZED
+ zoomDocProc,
+#else
+ documentProc,
+#endif
+ (WindowPtr)-1L, true, 0);
+ InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
+ gui.VimWindow, NULL);
+#ifdef USE_CARBONIZED
+ SetPortWindowPort ( gui.VimWindow );
+#else
+ SetPort(gui.VimWindow);
+#endif
+
+ gui.char_width = 7;
+ gui.char_height = 11;
+ gui.char_ascent = 6;
+ gui.num_rows = 24;
+ gui.num_cols = 80;
+ gui.in_focus = TRUE; /* For the moment -> syn. of front application */
+
+#if TARGET_API_MAC_CARBON
+ gScrollAction = NewControlActionUPP (gui_mac_scroll_action);
+ gScrollDrag = NewControlActionUPP (gui_mac_drag_thumb);
+#else
+ gScrollAction = NewControlActionProc (gui_mac_scroll_action);
+ gScrollDrag = NewControlActionProc (gui_mac_drag_thumb);
+#endif
+
+ /* Getting a handle to the Help menu */
+#ifdef USE_HELPMENU
+# ifdef USE_CARBONIZED
+ HMGetHelpMenu(&gui.MacOSHelpMenu, NULL);
+# else
+ (void) HMGetHelpMenuHandle(&gui.MacOSHelpMenu);
+# endif
+
+ if (gui.MacOSHelpMenu != nil)
+ gui.MacOSHelpItems = CountMenuItems (gui.MacOSHelpMenu);
+ else
+ gui.MacOSHelpItems = 0;
+#endif
+
+ dragRectEnbl = FALSE;
+ dragRgn = NULL;
+ dragRectControl = kCreateEmpty;
+ cursorRgn = NewRgn();
+#endif
+ /* Display any pending error messages */
+ display_errors();
+
+ /* Get background/foreground colors from system */
+ /* TODO: do the approriate call to get real defaults */
+ gui.norm_pixel = 0x00000000;
+ gui.back_pixel = 0x00FFFFFF;
+
+ /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
+ * file). */
+ set_normal_colors();
+
+ /*
+ * Check that none of the colors are the same as the background color.
+ * Then store the current values as the defaults.
+ */
+ gui_check_colors();
+ gui.def_norm_pixel = gui.norm_pixel;
+ gui.def_back_pixel = gui.back_pixel;
+
+ /* Get the colors for the highlight groups (gui_check_colors() might have
+ * changed them) */
+ highlight_gui_started();
+
+ /*
+ * Setting the gui constants
+ */
+#ifdef FEAT_MENU
+ gui.menu_height = 0;
+#endif
+ gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
+ gui.border_offset = gui.border_width = 2;
+
+#if defined(FEAT_GUI) && defined(MACOS_X)
+ /* If Quartz-style text antialiasing is available (see
+ gui_mch_draw_string() below), enable it for all font sizes. */
+ vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
+#endif
+
+#ifdef USE_MOUSEWHEEL
+ eventTypeSpec.eventClass = kEventClassMouse;
+ eventTypeSpec.eventKind = kEventMouseWheelMoved;
+ mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
+ if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
+ &eventTypeSpec, NULL, &mouseWheelHandlerRef))
+ {
+ mouseWheelHandlerRef = NULL;
+ DisposeEventHandlerUPP(mouseWheelHandlerUPP);
+ mouseWheelHandlerUPP = NULL;
+ }
+#endif
+
+#ifdef FEAT_MBYTE
+ set_option_value((char_u *)"termencoding", 0L, (char_u *)"macroman", 0);
+#endif
+
+ /* TODO: Load bitmap if using TOOLBAR */
+ return OK;
+}
+
+/*
+ * Called when the foreground or background color has been changed.
+ */
+ void
+gui_mch_new_colors()
+{
+ /* TODO:
+ * This proc is called when Normal is set to a value
+ * so what msut be done? I don't know
+ */
+}
+
+/*
+ * Open the GUI window which was created by a call to gui_mch_init().
+ */
+ int
+gui_mch_open()
+{
+ ShowWindow(gui.VimWindow);
+
+ if (gui_win_x != -1 && gui_win_y != -1)
+ gui_mch_set_winpos(gui_win_x, gui_win_y);
+
+#ifdef USE_CARBONIZED
+ /*
+ * Make the GUI the foreground process (in case it was launched
+ * from the Terminal or via :gui).
+ */
+ {
+ ProcessSerialNumber psn;
+ if (GetCurrentProcess(&psn) == noErr)
+ SetFrontProcess(&psn);
+ }
+#endif
+
+ return OK;
+}
+
+ void
+gui_mch_exit(int rc)
+{
+ /* TODO: find out all what is missing here? */
+ DisposeRgn(cursorRgn);
+
+#ifdef USE_MOUSEWHEEL
+ if (mouseWheelHandlerUPP != NULL)
+ DisposeEventHandlerUPP(mouseWheelHandlerUPP);
+#endif
+
+ /* Exit to shell? */
+ exit(rc);
+}
+
+/*
+ * Get the position of the top left corner of the window.
+ */
+ int
+gui_mch_get_winpos(int *x, int *y)
+{
+ /* TODO */
+#ifdef USE_CARBONIZED
+ Rect bounds;
+ OSStatus status;
+
+ /* Carbon >= 1.0.2, MacOS >= 8.5 */
+ status = GetWindowBounds (gui.VimWindow, kWindowStructureRgn, &bounds);
+
+ if (status != noErr)
+ return FAIL;
+ *x = bounds.left;
+ *y = bounds.top;
+ return OK;
+#endif
+ return FAIL;
+}
+
+/*
+ * Set the position of the top left corner of the window to the given
+ * coordinates.
+ */
+ void
+gui_mch_set_winpos(int x, int y)
+{
+ /* TODO: Should make sure the window is move within range
+ * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
+ */
+ MoveWindow(gui.VimWindow, x, y, TRUE);
+}
+
+ void
+gui_mch_set_shellsize(
+ int width,
+ int height,
+ int min_width,
+ int min_height,
+ int base_width,
+ int base_height)
+{
+#ifdef USE_CARBONIZED
+ CGrafPtr VimPort;
+ Rect VimBound;
+#endif
+
+ if (gui.which_scrollbars[SBAR_LEFT])
+ {
+#ifdef USE_CARBONIZED
+ VimPort = GetWindowPort ( gui.VimWindow );
+ GetPortBounds (VimPort, &VimBound);
+ VimBound.left = -gui.scrollbar_width; /* + 1;*/
+ SetPortBounds (VimPort, &VimBound);
+ /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
+#else
+ gui.VimWindow->portRect.left = -gui.scrollbar_width; /* + 1;*/
+ /* SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
+#endif
+ }
+ else
+ {
+#ifdef USE_CARBONIZED
+ VimPort = GetWindowPort ( gui.VimWindow );
+ GetPortBounds (VimPort, &VimBound);
+ VimBound.left = 0;
+ SetPortBounds (VimPort, &VimBound);
+#else
+ gui.VimWindow->portRect.left = 0;
+#endif;
+ }
+
+ SizeWindow(gui.VimWindow, width, height, TRUE);
+
+ gui_resize_shell(width, height);
+}
+
+/*
+ * Get the screen dimensions.
+ * Allow 10 pixels for horizontal borders, 40 for vertical borders.
+ * Is there no way to find out how wide the borders really are?
+ * TODO: Add live udate of those value on suspend/resume.
+ */
+ void
+gui_mch_get_screen_dimensions(screen_w, screen_h)
+ int *screen_w;
+ int *screen_h;
+{
+ GDHandle dominantDevice = GetMainDevice();
+ Rect screenRect = (**dominantDevice).gdRect;
+
+ *screen_w = screenRect.right - 10;
+ *screen_h = screenRect.bottom - 40;
+}
+
+
+
+/*
+ * Initialise vim to use the font with the given name. Return FAIL if the font
+ * could not be loaded, OK otherwise.
+ */
+ int
+gui_mch_init_font(font_name, fontset)
+ char_u *font_name;
+ int fontset; /* not used */
+{
+ /* TODO: Add support for bold italic underline proportional etc... */
+ Str255 suggestedFont = "\pMonaco";
+ int suggestedSize = 9;
+ FontInfo font_info;
+ short font_id;
+ GuiFont font;
+
+ if (font_name == NULL)
+ {
+ /* First try to get the suggested font */
+ GetFNum(suggestedFont, &font_id);
+
+ if (font_id == 0)
+ {
+ /* Then pickup the standard application font */
+ font_id = GetAppFont();
+ }
+ font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
+ }
+ else
+ {
+ font = gui_mac_find_font (font_name);
+
+ if (font == NOFONT)
+ return FAIL;
+ }
+ gui.norm_font = font;
+
+ TextSize (font >> 16);
+ TextFont (font & 0xFFFF);
+
+ GetFontInfo (&font_info);
+
+ gui.char_ascent = font_info.ascent;
+ gui.char_width = CharWidth ('_');
+ gui.char_height = font_info.ascent + font_info.descent + p_linespace;
+
+ return OK;
+
+}
+
+ int
+gui_mch_adjust_charsize()
+{
+ FontInfo font_info;
+
+ GetFontInfo (&font_info);
+ gui.char_height = font_info.ascent + font_info.descent + p_linespace;
+ gui.char_ascent = font_info.ascent + p_linespace / 2;
+ return OK;
+}
+
+/*
+ * Get a font structure for highlighting.
+ */
+ GuiFont
+gui_mch_get_font(name, giveErrorIfMissing)
+ char_u *name;
+ int giveErrorIfMissing;
+{
+ GuiFont font;
+
+ font = gui_mac_find_font(name);
+
+ if (font == NOFONT)
+ {
+ if (giveErrorIfMissing)
+ EMSG2(_(e_font), name);
+ return NOFONT;
+ }
+ /*
+ * TODO : Accept only monospace
+ */
+
+ return font;
+}
+
+/*
+ * Set the current text font.
+ */
+ void
+gui_mch_set_font(font)
+ GuiFont font;
+{
+ /*
+ * TODO: maybe avoid set again the current font.
+ */
+ TextSize(font >> 16);
+ TextFont(font & 0xFFFF);
+}
+
+#if 0 /* not used */
+/*
+ * Return TRUE if the two fonts given are equivalent.
+ */
+ int
+gui_mch_same_font(f1, f2)
+ GuiFont f1;
+ GuiFont f2;
+{
+ return f1 == f2;
+}
+#endif
+
+/*
+ * If a font is not going to be used, free its structure.
+ */
+ void
+gui_mch_free_font(font)
+ GuiFont font;
+{
+ /*
+ * Free font when "font" is not 0.
+ * Nothing to do in the current implementation, since
+ * nothing is allocated for each font used.
+ */
+}
+
+ static int
+hex_digit(c)
+ int c;
+{
+ if (isdigit(c))
+ return c - '0';
+ c = TOLOWER_ASC(c);
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return -1000;
+}
+
+/*
+ * Return the Pixel value (color) for the given color name. This routine was
+ * pretty much taken from example code in the Silicon Graphics OSF/Motif
+ * Programmer's Guide.
+ * Return INVALCOLOR when failed.
+ */
+ guicolor_T
+gui_mch_get_color(name)
+ char_u *name;
+{
+ /* TODO: Add support for the new named color of MacOS 8
+ */
+ RGBColor MacColor;
+// guicolor_T color = 0;
+
+ typedef struct guicolor_tTable
+ {
+ char *name;
+ guicolor_T color;
+ } guicolor_tTable;
+
+ /*
+ * The comment at the end of each line is the source
+ * (Mac, Window, Unix) and the number is the unix rgb.txt value
+ */
+ static guicolor_tTable table[] =
+ {
+ {"Black", RGB(0x00, 0x00, 0x00)},
+ {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
+ {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
+ {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
+ {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
+ {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
+ {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
+ {"white", RGB(0xFF, 0xFF, 0xFF)},
+ {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
+ {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
+ {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
+ {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
+ {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
+ {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
+ {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
+ {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
+ {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
+ {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
+ {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
+ {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
+ {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
+ {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
+ {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
+ {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
+ {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
+ {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
+ {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, /*W 0x4E8975 */
+ {"orange", RGB(0xFC, 0x80, 0x00)}, /*W 0xF87A17 */
+ {"Purple", RGB(0xA0, 0x20, 0xF0)}, /*W 0x8e35e5 */
+ {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, /*W 0x737CA1 */
+ {"Violet", RGB(0x8D, 0x38, 0xC9)}, /*U*/
+ };
+
+ int r, g, b;
+ int i;
+
+ if (name[0] == '#' && strlen((char *) name) == 7)
+ {
+ /* Name is in "#rrggbb" format */
+ r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
+ g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
+ b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
+ if (r < 0 || g < 0 || b < 0)
+ return INVALCOLOR;
+ return RGB(r, g, b);
+ }
+ else
+ {
+ if (STRICMP (name, "hilite") == 0)
+ {
+ LMGetHiliteRGB (&MacColor);
+ return (RGB (MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
+ }
+ /* Check if the name is one of the colors we know */
+ for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
+ if (STRICMP(name, table[i].name) == 0)
+ return table[i].color;
+ }
+
+
+ /*
+ * Last attempt. Look in the file "$VIM/rgb.txt".
+ */
+ {
+#define LINE_LEN 100
+ FILE *fd;
+ char line[LINE_LEN];
+ char_u *fname;
+
+#ifdef COLON_AS_PATHSEP
+ fname = expand_env_save((char_u *)"$VIMRUNTIME:rgb.txt");
+#else
+ fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
+#endif
+ if (fname == NULL)
+ return INVALCOLOR;
+
+ fd = fopen((char *)fname, "rt");
+ vim_free(fname);
+ if (fd == NULL)
+ return INVALCOLOR;
+
+ while (!feof(fd))
+ {
+ int len;
+ int pos;
+ char *color;
+
+ fgets(line, LINE_LEN, fd);
+ len = strlen(line);
+
+ if (len <= 1 || line[len-1] != '\n')
+ continue;
+
+ line[len-1] = '\0';
+
+ i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
+ if (i != 3)
+ continue;
+
+ color = line + pos;
+
+ if (STRICMP(color, name) == 0)
+ {
+ fclose(fd);
+ return (guicolor_T) RGB(r, g, b);
+ }
+ }
+ fclose(fd);
+ }
+
+ return INVALCOLOR;
+}
+
+/*
+ * Set the current text foreground color.
+ */
+ void
+gui_mch_set_fg_color(color)
+ guicolor_T color;
+{
+ RGBColor TheColor;
+
+ TheColor.red = Red(color) * 0x0101;
+ TheColor.green = Green(color) * 0x0101;
+ TheColor.blue = Blue(color) * 0x0101;
+
+ RGBForeColor (&TheColor);
+}
+
+/*
+ * Set the current text background color.
+ */
+ void
+gui_mch_set_bg_color(color)
+ guicolor_T color;
+{
+ RGBColor TheColor;
+
+ TheColor.red = Red(color) * 0x0101;
+ TheColor.green = Green(color) * 0x0101;
+ TheColor.blue = Blue(color) * 0x0101;
+
+ RGBBackColor (&TheColor);
+}
+
+ void
+gui_mch_draw_string(row, col, s, len, flags)
+ int row;
+ int col;
+ char_u *s;
+ int len;
+ int flags;
+{
+#if defined(FEAT_GUI) && defined(MACOS_X)
+ SInt32 sys_version;
+#endif
+#ifdef FEAT_MBYTE
+ char_u *tofree = NULL;
+
+ if (output_conv.vc_type != CONV_NONE)
+ {
+ tofree = string_convert(&output_conv, s, &len);
+ if (tofree != NULL)
+ s = tofree;
+ }
+#endif
+
+#if defined(FEAT_GUI) && defined(MACOS_X)
+ /*
+ * On OS X, try using Quartz-style text antialiasing.
+ */
+ sys_version = 0;
+
+ Gestalt(gestaltSystemVersion, &sys_version);
+ if (sys_version >= 0x1020)
+ {
+ /* Quartz antialiasing is available only in OS 10.2 and later. */
+ UInt32 qd_flags = (p_antialias ?
+ kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
+ (void)SwapQDTextFlags(qd_flags);
+ }
+
+ if (sys_version >= 0x1020 && p_antialias)
+ {
+ StyleParameter face;
+
+ face = normal;
+ if (flags & DRAW_BOLD)
+ face |= bold;
+ if (flags & DRAW_UNDERL)
+ face |= underline;
+ TextFace(face);
+
+ /* Quartz antialiasing works only in srcOr transfer mode. */
+ TextMode(srcOr);
+
+ if (!(flags & DRAW_TRANSP))
+ {
+ /*
+ * Since we're using srcOr mode, we have to clear the block
+ * before drawing the text. The following is like calling
+ * gui_mch_clear_block(row, col, row, col + len - 1),
+ * but without setting the bg color to gui.back_pixel.
+ */
+ Rect rc;
+ rc.left = FILL_X(col);
+ rc.top = FILL_Y(row);
+ rc.right = FILL_X(col + len) + (col + len == Columns);
+ rc.bottom = FILL_Y(row + 1);
+ EraseRect(&rc);
+ }
+
+ MoveTo(TEXT_X(col), TEXT_Y(row));
+ DrawText((char*)s, 0, len);
+ }
+ else
+#endif
+ {
+ /* Use old-style, non-antialiased QuickDraw text rendering. */
+ TextMode (srcCopy);
+ TextFace (normal);
+
+ /* SelectFont(hdc, gui.currFont); */
+
+ if (flags & DRAW_TRANSP)
+ {
+ TextMode (srcOr);
+ }
+
+ MoveTo (TEXT_X(col), TEXT_Y(row));
+ DrawText ((char *)s, 0, len);
+
+
+ if (flags & DRAW_BOLD)
+ {
+ TextMode (srcOr);
+ MoveTo (TEXT_X(col) + 1, TEXT_Y(row));
+ DrawText ((char *)s, 0, len);
+ }
+
+ if (flags & DRAW_UNDERL)
+ {
+ MoveTo (FILL_X(col), FILL_Y(row + 1) - 1);
+ LineTo (FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
+ }
+ }
+
+#ifdef FEAT_MBYTE
+ vim_free(tofree);
+#endif
+}
+
+/*
+ * Return OK if the key with the termcap name "name" is supported.
+ */
+ int
+gui_mch_haskey(name)
+ char_u *name;
+{
+ int i;
+
+ for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
+ if (name[0] == special_keys[i].vim_code0 &&
+ name[1] == special_keys[i].vim_code1)
+ return OK;
+ return FAIL;
+}
+
+ void
+gui_mch_beep()
+{
+ SysBeep (1); /* Should this be 0? (????) */
+}
+
+ void
+gui_mch_flash(msec)
+ int msec;
+{
+ /* Do a visual beep by reversing the foreground and background colors */
+ Rect rc;
+
+ /*
+ * Note: InvertRect() excludes right and bottom of rectangle.
+ */
+ rc.left = 0;
+ rc.top = 0;
+ rc.right = gui.num_cols * gui.char_width;
+ rc.bottom = gui.num_rows * gui.char_height;
+ InvertRect(&rc);
+
+ ui_delay((long)msec, TRUE); /* wait for some msec */
+
+ InvertRect(&rc);
+}
+
+/*
+ * Invert a rectangle from row r, column c, for nr rows and nc columns.
+ */
+ void
+gui_mch_invert_rectangle(r, c, nr, nc)
+ int r;
+ int c;
+ int nr;
+ int nc;
+{
+ Rect rc;
+
+ /*
+ * Note: InvertRect() excludes right and bottom of rectangle.
+ */
+ rc.left = FILL_X(c);
+ rc.top = FILL_Y(r);
+ rc.right = rc.left + nc * gui.char_width;
+ rc.bottom = rc.top + nr * gui.char_height;
+ InvertRect(&rc);
+
+}
+
+/*
+ * Iconify the GUI window.
+ */
+ void
+gui_mch_iconify()
+{
+ /* TODO: find out what could replace iconify
+ * -window shade?
+ * -hide application?
+ */
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Bring the Vim window to the foreground.
+ */
+ void
+gui_mch_set_foreground()
+{
+ /* TODO */
+}
+#endif
+
+/*
+ * Draw a cursor without focus.
+ */
+ void
+gui_mch_draw_hollow_cursor(color)
+ guicolor_T color;
+{
+ Rect rc;
+
+ gui_mch_set_fg_color(color);
+
+ /*
+ * Note: FrameRect() excludes right and bottom of rectangle.
+ */
+ rc.left = FILL_X(gui.col);
+ rc.top = FILL_Y(gui.row);
+ rc.right = rc.left + gui.char_width;
+ rc.bottom = rc.top + gui.char_height;
+
+ gui_mch_set_fg_color(color);
+
+ FrameRect (&rc);
+}
+
+/*
+ * Draw part of a cursor, only w pixels wide, and h pixels high.
+ */
+ void
+gui_mch_draw_part_cursor(w, h, color)
+ int w;
+ int h;
+ guicolor_T color;
+{
+ Rect rc;
+
+#ifdef FEAT_RIGHTLEFT
+ /* vertical line should be on the right of current point */
+ if (CURSOR_BAR_RIGHT)
+ rc.left = FILL_X(gui.col + 1) - w;
+ else
+#endif
+ rc.left = FILL_X(gui.col);
+ rc.top = FILL_Y(gui.row) + gui.char_height - h;
+ rc.right = rc.left + w;
+ rc.bottom = rc.top + h;
+
+ gui_mch_set_fg_color(color);
+
+ PaintRect (&rc);
+}
+
+
+
+/*
+ * Catch up with any queued X events. This may put keyboard input into the
+ * input buffer, call resize call-backs, trigger timers etc. If there is
+ * nothing in the X event queue (& no timers pending), then we return
+ * immediately.
+ */
+ void
+gui_mch_update()
+{
+ /* TODO: find what to do
+ * maybe call gui_mch_wait_for_chars (0)
+ * more like look at EventQueue then
+ * call heart of gui_mch_wait_for_chars;
+ *
+ * if (eventther)
+ * gui_mac_handle_event(&event);
+ */
+ EventRecord theEvent;
+
+ if (EventAvail (everyEvent, &theEvent))
+ if (theEvent.what != nullEvent)
+ gui_mch_wait_for_chars(0);
+}
+
+/*
+ * Simple wrapper to neglect more easily the time
+ * spent inside WaitNextEvent while profiling.
+ */
+
+#if defined(__MWERKS__) /* only in Codewarrior */
+# pragma profile reset
+#endif
+ pascal
+ Boolean
+WaitNextEventWrp (EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
+{
+ if (((long) sleep) < -1)
+ sleep = 32767;
+ return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
+}
+
+/*
+ * GUI input routine called by gui_wait_for_chars(). Waits for a character
+ * from the keyboard.
+ * wtime == -1 Wait forever.
+ * wtime == 0 This should never happen.
+ * wtime > 0 Wait wtime milliseconds for a character.
+ * Returns OK if a character was found to be available within the given time,
+ * or FAIL otherwise.
+ */
+#if defined(__MWERKS__) /* only in Codewarrior */
+# pragma profile reset
+#endif
+ int
+gui_mch_wait_for_chars(wtime)
+ int wtime;
+{
+ EventMask mask = (everyEvent);
+ EventRecord event;
+ long entryTick;
+ long currentTick;
+ long sleeppyTick;
+
+ /* If we are providing life feedback with the scrollbar,
+ * we don't want to try to wait for an event, or else
+ * there won't be any life feedback.
+ */
+ if (dragged_sb != NULL)
+ return FAIL;
+ /* TODO: Check if FAIL is the proper return code */
+
+ entryTick = TickCount();
+
+ allow_scrollbar = TRUE;
+
+ do
+ {
+/* if (dragRectControl == kCreateEmpty)
+ {
+ dragRgn = NULL;
+ dragRectControl = kNothing;
+ }
+ else*/ if (dragRectControl == kCreateRect)
+ {
+ dragRgn = cursorRgn;
+ RectRgn (dragRgn, &dragRect);
+ dragRectControl = kNothing;
+ }
+ /*
+ * Don't use gui_mch_update() because then we will spin-lock until a
+ * char arrives, instead we use WaitNextEventWrp() to hang until an
+ * event arrives. No need to check for input_buf_full because we are
+ * returning as soon as it contains a single char.
+ */
+ /* TODO: reduce wtime accordinly??? */
+ if (wtime > -1)
+ sleeppyTick = 60*wtime/1000;
+ else
+ sleeppyTick = 32767;
+ if (WaitNextEventWrp (mask, &event, sleeppyTick, dragRgn))
+ {
+#ifdef USE_SIOUX
+ if (!SIOUXHandleOneEvent(&event))
+#endif
+ gui_mac_handle_event (&event);
+ if (input_available())
+ {
+ allow_scrollbar = FALSE;
+ return OK;
+ }
+ }
+ currentTick = TickCount();
+ }
+ while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
+
+ allow_scrollbar = FALSE;
+ return FAIL;
+}
+
+#if defined(__MWERKS__) /* only in Codewarrior */
+# pragma profile reset
+#endif
+
+/*
+ * Output routines.
+ */
+
+/* Flush any output to the screen */
+ void
+gui_mch_flush()
+{
+ /* TODO: Is anything needed here? */
+}
+
+/*
+ * Clear a rectangular region of the screen from text pos (row1, col1) to
+ * (row2, col2) inclusive.
+ */
+ void
+gui_mch_clear_block(row1, col1, row2, col2)
+ int row1;
+ int col1;
+ int row2;
+ int col2;
+{
+ Rect rc;
+
+ /*
+ * Clear one extra pixel at the far right, for when bold characters have
+ * spilled over to the next column.
+ */
+ rc.left = FILL_X(col1);
+ rc.top = FILL_Y(row1);
+ rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
+ rc.bottom = FILL_Y(row2 + 1);
+
+ gui_mch_set_bg_color(gui.back_pixel);
+ EraseRect (&rc);
+}
+
+/*
+ * Clear the whole text window.
+ */
+ void
+gui_mch_clear_all()
+{
+ Rect rc;
+
+ rc.left = 0;
+ rc.top = 0;
+ rc.right = Columns * gui.char_width + 2 * gui.border_width;
+ rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
+
+ gui_mch_set_bg_color(gui.back_pixel);
+ EraseRect(&rc);
+/* gui_mch_set_fg_color(gui.norm_pixel);
+ FrameRect(&rc);
+*/
+}
+
+/*
+ * Delete the given number of lines from the given row, scrolling up any
+ * text further down within the scroll region.
+ */
+ void
+gui_mch_delete_lines(row, num_lines)
+ int row;
+ int num_lines;
+{
+ Rect rc;
+
+ /* changed without checking! */
+ rc.left = FILL_X(gui.scroll_region_left);
+ rc.right = FILL_X(gui.scroll_region_right + 1);
+ rc.top = FILL_Y(row);
+ rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
+
+ gui_mch_set_bg_color(gui.back_pixel);
+ ScrollRect (&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
+
+ gui_clear_block(gui.scroll_region_bot - num_lines + 1,
+ gui.scroll_region_left,
+ gui.scroll_region_bot, gui.scroll_region_right);
+}
+
+/*
+ * Insert the given number of lines before the given row, scrolling down any
+ * following text within the scroll region.
+ */
+ void
+gui_mch_insert_lines(row, num_lines)
+ int row;
+ int num_lines;
+{
+ Rect rc;
+
+ rc.left = FILL_X(gui.scroll_region_left);
+ rc.right = FILL_X(gui.scroll_region_right + 1);
+ rc.top = FILL_Y(row);
+ rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
+
+ gui_mch_set_bg_color(gui.back_pixel);
+
+ ScrollRect (&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
+
+ /* Update gui.cursor_row if the cursor scrolled or copied over */
+ if (gui.cursor_row >= gui.row
+ && gui.cursor_col >= gui.scroll_region_left
+ && gui.cursor_col <= gui.scroll_region_right)
+ {
+ if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
+ gui.cursor_row += num_lines;
+ else if (gui.cursor_row <= gui.scroll_region_bot)
+ gui.cursor_is_valid = FALSE;
+ }
+
+ gui_clear_block(row, gui.scroll_region_left,
+ row + num_lines - 1, gui.scroll_region_right);
+}
+
+ /*
+ * TODO: add a vim format to the clipboard which remember
+ * LINEWISE, CHARWISE, BLOCKWISE
+ */
+
+ void
+clip_mch_request_selection(cbd)
+ VimClipboard *cbd;
+{
+
+ Handle textOfClip;
+#ifdef USE_CARBONIZED
+ Size scrapSize;
+ ScrapFlavorFlags scrapFlags;
+ ScrapRef scrap = nil;
+ OSStatus error;
+#else
+ long scrapOffset;
+ long scrapSize;
+#endif
+ int type;
+ char *searchCR;
+ char_u *tempclip;
+
+
+#ifdef USE_CARBONIZED
+ error = GetCurrentScrap (&scrap);
+ if (error != noErr)
+ return;
+
+ error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeText, &scrapFlags);
+ if (error != noErr)
+ return;
+
+ error = GetScrapFlavorSize (scrap, kScrapFlavorTypeText, &scrapSize);
+ if (error != noErr)
+ return;
+
+ ReserveMem (scrapSize);
+#else
+ /* Call to LoadScrap seem to avoid problem with crash on first paste */
+ scrapSize = LoadScrap();
+ scrapSize = GetScrap(nil, 'TEXT', &scrapOffset);
+
+ if (scrapSize > 0)
+#endif
+ {
+#ifdef USE_CARBONIZED
+ /* In CARBON we don't need a Handle, a pointer is good */
+ textOfClip = NewHandle (scrapSize);
+ /* tempclip = lalloc(scrapSize+1, TRUE); */
+#else
+ textOfClip = NewHandle(0);
+#endif
+ HLock (textOfClip);
+#ifdef USE_CARBONIZED
+ error = GetScrapFlavorData (scrap, kScrapFlavorTypeText, &scrapSize, *textOfClip);
+#else
+ scrapSize = GetScrap(textOfClip, 'TEXT', &scrapOffset);
+#endif
+
+ type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
+
+ tempclip = lalloc(scrapSize+1, TRUE);
+ STRNCPY(tempclip, *textOfClip, scrapSize);
+ tempclip[scrapSize] = 0;
+
+ searchCR = (char *)tempclip;
+ while (searchCR != NULL)
+ {
+ searchCR = strchr(searchCR, '\r');
+
+ if (searchCR != NULL)
+ searchCR[0] = '\n';
+
+ }
+
+#ifdef FEAT_MBYTE
+ if (input_conv.vc_type != CONV_NONE)
+ {
+ char_u *to;
+ int l = scrapSize;
+
+ to = string_convert(&input_conv, tempclip, &l);
+ if (to != NULL)
+ {
+ vim_free(tempclip);
+ tempclip = to;
+ scrapSize = l;
+ }
+ }
+#endif
+ clip_yank_selection(type, tempclip, scrapSize, cbd);
+
+ vim_free(tempclip);
+ HUnlock(textOfClip);
+
+ DisposeHandle(textOfClip);
+ }
+}
+
+ void
+clip_mch_lose_selection(cbd)
+ VimClipboard *cbd;
+{
+ /*
+ * TODO: Really nothing to do?
+ */
+}
+
+ int
+clip_mch_own_selection(cbd)
+ VimClipboard *cbd;
+{
+ return OK;
+}
+
+/*
+ * Send the current selection to the clipboard.
+ */
+ void
+clip_mch_set_selection(cbd)
+ VimClipboard *cbd;
+{
+ Handle textOfClip;
+ long scrapSize;
+ int type;
+#ifdef USE_CARBONIZED
+ ScrapRef scrap;
+#endif
+
+ char_u *str = NULL;
+
+ if (!cbd->owned)
+ return;
+
+ clip_get_selection(cbd);
+
+ /*
+ * Once we set the clipboard, lose ownership. If another application sets
+ * the clipboard, we don't want to think that we still own it.
+ *
+ */
+
+ cbd->owned = FALSE;
+
+ type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd);
+
+#ifdef FEAT_MBYTE
+ if (str != NULL && output_conv.vc_type != CONV_NONE)
+ {
+ char_u *to;
+ int l = scrapSize;
+
+ to = string_convert(&output_conv, str, &l);
+ if (to != NULL)
+ {
+ vim_free(str);
+ str = to;
+ scrapSize = l;
+ }
+ }
+#endif
+
+ if (type >= 0)
+ {
+#ifdef USE_CARBONIZED
+ ClearCurrentScrap();
+#else
+ ZeroScrap();
+#endif
+
+ textOfClip = NewHandle(scrapSize);
+ HLock(textOfClip);
+
+ STRNCPY(*textOfClip, str, scrapSize);
+#ifdef USE_CARBONIZED
+ GetCurrentScrap (&scrap);
+ PutScrapFlavor(scrap, kScrapFlavorTypeText, kScrapFlavorMaskNone,
+ scrapSize, *textOfClip);
+#else
+ PutScrap(scrapSize, 'TEXT', *textOfClip);
+#endif
+ HUnlock(textOfClip);
+ DisposeHandle(textOfClip);
+ }
+
+ vim_free(str);
+}
+
+ void
+gui_mch_set_text_area_pos(x, y, w, h)
+ int x;
+ int y;
+ int w;
+ int h;
+{
+ Rect VimBound;
+
+/* HideWindow (gui.VimWindow); */
+#ifdef USE_CARBONIZED
+ GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
+#else
+ VimBound = gui.VimWindow->portRect;
+#endif
+
+ if (gui.which_scrollbars[SBAR_LEFT])
+ {
+ VimBound.left = -gui.scrollbar_width + 1;
+ }
+ else
+ {
+ VimBound.left = 0;
+ }
+
+#ifdef USE_CARBONIZED
+ SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
+#endif
+
+ ShowWindow (gui.VimWindow);
+}
+
+/*
+ * Menu stuff.
+ */
+
+ void
+gui_mch_enable_menu(flag)
+ int flag;
+{
+ /*
+ * Menu is always active in itself
+ * (maybe we should only disable a vim menu
+ * and keep standard menu)
+ *
+ */
+}
+
+ void
+gui_mch_set_menu_pos(x, y, w, h)
+ int x;
+ int y;
+ int w;
+ int h;
+{
+ /*
+ * The menu is always at the top of the screen
+ * Maybe a futur version will permit a menu in the window
+ *
+ */
+}
+
+/*
+ * Add a sub menu to the menu bar.
+ */
+ void
+gui_mch_add_menu(menu, idx)
+ vimmenu_T *menu;
+ int idx;
+{
+ /*
+ * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
+ * TODO: use menu->mnemonic and menu->actext
+ * TODO: Try to reuse menu id
+ * Carbon Help suggest to use only id between 1 and 235
+ */
+ static long next_avail_id = 128;
+ long menu_after_me = 0; /* Default to the end */
+ char_u *name;
+ short index;
+ vimmenu_T *parent = menu->parent;
+ vimmenu_T *brother = menu->next;
+
+ /* Cannot add a menu if ... */
+ if ((parent != NULL && parent->submenu_id == 0))
+ return;
+
+ /* menu ID greater than 1024 are reserved for ??? */
+ if (next_avail_id == 1024)
+ return;
+
+ /* My brother could be the PopUp, find my real brother */
+ while ((brother != NULL) && (!menu_is_menubar(brother->name)))
+ brother = brother->next;
+
+ /* Find where to insert the menu (for MenuBar) */
+ if ((parent == NULL) && (brother != NULL))
+ menu_after_me = brother->submenu_id;
+
+ /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
+ if (!menu_is_menubar(menu->name))
+ menu_after_me = hierMenu;
+
+ /* Convert the name */
+ name = C2Pascal_save(menu->dname);
+ if (name == NULL)
+ return;
+
+ /* Create the menu unless it's the help menu */
+#ifdef USE_HELPMENU
+ if (STRNCMP(name, "\4Help", 5) == 0)
+ {
+ menu->submenu_id = kHMHelpMenuID;
+ menu->submenu_handle = gui.MacOSHelpMenu;
+ }
+ else
+#endif
+ {
+ /* Carbon suggest use of
+ * OSStatus CreateNewMenu ( MenuID, MenuAttributes, MenuRef *);
+ * OSStatus SetMenuTitle ( MenuRef, ConstStr255Param title );
+ */
+ menu->submenu_id = next_avail_id;
+ menu->submenu_handle = NewMenu (menu->submenu_id, name);
+ next_avail_id++;
+ }
+
+ if (parent == NULL)
+ {
+ /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
+
+ /* TODO: Verify if we could only Insert Menu if really part of the
+ * menubar The Inserted menu are scanned or the Command-key combos
+ */
+
+ /* Insert the menu unless it's the Help menu */
+#ifdef USE_HELPMENU
+ if (menu->submenu_id != kHMHelpMenuID)
+#endif
+ InsertMenu (menu->submenu_handle, menu_after_me); /* insert before */
+#if 1
+ /* Vim should normally update it. TODO: verify */
+ DrawMenuBar();
+#endif
+ }
+ else
+ {
+ /* Adding as a submenu */
+
+ index = gui_mac_get_menu_item_index (menu);
+
+ /* Call InsertMenuItem followed by SetMenuItemText
+ * to avoid special character recognition by InsertMenuItem
+ */
+ InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
+ SetMenuItemText(parent->submenu_handle, idx+1, name);
+ SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
+ SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
+ InsertMenu(menu->submenu_handle, hierMenu);
+ }
+
+ vim_free (name);
+
+#if 0
+ /* Done by Vim later on */
+ DrawMenuBar();
+#endif
+}
+
+/*
+ * Add a menu item to a menu
+ */
+ void
+gui_mch_add_menu_item(menu, idx)
+ vimmenu_T *menu;
+ int idx;
+{
+ char_u *name;
+ vimmenu_T *parent = menu->parent;
+ int menu_inserted;
+
+ /* Cannot add item, if the menu have not been created */
+ if (parent->submenu_id == 0)
+ return;
+
+ /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
+ for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
+
+ /* Convert the name */
+ name = C2Pascal_save(menu->dname);
+
+ /* Where are just a menu item, so no handle, no id */
+ menu->submenu_id = 0;
+ menu->submenu_handle = NULL;
+
+#ifdef USE_HELPMENU
+ /* The index in the help menu are offseted */
+ if (parent->submenu_id == kHMHelpMenuID)
+ idx += gui.MacOSHelpItems;
+#endif
+
+ menu_inserted = 0;
+ if (menu->actext)
+ {
+ /* If the accelerator text for the menu item looks like it describes
+ * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
+ * item's command equivalent.
+ */
+ int key = 0;
+ int modifiers = 0;
+ char_u *p_actext;
+
+ p_actext = menu->actext;
+ key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
+ if (*p_actext != 0)
+ key = 0; /* error: trailing text */
+ /* find_special_key() returns a keycode with as many of the
+ * specified modifiers as appropriate already applied (e.g., for
+ * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
+ * as the only modifier). Since we want to display all of the
+ * modifiers, we need to convert the keycode back to a printable
+ * character plus modifiers.
+ * TODO: Write an alternative find_special_key() that doesn't
+ * apply modifiers.
+ */
+ if (key > 0 && key < 32)
+ {
+ /* Convert a control key to an uppercase letter. Note that
+ * by this point it is no longer possible to distinguish
+ * between, e.g., Ctrl-S and Ctrl-Shift-S.
+ */
+ modifiers |= MOD_MASK_CTRL;
+ key += '@';
+ }
+ /* If the keycode is an uppercase letter, set the Shift modifier.
+ * If it is a lowercase letter, don't set the modifier, but convert
+ * the letter to uppercase for display in the menu.
+ */
+ else if (key >= 'A' && key <= 'Z')
+ modifiers |= MOD_MASK_SHIFT;
+ else if (key >= 'a' && key <= 'z')
+ key += 'A' - 'a';
+ /* Note: keycodes below 0x22 are reserved by Apple. */
+ if (key >= 0x22 && vim_isprintc_strict(key))
+ {
+ int valid = 1;
+ char_u mac_mods = kMenuNoModifiers;
+ /* Convert Vim modifier codes to Menu Manager equivalents. */
+ if (modifiers & MOD_MASK_SHIFT)
+ mac_mods |= kMenuShiftModifier;
+ if (modifiers & MOD_MASK_CTRL)
+ mac_mods |= kMenuControlModifier;
+ if (!(modifiers & MOD_MASK_CMD))
+ mac_mods |= kMenuNoCommandModifier;
+ if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
+ valid = 0; /* TODO: will Alt someday map to Option? */
+ if (valid)
+ {
+ char_u item_txt[10];
+ /* Insert the menu item after idx, with its command key. */
+ item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
+ item_txt[3] = key;
+ InsertMenuItem(parent->submenu_handle, item_txt, idx);
+ /* Set the modifier keys. */
+ SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
+ menu_inserted = 1;
+ }
+ }
+ }
+ /* Call InsertMenuItem followed by SetMenuItemText
+ * to avoid special character recognition by InsertMenuItem
+ */
+ if (!menu_inserted)
+ InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
+ /* Set the menu item name. */
+ SetMenuItemText(parent->submenu_handle, idx+1, name);
+
+#if 0
+ /* Called by Vim */
+ DrawMenuBar();
+#endif
+
+ /* TODO: Can name be freed? */
+ vim_free(name);
+}
+
+ void
+gui_mch_toggle_tearoffs(enable)
+ int enable;
+{
+ /* no tearoff menus */
+}
+
+/*
+ * Destroy the machine specific menu widget.
+ */
+ void
+gui_mch_destroy_menu(menu)
+ vimmenu_T *menu;
+{
+ short index = gui_mac_get_menu_item_index (menu);
+
+ if (index > 0)
+ {
+ if (menu->parent)
+ {
+#ifdef USE_HELPMENU
+ if (menu->parent->submenu_handle != nil) /*gui.MacOSHelpMenu)*/
+#endif
+ {
+ /* For now just don't delete help menu items. (Huh? Dany) */
+ DeleteMenuItem (menu->parent->submenu_handle, index);
+
+ /* Delete the Menu if it was a hierarchical Menu */
+ if (menu->submenu_id != 0)
+ {
+ DeleteMenu (menu->submenu_id);
+ DisposeMenu (menu->submenu_handle);
+ }
+ }
+#ifdef USE_HELPMENU
+# ifdef DEBUG_MAC_MENU
+ else
+ {
+ printf ("gmdm 1\n");
+ }
+# endif
+#endif
+ }
+#ifdef DEBUG_MAC_MENU
+ else
+ {
+ printf ("gmdm 2\n");
+ }
+#endif
+ }
+ else
+ {
+ /* Do not delete the Help Menu */
+#ifdef USE_HELPMENU
+ if (menu->submenu_id != kHMHelpMenuID)
+#endif
+ {
+ DeleteMenu (menu->submenu_id);
+ DisposeMenu (menu->submenu_handle);
+ }
+ }
+ /* Shouldn't this be already done by Vim. TODO: Check */
+ DrawMenuBar();
+}
+
+/*
+ * Make a menu either grey or not grey.
+ */
+ void
+gui_mch_menu_grey(menu, grey)
+ vimmenu_T *menu;
+ int grey;
+{
+ /* TODO: Check if menu really exists */
+ short index = gui_mac_get_menu_item_index (menu);
+/*
+ index = menu->index;
+*/
+ if (grey)
+ {
+ if (menu->children)
+ DisableMenuItem(menu->submenu_handle, index);
+ if (menu->parent)
+ if (menu->parent->submenu_handle)
+ DisableMenuItem(menu->parent->submenu_handle, index);
+ }
+ else
+ {
+ if (menu->children)
+ EnableMenuItem(menu->submenu_handle, index);
+ if (menu->parent)
+ if (menu->parent->submenu_handle)
+ EnableMenuItem(menu->parent->submenu_handle, index);
+ }
+}
+
+/*
+ * Make menu item hidden or not hidden
+ */
+ void
+gui_mch_menu_hidden(menu, hidden)
+ vimmenu_T *menu;
+ int hidden;
+{
+ /* There's no hidden mode on MacOS */
+ gui_mch_menu_grey (menu, hidden);
+}
+
+
+/*
+ * This is called after setting all the menus to grey/hidden or not.
+ */
+ void
+gui_mch_draw_menubar()
+{
+ DrawMenuBar();
+}
+
+
+/*
+ * Scrollbar stuff.
+ */
+
+ void
+gui_mch_enable_scrollbar(sb, flag)
+ scrollbar_T *sb;
+ int flag;
+{
+ if (flag)
+ ShowControl(sb->id);
+ else
+ HideControl(sb->id);
+
+#ifdef DEBUG_MAC_SB
+ printf ("enb_sb (%x) %x\n",sb->id, flag);
+#endif
+}
+
+ void
+gui_mch_set_scrollbar_thumb(sb, val, size, max)
+ scrollbar_T *sb;
+ long val;
+ long size;
+ long max;
+{
+ SetControl32BitMaximum (sb->id, max);
+ SetControl32BitMinimum (sb->id, 0);
+ SetControl32BitValue (sb->id, val);
+#ifdef DEBUG_MAC_SB
+ printf ("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
+#endif
+}
+
+ void
+gui_mch_set_scrollbar_pos(sb, x, y, w, h)
+ scrollbar_T *sb;
+ int x;
+ int y;
+ int w;
+ int h;
+{
+ gui_mch_set_bg_color(gui.back_pixel);
+/* if (gui.which_scrollbars[SBAR_LEFT])
+ {
+ MoveControl (sb->id, x-16, y);
+ SizeControl (sb->id, w + 1, h);
+ }
+ else
+ {
+ MoveControl (sb->id, x, y);
+ SizeControl (sb->id, w + 1, h);
+ }*/
+ if (sb == &gui.bottom_sbar)
+ h += 1;
+ else
+ w += 1;
+
+ if (gui.which_scrollbars[SBAR_LEFT])
+ x -= 15;
+
+ MoveControl (sb->id, x, y);
+ SizeControl (sb->id, w, h);
+#ifdef DEBUG_MAC_SB
+ printf ("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
+#endif
+}
+
+ void
+gui_mch_create_scrollbar(sb, orient)
+ scrollbar_T *sb;
+ int orient; /* SBAR_VERT or SBAR_HORIZ */
+{
+ Rect bounds;
+
+ bounds.top = -16;
+ bounds.bottom = -10;
+ bounds.right = -10;
+ bounds.left = -16;
+
+ sb->id = NewControl (gui.VimWindow,
+ &bounds,
+ "\pScrollBar",
+ TRUE,
+ 0, /* current*/
+ 0, /* top */
+ 0, /* bottom */
+#ifdef USE_CARBONIZED
+ kControlScrollBarLiveProc,
+#else
+ scrollBarProc,
+#endif
+ (long) sb->ident);
+#ifdef DEBUG_MAC_SB
+ printf ("create_sb (%x) %x\n",sb->id, orient);
+#endif
+}
+
+ void
+gui_mch_destroy_scrollbar(sb)
+ scrollbar_T *sb;
+{
+ gui_mch_set_bg_color(gui.back_pixel);
+ DisposeControl (sb->id);
+#ifdef DEBUG_MAC_SB
+ printf ("dest_sb (%x) \n",sb->id);
+#endif
+}
+
+
+/*
+ * Cursor blink functions.
+ *
+ * This is a simple state machine:
+ * BLINK_NONE not blinking at all
+ * BLINK_OFF blinking, cursor is not shown
+ * BLINK_ON blinking, cursor is shown
+ */
+ void
+gui_mch_set_blinking(long wait, long on, long off)
+{
+ /* TODO: TODO: TODO: TODO: */
+/* blink_waittime = wait;
+ blink_ontime = on;
+ blink_offtime = off;*/
+}
+
+/*
+ * Stop the cursor blinking. Show the cursor if it wasn't shown.
+ */
+ void
+gui_mch_stop_blink()
+{
+ gui_update_cursor(TRUE, FALSE);
+ /* TODO: TODO: TODO: TODO: */
+/* gui_w32_rm_blink_timer();
+ if (blink_state == BLINK_OFF)
+ gui_update_cursor(TRUE, FALSE);
+ blink_state = BLINK_NONE;*/
+}
+
+/*
+ * Start the cursor blinking. If it was already blinking, this restarts the
+ * waiting time and shows the cursor.
+ */
+ void
+gui_mch_start_blink()
+{
+ gui_update_cursor(TRUE, FALSE);
+ /* TODO: TODO: TODO: TODO: */
+/* gui_w32_rm_blink_timer(); */
+
+ /* Only switch blinking on if none of the times is zero */
+/* if (blink_waittime && blink_ontime && blink_offtime)
+ {
+ blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
+ (TIMERPROC)_OnBlinkTimer);
+ blink_state = BLINK_ON;
+ gui_update_cursor(TRUE, FALSE);
+ }*/
+}
+
+/*
+ * Return the RGB value of a pixel as long.
+ */
+ long_u
+gui_mch_get_rgb(guicolor_T pixel)
+{
+ return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
+}
+
+
+
+#ifdef FEAT_BROWSE
+/*
+ * Pop open a file browser and return the file selected, in allocated memory,
+ * or NULL if Cancel is hit.
+ * saving - TRUE if the file will be saved to, FALSE if it will be opened.
+ * title - Title message for the file browser dialog.
+ * dflt - Default name of file.
+ * ext - Default extension to be added to files without extensions.
+ * initdir - directory in which to open the browser (NULL = current dir)
+ * filter - Filter for matched files to choose from.
+ * Has a format like this:
+ * "C Files (*.c)\0*.c\0"
+ * "All Files\0*.*\0\0"
+ * If these two strings were concatenated, then a choice of two file
+ * filters will be selectable to the user. Then only matching files will
+ * be shown in the browser. If NULL, the default allows all files.
+ *
+ * *NOTE* - the filter string must be terminated with TWO nulls.
+ */
+ char_u *
+gui_mch_browse(
+ int saving,
+ char_u *title,
+ char_u *dflt,
+ char_u *ext,
+ char_u *initdir,
+ char_u *filter)
+{
+#if defined (USE_NAVIGATION_SERVICE) || defined (USE_CARBONIZED)
+ /* TODO: Add Ammon's safety checl (Dany) */
+ NavReplyRecord reply;
+ char_u *fname = NULL;
+ char_u **fnames = NULL;
+ long numFiles;
+ NavDialogOptions navOptions;
+ OSErr error;
+
+ /* Get Navigation Service Defaults value */
+ NavGetDefaultDialogOptions (&navOptions);
+
+
+ /* TODO: If we get a :browse args, set the Multiple bit. */
+ navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
+ | kNavDontAutoTranslate
+ | kNavDontAddTranslateItems
+ /* | kNavAllowMultipleFiles */
+ | kNavAllowStationery;
+
+ (void) C2PascalString (title, &navOptions.message);
+ (void) C2PascalString (dflt, &navOptions.savedFileName);
+ /* Could set clientName?
+ * windowTitle? (there's no title bar?)
+ */
+
+ if (saving)
+ {
+ /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
+ NavPutFile (NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
+ if (!reply.validRecord)
+ return NULL;
+ }
+ else
+ {
+ /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
+ NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
+ if (!reply.validRecord)
+ return NULL;
+ }
+
+ fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
+
+ NavDisposeReply (&reply);
+
+ if (fnames)
+ {
+ fname = fnames[0];
+ vim_free(fnames);
+ }
+
+ /* TODO: Shorten the file name if possible */
+ return fname;
+#else
+ SFTypeList fileTypes;
+ StandardFileReply reply;
+ Str255 Prompt;
+ Str255 DefaultName;
+ Str255 Directory;
+
+ /* TODO: split dflt in path and filename */
+
+ (void) C2PascalString (title, &Prompt);
+ (void) C2PascalString (dflt, &DefaultName);
+ (void) C2PascalString (initdir, &Directory);
+
+ if (saving)
+ {
+ /* Use a custon filter instead of nil FAQ 9-4 */
+ StandardPutFile (Prompt, DefaultName, &reply);
+ if (!reply.sfGood)
+ return NULL;
+ }
+ else
+ {
+ StandardGetFile (nil, -1, fileTypes, &reply);
+ if (!reply.sfGood)
+ return NULL;
+ }
+
+ /* Work fine but append a : for new file */
+ return (FullPathFromFSSpec_save (reply.sfFile));
+
+ /* Shorten the file name if possible */
+/* mch_dirname(IObuff, IOSIZE);
+ p = shorten_fname(fileBuf, IObuff);
+ if (p == NULL)
+ p = fileBuf;
+ return vim_strsave(p);
+*/
+#endif
+}
+#endif /* FEAT_BROWSE */
+
+#ifdef FEAT_GUI_DIALOG
+/*
+ * Stuff for dialogues
+ */
+
+/*
+ * Create a dialogue dynamically from the parameter strings.
+ * type = type of dialogue (question, alert, etc.)
+ * title = dialogue title. may be NULL for default title.
+ * message = text to display. Dialogue sizes to accommodate it.
+ * buttons = '\n' separated list of button captions, default first.
+ * dfltbutton = number of default button.
+ *
+ * This routine returns 1 if the first button is pressed,
+ * 2 for the second, etc.
+ *
+ * 0 indicates Esc was pressed.
+ * -1 for unexpected error
+ *
+ * If stubbing out this fn, return 1.
+ */
+
+typedef struct
+{
+ short idx;
+ short width; /* Size of the text in pixel */
+ Rect box;
+} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
+
+#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
+
+ static void
+macMoveDialogItem(
+ DialogRef theDialog,
+ short itemNumber,
+ short X,
+ short Y,
+ Rect *inBox)
+{
+#if 0 /* USE_CARBONIZED */
+ /* Untested */
+ MoveDialogItem (theDialog, itemNumber, X, Y);
+ if (inBox != nil)
+ GetDialogItem (theDialog, itemNumber, &itemType, &itemHandle, inBox);
+#else
+ short itemType;
+ Handle itemHandle;
+ Rect localBox;
+ Rect *itemBox = &localBox;
+
+ if (inBox != nil)
+ itemBox = inBox;
+
+ GetDialogItem (theDialog, itemNumber, &itemType, &itemHandle, itemBox);
+ OffsetRect (itemBox, -itemBox->left, -itemBox->top);
+ OffsetRect (itemBox, X, Y);
+ /* To move a control (like a button) we need to call both
+ * MoveControl and SetDialogItem. FAQ 6-18 */
+ if (1) /*(itemType & kControlDialogItem) */
+ MoveControl ((ControlRef) itemHandle, X, Y);
+ SetDialogItem (theDialog, itemNumber, itemType, itemHandle, itemBox);
+#endif
+}
+
+ static void
+macSizeDialogItem(
+ DialogRef theDialog,
+ short itemNumber,
+ short width,
+ short height)
+{
+ short itemType;
+ Handle itemHandle;
+ Rect itemBox;
+
+ GetDialogItem (theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
+
+ /* When width or height is zero do not change it */
+ if (width == 0)
+ width = itemBox.right - itemBox.left;
+ if (height == 0)
+ height = itemBox.bottom - itemBox.top;
+
+#if 0 /* USE_CARBONIZED */
+ SizeDialogItem (theDialog, itemNumber, width, height); /* Untested */
+#else
+ /* Resize the bounding box */
+ itemBox.right = itemBox.left + width;
+ itemBox.bottom = itemBox.top + height;
+
+ /* To resize a control (like a button) we need to call both
+ * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
+ if (itemType & kControlDialogItem)
+ SizeControl ((ControlRef) itemHandle, width, height);
+
+ /* Configure back the item */
+ SetDialogItem (theDialog, itemNumber, itemType, itemHandle, &itemBox);
+#endif
+}
+
+ static void
+macSetDialogItemText(
+ DialogRef theDialog,
+ short itemNumber,
+ Str255 itemName)
+{
+ short itemType;
+ Handle itemHandle;
+ Rect itemBox;
+
+ GetDialogItem (theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
+
+ if (itemType & kControlDialogItem)
+ SetControlTitle ((ControlRef) itemHandle, itemName);
+ else
+ SetDialogItemText (itemHandle, itemName);
+}
+
+ int
+gui_mch_dialog(
+ int type,
+ char_u *title,
+ char_u *message,
+ char_u *buttons,
+ int dfltbutton,
+ char_u *textfield)
+{
+ Handle buttonDITL;
+ Handle iconDITL;
+ Handle inputDITL;
+ Handle messageDITL;
+ Handle itemHandle;
+ Handle iconHandle;
+ DialogPtr theDialog;
+ char_u len;
+ char_u PascalTitle[256]; /* place holder for the title */
+ char_u name[256];
+ GrafPtr oldPort;
+ short itemHit;
+ char_u *buttonChar;
+ Rect box;
+ short button;
+ short lastButton;
+ short itemType;
+ short useIcon;
+ short width;
+ short totalButtonWidth = 0; /* the width of all button together incuding spacing */
+ short widestButton = 0;
+ short dfltButtonEdge = 20; /* gut feeling */
+ short dfltElementSpacing = 13; /* from IM:V.2-29 */
+ short dfltIconSideSpace = 23; /* from IM:V.2-29 */
+ short maximumWidth = 400; /* gut feeling */
+ short maxButtonWidth = 175; /* gut feeling */
+
+ short vertical;
+ short dialogHeight;
+ short messageLines = 3;
+ FontInfo textFontInfo;
+
+ vgmDlgItm iconItm;
+ vgmDlgItm messageItm;
+ vgmDlgItm inputItm;
+ vgmDlgItm buttonItm;
+
+ WindowRef theWindow;
+
+ /* Check 'v' flag in 'guioptions': vertical button placement. */
+ vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
+
+ /* Create a new Dialog Box from template. */
+ theDialog = GetNewDialog (129, nil, (WindowRef) -1);
+
+ /* Get the WindowRef */
+ theWindow = GetDialogWindow(theDialog);
+
+ /* Hide the window.
+ * 1. to avoid seeing slow drawing
+ * 2. to prevent a problem seen while moving dialog item
+ * within a visible window. (non-Carbon MacOS 9)
+ * Could be avoided by changing the resource.
+ */
+ HideWindow (theWindow);
+
+ /* Change the graphical port to the dialog,
+ * so we can measure the text with the proper font */
+ GetPort (&oldPort);
+#ifdef USE_CARBONIZED
+ SetPortDialogPort (theDialog);
+#else
+ SetPort (theDialog);
+#endif
+
+ /* Get the info about the default text,
+ * used to calculate the height of the message
+ * and of the text field */
+ GetFontInfo(&textFontInfo);
+
+ /* Set the dialog title */
+ if (title != NULL)
+ {
+ (void) C2PascalString (title, &PascalTitle);
+ SetWTitle (theWindow, PascalTitle);
+ }
+
+ /* Creates the buttons and add them to the Dialog Box. */
+ buttonDITL = GetResource ('DITL', 130);
+ buttonChar = buttons;
+ button = 0;
+
+ for (;*buttonChar != 0;)
+ {
+ /* Get the name of the button */
+ button++;
+ len = 0;
+ for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
+ {
+ if (*buttonChar != DLG_HOTKEY_CHAR)
+ name[++len] = *buttonChar;
+ }
+ if (*buttonChar != 0)
+ buttonChar++;
+ name[0] = len;
+
+ /* Add the button */
+ AppendDITL (theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
+
+ /* Change the button's name */
+ macSetDialogItemText (theDialog, button, name);
+
+ /* Resize the button to fit its name */
+ width = StringWidth (name) + 2 * dfltButtonEdge;
+ /* Limite the size of any button to an acceptable value. */
+ /* TODO: Should be based on the message width */
+ if (width > maxButtonWidth)
+ width = maxButtonWidth;
+ macSizeDialogItem (theDialog, button, width, 0);
+
+ totalButtonWidth += width;
+
+ if (width > widestButton)
+ widestButton = width;
+ }
+ ReleaseResource (buttonDITL);
+ lastButton = button;
+
+ /* Add the icon to the Dialog Box. */
+ iconItm.idx = lastButton + 1;
+ iconDITL = GetResource ('DITL', 131);
+ switch (type)
+ {
+ case VIM_GENERIC: useIcon = kNoteIcon;
+ case VIM_ERROR: useIcon = kStopIcon;
+ case VIM_WARNING: useIcon = kCautionIcon;
+ case VIM_INFO: useIcon = kNoteIcon;
+ case VIM_QUESTION: useIcon = kNoteIcon;
+ default: useIcon = kStopIcon;
+ };
+ AppendDITL (theDialog, iconDITL, overlayDITL);
+ ReleaseResource (iconDITL);
+ GetDialogItem (theDialog, iconItm.idx, &itemType, &itemHandle, &box);
+ /* TODO: Should the item be freed? */
+ iconHandle = GetIcon (useIcon);
+ SetDialogItem (theDialog, iconItm.idx, itemType, iconHandle, &box);
+
+ /* Add the message to the Dialog box. */
+ messageItm.idx = lastButton + 2;
+ messageDITL = GetResource ('DITL', 132);
+ AppendDITL (theDialog, messageDITL, overlayDITL);
+ ReleaseResource (messageDITL);
+ GetDialogItem (theDialog, messageItm.idx, &itemType, &itemHandle, &box);
+ (void) C2PascalString (message, &name);
+ SetDialogItemText (itemHandle, name);
+ messageItm.width = StringWidth (name);
+
+ /* Add the input box if needed */
+ if (textfield != NULL)
+ {
+ /* Cheat for now reuse the message and convet to text edit */
+ inputItm.idx = lastButton + 3;
+ inputDITL = GetResource ('DITL', 132);
+ AppendDITL (theDialog, inputDITL, overlayDITL);
+ ReleaseResource (inputDITL);
+ GetDialogItem (theDialog, inputItm.idx, &itemType, &itemHandle, &box);
+/* SetDialogItem (theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
+ (void) C2PascalString (textfield, &name);
+ SetDialogItemText (itemHandle, name);
+ inputItm.width = StringWidth (name);
+ }
+
+ /* Set the <ENTER> and <ESC> button. */
+ SetDialogDefaultItem (theDialog, dfltbutton);
+ SetDialogCancelItem (theDialog, 0);
+
+ /* Reposition element */
+
+ /* Check if we need to force vertical */
+ if (totalButtonWidth > maximumWidth)
+ vertical = TRUE;
+
+ /* Place icon */
+ macMoveDialogItem (theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
+ iconItm.box.right = box.right;
+ iconItm.box.bottom = box.bottom;
+
+ /* Place Message */
+ messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
+ macSizeDialogItem (theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
+ macMoveDialogItem (theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
+
+ /* Place Input */
+ if (textfield != NULL)
+ {
+ inputItm.box.left = messageItm.box.left;
+ inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
+ macSizeDialogItem (theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
+ macMoveDialogItem (theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
+ /* Convert the static text into a text edit.
+ * For some reason this change need to be done last (Dany) */
+ GetDialogItem (theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
+ SetDialogItem (theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
+ SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
+ }
+
+ /* Place Button */
+ if (textfield != NULL)
+ {
+ buttonItm.box.left = inputItm.box.left;
+ buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
+ }
+ else
+ {
+ buttonItm.box.left = messageItm.box.left;
+ buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
+ }
+
+ for (button=1; button <= lastButton; button++)
+ {
+
+ macMoveDialogItem (theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
+ /* With vertical, it's better to have all button the same lenght */
+ if (vertical)
+ {
+ macSizeDialogItem (theDialog, button, widestButton, 0);
+ GetDialogItem (theDialog, button, &itemType, &itemHandle, &box);
+ }
+ /* Calculate position of next button */
+ if (vertical)
+ buttonItm.box.top = box.bottom + dfltElementSpacing;
+ else
+ buttonItm.box.left = box.right + dfltElementSpacing;
+ }
+
+ /* Resize the dialog box */
+ dialogHeight = box.bottom + dfltElementSpacing;
+ SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
+
+#ifdef USE_CARBONIZED
+ /* Magic resize */
+ AutoSizeDialog (theDialog);
+ /* Need a horizontal resize anyway so not that useful */
+#endif
+
+ /* Display it */
+ ShowWindow(theWindow);
+/* BringToFront(theWindow); */
+ SelectWindow(theWindow);
+
+/* DrawDialog (theDialog); */
+#if 0
+ GetPort (&oldPort);
+#ifdef USE_CARBONIZED
+ SetPortDialogPort (theDialog);
+#else
+ SetPort (theDialog);
+#endif
+#endif
+
+ /* Hang until one of the button is hit */
+ do
+ {
+ ModalDialog (nil, &itemHit);
+ } while ((itemHit < 1) || (itemHit > lastButton));
+
+ /* Copy back the text entered by the user into the param */
+ if (textfield != NULL)
+ {
+ GetDialogItem (theDialog, inputItm.idx, &itemType, &itemHandle, &box);
+ GetDialogItemText (itemHandle, (char_u *) &name);
+#if IOSIZE < 256
+ /* Truncate the name to IOSIZE if needed */
+ if (name[0] > IOSIZE)
+ name[0] = IOSIZE - 1;
+#endif
+ STRNCPY(textfield, &name[1], name[0]);
+ textfield[name[0]] = NUL;
+ }
+
+ /* Restore the original graphical port */
+ SetPort (oldPort);
+
+ /* Get ride of th edialog (free memory) */
+ DisposeDialog (theDialog);
+
+ return itemHit;
+/*
+ * Usefull thing which could be used
+ * SetDialogTimeout(): Auto click a button after timeout
+ * SetDialogTracksCursor() : Get the I-beam cursor over input box
+ * MoveDialogItem(): Probably better than SetDialogItem
+ * SizeDialogItem(): (but is it Carbon Only?)
+ * AutoSizeDialog(): Magic resize of dialog based on text lenght
+ */
+}
+#endif /* FEAT_DIALOG_GUI */
+
+/*
+ * Display the saved error message(s).
+ */
+#ifdef USE_MCH_ERRMSG
+ void
+display_errors()
+{
+ char *p;
+ char_u pError[256];
+
+ if (error_ga.ga_data != NULL)
+ {
+ /* avoid putting up a message box with blanks only */
+ for (p = (char *)error_ga.ga_data; *p; ++p)
+ if (!isspace(*p))
+ {
+ if (STRLEN(p) > 255)
+ pError[0] = 255;
+ else
+ pError[0] = STRLEN(p);
+
+ STRNCPY(&pError[1], p, pError[0]);
+ ParamText (pError, nil, nil, nil);
+ Alert (128, nil);
+ break;
+ /* TODO: handled message longer than 256 chars
+ * use auto-sizeable alert
+ * or dialog with scrollbars (TextEdit zone)
+ */
+ }
+ ga_clear(&error_ga);
+ }
+}
+#endif
+
+/*
+ * Get current y mouse coordinate in text window.
+ * Return -1 when unknown.
+ */
+ int
+gui_mch_get_mouse_x()
+{
+ Point where;
+
+ GetMouse(&where);
+
+ return (where.h);
+}
+
+ int
+gui_mch_get_mouse_y()
+{
+ Point where;
+
+ GetMouse(&where);
+
+ return (where.v);
+}
+
+ void
+gui_mch_setmouse(x, y)
+ int x;
+ int y;
+{
+ /* TODO */
+#if 0
+ /* From FAQ 3-11 */
+
+ CursorDevicePtr myMouse;
+ Point where;
+
+ if ( NGetTrapAddress (_CursorDeviceDispatch, ToolTrap)
+ != NGetTrapAddress (_Unimplemented, ToolTrap) )
+ {
+ /* New way */
+
+ /*
+ * Get first devoice with one button.
+ * This will probably be the standad mouse
+ * startat head of cursor dev list
+ *
+ */
+
+ myMouse = nil;
+
+ do
+ {
+ /* Get the next cursor device */
+ CursorDeviceNextDevice(&myMouse);
+ }
+ while ( (myMouse != nil) && (myMouse->cntButtons != 1) );
+
+ CursorDeviceMoveTo (myMouse, x, y);
+ }
+ else
+ {
+ /* Old way */
+ where.h = x;
+ where.v = y;
+
+ *(Point *)RawMouse = where;
+ *(Point *)MTemp = where;
+ *(Ptr) CrsrNew = 0xFFFF;
+ }
+#endif
+}
+
+ void
+gui_mch_show_popupmenu(menu)
+ vimmenu_T *menu;
+{
+#ifdef USE_CTRLCLICKMENU
+/*
+ * Clone PopUp to use menu
+ * Create a object descriptor for the current selection
+ * Call the procedure
+ */
+
+ MenuHandle CntxMenu;
+ Point where;
+ OSStatus status;
+ UInt32 CntxType;
+ SInt16 CntxMenuID;
+ UInt16 CntxMenuItem;
+ Str255 HelpName = "";
+ GrafPtr savePort;
+
+ /* Save Current Port: On MacOS X we seem to lose the port */
+ GetPort (&savePort); /*OSX*/
+
+ GetMouse (&where);
+ LocalToGlobal (&where); /*OSX*/
+ CntxMenu = menu->submenu_handle;
+
+ /* TODO: Get the text selection from Vim */
+
+ /* Call to Handle Popup */
+ status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
+
+ if (status == noErr)
+ {
+ if (CntxType == kCMMenuItemSelected)
+ {
+ /* Handle the menu CntxMenuID, CntxMenuItem */
+ /* The submenu can be handle directly by gui_mac_handle_menu */
+ /* But what about the current menu, is the menu changed by ContextualMenuSelect */
+ gui_mac_handle_menu ((CntxMenuID << 16) + CntxMenuItem);
+ }
+ else if (CntxMenuID == kCMShowHelpSelected)
+ {
+ /* Should come up with the help */
+ }
+ }
+
+ /* Restore original Port */
+ SetPort (savePort); /*OSX*/
+#endif
+}
+
+#if defined(FEAT_CW_EDITOR) || defined(PROTO)
+/* TODO: Is it need for MACOS_X? (Dany) */
+ void
+mch_post_buffer_write(buf_T *buf)
+{
+# ifdef USE_SIOUX
+ printf ("Writing Buf...\n");
+# endif
+ GetFSSpecFromPath (buf->b_ffname, &buf->b_FSSpec);
+ Send_KAHL_MOD_AE (buf);
+}
+#endif
+
+#ifdef FEAT_TITLE
+/*
+ * Set the window title and icon.
+ * (The icon is not taken care of).
+ */
+ void
+gui_mch_settitle(title, icon)
+ char_u *title;
+ char_u *icon;
+{
+ /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
+ * that 256. Even better get it to fit nicely in the titlebar.
+ */
+ char_u *pascalTitle;
+
+ if (title == NULL) /* nothing to do */
+ return;
+
+ pascalTitle = C2Pascal_save(title);
+ if (pascalTitle != NULL)
+ {
+ SetWTitle(gui.VimWindow, pascalTitle);
+ vim_free(pascalTitle);
+ }
+}
+#endif
+
+/*
+ * Transfered from os_mac.c for MacOS X using os_unix.c prep work
+ */
+
+ int
+C2PascalString (CString, PascalString)
+ char_u *CString;
+ Str255 *PascalString;
+{
+ char_u *PascalPtr = (char_u *) PascalString;
+ int len;
+ int i;
+
+ PascalPtr[0] = 0;
+ if (CString == NULL)
+ return 0;
+
+ len = STRLEN(CString);
+ if (len > 255)
+ len = 255;
+
+ for (i = 0; i < len; i++)
+ PascalPtr[i+1] = CString[i];
+
+ PascalPtr[0] = len;
+
+ return 0;
+}
+
+ int
+GetFSSpecFromPath (file, fileFSSpec)
+ char_u *file;
+ FSSpec *fileFSSpec;
+{
+ /* From FAQ 8-12 */
+ Str255 filePascal;
+ CInfoPBRec myCPB;
+ OSErr err;
+
+ (void) C2PascalString (file, &filePascal);
+
+ myCPB.dirInfo.ioNamePtr = filePascal;
+ myCPB.dirInfo.ioVRefNum = 0;
+ myCPB.dirInfo.ioFDirIndex = 0;
+ myCPB.dirInfo.ioDrDirID = 0;
+
+ err= PBGetCatInfo (&myCPB, false);
+
+ /* vRefNum, dirID, name */
+ FSMakeFSSpec (0, 0, filePascal, fileFSSpec);
+
+ /* TODO: Use an error code mechanism */
+ return 0;
+}
+
+/*
+ * Convert a FSSpec to a fuill path
+ */
+
+char_u *FullPathFromFSSpec_save (FSSpec file)
+{
+ /*
+ * TODO: Add protection for 256 char max.
+ */
+
+ CInfoPBRec theCPB;
+ char_u fname[256];
+ char_u *filenamePtr = fname;
+ OSErr error;
+ int folder = 1;
+#ifdef USE_UNIXFILENAME
+ SInt16 dfltVol_vRefNum;
+ SInt32 dfltVol_dirID;
+ FSRef refFile;
+ OSStatus status;
+ UInt32 pathSize = 256;
+ char_u pathname[256];
+ char_u *path = pathname;
+#else
+ Str255 directoryName;
+ char_u temporary[255];
+ char_u *temporaryPtr = temporary;
+#endif
+
+#ifdef USE_UNIXFILENAME
+ /* Get the default volume */
+ /* TODO: Remove as this only work if Vim is on the Boot Volume*/
+ error=HGetVol ( NULL, &dfltVol_vRefNum, &dfltVol_dirID );
+
+ if (error)
+ return NULL;
+#endif
+
+ /* Start filling fname with file.name */
+ STRNCPY(filenamePtr, &file.name[1], file.name[0]);
+ filenamePtr[file.name[0]] = 0; /* NULL terminate the string */
+
+ /* Get the info about the file specified in FSSpec */
+ theCPB.dirInfo.ioFDirIndex = 0;
+ theCPB.dirInfo.ioNamePtr = file.name;
+ theCPB.dirInfo.ioVRefNum = file.vRefNum;
+ /*theCPB.hFileInfo.ioDirID = 0;*/
+ theCPB.dirInfo.ioDrDirID = file.parID;
+
+ /* As ioFDirIndex = 0, get the info of ioNamePtr,
+ which is relative to ioVrefNum, ioDirID */
+ error = PBGetCatInfo (&theCPB, false);
+
+ /* If we are called for a new file we expect fnfErr */
+ if ((error) && (error != fnfErr))
+ return NULL;
+
+ /* Check if it's a file or folder */
+ /* default to file if file don't exist */
+ if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
+ folder = 0; /* It's not a folder */
+ else
+ folder = 1;
+
+#ifdef USE_UNIXFILENAME
+ /*
+ * The function used here are available in Carbon, but
+ * do nothing une MacOS 8 and 9
+ */
+ if (error == fnfErr)
+ {
+ /* If the file to be saved does not already exist, it isn't possible
+ to convert its FSSpec into an FSRef. But we can construct an
+ FSSpec for the file's parent folder (since we have its volume and
+ directory IDs), and since that folder does exist, we can convert
+ that FSSpec into an FSRef, convert the FSRef in turn into a path,
+ and, finally, append the filename. */
+ FSSpec dirSpec;
+ FSRef dirRef;
+ Str255 emptyFilename = "\p";
+ error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
+ theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
+ if (error)
+ return NULL;
+
+ error = FSpMakeFSRef(&dirSpec, &dirRef);
+ if (error)
+ return NULL;
+
+ status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
+ if (status)
+ return NULL;
+
+ STRCAT(path, "/");
+ STRCAT(path, filenamePtr);
+ }
+ else
+ {
+ /* If the file to be saved already exists, we can get its full path
+ by converting its FSSpec into an FSRef. */
+ error=FSpMakeFSRef (&file, &refFile);
+ if (error)
+ return NULL;
+
+ status=FSRefMakePath (&refFile, (UInt8 *) path, pathSize);
+ if (status)
+ return NULL;
+ }
+
+ /* Add a slash at the end if needed */
+ if (folder)
+ STRCAT (path, "/");
+
+ return (vim_strsave (path));
+#else
+ /* TODO: Get rid of all USE_UNIXFILENAME below */
+ /* Set ioNamePtr, it's the same area which is always reused. */
+ theCPB.dirInfo.ioNamePtr = directoryName;
+
+ /* Trick for first entry, set ioDrParID to the first value
+ * we want for ioDrDirID*/
+ theCPB.dirInfo.ioDrParID = file.parID;
+ theCPB.dirInfo.ioDrDirID = file.parID;
+
+ if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/ ))
+ do
+ {
+ theCPB.dirInfo.ioFDirIndex = -1;
+ /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
+ theCPB.dirInfo.ioVRefNum = file.vRefNum;
+ /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
+ theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
+
+ /* As ioFDirIndex = -1, get the info of ioDrDirID, */
+ /* *ioNamePtr[0 TO 31] will be updated */
+ error = PBGetCatInfo (&theCPB,false);
+
+ if (error)
+ return NULL;
+
+ /* Put the new directoryName in front of the current fname */
+ STRCPY(temporaryPtr, filenamePtr);
+ STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
+ filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
+ STRCAT(filenamePtr, ":");
+ STRCAT(filenamePtr, temporaryPtr);
+ }
+#if 1 /* def USE_UNIXFILENAME */
+ while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
+ /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
+#else
+ while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
+#endif
+
+ /* Get the information about the volume on which the file reside */
+ theCPB.dirInfo.ioFDirIndex = -1;
+ /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
+ theCPB.dirInfo.ioVRefNum = file.vRefNum;
+ /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
+ theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
+
+ /* As ioFDirIndex = -1, get the info of ioDrDirID, */
+ /* *ioNamePtr[0 TO 31] will be updated */
+ error = PBGetCatInfo (&theCPB,false);
+
+ if (error)
+ return NULL;
+
+ /* For MacOS Classic always add the volume name */
+ /* For MacOS X add the volume name preceded by "Volumes" */
+ /* when we are not refering to the boot volume */
+#ifdef USE_UNIXFILENAME
+ if (file.vRefNum != dfltVol_vRefNum)
+#endif
+ {
+ /* Add the volume name */
+ STRCPY(temporaryPtr, filenamePtr);
+ STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
+ filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
+ STRCAT(filenamePtr, ":");
+ STRCAT(filenamePtr, temporaryPtr);
+
+#ifdef USE_UNIXFILENAME
+ STRCPY(temporaryPtr, filenamePtr);
+ filenamePtr[0] = 0; /* NULL terminate the string */
+ STRCAT(filenamePtr, "Volumes:");
+ STRCAT(filenamePtr, temporaryPtr);
+#endif
+ }
+
+ /* Append final path separator if it's a folder */
+ if (folder)
+ STRCAT (fname, ":");
+
+ /* As we use Unix File Name for MacOS X convert it */
+#ifdef USE_UNIXFILENAME
+ /* Need to insert leading / */
+ /* TODO: get the above code to use directly the / */
+ STRCPY(&temporaryPtr[1], filenamePtr);
+ temporaryPtr[0] = '/';
+ STRCPY(filenamePtr, temporaryPtr);
+ {
+ char *p;
+ for (p = fname; *p; p++)
+ if (*p == ':')
+ *p = '/';
+ }
+#endif
+
+ return (vim_strsave (fname));
+#endif
+}
+
+#if defined(USE_IM_CONTROL) || defined(PROTO)
+/*
+ * Input Method Control functions.
+ */
+
+/*
+ * Notify cursor position to IM.
+ */
+ void
+im_set_position(int row, int col)
+{
+ /* TODO: Implement me! */
+}
+
+/*
+ * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
+ */
+ void
+im_set_active(int active)
+{
+ KeyScript(active ? smKeySysScript : smKeyRoman);
+}
+
+/*
+ * Get IM status. When IM is on, return not 0. Else return 0.
+ */
+ int
+im_get_status()
+{
+ SInt32 script = GetScriptManagerVariable(smKeyScript);
+ return (script != smRoman
+ && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
+}
+#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */
diff --git a/src/gui_mac.icns b/src/gui_mac.icns
new file mode 100644
index 000000000..b65fa11d8
--- /dev/null
+++ b/src/gui_mac.icns
Binary files differ
diff --git a/src/gui_mac.r b/src/gui_mac.r
new file mode 100644
index 000000000..7a1916bd0
--- /dev/null
+++ b/src/gui_mac.r
@@ -0,0 +1,33 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read a list of people who contributed.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+#ifdef environ_os_mac /* or 1 for Carbon, 0 for non-Carbon */
+# include <Carbon/Carbon.r>
+#else
+# include <SysTypes.r>
+# include <Types.r>
+#endif
+#include "version.h"
+
+/* Used as application version */
+resource 'vers' (1) {
+ VIM_VERSION_MAJOR, VIM_VERSION_BUILD_BCD, VIM_VERSION_RELEASE, VIM_VERSION_PATCHLEVEL,
+ verUS,
+ VIM_VERSION_MEDIUM,
+ VIM_VERSION_LONG_DATE $$date " " $$time ")"
+};
+
+/* Used as application group version */
+resource 'vers' (2) {
+ VIM_VERSION_MAJOR, VIM_VERSION_BUILD_BCD, VIM_VERSION_RELEASE, VIM_VERSION_PATCHLEVEL,
+ verUS,
+ VIM_VERSION_MEDIUM,
+ VIM_VERSION_LONG
+};
+
+/* TODO: Small About box with compile time */
diff --git a/src/gui_motif.c b/src/gui_motif.c
new file mode 100644
index 000000000..4fe26ec57
--- /dev/null
+++ b/src/gui_motif.c
@@ -0,0 +1,3090 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI/Motif support by Robert Webb
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include <Xm/Form.h>
+#include <Xm/RowColumn.h>
+#include <Xm/PushB.h>
+#include <Xm/Text.h>
+#include <Xm/TextF.h>
+#include <Xm/Separator.h>
+#include <Xm/Label.h>
+#include <Xm/CascadeB.h>
+#include <Xm/ScrollBar.h>
+#include <Xm/MenuShell.h>
+#include <Xm/DrawingA.h>
+#if (XmVersion >= 1002)
+# include <Xm/RepType.h>
+#endif
+#include <Xm/Frame.h>
+#include <Xm/LabelG.h>
+#include <Xm/ToggleBG.h>
+#include <Xm/SeparatoG.h>
+
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <X11/StringDefs.h>
+#include <X11/Intrinsic.h>
+
+#include "vim.h"
+
+#ifdef HAVE_X11_XPM_H
+# include <X11/xpm.h>
+#else
+# ifdef HAVE_XM_XPMP_H
+# include <Xm/XpmP.h>
+# endif
+#endif
+
+#if defined(FEAT_GUI_DIALOG) && defined(HAVE_XPM)
+# include "../pixmaps/alert.xpm"
+# include "../pixmaps/error.xpm"
+# include "../pixmaps/generic.xpm"
+# include "../pixmaps/info.xpm"
+# include "../pixmaps/quest.xpm"
+#endif
+
+#define MOTIF_POPUP
+
+extern Widget vimShell;
+
+static Widget vimForm;
+static Widget textAreaForm;
+Widget textArea;
+#ifdef FEAT_TOOLBAR
+static Widget toolBarFrame;
+static Widget toolBar;
+#endif
+#ifdef FEAT_FOOTER
+static Widget footer;
+#endif
+#ifdef FEAT_MENU
+# if (XmVersion >= 1002)
+/* remember the last set value for the tearoff item */
+static int tearoff_val = (int)XmTEAR_OFF_ENABLED;
+# endif
+static Widget menuBar;
+#endif
+
+static void scroll_cb __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
+#ifdef FEAT_TOOLBAR
+# if 0
+static void toolbar_enter_cb __ARGS((Widget, XtPointer, XEvent *, Boolean *));
+static void toolbar_leave_cb __ARGS((Widget, XtPointer, XEvent *, Boolean *));
+# endif
+# ifdef FEAT_FOOTER
+static void toolbarbutton_enter_cb __ARGS((Widget, XtPointer, XEvent *, Boolean *));
+static void toolbarbutton_leave_cb __ARGS((Widget, XtPointer, XEvent *, Boolean *));
+# endif
+static void gui_mch_reset_focus __ARGS((void));
+#endif
+#ifdef FEAT_FOOTER
+static int gui_mch_compute_footer_height __ARGS((void));
+#endif
+#ifdef WSDEBUG
+static void attachDump(Widget, char *);
+#endif
+
+static void gui_motif_menu_colors __ARGS((Widget id));
+static void gui_motif_scroll_colors __ARGS((Widget id));
+#ifdef FEAT_MENU
+static void gui_motif_menu_fontlist __ARGS((Widget id));
+#endif
+
+#if (XmVersion >= 1002)
+# define STRING_TAG XmFONTLIST_DEFAULT_TAG
+#else
+# define STRING_TAG XmSTRING_DEFAULT_CHARSET
+#endif
+
+/*
+ * Call-back routines.
+ */
+
+/* ARGSUSED */
+ static void
+scroll_cb(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data, call_data;
+{
+ scrollbar_T *sb;
+ long value;
+ int dragging;
+
+ sb = gui_find_scrollbar((long)client_data);
+
+ value = ((XmScrollBarCallbackStruct *)call_data)->value;
+ dragging = (((XmScrollBarCallbackStruct *)call_data)->reason ==
+ (int)XmCR_DRAG);
+ gui_drag_scrollbar(sb, value, dragging);
+}
+
+
+/*
+ * End of call-back routines
+ */
+
+/*
+ * Create all the motif widgets necessary.
+ */
+ void
+gui_x11_create_widgets()
+{
+ /*
+ * Start out by adding the configured border width into the border offset
+ */
+ gui.border_offset = gui.border_width;
+
+ /*
+ * Install the tearOffModel resource converter.
+ */
+#if (XmVersion >= 1002)
+ XmRepTypeInstallTearOffModelConverter();
+#endif
+
+ /* Make sure the "Quit" menu entry of the window manager is ignored */
+ XtVaSetValues(vimShell, XmNdeleteResponse, XmDO_NOTHING, NULL);
+
+ vimForm = XtVaCreateManagedWidget("vimForm",
+ xmFormWidgetClass, vimShell,
+ XmNborderWidth, 0,
+ XmNhighlightThickness, 0,
+ XmNshadowThickness, 0,
+ XmNmarginWidth, 0,
+ XmNmarginHeight, 0,
+ XmNresizePolicy, XmRESIZE_ANY,
+ NULL);
+ gui_motif_menu_colors(vimForm);
+
+#ifdef FEAT_MENU
+ {
+ Arg al[7]; /* Make sure there is enough room for arguments! */
+ int ac = 0;
+
+# if (XmVersion >= 1002)
+ XtSetArg(al[ac], XmNtearOffModel, tearoff_val); ac++;
+# endif
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+# ifndef FEAT_TOOLBAR
+ /* Always stick to right hand side. */
+ XtSetArg(al[ac], XmNrightOffset, 0); ac++;
+# endif
+ menuBar = XmCreateMenuBar(vimForm, "menuBar", al, ac);
+ XtManageChild(menuBar);
+
+ /* Remember the default colors, needed for ":hi clear". */
+ XtVaGetValues(menuBar,
+ XmNbackground, &gui.menu_def_bg_pixel,
+ XmNforeground, &gui.menu_def_fg_pixel,
+ NULL);
+ gui_motif_menu_colors(menuBar);
+ }
+#endif
+
+#ifdef FEAT_TOOLBAR
+ /*
+ * Create an empty ToolBar. We should get buttons defined from menu.vim.
+ */
+ toolBarFrame = XtVaCreateWidget("toolBarFrame",
+ xmFrameWidgetClass, vimForm,
+ XmNshadowThickness, 0,
+ XmNmarginHeight, 0,
+ XmNmarginWidth, 0,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ NULL);
+ gui_motif_menu_colors(toolBarFrame);
+
+ toolBar = XtVaCreateManagedWidget("toolBar",
+ xmRowColumnWidgetClass, toolBarFrame,
+ XmNchildType, XmFRAME_WORKAREA_CHILD,
+ XmNrowColumnType, XmWORK_AREA,
+ XmNorientation, XmHORIZONTAL,
+ XmNtraversalOn, False,
+ XmNisHomogeneous, False,
+ XmNpacking, XmPACK_TIGHT,
+ XmNspacing, 0,
+ XmNshadowThickness, 0,
+ XmNhighlightThickness, 0,
+ XmNmarginHeight, 0,
+ XmNmarginWidth, 0,
+ XmNadjustLast, True,
+ NULL);
+ gui_motif_menu_colors(toolBar);
+
+# if 0 /* these don't work, because of the XmNtraversalOn above. */
+ XtAddEventHandler(toolBar, EnterWindowMask, False,
+ toolbar_enter_cb, NULL);
+ XtAddEventHandler(toolBar, LeaveWindowMask, False,
+ toolbar_leave_cb, NULL);
+# endif
+#endif
+
+ textAreaForm = XtVaCreateManagedWidget("textAreaForm",
+ xmFormWidgetClass, vimForm,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNmarginWidth, 0,
+ XmNmarginHeight, 0,
+ XmNresizePolicy, XmRESIZE_ANY,
+ NULL);
+ gui_motif_scroll_colors(textAreaForm);
+
+ textArea = XtVaCreateManagedWidget("textArea",
+ xmDrawingAreaWidgetClass, textAreaForm,
+ XmNforeground, gui.norm_pixel,
+ XmNbackground, gui.back_pixel,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+
+ /*
+ * These take some control away from the user, but avoids making them
+ * add resources to get a decent looking setup.
+ */
+ XmNborderWidth, 0,
+ XmNhighlightThickness, 0,
+ XmNshadowThickness, 0,
+ NULL);
+
+#ifdef FEAT_FOOTER
+ /*
+ * Create the Footer.
+ */
+ footer = XtVaCreateWidget("footer",
+ xmLabelGadgetClass, vimForm,
+ XmNalignment, XmALIGNMENT_BEGINNING,
+ XmNmarginHeight, 0,
+ XmNmarginWidth, 0,
+ XmNtraversalOn, False,
+ XmNrecomputeSize, False,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 5,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ NULL);
+ gui_mch_set_footer((char_u *) "");
+#endif
+
+ /*
+ * Install the callbacks.
+ */
+ gui_x11_callbacks(textArea, vimForm);
+
+ /* Pretend we don't have input focus, we will get an event if we do. */
+ gui.in_focus = FALSE;
+}
+
+/*
+ * Called when the GUI is not going to start after all.
+ */
+ void
+gui_x11_destroy_widgets()
+{
+ textArea = NULL;
+#ifdef FEAT_MENU
+ menuBar = NULL;
+#endif
+}
+
+/*ARGSUSED*/
+ void
+gui_mch_set_text_area_pos(x, y, w, h)
+ int x;
+ int y;
+ int w;
+ int h;
+{
+#ifdef FEAT_TOOLBAR
+ /* Give keyboard focus to the textArea instead of the toolbar. */
+ gui_mch_reset_focus();
+#endif
+}
+
+ void
+gui_x11_set_back_color()
+{
+ if (textArea != NULL)
+#if (XmVersion >= 1002)
+ XmChangeColor(textArea, gui.back_pixel);
+#else
+ XtVaSetValues(textArea,
+ XmNbackground, gui.back_pixel,
+ NULL);
+#endif
+}
+
+/*
+ * Manage dialog centered on pointer. This could be used by the Athena code as
+ * well.
+ */
+static void manage_centered __ARGS((Widget dialog_child));
+
+static void
+manage_centered(dialog_child)
+ Widget dialog_child;
+{
+ Widget shell = XtParent(dialog_child);
+ Window root, child;
+ unsigned int mask;
+ unsigned int width, height, border_width, depth;
+ int x, y, win_x, win_y, maxX, maxY;
+ Boolean mappedWhenManaged;
+
+ /* Temporarily set value of XmNmappedWhenManaged
+ to stop the dialog from popping up right away */
+ XtVaGetValues(shell, XmNmappedWhenManaged, &mappedWhenManaged, 0);
+ XtVaSetValues(shell, XmNmappedWhenManaged, False, 0);
+
+ XtManageChild(dialog_child);
+
+ /* Get the pointer position (x, y) */
+ XQueryPointer(XtDisplay(shell), XtWindow(shell), &root, &child,
+ &x, &y, &win_x, &win_y, &mask);
+
+ /* Translate the pointer position (x, y) into a position for the new
+ window that will place the pointer at its center */
+ XGetGeometry(XtDisplay(shell), XtWindow(shell), &root, &win_x, &win_y,
+ &width, &height, &border_width, &depth);
+ width += 2 * border_width;
+ height += 2 * border_width;
+ x -= width / 2;
+ y -= height / 2;
+
+ /* Ensure that the dialog remains on screen */
+ maxX = XtScreen(shell)->width - width;
+ maxY = XtScreen(shell)->height - height;
+ if (x < 0)
+ x = 0;
+ if (x > maxX)
+ x = maxX;
+ if (y < 0)
+ y = 0;
+ if (y > maxY)
+ y = maxY;
+
+ /* Set desired window position in the DialogShell */
+ XtVaSetValues(shell, XmNx, x, XmNy, y, NULL);
+
+ /* Map the widget */
+ XtMapWidget(shell);
+
+ /* Restore the value of XmNmappedWhenManaged */
+ XtVaSetValues(shell, XmNmappedWhenManaged, mappedWhenManaged, 0);
+}
+
+#if defined(FEAT_MENU) || defined(FEAT_SUN_WORKSHOP) \
+ || defined(FEAT_GUI_DIALOG) || defined(PROTO)
+
+/*
+ * Encapsulate the way an XmFontList is created.
+ */
+ XmFontList
+gui_motif_create_fontlist(font)
+ XFontStruct *font;
+{
+ XmFontList font_list;
+
+# if (XmVersion <= 1001)
+ /* Motif 1.1 method */
+ font_list = XmFontListCreate(font, STRING_TAG);
+# else
+ /* Motif 1.2 method */
+ XmFontListEntry font_list_entry;
+
+ font_list_entry = XmFontListEntryCreate(STRING_TAG, XmFONT_IS_FONT,
+ (XtPointer)font);
+ font_list = XmFontListAppendEntry(NULL, font_list_entry);
+ XmFontListEntryFree(&font_list_entry);
+# endif
+ return font_list;
+}
+
+# if ((XmVersion > 1001) && defined(FEAT_XFONTSET)) || defined(PROTO)
+ XmFontList
+gui_motif_fontset2fontlist(fontset)
+ XFontSet *fontset;
+{
+ XmFontList font_list;
+
+ /* Motif 1.2 method */
+ XmFontListEntry font_list_entry;
+
+ font_list_entry = XmFontListEntryCreate(STRING_TAG,
+ XmFONT_IS_FONTSET,
+ (XtPointer)*fontset);
+ font_list = XmFontListAppendEntry(NULL, font_list_entry);
+ XmFontListEntryFree(&font_list_entry);
+ return font_list;
+}
+# endif
+
+#endif
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Menu stuff.
+ */
+
+static void gui_motif_add_actext __ARGS((vimmenu_T *menu));
+#if (XmVersion >= 1002)
+static void toggle_tearoff __ARGS((Widget wid));
+static void gui_mch_recurse_tearoffs __ARGS((vimmenu_T *menu));
+#endif
+static void gui_mch_submenu_change __ARGS((vimmenu_T *mp, int colors));
+
+static void do_set_mnemonics __ARGS((int enable));
+static int menu_enabled = TRUE;
+
+ void
+gui_mch_enable_menu(flag)
+ int flag;
+{
+ if (flag)
+ {
+ XtManageChild(menuBar);
+#ifdef FEAT_TOOLBAR
+ if (XtIsManaged(XtParent(toolBar)))
+ {
+ /* toolBar is attached to top form */
+ XtVaSetValues(XtParent(toolBar),
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, menuBar,
+ NULL);
+ XtVaSetValues(textAreaForm,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, XtParent(toolBar),
+ NULL);
+ }
+ else
+#endif
+ {
+ XtVaSetValues(textAreaForm,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, menuBar,
+ NULL);
+ }
+ }
+ else
+ {
+ XtUnmanageChild(menuBar);
+#ifdef FEAT_TOOLBAR
+ if (XtIsManaged(XtParent(toolBar)))
+ {
+ XtVaSetValues(XtParent(toolBar),
+ XmNtopAttachment, XmATTACH_FORM,
+ NULL);
+ XtVaSetValues(textAreaForm,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, XtParent(toolBar),
+ NULL);
+ }
+ else
+#endif
+ {
+ XtVaSetValues(textAreaForm,
+ XmNtopAttachment, XmATTACH_FORM,
+ NULL);
+ }
+ }
+
+}
+
+/*
+ * Enable or disable mnemonics for the toplevel menus.
+ */
+ void
+gui_motif_set_mnemonics(enable)
+ int enable;
+{
+ /*
+ * Don't enable menu mnemonics when the menu bar is disabled, LessTif
+ * crashes when using a mnemonic then.
+ */
+ if (!menu_enabled)
+ enable = FALSE;
+ do_set_mnemonics(enable);
+}
+
+ static void
+do_set_mnemonics(enable)
+ int enable;
+{
+ vimmenu_T *menu;
+
+ for (menu = root_menu; menu != NULL; menu = menu->next)
+ if (menu->id != (Widget)0)
+ XtVaSetValues(menu->id,
+ XmNmnemonic, enable ? menu->mnemonic : NUL,
+ NULL);
+}
+
+ void
+gui_mch_add_menu(menu, idx)
+ vimmenu_T *menu;
+ int idx;
+{
+ XmString label;
+ Widget shell;
+ vimmenu_T *parent = menu->parent;
+
+#ifdef MOTIF_POPUP
+ if (menu_is_popup(menu->name))
+ {
+ Arg arg[2];
+ int n = 0;
+
+ /* Only create the popup menu when it's actually used, otherwise there
+ * is a delay when using the right mouse button. */
+# if (XmVersion <= 1002)
+ if (mouse_model_popup())
+# endif
+ {
+ if (gui.menu_bg_pixel != INVALCOLOR)
+ {
+ XtSetArg(arg[0], XmNbackground, gui.menu_bg_pixel); n++;
+ }
+ if (gui.menu_fg_pixel != INVALCOLOR)
+ {
+ XtSetArg(arg[1], XmNforeground, gui.menu_fg_pixel); n++;
+ }
+ menu->submenu_id = XmCreatePopupMenu(textArea, "contextMenu",
+ arg, n);
+ menu->id = (Widget)0;
+ }
+ return;
+ }
+#endif
+
+ if (!menu_is_menubar(menu->name)
+ || (parent != NULL && parent->submenu_id == (Widget)0))
+ return;
+
+ label = XmStringCreate((char *)menu->dname, STRING_TAG);
+ if (label == NULL)
+ return;
+ menu->id = XtVaCreateWidget("subMenu",
+ xmCascadeButtonWidgetClass,
+ (parent == NULL) ? menuBar : parent->submenu_id,
+ XmNlabelString, label,
+ XmNmnemonic, p_wak[0] == 'n' ? NUL : menu->mnemonic,
+#if (XmVersion >= 1002)
+ /* submenu: count the tearoff item (needed for LessTif) */
+ XmNpositionIndex, idx + (parent != NULL
+ && tearoff_val == (int)XmTEAR_OFF_ENABLED ? 1 : 0),
+#endif
+ NULL);
+ gui_motif_menu_colors(menu->id);
+ gui_motif_menu_fontlist(menu->id);
+ XmStringFree(label);
+
+ if (menu->id == (Widget)0) /* failed */
+ return;
+
+ /* add accelerator text */
+ gui_motif_add_actext(menu);
+
+ shell = XtVaCreateWidget("subMenuShell",
+ xmMenuShellWidgetClass, menu->id,
+ XmNwidth, 1,
+ XmNheight, 1,
+ NULL);
+ gui_motif_menu_colors(shell);
+ menu->submenu_id = XtVaCreateWidget("rowColumnMenu",
+ xmRowColumnWidgetClass, shell,
+ XmNrowColumnType, XmMENU_PULLDOWN,
+ NULL);
+ gui_motif_menu_colors(menu->submenu_id);
+
+ if (menu->submenu_id == (Widget)0) /* failed */
+ return;
+
+#if (XmVersion >= 1002)
+ /* Set the colors for the tear off widget */
+ toggle_tearoff(menu->submenu_id);
+#endif
+
+ XtVaSetValues(menu->id,
+ XmNsubMenuId, menu->submenu_id,
+ NULL);
+
+ /*
+ * The "Help" menu is a special case, and should be placed at the far
+ * right hand side of the menu-bar. It's recognized by its high priority.
+ */
+ if (parent == NULL && menu->priority >= 9999)
+ XtVaSetValues(menuBar,
+ XmNmenuHelpWidget, menu->id,
+ NULL);
+
+ /*
+ * When we add a top-level item to the menu bar, we can figure out how
+ * high the menu bar should be.
+ */
+ if (parent == NULL)
+ gui_mch_compute_menu_height(menu->id);
+}
+
+
+/*
+ * Add mnemonic and accelerator text to a menu button.
+ */
+ static void
+gui_motif_add_actext(menu)
+ vimmenu_T *menu;
+{
+ XmString label;
+
+ /* Add accelrator text, if there is one */
+ if (menu->actext != NULL && menu->id != (Widget)0)
+ {
+ label = XmStringCreate((char *)menu->actext, STRING_TAG);
+ if (label == NULL)
+ return;
+ XtVaSetValues(menu->id, XmNacceleratorText, label, NULL);
+ XmStringFree(label);
+ }
+}
+
+ void
+gui_mch_toggle_tearoffs(enable)
+ int enable;
+{
+#if (XmVersion >= 1002)
+ if (enable)
+ tearoff_val = (int)XmTEAR_OFF_ENABLED;
+ else
+ tearoff_val = (int)XmTEAR_OFF_DISABLED;
+ toggle_tearoff(menuBar);
+ gui_mch_recurse_tearoffs(root_menu);
+#endif
+}
+
+#if (XmVersion >= 1002)
+/*
+ * Set the tearoff for one menu widget on or off, and set the color of the
+ * tearoff widget.
+ */
+ static void
+toggle_tearoff(wid)
+ Widget wid;
+{
+ Widget w;
+
+ XtVaSetValues(wid, XmNtearOffModel, tearoff_val, NULL);
+ if (tearoff_val == (int)XmTEAR_OFF_ENABLED
+ && (w = XmGetTearOffControl(wid)) != (Widget)0)
+ gui_motif_menu_colors(w);
+}
+
+ static void
+gui_mch_recurse_tearoffs(menu)
+ vimmenu_T *menu;
+{
+ while (menu != NULL)
+ {
+ if (!menu_is_popup(menu->name))
+ {
+ if (menu->submenu_id != (Widget)0)
+ toggle_tearoff(menu->submenu_id);
+ gui_mch_recurse_tearoffs(menu->children);
+ }
+ menu = menu->next;
+ }
+}
+#endif
+
+ int
+gui_mch_text_area_extra_height()
+{
+ Dimension shadowHeight;
+
+ XtVaGetValues(textAreaForm, XmNshadowThickness, &shadowHeight, NULL);
+ return shadowHeight;
+}
+
+/*
+ * Compute the height of the menu bar.
+ * We need to check all the items for their position and height, for the case
+ * there are several rows, and/or some characters extend higher or lower.
+ */
+ void
+gui_mch_compute_menu_height(id)
+ Widget id; /* can be NULL when deleting menu */
+{
+ Dimension y, maxy;
+ Dimension margin, shadow;
+ vimmenu_T *mp;
+ static Dimension height = 21; /* normal height of a menu item */
+
+ /*
+ * Get the height of the new item, before managing it, because it will
+ * still reflect the font size. After managing it depends on the menu
+ * height, which is what we just wanted to get!.
+ */
+ if (id != (Widget)0)
+ XtVaGetValues(id, XmNheight, &height, NULL);
+
+ /* Find any menu Widget, to be able to call XtManageChild() */
+ else
+ for (mp = root_menu; mp != NULL; mp = mp->next)
+ if (mp->id != (Widget)0 && menu_is_menubar(mp->name))
+ {
+ id = mp->id;
+ break;
+ }
+
+ /*
+ * Now manage the menu item, to make them all be positioned (makes an
+ * extra row when needed, removes it when not needed).
+ */
+ if (id != (Widget)0)
+ XtManageChild(id);
+
+ /*
+ * Now find the menu item that is the furthest down, and get it's position.
+ */
+ maxy = 0;
+ for (mp = root_menu; mp != NULL; mp = mp->next)
+ {
+ if (mp->id != (Widget)0 && menu_is_menubar(mp->name))
+ {
+ XtVaGetValues(mp->id, XmNy, &y, NULL);
+ if (y > maxy)
+ maxy = y;
+ }
+ }
+
+ XtVaGetValues(menuBar,
+ XmNmarginHeight, &margin,
+ XmNshadowThickness, &shadow,
+ NULL);
+
+ /*
+ * This computation is the result of trial-and-error:
+ * maxy = The maximum position of an item; required for when there are
+ * two or more rows
+ * height = height of an item, before managing it; Hopefully this will
+ * change with the font height. Includes shadow-border.
+ * shadow = shadow-border; must be subtracted from the height.
+ * margin = margin around the menu buttons; Must be added.
+ * Add 4 for the underlining of shortcut keys.
+ */
+ gui.menu_height = maxy + height - 2 * shadow + 2 * margin + 4;
+
+#ifdef LESSTIF_VERSION
+ /* Somehow the menu bar doesn't resize automatically. Set it here,
+ * even though this is a catch 22. Don't do this when starting up,
+ * somehow the menu gets very high then. */
+ if (gui.shell_created)
+ XtVaSetValues(menuBar, XmNheight, gui.menu_height, NULL);
+#endif
+}
+
+ void
+gui_mch_add_menu_item(menu, idx)
+ vimmenu_T *menu;
+ int idx;
+{
+ XmString label;
+ vimmenu_T *parent = menu->parent;
+
+# ifdef EBCDIC
+ menu->mnemonic = 0;
+# endif
+
+# if (XmVersion <= 1002)
+ /* Don't add Popup menu items when the popup menu isn't used. */
+ if (menu_is_child_of_popup(menu) && !mouse_model_popup())
+ return;
+# endif
+
+# ifdef FEAT_TOOLBAR
+ if (menu_is_toolbar(parent->name))
+ {
+ WidgetClass type;
+ XmString xms = NULL; /* fallback label if pixmap not found */
+ int n;
+ Arg args[18];
+
+ n = 0;
+ if (menu_is_separator(menu->name))
+ {
+ char *cp;
+ Dimension wid;
+
+ /*
+ * A separator has the format "-sep%d[:%d]-". The optional :%d is
+ * a width specifier. If no width is specified then we choose one.
+ */
+ cp = (char *)vim_strchr(menu->name, ':');
+ if (cp != NULL)
+ wid = (Dimension)atoi(++cp);
+ else
+ wid = 4;
+
+#if 0
+ /* We better use a FormWidget here, since it's far more
+ * flexible in terms of size. */
+ type = xmFormWidgetClass;
+ XtSetArg(args[n], XmNwidth, wid); n++;
+#else
+ type = xmSeparatorWidgetClass;
+ XtSetArg(args[n], XmNwidth, wid); n++;
+ XtSetArg(args[n], XmNminWidth, wid); n++;
+ XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
+ XtSetArg(args[n], XmNseparatorType, XmNO_LINE); n++;
+#endif
+ }
+ else
+ {
+ get_toolbar_pixmap(menu, &menu->image, &menu->image_ins);
+ /* Set the label here, so that we can switch between icons/text
+ * by changing the XmNlabelType resource. */
+ xms = XmStringCreate((char *)menu->dname, STRING_TAG);
+ XtSetArg(args[n], XmNlabelString, xms); n++;
+
+#ifndef FEAT_SUN_WORKSHOP
+
+ /* Without shadows one can't sense whatever the button has been
+ * pressed or not! However we wan't to save a bit of space...
+ */
+ XtSetArg(args[n], XmNhighlightThickness, 0); n++;
+ XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
+ XtSetArg(args[n], XmNmarginWidth, 0); n++;
+ XtSetArg(args[n], XmNmarginHeight, 0); n++;
+#endif
+ if (menu->image == 0)
+ {
+ XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
+ XtSetArg(args[n], XmNlabelPixmap, 0); n++;
+ XtSetArg(args[n], XmNlabelInsensitivePixmap, 0); n++;
+ }
+ else
+ {
+ XtSetArg(args[n], XmNlabelPixmap, menu->image); n++;
+ XtSetArg(args[n], XmNlabelInsensitivePixmap, menu->image_ins); n++;
+ XtSetArg(args[n], XmNlabelType, XmPIXMAP); n++;
+ }
+ type = xmPushButtonWidgetClass;
+ XtSetArg(args[n], XmNwidth, 80); n++;
+ }
+
+ XtSetArg(args[n], XmNpositionIndex, idx); n++;
+ if (menu->id == NULL)
+ {
+ menu->id = XtCreateManagedWidget((char *)menu->dname,
+ type, toolBar, args, n);
+ if (menu->id != NULL && type == xmPushButtonWidgetClass)
+ {
+ XtAddCallback(menu->id,
+ XmNactivateCallback, gui_x11_menu_cb, menu);
+
+# ifdef FEAT_FOOTER
+ XtAddEventHandler(menu->id, EnterWindowMask, False,
+ toolbarbutton_enter_cb, menu);
+ XtAddEventHandler(menu->id, LeaveWindowMask, False,
+ toolbarbutton_leave_cb, menu);
+# endif
+ }
+ }
+ else
+ XtSetValues(menu->id, args, n);
+ if (xms != NULL)
+ XmStringFree(xms);
+
+#ifdef FEAT_BEVAL
+ gui_mch_menu_set_tip(menu);
+#endif
+
+ menu->parent = parent;
+ menu->submenu_id = NULL;
+ /* When adding first item to toolbar it might have to be enabled .*/
+ if (!XtIsManaged(XtParent(toolBar))
+ && vim_strchr(p_go, GO_TOOLBAR) != NULL)
+ gui_mch_show_toolbar(TRUE);
+ gui.toolbar_height = gui_mch_compute_toolbar_height();
+ return;
+ } /* toolbar menu item */
+# endif
+
+ /* No parent, must be a non-menubar menu */
+ if (parent->submenu_id == (Widget)0)
+ return;
+
+ menu->submenu_id = (Widget)0;
+
+ /* Add menu separator */
+ if (menu_is_separator(menu->name))
+ {
+ menu->id = XtVaCreateWidget("subMenu",
+ xmSeparatorGadgetClass, parent->submenu_id,
+#if (XmVersion >= 1002)
+ /* count the tearoff item (needed for LessTif) */
+ XmNpositionIndex, idx + (tearoff_val == (int)XmTEAR_OFF_ENABLED
+ ? 1 : 0),
+#endif
+ NULL);
+ gui_motif_menu_colors(menu->id);
+ return;
+ }
+
+ label = XmStringCreate((char *)menu->dname, STRING_TAG);
+ if (label == NULL)
+ return;
+ menu->id = XtVaCreateWidget("subMenu",
+ xmPushButtonWidgetClass, parent->submenu_id,
+ XmNlabelString, label,
+ XmNmnemonic, menu->mnemonic,
+#if (XmVersion >= 1002)
+ /* count the tearoff item (needed for LessTif) */
+ XmNpositionIndex, idx + (tearoff_val == (int)XmTEAR_OFF_ENABLED
+ ? 1 : 0),
+#endif
+ NULL);
+ gui_motif_menu_colors(menu->id);
+ gui_motif_menu_fontlist(menu->id);
+ XmStringFree(label);
+
+ if (menu->id != (Widget)0)
+ {
+ XtAddCallback(menu->id, XmNactivateCallback, gui_x11_menu_cb,
+ (XtPointer)menu);
+ /* add accelerator text */
+ gui_motif_add_actext(menu);
+ }
+}
+
+#if (XmVersion <= 1002) || defined(PROTO)
+/*
+ * This function will destroy/create the popup menus dynamically,
+ * according to the value of 'mousemodel'.
+ * This will fix the "right mouse button freeze" that occurs when
+ * there exists a popup menu but it isn't managed.
+ */
+ void
+gui_motif_update_mousemodel(menu)
+ vimmenu_T *menu;
+{
+ int idx = 0;
+
+ /* When GUI hasn't started the menus have not been created. */
+ if (!gui.in_use)
+ return;
+
+ while (menu)
+ {
+ if (menu->children != NULL)
+ {
+ if (menu_is_popup(menu->name))
+ {
+ if (mouse_model_popup())
+ {
+ /* Popup menu will be used. Create the popup menus. */
+ gui_mch_add_menu(menu, idx);
+ gui_motif_update_mousemodel(menu->children);
+ }
+ else
+ {
+ /* Popup menu will not be used. Destroy the popup menus. */
+ gui_motif_update_mousemodel(menu->children);
+ gui_mch_destroy_menu(menu);
+ }
+ }
+ }
+ else if (menu_is_child_of_popup(menu))
+ {
+ if (mouse_model_popup())
+ gui_mch_add_menu_item(menu, idx);
+ else
+ gui_mch_destroy_menu(menu);
+ }
+ menu = menu->next;
+ ++idx;
+ }
+}
+#endif
+
+ void
+gui_mch_new_menu_colors()
+{
+ if (menuBar == (Widget)0)
+ return;
+ gui_motif_menu_colors(menuBar);
+#ifdef FEAT_TOOLBAR
+ gui_motif_menu_colors(toolBarFrame);
+ gui_motif_menu_colors(toolBar);
+#endif
+
+ gui_mch_submenu_change(root_menu, TRUE);
+}
+
+ void
+gui_mch_new_menu_font()
+{
+ if (menuBar == (Widget)0)
+ return;
+ gui_mch_submenu_change(root_menu, FALSE);
+ {
+ Dimension height;
+ Position w, h;
+
+ XtVaGetValues(menuBar, XmNheight, &height, NULL);
+ gui.menu_height = height;
+
+ XtVaGetValues(vimShell, XtNwidth, &w, XtNheight, &h, NULL);
+ gui_resize_shell(w, h
+#ifdef FEAT_XIM
+ - xim_get_status_area_height()
+#endif
+ );
+ }
+ gui_set_shellsize(FALSE, TRUE);
+ ui_new_shellsize();
+}
+
+#if defined(FEAT_BEVAL) || defined(PROTO)
+ void
+gui_mch_new_tooltip_font()
+{
+# ifdef FEAT_TOOLBAR
+ vimmenu_T *menu;
+
+ if (toolBar == (Widget)0)
+ return;
+
+ menu = gui_find_menu((char_u *)"ToolBar");
+ if (menu != NULL)
+ gui_mch_submenu_change(menu, FALSE);
+# endif
+}
+
+ void
+gui_mch_new_tooltip_colors()
+{
+# ifdef FEAT_TOOLBAR
+ vimmenu_T *toolbar;
+
+ if (toolBar == (Widget)0)
+ return;
+
+ toolbar = gui_find_menu((char_u *)"ToolBar");
+ if (toolbar != NULL)
+ gui_mch_submenu_change(toolbar, TRUE);
+# endif
+}
+#endif
+
+ static void
+gui_mch_submenu_change(menu, colors)
+ vimmenu_T *menu;
+ int colors; /* TRUE for colors, FALSE for font */
+{
+ vimmenu_T *mp;
+
+ for (mp = menu; mp != NULL; mp = mp->next)
+ {
+ if (mp->id != (Widget)0)
+ {
+ if (colors)
+ {
+ gui_motif_menu_colors(mp->id);
+#ifdef FEAT_TOOLBAR
+ /* For a toolbar item: Free the pixmap and allocate a new one,
+ * so that the background color is right. */
+ if (mp->image != (Pixmap)0)
+ {
+ XFreePixmap(gui.dpy, mp->image);
+ XFreePixmap(gui.dpy, mp->image_ins);
+ get_toolbar_pixmap(mp, &mp->image, &mp->image_ins);
+ if (mp->image != (Pixmap)0)
+ XtVaSetValues(mp->id,
+ XmNlabelPixmap, mp->image,
+ XmNlabelInsensitivePixmap, mp->image_ins,
+ NULL);
+ }
+# ifdef FEAT_BEVAL
+ /* If we have a tooltip, then we need to change it's font */
+ if (mp->tip != NULL)
+ {
+ Arg args[2];
+
+ args[0].name = XmNbackground;
+ args[0].value = gui.tooltip_bg_pixel;
+ args[1].name = XmNforeground;
+ args[1].value = gui.tooltip_fg_pixel;
+ XtSetValues(mp->tip->balloonLabel, &args[0], XtNumber(args));
+ }
+# endif
+#endif
+ }
+ else
+ {
+ gui_motif_menu_fontlist(mp->id);
+#ifdef FEAT_BEVAL
+ /* If we have a tooltip, then we need to change it's font */
+ if (mp->tip != NULL)
+ {
+ Arg args[1];
+
+ args[0].name = XmNfontList;
+ args[0].value = (XtArgVal)gui_motif_fontset2fontlist(
+ &gui.tooltip_fontset);
+ XtSetValues(mp->tip->balloonLabel, &args[0], XtNumber(args));
+ }
+#endif
+ }
+ }
+
+ if (mp->children != NULL)
+ {
+#if (XmVersion >= 1002)
+ /* Set the colors/font for the tear off widget */
+ if (mp->submenu_id != (Widget)0)
+ {
+ if (colors)
+ gui_motif_menu_colors(mp->submenu_id);
+ else
+ gui_motif_menu_fontlist(mp->submenu_id);
+ toggle_tearoff(mp->submenu_id);
+ }
+#endif
+ /* Set the colors for the children */
+ gui_mch_submenu_change(mp->children, colors);
+ }
+ }
+}
+
+/*
+ * Destroy the machine specific menu widget.
+ */
+ void
+gui_mch_destroy_menu(menu)
+ vimmenu_T *menu;
+{
+ /* Please be sure to destroy the parent widget first (i.e. menu->id).
+ * On the other hand, problems have been reported that the submenu must be
+ * deleted first...
+ *
+ * This code should be basically identical to that in the file gui_athena.c
+ * because they are both Xt based.
+ */
+ if (menu->submenu_id != (Widget)0)
+ {
+ XtDestroyWidget(menu->submenu_id);
+ menu->submenu_id = (Widget)0;
+ }
+
+ if (menu->id != (Widget)0)
+ {
+ Widget parent;
+
+ parent = XtParent(menu->id);
+#if defined(FEAT_TOOLBAR) && defined(FEAT_BEVAL)
+ if ((parent == toolBar) && (menu->tip != NULL))
+ {
+ /* We try to destroy this before the actual menu, because there are
+ * callbacks, etc. that will be unregistered during the tooltip
+ * destruction.
+ *
+ * If you call "gui_mch_destroy_beval_area()" after destroying
+ * menu->id, then the tooltip's window will have already been
+ * deallocated by Xt, and unknown behaviour will ensue (probably
+ * a core dump).
+ */
+ gui_mch_destroy_beval_area(menu->tip);
+ menu->tip = NULL;
+ }
+#endif
+ XtDestroyWidget(menu->id);
+ menu->id = (Widget)0;
+ if (parent == menuBar)
+ gui_mch_compute_menu_height((Widget)0);
+#ifdef FEAT_TOOLBAR
+ else if (parent == toolBar)
+ {
+ Cardinal num_children;
+
+ /* When removing last toolbar item, don't display the toolbar. */
+ XtVaGetValues(toolBar, XmNnumChildren, &num_children, NULL);
+ if (num_children == 0)
+ gui_mch_show_toolbar(FALSE);
+ else
+ gui.toolbar_height = gui_mch_compute_toolbar_height();
+ }
+#endif
+ }
+}
+
+/* ARGSUSED */
+ void
+gui_mch_show_popupmenu(menu)
+ vimmenu_T *menu;
+{
+#ifdef MOTIF_POPUP
+ XmMenuPosition(menu->submenu_id, gui_x11_get_last_mouse_event());
+ XtManageChild(menu->submenu_id);
+#endif
+}
+
+#endif /* FEAT_MENU */
+
+/*
+ * Set the menu and scrollbar colors to their default values.
+ */
+ void
+gui_mch_def_colors()
+{
+ if (gui.in_use)
+ {
+ /* Use the values saved when starting up. These should come from the
+ * window manager or a resources file. */
+ gui.menu_fg_pixel = gui.menu_def_fg_pixel;
+ gui.menu_bg_pixel = gui.menu_def_bg_pixel;
+ gui.scroll_fg_pixel = gui.scroll_def_fg_pixel;
+ gui.scroll_bg_pixel = gui.scroll_def_bg_pixel;
+#ifdef FEAT_BEVAL
+ gui.tooltip_fg_pixel =
+ gui_get_color((char_u *)gui.rsrc_tooltip_fg_name);
+ gui.tooltip_bg_pixel =
+ gui_get_color((char_u *)gui.rsrc_tooltip_bg_name);
+#endif
+ }
+}
+
+
+/*
+ * Scrollbar stuff.
+ */
+
+ void
+gui_mch_set_scrollbar_thumb(sb, val, size, max)
+ scrollbar_T *sb;
+ long val;
+ long size;
+ long max;
+{
+ if (sb->id != (Widget)0)
+ XtVaSetValues(sb->id,
+ XmNvalue, val,
+ XmNsliderSize, size,
+ XmNpageIncrement, (size > 2 ? size - 2 : 1),
+ XmNmaximum, max + 1, /* Motif has max one past the end */
+ NULL);
+}
+
+ void
+gui_mch_set_scrollbar_pos(sb, x, y, w, h)
+ scrollbar_T *sb;
+ int x;
+ int y;
+ int w;
+ int h;
+{
+ if (sb->id != (Widget)0)
+ {
+ if (sb->type == SBAR_LEFT || sb->type == SBAR_RIGHT)
+ {
+ if (y == 0)
+ h -= gui.border_offset;
+ else
+ y -= gui.border_offset;
+ XtVaSetValues(sb->id,
+ XmNtopOffset, y,
+ XmNbottomOffset, -y - h,
+ XmNwidth, w,
+ NULL);
+ }
+ else
+ XtVaSetValues(sb->id,
+ XmNtopOffset, y,
+ XmNleftOffset, x,
+ XmNrightOffset, gui.which_scrollbars[SBAR_RIGHT]
+ ? gui.scrollbar_width : 0,
+ XmNheight, h,
+ NULL);
+ XtManageChild(sb->id);
+ }
+}
+
+ void
+gui_mch_enable_scrollbar(sb, flag)
+ scrollbar_T *sb;
+ int flag;
+{
+ Arg args[16];
+ int n;
+
+ if (sb->id != (Widget)0)
+ {
+ n = 0;
+ if (flag)
+ {
+ switch (sb->type)
+ {
+ case SBAR_LEFT:
+ XtSetArg(args[n], XmNleftOffset, gui.scrollbar_width); n++;
+ break;
+
+ case SBAR_RIGHT:
+ XtSetArg(args[n], XmNrightOffset, gui.scrollbar_width); n++;
+ break;
+
+ case SBAR_BOTTOM:
+ XtSetArg(args[n], XmNbottomOffset, gui.scrollbar_height);n++;
+ break;
+ }
+ XtSetValues(textArea, args, n);
+ XtManageChild(sb->id);
+ }
+ else
+ {
+ if (!gui.which_scrollbars[sb->type])
+ {
+ /* The scrollbars of this type are all disabled, adjust the
+ * textArea attachment offset. */
+ switch (sb->type)
+ {
+ case SBAR_LEFT:
+ XtSetArg(args[n], XmNleftOffset, 0); n++;
+ break;
+
+ case SBAR_RIGHT:
+ XtSetArg(args[n], XmNrightOffset, 0); n++;
+ break;
+
+ case SBAR_BOTTOM:
+ XtSetArg(args[n], XmNbottomOffset, 0);n++;
+ break;
+ }
+ XtSetValues(textArea, args, n);
+ }
+ XtUnmanageChild(sb->id);
+ }
+ }
+}
+
+ void
+gui_mch_create_scrollbar(sb, orient)
+ scrollbar_T *sb;
+ int orient; /* SBAR_VERT or SBAR_HORIZ */
+{
+ Arg args[16];
+ int n;
+
+ n = 0;
+ XtSetArg(args[n], XmNshadowThickness, 1); n++;
+ XtSetArg(args[n], XmNminimum, 0); n++;
+ XtSetArg(args[n], XmNorientation,
+ (orient == SBAR_VERT) ? XmVERTICAL : XmHORIZONTAL); n++;
+
+ switch (sb->type)
+ {
+ case SBAR_LEFT:
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_OPPOSITE_FORM); n++;
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+ break;
+
+ case SBAR_RIGHT:
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_OPPOSITE_FORM); n++;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
+ break;
+
+ case SBAR_BOTTOM:
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
+ break;
+ }
+
+ sb->id = XtCreateWidget("scrollBar",
+ xmScrollBarWidgetClass, textAreaForm, args, n);
+
+ /* Remember the default colors, needed for ":hi clear". */
+ if (gui.scroll_def_bg_pixel == (guicolor_T)0
+ && gui.scroll_def_fg_pixel == (guicolor_T)0)
+ XtVaGetValues(sb->id,
+ XmNbackground, &gui.scroll_def_bg_pixel,
+ XmNforeground, &gui.scroll_def_fg_pixel,
+ NULL);
+
+ if (sb->id != (Widget)0)
+ {
+ gui_mch_set_scrollbar_colors(sb);
+ XtAddCallback(sb->id, XmNvalueChangedCallback,
+ scroll_cb, (XtPointer)sb->ident);
+ XtAddCallback(sb->id, XmNdragCallback,
+ scroll_cb, (XtPointer)sb->ident);
+ XtAddEventHandler(sb->id, KeyPressMask, FALSE, gui_x11_key_hit_cb,
+ (XtPointer)0);
+ }
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+ void
+gui_mch_destroy_scrollbar(sb)
+ scrollbar_T *sb;
+{
+ if (sb->id != (Widget)0)
+ XtDestroyWidget(sb->id);
+}
+#endif
+
+ void
+gui_mch_set_scrollbar_colors(sb)
+ scrollbar_T *sb;
+{
+ if (sb->id != (Widget)0)
+ {
+ if (gui.scroll_bg_pixel != INVALCOLOR)
+ {
+#if (XmVersion>=1002)
+ XmChangeColor(sb->id, gui.scroll_bg_pixel);
+#else
+ XtVaSetValues(sb->id,
+ XmNtroughColor, gui.scroll_bg_pixel,
+ NULL);
+#endif
+ }
+
+ if (gui.scroll_fg_pixel != INVALCOLOR)
+ XtVaSetValues(sb->id,
+ XmNforeground, gui.scroll_fg_pixel,
+#if (XmVersion<1002)
+ XmNbackground, gui.scroll_fg_pixel,
+#endif
+ NULL);
+ }
+
+ /* This is needed for the rectangle below the vertical scrollbars. */
+ if (sb == &gui.bottom_sbar && textAreaForm != (Widget)0)
+ gui_motif_scroll_colors(textAreaForm);
+}
+
+/*
+ * Miscellaneous stuff:
+ */
+
+ Window
+gui_x11_get_wid()
+{
+ return(XtWindow(textArea));
+}
+
+
+#if defined(FEAT_BROWSE) || defined(PROTO)
+
+/*
+ * file selector related stuff
+ */
+
+#include <Xm/FileSB.h>
+#include <Xm/XmStrDefs.h>
+
+typedef struct dialog_callback_arg
+{
+ char * args; /* not used right now */
+ int id;
+} dcbarg_T;
+
+static Widget dialog_wgt;
+static char *browse_fname = NULL;
+static XmStringCharSet charset = (XmStringCharSet) XmSTRING_DEFAULT_CHARSET;
+ /* used to set up XmStrings */
+
+static void DialogCancelCB __ARGS((Widget, XtPointer, XtPointer));
+static void DialogAcceptCB __ARGS((Widget, XtPointer, XtPointer));
+
+/*
+ * This function is used to translate the predefined label text of the
+ * precomposed dialogs. We do this explicitly to allow:
+ *
+ * - usage of gettext for translation, as in all the other places.
+ *
+ * - equalize the messages between different GUI implementations as far as
+ * possible.
+ */
+static void set_predefined_label __ARGS((Widget parent, String name, char * new_label));
+
+static void
+set_predefined_label(parent, name, new_label)
+ Widget parent;
+ String name;
+ char * new_label;
+{
+ XmString str;
+ Widget w;
+
+ w = XtNameToWidget(parent, name);
+
+ if (!w)
+ return;
+
+ str = XmStringCreate(new_label, STRING_TAG);
+
+ if (str)
+ {
+ XtVaSetValues(w, XmNlabelString, str, NULL);
+ XmStringFree(str);
+ }
+}
+
+/*
+ * Put up a file requester.
+ * Returns the selected name in allocated memory, or NULL for Cancel.
+ */
+/* ARGSUSED */
+ char_u *
+gui_mch_browse(saving, title, dflt, ext, initdir, filter)
+ int saving; /* select file to write */
+ char_u *title; /* title for the window */
+ char_u *dflt; /* default name */
+ char_u *ext; /* not used (extension added) */
+ char_u *initdir; /* initial directory, NULL for current dir */
+ char_u *filter; /* file name filter */
+{
+ char_u dirbuf[MAXPATHL];
+ char_u dfltbuf[MAXPATHL];
+ char_u *pattern;
+ char_u *tofree = NULL;
+
+ dialog_wgt = XmCreateFileSelectionDialog(vimShell, (char *)title, NULL, 0);
+
+ if (initdir == NULL || *initdir == NUL)
+ {
+ mch_dirname(dirbuf, MAXPATHL);
+ initdir = dirbuf;
+ }
+
+ if (dflt == NULL)
+ dflt = (char_u *)"";
+ else if (STRLEN(initdir) + STRLEN(dflt) + 2 < MAXPATHL)
+ {
+ /* The default selection should be the full path, "dflt" is only the
+ * file name. */
+ STRCPY(dfltbuf, initdir);
+ add_pathsep(dfltbuf);
+ STRCAT(dfltbuf, dflt);
+ dflt = dfltbuf;
+ }
+
+ /* Can only use one pattern for a file name. Get the first pattern out of
+ * the filter. An empty pattern means everything matches. */
+ if (filter == NULL)
+ pattern = (char_u *)"";
+ else
+ {
+ char_u *s, *p;
+
+ s = filter;
+ for (p = filter; *p != NUL; ++p)
+ {
+ if (*p == '\t') /* end of description, start of pattern */
+ s = p + 1;
+ if (*p == ';' || *p == '\n') /* end of (first) pattern */
+ break;
+ }
+ pattern = vim_strnsave(s, p - s);
+ tofree = pattern;
+ if (pattern == NULL)
+ pattern = (char_u *)"";
+ }
+
+ XtVaSetValues(dialog_wgt,
+ XtVaTypedArg,
+ XmNdirectory, XmRString, (char *)initdir, STRLEN(initdir) + 1,
+ XtVaTypedArg,
+ XmNdirSpec, XmRString, (char *)dflt, STRLEN(dflt) + 1,
+ XtVaTypedArg,
+ XmNpattern, XmRString, (char *)pattern, STRLEN(pattern) + 1,
+ XtVaTypedArg,
+ XmNdialogTitle, XmRString, (char *)title, STRLEN(title) + 1,
+ NULL);
+
+ set_predefined_label(dialog_wgt, "Apply", _("Filter"));
+ set_predefined_label(dialog_wgt, "Cancel", _("Cancel"));
+ set_predefined_label(dialog_wgt, "Dir", _("Directories"));
+ set_predefined_label(dialog_wgt, "FilterLabel", _("Filter"));
+ set_predefined_label(dialog_wgt, "Help", _("Help"));
+ set_predefined_label(dialog_wgt, "Items", _("Files"));
+ set_predefined_label(dialog_wgt, "OK", _("OK"));
+ set_predefined_label(dialog_wgt, "Selection", _("Selection"));
+
+ gui_motif_menu_colors(dialog_wgt);
+ if (gui.scroll_bg_pixel != INVALCOLOR)
+ XtVaSetValues(dialog_wgt, XmNtroughColor, gui.scroll_bg_pixel, NULL);
+
+ XtAddCallback(dialog_wgt, XmNokCallback, DialogAcceptCB, (XtPointer)0);
+ XtAddCallback(dialog_wgt, XmNcancelCallback, DialogCancelCB, (XtPointer)0);
+ /* We have no help in this window, so hide help button */
+ XtUnmanageChild(XmFileSelectionBoxGetChild(dialog_wgt,
+ (unsigned char)XmDIALOG_HELP_BUTTON));
+
+ manage_centered(dialog_wgt);
+
+ /* sit in a loop until the dialog box has gone away */
+ do
+ {
+ XtAppProcessEvent(XtWidgetToApplicationContext(dialog_wgt),
+ (XtInputMask)XtIMAll);
+ } while (XtIsManaged(dialog_wgt));
+
+ XtDestroyWidget(dialog_wgt);
+ vim_free(tofree);
+
+ if (browse_fname == NULL)
+ return NULL;
+ return vim_strsave((char_u *)browse_fname);
+}
+
+/*
+ * The code below was originally taken from
+ * /usr/examples/motif/xmsamplers/xmeditor.c
+ * on Digital Unix 4.0d, but heavily modified.
+ */
+
+/*
+ * Process callback from Dialog cancel actions.
+ */
+/* ARGSUSED */
+ static void
+DialogCancelCB(w, client_data, call_data)
+ Widget w; /* widget id */
+ XtPointer client_data; /* data from application */
+ XtPointer call_data; /* data from widget class */
+{
+ if (browse_fname != NULL)
+ {
+ XtFree(browse_fname);
+ browse_fname = NULL;
+ }
+ XtUnmanageChild(dialog_wgt);
+}
+
+/*
+ * Process callback from Dialog actions.
+ */
+/* ARGSUSED */
+ static void
+DialogAcceptCB(w, client_data, call_data)
+ Widget w; /* widget id */
+ XtPointer client_data; /* data from application */
+ XtPointer call_data; /* data from widget class */
+{
+ XmFileSelectionBoxCallbackStruct *fcb;
+
+ if (browse_fname != NULL)
+ {
+ XtFree(browse_fname);
+ browse_fname = NULL;
+ }
+ fcb = (XmFileSelectionBoxCallbackStruct *)call_data;
+
+ /* get the filename from the file selection box */
+ XmStringGetLtoR(fcb->value, charset, &browse_fname);
+
+ /* popdown the file selection box */
+ XtUnmanageChild(dialog_wgt);
+}
+
+#endif /* FEAT_BROWSE */
+
+#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
+
+static int dialogStatus;
+
+static void keyhit_callback __ARGS((Widget w, XtPointer client_data, XEvent *event, Boolean *cont));
+static void butproc __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
+
+/*
+ * Callback function for the textfield. When CR is hit this works like
+ * hitting the "OK" button, ESC like "Cancel".
+ */
+/* ARGSUSED */
+ static void
+keyhit_callback(w, client_data, event, cont)
+ Widget w;
+ XtPointer client_data;
+ XEvent *event;
+ Boolean *cont;
+{
+ char buf[2];
+ KeySym key_sym;
+
+ if (XLookupString(&(event->xkey), buf, 2, &key_sym, NULL) == 1)
+ {
+ if (*buf == CAR)
+ dialogStatus = 1;
+ else if (*buf == ESC)
+ dialogStatus = 2;
+ }
+ if ((key_sym == XK_Left || key_sym == XK_Right)
+ && !(event->xkey.state & ShiftMask))
+ XmTextFieldClearSelection(w, XtLastTimestampProcessed(gui.dpy));
+}
+
+/* ARGSUSED */
+ static void
+butproc(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data;
+ XtPointer call_data;
+{
+ dialogStatus = (int)(long)client_data + 1;
+}
+
+static void gui_motif_set_fontlist __ARGS((Widget wg));
+
+/*
+ * Use the 'guifont' or 'guifontset' as a fontlist for a dialog widget.
+ */
+ static void
+gui_motif_set_fontlist(wg)
+ Widget wg;
+{
+ XmFontList fl;
+
+ fl =
+#ifdef FEAT_XFONTSET
+ gui.fontset != NOFONTSET ?
+ gui_motif_fontset2fontlist((XFontSet *)&gui.fontset)
+ :
+#endif
+ gui_motif_create_fontlist((XFontStruct *)gui.norm_font);
+ if (fl != NULL)
+ {
+ XtVaSetValues(wg, XmNfontList, fl, NULL);
+ XmFontListFree(fl);
+ }
+}
+
+#ifdef HAVE_XPM
+
+static Widget create_pixmap_label(Widget parent, String name, char **data, ArgList args, Cardinal arg);
+
+ static Widget
+create_pixmap_label(parent, name, data, args, arg)
+ Widget parent;
+ String name;
+ char **data;
+ ArgList args;
+ Cardinal arg;
+{
+ Widget label;
+ Display *dsp;
+ Screen *scr;
+ int depth;
+ Pixmap pixmap = 0;
+ XpmAttributes attr;
+ Boolean rs;
+ XpmColorSymbol color[5] =
+ {
+ {"none", NULL, 0},
+ {"iconColor1", NULL, 0},
+ {"bottomShadowColor", NULL, 0},
+ {"topShadowColor", NULL, 0},
+ {"selectColor", NULL, 0}
+ };
+
+ label = XmCreateLabelGadget(parent, name, args, arg);
+
+ /*
+ * We need to be carefull here, since in case of gadgets, there is
+ * no way to get the background color directly from the widget itself.
+ * In such cases we get it from The Core part of his parent instead.
+ */
+ dsp = XtDisplayOfObject(label);
+ scr = XtScreenOfObject(label);
+ XtVaGetValues(XtIsSubclass(label, coreWidgetClass)
+ ? label : XtParent(label),
+ XmNdepth, &depth,
+ XmNbackground, &color[0].pixel,
+ XmNforeground, &color[1].pixel,
+ XmNbottomShadowColor, &color[2].pixel,
+ XmNtopShadowColor, &color[3].pixel,
+ XmNhighlight, &color[4].pixel,
+ NULL);
+
+ attr.valuemask = XpmColorSymbols | XpmCloseness | XpmDepth;
+ attr.colorsymbols = color;
+ attr.numsymbols = 5;
+ attr.closeness = 65535;
+ attr.depth = depth;
+ XpmCreatePixmapFromData(dsp, RootWindowOfScreen(scr),
+ data, &pixmap, NULL, &attr);
+
+ XtVaGetValues(label, XmNrecomputeSize, &rs, NULL);
+ XtVaSetValues(label, XmNrecomputeSize, True, NULL);
+ XtVaSetValues(label,
+ XmNlabelType, XmPIXMAP,
+ XmNlabelPixmap, pixmap,
+ NULL);
+ XtVaSetValues(label, XmNrecomputeSize, rs, NULL);
+
+ return label;
+}
+#endif
+
+/* ARGSUSED */
+ int
+gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield)
+ int type;
+ char_u *title;
+ char_u *message;
+ char_u *button_names;
+ int dfltbutton;
+ char_u *textfield; /* buffer of size IOSIZE */
+{
+ char_u *buts;
+ char_u *p, *next;
+ XtAppContext app;
+ XmString label;
+ int butcount;
+ Widget dialogform = NULL;
+ Widget form = NULL;
+ Widget dialogtextfield = NULL;
+ Widget *buttons;
+ Widget sep_form = NULL;
+ Boolean vertical;
+ Widget separator = NULL;
+ int n;
+ Arg args[6];
+#ifdef HAVE_XPM
+ char **icon_data = NULL;
+ Widget dialogpixmap = NULL;
+#endif
+
+ if (title == NULL)
+ title = (char_u *)_("Vim dialog");
+
+ /* if our pointer is currently hidden, then we should show it. */
+ gui_mch_mousehide(FALSE);
+
+ dialogform = XmCreateFormDialog(vimShell, (char *)"dialog", NULL, 0);
+
+ /* Check 'v' flag in 'guioptions': vertical button placement. */
+ vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
+
+ /* Set the title of the Dialog window */
+ label = XmStringCreateSimple((char *)title);
+ if (label == NULL)
+ return -1;
+ XtVaSetValues(dialogform,
+ XmNdialogTitle, label,
+ XmNhorizontalSpacing, 4,
+ XmNverticalSpacing, vertical ? 0 : 4,
+ NULL);
+ XmStringFree(label);
+
+ /* make a copy, so that we can insert NULs */
+ buts = vim_strsave(button_names);
+ if (buts == NULL)
+ return -1;
+
+ /* Count the number of buttons and allocate buttons[]. */
+ butcount = 1;
+ for (p = buts; *p; ++p)
+ if (*p == DLG_BUTTON_SEP)
+ ++butcount;
+ buttons = (Widget *)alloc((unsigned)(butcount * sizeof(Widget)));
+ if (buttons == NULL)
+ {
+ vim_free(buts);
+ return -1;
+ }
+
+ /*
+ * Create the buttons.
+ */
+ sep_form = (Widget) 0;
+ p = buts;
+ for (butcount = 0; *p; ++butcount)
+ {
+ for (next = p; *next; ++next)
+ {
+ if (*next == DLG_HOTKEY_CHAR)
+ mch_memmove(next, next + 1, STRLEN(next));
+ if (*next == DLG_BUTTON_SEP)
+ {
+ *next++ = NUL;
+ break;
+ }
+ }
+ label = XmStringCreate(_((char *)p), STRING_TAG);
+ if (label == NULL)
+ break;
+
+ buttons[butcount] = XtVaCreateManagedWidget("button",
+ xmPushButtonWidgetClass, dialogform,
+ XmNlabelString, label,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 4,
+ XmNshowAsDefault, butcount == dfltbutton - 1,
+ XmNdefaultButtonShadowThickness, 1,
+ NULL);
+ XmStringFree(label);
+
+ /* Layout properly. */
+
+ if (butcount > 0)
+ {
+ if (vertical)
+ XtVaSetValues(buttons[butcount],
+ XmNtopWidget, buttons[butcount - 1],
+ NULL);
+ else
+ {
+ if (*next == NUL)
+ {
+ XtVaSetValues(buttons[butcount],
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 4,
+ NULL);
+
+ /* fill in a form as invisible separator */
+ sep_form = XtVaCreateWidget("separatorForm",
+ xmFormWidgetClass, dialogform,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, buttons[butcount - 1],
+ XmNrightAttachment, XmATTACH_WIDGET,
+ XmNrightWidget, buttons[butcount],
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 4,
+ NULL);
+ XtManageChild(sep_form);
+ }
+ else
+ {
+ XtVaSetValues(buttons[butcount],
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, buttons[butcount - 1],
+ NULL);
+ }
+ }
+ }
+ else if (!vertical)
+ {
+ if (*next == NUL)
+ {
+ XtVaSetValues(buttons[0],
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 4,
+ NULL);
+
+ /* fill in a form as invisible separator */
+ sep_form = XtVaCreateWidget("separatorForm",
+ xmFormWidgetClass, dialogform,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 4,
+ XmNrightAttachment, XmATTACH_WIDGET,
+ XmNrightWidget, buttons[0],
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 4,
+ NULL);
+ XtManageChild(sep_form);
+ }
+ else
+ XtVaSetValues(buttons[0],
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 4,
+ NULL);
+ }
+
+ XtAddCallback(buttons[butcount], XmNactivateCallback,
+ (XtCallbackProc)butproc, (XtPointer)(long)butcount);
+ p = next;
+ }
+ vim_free(buts);
+
+ separator = (Widget) 0;
+ if (butcount > 0)
+ {
+ /* Create the separator for beauty. */
+ n = 0;
+ XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
+ XtSetArg(args[n], XmNbottomWidget, buttons[0]); n++;
+ XtSetArg(args[n], XmNbottomOffset, 4); n++;
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
+ separator = XmCreateSeparatorGadget(dialogform, "separator", args, n);
+ XtManageChild(separator);
+ }
+
+ if (textfield != NULL)
+ {
+ dialogtextfield = XtVaCreateWidget("textField",
+ xmTextFieldWidgetClass, dialogform,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ NULL);
+ if (butcount > 0)
+ XtVaSetValues(dialogtextfield,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, separator,
+ NULL);
+ else
+ XtVaSetValues(dialogtextfield,
+ XmNbottomAttachment, XmATTACH_FORM,
+ NULL);
+
+ gui_motif_set_fontlist(dialogtextfield);
+ XmTextFieldSetString(dialogtextfield, (char *)textfield);
+ XtManageChild(dialogtextfield);
+ XtAddEventHandler(dialogtextfield, KeyPressMask, False,
+ (XtEventHandler)keyhit_callback, (XtPointer)NULL);
+ }
+
+ /* Form holding both message and pixmap labels */
+ form = XtVaCreateWidget("separatorForm",
+ xmFormWidgetClass, dialogform,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNtopAttachment, XmATTACH_FORM,
+ NULL);
+ XtManageChild(form);
+
+#ifdef HAVE_XPM
+ /* Add a pixmap, left of the message. */
+ switch (type)
+ {
+ case VIM_GENERIC:
+ icon_data = generic_xpm;
+ break;
+ case VIM_ERROR:
+ icon_data = error_xpm;
+ break;
+ case VIM_WARNING:
+ icon_data = alert_xpm;
+ break;
+ case VIM_INFO:
+ icon_data = info_xpm;
+ break;
+ case VIM_QUESTION:
+ icon_data = quest_xpm;
+ break;
+ default:
+ icon_data = generic_xpm;
+ }
+
+ n = 0;
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNtopOffset, 8); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNbottomOffset, 8); n++;
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNleftOffset, 8); n++;
+
+ dialogpixmap = create_pixmap_label(form, "dialogPixmap",
+ icon_data, args, n);
+ XtManageChild(dialogpixmap);
+#endif
+
+ /* Create the dialog message. */
+ label = XmStringLtoRCreate((char *)message, STRING_TAG);
+ if (label == NULL)
+ return -1;
+ (void)XtVaCreateManagedWidget("dialogMessage",
+ xmLabelGadgetClass, form,
+ XmNlabelString, label,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 8,
+#ifdef HAVE_XPM
+ XmNleftAttachment, XmATTACH_WIDGET,
+ XmNleftWidget, dialogpixmap,
+#else
+ XmNleftAttachment, XmATTACH_FORM,
+#endif
+ XmNleftOffset, 8,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 8,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 8,
+ NULL);
+ XmStringFree(label);
+
+ if (textfield != NULL)
+ {
+ XtVaSetValues(form,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, dialogtextfield,
+ NULL);
+ }
+ else
+ {
+ if (butcount > 0)
+ XtVaSetValues(form,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, separator,
+ NULL);
+ else
+ XtVaSetValues(form,
+ XmNbottomAttachment, XmATTACH_FORM,
+ NULL);
+ }
+
+ if (dfltbutton < 1)
+ dfltbutton = 1;
+ if (dfltbutton > butcount)
+ dfltbutton = butcount;
+ XtVaSetValues(dialogform,
+ XmNdefaultButton, buttons[dfltbutton - 1], NULL);
+ if (textfield != NULL)
+ XtVaSetValues(dialogform, XmNinitialFocus, dialogtextfield, NULL);
+ else
+ XtVaSetValues(dialogform, XmNinitialFocus, buttons[dfltbutton - 1],
+ NULL);
+
+ manage_centered(dialogform);
+
+ if (textfield != NULL && *textfield != NUL)
+ {
+ /* This only works after the textfield has been realised. */
+ XmTextFieldSetSelection(dialogtextfield,
+ (XmTextPosition)0, (XmTextPosition)STRLEN(textfield),
+ XtLastTimestampProcessed(gui.dpy));
+ XmTextFieldSetCursorPosition(dialogtextfield,
+ (XmTextPosition)STRLEN(textfield));
+ }
+
+ app = XtWidgetToApplicationContext(dialogform);
+
+ /* Loop until a button is pressed or the dialog is killed somehow. */
+ dialogStatus = -1;
+ for (;;)
+ {
+ XtAppProcessEvent(app, (XtInputMask)XtIMAll);
+ if (dialogStatus >= 0 || !XtIsManaged(dialogform))
+ break;
+ }
+
+ vim_free(buttons);
+
+ if (textfield != NULL)
+ {
+ p = (char_u *)XmTextGetString(dialogtextfield);
+ if (p == NULL || dialogStatus < 0)
+ *textfield = NUL;
+ else
+ {
+ STRNCPY(textfield, p, IOSIZE);
+ textfield[IOSIZE - 1] = NUL;
+ }
+ }
+
+ XtDestroyWidget(dialogform);
+
+ return dialogStatus;
+}
+#endif /* FEAT_GUI_DIALOG */
+
+#if defined(FEAT_FOOTER) || defined(PROTO)
+
+ static int
+gui_mch_compute_footer_height()
+{
+ Dimension height; /* total Toolbar height */
+ Dimension top; /* XmNmarginTop */
+ Dimension bottom; /* XmNmarginBottom */
+ Dimension shadow; /* XmNshadowThickness */
+
+ XtVaGetValues(footer,
+ XmNheight, &height,
+ XmNmarginTop, &top,
+ XmNmarginBottom, &bottom,
+ XmNshadowThickness, &shadow,
+ NULL);
+
+ return (int) height + top + bottom + (shadow << 1);
+}
+
+#if 0 /* not used */
+ void
+gui_mch_set_footer_pos(h)
+ int h; /* textArea height */
+{
+ XtVaSetValues(footer,
+ XmNtopOffset, h + 7,
+ NULL);
+}
+#endif
+
+ void
+gui_mch_enable_footer(showit)
+ int showit;
+{
+ if (showit)
+ {
+ gui.footer_height = gui_mch_compute_footer_height();
+ XtManageChild(footer);
+ }
+ else
+ {
+ gui.footer_height = 0;
+ XtUnmanageChild(footer);
+ }
+ XtVaSetValues(textAreaForm, XmNbottomOffset, gui.footer_height, NULL);
+}
+
+ void
+gui_mch_set_footer(s)
+ char_u *s;
+{
+ XmString xms;
+
+ xms = XmStringCreate((char *)s, STRING_TAG);
+ XtVaSetValues(footer, XmNlabelString, xms, NULL);
+ XmStringFree(xms);
+}
+
+#endif
+
+
+#if defined(FEAT_TOOLBAR) || defined(PROTO)
+ void
+gui_mch_show_toolbar(int showit)
+{
+ Cardinal numChildren; /* how many children toolBar has */
+
+ if (toolBar == (Widget)0)
+ return;
+ XtVaGetValues(toolBar, XmNnumChildren, &numChildren, NULL);
+ if (showit && numChildren > 0)
+ {
+ /* Assume that we want to show the toolbar if p_toolbar contains
+ * valid option settings, therefore p_toolbar must not be NULL.
+ */
+ WidgetList children;
+
+ XtVaGetValues(toolBar, XmNchildren, &children, NULL);
+ {
+ void (*action)(BalloonEval *);
+ int text = 0;
+
+ if (strstr((const char *)p_toolbar, "tooltips"))
+ action = &gui_mch_enable_beval_area;
+ else
+ action = &gui_mch_disable_beval_area;
+ if (strstr((const char *)p_toolbar, "text"))
+ text = 1;
+ else if (strstr((const char *)p_toolbar, "icons"))
+ text = -1;
+ if (text != 0)
+ {
+ vimmenu_T *toolbar;
+ vimmenu_T *cur;
+
+ for (toolbar = root_menu; toolbar; toolbar = toolbar->next)
+ if (menu_is_toolbar(toolbar->dname))
+ break;
+ /* Assumption: toolbar is NULL if there is no toolbar,
+ * otherwise it contains the toolbar menu structure.
+ *
+ * Assumption: "numChildren" == the number of items in the list
+ * of items beginning with toolbar->children.
+ */
+ if (toolbar)
+ {
+ for (cur = toolbar->children; cur; cur = cur->next)
+ {
+ Arg args[1];
+ int n = 0;
+
+ /* Enable/Disable tooltip (OK to enable while
+ * currently enabled)
+ */
+ if (cur->tip != NULL)
+ (*action)(cur->tip);
+ if (!menu_is_separator(cur->name))
+ {
+ if (text == 1 || cur->image == 0)
+ XtSetArg(args[n], XmNlabelType, XmSTRING);
+ else
+ XtSetArg(args[n], XmNlabelType, XmPIXMAP);
+ n++;
+ if (cur->id != NULL)
+ {
+ XtUnmanageChild(cur->id);
+ XtSetValues(cur->id, args, n);
+ XtManageChild(cur->id);
+ }
+ }
+ }
+ }
+ }
+ }
+ gui.toolbar_height = gui_mch_compute_toolbar_height();
+ XtManageChild(XtParent(toolBar));
+ XtVaSetValues(textAreaForm,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, XtParent(toolBar),
+ NULL);
+ if (XtIsManaged(menuBar))
+ XtVaSetValues(XtParent(toolBar),
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, menuBar,
+ NULL);
+ else
+ XtVaSetValues(XtParent(toolBar),
+ XmNtopAttachment, XmATTACH_FORM,
+ NULL);
+ }
+ else
+ {
+ gui.toolbar_height = 0;
+ if (XtIsManaged(menuBar))
+ XtVaSetValues(textAreaForm,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, menuBar,
+ NULL);
+ else
+ XtVaSetValues(textAreaForm,
+ XmNtopAttachment, XmATTACH_FORM,
+ NULL);
+
+ XtUnmanageChild(XtParent(toolBar));
+ }
+ gui_set_shellsize(FALSE, FALSE);
+}
+
+/*
+ * A toolbar button has been pushed; now reset the input focus
+ * such that the user can type page up/down etc. and have the
+ * input go to the editor window, not the button
+ */
+ static void
+gui_mch_reset_focus()
+{
+ if (textArea != NULL)
+ XmProcessTraversal(textArea, XmTRAVERSE_CURRENT);
+}
+
+ int
+gui_mch_compute_toolbar_height()
+{
+ Dimension height; /* total Toolbar height */
+ Dimension whgt; /* height of each widget */
+ Dimension marginHeight; /* XmNmarginHeight of toolBar */
+ Dimension shadowThickness; /* thickness of Xtparent(toolBar) */
+ WidgetList children; /* list of toolBar's children */
+ Cardinal numChildren; /* how many children toolBar has */
+ int i;
+
+ height = 0;
+ shadowThickness = 0;
+ marginHeight = 0;
+ if (toolBar != (Widget)0 && toolBarFrame != (Widget)0)
+ { /* get height of XmFrame parent */
+ XtVaGetValues(toolBarFrame,
+ XmNshadowThickness, &shadowThickness,
+ NULL);
+ XtVaGetValues(toolBar,
+ XmNmarginHeight, &marginHeight,
+ XmNchildren, &children,
+ XmNnumChildren, &numChildren, NULL);
+ for (i = 0; i < numChildren; i++)
+ {
+ whgt = 0;
+ XtVaGetValues(children[i], XmNheight, &whgt, NULL);
+ if (height < whgt)
+ height = whgt;
+ }
+ }
+
+ return (int)(height + (marginHeight << 1) + (shadowThickness << 1));
+}
+
+#if 0 /* these are never called. */
+/*
+ * The next toolbar enter/leave callbacks make sure the text area gets the
+ * keyboard focus when the pointer is not in the toolbar.
+ */
+/*ARGSUSED*/
+ static void
+toolbar_enter_cb(w, client_data, event, cont)
+ Widget w;
+ XtPointer client_data;
+ XEvent *event;
+ Boolean *cont;
+{
+ XmProcessTraversal(toolBar, XmTRAVERSE_CURRENT);
+}
+
+/*ARGSUSED*/
+ static void
+toolbar_leave_cb(w, client_data, event, cont)
+ Widget w;
+ XtPointer client_data;
+ XEvent *event;
+ Boolean *cont;
+{
+ XmProcessTraversal(textArea, XmTRAVERSE_CURRENT);
+}
+#endif
+
+# ifdef FEAT_FOOTER
+/*
+ * The next toolbar enter/leave callbacks should really do balloon help. But
+ * I have to use footer help for backwards compatability. Hopefully both will
+ * get implemented and the user will have a choice.
+ */
+/*ARGSUSED*/
+ static void
+toolbarbutton_enter_cb(w, client_data, event, cont)
+ Widget w;
+ XtPointer client_data;
+ XEvent *event;
+ Boolean *cont;
+{
+ vimmenu_T *menu = (vimmenu_T *) client_data;
+
+ if (menu->strings[MENU_INDEX_TIP] != NULL)
+ {
+ if (vim_strchr(p_go, GO_FOOTER) != NULL)
+ gui_mch_set_footer(menu->strings[MENU_INDEX_TIP]);
+ }
+}
+
+/*ARGSUSED*/
+ static void
+toolbarbutton_leave_cb(w, client_data, event, cont)
+ Widget w;
+ XtPointer client_data;
+ XEvent *event;
+ Boolean *cont;
+{
+ gui_mch_set_footer((char_u *) "");
+}
+# endif
+
+ void
+gui_mch_get_toolbar_colors(bgp, fgp, bsp, tsp, hsp)
+ Pixel *bgp;
+ Pixel *fgp;
+ Pixel *bsp;
+ Pixel *tsp;
+ Pixel *hsp;
+{
+ XtVaGetValues(toolBar,
+ XmNbackground, bgp,
+ XmNforeground, fgp,
+ XmNbottomShadowColor, bsp,
+ XmNtopShadowColor, tsp,
+ XmNhighlightColor, hsp,
+ NULL);
+}
+#endif
+
+/*
+ * Set the colors of Widget "id" to the menu colors.
+ */
+ static void
+gui_motif_menu_colors(id)
+ Widget id;
+{
+ if (gui.menu_bg_pixel != INVALCOLOR)
+#if (XmVersion >= 1002)
+ XmChangeColor(id, gui.menu_bg_pixel);
+#else
+ XtVaSetValues(id, XmNbackground, gui.menu_bg_pixel, NULL);
+#endif
+ if (gui.menu_fg_pixel != INVALCOLOR)
+ XtVaSetValues(id, XmNforeground, gui.menu_fg_pixel, NULL);
+}
+
+/*
+ * Set the colors of Widget "id" to the scrollbar colors.
+ */
+ static void
+gui_motif_scroll_colors(id)
+ Widget id;
+{
+ if (gui.scroll_bg_pixel != INVALCOLOR)
+#if (XmVersion >= 1002)
+ XmChangeColor(id, gui.scroll_bg_pixel);
+#else
+ XtVaSetValues(id, XmNbackground, gui.scroll_bg_pixel, NULL);
+#endif
+ if (gui.scroll_fg_pixel != INVALCOLOR)
+ XtVaSetValues(id, XmNforeground, gui.scroll_fg_pixel, NULL);
+}
+
+#ifdef FEAT_MENU
+/*
+ * Set the fontlist for Widget "id" to use gui.menu_fontset or gui.menu_font.
+ */
+ static void
+gui_motif_menu_fontlist(id)
+ Widget id;
+{
+#ifdef FONTSET_ALWAYS
+ if (gui.menu_fontset != NOFONTSET)
+ {
+ XmFontList fl;
+
+ fl = gui_motif_fontset2fontlist((XFontSet *)&gui.menu_fontset);
+ if (fl != NULL)
+ {
+ if (XtIsManaged(id))
+ {
+ XtUnmanageChild(id);
+ XtVaSetValues(id, XmNfontList, fl, NULL);
+ /* We should force the widget to recalculate it's
+ * geometry now. */
+ XtManageChild(id);
+ }
+ else
+ XtVaSetValues(id, XmNfontList, fl, NULL);
+ XmFontListFree(fl);
+ }
+ }
+#else
+ if (gui.menu_font != NOFONT)
+ {
+ XmFontList fl;
+
+ fl = gui_motif_create_fontlist((XFontStruct *)gui.menu_font);
+ if (fl != NULL)
+ {
+ if (XtIsManaged(id))
+ {
+ XtUnmanageChild(id);
+ XtVaSetValues(id, XmNfontList, fl, NULL);
+ /* We should force the widget to recalculate it's
+ * geometry now. */
+ XtManageChild(id);
+ }
+ else
+ XtVaSetValues(id, XmNfontList, fl, NULL);
+ XmFontListFree(fl);
+ }
+ }
+#endif
+}
+
+#endif
+
+/*
+ * We don't create it twice for the sake of speed.
+ */
+
+typedef struct _SharedFindReplace
+{
+ Widget dialog; /* the main dialog widget */
+ Widget wword; /* 'Exact match' check button */
+ Widget mcase; /* 'match case' check button */
+ Widget up; /* search direction 'Up' radio button */
+ Widget down; /* search direction 'Down' radio button */
+ Widget what; /* 'Find what' entry text widget */
+ Widget with; /* 'Replace with' entry text widget */
+ Widget find; /* 'Find Next' action button */
+ Widget replace; /* 'Replace With' action button */
+ Widget all; /* 'Replace All' action button */
+ Widget undo; /* 'Undo' action button */
+
+ Widget cancel;
+} SharedFindReplace;
+
+static SharedFindReplace find_widgets = { NULL };
+static SharedFindReplace repl_widgets = { NULL };
+
+static void find_replace_destroy_callback __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
+static void find_replace_dismiss_callback __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
+static void entry_activate_callback __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
+static void find_replace_callback __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
+static void find_replace_keypress __ARGS((Widget w, SharedFindReplace * frdp, XKeyEvent * event));
+static void find_replace_dialog_create __ARGS((char_u *entry_text, int do_replace));
+
+/*ARGSUSED*/
+ static void
+find_replace_destroy_callback(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data;
+ XtPointer call_data;
+{
+ SharedFindReplace *cd = (SharedFindReplace *)client_data;
+
+ if (cd != NULL)
+ cd->dialog = (Widget)0;
+}
+
+/*ARGSUSED*/
+ static void
+find_replace_dismiss_callback(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data;
+ XtPointer call_data;
+{
+ SharedFindReplace *cd = (SharedFindReplace *)client_data;
+
+ if (cd != NULL)
+ XtUnmanageChild(cd->dialog);
+}
+
+/*ARGSUSED*/
+ static void
+entry_activate_callback(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data;
+ XtPointer call_data;
+{
+ XmProcessTraversal((Widget)client_data, XmTRAVERSE_CURRENT);
+}
+
+/*ARGSUSED*/
+ static void
+find_replace_callback(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data;
+ XtPointer call_data;
+{
+ long_u flags = (long_u)client_data;
+ char *find_text, *repl_text;
+ Boolean direction_down = TRUE;
+ Boolean wword;
+ Boolean mcase;
+ SharedFindReplace *sfr;
+
+ if (flags == FRD_UNDO)
+ {
+ char_u *save_cpo = p_cpo;
+
+ /* No need to be Vi compatible here. */
+ p_cpo = (char_u *)"";
+ u_undo(1);
+ p_cpo = save_cpo;
+ gui_update_screen();
+ return;
+ }
+
+ /* Get the search/replace strings from the dialog */
+ if (flags == FRD_FINDNEXT)
+ {
+ repl_text = NULL;
+ sfr = &find_widgets;
+ }
+ else
+ {
+ repl_text = XmTextFieldGetString(repl_widgets.with);
+ sfr = &repl_widgets;
+ }
+ find_text = XmTextFieldGetString(sfr->what);
+ XtVaGetValues(sfr->down, XmNset, &direction_down, NULL);
+ XtVaGetValues(sfr->wword, XmNset, &wword, NULL);
+ XtVaGetValues(sfr->mcase, XmNset, &mcase, NULL);
+ if (wword)
+ flags |= FRD_WHOLE_WORD;
+ if (mcase)
+ flags |= FRD_MATCH_CASE;
+
+ (void)gui_do_findrepl((int)flags, (char_u *)find_text, (char_u *)repl_text,
+ direction_down);
+
+ if (find_text != NULL)
+ XtFree(find_text);
+ if (repl_text != NULL)
+ XtFree(repl_text);
+}
+
+/*ARGSUSED*/
+ static void
+find_replace_keypress(w, frdp, event)
+ Widget w;
+ SharedFindReplace *frdp;
+ XKeyEvent *event;
+{
+ KeySym keysym;
+
+ if (frdp == NULL)
+ return;
+
+ keysym = XLookupKeysym(event, 0);
+
+ /* the scape key pops the whole dialog down */
+ if (keysym == XK_Escape)
+ XtUnmanageChild(frdp->dialog);
+}
+
+ static void
+find_replace_dialog_create(arg, do_replace)
+ char_u *arg;
+ int do_replace;
+{
+ SharedFindReplace *frdp;
+ Widget separator;
+ Widget input_form;
+ Widget button_form;
+ Widget toggle_form;
+ Widget frame;
+ XmString str;
+ int n;
+ Arg args[6];
+ int wword = FALSE;
+ int mcase = !p_ic;
+ Dimension width;
+ Dimension widest;
+ char_u *entry_text;
+
+ frdp = do_replace ? &repl_widgets : &find_widgets;
+
+ /* Get the search string to use. */
+ entry_text = get_find_dialog_text(arg, &wword, &mcase);
+
+ /* If the dialog already exists, just raise it. */
+ if (frdp->dialog)
+ {
+ /* If the window is already up, just pop it to the top */
+ if (XtIsManaged(frdp->dialog))
+ XMapRaised(XtDisplay(frdp->dialog),
+ XtWindow(XtParent(frdp->dialog)));
+ else
+ XtManageChild(frdp->dialog);
+ XtPopup(XtParent(frdp->dialog), XtGrabNone);
+ XmProcessTraversal(frdp->what, XmTRAVERSE_CURRENT);
+
+ if (entry_text != NULL)
+ XmTextFieldSetString(frdp->what, (char *)entry_text);
+ vim_free(entry_text);
+
+ XtVaSetValues(frdp->wword, XmNset, wword, NULL);
+ return;
+ }
+
+ /* Create a fresh new dialog window */
+ if (do_replace)
+ str = XmStringCreateSimple(_("VIM - Search and Replace..."));
+ else
+ str = XmStringCreateSimple(_("VIM - Search..."));
+
+ n = 0;
+ XtSetArg(args[n], XmNautoUnmanage, False); n++;
+ XtSetArg(args[n], XmNnoResize, True); n++;
+ XtSetArg(args[n], XmNdialogTitle, str); n++;
+
+ frdp->dialog = XmCreateFormDialog(vimShell, "findReplaceDialog", args, n);
+ XmStringFree(str);
+ XtAddCallback(frdp->dialog, XmNdestroyCallback,
+ find_replace_destroy_callback, frdp);
+
+ button_form = XtVaCreateWidget("buttonForm",
+ xmFormWidgetClass, frdp->dialog,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 4,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 4,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 4,
+ NULL);
+
+ str = XmStringCreateSimple(_("Find Next"));
+ frdp->find = XtVaCreateManagedWidget("findButton",
+ xmPushButtonWidgetClass, button_form,
+ XmNlabelString, str,
+ XmNsensitive, True,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ NULL);
+ XmStringFree(str);
+
+ XtAddCallback(frdp->find, XmNactivateCallback,
+ find_replace_callback,
+ (XtPointer) (do_replace ? FRD_R_FINDNEXT : FRD_FINDNEXT));
+
+ if (do_replace)
+ {
+ str = XmStringCreateSimple(_("Replace"));
+ frdp->replace = XtVaCreateManagedWidget("replaceButton",
+ xmPushButtonWidgetClass, button_form,
+ XmNlabelString, str,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frdp->find,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ NULL);
+ XmStringFree(str);
+ XtAddCallback(frdp->replace, XmNactivateCallback,
+ find_replace_callback, (XtPointer)FRD_REPLACE);
+
+ str = XmStringCreateSimple(_("Replace All"));
+ frdp->all = XtVaCreateManagedWidget("replaceAllButton",
+ xmPushButtonWidgetClass, button_form,
+ XmNlabelString, str,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frdp->replace,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ NULL);
+ XmStringFree(str);
+ XtAddCallback(frdp->all, XmNactivateCallback,
+ find_replace_callback, (XtPointer)FRD_REPLACEALL);
+
+ str = XmStringCreateSimple(_("Undo"));
+ frdp->undo = XtVaCreateManagedWidget("undoButton",
+ xmPushButtonWidgetClass, button_form,
+ XmNlabelString, str,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frdp->all,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ NULL);
+ XmStringFree(str);
+ XtAddCallback(frdp->undo, XmNactivateCallback,
+ find_replace_callback, (XtPointer)FRD_UNDO);
+ }
+
+ str = XmStringCreateSimple(_("Cancel"));
+ frdp->cancel = XtVaCreateManagedWidget("closeButton",
+ xmPushButtonWidgetClass, button_form,
+ XmNlabelString, str,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ NULL);
+ XmStringFree(str);
+ XtAddCallback(frdp->cancel, XmNactivateCallback,
+ find_replace_dismiss_callback, frdp);
+
+ XtManageChild(button_form);
+
+ n = 0;
+ XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
+ XtSetArg(args[n], XmNrightWidget, button_form); n++;
+ XtSetArg(args[n], XmNrightOffset, 4); n++;
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
+ separator = XmCreateSeparatorGadget(frdp->dialog, "separator", args, n);
+ XtManageChild(separator);
+
+ input_form = XtVaCreateWidget("inputForm",
+ xmFormWidgetClass, frdp->dialog,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 4,
+ XmNrightAttachment, XmATTACH_WIDGET,
+ XmNrightWidget, separator,
+ XmNrightOffset, 4,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 4,
+ NULL);
+
+ {
+ Widget label_what;
+ Widget label_with = (Widget)0;
+
+ str = XmStringCreateSimple(_("Find what:"));
+ label_what = XtVaCreateManagedWidget("whatLabel",
+ xmLabelGadgetClass, input_form,
+ XmNlabelString, str,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 4,
+ NULL);
+ XmStringFree(str);
+
+ frdp->what = XtVaCreateManagedWidget("whatText",
+ xmTextFieldWidgetClass, input_form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ NULL);
+
+ if (do_replace)
+ {
+ frdp->with = XtVaCreateManagedWidget("withText",
+ xmTextFieldWidgetClass, input_form,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frdp->what,
+ XmNtopOffset, 4,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ NULL);
+
+ XtAddCallback(frdp->with, XmNactivateCallback,
+ find_replace_callback, (XtPointer) FRD_R_FINDNEXT);
+
+ str = XmStringCreateSimple(_("Replace with:"));
+ label_with = XtVaCreateManagedWidget("withLabel",
+ xmLabelGadgetClass, input_form,
+ XmNlabelString, str,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frdp->what,
+ XmNtopOffset, 4,
+ XmNbottomAttachment, XmATTACH_FORM,
+ NULL);
+ XmStringFree(str);
+
+ /*
+ * Make the entry activation only change the input focus onto the
+ * with item.
+ */
+ XtAddCallback(frdp->what, XmNactivateCallback,
+ entry_activate_callback, frdp->with);
+ XtAddEventHandler(frdp->with, KeyPressMask, False,
+ (XtEventHandler)find_replace_keypress,
+ (XtPointer) frdp);
+
+ }
+ else
+ {
+ /*
+ * Make the entry activation do the search.
+ */
+ XtAddCallback(frdp->what, XmNactivateCallback,
+ find_replace_callback, (XtPointer)FRD_FINDNEXT);
+ }
+ XtAddEventHandler(frdp->what, KeyPressMask, False,
+ (XtEventHandler)find_replace_keypress,
+ (XtPointer)frdp);
+
+ /* Get the maximum width between the label widgets and line them up.
+ */
+ n = 0;
+ XtSetArg(args[n], XmNwidth, &width); n++;
+ XtGetValues(label_what, args, n);
+ widest = width;
+ if (do_replace)
+ {
+ XtGetValues(label_with, args, n);
+ if (width > widest)
+ widest = width;
+ }
+
+ XtVaSetValues(frdp->what, XmNleftOffset, widest, NULL);
+ if (do_replace)
+ XtVaSetValues(frdp->with, XmNleftOffset, widest, NULL);
+
+ }
+
+ XtManageChild(input_form);
+
+ {
+ Widget radio_box;
+
+ frame = XtVaCreateWidget("directionFrame",
+ xmFrameWidgetClass, frdp->dialog,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, input_form,
+ XmNtopOffset, 4,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 4,
+ XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNrightWidget, input_form,
+ NULL);
+
+ str = XmStringCreateSimple(_("Direction"));
+ (void)XtVaCreateManagedWidget("directionFrameLabel",
+ xmLabelGadgetClass, frame,
+ XmNlabelString, str,
+ XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ NULL);
+ XmStringFree(str);
+
+ radio_box = XmCreateRadioBox(frame, "radioBox",
+ (ArgList)NULL, 0);
+
+ str = XmStringCreateSimple( _("Up"));
+ frdp->up = XtVaCreateManagedWidget("upRadioButton",
+ xmToggleButtonGadgetClass, radio_box,
+ XmNlabelString, str,
+ XmNset, False,
+ NULL);
+ XmStringFree(str);
+
+ str = XmStringCreateSimple(_("Down"));
+ frdp->down = XtVaCreateManagedWidget("downRadioButton",
+ xmToggleButtonGadgetClass, radio_box,
+ XmNlabelString, str,
+ XmNset, True,
+ NULL);
+ XmStringFree(str);
+
+ XtManageChild(radio_box);
+ XtManageChild(frame);
+ }
+
+ toggle_form = XtVaCreateWidget("toggleForm",
+ xmFormWidgetClass, frdp->dialog,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 4,
+ XmNrightAttachment, XmATTACH_WIDGET,
+ XmNrightWidget, frame,
+ XmNrightOffset, 4,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, input_form,
+ XmNtopOffset, 4,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 4,
+ NULL);
+
+ str = XmStringCreateSimple(_("Match whole word only"));
+ frdp->wword = XtVaCreateManagedWidget("wordToggle",
+ xmToggleButtonGadgetClass, toggle_form,
+ XmNlabelString, str,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 4,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 4,
+ XmNset, wword,
+ NULL);
+ XmStringFree(str);
+
+ str = XmStringCreateSimple(_("Match case"));
+ frdp->mcase = XtVaCreateManagedWidget("caseToggle",
+ xmToggleButtonGadgetClass, toggle_form,
+ XmNlabelString, str,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 4,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, frdp->wword,
+ XmNtopOffset, 4,
+ XmNset, mcase,
+ NULL);
+ XmStringFree(str);
+
+ XtManageChild(toggle_form);
+
+ if (entry_text != NULL)
+ XmTextFieldSetString(frdp->what, (char *)entry_text);
+ vim_free(entry_text);
+
+ XtManageChild(frdp->dialog);
+ XmProcessTraversal(frdp->what, XmTRAVERSE_CURRENT);
+}
+
+ void
+gui_mch_find_dialog(eap)
+ exarg_T *eap;
+{
+ if (!gui.in_use)
+ return;
+
+ find_replace_dialog_create(eap->arg, FALSE);
+}
+
+
+ void
+gui_mch_replace_dialog(eap)
+ exarg_T *eap;
+{
+ if (!gui.in_use)
+ return;
+
+ find_replace_dialog_create(eap->arg, TRUE);
+}
diff --git a/src/gui_photon.c b/src/gui_photon.c
new file mode 100644
index 000000000..f2bd5f09b
--- /dev/null
+++ b/src/gui_photon.c
@@ -0,0 +1,3060 @@
+/* vi:set ts=8 sw=4 sts=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Photon GUI support by Julian Kinraid
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ *
+ *
+ * Clipboard support is in os_qnx.c
+ * PhAttach() is called in os_qnx.c:qnx_init()
+ */
+
+#include "vim.h"
+
+#ifdef FEAT_TOOLBAR
+# include <photon/PxImage.h>
+#endif
+
+#if !defined(__QNX__)
+/* Used when generating prototypes. */
+# define PgColor_t int
+# define PhEvent_t int
+# define PhPoint_t int
+# define PtWidget_t int
+# define Pg_BLACK 0
+# define PtCallbackF_t int
+# define PtCallbackInfo_t int
+# define PhTile_t int
+# define PtWidget_t int
+# define PhImage_t int
+#endif
+
+#define ARRAY_LENGTH(a) (sizeof(a) / sizeof(a[0]))
+#define RGB(r,g,b) PgRGB(r,g,b)
+
+#define EVENT_BUFFER_SIZE sizeof( PhEvent_t ) + 1000
+
+/* Some defines for gui_mch_mousehide() */
+#define MOUSE_HIDE TRUE
+#define MOUSE_SHOW FALSE
+
+/* Optional support for using a PtPanelGroup widget, needs work */
+#undef USE_PANEL_GROUP
+
+#ifdef USE_PANEL_GROUP
+static char *empty_title = " ";
+static char **panel_titles = NULL;
+static ushort_t num_panels = 0;
+static short pg_margin_left, pg_margin_right, pg_margin_top, pg_margin_bottom;
+#endif
+
+#define GUI_PH_MARGIN 4 /* Size of the bevel */
+
+#define GUI_PH_MOUSE_TYPE Ph_CURSOR_INSERT
+static PgColor_t gui_ph_mouse_color = Pg_BLACK;
+
+static PhPoint_t gui_ph_raw_offset;
+static PtWidget_t *gui_ph_timer_cursor; /* handle cursor blinking */
+static PtWidget_t *gui_ph_timer_timeout; /* used in gui_mch_wait_for_chars */
+static short is_timeout; /* Has the timeout occured? */
+
+/*
+ * This is set inside the mouse callback for a right mouse
+ * button click, and used for the popup menus
+ */
+static PhPoint_t abs_mouse;
+
+/* Try and avoid redraws while a resize is in progress */
+static int is_ignore_draw = FALSE;
+
+/* Used for converting to/from utf-8 and other charsets */
+static struct PxTransCtrl *charset_translate;
+
+/*
+ * Cursor blink functions.
+ *
+ * This is a simple state machine:
+ * BLINK_NONE not blinking at all
+ * BLINK_OFF blinking, cursor is not shown
+ * BLINK_ON blinking, cursor is shown
+ */
+static enum {
+ BLINK_NONE,
+ BLINK_OFF,
+ BLINK_ON
+} blink_state = BLINK_NONE;
+
+static long_u blink_waittime = 700;
+static long_u blink_ontime = 400;
+static long_u blink_offtime = 250;
+
+static struct
+{
+ int key_sym;
+ char_u vim_code0;
+ char_u vim_code1;
+} special_keys[] =
+{
+ {Pk_Up, 'k', 'u'},
+ {Pk_Down, 'k', 'd'},
+ {Pk_Left, 'k', 'l'},
+ {Pk_Right, 'k', 'r'},
+
+ {Pk_F1, 'k', '1'},
+ {Pk_F2, 'k', '2'},
+ {Pk_F3, 'k', '3'},
+ {Pk_F4, 'k', '4'},
+ {Pk_F5, 'k', '5'},
+ {Pk_F6, 'k', '6'},
+ {Pk_F7, 'k', '7'},
+ {Pk_F8, 'k', '8'},
+ {Pk_F9, 'k', '9'},
+ {Pk_F10, 'k', ';'},
+
+ {Pk_F11, 'F', '1'},
+ {Pk_F12, 'F', '2'},
+ {Pk_F13, 'F', '3'},
+ {Pk_F14, 'F', '4'},
+ {Pk_F15, 'F', '5'},
+ {Pk_F16, 'F', '6'},
+ {Pk_F17, 'F', '7'},
+ {Pk_F18, 'F', '8'},
+ {Pk_F19, 'F', '9'},
+ {Pk_F20, 'F', 'A'},
+
+ {Pk_F21, 'F', 'B'},
+ {Pk_F22, 'F', 'C'},
+ {Pk_F23, 'F', 'D'},
+ {Pk_F24, 'F', 'E'},
+ {Pk_F25, 'F', 'F'},
+ {Pk_F26, 'F', 'G'},
+ {Pk_F27, 'F', 'H'},
+ {Pk_F28, 'F', 'I'},
+ {Pk_F29, 'F', 'J'},
+
+ {Pk_F30, 'F', 'K'},
+ {Pk_F31, 'F', 'L'},
+ {Pk_F32, 'F', 'M'},
+ {Pk_F33, 'F', 'N'},
+ {Pk_F34, 'F', 'O'},
+ {Pk_F35, 'F', 'P'},
+
+ {Pk_Help, '%', '1'},
+ {Pk_BackSpace, 'k', 'b'},
+ {Pk_Insert, 'k', 'I'},
+ {Pk_Delete, 'k', 'D'},
+ {Pk_Home, 'k', 'h'},
+ {Pk_End, '@', '7'},
+ {Pk_Prior, 'k', 'P'},
+ {Pk_Next, 'k', 'N'},
+ {Pk_Print, '%', '9'},
+
+ {Pk_KP_Add, 'K', '6'},
+ {Pk_KP_Subtract,'K', '7'},
+ {Pk_KP_Divide, 'K', '8'},
+ {Pk_KP_Multiply,'K', '9'},
+ {Pk_KP_Enter, 'K', 'A'},
+
+ {Pk_KP_0, KS_EXTRA, KE_KINS}, /* Insert */
+ {Pk_KP_Decimal, KS_EXTRA, KE_KDEL}, /* Delete */
+
+ {Pk_KP_4, 'k', 'l'}, /* Left */
+ {Pk_KP_6, 'k', 'r'}, /* Right */
+ {Pk_KP_8, 'k', 'u'}, /* Up */
+ {Pk_KP_2, 'k', 'd'}, /* Down */
+
+ {Pk_KP_7, 'K', '1'}, /* Home */
+ {Pk_KP_1, 'K', '4'}, /* End */
+
+ {Pk_KP_9, 'K', '3'}, /* Page Up */
+ {Pk_KP_3, 'K', '5'}, /* Page Down */
+
+ {Pk_KP_5, '&', '8'}, /* Undo */
+
+ /* Keys that we want to be able to use any modifier with: */
+ {Pk_Return, CAR, NUL},
+ {Pk_space, ' ', NUL},
+ {Pk_Tab, TAB, NUL},
+ {Pk_Escape, ESC, NUL},
+ {NL, NL, NUL},
+ {CAR, CAR, NUL},
+
+ /* End of list marker: */
+ {0, 0, 0}
+};
+
+
+/****************************************************************************/
+
+static PtCallbackF_t gui_ph_handle_timer_cursor;
+static PtCallbackF_t gui_ph_handle_timer_timeout;
+
+static PtCallbackF_t gui_ph_handle_window_cb;
+
+static PtCallbackF_t gui_ph_handle_scrollbar;
+static PtCallbackF_t gui_ph_handle_keyboard;
+static PtCallbackF_t gui_ph_handle_mouse;
+static PtCallbackF_t gui_ph_handle_pulldown_menu;
+static PtCallbackF_t gui_ph_handle_menu;
+static PtCallbackF_t gui_ph_handle_focus; /* focus change of text area */
+
+static PtCallbackF_t gui_ph_handle_menu_resize;
+
+/* When a menu is unrealized, give focus back to vimTextArea */
+static PtCallbackF_t gui_ph_handle_menu_unrealized;
+
+#ifdef USE_PANEL_GROUP
+static void gui_ph_get_panelgroup_margins( short*, short*, short*, short* );
+#endif
+
+#ifdef FEAT_TOOLBAR
+static PhImage_t *gui_ph_toolbar_find_icon( vimmenu_T *menu );
+#endif
+
+static void gui_ph_draw_start( void );
+static void gui_ph_draw_end( void );
+
+/* Set the text for the balloon */
+static PtWidget_t * gui_ph_show_tooltip( PtWidget_t *window,
+ PtWidget_t *widget,
+ int position,
+ char *text,
+ char *font,
+ PgColor_t fill_color,
+ PgColor_t text_color );
+
+/****************************************************************************/
+
+static PtWidget_t * gui_ph_show_tooltip( PtWidget_t *window,
+ PtWidget_t *widget,
+ int position,
+ char *text,
+ char *font,
+ PgColor_t fill_color,
+ PgColor_t text_color )
+{
+ PtArg_t arg;
+ vimmenu_T *menu;
+ char_u *tooltip;
+
+ PtSetArg( &arg, Pt_ARG_POINTER, &menu, 0 );
+ PtGetResources( widget, 1, &arg );
+
+ /* Override the text and position */
+
+ tooltip = text;
+ if( menu != NULL )
+ {
+ int index = MENU_INDEX_TIP;
+ if( menu->strings[ index ] != NULL )
+ tooltip = menu->strings[ index ];
+ }
+
+ return( PtInflateBalloon(
+ window,
+ widget,
+ /* Don't put the balloon at the bottom,
+ * it gets drawn over by gfx done in the PtRaw */
+ Pt_BALLOON_TOP,
+ tooltip,
+ font,
+ fill_color,
+ text_color ) );
+}
+
+ static void
+gui_ph_resize_container( void )
+{
+ PhArea_t area;
+
+ PtWidgetArea( gui.vimWindow, &area );
+ PtWidgetPos ( gui.vimContainer, &area.pos );
+
+ PtSetResource( gui.vimContainer, Pt_ARG_AREA, &area, 0 );
+}
+
+ static int
+gui_ph_handle_menu_resize(
+ PtWidget_t *widget,
+ void *other,
+ PtCallbackInfo_t *info )
+{
+ PtContainerCallback_t *sizes = info->cbdata;
+ PtWidget_t *container;
+ PhPoint_t below_menu;
+ int_u height;
+
+ height = sizes->new_dim.h;
+
+ /* Because vim treats the toolbar and menubar separatly,
+ * and here they're lumped together into a PtToolbarGroup,
+ * we only need either menu_height or toolbar_height set at once */
+ if( gui.menu_is_active )
+ {
+ gui.menu_height = height;
+ gui.toolbar_height = 0;
+ }
+#ifdef FEAT_TOOLBAR
+ else
+ gui.toolbar_height = height;
+#endif
+
+ below_menu.x = 0;
+ below_menu.y = height;
+
+#ifdef USE_PANEL_GROUP
+ container = gui.vimPanelGroup;
+#else
+ container = gui.vimContainer;
+#endif
+
+ PtSetResource( container, Pt_ARG_POS, &below_menu, 0 );
+
+ gui_ph_resize_container();
+
+#ifdef USE_PANEL_GROUP
+ gui_ph_get_panelgroup_margins(
+ &pg_margin_top, &pg_margin_bottom,
+ &pg_margin_left, &pg_margin_right );
+#endif
+ return( Pt_CONTINUE );
+}
+
+/*
+ * Pt_ARG_TIMER_REPEAT isn't used because the on & off times
+ * are different
+ */
+ static int
+gui_ph_handle_timer_cursor(
+ PtWidget_t *widget,
+ void *data,
+ PtCallbackInfo_t *info )
+{
+ if( blink_state == BLINK_ON )
+ {
+ gui_undraw_cursor();
+ blink_state = BLINK_OFF;
+ PtSetResource( gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL,
+ blink_offtime, 0 );
+ }
+ else
+ {
+ gui_update_cursor(TRUE, FALSE);
+ blink_state = BLINK_ON;
+ PtSetResource( gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL,
+ blink_ontime, 0 );
+ }
+ return( Pt_CONTINUE );
+}
+
+ static int
+gui_ph_handle_timer_timeout(PtWidget_t *widget, void *data, PtCallbackInfo_t *info)
+{
+ is_timeout = TRUE;
+
+ return( Pt_CONTINUE );
+}
+
+ static int
+gui_ph_handle_window_cb( PtWidget_t *widget, void *data, PtCallbackInfo_t *info )
+{
+ PhWindowEvent_t *we = info->cbdata;
+ ushort_t *width, *height;
+
+ switch( we->event_f ) {
+ case Ph_WM_CLOSE:
+ gui_shell_closed();
+ break;
+
+ case Ph_WM_FOCUS:
+ /* Just in case it's hidden and needs to be shown */
+ gui_mch_mousehide( MOUSE_SHOW );
+
+ if( we->event_state == Ph_WM_EVSTATE_FOCUS )
+ {
+ gui_focus_change(TRUE);
+ gui_mch_start_blink();
+ }
+ else
+ {
+ gui_focus_change(FALSE);
+ gui_mch_stop_blink();
+ }
+ break;
+
+ case Ph_WM_RESIZE:
+ PtGetResource( gui.vimWindow, Pt_ARG_WIDTH, &width, 0 );
+ PtGetResource( gui.vimWindow, Pt_ARG_HEIGHT, &height, 0 );
+#ifdef USE_PANEL_GROUP
+ width -= (pg_margin_left + pg_margin_right);
+ height -= (pg_margin_top + pg_margin_bottom);
+#endif
+ gui_resize_shell( *width, *height );
+ gui_set_shellsize( FALSE, FALSE );
+ is_ignore_draw = FALSE;
+ PtEndFlux( gui.vimContainer );
+ PtContainerRelease( gui.vimContainer );
+ break;
+
+ default:
+ break;
+ }
+
+ return( Pt_CONTINUE );
+}
+
+ static int
+gui_ph_handle_scrollbar( PtWidget_t *widget, void *data, PtCallbackInfo_t *info )
+{
+ PtScrollbarCallback_t *scroll;
+ scrollbar_T *sb;
+ int value, dragging = FALSE;
+
+ scroll = info->cbdata;
+
+ sb = (scrollbar_T *) data;
+ if( sb != NULL )
+ {
+ value = scroll->position;
+ switch( scroll->action )
+ {
+ case Pt_SCROLL_DRAGGED:
+ dragging = TRUE;
+ break;
+
+ case Pt_SCROLL_SET:
+ /* FIXME: return straight away here? */
+ return( Pt_CONTINUE );
+ break;
+ }
+
+ gui_drag_scrollbar(sb, value, dragging);
+ }
+ return( Pt_CONTINUE );
+}
+
+ static int
+gui_ph_handle_keyboard( PtWidget_t *widget, void *data, PtCallbackInfo_t *info )
+{
+ PhKeyEvent_t *key;
+ unsigned char string[6];
+ int len, i;
+ int ch, modifiers;
+
+ key = PhGetData( info->event );
+
+ ch = modifiers = len = 0;
+
+ if( p_mh )
+ gui_mch_mousehide( MOUSE_HIDE );
+
+ /* We're a good lil photon program, aren't we? yes we are, yeess wee arrr */
+ if( key->key_flags & Pk_KF_Compose )
+ {
+ return( Pt_CONTINUE );
+ }
+
+ if( (key->key_flags & Pk_KF_Cap_Valid) &&
+ PkIsKeyDown( key->key_flags ) )
+ {
+#ifdef FEAT_MENU
+ /*
+ * Only show the menu if the Alt key is down, and the Shift & Ctrl
+ * keys aren't down, as well as the other conditions
+ */
+ if( ( ( key->key_mods & Pk_KM_Alt ) &&
+ !( key->key_mods & Pk_KM_Shift ) &&
+ !( key->key_mods & Pk_KM_Ctrl ) ) &&
+ gui.menu_is_active &&
+ ( *p_wak == 'y' ||
+ ( *p_wak == 'm' &&
+ gui_is_menu_shortcut( key->key_cap ) ) ) )
+ {
+ /* Fallthrough and let photon look for the hotkey */
+ return( Pt_CONTINUE );
+ }
+#endif
+
+ for( i = 0; special_keys[i].key_sym != 0; i++ )
+ {
+ if( special_keys[i].key_sym == key->key_cap )
+ {
+ len = 0;
+ if( special_keys[i].vim_code1 == NUL )
+ ch = special_keys[i].vim_code0;
+ else
+ {
+ /* Detect if a keypad number key has been pressed
+ * and change the key if Num Lock is on */
+ if( key->key_cap >= Pk_KP_Enter && key->key_cap <= Pk_KP_9
+ && ( key->key_mods & Pk_KM_Num_Lock ) )
+ {
+ /* FIXME: For now, just map the key to a ascii value
+ * (see <photon/PkKeyDef.h>) */
+ ch = key->key_cap - 0xf080;
+ }
+ else
+ ch = TO_SPECIAL( special_keys[i].vim_code0,
+ special_keys[i].vim_code1 );
+ }
+ break;
+ }
+ }
+
+ if( key->key_mods & Pk_KM_Ctrl )
+ modifiers |= MOD_MASK_CTRL;
+ if( key->key_mods & Pk_KM_Alt )
+ modifiers |= MOD_MASK_ALT;
+ if( key->key_mods & Pk_KM_Shift )
+ modifiers |= MOD_MASK_SHIFT;
+
+ /* Is this not a special key? */
+ if( special_keys[i].key_sym == 0 )
+ {
+ ch = PhTo8859_1( key );
+ if( ch == -1
+#ifdef FEAT_MBYTE
+ || ( enc_utf8 && ch > 127 )
+#endif
+ )
+ {
+#ifdef FEAT_MBYTE
+ len = PhKeyToMb( string, key );
+ if( len > 0 )
+ {
+ static char buf[6];
+ int src_taken, dst_made;
+ if( enc_utf8 != TRUE )
+ {
+ PxTranslateFromUTF(
+ charset_translate,
+ string,
+ len,
+ &src_taken,
+ buf,
+ 6,
+ &dst_made );
+
+ add_to_input_buf( buf, dst_made );
+ }
+ else
+ {
+ add_to_input_buf( string, len );
+ }
+
+ return( Pt_CONSUME );
+ }
+ len = 0;
+#endif
+ ch = key->key_cap;
+ if( ch < 0xff )
+ {
+ /* FIXME: is this the right thing to do? */
+ if( modifiers & MOD_MASK_CTRL )
+ {
+ modifiers &= ~MOD_MASK_CTRL;
+
+ if( ( ch >= 'a' && ch <= 'z' ) ||
+ ch == '[' ||
+ ch == ']' ||
+ ch == '\\' )
+ ch = Ctrl_chr( ch );
+ else if( ch == '2' )
+ ch = NUL;
+ else if( ch == '6' )
+ ch = 0x1e;
+ else if( ch == '-' )
+ ch = 0x1f;
+ else
+ modifiers |= MOD_MASK_CTRL;
+ }
+
+ if( modifiers & MOD_MASK_ALT )
+ {
+ ch = Meta( ch );
+ modifiers &= ~MOD_MASK_ALT;
+ }
+ }
+ else
+ {
+ return( Pt_CONTINUE );
+ }
+ }
+ else
+ modifiers &= ~MOD_MASK_SHIFT;
+ }
+
+ ch = simplify_key( ch, &modifiers );
+ if( modifiers )
+ {
+ string[ len++ ] = CSI;
+ string[ len++ ] = KS_MODIFIER;
+ string[ len++ ] = modifiers;
+ }
+
+ if( IS_SPECIAL( ch ) )
+ {
+ string[ len++ ] = CSI;
+ string[ len++ ] = K_SECOND( ch );
+ string[ len++ ] = K_THIRD( ch );
+ }
+ else
+ {
+ string[ len++ ] = ch;
+ }
+
+ if (len == 1 && ((ch == Ctrl_C && ctrl_c_interrupts)
+ || ch == intr_char))
+ {
+ trash_input_buf();
+ got_int = TRUE;
+ }
+
+ if (len == 1 && string[0] == CSI)
+ {
+ /* Turn CSI into K_CSI. */
+ string[ len++ ] = KS_EXTRA;
+ string[ len++ ] = KE_CSI;
+ }
+
+ if( len > 0 )
+ {
+ add_to_input_buf( string, len );
+ return( Pt_CONSUME );
+ }
+ }
+
+ return( Pt_CONTINUE );
+}
+
+ static int
+gui_ph_handle_mouse( PtWidget_t *widget, void *data, PtCallbackInfo_t *info )
+{
+ PhPointerEvent_t *pointer;
+ PhRect_t *pos;
+ int button = 0, repeated_click, modifiers = 0x0;
+ short mouse_x, mouse_y;
+
+ pointer = PhGetData( info->event );
+ pos = PhGetRects( info->event );
+
+ gui_mch_mousehide( MOUSE_SHOW );
+
+ /*
+ * Coordinates need to be relative to the base window,
+ * not relative to the vimTextArea widget
+ */
+ mouse_x = pos->ul.x + gui.border_width;
+ mouse_y = pos->ul.y + gui.border_width;
+
+ if( info->event->type == Ph_EV_PTR_MOTION_NOBUTTON )
+ {
+ gui_mouse_moved( mouse_x, mouse_y );
+ return( Pt_CONTINUE );
+ }
+
+ if( pointer->key_mods & Pk_KM_Shift )
+ modifiers |= MOUSE_SHIFT;
+ if( pointer->key_mods & Pk_KM_Ctrl )
+ modifiers |= MOUSE_CTRL;
+ if( pointer->key_mods & Pk_KM_Alt )
+ modifiers |= MOUSE_ALT;
+
+ /*
+ * FIXME More than one button may be involved, but for
+ * now just deal with one
+ */
+ if( pointer->buttons & Ph_BUTTON_SELECT )
+ button = MOUSE_LEFT;
+
+ if( pointer->buttons & Ph_BUTTON_MENU )
+ {
+ button = MOUSE_RIGHT;
+ /* Need the absolute coordinates for the popup menu */
+ abs_mouse.x = pointer->pos.x;
+ abs_mouse.y = pointer->pos.y;
+ }
+
+ if( pointer->buttons & Ph_BUTTON_ADJUST )
+ button = MOUSE_MIDDLE;
+
+ /* Catch a real release (not phantom or other releases */
+ if( info->event->type == Ph_EV_BUT_RELEASE )
+ button = MOUSE_RELEASE;
+
+ if( info->event->type & Ph_EV_PTR_MOTION_BUTTON )
+ button = MOUSE_DRAG;
+
+#if 0
+ /* Vim doesn't use button repeats */
+ if( info->event->type & Ph_EV_BUT_REPEAT )
+ button = MOUSE_DRAG;
+#endif
+
+ /* Don't do anything if it is one of the phantom mouse release events */
+ if( ( button != MOUSE_RELEASE ) ||
+ ( info->event->subtype == Ph_EV_RELEASE_REAL ) )
+ {
+ repeated_click = (pointer->click_count >= 2) ? TRUE : FALSE;
+
+ gui_send_mouse_event( button , mouse_x, mouse_y, repeated_click, modifiers );
+ }
+
+ return( Pt_CONTINUE );
+}
+
+/* Handle a focus change of the PtRaw widget */
+ static int
+gui_ph_handle_focus( PtWidget_t *widget, void *data, PtCallbackInfo_t *info )
+{
+ if( info->reason == Pt_CB_LOST_FOCUS )
+ {
+ PtRemoveEventHandler( gui.vimTextArea, Ph_EV_PTR_MOTION_NOBUTTON,
+ gui_ph_handle_mouse, NULL );
+
+ gui_mch_mousehide( MOUSE_SHOW );
+ }
+ else
+ {
+ PtAddEventHandler( gui.vimTextArea, Ph_EV_PTR_MOTION_NOBUTTON,
+ gui_ph_handle_mouse, NULL );
+ }
+ return( Pt_CONTINUE );
+}
+
+ static void
+gui_ph_handle_raw_draw( PtWidget_t *widget, PhTile_t *damage )
+{
+ PhRect_t *r;
+ PhPoint_t offset;
+ PhPoint_t translation;
+
+ if( is_ignore_draw == TRUE )
+ return;
+
+ PtSuperClassDraw( PtBasic, widget, damage );
+ PgGetTranslation( &translation );
+ PgClearTranslation();
+
+#if 0
+ /*
+ * This causes some wierd probems, with drawing being done from
+ * within this raw drawing function (rather than just simple clearing
+ * and text drawing done by gui_redraw)
+ *
+ * The main problem is when PhBlit is used, and the cursor appearing
+ * in places where it shouldn't
+ */
+ out_flush();
+#endif
+
+ PtWidgetOffset( widget, &offset );
+ PhTranslatePoint( &offset, PtWidgetPos( gui.vimTextArea, NULL ) );
+
+#if 1
+ /* Redraw individual damage regions */
+ if( damage->next != NULL )
+ damage = damage->next;
+
+ while( damage != NULL )
+ {
+ r = &damage->rect;
+ gui_redraw(
+ r->ul.x - offset.x, r->ul.y - offset.y,
+ r->lr.x - r->ul.x + 1,
+ r->lr.y - r->ul.y + 1 );
+ damage = damage->next;
+ }
+#else
+ /* Redraw the rectangle that covers all the damaged regions */
+ r = &damage->rect;
+ gui_redraw(
+ r->ul.x - offset.x, r->ul.y - offset.y,
+ r->lr.x - r->ul.x + 1,
+ r->lr.y - r->ul.y + 1 );
+#endif
+
+ PgSetTranslation( &translation, 0 );
+}
+
+ static int
+gui_ph_handle_pulldown_menu(
+ PtWidget_t *widget,
+ void *data,
+ PtCallbackInfo_t *info )
+{
+ if( data != NULL )
+ {
+ vimmenu_T *menu = (vimmenu_T *) data;
+
+ PtPositionMenu( menu->submenu_id, NULL );
+ PtRealizeWidget( menu->submenu_id );
+ }
+
+ return( Pt_CONTINUE );
+}
+
+/* This is used for pulldown/popup menus and also toolbar buttons */
+ static int
+gui_ph_handle_menu( PtWidget_t *widget, void *data, PtCallbackInfo_t *info )
+{
+ if( data != NULL )
+ {
+ vimmenu_T *menu = (vimmenu_T *) data;
+ gui_menu_cb( menu );
+ }
+ return( Pt_CONTINUE );
+}
+
+/* Stop focus from disappearing into the menubar... */
+ static int
+gui_ph_handle_menu_unrealized(
+ PtWidget_t *widget,
+ void *data,
+ PtCallbackInfo_t *info )
+{
+ PtGiveFocus( gui.vimTextArea, NULL );
+ return( Pt_CONTINUE );
+}
+
+ static int
+gui_ph_handle_window_open(
+ PtWidget_t *widget,
+ void *data,
+ PtCallbackInfo_t *info )
+{
+ gui_set_shellsize( FALSE, TRUE );
+ return( Pt_CONTINUE );
+}
+
+/****************************************************************************/
+
+#define DRAW_START gui_ph_draw_start()
+#define DRAW_END gui_ph_draw_end()
+
+/* TODO: Set a clipping rect? */
+ static void
+gui_ph_draw_start( void )
+{
+ PgSetRegion( PtWidgetRid( PtFindDisjoint( gui.vimTextArea ) ) );
+
+ PtWidgetOffset( gui.vimTextArea, &gui_ph_raw_offset );
+ PhTranslatePoint( &gui_ph_raw_offset, PtWidgetPos( gui.vimTextArea, NULL ) );
+
+ PgSetTranslation( &gui_ph_raw_offset, Pg_RELATIVE );
+}
+
+ static void
+gui_ph_draw_end( void )
+{
+ gui_ph_raw_offset.x = -gui_ph_raw_offset.x;
+ gui_ph_raw_offset.y = -gui_ph_raw_offset.y;
+ PgSetTranslation( &gui_ph_raw_offset, Pg_RELATIVE );
+}
+
+#ifdef USE_PANEL_GROUP
+ static vimmenu_T *
+gui_ph_find_buffer_item( char_u *name )
+{
+ vimmenu_T *top_level = root_menu;
+ vimmenu_T *items = NULL;
+
+ while( top_level != NULL &&
+ ( STRCMP( top_level->dname, "Buffers" ) != 0 ) )
+ top_level = top_level->next;
+
+ if( top_level != NULL )
+ {
+ items = top_level->children;
+
+ while( items != NULL &&
+ ( STRCMP( items->dname, name ) != 0 ) )
+ items = items->next;
+ }
+ return( items );
+}
+
+ static void
+gui_ph_pg_set_buffer_num( int_u buf_num )
+{
+ int i;
+ char search[16];
+ char *mark;
+
+ if( gui.vimTextArea == NULL || buf_num == 0 )
+ return;
+
+ search[0] = '(';
+ ultoa( buf_num, &search[1], 10 );
+ STRCAT( search, ")" );
+
+ for( i = 0; i < num_panels; i++ )
+ {
+ /* find the last "(" in the panel title and see if the buffer
+ * number in the title matches the one we're looking for */
+ mark = STRRCHR( panel_titles[ i ], '(' );
+ if( mark != NULL && STRCMP( mark, search ) == 0 )
+ {
+ PtSetResource( gui.vimPanelGroup, Pt_ARG_PG_CURRENT_INDEX,
+ i, 0 );
+ }
+ }
+}
+
+ static int
+gui_ph_handle_pg_change(
+ PtWidget_t *widget,
+ void *data,
+ PtCallbackInfo_t *info )
+{
+ vimmenu_T *menu;
+ PtPanelGroupCallback_t *panel;
+
+ if( info->event != NULL )
+ {
+ panel = info->cbdata;
+ if( panel->new_panel != NULL )
+ {
+ menu = gui_ph_find_buffer_item( panel->new_panel );
+ if( menu )
+ gui_menu_cb( menu );
+ }
+ }
+ return( Pt_CONTINUE );
+}
+
+ static void
+gui_ph_get_panelgroup_margins(
+ short *top,
+ short *bottom,
+ short *left,
+ short *right )
+{
+ unsigned short abs_raw_x, abs_raw_y, abs_panel_x, abs_panel_y;
+ const unsigned short *margin_top, *margin_bottom;
+ const unsigned short *margin_left, *margin_right;
+
+ PtGetAbsPosition( gui.vimTextArea, &abs_raw_x, &abs_raw_y );
+ PtGetAbsPosition( gui.vimPanelGroup, &abs_panel_x, &abs_panel_y );
+
+ PtGetResource( gui.vimPanelGroup, Pt_ARG_MARGIN_RIGHT, &margin_right, 0 );
+ PtGetResource( gui.vimPanelGroup, Pt_ARG_MARGIN_BOTTOM, &margin_bottom, 0 );
+
+ abs_raw_x -= abs_panel_x;
+ abs_raw_y -= abs_panel_y;
+
+ *top = abs_raw_y;
+ *bottom = *margin_bottom;
+
+ *left = abs_raw_x;
+ *right = *margin_right;
+}
+
+/* Used for the tabs for PtPanelGroup */
+ static int
+gui_ph_is_buffer_item( vimmenu_T *menu, vimmenu_T *parent )
+{
+ char *mark;
+
+ if( STRCMP( parent->dname, "Buffers" ) == 0 )
+ {
+ /* Look for '(' digits ')' */
+ mark = vim_strchr( menu->dname, '(' );
+ if( mark != NULL )
+ {
+ mark++;
+ while( isdigit( *mark ) )
+ mark++;
+
+ if( *mark == ')' )
+ return( TRUE);
+ }
+ }
+ return( FALSE );
+}
+
+ static void
+gui_ph_pg_add_buffer(char *name )
+{
+ char **new_titles = NULL;
+
+ new_titles = (char **) alloc( ( num_panels + 1 ) * sizeof( char ** ) );
+ if( new_titles != NULL )
+ {
+ if( num_panels > 0 )
+ memcpy( new_titles, panel_titles, num_panels * sizeof( char ** ) );
+
+ new_titles[ num_panels++ ] = name;
+
+ PtSetResource( gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, new_titles,
+ num_panels );
+
+ vim_free( panel_titles );
+ panel_titles = new_titles;
+ }
+}
+
+ static void
+gui_ph_pg_remove_buffer( char *name )
+{
+ int i;
+ char **new_titles = NULL;
+
+ /* If there is only 1 panel, we just use the temporary place holder */
+ if( num_panels > 1 )
+ {
+ new_titles = (char **) alloc( ( num_panels - 1 ) * sizeof( char ** ) );
+ if( new_titles != NULL )
+ {
+ char **s = new_titles;
+ /* Copy all the titles except the one we're removing */
+ for( i = 0; i < num_panels; i++ )
+ {
+ if( STRCMP( panel_titles[ i ], name ) != 0 )
+ {
+ *s++ = panel_titles[ i ];
+ }
+ }
+ num_panels--;
+
+ PtSetResource( gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, new_titles,
+ num_panels );
+
+ vim_free( panel_titles );
+ panel_titles = new_titles;
+ }
+ }
+ else
+ {
+ num_panels--;
+ PtSetResource( gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, &empty_title,
+ 1 );
+
+ vim_free( panel_titles );
+ panel_titles = NULL;
+ }
+}
+
+/* When a buffer item is deleted from the buffer menu */
+ static int
+gui_ph_handle_buffer_remove(
+ PtWidget_t *widget,
+ void *data,
+ PtCallbackInfo_t *info )
+{
+ vimmenu_T *menu;
+
+ if( data != NULL )
+ {
+ menu = (vimmenu_T *) data;
+ gui_ph_pg_remove_buffer( menu->dname );
+ }
+
+ return( Pt_CONTINUE );
+}
+#endif
+
+ static int
+gui_ph_pane_resize( PtWidget_t *widget, void *data, PtCallbackInfo_t *info )
+{
+ if( PtWidgetIsRealized( widget ) )
+ {
+ is_ignore_draw = TRUE;
+ PtStartFlux( gui.vimContainer );
+ PtContainerHold( gui.vimContainer );
+ }
+
+ return( Pt_CONTINUE );
+}
+
+/****************************************************************************/
+
+#ifdef FEAT_MBYTE
+ void
+gui_ph_encoding_changed( int new_encoding )
+{
+ /* Default encoding is latin1 */
+ char *charset = "latin1";
+ int i;
+
+ struct {
+ int encoding;
+ char *name;
+ } charsets[] = {
+ { DBCS_JPN, "SHIFT_JIS" },
+ { DBCS_KOR, "csEUCKR" },
+ { DBCS_CHT, "big5" },
+ { DBCS_CHS, "gb" }
+ };
+
+ for( i = 0; i < ARRAY_LENGTH( charsets ); i++ )
+ {
+ if( new_encoding == charsets[ i ].encoding )
+ charset = charsets[ i ].name;
+ }
+
+ charset_translate = PxTranslateSet( charset_translate, charset );
+}
+#endif
+
+/****************************************************************************/
+/****************************************************************************/
+
+ void
+gui_mch_prepare(argc, argv)
+ int *argc;
+ char **argv;
+{
+ PtInit( NULL );
+}
+
+ int
+gui_mch_init(void)
+{
+ PtArg_t args[10];
+ int flags = 0, n = 0;
+
+ PhDim_t window_size = {100, 100}; /* Abitrary values */
+ PhPoint_t pos = {0, 0};
+
+ gui.event_buffer = (PhEvent_t *) alloc( EVENT_BUFFER_SIZE );
+ if( gui.event_buffer == NULL )
+ return( FAIL );
+
+ /* Get a translation so we can convert from ISO Latin-1 to UTF */
+ charset_translate = PxTranslateSet( NULL, "latin1" );
+
+ /* The +2 is for the 1 pixel dark line on each side */
+ gui.border_offset = gui.border_width = GUI_PH_MARGIN + 2;
+
+ /* Handle close events ourselves */
+ PtSetArg( &args[ n++ ], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE );
+ PtSetArg( &args[ n++ ], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE,
+ Ph_WM_CLOSE | Ph_WM_RESIZE | Ph_WM_FOCUS );
+ PtSetArg( &args[ n++ ], Pt_ARG_DIM, &window_size, 0 );
+ gui.vimWindow = PtCreateWidget( PtWindow, NULL, n, args );
+ if( gui.vimWindow == NULL )
+ return( FAIL );
+
+ PtAddCallback( gui.vimWindow, Pt_CB_WINDOW, gui_ph_handle_window_cb, NULL );
+ PtAddCallback( gui.vimWindow, Pt_CB_WINDOW_OPENING,
+ gui_ph_handle_window_open, NULL );
+
+ n = 0;
+ PtSetArg( &args[ n++ ], Pt_ARG_ANCHOR_FLAGS, Pt_ANCHOR_ALL, Pt_IS_ANCHORED );
+ PtSetArg( &args[ n++ ], Pt_ARG_DIM, &window_size, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_POS, &pos, 0 );
+
+#ifdef USE_PANEL_GROUP
+ /* Put in a temprary place holder title */
+ PtSetArg( &args[ n++ ], Pt_ARG_PG_PANEL_TITLES, &empty_title, 1 );
+
+ gui.vimPanelGroup = PtCreateWidget( PtPanelGroup, gui.vimWindow, n, args );
+ if( gui.vimPanelGroup == NULL )
+ return( FAIL );
+
+ PtAddCallback( gui.vimPanelGroup, Pt_CB_PG_PANEL_SWITCHING,
+ gui_ph_handle_pg_change, NULL );
+#else
+ /* Turn off all edge decorations */
+ PtSetArg( &args[ n++ ], Pt_ARG_BASIC_FLAGS, Pt_FALSE, Pt_ALL );
+ PtSetArg( &args[ n++ ], Pt_ARG_BEVEL_WIDTH, 0, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_MARGIN_WIDTH, 0, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_MARGIN_HEIGHT, 0, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_CONTAINER_FLAGS, Pt_TRUE, Pt_AUTO_EXTENT );
+
+ gui.vimContainer = PtCreateWidget( PtPane, gui.vimWindow, n, args );
+ if( gui.vimContainer == NULL )
+ return( FAIL );
+
+ PtAddCallback( gui.vimContainer, Pt_CB_RESIZE, gui_ph_pane_resize, NULL );
+#endif
+
+ /* Size for the text area is set in gui_mch_set_text_area_pos */
+ n = 0;
+
+ PtSetArg( &args[ n++ ], Pt_ARG_RAW_DRAW_F, gui_ph_handle_raw_draw, 1 );
+ PtSetArg( &args[ n++ ], Pt_ARG_BEVEL_WIDTH, GUI_PH_MARGIN, 0 );
+ /*
+ * Using focus render also causes the whole widget to be redrawn
+ * whenever it changes focus, which is very annoying :p
+ */
+ PtSetArg( &args[ n++ ], Pt_ARG_FLAGS, Pt_TRUE,
+ Pt_GETS_FOCUS | Pt_HIGHLIGHTED );
+#ifndef FEAT_MOUSESHAPE
+ PtSetArg( &args[ n++ ], Pt_ARG_CURSOR_TYPE, GUI_PH_MOUSE_TYPE, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_CURSOR_COLOR, gui_ph_mouse_color, 0 );
+#endif
+
+ gui.vimTextArea = PtCreateWidget( PtRaw, Pt_DFLT_PARENT, n, args );
+ if( gui.vimTextArea == NULL)
+ return( FAIL );
+
+ /* TODO: use PtAddEventHandlers instead? */
+ /* Not using Ph_EV_BUT_REPEAT because vim wouldn't use it anyway */
+ PtAddEventHandler( gui.vimTextArea,
+ Ph_EV_BUT_PRESS | Ph_EV_BUT_RELEASE | Ph_EV_PTR_MOTION_BUTTON,
+ gui_ph_handle_mouse, NULL );
+ PtAddEventHandler( gui.vimTextArea, Ph_EV_KEY,
+ gui_ph_handle_keyboard, NULL );
+ PtAddCallback( gui.vimTextArea, Pt_CB_GOT_FOCUS,
+ gui_ph_handle_focus, NULL );
+ PtAddCallback( gui.vimTextArea, Pt_CB_LOST_FOCUS,
+ gui_ph_handle_focus, NULL );
+
+ /*
+ * Now that the text area widget has been created, set up the colours,
+ * which wil call PtSetResource from gui_mch_new_colors
+ */
+
+ /*
+ * Create the two timers, not as accurate as using the kernel timer
+ * functions, but good enough
+ */
+ gui_ph_timer_cursor = PtCreateWidget( PtTimer, gui.vimWindow, 0, NULL );
+ if( gui_ph_timer_cursor == NULL )
+ return( FAIL );
+
+ gui_ph_timer_timeout = PtCreateWidget( PtTimer, gui.vimWindow, 0, NULL );
+ if( gui_ph_timer_timeout == NULL )
+ return( FAIL );
+
+ PtAddCallback( gui_ph_timer_cursor, Pt_CB_TIMER_ACTIVATE,
+ gui_ph_handle_timer_cursor, NULL);
+ PtAddCallback( gui_ph_timer_timeout, Pt_CB_TIMER_ACTIVATE,
+ gui_ph_handle_timer_timeout, NULL);
+
+#ifdef FEAT_MENU
+ n = 0;
+ PtSetArg( &args[ n++ ], Pt_ARG_WIDTH, window_size.w, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_ANCHOR_FLAGS, Pt_ANCHOR_LEFT_RIGHT,
+ Pt_IS_ANCHORED );
+ gui.vimToolBarGroup = PtCreateWidget( PtToolbarGroup, gui.vimWindow,
+ n, args );
+ if( gui.vimToolBarGroup == NULL )
+ return( FAIL );
+
+ PtAddCallback( gui.vimToolBarGroup, Pt_CB_RESIZE,
+ gui_ph_handle_menu_resize, NULL );
+
+ n = 0;
+ flags = 0;
+ PtSetArg( &args[ n++ ], Pt_ARG_WIDTH, window_size.w, 0 );
+ if( ! vim_strchr( p_go, GO_MENUS ) )
+ {
+ flags |= Pt_DELAY_REALIZE;
+ PtSetArg( &args[ n++ ], Pt_ARG_FLAGS, Pt_TRUE, flags );
+ }
+ gui.vimMenuBar = PtCreateWidget( PtMenuBar, gui.vimToolBarGroup, n, args );
+ if( gui.vimMenuBar == NULL )
+ return( FAIL );
+
+# ifdef FEAT_TOOLBAR
+ n = 0;
+
+ PtSetArg( &args[ n++ ], Pt_ARG_ANCHOR_FLAGS,
+ Pt_ANCHOR_LEFT_RIGHT |Pt_TOP_ANCHORED_TOP, Pt_IS_ANCHORED );
+ PtSetArg( &args[ n++ ], Pt_ARG_RESIZE_FLAGS, Pt_TRUE,
+ Pt_RESIZE_Y_AS_REQUIRED );
+ PtSetArg( &args[ n++ ], Pt_ARG_WIDTH, window_size.w, 0 );
+
+ flags = Pt_GETS_FOCUS;
+ if( ! vim_strchr( p_go, GO_TOOLBAR ) )
+ flags |= Pt_DELAY_REALIZE;
+
+ PtSetArg( &args[ n++ ], Pt_ARG_FLAGS, Pt_DELAY_REALIZE, flags );
+
+ gui.vimToolBar = PtCreateWidget( PtToolbar, gui.vimToolBarGroup, n, args );
+ if( gui.vimToolBar == NULL )
+ return( FAIL );
+
+ /*
+ * Size for the toolbar is fetched in gui_mch_show_toolbar, after
+ * the buttons have been added and the toolbar has resized it's height
+ * for the buttons to fit
+ */
+# endif
+
+#endif
+
+ return( OK );
+}
+
+ int
+gui_mch_init_check(void)
+{
+ return( (is_photon_available == TRUE) ? OK : FAIL );
+}
+
+ int
+gui_mch_open(void)
+{
+ gui.norm_pixel = Pg_BLACK;
+ gui.back_pixel = Pg_WHITE;
+
+ set_normal_colors();
+
+ gui_check_colors();
+ gui.def_norm_pixel = gui.norm_pixel;
+ gui.def_back_pixel = gui.back_pixel;
+
+ highlight_gui_started();
+
+ if (gui_win_x != -1 && gui_win_y != -1)
+ gui_mch_set_winpos(gui_win_x, gui_win_y);
+
+ return( (PtRealizeWidget( gui.vimWindow ) == 0) ? OK : FAIL );
+}
+
+ void
+gui_mch_exit(int rc)
+{
+ PtDestroyWidget( gui.vimWindow );
+
+ PxTranslateSet( charset_translate, NULL );
+
+ vim_free( gui.event_buffer );
+
+#ifdef USE_PANEL_GROUPS
+ vim_free( panel_titles );
+#endif
+}
+
+/****************************************************************************/
+/* events */
+
+/* When no events are available, photon will call this function, working is
+ * set to FALSE, and the gui_mch_update loop will exit. */
+ static int
+exit_gui_mch_update( void *data )
+{
+ *(int *)data = FALSE;
+ return( Pt_END );
+}
+
+ void
+gui_mch_update(void)
+{
+ int working = TRUE;
+
+ PtAppAddWorkProc( NULL, exit_gui_mch_update, &working );
+ while( ( working == TRUE ) && !vim_is_input_buf_full())
+ {
+ PtProcessEvent();
+ }
+}
+
+ int
+gui_mch_wait_for_chars(int wtime)
+{
+ is_timeout = FALSE;
+
+ if( wtime > 0 )
+ PtSetResource( gui_ph_timer_timeout, Pt_ARG_TIMER_INITIAL, wtime, 0 );
+
+ while( 1 )
+ {
+ PtProcessEvent();
+ if( input_available() )
+ {
+ PtSetResource( gui_ph_timer_timeout, Pt_ARG_TIMER_INITIAL, 0, 0 );
+ return( OK );
+ }
+ else if( is_timeout == TRUE )
+ return( FAIL );
+ }
+}
+
+#if defined( FEAT_BROWSE ) || defined( PROTO )
+/*
+ * Put up a file requester.
+ * Returns the selected name in allocated memory, or NULL for Cancel.
+ * saving, select file to write
+ * title title for the window
+ * default_name default name (well duh!)
+ * ext not used (extension added)
+ * initdir initial directory, NULL for current dir
+ * filter not used (file name filter)
+ */
+ char_u *
+gui_mch_browse(
+ int saving,
+ char_u *title,
+ char_u *default_name,
+ char_u *ext,
+ char_u *initdir,
+ char_u *filter)
+{
+ PtFileSelectionInfo_t file;
+ int flags;
+ char_u *default_path;
+ char_u *open_text = NULL;
+
+ flags = 0;
+ memset( &file, 0, sizeof( file ) );
+
+ default_path = alloc( MAXPATHL + 1 + NAME_MAX + 1 );
+ if( default_path != NULL )
+ {
+ if( saving == TRUE )
+ {
+ /* Don't need Pt_FSR_CONFIRM_EXISTING, vim will ask anyway */
+ flags |= Pt_FSR_NO_FCHECK;
+ open_text = "&Save";
+ }
+
+ /* combine the directory and filename into a single path */
+ if( initdir == NULL || *initdir == NUL )
+ {
+ mch_dirname( default_path, MAXPATHL );
+ initdir = default_path;
+ }
+ else
+ {
+ STRCPY( default_path, initdir );
+ initdir = default_path;
+ }
+
+ if( default_name != NULL )
+ {
+ if( default_path[ STRLEN( default_path ) - 1 ] != '/' )
+ STRCAT( default_path, "/" );
+
+ STRCAT( default_path, default_name );
+ }
+
+ /* TODO: add a filter? */
+ PtFileSelection(
+ gui.vimWindow,
+ NULL,
+ title,
+ default_path,
+ NULL,
+ open_text,
+ NULL,
+ NULL,
+ &file,
+ flags );
+
+ vim_free( default_path );
+
+ if( file.ret == Pt_FSDIALOG_BTN1 )
+ return( vim_strsave( file.path ) );
+ }
+ return( NULL );
+}
+#endif
+
+#if defined( FEAT_GUI_DIALOG ) || defined( PROTO )
+static PtWidget_t *gui_ph_dialog_text = NULL;
+
+ static int
+gui_ph_dialog_close( int button, void *data )
+{
+ PtModalCtrl_t *modal_ctrl = data;
+ char_u *dialog_text, *vim_text;
+
+ if( gui_ph_dialog_text != NULL )
+ {
+ PtGetResource( gui_ph_dialog_text, Pt_ARG_TEXT_STRING, &dialog_text, 0 );
+ PtGetResource( gui_ph_dialog_text, Pt_ARG_POINTER, &vim_text, 0 );
+ STRNCPY( vim_text, dialog_text, IOSIZE - 1 );
+ }
+
+ PtModalUnblock( modal_ctrl, (void *) button );
+
+ return( Pt_TRUE );
+}
+
+ static int
+gui_ph_dialog_text_enter( PtWidget_t *widget, void *data, PtCallbackInfo_t *info )
+{
+ if( info->reason_subtype == Pt_EDIT_ACTIVATE )
+ gui_ph_dialog_close( 1, data );
+ return( Pt_CONTINUE );
+}
+
+ static int
+gui_ph_dialog_esc( PtWidget_t *widget, void *data, PtCallbackInfo_t *info )
+{
+ PhKeyEvent_t *key;
+
+ key = PhGetData( info->event );
+ if( ( key->key_flags & Pk_KF_Cap_Valid ) && ( key->key_cap == Pk_Escape ) )
+ {
+ gui_ph_dialog_close( 0, data );
+ return( Pt_CONSUME );
+ }
+ return( Pt_PROCESS );
+}
+
+ int
+gui_mch_dialog(
+ int type,
+ char_u *title,
+ char_u *message,
+ char_u *buttons,
+ int default_button,
+ char_u *textfield)
+{
+ char_u *str;
+ char_u **button_array;
+ char_u *buttons_copy;
+
+ int button_count;
+ int i, len;
+ int dialog_result = -1;
+
+ /* FIXME: the vertical option in guioptions is blatantly ignored */
+ /* FIXME: so is the type */
+
+ button_count = len = i = 0;
+
+ if( buttons == NULL || *buttons == NUL )
+ return( -1 );
+
+ /* There is one less separator than buttons, so bump up the button count */
+ button_count = 1;
+
+ /* Count string length and number of seperators */
+ for( str = buttons; *str; str++ )
+ {
+ len++;
+ if( *str == DLG_BUTTON_SEP )
+ button_count++;
+ }
+
+ if ( title == NULL )
+ title = "Vim";
+
+ buttons_copy = alloc( len + 1 );
+ button_array = (char_u **) alloc( button_count * sizeof( char_u * ) );
+ if( buttons_copy != NULL && button_array != NULL )
+ {
+ STRCPY( buttons_copy, buttons );
+
+ /*
+ * Convert DLG_BUTTON_SEP into NUL's and fill in
+ * button_array with the pointer to each NUL terminated string
+ */
+ str = buttons_copy;
+ for( i = 0; i < button_count; i++ )
+ {
+ button_array[ i ] = str;
+ for( ; *str; str++ )
+ {
+ if( *str == DLG_BUTTON_SEP )
+ {
+ *str++ = NUL;
+ break;
+ }
+ }
+ }
+#ifndef FEAT_GUI_TEXTDIALOG
+ dialog_result = PtAlert(
+ gui.vimWindow, NULL,
+ title,
+ NULL,
+ message, NULL,
+ button_count, (const char **) button_array, NULL,
+ default_button, 0, Pt_MODAL );
+#else
+ /* Writing the dialog ourselves lets us add extra features, like
+ * trapping the escape key and returning 0 to vim */
+ {
+ int n;
+ PtArg_t args[5];
+ PtWidget_t *dialog, *pane;
+ PtModalCtrl_t modal_ctrl;
+ PtDialogInfo_t di;
+
+ memset( &di, 0, sizeof( di ) );
+ memset( &modal_ctrl, 0, sizeof( modal_ctrl ) );
+
+ n = 0;
+ PtSetArg( &args[n++], Pt_ARG_GROUP_ROWS_COLS, 0, 0 );
+ PtSetArg( &args[n++], Pt_ARG_WIDTH, 350, 0 );
+ PtSetArg( &args[n++], Pt_ARG_GROUP_ORIENTATION,
+ Pt_GROUP_VERTICAL, 0 );
+ PtSetArg( &args[n++], Pt_ARG_GROUP_FLAGS,
+ Pt_TRUE, Pt_GROUP_NO_KEYS | Pt_GROUP_STRETCH_HORIZONTAL );
+ PtSetArg( &args[n++], Pt_ARG_CONTAINER_FLAGS, Pt_FALSE, Pt_TRUE );
+ pane = PtCreateWidget( PtGroup, NULL, n, args );
+
+ n = 0;
+ PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, message, 0 );
+ PtCreateWidget( PtLabel, pane, n, args );
+
+ if( textfield != NULL )
+ {
+ n = 0;
+ PtSetArg( &args[n++], Pt_ARG_MAX_LENGTH, IOSIZE - 1, 0 );
+ PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, textfield, 0 );
+ PtSetArg( &args[n++], Pt_ARG_POINTER, textfield, 0 );
+ gui_ph_dialog_text = PtCreateWidget( PtText, pane, n, args );
+ PtAddCallback( gui_ph_dialog_text, Pt_CB_ACTIVATE,
+ gui_ph_dialog_text_enter, &modal_ctrl );
+ }
+
+ di.parent = gui.vimWindow;
+ di.pane = pane;
+ di.title = title;
+ di.buttons = (const char **) button_array;
+ di.nbtns = button_count;
+ di.def_btn = default_button;
+ /* This is just to give the dialog the close button.
+ * We check for the Escape key ourselves and return 0 */
+ di.esc_btn = button_count;
+ di.callback = gui_ph_dialog_close;
+ di.data = &modal_ctrl;
+
+ dialog = PtCreateDialog( &di );
+ PtAddFilterCallback( dialog, Ph_EV_KEY,
+ gui_ph_dialog_esc, &modal_ctrl );
+
+ if( gui_ph_dialog_text != NULL )
+ PtGiveFocus( gui_ph_dialog_text, NULL );
+
+ /* Open dialog, block the vim window and wait for the dialog to close */
+ PtRealizeWidget( dialog );
+ PtMakeModal( dialog, Ph_CURSOR_NOINPUT, Ph_CURSOR_DEFAULT_COLOR );
+ dialog_result = (int) PtModalBlock( &modal_ctrl, 0 );
+
+ PtDestroyWidget( dialog );
+ gui_ph_dialog_text = NULL;
+ }
+#endif
+ }
+
+ vim_free( button_array );
+ vim_free( buttons_copy );
+
+ return( dialog_result );
+}
+#endif
+/****************************************************************************/
+/* window size/position/state */
+
+ int
+gui_mch_get_winpos(int *x, int *y)
+{
+ PhPoint_t *pos;
+
+ pos = PtWidgetPos( gui.vimWindow, NULL );
+
+ *x = pos->x;
+ *y = pos->y;
+
+ return( OK );
+}
+
+ void
+gui_mch_set_winpos(int x, int y)
+{
+ PhPoint_t pos = { x, y };
+
+ PtSetResource( gui.vimWindow, Pt_ARG_POS, &pos, 0 );
+}
+
+ void
+gui_mch_set_shellsize(int width, int height,
+ int min_width, int min_height, int base_width, int base_height)
+{
+ PhDim_t window_size = { width, height };
+ PhDim_t min_size = { min_width, min_height };
+
+#ifdef USE_PANEL_GROUP
+ window_size.w += pg_margin_left + pg_margin_right;
+ window_size.h += pg_margin_top + pg_margin_bottom;
+#endif
+
+ PtSetResource( gui.vimWindow, Pt_ARG_MINIMUM_DIM, &min_size, 0 );
+ PtSetResource( gui.vimWindow, Pt_ARG_DIM, &window_size, 0 );
+
+ if( ! PtWidgetIsRealized( gui.vimWindow ) )
+ gui_ph_resize_container();
+}
+
+/*
+ * Return the amount of screen space that hasn't been allocated (such as
+ * by the shelf).
+ */
+ void
+gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
+{
+ PhRect_t console;
+
+ PhWindowQueryVisible( Ph_QUERY_WORKSPACE, 0,
+ PhInputGroup( NULL ), &console );
+
+ *screen_w = console.lr.x - console.ul.x + 1;
+ *screen_h = console.lr.y - console.ul.y + 1;
+}
+
+ void
+gui_mch_iconify(void)
+{
+ PhWindowEvent_t event;
+
+ memset( &event, 0, sizeof (event) );
+ event.event_f = Ph_WM_HIDE;
+ event.event_state = Ph_WM_EVSTATE_HIDE;
+ event.rid = PtWidgetRid( gui.vimWindow );
+ PtForwardWindowEvent( &event );
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Bring the Vim window to the foreground.
+ */
+ void
+gui_mch_set_foreground()
+{
+ PhWindowEvent_t event;
+
+ memset( &event, 0, sizeof (event) );
+ event.event_f = Ph_WM_TOFRONT;
+ event.event_state = Ph_WM_EVSTATE_FFRONT;
+ event.rid = PtWidgetRid( gui.vimWindow );
+ PtForwardWindowEvent( &event );
+}
+#endif
+
+ void
+gui_mch_settitle(char_u *title, char_u *icon)
+{
+#ifdef USE_PANEL_GROUP
+ gui_ph_pg_set_buffer_num( curwin->w_buffer->b_fnum );
+#endif
+ PtSetResource( gui.vimWindow, Pt_ARG_WINDOW_TITLE, title, 0 );
+ /* Not sure what to do with the icon text, set balloon text somehow? */
+}
+
+/****************************************************************************/
+/* Scrollbar */
+
+ void
+gui_mch_set_scrollbar_thumb(scrollbar_T *sb, int val, int size, int max)
+{
+ int n = 0;
+ PtArg_t args[3];
+
+ PtSetArg( &args[ n++ ], Pt_ARG_MAXIMUM, max, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_SLIDER_SIZE, size, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_GAUGE_VALUE, val, 0 );
+ PtSetResources( sb->id, n, args );
+}
+
+ void
+gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h)
+{
+ PhArea_t area = {{ x, y }, { w, h }};
+
+ PtSetResource( sb->id, Pt_ARG_AREA, &area, 0 );
+}
+
+ void
+gui_mch_create_scrollbar(scrollbar_T *sb, int orient)
+{
+ int n = 0;
+/* int anchor_flags = 0;*/
+ PtArg_t args[4];
+
+ /*
+ * Stop the scrollbar from being realized when the parent
+ * is realized, so it can be explicitly realized by vim.
+ *
+ * Also, don't let the scrollbar get focus
+ */
+ PtSetArg( &args[ n++ ], Pt_ARG_FLAGS, Pt_DELAY_REALIZE,
+ Pt_DELAY_REALIZE | Pt_GETS_FOCUS );
+ PtSetArg( &args[ n++ ], Pt_ARG_SCROLLBAR_FLAGS, Pt_SCROLLBAR_SHOW_ARROWS, 0);
+#if 0
+ /* Don't need this anchoring for the scrollbars */
+ if( orient == SBAR_HORIZ )
+ {
+ anchor_flags = Pt_BOTTOM_ANCHORED_BOTTOM |
+ Pt_LEFT_ANCHORED_LEFT | Pt_RIGHT_ANCHORED_RIGHT;
+ }
+ else
+ {
+ anchor_flags = Pt_BOTTOM_ANCHORED_BOTTOM | Pt_TOP_ANCHORED_TOP;
+ if( sb->wp != NULL )
+ {
+ if( sb == &sb->wp->w_scrollbars[ SBAR_LEFT ] )
+ anchor_flags |= Pt_LEFT_ANCHORED_LEFT;
+ else
+ anchor_flags |= Pt_RIGHT_ANCHORED_RIGHT;
+ }
+ }
+ PtSetArg( &args[ n++ ], Pt_ARG_ANCHOR_FLAGS, anchor_flags, Pt_IS_ANCHORED );
+#endif
+ PtSetArg( &args[ n++ ], Pt_ARG_ORIENTATION,
+ (orient == SBAR_HORIZ) ? Pt_HORIZONTAL : Pt_VERTICAL, 0 );
+#ifdef USE_PANEL_GROUP
+ sb->id = PtCreateWidget( PtScrollbar, gui.vimPanelGroup, n, args );
+#else
+ sb->id = PtCreateWidget( PtScrollbar, gui.vimContainer, n, args );
+#endif
+
+ PtAddCallback( sb->id, Pt_CB_SCROLLBAR_MOVE, gui_ph_handle_scrollbar, sb );
+}
+
+ void
+gui_mch_enable_scrollbar(scrollbar_T *sb, int flag)
+{
+ if( flag != 0 )
+ PtRealizeWidget( sb->id );
+ else
+ PtUnrealizeWidget( sb->id );
+}
+
+ void
+gui_mch_destroy_scrollbar(scrollbar_T *sb)
+{
+ PtDestroyWidget( sb->id );
+ sb->id = NULL;
+}
+
+/****************************************************************************/
+/* Mouse functions */
+
+#if defined(FEAT_MOUSESHAPE) || defined(PROTO)
+/* The last set mouse pointer shape is remembered, to be used when it goes
+ * from hidden to not hidden. */
+static int last_shape = 0;
+
+/* Table for shape IDs. Keep in sync with the mshape_names[] table in
+ * misc2.c! */
+static int mshape_ids[] =
+{
+ Ph_CURSOR_POINTER, /* arrow */
+ Ph_CURSOR_NONE, /* blank */
+ Ph_CURSOR_INSERT, /* beam */
+ Ph_CURSOR_DRAG_VERTICAL, /* updown */
+ Ph_CURSOR_DRAG_VERTICAL, /* udsizing */
+ Ph_CURSOR_DRAG_HORIZONTAL, /* leftright */
+ Ph_CURSOR_DRAG_HORIZONTAL, /* lrsizing */
+ Ph_CURSOR_WAIT, /* busy */
+ Ph_CURSOR_DONT, /* no */
+ Ph_CURSOR_CROSSHAIR, /* crosshair */
+ Ph_CURSOR_FINGER, /* hand1 */
+ Ph_CURSOR_FINGER, /* hand2 */
+ Ph_CURSOR_FINGER, /* pencil */
+ Ph_CURSOR_QUESTION_POINT, /* question */
+ Ph_CURSOR_POINTER, /* right-arrow */
+ Ph_CURSOR_POINTER, /* up-arrow */
+ Ph_CURSOR_POINTER /* last one */
+};
+
+ void
+mch_set_mouse_shape(shape)
+ int shape;
+{
+ int id;
+
+ if (!gui.in_use)
+ return;
+
+ if (shape == MSHAPE_HIDE || gui.pointer_hidden)
+ PtSetResource( gui.vimTextArea, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NONE,
+ 0 );
+ else
+ {
+ if (shape >= MSHAPE_NUMBERED)
+ id = Ph_CURSOR_POINTER;
+ else
+ id = mshape_ids[shape];
+
+ PtSetResource( gui.vimTextArea, Pt_ARG_CURSOR_TYPE, id, 0 );
+ }
+ if (shape != MSHAPE_HIDE)
+ last_shape = shape;
+}
+#endif
+
+ void
+gui_mch_mousehide(int hide)
+{
+ if( gui.pointer_hidden != hide )
+ {
+ gui.pointer_hidden = hide;
+#ifdef FEAT_MOUSESHAPE
+ if( hide )
+ PtSetResource( gui.vimTextArea, Pt_ARG_CURSOR_TYPE,
+ Ph_CURSOR_NONE, 0 );
+ else
+ mch_set_mouse_shape( last_shape );
+#else
+ PtSetResource( gui.vimTextArea, Pt_ARG_CURSOR_TYPE,
+ ( hide == MOUSE_SHOW ) ? GUI_PH_MOUSE_TYPE : Ph_CURSOR_NONE,
+ 0 );
+#endif
+ }
+}
+
+ int
+gui_mch_get_mouse_x(void)
+{
+ PhCursorInfo_t info;
+ short x, y;
+
+ /* FIXME: does this return the correct position,
+ * with respect to the border? */
+ PhQueryCursor( PhInputGroup( NULL ), &info );
+ PtGetAbsPosition( gui.vimTextArea , &x, &y );
+
+ return( info.pos.x - x );
+}
+
+ int
+gui_mch_get_mouse_y(void)
+{
+ PhCursorInfo_t info;
+ short x, y;
+
+ PhQueryCursor( PhInputGroup( NULL ), &info );
+ PtGetAbsPosition( gui.vimTextArea , &x, &y );
+ /* TODO: Add border offset? */
+ return( info.pos.y - y );
+}
+
+ void
+gui_mch_setmouse(int x, int y)
+{
+ short abs_x, abs_y;
+
+ PtGetAbsPosition( gui.vimTextArea, &abs_x, &abs_y );
+ /* Add the border offset? */
+ PhMoveCursorAbs( PhInputGroup( NULL ), abs_x + x, abs_y + y );
+}
+
+/****************************************************************************/
+/* Colours */
+
+/*
+ * Return the RGB value of a pixel as a long.
+ */
+ long_u
+gui_mch_get_rgb(guicolor_T pixel)
+{
+ return PgRGB(PgRedValue(pixel), PgGreenValue(pixel), PgBlueValue(pixel));
+}
+
+ void
+gui_mch_new_colors(void)
+{
+#if 0 /* Don't bother changing the cursor colour */
+ short color_diff;
+
+ /*
+ * If there isn't enough difference between the background colour and
+ * the mouse pointer colour then change the mouse pointer colour
+ */
+ color_diff = gui_get_lightness(gui_ph_mouse_color)
+ - gui_get_lightness(gui.back_pixel);
+
+ if( abs( color_diff ) < 64 )
+ {
+ short r, g, b;
+ /* not a great algorithm... */
+ r = PgRedValue( gui_ph_mouse_color ) ^ 255;
+ g = PgGreenValue( gui_ph_mouse_color ) ^ 255;
+ b = PgBlueValue( gui_ph_mouse_color ) ^ 255;
+
+#ifndef FEAT_MOUSESHAPE
+ gui_ph_mouse_color = PgRGB( r, g, b );
+ PtSetResource( gui.vimTextArea, Pt_ARG_CURSOR_COLOR,
+ gui_ph_mouse_color, 0 );
+#endif
+ }
+#endif
+
+ PtSetResource( gui.vimTextArea, Pt_ARG_FILL_COLOR, gui.back_pixel, 0 );
+}
+
+ static int
+hex_digit(int c)
+{
+ if (VIM_ISDIGIT(c))
+ return( c - '0' );
+ c = TOLOWER_ASC(c);
+ if (c >= 'a' && c <= 'f')
+ return( c - 'a' + 10 );
+ return( -1000 );
+}
+
+
+/*
+ * This should be split out into a seperate file,
+ * every port does basically the same thing.
+ *
+ * This is the gui_w32.c version (i think..)
+ * Return INVALCOLOR when failed.
+ */
+
+ guicolor_T
+gui_mch_get_color(char_u *name)
+{
+ int i;
+ int r, g, b;
+
+
+ typedef struct GuiColourTable
+ {
+ char *name;
+ guicolor_T colour;
+ } GuiColourTable;
+
+ static GuiColourTable table[] =
+ {
+ {"Black", RGB(0x00, 0x00, 0x00)},
+ {"DarkGray", RGB(0x80, 0x80, 0x80)},
+ {"DarkGrey", RGB(0x80, 0x80, 0x80)},
+ {"Gray", RGB(0xC0, 0xC0, 0xC0)},
+ {"Grey", RGB(0xC0, 0xC0, 0xC0)},
+ {"LightGray", RGB(0xD3, 0xD3, 0xD3)},
+ {"LightGrey", RGB(0xD3, 0xD3, 0xD3)},
+ {"White", RGB(0xFF, 0xFF, 0xFF)},
+ {"DarkRed", RGB(0x80, 0x00, 0x00)},
+ {"Red", RGB(0xFF, 0x00, 0x00)},
+ {"LightRed", RGB(0xFF, 0xA0, 0xA0)},
+ {"DarkBlue", RGB(0x00, 0x00, 0x80)},
+ {"Blue", RGB(0x00, 0x00, 0xFF)},
+ {"LightBlue", RGB(0xA0, 0xA0, 0xFF)},
+ {"DarkGreen", RGB(0x00, 0x80, 0x00)},
+ {"Green", RGB(0x00, 0xFF, 0x00)},
+ {"LightGreen", RGB(0xA0, 0xFF, 0xA0)},
+ {"DarkCyan", RGB(0x00, 0x80, 0x80)},
+ {"Cyan", RGB(0x00, 0xFF, 0xFF)},
+ {"LightCyan", RGB(0xA0, 0xFF, 0xFF)},
+ {"DarkMagenta", RGB(0x80, 0x00, 0x80)},
+ {"Magenta", RGB(0xFF, 0x00, 0xFF)},
+ {"LightMagenta", RGB(0xFF, 0xA0, 0xFF)},
+ {"Brown", RGB(0x80, 0x40, 0x40)},
+ {"Yellow", RGB(0xFF, 0xFF, 0x00)},
+ {"LightYellow", RGB(0xFF, 0xFF, 0xA0)},
+ {"SeaGreen", RGB(0x2E, 0x8B, 0x57)},
+ {"Orange", RGB(0xFF, 0xA5, 0x00)},
+ {"Purple", RGB(0xA0, 0x20, 0xF0)},
+ {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)},
+ {"Violet", RGB(0xEE, 0x82, 0xEE)},
+ };
+
+ /* is name #rrggbb format? */
+ if( name[0] == '#' && STRLEN( name ) == 7 )
+ {
+ r = hex_digit( name[1] ) * 16 + hex_digit( name[2] );
+ g = hex_digit( name[3] ) * 16 + hex_digit( name[4] );
+ b = hex_digit( name[5] ) * 16 + hex_digit( name[6] );
+ if( r < 0 || g < 0 || b < 0 )
+ return INVALCOLOR;
+ return( RGB( r, g, b ) );
+ }
+
+ for( i = 0; i < ARRAY_LENGTH( table ); i++ )
+ {
+ if( STRICMP( name, table[i].name ) == 0 )
+ return( table[i].colour );
+ }
+
+ /*
+ * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt".
+ */
+ {
+#define LINE_LEN 100
+ FILE *fd;
+ char line[LINE_LEN];
+ char_u *fname;
+
+ fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
+ if (fname == NULL)
+ return INVALCOLOR;
+
+ fd = fopen((char *)fname, "rt");
+ vim_free(fname);
+ if (fd == NULL)
+ return INVALCOLOR;
+
+ while (!feof(fd))
+ {
+ int len;
+ int pos;
+ char *color;
+
+ fgets(line, LINE_LEN, fd);
+ len = STRLEN(line);
+
+ if (len <= 1 || line[len-1] != '\n')
+ continue;
+
+ line[len-1] = '\0';
+
+ i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
+ if (i != 3)
+ continue;
+
+ color = line + pos;
+
+ if (STRICMP(color, name) == 0)
+ {
+ fclose(fd);
+ return( (guicolor_T) RGB(r,g,b) );
+ }
+ }
+
+ fclose(fd);
+ }
+
+
+ return INVALCOLOR;
+}
+
+ void
+gui_mch_set_fg_color(guicolor_T color)
+{
+ PgSetTextColor( color );
+}
+
+ void
+gui_mch_set_bg_color(guicolor_T color)
+{
+ PgSetFillColor( color );
+}
+
+ void
+gui_mch_invert_rectangle(int row, int col, int nr, int nc)
+{
+ PhRect_t rect;
+
+ rect.ul.x = FILL_X( col );
+ rect.ul.y = FILL_Y( row );
+
+ /* FIXME: This has an off by one pixel problem */
+ rect.lr.x = rect.ul.x + nc * gui.char_width;
+ rect.lr.y = rect.ul.y + nr * gui.char_height;
+ if( nc > 0 )
+ rect.lr.x -= 1;
+ if( nr > 0 )
+ rect.lr.y -= 1;
+
+ DRAW_START;
+ PgSetDrawMode( Pg_DrawModeDSTINVERT );
+ PgDrawRect( &rect, Pg_DRAW_FILL );
+ PgSetDrawMode( Pg_DrawModeSRCCOPY );
+ DRAW_END;
+}
+
+ void
+gui_mch_clear_block(int row1, int col1, int row2, int col2)
+{
+ PhRect_t block = {
+ { FILL_X( col1 ), FILL_Y( row1 ) },
+ { FILL_X( col2 + 1 ) - 1, FILL_Y( row2 + 1 ) - 1}
+ };
+
+ DRAW_START;
+ gui_mch_set_bg_color( gui.back_pixel );
+ PgDrawRect( &block, Pg_DRAW_FILL );
+ DRAW_END;
+}
+
+ void
+gui_mch_clear_all()
+{
+ PhRect_t text_rect = {
+ { gui.border_width, gui.border_width },
+ { Columns * gui.char_width + gui.border_width - 1 ,
+ Rows * gui.char_height + gui.border_width - 1 }
+ };
+
+ if( is_ignore_draw == TRUE )
+ return;
+
+ DRAW_START;
+ gui_mch_set_bg_color( gui.back_pixel );
+ PgDrawRect( &text_rect, Pg_DRAW_FILL );
+ DRAW_END;
+}
+
+ void
+gui_mch_delete_lines(int row, int num_lines)
+{
+ PhRect_t rect;
+ PhPoint_t delta;
+
+ rect.ul.x = FILL_X( gui.scroll_region_left );
+ rect.ul.y = FILL_Y( row + num_lines );
+
+ rect.lr.x = FILL_X( gui.scroll_region_right + 1 ) - 1;
+ rect.lr.y = FILL_Y( gui.scroll_region_bot + 1) - 1;
+
+ PtWidgetOffset( gui.vimTextArea, &gui_ph_raw_offset );
+ PhTranslatePoint( &gui_ph_raw_offset, PtWidgetPos(gui.vimTextArea, NULL));
+ PhTranslateRect( &rect, &gui_ph_raw_offset );
+
+ delta.x = 0;
+ delta.y = -num_lines * gui.char_height;
+
+ PgFlush();
+
+ PhBlit( PtWidgetRid( PtFindDisjoint( gui.vimTextArea ) ), &rect, &delta );
+
+ gui_clear_block(
+ gui.scroll_region_bot - num_lines + 1,
+ gui.scroll_region_left,
+ gui.scroll_region_bot,
+ gui.scroll_region_right );
+}
+
+ void
+gui_mch_insert_lines(int row, int num_lines)
+{
+ PhRect_t rect;
+ PhPoint_t delta;
+
+ rect.ul.x = FILL_X( gui.scroll_region_left );
+ rect.ul.y = FILL_Y( row );
+
+ rect.lr.x = FILL_X( gui.scroll_region_right + 1 ) - 1;
+ rect.lr.y = FILL_Y( gui.scroll_region_bot - num_lines + 1 ) - 1;
+
+ PtWidgetOffset( gui.vimTextArea, &gui_ph_raw_offset );
+ PhTranslatePoint( &gui_ph_raw_offset, PtWidgetPos( gui.vimTextArea, NULL ) );
+ PhTranslateRect( &rect, &gui_ph_raw_offset );
+
+ delta.x = 0;
+ delta.y = num_lines * gui.char_height;
+
+ PgFlush();
+
+ PhBlit( PtWidgetRid( PtFindDisjoint( gui.vimTextArea ) ) , &rect, &delta );
+
+ gui_clear_block( row, gui.scroll_region_left,
+ row + num_lines - 1, gui.scroll_region_right );
+}
+
+ void
+gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
+{
+ static char *utf8_buffer = NULL;
+ static int utf8_len = 0;
+
+ PhPoint_t pos = { TEXT_X( col ), TEXT_Y( row ) };
+ PhRect_t rect;
+
+ if( is_ignore_draw == TRUE )
+ return;
+
+ DRAW_START;
+
+ if( !( flags & DRAW_TRANSP ) )
+ {
+ PgDrawIRect(
+ FILL_X( col ), FILL_Y( row ),
+ FILL_X( col + len ) - 1, FILL_Y( row + 1 ) - 1,
+ Pg_DRAW_FILL );
+ }
+
+ if( flags & DRAW_UNDERL )
+ PgSetUnderline( gui.norm_pixel, Pg_TRANSPARENT, 0 );
+
+ if( charset_translate != NULL
+#ifdef FEAT_MBYTE
+ && enc_utf8 == 0
+#endif
+ )
+ {
+ int src_taken, dst_made;
+
+ /* Use a static buffer to avoid large amounts of de/allocations */
+ if( utf8_len < len )
+ {
+ utf8_buffer = realloc( utf8_buffer, len * MB_LEN_MAX );
+ utf8_len = len;
+ }
+
+ PxTranslateToUTF(
+ charset_translate,
+ s,
+ len,
+ &src_taken,
+ utf8_buffer,
+ utf8_len,
+ &dst_made );
+ s = utf8_buffer;
+ len = dst_made;
+ }
+
+ PgDrawText( s, len, &pos, 0 );
+
+ if( flags & DRAW_BOLD )
+ {
+ /* FIXME: try and only calculate these values once... */
+ rect.ul.x = FILL_X( col ) + 1;
+ rect.ul.y = FILL_Y( row );
+ rect.lr.x = FILL_X( col + len ) - 1;
+ rect.lr.y = FILL_Y( row + 1) - 1;
+ /* PgSetUserClip( NULL ) causes the scrollbar to not redraw... */
+#if 0
+ pos.x++;
+
+ PgSetUserClip( &rect );
+ PgDrawText( s, len, &pos, 0 );
+ PgSetUserClip( NULL );
+#else
+ rect.lr.y -= ( p_linespace + 1 ) / 2;
+ /* XXX: DrawTextArea doesn't work with phditto */
+ PgDrawTextArea( s, len, &rect, Pg_TEXT_BOTTOM );
+#endif
+ }
+
+ if( flags & DRAW_UNDERL )
+ PgSetUnderline( Pg_TRANSPARENT, Pg_TRANSPARENT, 0 );
+
+ DRAW_END;
+}
+
+/****************************************************************************/
+/* Cursor */
+
+ void
+gui_mch_draw_hollow_cursor(guicolor_T color)
+{
+ PhRect_t r;
+
+ /* FIXME: Double width characters */
+
+ r.ul.x = FILL_X( gui.col );
+ r.ul.y = FILL_Y( gui.row );
+ r.lr.x = r.ul.x + gui.char_width - 1;
+ r.lr.y = r.ul.y + gui.char_height - 1;
+
+ DRAW_START;
+ PgSetStrokeColor( color );
+ PgDrawRect( &r, Pg_DRAW_STROKE );
+ DRAW_END;
+}
+
+ void
+gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
+{
+ PhRect_t r;
+
+ r.ul.x = FILL_X( gui.col );
+ r.ul.y = FILL_Y( gui.row ) + gui.char_height - h;
+ r.lr.x = r.ul.x + w - 1;
+ r.lr.y = r.ul.y + h - 1;
+
+ DRAW_START;
+ gui_mch_set_bg_color( color );
+ PgDrawRect( &r, Pg_DRAW_FILL );
+ DRAW_END;
+}
+
+ void
+gui_mch_set_blinking(long wait, long on, long off)
+{
+ blink_waittime = wait;
+ blink_ontime = on;
+ blink_offtime = off;
+}
+
+ void
+gui_mch_start_blink(void)
+{
+ /* Only turn on the timer on if none of the times are zero */
+ if( blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
+ {
+ PtSetResource( gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL,
+ blink_waittime, 0 );
+ blink_state = BLINK_ON;
+ gui_update_cursor(TRUE, FALSE);
+ }
+}
+
+ void
+gui_mch_stop_blink(void)
+{
+ PtSetResource( gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL, 0, 0 );
+
+ if( blink_state == BLINK_OFF )
+ gui_update_cursor(TRUE, FALSE);
+
+ blink_state = BLINK_NONE;
+}
+
+/****************************************************************************/
+/* miscellaneous functions */
+
+ void
+gui_mch_beep(void)
+{
+ PtBeep();
+}
+
+ void
+gui_mch_flash(int msec)
+{
+ PgSetFillXORColor( Pg_BLACK, Pg_WHITE );
+ PgSetDrawMode( Pg_DRAWMODE_XOR );
+ gui_mch_clear_all();
+ gui_mch_flush();
+
+ ui_delay( (long) msec, TRUE );
+
+ gui_mch_clear_all();
+ PgSetDrawMode( Pg_DRAWMODE_OPAQUE );
+ gui_mch_flush();
+}
+
+ void
+gui_mch_flush(void)
+{
+ PgFlush();
+}
+
+ void
+gui_mch_set_text_area_pos(int x, int y, int w, int h)
+{
+ PhArea_t area = {{x, y}, {w, h}};
+
+ PtSetResource( gui.vimTextArea, Pt_ARG_AREA, &area, 0 );
+}
+
+ int
+gui_mch_haskey(char_u *name)
+{
+ int i;
+
+ for (i = 0; special_keys[i].key_sym != 0; i++)
+ if (name[0] == special_keys[i].vim_code0 &&
+ name[1] == special_keys[i].vim_code1)
+ return( OK );
+ return( FAIL );
+}
+
+/****************************************************************************/
+/* Menu */
+
+#ifdef FEAT_TOOLBAR
+#include "toolbar.phi"
+
+static PhImage_t *gui_ph_toolbar_images[] = {
+ &tb_new_phi,
+ &tb_open_phi,
+ &tb_save_phi,
+ &tb_undo_phi,
+ &tb_redo_phi,
+ &tb_cut_phi,
+ &tb_copy_phi,
+ &tb_paste_phi,
+ &tb_print_phi,
+ &tb_help_phi,
+ &tb_find_phi,
+ &tb_save_all_phi,
+ &tb_save_session_phi,
+ &tb_new_session_phi,
+ &tb_load_session_phi,
+ &tb_macro_phi,
+ &tb_replace_phi,
+ &tb_close_phi,
+ &tb_maximize_phi,
+ &tb_minimize_phi,
+ &tb_split_phi,
+ &tb_shell_phi,
+ &tb_find_prev_phi,
+ &tb_find_next_phi,
+ &tb_find_help_phi,
+ &tb_make_phi,
+ &tb_jump_phi,
+ &tb_ctags_phi,
+ &tb_vsplit_phi,
+ &tb_maxwidth_phi,
+ &tb_minwidth_phi
+};
+
+static PhImage_t *
+gui_ph_toolbar_load_icon( char_u *iconfile )
+{
+ static PhImage_t external_icon;
+ PhImage_t *temp_phi = NULL;
+
+ temp_phi = PxLoadImage( iconfile, NULL );
+ if( temp_phi != NULL )
+ {
+ /* The label widget will free the image/palette/etc. for us when
+ * it's destroyed */
+ temp_phi->flags |= Ph_RELEASE_IMAGE_ALL;
+ memcpy( &external_icon, temp_phi, sizeof( external_icon ) );
+ free( temp_phi );
+
+ temp_phi = &external_icon;
+ }
+ return( temp_phi );
+}
+
+/*
+ * This returns either a builtin icon image, an external image or NULL
+ * if it can't find either. The caller can't and doesn't need to try and
+ * free() the returned image, and it can't store the image pointer.
+ * (When setting the Pt_ARG_LABEL_IMAGE resource, the contents of the
+ * PhImage_t are copied, and the original PhImage_t aren't needed anymore).
+ */
+static PhImage_t *
+gui_ph_toolbar_find_icon( vimmenu_T *menu )
+{
+ char_u full_pathname[ MAXPATHL + 1 ];
+ PhImage_t *icon = NULL;
+
+ if( menu->icon_builtin == FALSE )
+ {
+ if( menu->iconfile != NULL )
+ /* TODO: use gui_find_iconfile() */
+ icon = gui_ph_toolbar_load_icon( menu->iconfile );
+
+ /* TODO: Restrict loading to just .png? Search for any format? */
+ if( ( icon == NULL ) &&
+ ( ( gui_find_bitmap( menu->name, full_pathname, "gif" ) == OK ) ||
+ ( gui_find_bitmap( menu->name, full_pathname, "png" ) == OK ) ) )
+ icon = gui_ph_toolbar_load_icon( full_pathname );
+
+ if( icon != NULL )
+ return( icon );
+ }
+
+ if( menu->iconidx >= 0 &&
+ ( menu->iconidx < ARRAY_LENGTH( gui_ph_toolbar_images ) ) )
+ {
+ return( gui_ph_toolbar_images[ menu->iconidx ] );
+ }
+
+ return( NULL );
+}
+#endif
+
+#if defined( FEAT_MENU ) || defined( PROTO )
+ void
+gui_mch_enable_menu(int flag)
+{
+ if( flag != 0 )
+ PtRealizeWidget( gui.vimMenuBar );
+ else
+ PtUnrealizeWidget( gui.vimMenuBar );
+}
+
+ void
+gui_mch_set_menu_pos(int x, int y, int w, int h)
+{
+ /* Nothing */
+}
+
+/* Change the position of a menu button in the parent */
+ static void
+gui_ph_position_menu( PtWidget_t *widget, int priority )
+{
+ PtWidget_t *traverse;
+ vimmenu_T *menu;
+
+ traverse = PtWidgetChildBack( PtWidgetParent( widget ) );
+
+ /* Iterate through the list of widgets in traverse, until
+ * we find the position we want to insert our widget into */
+ /* TODO: traverse from front to back, possible speedup? */
+ while( traverse != NULL )
+ {
+ PtGetResource( traverse, Pt_ARG_POINTER, &menu, 0 );
+
+ if( menu != NULL &&
+ priority < menu->priority &&
+ widget != traverse )
+ {
+ /* Insert the widget before the current traverse widget */
+ PtWidgetInsert( widget, traverse, 1 );
+ return;
+ }
+
+ traverse = PtWidgetBrotherInFront( traverse );
+ }
+}
+
+/* the index is ignored because it's not useful for our purposes */
+ void
+gui_mch_add_menu(vimmenu_T *menu, int index)
+{
+ vimmenu_T *parent = menu->parent;
+ char_u *accel_key;
+ char_u mnemonic_str[MB_LEN_MAX];
+ int n;
+ PtArg_t args[5];
+
+ menu->submenu_id = menu->id = NULL;
+
+ if( menu_is_menubar( menu->name ) )
+ {
+
+ accel_key = vim_strchr( menu->name, '&' );
+ if( accel_key != NULL )
+ {
+ mnemonic_str[0] = accel_key[1];
+ mnemonic_str[1] = NUL;
+ }
+
+ /* Create the menu button */
+ n = 0;
+ PtSetArg( &args[ n++ ], Pt_ARG_TEXT_STRING, menu->dname, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_ACCEL_TEXT, menu->actext, 0 );
+ if( accel_key != NULL )
+ PtSetArg( &args[ n++ ], Pt_ARG_ACCEL_KEY, mnemonic_str, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_POINTER, menu, 0 );
+
+ if( parent != NULL )
+ PtSetArg( &args[ n++ ], Pt_ARG_BUTTON_TYPE, Pt_MENU_RIGHT, 0 );
+
+ menu->id = PtCreateWidget( PtMenuButton,
+ (parent == NULL) ? gui.vimMenuBar : parent->submenu_id,
+ n, args );
+
+ PtAddCallback( menu->id, Pt_CB_ARM, gui_ph_handle_pulldown_menu, menu );
+
+ /* Create the actual menu */
+ n = 0;
+ if( parent != NULL )
+ PtSetArg( &args[ n++ ], Pt_ARG_MENU_FLAGS, Pt_TRUE, Pt_MENU_CHILD );
+
+ menu->submenu_id = PtCreateWidget( PtMenu, menu->id, n, args );
+
+ if( parent == NULL )
+ {
+ PtAddCallback( menu->submenu_id, Pt_CB_UNREALIZED,
+ gui_ph_handle_menu_unrealized, menu );
+
+ if( menu->mnemonic != 0 )
+ {
+ PtAddHotkeyHandler( gui.vimWindow, tolower( menu->mnemonic ),
+ Pk_KM_Alt, 0, menu, gui_ph_handle_pulldown_menu );
+ }
+ }
+
+ gui_ph_position_menu( menu->id, menu->priority );
+
+ /* Redraw menubar here instead of gui_mch_draw_menubar */
+ if( gui.menu_is_active )
+ PtRealizeWidget( menu->id );
+ }
+ else if( menu_is_popup( menu->name ) )
+ {
+ menu->submenu_id = PtCreateWidget( PtMenu, gui.vimWindow, 0, NULL );
+ PtAddCallback( menu->submenu_id, Pt_CB_UNREALIZED,
+ gui_ph_handle_menu_unrealized, menu );
+ }
+}
+
+ void
+gui_mch_add_menu_item(vimmenu_T *menu, int index)
+{
+ vimmenu_T *parent = menu->parent;
+ char_u *accel_key;
+ char_u mnemonic_str[MB_LEN_MAX];
+ int n;
+ PtArg_t args[13];
+
+ n = 0;
+ PtSetArg( &args[ n++ ], Pt_ARG_POINTER, menu, 0 );
+
+#ifdef FEAT_TOOLBAR
+ if( menu_is_toolbar( parent->name ) )
+ {
+ if( menu_is_separator( menu->name ) )
+ {
+ PtSetArg( &args[ n++ ], Pt_ARG_SEP_FLAGS,
+ Pt_SEP_VERTICAL, Pt_SEP_ORIENTATION );
+ PtSetArg( &args[ n++ ], Pt_ARG_SEP_TYPE, Pt_ETCHED_IN, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_ANCHOR_FLAGS,
+ Pt_TRUE, Pt_ANCHOR_TOP_BOTTOM );
+ PtSetArg( &args[ n++ ], Pt_ARG_WIDTH, 2, 0 );
+ menu->id = PtCreateWidget( PtSeparator, gui.vimToolBar, n, args );
+ }
+ else
+ {
+ if( strstr( (const char *) p_toolbar, "text" ) != NULL )
+ {
+ PtSetArg( &args[ n++ ], Pt_ARG_BALLOON_POSITION,
+ Pt_BALLOON_BOTTOM, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_TEXT_STRING, menu->dname, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_TEXT_FONT, "TextFont08", 0 );
+ }
+ if( ( strstr( (const char *) p_toolbar, "icons" ) != NULL ) &&
+ ( gui_ph_toolbar_images != NULL ) )
+ {
+ PtSetArg( &args[ n++ ], Pt_ARG_LABEL_IMAGE,
+ gui_ph_toolbar_find_icon( menu ), 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_LABEL_TYPE, Pt_TEXT_IMAGE, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_TEXT_IMAGE_SPACING, 0, 0 );
+ }
+ if( strstr( (const char *) p_toolbar, "tooltips" ) != NULL )
+ {
+ PtSetArg( &args[ n++ ], Pt_ARG_LABEL_BALLOON,
+ gui_ph_show_tooltip, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_LABEL_FLAGS,
+ Pt_TRUE, Pt_SHOW_BALLOON );
+ }
+ PtSetArg( &args[ n++ ], Pt_ARG_MARGIN_HEIGHT, 1, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_MARGIN_WIDTH, 1, 0 );
+ PtSetArg( &args[ n++ ], Pt_ARG_FLAGS, Pt_FALSE,
+ Pt_HIGHLIGHTED | Pt_GETS_FOCUS );
+ PtSetArg( &args[ n++ ], Pt_ARG_FILL_COLOR, Pg_TRANSPARENT, 0 );
+ menu->id = PtCreateWidget( PtButton, gui.vimToolBar, n, args );
+
+ PtAddCallback( menu->id, Pt_CB_ACTIVATE, gui_ph_handle_menu, menu );
+ }
+ /* Update toolbar if it's open */
+ if( PtWidgetIsRealized( gui.vimToolBar ) )
+ PtRealizeWidget( menu->id );
+ }
+ else
+#endif
+ if( menu_is_separator( menu->name ) )
+ {
+ menu->id = PtCreateWidget( PtSeparator, parent->submenu_id, n, args );
+ }
+ else
+ {
+ accel_key = vim_strchr( menu->name, '&' );
+ if( accel_key != NULL )
+ {
+ mnemonic_str[0] = accel_key[1];
+ mnemonic_str[1] = NUL;
+ }
+
+ PtSetArg( &args[ n++ ], Pt_ARG_TEXT_STRING, menu->dname, 0 );
+ if( accel_key != NULL )
+ PtSetArg( &args[ n++ ], Pt_ARG_ACCEL_KEY, mnemonic_str,
+ 0 );
+
+ PtSetArg( &args[ n++ ], Pt_ARG_ACCEL_TEXT, menu->actext, 0 );
+
+ menu->id = PtCreateWidget( PtMenuButton, parent->submenu_id, n, args );
+
+ PtAddCallback( menu->id, Pt_CB_ACTIVATE, gui_ph_handle_menu, menu );
+
+#ifdef USE_PANEL_GROUP
+ if( gui_ph_is_buffer_item( menu, parent ) == TRUE )
+ {
+ PtAddCallback( menu->id, Pt_CB_DESTROYED,
+ gui_ph_handle_buffer_remove, menu );
+ gui_ph_pg_add_buffer( menu->dname );
+ }
+#endif
+ }
+
+ gui_ph_position_menu( menu->id, menu->priority );
+}
+
+ void
+gui_mch_destroy_menu(vimmenu_T *menu)
+{
+ if( menu->submenu_id != NULL )
+ PtDestroyWidget( menu->submenu_id );
+ if( menu->id != NULL )
+ PtDestroyWidget( menu->id );
+
+ menu->submenu_id = NULL;
+ menu->id = NULL;
+}
+
+ void
+gui_mch_menu_grey(vimmenu_T *menu, int grey)
+{
+ long flags, mask, fields;
+
+ if( menu->id == NULL )
+ return;
+
+ flags = PtWidgetFlags( menu->id );
+ if( PtWidgetIsClass( menu->id, PtMenuButton ) &&
+ PtWidgetIsClass( PtWidgetParent( menu->id ), PtMenu ) )
+ {
+ fields = Pt_FALSE;
+ mask = Pt_SELECTABLE | Pt_HIGHLIGHTED;
+ }
+ else
+ {
+ fields = Pt_TRUE;
+ mask = Pt_BLOCKED | Pt_GHOST;
+ }
+
+ if( ! grey )
+ fields = ~fields;
+
+ PtSetResource( menu->id, Pt_ARG_FLAGS, fields,
+ mask );
+}
+
+ void
+gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
+{
+ /* TODO: [un]realize the widget? */
+}
+
+ void
+gui_mch_draw_menubar(void)
+{
+ /* The only time a redraw is needed is when a menu button
+ * is added to the menubar, and that is detected and the bar
+ * redrawn in gui_mch_add_menu_item
+ */
+}
+
+ void
+gui_mch_show_popupmenu(vimmenu_T *menu)
+{
+ PtSetResource( menu->submenu_id, Pt_ARG_POS, &abs_mouse, 0 );
+ PtRealizeWidget( menu->submenu_id );
+}
+
+ void
+gui_mch_toggle_tearoffs(int enable)
+{
+ /* No tearoffs yet */
+}
+
+#endif
+
+#if defined( FEAT_TOOLBAR ) || defined( PROTO )
+ void
+gui_mch_show_toolbar(int showit)
+{
+ if( showit )
+ PtRealizeWidget( gui.vimToolBar );
+ else
+ PtUnrealizeWidget( gui.vimToolBar );
+}
+#endif
+
+/****************************************************************************/
+/* Fonts */
+
+ static GuiFont
+gui_ph_get_font(
+ char_u *font_name,
+ int_u font_flags,
+ int_u font_size,
+ /* Check whether the resulting font has the font flags and size that
+ * was asked for */
+ int_u enforce
+ )
+{
+ char_u *font_tag;
+ FontQueryInfo info;
+ int_u style;
+
+ font_tag = alloc( MAX_FONT_TAG );
+ if( font_tag != NULL )
+ {
+ if( PfGenerateFontName( font_name, font_flags, font_size,
+ font_tag ) != NULL )
+ {
+ /* Enforce some limits on the font used */
+ style = PHFONT_INFO_FIXED;
+
+ if( enforce & PF_STYLE_BOLD )
+ style |= PHFONT_INFO_BOLD;
+ if( enforce & PF_STYLE_ANTIALIAS )
+ style |= PHFONT_INFO_ALIAS;
+ if( enforce & PF_STYLE_ITALIC )
+ style |= PHFONT_INFO_ITALIC;
+
+ PfQueryFontInfo( font_tag, &info );
+
+ if( info.size == 0 )
+ font_size = 0;
+
+ /* Make sure font size matches, and that the font style
+ * at least has the bits we're checking for */
+ if( font_size == info.size &&
+ style == (info.style & style) )
+ return( (GuiFont) font_tag );
+ }
+ vim_free( font_tag );
+ }
+ return( NULL );
+}
+
+/*
+ * Split up the vim font name
+ *
+ * vim_font is in the form of
+ * <name>:s<height>:a:b:i
+ *
+ * a = antialias
+ * b = bold
+ * i = italic
+ *
+ */
+
+ static int
+gui_ph_parse_font_name(
+ char_u *vim_font,
+ char_u **font_name,
+ int_u *font_flags,
+ int_u *font_size )
+{
+ char_u *mark;
+ int_u name_len, size;
+
+ mark = vim_strchr( vim_font, ':' );
+ if( mark == NULL )
+ name_len = STRLEN( vim_font );
+ else
+ name_len = (int_u) ( mark - vim_font );
+
+ *font_name = vim_strnsave( vim_font, name_len );
+ if( *font_name != NULL )
+ {
+ if( mark != NULL )
+ {
+ while( *mark != NUL && *mark++ == ':')
+ {
+ switch( tolower( *mark++ ) )
+ {
+ case 'a': *font_flags |= PF_STYLE_ANTIALIAS; break;
+ case 'b': *font_flags |= PF_STYLE_BOLD; break;
+ case 'i': *font_flags |= PF_STYLE_ITALIC; break;
+
+ case 's':
+ size = getdigits( &mark );
+ /* Restrict the size to some vague limits */
+ if( size < 1 || size > 100 )
+ size = 8;
+
+ *font_size = size;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ return( TRUE );
+ }
+ return( FALSE );
+}
+
+ int
+gui_mch_init_font(char_u *vim_font_name, int fontset)
+{
+ char_u *font_tag;
+ char_u *font_name = NULL;
+ int_u font_flags = 0;
+ int_u font_size = 12;
+
+ FontQueryInfo info;
+ PhRect_t extent;
+
+ if( vim_font_name == NULL )
+ {
+ /* Default font */
+ vim_font_name = "PC Term";
+ }
+
+ if( STRCMP( vim_font_name, "*" ) == 0 )
+ {
+ font_tag = PtFontSelection( gui.vimWindow, NULL, NULL,
+ "pcterm12", -1, PHFONT_FIXED, NULL );
+
+ if( font_tag == NULL )
+ return( FAIL );
+
+ gui_mch_free_font( gui.norm_font );
+ gui.norm_font = font_tag;
+
+ PfQueryFontInfo( font_tag, &info );
+ font_name = vim_strsave( info.font );
+ }
+ else
+ {
+ if( gui_ph_parse_font_name( vim_font_name, &font_name, &font_flags,
+ &font_size ) == FALSE )
+ return( FAIL );
+
+ font_tag = gui_ph_get_font( font_name, font_flags, font_size, 0 );
+ if( font_tag == NULL )
+ {
+ vim_free( font_name );
+ return( FAIL );
+ }
+ gui_mch_free_font( gui.norm_font );
+ gui.norm_font = font_tag;
+ }
+
+ gui_mch_free_font( gui.bold_font );
+ gui.bold_font = gui_ph_get_font( font_name, font_flags | PF_STYLE_BOLD,
+ font_size, PF_STYLE_BOLD );
+
+ gui_mch_free_font( gui.ital_font );
+ gui.ital_font = gui_ph_get_font( font_name, font_flags | PF_STYLE_ITALIC,
+ font_size, PF_STYLE_ITALIC );
+
+ /* This extent was brought to you by the letter 'g' */
+ PfExtentText( &extent, NULL, font_tag, "g", 1 );
+
+ gui.char_width = extent.lr.x - extent.ul.x + 1;
+ gui.char_height = (- extent.ul.y) + extent.lr.y + 1;
+ gui.char_ascent = - extent.ul.y;
+
+ vim_free( font_name );
+ return( OK );
+}
+
+ int
+gui_mch_adjust_charsize(void)
+{
+ FontQueryInfo info;
+
+ PfQueryFontInfo( gui.norm_font, &info );
+
+ gui.char_height = - info.ascender + info.descender + p_linespace;
+ gui.char_ascent = - info.ascender + p_linespace / 2;
+
+ return( OK );
+}
+
+ GuiFont
+gui_mch_get_font(char_u *vim_font_name, int report_error)
+{
+ char_u *font_name;
+ char_u *font_tag;
+ int_u font_size = 12;
+ int_u font_flags = 0;
+
+ if( gui_ph_parse_font_name( vim_font_name, &font_name, &font_flags,
+ &font_size ) != FALSE )
+ {
+ font_tag = gui_ph_get_font( font_name, font_flags, font_size, -1 );
+ vim_free( font_name );
+
+ if( font_tag != NULL )
+ return( (GuiFont) font_tag );
+ }
+
+ if( report_error )
+ EMSG2(e_font, vim_font_name );
+
+ return( FAIL );
+}
+
+ void
+gui_mch_set_font(GuiFont font)
+{
+ PgSetFont( font );
+}
+
+ void
+gui_mch_free_font(GuiFont font)
+{
+ vim_free( font );
+}
+
diff --git a/src/gui_riscos.c b/src/gui_riscos.c
new file mode 100644
index 000000000..b823a79f8
--- /dev/null
+++ b/src/gui_riscos.c
@@ -0,0 +1,3547 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+#include <string.h>
+
+/*
+ * gui_riscos.c
+ *
+ * Thomas Leonard <tal197@ecs.soton.ac.uk>
+ * Updated by Andy Wingate <andy@sparse.net>
+ */
+
+extern int time_of_last_poll;
+
+int task_handle = 0; /* Zero means we are not yet a Wimp task */
+int child_handle = 0; /* Task handle of our child process (zero if none). */
+int *wimp_menu = (int *) -1; /* Pointer to a Wimp menu structure (or -1) */
+int save_window = -1; /* Save As window handle */
+
+int *redraw_block = NULL; /* NULL means not in a redraw loop. */
+int ro_return_early = FALSE; /* Break out of gui_mch_wait_for_chars() */
+
+int leaf_ref = 0; /* Wimp message number - send via Wimp$Scrap */
+char_u *leaf_name = NULL; /* Leaf name from DataSave */
+
+int default_columns = 120; /* These values are used if the --rows and --columns */
+int default_rows = 32; /* options aren't used on startup. */
+
+#define DRAG_FALSE 0
+#define DRAG_SELECTION 1
+#define DRAG_RESIZE_WINDOW 2
+int ro_dragging = DRAG_FALSE;
+int drag_button;
+int drag_modifiers;
+int drag_x_offset;
+int drag_y_offset;
+
+int nested_wimp = FALSE; /* Bool - can we use the new wimp? */
+
+int changed_mode = FALSE;
+int x_eigen_factor;
+int y_eigen_factor;
+
+/* If ro_current_font is non-zero then use the outline font with that handle,
+ * otherwise, if zap_redraw is TRUE then use ZapRedraw, otherwise use the
+ * system font.
+ *
+ * If zap_redraw is TRUE then zap_file[] contains valid Zap font file
+ * pointers (or NULLs).
+ */
+int ro_current_font = 0; /* 0 is system font, or ZapRedraw */
+int font_x_offset = 0; /* Where to position each char in its box */
+int font_y_offset = 0;
+
+int zap_redraw = FALSE;
+int double_height = FALSE; /* Plot each line twice? */
+
+#define grgb(r,g,b) ((b<<16) + (g<<8) + (r))
+#define UNUSED_COLOUR (gui.back_pixel)
+
+#define RO_LOAD_CLIPBOARD -2 /* Internal handle for DataSave message. */
+
+/* Changes by John Kortink, 22-23 July 1998
+ *
+ * Stuff to make redraw a lot faster. Almost all of it is right here below,
+ * elsewhere changes are marked with 'JK230798'. Apart from a small change in
+ * 'gui.c' all changes are limited to this file, 'gui_riscos.c'. The change in
+ * 'gui.c' is to make Vim stop being 'smart' not redrawing characters that are
+ * 'already there' (i.e. from the previous line, by coincidence). This caused a
+ * lot more calls to the redraw code, which we want to avoid because a few nice
+ * big strings at a time is a lot faster than a truckload of small ones. ('Dear
+ * Bram ...').
+ */
+
+/* The ZapRedraw structure */
+
+static struct
+{
+ int r_flags;
+ int r_minx;
+ int r_miny;
+ int r_maxx;
+ int r_maxy;
+ int r_screen;
+ int r_bpl;
+ int r_bpp;
+ int r_charw;
+ int r_charh;
+ char *r_caddr;
+ int r_cbpl;
+ int r_cbpc;
+ int r_linesp;
+ int r_data;
+ int r_scrollx;
+ int r_scrolly;
+ int *r_palette;
+ int r_for;
+ int r_bac;
+ char *r_workarea;
+ int r_magx;
+ int r_magy;
+ int r_xsize;
+ int r_ysize;
+ int r_mode;
+}
+zap_redraw_block;
+
+/* Other globals */
+
+static int zap_redraw_initialised = FALSE;
+static int zap_redraw_update_colours;
+static int zap_redraw_colours[2];
+static int zap_redraw_palette[16];
+
+/* Holds the current Zap font file(s).
+ * The font is recreated from this block on a mode change.
+ * When using zap, element ZAP_NORMAL is always valid, but
+ * the others can be NULL.
+ */
+
+#define ZAP_NORMAL 0
+#define ZAP_BOLD 1
+#define ZAP_ITALIC 2
+#define ZAP_BITALIC 3
+#define ZAP_STYLES 4
+
+/* Zap font file format data */
+static char *zap_file[ZAP_STYLES] = {NULL, NULL, NULL, NULL};
+
+/* r_caddr format for current mode */
+static char *zap_caddr[ZAP_STYLES] = {NULL, NULL, NULL, NULL};
+
+static void ro_remove_menu(int *menu);
+
+/*
+ * Initialise all the ZapRedraw stuff.
+ * Call this when changing font and after each mode change.
+ * zap_redraw_bitmap must contain a valid Zap font file (possibly
+ * created from the system font).
+ *
+ * Return FAIL to revert to system font (if we can't use ZapRedraw).
+ */
+ int
+ro_zap_redraw_initialise()
+{
+ int bytes_per_bitmap_char;
+ int first, last;
+ int i;
+
+ /* Can't have initialisers for struct members :-(, ok, this way then ... */
+ if (!zap_redraw_initialised)
+ {
+ zap_redraw_block.r_workarea = NULL;
+ zap_redraw_initialised = TRUE;
+ }
+
+ /* We redraw in DSA mode */
+ zap_redraw_block.r_flags = 0x0;
+
+ /* Let ZapRedraw get the screen address for us */
+ zap_redraw_block.r_screen = 0;
+
+ /* Read the font width and height from the font file header.
+ * Assume that all styles are the same size.
+ * ZAP_NORMAL is always present.
+ */
+ zap_redraw_block.r_charw = ((int *) zap_file[ZAP_NORMAL])[2];
+ zap_redraw_block.r_charh = ((int *) zap_file[ZAP_NORMAL])[3];
+
+ /* We have no linespacing */
+ zap_redraw_block.r_linesp = 0;
+
+ /* Fix foreground = colour 1 */
+ zap_redraw_block.r_for = 1;
+
+ /* Fix background = colour 0 */
+ zap_redraw_block.r_bac = 0;
+
+ /* Colour mask buffer */
+ zap_redraw_block.r_palette = zap_redraw_palette;
+
+ /* Allocate local workspace (for the few calls following here) */
+ if (zap_redraw_block.r_workarea != NULL)
+ free(zap_redraw_block.r_workarea);
+ zap_redraw_block.r_workarea = (char*) malloc(128);
+ if (!zap_redraw_block.r_workarea)
+ return FAIL; /* Out of memory */
+
+ /* Fill in VDU variables */
+ if (xswi(ZapRedraw_ReadVduVars, 0, &zap_redraw_block) & v_flag)
+ return FAIL; /* Can't find ZapRedraw module - use VDU instead */
+
+ /* Determine cbpl and cbpc */
+ swi(ZapRedraw_CachedCharSize, zap_redraw_block.r_bpp, 0,
+ zap_redraw_block.r_charw, zap_redraw_block.r_charh);
+ zap_redraw_block.r_cbpl = r2;
+ zap_redraw_block.r_cbpc = r3;
+
+ /* Allocate general workspace (for the calls outside) */
+ if (zap_redraw_block.r_workarea != NULL)
+ free(zap_redraw_block.r_workarea);
+ zap_redraw_block.r_workarea = (char*) malloc(128 + zap_redraw_block.r_cbpl);
+ if (!zap_redraw_block.r_workarea)
+ return FAIL; /* Out of memory */
+
+ /* Now convert the 1 bpp character data ready for the current mode */
+
+ bytes_per_bitmap_char = (zap_redraw_block.r_charw * zap_redraw_block.r_charh + 7) / 8;
+
+ /* Convert the fonts from 1bpp to a format suitable for the
+ * current mode.
+ */
+ for (i = 0; i < ZAP_STYLES; i++)
+ {
+ first = ((int *) zap_file[i])[4];
+ last = ((int *) zap_file[i])[5];
+
+ if (last > 255)
+ last = 255; /* Don't convert cursors (overwrites memory!) */
+
+ /* Allocate the font cache */
+ vim_free(zap_caddr[i]);
+ if (zap_file[i])
+ zap_caddr[i] = (char*) malloc(zap_redraw_block.r_cbpc * 256);
+ else
+ zap_caddr[i] = NULL; /* No file for this style */
+
+ if (zap_caddr[i])
+ {
+ zap_redraw_block.r_caddr = zap_caddr[i];
+
+ swi(ZapRedraw_ConvertBitmap, 0, &zap_redraw_block,
+ first, last, /* Range of characters to convert */
+ zap_file[i] + 0x20 /* Addr of first char provided by font */
+ - first * bytes_per_bitmap_char);
+ }
+ }
+
+ if (!zap_caddr[ZAP_NORMAL])
+ {
+ zap_redraw = FALSE; /* Out of memory */
+ return FAIL;
+ }
+
+ /* Next time we need them, we have to update the colour masks */
+ zap_redraw_update_colours = TRUE;
+
+ return OK;
+}
+
+/*
+ * Redraw a string at OS coordinates <x,y> (top-left, x inclusive, y exclusive).
+ * Graphics clip window is window[0..3] as in R1+28..40 of Wimp_RedrawWindow.
+ * Returns (possibly modified) flags.
+ */
+ int
+ro_zap_redraw_draw_string(x, y, string, length, flags, clip)
+ int x;
+ int y;
+ char *string;
+ int length;
+ int flags; /* DRAW_TRANSP, DRAW_BOLD, DRAW_UNDERL, DRAW_ITALIC */
+ int *clip;
+{
+ char redraw_data[1024];
+ int clip_minx;
+ int clip_miny;
+ int clip_maxx;
+ int clip_maxy;
+ int os_xshift = zap_redraw_block.r_magx;
+ int os_yshift = zap_redraw_block.r_magy;
+
+ if (flags & DRAW_TRANSP)
+ return flags; /* We don't do transparent plotting yet. */
+
+ if (flags & DRAW_BOLD)
+ {
+ if (flags & DRAW_ITALIC && zap_caddr[ZAP_BITALIC])
+ zap_redraw_block.r_caddr = zap_caddr[ZAP_BITALIC];
+ else
+ zap_redraw_block.r_caddr = zap_caddr[ZAP_BOLD];
+ }
+ else
+ {
+ if (flags & DRAW_ITALIC)
+ zap_redraw_block.r_caddr = zap_caddr[ZAP_ITALIC];
+ else
+ zap_redraw_block.r_caddr = zap_caddr[ZAP_NORMAL];
+ }
+ if (!zap_redraw_block.r_caddr)
+ {
+ zap_redraw_block.r_caddr = zap_caddr[ZAP_NORMAL];
+ flags |= DRAW_UNDERL; /* Style missing - we can always underline */
+ }
+
+ /* Set the vertical scaling flag */
+ if (double_height)
+ zap_redraw_block.r_flags = 1 << 1;
+ else
+ zap_redraw_block.r_flags = 0;
+
+ /* Update the colour masks (if needed) */
+ if (zap_redraw_update_colours)
+ {
+ swi(ZapRedraw_CreatePalette, 2,
+ &zap_redraw_block,
+ zap_redraw_colours,
+ zap_redraw_block.r_palette, 2);
+ zap_redraw_update_colours = FALSE;
+ }
+
+ /* Target rectangle in ZapRedraw rectangle coordinates (pixels, Y-min/max reversed !!!) */
+ zap_redraw_block.r_minx = x >> os_xshift; /* inclusive */
+ zap_redraw_block.r_miny = zap_redraw_block.r_ysize - (y >> os_yshift); /* inclusive */
+ zap_redraw_block.r_maxx = (x + length * gui.char_width) >> os_xshift; /* exclusive */
+ zap_redraw_block.r_maxy = zap_redraw_block.r_ysize - ((y - gui.char_height) >> os_yshift);
+ /* exclusive */
+
+ /* Clip rectangle in ZapRedraw rectangle coordinates (pixels, Y-min/max reversed !!!) */
+ clip_minx = clip[0] >> os_xshift; /* inclusive */
+ clip_miny = zap_redraw_block.r_ysize - (clip[3] >> os_yshift); /* inclusive */
+ clip_maxx = clip[2] >> os_xshift; /* exclusive */
+ clip_maxy = zap_redraw_block.r_ysize - (clip[1] >> os_yshift); /* exclusive */
+
+ /* Clip target rectangle against the current graphics window */
+ if (zap_redraw_block.r_minx < clip_minx)
+ {
+ zap_redraw_block.r_scrollx = clip_minx - zap_redraw_block.r_minx;
+ zap_redraw_block.r_minx = clip_minx;
+ }
+ else
+ zap_redraw_block.r_scrollx = 0;
+ if (zap_redraw_block.r_miny < clip_miny)
+ {
+ zap_redraw_block.r_scrolly = clip_miny - zap_redraw_block.r_miny;
+ zap_redraw_block.r_miny = clip_miny;
+ }
+ else
+ zap_redraw_block.r_scrolly = 0;
+ if (zap_redraw_block.r_maxx > clip_maxx)
+ zap_redraw_block.r_maxx = clip_maxx;
+ if (zap_redraw_block.r_maxy > clip_maxy)
+ zap_redraw_block.r_maxy = clip_maxy;
+
+ /* Fill in the character data structure */
+ if (length > (sizeof(redraw_data) - 2 * 4 - 2))
+ length = sizeof(redraw_data) - 2 * 4 - 2;
+ ((int*) redraw_data)[0] = 2 * 4;
+ ((int*) redraw_data)[1] = 0;
+ strncpy(redraw_data + 2 * 4, string, length);
+ redraw_data[2 * 4 + length + 0] = '\0';
+ redraw_data[2 * 4 + length + 1] = '\x2';
+ zap_redraw_block.r_data = (int) redraw_data;
+
+ /* Perform the draw */
+ swi(ZapRedraw_RedrawArea, 0, &zap_redraw_block);
+
+ return flags;
+}
+
+/*
+ * Okay that was it from me, back to Thomas ...
+ */
+
+/*
+ * Parse the GUI related command-line arguments. Any arguments used are
+ * deleted from argv, and *argc is decremented accordingly. This is called
+ * when vim is started, whether or not the GUI has been started.
+ */
+ void
+gui_mch_prepare(int *argc, char **argv)
+{
+ int arg = 1;
+
+ while (arg < *argc - 1)
+ {
+ if (strcmp(argv[arg], "--rows") == 0 || strcmp(argv[arg], "--columns") == 0)
+ {
+ int value;
+
+ value = atoi(argv[arg + 1]);
+
+ if (argv[arg][2] == 'r')
+ default_rows = value;
+ else
+ default_columns = value;
+
+ /* Delete argument from argv[]. (hope this is read/write!) */
+
+ *argc -= 2;
+ if (*argc > arg)
+ mch_memmove(&argv[arg], &argv[arg + 2], (*argc - arg)
+ * sizeof(char *));
+ }
+ else
+ arg++;
+ }
+}
+
+/* Fatal error on initialisation - report it and die. */
+ void
+ro_die(error)
+ char_u *error; /* RISC OS error block */
+{
+ swi(Wimp_ReportError, error, 5, "GVim");
+ exit(EXIT_FAILURE);
+}
+
+/* Find the sizes of the window tools:
+ *
+ * Create a test window.
+ * Find inner and outer sizes.
+ * Find the difference.
+ * Delete window.
+ *
+ * While we're here, find the eigen values too.
+ */
+ void
+ro_measure_tools()
+{
+ int block[10];
+ int vdu[] = { 4, 5, -1};
+ int test_window[] =
+ {
+ -100, -100, /* Visible area : min X,Y */
+ -50, -50, /* max X,Y */
+ 0, 0, /* Scroll offsets */
+ -1, /* Window in front */
+ 0xd0800150, /* Window flags */
+ 0xff070207, /* Colours */
+ 0x000c0103, /* More colours */
+ 0, -0x4000, /* Workarea extent */
+ 0x4000, 0, /* max X,Y */
+ 0x00000000, /* No title */
+ 0 << 12, /* No workarea button type */
+ 1, /* Wimp sprite area */
+ 0x00010001, /* Minimum width, height */
+ 0, 0, 0, /* Title data (none) */
+ 0 /* No icons */
+ };
+ int inner_max_x, inner_min_y;
+
+ swi(Wimp_CreateWindow, 0, test_window);
+
+ block[0] = r0;
+ /* Open the window (and read state).
+ * GetWindowOutline needs it too if the wimp isn't nested.
+ */
+ swi(Wimp_OpenWindow, 0, block);
+ inner_max_x = block[3];
+ inner_min_y = block[2];
+
+ swi(Wimp_GetWindowOutline, 0, block);
+
+ gui.scrollbar_width = block[3] - inner_max_x;
+ gui.scrollbar_height = inner_min_y - block[2];
+
+ swi(Wimp_DeleteWindow, 0, block);
+
+ /* Read the size of one pixel. */
+ swi(OS_ReadVduVariables, vdu, vdu);
+ x_eigen_factor = vdu[0];
+ y_eigen_factor = vdu[1];
+}
+
+/* Load a template from the current templates file.
+ * Create the window and return its handle.
+ */
+ int
+ro_load_template(str_name, title, title_size)
+ char_u *str_name; /* Identifier of window in file (max 12 chars) */
+ char_u **title; /* If not NULL then return pointer to title here */
+ int *title_size; /* If not NULL then return the title length here */
+{
+ int *window;
+ char *data;
+ int name[4];
+
+ strcpy( (char *) name, str_name);
+
+ /* Find how big we must make the buffers */
+
+ if (xswi(Wimp_LoadTemplate, 0, 0, 0, 0, -1, name, 0) & v_flag)
+ ro_die( (char *) r0);
+
+ window = malloc(r1); /* Don't print text messages from alloc() */
+ data = malloc(r2);
+ if (window == NULL || data == NULL)
+ ro_die("\0\0\0\0Out of memory - Can't load templates");
+
+ /* Load the template into the buffers */
+
+ swi(Wimp_LoadTemplate, 0,
+ window, /* Temp block */
+ data, /* Icon data */
+ data + r2 + 1, /* End of icon data */
+ -1, /* No fonts */
+ name, 0); /* First match */
+ if (r6 == 0)
+ ro_die("\0\0\0\0Can't find window in Templates file");
+
+ /* Create the window */
+
+ if (xswi(Wimp_CreateWindow, 0, window) & v_flag)
+ ro_die( (char *) r0);
+
+ if (title)
+ *title = (char_u *) window[18];
+ if (title_size)
+ *title_size = window[20];
+
+ free(window); /* Free temp block */
+ return r0; /* Return the window handle */
+}
+
+/*
+ * Check if the GUI can be started. Called before gvimrc is sourced.
+ * Return OK or FAIL.
+ */
+ int
+gui_mch_init_check()
+{
+ return OK; /* TODO: GUI can always be started? */
+}
+
+/*
+ * Initialise the RISC OS GUI.
+ * Create all the windows.
+ * Returns OK for success, FAIL when the GUI can't be started.
+ */
+ int
+gui_mch_init()
+{
+ int messages[] = {
+ 1, 2, 3, 4, /* DataSave, DataSaveAck, DataLoad, DataLoadAck */
+ 8, /* PreQuit */
+ 0xf, /* ClaimEntity (for clipboard) */
+ 0x10, /* DataRequest (for clipboard) */
+ 0x400c1, /* Mode change */
+ 0x400c3, /* TaskCloseDown */
+ 0x400c9, /* MenusDeleted */
+ 0x808c1, /* TW_Output */
+ 0x808c2, /* TW_Ego */
+ 0x808c3, /* TW_Morio */
+ 0x808c4, /* TW_Morite */
+ 0}; /* End-of-list. */
+
+
+ /* There may have been some errors reported in the
+ * command window before we get here. Wait if so.
+ */
+ swi(Wimp_ReadSysInfo, 3);
+ if (r0 == 0)
+ swi(Wimp_CommandWindow, 0); /* Window opened - close with prompt */
+
+ if (xswi(Wimp_Initialise, 310, 0x4b534154, "GVim", messages) & v_flag)
+ return FAIL;
+ nested_wimp = r0 >= 397;
+ task_handle = r1;
+
+ /* Load the templates. */
+
+ if (xswi(Wimp_OpenTemplate, 0, "Vim:Templates") & v_flag)
+ ro_die( (char *) r0);
+
+ gui.window_handle = ro_load_template("editor",
+ &gui.window_title,
+ &gui.window_title_size);
+
+ save_window = ro_load_template("save", NULL, NULL);
+
+ swi(Wimp_CloseTemplate);
+
+ /* Set default foreground and background colours. */
+
+ gui.norm_pixel = gui.def_norm_pixel;
+ gui.back_pixel = gui.def_back_pixel;
+
+ /* Get the colours from the "Normal" and "Menu" group (set in syntax.c or
+ * in a vimrc file) */
+
+ set_normal_colors();
+
+ /*
+ * Check that none of the colors are the same as the background color
+ */
+
+ gui_check_colors();
+
+ /* Get the colours for the highlight groups (gui_check_colors() might have
+ * changed them) */
+
+ highlight_gui_started(); /* re-init colours and fonts */
+
+ /* Set geometry based on values read on initialisation. */
+
+ gui.num_cols = Columns = default_columns;
+ gui.num_rows = Rows = default_rows;
+
+ /* Get some information about our environment. */
+
+ ro_measure_tools();
+
+ return OK;
+}
+
+/*
+ * Called when the foreground or background colour has been changed.
+ */
+ void
+gui_mch_new_colors()
+{
+}
+
+/*
+ * Open the GUI window which was created by a call to gui_mch_init().
+ */
+ int
+gui_mch_open(void)
+{
+ int block[10];
+
+ block[0] = gui.window_handle;
+ swi(Wimp_GetWindowState, 0, block);
+ block[7] = -1; /* Open at the top of the stack */
+ swi(Wimp_OpenWindow, 0, block);
+
+ /* Give the new window the input focus */
+ swi(Wimp_SetCaretPosition, gui.window_handle, -1, 0, 0, -1, -1);
+
+ if (gui_win_x != -1 && gui_win_y != -1)
+ gui_mch_set_winpos(gui_win_x, gui_win_y);
+
+ return OK;
+}
+
+ void
+gui_mch_exit(int rc)
+{
+ int block[64];
+
+ /* Close window. Stops us from getting troublesome events
+ * if we take a while to die.
+ */
+ block[0] = gui.window_handle;
+ swi(Wimp_CloseWindow, 0, block);
+
+ if (child_handle)
+ {
+ /* We still have a sub-task running - kill it */
+ block[0] = 20;
+ block[3] = 0;
+ block[4] = 0; /* Quit */
+ if ((xswi(Wimp_SendMessage, 17, block, child_handle) & v_flag) == 0)
+ {
+ /* Idle until child dies. */
+ while (child_handle)
+ {
+ process_event(wimp_poll(1, block), block);
+ }
+ }
+ }
+
+ exit(rc);
+}
+
+/*
+ * Get the position of the top left corner of the window.
+ */
+ int
+gui_mch_get_winpos(int *x, int *y)
+{
+ /* TODO */
+ return FAIL;
+}
+
+/*
+ * Set the position of the top left corner of the window to the given
+ * coordinates.
+ */
+ void
+gui_mch_set_winpos(int x, int y)
+{
+ /* TODO */
+}
+
+ void
+gui_mch_set_shellsize(width, height, min_width, min_height, base_width, base_height)
+ int width; /* In OS units */
+ int height;
+ int min_width; /* Smallest permissable window size (ignored) */
+ int min_height;
+ int base_width; /* Space for scroll bars, etc */
+ int base_height;
+{
+ int s_width, s_height;
+ int block[] = {
+ gui.window_handle,
+ 0,
+ -height + 1,
+ width,
+ 1};
+
+ gui_mch_get_screen_dimensions(&s_width, &s_height);
+ s_width -= base_width;
+ s_height -= base_height; /* Underestimate - ignores titlebar */
+
+ swi(Wimp_GetWindowState, 0, block);
+ block[3] = block[1] + width;
+ block[2] = block[4] - height;
+ if (block[3] > s_width)
+ {
+ block[3] = s_width;
+ block[1] = block[3] - width;
+ }
+ if (block[2] < gui.scrollbar_height)
+ {
+ block[2] = gui.scrollbar_height;
+ block[4] = block[2] + height;
+ }
+ swi(Wimp_OpenWindow, 0, block);
+ swi(Wimp_ForceRedraw, gui.window_handle, 0, -height, width, 0);
+}
+
+ void
+gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
+{
+ int block[] = {4, 5, 11, 12, -1};
+
+ swi(OS_ReadVduVariables, block, block);
+ *screen_w = (block[2] + 1) << block[0];
+ *screen_h = (block[3] + 1) << block[1];
+}
+
+/* Take a font name with options and return a font handle, or
+ * zero for failure.
+ * Replace extension with 'Bold' or 'Italic' depending on modifiers.
+ */
+ int
+ro_get_font(fullname, weight)
+ char_u *fullname;
+ int weight; /* Initial weights:
+ * BIT MEANING
+ * 0 bold
+ * 1 italic
+ */
+{
+ char_u *arg;
+ char_u font[41];
+ int width = -1;
+ int height = -1;
+ int name_len;
+ int i;
+ char_u c;
+
+ for (i = 0; i < 39;)
+ {
+ c = fullname[i];
+ if (c == ':' || c == NUL || c == '.')
+ break;
+ font[i++] = c;
+ }
+
+ /* find the first modifier, NULL if none */
+ arg = strchr(fullname + i, ':');
+
+ while (arg)
+ {
+ switch (*++arg)
+ {
+ case 'h':
+ height = strtol(arg + 1, (char **) &arg, 10);
+ break;
+ case 'w':
+ width = strtol(arg + 1, (char **) &arg, 10);
+ break;
+ case 'b':
+ weight |= 1;
+ break;
+ case 'i':
+ weight |= 2;
+ break;
+ default:
+ return 0;
+ }
+ arg = strchr(arg, ':');
+ }
+
+ if ((weight & 1) && i < 35)
+ {
+ /* Bold goes instead of given suffix */
+ strncpy(font + i, ".Bold", 5);
+ i += 5;
+ }
+ else
+ {
+ /* Copy rest of name unless we are using Bold */
+ while (i < 39)
+ {
+ c = fullname[i];
+ if (c == ':' || c == NUL)
+ break;
+ font[i++] = c;
+ }
+ }
+ if ((weight & 2) && i < 32)
+ {
+ strncpy(font + i, ".Oblique", 8);
+ i += 8;
+ }
+
+ font[i] = 0;
+
+ if (height < 1 && width < 1)
+ height = width = 10; /* Default to 10pt */
+ else if (height < 1)
+ height = width;
+ else if (width < 1)
+ width = height;
+
+ if (xswi(Font_FindFont, 0, font, width << 4, height << 4, 0, 0) & v_flag)
+ return NOFONT; /* Can't find font */
+
+ return r0;
+}
+
+/* Load a file into allocated memory and check it is valid.
+ * Return a pointer to the allocated block on success.
+ */
+ char *
+zap_load_file(name, style)
+ char_u *name; /* Name of directory containing styles */
+ char_u *style; /* Name of style within directory */
+{
+ char_u fname[256];
+ char_u *file;
+
+ if (strlen(name) + strlen(style) > 254)
+ return NULL; /* Names too long */
+
+ sprintf(fname, "%s.%s", name, style);
+
+ /* Load the named font in 1bpp format. */
+ if (xswi(OS_File, 13, fname, 0, 0, "VimFonts:") & v_flag || r0 != 1)
+ return NULL; /* Error reading file info, or not a file */
+
+ /* Allocate enough memory to load the whole file */
+ file = (char *) alloc(r4);
+ if (!file)
+ return NULL; /* Out of memory */
+
+ if (xswi(OS_File, 12, fname, file, 0, "VimFonts:") & v_flag)
+ return NULL; /* Unable to load file */
+
+ if (strncmp(file, "ZapFont\015", 8) == 0)
+ return file; /* Loaded OK! */
+
+ free(file);
+ return NULL; /* Not a valid font file */
+}
+
+/* Load and convert the named font.
+ * If name is NULL or a null string then convert the system font.
+ * Return OK on success; FAIL and we revert to using the VDU drivers.
+ *
+ * 'name' is the name of a directory.
+ * Tries to load 'name.0', 'name.B', 'name.I' and 'name.IB'.
+ */
+ int
+zap_load_font(name)
+ char_u *name;
+{
+ int i;
+
+ /* Free the existing font files, if any */
+ for (i = 0; i < ZAP_STYLES; i++)
+ {
+ vim_free(zap_file[i]);
+ zap_file[i] = NULL;
+ }
+
+ if (name && *name == '!')
+ {
+ name++;
+ double_height = TRUE;
+ }
+ else
+ double_height = FALSE;
+
+ if (name && *name)
+ {
+ zap_file[ZAP_NORMAL] = zap_load_file(name, "0");
+ if (!zap_file[ZAP_NORMAL])
+ return FAIL; /* Can't load the 'normal' style - error */
+
+ zap_file[ZAP_BOLD] = zap_load_file(name, "B");
+ zap_file[ZAP_ITALIC] = zap_load_file(name, "I");
+ zap_file[ZAP_BITALIC] = zap_load_file(name, "IB");
+ }
+ else
+ {
+ int *header;
+ char workarea[16];
+ char *old_wa;
+
+ /* Allocate memory for system font (8 x 8 x 256 bits, plus header) */
+ header = (int *) alloc(0x20 + 8 * 256);
+ if (header == NULL)
+ return FAIL;
+ zap_file[ZAP_NORMAL] = (char *) header;
+
+ /* Store details about the system font */
+ header[2] = 8; /* Width */
+ header[3] = 8; /* Height */
+ header[4] = 0; /* First char */
+ header[5] = 255; /* Last char */
+ header[6] = header[7] = 0; /* Reserved */
+
+ /* Get system font bitmap */
+ old_wa = zap_redraw_block.r_workarea;
+ zap_redraw_block.r_workarea = workarea;
+ swi(ZapRedraw_ReadSystemChars, zap_file[ZAP_NORMAL] + 0x20, &zap_redraw_block);
+ zap_redraw_block.r_workarea = old_wa;
+ }
+
+ return ro_zap_redraw_initialise();
+}
+
+/*
+ * Initialise vim to use the font with the given name.
+ * Return FAIL if the font could not be loaded, OK otherwise.
+ */
+ int
+gui_mch_init_font(char_u *font_name, int fontset)
+{
+ int new_handle = 0; /* Use the system font by default */
+
+ if (font_name[0] == '!')
+ {
+ /* Select a ZapRedraw font */
+ if (zap_load_font(font_name + 1))
+ zap_redraw = TRUE;
+ else
+ {
+ EMSG2(_("E610: Can't load Zap font '%s'"), font_name);
+ font_name = "System"; /* Error - use system font */
+ zap_redraw = FALSE;
+ }
+ }
+ else
+ {
+ zap_redraw = FALSE;
+
+ if (font_name)
+ {
+ /* Extract any extra details about the font */
+ new_handle = ro_get_font(font_name, 0);
+ if (!new_handle)
+ return FAIL;
+ }
+ else
+ font_name = "System";
+ }
+
+ /* Free the previous font, if any */
+ gui_mch_free_font(gui.norm_font);
+ gui.norm_font = new_handle;
+ gui.char_ascent = 0;
+
+ if (new_handle)
+ {
+ /* Read details about the chosen font */
+ swi(Font_ReadInfo, new_handle);
+
+ gui.char_width = r3 - r1;
+ gui.char_height = r4 - r2;
+
+ font_x_offset = -r1; /* Where to position each char in its box */
+ font_y_offset = -r4;
+
+ /* Try to load other fonts for bold, italic, and bold-italic */
+ gui_mch_free_font(gui.bold_font);
+ gui.bold_font = ro_get_font(font_name, 1);
+ gui_mch_free_font(gui.ital_font);
+ gui.ital_font = ro_get_font(font_name, 2);
+ gui_mch_free_font(gui.boldital_font);
+ gui.boldital_font = ro_get_font(font_name, 3);
+ }
+ else
+ {
+ /* Use the system font or ZapRedraw. */
+ if (zap_redraw)
+ {
+ gui.char_width = zap_redraw_block.r_charw << zap_redraw_block.r_magx;
+ gui.char_height = zap_redraw_block.r_charh << zap_redraw_block.r_magy;
+ if (double_height)
+ gui.char_height <<= 1;
+ }
+ else
+ {
+ gui.char_width = 16;
+ gui.char_height = 32;
+ }
+
+ gui_mch_free_font(gui.bold_font);
+ gui.bold_font = 0;
+ gui_mch_free_font(gui.ital_font);
+ gui.ital_font = 0;
+ gui_mch_free_font(gui.boldital_font);
+ gui.boldital_font = 0;
+ }
+ hl_set_font_name(font_name);
+
+ must_redraw = CLEAR;
+ return OK;
+}
+
+ int
+gui_mch_adjust_charsize()
+{
+ return FAIL;
+}
+
+/*
+ * Get a font structure for highlighting.
+ */
+ GuiFont
+gui_mch_get_font(name, giveErrorIfMissing)
+ char_u *name;
+ int giveErrorIfMissing;
+{
+ int handle;
+
+ if (!name)
+ return NOFONT; /* System font if no name */
+
+ handle = ro_get_font(name, 0);
+ if (!handle)
+ {
+ if (giveErrorIfMissing)
+ EMSG2(_("E611: Can't use font %s"), name);
+ return NOFONT;
+ }
+
+ return handle;
+}
+
+/*
+ * Set the current text font.
+ */
+ void
+gui_mch_set_font(GuiFont font)
+{
+ ro_current_font = font;
+
+ if (font)
+ {
+ /* Not the system font or ZapRedraw font - select it */
+ swi(Font_SetFont, font);
+ }
+}
+
+#if 0 /* not used */
+/*
+ * Return TRUE if the two fonts given are equivalent.
+ */
+ int
+gui_mch_same_font(GuiFont f1, GuiFont f2)
+{
+ return f1 == f2;
+}
+#endif
+
+/*
+ * If a font is not going to be used, free its structure.
+ */
+ void
+gui_mch_free_font(GuiFont font)
+{
+ if (font)
+ swi(Font_LoseFont, font);
+}
+
+/*
+ * Return the Pixel value (colour) for the given colour name.
+ * Return INVALCOLOR for error.
+ * NB: I've changed Green for now, since it looked really sick
+ */
+ guicolor_T
+gui_mch_get_color(char_u *name)
+{
+ int i;
+ struct colour
+ {
+ char_u *name;
+ guicolor_T value;
+ } colours[] =
+ {
+ { "Red", grgb(255, 0, 0) },
+ { "LightRed", grgb(255, 0, 0) },
+ { "DarkRed", grgb(139, 0, 0) },
+
+ { "Green", grgb(50, 200, 50) },
+ { "LightGreen", grgb(144, 238, 144) },
+ { "DarkGreen", grgb(0, 100, 0) },
+ { "SeaGreen", grgb(46, 139, 87) },
+
+ { "Blue", grgb(0, 0, 255) },
+ { "LightBlue", grgb(173, 216, 230) },
+ { "DarkBlue", grgb(0, 0, 139) },
+ { "SlateBlue", grgb(160, 90, 205) },
+
+ { "Cyan", grgb(0, 255, 255) },
+ { "LightCyan", grgb(224, 255, 255) },
+ { "DarkCyan", grgb(0, 139, 139) },
+
+ { "Magenta", grgb(255, 0, 255) },
+ { "LightMagenta", grgb(255, 224, 255) },
+ { "DarkMagenta", grgb(139, 0, 139) },
+
+ { "Yellow", grgb(255, 255, 0) },
+ { "LightYellow", grgb(255, 255, 224) },
+ { "DarkYellow", grgb(139, 139, 0) },
+ { "Brown", grgb(165, 42, 42) },
+
+ { "Gray", grgb(190, 190, 190) },
+ { "Grey", grgb(190, 190, 190) },
+ { "LightGray", grgb(211, 211, 211) },
+ { "LightGrey", grgb(211, 211, 211) },
+ { "DarkGray", grgb(169, 169, 169) },
+ { "DarkGrey", grgb(169, 169, 169) },
+
+ { "Black", grgb(0, 0, 0) },
+ { "White", grgb(255, 255, 255) },
+
+ { "Orange", grgb(255, 165, 0) },
+ { "Purple", grgb(160, 32, 240) },
+ { "Violet", grgb(238, 130, 238) },
+ {NULL, 0}
+ };
+
+ if (name[0] == '#')
+ {
+ char *end;
+ int c;
+
+ c = strtol(name + 1, &end, 16);
+ return (guicolor_T) ((c >> 16) & 0xff) | (c & 0xff00) | ((c & 0xff) << 16);
+ }
+
+ for (i = 0; colours[i].name != NULL; i++)
+ {
+ if (STRICMP(name, colours[i].name) == 0)
+ return colours[i].value;
+ }
+ if (strnicmp(name, "grey", 4) == 0 || strnicmp(name, "gray", 4) == 0)
+ {
+ int level = (255 * atoi(name + 4)) / 100;
+ return (guicolor_T) grgb(level, level, level);
+ }
+ return INVALCOLOR;
+}
+
+/*
+ * Set the current text colours.
+ * If we are using fonts then set the antialiasing colours too.
+ */
+ void
+gui_mch_set_colors(guicolor_T fg, guicolor_T bg)
+{
+ zap_redraw_colours[0] = bg << 8; /* JK230798, register new background colour */
+ zap_redraw_colours[1] = fg << 8; /* JK230798, register new foreground colour */
+ zap_redraw_update_colours = TRUE; /* JK230798, need update of colour masks */
+
+ swi(ColourTrans_ReturnGCOL, fg << 8);
+ gui.fg_colour = r0;
+ swi(ColourTrans_ReturnGCOL, bg << 8);
+ gui.bg_colour = r0;
+
+ if (ro_current_font)
+ swi(ColourTrans_SetFontColours, 0, bg << 8, fg << 8, 14);
+}
+
+ void
+ro_draw_string(x, y, s, len, flags, clip)
+ int x; /* Top-left coord to plot at (x incl, y excl) */
+ int y; /* (screen coords) */
+ char_u *s; /* String to plot */
+ int len; /* Length of string */
+ int flags; /* DRAW_TRANSP, DRAW_BOLD, DRAW_UNDERL */
+ int* clip; /* JK230798, added clip window */
+{
+ if (ro_current_font)
+ {
+ int fx;
+ int flen = len; /* Preserve for underline */
+
+ /* Use the Font manager to paint the string.
+ * Must do one char at a time to get monospacing.
+ */
+
+ if (flags & DRAW_ITALIC && !gui.ital_font)
+ flags |= DRAW_UNDERL; /* No italic - underline instead */
+
+ if ((flags & DRAW_TRANSP) == 0)
+ {
+ swi(ColourTrans_SetColour, gui.bg_colour, 0, 0, 0, 0);
+ swi(OS_Plot, 4, x, y - gui.char_height);
+ swi(OS_Plot, 96 + 5, x + len * gui.char_width - 1, y - 1);
+ }
+
+ fx = x + font_x_offset;
+ while (flen--)
+ {
+ swi(Font_Paint, 0, s++, 0x90, fx, y + font_y_offset, 0, 0, 1);
+ fx += gui.char_width;
+ }
+ }
+ else
+ {
+ if (zap_redraw)
+ {
+ /* Using fast Zap redraw. */
+ flags = ro_zap_redraw_draw_string(x, y, s, len, flags, clip);
+ }
+ else
+ {
+ /* Using the system font */
+ if (flags & DRAW_ITALIC)
+ flags |= DRAW_UNDERL;
+
+ if ((flags & DRAW_TRANSP) == 0)
+ {
+ swi(ColourTrans_SetColour, gui.bg_colour, 0, 0, 0, 0);
+ swi(OS_Plot, 4, x, y - gui.char_height);
+ swi(OS_Plot, 96 + 5, x + len * gui.char_width - 1, y - 1);
+ }
+ swi(OS_Plot, 4, /* Move the drawing cursor */
+ x,
+ y - 1);
+ swi(ColourTrans_SetColour, gui.fg_colour, 0, 0, 0, 0);
+ swi(OS_WriteN, s, len);
+
+ if (flags & DRAW_BOLD)
+ {
+ swi(OS_Plot, 4, x + (1 << x_eigen_factor), y - 1);
+ swi(OS_WriteN, s, len);
+ }
+ }
+ }
+
+ if (flags & DRAW_UNDERL)
+ {
+ if (ro_current_font || zap_redraw)
+ swi(ColourTrans_SetColour, gui.fg_colour, 0, 0, 0, 0);
+ /* Underlined is the same with all plotting methods */
+ swi(OS_Plot, 4, x, y - gui.char_height);
+ swi(OS_Plot, 1, gui.char_width * len, 0);
+ }
+}
+
+ void
+gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
+{
+ int x, y; /* Workarea x,y */
+ x = col * gui.char_width;
+ y = -row * gui.char_height;
+
+ if (redraw_block)
+ {
+ ro_draw_string(x + redraw_block[1], y + redraw_block[4],
+ s, len, flags, &redraw_block[7]); /* JK230798, added clip window */
+ }
+ else
+ {
+ int block[44];
+ block[0] = gui.window_handle;
+ block[1] = x;
+ block[2] = y - gui.char_height;
+ block[3] = (col + len) * gui.char_width;
+ block[4] = y;
+ swi(Wimp_UpdateWindow, 0, block);
+ while (r0)
+ {
+ ro_draw_string(x + block[1], y + block[4],
+ s, len, flags, &block[7]); /* JK230798, added clip window */
+ swi(Wimp_GetRectangle, 0, block);
+ }
+ }
+}
+
+/*
+ * Return OK if the key with the termcap name "name" is supported.
+ */
+ int
+gui_mch_haskey(char_u *name)
+{
+ return FAIL;
+}
+
+ void
+gui_mch_beep(void)
+{
+ swi(OS_WriteI + 7);
+}
+
+/*
+ * Visual bell.
+ */
+ void
+gui_mch_flash(int msec)
+{
+ /* TODO */
+}
+
+
+/*
+ * Plot a solid rectangle using the given plot action and colour.
+ * Coordinates are inclusive and window-relative.
+ */
+ void
+plot_rectangle(plot, colour, minx, miny, maxx, maxy)
+ int plot; /* OS_Plot action */
+ int colour;
+ int minx;
+ int miny;
+ int maxx;
+ int maxy;
+{
+ if (redraw_block)
+ {
+ swi(ColourTrans_SetColour, colour, 0, 0, 0, 0);
+ swi(OS_Plot, 4, minx + redraw_block[1], miny + redraw_block[4]);
+ swi(OS_Plot, plot, maxx + redraw_block[1], maxy + redraw_block[4]);
+ }
+ else
+ {
+ int block[44];
+ block[0] = gui.window_handle;
+ block[1] = minx;
+ block[2] = miny;
+ block[3] = maxx + 1;
+ block[4] = maxy + 1;
+ swi(Wimp_UpdateWindow, 0, block);
+ while (r0)
+ {
+ swi(ColourTrans_SetColour, colour, 0, 0, 0, 0);
+ swi(OS_Plot, 4, minx + block[1], miny + block[4]);
+ swi(OS_Plot, plot, maxx + block[1], maxy + block[4]);
+ swi(Wimp_GetRectangle, 0, block);
+ }
+ }
+}
+
+/*
+ * Invert a rectangle from row r, column c, for nr rows and nc columns.
+ */
+ void
+gui_mch_invert_rectangle(int r, int c, int nr, int nc)
+{
+ plot_rectangle(96 + 6, 0, FILL_X(c), -FILL_Y(r + nr), FILL_X(c + nc), -FILL_Y(r));
+}
+
+/*
+ * Iconify the GUI window.
+ */
+ void
+gui_mch_iconify(void)
+{
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Bring the Vim window to the foreground.
+ */
+ void
+gui_mch_set_foreground()
+{
+ /* TODO */
+}
+#endif
+
+/* Draw a hollow rectangle relative to the current
+ * graphics cursor position, with the given width
+ * and height. Start position is top-left.
+ */
+ void
+draw_hollow(w, h)
+ int w;
+ int h;
+{
+ swi(OS_Plot, 1, w - 1, 0);
+ swi(OS_Plot, 1, 0, 1 - h);
+ swi(OS_Plot, 1, 1 - w, 0);
+ swi(OS_Plot, 1, 0, h - 1);
+}
+
+/*
+ * Draw a cursor without focus.
+ */
+ void
+gui_mch_draw_hollow_cursor(guicolor_T colour)
+{
+ int x = FILL_X(gui.cursor_col); /* Window relative, top-left */
+ int y = -FILL_Y(gui.cursor_row);
+ if (redraw_block == NULL)
+ {
+ int block[11];
+
+ block[0] = gui.window_handle;
+ block[1] = x;
+ block[2] = y - gui.char_height;
+ block[3] = x + gui.char_width;
+ block[4] = y;
+ swi(Wimp_UpdateWindow, 0, block);
+ while (r0)
+ {
+ swi(ColourTrans_SetGCOL, colour << 8, 0, 0, 0, 0);
+
+ swi(OS_Plot, 4, x + block[1], y + block[4] - 1);
+ draw_hollow(gui.char_width, gui.char_height);
+
+ swi(Wimp_GetRectangle, 0, block);
+ }
+ }
+ else
+ {
+ swi(ColourTrans_SetGCOL, colour << 8, 0, 0, 0, 0);
+
+ swi(OS_Plot, 4, x + redraw_block[1], y + redraw_block[4] - 1);
+ draw_hollow(gui.char_width, gui.char_height);
+ }
+}
+
+/*
+ * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using
+ * color "color".
+ */
+ void
+gui_mch_draw_part_cursor(w, h, colour)
+ int w;
+ int h;
+ guicolor_T colour;
+{
+ int x = FILL_X(gui.cursor_col);
+ int y = -FILL_Y(gui.cursor_row);
+ swi(ColourTrans_ReturnGCOL, colour << 8);
+ plot_rectangle(96 + 5, r0, x, y - h, x + w - 1, y - 1);
+}
+
+/*
+ * Catch up with any queued events. This may put keyboard input into the
+ * input buffer, call resize call-backs, trigger timers etc.
+ * If there is nothing in the event queue(& no timers pending), then we return
+ * immediately (well, after a Wimp_Poll).
+ */
+ void
+gui_mch_update(void)
+{
+ int block[64];
+ int reason;
+
+ swi(OS_ReadMonotonicTime);
+ if ((r0 - time_of_last_poll) < 50)
+ return; /* Don't return too often */
+
+ reason = wimp_poll(0, block);
+ if (reason)
+ process_event(reason, block);
+ ro_return_early = FALSE; /* We're returning anyway. */
+}
+
+ void
+redraw_window(block)
+ int *block;
+{
+ int x, y; /* Vim workarea coords */
+ int width, height;
+ int blank_col;
+
+ swi(ColourTrans_ReturnGCOL, UNUSED_COLOUR << 8, 0, 0, 1<<7, 0);
+ blank_col = r0;
+
+ swi(Wimp_RedrawWindow, 0, block);
+ redraw_block = block;
+ while (r0)
+ {
+ x = block[7] - block[1];
+ y = block[4] - block[10];
+ width = block[9] - block[7];
+ height = block[10] - block[8];
+
+ if (height + y > Rows * gui.char_height)
+ {
+ /* Blank everything off the bottom. */
+ plot_rectangle(96 + 5, blank_col,
+ 0, block[8] - block[4],
+ block[9] - block[1], -FILL_Y(Rows) - 1);
+ height = Rows * gui.char_height;
+ }
+ if (width + x> Columns * gui.char_width)
+ {
+ /* Blank everything off to the right. */
+ plot_rectangle(96 + 5, blank_col,
+ FILL_X(Columns), block[8] - block[4],
+ block[9] - block[1], 0);
+ width = Columns * gui.char_width;
+ }
+ gui_redraw(x , y, width, height);
+ swi(Wimp_GetRectangle, 0, block);
+ }
+ redraw_block = NULL;
+}
+
+/* Check if we have modified data.
+ * If we do then ack the message to stop the shutdown.
+ * Otherwise, ignore the message.
+ */
+ void
+ro_prequit(block)
+ int *block;
+{
+ if (!ro_ok_to_quit())
+ {
+ /* Not OK to quit - stop shutdown */
+ block[3] = block[2];
+ swi(Wimp_SendMessage, 19, block, block[1]);
+ }
+ /* Do nothing. We may get a Message_Quit later. */
+}
+
+/* If there is unsaved data then ask the user if they mind losing it.
+ * Return TRUE if we can quit without saving, FALSE to halt the
+ * shutdown.
+ */
+ int
+ro_ok_to_quit()
+{
+ int old_confirm = cmdmod.confirm;
+
+ cmdmod.confirm = FALSE; /* Use our own, single tasking, box */
+
+ if (check_changed_any(FALSE))
+ {
+ swi(Wimp_ReportError,
+ "\0\0\0\0Vim contains unsaved data - quit anyway?",
+ 0x17,
+ "Vim");
+ cmdmod.confirm = old_confirm;
+ if (r1 != 1)
+ return FALSE;
+ }
+ cmdmod.confirm = old_confirm;
+ return TRUE;
+}
+
+/* Quit without checking for unsaved data. */
+ void
+ro_quit()
+{
+ exiting = TRUE;
+ getout(0);
+
+ exiting = FALSE; /* probably can't get here */
+ setcursor(); /* position cursor */
+ out_flush();
+}
+
+/* Insent the given vim special code into the input buffer */
+ void
+ro_press(a, b, modifier)
+ char a;
+ char b;
+ int modifier; /* %<Ctrl><Shift> 0000 0000 */
+{
+ char_u buf[6];
+ int vim_mod;
+ int key;
+
+
+ /* Convert RISC OS modifier to Vim modifier. */
+ vim_mod = ((modifier & 0x10) ? MOD_MASK_SHIFT : 0)
+ | ((modifier & 0x20) ? MOD_MASK_CTRL : 0);
+ key = simplify_key(TERMCAP2KEY(a, b), &vim_mod);
+
+ buf[3] = CSI;
+ buf[4] = KEY2TERMCAP0(key);
+ buf[5] = KEY2TERMCAP1(key);
+ if (vim_mod)
+ {
+ buf[0] = CSI;
+ buf[1] = KS_MODIFIER;
+ buf[2] = vim_mod;
+ add_to_input_buf(buf, 6);
+ }
+ else
+ add_to_input_buf(buf + 3, 3);
+}
+
+/* Take a wimp key code and insert the vim equivalent
+ * into vim's input buffer.
+ * CTRL-C also sets got_int.
+ */
+ void
+ro_insert_key(code)
+ char_u *code; /* Wimp_ProcessKey code (4 bytes) */
+{
+ char a = code[0];
+ char b = code[1];
+ int base, modifier;
+
+ if (a == 3 && ctrl_c_interrupts)
+ got_int = TRUE;
+
+ /* Is it a normal key? */
+ if (a > 31 && a < 127)
+ {
+ add_to_input_buf(code, 1);
+ return;
+ }
+
+ /* We should pass any unrecognised keys on, but
+ * for now just pass on F12 combinations.
+ */
+ switch (b)
+ {
+ case 0:
+ /* Home and Delete are the only special cases */
+ switch (a)
+ {
+ case 0x1e:
+ ro_press('k','h', 0); /* Home */
+ return;
+ case 0x7f:
+ ro_press('k','D', 0); /* Delete */
+ return;
+ case CSI:
+ {
+ /* Turn CSI into K_CSI. Untested! */
+ char_u string[3] = {CSI, KS_EXTRA, KE_CSI};
+
+ add_to_input_buf(string, 3);
+ return;
+ }
+ default:
+ add_to_input_buf(code, 1);
+ return;
+ }
+ case 1:
+ if ((a & 0xcf) == 0xcc)
+ {
+ /* F12 pressed - pass it on (quick hack) */
+ swi(Wimp_ProcessKey, a | 0x100);
+ return;
+ }
+ base = a & 0xcf;
+ modifier = a & 0x30;
+ switch (base)
+ {
+ case 0x8a: /* Tab */
+ add_to_input_buf("\011", 1);
+ return;
+ case 0x8b: /* Copy (End) */
+ return ro_press('@', '7', modifier);
+ case 0x8c: /* Left */
+ return ro_press('k', 'l', modifier);
+ case 0x8d: /* Right */
+ return ro_press('k', 'r', modifier);
+ case 0x8e: /* Down */
+ if (modifier & 0x10)
+ return ro_press('k', 'N', modifier ^ 0x10);
+ else
+ return ro_press('k', 'd', modifier);
+ case 0x8f: /* Up */
+ if (modifier & 0x10)
+ return ro_press('k', 'P', modifier ^ 0x10);
+ else
+ return ro_press('k', 'u', modifier);
+ case 0xca: /* F10 */
+ return ro_press('k', ';', modifier);
+ case 0xcb: /* F11 */
+ return ro_press('F', '1', modifier);
+ case 0xcd: /* Insert */
+ return ro_press('k', 'I', modifier);
+ default:
+ if (base > 0x80 && base < 0x18a)
+ {
+ /* One of the other function keys */
+ return ro_press('k', '0' + (base & 15), modifier);
+ }
+ }
+ }
+}
+
+/* Process a mouse event. */
+ void
+ro_mouse(block)
+ int *block;
+{
+ int x, y, button, vim_button;
+ int modifiers = 0;
+ int min_x, min_y; /* Visible area of editor window */
+ int max_x, max_y;
+
+ if (block[3] != gui.window_handle || ro_dragging)
+ return; /* Not our window or ignoring clicks*/
+
+ x = block[0]; /* Click position - screen coords */
+ y = block[1];
+ button = block[2];
+
+ block[0] = gui.window_handle;
+ swi(Wimp_GetWindowState, 0, block);
+ min_x = block[1];
+ min_y = block[2];
+ max_x = block[3];
+ max_y = block[4];
+
+ if (block[3] - x < gui.scrollbar_width)
+ {
+ /* Click in that blank area under the scrollbars */
+
+ if (button & 0x444)
+ {
+ int front_block[10];
+ /* Dragging with Select - bring window to front first */
+ front_block[0] = gui.window_handle;
+ swi(Wimp_GetWindowState, 0, front_block);
+ front_block[7] = -1;
+ ro_open_main(front_block);
+ }
+
+ block[0] = gui.window_handle;
+ block[1] = 7; /* Drag point */
+ block[2] = block[4] = 0; /* Coords of point. */
+ block[3] = block[5] = 0;
+ drag_x_offset = max_x - x;
+ drag_y_offset = min_y - y;
+
+ /* Parent box. */
+ block[6] = min_x +
+ gui.scrollbar_width * 2 +
+ MIN_COLUMNS * gui.char_width;
+ block[7] = 0;
+ gui_mch_get_screen_dimensions(&block[8], &block[9]);
+ block[9] = max_y -
+ 4 * gui.char_height -
+ gui.scrollbar_height;
+
+ swi(Wimp_DragBox, 0, block);
+ ro_dragging = DRAG_RESIZE_WINDOW;
+ drag_button = vim_button;
+ drag_modifiers = modifiers;
+ return;
+ }
+
+ if (button & 0x111)
+ vim_button = MOUSE_RIGHT;
+ else if (button & 0x222)
+ vim_button = MOUSE_MIDDLE;
+ else
+ vim_button = MOUSE_LEFT;
+
+ swi(OS_Byte, 121, 0x80);
+ if (r1 == 0xff)
+ modifiers |= MOUSE_SHIFT;
+ swi(OS_Byte, 121, 0x81);
+ if (r1 == 0xff)
+ modifiers |= MOUSE_CTRL;
+ swi(OS_Byte, 121, 0x82);
+ if (r1 == 0xff)
+ modifiers |= MOUSE_ALT;
+
+ if (button == 2)
+ {
+ /* Menu click:
+ * If shift was pressed then do the paste action.
+ * If not, then open the pop-up menu.
+ */
+ modifiers ^= MOUSE_SHIFT;
+ if (modifiers && MOUSE_SHIFT)
+ {
+ vimmenu_T main;
+ /* Shift was NOT pressed - show menu */
+ main.dname = (char_u *) "Vim";
+ main.children = root_menu;
+ gui_mch_show_popupmenu(&main);
+ return;
+ }
+ }
+
+ /* Gain the input focus */
+ swi(Wimp_SetCaretPosition, gui.window_handle, -1, 0, 0, -1, -1);
+
+ if (button & 0xf0)
+ {
+ /* Drag operation:
+ *
+ * Tell the Wimp to start a drag.
+ * Monitor null events.
+ */
+ block[1] = 7; /* Drag a point. */
+ block[2] = block[4] = x; /* Coords of point. */
+ block[3] = block[5] = y;
+ block[6] = 0; /* Coords of bounding box. */
+ block[7] = 0;
+ gui_mch_get_screen_dimensions(&block[8], &block[9]);
+
+ drag_x_offset = drag_y_offset = 0;
+
+ swi(Wimp_DragBox, 0, block);
+ ro_dragging = DRAG_SELECTION;
+ drag_button = vim_button;
+ drag_modifiers = modifiers;
+
+ vim_button |= MOUSE_DRAG;
+ }
+
+ gui_send_mouse_event(
+ vim_button,
+ x - min_x,
+ max_y - y,
+ button & 0xf ? TRUE : FALSE, /* dclick */
+ modifiers);
+}
+
+ void
+ro_continue_drag(block)
+ int *block; /* Just used as scrap. */
+{
+ int x, y;
+
+ /* Get screen coords of pointer. */
+ swi(Wimp_GetPointerInfo, 0, block);
+ x = block[0] + drag_x_offset;
+ y = block[1] + drag_y_offset;
+
+ block[0] = gui.window_handle;
+ swi(Wimp_GetWindowState, 0, block);
+
+ if (ro_dragging == DRAG_RESIZE_WINDOW)
+ {
+ /* Resizeing the main window. */
+ block[2] = y;
+ block[3] = x;
+ ro_open_main(block);
+ }
+ else
+ {
+ /* Selecting some text. */
+ gui_send_mouse_event(
+ drag_button | MOUSE_DRAG, /* Always report the same button */
+ x - block[1],
+ block[4] - y,
+ FALSE, /* Not a double click. */
+ drag_modifiers);
+ }
+}
+
+/* User has released all mouse buttons, marking the end of a drag. */
+ void
+ro_drag_finished(block)
+ int *block;
+{
+ int x;
+ int y;
+ int width, height;
+
+ /* I don't trust the box returned by Wimp_Poll; look at the pointer
+ * ourselves.
+ */
+ swi(Wimp_GetPointerInfo, 0, block);
+ x = block[0] + drag_x_offset;
+ y = block[1] + drag_y_offset;
+
+ if (ro_dragging == DRAG_RESIZE_WINDOW)
+ {
+ block[0] = gui.window_handle;
+ swi(Wimp_GetWindowState, 0, block);
+ block[2] = y;
+ block[3] = x;
+ ro_open_main(block);
+
+ width = (block[3] - block[1]);
+ height = (block[4] - block[2]);
+
+ swi(Wimp_ForceRedraw, gui.window_handle, 0, -height, width, 0);
+ gui_resize_shell(width, height);
+ }
+ else
+ {
+ block[0] = gui.window_handle;
+ swi(Wimp_GetWindowState, 0, block);
+ gui_send_mouse_event(
+ MOUSE_RELEASE,
+ x - block[1],
+ block[4] - y,
+ FALSE, /* not a double click */
+ drag_modifiers);
+ }
+ ro_dragging = DRAG_FALSE;
+}
+
+/* Load the file/pathname given in block into a [new] buffer.
+ *
+ * Modifier Action
+ *
+ * None :confirm e <file>
+ * Ctrl :sp <file>
+ * Shift <file>
+ *
+ * Insert into typebuf, at the start.
+ * If loading from !Scrap then use saved leafname instead, and
+ * delete the scrap file. Also, ignore shift key.
+ *
+ * NB: Doesn't send DataLoadAck (other app might delete temp file?).
+ */
+ void
+ro_dataload(block)
+ int *block;
+{
+ char_u new_path[MAXPATHL];
+ char_u *path = ((char_u *) block) + 44;
+ int scrap = FALSE;
+
+ if (block[3] == leaf_ref && leaf_name)
+ scrap = TRUE;
+
+ switch (get_real_state() & 0xff)
+ {
+ case INSERT:
+ case CMDLINE:
+ case CMDLINE+LANGMAP:
+ /* For insert mode we can only insert the pathname (currently)
+ * Make sure Shift is pressed.
+ */
+ swi(OS_Byte, 121, 0x80); /* Is Shift pressed? */
+ if (r1 == 0xff)
+ {
+ ins_typebuf(" ", REMAP_NONE, 0, TRUE, FALSE);
+ ins_typebuf(path, REMAP_NONE, 0, TRUE, FALSE);
+ ro_return_early = TRUE; /* Return even though nothing was typed. */
+ }
+ else
+ swi(Wimp_ReportError,
+ "\0\0\0\0Sorry, you can only load text in normal mode", 5, "Vim");
+ break;
+
+ case NORMAL:
+ ro_return_early = TRUE; /* Return even though nothing was typed. */
+
+ if (scrap) /* Remove <Wimp$Scrap>. Later. */
+ ins_typebuf(":!~remove <Wimp$Scrap>\r", REMAP_NONE, 0, TRUE, FALSE);
+
+ /* Insert {:sp ,:confirm e }[+f\ <leaf> ]<file><CR> */
+ ins_typebuf("\r", REMAP_NONE, 0, TRUE, FALSE);
+ ins_typebuf(path, REMAP_NONE, 0, TRUE, FALSE);
+ ins_typebuf(" ", REMAP_NONE, 0, TRUE, FALSE);
+
+ if (scrap)
+ {
+ /* Loading via !Scrap - change pathname to stored leafname */
+ ins_typebuf(leaf_name, REMAP_NONE, 0, TRUE, FALSE);
+ ins_typebuf(" +f\\ ", REMAP_NONE, 0, TRUE, FALSE);
+ leaf_ref = 0;
+ vim_free(leaf_name);
+ leaf_name = NULL;
+ }
+
+ swi(OS_Byte, 121, 0x81); /* Is Ctrl pressed? */
+ if (r1 == 0xff)
+ /* Yes, split window */
+ ins_typebuf(":sp", REMAP_NONE, 0, TRUE, FALSE);
+ else
+ ins_typebuf(":confirm e", REMAP_NONE, 0, TRUE, FALSE);
+ break;
+
+ default:
+ swi(Wimp_ReportError, "\0\0\0\0You can only load text in normal mode.", 5, "Vim");
+ }
+ /* Send DataSaveAck so other program doesn't think we died
+ * and delete <Wimp$Scrap>.
+ */
+ block[3] = block[2];
+ block[4] = 4;
+ swi(Wimp_SendMessage, 17, block, block[1]);
+}
+
+ void
+ro_datasave(block)
+ int *block;
+{
+ char_u *path = ((char_u *) block) + 44;
+
+ /* Preserve the name given so we can use it, not <Wimp$Scrap> */
+ if (leaf_name)
+ vim_free(leaf_name);
+ leaf_name = vim_strsave(path);
+
+ block[9] = -1; /* File is unsafe. */
+ strcpy(path, "<Wimp$Scrap>");
+ block[0] = 60;
+ block[3] = block[2];
+ block[4] = 2;
+ swi(Wimp_SendMessage, 17, block, block[1]);
+
+ leaf_ref = block[2];
+}
+
+ void
+ro_message(block)
+ int *block;
+{
+ char_u *buffer;
+ long_u len;
+
+ if (block[1] == task_handle)
+ return; /* Don't talk to ourself! */
+ switch (block[4])
+ {
+ case 0: /* Quit. */
+ if (block[4] == 0)
+ ro_quit();
+ break;
+ case 1: /* DataSave */
+ ro_datasave(block);
+ break;
+ case 2: /* DataSaveAck. */
+ if (clip_convert_selection(&buffer, &len, &clip_star) == -1)
+ return;
+
+ /* Save the clipboard contents to a file. */
+ swi(OS_File, 10, ((char_u *) block) + 44, 0xfff, 0, buffer, buffer + len);
+
+ /* Ack with DataLoad message. */
+ block[3] = block[2];
+ block[4] = 3;
+ block[9] = len;
+ swi(Wimp_SendMessage, 17, block, block[1]);
+
+ vim_free(buffer);
+ break;
+ case 3: /* DataLoad */
+ ro_dataload(block);
+ break;
+ case 8: /* PreQuit */
+ ro_prequit(block);
+ break;
+ case 0xf: /* Lose clipboard. */
+ if (block[5] & 4)
+ {
+ clip_free_selection(&clip_star);
+ clip_star.owned = FALSE;
+ }
+ break;
+ case 0x10: /* DataRequest (clip_star) */
+ if (clip_star.owned)
+ {
+ int rows;
+
+ /* Tell other program that we have the clipboard. */
+ block[0] = 52;
+ block[3] = block[2]; /* Copy myref to yourref. */
+ block[4] = 1; /* DataSave message. */
+ /* Create an estimate for the size (larger or same as true
+ * value) */
+ rows = clip_star.end.lnum - clip_star.start.lnum;
+ if (rows < 0)
+ rows = -rows;
+ block[9] = (rows + 1) * Columns + 1; /* Add one for possible
+ final newline. */
+ block[10] = 0xfff; /* Clipboard is text. */
+ strcpy( ((char_u *) block) + 44, "VimClip");
+ swi(Wimp_SendMessage, 17, block, block[1]);
+ }
+ break;
+ case 0x400c1: /* Mode change */
+ changed_mode = TRUE; /* Flag - update on next OpenWindow */
+ if (zap_redraw)
+ {
+ /* JK230798, re-initialise ZapRedraw stuff */
+ if (ro_zap_redraw_initialise() == FAIL)
+ zap_redraw = FALSE;
+ }
+ break;
+ case 0x400c3: /* TaskCloseDown */
+ if (block[1] == child_handle)
+ child_handle = 0;
+ break;
+ }
+}
+
+/*
+ * Converts a scrollbar's window handle into a scrollbar pointer.
+ * NULL on failure.
+ */
+ scrollbar_T *
+ro_find_sbar(id)
+ int id;
+{
+ win_T *wp;
+
+ if (gui.bottom_sbar.id == id)
+ return &gui.bottom_sbar;
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_scrollbars[SBAR_LEFT].id == id)
+ return &wp->w_scrollbars[SBAR_LEFT];
+ if (wp->w_scrollbars[SBAR_RIGHT].id == id)
+ return &wp->w_scrollbars[SBAR_RIGHT];
+ }
+ return NULL;
+}
+
+ void
+scroll_to(line, sb)
+ int sb; /* Scrollbar number */
+ int line;
+{
+ char_u code[8];
+
+ /* Don't put events in the input queue now. */
+ if (hold_gui_events)
+ return;
+
+ /* Send a scroll event:
+ *
+ * A scrollbar event is CSI (NOT K_SPECIAL), KS_VER_SCROLLBAR,
+ * KE_FILLER followed by:
+ * one byte representing the scrollbar number, and then four bytes
+ * representing a long_u which is the new value of the scrollbar.
+ */
+ code[0] = CSI;
+ code[1] = KS_VER_SCROLLBAR;
+ code[2] = KE_FILLER;
+ code[3] = sb;
+ code[4] = line >> 24;
+ code[5] = line >> 16;
+ code[6] = line >> 8;
+ code[7] = line;
+ add_to_input_buf(code, 8);
+}
+
+ void
+h_scroll_to(col)
+ int col;
+{
+ char_u code[8];
+
+ /* Don't put events in the input queue now. */
+ if (hold_gui_events)
+ return;
+
+ /* Send a scroll event:
+ *
+ * A scrollbar event is CSI (NOT K_SPECIAL)
+ *
+ * A horizontal scrollbar event is K_SPECIAL, KS_HOR_SCROLLBAR,
+ * KE_FILLER followed by four bytes representing a long_u which is the
+ * new value of the scrollbar.
+ */
+ code[0] = CSI;
+ code[1] = KS_HOR_SCROLLBAR;
+ code[2] = KE_FILLER;
+ code[4] = col >> 24;
+ code[5] = col >> 16;
+ code[6] = col >> 8;
+ code[7] = col;
+ add_to_input_buf(code, 8);
+}
+
+ void
+ro_scroll(block)
+ int *block;
+{
+ scrollbar_T *sb;
+ int offset;
+ win_T *wp;
+
+ /* Block is ready for Wimp_OpenWindow, and also contains:
+ *
+ * +32 = scroll X direction (-2 .. +2)
+ * +36 = scroll Y direction (-2 .. +2)
+ */
+
+ sb = ro_find_sbar(block[0]);
+ if (!sb)
+ return; /* Window not found (error). */
+
+ wp = sb-> wp;
+
+ if (wp == NULL)
+ {
+ /* Horizontal bar. */
+ offset = block[8];
+ if (offset == -2)
+ offset = (block[1] - block[3]) / gui.char_width;
+ else if (offset == 2)
+ offset = (block[3] - block[1]) / gui.char_width;
+
+ block[5] += offset * gui.char_width;
+
+ gui_drag_scrollbar(sb, block[5] / gui.char_width, FALSE);
+
+ swi(Wimp_OpenWindow, 0, block);
+ }
+ else
+ {
+ offset = -block[9];
+ if (offset == -2)
+ offset = -(wp -> w_height - 1);
+ else if (offset == 2)
+ offset = wp -> w_height - 1;
+
+ /* Possibly we should reposition the scrollbar?
+ * Vim seems to update the bar anyway...
+ */
+ gui_drag_scrollbar(sb, offset - (block[6] / gui.char_height), FALSE);
+ }
+}
+
+/* Move a window by a given offset. Used to simulate the function of the
+ * nested wimp.
+ */
+ void
+ro_move_child(window, x, y, pos_wanted, pos_got)
+ int window;
+ int x,y; /* offset to move by */
+ int pos_wanted, pos_got;
+{
+ int block[10];
+
+ block[0] = window;
+ swi(Wimp_GetWindowState, 0, block);
+ block[1] += x;
+ block[2] += y;
+ block[3] += x;
+ block[4] += y;
+ if (pos_wanted == -1)
+ block[7] = -1;
+ else if (pos_wanted == -2)
+ block[7] = pos_got;
+ swi(Wimp_OpenWindow, 0, block);
+}
+
+/* Open the main window. Also updates scrollbars if we are not
+ * using the nested Wimp.
+ * If we have just changed mode then re-read all values.
+ */
+ void
+ro_open_main(block)
+ int *block;
+{
+ int toggle_size;
+
+ /* Find out if the user clicked on the toggle size icon. */
+ block[20] = block[0];
+ swi(Wimp_GetWindowState, 0, block + 20);
+ toggle_size = block[28] & (1 << 19);
+
+ if (nested_wimp)
+ {
+ swi(Wimp_OpenWindow, 0, block);
+ }
+ else
+ {
+ int old[10];
+ int x_offset, y_offset; /* Move children same as parent. */
+ int pos_wanted, pos_got;
+ int left_bar = gui.which_scrollbars[SBAR_LEFT];
+ int right_bar = gui.which_scrollbars[SBAR_RIGHT];
+ win_T *wp;
+
+ /* Three cases to think about:
+ * 1) Move to top. Open each window at the top.
+ * 2) Same stack position. Open each with same position.
+ * 3) Open at bottom. Open children with parent's new position.
+ */
+
+ old[0] = block[0];
+ swi(Wimp_GetWindowState, 0, old);
+ pos_wanted = block[7];
+ swi(Wimp_OpenWindow, 0, block);
+ /* Block updated by OpenWindow? I don't think so! */
+ swi(Wimp_GetWindowState, 0, block);
+ pos_got = block[7];
+
+ x_offset = block[1] - old[1];
+ y_offset = block[4] - old[4];
+ if (x_offset || y_offset || pos_wanted == -1 || pos_wanted == -2)
+ {
+ /* If parent has moved, re-open all the child windows. */
+ FOR_ALL_WINDOWS(wp)
+ {
+ /* Reopen scrollbars for this window. */
+ if (left_bar)
+ ro_move_child(wp -> w_scrollbars[SBAR_LEFT].id,
+ x_offset, y_offset,
+ pos_wanted, pos_got);
+ if (right_bar)
+ ro_move_child(wp -> w_scrollbars[SBAR_RIGHT].id,
+ x_offset, y_offset,
+ pos_wanted, pos_got);
+ }
+ }
+ }
+ if (changed_mode || toggle_size)
+ {
+ int width, height;
+
+ if (changed_mode)
+ ro_measure_tools();
+ block[0] = gui.window_handle;
+ swi(Wimp_GetWindowState, 0, block);
+
+ width = block[3] - block[1];
+ height = block[4] - block[2];
+ swi(Wimp_ForceRedraw, gui.window_handle, 0, -height, width, 0);
+ gui_resize_shell(width, height);
+ changed_mode = FALSE;
+ }
+}
+
+ void
+ro_open_window(block)
+ int *block;
+{
+ int pos;
+ scrollbar_T *sb;
+
+ if (block[0] == gui.window_handle)
+ ro_open_main(block);
+ else
+ {
+ swi(Wimp_OpenWindow, 0, block);
+ if (block[0] != gui.window_handle)
+ {
+ sb = ro_find_sbar(block[0]);
+ if (sb)
+ {
+ if (sb-> wp != NULL)
+ gui_drag_scrollbar(sb, -block[6] / gui.char_height, FALSE);
+ else
+ gui_drag_scrollbar(sb, block[5] / gui.char_width, FALSE);
+ }
+ }
+ }
+}
+
+ void
+ro_menu_selection(block)
+ int *block;
+{
+ int *item = wimp_menu + 7;
+ vimmenu_T *menu;
+ /* wimp_menu points to a wimp menu structure */
+
+ for (;;)
+ {
+ while (block[0]--)
+ item += 6;
+ if (block[1] == -1)
+ break;
+ item = ((int *) item[1]) + 7;
+ block++;
+ }
+ /* item points to the wimp menu item structure chosen */
+ menu = (vimmenu_T *) item[5];
+
+ swi(Wimp_GetPointerInfo, 0, block);
+ if (block[2] == 1)
+ /* Adjust used - keep menu open */
+ swi(Wimp_CreateMenu, 0, wimp_menu);
+
+ if (menu-> cb)
+ menu-> cb(menu);
+}
+
+ void
+ro_open_parent()
+{
+ int head;
+ char_u *i = curbuf-> b_ffname;
+ char_u buffer[256];
+
+ head = 0;
+ for (; *i; i++)
+ {
+ if (*i == '.')
+ head = i - curbuf-> b_ffname;
+ }
+
+ /* Append head chars to buffer */
+ if (head < 240 && curbuf-> b_ffname && head)
+ {
+ strcpy(buffer, "%filer_opendir ");
+ strncpy(buffer + 15, curbuf-> b_ffname, head);
+ buffer[15 + head] = '\0';
+ swi(OS_CLI, buffer);
+ }
+}
+
+ void
+process_event(event, block)
+ int event;
+ int *block;
+{
+ switch (event)
+ {
+ case 0: /* Nothing - update drag state. */
+ if (ro_dragging)
+ ro_continue_drag(block);
+ break;
+ case 1: /* Redraw window. */
+ redraw_window(block);
+ break;
+ case 2: /* Open window. */
+ ro_open_window(block);
+ break;
+ case 3: /* Close window. */
+ swi(Wimp_GetPointerInfo, 0, block + 1);
+ if (block[3] == 1)
+ ro_open_parent();
+ else
+ if (ro_ok_to_quit())
+ ro_quit();
+ break;
+ case 6: /* Mouse click. */
+ ro_mouse(block);
+ break;
+ case 7: /* Finished drag. */
+ ro_drag_finished(block);
+ break;
+ case 8: /* Key pressed. */
+ ro_insert_key((char_u *) &block[6]);
+ break;
+ case 9:
+ ro_menu_selection(block);
+ break;
+ case 10: /* Scroll request. */
+ ro_scroll(block);
+ break;
+ case 11: /* Lose caret. */
+ if (block[0] == gui.window_handle)
+ gui_focus_change(FALSE);
+ break;
+ case 12: /* Gain caret. */
+ if (block[0] == gui.window_handle)
+ gui_focus_change(TRUE);
+ break;
+ case 17: /* User message. */
+ case 18: /* User message recorded. */
+ ro_message(block);
+ break;
+ }
+}
+
+/*
+ * GUI input routine called by gui_wait_for_chars(). Waits for a character
+ * from the keyboard.
+ * wtime == -1 Wait forever.
+ * wtime == 0 This should never happen.
+ * wtime > 0 Wait wtime milliseconds for a character.
+ * Returns OK if a character was found to be available within the given time,
+ * or FAIL otherwise.
+ */
+ int
+gui_mch_wait_for_chars(long wtime)
+{
+ int block[64];
+ int reason;
+ int start_time = -1;
+ int ctime = wtime / 10; /* delay in cs */
+
+ if (wtime != -1)
+ {
+ swi(OS_ReadMonotonicTime);
+ start_time = r0;
+ }
+
+ for (;;)
+ {
+ if (ro_dragging)
+ reason = wimp_poll(0, block); /* Always return immediately */
+ else if (wtime == -1)
+ reason = wimp_poll(1, block);
+ else
+ reason = wimp_pollidle(0, block, start_time + ctime);
+
+ process_event(reason, block);
+
+ if (input_available() || ro_return_early)
+ {
+ ro_return_early = FALSE;
+ return OK; /* There is something to process (key / menu event) */
+ }
+
+ if (wtime != -1)
+ {
+ swi(OS_ReadMonotonicTime);
+ if (r0 - start_time > ctime)
+ return FAIL; /* We've been waiting too long - return failure */
+ }
+ }
+}
+
+/* Flush any output to the screen */
+ void
+gui_mch_flush(void)
+{
+}
+
+/*
+ * Clear a rectangular region of the screen from text pos(row1, col1) to
+ * (row2, col2) inclusive.
+ */
+ void
+gui_mch_clear_block(int row1, int col1, int row2, int col2)
+{
+ swi(ColourTrans_ReturnGCOL, gui.back_pixel << 8, 0, 0, 1<<7, 0);
+ plot_rectangle(96 + 5, r0,
+ FILL_X(col1), -FILL_Y(row2 + 1),
+ FILL_X(col2 + 1), -FILL_Y(row1));
+}
+
+ void
+gui_mch_clear_all(void)
+{
+ if (redraw_block)
+ {
+ swi(ColourTrans_SetGCOL, gui.back_pixel << 8, 0, 0, 1<<7, 0);
+ swi(OS_WriteI + 16);
+ }
+ else
+ {
+ int block[44];
+ block[0] = gui.window_handle;
+ block[1] = 0;
+ block[2] = -gui.num_rows * gui.char_height;
+ block[3] = gui.num_cols * gui.char_width;
+ block[4] = 0;
+ swi(Wimp_UpdateWindow, 0, block);
+ while (r0)
+ {
+ swi(ColourTrans_SetGCOL, gui.back_pixel << 8, 0, 0, 1<<7, 0);
+ swi(OS_WriteI + 16);
+ swi(Wimp_GetRectangle, 0, block);
+ }
+ }
+}
+
+/*
+ * Delete the given number of lines from the given row, scrolling up any
+ * text further down within the scroll region.
+ */
+ void
+gui_mch_delete_lines(int row, int num_lines)
+{
+ int top_from = -row - num_lines;
+ int bot_from = -gui.scroll_region_bot - 1;
+ int bot_to = bot_from + num_lines;
+
+ swi(ColourTrans_SetGCOL, gui.back_pixel << 8, 0, 0, 0x80, 0);
+
+ /* Changed without checking! */
+ swi(Wimp_BlockCopy, gui.window_handle,
+ gui.scroll_region_left * gui.char_width,
+ bot_from * gui.char_height,
+ (gui.scroll_region_right - gui.scroll_region_left
+ + 1) * gui.char_width,
+ top_from * gui.char_height,
+
+ gui.scroll_region_left * gui.char_width,
+ bot_to * gui.char_height);
+
+ gui_clear_block(gui.scroll_region_bot - num_lines + 1,
+ gui.scroll_region_left,
+ gui.scroll_region_bot, gui.scroll_region_right);
+}
+
+/*
+ * Insert the given number of lines before the given row, scrolling down any
+ * following text within the scroll region.
+ */
+ void
+gui_mch_insert_lines(int row, int num_lines)
+{
+ int top_from = -row;
+ int bot_to = -gui.scroll_region_bot - 1;
+ int bot_from = bot_to + num_lines;
+
+ swi(ColourTrans_SetGCOL, gui.back_pixel << 8, 0, 0, 0x80, 0);
+
+ swi(Wimp_BlockCopy, gui.window_handle,
+ gui.scroll_region_left * gui.char_width,
+ bot_from * gui.char_height,
+ (gui.scroll_region_right - gui.scroll_region_left
+ + 1) * gui.char_width,
+ top_from * gui.char_height,
+
+ gui.scroll_region_left * gui.char_width,
+ bot_to * gui.char_height);
+
+ gui_clear_block(row, gui.scroll_region_left,
+ row + num_lines - 1, gui.scroll_region_right);
+}
+
+/* Put selection in clipboard buffer.
+ * Should we become the new owner?
+ */
+ void
+clip_mch_request_selection(VimClipboard *cbd)
+{
+ int block[64]; /* Will be used in Wimp_Poll. */
+ int reason;
+ char_u *buffer;
+ long_u length;
+
+ block[0] = 48; /* Size of block. */
+ block[3] = 0; /* Orinial message. */
+ block[4] = 0x10; /* Data request. */
+ block[5] = gui.window_handle;
+ block[6] = RO_LOAD_CLIPBOARD; /* Internal handle. */
+ block[7] = block[8] = 0; /* (x,y) not used. */
+ block[9] = 4;
+ block[10] = 0xfff; /* We want text files if possible, I think. */
+ block[11] = -1; /* End of list. */
+ swi(Wimp_SendMessage, 17, block, 0); /* Broadcast request. */
+
+ /* OK, we've sent the request. Poll until we get a null poll (failure) or
+ * we load the clipboard.
+ * If we receive a DataSave event with icon handle = -2 then put it on the
+ * clipboard. RISC OS should ensure that key events will not be delivered
+ * until the clipboard operation completes (unless the owner starts idling
+ * - we can't wait forever!).
+ */
+ for (;;)
+ {
+ reason = wimp_poll(0, block);
+ if (reason == 0)
+ return; /* Failed to get clipboard. */
+ if ((reason == 17 || reason == 18) &&
+ block[4] == 1 && block[6] == RO_LOAD_CLIPBOARD)
+ break; /* Got it - stop waiting. */
+ process_event(reason, block);
+ if (ro_return_early)
+ return;
+ }
+ /* Tell owner to save data in <Wimp$Scrap>. */
+ block[0] = 60;
+ block[3] = block[2]; /* Copy myref -> yourref */
+ block[4] = 2; /* DataSaveAck. */
+ block[9] = -1; /* Data is unsafe. */
+ strcpy( ((char_u *) block) + 44, "<Wimp$Scrap>");
+ swi(Wimp_SendMessage, 17, block, block[1]);
+
+ /* Wait again for reply. */
+ for (;;)
+ {
+ reason = wimp_poll(0, block);
+ if (reason == 0)
+ return; /* Other program has given up! */
+ if ((reason == 17 || reason == 18) && block[4] == 3 && block[6] == RO_LOAD_CLIPBOARD)
+ break; /* Clipboard data saved to <Wimp$Scrap> */
+ process_event(reason, block);
+ if (ro_return_early)
+ return;
+ }
+
+ /* <Wimp$Scrap> contains clipboard - load it. */
+ if (xswi(OS_File, 17, "<Wimp$Scrap>") & v_flag)
+ return; /* Error! */
+ if (r0 != 1 && r0 != 3)
+ return;
+ length = r4;
+
+ buffer = lalloc(length, TRUE); /* Claim memory (and report errors). */
+ if (buffer == NULL)
+ return;
+
+ if (xswi(OS_File, 16, "<Wimp$Scrap>", buffer, 0) & v_flag)
+ return;
+
+ clip_yank_selection(MCHAR, buffer, length, cbd);
+
+ vim_free(buffer);
+
+ swi(OS_FSControl, 27, "<Wimp$Scrap>", 0, 0); /* Delete temp file. */
+
+ block[4] = 4; /* Send DataLoadAck. */
+ block[3] = block[2]; /* Copy myref -> yourref. */
+ swi(Wimp_SendMessage, 17, block, block[1]);
+}
+
+/* Not sure what this means under RISC OS. */
+ void
+clip_mch_lose_selection(VimClipboard *cbd)
+{
+}
+
+/* Tell everyone that we now own the clipboard.
+ * Return OK if our claim is accepted (always, under RISC OS)
+ */
+ int
+clip_mch_own_selection(VimClipboard *cbd)
+{
+ int block[6];
+ block[0] = 24; /* Length of block. */
+ block[3] = 0; /* Original message. */
+ block[4] = 0xf; /* ClaimEntity. */
+ block[5] = 0x4; /* Claim clipboard only. */
+ swi(Wimp_SendMessage, 17, block, 0);
+ return OK;
+}
+
+/*
+ * Send the current selection to the clipboard. Do nothing for X because we
+ * will fill in the selection only when requested by another app. Sounds good
+ * for RISC OS too.
+ */
+ void
+clip_mch_set_selection(VimClipboard *cbd)
+{
+ clip_get_selection(cbd);
+}
+
+/*
+ * Make a menu either grey or not grey.
+ */
+ void
+gui_mch_menu_grey(vimmenu_T *menu, int grey)
+{
+ menu-> greyed_out = grey;
+}
+
+/*
+ * Make menu item hidden or not hidden
+ */
+ void
+gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
+{
+ menu-> hidden = hidden;
+}
+
+/*
+ * This is called after setting all the menus to grey/hidden or not.
+ */
+ void
+gui_mch_draw_menubar(void)
+{
+ swi(Wimp_CreateMenu, 0, -1);
+ if (wimp_menu != (int *) -1)
+ {
+ ro_remove_menu(wimp_menu);
+ wimp_menu = (int *) -1;
+ }
+}
+
+/* Add or remove a scrollbar. Note that this is only called when
+ * the scrollbar state is changing.
+ * The scroll bar window has already been created.
+ * We can't do anything except remove the scroll bar
+ * until we know what size to use.
+ */
+ void
+gui_mch_enable_scrollbar(sb, flag)
+ scrollbar_T *sb;
+ int flag;
+{
+ if (!flag)
+ swi(Wimp_CloseWindow, 0, & (sb->id) );
+ return;
+}
+
+ void
+gui_mch_set_blinking(long waittime, long on, long off)
+{
+}
+
+/*
+ * Stop the cursor blinking. Show the cursor if it wasn't shown.
+ */
+ void
+gui_mch_stop_blink(void)
+{
+}
+
+/*
+ * Start the cursor blinking. If it was already blinking, this restarts the
+ * waiting time and shows the cursor.
+ */
+ void
+gui_mch_start_blink(void)
+{
+}
+
+/*
+ * Return the RGB value of a pixel as a long.
+ */
+ long_u
+gui_mch_get_rgb(guicolor_T pixel)
+{
+ return (long_u)pixel;
+}
+
+ void
+gui_mch_set_text_area_pos(int x, int y, int w, int h)
+{
+}
+
+ void
+gui_mch_enable_menu(int flag)
+{
+}
+
+ void
+gui_mch_set_menu_pos(int x, int y, int w, int h)
+{
+}
+
+ void
+gui_mch_add_menu(vimmenu_T *menu, int idx)
+{
+}
+
+ void
+gui_mch_add_menu_item(vimmenu_T *menu, int idx)
+{
+}
+
+ void
+gui_mch_new_menu_colors(void)
+{
+}
+
+ void
+gui_mch_destroy_menu(vimmenu_T *menu)
+{
+}
+
+/* Size of buffer has changed.
+ * Add one to max since gui.c substracts one more than it should!
+ */
+ void
+gui_mch_set_scrollbar_thumb(sb, val, size, max)
+ scrollbar_T *sb;
+ long val;
+ long size;
+ long max;
+{
+ int block[10], width, height;
+
+ width = (max + 1) * gui.char_width;
+ height = (max + 1 + W_STATUS_HEIGHT(sb->wp)) * gui.char_height;
+
+ block[0] = block[3] = 0;
+ block[1] = -height + (1 << y_eigen_factor);
+ block[2] = width;
+
+ swi(Wimp_SetExtent, sb -> id, block);
+
+ block[0] = sb -> id;
+ swi(Wimp_GetWindowState, 0, block);
+ block[5] = val * gui.char_width;
+ block[6] = -val * gui.char_height;
+ swi(Wimp_OpenWindow, 0, block, 0x4b534154,
+ gui.window_handle, /* Parent window handle. */
+ (CHILD_FIX_TO_RIGHT << CHILD_LEFT ) |
+ (CHILD_FIX_TO_RIGHT << CHILD_RIGHT ) |
+ (CHILD_FIX_TO_BOTTOM << CHILD_TOP ) |
+ (CHILD_FIX_TO_BOTTOM << CHILD_BOTTOM) |
+ (CHILD_SELF_SCROLL << CHILD_SCROLL_X) |
+ (CHILD_SELF_SCROLL << CHILD_SCROLL_Y)
+ );
+}
+
+/* Set the position of the scrollbar within the editor
+ * window. Note that, for vertical scrollbars, x and w
+ * are ignored. For horizontal bars y and h are ignored.
+ */
+ void
+gui_mch_set_scrollbar_pos(sb, x, y, w, h)
+ scrollbar_T *sb;
+ int x; /* Horizontal sb position */
+ int y; /* Top of scroll bar */
+ int w; /* Width */
+ int h; /* Height */
+{
+ int block[24];
+ int px1, py1; /* Parent window min coords */
+ int px2, py2; /* Parent window max coords */
+
+ /* Find where the parent window is. */
+ block[0] = gui.window_handle;
+ swi(Wimp_GetWindowState, 0, block);
+ px1 = block[1];
+ py1 = block[2];
+ px2 = block[3];
+ py2 = block[4];
+
+ block[0] = sb -> id;
+
+ /* Find out how big the scroll window is at the moment. */
+ swi(Wimp_GetWindowInfo, 0, ((char_u *)block) + 1);
+
+ if (block[13] < w || block[12] > -h)
+ {
+ /* Current window is too small! */
+ if (block[12] > -h)
+ block[12] = -h;
+ if (block[13] < w)
+ block[13] = w;
+ swi(Wimp_SetExtent, block[0], block + 11);
+ }
+
+ /* This works better on the nested_wimp. */
+ if (sb-> wp)
+ {
+ /* This is a vertical scrollbar. */
+ block[1] = block[3] = px2 - gui.scrollbar_width + (1 << x_eigen_factor);
+ block[2] = 1 + py2 - (y + h) + (1 << y_eigen_factor);
+ block[4] = 1 + py2 - y;
+ }
+ else
+ {
+ /* This is a horizontal scrollbar. */
+ block[2] = block[4] = py1 + gui.scrollbar_height;
+ block[1] = px1;
+ block[3] = px2 - gui.scrollbar_width;
+ }
+
+ block[5] = 0;
+ block[6] = 0;
+ block[7] = -1;
+
+ swi(Wimp_OpenWindow, 0, block, 0x4b534154,
+ gui.window_handle, /* Parent window handle. */
+ (CHILD_FIX_TO_RIGHT << CHILD_LEFT ) |
+ (CHILD_FIX_TO_RIGHT << CHILD_RIGHT ) |
+ (CHILD_FIX_TO_BOTTOM << CHILD_TOP ) |
+ (CHILD_FIX_TO_BOTTOM << CHILD_BOTTOM) |
+ (CHILD_SELF_SCROLL << CHILD_SCROLL_X) |
+ (CHILD_SELF_SCROLL << CHILD_SCROLL_Y)
+ );
+}
+
+/* Create a window with no workarea to place inside editor window.
+ * (what happens without the nested wimp?)
+ * Data for scrollbar is invalid.
+ */
+ void
+gui_mch_create_scrollbar(sb, orient)
+ scrollbar_T *sb;
+ int orient; /* orient is SBAR_HORIZ or SBAR_VERT */
+{
+ int bar[] =
+ {
+ 0, 0, /* Visible area : min X,Y */
+ 100, 100, /* max X,Y */
+ 0, 0, /* Scroll offsets */
+ -1, /* Window in front */
+ 0x80800150 | (orient == SBAR_HORIZ ? (1 << 30) : (1 << 28)),
+ 0xff070207, /* Colours */
+ 0x000c0103, /* More colours */
+ 0, -0x4000, /* Workarea extent */
+ 0x4000, 0, /* max X,Y */
+ 0x00000000, /* No title */
+ 0 << 12, /* No workarea button type */
+ 1, /* Wimp sprite area */
+ 0x00010001, /* Minimum width, height */
+ 0, 0, 0, /* Title data (none) */
+ 0 /* No icons */
+ };
+ swi(Wimp_CreateWindow, 0, bar);
+ sb -> id = r0;
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+ void
+gui_mch_destroy_scrollbar(scrollbar_T *sb)
+{
+ swi(Wimp_DeleteWindow, 0, & (sb->id));
+ sb -> id = -1;
+}
+#endif
+
+ void
+gui_mch_set_scrollbar_colors(scrollbar_T *sb)
+{
+ /* Always use default RO colour scheme. */
+}
+
+/*
+ * Get current x mouse coordinate in text window.
+ * Note: (0,0) is the bottom left corner, positive y is UP.
+ * Return -1 when unknown.
+ */
+ int
+gui_mch_get_mouse_x()
+{
+ int left;
+ int block[10];
+
+ block[0] = gui.window_handle;
+ swi(Wimp_GetWindowState, 0, block);
+ left = block[1];
+
+ swi(Wimp_GetPointerInfo, 0, block);
+ return block[0] - left;
+}
+
+/*
+ * Get current y mouse coordinate in text window.
+ * Return -1 when unknown.
+ */
+ int
+gui_mch_get_mouse_y()
+{
+ int top;
+ int block[10];
+
+ block[0] = gui.window_handle;
+ swi(Wimp_GetWindowState, 0, block);
+ top = block[4];
+
+ swi(Wimp_GetPointerInfo, 0, block);
+ return top - block[1];
+}
+
+/* MouseTo(x, y) */
+ void
+gui_mch_setmouse(x, y)
+ int x;
+ int y;
+{
+}
+
+ void
+gui_mch_toggle_tearoffs(enable)
+ int enable;
+{
+ /* no tearoff menus */
+}
+
+/* Redraw a window's title.
+ * For the nested wimp we use the new 'redraw-title-bar' reason code.
+ * For older wimps we mark the area of the screen where the title bar
+ * is as invalid.
+ */
+ void
+ro_redraw_title(window)
+ int window;
+{
+ if (nested_wimp)
+ {
+ swi(Wimp_ForceRedraw, window, 0x4b534154, 3);
+ }
+ else
+ {
+ int block[10];
+ int miny;
+
+ block[0] = window;
+ swi(Wimp_GetWindowState, 0, block);
+ miny = block[4];
+ swi(Wimp_GetWindowOutline, 0, block);
+ swi(Wimp_ForceRedraw, -1,
+ block[1], miny,
+ block[3], block[4]);
+ }
+}
+
+/* Turn a vimmenu_T structure into a wimp menu structure.
+ * -1 if resulting menu is empty.
+ * Only the children and dname items in the root menu are used.
+ */
+ int *
+ro_build_menu(menu)
+ vimmenu_T *menu;
+{
+ int *wimp_menu;
+ int width = 4;
+ int w;
+ int size = 28;
+ vimmenu_T *item;
+ int *wimp_item;
+
+ /* Find out how big the menu is so we can allocate memory for it */
+ for (item = menu-> children; item; item = item-> next)
+ {
+ if (item-> hidden == FALSE && !menu_is_separator(item->name))
+ size += 24;
+ }
+
+ if (size <= 28)
+ return (int *) -1; /* No children - shouldn't happen */
+
+ wimp_menu = (int *) alloc(size);
+
+ wimp_menu[0] = (int) menu-> dname;
+ wimp_menu[1] = -1;
+ wimp_menu[2] = 0;
+ wimp_menu[3] = 0x00070207;
+ wimp_menu[5] = 44;
+ wimp_menu[6] = 0;
+
+ wimp_item = wimp_menu + 7;
+
+ for (item = menu-> children; item; item = item-> next)
+ {
+ if (menu_is_separator(item-> name))
+ {
+ /* This menu entry is actually a separator. If it is not the first
+ * menu entry then mark the previous menu item as needing a dotted
+ * line after it.
+ */
+ if (wimp_item > wimp_menu + 7)
+ wimp_item[-6] |= 0x2;
+ }
+ else if (item-> hidden == FALSE)
+ {
+ wimp_item[0] = 0;
+ wimp_item[1] = item-> children ? (int) ro_build_menu(item) : -1;
+ wimp_item[2] = 0x07009131 | (item-> greyed_out << 22);
+ wimp_item[3] = (int) item-> dname;
+ wimp_item[4] = -1;
+ wimp_item[5] = (int) item; /* Stuff the menu address in this unused space */
+
+ w = strlen(item-> dname) + 1;
+ if (w > width)
+ width = w;
+ wimp_item += 6;
+ }
+ }
+
+ wimp_menu[4] = (width + 2) * 16;
+ wimp_menu[7] |= 0x100; /* Menu title is indirected */
+ wimp_item[-6] |= 0x080; /* Last entry in menu */
+ return wimp_menu;
+}
+
+ static void
+ro_remove_menu(menu)
+ int *menu;
+{
+ int *item = menu + 7;
+
+ if (menu == NULL || menu == (int *) -1)
+ return;
+
+ for (;;)
+ {
+ if (item[1] != -1)
+ ro_remove_menu((int *) item[1]); /* Remove sub-menu */
+ if (item[0] & 0x80)
+ break; /* This was the last entry */
+ item += 6;
+ }
+ vim_free(menu);
+}
+
+ void
+gui_mch_show_popupmenu(menu)
+ vimmenu_T *menu;
+{
+ int block[10];
+
+ /* Remove the existing menu, if any */
+ if (wimp_menu != (int *) -1)
+ {
+ swi(Wimp_CreateMenu, 0, -1);
+ ro_remove_menu(wimp_menu);
+ wimp_menu = (int *) -1;
+ }
+
+ wimp_menu = ro_build_menu(menu);
+ if (wimp_menu != (int *) -1)
+ {
+ swi(Wimp_GetPointerInfo, 0, block);
+ swi(Wimp_CreateMenu, 0, wimp_menu, block[0] - 64, block[1] + 64);
+ }
+}
+
+/* Run a command using the TaskWindow module.
+ * If SHELL_FILTER is set then output is not echoed to the screen,
+ * If it is not set, then \r is not sent to the output file.
+ */
+ int
+gui_mch_call_shell(cmd, options)
+ char_u *cmd;
+ int options; /* SHELL_FILTER if called by do_filter() */
+ /* SHELL_COOKED if term needs cooked mode */
+{
+ char_u task_cmd[256]; /* Contains *TaskWindow command. */
+ int block[64];
+ int reason;
+ char_u *out;
+ char_u c;
+ int old_msg_col;
+ char_u *out_redir;
+ int length;
+ FILE *out_file = NULL;
+
+ out_redir = strstr(cmd, " > ");
+ if (out_redir == NULL)
+ length = strlen(cmd); /* No redirection. */
+ else
+ {
+ length = out_redir - cmd;
+ out_file = fopen(out_redir + 3, "wb");
+ if (out_file == NULL)
+ msg_str("WARNING : Can't open file %s for writing\n",
+ out_redir + 3);
+ }
+
+ if (length > 180)
+ {
+ if (out_file)
+ fclose(out_file);
+ return FAIL; /* Command too long. */
+ }
+
+ strcpy(task_cmd, "TaskWindow \"");
+ strncpy(task_cmd + 12, cmd, length);
+ sprintf(task_cmd + 12 + length,
+ "\" -task &%08x -ctrl -quit -name \"Vim command\"",
+ task_handle);
+
+ if (options & SHELL_COOKED)
+ settmode(TMODE_COOK);
+
+ if (xswi(Wimp_StartTask, task_cmd) & v_flag)
+ {
+ /* Failed to even start a new task (out of memory?) */
+ settmode(TMODE_RAW);
+ if (out_file)
+ fclose(out_file);
+ return FAIL;
+ }
+
+ /* Wait for the child process to initialise. */
+ child_handle = 0;
+ while (!child_handle)
+ {
+ reason = wimp_poll(0, block);
+ if ((reason == 17 || reason == 18) && block[4] == 0x808c2)
+ child_handle = block[1];
+ else
+ process_event(reason, block);
+ }
+
+ /* Block until finished */
+ while (child_handle)
+ {
+ reason = wimp_poll(1, block);
+ if (reason == 3 || (reason == 8 && block[6] == 3))
+ {
+ /* Close window request or CTRL-C - kill child task. */
+ block[0] = 20;
+ block[3] = 0;
+ block[4] = 0x808c4; /* Morite */
+ swi(Wimp_SendMessage, 17, block, child_handle);
+ MSG_PUTS(_("\nSending message to terminate child process.\n"));
+ continue;
+ }
+ else if (reason == 8)
+ {
+ block[0] = 28;
+ block[3] = 0;
+ block[4] = 0x808c0; /* Input */
+ block[5] = 1;
+ /* Block[6] is OK as it is! */
+ swi(Wimp_SendMessage, 17, block, child_handle);
+ continue;
+ }
+ else if (reason == 17 || reason == 18)
+ {
+ if (block[4] == 0x808c1)
+ {
+ /* Ack message. */
+ block[3] = block[2];
+ swi(Wimp_SendMessage, 19, block, block[1]);
+ out = (char_u *)block + 24;
+ old_msg_col = msg_col;
+ while (block[5]--)
+ {
+ c = *out++;
+ if (out_file && (c != '\r' || (options & SHELL_FILTER)))
+ fputc(c, out_file);
+ if ((options & SHELL_FILTER) == 0)
+ {
+ if (c == 127)
+ msg_puts("\b \b");
+ else if (c > 31)
+ msg_putchar(c);
+ else if (c == 10)
+ {
+ lines_left = 8; /* Don't do More prompt! */
+ msg_putchar(10);
+ }
+ }
+ }
+ /* Flush output to the screen. */
+ windgoto(msg_row, msg_col);
+ out_flush();
+ continue;
+ }
+ }
+ process_event(reason, block);
+ }
+ msg_putchar('\n');
+ settmode(TMODE_RAW);
+ if (out_file)
+ fclose(out_file);
+ return OK;
+}
+
+/* Like strsave(), but stops at any control char */
+ char_u *
+wimp_strsave(str)
+ char *str;
+{
+ int strlen = 0;
+ char_u *retval;
+ while (str[strlen] > 31)
+ strlen++;
+ retval = alloc(strlen + 1);
+ if (retval)
+ {
+ memcpy(retval, str, strlen);
+ retval[strlen] = '\0';
+ }
+ return retval;
+}
+
+/* If we are saving then pop up a standard RISC OS save box.
+ * Otherwise, open a directory viewer on the given directory (and return NULL)
+ * The string we return will be freed later.
+ */
+ char_u *
+gui_mch_browse(saving, title, dflt, ext, initdir, filter)
+ int saving; /* write action */
+ char_u *title; /* title for the window */
+ char_u *dflt; /* default file name */
+ char_u *ext; /* extension added */
+ char_u *initdir; /* initial directory, NULL for current dir */
+ char_u *filter; /* file name filter */
+{
+ char command[256];
+ int length;
+
+ if (saving)
+ {
+ int block[64];
+ int reason;
+ int done_save = FALSE;
+ char_u *retval = NULL;
+ char_u *sprname;
+ char_u *fname;
+ int dragging_icon = FALSE;
+ int filetype;
+
+ if (!dflt)
+ dflt = "TextFile";
+
+ block[0] = save_window;
+ block[1] = 0;
+ swi(Wimp_GetIconState, 0, block);
+ sprname = ((char_u *) block[7]);
+ block[1] = 1;
+ swi(Wimp_GetIconState, 0, block);
+ fname = ((char *) block[7]);
+ strncpy(fname, dflt, 255);
+
+ if (xswi(OS_FSControl, 31, curbuf->b_p_oft) & v_flag)
+ {
+ filetype = 0xfff;
+ strcpy(sprname + 5, "xxx");
+ }
+ else
+ {
+ filetype = r2;
+ sprintf(sprname + 5, "%03x", filetype);
+ }
+
+ /* Open the save box */
+
+ swi(Wimp_GetPointerInfo, 0, block);
+ swi(Wimp_CreateMenu, 0, save_window, block[0] - 64, block[1] + 64);
+ swi(Wimp_SetCaretPosition, save_window, 1, 0, 0, -1, -1);
+
+ while (!done_save)
+ {
+ reason = wimp_poll(1, block);
+ switch (reason)
+ {
+ case 1:
+ redraw_window(block);
+ break;
+ case 2:
+ if (block[0] == save_window)
+ swi(Wimp_OpenWindow, 0, block);
+ else
+ ro_open_window(block);
+ break;
+ case 3:
+ done_save = TRUE;
+ break;
+ case 6:
+ if (block[3] != save_window)
+ done_save = TRUE;
+ else
+ {
+ int drag_box[4];
+ int min_x, max_y;
+
+ switch (block[4])
+ {
+ case 0: /* Start drag */
+ block[0] = save_window;
+ swi(Wimp_GetWindowState, 0, block);
+ min_x = block[1];
+ max_y = block[4];
+ block[1] = 0;
+ swi(Wimp_GetIconState, 0, block);
+ drag_box[0] = block[2] + min_x;
+ drag_box[1] = block[3] + max_y;
+ drag_box[2] = block[4] + min_x;
+ drag_box[3] = block[5] + max_y;
+
+ swi(DragASprite_Start,
+ 0x45,
+ 1,
+ sprname,
+ drag_box);
+ dragging_icon = TRUE;
+ break;
+ case 2: /* OK */
+ retval = wimp_strsave(fname);
+ done_save = TRUE;
+ break;
+ case 3: /* Cancel */
+ done_save = TRUE;
+ break;
+ }
+ }
+ break;
+ case 7:
+ if (dragging_icon)
+ {
+ int len = 0;
+
+ dragging_icon = FALSE;
+ swi(Wimp_GetPointerInfo, 0, block);
+ block[5] = block[3];
+ block[6] = block[4];
+ block[7] = block[0];
+ block[8] = block[1];
+ block[9] = 0; /* Don't know the size */
+ block[10] = filetype;
+
+ while (fname[len] > 31)
+ {
+ if (fname[len] == '.')
+ {
+ fname += len + 1;
+ len = 0;
+ }
+ else
+ len++;
+ }
+ if (len > 211)
+ len = 211;
+
+ memcpy(((char_u *) block) + 44, fname, len);
+ ((char_u *)block)[44 + len] = '\0';
+
+ block[0] = (len + 48) & 0xfc;
+ block[3] = 0;
+ block[4] = 1; /* DataSave */
+
+ swi(Wimp_SendMessage, 17, block, block[5], block[6]);
+ }
+ else
+ ro_drag_finished(block);
+ break;
+ case 8:
+ if (block[6] == 13)
+ {
+ retval = wimp_strsave(fname);
+ done_save = TRUE;
+ }
+ else if (block[6] == 0x1b)
+ done_save = TRUE;
+ else
+ swi(Wimp_ProcessKey, block[6]);
+ break;
+ case 17:
+ case 18:
+ if (block[4] == 2 && block[9] != -1)
+ {
+ /* DataSaveAck from dragging icon. */
+ retval = wimp_strsave(((char_u *) block) + 44);
+ done_save = TRUE;
+ }
+ else if (block[4] == 0x400c9)
+ {
+ /* MenusDeleted */
+ done_save = TRUE;
+ }
+ else
+ ro_message(block);
+ break;
+ }
+ }
+ block[0] = save_window;
+ swi(Wimp_CloseWindow, 0, block);
+ swi(Wimp_GetCaretPosition, 0, block);
+ if (block[0] == -1)
+ swi(Wimp_SetCaretPosition, gui.window_handle, -1, 0, 0, -1, -1);
+
+ return retval;
+ }
+ else if (initdir)
+ {
+ /* Open a directory viewer */
+ length = strlen(initdir);
+
+ if (length > 240)
+ return NULL; /* Path too long! */
+
+ length = sprintf(command, "Filer_OpenDir %s", initdir);
+ while (command[length - 1] == '.')
+ length--;
+ command[length] = '\0';
+ swi(OS_CLI, command);
+ }
+ return NULL;
+}
+
diff --git a/src/gui_riscos.h b/src/gui_riscos.h
new file mode 100644
index 000000000..fe22e6a81
--- /dev/null
+++ b/src/gui_riscos.h
@@ -0,0 +1,32 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+#define FEAT_BROWSE
+
+#define TASK 0x4b534154
+
+/* Nested wimp flags: */
+#define CHILD_FIX_TO_WORKAREA 0
+#define CHILD_FIX_TO_LEFT 1
+#define CHILD_FIX_TO_BOTTOM 1
+#define CHILD_FIX_TO_RIGHT 2
+#define CHILD_FIX_TO_TOP 2
+
+#define CHILD_SELF_SCROLL 0
+#define CHILD_PARENT_SCROLL 1
+
+#define CHILD_LEFT 16
+#define CHILD_BOTTOM 18
+#define CHILD_RIGHT 20
+#define CHILD_TOP 22
+#define CHILD_SCROLL_X 24
+#define CHILD_SCROLL_Y 26
+
+int wimp_poll(int mask, int *block);
+int wimp_poll_idle(int mask, int *block, int end_time);
+void ro_open_main(int *block);
diff --git a/src/gui_w16.c b/src/gui_w16.c
new file mode 100644
index 000000000..e6aa85057
--- /dev/null
+++ b/src/gui_w16.c
@@ -0,0 +1,1524 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI support by Robert Webb
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * gui_w16.c
+ *
+ * GUI support for Microsoft Windows 3.1x
+ *
+ * George V. Reilly <george@reilly.org> wrote the original Win32 GUI.
+ * Robert Webb reworked it to use the existing GUI stuff and added menu,
+ * scrollbars, etc.
+ *
+ * Vince Negri then butchered the code to get it compiling for
+ * 16-bit windows.
+ *
+ */
+
+/*
+ * Include the common stuff for MS-Windows GUI.
+ */
+#include "gui_w48.c"
+
+#include "guiw16rc.h"
+
+/* Undocumented Windows Message - not even defined in some SDK headers */
+#define WM_EXITSIZEMOVE 0x0232
+
+
+#ifdef FEAT_TOOLBAR
+# define CMD_TB_BASE (99)
+# include <vimtbar.h>
+#endif
+
+#ifdef PROTO
+# define WINAPI
+#endif
+
+#define HANDLE_WM_DROPFILES(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (HDROP)(wParam)), 0L)
+
+
+/* Local variables: */
+
+#ifdef FEAT_MENU
+static UINT s_menu_id = 100;
+#endif
+
+
+#define VIM_NAME "vim"
+#define VIM_CLASS "Vim"
+
+#define DLG_ALLOC_SIZE 16 * 1024
+
+/*
+ * stuff for dialogs, menus, tearoffs etc.
+ */
+#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
+static BOOL CALLBACK dialog_callback(HWND, UINT, WPARAM, LPARAM);
+
+static LPWORD
+add_dialog_element(
+ LPWORD p,
+ DWORD lStyle,
+ WORD x,
+ WORD y,
+ WORD w,
+ WORD h,
+ WORD Id,
+ BYTE clss,
+ const char *caption);
+
+static int dialog_default_button = -1;
+#endif
+
+static void get_dialog_font_metrics(void);
+
+#ifdef FEAT_TOOLBAR
+static void initialise_toolbar(void);
+#endif
+
+
+#ifdef FEAT_MENU
+/*
+ * Figure out how high the menu bar is at the moment.
+ */
+ static int
+gui_mswin_get_menu_height(
+ int fix_window) /* If TRUE, resize window if menu height changed */
+{
+ static int old_menu_height = -1;
+
+ int num;
+ int menu_height;
+
+ if (gui.menu_is_active)
+ num = GetMenuItemCount(s_menuBar);
+ else
+ num = 0;
+
+ if (num == 0)
+ menu_height = 0;
+ else if (gui.starting)
+ menu_height = GetSystemMetrics(SM_CYMENU);
+ else
+ {
+ RECT r1, r2;
+ int frameht = GetSystemMetrics(SM_CYFRAME);
+ int capht = GetSystemMetrics(SM_CYCAPTION);
+
+ /* get window rect of s_hwnd
+ * get client rect of s_hwnd
+ * get cap height
+ * subtract from window rect, the sum of client height,
+ * (if not maximized)frame thickness, and caption height.
+ */
+ GetWindowRect(s_hwnd, &r1);
+ GetClientRect(s_hwnd, &r2);
+ menu_height = r1.bottom - r1.top - (r2.bottom-r2.top +
+ 2 * frameht * (!IsZoomed(s_hwnd)) + capht);
+ }
+
+ if (fix_window && menu_height != old_menu_height)
+ {
+ old_menu_height = menu_height;
+ gui_set_shellsize(FALSE, FALSE);
+ }
+
+ return menu_height;
+}
+#endif /*FEAT_MENU*/
+
+
+/*
+ * Even though we have _DuringSizing() which makes the rubber band a valid
+ * size, we need this for when the user maximises the window.
+ * TODO: Doesn't seem to adjust the width though for some reason.
+ */
+ static BOOL
+_OnWindowPosChanging(
+ HWND hwnd,
+ LPWINDOWPOS lpwpos)
+{
+
+ if (!IsIconic(hwnd) && !(lpwpos->flags & SWP_NOSIZE))
+ {
+ gui_mswin_get_valid_dimensions(lpwpos->cx, lpwpos->cy,
+ &lpwpos->cx, &lpwpos->cy);
+ }
+ return 0;
+}
+
+
+
+
+
+ static LRESULT CALLBACK
+_WndProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ /*
+ TRACE("WndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n",
+ hwnd, uMsg, wParam, lParam);
+ */
+
+ HandleMouseHide(uMsg, lParam);
+
+ s_uMsg = uMsg;
+ s_wParam = wParam;
+ s_lParam = lParam;
+
+ switch (uMsg)
+ {
+ HANDLE_MSG(hwnd, WM_DEADCHAR, _OnDeadChar);
+ HANDLE_MSG(hwnd, WM_SYSDEADCHAR, _OnDeadChar);
+ /* HANDLE_MSG(hwnd, WM_ACTIVATE, _OnActivate); */
+ HANDLE_MSG(hwnd, WM_CHAR, _OnChar);
+ HANDLE_MSG(hwnd, WM_CLOSE, _OnClose);
+ /* HANDLE_MSG(hwnd, WM_COMMAND, _OnCommand); */
+ HANDLE_MSG(hwnd, WM_DESTROY, _OnDestroy);
+ HANDLE_MSG(hwnd, WM_DROPFILES, _OnDropFiles);
+ HANDLE_MSG(hwnd, WM_HSCROLL, _OnScroll);
+ HANDLE_MSG(hwnd, WM_KILLFOCUS, _OnKillFocus);
+#ifdef FEAT_MENU
+ HANDLE_MSG(hwnd, WM_COMMAND, _OnMenu);
+#endif
+ /* HANDLE_MSG(hwnd, WM_MOVE, _OnMove); */
+ /* HANDLE_MSG(hwnd, WM_NCACTIVATE, _OnNCActivate); */
+ HANDLE_MSG(hwnd, WM_SETFOCUS, _OnSetFocus);
+ HANDLE_MSG(hwnd, WM_SIZE, _OnSize);
+ /* HANDLE_MSG(hwnd, WM_SYSCOMMAND, _OnSysCommand); */
+ /* HANDLE_MSG(hwnd, WM_SYSKEYDOWN, _OnAltKey); */
+ HANDLE_MSG(hwnd, WM_VSCROLL, _OnScroll);
+ HANDLE_MSG(hwnd, WM_WINDOWPOSCHANGING, _OnWindowPosChanging);
+ HANDLE_MSG(hwnd, WM_ACTIVATEAPP, _OnActivateApp);
+
+ case WM_QUERYENDSESSION: /* System wants to go down. */
+ gui_shell_closed(); /* Will exit when no changed buffers. */
+ return FALSE; /* Do NOT allow system to go down. */
+
+ case WM_ENDSESSION:
+ if (wParam) /* system only really goes down when wParam is TRUE */
+ _OnEndSession();
+ break;
+
+ case WM_SYSCHAR:
+ /*
+ * if 'winaltkeys' is "no", or it's "menu" and it's not a menu
+ * shortcut key, handle like a typed ALT key, otherwise call Windows
+ * ALT key handling.
+ */
+#ifdef FEAT_MENU
+ if ( !gui.menu_is_active
+ || p_wak[0] == 'n'
+ || (p_wak[0] == 'm' && !gui_is_menu_shortcut((int)wParam))
+ )
+#endif
+ return HANDLE_WM_SYSCHAR((hwnd), (wParam), (lParam), (_OnSysChar));
+#ifdef FEAT_MENU
+ else
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+#endif
+
+ case WM_SYSKEYUP:
+#ifdef FEAT_MENU
+ /* Only when menu is active, ALT key is used for that. */
+ if (gui.menu_is_active)
+ {
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+ else
+#endif
+ return 0;
+
+#if defined(MENUHINTS) && defined(FEAT_MENU)
+ case WM_MENUSELECT:
+ if (((UINT) LOWORD(lParam)
+ & (0xffff ^ (MF_MOUSESELECT + MF_BITMAP + MF_POPUP)))
+ == MF_HILITE
+ && (State & CMDLINE) == 0)
+ {
+ UINT idButton;
+ int idx;
+ vimmenu_T *pMenu;
+
+ idButton = (UINT)LOWORD(wParam);
+ pMenu = gui_mswin_find_menu(root_menu, idButton);
+ if (pMenu)
+ {
+ idx = MENU_INDEX_TIP;
+ msg_clr_cmdline();
+ if (pMenu->strings[idx])
+ msg(pMenu->strings[idx]);
+ else
+ msg("");
+ setcursor();
+ out_flush();
+ }
+ }
+ break;
+#endif
+ case WM_NCHITTEST:
+ {
+ LRESULT result;
+ int x, y;
+ int xPos = GET_X_LPARAM(lParam);
+
+ result = MyWindowProc(hwnd, uMsg, wParam, lParam);
+ if (result == HTCLIENT)
+ {
+ gui_mch_get_winpos(&x, &y);
+ xPos -= x;
+
+ if (xPos < 48) /*<VN> TODO should use system metric?*/
+ return HTBOTTOMLEFT;
+ else
+ return HTBOTTOMRIGHT;
+ }
+ else
+ return result;
+ }
+ /* break; */
+ default:
+#ifdef MSWIN_FIND_REPLACE
+ if (uMsg == s_findrep_msg && s_findrep_msg != 0)
+ {
+ _OnFindRepl();
+ }
+#endif
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ return 1;
+}
+
+
+
+/*
+ * End of call-back routines
+ */
+
+
+/*
+ * Parse the GUI related command-line arguments. Any arguments used are
+ * deleted from argv, and *argc is decremented accordingly. This is called
+ * when vim is started, whether or not the GUI has been started.
+ */
+ void
+gui_mch_prepare(int *argc, char **argv)
+{
+ /* No special args for win16 GUI at the moment. */
+
+}
+
+/*
+ * Initialise the GUI. Create all the windows, set up all the call-backs
+ * etc.
+ */
+ int
+gui_mch_init(void)
+{
+ const char szVimWndClass[] = VIM_CLASS;
+ const char szTextAreaClass[] = "VimTextArea";
+ WNDCLASS wndclass;
+
+#ifdef WIN16_3DLOOK
+ Ctl3dRegister(s_hinst);
+ Ctl3dAutoSubclass(s_hinst);
+#endif
+
+ /* Display any pending error messages */
+ display_errors();
+
+ gui.scrollbar_width = GetSystemMetrics(SM_CXVSCROLL);
+ gui.scrollbar_height = GetSystemMetrics(SM_CYHSCROLL);
+#ifdef FEAT_MENU
+ gui.menu_height = 0; /* Windows takes care of this */
+#endif
+ gui.border_width = 0;
+
+ gui.currBgColor = INVALCOLOR;
+
+ s_brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
+
+ if (GetClassInfo(s_hinst, szVimWndClass, &wndclass) == 0) {
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = _WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = s_hinst;
+ wndclass.hIcon = LoadIcon(wndclass.hInstance, MAKEINTRESOURCE(IDR_VIM));
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = s_brush;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = szVimWndClass;
+
+ if ((
+#ifdef GLOBAL_IME
+ atom =
+#endif
+ RegisterClass(&wndclass)) == 0)
+ return FAIL;
+ }
+
+ s_hwnd = CreateWindow(
+ szVimWndClass, "Vim MSWindows GUI",
+ WS_OVERLAPPEDWINDOW,
+ gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x,
+ gui_win_y == -1 ? CW_USEDEFAULT : gui_win_y,
+ 100, /* Any value will do */
+ 100, /* Any value will do */
+ NULL, NULL,
+ s_hinst, NULL);
+
+ if (s_hwnd == NULL)
+ return FAIL;
+
+#ifdef GLOBAL_IME
+ global_ime_init(atom, s_hwnd);
+#endif
+
+ /* Create the text area window */
+ if (GetClassInfo(s_hinst, szTextAreaClass, &wndclass) == 0) {
+ wndclass.style = CS_OWNDC;
+ wndclass.lpfnWndProc = _TextAreaWndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = s_hinst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = NULL;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = szTextAreaClass;
+
+ if (RegisterClass(&wndclass) == 0)
+ return FAIL;
+ }
+ s_textArea = CreateWindow(
+ szTextAreaClass, "Vim text area",
+ WS_CHILD | WS_VISIBLE, 0, 0,
+ 100, /* Any value will do for now */
+ 100, /* Any value will do for now */
+ s_hwnd, NULL,
+ s_hinst, NULL);
+
+ if (s_textArea == NULL)
+ return FAIL;
+
+#ifdef FEAT_MENU
+ s_menuBar = CreateMenu();
+#endif
+ s_hdc = GetDC(s_textArea);
+
+#ifdef MSWIN16_FASTTEXT
+ SetBkMode(s_hdc, OPAQUE);
+#endif
+
+ DragAcceptFiles(s_hwnd, TRUE);
+
+ /* Do we need to bother with this? */
+ /* m_fMouseAvail = GetSystemMetrics(SM_MOUSEPRESENT); */
+
+ /* Get background/foreground colors from the system */
+ gui_mch_def_colors();
+
+ /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
+ * file) */
+ set_normal_colors();
+
+ /*
+ * Check that none of the colors are the same as the background color.
+ * Then store the current values as the defaults.
+ */
+ gui_check_colors();
+ gui.def_norm_pixel = gui.norm_pixel;
+ gui.def_back_pixel = gui.back_pixel;
+
+ /* Get the colors for the highlight groups (gui_check_colors() might have
+ * changed them) */
+ highlight_gui_started();
+
+ /*
+ * Start out by adding the configured border width into the border offset
+ */
+ gui.border_offset = gui.border_width;
+
+
+ /*
+ * compute a couple of metrics used for the dialogs
+ */
+ get_dialog_font_metrics();
+#ifdef FEAT_TOOLBAR
+ /*
+ * Create the toolbar
+ */
+ initialise_toolbar();
+#endif
+#ifdef MSWIN_FIND_REPLACE
+ /*
+ * Initialise the dialog box stuff
+ */
+ s_findrep_msg = RegisterWindowMessage(FINDMSGSTRING);
+
+ /* Initialise the struct */
+ s_findrep_struct.lStructSize = sizeof(s_findrep_struct);
+ s_findrep_struct.lpstrFindWhat = alloc(MSWIN_FR_BUFSIZE);
+ s_findrep_struct.lpstrFindWhat[0] = NUL;
+ s_findrep_struct.lpstrReplaceWith = alloc(MSWIN_FR_BUFSIZE);
+ s_findrep_struct.lpstrReplaceWith[0] = NUL;
+ s_findrep_struct.wFindWhatLen = MSWIN_FR_BUFSIZE;
+ s_findrep_struct.wReplaceWithLen = MSWIN_FR_BUFSIZE;
+#endif
+
+ return OK;
+}
+
+
+/*
+ * Set the size of the window to the given width and height in pixels.
+ */
+ void
+gui_mch_set_shellsize(int width, int height,
+ int min_width, int min_height, int base_width, int base_height)
+{
+ RECT workarea_rect;
+ int win_width, win_height;
+ int win_xpos, win_ypos;
+ WINDOWPLACEMENT wndpl;
+
+ /* try to keep window completely on screen */
+ /* get size of the screen work area - use SM_CYFULLSCREEN
+ * instead of SM_CYSCREEN so that we don't overlap the
+ * taskbar if someone fires us up on Win95/NT */
+ workarea_rect.left = 0;
+ workarea_rect.top = 0;
+ workarea_rect.right = GetSystemMetrics(SM_CXSCREEN);
+ workarea_rect.bottom = GetSystemMetrics(SM_CYFULLSCREEN);
+
+ /* get current posision of our window */
+ wndpl.length = sizeof(WINDOWPLACEMENT);
+ GetWindowPlacement(s_hwnd, &wndpl);
+ if (wndpl.showCmd == SW_SHOWNORMAL)
+ {
+ win_xpos = wndpl.rcNormalPosition.left;
+ win_ypos = wndpl.rcNormalPosition.top;
+ }
+ else
+ {
+ win_xpos = workarea_rect.left;
+ win_ypos = workarea_rect.top;
+ }
+
+ /* compute the size of the outside of the window */
+ win_width = width + GetSystemMetrics(SM_CXFRAME) * 2;
+ win_height = height + GetSystemMetrics(SM_CYFRAME) * 2
+ + GetSystemMetrics(SM_CYCAPTION)
+#ifdef FEAT_MENU
+ + gui_mswin_get_menu_height(FALSE)
+#endif
+ ;
+
+ /* if the window is going off the screen, move it on to the screen */
+ if (win_xpos + win_width > workarea_rect.right)
+ win_xpos = workarea_rect.right - win_width;
+
+ if (win_xpos < workarea_rect.left)
+ win_xpos = workarea_rect.left;
+
+ if (win_ypos + win_height > workarea_rect.bottom)
+ win_ypos = workarea_rect.bottom - win_height;
+
+ if (win_ypos < workarea_rect.top)
+ win_ypos = workarea_rect.top;
+
+ /* set window position */
+ SetWindowPos(s_hwnd, NULL, win_xpos, win_ypos, win_width, win_height,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+
+#ifdef FEAT_MENU
+ /* Menu may wrap differently now */
+ gui_mswin_get_menu_height(!gui.starting);
+#endif
+}
+
+ void
+gui_mch_set_scrollbar_thumb(
+ scrollbar_T *sb,
+ long val,
+ long size,
+ long max)
+{
+ sb->scroll_shift = 0;
+ while (max > 32767)
+ {
+ max = (max + 1) >> 1;
+ val >>= 1;
+ size >>= 1;
+ ++sb->scroll_shift;
+ }
+
+ if (sb->scroll_shift > 0)
+ ++size;
+
+ SetScrollRange(sb->id, SB_CTL, 0, (int) max, FALSE);
+ SetScrollPos(sb->id, SB_CTL, (int) val, TRUE);
+}
+
+
+/*
+ * Set the current text font.
+ */
+ void
+gui_mch_set_font(GuiFont font)
+{
+ gui.currFont = font;
+ SelectFont(s_hdc, gui.currFont);
+}
+
+
+
+
+/*
+ * Set the current text foreground color.
+ */
+ void
+gui_mch_set_fg_color(guicolor_T color)
+{
+ gui.currFgColor = color;
+ SetTextColor(s_hdc, gui.currFgColor);
+}
+
+/*
+ * Set the current text background color.
+ */
+ void
+gui_mch_set_bg_color(guicolor_T color)
+{
+ if (gui.currBgColor == color)
+ return;
+
+ gui.currBgColor = color;
+ SetBkColor(s_hdc, gui.currBgColor);
+}
+
+
+
+ void
+gui_mch_draw_string(
+ int row,
+ int col,
+ char_u *text,
+ int len,
+ int flags)
+{
+#ifndef MSWIN16_FASTTEXT
+ static int *padding = NULL;
+ static int pad_size = 0;
+ int i;
+#endif
+ HPEN hpen, old_pen;
+ int y;
+
+#ifndef MSWIN16_FASTTEXT
+ /*
+ * Italic and bold text seems to have an extra row of pixels at the bottom
+ * (below where the bottom of the character should be). If we draw the
+ * characters with a solid background, the top row of pixels in the
+ * character below will be overwritten. We can fix this by filling in the
+ * background ourselves, to the correct character proportions, and then
+ * writing the character in transparent mode. Still have a problem when
+ * the character is "_", which gets written on to the character below.
+ * New fix: set gui.char_ascent to -1. This shifts all characters up one
+ * pixel in their slots, which fixes the problem with the bottom row of
+ * pixels. We still need this code because otherwise the top row of pixels
+ * becomes a problem. - webb.
+ */
+ HBRUSH hbr;
+ RECT rc;
+
+ if (!(flags & DRAW_TRANSP))
+ {
+ /*
+ * Clear background first.
+ * Note: FillRect() excludes right and bottom of rectangle.
+ */
+ rc.left = FILL_X(col);
+ rc.top = FILL_Y(row);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int cell_len = 0;
+
+ /* Compute the length in display cells. */
+ for (n = 0; n < len; n += MB_BYTE2LEN(text[n]))
+ cell_len += (*mb_ptr2cells)(text + n);
+ rc.right = FILL_X(col + cell_len);
+ }
+ else
+#endif
+ rc.right = FILL_X(col + len);
+ rc.bottom = FILL_Y(row + 1);
+ hbr = CreateSolidBrush(gui.currBgColor);
+ FillRect(s_hdc, &rc, hbr);
+ DeleteBrush(hbr);
+
+ SetBkMode(s_hdc, TRANSPARENT);
+
+ /*
+ * When drawing block cursor, prevent inverted character spilling
+ * over character cell (can happen with bold/italic)
+ */
+ if (flags & DRAW_CURSOR)
+ {
+ pcliprect = &rc;
+ foptions = ETO_CLIPPED;
+ }
+ }
+#else
+ /*
+ * Alternative: write the characters in opaque mode, since we have blocked
+ * bold or italic fonts.
+ */
+ /* The OPAQUE mode and backcolour have already been set */
+#endif
+ /* The forecolor and font have already been set */
+
+#ifndef MSWIN16_FASTTEXT
+
+ if (pad_size != Columns || padding == NULL || padding[0] != gui.char_width)
+ {
+ vim_free(padding);
+ pad_size = Columns;
+
+ padding = (int *)alloc(pad_size * sizeof(int));
+ if (padding != NULL)
+ for (i = 0; i < pad_size; i++)
+ padding[i] = gui.char_width;
+ }
+#endif
+
+ /*
+ * We have to provide the padding argument because italic and bold versions
+ * of fixed-width fonts are often one pixel or so wider than their normal
+ * versions.
+ * No check for DRAW_BOLD, Windows will have done it already.
+ */
+#ifndef MSWIN16_FASTTEXT
+ ExtTextOut(s_hdc, TEXT_X(col), TEXT_Y(row), 0, NULL,
+ (char *)text, len, padding);
+#else
+ TextOut(s_hdc, TEXT_X(col), TEXT_Y(row), (char *)text, len);
+#endif
+
+ if (flags & DRAW_UNDERL)
+ {
+ hpen = CreatePen(PS_SOLID, 1, gui.currFgColor);
+ old_pen = SelectObject(s_hdc, hpen);
+ /* When p_linespace is 0, overwrite the bottom row of pixels.
+ * Otherwise put the line just below the character. */
+ y = FILL_Y(row + 1) - 1;
+#ifndef MSWIN16_FASTTEXT
+ if (p_linespace > 1)
+ y -= p_linespace - 1;
+#endif
+ MoveToEx(s_hdc, FILL_X(col), y, NULL);
+ /* Note: LineTo() excludes the last pixel in the line. */
+ LineTo(s_hdc, FILL_X(col + len), y);
+ DeleteObject(SelectObject(s_hdc, old_pen));
+ }
+}
+
+
+/*
+ * Output routines.
+ */
+
+/* Flush any output to the screen */
+ void
+gui_mch_flush(void)
+{
+ /* Is anything needed here? */
+}
+
+ static void
+clear_rect(RECT *rcp)
+{
+ /* Use trick for fast rect clear */
+ gui_mch_set_bg_color(gui.back_pixel);
+ ExtTextOut(s_hdc, 0, 0, ETO_CLIPPED | ETO_OPAQUE, rcp, NULL, 0, NULL);
+}
+
+
+
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Add a sub menu to the menu bar.
+ */
+ void
+gui_mch_add_menu(
+ vimmenu_T *menu,
+ int pos)
+{
+ vimmenu_T *parent = menu->parent;
+
+ menu->submenu_id = CreatePopupMenu();
+ menu->id = s_menu_id++;
+
+ if (menu_is_menubar(menu->name))
+ {
+ InsertMenu((parent == NULL) ? s_menuBar : parent->submenu_id,
+ (UINT)pos, MF_POPUP | MF_STRING | MF_BYPOSITION,
+ (UINT)menu->submenu_id, menu->name);
+ }
+
+ /* Fix window size if menu may have wrapped */
+ if (parent == NULL)
+ gui_mswin_get_menu_height(!gui.starting);
+}
+
+ void
+gui_mch_show_popupmenu(vimmenu_T *menu)
+{
+ POINT mp;
+
+ (void)GetCursorPos((LPPOINT)&mp);
+ gui_mch_show_popupmenu_at(menu, (int)mp.x, (int)mp.y);
+}
+
+ void
+gui_make_popup(char_u *path_name)
+{
+ vimmenu_T *menu = gui_find_menu(path_name);
+
+ if (menu != NULL)
+ {
+ /* Find the position of the current cursor */
+ DWORD temp_p;
+ POINT p;
+ temp_p = GetDCOrg(s_hdc);
+ p.x = LOWORD(temp_p);
+ p.y = HIWORD(temp_p);
+ if (curwin!=NULL)
+ {
+ p.x+= TEXT_X(W_WINCOL(curwin) + curwin->w_wcol +1);
+ p.y+= TEXT_Y(W_WINROW(curwin) + curwin->w_wrow +1);
+ }
+ msg_scroll = FALSE;
+ gui_mch_show_popupmenu_at(menu, (int)p.x, (int)p.y);
+ }
+}
+
+/*
+ * Add a menu item to a menu
+ */
+ void
+gui_mch_add_menu_item(
+ vimmenu_T *menu,
+ int idx)
+{
+ vimmenu_T *parent = menu->parent;
+
+ menu->id = s_menu_id++;
+ menu->submenu_id = NULL;
+
+#ifdef FEAT_TOOLBAR
+ if (menu_is_toolbar(parent->name))
+ {
+ TBBUTTON newtb;
+
+ vim_memset(&newtb, 0, sizeof(newtb));
+ if (menu_is_separator(menu->name))
+ {
+ newtb.iBitmap = 0;
+ newtb.fsStyle = TBSTYLE_SEP;
+ }
+ else
+ {
+ if (menu->iconidx >= TOOLBAR_BITMAP_COUNT)
+ newtb.iBitmap = -1;
+ else
+ newtb.iBitmap = menu->iconidx;
+ newtb.fsStyle = TBSTYLE_BUTTON;
+ }
+ newtb.idCommand = menu->id;
+ newtb.fsState = TBSTATE_ENABLED;
+ SendMessage(s_toolbarhwnd, TB_INSERTBUTTON, (WPARAM)idx,
+ (LPARAM)&newtb);
+ menu->submenu_id = (HMENU)-1;
+ }
+ else
+#endif
+ {
+ InsertMenu(parent->submenu_id, (UINT)idx,
+ (menu_is_separator(menu->name) ? MF_SEPARATOR : MF_STRING)
+ | MF_BYPOSITION,
+ (UINT)menu->id, menu->name);
+ }
+}
+
+/*
+ * Destroy the machine specific menu widget.
+ */
+ void
+gui_mch_destroy_menu(vimmenu_T *menu)
+{
+ UINT i, j;
+ char pants[80]; /*<VN> hack*/
+#ifdef FEAT_TOOLBAR
+ /*
+ * is this a toolbar button?
+ */
+ if (menu->submenu_id == (HMENU)-1)
+ {
+ int iButton;
+
+ iButton = SendMessage(s_toolbarhwnd, TB_COMMANDTOINDEX, (WPARAM)menu->id, 0);
+ SendMessage(s_toolbarhwnd, TB_DELETEBUTTON, (WPARAM)iButton, 0);
+ }
+ else
+#endif
+ {
+ /*
+ * negri: horrible API bug when running 16-bit programs under Win9x or
+ * NT means that we can't use MF_BYCOMMAND for menu items which have
+ * submenus, including the top-level headings. We have to find the menu
+ * item and use MF_BYPOSITION instead. :-p
+ */
+ if (menu->parent != NULL
+ && menu_is_popup(menu->parent->dname)
+ && menu->parent->submenu_id != NULL)
+ RemoveMenu(menu->parent->submenu_id, menu->id, MF_BYCOMMAND);
+ else if (menu->submenu_id == NULL)
+ RemoveMenu(s_menuBar, menu->id, MF_BYCOMMAND);
+ else if (menu->parent != NULL)
+ {
+ i = GetMenuItemCount(menu->parent->submenu_id);
+ for (j = 0; j < i; ++j)
+ {
+ GetMenuString(menu->parent->submenu_id, j,
+ pants, 80, MF_BYPOSITION);
+ if (strcmp(pants, menu->name) == 0)
+ {
+ RemoveMenu(menu->parent->submenu_id, j, MF_BYPOSITION);
+ break;
+ }
+ }
+ }
+ else
+ {
+ i = GetMenuItemCount(s_menuBar);
+ for (j = 0; j < i; ++j)
+ {
+ GetMenuString(s_menuBar, j, pants, 80, MF_BYPOSITION);
+ if (strcmp(pants, menu->name) == 0)
+ {
+ RemoveMenu(s_menuBar, j, MF_BYPOSITION);
+ break;
+ }
+ }
+ }
+
+ if (menu->submenu_id != NULL)
+ DestroyMenu(menu->submenu_id);
+ }
+ DrawMenuBar(s_hwnd);
+}
+
+
+/*
+ * Make a menu either grey or not grey.
+ */
+ void
+gui_mch_menu_grey(
+ vimmenu_T *menu,
+ int grey)
+{
+#ifdef FEAT_TOOLBAR
+ /*
+ * is this a toolbar button?
+ */
+ if (menu->submenu_id == (HMENU)-1)
+ {
+ SendMessage(s_toolbarhwnd, TB_ENABLEBUTTON,
+ (WPARAM)menu->id, (LPARAM) MAKELONG((grey ? FALSE : TRUE), 0) );
+ }
+ else
+#endif
+ if (grey)
+ EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_GRAYED);
+ else
+ EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_ENABLED);
+
+}
+
+
+#endif /*FEAT_MENU*/
+
+
+/* define some macros used to make the dialogue creation more readable */
+
+#define add_string(s) strcpy((LPSTR)p, s); (LPSTR)p += (strlen((LPSTR)p) + 1)
+#define add_word(x) *p++ = (x)
+#define add_byte(x) *((LPSTR)p)++ = (x)
+#define add_long(x) *((LPDWORD)p)++ = (x)
+
+#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
+/*
+ * stuff for dialogs
+ */
+
+/*
+ * The callback routine used by all the dialogs. Very simple. First,
+ * acknowledges the INITDIALOG message so that Windows knows to do standard
+ * dialog stuff (Return = default, Esc = cancel....) Second, if a button is
+ * pressed, return that button's ID - IDCANCEL (2), which is the button's
+ * number.
+ */
+ static BOOL CALLBACK
+dialog_callback(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ if (message == WM_INITDIALOG)
+ {
+ CenterWindow(hwnd, GetWindow(hwnd, GW_OWNER));
+ /* Set focus to the dialog. Set the default button, if specified. */
+ (void)SetFocus(hwnd);
+ if (dialog_default_button > IDCANCEL)
+ (void)SetFocus(GetDlgItem(hwnd, dialog_default_button));
+// if (dialog_default_button > 0)
+// (void)SetFocus(GetDlgItem(hwnd, dialog_default_button + IDCANCEL));
+ return FALSE;
+ }
+
+ if (message == WM_COMMAND)
+ {
+ int button = LOWORD(wParam);
+
+ /* Don't end the dialog if something was selected that was
+ * not a button.
+ */
+ if (button >= DLG_NONBUTTON_CONTROL)
+ return TRUE;
+
+ /* If the edit box exists, copy the string. */
+ if (s_textfield != NULL)
+ GetDlgItemText(hwnd, DLG_NONBUTTON_CONTROL + 2,
+ s_textfield, IOSIZE);
+
+ /*
+ * Need to check for IDOK because if the user just hits Return to
+ * accept the default value, some reason this is what we get.
+ */
+ if (button == IDOK)
+ EndDialog(hwnd, dialog_default_button);
+ else
+ EndDialog(hwnd, button - IDCANCEL);
+ return TRUE;
+ }
+
+ if ((message == WM_SYSCOMMAND) && (wParam == SC_CLOSE))
+ {
+ EndDialog(hwnd, 0);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Create a dialog dynamically from the parameter strings.
+ * type = type of dialog (question, alert, etc.)
+ * title = dialog title. may be NULL for default title.
+ * message = text to display. Dialog sizes to accommodate it.
+ * buttons = '\n' separated list of button captions, default first.
+ * dfltbutton = number of default button.
+ *
+ * This routine returns 1 if the first button is pressed,
+ * 2 for the second, etc.
+ *
+ * 0 indicates Esc was pressed.
+ * -1 for unexpected error
+ *
+ * If stubbing out this fn, return 1.
+ */
+
+static const char_u dlg_icons[] = /* must match names in resource file */
+{
+ IDR_VIM,
+ IDR_VIM_ERROR,
+ IDR_VIM_ALERT,
+ IDR_VIM_INFO,
+ IDR_VIM_QUESTION
+};
+
+ int
+gui_mch_dialog(
+ int type,
+ char_u *title,
+ char_u *message,
+ char_u *buttons,
+ int dfltbutton,
+ char_u *textfield)
+{
+ FARPROC dp;
+ LPWORD p, pnumitems;
+ int numButtons;
+ int *buttonWidths, *buttonPositions;
+ int buttonYpos;
+ int nchar, i;
+ DWORD lStyle;
+ int dlgwidth = 0;
+ int dlgheight;
+ int editboxheight;
+ int horizWidth;
+ int msgheight;
+ char_u *pstart;
+ char_u *pend;
+ char_u *tbuffer;
+ RECT rect;
+ HWND hwnd;
+ HDC hdc;
+ HFONT oldFont;
+ TEXTMETRIC fontInfo;
+ int fontHeight;
+ int textWidth, minButtonWidth, messageWidth;
+ int maxDialogWidth;
+ int vertical;
+ int dlgPaddingX;
+ int dlgPaddingY;
+ HGLOBAL hglbDlgTemp;
+
+#ifndef NO_CONSOLE
+ /* Don't output anything in silent mode ("ex -s") */
+ if (silent_mode)
+ return dfltbutton; /* return default option */
+#endif
+
+ /* If there is no window yet, open it. */
+ if (s_hwnd == NULL && gui_mch_init() == FAIL)
+ return dfltbutton;
+
+ if ((type < 0) || (type > VIM_LAST_TYPE))
+ type = 0;
+
+ /* allocate some memory for dialog template */
+ /* TODO should compute this really*/
+
+ hglbDlgTemp = GlobalAlloc(GHND, DLG_ALLOC_SIZE);
+ if (hglbDlgTemp == NULL)
+ return -1;
+
+ p = (LPWORD) GlobalLock(hglbDlgTemp);
+
+ if (p == NULL)
+ return -1;
+
+ /*
+ * make a copy of 'buttons' to fiddle with it. complier grizzles because
+ * vim_strsave() doesn't take a const arg (why not?), so cast away the
+ * const.
+ */
+ tbuffer = vim_strsave(buttons);
+ if (tbuffer == NULL)
+ return -1;
+
+ --dfltbutton; /* Change from one-based to zero-based */
+
+ /* Count buttons */
+ numButtons = 1;
+ for (i = 0; tbuffer[i] != '\0'; i++)
+ {
+ if (tbuffer[i] == DLG_BUTTON_SEP)
+ numButtons++;
+ }
+ if (dfltbutton >= numButtons)
+ dfltbutton = 0;
+
+ /* Allocate array to hold the width of each button */
+ buttonWidths = (int *) lalloc(numButtons * sizeof(int), TRUE);
+ if (buttonWidths == NULL)
+ return -1;
+
+ /* Allocate array to hold the X position of each button */
+ buttonPositions = (int *) lalloc(numButtons * sizeof(int), TRUE);
+ if (buttonPositions == NULL)
+ return -1;
+
+ /*
+ * Calculate how big the dialog must be.
+ */
+ hwnd = GetDesktopWindow();
+ hdc = GetWindowDC(hwnd);
+ oldFont = SelectFont(hdc, GetStockObject(SYSTEM_FONT));
+ dlgPaddingX = DLG_OLD_STYLE_PADDING_X;
+ dlgPaddingY = DLG_OLD_STYLE_PADDING_Y;
+
+ GetTextMetrics(hdc, &fontInfo);
+ fontHeight = fontInfo.tmHeight;
+
+ /* Minimum width for horizontal button */
+ minButtonWidth = GetTextWidth(hdc, "Cancel", 6);
+
+ /* Maximum width of a dialog, if possible */
+ GetWindowRect(s_hwnd, &rect);
+ maxDialogWidth = rect.right - rect.left
+ - GetSystemMetrics(SM_CXFRAME) * 2;
+ if (maxDialogWidth < DLG_MIN_MAX_WIDTH)
+ maxDialogWidth = DLG_MIN_MAX_WIDTH;
+
+ /* Set dlgwidth to width of message */
+ pstart = message;
+ messageWidth = 0;
+ msgheight = 0;
+ do
+ {
+ pend = vim_strchr(pstart, DLG_BUTTON_SEP);
+ if (pend == NULL)
+ pend = pstart + STRLEN(pstart); /* Last line of message. */
+ msgheight += fontHeight;
+ textWidth = GetTextWidth(hdc, pstart, pend - pstart);
+ if (textWidth > messageWidth)
+ messageWidth = textWidth;
+ pstart = pend + 1;
+ } while (*pend != NUL);
+ dlgwidth = messageWidth;
+
+ /* Add width of icon to dlgwidth, and some space */
+ dlgwidth += DLG_ICON_WIDTH + 3 * dlgPaddingX;
+
+ if (msgheight < DLG_ICON_HEIGHT)
+ msgheight = DLG_ICON_HEIGHT;
+
+ /*
+ * Check button names. A long one will make the dialog wider.
+ */
+ vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
+ if (!vertical)
+ {
+ // Place buttons horizontally if they fit.
+ horizWidth = dlgPaddingX;
+ pstart = tbuffer;
+ i = 0;
+ do
+ {
+ pend = vim_strchr(pstart, DLG_BUTTON_SEP);
+ if (pend == NULL)
+ pend = pstart + STRLEN(pstart); // Last button name.
+ textWidth = GetTextWidth(hdc, pstart, pend - pstart);
+ if (textWidth < minButtonWidth)
+ textWidth = minButtonWidth;
+ textWidth += dlgPaddingX; /* Padding within button */
+ buttonWidths[i] = textWidth;
+ buttonPositions[i++] = horizWidth;
+ horizWidth += textWidth + dlgPaddingX; /* Pad between buttons */
+ pstart = pend + 1;
+ } while (*pend != NUL);
+
+ if (horizWidth > maxDialogWidth)
+ vertical = TRUE; // Too wide to fit on the screen.
+ else if (horizWidth > dlgwidth)
+ dlgwidth = horizWidth;
+ }
+
+ if (vertical)
+ {
+ // Stack buttons vertically.
+ pstart = tbuffer;
+ do
+ {
+ pend = vim_strchr(pstart, DLG_BUTTON_SEP);
+ if (pend == NULL)
+ pend = pstart + STRLEN(pstart); // Last button name.
+ textWidth = GetTextWidth(hdc, pstart, pend - pstart);
+ textWidth += dlgPaddingX; /* Padding within button */
+ textWidth += DLG_VERT_PADDING_X * 2; /* Padding around button */
+ if (textWidth > dlgwidth)
+ dlgwidth = textWidth;
+ pstart = pend + 1;
+ } while (*pend != NUL);
+ }
+
+ if (dlgwidth < DLG_MIN_WIDTH)
+ dlgwidth = DLG_MIN_WIDTH; /* Don't allow a really thin dialog!*/
+
+ /* start to fill in the dlgtemplate information. addressing by WORDs */
+ lStyle = DS_MODALFRAME | WS_CAPTION | WS_VISIBLE ;
+
+ add_long(lStyle);
+ pnumitems = p; /*save where the number of items must be stored*/
+ add_byte(0); // NumberOfItems(will change later)
+ add_word(10); // x
+ add_word(10); // y
+ add_word(PixelToDialogX(dlgwidth));
+
+ // Dialog height.
+ if (vertical)
+ dlgheight = msgheight + 2 * dlgPaddingY +
+ DLG_VERT_PADDING_Y + 2 * fontHeight * numButtons;
+ else
+ dlgheight = msgheight + 3 * dlgPaddingY + 2 * fontHeight;
+
+ // Dialog needs to be taller if contains an edit box.
+ editboxheight = fontHeight + dlgPaddingY + 4 * DLG_VERT_PADDING_Y;
+ if (textfield != NULL)
+ dlgheight += editboxheight;
+
+ add_word(PixelToDialogY(dlgheight));
+
+ add_byte(0); //menu
+ add_byte(0); //class
+
+ /* copy the title of the dialog */
+ add_string(title ? title : ("Vim"VIM_VERSION_MEDIUM));
+
+ buttonYpos = msgheight + 2 * dlgPaddingY;
+
+ if (textfield != NULL)
+ buttonYpos += editboxheight;
+
+ pstart = tbuffer; //dflt_text
+ horizWidth = (dlgwidth - horizWidth) / 2; /* Now it's X offset */
+ for (i = 0; i < numButtons; i++)
+ {
+ /* get end of this button. */
+ for ( pend = pstart;
+ *pend && (*pend != DLG_BUTTON_SEP);
+ pend++)
+ ;
+
+ if (*pend)
+ *pend = '\0';
+
+ /*
+ * NOTE:
+ * setting the BS_DEFPUSHBUTTON style doesn't work because Windows sets
+ * the focus to the first tab-able button and in so doing makes that
+ * the default!! Grrr. Workaround: Make the default button the only
+ * one with WS_TABSTOP style. Means user can't tab between buttons, but
+ * he/she can use arrow keys.
+ *
+ * NOTE (Thore): Setting BS_DEFPUSHBUTTON works fine when it's the
+ * first one, so I changed the correct button to be this style. This
+ * is necessary because when an edit box is added, we need a button to
+ * be default. The edit box will be the default control, and when the
+ * user presses enter from the edit box we want the default button to
+ * be pressed.
+ */
+ if (vertical)
+ {
+ p = add_dialog_element(p,
+ ((i == dfltbutton || dfltbutton < 0) && textfield != NULL
+ ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP,
+ PixelToDialogX(DLG_VERT_PADDING_X),
+ PixelToDialogY(buttonYpos /* TBK */
+ + 2 * fontHeight * i),
+ PixelToDialogX(dlgwidth - 2 * DLG_VERT_PADDING_X),
+ (WORD)(PixelToDialogY(2 * fontHeight) - 1),
+ (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart);
+ }
+ else
+ {
+ p = add_dialog_element(p,
+ ((i == dfltbutton || dfltbutton < 0) && textfield != NULL
+ ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP,
+ PixelToDialogX(horizWidth + buttonPositions[i]),
+ PixelToDialogY(buttonYpos), /* TBK */
+ PixelToDialogX(buttonWidths[i]),
+ (WORD)(PixelToDialogY(2 * fontHeight) - 1),
+ (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart);
+ }
+
+ pstart = pend + 1; /*next button*/
+
+ }
+ *pnumitems += numButtons;
+
+ /* Vim icon */
+ p = add_dialog_element(p, SS_ICON,
+ PixelToDialogX(dlgPaddingX),
+ PixelToDialogY(dlgPaddingY),
+ PixelToDialogX(DLG_ICON_WIDTH),
+ PixelToDialogY(DLG_ICON_HEIGHT),
+ DLG_NONBUTTON_CONTROL + 0, (BYTE)0x82,
+ &dlg_icons[type]);
+
+
+ /* Dialog message */
+ p = add_dialog_element(p, SS_LEFT,
+ PixelToDialogX(2 * dlgPaddingX + DLG_ICON_WIDTH),
+ PixelToDialogY(dlgPaddingY),
+ (WORD)(PixelToDialogX(messageWidth) + 1),
+ PixelToDialogY(msgheight),
+ DLG_NONBUTTON_CONTROL + 1, (BYTE)0x82, message);
+
+ /* Edit box */
+ if (textfield != NULL)
+ {
+ p = add_dialog_element(p, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP | WS_BORDER,
+ PixelToDialogX(2 * dlgPaddingX),
+ PixelToDialogY(2 * dlgPaddingY + msgheight),
+ PixelToDialogX(dlgwidth - 4 * dlgPaddingX),
+ PixelToDialogY(fontHeight + dlgPaddingY),
+ DLG_NONBUTTON_CONTROL + 2, (BYTE)0x81, textfield);
+ *pnumitems += 1;
+ }
+
+ *pnumitems += 2;
+
+ SelectFont(hdc, oldFont);
+ ReleaseDC(hwnd, hdc);
+ dp = MakeProcInstance((FARPROC)dialog_callback, s_hinst);
+
+
+ /* Let the dialog_callback() function know which button to make default
+ * If we have an edit box, make that the default. We also need to tell
+ * dialog_callback() if this dialog contains an edit box or not. We do
+ * this by setting s_textfield if it does.
+ */
+ if (textfield != NULL)
+ {
+ dialog_default_button = DLG_NONBUTTON_CONTROL + 2;
+ s_textfield = textfield;
+ }
+ else
+ {
+ dialog_default_button = IDCANCEL + 1 + dfltbutton;
+ s_textfield = NULL;
+ }
+
+ /*show the dialog box modally and get a return value*/
+ nchar = DialogBoxIndirect(
+ s_hinst,
+ (HGLOBAL) hglbDlgTemp,
+ s_hwnd,
+ (DLGPROC)dp);
+
+ FreeProcInstance( dp );
+ GlobalUnlock(hglbDlgTemp);
+ GlobalFree(hglbDlgTemp);
+ vim_free(tbuffer);
+ vim_free(buttonWidths);
+ vim_free(buttonPositions);
+
+
+ return nchar;
+}
+
+/*
+ * Put a simple element (basic class) onto a dialog template in memory.
+ * return a pointer to where the next item should be added.
+ *
+ * parameters:
+ * lStyle = additional style flags
+ * x,y = x & y positions IN DIALOG UNITS
+ * w,h = width and height IN DIALOG UNITS
+ * Id = ID used in messages
+ * clss = class ID, e.g 0x80 for a button, 0x82 for a static
+ * caption = usually text or resource name
+ *
+ * TODO: use the length information noted here to enable the dialog creation
+ * routines to work out more exactly how much memory they need to alloc.
+ */
+ static LPWORD
+add_dialog_element(
+ LPWORD p,
+ DWORD lStyle,
+ WORD x,
+ WORD y,
+ WORD w,
+ WORD h,
+ WORD Id,
+ BYTE clss,
+ const char *caption)
+{
+
+ lStyle = lStyle | WS_VISIBLE | WS_CHILD;
+
+ add_word(x);
+ add_word(y);
+ add_word(w);
+ add_word(h);
+ add_word(Id);
+ add_long(lStyle);
+ add_byte(clss);
+ if (((lStyle & SS_ICON) != 0) && (clss == 0x82))
+ {
+ /* Use resource ID */
+ add_byte(0xff);
+ add_byte(*caption);
+ }
+ else
+ add_string(caption);
+
+ add_byte(0); //# of extra bytes following
+
+
+ return p;
+}
+
+#undef add_byte
+#undef add_string
+#undef add_long
+#undef add_word
+
+#endif /* FEAT_GUI_DIALOG */
+
+ static void
+get_dialog_font_metrics(void)
+{
+ DWORD dlgFontSize;
+ dlgFontSize = GetDialogBaseUnits(); /* fall back to big old system*/
+ s_dlgfntwidth = LOWORD(dlgFontSize);
+ s_dlgfntheight = HIWORD(dlgFontSize);
+}
+
+
+#if defined(FEAT_TOOLBAR) || defined(PROTO)
+#include "gui_w3~1.h"
+/*
+ * Create the toolbar, initially unpopulated.
+ * (just like the menu, there are no defaults, it's all
+ * set up through menu.vim)
+ */
+ static void
+initialise_toolbar(void)
+{
+ s_toolbarhwnd = CreateToolbar(
+ s_hwnd,
+ WS_CHILD | WS_VISIBLE,
+ CMD_TB_BASE, /*<vn>*/
+ 31, //number of images in inital bitmap
+ s_hinst,
+ IDR_TOOLBAR1, // id of initial bitmap
+ NULL,
+ 0 // initial number of buttons
+ );
+
+ gui_mch_show_toolbar(vim_strchr(p_go, GO_TOOLBAR) != NULL);
+}
+#endif
+
+#if defined(FEAT_OLE) || defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Make the GUI window come to the foreground.
+ */
+ void
+gui_mch_set_foreground(void)
+{
+ if (IsIconic(s_hwnd))
+ SendMessage(s_hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
+ SetActiveWindow(s_hwnd);
+}
+#endif
diff --git a/src/gui_w32.c b/src/gui_w32.c
new file mode 100644
index 000000000..df079538a
--- /dev/null
+++ b/src/gui_w32.c
@@ -0,0 +1,4077 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI support by Robert Webb
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * Windows GUI.
+ *
+ * GUI support for Microsoft Windows. Win32 initially; maybe Win16 later
+ *
+ * George V. Reilly <george@reilly.org> wrote the original Win32 GUI.
+ * Robert Webb reworked it to use the existing GUI stuff and added menu,
+ * scrollbars, etc.
+ *
+ * Note: Clipboard stuff, for cutting and pasting text to other windows, is in
+ * os_win32.c. (It can also be done from the terminal version).
+ *
+ * TODO: Some of the function signatures ought to be updated for Win64;
+ * e.g., replace LONG with LONG_PTR, etc.
+ */
+
+/*
+ * These are new in Windows ME/XP, only defined in recent compilers.
+ */
+#ifndef HANDLE_WM_XBUTTONUP
+# define HANDLE_WM_XBUTTONUP(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+#endif
+#ifndef HANDLE_WM_XBUTTONDOWN
+# define HANDLE_WM_XBUTTONDOWN(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), FALSE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+#endif
+#ifndef HANDLE_WM_XBUTTONDBLCLK
+# define HANDLE_WM_XBUTTONDBLCLK(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), TRUE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+#endif
+
+/*
+ * Include the common stuff for MS-Windows GUI.
+ */
+#include "gui_w48.c"
+
+#ifdef FEAT_XPM_W32
+# include "xpm_w32.h"
+#endif
+
+#ifdef PROTO
+# define WINAPI
+#endif
+
+#ifdef __MINGW32__
+/*
+ * Add a lot of missing defines.
+ * They are not always missing, we need the #ifndef's.
+ */
+# ifndef _cdecl
+# define _cdecl
+# endif
+# ifndef IsMinimized
+# define IsMinimized(hwnd) IsIconic(hwnd)
+# endif
+# ifndef IsMaximized
+# define IsMaximized(hwnd) IsZoomed(hwnd)
+# endif
+# ifndef SelectFont
+# define SelectFont(hdc, hfont) ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT)(hfont)))
+# endif
+# ifndef GetStockBrush
+# define GetStockBrush(i) ((HBRUSH)GetStockObject(i))
+# endif
+# ifndef DeleteBrush
+# define DeleteBrush(hbr) DeleteObject((HGDIOBJ)(HBRUSH)(hbr))
+# endif
+
+# ifndef HANDLE_WM_RBUTTONDBLCLK
+# define HANDLE_WM_RBUTTONDBLCLK(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), TRUE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_MBUTTONUP
+# define HANDLE_WM_MBUTTONUP(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_MBUTTONDBLCLK
+# define HANDLE_WM_MBUTTONDBLCLK(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), TRUE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_LBUTTONDBLCLK
+# define HANDLE_WM_LBUTTONDBLCLK(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), TRUE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_RBUTTONDOWN
+# define HANDLE_WM_RBUTTONDOWN(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), FALSE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_MOUSEMOVE
+# define HANDLE_WM_MOUSEMOVE(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_RBUTTONUP
+# define HANDLE_WM_RBUTTONUP(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_MBUTTONDOWN
+# define HANDLE_WM_MBUTTONDOWN(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), FALSE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_LBUTTONUP
+# define HANDLE_WM_LBUTTONUP(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_LBUTTONDOWN
+# define HANDLE_WM_LBUTTONDOWN(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), FALSE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_SYSCHAR
+# define HANDLE_WM_SYSCHAR(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (TCHAR)(wParam), (int)(short)LOWORD(lParam)), 0L)
+# endif
+# ifndef HANDLE_WM_ACTIVATEAPP
+# define HANDLE_WM_ACTIVATEAPP(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (BOOL)(wParam), (DWORD)(lParam)), 0L)
+# endif
+# ifndef HANDLE_WM_WINDOWPOSCHANGING
+# define HANDLE_WM_WINDOWPOSCHANGING(hwnd, wParam, lParam, fn) \
+ (LRESULT)(DWORD)(BOOL)(fn)((hwnd), (LPWINDOWPOS)(lParam))
+# endif
+# ifndef HANDLE_WM_VSCROLL
+# define HANDLE_WM_VSCROLL(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (HWND)(lParam), (UINT)(LOWORD(wParam)), (int)(short)HIWORD(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_SETFOCUS
+# define HANDLE_WM_SETFOCUS(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (HWND)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_KILLFOCUS
+# define HANDLE_WM_KILLFOCUS(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (HWND)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_HSCROLL
+# define HANDLE_WM_HSCROLL(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (HWND)(lParam), (UINT)(LOWORD(wParam)), (int)(short)HIWORD(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_DROPFILES
+# define HANDLE_WM_DROPFILES(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (HDROP)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_CHAR
+# define HANDLE_WM_CHAR(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (TCHAR)(wParam), (int)(short)LOWORD(lParam)), 0L)
+# endif
+# ifndef HANDLE_WM_SYSDEADCHAR
+# define HANDLE_WM_SYSDEADCHAR(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (TCHAR)(wParam), (int)(short)LOWORD(lParam)), 0L)
+# endif
+# ifndef HANDLE_WM_DEADCHAR
+# define HANDLE_WM_DEADCHAR(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (TCHAR)(wParam), (int)(short)LOWORD(lParam)), 0L)
+# endif
+#endif /* __MINGW32__ */
+
+
+/* Some parameters for tearoff menus. All in pixels. */
+#define TEAROFF_PADDING_X 2
+#define TEAROFF_BUTTON_PAD_X 8
+#define TEAROFF_MIN_WIDTH 200
+#define TEAROFF_SUBMENU_LABEL ">>"
+#define TEAROFF_COLUMN_PADDING 3 // # spaces to pad column with.
+
+
+/* For the Intellimouse: */
+#ifndef WM_MOUSEWHEEL
+#define WM_MOUSEWHEEL 0x20a
+#endif
+
+
+#ifdef FEAT_BEVAL
+# define ID_BEVAL_TOOLTIP 200
+# define BEVAL_TEXT_LEN MAXPATHL
+
+static void make_tooltip __ARGS((BalloonEval *beval, char *text, POINT pt));
+static void delete_tooltip __ARGS((BalloonEval *beval));
+static VOID CALLBACK BevalTimerProc __ARGS((HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime));
+
+static BalloonEval *cur_beval = NULL;
+static UINT BevalTimerId = 0;
+static DWORD LastActivity = 0;
+#endif
+
+/* Local variables: */
+
+#ifdef FEAT_MENU
+static UINT s_menu_id = 100;
+
+/*
+ * Use the system font for dialogs and tear-off menus. Remove this line to
+ * use DLG_FONT_NAME.
+ */
+# define USE_SYSMENU_FONT
+#endif
+
+#define VIM_NAME "vim"
+#define VIM_CLASS "Vim"
+#define VIM_CLASSW L"Vim"
+
+/* Initial size for the dialog template. For gui_mch_dialog() it's fixed,
+ * thus there should be room for every dialog. For tearoffs it's made bigger
+ * when needed. */
+#define DLG_ALLOC_SIZE 16 * 1024
+
+/*
+ * stuff for dialogs, menus, tearoffs etc.
+ */
+static LRESULT APIENTRY dialog_callback(HWND, UINT, WPARAM, LPARAM);
+static LRESULT APIENTRY tearoff_callback(HWND, UINT, WPARAM, LPARAM);
+static PWORD
+add_dialog_element(
+ PWORD p,
+ DWORD lStyle,
+ WORD x,
+ WORD y,
+ WORD w,
+ WORD h,
+ WORD Id,
+ WORD clss,
+ const char *caption);
+static LPWORD lpwAlign(LPWORD);
+static int nCopyAnsiToWideChar(LPWORD, LPSTR);
+static void gui_mch_tearoff(char_u *title, vimmenu_T *menu, int initX, int initY);
+static void get_dialog_font_metrics(void);
+
+static int dialog_default_button = -1;
+
+/* Intellimouse support */
+static int mouse_scroll_lines = 0;
+static UINT msh_msgmousewheel = 0;
+
+static int s_usenewlook; /* emulate W95/NT4 non-bold dialogs */
+#ifdef FEAT_TOOLBAR
+static void initialise_toolbar(void);
+static int get_toolbar_bitmap(vimmenu_T *menu);
+#endif
+
+#ifdef FEAT_MBYTE_IME
+static LRESULT _OnImeComposition(HWND hwnd, WPARAM dbcs, LPARAM param);
+static char_u *GetResultStr(HWND hwnd, int GCS, int *lenp);
+#endif
+#if defined(FEAT_MBYTE_IME) && defined(DYNAMIC_IME)
+# ifdef NOIME
+typedef struct tagCOMPOSITIONFORM {
+ DWORD dwStyle;
+ POINT ptCurrentPos;
+ RECT rcArea;
+} COMPOSITIONFORM, *PCOMPOSITIONFORM, NEAR *NPCOMPOSITIONFORM, FAR *LPCOMPOSITIONFORM;
+typedef HANDLE HIMC;
+# endif
+
+HINSTANCE hLibImm = NULL;
+LONG (WINAPI *pImmGetCompositionStringA)(HIMC, DWORD, LPVOID, DWORD);
+LONG (WINAPI *pImmGetCompositionStringW)(HIMC, DWORD, LPVOID, DWORD);
+HIMC (WINAPI *pImmGetContext)(HWND);
+HIMC (WINAPI *pImmAssociateContext)(HWND, HIMC);
+BOOL (WINAPI *pImmReleaseContext)(HWND, HIMC);
+BOOL (WINAPI *pImmGetOpenStatus)(HIMC);
+BOOL (WINAPI *pImmSetOpenStatus)(HIMC, BOOL);
+BOOL (WINAPI *pImmGetCompositionFont)(HIMC, LPLOGFONTA);
+BOOL (WINAPI *pImmSetCompositionFont)(HIMC, LPLOGFONTA);
+BOOL (WINAPI *pImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM);
+BOOL (WINAPI *pImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD);
+static void dyn_imm_load(void);
+#else
+# define pImmGetCompositionStringA ImmGetCompositionStringA
+# define pImmGetCompositionStringW ImmGetCompositionStringW
+# define pImmGetContext ImmGetContext
+# define pImmAssociateContext ImmAssociateContext
+# define pImmReleaseContext ImmReleaseContext
+# define pImmGetOpenStatus ImmGetOpenStatus
+# define pImmSetOpenStatus ImmSetOpenStatus
+# define pImmGetCompositionFont ImmGetCompositionFontA
+# define pImmSetCompositionFont ImmSetCompositionFontA
+# define pImmSetCompositionWindow ImmSetCompositionWindow
+# define pImmGetConversionStatus ImmGetConversionStatus
+#endif
+
+#ifndef ETO_IGNORELANGUAGE
+# define ETO_IGNORELANGUAGE 0x1000
+#endif
+
+/* multi monitor support */
+typedef struct _MONITORINFOstruct
+{
+ DWORD cbSize;
+ RECT rcMonitor;
+ RECT rcWork;
+ DWORD dwFlags;
+} _MONITORINFO;
+
+typedef HANDLE _HMONITOR;
+typedef _HMONITOR (WINAPI *TMonitorFromWindow)(HWND, DWORD);
+typedef BOOL (WINAPI *TGetMonitorInfo)(_HMONITOR, _MONITORINFO *);
+
+static TMonitorFromWindow pMonitorFromWindow = NULL;
+static TGetMonitorInfo pGetMonitorInfo = NULL;
+static HANDLE user32_lib = NULL;
+#ifdef FEAT_NETBEANS_INTG
+int WSInitialized = FALSE; /* WinSock is initialized */
+#endif
+/*
+ * Return TRUE when running under Windows NT 3.x or Win32s, both of which have
+ * less fancy GUI APIs.
+ */
+ static int
+is_winnt_3(void)
+{
+ return ((os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && os_version.dwMajorVersion == 3)
+ || (os_version.dwPlatformId == VER_PLATFORM_WIN32s));
+}
+
+/*
+ * Return TRUE when running under Win32s.
+ */
+ int
+gui_is_win32s(void)
+{
+ return (os_version.dwPlatformId == VER_PLATFORM_WIN32s);
+}
+
+#ifdef FEAT_MENU
+/*
+ * Figure out how high the menu bar is at the moment.
+ */
+ static int
+gui_mswin_get_menu_height(
+ int fix_window) /* If TRUE, resize window if menu height changed */
+{
+ static int old_menu_height = -1;
+
+ RECT rc1, rc2;
+ int num;
+ int menu_height;
+
+ if (gui.menu_is_active)
+ num = GetMenuItemCount(s_menuBar);
+ else
+ num = 0;
+
+ if (num == 0)
+ menu_height = 0;
+ else
+ {
+ if (is_winnt_3()) /* for NT 3.xx */
+ {
+ if (gui.starting)
+ menu_height = GetSystemMetrics(SM_CYMENU);
+ else
+ {
+ RECT r1, r2;
+ int frameht = GetSystemMetrics(SM_CYFRAME);
+ int capht = GetSystemMetrics(SM_CYCAPTION);
+
+ /* get window rect of s_hwnd
+ * get client rect of s_hwnd
+ * get cap height
+ * subtract from window rect, the sum of client height,
+ * (if not maximized)frame thickness, and caption height.
+ */
+ GetWindowRect(s_hwnd, &r1);
+ GetClientRect(s_hwnd, &r2);
+ menu_height = r1.bottom - r1.top - (r2.bottom - r2.top
+ + 2 * frameht * (!IsZoomed(s_hwnd)) + capht);
+ }
+ }
+ else /* win95 and variants (NT 4.0, I guess) */
+ {
+ /*
+ * In case 'lines' is set in _vimrc/_gvimrc window width doesn't
+ * seem to have been set yet, so menu wraps in default window
+ * width which is very narrow. Instead just return height of a
+ * single menu item. Will still be wrong when the menu really
+ * should wrap over more than one line.
+ */
+ GetMenuItemRect(s_hwnd, s_menuBar, 0, &rc1);
+ if (gui.starting)
+ menu_height = rc1.bottom - rc1.top + 1;
+ else
+ {
+ GetMenuItemRect(s_hwnd, s_menuBar, num - 1, &rc2);
+ menu_height = rc2.bottom - rc1.top + 1;
+ }
+ }
+ }
+
+ if (fix_window && menu_height != old_menu_height)
+ {
+ old_menu_height = menu_height;
+ gui_set_shellsize(FALSE, FALSE);
+ }
+
+ return menu_height;
+}
+#endif /*FEAT_MENU*/
+
+
+/*
+ * Setup for the Intellimouse
+ */
+ static void
+init_mouse_wheel(void)
+{
+
+#ifndef SPI_GETWHEELSCROLLLINES
+# define SPI_GETWHEELSCROLLLINES 104
+#endif
+
+#define VMOUSEZ_CLASSNAME "MouseZ" /* hidden wheel window class */
+#define VMOUSEZ_TITLE "Magellan MSWHEEL" /* hidden wheel window title */
+#define VMSH_MOUSEWHEEL "MSWHEEL_ROLLMSG"
+#define VMSH_SCROLL_LINES "MSH_SCROLL_LINES_MSG"
+
+ HWND hdl_mswheel;
+ UINT msh_msgscrolllines;
+
+ msh_msgmousewheel = 0;
+ mouse_scroll_lines = 3; /* reasonable default */
+
+ if ((os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && os_version.dwMajorVersion >= 4)
+ || (os_version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
+ && ((os_version.dwMajorVersion == 4
+ && os_version.dwMinorVersion >= 10)
+ || os_version.dwMajorVersion >= 5)))
+ {
+ /* if NT 4.0+ (or Win98) get scroll lines directly from system */
+ SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
+ &mouse_scroll_lines, 0);
+ }
+ else if (os_version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
+ || (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && os_version.dwMajorVersion < 4))
+ { /*
+ * If Win95 or NT 3.51,
+ * try to find the hidden point32 window.
+ */
+ hdl_mswheel = FindWindow(VMOUSEZ_CLASSNAME, VMOUSEZ_TITLE);
+ if (hdl_mswheel)
+ {
+ msh_msgscrolllines = RegisterWindowMessage(VMSH_SCROLL_LINES);
+ if (msh_msgscrolllines)
+ {
+ mouse_scroll_lines = (int)SendMessage(hdl_mswheel,
+ msh_msgscrolllines, 0, 0);
+ msh_msgmousewheel = RegisterWindowMessage(VMSH_MOUSEWHEEL);
+ }
+ }
+ }
+}
+
+
+/* Intellimouse wheel handler */
+ static void
+_OnMouseWheel(
+ HWND hwnd,
+ short zDelta)
+{
+/* Treat a mouse wheel event as if it were a scroll request */
+ int i;
+ int size;
+ HWND hwndCtl;
+
+ if (curwin->w_scrollbars[SBAR_RIGHT].id != 0)
+ {
+ hwndCtl = curwin->w_scrollbars[SBAR_RIGHT].id;
+ size = curwin->w_scrollbars[SBAR_RIGHT].size;
+ }
+ else if (curwin->w_scrollbars[SBAR_LEFT].id != 0)
+ {
+ hwndCtl = curwin->w_scrollbars[SBAR_LEFT].id;
+ size = curwin->w_scrollbars[SBAR_LEFT].size;
+ }
+ else
+ return;
+
+ size = curwin->w_height;
+ if (mouse_scroll_lines == 0)
+ init_mouse_wheel();
+
+ if (mouse_scroll_lines > 0
+ && mouse_scroll_lines < (size > 2 ? size - 2 : 1))
+ {
+ for (i = mouse_scroll_lines; i > 0; --i)
+ _OnScroll(hwnd, hwndCtl, zDelta >= 0 ? SB_LINEUP : SB_LINEDOWN, 0);
+ }
+ else
+ _OnScroll(hwnd, hwndCtl, zDelta >= 0 ? SB_PAGEUP : SB_PAGEDOWN, 0);
+}
+
+#if 0 /* disabled, a gap appears below and beside the window, and the window
+ can be moved (in a strange way) */
+/*
+ * Even though we have _DuringSizing() which makes the rubber band a valid
+ * size, we need this for when the user maximises the window.
+ * TODO: Doesn't seem to adjust the width though for some reason.
+ */
+ static BOOL
+_OnWindowPosChanging(
+ HWND hwnd,
+ LPWINDOWPOS lpwpos)
+{
+ RECT workarea_rect;
+
+ if (!(lpwpos->flags & SWP_NOSIZE))
+ {
+ if (IsMaximized(hwnd)
+ && (os_version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
+ || (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && os_version.dwMajorVersion >= 4)))
+ {
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &workarea_rect, 0);
+ lpwpos->x = workarea_rect.left;
+ lpwpos->y = workarea_rect.top;
+ lpwpos->cx = workarea_rect.right - workarea_rect.left;
+ lpwpos->cy = workarea_rect.bottom - workarea_rect.top;
+ }
+ gui_mswin_get_valid_dimensions(lpwpos->cx, lpwpos->cy,
+ &lpwpos->cx, &lpwpos->cy);
+ }
+ return 0;
+}
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+ static void
+_OnWindowPosChanged(
+ HWND hwnd,
+ const LPWINDOWPOS lpwpos)
+{
+ static int x = 0, y = 0, cx = 0, cy = 0;
+
+ if (WSInitialized && (lpwpos->x != x || lpwpos->y != y
+ || lpwpos->cx != cx || lpwpos->cy != cy))
+ {
+ x = lpwpos->x;
+ y = lpwpos->y;
+ cx = lpwpos->cx;
+ cy = lpwpos->cy;
+ netbeans_frame_moved(x, y);
+ }
+ /* Allow to send WM_SIZE and WM_MOVE */
+ FORWARD_WM_WINDOWPOSCHANGED(hwnd, lpwpos, MyWindowProc);
+}
+#endif
+
+ static int
+_DuringSizing(
+ HWND hwnd,
+ UINT fwSide,
+ LPRECT lprc)
+{
+ int w, h;
+ int valid_w, valid_h;
+ int w_offset, h_offset;
+
+ w = lprc->right - lprc->left;
+ h = lprc->bottom - lprc->top;
+ gui_mswin_get_valid_dimensions(w, h, &valid_w, &valid_h);
+ w_offset = w - valid_w;
+ h_offset = h - valid_h;
+
+ if (fwSide == WMSZ_LEFT || fwSide == WMSZ_TOPLEFT
+ || fwSide == WMSZ_BOTTOMLEFT)
+ lprc->left += w_offset;
+ else if (fwSide == WMSZ_RIGHT || fwSide == WMSZ_TOPRIGHT
+ || fwSide == WMSZ_BOTTOMRIGHT)
+ lprc->right -= w_offset;
+
+ if (fwSide == WMSZ_TOP || fwSide == WMSZ_TOPLEFT
+ || fwSide == WMSZ_TOPRIGHT)
+ lprc->top += h_offset;
+ else if (fwSide == WMSZ_BOTTOM || fwSide == WMSZ_BOTTOMLEFT
+ || fwSide == WMSZ_BOTTOMRIGHT)
+ lprc->bottom -= h_offset;
+ return TRUE;
+}
+
+
+
+ static LRESULT CALLBACK
+_WndProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ /*
+ TRACE("WndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n",
+ hwnd, uMsg, wParam, lParam);
+ */
+
+ HandleMouseHide(uMsg, lParam);
+
+ s_uMsg = uMsg;
+ s_wParam = wParam;
+ s_lParam = lParam;
+
+ switch (uMsg)
+ {
+ HANDLE_MSG(hwnd, WM_DEADCHAR, _OnDeadChar);
+ HANDLE_MSG(hwnd, WM_SYSDEADCHAR, _OnDeadChar);
+ /* HANDLE_MSG(hwnd, WM_ACTIVATE, _OnActivate); */
+ HANDLE_MSG(hwnd, WM_CLOSE, _OnClose);
+ /* HANDLE_MSG(hwnd, WM_COMMAND, _OnCommand); */
+ HANDLE_MSG(hwnd, WM_DESTROY, _OnDestroy);
+ HANDLE_MSG(hwnd, WM_DROPFILES, _OnDropFiles);
+ HANDLE_MSG(hwnd, WM_HSCROLL, _OnScroll);
+ HANDLE_MSG(hwnd, WM_KILLFOCUS, _OnKillFocus);
+#ifdef FEAT_MENU
+ HANDLE_MSG(hwnd, WM_COMMAND, _OnMenu);
+#endif
+ /* HANDLE_MSG(hwnd, WM_MOVE, _OnMove); */
+ /* HANDLE_MSG(hwnd, WM_NCACTIVATE, _OnNCActivate); */
+ HANDLE_MSG(hwnd, WM_SETFOCUS, _OnSetFocus);
+ HANDLE_MSG(hwnd, WM_SIZE, _OnSize);
+ /* HANDLE_MSG(hwnd, WM_SYSCOMMAND, _OnSysCommand); */
+ /* HANDLE_MSG(hwnd, WM_SYSKEYDOWN, _OnAltKey); */
+ HANDLE_MSG(hwnd, WM_VSCROLL, _OnScroll);
+ // HANDLE_MSG(hwnd, WM_WINDOWPOSCHANGING, _OnWindowPosChanging);
+ HANDLE_MSG(hwnd, WM_ACTIVATEAPP, _OnActivateApp);
+#ifdef FEAT_NETBEANS_INTG
+ HANDLE_MSG(hwnd, WM_WINDOWPOSCHANGED, _OnWindowPosChanged);
+#endif
+
+ case WM_QUERYENDSESSION: /* System wants to go down. */
+ gui_shell_closed(); /* Will exit when no changed buffers. */
+ return FALSE; /* Do NOT allow system to go down. */
+
+ case WM_ENDSESSION:
+ if (wParam) /* system only really goes down when wParam is TRUE */
+ _OnEndSession();
+ break;
+
+ case WM_CHAR:
+ /* Don't use HANDLE_MSG() for WM_CHAR, it truncates wParam to a single
+ * byte while we want the UTF-16 character value. */
+ _OnChar(hwnd, wParam, (int)(short)LOWORD(lParam));
+ return 0L;
+
+ case WM_SYSCHAR:
+ /*
+ * if 'winaltkeys' is "no", or it's "menu" and it's not a menu
+ * shortcut key, handle like a typed ALT key, otherwise call Windows
+ * ALT key handling.
+ */
+#ifdef FEAT_MENU
+ if ( !gui.menu_is_active
+ || p_wak[0] == 'n'
+ || (p_wak[0] == 'm' && !gui_is_menu_shortcut((int)wParam))
+ )
+#endif
+ {
+ _OnSysChar(hwnd, wParam, (int)(short)LOWORD(lParam));
+ return 0L;
+ }
+#ifdef FEAT_MENU
+ else
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+#endif
+
+ case WM_SYSKEYUP:
+#ifdef FEAT_MENU
+ /* This used to be done only when menu is active: ALT key is used for
+ * that. But that caused problems when menu is disabled and using
+ * Alt-Tab-Esc: get into a strange state where no mouse-moved events
+ * are received, mouse pointer remains hidden. */
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+#else
+ return 0;
+#endif
+
+ case WM_SIZING: /* HANDLE_MSG doesn't seem to handle this one */
+ return _DuringSizing(hwnd, (UINT)wParam, (LPRECT)lParam);
+
+ case WM_MOUSEWHEEL:
+ _OnMouseWheel(hwnd, HIWORD(wParam));
+ break;
+
+#ifdef FEAT_TOOLBAR
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->code)
+ {
+ case TTN_NEEDTEXT:
+ {
+ LPTOOLTIPTEXT lpttt;
+ UINT idButton;
+ int idx;
+ vimmenu_T *pMenu;
+
+ lpttt = (LPTOOLTIPTEXT)lParam;
+ idButton = (UINT) lpttt->hdr.idFrom;
+ pMenu = gui_mswin_find_menu(root_menu, idButton);
+ if (pMenu)
+ {
+ idx = MENU_INDEX_TIP;
+ if (pMenu->strings[idx])
+ {
+ lpttt->hinst = NULL; /* string, not resource */
+ lpttt->lpszText = pMenu->strings[idx];
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+#if defined(MENUHINTS) && defined(FEAT_MENU)
+ case WM_MENUSELECT:
+ if (((UINT) HIWORD(wParam)
+ & (0xffff ^ (MF_MOUSESELECT + MF_BITMAP + MF_POPUP)))
+ == MF_HILITE
+ && (State & CMDLINE) == 0)
+ {
+ UINT idButton;
+ vimmenu_T *pMenu;
+ static int did_menu_tip = FALSE;
+
+ if (did_menu_tip)
+ {
+ msg_clr_cmdline();
+ setcursor();
+ out_flush();
+ did_menu_tip = FALSE;
+ }
+
+ idButton = (UINT)LOWORD(wParam);
+ pMenu = gui_mswin_find_menu(root_menu, idButton);
+ if (pMenu != NULL && pMenu->strings[MENU_INDEX_TIP] != 0
+ && GetMenuState(s_menuBar, pMenu->id, MF_BYCOMMAND) != -1)
+ {
+ msg(pMenu->strings[MENU_INDEX_TIP]);
+ setcursor();
+ out_flush();
+ did_menu_tip = TRUE;
+ }
+ }
+ break;
+#endif
+ case WM_NCHITTEST:
+ {
+ LRESULT result;
+ int x, y;
+ int xPos = GET_X_LPARAM(lParam);
+
+ result = MyWindowProc(hwnd, uMsg, wParam, lParam);
+ if (result == HTCLIENT)
+ {
+ gui_mch_get_winpos(&x, &y);
+ xPos -= x;
+
+ if (xPos < 48) /* <VN> TODO should use system metric? */
+ return HTBOTTOMLEFT;
+ else
+ return HTBOTTOMRIGHT;
+ }
+ else
+ return result;
+ }
+ /* break; notreached */
+
+#ifdef FEAT_MBYTE_IME
+ case WM_IME_NOTIFY:
+ if (!_OnImeNotify(hwnd, (DWORD)wParam, (DWORD)lParam))
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+ break;
+ case WM_IME_COMPOSITION:
+ if (!_OnImeComposition(hwnd, wParam, lParam))
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+ break;
+#endif
+
+ default:
+ if (uMsg == msh_msgmousewheel && msh_msgmousewheel != 0)
+ { /* handle MSH_MOUSEWHEEL messages for Intellimouse */
+ _OnMouseWheel(hwnd, HIWORD(wParam));
+ break;
+ }
+#ifdef MSWIN_FIND_REPLACE
+ else
+ if (uMsg == s_findrep_msg && s_findrep_msg != 0)
+ {
+ _OnFindRepl();
+ }
+#endif
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ return 1;
+}
+
+/*
+ * End of call-back routines
+ */
+
+/* parent window, if specified with -P */
+HWND vim_parent_hwnd = NULL;
+
+ static BOOL CALLBACK
+FindWindowTitle(HWND hwnd, LPARAM lParam)
+{
+ char buf[2048];
+ char *title = (char *)lParam;
+
+ if (GetWindowText(hwnd, buf, sizeof(buf)))
+ {
+ if (strstr(buf, title) != NULL)
+ {
+ /* Found it. Store the window ref. and quit searching. */
+ vim_parent_hwnd = FindWindowEx(hwnd, NULL, "MDIClient", NULL);
+ return FALSE;
+ }
+ }
+ return TRUE; /* continue searching */
+}
+
+/*
+ * Invoked for '-P "title"' argument: search for parent application to open
+ * our window in.
+ */
+ void
+gui_mch_set_parent(char *title)
+{
+ EnumWindows(FindWindowTitle, (LPARAM)title);
+ if (vim_parent_hwnd == NULL)
+ {
+ EMSG2(_("E671: Cannot find window title \"%s\""), title);
+ mch_exit(2);
+ }
+}
+
+ static void
+ole_error(char *arg)
+{
+ EMSG2(_("E243: Argument not supported: \"-%s\"; Use the OLE version."),
+ arg);
+}
+
+/*
+ * Parse the GUI related command-line arguments. Any arguments used are
+ * deleted from argv, and *argc is decremented accordingly. This is called
+ * when vim is started, whether or not the GUI has been started.
+ */
+ void
+gui_mch_prepare(int *argc, char **argv)
+{
+ int silent = FALSE;
+ int idx;
+
+ /* Check for special OLE command line parameters */
+ if ((*argc == 2 || *argc == 3) && (argv[1][0] == '-' || argv[1][0] == '/'))
+ {
+ /* Check for a "-silent" argument first. */
+ if (*argc == 3 && STRICMP(argv[1] + 1, "silent") == 0
+ && (argv[2][0] == '-' || argv[2][0] == '/'))
+ {
+ silent = TRUE;
+ idx = 2;
+ }
+ else
+ idx = 1;
+
+ /* Register Vim as an OLE Automation server */
+ if (STRICMP(argv[idx] + 1, "register") == 0)
+ {
+#ifdef FEAT_OLE
+ RegisterMe(silent);
+ mch_exit(0);
+#else
+ if (!silent)
+ ole_error("register");
+ mch_exit(2);
+#endif
+ }
+
+ /* Unregister Vim as an OLE Automation server */
+ if (STRICMP(argv[idx] + 1, "unregister") == 0)
+ {
+#ifdef FEAT_OLE
+ UnregisterMe(!silent);
+ mch_exit(0);
+#else
+ if (!silent)
+ ole_error("unregister");
+ mch_exit(2);
+#endif
+ }
+
+ /* Ignore an -embedding argument. It is only relevant if the
+ * application wants to treat the case when it is started manually
+ * differently from the case where it is started via automation (and
+ * we don't).
+ */
+ if (STRICMP(argv[idx] + 1, "embedding") == 0)
+ {
+#ifdef FEAT_OLE
+ *argc = 1;
+#else
+ ole_error("embedding");
+ mch_exit(2);
+#endif
+ }
+ }
+
+#ifdef FEAT_OLE
+ {
+ int bDoRestart = FALSE;
+
+ InitOLE(&bDoRestart);
+ /* automatically exit after registering */
+ if (bDoRestart)
+ mch_exit(0);
+ }
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+ {
+ /* stolen from gui_x11.x */
+ int arg;
+
+ for (arg = 1; arg < *argc; arg++)
+ if (strncmp("-nb", argv[arg], 3) == 0)
+ {
+ usingNetbeans++;
+ netbeansArg = argv[arg];
+ mch_memmove(&argv[arg], &argv[arg + 1],
+ (--*argc - arg) * sizeof(char *));
+ argv[*argc] = NULL;
+ break; /* enough? */
+ }
+
+ if (usingNetbeans)
+ {
+ WSADATA wsaData;
+ int wsaerr;
+
+ /* Init WinSock */
+ wsaerr = WSAStartup(MAKEWORD(2, 2), &wsaData);
+ if (wsaerr == 0)
+ WSInitialized = TRUE;
+ }
+ }
+#endif
+
+ /* get the OS version info */
+ os_version.dwOSVersionInfoSize = sizeof(os_version);
+ GetVersionEx(&os_version); /* this call works on Win32s, Win95 and WinNT */
+
+ /* try and load the user32.dll library and get the entry points for
+ * multi-monitor-support. */
+ if ((user32_lib = LoadLibrary("User32.dll")) != NULL)
+ {
+ pMonitorFromWindow = (TMonitorFromWindow)GetProcAddress(user32_lib,
+ "MonitorFromWindow");
+
+ /* there are ...A and ...W version of GetMonitorInfo - looking at
+ * winuser.h, they have exactly the same declaration. */
+ pGetMonitorInfo = (TGetMonitorInfo)GetProcAddress(user32_lib,
+ "GetMonitorInfoA");
+ }
+}
+
+/*
+ * Initialise the GUI. Create all the windows, set up all the call-backs
+ * etc.
+ */
+ int
+gui_mch_init(void)
+{
+ const char szVimWndClass[] = VIM_CLASS;
+ const char szTextAreaClass[] = "VimTextArea";
+ WNDCLASS wndclass;
+#ifdef FEAT_MBYTE
+ const WCHAR szVimWndClassW[] = VIM_CLASSW;
+ WNDCLASSW wndclassw;
+#endif
+#ifdef GLOBAL_IME
+ ATOM atom;
+#endif
+
+ /* Display any pending error messages */
+ display_errors();
+
+ /* Return here if the window was already opened (happens when
+ * gui_mch_dialog() is called early). */
+ if (s_hwnd != NULL)
+ return OK;
+
+ /*
+ * Load the tearoff bitmap
+ */
+#ifdef FEAT_TEAROFF
+ s_htearbitmap = LoadBitmap(s_hinst, "IDB_TEAROFF");
+#endif
+
+ gui.scrollbar_width = GetSystemMetrics(SM_CXVSCROLL);
+ gui.scrollbar_height = GetSystemMetrics(SM_CYHSCROLL);
+#ifdef FEAT_MENU
+ gui.menu_height = 0; /* Windows takes care of this */
+#endif
+ gui.border_width = 0;
+
+ s_brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
+
+#ifdef FEAT_MBYTE
+ /* First try using the wide version, so that we can use any title.
+ * Otherwise only characters in the active codepage will work. */
+ if (GetClassInfoW(s_hinst, szVimWndClassW, &wndclassw) == 0)
+ {
+ wndclassw.style = 0;
+ wndclassw.lpfnWndProc = _WndProc;
+ wndclassw.cbClsExtra = 0;
+ wndclassw.cbWndExtra = 0;
+ wndclassw.hInstance = s_hinst;
+ wndclassw.hIcon = LoadIcon(wndclassw.hInstance, "IDR_VIM");
+ wndclassw.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclassw.hbrBackground = s_brush;
+ wndclassw.lpszMenuName = NULL;
+ wndclassw.lpszClassName = szVimWndClassW;
+
+ if ((
+#ifdef GLOBAL_IME
+ atom =
+#endif
+ RegisterClassW(&wndclassw)) == 0)
+ {
+ if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return FAIL;
+
+ /* Must be Windows 98, fall back to non-wide function. */
+ }
+ else
+ wide_WindowProc = TRUE;
+ }
+
+ if (!wide_WindowProc)
+#endif
+
+ if (GetClassInfo(s_hinst, szVimWndClass, &wndclass) == 0)
+ {
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = _WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = s_hinst;
+ wndclass.hIcon = LoadIcon(wndclass.hInstance, "IDR_VIM");
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = s_brush;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = szVimWndClass;
+
+ if ((
+#ifdef GLOBAL_IME
+ atom =
+#endif
+ RegisterClass(&wndclass)) == 0)
+ return FAIL;
+ }
+
+ if (vim_parent_hwnd != NULL)
+ {
+#ifdef HAVE_TRY_EXCEPT
+ __try
+ {
+#endif
+ /* Open inside the specified parent window.
+ * TODO: last argument should point to a CLIENTCREATESTRUCT
+ * structure. */
+ s_hwnd = CreateWindowEx(
+ WS_EX_MDICHILD,
+ szVimWndClass, "Vim MSWindows GUI",
+ WS_OVERLAPPEDWINDOW | WS_CHILD | WS_CLIPSIBLINGS | 0xC000,
+ gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x,
+ gui_win_y == -1 ? CW_USEDEFAULT : gui_win_y,
+ 100, /* Any value will do */
+ 100, /* Any value will do */
+ vim_parent_hwnd, NULL,
+ s_hinst, NULL);
+#ifdef HAVE_TRY_EXCEPT
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* NOP */
+ }
+#endif
+ if (s_hwnd == NULL)
+ {
+ EMSG(_("E672: Unable to open window inside MDI application"));
+ mch_exit(2);
+ }
+ }
+ else
+ /* Open toplevel window. */
+ s_hwnd = CreateWindow(
+ szVimWndClass, "Vim MSWindows GUI",
+ WS_OVERLAPPEDWINDOW,
+ gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x,
+ gui_win_y == -1 ? CW_USEDEFAULT : gui_win_y,
+ 100, /* Any value will do */
+ 100, /* Any value will do */
+ NULL, NULL,
+ s_hinst, NULL);
+
+ if (s_hwnd == NULL)
+ return FAIL;
+
+#ifdef GLOBAL_IME
+ global_ime_init(atom, s_hwnd);
+#endif
+#if defined(FEAT_MBYTE_IME) && defined(DYNAMIC_IME)
+ dyn_imm_load();
+#endif
+
+ /* Create the text area window */
+ if (GetClassInfo(s_hinst, szTextAreaClass, &wndclass) == 0)
+ {
+ wndclass.style = CS_OWNDC;
+ wndclass.lpfnWndProc = _TextAreaWndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = s_hinst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = NULL;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = szTextAreaClass;
+
+ if (RegisterClass(&wndclass) == 0)
+ return FAIL;
+ }
+ s_textArea = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ szTextAreaClass, "Vim text area",
+ WS_CHILD | WS_VISIBLE, 0, 0,
+ 100, /* Any value will do for now */
+ 100, /* Any value will do for now */
+ s_hwnd, NULL,
+ s_hinst, NULL);
+
+ if (s_textArea == NULL)
+ return FAIL;
+
+#ifdef FEAT_MENU
+ s_menuBar = CreateMenu();
+#endif
+ s_hdc = GetDC(s_textArea);
+
+#ifdef MSWIN16_FASTTEXT
+ SetBkMode(s_hdc, OPAQUE);
+#endif
+
+#ifdef FEAT_WINDOWS
+ DragAcceptFiles(s_hwnd, TRUE);
+#endif
+
+ /* Do we need to bother with this? */
+ /* m_fMouseAvail = GetSystemMetrics(SM_MOUSEPRESENT); */
+
+ /* Get background/foreground colors from the system */
+ gui_mch_def_colors();
+
+ /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
+ * file) */
+ set_normal_colors();
+
+ /*
+ * Check that none of the colors are the same as the background color.
+ * Then store the current values as the defaults.
+ */
+ gui_check_colors();
+ gui.def_norm_pixel = gui.norm_pixel;
+ gui.def_back_pixel = gui.back_pixel;
+
+ /* Get the colors for the highlight groups (gui_check_colors() might have
+ * changed them) */
+ highlight_gui_started();
+
+ /*
+ * Start out by adding the configured border width into the border offset
+ */
+ gui.border_offset = gui.border_width + 2; /*CLIENT EDGE*/
+
+ /*
+ * Set up for Intellimouse processing
+ */
+ init_mouse_wheel();
+
+ /*
+ * compute a couple of metrics used for the dialogs
+ */
+ get_dialog_font_metrics();
+#ifdef FEAT_TOOLBAR
+ /*
+ * Create the toolbar
+ */
+ initialise_toolbar();
+#endif
+#ifdef MSWIN_FIND_REPLACE
+ /*
+ * Initialise the dialog box stuff
+ */
+ s_findrep_msg = RegisterWindowMessage(FINDMSGSTRING);
+
+ /* Initialise the struct */
+ s_findrep_struct.lStructSize = sizeof(s_findrep_struct);
+ s_findrep_struct.lpstrFindWhat = alloc(MSWIN_FR_BUFSIZE);
+ s_findrep_struct.lpstrFindWhat[0] = NUL;
+ s_findrep_struct.lpstrReplaceWith = alloc(MSWIN_FR_BUFSIZE);
+ s_findrep_struct.lpstrReplaceWith[0] = NUL;
+ s_findrep_struct.wFindWhatLen = MSWIN_FR_BUFSIZE;
+ s_findrep_struct.wReplaceWithLen = MSWIN_FR_BUFSIZE;
+#endif
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ netbeans_w32_connect();
+#endif
+
+ return OK;
+}
+
+/*
+ * Get the size of the screen, taking position on multiple monitors into
+ * account (if supported).
+ */
+ static void
+get_work_area(RECT *spi_rect)
+{
+ _HMONITOR mon;
+ _MONITORINFO moninfo;
+
+ /* use these functions only if available */
+ if (pMonitorFromWindow != NULL && pGetMonitorInfo != NULL)
+ {
+ /* work out which monitor the window is on, and get *it's* work area */
+ mon = pMonitorFromWindow(s_hwnd, 1 /*MONITOR_DEFAULTTOPRIMARY*/);
+ if (mon != NULL)
+ {
+ moninfo.cbSize = sizeof(_MONITORINFO);
+ if (pGetMonitorInfo(mon, &moninfo))
+ {
+ *spi_rect = moninfo.rcWork;
+ return;
+ }
+ }
+ }
+ /* this is the old method... */
+ SystemParametersInfo(SPI_GETWORKAREA, 0, spi_rect, 0);
+}
+
+/*
+ * Set the size of the window to the given width and height in pixels.
+ */
+ void
+gui_mch_set_shellsize(int width, int height,
+ int min_width, int min_height, int base_width, int base_height)
+{
+ RECT workarea_rect;
+ int win_width, win_height;
+ int win_xpos, win_ypos;
+ WINDOWPLACEMENT wndpl;
+
+ /* try to keep window completely on screen */
+ /* get size of the screen work area (excludes taskbar, appbars) */
+ get_work_area(&workarea_rect);
+
+ /* get current posision of our window */
+ wndpl.length = sizeof(WINDOWPLACEMENT);
+ GetWindowPlacement(s_hwnd, &wndpl);
+
+ /* Resizing a maximized window looks very strange, unzoom it first.
+ * But don't do it when still starting up, it may have been requested in
+ * the shortcut. */
+ if (wndpl.showCmd == SW_SHOWMAXIMIZED && starting == 0)
+ {
+ ShowWindow(s_hwnd, SW_SHOWNORMAL);
+ /* Need to get the settings of the normal window. */
+ GetWindowPlacement(s_hwnd, &wndpl);
+ }
+
+ win_xpos = wndpl.rcNormalPosition.left;
+ win_ypos = wndpl.rcNormalPosition.top;
+
+ /* compute the size of the outside of the window */
+ win_width = width + GetSystemMetrics(SM_CXFRAME) * 2;
+ win_height = height + GetSystemMetrics(SM_CYFRAME) * 2
+ + GetSystemMetrics(SM_CYCAPTION)
+#ifdef FEAT_MENU
+ + gui_mswin_get_menu_height(FALSE)
+#endif
+ ;
+
+ /* if the window is going off the screen, move it on to the screen */
+ if (win_xpos + win_width > workarea_rect.right)
+ win_xpos = workarea_rect.right - win_width;
+
+ if (win_xpos < workarea_rect.left)
+ win_xpos = workarea_rect.left;
+
+ if (win_ypos + win_height > workarea_rect.bottom)
+ win_ypos = workarea_rect.bottom - win_height;
+
+ if (win_ypos < workarea_rect.top)
+ win_ypos = workarea_rect.top;
+
+ /* When the taskbar is placed on the left or top of the screen,
+ * SetWindowPlacement() adds its width or height automatically, compensate
+ * for that. When the offset is over 400 it's probably something else,
+ * skip it then (just in case). */
+ if (workarea_rect.left > 0 && workarea_rect.left < 400)
+ win_xpos -= workarea_rect.left;
+ if (workarea_rect.top > 0 && workarea_rect.top < 400)
+ win_ypos -= workarea_rect.top;
+
+ wndpl.rcNormalPosition.left = win_xpos;
+ wndpl.rcNormalPosition.right = win_xpos + win_width;
+ wndpl.rcNormalPosition.top = win_ypos;
+ wndpl.rcNormalPosition.bottom = win_ypos + win_height;
+
+ /* set window position - we should use SetWindowPlacement rather than
+ * SetWindowPos as the MSDN docs say the coord systems returned by
+ * these two are not compatible. */
+ SetWindowPlacement(s_hwnd, &wndpl);
+
+ SetActiveWindow(s_hwnd);
+ SetFocus(s_hwnd);
+
+#ifdef FEAT_MENU
+ /* Menu may wrap differently now */
+ gui_mswin_get_menu_height(!gui.starting);
+#endif
+}
+
+
+ void
+gui_mch_set_scrollbar_thumb(
+ scrollbar_T *sb,
+ long val,
+ long size,
+ long max)
+{
+ SCROLLINFO info;
+
+ sb->scroll_shift = 0;
+ while (max > 32767)
+ {
+ max = (max + 1) >> 1;
+ val >>= 1;
+ size >>= 1;
+ ++sb->scroll_shift;
+ }
+
+ if (sb->scroll_shift > 0)
+ ++size;
+
+ info.cbSize = sizeof(info);
+ info.fMask = SIF_POS | SIF_RANGE | SIF_PAGE;
+ info.nPos = val;
+ info.nMin = 0;
+ info.nMax = max;
+ info.nPage = size;
+ SetScrollInfo(sb->id, SB_CTL, &info, TRUE);
+}
+
+
+/*
+ * Set the current text font.
+ */
+ void
+gui_mch_set_font(GuiFont font)
+{
+ gui.currFont = font;
+}
+
+
+/*
+ * Set the current text foreground color.
+ */
+ void
+gui_mch_set_fg_color(guicolor_T color)
+{
+ gui.currFgColor = color;
+}
+
+/*
+ * Set the current text background color.
+ */
+ void
+gui_mch_set_bg_color(guicolor_T color)
+{
+ gui.currBgColor = color;
+}
+
+#if defined(FEAT_MBYTE) && defined(FEAT_MBYTE_IME)
+/*
+ * Multi-byte handling, originally by Sung-Hoon Baek.
+ * First static functions (no prototypes generated).
+ */
+#ifdef _MSC_VER
+# include <ime.h> /* Apparently not needed for Cygwin, MingW or Borland. */
+#endif
+#include <imm.h>
+
+/*
+ * display composition string(korean)
+ */
+ static void
+DisplayCompStringOpaque(char_u *s, int len)
+{
+ int OldBkMode = GetBkMode(s_hdc);
+
+ SetBkMode(s_hdc, OPAQUE);
+ gui_outstr_nowrap(s, len, GUI_MON_TRS_CURSOR,
+ (guicolor_T)0, (guicolor_T)0, 0);
+ SetBkMode(s_hdc, OldBkMode);
+}
+
+/*
+ * handle WM_IME_NOTIFY message
+ */
+ static LRESULT
+_OnImeNotify(HWND hWnd, DWORD dwCommand, DWORD dwData)
+{
+ LRESULT lResult = 0;
+ HIMC hImc;
+
+ if (!pImmGetContext || (hImc = pImmGetContext(hWnd)) == (HIMC)0)
+ return lResult;
+ switch (dwCommand)
+ {
+ case IMN_SETOPENSTATUS:
+ if (pImmGetOpenStatus(hImc))
+ {
+ pImmSetCompositionFont(hImc, &norm_logfont);
+ im_set_position(gui.row, gui.col);
+
+ /* Disable langmap */
+ State &= ~LANGMAP;
+ if (State & INSERT)
+ {
+#if defined(FEAT_WINDOWS) && defined(FEAT_KEYMAP)
+ /* Unshown 'keymap' in status lines */
+ if (curbuf->b_p_iminsert == B_IMODE_LMAP)
+ {
+ /* Save cursor position */
+ int old_row = gui.row;
+ int old_col = gui.col;
+
+ // This must be called here before
+ // status_redraw_curbuf(), otherwise the mode
+ // message may appear in the wrong position.
+ showmode();
+ status_redraw_curbuf();
+ update_screen(0);
+ /* Restore cursor position */
+ gui.row = old_row;
+ gui.col = old_col;
+ }
+#endif
+ }
+ }
+ gui_update_cursor(TRUE, FALSE);
+ lResult = 0;
+ break;
+ }
+ pImmReleaseContext(hWnd, hImc);
+ return lResult;
+}
+
+ static LRESULT
+_OnImeComposition(HWND hwnd, WPARAM dbcs, LPARAM param)
+{
+ char_u *ret;
+ int len;
+
+ if ((param & GCS_RESULTSTR) == 0) /* Composition unfinished. */
+ return 0;
+
+ ret = GetResultStr(hwnd, GCS_RESULTSTR, &len);
+ if (ret != NULL)
+ {
+ add_to_input_buf_csi(ret, len);
+ vim_free(ret);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * get the current composition string, in UCS-2; *lenp is the number of
+ * *lenp is the number of Unicode characters.
+ */
+ static short_u *
+GetCompositionString_inUCS2(HIMC hIMC, DWORD GCS, int *lenp)
+{
+ LONG ret;
+ LPWSTR wbuf = NULL;
+ char_u *buf;
+
+ if (!pImmGetContext)
+ return NULL; /* no imm32.dll */
+
+ /* Try Unicode; this'll always work on NT regardless of codepage. */
+ ret = pImmGetCompositionStringW(hIMC, GCS, NULL, 0);
+ if (ret == 0)
+ return NULL; /* empty */
+
+ if (ret > 0)
+ {
+ /* Allocate the requested buffer plus space for the NUL character. */
+ wbuf = (LPWSTR)alloc(ret + sizeof(WCHAR));
+ if (wbuf != NULL)
+ {
+ pImmGetCompositionStringW(hIMC, GCS, wbuf, ret);
+ *lenp = ret / sizeof(WCHAR);
+ }
+ return (short_u *)wbuf;
+ }
+
+ /* ret < 0; we got an error, so try the ANSI version. This'll work
+ * on 9x/ME, but only if the codepage happens to be set to whatever
+ * we're inputting. */
+ ret = pImmGetCompositionStringA(hIMC, GCS, NULL, 0);
+ if (ret <= 0)
+ return NULL; /* empty or error */
+
+ buf = alloc(ret);
+ if (buf == NULL)
+ return NULL;
+ pImmGetCompositionStringA(hIMC, GCS, buf, ret);
+
+ /* convert from codepage to UCS-2 */
+ MultiByteToWideChar_alloc(GetACP(), 0, buf, ret, &wbuf, lenp);
+ vim_free(buf);
+
+ return (short_u *)wbuf;
+}
+
+/*
+ * void GetResultStr()
+ *
+ * This handles WM_IME_COMPOSITION with GCS_RESULTSTR flag on.
+ * get complete composition string
+ */
+ static char_u *
+GetResultStr(HWND hwnd, int GCS, int *lenp)
+{
+ HIMC hIMC; /* Input context handle. */
+ short_u *buf = NULL;
+ char_u *convbuf = NULL;
+
+ if (!pImmGetContext || (hIMC = pImmGetContext(hwnd)) == (HIMC)0)
+ return NULL;
+
+ /* Reads in the composition string. */
+ buf = GetCompositionString_inUCS2(hIMC, GCS, lenp);
+ if (buf == NULL)
+ return NULL;
+
+ convbuf = ucs2_to_enc(buf, lenp);
+ pImmReleaseContext(hwnd, hIMC);
+ vim_free(buf);
+ return convbuf;
+}
+#endif
+
+/* For global functions we need prototypes. */
+#if (defined(FEAT_MBYTE) && defined(FEAT_MBYTE_IME)) || defined(PROTO)
+
+/*
+ * set font to IM.
+ */
+ void
+im_set_font(LOGFONT *lf)
+{
+ HIMC hImc;
+
+ if (pImmGetContext && (hImc = pImmGetContext(s_hwnd)) != (HIMC)0)
+ {
+ pImmSetCompositionFont(hImc, lf);
+ pImmReleaseContext(s_hwnd, hImc);
+ }
+}
+
+/*
+ * Notify cursor position to IM.
+ */
+ void
+im_set_position(int row, int col)
+{
+ HIMC hImc;
+
+ if (pImmGetContext && (hImc = pImmGetContext(s_hwnd)) != (HIMC)0)
+ {
+ COMPOSITIONFORM cfs;
+
+ cfs.dwStyle = CFS_POINT;
+ cfs.ptCurrentPos.x = FILL_X(col);
+ cfs.ptCurrentPos.y = FILL_Y(row);
+ MapWindowPoints(s_textArea, s_hwnd, &cfs.ptCurrentPos, 1);
+ pImmSetCompositionWindow(hImc, &cfs);
+
+ pImmReleaseContext(s_hwnd, hImc);
+ }
+}
+
+/*
+ * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
+ */
+ void
+im_set_active(int active)
+{
+ HIMC hImc;
+ static HIMC hImcOld = (HIMC)0;
+
+ if (pImmGetContext) /* if NULL imm32.dll wasn't loaded (yet) */
+ {
+ if (p_imdisable)
+ {
+ if (hImcOld == (HIMC)0)
+ {
+ hImcOld = pImmGetContext(s_hwnd);
+ if (hImcOld)
+ pImmAssociateContext(s_hwnd, (HIMC)0);
+ }
+ active = FALSE;
+ }
+ else if (hImcOld != (HIMC)0)
+ {
+ pImmAssociateContext(s_hwnd, hImcOld);
+ hImcOld = (HIMC)0;
+ }
+
+ hImc = pImmGetContext(s_hwnd);
+ if (hImc)
+ {
+ pImmSetOpenStatus(hImc, active);
+ pImmReleaseContext(s_hwnd, hImc);
+ }
+ }
+}
+
+/*
+ * Get IM status. When IM is on, return not 0. Else return 0.
+ */
+ int
+im_get_status()
+{
+ int status = 0;
+ HIMC hImc;
+
+ if (pImmGetContext && (hImc = pImmGetContext(s_hwnd)) != (HIMC)0)
+ {
+ status = pImmGetOpenStatus(hImc) ? 1 : 0;
+ pImmReleaseContext(s_hwnd, hImc);
+ }
+ return status;
+}
+
+#endif /* FEAT_MBYTE && FEAT_MBYTE_IME */
+
+#if defined(FEAT_MBYTE) && !defined(FEAT_MBYTE_IME) && defined(GLOBAL_IME)
+/* Win32 with GLOBAL IME */
+
+/*
+ * Notify cursor position to IM.
+ */
+ void
+im_set_position(int row, int col)
+{
+ /* Win32 with GLOBAL IME */
+ POINT p;
+
+ p.x = FILL_X(col);
+ p.y = FILL_Y(row);
+ MapWindowPoints(s_textArea, s_hwnd, &p, 1);
+ global_ime_set_position(&p);
+}
+
+/*
+ * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
+ */
+ void
+im_set_active(int active)
+{
+ global_ime_set_status(active);
+}
+
+/*
+ * Get IM status. When IM is on, return not 0. Else return 0.
+ */
+ int
+im_get_status()
+{
+ return global_ime_get_status();
+}
+#endif
+
+
+#ifdef FEAT_RIGHTLEFT
+/*
+ * What is this for? In the case where you are using Win98 or Win2K or later,
+ * and you are using a Hebrew font (or Arabic!), Windows does you a favor and
+ * reverses the string sent to the TextOut... family. This sucks, because we
+ * go to a lot of effort to do the right thing, and there doesn't seem to be a
+ * way to tell Windblows not to do this!
+ *
+ * The short of it is that this 'RevOut' only gets called if you are running
+ * one of the new, "improved" MS OSes, and only if you are running in
+ * 'rightleft' mode. It makes display take *slightly* longer, but not
+ * noticeably so.
+ */
+ static void
+RevOut( HDC s_hdc,
+ int col,
+ int row,
+ UINT foptions,
+ CONST RECT *pcliprect,
+ LPCTSTR text,
+ UINT len,
+ CONST INT *padding)
+{
+ int ix;
+ static int special = -1;
+
+ if (special == -1)
+ {
+ /* Check windows version: special treatment is needed if it is NT 5 or
+ * Win98 or higher. */
+ if ((os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && os_version.dwMajorVersion >= 5)
+ || (os_version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
+ && (os_version.dwMajorVersion > 4
+ || (os_version.dwMajorVersion == 4
+ && os_version.dwMinorVersion > 0))))
+ special = 1;
+ else
+ special = 0;
+ }
+
+ if (special)
+ for (ix = 0; ix < (int)len; ++ix)
+ ExtTextOut(s_hdc, col + TEXT_X(ix), row, foptions,
+ pcliprect, text + ix, 1, padding);
+ else
+ ExtTextOut(s_hdc, col, row, foptions, pcliprect, text, len, padding);
+}
+#endif
+
+ void
+gui_mch_draw_string(
+ int row,
+ int col,
+ char_u *text,
+ int len,
+ int flags)
+{
+ static int *padding = NULL;
+ static int pad_size = 0;
+ int i;
+ const RECT *pcliprect = NULL;
+ UINT foptions = 0;
+#ifdef FEAT_MBYTE
+ static WCHAR *unicodebuf = NULL;
+ static int *unicodepdy = NULL;
+ int unibuflen = 0;
+ int n = 0;
+#endif
+ HPEN hpen, old_pen;
+ int y;
+
+#ifndef MSWIN16_FASTTEXT
+ /*
+ * Italic and bold text seems to have an extra row of pixels at the bottom
+ * (below where the bottom of the character should be). If we draw the
+ * characters with a solid background, the top row of pixels in the
+ * character below will be overwritten. We can fix this by filling in the
+ * background ourselves, to the correct character proportions, and then
+ * writing the character in transparent mode. Still have a problem when
+ * the character is "_", which gets written on to the character below.
+ * New fix: set gui.char_ascent to -1. This shifts all characters up one
+ * pixel in their slots, which fixes the problem with the bottom row of
+ * pixels. We still need this code because otherwise the top row of pixels
+ * becomes a problem. - webb.
+ */
+ static HBRUSH hbr_cache[2] = {NULL, NULL};
+ static guicolor_T brush_color[2] = {INVALCOLOR, INVALCOLOR};
+ static int brush_lru = 0;
+ HBRUSH hbr;
+ RECT rc;
+
+ if (!(flags & DRAW_TRANSP))
+ {
+ /*
+ * Clear background first.
+ * Note: FillRect() excludes right and bottom of rectangle.
+ */
+ rc.left = FILL_X(col);
+ rc.top = FILL_Y(row);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int cell_len = 0;
+
+ /* Compute the length in display cells. */
+ for (n = 0; n < len; n += MB_BYTE2LEN(text[n]))
+ cell_len += (*mb_ptr2cells)(text + n);
+ rc.right = FILL_X(col + cell_len);
+ }
+ else
+#endif
+ rc.right = FILL_X(col + len);
+ rc.bottom = FILL_Y(row + 1);
+
+ /* Cache the created brush, that saves a lot of time. We need two:
+ * one for cursor background and one for the normal background. */
+ if (gui.currBgColor == brush_color[0])
+ {
+ hbr = hbr_cache[0];
+ brush_lru = 1;
+ }
+ else if (gui.currBgColor == brush_color[1])
+ {
+ hbr = hbr_cache[1];
+ brush_lru = 0;
+ }
+ else
+ {
+ if (hbr_cache[brush_lru] != NULL)
+ DeleteBrush(hbr_cache[brush_lru]);
+ hbr_cache[brush_lru] = CreateSolidBrush(gui.currBgColor);
+ brush_color[brush_lru] = gui.currBgColor;
+ hbr = hbr_cache[brush_lru];
+ brush_lru = !brush_lru;
+ }
+ FillRect(s_hdc, &rc, hbr);
+
+ SetBkMode(s_hdc, TRANSPARENT);
+
+ /*
+ * When drawing block cursor, prevent inverted character spilling
+ * over character cell (can happen with bold/italic)
+ */
+ if (flags & DRAW_CURSOR)
+ {
+ pcliprect = &rc;
+ foptions = ETO_CLIPPED;
+ }
+ }
+#else
+ /*
+ * The alternative would be to write the characters in opaque mode, but
+ * when the text is not exactly the same proportions as normal text, too
+ * big or too little a rectangle gets drawn for the background.
+ */
+ SetBkMode(s_hdc, OPAQUE);
+ SetBkColor(s_hdc, gui.currBgColor);
+#endif
+ SetTextColor(s_hdc, gui.currFgColor);
+ SelectFont(s_hdc, gui.currFont);
+
+ if (pad_size != Columns || padding == NULL || padding[0] != gui.char_width)
+ {
+ vim_free(padding);
+ pad_size = Columns;
+
+ padding = (int *)alloc(pad_size * sizeof(int));
+ if (padding != NULL)
+ for (i = 0; i < pad_size; i++)
+ padding[i] = gui.char_width;
+ }
+
+ /* On NT, tell the font renderer not to "help" us with Hebrew and Arabic
+ * text. This doesn't work in 9x, so we have to deal with it manually on
+ * those systems. */
+ if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ foptions |= ETO_IGNORELANGUAGE;
+
+ /*
+ * We have to provide the padding argument because italic and bold versions
+ * of fixed-width fonts are often one pixel or so wider than their normal
+ * versions.
+ * No check for DRAW_BOLD, Windows will have done it already.
+ */
+
+#ifdef FEAT_MBYTE
+ /* Check if there are any UTF-8 characters. If not, use normal text
+ * output to speed up output. */
+ if (enc_utf8)
+ for (n = 0; n < len; ++n)
+ if (text[n] >= 0x80)
+ break;
+
+ /* Check if the Unicode buffer exists and is big enough. Create it
+ * with the same lengt as the multi-byte string, the number of wide
+ * characters is always equal or smaller. */
+ if ((enc_utf8 || (enc_codepage > 0 && (int)GetACP() != enc_codepage))
+ && (unicodebuf == NULL || len > unibuflen))
+ {
+ vim_free(unicodebuf);
+ unicodebuf = (WCHAR *)alloc(len * sizeof(WCHAR));
+
+ vim_free(unicodepdy);
+ unicodepdy = (int *)alloc(len * sizeof(int));
+
+ unibuflen = len;
+ }
+
+ if (enc_utf8 && n < len && unicodebuf != NULL)
+ {
+ /* Output UTF-8 characters. Caller has already separated
+ * composing characters. */
+ int i = 0;
+ int clen; /* string length up to composing char */
+ int cells; /* cell width of string up to composing char */
+ int cw; /* width of current cell */
+
+ cells = 0;
+ for (clen = 0; i < len; )
+ {
+ unicodebuf[clen] = utf_ptr2char(text + i);
+ cw = utf_char2cells(unicodebuf[clen]);
+ if (cw > 2) /* don't use 4 for unprintable char */
+ cw = 1;
+ if (unicodepdy != NULL)
+ {
+ /* Use unicodepdy to make characters fit as we expect, even
+ * when the font uses different widths (e.g., bold character
+ * is wider). */
+ unicodepdy[clen] = cw * gui.char_width;
+ }
+ cells += cw;
+ i += utfc_ptr2len_check_len(text + i, len - i);
+ ++clen;
+ }
+ ExtTextOutW(s_hdc, TEXT_X(col), TEXT_Y(row),
+ foptions, pcliprect, unicodebuf, clen, unicodepdy);
+ len = cells; /* used for underlining */
+ }
+ else if (enc_codepage > 0 && (int)GetACP() != enc_codepage)
+ {
+ /* If we want to display codepage data, and the current CP is not the
+ * ANSI one, we need to go via Unicode. */
+ if (unicodebuf != NULL)
+ {
+ len = MultiByteToWideChar(enc_codepage,
+ MB_PRECOMPOSED,
+ (char *)text, len,
+ (LPWSTR)unicodebuf, unibuflen);
+ if (len != 0)
+ ExtTextOutW(s_hdc, TEXT_X(col), TEXT_Y(row),
+ foptions, pcliprect, unicodebuf, len, NULL);
+ }
+ }
+ else
+#endif
+ {
+#ifdef FEAT_RIGHTLEFT
+ /* If we can't use ETO_IGNORELANGUAGE, we can't tell Windows not to
+ * mess up RL text, so we have to draw it character-by-character.
+ * Only do this if RL is on, since it's slow. */
+ if (curwin->w_p_rl && !(foptions & ETO_IGNORELANGUAGE))
+ RevOut(s_hdc, TEXT_X(col), TEXT_Y(row),
+ foptions, pcliprect, (char *)text, len, padding);
+ else
+#endif
+ ExtTextOut(s_hdc, TEXT_X(col), TEXT_Y(row),
+ foptions, pcliprect, (char *)text, len, padding);
+ }
+
+ if (flags & DRAW_UNDERL)
+ {
+ hpen = CreatePen(PS_SOLID, 1, gui.currFgColor);
+ old_pen = SelectObject(s_hdc, hpen);
+ /* When p_linespace is 0, overwrite the bottom row of pixels.
+ * Otherwise put the line just below the character. */
+ y = FILL_Y(row + 1) - 1;
+#ifndef MSWIN16_FASTTEXT
+ if (p_linespace > 1)
+ y -= p_linespace - 1;
+#endif
+ MoveToEx(s_hdc, FILL_X(col), y, NULL);
+ /* Note: LineTo() excludes the last pixel in the line. */
+ LineTo(s_hdc, FILL_X(col + len), y);
+ DeleteObject(SelectObject(s_hdc, old_pen));
+ }
+}
+
+
+/*
+ * Output routines.
+ */
+
+/* Flush any output to the screen */
+ void
+gui_mch_flush(void)
+{
+# if defined(__BORLANDC__)
+ /*
+ * The GdiFlush declaration (in Borland C 5.01 <wingdi.h>) is not a
+ * prototype declaration.
+ * The compiler complains if __stdcall is not used in both declarations.
+ */
+ BOOL __stdcall GdiFlush(void);
+# endif
+
+ GdiFlush();
+}
+
+ static void
+clear_rect(RECT *rcp)
+{
+ HBRUSH hbr;
+
+ hbr = CreateSolidBrush(gui.back_pixel);
+ FillRect(s_hdc, rcp, hbr);
+ DeleteBrush(hbr);
+}
+
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Add a sub menu to the menu bar.
+ */
+ void
+gui_mch_add_menu(
+ vimmenu_T *menu,
+ int pos)
+{
+ vimmenu_T *parent = menu->parent;
+
+ menu->submenu_id = CreatePopupMenu();
+ menu->id = s_menu_id++;
+
+ if (menu_is_menubar(menu->name))
+ {
+ if (is_winnt_3())
+ {
+ InsertMenu((parent == NULL) ? s_menuBar : parent->submenu_id,
+ (UINT)pos, MF_POPUP | MF_STRING | MF_BYPOSITION,
+ (UINT)menu->submenu_id, (LPCTSTR) menu->name);
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ WCHAR *wn = NULL;
+ int n;
+
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+ /* 'encoding' differs from active codepage: convert menu name
+ * and use wide function */
+ wn = enc_to_ucs2(menu->name, NULL);
+ if (wn != NULL)
+ {
+ MENUITEMINFOW infow;
+
+ infow.cbSize = sizeof(infow);
+ infow.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID
+ | MIIM_SUBMENU;
+ infow.dwItemData = (DWORD)menu;
+ infow.wID = menu->id;
+ infow.fType = MFT_STRING;
+ infow.dwTypeData = wn;
+ infow.cch = wcslen(wn);
+ infow.hSubMenu = menu->submenu_id;
+ n = InsertMenuItemW((parent == NULL)
+ ? s_menuBar : parent->submenu_id,
+ (UINT)pos, TRUE, &infow);
+ vim_free(wn);
+ if (n == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ /* Failed, try using non-wide function. */
+ wn = NULL;
+ }
+ }
+
+ if (wn == NULL)
+#endif
+ {
+ MENUITEMINFO info;
+
+ info.cbSize = sizeof(info);
+ info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID | MIIM_SUBMENU;
+ info.dwItemData = (DWORD)menu;
+ info.wID = menu->id;
+ info.fType = MFT_STRING;
+ info.dwTypeData = (LPTSTR)menu->name;
+ info.cch = (UINT)STRLEN(menu->name);
+ info.hSubMenu = menu->submenu_id;
+ InsertMenuItem((parent == NULL)
+ ? s_menuBar : parent->submenu_id,
+ (UINT)pos, TRUE, &info);
+ }
+ }
+ }
+
+ /* Fix window size if menu may have wrapped */
+ if (parent == NULL)
+ gui_mswin_get_menu_height(!gui.starting);
+#ifdef FEAT_TEAROFF
+ else if (IsWindow(parent->tearoff_handle))
+ rebuild_tearoff(parent);
+#endif
+}
+
+ void
+gui_mch_show_popupmenu(vimmenu_T *menu)
+{
+ POINT mp;
+
+ (void)GetCursorPos((LPPOINT)&mp);
+ gui_mch_show_popupmenu_at(menu, (int)mp.x, (int)mp.y);
+}
+
+ void
+gui_make_popup(char_u *path_name)
+{
+ vimmenu_T *menu = gui_find_menu(path_name);
+
+ if (menu != NULL)
+ {
+ POINT p;
+
+ /* Find the position of the current cursor */
+ GetDCOrgEx(s_hdc, &p);
+ if (curwin != NULL)
+ {
+ p.x += TEXT_X(W_WINCOL(curwin) + curwin->w_wcol + 1);
+ p.y += TEXT_Y(W_WINROW(curwin) + curwin->w_wrow + 1);
+ }
+ msg_scroll = FALSE;
+ gui_mch_show_popupmenu_at(menu, (int)p.x, (int)p.y);
+ }
+}
+
+#if defined(FEAT_TEAROFF) || defined(PROTO)
+/*
+ * Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy and
+ * create it as a pseudo-"tearoff menu".
+ */
+ void
+gui_make_tearoff(char_u *path_name)
+{
+ vimmenu_T *menu = gui_find_menu(path_name);
+
+ /* Found the menu, so tear it off. */
+ if (menu != NULL)
+ gui_mch_tearoff(menu->dname, menu, 0xffffL, 0xffffL);
+}
+#endif
+
+/*
+ * Add a menu item to a menu
+ */
+ void
+gui_mch_add_menu_item(
+ vimmenu_T *menu,
+ int idx)
+{
+ vimmenu_T *parent = menu->parent;
+
+ menu->id = s_menu_id++;
+ menu->submenu_id = NULL;
+
+#ifdef FEAT_TEAROFF
+ if (STRNCMP(menu->name, TEAR_STRING, TEAR_LEN) == 0)
+ {
+ InsertMenu(parent->submenu_id, (UINT)idx, MF_BITMAP|MF_BYPOSITION,
+ (UINT)menu->id, (LPCTSTR) s_htearbitmap);
+ }
+ else
+#endif
+#ifdef FEAT_TOOLBAR
+ if (menu_is_toolbar(parent->name))
+ {
+ TBBUTTON newtb;
+
+ vim_memset(&newtb, 0, sizeof(newtb));
+ if (menu_is_separator(menu->name))
+ {
+ newtb.iBitmap = 0;
+ newtb.fsStyle = TBSTYLE_SEP;
+ }
+ else
+ {
+ newtb.iBitmap = get_toolbar_bitmap(menu);
+ newtb.fsStyle = TBSTYLE_BUTTON;
+ }
+ newtb.idCommand = menu->id;
+ newtb.fsState = TBSTATE_ENABLED;
+ newtb.iString = 0;
+ SendMessage(s_toolbarhwnd, TB_INSERTBUTTON, (WPARAM)idx,
+ (LPARAM)&newtb);
+ menu->submenu_id = (HMENU)-1;
+ }
+ else
+#endif
+ {
+#ifdef FEAT_MBYTE
+ WCHAR *wn = NULL;
+ int n;
+
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+ /* 'encoding' differs from active codepage: convert menu item name
+ * and use wide function */
+ wn = enc_to_ucs2(menu->name, NULL);
+ if (wn != NULL)
+ {
+ n = InsertMenuW(parent->submenu_id, (UINT)idx,
+ (menu_is_separator(menu->name)
+ ? MF_SEPARATOR : MF_STRING) | MF_BYPOSITION,
+ (UINT)menu->id, wn);
+ vim_free(wn);
+ if (n == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ /* Failed, try using non-wide function. */
+ wn = NULL;
+ }
+ }
+ if (wn == NULL)
+#endif
+ InsertMenu(parent->submenu_id, (UINT)idx,
+ (menu_is_separator(menu->name) ? MF_SEPARATOR : MF_STRING)
+ | MF_BYPOSITION,
+ (UINT)menu->id, (LPCTSTR)menu->name);
+#ifdef FEAT_TEAROFF
+ if (IsWindow(parent->tearoff_handle))
+ rebuild_tearoff(parent);
+#endif
+ }
+}
+
+/*
+ * Destroy the machine specific menu widget.
+ */
+ void
+gui_mch_destroy_menu(vimmenu_T *menu)
+{
+#ifdef FEAT_TOOLBAR
+ /*
+ * is this a toolbar button?
+ */
+ if (menu->submenu_id == (HMENU)-1)
+ {
+ int iButton;
+
+ iButton = (int)SendMessage(s_toolbarhwnd, TB_COMMANDTOINDEX,
+ (WPARAM)menu->id, 0);
+ SendMessage(s_toolbarhwnd, TB_DELETEBUTTON, (WPARAM)iButton, 0);
+ }
+ else
+#endif
+ {
+ if (menu->parent != NULL
+ && menu_is_popup(menu->parent->dname)
+ && menu->parent->submenu_id != NULL)
+ RemoveMenu(menu->parent->submenu_id, menu->id, MF_BYCOMMAND);
+ else
+ RemoveMenu(s_menuBar, menu->id, MF_BYCOMMAND);
+ if (menu->submenu_id != NULL)
+ DestroyMenu(menu->submenu_id);
+#ifdef FEAT_TEAROFF
+ if (IsWindow(menu->tearoff_handle))
+ DestroyWindow(menu->tearoff_handle);
+ if (menu->parent != NULL
+ && menu->parent->children != NULL
+ && IsWindow(menu->parent->tearoff_handle))
+ {
+ /* This menu must not show up when rebuilding the tearoff window. */
+ menu->modes = 0;
+ rebuild_tearoff(menu->parent);
+ }
+#endif
+ }
+}
+
+#ifdef FEAT_TEAROFF
+ static void
+rebuild_tearoff(vimmenu_T *menu)
+{
+ /*hackish*/
+ char_u tbuf[128];
+ RECT trect;
+ RECT rct;
+ RECT roct;
+ int x, y;
+
+ HWND thwnd = menu->tearoff_handle;
+
+ GetWindowText(thwnd, tbuf, 127);
+ if (GetWindowRect(thwnd, &trect)
+ && GetWindowRect(s_hwnd, &rct)
+ && GetClientRect(s_hwnd, &roct))
+ {
+ x = trect.left - rct.left;
+ y = (trect.top - rct.bottom + roct.bottom);
+ }
+ else
+ {
+ x = y = 0xffffL;
+ }
+ DestroyWindow(thwnd);
+ if (menu->children != NULL)
+ {
+ gui_mch_tearoff(tbuf, menu, x, y);
+ if (IsWindow(menu->tearoff_handle))
+ (void) SetWindowPos(menu->tearoff_handle,
+ NULL,
+ (int)trect.left,
+ (int)trect.top,
+ 0, 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+}
+#endif /* FEAT_TEAROFF */
+
+/*
+ * Make a menu either grey or not grey.
+ */
+ void
+gui_mch_menu_grey(
+ vimmenu_T *menu,
+ int grey)
+{
+#ifdef FEAT_TOOLBAR
+ /*
+ * is this a toolbar button?
+ */
+ if (menu->submenu_id == (HMENU)-1)
+ {
+ SendMessage(s_toolbarhwnd, TB_ENABLEBUTTON,
+ (WPARAM)menu->id, (LPARAM) MAKELONG((grey ? FALSE : TRUE), 0) );
+ }
+ else
+#endif
+ if (grey)
+ EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_GRAYED);
+ else
+ EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_ENABLED);
+
+#ifdef FEAT_TEAROFF
+ if ((menu->parent != NULL) && (IsWindow(menu->parent->tearoff_handle)))
+ {
+ WORD menuID;
+ HWND menuHandle;
+
+ /*
+ * A tearoff button has changed state.
+ */
+ if (menu->children == NULL)
+ menuID = (WORD)(menu->id);
+ else
+ menuID = (WORD)((DWORD)(menu->submenu_id) | (DWORD)0x8000);
+ menuHandle = GetDlgItem(menu->parent->tearoff_handle, menuID);
+ if (menuHandle)
+ EnableWindow(menuHandle, !grey);
+
+ }
+#endif
+}
+
+#endif /* FEAT_MENU */
+
+
+/* define some macros used to make the dialogue creation more readable */
+
+#define add_string(s) strcpy((LPSTR)p, s); (LPSTR)p += (strlen((LPSTR)p) + 1)
+#define add_word(x) *p++ = (x)
+#define add_byte(x) *((LPSTR)p)++ = (x)
+#define add_long(x) *((LPDWORD)p)++ = (x)
+
+#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
+/*
+ * stuff for dialogs
+ */
+
+/*
+ * The callback routine used by all the dialogs. Very simple. First,
+ * acknowledges the INITDIALOG message so that Windows knows to do standard
+ * dialog stuff (Return = default, Esc = cancel....) Second, if a button is
+ * pressed, return that button's ID - IDCANCEL (2), which is the button's
+ * number.
+ */
+ static LRESULT CALLBACK
+dialog_callback(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ if (message == WM_INITDIALOG)
+ {
+ CenterWindow(hwnd, GetWindow(hwnd, GW_OWNER));
+ /* Set focus to the dialog. Set the default button, if specified. */
+ (void)SetFocus(hwnd);
+ if (dialog_default_button > IDCANCEL)
+ (void)SetFocus(GetDlgItem(hwnd, dialog_default_button));
+ return FALSE;
+ }
+
+ if (message == WM_COMMAND)
+ {
+ int button = LOWORD(wParam);
+
+ /* Don't end the dialog if something was selected that was
+ * not a button.
+ */
+ if (button >= DLG_NONBUTTON_CONTROL)
+ return TRUE;
+
+ /* If the edit box exists, copy the string. */
+ if (s_textfield != NULL)
+ GetDlgItemText(hwnd, DLG_NONBUTTON_CONTROL + 2,
+ s_textfield, IOSIZE);
+
+ /*
+ * Need to check for IDOK because if the user just hits Return to
+ * accept the default value, some reason this is what we get.
+ */
+ if (button == IDOK)
+ {
+ if (dialog_default_button > IDCANCEL)
+ EndDialog(hwnd, dialog_default_button);
+ }
+ else
+ EndDialog(hwnd, button - IDCANCEL);
+ return TRUE;
+ }
+
+ if ((message == WM_SYSCOMMAND) && (wParam == SC_CLOSE))
+ {
+ EndDialog(hwnd, 0);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Create a dialog dynamically from the parameter strings.
+ * type = type of dialog (question, alert, etc.)
+ * title = dialog title. may be NULL for default title.
+ * message = text to display. Dialog sizes to accommodate it.
+ * buttons = '\n' separated list of button captions, default first.
+ * dfltbutton = number of default button.
+ *
+ * This routine returns 1 if the first button is pressed,
+ * 2 for the second, etc.
+ *
+ * 0 indicates Esc was pressed.
+ * -1 for unexpected error
+ *
+ * If stubbing out this fn, return 1.
+ */
+
+static const char_u *dlg_icons[] = /* must match names in resource file */
+{
+ "IDR_VIM",
+ "IDR_VIM_ERROR",
+ "IDR_VIM_ALERT",
+ "IDR_VIM_INFO",
+ "IDR_VIM_QUESTION"
+};
+
+#ifdef USE_SYSMENU_FONT
+/*
+ * Get Menu Font.
+ * Return OK or FAIL.
+ */
+ static int
+gui_w32_get_menu_font(LOGFONT *lf)
+{
+ NONCLIENTMETRICS nm;
+
+ nm.cbSize = sizeof(NONCLIENTMETRICS);
+ if (!SystemParametersInfo(
+ SPI_GETNONCLIENTMETRICS,
+ sizeof(NONCLIENTMETRICS),
+ &nm,
+ 0))
+ return FAIL;
+ *lf = nm.lfMenuFont;
+ return OK;
+}
+#endif
+
+ int
+gui_mch_dialog(
+ int type,
+ char_u *title,
+ char_u *message,
+ char_u *buttons,
+ int dfltbutton,
+ char_u *textfield)
+{
+ WORD *p, *pdlgtemplate, *pnumitems;
+ int numButtons;
+ int *buttonWidths, *buttonPositions;
+ int buttonYpos;
+ int nchar, i;
+ DWORD lStyle;
+ int dlgwidth = 0;
+ int dlgheight;
+ int editboxheight;
+ int horizWidth = 0;
+ int msgheight;
+ char_u *pstart;
+ char_u *pend;
+ char_u *tbuffer;
+ RECT rect;
+ HWND hwnd;
+ HDC hdc;
+ HFONT font, oldFont;
+ TEXTMETRIC fontInfo;
+ int fontHeight;
+ int textWidth, minButtonWidth, messageWidth;
+ int maxDialogWidth;
+ int vertical;
+ int dlgPaddingX;
+ int dlgPaddingY;
+#ifdef USE_SYSMENU_FONT
+ LOGFONT lfSysmenu;
+ int use_lfSysmenu = FALSE;
+#endif
+
+#ifndef NO_CONSOLE
+ /* Don't output anything in silent mode ("ex -s") */
+ if (silent_mode)
+ return dfltbutton; /* return default option */
+#endif
+
+ /* If there is no window yet, open it. */
+ if (s_hwnd == NULL && gui_mch_init() == FAIL)
+ return dfltbutton;
+
+ if ((type < 0) || (type > VIM_LAST_TYPE))
+ type = 0;
+
+ /* allocate some memory for dialog template */
+ /* TODO should compute this really*/
+ pdlgtemplate = p = (PWORD)LocalAlloc(LPTR, DLG_ALLOC_SIZE);
+
+ if (p == NULL)
+ return -1;
+
+ /*
+ * make a copy of 'buttons' to fiddle with it. complier grizzles because
+ * vim_strsave() doesn't take a const arg (why not?), so cast away the
+ * const.
+ */
+ tbuffer = vim_strsave(buttons);
+ if (tbuffer == NULL)
+ return -1;
+
+ --dfltbutton; /* Change from one-based to zero-based */
+
+ /* Count buttons */
+ numButtons = 1;
+ for (i = 0; tbuffer[i] != '\0'; i++)
+ {
+ if (tbuffer[i] == DLG_BUTTON_SEP)
+ numButtons++;
+ }
+ if (dfltbutton >= numButtons)
+ dfltbutton = -1;
+
+ /* Allocate array to hold the width of each button */
+ buttonWidths = (int *) lalloc(numButtons * sizeof(int), TRUE);
+ if (buttonWidths == NULL)
+ return -1;
+
+ /* Allocate array to hold the X position of each button */
+ buttonPositions = (int *) lalloc(numButtons * sizeof(int), TRUE);
+ if (buttonPositions == NULL)
+ return -1;
+
+ /*
+ * Calculate how big the dialog must be.
+ */
+ hwnd = GetDesktopWindow();
+ hdc = GetWindowDC(hwnd);
+#ifdef USE_SYSMENU_FONT
+ if (gui_w32_get_menu_font(&lfSysmenu) == OK)
+ {
+ font = CreateFontIndirect(&lfSysmenu);
+ use_lfSysmenu = TRUE;
+ }
+ else
+#endif
+ font = CreateFont(-DLG_FONT_POINT_SIZE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ VARIABLE_PITCH , DLG_FONT_NAME);
+ if (s_usenewlook)
+ {
+ oldFont = SelectFont(hdc, font);
+ dlgPaddingX = DLG_PADDING_X;
+ dlgPaddingY = DLG_PADDING_Y;
+ }
+ else
+ {
+ oldFont = SelectFont(hdc, GetStockObject(SYSTEM_FONT));
+ dlgPaddingX = DLG_OLD_STYLE_PADDING_X;
+ dlgPaddingY = DLG_OLD_STYLE_PADDING_Y;
+ }
+ GetTextMetrics(hdc, &fontInfo);
+ fontHeight = fontInfo.tmHeight;
+
+ /* Minimum width for horizontal button */
+ minButtonWidth = GetTextWidth(hdc, "Cancel", 6);
+
+ /* Maximum width of a dialog, if possible */
+ GetWindowRect(s_hwnd, &rect);
+ maxDialogWidth = rect.right - rect.left
+ - GetSystemMetrics(SM_CXFRAME) * 2;
+ if (maxDialogWidth < DLG_MIN_MAX_WIDTH)
+ maxDialogWidth = DLG_MIN_MAX_WIDTH;
+
+ /* Set dlgwidth to width of message */
+ pstart = message;
+ messageWidth = 0;
+ msgheight = 0;
+ do
+ {
+ pend = vim_strchr(pstart, DLG_BUTTON_SEP);
+ if (pend == NULL)
+ pend = pstart + STRLEN(pstart); /* Last line of message. */
+ msgheight += fontHeight;
+ textWidth = GetTextWidth(hdc, pstart, (int)(pend - pstart));
+ if (textWidth > messageWidth)
+ messageWidth = textWidth;
+ pstart = pend + 1;
+ } while (*pend != NUL);
+ dlgwidth = messageWidth;
+
+ /* Add width of icon to dlgwidth, and some space */
+ dlgwidth += DLG_ICON_WIDTH + 3 * dlgPaddingX;
+
+ if (msgheight < DLG_ICON_HEIGHT)
+ msgheight = DLG_ICON_HEIGHT;
+
+ /*
+ * Check button names. A long one will make the dialog wider.
+ */
+ vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
+ if (!vertical)
+ {
+ // Place buttons horizontally if they fit.
+ horizWidth = dlgPaddingX;
+ pstart = tbuffer;
+ i = 0;
+ do
+ {
+ pend = vim_strchr(pstart, DLG_BUTTON_SEP);
+ if (pend == NULL)
+ pend = pstart + STRLEN(pstart); // Last button name.
+ textWidth = GetTextWidth(hdc, pstart, (int)(pend - pstart));
+ if (textWidth < minButtonWidth)
+ textWidth = minButtonWidth;
+ textWidth += dlgPaddingX; /* Padding within button */
+ buttonWidths[i] = textWidth;
+ buttonPositions[i++] = horizWidth;
+ horizWidth += textWidth + dlgPaddingX; /* Pad between buttons */
+ pstart = pend + 1;
+ } while (*pend != NUL);
+
+ if (horizWidth > maxDialogWidth)
+ vertical = TRUE; // Too wide to fit on the screen.
+ else if (horizWidth > dlgwidth)
+ dlgwidth = horizWidth;
+ }
+
+ if (vertical)
+ {
+ // Stack buttons vertically.
+ pstart = tbuffer;
+ do
+ {
+ pend = vim_strchr(pstart, DLG_BUTTON_SEP);
+ if (pend == NULL)
+ pend = pstart + STRLEN(pstart); // Last button name.
+ textWidth = GetTextWidth(hdc, pstart, (int)(pend - pstart));
+ textWidth += dlgPaddingX; /* Padding within button */
+ textWidth += DLG_VERT_PADDING_X * 2; /* Padding around button */
+ if (textWidth > dlgwidth)
+ dlgwidth = textWidth;
+ pstart = pend + 1;
+ } while (*pend != NUL);
+ }
+
+ if (dlgwidth < DLG_MIN_WIDTH)
+ dlgwidth = DLG_MIN_WIDTH; /* Don't allow a really thin dialog!*/
+
+ /* start to fill in the dlgtemplate information. addressing by WORDs */
+ if (s_usenewlook)
+ lStyle = DS_MODALFRAME | WS_CAPTION |DS_3DLOOK| WS_VISIBLE |DS_SETFONT;
+ else
+ lStyle = DS_MODALFRAME | WS_CAPTION |DS_3DLOOK| WS_VISIBLE;
+
+ add_long(lStyle);
+ add_long(0); // (lExtendedStyle)
+ pnumitems = p; /*save where the number of items must be stored*/
+ add_word(0); // NumberOfItems(will change later)
+ add_word(10); // x
+ add_word(10); // y
+ add_word(PixelToDialogX(dlgwidth)); // cx
+
+ // Dialog height.
+ if (vertical)
+ dlgheight = msgheight + 2 * dlgPaddingY +
+ DLG_VERT_PADDING_Y + 2 * fontHeight * numButtons;
+ else
+ dlgheight = msgheight + 3 * dlgPaddingY + 2 * fontHeight;
+
+ // Dialog needs to be taller if contains an edit box.
+ editboxheight = fontHeight + dlgPaddingY + 4 * DLG_VERT_PADDING_Y;
+ if (textfield != NULL)
+ dlgheight += editboxheight;
+
+ add_word(PixelToDialogY(dlgheight));
+
+ add_word(0); // Menu
+ add_word(0); // Class
+
+ /* copy the title of the dialog */
+ nchar = nCopyAnsiToWideChar(p, (title ?
+ (LPSTR)title :
+ (LPSTR)("Vim "VIM_VERSION_MEDIUM)));
+ p += nchar;
+
+ if (s_usenewlook)
+ {
+ /* do the font, since DS_3DLOOK doesn't work properly */
+#ifdef USE_SYSMENU_FONT
+ if (use_lfSysmenu)
+ {
+ /* point size */
+ *p++ = -MulDiv(lfSysmenu.lfHeight, 72,
+ GetDeviceCaps(hdc, LOGPIXELSY));
+ nchar = nCopyAnsiToWideChar(p, TEXT(lfSysmenu.lfFaceName));
+ }
+ else
+#endif
+ {
+ *p++ = DLG_FONT_POINT_SIZE; // point size
+ nchar = nCopyAnsiToWideChar(p, TEXT(DLG_FONT_NAME));
+ }
+ p += nchar;
+ }
+
+ buttonYpos = msgheight + 2 * dlgPaddingY;
+
+ if (textfield != NULL)
+ buttonYpos += editboxheight;
+
+ pstart = tbuffer;
+ if (!vertical)
+ horizWidth = (dlgwidth - horizWidth) / 2; /* Now it's X offset */
+ for (i = 0; i < numButtons; i++)
+ {
+ /* get end of this button. */
+ for ( pend = pstart;
+ *pend && (*pend != DLG_BUTTON_SEP);
+ pend++)
+ ;
+
+ if (*pend)
+ *pend = '\0';
+
+ /*
+ * old NOTE:
+ * setting the BS_DEFPUSHBUTTON style doesn't work because Windows sets
+ * the focus to the first tab-able button and in so doing makes that
+ * the default!! Grrr. Workaround: Make the default button the only
+ * one with WS_TABSTOP style. Means user can't tab between buttons, but
+ * he/she can use arrow keys.
+ *
+ * new NOTE: BS_DEFPUSHBUTTON is required to be able to select the
+ * right buttun when hitting <Enter>. E.g., for the ":confirm quit"
+ * dialog. Also needed for when the textfield is the default control.
+ * It appears to work now (perhaps not on Win95?).
+ */
+ if (vertical)
+ {
+ p = add_dialog_element(p,
+ (i == dfltbutton
+ ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP,
+ PixelToDialogX(DLG_VERT_PADDING_X),
+ PixelToDialogY(buttonYpos /* TBK */
+ + 2 * fontHeight * i),
+ PixelToDialogX(dlgwidth - 2 * DLG_VERT_PADDING_X),
+ (WORD)(PixelToDialogY(2 * fontHeight) - 1),
+ (WORD)(IDCANCEL + 1 + i), (WORD)0x0080, pstart);
+ }
+ else
+ {
+ p = add_dialog_element(p,
+ (i == dfltbutton
+ ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP,
+ PixelToDialogX(horizWidth + buttonPositions[i]),
+ PixelToDialogY(buttonYpos), /* TBK */
+ PixelToDialogX(buttonWidths[i]),
+ (WORD)(PixelToDialogY(2 * fontHeight) - 1),
+ (WORD)(IDCANCEL + 1 + i), (WORD)0x0080, pstart);
+ }
+ pstart = pend + 1; /*next button*/
+ }
+ *pnumitems += numButtons;
+
+ /* Vim icon */
+ p = add_dialog_element(p, SS_ICON,
+ PixelToDialogX(dlgPaddingX),
+ PixelToDialogY(dlgPaddingY),
+ PixelToDialogX(DLG_ICON_WIDTH),
+ PixelToDialogY(DLG_ICON_HEIGHT),
+ DLG_NONBUTTON_CONTROL + 0, (WORD)0x0082,
+ dlg_icons[type]);
+
+ /* Dialog message */
+ p = add_dialog_element(p, SS_LEFT,
+ PixelToDialogX(2 * dlgPaddingX + DLG_ICON_WIDTH),
+ PixelToDialogY(dlgPaddingY),
+ (WORD)(PixelToDialogX(messageWidth) + 1),
+ PixelToDialogY(msgheight),
+ DLG_NONBUTTON_CONTROL + 1, (WORD)0x0082, message);
+
+ /* Edit box */
+ if (textfield != NULL)
+ {
+ p = add_dialog_element(p, ES_LEFT|ES_AUTOHSCROLL|WS_TABSTOP|WS_BORDER,
+ PixelToDialogX(2 * dlgPaddingX),
+ PixelToDialogY(2 * dlgPaddingY + msgheight),
+ PixelToDialogX(dlgwidth - 4 * dlgPaddingX),
+ PixelToDialogY(fontHeight + dlgPaddingY),
+ DLG_NONBUTTON_CONTROL + 2, (WORD)0x0081, textfield);
+ *pnumitems += 1;
+ }
+
+ *pnumitems += 2;
+
+ SelectFont(hdc, oldFont);
+ DeleteObject(font);
+ ReleaseDC(hwnd, hdc);
+
+ /* Let the dialog_callback() function know which button to make default
+ * If we have an edit box, make that the default. We also need to tell
+ * dialog_callback() if this dialog contains an edit box or not. We do
+ * this by setting s_textfield if it does.
+ */
+ if (textfield != NULL)
+ {
+ dialog_default_button = DLG_NONBUTTON_CONTROL + 2;
+ s_textfield = textfield;
+ }
+ else
+ {
+ dialog_default_button = IDCANCEL + 1 + dfltbutton;
+ s_textfield = NULL;
+ }
+
+ /* show the dialog box modally and get a return value */
+ nchar = (int)DialogBoxIndirect(
+ s_hinst,
+ (LPDLGTEMPLATE)pdlgtemplate,
+ s_hwnd,
+ (DLGPROC)dialog_callback);
+
+ LocalFree(LocalHandle(pdlgtemplate));
+ vim_free(tbuffer);
+ vim_free(buttonWidths);
+ vim_free(buttonPositions);
+
+ /* Focus back to our window (for when MDI is used). */
+ (void)SetFocus(s_hwnd);
+
+ return nchar;
+}
+
+#endif /* FEAT_GUI_DIALOG */
+/*
+ * Put a simple element (basic class) onto a dialog template in memory.
+ * return a pointer to where the next item should be added.
+ *
+ * parameters:
+ * lStyle = additional style flags
+ * (be careful, NT3.51 & Win32s will ignore the new ones)
+ * x,y = x & y positions IN DIALOG UNITS
+ * w,h = width and height IN DIALOG UNITS
+ * Id = ID used in messages
+ * clss = class ID, e.g 0x0080 for a button, 0x0082 for a static
+ * caption = usually text or resource name
+ *
+ * TODO: use the length information noted here to enable the dialog creation
+ * routines to work out more exactly how much memory they need to alloc.
+ */
+ static PWORD
+add_dialog_element(
+ PWORD p,
+ DWORD lStyle,
+ WORD x,
+ WORD y,
+ WORD w,
+ WORD h,
+ WORD Id,
+ WORD clss,
+ const char *caption)
+{
+ int nchar;
+
+ p = lpwAlign(p); /* Align to dword boundary*/
+ lStyle = lStyle | WS_VISIBLE | WS_CHILD;
+ *p++ = LOWORD(lStyle);
+ *p++ = HIWORD(lStyle);
+ *p++ = 0; // LOWORD (lExtendedStyle)
+ *p++ = 0; // HIWORD (lExtendedStyle)
+ *p++ = x;
+ *p++ = y;
+ *p++ = w;
+ *p++ = h;
+ *p++ = Id; //9 or 10 words in all
+
+ *p++ = (WORD)0xffff;
+ *p++ = clss; //2 more here
+
+ nchar = nCopyAnsiToWideChar(p, (LPSTR)caption); //strlen(caption)+1
+ p += nchar;
+
+ *p++ = 0; // advance pointer over nExtraStuff WORD - 2 more
+
+ return p; //total = 15+ (strlen(caption)) words
+ // = 30 + 2(strlen(caption) bytes reqd
+}
+
+
+/*
+ * Helper routine. Take an input pointer, return closest pointer that is
+ * aligned on a DWORD (4 byte) boundary. Taken from the Win32SDK samples.
+ */
+ static LPWORD
+lpwAlign(
+ LPWORD lpIn)
+{
+ ULONG ul;
+
+ ul = (ULONG)lpIn;
+ ul += 3;
+ ul >>= 2;
+ ul <<= 2;
+ return (LPWORD)ul;
+}
+
+/*
+ * Helper routine. Takes second parameter as Ansi string, copies it to first
+ * parameter as wide character (16-bits / char) string, and returns integer
+ * number of wide characters (words) in string (including the trailing wide
+ * char NULL). Partly taken from the Win32SDK samples.
+ */
+ static int
+nCopyAnsiToWideChar(
+ LPWORD lpWCStr,
+ LPSTR lpAnsiIn)
+{
+ int nChar = 0;
+#ifdef FEAT_MBYTE
+ int len = lstrlen(lpAnsiIn) + 1; /* include NUL character */
+ int i;
+ WCHAR *wn;
+
+ if (enc_codepage == 0 && (int)GetACP() != enc_codepage)
+ {
+ /* Not a codepage, use our own conversion function. */
+ wn = enc_to_ucs2(lpAnsiIn, NULL);
+ if (wn != NULL)
+ {
+ wcscpy(lpWCStr, wn);
+ nChar = wcslen(wn) + 1;
+ vim_free(wn);
+ }
+ }
+ if (nChar == 0)
+ /* Use Win32 conversion function. */
+ nChar = MultiByteToWideChar(
+ enc_codepage > 0 ? enc_codepage : CP_ACP,
+ MB_PRECOMPOSED,
+ lpAnsiIn, len,
+ lpWCStr, len);
+ for (i = 0; i < nChar; ++i)
+ if (lpWCStr[i] == (WORD)'\t') /* replace tabs with spaces */
+ lpWCStr[i] = (WORD)' ';
+#else
+ do
+ {
+ if (*lpAnsiIn == '\t')
+ *lpWCStr++ = (WORD)' ';
+ else
+ *lpWCStr++ = (WORD)*lpAnsiIn;
+ nChar++;
+ } while (*lpAnsiIn++);
+#endif
+
+ return nChar;
+}
+
+
+#ifdef FEAT_TEAROFF
+/*
+ * The callback function for all the modeless dialogs that make up the
+ * "tearoff menus" Very simple - forward button presses (to fool Vim into
+ * thinking its menus have been clicked), and go away when closed.
+ */
+ static LRESULT CALLBACK
+tearoff_callback(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ if (message == WM_INITDIALOG)
+ return (TRUE);
+
+ /* May show the mouse pointer again. */
+ HandleMouseHide(message, lParam);
+
+ if (message == WM_COMMAND)
+ {
+ if ((WORD)(LOWORD(wParam)) & 0x8000)
+ {
+ POINT mp;
+ RECT rect;
+
+ if (GetCursorPos(&mp) && GetWindowRect(hwnd, &rect))
+ {
+ (void)TrackPopupMenu(
+ (HMENU)(LOWORD(wParam) ^ 0x8000),
+ TPM_LEFTALIGN | TPM_LEFTBUTTON,
+ (int)rect.right - 8,
+ (int)mp.y,
+ (int)0, /*reserved param*/
+ s_hwnd,
+ NULL);
+ /*
+ * NOTE: The pop-up menu can eat the mouse up event.
+ * We deal with this in normal.c.
+ */
+ }
+ }
+ else
+ /* Pass on messages to the main Vim window */
+ PostMessage(s_hwnd, WM_COMMAND, LOWORD(wParam), 0);
+ /*
+ * Give main window the focus back: this is so after
+ * choosing a tearoff button you can start typing again
+ * straight away.
+ */
+ (void)SetFocus(s_hwnd);
+ return TRUE;
+ }
+ if ((message == WM_SYSCOMMAND) && (wParam == SC_CLOSE))
+ {
+ DestroyWindow(hwnd);
+ return TRUE;
+ }
+
+ /* When moved around, give main window the focus back. */
+ if (message == WM_EXITSIZEMOVE)
+ (void)SetActiveWindow(s_hwnd);
+
+ return FALSE;
+}
+#endif
+
+
+/*
+ * Decide whether to use the "new look" (small, non-bold font) or the "old
+ * look" (big, clanky font) for dialogs, and work out a few values for use
+ * later accordingly.
+ */
+ static void
+get_dialog_font_metrics(void)
+{
+ HDC hdc;
+ HFONT hfontTools = 0;
+ DWORD dlgFontSize;
+ SIZE size;
+#ifdef USE_SYSMENU_FONT
+ LOGFONT lfSysmenu;
+#endif
+
+ s_usenewlook = FALSE;
+
+ /*
+ * For NT3.51 and Win32s, we stick with the old look
+ * because it matches everything else.
+ */
+ if (!is_winnt_3())
+ {
+#ifdef USE_SYSMENU_FONT
+ if (gui_w32_get_menu_font(&lfSysmenu) == OK)
+ hfontTools = CreateFontIndirect(&lfSysmenu);
+ else
+#endif
+ hfontTools = CreateFont(-DLG_FONT_POINT_SIZE, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, VARIABLE_PITCH , DLG_FONT_NAME);
+
+ if (hfontTools)
+ {
+ hdc = GetDC(s_hwnd);
+ SelectObject(hdc, hfontTools);
+ /*
+ * GetTextMetrics() doesn't return the right value in
+ * tmAveCharWidth, so we have to figure out the dialog base units
+ * ourselves.
+ */
+ GetTextExtentPoint(hdc,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
+ 52, &size);
+ ReleaseDC(s_hwnd, hdc);
+
+ s_dlgfntwidth = (WORD)((size.cx / 26 + 1) / 2);
+ s_dlgfntheight = (WORD)size.cy;
+ s_usenewlook = TRUE;
+ }
+ }
+
+ if (!s_usenewlook)
+ {
+ dlgFontSize = GetDialogBaseUnits(); /* fall back to big old system*/
+ s_dlgfntwidth = LOWORD(dlgFontSize);
+ s_dlgfntheight = HIWORD(dlgFontSize);
+ }
+}
+
+#if defined(FEAT_MENU) && defined(FEAT_TEAROFF)
+/*
+ * Create a pseudo-"tearoff menu" based on the child
+ * items of a given menu pointer.
+ */
+ static void
+gui_mch_tearoff(
+ char_u *title,
+ vimmenu_T *menu,
+ int initX,
+ int initY)
+{
+ WORD *p, *pdlgtemplate, *pnumitems, *ptrueheight;
+ int template_len;
+ int nchar, textWidth, submenuWidth;
+ DWORD lStyle;
+ DWORD lExtendedStyle;
+ WORD dlgwidth;
+ WORD menuID;
+ vimmenu_T *pmenu;
+ vimmenu_T *the_menu = menu;
+ HWND hwnd;
+ HDC hdc;
+ HFONT font, oldFont;
+ int col, spaceWidth, len;
+ int columnWidths[2];
+ char_u *label, *text;
+ int acLen = 0;
+ int nameLen;
+ int padding0, padding1, padding2 = 0;
+ int sepPadding=0;
+#ifdef USE_SYSMENU_FONT
+ LOGFONT lfSysmenu;
+ int use_lfSysmenu = FALSE;
+#endif
+
+ /*
+ * If this menu is already torn off, move it to the mouse position.
+ */
+ if (IsWindow(menu->tearoff_handle))
+ {
+ POINT mp;
+ if (GetCursorPos((LPPOINT)&mp))
+ {
+ SetWindowPos(menu->tearoff_handle, NULL, mp.x, mp.y, 0, 0,
+ SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
+ }
+ return;
+ }
+
+ /*
+ * Create a new tearoff.
+ */
+ if (*title == MNU_HIDDEN_CHAR)
+ title++;
+
+ /* Allocate memory to store the dialog template. It's made bigger when
+ * needed. */
+ template_len = DLG_ALLOC_SIZE;
+ pdlgtemplate = p = (WORD *)LocalAlloc(LPTR, template_len);
+ if (p == NULL)
+ return;
+
+ hwnd = GetDesktopWindow();
+ hdc = GetWindowDC(hwnd);
+#ifdef USE_SYSMENU_FONT
+ if (gui_w32_get_menu_font(&lfSysmenu) == OK)
+ {
+ font = CreateFontIndirect(&lfSysmenu);
+ use_lfSysmenu = TRUE;
+ }
+ else
+#endif
+ font = CreateFont(-DLG_FONT_POINT_SIZE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ VARIABLE_PITCH , DLG_FONT_NAME);
+ if (s_usenewlook)
+ oldFont = SelectFont(hdc, font);
+ else
+ oldFont = SelectFont(hdc, GetStockObject(SYSTEM_FONT));
+
+ /* Calculate width of a single space. Used for padding columns to the
+ * right width. */
+ spaceWidth = GetTextWidth(hdc, " ", 1);
+
+ /* Figure out max width of the text column, the accelerator column and the
+ * optional submenu column. */
+ submenuWidth = 0;
+ for (col = 0; col < 2; col++)
+ {
+ columnWidths[col] = 0;
+ for (pmenu = menu->children; pmenu != NULL; pmenu = pmenu->next)
+ {
+ /* Use "dname" here to compute the width of the visible text. */
+ text = (col == 0) ? pmenu->dname : pmenu->actext;
+ if (text != NULL && *text != NUL)
+ {
+ textWidth = GetTextWidthEnc(hdc, text, (int)STRLEN(text));
+ if (textWidth > columnWidths[col])
+ columnWidths[col] = textWidth;
+ }
+ if (pmenu->children != NULL)
+ submenuWidth = TEAROFF_COLUMN_PADDING * spaceWidth;
+ }
+ }
+ if (columnWidths[1] == 0)
+ {
+ /* no accelerators */
+ if (submenuWidth != 0)
+ columnWidths[0] += submenuWidth;
+ else
+ columnWidths[0] += spaceWidth;
+ }
+ else
+ {
+ /* there is an accelerator column */
+ columnWidths[0] += TEAROFF_COLUMN_PADDING * spaceWidth;
+ columnWidths[1] += submenuWidth;
+ }
+
+ /*
+ * Now find the total width of our 'menu'.
+ */
+ textWidth = columnWidths[0] + columnWidths[1];
+ if (submenuWidth != 0)
+ {
+ submenuWidth = GetTextWidth(hdc, TEAROFF_SUBMENU_LABEL,
+ (int)STRLEN(TEAROFF_SUBMENU_LABEL));
+ textWidth += submenuWidth;
+ }
+ dlgwidth = GetTextWidthEnc(hdc, title, (int)STRLEN(title));
+ if (textWidth > dlgwidth)
+ dlgwidth = textWidth;
+ dlgwidth += 2 * TEAROFF_PADDING_X + TEAROFF_BUTTON_PAD_X;
+
+ /* W95 can't do thin dialogs, they look v. weird! */
+ if (mch_windows95() && dlgwidth < TEAROFF_MIN_WIDTH)
+ dlgwidth = TEAROFF_MIN_WIDTH;
+
+ /* start to fill in the dlgtemplate information. addressing by WORDs */
+ if (s_usenewlook)
+ lStyle = DS_MODALFRAME | WS_CAPTION| WS_SYSMENU |DS_SETFONT| WS_VISIBLE;
+ else
+ lStyle = DS_MODALFRAME | WS_CAPTION| WS_SYSMENU | WS_VISIBLE;
+
+ lExtendedStyle = WS_EX_TOOLWINDOW|WS_EX_STATICEDGE;
+ *p++ = LOWORD(lStyle);
+ *p++ = HIWORD(lStyle);
+ *p++ = LOWORD(lExtendedStyle);
+ *p++ = HIWORD(lExtendedStyle);
+ pnumitems = p; /* save where the number of items must be stored */
+ *p++ = 0; // NumberOfItems(will change later)
+ if (initX == 0xffffL)
+ *p++ = PixelToDialogX(gui_mch_get_mouse_x()); // x
+ else
+ *p++ = PixelToDialogX(initX); // x
+ if (initY == 0xffffL)
+ *p++ = PixelToDialogY(gui_mch_get_mouse_y()); // y
+ else
+ *p++ = PixelToDialogY(initY); // y
+ *p++ = PixelToDialogX(dlgwidth); // cx
+ ptrueheight = p;
+ *p++ = 0; // dialog height: changed later anyway
+ *p++ = 0; // Menu
+ *p++ = 0; // Class
+
+ /* copy the title of the dialog */
+ nchar = nCopyAnsiToWideChar(p, ((*title)
+ ? (LPSTR)title
+ : (LPSTR)("Vim "VIM_VERSION_MEDIUM)));
+ p += nchar;
+
+ if (s_usenewlook)
+ {
+ /* do the font, since DS_3DLOOK doesn't work properly */
+#ifdef USE_SYSMENU_FONT
+ if (use_lfSysmenu)
+ {
+ /* point size */
+ *p++ = -MulDiv(lfSysmenu.lfHeight, 72,
+ GetDeviceCaps(hdc, LOGPIXELSY));
+ nchar = nCopyAnsiToWideChar(p, TEXT(lfSysmenu.lfFaceName));
+ }
+ else
+#endif
+ {
+ *p++ = DLG_FONT_POINT_SIZE; // point size
+ nchar = nCopyAnsiToWideChar (p, TEXT(DLG_FONT_NAME));
+ }
+ p += nchar;
+ }
+
+ /*
+ * Loop over all the items in the menu.
+ * But skip over the tearbar.
+ */
+ if (STRCMP(menu->children->name, TEAR_STRING) == 0)
+ menu = menu->children->next;
+ else
+ menu = menu->children;
+ for ( ; menu != NULL; menu = menu->next)
+ {
+ if (menu->modes == 0) /* this menu has just been deleted */
+ continue;
+ if (menu_is_separator(menu->dname))
+ {
+ sepPadding += 3;
+ continue;
+ }
+
+ /* Check if there still is plenty of room in the template. Make it
+ * larger when needed. */
+ if (((char *)p - (char *)pdlgtemplate) + 1000 > template_len)
+ {
+ WORD *newp;
+
+ newp = (WORD *)LocalAlloc(LPTR, template_len + 4096);
+ if (newp != NULL)
+ {
+ template_len += 4096;
+ mch_memmove(newp, pdlgtemplate,
+ (char *)p - (char *)pdlgtemplate);
+ p = newp + (p - pdlgtemplate);
+ pnumitems = newp + (pnumitems - pdlgtemplate);
+ ptrueheight = newp + (ptrueheight - pdlgtemplate);
+ LocalFree(LocalHandle(pdlgtemplate));
+ pdlgtemplate = newp;
+ }
+ }
+
+ /* Figure out minimal length of this menu label. Use "name" for the
+ * actual text, "dname" for estimating the displayed size. "name"
+ * has "&a" for mnemonic and includes the accelerator. */
+ len = nameLen = (int)STRLEN(menu->name);
+ padding0 = (columnWidths[0] - GetTextWidthEnc(hdc, menu->dname,
+ (int)STRLEN(menu->dname))) / spaceWidth;
+ len += padding0;
+
+ if (menu->actext != NULL)
+ {
+ acLen = (int)STRLEN(menu->actext);
+ len += acLen;
+ textWidth = GetTextWidthEnc(hdc, menu->actext, acLen);
+ }
+ else
+ textWidth = 0;
+ padding1 = (columnWidths[1] - textWidth) / spaceWidth;
+ len += padding1;
+
+ if (menu->children == NULL)
+ {
+ padding2 = submenuWidth / spaceWidth;
+ len += padding2;
+ menuID = (WORD)(menu->id);
+ }
+ else
+ {
+ len += (int)STRLEN(TEAROFF_SUBMENU_LABEL);
+ menuID = (WORD)((DWORD)(menu->submenu_id) | (DWORD)0x8000);
+ }
+
+ /* Allocate menu label and fill it in */
+ text = label = alloc((unsigned)len + 1);
+ if (label == NULL)
+ break;
+
+ STRNCPY(text, menu->name, nameLen);
+ text[nameLen] = NUL;
+ text = vim_strchr(text, TAB); /* stop at TAB before actext */
+ if (text == NULL)
+ text = label + nameLen; /* no actext, use whole name */
+ while (padding0-- > 0)
+ *text++ = ' ';
+ if (menu->actext != NULL)
+ {
+ STRNCPY(text, menu->actext, acLen);
+ text += acLen;
+ }
+ while (padding1-- > 0)
+ *text++ = ' ';
+ if (menu->children != NULL)
+ {
+ STRCPY(text, TEAROFF_SUBMENU_LABEL);
+ text += STRLEN(TEAROFF_SUBMENU_LABEL);
+ }
+ else
+ {
+ while (padding2-- > 0)
+ *text++ = ' ';
+ }
+ *text = NUL;
+
+ /*
+ * BS_LEFT will just be ignored on Win32s/NT3.5x - on
+ * W95/NT4 it makes the tear-off look more like a menu.
+ */
+ p = add_dialog_element(p,
+ BS_PUSHBUTTON|BS_LEFT,
+ (WORD)PixelToDialogX(TEAROFF_PADDING_X),
+ (WORD)(sepPadding + 1 + 13 * (*pnumitems)),
+ (WORD)PixelToDialogX(dlgwidth - 2 * TEAROFF_PADDING_X),
+ (WORD)12,
+ menuID, (WORD)0x0080, label);
+ vim_free(label);
+ (*pnumitems)++;
+ }
+
+ *ptrueheight = (WORD)(sepPadding + 1 + 13 * (*pnumitems));
+
+
+ /* show modelessly */
+ the_menu->tearoff_handle = CreateDialogIndirect(
+ s_hinst,
+ (LPDLGTEMPLATE)pdlgtemplate,
+ s_hwnd,
+ (DLGPROC)tearoff_callback);
+
+ LocalFree(LocalHandle(pdlgtemplate));
+ SelectFont(hdc, oldFont);
+ DeleteObject(font);
+ ReleaseDC(hwnd, hdc);
+
+ /*
+ * Reassert ourselves as the active window. This is so that after creating
+ * a tearoff, the user doesn't have to click with the mouse just to start
+ * typing again!
+ */
+ (void)SetActiveWindow(s_hwnd);
+
+ /* make sure the right buttons are enabled */
+ force_menu_update = TRUE;
+}
+#endif
+
+#if defined(FEAT_TOOLBAR) || defined(PROTO)
+#include "gui_w32_rc.h"
+
+/* This not defined in older SDKs */
+# ifndef TBSTYLE_FLAT
+# define TBSTYLE_FLAT 0x0800
+# endif
+
+/*
+ * Create the toolbar, initially unpopulated.
+ * (just like the menu, there are no defaults, it's all
+ * set up through menu.vim)
+ */
+ static void
+initialise_toolbar(void)
+{
+ InitCommonControls();
+ s_toolbarhwnd = CreateToolbarEx(
+ s_hwnd,
+ WS_CHILD | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT,
+ 4000, //any old big number
+ 31, //number of images in inital bitmap
+ s_hinst,
+ IDR_TOOLBAR1, // id of initial bitmap
+ NULL,
+ 0, // initial number of buttons
+ TOOLBAR_BUTTON_WIDTH, //api guide is wrong!
+ TOOLBAR_BUTTON_HEIGHT,
+ TOOLBAR_BUTTON_WIDTH,
+ TOOLBAR_BUTTON_HEIGHT,
+ sizeof(TBBUTTON)
+ );
+
+ gui_mch_show_toolbar(vim_strchr(p_go, GO_TOOLBAR) != NULL);
+}
+
+ static int
+get_toolbar_bitmap(vimmenu_T *menu)
+{
+ int i = -1;
+
+ /*
+ * Check user bitmaps first, unless builtin is specified.
+ */
+ if (!is_winnt_3() && !menu->icon_builtin)
+ {
+ char_u fname[MAXPATHL];
+ HANDLE hbitmap = NULL;
+
+ if (menu->iconfile != NULL)
+ {
+ gui_find_iconfile(menu->iconfile, fname, "bmp");
+ hbitmap = LoadImage(
+ NULL,
+ fname,
+ IMAGE_BITMAP,
+ TOOLBAR_BUTTON_WIDTH,
+ TOOLBAR_BUTTON_HEIGHT,
+ LR_LOADFROMFILE |
+ LR_LOADMAP3DCOLORS
+ );
+ }
+
+ /*
+ * If the LoadImage call failed, or the "icon=" file
+ * didn't exist or wasn't specified, try the menu name
+ */
+ if (hbitmap == NULL
+ && (gui_find_bitmap(menu->name, fname, "bmp") == OK))
+ hbitmap = LoadImage(
+ NULL,
+ fname,
+ IMAGE_BITMAP,
+ TOOLBAR_BUTTON_WIDTH,
+ TOOLBAR_BUTTON_HEIGHT,
+ LR_LOADFROMFILE |
+ LR_LOADMAP3DCOLORS
+ );
+
+ if (hbitmap != NULL)
+ {
+ TBADDBITMAP tbAddBitmap;
+
+ tbAddBitmap.hInst = NULL;
+ tbAddBitmap.nID = (UINT)hbitmap;
+
+ i = (int)SendMessage(s_toolbarhwnd, TB_ADDBITMAP,
+ (WPARAM)1, (LPARAM)&tbAddBitmap);
+ /* i will be set to -1 if it fails */
+ }
+ }
+ if (i == -1 && menu->iconidx >= 0 && menu->iconidx < TOOLBAR_BITMAP_COUNT)
+ i = menu->iconidx;
+
+ return i;
+}
+#endif
+
+#if defined(FEAT_OLE) || defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Make the GUI window come to the foreground.
+ */
+ void
+gui_mch_set_foreground(void)
+{
+ if (IsIconic(s_hwnd))
+ SendMessage(s_hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
+ SetForegroundWindow(s_hwnd);
+}
+#endif
+
+#if defined(FEAT_MBYTE_IME) && defined(DYNAMIC_IME)
+ static void
+dyn_imm_load(void)
+{
+ hLibImm = LoadLibrary("imm32.dll");
+ if (hLibImm == NULL)
+ return;
+
+ pImmGetCompositionStringA
+ = (void *)GetProcAddress(hLibImm, "ImmGetCompositionStringA");
+ pImmGetCompositionStringW
+ = (void *)GetProcAddress(hLibImm, "ImmGetCompositionStringW");
+ pImmGetContext
+ = (void *)GetProcAddress(hLibImm, "ImmGetContext");
+ pImmAssociateContext
+ = (void *)GetProcAddress(hLibImm, "ImmAssociateContext");
+ pImmReleaseContext
+ = (void *)GetProcAddress(hLibImm, "ImmReleaseContext");
+ pImmGetOpenStatus
+ = (void *)GetProcAddress(hLibImm, "ImmGetOpenStatus");
+ pImmSetOpenStatus
+ = (void *)GetProcAddress(hLibImm, "ImmSetOpenStatus");
+ pImmGetCompositionFont
+ = (void *)GetProcAddress(hLibImm, "ImmGetCompositionFontA");
+ pImmSetCompositionFont
+ = (void *)GetProcAddress(hLibImm, "ImmSetCompositionFontA");
+ pImmSetCompositionWindow
+ = (void *)GetProcAddress(hLibImm, "ImmSetCompositionWindow");
+ pImmGetConversionStatus
+ = (void *)GetProcAddress(hLibImm, "ImmGetConversionStatus");
+
+ if ( pImmGetCompositionStringA == NULL
+ || pImmGetCompositionStringW == NULL
+ || pImmGetContext == NULL
+ || pImmAssociateContext == NULL
+ || pImmReleaseContext == NULL
+ || pImmGetOpenStatus == NULL
+ || pImmSetOpenStatus == NULL
+ || pImmGetCompositionFont == NULL
+ || pImmSetCompositionFont == NULL
+ || pImmSetCompositionWindow == NULL
+ || pImmGetConversionStatus == NULL)
+ {
+ FreeLibrary(hLibImm);
+ hLibImm = NULL;
+ pImmGetContext = NULL;
+ return;
+ }
+
+ return;
+}
+
+# if 0 /* not used */
+ int
+dyn_imm_unload(void)
+{
+ if (!hLibImm)
+ return FALSE;
+ FreeLibrary(hLibImm);
+ hLibImm = NULL;
+ return TRUE;
+}
+# endif
+
+#endif
+
+#if defined(FEAT_SIGN_ICONS) || defined(PROTO)
+
+# ifdef FEAT_XPM_W32
+# define IMAGE_XPM 100
+# endif
+
+typedef struct _signicon_t
+{
+ HANDLE hImage;
+ UINT uType;
+#ifdef FEAT_XPM_W32
+ HANDLE hShape; /* Mask bitmap handle */
+#endif
+} signicon_t;
+
+ void
+gui_mch_drawsign(row, col, typenr)
+ int row;
+ int col;
+ int typenr;
+{
+ signicon_t *sign;
+ int x, y, w, h;
+
+ if (!gui.in_use || (sign = (signicon_t *)sign_get_image(typenr)) == NULL)
+ return;
+
+ x = TEXT_X(col);
+ y = TEXT_Y(row);
+ w = gui.char_width * 2;
+ h = gui.char_height;
+ switch (sign->uType)
+ {
+ case IMAGE_BITMAP:
+ {
+ HDC hdcMem;
+ HBITMAP hbmpOld;
+
+ hdcMem = CreateCompatibleDC(s_hdc);
+ hbmpOld = (HBITMAP)SelectObject(hdcMem, sign->hImage);
+ BitBlt(s_hdc, x, y, w, h, hdcMem, 0, 0, SRCCOPY);
+ SelectObject(hdcMem, hbmpOld);
+ DeleteDC(hdcMem);
+ }
+ break;
+ case IMAGE_ICON:
+ case IMAGE_CURSOR:
+ DrawIconEx(s_hdc, x, y, (HICON)sign->hImage, w, h, 0, NULL, DI_NORMAL);
+ break;
+#ifdef FEAT_XPM_W32
+ case IMAGE_XPM:
+ {
+ HDC hdcMem;
+ HBITMAP hbmpOld;
+
+ hdcMem = CreateCompatibleDC(s_hdc);
+ hbmpOld = (HBITMAP)SelectObject(hdcMem, sign->hShape);
+ /* Make hole */
+ BitBlt(s_hdc, x, y, w, h, hdcMem, 0, 0, SRCAND);
+
+ SelectObject(hdcMem, sign->hImage);
+ /* Paint sign */
+ BitBlt(s_hdc, x, y, w, h, hdcMem, 0, 0, SRCPAINT);
+ SelectObject(hdcMem, hbmpOld);
+ DeleteDC(hdcMem);
+ }
+ break;
+#endif
+ }
+}
+
+ static void
+close_signicon_image(signicon_t *sign)
+{
+ if (sign)
+ switch (sign->uType)
+ {
+ case IMAGE_BITMAP:
+ DeleteObject((HGDIOBJ)sign->hImage);
+ break;
+ case IMAGE_CURSOR:
+ DestroyCursor((HCURSOR)sign->hImage);
+ break;
+ case IMAGE_ICON:
+ DestroyIcon((HICON)sign->hImage);
+ break;
+#ifdef FEAT_XPM_W32
+ case IMAGE_XPM:
+ DeleteObject((HBITMAP)sign->hImage);
+ DeleteObject((HBITMAP)sign->hShape);
+ break;
+#endif
+ }
+}
+
+ void *
+gui_mch_register_sign(signfile)
+ char_u *signfile;
+{
+ signicon_t sign, *psign;
+ char_u *ext;
+
+ if (is_winnt_3())
+ {
+ EMSG(_(e_signdata));
+ return NULL;
+ }
+
+ sign.hImage = NULL;
+ ext = signfile + STRLEN(signfile) - 4; /* get extention */
+ if (ext > signfile)
+ {
+ int do_load = 1;
+
+ if (!STRICMP(ext, ".bmp"))
+ sign.uType = IMAGE_BITMAP;
+ else if (!STRICMP(ext, ".ico"))
+ sign.uType = IMAGE_ICON;
+ else if (!STRICMP(ext, ".cur") || !STRICMP(ext, ".ani"))
+ sign.uType = IMAGE_CURSOR;
+ else
+ do_load = 0;
+
+ if (do_load)
+ sign.hImage = (HANDLE)LoadImage(NULL, signfile, sign.uType,
+ gui.char_width * 2, gui.char_height,
+ LR_LOADFROMFILE | LR_CREATEDIBSECTION);
+#ifdef FEAT_XPM_W32
+ if (!STRICMP(ext, ".xpm"))
+ {
+ sign.uType = IMAGE_XPM;
+ LoadXpmImage(signfile, (HBITMAP *)&sign.hImage, (HBITMAP *)&sign.hShape);
+ }
+#endif
+ }
+
+ psign = NULL;
+ if (sign.hImage && (psign = (signicon_t *)alloc(sizeof(signicon_t)))
+ != NULL)
+ *psign = sign;
+
+ if (!psign)
+ {
+ if (sign.hImage)
+ close_signicon_image(&sign);
+ EMSG(_(e_signdata));
+ }
+ return (void *)psign;
+
+}
+
+ void
+gui_mch_destroy_sign(sign)
+ void *sign;
+{
+ if (sign)
+ {
+ close_signicon_image((signicon_t *)sign);
+ vim_free(sign);
+ }
+}
+
+#if defined(FEAT_BEVAL) || defined(PROTO)
+
+/* BALLOON-EVAL IMPLEMENTATION FOR WINDOWS.
+ * Added by Sergey Khorev
+ *
+ * The only reused thing is gui_beval.h and gui_mch_get_beval_info()
+ * from gui_beval.c (note it uses x and y of the BalloonEval struct
+ * to get current mouse position).
+ *
+ * Trying to use as more Windows services as possible, and as less
+ * IE version as possible :)).
+ *
+ * 1) Don't create ToolTip in gui_mch_create_beval_area, only initialize
+ * BalloonEval struct.
+ * 2) Enable/Disable simply create/kill BalloonEval Timer
+ * 3) When there was enough inactivity, timer procedure posts
+ * async request to debugger
+ * 4) gui_mch_post_balloon (invoked from netbeans.c) creates tooltip control
+ * and performs some actions to show it ASAP
+ * 5) WM_NOTOFY:TTN_POP destroys created tooltip
+ */
+
+ static void
+make_tooltip(beval, text, pt)
+ BalloonEval *beval;
+ char *text;
+ POINT pt;
+{
+ TOOLINFO ti;
+
+ beval->balloon = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS,
+ NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ beval->target, NULL, s_hinst, NULL);
+
+ SetWindowPos(beval->balloon, HWND_TOPMOST, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+
+ ti.cbSize = sizeof(TOOLINFO);
+ ti.uFlags = TTF_SUBCLASS;
+ ti.hwnd = beval->target;
+ ti.hinst = 0; /* Don't use string resources */
+ ti.uId = ID_BEVAL_TOOLTIP;
+ ti.lpszText = text;
+
+ /* Limit ballooneval bounding rect to CursorPos neighbourhood */
+ ti.rect.left = pt.x - 3;
+ ti.rect.top = pt.y - 3;
+ ti.rect.right = pt.x + 3;
+ ti.rect.bottom = pt.y + 3;
+
+ SendMessage(beval->balloon, TTM_ADDTOOL, 0, (LPARAM)&ti);
+ /* Make tooltip appear sooner */
+ SendMessage(beval->balloon, TTM_SETDELAYTIME, TTDT_INITIAL, 10);
+ /*
+ * HACK: force tooltip to appear, because it'll not appear until
+ * first mouse move. D*mn M$
+ */
+ mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
+ mouse_event(MOUSEEVENTF_MOVE, (DWORD)-1, (DWORD)-1, 0, 0);
+}
+
+ static void
+delete_tooltip(beval)
+ BalloonEval *beval;
+{
+ DestroyWindow(beval->balloon);
+}
+
+ static VOID CALLBACK
+BevalTimerProc(hwnd, uMsg, idEvent, dwTime)
+ HWND hwnd;
+ UINT uMsg;
+ UINT idEvent;
+ DWORD dwTime;
+{
+ POINT pt;
+ RECT rect;
+
+ if (cur_beval == NULL || cur_beval->showState == ShS_SHOWING || !p_beval)
+ return;
+
+ GetCursorPos(&pt);
+ if (WindowFromPoint(pt) != s_textArea)
+ return;
+
+ ScreenToClient(s_textArea, &pt);
+ GetClientRect(s_textArea, &rect);
+ if (!PtInRect(&rect, pt))
+ return;
+
+ if (LastActivity > 0
+ && (dwTime - LastActivity) >= (DWORD)p_bdlay
+ && (cur_beval->showState != ShS_PENDING
+ || abs(cur_beval->x - pt.x) > 3
+ || abs(cur_beval->y - pt.y) > 3))
+ {
+ /* Pointer resting in one place long enough, it's time to show
+ * the tooltip. */
+ cur_beval->showState = ShS_PENDING;
+ cur_beval->x = pt.x;
+ cur_beval->y = pt.y;
+
+ TRACE0("BevalTimerProc: sending request");
+
+ if (cur_beval->msgCB != NULL)
+ (*cur_beval->msgCB)(cur_beval, 0);
+ }
+}
+
+ void
+gui_mch_disable_beval_area(beval)
+ BalloonEval *beval;
+{
+ TRACE0("gui_mch_disable_beval_area {{{");
+ KillTimer(s_textArea, BevalTimerId);
+ TRACE0("gui_mch_disable_beval_area }}}");
+}
+
+ void
+gui_mch_enable_beval_area(beval)
+ BalloonEval *beval;
+{
+ TRACE0("gui_mch_enable_beval_area |||");
+ if (beval == NULL)
+ return;
+ TRACE0("gui_mch_enable_beval_area {{{");
+ BevalTimerId = SetTimer(s_textArea, 0, p_bdlay / 2, (TIMERPROC)BevalTimerProc);
+ TRACE0("gui_mch_enable_beval_area }}}");
+}
+
+ void
+gui_mch_post_balloon(beval, mesg)
+ BalloonEval *beval;
+ char_u *mesg;
+{
+ POINT pt;
+ TRACE0("gui_mch_post_balloon {{{");
+ if (beval->showState == ShS_SHOWING)
+ return;
+ GetCursorPos(&pt);
+ ScreenToClient(s_textArea, &pt);
+
+ if (abs(beval->x - pt.x) < 3 && abs(beval->y - pt.y) < 3)
+ /* cursor is still here */
+ {
+ gui_mch_disable_beval_area(cur_beval);
+ beval->showState = ShS_SHOWING;
+ make_tooltip(beval, mesg, pt);
+ }
+ TRACE0("gui_mch_post_balloon }}}");
+}
+
+ BalloonEval *
+gui_mch_create_beval_area(target, mesg, mesgCB, clientData)
+ void *target; /* ignored, always use s_textArea */
+ char_u *mesg;
+ void (*mesgCB)__ARGS((BalloonEval *, int));
+ void *clientData;
+{
+ /* partially stolen from gui_beval.c */
+ BalloonEval *beval;
+
+ if (mesg != NULL && mesgCB != NULL)
+ {
+ EMSG(_("E232: Cannot create BalloonEval with both message and callback"));
+ return NULL;
+ }
+
+ beval = (BalloonEval *)alloc(sizeof(BalloonEval));
+ if (beval != NULL)
+ {
+ beval->target = s_textArea;
+ beval->balloon = NULL;
+
+ beval->showState = ShS_NEUTRAL;
+ beval->x = 0;
+ beval->y = 0;
+ beval->msg = mesg;
+ beval->msgCB = mesgCB;
+ beval->clientData = clientData;
+
+ InitCommonControls();
+
+ cur_beval = beval;
+
+ if (p_beval)
+ gui_mch_enable_beval_area(beval);
+
+ }
+ return beval;
+}
+
+ static void
+Handle_WM_Notify(hwnd, pnmh)
+ HWND hwnd;
+ LPNMHDR pnmh;
+{
+ if (pnmh->idFrom != ID_BEVAL_TOOLTIP) /* it is not our tooltip */
+ return;
+
+ if (cur_beval != NULL)
+ {
+ if (pnmh->code == TTN_SHOW)
+ {
+ TRACE0("TTN_SHOW {{{");
+ TRACE0("TTN_SHOW }}}");
+ }
+ else if (pnmh->code == TTN_POP) /* Before tooltip disappear */
+ {
+ TRACE0("TTN_POP {{{");
+ delete_tooltip(cur_beval);
+ gui_mch_enable_beval_area(cur_beval);
+ TRACE0("TTN_POP }}}");
+
+ cur_beval->showState = ShS_NEUTRAL;
+ }
+ }
+}
+
+ static void
+TrackUserActivity(UINT uMsg)
+{
+ if ((uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST)
+ || (uMsg >= WM_KEYFIRST && uMsg <= WM_KEYLAST))
+ LastActivity = GetTickCount();
+}
+
+ void
+gui_mch_destroy_beval_area(beval)
+ BalloonEval *beval;
+{
+ vim_free(beval);
+}
+#endif /* FEAT_BEVAL */
+
+#if defined(FEAT_NETBEANS_INTG) || defined(PROTO)
+/*
+ * We have multiple signs to draw at the same location. Draw the
+ * multi-sign indicator (down-arrow) instead. This is the Win32 version.
+ */
+ void
+netbeans_draw_multisign_indicator(int row)
+{
+ int i;
+ int y;
+ int x;
+
+ x = 0;
+ y = TEXT_Y(row);
+
+ for (i = 0; i < gui.char_height - 3; i++)
+ SetPixel(s_hdc, x+2, y++, gui.currFgColor);
+
+ SetPixel(s_hdc, x+0, y, gui.currFgColor);
+ SetPixel(s_hdc, x+2, y, gui.currFgColor);
+ SetPixel(s_hdc, x+4, y++, gui.currFgColor);
+ SetPixel(s_hdc, x+1, y, gui.currFgColor);
+ SetPixel(s_hdc, x+2, y, gui.currFgColor);
+ SetPixel(s_hdc, x+3, y++, gui.currFgColor);
+ SetPixel(s_hdc, x+2, y, gui.currFgColor);
+}
+#endif
+
+#endif
diff --git a/src/gui_w32_rc.h b/src/gui_w32_rc.h
new file mode 100644
index 000000000..6c0d77341
--- /dev/null
+++ b/src/gui_w32_rc.h
@@ -0,0 +1,8 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Script1.rc
+//
+#define IDR_TOOLBAR1 101
+//#define ID_TB_BLOB 40001
+//#define ID_TB_CIRCLE 40002
+
diff --git a/src/gui_w48.c b/src/gui_w48.c
new file mode 100644
index 000000000..761c1af16
--- /dev/null
+++ b/src/gui_w48.c
@@ -0,0 +1,3402 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI support by Robert Webb
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * gui_w48.c: This file is included in gui_w16.c and gui_w32.c.
+ *
+ * GUI support for Microsoft Windows (Win16 + Win32 = Win48 :-)
+ *
+ * The combined efforts of:
+ * George V. Reilly <george@reilly.org>
+ * Robert Webb
+ * Vince Negri
+ * ...and contributions from many others
+ *
+ */
+
+#include "vim.h"
+#include "version.h" /* used by dialog box routine for default title */
+#ifdef DEBUG
+# include <tchar.h>
+#endif
+#ifndef __MINGW32__
+# include <shellapi.h>
+#endif
+#if defined(FEAT_TOOLBAR) || defined(FEAT_BEVAL)
+# include <commctrl.h>
+#endif
+#ifdef WIN16
+# include <commdlg.h>
+# include <shellapi.h>
+# ifdef WIN16_3DLOOK
+# include <ctl3d.h>
+# endif
+#endif
+#include <windowsx.h>
+
+#ifdef GLOBAL_IME
+# include "glbl_ime.h"
+#endif
+
+#ifdef FEAT_MENU
+# define MENUHINTS /* show menu hints in command line */
+#endif
+
+/* Some parameters for dialog boxes. All in pixels. */
+#define DLG_PADDING_X 10
+#define DLG_PADDING_Y 10
+#define DLG_OLD_STYLE_PADDING_X 5
+#define DLG_OLD_STYLE_PADDING_Y 5
+#define DLG_VERT_PADDING_X 4 /* For vertical buttons */
+#define DLG_VERT_PADDING_Y 4
+#define DLG_ICON_WIDTH 34
+#define DLG_ICON_HEIGHT 34
+#define DLG_MIN_WIDTH 150
+#define DLG_FONT_NAME "MS Sans Serif"
+#define DLG_FONT_POINT_SIZE 8
+#define DLG_MIN_MAX_WIDTH 400
+
+#define DLG_NONBUTTON_CONTROL 5000 /* First ID of non-button controls */
+
+#ifndef WM_XBUTTONDOWN /* For Win2K / winME ONLY */
+# define WM_XBUTTONDOWN 0x020B
+# define WM_XBUTTONUP 0x020C
+# define WM_XBUTTONDBLCLK 0x020D
+# define MK_XBUTTON1 0x0020
+# define MK_XBUTTON2 0x0040
+#endif
+
+#ifdef PROTO
+/*
+ * Define a few things for generating prototypes. This is just to avoid
+ * syntax errors, the defines do not need to be correct.
+ */
+# define APIENTRY
+# define CALLBACK
+# define CONST
+# define FAR
+# define NEAR
+# define _cdecl
+typedef int BOOL;
+typedef int BYTE;
+typedef int DWORD;
+typedef int WCHAR;
+typedef int ENUMLOGFONT;
+typedef int FINDREPLACE;
+typedef int HANDLE;
+typedef int HBITMAP;
+typedef int HBRUSH;
+typedef int HDROP;
+typedef int INT;
+typedef int LOGFONT[];
+typedef int LPARAM;
+typedef int LPCREATESTRUCT;
+typedef int LPCSTR;
+typedef int LPCTSTR;
+typedef int LPRECT;
+typedef int LPSTR;
+typedef int LPWINDOWPOS;
+typedef int LPWORD;
+typedef int LRESULT;
+# undef MSG
+typedef int MSG;
+typedef int NEWTEXTMETRIC;
+typedef int OSVERSIONINFO;
+typedef int PWORD;
+typedef int RECT;
+typedef int UINT;
+typedef int WORD;
+typedef int WPARAM;
+typedef int POINT;
+typedef void *HINSTANCE;
+typedef void *HMENU;
+typedef void *HWND;
+typedef void *HDC;
+typedef void VOID;
+typedef int LPNMHDR;
+typedef int LONG;
+#endif
+
+#ifndef GET_X_LPARAM
+# define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
+#endif
+
+static void _OnPaint( HWND hwnd);
+static void clear_rect(RECT *rcp);
+static int gui_mswin_get_menu_height(int fix_window);
+
+static WORD s_dlgfntheight; /* height of the dialog font */
+static WORD s_dlgfntwidth; /* width of the dialog font */
+
+#ifdef FEAT_MENU
+static HMENU s_menuBar = NULL;
+#endif
+#ifdef FEAT_TEAROFF
+static void rebuild_tearoff(vimmenu_T *menu);
+static HBITMAP s_htearbitmap; /* bitmap used to indicate tearoff */
+#endif
+
+/* Flag that is set while processing a message that must not be interupted by
+ * processing another message. */
+static int s_busy_processing = FALSE;
+
+static int destroying = FALSE; /* call DestroyWindow() ourselves */
+
+#ifdef MSWIN_FIND_REPLACE
+static UINT s_findrep_msg = 0; /* set in gui_w[16/32].c */
+static FINDREPLACE s_findrep_struct;
+static HWND s_findrep_hwnd = NULL;
+static int s_findrep_is_find; /* TRUE for find dialog, FALSE
+ for find/replace dialog */
+#endif
+
+static HINSTANCE s_hinst = NULL;
+#if !defined(FEAT_SNIFF) && !defined(FEAT_GUI)
+static
+#endif
+HWND s_hwnd = NULL;
+static HDC s_hdc = NULL;
+static HBRUSH s_brush = NULL;
+
+#ifdef FEAT_TOOLBAR
+static HWND s_toolbarhwnd = NULL;
+#endif
+
+static WPARAM s_wParam = 0;
+static LPARAM s_lParam = 0;
+
+static HWND s_textArea = NULL;
+static UINT s_uMsg = 0;
+
+static char_u *s_textfield; /* Used by dialogs to pass back strings */
+
+static int s_need_activate = FALSE;
+
+/* This variable is set when waiting for an event, which is the only moment
+ * scrollbar dragging can be done directly. It's not allowed while commands
+ * are executed, because it may move the cursor and that may cause unexpected
+ * problems (e.g., while ":s" is working).
+ */
+static int allow_scrollbar = FALSE;
+
+#ifdef GLOBAL_IME
+# define MyTranslateMessage(x) global_ime_TranslateMessage(x)
+#else
+# define MyTranslateMessage(x) TranslateMessage(x)
+#endif
+
+#if (defined(WIN3264) && defined(FEAT_MBYTE)) || defined(GLOBAL_IME)
+ /* use of WindowProc depends on wide_WindowProc */
+# define MyWindowProc vim_WindowProc
+#else
+ /* use ordinary WindowProc */
+# define MyWindowProc DefWindowProc
+#endif
+
+extern int current_font_height; /* this is in os_mswin.c */
+
+static struct
+{
+ UINT key_sym;
+ char_u vim_code0;
+ char_u vim_code1;
+} special_keys[] =
+{
+ {VK_UP, 'k', 'u'},
+ {VK_DOWN, 'k', 'd'},
+ {VK_LEFT, 'k', 'l'},
+ {VK_RIGHT, 'k', 'r'},
+
+ {VK_F1, 'k', '1'},
+ {VK_F2, 'k', '2'},
+ {VK_F3, 'k', '3'},
+ {VK_F4, 'k', '4'},
+ {VK_F5, 'k', '5'},
+ {VK_F6, 'k', '6'},
+ {VK_F7, 'k', '7'},
+ {VK_F8, 'k', '8'},
+ {VK_F9, 'k', '9'},
+ {VK_F10, 'k', ';'},
+
+ {VK_F11, 'F', '1'},
+ {VK_F12, 'F', '2'},
+ {VK_F13, 'F', '3'},
+ {VK_F14, 'F', '4'},
+ {VK_F15, 'F', '5'},
+ {VK_F16, 'F', '6'},
+ {VK_F17, 'F', '7'},
+ {VK_F18, 'F', '8'},
+ {VK_F19, 'F', '9'},
+ {VK_F20, 'F', 'A'},
+
+ {VK_F21, 'F', 'B'},
+#ifdef FEAT_NETBEANS_INTG
+ {VK_PAUSE, 'F', 'B'}, /* Pause == F21 (see gui_gtk_x11.c) */
+#endif
+ {VK_F22, 'F', 'C'},
+ {VK_F23, 'F', 'D'},
+ {VK_F24, 'F', 'E'}, /* winuser.h defines up to F24 */
+
+ {VK_HELP, '%', '1'},
+ {VK_BACK, 'k', 'b'},
+ {VK_INSERT, 'k', 'I'},
+ {VK_DELETE, 'k', 'D'},
+ {VK_HOME, 'k', 'h'},
+ {VK_END, '@', '7'},
+ {VK_PRIOR, 'k', 'P'},
+ {VK_NEXT, 'k', 'N'},
+ {VK_PRINT, '%', '9'},
+ {VK_ADD, 'K', '6'},
+ {VK_SUBTRACT, 'K', '7'},
+ {VK_DIVIDE, 'K', '8'},
+ {VK_MULTIPLY, 'K', '9'},
+ {VK_SEPARATOR, 'K', 'A'}, /* Keypad Enter */
+ {VK_DECIMAL, 'K', 'B'},
+
+ {VK_NUMPAD0, 'K', 'C'},
+ {VK_NUMPAD1, 'K', 'D'},
+ {VK_NUMPAD2, 'K', 'E'},
+ {VK_NUMPAD3, 'K', 'F'},
+ {VK_NUMPAD4, 'K', 'G'},
+ {VK_NUMPAD5, 'K', 'H'},
+ {VK_NUMPAD6, 'K', 'I'},
+ {VK_NUMPAD7, 'K', 'J'},
+ {VK_NUMPAD8, 'K', 'K'},
+ {VK_NUMPAD9, 'K', 'L'},
+
+ /* Keys that we want to be able to use any modifier with: */
+ {VK_SPACE, ' ', NUL},
+ {VK_TAB, TAB, NUL},
+ {VK_ESCAPE, ESC, NUL},
+ {NL, NL, NUL},
+ {CAR, CAR, NUL},
+
+ /* End of list marker: */
+ {0, 0, 0}
+};
+
+/* Local variables */
+static int s_button_pending = -1;
+static int s_x_pending;
+static int s_y_pending;
+static UINT s_kFlags_pending;
+static UINT s_wait_timer = 0; /* Timer for get char from user */
+static int s_timed_out = FALSE;
+static int dead_key = 0; /* 0 - no dead key, 1 - dead key pressed */
+
+#ifdef WIN3264
+static OSVERSIONINFO os_version; /* like it says. Init in gui_mch_init() */
+#endif
+
+#ifdef FEAT_BEVAL
+/* balloon-eval WM_NOTIFY_HANDLER */
+static void Handle_WM_Notify __ARGS((HWND hwnd, LPNMHDR pnmh));
+static void TrackUserActivity __ARGS((UINT uMsg));
+#endif
+
+/*
+ * For control IME.
+ */
+#ifdef FEAT_MBYTE
+# ifdef USE_IM_CONTROL
+static LOGFONT norm_logfont;
+# endif
+#endif
+
+#ifdef FEAT_MBYTE_IME
+static LRESULT _OnImeNotify(HWND hWnd, DWORD dwCommand, DWORD dwData);
+#endif
+
+#ifdef DEBUG
+/*
+ * Print out the last Windows error message
+ */
+ static void
+print_windows_error(void)
+{
+ LPVOID lpMsgBuf;
+
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf, 0, NULL);
+ TRACE1("Error: %s\n", lpMsgBuf);
+ LocalFree(lpMsgBuf);
+}
+#endif /* DEBUG */
+
+/*
+ * Cursor blink functions.
+ *
+ * This is a simple state machine:
+ * BLINK_NONE not blinking at all
+ * BLINK_OFF blinking, cursor is not shown
+ * BLINK_ON blinking, cursor is shown
+ */
+
+#define BLINK_NONE 0
+#define BLINK_OFF 1
+#define BLINK_ON 2
+
+static int blink_state = BLINK_NONE;
+static long_u blink_waittime = 700;
+static long_u blink_ontime = 400;
+static long_u blink_offtime = 250;
+static UINT blink_timer = 0;
+
+ void
+gui_mch_set_blinking(long wait, long on, long off)
+{
+ blink_waittime = wait;
+ blink_ontime = on;
+ blink_offtime = off;
+}
+
+/* ARGSUSED */
+ static VOID CALLBACK
+_OnBlinkTimer(
+ HWND hwnd,
+ UINT uMsg,
+ UINT idEvent,
+ DWORD dwTime)
+{
+ MSG msg;
+
+ /*
+ TRACE2("Got timer event, id %d, blink_timer %d\n", idEvent, blink_timer);
+ */
+
+ KillTimer(NULL, idEvent);
+
+ /* Eat spurious WM_TIMER messages */
+ while (PeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
+ ;
+
+ if (blink_state == BLINK_ON)
+ {
+ gui_undraw_cursor();
+ blink_state = BLINK_OFF;
+ blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_offtime,
+ (TIMERPROC)_OnBlinkTimer);
+ }
+ else
+ {
+ gui_update_cursor(TRUE, FALSE);
+ blink_state = BLINK_ON;
+ blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime,
+ (TIMERPROC)_OnBlinkTimer);
+ }
+}
+
+ static void
+gui_mswin_rm_blink_timer(void)
+{
+ MSG msg;
+
+ if (blink_timer != 0)
+ {
+ KillTimer(NULL, blink_timer);
+ /* Eat spurious WM_TIMER messages */
+ while (PeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
+ ;
+ blink_timer = 0;
+ }
+}
+
+/*
+ * Stop the cursor blinking. Show the cursor if it wasn't shown.
+ */
+ void
+gui_mch_stop_blink(void)
+{
+ gui_mswin_rm_blink_timer();
+ if (blink_state == BLINK_OFF)
+ gui_update_cursor(TRUE, FALSE);
+ blink_state = BLINK_NONE;
+}
+
+/*
+ * Start the cursor blinking. If it was already blinking, this restarts the
+ * waiting time and shows the cursor.
+ */
+ void
+gui_mch_start_blink(void)
+{
+ gui_mswin_rm_blink_timer();
+
+ /* Only switch blinking on if none of the times is zero */
+ if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
+ {
+ blink_timer = (UINT)SetTimer(NULL, 0, (UINT)blink_waittime,
+ (TIMERPROC)_OnBlinkTimer);
+ blink_state = BLINK_ON;
+ gui_update_cursor(TRUE, FALSE);
+ }
+}
+
+/*
+ * Call-back routines.
+ */
+
+ static VOID CALLBACK
+_OnTimer(
+ HWND hwnd,
+ UINT uMsg,
+ UINT idEvent,
+ DWORD dwTime)
+{
+ MSG msg;
+
+ /*
+ TRACE2("Got timer event, id %d, s_wait_timer %d\n", idEvent, s_wait_timer);
+ */
+ KillTimer(NULL, idEvent);
+ s_timed_out = TRUE;
+
+ /* Eat spurious WM_TIMER messages */
+ while (PeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
+ ;
+ if (idEvent == s_wait_timer)
+ s_wait_timer = 0;
+}
+
+ static void
+_OnDeadChar(
+ HWND hwnd,
+ UINT ch,
+ int cRepeat)
+{
+ dead_key = 1;
+}
+
+/*
+ * Convert Unicode character "ch" to bytes in "string[slen]".
+ * Return the length.
+ */
+ static int
+char_to_string(int ch, char_u *string, int slen)
+{
+ int len;
+ int i;
+#ifdef FEAT_MBYTE
+ WCHAR wstring[2];
+ char_u *ws = NULL;;
+
+ /* "ch" is a UTF-16 character. Convert it to a string of bytes. When
+ * "enc_codepage" is non-zero use the standard Win32 function, otherwise
+ * use our own conversion function (e.g., for UTF-8). */
+ wstring[0] = ch;
+ if (enc_codepage > 0)
+ len = WideCharToMultiByte(enc_codepage, 0, wstring, 1, string, slen,
+ 0, NULL);
+ else
+ {
+ len = 1;
+ ws = ucs2_to_enc(wstring, &len);
+ if (ws == NULL)
+ len = 0;
+ else
+ {
+ if (len > slen) /* just in case */
+ len = slen;
+ mch_memmove(string, ws, len);
+ vim_free(ws);
+ }
+ }
+ if (len == 0)
+#endif
+ {
+ string[0] = ch;
+ len = 1;
+ }
+
+ for (i = 0; i < len; ++i)
+ if (string[i] == CSI && len <= slen - 2)
+ {
+ /* Insert CSI as K_CSI. */
+ mch_memmove(string + i + 3, string + i + 1, len - i - 1);
+ string[++i] = KS_EXTRA;
+ string[++i] = (int)KE_CSI;
+ len += 2;
+ }
+
+ return len;
+}
+
+/*
+ * Key hit, add it to the input buffer.
+ */
+ static void
+_OnChar(
+ HWND hwnd,
+ UINT ch,
+ int cRepeat)
+{
+ char_u string[40];
+ int len = 0;
+
+ len = char_to_string(ch, string, 40);
+ if (len == 1 && string[0] == Ctrl_C && ctrl_c_interrupts)
+ {
+ trash_input_buf();
+ got_int = TRUE;
+ }
+
+ add_to_input_buf(string, len);
+}
+
+/*
+ * Alt-Key hit, add it to the input buffer.
+ */
+ static void
+_OnSysChar(
+ HWND hwnd,
+ UINT cch,
+ int cRepeat)
+{
+ char_u string[40]; /* Enough for multibyte character */
+ int len;
+ int modifiers;
+ int ch = cch; /* special keys are negative */
+
+ /* TRACE("OnSysChar(%d, %c)\n", ch, ch); */
+
+ /* OK, we have a character key (given by ch) which was entered with the
+ * ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note
+ * that the system distinguishes Alt-a and Alt-A (Alt-Shift-a unless
+ * CAPSLOCK is pressed) at this point.
+ */
+ modifiers = MOD_MASK_ALT;
+ if (GetKeyState(VK_SHIFT) & 0x8000)
+ modifiers |= MOD_MASK_SHIFT;
+ if (GetKeyState(VK_CONTROL) & 0x8000)
+ modifiers |= MOD_MASK_CTRL;
+
+ ch = simplify_key(ch, &modifiers);
+ /* remove the SHIFT modifier for keys where it's already included, e.g.,
+ * '(' and '*' */
+ if (ch < 0x100 && !isalpha(ch) && isprint(ch))
+ modifiers &= ~MOD_MASK_SHIFT;
+
+ /* Interpret the ALT key as making the key META, include SHIFT, etc. */
+ ch = extract_modifiers(ch, &modifiers);
+ if (ch == CSI)
+ ch = K_CSI;
+
+ len = 0;
+ if (modifiers)
+ {
+ string[len++] = CSI;
+ string[len++] = KS_MODIFIER;
+ string[len++] = modifiers;
+ }
+
+ if (IS_SPECIAL((int)ch))
+ {
+ string[len++] = CSI;
+ string[len++] = K_SECOND((int)ch);
+ string[len++] = K_THIRD((int)ch);
+ }
+ else
+ {
+ /* Although the documentation isn't clear about it, we assume "ch" is
+ * a Unicode character. */
+ len += char_to_string(ch, string + len, 40 - len);
+ }
+
+ add_to_input_buf(string, len);
+}
+
+ static void
+_OnMouseEvent(
+ int button,
+ int x,
+ int y,
+ int repeated_click,
+ UINT keyFlags)
+{
+ int vim_modifiers = 0x0;
+
+ if (keyFlags & MK_SHIFT)
+ vim_modifiers |= MOUSE_SHIFT;
+ if (keyFlags & MK_CONTROL)
+ vim_modifiers |= MOUSE_CTRL;
+ if (GetKeyState(VK_MENU) & 0x8000)
+ vim_modifiers |= MOUSE_ALT;
+
+ gui_send_mouse_event(button, x, y, repeated_click, vim_modifiers);
+}
+
+ static void
+_OnMouseButtonDown(
+ HWND hwnd,
+ BOOL fDoubleClick,
+ int x,
+ int y,
+ UINT keyFlags)
+{
+ static LONG s_prevTime = 0;
+
+ LONG currentTime = GetMessageTime();
+ int button = -1;
+ int repeated_click;
+
+ /* Give main window the focus: this is so the cursor isn't hollow. */
+ (void)SetFocus(s_hwnd);
+
+ if (s_uMsg == WM_LBUTTONDOWN || s_uMsg == WM_LBUTTONDBLCLK)
+ button = MOUSE_LEFT;
+ else if (s_uMsg == WM_MBUTTONDOWN || s_uMsg == WM_MBUTTONDBLCLK)
+ button = MOUSE_MIDDLE;
+ else if (s_uMsg == WM_RBUTTONDOWN || s_uMsg == WM_RBUTTONDBLCLK)
+ button = MOUSE_RIGHT;
+#ifndef WIN16 /*<VN>*/
+ else if (s_uMsg == WM_XBUTTONDOWN || s_uMsg == WM_XBUTTONDBLCLK)
+ {
+#ifndef GET_XBUTTON_WPARAM
+# define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam))
+#endif
+ button = ((GET_XBUTTON_WPARAM(s_wParam) == 1) ? MOUSE_X1 : MOUSE_X2);
+ }
+ else if (s_uMsg == WM_CAPTURECHANGED)
+ {
+ /* on W95/NT4, somehow you get in here with an odd Msg
+ * if you press one button while holding down the other..*/
+ if (s_button_pending == MOUSE_LEFT)
+ button = MOUSE_RIGHT;
+ else
+ button = MOUSE_LEFT;
+ }
+#endif
+ if (button >= 0)
+ {
+ repeated_click = ((int)(currentTime - s_prevTime) < p_mouset);
+
+ /*
+ * Holding down the left and right buttons simulates pushing the middle
+ * button.
+ */
+ if (repeated_click &&
+ ((button == MOUSE_LEFT && s_button_pending == MOUSE_RIGHT) ||
+ (button == MOUSE_RIGHT && s_button_pending == MOUSE_LEFT)))
+ {
+ /*
+ * Hmm, gui.c will ignore more than one button down at a time, so
+ * pretend we let go of it first.
+ */
+ gui_send_mouse_event(MOUSE_RELEASE, x, y, FALSE, 0x0);
+ button = MOUSE_MIDDLE;
+ repeated_click = FALSE;
+ s_button_pending = -1;
+ _OnMouseEvent(button, x, y, repeated_click, keyFlags);
+ }
+ else if ((repeated_click)
+ || (mouse_model_popup() && (button == MOUSE_RIGHT)))
+ {
+ if (s_button_pending > -1)
+ {
+ _OnMouseEvent(s_button_pending, x, y, FALSE, keyFlags);
+ s_button_pending = -1;
+ }
+ /* TRACE("Button down at x %d, y %d\n", x, y); */
+ _OnMouseEvent(button, x, y, repeated_click, keyFlags);
+ }
+ else
+ {
+ /*
+ * If this is the first press (i.e. not a multiple click) don't
+ * action immediately, but store and wait for:
+ * i) button-up
+ * ii) mouse move
+ * iii) another button press
+ * before using it.
+ * This enables us to make left+right simulate middle button,
+ * without left or right being actioned first. The side-effect is
+ * that if you click and hold the mouse without dragging, the
+ * cursor doesn't move until you release the button. In practice
+ * this is hardly a problem.
+ */
+ s_button_pending = button;
+ s_x_pending = x;
+ s_y_pending = y;
+ s_kFlags_pending = keyFlags;
+ }
+
+ s_prevTime = currentTime;
+ }
+}
+
+ static void
+_OnMouseMoveOrRelease(
+ HWND hwnd,
+ int x,
+ int y,
+ UINT keyFlags)
+{
+ int button;
+
+ if (s_button_pending > -1)
+ {
+ /* Delayed action for mouse down event */
+ _OnMouseEvent(s_button_pending, s_x_pending,
+ s_y_pending, FALSE, s_kFlags_pending);
+ s_button_pending = -1;
+ }
+ if (s_uMsg == WM_MOUSEMOVE)
+ {
+ /*
+ * It's only a MOUSE_DRAG if one or more mouse buttons are being held
+ * down.
+ */
+ if (!(keyFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON
+ | MK_XBUTTON1 | MK_XBUTTON2)))
+ {
+ gui_mouse_moved(x, y);
+ return;
+ }
+
+ /*
+ * While button is down, keep grabbing mouse move events when
+ * the mouse goes outside the window
+ */
+ SetCapture(s_textArea);
+ button = MOUSE_DRAG;
+ /* TRACE(" move at x %d, y %d\n", x, y); */
+ }
+ else
+ {
+ ReleaseCapture();
+ button = MOUSE_RELEASE;
+ /* TRACE(" up at x %d, y %d\n", x, y); */
+ }
+
+ _OnMouseEvent(button, x, y, FALSE, keyFlags);
+}
+
+#ifdef FEAT_MENU
+/*
+ * Find the vimmenu_T with the given id
+ */
+ static vimmenu_T *
+gui_mswin_find_menu(
+ vimmenu_T *pMenu,
+ int id)
+{
+ vimmenu_T *pChildMenu;
+
+ while (pMenu)
+ {
+ if (pMenu->id == (UINT)id)
+ break;
+ if (pMenu->children != NULL)
+ {
+ pChildMenu = gui_mswin_find_menu(pMenu->children, id);
+ if (pChildMenu)
+ {
+ pMenu = pChildMenu;
+ break;
+ }
+ }
+ pMenu = pMenu->next;
+ }
+ return pMenu;
+}
+
+ static void
+_OnMenu(
+ HWND hwnd,
+ int id,
+ HWND hwndCtl,
+ UINT codeNotify)
+{
+ vimmenu_T *pMenu;
+
+ pMenu = gui_mswin_find_menu(root_menu, id);
+ if (pMenu)
+ gui_menu_cb(pMenu);
+}
+#endif
+
+#ifdef MSWIN_FIND_REPLACE
+/*
+ * Handle a Find/Replace window message.
+ */
+ static void
+_OnFindRepl(void)
+{
+ int flags = 0;
+ int down;
+
+ if (s_findrep_struct.Flags & FR_DIALOGTERM)
+ /* Give main window the focus back. */
+ (void)SetFocus(s_hwnd);
+
+ if (s_findrep_struct.Flags & FR_FINDNEXT)
+ {
+ flags = FRD_FINDNEXT;
+
+ /* Give main window the focus back: this is so the cursor isn't
+ * hollow. */
+ (void)SetFocus(s_hwnd);
+ }
+ else if (s_findrep_struct.Flags & FR_REPLACE)
+ {
+ flags = FRD_REPLACE;
+
+ /* Give main window the focus back: this is so the cursor isn't
+ * hollow. */
+ (void)SetFocus(s_hwnd);
+ }
+ else if (s_findrep_struct.Flags & FR_REPLACEALL)
+ {
+ flags = FRD_REPLACEALL;
+ }
+
+ if (flags != 0)
+ {
+ /* Call the generic GUI function to do the actual work. */
+ if (s_findrep_struct.Flags & FR_WHOLEWORD)
+ flags |= FRD_WHOLE_WORD;
+ if (s_findrep_struct.Flags & FR_MATCHCASE)
+ flags |= FRD_MATCH_CASE;
+ down = (s_findrep_struct.Flags & FR_DOWN) != 0;
+ gui_do_findrepl(flags, s_findrep_struct.lpstrFindWhat,
+ s_findrep_struct.lpstrReplaceWith, down);
+ }
+}
+#endif
+
+ static void
+HandleMouseHide(UINT uMsg, LPARAM lParam)
+{
+ static LPARAM last_lParam = 0L;
+
+ /* We sometimes get a mousemove when the mouse didn't move... */
+ if (uMsg == WM_MOUSEMOVE)
+ {
+ if (lParam == last_lParam)
+ return;
+ last_lParam = lParam;
+ }
+
+ /* Handle specially, to centralise coding. We need to be sure we catch all
+ * possible events which should cause us to restore the cursor (as it is a
+ * shared resource, we take full responsibility for it).
+ */
+ switch (uMsg)
+ {
+ case WM_KEYUP:
+ case WM_CHAR:
+ /*
+ * blank out the pointer if necessary
+ */
+ if (p_mh)
+ gui_mch_mousehide(TRUE);
+ break;
+
+ case WM_SYSKEYUP: /* show the pointer when a system-key is pressed */
+ case WM_SYSCHAR:
+ case WM_MOUSEMOVE: /* show the pointer on any mouse action */
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_MBUTTONDOWN:
+ case WM_MBUTTONUP:
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONUP:
+ case WM_XBUTTONDOWN:
+ case WM_XBUTTONUP:
+ case WM_NCMOUSEMOVE:
+ case WM_NCLBUTTONDOWN:
+ case WM_NCLBUTTONUP:
+ case WM_NCMBUTTONDOWN:
+ case WM_NCMBUTTONUP:
+ case WM_NCRBUTTONDOWN:
+ case WM_NCRBUTTONUP:
+ case WM_KILLFOCUS:
+ /*
+ * if the pointer is currently hidden, then we should show it.
+ */
+ gui_mch_mousehide(FALSE);
+ break;
+ }
+}
+
+ static LRESULT CALLBACK
+_TextAreaWndProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ /*
+ TRACE("TextAreaWndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n",
+ hwnd, uMsg, wParam, lParam);
+ */
+
+ HandleMouseHide(uMsg, lParam);
+
+ s_uMsg = uMsg;
+ s_wParam = wParam;
+ s_lParam = lParam;
+
+#ifdef FEAT_BEVAL
+ TrackUserActivity(uMsg);
+#endif
+
+ switch (uMsg)
+ {
+ HANDLE_MSG(hwnd, WM_LBUTTONDBLCLK,_OnMouseButtonDown);
+ HANDLE_MSG(hwnd, WM_LBUTTONDOWN,_OnMouseButtonDown);
+ HANDLE_MSG(hwnd, WM_LBUTTONUP, _OnMouseMoveOrRelease);
+ HANDLE_MSG(hwnd, WM_MBUTTONDBLCLK,_OnMouseButtonDown);
+ HANDLE_MSG(hwnd, WM_MBUTTONDOWN,_OnMouseButtonDown);
+ HANDLE_MSG(hwnd, WM_MBUTTONUP, _OnMouseMoveOrRelease);
+ HANDLE_MSG(hwnd, WM_MOUSEMOVE, _OnMouseMoveOrRelease);
+ HANDLE_MSG(hwnd, WM_PAINT, _OnPaint);
+ HANDLE_MSG(hwnd, WM_RBUTTONDBLCLK,_OnMouseButtonDown);
+ HANDLE_MSG(hwnd, WM_RBUTTONDOWN,_OnMouseButtonDown);
+ HANDLE_MSG(hwnd, WM_RBUTTONUP, _OnMouseMoveOrRelease);
+#ifndef WIN16 /*<VN>*/
+ HANDLE_MSG(hwnd, WM_XBUTTONDBLCLK,_OnMouseButtonDown);
+ HANDLE_MSG(hwnd, WM_XBUTTONDOWN,_OnMouseButtonDown);
+ HANDLE_MSG(hwnd, WM_XBUTTONUP, _OnMouseMoveOrRelease);
+#endif
+
+#ifdef FEAT_BEVAL
+ case WM_NOTIFY: Handle_WM_Notify(hwnd, (LPNMHDR)lParam);
+ return TRUE;
+#endif
+
+ default:
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+}
+
+#if (defined(WIN3264) && defined(FEAT_MBYTE)) \
+ || defined(GLOBAL_IME) \
+ || defined(PROTO)
+# ifdef PROTO
+typedef int WINAPI;
+# endif
+
+ LRESULT WINAPI
+vim_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+# ifdef GLOBAL_IME
+ return global_ime_DefWindowProc(hwnd, message, wParam, lParam);
+# else
+ if (wide_WindowProc)
+ return DefWindowProcW(hwnd, message, wParam, lParam);
+ return DefWindowProc(hwnd, message, wParam, lParam);
+#endif
+}
+#endif
+
+/*
+ * Called when the foreground or background color has been changed.
+ */
+ void
+gui_mch_new_colors(void)
+{
+ /* nothing to do? */
+}
+
+/*
+ * Set the colors to their default values.
+ */
+ void
+gui_mch_def_colors()
+{
+ gui.norm_pixel = GetSysColor(COLOR_WINDOWTEXT);
+ gui.back_pixel = GetSysColor(COLOR_WINDOW);
+ gui.def_norm_pixel = gui.norm_pixel;
+ gui.def_back_pixel = gui.back_pixel;
+}
+
+/*
+ * Open the GUI window which was created by a call to gui_mch_init().
+ */
+ int
+gui_mch_open(void)
+{
+#ifndef SW_SHOWDEFAULT
+# define SW_SHOWDEFAULT 10 /* Borland 5.0 doesn't have it */
+#endif
+ /* Actually open the window, if not already visible
+ * (may be done already in gui_mch_set_shellsize) */
+ if (!IsWindowVisible(s_hwnd))
+ ShowWindow(s_hwnd, SW_SHOWDEFAULT);
+
+ return OK;
+}
+
+/*
+ * Get the position of the top left corner of the window.
+ */
+ int
+gui_mch_get_winpos(int *x, int *y)
+{
+ RECT rect;
+
+ GetWindowRect(s_hwnd, &rect);
+ *x = rect.left;
+ *y = rect.top;
+ return OK;
+}
+
+/*
+ * Set the position of the top left corner of the window to the given
+ * coordinates.
+ */
+ void
+gui_mch_set_winpos(int x, int y)
+{
+ SetWindowPos(s_hwnd, NULL, x, y, 0, 0,
+ SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
+}
+ void
+gui_mch_set_text_area_pos(int x, int y, int w, int h)
+{
+ static int oldx = 0;
+ static int oldy = 0;
+
+ SetWindowPos(s_textArea, NULL, x, y, w, h, SWP_NOZORDER | SWP_NOACTIVATE);
+
+#ifdef FEAT_TOOLBAR
+ if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
+ SendMessage(s_toolbarhwnd, WM_SIZE,
+ (WPARAM)0, (LPARAM)(w + ((long)(TOOLBAR_BUTTON_HEIGHT+8)<<16)));
+#endif
+ /* When side scroll bar is unshown, the size of window will change.
+ * then, the text area move left or right. thus client rect should be
+ * forcely redraw. (Yasuhiro Matsumoto) */
+ if (oldx != x || oldy != y)
+ {
+ InvalidateRect(s_hwnd, NULL, FALSE);
+ oldx = x;
+ oldy = y;
+ }
+
+}
+
+
+/*
+ * Scrollbar stuff:
+ */
+
+ void
+gui_mch_enable_scrollbar(
+ scrollbar_T *sb,
+ int flag)
+{
+ ShowScrollBar(sb->id, SB_CTL, flag);
+
+ /* TODO: When the window is maximized, the size of the window stays the
+ * same, thus the size of the text area changes. On Win98 it's OK, on Win
+ * NT 4.0 it's not... */
+}
+
+ void
+gui_mch_set_scrollbar_pos(
+ scrollbar_T *sb,
+ int x,
+ int y,
+ int w,
+ int h)
+{
+ SetWindowPos(sb->id, NULL, x, y, w, h, SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
+}
+
+ void
+gui_mch_create_scrollbar(
+ scrollbar_T *sb,
+ int orient) /* SBAR_VERT or SBAR_HORIZ */
+{
+ sb->id = CreateWindow(
+ "SCROLLBAR", "Scrollbar",
+ WS_CHILD | ((orient == SBAR_VERT) ? SBS_VERT : SBS_HORZ), 0, 0,
+ 10, /* Any value will do for now */
+ 10, /* Any value will do for now */
+ s_hwnd, NULL,
+ s_hinst, NULL);
+}
+
+/*
+ * Find the scrollbar with the given hwnd.
+ */
+ static scrollbar_T *
+gui_mswin_find_scrollbar(HWND hwnd)
+{
+ win_T *wp;
+
+ if (gui.bottom_sbar.id == hwnd)
+ return &gui.bottom_sbar;
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_scrollbars[SBAR_LEFT].id == hwnd)
+ return &wp->w_scrollbars[SBAR_LEFT];
+ if (wp->w_scrollbars[SBAR_RIGHT].id == hwnd)
+ return &wp->w_scrollbars[SBAR_RIGHT];
+ }
+ return NULL;
+}
+
+/*
+ * Get the character size of a font.
+ */
+ static void
+GetFontSize(GuiFont font)
+{
+ HWND hwnd = GetDesktopWindow();
+ HDC hdc = GetWindowDC(hwnd);
+ HFONT hfntOld = SelectFont(hdc, (HFONT)font);
+ TEXTMETRIC tm;
+
+ GetTextMetrics(hdc, &tm);
+ gui.char_width = tm.tmAveCharWidth + tm.tmOverhang;
+
+ gui.char_height = tm.tmHeight
+#ifndef MSWIN16_FASTTEXT
+ + p_linespace
+#endif
+ ;
+
+ SelectFont(hdc, hfntOld);
+
+ ReleaseDC(hwnd, hdc);
+}
+
+ int
+gui_mch_adjust_charsize(void)
+{
+ GetFontSize(gui.norm_font);
+ return OK;
+}
+
+ static GuiFont
+get_font_handle(LOGFONT *lf)
+{
+ HFONT font = NULL;
+
+ /* Load the font */
+ font = CreateFontIndirect(lf);
+
+ if (font == NULL)
+ return NOFONT;
+
+ return (GuiFont)font;
+}
+
+ static int
+pixels_to_points(int pixels, int vertical)
+{
+ int points;
+ HWND hwnd;
+ HDC hdc;
+
+ hwnd = GetDesktopWindow();
+ hdc = GetWindowDC(hwnd);
+
+ points = MulDiv(pixels, 72,
+ GetDeviceCaps(hdc, vertical ? LOGPIXELSY : LOGPIXELSX));
+
+ ReleaseDC(hwnd, hdc);
+
+ return points;
+}
+
+ GuiFont
+gui_mch_get_font(
+ char_u *name,
+ int giveErrorIfMissing)
+{
+ LOGFONT lf;
+ GuiFont font;
+
+ get_logfont(&lf, name, NULL);
+ font = get_font_handle(&lf);
+ if (font == NOFONT && giveErrorIfMissing)
+ EMSG2(_(e_font), name);
+ return font;
+}
+ void
+gui_mch_free_font(GuiFont font)
+{
+ if (font)
+ DeleteObject((HFONT)font);
+}
+
+ static int
+hex_digit(int c)
+{
+ if (VIM_ISDIGIT(c))
+ return c - '0';
+ c = TOLOWER_ASC(c);
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return -1000;
+}
+/*
+ * Return the Pixel value (color) for the given color name.
+ * Return INVALCOLOR for error.
+ */
+ guicolor_T
+gui_mch_get_color(char_u *name)
+{
+ typedef struct guicolor_tTable
+ {
+ char *name;
+ COLORREF color;
+ } guicolor_tTable;
+
+ static guicolor_tTable table[] =
+ {
+ {"Black", RGB(0x00, 0x00, 0x00)},
+ {"DarkGray", RGB(0x80, 0x80, 0x80)},
+ {"DarkGrey", RGB(0x80, 0x80, 0x80)},
+ {"Gray", RGB(0xC0, 0xC0, 0xC0)},
+ {"Grey", RGB(0xC0, 0xC0, 0xC0)},
+ {"LightGray", RGB(0xE0, 0xE0, 0xE0)},
+ {"LightGrey", RGB(0xE0, 0xE0, 0xE0)},
+ {"White", RGB(0xFF, 0xFF, 0xFF)},
+ {"DarkRed", RGB(0x80, 0x00, 0x00)},
+ {"Red", RGB(0xFF, 0x00, 0x00)},
+ {"LightRed", RGB(0xFF, 0xA0, 0xA0)},
+ {"DarkBlue", RGB(0x00, 0x00, 0x80)},
+ {"Blue", RGB(0x00, 0x00, 0xFF)},
+ {"LightBlue", RGB(0xA0, 0xA0, 0xFF)},
+ {"DarkGreen", RGB(0x00, 0x80, 0x00)},
+ {"Green", RGB(0x00, 0xFF, 0x00)},
+ {"LightGreen", RGB(0xA0, 0xFF, 0xA0)},
+ {"DarkCyan", RGB(0x00, 0x80, 0x80)},
+ {"Cyan", RGB(0x00, 0xFF, 0xFF)},
+ {"LightCyan", RGB(0xA0, 0xFF, 0xFF)},
+ {"DarkMagenta", RGB(0x80, 0x00, 0x80)},
+ {"Magenta", RGB(0xFF, 0x00, 0xFF)},
+ {"LightMagenta", RGB(0xFF, 0xA0, 0xFF)},
+ {"Brown", RGB(0x80, 0x40, 0x40)},
+ {"Yellow", RGB(0xFF, 0xFF, 0x00)},
+ {"LightYellow", RGB(0xFF, 0xFF, 0xA0)},
+ {"DarkYellow", RGB(0xBB, 0xBB, 0x00)},
+ {"SeaGreen", RGB(0x2E, 0x8B, 0x57)},
+ {"Orange", RGB(0xFF, 0xA5, 0x00)},
+ {"Purple", RGB(0xA0, 0x20, 0xF0)},
+ {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)},
+ {"Violet", RGB(0xEE, 0x82, 0xEE)},
+ };
+
+ typedef struct SysColorTable
+ {
+ char *name;
+ int color;
+ } SysColorTable;
+
+ static SysColorTable sys_table[] =
+ {
+#ifdef WIN3264
+ {"SYS_3DDKSHADOW", COLOR_3DDKSHADOW},
+ {"SYS_3DHILIGHT", COLOR_3DHILIGHT},
+#ifndef __MINGW32__
+ {"SYS_3DHIGHLIGHT", COLOR_3DHIGHLIGHT},
+#endif
+ {"SYS_BTNHILIGHT", COLOR_BTNHILIGHT},
+ {"SYS_BTNHIGHLIGHT", COLOR_BTNHIGHLIGHT},
+ {"SYS_3DLIGHT", COLOR_3DLIGHT},
+ {"SYS_3DSHADOW", COLOR_3DSHADOW},
+ {"SYS_DESKTOP", COLOR_DESKTOP},
+ {"SYS_INFOBK", COLOR_INFOBK},
+ {"SYS_INFOTEXT", COLOR_INFOTEXT},
+ {"SYS_3DFACE", COLOR_3DFACE},
+#endif
+ {"SYS_BTNFACE", COLOR_BTNFACE},
+ {"SYS_BTNSHADOW", COLOR_BTNSHADOW},
+ {"SYS_ACTIVEBORDER", COLOR_ACTIVEBORDER},
+ {"SYS_ACTIVECAPTION", COLOR_ACTIVECAPTION},
+ {"SYS_APPWORKSPACE", COLOR_APPWORKSPACE},
+ {"SYS_BACKGROUND", COLOR_BACKGROUND},
+ {"SYS_BTNTEXT", COLOR_BTNTEXT},
+ {"SYS_CAPTIONTEXT", COLOR_CAPTIONTEXT},
+ {"SYS_GRAYTEXT", COLOR_GRAYTEXT},
+ {"SYS_HIGHLIGHT", COLOR_HIGHLIGHT},
+ {"SYS_HIGHLIGHTTEXT", COLOR_HIGHLIGHTTEXT},
+ {"SYS_INACTIVEBORDER", COLOR_INACTIVEBORDER},
+ {"SYS_INACTIVECAPTION", COLOR_INACTIVECAPTION},
+ {"SYS_INACTIVECAPTIONTEXT", COLOR_INACTIVECAPTIONTEXT},
+ {"SYS_MENU", COLOR_MENU},
+ {"SYS_MENUTEXT", COLOR_MENUTEXT},
+ {"SYS_SCROLLBAR", COLOR_SCROLLBAR},
+ {"SYS_WINDOW", COLOR_WINDOW},
+ {"SYS_WINDOWFRAME", COLOR_WINDOWFRAME},
+ {"SYS_WINDOWTEXT", COLOR_WINDOWTEXT}
+ };
+
+ int r, g, b;
+ int i;
+
+ if (name[0] == '#' && strlen(name) == 7)
+ {
+ /* Name is in "#rrggbb" format */
+ r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
+ g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
+ b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
+ if (r < 0 || g < 0 || b < 0)
+ return INVALCOLOR;
+ return RGB(r, g, b);
+ }
+ else
+ {
+ /* Check if the name is one of the colors we know */
+ for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
+ if (STRICMP(name, table[i].name) == 0)
+ return table[i].color;
+ }
+
+ /*
+ * Try to look up a system colour.
+ */
+ for (i = 0; i < sizeof(sys_table) / sizeof(sys_table[0]); i++)
+ if (STRICMP(name, sys_table[i].name) == 0)
+ return GetSysColor(sys_table[i].color);
+
+ /*
+ * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt".
+ */
+ {
+#define LINE_LEN 100
+ FILE *fd;
+ char line[LINE_LEN];
+ char_u *fname;
+
+ fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
+ if (fname == NULL)
+ return INVALCOLOR;
+
+ fd = fopen((char *)fname, "rt");
+ vim_free(fname);
+ if (fd == NULL)
+ return INVALCOLOR;
+
+ while (!feof(fd))
+ {
+ int len;
+ int pos;
+ char *color;
+
+ fgets(line, LINE_LEN, fd);
+ len = (int)STRLEN(line);
+
+ if (len <= 1 || line[len-1] != '\n')
+ continue;
+
+ line[len-1] = '\0';
+
+ i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
+ if (i != 3)
+ continue;
+
+ color = line + pos;
+
+ if (STRICMP(color, name) == 0)
+ {
+ fclose(fd);
+ return (guicolor_T) RGB(r, g, b);
+ }
+ }
+
+ fclose(fd);
+ }
+
+ return INVALCOLOR;
+}
+/*
+ * Return OK if the key with the termcap name "name" is supported.
+ */
+ int
+gui_mch_haskey(char_u *name)
+{
+ int i;
+
+ for (i = 0; special_keys[i].vim_code1 != NUL; i++)
+ if (name[0] == special_keys[i].vim_code0 &&
+ name[1] == special_keys[i].vim_code1)
+ return OK;
+ return FAIL;
+}
+
+ void
+gui_mch_beep(void)
+{
+ MessageBeep(MB_OK);
+}
+/*
+ * Invert a rectangle from row r, column c, for nr rows and nc columns.
+ */
+ void
+gui_mch_invert_rectangle(
+ int r,
+ int c,
+ int nr,
+ int nc)
+{
+ RECT rc;
+
+ /*
+ * Note: InvertRect() excludes right and bottom of rectangle.
+ */
+ rc.left = FILL_X(c);
+ rc.top = FILL_Y(r);
+ rc.right = rc.left + nc * gui.char_width;
+ rc.bottom = rc.top + nr * gui.char_height;
+ InvertRect(s_hdc, &rc);
+}
+
+/*
+ * Iconify the GUI window.
+ */
+ void
+gui_mch_iconify(void)
+{
+ ShowWindow(s_hwnd, SW_MINIMIZE);
+}
+
+/*
+ * Draw a cursor without focus.
+ */
+ void
+gui_mch_draw_hollow_cursor(guicolor_T color)
+{
+ HBRUSH hbr;
+ RECT rc;
+
+ /*
+ * Note: FrameRect() excludes right and bottom of rectangle.
+ */
+ rc.left = FILL_X(gui.col);
+ rc.top = FILL_Y(gui.row);
+ rc.right = rc.left + gui.char_width;
+#ifdef FEAT_MBYTE
+ if (mb_lefthalve(gui.row, gui.col))
+ rc.right += gui.char_width;
+#endif
+ rc.bottom = rc.top + gui.char_height;
+ hbr = CreateSolidBrush(color);
+ FrameRect(s_hdc, &rc, hbr);
+ DeleteBrush(hbr);
+}
+/*
+ * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using
+ * color "color".
+ */
+ void
+gui_mch_draw_part_cursor(
+ int w,
+ int h,
+ guicolor_T color)
+{
+ HBRUSH hbr;
+ RECT rc;
+
+ /*
+ * Note: FillRect() excludes right and bottom of rectangle.
+ */
+ rc.left =
+#ifdef FEAT_RIGHTLEFT
+ /* vertical line should be on the right of current point */
+ CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
+#endif
+ FILL_X(gui.col);
+ rc.top = FILL_Y(gui.row) + gui.char_height - h;
+ rc.right = rc.left + w;
+ rc.bottom = rc.top + h;
+ hbr = CreateSolidBrush(color);
+ FillRect(s_hdc, &rc, hbr);
+ DeleteBrush(hbr);
+}
+
+/*
+ * Process a single Windows message.
+ * If one is not available we hang until one is.
+ */
+ static void
+process_message(void)
+{
+ MSG msg;
+ UINT vk = 0; /* Virtual key */
+ char_u string[40];
+ int i;
+ int modifiers = 0;
+ int key;
+
+ GetMessage(&msg, NULL, 0, 0);
+
+#ifdef FEAT_OLE
+ /* Look after OLE Automation commands */
+ if (msg.message == WM_OLE)
+ {
+ char_u *str = (char_u *)msg.lParam;
+ add_to_input_buf(str, (int)STRLEN(str));
+ vim_free(str);
+ return;
+ }
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+ if (msg.message == WM_NETBEANS)
+ {
+ messageFromNetbeansW32();
+ return;
+ }
+#endif
+
+#ifdef FEAT_SNIFF
+ if (sniff_request_waiting && want_sniff_request)
+ {
+ static char_u bytes[3] = {CSI, (char_u)KS_EXTRA, (char_u)KE_SNIFF};
+ add_to_input_buf(bytes, 3); /* K_SNIFF */
+ sniff_request_waiting = 0;
+ want_sniff_request = 0;
+ /* request is handled in normal.c */
+ }
+ if (msg.message == WM_USER)
+ return;
+#endif
+
+#ifdef MSWIN_FIND_REPLACE
+ /* Don't process messages used by the dialog */
+ if (s_findrep_hwnd != NULL && IsDialogMessage(s_findrep_hwnd, &msg))
+ {
+ HandleMouseHide(msg.message, msg.lParam);
+ return;
+ }
+#endif
+
+ /*
+ * Check if it's a special key that we recognise. If not, call
+ * TranslateMessage().
+ */
+ if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
+ {
+ vk = (int) msg.wParam;
+ /* handle key after dead key, but ignore shift, alt and control */
+ if (dead_key && vk != VK_SHIFT && vk != VK_MENU && vk != VK_CONTROL)
+ {
+ dead_key = 0;
+ /* handle non-alphabetic keys (ones that hopefully cannot generate
+ * umlaut-characters), unless when control is down */
+ if (vk < 'A' || vk > 'Z' || (GetKeyState(VK_CONTROL) & 0x8000))
+ {
+ MSG dm;
+
+ dm.message = msg.message;
+ dm.hwnd = msg.hwnd;
+ dm.wParam = VK_SPACE;
+ MyTranslateMessage(&dm); /* generate dead character */
+ if (vk != VK_SPACE) /* and send current character once more */
+ PostMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam);
+ return;
+ }
+ }
+
+ /* Check for CTRL-BREAK */
+ if (vk == VK_CANCEL)
+ {
+ trash_input_buf();
+ got_int = TRUE;
+ string[0] = Ctrl_C;
+ add_to_input_buf(string, 1);
+ }
+
+ for (i = 0; special_keys[i].key_sym != 0; i++)
+ {
+ /* ignore VK_SPACE when ALT key pressed: system menu */
+ if (special_keys[i].key_sym == vk
+ && (vk != VK_SPACE || !(GetKeyState(VK_MENU) & 0x8000)))
+ {
+#ifdef FEAT_MENU
+ /* Check for <F10>: Windows selects the menu. Ignore it when
+ * 'winaltkeys' is "yes" or "menu" */
+ if (vk == VK_F10
+ && gui.menu_is_active
+ && (*p_wak == 'y' || *p_wak == 'm'))
+ break;
+#endif
+ if (GetKeyState(VK_SHIFT) & 0x8000)
+ modifiers |= MOD_MASK_SHIFT;
+ /*
+ * Don't use caps-lock as shift, because these are special keys
+ * being considered here, and we only want letters to get
+ * shifted -- webb
+ */
+ /*
+ if (GetKeyState(VK_CAPITAL) & 0x0001)
+ modifiers ^= MOD_MASK_SHIFT;
+ */
+ if (GetKeyState(VK_CONTROL) & 0x8000)
+ modifiers |= MOD_MASK_CTRL;
+ if (GetKeyState(VK_MENU) & 0x8000)
+ modifiers |= MOD_MASK_ALT;
+
+ if (special_keys[i].vim_code1 == NUL)
+ key = special_keys[i].vim_code0;
+ else
+ key = TO_SPECIAL(special_keys[i].vim_code0,
+ special_keys[i].vim_code1);
+ key = simplify_key(key, &modifiers);
+ if (key == CSI)
+ key = K_CSI;
+
+ if (modifiers)
+ {
+ string[0] = CSI;
+ string[1] = KS_MODIFIER;
+ string[2] = modifiers;
+ add_to_input_buf(string, 3);
+ }
+
+ if (IS_SPECIAL(key))
+ {
+ string[0] = CSI;
+ string[1] = K_SECOND(key);
+ string[2] = K_THIRD(key);
+ add_to_input_buf(string, 3);
+ }
+ else
+ {
+ int len;
+
+ /* Handle "key" as a Unicode character. */
+ len = char_to_string(key, string, 40);
+ add_to_input_buf(string, len);
+ }
+ break;
+ }
+ }
+ if (special_keys[i].key_sym == 0)
+ {
+ /* Some keys need C-S- where they should only need C-.
+ * Ignore 0xff, Windows XP sends it when NUMLOCK has changed since
+ * system startup (Helmut Stiegler, 2003 Oct 3). */
+ if (vk != 0xff
+ && (GetKeyState(VK_CONTROL) & 0x8000)
+ && !(GetKeyState(VK_SHIFT) & 0x8000)
+ && !(GetKeyState(VK_MENU) & 0x8000))
+ {
+ /* CTRL-6 is '^'; Japanese keyboard maps '^' to vk == 0xDE */
+ if (vk == '6' || MapVirtualKey(vk, 2) == (UINT)'^')
+ {
+ string[0] = Ctrl_HAT;
+ add_to_input_buf(string, 1);
+ }
+ /* vk == 0xBD AZERTY for CTRL-'-', but CTRL-[ for * QWERTY! */
+ else if (vk == 0xBD) /* QWERTY for CTRL-'-' */
+ {
+ string[0] = Ctrl__;
+ add_to_input_buf(string, 1);
+ }
+ /* CTRL-2 is '@'; Japanese keyboard maps '@' to vk == 0xC0 */
+ else if (vk == '2' || MapVirtualKey(vk, 2) == (UINT)'@')
+ {
+ string[0] = Ctrl_AT;
+ add_to_input_buf(string, 1);
+ }
+ else
+ MyTranslateMessage(&msg);
+ }
+ else
+ MyTranslateMessage(&msg);
+ }
+ }
+#ifdef FEAT_MBYTE_IME
+ else if (msg.message == WM_IME_NOTIFY)
+ _OnImeNotify(msg.hwnd, (DWORD)msg.wParam, (DWORD)msg.lParam);
+ else if (msg.message == WM_KEYUP && im_get_status())
+ /* added for non-MS IME (Yasuhiro Matsumoto) */
+ MyTranslateMessage(&msg);
+#endif
+#if !defined(FEAT_MBYTE_IME) && defined(GLOBAL_IME)
+/* GIME_TEST */
+ else if (msg.message == WM_IME_STARTCOMPOSITION)
+ {
+ POINT point;
+
+ global_ime_set_font(&norm_logfont);
+ point.x = FILL_X(gui.col);
+ point.y = FILL_Y(gui.row);
+ MapWindowPoints(s_textArea, s_hwnd, &point, 1);
+ global_ime_set_position(&point);
+ }
+#endif
+
+#ifdef FEAT_MENU
+ /* Check for <F10>: Windows selects the menu. Don't let Windows handle it
+ * when 'winaltkeys' is "no" */
+ if (vk != VK_F10 || *p_wak != 'n')
+#endif
+ DispatchMessage(&msg);
+}
+
+/*
+ * Catch up with any queued events. This may put keyboard input into the
+ * input buffer, call resize call-backs, trigger timers etc. If there is
+ * nothing in the event queue (& no timers pending), then we return
+ * immediately.
+ */
+ void
+gui_mch_update(void)
+{
+ MSG msg;
+
+ if (!s_busy_processing)
+ while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)
+ && !vim_is_input_buf_full())
+ process_message();
+}
+
+/*
+ * GUI input routine called by gui_wait_for_chars(). Waits for a character
+ * from the keyboard.
+ * wtime == -1 Wait forever.
+ * wtime == 0 This should never happen.
+ * wtime > 0 Wait wtime milliseconds for a character.
+ * Returns OK if a character was found to be available within the given time,
+ * or FAIL otherwise.
+ */
+ int
+gui_mch_wait_for_chars(int wtime)
+{
+ MSG msg;
+ int focus;
+
+ s_timed_out = FALSE;
+
+ if (wtime > 0)
+ {
+ /* Don't do anything while processing a (scroll) message. */
+ if (s_busy_processing)
+ return FAIL;
+ s_wait_timer = (UINT)SetTimer(NULL, 0, (UINT)wtime,
+ (TIMERPROC)_OnTimer);
+ }
+
+ allow_scrollbar = TRUE;
+
+ focus = gui.in_focus;
+ while (!s_timed_out)
+ {
+ /* Stop or start blinking when focus changes */
+ if (gui.in_focus != focus)
+ {
+ if (gui.in_focus)
+ gui_mch_start_blink();
+ else
+ gui_mch_stop_blink();
+ focus = gui.in_focus;
+ }
+
+ if (s_need_activate)
+ {
+#ifdef WIN32
+ (void)SetForegroundWindow(s_hwnd);
+#else
+ (void)SetActiveWindow(s_hwnd);
+#endif
+ s_need_activate = FALSE;
+ }
+
+ /*
+ * Don't use gui_mch_update() because then we will spin-lock until a
+ * char arrives, instead we use GetMessage() to hang until an
+ * event arrives. No need to check for input_buf_full because we are
+ * returning as soon as it contains a single char -- webb
+ */
+ process_message();
+
+ if (input_available())
+ {
+ if (s_wait_timer != 0 && !s_timed_out)
+ {
+ KillTimer(NULL, s_wait_timer);
+
+ /* Eat spurious WM_TIMER messages */
+ while (PeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
+ ;
+ s_wait_timer = 0;
+ }
+ allow_scrollbar = FALSE;
+ return OK;
+ }
+ }
+ allow_scrollbar = FALSE;
+ return FAIL;
+}
+
+/*
+ * Clear a rectangular region of the screen from text pos (row1, col1) to
+ * (row2, col2) inclusive.
+ */
+ void
+gui_mch_clear_block(
+ int row1,
+ int col1,
+ int row2,
+ int col2)
+{
+ RECT rc;
+
+ /*
+ * Clear one extra pixel at the far right, for when bold characters have
+ * spilled over to the window border.
+ * Note: FillRect() excludes right and bottom of rectangle.
+ */
+ rc.left = FILL_X(col1);
+ rc.top = FILL_Y(row1);
+ rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
+ rc.bottom = FILL_Y(row2 + 1);
+ clear_rect(&rc);
+}
+
+/*
+ * Clear the whole text window.
+ */
+ void
+gui_mch_clear_all(void)
+{
+ RECT rc;
+
+ rc.left = 0;
+ rc.top = 0;
+ rc.right = Columns * gui.char_width + 2 * gui.border_width;
+ rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
+ clear_rect(&rc);
+}
+/*
+ * Menu stuff.
+ */
+
+ void
+gui_mch_enable_menu(int flag)
+{
+#ifdef FEAT_MENU
+ SetMenu(s_hwnd, flag ? s_menuBar : NULL);
+#endif
+}
+
+ void
+gui_mch_set_menu_pos(
+ int x,
+ int y,
+ int w,
+ int h)
+{
+ /* It will be in the right place anyway */
+}
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Make menu item hidden or not hidden
+ */
+ void
+gui_mch_menu_hidden(
+ vimmenu_T *menu,
+ int hidden)
+{
+ /*
+ * This doesn't do what we want. Hmm, just grey the menu items for now.
+ */
+ /*
+ if (hidden)
+ EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_DISABLED);
+ else
+ EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_ENABLED);
+ */
+ gui_mch_menu_grey(menu, hidden);
+}
+
+/*
+ * This is called after setting all the menus to grey/hidden or not.
+ */
+ void
+gui_mch_draw_menubar(void)
+{
+ DrawMenuBar(s_hwnd);
+}
+#endif /*FEAT_MENU*/
+
+#ifndef PROTO
+void
+#ifdef VIMDLL
+_export
+#endif
+_cdecl
+SaveInst(HINSTANCE hInst)
+{
+ s_hinst = hInst;
+}
+#endif
+
+/*
+ * Return the RGB value of a pixel as a long.
+ */
+ long_u
+gui_mch_get_rgb(guicolor_T pixel)
+{
+ return (GetRValue(pixel) << 16) + (GetGValue(pixel) << 8)
+ + GetBValue(pixel);
+}
+
+#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
+/* Convert pixels in X to dialog units */
+ static WORD
+PixelToDialogX(int numPixels)
+{
+ return (WORD)((numPixels * 4) / s_dlgfntwidth);
+}
+
+/* Convert pixels in Y to dialog units */
+ static WORD
+PixelToDialogY(int numPixels)
+{
+ return (WORD)((numPixels * 8) / s_dlgfntheight);
+}
+
+/* Return the width in pixels of the given text in the given DC. */
+ static int
+GetTextWidth(HDC hdc, char_u *str, int len)
+{
+ SIZE size;
+
+ GetTextExtentPoint(hdc, str, len, &size);
+ return size.cx;
+}
+
+#ifdef FEAT_MBYTE
+/*
+ * Return the width in pixels of the given text in the given DC, taking care
+ * of 'encoding' to active codepage conversion.
+ */
+ static int
+GetTextWidthEnc(HDC hdc, char_u *str, int len)
+{
+ SIZE size;
+ WCHAR *wstr;
+ int n;
+ int wlen = len;
+
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+ /* 'encoding' differs from active codepage: convert text and use wide
+ * function */
+ wstr = enc_to_ucs2(str, &wlen);
+ if (wstr != NULL)
+ {
+ n = GetTextExtentPointW(hdc, wstr, wlen, &size);
+ vim_free(wstr);
+ if (n)
+ return size.cx;
+ }
+ }
+
+ return GetTextWidth(hdc, str, len);
+}
+#else
+# define GetTextWidthEnc(h, s, l) GetTextWidth((h), (s), (l))
+#endif
+
+/*
+ * A quick little routine that will center one window over another, handy for
+ * dialog boxes. Taken from the Win32SDK samples.
+ */
+ static BOOL
+CenterWindow(
+ HWND hwndChild,
+ HWND hwndParent)
+{
+ RECT rChild, rParent;
+ int wChild, hChild, wParent, hParent;
+ int wScreen, hScreen, xNew, yNew;
+ HDC hdc;
+
+ GetWindowRect(hwndChild, &rChild);
+ wChild = rChild.right - rChild.left;
+ hChild = rChild.bottom - rChild.top;
+
+ /* If Vim is minimized put the window in the middle of the screen. */
+ if (IsMinimized(hwndParent))
+ {
+#ifdef WIN16
+ rParent.left = 0;
+ rParent.top = 0;
+ rParent.right = GetSystemMetrics(SM_CXSCREEN);
+ rParent.bottom = GetSystemMetrics(SM_CYFULLSCREEN);
+#else
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &rParent, 0);
+#endif
+ }
+ else
+ GetWindowRect(hwndParent, &rParent);
+ wParent = rParent.right - rParent.left;
+ hParent = rParent.bottom - rParent.top;
+
+ hdc = GetDC(hwndChild);
+ wScreen = GetDeviceCaps (hdc, HORZRES);
+ hScreen = GetDeviceCaps (hdc, VERTRES);
+ ReleaseDC(hwndChild, hdc);
+
+ xNew = rParent.left + ((wParent - wChild) /2);
+ if (xNew < 0)
+ {
+ xNew = 0;
+ }
+ else if ((xNew+wChild) > wScreen)
+ {
+ xNew = wScreen - wChild;
+ }
+
+ yNew = rParent.top + ((hParent - hChild) /2);
+ if (yNew < 0)
+ yNew = 0;
+ else if ((yNew+hChild) > hScreen)
+ yNew = hScreen - hChild;
+
+ return SetWindowPos(hwndChild, NULL, xNew, yNew, 0, 0,
+ SWP_NOSIZE | SWP_NOZORDER);
+}
+#endif /* FEAT_GUI_DIALOG */
+
+void
+gui_mch_activate_window(void)
+{
+ (void)SetActiveWindow(s_hwnd);
+}
+
+#if defined(FEAT_TOOLBAR) || defined(PROTO)
+ void
+gui_mch_show_toolbar(int showit)
+{
+ if (s_toolbarhwnd == NULL)
+ return;
+
+ if (showit)
+ ShowWindow(s_toolbarhwnd, SW_SHOW);
+ else
+ ShowWindow(s_toolbarhwnd, SW_HIDE);
+}
+
+/* Then number of bitmaps is fixed. Exit is missing! */
+#define TOOLBAR_BITMAP_COUNT 31
+
+#endif
+
+/*
+ * ":simalt" command.
+ */
+ void
+ex_simalt(exarg_T *eap)
+{
+ char_u *keys = eap->arg;
+
+ PostMessage(s_hwnd, WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)0);
+ while (*keys)
+ {
+ if (*keys == '~')
+ *keys = ' '; /* for showing system menu */
+ PostMessage(s_hwnd, WM_CHAR, (WPARAM)*keys, (LPARAM)0);
+ keys++;
+ }
+}
+
+/*
+ * Create the find & replace dialogs.
+ * You can't have both at once: ":find" when replace is showing, destroys
+ * the replace dialog first, and the other way around.
+ */
+#ifdef MSWIN_FIND_REPLACE
+ static void
+initialise_findrep(char_u *initial_string)
+{
+ int wword = FALSE;
+ int mcase = !p_ic;
+ char_u *entry_text;
+
+ /* Get the search string to use. */
+ entry_text = get_find_dialog_text(initial_string, &wword, &mcase);
+
+ s_findrep_struct.hwndOwner = s_hwnd;
+ s_findrep_struct.Flags = FR_DOWN;
+ if (mcase)
+ s_findrep_struct.Flags |= FR_MATCHCASE;
+ if (wword)
+ s_findrep_struct.Flags |= FR_WHOLEWORD;
+ if (entry_text != NULL && *entry_text != NUL)
+ {
+ STRNCPY(s_findrep_struct.lpstrFindWhat, entry_text,
+ s_findrep_struct.wFindWhatLen);
+ s_findrep_struct.lpstrFindWhat[s_findrep_struct.wFindWhatLen - 1] = NUL;
+ s_findrep_struct.lpstrReplaceWith[0] = NUL;
+ }
+ vim_free(entry_text);
+}
+#endif
+
+ void
+gui_mch_find_dialog(exarg_T *eap)
+{
+#ifdef MSWIN_FIND_REPLACE
+ if (s_findrep_msg != 0)
+ {
+ if (IsWindow(s_findrep_hwnd) && !s_findrep_is_find)
+ DestroyWindow(s_findrep_hwnd);
+
+ if (!IsWindow(s_findrep_hwnd))
+ {
+ initialise_findrep(eap->arg);
+ s_findrep_hwnd = FindText((LPFINDREPLACE) &s_findrep_struct);
+ }
+
+ (void)SetWindowText(s_findrep_hwnd,
+ (LPCSTR)_("Find string (use '\\\\' to find a '\\')"));
+ (void)SetFocus(s_findrep_hwnd);
+
+ s_findrep_is_find = TRUE;
+ }
+#endif
+}
+
+
+ void
+gui_mch_replace_dialog(exarg_T *eap)
+{
+#ifdef MSWIN_FIND_REPLACE
+ if (s_findrep_msg != 0)
+ {
+ if (IsWindow(s_findrep_hwnd) && s_findrep_is_find)
+ DestroyWindow(s_findrep_hwnd);
+
+ if (!IsWindow(s_findrep_hwnd))
+ {
+ initialise_findrep(eap->arg);
+ s_findrep_hwnd = ReplaceText((LPFINDREPLACE) &s_findrep_struct);
+ }
+
+ (void)SetWindowText(s_findrep_hwnd,
+ (LPCSTR)_("Find & Replace (use '\\\\' to find a '\\')"));
+ (void)SetFocus(s_findrep_hwnd);
+
+ s_findrep_is_find = FALSE;
+ }
+#endif
+}
+
+
+/*
+ * Set visibility of the pointer.
+ */
+ void
+gui_mch_mousehide(int hide)
+{
+ if (hide != gui.pointer_hidden)
+ {
+ ShowCursor(!hide);
+ gui.pointer_hidden = hide;
+ }
+}
+
+#ifdef FEAT_MENU
+ static void
+gui_mch_show_popupmenu_at(vimmenu_T *menu, int x, int y)
+{
+ /* Unhide the mouse, we don't get move events here. */
+ gui_mch_mousehide(FALSE);
+
+ (void)TrackPopupMenu(
+ (HMENU)menu->submenu_id,
+ TPM_LEFTALIGN | TPM_LEFTBUTTON,
+ x, y,
+ (int)0, /*reserved param*/
+ s_hwnd,
+ NULL);
+ /*
+ * NOTE: The pop-up menu can eat the mouse up event.
+ * We deal with this in normal.c.
+ */
+}
+#endif
+
+/*
+ * Got a message when the system will go down.
+ */
+ static void
+_OnEndSession(void)
+{
+ getout_preserve_modified(1);
+}
+
+/*
+ * Get this message when the user clicks on the cross in the top right corner
+ * of a Windows95 window.
+ */
+ static void
+_OnClose(
+ HWND hwnd)
+{
+ gui_shell_closed();
+}
+
+/*
+ * Get a message when the window is being destroyed.
+ */
+ static void
+_OnDestroy(
+ HWND hwnd)
+{
+#ifdef WIN16_3DLOOK
+ Ctl3dUnregister(s_hinst);
+#endif
+ if (!destroying)
+ _OnClose(hwnd);
+}
+
+ static void
+_OnPaint(
+ HWND hwnd)
+{
+ if (!IsMinimized(hwnd))
+ {
+ PAINTSTRUCT ps;
+
+ out_flush(); /* make sure all output has been processed */
+ (void)BeginPaint(hwnd, &ps);
+
+#ifdef FEAT_MBYTE
+ /* prevent multi-byte characters from misprinting on an invalid
+ * rectangle */
+ if (has_mbyte)
+ {
+ RECT rect;
+
+ GetClientRect(hwnd, &rect);
+ ps.rcPaint.left = rect.left;
+ ps.rcPaint.right = rect.right;
+ }
+#endif
+
+ if (!IsRectEmpty(&ps.rcPaint))
+ gui_redraw(ps.rcPaint.left, ps.rcPaint.top,
+ ps.rcPaint.right - ps.rcPaint.left + 1,
+ ps.rcPaint.bottom - ps.rcPaint.top + 1);
+ EndPaint(hwnd, &ps);
+ }
+}
+
+ static void
+_OnSize(
+ HWND hwnd,
+ UINT state,
+ int cx,
+ int cy)
+{
+ if (!IsMinimized(hwnd))
+ {
+ gui_resize_shell(cx, cy);
+
+#ifdef FEAT_MENU
+ /* Menu bar may wrap differently now */
+ gui_mswin_get_menu_height(TRUE);
+#endif
+ }
+}
+
+ static void
+_OnSetFocus(
+ HWND hwnd,
+ HWND hwndOldFocus)
+{
+ gui_focus_change(TRUE);
+ (void)MyWindowProc(hwnd, WM_SETFOCUS, (WPARAM)hwndOldFocus, 0);
+}
+
+ static void
+_OnKillFocus(
+ HWND hwnd,
+ HWND hwndNewFocus)
+{
+ gui_focus_change(FALSE);
+ (void)MyWindowProc(hwnd, WM_KILLFOCUS, (WPARAM)hwndNewFocus, 0);
+}
+
+/*
+ * Get a message when the user switches back to vim
+ */
+#ifdef WIN16
+ static BOOL
+#else
+ static LRESULT
+#endif
+_OnActivateApp(
+ HWND hwnd,
+ BOOL fActivate,
+#ifdef WIN16
+ HTASK dwThreadId
+#else
+ DWORD dwThreadId
+#endif
+ )
+{
+ /* we call gui_focus_change() in _OnSetFocus() */
+ /* gui_focus_change((int)fActivate); */
+ return MyWindowProc(hwnd, WM_ACTIVATEAPP, fActivate, (DWORD)dwThreadId);
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+ void
+gui_mch_destroy_scrollbar(scrollbar_T *sb)
+{
+ DestroyWindow(sb->id);
+}
+#endif
+
+/*
+ * Get current x mouse coordinate in text window.
+ * Return -1 when unknown.
+ */
+ int
+gui_mch_get_mouse_x(void)
+{
+ RECT rct;
+ POINT mp;
+
+ (void)GetWindowRect(s_textArea, &rct);
+ (void)GetCursorPos((LPPOINT)&mp);
+ return (int)(mp.x - rct.left);
+}
+
+/*
+ * Get current y mouse coordinate in text window.
+ * Return -1 when unknown.
+ */
+ int
+gui_mch_get_mouse_y(void)
+{
+ RECT rct;
+ POINT mp;
+
+ (void)GetWindowRect(s_textArea, &rct);
+ (void)GetCursorPos((LPPOINT)&mp);
+ return (int)(mp.y - rct.top);
+}
+
+/*
+ * Move mouse pointer to character at (x, y).
+ */
+ void
+gui_mch_setmouse(int x, int y)
+{
+ RECT rct;
+
+ (void)GetWindowRect(s_textArea, &rct);
+ (void)SetCursorPos(x + gui.border_offset + rct.left,
+ y + gui.border_offset + rct.top);
+}
+
+ static void
+gui_mswin_get_valid_dimensions(
+ int w,
+ int h,
+ int *valid_w,
+ int *valid_h)
+{
+ int base_width, base_height;
+
+ base_width = gui_get_base_width()
+ + GetSystemMetrics(SM_CXFRAME) * 2;
+ base_height = gui_get_base_height()
+ + GetSystemMetrics(SM_CYFRAME) * 2
+ + GetSystemMetrics(SM_CYCAPTION)
+#ifdef FEAT_MENU
+ + gui_mswin_get_menu_height(FALSE)
+#endif
+ ;
+ *valid_w = base_width +
+ ((w - base_width) / gui.char_width) * gui.char_width;
+ *valid_h = base_height +
+ ((h - base_height) / gui.char_height) * gui.char_height;
+}
+
+ void
+gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
+{
+
+ *screen_w = GetSystemMetrics(SM_CXFULLSCREEN)
+ - GetSystemMetrics(SM_CXFRAME) * 2;
+ /* FIXME: dirty trick: Because the gui_get_base_height() doesn't include
+ * the menubar for MSwin, we subtract it from the screen height, so that
+ * the window size can be made to fit on the screen. */
+ *screen_h = GetSystemMetrics(SM_CYFULLSCREEN)
+ - GetSystemMetrics(SM_CYFRAME) * 2
+#ifdef FEAT_MENU
+ - gui_mswin_get_menu_height(FALSE)
+#endif
+ ;
+}
+
+ void
+gui_mch_flash(int msec)
+{
+ RECT rc;
+
+ /*
+ * Note: InvertRect() excludes right and bottom of rectangle.
+ */
+ rc.left = 0;
+ rc.top = 0;
+ rc.right = gui.num_cols * gui.char_width;
+ rc.bottom = gui.num_rows * gui.char_height;
+ InvertRect(s_hdc, &rc);
+ gui_mch_flush(); /* make sure it's displayed */
+
+ ui_delay((long)msec, TRUE); /* wait for a few msec */
+
+ InvertRect(s_hdc, &rc);
+}
+
+/*
+ * Return flags used for scrolling.
+ * The SW_INVALIDATE is required when part of the window is covered or
+ * off-screen. Refer to MS KB Q75236.
+ */
+ static int
+get_scroll_flags(void)
+{
+ HWND hwnd;
+ RECT rcVim, rcOther, rcDest;
+
+ GetWindowRect(s_hwnd, &rcVim);
+ for (hwnd = s_hwnd; (hwnd = GetWindow(hwnd, GW_HWNDPREV)) != (HWND)0; )
+ if (IsWindowVisible(hwnd))
+ {
+ GetWindowRect(hwnd, &rcOther);
+ if (IntersectRect(&rcDest, &rcVim, &rcOther))
+ return SW_INVALIDATE;
+ }
+ return 0;
+}
+
+/*
+ * Delete the given number of lines from the given row, scrolling up any
+ * text further down within the scroll region.
+ */
+ void
+gui_mch_delete_lines(
+ int row,
+ int num_lines)
+{
+ RECT rc;
+
+ rc.left = FILL_X(gui.scroll_region_left);
+ rc.right = FILL_X(gui.scroll_region_right + 1);
+ rc.top = FILL_Y(row);
+ rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
+
+ ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height,
+ &rc, &rc, NULL, NULL, get_scroll_flags());
+
+ UpdateWindow(s_textArea);
+ /* This seems to be required to avoid the cursor disappearing when
+ * scrolling such that the cursor ends up in the top-left character on
+ * the screen... But why? (Webb) */
+ /* It's probably fixed by disabling drawing the cursor while scrolling. */
+ /* gui.cursor_is_valid = FALSE; */
+
+ gui_clear_block(gui.scroll_region_bot - num_lines + 1,
+ gui.scroll_region_left,
+ gui.scroll_region_bot, gui.scroll_region_right);
+}
+
+/*
+ * Insert the given number of lines before the given row, scrolling down any
+ * following text within the scroll region.
+ */
+ void
+gui_mch_insert_lines(
+ int row,
+ int num_lines)
+{
+ RECT rc;
+
+ rc.left = FILL_X(gui.scroll_region_left);
+ rc.right = FILL_X(gui.scroll_region_right + 1);
+ rc.top = FILL_Y(row);
+ rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
+ /* The SW_INVALIDATE is required when part of the window is covered or
+ * off-screen. How do we avoid it when it's not needed? */
+ ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height,
+ &rc, &rc, NULL, NULL, get_scroll_flags());
+
+ UpdateWindow(s_textArea);
+
+ gui_clear_block(row, gui.scroll_region_left,
+ row + num_lines - 1, gui.scroll_region_right);
+}
+
+
+ void
+gui_mch_exit(int rc)
+{
+ ReleaseDC(s_textArea, s_hdc);
+ DeleteObject(s_brush);
+
+#ifdef FEAT_TEAROFF
+ /* Unload the tearoff bitmap */
+ (void)DeleteObject((HGDIOBJ)s_htearbitmap);
+#endif
+
+ /* Destroy our window (if we have one). */
+ if (s_hwnd != NULL)
+ {
+ destroying = TRUE; /* ignore WM_DESTROY message now */
+ DestroyWindow(s_hwnd);
+ }
+
+#ifdef GLOBAL_IME
+ global_ime_end();
+#endif
+}
+
+/*
+ * Initialise vim to use the font with the given name. Return FAIL if the font
+ * could not be loaded, OK otherwise.
+ */
+ int
+gui_mch_init_font(char_u *font_name, int fontset)
+{
+ LOGFONT lf;
+ GuiFont font = NOFONT;
+
+ /* Load the font */
+ if (get_logfont(&lf, font_name, NULL))
+ font = get_font_handle(&lf);
+ if (font == NOFONT)
+ return FAIL;
+ if (font_name == NULL)
+ font_name = lf.lfFaceName;
+#if defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME)
+ norm_logfont = lf;
+#endif
+#ifdef FEAT_MBYTE_IME
+ im_set_font(&lf);
+#endif
+ gui_mch_free_font(gui.norm_font);
+ gui.norm_font = font;
+ current_font_height = lf.lfHeight;
+ GetFontSize(font);
+ hl_set_font_name(lf.lfFaceName);
+
+ /* When setting 'guifont' to "*" replace it with the actual font name. */
+ if (STRCMP(font_name, "*") == 0 && STRCMP(p_guifont, "*") == 0)
+ {
+ char *charset_name;
+ char_u *p;
+
+ charset_name = charset_id2name((int)lf.lfCharSet);
+ p = alloc((unsigned)(strlen(lf.lfFaceName) + 20
+ + (charset_name == NULL ? 0 : strlen(charset_name) + 2)));
+ if (p != NULL)
+ {
+ /* make a normal font string out of the lf thing:*/
+ sprintf((char *)p, "%s:h%d", lf.lfFaceName, pixels_to_points(
+ lf.lfHeight < 0 ? -lf.lfHeight : lf.lfHeight, TRUE));
+ vim_free(p_guifont);
+ p_guifont = p;
+ while (*p)
+ {
+ if (*p == ' ')
+ *p = '_';
+ ++p;
+ }
+#ifndef MSWIN16_FASTTEXT
+ if (lf.lfItalic)
+ STRCAT(p, ":i");
+ if (lf.lfWeight >= FW_BOLD)
+ STRCAT(p, ":b");
+#endif
+ if (lf.lfUnderline)
+ STRCAT(p, ":u");
+ if (lf.lfStrikeOut)
+ STRCAT(p, ":s");
+ if (charset_name != NULL)
+ {
+ STRCAT(p, ":c");
+ STRCAT(p, charset_name);
+ }
+ }
+ }
+
+#ifndef MSWIN16_FASTTEXT
+ gui_mch_free_font(gui.ital_font);
+ gui.ital_font = NOFONT;
+ gui_mch_free_font(gui.bold_font);
+ gui.bold_font = NOFONT;
+ gui_mch_free_font(gui.boldital_font);
+ gui.boldital_font = NOFONT;
+
+ if (!lf.lfItalic)
+ {
+ lf.lfItalic = TRUE;
+ gui.ital_font = get_font_handle(&lf);
+ lf.lfItalic = FALSE;
+ }
+ if (lf.lfWeight < FW_BOLD)
+ {
+ lf.lfWeight = FW_BOLD;
+ gui.bold_font = get_font_handle(&lf);
+ if (!lf.lfItalic)
+ {
+ lf.lfItalic = TRUE;
+ gui.boldital_font = get_font_handle(&lf);
+ }
+ }
+#endif
+
+ return OK;
+}
+
+/*
+ * Return TRUE if the GUI window is maximized, filling the whole screen.
+ */
+ int
+gui_mch_maximized()
+{
+ return IsZoomed(s_hwnd);
+}
+
+/*
+ * Called when the font changed while the window is maximized. Compute the
+ * new Rows and Columns. This is like resizing the window.
+ */
+ void
+gui_mch_newfont()
+{
+ RECT rect;
+
+ GetWindowRect(s_hwnd, &rect);
+ gui_resize_shell(rect.right - rect.left
+ - GetSystemMetrics(SM_CXFRAME) * 2,
+ rect.bottom - rect.top
+ - GetSystemMetrics(SM_CYFRAME) * 2
+ - GetSystemMetrics(SM_CYCAPTION)
+#ifdef FEAT_MENU
+ - gui_mswin_get_menu_height(FALSE)
+#endif
+ );
+}
+
+/*
+ * Set the window title
+ */
+ void
+gui_mch_settitle(
+ char_u *title,
+ char_u *icon)
+{
+#ifdef FEAT_MBYTE
+ if (title != NULL && enc_codepage >= 0 && enc_codepage != (int)GetACP())
+ {
+ WCHAR *wbuf;
+ int n;
+
+ /* Convert the title from 'encoding' to ucs2. */
+ wbuf = (WCHAR *)enc_to_ucs2(title, NULL);
+ if (wbuf != NULL)
+ {
+ n = SetWindowTextW(s_hwnd, wbuf);
+ vim_free(wbuf);
+ if (n != 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return;
+ /* Retry with non-wide function (for Windows 98). */
+ }
+ }
+#endif
+ SetWindowText(s_hwnd, (LPCSTR)(title == NULL ? "VIM" : (char *)title));
+}
+
+#ifdef FEAT_MOUSESHAPE
+/* Table for shape IDCs. Keep in sync with the mshape_names[] table in
+ * misc2.c! */
+static LPCSTR mshape_idcs[] =
+{
+ MAKEINTRESOURCE(IDC_ARROW), /* arrow */
+ MAKEINTRESOURCE(0), /* blank */
+ MAKEINTRESOURCE(IDC_IBEAM), /* beam */
+ MAKEINTRESOURCE(IDC_SIZENS), /* updown */
+ MAKEINTRESOURCE(IDC_SIZENS), /* udsizing */
+ MAKEINTRESOURCE(IDC_SIZEWE), /* leftright */
+ MAKEINTRESOURCE(IDC_SIZEWE), /* lrsizing */
+ MAKEINTRESOURCE(IDC_WAIT), /* busy */
+#ifdef WIN3264
+ MAKEINTRESOURCE(IDC_NO), /* no */
+#else
+ MAKEINTRESOURCE(IDC_ICON), /* no */
+#endif
+ MAKEINTRESOURCE(IDC_ARROW), /* crosshair */
+ MAKEINTRESOURCE(IDC_ARROW), /* hand1 */
+ MAKEINTRESOURCE(IDC_ARROW), /* hand2 */
+ MAKEINTRESOURCE(IDC_ARROW), /* pencil */
+ MAKEINTRESOURCE(IDC_ARROW), /* question */
+ MAKEINTRESOURCE(IDC_ARROW), /* right-arrow */
+ MAKEINTRESOURCE(IDC_UPARROW), /* up-arrow */
+ MAKEINTRESOURCE(IDC_ARROW) /* last one */
+};
+
+ void
+mch_set_mouse_shape(int shape)
+{
+ LPCSTR idc;
+
+ if (shape == MSHAPE_HIDE)
+ ShowCursor(FALSE);
+ else
+ {
+ if (shape >= MSHAPE_NUMBERED)
+ idc = MAKEINTRESOURCE(IDC_ARROW);
+ else
+ idc = mshape_idcs[shape];
+#ifdef _WIN64
+ SetClassLongPtr(s_textArea, GCLP_HCURSOR, (LONG_PTR)LoadCursor(NULL, idc));
+#else
+# ifdef WIN32
+ SetClassLong(s_textArea, GCL_HCURSOR, (LONG)LoadCursor(NULL, idc));
+# else
+ SetClassWord(s_textArea, GCW_HCURSOR, (WORD)LoadCursor(NULL, idc));
+# endif
+#endif
+ if (!p_mh)
+ {
+ POINT mp;
+
+ /* Set the position to make it redrawn with the new shape. */
+ (void)GetCursorPos((LPPOINT)&mp);
+ (void)SetCursorPos(mp.x, mp.y);
+ ShowCursor(TRUE);
+ }
+ }
+}
+#endif
+
+#ifdef FEAT_BROWSE
+/*
+ * The file browser exists in two versions: with "W" uses wide characters,
+ * without "W" the current codepage. When FEAT_MBYTE is defined and on
+ * Windows NT/2000/XP the "W" functions are used.
+ */
+
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+/*
+ * Wide version of convert_filter(). Keep in sync!
+ */
+ static WCHAR *
+convert_filterW(char_u *s)
+{
+ WCHAR *res;
+ unsigned s_len = (unsigned)STRLEN(s);
+ unsigned i;
+
+ res = (WCHAR *)alloc((s_len + 3) * sizeof(WCHAR));
+ if (res != NULL)
+ {
+ for (i = 0; i < s_len; ++i)
+ if (s[i] == '\t' || s[i] == '\n')
+ res[i] = '\0';
+ else
+ res[i] = s[i];
+ res[s_len] = NUL;
+ /* Add two extra NULs to make sure it's properly terminated. */
+ res[s_len + 1] = NUL;
+ res[s_len + 2] = NUL;
+ }
+ return res;
+}
+
+/*
+ * Wide version of gui_mch_browse(). Keep in sync!
+ */
+ static char_u *
+gui_mch_browseW(
+ int saving,
+ char_u *title,
+ char_u *dflt,
+ char_u *ext,
+ char_u *initdir,
+ char_u *filter)
+{
+ /* We always use the wide function. This means enc_to_ucs2() must work,
+ * otherwise it fails miserably! */
+ OPENFILENAMEW fileStruct;
+ WCHAR fileBuf[MAXPATHL];
+ WCHAR *wp;
+ int i;
+ WCHAR *titlep = NULL;
+ WCHAR *extp = NULL;
+ WCHAR *initdirp = NULL;
+ WCHAR *filterp;
+ char_u *p;
+
+ if (dflt == NULL)
+ fileBuf[0] = NUL;
+ else
+ {
+ wp = enc_to_ucs2(dflt, NULL);
+ if (wp == NULL)
+ fileBuf[0] = NUL;
+ else
+ {
+ for (i = 0; wp[i] != NUL && i < MAXPATHL - 1; ++i)
+ fileBuf[i] = wp[i];
+ fileBuf[i] = NUL;
+ vim_free(wp);
+ }
+ }
+
+ /* Convert the filter to Windows format. */
+ filterp = convert_filterW(filter);
+
+ memset(&fileStruct, 0, sizeof(OPENFILENAMEW));
+#ifdef OPENFILENAME_SIZE_VERSION_400
+ /* be compatible with Windows NT 4.0 */
+ /* TODO: what to use for OPENFILENAMEW??? */
+ fileStruct.lStructSize = sizeof(OPENFILENAME_SIZE_VERSION_400);
+#else
+ fileStruct.lStructSize = sizeof(fileStruct);
+#endif
+
+ if (title != NULL)
+ titlep = enc_to_ucs2(title, NULL);
+ fileStruct.lpstrTitle = titlep;
+
+ if (ext != NULL)
+ extp = enc_to_ucs2(ext, NULL);
+ fileStruct.lpstrDefExt = extp;
+
+ fileStruct.lpstrFile = fileBuf;
+ fileStruct.nMaxFile = MAXPATHL;
+ fileStruct.lpstrFilter = filterp;
+ fileStruct.hwndOwner = s_hwnd; /* main Vim window is owner*/
+ /* has an initial dir been specified? */
+ if (initdir != NULL && *initdir != NUL)
+ {
+ /* Must have backslashes here, no matter what 'shellslash' says */
+ initdirp = enc_to_ucs2(initdir, NULL);
+ if (initdirp != NULL)
+ {
+ for (wp = initdirp; *wp != NUL; ++wp)
+ if (*wp == '/')
+ *wp = '\\';
+ }
+ fileStruct.lpstrInitialDir = initdirp;
+ }
+
+ /*
+ * TODO: Allow selection of multiple files. Needs another arg to this
+ * function to ask for it, and need to use OFN_ALLOWMULTISELECT below.
+ * Also, should we use OFN_FILEMUSTEXIST when opening? Vim can edit on
+ * files that don't exist yet, so I haven't put it in. What about
+ * OFN_PATHMUSTEXIST?
+ * Don't use OFN_OVERWRITEPROMPT, Vim has its own ":confirm" dialog.
+ */
+ fileStruct.Flags = (OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY);
+#ifdef FEAT_SHORTCUT
+ if (curbuf->b_p_bin)
+ fileStruct.Flags |= OFN_NODEREFERENCELINKS;
+#endif
+ if (saving)
+ {
+ if (!GetSaveFileNameW(&fileStruct))
+ return NULL;
+ }
+ else
+ {
+ if (!GetOpenFileNameW(&fileStruct))
+ return NULL;
+ }
+
+ vim_free(filterp);
+ vim_free(initdirp);
+ vim_free(titlep);
+ vim_free(extp);
+
+ /* Convert from UCS2 to 'encoding'. */
+ p = ucs2_to_enc(fileBuf, NULL);
+ if (p != NULL)
+ /* when out of memory we get garbage for non-ASCII chars */
+ STRCPY(fileBuf, p);
+ vim_free(p);
+
+ /* Give focus back to main window (when using MDI). */
+ SetFocus(s_hwnd);
+
+ /* Shorten the file name if possible */
+ mch_dirname(IObuff, IOSIZE);
+ p = shorten_fname((char_u *)fileBuf, IObuff);
+ if (p == NULL)
+ p = (char_u *)fileBuf;
+ return vim_strsave(p);
+}
+# endif /* FEAT_MBYTE */
+
+
+/*
+ * Convert the string s to the proper format for a filter string by replacing
+ * the \t and \n delimeters with \0.
+ * Returns the converted string in allocated memory.
+ *
+ * Keep in sync with convert_filterW() above!
+ */
+ static char_u *
+convert_filter(char_u *s)
+{
+ char_u *res;
+ unsigned s_len = (unsigned)STRLEN(s);
+ unsigned i;
+
+ res = alloc(s_len + 3);
+ if (res != NULL)
+ {
+ for (i = 0; i < s_len; ++i)
+ if (s[i] == '\t' || s[i] == '\n')
+ res[i] = '\0';
+ else
+ res[i] = s[i];
+ res[s_len] = NUL;
+ /* Add two extra NULs to make sure it's properly terminated. */
+ res[s_len + 1] = NUL;
+ res[s_len + 2] = NUL;
+ }
+ return res;
+}
+
+/*
+ * Pop open a file browser and return the file selected, in allocated memory,
+ * or NULL if Cancel is hit.
+ * saving - TRUE if the file will be saved to, FALSE if it will be opened.
+ * title - Title message for the file browser dialog.
+ * dflt - Default name of file.
+ * ext - Default extension to be added to files without extensions.
+ * initdir - directory in which to open the browser (NULL = current dir)
+ * filter - Filter for matched files to choose from.
+ *
+ * Keep in sync with gui_mch_browseW() above!
+ */
+ char_u *
+gui_mch_browse(
+ int saving,
+ char_u *title,
+ char_u *dflt,
+ char_u *ext,
+ char_u *initdir,
+ char_u *filter)
+{
+ OPENFILENAME fileStruct;
+ char_u fileBuf[MAXPATHL];
+ char_u *initdirp = NULL;
+ char_u *filterp;
+ char_u *p;
+
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+ if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ return gui_mch_browseW(saving, title, dflt, ext, initdir, filter);
+# endif
+
+ if (dflt == NULL)
+ fileBuf[0] = NUL;
+ else
+ {
+ STRNCPY(fileBuf, dflt, MAXPATHL - 1);
+ fileBuf[MAXPATHL - 1] = NUL;
+ }
+
+ /* Convert the filter to Windows format. */
+ filterp = convert_filter(filter);
+
+ memset(&fileStruct, 0, sizeof(OPENFILENAME));
+#ifdef OPENFILENAME_SIZE_VERSION_400
+ /* be compatible with Windows NT 4.0 */
+ fileStruct.lStructSize = sizeof(OPENFILENAME_SIZE_VERSION_400);
+#else
+ fileStruct.lStructSize = sizeof(fileStruct);
+#endif
+
+ fileStruct.lpstrTitle = title;
+ fileStruct.lpstrDefExt = ext;
+
+ fileStruct.lpstrFile = fileBuf;
+ fileStruct.nMaxFile = MAXPATHL;
+ fileStruct.lpstrFilter = filterp;
+ fileStruct.hwndOwner = s_hwnd; /* main Vim window is owner*/
+ /* has an initial dir been specified? */
+ if (initdir != NULL && *initdir != NUL)
+ {
+ /* Must have backslashes here, no matter what 'shellslash' says */
+ initdirp = vim_strsave(initdir);
+ if (initdirp != NULL)
+ for (p = initdirp; *p != NUL; ++p)
+ if (*p == '/')
+ *p = '\\';
+ fileStruct.lpstrInitialDir = initdirp;
+ }
+
+ /*
+ * TODO: Allow selection of multiple files. Needs another arg to this
+ * function to ask for it, and need to use OFN_ALLOWMULTISELECT below.
+ * Also, should we use OFN_FILEMUSTEXIST when opening? Vim can edit on
+ * files that don't exist yet, so I haven't put it in. What about
+ * OFN_PATHMUSTEXIST?
+ * Don't use OFN_OVERWRITEPROMPT, Vim has its own ":confirm" dialog.
+ */
+ fileStruct.Flags = (OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY);
+#ifdef FEAT_SHORTCUT
+ if (curbuf->b_p_bin)
+ fileStruct.Flags |= OFN_NODEREFERENCELINKS;
+#endif
+ if (saving)
+ {
+ if (!GetSaveFileName(&fileStruct))
+ return NULL;
+ }
+ else
+ {
+ if (!GetOpenFileName(&fileStruct))
+ return NULL;
+ }
+
+ vim_free(filterp);
+ vim_free(initdirp);
+
+ /* Give focus back to main window (when using MDI). */
+ SetFocus(s_hwnd);
+
+ /* Shorten the file name if possible */
+ mch_dirname(IObuff, IOSIZE);
+ p = shorten_fname((char_u *)fileBuf, IObuff);
+ if (p == NULL)
+ p = (char_u *)fileBuf;
+ return vim_strsave(p);
+}
+#endif /* FEAT_BROWSE */
+
+ static void
+_OnDropFiles(
+ HWND hwnd,
+ HDROP hDrop)
+{
+#ifdef FEAT_WINDOWS
+#ifdef WIN3264
+# define BUFPATHLEN _MAX_PATH
+# define DRAGQVAL 0xFFFFFFFF
+#else
+# define BUFPATHLEN MAXPATHL
+# define DRAGQVAL 0xFFFF
+#endif
+#ifdef FEAT_MBYTE
+ WCHAR wszFile[BUFPATHLEN];
+#endif
+ char szFile[BUFPATHLEN];
+ UINT cFiles = DragQueryFile(hDrop, DRAGQVAL, NULL, 0);
+ UINT i;
+ char_u **fnames;
+ POINT pt;
+ int_u modifiers = 0;
+
+ /* TRACE("_OnDropFiles: %d files dropped\n", cFiles); */
+
+ /* Obtain dropped position */
+ DragQueryPoint(hDrop, &pt);
+ MapWindowPoints(s_hwnd, s_textArea, &pt, 1);
+
+# ifdef FEAT_VISUAL
+ reset_VIsual();
+# endif
+
+ fnames = (char_u **)alloc(cFiles * sizeof(char_u *));
+
+ if (fnames != NULL)
+ for (i = 0; i < cFiles; ++i)
+ {
+#ifdef FEAT_MBYTE
+ if (DragQueryFileW(hDrop, i, wszFile, BUFPATHLEN) > 0)
+ fnames[i] = ucs2_to_enc(wszFile, NULL);
+ else
+#endif
+ {
+ DragQueryFile(hDrop, i, szFile, BUFPATHLEN);
+ fnames[i] = vim_strsave(szFile);
+ }
+ }
+
+ DragFinish(hDrop);
+
+ if (fnames != NULL)
+ {
+ if ((GetKeyState(VK_SHIFT) & 0x8000) != 0)
+ modifiers |= MOUSE_SHIFT;
+ if ((GetKeyState(VK_CONTROL) & 0x8000) != 0)
+ modifiers |= MOUSE_CTRL;
+ if ((GetKeyState(VK_MENU) & 0x8000) != 0)
+ modifiers |= MOUSE_ALT;
+
+ gui_handle_drop(pt.x, pt.y, modifiers, fnames, cFiles);
+
+ s_need_activate = TRUE;
+ }
+#endif
+}
+
+ static int
+_OnScroll(
+ HWND hwnd,
+ HWND hwndCtl,
+ UINT code,
+ int pos)
+{
+ static UINT prev_code = 0; /* code of previous call */
+ scrollbar_T *sb, *sb_info;
+ long val;
+ int dragging = FALSE;
+ int dont_scroll_save = dont_scroll;
+#ifndef WIN3264
+ int nPos;
+#else
+ SCROLLINFO si;
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+#endif
+
+ sb = gui_mswin_find_scrollbar(hwndCtl);
+ if (sb == NULL)
+ return 0;
+
+ if (sb->wp != NULL) /* Left or right scrollbar */
+ {
+ /*
+ * Careful: need to get scrollbar info out of first (left) scrollbar
+ * for window, but keep real scrollbar too because we must pass it to
+ * gui_drag_scrollbar().
+ */
+ sb_info = &sb->wp->w_scrollbars[0];
+ }
+ else /* Bottom scrollbar */
+ sb_info = sb;
+ val = sb_info->value;
+
+ switch (code)
+ {
+ case SB_THUMBTRACK:
+ val = pos;
+ dragging = TRUE;
+ if (sb->scroll_shift > 0)
+ val <<= sb->scroll_shift;
+ break;
+ case SB_LINEDOWN:
+ val++;
+ break;
+ case SB_LINEUP:
+ val--;
+ break;
+ case SB_PAGEDOWN:
+ val += (sb_info->size > 2 ? sb_info->size - 2 : 1);
+ break;
+ case SB_PAGEUP:
+ val -= (sb_info->size > 2 ? sb_info->size - 2 : 1);
+ break;
+ case SB_TOP:
+ val = 0;
+ break;
+ case SB_BOTTOM:
+ val = sb_info->max;
+ break;
+ case SB_ENDSCROLL:
+ if (prev_code == SB_THUMBTRACK)
+ {
+ /*
+ * "pos" only gives us 16-bit data. In case of large file,
+ * use GetScrollPos() which returns 32-bit. Unfortunately it
+ * is not valid while the scrollbar is being dragged.
+ */
+ val = GetScrollPos(hwndCtl, SB_CTL);
+ if (sb->scroll_shift > 0)
+ val <<= sb->scroll_shift;
+ }
+ break;
+
+ default:
+ /* TRACE("Unknown scrollbar event %d\n", code); */
+ return 0;
+ }
+ prev_code = code;
+
+#ifdef WIN3264
+ si.nPos = (sb->scroll_shift > 0) ? val >> sb->scroll_shift : val;
+ SetScrollInfo(hwndCtl, SB_CTL, &si, TRUE);
+#else
+ nPos = (sb->scroll_shift > 0) ? val >> sb->scroll_shift : val;
+ SetScrollPos(hwndCtl, SB_CTL, nPos, TRUE);
+#endif
+
+ /*
+ * When moving a vertical scrollbar, move the other vertical scrollbar too.
+ */
+ if (sb->wp != NULL)
+ {
+ scrollbar_T *sba = sb->wp->w_scrollbars;
+ HWND id = sba[ (sb == sba + SBAR_LEFT) ? SBAR_RIGHT : SBAR_LEFT].id;
+
+#ifdef WIN3264
+ SetScrollInfo(id, SB_CTL, &si, TRUE);
+#else
+ SetScrollPos(id, SB_CTL, nPos, TRUE);
+#endif
+ }
+
+ /* Don't let us be interrupted here by another message. */
+ s_busy_processing = TRUE;
+
+ /* When "allow_scrollbar" is FALSE still need to remember the new
+ * position, but don't actually scroll by setting "dont_scroll". */
+ dont_scroll = !allow_scrollbar;
+
+ gui_drag_scrollbar(sb, val, dragging);
+
+ s_busy_processing = FALSE;
+ dont_scroll = dont_scroll_save;
+
+ return 0;
+}
+
+/*
+ * Get command line arguments.
+ * Use "prog" as the name of the program and "cmdline" as the arguments.
+ * Copy the arguments to allocated memory.
+ * Return the number of arguments (including program name).
+ * Return pointers to the arguments in "argvp".
+ * Return pointer to buffer in "tofree".
+ * Returns zero when out of memory.
+ */
+ int
+get_cmd_args(char *prog, char *cmdline, char ***argvp, char **tofree)
+{
+ int i;
+ char *p;
+ char *progp;
+ char *pnew = NULL;
+ char *newcmdline;
+ int inquote;
+ int argc;
+ char **argv = NULL;
+ int round;
+
+ /* Handle the program name. Remove the ".exe" extension, and find the 1st
+ * non-space. */
+ p = strrchr(prog, '.');
+ if (p != NULL)
+ *p = NUL;
+ for (progp = prog; *progp == ' '; ++progp)
+ ;
+
+ /* The command line is copied to allocated memory, so that we can change
+ * it. Add the size of the string, the separating NUL and a terminating
+ * NUL. */
+ newcmdline = malloc(STRLEN(cmdline) + STRLEN(progp) + 2);
+ if (newcmdline == NULL)
+ return 0;
+
+ /*
+ * First round: count the number of arguments ("pnew" == NULL).
+ * Second round: produce the arguments.
+ */
+ for (round = 1; round <= 2; ++round)
+ {
+ /* First argument is the program name. */
+ if (pnew != NULL)
+ {
+ argv[0] = pnew;
+ strcpy(pnew, progp);
+ pnew += strlen(pnew);
+ *pnew++ = NUL;
+ }
+
+ /*
+ * Isolate each argument and put it in argv[].
+ */
+ p = cmdline;
+ argc = 1;
+ while (*p != NUL)
+ {
+ inquote = FALSE;
+ if (pnew != NULL)
+ argv[argc] = pnew;
+ ++argc;
+ while (*p != NUL && (inquote || (*p != ' ' && *p != '\t')))
+ {
+ /* Backslashes are only special when followed by a double
+ * quote. */
+ i = strspn(p, "\\");
+ if (p[i] == '"')
+ {
+ /* Halve the number of backslashes. */
+ if (i > 1 && pnew != NULL)
+ {
+ memset(pnew, '\\', i / 2);
+ pnew += i / 2;
+ }
+
+ /* Even nr of backslashes toggles quoting, uneven copies
+ * the double quote. */
+ if ((i & 1) == 0)
+ inquote = !inquote;
+ else if (pnew != NULL)
+ *pnew++ = '"';
+ p += i + 1;
+ }
+ else if (i > 0)
+ {
+ /* Copy span of backslashes unmodified. */
+ if (pnew != NULL)
+ {
+ memset(pnew, '\\', i);
+ pnew += i;
+ }
+ p += i;
+ }
+ else
+ {
+ if (pnew != NULL)
+ *pnew++ = *p;
+ ++p;
+ }
+ }
+
+ if (pnew != NUL)
+ *pnew++ = NUL;
+ while (*p == ' ' || *p == '\t')
+ ++p; /* advance until a non-space */
+ }
+
+ if (round == 1)
+ {
+ argv = (char **)malloc((argc + 1) * sizeof(char *));
+ if (argv == NULL )
+ return 0; /* malloc error */
+ pnew = newcmdline;
+ }
+ }
+
+ argv[argc] = NULL; /* NULL-terminated list */
+
+ *argvp = argv;
+ return argc;
+}
diff --git a/src/gui_x11.c b/src/gui_x11.c
new file mode 100644
index 000000000..7087e0208
--- /dev/null
+++ b/src/gui_x11.c
@@ -0,0 +1,3748 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI/Motif support by Robert Webb
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * Common code for the Motif and Athena GUI.
+ * Not used for GTK.
+ */
+
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <X11/StringDefs.h>
+#include <X11/Intrinsic.h>
+#include <X11/Shell.h>
+#include <X11/cursorfont.h>
+
+#include "vim.h"
+
+/*
+ * For Workshop XpmP.h is preferred, because it makes the signs drawn with a
+ * transparent background instead of black.
+ */
+#if defined(HAVE_XM_XPMP_H) && defined(FEAT_GUI_MOTIF) \
+ && (!defined(HAVE_X11_XPM_H) || defined(FEAT_SUN_WORKSHOP))
+# include <Xm/XpmP.h>
+#else
+# ifdef HAVE_X11_XPM_H
+# include <X11/xpm.h>
+# endif
+#endif
+
+#ifdef FEAT_XFONTSET
+# ifdef X_LOCALE
+# include <X11/Xlocale.h>
+# else
+# include <locale.h>
+# endif
+#endif
+
+#ifdef HAVE_X11_SUNKEYSYM_H
+# include <X11/Sunkeysym.h>
+#endif
+
+#ifdef HAVE_X11_XMU_EDITRES_H
+# include <X11/Xmu/Editres.h>
+#endif
+
+#ifdef FEAT_BEVAL_TIP
+# include "gui_beval.h"
+#endif
+
+#define VIM_NAME "vim"
+#define VIM_CLASS "Vim"
+
+/* Default resource values */
+#define DFLT_FONT "7x13"
+#ifdef FONTSET_ALWAYS
+# define DFLT_MENU_FONT XtDefaultFontSet
+#else
+# define DFLT_MENU_FONT XtDefaultFont
+#endif
+#define DFLT_TOOLTIP_FONT XtDefaultFontSet
+
+#ifdef FEAT_GUI_ATHENA
+# define DFLT_MENU_BG_COLOR "gray77"
+# define DFLT_MENU_FG_COLOR "black"
+# define DFLT_SCROLL_BG_COLOR "gray60"
+# define DFLT_SCROLL_FG_COLOR "gray77"
+# define DFLT_TOOLTIP_BG_COLOR "#ffffffff9191"
+# define DFLT_TOOLTIP_FG_COLOR "#000000000000"
+#else
+/* use the default (CDE) colors */
+# define DFLT_MENU_BG_COLOR ""
+# define DFLT_MENU_FG_COLOR ""
+# define DFLT_SCROLL_BG_COLOR ""
+# define DFLT_SCROLL_FG_COLOR ""
+# define DFLT_TOOLTIP_BG_COLOR "#ffffffff9191"
+# define DFLT_TOOLTIP_FG_COLOR "#000000000000"
+#endif
+
+Widget vimShell = (Widget)0;
+
+static Atom wm_atoms[2]; /* Window Manager Atoms */
+#define DELETE_WINDOW_IDX 0 /* index in wm_atoms[] for WM_DELETE_WINDOW */
+#define SAVE_YOURSELF_IDX 1 /* index in wm_atoms[] for WM_SAVE_YOURSELF */
+
+#ifdef FEAT_XFONTSET
+/*
+ * We either draw with a fontset (when current_fontset != NULL) or with a
+ * normal font (current_fontset == NULL, use gui.text_gc and gui.back_gc).
+ */
+static XFontSet current_fontset = NULL;
+
+#define XDrawString(dpy, win, gc, x, y, str, n) \
+ do \
+ { \
+ if (current_fontset != NULL) \
+ XmbDrawString(dpy, win, current_fontset, gc, x, y, str, n); \
+ else \
+ XDrawString(dpy, win, gc, x, y, str, n); \
+ } while (0)
+
+#define XDrawString16(dpy, win, gc, x, y, str, n) \
+ do \
+ { \
+ if (current_fontset != NULL) \
+ XwcDrawString(dpy, win, current_fontset, gc, x, y, (wchar_t *)str, n); \
+ else \
+ XDrawString16(dpy, win, gc, x, y, str, n); \
+ } while (0)
+
+static int check_fontset_sanity __ARGS((XFontSet fs));
+static int fontset_width __ARGS((XFontSet fs));
+static int fontset_ascent __ARGS((XFontSet fs));
+#endif
+
+static guicolor_T prev_fg_color = INVALCOLOR;
+static guicolor_T prev_bg_color = INVALCOLOR;
+
+#if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU)
+static XButtonPressedEvent last_mouse_event;
+#endif
+
+static int find_closest_color __ARGS((Colormap colormap, XColor *colorPtr));
+static void gui_x11_timer_cb __ARGS((XtPointer timed_out, XtIntervalId *interval_id));
+static void gui_x11_visibility_cb __ARGS((Widget w, XtPointer dud, XEvent *event, Boolean *dum));
+static void gui_x11_expose_cb __ARGS((Widget w, XtPointer dud, XEvent *event, Boolean *dum));
+static void gui_x11_resize_window_cb __ARGS((Widget w, XtPointer dud, XEvent *event, Boolean *dum));
+static void gui_x11_focus_change_cb __ARGS((Widget w, XtPointer data, XEvent *event, Boolean *dum));
+static void gui_x11_enter_cb __ARGS((Widget w, XtPointer data, XEvent *event, Boolean *dum));
+static void gui_x11_leave_cb __ARGS((Widget w, XtPointer data, XEvent *event, Boolean *dum));
+static void gui_x11_mouse_cb __ARGS((Widget w, XtPointer data, XEvent *event, Boolean *dum));
+#ifdef FEAT_SNIFF
+static void gui_x11_sniff_request_cb __ARGS((XtPointer closure, int *source, XtInputId *id));
+#endif
+static void gui_x11_check_copy_area __ARGS((void));
+#ifdef FEAT_CLIENTSERVER
+static void gui_x11_send_event_handler __ARGS((Widget, XtPointer, XEvent *, Boolean *));
+#endif
+static void gui_x11_wm_protocol_handler __ARGS((Widget, XtPointer, XEvent *, Boolean *));
+static void gui_x11_blink_cb __ARGS((XtPointer timed_out, XtIntervalId *interval_id));
+static Cursor gui_x11_create_blank_mouse __ARGS((void));
+
+
+/*
+ * Keycodes recognized by vim.
+ * NOTE: when changing this, the table in gui_gtk_x11.c probably needs the
+ * same change!
+ */
+static struct specialkey
+{
+ KeySym key_sym;
+ char_u vim_code0;
+ char_u vim_code1;
+} special_keys[] =
+{
+ {XK_Up, 'k', 'u'},
+ {XK_Down, 'k', 'd'},
+ {XK_Left, 'k', 'l'},
+ {XK_Right, 'k', 'r'},
+
+ {XK_F1, 'k', '1'},
+ {XK_F2, 'k', '2'},
+ {XK_F3, 'k', '3'},
+ {XK_F4, 'k', '4'},
+ {XK_F5, 'k', '5'},
+ {XK_F6, 'k', '6'},
+ {XK_F7, 'k', '7'},
+ {XK_F8, 'k', '8'},
+ {XK_F9, 'k', '9'},
+ {XK_F10, 'k', ';'},
+
+ {XK_F11, 'F', '1'},
+ {XK_F12, 'F', '2'},
+ {XK_F13, 'F', '3'},
+ {XK_F14, 'F', '4'},
+ {XK_F15, 'F', '5'},
+ {XK_F16, 'F', '6'},
+ {XK_F17, 'F', '7'},
+ {XK_F18, 'F', '8'},
+ {XK_F19, 'F', '9'},
+ {XK_F20, 'F', 'A'},
+
+ {XK_F21, 'F', 'B'},
+ {XK_F22, 'F', 'C'},
+ {XK_F23, 'F', 'D'},
+ {XK_F24, 'F', 'E'},
+ {XK_F25, 'F', 'F'},
+ {XK_F26, 'F', 'G'},
+ {XK_F27, 'F', 'H'},
+ {XK_F28, 'F', 'I'},
+ {XK_F29, 'F', 'J'},
+ {XK_F30, 'F', 'K'},
+
+ {XK_F31, 'F', 'L'},
+ {XK_F32, 'F', 'M'},
+ {XK_F33, 'F', 'N'},
+ {XK_F34, 'F', 'O'},
+ {XK_F35, 'F', 'P'}, /* keysymdef.h defines up to F35 */
+#ifdef SunXK_F36
+ {SunXK_F36, 'F', 'Q'},
+ {SunXK_F37, 'F', 'R'},
+#endif
+
+ {XK_Help, '%', '1'},
+ {XK_Undo, '&', '8'},
+ {XK_BackSpace, 'k', 'b'},
+ {XK_Insert, 'k', 'I'},
+ {XK_Delete, 'k', 'D'},
+ {XK_Home, 'k', 'h'},
+ {XK_End, '@', '7'},
+ {XK_Prior, 'k', 'P'},
+ {XK_Next, 'k', 'N'},
+ {XK_Print, '%', '9'},
+
+ /* Keypad keys: */
+#ifdef XK_KP_Left
+ {XK_KP_Left, 'k', 'l'},
+ {XK_KP_Right, 'k', 'r'},
+ {XK_KP_Up, 'k', 'u'},
+ {XK_KP_Down, 'k', 'd'},
+ {XK_KP_Insert, KS_EXTRA, (char_u)KE_KINS},
+ {XK_KP_Delete, KS_EXTRA, (char_u)KE_KDEL},
+ {XK_KP_Home, 'K', '1'},
+ {XK_KP_End, 'K', '4'},
+ {XK_KP_Prior, 'K', '3'},
+ {XK_KP_Next, 'K', '5'},
+
+ {XK_KP_Add, 'K', '6'},
+ {XK_KP_Subtract, 'K', '7'},
+ {XK_KP_Divide, 'K', '8'},
+ {XK_KP_Multiply, 'K', '9'},
+ {XK_KP_Enter, 'K', 'A'},
+ {XK_KP_Decimal, 'K', 'B'},
+
+ {XK_KP_0, 'K', 'C'},
+ {XK_KP_1, 'K', 'D'},
+ {XK_KP_2, 'K', 'E'},
+ {XK_KP_3, 'K', 'F'},
+ {XK_KP_4, 'K', 'G'},
+ {XK_KP_5, 'K', 'H'},
+ {XK_KP_6, 'K', 'I'},
+ {XK_KP_7, 'K', 'J'},
+ {XK_KP_8, 'K', 'K'},
+ {XK_KP_9, 'K', 'L'},
+#endif
+
+ /* End of list marker: */
+ {(KeySym)0, 0, 0}
+};
+
+#define XtNboldFont "boldFont"
+#define XtCBoldFont "BoldFont"
+#define XtNitalicFont "italicFont"
+#define XtCItalicFont "ItalicFont"
+#define XtNboldItalicFont "boldItalicFont"
+#define XtCBoldItalicFont "BoldItalicFont"
+#define XtNscrollbarWidth "scrollbarWidth"
+#define XtCScrollbarWidth "ScrollbarWidth"
+#define XtNmenuHeight "menuHeight"
+#define XtCMenuHeight "MenuHeight"
+#define XtNmenuFont "menuFont"
+#define XtCMenuFont "MenuFont"
+#define XtNmenuFontSet "menuFontSet"
+#define XtCMenuFontSet "MenuFontSet"
+
+
+/* Resources for setting the foreground and background colors of menus */
+#define XtNmenuBackground "menuBackground"
+#define XtCMenuBackground "MenuBackground"
+#define XtNmenuForeground "menuForeground"
+#define XtCMenuForeground "MenuForeground"
+
+/* Resources for setting the foreground and background colors of scrollbars */
+#define XtNscrollBackground "scrollBackground"
+#define XtCScrollBackground "ScrollBackground"
+#define XtNscrollForeground "scrollForeground"
+#define XtCScrollForeground "ScrollForeground"
+
+/* Resources for setting the foreground and background colors of tooltip */
+#define XtNtooltipBackground "tooltipBackground"
+#define XtCTooltipBackground "TooltipBackground"
+#define XtNtooltipForeground "tooltipForeground"
+#define XtCTooltipForeground "TooltipForeground"
+#define XtNtooltipFont "tooltipFont"
+#define XtCTooltipFont "TooltipFont"
+
+/*
+ * X Resources:
+ */
+static XtResource vim_resources[] =
+{
+ {
+ XtNforeground,
+ XtCForeground,
+ XtRPixel,
+ sizeof(Pixel),
+ XtOffsetOf(gui_T, def_norm_pixel),
+ XtRString,
+ XtDefaultForeground
+ },
+ {
+ XtNbackground,
+ XtCBackground,
+ XtRPixel,
+ sizeof(Pixel),
+ XtOffsetOf(gui_T, def_back_pixel),
+ XtRString,
+ XtDefaultBackground
+ },
+ {
+ XtNfont,
+ XtCFont,
+ XtRString,
+ sizeof(String *),
+ XtOffsetOf(gui_T, rsrc_font_name),
+ XtRImmediate,
+ XtDefaultFont
+ },
+ {
+ XtNboldFont,
+ XtCBoldFont,
+ XtRString,
+ sizeof(String *),
+ XtOffsetOf(gui_T, rsrc_bold_font_name),
+ XtRImmediate,
+ ""
+ },
+ {
+ XtNitalicFont,
+ XtCItalicFont,
+ XtRString,
+ sizeof(String *),
+ XtOffsetOf(gui_T, rsrc_ital_font_name),
+ XtRImmediate,
+ ""
+ },
+ {
+ XtNboldItalicFont,
+ XtCBoldItalicFont,
+ XtRString,
+ sizeof(String *),
+ XtOffsetOf(gui_T, rsrc_boldital_font_name),
+ XtRImmediate,
+ ""
+ },
+ {
+ XtNgeometry,
+ XtCGeometry,
+ XtRString,
+ sizeof(String *),
+ XtOffsetOf(gui_T, geom),
+ XtRImmediate,
+ ""
+ },
+ {
+ XtNreverseVideo,
+ XtCReverseVideo,
+ XtRBool,
+ sizeof(Bool),
+ XtOffsetOf(gui_T, rsrc_rev_video),
+ XtRImmediate,
+ (XtPointer)False
+ },
+ {
+ XtNborderWidth,
+ XtCBorderWidth,
+ XtRInt,
+ sizeof(int),
+ XtOffsetOf(gui_T, border_width),
+ XtRImmediate,
+ (XtPointer)2
+ },
+ {
+ XtNscrollbarWidth,
+ XtCScrollbarWidth,
+ XtRInt,
+ sizeof(int),
+ XtOffsetOf(gui_T, scrollbar_width),
+ XtRImmediate,
+ (XtPointer)SB_DEFAULT_WIDTH
+ },
+#ifdef FEAT_MENU
+# ifdef FEAT_GUI_ATHENA /* with Motif the height is always computed */
+ {
+ XtNmenuHeight,
+ XtCMenuHeight,
+ XtRInt,
+ sizeof(int),
+ XtOffsetOf(gui_T, menu_height),
+ XtRImmediate,
+ (XtPointer)MENU_DEFAULT_HEIGHT /* Should figure out at run time */
+ },
+# endif
+ {
+# ifdef FONTSET_ALWAYS
+ XtNmenuFontSet,
+ XtCMenuFontSet,
+#else
+ XtNmenuFont,
+ XtCMenuFont,
+#endif
+ XtRString,
+ sizeof(char *),
+ XtOffsetOf(gui_T, rsrc_menu_font_name),
+ XtRString,
+ DFLT_MENU_FONT
+ },
+#endif
+ {
+ XtNmenuForeground,
+ XtCMenuForeground,
+ XtRString,
+ sizeof(char *),
+ XtOffsetOf(gui_T, rsrc_menu_fg_name),
+ XtRString,
+ DFLT_MENU_FG_COLOR
+ },
+ {
+ XtNmenuBackground,
+ XtCMenuBackground,
+ XtRString,
+ sizeof(char *),
+ XtOffsetOf(gui_T, rsrc_menu_bg_name),
+ XtRString,
+ DFLT_MENU_BG_COLOR
+ },
+ {
+ XtNscrollForeground,
+ XtCScrollForeground,
+ XtRString,
+ sizeof(char *),
+ XtOffsetOf(gui_T, rsrc_scroll_fg_name),
+ XtRString,
+ DFLT_SCROLL_FG_COLOR
+ },
+ {
+ XtNscrollBackground,
+ XtCScrollBackground,
+ XtRString,
+ sizeof(char *),
+ XtOffsetOf(gui_T, rsrc_scroll_bg_name),
+ XtRString,
+ DFLT_SCROLL_BG_COLOR
+ },
+#ifdef FEAT_BEVAL
+ {
+ XtNtooltipForeground,
+ XtCTooltipForeground,
+ XtRString,
+ sizeof(char *),
+ XtOffsetOf(gui_T, rsrc_tooltip_fg_name),
+ XtRString,
+ DFLT_TOOLTIP_FG_COLOR
+ },
+ {
+ XtNtooltipBackground,
+ XtCTooltipBackground,
+ XtRString,
+ sizeof(char *),
+ XtOffsetOf(gui_T, rsrc_tooltip_bg_name),
+ XtRString,
+ DFLT_TOOLTIP_BG_COLOR
+ },
+ {
+ XtNtooltipFont,
+ XtCTooltipFont,
+ XtRString,
+ sizeof(char *),
+ XtOffsetOf(gui_T, rsrc_tooltip_font_name),
+ XtRString,
+ DFLT_TOOLTIP_FONT
+ },
+ /* This one isn't really needed, keep for Sun Workshop? */
+ {
+ "balloonEvalFontSet",
+ XtCFontSet,
+ XtRFontSet,
+ sizeof(XFontSet),
+ XtOffsetOf(gui_T, tooltip_fontset),
+ XtRImmediate,
+ (XtPointer)NOFONTSET
+ },
+#endif /* FEAT_BEVAL */
+#ifdef FEAT_XIM
+ {
+ "preeditType",
+ "PreeditType",
+ XtRString,
+ sizeof(char*),
+ XtOffsetOf(gui_T, rsrc_preedit_type_name),
+ XtRString,
+ (XtPointer)"OverTheSpot,OffTheSpot,Root"
+ },
+ {
+ "inputMethod",
+ "InputMethod",
+ XtRString,
+ sizeof(char*),
+ XtOffsetOf(gui_T, rsrc_input_method),
+ XtRString,
+ NULL
+ },
+#endif /* FEAT_XIM */
+};
+
+/*
+ * This table holds all the X GUI command line options allowed. This includes
+ * the standard ones so that we can skip them when vim is started without the
+ * GUI (but the GUI might start up later).
+ * When changing this, also update doc/vim_gui.txt and the usage message!!!
+ */
+static XrmOptionDescRec cmdline_options[] =
+{
+ /* We handle these options ourselves */
+ {"-bg", ".background", XrmoptionSepArg, NULL},
+ {"-background", ".background", XrmoptionSepArg, NULL},
+ {"-fg", ".foreground", XrmoptionSepArg, NULL},
+ {"-foreground", ".foreground", XrmoptionSepArg, NULL},
+ {"-fn", ".font", XrmoptionSepArg, NULL},
+ {"-font", ".font", XrmoptionSepArg, NULL},
+ {"-boldfont", ".boldFont", XrmoptionSepArg, NULL},
+ {"-italicfont", ".italicFont", XrmoptionSepArg, NULL},
+ {"-geom", ".geometry", XrmoptionSepArg, NULL},
+ {"-geometry", ".geometry", XrmoptionSepArg, NULL},
+ {"-reverse", "*reverseVideo", XrmoptionNoArg, "True"},
+ {"-rv", "*reverseVideo", XrmoptionNoArg, "True"},
+ {"+reverse", "*reverseVideo", XrmoptionNoArg, "False"},
+ {"+rv", "*reverseVideo", XrmoptionNoArg, "False"},
+ {"-display", ".display", XrmoptionSepArg, NULL},
+ {"-iconic", "*iconic", XrmoptionNoArg, "True"},
+ {"-name", ".name", XrmoptionSepArg, NULL},
+ {"-bw", ".borderWidth", XrmoptionSepArg, NULL},
+ {"-borderwidth", ".borderWidth", XrmoptionSepArg, NULL},
+ {"-sw", ".scrollbarWidth", XrmoptionSepArg, NULL},
+ {"-scrollbarwidth", ".scrollbarWidth", XrmoptionSepArg, NULL},
+ {"-mh", ".menuHeight", XrmoptionSepArg, NULL},
+ {"-menuheight", ".menuHeight", XrmoptionSepArg, NULL},
+#ifdef FONTSET_ALWAYS
+ {"-mf", ".menuFontSet", XrmoptionSepArg, NULL},
+ {"-menufont", ".menuFontSet", XrmoptionSepArg, NULL},
+ {"-menufontset", ".menuFontSet", XrmoptionSepArg, NULL},
+#else
+ {"-mf", ".menuFont", XrmoptionSepArg, NULL},
+ {"-menufont", ".menuFont", XrmoptionSepArg, NULL},
+#endif
+ {"-xrm", NULL, XrmoptionResArg, NULL}
+};
+
+static int gui_argc = 0;
+static char **gui_argv = NULL;
+
+/*
+ * Call-back routines.
+ */
+
+/* ARGSUSED */
+ static void
+gui_x11_timer_cb(timed_out, interval_id)
+ XtPointer timed_out;
+ XtIntervalId *interval_id;
+{
+ *((int *)timed_out) = TRUE;
+}
+
+/* ARGSUSED */
+ static void
+gui_x11_visibility_cb(w, dud, event, dum)
+ Widget w;
+ XtPointer dud;
+ XEvent *event;
+ Boolean *dum;
+{
+ if (event->type != VisibilityNotify)
+ return;
+
+ gui.visibility = event->xvisibility.state;
+
+ /*
+ * When we do an XCopyArea(), and the window is partially obscured, we want
+ * to receive an event to tell us whether it worked or not.
+ */
+ XSetGraphicsExposures(gui.dpy, gui.text_gc,
+ gui.visibility != VisibilityUnobscured);
+
+ /* This is needed for when redrawing is slow. */
+ gui_mch_update();
+}
+
+/* ARGSUSED */
+ static void
+gui_x11_expose_cb(w, dud, event, dum)
+ Widget w;
+ XtPointer dud;
+ XEvent *event;
+ Boolean *dum;
+{
+ XExposeEvent *gevent;
+ int new_x;
+
+ if (event->type != Expose)
+ return;
+
+ out_flush(); /* make sure all output has been processed */
+
+ gevent = (XExposeEvent *)event;
+ gui_redraw(gevent->x, gevent->y, gevent->width, gevent->height);
+
+ new_x = FILL_X(0);
+
+ /* Clear the border areas if needed */
+ if (gevent->x < new_x)
+ XClearArea(gui.dpy, gui.wid, 0, 0, new_x, 0, False);
+ if (gevent->y < FILL_Y(0))
+ XClearArea(gui.dpy, gui.wid, 0, 0, 0, FILL_Y(0), False);
+ if (gevent->x > FILL_X(Columns))
+ XClearArea(gui.dpy, gui.wid, FILL_X((int)Columns), 0, 0, 0, False);
+ if (gevent->y > FILL_Y(Rows))
+ XClearArea(gui.dpy, gui.wid, 0, FILL_Y((int)Rows), 0, 0, False);
+
+ /* This is needed for when redrawing is slow. */
+ gui_mch_update();
+}
+
+#if (defined(FEAT_NETBEANS_INTG) || defined(FEAT_SUN_WORKSHOP)) \
+ || defined(PROTO)
+/*
+ * This function fills in the XRectangle object with the current
+ * x,y coordinates and height, width so that an XtVaSetValues to
+ * the same shell of those resources will restore the window to its
+ * formar position and dimensions.
+ *
+ * Note: This function may fail, in which case the XRectangle will
+ * be unchanged. Be sure to have the XRectangle set with the
+ * proper values for a failed condition prior to calling this
+ * function.
+ */
+ static void
+shellRectangle(Widget shell, XRectangle *r)
+{
+ Window rootw, shellw, child, parentw;
+ int absx, absy;
+ XWindowAttributes a;
+ Window *children;
+ unsigned int childrenCount;
+
+ shellw = XtWindow(shell);
+ if (shellw == 0)
+ return;
+ for (;;)
+ {
+ XQueryTree(XtDisplay(shell), shellw, &rootw, &parentw,
+ &children, &childrenCount);
+ XFree(children);
+ if (parentw == rootw)
+ break;
+ shellw = parentw;
+ }
+ XGetWindowAttributes(XtDisplay(shell), shellw, &a);
+ XTranslateCoordinates(XtDisplay(shell), shellw, a.root, 0, 0,
+ &absx, &absy, &child);
+ r->x = absx;
+ r->y = absy;
+ XtVaGetValues(shell, XmNheight, &r->height, XmNwidth, &r->width, NULL);
+}
+#endif
+
+/* ARGSUSED */
+ static void
+gui_x11_resize_window_cb(w, dud, event, dum)
+ Widget w;
+ XtPointer dud;
+ XEvent *event;
+ Boolean *dum;
+{
+ static int lastWidth, lastHeight;
+
+ if (event->type != ConfigureNotify)
+ return;
+
+ if (event->xconfigure.width != lastWidth
+ || event->xconfigure.height != lastHeight)
+ {
+ lastWidth = event->xconfigure.width;
+ lastHeight = event->xconfigure.height;
+ gui_resize_shell(event->xconfigure.width, event->xconfigure.height
+#ifdef FEAT_XIM
+ - xim_get_status_area_height()
+#endif
+ );
+ }
+#ifdef FEAT_SUN_WORKSHOP
+ if (usingSunWorkShop)
+ {
+ XRectangle rec;
+
+ shellRectangle(w, &rec);
+ workshop_frame_moved(rec.x, rec.y, rec.width, rec.height);
+ }
+#endif
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ {
+ XRectangle rec;
+
+ shellRectangle(w, &rec);
+ netbeans_frame_moved(rec.x, rec.y);
+ }
+#endif
+#ifdef FEAT_XIM
+ xim_set_preedit();
+#endif
+}
+
+/* ARGSUSED */
+ static void
+gui_x11_focus_change_cb(w, data, event, dum)
+ Widget w;
+ XtPointer data;
+ XEvent *event;
+ Boolean *dum;
+{
+ gui_focus_change(event->type == FocusIn);
+}
+
+/* ARGSUSED */
+ static void
+gui_x11_enter_cb(w, data, event, dum)
+ Widget w;
+ XtPointer data;
+ XEvent *event;
+ Boolean *dum;
+{
+ gui_focus_change(TRUE);
+}
+
+/* ARGSUSED */
+ static void
+gui_x11_leave_cb(w, data, event, dum)
+ Widget w;
+ XtPointer data;
+ XEvent *event;
+ Boolean *dum;
+{
+ gui_focus_change(FALSE);
+}
+
+#if defined(X_HAVE_UTF8_STRING) && defined(FEAT_MBYTE)
+# if X_HAVE_UTF8_STRING
+# define USE_UTF8LOOKUP
+# endif
+#endif
+
+/* ARGSUSED */
+ void
+gui_x11_key_hit_cb(w, dud, event, dum)
+ Widget w;
+ XtPointer dud;
+ XEvent *event;
+ Boolean *dum;
+{
+ XKeyPressedEvent *ev_press;
+#ifdef FEAT_XIM
+ char_u string2[256];
+ char_u string_shortbuf[256];
+ char_u *string = string_shortbuf;
+ Boolean string_alloced = False;
+ Status status;
+#else
+ char_u string[4], string2[3];
+#endif
+ KeySym key_sym, key_sym2;
+ int len, len2;
+ int i;
+ int modifiers;
+ int key;
+
+ ev_press = (XKeyPressedEvent *)event;
+
+#ifdef FEAT_XIM
+ if (xic)
+ {
+# ifdef USE_UTF8LOOKUP
+ /* XFree86 4.0.2 or newer: Be able to get UTF-8 characters even when
+ * the locale isn't utf-8. */
+ if (enc_utf8)
+ len = Xutf8LookupString(xic, ev_press, (char *)string,
+ sizeof(string_shortbuf), &key_sym, &status);
+ else
+# endif
+ len = XmbLookupString(xic, ev_press, (char *)string,
+ sizeof(string_shortbuf), &key_sym, &status);
+ if (status == XBufferOverflow)
+ {
+ string = (char_u *)XtMalloc(len + 1);
+ string_alloced = True;
+# ifdef USE_UTF8LOOKUP
+ /* XFree86 4.0.2 or newer: Be able to get UTF-8 characters even
+ * when the locale isn't utf-8. */
+ if (enc_utf8)
+ len = Xutf8LookupString(xic, ev_press, (char *)string,
+ len, &key_sym, &status);
+ else
+# endif
+ len = XmbLookupString(xic, ev_press, (char *)string,
+ len, &key_sym, &status);
+ }
+ if (status == XLookupNone || status == XLookupChars)
+ key_sym = XK_VoidSymbol;
+
+# ifdef FEAT_MBYTE
+ /* Do conversion from 'termencoding' to 'encoding'. When using
+ * Xutf8LookupString() it has already been done. */
+ if (len > 0 && input_conv.vc_type != CONV_NONE
+# ifdef USE_UTF8LOOKUP
+ && !enc_utf8
+# endif
+ )
+ {
+ int maxlen = len * 4 + 40; /* guessed */
+ char_u *p = (char_u *)XtMalloc(maxlen);
+
+ mch_memmove(p, string, len);
+ if (string_alloced)
+ XtFree((char *)string);
+ string = p;
+ string_alloced = True;
+ len = convert_input(p, len, maxlen);
+ }
+# endif
+
+ /* Translate CSI to K_CSI, otherwise it could be recognized as the
+ * start of a special key. */
+ for (i = 0; i < len; ++i)
+ if (string[i] == CSI)
+ {
+ char_u *p = (char_u *)XtMalloc(len + 3);
+
+ mch_memmove(p, string, i + 1);
+ p[i + 1] = KS_EXTRA;
+ p[i + 2] = (int)KE_CSI;
+ mch_memmove(p + i + 3, string + i + 1, len - i);
+ if (string_alloced)
+ XtFree((char *)string);
+ string = p;
+ string_alloced = True;
+ i += 2;
+ len += 2;
+ }
+ }
+ else
+#endif
+ len = XLookupString(ev_press, (char *)string, sizeof(string),
+ &key_sym, NULL);
+
+#ifdef SunXK_F36
+ /*
+ * These keys have bogus lookup strings, and trapping them here is
+ * easier than trying to XRebindKeysym() on them with every possible
+ * combination of modifiers.
+ */
+ if (key_sym == SunXK_F36 || key_sym == SunXK_F37)
+ len = 0;
+#endif
+
+#ifdef FEAT_HANGULIN
+ if ((key_sym == XK_space) && (ev_press->state & ShiftMask))
+ {
+ hangul_input_state_toggle();
+ goto theend;
+ }
+#endif
+
+ if (key_sym == XK_space)
+ string[0] = ' '; /* Otherwise Ctrl-Space doesn't work */
+
+ /*
+ * Only on some machines ^_ requires Ctrl+Shift+minus. For consistency,
+ * allow just Ctrl+minus too.
+ */
+ if (key_sym == XK_minus && (ev_press->state & ControlMask))
+ string[0] = Ctrl__;
+
+#ifdef XK_ISO_Left_Tab
+ /* why do we get XK_ISO_Left_Tab instead of XK_Tab for shift-tab? */
+ if (key_sym == XK_ISO_Left_Tab)
+ {
+ key_sym = XK_Tab;
+ string[0] = TAB;
+ len = 1;
+ }
+#endif
+
+ /* Check for Alt/Meta key (Mod1Mask), but not for a BS, DEL or character
+ * that already has the 8th bit set. And not when using a double-byte
+ * encoding, setting the 8th bit may make it the lead byte of a
+ * double-byte character. */
+ if (len == 1
+ && (ev_press->state & Mod1Mask)
+ && !(key_sym == XK_BackSpace || key_sym == XK_Delete)
+ && (string[0] & 0x80) == 0
+#ifdef FEAT_MBYTE
+ && !enc_dbcs
+#endif
+ )
+ {
+#if defined(FEAT_MENU) && defined(FEAT_GUI_MOTIF)
+ /* Ignore ALT keys when they are used for the menu only */
+ if (gui.menu_is_active
+ && (p_wak[0] == 'y'
+ || (p_wak[0] == 'm' && gui_is_menu_shortcut(string[0]))))
+ goto theend;
+#endif
+ /*
+ * Before we set the 8th bit, check to make sure the user doesn't
+ * already have a mapping defined for this sequence. We determine this
+ * by checking to see if the input would be the same without the
+ * Alt/Meta key.
+ * Don't do this for <S-M-Tab>, that should become K_S_TAB with ALT.
+ */
+ ev_press->state &= ~Mod1Mask;
+ len2 = XLookupString(ev_press, (char *)string2, sizeof(string2),
+ &key_sym2, NULL);
+ if (key_sym2 == XK_space)
+ string2[0] = ' '; /* Otherwise Meta-Ctrl-Space doesn't work */
+ if ( len2 == 1
+ && string[0] == string2[0]
+ && !(key_sym == XK_Tab && (ev_press->state & ShiftMask)))
+ {
+ string[0] |= 0x80;
+#ifdef FEAT_MBYTE
+ if (enc_utf8) /* convert to utf-8 */
+ {
+ string[1] = string[0] & 0xbf;
+ string[0] = ((unsigned)string[0] >> 6) + 0xc0;
+ if (string[1] == CSI)
+ {
+ string[2] = KS_EXTRA;
+ string[3] = (int)KE_CSI;
+ len = 4;
+ }
+ else
+ len = 2;
+ }
+#endif
+ }
+ else
+ ev_press->state |= Mod1Mask;
+ }
+
+ if (len == 1 && string[0] == CSI)
+ {
+ string[1] = KS_EXTRA;
+ string[2] = (int)KE_CSI;
+ len = -3;
+ }
+
+ /* Check for special keys. Also do this when len == 1 (key has an ASCII
+ * value) to detect backspace, delete and keypad keys. */
+ if (len == 0 || len == 1)
+ {
+ for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
+ {
+ if (special_keys[i].key_sym == key_sym)
+ {
+ string[0] = CSI;
+ string[1] = special_keys[i].vim_code0;
+ string[2] = special_keys[i].vim_code1;
+ len = -3;
+ break;
+ }
+ }
+ }
+
+ /* Unrecognised key is ignored. */
+ if (len == 0)
+ goto theend;
+
+ /* Special keys (and a few others) may have modifiers. Also when using a
+ * double-byte encoding (can't set the 8th bit). */
+ if (len == -3 || key_sym == XK_space || key_sym == XK_Tab
+ || key_sym == XK_Return || key_sym == XK_Linefeed
+ || key_sym == XK_Escape
+#ifdef FEAT_MBYTE
+ || (enc_dbcs && len == 1 && (ev_press->state & Mod1Mask))
+#endif
+ )
+ {
+ modifiers = 0;
+ if (ev_press->state & ShiftMask)
+ modifiers |= MOD_MASK_SHIFT;
+ if (ev_press->state & ControlMask)
+ modifiers |= MOD_MASK_CTRL;
+ if (ev_press->state & Mod1Mask)
+ modifiers |= MOD_MASK_ALT;
+
+ /*
+ * For some keys a shift modifier is translated into another key
+ * code.
+ */
+ if (len == -3)
+ key = TO_SPECIAL(string[1], string[2]);
+ else
+ key = string[0];
+ key = simplify_key(key, &modifiers);
+ if (key == CSI)
+ key = K_CSI;
+ if (IS_SPECIAL(key))
+ {
+ string[0] = CSI;
+ string[1] = K_SECOND(key);
+ string[2] = K_THIRD(key);
+ len = 3;
+ }
+ else
+ {
+ string[0] = key;
+ len = 1;
+ }
+
+ if (modifiers != 0)
+ {
+ string2[0] = CSI;
+ string2[1] = KS_MODIFIER;
+ string2[2] = modifiers;
+ add_to_input_buf(string2, 3);
+ }
+ }
+
+ if (len == 1 && ((string[0] == Ctrl_C && ctrl_c_interrupts)
+#ifdef UNIX
+ || (intr_char != 0 && string[0] == intr_char)
+#endif
+ ))
+ {
+ trash_input_buf();
+ got_int = TRUE;
+ }
+
+ add_to_input_buf(string, len);
+
+ /*
+ * blank out the pointer if necessary
+ */
+ if (p_mh)
+ gui_mch_mousehide(TRUE);
+
+#if defined(FEAT_BEVAL_TIP)
+ {
+ BalloonEval *be;
+
+ if ((be = gui_mch_currently_showing_beval()) != NULL)
+ gui_mch_unpost_balloon(be);
+ }
+#endif
+theend:
+ {} /* some compilers need a statement here */
+#ifdef FEAT_XIM
+ if (string_alloced)
+ XtFree((char *)string);
+#endif
+}
+
+/* ARGSUSED */
+ static void
+gui_x11_mouse_cb(w, dud, event, dum)
+ Widget w;
+ XtPointer dud;
+ XEvent *event;
+ Boolean *dum;
+{
+ static XtIntervalId timer = (XtIntervalId)0;
+ static int timed_out = TRUE;
+
+ int button;
+ int repeated_click = FALSE;
+ int x, y;
+ int_u x_modifiers;
+ int_u vim_modifiers;
+
+ if (event->type == MotionNotify)
+ {
+ /* Get the latest position, avoids lagging behind on a drag. */
+ x = event->xmotion.x;
+ y = event->xmotion.y;
+ x_modifiers = event->xmotion.state;
+ button = (x_modifiers & (Button1Mask | Button2Mask | Button3Mask))
+ ? MOUSE_DRAG : ' ';
+
+ /*
+ * if our pointer is currently hidden, then we should show it.
+ */
+ gui_mch_mousehide(FALSE);
+
+ if (button != MOUSE_DRAG) /* just moving the rodent */
+ {
+#ifdef FEAT_MENU
+ if (dud) /* moved in vimForm */
+ y -= gui.menu_height;
+#endif
+ gui_mouse_moved(x, y);
+ return;
+ }
+ }
+ else
+ {
+ x = event->xbutton.x;
+ y = event->xbutton.y;
+ if (event->type == ButtonPress)
+ {
+ /* Handle multiple clicks */
+ if (!timed_out)
+ {
+ XtRemoveTimeOut(timer);
+ repeated_click = TRUE;
+ }
+ timed_out = FALSE;
+ timer = XtAppAddTimeOut(app_context, (long_u)p_mouset,
+ gui_x11_timer_cb, &timed_out);
+ switch (event->xbutton.button)
+ {
+ case Button1: button = MOUSE_LEFT; break;
+ case Button2: button = MOUSE_MIDDLE; break;
+ case Button3: button = MOUSE_RIGHT; break;
+ case Button4: button = MOUSE_4; break;
+ case Button5: button = MOUSE_5; break;
+ default:
+ return; /* Unknown button */
+ }
+ }
+ else if (event->type == ButtonRelease)
+ button = MOUSE_RELEASE;
+ else
+ return; /* Unknown mouse event type */
+
+ x_modifiers = event->xbutton.state;
+#if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU)
+ last_mouse_event = event->xbutton;
+#endif
+ }
+
+ vim_modifiers = 0x0;
+ if (x_modifiers & ShiftMask)
+ vim_modifiers |= MOUSE_SHIFT;
+ if (x_modifiers & ControlMask)
+ vim_modifiers |= MOUSE_CTRL;
+ if (x_modifiers & Mod1Mask) /* Alt or Meta key */
+ vim_modifiers |= MOUSE_ALT;
+
+ gui_send_mouse_event(button, x, y, repeated_click, vim_modifiers);
+}
+
+#ifdef FEAT_SNIFF
+/* ARGSUSED */
+ static void
+gui_x11_sniff_request_cb(closure, source, id)
+ XtPointer closure;
+ int *source;
+ XtInputId *id;
+{
+ static char_u bytes[3] = {CSI, (int)KS_EXTRA, (int)KE_SNIFF};
+
+ add_to_input_buf(bytes, 3);
+}
+#endif
+
+/*
+ * End of call-back routines
+ */
+
+/*
+ * Parse the GUI related command-line arguments. Any arguments used are
+ * deleted from argv, and *argc is decremented accordingly. This is called
+ * when vim is started, whether or not the GUI has been started.
+ */
+ void
+gui_mch_prepare(argc, argv)
+ int *argc;
+ char **argv;
+{
+ int arg;
+ int i;
+
+ /*
+ * Move all the entries in argv which are relevant to X into gui_argv.
+ */
+ gui_argc = 0;
+ gui_argv = (char **)lalloc((long_u)(*argc * sizeof(char *)), FALSE);
+ if (gui_argv == NULL)
+ return;
+ gui_argv[gui_argc++] = argv[0];
+ arg = 1;
+ while (arg < *argc)
+ {
+ /* Look for argv[arg] in cmdline_options[] table */
+ for (i = 0; i < XtNumber(cmdline_options); i++)
+ if (strcmp(argv[arg], cmdline_options[i].option) == 0)
+ break;
+
+ if (i < XtNumber(cmdline_options))
+ {
+ /* Remember finding "-rv" or "-reverse" */
+ if (strcmp("-rv", argv[arg]) == 0
+ || strcmp("-reverse", argv[arg]) == 0)
+ found_reverse_arg = TRUE;
+ else if ((strcmp("-fn", argv[arg]) == 0
+ || strcmp("-font", argv[arg]) == 0)
+ && arg + 1 < *argc)
+ font_argument = argv[arg + 1];
+
+ /* Found match in table, so move it into gui_argv */
+ gui_argv[gui_argc++] = argv[arg];
+ if (--*argc > arg)
+ {
+ mch_memmove(&argv[arg], &argv[arg + 1], (*argc - arg)
+ * sizeof(char *));
+ if (cmdline_options[i].argKind != XrmoptionNoArg)
+ {
+ /* Move the options argument as well */
+ gui_argv[gui_argc++] = argv[arg];
+ if (--*argc > arg)
+ mch_memmove(&argv[arg], &argv[arg + 1], (*argc - arg)
+ * sizeof(char *));
+ }
+ }
+ argv[*argc] = NULL;
+ }
+ else
+#ifdef FEAT_SUN_WORKSHOP
+ if (strcmp("-ws", argv[arg]) == 0)
+ {
+ usingSunWorkShop++;
+ p_acd = TRUE;
+ gui.dofork = FALSE; /* don't fork() when starting GUI */
+ mch_memmove(&argv[arg], &argv[arg + 1],
+ (--*argc - arg) * sizeof(char *));
+ argv[*argc] = NULL;
+# ifdef WSDEBUG
+ wsdebug_wait(WT_ENV | WT_WAIT | WT_STOP, "SPRO_GVIM_WAIT", 20);
+ wsdebug_log_init("SPRO_GVIM_DEBUG", "SPRO_GVIM_DLEVEL");
+# endif
+ }
+ else
+#endif
+#ifdef FEAT_NETBEANS_INTG
+ if (strncmp("-nb", argv[arg], 3) == 0)
+ {
+ usingNetbeans++;
+ gui.dofork = FALSE; /* don't fork() when starting GUI */
+ netbeansArg = argv[arg];
+ mch_memmove(&argv[arg], &argv[arg + 1],
+ (--*argc - arg) * sizeof(char *));
+ argv[*argc] = NULL;
+ }
+ else
+#endif
+ arg++;
+ }
+}
+
+#ifndef XtSpecificationRelease
+# define CARDINAL (Cardinal *)
+#else
+# if XtSpecificationRelease == 4
+# define CARDINAL (Cardinal *)
+# else
+# define CARDINAL (int *)
+# endif
+#endif
+
+/*
+ * Check if the GUI can be started. Called before gvimrc is sourced.
+ * Return OK or FAIL.
+ */
+ int
+gui_mch_init_check()
+{
+#ifdef FEAT_XIM
+ XtSetLanguageProc(NULL, NULL, NULL);
+#endif
+ open_app_context();
+ if (app_context != NULL)
+ gui.dpy = XtOpenDisplay(app_context, 0, VIM_NAME, VIM_CLASS,
+ cmdline_options, XtNumber(cmdline_options),
+ CARDINAL &gui_argc, gui_argv);
+
+ if (app_context == NULL || gui.dpy == NULL)
+ {
+ gui.dying = TRUE;
+ EMSG(_(e_opendisp));
+ return FAIL;
+ }
+ return OK;
+}
+
+
+#ifdef USE_XSMP
+/*
+ * Handle XSMP processing, de-registering the attachment upon error
+ */
+static XtInputId _xsmp_xtinputid;
+
+static void local_xsmp_handle_requests __ARGS((XtPointer c, int *s, XtInputId *i));
+
+/*ARGSUSED*/
+ static void
+local_xsmp_handle_requests(c, s, i)
+ XtPointer c;
+ int *s;
+ XtInputId *i;
+{
+ if (xsmp_handle_requests() == FAIL)
+ XtRemoveInput(_xsmp_xtinputid);
+}
+#endif
+
+
+/*
+ * Initialise the X GUI. Create all the windows, set up all the call-backs etc.
+ * Returns OK for success, FAIL when the GUI can't be started.
+ */
+ int
+gui_mch_init()
+{
+ XtGCMask gc_mask;
+ XGCValues gc_vals;
+ int x, y, mask;
+ unsigned w, h;
+
+#if 0
+ /* Uncomment this to enable synchronous mode for debugging */
+ XSynchronize(gui.dpy, True);
+#endif
+
+ vimShell = XtVaAppCreateShell(VIM_NAME, VIM_CLASS,
+ applicationShellWidgetClass, gui.dpy, NULL);
+
+ /*
+ * Get the application resources
+ */
+ XtVaGetApplicationResources(vimShell, (XtPointer)&gui,
+ vim_resources, XtNumber(vim_resources), NULL);
+
+ gui.scrollbar_height = gui.scrollbar_width;
+
+ /*
+ * Get the colors ourselves. Using the automatic conversion doesn't
+ * handle looking for approximate colors.
+ */
+ /* NOTE: These next few lines are an exact duplicate of gui_athena.c's
+ * gui_mch_def_colors(). Why?
+ */
+ gui.menu_fg_pixel = gui_get_color((char_u *)gui.rsrc_menu_fg_name);
+ gui.menu_bg_pixel = gui_get_color((char_u *)gui.rsrc_menu_bg_name);
+ gui.scroll_fg_pixel = gui_get_color((char_u *)gui.rsrc_scroll_fg_name);
+ gui.scroll_bg_pixel = gui_get_color((char_u *)gui.rsrc_scroll_bg_name);
+#ifdef FEAT_BEVAL
+ gui.tooltip_fg_pixel = gui_get_color((char_u *)gui.rsrc_tooltip_fg_name);
+ gui.tooltip_bg_pixel = gui_get_color((char_u *)gui.rsrc_tooltip_bg_name);
+#endif
+
+#if defined(FEAT_MENU) && defined(FEAT_GUI_ATHENA)
+ /* If the menu height was set, don't change it at runtime */
+ if (gui.menu_height != MENU_DEFAULT_HEIGHT)
+ gui.menu_height_fixed = TRUE;
+#endif
+
+ /* Set default foreground and background colours */
+ gui.norm_pixel = gui.def_norm_pixel;
+ gui.back_pixel = gui.def_back_pixel;
+
+ /* Check if reverse video needs to be applied (on Sun it's done by X) */
+ if (gui.rsrc_rev_video && gui_get_lightness(gui.back_pixel)
+ > gui_get_lightness(gui.norm_pixel))
+ {
+ gui.norm_pixel = gui.def_back_pixel;
+ gui.back_pixel = gui.def_norm_pixel;
+ gui.def_norm_pixel = gui.norm_pixel;
+ gui.def_back_pixel = gui.back_pixel;
+ }
+
+ /* Get the colors from the "Normal", "Tooltip", "Scrollbar" and "Menu"
+ * group (set in syntax.c or in a vimrc file) */
+ set_normal_colors();
+
+ /*
+ * Check that none of the colors are the same as the background color
+ */
+ gui_check_colors();
+
+ /*
+ * Set up the GCs. The font attributes will be set in gui_init_font().
+ */
+ gc_mask = GCForeground | GCBackground;
+ gc_vals.foreground = gui.norm_pixel;
+ gc_vals.background = gui.back_pixel;
+ gui.text_gc = XtGetGC(vimShell, gc_mask, &gc_vals);
+
+ gc_vals.foreground = gui.back_pixel;
+ gc_vals.background = gui.norm_pixel;
+ gui.back_gc = XtGetGC(vimShell, gc_mask, &gc_vals);
+
+ gc_mask |= GCFunction;
+ gc_vals.foreground = gui.norm_pixel ^ gui.back_pixel;
+ gc_vals.background = gui.norm_pixel ^ gui.back_pixel;
+ gc_vals.function = GXxor;
+ gui.invert_gc = XtGetGC(vimShell, gc_mask, &gc_vals);
+
+ gui.visibility = VisibilityUnobscured;
+ x11_setup_atoms(gui.dpy);
+
+ if (gui_win_x != -1 && gui_win_y != -1)
+ gui_mch_set_winpos(gui_win_x, gui_win_y);
+
+ /* Now adapt the supplied(?) geometry-settings */
+ /* Added by Kjetil Jacobsen <kjetilja@stud.cs.uit.no> */
+ if (gui.geom != NULL && *gui.geom != NUL)
+ {
+ mask = XParseGeometry((char *)gui.geom, &x, &y, &w, &h);
+ if (mask & WidthValue)
+ Columns = w;
+ if (mask & HeightValue)
+ Rows = h;
+ /*
+ * Set the (x,y) position of the main window only if specified in the
+ * users geometry, so we get good defaults when they don't. This needs
+ * to be done before the shell is popped up.
+ */
+ if (mask & (XValue|YValue))
+ XtVaSetValues(vimShell, XtNgeometry, gui.geom, NULL);
+ }
+
+ gui_x11_create_widgets();
+
+ /*
+ * Add an icon to Vim (Marcel Douben: 11 May 1998).
+ */
+ if (vim_strchr(p_go, GO_ICON) != NULL)
+ {
+#ifndef HAVE_XPM
+# include "vim_icon.xbm"
+# include "vim_mask.xbm"
+
+ Arg arg[2];
+
+ XtSetArg(arg[0], XtNiconPixmap,
+ XCreateBitmapFromData(gui.dpy,
+ DefaultRootWindow(gui.dpy),
+ (char *)vim_icon_bits,
+ vim_icon_width,
+ vim_icon_height));
+ XtSetArg(arg[1], XtNiconMask,
+ XCreateBitmapFromData(gui.dpy,
+ DefaultRootWindow(gui.dpy),
+ (char *)vim_mask_icon_bits,
+ vim_mask_icon_width,
+ vim_mask_icon_height));
+ XtSetValues(vimShell, arg, (Cardinal)2);
+#else
+/* Use Pixmaps, looking much nicer. */
+
+/* If you get an error message here, you still need to unpack the runtime
+ * archive! */
+# ifdef magick
+# undef magick
+# endif
+# define magick vim32x32
+# include "../runtime/vim32x32.xpm"
+# undef magick
+# define magick vim16x16
+# include "../runtime/vim16x16.xpm"
+# undef magick
+# define magick vim48x48
+# include "../runtime/vim48x48.xpm"
+# undef magick
+
+ static Pixmap icon = 0;
+ static Pixmap icon_mask = 0;
+ static char **magick = vim32x32;
+ Window root_window;
+ XIconSize *size;
+ int number_sizes;
+ Display *dsp;
+ Screen *scr;
+ XpmAttributes attr;
+ Colormap cmap;
+
+ /*
+ * Adjust the icon to the preferences of the actual window manager.
+ */
+ root_window = XRootWindowOfScreen(XtScreen(vimShell));
+ if (XGetIconSizes(XtDisplay(vimShell), root_window,
+ &size, &number_sizes) != 0)
+ {
+
+ if (number_sizes > 0)
+ {
+ if (size->max_height >= 48 && size->max_height >= 48)
+ magick = vim48x48;
+ else if (size->max_height >= 32 && size->max_height >= 32)
+ magick = vim32x32;
+ else if (size->max_height >= 16 && size->max_height >= 16)
+ magick = vim16x16;
+ }
+ }
+
+ dsp = XtDisplay(vimShell);
+ scr = XtScreen(vimShell);
+
+ cmap = DefaultColormap(dsp, DefaultScreen(dsp));
+ XtVaSetValues(vimShell, XtNcolormap, cmap, NULL);
+
+ attr.valuemask = 0L;
+ attr.valuemask = XpmCloseness | XpmReturnPixels | XpmColormap | XpmDepth;
+ attr.closeness = 65535; /* accuracy isn't crucial */
+ attr.colormap = cmap;
+ attr.depth = DefaultDepthOfScreen(scr);
+
+ if (!icon)
+ XpmCreatePixmapFromData(dsp, root_window, magick, &icon,
+ &icon_mask, &attr);
+
+# ifdef FEAT_GUI_ATHENA
+ XtVaSetValues(vimShell, XtNiconPixmap, icon, XtNiconMask, icon_mask, NULL);
+# else
+ XtVaSetValues(vimShell, XmNiconPixmap, icon, XmNiconMask, icon_mask, NULL);
+# endif
+#endif
+ }
+
+ if (gui.color_approx)
+ EMSG(_("Vim E458: Cannot allocate colormap entry, some colors may be incorrect"));
+
+#ifdef FEAT_SUN_WORKSHOP
+ if (usingSunWorkShop)
+ workshop_connect(app_context);
+#endif
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ netbeans_Xt_connect(app_context);
+#endif
+
+#ifdef FEAT_BEVAL
+ gui_init_tooltip_font();
+#endif
+#ifdef FEAT_MENU
+ gui_init_menu_font();
+#endif
+
+#ifdef USE_XSMP
+ /* Attach listener on ICE connection */
+ if (-1 != xsmp_icefd)
+ _xsmp_xtinputid = XtAppAddInput(app_context, xsmp_icefd,
+ (XtPointer)XtInputReadMask, local_xsmp_handle_requests, NULL);
+#endif
+
+ return OK;
+}
+
+/*
+ * Called when starting the GUI fails after calling gui_mch_init().
+ */
+ void
+gui_mch_uninit()
+{
+ gui_x11_destroy_widgets();
+#ifndef LESSTIF_VERSION
+ XtCloseDisplay(gui.dpy);
+#endif
+ gui.dpy = NULL;
+ vimShell = (Widget)0;
+}
+
+/*
+ * Called when the foreground or background color has been changed.
+ */
+ void
+gui_mch_new_colors()
+{
+ long_u gc_mask;
+ XGCValues gc_vals;
+
+ gc_mask = GCForeground | GCBackground;
+ gc_vals.foreground = gui.norm_pixel;
+ gc_vals.background = gui.back_pixel;
+ if (gui.text_gc != NULL)
+ XChangeGC(gui.dpy, gui.text_gc, gc_mask, &gc_vals);
+
+ gc_vals.foreground = gui.back_pixel;
+ gc_vals.background = gui.norm_pixel;
+ if (gui.back_gc != NULL)
+ XChangeGC(gui.dpy, gui.back_gc, gc_mask, &gc_vals);
+
+ gc_mask |= GCFunction;
+ gc_vals.foreground = gui.norm_pixel ^ gui.back_pixel;
+ gc_vals.background = gui.norm_pixel ^ gui.back_pixel;
+ gc_vals.function = GXxor;
+ if (gui.invert_gc != NULL)
+ XChangeGC(gui.dpy, gui.invert_gc, gc_mask, &gc_vals);
+
+ gui_x11_set_back_color();
+}
+
+/*
+ * Open the GUI window which was created by a call to gui_mch_init().
+ */
+ int
+gui_mch_open()
+{
+ /* Actually open the window */
+ XtPopup(vimShell, XtGrabNone);
+
+ gui.wid = gui_x11_get_wid();
+ gui.blank_pointer = gui_x11_create_blank_mouse();
+
+ /*
+ * Add a callback for the Close item on the window managers menu, and the
+ * save-yourself event.
+ */
+ wm_atoms[SAVE_YOURSELF_IDX] =
+ XInternAtom(gui.dpy, "WM_SAVE_YOURSELF", False);
+ wm_atoms[DELETE_WINDOW_IDX] =
+ XInternAtom(gui.dpy, "WM_DELETE_WINDOW", False);
+ XSetWMProtocols(gui.dpy, XtWindow(vimShell), wm_atoms, 2);
+ XtAddEventHandler(vimShell, NoEventMask, True, gui_x11_wm_protocol_handler,
+ NULL);
+#ifdef HAVE_X11_XMU_EDITRES_H
+ /*
+ * Enable editres protocol (see "man editres").
+ * Usually will need to add -lXmu to the linker line as well.
+ */
+ XtAddEventHandler(vimShell, (EventMask)0, True, _XEditResCheckMessages,
+ (XtPointer)NULL);
+#endif
+
+#ifdef FEAT_CLIENTSERVER
+ if (serverName == NULL && serverDelayedStartName != NULL)
+ {
+ /* This is a :gui command in a plain vim with no previous server */
+ commWindow = XtWindow(vimShell);
+ (void)serverRegisterName(gui.dpy, serverDelayedStartName);
+ }
+ else
+ {
+ /*
+ * Cannot handle "widget-less" windows with XtProcessEvent() we'll
+ * have to change the "server" registration to that of the main window
+ * If we have not registered a name yet, remember the window
+ */
+ serverChangeRegisteredWindow(gui.dpy, XtWindow(vimShell));
+ }
+ XtAddEventHandler(vimShell, PropertyChangeMask, False,
+ gui_x11_send_event_handler, NULL);
+#endif
+
+
+#if defined(FEAT_MENU) && defined(FEAT_GUI_ATHENA)
+ /* The Athena GUI needs this again after opening the window */
+ gui_position_menu();
+# ifdef FEAT_TOOLBAR
+ gui_mch_set_toolbar_pos(0, gui.menu_height, gui.menu_width,
+ gui.toolbar_height);
+# endif
+#endif
+
+ /* Get the colors for the highlight groups (gui_check_colors() might have
+ * changed them) */
+ highlight_gui_started(); /* re-init colors and fonts */
+
+#ifdef FEAT_HANGULIN
+ hangul_keyboard_set();
+#endif
+#ifdef FEAT_XIM
+ xim_init();
+#endif
+#ifdef FEAT_SUN_WORKSHOP
+ workshop_postinit();
+#endif
+
+ return OK;
+}
+
+#if defined(FEAT_BEVAL) || defined(PROTO)
+/*
+ * Convert the tooltip fontset name to an XFontSet.
+ */
+ void
+gui_init_tooltip_font()
+{
+ XrmValue from, to;
+
+ from.addr = (char *)gui.rsrc_tooltip_font_name;
+ from.size = strlen(from.addr);
+ to.addr = (XtPointer)&gui.tooltip_fontset;
+ to.size = sizeof(XFontSet);
+
+ if (XtConvertAndStore(vimShell, XtRString, &from, XtRFontSet, &to) == False)
+ {
+ /* Failed. What to do? */
+ }
+}
+#endif
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/* Convert the menu font/fontset name to an XFontStruct/XFontset */
+ void
+gui_init_menu_font()
+{
+ XrmValue from, to;
+
+#ifdef FONTSET_ALWAYS
+ from.addr = (char *)gui.rsrc_menu_font_name;
+ from.size = strlen(from.addr);
+ to.addr = (XtPointer)&gui.menu_fontset;
+ to.size = sizeof(GuiFontset);
+
+ if (XtConvertAndStore(vimShell, XtRString, &from, XtRFontSet, &to) == False)
+ {
+ /* Failed. What to do? */
+ }
+#else
+ from.addr = (char *)gui.rsrc_menu_font_name;
+ from.size = strlen(from.addr);
+ to.addr = (XtPointer)&gui.menu_font;
+ to.size = sizeof(GuiFont);
+
+ if (XtConvertAndStore(vimShell, XtRString, &from, XtRFontStruct, &to) == False)
+ {
+ /* Failed. What to do? */
+ }
+#endif
+}
+#endif
+
+/*ARGSUSED*/
+ void
+gui_mch_exit(rc)
+ int rc;
+{
+#if 0
+ /* Lesstif gives an error message here, and so does Solaris. The man page
+ * says that this isn't needed when exiting, so just skip it. */
+ XtCloseDisplay(gui.dpy);
+#endif
+}
+
+/*
+ * Get the position of the top left corner of the window.
+ */
+ int
+gui_mch_get_winpos(x, y)
+ int *x, *y;
+{
+ Dimension xpos, ypos;
+
+ XtVaGetValues(vimShell,
+ XtNx, &xpos,
+ XtNy, &ypos,
+ NULL);
+ *x = xpos;
+ *y = ypos;
+ return OK;
+}
+
+/*
+ * Set the position of the top left corner of the window to the given
+ * coordinates.
+ */
+ void
+gui_mch_set_winpos(x, y)
+ int x, y;
+{
+ XtVaSetValues(vimShell,
+ XtNx, x,
+ XtNy, y,
+ NULL);
+}
+
+ void
+gui_mch_set_shellsize(width, height, min_width, min_height,
+ base_width, base_height)
+ int width;
+ int height;
+ int min_width;
+ int min_height;
+ int base_width;
+ int base_height;
+{
+ XtVaSetValues(vimShell,
+ XtNwidthInc, gui.char_width,
+ XtNheightInc, gui.char_height,
+#if defined(XtSpecificationRelease) && XtSpecificationRelease >= 4
+ XtNbaseWidth, base_width,
+ XtNbaseHeight, base_height,
+#endif
+ XtNminWidth, min_width,
+ XtNminHeight, min_height,
+ XtNwidth, width,
+#ifdef FEAT_XIM
+ XtNheight, height + xim_get_status_area_height(),
+#else
+ XtNheight, height,
+#endif
+ NULL);
+}
+
+/*
+ * Allow 10 pixels for horizontal borders, 30 for vertical borders.
+ * Is there no way in X to find out how wide the borders really are?
+ */
+ void
+gui_mch_get_screen_dimensions(screen_w, screen_h)
+ int *screen_w;
+ int *screen_h;
+{
+ *screen_w = DisplayWidth(gui.dpy, DefaultScreen(gui.dpy)) - 10;
+ *screen_h = DisplayHeight(gui.dpy, DefaultScreen(gui.dpy)) - p_ghr;
+}
+
+/*
+ * Initialise vim to use the font "font_name". If it's NULL, pick a default
+ * font.
+ * If "fontset" is TRUE, load the "font_name" as a fontset.
+ * Return FAIL if the font could not be loaded, OK otherwise.
+ */
+/*ARGSUSED*/
+ int
+gui_mch_init_font(font_name, do_fontset)
+ char_u *font_name;
+ int do_fontset;
+{
+ XFontStruct *font = NULL;
+
+#ifdef FEAT_XFONTSET
+ XFontSet fontset = NULL;
+
+ if (do_fontset)
+ {
+ /* If 'guifontset' is set, VIM treats all font specifications as if
+ * they were fontsets, and 'guifontset' becomes the default. */
+ if (font_name != NULL)
+ {
+ fontset = (XFontSet)gui_mch_get_fontset(font_name, FALSE, TRUE);
+ if (fontset == NULL)
+ return FAIL;
+ }
+ }
+ else
+#endif
+ {
+ if (font_name == NULL)
+ {
+ /*
+ * If none of the fonts in 'font' could be loaded, try the one set
+ * in the X resource, and finally just try using DFLT_FONT, which
+ * will hopefully always be there.
+ */
+ font_name = gui.rsrc_font_name;
+ font = (XFontStruct *)gui_mch_get_font(font_name, FALSE);
+ if (font == NULL)
+ font_name = (char_u *)DFLT_FONT;
+ }
+ if (font == NULL)
+ font = (XFontStruct *)gui_mch_get_font(font_name, FALSE);
+ if (font == NULL)
+ return FAIL;
+ }
+
+ gui_mch_free_font(gui.norm_font);
+#ifdef FEAT_XFONTSET
+ gui_mch_free_fontset(gui.fontset);
+
+ if (fontset != NULL)
+ {
+ gui.norm_font = NOFONT;
+ gui.fontset = (GuiFontset)fontset;
+ gui.char_width = fontset_width(fontset);
+ gui.char_height = fontset_height(fontset) + p_linespace;
+ gui.char_ascent = fontset_ascent(fontset) + p_linespace / 2;
+ }
+ else
+#endif
+ {
+ gui.norm_font = (GuiFont)font;
+#ifdef FEAT_XFONTSET
+ gui.fontset = NOFONTSET;
+#endif
+ gui.char_width = font->max_bounds.width;
+ gui.char_height = font->ascent + font->descent + p_linespace;
+ gui.char_ascent = font->ascent + p_linespace / 2;
+ }
+
+ hl_set_font_name(font_name);
+
+ /*
+ * Try to load other fonts for bold, italic, and bold-italic.
+ * We should also try to work out what font to use for these when they are
+ * not specified by X resources, but we don't yet.
+ */
+ if (font_name == gui.rsrc_font_name)
+ {
+ if (gui.bold_font == NOFONT
+ && gui.rsrc_bold_font_name != NULL
+ && *gui.rsrc_bold_font_name != NUL)
+ gui.bold_font = gui_mch_get_font(gui.rsrc_bold_font_name, FALSE);
+ if (gui.ital_font == NOFONT
+ && gui.rsrc_ital_font_name != NULL
+ && *gui.rsrc_ital_font_name != NUL)
+ gui.ital_font = gui_mch_get_font(gui.rsrc_ital_font_name, FALSE);
+ if (gui.boldital_font == NOFONT
+ && gui.rsrc_boldital_font_name != NULL
+ && *gui.rsrc_boldital_font_name != NUL)
+ gui.boldital_font = gui_mch_get_font(gui.rsrc_boldital_font_name,
+ FALSE);
+ }
+ else
+ {
+ /* When not using the font specified by the resources, also don't use
+ * the bold/italic fonts, otherwise setting 'guifont' will look very
+ * strange. */
+ if (gui.bold_font != NOFONT)
+ {
+ XFreeFont(gui.dpy, (XFontStruct *)gui.bold_font);
+ gui.bold_font = NOFONT;
+ }
+ if (gui.ital_font != NOFONT)
+ {
+ XFreeFont(gui.dpy, (XFontStruct *)gui.ital_font);
+ gui.ital_font = NOFONT;
+ }
+ if (gui.boldital_font != NOFONT)
+ {
+ XFreeFont(gui.dpy, (XFontStruct *)gui.boldital_font);
+ gui.boldital_font = NOFONT;
+ }
+ }
+
+ return OK;
+}
+
+/*
+ * Get a font structure for highlighting.
+ */
+ GuiFont
+gui_mch_get_font(name, giveErrorIfMissing)
+ char_u *name;
+ int giveErrorIfMissing;
+{
+ XFontStruct *font;
+
+ if (!gui.in_use || name == NULL) /* can't do this when GUI not running */
+ return NOFONT;
+
+ font = XLoadQueryFont(gui.dpy, (char *)name);
+
+ if (font == NULL)
+ {
+ if (giveErrorIfMissing)
+ EMSG2(_(e_font), name);
+ return NOFONT;
+ }
+
+#ifdef DEBUG
+ printf("Font Information for '%s':\n", name);
+ printf(" w = %d, h = %d, ascent = %d, descent = %d\n",
+ font->max_bounds.width, font->ascent + font->descent,
+ font->ascent, font->descent);
+ printf(" max ascent = %d, max descent = %d, max h = %d\n",
+ font->max_bounds.ascent, font->max_bounds.descent,
+ font->max_bounds.ascent + font->max_bounds.descent);
+ printf(" min lbearing = %d, min rbearing = %d\n",
+ font->min_bounds.lbearing, font->min_bounds.rbearing);
+ printf(" max lbearing = %d, max rbearing = %d\n",
+ font->max_bounds.lbearing, font->max_bounds.rbearing);
+ printf(" leftink = %d, rightink = %d\n",
+ (font->min_bounds.lbearing < 0),
+ (font->max_bounds.rbearing > font->max_bounds.width));
+ printf("\n");
+#endif
+
+ if (font->max_bounds.width != font->min_bounds.width)
+ {
+ EMSG2(_(e_fontwidth), name);
+ XFreeFont(gui.dpy, font);
+ return NOFONT;
+ }
+ return (GuiFont)font;
+}
+
+ int
+gui_mch_adjust_charsize()
+{
+#ifdef FEAT_XFONTSET
+ if (gui.fontset != NOFONTSET)
+ {
+ gui.char_height = fontset_height((XFontSet)gui.fontset) + p_linespace;
+ gui.char_ascent = fontset_ascent((XFontSet)gui.fontset)
+ + p_linespace / 2;
+ }
+ else
+#endif
+ {
+ XFontStruct *font = (XFontStruct *)gui.norm_font;
+
+ gui.char_height = font->ascent + font->descent + p_linespace;
+ gui.char_ascent = font->ascent + p_linespace / 2;
+ }
+ return OK;
+}
+
+/*
+ * Set the current text font.
+ */
+ void
+gui_mch_set_font(font)
+ GuiFont font;
+{
+ static Font prev_font = (Font)-1;
+ Font fid = ((XFontStruct *)font)->fid;
+
+ if (fid != prev_font)
+ {
+ XSetFont(gui.dpy, gui.text_gc, fid);
+ XSetFont(gui.dpy, gui.back_gc, fid);
+ prev_font = fid;
+ gui.char_ascent = ((XFontStruct *)font)->ascent + p_linespace / 2;
+ }
+#ifdef FEAT_XFONTSET
+ current_fontset = (XFontSet)NULL;
+#endif
+}
+
+#if defined(FEAT_XFONTSET) || defined(PROTO)
+/*
+ * Set the current text fontset.
+ * Adjust the ascent, in case it's different.
+ */
+ void
+gui_mch_set_fontset(fontset)
+ GuiFontset fontset;
+{
+ current_fontset = (XFontSet)fontset;
+ gui.char_ascent = fontset_ascent(current_fontset) + p_linespace / 2;
+}
+#endif
+
+#if 0 /* not used */
+/*
+ * Return TRUE if the two fonts given are equivalent.
+ */
+ int
+gui_mch_same_font(f1, f2)
+ GuiFont f1;
+ GuiFont f2;
+{
+#ifdef FEAT_XFONTSET
+ if (gui.fontset != NULL)
+ return f1 == f2;
+ else
+#endif
+ return ((XFontStruct *)f1)->fid == ((XFontStruct *)f2)->fid;
+}
+#endif
+
+/*
+ * If a font is not going to be used, free its structure.
+ */
+ void
+gui_mch_free_font(font)
+ GuiFont font;
+{
+ if (font != NOFONT)
+ XFreeFont(gui.dpy, (XFontStruct *)font);
+}
+
+#if defined(FEAT_XFONTSET) || defined(PROTO)
+/*
+ * If a fontset is not going to be used, free its structure.
+ */
+ void
+gui_mch_free_fontset(fontset)
+ GuiFontset fontset;
+{
+ if (fontset != NOFONTSET)
+ XFreeFontSet(gui.dpy, (XFontSet)fontset);
+}
+
+/*
+ * Load the fontset "name".
+ * Return a reference to the fontset, or NOFONTSET when failing.
+ */
+ GuiFontset
+gui_mch_get_fontset(name, giveErrorIfMissing, fixed_width)
+ char_u *name;
+ int giveErrorIfMissing;
+ int fixed_width;
+{
+ XFontSet fontset;
+ char **missing, *def_str;
+ int num_missing;
+
+ if (!gui.in_use || name == NULL)
+ return NOFONTSET;
+
+ fontset = XCreateFontSet(gui.dpy, (char *)name, &missing, &num_missing,
+ &def_str);
+ if (num_missing > 0)
+ {
+ int i;
+
+ if (giveErrorIfMissing)
+ {
+ EMSG2(_("E250: Fonts for the following charsets are missing in fontset %s:"), name);
+ for (i = 0; i < num_missing; i++)
+ EMSG2("%s", missing[i]);
+ }
+ XFreeStringList(missing);
+ }
+
+ if (fontset == NULL)
+ {
+ if (giveErrorIfMissing)
+ EMSG2(_(e_fontset), name);
+ return NOFONTSET;
+ }
+
+ if (fixed_width && check_fontset_sanity(fontset) == FAIL)
+ {
+ XFreeFontSet(gui.dpy, fontset);
+ return NOFONTSET;
+ }
+ return (GuiFontset)fontset;
+}
+
+/*
+ * Check if fontset "fs" is fixed width.
+ */
+ static int
+check_fontset_sanity(fs)
+ XFontSet fs;
+{
+ XFontStruct **xfs;
+ char **font_name;
+ int fn;
+ char *base_name;
+ int i;
+ int min_width;
+ int min_font_idx = 0;
+
+ base_name = XBaseFontNameListOfFontSet(fs);
+ fn = XFontsOfFontSet(fs, &xfs, &font_name);
+ for (i = 0; i < fn; i++)
+ {
+ if (xfs[i]->max_bounds.width != xfs[i]->min_bounds.width)
+ {
+ EMSG2(_("E252: Fontset name: %s"), base_name);
+ EMSG2(_("Font '%s' is not fixed-width"), font_name[i]);
+ return FAIL;
+ }
+ }
+ /* scan base font width */
+ min_width = 32767;
+ for (i = 0; i < fn; i++)
+ {
+ if (xfs[i]->max_bounds.width<min_width)
+ {
+ min_width = xfs[i]->max_bounds.width;
+ min_font_idx = i;
+ }
+ }
+ for (i = 0; i < fn; i++)
+ {
+ if ( xfs[i]->max_bounds.width != 2 * min_width
+ && xfs[i]->max_bounds.width != min_width)
+ {
+ EMSG2(_("E253: Fontset name: %s\n"), base_name);
+ EMSG2(_("Font0: %s\n"), font_name[min_font_idx]);
+ EMSG2(_("Font1: %s\n"), font_name[i]);
+ EMSGN(_("Font%ld width is not twice that of font0\n"), i);
+ EMSGN(_("Font0 width: %ld\n"), xfs[min_font_idx]->max_bounds.width);
+ EMSGN(_("Font1 width: %ld\n\n"), xfs[i]->max_bounds.width);
+ return FAIL;
+ }
+ }
+ /* it seems ok. Good Luck!! */
+ return OK;
+}
+
+ static int
+fontset_width(fs)
+ XFontSet fs;
+{
+ return XmbTextEscapement(fs, "Vim", 3) / 3;
+}
+
+ int
+fontset_height(fs)
+ XFontSet fs;
+{
+ XFontSetExtents *extents;
+
+ extents = XExtentsOfFontSet(fs);
+ return extents->max_logical_extent.height;
+}
+
+#if (defined(FONTSET_ALWAYS) && defined(FEAT_GUI_ATHENA) \
+ && defined(FEAT_MENU)) || defined(PROTO)
+/*
+ * Returns the bounding box height around the actual glyph image of all
+ * characters in all fonts of the fontset.
+ */
+ int
+fontset_height2(fs)
+ XFontSet fs;
+{
+ XFontSetExtents *extents;
+
+ extents = XExtentsOfFontSet(fs);
+ return extents->max_ink_extent.height;
+}
+#endif
+
+/* NOT USED YET
+ static int
+fontset_descent(fs)
+ XFontSet fs;
+{
+ XFontSetExtents *extents;
+
+ extents = XExtentsOfFontSet (fs);
+ return extents->max_logical_extent.height + extents->max_logical_extent.y;
+}
+*/
+
+ static int
+fontset_ascent(fs)
+ XFontSet fs;
+{
+ XFontSetExtents *extents;
+
+ extents = XExtentsOfFontSet(fs);
+ return -extents->max_logical_extent.y;
+}
+
+#endif /* FEAT_XFONTSET */
+
+/*
+ * Return the Pixel value (color) for the given color name.
+ * Return INVALCOLOR for error.
+ */
+ guicolor_T
+gui_mch_get_color(reqname)
+ char_u *reqname;
+{
+ int i;
+ char_u *name = reqname;
+ Colormap colormap;
+ XColor color;
+ static char *(vimnames[][2]) =
+ {
+ /* A number of colors that some X11 systems don't have */
+ {"LightRed", "#FFBBBB"},
+ {"LightGreen", "#88FF88"},
+ {"LightMagenta","#FFBBFF"},
+ {"DarkCyan", "#008888"},
+ {"DarkBlue", "#0000BB"},
+ {"DarkRed", "#BB0000"},
+ {"DarkMagenta", "#BB00BB"},
+ {"DarkGrey", "#BBBBBB"},
+ {"DarkYellow", "#BBBB00"},
+ {NULL, NULL}
+ };
+
+ /* can't do this when GUI not running */
+ if (!gui.in_use || *reqname == NUL)
+ return INVALCOLOR;
+
+ colormap = DefaultColormap(gui.dpy, XDefaultScreen(gui.dpy));
+
+ /* Do this twice if the name isn't recognized. */
+ while (name != NULL)
+ {
+ i = XParseColor(gui.dpy, colormap, (char *)name, &color);
+
+#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+ if (i == 0)
+ {
+ char *old;
+
+ /* The X11 system is trying to resolve named colors only by names
+ * corresponding to the current locale language. But Vim scripts
+ * usually contain the English color names. Therefore we have to
+ * try a second time here with the native "C" locale set.
+ * Hopefully, restoring the old locale this way works on all
+ * systems...
+ */
+ old = setlocale(LC_ALL, NULL);
+ if (old != NULL && STRCMP(old, "C") != 0)
+ {
+ old = (char *)vim_strsave((char_u *)old);
+ setlocale(LC_ALL, "C");
+ i = XParseColor(gui.dpy, colormap, (char *)name, &color);
+ setlocale(LC_ALL, old);
+ vim_free(old);
+ }
+ }
+#endif
+ if (i != 0 && (XAllocColor(gui.dpy, colormap, &color) != 0
+ || find_closest_color(colormap, &color) == OK))
+ return (guicolor_T)color.pixel;
+
+ /* check for a few builtin names */
+ for (i = 0; ; ++i)
+ {
+ if (vimnames[i][0] == NULL)
+ {
+ name = NULL;
+ break;
+ }
+ if (STRICMP(name, vimnames[i][0]) == 0)
+ {
+ name = (char_u *)vimnames[i][1];
+ break;
+ }
+ }
+ }
+
+ return INVALCOLOR;
+}
+
+/*
+ * Find closest color for "colorPtr" in "colormap". set "colorPtr" to the
+ * resulting color.
+ * Based on a similar function in TCL.
+ * Return FAIL if not able to find or allocate a color.
+ */
+ static int
+find_closest_color(colormap, colorPtr)
+ Colormap colormap;
+ XColor *colorPtr;
+{
+ double tmp, distance, closestDistance;
+ int i, closest, numFound, cmap_size;
+ XColor *colortable;
+ XVisualInfo template, *visInfoPtr;
+
+ template.visualid = XVisualIDFromVisual(DefaultVisual(gui.dpy,
+ XDefaultScreen(gui.dpy)));
+ visInfoPtr = XGetVisualInfo(gui.dpy, (long)VisualIDMask,
+ &template, &numFound);
+ if (numFound < 1)
+ /* FindClosestColor couldn't lookup visual */
+ return FAIL;
+
+ cmap_size = visInfoPtr->colormap_size;
+ XFree((char *)visInfoPtr);
+ colortable = (XColor *)alloc((unsigned)(cmap_size * sizeof(XColor)));
+ if (!colortable)
+ return FAIL; /* out of memory */
+
+ for (i = 0; i < cmap_size; i++)
+ colortable[i].pixel = (unsigned long)i;
+ XQueryColors (gui.dpy, colormap, colortable, cmap_size);
+
+ /*
+ * Find the color that best approximates the desired one, then
+ * try to allocate that color. If that fails, it must mean that
+ * the color was read-write (so we can't use it, since it's owner
+ * might change it) or else it was already freed. Try again,
+ * over and over again, until something succeeds.
+ */
+ closestDistance = 1e30;
+ closest = 0;
+ for (i = 0; i < cmap_size; i++)
+ {
+ /*
+ * Use Euclidean distance in RGB space, weighted by Y (of YIQ)
+ * as the objective function; this accounts for differences
+ * in the color sensitivity of the eye.
+ */
+ tmp = .30 * (((int)colorPtr->red) - (int)colortable[i].red);
+ distance = tmp * tmp;
+ tmp = .61 * (((int)colorPtr->green) - (int)colortable[i].green);
+ distance += tmp * tmp;
+ tmp = .11 * (((int)colorPtr->blue) - (int)colortable[i].blue);
+ distance += tmp * tmp;
+ if (distance < closestDistance)
+ {
+ closest = i;
+ closestDistance = distance;
+ }
+ }
+
+ if (XAllocColor(gui.dpy, colormap, &colortable[closest]) != 0)
+ {
+ gui.color_approx = TRUE;
+ *colorPtr = colortable[closest];
+ }
+
+ free(colortable);
+ return OK;
+}
+
+ void
+gui_mch_set_fg_color(color)
+ guicolor_T color;
+{
+ if (color != prev_fg_color)
+ {
+ XSetForeground(gui.dpy, gui.text_gc, (Pixel)color);
+ prev_fg_color = color;
+ }
+}
+
+/*
+ * Set the current text background color.
+ */
+ void
+gui_mch_set_bg_color(color)
+ guicolor_T color;
+{
+ if (color != prev_bg_color)
+ {
+ XSetBackground(gui.dpy, gui.text_gc, (Pixel)color);
+ prev_bg_color = color;
+ }
+}
+
+/*
+ * create a mouse pointer that is blank
+ */
+ static Cursor
+gui_x11_create_blank_mouse()
+{
+ Pixmap blank_pixmap = XCreatePixmap(gui.dpy, gui.wid, 1, 1, 1);
+ GC gc = XCreateGC(gui.dpy, blank_pixmap, (unsigned long)0, (XGCValues*)0);
+ XDrawPoint(gui.dpy, blank_pixmap, gc, 0, 0);
+ XFreeGC(gui.dpy, gc);
+ return XCreatePixmapCursor(gui.dpy, blank_pixmap, blank_pixmap,
+ (XColor*)&gui.norm_pixel, (XColor*)&gui.norm_pixel, 0, 0);
+}
+
+ void
+gui_mch_draw_string(row, col, s, len, flags)
+ int row;
+ int col;
+ char_u *s;
+ int len;
+ int flags;
+{
+ int cells = len;
+#ifdef FEAT_MBYTE
+ static XChar2b *buf = NULL;
+ static int buflen = 0;
+ char_u *p;
+ int wlen = 0;
+ int c;
+
+ if (enc_utf8)
+ {
+ /* Convert UTF-8 byte sequence to 16 bit characters for the X
+ * functions. Need a buffer for the 16 bit characters. Keep it
+ * between calls, because allocating it each time is slow. */
+ if (buflen < len)
+ {
+ XtFree((char *)buf);
+ buf = (XChar2b *)XtMalloc(len * sizeof(XChar2b));
+ buflen = len;
+ }
+ p = s;
+ cells = 0;
+ while (p < s + len)
+ {
+ c = utf_ptr2char(p);
+ if (c >= 0x10000) /* show chars > 0xffff as ? */
+ c = 0xbf;
+ buf[wlen].byte1 = (unsigned)c >> 8;
+ buf[wlen].byte2 = c;
+ ++wlen;
+ cells += utf_char2cells(c);
+ p += utf_ptr2len_check(p);
+ }
+ }
+ else if (has_mbyte)
+ {
+ cells = 0;
+ for (p = s; p < s + len; )
+ {
+ cells += ptr2cells(p);
+ p += (*mb_ptr2len_check)(p);
+ }
+ }
+
+#endif
+
+#ifdef FEAT_XFONTSET
+ if (current_fontset != NULL)
+ {
+ /* Setup a clip rectangle to avoid spilling over in the next or
+ * previous line. This is apparently needed for some fonts which are
+ * used in a fontset. */
+ XRectangle clip;
+
+ clip.x = 0;
+ clip.y = 0;
+ clip.height = gui.char_height;
+ clip.width = gui.char_width * cells + 1;
+ XSetClipRectangles(gui.dpy, gui.text_gc, FILL_X(col), FILL_Y(row),
+ &clip, 1, Unsorted);
+ }
+#endif
+
+ if (flags & DRAW_TRANSP)
+ {
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ XDrawString16(gui.dpy, gui.wid, gui.text_gc, TEXT_X(col),
+ TEXT_Y(row), buf, wlen);
+ else
+#endif
+ XDrawString(gui.dpy, gui.wid, gui.text_gc, TEXT_X(col),
+ TEXT_Y(row), (char *)s, len);
+ }
+ else if (p_linespace != 0
+#ifdef FEAT_XFONTSET
+ || current_fontset != NULL
+#endif
+ )
+ {
+ XSetForeground(gui.dpy, gui.text_gc, prev_bg_color);
+ XFillRectangle(gui.dpy, gui.wid, gui.text_gc, FILL_X(col),
+ FILL_Y(row), gui.char_width * cells, gui.char_height);
+ XSetForeground(gui.dpy, gui.text_gc, prev_fg_color);
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ XDrawString16(gui.dpy, gui.wid, gui.text_gc, TEXT_X(col),
+ TEXT_Y(row), buf, wlen);
+ else
+#endif
+ XDrawString(gui.dpy, gui.wid, gui.text_gc, TEXT_X(col),
+ TEXT_Y(row), (char *)s, len);
+ }
+ else
+ {
+ /* XmbDrawImageString has bug, don't use it for fontset. */
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ XDrawImageString16(gui.dpy, gui.wid, gui.text_gc, TEXT_X(col),
+ TEXT_Y(row), buf, wlen);
+ else
+#endif
+ XDrawImageString(gui.dpy, gui.wid, gui.text_gc, TEXT_X(col),
+ TEXT_Y(row), (char *)s, len);
+ }
+
+ /* Bold trick: draw the text again with a one-pixel offset. */
+ if (flags & DRAW_BOLD)
+ {
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ XDrawString16(gui.dpy, gui.wid, gui.text_gc, TEXT_X(col) + 1,
+ TEXT_Y(row), buf, wlen);
+ else
+#endif
+ XDrawString(gui.dpy, gui.wid, gui.text_gc, TEXT_X(col) + 1,
+ TEXT_Y(row), (char *)s, len);
+ }
+
+ /* Underline: draw a line at the bottom of the character cell. */
+ if (flags & DRAW_UNDERL)
+ XDrawLine(gui.dpy, gui.wid, gui.text_gc, FILL_X(col),
+ FILL_Y(row + 1) - 1, FILL_X(col + cells) - 1, FILL_Y(row + 1) - 1);
+
+#ifdef FEAT_XFONTSET
+ if (current_fontset != NULL)
+ XSetClipMask(gui.dpy, gui.text_gc, None);
+#endif
+}
+
+/*
+ * Return OK if the key with the termcap name "name" is supported.
+ */
+ int
+gui_mch_haskey(name)
+ char_u *name;
+{
+ int i;
+
+ for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
+ if (name[0] == special_keys[i].vim_code0 &&
+ name[1] == special_keys[i].vim_code1)
+ return OK;
+ return FAIL;
+}
+
+/*
+ * Return the text window-id and display. Only required for X-based GUI's
+ */
+ int
+gui_get_x11_windis(win, dis)
+ Window *win;
+ Display **dis;
+{
+ *win = XtWindow(vimShell);
+ *dis = gui.dpy;
+ return OK;
+}
+
+ void
+gui_mch_beep()
+{
+ XBell(gui.dpy, 0);
+}
+
+ void
+gui_mch_flash(msec)
+ int msec;
+{
+ /* Do a visual beep by reversing the foreground and background colors */
+ XFillRectangle(gui.dpy, gui.wid, gui.invert_gc, 0, 0,
+ FILL_X((int)Columns) + gui.border_offset,
+ FILL_Y((int)Rows) + gui.border_offset);
+ XSync(gui.dpy, False);
+ ui_delay((long)msec, TRUE); /* wait for a few msec */
+ XFillRectangle(gui.dpy, gui.wid, gui.invert_gc, 0, 0,
+ FILL_X((int)Columns) + gui.border_offset,
+ FILL_Y((int)Rows) + gui.border_offset);
+}
+
+/*
+ * Invert a rectangle from row r, column c, for nr rows and nc columns.
+ */
+ void
+gui_mch_invert_rectangle(r, c, nr, nc)
+ int r;
+ int c;
+ int nr;
+ int nc;
+{
+ XFillRectangle(gui.dpy, gui.wid, gui.invert_gc,
+ FILL_X(c), FILL_Y(r), (nc) * gui.char_width, (nr) * gui.char_height);
+}
+
+/*
+ * Iconify the GUI window.
+ */
+ void
+gui_mch_iconify()
+{
+ XIconifyWindow(gui.dpy, XtWindow(vimShell), DefaultScreen(gui.dpy));
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Bring the Vim window to the foreground.
+ */
+ void
+gui_mch_set_foreground()
+{
+ XMapRaised(gui.dpy, XtWindow(vimShell));
+}
+#endif
+
+/*
+ * Draw a cursor without focus.
+ */
+ void
+gui_mch_draw_hollow_cursor(color)
+ guicolor_T color;
+{
+ int w = 1;
+
+#ifdef FEAT_MBYTE
+ if (mb_lefthalve(gui.row, gui.col))
+ w = 2;
+#endif
+ gui_mch_set_fg_color(color);
+ XDrawRectangle(gui.dpy, gui.wid, gui.text_gc, FILL_X(gui.col),
+ FILL_Y(gui.row), w * gui.char_width - 1, gui.char_height - 1);
+}
+
+/*
+ * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using
+ * color "color".
+ */
+ void
+gui_mch_draw_part_cursor(w, h, color)
+ int w;
+ int h;
+ guicolor_T color;
+{
+ gui_mch_set_fg_color(color);
+
+ XFillRectangle(gui.dpy, gui.wid, gui.text_gc,
+#ifdef FEAT_RIGHTLEFT
+ /* vertical line should be on the right of current point */
+ CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
+#endif
+ FILL_X(gui.col),
+ FILL_Y(gui.row) + gui.char_height - h,
+ w, h);
+}
+
+/*
+ * Catch up with any queued X events. This may put keyboard input into the
+ * input buffer, call resize call-backs, trigger timers etc. If there is
+ * nothing in the X event queue (& no timers pending), then we return
+ * immediately.
+ */
+ void
+gui_mch_update()
+{
+ XtInputMask mask, desired;
+
+#ifdef ALT_X_INPUT
+ if (suppress_alternate_input)
+ desired = (XtIMXEvent | XtIMTimer);
+ else
+#endif
+ desired = (XtIMAll);
+ while ((mask = XtAppPending(app_context)) && (mask & desired)
+ && !vim_is_input_buf_full())
+ XtAppProcessEvent(app_context, desired);
+}
+
+/*
+ * GUI input routine called by gui_wait_for_chars(). Waits for a character
+ * from the keyboard.
+ * wtime == -1 Wait forever.
+ * wtime == 0 This should never happen.
+ * wtime > 0 Wait wtime milliseconds for a character.
+ * Returns OK if a character was found to be available within the given time,
+ * or FAIL otherwise.
+ */
+ int
+gui_mch_wait_for_chars(wtime)
+ long wtime;
+{
+ int focus;
+
+ /*
+ * Make this static, in case gui_x11_timer_cb is called after leaving
+ * this function (otherwise a random value on the stack may be changed).
+ */
+ static int timed_out;
+ XtIntervalId timer = (XtIntervalId)0;
+ XtInputMask desired;
+#ifdef FEAT_SNIFF
+ static int sniff_on = 0;
+ static XtInputId sniff_input_id = 0;
+#endif
+
+ timed_out = FALSE;
+
+#ifdef FEAT_SNIFF
+ if (sniff_on && !want_sniff_request)
+ {
+ if (sniff_input_id)
+ XtRemoveInput(sniff_input_id);
+ sniff_on = 0;
+ }
+ else if (!sniff_on && want_sniff_request)
+ {
+ sniff_input_id = XtAppAddInput(app_context, fd_from_sniff,
+ (XtPointer)XtInputReadMask, gui_x11_sniff_request_cb, 0);
+ sniff_on = 1;
+ }
+#endif
+
+ if (wtime > 0)
+ timer = XtAppAddTimeOut(app_context, (long_u)wtime, gui_x11_timer_cb,
+ &timed_out);
+
+ focus = gui.in_focus;
+#ifdef ALT_X_INPUT
+ if (suppress_alternate_input)
+ desired = (XtIMXEvent | XtIMTimer);
+ else
+#endif
+ desired = (XtIMAll);
+ while (!timed_out)
+ {
+ /* Stop or start blinking when focus changes */
+ if (gui.in_focus != focus)
+ {
+ if (gui.in_focus)
+ gui_mch_start_blink();
+ else
+ gui_mch_stop_blink();
+ focus = gui.in_focus;
+ }
+
+ /*
+ * Don't use gui_mch_update() because then we will spin-lock until a
+ * char arrives, instead we use XtAppProcessEvent() to hang until an
+ * event arrives. No need to check for input_buf_full because we are
+ * returning as soon as it contains a single char. Note that
+ * XtAppNextEvent() may not be used because it will not return after a
+ * timer event has arrived -- webb
+ */
+ XtAppProcessEvent(app_context, desired);
+
+ if (input_available())
+ {
+ if (timer != (XtIntervalId)0 && !timed_out)
+ XtRemoveTimeOut(timer);
+ return OK;
+ }
+ }
+ return FAIL;
+}
+
+/*
+ * Output routines.
+ */
+
+/* Flush any output to the screen */
+ void
+gui_mch_flush()
+{
+ XFlush(gui.dpy);
+}
+
+/*
+ * Clear a rectangular region of the screen from text pos (row1, col1) to
+ * (row2, col2) inclusive.
+ */
+ void
+gui_mch_clear_block(row1, col1, row2, col2)
+ int row1;
+ int col1;
+ int row2;
+ int col2;
+{
+ int x;
+
+ x = FILL_X(col1);
+
+ /* Clear one extra pixel at the far right, for when bold characters have
+ * spilled over to the next column. */
+ XFillRectangle(gui.dpy, gui.wid, gui.back_gc, x, FILL_Y(row1),
+ (col2 - col1 + 1) * gui.char_width + (col2 == Columns - 1),
+ (row2 - row1 + 1) * gui.char_height);
+}
+
+ void
+gui_mch_clear_all()
+{
+ XClearArea(gui.dpy, gui.wid, 0, 0, 0, 0, False);
+}
+
+/*
+ * Delete the given number of lines from the given row, scrolling up any
+ * text further down within the scroll region.
+ */
+ void
+gui_mch_delete_lines(row, num_lines)
+ int row;
+ int num_lines;
+{
+ if (gui.visibility == VisibilityFullyObscured)
+ return; /* Can't see the window */
+
+ /* copy one extra pixel at the far right, for when bold has spilled
+ * over */
+ XCopyArea(gui.dpy, gui.wid, gui.wid, gui.text_gc,
+ FILL_X(gui.scroll_region_left), FILL_Y(row + num_lines),
+ gui.char_width * (gui.scroll_region_right - gui.scroll_region_left + 1)
+ + (gui.scroll_region_right == Columns - 1),
+ gui.char_height * (gui.scroll_region_bot - row - num_lines + 1),
+ FILL_X(gui.scroll_region_left), FILL_Y(row));
+
+ gui_clear_block(gui.scroll_region_bot - num_lines + 1,
+ gui.scroll_region_left,
+ gui.scroll_region_bot, gui.scroll_region_right);
+ gui_x11_check_copy_area();
+}
+
+/*
+ * Insert the given number of lines before the given row, scrolling down any
+ * following text within the scroll region.
+ */
+ void
+gui_mch_insert_lines(row, num_lines)
+ int row;
+ int num_lines;
+{
+ if (gui.visibility == VisibilityFullyObscured)
+ return; /* Can't see the window */
+
+ /* copy one extra pixel at the far right, for when bold has spilled
+ * over */
+ XCopyArea(gui.dpy, gui.wid, gui.wid, gui.text_gc,
+ FILL_X(gui.scroll_region_left), FILL_Y(row),
+ gui.char_width * (gui.scroll_region_right - gui.scroll_region_left + 1)
+ + (gui.scroll_region_right == Columns - 1),
+ gui.char_height * (gui.scroll_region_bot - row - num_lines + 1),
+ FILL_X(gui.scroll_region_left), FILL_Y(row + num_lines));
+
+ gui_clear_block(row, gui.scroll_region_left,
+ row + num_lines - 1, gui.scroll_region_right);
+ gui_x11_check_copy_area();
+}
+
+/*
+ * Update the region revealed by scrolling up/down.
+ */
+ static void
+gui_x11_check_copy_area()
+{
+ XEvent event;
+ XGraphicsExposeEvent *gevent;
+
+ if (gui.visibility != VisibilityPartiallyObscured)
+ return;
+
+ XFlush(gui.dpy);
+
+ /* Wait to check whether the scroll worked or not */
+ for (;;)
+ {
+ if (XCheckTypedEvent(gui.dpy, NoExpose, &event))
+ return; /* The scroll worked. */
+
+ if (XCheckTypedEvent(gui.dpy, GraphicsExpose, &event))
+ {
+ gevent = (XGraphicsExposeEvent *)&event;
+ gui_redraw(gevent->x, gevent->y, gevent->width, gevent->height);
+ if (gevent->count == 0)
+ return; /* This was the last expose event */
+ }
+ XSync(gui.dpy, False);
+ }
+}
+
+/*
+ * X Selection stuff, for cutting and pasting text to other windows.
+ */
+
+ void
+clip_mch_lose_selection(cbd)
+ VimClipboard *cbd;
+{
+ clip_x11_lose_selection(vimShell, cbd);
+}
+
+ int
+clip_mch_own_selection(cbd)
+ VimClipboard *cbd;
+{
+ return clip_x11_own_selection(vimShell, cbd);
+}
+
+ void
+clip_mch_request_selection(cbd)
+ VimClipboard *cbd;
+{
+ clip_x11_request_selection(vimShell, gui.dpy, cbd);
+}
+
+ void
+clip_mch_set_selection(cbd)
+ VimClipboard *cbd;
+{
+ clip_x11_set_selection(cbd);
+}
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Menu stuff.
+ */
+
+/*
+ * Make a menu either grey or not grey.
+ */
+ void
+gui_mch_menu_grey(menu, grey)
+ vimmenu_T *menu;
+ int grey;
+{
+ if (menu->id != (Widget)0)
+ {
+ gui_mch_menu_hidden(menu, False);
+ if (grey
+#ifdef FEAT_GUI_MOTIF
+ || !menu->sensitive
+#endif
+ )
+ XtSetSensitive(menu->id, False);
+ else
+ XtSetSensitive(menu->id, True);
+ }
+}
+
+/*
+ * Make menu item hidden or not hidden
+ */
+ void
+gui_mch_menu_hidden(menu, hidden)
+ vimmenu_T *menu;
+ int hidden;
+{
+ if (menu->id != (Widget)0)
+ {
+ if (hidden)
+ XtUnmanageChild(menu->id);
+ else
+ XtManageChild(menu->id);
+ }
+}
+
+/*
+ * This is called after setting all the menus to grey/hidden or not.
+ */
+ void
+gui_mch_draw_menubar()
+{
+ /* Nothing to do in X */
+}
+
+/* ARGSUSED */
+ void
+gui_x11_menu_cb(w, client_data, call_data)
+ Widget w;
+ XtPointer client_data, call_data;
+{
+ gui_menu_cb((vimmenu_T *)client_data);
+}
+
+#endif /* FEAT_MENU */
+
+
+
+/*
+ * Function called when window closed. Works like ":qa".
+ * Should put up a requester!
+ */
+/*ARGSUSED*/
+ static void
+gui_x11_wm_protocol_handler(w, client_data, event, dum)
+ Widget w;
+ XtPointer client_data;
+ XEvent *event;
+ Boolean *dum;
+{
+ /*
+ * Only deal with Client messages.
+ */
+ if (event->type != ClientMessage)
+ return;
+
+ /*
+ * The WM_SAVE_YOURSELF event arrives when the window manager wants to
+ * exit. That can be cancelled though, thus Vim shouldn't exit here.
+ * Just sync our swap files.
+ */
+ if (((XClientMessageEvent *)event)->data.l[0] ==
+ wm_atoms[SAVE_YOURSELF_IDX])
+ {
+ out_flush();
+ ml_sync_all(FALSE, FALSE); /* preserve all swap files */
+
+ /* Set the window's WM_COMMAND property, to let the window manager
+ * know we are done saving ourselves. We don't want to be restarted,
+ * thus set argv to NULL. */
+ XSetCommand(gui.dpy, XtWindow(vimShell), NULL, 0);
+ return;
+ }
+
+ if (((XClientMessageEvent *)event)->data.l[0] !=
+ wm_atoms[DELETE_WINDOW_IDX])
+ return;
+
+ gui_shell_closed();
+}
+
+#ifdef FEAT_CLIENTSERVER
+/*
+ * Function called when property changed. Check for incoming commands
+ */
+/*ARGSUSED*/
+ static void
+gui_x11_send_event_handler(w, client_data, event, dum)
+ Widget w;
+ XtPointer client_data;
+ XEvent *event;
+ Boolean *dum;
+{
+ XPropertyEvent *e = (XPropertyEvent *) event;
+
+ if (e->type == PropertyNotify && e->window == commWindow
+ && e->atom == commProperty && e->state == PropertyNewValue)
+ {
+ serverEventProc(gui.dpy, event);
+ }
+}
+#endif
+
+/*
+ * Cursor blink functions.
+ *
+ * This is a simple state machine:
+ * BLINK_NONE not blinking at all
+ * BLINK_OFF blinking, cursor is not shown
+ * BLINK_ON blinking, cursor is shown
+ */
+
+#define BLINK_NONE 0
+#define BLINK_OFF 1
+#define BLINK_ON 2
+
+static int blink_state = BLINK_NONE;
+static long_u blink_waittime = 700;
+static long_u blink_ontime = 400;
+static long_u blink_offtime = 250;
+static XtIntervalId blink_timer = (XtIntervalId)0;
+
+ void
+gui_mch_set_blinking(waittime, on, off)
+ long waittime, on, off;
+{
+ blink_waittime = waittime;
+ blink_ontime = on;
+ blink_offtime = off;
+}
+
+/*
+ * Stop the cursor blinking. Show the cursor if it wasn't shown.
+ */
+ void
+gui_mch_stop_blink()
+{
+ if (blink_timer != (XtIntervalId)0)
+ {
+ XtRemoveTimeOut(blink_timer);
+ blink_timer = (XtIntervalId)0;
+ }
+ if (blink_state == BLINK_OFF)
+ gui_update_cursor(TRUE, FALSE);
+ blink_state = BLINK_NONE;
+}
+
+/*
+ * Start the cursor blinking. If it was already blinking, this restarts the
+ * waiting time and shows the cursor.
+ */
+ void
+gui_mch_start_blink()
+{
+ if (blink_timer != (XtIntervalId)0)
+ XtRemoveTimeOut(blink_timer);
+ /* Only switch blinking on if none of the times is zero */
+ if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
+ {
+ blink_timer = XtAppAddTimeOut(app_context, blink_waittime,
+ gui_x11_blink_cb, NULL);
+ blink_state = BLINK_ON;
+ gui_update_cursor(TRUE, FALSE);
+ }
+}
+
+/* ARGSUSED */
+ static void
+gui_x11_blink_cb(timed_out, interval_id)
+ XtPointer timed_out;
+ XtIntervalId *interval_id;
+{
+ if (blink_state == BLINK_ON)
+ {
+ gui_undraw_cursor();
+ blink_state = BLINK_OFF;
+ blink_timer = XtAppAddTimeOut(app_context, blink_offtime,
+ gui_x11_blink_cb, NULL);
+ }
+ else
+ {
+ gui_update_cursor(TRUE, FALSE);
+ blink_state = BLINK_ON;
+ blink_timer = XtAppAddTimeOut(app_context, blink_ontime,
+ gui_x11_blink_cb, NULL);
+ }
+}
+
+/*
+ * Return the RGB value of a pixel as a long.
+ */
+ long_u
+gui_mch_get_rgb(pixel)
+ guicolor_T pixel;
+{
+ XColor xc;
+ Colormap colormap;
+
+ colormap = DefaultColormap(gui.dpy, XDefaultScreen(gui.dpy));
+ xc.pixel = pixel;
+ XQueryColor(gui.dpy, colormap, &xc);
+
+ return ((xc.red & 0xff00) << 8) + (xc.green & 0xff00)
+ + ((unsigned)xc.blue >> 8);
+}
+
+/*
+ * Add the callback functions.
+ */
+ void
+gui_x11_callbacks(textArea, vimForm)
+ Widget textArea;
+ Widget vimForm;
+{
+ XtAddEventHandler(textArea, VisibilityChangeMask, FALSE,
+ gui_x11_visibility_cb, (XtPointer)0);
+
+ XtAddEventHandler(textArea, ExposureMask, FALSE, gui_x11_expose_cb,
+ (XtPointer)0);
+
+ XtAddEventHandler(vimShell, StructureNotifyMask, FALSE,
+ gui_x11_resize_window_cb, (XtPointer)0);
+
+ XtAddEventHandler(vimShell, FocusChangeMask, FALSE, gui_x11_focus_change_cb,
+ (XtPointer)0);
+ /*
+ * Only install these enter/leave callbacks when 'p' in 'guioptions'.
+ * Only needed for some window managers.
+ */
+ if (vim_strchr(p_go, GO_POINTER) != NULL)
+ {
+ XtAddEventHandler(vimShell, LeaveWindowMask, FALSE, gui_x11_leave_cb,
+ (XtPointer)0);
+ XtAddEventHandler(textArea, LeaveWindowMask, FALSE, gui_x11_leave_cb,
+ (XtPointer)0);
+ XtAddEventHandler(textArea, EnterWindowMask, FALSE, gui_x11_enter_cb,
+ (XtPointer)0);
+ XtAddEventHandler(vimShell, EnterWindowMask, FALSE, gui_x11_enter_cb,
+ (XtPointer)0);
+ }
+
+ XtAddEventHandler(vimForm, KeyPressMask, FALSE, gui_x11_key_hit_cb,
+ (XtPointer)0);
+ XtAddEventHandler(textArea, KeyPressMask, FALSE, gui_x11_key_hit_cb,
+ (XtPointer)0);
+
+ /* get pointer moved events from scrollbar, needed for 'mousefocus' */
+ XtAddEventHandler(vimForm, PointerMotionMask,
+ FALSE, gui_x11_mouse_cb, (XtPointer)1);
+ XtAddEventHandler(textArea, ButtonPressMask | ButtonReleaseMask |
+ ButtonMotionMask | PointerMotionMask,
+ FALSE, gui_x11_mouse_cb, (XtPointer)0);
+}
+
+/*
+ * Get current y mouse coordinate in text window.
+ * Return -1 when unknown.
+ */
+ int
+gui_mch_get_mouse_x()
+{
+ int rootx, rooty, winx, winy;
+ Window root, child;
+ unsigned int mask;
+
+ if (gui.wid && XQueryPointer(gui.dpy, gui.wid, &root, &child,
+ &rootx, &rooty, &winx, &winy, &mask))
+ return winx;
+ return -1;
+}
+
+ int
+gui_mch_get_mouse_y()
+{
+ int rootx, rooty, winx, winy;
+ Window root, child;
+ unsigned int mask;
+
+ if (gui.wid && XQueryPointer(gui.dpy, gui.wid, &root, &child,
+ &rootx, &rooty, &winx, &winy, &mask))
+ return winy;
+ return -1;
+}
+
+ void
+gui_mch_setmouse(x, y)
+ int x;
+ int y;
+{
+ if (gui.wid)
+ XWarpPointer(gui.dpy, (Window)0, gui.wid, 0, 0, 0, 0, x, y);
+}
+
+#if (defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU)) || defined(PROTO)
+ XButtonPressedEvent *
+gui_x11_get_last_mouse_event()
+{
+ return &last_mouse_event;
+}
+#endif
+
+#if defined(FEAT_SIGN_ICONS) || defined(PROTO)
+
+/* Signs are currently always 2 chars wide. Hopefully the font is big enough
+ * to provide room for the bitmap! */
+# define SIGN_WIDTH (gui.char_width * 2)
+
+#if 0 /* not used */
+ void
+gui_mch_clearsign(row)
+ int row;
+{
+ if (gui.in_use)
+ XClearArea(gui.dpy, gui.wid, 0, TEXT_Y(row) - gui.char_height,
+ SIGN_WIDTH, gui.char_height, FALSE);
+}
+#endif
+
+ void
+gui_mch_drawsign(row, col, typenr)
+ int row;
+ int col;
+ int typenr;
+{
+ XImage *sign;
+
+ if (gui.in_use && (sign = (XImage *)sign_get_image(typenr)) != NULL)
+ {
+ XClearArea(gui.dpy, gui.wid, TEXT_X(col), TEXT_Y(row) - sign->height,
+ SIGN_WIDTH, gui.char_height, FALSE);
+ XPutImage(gui.dpy, gui.wid, gui.text_gc, sign, 0, 0,
+ TEXT_X(col) + (SIGN_WIDTH - sign->width) / 2,
+ TEXT_Y(row) - sign->height,
+ sign->width, sign->height);
+ }
+}
+
+ void *
+gui_mch_register_sign(signfile)
+ char_u *signfile;
+{
+ XpmAttributes attrs;
+ XImage *sign;
+ int status;
+
+ /*
+ * Setup the color substitution table.
+ */
+ sign = NULL;
+ if (signfile[0] != NUL && signfile[0] != '-')
+ {
+ sign = (XImage *)alloc(sizeof(XImage));
+ if (sign != NULL)
+ {
+ XpmColorSymbol color[5] =
+ {
+ {"none", NULL, 0},
+ {"iconColor1", NULL, 0},
+ {"bottomShadowColor", NULL, 0},
+ {"topShadowColor", NULL, 0},
+ {"selectColor", NULL, 0}
+ };
+ attrs.valuemask = XpmColorSymbols;
+ attrs.numsymbols = 2;
+ attrs.colorsymbols = color;
+ attrs.colorsymbols[0].pixel = gui.back_pixel;
+ attrs.colorsymbols[1].pixel = gui.norm_pixel;
+ status = XpmReadFileToImage(gui.dpy, (char *)signfile,
+ &sign, NULL, &attrs);
+
+ if (status == 0)
+ {
+ /* Sign width is fixed at two columns now.
+ if (sign->width > gui.sign_width)
+ gui.sign_width = sign->width + 8; */
+ }
+ else
+ {
+ vim_free(sign);
+ sign = NULL;
+ EMSG(_(e_signdata));
+ }
+ }
+ }
+
+ return (void *)sign;
+}
+
+ void
+gui_mch_destroy_sign(sign)
+ void *sign;
+{
+ XFree(((XImage *)sign)->data);
+ vim_free(sign);
+}
+#endif
+
+
+#ifdef FEAT_MOUSESHAPE
+/* The last set mouse pointer shape is remembered, to be used when it goes
+ * from hidden to not hidden. */
+static int last_shape = 0;
+#endif
+
+/*
+ * Use the blank mouse pointer or not.
+ */
+ void
+gui_mch_mousehide(hide)
+ int hide; /* TRUE = use blank ptr, FALSE = use parent ptr */
+{
+ if (gui.pointer_hidden != hide)
+ {
+ gui.pointer_hidden = hide;
+ if (hide)
+ XDefineCursor(gui.dpy, gui.wid, gui.blank_pointer);
+ else
+#ifdef FEAT_MOUSESHAPE
+ mch_set_mouse_shape(last_shape);
+#else
+ XUndefineCursor(gui.dpy, gui.wid);
+#endif
+ }
+}
+
+#if defined(FEAT_MOUSESHAPE) || defined(PROTO)
+
+/* Table for shape IDs. Keep in sync with the mshape_names[] table in
+ * misc2.c! */
+static int mshape_ids[] =
+{
+ XC_left_ptr, /* arrow */
+ 0, /* blank */
+ XC_xterm, /* beam */
+ XC_sb_v_double_arrow, /* updown */
+ XC_sizing, /* udsizing */
+ XC_sb_h_double_arrow, /* leftright */
+ XC_sizing, /* lrsizing */
+ XC_watch, /* busy */
+ XC_X_cursor, /* no */
+ XC_crosshair, /* crosshair */
+ XC_hand1, /* hand1 */
+ XC_hand2, /* hand2 */
+ XC_pencil, /* pencil */
+ XC_question_arrow, /* question */
+ XC_right_ptr, /* right-arrow */
+ XC_center_ptr, /* up-arrow */
+ XC_left_ptr /* last one */
+};
+
+ void
+mch_set_mouse_shape(shape)
+ int shape;
+{
+ int id;
+
+ if (!gui.in_use)
+ return;
+
+ if (shape == MSHAPE_HIDE || gui.pointer_hidden)
+ XDefineCursor(gui.dpy, gui.wid, gui.blank_pointer);
+ else
+ {
+ if (shape >= MSHAPE_NUMBERED)
+ {
+ id = shape - MSHAPE_NUMBERED;
+ if (id >= XC_num_glyphs)
+ id = XC_left_ptr;
+ else
+ id &= ~1; /* they are always even (why?) */
+ }
+ else
+ id = mshape_ids[shape];
+
+ XDefineCursor(gui.dpy, gui.wid, XCreateFontCursor(gui.dpy, id));
+ }
+ if (shape != MSHAPE_HIDE)
+ last_shape = shape;
+}
+#endif
+
+#if defined(FEAT_TOOLBAR) || defined(PROTO)
+/*
+ * Icons used by the toolbar code.
+ */
+#include "../pixmaps/tb_new.xpm"
+#include "../pixmaps/tb_open.xpm"
+#include "../pixmaps/tb_close.xpm"
+#include "../pixmaps/tb_save.xpm"
+#include "../pixmaps/tb_print.xpm"
+#include "../pixmaps/tb_cut.xpm"
+#include "../pixmaps/tb_copy.xpm"
+#include "../pixmaps/tb_paste.xpm"
+#include "../pixmaps/tb_find.xpm"
+#include "../pixmaps/tb_find_next.xpm"
+#include "../pixmaps/tb_find_prev.xpm"
+#include "../pixmaps/tb_find_help.xpm"
+#include "../pixmaps/tb_exit.xpm"
+#include "../pixmaps/tb_undo.xpm"
+#include "../pixmaps/tb_redo.xpm"
+#include "../pixmaps/tb_help.xpm"
+#include "../pixmaps/tb_macro.xpm"
+#include "../pixmaps/tb_make.xpm"
+#include "../pixmaps/tb_save_all.xpm"
+#include "../pixmaps/tb_jump.xpm"
+#include "../pixmaps/tb_ctags.xpm"
+#include "../pixmaps/tb_load_session.xpm"
+#include "../pixmaps/tb_save_session.xpm"
+#include "../pixmaps/tb_new_session.xpm"
+#include "../pixmaps/tb_blank.xpm"
+#include "../pixmaps/tb_maximize.xpm"
+#include "../pixmaps/tb_split.xpm"
+#include "../pixmaps/tb_minimize.xpm"
+#include "../pixmaps/tb_shell.xpm"
+#include "../pixmaps/tb_replace.xpm"
+#include "../pixmaps/tb_vsplit.xpm"
+#include "../pixmaps/tb_maxwidth.xpm"
+#include "../pixmaps/tb_minwidth.xpm"
+
+/*
+ * Those are the pixmaps used for the default buttons.
+ */
+static char **(built_in_pixmaps[]) =
+{
+ tb_new_xpm,
+ tb_open_xpm,
+ tb_save_xpm,
+ tb_undo_xpm,
+ tb_redo_xpm,
+ tb_cut_xpm,
+ tb_copy_xpm,
+ tb_paste_xpm,
+ tb_print_xpm,
+ tb_help_xpm,
+ tb_find_xpm,
+ tb_save_all_xpm,
+ tb_save_session_xpm,
+ tb_new_session_xpm,
+ tb_load_session_xpm,
+ tb_macro_xpm,
+ tb_replace_xpm,
+ tb_close_xpm,
+ tb_maximize_xpm,
+ tb_minimize_xpm,
+ tb_split_xpm,
+ tb_shell_xpm,
+ tb_find_prev_xpm,
+ tb_find_next_xpm,
+ tb_find_help_xpm,
+ tb_make_xpm,
+ tb_jump_xpm,
+ tb_ctags_xpm,
+ tb_vsplit_xpm,
+ tb_maxwidth_xpm,
+ tb_minwidth_xpm,
+ tb_exit_xpm
+};
+
+static void createXpmImages __ARGS((char_u *path, char **xpm, Pixmap *sen, Pixmap *insen));
+
+/*
+ * Allocated a pixmap for toolbar menu "menu".
+ * Return in "sen" and "insen". "insen" can be NULL.
+ */
+ void
+get_toolbar_pixmap(menu, sen, insen)
+ vimmenu_T *menu;
+ Pixmap *sen;
+ Pixmap *insen;
+{
+ char_u buf[MAXPATHL]; /* buffer storing expanded pathname */
+ char **xpm = NULL; /* xpm array */
+
+ buf[0] = NUL; /* start with NULL path */
+
+ if (menu->iconfile != NULL)
+ {
+ /* Use the "icon=" argument. */
+ gui_find_iconfile(menu->iconfile, buf, "xpm");
+ createXpmImages(buf, NULL, sen, insen);
+
+ /* If it failed, try using the menu name. */
+ if (*sen == (Pixmap)0 && gui_find_bitmap(menu->name, buf, "xpm") == OK)
+ createXpmImages(buf, NULL, sen, insen);
+ if (*sen != (Pixmap)0)
+ return;
+ }
+
+ if (menu->icon_builtin || gui_find_bitmap(menu->name, buf, "xpm") == FAIL)
+ {
+ if (menu->iconidx >= 0 && menu->iconidx
+ < (sizeof(built_in_pixmaps) / sizeof(built_in_pixmaps[0])))
+ xpm = built_in_pixmaps[menu->iconidx];
+ else
+ xpm = tb_blank_xpm;
+ }
+
+ if (xpm != NULL || buf[0] != NUL)
+ createXpmImages(buf, xpm, sen, insen);
+}
+
+/* Indices for named colors */
+#define BACKGROUND 0
+#define FOREGROUND 1
+#define BOTTOM_SHADOW 2
+#define TOP_SHADOW 3
+#define HIGHLIGHT 4
+
+/*
+ * Read an Xpm file, doing color substitutions for the foreground and
+ * background colors. If there is an error reading a color xpm file,
+ * drop back and read the monochrome file. If successful, create the
+ * insensitive Pixmap too.
+ */
+ static void
+createXpmImages(path, xpm, sen, insen)
+ char_u *path;
+ char **xpm;
+ Pixmap *sen;
+ Pixmap *insen; /* can be NULL */
+{
+ Window rootWindow;
+ XpmAttributes attrs;
+ XpmColorSymbol color[5] =
+ {
+ {"none", "none", 0},
+ {"iconColor1", NULL, 0},
+ {"bottomShadowColor", NULL, 0},
+ {"topShadowColor", NULL, 0},
+ {"selectColor", NULL, 0}
+ };
+ int screenNum;
+ int status;
+ Pixmap mask;
+ Pixmap map;
+
+ gui_mch_get_toolbar_colors(
+ &color[BACKGROUND].pixel,
+ &color[FOREGROUND].pixel,
+ &color[BOTTOM_SHADOW].pixel,
+ &color[TOP_SHADOW].pixel,
+ &color[HIGHLIGHT].pixel);
+
+ /* Setup the color subsititution table */
+ attrs.valuemask = XpmColorSymbols;
+ attrs.colorsymbols = color;
+ attrs.numsymbols = 5;
+
+ screenNum = DefaultScreen(gui.dpy);
+ rootWindow = RootWindow(gui.dpy, screenNum);
+
+ /* Create the "sensitive" pixmap */
+ if (xpm != NULL)
+ status = XpmCreatePixmapFromData(gui.dpy, rootWindow, xpm,
+ &map, &mask, &attrs);
+ else
+ status = XpmReadFileToPixmap(gui.dpy, rootWindow, (char *)path,
+ &map, &mask, &attrs);
+ if (status == XpmSuccess && map != 0)
+ {
+ XGCValues gcvalues;
+ GC back_gc;
+ GC mask_gc;
+
+ /* Need to create new Pixmaps with the mask applied. */
+ gcvalues.foreground = color[BACKGROUND].pixel;
+ back_gc = XCreateGC(gui.dpy, map, GCForeground, &gcvalues);
+ mask_gc = XCreateGC(gui.dpy, map, GCForeground, &gcvalues);
+ XSetClipMask(gui.dpy, mask_gc, mask);
+
+ /* Create the "sensitive" pixmap. */
+ *sen = XCreatePixmap(gui.dpy, rootWindow,
+ attrs.width, attrs.height,
+ DefaultDepth(gui.dpy, screenNum));
+ XFillRectangle(gui.dpy, *sen, back_gc, 0, 0,
+ attrs.width, attrs.height);
+ XCopyArea(gui.dpy, map, *sen, mask_gc, 0, 0,
+ attrs.width, attrs.height, 0, 0);
+
+#ifdef FEAT_GUI_MOTIF /* not used for Athena */
+ if (insen != NULL)
+ {
+ int x, y;
+ int startX;
+
+ /* Create the "insensitive" pixmap. It's a copy of the "sensitive"
+ * pixmap with half the pixels set to the background color. */
+ *insen = XCreatePixmap(gui.dpy, rootWindow,
+ attrs.width, attrs.height,
+ DefaultDepth(gui.dpy, screenNum));
+ XCopyArea(gui.dpy, *sen, *insen, back_gc, 0, 0,
+ attrs.width, attrs.height, 0, 0);
+ for (y = 0; y < attrs.height; y++)
+ {
+ if (y % 2 == 0)
+ startX = 0;
+ else
+ startX = 1;
+ for (x = startX; x < attrs.width; x += 2)
+ XDrawPoint(gui.dpy, *insen, back_gc, x, y);
+ }
+
+ }
+#endif
+ XFreeGC(gui.dpy, back_gc);
+ XFreeGC(gui.dpy, mask_gc);
+ XFreePixmap(gui.dpy, map);
+ }
+ else
+ {
+ *sen = 0;
+ if (insen != NULL)
+ *insen = 0;
+ }
+
+ XpmFreeAttributes(&attrs);
+}
+#endif
+
+#if (defined(FEAT_TOOLBAR) && defined(FEAT_BEVAL)) || defined(PROTO)
+/*
+ * Set the balloon-eval used for the tooltip of a toolbar menu item.
+ * The check for a non-toolbar item was added, because there is a crash when
+ * passing a normal menu item here. Can't explain that, but better avoid it.
+ */
+ void
+gui_mch_menu_set_tip(menu)
+ vimmenu_T *menu;
+{
+ if (menu->id != NULL && menu->parent != NULL
+ && menu_is_toolbar(menu->parent->name))
+ {
+ /* Always destroy and create the balloon, in case the string was
+ * changed. */
+ if (menu->tip != NULL)
+ {
+ gui_mch_destroy_beval_area(menu->tip);
+ menu->tip = NULL;
+ }
+ if (menu->strings[MENU_INDEX_TIP] != NULL)
+ menu->tip = gui_mch_create_beval_area(
+ menu->id,
+ menu->strings[MENU_INDEX_TIP],
+ NULL,
+ NULL);
+ }
+}
+#endif
diff --git a/src/guiw16rc.h b/src/guiw16rc.h
new file mode 100644
index 000000000..1e55200bd
--- /dev/null
+++ b/src/guiw16rc.h
@@ -0,0 +1,17 @@
+
+#define IDR_VIM 150
+
+#define IDR_VIM_ERROR 151
+#define IDR_VIM_ALERT 152
+#define IDR_VIM_INFO 153
+#define IDR_VIM_QUESTION 154
+
+#define IDR_ICOBUDDYBASE 200
+
+#define IDR_ICOBUDDY_DEF1 (IDR_ICOBUDDYBASE + 3)
+#define IDR_ICOBUDDY_DEF2 (IDR_ICOBUDDYBASE + 0)
+#define IDR_ICOBUDDY_DEF3 (IDR_ICOBUDDYBASE + 1)
+#define IDR_ICOBUDDY_DEF4 (IDR_ICOBUDDYBASE + 2)
+
+#define IDR_ICOBUDDY_GRIN (IDR_ICOBUDDYBASE + 4)
+#define IDR_ICOBUDDY_ALARM (IDR_ICOBUDDYBASE + 5)
diff --git a/src/gvim.exe.mnf b/src/gvim.exe.mnf
new file mode 100644
index 000000000..70358c1e2
--- /dev/null
+++ b/src/gvim.exe.mnf
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <assemblyIdentity
+ processorArchitecture="X86"
+ version="6.2.0.0"
+ type="win32"
+ name="Vim"
+ />
+ <description>Vi Improved - A Text Editor</description>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0"
+ publicKeyToken="6595b64144ccf1df"
+ language="*"
+ processorArchitecture="X86"
+ />
+ </dependentAssembly>
+ </dependency>
+</assembly>
diff --git a/src/hangulin.c b/src/hangulin.c
new file mode 100644
index 000000000..4ae16a18e
--- /dev/null
+++ b/src/hangulin.c
@@ -0,0 +1,1621 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+
+#ifndef HANGUL_DEFAULT_KEYBOARD
+# define HANGUL_DEFAULT_KEYBOARD 3
+#endif
+
+#define AUTOMATA_NEW 0
+#define AUTOMATA_CORRECT 1
+#define AUTOMATA_SPECIAL 2
+#define AUTOMATA_CORRECT_NEW 3
+#define AUTOMATA_ERROR 4
+#define AUTOMATA_NULL 5
+
+#define F_F 0x1 /* Ãʼº (initial sound) */
+#define F_M 0x2 /* Áß¼º (medial vowel) */
+#define F_L 0x4 /* Á¾¼º (final consonant) */
+#define F_A 0x8 /* ASCII */
+#define F_NULL 1
+#define M_NULL 2
+#define L_NULL 1
+
+static int hangul_input_state = 0;
+static int f=F_NULL, m=M_NULL, l=L_NULL;
+static int sp=0;
+static char_u stack[20] = {0};
+static int last_l = -1, last_ll = -1;
+static int hangul_keyboard_type = HANGUL_DEFAULT_KEYBOARD;
+
+static void convert_ks_to_3 __ARGS((const char_u *src, int *fp, int *mp, int *lp));
+static int convert_3_to_ks __ARGS((int fv, int mv, int lv, char_u *des));
+static int hangul_automata2 __ARGS((char_u *buf, unsigned int *c));
+static int hangul_automata3 __ARGS((char_u *buf, unsigned int *c));
+
+#define push(x) {stack[ sp++ ] = *(x); stack[sp++] = *((x)+1);}
+#define pop(x) {*((x) + 1) = stack[--sp]; *(x) = stack[--sp];}
+#define query(x) {*((x) + 1) = stack[sp - 1]; *(x) = stack[sp - 2];}
+
+#define convert_3_to_code convert_3_to_ks
+
+
+/**********************************************************************/
+/****** 3 ¹ú½ÄÀÚÆÇÀ» À§ÇÑ ·çƾ (Routines for 3 bulsik keyboard) ******/
+/**********************************************************************/
+
+/* 3 ¹ú½Ä¿¡¼­ ÀÚÆÇ º¯È¯ (3 bulsik keyboard conversion) */
+
+static char_u value_table_for_3[] =
+{
+ 24 , '"' , '#' , '$' , '%' , '&' , /* ! " # $ % & */
+ 18 , '(' , ')' , '*' , '+' , ',' , /* ' ( ) * + , */
+ '-' , '.' , 13 , 17 , 29 , 22 , /* - . / 0 1 2 */
+ 19 , 19 , 26 , 5 , 12 , 28 , /* 3 4 5 6 7 8 */
+ 20 , ':' , 9 , '2' , '=' , '3' , /* 9 : ; < = > */
+ '?' , '@' , 8 , '!' , 11 , 10 , /* ? @ A B C D */
+ 26 , 3 , '/' , 39 , '8' , '4' , /* E F G H I J */
+ '5' , '6' , '1' , '0' , '9' , '>' , /* K L M N O P */
+ 28 , 6 , 7 , ';' , '7' , 16 , /* Q R S T U V */
+ 27 , 20 , '<' , 25 , '[' , 92 , /* W X Y Z [ \ */
+ ']' , '^' , '_' , '`' , 23 , 20 , /* ] ^ _ ` a b */
+ 10 , 29 , 11 , 3 , 27 , 4 , /* c d e f g h */
+ 8 , 13 , 2 , 14 , 20 , 11 , /* i j k l m n */
+ 16 , 19 , 21 , 4 , 5 , 7 , /* o p q r s t */
+ 5 , 13 , 9 , 2 , 7 , 17 , /* u v w x y z */
+};
+
+static short_u kind_table_for_3[] =
+{
+ F_L, F_A, F_A, F_A, F_A, F_A, /* ! " # $ % & */
+ F_F, F_A, F_A, F_A, F_A, F_A, /* ' ( ) * + , */
+ F_A, F_A, F_M, F_F, F_L, F_L, /* - . / 0 1 2 */
+ F_L, F_M, F_M, F_M, F_M, F_M, /* 3 4 5 6 7 8 */
+ F_M, F_A, F_F, F_A, F_A, F_A, /* 9 : ; < = > */
+ F_A, F_A, F_L, F_A, F_L, F_L, /* ? @ A B C D */
+ F_L, F_L, F_A, F_A, F_A, F_A, /* E F G H I J */
+ F_A, F_A, F_A, F_A, F_A, F_A, /* K L M N O P */
+ F_L, F_M, F_L, F_A, F_A, F_L, /* Q R S T U V */
+ F_L, F_L, F_A, F_L, F_A, F_A, /* W X Y Z [ \ */
+ F_A, F_A, F_A, F_A, F_L, F_M, /* ] ^ _ ` a b */
+ F_M, F_M, F_M, F_M, F_M, F_F, /* c d e f g h */
+ F_F, F_F, F_F, F_F, F_F, F_F, /* i j k l m n */
+ F_F, F_F, F_L, F_M, F_L, F_M, /* o p q r s t */
+ F_F, F_M, F_L, F_L, F_F, F_L, /* u v w x y z */
+};
+
+/* 3 ¹ú½Ä¿¡¼­ (ÇöÀçÃʼº, ÀԷ¿µ¹®) -> º¹ÇÕÃʼº ó¸®
+ * 3 bulsik: (current initial sound, input english) -> compound initial sound.
+ */
+
+ static int
+comfcon3(v, c)
+ int v;
+ int c;
+{
+ if (v == 2 && c == 2)
+ return 3;
+ if (v == 5 && c == 5)
+ return 6;
+ if (v == 9 && c == 9)
+ return 10;
+ if (v == 11 && c == 11)
+ return 12;
+ if (v == 14 && c == 14)
+ return 15;
+ return 0;
+}
+
+/* 3 ¹ú½Ä¿¡¼­ (ÇöÀç¸ðÀ½, ÀÔ·Â ¿µ¹®) -> º¹ÇÕ ¸ðÀ½ ó¸®
+ * 3 bulsik: (current vowel, input english) -> compound vowel.
+ */
+
+ static int
+comvow3(v, c)
+ int v;
+ int c;
+{
+ switch (v)
+ {
+ case 13: /* ¤Ç */
+ switch (c) {
+ case 3: /* ¤Ç¤¿ */
+ return 14;
+ case 4: /* ¤Ç¤À */
+ return 15;
+ case 29: /* ¤Ç¤Ó */
+ return 18;
+ }
+ break;
+
+ case 20: /* ¤Ì */
+ switch (c) {
+ case 7: /* ¤Ì¤Ã */
+ return 21;
+ case 10: /* ¤Ì¤Ä */
+ return 22;
+ case 29: /* ¤Ì¤Ó */
+ return 23;
+ }
+ break;
+
+ /* 3 ¹ú½Ä ÀÚÆÇÀº ¤Ñ¤Ó °¡ ÀÖÀ¸¹Ç·Î ... */
+ }
+ return 0;
+}
+
+/* 3 ¹ú½Ä¿¡¼­ (ÇöÀç ¹Þħ, ¿µ¹®ÀÚ ÀÔ·Â) -> ¹Þħ
+ * 3 bulsik: (current prop(?), input english) -> prop(?).
+ * I want to say, the 'prop' is similar to 'final consonant', but not vowel.
+ * (I cannot find the real english from my dictionary. Sorry!)
+ * VIM: V = initial sound, I = medial vowel, M = final consonant.
+ */
+
+ static int
+comcon3(k, c)
+ int k;
+ int c;
+{
+ switch (k)
+ {
+ case 2: /* ¤¡ */
+ switch (c) {
+ case 2:
+ return 3; /* ¤¡¤¡ */
+ case 21:
+ return 4; /* ¤¡¤µ */
+ }
+ break;
+
+ case 5: /* ¤¤ */
+ switch (c) {
+ case 24: /* ¤¤¤¸ */
+ return 6;
+ case 29:
+ return 7; /* ¤¤¤¾ */
+ }
+ break;
+
+ case 9: /* ¤© */
+ switch (c) {
+ case 2: /* ¤©¤¡ */
+ return 10;
+ case 17: /* ¤©¤± */
+ return 11;
+ case 19: /* ¤©¤² */
+ return 12;
+ case 21: /* ¤©¤µ */
+ return 13;
+ case 27: /* ¤©¤¼ */
+ return 14;
+ case 28: /* ¤©¤½ */
+ return 15;
+ case 29: /* ¤©¤¾ */
+ return 16;
+ }
+ break;
+
+ case 19:
+ switch (c) {
+ case 21: /* ¤²¤µ */
+ return 20;
+ }
+ break;
+ }
+ return 0;
+}
+
+/**********************************************************************/
+/****** 2 ¹ú½ÄÀÚÆÇÀ» À§ÇÑ ·çƾ (Routines for 2 bulsik keyboard) ******/
+/**********************************************************************/
+
+ static int
+kind_table_for_2(c)
+ int c;
+{
+ static char_u table[] =
+ {
+ /* a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s */
+ 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ /* t, u, v, w, x, y, z */
+ 0, 1, 0, 0, 0, 1, 0
+ };
+
+ if (c <= 'Z')
+ c -= 'A';
+ else
+ c -= 'a';
+
+ return table[c];
+}
+
+/* 2 ¹ú½Ä¿¡¼­ ¿µ¹®ÀÚ -> Á¶ÇÕÇü Ãʼº º¯È¯
+ * (2 bulsik: conversion english char. to initial sound of compound type)
+ * °á°ú: ÃʼºÀÌ ¾Æ´Ï¸é 0 (If it is not initial sound, return 0).
+ */
+ static int
+fcon(c)
+ int c;
+{
+ static char_u table[] =
+ {
+ /*E */ 6 , /*F */ 0 , /*G */ 0 , /*H */ 0 , /*I */ 0 , /*J */ 0 , /*K */ 0 ,
+ /*L */ 0 , /*M */ 0 , /*N */ 0 , /*O */ 0 , /*P */ 0 , /*Q */ 10, /*R */ 3 ,
+ /*S */ 0 , /*T */ 12, /*U */ 0 , /*V */ 0 , /*W */ 15, /*X */ 0 , /*Y */ 0 ,
+ /*Z */ 0 , /*[ */ 0 , /*\ */ 0 , /*] */ 0 , /*^ */ 0 , /*_ */ 0 , /*` */ 0 ,
+ /*a */ 8 , /*b */ 0 , /*c */ 16, /*d */ 13, /*e */ 5 , /*f */ 7 , /*g */ 20,
+ /*h */ 0 , /*i */ 0 , /*j */ 0 , /*k */ 0 , /*l */ 0 , /*m */ 0 , /*n */ 0 ,
+ /*o */ 0 , /*p */ 0 , /*q */ 9 , /*r */ 2 , /*s */ 4 , /*t */ 11, /*u */ 0 ,
+ /*v */ 19, /*w */ 14, /*x */ 18, /*y */ 0 , /*z */ 17
+ };
+
+ if (c < 'E' || c > 'z')
+ return 0;
+ return table[c - 'E'];
+}
+
+/* 2 ¹ú½Ä¿¡¼­ ¿µ¹®ÀÚ -> Áß¼º º¯È¯
+ * (2 bulsik: conversion english char. to medial vowel)
+ * °á°ú: Áß¼ºÀÌ ¾Æ´Ï¸é 0 (If it is not medial vowel, return 0).
+ */
+ static int
+vow(c)
+ int c;
+{
+ static char_u table[] =
+ {
+ /*O */ 6 , /*P */ 12, /*Q */ 0 , /*R */ 0 , /*S */ 0 , /*T */ 0 , /*U */ 0 ,
+ /*V */ 0 , /*W */ 0 , /*X */ 0 , /*Y */ 0 , /*Z */ 0 , /*[ */ 0 , /*\ */ 0 ,
+ /*] */ 0 , /*^ */ 0 , /*_ */ 0 , /*` */ 0 , /*a */ 0 , /*b */ 26, /*c */ 0 ,
+ /*d */ 0 , /*e */ 0 , /*f */ 0 , /*g */ 0 , /*h */ 13, /*i */ 5 , /*j */ 7 ,
+ /*k */ 3 , /*l */ 29, /*m */ 27, /*n */ 20, /*o */ 4 , /*p */ 10, /*q */ 0 ,
+ /*r */ 0 , /*s */ 0 , /*t */ 0 , /*u */ 11, /*v */ 0 , /*w */ 0 , /*x */ 0 ,
+ /*y */ 19};
+
+ if (c < 'O' || c > 'y')
+ return 0;
+ return table[c - 'O'];
+}
+
+/* 2¹ú½Ä¿¡¼­ ¿µ¹®ÀÚ -> ¹Þħ º¯È¯
+ * (2 bulsik: conversion english char. to prop)
+ * °á°ú: ¹ÞħÀÌ ¾Æ´Ï¸é 0 (If not prop, return 0)
+ */
+ static int
+lcon(c)
+ int c;
+{
+ static char_u table[] =
+ {
+ /*R */ 3 , /*S */ 0 , /*T */ 22, /*U */ 0 , /*V */ 0 , /*W */ 0 , /*X */ 0 ,
+ /*Y */ 0 , /*Z */ 0 , /*[ */ 0 , /*\ */ 0 , /*] */ 0 , /*^ */ 0 , /*_ */ 0 ,
+ /*` */ 0 , /*a */ 17, /*b */ 0 , /*c */ 25, /*d */ 23, /*e */ 8 , /*f */ 9 ,
+ /*g */ 29, /*h */ 0 , /*i */ 0 , /*j */ 0 , /*k */ 0 , /*l */ 0 , /*m */ 0 ,
+ /*n */ 0 , /*o */ 0 , /*p */ 0 , /*q */ 19, /*r */ 2 , /*s */ 5 , /*t */ 21,
+ /*u */ 0 , /*v */ 28, /*w */ 24, /*x */ 27, /*y */ 0 , /*z */ 26
+ };
+
+ if (c < 'R' || c > 'z')
+ return 0;
+ return table[c - 'R'];
+}
+
+/* 2 ¹ú½Ä¿¡¼­ (ÇöÀç ¹Þħ, ¿µ¹®ÀÚ ÀÔ·Â) -> ¹Þħ º¯È¯
+ * (2 bulsik: conversion (curr. prop, input english) to prop)
+ */
+
+ static int
+comcon2(k, c)
+ int k;
+ int c;
+{
+ switch (k)
+ {
+ case 2: /* ¤¡ */
+ switch (c) {
+ case 't':
+ return 4; /* ¤¡¤µ */
+ }
+ break;
+
+ case 5: /* ¤¤ */
+ switch (c) {
+ case 'w': /* ¤¤¤¸ */
+ return 6;
+ case 'g': /* ¤¤¤¾ */
+ return 7;
+ }
+ break;
+
+ case 9: /* ¤© */
+ switch (c) {
+ case 'r': /* ¤©¤¡ */
+ return 10;
+ case 'a': /* ¤©¤± */
+ return 11;
+ case 'q': /* ¤©¤² */
+ return 12;
+ case 't': /* ¤©¤µ */
+ return 13;
+ case 'x': /* ¤©¤¼ */
+ return 14;
+ case 'v': /* ¤©¤½ */
+ return 15;
+ case 'g': /* ¤©¤¾ */
+ return 16;
+ }
+ break;
+
+ case 19: /* ¤² */
+ switch (c) {
+ case 't': /* ¤²¤µ */
+ return 20;
+ }
+ break;
+ }
+ return 0;
+}
+
+/* 2¹ú½Ä¿¡¼­ (ÇöÀç Áß¼º, ¿µ¹® ÀÔ·Â) -> Áß¼º º¯È¯
+ * (2 bulsik: conversion (curr. medial vowel, input english) to medial
+ * vowel)
+ */
+
+ static int
+comvow2(v, c)
+ int v;
+ int c;
+{
+ switch (v)
+ {
+ case 13: /* ¤Ç */
+ switch (c) {
+ case 'k': /* ¤Ç¤¿ */
+ return 14;
+ case 'o': /* ¤Ç¤À */
+ return 15;
+ case 'l': /* ¤Ç¤Ó */
+ return 18;
+ }
+ break;
+
+ case 20: /* ¤Ì */
+ switch (c) {
+ case 'j': /* ¤Ì¤Ã */
+ return 21;
+ case 'p': /* ¤Ì¤Ä */
+ return 22;
+ case 'l': /* ¤Ì¤Ó */
+ return 23;
+ }
+ break;
+
+ case 27: /* ¤Ñ */
+ switch (c) {
+ case 'l': /* ¤Ñ¤Ó */
+ return 28;
+ }
+ break;
+ }
+ return 0;
+}
+
+ int
+hangul_input_state_get()
+{
+ return hangul_input_state;
+}
+
+ void
+hangul_input_state_set(state)
+ int state;
+{
+ hangul_input_state = state;
+ hangul_input_clear();
+}
+
+ int
+im_get_status()
+{
+ return hangul_input_state_get();
+}
+
+ void
+hangul_input_state_toggle()
+{
+ if (hangul_input_state_get())
+ {
+ hangul_input_state_set(0);
+ if (composing_hangul)
+ {
+ push_raw_key(composing_hangul_buffer, 2);
+ composing_hangul = 0;
+ }
+ }
+ else
+ hangul_input_state_set(1);
+
+ if (showmode())
+ {
+ setcursor();
+ out_flush();
+ }
+
+ gui_update_cursor(TRUE, FALSE);
+}
+
+ static int
+hangul_automata2(buf, c)
+ char_u *buf;
+ int_u *c;
+{
+ int t,t2;
+
+ if (*c == BS)
+ {
+ if (sp == 0)
+ return AUTOMATA_SPECIAL;
+ else if (sp < 4)
+ {
+ hangul_input_clear();
+ return AUTOMATA_NULL;
+ }
+ pop(buf);
+ query(buf);
+ convert_ks_to_3(buf, &f, &m, &l);
+ last_l = last_ll;
+ last_ll = -1;
+ return AUTOMATA_CORRECT;
+ }
+ if ((!(*c >= 'A' && *c <= 'Z')) && (!(*c >= 'a' && *c <= 'z')))
+ {
+ hangul_input_clear();
+ return AUTOMATA_SPECIAL;
+ }
+ t = *c;
+ switch (kind_table_for_2(t))
+ {
+ case 0: /* ÀÚÀ½ (consonant) */
+ if (f == F_NULL)
+ {
+ if (m != M_NULL)
+ hangul_input_clear();
+ f = fcon(t);
+ convert_3_to_code(f, M_NULL, L_NULL, buf);
+ push(buf);
+ last_ll = last_l = -1;
+ return AUTOMATA_NEW;
+ }
+ if (m == M_NULL)
+ return AUTOMATA_ERROR;
+ if (l == L_NULL)
+ {
+ t2 = lcon(t);
+ if (!t2) /* ¹ÞħÀ¸·Î ÀûÇÕÇÏÁö¾Ê´Ù (cannot use it as a prop) */
+ {
+ hangul_input_clear();
+ last_ll = last_l = -1;
+ f = fcon(t);
+ convert_3_to_code(f, m, l, buf);
+ push(buf);
+ return AUTOMATA_NEW;
+ }
+ if (2 == convert_3_to_code(f, m, t2, buf))
+ {
+ last_ll = -1;
+ last_l = t;
+ l = t2;
+ push(buf);
+ return AUTOMATA_CORRECT;
+ }
+ else /* ¹ÞħÀ¸·Î ¾²·ÁÇÏ¿´À¸³ª code¿¡ ¾ø´Â ±ÛÀÚÀÌ´Ù */
+ { /* cannot find such a prop in the code table */
+ last_ll = last_l = -1;
+ hangul_input_clear();
+ f = fcon(t);
+ convert_3_to_code(f, m, l, buf);
+ push(buf);
+ return AUTOMATA_NEW;
+ }
+ }
+ /* ÃÊ Áß Á¾¼ºÀÌ ¸ðµÎ °®Ãß¾îÁ® ÀÖ´Ù
+ * I have all the 'initial sound' and 'medial vowel' and 'final
+ * consonant'.
+ */
+ t2 = comcon2(l, t);
+ if (t2)
+ {
+ if (2 == convert_3_to_code(f, m, t2, buf))
+ {
+ l = t2;
+ last_ll = last_l;
+ last_l = t;
+ push(buf);
+ return AUTOMATA_CORRECT;
+ }
+ }
+ last_ll = last_l = -1;
+ hangul_input_clear();
+ f = fcon(t);
+ convert_3_to_code(f, m, l, buf);
+ push(buf);
+ return AUTOMATA_NEW;
+
+ case 1:
+ if (f == F_NULL)
+ {
+ hangul_input_clear();
+ m = vow(t);
+ convert_3_to_code (f, m, L_NULL, buf);
+ push (buf);
+ last_ll = last_l = -1;
+ return AUTOMATA_NEW;
+ }
+ if (m == M_NULL)
+ {
+ m = vow(t);
+ if (2 == convert_3_to_code(f, m, L_NULL, buf))
+ {
+ last_ll = last_l = -1;
+ push(buf);
+ return AUTOMATA_CORRECT;
+ }
+ m = M_NULL;
+ return AUTOMATA_ERROR;
+ }
+ if (l == L_NULL)
+ {
+ t2 = comvow2(m, t);
+ if (t2)
+ {
+ if (2 != convert_3_to_code(f, t2, L_NULL, buf))
+ return AUTOMATA_ERROR;
+
+ m = t2;
+ push(buf);
+ last_ll = last_l = -1;
+ return AUTOMATA_CORRECT;
+ }
+ return AUTOMATA_ERROR;
+ }
+ pop(buf);
+ pop(buf);
+ sp = 0;
+ if (last_l == -1)
+ {
+ /* À½... ÀÌ°Ô ÇÊ¿äÇϳª?? (Hmm... Is it needed?) */
+ convert_ks_to_3(buf, &f, &m, &l);
+ }
+ else
+ {
+ char_u tmp[3];
+ f = fcon(last_l);
+ convert_3_to_code (f, M_NULL, L_NULL, tmp);
+ push (tmp);
+ }
+ m = vow(t);
+ l = L_NULL;
+ convert_3_to_code(f, m, l, buf + 2);
+ push(buf + 2);
+ return AUTOMATA_CORRECT_NEW;
+
+ default:
+ EMSG(_("E256: Hangul automata ERROR"));
+ break;
+ }
+ return AUTOMATA_ERROR; /* RrEeAaLlLlYy EeRrRrOoRr */
+}
+
+ static int
+hangul_automata3(buf, c)
+ char_u *buf;
+ int_u *c;
+{
+ int t, t2;
+
+ if (*c >= '!' && *c <= 'z')
+ {
+ *c -= '!';
+ t = value_table_for_3[*c];
+ switch (kind_table_for_3[*c])
+ {
+ case F_F: /* Ãʼº¹®ÀÚ (char. of an initial sound) */
+ if (m != M_NULL || sp == 0)
+ {
+ /* ÃʼºÀÌ ºñ¾ú°Å³ª ´ÙÀ½ ±ÛÀÚ ¸ðÀ¸±â ½ÃÀÛ
+ * Empty 'initial sound', so starting automata.
+ */
+ hangul_input_clear();
+ f = t;
+ convert_3_to_code(f, M_NULL, L_NULL, buf);
+ push(buf);
+ return AUTOMATA_NEW;
+ }
+ if ((t2 = comfcon3(f,t)) != 0) /* º¹ÀÚÀ½ (double? consonant) */
+ {
+ f=t2;
+ convert_3_to_code(f, M_NULL, L_NULL, buf);
+ push(buf);
+ return AUTOMATA_CORRECT;
+ }
+ return AUTOMATA_ERROR;
+
+ case F_M: /* ¸ðÀ½ (vowel) */
+ if (m == M_NULL)
+ {
+ if (2 != convert_3_to_code(f, t, L_NULL,buf))
+ return AUTOMATA_ERROR;
+
+ m = t;
+ push(buf);
+ if (f == F_NULL)
+ return AUTOMATA_NEW;
+ else
+ return AUTOMATA_CORRECT;
+ }
+ if ((t2 = comvow3(m,t))) /* º¹¸ðÀ½ (a diphthong) */
+ {
+ m = t2;
+ convert_3_to_code(f, m, L_NULL, buf);
+ push(buf);
+ return AUTOMATA_CORRECT;
+ }
+ return AUTOMATA_ERROR;
+
+ case F_L: /* ¹Þħ (prop?) */
+ if (m == M_NULL)
+ return AUTOMATA_ERROR; /* Áß¼º¾ø´Â Á¾¼º */
+ if (l == L_NULL)
+ {
+ if (2 != convert_3_to_code(f, m, t, buf))
+ {
+ l = L_NULL;
+ return AUTOMATA_ERROR;
+ }
+ push(buf);
+ l = t;
+ return AUTOMATA_CORRECT;
+ }
+ if ((t2 = comcon3(l,t)) != 0) /* º¹ ¹Þħ ?? (double prop?) */
+ {
+ if (2 != convert_3_to_code(f, m, t2, buf))
+ return AUTOMATA_ERROR;
+
+ push(buf);
+ l = t2;
+ return AUTOMATA_CORRECT;
+ }
+ return AUTOMATA_ERROR;
+
+ case F_A: /* Ư¼ö¹®ÀÚ³ª ¼ýÀÚ (special char. or number) */
+ hangul_input_clear();
+ *c = t;
+ return AUTOMATA_SPECIAL;
+ }
+ }
+ if (*c == BS)
+ {
+ if (sp >= 4)
+ {
+ pop(buf);
+ pop(buf);
+ convert_ks_to_3(buf, &f, &m, &l);
+ push(buf);
+ return AUTOMATA_CORRECT;
+ }
+ else if (sp == 0)
+ {
+ return AUTOMATA_SPECIAL;
+ }
+ else
+ {
+ hangul_input_clear();
+ return AUTOMATA_NULL;
+ }
+ }
+ hangul_input_clear();
+ return AUTOMATA_SPECIAL;
+}
+
+ void
+hangul_keyboard_set()
+{
+ int keyboard;
+ char *s;
+
+ hangul_input_clear();
+
+ if ((s = getenv("VIM_KEYBOARD")) == NULL)
+ s = getenv("HANGUL_KEYBOARD_TYPE");
+
+ if (s)
+ {
+ if (*s == '2')
+ keyboard = 2;
+ else
+ keyboard = 3;
+ hangul_keyboard_type = keyboard;
+ }
+}
+
+ int
+hangul_input_process(s, len)
+ char_u *s;
+ int len;
+{
+ int n;
+ unsigned int c;
+ char_u hanbuf[20];
+
+ if (len == 1)
+ /* normal key press */
+ c = *s;
+ else if (len == 3 && s[0] == CSI && s[1] == 'k' && s[2] == 'b')
+ {
+ /* backspace */
+ if (composing_hangul)
+ c = Ctrl_H;
+ else
+ return len;
+ }
+ else
+ {
+ if (composing_hangul)
+ push_raw_key(composing_hangul_buffer, 2);
+ hangul_input_clear();
+ composing_hangul = 0;
+ return len;
+ }
+
+ if (hangul_keyboard_type == 2)
+ n = hangul_automata2(hanbuf, &c);
+ else
+ n = hangul_automata3(hanbuf, &c);
+
+ if (n == AUTOMATA_CORRECT)
+ {
+ STRNCPY(composing_hangul_buffer, hanbuf, 2);
+ gui_update_cursor(TRUE, FALSE);
+ return 0;
+ }
+ else if (n == AUTOMATA_NEW)
+ {
+ if (composing_hangul)
+ push_raw_key(composing_hangul_buffer, 2);
+ STRNCPY(composing_hangul_buffer, hanbuf, 2);
+ composing_hangul = 1;
+ gui_update_cursor(TRUE, FALSE);
+ return 0;
+ }
+ else if (n == AUTOMATA_CORRECT_NEW)
+ {
+ if (composing_hangul)
+ push_raw_key(hanbuf, 2);
+ STRNCPY(composing_hangul_buffer, hanbuf+2, 2);
+ composing_hangul = 1;
+ gui_update_cursor(TRUE, FALSE);
+ return 0;
+ }
+ else if (n == AUTOMATA_NULL)
+ {
+ composing_hangul = 0;
+ gui_redraw_block(gui.cursor_row, gui.cursor_col,
+ gui.cursor_row, gui.cursor_col + 1,
+ GUI_MON_NOCLEAR);
+ gui_update_cursor(TRUE, FALSE);
+ return 0;
+ }
+ else if (n == AUTOMATA_SPECIAL)
+ {
+ if (composing_hangul)
+ {
+ push_raw_key(composing_hangul_buffer, 2);
+ composing_hangul = 0;
+ }
+ *s = c;
+ return 1;
+ }
+ else if (n == AUTOMATA_ERROR)
+ {
+ vim_beep();
+ return 0;
+ }
+ return len;
+}
+
+ void
+hangul_input_clear()
+{
+ sp = 0;
+ f = F_NULL;
+ m = M_NULL;
+ l = L_NULL;
+}
+
+#define han_index(h, l) (((h)-0xb0)*(0xff-0xa1)+((l)-0xa1))
+
+static const char_u ks_table1[][3] =
+{
+ { 2, 3, 1}, { 2, 3, 2}, { 2, 3, 5}, { 2, 3, 8},
+ { 2, 3, 9}, { 2, 3, 10}, { 2, 3, 11}, { 2, 3, 17},
+ { 2, 3, 19}, { 2, 3, 20}, { 2, 3, 21}, { 2, 3, 22},
+ { 2, 3, 23}, { 2, 3, 24}, { 2, 3, 25}, { 2, 3, 27},
+ { 2, 3, 28}, { 2, 3, 29}, { 2, 4, 1}, { 2, 4, 2},
+ { 2, 4, 5}, { 2, 4, 9}, { 2, 4, 17}, { 2, 4, 19},
+ { 2, 4, 21}, { 2, 4, 22}, { 2, 4, 23}, { 2, 5, 1},
+ { 2, 5, 2}, { 2, 5, 5}, { 2, 5, 9}, { 2, 5, 21},
+ { 2, 5, 23}, { 2, 6, 1}, { 2, 6, 5}, { 2, 6, 9},
+ { 2, 7, 1}, { 2, 7, 2}, { 2, 7, 5}, { 2, 7, 8},
+ { 2, 7, 9}, { 2, 7, 11}, { 2, 7, 17}, { 2, 7, 19},
+ { 2, 7, 21}, { 2, 7, 22}, { 2, 7, 23}, { 2, 7, 24},
+ { 2, 7, 27}, { 2, 7, 28}, { 2, 7, 29}, { 2, 10, 1},
+ { 2, 10, 5}, { 2, 10, 9}, { 2, 10, 17}, { 2, 10, 19},
+ { 2, 10, 21}, { 2, 10, 22}, { 2, 10, 23}, { 2, 11, 1},
+ { 2, 11, 2}, { 2, 11, 3}, { 2, 11, 5}, { 2, 11, 8},
+ { 2, 11, 9}, { 2, 11, 17}, { 2, 11, 19}, { 2, 11, 21},
+ { 2, 11, 22}, { 2, 11, 23}, { 2, 11, 27}, { 2, 12, 1},
+ { 2, 12, 5}, { 2, 12, 9}, { 2, 12, 19}, { 2, 12, 21},
+ { 2, 13, 1}, { 2, 13, 2}, { 2, 13, 5}, { 2, 13, 8},
+ { 2, 13, 9}, { 2, 13, 11}, { 2, 13, 13}, { 2, 13, 16},
+ { 2, 13, 17}, { 2, 13, 19}, { 2, 13, 21}, { 2, 13, 23},
+ { 2, 13, 24}, { 2, 14, 1}, { 2, 14, 2}, { 2, 14, 5},
+ { 2, 14, 9}, { 2, 14, 11}, { 2, 14, 17}, { 2, 14, 19},
+ { 2, 14, 21}, { 2, 14, 23}, { 2, 15, 1}, { 2, 15, 5},
+ { 2, 15, 9}, { 2, 15, 19}, { 2, 15, 22}, { 2, 15, 23},
+ { 2, 18, 1}, { 2, 18, 2}, { 2, 18, 5}, { 2, 18, 9},
+ { 2, 18, 17}, { 2, 18, 19}, { 2, 18, 21}, { 2, 18, 23},
+ { 2, 19, 1}, { 2, 19, 5}, { 2, 19, 9}, { 2, 19, 19},
+ { 2, 19, 21}, { 2, 20, 1}, { 2, 20, 2}, { 2, 20, 5},
+ { 2, 20, 8}, { 2, 20, 9}, { 2, 20, 10}, { 2, 20, 11},
+ { 2, 20, 16}, { 2, 20, 17}, { 2, 20, 19}, { 2, 20, 21},
+ { 2, 20, 23}, { 2, 20, 24}, { 2, 21, 1}, { 2, 21, 2},
+ { 2, 21, 5}, { 2, 21, 9}, { 2, 21, 22}, { 2, 21, 23},
+ { 2, 22, 1}, { 2, 22, 21}, { 2, 23, 1}, { 2, 23, 2},
+ { 2, 23, 5}, { 2, 23, 9}, { 2, 23, 17}, { 2, 23, 19},
+ { 2, 23, 21}, { 2, 26, 1}, { 2, 26, 5}, { 2, 26, 9},
+ { 2, 27, 1}, { 2, 27, 2}, { 2, 27, 5}, { 2, 27, 8},
+ { 2, 27, 9}, { 2, 27, 10}, { 2, 27, 17}, { 2, 27, 19},
+ { 2, 27, 21}, { 2, 27, 23}, { 2, 28, 1}, { 2, 29, 1},
+ { 2, 29, 2}, { 2, 29, 5}, { 2, 29, 8}, { 2, 29, 9},
+ { 2, 29, 11}, { 2, 29, 17}, { 2, 29, 19}, { 2, 29, 21},
+ { 2, 29, 23}, { 2, 29, 24}, { 2, 29, 28}, { 3, 3, 1},
+ { 3, 3, 2}, { 3, 3, 3}, { 3, 3, 5}, { 3, 3, 9},
+ { 3, 3, 11}, { 3, 3, 17}, { 3, 3, 19}, { 3, 3, 21},
+ { 3, 3, 22}, { 3, 3, 23}, { 3, 3, 27}, { 3, 4, 1},
+ { 3, 4, 2}, { 3, 4, 5}, { 3, 4, 9}, { 3, 4, 17},
+ { 3, 4, 19}, { 3, 4, 21}, { 3, 4, 22}, { 3, 4, 23},
+ { 3, 5, 1}, { 3, 5, 2}, { 3, 5, 9}, { 3, 7, 1},
+ { 3, 7, 2}, { 3, 7, 3}, { 3, 7, 5}, { 3, 7, 9},
+ { 3, 7, 17}, { 3, 7, 19}, { 3, 7, 21}, { 3, 7, 22},
+ { 3, 7, 23}, { 3, 10, 1}, { 3, 10, 2}, { 3, 10, 5},
+ { 3, 10, 17}, { 3, 10, 21}, { 3, 10, 23}, { 3, 11, 1},
+ { 3, 11, 5}, { 3, 11, 9}, { 3, 11, 21}, { 3, 11, 22},
+ { 3, 11, 27}, { 3, 12, 1}, { 3, 13, 1}, { 3, 13, 2},
+ { 3, 13, 5}, { 3, 13, 7}, { 3, 13, 9}, { 3, 13, 17},
+ { 3, 13, 19}, { 3, 13, 21}, { 3, 13, 23}, { 3, 13, 24},
+ { 3, 13, 25}, { 3, 14, 1}, { 3, 14, 2}, { 3, 14, 9},
+ { 3, 14, 22}, { 3, 14, 23}, { 3, 15, 1}, { 3, 15, 2},
+ { 3, 15, 23}, { 3, 18, 1}, { 3, 18, 5}, { 3, 18, 9},
+ { 3, 18, 17}, { 3, 18, 19}, { 3, 18, 23}, { 3, 19, 1},
+ { 3, 20, 1}, { 3, 20, 2}, { 3, 20, 5}, { 3, 20, 9},
+ { 3, 20, 16}, { 3, 20, 17}, { 3, 20, 19}, { 3, 20, 21},
+ { 3, 20, 23}, { 3, 20, 24}, { 3, 21, 1}, { 3, 21, 9},
+ { 3, 21, 22}, { 3, 21, 23}, { 3, 22, 1}, { 3, 22, 2},
+ { 3, 22, 5}, { 3, 22, 9}, { 3, 22, 17}, { 3, 22, 19},
+ { 3, 22, 22}, { 3, 23, 1}, { 3, 23, 5}, { 3, 23, 9},
+ { 3, 23, 17}, { 3, 23, 19}, { 3, 26, 1}, { 3, 27, 1},
+ { 3, 27, 2}, { 3, 27, 5}, { 3, 27, 7}, { 3, 27, 9},
+ { 3, 27, 11}, { 3, 27, 16}, { 3, 27, 17}, { 3, 27, 19},
+ { 3, 27, 21}, { 3, 27, 23}, { 3, 27, 27}, { 3, 29, 1},
+ { 3, 29, 2}, { 3, 29, 5}, { 3, 29, 9}, { 3, 29, 17},
+ { 3, 29, 19}, { 3, 29, 21}, { 3, 29, 23}, { 4, 3, 1},
+ { 4, 3, 2}, { 4, 3, 3}, { 4, 3, 5}, { 4, 3, 8},
+ { 4, 3, 9}, { 4, 3, 10}, { 4, 3, 11}, { 4, 3, 17},
+ { 4, 3, 19}, { 4, 3, 21}, { 4, 3, 22}, { 4, 3, 23},
+ { 4, 3, 24}, { 4, 3, 25}, { 4, 3, 27}, { 4, 3, 29},
+ { 4, 4, 1}, { 4, 4, 2}, { 4, 4, 5}, { 4, 4, 9},
+ { 4, 4, 17}, { 4, 4, 19}, { 4, 4, 21}, { 4, 4, 22},
+ { 4, 4, 23}, { 4, 5, 1}, { 4, 5, 2}, { 4, 5, 5},
+ { 4, 5, 9}, { 4, 5, 17}, { 4, 5, 23}, { 4, 7, 1},
+ { 4, 7, 2}, { 4, 7, 4}, { 4, 7, 5}, { 4, 7, 9},
+ { 4, 7, 11}, { 4, 7, 12}, { 4, 7, 17}, { 4, 7, 19},
+ { 4, 7, 21}, { 4, 7, 22}, { 4, 7, 23}, { 4, 7, 29},
+ { 4, 10, 1}, { 4, 10, 2}, { 4, 10, 5}, { 4, 10, 9},
+ { 4, 10, 17}, { 4, 10, 19}, { 4, 10, 21}, { 4, 10, 22},
+ { 4, 10, 23}, { 4, 11, 1}, { 4, 11, 2}, { 4, 11, 5},
+ { 4, 11, 9}, { 4, 11, 17}, { 4, 11, 19}, { 4, 11, 22},
+ { 4, 11, 23}, { 4, 11, 26}, { 4, 12, 1}, { 4, 12, 5},
+ { 4, 13, 1}, { 4, 13, 2}, { 4, 13, 5}, { 4, 13, 9},
+ { 4, 13, 11}, { 4, 13, 17}, { 4, 13, 19}, { 4, 13, 21},
+ { 4, 13, 23}, { 4, 13, 28}, { 4, 13, 29}, { 4, 14, 1},
+ { 4, 14, 5}, { 4, 14, 9}, { 4, 14, 22}, { 4, 18, 1},
+ { 4, 18, 5}, { 4, 18, 9}, { 4, 18, 17}, { 4, 18, 19},
+ { 4, 18, 21}, { 4, 19, 1}, { 4, 19, 2}, { 4, 19, 5},
+ { 4, 19, 9}, { 4, 19, 19}, { 4, 19, 21}, { 4, 19, 23},
+ { 4, 20, 1}, { 4, 20, 2}, { 4, 20, 5}, { 4, 20, 8},
+ { 4, 20, 9}, { 4, 20, 17}, { 4, 20, 19}, { 4, 20, 21},
+ { 4, 20, 23}, { 4, 21, 1}, { 4, 21, 22}, { 4, 22, 1},
+ { 4, 23, 1}, { 4, 23, 5}, { 4, 23, 9}, { 4, 23, 17},
+ { 4, 23, 19}, { 4, 26, 1}, { 4, 26, 2}, { 4, 26, 9},
+ { 4, 26, 17}, { 4, 26, 19}, { 4, 26, 23}, { 4, 27, 1},
+ { 4, 27, 2}, { 4, 27, 5}, { 4, 27, 9}, { 4, 27, 10},
+ { 4, 27, 11}, { 4, 27, 17}, { 4, 27, 19}, { 4, 27, 21},
+ { 4, 27, 23}, { 4, 27, 24}, { 4, 27, 28}, { 4, 28, 1},
+ { 4, 28, 5}, { 4, 28, 9}, { 4, 29, 1}, { 4, 29, 2},
+ { 4, 29, 5}, { 4, 29, 9}, { 4, 29, 11}, { 4, 29, 17},
+ { 4, 29, 19}, { 4, 29, 21}, { 4, 29, 23}, { 4, 29, 28},
+ { 5, 3, 1}, { 5, 3, 2}, { 5, 3, 3}, { 5, 3, 5},
+ { 5, 3, 8}, { 5, 3, 9}, { 5, 3, 10}, { 5, 3, 11},
+ { 5, 3, 12}, { 5, 3, 16}, { 5, 3, 17}, { 5, 3, 19},
+ { 5, 3, 21}, { 5, 3, 22}, { 5, 3, 23}, { 5, 3, 24},
+ { 5, 3, 25}, { 5, 3, 29}, { 5, 4, 1}, { 5, 4, 2},
+ { 5, 4, 5}, { 5, 4, 9}, { 5, 4, 17}, { 5, 4, 19},
+ { 5, 4, 21}, { 5, 4, 22}, { 5, 4, 23}, { 5, 5, 1},
+ { 5, 7, 1}, { 5, 7, 2}, { 5, 7, 3}, { 5, 7, 5},
+ { 5, 7, 8}, { 5, 7, 9}, { 5, 7, 11}, { 5, 7, 12},
+ { 5, 7, 17}, { 5, 7, 19}, { 5, 7, 21}, { 5, 7, 23},
+ { 5, 7, 25}, { 5, 7, 28}, { 5, 10, 1}, { 5, 10, 2},
+ { 5, 10, 5}, { 5, 10, 9}, { 5, 10, 17}, { 5, 10, 19},
+ { 5, 10, 21}, { 5, 10, 22}, { 5, 10, 23}, { 5, 11, 1},
+ { 5, 11, 5}, { 5, 11, 9}, { 5, 11, 22}, { 5, 11, 23},
+ { 5, 12, 1}, { 5, 12, 5}, { 5, 13, 1}, { 5, 13, 2},
+ { 5, 13, 5}, { 5, 13, 8}, { 5, 13, 9}, { 5, 13, 11},
+ { 5, 13, 13}, { 5, 13, 17}, { 5, 13, 19}, { 5, 13, 21},
+ { 5, 13, 23}, { 5, 13, 25}, { 5, 13, 27}, { 5, 14, 1},
+ { 5, 14, 5}, { 5, 14, 9}, { 5, 15, 1}, { 5, 15, 22},
+ { 5, 18, 1}, { 5, 18, 5}, { 5, 18, 9}, { 5, 18, 17},
+ { 5, 18, 19}, { 5, 18, 21}, { 5, 19, 1}, { 5, 20, 1},
+ { 5, 20, 2}, { 5, 20, 5}, { 5, 20, 9}, { 5, 20, 17},
+ { 5, 20, 19}, { 5, 20, 21}, { 5, 20, 23}, { 5, 21, 1},
+ { 5, 21, 22}, { 5, 22, 1}, { 5, 22, 23}, { 5, 23, 1},
+ { 5, 23, 5}, { 5, 23, 9}, { 5, 23, 19}, { 5, 23, 21},
+ { 5, 23, 23}, { 5, 26, 1}, { 5, 26, 5}, { 5, 26, 9},
+ { 5, 26, 17}, { 5, 26, 23}, { 5, 27, 1}, { 5, 27, 2},
+ { 5, 27, 5}, { 5, 27, 8}, { 5, 27, 9}, { 5, 27, 11},
+ { 5, 27, 17}, { 5, 27, 19}, { 5, 27, 21}, { 5, 27, 23},
+ { 5, 28, 1}, { 5, 29, 1}, { 5, 29, 2}, { 5, 29, 5},
+ { 5, 29, 8}, { 5, 29, 9}, { 5, 29, 17}, { 5, 29, 19},
+ { 5, 29, 21}, { 5, 29, 22}, { 5, 29, 23}, { 5, 29, 24},
+ { 6, 3, 1}, { 6, 3, 2}, { 6, 3, 5}, { 6, 3, 9},
+ { 6, 3, 17}, { 6, 3, 19}, { 6, 3, 21}, { 6, 3, 22},
+ { 6, 3, 23}, { 6, 3, 29}, { 6, 4, 1}, { 6, 4, 2},
+ { 6, 4, 5}, { 6, 4, 9}, { 6, 4, 17}, { 6, 4, 19},
+ { 6, 4, 21}, { 6, 4, 22}, { 6, 4, 23}, { 6, 7, 1},
+ { 6, 7, 2}, { 6, 7, 5}, { 6, 7, 9}, { 6, 7, 11},
+ { 6, 7, 12}, { 6, 7, 17}, { 6, 7, 19}, { 6, 7, 21},
+ { 6, 7, 22}, { 6, 7, 23}, { 6, 7, 29}, { 6, 10, 1},
+ { 6, 10, 2}, { 6, 10, 5}, { 6, 10, 9}, { 6, 10, 17},
+ { 6, 10, 19}, { 6, 10, 21}, { 6, 10, 22}, { 6, 10, 23},
+ { 6, 11, 1}, { 6, 11, 22}, { 6, 13, 1}, { 6, 13, 2},
+ { 6, 13, 5}, { 6, 13, 9}, { 6, 13, 23}, { 6, 14, 1},
+ { 6, 14, 9}, { 6, 15, 1}, { 6, 18, 1}, { 6, 18, 5},
+ { 6, 20, 1}, { 6, 20, 2}, { 6, 20, 5}, { 6, 20, 9},
+ { 6, 20, 16}, { 6, 20, 17}, { 6, 20, 23}, { 6, 22, 1},
+ { 6, 23, 1}, { 6, 23, 5}, { 6, 23, 9}, { 6, 23, 17},
+ { 6, 23, 19}, { 6, 23, 23}, { 6, 27, 1}, { 6, 27, 2},
+ { 6, 27, 5}, { 6, 27, 8}, { 6, 27, 9}, { 6, 27, 17},
+ { 6, 27, 19}, { 6, 27, 21}, { 6, 28, 1}, { 6, 28, 5},
+ { 6, 28, 9}, { 6, 28, 17}, { 6, 28, 19}, { 6, 29, 1},
+ { 6, 29, 5}, { 6, 29, 9}, { 6, 29, 17}, { 6, 29, 19},
+ { 6, 29, 21}, { 6, 29, 23}, { 7, 3, 1}, { 7, 3, 2},
+ { 7, 3, 5}, { 7, 3, 9}, { 7, 3, 17}, { 7, 3, 19},
+ { 7, 3, 21}, { 7, 3, 22}, { 7, 3, 23}, { 7, 3, 24},
+ { 7, 3, 28}, { 7, 3, 29}, { 7, 4, 1}, { 7, 4, 2},
+ { 7, 4, 5}, { 7, 4, 9}, { 7, 4, 17}, { 7, 4, 19},
+ { 7, 4, 21}, { 7, 4, 22}, { 7, 4, 23}, { 7, 5, 1},
+ { 7, 5, 2}, { 7, 5, 5}, { 7, 5, 21}, { 7, 5, 23},
+ { 7, 7, 1}, { 7, 7, 2}, { 7, 7, 5}, { 7, 7, 9},
+ { 7, 7, 17}, { 7, 7, 19}, { 7, 7, 21}, { 7, 7, 22},
+ { 7, 7, 23}, { 7, 7, 29}, { 7, 10, 1}, { 7, 10, 2},
+ { 7, 10, 5}, { 7, 10, 9}, { 7, 10, 17}, { 7, 10, 19},
+ { 7, 10, 21}, { 7, 10, 23}, { 7, 11, 1}, { 7, 11, 2},
+ { 7, 11, 5}, { 7, 11, 9}, { 7, 11, 17}, { 7, 11, 19},
+ { 7, 11, 21}, { 7, 11, 22}, { 7, 11, 23}, { 7, 12, 1},
+ { 7, 12, 5}, { 7, 12, 19}, { 7, 12, 21}, { 7, 13, 1},
+ { 7, 13, 2}, { 7, 13, 5}, { 7, 13, 9}, { 7, 13, 17},
+ { 7, 13, 19}, { 7, 13, 21}, { 7, 13, 23}, { 7, 14, 1},
+ { 7, 14, 5}, { 7, 14, 23}, { 7, 15, 22}, { 7, 18, 1},
+ { 7, 18, 5}, { 7, 18, 9}, { 7, 18, 17}, { 7, 18, 19},
+ { 7, 18, 21}, { 7, 18, 23}, { 7, 19, 1}, { 7, 19, 5},
+ { 7, 19, 9}, { 7, 19, 19}, { 7, 19, 21}, { 7, 19, 23},
+ { 7, 20, 1}, { 7, 20, 2}, { 7, 20, 5}, { 7, 20, 9},
+ { 7, 20, 17}, { 7, 20, 19}, { 7, 20, 21}, { 7, 20, 23},
+ { 7, 21, 1}, { 7, 21, 22}, { 7, 22, 1}, { 7, 23, 1},
+ { 7, 23, 2}, { 7, 23, 5}, { 7, 23, 9}, { 7, 23, 17},
+ { 7, 23, 21}, { 7, 23, 23}, { 7, 26, 1}, { 7, 26, 2},
+ { 7, 26, 5}, { 7, 26, 9}, { 7, 26, 17}, { 7, 26, 19},
+ { 7, 26, 21}, { 7, 26, 23}, { 7, 27, 1}, { 7, 27, 2},
+ { 7, 27, 5}, { 7, 27, 9}, { 7, 27, 17}, { 7, 27, 19},
+ { 7, 27, 21}, { 7, 27, 23}, { 7, 27, 24}, { 7, 27, 27},
+ { 7, 27, 28}, { 7, 29, 1}, { 7, 29, 2}, { 7, 29, 5},
+ { 7, 29, 9}, { 7, 29, 17}, { 7, 29, 19}, { 7, 29, 21},
+ { 7, 29, 23}, { 8, 3, 1}, { 8, 3, 2}, { 8, 3, 5},
+ { 8, 3, 7}, { 8, 3, 8}, { 8, 3, 9}, { 8, 3, 10},
+ { 8, 3, 11}, { 8, 3, 17}, { 8, 3, 19}, { 8, 3, 21},
+ { 8, 3, 23}, { 8, 3, 24}, { 8, 3, 27}, { 8, 3, 29},
+ { 8, 4, 1}, { 8, 4, 2}, { 8, 4, 5}, { 8, 4, 9},
+ { 8, 4, 17}, { 8, 4, 19}, { 8, 4, 21}, { 8, 4, 22},
+ { 8, 4, 23}, { 8, 4, 24}, { 8, 5, 1}, { 8, 5, 2},
+ { 8, 5, 9}, { 8, 5, 23}, { 8, 7, 1}, { 8, 7, 2},
+ { 8, 7, 5}, { 8, 7, 9}, { 8, 7, 11}, { 8, 7, 17},
+ { 8, 7, 19}, { 8, 7, 21}, { 8, 7, 23}, { 8, 7, 24},
+ { 8, 7, 29}, { 8, 10, 1}, { 8, 10, 2}, { 8, 10, 5},
+ { 8, 10, 9}, { 8, 10, 17}, { 8, 10, 19}, { 8, 10, 21},
+ { 8, 10, 22}, { 8, 10, 23}, { 8, 11, 1}, { 8, 11, 2},
+ { 8, 11, 5}, { 8, 11, 9}, { 8, 11, 21}, { 8, 11, 22},
+ { 8, 11, 23}, { 8, 11, 25}, { 8, 12, 1}, { 8, 13, 1},
+ { 8, 13, 2}, { 8, 13, 4}, { 8, 13, 5}, { 8, 13, 9},
+ { 8, 13, 11}, { 8, 13, 17}, { 8, 13, 19}, { 8, 13, 21},
+ { 8, 13, 23}, { 8, 14, 1}, { 8, 14, 5}, { 8, 14, 22},
+ { 8, 14, 23}, { 8, 18, 1}, { 8, 18, 5}, { 8, 18, 9},
+ { 8, 18, 19}, { 8, 18, 21}, { 8, 18, 23}, { 8, 19, 1},
+ { 8, 19, 5}, { 8, 19, 9}, { 8, 19, 19}, { 8, 19, 21},
+ { 8, 20, 1}, { 8, 20, 2}, { 8, 20, 3}, { 8, 20, 5},
+ { 8, 20, 8}, { 8, 20, 9}, { 8, 20, 10}, { 8, 20, 11},
+ { 8, 20, 17}, { 8, 20, 19}, { 8, 20, 21}, { 8, 20, 23},
+ { 8, 20, 27}, { 8, 20, 29}, { 8, 21, 1}, { 8, 21, 5},
+ { 8, 21, 9}, { 8, 21, 19}, { 8, 21, 21}, { 8, 22, 1},
+ { 8, 23, 1}, { 8, 23, 5}, { 8, 23, 9}, { 8, 26, 1},
+ { 8, 26, 5}, { 8, 26, 9}, { 8, 26, 17}, { 8, 26, 21},
+ { 8, 27, 1}, { 8, 27, 5}, { 8, 27, 9}, { 8, 27, 17},
+ { 8, 27, 21}, { 8, 29, 1}, { 8, 29, 2}, { 8, 29, 5},
+ { 8, 29, 8}, { 8, 29, 9}, { 8, 29, 11}, { 8, 29, 17},
+ { 8, 29, 19}, { 8, 29, 21}, { 8, 29, 22}, { 8, 29, 23},
+ { 8, 29, 25}, { 8, 29, 27}, { 9, 3, 1}, { 9, 3, 2},
+ { 9, 3, 3}, { 9, 3, 4}, { 9, 3, 5}, { 9, 3, 8},
+ { 9, 3, 9}, { 9, 3, 10}, { 9, 3, 11}, { 9, 3, 12},
+ { 9, 3, 17}, { 9, 3, 19}, { 9, 3, 21}, { 9, 3, 23},
+ { 9, 3, 27}, { 9, 4, 1}, { 9, 4, 2}, { 9, 4, 5},
+ { 9, 4, 9}, { 9, 4, 17}, { 9, 4, 19}, { 9, 4, 21},
+ { 9, 4, 22}, { 9, 4, 23}, { 9, 4, 27}, { 9, 5, 1},
+ { 9, 5, 2}, { 9, 5, 5}, { 9, 5, 19}, { 9, 7, 1},
+ { 9, 7, 2}, { 9, 7, 5}, { 9, 7, 8}, { 9, 7, 9},
+ { 9, 7, 11}, { 9, 7, 17}, { 9, 7, 19}, { 9, 7, 21},
+ { 9, 7, 23}, { 9, 7, 24}, { 9, 10, 1}, { 9, 10, 2},
+ { 9, 10, 5}, { 9, 10, 8}, { 9, 10, 9}, { 9, 10, 17},
+ { 9, 10, 19}, { 9, 10, 21}, { 9, 10, 22}, { 9, 10, 23},
+ { 9, 11, 1}, { 9, 11, 2}, { 9, 11, 5}, { 9, 11, 9},
+ { 9, 11, 19}, { 9, 11, 21}, { 9, 11, 22}, { 9, 11, 23},
+ { 9, 11, 27}, { 9, 12, 1}, { 9, 12, 5}, { 9, 13, 1},
+ { 9, 13, 2}, { 9, 13, 3}, { 9, 13, 5}, { 9, 13, 9},
+ { 9, 13, 17}, { 9, 13, 19}, { 9, 13, 21}, { 9, 13, 23},
+ { 9, 14, 1}, { 9, 14, 5}, { 9, 14, 22}, { 9, 15, 1},
+ { 9, 15, 22}, { 9, 18, 1}, { 9, 18, 2}, { 9, 18, 5},
+ { 9, 18, 9}, { 9, 18, 17}, { 9, 18, 19}, { 9, 19, 1},
+ { 9, 19, 5}, { 9, 20, 1}, { 9, 20, 2}, { 9, 20, 5},
+ { 9, 20, 8}, { 9, 20, 9}, { 9, 20, 10}, { 9, 20, 11},
+ { 9, 20, 17}, { 9, 20, 19}, { 9, 20, 21}, { 9, 20, 23},
+ { 9, 20, 27}, { 9, 20, 28}, { 9, 21, 1}, { 9, 21, 9},
+ { 9, 21, 22}, { 9, 22, 1}, { 9, 23, 1}, { 9, 23, 2},
+ { 9, 23, 5}, { 9, 23, 9}, { 9, 23, 23}, { 9, 26, 1},
+ { 9, 26, 5}, { 9, 26, 9}, { 9, 26, 17}, { 9, 26, 21},
+ { 9, 26, 23}, { 9, 27, 1}, { 9, 27, 2}, { 9, 27, 5},
+ { 9, 27, 9}, { 9, 27, 17}, { 9, 27, 19}, { 9, 27, 21},
+ { 9, 29, 1}, { 9, 29, 2}, { 9, 29, 5}, { 9, 29, 9},
+ { 9, 29, 11}, { 9, 29, 17}, { 9, 29, 19}, { 9, 29, 21},
+ { 9, 29, 23}, { 9, 29, 24}, { 9, 29, 25}, { 10, 3, 1},
+ { 10, 3, 2}, { 10, 3, 5}, { 10, 3, 9}, { 10, 3, 11},
+ { 10, 3, 17}, { 10, 3, 19}, { 10, 3, 21}, { 10, 3, 22},
+ { 10, 3, 23}, { 10, 3, 29}, { 10, 4, 1}, { 10, 4, 2},
+ { 10, 4, 5}, { 10, 4, 9}, { 10, 4, 17}, { 10, 4, 19},
+ { 10, 4, 21}, { 10, 4, 22}, { 10, 4, 23}, { 10, 5, 1},
+ { 10, 5, 2}, { 10, 5, 17}, { 10, 7, 1}, { 10, 7, 2},
+ { 10, 7, 5}, { 10, 7, 8}, { 10, 7, 9}, { 10, 7, 17},
+ { 10, 7, 21}, { 10, 7, 22}, { 10, 7, 23}, { 10, 10, 1},
+ { 10, 10, 23}, { 10, 11, 1}, { 10, 11, 2}, { 10, 11, 17},
+ { 10, 11, 19}, { 10, 11, 21}, { 10, 11, 22}, { 10, 11, 23},
+ { 10, 13, 1}, { 10, 13, 2}, { 10, 13, 5}, { 10, 13, 9},
+ { 10, 13, 17}, { 10, 13, 19}, { 10, 13, 23}, { 10, 18, 1},
+ { 10, 19, 1}, { 10, 19, 23}, { 10, 20, 1}, { 10, 20, 2},
+ { 10, 20, 5}, { 10, 20, 9}, { 10, 20, 17}, { 10, 20, 21},
+ { 10, 20, 23}, { 10, 26, 1}, { 10, 26, 23}, { 10, 27, 1},
+ { 10, 27, 5}, { 10, 27, 9}, { 10, 27, 17}, { 10, 27, 19},
+ { 10, 29, 1}, { 10, 29, 2}, { 10, 29, 5}, { 10, 29, 9},
+ { 10, 29, 17}, { 10, 29, 19}, { 10, 29, 21}, { 10, 29, 23},
+ { 11, 3, 1}, { 11, 3, 2}, { 11, 3, 4}, { 11, 3, 5},
+ { 11, 3, 8}, { 11, 3, 9}, { 11, 3, 10}, { 11, 3, 11},
+ { 11, 3, 17}, { 11, 3, 19}, { 11, 3, 21}, { 11, 3, 22},
+ { 11, 3, 23}, { 11, 3, 27}, { 11, 4, 1}, { 11, 4, 2},
+ { 11, 4, 5}, { 11, 4, 9}, { 11, 4, 17}, { 11, 4, 19},
+ { 11, 4, 21}, { 11, 4, 22}, { 11, 4, 23}, { 11, 5, 1},
+ { 11, 5, 2}, { 11, 5, 5}, { 11, 5, 9}, { 11, 5, 17},
+ { 11, 5, 19}, { 11, 5, 21}, { 11, 5, 23}, { 11, 6, 1},
+ { 11, 6, 5}, { 11, 6, 9}, { 11, 6, 17}, { 11, 6, 23},
+ { 11, 7, 1}, { 11, 7, 2}, { 11, 7, 3}, { 11, 7, 4},
+ { 11, 7, 5}, { 11, 7, 8}, { 11, 7, 9}, { 11, 7, 11},
+ { 11, 7, 12}, { 11, 7, 17}, { 11, 7, 19}, { 11, 7, 21},
+ { 11, 7, 22}, { 11, 7, 23}, { 11, 7, 28}, { 11, 10, 1},
+ { 11, 10, 2}, { 11, 10, 5}, { 11, 10, 9}, { 11, 10, 17},
+ { 11, 10, 19}, { 11, 10, 21}, { 11, 10, 22}, { 11, 10, 23},
+ { 11, 11, 1}, { 11, 11, 2}, { 11, 11, 5}, { 11, 11, 9},
+ { 11, 11, 17}, { 11, 11, 19}, { 11, 11, 21}, { 11, 11, 22},
+ { 11, 11, 23}, { 11, 12, 1}, { 11, 12, 5}, { 11, 12, 9},
+ { 11, 12, 23}, { 11, 13, 1}, { 11, 13, 2}, { 11, 13, 3},
+ { 11, 13, 5}, { 11, 13, 9}, { 11, 13, 11}, { 11, 13, 17},
+ { 11, 13, 19}, { 11, 13, 21}, { 11, 13, 23}, { 11, 13, 27},
+ { 11, 14, 1}, { 11, 14, 2}, { 11, 14, 5}, { 11, 14, 9},
+ { 11, 14, 23}, { 11, 15, 1}, { 11, 15, 5}, { 11, 15, 9},
+ { 11, 15, 17}, { 11, 15, 21}, { 11, 15, 22}, { 11, 18, 1},
+ { 11, 18, 5}, { 11, 18, 9}, { 11, 18, 17}, { 11, 18, 19},
+ { 11, 18, 21}, { 11, 19, 1}, { 11, 19, 2}, { 11, 19, 5},
+ { 11, 19, 9}, { 11, 19, 17}, { 11, 19, 19}, { 11, 19, 21},
+ { 11, 19, 23}, { 11, 20, 1}, { 11, 20, 2}, { 11, 20, 5},
+ { 11, 20, 8}, { 11, 20, 9}, { 11, 20, 17}, { 11, 20, 19},
+ { 11, 20, 21}, { 11, 20, 23}, { 11, 20, 25}, { 11, 20, 27},
+ { 11, 20, 28}, { 11, 21, 1}, { 11, 21, 22}, { 11, 22, 1},
+ { 11, 22, 2}, { 11, 22, 5}, { 11, 22, 9}, { 11, 22, 17},
+ { 11, 22, 23}, { 11, 23, 1}, { 11, 23, 2}, { 11, 23, 5},
+ { 11, 23, 9}, { 11, 23, 17}, { 11, 23, 19}, { 11, 23, 21},
+ { 11, 23, 23}, { 11, 26, 1}, { 11, 26, 2}, { 11, 26, 9},
+ { 11, 26, 17}, { 11, 26, 21}, { 11, 26, 23}, { 11, 27, 1},
+ { 11, 27, 2}, { 11, 27, 5}, { 11, 27, 9}, { 11, 27, 10},
+ { 11, 27, 17}, { 11, 27, 19}, { 11, 27, 21}, { 11, 27, 23},
+ { 11, 29, 1}, { 11, 29, 2}, { 11, 29, 5}, { 11, 29, 8},
+ { 11, 29, 9}, { 11, 29, 16}, { 11, 29, 17}, { 11, 29, 19},
+ { 11, 29, 21}, { 11, 29, 23}, { 11, 29, 28}, { 12, 3, 1},
+ { 12, 3, 2}, { 12, 3, 4}, { 12, 3, 5}, { 12, 3, 9},
+ { 12, 3, 17}, { 12, 3, 19}, { 12, 3, 22}, { 12, 3, 23},
+ { 12, 3, 29}, { 12, 4, 1}, { 12, 4, 2}, { 12, 4, 5},
+ { 12, 4, 9}, { 12, 4, 17}, { 12, 4, 19}, { 12, 4, 22},
+ { 12, 4, 23}, { 12, 5, 23}, { 12, 7, 1}, { 12, 7, 2},
+ { 12, 7, 5}, { 12, 7, 9}, { 12, 7, 11}, { 12, 7, 17},
+ { 12, 7, 19}, { 12, 7, 22}, { 12, 7, 23}, { 12, 10, 1},
+ { 12, 10, 5}, { 12, 10, 9}, { 12, 12, 5}, { 12, 13, 1},
+ { 12, 13, 2}, { 12, 13, 5}, { 12, 13, 8}, { 12, 13, 9},
+ { 12, 13, 11}, { 12, 13, 17}, { 12, 13, 19}, { 12, 13, 23},
+ { 12, 14, 1}, { 12, 14, 2}, { 12, 14, 5}, { 12, 14, 22},
+ { 12, 15, 1}, { 12, 15, 22}, { 12, 18, 1}, { 12, 18, 5},
+ { 12, 18, 9}, { 12, 18, 17}, { 12, 18, 19}, { 12, 19, 1},
+ { 12, 20, 1}, { 12, 20, 2}, { 12, 20, 5}, { 12, 20, 9},
+ { 12, 20, 17}, { 12, 20, 19}, { 12, 20, 23}, { 12, 21, 1},
+ { 12, 21, 22}, { 12, 22, 1}, { 12, 23, 1}, { 12, 23, 5},
+ { 12, 26, 23}, { 12, 27, 1}, { 12, 27, 2}, { 12, 27, 5},
+ { 12, 27, 9}, { 12, 27, 11}, { 12, 27, 16}, { 12, 27, 17},
+ { 12, 27, 19}, { 12, 28, 1}, { 12, 28, 5}, { 12, 28, 9},
+ { 12, 28, 17}, { 12, 29, 1}, { 12, 29, 2}, { 12, 29, 5},
+ { 12, 29, 9}, { 12, 29, 17}, { 12, 29, 19}, { 12, 29, 21},
+ { 12, 29, 23}, { 13, 3, 1}, { 13, 3, 2}, { 13, 3, 5},
+ { 13, 3, 6}, { 13, 3, 7}, { 13, 3, 9}, { 13, 3, 10},
+ { 13, 3, 11}, { 13, 3, 16}, { 13, 3, 17}, { 13, 3, 19},
+ { 13, 3, 21}, { 13, 3, 22}, { 13, 3, 23}, { 13, 3, 27},
+ { 13, 3, 28}, { 13, 4, 1}, { 13, 4, 2}, { 13, 4, 5},
+ { 13, 4, 9}, { 13, 4, 17}, { 13, 4, 19}, { 13, 4, 21},
+ { 13, 4, 22}, { 13, 4, 23}, { 13, 5, 1}, { 13, 5, 2},
+ { 13, 5, 5}, { 13, 5, 9}, { 13, 5, 12}, { 13, 5, 17},
+ { 13, 5, 19}, { 13, 5, 21}, { 13, 5, 23}, { 13, 5, 27},
+ { 13, 5, 29}, { 13, 6, 1}, { 13, 6, 5}, { 13, 6, 9},
+ { 13, 6, 19}, { 13, 7, 1}, { 13, 7, 2}, { 13, 7, 5},
+ { 13, 7, 6}, { 13, 7, 8}, { 13, 7, 9}, { 13, 7, 10},
+ { 13, 7, 11}, { 13, 7, 17}, { 13, 7, 19}, { 13, 7, 20},
+ { 13, 7, 21}, { 13, 7, 22}, { 13, 7, 23}, { 13, 7, 24},
+ { 13, 7, 26}, { 13, 7, 28}, { 13, 10, 1}, { 13, 10, 2},
+ { 13, 10, 5}, { 13, 10, 9}, { 13, 10, 17}, { 13, 10, 19},
+ { 13, 10, 21}, { 13, 10, 23}, { 13, 11, 1}, { 13, 11, 2},
+ { 13, 11, 3}, { 13, 11, 5}, { 13, 11, 9}, { 13, 11, 11},
+ { 13, 11, 12}, { 13, 11, 17}, { 13, 11, 19}, { 13, 11, 20},
+ { 13, 11, 21}, { 13, 11, 22}, { 13, 11, 23}, { 13, 11, 27},
+ { 13, 11, 28}, { 13, 11, 29}, { 13, 12, 1}, { 13, 12, 5},
+ { 13, 12, 9}, { 13, 12, 17}, { 13, 12, 19}, { 13, 12, 21},
+ { 13, 12, 22}, { 13, 13, 1}, { 13, 13, 2}, { 13, 13, 5},
+ { 13, 13, 9}, { 13, 13, 10}, { 13, 13, 11}, { 13, 13, 13},
+ { 13, 13, 16}, { 13, 13, 17}, { 13, 13, 19}, { 13, 13, 21},
+ { 13, 13, 23}, { 13, 13, 25}, { 13, 14, 1}, { 13, 14, 2},
+ { 13, 14, 5}, { 13, 14, 9}, { 13, 14, 17}, { 13, 14, 19},
+ { 13, 14, 21}, { 13, 14, 22}, { 13, 14, 23}, { 13, 15, 1},
+ { 13, 15, 2}, { 13, 15, 5}, { 13, 15, 17}, { 13, 15, 21},
+ { 13, 15, 23}, { 13, 18, 1}, { 13, 18, 2}, { 13, 18, 5},
+ { 13, 18, 9}, { 13, 18, 17}, { 13, 18, 19}, { 13, 18, 21},
+ { 13, 18, 23}, { 13, 19, 1}, { 13, 19, 2}, { 13, 19, 5},
+ { 13, 19, 9}, { 13, 19, 17}, { 13, 19, 19}, { 13, 19, 21},
+ { 13, 19, 23}, { 13, 20, 1}, { 13, 20, 2}, { 13, 20, 5},
+ { 13, 20, 9}, { 13, 20, 10}, { 13, 20, 11}, { 13, 20, 17},
+ { 13, 20, 19}, { 13, 20, 21}, { 13, 20, 23}, { 13, 21, 1},
+ { 13, 21, 2}, { 13, 21, 5}, { 13, 21, 9}, { 13, 21, 17},
+ { 13, 21, 19}, { 13, 21, 22}, { 13, 21, 23}, { 13, 22, 1},
+ { 13, 22, 2}, { 13, 22, 5}, { 13, 22, 9}, { 13, 22, 17},
+ { 13, 22, 19}, { 13, 22, 23}, { 13, 23, 1}, { 13, 23, 2},
+ { 13, 23, 5}, { 13, 23, 9}, { 13, 23, 17}, { 13, 23, 19},
+ { 13, 23, 21}, { 13, 23, 23}, { 13, 26, 1}, { 13, 26, 2},
+ { 13, 26, 5}, { 13, 26, 9}, { 13, 26, 17}, { 13, 26, 19},
+ { 13, 26, 21}, { 13, 26, 23}, { 13, 26, 25}, { 13, 27, 1},
+ { 13, 27, 2}, { 13, 27, 5}, { 13, 27, 9}, { 13, 27, 15},
+ { 13, 27, 17}, { 13, 27, 19}, { 13, 27, 21}, { 13, 27, 23},
+ { 13, 27, 24}, { 13, 27, 25}, { 13, 27, 26}, { 13, 27, 27},
+ { 13, 27, 28}, { 13, 27, 29}, { 13, 28, 1}, { 13, 28, 5},
+ { 13, 28, 9}, { 13, 28, 17}, { 13, 28, 21}, { 13, 29, 1},
+ { 13, 29, 2}, { 13, 29, 5}, { 13, 29, 9}, { 13, 29, 10},
+ { 13, 29, 11}, { 13, 29, 16}, { 13, 29, 17}, { 13, 29, 19},
+ { 13, 29, 21}, { 13, 29, 22}, { 13, 29, 23}, { 13, 29, 24},
+ { 13, 29, 28}, { 14, 3, 1}, { 14, 3, 2}, { 14, 3, 5},
+ { 14, 3, 7}, { 14, 3, 8}, { 14, 3, 9}, { 14, 3, 11},
+ { 14, 3, 17}, { 14, 3, 19}, { 14, 3, 21}, { 14, 3, 22},
+ { 14, 3, 23}, { 14, 3, 24}, { 14, 4, 1}, { 14, 4, 2},
+ { 14, 4, 5}, { 14, 4, 9}, { 14, 4, 17}, { 14, 4, 19},
+ { 14, 4, 21}, { 14, 4, 22}, { 14, 4, 23}, { 14, 5, 1},
+ { 14, 5, 2}, { 14, 5, 5}, { 14, 5, 7}, { 14, 5, 9},
+ { 14, 5, 17}, { 14, 5, 23}, { 14, 6, 1}, { 14, 6, 5},
+ { 14, 6, 9}, { 14, 7, 1}, { 14, 7, 2}, { 14, 7, 5},
+ { 14, 7, 9}, { 14, 7, 11}, { 14, 7, 17}, { 14, 7, 19},
+ { 14, 7, 21}, { 14, 7, 23}, { 14, 7, 24}, { 14, 10, 1},
+ { 14, 10, 2}, { 14, 10, 5}, { 14, 10, 9}, { 14, 10, 17},
+ { 14, 10, 19}, { 14, 10, 21}, { 14, 10, 23}, { 14, 11, 1},
+ { 14, 11, 5}, { 14, 11, 9}, { 14, 11, 17}, { 14, 11, 19},
+ { 14, 11, 22}, { 14, 11, 23}, { 14, 12, 1}, { 14, 13, 1},
+ { 14, 13, 2}, { 14, 13, 5}, { 14, 13, 9}, { 14, 13, 11},
+ { 14, 13, 17}, { 14, 13, 19}, { 14, 13, 21}, { 14, 13, 23},
+ { 14, 13, 24}, { 14, 13, 25}, { 14, 13, 29}, { 14, 14, 1},
+ { 14, 14, 2}, { 14, 14, 9}, { 14, 14, 19}, { 14, 14, 21},
+ { 14, 14, 23}, { 14, 15, 1}, { 14, 15, 22}, { 14, 15, 23},
+ { 14, 18, 1}, { 14, 18, 5}, { 14, 18, 9}, { 14, 18, 17},
+ { 14, 18, 19}, { 14, 18, 21}, { 14, 18, 23}, { 14, 19, 1},
+ { 14, 19, 2}, { 14, 19, 5}, { 14, 19, 23}, { 14, 20, 1},
+ { 14, 20, 2}, { 14, 20, 5}, { 14, 20, 9}, { 14, 20, 10},
+ { 14, 20, 11}, { 14, 20, 17}, { 14, 20, 19}, { 14, 20, 21},
+ { 14, 20, 23}, { 14, 21, 1}, { 14, 21, 22}, { 14, 22, 1},
+ { 14, 23, 1}, { 14, 23, 2}, { 14, 23, 5}, { 14, 23, 9},
+ { 14, 23, 17}, { 14, 23, 19}, { 14, 23, 21}, { 14, 26, 1},
+ { 14, 26, 5}, { 14, 26, 9}, { 14, 26, 17}, { 14, 27, 1},
+ { 14, 27, 2}, { 14, 27, 5}, { 14, 27, 9}, { 14, 27, 17},
+ { 14, 27, 19}, { 14, 27, 21}, { 14, 27, 23}, { 14, 29, 1},
+ { 14, 29, 2}, { 14, 29, 5}, { 14, 29, 8}, { 14, 29, 9},
+ { 14, 29, 11}, { 14, 29, 17}, { 14, 29, 19}, { 14, 29, 21},
+ { 14, 29, 23}, { 14, 29, 24}, { 14, 29, 27}, { 14, 29, 28},
+ { 15, 3, 1}, { 15, 3, 2}, { 15, 3, 5}, { 15, 3, 7},
+ { 15, 3, 9}, { 15, 3, 12}, { 15, 3, 17}, { 15, 3, 19},
+ { 15, 3, 21}, { 15, 3, 22}, { 15, 3, 23}, { 15, 4, 1},
+ { 15, 4, 2}, { 15, 4, 5}, { 15, 4, 9}, { 15, 4, 17},
+ { 15, 4, 19}, { 15, 4, 21}, { 15, 4, 22}, { 15, 4, 23},
+ { 15, 5, 1}, { 15, 5, 5}, { 15, 5, 23}, { 15, 7, 1},
+ { 15, 7, 2}, { 15, 7, 5}, { 15, 7, 9}, { 15, 7, 17},
+ { 15, 7, 19}, { 15, 7, 21}, { 15, 7, 22}, { 15, 7, 23},
+ { 15, 10, 1}, { 15, 10, 23}, { 15, 11, 1}, { 15, 11, 22},
+ { 15, 13, 1}, { 15, 13, 2}, { 15, 13, 5}, { 15, 13, 9},
+ { 15, 13, 17}, { 15, 13, 19}, { 15, 13, 21}, { 15, 13, 23},
+ { 15, 13, 25}, { 15, 14, 1}, { 15, 14, 2}, { 15, 14, 9},
+ { 15, 14, 22}, { 15, 15, 1}, { 15, 15, 22}, { 15, 18, 1},
+ { 15, 18, 5}, { 15, 18, 9}, { 15, 18, 17}, { 15, 18, 19},
+ { 15, 19, 23}, { 15, 20, 1}, { 15, 20, 2}, { 15, 20, 5},
+ { 15, 20, 9}, { 15, 20, 17}, { 15, 20, 19}, { 15, 20, 23},
+ { 15, 21, 1}, { 15, 21, 22}, { 15, 21, 23}, { 15, 23, 1},
+ { 15, 26, 1}, { 15, 27, 1}, { 15, 27, 17}, { 15, 27, 21},
+ { 15, 27, 23}, { 15, 29, 1}, { 15, 29, 2}, { 15, 29, 5},
+ { 15, 29, 9}, { 15, 29, 17}, { 15, 29, 19}, { 15, 29, 23},
+ { 15, 29, 24}, { 15, 29, 29}, { 16, 3, 1}, { 16, 3, 2},
+ { 16, 3, 5}, { 16, 3, 7}, { 16, 3, 9}, { 16, 3, 17},
+ { 16, 3, 19}, { 16, 3, 21}, { 16, 3, 22}, { 16, 3, 23},
+ { 16, 3, 24}, { 16, 4, 1}, { 16, 4, 2}, { 16, 4, 5},
+ { 16, 4, 9}, { 16, 4, 17}, { 16, 4, 19}, { 16, 4, 21},
+ { 16, 4, 22}, { 16, 4, 23}, { 16, 5, 1}, { 16, 5, 5},
+ { 16, 5, 7}, { 16, 5, 9}, { 16, 5, 17}, { 16, 5, 23},
+ { 16, 7, 1}, { 16, 7, 2}, { 16, 7, 5}, { 16, 7, 9},
+ { 16, 7, 17}, { 16, 7, 19}, { 16, 7, 21}, { 16, 7, 22},
+ { 16, 7, 23}, { 16, 10, 1}, { 16, 10, 2}, { 16, 10, 5},
+ { 16, 10, 9}, { 16, 10, 17}, { 16, 10, 19}, { 16, 10, 21},
+ { 16, 10, 23}, { 16, 11, 1}, { 16, 11, 5}, { 16, 11, 22},
+ { 16, 12, 1}, { 16, 12, 5}, { 16, 12, 23}, { 16, 13, 1},
+ { 16, 13, 2}, { 16, 13, 5}, { 16, 13, 9}, { 16, 13, 17},
+ { 16, 13, 19}, { 16, 13, 21}, { 16, 13, 23}, { 16, 14, 1},
+ { 16, 14, 5}, { 16, 14, 9}, { 16, 14, 23}, { 16, 18, 1},
+ { 16, 18, 5}, { 16, 18, 9}, { 16, 18, 17}, { 16, 18, 19},
+ { 16, 18, 21}, { 16, 18, 23}, { 16, 19, 1}, { 16, 19, 17},
+ { 16, 20, 1}, { 16, 20, 2}, { 16, 20, 5}, { 16, 20, 9},
+ { 16, 20, 17}, { 16, 20, 19}, { 16, 20, 21}, { 16, 20, 23},
+ { 16, 21, 1}, { 16, 21, 22}, { 16, 22, 1}, { 16, 22, 5},
+ { 16, 23, 1}, { 16, 23, 5}, { 16, 23, 9}, { 16, 23, 17},
+ { 16, 23, 19}, { 16, 23, 21}, { 16, 23, 23}, { 16, 26, 1},
+ { 16, 26, 5}, { 16, 26, 9}, { 16, 26, 17}, { 16, 26, 23},
+ { 16, 27, 1}, { 16, 27, 2}, { 16, 27, 5}, { 16, 27, 9},
+ { 16, 27, 17}, { 16, 27, 19}, { 16, 27, 21}, { 16, 27, 23},
+ { 16, 29, 1}, { 16, 29, 2}, { 16, 29, 5}, { 16, 29, 8},
+ { 16, 29, 9}, { 16, 29, 10}, { 16, 29, 17}, { 16, 29, 19},
+ { 16, 29, 21}, { 16, 29, 23}, { 17, 3, 1}, { 17, 3, 2},
+ { 17, 3, 5}, { 17, 3, 9}, { 17, 3, 17}, { 17, 3, 19},
+ { 17, 3, 21}, { 17, 3, 23}, { 17, 4, 1}, { 17, 4, 2},
+ { 17, 4, 5}, { 17, 4, 9}, { 17, 4, 17}, { 17, 4, 19},
+ { 17, 4, 21}, { 17, 4, 22}, { 17, 4, 23}, { 17, 5, 1},
+ { 17, 5, 2}, { 17, 5, 23}, { 17, 7, 1}, { 17, 7, 2},
+ { 17, 7, 5}, { 17, 7, 8}, { 17, 7, 9}, { 17, 7, 17},
+ { 17, 7, 19}, { 17, 7, 21}, { 17, 7, 22}, { 17, 7, 23},
+ { 17, 10, 1}, { 17, 10, 2}, { 17, 10, 5}, { 17, 10, 9},
+ { 17, 10, 17}, { 17, 10, 19}, { 17, 10, 21}, { 17, 10, 23},
+ { 17, 11, 1}, { 17, 11, 5}, { 17, 11, 9}, { 17, 11, 17},
+ { 17, 11, 19}, { 17, 11, 21}, { 17, 11, 22}, { 17, 11, 23},
+ { 17, 12, 1}, { 17, 13, 1}, { 17, 13, 2}, { 17, 13, 5},
+ { 17, 13, 9}, { 17, 13, 17}, { 17, 13, 19}, { 17, 13, 21},
+ { 17, 13, 23}, { 17, 14, 1}, { 17, 14, 2}, { 17, 14, 5},
+ { 17, 14, 9}, { 17, 14, 17}, { 17, 14, 23}, { 17, 15, 1},
+ { 17, 15, 23}, { 17, 18, 1}, { 17, 18, 9}, { 17, 19, 1},
+ { 17, 20, 1}, { 17, 20, 2}, { 17, 20, 5}, { 17, 20, 9},
+ { 17, 20, 17}, { 17, 20, 19}, { 17, 20, 21}, { 17, 20, 23},
+ { 17, 21, 1}, { 17, 21, 5}, { 17, 21, 9}, { 17, 21, 23},
+ { 17, 22, 1}, { 17, 22, 23}, { 17, 23, 1}, { 17, 23, 2},
+ { 17, 23, 5}, { 17, 23, 9}, { 17, 23, 17}, { 17, 23, 19},
+ { 17, 23, 21}, { 17, 23, 23}, { 17, 26, 1}, { 17, 26, 5},
+ { 17, 26, 9}, { 17, 26, 17}, { 17, 27, 1}, { 17, 27, 2},
+ { 17, 27, 5}, { 17, 27, 9}, { 17, 27, 17}, { 17, 27, 19},
+ { 17, 27, 23}, { 17, 29, 1}, { 17, 29, 2}, { 17, 29, 5},
+ { 17, 29, 9}, { 17, 29, 17}, { 17, 29, 19}, { 17, 29, 21},
+ { 17, 29, 23}, { 18, 3, 1}, { 18, 3, 2}, { 18, 3, 5},
+ { 18, 3, 9}, { 18, 3, 10}, { 18, 3, 17}, { 18, 3, 19},
+ { 18, 3, 21}, { 18, 3, 22}, { 18, 3, 23}, { 18, 4, 1},
+ { 18, 4, 2}, { 18, 4, 5}, { 18, 4, 9}, { 18, 4, 17},
+ { 18, 4, 19}, { 18, 4, 21}, { 18, 4, 22}, { 18, 4, 23},
+ { 18, 5, 1}, { 18, 5, 23}, { 18, 7, 1}, { 18, 7, 2},
+ { 18, 7, 5}, { 18, 7, 9}, { 18, 7, 11}, { 18, 7, 17},
+ { 18, 7, 19}, { 18, 7, 21}, { 18, 7, 22}, { 18, 7, 23},
+ { 18, 10, 1}, { 18, 10, 2}, { 18, 10, 5}, { 18, 10, 9},
+ { 18, 10, 17}, { 18, 10, 19}, { 18, 10, 21}, { 18, 10, 23},
+ { 18, 11, 1}, { 18, 11, 5}, { 18, 11, 22}, { 18, 12, 1},
+ { 18, 12, 5}, { 18, 13, 1}, { 18, 13, 2}, { 18, 13, 5},
+ { 18, 13, 9}, { 18, 13, 17}, { 18, 13, 19}, { 18, 13, 21},
+ { 18, 13, 23}, { 18, 13, 28}, { 18, 14, 1}, { 18, 14, 5},
+ { 18, 15, 1}, { 18, 18, 1}, { 18, 18, 5}, { 18, 18, 21},
+ { 18, 18, 23}, { 18, 19, 1}, { 18, 20, 1}, { 18, 20, 2},
+ { 18, 20, 5}, { 18, 20, 9}, { 18, 20, 17}, { 18, 20, 19},
+ { 18, 20, 21}, { 18, 20, 23}, { 18, 21, 1}, { 18, 21, 22},
+ { 18, 22, 1}, { 18, 23, 1}, { 18, 23, 2}, { 18, 23, 5},
+ { 18, 23, 9}, { 18, 23, 17}, { 18, 23, 19}, { 18, 23, 23},
+ { 18, 26, 1}, { 18, 26, 5}, { 18, 26, 9}, { 18, 26, 17},
+ { 18, 26, 23}, { 18, 27, 1}, { 18, 27, 2}, { 18, 27, 5},
+ { 18, 27, 8}, { 18, 27, 9}, { 18, 27, 11}, { 18, 27, 17},
+ { 18, 27, 19}, { 18, 27, 21}, { 18, 28, 1}, { 18, 28, 5},
+ { 18, 28, 9}, { 18, 28, 17}, { 18, 28, 19}, { 18, 29, 1},
+ { 18, 29, 2}, { 18, 29, 5}, { 18, 29, 9}, { 18, 29, 17},
+ { 18, 29, 19}, { 18, 29, 21}, { 18, 29, 23}, { 19, 3, 1},
+ { 19, 3, 2}, { 19, 3, 3}, { 19, 3, 5}, { 19, 3, 9},
+ { 19, 3, 11}, { 19, 3, 17}, { 19, 3, 19}, { 19, 3, 21},
+ { 19, 3, 22}, { 19, 3, 23}, { 19, 3, 27}, { 19, 4, 1},
+ { 19, 4, 2}, { 19, 4, 5}, { 19, 4, 9}, { 19, 4, 17},
+ { 19, 4, 19}, { 19, 4, 21}, { 19, 4, 22}, { 19, 4, 23},
+ { 19, 5, 1}, { 19, 5, 2}, { 19, 7, 1}, { 19, 7, 2},
+ { 19, 7, 5}, { 19, 7, 9}, { 19, 7, 17}, { 19, 7, 19},
+ { 19, 7, 21}, { 19, 7, 22}, { 19, 7, 23}, { 19, 10, 1},
+ { 19, 10, 2}, { 19, 10, 5}, { 19, 10, 9}, { 19, 10, 17},
+ { 19, 10, 19}, { 19, 10, 21}, { 19, 10, 23}, { 19, 11, 1},
+ { 19, 11, 5}, { 19, 11, 9}, { 19, 11, 17}, { 19, 11, 19},
+ { 19, 11, 22}, { 19, 11, 23}, { 19, 12, 1}, { 19, 12, 9},
+ { 19, 12, 19}, { 19, 12, 21}, { 19, 13, 1}, { 19, 13, 2},
+ { 19, 13, 5}, { 19, 13, 9}, { 19, 13, 17}, { 19, 13, 19},
+ { 19, 13, 21}, { 19, 13, 23}, { 19, 14, 1}, { 19, 14, 23},
+ { 19, 18, 1}, { 19, 18, 5}, { 19, 19, 1}, { 19, 19, 5},
+ { 19, 19, 9}, { 19, 19, 19}, { 19, 19, 21}, { 19, 20, 1},
+ { 19, 20, 2}, { 19, 20, 5}, { 19, 20, 8}, { 19, 20, 9},
+ { 19, 20, 11}, { 19, 20, 17}, { 19, 20, 19}, { 19, 20, 21},
+ { 19, 20, 23}, { 19, 21, 1}, { 19, 21, 23}, { 19, 23, 1},
+ { 19, 23, 5}, { 19, 23, 9}, { 19, 23, 17}, { 19, 23, 21},
+ { 19, 26, 1}, { 19, 26, 5}, { 19, 26, 9}, { 19, 26, 17},
+ { 19, 26, 21}, { 19, 26, 23}, { 19, 27, 1}, { 19, 27, 5},
+ { 19, 27, 9}, { 19, 27, 17}, { 19, 27, 19}, { 19, 27, 21},
+ { 19, 29, 1}, { 19, 29, 2}, { 19, 29, 5}, { 19, 29, 9},
+ { 19, 29, 17}, { 19, 29, 19}, { 19, 29, 21}, { 19, 29, 23},
+ { 20, 3, 1}, { 20, 3, 2}, { 20, 3, 5}, { 20, 3, 9},
+ { 20, 3, 14}, { 20, 3, 17}, { 20, 3, 19}, { 20, 3, 21},
+ { 20, 3, 23}, { 20, 4, 1}, { 20, 4, 2}, { 20, 4, 5},
+ { 20, 4, 9}, { 20, 4, 17}, { 20, 4, 19}, { 20, 4, 21},
+ { 20, 4, 22}, { 20, 4, 23}, { 20, 5, 1}, { 20, 5, 23},
+ { 20, 7, 1}, { 20, 7, 2}, { 20, 7, 5}, { 20, 7, 9},
+ { 20, 7, 11}, { 20, 7, 17}, { 20, 7, 19}, { 20, 7, 21},
+ { 20, 7, 23}, { 20, 10, 1}, { 20, 10, 2}, { 20, 10, 5},
+ { 20, 10, 9}, { 20, 10, 17}, { 20, 10, 19}, { 20, 10, 21},
+ { 20, 10, 23}, { 20, 11, 1}, { 20, 11, 2}, { 20, 11, 5},
+ { 20, 11, 9}, { 20, 11, 17}, { 20, 11, 19}, { 20, 11, 21},
+ { 20, 11, 22}, { 20, 11, 23}, { 20, 12, 1}, { 20, 12, 5},
+ { 20, 12, 9}, { 20, 12, 19}, { 20, 13, 1}, { 20, 13, 2},
+ { 20, 13, 5}, { 20, 13, 9}, { 20, 13, 14}, { 20, 13, 17},
+ { 20, 13, 19}, { 20, 13, 21}, { 20, 13, 23}, { 20, 13, 27},
+ { 20, 14, 1}, { 20, 14, 2}, { 20, 14, 5}, { 20, 14, 9},
+ { 20, 14, 21}, { 20, 14, 23}, { 20, 15, 1}, { 20, 15, 2},
+ { 20, 15, 5}, { 20, 15, 21}, { 20, 15, 23}, { 20, 18, 1},
+ { 20, 18, 2}, { 20, 18, 5}, { 20, 18, 9}, { 20, 18, 19},
+ { 20, 18, 21}, { 20, 18, 23}, { 20, 19, 1}, { 20, 19, 5},
+ { 20, 19, 9}, { 20, 19, 19}, { 20, 19, 21}, { 20, 20, 1},
+ { 20, 20, 2}, { 20, 20, 5}, { 20, 20, 9}, { 20, 20, 14},
+ { 20, 20, 17}, { 20, 20, 21}, { 20, 20, 23}, { 20, 21, 1},
+ { 20, 21, 5}, { 20, 21, 9}, { 20, 21, 17}, { 20, 21, 23},
+ { 20, 22, 1}, { 20, 22, 2}, { 20, 22, 5}, { 20, 22, 9},
+ { 20, 22, 23}, { 20, 23, 1}, { 20, 23, 2}, { 20, 23, 5},
+ { 20, 23, 9}, { 20, 23, 17}, { 20, 23, 19}, { 20, 23, 21},
+ { 20, 23, 23}, { 20, 26, 1}, { 20, 26, 2}, { 20, 26, 5},
+ { 20, 26, 9}, { 20, 26, 17}, { 20, 26, 21}, { 20, 26, 23},
+ { 20, 27, 1}, { 20, 27, 2}, { 20, 27, 5}, { 20, 27, 7},
+ { 20, 27, 8}, { 20, 27, 9}, { 20, 27, 10}, { 20, 27, 17},
+ { 20, 27, 19}, { 20, 27, 21}, { 20, 27, 23}, { 20, 27, 27},
+ { 20, 28, 1}, { 20, 28, 5}, { 20, 28, 9}, { 20, 28, 17},
+ { 20, 28, 19}, { 20, 28, 23}, { 20, 29, 1}, { 20, 29, 2},
+ { 20, 29, 5}, { 20, 29, 9}, { 20, 29, 17}, { 20, 29, 19},
+ { 20, 29, 21}, { 20, 29, 23},
+};
+
+
+static const unsigned short ks_table2[][4] =
+{
+ {0xa4bf, 1, 3, 1}, {0xa4c0, 1, 4, 1},
+ {0xa4c1, 1, 5, 1}, {0xa4c2, 1, 6, 1},
+ {0xa4c3, 1, 7, 1}, {0xa4c4, 1, 10, 1},
+ {0xa4c5, 1, 11, 1}, {0xa4c6, 1, 12, 1},
+ {0xa4c7, 1, 13, 1}, {0xa4c8, 1, 14, 1},
+ {0xa4c9, 1, 15, 1}, {0xa4ca, 1, 18, 1},
+ {0xa4cb, 1, 19, 1}, {0xa4cc, 1, 20, 1},
+ {0xa4cd, 1, 21, 1}, {0xa4ce, 1, 22, 1},
+ {0xa4cf, 1, 23, 1}, {0xa4d0, 1, 26, 1},
+ {0xa4d1, 1, 27, 1}, {0xa4d2, 1, 28, 1},
+ {0xa4d3, 1, 29, 1}, {0xa4a1, 2, 2, 1},
+ {0xa4a2, 3, 2, 1}, {0xa4a4, 4, 2, 1},
+ {0xa4a7, 5, 2, 1}, {0xa4a8, 6, 2, 1},
+ {0xa4a9, 7, 2, 1}, {0xa4b1, 8, 2, 1},
+ {0xa4b2, 9, 2, 1}, {0xa4b3, 10, 2, 1},
+ {0xa4b5, 11, 2, 1}, {0xa4b6, 12, 2, 1},
+ {0xa4b7, 13, 2, 1}, {0xa4b8, 14, 2, 1},
+ {0xa4b9, 15, 2, 1}, {0xa4ba, 16, 2, 1},
+ {0xa4bb, 17, 2, 1}, {0xa4bc, 18, 2, 1},
+ {0xa4bd, 19, 2, 1}, {0xa4be, 20, 2, 1},
+};
+
+/* Á¶ÇÕÇü Ãʼº - ¿Ï¼ºÇü ³¹ÀÚ º¯È¯
+ * conversion: initial sound of compound type - ??? of completion type
+ */
+
+static const char_u johab_fcon_to_wan[] =
+{
+ 0,
+ 0xd4, 0xa1, 0xa2, 0xa4, 0xa7, /* (ä¿ò),¤¡,¤¢,¤¤,¤§ */
+ 0xa8, 0xa9, 0xb1, 0xb2, 0xb3, /* ¤¨,¤©,¤±,¤²,¤³ */
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, /* ¤µ,¤¶,¤·,¤¸,¤¹ */
+ 0xba, 0xbb, 0xbc, 0xbd, 0xbe /* ¤º,¤»,¤¼,¤½,¤¾ */
+};
+
+/* Á¶ÇÕÇü Áß¼º -> ¿Ï¼ºÇü ³¹ÀÚ º¯È¯
+ * conversion: medial vowel of compound type - ??? of completion type
+ */
+
+static const char_u johab_vow_to_wan[] =
+{
+ 0, 0,
+ 0xd4, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, /* (ä¿ò),¤¿,¤À,¤Á,¤Â,¤Ã */
+ 0, 0,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, /* ¤Ä,¤Å,¤Æ,¤Ç,¤Ç¤¿,¤Ç¤À */
+ 0, 0,
+ 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* ¤Ç¤Ó,¤Ë,¤Ì,¤Ì¤Ã,¤Ì¤Ä,¤Ì¤Ó */
+ 0, 0,
+ 0xd0, 0xd1, 0xd2, 0xd3 /* ¤Ð,¤Ñ,¤Ñ¤Ó,¤Ó */
+};
+
+/* Á¶ÇÕÇü Á¾¼º -> ¿Ï¼ºÇü ³¹ÀÚ º¯È¯
+ * conversion: final consonant of compound type - ??? of completion type
+ */
+
+static const char_u johab_lcon_to_wan[] =
+{
+ 0,
+ 0xd4, 0xa1, 0xa2, 0xa3, 0xa4, /* (ä¿ò), ¤¡, ¤¢, ¤¡¤µ, ¤¤ */
+ 0xa5, 0xa6, 0xa7, 0xa9, 0xaa, /* ¤¤¤¸, ¤¤¤¾, ¤§, ¤©, ¤©¤¡ */
+ 0xab, 0xac, 0xad, 0xae, 0xaf, /* ¤©¤±, ¤©¤², ¤©¤µ, ¤©¤¼, ¤©¤½ */
+ 0xb0, 0xb1, 0, 0xb2, 0xb4, /* ¤©¤¾, ¤±, 0, ¤², ¤²¤µ */
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xba, /* ¤µ, ¤¶, ¤·, ¤¸, ¤º */
+ 0xbb, 0xbc, 0xbd, 0xbe /* ¤», ¤¼, ¤½, ¤¾ */
+};
+
+ static void
+convert_ks_to_3(src, fp, mp, lp)
+ const char_u *src;
+ int *fp;
+ int *mp;
+ int *lp;
+{
+ int h = *src;
+ int low = *(src + 1);
+ int c;
+ int i;
+
+ if ((i = han_index(h, low)) >= 0
+ && i < sizeof(ks_table1)/sizeof(ks_table1[0]))
+ {
+ *fp = ks_table1[i][0];
+ *mp = ks_table1[i][1];
+ *lp = ks_table1[i][2];
+ }
+ else
+ {
+ c = (h << 8) | low;
+ for (i = 0; i < 40; i++)
+ if (ks_table2[i][0] == c)
+ {
+ *fp = ks_table2[i][1];
+ *mp = ks_table2[i][2];
+ *lp = ks_table2[i][3];
+ return;
+ }
+ *fp = 0xff; /* ±×·¡ÇÈ ÄÚµå (graphic code) */
+ *mp = h;
+ *lp = low;
+ }
+}
+
+ static int
+convert_3_to_ks(fv, mv, lv, des)
+ int fv;
+ int mv;
+ int lv;
+ char_u *des;
+{
+ char_u key[3];
+ register int hi, lo, mi = 0, result, found;
+
+ if (fv == 0xff)
+ {
+ des[0] = mv;
+ des[1] = lv;
+ return 2;
+ }
+ key[0] = fv;
+ key[1] = mv;
+ key[2] = lv;
+ lo = 0;
+ hi = sizeof(ks_table1)/3 - 1;
+ found = 0;
+ while (lo + 1 < hi)
+ {
+ mi = (lo + hi)/2;
+ result = STRNCMP(ks_table1[mi], key, 3);
+ if (result == 0)
+ {
+ found = 1;
+ break;
+ }
+ else if (result > 0)
+ hi = mi;
+ else
+ lo = mi;
+ }
+ if (!found)
+ {
+ if (!STRNCMP(ks_table1[lo], key, 3))
+ {
+ found = 1;
+ mi = lo;
+ }
+ if (!STRNCMP(ks_table1[hi], key, 3))
+ {
+ found = 1;
+ mi = hi;
+ }
+ }
+ if (!found)
+ {
+ for (mi = 0; mi < 40; mi++)
+ if (ks_table2[mi][1] == fv && ks_table2[mi][2] == mv &&
+ ks_table2[mi][3] == lv)
+ {
+ des[0] = (unsigned)(ks_table2[mi][0]) >> 8;
+ des[1] = ks_table2[mi][0];
+ return 2; /* found */
+ }
+ }
+ else
+ {
+ des[0] = mi / (0xff-0xa1) + 0xb0;
+ des[1] = mi % (0xff-0xa1) + 0xa1;
+ return 2; /* found */
+ }
+
+ /* ¿Ï¼ºÇü Ç¥¿¡ ¾ø´Ù. ``KS C 5601 - 1992 Á¤º¸ ±³È¯¿ë ºÎÈ£ Çؼ³''
+ * 3.3 Àý¿¡ ¼³¸íµÈ ¹æ¹ýÀ¸·Î encoding ÇÑ´Ù.
+ */
+
+ *des++ = 0xa4; /* ä¿ò */
+ *des++ = 0xd4;
+ *des++ = 0xa4; /* ³¹ÀÚ´Â ¸ðµÎ a4 Çà¿¡ ÀÖ´Ù. */
+ *des++ = johab_fcon_to_wan[fv];
+ *des++ = 0xa4;
+ *des++ = johab_vow_to_wan[mv];
+ *des++ = 0xa4;
+ *des++ = johab_lcon_to_wan[lv];
+ return 8;
+}
diff --git a/src/if_cscope.c b/src/if_cscope.c
new file mode 100644
index 000000000..eec3de8de
--- /dev/null
+++ b/src/if_cscope.c
@@ -0,0 +1,2270 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * CSCOPE support for Vim added by Andy Kahn <kahn@zk3.dec.com>
+ * Ported to Win32 by Sergey Khorev <khorev@softlab.ru>
+ *
+ * The basic idea/structure of cscope for Vim was borrowed from Nvi. There
+ * might be a few lines of code that look similar to what Nvi has.
+ *
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_CSCOPE) || defined(PROTO)
+
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(UNIX)
+# include <sys/wait.h>
+#else
+ /* not UNIX, must be WIN32 */
+# include <io.h>
+# include <fcntl.h>
+# include <process.h>
+# define STDIN_FILENO 0
+# define STDOUT_FILENO 1
+# define STDERR_FILENO 2
+# define pipe(fds) _pipe(fds, 256, O_TEXT|O_NOINHERIT)
+#endif
+#include "if_cscope.h"
+
+static void cs_usage_msg __ARGS((csid_e x));
+static int cs_add __ARGS((exarg_T *eap));
+static void cs_stat_emsg __ARGS((char *fname));
+static int cs_add_common __ARGS((char *, char *, char *));
+static int cs_check_for_connections __ARGS((void));
+static int cs_check_for_tags __ARGS((void));
+static int cs_cnt_connections __ARGS((void));
+static void cs_reading_emsg __ARGS((int idx));
+static int cs_cnt_matches __ARGS((int idx));
+static char * cs_create_cmd __ARGS((char *csoption, char *pattern));
+static int cs_create_connection __ARGS((int i));
+static void do_cscope_general __ARGS((exarg_T *eap, int make_split));
+static void cs_file_results __ARGS((FILE *, int *));
+static void cs_fill_results __ARGS((char *, int , int *, char ***,
+ char ***, int *));
+static int cs_find __ARGS((exarg_T *eap));
+static int cs_find_common __ARGS((char *opt, char *pat, int, int ));
+static int cs_help __ARGS((exarg_T *eap));
+static void cs_init __ARGS((void));
+static void clear_csinfo __ARGS((int i));
+static int cs_insert_filelist __ARGS((char *, char *, char *,
+ struct stat *));
+static int cs_kill __ARGS((exarg_T *eap));
+static void cs_kill_execute __ARGS((int, char *));
+static cscmd_T * cs_lookup_cmd __ARGS((exarg_T *eap));
+static char * cs_make_vim_style_matches __ARGS((char *, char *,
+ char *, char *));
+static char * cs_manage_matches __ARGS((char **, char **, int, mcmd_e));
+static char * cs_parse_results __ARGS((int cnumber, char *buf, int bufsize, char **context, char **linenumber, char **search));
+static char * cs_pathcomponents __ARGS((char *path));
+static void cs_print_tags_priv __ARGS((char **, char **, int));
+static int cs_read_prompt __ARGS((int ));
+static void cs_release_csp __ARGS((int, int freefnpp));
+static int cs_reset __ARGS((exarg_T *eap));
+static char * cs_resolve_file __ARGS((int, char *));
+static int cs_show __ARGS((exarg_T *eap));
+
+
+static csinfo_T csinfo[CSCOPE_MAX_CONNECTIONS];
+static cscmd_T cs_cmds[] =
+{
+ { "add", cs_add,
+ N_("Add a new database"), "add file|dir [pre-path] [flags]", 0 },
+ { "find", cs_find,
+ N_("Query for a pattern"), FIND_USAGE, 1 },
+ { "help", cs_help,
+ N_("Show this message"), "help", 0 },
+ { "kill", cs_kill,
+ N_("Kill a connection"), "kill #", 0 },
+ { "reset", cs_reset,
+ N_("Reinit all connections"), "reset", 0 },
+ { "show", cs_show,
+ N_("Show connections"), "show", 0 },
+ { NULL }
+};
+
+ static void
+cs_usage_msg(x)
+ csid_e x;
+{
+ (void)EMSG2(_("E560: Usage: cs[cope] %s"), cs_cmds[(int)x].usage);
+}
+
+/*
+ * PRIVATE: do_cscope_general
+ *
+ * find the command, print help if invalid, and the then call the
+ * corresponding command function,
+ * called from do_cscope and do_scscope
+ */
+ static void
+do_cscope_general(eap, make_split)
+ exarg_T *eap;
+ int make_split; /* whether to split window */
+{
+ cscmd_T *cmdp;
+
+ cs_init();
+ if ((cmdp = cs_lookup_cmd(eap)) == NULL)
+ {
+ cs_help(eap);
+ return;
+ }
+
+#ifdef FEAT_WINDOWS
+ if (make_split)
+ {
+ if (!cmdp->cansplit)
+ {
+ (void)MSG_PUTS(_("This cscope command does not support splitting the window.\n"));
+ return;
+ }
+ postponed_split = -1;
+ postponed_split_flags = cmdmod.split;
+ }
+#endif
+
+ cmdp->func(eap);
+
+#ifdef FEAT_WINDOWS
+ postponed_split_flags = 0;
+#endif
+}
+
+/*
+ * PUBLIC: do_cscope
+ */
+ void
+do_cscope(eap)
+ exarg_T *eap;
+{
+ do_cscope_general(eap, FALSE);
+}
+
+/*
+ * PUBLIC: do_scscope
+ *
+ * same as do_cscope, but splits window, too.
+ */
+ void
+do_scscope(eap)
+ exarg_T *eap;
+{
+ do_cscope_general(eap, TRUE);
+}
+
+/*
+ * PUBLIC: do_cstag
+ *
+ */
+ void
+do_cstag(eap)
+ exarg_T *eap;
+{
+ int ret = FALSE;
+
+ cs_init();
+
+ if (eap->arg == NULL || strlen((const char *)(eap->arg)) == 0)
+ {
+ (void)EMSG(_("E562: Usage: cstag <ident>"));
+ return;
+ }
+
+ switch (p_csto)
+ {
+ case 0 :
+ if (cs_check_for_connections())
+ {
+ ret = cs_find_common("g", (char *)(eap->arg), eap->forceit, FALSE);
+ if (ret == FALSE)
+ {
+ cs_free_tags();
+ if (msg_col)
+ msg_putchar('\n');
+
+ if (cs_check_for_tags())
+ ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, FALSE);
+ }
+ }
+ else if (cs_check_for_tags())
+ {
+ ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, FALSE);
+ }
+ break;
+ case 1 :
+ if (cs_check_for_tags())
+ {
+ ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, FALSE);
+ if (ret == FALSE)
+ {
+ if (msg_col)
+ msg_putchar('\n');
+
+ if (cs_check_for_connections())
+ {
+ ret = cs_find_common("g", (char *)(eap->arg), eap->forceit,
+ FALSE);
+ if (ret == FALSE)
+ cs_free_tags();
+ }
+ }
+ }
+ else if (cs_check_for_connections())
+ {
+ ret = cs_find_common("g", (char *)(eap->arg), eap->forceit, FALSE);
+ if (ret == FALSE)
+ cs_free_tags();
+ }
+ break;
+ default :
+ break;
+ }
+
+ if (!ret)
+ {
+ (void)EMSG(_("E257: cstag: tag not found"));
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ g_do_tagpreview = 0;
+#endif
+ }
+
+} /* do_cscope */
+
+
+/*
+ * PUBLIC: cs_find
+ *
+ * this simulates a vim_fgets(), but for cscope, returns the next line
+ * from the cscope output. should only be called from find_tags()
+ *
+ * returns TRUE if eof, FALSE otherwise
+ */
+ int
+cs_fgets(buf, size)
+ char_u *buf;
+ int size;
+{
+ char *p;
+
+ if ((p = cs_manage_matches(NULL, NULL, -1, Get)) == NULL)
+ return TRUE;
+
+ if ((int)strlen(p) > size)
+ {
+ strncpy((char *)buf, p, size - 1);
+ buf[size] = '\0';
+ }
+ else
+ (void)strcpy((char *)buf, p);
+
+ return FALSE;
+} /* cs_fgets */
+
+
+/*
+ * PUBLIC: cs_free_tags
+ *
+ * called only from do_tag(), when popping the tag stack
+ */
+ void
+cs_free_tags()
+{
+ cs_manage_matches(NULL, NULL, -1, Free);
+}
+
+
+/*
+ * PUBLIC: cs_print_tags
+ *
+ * called from do_tag()
+ */
+ void
+cs_print_tags()
+{
+ cs_manage_matches(NULL, NULL, -1, Print);
+}
+
+
+/*
+ * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
+ *
+ * Checks for the existence of a |cscope| connection. If no
+ * parameters are specified, then the function returns:
+ *
+ * 0, if cscope was not available (not compiled in), or if there
+ * are no cscope connections; or
+ * 1, if there is at least one cscope connection.
+ *
+ * If parameters are specified, then the value of {num}
+ * determines how existence of a cscope connection is checked:
+ *
+ * {num} Description of existence check
+ * ----- ------------------------------
+ * 0 Same as no parameters (e.g., "cscope_connection()").
+ * 1 Ignore {prepend}, and use partial string matches for
+ * {dbpath}.
+ * 2 Ignore {prepend}, and use exact string matches for
+ * {dbpath}.
+ * 3 Use {prepend}, use partial string matches for both
+ * {dbpath} and {prepend}.
+ * 4 Use {prepend}, use exact string matches for both
+ * {dbpath} and {prepend}.
+ *
+ * Note: All string comparisons are case sensitive!
+ */
+#if defined(FEAT_EVAL) || defined(PROTO)
+ int
+cs_connection(num, dbpath, ppath)
+ int num;
+ char_u *dbpath;
+ char_u *ppath;
+{
+ int i;
+
+ if (num < 0 || num > 4 || (num > 0 && !dbpath))
+ return FALSE;
+
+ for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+ {
+ if (!csinfo[i].fname)
+ continue;
+
+ if (num == 0)
+ return TRUE;
+
+ switch (num)
+ {
+ case 1:
+ if (strstr(csinfo[i].fname, (char *)dbpath))
+ return TRUE;
+ break;
+ case 2:
+ if (strcmp(csinfo[i].fname, (char *)dbpath) == 0)
+ return TRUE;
+ break;
+ case 3:
+ if (strstr(csinfo[i].fname, (char *)dbpath)
+ && ((!ppath && !csinfo[i].ppath)
+ || (ppath
+ && csinfo[i].ppath
+ && strstr(csinfo[i].ppath, (char *)ppath))))
+ return TRUE;
+ break;
+ case 4:
+ if ((strcmp(csinfo[i].fname, (char *)dbpath) == 0)
+ && ((!ppath && !csinfo[i].ppath)
+ || (ppath
+ && csinfo[i].ppath
+ && (strcmp(csinfo[i].ppath, (char *)ppath) == 0))))
+ return TRUE;
+ break;
+ }
+ }
+
+ return FALSE;
+} /* cs_connection */
+#endif
+
+
+/*
+ * PRIVATE functions
+ ****************************************************************************/
+
+/*
+ * PRIVATE: cs_add
+ *
+ * add cscope database or a directory name (to look for cscope.out)
+ * the the cscope connection list
+ *
+ * MAXPATHL 256
+ */
+/* ARGSUSED */
+ static int
+cs_add(eap)
+ exarg_T *eap;
+{
+ char *fname, *ppath, *flags = NULL;
+
+ if ((fname = strtok((char *)NULL, (const char *)" ")) == NULL)
+ {
+ cs_usage_msg(Add);
+ return CSCOPE_FAILURE;
+ }
+ if ((ppath = strtok((char *)NULL, (const char *)" ")) != NULL)
+ flags = strtok((char *)NULL, (const char *)" ");
+
+ return cs_add_common(fname, ppath, flags);
+}
+
+ static void
+cs_stat_emsg(fname)
+ char *fname;
+{
+ char *stat_emsg = _("E563: stat(%s) error: %d");
+ char *buf = (char *)alloc((unsigned)strlen(stat_emsg) + MAXPATHL + 10);
+
+ if (buf != NULL)
+ {
+ (void)sprintf(buf, stat_emsg, fname, errno);
+ (void)EMSG(buf);
+ vim_free(buf);
+ }
+ else
+ (void)EMSG(_("E563: stat error"));
+}
+
+
+/*
+ * PRIVATE: cs_add_common
+ *
+ * the common routine to add a new cscope connection. called by
+ * cs_add() and cs_reset(). i really don't like to do this, but this
+ * routine uses a number of goto statements.
+ */
+ static int
+cs_add_common(arg1, arg2, flags)
+ char *arg1; /* filename - may contain environment variables */
+ char *arg2; /* prepend path - may contain environment variables */
+ char *flags;
+{
+ struct stat statbuf;
+ int ret;
+ char *fname = NULL;
+ char *fname2 = NULL;
+ char *ppath = NULL;
+ int i;
+
+ /* get the filename (arg1), expand it, and try to stat it */
+ if ((fname = (char *)alloc(MAXPATHL+1)) == NULL)
+ goto add_err;
+
+ expand_env((char_u *)arg1, (char_u *)fname, MAXPATHL);
+ ret = stat(fname, &statbuf);
+ if (ret < 0)
+ {
+staterr:
+ if (p_csverbose)
+ cs_stat_emsg(fname);
+ goto add_err;
+ }
+
+ /* get the prepend path (arg2), expand it, and try to stat it */
+ if (arg2 != NULL)
+ {
+ struct stat statbuf2;
+
+ if ((ppath = (char *)alloc(MAXPATHL+1)) == NULL)
+ goto add_err;
+
+ expand_env((char_u *)arg2, (char_u *)ppath, MAXPATHL);
+ ret = stat(ppath, &statbuf2);
+ if (ret < 0)
+ goto staterr;
+ }
+
+ /* if filename is a directory, append the cscope database name to it */
+ if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
+ {
+ fname2 = (char *)alloc(strlen(CSCOPE_DBFILE) + strlen(fname) + 2);
+ if (fname2 == NULL)
+ goto add_err;
+
+ while (fname[strlen(fname)-1] == '/'
+#ifdef WIN32
+ || fname[strlen(fname)-1] == '\\'
+#endif
+ )
+ {
+ fname[strlen(fname)-1] = '\0';
+ if (strlen(fname) == 0)
+ break;
+ }
+ if (fname[0] == '\0')
+ (void)sprintf(fname2, "/%s", CSCOPE_DBFILE);
+ else
+ (void)sprintf(fname2, "%s/%s", fname, CSCOPE_DBFILE);
+
+ ret = stat(fname2, &statbuf);
+ if (ret < 0)
+ {
+ if (p_csverbose)
+ cs_stat_emsg(fname2);
+ goto add_err;
+ }
+
+ i = cs_insert_filelist(fname2, ppath, flags, &statbuf);
+ }
+#if defined(UNIX)
+ else if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode))
+#else
+ /* substitute define S_ISREG from os_unix.h */
+ else if (((statbuf.st_mode) & S_IFMT) == S_IFREG)
+#endif
+ {
+ i = cs_insert_filelist(fname, ppath, flags, &statbuf);
+ }
+ else
+ {
+ if (p_csverbose)
+ (void)EMSG2(
+ _("E564: %s is not a directory or a valid cscope database"),
+ fname);
+ goto add_err;
+ }
+
+ if (i != -1)
+ {
+ if (cs_create_connection(i) == CSCOPE_FAILURE
+ || cs_read_prompt(i) == CSCOPE_FAILURE)
+ {
+ cs_release_csp(i, TRUE);
+ goto add_err;
+ }
+
+ if (p_csverbose)
+ {
+ msg_clr_eos();
+ (void)smsg_attr(hl_attr(HLF_R),
+ (char_u *)_("Added cscope database %s"),
+ csinfo[i].fname);
+ }
+ }
+
+ vim_free(fname);
+ vim_free(fname2);
+ vim_free(ppath);
+ return CSCOPE_SUCCESS;
+
+add_err:
+ vim_free(fname2);
+ vim_free(fname);
+ vim_free(ppath);
+ return CSCOPE_FAILURE;
+} /* cs_add_common */
+
+
+ static int
+cs_check_for_connections()
+{
+ return (cs_cnt_connections() > 0);
+} /* cs_check_for_connections */
+
+
+ static int
+cs_check_for_tags()
+{
+ return (p_tags[0] != NUL && curbuf->b_p_tags != NUL);
+} /* cs_check_for_tags */
+
+
+/*
+ * PRIVATE: cs_cnt_connections
+ *
+ * count the number of cscope connections
+ */
+ static int
+cs_cnt_connections()
+{
+ short i;
+ short cnt = 0;
+
+ for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+ {
+ if (csinfo[i].fname != NULL)
+ cnt++;
+ }
+ return cnt;
+} /* cs_cnt_connections */
+
+ static void
+cs_reading_emsg(idx)
+ int idx; /* connection index */
+{
+ EMSGN(_("E262: error reading cscope connection %ld"), idx);
+}
+
+#define CSREAD_BUFSIZE 2048
+/*
+ * PRIVATE: cs_cnt_matches
+ *
+ * count the number of matches for a given cscope connection.
+ */
+ static int
+cs_cnt_matches(idx)
+ int idx;
+{
+ char *stok;
+ char *buf;
+ int nlines;
+
+ buf = (char *)alloc(CSREAD_BUFSIZE);
+ if (buf == NULL)
+ return 0;
+ for (;;)
+ {
+ if (!fgets(buf, CSREAD_BUFSIZE, csinfo[idx].fr_fp))
+ {
+ if (feof(csinfo[idx].fr_fp))
+ errno = EIO;
+
+ cs_reading_emsg(idx);
+
+ vim_free(buf);
+ return -1;
+ }
+
+ /*
+ * If the database is out of date, or there's some other problem,
+ * cscope will output error messages before the number-of-lines output.
+ * Display/discard any output that doesn't match what we want.
+ */
+ if ((stok = strtok(buf, (const char *)" ")) == NULL)
+ continue;
+ if (strcmp((const char *)stok, "cscope:"))
+ continue;
+
+ if ((stok = strtok(NULL, (const char *)" ")) == NULL)
+ continue;
+ nlines = atoi(stok);
+ if (nlines < 0)
+ {
+ nlines = 0;
+ break;
+ }
+
+ if ((stok = strtok(NULL, (const char *)" ")) == NULL)
+ continue;
+ if (strncmp((const char *)stok, "lines", 5))
+ continue;
+
+ break;
+ }
+
+ vim_free(buf);
+ return nlines;
+} /* cs_cnt_matches */
+
+
+/*
+ * PRIVATE: cs_create_cmd
+ *
+ * Creates the actual cscope command query from what the user entered.
+ */
+ static char *
+cs_create_cmd(csoption, pattern)
+ char *csoption;
+ char *pattern;
+{
+ char *cmd;
+ short search;
+
+ switch (csoption[0])
+ {
+ case '0' : case 's' :
+ search = 0;
+ break;
+ case '1' : case 'g' :
+ search = 1;
+ break;
+ case '2' : case 'd' :
+ search = 2;
+ break;
+ case '3' : case 'c' :
+ search = 3;
+ break;
+ case '4' : case 't' :
+ search = 4;
+ break;
+ case '6' : case 'e' :
+ search = 6;
+ break;
+ case '7' : case 'f' :
+ search = 7;
+ break;
+ case '8' : case 'i' :
+ search = 8;
+ break;
+ default :
+ (void)EMSG(_("E561: unknown cscope search type"));
+ cs_usage_msg(Find);
+ return NULL;
+ }
+
+ if ((cmd = (char *)alloc(strlen(pattern) + 2)) == NULL)
+ return NULL;
+
+ (void)sprintf(cmd, "%d%s", search, pattern);
+
+ return cmd;
+} /* cs_create_cmd */
+
+
+/*
+ * PRIVATE: cs_create_connection
+ *
+ * This piece of code was taken/adapted from nvi. do we need to add
+ * the BSD license notice?
+ */
+ static int
+cs_create_connection(i)
+ int i;
+{
+ int to_cs[2], from_cs[2], len;
+ char *prog, *cmd, *ppath = NULL;
+#ifndef UNIX
+ int in_save, out_save, err_save;
+ int ph;
+# ifdef FEAT_GUI
+ HWND activewnd = NULL;
+ HWND consolewnd = NULL;
+# endif
+#endif
+
+ /*
+ * Cscope reads from to_cs[0] and writes to from_cs[1]; vi reads from
+ * from_cs[0] and writes to to_cs[1].
+ */
+ to_cs[0] = to_cs[1] = from_cs[0] = from_cs[1] = -1;
+ if (pipe(to_cs) < 0 || pipe(from_cs) < 0)
+ {
+ (void)EMSG(_("E566: Could not create cscope pipes"));
+err_closing:
+ if (to_cs[0] != -1)
+ (void)close(to_cs[0]);
+ if (to_cs[1] != -1)
+ (void)close(to_cs[1]);
+ if (from_cs[0] != -1)
+ (void)close(from_cs[0]);
+ if (from_cs[1] != -1)
+ (void)close(from_cs[1]);
+ return CSCOPE_FAILURE;
+ }
+
+#if defined(UNIX)
+ switch (csinfo[i].pid = fork())
+ {
+ case -1:
+ (void)EMSG(_("E622: Could not fork for cscope"));
+ goto err_closing;
+ case 0: /* child: run cscope. */
+#else
+ in_save = dup(STDIN_FILENO);
+ out_save = dup(STDOUT_FILENO);
+ err_save = dup(STDERR_FILENO);
+#endif
+ if (dup2(to_cs[0], STDIN_FILENO) == -1)
+ PERROR("cs_create_connection 1");
+ if (dup2(from_cs[1], STDOUT_FILENO) == -1)
+ PERROR("cs_create_connection 2");
+ if (dup2(from_cs[1], STDERR_FILENO) == -1)
+ PERROR("cs_create_connection 3");
+
+ /* close unused */
+#if defined(UNIX)
+ (void)close(to_cs[1]);
+ (void)close(from_cs[0]);
+#else
+ /* On win32 we must close opposite ends because we are the parent */
+ (void)close(to_cs[0]);
+ to_cs[0] = -1;
+ (void)close(from_cs[1]);
+ from_cs[1] = -1;
+#endif
+ /* expand the cscope exec for env var's */
+ if ((prog = (char *)alloc(MAXPATHL + 1)) == NULL)
+ {
+#ifdef UNIX
+ return CSCOPE_FAILURE;
+#else
+ goto err_closing;
+#endif
+ }
+ expand_env((char_u *)p_csprg, (char_u *)prog, MAXPATHL);
+
+ /* alloc space to hold the cscope command */
+ len = strlen(prog) + strlen(csinfo[i].fname) + 32;
+ if (csinfo[i].ppath)
+ {
+ /* expand the prepend path for env var's */
+ if ((ppath = (char *)alloc(MAXPATHL + 1)) == NULL)
+ {
+ vim_free(prog);
+#ifdef UNIX
+ return CSCOPE_FAILURE;
+#else
+ goto err_closing;
+#endif
+ }
+ expand_env((char_u *)csinfo[i].ppath, (char_u *)ppath, MAXPATHL);
+
+ len += strlen(ppath);
+ }
+
+ if (csinfo[i].flags)
+ len += strlen(csinfo[i].flags);
+
+ if ((cmd = (char *)alloc(len)) == NULL)
+ {
+ vim_free(prog);
+ vim_free(ppath);
+#ifdef UNIX
+ return CSCOPE_FAILURE;
+#else
+ goto err_closing;
+#endif
+ }
+
+ /* run the cscope command; is there execl for non-unix systems? */
+#if defined(UNIX)
+ (void)sprintf(cmd, "exec %s -dl -f %s", prog, csinfo[i].fname);
+#else
+ (void)sprintf(cmd, "%s -dl -f %s", prog, csinfo[i].fname);
+#endif
+ if (csinfo[i].ppath != NULL)
+ {
+ (void)strcat(cmd, " -P");
+ (void)strcat(cmd, csinfo[i].ppath);
+ }
+ if (csinfo[i].flags != NULL)
+ {
+ (void)strcat(cmd, " ");
+ (void)strcat(cmd, csinfo[i].flags);
+ }
+# ifdef UNIX
+ /* on Win32 we still need prog */
+ vim_free(prog);
+# endif
+ vim_free(ppath);
+
+#if defined(UNIX)
+ if (execl("/bin/sh", "sh", "-c", cmd, NULL) == -1)
+ PERROR(_("cs_create_connection exec failed"));
+
+ exit(127);
+ /* NOTREACHED */
+ default: /* parent. */
+#else
+# ifdef FEAT_GUI
+ activewnd = GetForegroundWindow(); /* on win9x cscope steals focus */
+ /* Dirty hack to hide annoying console window */
+ if (AllocConsole())
+ {
+ char *title;
+ title = (char *)alloc(1024);
+ if (title == NULL)
+ FreeConsole();
+ else
+ {
+ GetConsoleTitle(title, 1024); /* save for future restore */
+ SetConsoleTitle(
+ "GVIMCS{5499421B-CBEF-45b0-85EF-38167FDEA5C5}GVIMCS");
+ Sleep(40); /* as stated in MS KB we must wait 40 ms */
+ consolewnd = FindWindow(NULL,
+ "GVIMCS{5499421B-CBEF-45b0-85EF-38167FDEA5C5}GVIMCS");
+ if (consolewnd != NULL)
+ ShowWindow(consolewnd, SW_HIDE);
+ SetConsoleTitle(title);
+ vim_free(title);
+ }
+ }
+# endif
+ /* May be use &shell, &shellquote etc */
+# ifdef __BORLANDC__
+ /* BCC 5.5 uses a different function name for spawnlp */
+ ph = spawnlp(P_NOWAIT, prog, cmd, NULL);
+# else
+ ph = _spawnlp(_P_NOWAIT, prog, cmd, NULL);
+# endif
+ vim_free(prog);
+ vim_free(cmd);
+# ifdef FEAT_GUI
+ /* Dirty hack part two */
+ if (activewnd != NULL)
+ /* restoring focus */
+ SetForegroundWindow(activewnd);
+ if (consolewnd != NULL)
+ FreeConsole();
+
+# endif
+ if (ph == -1)
+ {
+ PERROR(_("cs_create_connection exec failed"));
+ (void)EMSG(_("E623: Could not spawn cscope process"));
+ goto err_closing;
+ }
+ /* else */
+ csinfo[i].pid = 0;
+ csinfo[i].hProc = (HANDLE)ph;
+
+#endif /* !UNIX */
+ /*
+ * Save the file descriptors for later duplication, and
+ * reopen as streams.
+ */
+ if ((csinfo[i].to_fp = fdopen(to_cs[1], "w")) == NULL)
+ PERROR(_("cs_create_connection: fdopen for to_fp failed"));
+ if ((csinfo[i].fr_fp = fdopen(from_cs[0], "r")) == NULL)
+ PERROR(_("cs_create_connection: fdopen for fr_fp failed"));
+
+#if defined(UNIX)
+ /* close unused */
+ (void)close(to_cs[0]);
+ (void)close(from_cs[1]);
+
+ break;
+ }
+#else
+ /* restore stdhandles */
+ dup2(in_save, STDIN_FILENO);
+ dup2(out_save, STDOUT_FILENO);
+ dup2(err_save, STDERR_FILENO);
+ close(in_save);
+ close(out_save);
+ close(err_save);
+#endif
+ return CSCOPE_SUCCESS;
+} /* cs_create_connection */
+
+
+/*
+ * PRIVATE: cs_find
+ *
+ * query cscope using command line interface. parse the output and use tselect
+ * to allow choices. like Nvi, creates a pipe to send to/from query/cscope.
+ *
+ * returns TRUE if we jump to a tag or abort, FALSE if not.
+ */
+ static int
+cs_find(eap)
+ exarg_T *eap;
+{
+ char *opt, *pat;
+
+ if (cs_check_for_connections() == FALSE)
+ {
+ (void)EMSG(_("E567: no cscope connections"));
+ return FALSE;
+ }
+
+ if ((opt = strtok((char *)NULL, (const char *)" ")) == NULL)
+ {
+ cs_usage_msg(Find);
+ return FALSE;
+ }
+
+ pat = opt + strlen(opt) + 1;
+ if (pat == NULL || (pat != NULL && pat[0] == '\0'))
+ {
+ cs_usage_msg(Find);
+ return FALSE;
+ }
+
+ return cs_find_common(opt, pat, eap->forceit, TRUE);
+} /* cs_find */
+
+
+/*
+ * PRIVATE: cs_find_common
+ *
+ * common code for cscope find, shared by cs_find() and do_cstag()
+ */
+ static int
+cs_find_common(opt, pat, forceit, verbose)
+ char *opt;
+ char *pat;
+ int forceit;
+ int verbose;
+{
+ int i;
+ char *cmd;
+ char **matches, **contexts;
+ int nummatches[CSCOPE_MAX_CONNECTIONS], totmatches, matched;
+#ifdef FEAT_QUICKFIX
+ char cmdletter;
+ char *qfpos;
+#endif
+
+ /* create the actual command to send to cscope */
+ cmd = cs_create_cmd(opt, pat);
+ if (cmd == NULL)
+ return FALSE;
+
+ /* send query to all open connections, then count the total number
+ * of matches so we can alloc matchesp all in one swell foop
+ */
+ for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+ nummatches[i] = 0;
+ totmatches = 0;
+ for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+ {
+ if (csinfo[i].fname == NULL)
+ continue;
+
+ /* send cmd to cscope */
+ (void)fprintf(csinfo[i].to_fp, "%s\n", cmd);
+ (void)fflush(csinfo[i].to_fp);
+
+ nummatches[i] = cs_cnt_matches(i);
+
+ if (nummatches[i] > -1)
+ totmatches += nummatches[i];
+
+ if (nummatches[i] == 0)
+ (void)cs_read_prompt(i);
+ }
+ vim_free(cmd);
+
+ if (totmatches == 0)
+ {
+ char *nf = _("E259: no matches found for cscope query %s of %s");
+ char *buf;
+
+ if (!verbose)
+ return FALSE;
+
+ buf = (char *)alloc(strlen(opt) + strlen(pat) + strlen(nf));
+ if (buf == NULL)
+ (void)EMSG(nf);
+ else
+ {
+ sprintf(buf, nf, opt, pat);
+ (void)EMSG(buf);
+ vim_free(buf);
+ }
+ return FALSE;
+ }
+
+#ifdef FEAT_QUICKFIX
+ /* get cmd letter */
+ switch (opt[0])
+ {
+ case '0' :
+ cmdletter = 's';
+ break;
+ case '1' :
+ cmdletter = 'g';
+ break;
+ case '2' :
+ cmdletter = 'd';
+ break;
+ case '3' :
+ cmdletter = 'c';
+ break;
+ case '4' :
+ cmdletter = 't';
+ break;
+ case '6' :
+ cmdletter = 'e';
+ break;
+ case '7' :
+ cmdletter = 'f';
+ break;
+ case '8' :
+ cmdletter = 'i';
+ break;
+ default :
+ cmdletter = opt[0];
+ }
+
+ qfpos = (char *)vim_strchr(p_csqf, cmdletter);
+ if (qfpos != NULL)
+ {
+ qfpos++;
+ /* next symbol must be + or - */
+ if (strchr(CSQF_FLAGS, *qfpos) == NULL)
+ {
+ char *nf = _("E469: invalid cscopequickfix flag %c for %c");
+ char *buf = (char *)alloc(strlen(nf));
+
+ /* strlen will be enough because we use chars */
+ if (buf != NULL)
+ {
+ sprintf(buf, nf, *qfpos, *(qfpos-1));
+ (void)EMSG(buf);
+ vim_free(buf);
+ }
+ return FALSE;
+ }
+ }
+ if (qfpos != NULL && *qfpos != '0' && totmatches > 1)
+ {
+ /* fill error list */
+ FILE *f;
+ char_u *tmp = vim_tempname('c');
+
+ f = fopen((char *)tmp, "w");
+ cs_file_results(f, nummatches);
+ fclose(f);
+ /* '-' starts a new error list */
+ if (qf_init(tmp, (char_u *)"%f%*\\t%l%*\\t%m", *qfpos == '-') > 0)
+ {
+# ifdef FEAT_WINDOWS
+ if (postponed_split != 0)
+ {
+ win_split(postponed_split > 0 ? postponed_split : 0,
+ postponed_split_flags);
+# ifdef FEAT_SCROLLBIND
+ curwin->w_p_scb = FALSE;
+# endif
+ postponed_split = 0;
+ }
+# endif
+ qf_jump(0, 0, forceit);
+ }
+ mch_remove(tmp);
+ vim_free(tmp);
+ return TRUE;
+ }
+ else
+#endif /* FEAT_QUICKFIX */
+ {
+ /* read output */
+ cs_fill_results((char *)pat, totmatches, nummatches, &matches,
+ &contexts, &matched);
+ if (matches == NULL)
+ return FALSE;
+
+ (void)cs_manage_matches(matches, contexts, totmatches, Store);
+
+ return do_tag((char_u *)pat, DT_CSCOPE, 0, forceit, verbose);
+ }
+
+} /* cs_find_common */
+
+/*
+ * PRIVATE: cs_help
+ *
+ * print help
+ */
+/* ARGSUSED */
+ static int
+cs_help(eap)
+ exarg_T *eap;
+{
+ cscmd_T *cmdp = cs_cmds;
+
+ (void)MSG_PUTS(_("cscope commands:\n"));
+ while (cmdp->name != NULL)
+ {
+ (void)smsg((char_u *)_("%-5s: %-30s (Usage: %s)"),
+ cmdp->name, _(cmdp->help), cmdp->usage);
+ if (strcmp(cmdp->name, "find") == 0)
+ MSG_PUTS(FIND_HELP);
+ cmdp++;
+ }
+
+ wait_return(TRUE);
+ return 0;
+} /* cs_help */
+
+
+/*
+ * PRIVATE: cs_init
+ *
+ * initialize cscope structure if not already
+ */
+ static void
+cs_init()
+{
+ short i;
+ static int init_already = FALSE;
+
+ if (init_already)
+ return;
+
+ for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+ clear_csinfo(i);
+
+ init_already = TRUE;
+} /* cs_init */
+
+ static void
+clear_csinfo(i)
+ int i;
+{
+ csinfo[i].fname = NULL;
+ csinfo[i].ppath = NULL;
+ csinfo[i].flags = NULL;
+#if defined(UNIX)
+ csinfo[i].st_dev = (dev_t)0;
+ csinfo[i].st_ino = (ino_t)0;
+#else
+ csinfo[i].nVolume = 0;
+ csinfo[i].nIndexHigh = 0;
+ csinfo[i].nIndexLow = 0;
+#endif
+ csinfo[i].pid = -1;
+ csinfo[i].fr_fp = NULL;
+ csinfo[i].to_fp = NULL;
+}
+
+#ifndef UNIX
+static char *GetWin32Error __ARGS((void));
+
+ static char *
+GetWin32Error()
+{
+ char *msg = NULL;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(), 0, (LPSTR)&msg, 0, NULL);
+ if (msg != NULL)
+ {
+ /* remove trailing \r\n */
+ char *pcrlf = strstr(msg, "\r\n");
+ if (pcrlf != NULL)
+ *pcrlf = '\0';
+ }
+ return msg;
+}
+#endif
+/*
+ * PRIVATE: cs_insert_filelist
+ *
+ * insert a new cscope database filename into the filelist
+ */
+ static int
+cs_insert_filelist(fname, ppath, flags, sb)
+ char *fname;
+ char *ppath;
+ char *flags;
+ struct stat *sb;
+{
+ short i, j;
+#ifndef UNIX
+ HANDLE hFile;
+ BY_HANDLE_FILE_INFORMATION bhfi;
+
+ vim_memset(&bhfi, 0, sizeof(bhfi));
+ /* On windows 9x GetFileInformationByHandle doesn't work, so skip it */
+ if (!mch_windows95())
+ {
+ hFile = CreateFile(fname, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ if (p_csverbose)
+ {
+ char *cant_msg = _("E625: cannot open cscope database: %s");
+ char *winmsg = GetWin32Error();
+
+ if (winmsg != NULL)
+ {
+ (void)EMSG2(cant_msg, winmsg);
+ LocalFree(winmsg);
+ }
+ else
+ /* subst filename if can't get error text */
+ (void)EMSG2(cant_msg, fname);
+ }
+ return -1;
+ }
+ if (!GetFileInformationByHandle(hFile, &bhfi))
+ {
+ CloseHandle(hFile);
+ if (p_csverbose)
+ (void)EMSG(_("E626: cannot get cscope database information"));
+ return -1;
+ }
+ CloseHandle(hFile);
+ }
+#endif
+
+ i = -1; /* can be set to the index of an empty item in csinfo */
+ for (j = 0; j < CSCOPE_MAX_CONNECTIONS; j++)
+ {
+ if (csinfo[j].fname != NULL
+#if defined(UNIX)
+ && csinfo[j].st_dev == sb->st_dev && csinfo[j].st_ino == sb->st_ino
+#else
+ /* compare pathnames first */
+ && ((fullpathcmp(csinfo[j].fname, fname, FALSE) & FPC_SAME)
+ /* if not Windows 9x, test index file atributes too */
+ || (!mch_windows95()
+ && csinfo[j].nVolume == bhfi.dwVolumeSerialNumber
+ && csinfo[j].nIndexHigh == bhfi.nFileIndexHigh
+ && csinfo[j].nIndexLow == bhfi.nFileIndexLow))
+#endif
+ )
+ {
+ if (p_csverbose)
+ (void)EMSG(_("E568: duplicate cscope database not added"));
+ return -1;
+ }
+
+ if (csinfo[j].fname == NULL && i == -1)
+ i = j; /* remember first empty entry */
+ }
+
+ if (i == -1)
+ {
+ if (p_csverbose)
+ (void)EMSG(_("E569: maximum number of cscope connections reached"));
+ return -1;
+ }
+
+ if ((csinfo[i].fname = (char *)alloc(strlen(fname)+1)) == NULL)
+ return -1;
+
+ (void)strcpy(csinfo[i].fname, (const char *)fname);
+
+ if (ppath != NULL)
+ {
+ if ((csinfo[i].ppath = (char *)alloc(strlen(ppath) + 1)) == NULL)
+ {
+ vim_free(csinfo[i].fname);
+ csinfo[i].fname = NULL;
+ return -1;
+ }
+ (void)strcpy(csinfo[i].ppath, (const char *)ppath);
+ } else
+ csinfo[i].ppath = NULL;
+
+ if (flags != NULL)
+ {
+ if ((csinfo[i].flags = (char *)alloc(strlen(flags) + 1)) == NULL)
+ {
+ vim_free(csinfo[i].fname);
+ vim_free(csinfo[i].ppath);
+ csinfo[i].fname = NULL;
+ csinfo[i].ppath = NULL;
+ return -1;
+ }
+ (void)strcpy(csinfo[i].flags, (const char *)flags);
+ } else
+ csinfo[i].flags = NULL;
+
+#if defined(UNIX)
+ csinfo[i].st_dev = sb->st_dev;
+ csinfo[i].st_ino = sb->st_ino;
+
+#else
+ csinfo[i].nVolume = bhfi.dwVolumeSerialNumber;
+ csinfo[i].nIndexLow = bhfi.nFileIndexLow;
+ csinfo[i].nIndexHigh = bhfi.nFileIndexHigh;
+#endif
+ return i;
+} /* cs_insert_filelist */
+
+
+/*
+ * PRIVATE: cs_lookup_cmd
+ *
+ * find cscope command in command table
+ */
+ static cscmd_T *
+cs_lookup_cmd(eap)
+ exarg_T *eap;
+{
+ cscmd_T *cmdp;
+ char *stok;
+ size_t len;
+
+ if (eap->arg == NULL)
+ return NULL;
+
+ if ((stok = strtok((char *)(eap->arg), (const char *)" ")) == NULL)
+ return NULL;
+
+ len = strlen(stok);
+ for (cmdp = cs_cmds; cmdp->name != NULL; ++cmdp)
+ {
+ if (strncmp((const char *)(stok), cmdp->name, len) == 0)
+ return (cmdp);
+ }
+ return NULL;
+} /* cs_lookup_cmd */
+
+
+/*
+ * PRIVATE: cs_kill
+ *
+ * nuke em
+ */
+/* ARGSUSED */
+ static int
+cs_kill(eap)
+ exarg_T *eap;
+{
+ char *stok;
+ short i;
+
+ if ((stok = strtok((char *)NULL, (const char *)" ")) == NULL)
+ {
+ cs_usage_msg(Kill);
+ return CSCOPE_FAILURE;
+ }
+
+ /* only single digit positive and negative integers are allowed */
+ if ((strlen(stok) < 2 && VIM_ISDIGIT((int)(stok[0])))
+ || (strlen(stok) < 3 && stok[0] == '-'
+ && VIM_ISDIGIT((int)(stok[1]))))
+ i = atoi(stok);
+ else
+ {
+ /* It must be part of a name. We will try to find a match
+ * within all the names in the csinfo data structure
+ */
+ for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+ {
+ if (csinfo[i].fname != NULL && strstr(csinfo[i].fname, stok))
+ break;
+ }
+ }
+
+ if ((i >= CSCOPE_MAX_CONNECTIONS || i < -1 || csinfo[i].fname == NULL)
+ && i != -1)
+ {
+ if (p_csverbose)
+ (void)EMSG2(_("E261: cscope connection %s not found"), stok);
+ }
+ else
+ {
+ if (i == -1)
+ {
+ for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+ {
+ if (csinfo[i].fname)
+ cs_kill_execute(i, csinfo[i].fname);
+ }
+ }
+ else
+ cs_kill_execute(i, stok);
+ }
+
+ return 0;
+} /* cs_kill */
+
+
+/*
+ * PRIVATE: cs_kill_execute
+ *
+ * Actually kills a specific cscope connection.
+ */
+ static void
+cs_kill_execute(i, cname)
+ int i; /* cscope table index */
+ char *cname; /* cscope database name */
+{
+ if (p_csverbose)
+ {
+ msg_clr_eos();
+ (void)smsg_attr(hl_attr(HLF_R) | MSG_HIST,
+ (char_u *)_("cscope connection %s closed"), cname);
+ }
+ cs_release_csp(i, TRUE);
+}
+
+
+/*
+ * PRIVATE: cs_make_vim_style_matches
+ *
+ * convert the cscope output into into a ctags style entry (as might be found
+ * in a ctags tags file). there's one catch though: cscope doesn't tell you
+ * the type of the tag you are looking for. for example, in Darren Hiebert's
+ * ctags (the one that comes with vim), #define's use a line number to find the
+ * tag in a file while function definitions use a regexp search pattern.
+ *
+ * i'm going to always use the line number because cscope does something
+ * quirky (and probably other things i don't know about):
+ *
+ * if you have "# define" in your source file, which is
+ * perfectly legal, cscope thinks you have "#define". this
+ * will result in a failed regexp search. :(
+ *
+ * besides, even if this particular case didn't happen, the search pattern
+ * would still have to be modified to escape all the special regular expression
+ * characters to comply with ctags formatting.
+ */
+ static char *
+cs_make_vim_style_matches(fname, slno, search, tagstr)
+ char *fname;
+ char *slno;
+ char *search;
+ char *tagstr;
+{
+ /* vim style is ctags:
+ *
+ * <tagstr>\t<filename>\t<linenum_or_search>"\t<extra>
+ *
+ * but as mentioned above, we'll always use the line number and
+ * put the search pattern (if one exists) as "extra"
+ *
+ * buf is used as part of vim's method of handling tags, and
+ * (i think) vim frees it when you pop your tags and get replaced
+ * by new ones on the tag stack.
+ */
+ char *buf;
+ int amt;
+
+ if (search != NULL)
+ {
+ amt = strlen(fname) + strlen(slno) + strlen(tagstr) + strlen(search)+6;
+ if ((buf = (char *)alloc(amt)) == NULL)
+ return NULL;
+
+ (void)sprintf(buf, "%s\t%s\t%s;\"\t%s", tagstr, fname, slno, search);
+ }
+ else
+ {
+ amt = strlen(fname) + strlen(slno) + strlen(tagstr) + 5;
+ if ((buf = (char *)alloc(amt)) == NULL)
+ return NULL;
+
+ (void)sprintf(buf, "%s\t%s\t%s;\"", tagstr, fname, slno);
+ }
+
+ return buf;
+} /* cs_make_vim_style_matches */
+
+
+/*
+ * PRIVATE: cs_manage_matches
+ *
+ * this is kind of hokey, but i don't see an easy way round this..
+ *
+ * Store: keep a ptr to the (malloc'd) memory of matches originally
+ * generated from cs_find(). the matches are originally lines directly
+ * from cscope output, but transformed to look like something out of a
+ * ctags. see cs_make_vim_style_matches for more details.
+ *
+ * Get: used only from cs_fgets(), this simulates a vim_fgets() to return
+ * the next line from the cscope output. it basically keeps track of which
+ * lines have been "used" and returns the next one.
+ *
+ * Free: frees up everything and resets
+ *
+ * Print: prints the tags
+ */
+ static char *
+cs_manage_matches(matches, contexts, totmatches, cmd)
+ char **matches;
+ char **contexts;
+ int totmatches;
+ mcmd_e cmd;
+{
+ static char **mp = NULL;
+ static char **cp = NULL;
+ static int cnt = -1;
+ static int next = -1;
+ char *p = NULL;
+
+ switch (cmd)
+ {
+ case Store:
+ assert(matches != NULL);
+ assert(totmatches > 0);
+ if (mp != NULL || cp != NULL)
+ (void)cs_manage_matches(NULL, NULL, -1, Free);
+ mp = matches;
+ cp = contexts;
+ cnt = totmatches;
+ next = 0;
+ break;
+ case Get:
+ if (next >= cnt)
+ return NULL;
+
+ p = mp[next];
+ next++;
+ break;
+ case Free:
+ if (mp != NULL)
+ {
+ if (cnt > 0)
+ while (cnt--)
+ {
+ vim_free(mp[cnt]);
+ if (cp != NULL)
+ vim_free(cp[cnt]);
+ }
+ vim_free(mp);
+ vim_free(cp);
+ }
+ mp = NULL;
+ cp = NULL;
+ cnt = 0;
+ next = 0;
+ break;
+ case Print:
+ cs_print_tags_priv(mp, cp, cnt);
+ break;
+ default: /* should not reach here */
+ (void)EMSG(_("E570: fatal error in cs_manage_matches"));
+ return NULL;
+ }
+
+ return p;
+} /* cs_manage_matches */
+
+
+/*
+ * PRIVATE: cs_parse_results
+ *
+ * parse cscope output
+ */
+ static char *
+cs_parse_results(cnumber, buf, bufsize, context, linenumber, search)
+ int cnumber;
+ char *buf;
+ int bufsize;
+ char **context;
+ char **linenumber;
+ char **search;
+{
+ int ch;
+ char *p;
+ char *name;
+
+ if (fgets(buf, bufsize, csinfo[cnumber].fr_fp) == NULL)
+ {
+ if (feof(csinfo[cnumber].fr_fp))
+ errno = EIO;
+
+ cs_reading_emsg(cnumber);
+
+ return NULL;
+ }
+
+ /* If the line's too long for the buffer, discard it. */
+ if ((p = strchr(buf, '\n')) == NULL)
+ {
+ while ((ch = getc(csinfo[cnumber].fr_fp)) != EOF && ch != '\n')
+ ;
+ return NULL;
+ }
+ *p = '\0';
+
+ /*
+ * cscope output is in the following format:
+ *
+ * <filename> <context> <line number> <pattern>
+ */
+ if ((name = strtok((char *)buf, (const char *)" ")) == NULL)
+ return NULL;
+ if ((*context = strtok(NULL, (const char *)" ")) == NULL)
+ return NULL;
+ if ((*linenumber = strtok(NULL, (const char *)" ")) == NULL)
+ return NULL;
+ *search = *linenumber + strlen(*linenumber) + 1; /* +1 to skip \0 */
+
+ /* --- nvi ---
+ * If the file is older than the cscope database, that is,
+ * the database was built since the file was last modified,
+ * or there wasn't a search string, use the line number.
+ */
+ if (strcmp(*search, "<unknown>") == 0)
+ *search = NULL;
+
+ name = cs_resolve_file(cnumber, name);
+ return name;
+}
+
+/*
+ * PRIVATE: cs_file_results
+ *
+ * write cscope find results to file
+ */
+ static void
+cs_file_results(f, nummatches_a)
+ FILE *f;
+ int *nummatches_a;
+{
+ int i, j;
+ char *buf;
+ char *search, *slno;
+ char *fullname;
+ char *cntx;
+ char *context;
+
+ buf = (char *)alloc(CSREAD_BUFSIZE);
+ if (buf == NULL)
+ return;
+
+ for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+ {
+ if (nummatches_a[i] < 1)
+ continue;
+
+ for (j = 0; j < nummatches_a[i]; j++)
+ {
+ if ((fullname=cs_parse_results(i, buf, CSREAD_BUFSIZE, &cntx,
+ &slno, &search))==NULL)
+ continue;
+
+ context = (char *)alloc(strlen(cntx)+5);
+ if (context==NULL)
+ continue;
+
+ if (strcmp(cntx, "<global>")==0)
+ strcpy(context, "<<global>>");
+ else
+ sprintf(context, "<<%s>>", cntx);
+
+ if (search==NULL)
+ fprintf(f, "%s\t%s\t%s\n", fullname, slno, context);
+ else
+ fprintf(f, "%s\t%s\t%s %s\n", fullname, slno, context, search);
+
+ vim_free(context);
+ vim_free(fullname);
+ } /* for all matches */
+
+ (void)cs_read_prompt(i);
+
+ } /* for all cscope connections */
+ vim_free(buf);
+}
+
+/*
+ * PRIVATE: cs_fill_results
+ *
+ * get parsed cscope output and calls cs_make_vim_style_matches to convert
+ * into ctags format
+ */
+ static void
+cs_fill_results(tagstr, totmatches, nummatches_a, matches_p, cntxts_p, matched)
+ char *tagstr;
+ int totmatches;
+ int *nummatches_a;
+ char ***matches_p;
+ char ***cntxts_p;
+ int *matched;
+{
+ int i, j;
+ char *buf;
+ char *search, *slno;
+ int totsofar = 0;
+ char **matches = NULL;
+ char **cntxts = NULL;
+ char *fullname;
+ char *cntx;
+
+ assert(totmatches > 0);
+
+ buf = (char *)alloc(CSREAD_BUFSIZE);
+ if (buf == NULL)
+ return;
+
+ if ((matches = (char **)alloc(sizeof(char *) * totmatches)) == NULL)
+ goto parse_out;
+ if ((cntxts = (char **)alloc(sizeof(char *) * totmatches)) == NULL)
+ goto parse_out;
+
+ for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+ {
+ if (nummatches_a[i] < 1)
+ continue;
+
+ for (j = 0; j < nummatches_a[i]; j++)
+ {
+ if ((fullname = cs_parse_results(i, buf, CSREAD_BUFSIZE, &cntx,
+ &slno, &search)) == NULL)
+ continue;
+
+ matches[totsofar] = cs_make_vim_style_matches(fullname, slno,
+ search, tagstr);
+
+ vim_free(fullname);
+
+ if (strcmp(cntx, "<global>") == 0)
+ cntxts[totsofar] = NULL;
+ else
+ /* note: if vim_strsave returns NULL, then the context
+ * will be "<global>", which is misleading.
+ */
+ cntxts[totsofar] = (char *)vim_strsave((char_u *)cntx);
+
+ if (matches[totsofar] != NULL)
+ totsofar++;
+
+ } /* for all matches */
+
+ (void)cs_read_prompt(i);
+
+ } /* for all cscope connections */
+
+parse_out:
+ *matched = totsofar;
+ *matches_p = matches;
+ *cntxts_p = cntxts;
+ vim_free(buf);
+} /* cs_fill_results */
+
+
+/* get the requested path components */
+ static char *
+cs_pathcomponents(path)
+ char *path;
+{
+ int i;
+ char *s;
+
+ if (p_cspc == 0)
+ return path;
+
+ s = path + strlen(path) - 1;
+ for (i = 0; i < p_cspc; ++i)
+ while (s > path && *--s != '/'
+#ifdef WIN32
+ && *--s != '\\'
+#endif
+ )
+ ;
+ if ((s > path && *s == '/')
+#ifdef WIN32
+ || (s > path && *s == '\\')
+#endif
+ )
+ ++s;
+ return s;
+}
+
+/*
+ * PRIVATE: cs_print_tags_priv
+ *
+ * called from cs_manage_matches()
+ */
+ static void
+cs_print_tags_priv(matches, cntxts, num_matches)
+ char **matches;
+ char **cntxts;
+ int num_matches;
+{
+ char *buf = NULL;
+ int bufsize = 0; /* Track available bufsize */
+ int newsize = 0;
+ char *ptag;
+ char *fname, *lno, *extra, *tbuf;
+ int i, idx, num;
+ char *globalcntx = "GLOBAL";
+ char *cntxformat = " <<%s>>";
+ char *context;
+ char *cstag_msg = _("Cscope tag: %s");
+ char *csfmt_str = "%4d %6s ";
+
+ assert (num_matches > 0);
+
+ if ((tbuf = (char *)alloc(strlen(matches[0]) + 1)) == NULL)
+ return;
+
+ strcpy(tbuf, matches[0]);
+ ptag = strtok(tbuf, "\t");
+
+ newsize = strlen(cstag_msg) + strlen(ptag);
+ buf = (char *)alloc(newsize);
+ if (buf != NULL)
+ {
+ bufsize = newsize;
+ (void)sprintf(buf, cstag_msg, ptag);
+ MSG_PUTS_ATTR(buf, hl_attr(HLF_T));
+ }
+
+ vim_free(tbuf);
+
+ MSG_PUTS_ATTR(_("\n # line"), hl_attr(HLF_T)); /* strlen is 7 */
+ msg_advance(msg_col + 2);
+ MSG_PUTS_ATTR(_("filename / context / line\n"), hl_attr(HLF_T));
+
+ num = 1;
+ for (i = 0; i < num_matches; i++)
+ {
+ idx = i;
+
+ /* if we really wanted to, we could avoid this malloc and strcpy
+ * by parsing matches[i] on the fly and placing stuff into buf
+ * directly, but that's too much of a hassle
+ */
+ if ((tbuf = (char *)alloc(strlen(matches[idx]) + 1)) == NULL)
+ continue;
+ (void)strcpy(tbuf, matches[idx]);
+
+ if ((fname = strtok(tbuf, (const char *)"\t")) == NULL)
+ continue;
+ if ((fname = strtok(NULL, (const char *)"\t")) == NULL)
+ continue;
+ if ((lno = strtok(NULL, (const char *)"\t")) == NULL)
+ {
+ /* if NULL, then no "extra", although in cscope's case, there
+ * should always be "extra".
+ */
+ extra = NULL;
+ }
+
+ extra = lno + strlen(lno) + 1;
+
+ lno[strlen(lno)-2] = '\0'; /* ignore ;" at the end */
+
+ /* hopefully 'num' (num of matches) will be less than 10^16 */
+ newsize = strlen(csfmt_str) + 16 + strlen(lno);
+ if (bufsize < newsize)
+ {
+ buf = (char *)vim_realloc(buf, newsize);
+ if (buf == NULL)
+ bufsize = 0;
+ else
+ bufsize = newsize;
+ }
+ if (buf != NULL)
+ {
+ /* csfmt_str = "%4d %6s "; */
+ (void)sprintf(buf, csfmt_str, num, lno);
+ MSG_PUTS_ATTR(buf, hl_attr(HLF_CM));
+ }
+ MSG_PUTS_LONG_ATTR(cs_pathcomponents(fname), hl_attr(HLF_CM));
+
+ /* compute the required space for the context */
+ if (cntxts[idx] != NULL)
+ context = cntxts[idx];
+ else
+ context = globalcntx;
+ newsize = strlen(context) + strlen(cntxformat);
+
+ if (bufsize < newsize)
+ {
+ buf = (char *)vim_realloc(buf, newsize);
+ if (buf == NULL)
+ bufsize = 0;
+ else
+ bufsize = newsize;
+ }
+ if (buf != NULL)
+ {
+ (void)sprintf(buf, cntxformat, context);
+
+ /* print the context only if it fits on the same line */
+ if (msg_col + (int)strlen(buf) >= (int)Columns)
+ msg_putchar('\n');
+ msg_advance(12);
+ MSG_PUTS_LONG(buf);
+ msg_putchar('\n');
+ }
+ if (extra != NULL)
+ {
+ msg_advance(13);
+ MSG_PUTS_LONG(extra);
+ }
+
+ vim_free(tbuf); /* only after printing extra due to strtok use */
+
+ if (msg_col)
+ msg_putchar('\n');
+
+ ui_breakcheck();
+ if (got_int)
+ {
+ got_int = FALSE; /* don't print any more matches */
+ break;
+ }
+
+ num++;
+ } /* for all matches */
+
+ vim_free(buf);
+} /* cs_print_tags_priv */
+
+
+/*
+ * PRIVATE: cs_read_prompt
+ *
+ * read a cscope prompt (basically, skip over the ">> ")
+ */
+ static int
+cs_read_prompt(i)
+ int i;
+{
+ int ch;
+ char *buf = NULL; /* buffer for possible error message from cscope */
+ int bufpos = 0;
+ char *cs_emsg;
+ int maxlen;
+ static char *eprompt = "Press the RETURN key to continue:";
+ int epromptlen = strlen(eprompt);
+ int n;
+
+ cs_emsg = _("E609: Cscope error: %s");
+ /* compute maximum allowed len for Cscope error message */
+ maxlen = (int)(IOSIZE - strlen(cs_emsg));
+
+ for (;;)
+ {
+ while ((ch = getc(csinfo[i].fr_fp)) != EOF && ch != CSCOPE_PROMPT[0])
+ /* if there is room and char is printable */
+ if (bufpos < maxlen - 1 && vim_isprintc(ch))
+ {
+ if (buf == NULL) /* lazy buffer allocation */
+ buf = (char *)alloc(maxlen);
+ if (buf != NULL)
+ {
+ /* append character to the message */
+ buf[bufpos++] = ch;
+ buf[bufpos] = NUL;
+ if (bufpos >= epromptlen
+ && strcmp(&buf[bufpos - epromptlen], eprompt) == 0)
+ {
+ /* remove eprompt from buf */
+ buf[bufpos - epromptlen] = NUL;
+
+ /* print message to user */
+ (void)EMSG2(cs_emsg, buf);
+
+ /* send RETURN to cscope */
+ (void)putc('\n', csinfo[i].to_fp);
+ (void)fflush(csinfo[i].to_fp);
+
+ /* clear buf */
+ bufpos = 0;
+ buf[bufpos] = NUL;
+ }
+ }
+ }
+
+ for (n = 0; n < (int)strlen(CSCOPE_PROMPT); ++n)
+ {
+ if (n > 0)
+ ch = getc(csinfo[i].fr_fp);
+ if (ch == EOF)
+ {
+ PERROR("cs_read_prompt EOF");
+ if (buf != NULL && buf[0] != NUL)
+ (void)EMSG2(cs_emsg, buf);
+ else if (p_csverbose)
+ cs_reading_emsg(i); /* don't have additional information */
+ cs_release_csp(i, TRUE);
+ vim_free(buf);
+ return CSCOPE_FAILURE;
+ }
+
+ if (ch != CSCOPE_PROMPT[n])
+ {
+ ch = EOF;
+ break;
+ }
+ }
+
+ if (ch == EOF)
+ continue; /* didn't find the prompt */
+ break; /* did find the prompt */
+ }
+
+ vim_free(buf);
+ return CSCOPE_SUCCESS;
+}
+
+
+/*
+ * PRIVATE: cs_release_csp
+ *
+ * does the actual free'ing for the cs ptr with an optional flag of whether
+ * or not to free the filename. called by cs_kill and cs_reset.
+ */
+ static void
+cs_release_csp(i, freefnpp)
+ int i;
+ int freefnpp;
+{
+#if defined(UNIX)
+ int pstat;
+#else
+ /*
+ * Trying to exit normally (not sure whether it is fit to UNIX cscope
+ */
+ if (csinfo[i].to_fp != NULL)
+ {
+ (void)fputs("q\n", csinfo[i].to_fp);
+ (void)fflush(csinfo[i].to_fp);
+ }
+ /* give cscope chance to exit normally */
+ if (csinfo[i].hProc > 0
+ && WaitForSingleObject(csinfo[i].hProc, 1000) == WAIT_TIMEOUT)
+ TerminateProcess(csinfo[i].hProc, 0);
+#endif
+
+ if (csinfo[i].fr_fp != NULL)
+ (void)fclose(csinfo[i].fr_fp);
+ if (csinfo[i].to_fp != NULL)
+ (void)fclose(csinfo[i].to_fp);
+
+ /*
+ * Safety check: If the PID would be zero here, the entire X session would
+ * be killed. -1 and 1 are dangerous as well.
+ */
+#if defined(UNIX)
+ if (csinfo[i].pid > 1)
+ {
+ kill(csinfo[i].pid, SIGTERM);
+ (void)waitpid(csinfo[i].pid, &pstat, 0);
+ }
+#endif
+
+ if (freefnpp)
+ {
+ vim_free(csinfo[i].fname);
+ vim_free(csinfo[i].ppath);
+ vim_free(csinfo[i].flags);
+ }
+
+ clear_csinfo(i);
+} /* cs_release_csp */
+
+
+/*
+ * PRIVATE: cs_reset
+ *
+ * calls cs_kill on all cscope connections then reinits
+ */
+/* ARGSUSED */
+ static int
+cs_reset(eap)
+ exarg_T *eap;
+{
+ char **dblist = NULL, **pplist = NULL, **fllist = NULL;
+ int i;
+ char buf[8]; /* for sprintf " (#%d)" */
+
+ /* malloc our db and ppath list */
+ dblist = (char **)alloc(CSCOPE_MAX_CONNECTIONS * sizeof(char *));
+ pplist = (char **)alloc(CSCOPE_MAX_CONNECTIONS * sizeof(char *));
+ fllist = (char **)alloc(CSCOPE_MAX_CONNECTIONS * sizeof(char *));
+ if (dblist == NULL || pplist == NULL || fllist == NULL)
+ {
+ vim_free(dblist);
+ vim_free(pplist);
+ vim_free(fllist);
+ return CSCOPE_FAILURE;
+ }
+
+ for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+ {
+ dblist[i] = csinfo[i].fname;
+ pplist[i] = csinfo[i].ppath;
+ fllist[i] = csinfo[i].flags;
+ if (csinfo[i].fname != NULL)
+ cs_release_csp(i, FALSE);
+ }
+
+ /* rebuild the cscope connection list */
+ for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+ {
+ if (dblist[i] != NULL)
+ {
+ cs_add_common(dblist[i], pplist[i], fllist[i]);
+ if (p_csverbose)
+ {
+ /* dont' use smsg_attr because want to display
+ * connection number in the same line as
+ * "Added cscope database..."
+ */
+ sprintf(buf, " (#%d)", i);
+ MSG_PUTS_ATTR(buf, hl_attr(HLF_R));
+ }
+ }
+ vim_free(dblist[i]);
+ vim_free(pplist[i]);
+ vim_free(fllist[i]);
+ }
+ vim_free(dblist);
+ vim_free(pplist);
+ vim_free(fllist);
+
+ if (p_csverbose)
+ MSG_ATTR(_("All cscope databases reset"), hl_attr(HLF_R) | MSG_HIST);
+ return CSCOPE_SUCCESS;
+} /* cs_reset */
+
+
+/*
+ * PRIVATE: cs_resolve_file
+ *
+ * construct the full pathname to a file found in the cscope database.
+ * (Prepends ppath, if there is one and if it's not already prepended,
+ * otherwise just uses the name found.)
+ *
+ * we need to prepend the prefix because on some cscope's (e.g., the one that
+ * ships with Solaris 2.6), the output never has the prefix prepended.
+ * contrast this with my development system (Digital Unix), which does.
+ */
+ static char *
+cs_resolve_file(i, name)
+ int i;
+ char *name;
+{
+ char *fullname;
+ int len;
+
+ /*
+ * ppath is freed when we destroy the cscope connection.
+ * fullname is freed after cs_make_vim_style_matches, after it's been
+ * copied into the tag buffer used by vim
+ */
+ len = strlen(name) + 2;
+ if (csinfo[i].ppath != NULL)
+ len += strlen(csinfo[i].ppath);
+
+ if ((fullname = (char *)alloc(len)) == NULL)
+ return NULL;
+
+ /*
+ * note/example: this won't work if the cscope output already starts
+ * "../.." and the prefix path is also "../..". if something like this
+ * happens, you are screwed up and need to fix how you're using cscope.
+ */
+ if (csinfo[i].ppath != NULL &&
+ (strncmp(name, csinfo[i].ppath, strlen(csinfo[i].ppath)) != 0) &&
+ (name[0] != '/')
+#ifdef WIN32
+ && name[0] != '\\' && name[1] != ':'
+#endif
+ )
+ (void)sprintf(fullname, "%s/%s", csinfo[i].ppath, name);
+ else
+ (void)sprintf(fullname, "%s", name);
+
+ return fullname;
+} /* cs_resolve_file */
+
+
+/*
+ * PRIVATE: cs_show
+ *
+ * show all cscope connections
+ */
+/* ARGSUSED */
+ static int
+cs_show(eap)
+ exarg_T *eap;
+{
+ short i;
+ if (cs_cnt_connections() == 0)
+ MSG_PUTS(_("no cscope connections\n"));
+ else
+ {
+ MSG_PUTS_ATTR(
+ _(" # pid database name prepend path\n"),
+ hl_attr(HLF_T));
+ for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+ {
+ if (csinfo[i].fname == NULL)
+ continue;
+
+ if (csinfo[i].ppath != NULL)
+ (void)smsg((char_u *)"%2d %-5ld %-34s %-32s",
+ i, (long)csinfo[i].pid, csinfo[i].fname, csinfo[i].ppath);
+ else
+ (void)smsg((char_u *)"%2d %-5ld %-34s <none>",
+ i, (long)csinfo[i].pid, csinfo[i].fname);
+ }
+ }
+
+ wait_return(TRUE);
+ return CSCOPE_SUCCESS;
+} /* cs_show */
+
+#endif /* FEAT_CSCOPE */
+
+/* the end */
diff --git a/src/if_cscope.h b/src/if_cscope.h
new file mode 100644
index 000000000..b3149d6c6
--- /dev/null
+++ b/src/if_cscope.h
@@ -0,0 +1,96 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * CSCOPE support for Vim added by Andy Kahn <kahn@zk3.dec.com>
+ * Ported to Win32 by Sergey Khorev <khorev@softlab.ru>
+ *
+ * The basic idea/structure of cscope for Vim was borrowed from Nvi.
+ * There might be a few lines of code that look similar to what Nvi
+ * has. If this is a problem and requires inclusion of the annoying
+ * BSD license, then sue me; I'm not worth much anyway.
+ */
+
+#if defined(FEAT_CSCOPE) || defined(PROTO)
+
+#if defined(UNIX)
+#include <sys/types.h> /* pid_t */
+#include <sys/stat.h> /* dev_t, ino_t */
+#elif defined (WIN32)
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+#endif
+
+#define CSCOPE_SUCCESS 0
+#define CSCOPE_FAILURE -1
+#define CSCOPE_MAX_CONNECTIONS 8 /* you actually need more? */
+
+#define CSCOPE_DBFILE "cscope.out"
+#define CSCOPE_PROMPT ">> "
+#define CSCOPE_QUERIES "sgdct efi"
+
+/*
+ * s 0name Find this C symbol
+ * g 1name Find this definition
+ * d 2name Find functions called by this function
+ * c 3name Find functions calling this function
+ * t 4string find text string (cscope 12.9)
+ * t 4name Find assignments to (cscope 13.3)
+ * 5pattern change pattern -- NOT USED
+ * e 6pattern Find this egrep pattern
+ * f 7name Find this file
+ * i 8name Find files #including this file
+ */
+#define FIND_USAGE "find c|d|e|f|g|i|s|t name"
+#define FIND_HELP "\n\
+ c: Find functions calling this function\n\
+ d: Find functions called by this function\n\
+ e: Find this egrep pattern\n\
+ f: Find this file\n\
+ g: Find this definition\n\
+ i: Find files #including this file\n\
+ s: Find this C symbol\n\
+ t: Find assignments to\n"
+
+
+typedef struct {
+ char * name;
+ int (*func) __ARGS((exarg_T *eap));
+ char * help;
+ char * usage;
+ int cansplit; /* if supports splitting window */
+} cscmd_T;
+
+typedef struct csi {
+ char * fname; /* cscope db name */
+ char * ppath; /* path to prepend (the -P option) */
+ char * flags; /* additional cscope flags/options (e.g, -p2) */
+#if defined(UNIX)
+ pid_t pid; /* PID of the connected cscope process. */
+ dev_t st_dev; /* ID of dev containing cscope db */
+ ino_t st_ino; /* inode number of cscope db */
+#elif defined(WIN32)
+ int pid; /* Can't get pid so set it to 0 ;) */
+ HANDLE hProc; /* cscope process handle */
+ DWORD nVolume; /* Volume serial number, instead of st_dev */
+ DWORD nIndexHigh; /* st_ino has no meaning in the Windows */
+ DWORD nIndexLow;
+#endif
+
+ FILE * fr_fp; /* from cscope: FILE. */
+ FILE * to_fp; /* to cscope: FILE. */
+} csinfo_T;
+
+typedef enum { Add, Find, Help, Kill, Reset, Show } csid_e;
+
+typedef enum {
+ Store,
+ Get,
+ Free,
+ Print
+} mcmd_e;
+
+
+#endif /* FEAT_CSCOPE */
+
+/* the end */
diff --git a/src/if_ole.cpp b/src/if_ole.cpp
new file mode 100644
index 000000000..bc57f1255
--- /dev/null
+++ b/src/if_ole.cpp
@@ -0,0 +1,778 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+#if defined(FEAT_OLE) && defined(FEAT_GUI_W32)
+/*
+ * OLE server implementation.
+ *
+ * See os_mswin.c for the client side.
+ */
+
+#include <windows.h>
+#include <oleauto.h>
+
+extern "C" {
+#include "vim.h"
+extern HWND s_hwnd;
+extern HWND vim_parent_hwnd;
+}
+
+#include "if_ole.h" // Interface definitions
+#include "iid_ole.c" // UUID definitions (compile here)
+
+/* Supply function prototype to work around bug in Mingw oleauto.h header */
+#ifdef __MINGW32__
+WINOLEAUTAPI UnRegisterTypeLib(REFGUID libID, WORD wVerMajor,
+ WORD wVerMinor, LCID lcid, SYSKIND syskind);
+#endif
+
+/*****************************************************************************
+ 1. Internal definitions for this file
+*****************************************************************************/
+
+class CVim;
+class CVimCF;
+
+/* Internal data */
+// The identifier of the registered class factory
+static unsigned long cf_id = 0;
+
+// The identifier of the running application object
+static unsigned long app_id = 0;
+
+// The single global instance of the class factory
+static CVimCF *cf = 0;
+
+// The single global instance of the application object
+static CVim *app = 0;
+
+/* GUIDs, versions and type library information */
+#define MYCLSID CLSID_Vim
+#define MYLIBID LIBID_Vim
+#define MYIID IID_IVim
+
+#define MAJORVER 1
+#define MINORVER 0
+#define LOCALE 0x0409
+
+#define MYNAME "Vim"
+#define MYPROGID "Vim.Application.1"
+#define MYVIPROGID "Vim.Application"
+
+#define MAX_CLSID_LEN 100
+
+/*****************************************************************************
+ 2. The application object
+*****************************************************************************/
+
+/* Definition
+ * ----------
+ */
+
+class CVim : public IVim
+{
+public:
+ ~CVim();
+ static CVim *Create(int* pbDoRestart);
+
+ // IUnknown members
+ STDMETHOD(QueryInterface)(REFIID riid, void ** ppv);
+ STDMETHOD_(unsigned long, AddRef)(void);
+ STDMETHOD_(unsigned long, Release)(void);
+
+ // IDispatch members
+ STDMETHOD(GetTypeInfoCount)(UINT *pCount);
+ STDMETHOD(GetTypeInfo)(UINT iTypeInfo, LCID, ITypeInfo **ppITypeInfo);
+ STDMETHOD(GetIDsOfNames)(const IID& iid, OLECHAR** names, UINT n, LCID, DISPID *dispids);
+ STDMETHOD(Invoke)(DISPID member, const IID& iid, LCID, WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr);
+
+ // IVim members
+ STDMETHOD(SendKeys)(BSTR keys);
+ STDMETHOD(Eval)(BSTR expr, BSTR *result);
+ STDMETHOD(SetForeground)(void);
+ STDMETHOD(GetHwnd)(UINT* result);
+
+private:
+ // Constructor is private - create using CVim::Create()
+ CVim() : ref(0), typeinfo(0) {};
+
+ // Reference count
+ unsigned long ref;
+
+ // The object's TypeInfo
+ ITypeInfo *typeinfo;
+};
+
+/* Implementation
+ * --------------
+ */
+
+CVim *CVim::Create(int* pbDoRestart)
+{
+ HRESULT hr;
+ CVim *me = 0;
+ ITypeLib *typelib = 0;
+ ITypeInfo *typeinfo = 0;
+
+ *pbDoRestart = FALSE;
+
+ // Create the object
+ me = new CVim();
+ if (me == NULL)
+ {
+ MessageBox(0, "Cannot create application object", "Vim Initialisation", 0);
+ return NULL;
+ }
+
+ // Load the type library from the registry
+ hr = LoadRegTypeLib(MYLIBID, 1, 0, 0x00, &typelib);
+ if (FAILED(hr))
+ {
+ HKEY hKey;
+
+ // Check we can write to the registry.
+ // RegCreateKeyEx succeeds even if key exists. W.Briscoe W2K 20021011
+ if (RegCreateKeyEx(HKEY_CLASSES_ROOT, MYVIPROGID, 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
+ {
+ delete me;
+ return NULL; // Unable to write to registry. Quietly fail.
+ }
+ RegCloseKey(hKey);
+
+ if (MessageBox(0, "Cannot load registered type library.\nDo you want to register Vim now?",
+ "Vim Initialisation", MB_YESNO | MB_ICONQUESTION) != IDYES)
+ {
+ delete me;
+ return NULL;
+ }
+
+ RegisterMe(FALSE);
+
+ // Load the type library from the registry
+ hr = LoadRegTypeLib(MYLIBID, 1, 0, 0x00, &typelib);
+ if (FAILED(hr))
+ {
+ MessageBox(0, "You must restart Vim in order for the registration to take effect.",
+ "Vim Initialisation", 0);
+ *pbDoRestart = TRUE;
+ delete me;
+ return NULL;
+ }
+ }
+
+ // Get the type info of the vtable interface
+ hr = typelib->GetTypeInfoOfGuid(MYIID, &typeinfo);
+ typelib->Release();
+
+ if (FAILED(hr))
+ {
+ MessageBox(0, "Cannot get interface type information",
+ "Vim Initialisation", 0);
+ delete me;
+ return NULL;
+ }
+
+ // Save the type information
+ me->typeinfo = typeinfo;
+ return me;
+}
+
+CVim::~CVim()
+{
+ if (typeinfo && vim_parent_hwnd == NULL)
+ typeinfo->Release();
+}
+
+STDMETHODIMP
+CVim::QueryInterface(REFIID riid, void **ppv)
+{
+ if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDispatch) || IsEqualIID(riid, MYIID))
+ {
+ AddRef();
+ *ppv = this;
+ return S_OK;
+ }
+
+ *ppv = 0;
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG)
+CVim::AddRef()
+{
+ return ++ref;
+}
+
+STDMETHODIMP_(ULONG)
+CVim::Release()
+{
+ // Don't delete the object when the reference count reaches zero, as there
+ // is only a single application object, and its lifetime is controlled by
+ // the running instance, not by its reference count.
+ if (ref > 0)
+ --ref;
+ return ref;
+}
+
+STDMETHODIMP
+CVim::GetTypeInfoCount(UINT *pCount)
+{
+ *pCount = 1;
+ return S_OK;
+}
+
+STDMETHODIMP
+CVim::GetTypeInfo(UINT iTypeInfo, LCID, ITypeInfo **ppITypeInfo)
+{
+ *ppITypeInfo = 0;
+
+ if (iTypeInfo != 0)
+ return DISP_E_BADINDEX;
+
+ typeinfo->AddRef();
+ *ppITypeInfo = typeinfo;
+ return S_OK;
+}
+
+STDMETHODIMP
+CVim::GetIDsOfNames(
+ const IID& iid,
+ OLECHAR** names,
+ UINT n,
+ LCID,
+ DISPID *dispids)
+{
+ if (iid != IID_NULL)
+ return DISP_E_UNKNOWNINTERFACE;
+
+ return typeinfo->GetIDsOfNames(names, n, dispids);
+}
+
+STDMETHODIMP
+CVim::Invoke(
+ DISPID member,
+ const IID& iid,
+ LCID,
+ WORD flags,
+ DISPPARAMS *dispparams,
+ VARIANT *result,
+ EXCEPINFO *excepinfo,
+ UINT *argerr)
+{
+ if (iid != IID_NULL)
+ return DISP_E_UNKNOWNINTERFACE;
+
+ ::SetErrorInfo(0, NULL);
+ return typeinfo->Invoke(static_cast<IDispatch*>(this),
+ member, flags, dispparams,
+ result, excepinfo, argerr);
+}
+
+STDMETHODIMP
+CVim::GetHwnd(UINT* result)
+{
+ *result = (UINT) s_hwnd;
+ return S_OK;
+}
+
+STDMETHODIMP
+CVim::SetForeground(void)
+{
+ /* Make the Vim window come to the foreground */
+ gui_mch_set_foreground();
+ return S_OK;
+}
+
+STDMETHODIMP
+CVim::SendKeys(BSTR keys)
+{
+ int len;
+ char *buffer;
+ char_u *str;
+ char_u *ptr;
+
+ /* Get a suitable buffer */
+ len = WideCharToMultiByte(CP_ACP, 0, keys, -1, 0, 0, 0, 0);
+ buffer = (char *)alloc(len+1);
+
+ if (buffer == NULL)
+ return E_OUTOFMEMORY;
+
+ len = WideCharToMultiByte(CP_ACP, 0, keys, -1, buffer, len, 0, 0);
+
+ if (len == 0)
+ {
+ vim_free(buffer);
+ return E_INVALIDARG;
+ }
+
+ /* Translate key codes like <Esc> */
+ str = replace_termcodes((char_u *)buffer, &ptr, FALSE, TRUE);
+
+ /* If ptr was set, then a new buffer was allocated,
+ * so we can free the old one.
+ */
+ if (ptr)
+ vim_free((char_u *)(buffer));
+
+ /* Reject strings too long to fit in the input buffer. Allow 10 bytes
+ * space to cover for the (remote) possibility that characters may enter
+ * the input buffer between now and when the WM_OLE message is actually
+ * processed. If more that 10 characters enter the input buffer in that
+ * time, the WM_OLE processing will simply fail to insert the characters.
+ */
+ if ((int)(STRLEN(str)) > (vim_free_in_input_buf() - 10))
+ {
+ vim_free(str);
+ return E_INVALIDARG;
+ }
+
+ /* Pass the string to the main input loop. The memory will be freed when
+ * the message is processed.
+ */
+ PostMessage(NULL, WM_OLE, 0, (LPARAM)str);
+
+ return S_OK;
+}
+
+STDMETHODIMP
+CVim::Eval(BSTR expr, BSTR *result)
+{
+#ifdef FEAT_EVAL
+ int len;
+ char *buffer;
+ char *str;
+ wchar_t *w_buffer;
+
+ /* Get a suitable buffer */
+ len = WideCharToMultiByte(CP_ACP, 0, expr, -1, 0, 0, 0, 0);
+ if (len == 0)
+ return E_INVALIDARG;
+
+ buffer = (char *)alloc((unsigned)len);
+
+ if (buffer == NULL)
+ return E_OUTOFMEMORY;
+
+ /* Convert the (wide character) expression to an ASCII string */
+ len = WideCharToMultiByte(CP_ACP, 0, expr, -1, buffer, len, 0, 0);
+ if (len == 0)
+ return E_INVALIDARG;
+
+ /* Evaluate the expression */
+ ++emsg_skip;
+ str = (char *)eval_to_string((char_u *)buffer, NULL);
+ --emsg_skip;
+ vim_free(buffer);
+ if (str == NULL)
+ return E_FAIL;
+
+ /* Convert the result to wide characters */
+ MultiByteToWideChar_alloc(CP_ACP, 0, str, -1, &w_buffer, &len);
+ vim_free(str);
+ if (w_buffer == NULL)
+ return E_OUTOFMEMORY;
+
+ if (len == 0)
+ {
+ vim_free(w_buffer);
+ return E_FAIL;
+ }
+
+ /* Store the result */
+ *result = SysAllocString(w_buffer);
+ vim_free(w_buffer);
+
+ return S_OK;
+#else
+ return E_NOTIMPL;
+#endif
+}
+
+/*****************************************************************************
+ 3. The class factory
+*****************************************************************************/
+
+/* Definition
+ * ----------
+ */
+
+class CVimCF : public IClassFactory
+{
+public:
+ static CVimCF *Create();
+
+ STDMETHOD(QueryInterface)(REFIID riid, void ** ppv);
+ STDMETHOD_(unsigned long, AddRef)(void);
+ STDMETHOD_(unsigned long, Release)(void);
+ STDMETHOD(CreateInstance)(IUnknown *punkOuter, REFIID riid, void ** ppv);
+ STDMETHOD(LockServer)(BOOL lock);
+
+private:
+ // Constructor is private - create via Create()
+ CVimCF() : ref(0) {};
+
+ // Reference count
+ unsigned long ref;
+};
+
+/* Implementation
+ * --------------
+ */
+
+CVimCF *CVimCF::Create()
+{
+ CVimCF *me = new CVimCF();
+
+ if (me == NULL)
+ MessageBox(0, "Cannot create class factory", "Vim Initialisation", 0);
+
+ return me;
+}
+
+STDMETHODIMP
+CVimCF::QueryInterface(REFIID riid, void **ppv)
+{
+ if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
+ {
+ AddRef();
+ *ppv = this;
+ return S_OK;
+ }
+
+ *ppv = 0;
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG)
+CVimCF::AddRef()
+{
+ return ++ref;
+}
+
+STDMETHODIMP_(ULONG)
+CVimCF::Release()
+{
+ // Don't delete the object when the reference count reaches zero, as there
+ // is only a single application object, and its lifetime is controlled by
+ // the running instance, not by its reference count.
+ if (ref > 0)
+ --ref;
+ return ref;
+}
+
+STDMETHODIMP
+CVimCF::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
+{
+ return app->QueryInterface(riid, ppv);
+}
+
+STDMETHODIMP
+CVimCF::LockServer(BOOL lock)
+{
+ return S_OK;
+}
+
+/*****************************************************************************
+ 4. Registry manipulation code
+*****************************************************************************/
+
+// Internal use only
+static void SetKeyAndValue(const char* path, const char* subkey, const char* value);
+static void GUIDtochar(const GUID& guid, char* GUID, int length);
+static void RecursiveDeleteKey(HKEY hKeyParent, const char* child);
+static const int GUID_STRING_SIZE = 39;
+
+// Register the component in the registry
+// When "silent" is TRUE don't give any messages.
+
+extern "C" void RegisterMe(int silent)
+{
+ BOOL ok = TRUE;
+
+ // Get the application startup command
+ char module[MAX_PATH];
+
+ ::GetModuleFileName(NULL, module, MAX_PATH);
+
+ // Unregister first (quietly)
+ UnregisterMe(FALSE);
+
+ // Convert the CLSID into a char
+ char clsid[GUID_STRING_SIZE];
+ GUIDtochar(MYCLSID, clsid, sizeof(clsid));
+
+ // Convert the LIBID into a char
+ char libid[GUID_STRING_SIZE];
+ GUIDtochar(MYLIBID, libid, sizeof(libid));
+
+ // Build the key CLSID\\{...}
+ char Key[MAX_CLSID_LEN];
+ strcpy(Key, "CLSID\\");
+ strcat(Key, clsid);
+
+ // Add the CLSID to the registry
+ SetKeyAndValue(Key, NULL, MYNAME);
+ SetKeyAndValue(Key, "LocalServer32", module);
+ SetKeyAndValue(Key, "ProgID", MYPROGID);
+ SetKeyAndValue(Key, "VersionIndependentProgID", MYVIPROGID);
+ SetKeyAndValue(Key, "TypeLib", libid);
+
+ // Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT
+ SetKeyAndValue(MYVIPROGID, NULL, MYNAME);
+ SetKeyAndValue(MYVIPROGID, "CLSID", clsid);
+ SetKeyAndValue(MYVIPROGID, "CurVer", MYPROGID);
+
+ // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT
+ SetKeyAndValue(MYPROGID, NULL, MYNAME);
+ SetKeyAndValue(MYPROGID, "CLSID", clsid);
+
+ wchar_t w_module[MAX_PATH];
+ MultiByteToWideChar(CP_ACP, 0, module, -1, w_module, MAX_PATH);
+
+ ITypeLib *typelib = NULL;
+ if (LoadTypeLib(w_module, &typelib) != S_OK)
+ {
+ if (!silent)
+ MessageBox(0, "Cannot load type library to register",
+ "Vim Registration", 0);
+ ok = FALSE;
+ }
+ else
+ {
+ if (RegisterTypeLib(typelib, w_module, NULL) != S_OK)
+ {
+ if (!silent)
+ MessageBox(0, "Cannot register type library",
+ "Vim Registration", 0);
+ ok = FALSE;
+ }
+ typelib->Release();
+ }
+
+ if (ok && !silent)
+ MessageBox(0, "Registered successfully", "Vim", 0);
+}
+
+// Remove the component from the registry
+//
+// Note: There is little error checking in this code, to allow incomplete
+// or failed registrations to be undone.
+extern "C" void UnregisterMe(int bNotifyUser)
+{
+ // Unregister the type library
+ ITypeLib *typelib;
+ if (SUCCEEDED(LoadRegTypeLib(MYLIBID, MAJORVER, MINORVER, LOCALE, &typelib)))
+ {
+ TLIBATTR *tla;
+ if (SUCCEEDED(typelib->GetLibAttr(&tla)))
+ {
+ UnRegisterTypeLib(tla->guid, tla->wMajorVerNum, tla->wMinorVerNum,
+ tla->lcid, tla->syskind);
+ typelib->ReleaseTLibAttr(tla);
+ }
+ typelib->Release();
+ }
+
+ // Convert the CLSID into a char
+ char clsid[GUID_STRING_SIZE];
+ GUIDtochar(MYCLSID, clsid, sizeof(clsid));
+
+ // Build the key CLSID\\{...}
+ char Key[MAX_CLSID_LEN];
+ strcpy(Key, "CLSID\\");
+ strcat(Key, clsid);
+
+ // Delete the CLSID Key - CLSID\{...}
+ RecursiveDeleteKey(HKEY_CLASSES_ROOT, Key);
+
+ // Delete the version-independent ProgID Key
+ RecursiveDeleteKey(HKEY_CLASSES_ROOT, MYVIPROGID);
+
+ // Delete the ProgID key
+ RecursiveDeleteKey(HKEY_CLASSES_ROOT, MYPROGID);
+
+ if (bNotifyUser)
+ MessageBox(0, "Unregistered successfully", "Vim", 0);
+}
+
+/****************************************************************************/
+
+// Convert a GUID to a char string
+static void GUIDtochar(const GUID& guid, char* GUID, int length)
+{
+ // Get wide string version
+ LPOLESTR wGUID = NULL;
+ StringFromCLSID(guid, &wGUID);
+
+ // Covert from wide characters to non-wide
+ wcstombs(GUID, wGUID, length);
+
+ // Free memory
+ CoTaskMemFree(wGUID);
+}
+
+// Delete a key and all of its descendents
+static void RecursiveDeleteKey(HKEY hKeyParent, const char* child)
+{
+ // Open the child
+ HKEY hKeyChild;
+ LONG result = RegOpenKeyEx(hKeyParent, child, 0, KEY_ALL_ACCESS, &hKeyChild);
+ if (result != ERROR_SUCCESS)
+ return;
+
+ // Enumerate all of the decendents of this child
+ FILETIME time;
+ char buffer[1024];
+ DWORD size = 1024;
+
+ while (RegEnumKeyEx(hKeyChild, 0, buffer, &size, NULL,
+ NULL, NULL, &time) == S_OK)
+ {
+ // Delete the decendents of this child
+ RecursiveDeleteKey(hKeyChild, buffer);
+ size = 256;
+ }
+
+ // Close the child
+ RegCloseKey(hKeyChild);
+
+ // Delete this child
+ RegDeleteKey(hKeyParent, child);
+}
+
+// Create a key and set its value
+static void SetKeyAndValue(const char* key, const char* subkey, const char* value)
+{
+ HKEY hKey;
+ char buffer[1024];
+
+ strcpy(buffer, key);
+
+ // Add subkey name to buffer.
+ if (subkey)
+ {
+ strcat(buffer, "\\");
+ strcat(buffer, subkey);
+ }
+
+ // Create and open key and subkey.
+ long result = RegCreateKeyEx(HKEY_CLASSES_ROOT,
+ buffer,
+ 0, NULL, REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS, NULL,
+ &hKey, NULL);
+ if (result != ERROR_SUCCESS)
+ return;
+
+ // Set the value
+ if (value)
+ RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)value,
+ (DWORD)STRLEN(value)+1);
+
+ RegCloseKey(hKey);
+}
+
+/*****************************************************************************
+ 5. OLE Initialisation and shutdown processing
+*****************************************************************************/
+extern "C" void InitOLE(int* pbDoRestart)
+{
+ HRESULT hr;
+
+ *pbDoRestart = FALSE;
+
+ // Initialize the OLE libraries
+ hr = OleInitialize(NULL);
+ if (FAILED(hr))
+ {
+ MessageBox(0, "Cannot initialise OLE", "Vim Initialisation", 0);
+ goto error0;
+ }
+
+ // Create the application object
+ app = CVim::Create(pbDoRestart);
+ if (app == NULL)
+ goto error1;
+
+ // Create the class factory
+ cf = CVimCF::Create();
+ if (cf == NULL)
+ goto error1;
+
+ // Register the class factory
+ hr = CoRegisterClassObject(
+ MYCLSID,
+ cf,
+ CLSCTX_LOCAL_SERVER,
+ REGCLS_MULTIPLEUSE,
+ &cf_id);
+
+ if (FAILED(hr))
+ {
+ MessageBox(0, "Cannot register class factory", "Vim Initialisation", 0);
+ goto error1;
+ }
+
+ // Register the application object as active
+ hr = RegisterActiveObject(
+ app,
+ MYCLSID,
+ NULL,
+ &app_id);
+
+ if (FAILED(hr))
+ {
+ MessageBox(0, "Cannot register application object", "Vim Initialisation", 0);
+ goto error1;
+ }
+
+ return;
+
+ // Errors: tidy up as much as needed and return
+error1:
+ UninitOLE();
+error0:
+ return;
+}
+
+extern "C" void UninitOLE()
+{
+ // Unregister the application object
+ if (app_id)
+ {
+ RevokeActiveObject(app_id, NULL);
+ app_id = 0;
+ }
+
+ // Unregister the class factory
+ if (cf_id)
+ {
+ CoRevokeClassObject(cf_id);
+ cf_id = 0;
+ }
+
+ // Shut down the OLE libraries
+ OleUninitialize();
+
+ // Delete the application object
+ if (app)
+ {
+ delete app;
+ app = NULL;
+ }
+
+ // Delete the class factory
+ if (cf)
+ {
+ delete cf;
+ cf = NULL;
+ }
+}
+#endif /* FEAT_OLE */
diff --git a/src/if_ole.h b/src/if_ole.h
new file mode 100644
index 000000000..30191b843
--- /dev/null
+++ b/src/if_ole.h
@@ -0,0 +1,289 @@
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+/* File created by MIDL compiler version 3.01.75 */
+/* at Wed Jun 06 18:20:37 2001
+ */
+/* Compiler settings for .\if_ole.idl:
+ Os (OptLev=s), W1, Zp8, env=Win32, ms_ext, c_ext
+ error checks: none
+*/
+//@@MIDL_FILE_HEADING( )
+#include "rpc.h"
+#include "rpcndr.h"
+#ifndef COM_NO_WINDOWS_H
+#include "windows.h"
+#include "ole2.h"
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __if_ole_h__
+#define __if_ole_h__
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/* Forward Declarations */
+
+#ifndef __IVim_FWD_DEFINED__
+#define __IVim_FWD_DEFINED__
+typedef interface IVim IVim;
+#endif /* __IVim_FWD_DEFINED__ */
+
+
+#ifndef __Vim_FWD_DEFINED__
+#define __Vim_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class Vim Vim;
+#else
+typedef struct Vim Vim;
+#endif /* __cplusplus */
+
+#endif /* __Vim_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "oaidl.h"
+
+void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
+void __RPC_USER MIDL_user_free( void __RPC_FAR * );
+
+#ifndef __IVim_INTERFACE_DEFINED__
+#define __IVim_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IVim
+ * at Wed Jun 06 18:20:37 2001
+ * using MIDL 3.01.75
+ ****************************************/
+/* [oleautomation][dual][unique][helpstring][uuid][object] */
+
+
+
+EXTERN_C const IID IID_IVim;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface DECLSPEC_UUID("0F0BFAE2-4C90-11d1-82D7-0004AC368519")
+ IVim : public IDispatch
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE SendKeys(
+ /* [in] */ BSTR keys) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Eval(
+ /* [in] */ BSTR expr,
+ /* [retval][out] */ BSTR __RPC_FAR *result) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetForeground( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHwnd(
+ /* [retval][out] */ UINT __RPC_FAR *result) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IVimVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
+ IVim __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
+ IVim __RPC_FAR * This);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
+ IVim __RPC_FAR * This);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount )(
+ IVim __RPC_FAR * This,
+ /* [out] */ UINT __RPC_FAR *pctinfo);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo )(
+ IVim __RPC_FAR * This,
+ /* [in] */ UINT iTInfo,
+ /* [in] */ LCID lcid,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames )(
+ IVim __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
+ /* [in] */ UINT cNames,
+ /* [in] */ LCID lcid,
+ /* [size_is][out] */ DISPID __RPC_FAR *rgDispId);
+
+ /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Invoke )(
+ IVim __RPC_FAR * This,
+ /* [in] */ DISPID dispIdMember,
+ /* [in] */ REFIID riid,
+ /* [in] */ LCID lcid,
+ /* [in] */ WORD wFlags,
+ /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
+ /* [out] */ VARIANT __RPC_FAR *pVarResult,
+ /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
+ /* [out] */ UINT __RPC_FAR *puArgErr);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SendKeys )(
+ IVim __RPC_FAR * This,
+ /* [in] */ BSTR keys);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Eval )(
+ IVim __RPC_FAR * This,
+ /* [in] */ BSTR expr,
+ /* [retval][out] */ BSTR __RPC_FAR *result);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetForeground )(
+ IVim __RPC_FAR * This);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetHwnd )(
+ IVim __RPC_FAR * This,
+ /* [retval][out] */ UINT __RPC_FAR *result);
+
+ END_INTERFACE
+ } IVimVtbl;
+
+ interface IVim
+ {
+ CONST_VTBL struct IVimVtbl __RPC_FAR *lpVtbl;
+ };
+
+#ifdef COBJMACROS
+
+
+#define IVim_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IVim_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IVim_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IVim_GetTypeInfoCount(This,pctinfo) \
+ (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)
+
+#define IVim_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
+ (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)
+
+#define IVim_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
+ (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)
+
+#define IVim_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
+ (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)
+
+
+#define IVim_SendKeys(This,keys) \
+ (This)->lpVtbl -> SendKeys(This,keys)
+
+#define IVim_Eval(This,expr,result) \
+ (This)->lpVtbl -> Eval(This,expr,result)
+
+#define IVim_SetForeground(This) \
+ (This)->lpVtbl -> SetForeground(This)
+
+#define IVim_GetHwnd(This,result) \
+ (This)->lpVtbl -> GetHwnd(This,result)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+HRESULT STDMETHODCALLTYPE IVim_SendKeys_Proxy(
+ IVim __RPC_FAR * This,
+ /* [in] */ BSTR keys);
+
+
+void __RPC_STUB IVim_SendKeys_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT STDMETHODCALLTYPE IVim_Eval_Proxy(
+ IVim __RPC_FAR * This,
+ /* [in] */ BSTR expr,
+ /* [retval][out] */ BSTR __RPC_FAR *result);
+
+
+void __RPC_STUB IVim_Eval_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT STDMETHODCALLTYPE IVim_SetForeground_Proxy(
+ IVim __RPC_FAR * This);
+
+
+void __RPC_STUB IVim_SetForeground_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT STDMETHODCALLTYPE IVim_GetHwnd_Proxy(
+ IVim __RPC_FAR * This,
+ /* [retval][out] */ UINT __RPC_FAR *result);
+
+
+void __RPC_STUB IVim_GetHwnd_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+
+#endif /* __IVim_INTERFACE_DEFINED__ */
+
+
+
+#ifndef __Vim_LIBRARY_DEFINED__
+#define __Vim_LIBRARY_DEFINED__
+
+/****************************************
+ * Generated header for library: Vim
+ * at Wed Jun 06 18:20:37 2001
+ * using MIDL 3.01.75
+ ****************************************/
+/* [version][helpstring][uuid] */
+
+
+
+EXTERN_C const IID LIBID_Vim;
+
+#ifdef __cplusplus
+EXTERN_C const CLSID CLSID_Vim;
+
+class DECLSPEC_UUID("0F0BFAE1-4C90-11d1-82D7-0004AC368519")
+Vim;
+#endif
+#endif /* __Vim_LIBRARY_DEFINED__ */
+
+/* Additional Prototypes for ALL interfaces */
+
+unsigned long __RPC_USER BSTR_UserSize( unsigned long __RPC_FAR *, unsigned long , BSTR __RPC_FAR * );
+unsigned char __RPC_FAR * __RPC_USER BSTR_UserMarshal( unsigned long __RPC_FAR *, unsigned char __RPC_FAR *, BSTR __RPC_FAR * );
+unsigned char __RPC_FAR * __RPC_USER BSTR_UserUnmarshal(unsigned long __RPC_FAR *, unsigned char __RPC_FAR *, BSTR __RPC_FAR * );
+void __RPC_USER BSTR_UserFree( unsigned long __RPC_FAR *, BSTR __RPC_FAR * );
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/if_ole.idl b/src/if_ole.idl
new file mode 100644
index 000000000..83cde3acd
--- /dev/null
+++ b/src/if_ole.idl
@@ -0,0 +1,45 @@
+// if_ole.idl - IDL source for the Vim OLE Automation interface
+//
+// Processed by the IDL compiler (MIDL) to generate the type library
+// (Vim.tlb).
+//
+// Command line:
+// MIDL /proxy nul /iid iid_ole.c /h if_ole.h /tlb vim.tlb if_ole.idl
+
+[
+ object,
+ uuid(0F0BFAE2-4C90-11d1-82D7-0004AC368519), // IID_IVim
+ helpstring("IVim"),
+ pointer_default(unique),
+ dual,
+ oleautomation
+]
+interface IVim : IDispatch
+{
+ import "oaidl.idl";
+ HRESULT SendKeys([in]BSTR keys);
+ HRESULT Eval([in]BSTR expr, [out, retval]BSTR* result);
+ HRESULT SetForeground(void);
+ HRESULT GetHwnd([out, retval]UINT* result);
+};
+
+// Component and type library definitions
+[
+ uuid(0F0BFAE0-4C90-11d1-82D7-0004AC368519), // LIBID_Vim
+ helpstring("Vim OLE Interface 1.1 Type Library"),
+ version(1.1)
+]
+library Vim
+{
+ importlib("stdole32.tlb");
+
+ // Component
+ [
+ uuid(0F0BFAE1-4C90-11d1-82D7-0004AC368519), // CLSID_Vim
+ helpstring("Vim OLE Interface")
+ ]
+ coclass Vim
+ {
+ [default] interface IVim;
+ };
+};
diff --git a/src/if_perl.xs b/src/if_perl.xs
new file mode 100644
index 000000000..96608ef6b
--- /dev/null
+++ b/src/if_perl.xs
@@ -0,0 +1,1150 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+/*
+ * if_perl.xs: Main code for Perl interface support.
+ * Mostly written by Sven Verdoolaege.
+ */
+
+#define _memory_h /* avoid memset redeclaration */
+#define IN_PERL_FILE /* don't include if_perl.pro from proto.h */
+
+#include "vim.h"
+
+
+/*
+ * Work around clashes between Perl and Vim namespace. proto.h doesn't
+ * include if_perl.pro and perlsfio.pro when IN_PERL_FILE is defined, because
+ * we need the CV typedef. proto.h can't be moved to after including
+ * if_perl.h, because we get all sorts of name clashes then.
+ */
+#ifndef PROTO
+#ifndef __MINGW32__
+# include "proto/if_perl.pro"
+# include "proto/if_perlsfio.pro"
+#endif
+#endif
+
+/* Perl compatibility stuff. This should ensure compatibility with older
+ * versions of Perl.
+ */
+
+#ifndef PERL_VERSION
+# include <patchlevel.h>
+# define PERL_REVISION 5
+# define PERL_VERSION PATCHLEVEL
+# define PERL_SUBVERSION SUBVERSION
+#endif
+
+#ifndef pTHX
+# define pTHX void
+# define pTHX_
+#endif
+
+#ifndef EXTERN_C
+# define EXTERN_C
+#endif
+
+/* Compatibility hacks over */
+
+static PerlInterpreter *perl_interp = NULL;
+static void xs_init __ARGS((pTHX));
+static void VIM_init __ARGS((void));
+EXTERN_C void boot_DynaLoader __ARGS((pTHX_ CV*));
+
+/*
+ * For dynamic linked perl. (Windows)
+ */
+#if defined(DYNAMIC_PERL) || defined(PROTO)
+/*
+ * Wrapper defines
+ */
+# define perl_alloc dll_perl_alloc
+# define perl_construct dll_perl_construct
+# define perl_parse dll_perl_parse
+# define perl_run dll_perl_run
+# define perl_destruct dll_perl_destruct
+# define perl_free dll_perl_free
+# define Perl_get_context dll_Perl_get_context
+# define Perl_croak dll_Perl_croak
+# ifndef PROTO
+# define Perl_croak_nocontext dll_Perl_croak_nocontext
+# define Perl_call_argv dll_Perl_call_argv
+# define Perl_call_pv dll_Perl_call_pv
+# define Perl_eval_sv dll_Perl_eval_sv
+# define Perl_get_sv dll_Perl_get_sv
+# define Perl_eval_pv dll_Perl_eval_pv
+# define Perl_call_method dll_Perl_call_method
+# endif
+# define Perl_dowantarray dll_Perl_dowantarray
+# define Perl_free_tmps dll_Perl_free_tmps
+# define Perl_gv_stashpv dll_Perl_gv_stashpv
+# define Perl_markstack_grow dll_Perl_markstack_grow
+# define Perl_mg_find dll_Perl_mg_find
+# define Perl_newXS dll_Perl_newXS
+# define Perl_newSV dll_Perl_newSV
+# define Perl_newSViv dll_Perl_newSViv
+# define Perl_newSVpv dll_Perl_newSVpv
+# define Perl_pop_scope dll_Perl_pop_scope
+# define Perl_push_scope dll_Perl_push_scope
+# define Perl_save_int dll_Perl_save_int
+# define Perl_stack_grow dll_Perl_stack_grow
+# define Perl_set_context dll_Perl_set_context
+# define Perl_sv_2bool dll_Perl_sv_2bool
+# define Perl_sv_2iv dll_Perl_sv_2iv
+# define Perl_sv_2mortal dll_Perl_sv_2mortal
+# if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
+# define Perl_sv_2pv_flags dll_Perl_sv_2pv_flags
+# define Perl_sv_2pv_nolen dll_Perl_sv_2pv_nolen
+# else
+# define Perl_sv_2pv dll_Perl_sv_2pv
+# endif
+# define Perl_sv_bless dll_Perl_sv_bless
+# if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
+# define Perl_sv_catpvn_flags dll_Perl_sv_catpvn_flags
+# else
+# define Perl_sv_catpvn dll_Perl_sv_catpvn
+# endif
+# define Perl_sv_free dll_Perl_sv_free
+# define Perl_sv_isa dll_Perl_sv_isa
+# define Perl_sv_magic dll_Perl_sv_magic
+# define Perl_sv_setiv dll_Perl_sv_setiv
+# define Perl_sv_setpv dll_Perl_sv_setpv
+# define Perl_sv_setpvn dll_Perl_sv_setpvn
+# if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
+# define Perl_sv_setsv_flags dll_Perl_sv_setsv_flags
+# else
+# define Perl_sv_setsv dll_Perl_sv_setsv
+# endif
+# define Perl_sv_upgrade dll_Perl_sv_upgrade
+# define Perl_Tstack_sp_ptr dll_Perl_Tstack_sp_ptr
+# define Perl_Top_ptr dll_Perl_Top_ptr
+# define Perl_Tstack_base_ptr dll_Perl_Tstack_base_ptr
+# define Perl_Tstack_max_ptr dll_Perl_Tstack_max_ptr
+# define Perl_Ttmps_ix_ptr dll_Perl_Ttmps_ix_ptr
+# define Perl_Ttmps_floor_ptr dll_Perl_Ttmps_floor_ptr
+# define Perl_Tmarkstack_ptr_ptr dll_Perl_Tmarkstack_ptr_ptr
+# define Perl_Tmarkstack_max_ptr dll_Perl_Tmarkstack_max_ptr
+# define Perl_TSv_ptr dll_Perl_TSv_ptr
+# define Perl_TXpv_ptr dll_Perl_TXpv_ptr
+# define Perl_Tna_ptr dll_Perl_Tna_ptr
+# define Perl_Idefgv_ptr dll_Perl_Idefgv_ptr
+# define Perl_Ierrgv_ptr dll_Perl_Ierrgv_ptr
+# define Perl_Isv_yes_ptr dll_Perl_Isv_yes_ptr
+# define boot_DynaLoader dll_boot_DynaLoader
+
+#ifndef DYNAMIC_PERL /* just generating prototypes */
+typedef int HANDLE;
+typedef int XSINIT_t;
+typedef int XSUBADDR_t;
+#endif
+
+/*
+ * Declare HANDLE for perl.dll and function pointers.
+ */
+static HANDLE hPerlLib = NULL;
+
+static PerlInterpreter* (*perl_alloc)();
+static void (*perl_construct)(PerlInterpreter*);
+static void (*perl_destruct)(PerlInterpreter*);
+static void (*perl_free)(PerlInterpreter*);
+static int (*perl_run)(PerlInterpreter*);
+static int (*perl_parse)(PerlInterpreter*, XSINIT_t, int, char**, char**);
+static void* (*Perl_get_context)(void);
+static void (*Perl_croak)(pTHX_ const char*, ...) __attribute__((noreturn));
+static void (*Perl_croak_nocontext)(const char*, ...) __attribute__((noreturn));
+static I32 (*Perl_dowantarray)(pTHX);
+static void (*Perl_free_tmps)(pTHX);
+static HV* (*Perl_gv_stashpv)(pTHX_ const char*, I32);
+static void (*Perl_markstack_grow)(pTHX);
+static MAGIC* (*Perl_mg_find)(pTHX_ SV*, int);
+static CV* (*Perl_newXS)(pTHX_ char*, XSUBADDR_t, char*);
+static SV* (*Perl_newSV)(pTHX_ STRLEN);
+static SV* (*Perl_newSViv)(pTHX_ IV);
+static SV* (*Perl_newSVpv)(pTHX_ const char*, STRLEN);
+static I32 (*Perl_call_argv)(pTHX_ const char*, I32, char**);
+static I32 (*Perl_call_pv)(pTHX_ const char*, I32);
+static I32 (*Perl_eval_sv)(pTHX_ SV*, I32);
+static SV* (*Perl_get_sv)(pTHX_ const char*, I32);
+static SV* (*Perl_eval_pv)(pTHX_ const char*, I32);
+static SV* (*Perl_call_method)(pTHX_ const char*, I32);
+static void (*Perl_pop_scope)(pTHX);
+static void (*Perl_push_scope)(pTHX);
+static void (*Perl_save_int)(pTHX_ int*);
+static SV** (*Perl_stack_grow)(pTHX_ SV**, SV**p, int);
+static SV** (*Perl_set_context)(void*);
+static bool (*Perl_sv_2bool)(pTHX_ SV*);
+static IV (*Perl_sv_2iv)(pTHX_ SV*);
+static SV* (*Perl_sv_2mortal)(pTHX_ SV*);
+#if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
+static char* (*Perl_sv_2pv_flags)(pTHX_ SV*, STRLEN*, I32);
+static char* (*Perl_sv_2pv_nolen)(pTHX_ SV*);
+#else
+static char* (*Perl_sv_2pv)(pTHX_ SV*, STRLEN*);
+#endif
+static SV* (*Perl_sv_bless)(pTHX_ SV*, HV*);
+#if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
+static void (*Perl_sv_catpvn_flags)(pTHX_ SV* , const char*, STRLEN, I32);
+#else
+static void (*Perl_sv_catpvn)(pTHX_ SV*, const char*, STRLEN);
+#endif
+static void (*Perl_sv_free)(pTHX_ SV*);
+static int (*Perl_sv_isa)(pTHX_ SV*, const char*);
+static void (*Perl_sv_magic)(pTHX_ SV*, SV*, int, const char*, I32);
+static void (*Perl_sv_setiv)(pTHX_ SV*, IV);
+static void (*Perl_sv_setpv)(pTHX_ SV*, const char*);
+static void (*Perl_sv_setpvn)(pTHX_ SV*, const char*, STRLEN);
+#if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
+static void (*Perl_sv_setsv_flags)(pTHX_ SV*, SV*, I32);
+#else
+static void (*Perl_sv_setsv)(pTHX_ SV*, SV*);
+#endif
+static bool (*Perl_sv_upgrade)(pTHX_ SV*, U32);
+static SV*** (*Perl_Tstack_sp_ptr)(register PerlInterpreter*);
+static OP** (*Perl_Top_ptr)(register PerlInterpreter*);
+static SV*** (*Perl_Tstack_base_ptr)(register PerlInterpreter*);
+static SV*** (*Perl_Tstack_max_ptr)(register PerlInterpreter*);
+static I32* (*Perl_Ttmps_ix_ptr)(register PerlInterpreter*);
+static I32* (*Perl_Ttmps_floor_ptr)(register PerlInterpreter*);
+static I32** (*Perl_Tmarkstack_ptr_ptr)(register PerlInterpreter*);
+static I32** (*Perl_Tmarkstack_max_ptr)(register PerlInterpreter*);
+static SV** (*Perl_TSv_ptr)(register PerlInterpreter*);
+static XPV** (*Perl_TXpv_ptr)(register PerlInterpreter*);
+static STRLEN* (*Perl_Tna_ptr)(register PerlInterpreter*);
+static GV** (*Perl_Idefgv_ptr)(register PerlInterpreter*);
+static GV** (*Perl_Ierrgv_ptr)(register PerlInterpreter*);
+static SV* (*Perl_Isv_yes_ptr)(register PerlInterpreter*);
+static void (*boot_DynaLoader)_((pTHX_ CV*));
+
+
+/*
+ * Table of name to function pointer of perl.
+ */
+#define PERL_PROC FARPROC
+static struct {
+ char* name;
+ PERL_PROC* ptr;
+} perl_funcname_table[] = {
+ {"perl_alloc", (PERL_PROC*)&perl_alloc},
+ {"perl_construct", (PERL_PROC*)&perl_construct},
+ {"perl_destruct", (PERL_PROC*)&perl_destruct},
+ {"perl_free", (PERL_PROC*)&perl_free},
+ {"perl_run", (PERL_PROC*)&perl_run},
+ {"perl_parse", (PERL_PROC*)&perl_parse},
+ {"Perl_get_context", (PERL_PROC*)&Perl_get_context},
+ {"Perl_croak", (PERL_PROC*)&Perl_croak},
+ {"Perl_croak_nocontext", (PERL_PROC*)&Perl_croak_nocontext},
+ {"Perl_dowantarray", (PERL_PROC*)&Perl_dowantarray},
+ {"Perl_free_tmps", (PERL_PROC*)&Perl_free_tmps},
+ {"Perl_gv_stashpv", (PERL_PROC*)&Perl_gv_stashpv},
+ {"Perl_markstack_grow", (PERL_PROC*)&Perl_markstack_grow},
+ {"Perl_mg_find", (PERL_PROC*)&Perl_mg_find},
+ {"Perl_newXS", (PERL_PROC*)&Perl_newXS},
+ {"Perl_newSV", (PERL_PROC*)&Perl_newSV},
+ {"Perl_newSViv", (PERL_PROC*)&Perl_newSViv},
+ {"Perl_newSVpv", (PERL_PROC*)&Perl_newSVpv},
+ {"Perl_call_argv", (PERL_PROC*)&Perl_call_argv},
+ {"Perl_call_pv", (PERL_PROC*)&Perl_call_pv},
+ {"Perl_eval_sv", (PERL_PROC*)&Perl_eval_sv},
+ {"Perl_get_sv", (PERL_PROC*)&Perl_get_sv},
+ {"Perl_eval_pv", (PERL_PROC*)&Perl_eval_pv},
+ {"Perl_call_method", (PERL_PROC*)&Perl_call_method},
+ {"Perl_pop_scope", (PERL_PROC*)&Perl_pop_scope},
+ {"Perl_push_scope", (PERL_PROC*)&Perl_push_scope},
+ {"Perl_save_int", (PERL_PROC*)&Perl_save_int},
+ {"Perl_stack_grow", (PERL_PROC*)&Perl_stack_grow},
+ {"Perl_set_context", (PERL_PROC*)&Perl_set_context},
+ {"Perl_sv_2bool", (PERL_PROC*)&Perl_sv_2bool},
+ {"Perl_sv_2iv", (PERL_PROC*)&Perl_sv_2iv},
+ {"Perl_sv_2mortal", (PERL_PROC*)&Perl_sv_2mortal},
+#if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
+ {"Perl_sv_2pv_flags", (PERL_PROC*)&Perl_sv_2pv_flags},
+ {"Perl_sv_2pv_nolen", (PERL_PROC*)&Perl_sv_2pv_nolen},
+#else
+ {"Perl_sv_2pv", (PERL_PROC*)&Perl_sv_2pv},
+#endif
+ {"Perl_sv_bless", (PERL_PROC*)&Perl_sv_bless},
+#if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
+ {"Perl_sv_catpvn_flags", (PERL_PROC*)&Perl_sv_catpvn_flags},
+#else
+ {"Perl_sv_catpvn", (PERL_PROC*)&Perl_sv_catpvn},
+#endif
+ {"Perl_sv_free", (PERL_PROC*)&Perl_sv_free},
+ {"Perl_sv_isa", (PERL_PROC*)&Perl_sv_isa},
+ {"Perl_sv_magic", (PERL_PROC*)&Perl_sv_magic},
+ {"Perl_sv_setiv", (PERL_PROC*)&Perl_sv_setiv},
+ {"Perl_sv_setpv", (PERL_PROC*)&Perl_sv_setpv},
+ {"Perl_sv_setpvn", (PERL_PROC*)&Perl_sv_setpvn},
+#if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
+ {"Perl_sv_setsv_flags", (PERL_PROC*)&Perl_sv_setsv_flags},
+#else
+ {"Perl_sv_setsv", (PERL_PROC*)&Perl_sv_setsv},
+#endif
+ {"Perl_sv_upgrade", (PERL_PROC*)&Perl_sv_upgrade},
+ {"Perl_Tstack_sp_ptr", (PERL_PROC*)&Perl_Tstack_sp_ptr},
+ {"Perl_Top_ptr", (PERL_PROC*)&Perl_Top_ptr},
+ {"Perl_Tstack_base_ptr", (PERL_PROC*)&Perl_Tstack_base_ptr},
+ {"Perl_Tstack_max_ptr", (PERL_PROC*)&Perl_Tstack_max_ptr},
+ {"Perl_Ttmps_ix_ptr", (PERL_PROC*)&Perl_Ttmps_ix_ptr},
+ {"Perl_Ttmps_floor_ptr", (PERL_PROC*)&Perl_Ttmps_floor_ptr},
+ {"Perl_Tmarkstack_ptr_ptr", (PERL_PROC*)&Perl_Tmarkstack_ptr_ptr},
+ {"Perl_Tmarkstack_max_ptr", (PERL_PROC*)&Perl_Tmarkstack_max_ptr},
+ {"Perl_TSv_ptr", (PERL_PROC*)&Perl_TSv_ptr},
+ {"Perl_TXpv_ptr", (PERL_PROC*)&Perl_TXpv_ptr},
+ {"Perl_Tna_ptr", (PERL_PROC*)&Perl_Tna_ptr},
+ {"Perl_Idefgv_ptr", (PERL_PROC*)&Perl_Idefgv_ptr},
+ {"Perl_Ierrgv_ptr", (PERL_PROC*)&Perl_Ierrgv_ptr},
+ {"Perl_Isv_yes_ptr", (PERL_PROC*)&Perl_Isv_yes_ptr},
+ {"boot_DynaLoader", (PERL_PROC*)&boot_DynaLoader},
+ {"", NULL},
+};
+
+/*
+ * Make all runtime-links of perl.
+ *
+ * 1. Get module handle using LoadLibraryEx.
+ * 2. Get pointer to perl function by GetProcAddress.
+ * 3. Repeat 2, until get all functions will be used.
+ *
+ * Parameter 'libname' provides name of DLL.
+ * Return OK or FAIL.
+ */
+ static int
+perl_runtime_link_init(char *libname, int verbose)
+{
+ int i;
+
+ if (hPerlLib != NULL)
+ return OK;
+ if (!(hPerlLib = LoadLibraryEx(libname, NULL, 0)))
+ {
+ if (verbose)
+ EMSG2(_("E370: Could not load library %s"), libname);
+ return FAIL;
+ }
+ for (i = 0; perl_funcname_table[i].ptr; ++i)
+ {
+ if (!(*perl_funcname_table[i].ptr = GetProcAddress(hPerlLib,
+ perl_funcname_table[i].name)))
+ {
+ FreeLibrary(hPerlLib);
+ hPerlLib = NULL;
+ if (verbose)
+ EMSG2(_(e_loadfunc), perl_funcname_table[i].name);
+ return FAIL;
+ }
+ }
+ return OK;
+}
+
+/*
+ * If runtime-link-perl(DLL) was loaded successfully, return TRUE.
+ * There were no DLL loaded, return FALSE.
+ */
+ int
+perl_enabled(verbose)
+ int verbose;
+{
+ return perl_runtime_link_init(DYNAMIC_PERL_DLL, verbose) == OK;
+}
+#endif /* DYNAMIC_PERL */
+
+/*
+ * perl_init(): initialize perl interpreter
+ * We have to call perl_parse to initialize some structures,
+ * there's nothing to actually parse.
+ */
+ static void
+perl_init()
+{
+ char *bootargs[] = { "VI", NULL };
+ static char *args[] = { "", "-e", "" };
+
+ perl_interp = perl_alloc();
+ perl_construct(perl_interp);
+ perl_parse(perl_interp, xs_init, 3, args, 0);
+ perl_call_argv("VIM::bootstrap", (long)G_DISCARD, bootargs);
+ VIM_init();
+#ifdef USE_SFIO
+ sfdisc(PerlIO_stdout(), sfdcnewvim());
+ sfdisc(PerlIO_stderr(), sfdcnewvim());
+ sfsetbuf(PerlIO_stdout(), NULL, 0);
+ sfsetbuf(PerlIO_stderr(), NULL, 0);
+#endif
+}
+
+/*
+ * perl_end(): clean up after ourselves
+ */
+ void
+perl_end()
+{
+ if (perl_interp)
+ {
+ perl_run(perl_interp);
+ perl_destruct(perl_interp);
+ perl_free(perl_interp);
+ perl_interp = NULL;
+ }
+#ifdef DYNAMIC_PERL
+ if (hPerlLib)
+ {
+ FreeLibrary(hPerlLib);
+ hPerlLib = NULL;
+ }
+#endif
+}
+
+/*
+ * msg_split(): send a message to the message handling routines
+ * split at '\n' first though.
+ */
+ void
+msg_split(s, attr)
+ char_u *s;
+ int attr; /* highlighting attributes */
+{
+ char *next;
+ char *token = (char *)s;
+
+ while ((next = strchr(token, '\n')))
+ {
+ *next++ = '\0'; /* replace \n with \0 */
+ msg_attr((char_u *)token, attr);
+ token = next;
+ }
+ if (*token)
+ msg_attr((char_u *)token, attr);
+}
+
+#ifndef FEAT_EVAL
+/*
+ * This stub is needed because an "#ifdef FEAT_EVAL" around Eval() doesn't
+ * work properly.
+ */
+ char_u *
+eval_to_string(arg, nextcmd)
+ char_u *arg;
+ char_u **nextcmd;
+{
+ return NULL;
+}
+#endif
+
+/*
+ * Create a new reference to an SV pointing to the SCR structure
+ * The perl_private part of the SCR structure points to the SV,
+ * so there can only be one such SV for a particular SCR structure.
+ * When the last reference has gone (DESTROY is called),
+ * perl_private is reset; When the screen goes away before
+ * all references are gone, the value of the SV is reset;
+ * any subsequent use of any of those reference will produce
+ * a warning. (see typemap)
+ */
+#define newANYrv(TYPE, TNAME) \
+static SV * \
+new ## TNAME ## rv(rv, ptr) \
+ SV *rv; \
+ TYPE *ptr; \
+{ \
+ sv_upgrade(rv, SVt_RV); \
+ if (!ptr->perl_private) \
+ { \
+ ptr->perl_private = newSV(0); \
+ sv_setiv(ptr->perl_private, (IV)ptr); \
+ } \
+ else \
+ SvREFCNT_inc(ptr->perl_private); \
+ SvRV(rv) = ptr->perl_private; \
+ SvROK_on(rv); \
+ return sv_bless(rv, gv_stashpv("VI" #TNAME, TRUE)); \
+}
+
+newANYrv(win_T, WIN)
+newANYrv(buf_T, BUF)
+
+/*
+ * perl_win_free
+ * Remove all refences to the window to be destroyed
+ */
+ void
+perl_win_free(wp)
+ win_T *wp;
+{
+ if (wp->perl_private)
+ sv_setiv((SV *)wp->perl_private, 0);
+ return;
+}
+
+ void
+perl_buf_free(bp)
+ buf_T *bp;
+{
+ if (bp->perl_private)
+ sv_setiv((SV *)bp->perl_private, 0);
+ return;
+}
+
+#ifndef PROTO
+# if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
+I32 cur_val(pTHX_ IV iv, SV *sv);
+# else
+I32 cur_val(IV iv, SV *sv);
+#endif
+
+/*
+ * Handler for the magic variables $main::curwin and $main::curbuf.
+ * The handler is put into the magic vtbl for these variables.
+ * (This is effectively a C-level equivalent of a tied variable).
+ * There is no "set" function as the variables are read-only.
+ */
+# if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
+I32 cur_val(pTHX_ IV iv, SV *sv)
+# else
+I32 cur_val(IV iv, SV *sv)
+# endif
+{
+ SV *rv;
+ if (iv == 0)
+ rv = newWINrv(newSV(0), curwin);
+ else
+ rv = newBUFrv(newSV(0), curbuf);
+ sv_setsv(sv, rv);
+ return 0;
+}
+#endif /* !PROTO */
+
+struct ufuncs cw_funcs = { cur_val, 0, 0 };
+struct ufuncs cb_funcs = { cur_val, 0, 1 };
+
+/*
+ * VIM_init(): Vim-specific initialisation.
+ * Make the magical main::curwin and main::curbuf variables
+ */
+ static void
+VIM_init()
+{
+ static char cw[] = "main::curwin";
+ static char cb[] = "main::curbuf";
+ SV *sv;
+
+ sv = perl_get_sv(cw, TRUE);
+ sv_magic(sv, NULL, 'U', (char *)&cw_funcs, sizeof(cw_funcs));
+ SvREADONLY_on(sv);
+
+ sv = perl_get_sv(cb, TRUE);
+ sv_magic(sv, NULL, 'U', (char *)&cb_funcs, sizeof(cb_funcs));
+ SvREADONLY_on(sv);
+
+ /*
+ * Setup the Safe compartment.
+ * It shouldn't be a fatal error if the Safe module is missing.
+ * XXX: Only shares the 'Msg' routine (which has to be called
+ * like 'Msg(...)').
+ */
+ (void)perl_eval_pv( "if ( eval( 'require Safe' ) ) { $VIM::safe = Safe->new(); $VIM::safe->share_from( 'VIM', ['Msg'] ); }", G_DISCARD | G_VOID );
+
+}
+
+#ifdef DYNAMIC_PERL
+static char *e_noperl = N_("Sorry, this command is disabled: the Perl library could not be loaded.");
+#endif
+
+/*
+ * ":perl"
+ */
+ void
+ex_perl(eap)
+ exarg_T *eap;
+{
+ char *err;
+ char *script;
+ STRLEN length;
+ SV *sv;
+ SV *safe;
+
+ script = (char *)script_get(eap, eap->arg);
+ if (eap->skip)
+ {
+ vim_free(script);
+ return;
+ }
+
+ if (perl_interp == NULL)
+ {
+#ifdef DYNAMIC_PERL
+ if (!perl_enabled(TRUE))
+ {
+ EMSG(_(e_noperl));
+ vim_free(script);
+ return;
+ }
+#endif
+ perl_init();
+ }
+
+ {
+ dSP;
+ ENTER;
+ SAVETMPS;
+
+ if (script == NULL)
+ sv = newSVpv((char *)eap->arg, 0);
+ else
+ {
+ sv = newSVpv(script, 0);
+ vim_free(script);
+ }
+
+#ifdef HAVE_SANDBOX
+ if (sandbox)
+ {
+ if ((safe = perl_get_sv( "VIM::safe", FALSE )) == NULL || !SvTRUE(safe))
+ EMSG(_("E299: Perl evaluation forbidden in sandbox without the Safe module"));
+ else
+ {
+ PUSHMARK(SP);
+ XPUSHs(safe);
+ XPUSHs(sv);
+ PUTBACK;
+ perl_call_method("reval", G_DISCARD);
+ }
+ }
+ else
+#endif
+ perl_eval_sv(sv, G_DISCARD | G_NOARGS);
+
+ SvREFCNT_dec(sv);
+
+ err = SvPV(GvSV(PL_errgv), length);
+
+ FREETMPS;
+ LEAVE;
+
+ if (!length)
+ return;
+
+ msg_split((char_u *)err, highlight_attr[HLF_E]);
+ return;
+ }
+}
+
+ static int
+replace_line(line, end)
+ linenr_T *line, *end;
+{
+ char *str;
+
+ if (SvOK(GvSV(PL_defgv)))
+ {
+ str = SvPV(GvSV(PL_defgv), PL_na);
+ ml_replace(*line, (char_u *)str, 1);
+ changed_bytes(*line, 0);
+ }
+ else
+ {
+ ml_delete(*line, FALSE);
+ deleted_lines_mark(*line, 1L);
+ --(*end);
+ --(*line);
+ }
+ return OK;
+}
+
+/*
+ * ":perldo".
+ */
+ void
+ex_perldo(eap)
+ exarg_T *eap;
+{
+ STRLEN length;
+ SV *sv;
+ char *str;
+ linenr_T i;
+
+ if (bufempty())
+ return;
+
+ if (perl_interp == NULL)
+ {
+#ifdef DYNAMIC_PERL
+ if (!perl_enabled(TRUE))
+ {
+ EMSG(_(e_noperl));
+ return;
+ }
+#endif
+ perl_init();
+ }
+ {
+ dSP;
+ length = strlen((char *)eap->arg);
+ sv = newSV(length + sizeof("sub VIM::perldo {")-1 + 1);
+ sv_setpvn(sv, "sub VIM::perldo {", sizeof("sub VIM::perldo {")-1);
+ sv_catpvn(sv, (char *)eap->arg, length);
+ sv_catpvn(sv, "}", 1);
+ perl_eval_sv(sv, G_DISCARD | G_NOARGS);
+ SvREFCNT_dec(sv);
+ str = SvPV(GvSV(PL_errgv), length);
+ if (length)
+ goto err;
+
+ if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
+ return;
+
+ ENTER;
+ SAVETMPS;
+ for (i = eap->line1; i <= eap->line2; i++)
+ {
+ sv_setpv(GvSV(PL_defgv),(char *)ml_get(i));
+ PUSHMARK(sp);
+ perl_call_pv("VIM::perldo", G_SCALAR | G_EVAL);
+ str = SvPV(GvSV(PL_errgv), length);
+ if (length)
+ break;
+ SPAGAIN;
+ if (SvTRUEx(POPs))
+ {
+ if (replace_line(&i, &eap->line2) != OK)
+ {
+ PUTBACK;
+ break;
+ }
+ }
+ PUTBACK;
+ }
+ FREETMPS;
+ LEAVE;
+ check_cursor();
+ update_screen(NOT_VALID);
+ if (!length)
+ return;
+
+err:
+ msg_split((char_u *)str, highlight_attr[HLF_E]);
+ return;
+ }
+}
+
+XS(XS_VIM_Msg);
+XS(XS_VIM_SetOption);
+XS(XS_VIM_DoCommand);
+XS(XS_VIM_Eval);
+XS(XS_VIM_Buffers);
+XS(XS_VIM_Windows);
+XS(XS_VIWIN_DESTROY);
+XS(XS_VIWIN_Buffer);
+XS(XS_VIWIN_SetHeight);
+XS(XS_VIWIN_Cursor);
+XS(XS_VIBUF_DESTROY);
+XS(XS_VIBUF_Name);
+XS(XS_VIBUF_Number);
+XS(XS_VIBUF_Count);
+XS(XS_VIBUF_Get);
+XS(XS_VIBUF_Set);
+XS(XS_VIBUF_Delete);
+XS(XS_VIBUF_Append);
+XS(boot_VIM);
+
+ static void
+xs_init(pTHX)
+{
+ char *file = __FILE__;
+
+ /* DynaLoader is a special case */
+ newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
+ newXS("VIM::bootstrap", boot_VIM, file);
+}
+
+typedef win_T * VIWIN;
+typedef buf_T * VIBUF;
+
+MODULE = VIM PACKAGE = VIM
+
+void
+Msg(text, hl=NULL)
+ char *text;
+ char *hl;
+
+ PREINIT:
+ int attr;
+ int id;
+
+ PPCODE:
+ if (text != NULL)
+ {
+ attr = 0;
+ if (hl != NULL)
+ {
+ id = syn_name2id((char_u *)hl);
+ if (id != 0)
+ attr = syn_id2attr(id);
+ }
+ msg_split((char_u *)text, attr);
+ }
+
+void
+SetOption(line)
+ char *line;
+
+ PPCODE:
+ if (line != NULL)
+ do_set((char_u *)line, 0);
+ update_screen(NOT_VALID);
+
+void
+DoCommand(line)
+ char *line;
+
+ PPCODE:
+ if (line != NULL)
+ do_cmdline_cmd((char_u *)line);
+
+void
+Eval(str)
+ char *str;
+
+ PREINIT:
+ char_u *value;
+ PPCODE:
+ value = eval_to_string((char_u *)str, (char_u**)0);
+ if (value == NULL)
+ {
+ XPUSHs(sv_2mortal(newSViv(0)));
+ XPUSHs(sv_2mortal(newSVpv("", 0)));
+ }
+ else
+ {
+ XPUSHs(sv_2mortal(newSViv(1)));
+ XPUSHs(sv_2mortal(newSVpv((char *)value, 0)));
+ vim_free(value);
+ }
+
+void
+Buffers(...)
+
+ PREINIT:
+ buf_T *vimbuf;
+ int i, b;
+
+ PPCODE:
+ if (items == 0)
+ {
+ if (GIMME == G_SCALAR)
+ {
+ i = 0;
+ for (vimbuf = firstbuf; vimbuf; vimbuf = vimbuf->b_next)
+ ++i;
+
+ XPUSHs(sv_2mortal(newSViv(i)));
+ }
+ else
+ {
+ for (vimbuf = firstbuf; vimbuf; vimbuf = vimbuf->b_next)
+ XPUSHs(newBUFrv(newSV(0), vimbuf));
+ }
+ }
+ else
+ {
+ for (i = 0; i < items; i++)
+ {
+ SV *sv = ST(i);
+ if (SvIOK(sv))
+ b = SvIV(ST(i));
+ else
+ {
+ char_u *pat;
+ STRLEN len;
+
+ pat = (char_u *)SvPV(sv, len);
+ ++emsg_off;
+ b = buflist_findpat(pat, pat+len, FALSE, FALSE);
+ --emsg_off;
+ }
+
+ if (b >= 0)
+ {
+ vimbuf = buflist_findnr(b);
+ if (vimbuf)
+ XPUSHs(newBUFrv(newSV(0), vimbuf));
+ }
+ }
+ }
+
+void
+Windows(...)
+
+ PREINIT:
+ win_T *vimwin;
+ int i, w;
+
+ PPCODE:
+ if (items == 0)
+ {
+ if (GIMME == G_SCALAR)
+ XPUSHs(sv_2mortal(newSViv(win_count())));
+ else
+ {
+ for (vimwin = firstwin; vimwin != NULL; vimwin = W_NEXT(vimwin))
+ XPUSHs(newWINrv(newSV(0), vimwin));
+ }
+ }
+ else
+ {
+ for (i = 0; i < items; i++)
+ {
+ w = SvIV(ST(i));
+ vimwin = win_find_nr(w);
+ if (vimwin)
+ XPUSHs(newWINrv(newSV(0), vimwin));
+ }
+ }
+
+MODULE = VIM PACKAGE = VIWIN
+
+void
+DESTROY(win)
+ VIWIN win
+
+ CODE:
+ if (win_valid(win))
+ win->perl_private = 0;
+
+SV *
+Buffer(win)
+ VIWIN win
+
+ CODE:
+ if (!win_valid(win))
+ win = curwin;
+ RETVAL = newBUFrv(newSV(0), win->w_buffer);
+ OUTPUT:
+ RETVAL
+
+void
+SetHeight(win, height)
+ VIWIN win
+ int height;
+
+ PREINIT:
+ win_T *savewin;
+
+ PPCODE:
+ if (!win_valid(win))
+ win = curwin;
+ savewin = curwin;
+ curwin = win;
+ win_setheight(height);
+ curwin = savewin;
+
+void
+Cursor(win, ...)
+ VIWIN win
+
+ PPCODE:
+ if(items == 1)
+ {
+ EXTEND(sp, 2);
+ if (!win_valid(win))
+ win = curwin;
+ PUSHs(sv_2mortal(newSViv(win->w_cursor.lnum)));
+ PUSHs(sv_2mortal(newSViv(win->w_cursor.col)));
+ }
+ else if(items == 3)
+ {
+ int lnum, col;
+
+ if (!win_valid(win))
+ win = curwin;
+ lnum = SvIV(ST(1));
+ col = SvIV(ST(2));
+ win->w_cursor.lnum = lnum;
+ win->w_cursor.col = col;
+ check_cursor(); /* put cursor on an existing line */
+ update_screen(NOT_VALID);
+ }
+
+MODULE = VIM PACKAGE = VIBUF
+
+void
+DESTROY(vimbuf)
+ VIBUF vimbuf;
+
+ CODE:
+ if (buf_valid(vimbuf))
+ vimbuf->perl_private = 0;
+
+void
+Name(vimbuf)
+ VIBUF vimbuf;
+
+ PPCODE:
+ if (!buf_valid(vimbuf))
+ vimbuf = curbuf;
+ /* No file name returns an empty string */
+ if (vimbuf->b_fname == NULL)
+ XPUSHs(sv_2mortal(newSVpv("", 0)));
+ else
+ XPUSHs(sv_2mortal(newSVpv((char *)vimbuf->b_fname, 0)));
+
+void
+Number(vimbuf)
+ VIBUF vimbuf;
+
+ PPCODE:
+ if (!buf_valid(vimbuf))
+ vimbuf = curbuf;
+ XPUSHs(sv_2mortal(newSViv(vimbuf->b_fnum)));
+
+void
+Count(vimbuf)
+ VIBUF vimbuf;
+
+ PPCODE:
+ if (!buf_valid(vimbuf))
+ vimbuf = curbuf;
+ XPUSHs(sv_2mortal(newSViv(vimbuf->b_ml.ml_line_count)));
+
+void
+Get(vimbuf, ...)
+ VIBUF vimbuf;
+
+ PREINIT:
+ char_u *line;
+ int i;
+ long lnum;
+ PPCODE:
+ if (buf_valid(vimbuf))
+ {
+ for (i = 1; i < items; i++)
+ {
+ lnum = SvIV(ST(i));
+ if (lnum > 0 && lnum <= vimbuf->b_ml.ml_line_count)
+ {
+ line = ml_get_buf(vimbuf, lnum, FALSE);
+ XPUSHs(sv_2mortal(newSVpv((char *)line, 0)));
+ }
+ }
+ }
+
+void
+Set(vimbuf, ...)
+ VIBUF vimbuf;
+
+ PREINIT:
+ int i;
+ long lnum;
+ char *line;
+ buf_T *savebuf;
+ PPCODE:
+ if (buf_valid(vimbuf))
+ {
+ if (items < 3)
+ croak("Usage: VIBUF::Set(vimbuf, lnum, @lines)");
+
+ lnum = SvIV(ST(1));
+ for(i = 2; i < items; i++, lnum++)
+ {
+ line = SvPV(ST(i),PL_na);
+ if (lnum > 0 && lnum <= vimbuf->b_ml.ml_line_count && line != NULL)
+ {
+ savebuf = curbuf;
+ curbuf = vimbuf;
+ if (u_savesub(lnum) == OK)
+ {
+ ml_replace(lnum, (char_u *)line, TRUE);
+ changed_bytes(lnum, 0);
+ }
+ curbuf = savebuf;
+ }
+ }
+ }
+
+void
+Delete(vimbuf, ...)
+ VIBUF vimbuf;
+
+ PREINIT:
+ long i, lnum = 0, count = 0;
+ buf_T *savebuf;
+ PPCODE:
+ if (buf_valid(vimbuf))
+ {
+ if (items == 2)
+ {
+ lnum = SvIV(ST(1));
+ count = 1;
+ }
+ else if (items == 3)
+ {
+ lnum = SvIV(ST(1));
+ count = 1 + SvIV(ST(2)) - lnum;
+ if(count == 0)
+ count = 1;
+ if(count < 0)
+ {
+ lnum -= count;
+ count = -count;
+ }
+ }
+ if (items >= 2)
+ {
+ for (i = 0; i < count; i++)
+ {
+ if (lnum > 0 && lnum <= vimbuf->b_ml.ml_line_count)
+ {
+ savebuf = curbuf;
+ curbuf = vimbuf;
+ if (u_savedel(lnum, 1) == OK)
+ {
+ ml_delete(lnum, 0);
+ deleted_lines_mark(lnum, 1L);
+ if (savebuf == curbuf)
+ check_cursor();
+ }
+ curbuf = savebuf;
+ update_curbuf(VALID);
+ }
+ }
+ }
+ }
+
+void
+Append(vimbuf, ...)
+ VIBUF vimbuf;
+
+ PREINIT:
+ int i;
+ long lnum;
+ char *line;
+ buf_T *savebuf;
+ PPCODE:
+ if (buf_valid(vimbuf))
+ {
+ if (items < 3)
+ croak("Usage: VIBUF::Append(vimbuf, lnum, @lines)");
+
+ lnum = SvIV(ST(1));
+ for (i = 2; i < items; i++, lnum++)
+ {
+ line = SvPV(ST(i),PL_na);
+ if (lnum >= 0 && lnum <= vimbuf->b_ml.ml_line_count && line != NULL)
+ {
+ savebuf = curbuf;
+ curbuf = vimbuf;
+ if (u_inssub(lnum + 1) == OK)
+ {
+ ml_append(lnum, (char_u *)line, (colnr_T)0, FALSE);
+ appended_lines_mark(lnum, 1L);
+ }
+ curbuf = savebuf;
+ update_curbuf(VALID);
+ }
+ }
+ }
+
diff --git a/src/if_perlsfio.c b/src/if_perlsfio.c
new file mode 100644
index 000000000..0ae1b956d
--- /dev/null
+++ b/src/if_perlsfio.c
@@ -0,0 +1,66 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * if_perlsfio.c: Special I/O functions for Perl interface.
+ */
+
+#define _memory_h /* avoid memset redeclaration */
+#define IN_PERL_FILE /* don't include if_perl.pro from prot.h */
+
+#include "vim.h"
+
+#if defined(USE_SFIO) || defined(PROTO)
+
+#ifndef USE_SFIO /* just generating prototypes */
+# define Sfio_t int
+# define Sfdisc_t int
+#endif
+
+#define NIL(type) ((type)0)
+
+ static int
+sfvimwrite(f, buf, n, disc)
+ Sfio_t *f; /* stream involved */
+ char *buf; /* buffer to read from */
+ int n; /* number of bytes to write */
+ Sfdisc_t *disc; /* discipline */
+{
+ char_u *str;
+
+ str = vim_strnsave((char_u *)buf, n);
+ if (str == NULL)
+ return 0;
+ msg_split((char *)str);
+ vim_free(str);
+
+ return n;
+}
+
+/*
+ * sfdcnewnvi --
+ * Create Vim discipline
+ */
+ Sfdisc_t *
+sfdcnewvim()
+{
+ Sfdisc_t *disc;
+
+ disc = (Sfdisc_t *)alloc((unsigned)sizeof(Sfdisc_t));
+ if (disc == NULL)
+ return NULL;
+
+ disc->readf = (Sfread_f)NULL;
+ disc->writef = sfvimwrite;
+ disc->seekf = (Sfseek_f)NULL;
+ disc->exceptf = (Sfexcept_f)NULL;
+
+ return disc;
+}
+
+#endif /* USE_SFIO */
diff --git a/src/if_python.c b/src/if_python.c
new file mode 100644
index 000000000..21c436520
--- /dev/null
+++ b/src/if_python.c
@@ -0,0 +1,2807 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * Python extensions by Paul Moore.
+ * Changes for Unix by David Leonard.
+ *
+ * This consists of four parts:
+ * 1. Python interpreter main program
+ * 2. Python output stream: writes output via [e]msg().
+ * 3. Implementation of the Vim module for Python
+ * 4. Utility functions for handling the interface between Vim and Python.
+ */
+
+#include "vim.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+
+/* Python.h defines _POSIX_THREADS itself (if needed) */
+#ifdef _POSIX_THREADS
+# undef _POSIX_THREADS
+#endif
+
+#if defined(_WIN32) && defined (HAVE_FCNTL_H)
+# undef HAVE_FCNTL_H
+#endif
+
+#ifdef _DEBUG
+# undef _DEBUG
+#endif
+
+#ifdef HAVE_STDARG_H
+# undef HAVE_STDARG_H /* Python's config.h defines it as well. */
+#endif
+
+#include <Python.h>
+#if defined(MACOS) && !defined(MACOS_X_UNIX)
+# include "macglue.h"
+# include <CodeFragments.h>
+#endif
+#undef main /* Defined in python.h - aargh */
+#undef HAVE_FCNTL_H /* Clash with os_win32.h */
+
+#if !defined(FEAT_PYTHON) && defined(PROTO)
+/* Use this to be able to generate prototypes without python being used. */
+# define PyObject int
+# define PyThreadState int
+# define PyTypeObject int
+struct PyMethodDef { int a; };
+# define PySequenceMethods int
+#endif
+
+/* Parser flags */
+#define single_input 256
+#define file_input 257
+#define eval_input 258
+
+#if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x020300F0
+ /* Python 2.3: can invoke ":python" recursively. */
+# define PY_CAN_RECURSE
+#endif
+
+#if defined(DYNAMIC_PYTHON) || defined(PROTO)
+# ifndef DYNAMIC_PYTHON
+# define HINSTANCE int /* for generating prototypes */
+# endif
+
+/*
+ * Wrapper defines
+ */
+# define PyArg_Parse dll_PyArg_Parse
+# define PyArg_ParseTuple dll_PyArg_ParseTuple
+# define PyDict_SetItemString dll_PyDict_SetItemString
+# define PyErr_BadArgument dll_PyErr_BadArgument
+# define PyErr_Clear dll_PyErr_Clear
+# define PyErr_NoMemory dll_PyErr_NoMemory
+# define PyErr_Occurred dll_PyErr_Occurred
+# define PyErr_SetNone dll_PyErr_SetNone
+# define PyErr_SetString dll_PyErr_SetString
+# define PyEval_InitThreads dll_PyEval_InitThreads
+# define PyEval_RestoreThread dll_PyEval_RestoreThread
+# define PyEval_SaveThread dll_PyEval_SaveThread
+# ifdef PY_CAN_RECURSE
+# define PyGILState_Ensure dll_PyGILState_Ensure
+# define PyGILState_Release dll_PyGILState_Release
+# endif
+# define PyInt_AsLong dll_PyInt_AsLong
+# define PyInt_FromLong dll_PyInt_FromLong
+# define PyInt_Type (*dll_PyInt_Type)
+# define PyList_GetItem dll_PyList_GetItem
+# define PyList_New dll_PyList_New
+# define PyList_SetItem dll_PyList_SetItem
+# define PyList_Size dll_PyList_Size
+# define PyList_Type (*dll_PyList_Type)
+# define PyImport_ImportModule dll_PyImport_ImportModule
+# define PyDict_GetItemString dll_PyDict_GetItemString
+# define PyModule_GetDict dll_PyModule_GetDict
+# define PyRun_SimpleString dll_PyRun_SimpleString
+# define PyString_AsString dll_PyString_AsString
+# define PyString_FromString dll_PyString_FromString
+# define PyString_FromStringAndSize dll_PyString_FromStringAndSize
+# define PyString_Size dll_PyString_Size
+# define PyString_Type (*dll_PyString_Type)
+# define PySys_SetObject dll_PySys_SetObject
+# define PySys_SetArgv dll_PySys_SetArgv
+# define PyType_Type (*dll_PyType_Type)
+# define Py_BuildValue dll_Py_BuildValue
+# define Py_FindMethod dll_Py_FindMethod
+# define Py_InitModule4 dll_Py_InitModule4
+# define Py_Initialize dll_Py_Initialize
+# define _PyObject_New dll__PyObject_New
+# define _Py_NoneStruct (*dll__Py_NoneStruct)
+# define PyObject_Init dll__PyObject_Init
+# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
+# define PyType_IsSubtype dll_PyType_IsSubtype
+# endif
+# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000
+# define PyObject_Malloc dll_PyObject_Malloc
+# define PyObject_Free dll_PyObject_Free
+# endif
+
+/*
+ * Pointers for dynamic link
+ */
+static int(*dll_PyArg_Parse)(PyObject *, char *, ...);
+static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...);
+static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item);
+static int(*dll_PyErr_BadArgument)(void);
+static void(*dll_PyErr_Clear)(void);
+static PyObject*(*dll_PyErr_NoMemory)(void);
+static PyObject*(*dll_PyErr_Occurred)(void);
+static void(*dll_PyErr_SetNone)(PyObject *);
+static void(*dll_PyErr_SetString)(PyObject *, const char *);
+static void(*dll_PyEval_InitThreads)(void);
+static void(*dll_PyEval_RestoreThread)(PyThreadState *);
+static PyThreadState*(*dll_PyEval_SaveThread)(void);
+# ifdef PY_CAN_RECURSE
+static PyGILState_STATE (*dll_PyGILState_Ensure)(void);
+static void (*dll_PyGILState_Release)(PyGILState_STATE);
+#endif
+static long(*dll_PyInt_AsLong)(PyObject *);
+static PyObject*(*dll_PyInt_FromLong)(long);
+static PyTypeObject* dll_PyInt_Type;
+static PyObject*(*dll_PyList_GetItem)(PyObject *, int);
+static PyObject*(*dll_PyList_New)(int size);
+static int(*dll_PyList_SetItem)(PyObject *, int, PyObject *);
+static int(*dll_PyList_Size)(PyObject *);
+static PyTypeObject* dll_PyList_Type;
+static PyObject*(*dll_PyImport_ImportModule)(const char *);
+static PyObject*(*dll_PyDict_GetItemString)(PyObject *, const char *);
+static PyObject*(*dll_PyModule_GetDict)(PyObject *);
+static int(*dll_PyRun_SimpleString)(char *);
+static char*(*dll_PyString_AsString)(PyObject *);
+static PyObject*(*dll_PyString_FromString)(const char *);
+static PyObject*(*dll_PyString_FromStringAndSize)(const char *, int);
+static int(*dll_PyString_Size)(PyObject *);
+static PyTypeObject* dll_PyString_Type;
+static int(*dll_PySys_SetObject)(char *, PyObject *);
+static int(*dll_PySys_SetArgv)(int, char **);
+static PyTypeObject* dll_PyType_Type;
+static PyObject*(*dll_Py_BuildValue)(char *, ...);
+static PyObject*(*dll_Py_FindMethod)(struct PyMethodDef[], PyObject *, char *);
+static PyObject*(*dll_Py_InitModule4)(char *, struct PyMethodDef *, char *, PyObject *, int);
+static void(*dll_Py_Initialize)(void);
+static PyObject*(*dll__PyObject_New)(PyTypeObject *, PyObject *);
+static PyObject*(*dll__PyObject_Init)(PyObject *, PyTypeObject *);
+static PyObject* dll__Py_NoneStruct;
+# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
+static int (*dll_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *);
+# endif
+# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000
+static void* (*dll_PyObject_Malloc)(size_t);
+static void (*dll_PyObject_Free)(void*);
+# endif
+
+static HINSTANCE hinstPython = 0; /* Instance of python.dll */
+
+/* Imported exception objects */
+static PyObject *imp_PyExc_AttributeError;
+static PyObject *imp_PyExc_IndexError;
+static PyObject *imp_PyExc_KeyboardInterrupt;
+static PyObject *imp_PyExc_TypeError;
+static PyObject *imp_PyExc_ValueError;
+
+# define PyExc_AttributeError imp_PyExc_AttributeError
+# define PyExc_IndexError imp_PyExc_IndexError
+# define PyExc_KeyboardInterrupt imp_PyExc_KeyboardInterrupt
+# define PyExc_TypeError imp_PyExc_TypeError
+# define PyExc_ValueError imp_PyExc_ValueError
+
+/*
+ * Table of name to function pointer of python.
+ */
+# define PYTHON_PROC FARPROC
+static struct
+{
+ char *name;
+ PYTHON_PROC *ptr;
+} python_funcname_table[] =
+{
+ {"PyArg_Parse", (PYTHON_PROC*)&dll_PyArg_Parse},
+ {"PyArg_ParseTuple", (PYTHON_PROC*)&dll_PyArg_ParseTuple},
+ {"PyDict_SetItemString", (PYTHON_PROC*)&dll_PyDict_SetItemString},
+ {"PyErr_BadArgument", (PYTHON_PROC*)&dll_PyErr_BadArgument},
+ {"PyErr_Clear", (PYTHON_PROC*)&dll_PyErr_Clear},
+ {"PyErr_NoMemory", (PYTHON_PROC*)&dll_PyErr_NoMemory},
+ {"PyErr_Occurred", (PYTHON_PROC*)&dll_PyErr_Occurred},
+ {"PyErr_SetNone", (PYTHON_PROC*)&dll_PyErr_SetNone},
+ {"PyErr_SetString", (PYTHON_PROC*)&dll_PyErr_SetString},
+ {"PyEval_InitThreads", (PYTHON_PROC*)&dll_PyEval_InitThreads},
+ {"PyEval_RestoreThread", (PYTHON_PROC*)&dll_PyEval_RestoreThread},
+ {"PyEval_SaveThread", (PYTHON_PROC*)&dll_PyEval_SaveThread},
+# ifdef PY_CAN_RECURSE
+ {"PyGILState_Ensure", (PYTHON_PROC*)&dll_PyGILState_Ensure},
+ {"PyGILState_Release", (PYTHON_PROC*)&dll_PyGILState_Release},
+# endif
+ {"PyInt_AsLong", (PYTHON_PROC*)&dll_PyInt_AsLong},
+ {"PyInt_FromLong", (PYTHON_PROC*)&dll_PyInt_FromLong},
+ {"PyInt_Type", (PYTHON_PROC*)&dll_PyInt_Type},
+ {"PyList_GetItem", (PYTHON_PROC*)&dll_PyList_GetItem},
+ {"PyList_New", (PYTHON_PROC*)&dll_PyList_New},
+ {"PyList_SetItem", (PYTHON_PROC*)&dll_PyList_SetItem},
+ {"PyList_Size", (PYTHON_PROC*)&dll_PyList_Size},
+ {"PyList_Type", (PYTHON_PROC*)&dll_PyList_Type},
+ {"PyImport_ImportModule", (PYTHON_PROC*)&dll_PyImport_ImportModule},
+ {"PyDict_GetItemString", (PYTHON_PROC*)&dll_PyDict_GetItemString},
+ {"PyModule_GetDict", (PYTHON_PROC*)&dll_PyModule_GetDict},
+ {"PyRun_SimpleString", (PYTHON_PROC*)&dll_PyRun_SimpleString},
+ {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString},
+ {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString},
+ {"PyString_FromStringAndSize", (PYTHON_PROC*)&dll_PyString_FromStringAndSize},
+ {"PyString_Size", (PYTHON_PROC*)&dll_PyString_Size},
+ {"PyString_Type", (PYTHON_PROC*)&dll_PyString_Type},
+ {"PySys_SetObject", (PYTHON_PROC*)&dll_PySys_SetObject},
+ {"PySys_SetArgv", (PYTHON_PROC*)&dll_PySys_SetArgv},
+ {"PyType_Type", (PYTHON_PROC*)&dll_PyType_Type},
+ {"Py_BuildValue", (PYTHON_PROC*)&dll_Py_BuildValue},
+ {"Py_FindMethod", (PYTHON_PROC*)&dll_Py_FindMethod},
+ {"Py_InitModule4", (PYTHON_PROC*)&dll_Py_InitModule4},
+ {"Py_Initialize", (PYTHON_PROC*)&dll_Py_Initialize},
+ {"_PyObject_New", (PYTHON_PROC*)&dll__PyObject_New},
+ {"PyObject_Init", (PYTHON_PROC*)&dll__PyObject_Init},
+ {"_Py_NoneStruct", (PYTHON_PROC*)&dll__Py_NoneStruct},
+# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
+ {"PyType_IsSubtype", (PYTHON_PROC*)&dll_PyType_IsSubtype},
+# endif
+# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000
+ {"PyObject_Malloc", (PYTHON_PROC*)&dll_PyObject_Malloc},
+ {"PyObject_Free", (PYTHON_PROC*)&dll_PyObject_Free},
+# endif
+ {"", NULL},
+};
+
+/*
+ * Free python.dll
+ */
+ static void
+end_dynamic_python(void)
+{
+ if (hinstPython)
+ {
+ FreeLibrary(hinstPython);
+ hinstPython = 0;
+ }
+}
+
+/*
+ * Load library and get all pointers.
+ * Parameter 'libname' provides name of DLL.
+ * Return OK or FAIL.
+ */
+ static int
+python_runtime_link_init(char *libname, int verbose)
+{
+ int i;
+
+ if (hinstPython)
+ return OK;
+ hinstPython = LoadLibrary(libname);
+ if (!hinstPython)
+ {
+ if (verbose)
+ EMSG2(_(e_loadlib), libname);
+ return FAIL;
+ }
+
+ for (i = 0; python_funcname_table[i].ptr; ++i)
+ {
+ if ((*python_funcname_table[i].ptr = GetProcAddress(hinstPython,
+ python_funcname_table[i].name)) == NULL)
+ {
+ FreeLibrary(hinstPython);
+ hinstPython = 0;
+ if (verbose)
+ EMSG2(_(e_loadfunc), python_funcname_table[i].name);
+ return FAIL;
+ }
+ }
+ return OK;
+}
+
+/*
+ * If python is enabled (there is installed python on Windows system) return
+ * TRUE, else FALSE.
+ */
+ int
+python_enabled(verbose)
+ int verbose;
+{
+ return python_runtime_link_init(DYNAMIC_PYTHON_DLL, verbose) == OK;
+}
+
+/* Load the standard Python exceptions - don't import the symbols from the
+ * DLL, as this can cause errors (importing data symbols is not reliable).
+ */
+static void get_exceptions __ARGS((void));
+
+ static void
+get_exceptions()
+{
+ PyObject *exmod = PyImport_ImportModule("exceptions");
+ PyObject *exdict = PyModule_GetDict(exmod);
+ imp_PyExc_AttributeError = PyDict_GetItemString(exdict, "AttributeError");
+ imp_PyExc_IndexError = PyDict_GetItemString(exdict, "IndexError");
+ imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt");
+ imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError");
+ imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError");
+ Py_XINCREF(imp_PyExc_AttributeError);
+ Py_XINCREF(imp_PyExc_IndexError);
+ Py_XINCREF(imp_PyExc_KeyboardInterrupt);
+ Py_XINCREF(imp_PyExc_TypeError);
+ Py_XINCREF(imp_PyExc_ValueError);
+ Py_XDECREF(exmod);
+}
+#endif /* DYNAMIC_PYTHON */
+
+/******************************************************
+ * Internal function prototypes.
+ */
+
+static void DoPythonCommand(exarg_T *, const char *);
+static int RangeStart;
+static int RangeEnd;
+
+static void PythonIO_Flush(void);
+static int PythonIO_Init(void);
+static int PythonMod_Init(void);
+
+/* Utility functions for the vim/python interface
+ * ----------------------------------------------
+ */
+static PyObject *GetBufferLine(buf_T *, int);
+static PyObject *GetBufferLineList(buf_T *, int, int);
+
+static int SetBufferLine(buf_T *, int, PyObject *, int *);
+static int SetBufferLineList(buf_T *, int, int, PyObject *, int *);
+static int InsertBufferLines(buf_T *, int, PyObject *, int *);
+
+static PyObject *LineToString(const char *);
+static char *StringToLine(PyObject *);
+
+static int VimErrorCheck(void);
+
+#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
+
+/******************************************************
+ * 1. Python interpreter main program.
+ */
+
+static int initialised = 0;
+
+#if PYTHON_API_VERSION < 1007 /* Python 1.4 */
+typedef PyObject PyThreadState;
+#endif /* Python 1.4 */
+
+#ifndef PY_CAN_RECURSE
+static PyThreadState* saved_python_thread = NULL;
+
+/*
+ * Suspend a thread of the Python interpreter, other threads are allowed to
+ * run.
+ */
+static void Python_SaveThread(void)
+{
+ saved_python_thread = PyEval_SaveThread();
+}
+
+/*
+ * Restore a thread of the Python interpreter, waits for other threads to
+ * block.
+ */
+static void Python_RestoreThread(void)
+{
+ PyEval_RestoreThread(saved_python_thread);
+ saved_python_thread = NULL;
+}
+#endif
+
+/*
+ * obtain a lock on the Vim data structures
+ */
+static void Python_Lock_Vim(void)
+{
+}
+
+/*
+ * release a lock on the Vim data structures
+ */
+static void Python_Release_Vim(void)
+{
+}
+
+ void
+python_end()
+{
+#ifdef DYNAMIC_PYTHON
+ end_dynamic_python();
+#endif
+}
+
+ static int
+Python_Init(void)
+{
+ if (!initialised)
+ {
+#ifdef DYNAMIC_PYTHON
+ if (!python_enabled(TRUE))
+ {
+ EMSG(_("E263: Sorry, this command is disabled, the Python library could not be loaded."));
+ goto fail;
+ }
+#endif
+
+#if !defined(MACOS) || defined(MACOS_X_UNIX)
+ Py_Initialize();
+#else
+ PyMac_Initialize();
+#endif
+ /* initialise threads */
+ PyEval_InitThreads();
+
+#ifdef DYNAMIC_PYTHON
+ get_exceptions();
+#endif
+
+ if (PythonIO_Init())
+ goto fail;
+
+ if (PythonMod_Init())
+ goto fail;
+
+#ifndef PY_CAN_RECURSE
+ /* the first python thread is vim's */
+ Python_SaveThread();
+#endif
+
+ initialised = 1;
+ }
+
+ return 0;
+
+fail:
+ /* We call PythonIO_Flush() here to print any Python errors.
+ * This is OK, as it is possible to call this function even
+ * if PythonIO_Init() has not completed successfully (it will
+ * not do anything in this case).
+ */
+ PythonIO_Flush();
+ return -1;
+}
+
+/*
+ * External interface
+ */
+ static void
+DoPythonCommand(exarg_T *eap, const char *cmd)
+{
+#ifdef PY_CAN_RECURSE
+ PyGILState_STATE pygilstate;
+#else
+ static int recursive = 0;
+#endif
+#if defined(MACOS) && !defined(MACOS_X_UNIX)
+ GrafPtr oldPort;
+#endif
+#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+ char *saved_locale;
+#endif
+
+#ifndef PY_CAN_RECURSE
+ if (recursive)
+ {
+ EMSG(_("E659: Cannot invoke Python recursively"));
+ return;
+ }
+ ++recursive;
+#endif
+
+#if defined(MACOS) && !defined(MACOS_X_UNIX)
+ GetPort(&oldPort);
+ /* Check if the Python library is available */
+ if ((Ptr)PyMac_Initialize == (Ptr)kUnresolvedCFragSymbolAddress)
+ goto theend;
+#endif
+ if (Python_Init())
+ goto theend;
+
+ RangeStart = eap->line1;
+ RangeEnd = eap->line2;
+ Python_Release_Vim(); /* leave vim */
+
+#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+ /* Python only works properly when the LC_NUMERIC locale is "C". */
+ saved_locale = setlocale(LC_NUMERIC, NULL);
+ if (saved_locale == NULL || STRCMP(saved_locale, "C") == 0)
+ saved_locale = NULL;
+ else
+ {
+ /* Need to make a copy, value may change when setting new locale. */
+ saved_locale = (char *)vim_strsave((char_u *)saved_locale);
+ (void)setlocale(LC_NUMERIC, "C");
+ }
+#endif
+
+#ifdef PY_CAN_RECURSE
+ pygilstate = PyGILState_Ensure();
+#else
+ Python_RestoreThread(); /* enter python */
+#endif
+
+ PyRun_SimpleString((char *)(cmd));
+
+#ifdef PY_CAN_RECURSE
+ PyGILState_Release(pygilstate);
+#else
+ Python_SaveThread(); /* leave python */
+#endif
+
+#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+ if (saved_locale != NULL)
+ {
+ (void)setlocale(LC_NUMERIC, saved_locale);
+ vim_free(saved_locale);
+ }
+#endif
+
+ Python_Lock_Vim(); /* enter vim */
+ PythonIO_Flush();
+#if defined(MACOS) && !defined(MACOS_X_UNIX)
+ SetPort(oldPort);
+#endif
+
+theend:
+#ifndef PY_CAN_RECURSE
+ --recursive;
+#endif
+ return; /* keeps lint happy */
+}
+
+/*
+ * ":python"
+ */
+ void
+ex_python(exarg_T *eap)
+{
+ char_u *script;
+
+ script = script_get(eap, eap->arg);
+ if (!eap->skip)
+ {
+ if (script == NULL)
+ DoPythonCommand(eap, (char *)eap->arg);
+ else
+ DoPythonCommand(eap, (char *)script);
+ }
+ vim_free(script);
+}
+
+#define BUFFER_SIZE 1024
+
+/*
+ * ":pyfile"
+ */
+ void
+ex_pyfile(exarg_T *eap)
+{
+ static char buffer[BUFFER_SIZE];
+ const char *file = (char *)eap->arg;
+ char *p;
+
+ /* Have to do it like this. PyRun_SimpleFile requires you to pass a
+ * stdio file pointer, but Vim and the Python DLL are compiled with
+ * different options under Windows, meaning that stdio pointers aren't
+ * compatible between the two. Yuk.
+ *
+ * Put the string "execfile('file')" into buffer. But, we need to
+ * escape any backslashes or single quotes in the file name, so that
+ * Python won't mangle the file name.
+ */
+ strcpy(buffer, "execfile('");
+ p = buffer + 10; /* size of "execfile('" */
+
+ while (*file && p < buffer + (BUFFER_SIZE - 3))
+ {
+ if (*file == '\\' || *file == '\'')
+ *p++ = '\\';
+ *p++ = *file++;
+ }
+
+ /* If we didn't finish the file name, we hit a buffer overflow */
+ if (*file != '\0')
+ return;
+
+ /* Put in the terminating "')" and a null */
+ *p++ = '\'';
+ *p++ = ')';
+ *p++ = '\0';
+
+ /* Execute the file */
+ DoPythonCommand(eap, buffer);
+}
+
+/******************************************************
+ * 2. Python output stream: writes output via [e]msg().
+ */
+
+/* Implementation functions
+ */
+
+static PyObject *OutputGetattr(PyObject *, char *);
+static int OutputSetattr(PyObject *, char *, PyObject *);
+
+static PyObject *OutputWrite(PyObject *, PyObject *);
+static PyObject *OutputWritelines(PyObject *, PyObject *);
+
+typedef void (*writefn)(char_u *);
+static void writer(writefn fn, char_u *str, int n);
+
+/* Output object definition
+ */
+
+typedef struct
+{
+ PyObject_HEAD
+ long softspace;
+ long error;
+} OutputObject;
+
+static struct PyMethodDef OutputMethods[] = {
+ /* name, function, calling, documentation */
+ {"write", OutputWrite, 1, "" },
+ {"writelines", OutputWritelines, 1, "" },
+ { NULL, NULL, 0, NULL }
+};
+
+static PyTypeObject OutputType = {
+ PyObject_HEAD_INIT(0)
+ 0,
+ "message",
+ sizeof(OutputObject),
+ 0,
+
+ (destructor) 0,
+ (printfunc) 0,
+ (getattrfunc) OutputGetattr,
+ (setattrfunc) OutputSetattr,
+ (cmpfunc) 0,
+ (reprfunc) 0,
+
+ 0, /* as number */
+ 0, /* as sequence */
+ 0, /* as mapping */
+
+ (hashfunc) 0,
+ (ternaryfunc) 0,
+ (reprfunc) 0
+};
+
+/*************/
+
+ static PyObject *
+OutputGetattr(PyObject *self, char *name)
+{
+ if (strcmp(name, "softspace") == 0)
+ return PyInt_FromLong(((OutputObject *)(self))->softspace);
+
+ return Py_FindMethod(OutputMethods, self, name);
+}
+
+ static int
+OutputSetattr(PyObject *self, char *name, PyObject *val)
+{
+ if (val == NULL) {
+ PyErr_SetString(PyExc_AttributeError, _("can't delete OutputObject attributes"));
+ return -1;
+ }
+
+ if (strcmp(name, "softspace") == 0)
+ {
+ if (!PyInt_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, _("softspace must be an integer"));
+ return -1;
+ }
+
+ ((OutputObject *)(self))->softspace = PyInt_AsLong(val);
+ return 0;
+ }
+
+ PyErr_SetString(PyExc_AttributeError, _("invalid attribute"));
+ return -1;
+}
+
+/*************/
+
+ static PyObject *
+OutputWrite(PyObject *self, PyObject *args)
+{
+ int len;
+ char *str;
+ int error = ((OutputObject *)(self))->error;
+
+ if (!PyArg_ParseTuple(args, "s#", &str, &len))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+ writer((writefn)(error ? emsg : msg), (char_u *)str, len);
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+ static PyObject *
+OutputWritelines(PyObject *self, PyObject *args)
+{
+ int n;
+ int i;
+ PyObject *list;
+ int error = ((OutputObject *)(self))->error;
+
+ if (!PyArg_ParseTuple(args, "O", &list))
+ return NULL;
+ Py_INCREF(list);
+
+ if (!PyList_Check(list)) {
+ PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
+ Py_DECREF(list);
+ return NULL;
+ }
+
+ n = PyList_Size(list);
+
+ for (i = 0; i < n; ++i)
+ {
+ PyObject *line = PyList_GetItem(list, i);
+ char *str;
+ int len;
+
+ if (!PyArg_Parse(line, "s#", &str, &len)) {
+ PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
+ Py_DECREF(list);
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+ writer((writefn)(error ? emsg : msg), (char_u *)str, len);
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+ }
+
+ Py_DECREF(list);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* Output buffer management
+ */
+
+static char_u *buffer = NULL;
+static int buffer_len = 0;
+static int buffer_size = 0;
+
+static writefn old_fn = NULL;
+
+ static void
+buffer_ensure(int n)
+{
+ int new_size;
+ char_u *new_buffer;
+
+ if (n < buffer_size)
+ return;
+
+ new_size = buffer_size;
+ while (new_size < n)
+ new_size += 80;
+
+ if (new_size != buffer_size)
+ {
+ new_buffer = alloc((unsigned)new_size);
+ if (new_buffer == NULL)
+ return;
+
+ if (buffer)
+ {
+ memcpy(new_buffer, buffer, buffer_len);
+ vim_free(buffer);
+ }
+
+ buffer = new_buffer;
+ buffer_size = new_size;
+ }
+}
+
+ static void
+PythonIO_Flush(void)
+{
+ if (old_fn && buffer_len)
+ {
+ buffer[buffer_len] = 0;
+ old_fn(buffer);
+ }
+
+ buffer_len = 0;
+}
+
+ static void
+writer(writefn fn, char_u *str, int n)
+{
+ char_u *ptr;
+
+ if (fn != old_fn && old_fn != NULL)
+ PythonIO_Flush();
+
+ old_fn = fn;
+
+ while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL)
+ {
+ int len = ptr - str;
+
+ buffer_ensure(buffer_len + len + 1);
+
+ memcpy(buffer + buffer_len, str, len);
+ buffer_len += len;
+ buffer[buffer_len] = 0;
+ fn(buffer);
+ str = ptr + 1;
+ n -= len + 1;
+ buffer_len = 0;
+ }
+
+ /* Put the remaining text into the buffer for later printing */
+ buffer_ensure(buffer_len + n + 1);
+ memcpy(buffer + buffer_len, str, n);
+ buffer_len += n;
+}
+
+/***************/
+
+static OutputObject Output =
+{
+ PyObject_HEAD_INIT(&OutputType)
+ 0,
+ 0
+};
+
+static OutputObject Error =
+{
+ PyObject_HEAD_INIT(&OutputType)
+ 0,
+ 1
+};
+
+ static int
+PythonIO_Init(void)
+{
+ /* Fixups... */
+ OutputType.ob_type = &PyType_Type;
+
+ PySys_SetObject("stdout", (PyObject *)(&Output));
+ PySys_SetObject("stderr", (PyObject *)(&Error));
+
+ if (PyErr_Occurred())
+ {
+ EMSG(_("E264: Python: Error initialising I/O objects"));
+ return -1;
+ }
+
+ return 0;
+}
+
+/******************************************************
+ * 3. Implementation of the Vim module for Python
+ */
+
+/* Vim module - Implementation functions
+ * -------------------------------------
+ */
+
+static PyObject *VimError;
+
+static PyObject *VimCommand(PyObject *, PyObject *);
+static PyObject *VimEval(PyObject *, PyObject *);
+
+/* Window type - Implementation functions
+ * --------------------------------------
+ */
+
+typedef struct
+{
+ PyObject_HEAD
+ win_T *win;
+}
+WindowObject;
+
+#define INVALID_WINDOW_VALUE ((win_T *)(-1))
+
+#define WindowType_Check(obj) ((obj)->ob_type == &WindowType)
+
+static PyObject *WindowNew(win_T *);
+
+static void WindowDestructor(PyObject *);
+static PyObject *WindowGetattr(PyObject *, char *);
+static int WindowSetattr(PyObject *, char *, PyObject *);
+static PyObject *WindowRepr(PyObject *);
+
+/* Buffer type - Implementation functions
+ * --------------------------------------
+ */
+
+typedef struct
+{
+ PyObject_HEAD
+ buf_T *buf;
+}
+BufferObject;
+
+#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
+
+#define BufferType_Check(obj) ((obj)->ob_type == &BufferType)
+
+static PyObject *BufferNew (buf_T *);
+
+static void BufferDestructor(PyObject *);
+static PyObject *BufferGetattr(PyObject *, char *);
+static PyObject *BufferRepr(PyObject *);
+
+static int BufferLength(PyObject *);
+static PyObject *BufferItem(PyObject *, int);
+static PyObject *BufferSlice(PyObject *, int, int);
+static int BufferAssItem(PyObject *, int, PyObject *);
+static int BufferAssSlice(PyObject *, int, int, PyObject *);
+
+static PyObject *BufferAppend(PyObject *, PyObject *);
+static PyObject *BufferMark(PyObject *, PyObject *);
+static PyObject *BufferRange(PyObject *, PyObject *);
+
+/* Line range type - Implementation functions
+ * --------------------------------------
+ */
+
+typedef struct
+{
+ PyObject_HEAD
+ BufferObject *buf;
+ int start;
+ int end;
+}
+RangeObject;
+
+#define RangeType_Check(obj) ((obj)->ob_type == &RangeType)
+
+static PyObject *RangeNew(buf_T *, int, int);
+
+static void RangeDestructor(PyObject *);
+static PyObject *RangeGetattr(PyObject *, char *);
+static PyObject *RangeRepr(PyObject *);
+
+static int RangeLength(PyObject *);
+static PyObject *RangeItem(PyObject *, int);
+static PyObject *RangeSlice(PyObject *, int, int);
+static int RangeAssItem(PyObject *, int, PyObject *);
+static int RangeAssSlice(PyObject *, int, int, PyObject *);
+
+static PyObject *RangeAppend(PyObject *, PyObject *);
+
+/* Window list type - Implementation functions
+ * -------------------------------------------
+ */
+
+static int WinListLength(PyObject *);
+static PyObject *WinListItem(PyObject *, int);
+
+/* Buffer list type - Implementation functions
+ * -------------------------------------------
+ */
+
+static int BufListLength(PyObject *);
+static PyObject *BufListItem(PyObject *, int);
+
+/* Current objects type - Implementation functions
+ * -----------------------------------------------
+ */
+
+static PyObject *CurrentGetattr(PyObject *, char *);
+static int CurrentSetattr(PyObject *, char *, PyObject *);
+
+/* Vim module - Definitions
+ */
+
+static struct PyMethodDef VimMethods[] = {
+ /* name, function, calling, documentation */
+ {"command", VimCommand, 1, "" },
+ {"eval", VimEval, 1, "" },
+ { NULL, NULL, 0, NULL }
+};
+
+/* Vim module - Implementation
+ */
+/*ARGSUSED*/
+ static PyObject *
+VimCommand(PyObject *self, PyObject *args)
+{
+ char *cmd;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "s", &cmd))
+ return NULL;
+
+ PyErr_Clear();
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+
+ do_cmdline_cmd((char_u *)cmd);
+ update_screen(VALID);
+
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+
+ if (VimErrorCheck())
+ result = NULL;
+ else
+ result = Py_None;
+
+ Py_XINCREF(result);
+ return result;
+}
+
+/*ARGSUSED*/
+ static PyObject *
+VimEval(PyObject *self, PyObject *args)
+{
+#ifdef FEAT_EVAL
+ char *expr;
+ char *str;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "s", &expr))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+ str = (char *)eval_to_string((char_u *)expr, NULL);
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+
+ if (str == NULL)
+ {
+ PyErr_SetVim(_("invalid expression"));
+ return NULL;
+ }
+
+ result = Py_BuildValue("s", str);
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+ vim_free(str);
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+
+ return result;
+#else
+ PyErr_SetVim(_("expressions disabled at compile time"));
+ return NULL;
+#endif
+}
+
+/* Common routines for buffers and line ranges
+ * -------------------------------------------
+ */
+ static int
+CheckBuffer(BufferObject *this)
+{
+ if (this->buf == INVALID_BUFFER_VALUE)
+ {
+ PyErr_SetVim(_("attempt to refer to deleted buffer"));
+ return -1;
+ }
+
+ return 0;
+}
+
+ static PyObject *
+RBItem(BufferObject *self, int n, int start, int end)
+{
+ if (CheckBuffer(self))
+ return NULL;
+
+ if (n < 0 || n > end - start)
+ {
+ PyErr_SetString(PyExc_IndexError, _("line number out of range"));
+ return NULL;
+ }
+
+ return GetBufferLine(self->buf, n+start);
+}
+
+ static PyObject *
+RBSlice(BufferObject *self, int lo, int hi, int start, int end)
+{
+ int size;
+
+ if (CheckBuffer(self))
+ return NULL;
+
+ size = end - start + 1;
+
+ if (lo < 0)
+ lo = 0;
+ else if (lo > size)
+ lo = size;
+ if (hi < 0)
+ hi = 0;
+ if (hi < lo)
+ hi = lo;
+ else if (hi > size)
+ hi = size;
+
+ return GetBufferLineList(self->buf, lo+start, hi+start);
+}
+
+ static int
+RBAssItem(BufferObject *self, int n, PyObject *val, int start, int end, int *new_end)
+{
+ int len_change;
+
+ if (CheckBuffer(self))
+ return -1;
+
+ if (n < 0 || n > end - start)
+ {
+ PyErr_SetString(PyExc_IndexError, _("line number out of range"));
+ return -1;
+ }
+
+ if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL)
+ return -1;
+
+ if (new_end)
+ *new_end = end + len_change;
+
+ return 0;
+}
+
+ static int
+RBAssSlice(BufferObject *self, int lo, int hi, PyObject *val, int start, int end, int *new_end)
+{
+ int size;
+ int len_change;
+
+ /* Self must be a valid buffer */
+ if (CheckBuffer(self))
+ return -1;
+
+ /* Sort out the slice range */
+ size = end - start + 1;
+
+ if (lo < 0)
+ lo = 0;
+ else if (lo > size)
+ lo = size;
+ if (hi < 0)
+ hi = 0;
+ if (hi < lo)
+ hi = lo;
+ else if (hi > size)
+ hi = size;
+
+ if (SetBufferLineList(self->buf, lo+start, hi+start, val, &len_change) == FAIL)
+ return -1;
+
+ if (new_end)
+ *new_end = end + len_change;
+
+ return 0;
+}
+
+ static PyObject *
+RBAppend(BufferObject *self, PyObject *args, int start, int end, int *new_end)
+{
+ PyObject *lines;
+ int len_change;
+ int max;
+ int n;
+
+ if (CheckBuffer(self))
+ return NULL;
+
+ max = n = end - start + 1;
+
+ if (!PyArg_ParseTuple(args, "O|i", &lines, &n))
+ return NULL;
+
+ if (n < 0 || n > max)
+ {
+ PyErr_SetString(PyExc_ValueError, _("line number out of range"));
+ return NULL;
+ }
+
+ if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
+ return NULL;
+
+ if (new_end)
+ *new_end = end + len_change;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+/* Buffer object - Definitions
+ */
+
+static struct PyMethodDef BufferMethods[] = {
+ /* name, function, calling, documentation */
+ {"append", BufferAppend, 1, "" },
+ {"mark", BufferMark, 1, "" },
+ {"range", BufferRange, 1, "" },
+ { NULL, NULL, 0, NULL }
+};
+
+static PySequenceMethods BufferAsSeq = {
+ (inquiry) BufferLength, /* sq_length, len(x) */
+ (binaryfunc) 0, /* BufferConcat, */ /* sq_concat, x+y */
+ (intargfunc) 0, /* BufferRepeat, */ /* sq_repeat, x*n */
+ (intargfunc) BufferItem, /* sq_item, x[i] */
+ (intintargfunc) BufferSlice, /* sq_slice, x[i:j] */
+ (intobjargproc) BufferAssItem, /* sq_ass_item, x[i]=v */
+ (intintobjargproc) BufferAssSlice, /* sq_ass_slice, x[i:j]=v */
+};
+
+static PyTypeObject BufferType = {
+ PyObject_HEAD_INIT(0)
+ 0,
+ "buffer",
+ sizeof(BufferObject),
+ 0,
+
+ (destructor) BufferDestructor, /* tp_dealloc, refcount==0 */
+ (printfunc) 0, /* tp_print, print x */
+ (getattrfunc) BufferGetattr, /* tp_getattr, x.attr */
+ (setattrfunc) 0, /* tp_setattr, x.attr=v */
+ (cmpfunc) 0, /* tp_compare, x>y */
+ (reprfunc) BufferRepr, /* tp_repr, `x`, print x */
+
+ 0, /* as number */
+ &BufferAsSeq, /* as sequence */
+ 0, /* as mapping */
+
+ (hashfunc) 0, /* tp_hash, dict(x) */
+ (ternaryfunc) 0, /* tp_call, x() */
+ (reprfunc) 0, /* tp_str, str(x) */
+};
+
+/* Buffer object - Implementation
+ */
+
+ static PyObject *
+BufferNew(buf_T *buf)
+{
+ /* We need to handle deletion of buffers underneath us.
+ * If we add a "python_ref" field to the buf_T structure,
+ * then we can get at it in buf_freeall() in vim. We then
+ * need to create only ONE Python object per buffer - if
+ * we try to create a second, just INCREF the existing one
+ * and return it. The (single) Python object referring to
+ * the buffer is stored in "python_ref".
+ * Question: what to do on a buf_freeall(). We'll probably
+ * have to either delete the Python object (DECREF it to
+ * zero - a bad idea, as it leaves dangling refs!) or
+ * set the buf_T * value to an invalid value (-1?), which
+ * means we need checks in all access functions... Bah.
+ */
+
+ BufferObject *self;
+
+ if (buf->python_ref)
+ {
+ self = buf->python_ref;
+ Py_INCREF(self);
+ }
+ else
+ {
+ self = PyObject_NEW(BufferObject, &BufferType);
+ if (self == NULL)
+ return NULL;
+ self->buf = buf;
+ buf->python_ref = self;
+ }
+
+ return (PyObject *)(self);
+}
+
+ static void
+BufferDestructor(PyObject *self)
+{
+ BufferObject *this = (BufferObject *)(self);
+
+ if (this->buf && this->buf != INVALID_BUFFER_VALUE)
+ this->buf->python_ref = NULL;
+
+ PyMem_DEL(self);
+}
+
+ static PyObject *
+BufferGetattr(PyObject *self, char *name)
+{
+ BufferObject *this = (BufferObject *)(self);
+
+ if (CheckBuffer(this))
+ return NULL;
+
+ if (strcmp(name, "name") == 0)
+ return Py_BuildValue("s",this->buf->b_ffname);
+ else if (strcmp(name, "number") == 0)
+ return Py_BuildValue("i",this->buf->b_fnum);
+ else if (strcmp(name,"__members__") == 0)
+ return Py_BuildValue("[ss]", "name", "number");
+ else
+ return Py_FindMethod(BufferMethods, self, name);
+}
+
+ static PyObject *
+BufferRepr(PyObject *self)
+{
+ static char repr[50];
+ BufferObject *this = (BufferObject *)(self);
+
+ if (this->buf == INVALID_BUFFER_VALUE)
+ {
+ sprintf(repr, _("<buffer object (deleted) at %8lX>"), (long)(self));
+ return PyString_FromString(repr);
+ }
+ else
+ {
+ char *name = (char *)this->buf->b_fname;
+ int len;
+
+ if (name == NULL)
+ name = "";
+ len = strlen(name);
+
+ if (len > 35)
+ name = name + (35 - len);
+
+ sprintf(repr, "<buffer %s%s>", len > 35 ? "..." : "", name);
+
+ return PyString_FromString(repr);
+ }
+}
+
+/******************/
+
+ static int
+BufferLength(PyObject *self)
+{
+ /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
+ if (CheckBuffer((BufferObject *)(self)))
+ return -1; /* ??? */
+
+ return (((BufferObject *)(self))->buf->b_ml.ml_line_count);
+}
+
+ static PyObject *
+BufferItem(PyObject *self, int n)
+{
+ return RBItem((BufferObject *)(self), n, 1,
+ (int)((BufferObject *)(self))->buf->b_ml.ml_line_count);
+}
+
+ static PyObject *
+BufferSlice(PyObject *self, int lo, int hi)
+{
+ return RBSlice((BufferObject *)(self), lo, hi, 1,
+ (int)((BufferObject *)(self))->buf->b_ml.ml_line_count);
+}
+
+ static int
+BufferAssItem(PyObject *self, int n, PyObject *val)
+{
+ return RBAssItem((BufferObject *)(self), n, val, 1,
+ (int)((BufferObject *)(self))->buf->b_ml.ml_line_count,
+ NULL);
+}
+
+ static int
+BufferAssSlice(PyObject *self, int lo, int hi, PyObject *val)
+{
+ return RBAssSlice((BufferObject *)(self), lo, hi, val, 1,
+ (int)((BufferObject *)(self))->buf->b_ml.ml_line_count,
+ NULL);
+}
+
+ static PyObject *
+BufferAppend(PyObject *self, PyObject *args)
+{
+ return RBAppend((BufferObject *)(self), args, 1,
+ (int)((BufferObject *)(self))->buf->b_ml.ml_line_count,
+ NULL);
+}
+
+ static PyObject *
+BufferMark(PyObject *self, PyObject *args)
+{
+ pos_T *posp;
+ char mark;
+ buf_T *curbuf_save;
+
+ if (CheckBuffer((BufferObject *)(self)))
+ return NULL;
+
+ if (!PyArg_ParseTuple(args, "c", &mark))
+ return NULL;
+
+ curbuf_save = curbuf;
+ curbuf = ((BufferObject *)(self))->buf;
+ posp = getmark(mark, FALSE);
+ curbuf = curbuf_save;
+
+ if (posp == NULL)
+ {
+ PyErr_SetVim(_("invalid mark name"));
+ return NULL;
+ }
+
+ /* Ckeck for keyboard interrupt */
+ if (VimErrorCheck())
+ return NULL;
+
+ if (posp->lnum <= 0)
+ {
+ /* Or raise an error? */
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
+}
+
+ static PyObject *
+BufferRange(PyObject *self, PyObject *args)
+{
+ int start;
+ int end;
+
+ if (CheckBuffer((BufferObject *)(self)))
+ return NULL;
+
+ if (!PyArg_ParseTuple(args, "ii", &start, &end))
+ return NULL;
+
+ return RangeNew(((BufferObject *)(self))->buf, start, end);
+}
+
+/* Line range object - Definitions
+ */
+
+static struct PyMethodDef RangeMethods[] = {
+ /* name, function, calling, documentation */
+ {"append", RangeAppend, 1, "" },
+ { NULL, NULL, 0, NULL }
+};
+
+static PySequenceMethods RangeAsSeq = {
+ (inquiry) RangeLength, /* sq_length, len(x) */
+ (binaryfunc) 0, /* RangeConcat, */ /* sq_concat, x+y */
+ (intargfunc) 0, /* RangeRepeat, */ /* sq_repeat, x*n */
+ (intargfunc) RangeItem, /* sq_item, x[i] */
+ (intintargfunc) RangeSlice, /* sq_slice, x[i:j] */
+ (intobjargproc) RangeAssItem, /* sq_ass_item, x[i]=v */
+ (intintobjargproc) RangeAssSlice, /* sq_ass_slice, x[i:j]=v */
+};
+
+static PyTypeObject RangeType = {
+ PyObject_HEAD_INIT(0)
+ 0,
+ "range",
+ sizeof(RangeObject),
+ 0,
+
+ (destructor) RangeDestructor, /* tp_dealloc, refcount==0 */
+ (printfunc) 0, /* tp_print, print x */
+ (getattrfunc) RangeGetattr, /* tp_getattr, x.attr */
+ (setattrfunc) 0, /* tp_setattr, x.attr=v */
+ (cmpfunc) 0, /* tp_compare, x>y */
+ (reprfunc) RangeRepr, /* tp_repr, `x`, print x */
+
+ 0, /* as number */
+ &RangeAsSeq, /* as sequence */
+ 0, /* as mapping */
+
+ (hashfunc) 0, /* tp_hash, dict(x) */
+ (ternaryfunc) 0, /* tp_call, x() */
+ (reprfunc) 0, /* tp_str, str(x) */
+};
+
+/* Line range object - Implementation
+ */
+
+ static PyObject *
+RangeNew(buf_T *buf, int start, int end)
+{
+ BufferObject *bufr;
+ RangeObject *self;
+ self = PyObject_NEW(RangeObject, &RangeType);
+ if (self == NULL)
+ return NULL;
+
+ bufr = (BufferObject *)BufferNew(buf);
+ if (bufr == NULL)
+ {
+ PyMem_DEL(self);
+ return NULL;
+ }
+ Py_INCREF(bufr);
+
+ self->buf = bufr;
+ self->start = start;
+ self->end = end;
+
+ return (PyObject *)(self);
+}
+
+ static void
+RangeDestructor(PyObject *self)
+{
+ Py_DECREF(((RangeObject *)(self))->buf);
+ PyMem_DEL(self);
+}
+
+ static PyObject *
+RangeGetattr(PyObject *self, char *name)
+{
+ if (strcmp(name, "start") == 0)
+ return Py_BuildValue("i",((RangeObject *)(self))->start - 1);
+ else if (strcmp(name, "end") == 0)
+ return Py_BuildValue("i",((RangeObject *)(self))->end - 1);
+ else
+ return Py_FindMethod(RangeMethods, self, name);
+}
+
+ static PyObject *
+RangeRepr(PyObject *self)
+{
+ static char repr[75];
+ RangeObject *this = (RangeObject *)(self);
+
+ if (this->buf->buf == INVALID_BUFFER_VALUE)
+ {
+ sprintf(repr, "<range object (for deleted buffer) at %8lX>",
+ (long)(self));
+ return PyString_FromString(repr);
+ }
+ else
+ {
+ char *name = (char *)this->buf->buf->b_fname;
+ int len;
+
+ if (name == NULL)
+ name = "";
+ len = strlen(name);
+
+ if (len > 45)
+ name = name + (45 - len);
+
+ sprintf(repr, "<range %s%s (%d:%d)>",
+ len > 45 ? "..." : "", name,
+ this->start, this->end);
+
+ return PyString_FromString(repr);
+ }
+}
+
+/****************/
+
+ static int
+RangeLength(PyObject *self)
+{
+ /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
+ if (CheckBuffer(((RangeObject *)(self))->buf))
+ return -1; /* ??? */
+
+ return (((RangeObject *)(self))->end - ((RangeObject *)(self))->start + 1);
+}
+
+ static PyObject *
+RangeItem(PyObject *self, int n)
+{
+ return RBItem(((RangeObject *)(self))->buf, n,
+ ((RangeObject *)(self))->start,
+ ((RangeObject *)(self))->end);
+}
+
+ static PyObject *
+RangeSlice(PyObject *self, int lo, int hi)
+{
+ return RBSlice(((RangeObject *)(self))->buf, lo, hi,
+ ((RangeObject *)(self))->start,
+ ((RangeObject *)(self))->end);
+}
+
+ static int
+RangeAssItem(PyObject *self, int n, PyObject *val)
+{
+ return RBAssItem(((RangeObject *)(self))->buf, n, val,
+ ((RangeObject *)(self))->start,
+ ((RangeObject *)(self))->end,
+ &((RangeObject *)(self))->end);
+}
+
+ static int
+RangeAssSlice(PyObject *self, int lo, int hi, PyObject *val)
+{
+ return RBAssSlice(((RangeObject *)(self))->buf, lo, hi, val,
+ ((RangeObject *)(self))->start,
+ ((RangeObject *)(self))->end,
+ &((RangeObject *)(self))->end);
+}
+
+ static PyObject *
+RangeAppend(PyObject *self, PyObject *args)
+{
+ return RBAppend(((RangeObject *)(self))->buf, args,
+ ((RangeObject *)(self))->start,
+ ((RangeObject *)(self))->end,
+ &((RangeObject *)(self))->end);
+}
+
+/* Buffer list object - Definitions
+ */
+
+typedef struct
+{
+ PyObject_HEAD
+}
+BufListObject;
+
+static PySequenceMethods BufListAsSeq = {
+ (inquiry) BufListLength, /* sq_length, len(x) */
+ (binaryfunc) 0, /* sq_concat, x+y */
+ (intargfunc) 0, /* sq_repeat, x*n */
+ (intargfunc) BufListItem, /* sq_item, x[i] */
+ (intintargfunc) 0, /* sq_slice, x[i:j] */
+ (intobjargproc) 0, /* sq_ass_item, x[i]=v */
+ (intintobjargproc) 0, /* sq_ass_slice, x[i:j]=v */
+};
+
+static PyTypeObject BufListType = {
+ PyObject_HEAD_INIT(0)
+ 0,
+ "buffer list",
+ sizeof(BufListObject),
+ 0,
+
+ (destructor) 0, /* tp_dealloc, refcount==0 */
+ (printfunc) 0, /* tp_print, print x */
+ (getattrfunc) 0, /* tp_getattr, x.attr */
+ (setattrfunc) 0, /* tp_setattr, x.attr=v */
+ (cmpfunc) 0, /* tp_compare, x>y */
+ (reprfunc) 0, /* tp_repr, `x`, print x */
+
+ 0, /* as number */
+ &BufListAsSeq, /* as sequence */
+ 0, /* as mapping */
+
+ (hashfunc) 0, /* tp_hash, dict(x) */
+ (ternaryfunc) 0, /* tp_call, x() */
+ (reprfunc) 0, /* tp_str, str(x) */
+};
+
+/* Buffer list object - Implementation
+ */
+
+/*ARGSUSED*/
+ static int
+BufListLength(PyObject *self)
+{
+ buf_T *b = firstbuf;
+ int n = 0;
+
+ while (b)
+ {
+ ++n;
+ b = b->b_next;
+ }
+
+ return n;
+}
+
+/*ARGSUSED*/
+ static PyObject *
+BufListItem(PyObject *self, int n)
+{
+ buf_T *b;
+
+ for (b = firstbuf; b; b = b->b_next, --n)
+ {
+ if (n == 0)
+ return BufferNew(b);
+ }
+
+ PyErr_SetString(PyExc_IndexError, _("no such buffer"));
+ return NULL;
+}
+
+/* Window object - Definitions
+ */
+
+static struct PyMethodDef WindowMethods[] = {
+ /* name, function, calling, documentation */
+ { NULL, NULL, 0, NULL }
+};
+
+static PyTypeObject WindowType = {
+ PyObject_HEAD_INIT(0)
+ 0,
+ "window",
+ sizeof(WindowObject),
+ 0,
+
+ (destructor) WindowDestructor, /* tp_dealloc, refcount==0 */
+ (printfunc) 0, /* tp_print, print x */
+ (getattrfunc) WindowGetattr, /* tp_getattr, x.attr */
+ (setattrfunc) WindowSetattr, /* tp_setattr, x.attr=v */
+ (cmpfunc) 0, /* tp_compare, x>y */
+ (reprfunc) WindowRepr, /* tp_repr, `x`, print x */
+
+ 0, /* as number */
+ 0, /* as sequence */
+ 0, /* as mapping */
+
+ (hashfunc) 0, /* tp_hash, dict(x) */
+ (ternaryfunc) 0, /* tp_call, x() */
+ (reprfunc) 0, /* tp_str, str(x) */
+};
+
+/* Window object - Implementation
+ */
+
+ static PyObject *
+WindowNew(win_T *win)
+{
+ /* We need to handle deletion of windows underneath us.
+ * If we add a "python_ref" field to the win_T structure,
+ * then we can get at it in win_free() in vim. We then
+ * need to create only ONE Python object per window - if
+ * we try to create a second, just INCREF the existing one
+ * and return it. The (single) Python object referring to
+ * the window is stored in "python_ref".
+ * On a win_free() we set the Python object's win_T* field
+ * to an invalid value. We trap all uses of a window
+ * object, and reject them if the win_T* field is invalid.
+ */
+
+ WindowObject *self;
+
+ if (win->python_ref)
+ {
+ self = win->python_ref;
+ Py_INCREF(self);
+ }
+ else
+ {
+ self = PyObject_NEW(WindowObject, &WindowType);
+ if (self == NULL)
+ return NULL;
+ self->win = win;
+ win->python_ref = self;
+ }
+
+ return (PyObject *)(self);
+}
+
+ static void
+WindowDestructor(PyObject *self)
+{
+ WindowObject *this = (WindowObject *)(self);
+
+ if (this->win && this->win != INVALID_WINDOW_VALUE)
+ this->win->python_ref = NULL;
+
+ PyMem_DEL(self);
+}
+
+ static int
+CheckWindow(WindowObject *this)
+{
+ if (this->win == INVALID_WINDOW_VALUE)
+ {
+ PyErr_SetVim(_("attempt to refer to deleted window"));
+ return -1;
+ }
+
+ return 0;
+}
+
+ static PyObject *
+WindowGetattr(PyObject *self, char *name)
+{
+ WindowObject *this = (WindowObject *)(self);
+
+ if (CheckWindow(this))
+ return NULL;
+
+ if (strcmp(name, "buffer") == 0)
+ return (PyObject *)BufferNew(this->win->w_buffer);
+ else if (strcmp(name, "cursor") == 0)
+ {
+ pos_T *pos = &this->win->w_cursor;
+
+ return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
+ }
+ else if (strcmp(name, "height") == 0)
+ return Py_BuildValue("l", (long)(this->win->w_height));
+#ifdef FEAT_VERTSPLIT
+ else if (strcmp(name, "width") == 0)
+ return Py_BuildValue("l", (long)(W_WIDTH(this->win)));
+#endif
+ else if (strcmp(name,"__members__") == 0)
+ return Py_BuildValue("[sss]", "buffer", "cursor", "height");
+ else
+ return Py_FindMethod(WindowMethods, self, name);
+}
+
+ static int
+WindowSetattr(PyObject *self, char *name, PyObject *val)
+{
+ WindowObject *this = (WindowObject *)(self);
+
+ if (CheckWindow(this))
+ return -1;
+
+ if (strcmp(name, "buffer") == 0)
+ {
+ PyErr_SetString(PyExc_TypeError, _("readonly attribute"));
+ return -1;
+ }
+ else if (strcmp(name, "cursor") == 0)
+ {
+ long lnum;
+ long col;
+
+ if (!PyArg_Parse(val, "(ll)", &lnum, &col))
+ return -1;
+
+ if (lnum <= 0 || lnum > this->win->w_buffer->b_ml.ml_line_count)
+ {
+ PyErr_SetVim(_("cursor position outside buffer"));
+ return -1;
+ }
+
+ /* Check for keyboard interrupts */
+ if (VimErrorCheck())
+ return -1;
+
+ /* NO CHECK ON COLUMN - SEEMS NOT TO MATTER */
+
+ this->win->w_cursor.lnum = lnum;
+ this->win->w_cursor.col = col;
+ update_screen(VALID);
+
+ return 0;
+ }
+ else if (strcmp(name, "height") == 0)
+ {
+ int height;
+ win_T *savewin;
+
+ if (!PyArg_Parse(val, "i", &height))
+ return -1;
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ savewin = curwin;
+ curwin = this->win;
+ win_setheight(height);
+ curwin = savewin;
+
+ /* Check for keyboard interrupts */
+ if (VimErrorCheck())
+ return -1;
+
+ return 0;
+ }
+#ifdef FEAT_VERTSPLIT
+ else if (strcmp(name, "width") == 0)
+ {
+ int width;
+ win_T *savewin;
+
+ if (!PyArg_Parse(val, "i", &width))
+ return -1;
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ savewin = curwin;
+ curwin = this->win;
+ win_setwidth(width);
+ curwin = savewin;
+
+ /* Check for keyboard interrupts */
+ if (VimErrorCheck())
+ return -1;
+
+ return 0;
+ }
+#endif
+ else
+ {
+ PyErr_SetString(PyExc_AttributeError, name);
+ return -1;
+ }
+}
+
+ static PyObject *
+WindowRepr(PyObject *self)
+{
+ static char repr[50];
+ WindowObject *this = (WindowObject *)(self);
+
+ if (this->win == INVALID_WINDOW_VALUE)
+ {
+ sprintf(repr, _("<window object (deleted) at %.8lX>"), (long)(self));
+ return PyString_FromString(repr);
+ }
+ else
+ {
+ int i = 0;
+ win_T *w;
+
+ for (w = firstwin; w != NULL && w != this->win; w = W_NEXT(w))
+ ++i;
+
+ if (w == NULL)
+ sprintf(repr, _("<window object (unknown) at %.8lX>"), (long)(self));
+ else
+ sprintf(repr, _("<window %d>"), i);
+
+ return PyString_FromString(repr);
+ }
+}
+
+/* Window list object - Definitions
+ */
+
+typedef struct
+{
+ PyObject_HEAD
+}
+WinListObject;
+
+static PySequenceMethods WinListAsSeq = {
+ (inquiry) WinListLength, /* sq_length, len(x) */
+ (binaryfunc) 0, /* sq_concat, x+y */
+ (intargfunc) 0, /* sq_repeat, x*n */
+ (intargfunc) WinListItem, /* sq_item, x[i] */
+ (intintargfunc) 0, /* sq_slice, x[i:j] */
+ (intobjargproc) 0, /* sq_ass_item, x[i]=v */
+ (intintobjargproc) 0, /* sq_ass_slice, x[i:j]=v */
+};
+
+static PyTypeObject WinListType = {
+ PyObject_HEAD_INIT(0)
+ 0,
+ "window list",
+ sizeof(WinListObject),
+ 0,
+
+ (destructor) 0, /* tp_dealloc, refcount==0 */
+ (printfunc) 0, /* tp_print, print x */
+ (getattrfunc) 0, /* tp_getattr, x.attr */
+ (setattrfunc) 0, /* tp_setattr, x.attr=v */
+ (cmpfunc) 0, /* tp_compare, x>y */
+ (reprfunc) 0, /* tp_repr, `x`, print x */
+
+ 0, /* as number */
+ &WinListAsSeq, /* as sequence */
+ 0, /* as mapping */
+
+ (hashfunc) 0, /* tp_hash, dict(x) */
+ (ternaryfunc) 0, /* tp_call, x() */
+ (reprfunc) 0, /* tp_str, str(x) */
+};
+
+/* Window list object - Implementation
+ */
+/*ARGSUSED*/
+ static int
+WinListLength(PyObject *self)
+{
+ win_T *w = firstwin;
+ int n = 0;
+
+ while (w)
+ {
+ ++n;
+ w = W_NEXT(w);
+ }
+
+ return n;
+}
+
+/*ARGSUSED*/
+ static PyObject *
+WinListItem(PyObject *self, int n)
+{
+ win_T *w;
+
+ for (w = firstwin; w; w = W_NEXT(w), --n)
+ if (n == 0)
+ return WindowNew(w);
+
+ PyErr_SetString(PyExc_IndexError, _("no such window"));
+ return NULL;
+}
+
+/* Current items object - Definitions
+ */
+
+typedef struct
+{
+ PyObject_HEAD
+}
+CurrentObject;
+
+static PyTypeObject CurrentType = {
+ PyObject_HEAD_INIT(0)
+ 0,
+ "current data",
+ sizeof(CurrentObject),
+ 0,
+
+ (destructor) 0, /* tp_dealloc, refcount==0 */
+ (printfunc) 0, /* tp_print, print x */
+ (getattrfunc) CurrentGetattr, /* tp_getattr, x.attr */
+ (setattrfunc) CurrentSetattr, /* tp_setattr, x.attr=v */
+ (cmpfunc) 0, /* tp_compare, x>y */
+ (reprfunc) 0, /* tp_repr, `x`, print x */
+
+ 0, /* as number */
+ 0, /* as sequence */
+ 0, /* as mapping */
+
+ (hashfunc) 0, /* tp_hash, dict(x) */
+ (ternaryfunc) 0, /* tp_call, x() */
+ (reprfunc) 0, /* tp_str, str(x) */
+};
+
+/* Current items object - Implementation
+ */
+/*ARGSUSED*/
+ static PyObject *
+CurrentGetattr(PyObject *self, char *name)
+{
+ if (strcmp(name, "buffer") == 0)
+ return (PyObject *)BufferNew(curbuf);
+ else if (strcmp(name, "window") == 0)
+ return (PyObject *)WindowNew(curwin);
+ else if (strcmp(name, "line") == 0)
+ return GetBufferLine(curbuf, (int)curwin->w_cursor.lnum);
+ else if (strcmp(name, "range") == 0)
+ return RangeNew(curbuf, RangeStart, RangeEnd);
+ else if (strcmp(name,"__members__") == 0)
+ return Py_BuildValue("[ssss]", "buffer", "window", "line", "range");
+ else
+ {
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+ }
+}
+
+/*ARGSUSED*/
+ static int
+CurrentSetattr(PyObject *self, char *name, PyObject *value)
+{
+ if (strcmp(name, "line") == 0)
+ {
+ if (SetBufferLine(curbuf, (int)curwin->w_cursor.lnum, value, NULL) == FAIL)
+ return -1;
+
+ return 0;
+ }
+ else
+ {
+ PyErr_SetString(PyExc_AttributeError, name);
+ return -1;
+ }
+}
+
+/* External interface
+ */
+
+ void
+python_buffer_free(buf_T *buf)
+{
+ if (buf->python_ref)
+ {
+ BufferObject *bp = buf->python_ref;
+ bp->buf = INVALID_BUFFER_VALUE;
+ buf->python_ref = NULL;
+ }
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+ void
+python_window_free(win_T *win)
+{
+ if (win->python_ref)
+ {
+ WindowObject *wp = win->python_ref;
+ wp->win = INVALID_WINDOW_VALUE;
+ win->python_ref = NULL;
+ }
+}
+#endif
+
+static BufListObject TheBufferList =
+{
+ PyObject_HEAD_INIT(&BufListType)
+};
+
+static WinListObject TheWindowList =
+{
+ PyObject_HEAD_INIT(&WinListType)
+};
+
+static CurrentObject TheCurrent =
+{
+ PyObject_HEAD_INIT(&CurrentType)
+};
+
+ static int
+PythonMod_Init(void)
+{
+ PyObject *mod;
+ PyObject *dict;
+ static char *(argv[2]) = {"", NULL};
+
+ /* Fixups... */
+ BufferType.ob_type = &PyType_Type;
+ RangeType.ob_type = &PyType_Type;
+ WindowType.ob_type = &PyType_Type;
+ BufListType.ob_type = &PyType_Type;
+ WinListType.ob_type = &PyType_Type;
+ CurrentType.ob_type = &PyType_Type;
+
+ /* Set sys.argv[] to avoid a crash in warn(). */
+ PySys_SetArgv(1, argv);
+
+ mod = Py_InitModule("vim", VimMethods);
+ dict = PyModule_GetDict(mod);
+
+ VimError = Py_BuildValue("s", "vim.error");
+
+ PyDict_SetItemString(dict, "error", VimError);
+ PyDict_SetItemString(dict, "buffers", (PyObject *)(&TheBufferList));
+ PyDict_SetItemString(dict, "current", (PyObject *)(&TheCurrent));
+ PyDict_SetItemString(dict, "windows", (PyObject *)(&TheWindowList));
+
+ if (PyErr_Occurred())
+ return -1;
+
+ return 0;
+}
+
+/*************************************************************************
+ * 4. Utility functions for handling the interface between Vim and Python.
+ */
+
+/* Get a line from the specified buffer. The line number is
+ * in Vim format (1-based). The line is returned as a Python
+ * string object.
+ */
+ static PyObject *
+GetBufferLine(buf_T *buf, int n)
+{
+ return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
+}
+
+/* Get a list of lines from the specified buffer. The line numbers
+ * are in Vim format (1-based). The range is from lo up to, but not
+ * including, hi. The list is returned as a Python list of string objects.
+ */
+ static PyObject *
+GetBufferLineList(buf_T *buf, int lo, int hi)
+{
+ int i;
+ int n = hi - lo;
+ PyObject *list = PyList_New(n);
+
+ if (list == NULL)
+ return NULL;
+
+ for (i = 0; i < n; ++i)
+ {
+ PyObject *str = LineToString((char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE));
+
+ /* Error check - was the Python string creation OK? */
+ if (str == NULL)
+ {
+ Py_DECREF(list);
+ return NULL;
+ }
+
+ /* Set the list item */
+ if (PyList_SetItem(list, i, str))
+ {
+ Py_DECREF(str);
+ Py_DECREF(list);
+ return NULL;
+ }
+ }
+
+ /* The ownership of the Python list is passed to the caller (ie,
+ * the caller should Py_DECREF() the object when it is finished
+ * with it).
+ */
+
+ return list;
+}
+
+/*
+ * Check if deleting lines made the cursor position invalid.
+ * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
+ * deleted).
+ */
+ static void
+py_fix_cursor(int lo, int hi, int extra)
+{
+ if (curwin->w_cursor.lnum >= lo)
+ {
+ /* Adjust the cursor position if it's in/after the changed
+ * lines. */
+ if (curwin->w_cursor.lnum >= hi)
+ {
+ curwin->w_cursor.lnum += extra;
+ check_cursor_col();
+ }
+ else if (extra < 0)
+ {
+ curwin->w_cursor.lnum = lo;
+ check_cursor();
+ }
+ changed_cline_bef_curs();
+ }
+ invalidate_botline();
+}
+
+/* Replace a line in the specified buffer. The line number is
+ * in Vim format (1-based). The replacement line is given as
+ * a Python string object. The object is checked for validity
+ * and correct format. Errors are returned as a value of FAIL.
+ * The return value is OK on success.
+ * If OK is returned and len_change is not NULL, *len_change
+ * is set to the change in the buffer length.
+ */
+ static int
+SetBufferLine(buf_T *buf, int n, PyObject *line, int *len_change)
+{
+ /* First of all, we check the thpe of the supplied Python object.
+ * There are three cases:
+ * 1. NULL, or None - this is a deletion.
+ * 2. A string - this is a replacement.
+ * 3. Anything else - this is an error.
+ */
+ if (line == Py_None || line == NULL)
+ {
+ buf_T *savebuf = curbuf;
+
+ PyErr_Clear();
+ curbuf = buf;
+
+ if (u_savedel((linenr_T)n, 1L) == FAIL)
+ PyErr_SetVim(_("cannot save undo information"));
+ else if (ml_delete((linenr_T)n, FALSE) == FAIL)
+ PyErr_SetVim(_("cannot delete line"));
+ else
+ {
+ deleted_lines_mark((linenr_T)n, 1L);
+ if (buf == curwin->w_buffer)
+ py_fix_cursor(n, n + 1, -1);
+ }
+
+ curbuf = savebuf;
+
+ if (PyErr_Occurred() || VimErrorCheck())
+ return FAIL;
+
+ if (len_change)
+ *len_change = -1;
+
+ return OK;
+ }
+ else if (PyString_Check(line))
+ {
+ char *save = StringToLine(line);
+ buf_T *savebuf = curbuf;
+
+ if (save == NULL)
+ return FAIL;
+
+ /* We do not need to free "save" if ml_replace() consumes it. */
+ PyErr_Clear();
+ curbuf = buf;
+
+ if (u_savesub((linenr_T)n) == FAIL)
+ {
+ PyErr_SetVim(_("cannot save undo information"));
+ vim_free(save);
+ }
+ else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
+ {
+ PyErr_SetVim(_("cannot replace line"));
+ vim_free(save);
+ }
+ else
+ changed_bytes((linenr_T)n, 0);
+
+ curbuf = savebuf;
+
+ if (PyErr_Occurred() || VimErrorCheck())
+ return FAIL;
+
+ if (len_change)
+ *len_change = 0;
+
+ return OK;
+ }
+ else
+ {
+ PyErr_BadArgument();
+ return FAIL;
+ }
+}
+
+/* Replace a range of lines in the specified buffer. The line numbers are in
+ * Vim format (1-based). The range is from lo up to, but not including, hi.
+ * The replacement lines are given as a Python list of string objects. The
+ * list is checked for validity and correct format. Errors are returned as a
+ * value of FAIL. The return value is OK on success.
+ * If OK is returned and len_change is not NULL, *len_change
+ * is set to the change in the buffer length.
+ */
+ static int
+SetBufferLineList(buf_T *buf, int lo, int hi, PyObject *list, int *len_change)
+{
+ /* First of all, we check the thpe of the supplied Python object.
+ * There are three cases:
+ * 1. NULL, or None - this is a deletion.
+ * 2. A list - this is a replacement.
+ * 3. Anything else - this is an error.
+ */
+ if (list == Py_None || list == NULL)
+ {
+ int i;
+ int n = hi - lo;
+ buf_T *savebuf = curbuf;
+
+ PyErr_Clear();
+ curbuf = buf;
+
+ if (u_savedel((linenr_T)lo, (long)n) == FAIL)
+ PyErr_SetVim(_("cannot save undo information"));
+ else
+ {
+ for (i = 0; i < n; ++i)
+ {
+ if (ml_delete((linenr_T)lo, FALSE) == FAIL)
+ {
+ PyErr_SetVim(_("cannot delete line"));
+ break;
+ }
+ }
+ deleted_lines_mark((linenr_T)lo, (long)i);
+
+ if (buf == curwin->w_buffer)
+ py_fix_cursor(lo, hi, -n);
+ }
+
+ curbuf = savebuf;
+
+ if (PyErr_Occurred() || VimErrorCheck())
+ return FAIL;
+
+ if (len_change)
+ *len_change = -n;
+
+ return OK;
+ }
+ else if (PyList_Check(list))
+ {
+ int i;
+ int new_len = PyList_Size(list);
+ int old_len = hi - lo;
+ int extra = 0; /* lines added to text, can be negative */
+ char **array;
+ buf_T *savebuf;
+
+ if (new_len == 0) /* avoid allocating zero bytes */
+ array = NULL;
+ else
+ {
+ array = (char **)alloc((unsigned)(new_len * sizeof(char *)));
+ if (array == NULL)
+ {
+ PyErr_NoMemory();
+ return FAIL;
+ }
+ }
+
+ for (i = 0; i < new_len; ++i)
+ {
+ PyObject *line = PyList_GetItem(list, i);
+
+ array[i] = StringToLine(line);
+ if (array[i] == NULL)
+ {
+ while (i)
+ vim_free(array[--i]);
+ vim_free(array);
+ return FAIL;
+ }
+ }
+
+ savebuf = curbuf;
+
+ PyErr_Clear();
+ curbuf = buf;
+
+ if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
+ PyErr_SetVim(_("cannot save undo information"));
+
+ /* If the size of the range is reducing (ie, new_len < old_len) we
+ * need to delete some old_len. We do this at the start, by
+ * repeatedly deleting line "lo".
+ */
+ if (!PyErr_Occurred())
+ {
+ for (i = 0; i < old_len - new_len; ++i)
+ if (ml_delete((linenr_T)lo, FALSE) == FAIL)
+ {
+ PyErr_SetVim(_("cannot delete line"));
+ break;
+ }
+ extra -= i;
+ }
+
+ /* For as long as possible, replace the existing old_len with the
+ * new old_len. This is a more efficient operation, as it requires
+ * less memory allocation and freeing.
+ */
+ if (!PyErr_Occurred())
+ {
+ for (i = 0; i < old_len && i < new_len; ++i)
+ if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
+ == FAIL)
+ {
+ PyErr_SetVim(_("cannot replace line"));
+ break;
+ }
+ }
+ else
+ i = 0;
+
+ /* Now we may need to insert the remaining new old_len. If we do, we
+ * must free the strings as we finish with them (we can't pass the
+ * responsibility to vim in this case).
+ */
+ if (!PyErr_Occurred())
+ {
+ while (i < new_len)
+ {
+ if (ml_append((linenr_T)(lo + i - 1),
+ (char_u *)array[i], 0, FALSE) == FAIL)
+ {
+ PyErr_SetVim(_("cannot insert line"));
+ break;
+ }
+ vim_free(array[i]);
+ ++i;
+ ++extra;
+ }
+ }
+
+ /* Free any left-over old_len, as a result of an error */
+ while (i < new_len)
+ {
+ vim_free(array[i]);
+ ++i;
+ }
+
+ /* Free the array of old_len. All of its contents have now
+ * been dealt with (either freed, or the responsibility passed
+ * to vim.
+ */
+ vim_free(array);
+
+ /* Adjust marks. Invalidate any which lie in the
+ * changed range, and move any in the remainder of the buffer.
+ */
+ mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
+ (long)MAXLNUM, (long)extra);
+ changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
+
+ if (buf == curwin->w_buffer)
+ py_fix_cursor(lo, hi, extra);
+
+ curbuf = savebuf;
+
+ if (PyErr_Occurred() || VimErrorCheck())
+ return FAIL;
+
+ if (len_change)
+ *len_change = new_len - old_len;
+
+ return OK;
+ }
+ else
+ {
+ PyErr_BadArgument();
+ return FAIL;
+ }
+}
+
+/* Insert a number of lines into the specified buffer after the specifed line.
+ * The line number is in Vim format (1-based). The lines to be inserted are
+ * given as a Python list of string objects or as a single string. The lines
+ * to be added are checked for validity and correct format. Errors are
+ * returned as a value of FAIL. The return value is OK on success.
+ * If OK is returned and len_change is not NULL, *len_change
+ * is set to the change in the buffer length.
+ */
+ static int
+InsertBufferLines(buf_T *buf, int n, PyObject *lines, int *len_change)
+{
+ /* First of all, we check the type of the supplied Python object.
+ * It must be a string or a list, or the call is in error.
+ */
+ if (PyString_Check(lines))
+ {
+ char *str = StringToLine(lines);
+ buf_T *savebuf;
+
+ if (str == NULL)
+ return FAIL;
+
+ savebuf = curbuf;
+
+ PyErr_Clear();
+ curbuf = buf;
+
+ if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
+ PyErr_SetVim(_("cannot save undo information"));
+ else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
+ PyErr_SetVim(_("cannot insert line"));
+ else
+ appended_lines_mark((linenr_T)n, 1L);
+
+ vim_free(str);
+ curbuf = savebuf;
+ update_screen(VALID);
+
+ if (PyErr_Occurred() || VimErrorCheck())
+ return FAIL;
+
+ if (len_change)
+ *len_change = 1;
+
+ return OK;
+ }
+ else if (PyList_Check(lines))
+ {
+ int i;
+ int size = PyList_Size(lines);
+ char **array;
+ buf_T *savebuf;
+
+ array = (char **)alloc((unsigned)(size * sizeof(char *)));
+ if (array == NULL)
+ {
+ PyErr_NoMemory();
+ return FAIL;
+ }
+
+ for (i = 0; i < size; ++i)
+ {
+ PyObject *line = PyList_GetItem(lines, i);
+ array[i] = StringToLine(line);
+
+ if (array[i] == NULL)
+ {
+ while (i)
+ vim_free(array[--i]);
+ vim_free(array);
+ return FAIL;
+ }
+ }
+
+ savebuf = curbuf;
+
+ PyErr_Clear();
+ curbuf = buf;
+
+ if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
+ PyErr_SetVim(_("cannot save undo information"));
+ else
+ {
+ for (i = 0; i < size; ++i)
+ {
+ if (ml_append((linenr_T)(n + i),
+ (char_u *)array[i], 0, FALSE) == FAIL)
+ {
+ PyErr_SetVim(_("cannot insert line"));
+
+ /* Free the rest of the lines */
+ while (i < size)
+ vim_free(array[i++]);
+
+ break;
+ }
+ vim_free(array[i]);
+ }
+ if (i > 0)
+ appended_lines_mark((linenr_T)n, (long)i);
+ }
+
+ /* Free the array of lines. All of its contents have now
+ * been freed.
+ */
+ vim_free(array);
+
+ curbuf = savebuf;
+ update_screen(VALID);
+
+ if (PyErr_Occurred() || VimErrorCheck())
+ return FAIL;
+
+ if (len_change)
+ *len_change = size;
+
+ return OK;
+ }
+ else
+ {
+ PyErr_BadArgument();
+ return FAIL;
+ }
+}
+
+/* Convert a Vim line into a Python string.
+ * All internal newlines are replaced by null characters.
+ *
+ * On errors, the Python exception data is set, and NULL is returned.
+ */
+ static PyObject *
+LineToString(const char *str)
+{
+ PyObject *result;
+ int len = strlen(str);
+ char *p;
+
+ /* Allocate an Python string object, with uninitialised contents. We
+ * must do it this way, so that we can modify the string in place
+ * later. See the Python source, Objects/stringobject.c for details.
+ */
+ result = PyString_FromStringAndSize(NULL, len);
+ if (result == NULL)
+ return NULL;
+
+ p = PyString_AsString(result);
+
+ while (*str)
+ {
+ if (*str == '\n')
+ *p = '\0';
+ else
+ *p = *str;
+
+ ++p;
+ ++str;
+ }
+
+ return result;
+}
+
+/* Convert a Python string into a Vim line.
+ *
+ * The result is in allocated memory. All internal nulls are replaced by
+ * newline characters. It is an error for the string to contain newline
+ * characters.
+ *
+ * On errors, the Python exception data is set, and NULL is returned.
+ */
+ static char *
+StringToLine(PyObject *obj)
+{
+ const char *str;
+ char *save;
+ int len;
+ int i;
+
+ if (obj == NULL || !PyString_Check(obj))
+ {
+ PyErr_BadArgument();
+ return NULL;
+ }
+
+ str = PyString_AsString(obj);
+ len = PyString_Size(obj);
+
+ /* Error checking: String must not contain newlines, as we
+ * are replacing a single line, and we must replace it with
+ * a single line.
+ */
+ if (memchr(str, '\n', len))
+ {
+ PyErr_SetVim(_("string cannot contain newlines"));
+ return NULL;
+ }
+
+ /* Create a copy of the string, with internal nulls replaced by
+ * newline characters, as is the vim convention.
+ */
+ save = (char *)alloc((unsigned)(len+1));
+ if (save == NULL)
+ {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ for (i = 0; i < len; ++i)
+ {
+ if (str[i] == '\0')
+ save[i] = '\n';
+ else
+ save[i] = str[i];
+ }
+
+ save[i] = '\0';
+
+ return save;
+}
+
+/* Check to see whether a Vim error has been reported, or a keyboard
+ * interrupt has been detected.
+ */
+ static int
+VimErrorCheck(void)
+{
+ if (got_int)
+ {
+ PyErr_SetNone(PyExc_KeyboardInterrupt);
+ return 1;
+ }
+ else if (did_emsg && !PyErr_Occurred())
+ {
+ PyErr_SetNone(VimError);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* Don't generate a prototype for the next function, it generates an error on
+ * newer Python versions. */
+#if PYTHON_API_VERSION < 1007 /* Python 1.4 */ && !defined(PROTO)
+
+ char *
+Py_GetProgramName(void)
+{
+ return "vim";
+}
+#endif /* Python 1.4 */
diff --git a/src/if_ruby.c b/src/if_ruby.c
new file mode 100644
index 000000000..9ef504cff
--- /dev/null
+++ b/src/if_ruby.c
@@ -0,0 +1,868 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Ruby interface by Shugo Maeda.
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef _WIN32
+# if !defined(DYNAMIC_RUBY_VER) || (DYNAMIC_RUBY_VER < 18)
+# define NT
+# endif
+# ifndef DYNAMIC_RUBY
+# define IMPORT /* For static dll usage __declspec(dllimport) */
+# define RUBYEXTERN __declspec(dllimport)
+# endif
+#endif
+#ifndef RUBYEXTERN
+# define RUBYEXTERN extern
+#endif
+
+/*
+ * This is tricky. In ruby.h there is (inline) function rb_class_of()
+ * definition. This function use these variables. But we want function to
+ * use dll_* variables.
+ */
+#ifdef DYNAMIC_RUBY
+# define rb_cFalseClass (*dll_rb_cFalseClass)
+# define rb_cFixnum (*dll_rb_cFixnum)
+# define rb_cNilClass (*dll_rb_cNilClass)
+# define rb_cSymbol (*dll_rb_cSymbol)
+# define rb_cTrueClass (*dll_rb_cTrueClass)
+# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
+/*
+ * On ver 1.8, all Ruby functions are exported with "__declspce(dllimport)"
+ * in ruby.h. But it cause trouble for these variables, because it is
+ * defined in this file. When defined this RUBY_EXPORT it modified to
+ * "extern" and be able to avoid this problem.
+ */
+# define RUBY_EXPORT
+# endif
+#endif
+
+#include <ruby.h>
+
+#undef EXTERN
+#undef _
+
+/* T_DATA defined both by Ruby and Mac header files, hack around it... */
+#ifdef FEAT_GUI_MAC
+# define __OPENTRANSPORT__
+# define __OPENTRANSPORTPROTOCOL__
+# define __OPENTRANSPORTPROVIDERS__
+#endif
+
+#include "vim.h"
+#include "version.h"
+
+#if defined(PROTO) && !defined(FEAT_RUBY)
+/* Define these to be able to generate the function prototypes. */
+# define VALUE int
+# define RUBY_DATA_FUNC int
+#endif
+
+static int ruby_initialized = 0;
+static VALUE objtbl;
+
+static VALUE mVIM;
+static VALUE cBuffer;
+static VALUE cVimWindow;
+static VALUE eDeletedBufferError;
+static VALUE eDeletedWindowError;
+
+static int ensure_ruby_initialized(void);
+static void error_print(int);
+static void ruby_io_init(void);
+static void ruby_vim_init(void);
+
+#if defined(DYNAMIC_RUBY) || defined(PROTO)
+#ifdef PROTO
+# define HINSTANCE int /* for generating prototypes */
+#endif
+
+/*
+ * Wrapper defines
+ */
+#define rb_assoc_new dll_rb_assoc_new
+#define rb_cObject (*dll_rb_cObject)
+#define rb_check_type dll_rb_check_type
+#define rb_class_path dll_rb_class_path
+#define rb_data_object_alloc dll_rb_data_object_alloc
+#define rb_define_class_under dll_rb_define_class_under
+#define rb_define_const dll_rb_define_const
+#define rb_define_global_function dll_rb_define_global_function
+#define rb_define_method dll_rb_define_method
+#define rb_define_module dll_rb_define_module
+#define rb_define_module_function dll_rb_define_module_function
+#define rb_define_singleton_method dll_rb_define_singleton_method
+#define rb_define_virtual_variable dll_rb_define_virtual_variable
+#define rb_stdout (*dll_rb_stdout)
+#define rb_eArgError (*dll_rb_eArgError)
+#define rb_eIndexError (*dll_rb_eIndexError)
+#define rb_eRuntimeError (*dll_rb_eRuntimeError)
+#define rb_eStandardError (*dll_rb_eStandardError)
+#define rb_eval_string_protect dll_rb_eval_string_protect
+#define rb_global_variable dll_rb_global_variable
+#define rb_hash_aset dll_rb_hash_aset
+#define rb_hash_new dll_rb_hash_new
+#define rb_inspect dll_rb_inspect
+#define rb_int2inum dll_rb_int2inum
+#define rb_lastline_get dll_rb_lastline_get
+#define rb_lastline_set dll_rb_lastline_set
+#define rb_load_protect dll_rb_load_protect
+#define rb_num2long dll_rb_num2long
+#define rb_num2ulong dll_rb_num2ulong
+#define rb_obj_alloc dll_rb_obj_alloc
+#define rb_obj_as_string dll_rb_obj_as_string
+#define rb_obj_id dll_rb_obj_id
+#define rb_raise dll_rb_raise
+#define rb_str2cstr dll_rb_str2cstr
+#define rb_str_cat dll_rb_str_cat
+#define rb_str_concat dll_rb_str_concat
+#define rb_str_new dll_rb_str_new
+#define rb_str_new2 dll_rb_str_new2
+#define ruby_errinfo (*dll_ruby_errinfo)
+#define ruby_init dll_ruby_init
+#define ruby_init_loadpath dll_ruby_init_loadpath
+#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
+# define rb_w32_snprintf dll_rb_w32_snprintf
+#endif
+
+/*
+ * Pointers for dynamic link
+ */
+static VALUE (*dll_rb_assoc_new) (VALUE, VALUE);
+static VALUE *dll_rb_cFalseClass;
+static VALUE *dll_rb_cFixnum;
+static VALUE *dll_rb_cNilClass;
+static VALUE *dll_rb_cObject;
+static VALUE *dll_rb_cSymbol;
+static VALUE *dll_rb_cTrueClass;
+static void (*dll_rb_check_type) (VALUE,int);
+static VALUE (*dll_rb_class_path) (VALUE);
+static VALUE (*dll_rb_data_object_alloc) (VALUE, void*, RUBY_DATA_FUNC, RUBY_DATA_FUNC);
+static VALUE (*dll_rb_define_class_under) (VALUE, const char*, VALUE);
+static void (*dll_rb_define_const) (VALUE,const char*,VALUE);
+static void (*dll_rb_define_global_function) (const char*,VALUE(*)(),int);
+static void (*dll_rb_define_method) (VALUE,const char*,VALUE(*)(),int);
+static VALUE (*dll_rb_define_module) (const char*);
+static void (*dll_rb_define_module_function) (VALUE,const char*,VALUE(*)(),int);
+static void (*dll_rb_define_singleton_method) (VALUE,const char*,VALUE(*)(),int);
+static void (*dll_rb_define_virtual_variable) (const char*,VALUE(*)(),void(*)());
+static VALUE *dll_rb_stdout;
+static VALUE *dll_rb_eArgError;
+static VALUE *dll_rb_eIndexError;
+static VALUE *dll_rb_eRuntimeError;
+static VALUE *dll_rb_eStandardError;
+static VALUE (*dll_rb_eval_string_protect) (const char*, int*);
+static void (*dll_rb_global_variable) (VALUE*);
+static VALUE (*dll_rb_hash_aset) (VALUE, VALUE, VALUE);
+static VALUE (*dll_rb_hash_new) (void);
+static VALUE (*dll_rb_inspect) (VALUE);
+static VALUE (*dll_rb_int2inum) (long);
+static VALUE (*dll_rb_int2inum) (long);
+static VALUE (*dll_rb_lastline_get) (void);
+static void (*dll_rb_lastline_set) (VALUE);
+static void (*dll_rb_load_protect) (VALUE, int, int*);
+static long (*dll_rb_num2long) (VALUE);
+static unsigned long (*dll_rb_num2ulong) (VALUE);
+static VALUE (*dll_rb_obj_alloc) (VALUE);
+static VALUE (*dll_rb_obj_as_string) (VALUE);
+static VALUE (*dll_rb_obj_id) (VALUE);
+static void (*dll_rb_raise) (VALUE, const char*, ...);
+static char *(*dll_rb_str2cstr) (VALUE,int*);
+static VALUE (*dll_rb_str_cat) (VALUE, const char*, long);
+static VALUE (*dll_rb_str_concat) (VALUE, VALUE);
+static VALUE (*dll_rb_str_new) (const char*, long);
+static VALUE (*dll_rb_str_new2) (const char*);
+static VALUE *dll_ruby_errinfo;
+static void (*dll_ruby_init) (void);
+static void (*dll_ruby_init_loadpath) (void);
+#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
+static int (*dll_rb_w32_snprintf)(char*, size_t, const char*, ...);
+#endif
+
+static HINSTANCE hinstRuby = 0; /* Instance of ruby.dll */
+
+/*
+ * Table of name to function pointer of python.
+ */
+#define RUBY_PROC FARPROC
+static struct
+{
+ char *name;
+ RUBY_PROC *ptr;
+} ruby_funcname_table[] =
+{
+ {"rb_assoc_new", (RUBY_PROC*)&dll_rb_assoc_new},
+ {"rb_cFalseClass", (RUBY_PROC*)&dll_rb_cFalseClass},
+ {"rb_cFixnum", (RUBY_PROC*)&dll_rb_cFixnum},
+ {"rb_cNilClass", (RUBY_PROC*)&dll_rb_cNilClass},
+ {"rb_cObject", (RUBY_PROC*)&dll_rb_cObject},
+ {"rb_cSymbol", (RUBY_PROC*)&dll_rb_cSymbol},
+ {"rb_cTrueClass", (RUBY_PROC*)&dll_rb_cTrueClass},
+ {"rb_check_type", (RUBY_PROC*)&dll_rb_check_type},
+ {"rb_class_path", (RUBY_PROC*)&dll_rb_class_path},
+ {"rb_data_object_alloc", (RUBY_PROC*)&dll_rb_data_object_alloc},
+ {"rb_define_class_under", (RUBY_PROC*)&dll_rb_define_class_under},
+ {"rb_define_const", (RUBY_PROC*)&dll_rb_define_const},
+ {"rb_define_global_function", (RUBY_PROC*)&dll_rb_define_global_function},
+ {"rb_define_method", (RUBY_PROC*)&dll_rb_define_method},
+ {"rb_define_module", (RUBY_PROC*)&dll_rb_define_module},
+ {"rb_define_module_function", (RUBY_PROC*)&dll_rb_define_module_function},
+ {"rb_define_singleton_method", (RUBY_PROC*)&dll_rb_define_singleton_method},
+ {"rb_define_virtual_variable", (RUBY_PROC*)&dll_rb_define_virtual_variable},
+ {"rb_stdout", (RUBY_PROC*)&dll_rb_stdout},
+ {"rb_eArgError", (RUBY_PROC*)&dll_rb_eArgError},
+ {"rb_eIndexError", (RUBY_PROC*)&dll_rb_eIndexError},
+ {"rb_eRuntimeError", (RUBY_PROC*)&dll_rb_eRuntimeError},
+ {"rb_eStandardError", (RUBY_PROC*)&dll_rb_eStandardError},
+ {"rb_eval_string_protect", (RUBY_PROC*)&dll_rb_eval_string_protect},
+ {"rb_global_variable", (RUBY_PROC*)&dll_rb_global_variable},
+ {"rb_hash_aset", (RUBY_PROC*)&dll_rb_hash_aset},
+ {"rb_hash_new", (RUBY_PROC*)&dll_rb_hash_new},
+ {"rb_inspect", (RUBY_PROC*)&dll_rb_inspect},
+ {"rb_int2inum", (RUBY_PROC*)&dll_rb_int2inum},
+ {"rb_lastline_get", (RUBY_PROC*)&dll_rb_lastline_get},
+ {"rb_lastline_set", (RUBY_PROC*)&dll_rb_lastline_set},
+ {"rb_load_protect", (RUBY_PROC*)&dll_rb_load_protect},
+ {"rb_num2long", (RUBY_PROC*)&dll_rb_num2long},
+ {"rb_num2ulong", (RUBY_PROC*)&dll_rb_num2ulong},
+ {"rb_obj_alloc", (RUBY_PROC*)&dll_rb_obj_alloc},
+ {"rb_obj_as_string", (RUBY_PROC*)&dll_rb_obj_as_string},
+ {"rb_obj_id", (RUBY_PROC*)&dll_rb_obj_id},
+ {"rb_raise", (RUBY_PROC*)&dll_rb_raise},
+ {"rb_str2cstr", (RUBY_PROC*)&dll_rb_str2cstr},
+ {"rb_str_cat", (RUBY_PROC*)&dll_rb_str_cat},
+ {"rb_str_concat", (RUBY_PROC*)&dll_rb_str_concat},
+ {"rb_str_new", (RUBY_PROC*)&dll_rb_str_new},
+ {"rb_str_new2", (RUBY_PROC*)&dll_rb_str_new2},
+ {"ruby_errinfo", (RUBY_PROC*)&dll_ruby_errinfo},
+ {"ruby_init", (RUBY_PROC*)&dll_ruby_init},
+ {"ruby_init_loadpath", (RUBY_PROC*)&dll_ruby_init_loadpath},
+#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
+ {"rb_w32_snprintf", (RUBY_PROC*)&dll_rb_w32_snprintf},
+#endif
+ {"", NULL},
+};
+
+/*
+ * Free ruby.dll
+ */
+ static void
+end_dynamic_ruby()
+{
+ if (hinstRuby)
+ {
+ FreeLibrary(hinstRuby);
+ hinstRuby = 0;
+ }
+}
+
+/*
+ * Load library and get all pointers.
+ * Parameter 'libname' provides name of DLL.
+ * Return OK or FAIL.
+ */
+ static int
+ruby_runtime_link_init(char *libname, int verbose)
+{
+ int i;
+
+ if (hinstRuby)
+ return OK;
+ hinstRuby = LoadLibrary(libname);
+ if (!hinstRuby)
+ {
+ if (verbose)
+ EMSG2(_(e_loadlib), libname);
+ return FAIL;
+ }
+
+ for (i = 0; ruby_funcname_table[i].ptr; ++i)
+ {
+ if (!(*ruby_funcname_table[i].ptr = GetProcAddress(hinstRuby,
+ ruby_funcname_table[i].name)))
+ {
+ FreeLibrary(hinstRuby);
+ hinstRuby = 0;
+ if (verbose)
+ EMSG2(_(e_loadfunc), ruby_funcname_table[i].name);
+ return FAIL;
+ }
+ }
+ return OK;
+}
+
+/*
+ * If ruby is enabled (there is installed ruby on Windows system) return TRUE,
+ * else FALSE.
+ */
+ int
+ruby_enabled(verbose)
+ int verbose;
+{
+ return ruby_runtime_link_init(DYNAMIC_RUBY_DLL, verbose) == OK;
+}
+#endif /* defined(DYNAMIC_RUBY) || defined(PROTO) */
+
+ void
+ruby_end()
+{
+#ifdef DYNAMIC_RUBY
+ end_dynamic_ruby();
+#endif
+}
+
+void ex_ruby(exarg_T *eap)
+{
+ int state;
+ char *script = NULL;
+
+ script = script_get(eap, eap->arg);
+ if (!eap->skip && ensure_ruby_initialized())
+ {
+ if (script == NULL)
+ rb_eval_string_protect((char *)eap->arg, &state);
+ else
+ rb_eval_string_protect(script, &state);
+ if (state)
+ error_print(state);
+ }
+ vim_free(script);
+}
+
+void ex_rubydo(exarg_T *eap)
+{
+ int state;
+ linenr_T i;
+
+ if (ensure_ruby_initialized())
+ {
+ if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
+ return;
+ for (i = eap->line1; i <= eap->line2; i++) {
+ VALUE line, oldline;
+
+ line = oldline = rb_str_new2(ml_get(i));
+ rb_lastline_set(line);
+ rb_eval_string_protect((char *) eap->arg, &state);
+ if (state) {
+ error_print(state);
+ break;
+ }
+ line = rb_lastline_get();
+ if (!NIL_P(line)) {
+ if (TYPE(line) != T_STRING) {
+ EMSG("E265: $_ must be an instance of String");
+ return;
+ }
+ ml_replace(i, (char_u *) STR2CSTR(line), 1);
+ changed();
+#ifdef SYNTAX_HL
+ syn_changed(i); /* recompute syntax hl. for this line */
+#endif
+ }
+ }
+ check_cursor();
+ update_curbuf(NOT_VALID);
+ }
+}
+
+void ex_rubyfile(exarg_T *eap)
+{
+ int state;
+
+ if (ensure_ruby_initialized())
+ {
+ rb_load_protect(rb_str_new2((char *) eap->arg), 0, &state);
+ if (state) error_print(state);
+ }
+}
+
+void ruby_buffer_free(buf_T *buf)
+{
+ if (buf->ruby_ref) {
+ rb_hash_aset(objtbl, rb_obj_id((VALUE) buf->ruby_ref), Qnil);
+ RDATA(buf->ruby_ref)->data = NULL;
+ }
+}
+
+void ruby_window_free(win_T *win)
+{
+ if (win->ruby_ref) {
+ rb_hash_aset(objtbl, rb_obj_id((VALUE) win->ruby_ref), Qnil);
+ RDATA(win->ruby_ref)->data = NULL;
+ }
+}
+
+static int ensure_ruby_initialized(void)
+{
+ if (!ruby_initialized)
+ {
+#ifdef DYNAMIC_RUBY
+ if (ruby_enabled(TRUE))
+ {
+#endif
+ ruby_init();
+ ruby_init_loadpath();
+ ruby_io_init();
+ ruby_vim_init();
+ ruby_initialized = 1;
+#ifdef DYNAMIC_RUBY
+ }
+ else
+ {
+ EMSG(_("E266: Sorry, this command is disabled, the Ruby library could not be loaded."));
+ return 0;
+ }
+#endif
+ }
+ return ruby_initialized;
+}
+
+static void error_print(int state)
+{
+#ifndef DYNAMIC_RUBY
+ RUBYEXTERN VALUE ruby_errinfo;
+#endif
+ VALUE eclass;
+ VALUE einfo;
+ char buff[BUFSIZ];
+
+#define TAG_RETURN 0x1
+#define TAG_BREAK 0x2
+#define TAG_NEXT 0x3
+#define TAG_RETRY 0x4
+#define TAG_REDO 0x5
+#define TAG_RAISE 0x6
+#define TAG_THROW 0x7
+#define TAG_FATAL 0x8
+#define TAG_MASK 0xf
+
+ switch (state) {
+ case TAG_RETURN:
+ EMSG("E267: unexpected return");
+ break;
+ case TAG_NEXT:
+ EMSG("E268: unexpected next");
+ break;
+ case TAG_BREAK:
+ EMSG("E269: unexpected break");
+ break;
+ case TAG_REDO:
+ EMSG("E270: unexpected redo");
+ break;
+ case TAG_RETRY:
+ EMSG("E271: retry outside of rescue clause");
+ break;
+ case TAG_RAISE:
+ case TAG_FATAL:
+ eclass = CLASS_OF(ruby_errinfo);
+ einfo = rb_obj_as_string(ruby_errinfo);
+ if (eclass == rb_eRuntimeError && RSTRING(einfo)->len == 0) {
+ EMSG("E272: unhandled exception");
+ }
+ else {
+ VALUE epath;
+ char *p;
+
+ epath = rb_class_path(eclass);
+ snprintf(buff, BUFSIZ, "%s: %s",
+ RSTRING(epath)->ptr, RSTRING(einfo)->ptr);
+ p = strchr(buff, '\n');
+ if (p) *p = '\0';
+ EMSG(buff);
+ }
+ break;
+ default:
+ snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state);
+ EMSG(buff);
+ break;
+ }
+}
+
+static VALUE vim_message(VALUE self, VALUE str)
+{
+ char *buff, *p;
+
+ str = rb_obj_as_string(str);
+ buff = ALLOCA_N(char, RSTRING(str)->len);
+ strcpy(buff, RSTRING(str)->ptr);
+ p = strchr(buff, '\n');
+ if (p) *p = '\0';
+ MSG(buff);
+ return Qnil;
+}
+
+static VALUE vim_set_option(VALUE self, VALUE str)
+{
+ do_set((char_u *)STR2CSTR(str), 0);
+ update_screen(NOT_VALID);
+ return Qnil;
+}
+
+static VALUE vim_command(VALUE self, VALUE str)
+{
+ do_cmdline_cmd((char_u *)STR2CSTR(str));
+ return Qnil;
+}
+
+static VALUE vim_evaluate(VALUE self, VALUE str)
+{
+#ifdef FEAT_EVAL
+ char_u *value = eval_to_string((char_u *)STR2CSTR(str), NULL);
+
+ if (value)
+ {
+ VALUE val = rb_str_new2(value);
+ vim_free(value);
+ return val;
+ }
+ else
+#endif
+ return Qnil;
+}
+
+static VALUE buffer_new(buf_T *buf)
+{
+ if (buf->ruby_ref) {
+ return (VALUE) buf->ruby_ref;
+ }
+ else {
+ VALUE obj = Data_Wrap_Struct(cBuffer, 0, 0, buf);
+ buf->ruby_ref = (void *) obj;
+ rb_hash_aset(objtbl, rb_obj_id(obj), obj);
+ return obj;
+ }
+}
+
+static buf_T *get_buf(VALUE obj)
+{
+ buf_T *buf;
+
+ Data_Get_Struct(obj, buf_T, buf);
+ if (buf == NULL)
+ rb_raise(eDeletedBufferError, "attempt to refer to deleted buffer");
+ return buf;
+}
+
+static VALUE buffer_s_current()
+{
+ return buffer_new(curbuf);
+}
+
+static VALUE buffer_s_count()
+{
+ buf_T *b;
+ int n = 0;
+
+ for (b = firstbuf; b; b = b->b_next) n++;
+ return INT2NUM(n);
+}
+
+static VALUE buffer_s_aref(VALUE self, VALUE num)
+{
+ buf_T *b;
+ int n = NUM2INT(num);
+
+ for (b = firstbuf; b; b = b->b_next, --n) {
+ if (n == 0)
+ return buffer_new(b);
+ }
+ return Qnil;
+}
+
+static VALUE buffer_name(VALUE self)
+{
+ buf_T *buf = get_buf(self);
+
+ return buf->b_ffname ? rb_str_new2(buf->b_ffname) : Qnil;
+}
+
+static VALUE buffer_number(VALUE self)
+{
+ buf_T *buf = get_buf(self);
+
+ return INT2NUM(buf->b_fnum);
+}
+
+static VALUE buffer_count(VALUE self)
+{
+ buf_T *buf = get_buf(self);
+
+ return INT2NUM(buf->b_ml.ml_line_count);
+}
+
+static VALUE buffer_aref(VALUE self, VALUE num)
+{
+ buf_T *buf = get_buf(self);
+ long n = NUM2LONG(num);
+
+ if (n > 0 && n <= buf->b_ml.ml_line_count) {
+ char *line = ml_get_buf(buf, n, FALSE);
+ return line ? rb_str_new2(line) : Qnil;
+ }
+ else {
+ rb_raise(rb_eIndexError, "index %d out of buffer", n);
+ return Qnil; /* For stop warning */
+ }
+}
+
+static VALUE buffer_aset(VALUE self, VALUE num, VALUE str)
+{
+ buf_T *buf = get_buf(self);
+ buf_T *savebuf = curbuf;
+ char *line = STR2CSTR(str);
+ long n = NUM2LONG(num);
+
+ if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL) {
+ curbuf = buf;
+ if (u_savesub(n) == OK) {
+ ml_replace(n, (char_u *) line, TRUE);
+ changed();
+#ifdef SYNTAX_HL
+ syn_changed(n); /* recompute syntax hl. for this line */
+#endif
+ }
+ curbuf = savebuf;
+ update_curbuf(NOT_VALID);
+ }
+ else {
+ rb_raise(rb_eIndexError, "index %d out of buffer", n);
+ return Qnil; /* For stop warning */
+ }
+ return str;
+}
+
+static VALUE buffer_delete(VALUE self, VALUE num)
+{
+ buf_T *buf = get_buf(self);
+ buf_T *savebuf = curbuf;
+ long n = NUM2LONG(num);
+
+ if (n > 0 && n <= buf->b_ml.ml_line_count) {
+ curbuf = buf;
+ if (u_savedel(n, 1) == OK) {
+ mark_adjust(n, n, MAXLNUM, -1);
+ ml_delete(n, 0);
+ changed();
+ }
+ curbuf = savebuf;
+ update_curbuf(NOT_VALID);
+ }
+ else {
+ rb_raise(rb_eIndexError, "index %d out of buffer", n);
+ }
+ return Qnil;
+}
+
+static VALUE buffer_append(VALUE self, VALUE num, VALUE str)
+{
+ buf_T *buf = get_buf(self);
+ buf_T *savebuf = curbuf;
+ char *line = STR2CSTR(str);
+ long n = NUM2LONG(num);
+
+ if (n >= 0 && n <= buf->b_ml.ml_line_count && line != NULL) {
+ curbuf = buf;
+ if (u_inssub(n + 1) == OK) {
+ mark_adjust(n + 1, MAXLNUM, 1L, 0L);
+ ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
+ changed();
+ }
+ curbuf = savebuf;
+ update_curbuf(NOT_VALID);
+ }
+ else {
+ rb_raise(rb_eIndexError, "index %d out of buffer", n);
+ }
+ return str;
+}
+
+static VALUE window_new(win_T *win)
+{
+ if (win->ruby_ref) {
+ return (VALUE) win->ruby_ref;
+ }
+ else {
+ VALUE obj = Data_Wrap_Struct(cVimWindow, 0, 0, win);
+ win->ruby_ref = (void *) obj;
+ rb_hash_aset(objtbl, rb_obj_id(obj), obj);
+ return obj;
+ }
+}
+
+static win_T *get_win(VALUE obj)
+{
+ win_T *win;
+
+ Data_Get_Struct(obj, win_T, win);
+ if (win == NULL)
+ rb_raise(eDeletedWindowError, "attempt to refer to deleted window");
+ return win;
+}
+
+static VALUE window_s_current()
+{
+ return window_new(curwin);
+}
+
+static VALUE window_s_count()
+{
+#ifdef FEAT_WINDOWS
+ win_T *w;
+ int n = 0;
+
+ for (w = firstwin; w; w = w->w_next)
+ n++;
+ return INT2NUM(n);
+#else
+ return INT2NUM(1);
+#endif
+}
+
+static VALUE window_s_aref(VALUE self, VALUE num)
+{
+ win_T *w;
+ int n = NUM2INT(num);
+
+#ifndef FEAT_WINDOWS
+ w = curwin;
+#else
+ for (w = firstwin; w != NULL; w = w->w_next, --n)
+#endif
+ if (n == 0)
+ return window_new(w);
+ return Qnil;
+}
+
+static VALUE window_buffer(VALUE self)
+{
+ win_T *win = get_win(self);
+
+ return buffer_new(win->w_buffer);
+}
+
+static VALUE window_height(VALUE self)
+{
+ win_T *win = get_win(self);
+
+ return INT2NUM(win->w_height);
+}
+
+static VALUE window_set_height(VALUE self, VALUE height)
+{
+ win_T *win = get_win(self);
+ win_T *savewin = curwin;
+
+ curwin = win;
+ win_setheight(NUM2INT(height));
+ curwin = savewin;
+ return height;
+}
+
+static VALUE window_cursor(VALUE self)
+{
+ win_T *win = get_win(self);
+
+ return rb_assoc_new(INT2NUM(win->w_cursor.lnum), INT2NUM(win->w_cursor.col));
+}
+
+static VALUE window_set_cursor(VALUE self, VALUE pos)
+{
+ VALUE lnum, col;
+ win_T *win = get_win(self);
+
+ Check_Type(pos, T_ARRAY);
+ if (RARRAY(pos)->len != 2)
+ rb_raise(rb_eArgError, "array length must be 2");
+ lnum = RARRAY(pos)->ptr[0];
+ col = RARRAY(pos)->ptr[1];
+ win->w_cursor.lnum = NUM2LONG(lnum);
+ win->w_cursor.col = NUM2UINT(col);
+ check_cursor(); /* put cursor on an existing line */
+ update_screen(NOT_VALID);
+ return Qnil;
+}
+
+static VALUE f_p(int argc, VALUE *argv, VALUE self)
+{
+ int i;
+ VALUE str = rb_str_new("", 0);
+
+ for (i = 0; i < argc; i++) {
+ if (i > 0) rb_str_cat(str, ", ", 2);
+ rb_str_concat(str, rb_inspect(argv[i]));
+ }
+ MSG(RSTRING(str)->ptr);
+ return Qnil;
+}
+
+static void ruby_io_init(void)
+{
+#ifndef DYNAMIC_RUBY
+ RUBYEXTERN VALUE rb_stdout;
+#endif
+
+ rb_stdout = rb_obj_alloc(rb_cObject);
+ rb_define_singleton_method(rb_stdout, "write", vim_message, 1);
+ rb_define_global_function("p", f_p, -1);
+}
+
+static void ruby_vim_init(void)
+{
+ objtbl = rb_hash_new();
+ rb_global_variable(&objtbl);
+
+ mVIM = rb_define_module("VIM");
+ rb_define_const(mVIM, "VERSION_MAJOR", INT2NUM(VIM_VERSION_MAJOR));
+ rb_define_const(mVIM, "VERSION_MINOR", INT2NUM(VIM_VERSION_MINOR));
+ rb_define_const(mVIM, "VERSION_BUILD", INT2NUM(VIM_VERSION_BUILD));
+ rb_define_const(mVIM, "VERSION_PATCHLEVEL", INT2NUM(VIM_VERSION_PATCHLEVEL));
+ rb_define_const(mVIM, "VERSION_SHORT", rb_str_new2(VIM_VERSION_SHORT));
+ rb_define_const(mVIM, "VERSION_MEDIUM", rb_str_new2(VIM_VERSION_MEDIUM));
+ rb_define_const(mVIM, "VERSION_LONG", rb_str_new2(VIM_VERSION_LONG));
+ rb_define_const(mVIM, "VERSION_LONG_DATE", rb_str_new2(VIM_VERSION_LONG_DATE));
+ rb_define_module_function(mVIM, "message", vim_message, 1);
+ rb_define_module_function(mVIM, "set_option", vim_set_option, 1);
+ rb_define_module_function(mVIM, "command", vim_command, 1);
+ rb_define_module_function(mVIM, "evaluate", vim_evaluate, 1);
+
+ eDeletedBufferError = rb_define_class_under(mVIM, "DeletedBufferError",
+ rb_eStandardError);
+ eDeletedWindowError = rb_define_class_under(mVIM, "DeletedWindowError",
+ rb_eStandardError);
+
+ cBuffer = rb_define_class_under(mVIM, "Buffer", rb_cObject);
+ rb_define_singleton_method(cBuffer, "current", buffer_s_current, 0);
+ rb_define_singleton_method(cBuffer, "count", buffer_s_count, 0);
+ rb_define_singleton_method(cBuffer, "[]", buffer_s_aref, 1);
+ rb_define_method(cBuffer, "name", buffer_name, 0);
+ rb_define_method(cBuffer, "number", buffer_number, 0);
+ rb_define_method(cBuffer, "count", buffer_count, 0);
+ rb_define_method(cBuffer, "length", buffer_count, 0);
+ rb_define_method(cBuffer, "[]", buffer_aref, 1);
+ rb_define_method(cBuffer, "[]=", buffer_aset, 2);
+ rb_define_method(cBuffer, "delete", buffer_delete, 1);
+ rb_define_method(cBuffer, "append", buffer_append, 2);
+
+ cVimWindow = rb_define_class_under(mVIM, "Window", rb_cObject);
+ rb_define_singleton_method(cVimWindow, "current", window_s_current, 0);
+ rb_define_singleton_method(cVimWindow, "count", window_s_count, 0);
+ rb_define_singleton_method(cVimWindow, "[]", window_s_aref, 1);
+ rb_define_method(cVimWindow, "buffer", window_buffer, 0);
+ rb_define_method(cVimWindow, "height", window_height, 0);
+ rb_define_method(cVimWindow, "height=", window_set_height, 1);
+ rb_define_method(cVimWindow, "cursor", window_cursor, 0);
+ rb_define_method(cVimWindow, "cursor=", window_set_cursor, 1);
+
+ rb_define_virtual_variable("$curbuf", buffer_s_current, 0);
+ rb_define_virtual_variable("$curwin", window_s_current, 0);
+}
diff --git a/src/if_sniff.c b/src/if_sniff.c
new file mode 100644
index 000000000..4cb0bee24
--- /dev/null
+++ b/src/if_sniff.c
@@ -0,0 +1,1210 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * if_sniff.c Interface between Vim and SNiFF+
+ *
+ * $Id$
+ *
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+
+#ifdef WIN32
+# include <stdio.h>
+# include <fcntl.h>
+# include <io.h>
+# include <process.h>
+# include <string.h>
+# include <assert.h>
+#else
+# ifdef FEAT_GUI_X11
+# include "gui_x11.pro"
+# endif
+# include "os_unixx.h"
+#endif
+
+static int sniffemacs_pid;
+
+int fd_from_sniff;
+int sniff_connected = 0;
+int sniff_request_waiting = 0;
+int want_sniff_request = 0;
+
+#define MAX_REQUEST_LEN 512
+
+#define NEED_SYMBOL 2
+#define EMPTY_SYMBOL 4
+#define NEED_FILE 8
+#define SILENT 16
+#define DISCONNECT 32
+#define CONNECT 64
+
+#define RQ_NONE 0
+#define RQ_SIMPLE 1
+#define RQ_CONTEXT NEED_FILE + NEED_SYMBOL
+#define RQ_SCONTEXT NEED_FILE + NEED_SYMBOL + EMPTY_SYMBOL
+#define RQ_NOSYMBOL NEED_FILE
+#define RQ_SILENT RQ_NOSYMBOL + SILENT
+#define RQ_CONNECT RQ_NONE + CONNECT
+#define RQ_DISCONNECT RQ_SIMPLE + DISCONNECT
+
+struct sn_cmd
+{
+ char *cmd_name;
+ char cmd_code;
+ char *cmd_msg;
+ int cmd_type;
+};
+
+struct sn_cmd_list
+{
+ struct sn_cmd* sniff_cmd;
+ struct sn_cmd_list* next_cmd;
+};
+
+static struct sn_cmd sniff_cmds[] =
+{
+ { "toggle", 'e', N_("Toggle implementation/definition"),RQ_SCONTEXT },
+ { "superclass", 's', N_("Show base class of"), RQ_CONTEXT },
+ { "overridden", 'm', N_("Show overridden member function"),RQ_SCONTEXT },
+ { "retrieve-file", 'r', N_("Retrieve from file"), RQ_CONTEXT },
+ { "retrieve-project",'p', N_("Retrieve from project"), RQ_CONTEXT },
+ { "retrieve-all-projects",
+ 'P', N_("Retrieve from all projects"), RQ_CONTEXT },
+ { "retrieve-next", 'R', N_("Retrieve"), RQ_CONTEXT },
+ { "goto-symbol", 'g', N_("Show source of"), RQ_CONTEXT },
+ { "find-symbol", 'f', N_("Find symbol"), RQ_CONTEXT },
+ { "browse-class", 'w', N_("Browse class"), RQ_CONTEXT },
+ { "hierarchy", 't', N_("Show class in hierarchy"), RQ_CONTEXT },
+ { "restr-hier", 'T', N_("Show class in restricted hierarchy"),RQ_CONTEXT },
+ { "xref-to", 'x', N_("Xref refers to"), RQ_CONTEXT },
+ { "xref-by", 'X', N_("Xref referred by"), RQ_CONTEXT },
+ { "xref-has", 'c', N_("Xref has a"), RQ_CONTEXT },
+ { "xref-used-by", 'C', N_("Xref used by"), RQ_CONTEXT },
+ { "show-docu", 'd', N_("Show docu of"), RQ_CONTEXT },
+ { "gen-docu", 'D', N_("Generate docu for"), RQ_CONTEXT },
+ { "connect", 'y', NULL, RQ_CONNECT },
+ { "disconnect", 'q', NULL, RQ_DISCONNECT },
+ { "font-info", 'z', NULL, RQ_SILENT },
+ { "update", 'u', NULL, RQ_SILENT },
+ { NULL, '\0', NULL, 0}
+};
+
+
+static char *SniffEmacs[2] = {"sniffemacs", (char *)NULL}; /* Yes, Emacs! */
+static int fd_to_sniff;
+static int sniff_will_disconnect = 0;
+static char msg_sniff_disconnect[] = N_("Cannot connect to SNiFF+. Check environment (sniffemacs must be found in $PATH).\n");
+static char sniff_rq_sep[] = " ";
+static struct sn_cmd_list *sniff_cmd_ext = NULL;
+
+/* Initializing vim commands
+ * executed each time vim connects to Sniff
+ */
+static char *init_cmds[]= {
+ "augroup sniff",
+ "autocmd BufWritePost * sniff update",
+ "autocmd BufReadPost * sniff font-info",
+ "autocmd VimLeave * sniff disconnect",
+ "augroup END",
+
+ "let g:sniff_connected = 1",
+
+ "if ! exists('g:sniff_mappings_sourced')|"
+ "if ! exists('g:sniff_mappings')|"
+ "if exists('$SNIFF_DIR4')|"
+ "let g:sniff_mappings='$SNIFF_DIR4/config/integrations/vim/sniff.vim'|"
+ "else|"
+ "let g:sniff_mappings='$SNIFF_DIR/config/sniff.vim'|"
+ "endif|"
+ "endif|"
+ "let g:sniff_mappings=expand(g:sniff_mappings)|"
+ "if filereadable(g:sniff_mappings)|"
+ "execute 'source' g:sniff_mappings|"
+ "let g:sniff_mappings_sourced=1|"
+ "endif|"
+ "endif",
+
+ NULL
+};
+
+/*-------- Function Prototypes ----------------------------------*/
+
+static int ConnectToSniffEmacs __ARGS((void));
+static void sniff_connect __ARGS((void));
+static void HandleSniffRequest __ARGS((char* buffer));
+static int get_request __ARGS((int fd, char *buf, int maxlen));
+static void WriteToSniff __ARGS((char *str));
+static void SendRequest __ARGS((struct sn_cmd *command, char* symbol));
+static void vi_msg __ARGS((char *));
+static void vi_error_msg __ARGS((char *));
+static char *vi_symbol_under_cursor __ARGS((void));
+static void vi_open_file __ARGS((char *));
+static char *vi_buffer_name __ARGS((void));
+static buf_T *vi_find_buffer __ARGS((char *));
+static void vi_exec_cmd __ARGS((char *));
+static void vi_set_cursor_pos __ARGS((long char_nr));
+static long vi_cursor_pos __ARGS((void));
+
+/* debug trace */
+#if 0
+static FILE* _tracefile = NULL;
+#define SNIFF_TRACE_OPEN(file) if (!_tracefile) _tracefile = fopen(file, "w")
+#define SNIFF_TRACE(msg) fprintf(_tracefile, msg); fflush(_tracefile);
+#define SNIFF_TRACE1(msg, arg) fprintf(_tracefile, msg,arg); fflush(_tracefile);
+#define SNIFF_TRACE_CLOSE fclose(_tracefile); _tracefile=NULL;
+#else
+#define SNIFF_TRACE_OPEN(file)
+#define SNIFF_TRACE(msg)
+#define SNIFF_TRACE1(msg, arg)
+#define SNIFF_TRACE_CLOSE
+#endif
+
+/*-------- Windows Only Declarations -----------------------------*/
+#ifdef WIN32
+
+static int sniff_request_processed=1;
+static HANDLE sniffemacs_handle=NULL;
+static HANDLE readthread_handle=NULL;
+static HANDLE handle_to_sniff=NULL;
+static HANDLE handle_from_sniff=NULL;
+
+struct sniffBufNode
+{
+ struct sniffBufNode *next;
+ int bufLen;
+ char buf[MAX_REQUEST_LEN];
+};
+static struct sniffBufNode *sniffBufStart=NULL;
+static struct sniffBufNode *sniffBufEnd=NULL;
+static HANDLE hBufferMutex=NULL;
+
+# ifdef FEAT_GUI_W32
+ extern HWND s_hwnd; /* gvim's Window handle */
+# endif
+/*
+ * some helper functions for Windows port only
+ */
+
+ static HANDLE
+ExecuteDetachedProgram(char *szBinary, char *szCmdLine,
+ HANDLE hStdInput, HANDLE hStdOutput)
+{
+ BOOL bResult;
+ DWORD nError;
+ PROCESS_INFORMATION aProcessInformation;
+ PROCESS_INFORMATION *pProcessInformation= &aProcessInformation;
+ STARTUPINFO aStartupInfo;
+ STARTUPINFO *pStartupInfo= &aStartupInfo;
+ DWORD dwCreationFlags= 0;
+ char szPath[512];
+ HINSTANCE hResult;
+
+ hResult = FindExecutable(szBinary, ".", szPath);
+ if ((int)hResult <= 32)
+ {
+ /* can't find the exe file */
+ return NULL;
+ }
+
+ ZeroMemory(pStartupInfo, sizeof(*pStartupInfo));
+ pStartupInfo->dwFlags= STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
+ pStartupInfo->hStdInput = hStdInput;
+ pStartupInfo->hStdOutput = hStdOutput;
+ pStartupInfo->wShowWindow= SW_HIDE;
+ pStartupInfo->cb = sizeof(STARTUPINFO);
+
+ bResult= CreateProcess(
+ szPath,
+ szCmdLine,
+ NULL, /* security attr for process */
+ NULL, /* security attr for primary thread */
+ TRUE, /* DO inherit stdin and stdout */
+ dwCreationFlags, /* creation flags */
+ NULL, /* environment */
+ ".", /* current directory */
+ pStartupInfo, /* startup info: NULL crashes */
+ pProcessInformation /* process information: NULL crashes */
+ );
+ nError= GetLastError();
+ if (bResult)
+ {
+ CloseHandle(pProcessInformation->hThread);
+ CloseHandle(hStdInput);
+ CloseHandle(hStdOutput);
+ return(pProcessInformation->hProcess);
+ }
+ else
+ return(NULL);
+}
+
+/*
+ * write to the internal Thread / Thread communications buffer.
+ * Return TRUE if successful, FALSE else.
+ */
+ static BOOL
+writeToBuffer(char *msg, int len)
+{
+ DWORD dwWaitResult; /* Request ownership of mutex. */
+ struct sniffBufNode *bn;
+ int bnSize;
+
+ SNIFF_TRACE1("writeToBuffer %d\n", len);
+ bnSize = sizeof(struct sniffBufNode) - MAX_REQUEST_LEN + len + 1;
+ if (bnSize < 128) bnSize = 128; /* minimum length to avoid fragmentation */
+ bn = (struct sniffBufNode *)malloc(bnSize);
+ if (!bn)
+ return FALSE;
+
+ memcpy(bn->buf, msg, len);
+ bn->buf[len]='\0'; /* terminate CString for added safety */
+ bn->next = NULL;
+ bn->bufLen = len;
+ /* now, acquire a Mutex for adding the string to our linked list */
+ dwWaitResult = WaitForSingleObject(
+ hBufferMutex, /* handle of mutex */
+ 1000L); /* one-second time-out interval */
+ if (dwWaitResult == WAIT_OBJECT_0)
+ {
+ /* The thread got mutex ownership. */
+ if (sniffBufEnd)
+ {
+ sniffBufEnd->next = bn;
+ sniffBufEnd = bn;
+ }
+ else
+ sniffBufStart = sniffBufEnd = bn;
+ /* Release ownership of the mutex object. */
+ if (! ReleaseMutex(hBufferMutex))
+ {
+ /* Deal with error. */
+ }
+ return TRUE;
+ }
+
+ /* Cannot get mutex ownership due to time-out or mutex object abandoned. */
+ free(bn);
+ return FALSE;
+}
+
+/*
+ * read from the internal Thread / Thread communications buffer.
+ * Return TRUE if successful, FALSE else.
+ */
+ static int
+ReadFromBuffer(char *buf, int maxlen)
+{
+ DWORD dwWaitResult; /* Request ownership of mutex. */
+ int theLen;
+ struct sniffBufNode *bn;
+
+ dwWaitResult = WaitForSingleObject(
+ hBufferMutex, /* handle of mutex */
+ 1000L); /* one-second time-out interval */
+ if (dwWaitResult == WAIT_OBJECT_0)
+ {
+ if (!sniffBufStart)
+ {
+ /* all pending Requests Processed */
+ theLen = 0;
+ }
+ else
+ {
+ bn = sniffBufStart;
+ theLen = bn->bufLen;
+ SNIFF_TRACE1("ReadFromBuffer %d\n", theLen);
+ if (theLen >= maxlen)
+ {
+ /* notify the user of buffer overflow? */
+ theLen = maxlen-1;
+ }
+ memcpy(buf, bn->buf, theLen);
+ buf[theLen] = '\0';
+ if (! (sniffBufStart = bn->next))
+ {
+ sniffBufEnd = NULL;
+ sniff_request_processed = 1;
+ }
+ free(bn);
+ }
+ if (! ReleaseMutex(hBufferMutex))
+ {
+ /* Deal with error. */
+ }
+ return theLen;
+ }
+
+ /* Cannot get mutex ownership due to time-out or mutex object abandoned. */
+ return -1;
+}
+
+/* on Win32, a separate Thread reads the input pipe. get_request is not needed here. */
+ static void __cdecl
+SniffEmacsReadThread(void *dummy)
+{
+ static char ReadThreadBuffer[MAX_REQUEST_LEN];
+ int ReadThreadLen=0;
+ int result=0;
+ int msgLen=0;
+ char *msgStart, *msgCur;
+
+ SNIFF_TRACE("begin thread\n");
+ /* Read from the pipe to SniffEmacs */
+ while (sniff_connected)
+ {
+ if (!ReadFile(handle_from_sniff,
+ ReadThreadBuffer + ReadThreadLen, /* acknowledge rest in buffer */
+ MAX_REQUEST_LEN - ReadThreadLen,
+ &result,
+ NULL))
+ {
+ DWORD err = GetLastError();
+ result = -1;
+ }
+
+ if (result < 0)
+ {
+ /* probably sniffemacs died... log the Error? */
+ sniff_disconnect(1);
+ }
+ else if (result > 0)
+ {
+ ReadThreadLen += result-1; /* total length of valid chars */
+ for(msgCur=msgStart=ReadThreadBuffer; ReadThreadLen > 0; msgCur++, ReadThreadLen--)
+ {
+ if (*msgCur == '\0' || *msgCur == '\r' || *msgCur == '\n')
+ {
+ msgLen = msgCur-msgStart; /* don't add the CR/LF chars */
+ if (msgLen > 0)
+ writeToBuffer(msgStart, msgLen);
+ msgStart = msgCur + 1; /* over-read single CR/LF chars */
+ }
+ }
+
+ /* move incomplete message to beginning of buffer */
+ ReadThreadLen = msgCur - msgStart;
+ if (ReadThreadLen > 0)
+ mch_memmove(ReadThreadBuffer, msgStart, ReadThreadLen);
+
+ if (sniff_request_processed)
+ {
+ /* notify others that new data has arrived */
+ sniff_request_processed = 0;
+ sniff_request_waiting = 1;
+#ifdef FEAT_GUI_W32
+ PostMessage(s_hwnd, WM_USER, (WPARAM)0, (LPARAM)0);
+#endif
+ }
+ }
+ }
+ SNIFF_TRACE("end thread\n");
+}
+#endif /* WIN32 */
+/*-------- End of Windows Only Declarations ------------------------*/
+
+
+/* ProcessSniffRequests
+ * Function that should be called from outside
+ * to process the waiting sniff requests
+ */
+ void
+ProcessSniffRequests()
+{
+ static char buf[MAX_REQUEST_LEN];
+ int len;
+
+ while (sniff_connected)
+ {
+#ifdef WIN32
+ len = ReadFromBuffer(buf, sizeof(buf));
+#else
+ len = get_request(fd_from_sniff, buf, sizeof(buf));
+#endif
+ if (len < 0)
+ {
+ vi_error_msg(_("E274: Sniff: Error during read. Disconnected"));
+ sniff_disconnect(1);
+ break;
+ }
+ else if (len > 0)
+ HandleSniffRequest( buf );
+ else
+ break;
+ }
+
+ if (sniff_will_disconnect) /* Now the last msg has been processed */
+ sniff_disconnect(1);
+}
+
+ static struct sn_cmd *
+find_sniff_cmd(cmd)
+ char *cmd;
+{
+ struct sn_cmd *sniff_cmd = NULL;
+ int i;
+ for(i=0; sniff_cmds[i].cmd_name; i++)
+ {
+ if (!strcmp(cmd, sniff_cmds[i].cmd_name))
+ {
+ sniff_cmd = &sniff_cmds[i];
+ break;
+ }
+ }
+ if (!sniff_cmd)
+ {
+ struct sn_cmd_list *list = sniff_cmd_ext;
+ while(list)
+ {
+ if (!strcmp(cmd, list->sniff_cmd->cmd_name))
+ {
+ sniff_cmd = list->sniff_cmd;
+ break;
+ }
+ list = list->next_cmd;
+ }
+ }
+ return sniff_cmd;
+}
+
+ static int
+add_sniff_cmd(cmd, def, msg)
+ char *cmd;
+ char *def;
+ char *msg;
+{
+ int rc = 0;
+ if (def != NULL && def[0] != NUL && find_sniff_cmd(cmd) == NULL)
+ {
+ struct sn_cmd_list *list = sniff_cmd_ext;
+ struct sn_cmd *sniff_cmd = (struct sn_cmd*)malloc(sizeof(struct sn_cmd));
+ struct sn_cmd_list *cmd_node = (struct sn_cmd_list*)malloc(sizeof(struct sn_cmd_list));
+ int rq_type = 0;
+
+ /* unescape message text */
+ char *p = msg;
+ char *end = p+strlen(msg);
+ while(*p)
+ {
+ if (*p == '\\')
+ mch_memmove(p,p+1,end-p);
+ p++;
+ }
+ SNIFF_TRACE1("request name = %s\n",cmd);
+ SNIFF_TRACE1("request def = %s\n",def);
+ SNIFF_TRACE1("request msg = %s\n",msg);
+
+ while(list && list->next_cmd)
+ list = list->next_cmd;
+ if (!list)
+ sniff_cmd_ext = cmd_node;
+ else
+ list->next_cmd = cmd_node;
+
+ sniff_cmd->cmd_name = cmd;
+ sniff_cmd->cmd_code = def[0];
+ sniff_cmd->cmd_msg = msg;
+ switch(def[1])
+ {
+ case 'f':
+ rq_type = RQ_NOSYMBOL;
+ break;
+ case 's':
+ rq_type = RQ_CONTEXT;
+ break;
+ case 'S':
+ rq_type = RQ_SCONTEXT;
+ break;
+ default:
+ rq_type = RQ_SIMPLE;
+ break;
+ }
+ sniff_cmd->cmd_type = rq_type;
+ cmd_node->sniff_cmd = sniff_cmd;
+ cmd_node->next_cmd = NULL;
+ rc = 1;
+ }
+ return rc;
+}
+
+/* ex_sniff
+ * Handle ":sniff" command
+ */
+ void
+ex_sniff(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+ char_u *symbol = NULL;
+ char_u *cmd = NULL;
+
+ SNIFF_TRACE_OPEN("if_sniff.log");
+ if (ends_excmd(*arg)) /* no request: print available commands */
+ {
+ int i;
+ msg_start();
+ msg_outtrans_attr((char_u *)"-- SNiFF+ commands --", hl_attr(HLF_T));
+ for(i=0; sniff_cmds[i].cmd_name; i++)
+ {
+ msg_putchar('\n');
+ msg_outtrans((char_u *)":sniff ");
+ msg_outtrans((char_u *)sniff_cmds[i].cmd_name);
+ }
+ msg_putchar('\n');
+ msg_outtrans((char_u *)_("SNiFF+ is currently "));
+ if (!sniff_connected)
+ msg_outtrans((char_u *)_("not "));
+ msg_outtrans((char_u *)_("connected"));
+ msg_end();
+ }
+ else /* extract command name and symbol if present */
+ {
+ symbol = skiptowhite(arg);
+ cmd = vim_strnsave(arg, (int)(symbol-arg));
+ symbol = skipwhite(symbol);
+ if (ends_excmd(*symbol))
+ symbol = NULL;
+ if (!strcmp((char *)cmd, "addcmd"))
+ {
+ char_u *def = skiptowhite(symbol);
+ char_u *name = vim_strnsave(symbol, (int)(def-symbol));
+ char_u *msg;
+ def = skipwhite(def);
+ msg = skiptowhite(def);
+ def = vim_strnsave(def, (int)(msg-def));
+ msg = skipwhite(msg);
+ if (ends_excmd(*msg))
+ msg = vim_strsave(name);
+ else
+ msg = vim_strnsave(msg, (int)(skiptowhite_esc(msg)-msg));
+ if (!add_sniff_cmd((char*)name, (char*)def, (char*)msg))
+ {
+ vim_free(msg);
+ vim_free(def);
+ vim_free(name);
+ }
+ }
+ else
+ {
+ struct sn_cmd* sniff_cmd = find_sniff_cmd((char*)cmd);
+ if (sniff_cmd)
+ SendRequest(sniff_cmd, (char *)symbol);
+ else
+ EMSG2(_("E275: Unknown SNiFF+ request: %s"), cmd);
+ }
+ vim_free(cmd);
+ }
+}
+
+
+ static void
+sniff_connect()
+{
+ if (sniff_connected)
+ return;
+ if (ConnectToSniffEmacs())
+ vi_error_msg(_("E276: Error connecting to SNiFF+"));
+ else
+ {
+ int i;
+
+ for (i = 0; init_cmds[i]; i++)
+ vi_exec_cmd(init_cmds[i]);
+ }
+}
+
+ void
+sniff_disconnect(immediately)
+ int immediately;
+{
+ if (!sniff_connected)
+ return;
+ if (immediately)
+ {
+ vi_exec_cmd("augroup sniff");
+ vi_exec_cmd("au!");
+ vi_exec_cmd("augroup END");
+ vi_exec_cmd("unlet g:sniff_connected");
+ sniff_connected = 0;
+ want_sniff_request = 0;
+ sniff_will_disconnect = 0;
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_mch_wait_for_chars(0L);
+#endif
+#ifdef WIN32
+ while(sniffBufStart != NULL)
+ {
+ struct sniffBufNode *node = sniffBufStart;
+ sniffBufStart = sniffBufStart->next;
+ free(node);
+ }
+ sniffBufStart = sniffBufEnd = NULL;
+ sniff_request_processed = 1;
+ CloseHandle(handle_to_sniff);
+ CloseHandle(handle_from_sniff);
+ WaitForSingleObject(sniffemacs_handle, 1000L);
+ CloseHandle(sniffemacs_handle);
+ sniffemacs_handle = NULL;
+ WaitForSingleObject(readthread_handle, 1000L);
+ readthread_handle = NULL;
+ CloseHandle(hBufferMutex);
+ hBufferMutex = NULL;
+ SNIFF_TRACE_CLOSE;
+#else
+ close(fd_to_sniff);
+ close(fd_from_sniff);
+ wait(NULL);
+#endif
+ }
+ else
+ {
+#ifdef WIN32
+ _sleep(2);
+ if (!sniff_request_processed)
+ ProcessSniffRequests();
+#else
+ sleep(2); /* Incoming msg could disturb edit */
+#endif
+ sniff_will_disconnect = 1; /* We expect disconnect msg in 2 secs */
+ }
+}
+
+
+/* ConnectToSniffEmacs
+ * Connect to Sniff: returns 1 on error
+ */
+ static int
+ConnectToSniffEmacs()
+{
+#ifdef WIN32 /* Windows Version of the Code */
+ HANDLE ToSniffEmacs[2], FromSniffEmacs[2];
+ SECURITY_ATTRIBUTES sa;
+
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = TRUE;
+
+ if (! CreatePipe(&ToSniffEmacs[0], &ToSniffEmacs[1], &sa, 0))
+ return 1;
+ if (! CreatePipe(&FromSniffEmacs[0], &FromSniffEmacs[1], &sa, 0))
+ return 1;
+
+ sniffemacs_handle = ExecuteDetachedProgram(SniffEmacs[0], SniffEmacs[0],
+ ToSniffEmacs[0], FromSniffEmacs[1]);
+
+ if (sniffemacs_handle)
+ {
+ handle_to_sniff = ToSniffEmacs[1];
+ handle_from_sniff = FromSniffEmacs[0];
+ sniff_connected = 1;
+ hBufferMutex = CreateMutex(
+ NULL, /* no security attributes */
+ FALSE, /* initially not owned */
+ "SniffReadBufferMutex"); /* name of mutex */
+ if (hBufferMutex == NULL)
+ {
+ /* Check for error. */
+ }
+ readthread_handle = (HANDLE)_beginthread(SniffEmacsReadThread, 0, NULL);
+ return 0;
+ }
+ else
+ {
+ /* error in spawn() */
+ return 1;
+ }
+
+#else /* UNIX Version of the Code */
+ int ToSniffEmacs[2], FromSniffEmacs[2];
+
+ pipe(ToSniffEmacs);
+ pipe(FromSniffEmacs);
+
+ /* fork */
+ if ((sniffemacs_pid=fork()) == 0)
+ {
+ /* child */
+
+ /* prepare communication pipes */
+ close(ToSniffEmacs[1]);
+ close(FromSniffEmacs[0]);
+
+ dup2(ToSniffEmacs[0],fileno(stdin)); /* write to ToSniffEmacs[1] */
+ dup2(FromSniffEmacs[1],fileno(stdout));/* read from FromSniffEmacs[0] */
+
+ close(ToSniffEmacs[0]);
+ close(FromSniffEmacs[1]);
+
+ /* start sniffemacs */
+ execvp (SniffEmacs[0], SniffEmacs);
+ {
+/* FILE *out = fdopen(FromSniffEmacs[1], "w"); */
+ sleep(1);
+ fputs(_(msg_sniff_disconnect), stdout);
+ fflush(stdout);
+ sleep(3);
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_exit(1);
+#endif
+ exit(1);
+ }
+ return 1;
+ }
+ else if (sniffemacs_pid > 0)
+ {
+ /* parent process */
+ close(ToSniffEmacs[0]);
+ fd_to_sniff = ToSniffEmacs[1];
+ close(FromSniffEmacs[1]);
+ fd_from_sniff = FromSniffEmacs[0];
+ sniff_connected = 1;
+ return 0;
+ }
+ else /* error in fork() */
+ return 1;
+#endif /* UNIX Version of the Code */
+}
+
+
+/* HandleSniffRequest
+ * Handle one request from SNiFF+
+ */
+ static void
+HandleSniffRequest(buffer)
+ char *buffer;
+{
+ char VICommand[MAX_REQUEST_LEN];
+ char command;
+ char *arguments;
+ char *token;
+ char *argv[3];
+ int argc = 0;
+ buf_T *buf;
+
+ const char *SetTab = "set tabstop=%d";
+ const char *SelectBuf = "buf %s";
+ const char *DeleteBuf = "bd %s";
+ const char *UnloadBuf = "bun %s";
+ const char *GotoLine = "%d";
+
+ command = buffer[0];
+ arguments = &buffer[1];
+ token = strtok(arguments, sniff_rq_sep);
+ while(argc <3)
+ {
+ if (token)
+ {
+ argv[argc] = (char*)vim_strsave((char_u *)token);
+ token = strtok(0, sniff_rq_sep);
+ }
+ else
+ argv[argc] = strdup("");
+ argc++;
+ }
+
+ switch (command)
+ {
+ case 'o' : /* visit file at char pos */
+ case 'O' : /* visit file at line number */
+ {
+ char *file = argv[0];
+ int position = atoi(argv[1]);
+
+ buf = vi_find_buffer(file);
+ setpcmark(); /* insert current pos in jump list [mark.c]*/
+ if (!buf)
+ vi_open_file(file);
+ else if (buf!=curbuf)
+ {
+ sprintf(VICommand, SelectBuf, file);
+ vi_exec_cmd(VICommand);
+ }
+ if (command == 'o')
+ vi_set_cursor_pos((long)position);
+ else
+ {
+ sprintf(VICommand, GotoLine, (int)position);
+ vi_exec_cmd(VICommand);
+ }
+ checkpcmark(); /* [mark.c] */
+#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_W32)
+ if (gui.in_use && !gui.in_focus) /* Raise Vim Window */
+ {
+# ifdef FEAT_GUI_W32
+ SetForegroundWindow(s_hwnd);
+# else
+ extern Widget vimShell;
+
+ XSetInputFocus(gui.dpy, XtWindow(vimShell), RevertToNone,
+ CurrentTime);
+ XRaiseWindow(gui.dpy, XtWindow(vimShell));
+# endif
+ }
+#endif
+ break;
+ }
+ case 'p' : /* path of file has changed */
+ /* when changing from shared to private WS (checkout) */
+ {
+ char *file = argv[0];
+ char *new_path = argv[1];
+
+ buf = vi_find_buffer(file);
+ if (buf && !buf->b_changed) /* delete buffer only if not modified */
+ {
+ sprintf(VICommand, DeleteBuf, file);
+ vi_exec_cmd(VICommand);
+ }
+ vi_open_file(new_path);
+ break;
+ }
+ case 'w' : /* writability has changed */
+ /* Sniff sends request twice,
+ * but only the last one is the right one */
+ {
+ char *file = argv[0];
+ int writable = atoi(argv[1]);
+
+ buf = vi_find_buffer(file);
+ if (buf)
+ {
+ buf->b_p_ro = !writable;
+ if (buf != curbuf)
+ {
+ buf->b_flags |= BF_CHECK_RO + BF_NEVERLOADED;
+ if (writable && !buf->b_changed)
+ {
+ sprintf(VICommand, UnloadBuf, file);
+ vi_exec_cmd(VICommand);
+ }
+ }
+ else if (writable && !buf->b_changed)
+ {
+ vi_exec_cmd("e");
+ }
+ }
+ break;
+ }
+ case 'h' : /* highlight info */
+ break; /* not implemented */
+
+ case 't' : /* Set tab width */
+ {
+ int tab_width = atoi(argv[1]);
+
+ if (tab_width > 0 && tab_width <= 16)
+ {
+ sprintf(VICommand, SetTab, tab_width);
+ vi_exec_cmd(VICommand);
+ }
+ break;
+ }
+ case '|':
+ {
+ /* change the request separator */
+ sniff_rq_sep[0] = arguments[0];
+ /* echo the request */
+ WriteToSniff(buffer);
+ break;
+ }
+ case 'A' : /* Warning/Info msg */
+ vi_msg(arguments);
+ if (!strncmp(arguments, "Disconnected", 12)) /* "Disconnected ..." */
+ sniff_disconnect(1); /* unexpected disconnection */
+ break;
+ case 'a' : /* Error msg */
+ vi_error_msg(arguments);
+ if (!strncmp(arguments, "Cannot connect", 14)) /* "Cannot connect ..." */
+ sniff_disconnect(1);
+ break;
+
+ default :
+ break;
+ }
+ while(argc)
+ vim_free(argv[--argc]);
+}
+
+
+#ifndef WIN32
+/* get_request
+ * read string from fd up to next newline (excluding the nl),
+ * returns length of string
+ * 0 if no data available or no complete line
+ * <0 on error
+ */
+ static int
+get_request(fd, buf, maxlen)
+ int fd;
+ char *buf;
+ int maxlen;
+{
+ static char inbuf[1024];
+ static int pos = 0, bytes = 0;
+ int len;
+#ifdef HAVE_SELECT
+ struct timeval tval;
+ fd_set rfds;
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+ tval.tv_sec = 0;
+ tval.tv_usec = 0;
+#else
+ struct pollfd fds;
+
+ fds.fd = fd;
+ fds.events = POLLIN;
+#endif
+
+ for (len = 0; len < maxlen; len++)
+ {
+ if (pos >= bytes) /* end of buffer reached? */
+ {
+#ifdef HAVE_SELECT
+ if (select(fd + 1, &rfds, NULL, NULL, &tval) > 0)
+#else
+ if (poll(&fds, 1, 0) > 0)
+#endif
+ {
+ pos = 0;
+ bytes = read(fd, inbuf, sizeof(inbuf));
+ if (bytes <= 0)
+ return bytes;
+ }
+ else
+ {
+ pos = pos-len;
+ buf[0] = '\0';
+ return 0;
+ }
+ }
+ if ((buf[len] = inbuf[pos++]) =='\n')
+ break;
+ }
+ buf[len] = '\0';
+ return len;
+}
+#endif /* WIN32 */
+
+
+ static void
+SendRequest(command, symbol)
+ struct sn_cmd *command;
+ char *symbol;
+{
+ int cmd_type = command->cmd_type;
+ static char cmdstr[MAX_REQUEST_LEN];
+ static char msgtxt[MAX_REQUEST_LEN];
+ char *buffer_name = NULL;
+
+ if (cmd_type == RQ_CONNECT)
+ {
+ sniff_connect();
+ return;
+ }
+ if (!sniff_connected && !(cmd_type & SILENT))
+ {
+ vi_error_msg(_("E278: SNiFF+ not connected"));
+ return;
+ }
+
+ if (cmd_type & NEED_FILE)
+ {
+ if (!curbuf->b_sniff)
+ {
+ if (!(cmd_type & SILENT))
+ vi_error_msg(_("E279: Not a SNiFF+ buffer"));
+ return;
+ }
+ buffer_name = vi_buffer_name();
+ if (buffer_name == NULL)
+ return;
+ if (cmd_type & NEED_SYMBOL)
+ {
+ if (cmd_type & EMPTY_SYMBOL)
+ symbol = " ";
+ else if (!symbol && !(symbol = vi_symbol_under_cursor()))
+ return; /* error msg already displayed */
+ }
+
+ if (symbol)
+ sprintf(cmdstr, "%c%s%s%ld%s%s\n",
+ command->cmd_code,
+ buffer_name,
+ sniff_rq_sep,
+ vi_cursor_pos(),
+ sniff_rq_sep,
+ symbol
+ );
+ else
+ sprintf(cmdstr, "%c%s\n", command->cmd_code, buffer_name);
+ }
+ else /* simple request */
+ {
+ cmdstr[0] = command->cmd_code;
+ cmdstr[1] = '\n';
+ cmdstr[2] = '\0';
+ }
+ if (command->cmd_msg && !(cmd_type & SILENT))
+ {
+ if ((cmd_type & NEED_SYMBOL) && !(cmd_type & EMPTY_SYMBOL))
+ {
+ sprintf(msgtxt, "%s: %s", _(command->cmd_msg), symbol);
+ vi_msg(msgtxt);
+ }
+ else
+ vi_msg(_(command->cmd_msg));
+ }
+ WriteToSniff(cmdstr);
+ if (cmd_type & DISCONNECT)
+ sniff_disconnect(0);
+}
+
+
+
+ static void
+WriteToSniff(str)
+ char *str;
+{
+ int bytes;
+#ifdef WIN32
+ if (! WriteFile(handle_to_sniff, str, strlen(str), &bytes, NULL))
+ {
+ DWORD err=GetLastError();
+ bytes = -1;
+ }
+#else
+ bytes = write(fd_to_sniff, str, strlen(str));
+#endif
+ if (bytes<0)
+ {
+ vi_msg(_("Sniff: Error during write. Disconnected"));
+ sniff_disconnect(1);
+ }
+}
+
+/*-------- vim helping functions --------------------------------*/
+
+ static void
+vi_msg(str)
+ char *str;
+{
+ if (str != NULL && *str != NUL)
+ MSG((char_u *)str);
+}
+
+ static void
+vi_error_msg(str)
+ char *str;
+{
+ if (str != NULL && *str != NUL)
+ EMSG((char_u *)str);
+}
+
+ static void
+vi_open_file(fname)
+ char *fname;
+{
+ ++no_wait_return;
+ do_ecmd(0, (char_u *)fname, NULL, NULL, ECMD_ONE, ECMD_HIDE+ECMD_OLDBUF);
+ curbuf->b_sniff = TRUE;
+ --no_wait_return; /* [ex_docmd.c] */
+}
+
+ static buf_T *
+vi_find_buffer(fname)
+ char *fname;
+{ /* derived from buflist_findname() [buffer.c] */
+ buf_T *buf;
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (buf->b_sfname != NULL && fnamecmp(fname, buf->b_sfname) == 0)
+ return (buf);
+ return NULL;
+}
+
+
+ static char *
+vi_symbol_under_cursor()
+{
+ int len;
+ char *symbolp;
+ char *p;
+ static char sniff_symbol[256];
+
+ len = find_ident_under_cursor((char_u **)&symbolp, FIND_IDENT);
+ /* [normal.c] */
+ if (len <= 0)
+ return NULL;
+ for (p=sniff_symbol; len; len--)
+ *p++ = *symbolp++;
+ *p = '\0';
+ return sniff_symbol;
+}
+
+
+ static char *
+vi_buffer_name()
+{
+ return (char *)curbuf->b_sfname;
+}
+
+ static void
+vi_exec_cmd(vicmd)
+ char *vicmd;
+{
+ do_cmdline_cmd((char_u *)vicmd); /* [ex_docmd.c] */
+}
+
+/*
+ * Set cursor on character position
+ * derived from cursor_pos_info() [buffer.c]
+ */
+ static void
+vi_set_cursor_pos(char_pos)
+ long char_pos;
+{
+ linenr_T lnum;
+ long char_count = 1; /* first position = 1 */
+ int line_size;
+ int eol_size;
+
+ if (char_pos == 0)
+ {
+ char_pos = 1;
+ }
+ if (get_fileformat(curbuf) == EOL_DOS)
+ eol_size = 2;
+ else
+ eol_size = 1;
+ for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
+ {
+ line_size = STRLEN(ml_get(lnum)) + eol_size;
+ if (char_count+line_size > char_pos) break;
+ char_count += line_size;
+ }
+ curwin->w_cursor.lnum = lnum;
+ curwin->w_cursor.col = char_pos - char_count;
+}
+
+ static long
+vi_cursor_pos()
+{
+ linenr_T lnum;
+ long char_count=1; /* sniff starts with pos 1 */
+ int line_size;
+ int eol_size;
+
+ if (curbuf->b_p_tx)
+ eol_size = 2;
+ else
+ eol_size = 1;
+ for (lnum = 1; lnum < curwin->w_cursor.lnum; ++lnum)
+ {
+ line_size = STRLEN(ml_get(lnum)) + eol_size;
+ char_count += line_size;
+ }
+ return char_count + curwin->w_cursor.col;
+}
diff --git a/src/if_sniff.h b/src/if_sniff.h
new file mode 100644
index 000000000..901b06a63
--- /dev/null
+++ b/src/if_sniff.h
@@ -0,0 +1,18 @@
+/*
+ * if_sniff.h Interface between Vim and SNiFF+
+ *
+ * $Id$
+ */
+
+#ifndef __if_sniff_h__
+#define __if_sniff_h__
+
+extern int want_sniff_request;
+extern int sniff_request_waiting;
+extern int sniff_connected;
+extern int fd_from_sniff;
+extern void sniff_disconnect __ARGS((int immediately));
+extern void ProcessSniffRequests __ARGS((void));
+extern void ex_sniff __ARGS((exarg_T *eap));
+
+#endif
diff --git a/src/if_tcl.c b/src/if_tcl.c
new file mode 100644
index 000000000..61b1fb9da
--- /dev/null
+++ b/src/if_tcl.c
@@ -0,0 +1,2118 @@
+/* vi:set ts=8 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * Tcl extensions by Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
+ * Last modification: Wed May 10 21:28:44 CEST 2000
+ * Requires Tcl 8.0 or higher.
+ *
+ * Variables:
+ * ::vim::current(buffer) # Name of buffer command for current buffer.
+ * ::vim::current(window) # Name of window command for current window.
+ * ::vim::range(start) # Start of current range (line number).
+ * ::vim::range(end) # End of current range (line number).
+ * ::vim::lbase # Start of line/column numbers (1 or 0).
+ *
+ * Commands:
+ * ::vim::command {cmd} # Execute ex command {cmd}.
+ * ::vim::option {opt} [val] # Get/Set option {opt}.
+ * ::vim::expr {expr} # Evaluate {expr} using vim's evaluator.
+ * ::vim::beep # Guess.
+ *
+ * set buf [::vim::buffer {n}] # Create Tcl command for buffer N.
+ * set bl [::vim::buffer list] # Get list of Tcl commands of all buffers.
+ * ::vim::buffer exists {n} # True if buffer {n} exists.
+ *
+ * set wl [::vim::window list] # Get list of Tcl commands of all windows.
+ *
+ * set n [$win height] # Report window height.
+ * $win height {n} # Set window height to {n}.
+ * array set pos [$win cursor] # Get cursor position.
+ * $win cursor {row} {col} # Set cursor position.
+ * $win cursor pos # Set cursor position from array var "pos"
+ * $win delcmd {cmd} # Register callback command for closed window.
+ * $win option {opt} [val] # Get/Set vim option in context of $win.
+ * $win command {cmd} # Execute ex command in context of $win.
+ * $win expr {expr} # Evaluate vim expression in context of $win.
+ * set buf [$win buffer] # Create Tcl command for window's buffer.
+ *
+ * $buf name # Reports file name in buffer.
+ * $buf number # Reports buffer number.
+ * set l [$buf get {n}] # Get buffer line {n} as a string.
+ * set L [$buf get {n} {m}] # Get lines {n} through {m} as a list.
+ * $buf count # Reports number of lines in buffer.
+ * $buf last # Reports number of last line in buffer.
+ * $buf delete {n} # Delete line {n}.
+ * $buf delete {n} {m} # Delete lines {n} through {m}.
+ * $buf set {n} {l} # Set line {n} to string {l}.
+ * $buf set {n} {m} {L} # Set lines {n} through {m} from list {L}.
+ * # Delete/inserts lines as appropriate.
+ * $buf option {opt} [val] # Get/Set vim option in context of $buf.
+ * $buf command {cmd} # Execute ex command in context of $buf
+ * $buf expr {cmd} # Evaluate vim expression in context of $buf.
+ * array set pos [$buf mark {m}] # Get position of mark.
+ * $buf append {n} {str} # Append string {str} to buffer,after line {n}.
+ * $buf insert {n} {str} # Insert string {str} in buffer as line {n}.
+ * $buf delcmd {cmd} # Register callback command for deleted buffer.
+ * set wl [$buf windows] # Get list of Tcl commands for all windows of
+ * # this buffer.
+TODO:
+ * ::vim::buffer new # create new buffer + Tcl command
+ */
+
+#include "vim.h"
+#undef EXTERN /* tcl.h defines it too */
+
+#ifdef DYNAMIC_TCL
+# define USE_TCL_STUBS /* use tcl's stubs mechanism */
+#endif
+
+#include <tcl.h>
+#include <errno.h>
+#include <string.h>
+
+typedef struct
+{
+ Tcl_Interp *interp;
+ int range_start, range_end;
+ int lbase;
+ char *curbuf, *curwin;
+} tcl_info;
+
+static tcl_info tclinfo = { NULL, 0, 0, 0, NULL, NULL };
+
+#define VAR_RANGE1 "::vim::range(start)"
+#define VAR_RANGE2 "::vim::range(begin)"
+#define VAR_RANGE3 "::vim::range(end)"
+#define VAR_CURBUF "::vim::current(buffer)"
+#define VAR_CURWIN "::vim::current(window)"
+#define VAR_LBASE "::vim::lbase"
+#define VAR_CURLINE "line"
+#define VAR_CURLNUM "lnum"
+#define VARNAME_SIZE 64
+
+#define row2tcl(x) ((x) - (tclinfo.lbase==0))
+#define row2vim(x) ((x) + (tclinfo.lbase==0))
+#define col2tcl(x) ((x) + (tclinfo.lbase!=0))
+#define col2vim(x) ((x) - (tclinfo.lbase!=0))
+
+
+#define VIMOUT ((ClientData)1)
+#define VIMERR ((ClientData)2)
+
+/*
+ * List of Tcl interpreters who reference a vim window or buffer.
+ * Each buffer and window has it's own list in the tcl_ref struct member.
+ * We need this because Tcl can create sub-interpreters with the "interp"
+ * command, and each interpreter can reference all windows and buffers.
+ */
+struct ref
+{
+ struct ref *next;
+
+ Tcl_Interp *interp;
+ Tcl_Command cmd; /* Tcl command that represents this object */
+ Tcl_Obj *delcmd; /* Tcl command to call when object is being del. */
+ void *vimobj; /* Vim window or buffer (win_T* or buf_T*) */
+};
+static char * tclgetbuffer _ANSI_ARGS_((Tcl_Interp *interp, buf_T *buf));
+static char * tclgetwindow _ANSI_ARGS_((Tcl_Interp *interp, win_T *win));
+static int tclsetdelcmd _ANSI_ARGS_((Tcl_Interp *interp, struct ref *reflist, void *vimobj, Tcl_Obj *delcmd));
+static int tclgetlinenum _ANSI_ARGS_ ((Tcl_Interp *interp, Tcl_Obj *obj, int *valueP, buf_T *buf));
+static win_T *tclfindwin _ANSI_ARGS_ ((buf_T *buf));
+static int tcldoexcommand _ANSI_ARGS_ ((Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int objn));
+static int tclsetoption _ANSI_ARGS_ ((Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int objn));
+static int tclvimexpr _ANSI_ARGS_ ((Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int objn));
+static void tcldelthisinterp _ANSI_ARGS_ ((void));
+
+static int vimerror _ANSI_ARGS_((Tcl_Interp *interp));
+static void tclmsg _ANSI_ARGS_((char *text));
+static void tclerrmsg _ANSI_ARGS_((char *text));
+static void tclupdatevars _ANSI_ARGS_((void));
+
+static struct ref refsdeleted; /* dummy object for deleted ref list */
+
+/*****************************************************************************
+ * TCL interface manager
+ ****************************************************************************/
+
+#if defined(DYNAMIC_TCL) || defined(PROTO)
+# ifndef DYNAMIC_TCL_DLL
+# define DYNAMIC_TCL_DLL "tcl83.dll"
+# endif
+# ifndef DYNAMIC_TCL_VER
+# define DYNAMIC_TCL_VER "8.3"
+# endif
+
+# ifndef DYNAMIC_TCL /* Just generating prototypes */
+typedef int HANDLE;
+# endif
+
+/*
+ * Declare HANDLE for perl.dll and function pointers.
+ */
+static HANDLE hTclLib = NULL;
+Tcl_Interp* (*dll_Tcl_CreateInterp)();
+
+/*
+ * Table of name to function pointer of tcl.
+ */
+#define TCL_PROC FARPROC
+static struct {
+ char* name;
+ TCL_PROC* ptr;
+} tcl_funcname_table[] = {
+ {"Tcl_CreateInterp", (TCL_PROC*)&dll_Tcl_CreateInterp},
+ {NULL, NULL},
+};
+
+/*
+ * Make all runtime-links of tcl.
+ *
+ * 1. Get module handle using LoadLibraryEx.
+ * 2. Get pointer to perl function by GetProcAddress.
+ * 3. Repeat 2, until get all functions will be used.
+ *
+ * Parameter 'libname' provides name of DLL.
+ * Return OK or FAIL.
+ */
+ static int
+tcl_runtime_link_init(char *libname, int verbose)
+{
+ int i;
+
+ if (hTclLib)
+ return OK;
+ if (!(hTclLib = LoadLibraryEx(libname, NULL, 0)))
+ {
+ if (verbose)
+ EMSG2(_(e_loadlib), libname);
+ return FAIL;
+ }
+ for (i = 0; tcl_funcname_table[i].ptr; ++i)
+ {
+ if (!(*tcl_funcname_table[i].ptr = GetProcAddress(hTclLib,
+ tcl_funcname_table[i].name)))
+ {
+ FreeLibrary(hTclLib);
+ hTclLib = NULL;
+ if (verbose)
+ EMSG2(_(e_loadfunc), tcl_funcname_table[i].name);
+ return FAIL;
+ }
+ }
+ return OK;
+}
+#endif /* defined(DYNAMIC_TCL) || defined(PROTO) */
+
+#ifdef DYNAMIC_TCL
+static char *find_executable_arg = NULL;
+#endif
+
+ void
+vim_tcl_init(arg)
+ char *arg;
+{
+#ifndef DYNAMIC_TCL
+ Tcl_FindExecutable(arg);
+#else
+ find_executable_arg = arg;
+#endif
+}
+
+#if defined(DYNAMIC_TCL) || defined(PROTO)
+
+static int stubs_initialized = FALSE;
+
+/*
+ * Return TRUE if the TCL interface can be used.
+ */
+ int
+tcl_enabled(verbose)
+ int verbose;
+{
+ if (!stubs_initialized && find_executable_arg != NULL
+ && tcl_runtime_link_init(DYNAMIC_TCL_DLL, verbose) == OK)
+ {
+ Tcl_Interp *interp;
+
+ if (interp = dll_Tcl_CreateInterp())
+ {
+ if (Tcl_InitStubs(interp, DYNAMIC_TCL_VER, 0))
+ {
+ Tcl_FindExecutable(find_executable_arg);
+ Tcl_DeleteInterp(interp);
+ stubs_initialized = TRUE;
+ }
+ /* FIXME: When Tcl_InitStubs() was failed, how delete interp? */
+ }
+ }
+ return stubs_initialized;
+}
+#endif
+
+ void
+tcl_end()
+{
+#ifdef DYNAMIC_TCL
+ if (hTclLib)
+ {
+ FreeLibrary(hTclLib);
+ hTclLib = NULL;
+ }
+#endif
+}
+
+/****************************************************************************
+ Tcl commands
+ ****************************************************************************/
+
+/*
+ * Replace standard "exit" and "catch" commands.
+ *
+ * This is a design flaw in Tcl - the standard "exit" command just calls
+ * exit() and kills the application. It should return TCL_EXIT to the
+ * app, which then decides if it wants to terminate or not. In our case,
+ * we just delete the Tcl interpreter (and create a new one with the next
+ * :tcl command).
+ */
+#define TCL_EXIT 5
+
+/* ARGSUSED */
+ static int
+exitcmd(dummy, interp, objc, objv)
+ ClientData dummy;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+{
+ int value = 0;
+
+ switch (objc)
+ {
+ case 2:
+ if (Tcl_GetIntFromObj(interp, objv[1], &value) != TCL_OK)
+ break;
+ /* FALLTHROUGH */
+ case 1:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(value));
+ return TCL_EXIT;
+ default:
+ Tcl_WrongNumArgs(interp, 1, objv, "?returnCode?");
+ }
+ return TCL_ERROR;
+}
+
+/* ARGSUSED */
+ static int
+catchcmd(dummy, interp, objc, objv)
+ ClientData dummy;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+{
+ char *varname = NULL;
+ int result;
+
+ switch (objc)
+ {
+ case 3:
+ varname = Tcl_GetStringFromObj(objv[2], NULL);
+ /* fallthrough */
+ case 2:
+ Tcl_ResetResult(interp);
+ Tcl_AllowExceptions(interp);
+ result = Tcl_EvalObj(interp, objv[1]);
+ if (result == TCL_EXIT)
+ return result;
+ if (varname)
+ {
+ if (Tcl_SetVar(interp, varname, Tcl_GetStringResult(interp), 0) == NULL)
+ {
+ Tcl_SetResult(interp, "couldn't save command result in variable", TCL_STATIC);
+ return TCL_ERROR;
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
+ return TCL_OK;
+ default:
+ Tcl_WrongNumArgs(interp, 1, objv, "command ?varName?");
+ }
+ return TCL_ERROR;
+}
+
+/*
+ * "::vim::beep" - what Vi[m] does best :-)
+ */
+/* ARGSUSED */
+ static int
+beepcmd(dummy, interp, objc, objv)
+ ClientData dummy;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+{
+ if (objc != 1)
+ {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
+ }
+ vim_beep();
+ return TCL_OK;
+}
+
+/*
+ * "::vim::buffer list" - create a list of buffer commands.
+ * "::vim::bufffer {N}" - create buffer command for buffer N.
+ * "::vim::buffer new" - create a new buffer (not implemented)
+ */
+/* ARGSUSED */
+ static int
+buffercmd(dummy, interp, objc, objv)
+ ClientData dummy;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+{
+ char *name;
+ buf_T *buf;
+ Tcl_Obj *resobj;
+ int err, n, idx;
+
+ enum {BCMD_EXISTS, BCMD_LIST};
+ static char *bcmdoptions[] =
+ {
+ "exists", "list", (char *)0
+ };
+
+ if (objc < 2)
+ {
+ Tcl_WrongNumArgs(interp, 1, objv, "option");
+ return TCL_ERROR;
+ }
+ err = Tcl_GetIntFromObj(interp, objv[1], &n);
+ if (err == TCL_OK)
+ {
+ if (objc != 2)
+ {
+ Tcl_WrongNumArgs(interp, 1, objv, "bufNumber");
+ return TCL_ERROR;
+ }
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ if (buf->b_fnum == n)
+ {
+ name = tclgetbuffer(interp, buf);
+ if (name == NULL)
+ return TCL_ERROR;
+ Tcl_SetResult(interp, name, TCL_VOLATILE);
+ return TCL_OK;
+ }
+ }
+ Tcl_SetResult(interp, _("invalid buffer number"), TCL_STATIC);
+ return TCL_ERROR;
+ }
+ Tcl_ResetResult(interp); /* clear error from Tcl_GetIntFromObj */
+
+ err = Tcl_GetIndexFromObj(interp, objv[1], bcmdoptions, "option", 0, &idx);
+ if (err != TCL_OK)
+ return err;
+ switch (idx)
+ {
+ case BCMD_LIST:
+ if (objc != 2)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, "");
+ err = TCL_ERROR;
+ break;
+ }
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ name = tclgetbuffer(interp, buf);
+ if (name == NULL)
+ {
+ err = TCL_ERROR;
+ break;
+ }
+ Tcl_AppendElement(interp, name);
+ }
+ break;
+
+ case BCMD_EXISTS:
+ if (objc != 3)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, "bufNumber");
+ err = TCL_ERROR;
+ break;
+ }
+ err = Tcl_GetIntFromObj(interp, objv[2], &n);
+ if (err == TCL_OK)
+ {
+ buf = buflist_findnr(n);
+ resobj = Tcl_NewIntObj(buf != NULL);
+ Tcl_SetObjResult(interp, resobj);
+ }
+ break;
+
+ default:
+ Tcl_SetResult(interp, _("not implemented yet"), TCL_STATIC);
+ err = TCL_ERROR;
+ }
+ return err;
+}
+
+/*
+ * "::vim::window list" - create list of window commands.
+ */
+/* ARGSUSED */
+ static int
+windowcmd(dummy, interp, objc, objv)
+ ClientData dummy;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+{
+ char *what, *string;
+ win_T *win;
+
+ if (objc != 2)
+ {
+ Tcl_WrongNumArgs(interp, 1, objv, "option");
+ return TCL_ERROR;
+ }
+ what = Tcl_GetStringFromObj(objv[1], NULL);
+ if (strcmp(what, "list") == 0)
+ {
+ FOR_ALL_WINDOWS(win)
+ {
+ string = tclgetwindow(interp, win);
+ if (string == NULL)
+ return TCL_ERROR;
+ Tcl_AppendElement(interp, string);
+ }
+ return TCL_OK;
+ }
+ Tcl_SetResult(interp, _("unknown option"), TCL_STATIC);
+ return TCL_ERROR;
+}
+
+/*
+ * flags for bufselfcmd and winselfcmd to indicate outstanding actions.
+ */
+#define FL_UPDATE_SCREEN (1<<0)
+#define FL_UPDATE_CURBUF (1<<1)
+#define FL_ADJUST_CURSOR (1<<2)
+
+/*
+ * This function implements the buffer commands.
+ */
+ static int
+bufselfcmd(ref, interp, objc, objv)
+ ClientData ref;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+{
+ int opt, err, idx, flags;
+ int val1, val2, n, i;
+ buf_T *buf, *savebuf;
+ win_T *win, *savewin;
+ Tcl_Obj *resobj;
+ pos_T *pos;
+ char *line;
+
+ enum
+ {
+ BUF_APPEND, BUF_COMMAND, BUF_COUNT, BUF_DELCMD, BUF_DELETE, BUF_EXPR,
+ BUF_GET, BUF_INSERT, BUF_LAST, BUF_MARK, BUF_NAME, BUF_NUMBER,
+ BUF_OPTION, BUF_SET, BUF_WINDOWS
+ };
+ static char *bufoptions[] =
+ {
+ "append", "command", "count", "delcmd", "delete", "expr",
+ "get", "insert", "last", "mark", "name", "number",
+ "option", "set", "windows", (char *)0
+ };
+
+ if (objc < 2)
+ {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ err = Tcl_GetIndexFromObj(interp, objv[1], bufoptions, "option", 0, &idx);
+ if (err != TCL_OK)
+ return err;
+
+ buf = (buf_T *)((struct ref *)ref)->vimobj;
+ savebuf = curbuf; curbuf = buf;
+ savewin = curwin; curwin = tclfindwin(buf);
+ flags = 0;
+ opt = 0;
+
+ switch (idx)
+ {
+ case BUF_COMMAND:
+ err = tcldoexcommand(interp, objc, objv, 2);
+ flags |= FL_UPDATE_SCREEN;
+ break;
+
+ case BUF_OPTION:
+ err = tclsetoption(interp, objc, objv, 2);
+ flags |= FL_UPDATE_SCREEN;
+ break;
+
+ case BUF_EXPR:
+ err = tclvimexpr(interp, objc, objv, 2);
+ break;
+
+ case BUF_NAME:
+ /*
+ * Get filename of buffer.
+ */
+ if (objc != 2)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ err = TCL_ERROR;
+ break;
+ }
+ if (buf->b_ffname)
+ Tcl_SetResult(interp, (char *)buf->b_ffname, TCL_VOLATILE);
+ else
+ Tcl_SetResult(interp, "", TCL_STATIC);
+ break;
+
+ case BUF_LAST:
+ /*
+ * Get line number of last line.
+ */
+ opt = 1;
+ /* fallthrough */
+ case BUF_COUNT:
+ /*
+ * Get number of lines in buffer.
+ */
+ if (objc != 2)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ err = TCL_ERROR;
+ break;
+ }
+ val1 = (int)buf->b_ml.ml_line_count;
+ if (opt)
+ val1 = row2tcl(val1);
+
+ resobj = Tcl_NewIntObj(val1);
+ Tcl_SetObjResult(interp, resobj);
+ break;
+
+ case BUF_NUMBER:
+ /*
+ * Get buffer's number.
+ */
+ if (objc != 2)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ err = TCL_ERROR;
+ break;
+ }
+ resobj = Tcl_NewIntObj((int)buf->b_fnum);
+ Tcl_SetObjResult(interp, resobj);
+ break;
+
+ case BUF_GET:
+ if (objc != 3 && objc != 4)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, "lineNumber ?lineNumber?");
+ err = TCL_ERROR;
+ break;
+ }
+ err = tclgetlinenum(interp, objv[2], &val1, buf);
+ if (err != TCL_OK)
+ break;
+ if (objc == 4)
+ {
+ err = tclgetlinenum(interp, objv[3], &val2, buf);
+ if (err != TCL_OK)
+ break;
+ if (val1 > val2)
+ {
+ n = val1; val1 = val2; val2 = n;
+ }
+ Tcl_ResetResult(interp);
+
+ for (n = val1; n <= val2 && err == TCL_OK; n++)
+ {
+ line = (char *)ml_get_buf(buf, (linenr_T)n, FALSE);
+ if (line)
+ Tcl_AppendElement(interp, line);
+ else
+ err = TCL_ERROR;
+ }
+ }
+ else { /* objc == 3 */
+ line = (char *)ml_get_buf(buf, (linenr_T)val1, FALSE);
+ Tcl_SetResult(interp, line, TCL_VOLATILE);
+ }
+ break;
+
+ case BUF_SET:
+ if (objc != 4 && objc != 5)
+ {
+ Tcl_WrongNumArgs(interp, 3, objv, "lineNumber ?lineNumber? stringOrList");
+ err = TCL_ERROR;
+ break;
+ }
+ err = tclgetlinenum(interp, objv[2], &val1, buf);
+ if (err != TCL_OK)
+ return TCL_ERROR;
+ if (objc == 4)
+ {
+ /*
+ * Replace one line with a string.
+ * $buf set {n} {string}
+ */
+ line = Tcl_GetStringFromObj(objv[3], NULL);
+ if (u_savesub((linenr_T)val1) != OK)
+ {
+ Tcl_SetResult(interp, _("cannot save undo information"), TCL_STATIC);
+ err = TCL_ERROR;
+ }
+ else
+ if (ml_replace((linenr_T)val1, (char_u *)line, TRUE) != OK)
+ {
+ Tcl_SetResult(interp, _("cannot replace line"), TCL_STATIC);
+ err = TCL_ERROR;
+ }
+ else
+ {
+ changed_bytes((linenr_T)val1, 0);
+ flags |= FL_UPDATE_CURBUF;
+ }
+ break;
+ }
+ else
+ {
+ /*
+ * Replace several lines with the elements of a Tcl list.
+ * $buf set {n} {m} {list}
+ * If the list contains more than {m}-{n}+1 elements, they
+ * are * inserted after line {m}. If the list contains fewer
+ * elements, * the lines from {n}+length({list}) through {m}
+ * are deleted.
+ */
+ int lc;
+ Tcl_Obj **lv;
+
+ err = tclgetlinenum(interp, objv[3], &val2, buf);
+ if (err != TCL_OK)
+ break;
+ err = Tcl_ListObjGetElements(interp, objv[4], &lc, &lv);
+ if (err != TCL_OK)
+ break;
+ if (val1 > val2)
+ {
+ n = val1;
+ val1 = val2;
+ val2 = n;
+ }
+
+ n = val1;
+ if (u_save((linenr_T)(val1 - 1), (linenr_T)(val2 + 1)) != OK)
+ {
+ Tcl_SetResult(interp, _("cannot save undo information"),
+ TCL_STATIC);
+ err = TCL_ERROR;
+ break;
+ }
+ flags |= FL_UPDATE_CURBUF;
+
+ for (i = 0; i < lc && n <= val2; i++)
+ {
+ line = Tcl_GetStringFromObj(lv[i], NULL);
+ if (ml_replace((linenr_T)n, (char_u *)line, TRUE) != OK)
+ goto setListError;
+ ++n;
+ }
+ if (i < lc)
+ {
+ /* append lines */
+ do
+ {
+ line = Tcl_GetStringFromObj(lv[i], NULL);
+ if (ml_append((linenr_T)(n - 1),
+ (char_u *)line, 0, FALSE) != OK)
+ goto setListError;
+ ++n;
+ ++i;
+ } while (i < lc);
+ }
+ else if (n <= val2)
+ {
+ /* did not replace all lines, delete */
+ i = n;
+ do
+ {
+ if (ml_delete((linenr_T)i, FALSE) != OK)
+ goto setListError;
+ ++n;
+ } while (n <= val2);
+ }
+ lc -= val2 - val1 + 1; /* number of lines to be replaced */
+ mark_adjust((linenr_T)val1, (linenr_T)val2, (long)MAXLNUM,
+ (long)lc);
+ changed_lines((linenr_T)val1, 0, (linenr_T)val2 + 1, (long)lc);
+ break;
+ setListError:
+ u_undo(1); /* ??? */
+ Tcl_SetResult(interp, _("cannot set line(s)"), TCL_STATIC);
+ err = TCL_ERROR;
+ }
+ break;
+
+ case BUF_DELETE:
+ if (objc != 3 && objc != 4)
+ {
+ Tcl_WrongNumArgs(interp, 3, objv, "lineNumber ?lineNumber?");
+ err = TCL_ERROR;
+ break;
+ }
+ err = tclgetlinenum(interp, objv[2], &val1, buf);
+ if (err != TCL_OK)
+ break;
+ val2 = val1;
+ if (objc == 4)
+ {
+ err = tclgetlinenum(interp, objv[3], &val2, buf);
+ if (err != TCL_OK)
+ return err;
+ if (val1 > val2)
+ {
+ i = val1; val1 = val2; val2 = i;
+ }
+ }
+ n = val2 - val1 + 1;
+ if (u_savedel((linenr_T)val1, (long)n) != OK)
+ {
+ Tcl_SetResult(interp, _("cannot save undo information"),
+ TCL_STATIC);
+ err = TCL_ERROR;
+ break;
+ }
+ for (i = 0; i < n; i++)
+ {
+ ml_delete((linenr_T)val1, FALSE);
+ err = vimerror(interp);
+ if (err != TCL_OK)
+ break;
+ }
+ if (i > 0)
+ deleted_lines_mark((linenr_T)val1, (long)i);
+ flags |= FL_ADJUST_CURSOR|FL_UPDATE_SCREEN;
+ break;
+
+ case BUF_MARK:
+ if (objc != 3)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, "markName");
+ err = TCL_ERROR;
+ break;
+ }
+ line = Tcl_GetStringFromObj(objv[2], NULL);
+
+ pos = NULL;
+ if (line[0] != '\0' && line[1] == '\0')
+ {
+ pos = getmark(line[0], FALSE);
+ }
+ if (pos == NULL)
+ {
+ Tcl_SetResult(interp, _("invalid mark name"), TCL_STATIC);
+ err = TCL_ERROR;
+ break;
+ }
+ err = vimerror(interp);
+ if (err != TCL_OK)
+ break;
+ if (pos->lnum <= 0)
+ {
+ Tcl_SetResult(interp, _("mark not set"), TCL_STATIC);
+ err = TCL_ERROR;
+ }
+ else
+ {
+ char rbuf[64];
+ sprintf(rbuf, _("row %d column %d"), (int)row2tcl(pos->lnum), (int)col2tcl(pos->col));
+ Tcl_SetResult(interp, rbuf, TCL_VOLATILE);
+ }
+ break;
+
+ case BUF_INSERT:
+ opt = 1;
+ /* fallthrough */
+ case BUF_APPEND:
+ if (objc != 4)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, "lineNum text");
+ err = TCL_ERROR;
+ break;
+ }
+ err = tclgetlinenum(interp, objv[2], &val1, buf);
+ if (err != TCL_OK)
+ break;
+ if (opt)
+ --val1;
+ if (u_save((linenr_T)val1, (linenr_T)(val1+1)) != OK)
+ {
+ Tcl_SetResult(interp, _("cannot save undo information"), TCL_STATIC);
+ err = TCL_ERROR;
+ break;
+ }
+
+ line = Tcl_GetStringFromObj(objv[3], NULL);
+ if (ml_append((linenr_T)val1, (char_u *)line, 0, FALSE) != OK)
+ {
+ Tcl_SetResult(interp, _("cannot insert/append line"), TCL_STATIC);
+ err = TCL_ERROR;
+ break;
+ }
+ appended_lines_mark((linenr_T)val1, 1L);
+ flags |= FL_UPDATE_SCREEN;
+ break;
+
+ case BUF_WINDOWS:
+ /*
+ * Return list of window commands.
+ */
+ if (objc != 2)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ err = TCL_ERROR;
+ break;
+ }
+ Tcl_ResetResult(interp);
+ FOR_ALL_WINDOWS(win)
+ {
+ if (win->w_buffer == buf)
+ {
+ line = tclgetwindow(interp, win);
+ if (line != NULL)
+ Tcl_AppendElement(interp, line);
+ else
+ {
+ err = TCL_ERROR;
+ break;
+ }
+ }
+ }
+ break;
+
+ case BUF_DELCMD:
+ /*
+ * Register deletion callback.
+ * TODO: Should be able to register multiple callbacks
+ */
+ if (objc != 3)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, "command");
+ err = TCL_ERROR;
+ break;
+ }
+ err = tclsetdelcmd(interp, buf->tcl_ref, (void *)buf, objv[2]);
+ break;
+
+ default:
+ Tcl_SetResult(interp, _("not implemented yet"), TCL_STATIC);
+ err = TCL_ERROR;
+ }
+
+ if (flags & FL_UPDATE_CURBUF)
+ redraw_curbuf_later(NOT_VALID);
+ curbuf = savebuf;
+ curwin = savewin;
+ if (flags & FL_ADJUST_CURSOR)
+ check_cursor();
+ if (flags & (FL_UPDATE_SCREEN | FL_UPDATE_CURBUF))
+ update_screen(NOT_VALID);
+
+ return err;
+}
+
+/*
+ * This function implements the window commands.
+ */
+ static int
+winselfcmd(ref, interp, objc, objv)
+ ClientData ref;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+{
+ int err, idx, flags;
+ int val1, val2;
+ Tcl_Obj *resobj;
+ win_T *savewin, *win;
+ buf_T *savebuf;
+ char *str;
+
+ enum
+ {
+ WIN_BUFFER, WIN_COMMAND, WIN_CURSOR, WIN_DELCMD, WIN_EXPR,
+ WIN_HEIGHT, WIN_OPTION
+ };
+ static char *winoptions[] =
+ {
+ "buffer", "command", "cursor", "delcmd", "expr",
+ "height", "option", (char *)0
+ };
+
+ if (objc < 2)
+ {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ err = Tcl_GetIndexFromObj(interp, objv[1], winoptions, "option", 0, &idx);
+ if (err != TCL_OK)
+ return TCL_ERROR;
+
+ win = (win_T *)((struct ref *)ref)->vimobj;
+ savewin = curwin; curwin = win;
+ savebuf = curbuf; curbuf = win->w_buffer;
+ flags = 0;
+
+ switch (idx)
+ {
+ case WIN_OPTION:
+ err = tclsetoption(interp, objc, objv, 2);
+ flags |= FL_UPDATE_SCREEN;
+ break;
+
+ case WIN_COMMAND:
+ err = tcldoexcommand(interp, objc, objv, 2);
+ flags |= FL_UPDATE_SCREEN;
+ break;
+
+ case WIN_EXPR:
+ err = tclvimexpr(interp, objc, objv, 2);
+ break;
+
+ case WIN_HEIGHT:
+ if (objc == 3)
+ {
+ err = Tcl_GetIntFromObj(interp, objv[2], &val1);
+ if (err != TCL_OK)
+ break;
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ win_setheight(val1);
+ err = vimerror(interp);
+ if (err != TCL_OK)
+ break;
+ }
+ else
+ if (objc != 2)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, "?value?");
+ err = TCL_ERROR;
+ break;
+ }
+
+ resobj = Tcl_NewIntObj((int)(win->w_height));
+ Tcl_SetObjResult(interp, resobj);
+ break;
+
+ case WIN_BUFFER:
+ if (objc != 2)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ err = TCL_ERROR;
+ break;
+ }
+ str = tclgetbuffer(interp, win->w_buffer);
+ if (str)
+ Tcl_SetResult(interp, str, TCL_VOLATILE);
+ else
+ err = TCL_ERROR;
+ break;
+
+ case WIN_DELCMD:
+ if (objc != 3)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, "command");
+ err = TCL_ERROR;
+ break;
+ }
+ err = tclsetdelcmd(interp, win->tcl_ref, (void *)win, objv[2]);
+ break;
+
+ case WIN_CURSOR:
+ if (objc > 4)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, "?arg1 ?arg2??");
+ err = TCL_ERROR;
+ break;
+ }
+ if (objc == 2)
+ {
+ char buf[64];
+ sprintf(buf, _("row %d column %d"), (int)row2tcl(win->w_cursor.lnum), (int)col2tcl(win->w_cursor.col));
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ break;
+ }
+ else if (objc == 3)
+ {
+ Tcl_Obj *part, *var;
+
+ part = Tcl_NewStringObj("row", -1);
+ var = Tcl_ObjGetVar2(interp, objv[2], part, TCL_LEAVE_ERR_MSG);
+ if (var == NULL)
+ {
+ err = TCL_ERROR;
+ break;
+ }
+ err = tclgetlinenum(interp, var, &val1, win->w_buffer);
+ if (err != TCL_OK)
+ break;
+ part = Tcl_NewStringObj("column", -1);
+ var = Tcl_ObjGetVar2(interp, objv[2], part, TCL_LEAVE_ERR_MSG);
+ if (var == NULL)
+ {
+ err = TCL_ERROR;
+ break;
+ }
+ err = Tcl_GetIntFromObj(interp, var, &val2);
+ if (err != TCL_OK)
+ break;
+ }
+ else { /* objc == 4 */
+ err = tclgetlinenum(interp, objv[2], &val1, win->w_buffer);
+ if (err != TCL_OK)
+ break;
+ err = Tcl_GetIntFromObj(interp, objv[3], &val2);
+ if (err != TCL_OK)
+ break;
+ }
+ /* TODO: should check column */
+ win->w_cursor.lnum = val1;
+ win->w_cursor.col = col2vim(val2);
+ flags |= FL_UPDATE_SCREEN;
+ break;
+
+ default:
+ Tcl_SetResult(interp, _("not implemented yet"), TCL_STATIC);
+ break;
+ }
+
+ curwin = savewin;
+ curbuf = savebuf;
+ if (flags & FL_UPDATE_SCREEN)
+ update_screen(NOT_VALID);
+
+ return err;
+}
+
+
+/* ARGSUSED */
+ static int
+commandcmd(dummy, interp, objc, objv)
+ ClientData dummy;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+{
+ int err;
+
+ err = tcldoexcommand(interp, objc, objv, 1);
+ update_screen(VALID);
+ return err;
+}
+
+/* ARGSUSED */
+ static int
+optioncmd(dummy, interp, objc, objv)
+ ClientData dummy;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+{
+ int err;
+
+ err = tclsetoption(interp, objc, objv, 1);
+ update_screen(VALID);
+ return err;
+}
+
+/* ARGSUSED */
+ static int
+exprcmd(dummy, interp, objc, objv)
+ ClientData dummy;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+{
+ return tclvimexpr(interp, objc, objv, 1);
+}
+
+/****************************************************************************
+ Support functions for Tcl commands
+ ****************************************************************************/
+
+/*
+ * Get a line number from 'obj' and convert it to vim's range.
+ */
+ static int
+tclgetlinenum(interp, obj, valueP, buf)
+ Tcl_Interp *interp;
+ Tcl_Obj *obj;
+ int *valueP;
+ buf_T *buf;
+{
+ int err, i;
+
+ enum { LN_BEGIN, LN_BOTTOM, LN_END, LN_FIRST, LN_LAST, LN_START, LN_TOP };
+
+ static char *keyw[] =
+ {
+ "begin", "bottom", "end", "first", "last", "start", "top", (char *)0
+ };
+
+ err = Tcl_GetIndexFromObj(interp, obj, keyw, "", 0, &i);
+ if (err == TCL_OK)
+ {
+ switch (i)
+ {
+ case LN_BEGIN:
+ case LN_FIRST:
+ case LN_START:
+ case LN_TOP:
+ *valueP = 1;
+ break;
+ case LN_BOTTOM:
+ case LN_END:
+ case LN_LAST:
+ *valueP = buf->b_ml.ml_line_count;
+ break;
+ }
+ return TCL_OK;
+ }
+ Tcl_ResetResult(interp);
+
+ err = Tcl_GetIntFromObj(interp, obj, &i);
+ if (err != TCL_OK)
+ return err;
+ i = row2vim(i);
+ if (i < 1 || i > buf->b_ml.ml_line_count)
+ {
+ Tcl_SetResult(interp, _("line number out of range"), TCL_STATIC);
+ return TCL_ERROR;
+ }
+ *valueP = i;
+ return TCL_OK;
+}
+
+/*
+ * Find the first window in the window list that displays the buffer.
+ */
+ static win_T *
+tclfindwin(buf)
+ buf_T *buf;
+{
+ win_T *win;
+
+ FOR_ALL_WINDOWS(win)
+ {
+ if (win->w_buffer == buf)
+ return win;
+ }
+ return curwin; /* keep current window context */
+}
+
+/*
+ * Do-it-all function for "::vim::command", "$buf command" and "$win command".
+ */
+ static int
+tcldoexcommand(interp, objc, objv, objn)
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+ int objn;
+{
+ tcl_info saveinfo;
+ int err, flag, nobjs;
+ char *arg;
+
+ nobjs = objc - objn;
+ if (nobjs < 1 || nobjs > 2)
+ {
+ Tcl_WrongNumArgs(interp, objn, objv, "?-quiet? exCommand");
+ return TCL_ERROR;
+ }
+
+ flag = 0;
+ if (nobjs == 2)
+ {
+ arg = Tcl_GetStringFromObj(objv[objn], NULL);
+ if (strcmp(arg, "-quiet") == 0)
+ flag = 1;
+ else
+ {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, _("unknown flag: "), arg, (char *)0);
+ return TCL_ERROR;
+ }
+ ++objn;
+ }
+
+ memcpy(&saveinfo, &tclinfo, sizeof(tcl_info));
+ tclinfo.interp = NULL;
+ tclinfo.curwin = NULL;
+ tclinfo.curbuf = NULL;
+
+ arg = Tcl_GetStringFromObj(objv[objn], NULL);
+ if (flag)
+ ++emsg_off;
+ do_cmdline_cmd((char_u *)arg);
+ if (flag)
+ --emsg_off;
+ err = vimerror(interp);
+
+ /* If the ex command created a new Tcl interpreter, remove it */
+ if (tclinfo.interp)
+ tcldelthisinterp();
+ memcpy(&tclinfo, &saveinfo, sizeof(tcl_info));
+ tclupdatevars();
+
+ return err;
+}
+
+/*
+ * Do-it-all function for "::vim::option", "$buf option" and "$win option".
+ */
+ static int
+tclsetoption(interp, objc, objv, objn)
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+ int objn;
+{
+ int err, nobjs, idx;
+ char_u *option;
+ int isnum;
+ long lval;
+ char_u *sval;
+ Tcl_Obj *resobj;
+
+ enum { OPT_OFF, OPT_ON, OPT_TOGGLE };
+ static char *optkw[] = { "off", "on", "toggle", (char *)0 };
+
+ nobjs = objc - objn;
+ if (nobjs != 1 && nobjs != 2)
+ {
+ Tcl_WrongNumArgs(interp, objn, objv, "vimOption ?value?");
+ return TCL_ERROR;
+ }
+
+ option = (char_u *)Tcl_GetStringFromObj(objv[objn], NULL);
+ ++objn;
+ isnum = get_option_value(option, &lval, &sval, 0);
+ err = TCL_OK;
+ switch (isnum)
+ {
+ case 0:
+ Tcl_SetResult(interp, (char *)sval, TCL_VOLATILE);
+ vim_free(sval);
+ break;
+ case 1:
+ resobj = Tcl_NewLongObj(lval);
+ Tcl_SetObjResult(interp, resobj);
+ break;
+ default:
+ Tcl_SetResult(interp, _("unknown vimOption"), TCL_STATIC);
+ return TCL_ERROR;
+ }
+ if (nobjs == 2)
+ {
+ if (isnum)
+ {
+ sval = NULL; /* avoid compiler warning */
+ err = Tcl_GetIndexFromObj(interp, objv[objn], optkw, "", 0, &idx);
+ if (err != TCL_OK)
+ {
+ Tcl_ResetResult(interp);
+ err = Tcl_GetLongFromObj(interp, objv[objn], &lval);
+ }
+ else
+ switch (idx)
+ {
+ case OPT_ON:
+ lval = 1;
+ break;
+ case OPT_OFF:
+ lval = 0;
+ break;
+ case OPT_TOGGLE:
+ lval = !lval;
+ break;
+ }
+ }
+ else
+ sval = (char_u *)Tcl_GetStringFromObj(objv[objn], NULL);
+ if (err == TCL_OK)
+ {
+ set_option_value(option, lval, sval, OPT_LOCAL);
+ err = vimerror(interp);
+ }
+ }
+ return err;
+}
+
+/*
+ * Do-it-all function for "::vim::expr", "$buf expr" and "$win expr".
+ */
+ static int
+tclvimexpr(interp, objc, objv, objn)
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj *CONST objv[];
+ int objn;
+{
+#ifdef FEAT_EVAL
+ char *expr, *str;
+#endif
+ int err;
+
+ if (objc - objn != 1)
+ {
+ Tcl_WrongNumArgs(interp, objn, objv, "vimExpr");
+ return TCL_ERROR;
+ }
+
+#ifdef FEAT_EVAL
+ expr = Tcl_GetStringFromObj(objv[objn], NULL);
+ str = (char *)eval_to_string((char_u *)expr, NULL);
+ if (str == NULL)
+ Tcl_SetResult(interp, _("invalid expression"), TCL_STATIC);
+ else
+ Tcl_SetResult(interp, str, TCL_VOLATILE);
+ err = vimerror(interp);
+#else
+ Tcl_SetResult(interp, _("expressions disabled at compile time"), TCL_STATIC);
+ err = TCL_ERROR;
+#endif
+
+ return err;
+}
+
+/*
+ * Check for internal vim errors.
+ */
+ static int
+vimerror(interp)
+ Tcl_Interp *interp;
+{
+ if (got_int)
+ {
+ Tcl_SetResult(interp, _("keyboard interrupt"), TCL_STATIC);
+ return TCL_ERROR;
+ }
+ else if (did_emsg)
+ {
+ Tcl_SetResult(interp, _("vim error"), TCL_STATIC);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ * Functions that handle the reference lists:
+ * delref() - callback for Tcl's DeleteCommand
+ * tclgetref() - find/create Tcl command for a win_T* or buf_T* object
+ * tclgetwindow() - window frontend for tclgetref()
+ * tclgetbuffer() - buffer frontend for tclgetref()
+ * tclsetdelcmd() - add Tcl callback command to a vim object
+ */
+ static void
+delref(cref)
+ ClientData cref;
+{
+ struct ref *ref = (struct ref *)cref;
+
+ if (ref->delcmd)
+ {
+ Tcl_DecrRefCount(ref->delcmd);
+ ref->delcmd = NULL;
+ }
+ ref->interp = NULL;
+}
+
+ static char *
+tclgetref(interp, refstartP, prefix, vimobj, proc)
+ Tcl_Interp *interp;
+ void **refstartP; /* ptr to tcl_ref member of win_T/buf_T struct */
+ char *prefix; /* "win" or "buf" */
+ void *vimobj; /* win_T* or buf_T* */
+ Tcl_ObjCmdProc *proc; /* winselfcmd or bufselfcmd */
+{
+ struct ref *ref, *unused = NULL;
+ static char name[VARNAME_SIZE];
+ Tcl_Command cmd;
+
+ ref = (struct ref *)(*refstartP);
+ if (ref == &refsdeleted)
+ {
+ Tcl_SetResult(interp, _("cannot create buffer/window command: object is being deleted"), TCL_STATIC);
+ return NULL;
+ }
+
+ while (ref != NULL)
+ {
+ if (ref->interp == interp)
+ break;
+ if (ref->interp == NULL)
+ unused = ref;
+ ref = ref->next;
+ }
+
+ if (ref)
+ sprintf(name, "::vim::%s", Tcl_GetCommandName(interp, ref->cmd));
+ else
+ {
+ if (unused)
+ ref = unused;
+ else
+ {
+ ref = (struct ref *)Tcl_Alloc(sizeof(struct ref));
+#if 0 /* Tcl_Alloc either succeeds or does not return */
+ if (!ref)
+ {
+ Tcl_SetResult(interp, "out of memory", TCL_STATIC);
+ return NULL;
+ }
+#endif
+ ref->interp = NULL;
+ ref->next = (struct ref *)(*refstartP);
+ (*refstartP) = (void *)ref;
+ }
+
+ /* This might break on some exotic systems... */
+ sprintf(name, "::vim::%s_%lx", prefix, (unsigned long)vimobj);
+ cmd = Tcl_CreateObjCommand(interp, name, proc,
+ (ClientData)ref, (Tcl_CmdDeleteProc *)delref);
+ if (!cmd)
+ return NULL;
+
+ ref->interp = interp;
+ ref->cmd = cmd;
+ ref->delcmd = NULL;
+ ref->vimobj = vimobj;
+ }
+ return name;
+}
+
+ static char *
+tclgetwindow(interp, win)
+ Tcl_Interp *interp;
+ win_T *win;
+{
+ return tclgetref(interp, &(win->tcl_ref), "win", (void *)win, winselfcmd);
+}
+
+ static char *
+tclgetbuffer(interp, buf)
+ Tcl_Interp *interp;
+ buf_T *buf;
+{
+ return tclgetref(interp, &(buf->tcl_ref), "buf", (void *)buf, bufselfcmd);
+}
+
+ static int
+tclsetdelcmd(interp, reflist, vimobj, delcmd)
+ Tcl_Interp *interp;
+ struct ref *reflist;
+ void *vimobj;
+ Tcl_Obj *delcmd;
+{
+ if (reflist == &refsdeleted)
+ {
+ Tcl_SetResult(interp, _("cannot register callback command: buffer/window is already being deleted"), TCL_STATIC);
+ return TCL_ERROR;
+ }
+
+ while (reflist != NULL)
+ {
+ if (reflist->interp == interp && reflist->vimobj == vimobj)
+ {
+ if (reflist->delcmd)
+ Tcl_DecrRefCount(reflist->delcmd);
+ Tcl_IncrRefCount(delcmd);
+ reflist->delcmd = delcmd;
+ return TCL_OK;
+ }
+ reflist = reflist->next;
+ }
+ /* This should never happen. Famous last word? */
+ EMSG(_("E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim.org"));
+ Tcl_SetResult(interp, _("cannot register callback command: buffer/window reference not found"), TCL_STATIC);
+ return TCL_ERROR;
+}
+
+
+/*******************************************
+ I/O Channel
+********************************************/
+
+/* ARGSUSED */
+ static int
+channel_close(instance, interp)
+ ClientData instance;
+ Tcl_Interp *interp;
+{
+ int err = 0;
+
+ /* currently does nothing */
+
+ if (instance != VIMOUT && instance != VIMERR)
+ {
+ Tcl_SetErrno(EBADF);
+ err = EBADF;
+ }
+ return err;
+}
+
+/* ARGSUSED */
+ static int
+channel_input(instance, buf, bufsiz, errptr)
+ ClientData instance;
+ char *buf;
+ int bufsiz;
+ int *errptr;
+{
+
+ /* input is currently not supported */
+
+ Tcl_SetErrno(EINVAL);
+ if (errptr)
+ *errptr = EINVAL;
+ return -1;
+}
+
+ static int
+channel_output(instance, buf, bufsiz, errptr)
+ ClientData instance;
+ char *buf;
+ int bufsiz;
+ int *errptr;
+{
+ char_u *str;
+ int result;
+
+ /* The buffer is not guaranteed to be 0-terminated, and we don't if
+ * there is enough room to add a '\0'. So we have to create a copy
+ * of the buffer...
+ */
+ str = vim_strnsave((char_u *)buf, bufsiz);
+ if (!str)
+ {
+ Tcl_SetErrno(ENOMEM);
+ if (errptr)
+ *errptr = ENOMEM;
+ return -1;
+ }
+
+ result = bufsiz;
+ if (instance == VIMOUT)
+ tclmsg((char *)str);
+ else
+ if (instance == VIMERR)
+ tclerrmsg((char *)str);
+ else
+ {
+ Tcl_SetErrno(EBADF);
+ if (errptr)
+ *errptr = EBADF;
+ result = -1;
+ }
+ vim_free(str);
+ return result;
+}
+
+/* ARGSUSED */
+ static void
+channel_watch(instance, mask)
+ ClientData instance;
+ int mask;
+{
+ Tcl_SetErrno(EINVAL);
+}
+
+/* ARGSUSED */
+ static int
+channel_gethandle(instance, direction, handleptr)
+ ClientData instance;
+ int direction;
+ ClientData *handleptr;
+{
+ Tcl_SetErrno(EINVAL);
+ return EINVAL;
+}
+
+
+static Tcl_ChannelType channel_type =
+{
+ "vimmessage",
+ NULL, /* blockmode */
+ channel_close,
+ channel_input,
+ channel_output,
+ NULL, /* seek */
+ NULL, /* set option */
+ NULL, /* get option */
+ channel_watch,
+ channel_gethandle
+};
+
+/**********************************
+ Interface to vim
+ **********************************/
+
+ static void
+tclupdatevars()
+{
+ char varname[VARNAME_SIZE]; /* must be writeable */
+ char *name;
+
+ strcpy(varname, VAR_RANGE1);
+ Tcl_UpdateLinkedVar(tclinfo.interp, varname);
+ strcpy(varname, VAR_RANGE2);
+ Tcl_UpdateLinkedVar(tclinfo.interp, varname);
+ strcpy(varname, VAR_RANGE3);
+ Tcl_UpdateLinkedVar(tclinfo.interp, varname);
+
+ strcpy(varname, VAR_LBASE);
+ Tcl_UpdateLinkedVar(tclinfo.interp, varname);
+
+ name = tclgetbuffer(tclinfo.interp, curbuf);
+ strcpy(tclinfo.curbuf, name);
+ strcpy(varname, VAR_CURBUF);
+ Tcl_UpdateLinkedVar(tclinfo.interp, varname);
+
+ name = tclgetwindow(tclinfo.interp, curwin);
+ strcpy(tclinfo.curwin, name);
+ strcpy(varname, VAR_CURWIN);
+ Tcl_UpdateLinkedVar(tclinfo.interp, varname);
+}
+
+
+ static int
+tclinit(eap)
+ exarg_T *eap;
+{
+ char varname[VARNAME_SIZE]; /* Tcl_LinkVar requires writeable varname */
+ char *name;
+
+#ifdef DYNAMIC_TCL
+ if (!tcl_enabled(TRUE))
+ {
+ EMSG(_("E571: Sorry, this command is disabled: the Tcl library could not be loaded."));
+ return FAIL;
+ }
+#endif
+
+ if (!tclinfo.interp)
+ {
+ Tcl_Interp *interp;
+ static Tcl_Channel ch1, ch2;
+
+ /* replace stdout and stderr */
+ ch1 = Tcl_CreateChannel(&channel_type, "vimout", VIMOUT, TCL_WRITABLE);
+ ch2 = Tcl_CreateChannel(&channel_type, "vimerr", VIMERR, TCL_WRITABLE);
+ Tcl_SetStdChannel(ch1, TCL_STDOUT);
+ Tcl_SetStdChannel(ch2, TCL_STDERR);
+
+ interp = Tcl_CreateInterp();
+ Tcl_Preserve(interp);
+ if (Tcl_Init(interp) == TCL_ERROR)
+ {
+ Tcl_Release(interp);
+ Tcl_DeleteInterp(interp);
+ return FAIL;
+ }
+#if 0
+ /* VIM sure is interactive */
+ Tcl_SetVar(interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
+#endif
+
+ Tcl_SetChannelOption(interp, ch1, "-buffering", "line");
+ Tcl_SetChannelOption(interp, ch2, "-buffering", "line");
+
+ /* replace some standard Tcl commands */
+ Tcl_DeleteCommand(interp, "exit");
+ Tcl_CreateObjCommand(interp, "exit", exitcmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
+ Tcl_DeleteCommand(interp, "catch");
+ Tcl_CreateObjCommand(interp, "catch", catchcmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
+
+ /* new commands, in ::vim namespace */
+ Tcl_CreateObjCommand(interp, "::vim::buffer", buffercmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
+ Tcl_CreateObjCommand(interp, "::vim::window", windowcmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
+ Tcl_CreateObjCommand(interp, "::vim::command", commandcmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
+ Tcl_CreateObjCommand(interp, "::vim::beep", beepcmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
+ Tcl_CreateObjCommand(interp, "::vim::option", optioncmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
+ Tcl_CreateObjCommand(interp, "::vim::expr", exprcmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
+
+ /* "lbase" variable */
+ tclinfo.lbase = 1;
+ strcpy(varname, VAR_LBASE);
+ Tcl_LinkVar(interp, varname, (char *)&tclinfo.lbase, TCL_LINK_INT);
+
+ /* "range" variable */
+ tclinfo.range_start = eap->line1;
+ strcpy(varname, VAR_RANGE1);
+ Tcl_LinkVar(interp, varname, (char *)&tclinfo.range_start, TCL_LINK_INT|TCL_LINK_READ_ONLY);
+ strcpy(varname, VAR_RANGE2);
+ Tcl_LinkVar(interp, varname, (char *)&tclinfo.range_start, TCL_LINK_INT|TCL_LINK_READ_ONLY);
+ tclinfo.range_end = eap->line2;
+ strcpy(varname, VAR_RANGE3);
+ Tcl_LinkVar(interp, varname, (char *)&tclinfo.range_end, TCL_LINK_INT|TCL_LINK_READ_ONLY);
+
+ /* "current" variable */
+ tclinfo.curbuf = Tcl_Alloc(VARNAME_SIZE);
+ tclinfo.curwin = Tcl_Alloc(VARNAME_SIZE);
+ name = tclgetbuffer(interp, curbuf);
+ strcpy(tclinfo.curbuf, name);
+ strcpy(varname, VAR_CURBUF);
+ Tcl_LinkVar(interp, varname, (char *)&tclinfo.curbuf, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
+ name = tclgetwindow(interp, curwin);
+ strcpy(tclinfo.curwin, name);
+ strcpy(varname, VAR_CURWIN);
+ Tcl_LinkVar(interp, varname, (char *)&tclinfo.curwin, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
+
+ tclinfo.interp = interp;
+ }
+ else
+ {
+ /* Interpreter already exists, just update variables */
+ tclinfo.range_start = row2tcl(eap->line1);
+ tclinfo.range_end = row2tcl(eap->line2);
+ tclupdatevars();
+ }
+ return OK;
+}
+
+ static void
+tclerrmsg(text)
+ char *text;
+{
+ char *next;
+
+ while ((next=strchr(text, '\n')))
+ {
+ *next++ = '\0';
+ EMSG(text);
+ text = next;
+ }
+ if (*text)
+ EMSG(text);
+}
+
+ static void
+tclmsg(text)
+ char *text;
+{
+ char *next;
+
+ while ((next=strchr(text, '\n')))
+ {
+ *next++ = '\0';
+ MSG(text);
+ text = next;
+ }
+ if (*text)
+ MSG(text);
+}
+
+ static void
+tcldelthisinterp()
+{
+ if (!Tcl_InterpDeleted(tclinfo.interp))
+ Tcl_DeleteInterp(tclinfo.interp);
+ Tcl_Release(tclinfo.interp);
+ /* The interpreter is now gets deleted. All registered commands (esp.
+ * window and buffer commands) are deleted, triggering their deletion
+ * callback, which deletes all refs pointing to this interpreter.
+ * We could garbage-collect the unused ref structs in all windows and
+ * buffers, but unless the user creates hundreds of sub-interpreters
+ * all refering to lots of windows and buffers, this is hardly worth
+ * the effort. Unused refs are recycled by other interpreters, and
+ * all refs are free'd when the window/buffer gets closed by vim.
+ */
+
+ tclinfo.interp = NULL;
+ Tcl_Free(tclinfo.curbuf);
+ Tcl_Free(tclinfo.curwin);
+ tclinfo.curbuf = tclinfo.curwin = NULL;
+}
+
+ static int
+tclexit(error)
+ int error;
+{
+ int newerr = OK;
+
+ if (error == TCL_EXIT )
+ {
+ int retval;
+ char buf[32];
+ Tcl_Obj *robj;
+
+ robj = Tcl_GetObjResult(tclinfo.interp);
+ if( Tcl_GetIntFromObj(tclinfo.interp, robj, &retval) != TCL_OK )
+ {
+ EMSG(_("E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"));
+ newerr = FAIL;
+ }
+ else
+ {
+ sprintf(buf, "E572: exit code %d", retval);
+ tclerrmsg(buf);
+ if (retval == 0 )
+ {
+ did_emsg = 0;
+ newerr = OK;
+ }
+ else
+ newerr = FAIL;
+ }
+
+ tcldelthisinterp();
+ }
+ else
+ {
+ char *result;
+
+ result = Tcl_GetStringResult(tclinfo.interp);
+ if (error == TCL_OK)
+ {
+ tclmsg(result);
+ newerr = OK;
+ }
+ else
+ {
+ tclerrmsg(result);
+ newerr = FAIL;
+ }
+ }
+
+ return newerr;
+}
+
+/*
+ * ":tcl"
+ */
+ void
+ex_tcl(eap)
+ exarg_T *eap;
+{
+ char_u *script;
+ int err;
+
+ script = script_get(eap, eap->arg);
+ if (!eap->skip)
+ {
+ err = tclinit(eap);
+ if (err == OK)
+ {
+ Tcl_AllowExceptions(tclinfo.interp);
+ if (script == NULL)
+ err = Tcl_Eval(tclinfo.interp, (char *)eap->arg);
+ else
+ err = Tcl_Eval(tclinfo.interp, (char *)script);
+ err = tclexit(err);
+ }
+ }
+ vim_free(script);
+}
+
+/*
+ * ":tclfile"
+ */
+ void
+ex_tclfile(eap)
+ exarg_T *eap;
+{
+ char *file = (char *)eap->arg;
+ int err;
+
+ err = tclinit(eap);
+ if (err == OK)
+ {
+ Tcl_AllowExceptions(tclinfo.interp);
+ err = Tcl_EvalFile(tclinfo.interp, file);
+ err = tclexit(err);
+ }
+}
+
+/*
+ * ":tcldo"
+ */
+ void
+ex_tcldo(eap)
+ exarg_T *eap;
+{
+ char *script, *line;
+ int err, rs, re, lnum;
+ char var_lnum[VARNAME_SIZE]; /* must be writeable memory */
+ char var_line[VARNAME_SIZE];
+ linenr_T first_line = 0;
+ linenr_T last_line = 0;
+
+ rs = eap->line1;
+ re = eap->line2;
+ script = (char *)eap->arg;
+ strcpy(var_lnum, VAR_CURLNUM);
+ strcpy(var_line, VAR_CURLINE);
+
+ err = tclinit(eap);
+ if (err != OK)
+ return;
+
+ lnum = row2tcl(rs);
+ Tcl_LinkVar(tclinfo.interp, var_lnum, (char *)&lnum, TCL_LINK_INT|TCL_LINK_READ_ONLY);
+ err = TCL_OK;
+ if (u_save((linenr_T)(rs-1), (linenr_T)(re+1)) != OK)
+ {
+ Tcl_SetResult(tclinfo.interp, _("cannot save undo information"), TCL_STATIC);
+ err = TCL_ERROR;
+ }
+ while (err == TCL_OK && rs <= re)
+ {
+ line = (char *)ml_get_buf(curbuf, (linenr_T)rs, FALSE);
+ if (!line)
+ {
+ Tcl_SetResult(tclinfo.interp, _("cannot get line"), TCL_STATIC);
+ err = TCL_ERROR;
+ break;
+ }
+ Tcl_SetVar(tclinfo.interp, var_line, line, 0);
+ Tcl_AllowExceptions(tclinfo.interp);
+ err = Tcl_Eval(tclinfo.interp, script);
+ if (err != TCL_OK)
+ break;
+ line = Tcl_GetVar(tclinfo.interp, var_line, 0);
+ if (line)
+ {
+ if (ml_replace((linenr_T)rs, (char_u *)line, TRUE) != OK)
+ {
+ Tcl_SetResult(tclinfo.interp, _("cannot replace line"), TCL_STATIC);
+ err = TCL_ERROR;
+ break;
+ }
+ if (first_line == 0)
+ first_line = rs;
+ last_line = rs;
+ }
+ ++rs;
+ ++lnum;
+ Tcl_UpdateLinkedVar(tclinfo.interp, var_lnum);
+ }
+ if (first_line)
+ changed_lines(first_line, 0, last_line + 1, (long)0);
+
+ Tcl_UnsetVar(tclinfo.interp, var_line, 0);
+ Tcl_UnlinkVar(tclinfo.interp, var_lnum);
+ if (err == TCL_OK)
+ Tcl_ResetResult(tclinfo.interp);
+
+ (void)tclexit(err);
+}
+
+ static void
+tcldelallrefs(ref)
+ struct ref *ref;
+{
+ struct ref *next;
+ int err;
+ char *result;
+
+ while (ref != NULL)
+ {
+ next = ref->next;
+ if (ref->interp)
+ {
+ if (ref->delcmd)
+ {
+ err = Tcl_GlobalEvalObj(ref->interp, ref->delcmd);
+ if (err != TCL_OK)
+ {
+ result = Tcl_GetStringResult(ref->interp);
+ if (result)
+ tclerrmsg(result);
+ }
+ Tcl_DecrRefCount(ref->delcmd);
+ ref->delcmd = NULL;
+ }
+ Tcl_DeleteCommandFromToken(ref->interp, ref->cmd);
+ }
+ Tcl_Free((char *)ref);
+ ref = next;
+ }
+}
+
+ void
+tcl_buffer_free(buf)
+ buf_T *buf;
+{
+ struct ref *reflist;
+
+#ifdef DYNAMIC_TCL
+ if (!stubs_initialized) /* Not using Tcl, nothing to do. */
+ return;
+#endif
+
+ reflist = (struct ref*)(buf->tcl_ref);
+ if (reflist != &refsdeleted)
+ {
+ buf->tcl_ref = (void *)&refsdeleted;
+ tcldelallrefs(reflist);
+ buf->tcl_ref = NULL;
+ }
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+ void
+tcl_window_free(win)
+ win_T *win;
+{
+ struct ref *reflist;
+
+#ifdef DYNAMIC_TCL
+ if (!stubs_initialized) /* Not using Tcl, nothing to do. */
+ return;
+#endif
+
+ reflist = (struct ref*)(win->tcl_ref);
+ if (reflist != &refsdeleted)
+ {
+ win->tcl_ref = (void *)&refsdeleted;
+ tcldelallrefs(reflist);
+ win->tcl_ref = NULL;
+ }
+}
+#endif
+
+/* The End */
diff --git a/src/if_xcmdsrv.c b/src/if_xcmdsrv.c
new file mode 100644
index 000000000..a82139e64
--- /dev/null
+++ b/src/if_xcmdsrv.c
@@ -0,0 +1,1441 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * X command server by Flemming Madsen
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ *
+ * if_xcmdsrv.c: Functions for passing commands through an X11 display.
+ *
+ */
+
+#include "vim.h"
+#include "version.h"
+
+#if defined(FEAT_CLIENTSERVER) || defined(PROTO)
+
+# ifdef FEAT_X11
+# include <X11/Intrinsic.h>
+# include <X11/Xatom.h>
+# endif
+
+# if defined(HAVE_SYS_SELECT_H) && \
+ (!defined(HAVE_SYS_TIME_H) || defined(SYS_SELECT_WITH_SYS_TIME))
+# include <sys/select.h>
+# endif
+
+# ifndef HAVE_SELECT
+# ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+# else
+# ifdef HAVE_POLL_H
+# include <poll.h>
+# endif
+# endif
+# endif
+
+/*
+ * This file provides procedures that implement the command server functionality
+ * of Vim when in contact with an X11 server.
+ *
+ * Adapted from TCL/TK's send command in tkSend.c of the tk 3.6 distribution.
+ * Adapted for use in Vim by Flemming Madsen. Protocol changed to that of tk 4
+ */
+
+/*
+ * Copyright (c) 1989-1993 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+
+/*
+ * When a result is being awaited from a sent command, one of
+ * the following structures is present on a list of all outstanding
+ * sent commands. The information in the structure is used to
+ * process the result when it arrives. You're probably wondering
+ * how there could ever be multiple outstanding sent commands.
+ * This could happen if Vim instances invoke each other recursively.
+ * It's unlikely, but possible.
+ */
+
+typedef struct PendingCommand
+{
+ int serial; /* Serial number expected in result. */
+ int code; /* Result Code. 0 is OK */
+ char_u *result; /* String result for command (malloc'ed).
+ * NULL means command still pending. */
+ struct PendingCommand *nextPtr;
+ /* Next in list of all outstanding commands.
+ * NULL means end of list. */
+} PendingCommand;
+
+static PendingCommand *pendingCommands = NULL;
+ /* List of all commands currently
+ * being waited for. */
+
+/*
+ * The information below is used for communication between processes
+ * during "send" commands. Each process keeps a private window, never
+ * even mapped, with one property, "Comm". When a command is sent to
+ * an interpreter, the command is appended to the comm property of the
+ * communication window associated with the interp's process. Similarly,
+ * when a result is returned from a sent command, it is also appended
+ * to the comm property.
+ *
+ * Each command and each result takes the form of ASCII text. For a
+ * command, the text consists of a nul character followed by several
+ * nul-terminated ASCII strings. The first string consists of the
+ * single letter "c" for an expression, or "k" for keystrokes. Subsequent
+ * strings have the form "option value" where the following options are
+ * supported:
+ *
+ * -r commWindow serial
+ *
+ * This option means that a response should be sent to the window
+ * whose X identifier is "commWindow" (in hex), and the response should
+ * be identified with the serial number given by "serial" (in decimal).
+ * If this option isn't specified then the send is asynchronous and
+ * no response is sent.
+ *
+ * -n name
+ * "Name" gives the name of the application for which the command is
+ * intended. This option must be present.
+ *
+ * -s script
+ * "Script" is the script to be executed. This option must be
+ * present. Taken as a series of keystrokes in a "k" command where
+ * <Key>'s are expanded
+ *
+ * The options may appear in any order. The -n and -s options must be
+ * present, but -r may be omitted for asynchronous RPCs. For compatibility
+ * with future releases that may add new features, there may be additional
+ * options present; as long as they start with a "-" character, they will
+ * be ignored.
+ *
+ * A result also consists of a zero character followed by several null-
+ * terminated ASCII strings. The first string consists of the single
+ * letter "r". Subsequent strings have the form "option value" where
+ * the following options are supported:
+ *
+ * -s serial
+ * Identifies the command for which this is the result. It is the
+ * same as the "serial" field from the -s option in the command. This
+ * option must be present.
+ *
+ * -r result
+ * "Result" is the result string for the script, which may be either
+ * a result or an error message. If this field is omitted then it
+ * defaults to an empty string.
+ *
+ * -c code
+ * 0: for OK. This is the default.
+ * 1: for error: Result is the last error
+ *
+ * -i errorInfo
+ * -e errorCode
+ * Not applicable for Vim
+ *
+ * Options may appear in any order, and only the -s option must be
+ * present. As with commands, there may be additional options besides
+ * these; unknown options are ignored.
+ */
+
+/*
+ * Maximum size property that can be read at one time by
+ * this module:
+ */
+
+#define MAX_PROP_WORDS 100000
+
+struct ServerReply
+{
+ Window id;
+ garray_T strings;
+};
+static garray_T serverReply = { 0, 0, 0, 0, 0 };
+enum ServerReplyOp { SROP_Find, SROP_Add, SROP_Delete };
+
+typedef int (*EndCond) __ARGS((void *));
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static Window LookupName __ARGS((Display *dpy, char_u *name, int delete, char_u **loose));
+static int SendInit __ARGS((Display *dpy));
+static int DoRegisterName __ARGS((Display *dpy, char_u *name));
+static void DeleteAnyLingerer __ARGS((Display *dpy, Window w));
+static int GetRegProp __ARGS((Display *dpy, char_u **regPropp, long_u *numItemsp, int domsg));
+static int WaitForPend __ARGS((void *p));
+static int WaitForReply __ARGS((void *p));
+static int WindowValid __ARGS((Display *dpy, Window w));
+static void ServerWait __ARGS((Display *dpy, Window w, EndCond endCond, void *endData, int localLoop, int seconds));
+static struct ServerReply *ServerReplyFind __ARGS((Window w, enum ServerReplyOp op));
+static int AppendPropCarefully __ARGS((Display *display, Window window, Atom property, char_u *value, int length));
+static int x_error_check __ARGS((Display *dpy, XErrorEvent *error_event));
+static int IsSerialName __ARGS((char_u *name));
+
+/* Private variables for the "server" functionality */
+static Atom registryProperty = None;
+static Atom vimProperty = None;
+static int got_x_error = FALSE;
+
+static char_u *empty_prop = (char_u *)""; /* empty GetRegProp() result */
+
+/*
+ * Associate an ASCII name with Vim. Try real hard to get a unique one.
+ * Returns FAIL or OK.
+ */
+ int
+serverRegisterName(dpy, name)
+ Display *dpy; /* display to register with */
+ char_u *name; /* the name that will be used as a base */
+{
+ int i;
+ int res;
+ char_u *p = NULL;
+
+ res = DoRegisterName(dpy, name);
+ if (res < 0)
+ {
+ i = 1;
+ do
+ {
+ if (res < -1 || i >= 1000)
+ {
+ MSG_ATTR(_("Unable to register a command server name"),
+ hl_attr(HLF_W));
+ return FAIL;
+ }
+ if (p == NULL)
+ p = alloc(STRLEN(name) + 10);
+ if (p == NULL)
+ {
+ res = -10;
+ continue;
+ }
+ sprintf((char *)p, "%s%d", name, i++);
+ res = DoRegisterName(dpy, p);
+ }
+ while (res < 0)
+ ;
+ vim_free(p);
+ }
+ return OK;
+}
+
+ static int
+DoRegisterName(dpy, name)
+ Display *dpy;
+ char_u *name;
+{
+ Window w;
+ XErrorHandler old_handler;
+#define MAX_NAME_LENGTH 100
+ char_u propInfo[MAX_NAME_LENGTH + 20];
+
+ if (commProperty == None)
+ {
+ if (SendInit(dpy) < 0)
+ return -2;
+ }
+
+ /*
+ * Make sure the name is unique, and append info about it to
+ * the registry property. It's important to lock the server
+ * here to prevent conflicting changes to the registry property.
+ * WARNING: Do not step through this while debugging, it will hangup the X
+ * server!
+ */
+ XGrabServer(dpy);
+ w = LookupName(dpy, name, FALSE, NULL);
+ if (w != (Window)0)
+ {
+ Status status;
+ int dummyInt;
+ unsigned int dummyUns;
+ Window dummyWin;
+
+ /*
+ * The name is currently registered. See if the commWindow
+ * associated with the name exists. If not, or if the commWindow
+ * is *our* commWindow, then just unregister the old name (this
+ * could happen if an application dies without cleaning up the
+ * registry).
+ */
+ old_handler = XSetErrorHandler(x_error_check);
+ status = XGetGeometry(dpy, w, &dummyWin, &dummyInt, &dummyInt,
+ &dummyUns, &dummyUns, &dummyUns, &dummyUns);
+ (void)XSetErrorHandler(old_handler);
+ if (status != Success && w != commWindow)
+ {
+ XUngrabServer(dpy);
+ XFlush(dpy);
+ return -1;
+ }
+ (void)LookupName(dpy, name, /*delete=*/TRUE, NULL);
+ }
+ sprintf((char *)propInfo, "%x %.*s", (int_u)commWindow,
+ MAX_NAME_LENGTH, name);
+ old_handler = XSetErrorHandler(x_error_check);
+ got_x_error = FALSE;
+ XChangeProperty(dpy, RootWindow(dpy, 0), registryProperty, XA_STRING, 8,
+ PropModeAppend, propInfo, STRLEN(propInfo) + 1);
+ XUngrabServer(dpy);
+ XSync(dpy, False);
+ (void)XSetErrorHandler(old_handler);
+
+ if (!got_x_error)
+ {
+#ifdef FEAT_EVAL
+ set_vim_var_string(VV_SEND_SERVER, name, -1);
+#endif
+ serverName = vim_strsave(name);
+#ifdef FEAT_TITLE
+ need_maketitle = TRUE;
+#endif
+ return 0;
+ }
+ return -2;
+}
+
+#if defined(FEAT_GUI) || defined(PROTO)
+/*
+ * Clean out new ID from registry and set it as comm win.
+ * Change any registered window ID.
+ */
+ void
+serverChangeRegisteredWindow(dpy, newwin)
+ Display *dpy; /* Display to register with */
+ Window newwin; /* Re-register to this ID */
+{
+ char_u propInfo[MAX_NAME_LENGTH + 20];
+
+ commWindow = newwin;
+
+ /* Always call SendInit() here, to make sure commWindow is marked as a Vim
+ * window. */
+ if (SendInit(dpy) < 0)
+ return;
+
+ /* WARNING: Do not step through this while debugging, it will hangup the X
+ * server! */
+ XGrabServer(dpy);
+ DeleteAnyLingerer(dpy, newwin);
+ if (serverName != NULL)
+ {
+ /* Reinsert name if we was already registered */
+ (void)LookupName(dpy, serverName, /*delete=*/TRUE, NULL);
+ sprintf((char *)propInfo, "%x %.*s",
+ (int_u)newwin, MAX_NAME_LENGTH, serverName);
+ XChangeProperty(dpy, RootWindow(dpy, 0), registryProperty, XA_STRING, 8,
+ PropModeAppend, (char_u *)propInfo,
+ STRLEN(propInfo) + 1);
+ }
+ XUngrabServer(dpy);
+}
+#endif
+
+/*
+ * Send to an instance of Vim via the X display.
+ * Returns 0 for OK, negative for an error.
+ */
+ int
+serverSendToVim(dpy, name, cmd, result, server, asExpr, localLoop, silent)
+ Display *dpy; /* Where to send. */
+ char_u *name; /* Where to send. */
+ char_u *cmd; /* What to send. */
+ char_u **result; /* Result of eval'ed expression */
+ Window *server; /* Actual ID of receiving app */
+ Bool asExpr; /* Interpret as keystrokes or expr ? */
+ Bool localLoop; /* Throw away everything but result */
+ int silent; /* don't complain about no server */
+{
+ Window w;
+ char_u *property;
+ int length;
+ int res;
+ static int serial = 0; /* Running count of sent commands.
+ * Used to give each command a
+ * different serial number. */
+ PendingCommand pending;
+ char_u *loosename = NULL;
+
+ if (result != NULL)
+ *result = NULL;
+ if (name == NULL || *name == NUL)
+ name = (char_u *)"GVIM"; /* use a default name */
+
+ if (commProperty == None && dpy != NULL)
+ {
+ if (SendInit(dpy) < 0)
+ return -1;
+ }
+
+ /* Execute locally if no display or target is ourselves */
+ if (dpy == NULL || (serverName != NULL && STRICMP(name, serverName) == 0))
+ {
+ if (asExpr)
+ {
+ char_u *ret;
+
+ ret = eval_client_expr_to_string(cmd);
+ if (result != NULL)
+ {
+ if (ret == NULL)
+ *result = vim_strsave((char_u *)_(e_invexprmsg));
+ else
+ *result = ret;
+ }
+ else
+ vim_free(ret);
+ return ret == NULL ? -1 : 0;
+ }
+ else
+ server_to_input_buf(cmd);
+ return 0;
+ }
+
+ /*
+ * Bind the server name to a communication window.
+ *
+ * Find any survivor with a serialno attached to the name if the
+ * original registrant of the wanted name is no longer present.
+ *
+ * Delete any lingering names from dead editors.
+ */
+ while (TRUE)
+ {
+ w = LookupName(dpy, name, FALSE, &loosename);
+ /* Check that the window is hot */
+ if (w != None)
+ {
+ if (!WindowValid(dpy, w))
+ {
+ LookupName(dpy, loosename ? loosename : name,
+ /*DELETE=*/TRUE, NULL);
+ continue;
+ }
+ }
+ break;
+ }
+ if (w == None)
+ {
+ if (!silent)
+ EMSG2(_(e_noserver), name);
+ return -1;
+ }
+ else if (loosename != NULL)
+ name = loosename;
+ if (server != NULL)
+ *server = w;
+
+ /*
+ * Send the command to target interpreter by appending it to the
+ * comm window in the communication window.
+ */
+ length = STRLEN(name) + STRLEN(cmd) + 10;
+ property = (char_u *)alloc((unsigned) length + 30);
+
+ sprintf((char *)property, "%c%c%c-n %s%c-s %s",
+ 0, asExpr ? 'c' : 'k', 0, name, 0, cmd);
+ if (name == loosename)
+ vim_free(loosename);
+ /* Add a back reference to our comm window */
+ serial++;
+ sprintf((char *)property + length, "%c-r %x %d",
+ 0, (int_u)commWindow, serial);
+ length += STRLEN(property + length + 1) + 1;
+
+ res = AppendPropCarefully(dpy, w, commProperty, property, length + 1);
+ vim_free(property);
+ if (res < 0)
+ {
+ EMSG(_("E248: Failed to send command to the destination program"));
+ return -1;
+ }
+
+ if (!asExpr) /* There is no answer for this - Keys are sent async */
+ return 0;
+
+ /*
+ * Register the fact that we're waiting for a command to
+ * complete (this is needed by SendEventProc and by
+ * AppendErrorProc to pass back the command's results).
+ */
+ pending.serial = serial;
+ pending.code = 0;
+ pending.result = NULL;
+ pending.nextPtr = pendingCommands;
+ pendingCommands = &pending;
+
+ ServerWait(dpy, w, WaitForPend, &pending, localLoop, 600);
+
+ /*
+ * Unregister the information about the pending command
+ * and return the result.
+ */
+ if (pendingCommands == &pending)
+ pendingCommands = pending.nextPtr;
+ else
+ {
+ PendingCommand *pcPtr;
+
+ for (pcPtr = pendingCommands; pcPtr != NULL; pcPtr = pcPtr->nextPtr)
+ if (pcPtr->nextPtr == &pending)
+ {
+ pcPtr->nextPtr = pending.nextPtr;
+ break;
+ }
+ }
+ if (result != NULL)
+ *result = pending.result;
+ else
+ vim_free(pending.result);
+
+ return pending.code == 0 ? 0 : -1;
+}
+
+ static int
+WaitForPend(p)
+ void *p;
+{
+ PendingCommand *pending = (PendingCommand *) p;
+ return pending->result != NULL;
+}
+
+/*
+ * Return TRUE if window "w" exists and has a "Vim" property on it.
+ */
+ static int
+WindowValid(dpy, w)
+ Display *dpy;
+ Window w;
+{
+ XErrorHandler old_handler;
+ Atom *plist;
+ int numProp;
+ int i;
+
+ old_handler = XSetErrorHandler(x_error_check);
+ got_x_error = 0;
+ plist = XListProperties(dpy, w, &numProp);
+ XSync(dpy, False);
+ XSetErrorHandler(old_handler);
+ if (plist == NULL || got_x_error)
+ return FALSE;
+
+ for (i = 0; i < numProp; i++)
+ if (plist[i] == vimProperty)
+ {
+ XFree(plist);
+ return TRUE;
+ }
+ XFree(plist);
+ return FALSE;
+}
+
+/*
+ * Enter a loop processing X events & polling chars until we see a result
+ */
+ static void
+ServerWait(dpy, w, endCond, endData, localLoop, seconds)
+ Display *dpy;
+ Window w;
+ EndCond endCond;
+ void *endData;
+ int localLoop;
+ int seconds;
+{
+ time_t start;
+ time_t now;
+ time_t lastChk = 0;
+ XEvent event;
+ XPropertyEvent *e = (XPropertyEvent *)&event;
+# define SEND_MSEC_POLL 50
+
+ time(&start);
+ while (endCond(endData) == 0)
+ {
+ time(&now);
+ if (seconds >= 0 && (now - start) >= seconds)
+ break;
+ if (now != lastChk)
+ {
+ lastChk = now;
+ if (!WindowValid(dpy, w))
+ break;
+ /*
+ * Sometimes the PropertyChange event doesn't come.
+ * This can be seen in eg: vim -c 'echo remote_expr("gvim", "3+2")'
+ */
+ serverEventProc(dpy, NULL);
+ }
+ if (localLoop)
+ {
+ /* Just look out for the answer without calling back into Vim */
+#ifndef HAVE_SELECT
+ struct pollfd fds;
+
+ fds.fd = ConnectionNumber(dpy);
+ fds.events = POLLIN;
+ if (poll(&fds, 1, SEND_MSEC_POLL) < 0)
+ break;
+#else
+ fd_set fds;
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = SEND_MSEC_POLL * 1000;
+ FD_ZERO(&fds);
+ FD_SET(ConnectionNumber(dpy), &fds);
+ if (select(ConnectionNumber(dpy) + 1, &fds, NULL, NULL, &tv) < 0)
+ break;
+#endif
+ while (XEventsQueued(dpy, QueuedAfterReading) > 0)
+ {
+ XNextEvent(dpy, &event);
+ if (event.type == PropertyNotify && e->window == commWindow)
+ serverEventProc(dpy, &event);
+ }
+ }
+ else
+ {
+ if (got_int)
+ break;
+ ui_delay((long)SEND_MSEC_POLL, TRUE);
+ ui_breakcheck();
+ }
+ }
+}
+
+
+/*
+ * Fetch a list of all the Vim instance names currently registered for the
+ * display.
+ *
+ * Returns a newline separated list in allocated memory or NULL.
+ */
+ char_u *
+serverGetVimNames(dpy)
+ Display *dpy;
+{
+ char_u *regProp;
+ char_u *entry;
+ char_u *p;
+ long_u numItems;
+ int_u w;
+ garray_T ga;
+
+ if (registryProperty == None)
+ {
+ if (SendInit(dpy) < 0)
+ return NULL;
+ }
+ ga_init2(&ga, 1, 100);
+
+ /*
+ * Read the registry property.
+ */
+ if (GetRegProp(dpy, &regProp, &numItems, TRUE) == FAIL)
+ return NULL;
+
+ /*
+ * Scan all of the names out of the property.
+ */
+ ga_init2(&ga, 1, 100);
+ for (p = regProp; (p - regProp) < numItems; p++)
+ {
+ entry = p;
+ while (*p != 0 && !isspace(*p))
+ p++;
+ if (*p != 0)
+ {
+ w = None;
+ sscanf((char *)entry, "%x", &w);
+ if (WindowValid(dpy, (Window)w))
+ {
+ ga_concat(&ga, p + 1);
+ ga_concat(&ga, (char_u *)"\n");
+ }
+ while (*p != 0)
+ p++;
+ }
+ }
+ if (regProp != empty_prop)
+ XFree(regProp);
+ return ga.ga_data;
+}
+
+/* ----------------------------------------------------------
+ * Reply stuff
+ */
+
+ static struct ServerReply *
+ServerReplyFind(w, op)
+ Window w;
+ enum ServerReplyOp op;
+{
+ struct ServerReply *p;
+ struct ServerReply e;
+ int i;
+
+ p = (struct ServerReply *) serverReply.ga_data;
+ for (i = 0; i < serverReply.ga_len; i++, p++)
+ if (p->id == w)
+ break;
+ if (i >= serverReply.ga_len)
+ p = NULL;
+
+ if (p == NULL && op == SROP_Add)
+ {
+ if (serverReply.ga_growsize == 0)
+ ga_init2(&serverReply, sizeof(struct ServerReply), 1);
+ if (ga_grow(&serverReply, 1) == OK)
+ {
+ p = ((struct ServerReply *) serverReply.ga_data)
+ + serverReply.ga_len;
+ e.id = w;
+ ga_init2(&e.strings, 1, 100);
+ memcpy(p, &e, sizeof(e));
+ serverReply.ga_len++;
+ serverReply.ga_room--;
+ }
+ }
+ else if (p != NULL && op == SROP_Delete)
+ {
+ ga_clear(&p->strings);
+ mch_memmove(p, p + 1, (serverReply.ga_len - i - 1) * sizeof(*p));
+ serverReply.ga_len--;
+ serverReply.ga_room++;
+ }
+
+ return p;
+}
+
+/*
+ * Convert string to windowid.
+ * Issue an error if the id is invalid.
+ */
+ Window
+serverStrToWin(str)
+ char_u *str;
+{
+ unsigned id = None;
+
+ sscanf((char *)str, "0x%x", &id);
+ if (id == None)
+ EMSG2(_("E573: Invalid server id used: %s"), str);
+
+ return (Window)id;
+}
+
+/*
+ * Send a reply string to client with id "name".
+ * Return -1 if the window is invalid.
+ */
+ int
+serverSendReply(name, str)
+ char_u *name;
+ char_u *str;
+{
+ char_u *property;
+ int length;
+ int res;
+ Display *dpy = X_DISPLAY;
+ Window win = serverStrToWin(name);
+
+ if (commProperty == None)
+ {
+ if (SendInit(dpy) < 0)
+ return -2;
+ }
+ if (!WindowValid(dpy, win))
+ return -1;
+
+ length = STRLEN(str) + 7;
+ if ((property = (char_u *)alloc((unsigned) length + 30)) != NULL)
+ {
+ sprintf((char *)property, "%c%c%c-n %s%c-w %x",
+ 0, 'n', 0, str, 0, (unsigned int)commWindow);
+ length += STRLEN(property + length);
+ res = AppendPropCarefully(dpy, win, commProperty, property, length + 1);
+ vim_free(property);
+ return res;
+ }
+ return -1;
+}
+
+ static int
+WaitForReply(p)
+ void *p;
+{
+ Window *w = (Window *) p;
+ return ServerReplyFind(*w, SROP_Find) != NULL;
+}
+
+/*
+ * Wait for replies from id (win)
+ * Return 0 and the malloc'ed string when a reply is available.
+ * Return -1 if the window becomes invalid while waiting.
+ */
+ int
+serverReadReply(dpy, win, str, localLoop)
+ Display *dpy;
+ Window win;
+ char_u **str;
+ int localLoop;
+{
+ int len;
+ char_u *s;
+ struct ServerReply *p;
+
+ ServerWait(dpy, win, WaitForReply, &win, localLoop, -1);
+
+ if ((p = ServerReplyFind(win, SROP_Find)) != NULL && p->strings.ga_len > 0)
+ {
+ *str = vim_strsave(p->strings.ga_data);
+ len = STRLEN(*str) + 1;
+ if (len < p->strings.ga_len)
+ {
+ s = (char_u *) p->strings.ga_data;
+ mch_memmove(s, s + len, p->strings.ga_len - len);
+ p->strings.ga_room += len;
+ p->strings.ga_len -= len;
+ }
+ else
+ {
+ /* Last string read. Remove from list */
+ ga_clear(&p->strings);
+ ServerReplyFind(win, SROP_Delete);
+ }
+ return 0;
+ }
+ return -1;
+}
+
+/*
+ * Check for replies from id (win).
+ * Return TRUE and a non-malloc'ed string if there is. Else return FALSE.
+ */
+ int
+serverPeekReply(dpy, win, str)
+ Display *dpy;
+ Window win;
+ char_u **str;
+{
+ struct ServerReply *p;
+
+ if ((p = ServerReplyFind(win, SROP_Find)) != NULL && p->strings.ga_len > 0)
+ {
+ if (str != NULL)
+ *str = p->strings.ga_data;
+ return 1;
+ }
+ if (!WindowValid(dpy, win))
+ return -1;
+ return 0;
+}
+
+
+/*
+ * Initialize the communication channels for sending commands and receiving
+ * results.
+ */
+ static int
+SendInit(dpy)
+ Display *dpy;
+{
+ XErrorHandler old_handler;
+
+ /*
+ * Create the window used for communication, and set up an
+ * event handler for it.
+ */
+ old_handler = XSetErrorHandler(x_error_check);
+ got_x_error = FALSE;
+
+ if (commProperty == None)
+ commProperty = XInternAtom(dpy, "Comm", False);
+ if (vimProperty == None)
+ vimProperty = XInternAtom(dpy, "Vim", False);
+ if (registryProperty == None)
+ registryProperty = XInternAtom(dpy, "VimRegistry", False);
+
+ if (commWindow == None)
+ {
+ commWindow = XCreateSimpleWindow(dpy, XDefaultRootWindow(dpy),
+ getpid(), 0, 10, 10, 0,
+ WhitePixel(dpy, DefaultScreen(dpy)),
+ WhitePixel(dpy, DefaultScreen(dpy)));
+ XSelectInput(dpy, commWindow, PropertyChangeMask);
+ /* WARNING: Do not step through this while debugging, it will hangup
+ * the X server! */
+ XGrabServer(dpy);
+ DeleteAnyLingerer(dpy, commWindow);
+ XUngrabServer(dpy);
+ }
+
+ /* Make window recognizable as a vim window */
+ XChangeProperty(dpy, commWindow, vimProperty, XA_STRING,
+ 8, PropModeReplace, (char_u *)VIM_VERSION_SHORT,
+ (int)STRLEN(VIM_VERSION_SHORT) + 1);
+
+ XSync(dpy, False);
+ (void)XSetErrorHandler(old_handler);
+
+ return got_x_error ? -1 : 0;
+}
+
+/*
+ * Given a server name, see if the name exists in the registry for a
+ * particular display.
+ *
+ * If the given name is registered, return the ID of the window associated
+ * with the name. If the name isn't registered, then return 0.
+ *
+ * Side effects:
+ * If the registry property is improperly formed, then it is deleted.
+ * If "delete" is non-zero, then if the named server is found it is
+ * removed from the registry property.
+ */
+ static Window
+LookupName(dpy, name, delete, loose)
+ Display *dpy; /* Display whose registry to check. */
+ char_u *name; /* Name of a server. */
+ int delete; /* If non-zero, delete info about name. */
+ char_u **loose; /* Do another search matching -999 if not found
+ Return result here if a match is found */
+{
+ char_u *regProp, *entry;
+ char_u *p;
+ long_u numItems;
+ int_u returnValue;
+
+ /*
+ * Read the registry property.
+ */
+ if (GetRegProp(dpy, &regProp, &numItems, FALSE) == FAIL)
+ return 0;
+
+ /*
+ * Scan the property for the desired name.
+ */
+ returnValue = (int_u)None;
+ entry = NULL; /* Not needed, but eliminates compiler warning. */
+ for (p = regProp; (p - regProp) < numItems; )
+ {
+ entry = p;
+ while (*p != 0 && !isspace(*p))
+ p++;
+ if (*p != 0 && STRICMP(name, p + 1) == 0)
+ {
+ sscanf((char *)entry, "%x", &returnValue);
+ break;
+ }
+ while (*p != 0)
+ p++;
+ p++;
+ }
+
+ if (loose != NULL && returnValue == (int_u)None && !IsSerialName(name))
+ {
+ for (p = regProp; (p - regProp) < numItems; )
+ {
+ entry = p;
+ while (*p != 0 && !isspace(*p))
+ p++;
+ if (*p != 0 && IsSerialName(p + 1)
+ && STRNICMP(name, p + 1, STRLEN(name)) == 0)
+ {
+ sscanf((char *)entry, "%x", &returnValue);
+ *loose = vim_strsave(p + 1);
+ break;
+ }
+ while (*p != 0)
+ p++;
+ p++;
+ }
+ }
+
+ /*
+ * Delete the property, if that is desired (copy down the
+ * remainder of the registry property to overlay the deleted
+ * info, then rewrite the property).
+ */
+ if (delete && returnValue != (int_u)None)
+ {
+ int count;
+
+ while (*p != 0)
+ p++;
+ p++;
+ count = numItems - (p - regProp);
+ if (count > 0)
+ memcpy(entry, p, count);
+ XChangeProperty(dpy, RootWindow(dpy, 0), registryProperty, XA_STRING,
+ 8, PropModeReplace, regProp,
+ (int)(numItems - (p - entry)));
+ XSync(dpy, False);
+ }
+
+ if (regProp != empty_prop)
+ XFree(regProp);
+ return (Window)returnValue;
+}
+
+/*
+ * Delete any lingering occurences of window id. We promise that any
+ * occurences is not ours since it is not yet put into the registry (by us)
+ *
+ * This is necessary in the following scenario:
+ * 1. There is an old windowid for an exit'ed vim in the registry
+ * 2. We get that id for our commWindow but only want to send, not register.
+ * 3. The window will mistakenly be regarded valid because of own commWindow
+ */
+ static void
+DeleteAnyLingerer(dpy, win)
+ Display *dpy; /* Display whose registry to check. */
+ Window win; /* Window to remove */
+{
+ char_u *regProp, *entry = NULL;
+ char_u *p;
+ long_u numItems;
+ Window wwin;
+
+ /*
+ * Read the registry property.
+ */
+ if (GetRegProp(dpy, &regProp, &numItems, FALSE) == FAIL)
+ return;
+
+ /* Scan the property for the window id. */
+ for (p = regProp; (p - regProp) < numItems; )
+ {
+ if (*p != 0)
+ {
+ sscanf((char *)p, "%x", (int_u *)&wwin);
+ if (wwin == win)
+ {
+ int lastHalf;
+
+ /* Copy down the remainder to delete entry */
+ entry = p;
+ while (*p != 0)
+ p++;
+ p++;
+ lastHalf = numItems - (p - regProp);
+ if (lastHalf > 0)
+ memcpy(entry, p, lastHalf);
+ numItems = (entry - regProp) + lastHalf;
+ p = entry;
+ continue;
+ }
+ }
+ while (*p != 0)
+ p++;
+ p++;
+ }
+
+ if (entry != NULL)
+ {
+ XChangeProperty(dpy, RootWindow(dpy, 0), registryProperty,
+ XA_STRING, 8, PropModeReplace, regProp,
+ (int)(p - regProp));
+ XSync(dpy, False);
+ }
+
+ if (regProp != empty_prop)
+ XFree(regProp);
+}
+
+/*
+ * Read the registry property. Delete it when it's formatted wrong.
+ * Return the property in "regPropp". "empty_prop" is used when it doesn't
+ * exist yet.
+ * Return OK when successful.
+ */
+ static int
+GetRegProp(dpy, regPropp, numItemsp, domsg)
+ Display *dpy;
+ char_u **regPropp;
+ long_u *numItemsp;
+ int domsg; /* When TRUE give error message. */
+{
+ int result, actualFormat;
+ long_u bytesAfter;
+ Atom actualType;
+
+ *regPropp = NULL;
+ result = XGetWindowProperty(dpy, RootWindow(dpy, 0), registryProperty, 0L,
+ (long)MAX_PROP_WORDS, False,
+ XA_STRING, &actualType,
+ &actualFormat, numItemsp, &bytesAfter,
+ regPropp);
+
+ if (actualType == None)
+ {
+ /* No prop yet. Logically equal to the empty list */
+ *numItemsp = 0;
+ *regPropp = empty_prop;
+ return OK;
+ }
+
+ /* If the property is improperly formed, then delete it. */
+ if (result != Success || actualFormat != 8 || actualType != XA_STRING)
+ {
+ if (*regPropp != NULL)
+ XFree(*regPropp);
+ XDeleteProperty(dpy, RootWindow(dpy, 0), registryProperty);
+ if (domsg)
+ EMSG(_("E251: VIM instance registry property is badly formed. Deleted!"));
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
+ * This procedure is invoked by the varous X event loops throughout Vims when
+ * a property changes on the communication window. This procedure reads the
+ * property and handles command requests and responses.
+ */
+ void
+serverEventProc(dpy, eventPtr)
+ Display *dpy;
+ XEvent *eventPtr; /* Information about event. */
+{
+ char_u *propInfo;
+ char_u *p;
+ int result, actualFormat, code;
+ long_u numItems, bytesAfter;
+ Atom actualType;
+
+ if (eventPtr != NULL)
+ {
+ if (eventPtr->xproperty.atom != commProperty
+ || eventPtr->xproperty.state != PropertyNewValue)
+ return;
+ }
+
+ /*
+ * Read the comm property and delete it.
+ */
+ propInfo = NULL;
+ result = XGetWindowProperty(dpy, commWindow, commProperty, 0L,
+ (long)MAX_PROP_WORDS, True,
+ XA_STRING, &actualType,
+ &actualFormat, &numItems, &bytesAfter,
+ &propInfo);
+
+ /* If the property doesn't exist or is improperly formed then ignore it. */
+ if (result != Success || actualType != XA_STRING || actualFormat != 8)
+ {
+ if (propInfo != NULL)
+ XFree(propInfo);
+ return;
+ }
+
+ /*
+ * Several commands and results could arrive in the property at
+ * one time; each iteration through the outer loop handles a
+ * single command or result.
+ */
+ for (p = propInfo; (p - propInfo) < numItems; )
+ {
+ /*
+ * Ignore leading NULs; each command or result starts with a
+ * NUL so that no matter how badly formed a preceding command
+ * is, we'll be able to tell that a new command/result is
+ * starting.
+ */
+ if (*p == 0)
+ {
+ p++;
+ continue;
+ }
+
+ if ((*p == 'c' || *p == 'k') && (p[1] == 0))
+ {
+ Window resWindow;
+ char_u *name, *script, *serial, *end, *res;
+ Bool asKeys = *p == 'k';
+ garray_T reply;
+
+ /*
+ * This is an incoming command from some other application.
+ * Iterate over all of its options. Stop when we reach
+ * the end of the property or something that doesn't look
+ * like an option.
+ */
+ p += 2;
+ name = NULL;
+ resWindow = None;
+ serial = (char_u *)"";
+ script = NULL;
+ while (p - propInfo < numItems && *p == '-')
+ {
+ switch (p[1])
+ {
+ case 'r':
+ end = skipwhite(p + 2);
+ resWindow = 0;
+ while (vim_isxdigit(*end))
+ {
+ resWindow = 16 * resWindow + (long_u)hex2nr(*end);
+ ++end;
+ }
+ if (end == p + 2 || *end != ' ')
+ resWindow = None;
+ else
+ {
+ p = serial = end + 1;
+ clientWindow = resWindow; /* Remember in global */
+ }
+ break;
+ case 'n':
+ if (p[2] == ' ')
+ name = p + 3;
+ break;
+ case 's':
+ if (p[2] == ' ')
+ script = p + 3;
+ break;
+ }
+ while (*p != 0)
+ p++;
+ p++;
+ }
+
+ if (script == NULL || name == NULL)
+ continue;
+
+ /*
+ * Initialize the result property, so that we're ready at any
+ * time if we need to return an error.
+ */
+ if (resWindow != None)
+ {
+ ga_init2(&reply, 1, 100);
+ ga_grow(&reply, 50);
+ sprintf(reply.ga_data, "%cr%c-s %s%c-r ", 0, 0, serial, 0);
+ reply.ga_len = 10 + STRLEN(serial);
+ reply.ga_room -= reply.ga_len;
+ }
+ res = NULL;
+ if (serverName != NULL && STRICMP(name, serverName) == 0)
+ {
+ if (asKeys)
+ server_to_input_buf(script);
+ else
+ res = eval_client_expr_to_string(script);
+ }
+ if (resWindow != None)
+ {
+ if (res != NULL)
+ ga_concat(&reply, res);
+ else if (asKeys == 0)
+ {
+ ga_concat(&reply, (char_u *)_(e_invexprmsg));
+ ga_append(&reply, 0);
+ ga_concat(&reply, (char_u *)"-c 1");
+ }
+ ga_append(&reply, 0);
+ (void)AppendPropCarefully(dpy, resWindow, commProperty,
+ reply.ga_data, reply.ga_len);
+ }
+ vim_free(res);
+ }
+ else if (*p == 'r' && p[1] == 0)
+ {
+ int serial, gotSerial;
+ char_u *res;
+ PendingCommand *pcPtr;
+
+ /*
+ * This is a reply to some command that we sent out. Iterate
+ * over all of its options. Stop when we reach the end of the
+ * property or something that doesn't look like an option.
+ */
+ p += 2;
+ gotSerial = 0;
+ res = (char_u *)"";
+ code = 0;
+ while ((p-propInfo) < numItems && *p == '-')
+ {
+ switch (p[1])
+ {
+ case 'r':
+ if (p[2] == ' ')
+ res = p + 3;
+ break;
+ case 's':
+ if (sscanf((char *)p + 2, " %d", &serial) == 1)
+ gotSerial = 1;
+ break;
+ case 'c':
+ if (sscanf((char *)p + 2, " %d", &code) != 1)
+ code = 0;
+ break;
+ }
+ while (*p != 0)
+ p++;
+ p++;
+ }
+
+ if (!gotSerial)
+ continue;
+
+ /*
+ * Give the result information to anyone who's
+ * waiting for it.
+ */
+ for (pcPtr = pendingCommands; pcPtr != NULL; pcPtr = pcPtr->nextPtr)
+ {
+ if (serial != pcPtr->serial || pcPtr->result != NULL)
+ continue;
+
+ pcPtr->code = code;
+ if (res != NULL)
+ pcPtr->result = vim_strsave(res);
+ else
+ pcPtr->result = vim_strsave((char_u *)"");
+ break;
+ }
+ }
+ else if (*p == 'n' && p[1] == 0)
+ {
+ Window win = 0;
+ unsigned int u;
+ int gotWindow;
+ char_u *str;
+ char_u winstr[30];
+ struct ServerReply *r;
+
+ /*
+ * This is a (n)otification. Sent with serverreply_send in VimL.
+ * Execute any autocommand and save it for later retrieval
+ */
+ p += 2;
+ gotWindow = 0;
+ str = (char_u *)"";
+ while ((p-propInfo) < numItems && *p == '-')
+ {
+ switch (p[1])
+ {
+ case 'n':
+ if (p[2] == ' ')
+ str = p + 3;
+ break;
+ case 'w':
+ if (sscanf((char *)p + 2, " %x", &u) == 1)
+ {
+ win = u;
+ gotWindow = 1;
+ }
+ break;
+ }
+ while (*p != 0)
+ p++;
+ p++;
+ }
+
+ if (!gotWindow)
+ continue;
+ if ((r = ServerReplyFind(win, SROP_Add)) != NULL)
+ {
+ ga_concat(&(r->strings), str);
+ ga_append(&(r->strings), 0);
+ }
+#ifdef FEAT_AUTOCMD
+ sprintf((char *)winstr, "0x%x", (unsigned int)win);
+ apply_autocmds(EVENT_REMOTEREPLY, winstr, str, TRUE, curbuf);
+#endif
+
+ }
+ else
+ {
+ /*
+ * Didn't recognize this thing. Just skip through the next
+ * null character and try again.
+ * Even if we get an 'r'(eply) we will throw it away as we
+ * never specify (and thus expect) one
+ */
+ while (*p != 0)
+ p++;
+ p++;
+ }
+ }
+ XFree(propInfo);
+}
+
+/*
+ * Append a given property to a given window, but set up an X error handler so
+ * that if the append fails this procedure can return an error code rather
+ * than having Xlib panic.
+ * Return: 0 for OK, -1 for error
+ */
+ static int
+AppendPropCarefully(dpy, window, property, value, length)
+ Display *dpy; /* Display on which to operate. */
+ Window window; /* Window whose property is to be modified. */
+ Atom property; /* Name of property. */
+ char_u *value; /* Characters to append to property. */
+ int length; /* How much to append */
+{
+ XErrorHandler old_handler;
+
+ old_handler = XSetErrorHandler(x_error_check);
+ got_x_error = FALSE;
+ XChangeProperty(dpy, window, property, XA_STRING, 8,
+ PropModeAppend, value, length);
+ XSync(dpy, False);
+ (void) XSetErrorHandler(old_handler);
+ return got_x_error ? -1 : 0;
+}
+
+
+/*
+ * Another X Error handler, just used to check for errors.
+ */
+/* ARGSUSED */
+ static int
+x_error_check(dpy, error_event)
+ Display *dpy;
+ XErrorEvent *error_event;
+{
+ got_x_error = TRUE;
+ return 0;
+}
+
+/*
+ * Check if "str" looks like it had a serial number appended.
+ * Actually just checks if the name ends in a digit.
+ */
+ static int
+IsSerialName(str)
+ char_u *str;
+{
+ int len = STRLEN(str);
+
+ return (len > 1 && vim_isdigit(str[len - 1]));
+}
+#endif /* FEAT_CLIENTSERVER */
diff --git a/src/iid_ole.c b/src/iid_ole.c
new file mode 100644
index 000000000..6ade213fe
--- /dev/null
+++ b/src/iid_ole.c
@@ -0,0 +1,50 @@
+/* this file contains the actual definitions of */
+/* the IIDs and CLSIDs */
+
+/* link this file in with the server and any clients */
+
+
+/* File created by MIDL compiler version 3.00.44 */
+/* at Sat Jan 03 16:34:55 1998
+ */
+/* Compiler settings for if_ole.idl:
+ Os (OptLev=s), W1, Zp8, env=Win32, ms_ext, c_ext
+ error checks: none
+*/
+//@@MIDL_FILE_HEADING( )
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+#ifndef __IID_DEFINED__
+#define __IID_DEFINED__
+
+typedef struct _IID
+{
+ unsigned long x;
+ unsigned short s1;
+ unsigned short s2;
+ unsigned char c[8];
+} IID;
+
+#endif // __IID_DEFINED__
+
+#ifndef CLSID_DEFINED
+#define CLSID_DEFINED
+typedef IID CLSID;
+#endif // CLSID_DEFINED
+
+const IID IID_IVim = {0x0F0BFAE2,0x4C90,0x11d1,{0x82,0xD7,0x00,0x04,0xAC,0x36,0x85,0x19}};
+
+
+const IID LIBID_Vim = {0x0F0BFAE0,0x4C90,0x11d1,{0x82,0xD7,0x00,0x04,0xAC,0x36,0x85,0x19}};
+
+
+const CLSID CLSID_Vim = {0x0F0BFAE1,0x4C90,0x11d1,{0x82,0xD7,0x00,0x04,0xAC,0x36,0x85,0x19}};
+
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/infplist.xml b/src/infplist.xml
new file mode 100644
index 000000000..f0ba5fc58
--- /dev/null
+++ b/src/infplist.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vim:set ts=2 sts=2 sw=2 tw=0: -->
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+ <dict>
+
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+
+ <key>CFBundleExecutable</key>
+ <string>APP_EXE</string>
+ <key>CFBundleName</key>
+ <string>APP_NAME</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleVersion</key>
+ <string>APP_VER</string>
+ <key>CFBundleShortVersionString</key>
+ <string>APP_VER</string>
+ <key>CFBundleSignature</key>
+ <string>VIM!</string>
+
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+ <key>CFBundleIconFile</key>
+ <string>ICON_APP</string>
+
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>*</string>
+ </array>
+ <key>CFBundleTypeIconFile</key>
+ <string>doc-txt.icns</string>
+ <key>CFBundleTypeName</key>
+ <string>NSStringPboardType</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>****</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ </array>
+
+ </dict>
+</plist>
diff --git a/src/integration.c b/src/integration.c
new file mode 100644
index 000000000..05a9dec3f
--- /dev/null
+++ b/src/integration.c
@@ -0,0 +1,1198 @@
+/* vi:set ts=8 sw=8:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Visual Workshop integration by Gordon Prieur
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * Integration with Sun Workshop.
+ *
+ * This file should not change much, it's also used by other editors that
+ * connect to Workshop. Consider changing workshop.c instead.
+ */
+/*
+-> consider using MakeSelectionVisible instead of gotoLine hacks
+ to show the line properly
+ -> consider using glue instead of our own message wrapping functions
+ (but can only use glue if we don't have to distribute source)
+*/
+
+#include "vim.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+
+#ifdef INET_SOCKETS
+#include <netdb.h>
+#include <netinet/in.h>
+#else
+#include <sys/un.h>
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#ifdef HAVE_LIBGEN_H
+# include <libgen.h>
+#endif
+#include <unistd.h>
+#include <string.h>
+
+#include <X11/Intrinsic.h>
+#include <Xm/Xm.h>
+#include <Xm/AtomMgr.h>
+#include <Xm/PushB.h>
+
+#ifdef HAVE_X11_XPM_H
+# include <X11/xpm.h>
+#else
+# ifdef HAVE_XM_XPMP_H
+# include <Xm/XpmP.h>
+# endif
+#endif
+
+#ifdef HAVE_UTIL_DEBUG_H
+# include <util/debug.h>
+#endif
+#ifdef HAVE_UTIL_MSGI18N_H
+# include <util/msgi18n.h>
+#endif
+
+#include "integration.h" /* <EditPlugin/integration.h> */
+#ifdef HAVE_FRAME_H
+# include <frame.h>
+#endif
+
+#ifndef MAX
+# define MAX(a, b) (a) > (b) ? (a) : (b)
+#endif
+
+#ifndef NOCATGETS
+# define NOCATGETS(x) x
+#endif
+
+/* Functions private to this file */
+static void workshop_connection_closed(void);
+static void messageFromEserve(XtPointer clientData, int *NOTUSED1, XtInputId *NOTUSED2);
+static void workshop_disconnect(void);
+static void workshop_sensitivity(int num, char *table);
+static void adjust_sign_name(char *filename);
+static void process_menuItem(char *);
+static void process_toolbarButton(char *);
+static void workshop_set_option_first(char *name, char *value);
+
+
+#define CMDBUFSIZ 2048
+
+#ifdef DEBUG
+static FILE *dfd;
+static void pldebug(char *, ...);
+static void unrecognised_message(char *);
+
+#define HANDLE_ERRORS(cmd) else unrecognised_message(cmd);
+#else
+#define HANDLE_ERRORS(cmd)
+#endif
+
+/*
+ * Version number of the protocol between an editor and eserve.
+ * This number should be incremented when the protocol
+ * is changed.
+ */
+#define PROTOCOL_VERSION "4.0.0"
+
+static int sd = -1;
+static XtInputId inputHandler; /* Cookie for input */
+
+Boolean save_files = True; /* When true, save all files before build actions */
+
+void
+workshop_connection_closed(void)
+{
+ /*
+ * socket closed on other end
+ */
+ XtRemoveInput(inputHandler);
+ inputHandler = 0;
+ sd = -1;
+}
+
+ static char *
+getCommand(void)
+{
+ int len; /* length of this command */
+ char lenbuf[7]; /* get the length string here */
+ char *newcb; /* used to realloc cmdbuf */
+ static char *cmdbuf;/* get the command string here */
+ static int cbsize;/* size of cmdbuf */
+
+ if ((len = read(sd, &lenbuf, 6)) == 6) {
+ lenbuf[6] = 0; /* Terminate buffer such that atoi() works right */
+ len = atoi(lenbuf);
+ if (cbsize < (len + 1)) {
+ newcb = (char *) realloc(cmdbuf,
+ MAX((len + 256), CMDBUFSIZ));
+ if (newcb != NULL) {
+ cmdbuf = newcb;
+ cbsize = MAX((len + 256), CMDBUFSIZ);
+ }
+ }
+ if (cbsize >= len && (len = read(sd, cmdbuf, len)) > 0) {
+ cmdbuf[len] = 0;
+ return cmdbuf;
+ } else {
+ return NULL;
+ }
+ } else {
+ if (len == 0) { /* EOF */
+ workshop_connection_closed();
+ }
+ return NULL;
+ }
+
+}
+
+/*ARGSUSED*/
+void
+messageFromEserve(XtPointer clientData, int *NOTUSED1, XtInputId *NOTUSED2)
+{
+ char *cmd; /* the 1st word of the command */
+
+ cmd = getCommand();
+ if (cmd == NULL) {
+ /* We're being shut down by eserve and the "quit" message
+ * didn't arrive before the socket connection got closed */
+ return;
+ }
+#ifdef DEBUG
+ pldebug("%s\n", cmd);
+#endif
+ switch (*cmd) {
+ case 'a':
+ if (cmd[1] == 'c' &&
+ strncmp(cmd, NOCATGETS("ack "), 4) == 0) {
+ int ackNum;
+ char buf[20];
+
+ ackNum = atoi(&cmd[4]);
+ sprintf(buf, NOCATGETS("ack %d\n"), ackNum);
+ write(sd, buf, strlen(buf));
+ } else if (strncmp(cmd,
+ NOCATGETS("addMarkType "), 12) == 0) {
+ int idx;
+ char *color;
+ char *sign;
+
+ idx = atoi(strtok(&cmd[12], " "));
+ color = strtok(NULL, NOCATGETS("\001"));
+ sign = strtok(NULL, NOCATGETS("\001"));
+ /* Skip space that separates names */
+ if (color) {
+ color++;
+ }
+ if (sign) {
+ sign++;
+ }
+ /* Change sign name to accomodate a different size? */
+ adjust_sign_name(sign);
+ workshop_add_mark_type(idx, color, sign);
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 'b':
+ if (strncmp(cmd,
+ NOCATGETS("balloon "), 8) == 0) {
+ char *tip;
+
+ tip = strtok(&cmd[8], NOCATGETS("\001"));
+ workshop_show_balloon_tip(tip);
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 'c':
+ if (strncmp(cmd,
+ NOCATGETS("changeMarkType "), 15) == 0) {
+ char *file;
+ int markId;
+ int type;
+
+ file = strtok(&cmd[15], " ");
+ markId = atoi(strtok(NULL, " "));
+ type = atoi(strtok(NULL, " "));
+ workshop_change_mark_type(file, markId, type);
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 'd':
+ if (strncmp(cmd, NOCATGETS("deleteMark "), 11) == 0) {
+ char *file;
+ int markId;
+
+ file = strtok(&cmd[11], " ");
+ markId = atoi(strtok(NULL, " "));
+ workshop_delete_mark(file, markId);
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 'f':
+ if (cmd[1] == 'o' &&
+ strncmp(cmd, NOCATGETS("footerMsg "), 10) == 0) {
+ int severity;
+ char *message;
+
+ severity =
+ atoi(strtok(&cmd[10], " "));
+ message = strtok(NULL, NOCATGETS("\001"));
+
+ workshop_footer_message(message, severity);
+ } else if (strncmp(cmd,
+ NOCATGETS("frontFile "), 10) == 0) {
+ char *file;
+
+ file = strtok(&cmd[10], " ");
+ workshop_front_file(file);
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 'g':
+ if (cmd[1] == 'e' &&
+ strncmp(cmd, NOCATGETS("getMarkLine "), 12) == 0) {
+ char *file;
+ int markid;
+ int line;
+ char buf[100];
+
+ file = strtok(&cmd[12], " ");
+ markid = atoi(strtok(NULL, " "));
+ line = workshop_get_mark_lineno(file, markid);
+ sprintf(buf, NOCATGETS("markLine %s %d %d\n"),
+ file, markid, line);
+ write(sd, buf, strlen(buf));
+ } else if (cmd[1] == 'o' && cmd[4] == 'L' &&
+ strncmp(cmd, NOCATGETS("gotoLine "), 9) == 0) {
+ char *file;
+ int lineno;
+
+ file = strtok(&cmd[9], " ");
+ lineno = atoi(strtok(NULL, " "));
+ workshop_goto_line(file, lineno);
+ } else if (strncmp(cmd,
+ NOCATGETS("gotoMark "), 9) == 0) {
+ char *file;
+ int markId;
+ char *message;
+
+ file = strtok(&cmd[9], " ");
+ markId = atoi(strtok(NULL, " "));
+ message = strtok(NULL, NOCATGETS("\001"));
+ workshop_goto_mark(file, markId, message);
+#ifdef NOHANDS_SUPPORT_FUNCTIONS
+ } else if (strcmp(cmd, NOCATGETS("getCurrentFile")) == 0) {
+ char *f = workshop_test_getcurrentfile();
+ char buffer[2*MAXPATHLEN];
+ sprintf(buffer, NOCATGETS("currentFile %d %s"),
+ f ? strlen(f) : 0, f ? f : "");
+ workshop_send_message(buffer);
+ } else if (strcmp(cmd, NOCATGETS("getCursorRow")) == 0) {
+ int row = workshop_test_getcursorrow();
+ char buffer[2*MAXPATHLEN];
+ sprintf(buffer, NOCATGETS("cursorRow %d"), row);
+ workshop_send_message(buffer);
+ } else if (strcmp(cmd, NOCATGETS("getCursorCol")) == 0) {
+ int col = workshop_test_getcursorcol();
+ char buffer[2*MAXPATHLEN];
+ sprintf(buffer, NOCATGETS("cursorCol %d"), col);
+ workshop_send_message(buffer);
+ } else if (strcmp(cmd, NOCATGETS("getCursorRowText")) == 0) {
+ char *t = workshop_test_getcursorrowtext();
+ char buffer[2*MAXPATHLEN];
+ sprintf(buffer, NOCATGETS("cursorRowText %d %s"),
+ t ? strlen(t) : 0, t ? t : "");
+ workshop_send_message(buffer);
+ } else if (strcmp(cmd, NOCATGETS("getSelectedText")) == 0) {
+ char *t = workshop_test_getselectedtext();
+ char buffer[2*MAXPATHLEN];
+ sprintf(buffer, NOCATGETS("selectedText %d %s"),
+ t ? strlen(t) : 0, t ? t : "");
+ workshop_send_message(buffer);
+#endif
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 'l':
+ if (strncmp(cmd, NOCATGETS("loadFile "), 9) == 0) {
+ char *file;
+ int line;
+ char *frameid;
+
+ file = strtok(&cmd[9], " ");
+ line = atoi(strtok(NULL, " "));
+ frameid = strtok(NULL, " ");
+ workshop_load_file(file, line, frameid);
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 'm': /* Menu, minimize, maximize */
+ if (cmd[1] == 'e' && cmd[4] == 'B' &&
+ strncmp(cmd, NOCATGETS("menuBegin "), 10) == 0) {
+ workshop_menu_begin(&cmd[10]);
+ } else if (cmd[1] == 'e' && cmd[4] == 'I' &&
+ strncmp(cmd, NOCATGETS("menuItem "), 9) == 0) {
+ process_menuItem(cmd);
+ } else if (cmd[1] == 'e' && cmd[4] == 'E' &&
+ strcmp(cmd, NOCATGETS("menuEnd")) == 0) {
+ workshop_menu_end();
+ } else if (cmd[1] == 'a' &&
+ strcmp(cmd, NOCATGETS("maximize")) == 0) {
+ workshop_maximize();
+ } else if (strcmp(cmd, NOCATGETS("minimize")) == 0) {
+ workshop_minimize();
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 'o':
+ if (cmd[1] == 'p' &&
+ strcmp(cmd, NOCATGETS("option"))) {
+ char *name;
+ char *value;
+
+ name = strtok(&cmd[7], " ");
+ value = strtok(NULL, " ");
+ workshop_set_option_first(name, value);
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 'p':
+ if (strcmp(cmd, NOCATGETS("ping")) == 0) {
+#if 0
+ int pingNum;
+
+ pingNum = atoi(&cmd[5]);
+ workshop_send_ack(ackNum);
+ WHAT DO I DO HERE?
+#endif
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 'q':
+ if (strncmp(cmd, NOCATGETS("quit"), 4) == 0) {
+
+ /* Close the connection. It's important to do
+ * that now, since workshop_quit might be
+ * looking at open files. For example, if you
+ * have modified one of the files without
+ * saving, NEdit will ask you what you want to
+ * do, and spin loop by calling
+ * XtAppProcessEvent while waiting for your
+ * reply. In this case, if we still have an
+ * input handler and the socket has been
+ * closed on the other side when eserve
+ * expired, we will hang in IoWait.
+ */
+ workshop_disconnect();
+
+ workshop_quit();
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 'r':
+ if (cmd[1] == 'e' &&
+ strncmp(cmd, NOCATGETS("reloadFile "), 11) == 0) {
+ char *file;
+ int line;
+
+ file = strtok(&cmd[11], " ");
+ line = atoi(strtok(NULL, " "));
+ workshop_reload_file(file, line);
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 's':
+ if (cmd[1] == 'e' && cmd[2] == 't' &&
+ strncmp(cmd, NOCATGETS("setMark "), 8) == 0) {
+ char *file;
+ int line;
+ int markId;
+ int type;
+
+ file = strtok(&cmd[8], " ");
+ line = atoi(strtok(NULL, " "));
+ markId = atoi(strtok(NULL, " "));
+ type = atoi(strtok(NULL, " "));
+ workshop_set_mark(file, line, markId, type);
+ } else if (cmd[1] == 'h' &&
+ strncmp(cmd, NOCATGETS("showFile "), 9) == 0) {
+ workshop_show_file(&cmd[9]);
+ } else if (cmd[1] == 'u' &&
+ strncmp(cmd, NOCATGETS("subMenu "), 8) == 0) {
+ char *label;
+
+ label = strtok(&cmd[8], NOCATGETS("\001"));
+ workshop_submenu_begin(label);
+ } else if (cmd[1] == 'u' &&
+ strcmp(cmd, NOCATGETS("subMenuEnd")) == 0) {
+ workshop_submenu_end();
+ } else if (cmd[1] == 'e' && cmd[2] == 'n' &&
+ strncmp(cmd, NOCATGETS("sensitivity "), 12) == 0) {
+ int num;
+ char *bracket;
+ char *table;
+
+ num = atoi(strtok(&cmd[12], " "));
+ bracket = strtok(NULL, " ");
+ if (*bracket != '[') {
+ fprintf(stderr, NOCATGETS("Parsing "
+ "error for sensitivity\n"));
+ } else {
+ table = strtok(NULL, NOCATGETS("]"));
+ workshop_sensitivity(num, table);
+ }
+ } else if (cmd[1] == 'e' && cmd[2] == 'n' && cmd[3] == 'd' &&
+ strncmp(cmd, NOCATGETS("sendVerb "), 9) == 0) {
+ /* Send the given verb back (used for the
+ * debug.lineno callback (such that other tools
+ * can obtain the position coordinates or the
+ * selection) */
+ char *verb;
+
+ verb = strtok(&cmd[9], " ");
+ workshop_perform_verb(verb, NULL);
+ } else if (cmd[1] == 'a' &&
+ strncmp(cmd, NOCATGETS("saveFile "), 9) == 0) {
+ workshop_save_file(&cmd[9]);
+#ifdef NOHANDS_SUPPORT_FUNCTIONS
+ } else if (strncmp(cmd, NOCATGETS("saveSensitivity "), 16) == 0) {
+ char *file;
+
+ file = strtok(&cmd[16], " ");
+ workshop_save_sensitivity(file);
+#endif
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+ case 't': /* Toolbar */
+ if (cmd[8] == 'e' &&
+ strncmp(cmd, NOCATGETS("toolbarBegin"), 12) == 0) {
+ workshop_toolbar_begin();
+ } else if (cmd[8] == 'u' &&
+ strncmp(cmd, NOCATGETS("toolbarButton"), 13) == 0) {
+ process_toolbarButton(cmd);
+ } else if (cmd[7] == 'E' &&
+ strcmp(cmd, NOCATGETS("toolbarEnd")) == 0) {
+ workshop_toolbar_end();
+ }
+ HANDLE_ERRORS(cmd);
+ break;
+
+#ifdef DEBUG
+ default:
+ unrecognised_message(cmd);
+ break;
+#endif
+ }
+}
+
+static void
+process_menuItem(
+ char *cmd)
+{
+ char *label = strtok(&cmd[9], NOCATGETS("\001"));
+ char *verb = strtok(NULL, NOCATGETS("\001"));
+ char *acc = strtok(NULL, NOCATGETS("\001"));
+ char *accText = strtok(NULL, NOCATGETS("\001"));
+ char *name = strtok(NULL, NOCATGETS("\001"));
+ char *sense = strtok(NULL, NOCATGETS("\n"));
+ char *filepos = strtok(NULL, NOCATGETS("\n"));
+ if (*acc == '-') {
+ acc = NULL;
+ }
+ if (*accText == '-') {
+ accText = NULL;
+ }
+ workshop_menu_item(label, verb, acc, accText, name, filepos, sense);
+
+}
+
+
+static void
+process_toolbarButton(
+ char *cmd) /* button definition */
+{
+ char *label = strtok(&cmd[14], NOCATGETS("\001"));
+ char *verb = strtok(NULL, NOCATGETS("\001"));
+ char *senseVerb = strtok(NULL, NOCATGETS("\001"));
+ char *filepos = strtok(NULL, NOCATGETS("\001"));
+ char *help = strtok(NULL, NOCATGETS("\001"));
+ char *sense = strtok(NULL, NOCATGETS("\001"));
+ char *file = strtok(NULL, NOCATGETS("\001"));
+ char *left = strtok(NULL, NOCATGETS("\n"));
+
+ if (!strcmp(label, NOCATGETS("-"))) {
+ label = NULL;
+ }
+ if (!strcmp(help, NOCATGETS("-"))) {
+ help = NULL;
+ }
+ if (!strcmp(file, NOCATGETS("-"))) {
+ file = NULL;
+ }
+ if (!strcmp(senseVerb, NOCATGETS("-"))) {
+ senseVerb = NULL;
+ }
+ workshop_toolbar_button(label, verb, senseVerb, filepos, help,
+ sense, file, left);
+}
+
+
+#ifdef DEBUG
+void
+unrecognised_message(
+ char *cmd)
+{
+ pldebug("Unrecognised eserve message:\n\t%s\n", cmd);
+ /* abort(); */
+}
+#endif
+
+
+/* Change sign name to accomodate a different size:
+ * Create the filename based on the height. The filename format
+ * of multisize icons are:
+ * x.xpm : largest icon
+ * x1.xpm : smaller icon
+ * x2.xpm : smallest icon */
+ void
+adjust_sign_name(char *filename)
+{
+ char *s;
+ static int fontSize = -1;
+
+ if (fontSize == -1)
+ fontSize = workshop_get_font_height();
+ if (fontSize == 0)
+ return;
+ if (filename[0] == '-')
+ return;
+
+ /* This is ugly: later we should instead pass the fontheight over
+ * to eserve on startup and let eserve just send the right filenames
+ * to us in the first place
+
+ * I know that the filename will end with 1.xpm (see
+ * GuiEditor.cc`LispPrintSign if you wonder why) */
+ s = filename+strlen(filename)-5;
+ if (fontSize <= 11)
+ strcpy(s, "2.xpm");
+ else if (fontSize <= 15)
+ strcpy(s, "1.xpm");
+ else
+ strcpy(s, ".xpm");
+}
+
+/* Were we invoked by WorkShop? This function can be used early during startup
+ if you want to do things differently if the editor is started standalone
+ or in WorkShop mode. For example, in standalone mode you may not want to
+ add a footer/message area or a sign gutter. */
+int
+workshop_invoked()
+{
+ static int result = -1;
+ if (result == -1) {
+ result = (getenv(NOCATGETS("SPRO_EDITOR_SOCKET")) != NULL);
+ }
+ return result;
+}
+
+/* Connect back to eserve */
+void workshop_connect(XtAppContext context)
+{
+#ifdef INET_SOCKETS
+ struct sockaddr_in server;
+ struct hostent * host;
+ int port;
+#else
+ struct sockaddr_un server;
+#endif
+ char buf[32];
+ char * address;
+#ifdef DEBUG
+ char *file;
+#endif
+
+ address = getenv(NOCATGETS("SPRO_EDITOR_SOCKET"));
+ if (address == NULL) {
+ return;
+ }
+
+#ifdef INET_SOCKETS
+ port = atoi(address);
+
+ if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+ PERROR(NOCATGETS("workshop_connect"));
+ return;
+ }
+
+ /* Get the server internet address and put into addr structure */
+ /* fill in the socket address structure and connect to server */
+ memset((char *)&server, '\0', sizeof(server));
+ server.sin_family = AF_INET;
+ server.sin_port = port;
+ if ((host = gethostbyname(NOCATGETS("localhost"))) == NULL) {
+ PERROR(NOCATGETS("gethostbyname"));
+ sd = -1;
+ return;
+ }
+ memcpy((char *)&server.sin_addr, host->h_addr, host->h_length);
+#else
+ if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ PERROR(NOCATGETS("workshop_connect"));
+ return;
+ }
+
+ server.sun_family = AF_UNIX;
+ strcpy(server.sun_path, address);
+#endif
+ /* Connect to server */
+ if (connect(sd, (struct sockaddr *)&server, sizeof(server))) {
+ if (errno == ECONNREFUSED) {
+ close(sd);
+#ifdef INET_SOCKETS
+ if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+ PERROR(NOCATGETS("workshop_connect"));
+ return;
+ }
+#else
+ if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ PERROR(NOCATGETS("workshop_connect"));
+ return;
+ }
+#endif
+ if (connect(sd, (struct sockaddr *)&server,
+ sizeof(server))) {
+ PERROR(NOCATGETS("workshop_connect"));
+ return;
+ }
+
+ } else {
+ PERROR(NOCATGETS("workshop_connect"));
+ return;
+ }
+ }
+
+ /* tell notifier we are interested in being called
+ * when there is input on the editor connection socket
+ */
+ inputHandler = XtAppAddInput(context, sd, (XtPointer) XtInputReadMask,
+ messageFromEserve, NULL);
+#ifdef DEBUG
+ if ((file = getenv(NOCATGETS("SPRO_PLUGIN_DEBUG"))) != NULL) {
+ char buf[BUFSIZ];
+
+ unlink(file);
+ sprintf(buf, "date > %s", file);
+ system(buf);
+ dfd = fopen(file, "a");
+ } else {
+ dfd = NULL;
+ }
+#endif
+
+ sprintf(buf, NOCATGETS("connected %s %s %s\n"),
+ workshop_get_editor_name(),
+ PROTOCOL_VERSION,
+ workshop_get_editor_version());
+ write(sd, buf, strlen(buf));
+
+ sprintf(buf, NOCATGETS("ack 1\n"));
+ write(sd, buf, strlen(buf));
+}
+
+void workshop_disconnect()
+{
+ /* Probably need to send some message here */
+
+ /*
+ * socket closed on other end
+ */
+ XtRemoveInput(inputHandler);
+ close(sd);
+ inputHandler = 0;
+ sd = -1;
+
+}
+
+/*
+ * Utility functions
+ */
+
+/* Set icon for the window */
+void
+workshop_set_icon(Display *display, Widget shell, char **xpmdata,
+ int width, int height)
+{
+ Pixel bgPixel;
+ XpmAttributes xpmAttributes;
+ XSetWindowAttributes attr;
+ Window iconWindow;
+ int depth;
+ int screenNum;
+ Pixmap pixmap;
+
+ /* Create the pixmap/icon window which is shown when you
+ * iconify the sccs viewer
+ * This code snipped was adapted from Sun WorkShop's source base,
+ * setIcon.cc.
+ */
+ XtVaGetValues(shell, XmNbackground, &bgPixel, NULL);
+ screenNum = XScreenNumberOfScreen(XtScreen(shell));
+ depth = DisplayPlanes(display, screenNum);
+ xpmAttributes.valuemask = XpmColorSymbols;
+ xpmAttributes.numsymbols = 1;
+ xpmAttributes.colorsymbols =
+ (XpmColorSymbol *)XtMalloc(sizeof (XpmColorSymbol) *
+ xpmAttributes.numsymbols);
+ xpmAttributes.colorsymbols[0].name = NOCATGETS("BgColor");
+ xpmAttributes.colorsymbols[0].value = NULL;
+ xpmAttributes.colorsymbols[0].pixel = bgPixel;
+ if (XpmCreatePixmapFromData(display,
+ RootWindow(display, screenNum), xpmdata, &pixmap,
+ NULL, &xpmAttributes) >= 0) {
+ attr.background_pixmap = pixmap;
+ iconWindow = XCreateWindow(display, RootWindow(display,
+ screenNum), 0, 0, width, height, 0, depth,
+ (unsigned int)CopyFromParent,
+ CopyFromParent, CWBackPixmap, &attr);
+
+ XtVaSetValues(shell,
+ XtNiconWindow, iconWindow, NULL);
+ }
+ XtFree((char *)xpmAttributes.colorsymbols);
+}
+
+/* Minimize and maximize shells. From libutil's shell.cc. */
+
+/* utility functions from libutil's shell.cc */
+static Boolean
+isWindowMapped(Display *display, Window win)
+{
+ XWindowAttributes winAttrs;
+ XGetWindowAttributes(display,
+ win,
+ &winAttrs);
+ if (winAttrs.map_state == IsViewable) {
+ return(True);
+ } else {
+ return(False);
+ }
+}
+
+static Boolean
+isMapped(Widget widget)
+{
+ if (widget == NULL) {
+ return(False);
+ }
+
+ if (XtIsRealized(widget) == False) {
+ return(False);
+ }
+
+ return(isWindowMapped(XtDisplay(widget), XtWindow(widget)));
+}
+
+static Boolean
+widgetIsIconified(
+ Widget w)
+{
+ Atom wm_state;
+ Atom act_type; /* actual Atom type returned */
+ int act_fmt; /* actual format returned */
+ u_long nitems_ret; /* number of items returned */
+ u_long bytes_after; /* number of bytes remaining */
+ u_long *property; /* actual property returned */
+
+ /*
+ * If a window is iconified its WM_STATE is set to IconicState. See
+ * ICCCM Version 2.0, section 4.1.3.1 for more details.
+ */
+
+ wm_state = XmInternAtom(XtDisplay(w), NOCATGETS("WM_STATE"), False);
+ if (XtWindow(w) != 0) { /* only check if window exists! */
+ XGetWindowProperty(XtDisplay(w), XtWindow(w), wm_state, 0L, 2L,
+ False, AnyPropertyType, &act_type, &act_fmt, &nitems_ret,
+ &bytes_after, (u_char **) &property);
+ if (nitems_ret == 2 && property[0] == IconicState) {
+ return True;
+ }
+ }
+
+ return False;
+
+} /* end widgetIsIconified */
+
+void
+workshop_minimize_shell(Widget shell)
+{
+ if (shell != NULL &&
+ XtIsObject(shell) &&
+ XtIsRealized(shell) == True) {
+ if (isMapped(shell) == True) {
+ XIconifyWindow(XtDisplay(shell), XtWindow(shell),
+ XScreenNumberOfScreen(XtScreen(shell)));
+ }
+ XtVaSetValues(shell,
+ XmNiconic, True,
+ NULL);
+ }
+}
+
+void workshop_maximize_shell(Widget shell)
+{
+ if (shell != NULL &&
+ XtIsRealized(shell) == True &&
+ widgetIsIconified(shell) == True &&
+ isMapped(shell) == False) {
+ XtMapWidget(shell);
+ /* This used to be
+ XtPopdown(shell);
+ XtPopup(shell, XtGrabNone);
+ However, I found that that would drop any transient
+ windows that had been iconified with the window.
+ According to the ICCCM, XtMapWidget should be used
+ to bring a window from Iconic to Normal state.
+ However, Rich Mauri did a lot of work on this during
+ Bart, and found that XtPopDown,XtPopup was required
+ to fix several bugs involving multiple CDE workspaces.
+ I've tested it now and things seem to work fine but
+ I'm leaving this note for history in case this needs
+ to be revisited.
+ */
+ }
+}
+
+
+Boolean workshop_get_width_height(int *width, int *height)
+{
+ static int wid = 0;
+ static int hgt = 0;
+ static Boolean firstTime = True;
+ static Boolean success = False;
+
+ if (firstTime) {
+ char *settings;
+
+ settings = getenv(NOCATGETS("SPRO_GUI_WIDTH_HEIGHT"));
+ if (settings != NULL) {
+ wid = atoi(settings);
+ settings = strrchr(settings, ':');
+ if (settings++ != NULL) {
+ hgt = atoi(settings);
+ }
+ if (wid > 0 && hgt > 0) {
+ success = True;
+ }
+ firstTime = False;
+ }
+ }
+
+ if (success) {
+ *width = wid;
+ *height = hgt;
+ }
+ return success;
+}
+
+
+Boolean workshop_get_rows_cols(int *rows, int *cols)
+{
+ static int r = 0;
+ static int c = 0;
+ static Boolean firstTime = True;
+ static Boolean success = False;
+
+ if (firstTime) {
+ char *settings;
+
+ settings = getenv(NOCATGETS("SPRO_GUI_ROWS_COLS"));
+ if (settings != NULL) {
+ r = atoi(settings);
+ settings = strrchr(settings, ':');
+ if (settings++ != NULL) {
+ c = atoi(settings);
+ }
+ if (r > 0 && c > 0) {
+ success = True;
+ }
+ firstTime = False;
+ }
+ }
+
+ if (success) {
+ *rows = r;
+ *cols = c;
+ }
+ return success;
+}
+
+/*
+ * Toolbar code
+ */
+
+void workshop_sensitivity(int num, char *table)
+{
+ /* build up a verb table */
+ VerbSense *vs;
+ int i;
+ char *s;
+ if ((num < 1) || (num > 500)) {
+ return;
+ }
+
+ vs = (VerbSense *)malloc((num+1)*sizeof(VerbSense));
+
+ /* Point to the individual names (destroys the table string, but
+ * that's okay -- this is more efficient than duplicating strings) */
+ s = table;
+ for (i = 0; i < num; i++) {
+ while (*s == ' ') {
+ s++;
+ }
+ vs[i].verb = s;
+ while (*s && (*s != ' ') && (*s != '\001')) {
+ s++;
+ }
+ if (*s == 0) {
+ vs[i].verb = NULL;
+ break;
+ }
+ if (*s == '\001') {
+ *s = 0;
+ s++;
+ }
+ *s = 0;
+ s++;
+ while (*s == ' ') {
+ s++;
+ }
+ if (*s == '1') {
+ vs[i].sense = 1;
+ } else {
+ vs[i].sense = 0;
+ }
+ s++;
+ }
+ vs[i].verb = NULL;
+
+ workshop_frame_sensitivities(vs);
+
+ free(vs);
+}
+
+/*
+ * Options code
+ */
+/* Set an editor option.
+ * IGNORE an option if you do not recognize it.
+ */
+void workshop_set_option_first(char *name, char *value)
+{
+ /* Currently value can only be on/off. This may change later (for
+ * example to set an option like "balloon evaluate delay", but
+ * for now just convert it into a boolean */
+ Boolean on = !strcmp(value, "on");
+
+ if (!strcmp(name, "workshopkeys")) {
+ workshop_hotkeys(on);
+ } else if (!strcmp(name, "savefiles")) {
+ save_files = on;
+ } else if (!strcmp(name, "balloon")) {
+ workshop_balloon_mode(on);
+ } else if (!strcmp(name, "balloondelay")) {
+ int delay = atoi(value);
+ /* Should I validate the number here?? */
+ workshop_balloon_delay(delay);
+ } else {
+ /* Let editor interpret it */
+ workshop_set_option(name, value);
+ }
+}
+
+
+
+/*
+ * Send information to eserve on certain editor events
+ * You must make sure these are called when necessary
+ */
+
+void workshop_file_closed(char *filename)
+{
+ char buffer[2*MAXPATHLEN];
+ sprintf(buffer, NOCATGETS("deletedFile %s\n"), filename);
+ write(sd, buffer, strlen(buffer));
+}
+
+void workshop_file_closed_lineno(char *filename, int lineno)
+{
+ char buffer[2*MAXPATHLEN];
+ sprintf(buffer, NOCATGETS("deletedFile %s %d\n"), filename, lineno);
+ write(sd, buffer, strlen(buffer));
+}
+
+void workshop_file_opened(char *filename, int readOnly)
+{
+ char buffer[2*MAXPATHLEN];
+ sprintf(buffer, NOCATGETS("loadedFile %s %d\n"), filename, readOnly);
+ write(sd, buffer, strlen(buffer));
+}
+
+
+void workshop_file_saved(char *filename)
+{
+ char buffer[2*MAXPATHLEN];
+ sprintf(buffer, NOCATGETS("savedFile %s\n"), filename);
+ write(sd, buffer, strlen(buffer));
+
+ /* Let editor report any moved marks that the eserve client
+ * should deal with (for example, moving location-based breakpoints) */
+ workshop_moved_marks(filename);
+}
+
+void workshop_move_mark(char *filename, int markId, int newLineno)
+{
+ char buffer[2*MAXPATHLEN];
+ sprintf(buffer, NOCATGETS("moveMark %s %d %d\n"), filename, markId, newLineno);
+ write(sd, buffer, strlen(buffer));
+}
+
+void workshop_file_modified(char *filename)
+{
+ char buffer[2*MAXPATHLEN];
+ sprintf(buffer, NOCATGETS("modifiedFile %s\n"), filename);
+ write(sd, buffer, strlen(buffer));
+}
+
+void workshop_frame_moved(int new_x, int new_y, int new_w, int new_h)
+{
+ char buffer[200];
+
+ if (sd >= 0)
+ {
+ sprintf(buffer, NOCATGETS("frameAt %d %d %d %d\n"),
+ new_x, new_y, new_w, new_h);
+ write(sd, buffer, strlen(buffer));
+ }
+}
+
+/* A button in the toolbar has been pushed.
+ * Clientdata is a pointer used by the editor code to figure out the
+ * positions for this toolbar (probably by storing a window pointer,
+ * and then fetching the current buffer for that window and looking up
+ * cursor and selection positions etc.) */
+void workshop_perform_verb(char *verb, void *clientData)
+{
+ char *filename;
+ int curLine;
+ int curCol;
+ int selStartLine;
+ int selStartCol;
+ int selEndLine;
+ int selEndCol;
+ int selLength;
+ char *selection;
+
+ char buf[2*MAXPATHLEN];
+/* Later: needsFilePos indicates whether or not we need to fetch all this
+ * info for this verb... for now, however, it looks as if
+ * eserve parsing routines depend on it always being present */
+
+ if (workshop_get_positions(clientData,
+ &filename,
+ &curLine,
+ &curCol,
+ &selStartLine,
+ &selStartCol,
+ &selEndLine,
+ &selEndCol,
+ &selLength,
+ &selection)) {
+ if (selection == NULL) {
+ selection = NOCATGETS("");
+ }
+
+ /* Should I save the files??? This is currently done by checking
+ if the verb is one of a few recognized ones. Later we can pass
+ this list from eserve to the editor (it's currently hardcoded in
+ vi and emacs as well). */
+ if (save_files) {
+ if (!strcmp(verb, "build.build") || !strcmp(verb, "build.build-file") ||
+ !strcmp(verb, "debug.fix") || !strcmp(verb, "debug.fix-all")) {
+ workshop_save_files();
+ }
+ }
+
+ sprintf(buf, NOCATGETS("toolVerb %s %s %d,%d %d,%d %d,%d %d %s\n"),
+ verb,
+ filename,
+ curLine, curCol,
+ selStartLine, selStartCol,
+ selEndLine, selEndCol,
+ selLength,
+ selection);
+ write(sd, buf, strlen(buf));
+ if (*selection) {
+ free(selection);
+ }
+ }
+}
+
+/* Send a message to eserve */
+void workshop_send_message(char *buf)
+{
+ write(sd, buf, strlen(buf));
+}
+
+/* Some methods, like currentFile, cursorPos, etc. are missing here.
+ * But it looks like these are used for NoHands testing only so we
+ * won't bother requiring editors to implement these
+ */
+
+
+#ifdef DEBUG
+
+void
+pldebug(
+ char *fmt, /* a printf style format line */
+ ...)
+{
+ va_list ap;
+
+ if (dfd != NULL) {
+ va_start(ap, fmt);
+ vfprintf(dfd, fmt, ap);
+ va_end(ap);
+ fflush(dfd);
+ }
+
+} /* end pldebug */
+
+#endif
diff --git a/src/integration.h b/src/integration.h
new file mode 100644
index 000000000..d6c687d46
--- /dev/null
+++ b/src/integration.h
@@ -0,0 +1,453 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Visual Workshop integration by Gordon Prieur
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+/*
+ THIS IS AN UNSTABLE INTERFACE! It is unsupported and will likely
+ change in future releases, possibly breaking compatibility!
+*/
+
+#ifndef _INTEGRATION_H
+#define _INTEGRATION_H
+
+#include <X11/Intrinsic.h>
+#include <Xm/Xm.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Enable NoHands test support functions. Define this only if you want to
+ compile in support in the editor such that it can be run under
+ the WorkShop test suite. */
+#ifndef NOHANDS_SUPPORT_FUNCTIONS
+#define NOHANDS_SUPPORT_FUNCTIONS
+#endif
+
+
+/* This header file has three parts.
+ * 1. Functions you need to implement; these are called by the integration
+ * library
+ * 2. Functions you need to call when certain events happen in the editor;
+ * these are implemented by the integration library
+ * 3. Utility functions provided by the integration library; these make
+ * task 1 a bit easier.
+ */
+
+/*
+ * The following functions need to be implemented by the editor
+ * integration code (and will be editor-specific). Please see the
+ * sample workshop.c file for comments explaining what each functions
+ * needs to do, what the arguments mean, etc.
+ */
+
+/*
+ * This string is recognized by eserve and should be all lower case.
+ * This is how the editor detects that it is talking to NEdit instead
+ * of Vim, for example, when the connection is initiated from the editor.
+ * Examples: "nedit", "gvim"
+ */
+char *workshop_get_editor_name();
+
+/*
+ * Version number of the editor.
+ * This number is communicated along with the protocol
+ * version to the application.
+ * Examples: "5.0.2", "19.3"
+ */
+char *workshop_get_editor_version();
+
+
+/* Goto a given line in a given file */
+void workshop_goto_line(char *filename, int lineno);
+
+
+/* Set mark in a given file */
+void workshop_set_mark(char *filename, int lineno, int markId, int type);
+
+
+/* Change mark type (for example from current-pc to pc-and-breakpoint) */
+void workshop_change_mark_type(char *filename, int markId, int type);
+
+/*
+ * Goto the given mark in a file (e.g. show it).
+ * If message is not null, display it in the footer.
+ */
+
+void workshop_goto_mark(char *filename, int markId, char *message);
+
+
+/* Delete mark */
+void workshop_delete_mark(char *filename, int markId);
+
+/* Begin/end pair of messages indicating that a series of _set_mark and
+ * _delete_mark messages will be sent. This can/should be used to suppress gui
+ * redraws between the begin and end messages. For example, if you switch
+ * to a headerfile that has a class breakpoint set, there may be hundreds
+ * of marks that need to be added. You don't want to refresh the gui for each
+ * added sign, you want to wait until the final end message.
+ */
+void workshop_mark_batch_begin();
+void workshop_mark_batch_end();
+
+
+/* Load a given file into the WorkShop buffer. "frameid" is a token string
+ * that identifies which frame the file would like to be loaded into. This
+ * will usually be null, in which case you should use the default frame.
+ * However, if frameid is not null, you need to find a frame that has this
+ * frameid, and replace the file in that frame. Finally, if the frameid is
+ * one you haven't seen before, you should create a new frame for this file.
+ * Note that "frameid" is a string value, not just an opaque pointer, so
+ * you should use strcmp rather than == when testing for equality.
+ */
+void workshop_load_file(char *filename, int line, char *frameid);
+
+
+/* Reload the WorkShop buffer */
+void workshop_reload_file(char *filename, int line);
+
+
+/* Show the given file */
+void workshop_show_file(char *filename);
+
+
+/* Front the given file */
+void workshop_front_file(char *filename);
+
+
+/* Save the given file */
+void workshop_save_file(char *filename);
+
+/* Save all WorkShop edited files. You can ask user about modified files
+ * and skip saving any files the user doesn't want to save.
+ * This function is typically called when the user issues a build, a fix,
+ * etc. (and also if you select "Save All" from the File menu :-)
+ */
+void workshop_save_files();
+
+/* Show a message in all footers.
+ Severity currently is not defined. */
+void workshop_footer_message(char *message, int severity);
+
+/* Minimize all windows */
+void workshop_minimize();
+
+
+/* Maximize all windows */
+void workshop_maximize();
+
+
+/*
+ * Create a new mark type, assign it a given index, a given textbackground
+ * color, and a given left-margin sign (where sign is a filename to an
+ * .xpm file)
+ */
+void workshop_add_mark_type(int idx, char *colorspec, char *sign);
+
+
+/* Get mark line number */
+int workshop_get_mark_lineno(char *filename, int markId);
+
+
+/* Exit editor; save confirmation dialogs are okay */
+void workshop_quit();
+
+/* Set an editor option.
+ * For example, name="syntax",value="on" would enable syntax highlighting.
+ * The currently defined options are:
+ * lineno {on,off} show line numbers
+ * syntax {on,off} highlight syntax
+ * parentheses {on,off} show matching parentheses
+ * The following options are interpreted by the library for you (so you
+ * will never see the message. However, the implementation requires you
+ * to provide certain callbacks, like restore hotkeys or save all files.
+ * These are documented separately).
+ * workshopkeys {on,off} set workshop hotkeys
+ * savefiles {on,off} save all files before issuing a build
+ * balloon {on,off} enable/disable balloon evaluate
+ *
+ * IGNORE an option if you do not recognize it.
+ */
+void workshop_set_option(char *name, char *value);
+
+/*
+ * (See workshop_add_frame first.) This function notifies the editor
+ * that the frame for the given window (indicated by "frame", which
+ * was supplied by the editor in workshop_add_frame) has been created.
+ * This can happen much later than the workshop_add_frame message, since
+ * often a window is created on editor startup, while the frame description
+ * is passed over from eserve much later, when the connection is complete.
+ * This gives the editor a chance to kick its GUI to show the frame
+ * properly; typically you'll unmanage and remanage the parent widget to
+ * force a geometry recalculation.
+ */
+
+void workshop_reconfigure_frame(void *frame);
+
+
+/* Are there any moved marks? If so, call workshop_move_mark on
+ * each of them now. This is how eserve can find out if for example
+ * breakpoints have moved when a program has been recompiled and
+ * reloaded into dbx.
+ */
+void workshop_moved_marks(char *filename);
+
+
+/* A button in the toolbar has been pushed. "frame" is provided
+ * which should let you determine which toolbar had a button pushed
+ * (you supplied this clientData when you created a toolbar). From
+ * this you should be able to figure out which file the operation
+ * applies to, and for that window the cursor line and column,
+ * selection begin line and column, selection end line and column,
+ * selection text and selection text length. The column numbers are
+ * currently unused but implement it anyway in case we decide to use
+ * them in the future.
+ * Note that frame can be NULL. In this case, you should pick
+ * a default window to translate coordinates for (ideally, the
+ * last window the user has operated on.) This will be the case when
+ * the user clicks on a Custom Button programmed to take the current
+ * line number as an argument. Here it's ambiguous which buffer
+ * to use, so you need to pick one.
+ * (Interface consideration: Perhaps we instead should add smarts
+ * into the library such that we remember which frame pointer
+ * we last noticed (e.g. last call to get_positions, or perhaps
+ * last add_frame) and then pass that instead? For example, we could
+ * have all workshop operations return the clientData when passed
+ * the filename (or add a filename-to-clientData converter?) and then
+ * remember the last filename/clientData used.
+ */
+int workshop_get_positions(void *frame,
+ char **filename,
+ int *curLine,
+ int *curCol,
+ int *selStartLine,
+ int *selStartCol,
+ int *selEndLine,
+ int *selEndCol,
+ int *selLength,
+ char **selection);
+
+/* The following function should return the height of a character
+ * in the text display. This is used to pick out a suitable size
+ * for the signs to match the text (currently available in three
+ * sizes). If you just return 0, WorkShop will use the default
+ * sign size. (Use XmStringExtent on character "A" to get the height.)
+ */
+
+int workshop_get_font_height(void);
+
+/* The following function requests that you register the given
+ * hotkey as a keyboard accelerator for all frames. Whenever the
+ * hotkey is pressed, you should invoke workshop_hotkey_pressed
+ * and pass the current frame pointer as an argument as well as
+ * the clientData pointer passed in to this function.
+ * The remove function unregisters the hotkey.
+ */
+void workshop_register_hotkey(Modifiers modifiers, KeySym keysym,
+ void *clientData);
+void workshop_unregister_hotkey(Modifiers modifiers, KeySym keysym,
+ void *clientData);
+
+
+
+
+/*
+ *
+ * The following functions notify eserve of important editor events,
+ * such as files being modified, files being saved, etc. You must
+ * sprinkle your editor code with calls to these. For example, whenever
+ * a file is modified (well, when its read-only status changes to modified),
+ * call workshop_file_modified().
+ *
+ */
+
+
+
+/* Connect with eserve. Add this call after you editor initialization
+ * is done, right before entering the event loop or blocking on input.
+ * This will set up a socket connection with eserve.
+ */
+void workshop_connect(XtAppContext context);
+
+/* A file has been opened. */
+void workshop_file_opened(char *filename, int readOnly);
+
+
+/* A file has been saved. Despite its name, eserve also uses this
+ * message to mean a file has been reverted or unmodified.
+ */
+void workshop_file_saved(char *filename);
+
+
+/* A file has been closed */
+void workshop_file_closed(char *filename);
+
+/* Like workshop_file_closed, but also inform eserve what line the
+ cursor was on when you left the file. That way eserve can put you
+ back where you left off when you return to this file. */
+void workshop_file_closed_lineno(char *filename, int line);
+
+/* A file has been modified */
+void workshop_file_modified(char *filename);
+
+
+/*
+ * A mark has been moved. Only call this as a response to
+ * a workshop_moved_marks request call.
+ */
+void workshop_move_mark(char *filename, int markId, int newLineno);
+
+/* Tell the integration library about a new frame being added.
+ * Supply a form for the toolbar, a label for the footer, and an
+ * XmPulldown menu for the WorkShop menu to attach to. Top and bottom
+ * are the widgets above and below the toolbar form widget, if
+ * any. Call this function when you create a new window. It returns a
+ * void *, a handle which you should keep and return when you delete
+ * the window with workshop_delete_toolbar. The "footer" argument
+ * points to a Label widget that is going to be used as a status
+ * message area, and "menu" (if any) points to an Menu widget that
+ * should contain a WorkShop menu. Clientdata is a pointer which is
+ * only used by the editor. It will typically be a pointer to the
+ * window object that the toolbar is placed in. If you have multiple
+ * windows, you need to use this pointer to figure out which window
+ * (and thus corresponding buffer) the user has clicked on to respond
+ * to the workshop_get_positions message.
+ * Each frame's clientData ("frame") should be unique.
+ */
+void *workshop_add_frame(void *frame, Widget form,
+ Widget top, Widget bottom, Widget footer,
+ Widget menu);
+
+/* Delete a window/frame. Call this when an editor window is being deleted. */
+void workshop_delete_frame(void *handle);
+
+/* Add a balloon evaluate text area. "frame" is used the same way
+ * as in workshop_add_frame. This call is not part of workshop_add_frame because
+ * a frame can have multiple tooltip areas (typically, an editor frame that
+ * is split showing multiple buffers will have a separate tooltip area for
+ * each text widget. Each such area is called a "window" (consistent with
+ * XEmacs terminology). Separate these by the window argument if necessary.
+ * You will need to implement workshop_get_balloon_text such that it uses
+ * these two arguments to derive the file, line etc. for the tip.
+ * Call the remove function if you delete this area such that the integration
+ * library can update itself. You must call workshop_add_frame before you
+ * call add_balloon_eval_area, and you must pass the same frame pointer.
+ */
+void workshop_add_balloon_eval_area(void *frame, void *window, Widget widget);
+void workshop_remove_balloon_eval_area(void *frame, void *window, Widget widget);
+
+
+/* For a given mouse position inside the balloon area (passed as x,y),
+ * return the balloon text to be evaluated. There are two scenarios:
+ * If the position is inside the selection, return the selection
+ * string. Else, return the full line (or possibly the full line up
+ * to the last semicolon (that's TBD), along with an index pointing to
+ * where which character the mouse is over.
+ * If we have the selection-scenario, set mouseIndex to -1 to indicate
+ * that no autoexpansion should occur but that the selection should
+ * be evaluated as is.
+ *
+ * XXX Does dbx need more information here, like the filename and line
+ * number in order to determine the correct language and scope to be
+ * used during evaluation?? Or should it just work like the p= button
+ * (where the current scope and language is used, even if you are
+ * pointing at a different file with a different scope) ?
+ */
+int workshop_get_balloon_text(Position x, Position y,
+ void *frame,
+ void *window,
+ char **filename,
+ int *line,
+ char **text,
+ int *mouseIndex);
+
+
+/* Window size and location
+ * WorkShop will attempt to restore the size and location of a single
+ * editor frame. For vi, this window is designated as the "reusable" one.
+ * You can implement your own scheme for determining which window you
+ * want to associate with WorkShop. Whenever the size and location of
+ * this window is changed, call the following function to notify eserve.
+ * Like workshop_invoked, this can be called before the workshop_connect()
+ * call.
+ */
+void workshop_frame_moved(int new_x, int new_y, int new_w, int new_h);
+Boolean workshop_get_width_height(int *, int *);
+Boolean workshop_get_rows_cols(int *, int *);
+
+/* This function should be invoked when you press a hotkey
+ * set up by workshop_register_hotkey. Pass the clientData
+ * to it that was given to you with workshop_register_hotkey.
+*/
+void workshop_hotkey_pressed(void *frame, void *clientData);
+
+
+
+
+
+/*
+ * Utility functions
+ * These provide convenience functions to simplify implementing some
+ * of the above functions.
+ *
+ */
+
+/* Were we invoked by WorkShop? This function can be used early during startup
+ * if you want to do things differently if the editor is started standalone
+ * or in WorkShop mode. For example, in standalone mode you may not want to
+ * add a footer/message area or a sign gutter.
+ */
+int workshop_invoked(void);
+
+/*
+ *Set the desktop icon of the current shell to the given xpm icon.
+ * Standard WorkShop desktop icons should be 48x48.
+ */
+
+void workshop_set_icon(Display *display, Widget shell, char **xpmdata,
+ int width, int height);
+
+
+/* Minimize (iconify) the given shell */
+void workshop_minimize_shell(Widget shell);
+
+/* Maximize (deiconify) the given shell */
+void workshop_maximize_shell(Widget shell);
+
+/* Called by frame.cc -- editor shouldn't call this directly.
+ * Perhaps we need an integrationP.h file ? */
+void workshop_perform_verb(char *verb, void *clientData);
+void workshop_send_message(char *buf);
+
+
+#ifdef NOHANDS_SUPPORT_FUNCTIONS
+/* The following functions are needed to run the WorkShop testsuite
+ * with this editor. You don't need to implement these unless you
+ * intend for your editor to be run by Workshop's testsuite.
+ * getcursorrow should return the number of lines from the top of
+ * the window the cursor is; similarly for getcursorcol.
+ */
+char *workshop_test_getcurrentfile();
+int workshop_test_getcursorrow();
+int workshop_test_getcursorcol();
+char *workshop_test_getcursorrowtext();
+char *workshop_test_getselectedtext();
+#endif
+
+/*
+ * Struct used to set/unset the sensitivity of verbs.
+ */
+typedef struct {
+ char *verb;
+ Boolean sense;
+} VerbSense;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _INTEGRATION_H */
diff --git a/src/keymap.h b/src/keymap.h
new file mode 100644
index 000000000..24b0d61d8
--- /dev/null
+++ b/src/keymap.h
@@ -0,0 +1,484 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * For MSDOS some keys produce codes larger than 0xff. They are split into two
+ * chars, the first one is K_NUL (same value used in term.h).
+ */
+#define K_NUL (0xce) /* for MSDOS: special key follows */
+
+/*
+ * Keycode definitions for special keys.
+ *
+ * Any special key code sequences are replaced by these codes.
+ */
+
+/*
+ * K_SPECIAL is the first byte of a special key code and is always followed by
+ * two bytes.
+ * The second byte can have any value. ASCII is used for normal termcap
+ * entries, 0x80 and higher for special keys, see below.
+ * The third byte is guaranteed to be between 0x02 and 0x7f.
+ */
+
+#define K_SPECIAL (0x80)
+
+/*
+ * Positive characters are "normal" characters.
+ * Negative characters are special key codes. Only characters below -0x200
+ * are used to so that the absolute value can't be mistaken for a single-byte
+ * character.
+ */
+#define IS_SPECIAL(c) ((c) < 0)
+
+/*
+ * Characters 0x0100 - 0x01ff have a special meaning for abbreviations.
+ * Multi-byte characters also have ABBR_OFF added, thus are above 0x0200.
+ */
+#define ABBR_OFF 0x100
+
+/*
+ * NUL cannot be in the input string, therefore it is replaced by
+ * K_SPECIAL KS_ZERO KE_FILLER
+ */
+#define KS_ZERO 255
+
+/*
+ * K_SPECIAL cannot be in the input string, therefore it is replaced by
+ * K_SPECIAL KS_SPECIAL KE_FILLER
+ */
+#define KS_SPECIAL 254
+
+/*
+ * KS_EXTRA is used for keys that have no termcap name
+ * K_SPECIAL KS_EXTRA KE_xxx
+ */
+#define KS_EXTRA 253
+
+/*
+ * KS_MODIFIER is used when a modifier is given for a (special) key
+ * K_SPECIAL KS_MODIFIER bitmask
+ */
+#define KS_MODIFIER 252
+
+/*
+ * These are used for the GUI
+ * K_SPECIAL KS_xxx KE_FILLER
+ */
+#define KS_MOUSE 251
+#define KS_MENU 250
+#define KS_VER_SCROLLBAR 249
+#define KS_HOR_SCROLLBAR 248
+
+/*
+ * These are used for DEC mouse
+ */
+#define KS_NETTERM_MOUSE 247
+#define KS_DEC_MOUSE 246
+
+/*
+ * Used for switching Select mode back on after a mapping or menu.
+ */
+#define KS_SELECT 245
+#define K_SELECT_STRING (char_u *)"\200\365X"
+
+/*
+ * Used for tearing off a menu.
+ */
+#define KS_TEAROFF 244
+
+/* used for JSB term mouse */
+#define KS_JSBTERM_MOUSE 243
+
+/* used a termcap entry that produces a normal character */
+#define KS_KEY 242
+
+/* Used for the qnx pterm mouse */
+#define KS_PTERM_MOUSE 241
+
+/*
+ * Filler used after KS_SPECIAL and others
+ */
+#define KE_FILLER ('X')
+
+/*
+ * translation of three byte code "K_SPECIAL a b" into int "K_xxx" and back
+ */
+#define TERMCAP2KEY(a, b) (-((a) + ((int)(b) << 8)))
+#define KEY2TERMCAP0(x) ((-(x)) & 0xff)
+#define KEY2TERMCAP1(x) (((unsigned)(-(x)) >> 8) & 0xff)
+
+/*
+ * get second or third byte when translating special key code into three bytes
+ */
+#define K_SECOND(c) ((c) == K_SPECIAL ? KS_SPECIAL : (c) == NUL ? KS_ZERO : KEY2TERMCAP0(c))
+
+#define K_THIRD(c) (((c) == K_SPECIAL || (c) == NUL) ? KE_FILLER : KEY2TERMCAP1(c))
+
+/*
+ * get single int code from second byte after K_SPECIAL
+ */
+#define TO_SPECIAL(a, b) ((a) == KS_SPECIAL ? K_SPECIAL : (a) == KS_ZERO ? K_ZERO : TERMCAP2KEY(a, b))
+
+/*
+ * Codes for keys that do not have a termcap name.
+ *
+ * K_SPECIAL KS_EXTRA KE_xxx
+ */
+enum key_extra
+{
+ KE_NAME = 3 /* name of this terminal entry */
+
+ , KE_S_UP /* shift-up */
+ , KE_S_DOWN /* shift-down */
+
+ , KE_S_F1 /* shifted function keys */
+ , KE_S_F2
+ , KE_S_F3
+ , KE_S_F4
+ , KE_S_F5
+ , KE_S_F6
+ , KE_S_F7
+ , KE_S_F8
+ , KE_S_F9
+ , KE_S_F10
+
+ , KE_S_F11
+ , KE_S_F12
+ , KE_S_F13
+ , KE_S_F14
+ , KE_S_F15
+ , KE_S_F16
+ , KE_S_F17
+ , KE_S_F18
+ , KE_S_F19
+ , KE_S_F20
+
+ , KE_S_F21
+ , KE_S_F22
+ , KE_S_F23
+ , KE_S_F24
+ , KE_S_F25
+ , KE_S_F26
+ , KE_S_F27
+ , KE_S_F28
+ , KE_S_F29
+ , KE_S_F30
+
+ , KE_S_F31
+ , KE_S_F32
+ , KE_S_F33
+ , KE_S_F34
+ , KE_S_F35
+ , KE_S_F36
+ , KE_S_F37
+
+ , KE_MOUSE /* mouse event start */
+
+/*
+ * Symbols for pseudo keys which are translated from the real key symbols
+ * above.
+ */
+ , KE_LEFTMOUSE /* Left mouse button click */
+ , KE_LEFTDRAG /* Drag with left mouse button down */
+ , KE_LEFTRELEASE /* Left mouse button release */
+ , KE_MIDDLEMOUSE /* Middle mouse button click */
+ , KE_MIDDLEDRAG /* Drag with middle mouse button down */
+ , KE_MIDDLERELEASE /* Middle mouse button release */
+ , KE_RIGHTMOUSE /* Right mouse button click */
+ , KE_RIGHTDRAG /* Drag with right mouse button down */
+ , KE_RIGHTRELEASE /* Right mouse button release */
+
+ , KE_IGNORE /* Ignored mouse drag/release */
+
+ , KE_TAB /* unshifted TAB key */
+ , KE_S_TAB_OLD /* shifted TAB key (no longer used) */
+
+ , KE_SNIFF /* SNiFF+ input waiting */
+
+ , KE_XF1 /* extra vt100 function keys for xterm */
+ , KE_XF2
+ , KE_XF3
+ , KE_XF4
+ , KE_XEND /* extra (vt100) end key for xterm */
+ , KE_XHOME /* extra (vt100) home key for xterm */
+
+ , KE_LEFTMOUSE_NM /* non-mappable Left mouse button click */
+ , KE_LEFTRELEASE_NM /* non-mappable left mouse button release */
+
+ , KE_S_XF1 /* extra vt100 shifted function keys for xterm */
+ , KE_S_XF2
+ , KE_S_XF3
+ , KE_S_XF4
+
+ , KE_MOUSEDOWN /* scroll wheel pseudo-button Down */
+ , KE_MOUSEUP /* scroll wheel pseudo-button Up */
+
+ , KE_KINS /* keypad Insert key */
+ , KE_KDEL /* keypad Delete key */
+
+ , KE_CSI /* CSI typed directly */
+ , KE_SNR /* <SNR> */
+ , KE_PLUG /* <Plug> */
+ , KE_CMDWIN /* open command-line window from Command-line Mode */
+
+ , KE_C_LEFT /* control-left */
+ , KE_C_RIGHT /* control-right */
+ , KE_C_HOME /* control-home */
+ , KE_C_END /* control-end */
+
+ , KE_X1MOUSE /* X1/X2 mouse-buttons */
+ , KE_X1DRAG
+ , KE_X1RELEASE
+ , KE_X2MOUSE
+ , KE_X2DRAG
+ , KE_X2RELEASE
+
+ , KE_DROP /* DnD data is available */
+};
+
+/*
+ * the three byte codes are replaced with the following int when using vgetc()
+ */
+#define K_ZERO TERMCAP2KEY(KS_ZERO, KE_FILLER)
+
+#define K_UP TERMCAP2KEY('k', 'u')
+#define K_DOWN TERMCAP2KEY('k', 'd')
+#define K_LEFT TERMCAP2KEY('k', 'l')
+#define K_RIGHT TERMCAP2KEY('k', 'r')
+#define K_S_UP TERMCAP2KEY(KS_EXTRA, KE_S_UP)
+#define K_S_DOWN TERMCAP2KEY(KS_EXTRA, KE_S_DOWN)
+#define K_S_LEFT TERMCAP2KEY('#', '4')
+#define K_C_LEFT TERMCAP2KEY(KS_EXTRA, KE_C_LEFT)
+#define K_S_RIGHT TERMCAP2KEY('%', 'i')
+#define K_C_RIGHT TERMCAP2KEY(KS_EXTRA, KE_C_RIGHT)
+#define K_S_HOME TERMCAP2KEY('#', '2')
+#define K_C_HOME TERMCAP2KEY(KS_EXTRA, KE_C_HOME)
+#define K_S_END TERMCAP2KEY('*', '7')
+#define K_C_END TERMCAP2KEY(KS_EXTRA, KE_C_END)
+#define K_TAB TERMCAP2KEY(KS_EXTRA, KE_TAB)
+#define K_S_TAB TERMCAP2KEY('k', 'B')
+
+/* extra set of function keys F1-F4, for vt100 compatible xterm */
+#define K_XF1 TERMCAP2KEY(KS_EXTRA, KE_XF1)
+#define K_XF2 TERMCAP2KEY(KS_EXTRA, KE_XF2)
+#define K_XF3 TERMCAP2KEY(KS_EXTRA, KE_XF3)
+#define K_XF4 TERMCAP2KEY(KS_EXTRA, KE_XF4)
+
+#define K_F1 TERMCAP2KEY('k', '1') /* function keys */
+#define K_F2 TERMCAP2KEY('k', '2')
+#define K_F3 TERMCAP2KEY('k', '3')
+#define K_F4 TERMCAP2KEY('k', '4')
+#define K_F5 TERMCAP2KEY('k', '5')
+#define K_F6 TERMCAP2KEY('k', '6')
+#define K_F7 TERMCAP2KEY('k', '7')
+#define K_F8 TERMCAP2KEY('k', '8')
+#define K_F9 TERMCAP2KEY('k', '9')
+#define K_F10 TERMCAP2KEY('k', ';')
+
+#define K_F11 TERMCAP2KEY('F', '1')
+#define K_F12 TERMCAP2KEY('F', '2')
+#define K_F13 TERMCAP2KEY('F', '3')
+#define K_F14 TERMCAP2KEY('F', '4')
+#define K_F15 TERMCAP2KEY('F', '5')
+#define K_F16 TERMCAP2KEY('F', '6')
+#define K_F17 TERMCAP2KEY('F', '7')
+#define K_F18 TERMCAP2KEY('F', '8')
+#define K_F19 TERMCAP2KEY('F', '9')
+#define K_F20 TERMCAP2KEY('F', 'A')
+
+#define K_F21 TERMCAP2KEY('F', 'B')
+#define K_F22 TERMCAP2KEY('F', 'C')
+#define K_F23 TERMCAP2KEY('F', 'D')
+#define K_F24 TERMCAP2KEY('F', 'E')
+#define K_F25 TERMCAP2KEY('F', 'F')
+#define K_F26 TERMCAP2KEY('F', 'G')
+#define K_F27 TERMCAP2KEY('F', 'H')
+#define K_F28 TERMCAP2KEY('F', 'I')
+#define K_F29 TERMCAP2KEY('F', 'J')
+#define K_F30 TERMCAP2KEY('F', 'K')
+
+#define K_F31 TERMCAP2KEY('F', 'L')
+#define K_F32 TERMCAP2KEY('F', 'M')
+#define K_F33 TERMCAP2KEY('F', 'N')
+#define K_F34 TERMCAP2KEY('F', 'O')
+#define K_F35 TERMCAP2KEY('F', 'P')
+#define K_F36 TERMCAP2KEY('F', 'Q')
+#define K_F37 TERMCAP2KEY('F', 'R')
+
+/* extra set of shifted function keys F1-F4, for vt100 compatible xterm */
+#define K_S_XF1 TERMCAP2KEY(KS_EXTRA, KE_S_XF1)
+#define K_S_XF2 TERMCAP2KEY(KS_EXTRA, KE_S_XF2)
+#define K_S_XF3 TERMCAP2KEY(KS_EXTRA, KE_S_XF3)
+#define K_S_XF4 TERMCAP2KEY(KS_EXTRA, KE_S_XF4)
+
+#define K_S_F1 TERMCAP2KEY(KS_EXTRA, KE_S_F1) /* shifted func. keys */
+#define K_S_F2 TERMCAP2KEY(KS_EXTRA, KE_S_F2)
+#define K_S_F3 TERMCAP2KEY(KS_EXTRA, KE_S_F3)
+#define K_S_F4 TERMCAP2KEY(KS_EXTRA, KE_S_F4)
+#define K_S_F5 TERMCAP2KEY(KS_EXTRA, KE_S_F5)
+#define K_S_F6 TERMCAP2KEY(KS_EXTRA, KE_S_F6)
+#define K_S_F7 TERMCAP2KEY(KS_EXTRA, KE_S_F7)
+#define K_S_F8 TERMCAP2KEY(KS_EXTRA, KE_S_F8)
+#define K_S_F9 TERMCAP2KEY(KS_EXTRA, KE_S_F9)
+#define K_S_F10 TERMCAP2KEY(KS_EXTRA, KE_S_F10)
+
+#define K_S_F11 TERMCAP2KEY(KS_EXTRA, KE_S_F11)
+#define K_S_F12 TERMCAP2KEY(KS_EXTRA, KE_S_F12)
+#define K_S_F13 TERMCAP2KEY(KS_EXTRA, KE_S_F13)
+#define K_S_F14 TERMCAP2KEY(KS_EXTRA, KE_S_F14)
+#define K_S_F15 TERMCAP2KEY(KS_EXTRA, KE_S_F15)
+#define K_S_F16 TERMCAP2KEY(KS_EXTRA, KE_S_F16)
+#define K_S_F17 TERMCAP2KEY(KS_EXTRA, KE_S_F17)
+#define K_S_F18 TERMCAP2KEY(KS_EXTRA, KE_S_F18)
+#define K_S_F19 TERMCAP2KEY(KS_EXTRA, KE_S_F19)
+#define K_S_F20 TERMCAP2KEY(KS_EXTRA, KE_S_F20)
+
+#define K_S_F21 TERMCAP2KEY(KS_EXTRA, KE_S_F21)
+#define K_S_F22 TERMCAP2KEY(KS_EXTRA, KE_S_F22)
+#define K_S_F23 TERMCAP2KEY(KS_EXTRA, KE_S_F23)
+#define K_S_F24 TERMCAP2KEY(KS_EXTRA, KE_S_F24)
+#define K_S_F25 TERMCAP2KEY(KS_EXTRA, KE_S_F25)
+#define K_S_F26 TERMCAP2KEY(KS_EXTRA, KE_S_F26)
+#define K_S_F27 TERMCAP2KEY(KS_EXTRA, KE_S_F27)
+#define K_S_F28 TERMCAP2KEY(KS_EXTRA, KE_S_F28)
+#define K_S_F29 TERMCAP2KEY(KS_EXTRA, KE_S_F29)
+#define K_S_F30 TERMCAP2KEY(KS_EXTRA, KE_S_F30)
+
+#define K_S_F31 TERMCAP2KEY(KS_EXTRA, KE_S_F31)
+#define K_S_F32 TERMCAP2KEY(KS_EXTRA, KE_S_F32)
+#define K_S_F33 TERMCAP2KEY(KS_EXTRA, KE_S_F33)
+#define K_S_F34 TERMCAP2KEY(KS_EXTRA, KE_S_F34)
+#define K_S_F35 TERMCAP2KEY(KS_EXTRA, KE_S_F35)
+#define K_S_F36 TERMCAP2KEY(KS_EXTRA, KE_S_F36)
+#define K_S_F37 TERMCAP2KEY(KS_EXTRA, KE_S_F37)
+
+#define K_HELP TERMCAP2KEY('%', '1')
+#define K_UNDO TERMCAP2KEY('&', '8')
+
+#define K_BS TERMCAP2KEY('k', 'b')
+
+#define K_INS TERMCAP2KEY('k', 'I')
+#define K_KINS TERMCAP2KEY(KS_EXTRA, KE_KINS)
+#define K_DEL TERMCAP2KEY('k', 'D')
+#define K_KDEL TERMCAP2KEY(KS_EXTRA, KE_KDEL)
+#define K_HOME TERMCAP2KEY('k', 'h')
+#define K_KHOME TERMCAP2KEY('K', '1') /* keypad home (upper left) */
+#define K_XHOME TERMCAP2KEY(KS_EXTRA, KE_XHOME)
+#define K_END TERMCAP2KEY('@', '7')
+#define K_KEND TERMCAP2KEY('K', '4') /* keypad end (lower left) */
+#define K_XEND TERMCAP2KEY(KS_EXTRA, KE_XEND)
+#define K_PAGEUP TERMCAP2KEY('k', 'P')
+#define K_PAGEDOWN TERMCAP2KEY('k', 'N')
+#define K_KPAGEUP TERMCAP2KEY('K', '3') /* keypad pageup (upper R.) */
+#define K_KPAGEDOWN TERMCAP2KEY('K', '5') /* keypad pagedown (lower R.) */
+
+#define K_KPLUS TERMCAP2KEY('K', '6') /* keypad plus */
+#define K_KMINUS TERMCAP2KEY('K', '7') /* keypad minus */
+#define K_KDIVIDE TERMCAP2KEY('K', '8') /* keypad / */
+#define K_KMULTIPLY TERMCAP2KEY('K', '9') /* keypad * */
+#define K_KENTER TERMCAP2KEY('K', 'A') /* keypad Enter */
+#define K_KPOINT TERMCAP2KEY('K', 'B') /* keypad . */
+
+#define K_K0 TERMCAP2KEY('K', 'C') /* keypad 0 */
+#define K_K1 TERMCAP2KEY('K', 'D') /* keypad 1 */
+#define K_K2 TERMCAP2KEY('K', 'E') /* keypad 2 */
+#define K_K3 TERMCAP2KEY('K', 'F') /* keypad 3 */
+#define K_K4 TERMCAP2KEY('K', 'G') /* keypad 4 */
+#define K_K5 TERMCAP2KEY('K', 'H') /* keypad 5 */
+#define K_K6 TERMCAP2KEY('K', 'I') /* keypad 6 */
+#define K_K7 TERMCAP2KEY('K', 'J') /* keypad 7 */
+#define K_K8 TERMCAP2KEY('K', 'K') /* keypad 8 */
+#define K_K9 TERMCAP2KEY('K', 'L') /* keypad 9 */
+
+/*
+ * These are used to recognize a keypad key that does have an ASCII equivalent.
+ * Since the values are negative, it's the other way around.
+ */
+#define FIRST_KEYPAD K_K9
+#define LAST_KEYPAD K_KPLUS
+
+#define K_MOUSE TERMCAP2KEY(KS_MOUSE, KE_FILLER)
+#define K_MENU TERMCAP2KEY(KS_MENU, KE_FILLER)
+#define K_VER_SCROLLBAR TERMCAP2KEY(KS_VER_SCROLLBAR, KE_FILLER)
+#define K_HOR_SCROLLBAR TERMCAP2KEY(KS_HOR_SCROLLBAR, KE_FILLER)
+
+#define K_NETTERM_MOUSE TERMCAP2KEY(KS_NETTERM_MOUSE, KE_FILLER)
+#define K_DEC_MOUSE TERMCAP2KEY(KS_DEC_MOUSE, KE_FILLER)
+#define K_JSBTERM_MOUSE TERMCAP2KEY(KS_JSBTERM_MOUSE, KE_FILLER)
+#define K_PTERM_MOUSE TERMCAP2KEY(KS_PTERM_MOUSE, KE_FILLER)
+
+#define K_SELECT TERMCAP2KEY(KS_SELECT, KE_FILLER)
+#define K_TEAROFF TERMCAP2KEY(KS_TEAROFF, KE_FILLER)
+
+/*
+ * Symbols for pseudo keys which are translated from the real key symbols
+ * above.
+ */
+#define K_LEFTMOUSE TERMCAP2KEY(KS_EXTRA, KE_LEFTMOUSE)
+#define K_LEFTMOUSE_NM TERMCAP2KEY(KS_EXTRA, KE_LEFTMOUSE_NM)
+#define K_LEFTDRAG TERMCAP2KEY(KS_EXTRA, KE_LEFTDRAG)
+#define K_LEFTRELEASE TERMCAP2KEY(KS_EXTRA, KE_LEFTRELEASE)
+#define K_LEFTRELEASE_NM TERMCAP2KEY(KS_EXTRA, KE_LEFTRELEASE_NM)
+#define K_MIDDLEMOUSE TERMCAP2KEY(KS_EXTRA, KE_MIDDLEMOUSE)
+#define K_MIDDLEDRAG TERMCAP2KEY(KS_EXTRA, KE_MIDDLEDRAG)
+#define K_MIDDLERELEASE TERMCAP2KEY(KS_EXTRA, KE_MIDDLERELEASE)
+#define K_RIGHTMOUSE TERMCAP2KEY(KS_EXTRA, KE_RIGHTMOUSE)
+#define K_RIGHTDRAG TERMCAP2KEY(KS_EXTRA, KE_RIGHTDRAG)
+#define K_RIGHTRELEASE TERMCAP2KEY(KS_EXTRA, KE_RIGHTRELEASE)
+#define K_X1MOUSE TERMCAP2KEY(KS_EXTRA, KE_X1MOUSE)
+#define K_X1MOUSE TERMCAP2KEY(KS_EXTRA, KE_X1MOUSE)
+#define K_X1DRAG TERMCAP2KEY(KS_EXTRA, KE_X1DRAG)
+#define K_X1RELEASE TERMCAP2KEY(KS_EXTRA, KE_X1RELEASE)
+#define K_X2MOUSE TERMCAP2KEY(KS_EXTRA, KE_X2MOUSE)
+#define K_X2DRAG TERMCAP2KEY(KS_EXTRA, KE_X2DRAG)
+#define K_X2RELEASE TERMCAP2KEY(KS_EXTRA, KE_X2RELEASE)
+
+#define K_IGNORE TERMCAP2KEY(KS_EXTRA, KE_IGNORE)
+
+#define K_SNIFF TERMCAP2KEY(KS_EXTRA, KE_SNIFF)
+
+#define K_MOUSEDOWN TERMCAP2KEY(KS_EXTRA, KE_MOUSEDOWN)
+#define K_MOUSEUP TERMCAP2KEY(KS_EXTRA, KE_MOUSEUP)
+
+#define K_CSI TERMCAP2KEY(KS_EXTRA, KE_CSI)
+#define K_SNR TERMCAP2KEY(KS_EXTRA, KE_SNR)
+#define K_PLUG TERMCAP2KEY(KS_EXTRA, KE_PLUG)
+#define K_CMDWIN TERMCAP2KEY(KS_EXTRA, KE_CMDWIN)
+
+#define K_DROP TERMCAP2KEY(KS_EXTRA, KE_DROP)
+
+/* Bits for modifier mask */
+/* 0x01 cannot be used, because the modifier must be 0x02 or higher */
+#define MOD_MASK_SHIFT 0x02
+#define MOD_MASK_CTRL 0x04
+#define MOD_MASK_ALT 0x08 /* aka META */
+#define MOD_MASK_2CLICK 0x10 /* use MOD_MASK_MULTI_CLICK */
+#define MOD_MASK_3CLICK 0x20 /* use MOD_MASK_MULTI_CLICK */
+#define MOD_MASK_4CLICK 0x30 /* use MOD_MASK_MULTI_CLICK */
+#ifdef MACOS
+# define MOD_MASK_CMD 0x80
+#endif
+
+#define MOD_MASK_MULTI_CLICK (MOD_MASK_2CLICK|MOD_MASK_3CLICK|MOD_MASK_4CLICK)
+
+/*
+ * The length of the longest special key name, including modifiers.
+ * Current longest is <M-C-S-4-MiddleRelease> (length includes '<' and '>').
+ */
+#define MAX_KEY_NAME_LEN 23
+
+/* Maximum length of a special key event as tokens. This includes modifiers.
+ * The longest event is something like <M-C-S-4-LeftDrag> which would be the
+ * following string of tokens:
+ *
+ * <K_SPECIAL> <KS_MODIFIER> bitmask <K_SPECIAL> <KS_EXTRA> <KT_LEFTDRAG>.
+ *
+ * This is a total of 6 tokens, and is currently the longest one possible.
+ */
+#define MAX_KEY_CODE_LEN 6
diff --git a/src/link.390 b/src/link.390
new file mode 100644
index 000000000..76edc04fd
--- /dev/null
+++ b/src/link.390
@@ -0,0 +1,7 @@
+s%-lXext *%%g
+s%-lXmu *%%g
+s%-lXm *%/usr/lib/Xm.x %g
+s%-lX11 *%/usr/lib/X11.x %g
+s%-lXt *%%g
+s%-lSM *%/usr/lib/SM.x %g
+s%-lICE *%/usr/lib/ICE.x %g
diff --git a/src/link.sh b/src/link.sh
new file mode 100755
index 000000000..dc9c4a2ac
--- /dev/null
+++ b/src/link.sh
@@ -0,0 +1,136 @@
+#! /bin/sh
+#
+# link.sh -- try linking Vim with different sets of libraries, finding the
+# minimal set for fastest startup. The problem is that configure adds a few
+# libraries when they exist, but this doesn't mean they are needed for Vim.
+#
+# Author: Bram Moolenaar
+# Last change: 2004 Apr 05
+#
+# Warning: This fails miserably if the linker doesn't return an error code!
+#
+# Otherwise this script is fail-safe, falling back to the original full link
+# command if anything fails.
+
+echo "$LINK " >link.cmd
+exit_value=0
+
+#
+# If auto/link.sed already exists, use it. We assume a previous run of
+# link.sh has found the correct set of libraries.
+#
+if test -f auto/link.sed; then
+ echo "link.sh: The file 'auto/link.sed' exists, which is going to be used now."
+ echo "link.sh: If linking fails, try deleting the auto/link.sed file."
+ echo "link.sh: If this fails too, try creating an empty auto/link.sed file."
+else
+
+# If linking works with the full link command, try removing some libraries,
+# that are known not to be needed on at least one system.
+# Remove auto/pathdef.c if there is a new link command and compile it again.
+# There is a loop to remove libraries that appear several times.
+#
+# Notes:
+# - Can't remove Xext; It links fine but will give an error when running gvim
+# with Motif.
+# - Don't remove the last -lm: On HP-UX Vim links OK but crashes when the GTK
+# GUI is started, because the "floor" symbol could not be resolved.
+#
+ cat link.cmd
+ if sh link.cmd; then
+ touch auto/link.sed
+ cp link.cmd linkit.sh
+ for libname in SM ICE nsl dnet dnet_stub inet socket dir elf iconv Xt Xmu Xp Xpm X11 Xdmcp x w dl pthread thread readline m perl crypt attr; do
+ cont=yes
+ while test -n "$cont"; do
+ if grep "l$libname " linkit.sh >/dev/null; then
+ if test ! -f link1.sed; then
+ echo "link.sh: OK, linking works, let's try removing a few libraries."
+ echo "link.sh: See auto/link.log for details."
+ rm -f auto/link.log
+ fi
+ echo "s/-l$libname *//" >link1.sed
+ sed -f auto/link.sed <link.cmd >linkit2.sh
+ sed -f link1.sed <linkit2.sh >linkit.sh
+ # keep the last -lm
+ if test $libname != "m" || grep "lm " linkit.sh >/dev/null; then
+ echo "link.sh: Trying to remove the $libname library..."
+ cat linkit.sh >>auto/link.log
+ # Redirect this link output, it may contain error messages which
+ # should be ignored.
+ if sh linkit.sh >>auto/link.log 2>&1; then
+ echo "link.sh: We don't need the $libname library!"
+ cat link1.sed >>auto/link.sed
+ rm -f auto/pathdef.c
+ else
+ echo "link.sh: We DO need the $libname library."
+ cont=
+ cp link.cmd linkit.sh
+ fi
+ else
+ cont=
+ cp link.cmd linkit.sh
+ fi
+ else
+ cont=
+ cp link.cmd linkit.sh
+ fi
+ done
+ done
+ if test ! -f auto/pathdef.c; then
+ $MAKE objects/pathdef.o
+ fi
+ if test ! -f link1.sed; then
+ echo "link.sh: Linked fine, no libraries can be removed"
+ touch link3.sed
+ fi
+ else
+ exit_value=$?
+ fi
+fi
+
+#
+# Now do the real linking.
+#
+if test -s auto/link.sed; then
+ echo "link.sh: Using auto/link.sed file to remove a few libraries"
+ sed -f auto/link.sed <link.cmd >linkit.sh
+ cat linkit.sh
+ if sh linkit.sh; then
+ exit_value=0
+ echo "link.sh: Linked fine with a few libraries removed"
+ else
+ exit_value=$?
+ echo "link.sh: Linking failed, making auto/link.sed empty and trying again"
+ mv -f auto/link.sed link2.sed
+ touch auto/link.sed
+ rm -f auto/pathdef.c
+ $MAKE objects/pathdef.o
+ fi
+fi
+if test -f auto/link.sed -a ! -s auto/link.sed -a ! -f link3.sed; then
+ echo "link.sh: Using unmodified link command"
+ cat link.cmd
+ if sh link.cmd; then
+ exit_value=0
+ echo "link.sh: Linked OK"
+ else
+ exit_value=$?
+ if test -f link2.sed; then
+ echo "link.sh: Linking doesn't work at all, removing auto/link.sed"
+ rm -f auto/link.sed
+ fi
+ fi
+fi
+
+#
+# cleanup
+#
+rm -f link.cmd linkit.sh link1.sed link2.sed link3.sed linkit2.sh
+
+#
+# return an error code if something went wrong
+#
+exit $exit_value
+
+# vim:set sw=2 et:
diff --git a/src/macros.h b/src/macros.h
new file mode 100644
index 000000000..9dbb393f5
--- /dev/null
+++ b/src/macros.h
@@ -0,0 +1,245 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * macros.h: macro definitions for often used code
+ */
+
+/*
+ * pchar(lp, c) - put character 'c' at position 'lp'
+ */
+#define pchar(lp, c) (*(ml_get_buf(curbuf, (lp).lnum, TRUE) + (lp).col) = (c))
+
+/*
+ * Position comparisons
+ */
+#ifdef FEAT_VIRTUALEDIT
+# define lt(a, b) (((a).lnum != (b).lnum) \
+ ? (a).lnum < (b).lnum \
+ : (a).col != (b).col \
+ ? (a).col < (b).col \
+ : (a).coladd < (b).coladd)
+# define ltp(a, b) (((a)->lnum != (b)->lnum) \
+ ? (a)->lnum < (b)->lnum \
+ : (a)->col != (b)->col \
+ ? (a)->col < (b)->col \
+ : (a)->coladd < (b)->coladd)
+# define equalpos(a, b) (((a).lnum == (b).lnum) && ((a).col == (b).col) && ((a).coladd == (b).coladd))
+#else
+# define lt(a, b) (((a).lnum != (b).lnum) \
+ ? ((a).lnum < (b).lnum) : ((a).col < (b).col))
+# define ltp(a, b) (((a)->lnum != (b)->lnum) \
+ ? ((a)->lnum < (b)->lnum) : ((a)->col < (b)->col))
+# define equalpos(a, b) (((a).lnum == (b).lnum) && ((a).col == (b).col))
+#endif
+
+#define ltoreq(a, b) (lt(a, b) || equalpos(a, b))
+
+/*
+ * lineempty() - return TRUE if the line is empty
+ */
+#define lineempty(p) (*ml_get(p) == NUL)
+
+/*
+ * bufempty() - return TRUE if the current buffer is empty
+ */
+#define bufempty() (curbuf->b_ml.ml_line_count == 1 && *ml_get((linenr_T)1) == NUL)
+
+/*
+ * toupper() and tolower() that use the current locale.
+ * On some systems toupper()/tolower() only work on lower/uppercase characters
+ * Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the
+ * range 0 - 255. toupper()/tolower() on some systems can't handle others.
+ * Note: for UTF-8 use utf_toupper() and utf_tolower().
+ */
+#ifdef MSWIN
+# define TOUPPER_LOC(c) toupper_tab[(c) & 255]
+# define TOLOWER_LOC(c) tolower_tab[(c) & 255]
+#else
+# ifdef BROKEN_TOUPPER
+# define TOUPPER_LOC(c) (islower(c) ? toupper(c) : (c))
+# define TOLOWER_LOC(c) (isupper(c) ? tolower(c) : (c))
+# else
+# define TOUPPER_LOC toupper
+# define TOLOWER_LOC tolower
+# endif
+#endif
+
+/* toupper() and tolower() for ASCII only and ignore the current locale. */
+#ifdef EBCDIC
+# define TOUPPER_ASC(c) (islower(c) ? toupper(c) : (c))
+# define TOLOWER_ASC(c) (isupper(c) ? tolower(c) : (c))
+#else
+# define TOUPPER_ASC(c) (((c) < 'a' || (c) > 'z') ? (c) : (c) - ('a' - 'A'))
+# define TOLOWER_ASC(c) (((c) < 'A' || (c) > 'Z') ? (c) : (c) + ('a' - 'A'))
+#endif
+
+/*
+ * MB_ISLOWER() and MB_ISUPPER() are to be used on multi-byte characters. But
+ * don't use them for negative values.
+ */
+#ifdef FEAT_MBYTE
+# define MB_ISLOWER(c) (enc_utf8 && (c) > 0x80 ? utf_islower(c) : (has_mbyte && c > 255 ? FALSE : islower(c)))
+# define MB_ISUPPER(c) (enc_utf8 && (c) > 0x80 ? utf_isupper(c) : (has_mbyte && c > 255 ? FALSE : isupper(c)))
+# define MB_TOLOWER(c) (enc_utf8 && (c) > 0x80 ? utf_tolower(c) : (has_mbyte && c > 255 ? c : TOLOWER_LOC(c)))
+# define MB_TOUPPER(c) (enc_utf8 && (c) > 0x80 ? utf_toupper(c) : (has_mbyte && c > 255 ? c : TOUPPER_LOC(c)))
+#else
+# define MB_ISLOWER(c) islower(c)
+# define MB_ISUPPER(c) isupper(c)
+# define MB_TOLOWER(c) TOLOWER_LOC(c)
+# define MB_TOUPPER(c) TOUPPER_LOC(c)
+#endif
+
+/* Like isalpha() but reject non-ASCII characters. Can't be used with a
+ * special key (negative value). */
+#ifdef EBCDIC
+# define ASCII_ISALPHA(c) isalpha(c)
+# define ASCII_ISALNUM(c) isalnum(c)
+# define ASCII_ISLOWER(c) islower(c)
+# define ASCII_ISUPPER(c) isupper(c)
+#else
+# define ASCII_ISALPHA(c) ((c) < 0x7f && isalpha(c))
+# define ASCII_ISALNUM(c) ((c) < 0x7f && isalnum(c))
+# define ASCII_ISLOWER(c) ((c) < 0x7f && islower(c))
+# define ASCII_ISUPPER(c) ((c) < 0x7f && isupper(c))
+#endif
+
+/* Use our own isdigit() replacement, because on MS-Windows isdigit() returns
+ * non-zero for superscript 1. Also avoids that isdigit() crashes for numbers
+ * below 0 and above 255. For complicated arguments and in/decrement use
+ * vim_isdigit() instead. */
+#define VIM_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
+
+/* macro version of chartab().
+ * Only works with values 0-255!
+ * Doesn't work for UTF-8 mode with chars >= 0x80. */
+#define CHARSIZE(c) (chartab[c] & CT_CELL_MASK)
+
+#ifdef FEAT_LANGMAP
+/*
+ * Adjust chars in a language according to 'langmap' option.
+ * NOTE that there is NO overhead if 'langmap' is not set; but even
+ * when set we only have to do 2 ifs and an array lookup.
+ * Don't apply 'langmap' if the character comes from the Stuff buffer.
+ * The do-while is just to ignore a ';' after the macro.
+ */
+# define LANGMAP_ADJUST(c, condition) do { \
+ if (*p_langmap && (condition) && !KeyStuffed && (c) >= 0 && (c) < 256) \
+ c = langmap_mapchar[c]; \
+ } while (0)
+#endif
+
+/*
+ * vim_isbreak() is used very often if 'linebreak' is set, use a macro to make
+ * it work fast.
+ */
+#define vim_isbreak(c) (breakat_flags[(char_u)(c)])
+
+/*
+ * On VMS file names are different and require a translation.
+ * On the Mac open() has only two arguments.
+ */
+#ifdef VMS
+# define mch_access(n, p) access(vms_fixfilename(n), (p))
+ /* see mch_open() comment */
+# define mch_fopen(n, p) fopen(vms_fixfilename(n), (p))
+# define mch_fstat(n, p) fstat(vms_fixfilename(n), (p))
+ /* VMS does not have lstat() */
+# define mch_stat(n, p) stat(vms_fixfilename(n), (p))
+#else
+# ifndef WIN32
+# define mch_access(n, p) access((n), (p))
+# endif
+# if !(defined(FEAT_MBYTE) && defined(WIN3264))
+# define mch_fopen(n, p) fopen((n), (p))
+# endif
+# define mch_fstat(n, p) fstat((n), (p))
+# define mch_lstat(n, p) lstat((n), (p))
+# ifdef MSWIN /* has it's own mch_stat() function */
+# define mch_stat(n, p) vim_stat((n), (p))
+# else
+# ifdef STAT_IGNORES_SLASH
+ /* On Solaris stat() accepts "file/" as if it was "file". Return -1 if
+ * the name ends in "/" and it's not a directory. */
+# define mch_stat(n, p) (illegal_slash(n) ? -1 : stat((n), (p)))
+# else
+# define mch_stat(n, p) stat((n), (p))
+# endif
+# endif
+#endif
+
+#ifdef MACOS_CLASSIC
+/* MacOS classic doesn't support perm but MacOS X does. */
+# define mch_open(n, m, p) open((n), (m))
+#else
+# ifdef VMS
+/*
+ * It is possible to force some record format with:
+ * # define mch_open(n, m, p) open(vms_fixfilename(n), (m), (p)), "rat=cr", "rfm=stmlf", "mrs=0")
+ * but it is not recomended, because it can destroy indexes etc.
+ */
+# define mch_open(n, m, p) open(vms_fixfilename(n), (m), (p))
+# else
+# if !(defined(FEAT_MBYTE) && defined(WIN3264))
+# define mch_open(n, m, p) open((n), (m), (p))
+# endif
+# endif
+#endif
+
+/* mch_open_rw(): invoke mch_open() with third argument for user R/W. */
+#if defined(UNIX) || defined(VMS) /* open in rw------- mode */
+# define mch_open_rw(n, f) mch_open((n), (f), (mode_t)0600)
+#else
+# if defined(MSDOS) || defined(MSWIN) || defined(OS2) /* open read/write */
+# define mch_open_rw(n, f) mch_open((n), (f), S_IREAD | S_IWRITE)
+# else
+# define mch_open_rw(n, f) mch_open((n), (f), 0)
+# endif
+#endif
+
+/*
+ * Encryption macros. Mohsin Ahmed, mosh@sasi.com 98-09-24
+ * Based on zip/crypt sources.
+ */
+
+#ifdef FEAT_CRYPT
+
+#ifndef __MINGW32__
+# define PWLEN 80
+#endif
+
+/* encode byte c, using temp t. Warning: c must not have side effects. */
+# define ZENCODE(c, t) (t = decrypt_byte(), update_keys(c), t^(c))
+
+/* decode byte c in place */
+# define ZDECODE(c) update_keys(c ^= decrypt_byte())
+
+#endif
+
+#ifdef STARTUPTIME
+# define TIME_MSG(s) time_msg(s, NULL)
+#else
+# define TIME_MSG(s)
+#endif
+
+#ifdef FEAT_VREPLACE
+# define REPLACE_NORMAL(s) (((s) & REPLACE_FLAG) && !((s) & VREPLACE_FLAG))
+#else
+# define REPLACE_NORMAL(s) ((s) & REPLACE_FLAG)
+#endif
+
+#ifdef FEAT_ARABIC
+# define UTF_COMPOSINGLIKE(p1, p2) utf_composinglike((p1), (p2))
+#else
+# define UTF_COMPOSINGLIKE(p1, p2) utf_iscomposing(utf_ptr2char(p2))
+#endif
+
+#ifdef FEAT_RIGHTLEFT
+ /* Whether to draw the vertical bar on the right side of the cell. */
+# define CURSOR_BAR_RIGHT (curwin->w_p_rl && (!(State & CMDLINE) || cmdmsg_rl))
+#endif
diff --git a/src/main.aap b/src/main.aap
new file mode 100644
index 000000000..1d90a8795
--- /dev/null
+++ b/src/main.aap
@@ -0,0 +1,1014 @@
+# A-A-P recipe for building Vim
+#
+# There are no user choices in here!
+# Put configure arguments in the file config.arg.
+# Later there will be a config.txt file that contains examples and
+# explanations.
+#
+# Optional arguments:
+# PREFIX=dir Overrules the install directory.
+# Can be specified when installing only.
+# Example: aap install PREFIX=$HOME
+#
+
+# Skip the configure stuff when "link.sh" is executing this recipe recursively
+# to build pathdef.c or not building something and auto/config.aap does exist.
+@if ((_no.TARGETARG != "pathdef" and has_build_target())
+@ or not os.path.exists("auto/config.aap")):
+
+ #
+ # A U T O C O N F
+ #
+
+ # Run autoconf when configure.in has been changed since it was last run.
+ # This is skipped when the signatures in "mysign" are up-to-date. When
+ # there is no autoconf program skip this (the signature is often the only
+ # thing that's outdated)
+ auto/configure {signfile = mysign} : configure.in
+ @if not program_path("autoconf"):
+ :print Can't find autoconf, using existing configure script.
+ @else:
+ # Move configure aside, autoconf would overwrite it
+ :move {exist} configure configure.save
+ :sys autoconf
+ :cat configure | :eval re.sub('\\./config.log', 'auto/config.log', stdin) >! auto/configure
+ :chmod 755 auto/configure
+ :move configure.save configure
+ :del {force} auto/config.cache auto/config.status
+
+ # Change the configure script to produce config.aap instead of config.mk.
+ auto/configure.aap : auto/configure
+ :print Adjusting auto/configure for A-A-P.
+ :cat auto/configure | :eval re.sub("config.mk", "config.aap", stdin)
+ >! auto/configure.aap
+ :chmod 755 auto/configure.aap
+
+ # The configure script uses the directory where it's located, use a link.
+ configure.aap: {buildcheck=}
+ :sys ln -s auto/configure.aap configure.aap
+
+ # Dependency: run configure.aap to update config.h and config.aap in the
+ # "auto" directory.
+ config {virtual} auto/config.h auto/config.aap :
+ auto/configure.aap configure.aap
+ config.arg config.h.in config.aap.in
+ :sys CONFIG_STATUS=auto/config.status
+ ./configure.aap `file2string("config.arg")`
+ --cache-file=auto/config.cache
+
+ # Configure arguments: create an empty "config.arg" file when its missing
+ config.arg:
+ :touch {exist} config.arg
+
+ # "auto/config.aap" contains a lot of settings, such as the name of the
+ # executable "Target".
+ # First update it, forcefully if the "reconfig" target was used.
+ @if _no.TARGETARG != "comment" and _no.TARGETARG != "make":
+ @if "reconfig" in var2list(_no.TARGETARG):
+ :del {force} auto/config.cache auto/config.status
+ :update {force} auto/config.aap
+ @else:
+ :update auto/config.aap
+
+# Include the recipe that autoconf generated.
+:include auto/config.aap
+
+# A "PREFIX=dir" argument overrules the value of $prefix
+@if _no.get("PREFIX"):
+ prefix = $PREFIX
+
+# Don't want "~/" in prefix.
+prefix = `os.path.expanduser(prefix)`
+
+#
+# G U I variant
+#
+# The GUI is selected by configure, a lot of other things depend on it.
+#
+:variant GUI
+ GTK
+ GUI_SRC = gui.c gui_gtk.c gui_gtk_x11.c pty.c gui_beval.c
+ gui_gtk_f.c
+ GUI_OBJ $= $BDIR/gui.o $BDIR/gui_gtk.o $BDIR/gui_gtk_x11.o
+ $BDIR/pty.o $BDIR/gui_gtk_f.o
+ GUI_DEFS = -DFEAT_GUI_GTK $NARROW_PROTO
+ GUI_IPATH = $GUI_INC_LOC
+ GUI_LIBS_DIR = $GUI_LIB_LOC
+ GUI_LIBS1 =
+ GUI_LIBS2 = $GTK_LIBNAME
+ GUI_TARGETS = installglinks
+ GUI_MAN_TARGETS = installghelplinks
+ GUI_TESTTARGET = gui
+ MOTIF
+ GUI_SRC = gui.c gui_motif.c gui_x11.c pty.c gui_beval.c
+ GUI_OBJ $= $BDIR/gui.o $BDIR/gui_motif.o $BDIR/gui_x11.o
+ $BDIR/pty.o $BDIR/gui_beval.o
+ GUI_DEFS = -DFEAT_GUI_MOTIF $NARROW_PROTO
+ GUI_IPATH = $GUI_INC_LOC
+ GUI_LIBS_DIR = $GUI_LIB_LOC
+ GUI_LIBS1 =
+ GUI_LIBS2 = $MOTIF_LIBNAME -lXt
+ GUI_TARGETS = installglinks
+ GUI_MAN_TARGETS = installghelplinks
+ GUI_TESTTARGET = gui
+ ATHENA
+ # XAW_LIB et al. can be overruled to use Xaw3d widgets
+ XAW_LIB ?= -lXaw
+ GUI_SRC = gui.c gui_athena.c gui_x11.c pty.c gui_beval.c \
+ gui_at_sb.c gui_at_fs.c
+ GUI_OBJ $= $BDIR/gui.o $BDIR/gui_athena.o $BDIR/gui_x11.o \
+ $BDIR/pty.o $BDIR/gui_beval.o \
+ $BDIR/gui_at_sb.o $BDIR/gui_at_fs.o
+ GUI_DEFS = -DFEAT_GUI_ATHENA $NARROW_PROTO
+ GUI_IPATH = $GUI_INC_LOC
+ GUI_LIBS_DIR = $GUI_LIB_LOC
+ GUI_LIBS1 = $XAW_LIB
+ GUI_LIBS2 = -lXt
+ GUI_TARGETS = installglinks
+ GUI_MAN_TARGETS = installghelplinks
+ GUI_TESTTARGET = gui
+ NEXTAW
+ # XAW_LIB et al. can be overruled to use Xaw3d widgets
+ XAW_LIB ?= -lXaw
+ GUI_SRC = gui.c gui_athena.c gui_x11.c pty.c gui_beval.c
+ gui_at_fs.c
+ GUI_OBJ $= $BDIR/gui.o $BDIR/gui_athena.o $BDIR/gui_x11.o
+ $BDIR/pty.o $BDIR/gui_beval.o $BDIR/gui_at_fs.o
+ GUI_DEFS = -DFEAT_GUI_ATHENA -DFEAT_GUI_NEXTAW $NARROW_PROTO
+ GUI_IPATH = $GUI_INC_LOC
+ GUI_LIBS_DIR = $GUI_LIB_LOC
+ GUI_LIBS1 = $NEXTAW_LIB
+ GUI_LIBS2 = -lXt
+ GUI_TARGETS = installglinks
+ GUI_MAN_TARGETS = installghelplinks
+ GUI_TESTTARGET = gui
+ BEOSGUI
+ GUI_SRC = gui.c gui_beos.cc pty.c
+ GUI_OBJ = $BDIR/gui.o $BDIR/gui_beos.o $BDIR/pty.o
+ GUI_DEFS = -DFEAT_GUI_BEOS
+ GUI_IPATH =
+ GUI_LIBS_DIR =
+ GUI_LIBS1 = -lbe -lroot
+ GUI_LIBS2 =
+ GUI_TARGETS = installglinks
+ GUI_MAN_TARGETS = installghelplinks
+ GUI_TESTTARGET = gui
+ PHOTONGUI
+ GUI_SRC = gui.c gui_photon.c pty.c
+ GUI_OBJ = $BDIR/gui.o $BDIR/gui_photon.o $BDIR/pty.o
+ GUI_DEFS = -DFEAT_GUI_PHOTON
+ GUI_IPATH =
+ GUI_LIBS_DIR =
+ GUI_LIBS1 = -lph -lphexlib
+ GUI_LIBS2 =
+ GUI_TARGETS = installglinks
+ GUI_MAN_TARGETS = installghelplinks
+ GUI_TESTTARGET = gui
+ *
+ GUI_SRC =
+ GUI_OBJ =
+ GUI_DEFS =
+ GUI_IPATH =
+ GUI_LIBS_DIR =
+ GUI_LIBS1 =
+ GUI_LIBS2 =
+ GUI_TARGETS =
+ GUI_MAN_TARGETS =
+ GUI_TESTTARGET =
+
+
+PRE_DEFS = -Iproto -I. $DEFS $GUI_DEFS $GUI_IPATH $CPPFLAGS $?(EXTRA_IPATHS)
+POST_DEFS = $X_CFLAGS $PERL_CFLAGS $PYTHON_CFLAGS $TCL_CFLAGS $RUBY_CFLAGS $?(EXTRA_DEFS)
+CFLAGS = $PRE_DEFS $CONF_CFLAGS $?(PROFILE_CFLAGS) $POST_DEFS
+CPPFLAGS =
+
+ALL_LIB_DIRS = $GUI_LIBS_DIR $X_LIBS_DIR
+LDFLAGS = $ALL_LIB_DIRS $CONF_LDFLAGS
+LIBS = $GUI_LIBS1 $GUI_X_LIBS $GUI_LIBS2 $X_PRE_LIBS $X_LIBS $X_EXTRA_LIBS $CONF_LIBS $?(EXTRA_LIBS) $PERL_LIBS $PYTHON_LIBS $TCL_LIBS $RUBY_LIBS $?(PROFILE_LIBS)
+
+Target = $VIMNAME
+
+# reconfig target also builds Vim (reconfiguration is handled above).
+reconfig {virtual}: $Target
+
+
+# Execute the test scripts. Run these after compiling Vim, before installing.
+#
+# This will produce a lot of garbage on your screen, including a few error
+# messages. Don't worry about that.
+# If there is a real error, there will be a difference between "test.out" and
+# a "test99.ok" file.
+# If everything is allright, the final message will be "ALL DONE".
+#
+test check:
+ VimProg = ../$Target
+ :execute testdir/main.aap $GUI_TESTTARGET
+
+testclean {virtual}:
+ :del {force} testdir/*.out testdir/test.log
+
+
+# When no fetch target exists we are not a child of the ../main.aap recipe,
+# Use ../main.aap to do the fetching.
+# --- If you get an error here for wrong number of arguments, you need to
+# update to a newer version of A-A-P.
+@if not has_target("fetch"):
+ fetch:
+ :execute ../main.aap fetch
+
+
+# All the source files that need to be compiled.
+# Some are optional and depend on configure.
+# "version.c" is missing, it's always compiled (see below).
+Source =
+ buffer.c
+ charset.c
+ diff.c
+ digraph.c
+ edit.c
+ eval.c
+ ex_cmds.c
+ ex_cmds2.c
+ ex_docmd.c
+ ex_eval.c
+ ex_getln.c
+ fileio.c
+ fold.c
+ getchar.c
+ if_cscope.c
+ if_xcmdsrv.c
+ main.c
+ mark.c
+ memfile.c
+ memline.c
+ menu.c
+ message.c
+ misc1.c
+ misc2.c
+ move.c
+ mbyte.c
+ normal.c
+ ops.c
+ option.c
+ os_unix.c
+ auto/pathdef.c
+ quickfix.c
+ regexp.c
+ screen.c
+ search.c
+ syntax.c
+ tag.c
+ term.c
+ ui.c
+ undo.c
+ window.c
+ $OS_EXTRA_SRC
+ $GUI_SRC
+ $HANGULIN_SRC
+ $PERL_SRC
+ $NETBEANS_SRC
+ $PYTHON_SRC
+ $TCL_SRC
+ $RUBY_SRC
+ $SNIFF_SRC
+ $WORKSHOP_SRC
+
+# TODO: make is still used for subdirectories, need to write a recipe.
+MAKE ?= make
+
+all: $Target
+
+# This dependency is required to build auto/osdef.h before automatic
+# dependencies are generated.
+$Source version.c : auto/osdef.h
+
+# Need to mention that the target also depends on version.c, since it's not
+# inluded in $Source
+$Target : version.c
+
+# Some sources are to be found in the "auto" directory.
+SRCPATH += auto
+
+# When building Vim always compile version.c to get the timestamp.
+:filetype
+ declare my_prog
+:attr {filetype = my_prog} $Target
+
+:program $Target : $Source
+
+:action build my_prog object
+ version_obj = `src2obj("version.c")`
+ :do compile {target = $version_obj} version.c
+ #:do build {target = $target {filetype = program}} $source $version_obj
+ link_sed = $BDIR/link.sed
+ @if os.path.exists(link_sed):
+ :move {force} $link_sed auto/link.sed
+ @else:
+ :del {force} auto/link.sed
+ :update link2.sh
+ :sys LINK="$?(PURIFY) $?(SHRPENV) $CC $LDFLAGS \
+ -o $target $source $version_obj $LIBS" \
+ MAKE="aap" sh ./link2.sh
+ :copy {force} auto/link.sed $BDIR/link.sed
+
+# "link.sh" must be modified for A-A-P
+link2.sh : link.sh
+ :print Adjusting $-source for A-A-P.
+ :cat $source | :eval re.sub("objects/pathdef.o", "pathdef", stdin)
+ >! $target
+
+xxd/xxd$EXESUF: xxd/xxd.c
+ :sys cd xxd; CC="$CC" CFLAGS="$CPPFLAGS $CFLAGS" \
+ $MAKE -f Makefile
+
+# Build the language specific files if they were unpacked.
+# Generate the converted .mo files separately, it's no problem if this fails.
+languages {virtual}:
+ @if _no.MAKEMO:
+ :sys cd $PODIR; CC="$CC" $MAKE prefix=$DESTDIR$prefix
+ @try:
+ :sys cd $PODIR; CC="$CC" $MAKE prefix=$DESTDIR$prefix converted
+ @except:
+ :print Generated converted language files failed, continuing
+
+# Update the *.po files for changes in the sources. Only run manually.
+update-po {virtual}:
+ cd $PODIR; CC="$CC" $MAKE prefix=$DESTDIR$prefix update-po
+
+auto/if_perl.c: if_perl.xs
+ :sys $PERL -e 'unless ( $$] >= 5.005 ) { for (qw(na defgv errgv)) { print "#define PL_$$_ $$_\n" }}' > $target
+ :sys $PERL $PERLLIB/ExtUtils/xsubpp -prototypes -typemap \
+ $PERLLIB/ExtUtils/typemap if_perl.xs >> $target
+
+auto/osdef.h: auto/config.h osdef.sh osdef1.h.in osdef2.h.in
+ :sys CC="$CC $CFLAGS" srcdir=$srcdir sh $srcdir/osdef.sh
+
+pathdef {virtual} : $BDIR/auto/pathdef$OBJSUF
+
+auto/pathdef.c: auto/config.aap
+ :print Creating $target
+ :print >! $target /* pathdef.c */
+ :print >> $target /* This file is automatically created by main.aap */
+ :print >> $target /* DO NOT EDIT! Change main.aap only. */
+ :print >> $target $#include "vim.h"
+ :print >> $target char_u *default_vim_dir = (char_u *)"$VIMRCLOC";
+ :print >> $target char_u *default_vimruntime_dir = (char_u *)"$?VIMRUNTIMEDIR";
+ :print >> $target char_u *all_cflags = (char_u *)"$CC -c -I$srcdir $CFLAGS";
+ linkcmd = $CC $LDFLAGS -o $VIMTARGET $LIBS
+ link_sed = $BDIR/link.sed
+ @if os.path.exists(link_sed):
+ # filter $linkcmd through $BDIR/link.sed
+ :print $linkcmd | :syseval sed -f $link_sed | :eval re.sub("\n", "", stdin) | :assign linkcmd
+ :print >> $target char_u *all_lflags = (char_u *)"$linkcmd";
+ @if _no.get("COMPILEDBY"):
+ who = $COMPILEDBY
+ where = ''
+ @else:
+ :syseval whoami | :eval re.sub("\n", "", stdin) | :assign who
+
+ :syseval hostname | :eval re.sub("\n", "", stdin) | :assign where
+ :print >> $target char_u *compiled_user = (char_u *)"$who";
+ :print >> $target char_u *compiled_sys = (char_u *)"$where";
+
+
+### Names of the programs and targets
+VIMTARGET = $VIMNAME$EXESUF
+EXTARGET = $EXNAME$LNKSUF
+VIEWTARGET = $VIEWNAME$LNKSUF
+GVIMNAME = g$VIMNAME
+GVIMTARGET = $GVIMNAME$LNKSUF
+GVIEWNAME = g$VIEWNAME
+GVIEWTARGET = $GVIEWNAME$LNKSUF
+RVIMNAME = r$VIMNAME
+RVIMTARGET = $RVIMNAME$LNKSUF
+RVIEWNAME = r$VIEWNAME
+RVIEWTARGET = $RVIEWNAME$LNKSUF
+RGVIMNAME = r$GVIMNAME
+RGVIMTARGET = $RGVIMNAME$LNKSUF
+RGVIEWNAME = r$GVIEWNAME
+RGVIEWTARGET = $RGVIEWNAME$LNKSUF
+VIMDIFFNAME = $(VIMNAME)diff
+GVIMDIFFNAME = g$VIMDIFFNAME
+VIMDIFFTARGET = $VIMDIFFNAME$LNKSUF
+GVIMDIFFTARGET = $GVIMDIFFNAME$LNKSUF
+EVIMNAME = e$VIMNAME
+EVIMTARGET = $EVIMNAME$LNKSUF
+EVIEWNAME = e$VIEWNAME
+EVIEWTARGET = $EVIEWNAME$LNKSUF
+
+### Names of the tools that are also made
+TOOLS = xxd/xxd$EXESUF
+
+# Root of the installation tree. Empty for a normal install, set to an
+# existing path to install into a special place (for generating a package).
+DESTDIR ?=
+
+### Location of man pages
+MANSUBDIR = $MANDIR/man1
+
+### Location of Vim files (should not need to be changed, and
+### some things might not work when they are changed!)
+VIMDIR = /vim
+@r = re.compile('.*VIM_VERSION_NODOT\\s*"(vim\\d\\d[^"]*)".*', re.S)
+VIMRTDIR = /`r.match(open("version.h").read()).group(1)`
+HELPSUBDIR = /doc
+COLSUBDIR = /colors
+SYNSUBDIR = /syntax
+INDSUBDIR = /indent
+PLUGSUBDIR = /plugin
+FTPLUGSUBDIR = /ftplugin
+LANGSUBDIR = /lang
+COMPSUBDIR = /compiler
+KMAPSUBDIR = /keymap
+MACROSUBDIR = /macros
+TOOLSSUBDIR = /tools
+TUTORSUBDIR = /tutor
+PRINTSUBDIR = /print
+PODIR = po
+
+### VIMLOC common root of the Vim files (all versions)
+### VIMRTLOC common root of the runtime Vim files (this version)
+### VIMRCLOC compiled-in location for global [g]vimrc files (all versions)
+### VIMRUNTIMEDIR compiled-in location for runtime files (optional)
+### HELPSUBLOC location for help files
+### COLSUBLOC location for colorscheme files
+### SYNSUBLOC location for syntax files
+### INDSUBLOC location for indent files
+### PLUGSUBLOC location for standard plugin files
+### FTPLUGSUBLOC location for ftplugin files
+### LANGSUBLOC location for language files
+### COMPSUBLOC location for compiler files
+### KMAPSUBLOC location for keymap files
+### MACROSUBLOC location for macro files
+### TOOLSSUBLOC location for tools files
+### TUTORSUBLOC location for tutor files
+### PRINTSUBLOC location for print files
+### SCRIPTLOC location for script files (menu.vim, bugreport.vim, ..)
+### You can override these if you want to install them somewhere else.
+### Edit feature.h for compile-time settings.
+VIMLOC = $DATADIR$VIMDIR
+VIMRTLOC = $DATADIR$VIMDIR$VIMRTDIR
+VIMRCLOC = $VIMLOC
+HELPSUBLOC = $VIMRTLOC$HELPSUBDIR
+COLSUBLOC = $VIMRTLOC$COLSUBDIR
+SYNSUBLOC = $VIMRTLOC$SYNSUBDIR
+INDSUBLOC = $VIMRTLOC$INDSUBDIR
+PLUGSUBLOC = $VIMRTLOC$PLUGSUBDIR
+FTPLUGSUBLOC = $VIMRTLOC$FTPLUGSUBDIR
+LANGSUBLOC = $VIMRTLOC$LANGSUBDIR
+COMPSUBLOC = $VIMRTLOC$COMPSUBDIR
+KMAPSUBLOC = $VIMRTLOC$KMAPSUBDIR
+MACROSUBLOC = $VIMRTLOC$MACROSUBDIR
+TOOLSSUBLOC = $VIMRTLOC$TOOLSSUBDIR
+TUTORSUBLOC = $VIMRTLOC$TUTORSUBDIR
+PRINTSUBLOC = $VIMRTLOC$PRINTSUBDIR
+SCRIPTLOC = $VIMRTLOC
+
+### Only set VIMRUNTIMEDIR when VIMRTLOC is set to a different location and
+### the runtime directory is not below it.
+#VIMRUNTIMEDIR = $VIMRTLOC
+
+### Name of the evim file target.
+EVIM_FILE = $DESTDIR$SCRIPTLOC/evim.vim
+MSWIN_FILE = $DESTDIR$SCRIPTLOC/mswin.vim
+
+### Name of the menu file target.
+SYS_MENU_FILE = $DESTDIR$SCRIPTLOC/menu.vim
+SYS_SYNMENU_FILE = $DESTDIR$SCRIPTLOC/synmenu.vim
+SYS_DELMENU_FILE = $DESTDIR$SCRIPTLOC/delmenu.vim
+
+### Name of the bugreport file target.
+SYS_BUGR_FILE = $DESTDIR$SCRIPTLOC/bugreport.vim
+
+### Name of the file type detection file target.
+SYS_FILETYPE_FILE = $DESTDIR$SCRIPTLOC/filetype.vim
+
+### Name of the file type detection file target.
+SYS_FTOFF_FILE = $DESTDIR$SCRIPTLOC/ftoff.vim
+
+### Name of the file type detection script file target.
+SYS_SCRIPTS_FILE = $DESTDIR$SCRIPTLOC/scripts.vim
+
+### Name of the ftplugin-on file target.
+SYS_FTPLUGIN_FILE = $DESTDIR$SCRIPTLOC/ftplugin.vim
+
+### Name of the ftplugin-off file target.
+SYS_FTPLUGOF_FILE = $DESTDIR$SCRIPTLOC/ftplugof.vim
+
+### Name of the indent-on file target.
+SYS_INDENT_FILE = $DESTDIR$SCRIPTLOC/indent.vim
+
+### Name of the indent-off file target.
+SYS_INDOFF_FILE = $DESTDIR$SCRIPTLOC/indoff.vim
+
+### Name of the option window script file target.
+SYS_OPTWIN_FILE = $DESTDIR$SCRIPTLOC/optwin.vim
+
+### Permissions for binaries
+BINMOD = 755
+
+### Permissions for man page
+MANMOD = 644
+
+### Permissions for help files
+HELPMOD = 644
+
+### Permissions for Perl and shell scripts
+SCRIPTMOD = 755
+
+### Permission for Vim script files (menu.vim, bugreport.vim, ..)
+VIMSCRIPTMOD = 644
+
+### Permissions for all directories that are created
+DIRMOD = 755
+
+### Permissions for all other files that are created
+FILEMOD = 644
+
+# Where to copy the man and help files from
+HELPSOURCE = ../runtime/doc
+
+# Where to copy the script files from (menu, bugreport)
+SCRIPTSOURCE = ../runtime
+
+# Where to copy the colorscheme files from
+COLSOURCE = ../runtime/colors
+
+# Where to copy the syntax files from
+SYNSOURCE = ../runtime/syntax
+
+# Where to copy the indent files from
+INDSOURCE = ../runtime/indent
+
+# Where to copy the standard plugin files from
+PLUGSOURCE = ../runtime/plugin
+
+# Where to copy the ftplugin files from
+FTPLUGSOURCE = ../runtime/ftplugin
+
+# Where to copy the macro files from
+MACROSOURCE = ../runtime/macros
+
+# Where to copy the tools files from
+TOOLSSOURCE = ../runtime/tools
+
+# Where to copy the tutor files from
+TUTORSOURCE = ../runtime/tutor
+
+# Where to look for language specific files
+LANGSOURCE = ../runtime/lang
+
+# Where to look for compiler files
+COMPSOURCE = ../runtime/compiler
+
+# Where to look for keymap files
+KMAPSOURCE = ../runtime/keymap
+
+# Where to look for print resource files
+PRINTSOURCE = ../runtime/print
+
+# abbreviations
+DEST_BIN = $DESTDIR$BINDIR
+DEST_VIM = $DESTDIR$VIMLOC
+DEST_RT = $DESTDIR$VIMRTLOC
+DEST_HELP = $DESTDIR$HELPSUBLOC
+DEST_COL = $DESTDIR$COLSUBLOC
+DEST_SYN = $DESTDIR$SYNSUBLOC
+DEST_IND = $DESTDIR$INDSUBLOC
+DEST_PLUG = $DESTDIR$PLUGSUBLOC
+DEST_FTP = $DESTDIR$FTPLUGSUBLOC
+DEST_LANG = $DESTDIR$LANGSUBLOC
+DEST_COMP = $DESTDIR$COMPSUBLOC
+DEST_KMAP = $DESTDIR$KMAPSUBLOC
+DEST_MACRO = $DESTDIR$MACROSUBLOC
+DEST_TOOLS = $DESTDIR$TOOLSSUBLOC
+DEST_TUTOR = $DESTDIR$TUTORSUBLOC
+DEST_SCRIPT = $DESTDIR$SCRIPTLOC
+DEST_PRINT = $DESTDIR$PRINTSUBLOC
+DEST_MAN = $DESTDIR$MANSUBDIR
+
+# These are directories, create them when needed.
+:attr {directory = $DIRMOD} $DEST_BIN $DEST_VIM $DEST_RT $DEST_HELP $DEST_COL
+ $DEST_SYN $DEST_IND $DEST_PLUG $DEST_FTP $DEST_LANG
+ $DEST_COMP $DEST_KMAP $DEST_MACRO $DEST_TOOLS $DEST_TUTOR
+ $DEST_SCRIPT $DEST_PRINT $DEST_MAN
+
+#
+# I N S T A L L
+#
+install:
+ @if not os.path.isdir(_no.DEST_BIN):
+ @try:
+ :mkdir $DEST_BIN
+ @except:
+ @ pass
+ @if os.access(_no.DEST_BIN, os.W_OK):
+ # Bin directory is writable, install directly.
+ :update installvim installtools install-languages install-icons
+ @else:
+ # Bin directory is not writable, need to become root.
+ :print The destination directory "$DEST_BIN" is not writable.
+ :print If this is the wrong directory, use PREFIX to specify another one.
+ :print Otherwise, type the root password to continue installing.
+ :asroot $AAP install
+
+installvim {virtual}: installvimbin installruntime installlinks \
+ installhelplinks installmacros installtutor
+
+installvimbin {virtual}{force}: $Target $DEST_BIN
+ exe = $DEST_BIN/$VIMTARGET
+ @if os.path.exists(exe):
+ # Move the old executable aside and delete it. Any other method
+ # may cause a crash if the executable is currently being used.
+ :move {force} $exe $(exe).rm
+ :del {force} $(exe).rm
+ :copy $VIMTARGET $DEST_BIN
+ :do strip $exe
+ :chmod $BINMOD $DEST_BIN/$VIMTARGET
+# may create a link to the new executable from /usr/bin/vi
+ @if _no.get("LINKIT"):
+ :sys $LINKIT
+
+# install the help files; first adjust the contents for the location
+installruntime {virtual}{force}: $HELPSOURCE/vim.1 $DEST_MAN $DEST_VIM
+ $DEST_RT $DEST_HELP $DEST_COL $DEST_SYN $DEST_IND
+ $DEST_FTP $DEST_PLUG $DEST_TUTOR $DEST_COMP $DEST_PRINT
+ :print generating $DEST_MAN/$(VIMNAME).1
+ :cat $HELPSOURCE/vim.1 |
+ :eval re.sub("/usr/local/lib/vim", _no.VIMLOC, stdin) |
+ :eval re.sub(_no.VIMLOC + "/doc", _no.HELPSUBLOC, stdin) |
+ :eval re.sub(_no.VIMLOC + "/syntax", _no.SYNSUBLOC, stdin) |
+ :eval re.sub(_no.VIMLOC + "/tutor", _no.TUTORSUBLOC, stdin) |
+ :eval re.sub(_no.VIMLOC + "/vimrc",
+ _no.VIMRCLOC + "/vimrc", stdin) |
+ :eval re.sub(_no.VIMLOC + "/gvimrc",
+ _no.VIMRCLOC + "/gvimrc", stdin) |
+ :eval re.sub(_no.VIMLOC + "/menu.vim",
+ _no.SCRIPTLOC + "/menu.vim", stdin) |
+ :eval re.sub(_no.VIMLOC + "/bugreport.vim",
+ _no.SCRIPTLOC + "/bugreport.vim", stdin) |
+ :eval re.sub(_no.VIMLOC + "/filetype.vim",
+ _no.SCRIPTLOC + "/filetype.vim", stdin) |
+ :eval re.sub(_no.VIMLOC + "/ftoff.vim",
+ _no.SCRIPTLOC + "/ftoff.vim", stdin) |
+ :eval re.sub(_no.VIMLOC + "/scripts.vim",
+ _no.SCRIPTLOC + "/scripts.vim", stdin) |
+ :eval re.sub(_no.VIMLOC + "/optwin.vim",
+ _no.SCRIPTLOC + "/optwin.vim", stdin) |
+ :eval re.sub(_no.VIMLOC + "/\\*.ps",
+ _no.SCRIPTLOC + "/*.ps", stdin)
+ >! $DEST_MAN/$(VIMNAME).1
+ :chmod $MANMOD $DEST_MAN/$(VIMNAME).1
+
+ :print generating $DEST_MAN/$(VIMNAME)tutor.1
+ :cat $HELPSOURCE/vimtutor.1 |
+ :eval re.sub("/usr/local/lib/vim", _no.VIMLOC, stdin) |
+ :eval re.sub(_no.VIMLOC + "/tutor", _no.TUTORSUBLOC, stdin)
+ >! $DEST_MAN/$(VIMNAME)tutor.1
+ :chmod $MANMOD $DEST_MAN/$(VIMNAME)tutor.1
+
+ :copy $HELPSOURCE/vimdiff.1 $DEST_MAN/$(VIMDIFFNAME).1
+ :chmod $MANMOD $DEST_MAN/$(VIMDIFFNAME).1
+
+ :print generating $DEST_MAN/$(EVIMNAME).1
+ :cat $HELPSOURCE/evim.1 |
+ :eval re.sub("/usr/local/lib/vim", _no.SCRIPTLOC, stdin)
+ >! $DEST_MAN/$(EVIMNAME).1
+ :chmod $MANMOD $DEST_MAN/$(EVIMNAME).1
+
+ :cd $HELPSOURCE
+ @try:
+ XTRA = `glob.glob("*.??x")` `glob.glob("tags-??")`
+ @except:
+ XTRA = # It's OK if there are no matches.
+ :copy *.txt tags $XTRA $DEST_HELP
+ :cd -
+ :cd $DEST_HELP
+ :chmod $HELPMOD *.txt tags $XTRA
+ :cd -
+ :copy $HELPSOURCE/*.pl $DEST_HELP
+ :chmod $SCRIPTMOD $DEST_HELP/*.pl
+# install the menu files
+ :copy $SCRIPTSOURCE/menu.vim $SYS_MENU_FILE
+ :chmod $VIMSCRIPTMOD $SYS_MENU_FILE
+ :copy $SCRIPTSOURCE/synmenu.vim $SYS_SYNMENU_FILE
+ :chmod $VIMSCRIPTMOD $SYS_SYNMENU_FILE
+ :copy $SCRIPTSOURCE/delmenu.vim $SYS_DELMENU_FILE
+ :chmod $VIMSCRIPTMOD $SYS_DELMENU_FILE
+# install the evim file
+ :copy $SCRIPTSOURCE/mswin.vim $MSWIN_FILE
+ :chmod $VIMSCRIPTMOD $MSWIN_FILE
+ :copy $SCRIPTSOURCE/evim.vim $EVIM_FILE
+ :chmod $VIMSCRIPTMOD $EVIM_FILE
+# install the bugreport file
+ :copy $SCRIPTSOURCE/bugreport.vim $SYS_BUGR_FILE
+ :chmod $VIMSCRIPTMOD $SYS_BUGR_FILE
+# install the example vimrc files
+ :copy $SCRIPTSOURCE/vimrc_example.vim $DEST_SCRIPT
+ :chmod $VIMSCRIPTMOD $DEST_SCRIPT/vimrc_example.vim
+ :copy $SCRIPTSOURCE/gvimrc_example.vim $DEST_SCRIPT
+ :chmod $VIMSCRIPTMOD $DEST_SCRIPT/gvimrc_example.vim
+# install the file type detection files
+ :copy $SCRIPTSOURCE/filetype.vim $SYS_FILETYPE_FILE
+ :chmod $VIMSCRIPTMOD $SYS_FILETYPE_FILE
+ :copy $SCRIPTSOURCE/ftoff.vim $SYS_FTOFF_FILE
+ :chmod $VIMSCRIPTMOD $SYS_FTOFF_FILE
+ :copy $SCRIPTSOURCE/scripts.vim $SYS_SCRIPTS_FILE
+ :chmod $VIMSCRIPTMOD $SYS_SCRIPTS_FILE
+ :copy $SCRIPTSOURCE/ftplugin.vim $SYS_FTPLUGIN_FILE
+ :chmod $VIMSCRIPTMOD $SYS_FTPLUGIN_FILE
+ :copy $SCRIPTSOURCE/ftplugof.vim $SYS_FTPLUGOF_FILE
+ :chmod $VIMSCRIPTMOD $SYS_FTPLUGOF_FILE
+ :copy $SCRIPTSOURCE/indent.vim $SYS_INDENT_FILE
+ :chmod $VIMSCRIPTMOD $SYS_INDENT_FILE
+ :copy $SCRIPTSOURCE/indoff.vim $SYS_INDOFF_FILE
+ :chmod $VIMSCRIPTMOD $SYS_INDOFF_FILE
+ :copy $SCRIPTSOURCE/optwin.vim $SYS_OPTWIN_FILE
+ :chmod $VIMSCRIPTMOD $SYS_OPTWIN_FILE
+# install the print resource files
+ :copy $PRINTSOURCE/*.ps $DEST_PRINT
+ :chmod $FILEMOD $DEST_PRINT/*.ps
+# install the colorscheme files
+ :copy $COLSOURCE/*.vim $COLSOURCE/README.txt $DEST_COL
+ :chmod $HELPMOD $DEST_COL/*.vim $DEST_COL/README.txt
+# install the syntax files
+ :copy $SYNSOURCE/*.vim $SYNSOURCE/README.txt $DEST_SYN
+ :chmod $HELPMOD $DEST_SYN/*.vim $DEST_SYN/README.txt
+# install the indent files
+ :copy $INDSOURCE/*.vim $INDSOURCE/README.txt $DEST_IND
+ :chmod $HELPMOD $DEST_IND/*.vim
+# install the standard plugin files
+ :copy $PLUGSOURCE/*.vim $PLUGSOURCE/README.txt $DEST_PLUG
+ :chmod $HELPMOD $DEST_PLUG/*.vim $DEST_PLUG/README.txt
+# install the ftplugin files
+ :copy $FTPLUGSOURCE/*.vim $FTPLUGSOURCE/README.txt $DEST_FTP
+ :chmod $HELPMOD $DEST_FTP/*.vim $DEST_FTP/README.txt
+# install the compiler files
+ :copy $COMPSOURCE/*.vim $COMPSOURCE/README.txt $DEST_COMP
+ :chmod $HELPMOD $DEST_COMP/*.vim $DEST_COMP/README.txt
+
+installmacros {virtual}{force}: $MACROSOURCE $DEST_VIM $DEST_RT $DEST_MACRO
+ :copy {recursive}{force} $MACROSOURCE/* $DEST_MACRO
+ # Delete any CVS and AAPDIR directories.
+ # Use the ":tree" command if possible. It was added later, fall back
+ # to using "find" when it doesn't work.
+ @try:
+ :tree $DEST_MACRO {dirname = CVS}
+ :del {recursive} $name
+ :tree $DEST_MACRO {dirname = AAPDIR}
+ :del {recursive} $name
+ :tree $DEST_MACRO {dirname = .*}
+ :chmod $DIRMOD $name
+ :tree $DEST_MACRO {filename = .*}
+ :chmod $FILEMOD $name
+ @except:
+ @ ok, cvsdirs = redir_system('find %s -name CVS -print' % _no.DEST_MACRO)
+ @ if ok and cvsdirs:
+ :del {recursive} $cvsdirs
+ :sys chmod $DIRMOD ``find $DEST_MACRO -type d -print``
+ :sys chmod $FILEMOD ``find $DEST_MACRO -type f -print``
+ :chmod $SCRIPTMOD $DEST_MACRO/less.sh
+
+# install the tutor files
+installtutor {virtual}{force}: $TUTORSOURCE $DEST_VIM $DEST_RT $DEST_TUTOR
+ :copy vimtutor $DEST_BIN/$(VIMNAME)tutor
+ :chmod $SCRIPTMOD $DEST_BIN/$(VIMNAME)tutor
+ :copy $TUTORSOURCE/tutor* $TUTORSOURCE/README* $DEST_TUTOR
+ :chmod $HELPMOD $DEST_TUTOR/*
+
+# install helper program xxd
+installtools {virtual}{force}: $TOOLS $DEST_BIN $DEST_MAN \
+ $TOOLSSOURCE $DEST_VIM $DEST_RT $DEST_TOOLS
+ xxd = $DEST_BIN/xxd$EXESUF
+ @if os.path.exists(xxd):
+ :move {force} $xxd $(xxd).rm
+ :del $(xxd).rm
+ :copy xxd/xxd$EXESUF $DEST_BIN
+ :do strip $DEST_BIN/xxd$EXESUF
+ :chmod $BINMOD $DEST_BIN/xxd$EXESUF
+ :copy $HELPSOURCE/xxd.1 $DEST_MAN
+ :chmod $MANMOD $DEST_MAN/xxd.1
+# install the runtime tools
+ @try:
+ @ if aap_has(":tree"):
+ # New method: copy everything and delete CVS and AAPDIR dirs
+ :copy {recursive} $TOOLSSOURCE/* $DEST_TOOLS
+ :tree $DEST_TOOLS {dirname = CVS}
+ :delete {recursive} $name
+ :tree $DEST_TOOLS {dirname = AAPDIR}
+ :delete {recursive} $name
+ @except:
+ # Old method: copy only specific files and directories.
+ :copy {recursive} $TOOLSSOURCE/README.txt $TOOLSSOURCE/[a-z]* $DEST_TOOLS
+ :chmod $FILEMOD $DEST_TOOLS/*
+# replace the path in some tools
+ :progsearch perlpath perl
+ @if perlpath:
+ :cat $TOOLSSOURCE/efm_perl.pl |
+ :eval re.sub("/usr/bin/perl", perlpath, stdin)
+ >! $DEST_TOOLS/efm_perl.pl
+ @else:
+ :copy $TOOLSSOURCE/efm_perl.pl $DEST_TOOLS
+
+ :progsearch awkpath nawk gawk awk
+ @if awkpath:
+ :cat $TOOLSSOURCE/mve.awk |
+ :eval re.sub("/usr/bin/nawk", awkpath, stdin)
+ >! $DEST_TOOLS/mve.awk
+ @else:
+ :copy $TOOLSSOURCE/mve.awk $DEST_TOOLS
+
+ :sys chmod $SCRIPTMOD ``grep -l "^#!" $DEST_TOOLS/*``
+
+# install the language specific files, if they were unpacked
+install-languages {virtual}{force}: languages $DEST_LANG $DEST_KMAP
+ @if _no.MAKEMO:
+ :sys cd $PODIR; $MAKE prefix=$DESTDIR$prefix \
+ LOCALEDIR=$DEST_LANG INSTALL_DATA=cp FILEMOD=$FILEMOD install
+ @if os.path.exists(_no.LANGSOURCE):
+ :print installing language files
+ :copy $LANGSOURCE/README.txt $LANGSOURCE/*.vim $DEST_LANG
+ :chmod $FILEMOD $DEST_LANG/*.vim
+ @if os.path.exists(_no.KMAPSOURCE):
+ :copy $KMAPSOURCE/README.txt $KMAPSOURCE/*.vim $DEST_KMAP
+ :chmod $FILEMOD $DEST_KMAP/*.vim
+
+# install the icons for KDE, if the directory exists and the icon doesn't.
+ICON48PATH = $DESTDIR$DATADIR/icons/hicolor/48x48/apps
+ICON32PATH = $DESTDIR$DATADIR/icons/locolor/32x32/apps
+ICON16PATH = $DESTDIR$DATADIR/icons/locolor/16x16/apps
+KDEPATH = $HOME/.kde/share/icons
+install-icons {virtual}:
+ gp = $ICON48PATH/gvim.png
+ @if os.path.isdir(_no.ICON48PATH) and not os.path.exists(gp):
+ :copy $SCRIPTSOURCE/vim48x48.png $gp
+ gp = $ICON32PATH/gvim.png
+ @if os.path.isdir(_no.ICON32PATH) and not os.path.exists(gp):
+ :copy $SCRIPTSOURCE/vim32x32.png $gp
+ gp = $ICON16PATH/gvim.png
+ @if os.path.isdir(_no.ICON16PATH) and not os.path.exists(gp):
+ :copy $SCRIPTSOURCE/vim16x16.png $gp
+
+
+$HELPSOURCE/vim.1 $MACROSOURCE $TOOLSSOURCE:
+ @if not os.path.exists(_no.TOOLSSOURCE):
+ :print Runtime files not found.
+ :error You need to unpack the runtime archive before running "make install".
+
+# create links from various names to vim. This is only done when the links
+# (or executables with the same name) don't exist yet.
+installlinks {virtual}: $GUI_TARGETS \
+ $DEST_BIN/$EXTARGET \
+ $DEST_BIN/$VIEWTARGET \
+ $DEST_BIN/$RVIMTARGET \
+ $DEST_BIN/$RVIEWTARGET \
+ $INSTALLVIMDIFF
+
+installglinks {virtual}: $DEST_BIN/$GVIMTARGET \
+ $DEST_BIN/$GVIEWTARGET \
+ $DEST_BIN/$RGVIMTARGET \
+ $DEST_BIN/$RGVIEWTARGET \
+ $DEST_BIN/$EVIMTARGET \
+ $DEST_BIN/$EVIEWTARGET \
+ $INSTALLGVIMDIFF
+
+installvimdiff {virtual}: $DEST_BIN/$VIMDIFFTARGET
+installgvimdiff {virtual}: $DEST_BIN/$GVIMDIFFTARGET
+
+# These dependencies use an empty buildcheck so that they are only done when
+# the target doesn't exist.
+$DEST_BIN/$EXTARGET: {buildcheck = }
+ :sys cd $DEST_BIN; ln -s $VIMTARGET $EXTARGET
+
+$DEST_BIN/$VIEWTARGET: {buildcheck = }
+ :sys cd $DEST_BIN; ln -s $VIMTARGET $VIEWTARGET
+
+$DEST_BIN/$GVIMTARGET: {buildcheck = }
+ :sys cd $DEST_BIN; ln -s $VIMTARGET $GVIMTARGET
+
+$DEST_BIN/$GVIEWTARGET: {buildcheck = }
+ :sys cd $DEST_BIN; ln -s $VIMTARGET $GVIEWTARGET
+
+$DEST_BIN/$RVIMTARGET: {buildcheck = }
+ :sys cd $DEST_BIN; ln -s $VIMTARGET $RVIMTARGET
+
+$DEST_BIN/$RVIEWTARGET: {buildcheck = }
+ :sys cd $DEST_BIN; ln -s $VIMTARGET $RVIEWTARGET
+
+$DEST_BIN/$RGVIMTARGET: {buildcheck = }
+ :sys cd $DEST_BIN; ln -s $VIMTARGET $RGVIMTARGET
+
+$DEST_BIN/$RGVIEWTARGET: {buildcheck = }
+ :sys cd $DEST_BIN; ln -s $VIMTARGET $RGVIEWTARGET
+
+$DEST_BIN/$VIMDIFFTARGET: {buildcheck = }
+ :sys cd $DEST_BIN; ln -s $VIMTARGET $VIMDIFFTARGET
+
+$DEST_BIN/$GVIMDIFFTARGET: {buildcheck = }
+ :sys cd $DEST_BIN; ln -s $VIMTARGET $GVIMDIFFTARGET
+
+$DEST_BIN/$EVIMTARGET: {buildcheck = }
+ :sys cd $DEST_BIN; ln -s $VIMTARGET $EVIMTARGET
+
+$DEST_BIN/$EVIEWTARGET: {buildcheck = }
+ :sys cd $DEST_BIN; ln -s $VIMTARGET $EVIEWTARGET
+
+# create links for the manual pages with various names to vim. This is only
+# done when the links (or manpages with the same name) don't exist yet.
+installhelplinks {virtual}: $GUI_MAN_TARGETS \
+ $DEST_MAN/$(EXNAME).1 \
+ $DEST_MAN/$(VIEWNAME).1 \
+ $DEST_MAN/$(RVIMNAME).1 \
+ $DEST_MAN/$(RVIEWNAME).1
+
+installghelplinks {virtual}: $DEST_MAN/$(GVIMNAME).1 \
+ $DEST_MAN/$(GVIEWNAME).1 \
+ $DEST_MAN/$(RGVIMNAME).1 \
+ $DEST_MAN/$(RGVIEWNAME).1 \
+ $DEST_MAN/$(GVIMDIFFNAME).1 \
+ $DEST_MAN/$(EVIEWNAME).1
+
+$DEST_MAN/$(EXNAME).1: {buildcheck = }
+ :sys cd $DEST_MAN; ln -s $(VIMNAME).1 $(EXNAME).1
+
+$DEST_MAN/$(VIEWNAME).1: {buildcheck = }
+ :sys cd $DEST_MAN; ln -s $(VIMNAME).1 $(VIEWNAME).1
+
+$DEST_MAN/$(GVIMNAME).1: {buildcheck = }
+ :sys cd $DEST_MAN; ln -s $(VIMNAME).1 $(GVIMNAME).1
+
+$DEST_MAN/$(GVIEWNAME).1: {buildcheck = }
+ :sys cd $DEST_MAN; ln -s $(VIMNAME).1 $(GVIEWNAME).1
+
+$DEST_MAN/$(RVIMNAME).1: {buildcheck = }
+ :sys cd $DEST_MAN; ln -s $(VIMNAME).1 $(RVIMNAME).1
+
+$DEST_MAN/$(RVIEWNAME).1: {buildcheck = }
+ :sys cd $DEST_MAN; ln -s $(VIMNAME).1 $(RVIEWNAME).1
+
+$DEST_MAN/$(RGVIMNAME).1: {buildcheck = }
+ :sys cd $DEST_MAN; ln -s $(VIMNAME).1 $(RGVIMNAME).1
+
+$DEST_MAN/$(RGVIEWNAME).1: {buildcheck = }
+ :sys cd $DEST_MAN; ln -s $(VIMNAME).1 $(RGVIEWNAME).1
+
+$DEST_MAN/$(GVIMDIFFNAME).1: {buildcheck = }
+ :sys cd $DEST_MAN; ln -s $(VIMDIFFNAME).1 $(GVIMDIFFNAME).1
+
+$DEST_MAN/$(EVIEWNAME).1: {buildcheck = }
+ :sys cd $DEST_MAN; ln -s $(EVIMNAME).1 $(EVIEWNAME).1
+
+#
+# U N I N S T A L L
+#
+uninstall {virtual}{force}: uninstall_runtime
+ :del {force} $DEST_BIN/$VIMTARGET
+ :del {force} $DEST_MAN/$(VIMNAME).1 $DEST_MAN/$(VIMNAME)tutor.1
+ :del {force} $DEST_BIN/vimtutor
+ :del {force} $DEST_BIN/xxd$EXESUF $DEST_MAN/xxd.1
+ :del {force} $DEST_BIN/$EXTARGET $DEST_BIN/$VIEWTARGET
+ :del {force} $DEST_BIN/$GVIMTARGET $DEST_BIN/$GVIEWTARGET
+ :del {force} $DEST_BIN/$RVIMTARGET $DEST_BIN/$RVIEWTARGET
+ :del {force} $DEST_BIN/$RGVIMTARGET $DEST_BIN/$RGVIEWTARGET
+ :del {force} $DEST_BIN/$VIMDIFFTARGET $DEST_BIN/$GVIMDIFFTARGET
+ :del {force} $DEST_BIN/$EVIMTARGET $DEST_BIN/$EVIEWTARGET
+ :del {force} $DEST_MAN/$(EXNAME).1 $DEST_MAN/$(VIEWNAME).1
+ :del {force} $DEST_MAN/$(GVIMNAME).1 $DEST_MAN/$(GVIEWNAME).1
+ :del {force} $DEST_MAN/$(RVIMNAME).1 $DEST_MAN/$(RVIEWNAME).1
+ :del {force} $DEST_MAN/$(RGVIMNAME).1 $DEST_MAN/$(RGVIEWNAME).1
+ :del {force} $DEST_MAN/$(VIMDIFFNAME).1 $DEST_MAN/$(GVIMDIFFNAME).1
+ :del {force} $DEST_MAN/$(EVIMNAME).1 $DEST_MAN/$(EVIEWNAME).1
+
+# Note: "deldir" will fail if any files were added after "make install", that
+# is intentionally: Keep files the user added.
+uninstall_runtime {virtual}{force}:
+ :del {force} $DEST_HELP/*.txt $DEST_HELP/tags $DEST_HELP/*.pl
+ :del {force} $SYS_MENU_FILE $SYS_SYNMENU_FILE $SYS_DELMENU_FILE
+ :del {force} $SYS_BUGR_FILE $EVIM_FILE $MSWIN_FILE
+ :del {force} $DEST_SCRIPT/gvimrc_example.vim $DEST_SCRIPT/vimrc_example.vim
+ :del {force} $SYS_FILETYPE_FILE $SYS_FTOFF_FILE $SYS_SCRIPTS_FILE
+ :del {force} $SYS_INDOFF_FILE $SYS_INDENT_FILE
+ :del {force} $SYS_FTPLUGOF_FILE $SYS_FTPLUGIN_FILE
+ :del {force} $SYS_OPTWIN_FILE
+ :del {force} $DEST_COL/*.vim $DEST_COL/README.txt
+ :del {force} $DEST_SYN/*.vim $DEST_SYN/README.txt
+ :del {force} $DEST_IND/*.vim $DEST_IND/README.txt
+ :del {force} $DEST_PRINT/*.ps
+ :del {force}{recursive} $DEST_MACRO
+ :del {force}{recursive} $DEST_TUTOR
+ :del {force}{recursive} $DEST_TOOLS
+ :del {force}{recursive} $DEST_LANG
+ :del {force}{recursive} $DEST_KMAP
+ :del {force}{recursive} $DEST_COMP
+ :deldir {force} $DEST_HELP $DEST_COL $DEST_SYN $DEST_IND
+ :del {force}{recursive} $DEST_FTP/*.vim $DEST_FTP/README.txt
+ :del {force} $DEST_PLUG/*.vim $DEST_PLUG/README.txt
+ :deldir {force} $DEST_FTP $DEST_PLUG $DEST_PRINT $DEST_RT
+# This will fail when other Vim versions are installed, no worries.
+ @try:
+ :deldir $DEST_VIM
+ @except:
+ :print Cannot delete $DEST_VIM
+
+
+# vim: sts=4 sw=4 :
diff --git a/src/mark.c b/src/mark.c
new file mode 100644
index 000000000..e1b800eb1
--- /dev/null
+++ b/src/mark.c
@@ -0,0 +1,1617 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * mark.c: functions for setting marks and jumping to them
+ */
+
+#include "vim.h"
+
+/*
+ * This file contains routines to maintain and manipulate marks.
+ */
+
+/*
+ * If a named file mark's lnum is non-zero, it is valid.
+ * If a named file mark's fnum is non-zero, it is for an existing buffer,
+ * otherwise it is from .viminfo and namedfm[n].fname is the file name.
+ * There are marks 'A - 'Z (set by user) and '0 to '9 (set when writing
+ * viminfo).
+ */
+#define EXTRA_MARKS 10 /* marks 0-9 */
+static xfmark_T namedfm[NMARKS + EXTRA_MARKS]; /* marks with file nr */
+
+static void fname2fnum __ARGS((xfmark_T *fm));
+static void fmarks_check_one __ARGS((xfmark_T *fm, char_u *name, buf_T *buf));
+static char_u *mark_line __ARGS((pos_T *mp, int lead_len));
+static void show_one_mark __ARGS((int, char_u *, pos_T *, char_u *, int current));
+#ifdef FEAT_JUMPLIST
+static void cleanup_jumplist __ARGS((void));
+#endif
+#ifdef FEAT_VIMINFO
+static void write_one_filemark __ARGS((FILE *fp, xfmark_T *fm, int c1, int c2));
+#endif
+
+/*
+ * Set named mark 'c' at current cursor position.
+ * Returns OK on success, FAIL if bad name given.
+ */
+ int
+setmark(c)
+ int c;
+{
+ int i;
+
+ /* Check for a special key (may cause islower() to crash). */
+ if (c < 0)
+ return FAIL;
+
+ if (c == '\'' || c == '`')
+ {
+ setpcmark();
+ /* keep it even when the cursor doesn't move */
+ curwin->w_prev_pcmark = curwin->w_pcmark;
+ return OK;
+ }
+
+ /* Allow setting '[ and '] for an autocommand that simulates reading a
+ * file. */
+ if (c == '[')
+ {
+ curbuf->b_op_start = curwin->w_cursor;
+ return OK;
+ }
+ if (c == ']')
+ {
+ curbuf->b_op_end = curwin->w_cursor;
+ return OK;
+ }
+
+#ifndef EBCDIC
+ if (c > 'z') /* some islower() and isupper() cannot handle
+ characters above 127 */
+ return FAIL;
+#endif
+ if (islower(c))
+ {
+ i = c - 'a';
+ curbuf->b_namedm[i] = curwin->w_cursor;
+ return OK;
+ }
+ if (isupper(c))
+ {
+ i = c - 'A';
+ namedfm[i].fmark.mark = curwin->w_cursor;
+ namedfm[i].fmark.fnum = curbuf->b_fnum;
+ vim_free(namedfm[i].fname);
+ namedfm[i].fname = NULL;
+ return OK;
+ }
+ return FAIL;
+}
+
+/*
+ * Set the previous context mark to the current position and add it to the
+ * jump list.
+ */
+ void
+setpcmark()
+{
+#ifdef FEAT_JUMPLIST
+ int i;
+ xfmark_T *fm;
+#endif
+#ifdef JUMPLIST_ROTATE
+ xfmark_T tempmark;
+#endif
+
+ /* for :global the mark is set only once */
+ if (global_busy || listcmd_busy || cmdmod.keepjumps)
+ return;
+
+ curwin->w_prev_pcmark = curwin->w_pcmark;
+ curwin->w_pcmark = curwin->w_cursor;
+
+#ifdef FEAT_JUMPLIST
+# ifdef JUMPLIST_ROTATE
+ /*
+ * If last used entry is not at the top, put it at the top by rotating
+ * the stack until it is (the newer entries will be at the bottom).
+ * Keep one entry (the last used one) at the top.
+ */
+ if (curwin->w_jumplistidx < curwin->w_jumplistlen)
+ ++curwin->w_jumplistidx;
+ while (curwin->w_jumplistidx < curwin->w_jumplistlen)
+ {
+ tempmark = curwin->w_jumplist[curwin->w_jumplistlen - 1];
+ for (i = curwin->w_jumplistlen - 1; i > 0; --i)
+ curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
+ curwin->w_jumplist[0] = tempmark;
+ ++curwin->w_jumplistidx;
+ }
+# endif
+
+ /* If jumplist is full: remove oldest entry */
+ if (++curwin->w_jumplistlen > JUMPLISTSIZE)
+ {
+ curwin->w_jumplistlen = JUMPLISTSIZE;
+ vim_free(curwin->w_jumplist[0].fname);
+ for (i = 1; i < JUMPLISTSIZE; ++i)
+ curwin->w_jumplist[i - 1] = curwin->w_jumplist[i];
+ }
+ curwin->w_jumplistidx = curwin->w_jumplistlen;
+ fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
+
+ fm->fmark.mark = curwin->w_pcmark;
+ fm->fmark.fnum = curbuf->b_fnum;
+ fm->fname = NULL;
+#endif
+}
+
+/*
+ * To change context, call setpcmark(), then move the current position to
+ * where ever, then call checkpcmark(). This ensures that the previous
+ * context will only be changed if the cursor moved to a different line.
+ * If pcmark was deleted (with "dG") the previous mark is restored.
+ */
+ void
+checkpcmark()
+{
+ if (curwin->w_prev_pcmark.lnum != 0
+ && (equalpos(curwin->w_pcmark, curwin->w_cursor)
+ || curwin->w_pcmark.lnum == 0))
+ {
+ curwin->w_pcmark = curwin->w_prev_pcmark;
+ curwin->w_prev_pcmark.lnum = 0; /* Show it has been checked */
+ }
+}
+
+#if defined(FEAT_JUMPLIST) || defined(PROTO)
+/*
+ * move "count" positions in the jump list (count may be negative)
+ */
+ pos_T *
+movemark(count)
+ int count;
+{
+ pos_T *pos;
+ xfmark_T *jmp;
+
+ cleanup_jumplist();
+
+ if (curwin->w_jumplistlen == 0) /* nothing to jump to */
+ return (pos_T *)NULL;
+
+ for (;;)
+ {
+ if (curwin->w_jumplistidx + count < 0
+ || curwin->w_jumplistidx + count >= curwin->w_jumplistlen)
+ return (pos_T *)NULL;
+
+ /*
+ * if first CTRL-O or CTRL-I command after a jump, add cursor position
+ * to list. Careful: If there are duplicates (CTRL-O immidiately after
+ * starting Vim on a file), another entry may have been removed.
+ */
+ if (curwin->w_jumplistidx == curwin->w_jumplistlen)
+ {
+ setpcmark();
+ --curwin->w_jumplistidx; /* skip the new entry */
+ if (curwin->w_jumplistidx + count < 0)
+ return (pos_T *)NULL;
+ }
+
+ curwin->w_jumplistidx += count;
+
+ jmp = curwin->w_jumplist + curwin->w_jumplistidx;
+ if (jmp->fmark.fnum == 0)
+ fname2fnum(jmp);
+ if (jmp->fmark.fnum != curbuf->b_fnum)
+ {
+ /* jump to other file */
+ if (buflist_findnr(jmp->fmark.fnum) == NULL)
+ { /* Skip this one .. */
+ count += count < 0 ? -1 : 1;
+ continue;
+ }
+ if (buflist_getfile(jmp->fmark.fnum, jmp->fmark.mark.lnum,
+ 0, FALSE) == FAIL)
+ return (pos_T *)NULL;
+ /* Set lnum again, autocommands my have changed it */
+ curwin->w_cursor = jmp->fmark.mark;
+ pos = (pos_T *)-1;
+ }
+ else
+ pos = &(jmp->fmark.mark);
+ return pos;
+ }
+}
+
+/*
+ * Move "count" positions in the changelist (count may be negative).
+ */
+ pos_T *
+movechangelist(count)
+ int count;
+{
+ int n;
+
+ if (curbuf->b_changelistlen == 0) /* nothing to jump to */
+ return (pos_T *)NULL;
+
+ n = curwin->w_changelistidx;
+ if (n + count < 0)
+ {
+ if (n == 0)
+ return (pos_T *)NULL;
+ n = 0;
+ }
+ else if (n + count >= curbuf->b_changelistlen)
+ {
+ if (n == curbuf->b_changelistlen - 1)
+ return (pos_T *)NULL;
+ n = curbuf->b_changelistlen - 1;
+ }
+ else
+ n += count;
+ curwin->w_changelistidx = n;
+ return curbuf->b_changelist + n;
+}
+#endif
+
+/*
+ * Find mark "c".
+ * Returns:
+ * - pointer to pos_T if found. lnum is 0 when mark not set, -1 when mark is
+ * in another file which can't be gotten. (caller needs to check lnum!)
+ * - NULL if there is no mark called 'c'.
+ * - -1 if mark is in other file and jumped there (only if changefile is TRUE)
+ */
+ pos_T *
+getmark(c, changefile)
+ int c;
+ int changefile; /* allowed to edit another file */
+{
+ pos_T *posp;
+#ifdef FEAT_VISUAL
+ pos_T *startp, *endp;
+#endif
+ static pos_T pos_copy;
+
+ posp = NULL;
+
+ /* Check for special key, can't be a mark name and might cause islower()
+ * to crash. */
+ if (c < 0)
+ return posp;
+#ifndef EBCDIC
+ if (c > '~') /* check for islower()/isupper() */
+ ;
+ else
+#endif
+ if (c == '\'' || c == '`') /* previous context mark */
+ {
+ pos_copy = curwin->w_pcmark; /* need to make a copy because */
+ posp = &pos_copy; /* w_pcmark may be changed soon */
+ }
+ else if (c == '"') /* to pos when leaving buffer */
+ posp = &(curbuf->b_last_cursor);
+ else if (c == '^') /* to where Insert mode stopped */
+ posp = &(curbuf->b_last_insert);
+ else if (c == '.') /* to where last change was made */
+ posp = &(curbuf->b_last_change);
+ else if (c == '[') /* to start of previous operator */
+ posp = &(curbuf->b_op_start);
+ else if (c == ']') /* to end of previous operator */
+ posp = &(curbuf->b_op_end);
+ else if (c == '{' || c == '}') /* to previous/next paragraph */
+ {
+ pos_T pos;
+ oparg_T oa;
+ int slcb = listcmd_busy;
+
+ pos = curwin->w_cursor;
+ listcmd_busy = TRUE; /* avoid that '' is changed */
+ if (findpar(&oa, c == '}' ? FORWARD : BACKWARD, 1L, NUL, FALSE))
+ {
+ pos_copy = curwin->w_cursor;
+ posp = &pos_copy;
+ }
+ curwin->w_cursor = pos;
+ listcmd_busy = slcb;
+ }
+ else if (c == '(' || c == ')') /* to previous/next sentence */
+ {
+ pos_T pos;
+ int slcb = listcmd_busy;
+
+ pos = curwin->w_cursor;
+ listcmd_busy = TRUE; /* avoid that '' is changed */
+ if (findsent(c == ')' ? FORWARD : BACKWARD, 1L))
+ {
+ pos_copy = curwin->w_cursor;
+ posp = &pos_copy;
+ }
+ curwin->w_cursor = pos;
+ listcmd_busy = slcb;
+ }
+#ifdef FEAT_VISUAL
+ else if (c == '<' || c == '>') /* start/end of visual area */
+ {
+ startp = &curbuf->b_visual_start;
+ endp = &curbuf->b_visual_end;
+ if ((c == '<') == lt(*startp, *endp))
+ posp = startp;
+ else
+ posp = endp;
+ /*
+ * For Visual line mode, set mark at begin or end of line
+ */
+ if (curbuf->b_visual_mode == 'V')
+ {
+ pos_copy = *posp;
+ posp = &pos_copy;
+ if (c == '<')
+ pos_copy.col = 0;
+ else
+ pos_copy.col = MAXCOL;
+#ifdef FEAT_VIRTUALEDIT
+ pos_copy.coladd = 0;
+#endif
+ }
+ }
+#endif
+ else if (ASCII_ISLOWER(c)) /* normal named mark */
+ {
+ posp = &(curbuf->b_namedm[c - 'a']);
+ }
+ else if (ASCII_ISUPPER(c) || VIM_ISDIGIT(c)) /* named file mark */
+ {
+ if (VIM_ISDIGIT(c))
+ c = c - '0' + NMARKS;
+ else
+ c -= 'A';
+ posp = &(namedfm[c].fmark.mark);
+
+ if (namedfm[c].fmark.fnum == 0)
+ fname2fnum(&namedfm[c]);
+ if (namedfm[c].fmark.fnum != curbuf->b_fnum)
+ {
+ posp = &pos_copy;
+
+ /* mark is in another file */
+ if (namedfm[c].fmark.mark.lnum != 0
+ && changefile && namedfm[c].fmark.fnum)
+ {
+ if (buflist_getfile(namedfm[c].fmark.fnum,
+ (linenr_T)1, GETF_SETMARK, FALSE) == OK)
+ {
+ /* Set the lnum now, autocommands could have changed it */
+ curwin->w_cursor = namedfm[c].fmark.mark;
+ return (pos_T *)-1;
+ }
+ pos_copy.lnum = -1; /* can't get file */
+ }
+ else
+ pos_copy.lnum = 0; /* mark exists, but is not valid in
+ current buffer */
+ }
+ }
+
+ return posp;
+}
+
+/*
+ * Search for the next named mark in the current file.
+ *
+ * Returns pointer to pos_T of the next mark or NULL if no mark is found.
+ */
+ pos_T *
+getnextmark(startpos, dir, begin_line)
+ pos_T *startpos; /* where to start */
+ int dir; /* direction for search */
+ int begin_line;
+{
+ int i;
+ pos_T *result = NULL;
+ pos_T pos;
+
+ pos = *startpos;
+
+ /* When searching backward and leaving the cursor on the first non-blank,
+ * position must be in a previous line.
+ * When searching forward and leaving the cursor on the first non-blank,
+ * position must be in a next line. */
+ if (dir == BACKWARD && begin_line)
+ pos.col = 0;
+ else if (dir == FORWARD && begin_line)
+ pos.col = MAXCOL;
+
+ for (i = 0; i < NMARKS; i++)
+ {
+ if (curbuf->b_namedm[i].lnum > 0)
+ {
+ if (dir == FORWARD)
+ {
+ if ((result == NULL || lt(curbuf->b_namedm[i], *result))
+ && lt(pos, curbuf->b_namedm[i]))
+ result = &curbuf->b_namedm[i];
+ }
+ else
+ {
+ if ((result == NULL || lt(*result, curbuf->b_namedm[i]))
+ && lt(curbuf->b_namedm[i], pos))
+ result = &curbuf->b_namedm[i];
+ }
+ }
+ }
+
+ return result;
+}
+
+/*
+ * For an xtended filemark: set the fnum from the fname.
+ * This is used for marks obtained from the .viminfo file. It's postponed
+ * until the mark is used to avoid a long startup delay.
+ */
+ static void
+fname2fnum(fm)
+ xfmark_T *fm;
+{
+ char_u *p;
+
+ if (fm->fname != NULL)
+ {
+ /*
+ * First expand "~/" in the file name to the home directory.
+ * Try to shorten the file name.
+ */
+ expand_env(fm->fname, NameBuff, MAXPATHL);
+ mch_dirname(IObuff, IOSIZE);
+ p = shorten_fname(NameBuff, IObuff);
+
+ /* buflist_new() will call fmarks_check_names() */
+ (void)buflist_new(NameBuff, p, (linenr_T)1, 0);
+ }
+}
+
+/*
+ * Check all file marks for a name that matches the file name in buf.
+ * May replace the name with an fnum.
+ * Used for marks that come from the .viminfo file.
+ */
+ void
+fmarks_check_names(buf)
+ buf_T *buf;
+{
+ char_u *name;
+ int i;
+#ifdef FEAT_JUMPLIST
+ win_T *wp;
+#endif
+
+ if (buf->b_ffname == NULL)
+ return;
+
+ name = home_replace_save(buf, buf->b_ffname);
+ if (name == NULL)
+ return;
+
+ for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
+ fmarks_check_one(&namedfm[i], name, buf);
+
+#ifdef FEAT_JUMPLIST
+ FOR_ALL_WINDOWS(wp)
+ {
+ for (i = 0; i < wp->w_jumplistlen; ++i)
+ fmarks_check_one(&wp->w_jumplist[i], name, buf);
+ }
+#endif
+
+ vim_free(name);
+}
+
+ static void
+fmarks_check_one(fm, name, buf)
+ xfmark_T *fm;
+ char_u *name;
+ buf_T *buf;
+{
+ if (fm->fmark.fnum == 0
+ && fm->fname != NULL
+ && fnamecmp(name, fm->fname) == 0)
+ {
+ fm->fmark.fnum = buf->b_fnum;
+ vim_free(fm->fname);
+ fm->fname = NULL;
+ }
+}
+
+/*
+ * Check a if a position from a mark is valid.
+ * Give and error message and return FAIL if not.
+ */
+ int
+check_mark(pos)
+ pos_T *pos;
+{
+ if (pos == NULL)
+ {
+ EMSG(_(e_umark));
+ return FAIL;
+ }
+ if (pos->lnum <= 0)
+ {
+ /* lnum is negative if mark is in another file can can't get that
+ * file, error message already give then. */
+ if (pos->lnum == 0)
+ EMSG(_(e_marknotset));
+ return FAIL;
+ }
+ if (pos->lnum > curbuf->b_ml.ml_line_count)
+ {
+ EMSG(_(e_markinval));
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
+ * clrallmarks() - clear all marks in the buffer 'buf'
+ *
+ * Used mainly when trashing the entire buffer during ":e" type commands
+ */
+ void
+clrallmarks(buf)
+ buf_T *buf;
+{
+ static int i = -1;
+
+ if (i == -1) /* first call ever: initialize */
+ for (i = 0; i < NMARKS + 1; i++)
+ {
+ namedfm[i].fmark.mark.lnum = 0;
+ namedfm[i].fname = NULL;
+ }
+
+ for (i = 0; i < NMARKS; i++)
+ buf->b_namedm[i].lnum = 0;
+ buf->b_op_start.lnum = 0; /* start/end op mark cleared */
+ buf->b_op_end.lnum = 0;
+ buf->b_last_cursor.lnum = 1; /* '" mark cleared */
+ buf->b_last_cursor.col = 0;
+#ifdef FEAT_VIRTUALEDIT
+ buf->b_last_cursor.coladd = 0;
+#endif
+ buf->b_last_insert.lnum = 0; /* '^ mark cleared */
+ buf->b_last_change.lnum = 0; /* '. mark cleared */
+#ifdef FEAT_JUMPLIST
+ buf->b_changelistlen = 0;
+#endif
+}
+
+/*
+ * Get name of file from a filemark.
+ * When it's in the current buffer, return the text at the mark.
+ * Returns an allocated string.
+ */
+ char_u *
+fm_getname(fmark, lead_len)
+ fmark_T *fmark;
+ int lead_len;
+{
+ if (fmark->fnum == curbuf->b_fnum) /* current buffer */
+ return mark_line(&(fmark->mark), lead_len);
+ return buflist_nr2name(fmark->fnum, FALSE, TRUE);
+}
+
+/*
+ * Return the line at mark "mp". Truncate to fit in window.
+ * The returned string has been allocated.
+ */
+ static char_u *
+mark_line(mp, lead_len)
+ pos_T *mp;
+ int lead_len;
+{
+ char_u *s, *p;
+ int len;
+
+ if (mp->lnum == 0 || mp->lnum > curbuf->b_ml.ml_line_count)
+ return vim_strsave((char_u *)"-invalid-");
+ s = vim_strnsave(skipwhite(ml_get(mp->lnum)), (int)Columns);
+ if (s == NULL)
+ return NULL;
+ /* Truncate the line to fit it in the window */
+ len = 0;
+ for (p = s; *p != NUL; ++p)
+ {
+ len += ptr2cells(p);
+ if (len >= Columns - lead_len)
+ break;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ *p = NUL;
+ return s;
+}
+
+/*
+ * print the marks
+ */
+ void
+do_marks(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+ int i;
+ char_u *name;
+
+ if (arg != NULL && *arg == NUL)
+ arg = NULL;
+
+ show_one_mark('\'', arg, &curwin->w_pcmark, NULL, TRUE);
+ for (i = 0; i < NMARKS; ++i)
+ show_one_mark(i + 'a', arg, &curbuf->b_namedm[i], NULL, TRUE);
+ for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
+ {
+ if (namedfm[i].fmark.fnum != 0)
+ name = fm_getname(&namedfm[i].fmark, 15);
+ else
+ name = namedfm[i].fname;
+ if (name != NULL)
+ {
+ show_one_mark(i >= NMARKS ? i - NMARKS + '0' : i + 'A',
+ arg, &namedfm[i].fmark.mark, name,
+ namedfm[i].fmark.fnum == curbuf->b_fnum);
+ if (namedfm[i].fmark.fnum != 0)
+ vim_free(name);
+ }
+ }
+ show_one_mark('"', arg, &curbuf->b_last_cursor, NULL, TRUE);
+ show_one_mark('[', arg, &curbuf->b_op_start, NULL, TRUE);
+ show_one_mark(']', arg, &curbuf->b_op_end, NULL, TRUE);
+ show_one_mark('^', arg, &curbuf->b_last_insert, NULL, TRUE);
+ show_one_mark('.', arg, &curbuf->b_last_change, NULL, TRUE);
+#ifdef FEAT_VISUAL
+ show_one_mark('<', arg, &curbuf->b_visual_start, NULL, TRUE);
+ show_one_mark('>', arg, &curbuf->b_visual_end, NULL, TRUE);
+#endif
+ show_one_mark(-1, arg, NULL, NULL, FALSE);
+}
+
+ static void
+show_one_mark(c, arg, p, name, current)
+ int c;
+ char_u *arg;
+ pos_T *p;
+ char_u *name;
+ int current; /* in current file */
+{
+ static int did_title = FALSE;
+ int mustfree = FALSE;
+
+ if (c == -1) /* finish up */
+ {
+ if (did_title)
+ did_title = FALSE;
+ else
+ {
+ if (arg == NULL)
+ MSG(_("No marks set"));
+ else
+ EMSG2(_("E283: No marks matching \"%s\""), arg);
+ }
+ }
+ /* don't output anything if 'q' typed at --more-- prompt */
+ else if (!got_int
+ && (arg == NULL || vim_strchr(arg, c) != NULL)
+ && p->lnum != 0)
+ {
+ if (!did_title)
+ {
+ /* Highlight title */
+ MSG_PUTS_TITLE(_("\nmark line col file/text"));
+ did_title = TRUE;
+ }
+ msg_putchar('\n');
+ if (!got_int)
+ {
+ sprintf((char *)IObuff, " %c %6ld %4d ", c, p->lnum, p->col);
+ msg_outtrans(IObuff);
+ if (name == NULL && current)
+ {
+ name = mark_line(p, 15);
+ mustfree = TRUE;
+ }
+ if (name != NULL)
+ {
+ msg_outtrans_attr(name, current ? hl_attr(HLF_D) : 0);
+ if (mustfree)
+ vim_free(name);
+ }
+ }
+ out_flush(); /* show one line at a time */
+ }
+}
+
+#if defined(FEAT_JUMPLIST) || defined(PROTO)
+/*
+ * print the jumplist
+ */
+/*ARGSUSED*/
+ void
+ex_jumps(eap)
+ exarg_T *eap;
+{
+ int i;
+ char_u *name;
+
+ cleanup_jumplist();
+ /* Highlight title */
+ MSG_PUTS_TITLE(_("\n jump line col file/text"));
+ for (i = 0; i < curwin->w_jumplistlen && !got_int; ++i)
+ {
+ if (curwin->w_jumplist[i].fmark.mark.lnum != 0)
+ {
+ if (curwin->w_jumplist[i].fmark.fnum == 0)
+ fname2fnum(&curwin->w_jumplist[i]);
+ name = fm_getname(&curwin->w_jumplist[i].fmark, 16);
+ if (name == NULL) /* file name not available */
+ continue;
+
+ msg_putchar('\n');
+ if (got_int)
+ break;
+ sprintf((char *)IObuff, "%c %2d %5ld %4d ",
+ i == curwin->w_jumplistidx ? '>' : ' ',
+ i > curwin->w_jumplistidx ? i - curwin->w_jumplistidx
+ : curwin->w_jumplistidx - i,
+ curwin->w_jumplist[i].fmark.mark.lnum,
+ curwin->w_jumplist[i].fmark.mark.col);
+ msg_outtrans(IObuff);
+ msg_outtrans_attr(name,
+ curwin->w_jumplist[i].fmark.fnum == curbuf->b_fnum
+ ? hl_attr(HLF_D) : 0);
+ vim_free(name);
+ ui_breakcheck();
+ }
+ out_flush();
+ }
+ if (curwin->w_jumplistidx == curwin->w_jumplistlen)
+ MSG_PUTS("\n>");
+}
+
+/*
+ * print the changelist
+ */
+/*ARGSUSED*/
+ void
+ex_changes(eap)
+ exarg_T *eap;
+{
+ int i;
+ char_u *name;
+
+ /* Highlight title */
+ MSG_PUTS_TITLE(_("\nchange line col text"));
+
+ for (i = 0; i < curbuf->b_changelistlen && !got_int; ++i)
+ {
+ if (curbuf->b_changelist[i].lnum != 0)
+ {
+ msg_putchar('\n');
+ if (got_int)
+ break;
+ sprintf((char *)IObuff, "%c %3d %5ld %4d ",
+ i == curwin->w_changelistidx ? '>' : ' ',
+ i > curwin->w_changelistidx ? i - curwin->w_changelistidx
+ : curwin->w_changelistidx - i,
+ (long)curbuf->b_changelist[i].lnum,
+ curbuf->b_changelist[i].col);
+ msg_outtrans(IObuff);
+ name = mark_line(&curbuf->b_changelist[i], 17);
+ if (name == NULL)
+ break;
+ msg_outtrans_attr(name, hl_attr(HLF_D));
+ vim_free(name);
+ ui_breakcheck();
+ }
+ out_flush();
+ }
+ if (curwin->w_changelistidx == curbuf->b_changelistlen)
+ MSG_PUTS("\n>");
+}
+#endif
+
+#define one_adjust(add) \
+ { \
+ lp = add; \
+ if (*lp >= line1 && *lp <= line2) \
+ { \
+ if (amount == MAXLNUM) \
+ *lp = 0; \
+ else \
+ *lp += amount; \
+ } \
+ else if (amount_after && *lp > line2) \
+ *lp += amount_after; \
+ }
+
+/* don't delete the line, just put at first deleted line */
+#define one_adjust_nodel(add) \
+ { \
+ lp = add; \
+ if (*lp >= line1 && *lp <= line2) \
+ { \
+ if (amount == MAXLNUM) \
+ *lp = line1; \
+ else \
+ *lp += amount; \
+ } \
+ else if (amount_after && *lp > line2) \
+ *lp += amount_after; \
+ }
+
+/*
+ * Adjust marks between line1 and line2 (inclusive) to move 'amount' lines.
+ * Must be called before changed_*(), appended_lines() or deleted_lines().
+ * May be called before or after changing the text.
+ * When deleting lines line1 to line2, use an 'amount' of MAXLNUM: The marks
+ * within this range are made invalid.
+ * If 'amount_after' is non-zero adjust marks after line2.
+ * Example: Delete lines 34 and 35: mark_adjust(34, 35, MAXLNUM, -2);
+ * Example: Insert two lines below 55: mark_adjust(56, MAXLNUM, 2, 0);
+ * or: mark_adjust(56, 55, MAXLNUM, 2);
+ */
+ void
+mark_adjust(line1, line2, amount, amount_after)
+ linenr_T line1;
+ linenr_T line2;
+ long amount;
+ long amount_after;
+{
+ int i;
+ int fnum = curbuf->b_fnum;
+ linenr_T *lp;
+ win_T *win;
+
+ if (line2 < line1 && amount_after == 0L) /* nothing to do */
+ return;
+
+ if (!cmdmod.lockmarks)
+ {
+ /* named marks, lower case and upper case */
+ for (i = 0; i < NMARKS; i++)
+ {
+ one_adjust(&(curbuf->b_namedm[i].lnum));
+ if (namedfm[i].fmark.fnum == fnum)
+ one_adjust_nodel(&(namedfm[i].fmark.mark.lnum));
+ }
+ for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++)
+ {
+ if (namedfm[i].fmark.fnum == fnum)
+ one_adjust_nodel(&(namedfm[i].fmark.mark.lnum));
+ }
+
+ /* last Insert position */
+ one_adjust(&(curbuf->b_last_insert.lnum));
+
+ /* last change position */
+ one_adjust(&(curbuf->b_last_change.lnum));
+
+#ifdef FEAT_JUMPLIST
+ /* list of change positions */
+ for (i = 0; i < curbuf->b_changelistlen; ++i)
+ one_adjust_nodel(&(curbuf->b_changelist[i].lnum));
+#endif
+
+#ifdef FEAT_VISUAL
+ /* Visual area */
+ one_adjust_nodel(&(curbuf->b_visual_start.lnum));
+ one_adjust_nodel(&(curbuf->b_visual_end.lnum));
+#endif
+
+#ifdef FEAT_QUICKFIX
+ /* quickfix marks */
+ qf_mark_adjust(line1, line2, amount, amount_after);
+#endif
+
+#ifdef FEAT_SIGNS
+ sign_mark_adjust(line1, line2, amount, amount_after);
+#endif
+ }
+
+ /* previous context mark */
+ one_adjust(&(curwin->w_pcmark.lnum));
+
+ /* previous pcmark */
+ one_adjust(&(curwin->w_prev_pcmark.lnum));
+
+ /* saved cursor for formatting */
+ if (saved_cursor.lnum != 0)
+ one_adjust_nodel(&(saved_cursor.lnum));
+
+ /*
+ * Adjust items in all windows related to the current buffer.
+ */
+ FOR_ALL_WINDOWS(win)
+ {
+#ifdef FEAT_JUMPLIST
+ if (!cmdmod.lockmarks)
+ /* Marks in the jumplist. When deleting lines, this may create
+ * duplicate marks in the jumplist, they will be removed later. */
+ for (i = 0; i < win->w_jumplistlen; ++i)
+ if (win->w_jumplist[i].fmark.fnum == fnum)
+ one_adjust_nodel(&(win->w_jumplist[i].fmark.mark.lnum));
+#endif
+
+ if (win->w_buffer == curbuf)
+ {
+ if (!cmdmod.lockmarks)
+ /* marks in the tag stack */
+ for (i = 0; i < win->w_tagstacklen; i++)
+ if (win->w_tagstack[i].fmark.fnum == fnum)
+ one_adjust_nodel(&(win->w_tagstack[i].fmark.mark.lnum));
+
+#ifdef FEAT_VISUAL
+ /* the displayed Visual area */
+ if (win->w_old_cursor_lnum != 0)
+ {
+ one_adjust_nodel(&(win->w_old_cursor_lnum));
+ one_adjust_nodel(&(win->w_old_visual_lnum));
+ }
+#endif
+
+ /* topline and cursor position for windows with the same buffer
+ * other than the current window */
+ if (win != curwin)
+ {
+ if (win->w_topline >= line1 && win->w_topline <= line2)
+ {
+ if (amount == MAXLNUM) /* topline is deleted */
+ {
+ if (line1 <= 1)
+ win->w_topline = 1;
+ else
+ win->w_topline = line1 - 1;
+ }
+ else /* keep topline on the same line */
+ win->w_topline += amount;
+#ifdef FEAT_DIFF
+ win->w_topfill = 0;
+#endif
+ }
+ else if (amount_after && win->w_topline > line2)
+ {
+ win->w_topline += amount_after;
+#ifdef FEAT_DIFF
+ win->w_topfill = 0;
+#endif
+ }
+ if (win->w_cursor.lnum >= line1 && win->w_cursor.lnum <= line2)
+ {
+ if (amount == MAXLNUM) /* line with cursor is deleted */
+ {
+ if (line1 <= 1)
+ win->w_cursor.lnum = 1;
+ else
+ win->w_cursor.lnum = line1 - 1;
+ win->w_cursor.col = 0;
+ }
+ else /* keep cursor on the same line */
+ win->w_cursor.lnum += amount;
+ }
+ else if (amount_after && win->w_cursor.lnum > line2)
+ win->w_cursor.lnum += amount_after;
+ }
+
+#ifdef FEAT_FOLDING
+ /* adjust folds */
+ foldMarkAdjust(win, line1, line2, amount, amount_after);
+#endif
+ }
+ }
+
+#ifdef FEAT_DIFF
+ /* adjust diffs */
+ diff_mark_adjust(line1, line2, amount, amount_after);
+#endif
+}
+
+/* This code is used often, needs to be fast. */
+#define col_adjust(pp) \
+ { \
+ posp = pp; \
+ if (posp->lnum == lnum && posp->col >= mincol) \
+ { \
+ posp->lnum += lnum_amount; \
+ if (col_amount < 0 && posp->col <= (colnr_T)-col_amount) \
+ posp->col = 0; \
+ else \
+ posp->col += col_amount; \
+ } \
+ }
+
+/*
+ * Adjust marks in line "lnum" at column "mincol" and further: add
+ * "lnum_amount" to the line number and add "col_amount" to the column
+ * position.
+ */
+ void
+mark_col_adjust(lnum, mincol, lnum_amount, col_amount)
+ linenr_T lnum;
+ colnr_T mincol;
+ long lnum_amount;
+ long col_amount;
+{
+ int i;
+ int fnum = curbuf->b_fnum;
+ win_T *win;
+ pos_T *posp;
+
+ if ((col_amount == 0L && lnum_amount == 0L) || cmdmod.lockmarks)
+ return; /* nothing to do */
+
+ /* named marks, lower case and upper case */
+ for (i = 0; i < NMARKS; i++)
+ {
+ col_adjust(&(curbuf->b_namedm[i]));
+ if (namedfm[i].fmark.fnum == fnum)
+ col_adjust(&(namedfm[i].fmark.mark));
+ }
+ for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++)
+ {
+ if (namedfm[i].fmark.fnum == fnum)
+ col_adjust(&(namedfm[i].fmark.mark));
+ }
+
+ /* last Insert position */
+ col_adjust(&(curbuf->b_last_insert));
+
+ /* last change position */
+ col_adjust(&(curbuf->b_last_change));
+
+#ifdef FEAT_JUMPLIST
+ /* list of change positions */
+ for (i = 0; i < curbuf->b_changelistlen; ++i)
+ col_adjust(&(curbuf->b_changelist[i]));
+#endif
+
+#ifdef FEAT_VISUAL
+ /* Visual area */
+ col_adjust(&(curbuf->b_visual_start));
+ col_adjust(&(curbuf->b_visual_end));
+#endif
+
+ /* previous context mark */
+ col_adjust(&(curwin->w_pcmark));
+
+ /* previous pcmark */
+ col_adjust(&(curwin->w_prev_pcmark));
+
+ /* saved cursor for formatting */
+ col_adjust(&saved_cursor);
+
+ /*
+ * Adjust items in all windows related to the current buffer.
+ */
+ FOR_ALL_WINDOWS(win)
+ {
+#ifdef FEAT_JUMPLIST
+ /* marks in the jumplist */
+ for (i = 0; i < win->w_jumplistlen; ++i)
+ if (win->w_jumplist[i].fmark.fnum == fnum)
+ col_adjust(&(win->w_jumplist[i].fmark.mark));
+#endif
+
+ if (win->w_buffer == curbuf)
+ {
+ /* marks in the tag stack */
+ for (i = 0; i < win->w_tagstacklen; i++)
+ if (win->w_tagstack[i].fmark.fnum == fnum)
+ col_adjust(&(win->w_tagstack[i].fmark.mark));
+
+ /* cursor position for other windows with the same buffer */
+ if (win != curwin)
+ col_adjust(&win->w_cursor);
+ }
+ }
+}
+
+#ifdef FEAT_JUMPLIST
+/*
+ * When deleting lines, this may create duplicate marks in the
+ * jumplist. They will be removed here for the current window.
+ */
+ static void
+cleanup_jumplist()
+{
+ int i;
+ int from, to;
+
+ to = 0;
+ for (from = 0; from < curwin->w_jumplistlen; ++from)
+ {
+ if (curwin->w_jumplistidx == from)
+ curwin->w_jumplistidx = to;
+ for (i = from + 1; i < curwin->w_jumplistlen; ++i)
+ if (curwin->w_jumplist[i].fmark.fnum
+ == curwin->w_jumplist[from].fmark.fnum
+ && curwin->w_jumplist[from].fmark.fnum != 0
+ && curwin->w_jumplist[i].fmark.mark.lnum
+ == curwin->w_jumplist[from].fmark.mark.lnum)
+ break;
+ if (i >= curwin->w_jumplistlen) /* no duplicate */
+ curwin->w_jumplist[to++] = curwin->w_jumplist[from];
+ else
+ vim_free(curwin->w_jumplist[from].fname);
+ }
+ if (curwin->w_jumplistidx == curwin->w_jumplistlen)
+ curwin->w_jumplistidx = to;
+ curwin->w_jumplistlen = to;
+}
+
+# if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * Copy the jumplist from window "from" to window "to".
+ */
+ void
+copy_jumplist(from, to)
+ win_T *from;
+ win_T *to;
+{
+ int i;
+
+ for (i = 0; i < from->w_jumplistlen; ++i)
+ {
+ to->w_jumplist[i] = from->w_jumplist[i];
+ if (from->w_jumplist[i].fname != NULL)
+ to->w_jumplist[i].fname = vim_strsave(from->w_jumplist[i].fname);
+ }
+ to->w_jumplistlen = from->w_jumplistlen;
+ to->w_jumplistidx = from->w_jumplistidx;
+}
+
+/*
+ * Free items in the jumplist of window "wp".
+ */
+ void
+free_jumplist(wp)
+ win_T *wp;
+{
+ int i;
+
+ for (i = 0; i < wp->w_jumplistlen; ++i)
+ vim_free(wp->w_jumplist[i].fname);
+}
+# endif
+#endif /* FEAT_JUMPLIST */
+
+ void
+set_last_cursor(win)
+ win_T *win;
+{
+ win->w_buffer->b_last_cursor = win->w_cursor;
+}
+
+#if defined(FEAT_VIMINFO) || defined(PROTO)
+ int
+read_viminfo_filemark(virp, force)
+ vir_T *virp;
+ int force;
+{
+ char_u *str;
+ xfmark_T *fm;
+ int i;
+
+ /* We only get here if line[0] == '\'' or '-'.
+ * Illegal mark names are ignored (for future expansion). */
+ str = virp->vir_line + 1;
+ if (
+#ifndef EBCDIC
+ *str <= 127 &&
+#endif
+ ((*virp->vir_line == '\'' && (VIM_ISDIGIT(*str) || isupper(*str)))
+ || (*virp->vir_line == '-' && *str == '\'')))
+ {
+ if (*str == '\'')
+ {
+#ifdef FEAT_JUMPLIST
+ /* If the jumplist isn't full insert fmark as oldest entry */
+ if (curwin->w_jumplistlen == JUMPLISTSIZE)
+ fm = NULL;
+ else
+ {
+ for (i = curwin->w_jumplistlen; i > 0; --i)
+ curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
+ ++curwin->w_jumplistidx;
+ ++curwin->w_jumplistlen;
+ fm = &curwin->w_jumplist[0];
+ fm->fmark.mark.lnum = 0;
+ fm->fname = NULL;
+ }
+#else
+ fm = NULL;
+#endif
+ }
+ else if (VIM_ISDIGIT(*str))
+ fm = &namedfm[*str - '0' + NMARKS];
+ else
+ fm = &namedfm[*str - 'A'];
+ if (fm != NULL && (fm->fmark.mark.lnum == 0 || force))
+ {
+ str = skipwhite(str + 1);
+ fm->fmark.mark.lnum = getdigits(&str);
+ str = skipwhite(str);
+ fm->fmark.mark.col = getdigits(&str);
+#ifdef FEAT_VIRTUALEDIT
+ fm->fmark.mark.coladd = 0;
+#endif
+ fm->fmark.fnum = 0;
+ str = skipwhite(str);
+ vim_free(fm->fname);
+ fm->fname = viminfo_readstring(virp, (int)(str - virp->vir_line),
+ FALSE);
+ }
+ }
+ return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
+}
+
+ void
+write_viminfo_filemarks(fp)
+ FILE *fp;
+{
+ int i;
+ char_u *name;
+ buf_T *buf;
+ xfmark_T *fm;
+
+ if (get_viminfo_parameter('f') == 0)
+ return;
+
+ fprintf(fp, _("\n# File marks:\n"));
+
+ /*
+ * Find a mark that is the same file and position as the cursor.
+ * That one, or else the last one is deleted.
+ * Move '0 to '1, '1 to '2, etc. until the matching one or '9
+ * Set '0 mark to current cursor position.
+ */
+ if (curbuf->b_ffname != NULL && !removable(curbuf->b_ffname))
+ {
+ name = buflist_nr2name(curbuf->b_fnum, TRUE, FALSE);
+ for (i = NMARKS; i < NMARKS + EXTRA_MARKS - 1; ++i)
+ if (namedfm[i].fmark.mark.lnum == curwin->w_cursor.lnum
+ && (namedfm[i].fname == NULL
+ ? namedfm[i].fmark.fnum == curbuf->b_fnum
+ : (name != NULL
+ && STRCMP(name, namedfm[i].fname) == 0)))
+ break;
+ vim_free(name);
+
+ vim_free(namedfm[i].fname);
+ for ( ; i > NMARKS; --i)
+ namedfm[i] = namedfm[i - 1];
+ namedfm[NMARKS].fmark.mark = curwin->w_cursor;
+ namedfm[NMARKS].fmark.fnum = curbuf->b_fnum;
+ namedfm[NMARKS].fname = NULL;
+ }
+
+ /* Write the filemarks '0 - '9 and 'A - 'Z */
+ for (i = 0; i < NMARKS + EXTRA_MARKS; i++)
+ write_one_filemark(fp, &namedfm[i], '\'',
+ i < NMARKS ? i + 'A' : i - NMARKS + '0');
+
+#ifdef FEAT_JUMPLIST
+ /* Write the jumplist with -' */
+ fprintf(fp, _("\n# Jumplist (newest first):\n"));
+ setpcmark(); /* add current cursor position */
+ cleanup_jumplist();
+ for (fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
+ fm >= &curwin->w_jumplist[0]; --fm)
+ {
+ if (fm->fmark.fnum == 0
+ || ((buf = buflist_findnr(fm->fmark.fnum)) != NULL
+ && !removable(buf->b_ffname)))
+ write_one_filemark(fp, fm, '-', '\'');
+ }
+#endif
+}
+
+ static void
+write_one_filemark(fp, fm, c1, c2)
+ FILE *fp;
+ xfmark_T *fm;
+ int c1;
+ int c2;
+{
+ char_u *name;
+
+ if (fm->fmark.mark.lnum == 0) /* not set */
+ return;
+
+ if (fm->fmark.fnum != 0) /* there is a buffer */
+ name = buflist_nr2name(fm->fmark.fnum, TRUE, FALSE);
+ else
+ name = fm->fname; /* use name from .viminfo */
+ if (name != NULL && *name != NUL)
+ {
+ fprintf(fp, "%c%c %ld %ld ", c1, c2, (long)fm->fmark.mark.lnum,
+ (long)fm->fmark.mark.col);
+ viminfo_writestring(fp, name);
+ }
+
+ if (fm->fmark.fnum != 0)
+ vim_free(name);
+}
+
+/*
+ * Return TRUE if "name" is on removable media (depending on 'viminfo').
+ */
+ int
+removable(name)
+ char_u *name;
+{
+ char_u *p;
+ char_u part[51];
+ int retval = FALSE;
+
+ name = home_replace_save(NULL, name);
+ if (name != NULL)
+ {
+ for (p = p_viminfo; *p; )
+ {
+ copy_option_part(&p, part, 51, ", ");
+ if (part[0] == 'r'
+ && MB_STRNICMP(part + 1, name, STRLEN(part + 1)) == 0)
+ {
+ retval = TRUE;
+ break;
+ }
+ }
+ vim_free(name);
+ }
+ return retval;
+}
+
+static void write_one_mark __ARGS((FILE *fp_out, int c, pos_T *pos));
+
+/*
+ * Write all the named marks for all buffers.
+ * Return the number of buffers for which marks have been written.
+ */
+ int
+write_viminfo_marks(fp_out)
+ FILE *fp_out;
+{
+ int count;
+ buf_T *buf;
+ int is_mark_set;
+ int i;
+#ifdef FEAT_WINDOWS
+ win_T *win;
+
+ /*
+ * Set b_last_cursor for the all buffers that have a window.
+ */
+ for (win = firstwin; win != NULL; win = win->w_next)
+ set_last_cursor(win);
+#else
+ set_last_cursor(curwin);
+#endif
+
+ fprintf(fp_out, _("\n# History of marks within files (newest to oldest):\n"));
+ count = 0;
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ /*
+ * Only write something if buffer has been loaded and at least one
+ * mark is set.
+ */
+ if (buf->b_marks_read)
+ {
+ if (buf->b_last_cursor.lnum != 0)
+ is_mark_set = TRUE;
+ else
+ {
+ is_mark_set = FALSE;
+ for (i = 0; i < NMARKS; i++)
+ if (buf->b_namedm[i].lnum != 0)
+ {
+ is_mark_set = TRUE;
+ break;
+ }
+ }
+ if (is_mark_set && buf->b_ffname != NULL
+ && buf->b_ffname[0] != NUL && !removable(buf->b_ffname))
+ {
+ home_replace(NULL, buf->b_ffname, IObuff, IOSIZE, TRUE);
+ fprintf(fp_out, "\n> ");
+ viminfo_writestring(fp_out, IObuff);
+ write_one_mark(fp_out, '"', &buf->b_last_cursor);
+ write_one_mark(fp_out, '^', &buf->b_last_insert);
+ write_one_mark(fp_out, '.', &buf->b_last_change);
+#ifdef FEAT_JUMPLIST
+ /* changelist positions are stored oldest first */
+ for (i = 0; i < buf->b_changelistlen; ++i)
+ write_one_mark(fp_out, '+', &buf->b_changelist[i]);
+#endif
+ for (i = 0; i < NMARKS; i++)
+ write_one_mark(fp_out, 'a' + i, &buf->b_namedm[i]);
+ count++;
+ }
+ }
+ }
+
+ return count;
+}
+
+ static void
+write_one_mark(fp_out, c, pos)
+ FILE *fp_out;
+ int c;
+ pos_T *pos;
+{
+ if (pos->lnum != 0)
+ fprintf(fp_out, "\t%c\t%ld\t%d\n", c, (long)pos->lnum, (int)pos->col);
+}
+
+/*
+ * Handle marks in the viminfo file:
+ * fp_out == NULL read marks for current buffer only
+ * fp_out != NULL copy marks for buffers not in buffer list
+ */
+ void
+copy_viminfo_marks(virp, fp_out, count, eof)
+ vir_T *virp;
+ FILE *fp_out;
+ int count;
+ int eof;
+{
+ char_u *line = virp->vir_line;
+ buf_T *buf;
+ int num_marked_files;
+ int load_marks;
+ int copy_marks_out;
+ char_u *str;
+ int i;
+ char_u *p;
+ char_u *name_buf;
+ pos_T pos;
+
+ if ((name_buf = alloc(LSIZE)) == NULL)
+ return;
+ *name_buf = NUL;
+ num_marked_files = get_viminfo_parameter('\'');
+ while (!eof && (count < num_marked_files || fp_out == NULL))
+ {
+ if (line[0] != '>')
+ {
+ if (line[0] != '\n' && line[0] != '\r' && line[0] != '#')
+ {
+ if (viminfo_error("E576: ", _("Missing '>'"), line))
+ break; /* too many errors, return now */
+ }
+ eof = vim_fgets(line, LSIZE, virp->vir_fd);
+ continue; /* Skip this dud line */
+ }
+
+ /*
+ * Handle long line and translate escaped characters.
+ * Find file name, set str to start.
+ * Ignore leading and trailing white space.
+ */
+ str = skipwhite(line + 1);
+ str = viminfo_readstring(virp, (int)(str - virp->vir_line), FALSE);
+ if (str == NULL)
+ continue;
+ p = str + STRLEN(str);
+ while (p != str && (*p == NUL || vim_isspace(*p)))
+ p--;
+ if (*p)
+ p++;
+ *p = NUL;
+
+ /*
+ * If fp_out == NULL, load marks for current buffer.
+ * If fp_out != NULL, copy marks for buffers not in buflist.
+ */
+ load_marks = copy_marks_out = FALSE;
+ if (fp_out == NULL)
+ {
+ if (curbuf->b_ffname != NULL)
+ {
+ if (*name_buf == NUL) /* only need to do this once */
+ home_replace(NULL, curbuf->b_ffname, name_buf, LSIZE, TRUE);
+ if (fnamecmp(str, name_buf) == 0)
+ load_marks = TRUE;
+ }
+ }
+ else /* fp_out != NULL */
+ {
+ /* This is slow if there are many buffers!! */
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (buf->b_ffname != NULL)
+ {
+ home_replace(NULL, buf->b_ffname, name_buf, LSIZE, TRUE);
+ if (fnamecmp(str, name_buf) == 0)
+ break;
+ }
+
+ /*
+ * copy marks if the buffer has not been loaded
+ */
+ if (buf == NULL || !buf->b_marks_read)
+ {
+ copy_marks_out = TRUE;
+ fputs("\n> ", fp_out);
+ viminfo_writestring(fp_out, str);
+ count++;
+ }
+ }
+ vim_free(str);
+
+#ifdef FEAT_VIRTUALEDIT
+ pos.coladd = 0;
+#endif
+ while (!(eof = viminfo_readline(virp)) && line[0] == TAB)
+ {
+ if (load_marks)
+ {
+ if (line[1] != NUL)
+ {
+ sscanf((char *)line + 2, "%ld %u", &pos.lnum, &pos.col);
+ switch (line[1])
+ {
+ case '"': curbuf->b_last_cursor = pos; break;
+ case '^': curbuf->b_last_insert = pos; break;
+ case '.': curbuf->b_last_change = pos; break;
+ case '+':
+#ifdef FEAT_JUMPLIST
+ /* changelist positions are stored oldest
+ * first */
+ if (curbuf->b_changelistlen == JUMPLISTSIZE)
+ /* list is full, remove oldest entry */
+ mch_memmove(curbuf->b_changelist,
+ curbuf->b_changelist + 1,
+ sizeof(pos_T) * (JUMPLISTSIZE - 1));
+ else
+ ++curbuf->b_changelistlen;
+ curbuf->b_changelist[
+ curbuf->b_changelistlen - 1] = pos;
+#endif
+ break;
+ default: if ((i = line[1] - 'a') >= 0 && i < NMARKS)
+ curbuf->b_namedm[i] = pos;
+ }
+ }
+ }
+ else if (copy_marks_out)
+ fputs((char *)line, fp_out);
+ }
+ if (load_marks)
+ {
+#ifdef FEAT_JUMPLIST
+ win_T *wp;
+
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_buffer == curbuf)
+ wp->w_changelistidx = curbuf->b_changelistlen;
+ }
+#endif
+ break;
+ }
+ }
+ vim_free(name_buf);
+}
+#endif /* FEAT_VIMINFO */
diff --git a/src/mbyte.c b/src/mbyte.c
new file mode 100644
index 000000000..699316d0e
--- /dev/null
+++ b/src/mbyte.c
@@ -0,0 +1,5833 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Multibyte extensions partly by Sung-Hoon Baek
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * mbyte.c: Code specifically for handling multi-byte characters.
+ *
+ * The encoding used in the core is set with 'encoding'. When 'encoding' is
+ * changed, the following four variables are set (for speed).
+ * Currently these types of character encodings are supported:
+ *
+ * "enc_dbcs" When non-zero it tells the type of double byte character
+ * encoding (Chinese, Korean, Japanese, etc.).
+ * The cell width on the display is equal to the number of
+ * bytes. (exception: DBCS_JPNU with first byte 0x8e)
+ * Recognizing the first or second byte is difficult, it
+ * requires checking a byte sequence from the start.
+ * "enc_utf8" When TRUE use Unicode characters in UTF-8 encoding.
+ * The cell width on the display needs to be determined from
+ * the character value.
+ * Recognizing bytes is easy: 0xxx.xxxx is a single-byte
+ * char, 10xx.xxxx is a trailing byte, 11xx.xxxx is a leading
+ * byte of a multi-byte character.
+ * To make things complicated, up to two composing characters
+ * are allowed. These are drawn on top of the first char.
+ * For most editing the sequence of bytes with composing
+ * characters included is considered to be one character.
+ * "enc_unicode" When 2 use 16-bit Unicode characters (or UTF-16).
+ * When 4 use 32-but Unicode characters.
+ * Internally characters are stored in UTF-8 encoding to
+ * avoid NUL bytes. Conversion happens when doing I/O.
+ * "enc_utf8" will also be TRUE.
+ *
+ * "has_mbyte" is set when "enc_dbcs" or "enc_utf8" is non-zero.
+ *
+ * If none of these is TRUE, 8-bit bytes are used for a character. The
+ * encoding isn't currently specified (TODO).
+ *
+ * 'encoding' specifies the encoding used in the core. This is in registers,
+ * text manipulation, buffers, etc. Conversion has to be done when characters
+ * in another encoding are received or send:
+ *
+ * clipboard
+ * ^
+ * | (2)
+ * V
+ * +---------------+
+ * (1) | | (3)
+ * keyboard ----->| core |-----> display
+ * | |
+ * +---------------+
+ * ^
+ * | (4)
+ * V
+ * file
+ *
+ * (1) Typed characters arrive in the current locale. Conversion is to be
+ * done when 'encoding' is different from 'termencoding'.
+ * (2) Text will be made available with the encoding specified with
+ * 'encoding'. If this is not sufficient, system-specific conversion
+ * might be required.
+ * (3) For the GUI the correct font must be selected, no conversion done.
+ * Otherwise, conversion is to be done when 'encoding' differs from
+ * 'termencoding'. (Different in the GTK+ 2 port -- 'termencoding'
+ * is always used for both input and output and must always be set to
+ * "utf-8". gui_mch_init() does this automatically.)
+ * (4) The encoding of the file is specified with 'fileencoding'. Conversion
+ * is to be done when it's different from 'encoding'.
+ *
+ * The viminfo file is a special case: Only text is converted, not file names.
+ * Vim scripts may contain an ":encoding" command. This has an effect for
+ * some commands, like ":menutrans"
+ */
+
+#include "vim.h"
+
+#ifdef WIN32UNIX
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+# ifdef WIN32
+# undef WIN32 /* Some windows.h define WIN32, we don't want that here. */
+# endif
+#endif
+
+#if (defined(WIN3264) || defined(WIN32UNIX)) && !defined(__MINGW32__)
+# include <winnls.h>
+#endif
+
+#ifdef FEAT_GUI_X11
+# include <X11/Intrinsic.h>
+#endif
+#ifdef X_LOCALE
+#include <X11/Xlocale.h>
+#endif
+
+#if defined(FEAT_XIM) && defined(HAVE_GTK2)
+# include <gdk/gdkkeysyms.h>
+# ifdef WIN3264
+# include <gdk/gdkwin32.h>
+# else
+# include <gdk/gdkx.h>
+# endif
+#endif
+
+#ifdef HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+
+#if 0
+/* This has been disabled, because several people reported problems with the
+ * wcwidth() and iswprint() library functions, esp. for Hebrew. */
+# ifdef __STDC_ISO_10646__
+# define USE_WCHAR_FUNCTIONS
+# endif
+#endif
+
+#if defined(FEAT_MBYTE) || defined(PROTO)
+
+static int enc_canon_search __ARGS((char_u *name));
+static int dbcs_char2len __ARGS((int c));
+static int dbcs_char2bytes __ARGS((int c, char_u *buf));
+static int dbcs_ptr2len_check __ARGS((char_u *p));
+static int dbcs_char2cells __ARGS((int c));
+static int dbcs_ptr2char __ARGS((char_u *p));
+
+/* Lookup table to quickly get the length in bytes of a UTF-8 character from
+ * the first byte of a UTF-8 string. Bytes which are illegal when used as the
+ * first byte have a one, because these will be used separately. */
+static char utf8len_tab[256] =
+{
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /*bogus*/
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /*bogus*/
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
+};
+
+/*
+ * XIM often causes trouble. Define XIM_DEBUG to get a log of XIM callbacks
+ * in the "xim.log" file.
+ */
+/* #define XIM_DEBUG */
+#ifdef XIM_DEBUG
+ static void
+xim_log(char *s, ...)
+{
+ va_list arglist;
+ static FILE *fd = NULL;
+
+ if (fd == (FILE *)-1)
+ return;
+ if (fd == NULL)
+ {
+ fd = fopen("xim.log", "w");
+ if (fd == NULL)
+ {
+ EMSG("Cannot open xim.log");
+ fd = (FILE *)-1;
+ return;
+ }
+ }
+
+ va_start(arglist, s);
+ vfprintf(fd, s, arglist);
+ va_end(arglist);
+}
+#endif
+
+#endif
+
+#if defined(FEAT_MBYTE) || defined(FEAT_POSTSCRIPT) || defined(PROTO)
+/*
+ * Canonical encoding names and their properties.
+ * "iso-8859-n" is handled by enc_canonize() directly.
+ */
+static struct
+{ char *name; int prop; int codepage;}
+enc_canon_table[] =
+{
+#define IDX_LATIN_1 0
+ {"latin1", ENC_8BIT + ENC_LATIN1, 1252},
+#define IDX_ISO_2 1
+ {"iso-8859-2", ENC_8BIT, 0},
+#define IDX_ISO_3 2
+ {"iso-8859-3", ENC_8BIT, 0},
+#define IDX_ISO_4 3
+ {"iso-8859-4", ENC_8BIT, 0},
+#define IDX_ISO_5 4
+ {"iso-8859-5", ENC_8BIT, 0},
+#define IDX_ISO_6 5
+ {"iso-8859-6", ENC_8BIT, 0},
+#define IDX_ISO_7 6
+ {"iso-8859-7", ENC_8BIT, 0},
+#define IDX_CP1255 7
+ {"cp1255", ENC_8BIT, 1255}, /* close to iso-8859-8 */
+#define IDX_ISO_8 8
+ {"iso-8859-8", ENC_8BIT, 0},
+#define IDX_ISO_9 9
+ {"iso-8859-9", ENC_8BIT, 0},
+#define IDX_ISO_10 10
+ {"iso-8859-10", ENC_8BIT, 0},
+#define IDX_ISO_11 11
+ {"iso-8859-11", ENC_8BIT, 0},
+#define IDX_ISO_13 12
+ {"iso-8859-13", ENC_8BIT, 0},
+#define IDX_ISO_14 13
+ {"iso-8859-14", ENC_8BIT, 0},
+#define IDX_ISO_15 14
+ {"iso-8859-15", ENC_8BIT, 0},
+#define IDX_KOI8_R 15
+ {"koi8-r", ENC_8BIT, 0},
+#define IDX_KOI8_U 16
+ {"koi8-u", ENC_8BIT, 0},
+#define IDX_UTF8 17
+ {"utf-8", ENC_UNICODE, 0},
+#define IDX_UCS2 18
+ {"ucs-2", ENC_UNICODE + ENC_ENDIAN_B + ENC_2BYTE, 0},
+#define IDX_UCS2LE 19
+ {"ucs-2le", ENC_UNICODE + ENC_ENDIAN_L + ENC_2BYTE, 0},
+#define IDX_UTF16 20
+ {"utf-16", ENC_UNICODE + ENC_ENDIAN_B + ENC_2WORD, 0},
+#define IDX_UTF16LE 21
+ {"utf-16le", ENC_UNICODE + ENC_ENDIAN_L + ENC_2WORD, 0},
+#define IDX_UCS4 22
+ {"ucs-4", ENC_UNICODE + ENC_ENDIAN_B + ENC_4BYTE, 0},
+#define IDX_UCS4LE 23
+ {"ucs-4le", ENC_UNICODE + ENC_ENDIAN_L + ENC_4BYTE, 0},
+#define IDX_DEBUG 24
+ {"debug", ENC_DBCS, DBCS_DEBUG},
+#define IDX_CP932 25
+ {"cp932", ENC_DBCS, DBCS_JPN},
+#define IDX_CP949 26
+ {"cp949", ENC_DBCS, DBCS_KOR},
+#define IDX_CP936 27
+ {"cp936", ENC_DBCS, DBCS_CHS},
+#define IDX_CP950 28
+ {"cp950", ENC_DBCS, DBCS_CHT},
+#define IDX_EUC_JP 29
+ {"euc-jp", ENC_DBCS, DBCS_JPNU},
+#define IDX_SJIS 30
+ {"sjis", ENC_DBCS, DBCS_JPN},
+#define IDX_EUC_KR 31
+ {"euc-kr", ENC_DBCS, DBCS_KORU},
+#define IDX_EUC_CN 32
+ {"euc-cn", ENC_DBCS, DBCS_CHSU},
+#define IDX_EUC_TW 33
+ {"euc-tw", ENC_DBCS, DBCS_CHTU},
+#define IDX_BIG5 34
+ {"big5", ENC_DBCS, DBCS_CHT},
+#define IDX_CP1251 35
+ {"cp1251", ENC_8BIT, 1251},
+#define IDX_MACROMAN 36
+ {"macroman", ENC_8BIT + ENC_MACROMAN, 0},
+#define IDX_COUNT 37
+};
+
+/*
+ * Aliases for encoding names.
+ */
+static struct
+{ char *name; int canon;}
+enc_alias_table[] =
+{
+ {"ansi", IDX_LATIN_1},
+ {"iso-8859-1", IDX_LATIN_1},
+ {"latin2", IDX_ISO_2},
+ {"latin3", IDX_ISO_3},
+ {"latin4", IDX_ISO_4},
+ {"cyrillic", IDX_ISO_5},
+ {"arabic", IDX_ISO_6},
+ {"greek", IDX_ISO_7},
+#ifdef WIN3264
+ {"hebrew", IDX_CP1255},
+#else
+ {"hebrew", IDX_ISO_8},
+#endif
+ {"latin5", IDX_ISO_9},
+ {"turkish", IDX_ISO_9}, /* ? */
+ {"latin6", IDX_ISO_10},
+ {"nordic", IDX_ISO_10}, /* ? */
+ {"thai", IDX_ISO_11}, /* ? */
+ {"latin7", IDX_ISO_13},
+ {"latin8", IDX_ISO_14},
+ {"latin9", IDX_ISO_15},
+ {"utf8", IDX_UTF8},
+ {"unicode", IDX_UCS2},
+ {"ucs2", IDX_UCS2},
+ {"ucs2be", IDX_UCS2},
+ {"ucs-2be", IDX_UCS2},
+ {"ucs2le", IDX_UCS2LE},
+ {"utf16", IDX_UTF16},
+ {"utf16be", IDX_UTF16},
+ {"utf-16be", IDX_UTF16},
+ {"utf16le", IDX_UTF16LE},
+ {"ucs4", IDX_UCS4},
+ {"ucs4be", IDX_UCS4},
+ {"ucs-4be", IDX_UCS4},
+ {"ucs4le", IDX_UCS4LE},
+ {"932", IDX_CP932},
+ {"949", IDX_CP949},
+ {"936", IDX_CP936},
+ {"950", IDX_CP950},
+ {"eucjp", IDX_EUC_JP},
+ {"unix-jis", IDX_EUC_JP},
+ {"ujis", IDX_EUC_JP},
+ {"shift-jis", IDX_SJIS},
+ {"euckr", IDX_EUC_KR},
+ {"5601", IDX_EUC_KR}, /* Sun: KS C 5601 */
+ {"euccn", IDX_EUC_CN},
+ {"gb2312", IDX_EUC_CN},
+ {"euctw", IDX_EUC_TW},
+#if defined(WIN3264) || defined(WIN32UNIX) || defined(MACOS)
+ {"japan", IDX_CP932},
+ {"korea", IDX_CP949},
+ {"prc", IDX_CP936},
+ {"chinese", IDX_CP936},
+ {"taiwan", IDX_CP950},
+ {"big5", IDX_CP950},
+#else
+ {"japan", IDX_EUC_JP},
+ {"korea", IDX_EUC_KR},
+ {"prc", IDX_EUC_CN},
+ {"chinese", IDX_EUC_CN},
+ {"taiwan", IDX_EUC_TW},
+ {"cp950", IDX_BIG5},
+ {"950", IDX_BIG5},
+#endif
+ {"mac", IDX_MACROMAN},
+ {NULL, 0}
+};
+
+#ifndef CP_UTF8
+# define CP_UTF8 65001 /* magic number from winnls.h */
+#endif
+
+/*
+ * Find encoding "name" in the list of canonical encoding names.
+ * Returns -1 if not found.
+ */
+ static int
+enc_canon_search(name)
+ char_u *name;
+{
+ int i;
+
+ for (i = 0; i < IDX_COUNT; ++i)
+ if (STRCMP(name, enc_canon_table[i].name) == 0)
+ return i;
+ return -1;
+}
+
+#endif
+
+#if defined(FEAT_MBYTE) || defined(PROTO)
+
+/*
+ * Find canonical encoding "name" in the list and return its properties.
+ * Returns 0 if not found.
+ */
+ int
+enc_canon_props(name)
+ char_u *name;
+{
+ int i;
+
+ i = enc_canon_search(name);
+ if (i >= 0)
+ return enc_canon_table[i].prop;
+#ifdef WIN3264
+ if (name[0] == 'c' && name[1] == 'p' && VIM_ISDIGIT(name[2]))
+ {
+ CPINFO cpinfo;
+
+ /* Get info on this codepage to find out what it is. */
+ if (GetCPInfo(atoi(name + 2), &cpinfo) != 0)
+ {
+ if (cpinfo.MaxCharSize == 1) /* some single-byte encoding */
+ return ENC_8BIT;
+ if (cpinfo.MaxCharSize == 2
+ && (cpinfo.LeadByte[0] != 0 || cpinfo.LeadByte[1] != 0))
+ /* must be a DBCS encoding */
+ return ENC_DBCS;
+ }
+ return 0;
+ }
+#endif
+ if (STRNCMP(name, "2byte-", 6) == 0)
+ return ENC_DBCS;
+ if (STRNCMP(name, "8bit-", 5) == 0 || STRNCMP(name, "iso-8859-", 9) == 0)
+ return ENC_8BIT;
+ return 0;
+}
+
+/*
+ * Set up for using multi-byte characters.
+ * Called in three cases:
+ * - by main() to initialize (p_enc == NULL)
+ * - by set_init_1() after 'encoding' was set to its default.
+ * - by do_set() when 'encoding' has been set.
+ * p_enc must have been passed through enc_canonize() already.
+ * Sets the "enc_unicode", "enc_utf8", "enc_dbcs" and "has_mbyte" flags.
+ * Fills mb_bytelen_tab[] and returns NULL when there are no problems.
+ * When there is something wrong: Returns an error message and doesn't change
+ * anything.
+ */
+ char_u *
+mb_init()
+{
+ int i;
+ int idx;
+ int n;
+ int enc_dbcs_new = 0;
+#if defined(USE_ICONV) && !defined(WIN3264) && !defined(WIN32UNIX) \
+ && !defined(MACOS)
+# define LEN_FROM_CONV
+ vimconv_T vimconv;
+ char_u *p;
+#endif
+
+ if (p_enc == NULL)
+ {
+ /* Just starting up: set the whole table to one's. */
+ for (i = 0; i < 256; ++i)
+ mb_bytelen_tab[i] = 1;
+ input_conv.vc_type = CONV_NONE;
+ input_conv.vc_factor = 1;
+ output_conv.vc_type = CONV_NONE;
+ return NULL;
+ }
+
+#ifdef WIN3264
+ if (p_enc[0] == 'c' && p_enc[1] == 'p' && VIM_ISDIGIT(p_enc[2]))
+ {
+ CPINFO cpinfo;
+
+ /* Get info on this codepage to find out what it is. */
+ if (GetCPInfo(atoi(p_enc + 2), &cpinfo) != 0)
+ {
+ if (cpinfo.MaxCharSize == 1)
+ {
+ /* some single-byte encoding */
+ enc_unicode = 0;
+ enc_utf8 = FALSE;
+ }
+ else if (cpinfo.MaxCharSize == 2
+ && (cpinfo.LeadByte[0] != 0 || cpinfo.LeadByte[1] != 0))
+ {
+ /* must be a DBCS encoding, check below */
+ enc_dbcs_new = atoi(p_enc + 2);
+ }
+ else
+ goto codepage_invalid;
+ }
+ else if (GetLastError() == ERROR_INVALID_PARAMETER)
+ {
+codepage_invalid:
+ return (char_u *)N_("E543: Not a valid codepage");
+ }
+ }
+#endif
+ else if (STRNCMP(p_enc, "8bit-", 5) == 0
+ || STRNCMP(p_enc, "iso-8859-", 9) == 0)
+ {
+ /* Accept any "8bit-" or "iso-8859-" name. */
+ enc_unicode = 0;
+ enc_utf8 = FALSE;
+ }
+ else if (STRNCMP(p_enc, "2byte-", 6) == 0)
+ {
+#ifdef WIN3264
+ /* Windows: accept only valid codepage numbers, check below. */
+ if (p_enc[6] != 'c' || p_enc[7] != 'p'
+ || (enc_dbcs_new = atoi(p_enc + 8)) == 0)
+ return e_invarg;
+#else
+ /* Unix: accept any "2byte-" name, assume current locale. */
+ enc_dbcs_new = DBCS_2BYTE;
+#endif
+ }
+ else if ((idx = enc_canon_search(p_enc)) >= 0)
+ {
+ i = enc_canon_table[idx].prop;
+ if (i & ENC_UNICODE)
+ {
+ /* Unicode */
+ enc_utf8 = TRUE;
+ if (i & (ENC_2BYTE | ENC_2WORD))
+ enc_unicode = 2;
+ else if (i & ENC_4BYTE)
+ enc_unicode = 4;
+ else
+ enc_unicode = 0;
+ }
+ else if (i & ENC_DBCS)
+ {
+ /* 2byte, handle below */
+ enc_dbcs_new = enc_canon_table[idx].codepage;
+ }
+ else
+ {
+ /* Must be 8-bit. */
+ enc_unicode = 0;
+ enc_utf8 = FALSE;
+ }
+ }
+ else /* Don't know what encoding this is, reject it. */
+ return e_invarg;
+
+ if (enc_dbcs_new != 0)
+ {
+#ifdef WIN3264
+ /* Check if the DBCS code page is OK. */
+ if (!IsValidCodePage(enc_dbcs_new))
+ goto codepage_invalid;
+#endif
+ enc_unicode = 0;
+ enc_utf8 = FALSE;
+ }
+ enc_dbcs = enc_dbcs_new;
+ has_mbyte = (enc_dbcs != 0 || enc_utf8);
+
+#ifdef WIN3264
+ enc_codepage = encname2codepage(p_enc);
+#endif
+
+ /*
+ * Set the function pointers.
+ */
+ if (enc_utf8)
+ {
+ mb_ptr2len_check = utfc_ptr2len_check;
+ mb_char2len = utf_char2len;
+ mb_char2bytes = utf_char2bytes;
+ mb_ptr2cells = utf_ptr2cells;
+ mb_char2cells = utf_char2cells;
+ mb_off2cells = utf_off2cells;
+ mb_ptr2char = utf_ptr2char;
+ mb_head_off = utf_head_off;
+ }
+ else if (enc_dbcs != 0)
+ {
+ mb_ptr2len_check = dbcs_ptr2len_check;
+ mb_char2len = dbcs_char2len;
+ mb_char2bytes = dbcs_char2bytes;
+ mb_ptr2cells = dbcs_ptr2cells;
+ mb_char2cells = dbcs_char2cells;
+ mb_off2cells = dbcs_off2cells;
+ mb_ptr2char = dbcs_ptr2char;
+ mb_head_off = dbcs_head_off;
+ }
+ else
+ {
+ mb_ptr2len_check = latin_ptr2len_check;
+ mb_char2len = latin_char2len;
+ mb_char2bytes = latin_char2bytes;
+ mb_ptr2cells = latin_ptr2cells;
+ mb_char2cells = latin_char2cells;
+ mb_off2cells = latin_off2cells;
+ mb_ptr2char = latin_ptr2char;
+ mb_head_off = latin_head_off;
+ }
+
+ /*
+ * Fill the mb_bytelen_tab[] for MB_BYTE2LEN().
+ */
+#ifdef LEN_FROM_CONV
+ /* When 'encoding' is different from the current locale mblen() won't
+ * work. Use conversion to "utf-8" instead. */
+ vimconv.vc_type = CONV_NONE;
+ if (enc_dbcs)
+ {
+ p = enc_locale();
+ if (p == NULL || STRCMP(p, p_enc) != 0)
+ {
+ convert_setup(&vimconv, p_enc, (char_u *)"utf-8");
+ vimconv.vc_fail = TRUE;
+ }
+ vim_free(p);
+ }
+#endif
+
+ for (i = 0; i < 256; ++i)
+ {
+ /* Our own function to reliably check the length of UTF-8 characters,
+ * independent of mblen(). */
+ if (enc_utf8)
+ n = utf8len_tab[i];
+ else if (enc_dbcs == 0)
+ n = 1;
+ else
+ {
+#if defined(WIN3264) || defined(WIN32UNIX)
+ /* enc_dbcs is set by setting 'fileencoding'. It becomes a Windows
+ * CodePage identifier, which we can pass directly in to Windows
+ * API */
+ n = IsDBCSLeadByteEx(enc_dbcs, (BYTE)i) ? 2 : 1;
+#else
+# ifdef MACOS
+ /*
+ * if mblen() is not available, character which MSB is turned on
+ * are treated as leading byte character. (note : This assumption
+ * is not always true.)
+ */
+ n = (i & 0x80) ? 2 : 1;
+# else
+ char buf[MB_MAXBYTES];
+# ifdef X_LOCALE
+# ifndef mblen
+# define mblen _Xmblen
+# endif
+# endif
+ if (i == NUL) /* just in case mblen() can't handle "" */
+ n = 1;
+ else
+ {
+ buf[0] = i;
+ buf[1] = 0;
+#ifdef LEN_FROM_CONV
+ if (vimconv.vc_type != CONV_NONE)
+ {
+ /*
+ * string_convert() should fail when converting the first
+ * byte of a double-byte character.
+ */
+ p = string_convert(&vimconv, (char_u *)buf, NULL);
+ if (p != NULL)
+ {
+ vim_free(p);
+ n = 1;
+ }
+ else
+ n = 2;
+ }
+ else
+#endif
+ {
+ /*
+ * mblen() should return -1 for invalid (means the leading
+ * multibyte) character. However there are some platforms
+ * where mblen() returns 0 for invalid character.
+ * Therefore, following condition includes 0.
+ */
+ if (mblen(buf, (size_t)1) <= 0)
+ n = 2;
+ else
+ n = 1;
+ }
+ }
+# endif
+#endif
+ }
+
+ mb_bytelen_tab[i] = n;
+ }
+
+#ifdef LEN_FROM_CONV
+ convert_setup(&vimconv, NULL, NULL);
+#endif
+
+ /* The cell width depends on the type of multi-byte characters. */
+ (void)init_chartab();
+
+ /* When enc_utf8 is set or reset, (de)allocate ScreenLinesUC[] */
+ screenalloc(FALSE);
+
+ /* When using Unicode, set default for 'fileencodings'. */
+ if (enc_utf8 && !option_was_set((char_u *)"fencs"))
+ set_string_option_direct((char_u *)"fencs", -1,
+ (char_u *)"ucs-bom,utf-8,latin1", OPT_FREE);
+#if defined(HAVE_BIND_TEXTDOMAIN_CODESET) && defined(FEAT_GETTEXT)
+ /* GNU gettext 0.10.37 supports this feature: set the codeset used for
+ * translated messages independently from the current locale. */
+ (void)bind_textdomain_codeset(VIMPACKAGE,
+ enc_utf8 ? "utf-8" : (char *)p_enc);
+#endif
+
+#ifdef FEAT_AUTOCMD
+ /* Fire an autocommand to let people do custom font setup. This must be
+ * after Vim has been setup for the new encoding. */
+ apply_autocmds(EVENT_ENCODINGCHANGED, NULL, (char_u *)"", FALSE, curbuf);
+#endif
+
+ return NULL;
+}
+
+/*
+ * Return the size of the BOM for the current buffer:
+ * 0 - no BOM
+ * 2 - UCS-2 or UTF-16 BOM
+ * 4 - UCS-4 BOM
+ * 3 - UTF-8 BOM
+ */
+ int
+bomb_size()
+{
+ int n = 0;
+
+ if (curbuf->b_p_bomb && !curbuf->b_p_bin)
+ {
+ if (*curbuf->b_p_fenc == NUL)
+ {
+ if (enc_utf8)
+ {
+ if (enc_unicode != 0)
+ n = enc_unicode;
+ else
+ n = 3;
+ }
+ }
+ else if (STRCMP(curbuf->b_p_fenc, "utf-8") == 0)
+ n = 3;
+ else if (STRNCMP(curbuf->b_p_fenc, "ucs-2", 5) == 0
+ || STRNCMP(curbuf->b_p_fenc, "utf-16", 6) == 0)
+ n = 2;
+ else if (STRNCMP(curbuf->b_p_fenc, "ucs-4", 5) == 0)
+ n = 4;
+ }
+ return n;
+}
+
+/*
+ * Get class of pointer:
+ * 0 for blank or NUL
+ * 1 for punctuation
+ * 2 for an (ASCII) word character
+ * >2 for other word characters
+ */
+ int
+mb_get_class(p)
+ char_u *p;
+{
+ if (MB_BYTE2LEN(p[0]) == 1)
+ {
+ if (p[0] == NUL || vim_iswhite(p[0]))
+ return 0;
+ if (vim_iswordc(p[0]))
+ return 2;
+ return 1;
+ }
+ if (enc_dbcs != 0 && p[0] != NUL && p[1] != NUL)
+ return dbcs_class(p[0], p[1]);
+ if (enc_utf8)
+ return utf_class(utf_ptr2char(p));
+ return 0;
+}
+
+/*
+ * Get class of a double-byte character. This always returns 3 or bigger.
+ * TODO: Should return 1 for punctuation.
+ */
+ int
+dbcs_class(lead, trail)
+ unsigned lead;
+ unsigned trail;
+{
+ switch (enc_dbcs)
+ {
+ /* please add classfy routine for your language in here */
+
+ case DBCS_JPNU: /* ? */
+ case DBCS_JPN:
+ {
+ /* JIS code classification */
+ unsigned char lb = lead;
+ unsigned char tb = trail;
+
+ /* convert process code to JIS */
+# if defined(WIN3264) || defined(WIN32UNIX) || defined(MACOS)
+ /* process code is SJIS */
+ if (lb <= 0x9f)
+ lb = (lb - 0x81) * 2 + 0x21;
+ else
+ lb = (lb - 0xc1) * 2 + 0x21;
+ if (tb <= 0x7e)
+ tb -= 0x1f;
+ else if (tb <= 0x9e)
+ tb -= 0x20;
+ else
+ {
+ tb -= 0x7e;
+ lb += 1;
+ }
+# else
+ /*
+ * XXX: Code page identification can not use with all
+ * system! So, some other encoding information
+ * will be needed.
+ * In japanese: SJIS,EUC,UNICODE,(JIS)
+ * Note that JIS-code system don't use as
+ * process code in most system because it uses
+ * escape sequences(JIS is context depend encoding).
+ */
+ /* assume process code is JAPANESE-EUC */
+ lb &= 0x7f;
+ tb &= 0x7f;
+# endif
+ /* exceptions */
+ switch (lb << 8 | tb)
+ {
+ case 0x2121: /* ZENKAKU space */
+ return 0;
+ case 0x2122: /* KU-TEN (Japanese comma) */
+ case 0x2123: /* TOU-TEN (Japanese period) */
+ case 0x2124: /* ZENKAKU comma */
+ case 0x2125: /* ZENKAKU period */
+ return 1;
+ case 0x213c: /* prolongedsound handled as KATAKANA */
+ return 13;
+ }
+ /* sieved by KU code */
+ switch (lb)
+ {
+ case 0x21:
+ case 0x22:
+ /* special symbols */
+ return 10;
+ case 0x23:
+ /* alpha-numeric */
+ return 11;
+ case 0x24:
+ /* hiragana */
+ return 12;
+ case 0x25:
+ /* katakana */
+ return 13;
+ case 0x26:
+ /* greek */
+ return 14;
+ case 0x27:
+ /* russian */
+ return 15;
+ case 0x28:
+ /* lines */
+ return 16;
+ default:
+ /* kanji */
+ return 17;
+ }
+ }
+
+ case DBCS_KORU: /* ? */
+ case DBCS_KOR:
+ {
+ /* KS code classification */
+ unsigned char c1 = lead;
+ unsigned char c2 = trail;
+
+ /*
+ * 20 : Hangul
+ * 21 : Hanja
+ * 22 : Symbols
+ * 23 : Alpha-numeric/Roman Letter (Full width)
+ * 24 : Hangul Letter(Alphabet)
+ * 25 : Roman Numeral/Greek Letter
+ * 26 : Box Drawings
+ * 27 : Unit Symbols
+ * 28 : Circled/Parenthesized Letter
+ * 29 : Hirigana/Katakana
+ * 30 : Cyrillic Letter
+ */
+
+ if (c1 >= 0xB0 && c1 <= 0xC8)
+ /* Hangul */
+ return 20;
+#if defined(WIN3264) || defined(WIN32UNIX)
+ else if (c1 <= 0xA0 || c2 <= 0xA0)
+ /* Extended Hangul Region : MS UHC(Unified Hangul Code) */
+ /* c1: 0x81-0xA0 with c2: 0x41-0x5A, 0x61-0x7A, 0x81-0xFE
+ * c1: 0xA1-0xC6 with c2: 0x41-0x5A, 0x61-0x7A, 0x81-0xA0
+ */
+ return 20;
+#endif
+
+ else if (c1 >= 0xCA && c1 <= 0xFD)
+ /* Hanja */
+ return 21;
+ else switch (c1)
+ {
+ case 0xA1:
+ case 0xA2:
+ /* Symbols */
+ return 22;
+ case 0xA3:
+ /* Alpha-numeric */
+ return 23;
+ case 0xA4:
+ /* Hangul Letter(Alphabet) */
+ return 24;
+ case 0xA5:
+ /* Roman Numeral/Greek Letter */
+ return 25;
+ case 0xA6:
+ /* Box Drawings */
+ return 26;
+ case 0xA7:
+ /* Unit Symbols */
+ return 27;
+ case 0xA8:
+ case 0xA9:
+ if (c2 <= 0xAF)
+ return 25; /* Roman Letter */
+ else if (c2 >= 0xF6)
+ return 22; /* Symbols */
+ else
+ /* Circled/Parenthesized Letter */
+ return 28;
+ case 0xAA:
+ case 0xAB:
+ /* Hirigana/Katakana */
+ return 29;
+ case 0xAC:
+ /* Cyrillic Letter */
+ return 30;
+ }
+ }
+ default:
+ break;
+ }
+ return 3;
+}
+
+/*
+ * mb_char2len() function pointer.
+ * Return length in bytes of character "c".
+ * Returns 1 for a single-byte character.
+ */
+/* ARGSUSED */
+ int
+latin_char2len(c)
+ int c;
+{
+ return 1;
+}
+
+ static int
+dbcs_char2len(c)
+ int c;
+{
+ if (c >= 0x100)
+ return 2;
+ return 1;
+}
+
+/*
+ * mb_char2bytes() function pointer.
+ * Convert a character to its bytes.
+ * Returns the length in bytes.
+ */
+ int
+latin_char2bytes(c, buf)
+ int c;
+ char_u *buf;
+{
+ buf[0] = c;
+ return 1;
+}
+
+ static int
+dbcs_char2bytes(c, buf)
+ int c;
+ char_u *buf;
+{
+ if (c >= 0x100)
+ {
+ buf[0] = (unsigned)c >> 8;
+ buf[1] = c;
+ return 2;
+ }
+ buf[0] = c;
+ return 1;
+}
+
+/*
+ * mb_ptr2len_check() function pointer.
+ * Get byte length of character at "*p" but stop at a NUL.
+ * For UTF-8 this includes following composing characters.
+ * Returns 0 when *p is NUL.
+ *
+ */
+ int
+latin_ptr2len_check(p)
+ char_u *p;
+{
+ return MB_BYTE2LEN(*p);
+}
+
+ static int
+dbcs_ptr2len_check(p)
+ char_u *p;
+{
+ int len;
+
+ /* Check if second byte is not missing. */
+ len = MB_BYTE2LEN(*p);
+ if (len == 2 && p[1] == NUL)
+ len = 1;
+ return len;
+}
+
+struct interval
+{
+ unsigned short first;
+ unsigned short last;
+};
+static int intable __ARGS((struct interval *table, size_t size, int c));
+
+/*
+ * Return TRUE if "c" is in "table[size / sizeof(struct interval)]".
+ */
+ static int
+intable(table, size, c)
+ struct interval *table;
+ size_t size;
+ int c;
+{
+ int mid, bot, top;
+
+ /* first quick check for Latin1 etc. characters */
+ if (c < table[0].first)
+ return FALSE;
+
+ /* binary search in table */
+ bot = 0;
+ top = size / sizeof(struct interval) - 1;
+ while (top >= bot)
+ {
+ mid = (bot + top) / 2;
+ if (table[mid].last < c)
+ bot = mid + 1;
+ else if (table[mid].first > c)
+ top = mid - 1;
+ else
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * For UTF-8 character "c" return 2 for a double-width character, 1 for others.
+ * Returns 4 or 6 for an unprintable character.
+ * Is only correct for characters >= 0x80.
+ * When p_ambw is "double", return 2 for a character with East Asian Width
+ * class 'A'(mbiguous).
+ */
+ int
+utf_char2cells(c)
+ int c;
+{
+ /* sorted list of non-overlapping intervals of East Asian Ambiguous
+ * characters, generated with:
+ * "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
+ static struct interval ambiguous[] = {
+ {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8},
+ {0x00AA, 0x00AA}, {0x00AE, 0x00AE}, {0x00B0, 0x00B4},
+ {0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6},
+ {0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1},
+ {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED},
+ {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA},
+ {0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101},
+ {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B},
+ {0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133},
+ {0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144},
+ {0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153},
+ {0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE},
+ {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4},
+ {0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA},
+ {0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261},
+ {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB},
+ {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB},
+ {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0391, 0x03A1},
+ {0x03A3, 0x03A9}, {0x03B1, 0x03C1}, {0x03C3, 0x03C9},
+ {0x0401, 0x0401}, {0x0410, 0x044F}, {0x0451, 0x0451},
+ {0x2010, 0x2010}, {0x2013, 0x2016}, {0x2018, 0x2019},
+ {0x201C, 0x201D}, {0x2020, 0x2022}, {0x2024, 0x2027},
+ {0x2030, 0x2030}, {0x2032, 0x2033}, {0x2035, 0x2035},
+ {0x203B, 0x203B}, {0x203E, 0x203E}, {0x2074, 0x2074},
+ {0x207F, 0x207F}, {0x2081, 0x2084}, {0x20AC, 0x20AC},
+ {0x2103, 0x2103}, {0x2105, 0x2105}, {0x2109, 0x2109},
+ {0x2113, 0x2113}, {0x2116, 0x2116}, {0x2121, 0x2122},
+ {0x2126, 0x2126}, {0x212B, 0x212B}, {0x2153, 0x2154},
+ {0x215B, 0x215E}, {0x2160, 0x216B}, {0x2170, 0x2179},
+ {0x2190, 0x2199}, {0x21B8, 0x21B9}, {0x21D2, 0x21D2},
+ {0x21D4, 0x21D4}, {0x21E7, 0x21E7}, {0x2200, 0x2200},
+ {0x2202, 0x2203}, {0x2207, 0x2208}, {0x220B, 0x220B},
+ {0x220F, 0x220F}, {0x2211, 0x2211}, {0x2215, 0x2215},
+ {0x221A, 0x221A}, {0x221D, 0x2220}, {0x2223, 0x2223},
+ {0x2225, 0x2225}, {0x2227, 0x222C}, {0x222E, 0x222E},
+ {0x2234, 0x2237}, {0x223C, 0x223D}, {0x2248, 0x2248},
+ {0x224C, 0x224C}, {0x2252, 0x2252}, {0x2260, 0x2261},
+ {0x2264, 0x2267}, {0x226A, 0x226B}, {0x226E, 0x226F},
+ {0x2282, 0x2283}, {0x2286, 0x2287}, {0x2295, 0x2295},
+ {0x2299, 0x2299}, {0x22A5, 0x22A5}, {0x22BF, 0x22BF},
+ {0x2312, 0x2312}, {0x2460, 0x24E9}, {0x24EB, 0x254B},
+ {0x2550, 0x2573}, {0x2580, 0x258F}, {0x2592, 0x2595},
+ {0x25A0, 0x25A1}, {0x25A3, 0x25A9}, {0x25B2, 0x25B3},
+ {0x25B6, 0x25B7}, {0x25BC, 0x25BD}, {0x25C0, 0x25C1},
+ {0x25C6, 0x25C8}, {0x25CB, 0x25CB}, {0x25CE, 0x25D1},
+ {0x25E2, 0x25E5}, {0x25EF, 0x25EF}, {0x2605, 0x2606},
+ {0x2609, 0x2609}, {0x260E, 0x260F}, {0x2614, 0x2615},
+ {0x261C, 0x261C}, {0x261E, 0x261E}, {0x2640, 0x2640},
+ {0x2642, 0x2642}, {0x2660, 0x2661}, {0x2663, 0x2665},
+ {0x2667, 0x266A}, {0x266C, 0x266D}, {0x266F, 0x266F},
+ {0x273D, 0x273D}, {0x2776, 0x277F}, {0xE000, 0xF8FF},
+ {0xFFFD, 0xFFFD}, /* {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD} */
+ };
+
+ if (c >= 0x100)
+ {
+#ifdef USE_WCHAR_FUNCTIONS
+ /*
+ * Assume the library function wcwidth() works better than our own
+ * stuff. It should return 1 for ambiguous width chars!
+ */
+ int n = wcwidth(c);
+
+ if (n < 0)
+ return 6; /* unprintable, displays <xxxx> */
+ if (n > 1)
+ return n;
+#else
+ if (!utf_printable(c))
+ return 6; /* unprintable, displays <xxxx> */
+ if (c >= 0x1100
+ && (c <= 0x115f /* Hangul Jamo */
+ || c == 0x2329
+ || c == 0x232a
+ || (c >= 0x2e80 && c <= 0xa4cf
+ && c != 0x303f) /* CJK ... Yi */
+ || (c >= 0xac00 && c <= 0xd7a3) /* Hangul Syllables */
+ || (c >= 0xf900 && c <= 0xfaff) /* CJK Compatibility
+ Ideographs */
+ || (c >= 0xfe30 && c <= 0xfe6f) /* CJK Compatibility Forms */
+ || (c >= 0xff00 && c <= 0xff60) /* Fullwidth Forms */
+ || (c >= 0xffe0 && c <= 0xffe6)
+ || (c >= 0x20000 && c <= 0x2fffd)
+ || (c >= 0x30000 && c <= 0x3fffd)))
+ return 2;
+#endif
+ }
+
+ /* Characters below 0x100 are influenced by 'isprint' option */
+ else if (c >= 0x80 && !vim_isprintc(c))
+ return 4; /* unprintable, displays <xx> */
+
+ if (c >= 0x80 && *p_ambw == 'd' && intable(ambiguous, sizeof(ambiguous), c))
+ return 2;
+
+ return 1;
+}
+
+/*
+ * mb_ptr2cells() function pointer.
+ * Return the number of display cells character at "*p" occupies.
+ * This doesn't take care of unprintable characters, use ptr2cells() for that.
+ */
+/*ARGSUSED*/
+ int
+latin_ptr2cells(p)
+ char_u *p;
+{
+ return 1;
+}
+
+ int
+utf_ptr2cells(p)
+ char_u *p;
+{
+ int c;
+
+ /* Need to convert to a wide character. */
+ if (*p >= 0x80)
+ {
+ c = utf_ptr2char(p);
+ /* An illegal byte is displayed as <xx>. */
+ if (utf_ptr2len_check(p) == 1 || c == NUL)
+ return 4;
+ /* If the char is ASCII it must be an overlong sequence. */
+ if (c < 0x80)
+ return char2cells(c);
+ return utf_char2cells(c);
+ }
+ return 1;
+}
+
+ int
+dbcs_ptr2cells(p)
+ char_u *p;
+{
+ /* Number of cells is equal to number of bytes, except for euc-jp when
+ * the first byte is 0x8e. */
+ if (enc_dbcs == DBCS_JPNU && *p == 0x8e)
+ return 1;
+ return MB_BYTE2LEN(*p);
+}
+
+/*
+ * mb_char2cells() function pointer.
+ * Return the number of display cells character "c" occupies.
+ * Only takes care of multi-byte chars, not "^C" and such.
+ */
+/*ARGSUSED*/
+ int
+latin_char2cells(c)
+ int c;
+{
+ return 1;
+}
+
+ static int
+dbcs_char2cells(c)
+ int c;
+{
+ /* Number of cells is equal to number of bytes, except for euc-jp when
+ * the first byte is 0x8e. */
+ if (enc_dbcs == DBCS_JPNU && ((unsigned)c >> 8) == 0x8e)
+ return 1;
+ /* use the first byte */
+ return MB_BYTE2LEN((unsigned)c >> 8);
+}
+
+/*
+ * mb_off2cells() function pointer.
+ * Return number of display cells for char at ScreenLines[off].
+ * Caller must make sure "off" and "off + 1" are valid!
+ */
+/*ARGSUSED*/
+ int
+latin_off2cells(off)
+ unsigned off;
+{
+ return 1;
+}
+
+ int
+dbcs_off2cells(off)
+ unsigned off;
+{
+ /* Number of cells is equal to number of bytes, except for euc-jp when
+ * the first byte is 0x8e. */
+ if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e)
+ return 1;
+ return MB_BYTE2LEN(ScreenLines[off]);
+}
+
+ int
+utf_off2cells(off)
+ unsigned off;
+{
+ return ScreenLines[off + 1] == 0 ? 2 : 1;
+}
+
+/*
+ * mb_ptr2char() function pointer.
+ * Convert a byte sequence into a character.
+ */
+ int
+latin_ptr2char(p)
+ char_u *p;
+{
+ return *p;
+}
+
+ static int
+dbcs_ptr2char(p)
+ char_u *p;
+{
+ if (MB_BYTE2LEN(*p) > 1 && p[1] != NUL)
+ return (p[0] << 8) + p[1];
+ return *p;
+}
+
+/*
+ * Convert a UTF-8 byte sequence to a wide character.
+ * If the sequence is illegal or truncated by a NUL the first byte is
+ * returned.
+ * Does not include composing characters, of course.
+ */
+ int
+utf_ptr2char(p)
+ char_u *p;
+{
+ int len;
+
+ if (p[0] < 0x80) /* be quick for ASCII */
+ return p[0];
+
+ len = utf8len_tab[p[0]];
+ if ((p[1] & 0xc0) == 0x80)
+ {
+ if (len == 2)
+ return ((p[0] & 0x1f) << 6) + (p[1] & 0x3f);
+ if ((p[2] & 0xc0) == 0x80)
+ {
+ if (len == 3)
+ return ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6)
+ + (p[2] & 0x3f);
+ if ((p[3] & 0xc0) == 0x80)
+ {
+ if (len == 4)
+ return ((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12)
+ + ((p[2] & 0x3f) << 6) + (p[3] & 0x3f);
+ if ((p[4] & 0xc0) == 0x80)
+ {
+ if (len == 5)
+ return ((p[0] & 0x03) << 24) + ((p[1] & 0x3f) << 18)
+ + ((p[2] & 0x3f) << 12) + ((p[3] & 0x3f) << 6)
+ + (p[4] & 0x3f);
+ if ((p[5] & 0xc0) == 0x80 && len == 6)
+ return ((p[0] & 0x01) << 30) + ((p[1] & 0x3f) << 24)
+ + ((p[2] & 0x3f) << 18) + ((p[3] & 0x3f) << 12)
+ + ((p[4] & 0x3f) << 6) + (p[5] & 0x3f);
+ }
+ }
+ }
+ }
+ /* Illegal value, just return the first byte */
+ return p[0];
+}
+
+/*
+ * Get character at **pp and advance *pp to the next character.
+ * Note: composing characters are skipped!
+ */
+ int
+mb_ptr2char_adv(pp)
+ char_u **pp;
+{
+ int c;
+
+ c = (*mb_ptr2char)(*pp);
+ *pp += (*mb_ptr2len_check)(*pp);
+ return c;
+}
+
+#if defined(FEAT_ARABIC) || defined(PROTO)
+/*
+ * Check whether we are dealing with Arabic combining characters.
+ * Note: these are NOT really composing characters!
+ */
+ int
+arabic_combine(one, two)
+ int one; /* first character */
+ int two; /* character just after "one" */
+{
+ if (one == a_LAM)
+ return arabic_maycombine(two);
+ return FALSE;
+}
+
+/*
+ * Check whether we are dealing with a character that could be regarded as an
+ * Arabic combining character, need to check the character before this.
+ */
+ int
+arabic_maycombine(two)
+ int two;
+{
+ if (p_arshape && !p_tbidi)
+ return (two == a_ALEF_MADDA
+ || two == a_ALEF_HAMZA_ABOVE
+ || two == a_ALEF_HAMZA_BELOW
+ || two == a_ALEF);
+ return FALSE;
+}
+
+/*
+ * Check if the character pointed to by "p2" is a composing character when it
+ * comes after "p1". For Arabic sometimes "ab" is replaced with "c", which
+ * behaves like a composing character.
+ */
+ int
+utf_composinglike(p1, p2)
+ char_u *p1;
+ char_u *p2;
+{
+ int c2;
+
+ c2 = utf_ptr2char(p2);
+ if (utf_iscomposing(c2))
+ return TRUE;
+ if (!arabic_maycombine(c2))
+ return FALSE;
+ return arabic_combine(utf_ptr2char(p1), c2);
+}
+#endif
+
+/*
+ * Convert a UTF-8 byte string to a wide chararacter. Also get up to two
+ * composing characters.
+ */
+ int
+utfc_ptr2char(p, p1, p2)
+ char_u *p;
+ int *p1; /* return: first composing char or 0 */
+ int *p2; /* return: second composing char or 0 */
+{
+ int len;
+ int c;
+ int cc;
+
+ c = utf_ptr2char(p);
+ len = utf_ptr2len_check(p);
+ /* Only accept a composing char when the first char isn't illegal. */
+ if ((len > 1 || *p < 0x80)
+ && p[len] >= 0x80
+ && UTF_COMPOSINGLIKE(p, p + len))
+ {
+ *p1 = utf_ptr2char(p + len);
+ len += utf_ptr2len_check(p + len);
+ if (p[len] >= 0x80 && utf_iscomposing(cc = utf_ptr2char(p + len)))
+ *p2 = cc;
+ else
+ *p2 = 0;
+ }
+ else
+ {
+ *p1 = 0;
+ *p2 = 0;
+ }
+ return c;
+}
+
+/*
+ * Convert a UTF-8 byte string to a wide chararacter. Also get up to two
+ * composing characters. Use no more than p[maxlen].
+ */
+ int
+utfc_ptr2char_len(p, p1, p2, maxlen)
+ char_u *p;
+ int *p1; /* return: first composing char or 0 */
+ int *p2; /* return: second composing char or 0 */
+ int maxlen;
+{
+ int len;
+ int c;
+ int cc;
+
+ c = utf_ptr2char(p);
+ len = utf_ptr2len_check_len(p, maxlen);
+ /* Only accept a composing char when the first char isn't illegal. */
+ if ((len > 1 || *p < 0x80)
+ && len < maxlen
+ && p[len] >= 0x80
+ && UTF_COMPOSINGLIKE(p, p + len))
+ {
+ *p1 = utf_ptr2char(p + len);
+ len += utf_ptr2len_check_len(p + len, maxlen - len);
+ if (len < maxlen
+ && p[len] >= 0x80
+ && utf_iscomposing(cc = utf_ptr2char(p + len)))
+ *p2 = cc;
+ else
+ *p2 = 0;
+ }
+ else
+ {
+ *p1 = 0;
+ *p2 = 0;
+ }
+ return c;
+}
+
+/*
+ * Convert the character at screen position "off" to a sequence of bytes.
+ * Includes the composing characters.
+ * "buf" must at least have the length MB_MAXBYTES.
+ * Returns the produced number of bytes.
+ */
+ int
+utfc_char2bytes(off, buf)
+ int off;
+ char_u *buf;
+{
+ int len;
+
+ len = utf_char2bytes(ScreenLinesUC[off], buf);
+ if (ScreenLinesC1[off] != 0)
+ {
+ len += utf_char2bytes(ScreenLinesC1[off], buf + len);
+ if (ScreenLinesC2[off] != 0)
+ len += utf_char2bytes(ScreenLinesC2[off], buf + len);
+ }
+ return len;
+}
+
+/*
+ * Get the length of a UTF-8 byte sequence, not including any following
+ * composing characters.
+ * Returns 0 for "".
+ * Returns 1 for an illegal byte sequence.
+ */
+ int
+utf_ptr2len_check(p)
+ char_u *p;
+{
+ int len;
+ int i;
+
+ if (*p == NUL)
+ return 0;
+ len = utf8len_tab[*p];
+ for (i = 1; i < len; ++i)
+ if ((p[i] & 0xc0) != 0x80)
+ return 1;
+ return len;
+}
+
+/*
+ * Return length of UTF-8 character, obtained from the first byte.
+ * "b" must be between 0 and 255!
+ */
+ int
+utf_byte2len(b)
+ int b;
+{
+ return utf8len_tab[b];
+}
+
+/*
+ * Get the length of UTF-8 byte sequence "p[size]". Does not include any
+ * following composing characters.
+ * Returns 1 for "".
+ * Returns 1 for an illegal byte sequence.
+ * Returns number > "size" for an incomplete byte sequence.
+ */
+ int
+utf_ptr2len_check_len(p, size)
+ char_u *p;
+ int size;
+{
+ int len;
+ int i;
+
+ if (*p == NUL)
+ return 1;
+ len = utf8len_tab[*p];
+ if (len > size)
+ return len; /* incomplete byte sequence. */
+ for (i = 1; i < len; ++i)
+ if ((p[i] & 0xc0) != 0x80)
+ return 1;
+ return len;
+}
+
+/*
+ * Return the number of bytes the UTF-8 encoding of the character at "p" takes.
+ * This includes following composing characters.
+ */
+ int
+utfc_ptr2len_check(p)
+ char_u *p;
+{
+ int len;
+#ifdef FEAT_ARABIC
+ int prevlen;
+#endif
+
+ if (*p == NUL)
+ return 0;
+ if (p[0] < 0x80 && p[1] < 0x80) /* be quick for ASCII */
+ return 1;
+
+ /* Skip over first UTF-8 char, stopping at a NUL byte. */
+ len = utf_ptr2len_check(p);
+
+ /* Check for illegal byte. */
+ if (len == 1 && p[0] >= 0x80)
+ return 1;
+
+ /*
+ * Check for composing characters. We can handle only the first two, but
+ * skip all of them (otherwise the cursor would get stuck).
+ */
+#ifdef FEAT_ARABIC
+ prevlen = 0;
+#endif
+ for (;;)
+ {
+ if (p[len] < 0x80 || !UTF_COMPOSINGLIKE(p + prevlen, p + len))
+ return len;
+
+ /* Skip over composing char */
+#ifdef FEAT_ARABIC
+ prevlen = len;
+#endif
+ len += utf_ptr2len_check(p + len);
+ }
+}
+
+/*
+ * Return the number of bytes the UTF-8 encoding of the character at "p[size]"
+ * takes. This includes following composing characters.
+ * Returns 1 for an illegal char or an incomplete byte sequence.
+ */
+ int
+utfc_ptr2len_check_len(p, size)
+ char_u *p;
+ int size;
+{
+ int len;
+#ifdef FEAT_ARABIC
+ int prevlen;
+#endif
+
+ if (*p == NUL)
+ return 0;
+ if (p[0] < 0x80 && (size == 1 || p[1] < 0x80)) /* be quick for ASCII */
+ return 1;
+
+ /* Skip over first UTF-8 char, stopping at a NUL byte. */
+ len = utf_ptr2len_check_len(p, size);
+
+ /* Check for illegal byte and incomplete byte sequence. */
+ if ((len == 1 && p[0] >= 0x80) || len > size)
+ return 1;
+
+ /*
+ * Check for composing characters. We can handle only the first two, but
+ * skip all of them (otherwise the cursor would get stuck).
+ */
+#ifdef FEAT_ARABIC
+ prevlen = 0;
+#endif
+ while (len < size)
+ {
+ if (p[len] < 0x80 || !UTF_COMPOSINGLIKE(p + prevlen, p + len))
+ break;
+
+ /* Skip over composing char */
+#ifdef FEAT_ARABIC
+ prevlen = len;
+#endif
+ len += utf_ptr2len_check_len(p + len, size - len);
+ }
+ return len;
+}
+
+/*
+ * Return the number of bytes the UTF-8 encoding of character "c" takes.
+ * This does not include composing characters.
+ */
+ int
+utf_char2len(c)
+ int c;
+{
+ if (c < 0x80)
+ return 1;
+ if (c < 0x800)
+ return 2;
+ if (c < 0x10000)
+ return 3;
+ if (c < 0x200000)
+ return 4;
+ if (c < 0x4000000)
+ return 5;
+ return 6;
+}
+
+/*
+ * Convert Unicode character "c" to UTF-8 string in "buf[]".
+ * Returns the number of bytes.
+ * This does not include composing characters.
+ */
+ int
+utf_char2bytes(c, buf)
+ int c;
+ char_u *buf;
+{
+ if (c < 0x80) /* 7 bits */
+ {
+ buf[0] = c;
+ return 1;
+ }
+ if (c < 0x800) /* 11 bits */
+ {
+ buf[0] = 0xc0 + ((unsigned)c >> 6);
+ buf[1] = 0x80 + (c & 0x3f);
+ return 2;
+ }
+ if (c < 0x10000) /* 16 bits */
+ {
+ buf[0] = 0xe0 + ((unsigned)c >> 12);
+ buf[1] = 0x80 + (((unsigned)c >> 6) & 0x3f);
+ buf[2] = 0x80 + (c & 0x3f);
+ return 3;
+ }
+ if (c < 0x200000) /* 21 bits */
+ {
+ buf[0] = 0xf0 + ((unsigned)c >> 18);
+ buf[1] = 0x80 + (((unsigned)c >> 12) & 0x3f);
+ buf[2] = 0x80 + (((unsigned)c >> 6) & 0x3f);
+ buf[3] = 0x80 + (c & 0x3f);
+ return 4;
+ }
+ if (c < 0x4000000) /* 26 bits */
+ {
+ buf[0] = 0xf8 + ((unsigned)c >> 24);
+ buf[1] = 0x80 + (((unsigned)c >> 18) & 0x3f);
+ buf[2] = 0x80 + (((unsigned)c >> 12) & 0x3f);
+ buf[3] = 0x80 + (((unsigned)c >> 6) & 0x3f);
+ buf[4] = 0x80 + (c & 0x3f);
+ return 5;
+ }
+ /* 31 bits */
+ buf[0] = 0xfc + ((unsigned)c >> 30);
+ buf[1] = 0x80 + (((unsigned)c >> 24) & 0x3f);
+ buf[2] = 0x80 + (((unsigned)c >> 18) & 0x3f);
+ buf[3] = 0x80 + (((unsigned)c >> 12) & 0x3f);
+ buf[4] = 0x80 + (((unsigned)c >> 6) & 0x3f);
+ buf[5] = 0x80 + (c & 0x3f);
+ return 6;
+}
+
+/*
+ * Return TRUE if "c" is a composing UTF-8 character. This means it will be
+ * drawn on top of the preceding character.
+ * Based on code from Markus Kuhn.
+ */
+ int
+utf_iscomposing(c)
+ int c;
+{
+ /* sorted list of non-overlapping intervals */
+ static struct interval combining[] =
+ {
+ {0x0300, 0x034f}, {0x0360, 0x036f}, {0x0483, 0x0486}, {0x0488, 0x0489},
+ {0x0591, 0x05a1}, {0x05a3, 0x05b9}, {0x05bb, 0x05bd}, {0x05bf, 0x05bf},
+ {0x05c1, 0x05c2}, {0x05c4, 0x05c4}, {0x0610, 0x0615}, {0x064b, 0x0658},
+ {0x0670, 0x0670}, {0x06d6, 0x06dc}, {0x06de, 0x06e4}, {0x06e7, 0x06e8},
+ {0x06ea, 0x06ed}, {0x0711, 0x0711}, {0x0730, 0x074a}, {0x07a6, 0x07b0},
+ {0x0901, 0x0903}, {0x093c, 0x093c}, {0x093e, 0x094d}, {0x0951, 0x0954},
+ {0x0962, 0x0963}, {0x0981, 0x0983}, {0x09bc, 0x09bc}, {0x09be, 0x09c4},
+ {0x09c7, 0x09c8}, {0x09cb, 0x09cd}, {0x09d7, 0x09d7}, {0x09e2, 0x09e3},
+ {0x0a01, 0x0a03}, {0x0a3c, 0x0a3c}, {0x0a3e, 0x0a42}, {0x0a47, 0x0a48},
+ {0x0a4b, 0x0a4d}, {0x0a70, 0x0a71}, {0x0a81, 0x0a83}, {0x0abc, 0x0abc},
+ {0x0abe, 0x0ac5}, {0x0ac7, 0x0ac9}, {0x0acb, 0x0acd}, {0x0ae2, 0x0ae3},
+ {0x0b01, 0x0b03}, {0x0b3c, 0x0b3c}, {0x0b3e, 0x0b43}, {0x0b47, 0x0b48},
+ {0x0b4b, 0x0b4d}, {0x0b56, 0x0b57}, {0x0b82, 0x0b82}, {0x0bbe, 0x0bc2},
+ {0x0bc6, 0x0bc8}, {0x0bca, 0x0bcd}, {0x0bd7, 0x0bd7}, {0x0c01, 0x0c03},
+ {0x0c3e, 0x0c44}, {0x0c46, 0x0c48}, {0x0c4a, 0x0c4d}, {0x0c55, 0x0c56},
+ {0x0c82, 0x0c83}, {0x0cbc, 0x0cbc}, {0x0cbe, 0x0cc4}, {0x0cc6, 0x0cc8},
+ {0x0cca, 0x0ccd}, {0x0cd5, 0x0cd6}, {0x0d02, 0x0d03}, {0x0d3e, 0x0d43},
+ {0x0d46, 0x0d48}, {0x0d4a, 0x0d4d}, {0x0d57, 0x0d57}, {0x0d82, 0x0d83},
+ {0x0dca, 0x0dca}, {0x0dcf, 0x0dd4}, {0x0dd6, 0x0dd6}, {0x0dd8, 0x0ddf},
+ {0x0df2, 0x0df3}, {0x0e31, 0x0e31}, {0x0e34, 0x0e3a}, {0x0e47, 0x0e4e},
+ {0x0eb1, 0x0eb1}, {0x0eb4, 0x0eb9}, {0x0ebb, 0x0ebc}, {0x0ec8, 0x0ecd},
+ {0x0f18, 0x0f19}, {0x0f35, 0x0f35}, {0x0f37, 0x0f37}, {0x0f39, 0x0f39},
+ {0x0f3e, 0x0f3f}, {0x0f71, 0x0f84}, {0x0f86, 0x0f87}, {0x0f90, 0x0f97},
+ {0x0f99, 0x0fbc}, {0x0fc6, 0x0fc6}, {0x102c, 0x1032}, {0x1036, 0x1039},
+ {0x1056, 0x1059}, {0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753},
+ {0x1772, 0x1773}, {0x17b6, 0x17d3}, {0x17dd, 0x17dd}, {0x180b, 0x180d},
+ {0x18a9, 0x18a9}, {0x1920, 0x192b}, {0x1930, 0x193b}, {0x20d0, 0x20ea},
+ {0x302a, 0x302f}, {0x3099, 0x309a}, {0xfb1e, 0xfb1e}, {0xfe00, 0xfe0f},
+ {0xfe20, 0xfe23},
+ };
+
+ return intable(combining, sizeof(combining), c);
+}
+
+/*
+ * Return TRUE for characters that can be displayed in a normal way.
+ * Only for characters of 0x100 and above!
+ */
+ int
+utf_printable(c)
+ int c;
+{
+#ifdef USE_WCHAR_FUNCTIONS
+ /*
+ * Assume the iswprint() library function works better than our own stuff.
+ */
+ return iswprint(c);
+#else
+ /* Sorted list of non-overlapping intervals.
+ * 0xd800-0xdfff is reserved for UTF-16, actually illegal. */
+ static struct interval nonprint[] =
+ {
+ {0x070f, 0x070f}, {0x180b, 0x180e}, {0x200b, 0x200f}, {0x202a, 0x202e},
+ {0x206a, 0x206f}, {0xd800, 0xdfff}, {0xfeff, 0xfeff}, {0xfff9, 0xfffb},
+ {0xfffe, 0xffff}
+ };
+
+ return !intable(nonprint, sizeof(nonprint), c);
+#endif
+}
+
+/*
+ * Get class of a Unicode character.
+ * 0: white space
+ * 1: punctuation
+ * 2 or bigger: some class of word character.
+ */
+ int
+utf_class(c)
+ int c;
+{
+ /* sorted list of non-overlapping intervals */
+ static struct clinterval
+ {
+ unsigned short first;
+ unsigned short last;
+ unsigned short class;
+ } classes[] =
+ {
+ {0x037e, 0x037e, 1}, /* Greek question mark */
+ {0x0387, 0x0387, 1}, /* Greek ano teleia */
+ {0x055a, 0x055f, 1}, /* Armenian punctuation */
+ {0x0589, 0x0589, 1}, /* Armenian full stop */
+ {0x05be, 0x05be, 1},
+ {0x05c0, 0x05c0, 1},
+ {0x05c3, 0x05c3, 1},
+ {0x05f3, 0x05f4, 1},
+ {0x060c, 0x060c, 1},
+ {0x061b, 0x061b, 1},
+ {0x061f, 0x061f, 1},
+ {0x066a, 0x066d, 1},
+ {0x06d4, 0x06d4, 1},
+ {0x0700, 0x070d, 1}, /* Syriac punctuation */
+ {0x0964, 0x0965, 1},
+ {0x0970, 0x0970, 1},
+ {0x0df4, 0x0df4, 1},
+ {0x0e4f, 0x0e4f, 1},
+ {0x0e5a, 0x0e5b, 1},
+ {0x0f04, 0x0f12, 1},
+ {0x0f3a, 0x0f3d, 1},
+ {0x0f85, 0x0f85, 1},
+ {0x104a, 0x104f, 1}, /* Myanmar punctuation */
+ {0x10fb, 0x10fb, 1}, /* Georgian punctuation */
+ {0x1361, 0x1368, 1}, /* Ethiopic punctuation */
+ {0x166d, 0x166e, 1}, /* Canadian Syl. punctuation */
+ {0x1680, 0x1680, 0},
+ {0x169b, 0x169c, 1},
+ {0x16eb, 0x16ed, 1},
+ {0x1735, 0x1736, 1},
+ {0x17d4, 0x17dc, 1}, /* Khmer punctuation */
+ {0x1800, 0x180a, 1}, /* Mongolian punctuation */
+ {0x2000, 0x200b, 0}, /* spaces */
+ {0x200c, 0x2027, 1}, /* punctuation and symbols */
+ {0x2028, 0x2029, 0},
+ {0x202a, 0x202e, 1}, /* punctuation and symbols */
+ {0x202f, 0x202f, 0},
+ {0x2030, 0x205e, 1}, /* punctuation and symbols */
+ {0x205f, 0x205f, 0},
+ {0x2060, 0x27ff, 1}, /* punctuation and symbols */
+ {0x2070, 0x207f, 0x2070}, /* superscript */
+ {0x2080, 0x208f, 0x2080}, /* subscript */
+ {0x2983, 0x2998, 1},
+ {0x29d8, 0x29db, 1},
+ {0x29fc, 0x29fd, 1},
+ {0x3000, 0x3000, 0}, /* ideographic space */
+ {0x3001, 0x3020, 1}, /* ideographic punctuation */
+ {0x3030, 0x3030, 1},
+ {0x303d, 0x303d, 1},
+ {0x3040, 0x309f, 0x3040}, /* Hiragana */
+ {0x30a0, 0x30ff, 0x30a0}, /* Katakana */
+ {0x3300, 0x9fff, 0x4e00}, /* CJK Ideographs */
+ {0xac00, 0xd7a3, 0xac00}, /* Hangul Syllables */
+ {0xf900, 0xfaff, 0x4e00}, /* CJK Ideographs */
+ {0xfd3e, 0xfd3f, 1},
+ {0xfe30, 0xfe6b, 1}, /* punctuation forms */
+ {0xff00, 0xff0f, 1}, /* half/fullwidth ASCII */
+ {0xff1a, 0xff20, 1}, /* half/fullwidth ASCII */
+ {0xff3b, 0xff40, 1}, /* half/fullwidth ASCII */
+ {0xff5b, 0xff65, 1}, /* half/fullwidth ASCII */
+ };
+ int bot = 0;
+ int top = sizeof(classes) / sizeof(struct clinterval) - 1;
+ int mid;
+
+ /* First quick check for Latin1 characters, use 'iskeyword'. */
+ if (c < 0x100)
+ {
+ if (c == ' ' || c == '\t' || c == NUL)
+ return 0; /* blank */
+ if (vim_iswordc(c))
+ return 2; /* word character */
+ return 1; /* punctuation */
+ }
+
+ /* binary search in table */
+ while (top >= bot)
+ {
+ mid = (bot + top) / 2;
+ if (classes[mid].last < c)
+ bot = mid + 1;
+ else if (classes[mid].first > c)
+ top = mid - 1;
+ else
+ return (int)classes[mid].class;
+ }
+
+ /* most other characters are "word" characters */
+ return 2;
+}
+
+/*
+ * Code for Unicode case-dependent operations. Based on notes in
+ * http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
+ * This code uses simple case folding, not full case folding.
+ */
+
+/*
+ * The following table is built by foldExtract.pl < CaseFolding.txt .
+ * It must be in numeric order, because we use binary search on it.
+ * An entry such as {0x41,0x5a,1,32} means that UCS-4 characters in the range
+ * from 0x41 to 0x5a inclusive, stepping by 1, are folded by adding 32.
+ */
+
+typedef struct
+{
+ int rangeStart;
+ int rangeEnd;
+ int step;
+ int offset;
+} convertStruct;
+
+convertStruct foldCase[] =
+{
+ {0x41,0x5a,1,32}, {0xc0,0xd6,1,32}, {0xd8,0xde,1,32},
+ {0x100,0x12e,2,1}, {0x130,0x130,-1,-199}, {0x132,0x136,2,1},
+ {0x139,0x147,2,1}, {0x14a,0x176,2,1}, {0x178,0x178,-1,-121},
+ {0x179,0x17d,2,1}, {0x181,0x181,-1,210}, {0x182,0x184,2,1},
+ {0x186,0x186,-1,206}, {0x187,0x187,-1,1}, {0x189,0x18a,1,205},
+ {0x18b,0x18b,-1,1}, {0x18e,0x18e,-1,79}, {0x18f,0x18f,-1,202},
+ {0x190,0x190,-1,203}, {0x191,0x191,-1,1}, {0x193,0x193,-1,205},
+ {0x194,0x194,-1,207}, {0x196,0x196,-1,211}, {0x197,0x197,-1,209},
+ {0x198,0x198,-1,1}, {0x19c,0x19c,-1,211}, {0x19d,0x19d,-1,213},
+ {0x19f,0x19f,-1,214}, {0x1a0,0x1a4,2,1}, {0x1a6,0x1a6,-1,218},
+ {0x1a7,0x1a7,-1,1}, {0x1a9,0x1a9,-1,218}, {0x1ac,0x1ac,-1,1},
+ {0x1ae,0x1ae,-1,218}, {0x1af,0x1af,-1,1}, {0x1b1,0x1b2,1,217},
+ {0x1b3,0x1b5,2,1}, {0x1b7,0x1b7,-1,219}, {0x1b8,0x1bc,4,1},
+ {0x1c4,0x1c4,-1,2}, {0x1c5,0x1c5,-1,1}, {0x1c7,0x1c7,-1,2},
+ {0x1c8,0x1c8,-1,1}, {0x1ca,0x1ca,-1,2}, {0x1cb,0x1db,2,1},
+ {0x1de,0x1ee,2,1}, {0x1f1,0x1f1,-1,2}, {0x1f2,0x1f4,2,1},
+ {0x1f6,0x1f6,-1,-97}, {0x1f7,0x1f7,-1,-56}, {0x1f8,0x21e,2,1},
+ {0x220,0x220,-1,-130}, {0x222,0x232,2,1}, {0x386,0x386,-1,38},
+ {0x388,0x38a,1,37}, {0x38c,0x38c,-1,64}, {0x38e,0x38f,1,63},
+ {0x391,0x3a1,1,32}, {0x3a3,0x3ab,1,32}, {0x3d8,0x3ee,2,1},
+ {0x3f4,0x3f4,-1,-60}, {0x3f7,0x3f7,-1,1}, {0x3f9,0x3f9,-1,-7},
+ {0x3fa,0x3fa,-1,1}, {0x400,0x40f,1,80}, {0x410,0x42f,1,32},
+ {0x460,0x480,2,1}, {0x48a,0x4be,2,1}, {0x4c1,0x4cd,2,1},
+ {0x4d0,0x4f4,2,1}, {0x4f8,0x500,8,1}, {0x502,0x50e,2,1},
+ {0x531,0x556,1,48}, {0x1e00,0x1e94,2,1}, {0x1ea0,0x1ef8,2,1},
+ {0x1f08,0x1f0f,1,-8}, {0x1f18,0x1f1d,1,-8}, {0x1f28,0x1f2f,1,-8},
+ {0x1f38,0x1f3f,1,-8}, {0x1f48,0x1f4d,1,-8}, {0x1f59,0x1f5f,2,-8},
+ {0x1f68,0x1f6f,1,-8}, {0x1f88,0x1f8f,1,-8}, {0x1f98,0x1f9f,1,-8},
+ {0x1fa8,0x1faf,1,-8}, {0x1fb8,0x1fb9,1,-8}, {0x1fba,0x1fbb,1,-74},
+ {0x1fbc,0x1fbc,-1,-9}, {0x1fc8,0x1fcb,1,-86}, {0x1fcc,0x1fcc,-1,-9},
+ {0x1fd8,0x1fd9,1,-8}, {0x1fda,0x1fdb,1,-100}, {0x1fe8,0x1fe9,1,-8},
+ {0x1fea,0x1feb,1,-112}, {0x1fec,0x1fec,-1,-7}, {0x1ff8,0x1ff9,1,-128},
+ {0x1ffa,0x1ffb,1,-126}, {0x1ffc,0x1ffc,-1,-9}, {0x2126,0x2126,-1,-7517},
+ {0x212a,0x212a,-1,-8383}, {0x212b,0x212b,-1,-8262},
+ {0x2160,0x216f,1,16}, {0x24b6,0x24cf,1,26}, {0xff21,0xff3a,1,32},
+ {0x10400,0x10427,1,40}
+};
+
+static int utf_convert(int a, convertStruct table[], int tableSize);
+
+/*
+ * Generic conversion function for case operations.
+ * Return the converted equivalent of "a", which is a UCS-4 character. Use
+ * the given conversion "table". Uses binary search on "table".
+ */
+ static int
+utf_convert(a, table, tableSize)
+ int a;
+ convertStruct table[];
+ int tableSize;
+{
+ int start, mid, end; /* indices into table */
+
+ start = 0;
+ end = tableSize / sizeof(convertStruct);
+ while (start < end)
+ {
+ /* need to search further */
+ mid = (end + start) /2;
+ if (table[mid].rangeEnd < a)
+ start = mid + 1;
+ else
+ end = mid;
+ }
+ if (table[start].rangeStart <= a && a <= table[start].rangeEnd
+ && (a - table[start].rangeStart) % table[start].step == 0)
+ return (a + table[start].offset);
+ else
+ return a;
+}
+
+/*
+ * Return the folded-case equivalent of "a", which is a UCS-4 character. Uses
+ * simple case folding.
+ */
+ int
+utf_fold(a)
+ int a;
+{
+ return utf_convert(a, foldCase, sizeof(foldCase));
+}
+
+/*
+ * The following tables are built by upperLowerExtract.pl < UnicodeData.txt .
+ * They must be in numeric order, because we use binary search on them.
+ * An entry such as {0x41,0x5a,1,32} means that UCS-4 characters in the range
+ * from 0x41 to 0x5a inclusive, stepping by 1, are switched to lower (for
+ * example) by adding 32.
+ */
+convertStruct toLower[] =
+{
+ {0x41,0x5a,1,32}, {0xc0,0xd6,1,32}, {0xd8,0xde,1,32},
+ {0x100,0x12e,2,1}, {0x130,0x130,-1,-199}, {0x132,0x136,2,1},
+ {0x139,0x147,2,1}, {0x14a,0x176,2,1}, {0x178,0x178,-1,-121},
+ {0x179,0x17d,2,1}, {0x181,0x181,-1,210}, {0x182,0x184,2,1},
+ {0x186,0x186,-1,206}, {0x187,0x187,-1,1}, {0x189,0x18a,1,205},
+ {0x18b,0x18b,-1,1}, {0x18e,0x18e,-1,79}, {0x18f,0x18f,-1,202},
+ {0x190,0x190,-1,203}, {0x191,0x191,-1,1}, {0x193,0x193,-1,205},
+ {0x194,0x194,-1,207}, {0x196,0x196,-1,211}, {0x197,0x197,-1,209},
+ {0x198,0x198,-1,1}, {0x19c,0x19c,-1,211}, {0x19d,0x19d,-1,213},
+ {0x19f,0x19f,-1,214}, {0x1a0,0x1a4,2,1}, {0x1a6,0x1a6,-1,218},
+ {0x1a7,0x1a7,-1,1}, {0x1a9,0x1a9,-1,218}, {0x1ac,0x1ac,-1,1},
+ {0x1ae,0x1ae,-1,218}, {0x1af,0x1af,-1,1}, {0x1b1,0x1b2,1,217},
+ {0x1b3,0x1b5,2,1}, {0x1b7,0x1b7,-1,219}, {0x1b8,0x1bc,4,1},
+ {0x1c4,0x1ca,3,2}, {0x1cd,0x1db,2,1}, {0x1de,0x1ee,2,1},
+ {0x1f1,0x1f1,-1,2}, {0x1f4,0x1f4,-1,1}, {0x1f6,0x1f6,-1,-97},
+ {0x1f7,0x1f7,-1,-56}, {0x1f8,0x21e,2,1}, {0x220,0x220,-1,-130},
+ {0x222,0x232,2,1}, {0x386,0x386,-1,38}, {0x388,0x38a,1,37},
+ {0x38c,0x38c,-1,64}, {0x38e,0x38f,1,63}, {0x391,0x3a1,1,32},
+ {0x3a3,0x3ab,1,32}, {0x3d8,0x3ee,2,1}, {0x3f4,0x3f4,-1,-60},
+ {0x3f7,0x3f7,-1,1}, {0x3f9,0x3f9,-1,-7}, {0x3fa,0x3fa,-1,1},
+ {0x400,0x40f,1,80}, {0x410,0x42f,1,32}, {0x460,0x480,2,1},
+ {0x48a,0x4be,2,1}, {0x4c1,0x4cd,2,1}, {0x4d0,0x4f4,2,1},
+ {0x4f8,0x500,8,1}, {0x502,0x50e,2,1}, {0x531,0x556,1,48},
+ {0x1e00,0x1e94,2,1}, {0x1ea0,0x1ef8,2,1}, {0x1f08,0x1f0f,1,-8},
+ {0x1f18,0x1f1d,1,-8}, {0x1f28,0x1f2f,1,-8}, {0x1f38,0x1f3f,1,-8},
+ {0x1f48,0x1f4d,1,-8}, {0x1f59,0x1f5f,2,-8}, {0x1f68,0x1f6f,1,-8},
+ {0x1fb8,0x1fb9,1,-8}, {0x1fba,0x1fbb,1,-74}, {0x1fc8,0x1fcb,1,-86},
+ {0x1fd8,0x1fd9,1,-8}, {0x1fda,0x1fdb,1,-100}, {0x1fe8,0x1fe9,1,-8},
+ {0x1fea,0x1feb,1,-112}, {0x1fec,0x1fec,-1,-7}, {0x1ff8,0x1ff9,1,-128},
+ {0x1ffa,0x1ffb,1,-126}, {0x2126,0x2126,-1,-7517}, {0x212a,0x212a,-1,-8383},
+ {0x212b,0x212b,-1,-8262}, {0xff21,0xff3a,1,32}, {0x10400,0x10427,1,40}
+};
+
+convertStruct toUpper[] =
+{
+ {0x61,0x7a,1,-32}, {0xb5,0xb5,-1,743}, {0xe0,0xf6,1,-32},
+ {0xf8,0xfe,1,-32}, {0xff,0xff,-1,121}, {0x101,0x12f,2,-1},
+ {0x131,0x131,-1,-232}, {0x133,0x137,2,-1}, {0x13a,0x148,2,-1},
+ {0x14b,0x177,2,-1}, {0x17a,0x17e,2,-1}, {0x17f,0x17f,-1,-300},
+ {0x183,0x185,2,-1}, {0x188,0x18c,4,-1}, {0x192,0x192,-1,-1},
+ {0x195,0x195,-1,97}, {0x199,0x199,-1,-1}, {0x19e,0x19e,-1,130},
+ {0x1a1,0x1a5,2,-1}, {0x1a8,0x1ad,5,-1}, {0x1b0,0x1b4,4,-1},
+ {0x1b6,0x1b9,3,-1}, {0x1bd,0x1bd,-1,-1}, {0x1bf,0x1bf,-1,56},
+ {0x1c5,0x1c6,1,-1}, {0x1c8,0x1c9,1,-1}, {0x1cb,0x1cc,1,-1},
+ {0x1ce,0x1dc,2,-1}, {0x1dd,0x1dd,-1,-79}, {0x1df,0x1ef,2,-1},
+ {0x1f2,0x1f3,1,-1}, {0x1f5,0x1f9,4,-1}, {0x1fb,0x21f,2,-1},
+ {0x223,0x233,2,-1}, {0x253,0x253,-1,-210}, {0x254,0x254,-1,-206},
+ {0x256,0x257,1,-205}, {0x259,0x259,-1,-202}, {0x25b,0x25b,-1,-203},
+ {0x260,0x260,-1,-205}, {0x263,0x263,-1,-207}, {0x268,0x268,-1,-209},
+ {0x269,0x26f,6,-211}, {0x272,0x272,-1,-213}, {0x275,0x275,-1,-214},
+ {0x280,0x283,3,-218}, {0x288,0x288,-1,-218}, {0x28a,0x28b,1,-217},
+ {0x292,0x292,-1,-219}, {0x3ac,0x3ac,-1,-38}, {0x3ad,0x3af,1,-37},
+ {0x3b1,0x3c1,1,-32}, {0x3c2,0x3c2,-1,-31}, {0x3c3,0x3cb,1,-32},
+ {0x3cc,0x3cc,-1,-64}, {0x3cd,0x3ce,1,-63}, {0x3d0,0x3d0,-1,-62},
+ {0x3d1,0x3d1,-1,-57}, {0x3d5,0x3d5,-1,-47}, {0x3d6,0x3d6,-1,-54},
+ {0x3d9,0x3ef,2,-1}, {0x3f0,0x3f0,-1,-86}, {0x3f1,0x3f1,-1,-80},
+ {0x3f2,0x3f2,-1,7}, {0x3f5,0x3f5,-1,-96}, {0x3f8,0x3fb,3,-1},
+ {0x430,0x44f,1,-32}, {0x450,0x45f,1,-80}, {0x461,0x481,2,-1},
+ {0x48b,0x4bf,2,-1}, {0x4c2,0x4ce,2,-1}, {0x4d1,0x4f5,2,-1},
+ {0x4f9,0x501,8,-1}, {0x503,0x50f,2,-1}, {0x561,0x586,1,-48},
+ {0x1e01,0x1e95,2,-1}, {0x1e9b,0x1e9b,-1,-59}, {0x1ea1,0x1ef9,2,-1},
+ {0x1f00,0x1f07,1,8}, {0x1f10,0x1f15,1,8}, {0x1f20,0x1f27,1,8},
+ {0x1f30,0x1f37,1,8}, {0x1f40,0x1f45,1,8}, {0x1f51,0x1f57,2,8},
+ {0x1f60,0x1f67,1,8}, {0x1f70,0x1f71,1,74}, {0x1f72,0x1f75,1,86},
+ {0x1f76,0x1f77,1,100}, {0x1f78,0x1f79,1,128}, {0x1f7a,0x1f7b,1,112},
+ {0x1f7c,0x1f7d,1,126}, {0x1f80,0x1f87,1,8}, {0x1f90,0x1f97,1,8},
+ {0x1fa0,0x1fa7,1,8}, {0x1fb0,0x1fb1,1,8}, {0x1fb3,0x1fb3,-1,9},
+ {0x1fbe,0x1fbe,-1,-7205}, {0x1fc3,0x1fc3,-1,9}, {0x1fd0,0x1fd1,1,8},
+ {0x1fe0,0x1fe1,1,8}, {0x1fe5,0x1fe5,-1,7}, {0x1ff3,0x1ff3,-1,9},
+ {0xff41,0xff5a,1,-32}, {0x10428,0x1044f,1,-40}
+};
+
+/*
+ * Return the upper-case equivalent of "a", which is a UCS-4 character. Use
+ * simple case folding.
+ */
+ int
+utf_toupper(a)
+ int a;
+{
+ /* If 'casemap' contains "keepascii" use ASCII style toupper(). */
+ if (a < 128 && (cmp_flags & CMP_KEEPASCII))
+ return TOUPPER_ASC(a);
+
+#if defined(HAVE_TOWUPPER) && defined(__STDC__ISO_10646__)
+ /* If towupper() is availble and handles Unicode, use it. */
+ if (!(cmp_flags & CMP_INTERNAL))
+ return towupper(a);
+#endif
+
+ /* For characters below 128 use locale sensitive toupper(). */
+ if (a < 128)
+ return TOUPPER_LOC(a);
+
+ /* For any other characters use the above mapping table. */
+ return utf_convert(a, toUpper, sizeof(toUpper));
+}
+
+ int
+utf_islower(a)
+ int a;
+{
+ return (utf_toupper(a) != a);
+}
+
+/*
+ * Return the lower-case equivalent of "a", which is a UCS-4 character. Use
+ * simple case folding.
+ */
+ int
+utf_tolower(a)
+ int a;
+{
+ /* If 'casemap' contains "keepascii" use ASCII style tolower(). */
+ if (a < 128 && (cmp_flags & CMP_KEEPASCII))
+ return TOLOWER_ASC(a);
+
+#if defined(HAVE_TOWLOWER) && defined(__STDC__ISO_10646__)
+ /* If towlower() is availble and handles Unicode, use it. */
+ if (!(cmp_flags & CMP_INTERNAL))
+ return towlower(a);
+#endif
+
+ /* For characters below 128 use locale sensitive tolower(). */
+ if (a < 128)
+ return TOLOWER_LOC(a);
+
+ /* For any other characters use the above mapping table. */
+ return utf_convert(a, toLower, sizeof(toLower));
+}
+
+ int
+utf_isupper(a)
+ int a;
+{
+ return (utf_tolower(a) != a);
+}
+
+/*
+ * Version of strnicmp() that handles multi-byte characters.
+ * Needed for Big5, Sjift-JIS and UTF-8 encoding. Other DBCS encodings can
+ * probably use strnicmp(), because there are no ASCII characters in the
+ * second byte.
+ * Returns zero if s1 and s2 are equal (ignoring case), the difference between
+ * two characters otherwise.
+ */
+ int
+mb_strnicmp(s1, s2, n)
+ char_u *s1, *s2;
+ int n;
+{
+ int i, j, l;
+ int cdiff;
+
+ for (i = 0; i < n; i += l)
+ {
+ if (s1[i] == NUL && s2[i] == NUL) /* both strings end */
+ return 0;
+ if (enc_utf8)
+ {
+ l = utf_byte2len(s1[i]);
+ if (l > n - i)
+ l = n - i; /* incomplete character */
+ /* Check directly first, it's faster. */
+ for (j = 0; j < l; ++j)
+ if (s1[i + j] != s2[i + j])
+ break;
+ if (j < l)
+ {
+ /* If one of the two characters is incomplete return -1. */
+ if (i + utf_byte2len(s1[i]) > n || i + utf_byte2len(s2[i]) > n)
+ return -1;
+ cdiff = utf_fold(utf_ptr2char(s1 + i))
+ - utf_fold(utf_ptr2char(s2 + i));
+ if (cdiff != 0)
+ return cdiff;
+ }
+ }
+ else
+ {
+ l = (*mb_ptr2len_check)(s1 + i);
+ if (l <= 1)
+ {
+ /* Single byte: first check normally, then with ignore case. */
+ if (s1[i] != s2[i])
+ {
+ cdiff = TOLOWER_LOC(s1[i]) - TOLOWER_LOC(s2[i]);
+ if (cdiff != 0)
+ return cdiff;
+ }
+ }
+ else
+ {
+ /* For non-Unicode multi-byte don't ignore case. */
+ if (l > n - i)
+ l = n - i;
+ cdiff = STRNCMP(s1 + i, s2 + i, l);
+ if (cdiff != 0)
+ return cdiff;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * "g8": show bytes of the UTF-8 char under the cursor. Doesn't matter what
+ * 'encoding' has been set to.
+ */
+ void
+show_utf8()
+{
+ int len;
+ char_u *line;
+ int clen;
+ int i;
+
+ /* Get the byte length of the char under the cursor, including composing
+ * characters. */
+ line = ml_get_cursor();
+ len = utfc_ptr2len_check(line);
+ if (len == 0)
+ {
+ MSG("NUL");
+ return;
+ }
+
+ IObuff[0] = NUL;
+ clen = 0;
+ for (i = 0; i < len; ++i)
+ {
+ if (clen == 0)
+ {
+ /* start of (composing) character, get its length */
+ if (i > 0)
+ STRCAT(IObuff, "+ ");
+ clen = utf_ptr2len_check(line + i);
+ }
+ sprintf((char *)IObuff + STRLEN(IObuff), "%02x ", line[i]);
+ --clen;
+ }
+
+ msg(IObuff);
+}
+
+/*
+ * mb_head_off() function pointer.
+ * Return offset from "p" to the first byte of the character it points into.
+ * Returns 0 when already at the first byte of a character.
+ */
+/*ARGSUSED*/
+ int
+latin_head_off(base, p)
+ char_u *base;
+ char_u *p;
+{
+ return 0;
+}
+
+ int
+dbcs_head_off(base, p)
+ char_u *base;
+ char_u *p;
+{
+ char_u *q;
+
+ /* It can't be a trailing byte when not using DBCS, at the start of the
+ * string or the previous byte can't start a double-byte. */
+ if (p <= base || MB_BYTE2LEN(p[-1]) == 1)
+ return 0;
+
+ /* This is slow: need to start at the base and go forward until the
+ * byte we are looking for. Return 1 when we went past it, 0 otherwise. */
+ q = base;
+ while (q < p)
+ q += dbcs_ptr2len_check(q);
+ return (q == p) ? 0 : 1;
+}
+
+#if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(FEAT_RIGHTLEFT) \
+ || defined(PROTO)
+/*
+ * Special version of dbcs_head_off() that works for ScreenLines[], where
+ * single-width DBCS_JPNU characters are stored separately.
+ */
+ int
+dbcs_screen_head_off(base, p)
+ char_u *base;
+ char_u *p;
+{
+ char_u *q;
+
+ /* It can't be a trailing byte when not using DBCS, at the start of the
+ * string or the previous byte can't start a double-byte.
+ * For euc-jp an 0x8e byte in the previous cell always means we have a
+ * lead byte in the current cell. */
+ if (p <= base
+ || (enc_dbcs == DBCS_JPNU && p[-1] == 0x8e)
+ || MB_BYTE2LEN(p[-1]) == 1)
+ return 0;
+
+ /* This is slow: need to start at the base and go forward until the
+ * byte we are looking for. Return 1 when we went past it, 0 otherwise.
+ * For DBCS_JPNU look out for 0x8e, which means the second byte is not
+ * stored as the next byte. */
+ q = base;
+ while (q < p)
+ {
+ if (enc_dbcs == DBCS_JPNU && *q == 0x8e)
+ ++q;
+ else
+ q += dbcs_ptr2len_check(q);
+ }
+ return (q == p) ? 0 : 1;
+}
+#endif
+
+ int
+utf_head_off(base, p)
+ char_u *base;
+ char_u *p;
+{
+ char_u *q;
+ char_u *s;
+ int c;
+#ifdef FEAT_ARABIC
+ char_u *j;
+#endif
+
+ if (*p < 0x80) /* be quick for ASCII */
+ return 0;
+
+ /* Skip backwards over trailing bytes: 10xx.xxxx
+ * Skip backwards again if on a composing char. */
+ for (q = p; ; --q)
+ {
+ /* Move s to the last byte of this char. */
+ for (s = q; (s[1] & 0xc0) == 0x80; ++s)
+ ;
+ /* Move q to the first byte of this char. */
+ while (q > base && (*q & 0xc0) == 0x80)
+ --q;
+ /* Check for illegal sequence. Do allow an illegal byte after where we
+ * started. */
+ if (utf8len_tab[*q] != (int)(s - q + 1)
+ && utf8len_tab[*q] != (int)(p - q + 1))
+ return 0;
+
+ if (q <= base)
+ break;
+
+ c = utf_ptr2char(q);
+ if (utf_iscomposing(c))
+ continue;
+
+#ifdef FEAT_ARABIC
+ if (arabic_maycombine(c))
+ {
+ /* Advance to get a sneak-peak at the next char */
+ j = q;
+ --j;
+ /* Move j to the first byte of this char. */
+ while (j > base && (*j & 0xc0) == 0x80)
+ --j;
+ if (arabic_combine(utf_ptr2char(j), c))
+ continue;
+ }
+#endif
+ break;
+ }
+
+ return (int)(p - q);
+}
+
+/*
+ * Return the offset from "p" to the first byte of a character. When "p" is
+ * at the start of a character 0 is returned, otherwise the offset to the next
+ * character. Can start anywhere in a stream of bytes.
+ */
+ int
+mb_off_next(base, p)
+ char_u *base;
+ char_u *p;
+{
+ int i;
+ int j;
+
+ if (enc_utf8)
+ {
+ if (*p < 0x80) /* be quick for ASCII */
+ return 0;
+
+ /* Find the next character that isn't 10xx.xxxx */
+ for (i = 0; (p[i] & 0xc0) == 0x80; ++i)
+ ;
+ if (i > 0)
+ {
+ /* Check for illegal sequence. */
+ for (j = 0; p - j > base; ++j)
+ if ((p[-j] & 0xc0) != 0x80)
+ break;
+ if (utf8len_tab[p[-j]] != i + j)
+ return 0;
+ }
+ return i;
+ }
+
+ /* Only need to check if we're on a trail byte, it doesn't matter if we
+ * want the offset to the next or current character. */
+ return (*mb_head_off)(base, p);
+}
+
+/*
+ * Return the offset from "p" to the last byte of the character it points
+ * into. Can start anywhere in a stream of bytes.
+ */
+ int
+mb_tail_off(base, p)
+ char_u *base;
+ char_u *p;
+{
+ int i;
+ int j;
+
+ if (*p == NUL)
+ return 0;
+
+ if (enc_utf8)
+ {
+ /* Find the last character that is 10xx.xxxx */
+ for (i = 0; (p[i + 1] & 0xc0) == 0x80; ++i)
+ ;
+ /* Check for illegal sequence. */
+ for (j = 0; p - j > base; ++j)
+ if ((p[-j] & 0xc0) != 0x80)
+ break;
+ if (utf8len_tab[p[-j]] != i + j + 1)
+ return 0;
+ return i;
+ }
+
+ /* It can't be the first byte if a double-byte when not using DBCS, at the
+ * end of the string or the byte can't start a double-byte. */
+ if (enc_dbcs == 0 || p[1] == NUL || MB_BYTE2LEN(*p) == 1)
+ return 0;
+
+ /* Return 1 when on the lead byte, 0 when on the tail byte. */
+ return 1 - dbcs_head_off(base, p);
+}
+
+#if defined(FEAT_GUI) || defined(PROTO)
+/*
+ * Special version of mb_tail_off() for use in ScreenLines[].
+ */
+ int
+dbcs_screen_tail_off(base, p)
+ char_u *base;
+ char_u *p;
+{
+ /* It can't be the first byte if a double-byte when not using DBCS, at the
+ * end of the string or the byte can't start a double-byte.
+ * For euc-jp an 0x8e byte always means we have a lead byte in the current
+ * cell. */
+ if (*p == NUL || p[1] == NUL
+ || (enc_dbcs == DBCS_JPNU && *p == 0x8e)
+ || MB_BYTE2LEN(*p) == 1)
+ return 0;
+
+ /* Return 1 when on the lead byte, 0 when on the tail byte. */
+ return 1 - dbcs_screen_head_off(base, p);
+}
+#endif
+
+/*
+ * If the cursor moves on an trail byte, set the cursor on the lead byte.
+ * Thus it moves left if necessary.
+ * Return TRUE when the cursor was adjusted.
+ */
+ void
+mb_adjust_cursor()
+{
+ mb_adjustpos(&curwin->w_cursor);
+}
+
+/*
+ * Adjust position "*lp" to point to the first byte of a multi-byte character.
+ * If it points to a tail byte it's moved backwards to the head byte.
+ */
+ void
+mb_adjustpos(lp)
+ pos_T *lp;
+{
+ char_u *p;
+
+ if (lp->col > 0
+#ifdef FEAT_VIRTUALEDIT
+ || lp->coladd > 1
+#endif
+ )
+ {
+ p = ml_get(lp->lnum);
+ lp->col -= (*mb_head_off)(p, p + lp->col);
+#ifdef FEAT_VIRTUALEDIT
+ /* Reset "coladd" when the cursor would be on the right half of a
+ * double-wide character. */
+ if (lp->coladd == 1
+ && p[lp->col] != TAB
+ && vim_isprintc((*mb_ptr2char)(p + lp->col))
+ && ptr2cells(p + lp->col) > 1)
+ lp->coladd = 0;
+#endif
+ }
+}
+
+/*
+ * Return a pointer to the character before "*p", if there is one.
+ */
+ char_u *
+mb_prevptr(line, p)
+ char_u *line; /* start of the string */
+ char_u *p;
+{
+ if (p > line)
+ p = p - (*mb_head_off)(line, p - 1) - 1;
+ return p;
+}
+
+/*
+ * Return the character length of "str". multi-byte characters counts as one.
+ */
+ int
+mb_charlen(str)
+ char_u *str;
+{
+ int count;
+
+ if (str == NULL)
+ return 0;
+
+ for (count = 0; *str != NUL; count++)
+ str += (*mb_ptr2len_check)(str);
+
+ return count;
+}
+
+/*
+ * Try to un-escape a multi-byte character.
+ * Used for the "to" and "from" part of a mapping.
+ * Return the un-escaped string if it is a multi-byte character, and advance
+ * "pp" to just after the bytes that formed it.
+ * Return NULL if no multi-byte char was found.
+ */
+ char_u *
+mb_unescape(pp)
+ char_u **pp;
+{
+ static char_u buf[MB_MAXBYTES + 1];
+ int n, m = 0;
+ char_u *str = *pp;
+
+ /* Must translate K_SPECIAL KS_SPECIAL KE_FILLER to K_SPECIAL and CSI
+ * KS_EXTRA KE_CSI to CSI. */
+ for (n = 0; str[n] != NUL && m <= MB_MAXBYTES; ++n)
+ {
+ if (str[n] == K_SPECIAL
+ && str[n + 1] == KS_SPECIAL
+ && str[n + 2] == KE_FILLER)
+ {
+ buf[m++] = K_SPECIAL;
+ n += 2;
+ }
+# ifdef FEAT_GUI
+ else if (str[n] == CSI
+ && str[n + 1] == KS_EXTRA
+ && str[n + 2] == (int)KE_CSI)
+ {
+ buf[m++] = CSI;
+ n += 2;
+ }
+# endif
+ else if (str[n] == K_SPECIAL
+# ifdef FEAT_GUI
+ || str[n] == CSI
+# endif
+ )
+ break; /* a special key can't be a multibyte char */
+ else
+ buf[m++] = str[n];
+ buf[m] = NUL;
+
+ /* Return a multi-byte character if it's found. An illegal sequence
+ * will result in a 1 here. */
+ if ((*mb_ptr2len_check)(buf) > 1)
+ {
+ *pp = str + n + 1;
+ return buf;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Return TRUE if the character at "row"/"col" on the screen is the left side
+ * of a double-width character.
+ * Caller must make sure "row" and "col" are not invalid!
+ */
+ int
+mb_lefthalve(row, col)
+ int row;
+ int col;
+{
+#ifdef FEAT_HANGULIN
+ if (composing_hangul)
+ return TRUE;
+#endif
+ if (enc_dbcs != 0)
+ return dbcs_off2cells(LineOffset[row] + col) > 1;
+ if (enc_utf8)
+ return (col + 1 < Columns
+ && ScreenLines[LineOffset[row] + col + 1] == 0);
+ return FALSE;
+}
+
+# if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(FEAT_RIGHTLEFT) \
+ || defined(PROTO)
+/*
+ * Correct a position on the screen, if it's the right halve of a double-wide
+ * char move it to the left halve. Returns the corrected column.
+ */
+ int
+mb_fix_col(col, row)
+ int col;
+ int row;
+{
+ col = check_col(col);
+ row = check_row(row);
+ if (has_mbyte && ScreenLines != NULL && col > 0
+ && ((enc_dbcs
+ && ScreenLines[LineOffset[row] + col] != NUL
+ && dbcs_screen_head_off(ScreenLines + LineOffset[row],
+ ScreenLines + LineOffset[row] + col))
+ || (enc_utf8 && ScreenLines[LineOffset[row] + col] == 0)))
+ --col;
+ return col;
+}
+# endif
+#endif
+
+#if defined(FEAT_MBYTE) || defined(FEAT_POSTSCRIPT) || defined(PROTO)
+static int enc_alias_search __ARGS((char_u *name));
+
+/*
+ * Skip the Vim specific head of a 'encoding' name.
+ */
+ char_u *
+enc_skip(p)
+ char_u *p;
+{
+ if (STRNCMP(p, "2byte-", 6) == 0)
+ return p + 6;
+ if (STRNCMP(p, "8bit-", 5) == 0)
+ return p + 5;
+ return p;
+}
+
+/*
+ * Find the canonical name for encoding "enc".
+ * When the name isn't recognized, returns "enc" itself, but with all lower
+ * case characters and '_' replaced with '-'.
+ * Returns an allocated string. NULL for out-of-memory.
+ */
+ char_u *
+enc_canonize(enc)
+ char_u *enc;
+{
+ char_u *r;
+ char_u *p, *s;
+ int i;
+
+ /* copy "enc" to allocted memory, with room for two '-' */
+ r = alloc((unsigned)(STRLEN(enc) + 3));
+ if (r != NULL)
+ {
+ /* Make it all lower case and replace '_' with '-'. */
+ p = r;
+ for (s = enc; *s != NUL; ++s)
+ {
+ if (*s == '_')
+ *p++ = '-';
+ else
+ *p++ = TOLOWER_ASC(*s);
+ }
+ *p = NUL;
+
+ /* Skip "2byte-" and "8bit-". */
+ p = enc_skip(r);
+
+ /* "iso8859" -> "iso-8859" */
+ if (STRNCMP(p, "iso8859", 7) == 0)
+ {
+ mch_memmove(p + 4, p + 3, STRLEN(p + 2));
+ p[3] = '-';
+ }
+
+ /* "iso-8859n" -> "iso-8859-n" */
+ if (STRNCMP(p, "iso-8859", 8) == 0 && p[8] != '-')
+ {
+ mch_memmove(p + 9, p + 8, STRLEN(p + 7));
+ p[8] = '-';
+ }
+
+ /* "latin-N" -> "latinN" */
+ if (STRNCMP(p, "latin-", 6) == 0)
+ mch_memmove(p + 5, p + 6, STRLEN(p + 5));
+
+ if (enc_canon_search(p) >= 0)
+ {
+ /* canonical name can be used unmodified */
+ if (p != r)
+ mch_memmove(r, p, STRLEN(p) + 1);
+ }
+ else if ((i = enc_alias_search(p)) >= 0)
+ {
+ /* alias recognized, get canonical name */
+ vim_free(r);
+ r = vim_strsave((char_u *)enc_canon_table[i].name);
+ }
+ }
+ return r;
+}
+
+/*
+ * Search for an encoding alias of "name".
+ * Returns -1 when not found.
+ */
+ static int
+enc_alias_search(name)
+ char_u *name;
+{
+ int i;
+
+ for (i = 0; enc_alias_table[i].name != NULL; ++i)
+ if (STRCMP(name, enc_alias_table[i].name) == 0)
+ return enc_alias_table[i].canon;
+ return -1;
+}
+#endif
+
+#if defined(FEAT_MBYTE) || defined(PROTO)
+
+#ifdef HAVE_LANGINFO_H
+# include <langinfo.h>
+#endif
+
+/*
+ * Get the canonicalized encoding of the current locale.
+ * Returns an allocated string when successful, NULL when not.
+ */
+ char_u *
+enc_locale()
+{
+#ifndef WIN3264
+ char *s;
+ char *p;
+ int i;
+#endif
+ char buf[50];
+#ifdef WIN3264
+ long acp = GetACP();
+
+ if (acp == 1200)
+ STRCPY(buf, "ucs-2le");
+ else if (acp == 1252)
+ STRCPY(buf, "latin1");
+ else
+ sprintf(buf, "cp%ld", acp);
+#else
+# ifdef HAVE_NL_LANGINFO_CODESET
+ if ((s = nl_langinfo(CODESET)) == NULL || *s == NUL)
+# endif
+# if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+ if ((s = setlocale(LC_CTYPE, NULL)) == NULL || *s == NUL)
+# endif
+ if ((s = getenv("LC_ALL")) == NULL || *s == NUL)
+ if ((s = getenv("LC_CTYPE")) == NULL || *s == NUL)
+ s = getenv("LANG");
+
+ if (s == NULL || *s == NUL)
+ return FAIL;
+
+ /* The most generic locale format is:
+ * language[_territory][.codeset][@modifier][+special][,[sponsor][_revision]]
+ * If there is a '.' remove the part before it.
+ * if there is something after the codeset, remove it.
+ * Make the name lowercase and replace '_' with '-'.
+ * Exception: "ja_JP.EUC" == "euc-jp", "zh_CN.EUC" = "euc-cn",
+ * "ko_KR.EUC" == "euc-kr"
+ */
+ if ((p = (char *)vim_strchr((char_u *)s, '.')) != NULL)
+ {
+ if (p > s + 2 && STRNICMP(p + 1, "EUC", 3) == 0
+ && !isalnum((int)p[4]) && p[4] != '-' && p[-3] == '_')
+ {
+ /* copy "XY.EUC" to "euc-XY" to buf[10] */
+ STRCPY(buf + 10, "euc-");
+ buf[14] = p[-2];
+ buf[15] = p[-1];
+ buf[16] = 0;
+ s = buf + 10;
+ }
+ else
+ s = p + 1;
+ }
+ for (i = 0; s[i] != NUL && i < sizeof(buf) - 1; ++i)
+ {
+ if (s[i] == '_' || s[i] == '-')
+ buf[i] = '-';
+ else if (isalnum((int)s[i]))
+ buf[i] = TOLOWER_ASC(s[i]);
+ else
+ break;
+ }
+ buf[i] = NUL;
+#endif
+
+ return enc_canonize((char_u *)buf);
+}
+
+#if defined(WIN3264) || defined(PROTO)
+/*
+ * Convert an encoding name to an MS-Windows codepage.
+ * Returns zero if no codepage can be figured out.
+ */
+ int
+encname2codepage(name)
+ char_u *name;
+{
+ int cp;
+ char_u *p = name;
+ int idx;
+
+ if (STRNCMP(p, "8bit-", 5) == 0)
+ p += 5;
+ else if (STRNCMP(p_enc, "2byte-", 6) == 0)
+ p += 6;
+
+ if (p[0] == 'c' && p[1] == 'p')
+ cp = atoi(p + 2);
+ else if ((idx = enc_canon_search(p)) >= 0)
+ cp = enc_canon_table[idx].codepage;
+ else
+ return 0;
+ if (IsValidCodePage(cp))
+ return cp;
+ return 0;
+}
+#endif
+
+# if defined(USE_ICONV) || defined(PROTO)
+
+static char_u *iconv_string __ARGS((vimconv_T *vcp, char_u *str, int slen, int *unconvlenp));
+
+/*
+ * Call iconv_open() with a check if iconv() works properly (there are broken
+ * versions).
+ * Returns (void *)-1 if failed.
+ * (should return iconv_t, but that causes problems with prototypes).
+ */
+ void *
+my_iconv_open(to, from)
+ char_u *to;
+ char_u *from;
+{
+ iconv_t fd;
+#define ICONV_TESTLEN 400
+ char_u tobuf[ICONV_TESTLEN];
+ char *p;
+ size_t tolen;
+ static int iconv_ok = -1;
+
+ if (iconv_ok == FALSE)
+ return (void *)-1; /* detected a broken iconv() previously */
+
+#ifdef DYNAMIC_ICONV
+ /* Check if the iconv.dll can be found. */
+ if (!iconv_enabled(TRUE))
+ return (void *)-1;
+#endif
+
+ fd = iconv_open((char *)enc_skip(to), (char *)enc_skip(from));
+
+ if (fd != (iconv_t)-1 && iconv_ok == -1)
+ {
+ /*
+ * Do a dummy iconv() call to check if it actually works. There is a
+ * version of iconv() on Linux that is broken. We can't ignore it,
+ * because it's wide-spread. The symptoms are that after outputting
+ * the initial shift state the "to" pointer is NULL and conversion
+ * stops for no apparent reason after about 8160 characters.
+ */
+ p = (char *)tobuf;
+ tolen = ICONV_TESTLEN;
+ (void)iconv(fd, NULL, NULL, &p, &tolen);
+ if (p == NULL)
+ {
+ iconv_ok = FALSE;
+ iconv_close(fd);
+ fd = (iconv_t)-1;
+ }
+ else
+ iconv_ok = TRUE;
+ }
+
+ return (void *)fd;
+}
+
+/*
+ * Convert the string "str[slen]" with iconv().
+ * If "unconvlenp" is not NULL handle the string ending in an incomplete
+ * sequence and set "*unconvlenp" to the length of it.
+ * Returns the converted string in allocated memory. NULL for an error.
+ */
+ static char_u *
+iconv_string(vcp, str, slen, unconvlenp)
+ vimconv_T *vcp;
+ char_u *str;
+ int slen;
+ int *unconvlenp;
+{
+ const char *from;
+ size_t fromlen;
+ char *to;
+ size_t tolen;
+ size_t len = 0;
+ size_t done = 0;
+ char_u *result = NULL;
+ char_u *p;
+ int l;
+
+ from = (char *)str;
+ fromlen = slen;
+ for (;;)
+ {
+ if (len == 0 || ICONV_ERRNO == ICONV_E2BIG)
+ {
+ /* Allocate enough room for most conversions. When re-allocating
+ * increase the buffer size. */
+ len = len + fromlen * 2 + 40;
+ p = alloc((unsigned)len);
+ if (p != NULL && done > 0)
+ mch_memmove(p, result, done);
+ vim_free(result);
+ result = p;
+ if (result == NULL) /* out of memory */
+ break;
+ }
+
+ to = (char *)result + done;
+ tolen = len - done - 2;
+ /* Avoid a warning for systems with a wrong iconv() prototype by
+ * casting the second argument to void *. */
+ if (iconv(vcp->vc_fd, (void *)&from, &fromlen, &to, &tolen)
+ != (size_t)-1)
+ {
+ /* Finished, append a NUL. */
+ *to = NUL;
+ break;
+ }
+
+ /* Check both ICONV_EINVAL and EINVAL, because the dynamically loaded
+ * iconv library may use one of them. */
+ if (!vcp->vc_fail && unconvlenp != NULL
+ && (ICONV_ERRNO == ICONV_EINVAL || ICONV_ERRNO == EINVAL))
+ {
+ /* Handle an incomplete sequence at the end. */
+ *to = NUL;
+ *unconvlenp = fromlen;
+ break;
+ }
+
+ /* Check both ICONV_EILSEQ and EILSEQ, because the dynamically loaded
+ * iconv library may use one of them. */
+ else if (!vcp->vc_fail
+ && (ICONV_ERRNO == ICONV_EILSEQ || ICONV_ERRNO == EILSEQ
+ || ICONV_ERRNO == ICONV_EINVAL || ICONV_ERRNO == EINVAL))
+ {
+ /* Can't convert: insert a '?' and skip a character. This assumes
+ * conversion from 'encoding' to something else. In other
+ * situations we don't know what to skip anyway. */
+ *to++ = '?';
+ if ((*mb_ptr2cells)((char_u *)from) > 1)
+ *to++ = '?';
+ l = (*mb_ptr2len_check)((char_u *)from);
+ from += l;
+ fromlen -= l;
+ }
+ else if (ICONV_ERRNO != ICONV_E2BIG)
+ {
+ /* conversion failed */
+ vim_free(result);
+ result = NULL;
+ break;
+ }
+ /* Not enough room or skipping illegal sequence. */
+ done = to - (char *)result;
+ }
+ return result;
+}
+
+# if defined(DYNAMIC_ICONV) || defined(PROTO)
+/*
+ * Dynamically load the "iconv.dll" on Win32.
+ */
+
+#ifndef DYNAMIC_ICONV /* just generating prototypes */
+# define HINSTANCE int
+#endif
+HINSTANCE hIconvDLL = 0;
+HINSTANCE hMsvcrtDLL = 0;
+
+# ifndef DYNAMIC_ICONV_DLL
+# define DYNAMIC_ICONV_DLL "iconv.dll"
+# define DYNAMIC_ICONV_DLL_ALT "libiconv.dll"
+# endif
+# ifndef DYNAMIC_MSVCRT_DLL
+# define DYNAMIC_MSVCRT_DLL "msvcrt.dll"
+# endif
+
+/*
+ * Try opening the iconv.dll and return TRUE if iconv() can be used.
+ */
+ int
+iconv_enabled(verbose)
+ int verbose;
+{
+ if (hIconvDLL != 0 && hMsvcrtDLL != 0)
+ return TRUE;
+ hIconvDLL = LoadLibrary(DYNAMIC_ICONV_DLL);
+ if (hIconvDLL == 0) /* sometimes it's called libiconv.dll */
+ hIconvDLL = LoadLibrary(DYNAMIC_ICONV_DLL_ALT);
+ if (hIconvDLL != 0)
+ hMsvcrtDLL = LoadLibrary(DYNAMIC_MSVCRT_DLL);
+ if (hIconvDLL == 0 || hMsvcrtDLL == 0)
+ {
+ /* Only give the message when 'verbose' is set, otherwise it might be
+ * done whenever a conversion is attempted. */
+ if (verbose && p_verbose > 0)
+ EMSG2(_(e_loadlib),
+ hIconvDLL == 0 ? DYNAMIC_ICONV_DLL : DYNAMIC_MSVCRT_DLL);
+ iconv_end();
+ return FALSE;
+ }
+
+ *((FARPROC*)&iconv) = GetProcAddress(hIconvDLL, "libiconv");
+ *((FARPROC*)&iconv_open) = GetProcAddress(hIconvDLL, "libiconv_open");
+ *((FARPROC*)&iconv_close) = GetProcAddress(hIconvDLL, "libiconv_close");
+ *((FARPROC*)&iconvctl) = GetProcAddress(hIconvDLL, "libiconvctl");
+ *((FARPROC*)&iconv_errno) = GetProcAddress(hMsvcrtDLL, "_errno");
+ if (iconv == NULL || iconv_open == NULL || iconv_close == NULL
+ || iconvctl == NULL || iconv_errno == NULL)
+ {
+ iconv_end();
+ if (verbose && p_verbose > 0)
+ EMSG2(_(e_loadfunc), "for libiconv");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+ void
+iconv_end()
+{
+ /* Don't use iconv() when inputting or outputting characters. */
+ if (input_conv.vc_type == CONV_ICONV)
+ convert_setup(&input_conv, NULL, NULL);
+ if (output_conv.vc_type == CONV_ICONV)
+ convert_setup(&output_conv, NULL, NULL);
+
+ if (hIconvDLL != 0)
+ FreeLibrary(hIconvDLL);
+ if (hMsvcrtDLL != 0)
+ FreeLibrary(hMsvcrtDLL);
+ hIconvDLL = 0;
+ hMsvcrtDLL = 0;
+}
+# endif /* DYNAMIC_ICONV */
+# endif /* USE_ICONV */
+
+#endif /* FEAT_MBYTE */
+
+#if defined(FEAT_XIM) || defined(PROTO)
+
+# ifdef FEAT_GUI_GTK
+static int xim_has_preediting INIT(= FALSE); /* IM current status */
+
+/*
+ * Set preedit_start_col to the current cursor position.
+ */
+ static void
+init_preedit_start_col(void)
+{
+ if (State & CMDLINE)
+ preedit_start_col = cmdline_getvcol_cursor();
+ else if (curwin != NULL)
+ getvcol(curwin, &curwin->w_cursor, &preedit_start_col, NULL, NULL);
+ /* Prevent that preediting marks the buffer as changed. */
+ xim_changed_while_preediting = curbuf->b_changed;
+}
+# endif
+
+# if defined(HAVE_GTK2) && !defined(PROTO)
+
+static int im_is_active = FALSE; /* IM is enabled for current mode */
+static int im_preedit_cursor = 0; /* cursor offset in characters */
+static int im_preedit_trailing = 0; /* number of characters after cursor */
+
+static unsigned long im_commit_handler_id = 0;
+static unsigned int im_activatekey_keyval = GDK_VoidSymbol;
+static unsigned int im_activatekey_state = 0;
+
+ void
+im_set_active(int active)
+{
+ int was_active;
+
+ was_active = !!im_is_active;
+ im_is_active = (active && !p_imdisable);
+
+ if (im_is_active != was_active)
+ xim_reset();
+}
+
+ void
+xim_set_focus(int focus)
+{
+ if (xic != NULL)
+ {
+ if (focus)
+ gtk_im_context_focus_in(xic);
+ else
+ gtk_im_context_focus_out(xic);
+ }
+}
+
+ void
+im_set_position(int row, int col)
+{
+ if (xic != NULL)
+ {
+ GdkRectangle area;
+
+ area.x = FILL_X(col);
+ area.y = FILL_Y(row);
+ area.width = gui.char_width * (mb_lefthalve(row, col) ? 2 : 1);
+ area.height = gui.char_height;
+
+ gtk_im_context_set_cursor_location(xic, &area);
+ }
+}
+
+# if 0 || defined(PROTO) /* apparently only used in gui_x11.c */
+ void
+xim_set_preedit(void)
+{
+ im_set_position(gui.row, gui.col);
+}
+# endif
+
+ static void
+im_add_to_input(char_u *str, int len)
+{
+ /* Convert from 'termencoding' (always "utf-8") to 'encoding' */
+ if (input_conv.vc_type != CONV_NONE)
+ {
+ str = string_convert(&input_conv, str, &len);
+ g_return_if_fail(str != NULL);
+ }
+
+ add_to_input_buf_csi(str, len);
+
+ if (input_conv.vc_type != CONV_NONE)
+ vim_free(str);
+
+ if (p_mh) /* blank out the pointer if necessary */
+ gui_mch_mousehide(TRUE);
+}
+
+ static void
+im_delete_preedit(void)
+{
+ char_u bskey[] = {CSI, 'k', 'b'};
+ char_u delkey[] = {CSI, 'k', 'D'};
+
+ if (State & NORMAL)
+ {
+ im_preedit_cursor = 0;
+ return;
+ }
+ for (; im_preedit_cursor > 0; --im_preedit_cursor)
+ add_to_input_buf(bskey, (int)sizeof(bskey));
+
+ for (; im_preedit_trailing > 0; --im_preedit_trailing)
+ add_to_input_buf(delkey, (int)sizeof(delkey));
+}
+
+ static void
+im_correct_cursor(int num_move_back)
+{
+ char_u backkey[] = {CSI, 'k', 'l'};
+
+ if (State & NORMAL)
+ return;
+# ifdef FEAT_RIGHTLEFT
+ if ((State & CMDLINE) == 0 && curwin != NULL && curwin->w_p_rl)
+ backkey[2] = 'r';
+# endif
+ for (; num_move_back > 0; --num_move_back)
+ add_to_input_buf(backkey, (int)sizeof(backkey));
+}
+
+static int xim_expected_char = NUL;
+static int xim_ignored_char = FALSE;
+
+/*
+ * Update the mode and cursor while in an IM callback.
+ */
+ static void
+im_show_info(void)
+{
+ int old_vgetc_busy;
+ old_vgetc_busy = vgetc_busy;
+ vgetc_busy = TRUE;
+ showmode();
+ vgetc_busy = old_vgetc_busy;
+ setcursor();
+ out_flush();
+}
+
+/*
+ * Callback invoked when the user finished preediting.
+ * Put the final string into the input buffer.
+ */
+/*ARGSUSED0*/
+ static void
+im_commit_cb(GtkIMContext *context, const gchar *str, gpointer data)
+{
+ int slen = (int)STRLEN(str);
+ int add_to_input = TRUE;
+ int clen;
+ int len = slen;
+ int commit_with_preedit = TRUE;
+ char_u *im_str, *p;
+
+#ifdef XIM_DEBUG
+ xim_log("im_commit_cb(): %s\n", str);
+#endif
+
+ /* The imhangul module doesn't reset the preedit string before
+ * committing. Call im_delete_preedit() to work around that. */
+ im_delete_preedit();
+
+ /* Indicate that preediting has finished. */
+ if (preedit_start_col == MAXCOL)
+ {
+ init_preedit_start_col();
+ commit_with_preedit = FALSE;
+ }
+
+ /* The thing which setting "preedit_start_col" to MAXCOL means that
+ * "preedit_start_col" will be set forcely when calling
+ * preedit_changed_cb() next time.
+ * "preedit_start_col" should not reset with MAXCOL on this part. Vim
+ * is simulating the preediting by using add_to_input_str(). when
+ * preedit begin immediately before committed, the typebuf is not
+ * flushed to screen, then it can't get correct "preedit_start_col".
+ * Thus, it should calculate the cells by adding cells of the committed
+ * string. */
+ if (input_conv.vc_type != CONV_NONE)
+ {
+ im_str = string_convert(&input_conv, (char_u *)str, &len);
+ g_return_if_fail(im_str != NULL);
+ }
+ else
+ im_str = (char_u *)str;
+ clen = 0;
+ for (p = im_str; p < im_str + len; p += (*mb_ptr2len_check)(p))
+ clen += (*mb_ptr2cells)(p);
+ if (input_conv.vc_type != CONV_NONE)
+ vim_free(im_str);
+ preedit_start_col += clen;
+
+ /* Is this a single character that matches a keypad key that's just
+ * been pressed? If so, we don't want it to be entered as such - let
+ * us carry on processing the raw keycode so that it may be used in
+ * mappings as <kSomething>. */
+ if (xim_expected_char != NUL)
+ {
+ /* We're currently processing a keypad or other special key */
+ if (slen == 1 && str[0] == xim_expected_char)
+ {
+ /* It's a match - don't do it here */
+ xim_ignored_char = TRUE;
+ add_to_input = FALSE;
+ }
+ else
+ {
+ /* Not a match */
+ xim_ignored_char = FALSE;
+ }
+ }
+
+ if (add_to_input)
+ im_add_to_input((char_u *)str, slen);
+
+ /* Inserting chars while "im_is_active" is set does not cause a change of
+ * buffer. When the chars are committed the buffer must be marked as
+ * changed. */
+ if (!commit_with_preedit)
+ preedit_start_col = MAXCOL;
+
+ /* This flag is used in changed() at next call. */
+ xim_changed_while_preediting = TRUE;
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+/*
+ * Callback invoked after start to the preedit.
+ */
+/*ARGSUSED*/
+ static void
+im_preedit_start_cb(GtkIMContext *context, gpointer data)
+{
+#ifdef XIM_DEBUG
+ xim_log("im_preedit_start_cb()\n");
+#endif
+
+ im_is_active = TRUE;
+ gui_update_cursor(TRUE, FALSE);
+}
+
+/*
+ * Callback invoked after end to the preedit.
+ */
+/*ARGSUSED*/
+ static void
+im_preedit_end_cb(GtkIMContext *context, gpointer data)
+{
+#ifdef XIM_DEBUG
+ xim_log("im_preedit_end_cb()\n");
+#endif
+ im_delete_preedit();
+
+ /* Indicate that preediting has finished */
+ preedit_start_col = MAXCOL;
+ xim_has_preediting = FALSE;
+
+ im_is_active = FALSE;
+ gui_update_cursor(TRUE, FALSE);
+ im_show_info();
+}
+
+/*
+ * Callback invoked after changes to the preedit string. If the preedit
+ * string was empty before, remember the preedit start column so we know
+ * where to apply feedback attributes. Delete the previous preedit string
+ * if there was one, save the new preedit cursor offset, and put the new
+ * string into the input buffer.
+ *
+ * TODO: The pragmatic "put into input buffer" approach used here has
+ * several fundamental problems:
+ *
+ * - The characters in the preedit string are subject to remapping.
+ * That's broken, only the finally committed string should be remapped.
+ *
+ * - There is a race condition involved: The retrieved value for the
+ * current cursor position will be wrong if any unprocessed characters
+ * are still queued in the input buffer.
+ *
+ * - Due to the lack of synchronization between the file buffer in memory
+ * and any typed characters, it's practically impossible to implement the
+ * "retrieve_surrounding" and "delete_surrounding" signals reliably. IM
+ * modules for languages such as Thai are likely to rely on this feature
+ * for proper operation.
+ *
+ * Conclusions: I think support for preediting needs to be moved to the
+ * core parts of Vim. Ideally, until it has been committed, the preediting
+ * string should only be displayed and not affect the buffer content at all.
+ * The question how to deal with the synchronization issue still remains.
+ * Circumventing the input buffer is probably not desirable. Anyway, I think
+ * implementing "retrieve_surrounding" is the only hard problem.
+ *
+ * One way to solve all of this in a clean manner would be to queue all key
+ * press/release events "as is" in the input buffer, and apply the IM filtering
+ * at the receiving end of the queue. This, however, would have a rather large
+ * impact on the code base. If there is an easy way to force processing of all
+ * remaining input from within the "retrieve_surrounding" signal handler, this
+ * might not be necessary. Gotta ask on vim-dev for opinions.
+ */
+/*ARGSUSED1*/
+ static void
+im_preedit_changed_cb(GtkIMContext *context, gpointer data)
+{
+ char *preedit_string = NULL;
+ int cursor_index = 0;
+ int num_move_back = 0;
+ char_u *str;
+ char_u *p;
+ int i;
+
+ gtk_im_context_get_preedit_string(context,
+ &preedit_string, NULL,
+ &cursor_index);
+
+#ifdef XIM_DEBUG
+ xim_log("im_preedit_changed_cb(): %s\n", preedit_string);
+#endif
+
+ g_return_if_fail(preedit_string != NULL); /* just in case */
+
+ /* If preedit_start_col is MAXCOL set it to the current cursor position. */
+ if (preedit_start_col == MAXCOL && preedit_string[0] != '\0')
+ {
+ xim_has_preediting = TRUE;
+
+ /* Urgh, this breaks if the input buffer isn't empty now */
+ init_preedit_start_col();
+ }
+ else if (cursor_index == 0 && preedit_string[0] == '\0')
+ {
+ if (preedit_start_col == MAXCOL)
+ xim_has_preediting = FALSE;
+
+ /* If at the start position (after typing backspace)
+ * preedit_start_col must be reset. */
+ preedit_start_col = MAXCOL;
+ }
+
+ im_delete_preedit();
+
+ /*
+ * Compute the end of the preediting area: "preedit_end_col".
+ * According to the documentation of gtk_im_context_get_preedit_string(),
+ * the cursor_pos output argument returns the offset in bytes. This is
+ * unfortunately not true -- real life shows the offset is in characters,
+ * and the GTK+ source code agrees with me. Will file a bug later.
+ */
+ if (preedit_start_col != MAXCOL)
+ preedit_end_col = preedit_start_col;
+ str = (char_u *)preedit_string;
+ for (p = str, i = 0; *p != NUL; p += utf_byte2len(*p), ++i)
+ {
+ int is_composing;
+
+ is_composing = ((*p & 0x80) != 0 && utf_iscomposing(utf_ptr2char(p)));
+ /*
+ * These offsets are used as counters when generating <BS> and <Del>
+ * to delete the preedit string. So don't count composing characters
+ * unless 'delcombine' is enabled.
+ */
+ if (!is_composing || p_deco)
+ {
+ if (i < cursor_index)
+ ++im_preedit_cursor;
+ else
+ ++im_preedit_trailing;
+ }
+ if (!is_composing && i >= cursor_index)
+ {
+ /* This is essentially the same as im_preedit_trailing, except
+ * composing characters are not counted even if p_deco is set. */
+ ++num_move_back;
+ }
+ if (preedit_start_col != MAXCOL)
+ preedit_end_col += utf_ptr2cells(p);
+ }
+
+ if (p > str)
+ {
+ im_add_to_input(str, (int)(p - str));
+ im_correct_cursor(num_move_back);
+ }
+
+ g_free(preedit_string);
+
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+/*
+ * Translate the Pango attributes at iter to Vim highlighting attributes.
+ * Ignore attributes not supported by Vim highlighting. This shouldn't have
+ * too much impact -- right now we handle even more attributes than necessary
+ * for the IM modules I tested with.
+ */
+ static int
+translate_pango_attributes(PangoAttrIterator *iter)
+{
+ PangoAttribute *attr;
+ int char_attr = HL_NORMAL;
+
+ attr = pango_attr_iterator_get(iter, PANGO_ATTR_UNDERLINE);
+ if (attr != NULL && ((PangoAttrInt *)attr)->value
+ != (int)PANGO_UNDERLINE_NONE)
+ char_attr |= HL_UNDERLINE;
+
+ attr = pango_attr_iterator_get(iter, PANGO_ATTR_WEIGHT);
+ if (attr != NULL && ((PangoAttrInt *)attr)->value >= (int)PANGO_WEIGHT_BOLD)
+ char_attr |= HL_BOLD;
+
+ attr = pango_attr_iterator_get(iter, PANGO_ATTR_STYLE);
+ if (attr != NULL && ((PangoAttrInt *)attr)->value
+ != (int)PANGO_STYLE_NORMAL)
+ char_attr |= HL_ITALIC;
+
+ attr = pango_attr_iterator_get(iter, PANGO_ATTR_BACKGROUND);
+ if (attr != NULL)
+ {
+ const PangoColor *color = &((PangoAttrColor *)attr)->color;
+
+ /* Assume inverse if black background is requested */
+ if ((color->red | color->green | color->blue) == 0)
+ char_attr |= HL_INVERSE;
+ }
+
+ return char_attr;
+}
+
+/*
+ * Retrieve the highlighting attributes at column col in the preedit string.
+ * Return -1 if not in preediting mode or if col is out of range.
+ */
+ int
+im_get_feedback_attr(int col)
+{
+ char *preedit_string = NULL;
+ PangoAttrList *attr_list = NULL;
+ int char_attr = -1;
+
+ if (xic == NULL)
+ return char_attr;
+
+ gtk_im_context_get_preedit_string(xic, &preedit_string, &attr_list, NULL);
+
+ if (preedit_string != NULL && attr_list != NULL)
+ {
+ int index;
+
+ /* Get the byte index as used by PangoAttrIterator */
+ for (index = 0; col > 0 && preedit_string[index] != '\0'; --col)
+ index += utfc_ptr2len_check((char_u *)preedit_string + index);
+
+ if (preedit_string[index] != '\0')
+ {
+ PangoAttrIterator *iter;
+ int start, end;
+
+ char_attr = HL_NORMAL;
+ iter = pango_attr_list_get_iterator(attr_list);
+
+ /* Extract all relevant attributes from the list. */
+ do
+ {
+ pango_attr_iterator_range(iter, &start, &end);
+
+ if (index >= start && index < end)
+ char_attr |= translate_pango_attributes(iter);
+ }
+ while (pango_attr_iterator_next(iter));
+
+ pango_attr_iterator_destroy(iter);
+ }
+ }
+
+ if (attr_list != NULL)
+ pango_attr_list_unref(attr_list);
+ g_free(preedit_string);
+
+ return char_attr;
+}
+
+ void
+xim_init(void)
+{
+#ifdef XIM_DEBUG
+ xim_log("xim_init()\n");
+#endif
+
+ g_return_if_fail(gui.drawarea != NULL);
+ g_return_if_fail(gui.drawarea->window != NULL);
+
+ xic = gtk_im_multicontext_new();
+ g_object_ref(xic);
+
+ im_commit_handler_id = g_signal_connect(G_OBJECT(xic), "commit",
+ G_CALLBACK(&im_commit_cb), NULL);
+ g_signal_connect(G_OBJECT(xic), "preedit_changed",
+ G_CALLBACK(&im_preedit_changed_cb), NULL);
+ g_signal_connect(G_OBJECT(xic), "preedit_start",
+ G_CALLBACK(&im_preedit_start_cb), NULL);
+ g_signal_connect(G_OBJECT(xic), "preedit_end",
+ G_CALLBACK(&im_preedit_end_cb), NULL);
+
+ gtk_im_context_set_client_window(xic, gui.drawarea->window);
+}
+
+ void
+im_shutdown(void)
+{
+#ifdef XIM_DEBUG
+ xim_log("im_shutdown()\n");
+#endif
+
+ if (xic != NULL)
+ {
+ gtk_im_context_focus_out(xic);
+ g_object_unref(xic);
+ xic = NULL;
+ }
+ im_is_active = FALSE;
+ im_commit_handler_id = 0;
+ preedit_start_col = MAXCOL;
+ xim_has_preediting = FALSE;
+}
+
+/*
+ * Convert the string argument to keyval and state for GdkEventKey.
+ * If str is valid return TRUE, otherwise FALSE.
+ *
+ * See 'imactivatekey' for documentation of the format.
+ */
+ static int
+im_string_to_keyval(const char *str, unsigned int *keyval, unsigned int *state)
+{
+ const char *mods_end;
+ unsigned tmp_keyval;
+ unsigned tmp_state = 0;
+
+ mods_end = strrchr(str, '-');
+ mods_end = (mods_end != NULL) ? mods_end + 1 : str;
+
+ /* Parse modifier keys */
+ while (str < mods_end)
+ switch (*str++)
+ {
+ case '-': break;
+ case 'S': case 's': tmp_state |= (unsigned)GDK_SHIFT_MASK; break;
+ case 'L': case 'l': tmp_state |= (unsigned)GDK_LOCK_MASK; break;
+ case 'C': case 'c': tmp_state |= (unsigned)GDK_CONTROL_MASK;break;
+ case '1': tmp_state |= (unsigned)GDK_MOD1_MASK; break;
+ case '2': tmp_state |= (unsigned)GDK_MOD2_MASK; break;
+ case '3': tmp_state |= (unsigned)GDK_MOD3_MASK; break;
+ case '4': tmp_state |= (unsigned)GDK_MOD4_MASK; break;
+ case '5': tmp_state |= (unsigned)GDK_MOD5_MASK; break;
+ default:
+ return FALSE;
+ }
+
+ tmp_keyval = gdk_keyval_from_name(str);
+
+ if (tmp_keyval == 0 || tmp_keyval == GDK_VoidSymbol)
+ return FALSE;
+
+ if (keyval != NULL)
+ *keyval = tmp_keyval;
+ if (state != NULL)
+ *state = tmp_state;
+
+ return TRUE;
+}
+
+/*
+ * Return TRUE if p_imak is valid, otherwise FALSE. As a special case, an
+ * empty string is also regarded as valid.
+ *
+ * Note: The numerical key value of p_imak is cached if it was valid; thus
+ * boldly assuming im_xim_isvalid_imactivate() will always be called whenever
+ * 'imak' changes. This is currently the case but not obvious -- should
+ * probably rename the function for clarity.
+ */
+ int
+im_xim_isvalid_imactivate(void)
+{
+ if (p_imak[0] == NUL)
+ {
+ im_activatekey_keyval = GDK_VoidSymbol;
+ im_activatekey_state = 0;
+ return TRUE;
+ }
+
+ return im_string_to_keyval((const char *)p_imak,
+ &im_activatekey_keyval,
+ &im_activatekey_state);
+}
+
+ static void
+im_synthesize_keypress(unsigned int keyval, unsigned int state)
+{
+ GdkEventKey *event;
+
+# ifdef HAVE_GTK_MULTIHEAD
+ event = (GdkEventKey *)gdk_event_new(GDK_KEY_PRESS);
+ g_object_ref(gui.drawarea->window); /* unreffed by gdk_event_free() */
+# else
+ event = (GdkEventKey *)g_malloc0((gulong)sizeof(GdkEvent));
+ event->type = GDK_KEY_PRESS;
+# endif
+ event->window = gui.drawarea->window;
+ event->send_event = TRUE;
+ event->time = GDK_CURRENT_TIME;
+ event->state = state;
+ event->keyval = keyval;
+ event->hardware_keycode = /* needed for XIM */
+ XKeysymToKeycode(GDK_WINDOW_XDISPLAY(event->window), (KeySym)keyval);
+ event->length = 0;
+ event->string = NULL;
+
+ gtk_im_context_filter_keypress(xic, event);
+
+ /* For consistency, also send the corresponding release event. */
+ event->type = GDK_KEY_RELEASE;
+ event->send_event = FALSE;
+ gtk_im_context_filter_keypress(xic, event);
+
+# ifdef HAVE_GTK_MULTIHEAD
+ gdk_event_free((GdkEvent *)event);
+# else
+ g_free(event);
+# endif
+}
+
+ void
+xim_reset(void)
+{
+ if (xic != NULL)
+ {
+ /*
+ * The third-party imhangul module (and maybe others too) ignores
+ * gtk_im_context_reset() or at least doesn't reset the active state.
+ * Thus sending imactivatekey would turn it off if it was on before,
+ * which is clearly not what we want. Fortunately we can work around
+ * that for imhangul by sending GDK_Escape, but I don't know if it
+ * works with all IM modules that support an activation key :/
+ *
+ * An alternative approach would be to destroy the IM context and
+ * recreate it. But that means loading/unloading the IM module on
+ * every mode switch, which causes a quite noticable delay even on
+ * my rather fast box...
+ * *
+ * Moreover, there are some XIM which cannot respond to
+ * im_synthesize_keypress(). we hope that they reset by
+ * xim_shutdown().
+ */
+ if (im_activatekey_keyval != GDK_VoidSymbol && im_is_active)
+ im_synthesize_keypress(GDK_Escape, 0U);
+
+ gtk_im_context_reset(xic);
+
+ /*
+ * HACK for Ami: This sequence of function calls makes Ami handle
+ * the IM reset gratiously, without breaking loads of other stuff.
+ * It seems to force English mode as well, which is exactly what we
+ * want because it makes the Ami status display work reliably.
+ */
+ gtk_im_context_set_use_preedit(xic, FALSE);
+
+ if (p_imdisable)
+ im_shutdown();
+ else
+ {
+ gtk_im_context_set_use_preedit(xic, TRUE);
+ xim_set_focus(gui.in_focus);
+
+ if (im_activatekey_keyval != GDK_VoidSymbol)
+ {
+ if (im_is_active)
+ {
+ g_signal_handler_block(xic, im_commit_handler_id);
+ im_synthesize_keypress(im_activatekey_keyval,
+ im_activatekey_state);
+ g_signal_handler_unblock(xic, im_commit_handler_id);
+ }
+ }
+ else
+ {
+ im_shutdown();
+ xim_init();
+ xim_set_focus(gui.in_focus);
+ }
+ }
+ }
+
+ preedit_start_col = MAXCOL;
+ xim_has_preediting = FALSE;
+}
+
+ int
+xim_queue_key_press_event(GdkEventKey *event, int down)
+{
+ if (down)
+ {
+ /*
+ * Workaround GTK2 XIM 'feature' that always converts keypad keys to
+ * chars., even when not part of an IM sequence (ref. feature of
+ * gdk/gdkkeyuni.c).
+ * Flag any keypad keys that might represent a single char.
+ * If this (on its own - i.e., not part of an IM sequence) is
+ * committed while we're processing one of these keys, we can ignore
+ * that commit and go ahead & process it ourselves. That way we can
+ * still distinguish keypad keys for use in mappings.
+ */
+ switch (event->keyval)
+ {
+ case GDK_KP_Add: xim_expected_char = '+'; break;
+ case GDK_KP_Subtract: xim_expected_char = '-'; break;
+ case GDK_KP_Divide: xim_expected_char = '/'; break;
+ case GDK_KP_Multiply: xim_expected_char = '*'; break;
+ case GDK_KP_Decimal: xim_expected_char = '.'; break;
+ case GDK_KP_Equal: xim_expected_char = '='; break;
+ case GDK_KP_0: xim_expected_char = '0'; break;
+ case GDK_KP_1: xim_expected_char = '1'; break;
+ case GDK_KP_2: xim_expected_char = '2'; break;
+ case GDK_KP_3: xim_expected_char = '3'; break;
+ case GDK_KP_4: xim_expected_char = '4'; break;
+ case GDK_KP_5: xim_expected_char = '5'; break;
+ case GDK_KP_6: xim_expected_char = '6'; break;
+ case GDK_KP_7: xim_expected_char = '7'; break;
+ case GDK_KP_8: xim_expected_char = '8'; break;
+ case GDK_KP_9: xim_expected_char = '9'; break;
+ default: xim_expected_char = NUL;
+ }
+ xim_ignored_char = FALSE;
+ }
+
+ /*
+ * When typing fFtT, XIM may be activated. Thus it must pass
+ * gtk_im_context_filter_keypress() in Normal mode.
+ * And while doing :sh too.
+ */
+ if (xic != NULL && !p_imdisable
+ && (State & (INSERT | CMDLINE | NORMAL | EXTERNCMD)) != 0)
+ {
+ /*
+ * Filter 'imactivatekey' and map it to CTRL-^. This way, Vim is
+ * always aware of the current status of IM, and can even emulate
+ * the activation key for modules that don't support one.
+ */
+ if (event->keyval == im_activatekey_keyval
+ && (event->state & im_activatekey_state) == im_activatekey_state)
+ {
+ unsigned int state_mask;
+
+ /* Require the state of the 3 most used modifiers to match exactly.
+ * Otherwise e.g. <S-C-space> would be unusable for other purposes
+ * if the IM activate key is <S-space>. */
+ state_mask = im_activatekey_state;
+ state_mask |= ((int)GDK_SHIFT_MASK | (int)GDK_CONTROL_MASK
+ | (int)GDK_MOD1_MASK);
+
+ if ((event->state & state_mask) != im_activatekey_state)
+ return FALSE;
+
+ /* Don't send it a second time on GDK_KEY_RELEASE. */
+ if (event->type != GDK_KEY_PRESS)
+ return TRUE;
+
+ if (map_to_exists_mode((char_u *)"", LANGMAP))
+ {
+ im_set_active(FALSE);
+
+ /* ":lmap" mappings exists, toggle use of mappings. */
+ State ^= LANGMAP;
+ if (State & LANGMAP)
+ {
+ curbuf->b_p_iminsert = B_IMODE_NONE;
+ State &= ~LANGMAP;
+ }
+ else
+ {
+ curbuf->b_p_iminsert = B_IMODE_LMAP;
+ State |= LANGMAP;
+ }
+ return TRUE;
+ }
+
+ return gtk_im_context_filter_keypress(xic, event);
+ }
+
+ /* Don't filter events through the IM context if IM isn't active
+ * right now. Unlike with GTK+ 1.2 we cannot rely on the IM module
+ * not doing anything before the activation key was sent. */
+ if (im_activatekey_keyval == GDK_VoidSymbol || im_is_active)
+ {
+ int imresult = gtk_im_context_filter_keypress(xic, event);
+
+ /* Some XIM send following sequence:
+ * 1. preedited string.
+ * 2. committed string.
+ * 3. line changed key.
+ * 4. preedited string.
+ * 5. remove preedited string.
+ * if 3, Vim can't move back the above line for 5.
+ * thus, this part should not parse the key. */
+ if (!imresult && preedit_start_col != MAXCOL
+ && event->keyval == GDK_Return)
+ {
+ im_synthesize_keypress(GDK_Return, 0U);
+ return FALSE;
+ }
+
+ /* If XIM tried to commit a keypad key as a single char.,
+ * ignore it so we can use the keypad key 'raw', for mappings. */
+ if (xim_expected_char != NUL && xim_ignored_char)
+ /* We had a keypad key, and XIM tried to thieve it */
+ return FALSE;
+
+ /* Normal processing */
+ return imresult;
+ }
+ }
+
+ return FALSE;
+}
+
+ int
+im_get_status(void)
+{
+ return im_is_active;
+}
+
+# else /* !HAVE_GTK2 */
+
+static int xim_is_active = FALSE; /* XIM should be active in the current
+ mode */
+static int xim_has_focus = FALSE; /* XIM is really being used for Vim */
+#ifdef FEAT_GUI_X11
+static XIMStyle input_style;
+static int status_area_enabled = TRUE;
+#endif
+
+#ifdef FEAT_GUI_GTK
+# ifdef WIN3264
+# include <gdk/gdkwin32.h>
+# else
+# include <gdk/gdkx.h>
+# endif
+#else
+# ifdef PROTO
+/* Define a few things to be able to generate prototypes while not configured
+ * for GTK. */
+# define GSList int
+# define gboolean int
+ typedef int GdkEvent;
+ typedef int GdkEventKey;
+# define GdkIC int
+# endif
+#endif
+
+#if defined(FEAT_GUI_GTK) || defined(PROTO)
+static int preedit_buf_len = 0;
+static int xim_can_preediting INIT(= FALSE); /* XIM in showmode() */
+static int xim_input_style;
+#ifndef FEAT_GUI_GTK
+# define gboolean int
+#endif
+static gboolean use_status_area = 0;
+
+static int im_xim_str2keycode __ARGS((unsigned int *code, unsigned int *state));
+static void im_xim_send_event_imactivate __ARGS((void));
+
+/*
+ * Convert string to keycode and state for XKeyEvent.
+ * When string is valid return OK, when invalid return FAIL.
+ *
+ * See 'imactivatekey' documentation for the format.
+ */
+ static int
+im_xim_str2keycode(code, state)
+ unsigned int *code;
+ unsigned int *state;
+{
+ int retval = OK;
+ int len;
+ unsigned keycode = 0, keystate = 0;
+ Window window;
+ Display *display;
+ char_u *flag_end;
+ char_u *str;
+
+ if (*p_imak != NUL)
+ {
+ len = STRLEN(p_imak);
+ for (flag_end = p_imak + len - 1;
+ flag_end > p_imak && *flag_end != '-'; --flag_end)
+ ;
+
+ /* Parse modifier keys */
+ for (str = p_imak; str < flag_end; ++str)
+ {
+ switch (*str)
+ {
+ case 's': case 'S':
+ keystate |= ShiftMask;
+ break;
+ case 'l': case 'L':
+ keystate |= LockMask;
+ break;
+ case 'c': case 'C':
+ keystate |= ControlMask;
+ break;
+ case '1':
+ keystate |= Mod1Mask;
+ break;
+ case '2':
+ keystate |= Mod2Mask;
+ break;
+ case '3':
+ keystate |= Mod3Mask;
+ break;
+ case '4':
+ keystate |= Mod4Mask;
+ break;
+ case '5':
+ keystate |= Mod5Mask;
+ break;
+ case '-':
+ break;
+ default:
+ retval = FAIL;
+ }
+ }
+ if (*str == '-')
+ ++str;
+
+ /* Get keycode from string. */
+ gui_get_x11_windis(&window, &display);
+ if (display)
+ keycode = XKeysymToKeycode(display, XStringToKeysym((char *)str));
+ if (keycode == 0)
+ retval = FAIL;
+
+ if (code != NULL)
+ *code = keycode;
+ if (state != NULL)
+ *state = keystate;
+ }
+ return retval;
+}
+
+ static void
+im_xim_send_event_imactivate()
+{
+ /* Force turn on preedit state by symulate keypress event.
+ * Keycode and state is specified by 'imactivatekey'.
+ */
+ XKeyEvent ev;
+
+ gui_get_x11_windis(&ev.window, &ev.display);
+ ev.root = RootWindow(ev.display, DefaultScreen(ev.display));
+ ev.subwindow = None;
+ ev.time = CurrentTime;
+ ev.x = 1;
+ ev.y = 1;
+ ev.x_root = 1;
+ ev.y_root = 1;
+ ev.same_screen = 1;
+ ev.type = KeyPress;
+ if (im_xim_str2keycode(&ev.keycode, &ev.state) == OK)
+ XSendEvent(ev.display, ev.window, 1, KeyPressMask, (XEvent*)&ev);
+}
+
+/*
+ * Return TRUE if 'imactivatekey' has a valid value.
+ */
+ int
+im_xim_isvalid_imactivate()
+{
+ return im_xim_str2keycode(NULL, NULL) == OK;
+}
+#endif /* FEAT_GUI_GTK */
+
+/*
+ * Switch using XIM on/off. This is used by the code that changes "State".
+ */
+ void
+im_set_active(active)
+ int active;
+{
+ if (xic == NULL)
+ return;
+
+ /* If 'imdisable' is set, XIM is never active. */
+ if (p_imdisable)
+ active = FALSE;
+#ifndef FEAT_GUI_GTK
+ else if (input_style & XIMPreeditPosition)
+ /* There is a problem in switching XIM off when preediting is used,
+ * and it is not clear how this can be solved. For now, keep XIM on
+ * all the time, like it was done in Vim 5.8. */
+ active = TRUE;
+#endif
+
+ /* Remember the active state, it is needed when Vim gets keyboard focus. */
+ xim_is_active = active;
+
+#ifdef FEAT_GUI_GTK
+ /* When 'imactivatekey' has valid key-string, try to control XIM preedit
+ * state. When 'imactivatekey' has no or invalid string, try old XIM
+ * focus control.
+ */
+ if (*p_imak != NUL)
+ {
+ /* BASIC STRATEGY:
+ * Destroy old Input Context (XIC), and create new one. New XIC
+ * would have a state of preedit that is off. When argument:active
+ * is false, that's all. Else argument:active is true, send a key
+ * event specified by 'imactivatekey' to activate XIM preedit state.
+ */
+
+ xim_is_active = TRUE; /* Disable old XIM focus control */
+ /* If we can monitor preedit state with preedit callback functions,
+ * try least creation of new XIC.
+ */
+ if (xim_input_style & (int)GDK_IM_PREEDIT_CALLBACKS)
+ {
+ if (xim_can_preediting && !active)
+ {
+ /* Force turn off preedit state. With some IM
+ * implementations, we cannot turn off preedit state by
+ * symulate keypress event. It is why using such a method
+ * that destroy old IC (input context), and create new one.
+ * When create new IC, its preedit state is usually off.
+ */
+ xim_reset();
+ xim_set_focus(FALSE);
+ gdk_ic_destroy(xic);
+ xim_init();
+ xim_can_preediting = FALSE;
+ }
+ else if (!xim_can_preediting && active)
+ im_xim_send_event_imactivate();
+ }
+ else
+ {
+ /* First, force destroy old IC, and create new one. It
+ * symulates "turning off preedit state".
+ */
+ xim_set_focus(FALSE);
+ gdk_ic_destroy(xic);
+ xim_init();
+ xim_can_preediting = FALSE;
+
+ /* 2nd, when requested to activate IM, symulate this by sending
+ * the event.
+ */
+ if (active)
+ {
+ im_xim_send_event_imactivate();
+ xim_can_preediting = TRUE;
+ }
+ }
+ }
+ else
+ {
+# ifndef XIMPreeditUnKnown
+ /* X11R5 doesn't have these, it looks safe enough to define here. */
+ typedef unsigned long XIMPreeditState;
+# define XIMPreeditUnKnown 0L
+# define XIMPreeditEnable 1L
+# define XIMPreeditDisable (1L<<1)
+# define XNPreeditState "preeditState"
+# endif
+ XIMPreeditState preedit_state = XIMPreeditUnKnown;
+ XVaNestedList preedit_attr;
+ XIC pxic;
+
+ preedit_attr = XVaCreateNestedList(0,
+ XNPreeditState, &preedit_state,
+ NULL);
+ pxic = ((GdkICPrivate *)xic)->xic;
+
+ if (!XGetICValues(pxic, XNPreeditAttributes, preedit_attr, NULL))
+ {
+ XFree(preedit_attr);
+ preedit_attr = XVaCreateNestedList(0,
+ XNPreeditState,
+ active ? XIMPreeditEnable : XIMPreeditDisable,
+ NULL);
+ XSetICValues(pxic, XNPreeditAttributes, preedit_attr, NULL);
+ xim_can_preediting = active;
+ xim_is_active = active;
+ }
+ XFree(preedit_attr);
+ }
+ if (xim_input_style & XIMPreeditCallbacks)
+ {
+ preedit_buf_len = 0;
+ init_preedit_start_col();
+ }
+#else
+# if 0
+ /* When had tested kinput2 + canna + Athena GUI version with
+ * 'imactivatekey' is "s-space", im_xim_send_event_imactivate() did not
+ * work correctly. It just inserted one space. I don't know why we
+ * couldn't switch state of XIM preediting. This is reason why these
+ * codes are commented out.
+ */
+ /* First, force destroy old IC, and create new one. It symulates
+ * "turning off preedit state".
+ */
+ xim_set_focus(FALSE);
+ XDestroyIC(xic);
+ xic = NULL;
+ xim_init();
+
+ /* 2nd, when requested to activate IM, symulate this by sending the
+ * event.
+ */
+ if (active)
+ im_xim_send_event_imactivate();
+# endif
+#endif
+ xim_set_preedit();
+}
+
+/*
+ * Adjust using XIM for gaining or losing keyboard focus. Also called when
+ * "xim_is_active" changes.
+ */
+ void
+xim_set_focus(focus)
+ int focus;
+{
+ if (xic == NULL)
+ return;
+
+ /*
+ * XIM only gets focus when the Vim window has keyboard focus and XIM has
+ * been set active for the current mode.
+ */
+ if (focus && xim_is_active)
+ {
+ if (!xim_has_focus)
+ {
+ xim_has_focus = TRUE;
+#ifdef FEAT_GUI_GTK
+ gdk_im_begin(xic, gui.drawarea->window);
+#else
+ XSetICFocus(xic);
+#endif
+ }
+ }
+ else
+ {
+ if (xim_has_focus)
+ {
+ xim_has_focus = FALSE;
+#ifdef FEAT_GUI_GTK
+ gdk_im_end();
+#else
+ XUnsetICFocus(xic);
+#endif
+ }
+ }
+}
+
+/*ARGSUSED*/
+ void
+im_set_position(row, col)
+ int row;
+ int col;
+{
+ xim_set_preedit();
+}
+
+/*
+ * Set the XIM to the current cursor position.
+ */
+ void
+xim_set_preedit()
+{
+ if (xic == NULL)
+ return;
+
+ xim_set_focus(TRUE);
+
+#ifdef FEAT_GUI_GTK
+ if (gdk_im_ready())
+ {
+ int attrmask;
+ GdkICAttr *attr;
+
+ if (!xic_attr)
+ return;
+
+ attr = xic_attr;
+ attrmask = 0;
+
+# ifdef FEAT_XFONTSET
+ if ((xim_input_style & (int)GDK_IM_PREEDIT_POSITION)
+ && gui.fontset != NOFONTSET
+ && gui.fontset->type == GDK_FONT_FONTSET)
+ {
+ if (!xim_has_focus)
+ {
+ if (attr->spot_location.y >= 0)
+ {
+ attr->spot_location.x = 0;
+ attr->spot_location.y = -100;
+ attrmask |= (int)GDK_IC_SPOT_LOCATION;
+ }
+ }
+ else
+ {
+ gint width, height;
+
+ if (attr->spot_location.x != TEXT_X(gui.col)
+ || attr->spot_location.y != TEXT_Y(gui.row))
+ {
+ attr->spot_location.x = TEXT_X(gui.col);
+ attr->spot_location.y = TEXT_Y(gui.row);
+ attrmask |= (int)GDK_IC_SPOT_LOCATION;
+ }
+
+ gdk_window_get_size(gui.drawarea->window, &width, &height);
+ width -= 2 * gui.border_offset;
+ height -= 2 * gui.border_offset;
+ if (xim_input_style & (int)GDK_IM_STATUS_AREA)
+ height -= gui.char_height;
+ if (attr->preedit_area.width != width
+ || attr->preedit_area.height != height)
+ {
+ attr->preedit_area.x = gui.border_offset;
+ attr->preedit_area.y = gui.border_offset;
+ attr->preedit_area.width = width;
+ attr->preedit_area.height = height;
+ attrmask |= (int)GDK_IC_PREEDIT_AREA;
+ }
+
+ if (attr->preedit_fontset != gui.current_font)
+ {
+ attr->preedit_fontset = gui.current_font;
+ attrmask |= (int)GDK_IC_PREEDIT_FONTSET;
+ }
+ }
+ }
+# endif /* FEAT_XFONTSET */
+
+ if (xim_fg_color == INVALCOLOR)
+ {
+ xim_fg_color = gui.def_norm_pixel;
+ xim_bg_color = gui.def_back_pixel;
+ }
+ if (attr->preedit_foreground.pixel != xim_fg_color)
+ {
+ attr->preedit_foreground.pixel = xim_fg_color;
+ attrmask |= (int)GDK_IC_PREEDIT_FOREGROUND;
+ }
+ if (attr->preedit_background.pixel != xim_bg_color)
+ {
+ attr->preedit_background.pixel = xim_bg_color;
+ attrmask |= (int)GDK_IC_PREEDIT_BACKGROUND;
+ }
+
+ if (attrmask != 0)
+ gdk_ic_set_attr(xic, attr, (GdkICAttributesType)attrmask);
+ }
+#else /* FEAT_GUI_GTK */
+ {
+ XVaNestedList attr_list;
+ XRectangle spot_area;
+ XPoint over_spot;
+ int line_space;
+
+ if (!xim_has_focus)
+ {
+ /* hide XIM cursor */
+ over_spot.x = 0;
+ over_spot.y = -100; /* arbitrary invisible position */
+ attr_list = (XVaNestedList) XVaCreateNestedList(0,
+ XNSpotLocation,
+ &over_spot,
+ NULL);
+ XSetICValues(xic, XNPreeditAttributes, attr_list, NULL);
+ XFree(attr_list);
+ return;
+ }
+
+ if (input_style & XIMPreeditPosition)
+ {
+ if (xim_fg_color == INVALCOLOR)
+ {
+ xim_fg_color = gui.def_norm_pixel;
+ xim_bg_color = gui.def_back_pixel;
+ }
+ over_spot.x = TEXT_X(gui.col);
+ over_spot.y = TEXT_Y(gui.row);
+ spot_area.x = 0;
+ spot_area.y = 0;
+ spot_area.height = gui.char_height * Rows;
+ spot_area.width = gui.char_width * Columns;
+ line_space = gui.char_height;
+ attr_list = (XVaNestedList) XVaCreateNestedList(0,
+ XNSpotLocation, &over_spot,
+ XNForeground, (Pixel) xim_fg_color,
+ XNBackground, (Pixel) xim_bg_color,
+ XNArea, &spot_area,
+ XNLineSpace, line_space,
+ NULL);
+ if (XSetICValues(xic, XNPreeditAttributes, attr_list, NULL))
+ EMSG(_("E284: Cannot set IC values"));
+ XFree(attr_list);
+ }
+ }
+#endif /* FEAT_GUI_GTK */
+}
+
+/*
+ * Set up the status area.
+ *
+ * This should use a separate Widget, but that seems not possible, because
+ * preedit_area and status_area should be set to the same window as for the
+ * text input. Unfortunately this means the status area pollutes the text
+ * window...
+ */
+ void
+xim_set_status_area()
+{
+ if (xic == NULL)
+ return;
+
+#ifdef FEAT_GUI_GTK
+# if defined(FEAT_XFONTSET)
+ if (use_status_area)
+ {
+ GdkICAttr *attr;
+ int style;
+ gint width, height;
+ GtkWidget *widget;
+ int attrmask;
+
+ if (!xic_attr)
+ return;
+
+ attr = xic_attr;
+ attrmask = 0;
+ style = (int)gdk_ic_get_style(xic);
+ if ((style & (int)GDK_IM_STATUS_MASK) == (int)GDK_IM_STATUS_AREA)
+ {
+ if (gui.fontset != NOFONTSET
+ && gui.fontset->type == GDK_FONT_FONTSET)
+ {
+ widget = gui.mainwin;
+ gdk_window_get_size(widget->window, &width, &height);
+
+ attrmask |= (int)GDK_IC_STATUS_AREA;
+ attr->status_area.x = 0;
+ attr->status_area.y = height - gui.char_height - 1;
+ attr->status_area.width = width;
+ attr->status_area.height = gui.char_height;
+ }
+ }
+ if (attrmask != 0)
+ gdk_ic_set_attr(xic, attr, (GdkICAttributesType)attrmask);
+ }
+# endif
+#else
+ {
+ XVaNestedList preedit_list = 0, status_list = 0, list = 0;
+ XRectangle pre_area, status_area;
+
+ if (input_style & XIMStatusArea)
+ {
+ if (input_style & XIMPreeditArea)
+ {
+ XRectangle *needed_rect;
+
+ /* to get status_area width */
+ status_list = XVaCreateNestedList(0, XNAreaNeeded,
+ &needed_rect, NULL);
+ XGetICValues(xic, XNStatusAttributes, status_list, NULL);
+ XFree(status_list);
+
+ status_area.width = needed_rect->width;
+ }
+ else
+ status_area.width = gui.char_width * Columns;
+
+ status_area.x = 0;
+ status_area.y = gui.char_height * Rows + gui.border_offset;
+ if (gui.which_scrollbars[SBAR_BOTTOM])
+ status_area.y += gui.scrollbar_height;
+#ifdef FEAT_MENU
+ if (gui.menu_is_active)
+ status_area.y += gui.menu_height;
+#endif
+ status_area.height = gui.char_height;
+ status_list = XVaCreateNestedList(0, XNArea, &status_area, NULL);
+ }
+ else
+ {
+ status_area.x = 0;
+ status_area.y = gui.char_height * Rows + gui.border_offset;
+ if (gui.which_scrollbars[SBAR_BOTTOM])
+ status_area.y += gui.scrollbar_height;
+#ifdef FEAT_MENU
+ if (gui.menu_is_active)
+ status_area.y += gui.menu_height;
+#endif
+ status_area.width = 0;
+ status_area.height = gui.char_height;
+ }
+
+ if (input_style & XIMPreeditArea) /* off-the-spot */
+ {
+ pre_area.x = status_area.x + status_area.width;
+ pre_area.y = gui.char_height * Rows + gui.border_offset;
+ pre_area.width = gui.char_width * Columns - pre_area.x;
+ if (gui.which_scrollbars[SBAR_BOTTOM])
+ pre_area.y += gui.scrollbar_height;
+#ifdef FEAT_MENU
+ if (gui.menu_is_active)
+ pre_area.y += gui.menu_height;
+#endif
+ pre_area.height = gui.char_height;
+ preedit_list = XVaCreateNestedList(0, XNArea, &pre_area, NULL);
+ }
+ else if (input_style & XIMPreeditPosition) /* over-the-spot */
+ {
+ pre_area.x = 0;
+ pre_area.y = 0;
+ pre_area.height = gui.char_height * Rows;
+ pre_area.width = gui.char_width * Columns;
+ preedit_list = XVaCreateNestedList(0, XNArea, &pre_area, NULL);
+ }
+
+ if (preedit_list && status_list)
+ list = XVaCreateNestedList(0, XNPreeditAttributes, preedit_list,
+ XNStatusAttributes, status_list, NULL);
+ else if (preedit_list)
+ list = XVaCreateNestedList(0, XNPreeditAttributes, preedit_list,
+ NULL);
+ else if (status_list)
+ list = XVaCreateNestedList(0, XNStatusAttributes, status_list,
+ NULL);
+ else
+ list = NULL;
+
+ if (list)
+ {
+ XSetICValues(xic, XNVaNestedList, list, NULL);
+ XFree(list);
+ }
+ if (status_list)
+ XFree(status_list);
+ if (preedit_list)
+ XFree(preedit_list);
+ }
+#endif
+}
+
+#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
+static char e_xim[] = N_("E285: Failed to create input context");
+#endif
+
+#if defined(FEAT_GUI_X11) || defined(PROTO)
+# if defined(XtSpecificationRelease) && XtSpecificationRelease >= 6 && !defined(sun)
+# define USE_X11R6_XIM
+# endif
+
+static int xim_real_init __ARGS((Window x11_window, Display *x11_display));
+
+
+#ifdef USE_X11R6_XIM
+static void xim_instantiate_cb __ARGS((Display *display, XPointer client_data, XPointer call_data));
+static void xim_destroy_cb __ARGS((XIM im, XPointer client_data, XPointer call_data));
+
+/*ARGSUSED*/
+ static void
+xim_instantiate_cb(display, client_data, call_data)
+ Display *display;
+ XPointer client_data;
+ XPointer call_data;
+{
+ Window x11_window;
+ Display *x11_display;
+
+#ifdef XIM_DEBUG
+ xim_log("xim_instantiate_cb()\n");
+#endif
+
+ gui_get_x11_windis(&x11_window, &x11_display);
+ if (display != x11_display)
+ return;
+
+ xim_real_init(x11_window, x11_display);
+ gui_set_shellsize(FALSE, FALSE);
+ if (xic != NULL)
+ XUnregisterIMInstantiateCallback(x11_display, NULL, NULL, NULL,
+ xim_instantiate_cb, NULL);
+}
+
+/*ARGSUSED*/
+ static void
+xim_destroy_cb(im, client_data, call_data)
+ XIM im;
+ XPointer client_data;
+ XPointer call_data;
+{
+ Window x11_window;
+ Display *x11_display;
+
+#ifdef XIM_DEBUG
+ xim_log("xim_destroy_cb()\n");
+#endif
+ gui_get_x11_windis(&x11_window, &x11_display);
+
+ xic = NULL;
+ status_area_enabled = FALSE;
+
+ gui_set_shellsize(FALSE, FALSE);
+
+ XRegisterIMInstantiateCallback(x11_display, NULL, NULL, NULL,
+ xim_instantiate_cb, NULL);
+}
+#endif
+
+ void
+xim_init()
+{
+ Window x11_window;
+ Display *x11_display;
+
+#ifdef XIM_DEBUG
+ xim_log("xim_init()\n");
+#endif
+
+ gui_get_x11_windis(&x11_window, &x11_display);
+
+ xic = NULL;
+
+ if (xim_real_init(x11_window, x11_display))
+ return;
+
+ gui_set_shellsize(FALSE, FALSE);
+
+#ifdef USE_X11R6_XIM
+ XRegisterIMInstantiateCallback(x11_display, NULL, NULL, NULL,
+ xim_instantiate_cb, NULL);
+#endif
+}
+
+ static int
+xim_real_init(x11_window, x11_display)
+ Window x11_window;
+ Display *x11_display;
+{
+ int i;
+ char *p,
+ *s,
+ *ns,
+ *end,
+ tmp[1024];
+#define IMLEN_MAX 40
+ char buf[IMLEN_MAX + 7];
+ XIM xim = NULL;
+ XIMStyles *xim_styles;
+ XIMStyle this_input_style = 0;
+ Boolean found;
+ XPoint over_spot;
+ XVaNestedList preedit_list, status_list;
+
+ input_style = 0;
+ status_area_enabled = FALSE;
+
+ if (xic != NULL)
+ return FALSE;
+
+ if (gui.rsrc_input_method != NULL && *gui.rsrc_input_method != NUL)
+ {
+ strcpy(tmp, gui.rsrc_input_method);
+ for (ns = s = tmp; ns != NULL && *s != NUL;)
+ {
+ s = (char *)skipwhite((char_u *)s);
+ if (*s == NUL)
+ break;
+ if ((ns = end = strchr(s, ',')) == NULL)
+ end = s + strlen(s);
+ while (isspace(((char_u *)end)[-1]))
+ end--;
+ *end = NUL;
+
+ if (strlen(s) <= IMLEN_MAX)
+ {
+ strcpy(buf, "@im=");
+ strcat(buf, s);
+ if ((p = XSetLocaleModifiers(buf)) != NULL && *p != NUL
+ && (xim = XOpenIM(x11_display, NULL, NULL, NULL))
+ != NULL)
+ break;
+ }
+
+ s = ns + 1;
+ }
+ }
+
+ if (xim == NULL && (p = XSetLocaleModifiers("")) != NULL && *p != NUL)
+ xim = XOpenIM(x11_display, NULL, NULL, NULL);
+
+ /* This is supposed to be useful to obtain characters through
+ * XmbLookupString() without really using a XIM. */
+ if (xim == NULL && (p = XSetLocaleModifiers("@im=none")) != NULL
+ && *p != NUL)
+ xim = XOpenIM(x11_display, NULL, NULL, NULL);
+
+ if (xim == NULL)
+ {
+ /* Only give this message when verbose is set, because too many people
+ * got this message when they didn't want to use a XIM. */
+ if (p_verbose > 0)
+ EMSG(_("E286: Failed to open input method"));
+ return FALSE;
+ }
+
+#ifdef USE_X11R6_XIM
+ {
+ XIMCallback destroy_cb;
+
+ destroy_cb.callback = xim_destroy_cb;
+ destroy_cb.client_data = NULL;
+ if (XSetIMValues(xim, XNDestroyCallback, &destroy_cb, NULL))
+ EMSG(_("E287: Warning: Could not set destroy callback to IM"));
+ }
+#endif
+
+ if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) || !xim_styles)
+ {
+ EMSG(_("E288: input method doesn't support any style"));
+ XCloseIM(xim);
+ return FALSE;
+ }
+
+ found = False;
+ strcpy(tmp, gui.rsrc_preedit_type_name);
+ for (s = tmp; s && !found; )
+ {
+ while (*s && isspace((unsigned char)*s))
+ s++;
+ if (!*s)
+ break;
+ if ((ns = end = strchr(s, ',')) != 0)
+ ns++;
+ else
+ end = s + strlen(s);
+ while (isspace((unsigned char)*end))
+ end--;
+ *end = '\0';
+
+ if (!strcmp(s, "OverTheSpot"))
+ this_input_style = (XIMPreeditPosition | XIMStatusArea);
+ else if (!strcmp(s, "OffTheSpot"))
+ this_input_style = (XIMPreeditArea | XIMStatusArea);
+ else if (!strcmp(s, "Root"))
+ this_input_style = (XIMPreeditNothing | XIMStatusNothing);
+
+ for (i = 0; (unsigned short)i < xim_styles->count_styles; i++)
+ {
+ if (this_input_style == xim_styles->supported_styles[i])
+ {
+ found = True;
+ break;
+ }
+ }
+ if (!found)
+ for (i = 0; (unsigned short)i < xim_styles->count_styles; i++)
+ {
+ if ((xim_styles->supported_styles[i] & this_input_style)
+ == (this_input_style & ~XIMStatusArea))
+ {
+ this_input_style &= ~XIMStatusArea;
+ found = True;
+ break;
+ }
+ }
+
+ s = ns;
+ }
+ XFree(xim_styles);
+
+ if (!found)
+ {
+ /* Only give this message when verbose is set, because too many people
+ * got this message when they didn't want to use a XIM. */
+ if (p_verbose > 0)
+ EMSG(_("E289: input method doesn't support my preedit type"));
+ XCloseIM(xim);
+ return FALSE;
+ }
+
+ over_spot.x = TEXT_X(gui.col);
+ over_spot.y = TEXT_Y(gui.row);
+ input_style = this_input_style;
+
+ /* A crash was reported when trying to pass gui.norm_font as XNFontSet,
+ * thus that has been removed. Hopefully the default works... */
+#ifdef FEAT_XFONTSET
+ if (gui.fontset != NOFONTSET)
+ {
+ preedit_list = XVaCreateNestedList(0,
+ XNSpotLocation, &over_spot,
+ XNForeground, (Pixel)gui.def_norm_pixel,
+ XNBackground, (Pixel)gui.def_back_pixel,
+ XNFontSet, (XFontSet)gui.fontset,
+ NULL);
+ status_list = XVaCreateNestedList(0,
+ XNForeground, (Pixel)gui.def_norm_pixel,
+ XNBackground, (Pixel)gui.def_back_pixel,
+ XNFontSet, (XFontSet)gui.fontset,
+ NULL);
+ }
+ else
+#endif
+ {
+ preedit_list = XVaCreateNestedList(0,
+ XNSpotLocation, &over_spot,
+ XNForeground, (Pixel)gui.def_norm_pixel,
+ XNBackground, (Pixel)gui.def_back_pixel,
+ NULL);
+ status_list = XVaCreateNestedList(0,
+ XNForeground, (Pixel)gui.def_norm_pixel,
+ XNBackground, (Pixel)gui.def_back_pixel,
+ NULL);
+ }
+
+ xic = XCreateIC(xim,
+ XNInputStyle, input_style,
+ XNClientWindow, x11_window,
+ XNFocusWindow, gui.wid,
+ XNPreeditAttributes, preedit_list,
+ XNStatusAttributes, status_list,
+ NULL);
+ XFree(status_list);
+ XFree(preedit_list);
+ if (xic != NULL)
+ {
+ if (input_style & XIMStatusArea)
+ {
+ xim_set_status_area();
+ status_area_enabled = TRUE;
+ }
+ else
+ gui_set_shellsize(FALSE, FALSE);
+ }
+ else
+ {
+ EMSG(_(e_xim));
+ XCloseIM(xim);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#endif /* FEAT_GUI_X11 */
+
+#if defined(FEAT_GUI_GTK) || defined(PROTO)
+
+# ifdef FEAT_XFONTSET
+static char e_overthespot[] = N_("E290: over-the-spot style requires fontset");
+# endif
+
+# ifdef PROTO
+typedef int GdkIC;
+# endif
+
+ void
+xim_decide_input_style()
+{
+ /* GDK_IM_STATUS_CALLBACKS was disabled, enabled it to allow Japanese
+ * OverTheSpot. */
+ int supported_style = (int)GDK_IM_PREEDIT_NONE |
+ (int)GDK_IM_PREEDIT_NOTHING |
+ (int)GDK_IM_PREEDIT_POSITION |
+ (int)GDK_IM_PREEDIT_CALLBACKS |
+ (int)GDK_IM_STATUS_CALLBACKS |
+ (int)GDK_IM_STATUS_AREA |
+ (int)GDK_IM_STATUS_NONE |
+ (int)GDK_IM_STATUS_NOTHING;
+
+#ifdef XIM_DEBUG
+ xim_log("xim_decide_input_style()\n");
+#endif
+
+ if (!gdk_im_ready())
+ xim_input_style = 0;
+ else
+ {
+ if (gtk_major_version > 1
+ || (gtk_major_version == 1
+ && (gtk_minor_version > 2
+ || (gtk_minor_version == 2 && gtk_micro_version >= 3))))
+ use_status_area = TRUE;
+ else
+ {
+ EMSG(_("E291: Your GTK+ is older than 1.2.3. Status area disabled"));
+ use_status_area = FALSE;
+ }
+#ifdef FEAT_XFONTSET
+ if (gui.fontset == NOFONTSET || gui.fontset->type != GDK_FONT_FONTSET)
+#endif
+ supported_style &= ~((int)GDK_IM_PREEDIT_POSITION
+ | (int)GDK_IM_STATUS_AREA);
+ if (!use_status_area)
+ supported_style &= ~(int)GDK_IM_STATUS_AREA;
+ xim_input_style = (int)gdk_im_decide_style((GdkIMStyle)supported_style);
+ }
+}
+
+/*ARGSUSED*/
+ static void
+preedit_start_cbproc(XIC xic, XPointer client_data, XPointer call_data)
+{
+#ifdef XIM_DEBUG
+ xim_log("xim_decide_input_style()\n");
+#endif
+
+ draw_feedback = NULL;
+ xim_can_preediting = TRUE;
+ xim_has_preediting = TRUE;
+ gui_update_cursor(TRUE, FALSE);
+ if (showmode() > 0)
+ {
+ setcursor();
+ out_flush();
+ }
+}
+
+ static void
+xim_back_delete(int n)
+{
+ char_u str[3];
+
+ str[0] = CSI;
+ str[1] = 'k';
+ str[2] = 'b';
+ while (n-- > 0)
+ add_to_input_buf(str, 3);
+}
+
+static GSList *key_press_event_queue = NULL;
+static gboolean processing_queued_event = FALSE;
+
+/*ARGSUSED*/
+ static void
+preedit_draw_cbproc(XIC xic, XPointer client_data, XPointer call_data)
+{
+ XIMPreeditDrawCallbackStruct *draw_data;
+ XIMText *text;
+ char *src;
+ GSList *event_queue;
+
+#ifdef XIM_DEBUG
+ xim_log("preedit_draw_cbproc()\n");
+#endif
+
+ draw_data = (XIMPreeditDrawCallbackStruct *) call_data;
+ text = (XIMText *) draw_data->text;
+
+ if ((text == NULL && draw_data->chg_length == preedit_buf_len)
+ || preedit_buf_len == 0)
+ {
+ init_preedit_start_col();
+ vim_free(draw_feedback);
+ draw_feedback = NULL;
+ }
+ if (draw_data->chg_length > 0)
+ {
+ int bs_cnt;
+
+ if (draw_data->chg_length > preedit_buf_len)
+ bs_cnt = preedit_buf_len;
+ else
+ bs_cnt = draw_data->chg_length;
+ xim_back_delete(bs_cnt);
+ preedit_buf_len -= bs_cnt;
+ }
+ if (text != NULL)
+ {
+ int len;
+#ifdef FEAT_MBYTE
+ char_u *buf = NULL;
+ unsigned int nfeedback = 0;
+#endif
+ char_u *ptr;
+
+ src = text->string.multi_byte;
+ if (src != NULL && !text->encoding_is_wchar)
+ {
+ len = strlen(src);
+ ptr = (char_u *)src;
+ /* Avoid the enter for decision */
+ if (*ptr == '\n')
+ return;
+
+#ifdef FEAT_MBYTE
+ if (input_conv.vc_type != CONV_NONE
+ && (buf = string_convert(&input_conv,
+ (char_u *)src, &len)) != NULL)
+ {
+ /* Converted from 'termencoding' to 'encoding'. */
+ add_to_input_buf_csi(buf, len);
+ ptr = buf;
+ }
+ else
+#endif
+ add_to_input_buf_csi((char_u *)src, len);
+ /* Add count of character to preedit_buf_len */
+ while (*ptr != NUL)
+ {
+#ifdef FEAT_MBYTE
+ if (draw_data->text->feedback != NULL)
+ {
+ if (draw_feedback == NULL)
+ draw_feedback = (char *)alloc(draw_data->chg_first
+ + text->length);
+ else
+ draw_feedback = realloc(draw_feedback,
+ draw_data->chg_first + text->length);
+ if (draw_feedback != NULL)
+ {
+ draw_feedback[nfeedback + draw_data->chg_first]
+ = draw_data->text->feedback[nfeedback];
+ nfeedback++;
+ }
+ }
+ if (has_mbyte)
+ ptr += mb_ptr2len_check(ptr);
+ else
+#endif
+ ptr++;
+ preedit_buf_len++;
+ }
+#ifdef FEAT_MBYTE
+ vim_free(buf);
+#endif
+ preedit_end_col = MAXCOL;
+ }
+ }
+ if (text != NULL || draw_data->chg_length > 0)
+ {
+ event_queue = key_press_event_queue;
+ processing_queued_event = TRUE;
+ while (event_queue != NULL && processing_queued_event)
+ {
+ GdkEvent *ev = event_queue->data;
+
+ gboolean *ret;
+ gtk_signal_emit_by_name((GtkObject*)gui.mainwin, "key_press_event",
+ ev, &ret);
+ gdk_event_free(ev);
+ event_queue = event_queue->next;
+ }
+ processing_queued_event = FALSE;
+ if (key_press_event_queue)
+ {
+ g_slist_free(key_press_event_queue);
+ key_press_event_queue = NULL;
+ }
+ }
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+}
+
+/*
+ * Retrieve the highlighting attributes at column col in the preedit string.
+ * Return -1 if not in preediting mode or if col is out of range.
+ */
+ int
+im_get_feedback_attr(int col)
+{
+ if (draw_feedback != NULL && col < preedit_buf_len)
+ {
+ if (draw_feedback[col] & XIMReverse)
+ return HL_INVERSE;
+ else if (draw_feedback[col] & XIMUnderline)
+ return HL_UNDERLINE;
+ else
+ return hl_attr(HLF_V);
+ }
+
+ return -1;
+}
+
+/*ARGSUSED*/
+ static void
+preedit_caret_cbproc(XIC xic, XPointer client_data, XPointer call_data)
+{
+#ifdef XIM_DEBUG
+ xim_log("preedit_caret_cbproc()\n");
+#endif
+}
+
+/*ARGSUSED*/
+ static void
+preedit_done_cbproc(XIC xic, XPointer client_data, XPointer call_data)
+{
+#ifdef XIM_DEBUG
+ xim_log("preedit_done_cbproc()\n");
+#endif
+
+ vim_free(draw_feedback);
+ draw_feedback = NULL;
+ xim_can_preediting = FALSE;
+ xim_has_preediting = FALSE;
+ gui_update_cursor(TRUE, FALSE);
+ if (showmode() > 0)
+ {
+ setcursor();
+ out_flush();
+ }
+}
+
+ void
+xim_reset(void)
+{
+ char *text;
+
+#ifdef XIM_DEBUG
+ xim_log("xim_reset()\n");
+#endif
+
+ if (xic != NULL)
+ {
+ text = XmbResetIC(((GdkICPrivate *)xic)->xic);
+ if (text != NULL && !(xim_input_style & (int)GDK_IM_PREEDIT_CALLBACKS))
+ add_to_input_buf_csi((char_u *)text, strlen(text));
+ else
+ preedit_buf_len = 0;
+ if (text != NULL)
+ XFree(text);
+ }
+}
+
+/*ARGSUSED*/
+ int
+xim_queue_key_press_event(GdkEventKey *event, int down)
+{
+#ifdef XIM_DEBUG
+ xim_log("xim_queue_key_press_event()\n");
+#endif
+
+ if (preedit_buf_len <= 0)
+ return FALSE;
+ if (processing_queued_event)
+ processing_queued_event = FALSE;
+
+ key_press_event_queue = g_slist_append(key_press_event_queue,
+ gdk_event_copy((GdkEvent *)event));
+ return TRUE;
+}
+
+/*ARGSUSED*/
+ static void
+preedit_callback_setup(GdkIC *ic)
+{
+ XIC xxic;
+ XVaNestedList preedit_attr;
+ XIMCallback preedit_start_cb;
+ XIMCallback preedit_draw_cb;
+ XIMCallback preedit_caret_cb;
+ XIMCallback preedit_done_cb;
+
+ xxic = ((GdkICPrivate*)xic)->xic;
+ preedit_start_cb.callback = (XIMProc)preedit_start_cbproc;
+ preedit_draw_cb.callback = (XIMProc)preedit_draw_cbproc;
+ preedit_caret_cb.callback = (XIMProc)preedit_caret_cbproc;
+ preedit_done_cb.callback = (XIMProc)preedit_done_cbproc;
+ preedit_attr
+ = XVaCreateNestedList (0,
+ XNPreeditStartCallback, &preedit_start_cb,
+ XNPreeditDrawCallback, &preedit_draw_cb,
+ XNPreeditCaretCallback, &preedit_caret_cb,
+ XNPreeditDoneCallback, &preedit_done_cb,
+ 0);
+ XSetICValues (xxic, XNPreeditAttributes, preedit_attr, 0);
+ XFree(preedit_attr);
+}
+
+/*ARGSUSED*/
+ static void
+reset_state_setup(GdkIC *ic)
+{
+#ifdef USE_X11R6_XIM
+ /* don't change the input context when we call reset */
+ XSetICValues(((GdkICPrivate*)ic)->xic, XNResetState, XIMPreserveState, 0);
+#endif
+}
+
+ void
+xim_init(void)
+{
+#ifdef XIM_DEBUG
+ xim_log("xim_init()\n");
+#endif
+
+ xic = NULL;
+ xic_attr = NULL;
+
+ if (!gdk_im_ready())
+ {
+ if (p_verbose > 0)
+ EMSG(_("E292: Input Method Server is not running"));
+ return;
+ }
+ if ((xic_attr = gdk_ic_attr_new()) != NULL)
+ {
+#ifdef FEAT_XFONTSET
+ gint width, height;
+#endif
+ int mask;
+ GdkColormap *colormap;
+ GdkICAttr *attr = xic_attr;
+ int attrmask = (int)GDK_IC_ALL_REQ;
+ GtkWidget *widget = gui.drawarea;
+
+ attr->style = (GdkIMStyle)xim_input_style;
+ attr->client_window = gui.mainwin->window;
+
+ if ((colormap = gtk_widget_get_colormap(widget)) !=
+ gtk_widget_get_default_colormap())
+ {
+ attrmask |= (int)GDK_IC_PREEDIT_COLORMAP;
+ attr->preedit_colormap = colormap;
+ }
+ attrmask |= (int)GDK_IC_PREEDIT_FOREGROUND;
+ attrmask |= (int)GDK_IC_PREEDIT_BACKGROUND;
+ attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL];
+ attr->preedit_background = widget->style->base[GTK_STATE_NORMAL];
+
+#ifdef FEAT_XFONTSET
+ if ((xim_input_style & (int)GDK_IM_PREEDIT_MASK)
+ == (int)GDK_IM_PREEDIT_POSITION)
+ {
+ if (gui.fontset == NOFONTSET
+ || gui.fontset->type != GDK_FONT_FONTSET)
+ {
+ EMSG(_(e_overthespot));
+ }
+ else
+ {
+ gdk_window_get_size(widget->window, &width, &height);
+
+ attrmask |= (int)GDK_IC_PREEDIT_POSITION_REQ;
+ attr->spot_location.x = TEXT_X(0);
+ attr->spot_location.y = TEXT_Y(0);
+ attr->preedit_area.x = gui.border_offset;
+ attr->preedit_area.y = gui.border_offset;
+ attr->preedit_area.width = width - 2*gui.border_offset;
+ attr->preedit_area.height = height - 2*gui.border_offset;
+ attr->preedit_fontset = gui.fontset;
+ }
+ }
+
+ if ((xim_input_style & (int)GDK_IM_STATUS_MASK)
+ == (int)GDK_IM_STATUS_AREA)
+ {
+ if (gui.fontset == NOFONTSET
+ || gui.fontset->type != GDK_FONT_FONTSET)
+ {
+ EMSG(_(e_overthespot));
+ }
+ else
+ {
+ gdk_window_get_size(gui.mainwin->window, &width, &height);
+ attrmask |= (int)GDK_IC_STATUS_AREA_REQ;
+ attr->status_area.x = 0;
+ attr->status_area.y = height - gui.char_height - 1;
+ attr->status_area.width = width;
+ attr->status_area.height = gui.char_height;
+ attr->status_fontset = gui.fontset;
+ }
+ }
+ else if ((xim_input_style & (int)GDK_IM_STATUS_MASK)
+ == (int)GDK_IM_STATUS_CALLBACKS)
+ {
+ /* FIXME */
+ }
+#endif
+
+ xic = gdk_ic_new(attr, (GdkICAttributesType)attrmask);
+
+ if (xic == NULL)
+ EMSG(_(e_xim));
+ else
+ {
+ mask = (int)gdk_window_get_events(widget->window);
+ mask |= (int)gdk_ic_get_events(xic);
+ gdk_window_set_events(widget->window, (GdkEventMask)mask);
+ if (xim_input_style & (int)GDK_IM_PREEDIT_CALLBACKS)
+ preedit_callback_setup(xic);
+ reset_state_setup(xic);
+ }
+ }
+}
+
+ void
+im_shutdown(void)
+{
+#ifdef XIM_DEBUG
+ xim_log("im_shutdown()\n");
+#endif
+
+ if (xic != NULL)
+ {
+ gdk_im_end();
+ gdk_ic_destroy(xic);
+ xic = NULL;
+ }
+ xim_is_active = FALSE;
+ xim_can_preediting = FALSE;
+ preedit_start_col = MAXCOL;
+ xim_has_preediting = FALSE;
+}
+
+#endif /* FEAT_GUI_GTK */
+
+ int
+xim_get_status_area_height()
+{
+#ifdef FEAT_GUI_GTK
+ if (xim_input_style & (int)GDK_IM_STATUS_AREA)
+ return gui.char_height;
+#else
+ if (status_area_enabled)
+ return gui.char_height;
+#endif
+ return 0;
+}
+
+/*
+ * Get IM status. When IM is on, return TRUE. Else return FALSE.
+ * FIXME: This doesn't work correctly: Having focus doesn't always mean XIM is
+ * active, when not having focus XIM may still be active (e.g., when using a
+ * tear-off menu item).
+ */
+ int
+im_get_status()
+{
+# ifdef FEAT_GUI_GTK
+ if (xim_input_style & (int)GDK_IM_PREEDIT_CALLBACKS)
+ return xim_can_preediting;
+# endif
+ return xim_has_focus;
+}
+
+# endif /* !HAVE_GTK2 */
+
+# if defined(FEAT_GUI_GTK) || defined(PROTO)
+ int
+im_is_preediting()
+{
+ return xim_has_preediting;
+}
+# endif
+#endif /* FEAT_XIM */
+
+#if defined(FEAT_MBYTE) || defined(PROTO)
+
+/*
+ * Setup "vcp" for conversion from "from" to "to".
+ * The names must have been made canonical with enc_canonize().
+ * vcp->vc_type must have been initialized to CONV_NONE.
+ * Note: cannot be used for conversion from/to ucs-2 and ucs-4 (will use utf-8
+ * instead).
+ * Afterwards invoke with "from" and "to" equal to NULL to cleanup.
+ * Return FAIL when conversion is not supported, OK otherwise.
+ */
+ int
+convert_setup(vcp, from, to)
+ vimconv_T *vcp;
+ char_u *from;
+ char_u *to;
+{
+ int from_prop;
+ int to_prop;
+
+ /* Reset to no conversion. */
+# ifdef USE_ICONV
+ if (vcp->vc_type == CONV_ICONV && vcp->vc_fd != (iconv_t)-1)
+ iconv_close(vcp->vc_fd);
+# endif
+ vcp->vc_type = CONV_NONE;
+ vcp->vc_factor = 1;
+ vcp->vc_fail = FALSE;
+
+ /* No conversion when one of the names is empty or they are equal. */
+ if (from == NULL || *from == NUL || to == NULL || *to == NUL
+ || STRCMP(from, to) == 0)
+ return OK;
+
+ from_prop = enc_canon_props(from);
+ to_prop = enc_canon_props(to);
+ if ((from_prop & ENC_LATIN1) && (to_prop & ENC_UNICODE))
+ {
+ /* Internal latin1 -> utf-8 conversion. */
+ vcp->vc_type = CONV_TO_UTF8;
+ vcp->vc_factor = 2; /* up to twice as long */
+ }
+ else if ((from_prop & ENC_UNICODE) && (to_prop & ENC_LATIN1))
+ {
+ /* Internal utf-8 -> latin1 conversion. */
+ vcp->vc_type = CONV_TO_LATIN1;
+ }
+#ifdef WIN3264
+ /* Win32-specific codepage <-> codepage conversion without iconv. */
+ else if (((from_prop & ENC_UNICODE) || encname2codepage(from) > 0)
+ && ((to_prop & ENC_UNICODE) || encname2codepage(to) > 0))
+ {
+ vcp->vc_type = CONV_CODEPAGE;
+ vcp->vc_factor = 2; /* up to twice as long */
+ vcp->vc_cpfrom = (from_prop & ENC_UNICODE) ? 0 : encname2codepage(from);
+ vcp->vc_cpto = (to_prop & ENC_UNICODE) ? 0 : encname2codepage(to);
+ }
+#endif
+#ifdef MACOS_X
+ else if ((from_prop & ENC_MACROMAN) && (to_prop & ENC_LATIN1))
+ {
+ vcp->vc_type = CONV_MAC_LATIN1;
+ }
+ else if ((from_prop & ENC_MACROMAN) && (to_prop & ENC_UNICODE))
+ {
+ vcp->vc_type = CONV_MAC_UTF8;
+ vcp->vc_factor = 2; /* up to twice as long */
+ }
+ else if ((from_prop & ENC_LATIN1) && (to_prop & ENC_MACROMAN))
+ {
+ vcp->vc_type = CONV_LATIN1_MAC;
+ }
+ else if ((from_prop & ENC_UNICODE) && (to_prop & ENC_MACROMAN))
+ {
+ vcp->vc_type = CONV_UTF8_MAC;
+ }
+#endif
+# ifdef USE_ICONV
+ else
+ {
+ /* Use iconv() for conversion. */
+ vcp->vc_fd = (iconv_t)my_iconv_open(
+ (to_prop & ENC_UNICODE) ? (char_u *)"utf-8" : to,
+ (from_prop & ENC_UNICODE) ? (char_u *)"utf-8" : from);
+ if (vcp->vc_fd != (iconv_t)-1)
+ {
+ vcp->vc_type = CONV_ICONV;
+ vcp->vc_factor = 4; /* could be longer too... */
+ }
+ }
+# endif
+ if (vcp->vc_type == CONV_NONE)
+ return FAIL;
+ return OK;
+}
+
+#if defined(FEAT_GUI) || defined(AMIGA) || defined(WIN3264) \
+ || defined(MSDOS) || defined(PROTO)
+/*
+ * Do conversion on typed input characters in-place.
+ * The input and output are not NUL terminated!
+ * Returns the length after conversion.
+ */
+ int
+convert_input(ptr, len, maxlen)
+ char_u *ptr;
+ int len;
+ int maxlen;
+{
+ return convert_input_safe(ptr, len, maxlen, NULL, NULL);
+}
+#endif
+
+/*
+ * Like convert_input(), but when there is an incomplete byte sequence at the
+ * end return that as an allocated string in "restp" and set "*restlenp" to
+ * the length. If "restp" is NULL it is not used.
+ */
+ int
+convert_input_safe(ptr, len, maxlen, restp, restlenp)
+ char_u *ptr;
+ int len;
+ int maxlen;
+ char_u **restp;
+ int *restlenp;
+{
+ char_u *d;
+ int dlen = len;
+ int unconvertlen = 0;
+
+ d = string_convert_ext(&input_conv, ptr, &dlen,
+ restp == NULL ? NULL : &unconvertlen);
+ if (d != NULL)
+ {
+ if (dlen <= maxlen)
+ {
+ if (unconvertlen > 0)
+ {
+ /* Move the unconverted characters to allocated memory. */
+ *restp = alloc(unconvertlen);
+ if (*restp != NULL)
+ mch_memmove(*restp, ptr + len - unconvertlen, unconvertlen);
+ *restlenp = unconvertlen;
+ }
+ mch_memmove(ptr, d, dlen);
+ }
+ else
+ /* result is too long, keep the unconverted text (the caller must
+ * have done something wrong!) */
+ dlen = len;
+ vim_free(d);
+ }
+ return dlen;
+}
+
+#if defined(MACOS_X)
+static char_u *mac_string_convert __ARGS((char_u *ptr, int len, int *lenp, int fail_on_error, CFStringEncoding from, CFStringEncoding to, int *unconvlenp));
+
+/*
+ * A Mac version of string_convert_ext() for special cases.
+ */
+ static char_u *
+mac_string_convert(ptr, len, lenp, fail_on_error, from, to, unconvlenp)
+ char_u *ptr;
+ int len;
+ int *lenp;
+ int fail_on_error;
+ CFStringEncoding from;
+ CFStringEncoding to;
+ int *unconvlenp;
+{
+ char_u *retval, *d;
+ CFStringRef cfstr;
+ int buflen, in, out, l, i;
+
+ if (unconvlenp != NULL)
+ *unconvlenp = 0;
+ cfstr = CFStringCreateWithBytes(NULL, ptr, len, from, 0);
+ /* When conversion failed, try excluding bytes from the end, helps when
+ * there is an incomplete byte sequence. Only do up to 6 bytes to avoid
+ * looping a long time when there really is something unconvertable. */
+ while (cfstr == NULL && unconvlenp != NULL && len > 1 && *unconvlenp < 6)
+ {
+ --len;
+ ++*unconvlenp;
+ cfstr = CFStringCreateWithBytes(NULL, ptr, len, from, 0);
+ }
+ if (cfstr == NULL)
+ return NULL;
+ if (to == kCFStringEncodingUTF8)
+ buflen = len * 6 + 1;
+ else
+ buflen = len + 1;
+ retval = alloc(buflen);
+ if (retval == NULL)
+ {
+ CFRelease(cfstr);
+ return NULL;
+ }
+ if (!CFStringGetCString(cfstr, retval, buflen, to))
+ {
+ CFRelease(cfstr);
+ if (fail_on_error)
+ {
+ vim_free(retval);
+ return NULL;
+ }
+
+ /* conversion failed for the whole string, but maybe it will work
+ * for each character */
+ for (d = retval, in = 0, out = 0; in < len && out < buflen - 1;)
+ {
+ if (from == kCFStringEncodingUTF8)
+ l = utf_ptr2len_check(ptr + in);
+ else
+ l = 1;
+ cfstr = CFStringCreateWithBytes(NULL, ptr + in, l, from, 0);
+ if (cfstr == NULL)
+ {
+ *d++ = '?';
+ out++;
+ }
+ else
+ {
+ if (!CFStringGetCString(cfstr, d, buflen - out, to))
+ {
+ *d++ = '?';
+ out++;
+ }
+ else
+ {
+ i = strlen(d);
+ d += i;
+ out += i;
+ }
+ CFRelease(cfstr);
+ }
+ in += l;
+ }
+ *d = NUL;
+ if (lenp != NULL)
+ *lenp = out;
+ return retval;
+ }
+ CFRelease(cfstr);
+ if (lenp != NULL)
+ *lenp = strlen(retval);
+ return retval;
+}
+#endif
+
+/*
+ * Convert text "ptr[*lenp]" according to "vcp".
+ * Returns the result in allocated memory and sets "*lenp".
+ * When "lenp" is NULL, use NUL terminated strings.
+ * Illegal chars are often changed to "?", unless vcp->vc_fail is set.
+ * When something goes wrong, NULL is returned and "*lenp" is unchanged.
+ */
+ char_u *
+string_convert(vcp, ptr, lenp)
+ vimconv_T *vcp;
+ char_u *ptr;
+ int *lenp;
+{
+ return string_convert_ext(vcp, ptr, lenp, NULL);
+}
+
+/*
+ * Like string_convert(), but when "unconvlenp" is not NULL and there are is
+ * an incomplete sequence at the end it is not converted and "*unconvlenp" is
+ * set to the number of remaining bytes.
+ */
+ char_u *
+string_convert_ext(vcp, ptr, lenp, unconvlenp)
+ vimconv_T *vcp;
+ char_u *ptr;
+ int *lenp;
+ int *unconvlenp;
+{
+ char_u *retval = NULL;
+ char_u *d;
+ int len;
+ int i;
+ int l;
+ int c;
+
+ if (lenp == NULL)
+ len = (int)STRLEN(ptr);
+ else
+ len = *lenp;
+ if (len == 0)
+ return vim_strsave((char_u *)"");
+
+ switch (vcp->vc_type)
+ {
+ case CONV_TO_UTF8: /* latin1 to utf-8 conversion */
+ retval = alloc(len * 2 + 1);
+ if (retval == NULL)
+ break;
+ d = retval;
+ for (i = 0; i < len; ++i)
+ {
+ if (ptr[i] < 0x80)
+ *d++ = ptr[i];
+ else
+ {
+ *d++ = 0xc0 + ((unsigned)ptr[i] >> 6);
+ *d++ = 0x80 + (ptr[i] & 0x3f);
+ }
+ }
+ *d = NUL;
+ if (lenp != NULL)
+ *lenp = (int)(d - retval);
+ break;
+
+ case CONV_TO_LATIN1: /* utf-8 to latin1 conversion */
+ retval = alloc(len + 1);
+ if (retval == NULL)
+ break;
+ d = retval;
+ for (i = 0; i < len; ++i)
+ {
+ l = utf_ptr2len_check(ptr + i);
+ if (l == 0)
+ *d++ = NUL;
+ else if (l == 1)
+ {
+ if (unconvlenp != NULL && utf8len_tab[ptr[i]] > len - i)
+ {
+ /* Incomplete sequence at the end. */
+ *unconvlenp = len - i;
+ break;
+ }
+ *d++ = ptr[i];
+ }
+ else
+ {
+ c = utf_ptr2char(ptr + i);
+ if (!utf_iscomposing(c)) /* skip composing chars */
+ {
+ if (c < 0x100)
+ *d++ = c;
+ else if (vcp->vc_fail)
+ {
+ vim_free(retval);
+ return NULL;
+ }
+ else
+ {
+ *d++ = 0xbf;
+ if (utf_char2cells(c) > 1)
+ *d++ = '?';
+ }
+ }
+ i += l - 1;
+ }
+ }
+ *d = NUL;
+ if (lenp != NULL)
+ *lenp = (int)(d - retval);
+ break;
+
+# ifdef MACOS_X
+ case CONV_MAC_LATIN1:
+ retval = mac_string_convert(ptr, len, lenp, vcp->vc_fail,
+ kCFStringEncodingMacRoman,
+ kCFStringEncodingISOLatin1,
+ unconvlenp);
+ break;
+
+ case CONV_LATIN1_MAC:
+ retval = mac_string_convert(ptr, len, lenp, vcp->vc_fail,
+ kCFStringEncodingISOLatin1,
+ kCFStringEncodingMacRoman,
+ unconvlenp);
+ break;
+
+ case CONV_MAC_UTF8:
+ retval = mac_string_convert(ptr, len, lenp, vcp->vc_fail,
+ kCFStringEncodingMacRoman,
+ kCFStringEncodingUTF8,
+ unconvlenp);
+ break;
+
+ case CONV_UTF8_MAC:
+ retval = mac_string_convert(ptr, len, lenp, vcp->vc_fail,
+ kCFStringEncodingUTF8,
+ kCFStringEncodingMacRoman,
+ unconvlenp);
+ break;
+# endif
+
+# ifdef USE_ICONV
+ case CONV_ICONV: /* conversion with output_conv.vc_fd */
+ retval = iconv_string(vcp, ptr, len, unconvlenp);
+ if (retval != NULL && lenp != NULL)
+ *lenp = (int)STRLEN(retval);
+ break;
+# endif
+# ifdef WIN3264
+ case CONV_CODEPAGE: /* codepage -> codepage */
+ {
+ int retlen;
+ int tmp_len;
+ short_u *tmp;
+
+ /* 1. codepage/UTF-8 -> ucs-2. */
+ if (vcp->vc_cpfrom == 0)
+ tmp_len = utf8_to_ucs2(ptr, len, NULL, NULL);
+ else
+ tmp_len = MultiByteToWideChar(vcp->vc_cpfrom, 0,
+ ptr, len, 0, 0);
+ tmp = (short_u *)alloc(sizeof(short_u) * tmp_len);
+ if (tmp == NULL)
+ break;
+ if (vcp->vc_cpfrom == 0)
+ utf8_to_ucs2(ptr, len, tmp, unconvlenp);
+ else
+ MultiByteToWideChar(vcp->vc_cpfrom, 0, ptr, len, tmp, tmp_len);
+
+ /* 2. ucs-2 -> codepage/UTF-8. */
+ if (vcp->vc_cpto == 0)
+ retlen = ucs2_to_utf8(tmp, tmp_len, NULL);
+ else
+ retlen = WideCharToMultiByte(vcp->vc_cpto, 0,
+ tmp, tmp_len, 0, 0, 0, 0);
+ retval = alloc(retlen + 1);
+ if (retval != NULL)
+ {
+ if (vcp->vc_cpto == 0)
+ ucs2_to_utf8(tmp, tmp_len, retval);
+ else
+ WideCharToMultiByte(vcp->vc_cpto, 0,
+ tmp, tmp_len, retval, retlen, 0, 0);
+ retval[retlen] = NUL;
+ if (lenp != NULL)
+ *lenp = retlen;
+ }
+ vim_free(tmp);
+ break;
+ }
+# endif
+ }
+
+ return retval;
+}
+#endif
diff --git a/src/memfile.c b/src/memfile.c
new file mode 100644
index 000000000..8c41832c2
--- /dev/null
+++ b/src/memfile.c
@@ -0,0 +1,1312 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * memfile.c: Contains the functions for handling blocks of memory which can
+ * be stored in a file. This is the implementation of a sort of virtual memory.
+ *
+ * A memfile consists of a sequence of blocks. The blocks numbered from 0
+ * upwards have been assigned a place in the actual file. The block number
+ * is equal to the page number in the file. The
+ * blocks with negative numbers are currently in memory only. They can be
+ * assigned a place in the file when too much memory is being used. At that
+ * moment they get a new, positive, number. A list is used for translation of
+ * negative to positive numbers.
+ *
+ * The size of a block is a multiple of a page size, normally the page size of
+ * the device the file is on. Most blocks are 1 page long. A Block of multiple
+ * pages is used for a line that does not fit in a single page.
+ *
+ * Each block can be in memory and/or in a file. The block stays in memory
+ * as long as it is locked. If it is no longer locked it can be swapped out to
+ * the file. It is only written to the file if it has been changed.
+ *
+ * Under normal operation the file is created when opening the memory file and
+ * deleted when closing the memory file. Only with recovery an existing memory
+ * file is opened.
+ */
+
+#if defined MSDOS || defined(WIN32) || defined(_WIN64)
+# include <io.h> /* for lseek(), must be before vim.h */
+#endif
+
+#include "vim.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+/*
+ * Some systems have the page size in statfs.f_bsize, some in stat.st_blksize
+ */
+#ifdef HAVE_ST_BLKSIZE
+# define STATFS stat
+# define F_BSIZE st_blksize
+# define fstatfs(fd, buf, len, nul) mch_fstat((fd), (buf))
+#else
+# ifdef HAVE_SYS_STATFS_H
+# include <sys/statfs.h>
+# define STATFS statfs
+# define F_BSIZE f_bsize
+# ifdef __MINT__ /* do we still need this? */
+# define fstatfs(fd, buf, len, nul) mch_fstat((fd), (buf))
+# endif
+# endif
+#endif
+
+/*
+ * for Amiga Dos 2.0x we use Flush
+ */
+#ifdef AMIGA
+# ifdef FEAT_ARP
+extern int dos2; /* this is in os_amiga.c */
+# endif
+# ifdef SASC
+# include <proto/dos.h>
+# include <ios1.h> /* for chkufb() */
+# endif
+#endif
+
+#define MEMFILE_PAGE_SIZE 4096 /* default page size */
+
+static long_u total_mem_used = 0; /* total memory used for memfiles */
+static int dont_release = FALSE; /* don't release blocks */
+
+static void mf_ins_hash __ARGS((memfile_T *, bhdr_T *));
+static void mf_rem_hash __ARGS((memfile_T *, bhdr_T *));
+static bhdr_T *mf_find_hash __ARGS((memfile_T *, blocknr_T));
+static void mf_ins_used __ARGS((memfile_T *, bhdr_T *));
+static void mf_rem_used __ARGS((memfile_T *, bhdr_T *));
+static bhdr_T *mf_release __ARGS((memfile_T *, int));
+static bhdr_T *mf_alloc_bhdr __ARGS((memfile_T *, int));
+static void mf_free_bhdr __ARGS((bhdr_T *));
+static void mf_ins_free __ARGS((memfile_T *, bhdr_T *));
+static bhdr_T *mf_rem_free __ARGS((memfile_T *));
+static int mf_read __ARGS((memfile_T *, bhdr_T *));
+static int mf_write __ARGS((memfile_T *, bhdr_T *));
+static int mf_trans_add __ARGS((memfile_T *, bhdr_T *));
+static void mf_do_open __ARGS((memfile_T *, char_u *, int));
+
+/*
+ * The functions for using a memfile:
+ *
+ * mf_open() open a new or existing memfile
+ * mf_open_file() open a swap file for an existing memfile
+ * mf_close() close (and delete) a memfile
+ * mf_new() create a new block in a memfile and lock it
+ * mf_get() get an existing block and lock it
+ * mf_put() unlock a block, may be marked for writing
+ * mf_free() remove a block
+ * mf_sync() sync changed parts of memfile to disk
+ * mf_release_all() release as much memory as possible
+ * mf_trans_del() may translate negative to positive block number
+ * mf_fullname() make file name full path (use before first :cd)
+ */
+
+/*
+ * Open an existing or new memory block file.
+ *
+ * fname: name of file to use (NULL means no file at all)
+ * Note: fname must have been allocated, it is not copied!
+ * If opening the file fails, fname is freed.
+ * flags: flags for open() call
+ *
+ * If fname != NULL and file cannot be opened, fail.
+ *
+ * return value: identifier for this memory block file.
+ */
+ memfile_T *
+mf_open(fname, flags)
+ char_u *fname;
+ int flags;
+{
+ memfile_T *mfp;
+ int i;
+ off_t size;
+#if defined(STATFS) && defined(UNIX) && !defined(__QNX__)
+# define USE_FSTATFS
+ struct STATFS stf;
+#endif
+
+ if ((mfp = (memfile_T *)alloc((unsigned)sizeof(memfile_T))) == NULL)
+ return NULL;
+
+ if (fname == NULL) /* no file for this memfile, use memory only */
+ {
+ mfp->mf_fname = NULL;
+ mfp->mf_ffname = NULL;
+ mfp->mf_fd = -1;
+ }
+ else
+ {
+ mf_do_open(mfp, fname, flags); /* try to open the file */
+
+ /* if the file cannot be opened, return here */
+ if (mfp->mf_fd < 0)
+ {
+ vim_free(mfp);
+ return NULL;
+ }
+ }
+
+ mfp->mf_free_first = NULL; /* free list is empty */
+ mfp->mf_used_first = NULL; /* used list is empty */
+ mfp->mf_used_last = NULL;
+ mfp->mf_dirty = FALSE;
+ mfp->mf_used_count = 0;
+ for (i = 0; i < MEMHASHSIZE; ++i)
+ {
+ mfp->mf_hash[i] = NULL; /* hash lists are empty */
+ mfp->mf_trans[i] = NULL; /* trans lists are empty */
+ }
+ mfp->mf_page_size = MEMFILE_PAGE_SIZE;
+
+#ifdef USE_FSTATFS
+ /*
+ * Try to set the page size equal to the block size of the device.
+ * Speeds up I/O a lot.
+ * When recovering, the actual block size will be retrieved from block 0
+ * in ml_recover(). The size used here may be wrong, therefore
+ * mf_blocknr_max must be rounded up.
+ */
+ if (mfp->mf_fd >= 0
+ && fstatfs(mfp->mf_fd, &stf, sizeof(struct statfs), 0) == 0
+ && stf.F_BSIZE >= MIN_SWAP_PAGE_SIZE
+ && stf.F_BSIZE <= MAX_SWAP_PAGE_SIZE)
+ mfp->mf_page_size = stf.F_BSIZE;
+#endif
+
+ if (mfp->mf_fd < 0 || (flags & (O_TRUNC|O_EXCL))
+ || (size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0)
+ mfp->mf_blocknr_max = 0; /* no file or empty file */
+ else
+ mfp->mf_blocknr_max = (blocknr_T)((size + mfp->mf_page_size - 1)
+ / mfp->mf_page_size);
+ mfp->mf_blocknr_min = -1;
+ mfp->mf_neg_count = 0;
+ mfp->mf_infile_count = mfp->mf_blocknr_max;
+ mfp->mf_used_count_max = p_mm * 1024 / mfp->mf_page_size;
+
+ return mfp;
+}
+
+/*
+ * Open a file for an existing memfile. Used when updatecount set from 0 to
+ * some value.
+ * If the file already exists, this fails.
+ * "fname" is the name of file to use (NULL means no file at all)
+ * Note: "fname" must have been allocated, it is not copied! If opening the
+ * file fails, "fname" is freed.
+ *
+ * return value: FAIL if file could not be opened, OK otherwise
+ */
+ int
+mf_open_file(mfp, fname)
+ memfile_T *mfp;
+ char_u *fname;
+{
+ mf_do_open(mfp, fname, O_RDWR|O_CREAT|O_EXCL); /* try to open the file */
+
+ if (mfp->mf_fd < 0)
+ return FAIL;
+
+ mfp->mf_dirty = TRUE;
+ return OK;
+}
+
+/*
+ * close a memory file and delete the associated file if 'del_file' is TRUE
+ */
+ void
+mf_close(mfp, del_file)
+ memfile_T *mfp;
+ int del_file;
+{
+ bhdr_T *hp, *nextp;
+ NR_TRANS *tp, *tpnext;
+ int i;
+
+ if (mfp == NULL) /* safety check */
+ return;
+ if (mfp->mf_fd >= 0)
+ {
+ if (close(mfp->mf_fd) < 0)
+ EMSG(_(e_swapclose));
+ }
+ if (del_file && mfp->mf_fname != NULL)
+ mch_remove(mfp->mf_fname);
+ /* free entries in used list */
+ for (hp = mfp->mf_used_first; hp != NULL; hp = nextp)
+ {
+ total_mem_used -= hp->bh_page_count * mfp->mf_page_size;
+ nextp = hp->bh_next;
+ mf_free_bhdr(hp);
+ }
+ while (mfp->mf_free_first != NULL) /* free entries in free list */
+ vim_free(mf_rem_free(mfp));
+ for (i = 0; i < MEMHASHSIZE; ++i) /* free entries in trans lists */
+ for (tp = mfp->mf_trans[i]; tp != NULL; tp = tpnext)
+ {
+ tpnext = tp->nt_next;
+ vim_free(tp);
+ }
+ vim_free(mfp->mf_fname);
+ vim_free(mfp->mf_ffname);
+ vim_free(mfp);
+}
+
+/*
+ * Close the swap file for a memfile. Used when 'swapfile' is reset.
+ */
+ void
+mf_close_file(buf, getlines)
+ buf_T *buf;
+ int getlines; /* get all lines into memory? */
+{
+ memfile_T *mfp;
+ linenr_T lnum;
+
+ mfp = buf->b_ml.ml_mfp;
+ if (mfp == NULL || mfp->mf_fd < 0) /* nothing to close */
+ return;
+
+ if (getlines)
+ {
+ /* get all blocks in memory by accessing all lines (clumsy!) */
+ dont_release = TRUE;
+ for (lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum)
+ (void)ml_get_buf(buf, lnum, FALSE);
+ dont_release = FALSE;
+ /* TODO: should check if all blocks are really in core */
+ }
+
+ if (close(mfp->mf_fd) < 0) /* close the file */
+ EMSG(_(e_swapclose));
+ mfp->mf_fd = -1;
+
+ if (mfp->mf_fname != NULL)
+ {
+ mch_remove(mfp->mf_fname); /* delete the swap file */
+ vim_free(mfp->mf_fname);
+ vim_free(mfp->mf_ffname);
+ mfp->mf_fname = NULL;
+ mfp->mf_ffname = NULL;
+ }
+}
+
+/*
+ * Set new size for a memfile. Used when block 0 of a swapfile has been read
+ * and the size it indicates differs from what was guessed.
+ */
+ void
+mf_new_page_size(mfp, new_size)
+ memfile_T *mfp;
+ unsigned new_size;
+{
+ /* Correct the memory used for block 0 to the new size, because it will be
+ * freed with that size later on. */
+ total_mem_used += new_size - mfp->mf_page_size;
+ mfp->mf_page_size = new_size;
+}
+
+/*
+ * get a new block
+ *
+ * negative: TRUE if negative block number desired (data block)
+ */
+ bhdr_T *
+mf_new(mfp, negative, page_count)
+ memfile_T *mfp;
+ int negative;
+ int page_count;
+{
+ bhdr_T *hp; /* new bhdr_T */
+ bhdr_T *freep; /* first block in free list */
+ char_u *p;
+
+ /*
+ * If we reached the maximum size for the used memory blocks, release one
+ * If a bhdr_T is returned, use it and adjust the page_count if necessary.
+ */
+ hp = mf_release(mfp, page_count);
+
+/*
+ * Decide on the number to use:
+ * If there is a free block, use its number.
+ * Otherwise use mf_block_min for a negative number, mf_block_max for
+ * a positive number.
+ */
+ freep = mfp->mf_free_first;
+ if (!negative && freep != NULL && freep->bh_page_count >= page_count)
+ {
+ /*
+ * If the block in the free list has more pages, take only the number
+ * of pages needed and allocate a new bhdr_T with data
+ *
+ * If the number of pages matches and mf_release did not return a bhdr_T,
+ * use the bhdr_T from the free list and allocate the data
+ *
+ * If the number of pages matches and mf_release returned a bhdr_T,
+ * just use the number and free the bhdr_T from the free list
+ */
+ if (freep->bh_page_count > page_count)
+ {
+ if (hp == NULL && (hp = mf_alloc_bhdr(mfp, page_count)) == NULL)
+ return NULL;
+ hp->bh_bnum = freep->bh_bnum;
+ freep->bh_bnum += page_count;
+ freep->bh_page_count -= page_count;
+ }
+ else if (hp == NULL) /* need to allocate memory for this block */
+ {
+ if ((p = (char_u *)alloc(mfp->mf_page_size * page_count)) == NULL)
+ return NULL;
+ hp = mf_rem_free(mfp);
+ hp->bh_data = p;
+ }
+ else /* use the number, remove entry from free list */
+ {
+ freep = mf_rem_free(mfp);
+ hp->bh_bnum = freep->bh_bnum;
+ vim_free(freep);
+ }
+ }
+ else /* get a new number */
+ {
+ if (hp == NULL && (hp = mf_alloc_bhdr(mfp, page_count)) == NULL)
+ return NULL;
+ if (negative)
+ {
+ hp->bh_bnum = mfp->mf_blocknr_min--;
+ mfp->mf_neg_count++;
+ }
+ else
+ {
+ hp->bh_bnum = mfp->mf_blocknr_max;
+ mfp->mf_blocknr_max += page_count;
+ }
+ }
+ hp->bh_flags = BH_LOCKED | BH_DIRTY; /* new block is always dirty */
+ mfp->mf_dirty = TRUE;
+ hp->bh_page_count = page_count;
+ mf_ins_used(mfp, hp);
+ mf_ins_hash(mfp, hp);
+
+ /*
+ * Init the data to all zero, to avoid reading uninitialized data.
+ * This also avoids that the passwd file ends up in the swap file!
+ */
+ (void)vim_memset((char *)(hp->bh_data), 0, (size_t)mfp->mf_page_size);
+
+ return hp;
+}
+
+/*
+ * get existing block 'nr' with 'page_count' pages
+ *
+ * Note: The caller should first check a negative nr with mf_trans_del()
+ */
+ bhdr_T *
+mf_get(mfp, nr, page_count)
+ memfile_T *mfp;
+ blocknr_T nr;
+ int page_count;
+{
+ bhdr_T *hp;
+ /* doesn't exist */
+ if (nr >= mfp->mf_blocknr_max || nr <= mfp->mf_blocknr_min)
+ return NULL;
+
+ /*
+ * see if it is in the cache
+ */
+ hp = mf_find_hash(mfp, nr);
+ if (hp == NULL) /* not in the hash list */
+ {
+ if (nr < 0 || nr >= mfp->mf_infile_count) /* can't be in the file */
+ return NULL;
+
+ /* could check here if the block is in the free list */
+
+ /*
+ * Check if we need to flush an existing block.
+ * If so, use that block.
+ * If not, allocate a new block.
+ */
+ hp = mf_release(mfp, page_count);
+ if (hp == NULL && (hp = mf_alloc_bhdr(mfp, page_count)) == NULL)
+ return NULL;
+
+ hp->bh_bnum = nr;
+ hp->bh_flags = 0;
+ hp->bh_page_count = page_count;
+ if (mf_read(mfp, hp) == FAIL) /* cannot read the block! */
+ {
+ mf_free_bhdr(hp);
+ return NULL;
+ }
+ }
+ else
+ {
+ mf_rem_used(mfp, hp); /* remove from list, insert in front below */
+ mf_rem_hash(mfp, hp);
+ }
+
+ hp->bh_flags |= BH_LOCKED;
+ mf_ins_used(mfp, hp); /* put in front of used list */
+ mf_ins_hash(mfp, hp); /* put in front of hash list */
+
+ return hp;
+}
+
+/*
+ * release the block *hp
+ *
+ * dirty: Block must be written to file later
+ * infile: Block should be in file (needed for recovery)
+ *
+ * no return value, function cannot fail
+ */
+ void
+mf_put(mfp, hp, dirty, infile)
+ memfile_T *mfp;
+ bhdr_T *hp;
+ int dirty;
+ int infile;
+{
+ int flags;
+
+ flags = hp->bh_flags;
+
+ if ((flags & BH_LOCKED) == 0)
+ EMSG(_("E293: block was not locked"));
+ flags &= ~BH_LOCKED;
+ if (dirty)
+ {
+ flags |= BH_DIRTY;
+ mfp->mf_dirty = TRUE;
+ }
+ hp->bh_flags = flags;
+ if (infile)
+ mf_trans_add(mfp, hp); /* may translate negative in positive nr */
+}
+
+/*
+ * block *hp is no longer in used, may put it in the free list of memfile *mfp
+ */
+ void
+mf_free(mfp, hp)
+ memfile_T *mfp;
+ bhdr_T *hp;
+{
+ vim_free(hp->bh_data); /* free the memory */
+ mf_rem_hash(mfp, hp); /* get *hp out of the hash list */
+ mf_rem_used(mfp, hp); /* get *hp out of the used list */
+ if (hp->bh_bnum < 0)
+ {
+ vim_free(hp); /* don't want negative numbers in free list */
+ mfp->mf_neg_count--;
+ }
+ else
+ mf_ins_free(mfp, hp); /* put *hp in the free list */
+}
+
+#if defined(__MORPHOS__)
+/* function is missing in MorphOS libnix version */
+extern unsigned long *__stdfiledes;
+
+ static unsigned long
+fdtofh(int filedescriptor)
+{
+ return __stdfiledes[filedescriptor];
+}
+#endif
+
+/*
+ * Sync the memory file *mfp to disk.
+ * Flags:
+ * MFS_ALL If not given, blocks with negative numbers are not synced,
+ * even when they are dirty!
+ * MFS_STOP Stop syncing when a character becomes available, but sync at
+ * least one block.
+ * MFS_FLUSH Make sure buffers are flushed to disk, so they will survive a
+ * system crash.
+ * MFS_ZERO Only write block 0.
+ *
+ * Return FAIL for failure, OK otherwise
+ */
+ int
+mf_sync(mfp, flags)
+ memfile_T *mfp;
+ int flags;
+{
+ int status;
+ bhdr_T *hp;
+#if defined(SYNC_DUP_CLOSE) && !defined(MSDOS)
+ int fd;
+#endif
+ int got_int_save = got_int;
+
+ if (mfp->mf_fd < 0) /* there is no file, nothing to do */
+ {
+ mfp->mf_dirty = FALSE;
+ return FAIL;
+ }
+
+ /* Only a CTRL-C while writing will break us here, not one typed
+ * previously. */
+ got_int = FALSE;
+
+ /*
+ * sync from last to first (may reduce the probability of an inconsistent
+ * file) If a write fails, it is very likely caused by a full filesystem.
+ * Then we only try to write blocks within the existing file. If that also
+ * fails then we give up.
+ */
+ status = OK;
+ for (hp = mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
+ if (((flags & MFS_ALL) || hp->bh_bnum >= 0)
+ && (hp->bh_flags & BH_DIRTY)
+ && (status == OK || (hp->bh_bnum >= 0
+ && hp->bh_bnum < mfp->mf_infile_count)))
+ {
+ if ((flags & MFS_ZERO) && hp->bh_bnum != 0)
+ continue;
+ if (mf_write(mfp, hp) == FAIL)
+ {
+ if (status == FAIL) /* double error: quit syncing */
+ break;
+ status = FAIL;
+ }
+ if (flags & MFS_STOP)
+ {
+ /* Stop when char available now. */
+ if (ui_char_avail())
+ break;
+ }
+ else
+ ui_breakcheck();
+ if (got_int)
+ break;
+ }
+
+ /*
+ * If the whole list is flushed, the memfile is not dirty anymore.
+ * In case of an error this flag is also set, to avoid trying all the time.
+ */
+ if (hp == NULL || status == FAIL)
+ mfp->mf_dirty = FALSE;
+
+ if ((flags & MFS_FLUSH) && *p_sws != NUL)
+ {
+#if defined(UNIX)
+# ifdef HAVE_FSYNC
+ /*
+ * most Unixes have the very useful fsync() function, just what we need.
+ * However, with OS/2 and EMX it is also available, but there are
+ * reports of bad problems with it (a bug in HPFS.IFS).
+ * So we disable use of it here in case someone tries to be smart
+ * and changes os_os2_cfg.h... (even though there is no __EMX__ test
+ * in the #if, as __EMX__ does not have sync(); we hope for a timely
+ * sync from the system itself).
+ */
+# if defined(__EMX__)
+ error "Dont use fsync with EMX! Read emxdoc.doc or emxfix01.doc for info."
+# endif
+ if (STRCMP(p_sws, "fsync") == 0)
+ {
+ if (fsync(mfp->mf_fd))
+ status = FAIL;
+ }
+ else
+# endif
+ /* OpenNT is strictly POSIX (Benzinger) */
+ /* Tandem/Himalaya NSK-OSS doesn't have sync() */
+# if defined(__OPENNT) || defined(__TANDEM)
+ fflush(NULL);
+# else
+ sync();
+# endif
+#endif
+#ifdef VMS
+ if (STRCMP(p_sws, "fsync") == 0)
+ {
+ if (fsync(mfp->mf_fd))
+ status = FAIL;
+ }
+#endif
+#ifdef MSDOS
+ if (_dos_commit(mfp->mf_fd))
+ status = FAIL;
+#else
+# ifdef SYNC_DUP_CLOSE
+ /*
+ * Win32 is a bit more work: Duplicate the file handle and close it.
+ * This should flush the file to disk.
+ */
+ if ((fd = dup(mfp->mf_fd)) >= 0)
+ close(fd);
+# endif
+#endif
+#ifdef AMIGA
+# ifdef __AROS__
+ if (fsync(mfp->mf_fd) != 0)
+ status = FAIL;
+# else
+ /*
+ * Flush() only exists for AmigaDos 2.0.
+ * For 1.3 it should be done with close() + open(), but then the risk
+ * is that the open() may fail and lose the file....
+ */
+# ifdef FEAT_ARP
+ if (dos2)
+# endif
+# ifdef SASC
+ {
+ struct UFB *fp = chkufb(mfp->mf_fd);
+
+ if (fp != NULL)
+ Flush(fp->ufbfh);
+ }
+# else
+# if defined(_DCC) || defined(__GNUC__) || defined(__MORPHOS__)
+ {
+# if defined(__GNUC__) && !defined(__MORPHOS__)
+ /* Have function (in libnix at least),
+ * but ain't got no prototype anywhere. */
+ extern unsigned long fdtofh(int filedescriptor);
+# endif
+ BPTR fh = (BPTR)fdtofh(mfp->mf_fd);
+
+ if (fh != 0)
+ Flush(fh);
+ }
+# else /* assume Manx */
+ Flush(_devtab[mfp->mf_fd].fd);
+# endif
+# endif
+# endif
+#endif /* AMIGA */
+ }
+
+ got_int |= got_int_save;
+
+ return status;
+}
+
+/*
+ * insert block *hp in front of hashlist of memfile *mfp
+ */
+ static void
+mf_ins_hash(mfp, hp)
+ memfile_T *mfp;
+ bhdr_T *hp;
+{
+ bhdr_T *hhp;
+ int hash;
+
+ hash = MEMHASH(hp->bh_bnum);
+ hhp = mfp->mf_hash[hash];
+ hp->bh_hash_next = hhp;
+ hp->bh_hash_prev = NULL;
+ if (hhp != NULL)
+ hhp->bh_hash_prev = hp;
+ mfp->mf_hash[hash] = hp;
+}
+
+/*
+ * remove block *hp from hashlist of memfile list *mfp
+ */
+ static void
+mf_rem_hash(mfp, hp)
+ memfile_T *mfp;
+ bhdr_T *hp;
+{
+ if (hp->bh_hash_prev == NULL)
+ mfp->mf_hash[MEMHASH(hp->bh_bnum)] = hp->bh_hash_next;
+ else
+ hp->bh_hash_prev->bh_hash_next = hp->bh_hash_next;
+
+ if (hp->bh_hash_next)
+ hp->bh_hash_next->bh_hash_prev = hp->bh_hash_prev;
+}
+
+/*
+ * look in hash lists of memfile *mfp for block header with number 'nr'
+ */
+ static bhdr_T *
+mf_find_hash(mfp, nr)
+ memfile_T *mfp;
+ blocknr_T nr;
+{
+ bhdr_T *hp;
+
+ for (hp = mfp->mf_hash[MEMHASH(nr)]; hp != NULL; hp = hp->bh_hash_next)
+ if (hp->bh_bnum == nr)
+ break;
+ return hp;
+}
+
+/*
+ * insert block *hp in front of used list of memfile *mfp
+ */
+ static void
+mf_ins_used(mfp, hp)
+ memfile_T *mfp;
+ bhdr_T *hp;
+{
+ hp->bh_next = mfp->mf_used_first;
+ mfp->mf_used_first = hp;
+ hp->bh_prev = NULL;
+ if (hp->bh_next == NULL) /* list was empty, adjust last pointer */
+ mfp->mf_used_last = hp;
+ else
+ hp->bh_next->bh_prev = hp;
+ mfp->mf_used_count += hp->bh_page_count;
+ total_mem_used += hp->bh_page_count * mfp->mf_page_size;
+}
+
+/*
+ * remove block *hp from used list of memfile *mfp
+ */
+ static void
+mf_rem_used(mfp, hp)
+ memfile_T *mfp;
+ bhdr_T *hp;
+{
+ if (hp->bh_next == NULL) /* last block in used list */
+ mfp->mf_used_last = hp->bh_prev;
+ else
+ hp->bh_next->bh_prev = hp->bh_prev;
+ if (hp->bh_prev == NULL) /* first block in used list */
+ mfp->mf_used_first = hp->bh_next;
+ else
+ hp->bh_prev->bh_next = hp->bh_next;
+ mfp->mf_used_count -= hp->bh_page_count;
+ total_mem_used -= hp->bh_page_count * mfp->mf_page_size;
+}
+
+/*
+ * Release the least recently used block from the used list if the number
+ * of used memory blocks gets to big.
+ *
+ * Return the block header to the caller, including the memory block, so
+ * it can be re-used. Make sure the page_count is right.
+ */
+ static bhdr_T *
+mf_release(mfp, page_count)
+ memfile_T *mfp;
+ int page_count;
+{
+ bhdr_T *hp;
+ int need_release;
+ buf_T *buf;
+
+ /* don't release while in mf_close_file() */
+ if (dont_release)
+ return NULL;
+
+ /*
+ * Need to release a block if the number of blocks for this memfile is
+ * higher than the maximum or total memory used is over 'maxmemtot'
+ */
+ need_release = ((mfp->mf_used_count >= mfp->mf_used_count_max)
+ || (total_mem_used >> 10) >= (long_u)p_mmt);
+
+ /*
+ * Try to create a swap file if the amount of memory used is getting too
+ * high.
+ */
+ if (mfp->mf_fd < 0 && need_release && p_uc)
+ {
+ /* find for which buffer this memfile is */
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (buf->b_ml.ml_mfp == mfp)
+ break;
+ if (buf != NULL && buf->b_may_swap)
+ ml_open_file(buf);
+ }
+
+ /*
+ * don't release a block if
+ * there is no file for this memfile
+ * or
+ * the number of blocks for this memfile is lower than the maximum
+ * and
+ * total memory used is not up to 'maxmemtot'
+ */
+ if (mfp->mf_fd < 0 || !need_release)
+ return NULL;
+
+ for (hp = mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
+ if (!(hp->bh_flags & BH_LOCKED))
+ break;
+ if (hp == NULL) /* not a single one that can be released */
+ return NULL;
+
+ /*
+ * If the block is dirty, write it.
+ * If the write fails we don't free it.
+ */
+ if ((hp->bh_flags & BH_DIRTY) && mf_write(mfp, hp) == FAIL)
+ return NULL;
+
+ mf_rem_used(mfp, hp);
+ mf_rem_hash(mfp, hp);
+
+ /*
+ * If a bhdr_T is returned, make sure that the page_count of bh_data is
+ * right
+ */
+ if (hp->bh_page_count != page_count)
+ {
+ vim_free(hp->bh_data);
+ if ((hp->bh_data = alloc(mfp->mf_page_size * page_count)) == NULL)
+ {
+ vim_free(hp);
+ return NULL;
+ }
+ hp->bh_page_count = page_count;
+ }
+ return hp;
+}
+
+/*
+ * release as many blocks as possible
+ * Used in case of out of memory
+ *
+ * return TRUE if any memory was released
+ */
+ int
+mf_release_all()
+{
+ buf_T *buf;
+ memfile_T *mfp;
+ bhdr_T *hp;
+ int retval = FALSE;
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ mfp = buf->b_ml.ml_mfp;
+ if (mfp != NULL)
+ {
+ /* If no swap file yet, may open one */
+ if (mfp->mf_fd < 0 && buf->b_may_swap)
+ ml_open_file(buf);
+
+ /* only if there is a swapfile */
+ if (mfp->mf_fd >= 0)
+ {
+ for (hp = mfp->mf_used_last; hp != NULL; )
+ {
+ if (!(hp->bh_flags & BH_LOCKED)
+ && (!(hp->bh_flags & BH_DIRTY)
+ || mf_write(mfp, hp) != FAIL))
+ {
+ mf_rem_used(mfp, hp);
+ mf_rem_hash(mfp, hp);
+ mf_free_bhdr(hp);
+ hp = mfp->mf_used_last; /* re-start, list was changed */
+ retval = TRUE;
+ }
+ else
+ hp = hp->bh_prev;
+ }
+ }
+ }
+ }
+ return retval;
+}
+
+/*
+ * Allocate a block header and a block of memory for it
+ */
+ static bhdr_T *
+mf_alloc_bhdr(mfp, page_count)
+ memfile_T *mfp;
+ int page_count;
+{
+ bhdr_T *hp;
+
+ if ((hp = (bhdr_T *)alloc((unsigned)sizeof(bhdr_T))) != NULL)
+ {
+ if ((hp->bh_data = (char_u *)alloc(mfp->mf_page_size * page_count))
+ == NULL)
+ {
+ vim_free(hp); /* not enough memory */
+ return NULL;
+ }
+ hp->bh_page_count = page_count;
+ }
+ return hp;
+}
+
+/*
+ * Free a block header and the block of memory for it
+ */
+ static void
+mf_free_bhdr(hp)
+ bhdr_T *hp;
+{
+ vim_free(hp->bh_data);
+ vim_free(hp);
+}
+
+/*
+ * insert entry *hp in the free list
+ */
+ static void
+mf_ins_free(mfp, hp)
+ memfile_T *mfp;
+ bhdr_T *hp;
+{
+ hp->bh_next = mfp->mf_free_first;
+ mfp->mf_free_first = hp;
+}
+
+/*
+ * remove the first entry from the free list and return a pointer to it
+ * Note: caller must check that mfp->mf_free_first is not NULL!
+ */
+ static bhdr_T *
+mf_rem_free(mfp)
+ memfile_T *mfp;
+{
+ bhdr_T *hp;
+
+ hp = mfp->mf_free_first;
+ mfp->mf_free_first = hp->bh_next;
+ return hp;
+}
+
+/*
+ * read a block from disk
+ *
+ * Return FAIL for failure, OK otherwise
+ */
+ static int
+mf_read(mfp, hp)
+ memfile_T *mfp;
+ bhdr_T *hp;
+{
+ off_t offset;
+ unsigned page_size;
+ unsigned size;
+
+ if (mfp->mf_fd < 0) /* there is no file, can't read */
+ return FAIL;
+
+ page_size = mfp->mf_page_size;
+ offset = (off_t)page_size * hp->bh_bnum;
+ size = page_size * hp->bh_page_count;
+ if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset)
+ {
+ EMSG(_("E294: Seek error in swap file read"));
+ return FAIL;
+ }
+ if ((unsigned)vim_read(mfp->mf_fd, hp->bh_data, size) != size)
+ {
+ EMSG(_("E295: Read error in swap file"));
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
+ * write a block to disk
+ *
+ * Return FAIL for failure, OK otherwise
+ */
+ static int
+mf_write(mfp, hp)
+ memfile_T *mfp;
+ bhdr_T *hp;
+{
+ off_t offset; /* offset in the file */
+ blocknr_T nr; /* block nr which is being written */
+ bhdr_T *hp2;
+ unsigned page_size; /* number of bytes in a page */
+ unsigned page_count; /* number of pages written */
+ unsigned size; /* number of bytes written */
+
+ if (mfp->mf_fd < 0) /* there is no file, can't write */
+ return FAIL;
+
+ if (hp->bh_bnum < 0) /* must assign file block number */
+ if (mf_trans_add(mfp, hp) == FAIL)
+ return FAIL;
+
+ page_size = mfp->mf_page_size;
+
+ /*
+ * We don't want gaps in the file. Write the blocks in front of *hp
+ * to extend the file.
+ * If block 'mf_infile_count' is not in the hash list, it has been
+ * freed. Fill the space in the file with data from the current block.
+ */
+ for (;;)
+ {
+ nr = hp->bh_bnum;
+ if (nr > mfp->mf_infile_count) /* beyond end of file */
+ {
+ nr = mfp->mf_infile_count;
+ hp2 = mf_find_hash(mfp, nr); /* NULL catched below */
+ }
+ else
+ hp2 = hp;
+
+ offset = (off_t)page_size * nr;
+ if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset)
+ {
+ EMSG(_("E296: Seek error in swap file write"));
+ return FAIL;
+ }
+ if (hp2 == NULL) /* freed block, fill with dummy data */
+ page_count = 1;
+ else
+ page_count = hp2->bh_page_count;
+ size = page_size * page_count;
+ if ((unsigned)vim_write(mfp->mf_fd,
+ (hp2 == NULL ? hp : hp2)->bh_data, size) != size)
+ {
+ /*
+ * Avoid repeating the error message, this mostly happens when the
+ * disk is full. We give the message again only after a succesful
+ * write or when hitting a key. We keep on trying, in case some
+ * space becomes available.
+ */
+ if (!did_swapwrite_msg)
+ EMSG(_("E297: Write error in swap file"));
+ did_swapwrite_msg = TRUE;
+ return FAIL;
+ }
+ did_swapwrite_msg = FALSE;
+ if (hp2 != NULL) /* written a non-dummy block */
+ hp2->bh_flags &= ~BH_DIRTY;
+ /* appended to the file */
+ if (nr + (blocknr_T)page_count > mfp->mf_infile_count)
+ mfp->mf_infile_count = nr + page_count;
+ if (nr == hp->bh_bnum) /* written the desired block */
+ break;
+ }
+ return OK;
+}
+
+/*
+ * Make block number for *hp positive and add it to the translation list
+ *
+ * Return FAIL for failure, OK otherwise
+ */
+ static int
+mf_trans_add(mfp, hp)
+ memfile_T *mfp;
+ bhdr_T *hp;
+{
+ bhdr_T *freep;
+ blocknr_T new_bnum;
+ int hash;
+ NR_TRANS *np;
+ int page_count;
+
+ if (hp->bh_bnum >= 0) /* it's already positive */
+ return OK;
+
+ if ((np = (NR_TRANS *)alloc((unsigned)sizeof(NR_TRANS))) == NULL)
+ return FAIL;
+
+/*
+ * get a new number for the block.
+ * If the first item in the free list has sufficient pages, use its number
+ * Otherwise use mf_blocknr_max.
+ */
+ freep = mfp->mf_free_first;
+ page_count = hp->bh_page_count;
+ if (freep != NULL && freep->bh_page_count >= page_count)
+ {
+ new_bnum = freep->bh_bnum;
+ /*
+ * If the page count of the free block was larger, recude it.
+ * If the page count matches, remove the block from the free list
+ */
+ if (freep->bh_page_count > page_count)
+ {
+ freep->bh_bnum += page_count;
+ freep->bh_page_count -= page_count;
+ }
+ else
+ {
+ freep = mf_rem_free(mfp);
+ vim_free(freep);
+ }
+ }
+ else
+ {
+ new_bnum = mfp->mf_blocknr_max;
+ mfp->mf_blocknr_max += page_count;
+ }
+
+ np->nt_old_bnum = hp->bh_bnum; /* adjust number */
+ np->nt_new_bnum = new_bnum;
+
+ mf_rem_hash(mfp, hp); /* remove from old hash list */
+ hp->bh_bnum = new_bnum;
+ mf_ins_hash(mfp, hp); /* insert in new hash list */
+
+ hash = MEMHASH(np->nt_old_bnum); /* insert in trans list */
+ np->nt_next = mfp->mf_trans[hash];
+ mfp->mf_trans[hash] = np;
+ if (np->nt_next != NULL)
+ np->nt_next->nt_prev = np;
+ np->nt_prev = NULL;
+
+ return OK;
+}
+
+/*
+ * Lookup a tranlation from the trans lists and delete the entry
+ *
+ * Return the positive new number when found, the old number when not found
+ */
+ blocknr_T
+mf_trans_del(mfp, old_nr)
+ memfile_T *mfp;
+ blocknr_T old_nr;
+{
+ int hash;
+ NR_TRANS *np;
+ blocknr_T new_bnum;
+
+ hash = MEMHASH(old_nr);
+ for (np = mfp->mf_trans[hash]; np != NULL; np = np->nt_next)
+ if (np->nt_old_bnum == old_nr)
+ break;
+ if (np == NULL) /* not found */
+ return old_nr;
+
+ mfp->mf_neg_count--;
+ new_bnum = np->nt_new_bnum;
+ if (np->nt_prev != NULL) /* remove entry from the trans list */
+ np->nt_prev->nt_next = np->nt_next;
+ else
+ mfp->mf_trans[hash] = np->nt_next;
+ if (np->nt_next != NULL)
+ np->nt_next->nt_prev = np->nt_prev;
+ vim_free(np);
+
+ return new_bnum;
+}
+
+/*
+ * Set mfp->mf_ffname according to mfp->mf_fname and some other things.
+ * Only called when creating or renaming the swapfile. Either way it's a new
+ * name so we must work out the full path name.
+ */
+ void
+mf_set_ffname(mfp)
+ memfile_T *mfp;
+{
+ mfp->mf_ffname = FullName_save(mfp->mf_fname, FALSE);
+}
+
+/*
+ * Make the name of the file used for the memfile a full path.
+ * Used before doing a :cd
+ */
+ void
+mf_fullname(mfp)
+ memfile_T *mfp;
+{
+ if (mfp != NULL && mfp->mf_fname != NULL && mfp->mf_ffname != NULL)
+ {
+ vim_free(mfp->mf_fname);
+ mfp->mf_fname = mfp->mf_ffname;
+ mfp->mf_ffname = NULL;
+ }
+}
+
+/*
+ * return TRUE if there are any translations pending for 'mfp'
+ */
+ int
+mf_need_trans(mfp)
+ memfile_T *mfp;
+{
+ return (mfp->mf_fname != NULL && mfp->mf_neg_count > 0);
+}
+
+/*
+ * Open a swap file for a memfile.
+ * The "fname" must be in allocated memory, and is consumed (also when an
+ * error occurs).
+ */
+ static void
+mf_do_open(mfp, fname, flags)
+ memfile_T *mfp;
+ char_u *fname;
+ int flags; /* flags for open() */
+{
+#ifdef HAVE_LSTAT
+ struct stat sb;
+#endif
+
+ mfp->mf_fname = fname;
+
+ /*
+ * Get the full path name before the open, because this is
+ * not possible after the open on the Amiga.
+ * fname cannot be NameBuff, because it must have been allocated.
+ */
+ mf_set_ffname(mfp);
+#if defined(MSDOS) || defined(MSWIN) || defined(RISCOS)
+ /*
+ * A ":!cd e:xxx" may change the directory without us knowning, use the
+ * full pathname always. Careful: This frees fname!
+ */
+ mf_fullname(mfp);
+#endif
+
+#ifdef HAVE_LSTAT
+ /*
+ * Extra security check: When creating a swap file it really shouldn't
+ * exist yet. If there is a symbolic link, this is most likely an attack.
+ */
+ if ((flags & O_CREAT) && mch_lstat((char *)mfp->mf_fname, &sb) >= 0)
+ {
+ mfp->mf_fd = -1;
+ EMSG(_("E300: Swap file already exists (symlink attack?)"));
+ }
+ else
+#endif
+ {
+ /*
+ * try to open the file
+ */
+ flags |= O_EXTRA;
+#ifdef WIN32
+ /* Prevent handle inheritance that cause problems with Cscope
+ * (swap file may not be deleted if cscope connection was open after
+ * the file) */
+ flags |= O_NOINHERIT;
+#endif
+ mfp->mf_fd = mch_open_rw((char *)mfp->mf_fname, flags);
+ }
+
+ /*
+ * If the file cannot be opened, use memory only
+ */
+ if (mfp->mf_fd < 0)
+ {
+ vim_free(mfp->mf_fname);
+ vim_free(mfp->mf_ffname);
+ mfp->mf_fname = NULL;
+ mfp->mf_ffname = NULL;
+ }
+ else
+ mch_hide(mfp->mf_fname); /* try setting the 'hidden' flag */
+}
diff --git a/src/memline.c b/src/memline.c
new file mode 100644
index 000000000..7c1866329
--- /dev/null
+++ b/src/memline.c
@@ -0,0 +1,4378 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/* for debugging */
+/* #define CHECK(c, s) if (c) EMSG(s) */
+#define CHECK(c, s)
+
+/*
+ * memline.c: Contains the functions for appending, deleting and changing the
+ * text lines. The memfile functions are used to store the information in blocks
+ * of memory, backed up by a file. The structure of the information is a tree.
+ * The root of the tree is a pointer block. The leaves of the tree are data
+ * blocks. In between may be several layers of pointer blocks, forming branches.
+ *
+ * Three types of blocks are used:
+ * - Block nr 0 contains information for recovery
+ * - Pointer blocks contain list of pointers to other blocks.
+ * - Data blocks contain the actual text.
+ *
+ * Block nr 0 contains the block0 structure (see below).
+ *
+ * Block nr 1 is the first pointer block. It is the root of the tree.
+ * Other pointer blocks are branches.
+ *
+ * If a line is too big to fit in a single page, the block containing that
+ * line is made big enough to hold the line. It may span several pages.
+ * Otherwise all blocks are one page.
+ *
+ * A data block that was filled when starting to edit a file and was not
+ * changed since then, can have a negative block number. This means that it
+ * has not yet been assigned a place in the file. When recovering, the lines
+ * in this data block can be read from the original file. When the block is
+ * changed (lines appended/deleted/changed) or when it is flushed it gets a
+ * positive number. Use mf_trans_del() to get the new number, before calling
+ * mf_get().
+ */
+
+#if defined(MSDOS) || defined(WIN32) || defined(_WIN64)
+# include <io.h>
+#endif
+
+#include "vim.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#ifndef UNIX /* it's in os_unix.h for Unix */
+# include <time.h>
+#endif
+
+#ifdef SASC
+# include <proto/dos.h> /* for Open() and Close() */
+#endif
+
+typedef struct block0 ZERO_BL; /* contents of the first block */
+typedef struct pointer_block PTR_BL; /* contents of a pointer block */
+typedef struct data_block DATA_BL; /* contents of a data block */
+typedef struct pointer_entry PTR_EN; /* block/line-count pair */
+
+#define DATA_ID (('d' << 8) + 'a') /* data block id */
+#define PTR_ID (('p' << 8) + 't') /* pointer block id */
+#define BLOCK0_ID0 'b' /* block 0 id 0 */
+#define BLOCK0_ID1 '0' /* block 0 id 1 */
+
+/*
+ * pointer to a block, used in a pointer block
+ */
+struct pointer_entry
+{
+ blocknr_T pe_bnum; /* block number */
+ linenr_T pe_line_count; /* number of lines in this branch */
+ linenr_T pe_old_lnum; /* lnum for this block (for recovery) */
+ int pe_page_count; /* number of pages in block pe_bnum */
+};
+
+/*
+ * A pointer block contains a list of branches in the tree.
+ */
+struct pointer_block
+{
+ short_u pb_id; /* ID for pointer block: PTR_ID */
+ short_u pb_count; /* number of pointer in this block */
+ short_u pb_count_max; /* maximum value for pb_count */
+ PTR_EN pb_pointer[1]; /* list of pointers to blocks (actually longer)
+ * followed by empty space until end of page */
+};
+
+/*
+ * A data block is a leaf in the tree.
+ *
+ * The text of the lines is at the end of the block. The text of the first line
+ * in the block is put at the end, the text of the second line in front of it,
+ * etc. Thus the order of the lines is the opposite of the line number.
+ */
+struct data_block
+{
+ short_u db_id; /* ID for data block: DATA_ID */
+ unsigned db_free; /* free space available */
+ unsigned db_txt_start; /* byte where text starts */
+ unsigned db_txt_end; /* byte just after data block */
+ linenr_T db_line_count; /* number of lines in this block */
+ unsigned db_index[1]; /* index for start of line (actually bigger)
+ * followed by empty space upto db_txt_start
+ * followed by the text in the lines until
+ * end of page */
+};
+
+/*
+ * The low bits of db_index hold the actual index. The topmost bit is
+ * used for the global command to be able to mark a line.
+ * This method is not clean, but otherwise there would be at least one extra
+ * byte used for each line.
+ * The mark has to be in this place to keep it with the correct line when other
+ * lines are inserted or deleted.
+ */
+#define DB_MARKED ((unsigned)1 << ((sizeof(unsigned) * 8) - 1))
+#define DB_INDEX_MASK (~DB_MARKED)
+
+#define INDEX_SIZE (sizeof(unsigned)) /* size of one db_index entry */
+#define HEADER_SIZE (sizeof(DATA_BL) - INDEX_SIZE) /* size of data block header */
+
+#define B0_FNAME_SIZE 900
+#define B0_UNAME_SIZE 40
+#define B0_HNAME_SIZE 40
+/*
+ * Restrict the numbers to 32 bits, otherwise most compilers will complain.
+ * This won't detect a 64 bit machine that only swaps a byte in the top 32
+ * bits, but that is crazy anyway.
+ */
+#define B0_MAGIC_LONG 0x30313233L
+#define B0_MAGIC_INT 0x20212223L
+#define B0_MAGIC_SHORT 0x10111213L
+#define B0_MAGIC_CHAR 0x55
+
+/*
+ * Block zero holds all info about the swap file.
+ *
+ * NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing
+ * swap files unusable!
+ *
+ * If size of block0 changes anyway, adjust MIN_SWAP_PAGE_SIZE in vim.h!!
+ *
+ * This block is built up of single bytes, to make it portable accros
+ * different machines. b0_magic_* is used to check the byte order and size of
+ * variables, because the rest of the swap file is not portable.
+ */
+struct block0
+{
+ char_u b0_id[2]; /* id for block 0: BLOCK0_ID0 and BLOCK0_ID1 */
+ char_u b0_version[10]; /* Vim version string */
+ char_u b0_page_size[4];/* number of bytes per page */
+ char_u b0_mtime[4]; /* last modification time of file */
+ char_u b0_ino[4]; /* inode of b0_fname */
+ char_u b0_pid[4]; /* process id of creator (or 0) */
+ char_u b0_uname[B0_UNAME_SIZE]; /* name of user (uid if no name) */
+ char_u b0_hname[B0_HNAME_SIZE]; /* host name (if it has a name) */
+ char_u b0_fname[B0_FNAME_SIZE]; /* name of file being edited */
+ long b0_magic_long; /* check for byte order of long */
+ int b0_magic_int; /* check for byte order of int */
+ short b0_magic_short; /* check for byte order of short */
+ char_u b0_magic_char; /* check for last char */
+};
+#define b0_dirty b0_fname[B0_FNAME_SIZE-1]
+
+#define STACK_INCR 5 /* nr of entries added to ml_stack at a time */
+
+/*
+ * The line number where the first mark may be is remembered.
+ * If it is 0 there are no marks at all.
+ * (always used for the current buffer only, no buffer change possible while
+ * executing a global command).
+ */
+static linenr_T lowest_marked = 0;
+
+/*
+ * arguments for ml_find_line()
+ */
+#define ML_DELETE 0x11 /* delete line */
+#define ML_INSERT 0x12 /* insert line */
+#define ML_FIND 0x13 /* just find the line */
+#define ML_FLUSH 0x02 /* flush locked block */
+#define ML_SIMPLE(x) (x & 0x10) /* DEL, INS or FIND */
+
+static void set_b0_fname __ARGS((ZERO_BL *, buf_T *buf));
+static time_t swapfile_info __ARGS((char_u *));
+static int recov_file_names __ARGS((char_u **, char_u *, int prepend_dot));
+static int ml_append_int __ARGS((buf_T *, linenr_T, char_u *, colnr_T, int, int));
+static int ml_delete_int __ARGS((buf_T *, linenr_T, int));
+static char_u *findswapname __ARGS((buf_T *, char_u **, char_u *));
+static void ml_flush_line __ARGS((buf_T *));
+static bhdr_T *ml_new_data __ARGS((memfile_T *, int, int));
+static bhdr_T *ml_new_ptr __ARGS((memfile_T *));
+static bhdr_T *ml_find_line __ARGS((buf_T *, linenr_T, int));
+static int ml_add_stack __ARGS((buf_T *));
+static char_u *makeswapname __ARGS((buf_T *, char_u *));
+static void ml_lineadd __ARGS((buf_T *, int));
+static int b0_magic_wrong __ARGS((ZERO_BL *));
+#ifdef CHECK_INODE
+static int fnamecmp_ino __ARGS((char_u *, char_u *, long));
+#endif
+static void long_to_char __ARGS((long, char_u *));
+static long char_to_long __ARGS((char_u *));
+#if defined(UNIX) || defined(WIN3264)
+static char_u *make_percent_swname __ARGS((char_u *dir, char_u *name));
+#endif
+#ifdef FEAT_BYTEOFF
+static void ml_updatechunk __ARGS((buf_T *buf, long line, long len, int updtype));
+#endif
+
+/*
+ * open a new memline for 'curbuf'
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+ml_open()
+{
+ memfile_T *mfp;
+ bhdr_T *hp = NULL;
+ ZERO_BL *b0p;
+ PTR_BL *pp;
+ DATA_BL *dp;
+
+/*
+ * init fields in memline struct
+ */
+ curbuf->b_ml.ml_stack_size = 0; /* no stack yet */
+ curbuf->b_ml.ml_stack = NULL; /* no stack yet */
+ curbuf->b_ml.ml_stack_top = 0; /* nothing in the stack */
+ curbuf->b_ml.ml_locked = NULL; /* no cached block */
+ curbuf->b_ml.ml_line_lnum = 0; /* no cached line */
+#ifdef FEAT_BYTEOFF
+ curbuf->b_ml.ml_chunksize = NULL;
+#endif
+
+/*
+ * When 'updatecount' is non-zero, flag that a swap file may be opened later.
+ */
+ if (p_uc && curbuf->b_p_swf)
+ curbuf->b_may_swap = TRUE;
+ else
+ curbuf->b_may_swap = FALSE;
+
+/*
+ * Open the memfile. No swap file is created yet.
+ */
+ mfp = mf_open(NULL, 0);
+ if (mfp == NULL)
+ goto error;
+
+ curbuf->b_ml.ml_mfp = mfp;
+ curbuf->b_ml.ml_flags = ML_EMPTY;
+ curbuf->b_ml.ml_line_count = 1;
+
+#if defined(MSDOS) && !defined(DJGPP)
+ /* for 16 bit MS-DOS create a swapfile now, because we run out of
+ * memory very quickly */
+ if (p_uc != 0)
+ ml_open_file(curbuf);
+#endif
+
+/*
+ * fill block0 struct and write page 0
+ */
+ if ((hp = mf_new(mfp, FALSE, 1)) == NULL)
+ goto error;
+ if (hp->bh_bnum != 0)
+ {
+ EMSG(_("E298: Didn't get block nr 0?"));
+ goto error;
+ }
+ b0p = (ZERO_BL *)(hp->bh_data);
+
+ b0p->b0_id[0] = BLOCK0_ID0;
+ b0p->b0_id[1] = BLOCK0_ID1;
+ b0p->b0_dirty = curbuf->b_changed ? 0x55 : 0;
+ b0p->b0_magic_long = (long)B0_MAGIC_LONG;
+ b0p->b0_magic_int = (int)B0_MAGIC_INT;
+ b0p->b0_magic_short = (short)B0_MAGIC_SHORT;
+ b0p->b0_magic_char = B0_MAGIC_CHAR;
+
+ STRNCPY(b0p->b0_version, "VIM ", 4);
+ STRNCPY(b0p->b0_version + 4, Version, 6);
+ set_b0_fname(b0p, curbuf);
+ long_to_char((long)mfp->mf_page_size, b0p->b0_page_size);
+ (void)get_user_name(b0p->b0_uname, B0_UNAME_SIZE);
+ b0p->b0_uname[B0_UNAME_SIZE - 1] = NUL;
+ mch_get_host_name(b0p->b0_hname, B0_HNAME_SIZE);
+ b0p->b0_hname[B0_HNAME_SIZE - 1] = NUL;
+ long_to_char(mch_get_pid(), b0p->b0_pid);
+
+ /*
+ * Always sync block number 0 to disk, so we can check the file name in
+ * the swap file in findswapname(). Don't do this for help files though.
+ * Only works when there's a swapfile, otherwise it's done when the file
+ * is created.
+ */
+ mf_put(mfp, hp, TRUE, FALSE);
+ if (!curbuf->b_help)
+ (void)mf_sync(mfp, 0);
+
+/*
+ * fill in root pointer block and write page 1
+ */
+ if ((hp = ml_new_ptr(mfp)) == NULL)
+ goto error;
+ if (hp->bh_bnum != 1)
+ {
+ EMSG(_("E298: Didn't get block nr 1?"));
+ goto error;
+ }
+ pp = (PTR_BL *)(hp->bh_data);
+ pp->pb_count = 1;
+ pp->pb_pointer[0].pe_bnum = 2;
+ pp->pb_pointer[0].pe_page_count = 1;
+ pp->pb_pointer[0].pe_old_lnum = 1;
+ pp->pb_pointer[0].pe_line_count = 1; /* line count after insertion */
+ mf_put(mfp, hp, TRUE, FALSE);
+
+/*
+ * allocate first data block and create an empty line 1.
+ */
+ if ((hp = ml_new_data(mfp, FALSE, 1)) == NULL)
+ goto error;
+ if (hp->bh_bnum != 2)
+ {
+ EMSG(_("E298: Didn't get block nr 2?"));
+ goto error;
+ }
+
+ dp = (DATA_BL *)(hp->bh_data);
+ dp->db_index[0] = --dp->db_txt_start; /* at end of block */
+ dp->db_free -= 1 + INDEX_SIZE;
+ dp->db_line_count = 1;
+ *((char_u *)dp + dp->db_txt_start) = NUL; /* emtpy line */
+
+ return OK;
+
+error:
+ if (mfp != NULL)
+ {
+ if (hp)
+ mf_put(mfp, hp, FALSE, FALSE);
+ mf_close(mfp, TRUE); /* will also free(mfp->mf_fname) */
+ }
+ curbuf->b_ml.ml_mfp = NULL;
+ return FAIL;
+}
+
+/*
+ * ml_setname() is called when the file name of "buf" has been changed.
+ * It may rename the swap file.
+ */
+ void
+ml_setname(buf)
+ buf_T *buf;
+{
+ int success = FALSE;
+ memfile_T *mfp;
+ char_u *fname;
+ char_u *dirp;
+#if defined(MSDOS) || defined(MSWIN)
+ char_u *p;
+#endif
+
+ mfp = buf->b_ml.ml_mfp;
+ if (mfp->mf_fd < 0) /* there is no swap file yet */
+ {
+ /*
+ * When 'updatecount' is 0 and 'noswapfile' there is no swap file.
+ * For help files we will make a swap file now.
+ */
+ if (p_uc != 0)
+ ml_open_file(buf); /* create a swap file */
+ return;
+ }
+
+ /*
+ * Try all directories in the 'directory' option.
+ */
+ dirp = p_dir;
+ for (;;)
+ {
+ if (*dirp == NUL) /* tried all directories, fail */
+ break;
+ fname = findswapname(buf, &dirp, mfp->mf_fname); /* alloc's fname */
+ if (fname == NULL) /* no file name found for this dir */
+ continue;
+
+#if defined(MSDOS) || defined(MSWIN)
+ /*
+ * Set full pathname for swap file now, because a ":!cd dir" may
+ * change directory without us knowing it.
+ */
+ p = FullName_save(fname, FALSE);
+ vim_free(fname);
+ fname = p;
+ if (fname == NULL)
+ continue;
+#endif
+ /* if the file name is the same we don't have to do anything */
+ if (fnamecmp(fname, mfp->mf_fname) == 0)
+ {
+ vim_free(fname);
+ success = TRUE;
+ break;
+ }
+ /* need to close the swap file before renaming */
+ if (mfp->mf_fd >= 0)
+ {
+ close(mfp->mf_fd);
+ mfp->mf_fd = -1;
+ }
+
+ /* try to rename the swap file */
+ if (vim_rename(mfp->mf_fname, fname) == 0)
+ {
+ success = TRUE;
+ vim_free(mfp->mf_fname);
+ mfp->mf_fname = fname;
+ vim_free(mfp->mf_ffname);
+#if defined(MSDOS) || defined(MSWIN)
+ mfp->mf_ffname = NULL; /* mf_fname is full pathname already */
+#else
+ mf_set_ffname(mfp);
+#endif
+ break;
+ }
+ vim_free(fname); /* this fname didn't work, try another */
+ }
+
+ if (mfp->mf_fd == -1) /* need to (re)open the swap file */
+ {
+ mfp->mf_fd = mch_open((char *)mfp->mf_fname, O_RDWR | O_EXTRA, 0);
+ if (mfp->mf_fd < 0)
+ {
+ /* could not (re)open the swap file, what can we do???? */
+ EMSG(_("E301: Oops, lost the swap file!!!"));
+ return;
+ }
+ }
+ if (!success)
+ EMSG(_("E302: Could not rename swap file"));
+}
+
+/*
+ * Open a file for the memfile for all buffers that are not readonly or have
+ * been modified.
+ * Used when 'updatecount' changes from zero to non-zero.
+ */
+ void
+ml_open_files()
+{
+ buf_T *buf;
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (!buf->b_p_ro || buf->b_changed)
+ ml_open_file(buf);
+}
+
+/*
+ * Open a swap file for an existing memfile, if there is no swap file yet.
+ * If we are unable to find a file name, mf_fname will be NULL
+ * and the memfile will be in memory only (no recovery possible).
+ */
+ void
+ml_open_file(buf)
+ buf_T *buf;
+{
+ memfile_T *mfp;
+ char_u *fname;
+ char_u *dirp;
+
+ mfp = buf->b_ml.ml_mfp;
+ if (mfp == NULL || mfp->mf_fd >= 0 || !buf->b_p_swf)
+ return; /* nothing to do */
+
+ /*
+ * Try all directories in 'directory' option.
+ */
+ dirp = p_dir;
+ for (;;)
+ {
+ if (*dirp == NUL)
+ break;
+ /* There is a small chance that between chosing the swap file name and
+ * creating it, another Vim creates the file. In that case the
+ * creation will fail and we will use another directory. */
+ fname = findswapname(buf, &dirp, NULL); /* allocates fname */
+ if (fname == NULL)
+ continue;
+ if (mf_open_file(mfp, fname) == OK) /* consumes fname! */
+ {
+#if defined(MSDOS) || defined(MSWIN) || defined(RISCOS)
+ /*
+ * set full pathname for swap file now, because a ":!cd dir" may
+ * change directory without us knowing it.
+ */
+ mf_fullname(mfp);
+#endif
+ /* Flush block zero, so others can read it */
+ if (mf_sync(mfp, MFS_ZERO) == OK)
+ break;
+ /* Writing block 0 failed: close the file and try another dir */
+ mf_close_file(buf, FALSE);
+ }
+ }
+
+ if (mfp->mf_fname == NULL) /* Failed! */
+ {
+ need_wait_return = TRUE; /* call wait_return later */
+ ++no_wait_return;
+ (void)EMSG2(_("E303: Unable to open swap file for \"%s\", recovery impossible"),
+ buf_spname(buf) != NULL
+ ? (char_u *)buf_spname(buf)
+ : buf->b_fname);
+ --no_wait_return;
+ }
+
+ /* don't try to open a swap file again */
+ buf->b_may_swap = FALSE;
+}
+
+/*
+ * If still need to create a swap file, and starting to edit a not-readonly
+ * file, or reading into an existing buffer, create a swap file now.
+ */
+ void
+check_need_swap(newfile)
+ int newfile; /* reading file into new buffer */
+{
+ if (curbuf->b_may_swap && (!curbuf->b_p_ro || !newfile))
+ ml_open_file(curbuf);
+}
+
+/*
+ * Close memline for buffer 'buf'.
+ * If 'del_file' is TRUE, delete the swap file
+ */
+ void
+ml_close(buf, del_file)
+ buf_T *buf;
+ int del_file;
+{
+ if (buf->b_ml.ml_mfp == NULL) /* not open */
+ return;
+ mf_close(buf->b_ml.ml_mfp, del_file); /* close the .swp file */
+ if (buf->b_ml.ml_line_lnum != 0 && (buf->b_ml.ml_flags & ML_LINE_DIRTY))
+ vim_free(buf->b_ml.ml_line_ptr);
+ vim_free(buf->b_ml.ml_stack);
+#ifdef FEAT_BYTEOFF
+ vim_free(buf->b_ml.ml_chunksize);
+ buf->b_ml.ml_chunksize = NULL;
+#endif
+ buf->b_ml.ml_mfp = NULL;
+
+ /* Reset the "recovered" flag, give the ATTENTION prompt the next time
+ * this buffer is loaded. */
+ buf->b_flags &= ~BF_RECOVERED;
+}
+
+/*
+ * Close all existing memlines and memfiles.
+ * Only used when exiting.
+ * When 'del_file' is TRUE, delete the memfiles.
+ */
+ void
+ml_close_all(del_file)
+ int del_file;
+{
+ buf_T *buf;
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ ml_close(buf, del_file);
+#ifdef TEMPDIRNAMES
+ vim_deltempdir(); /* delete created temp directory */
+#endif
+}
+
+/*
+ * Close all memfiles for not modified buffers.
+ * Only use just before exiting!
+ */
+ void
+ml_close_notmod()
+{
+ buf_T *buf;
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (!bufIsChanged(buf))
+ ml_close(buf, TRUE); /* close all not-modified buffers */
+}
+
+/*
+ * Update the timestamp in the .swp file.
+ * Used when the file has been written.
+ */
+ void
+ml_timestamp(buf)
+ buf_T *buf;
+{
+ memfile_T *mfp;
+ bhdr_T *hp;
+ ZERO_BL *b0p;
+
+ mfp = buf->b_ml.ml_mfp;
+
+ if (mfp == NULL || (hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL)
+ return;
+ b0p = (ZERO_BL *)(hp->bh_data);
+ if (b0p->b0_id[0] != BLOCK0_ID0 || b0p->b0_id[1] != BLOCK0_ID1)
+ EMSG(_("E304: ml_timestamp: Didn't get block 0??"));
+ else
+ set_b0_fname(b0p, buf);
+ mf_put(mfp, hp, TRUE, FALSE);
+}
+
+/*
+ * Write file name and timestamp into block 0 of a swap file.
+ * Also set buf->b_mtime.
+ * Don't use NameBuff[]!!!
+ */
+ static void
+set_b0_fname(b0p, buf)
+ ZERO_BL *b0p;
+ buf_T *buf;
+{
+ struct stat st;
+
+ if (buf->b_ffname == NULL)
+ b0p->b0_fname[0] = NUL;
+ else
+ {
+#if defined(MSDOS) || defined(MSWIN) || defined(AMIGA) || defined(RISCOS)
+ /* systems that cannot translate "~user" back into a path: copy the
+ * file name unmodified */
+ STRNCPY(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE);
+#else
+ size_t flen, ulen;
+ char_u uname[B0_UNAME_SIZE];
+
+ /*
+ * For a file under the home directory of the current user, we try to
+ * replace the home directory path with "~user". This helps when
+ * editing the same file on different machines over a network.
+ * First replace home dir path with "~/" with home_replace().
+ * Then insert the user name to get "~user/".
+ */
+ home_replace(NULL, buf->b_ffname, b0p->b0_fname, B0_FNAME_SIZE, TRUE);
+ if (b0p->b0_fname[0] == '~')
+ {
+ flen = STRLEN(b0p->b0_fname);
+ /* If there is no user name or it is too long, don't use "~/" */
+ if (get_user_name(uname, B0_UNAME_SIZE) == FAIL
+ || (ulen = STRLEN(uname)) + flen > B0_FNAME_SIZE - 1)
+ STRNCPY(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE);
+ else
+ {
+ mch_memmove(b0p->b0_fname + ulen + 1, b0p->b0_fname + 1, flen);
+ mch_memmove(b0p->b0_fname + 1, uname, ulen);
+ }
+ }
+#endif
+ if (mch_stat((char *)buf->b_ffname, &st) >= 0)
+ {
+ long_to_char((long)st.st_mtime, b0p->b0_mtime);
+#ifdef CHECK_INODE
+ long_to_char((long)st.st_ino, b0p->b0_ino);
+#endif
+ buf_store_time(buf, &st, buf->b_ffname);
+ buf->b_mtime_read = buf->b_mtime;
+ }
+ else
+ {
+ long_to_char(0L, b0p->b0_mtime);
+#ifdef CHECK_INODE
+ long_to_char(0L, b0p->b0_ino);
+#endif
+ buf->b_mtime = 0;
+ buf->b_mtime_read = 0;
+ buf->b_orig_size = 0;
+ buf->b_orig_mode = 0;
+ }
+ }
+}
+
+/*
+ * try to recover curbuf from the .swp file
+ */
+ void
+ml_recover()
+{
+ buf_T *buf = NULL;
+ memfile_T *mfp = NULL;
+ char_u *fname;
+ bhdr_T *hp = NULL;
+ ZERO_BL *b0p;
+ PTR_BL *pp;
+ DATA_BL *dp;
+ infoptr_T *ip;
+ blocknr_T bnum;
+ int page_count;
+ struct stat org_stat, swp_stat;
+ int len;
+ int directly;
+ linenr_T lnum;
+ char_u *p;
+ int i;
+ long error;
+ int cannot_open;
+ linenr_T line_count;
+ int has_error;
+ int idx;
+ int top;
+ int txt_start;
+ off_t size;
+ int called_from_main;
+ int serious_error = TRUE;
+ long mtime;
+ int attr;
+
+ recoverymode = TRUE;
+ called_from_main = (curbuf->b_ml.ml_mfp == NULL);
+ attr = hl_attr(HLF_E);
+/*
+ * If the file name ends in ".sw?" we use it directly.
+ * Otherwise a search is done to find the swap file(s).
+ */
+ fname = curbuf->b_fname;
+ if (fname == NULL) /* When there is no file name */
+ fname = (char_u *)"";
+ len = (int)STRLEN(fname);
+ if (len >= 4 &&
+#if defined(VMS) || defined(RISCOS)
+ STRNICMP(fname + len - 4, "_sw" , 3)
+#else
+ STRNICMP(fname + len - 4, ".sw" , 3)
+#endif
+ == 0)
+ {
+ directly = TRUE;
+ fname = vim_strsave(fname); /* make a copy for mf_open() */
+ }
+ else
+ {
+ directly = FALSE;
+
+ /* count the number of matching swap files */
+ len = recover_names(&fname, FALSE, 0);
+ if (len == 0) /* no swap files found */
+ {
+ EMSG2(_("E305: No swap file found for %s"), fname);
+ goto theend;
+ }
+ if (len == 1) /* one swap file found, use it */
+ i = 1;
+ else /* several swap files found, choose */
+ {
+ /* list the names of the swap files */
+ (void)recover_names(&fname, TRUE, 0);
+ msg_putchar('\n');
+ MSG_PUTS(_("Enter number of swap file to use (0 to quit): "));
+ i = get_number(FALSE);
+ if (i < 1 || i > len)
+ goto theend;
+ }
+ /* get the swap file name that will be used */
+ (void)recover_names(&fname, FALSE, i);
+ }
+ if (fname == NULL)
+ goto theend; /* out of memory */
+
+ /* When called from main() still need to initialize storage structure */
+ if (called_from_main && ml_open() == FAIL)
+ getout(1);
+
+/*
+ * allocate a buffer structure (only the memline in it is really used)
+ */
+ buf = (buf_T *)alloc((unsigned)sizeof(buf_T));
+ if (buf == NULL)
+ {
+ vim_free(fname);
+ goto theend;
+ }
+
+/*
+ * init fields in memline struct
+ */
+ buf->b_ml.ml_stack_size = 0; /* no stack yet */
+ buf->b_ml.ml_stack = NULL; /* no stack yet */
+ buf->b_ml.ml_stack_top = 0; /* nothing in the stack */
+ buf->b_ml.ml_line_lnum = 0; /* no cached line */
+ buf->b_ml.ml_locked = NULL; /* no locked block */
+ buf->b_ml.ml_flags = 0;
+
+/*
+ * open the memfile from the old swap file
+ */
+ p = vim_strsave(fname); /* save fname for the message
+ (mf_open() may free fname) */
+ mfp = mf_open(fname, O_RDONLY); /* consumes fname! */
+ if (mfp == NULL || mfp->mf_fd < 0)
+ {
+ if (p != NULL)
+ {
+ EMSG2(_("E306: Cannot open %s"), p);
+ vim_free(p);
+ }
+ goto theend;
+ }
+ vim_free(p);
+ buf->b_ml.ml_mfp = mfp;
+
+ /*
+ * The page size set in mf_open() might be different from the page size
+ * used in the swap file, we must get it from block 0. But to read block
+ * 0 we need a page size. Use the minimal size for block 0 here, it will
+ * be set to the real value below.
+ */
+ mfp->mf_page_size = MIN_SWAP_PAGE_SIZE;
+
+/*
+ * try to read block 0
+ */
+ if ((hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL)
+ {
+ msg_start();
+ MSG_PUTS_ATTR(_("Unable to read block 0 from "), attr | MSG_HIST);
+ msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST);
+ MSG_PUTS_ATTR(
+ _("\nMaybe no changes were made or Vim did not update the swap file."),
+ attr | MSG_HIST);
+ msg_end();
+ goto theend;
+ }
+ b0p = (ZERO_BL *)(hp->bh_data);
+ if (STRNCMP(b0p->b0_version, "VIM 3.0", 7) == 0)
+ {
+ msg_start();
+ msg_outtrans_attr(mfp->mf_fname, MSG_HIST);
+ MSG_PUTS_ATTR(_(" cannot be used with this version of Vim.\n"),
+ MSG_HIST);
+ MSG_PUTS_ATTR(_("Use Vim version 3.0.\n"), MSG_HIST);
+ msg_end();
+ goto theend;
+ }
+ if (b0p->b0_id[0] != BLOCK0_ID0 || b0p->b0_id[1] != BLOCK0_ID1)
+ {
+ EMSG2(_("E307: %s does not look like a Vim swap file"), mfp->mf_fname);
+ goto theend;
+ }
+ if (b0_magic_wrong(b0p))
+ {
+ msg_start();
+ msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST);
+#if defined(MSDOS) || defined(MSWIN)
+ if (STRNCMP(b0p->b0_hname, "PC ", 3) == 0)
+ MSG_PUTS_ATTR(_(" cannot be used with this version of Vim.\n"),
+ attr | MSG_HIST);
+ else
+#endif
+ MSG_PUTS_ATTR(_(" cannot be used on this computer.\n"),
+ attr | MSG_HIST);
+ MSG_PUTS_ATTR(_("The file was created on "), attr | MSG_HIST);
+ /* avoid going past the end of a currupted hostname */
+ b0p->b0_fname[0] = NUL;
+ MSG_PUTS_ATTR(b0p->b0_hname, attr | MSG_HIST);
+ MSG_PUTS_ATTR(_(",\nor the file has been damaged."), attr | MSG_HIST);
+ msg_end();
+ goto theend;
+ }
+ /*
+ * If we guessed the wrong page size, we have to recalculate the
+ * highest block number in the file.
+ */
+ if (mfp->mf_page_size != (unsigned)char_to_long(b0p->b0_page_size))
+ {
+ mf_new_page_size(mfp, (unsigned)char_to_long(b0p->b0_page_size));
+ if ((size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0)
+ mfp->mf_blocknr_max = 0; /* no file or empty file */
+ else
+ mfp->mf_blocknr_max = (blocknr_T)(size / mfp->mf_page_size);
+ mfp->mf_infile_count = mfp->mf_blocknr_max;
+ }
+
+/*
+ * If .swp file name given directly, use name from swap file for buffer.
+ */
+ if (directly)
+ {
+ expand_env(b0p->b0_fname, NameBuff, MAXPATHL);
+ if (setfname(curbuf, NameBuff, NULL, TRUE) == FAIL)
+ goto theend;
+ }
+
+ home_replace(NULL, mfp->mf_fname, NameBuff, MAXPATHL, TRUE);
+ msg_str((char_u *)_("Using swap file \"%s\""), NameBuff);
+
+ if (buf_spname(curbuf) != NULL)
+ STRCPY(NameBuff, buf_spname(curbuf));
+ else
+ home_replace(NULL, curbuf->b_ffname, NameBuff, MAXPATHL, TRUE);
+ msg_str((char_u *)_("Original file \"%s\""), NameBuff);
+ msg_putchar('\n');
+
+/*
+ * check date of swap file and original file
+ */
+ mtime = char_to_long(b0p->b0_mtime);
+ if (curbuf->b_ffname != NULL
+ && mch_stat((char *)curbuf->b_ffname, &org_stat) != -1
+ && ((mch_stat((char *)mfp->mf_fname, &swp_stat) != -1
+ && org_stat.st_mtime > swp_stat.st_mtime)
+ || org_stat.st_mtime != mtime))
+ {
+ EMSG(_("E308: Warning: Original file may have been changed"));
+ }
+ out_flush();
+ mf_put(mfp, hp, FALSE, FALSE); /* release block 0 */
+ hp = NULL;
+
+ /*
+ * Now that we are sure that the file is going to be recovered, clear the
+ * contents of the current buffer.
+ */
+ while (!(curbuf->b_ml.ml_flags & ML_EMPTY))
+ ml_delete((linenr_T)1, FALSE);
+
+ /*
+ * Try reading the original file to obtain the values of 'fileformat',
+ * 'fileencoding', etc. Ignore errors. The text itself is not used.
+ */
+ if (curbuf->b_ffname != NULL)
+ {
+ (void)readfile(curbuf->b_ffname, NULL, (linenr_T)0,
+ (linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW);
+ while (!(curbuf->b_ml.ml_flags & ML_EMPTY))
+ ml_delete((linenr_T)1, FALSE);
+ }
+
+ bnum = 1; /* start with block 1 */
+ page_count = 1; /* which is 1 page */
+ lnum = 0; /* append after line 0 in curbuf */
+ line_count = 0;
+ idx = 0; /* start with first index in block 1 */
+ error = 0;
+ buf->b_ml.ml_stack_top = 0;
+ buf->b_ml.ml_stack = NULL;
+ buf->b_ml.ml_stack_size = 0; /* no stack yet */
+
+ if (curbuf->b_ffname == NULL)
+ cannot_open = TRUE;
+ else
+ cannot_open = FALSE;
+
+ serious_error = FALSE;
+ for ( ; !got_int; line_breakcheck())
+ {
+ if (hp != NULL)
+ mf_put(mfp, hp, FALSE, FALSE); /* release previous block */
+
+ /*
+ * get block
+ */
+ if ((hp = mf_get(mfp, (blocknr_T)bnum, page_count)) == NULL)
+ {
+ if (bnum == 1)
+ {
+ EMSG2(_("E309: Unable to read block 1 from %s"), mfp->mf_fname);
+ goto theend;
+ }
+ ++error;
+ ml_append(lnum++, (char_u *)_("???MANY LINES MISSING"),
+ (colnr_T)0, TRUE);
+ }
+ else /* there is a block */
+ {
+ pp = (PTR_BL *)(hp->bh_data);
+ if (pp->pb_id == PTR_ID) /* it is a pointer block */
+ {
+ /* check line count when using pointer block first time */
+ if (idx == 0 && line_count != 0)
+ {
+ for (i = 0; i < (int)pp->pb_count; ++i)
+ line_count -= pp->pb_pointer[i].pe_line_count;
+ if (line_count != 0)
+ {
+ ++error;
+ ml_append(lnum++, (char_u *)_("???LINE COUNT WRONG"),
+ (colnr_T)0, TRUE);
+ }
+ }
+
+ if (pp->pb_count == 0)
+ {
+ ml_append(lnum++, (char_u *)_("???EMPTY BLOCK"),
+ (colnr_T)0, TRUE);
+ ++error;
+ }
+ else if (idx < (int)pp->pb_count) /* go a block deeper */
+ {
+ if (pp->pb_pointer[idx].pe_bnum < 0)
+ {
+ /*
+ * Data block with negative block number.
+ * Try to read lines from the original file.
+ * This is slow, but it works.
+ */
+ if (!cannot_open)
+ {
+ line_count = pp->pb_pointer[idx].pe_line_count;
+ if (readfile(curbuf->b_ffname, NULL, lnum,
+ pp->pb_pointer[idx].pe_old_lnum - 1,
+ line_count, NULL, 0) == FAIL)
+ cannot_open = TRUE;
+ else
+ lnum += line_count;
+ }
+ if (cannot_open)
+ {
+ ++error;
+ ml_append(lnum++, (char_u *)_("???LINES MISSING"),
+ (colnr_T)0, TRUE);
+ }
+ ++idx; /* get same block again for next index */
+ continue;
+ }
+
+ /*
+ * going one block deeper in the tree
+ */
+ if ((top = ml_add_stack(buf)) < 0) /* new entry in stack */
+ {
+ ++error;
+ break; /* out of memory */
+ }
+ ip = &(buf->b_ml.ml_stack[top]);
+ ip->ip_bnum = bnum;
+ ip->ip_index = idx;
+
+ bnum = pp->pb_pointer[idx].pe_bnum;
+ line_count = pp->pb_pointer[idx].pe_line_count;
+ page_count = pp->pb_pointer[idx].pe_page_count;
+ continue;
+ }
+ }
+ else /* not a pointer block */
+ {
+ dp = (DATA_BL *)(hp->bh_data);
+ if (dp->db_id != DATA_ID) /* block id wrong */
+ {
+ if (bnum == 1)
+ {
+ EMSG2(_("E310: Block 1 ID wrong (%s not a .swp file?)"),
+ mfp->mf_fname);
+ goto theend;
+ }
+ ++error;
+ ml_append(lnum++, (char_u *)_("???BLOCK MISSING"),
+ (colnr_T)0, TRUE);
+ }
+ else
+ {
+ /*
+ * it is a data block
+ * Append all the lines in this block
+ */
+ has_error = FALSE;
+ /*
+ * check length of block
+ * if wrong, use length in pointer block
+ */
+ if (page_count * mfp->mf_page_size != dp->db_txt_end)
+ {
+ ml_append(lnum++, (char_u *)_("??? from here until ???END lines may be messed up"),
+ (colnr_T)0, TRUE);
+ ++error;
+ has_error = TRUE;
+ dp->db_txt_end = page_count * mfp->mf_page_size;
+ }
+
+ /* make sure there is a NUL at the end of the block */
+ *((char_u *)dp + dp->db_txt_end - 1) = NUL;
+
+ /*
+ * check number of lines in block
+ * if wrong, use count in data block
+ */
+ if (line_count != dp->db_line_count)
+ {
+ ml_append(lnum++, (char_u *)_("??? from here until ???END lines may have been inserted/deleted"),
+ (colnr_T)0, TRUE);
+ ++error;
+ has_error = TRUE;
+ }
+
+ for (i = 0; i < dp->db_line_count; ++i)
+ {
+ txt_start = (dp->db_index[i] & DB_INDEX_MASK);
+ if (txt_start <= HEADER_SIZE
+ || txt_start >= (int)dp->db_txt_end)
+ {
+ p = (char_u *)"???";
+ ++error;
+ }
+ else
+ p = (char_u *)dp + txt_start;
+ ml_append(lnum++, p, (colnr_T)0, TRUE);
+ }
+ if (has_error)
+ ml_append(lnum++, (char_u *)_("???END"), (colnr_T)0, TRUE);
+ }
+ }
+ }
+
+ if (buf->b_ml.ml_stack_top == 0) /* finished */
+ break;
+
+ /*
+ * go one block up in the tree
+ */
+ ip = &(buf->b_ml.ml_stack[--(buf->b_ml.ml_stack_top)]);
+ bnum = ip->ip_bnum;
+ idx = ip->ip_index + 1; /* go to next index */
+ page_count = 1;
+ }
+
+ /*
+ * The dummy line from the empty buffer will now be after the last line in
+ * the buffer. Delete it.
+ */
+ ml_delete(curbuf->b_ml.ml_line_count, FALSE);
+ curbuf->b_flags |= BF_RECOVERED;
+
+ recoverymode = FALSE;
+ if (got_int)
+ EMSG(_("E311: Recovery Interrupted"));
+ else if (error)
+ {
+ ++no_wait_return;
+ MSG(">>>>>>>>>>>>>");
+ EMSG(_("E312: Errors detected while recovering; look for lines starting with ???"));
+ --no_wait_return;
+ MSG(_("See \":help E312\" for more information."));
+ MSG(">>>>>>>>>>>>>");
+ }
+ else
+ {
+ MSG(_("Recovery completed. You should check if everything is OK."));
+ MSG_PUTS(_("\n(You might want to write out this file under another name\n"));
+ MSG_PUTS(_("and run diff with the original file to check for changes)\n"));
+ MSG_PUTS(_("Delete the .swp file afterwards.\n\n"));
+ cmdline_row = msg_row;
+ }
+ redraw_curbuf_later(NOT_VALID);
+
+theend:
+ recoverymode = FALSE;
+ if (mfp != NULL)
+ {
+ if (hp != NULL)
+ mf_put(mfp, hp, FALSE, FALSE);
+ mf_close(mfp, FALSE); /* will also vim_free(mfp->mf_fname) */
+ }
+ vim_free(buf);
+ if (serious_error && called_from_main)
+ ml_close(curbuf, TRUE);
+#ifdef FEAT_AUTOCMD
+ else
+ {
+ apply_autocmds(EVENT_BUFREADPOST, NULL, curbuf->b_fname, FALSE, curbuf);
+ apply_autocmds(EVENT_BUFWINENTER, NULL, curbuf->b_fname, FALSE, curbuf);
+ }
+#endif
+ return;
+}
+
+/*
+ * Find the names of swap files in current directory and the directory given
+ * with the 'directory' option.
+ *
+ * Used to:
+ * - list the swap files for "vim -r"
+ * - count the number of swap files when recovering
+ * - list the swap files when recovering
+ * - find the name of the n'th swap file when recovering
+ */
+ int
+recover_names(fname, list, nr)
+ char_u **fname; /* base for swap file name */
+ int list; /* when TRUE, list the swap file names */
+ int nr; /* when non-zero, return nr'th swap file name */
+{
+ int num_names;
+ char_u *(names[6]);
+ char_u *tail;
+ char_u *p;
+ int num_files;
+ int file_count = 0;
+ char_u **files;
+ int i;
+ char_u *dirp;
+ char_u *dir_name;
+
+ if (list)
+ {
+ /* use msg() to start the scrolling properly */
+ msg((char_u *)_("Swap files found:"));
+ msg_putchar('\n');
+ }
+
+ /*
+ * Do the loop for every directory in 'directory'.
+ * First allocate some memory to put the directory name in.
+ */
+ dir_name = alloc((unsigned)STRLEN(p_dir) + 1);
+ dirp = p_dir;
+ while (dir_name != NULL && *dirp)
+ {
+ /*
+ * Isolate a directory name from *dirp and put it in dir_name (we know
+ * it is large enough, so use 31000 for length).
+ * Advance dirp to next directory name.
+ */
+ (void)copy_option_part(&dirp, dir_name, 31000, ",");
+
+ if (dir_name[0] == '.' && dir_name[1] == NUL) /* check current dir */
+ {
+ if (fname == NULL || *fname == NULL)
+ {
+#ifdef VMS
+ names[0] = vim_strsave((char_u *)"*_sw%");
+#else
+# ifdef RISCOS
+ names[0] = vim_strsave((char_u *)"*_sw#");
+# else
+ names[0] = vim_strsave((char_u *)"*.sw?");
+# endif
+#endif
+#ifdef UNIX
+ /* for Unix names starting with a dot are special */
+ names[1] = vim_strsave((char_u *)".*.sw?");
+ names[2] = vim_strsave((char_u *)".sw?");
+ num_names = 3;
+#else
+# ifdef VMS
+ names[1] = vim_strsave((char_u *)".*_sw%");
+ num_names = 2;
+# else
+ num_names = 1;
+# endif
+#endif
+ }
+ else
+ num_names = recov_file_names(names, *fname, TRUE);
+ }
+ else /* check directory dir_name */
+ {
+ if (fname == NULL || *fname == NULL)
+ {
+#ifdef VMS
+ names[0] = concat_fnames(dir_name, (char_u *)"*_sw%", TRUE);
+#else
+# ifdef RISCOS
+ names[0] = concat_fnames(dir_name, (char_u *)"*_sw#", TRUE);
+# else
+ names[0] = concat_fnames(dir_name, (char_u *)"*.sw?", TRUE);
+# endif
+#endif
+#ifdef UNIX
+ /* for Unix names starting with a dot are special */
+ names[1] = concat_fnames(dir_name, (char_u *)".*.sw?", TRUE);
+ names[2] = concat_fnames(dir_name, (char_u *)".sw?", TRUE);
+ num_names = 3;
+#else
+# ifdef VMS
+ names[1] = concat_fnames(dir_name, (char_u *)".*_sw%", TRUE);
+ num_names = 2;
+# else
+ num_names = 1;
+# endif
+#endif
+ }
+ else
+ {
+#if defined(UNIX) || defined(WIN3264)
+ p = dir_name + STRLEN(dir_name);
+ if (vim_ispathsep(p[-1]) && p[-1] == p[-2])
+ {
+ /* Ends with '//', Use Full path for swap name */
+ tail = make_percent_swname(dir_name, *fname);
+ }
+ else
+#endif
+ {
+ tail = gettail(*fname);
+ tail = concat_fnames(dir_name, tail, TRUE);
+ }
+ if (tail == NULL)
+ num_names = 0;
+ else
+ {
+ num_names = recov_file_names(names, tail, FALSE);
+ vim_free(tail);
+ }
+ }
+ }
+
+ /* check for out-of-memory */
+ for (i = 0; i < num_names; ++i)
+ {
+ if (names[i] == NULL)
+ {
+ for (i = 0; i < num_names; ++i)
+ vim_free(names[i]);
+ num_names = 0;
+ }
+ }
+ if (num_names == 0)
+ num_files = 0;
+ else if (expand_wildcards(num_names, names, &num_files, &files,
+ EW_KEEPALL|EW_FILE|EW_SILENT) == FAIL)
+ num_files = 0;
+
+ /*
+ * When no swap file found, wildcard expansion might have failed (e.g.
+ * not able to execute the shell).
+ * Try finding a swap file by simply adding ".swp" to the file name.
+ */
+ if (*dirp == NUL && file_count + num_files == 0
+ && fname != NULL && *fname != NULL)
+ {
+ struct stat st;
+ char_u *swapname;
+
+#if defined(VMS) || defined(RISCOS)
+ swapname = modname(*fname, (char_u *)"_swp", FALSE);
+#else
+ swapname = modname(*fname, (char_u *)".swp", TRUE);
+#endif
+ if (swapname != NULL)
+ {
+ if (mch_stat((char *)swapname, &st) != -1) /* It exists! */
+ {
+ files = (char_u **)alloc((unsigned)sizeof(char_u *));
+ if (files != NULL)
+ {
+ files[0] = swapname;
+ swapname = NULL;
+ num_files = 1;
+ }
+ }
+ vim_free(swapname);
+ }
+ }
+
+ /*
+ * remove swapfile name of the current buffer, it must be ignored
+ */
+ if (curbuf->b_ml.ml_mfp != NULL
+ && (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL)
+ {
+ for (i = 0; i < num_files; ++i)
+ if (fullpathcmp(p, files[i], TRUE) & FPC_SAME)
+ {
+ vim_free(files[i]);
+ --num_files;
+ for ( ; i < num_files; ++i)
+ files[i] = files[i + 1];
+ }
+ }
+ if (nr)
+ {
+ file_count += num_files;
+ if (nr <= file_count)
+ {
+ *fname = vim_strsave(files[nr - 1 + num_files - file_count]);
+ dirp = (char_u *)""; /* stop searching */
+ }
+ }
+ else if (list)
+ {
+ if (dir_name[0] == '.' && dir_name[1] == NUL)
+ {
+ if (fname == NULL || *fname == NULL)
+ MSG_PUTS(_(" In current directory:\n"));
+ else
+ MSG_PUTS(_(" Using specified name:\n"));
+ }
+ else
+ {
+ MSG_PUTS(_(" In directory "));
+ msg_home_replace(dir_name);
+ MSG_PUTS(":\n");
+ }
+
+ if (num_files)
+ {
+ for (i = 0; i < num_files; ++i)
+ {
+ /* print the swap file name */
+ msg_outnum((long)++file_count);
+ MSG_PUTS(". ");
+ msg_puts(gettail(files[i]));
+ msg_putchar('\n');
+ (void)swapfile_info(files[i]);
+ }
+ }
+ else
+ MSG_PUTS(_(" -- none --\n"));
+ out_flush();
+ }
+ else
+ file_count += num_files;
+
+ for (i = 0; i < num_names; ++i)
+ vim_free(names[i]);
+ FreeWild(num_files, files);
+ }
+ vim_free(dir_name);
+ return file_count;
+}
+
+#if defined(UNIX) || defined(WIN3264) /* Need _very_ long file names */
+/*
+ * Append the full path to name with path separators made into percent
+ * signs, to dir. An unnamed buffer is handled as "" (<currentdir>/"")
+ */
+ static char_u *
+make_percent_swname(dir, name)
+ char_u *dir;
+ char_u *name;
+{
+ char_u *d, *s, *f, *p;
+
+ f = fix_fname(name != NULL ? name : (char_u *) "");
+ d = NULL;
+ if (f != NULL)
+ {
+ s = alloc((unsigned)(STRLEN(f) + 1));
+ if (s != NULL)
+ {
+ for (d = s, p = f; *p; p++, d++)
+ *d = vim_ispathsep(*p) ? '%' : *p;
+ *d = 0;
+ d = concat_fnames(dir, s, TRUE);
+ vim_free(s);
+ }
+ vim_free(f);
+ }
+ return d;
+}
+#endif
+
+#if (defined(UNIX) || defined(__EMX__) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG))
+static int process_still_running;
+#endif
+
+/*
+ * Give information about an existing swap file
+ * Returns timestamp (0 when unknown).
+ */
+ static time_t
+swapfile_info(fname)
+ char_u *fname;
+{
+ struct stat st;
+ int fd;
+ struct block0 b0;
+ time_t x = (time_t)0;
+#ifdef UNIX
+ char_u uname[B0_UNAME_SIZE];
+#endif
+
+ /* print the swap file date */
+ if (mch_stat((char *)fname, &st) != -1)
+ {
+#ifdef UNIX
+ /* print name of owner of the file */
+ if (mch_get_uname(st.st_uid, uname, B0_UNAME_SIZE) == OK)
+ {
+ MSG_PUTS(_(" owned by: "));
+ msg_outtrans(uname);
+ MSG_PUTS(_(" dated: "));
+ }
+ else
+#endif
+ MSG_PUTS(_(" dated: "));
+ x = st.st_mtime; /* Manx C can't do &st.st_mtime */
+ MSG_PUTS(ctime(&x)); /* includes '\n' */
+
+ }
+
+ /*
+ * print the original file name
+ */
+ fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
+ if (fd >= 0)
+ {
+ if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0))
+ {
+ if (STRNCMP(b0.b0_version, "VIM 3.0", 7) == 0)
+ {
+ MSG_PUTS(_(" [from Vim version 3.0]"));
+ }
+ else if (b0.b0_id[0] != BLOCK0_ID0 || b0.b0_id[1] != BLOCK0_ID1)
+ {
+ MSG_PUTS(_(" [does not look like a Vim swap file]"));
+ }
+ else
+ {
+ MSG_PUTS(_(" file name: "));
+ if (b0.b0_fname[0] == NUL)
+ MSG_PUTS(_("[No File]"));
+ else
+ msg_outtrans(b0.b0_fname);
+
+ MSG_PUTS(_("\n modified: "));
+ MSG_PUTS(b0.b0_dirty ? _("YES") : _("no"));
+
+ if (*(b0.b0_uname) != NUL)
+ {
+ MSG_PUTS(_("\n user name: "));
+ msg_outtrans(b0.b0_uname);
+ }
+
+ if (*(b0.b0_hname) != NUL)
+ {
+ if (*(b0.b0_uname) != NUL)
+ MSG_PUTS(_(" host name: "));
+ else
+ MSG_PUTS(_("\n host name: "));
+ msg_outtrans(b0.b0_hname);
+ }
+
+ if (char_to_long(b0.b0_pid) != 0L)
+ {
+ MSG_PUTS(_("\n process ID: "));
+ msg_outnum(char_to_long(b0.b0_pid));
+#if defined(UNIX) || defined(__EMX__)
+ /* EMX kill() not working correctly, it seems */
+ if (kill((pid_t)char_to_long(b0.b0_pid), 0) == 0)
+ {
+ MSG_PUTS(_(" (still running)"));
+# if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ process_still_running = TRUE;
+# endif
+ }
+#endif
+ }
+
+ if (b0_magic_wrong(&b0))
+ {
+#if defined(MSDOS) || defined(MSWIN)
+ if (STRNCMP(b0.b0_hname, "PC ", 3) == 0)
+ MSG_PUTS(_("\n [not usable with this version of Vim]"));
+ else
+#endif
+ MSG_PUTS(_("\n [not usable on this computer]"));
+ }
+ }
+ }
+ else
+ MSG_PUTS(_(" [cannot be read]"));
+ close(fd);
+ }
+ else
+ MSG_PUTS(_(" [cannot be opened]"));
+ msg_putchar('\n');
+
+ return x;
+}
+
+ static int
+recov_file_names(names, path, prepend_dot)
+ char_u **names;
+ char_u *path;
+ int prepend_dot;
+{
+ int num_names;
+
+#ifdef SHORT_FNAME
+ /*
+ * (MS-DOS) always short names
+ */
+ names[0] = modname(path, (char_u *)".sw?", FALSE);
+ num_names = 1;
+#else /* !SHORT_FNAME */
+ /*
+ * (Win32 and Win64) never short names, but do prepend a dot.
+ * (Not MS-DOS or Win32 or Win64) maybe short name, maybe not: Try both.
+ * Only use the short name if it is different.
+ */
+ char_u *p;
+ int i;
+# ifndef WIN3264
+ int shortname = curbuf->b_shortname;
+
+ curbuf->b_shortname = FALSE;
+# endif
+
+ num_names = 0;
+
+ /*
+ * May also add the file name with a dot prepended, for swap file in same
+ * dir as original file.
+ */
+ if (prepend_dot)
+ {
+ names[num_names] = modname(path, (char_u *)".sw?", TRUE);
+ if (names[num_names] == NULL)
+ goto end;
+ ++num_names;
+ }
+
+ /*
+ * Form the normal swap file name pattern by appending ".sw?".
+ */
+#ifdef VMS
+ names[num_names] = concat_fnames(path, (char_u *)"_sw%", FALSE);
+#else
+# ifdef RISCOS
+ names[num_names] = concat_fnames(path, (char_u *)"_sw#", FALSE);
+# else
+ names[num_names] = concat_fnames(path, (char_u *)".sw?", FALSE);
+# endif
+#endif
+ if (names[num_names] == NULL)
+ goto end;
+ if (num_names >= 1) /* check if we have the same name twice */
+ {
+ p = names[num_names - 1];
+ i = (int)STRLEN(names[num_names - 1]) - (int)STRLEN(names[num_names]);
+ if (i > 0)
+ p += i; /* file name has been expanded to full path */
+
+ if (STRCMP(p, names[num_names]) != 0)
+ ++num_names;
+ else
+ vim_free(names[num_names]);
+ }
+ else
+ ++num_names;
+
+# ifndef WIN3264
+ /*
+ * Also try with 'shortname' set, in case the file is on a DOS filesystem.
+ */
+ curbuf->b_shortname = TRUE;
+#ifdef VMS
+ names[num_names] = modname(path, (char_u *)"_sw%", FALSE);
+#else
+# ifdef RISCOS
+ names[num_names] = modname(path, (char_u *)"_sw#", FALSE);
+# else
+ names[num_names] = modname(path, (char_u *)".sw?", FALSE);
+# endif
+#endif
+ if (names[num_names] == NULL)
+ goto end;
+
+ /*
+ * Remove the one from 'shortname', if it's the same as with 'noshortname'.
+ */
+ p = names[num_names];
+ i = STRLEN(names[num_names]) - STRLEN(names[num_names - 1]);
+ if (i > 0)
+ p += i; /* file name has been expanded to full path */
+ if (STRCMP(names[num_names - 1], p) == 0)
+ vim_free(names[num_names]);
+ else
+ ++num_names;
+# endif
+
+end:
+# ifndef WIN3264
+ curbuf->b_shortname = shortname;
+# endif
+
+#endif /* !SHORT_FNAME */
+
+ return num_names;
+}
+
+/*
+ * sync all memlines
+ *
+ * If 'check_file' is TRUE, check if original file exists and was not changed.
+ * If 'check_char' is TRUE, stop syncing when character becomes available, but
+ * always sync at least one block.
+ */
+ void
+ml_sync_all(check_file, check_char)
+ int check_file;
+ int check_char;
+{
+ buf_T *buf;
+ struct stat st;
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ if (buf->b_ml.ml_mfp == NULL || buf->b_ml.ml_mfp->mf_fname == NULL)
+ continue; /* no file */
+
+ ml_flush_line(buf); /* flush buffered line */
+ /* flush locked block */
+ (void)ml_find_line(buf, (linenr_T)0, ML_FLUSH);
+ if (bufIsChanged(buf) && check_file && mf_need_trans(buf->b_ml.ml_mfp)
+ && buf->b_ffname != NULL)
+ {
+ /*
+ * If the original file does not exist anymore or has been changed
+ * call ml_preserve() to get rid of all negative numbered blocks.
+ */
+ if (mch_stat((char *)buf->b_ffname, &st) == -1
+ || st.st_mtime != buf->b_mtime_read
+ || (size_t)st.st_size != buf->b_orig_size)
+ {
+ ml_preserve(buf, FALSE);
+ did_check_timestamps = FALSE;
+ need_check_timestamps = TRUE; /* give message later */
+ }
+ }
+ if (buf->b_ml.ml_mfp->mf_dirty)
+ {
+ (void)mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0)
+ | (bufIsChanged(buf) ? MFS_FLUSH : 0));
+ if (check_char && ui_char_avail()) /* character available now */
+ break;
+ }
+ }
+}
+
+/*
+ * sync one buffer, including negative blocks
+ *
+ * after this all the blocks are in the swap file
+ *
+ * Used for the :preserve command and when the original file has been
+ * changed or deleted.
+ *
+ * when message is TRUE the success of preserving is reported
+ */
+ void
+ml_preserve(buf, message)
+ buf_T *buf;
+ int message;
+{
+ bhdr_T *hp;
+ linenr_T lnum;
+ memfile_T *mfp = buf->b_ml.ml_mfp;
+ int status;
+ int got_int_save = got_int;
+
+ if (mfp == NULL || mfp->mf_fname == NULL)
+ {
+ if (message)
+ EMSG(_("E313: Cannot preserve, there is no swap file"));
+ return;
+ }
+
+ /* We only want to stop when interrupted here, not when interrupted
+ * before. */
+ got_int = FALSE;
+
+ ml_flush_line(buf); /* flush buffered line */
+ (void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); /* flush locked block */
+ status = mf_sync(mfp, MFS_ALL | MFS_FLUSH);
+
+ /* stack is invalid after mf_sync(.., MFS_ALL) */
+ buf->b_ml.ml_stack_top = 0;
+
+ /*
+ * Some of the data blocks may have been changed from negative to
+ * positive block number. In that case the pointer blocks need to be
+ * updated.
+ *
+ * We don't know in which pointer block the references are, so we visit
+ * all data blocks until there are no more translations to be done (or
+ * we hit the end of the file, which can only happen in case a write fails,
+ * e.g. when file system if full).
+ * ml_find_line() does the work by translating the negative block numbers
+ * when getting the first line of each data block.
+ */
+ if (mf_need_trans(mfp) && !got_int)
+ {
+ lnum = 1;
+ while (mf_need_trans(mfp) && lnum <= buf->b_ml.ml_line_count)
+ {
+ hp = ml_find_line(buf, lnum, ML_FIND);
+ if (hp == NULL)
+ {
+ status = FAIL;
+ goto theend;
+ }
+ CHECK(buf->b_ml.ml_locked_low != lnum, "low != lnum");
+ lnum = buf->b_ml.ml_locked_high + 1;
+ }
+ (void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); /* flush locked block */
+ /* sync the updated pointer blocks */
+ if (mf_sync(mfp, MFS_ALL | MFS_FLUSH) == FAIL)
+ status = FAIL;
+ buf->b_ml.ml_stack_top = 0; /* stack is invalid now */
+ }
+theend:
+ got_int |= got_int_save;
+
+ if (message)
+ {
+ if (status == OK)
+ MSG(_("File preserved"));
+ else
+ EMSG(_("E314: Preserve failed"));
+ }
+}
+
+/*
+ * NOTE: The pointer returned by the ml_get_*() functions only remains valid
+ * until the next call!
+ * line1 = ml_get(1);
+ * line2 = ml_get(2); // line1 is now invalid!
+ * Make a copy of the line if necessary.
+ */
+/*
+ * get a pointer to a (read-only copy of a) line
+ *
+ * On failure an error message is given and IObuff is returned (to avoid
+ * having to check for error everywhere).
+ */
+ char_u *
+ml_get(lnum)
+ linenr_T lnum;
+{
+ return ml_get_buf(curbuf, lnum, FALSE);
+}
+
+/*
+ * ml_get_pos: get pointer to position 'pos'
+ */
+ char_u *
+ml_get_pos(pos)
+ pos_T *pos;
+{
+ return (ml_get_buf(curbuf, pos->lnum, FALSE) + pos->col);
+}
+
+/*
+ * ml_get_curline: get pointer to cursor line.
+ */
+ char_u *
+ml_get_curline()
+{
+ return ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE);
+}
+
+/*
+ * ml_get_cursor: get pointer to cursor position
+ */
+ char_u *
+ml_get_cursor()
+{
+ return (ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE) +
+ curwin->w_cursor.col);
+}
+
+/*
+ * get a pointer to a line in a specific buffer
+ *
+ * "will_change": if TRUE mark the buffer dirty (chars in the line will be
+ * changed)
+ */
+ char_u *
+ml_get_buf(buf, lnum, will_change)
+ buf_T *buf;
+ linenr_T lnum;
+ int will_change; /* line will be changed */
+{
+ bhdr_T *hp;
+ DATA_BL *dp;
+ char_u *ptr;
+
+ if (lnum > buf->b_ml.ml_line_count) /* invalid line number */
+ {
+ EMSGN(_("E315: ml_get: invalid lnum: %ld"), lnum);
+errorret:
+ STRCPY(IObuff, "???");
+ return IObuff;
+ }
+ if (lnum <= 0) /* pretend line 0 is line 1 */
+ lnum = 1;
+
+ if (buf->b_ml.ml_mfp == NULL) /* there are no lines */
+ return (char_u *)"";
+
+/*
+ * See if it is the same line as requested last time.
+ * Otherwise may need to flush last used line.
+ */
+ if (buf->b_ml.ml_line_lnum != lnum)
+ {
+ ml_flush_line(buf);
+
+ /*
+ * Find the data block containing the line.
+ * This also fills the stack with the blocks from the root to the data
+ * block and releases any locked block.
+ */
+ if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL)
+ {
+ EMSGN(_("E316: ml_get: cannot find line %ld"), lnum);
+ goto errorret;
+ }
+
+ dp = (DATA_BL *)(hp->bh_data);
+
+ ptr = (char_u *)dp + ((dp->db_index[lnum - buf->b_ml.ml_locked_low]) & DB_INDEX_MASK);
+ buf->b_ml.ml_line_ptr = ptr;
+ buf->b_ml.ml_line_lnum = lnum;
+ buf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
+ }
+ if (will_change)
+ buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
+
+ return buf->b_ml.ml_line_ptr;
+}
+
+/*
+ * Check if a line that was just obtained by a call to ml_get
+ * is in allocated memory.
+ */
+ int
+ml_line_alloced()
+{
+ return (curbuf->b_ml.ml_flags & ML_LINE_DIRTY);
+}
+
+/*
+ * Append a line after lnum (may be 0 to insert a line in front of the file).
+ * "line" does not need to be allocated, but can't be another line in a
+ * buffer, unlocking may make it invalid.
+ *
+ * newfile: TRUE when starting to edit a new file, meaning that pe_old_lnum
+ * will be set for recovery
+ * Check: The caller of this function should probably also call
+ * appended_lines().
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+ml_append(lnum, line, len, newfile)
+ linenr_T lnum; /* append after this line (can be 0) */
+ char_u *line; /* text of the new line */
+ colnr_T len; /* length of new line, including NUL, or 0 */
+ int newfile; /* flag, see above */
+{
+ /* When starting up, we might still need to create the memfile */
+ if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL) == FAIL)
+ return FAIL;
+
+ if (curbuf->b_ml.ml_line_lnum != 0)
+ ml_flush_line(curbuf);
+ return ml_append_int(curbuf, lnum, line, len, newfile, FALSE);
+}
+
+ static int
+ml_append_int(buf, lnum, line, len, newfile, mark)
+ buf_T *buf;
+ linenr_T lnum; /* append after this line (can be 0) */
+ char_u *line; /* text of the new line */
+ colnr_T len; /* length of line, including NUL, or 0 */
+ int newfile; /* flag, see above */
+ int mark; /* mark the new line */
+{
+ int i;
+ int line_count; /* number of indexes in current block */
+ int offset;
+ int from, to;
+ int space_needed; /* space needed for new line */
+ int page_size;
+ int page_count;
+ int db_idx; /* index for lnum in data block */
+ bhdr_T *hp;
+ memfile_T *mfp;
+ DATA_BL *dp;
+ PTR_BL *pp;
+ infoptr_T *ip;
+
+ /* lnum out of range */
+ if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL)
+ return FAIL;
+
+ if (lowest_marked && lowest_marked > lnum)
+ lowest_marked = lnum + 1;
+
+ if (len == 0)
+ len = (colnr_T)STRLEN(line) + 1; /* space needed for the text */
+ space_needed = len + INDEX_SIZE; /* space needed for text + index */
+
+ mfp = buf->b_ml.ml_mfp;
+ page_size = mfp->mf_page_size;
+
+/*
+ * find the data block containing the previous line
+ * This also fills the stack with the blocks from the root to the data block
+ * This also releases any locked block.
+ */
+ if ((hp = ml_find_line(buf, lnum == 0 ? (linenr_T)1 : lnum,
+ ML_INSERT)) == NULL)
+ return FAIL;
+
+ buf->b_ml.ml_flags &= ~ML_EMPTY;
+
+ if (lnum == 0) /* got line one instead, correct db_idx */
+ db_idx = -1; /* careful, it is negative! */
+ else
+ db_idx = lnum - buf->b_ml.ml_locked_low;
+ /* get line count before the insertion */
+ line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;
+
+ dp = (DATA_BL *)(hp->bh_data);
+
+/*
+ * If
+ * - there is not enough room in the current block
+ * - appending to the last line in the block
+ * - not appending to the last line in the file
+ * insert in front of the next block.
+ */
+ if ((int)dp->db_free < space_needed && db_idx == line_count - 1
+ && lnum < buf->b_ml.ml_line_count)
+ {
+ /*
+ * Now that the line is not going to be inserted in the block that we
+ * expected, the line count has to be adjusted in the pointer blocks
+ * by using ml_locked_lineadd.
+ */
+ --(buf->b_ml.ml_locked_lineadd);
+ --(buf->b_ml.ml_locked_high);
+ if ((hp = ml_find_line(buf, lnum + 1, ML_INSERT)) == NULL)
+ return FAIL;
+
+ db_idx = -1; /* careful, it is negative! */
+ /* get line count before the insertion */
+ line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;
+ CHECK(buf->b_ml.ml_locked_low != lnum + 1, "locked_low != lnum + 1");
+
+ dp = (DATA_BL *)(hp->bh_data);
+ }
+
+ ++buf->b_ml.ml_line_count;
+
+ if ((int)dp->db_free >= space_needed) /* enough room in data block */
+ {
+/*
+ * Insert new line in existing data block, or in data block allocated above.
+ */
+ dp->db_txt_start -= len;
+ dp->db_free -= space_needed;
+ ++(dp->db_line_count);
+
+ /*
+ * move the text of the lines that follow to the front
+ * adjust the indexes of the lines that follow
+ */
+ if (line_count > db_idx + 1) /* if there are following lines */
+ {
+ /*
+ * Offset is the start of the previous line.
+ * This will become the character just after the new line.
+ */
+ if (db_idx < 0)
+ offset = dp->db_txt_end;
+ else
+ offset = ((dp->db_index[db_idx]) & DB_INDEX_MASK);
+ mch_memmove((char *)dp + dp->db_txt_start,
+ (char *)dp + dp->db_txt_start + len,
+ (size_t)(offset - (dp->db_txt_start + len)));
+ for (i = line_count - 1; i > db_idx; --i)
+ dp->db_index[i + 1] = dp->db_index[i] - len;
+ dp->db_index[db_idx + 1] = offset - len;
+ }
+ else /* add line at the end */
+ dp->db_index[db_idx + 1] = dp->db_txt_start;
+
+ /*
+ * copy the text into the block
+ */
+ mch_memmove((char *)dp + dp->db_index[db_idx + 1], line, (size_t)len);
+ if (mark)
+ dp->db_index[db_idx + 1] |= DB_MARKED;
+
+ /*
+ * Mark the block dirty.
+ */
+ buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
+ if (!newfile)
+ buf->b_ml.ml_flags |= ML_LOCKED_POS;
+ }
+ else /* not enough space in data block */
+ {
+/*
+ * If there is not enough room we have to create a new data block and copy some
+ * lines into it.
+ * Then we have to insert an entry in the pointer block.
+ * If this pointer block also is full, we go up another block, and so on, up
+ * to the root if necessary.
+ * The line counts in the pointer blocks have already been adjusted by
+ * ml_find_line().
+ */
+ long line_count_left, line_count_right;
+ int page_count_left, page_count_right;
+ bhdr_T *hp_left;
+ bhdr_T *hp_right;
+ bhdr_T *hp_new;
+ int lines_moved;
+ int data_moved = 0; /* init to shut up gcc */
+ int total_moved = 0; /* init to shut up gcc */
+ DATA_BL *dp_right, *dp_left;
+ int stack_idx;
+ int in_left;
+ int lineadd;
+ blocknr_T bnum_left, bnum_right;
+ linenr_T lnum_left, lnum_right;
+ int pb_idx;
+ PTR_BL *pp_new;
+
+ /*
+ * We are going to allocate a new data block. Depending on the
+ * situation it will be put to the left or right of the existing
+ * block. If possible we put the new line in the left block and move
+ * the lines after it to the right block. Otherwise the new line is
+ * also put in the right block. This method is more efficient when
+ * inserting a lot of lines at one place.
+ */
+ if (db_idx < 0) /* left block is new, right block is existing */
+ {
+ lines_moved = 0;
+ in_left = TRUE;
+ /* space_needed does not change */
+ }
+ else /* left block is existing, right block is new */
+ {
+ lines_moved = line_count - db_idx - 1;
+ if (lines_moved == 0)
+ in_left = FALSE; /* put new line in right block */
+ /* space_needed does not change */
+ else
+ {
+ data_moved = ((dp->db_index[db_idx]) & DB_INDEX_MASK) -
+ dp->db_txt_start;
+ total_moved = data_moved + lines_moved * INDEX_SIZE;
+ if ((int)dp->db_free + total_moved >= space_needed)
+ {
+ in_left = TRUE; /* put new line in left block */
+ space_needed = total_moved;
+ }
+ else
+ {
+ in_left = FALSE; /* put new line in right block */
+ space_needed += total_moved;
+ }
+ }
+ }
+
+ page_count = ((space_needed + HEADER_SIZE) + page_size - 1) / page_size;
+ if ((hp_new = ml_new_data(mfp, newfile, page_count)) == NULL)
+ {
+ /* correct line counts in pointer blocks */
+ --(buf->b_ml.ml_locked_lineadd);
+ --(buf->b_ml.ml_locked_high);
+ return FAIL;
+ }
+ if (db_idx < 0) /* left block is new */
+ {
+ hp_left = hp_new;
+ hp_right = hp;
+ line_count_left = 0;
+ line_count_right = line_count;
+ }
+ else /* right block is new */
+ {
+ hp_left = hp;
+ hp_right = hp_new;
+ line_count_left = line_count;
+ line_count_right = 0;
+ }
+ dp_right = (DATA_BL *)(hp_right->bh_data);
+ dp_left = (DATA_BL *)(hp_left->bh_data);
+ bnum_left = hp_left->bh_bnum;
+ bnum_right = hp_right->bh_bnum;
+ page_count_left = hp_left->bh_page_count;
+ page_count_right = hp_right->bh_page_count;
+
+ /*
+ * May move the new line into the right/new block.
+ */
+ if (!in_left)
+ {
+ dp_right->db_txt_start -= len;
+ dp_right->db_free -= len + INDEX_SIZE;
+ dp_right->db_index[0] = dp_right->db_txt_start;
+ if (mark)
+ dp_right->db_index[0] |= DB_MARKED;
+
+ mch_memmove((char *)dp_right + dp_right->db_txt_start,
+ line, (size_t)len);
+ ++line_count_right;
+ }
+ /*
+ * may move lines from the left/old block to the right/new one.
+ */
+ if (lines_moved)
+ {
+ /*
+ */
+ dp_right->db_txt_start -= data_moved;
+ dp_right->db_free -= total_moved;
+ mch_memmove((char *)dp_right + dp_right->db_txt_start,
+ (char *)dp_left + dp_left->db_txt_start,
+ (size_t)data_moved);
+ offset = dp_right->db_txt_start - dp_left->db_txt_start;
+ dp_left->db_txt_start += data_moved;
+ dp_left->db_free += total_moved;
+
+ /*
+ * update indexes in the new block
+ */
+ for (to = line_count_right, from = db_idx + 1;
+ from < line_count_left; ++from, ++to)
+ dp_right->db_index[to] = dp->db_index[from] + offset;
+ line_count_right += lines_moved;
+ line_count_left -= lines_moved;
+ }
+
+ /*
+ * May move the new line into the left (old or new) block.
+ */
+ if (in_left)
+ {
+ dp_left->db_txt_start -= len;
+ dp_left->db_free -= len + INDEX_SIZE;
+ dp_left->db_index[line_count_left] = dp_left->db_txt_start;
+ if (mark)
+ dp_left->db_index[line_count_left] |= DB_MARKED;
+ mch_memmove((char *)dp_left + dp_left->db_txt_start,
+ line, (size_t)len);
+ ++line_count_left;
+ }
+
+ if (db_idx < 0) /* left block is new */
+ {
+ lnum_left = lnum + 1;
+ lnum_right = 0;
+ }
+ else /* right block is new */
+ {
+ lnum_left = 0;
+ if (in_left)
+ lnum_right = lnum + 2;
+ else
+ lnum_right = lnum + 1;
+ }
+ dp_left->db_line_count = line_count_left;
+ dp_right->db_line_count = line_count_right;
+
+ /*
+ * release the two data blocks
+ * The new one (hp_new) already has a correct blocknumber.
+ * The old one (hp, in ml_locked) gets a positive blocknumber if
+ * we changed it and we are not editing a new file.
+ */
+ if (lines_moved || in_left)
+ buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
+ if (!newfile && db_idx >= 0 && in_left)
+ buf->b_ml.ml_flags |= ML_LOCKED_POS;
+ mf_put(mfp, hp_new, TRUE, FALSE);
+
+ /*
+ * flush the old data block
+ * set ml_locked_lineadd to 0, because the updating of the
+ * pointer blocks is done below
+ */
+ lineadd = buf->b_ml.ml_locked_lineadd;
+ buf->b_ml.ml_locked_lineadd = 0;
+ ml_find_line(buf, (linenr_T)0, ML_FLUSH); /* flush data block */
+
+ /*
+ * update pointer blocks for the new data block
+ */
+ for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0;
+ --stack_idx)
+ {
+ ip = &(buf->b_ml.ml_stack[stack_idx]);
+ pb_idx = ip->ip_index;
+ if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
+ return FAIL;
+ pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */
+ if (pp->pb_id != PTR_ID)
+ {
+ EMSG(_("E317: pointer block id wrong 3"));
+ mf_put(mfp, hp, FALSE, FALSE);
+ return FAIL;
+ }
+ /*
+ * TODO: If the pointer block is full and we are adding at the end
+ * try to insert in front of the next block
+ */
+ /* block not full, add one entry */
+ if (pp->pb_count < pp->pb_count_max)
+ {
+ if (pb_idx + 1 < (int)pp->pb_count)
+ mch_memmove(&pp->pb_pointer[pb_idx + 2],
+ &pp->pb_pointer[pb_idx + 1],
+ (size_t)(pp->pb_count - pb_idx - 1) * sizeof(PTR_EN));
+ ++pp->pb_count;
+ pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
+ pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
+ pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
+ pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
+ pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
+ pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
+
+ if (lnum_left != 0)
+ pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
+ if (lnum_right != 0)
+ pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
+
+ mf_put(mfp, hp, TRUE, FALSE);
+ buf->b_ml.ml_stack_top = stack_idx + 1; /* truncate stack */
+
+ if (lineadd)
+ {
+ --(buf->b_ml.ml_stack_top);
+ /* fix line count for rest of blocks in the stack */
+ ml_lineadd(buf, lineadd);
+ /* fix stack itself */
+ buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
+ lineadd;
+ ++(buf->b_ml.ml_stack_top);
+ }
+
+ /*
+ * We are finished, break the loop here.
+ */
+ break;
+ }
+ else /* pointer block full */
+ {
+ /*
+ * split the pointer block
+ * allocate a new pointer block
+ * move some of the pointer into the new block
+ * prepare for updating the parent block
+ */
+ for (;;) /* do this twice when splitting block 1 */
+ {
+ hp_new = ml_new_ptr(mfp);
+ if (hp_new == NULL) /* TODO: try to fix tree */
+ return FAIL;
+ pp_new = (PTR_BL *)(hp_new->bh_data);
+
+ if (hp->bh_bnum != 1)
+ break;
+
+ /*
+ * if block 1 becomes full the tree is given an extra level
+ * The pointers from block 1 are moved into the new block.
+ * block 1 is updated to point to the new block
+ * then continue to split the new block
+ */
+ mch_memmove(pp_new, pp, (size_t)page_size);
+ pp->pb_count = 1;
+ pp->pb_pointer[0].pe_bnum = hp_new->bh_bnum;
+ pp->pb_pointer[0].pe_line_count = buf->b_ml.ml_line_count;
+ pp->pb_pointer[0].pe_old_lnum = 1;
+ pp->pb_pointer[0].pe_page_count = 1;
+ mf_put(mfp, hp, TRUE, FALSE); /* release block 1 */
+ hp = hp_new; /* new block is to be split */
+ pp = pp_new;
+ CHECK(stack_idx != 0, _("stack_idx should be 0"));
+ ip->ip_index = 0;
+ ++stack_idx; /* do block 1 again later */
+ }
+ /*
+ * move the pointers after the current one to the new block
+ * If there are none, the new entry will be in the new block.
+ */
+ total_moved = pp->pb_count - pb_idx - 1;
+ if (total_moved)
+ {
+ mch_memmove(&pp_new->pb_pointer[0],
+ &pp->pb_pointer[pb_idx + 1],
+ (size_t)(total_moved) * sizeof(PTR_EN));
+ pp_new->pb_count = total_moved;
+ pp->pb_count -= total_moved - 1;
+ pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
+ pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
+ pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
+ if (lnum_right)
+ pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
+ }
+ else
+ {
+ pp_new->pb_count = 1;
+ pp_new->pb_pointer[0].pe_bnum = bnum_right;
+ pp_new->pb_pointer[0].pe_line_count = line_count_right;
+ pp_new->pb_pointer[0].pe_page_count = page_count_right;
+ pp_new->pb_pointer[0].pe_old_lnum = lnum_right;
+ }
+ pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
+ pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
+ pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
+ if (lnum_left)
+ pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
+ lnum_left = 0;
+ lnum_right = 0;
+
+ /*
+ * recompute line counts
+ */
+ line_count_right = 0;
+ for (i = 0; i < (int)pp_new->pb_count; ++i)
+ line_count_right += pp_new->pb_pointer[i].pe_line_count;
+ line_count_left = 0;
+ for (i = 0; i < (int)pp->pb_count; ++i)
+ line_count_left += pp->pb_pointer[i].pe_line_count;
+
+ bnum_left = hp->bh_bnum;
+ bnum_right = hp_new->bh_bnum;
+ page_count_left = 1;
+ page_count_right = 1;
+ mf_put(mfp, hp, TRUE, FALSE);
+ mf_put(mfp, hp_new, TRUE, FALSE);
+ }
+ }
+
+ /*
+ * Safety check: fallen out of for loop?
+ */
+ if (stack_idx < 0)
+ {
+ EMSG(_("E318: Updated too many blocks?"));
+ buf->b_ml.ml_stack_top = 0; /* invalidate stack */
+ }
+ }
+
+#ifdef FEAT_BYTEOFF
+ /* The line was inserted below 'lnum' */
+ ml_updatechunk(buf, lnum + 1, (long)len, ML_CHNK_ADDLINE);
+#endif
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ {
+ if (STRLEN(line) > 0)
+ netbeans_inserted(buf, lnum+1, (colnr_T)0, 0, line, STRLEN(line));
+ netbeans_inserted(buf, lnum+1, (colnr_T)STRLEN(line), 0,
+ (char_u *)"\n", 1);
+ }
+#endif
+ return OK;
+}
+
+/*
+ * replace line lnum, with buffering, in current buffer
+ *
+ * If copy is TRUE, make a copy of the line, otherwise the line has been
+ * copied to allocated memory already.
+ *
+ * Check: The caller of this function should probably also call
+ * changed_lines(), unless update_screen(NOT_VALID) is used.
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+ml_replace(lnum, line, copy)
+ linenr_T lnum;
+ char_u *line;
+ int copy;
+{
+ if (line == NULL) /* just checking... */
+ return FAIL;
+
+ /* When starting up, we might still need to create the memfile */
+ if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL) == FAIL)
+ return FAIL;
+
+ if (copy && (line = vim_strsave(line)) == NULL) /* allocate memory */
+ return FAIL;
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ {
+ netbeans_removed(curbuf, lnum, 0, (long)STRLEN(ml_get(lnum)));
+ netbeans_inserted(curbuf, lnum, 0, 0, line, STRLEN(line));
+ }
+#endif
+ if (curbuf->b_ml.ml_line_lnum != lnum) /* other line buffered */
+ ml_flush_line(curbuf); /* flush it */
+ else if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) /* same line allocated */
+ vim_free(curbuf->b_ml.ml_line_ptr); /* free it */
+ curbuf->b_ml.ml_line_ptr = line;
+ curbuf->b_ml.ml_line_lnum = lnum;
+ curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
+
+ return OK;
+}
+
+/*
+ * delete line 'lnum'
+ *
+ * Check: The caller of this function should probably also call
+ * deleted_lines() after this.
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+ml_delete(lnum, message)
+ linenr_T lnum;
+ int message;
+{
+ ml_flush_line(curbuf);
+ return ml_delete_int(curbuf, lnum, message);
+}
+
+ static int
+ml_delete_int(buf, lnum, message)
+ buf_T *buf;
+ linenr_T lnum;
+ int message;
+{
+ bhdr_T *hp;
+ memfile_T *mfp;
+ DATA_BL *dp;
+ PTR_BL *pp;
+ infoptr_T *ip;
+ int count; /* number of entries in block */
+ int idx;
+ int stack_idx;
+ int text_start;
+ int line_start;
+ long line_size;
+ int i;
+
+ if (lnum < 1 || lnum > buf->b_ml.ml_line_count)
+ return FAIL;
+
+ if (lowest_marked && lowest_marked > lnum)
+ lowest_marked--;
+
+/*
+ * If the file becomes empty the last line is replaced by an empty line.
+ */
+ if (buf->b_ml.ml_line_count == 1) /* file becomes empty */
+ {
+ if (message
+#ifdef FEAT_NETBEANS_INTG
+ && !netbeansSuppressNoLines
+#endif
+ )
+ {
+ set_keep_msg((char_u *)_(no_lines_msg));
+ keep_msg_attr = 0;
+ }
+ /* FEAT_BYTEOFF already handled in there, dont worry 'bout it below */
+ i = ml_replace((linenr_T)1, (char_u *)"", TRUE);
+ buf->b_ml.ml_flags |= ML_EMPTY;
+
+ return i;
+ }
+
+/*
+ * find the data block containing the line
+ * This also fills the stack with the blocks from the root to the data block
+ * This also releases any locked block.
+ */
+ mfp = buf->b_ml.ml_mfp;
+ if (mfp == NULL)
+ return FAIL;
+
+ if ((hp = ml_find_line(buf, lnum, ML_DELETE)) == NULL)
+ return FAIL;
+
+ dp = (DATA_BL *)(hp->bh_data);
+ /* compute line count before the delete */
+ count = (long)(buf->b_ml.ml_locked_high)
+ - (long)(buf->b_ml.ml_locked_low) + 2;
+ idx = lnum - buf->b_ml.ml_locked_low;
+
+ --buf->b_ml.ml_line_count;
+
+ line_start = ((dp->db_index[idx]) & DB_INDEX_MASK);
+ if (idx == 0) /* first line in block, text at the end */
+ line_size = dp->db_txt_end - line_start;
+ else
+ line_size = ((dp->db_index[idx - 1]) & DB_INDEX_MASK) - line_start;
+
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ netbeans_removed(buf, lnum, 0, line_size);
+#endif
+
+/*
+ * special case: If there is only one line in the data block it becomes empty.
+ * Then we have to remove the entry, pointing to this data block, from the
+ * pointer block. If this pointer block also becomes empty, we go up another
+ * block, and so on, up to the root if necessary.
+ * The line counts in the pointer blocks have already been adjusted by
+ * ml_find_line().
+ */
+ if (count == 1)
+ {
+ mf_free(mfp, hp); /* free the data block */
+ buf->b_ml.ml_locked = NULL;
+
+ for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; --stack_idx)
+ {
+ buf->b_ml.ml_stack_top = 0; /* stack is invalid when failing */
+ ip = &(buf->b_ml.ml_stack[stack_idx]);
+ idx = ip->ip_index;
+ if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
+ return FAIL;
+ pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */
+ if (pp->pb_id != PTR_ID)
+ {
+ EMSG(_("E317: pointer block id wrong 4"));
+ mf_put(mfp, hp, FALSE, FALSE);
+ return FAIL;
+ }
+ count = --(pp->pb_count);
+ if (count == 0) /* the pointer block becomes empty! */
+ mf_free(mfp, hp);
+ else
+ {
+ if (count != idx) /* move entries after the deleted one */
+ mch_memmove(&pp->pb_pointer[idx], &pp->pb_pointer[idx + 1],
+ (size_t)(count - idx) * sizeof(PTR_EN));
+ mf_put(mfp, hp, TRUE, FALSE);
+
+ buf->b_ml.ml_stack_top = stack_idx; /* truncate stack */
+ /* fix line count for rest of blocks in the stack */
+ if (buf->b_ml.ml_locked_lineadd)
+ {
+ ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
+ buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
+ buf->b_ml.ml_locked_lineadd;
+ }
+ ++(buf->b_ml.ml_stack_top);
+
+ break;
+ }
+ }
+ CHECK(stack_idx < 0, _("deleted block 1?"));
+ }
+ else
+ {
+ /*
+ * delete the text by moving the next lines forwards
+ */
+ text_start = dp->db_txt_start;
+ mch_memmove((char *)dp + text_start + line_size,
+ (char *)dp + text_start, (size_t)(line_start - text_start));
+
+ /*
+ * delete the index by moving the next indexes backwards
+ * Adjust the indexes for the text movement.
+ */
+ for (i = idx; i < count - 1; ++i)
+ dp->db_index[i] = dp->db_index[i + 1] + line_size;
+
+ dp->db_free += line_size + INDEX_SIZE;
+ dp->db_txt_start += line_size;
+ --(dp->db_line_count);
+
+ /*
+ * mark the block dirty and make sure it is in the file (for recovery)
+ */
+ buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
+ }
+
+#ifdef FEAT_BYTEOFF
+ ml_updatechunk(buf, lnum, line_size, ML_CHNK_DELLINE);
+#endif
+ return OK;
+}
+
+/*
+ * set the B_MARKED flag for line 'lnum'
+ */
+ void
+ml_setmarked(lnum)
+ linenr_T lnum;
+{
+ bhdr_T *hp;
+ DATA_BL *dp;
+ /* invalid line number */
+ if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count
+ || curbuf->b_ml.ml_mfp == NULL)
+ return; /* give error message? */
+
+ if (lowest_marked == 0 || lowest_marked > lnum)
+ lowest_marked = lnum;
+
+ /*
+ * find the data block containing the line
+ * This also fills the stack with the blocks from the root to the data block
+ * This also releases any locked block.
+ */
+ if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
+ return; /* give error message? */
+
+ dp = (DATA_BL *)(hp->bh_data);
+ dp->db_index[lnum - curbuf->b_ml.ml_locked_low] |= DB_MARKED;
+ curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
+}
+
+/*
+ * find the first line with its B_MARKED flag set
+ */
+ linenr_T
+ml_firstmarked()
+{
+ bhdr_T *hp;
+ DATA_BL *dp;
+ linenr_T lnum;
+ int i;
+
+ if (curbuf->b_ml.ml_mfp == NULL)
+ return (linenr_T) 0;
+
+ /*
+ * The search starts with lowest_marked line. This is the last line where
+ * a mark was found, adjusted by inserting/deleting lines.
+ */
+ for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; )
+ {
+ /*
+ * Find the data block containing the line.
+ * This also fills the stack with the blocks from the root to the data
+ * block This also releases any locked block.
+ */
+ if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
+ return (linenr_T)0; /* give error message? */
+
+ dp = (DATA_BL *)(hp->bh_data);
+
+ for (i = lnum - curbuf->b_ml.ml_locked_low;
+ lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum)
+ if ((dp->db_index[i]) & DB_MARKED)
+ {
+ (dp->db_index[i]) &= DB_INDEX_MASK;
+ curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
+ lowest_marked = lnum + 1;
+ return lnum;
+ }
+ }
+
+ return (linenr_T) 0;
+}
+
+#if 0 /* not used */
+/*
+ * return TRUE if line 'lnum' has a mark
+ */
+ int
+ml_has_mark(lnum)
+ linenr_T lnum;
+{
+ bhdr_T *hp;
+ DATA_BL *dp;
+
+ if (curbuf->b_ml.ml_mfp == NULL
+ || (hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
+ return FALSE;
+
+ dp = (DATA_BL *)(hp->bh_data);
+ return (int)((dp->db_index[lnum - curbuf->b_ml.ml_locked_low]) & DB_MARKED);
+}
+#endif
+
+/*
+ * clear all DB_MARKED flags
+ */
+ void
+ml_clearmarked()
+{
+ bhdr_T *hp;
+ DATA_BL *dp;
+ linenr_T lnum;
+ int i;
+
+ if (curbuf->b_ml.ml_mfp == NULL) /* nothing to do */
+ return;
+
+ /*
+ * The search starts with line lowest_marked.
+ */
+ for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; )
+ {
+ /*
+ * Find the data block containing the line.
+ * This also fills the stack with the blocks from the root to the data
+ * block and releases any locked block.
+ */
+ if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
+ return; /* give error message? */
+
+ dp = (DATA_BL *)(hp->bh_data);
+
+ for (i = lnum - curbuf->b_ml.ml_locked_low;
+ lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum)
+ if ((dp->db_index[i]) & DB_MARKED)
+ {
+ (dp->db_index[i]) &= DB_INDEX_MASK;
+ curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
+ }
+ }
+
+ lowest_marked = 0;
+ return;
+}
+
+/*
+ * flush ml_line if necessary
+ */
+ static void
+ml_flush_line(buf)
+ buf_T *buf;
+{
+ bhdr_T *hp;
+ DATA_BL *dp;
+ linenr_T lnum;
+ char_u *new_line;
+ char_u *old_line;
+ colnr_T new_len;
+ int old_len;
+ int extra;
+ int idx;
+ int start;
+ int count;
+ int i;
+
+ if (buf->b_ml.ml_line_lnum == 0 || buf->b_ml.ml_mfp == NULL)
+ return; /* nothing to do */
+
+ if (buf->b_ml.ml_flags & ML_LINE_DIRTY)
+ {
+ lnum = buf->b_ml.ml_line_lnum;
+ new_line = buf->b_ml.ml_line_ptr;
+
+ hp = ml_find_line(buf, lnum, ML_FIND);
+ if (hp == NULL)
+ EMSGN(_("E320: Cannot find line %ld"), lnum);
+ else
+ {
+ dp = (DATA_BL *)(hp->bh_data);
+ idx = lnum - buf->b_ml.ml_locked_low;
+ start = ((dp->db_index[idx]) & DB_INDEX_MASK);
+ old_line = (char_u *)dp + start;
+ if (idx == 0) /* line is last in block */
+ old_len = dp->db_txt_end - start;
+ else /* text of previous line follows */
+ old_len = (dp->db_index[idx - 1] & DB_INDEX_MASK) - start;
+ new_len = (colnr_T)STRLEN(new_line) + 1;
+ extra = new_len - old_len; /* negative if lines gets smaller */
+
+ /*
+ * if new line fits in data block, replace directly
+ */
+ if ((int)dp->db_free >= extra)
+ {
+ /* if the length changes and there are following lines */
+ count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1;
+ if (extra != 0 && idx < count - 1)
+ {
+ /* move text of following lines */
+ mch_memmove((char *)dp + dp->db_txt_start - extra,
+ (char *)dp + dp->db_txt_start,
+ (size_t)(start - dp->db_txt_start));
+
+ /* adjust pointers of this and following lines */
+ for (i = idx + 1; i < count; ++i)
+ dp->db_index[i] -= extra;
+ }
+ dp->db_index[idx] -= extra;
+
+ /* adjust free space */
+ dp->db_free -= extra;
+ dp->db_txt_start -= extra;
+
+ /* copy new line into the data block */
+ mch_memmove(old_line - extra, new_line, (size_t)new_len);
+ buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
+#ifdef FEAT_BYTEOFF
+ /* The else case is already covered by the insert and delete */
+ ml_updatechunk(buf, lnum, (long)extra, ML_CHNK_UPDLINE);
+#endif
+ }
+ else
+ {
+ /*
+ * Cannot do it in one data block: Delete and append.
+ * Append first, because ml_delete_int() cannot delete the
+ * last line in a buffer, which causes trouble for a buffer
+ * that has only one line.
+ * Don't forget to copy the mark!
+ */
+ /* How about handling errors??? */
+ (void)ml_append_int(buf, lnum, new_line, new_len, FALSE,
+ (dp->db_index[idx] & DB_MARKED));
+ (void)ml_delete_int(buf, lnum, FALSE);
+ }
+ }
+ vim_free(new_line);
+ }
+
+ buf->b_ml.ml_line_lnum = 0;
+}
+
+/*
+ * create a new, empty, data block
+ */
+ static bhdr_T *
+ml_new_data(mfp, negative, page_count)
+ memfile_T *mfp;
+ int negative;
+ int page_count;
+{
+ bhdr_T *hp;
+ DATA_BL *dp;
+
+ if ((hp = mf_new(mfp, negative, page_count)) == NULL)
+ return NULL;
+
+ dp = (DATA_BL *)(hp->bh_data);
+ dp->db_id = DATA_ID;
+ dp->db_txt_start = dp->db_txt_end = page_count * mfp->mf_page_size;
+ dp->db_free = dp->db_txt_start - HEADER_SIZE;
+ dp->db_line_count = 0;
+
+ return hp;
+}
+
+/*
+ * create a new, empty, pointer block
+ */
+ static bhdr_T *
+ml_new_ptr(mfp)
+ memfile_T *mfp;
+{
+ bhdr_T *hp;
+ PTR_BL *pp;
+
+ if ((hp = mf_new(mfp, FALSE, 1)) == NULL)
+ return NULL;
+
+ pp = (PTR_BL *)(hp->bh_data);
+ pp->pb_id = PTR_ID;
+ pp->pb_count = 0;
+ pp->pb_count_max = (short_u)((mfp->mf_page_size - sizeof(PTR_BL)) / sizeof(PTR_EN) + 1);
+
+ return hp;
+}
+
+/*
+ * lookup line 'lnum' in a memline
+ *
+ * action: if ML_DELETE or ML_INSERT the line count is updated while searching
+ * if ML_FLUSH only flush a locked block
+ * if ML_FIND just find the line
+ *
+ * If the block was found it is locked and put in ml_locked.
+ * The stack is updated to lead to the locked block. The ip_high field in
+ * the stack is updated to reflect the last line in the block AFTER the
+ * insert or delete, also if the pointer block has not been updated yet. But
+ * if if ml_locked != NULL ml_locked_lineadd must be added to ip_high.
+ *
+ * return: NULL for failure, pointer to block header otherwise
+ */
+ static bhdr_T *
+ml_find_line(buf, lnum, action)
+ buf_T *buf;
+ linenr_T lnum;
+ int action;
+{
+ DATA_BL *dp;
+ PTR_BL *pp;
+ infoptr_T *ip;
+ bhdr_T *hp;
+ memfile_T *mfp;
+ linenr_T t;
+ blocknr_T bnum, bnum2;
+ int dirty;
+ linenr_T low, high;
+ int top;
+ int page_count;
+ int idx;
+
+ mfp = buf->b_ml.ml_mfp;
+
+ /*
+ * If there is a locked block check if the wanted line is in it.
+ * If not, flush and release the locked block.
+ * Don't do this for ML_INSERT_SAME, because the stack need to be updated.
+ * Don't do this for ML_FLUSH, because we want to flush the locked block.
+ */
+ if (buf->b_ml.ml_locked)
+ {
+ if (ML_SIMPLE(action) && buf->b_ml.ml_locked_low <= lnum
+ && buf->b_ml.ml_locked_high >= lnum)
+ {
+ /* remember to update pointer blocks and stack later */
+ if (action == ML_INSERT)
+ {
+ ++(buf->b_ml.ml_locked_lineadd);
+ ++(buf->b_ml.ml_locked_high);
+ }
+ else if (action == ML_DELETE)
+ {
+ --(buf->b_ml.ml_locked_lineadd);
+ --(buf->b_ml.ml_locked_high);
+ }
+ return (buf->b_ml.ml_locked);
+ }
+
+ mf_put(mfp, buf->b_ml.ml_locked, buf->b_ml.ml_flags & ML_LOCKED_DIRTY,
+ buf->b_ml.ml_flags & ML_LOCKED_POS);
+ buf->b_ml.ml_locked = NULL;
+
+ /*
+ * if lines have been added or deleted in the locked block, need to
+ * update the line count in pointer blocks
+ */
+ if (buf->b_ml.ml_locked_lineadd)
+ ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
+ }
+
+ if (action == ML_FLUSH) /* nothing else to do */
+ return NULL;
+
+ bnum = 1; /* start at the root of the tree */
+ page_count = 1;
+ low = 1;
+ high = buf->b_ml.ml_line_count;
+
+ if (action == ML_FIND) /* first try stack entries */
+ {
+ for (top = buf->b_ml.ml_stack_top - 1; top >= 0; --top)
+ {
+ ip = &(buf->b_ml.ml_stack[top]);
+ if (ip->ip_low <= lnum && ip->ip_high >= lnum)
+ {
+ bnum = ip->ip_bnum;
+ low = ip->ip_low;
+ high = ip->ip_high;
+ buf->b_ml.ml_stack_top = top; /* truncate stack at prev entry */
+ break;
+ }
+ }
+ if (top < 0)
+ buf->b_ml.ml_stack_top = 0; /* not found, start at the root */
+ }
+ else /* ML_DELETE or ML_INSERT */
+ buf->b_ml.ml_stack_top = 0; /* start at the root */
+
+/*
+ * search downwards in the tree until a data block is found
+ */
+ for (;;)
+ {
+ if ((hp = mf_get(mfp, bnum, page_count)) == NULL)
+ goto error_noblock;
+
+ /*
+ * update high for insert/delete
+ */
+ if (action == ML_INSERT)
+ ++high;
+ else if (action == ML_DELETE)
+ --high;
+
+ dp = (DATA_BL *)(hp->bh_data);
+ if (dp->db_id == DATA_ID) /* data block */
+ {
+ buf->b_ml.ml_locked = hp;
+ buf->b_ml.ml_locked_low = low;
+ buf->b_ml.ml_locked_high = high;
+ buf->b_ml.ml_locked_lineadd = 0;
+ buf->b_ml.ml_flags &= ~(ML_LOCKED_DIRTY | ML_LOCKED_POS);
+ return hp;
+ }
+
+ pp = (PTR_BL *)(dp); /* must be pointer block */
+ if (pp->pb_id != PTR_ID)
+ {
+ EMSG(_("E317: pointer block id wrong"));
+ goto error_block;
+ }
+
+ if ((top = ml_add_stack(buf)) < 0) /* add new entry to stack */
+ goto error_block;
+ ip = &(buf->b_ml.ml_stack[top]);
+ ip->ip_bnum = bnum;
+ ip->ip_low = low;
+ ip->ip_high = high;
+ ip->ip_index = -1; /* index not known yet */
+
+ dirty = FALSE;
+ for (idx = 0; idx < (int)pp->pb_count; ++idx)
+ {
+ t = pp->pb_pointer[idx].pe_line_count;
+ CHECK(t == 0, _("pe_line_count is zero"));
+ if ((low += t) > lnum)
+ {
+ ip->ip_index = idx;
+ bnum = pp->pb_pointer[idx].pe_bnum;
+ page_count = pp->pb_pointer[idx].pe_page_count;
+ high = low - 1;
+ low -= t;
+
+ /*
+ * a negative block number may have been changed
+ */
+ if (bnum < 0)
+ {
+ bnum2 = mf_trans_del(mfp, bnum);
+ if (bnum != bnum2)
+ {
+ bnum = bnum2;
+ pp->pb_pointer[idx].pe_bnum = bnum;
+ dirty = TRUE;
+ }
+ }
+
+ break;
+ }
+ }
+ if (idx >= (int)pp->pb_count) /* past the end: something wrong! */
+ {
+ if (lnum > buf->b_ml.ml_line_count)
+ EMSGN(_("E322: line number out of range: %ld past the end"),
+ lnum - buf->b_ml.ml_line_count);
+
+ else
+ EMSGN(_("E323: line count wrong in block %ld"), bnum);
+ goto error_block;
+ }
+ if (action == ML_DELETE)
+ {
+ pp->pb_pointer[idx].pe_line_count--;
+ dirty = TRUE;
+ }
+ else if (action == ML_INSERT)
+ {
+ pp->pb_pointer[idx].pe_line_count++;
+ dirty = TRUE;
+ }
+ mf_put(mfp, hp, dirty, FALSE);
+ }
+
+error_block:
+ mf_put(mfp, hp, FALSE, FALSE);
+error_noblock:
+/*
+ * If action is ML_DELETE or ML_INSERT we have to correct the tree for
+ * the incremented/decremented line counts, because there won't be a line
+ * inserted/deleted after all.
+ */
+ if (action == ML_DELETE)
+ ml_lineadd(buf, 1);
+ else if (action == ML_INSERT)
+ ml_lineadd(buf, -1);
+ buf->b_ml.ml_stack_top = 0;
+ return NULL;
+}
+
+/*
+ * add an entry to the info pointer stack
+ *
+ * return -1 for failure, number of the new entry otherwise
+ */
+ static int
+ml_add_stack(buf)
+ buf_T *buf;
+{
+ int top;
+ infoptr_T *newstack;
+
+ top = buf->b_ml.ml_stack_top;
+
+ /* may have to increase the stack size */
+ if (top == buf->b_ml.ml_stack_size)
+ {
+ CHECK(top > 0, _("Stack size increases")); /* more than 5 levels??? */
+
+ newstack = (infoptr_T *)alloc((unsigned)sizeof(infoptr_T) *
+ (buf->b_ml.ml_stack_size + STACK_INCR));
+ if (newstack == NULL)
+ return -1;
+ mch_memmove(newstack, buf->b_ml.ml_stack, (size_t)top * sizeof(infoptr_T));
+ vim_free(buf->b_ml.ml_stack);
+ buf->b_ml.ml_stack = newstack;
+ buf->b_ml.ml_stack_size += STACK_INCR;
+ }
+
+ buf->b_ml.ml_stack_top++;
+ return top;
+}
+
+/*
+ * Update the pointer blocks on the stack for inserted/deleted lines.
+ * The stack itself is also updated.
+ *
+ * When a insert/delete line action fails, the line is not inserted/deleted,
+ * but the pointer blocks have already been updated. That is fixed here by
+ * walking through the stack.
+ *
+ * Count is the number of lines added, negative if lines have been deleted.
+ */
+ static void
+ml_lineadd(buf, count)
+ buf_T *buf;
+ int count;
+{
+ int idx;
+ infoptr_T *ip;
+ PTR_BL *pp;
+ memfile_T *mfp = buf->b_ml.ml_mfp;
+ bhdr_T *hp;
+
+ for (idx = buf->b_ml.ml_stack_top - 1; idx >= 0; --idx)
+ {
+ ip = &(buf->b_ml.ml_stack[idx]);
+ if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
+ break;
+ pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */
+ if (pp->pb_id != PTR_ID)
+ {
+ mf_put(mfp, hp, FALSE, FALSE);
+ EMSG(_("E317: pointer block id wrong 2"));
+ break;
+ }
+ pp->pb_pointer[ip->ip_index].pe_line_count += count;
+ ip->ip_high += count;
+ mf_put(mfp, hp, TRUE, FALSE);
+ }
+}
+
+/*
+ * make swap file name out of the file name and a directory name
+ */
+ static char_u *
+makeswapname(buf, dir_name)
+ buf_T *buf;
+ char_u *dir_name;
+{
+ char_u *r, *s;
+
+#if defined(UNIX) || defined(WIN3264) /* Need _very_ long file names */
+ s = dir_name + STRLEN(dir_name);
+ if (vim_ispathsep(s[-1]) && s[-1] == s[-2])
+ { /* Ends with '//', Use Full path */
+ r = NULL;
+ if ((s = make_percent_swname(dir_name, buf->b_fname)) != NULL)
+ {
+ r = modname(s, (char_u *)".swp", FALSE);
+ vim_free(s);
+ }
+ return r;
+ }
+#endif
+
+ r = buf_modname(
+#ifdef SHORT_FNAME
+ TRUE,
+#else
+ (buf->b_p_sn || buf->b_shortname),
+#endif
+#ifdef RISCOS
+ /* Avoid problems if fname has special chars, eg <Wimp$Scrap> */
+ buf->b_ffname,
+#else
+ buf->b_fname,
+#endif
+ (char_u *)
+#if defined(VMS) || defined(RISCOS)
+ "_swp",
+#else
+ ".swp",
+#endif
+#ifdef SHORT_FNAME /* always 8.3 file name */
+ FALSE
+#else
+ /* Prepend a '.' to the swap file name for the current directory. */
+ dir_name[0] == '.' && dir_name[1] == NUL
+#endif
+ );
+ if (r == NULL) /* out of memory */
+ return NULL;
+
+ s = get_file_in_dir(r, dir_name);
+ vim_free(r);
+ return s;
+}
+
+/*
+ * Get file name to use for swap file or backup file.
+ * Use the name of the edited file "fname" and an entry in the 'dir' or 'bdir'
+ * option "dname".
+ * - If "dname" is ".", return "fname" (swap file in dir of file).
+ * - If "dname" starts with "./", insert "dname" in "fname" (swap file
+ * relative to dir of file).
+ * - Otherwise, prepend "dname" to the tail of "fname" (swap file in specific
+ * dir).
+ *
+ * The return value is an allocated string and can be NULL.
+ */
+ char_u *
+get_file_in_dir(fname, dname)
+ char_u *fname;
+ char_u *dname; /* don't use "dirname", it is a global for Alpha */
+{
+ char_u *t;
+ char_u *tail;
+ char_u *retval;
+ int save_char;
+
+ tail = gettail(fname);
+
+ if (dname[0] == '.' && dname[1] == NUL)
+ retval = vim_strsave(fname);
+ else if (dname[0] == '.' && vim_ispathsep(dname[1]))
+ {
+ if (tail == fname) /* no path before file name */
+ retval = concat_fnames(dname + 2, tail, TRUE);
+ else
+ {
+ save_char = *tail;
+ *tail = NUL;
+ t = concat_fnames(fname, dname + 2, TRUE);
+ *tail = save_char;
+ if (t == NULL) /* out of memory */
+ retval = NULL;
+ else
+ {
+ retval = concat_fnames(t, tail, TRUE);
+ vim_free(t);
+ }
+ }
+ }
+ else
+ retval = concat_fnames(dname, tail, TRUE);
+
+ return retval;
+}
+
+/*
+ * Find out what name to use for the swap file for buffer 'buf'.
+ *
+ * Several names are tried to find one that does not exist
+ *
+ * Note: If BASENAMELEN is not correct, you will get error messages for
+ * not being able to open the swapfile
+ */
+ static char_u *
+findswapname(buf, dirp, old_fname)
+ buf_T *buf;
+ char_u **dirp; /* pointer to list of directories */
+ char_u *old_fname; /* don't give warning for this file name */
+{
+ char_u *fname;
+ int n;
+ time_t x, sx;
+ char_u *dir_name;
+#ifdef AMIGA
+ BPTR fh;
+#endif
+#ifndef SHORT_FNAME
+ int r;
+#endif
+
+#if !defined(SHORT_FNAME) \
+ && ((!defined(UNIX) && !defined(OS2)) || defined(ARCHIE))
+# define CREATE_DUMMY_FILE
+ FILE *dummyfd = NULL;
+
+/*
+ * If we start editing a new file, e.g. "test.doc", which resides on an MSDOS
+ * compatible filesystem, it is possible that the file "test.doc.swp" which we
+ * create will be exactly the same file. To avoid this problem we temporarily
+ * create "test.doc".
+ * Don't do this when the check below for a 8.3 file name is used.
+ */
+ if (!(buf->b_p_sn || buf->b_shortname) && buf->b_fname != NULL
+ && mch_getperm(buf->b_fname) < 0)
+ dummyfd = mch_fopen((char *)buf->b_fname, "w");
+#endif
+
+/*
+ * Isolate a directory name from *dirp and put it in dir_name.
+ * First allocate some memory to put the directory name in.
+ */
+ dir_name = alloc((unsigned)STRLEN(*dirp) + 1);
+ if (dir_name != NULL)
+ (void)copy_option_part(dirp, dir_name, 31000, ",");
+
+/*
+ * we try different names until we find one that does not exist yet
+ */
+ if (dir_name == NULL) /* out of memory */
+ fname = NULL;
+ else
+ fname = makeswapname(buf, dir_name);
+
+ for (;;)
+ {
+ if (fname == NULL) /* must be out of memory */
+ break;
+ if ((n = (int)STRLEN(fname)) == 0) /* safety check */
+ {
+ vim_free(fname);
+ fname = NULL;
+ break;
+ }
+#if (defined(UNIX) || defined(OS2)) && !defined(ARCHIE) && !defined(SHORT_FNAME)
+/*
+ * Some systems have a MS-DOS compatible filesystem that use 8.3 character
+ * file names. If this is the first try and the swap file name does not fit in
+ * 8.3, detect if this is the case, set shortname and try again.
+ */
+ if (fname[n - 2] == 'w' && fname[n - 1] == 'p'
+ && !(buf->b_p_sn || buf->b_shortname))
+ {
+ char_u *tail;
+ char_u *fname2;
+ struct stat s1, s2;
+ int f1, f2;
+ int created1 = FALSE, created2 = FALSE;
+ int same = FALSE;
+
+ /*
+ * Check if swapfile name does not fit in 8.3:
+ * It either contains two dots, is longer than 8 chars, or starts
+ * with a dot.
+ */
+ tail = gettail(buf->b_fname);
+ if ( vim_strchr(tail, '.') != NULL
+ || STRLEN(tail) > (size_t)8
+ || *gettail(fname) == '.')
+ {
+ fname2 = alloc(n + 2);
+ if (fname2 != NULL)
+ {
+ STRCPY(fname2, fname);
+ /* if fname == "xx.xx.swp", fname2 = "xx.xx.swx"
+ * if fname == ".xx.swp", fname2 = ".xx.swpx"
+ * if fname == "123456789.swp", fname2 = "12345678x.swp"
+ */
+ if (vim_strchr(tail, '.') != NULL)
+ fname2[n - 1] = 'x';
+ else if (*gettail(fname) == '.')
+ {
+ fname2[n] = 'x';
+ fname2[n + 1] = NUL;
+ }
+ else
+ fname2[n - 5] += 1;
+ /*
+ * may need to create the files to be able to use mch_stat()
+ */
+ f1 = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
+ if (f1 < 0)
+ {
+ f1 = mch_open_rw((char *)fname,
+ O_RDWR|O_CREAT|O_EXCL|O_EXTRA);
+#if defined(OS2)
+ if (f1 < 0 && errno == ENOENT)
+ same = TRUE;
+#endif
+ created1 = TRUE;
+ }
+ if (f1 >= 0)
+ {
+ f2 = mch_open((char *)fname2, O_RDONLY | O_EXTRA, 0);
+ if (f2 < 0)
+ {
+ f2 = mch_open_rw((char *)fname2,
+ O_RDWR|O_CREAT|O_EXCL|O_EXTRA);
+ created2 = TRUE;
+ }
+ if (f2 >= 0)
+ {
+ /*
+ * Both files exist now. If mch_stat() returns the
+ * same device and inode they are the same file.
+ */
+ if (mch_fstat(f1, &s1) != -1
+ && mch_fstat(f2, &s2) != -1
+ && s1.st_dev == s2.st_dev
+ && s1.st_ino == s2.st_ino)
+ same = TRUE;
+ close(f2);
+ if (created2)
+ mch_remove(fname2);
+ }
+ close(f1);
+ if (created1)
+ mch_remove(fname);
+ }
+ vim_free(fname2);
+ if (same)
+ {
+ buf->b_shortname = TRUE;
+ vim_free(fname);
+ fname = makeswapname(buf, dir_name);
+ continue; /* try again with b_shortname set */
+ }
+ }
+ }
+ }
+#endif
+ /*
+ * check if the swapfile already exists
+ */
+ if (mch_getperm(fname) < 0) /* it does not exist */
+ {
+#ifdef HAVE_LSTAT
+ struct stat sb;
+
+ /*
+ * Extra security check: When a swap file is a symbolic link, this
+ * is most likely a symlink attack.
+ */
+ if (mch_lstat((char *)fname, &sb) < 0)
+#else
+# ifdef AMIGA
+ fh = Open((UBYTE *)fname, (long)MODE_NEWFILE);
+ /*
+ * on the Amiga mch_getperm() will return -1 when the file exists
+ * but is being used by another program. This happens if you edit
+ * a file twice.
+ */
+ if (fh != (BPTR)NULL) /* can open file, OK */
+ {
+ Close(fh);
+ mch_remove(fname);
+ break;
+ }
+ if (IoErr() != ERROR_OBJECT_IN_USE
+ && IoErr() != ERROR_OBJECT_EXISTS)
+# endif
+#endif
+ break;
+ }
+
+ /*
+ * A file name equal to old_fname is OK to use.
+ */
+ if (old_fname != NULL && fnamecmp(fname, old_fname) == 0)
+ break;
+
+ /*
+ * get here when file already exists
+ */
+ if (fname[n - 2] == 'w' && fname[n - 1] == 'p') /* first try */
+ {
+#ifndef SHORT_FNAME
+ /*
+ * on MS-DOS compatible filesystems (e.g. messydos) file.doc.swp
+ * and file.doc are the same file. To guess if this problem is
+ * present try if file.doc.swx exists. If it does, we set
+ * buf->b_shortname and try file_doc.swp (dots replaced by
+ * underscores for this file), and try again. If it doesn't we
+ * assume that "file.doc.swp" already exists.
+ */
+ if (!(buf->b_p_sn || buf->b_shortname)) /* not tried yet */
+ {
+ fname[n - 1] = 'x';
+ r = mch_getperm(fname); /* try "file.swx" */
+ fname[n - 1] = 'p';
+ if (r >= 0) /* "file.swx" seems to exist */
+ {
+ buf->b_shortname = TRUE;
+ vim_free(fname);
+ fname = makeswapname(buf, dir_name);
+ continue; /* try again with '.' replaced with '_' */
+ }
+ }
+#endif
+ /*
+ * If we get here the ".swp" file really exists.
+ * Give an error message, unless recovering, no file name, we are
+ * viewing a help file or when the path of the file is different
+ * (happens when all .swp files are in one directory).
+ */
+ if (!recoverymode && buf->b_fname != NULL && !buf->b_help)
+ {
+ int fd;
+ struct block0 b0;
+ int differ = FALSE;
+
+ /*
+ * Try to read block 0 from the swap file to get the original
+ * file name (and inode number).
+ */
+ fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
+ if (fd >= 0)
+ {
+ if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0))
+ {
+ /*
+ * The name in the swap file may be "~user/path/file".
+ * Expand it first.
+ */
+ expand_env(b0.b0_fname, NameBuff, MAXPATHL);
+#ifdef CHECK_INODE
+ if (fnamecmp_ino(buf->b_ffname, NameBuff,
+ char_to_long(b0.b0_ino)))
+ differ = TRUE;
+#else
+ if (fnamecmp(NameBuff, buf->b_ffname) != 0)
+ differ = TRUE;
+#endif
+ }
+ close(fd);
+ }
+#ifdef RISCOS
+ else
+ /* Can't open swap file, though it does exist.
+ * Assume that the user is editing two files with
+ * the same name in different directories. No error.
+ */
+ differ = TRUE;
+#endif
+
+ /* give the ATTENTION message when there is an old swap file
+ * for the current file, and the buffer was not recovered. */
+ if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED)
+ && vim_strchr(p_shm, SHM_ATTENTION) == NULL)
+ {
+ struct stat st;
+#ifdef CREATE_DUMMY_FILE
+ int did_use_dummy = FALSE;
+
+ /* Avoid getting a warning for the file being created
+ * outside of Vim, it was created at the start of this
+ * function. Delete the file now, because Vim might exit
+ * here if the window is closed. */
+ if (dummyfd != NULL)
+ {
+ fclose(dummyfd);
+ dummyfd = NULL;
+ mch_remove(buf->b_fname);
+ did_use_dummy = TRUE;
+ }
+#endif
+#ifdef FEAT_GUI
+ /* If we are supposed to start the GUI but it wasn't
+ * completely started yet, start it now. This makes the
+ * messages displayed in the Vim window when loading a
+ * session from the .gvimrc file. */
+ if (gui.starting && !gui.in_use)
+ gui_start();
+#endif
+
+#if (defined(UNIX) || defined(__EMX__) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG))
+ process_still_running = FALSE;
+#endif
+ ++no_wait_return;
+ (void)EMSG(_("E325: ATTENTION"));
+ MSG_PUTS(_("\nFound a swap file by the name \""));
+ msg_home_replace(fname);
+ MSG_PUTS("\"\n");
+ sx = swapfile_info(fname);
+ MSG_PUTS(_("While opening file \""));
+ msg_outtrans(buf->b_fname);
+ MSG_PUTS("\"\n");
+ if (mch_stat((char *)buf->b_fname, &st) != -1)
+ {
+ MSG_PUTS(_(" dated: "));
+ x = st.st_mtime; /* Manx C can't do &st.st_mtime */
+ MSG_PUTS(ctime(&x));
+ if (sx != 0 && x > sx)
+ MSG_PUTS(_(" NEWER than swap file!\n"));
+ }
+ /* Some of these messages are long to allow translation to
+ * other languages. */
+ MSG_PUTS(_("\n(1) Another program may be editing the same file.\n If this is the case, be careful not to end up with two\n different instances of the same file when making changes.\n"));
+ MSG_PUTS(_(" Quit, or continue with caution.\n"));
+ MSG_PUTS(_("\n(2) An edit session for this file crashed.\n"));
+ MSG_PUTS(_(" If this is the case, use \":recover\" or \"vim -r "));
+ msg_outtrans(buf->b_fname);
+ MSG_PUTS(_("\"\n to recover the changes (see \":help recovery\").\n"));
+ MSG_PUTS(_(" If you did this already, delete the swap file \""));
+ msg_outtrans(fname);
+ MSG_PUTS(_("\"\n to avoid this message.\n"));
+ cmdline_row = msg_row;
+ --no_wait_return;
+
+ /* We don't want a 'q' typed at the more-prompt interrupt
+ * loading a file. */
+ got_int = FALSE;
+
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if (swap_exists_action)
+ {
+ char_u *name;
+
+ name = alloc((unsigned)(STRLEN(fname)
+ + STRLEN(_("Swap file \""))
+ + STRLEN(_("\" already exists!")) + 5));
+ if (name != NULL)
+ {
+ STRCPY(name, _("Swap file \""));
+ home_replace(NULL, fname, name + STRLEN(name),
+ 1000, TRUE);
+ STRCAT(name, _("\" already exists!"));
+ }
+ switch (do_dialog(VIM_WARNING,
+ (char_u *)_("VIM - ATTENTION"),
+ name == NULL
+ ? (char_u *)_("Swap file already exists!")
+ : name,
+# if defined(UNIX) || defined(__EMX__) || defined(VMS)
+ process_still_running
+ ? (char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort") :
+# endif
+ (char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort\n&Delete it"), 1, NULL))
+ {
+ case 1:
+ buf->b_p_ro = TRUE;
+ break;
+ case 2:
+ break;
+ case 3:
+ swap_exists_action = SEA_RECOVER;
+ break;
+ case 4:
+ swap_exists_action = SEA_QUIT;
+ break;
+ case 5:
+ swap_exists_action = SEA_QUIT;
+ got_int = TRUE;
+ break;
+ case 6:
+ mch_remove(fname);
+ break;
+ }
+ vim_free(name);
+
+ /* pretend screen didn't scroll, need redraw anyway */
+ msg_scrolled = 0;
+ redraw_all_later(NOT_VALID);
+
+ /* If the file was deleted this fname can be used. */
+ if (mch_getperm(fname) < 0)
+ break;
+ }
+ else
+#endif
+ {
+ MSG_PUTS("\n");
+ need_wait_return = TRUE; /* call wait_return later */
+ }
+
+#ifdef CREATE_DUMMY_FILE
+ /* Going to try another name, need the dummy file again. */
+ if (did_use_dummy)
+ dummyfd = mch_fopen((char *)buf->b_fname, "w");
+#endif
+ }
+ }
+ }
+
+ /*
+ * Change the ".swp" extension to find another file that can be used.
+ * First decrement the last char: ".swo", ".swn", etc.
+ * If that still isn't enough decrement the last but one char: ".svz"
+ * Can happen when editing many "No File" buffers.
+ */
+ if (fname[n - 1] == 'a') /* ".s?a" */
+ {
+ if (fname[n - 2] == 'a') /* ".saa": tried enough, give up */
+ {
+ EMSG(_("E326: Too many swap files found"));
+ vim_free(fname);
+ fname = NULL;
+ break;
+ }
+ --fname[n - 2]; /* ".svz", ".suz", etc. */
+ fname[n - 1] = 'z' + 1;
+ }
+ --fname[n - 1]; /* ".swo", ".swn", etc. */
+ }
+
+ vim_free(dir_name);
+#ifdef CREATE_DUMMY_FILE
+ if (dummyfd != NULL) /* file has been created temporarily */
+ {
+ fclose(dummyfd);
+ mch_remove(buf->b_fname);
+ }
+#endif
+ return fname;
+}
+
+ static int
+b0_magic_wrong(b0p)
+ ZERO_BL *b0p;
+{
+ return (b0p->b0_magic_long != (long)B0_MAGIC_LONG
+ || b0p->b0_magic_int != (int)B0_MAGIC_INT
+ || b0p->b0_magic_short != (short)B0_MAGIC_SHORT
+ || b0p->b0_magic_char != B0_MAGIC_CHAR);
+}
+
+#ifdef CHECK_INODE
+/*
+ * Compare current file name with file name from swap file.
+ * Try to use inode numbers when possible.
+ * Return non-zero when files are different.
+ *
+ * When comparing file names a few things have to be taken into consideration:
+ * - When working over a network the full path of a file depends on the host.
+ * We check the inode number if possible. It is not 100% reliable though,
+ * because the device number cannot be used over a network.
+ * - When a file does not exist yet (editing a new file) there is no inode
+ * number.
+ * - The file name in a swap file may not be valid on the current host. The
+ * "~user" form is used whenever possible to avoid this.
+ *
+ * This is getting complicated, let's make a table:
+ *
+ * ino_c ino_s fname_c fname_s differ =
+ *
+ * both files exist -> compare inode numbers:
+ * != 0 != 0 X X ino_c != ino_s
+ *
+ * inode number(s) unknown, file names available -> compare file names
+ * == 0 X OK OK fname_c != fname_s
+ * X == 0 OK OK fname_c != fname_s
+ *
+ * current file doesn't exist, file for swap file exist, file name(s) not
+ * available -> probably different
+ * == 0 != 0 FAIL X TRUE
+ * == 0 != 0 X FAIL TRUE
+ *
+ * current file exists, inode for swap unknown, file name(s) not
+ * available -> probably different
+ * != 0 == 0 FAIL X TRUE
+ * != 0 == 0 X FAIL TRUE
+ *
+ * current file doesn't exist, inode for swap unknown, one file name not
+ * available -> probably different
+ * == 0 == 0 FAIL OK TRUE
+ * == 0 == 0 OK FAIL TRUE
+ *
+ * current file doesn't exist, inode for swap unknown, both file names not
+ * available -> probably same file
+ * == 0 == 0 FAIL FAIL FALSE
+ *
+ * Note that when the ino_t is 64 bits, only the last 32 will be used. This
+ * can't be changed without making the block 0 incompatible with 32 bit
+ * versions.
+ */
+
+ static int
+fnamecmp_ino(fname_c, fname_s, ino_block0)
+ char_u *fname_c; /* current file name */
+ char_u *fname_s; /* file name from swap file */
+ long ino_block0;
+{
+ struct stat st;
+ ino_t ino_c = 0; /* ino of current file */
+ ino_t ino_s; /* ino of file from swap file */
+ char_u buf_c[MAXPATHL]; /* full path of fname_c */
+ char_u buf_s[MAXPATHL]; /* full path of fname_s */
+ int retval_c; /* flag: buf_c valid */
+ int retval_s; /* flag: buf_s valid */
+
+ if (mch_stat((char *)fname_c, &st) == 0)
+ ino_c = (ino_t)st.st_ino;
+
+ /*
+ * First we try to get the inode from the file name, because the inode in
+ * the swap file may be outdated. If that fails (e.g. this path is not
+ * valid on this machine), use the inode from block 0.
+ */
+ if (mch_stat((char *)fname_s, &st) == 0)
+ ino_s = (ino_t)st.st_ino;
+ else
+ ino_s = (ino_t)ino_block0;
+
+ if (ino_c && ino_s)
+ return (ino_c != ino_s);
+
+ /*
+ * One of the inode numbers is unknown, try a forced vim_FullName() and
+ * compare the file names.
+ */
+ retval_c = vim_FullName(fname_c, buf_c, MAXPATHL, TRUE);
+ retval_s = vim_FullName(fname_s, buf_s, MAXPATHL, TRUE);
+ if (retval_c == OK && retval_s == OK)
+ return (STRCMP(buf_c, buf_s) != 0);
+
+ /*
+ * Can't compare inodes or file names, guess that the files are different,
+ * unless both appear not to exist at all.
+ */
+ if (ino_s == 0 && ino_c == 0 && retval_c == FAIL && retval_s == FAIL)
+ return FALSE;
+ return TRUE;
+}
+#endif /* CHECK_INODE */
+
+/*
+ * Move a long integer into a four byte character array.
+ * Used for machine independency in block zero.
+ */
+ static void
+long_to_char(n, s)
+ long n;
+ char_u *s;
+{
+ s[0] = (char_u)(n & 0xff);
+ n = (unsigned)n >> 8;
+ s[1] = (char_u)(n & 0xff);
+ n = (unsigned)n >> 8;
+ s[2] = (char_u)(n & 0xff);
+ n = (unsigned)n >> 8;
+ s[3] = (char_u)(n & 0xff);
+}
+
+ static long
+char_to_long(s)
+ char_u *s;
+{
+ long retval;
+
+ retval = s[3];
+ retval <<= 8;
+ retval |= s[2];
+ retval <<= 8;
+ retval |= s[1];
+ retval <<= 8;
+ retval |= s[0];
+
+ return retval;
+}
+
+ void
+ml_setdirty(buf, flag)
+ buf_T *buf;
+ int flag;
+{
+ bhdr_T *hp;
+ ZERO_BL *b0p;
+
+ if (!buf->b_ml.ml_mfp)
+ return;
+ for (hp = buf->b_ml.ml_mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
+ {
+ if (hp->bh_bnum == 0)
+ {
+ b0p = (ZERO_BL *)(hp->bh_data);
+ b0p->b0_dirty = flag ? 0x55 : 0;
+ hp->bh_flags |= BH_DIRTY;
+ mf_sync(buf->b_ml.ml_mfp, MFS_ZERO);
+ break;
+ }
+ }
+}
+
+#if defined(FEAT_BYTEOFF) || defined(PROTO)
+
+#define MLCS_MAXL 800 /* max no of lines in chunk */
+#define MLCS_MINL 400 /* should be half of MLCS_MAXL */
+
+/*
+ * Keep information for finding byte offset of a line, updtytpe may be one of:
+ * ML_CHNK_ADDLINE: Add len to parent chunk, possibly splitting it
+ * Careful: ML_CHNK_ADDLINE may cause ml_find_line() to be called.
+ * ML_CHNK_DELLINE: Subtract len from parent chunk, possibly deleting it
+ * ML_CHNK_UPDLINE: Add len to parent chunk, as a signed entity.
+ */
+ static void
+ml_updatechunk(buf, line, len, updtype)
+ buf_T *buf;
+ linenr_T line;
+ long len;
+ int updtype;
+{
+ static buf_T *ml_upd_lastbuf = NULL;
+ static linenr_T ml_upd_lastline;
+ static linenr_T ml_upd_lastcurline;
+ static int ml_upd_lastcurix;
+
+ linenr_T curline = ml_upd_lastcurline;
+ int curix = ml_upd_lastcurix;
+ long size;
+ chunksize_T *curchnk;
+ int rest;
+ bhdr_T *hp;
+ DATA_BL *dp;
+
+ if (buf->b_ml.ml_usedchunks == -1 || len == 0)
+ return;
+ if (buf->b_ml.ml_chunksize == NULL)
+ {
+ buf->b_ml.ml_chunksize = (chunksize_T *)
+ alloc((unsigned)sizeof(chunksize_T) * 100);
+ if (buf->b_ml.ml_chunksize == NULL)
+ {
+ buf->b_ml.ml_usedchunks = -1;
+ return;
+ }
+ buf->b_ml.ml_numchunks = 100;
+ buf->b_ml.ml_usedchunks = 1;
+ buf->b_ml.ml_chunksize[0].mlcs_numlines = 1;
+ buf->b_ml.ml_chunksize[0].mlcs_totalsize = 1;
+ }
+
+ if (updtype == ML_CHNK_UPDLINE && buf->b_ml.ml_line_count == 1)
+ {
+ /*
+ * First line in empty buffer from ml_flush_line() -- reset
+ */
+ buf->b_ml.ml_usedchunks = 1;
+ buf->b_ml.ml_chunksize[0].mlcs_numlines = 1;
+ buf->b_ml.ml_chunksize[0].mlcs_totalsize =
+ (long)STRLEN(buf->b_ml.ml_line_ptr) + 1;
+ return;
+ }
+
+ /*
+ * Find chunk that our line belongs to, curline will be at start of the
+ * chunk.
+ */
+ if (buf != ml_upd_lastbuf || line != ml_upd_lastline + 1
+ || updtype != ML_CHNK_ADDLINE)
+ {
+ for (curline = 1, curix = 0;
+ curix < buf->b_ml.ml_usedchunks - 1
+ && line >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines;
+ curix++)
+ {
+ curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
+ }
+ }
+ else if (line >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines
+ && curix < buf->b_ml.ml_usedchunks - 1)
+ {
+ /* Adjust cached curix & curline */
+ curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
+ curix++;
+ }
+ curchnk = buf->b_ml.ml_chunksize + curix;
+
+ if (updtype == ML_CHNK_DELLINE)
+ len *= -1;
+ curchnk->mlcs_totalsize += len;
+ if (updtype == ML_CHNK_ADDLINE)
+ {
+ curchnk->mlcs_numlines++;
+
+ /* May resize here so we don't have to do it in both cases below */
+ if (buf->b_ml.ml_usedchunks + 1 >= buf->b_ml.ml_numchunks)
+ {
+ buf->b_ml.ml_numchunks = buf->b_ml.ml_numchunks * 3 / 2;
+ buf->b_ml.ml_chunksize = (chunksize_T *)
+ vim_realloc(buf->b_ml.ml_chunksize,
+ sizeof(chunksize_T) * buf->b_ml.ml_numchunks);
+ if (buf->b_ml.ml_chunksize == NULL)
+ {
+ /* Hmmmm, Give up on offset for this buffer */
+ buf->b_ml.ml_usedchunks = -1;
+ return;
+ }
+ }
+
+ if (buf->b_ml.ml_chunksize[curix].mlcs_numlines >= MLCS_MAXL)
+ {
+ int count; /* number of entries in block */
+ int idx;
+ int text_end;
+ int linecnt;
+
+ mch_memmove(buf->b_ml.ml_chunksize + curix + 1,
+ buf->b_ml.ml_chunksize + curix,
+ (buf->b_ml.ml_usedchunks - curix) *
+ sizeof(chunksize_T));
+ /* Compute length of first half of lines in the splitted chunk */
+ size = 0;
+ linecnt = 0;
+ while (curline < buf->b_ml.ml_line_count
+ && linecnt < MLCS_MINL)
+ {
+ if ((hp = ml_find_line(buf, curline, ML_FIND)) == NULL)
+ {
+ buf->b_ml.ml_usedchunks = -1;
+ return;
+ }
+ dp = (DATA_BL *)(hp->bh_data);
+ count = (long)(buf->b_ml.ml_locked_high) -
+ (long)(buf->b_ml.ml_locked_low) + 1;
+ idx = curline - buf->b_ml.ml_locked_low;
+ curline = buf->b_ml.ml_locked_high + 1;
+ if (idx == 0)/* first line in block, text at the end */
+ text_end = dp->db_txt_end;
+ else
+ text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK);
+ /* Compute index of last line to use in this MEMLINE */
+ rest = count - idx;
+ if (linecnt + rest > MLCS_MINL)
+ {
+ idx += MLCS_MINL - linecnt - 1;
+ linecnt = MLCS_MINL;
+ }
+ else
+ {
+ idx = count - 1;
+ linecnt += rest;
+ }
+ size += text_end - ((dp->db_index[idx]) & DB_INDEX_MASK);
+ }
+ buf->b_ml.ml_chunksize[curix].mlcs_numlines = linecnt;
+ buf->b_ml.ml_chunksize[curix + 1].mlcs_numlines -= linecnt;
+ buf->b_ml.ml_chunksize[curix].mlcs_totalsize = size;
+ buf->b_ml.ml_chunksize[curix + 1].mlcs_totalsize -= size;
+ buf->b_ml.ml_usedchunks++;
+ ml_upd_lastbuf = NULL; /* Force recalc of curix & curline */
+ return;
+ }
+ else if (buf->b_ml.ml_chunksize[curix].mlcs_numlines >= MLCS_MINL
+ && curix == buf->b_ml.ml_usedchunks - 1
+ && buf->b_ml.ml_line_count - line <= 1)
+ {
+ /*
+ * We are in the last chunk and it is cheap to crate a new one
+ * after this. Do it now to avoid the loop above later on
+ */
+ curchnk = buf->b_ml.ml_chunksize + curix + 1;
+ buf->b_ml.ml_usedchunks++;
+ if (line == buf->b_ml.ml_line_count)
+ {
+ curchnk->mlcs_numlines = 0;
+ curchnk->mlcs_totalsize = 0;
+ }
+ else
+ {
+ /*
+ * Line is just prior to last, move count for last
+ * This is the common case when loading a new file
+ */
+ hp = ml_find_line(buf, buf->b_ml.ml_line_count, ML_FIND);
+ if (hp == NULL)
+ {
+ buf->b_ml.ml_usedchunks = -1;
+ return;
+ }
+ dp = (DATA_BL *)(hp->bh_data);
+ if (dp->db_line_count == 1)
+ rest = dp->db_txt_end - dp->db_txt_start;
+ else
+ rest =
+ ((dp->db_index[dp->db_line_count - 2]) & DB_INDEX_MASK)
+ - dp->db_txt_start;
+ curchnk->mlcs_totalsize = rest;
+ curchnk->mlcs_numlines = 1;
+ curchnk[-1].mlcs_totalsize -= rest;
+ curchnk[-1].mlcs_numlines -= 1;
+ }
+ }
+ }
+ else if (updtype == ML_CHNK_DELLINE)
+ {
+ curchnk->mlcs_numlines--;
+ ml_upd_lastbuf = NULL; /* Force recalc of curix & curline */
+ if (curix < (buf->b_ml.ml_usedchunks - 1)
+ && (curchnk->mlcs_numlines + curchnk[1].mlcs_numlines)
+ <= MLCS_MINL)
+ {
+ curix++;
+ curchnk = buf->b_ml.ml_chunksize + curix;
+ }
+ else if (curix == 0 && curchnk->mlcs_numlines <= 0)
+ {
+ buf->b_ml.ml_usedchunks--;
+ mch_memmove(buf->b_ml.ml_chunksize, buf->b_ml.ml_chunksize + 1,
+ buf->b_ml.ml_usedchunks * sizeof(chunksize_T));
+ return;
+ }
+ else if (curix == 0 || (curchnk->mlcs_numlines > 10
+ && (curchnk->mlcs_numlines + curchnk[-1].mlcs_numlines)
+ > MLCS_MINL))
+ {
+ return;
+ }
+
+ /* Collapse chunks */
+ curchnk[-1].mlcs_numlines += curchnk->mlcs_numlines;
+ curchnk[-1].mlcs_totalsize += curchnk->mlcs_totalsize;
+ buf->b_ml.ml_usedchunks--;
+ if (curix < buf->b_ml.ml_usedchunks)
+ {
+ mch_memmove(buf->b_ml.ml_chunksize + curix,
+ buf->b_ml.ml_chunksize + curix + 1,
+ (buf->b_ml.ml_usedchunks - curix) *
+ sizeof(chunksize_T));
+ }
+ return;
+ }
+ ml_upd_lastbuf = buf;
+ ml_upd_lastline = line;
+ ml_upd_lastcurline = curline;
+ ml_upd_lastcurix = curix;
+}
+
+/*
+ * Find offset for line or line with offset.
+ * Find line with offset if line is 0; return remaining offset in offp
+ * Find offset of line if line > 0
+ * return -1 if information is not available
+ */
+ long
+ml_find_line_or_offset(buf, line, offp)
+ buf_T *buf;
+ linenr_T line;
+ long *offp;
+{
+ linenr_T curline;
+ int curix;
+ long size;
+ bhdr_T *hp;
+ DATA_BL *dp;
+ int count; /* number of entries in block */
+ int idx;
+ int start_idx;
+ int text_end;
+ long offset;
+ int len;
+ int ffdos = (get_fileformat(buf) == EOL_DOS);
+ int extra = 0;
+
+ if (buf->b_ml.ml_usedchunks == -1
+ || buf->b_ml.ml_chunksize == NULL
+ || line < 0)
+ return -1;
+
+ if (offp == NULL)
+ offset = 0;
+ else
+ offset = *offp;
+ if (line == 0 && offset <= 0)
+ return 1; /* Not a "find offset" and offset 0 _must_ be in line 1 */
+ /*
+ * Find the last chunk before the one containing our line. Last chunk is
+ * special because it will never qualify
+ */
+ curline = 1;
+ curix = size = 0;
+ while (curix < buf->b_ml.ml_usedchunks - 1
+ && ((line != 0
+ && line >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines)
+ || (offset != 0
+ && offset > size + buf->b_ml.ml_chunksize[curix].mlcs_totalsize
+ + ffdos * buf->b_ml.ml_chunksize[curix].mlcs_numlines)))
+ {
+ curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
+ size += buf->b_ml.ml_chunksize[curix].mlcs_totalsize;
+ if (offset && ffdos)
+ size += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
+ curix++;
+ }
+
+ while ((line != 0 && curline < line) || (offset != 0 && size < offset))
+ {
+ if (curline > buf->b_ml.ml_line_count
+ || (hp = ml_find_line(buf, curline, ML_FIND)) == NULL)
+ return -1;
+ dp = (DATA_BL *)(hp->bh_data);
+ count = (long)(buf->b_ml.ml_locked_high) -
+ (long)(buf->b_ml.ml_locked_low) + 1;
+ start_idx = idx = curline - buf->b_ml.ml_locked_low;
+ if (idx == 0)/* first line in block, text at the end */
+ text_end = dp->db_txt_end;
+ else
+ text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK);
+ /* Compute index of last line to use in this MEMLINE */
+ if (line != 0)
+ {
+ if (curline + (count - idx) >= line)
+ idx += line - curline - 1;
+ else
+ idx = count - 1;
+ }
+ else
+ {
+ extra = 0;
+ while (offset >= size
+ + text_end - (int)((dp->db_index[idx]) & DB_INDEX_MASK)
+ + ffdos)
+ {
+ if (ffdos)
+ size++;
+ if (idx == count - 1)
+ {
+ extra = 1;
+ break;
+ }
+ idx++;
+ }
+ }
+ len = text_end - ((dp->db_index[idx]) & DB_INDEX_MASK);
+ size += len;
+ if (offset != 0 && size >= offset)
+ {
+ if (size + ffdos == offset)
+ *offp = 0;
+ else if (idx == start_idx)
+ *offp = offset - size + len;
+ else
+ *offp = offset - size + len
+ - (text_end - ((dp->db_index[idx - 1]) & DB_INDEX_MASK));
+ curline += idx - start_idx + extra;
+ if (curline > buf->b_ml.ml_line_count)
+ return -1; /* exactly one byte beyond the end */
+ return curline;
+ }
+ curline = buf->b_ml.ml_locked_high + 1;
+ }
+
+ if (ffdos)
+ size += line - 1;
+ return size;
+}
+
+/*
+ * Goto byte in buffer with offset 'cnt'.
+ */
+ void
+goto_byte(cnt)
+ long cnt;
+{
+ long boff = cnt;
+ linenr_T lnum;
+
+ ml_flush_line(curbuf); /* cached line may be dirty */
+ setpcmark();
+ if (boff)
+ --boff;
+ lnum = ml_find_line_or_offset(curbuf, (linenr_T)0, &boff);
+ if (lnum < 1) /* past the end */
+ {
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ curwin->w_curswant = MAXCOL;
+ coladvance((colnr_T)MAXCOL);
+ }
+ else
+ {
+ curwin->w_cursor.lnum = lnum;
+ curwin->w_cursor.col = (colnr_T)boff;
+ curwin->w_set_curswant = TRUE;
+ }
+ check_cursor();
+
+# ifdef FEAT_MBYTE
+ /* Make sure the cursor is on the first byte of a multi-byte char. */
+ if (has_mbyte)
+ mb_adjust_cursor();
+# endif
+}
+#endif
diff --git a/src/menu.c b/src/menu.c
new file mode 100644
index 000000000..052910f7e
--- /dev/null
+++ b/src/menu.c
@@ -0,0 +1,2385 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI/Motif support by Robert Webb
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * Code for menus. Used for the GUI and 'wildmenu'.
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_MENU) || defined(PROTO)
+
+#define MENUDEPTH 10 /* maximum depth of menus */
+
+#ifdef FEAT_GUI_W32
+static int add_menu_path __ARGS((char_u *, vimmenu_T *, int *, char_u *, int));
+#else
+static int add_menu_path __ARGS((char_u *, vimmenu_T *, int *, char_u *));
+#endif
+static int menu_nable_recurse __ARGS((vimmenu_T *menu, char_u *name, int modes, int enable));
+static int remove_menu __ARGS((vimmenu_T **, char_u *, int, int silent));
+static void free_menu __ARGS((vimmenu_T **menup));
+static void free_menu_string __ARGS((vimmenu_T *, int));
+static int show_menus __ARGS((char_u *, int));
+static void show_menus_recursive __ARGS((vimmenu_T *, int, int));
+static int menu_name_equal __ARGS((char_u *name, vimmenu_T *menu));
+static int menu_namecmp __ARGS((char_u *name, char_u *mname));
+static int get_menu_cmd_modes __ARGS((char_u *, int, int *, int *));
+static char_u *popup_mode_name __ARGS((char_u *name, int idx));
+static char_u *menu_text __ARGS((char_u *text, int *mnemonic, char_u **actext));
+#ifdef FEAT_GUI
+static int get_menu_mode __ARGS((void));
+static void gui_update_menus_recurse __ARGS((vimmenu_T *, int));
+#endif
+
+#if defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF)
+static void gui_create_tearoffs_recurse __ARGS((vimmenu_T *menu, const char_u *pname, int *pri_tab, int pri_idx));
+static void gui_add_tearoff __ARGS((char_u *tearpath, int *pri_tab, int pri_idx));
+static void gui_destroy_tearoffs_recurse __ARGS((vimmenu_T *menu));
+static int s_tearoffs = FALSE;
+#endif
+
+static int menu_is_hidden __ARGS((char_u *name));
+#if defined(FEAT_CMDL_COMPL) || (defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF))
+static int menu_is_tearoff __ARGS((char_u *name));
+#endif
+
+#if defined(FEAT_MULTI_LANG) || defined(FEAT_TOOLBAR)
+static char_u *menu_skip_part __ARGS((char_u *p));
+#endif
+#ifdef FEAT_MULTI_LANG
+static char_u *menutrans_lookup __ARGS((char_u *name, int len));
+#endif
+
+/* The character for each menu mode */
+static char_u menu_mode_chars[] = {'n', 'v', 'o', 'i', 'c', 't'};
+
+static char_u e_notsubmenu[] = N_("E327: Part of menu-item path is not sub-menu");
+static char_u e_othermode[] = N_("E328: Menu only exists in another mode");
+static char_u e_nomenu[] = N_("E329: No menu of that name");
+
+#ifdef FEAT_TOOLBAR
+static const char *toolbar_names[] =
+{
+ /* 0 */ "New", "Open", "Save", "Undo", "Redo",
+ /* 5 */ "Cut", "Copy", "Paste", "Print", "Help",
+ /* 10 */ "Find", "SaveAll", "SaveSesn", "NewSesn", "LoadSesn",
+ /* 15 */ "RunScript", "Replace", "WinClose", "WinMax", "WinMin",
+ /* 20 */ "WinSplit", "Shell", "FindPrev", "FindNext", "FindHelp",
+ /* 25 */ "Make", "TagJump", "RunCtags", "WinVSplit", "WinMaxWidth",
+ /* 30 */ "WinMinWidth", "Exit"
+};
+# define TOOLBAR_NAME_COUNT (sizeof(toolbar_names) / sizeof(char *))
+#endif
+
+/*
+ * Do the :menu command and relatives.
+ */
+ void
+ex_menu(eap)
+ exarg_T *eap; /* Ex command arguments */
+{
+ char_u *menu_path;
+ int modes;
+ char_u *map_to;
+ int noremap;
+ int silent = FALSE;
+ int unmenu;
+ char_u *map_buf;
+ char_u *arg;
+ char_u *p;
+ int i;
+#if defined(FEAT_GUI) && !defined(FEAT_GUI_GTK)
+ int old_menu_height;
+# if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32) && !defined(FEAT_GUI_W16)
+ int old_toolbar_height;
+# endif
+#endif
+ int pri_tab[MENUDEPTH + 1];
+ int enable = MAYBE; /* TRUE for "menu enable", FALSE for "menu
+ * disable */
+#ifdef FEAT_MULTI_LANG
+ char_u *tofree = NULL;
+ char_u *new_cmd;
+#endif
+#ifdef FEAT_TOOLBAR
+ char_u *icon = NULL;
+#endif
+ vimmenu_T menuarg;
+
+ modes = get_menu_cmd_modes(eap->cmd, eap->forceit, &noremap, &unmenu);
+ arg = eap->arg;
+
+ for (;;)
+ {
+ if (STRNCMP(arg, "<script>", 8) == 0)
+ {
+ noremap = REMAP_SCRIPT;
+ arg = skipwhite(arg + 8);
+ continue;
+ }
+ if (STRNCMP(arg, "<silent>", 8) == 0)
+ {
+ silent = TRUE;
+ arg = skipwhite(arg + 8);
+ continue;
+ }
+ break;
+ }
+
+
+ /* Locate an optional "icon=filename" argument. */
+ if (STRNCMP(arg, "icon=", 5) == 0)
+ {
+ arg += 5;
+#ifdef FEAT_TOOLBAR
+ icon = arg;
+#endif
+ while (*arg != NUL && *arg != ' ')
+ {
+ if (*arg == '\\')
+ mch_memmove(arg, arg + 1, STRLEN(arg));
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ arg += (*mb_ptr2len_check)(arg);
+ else
+#endif
+ ++arg;
+ }
+ if (*arg != NUL)
+ {
+ *arg++ = NUL;
+ arg = skipwhite(arg);
+ }
+ }
+
+ /*
+ * Fill in the priority table.
+ */
+ for (p = arg; *p; ++p)
+ if (!VIM_ISDIGIT(*p) && *p != '.')
+ break;
+ if (vim_iswhite(*p))
+ {
+ for (i = 0; i < MENUDEPTH && !vim_iswhite(*arg); ++i)
+ {
+ pri_tab[i] = getdigits(&arg);
+ if (pri_tab[i] == 0)
+ pri_tab[i] = 500;
+ if (*arg == '.')
+ ++arg;
+ }
+ arg = skipwhite(arg);
+ }
+ else if (eap->addr_count && eap->line2 != 0)
+ {
+ pri_tab[0] = eap->line2;
+ i = 1;
+ }
+ else
+ i = 0;
+ while (i < MENUDEPTH)
+ pri_tab[i++] = 500;
+ pri_tab[MENUDEPTH] = -1; /* mark end of the table */
+
+ /*
+ * Check for "disable" or "enable" argument.
+ */
+ if (STRNCMP(arg, "enable", 6) == 0 && vim_iswhite(arg[6]))
+ {
+ enable = TRUE;
+ arg = skipwhite(arg + 6);
+ }
+ else if (STRNCMP(arg, "disable", 7) == 0 && vim_iswhite(arg[7]))
+ {
+ enable = FALSE;
+ arg = skipwhite(arg + 7);
+ }
+
+ /*
+ * If there is no argument, display all menus.
+ */
+ if (*arg == NUL)
+ {
+ show_menus(arg, modes);
+ return;
+ }
+
+#ifdef FEAT_TOOLBAR
+ /*
+ * Need to get the toolbar icon index before doing the translation.
+ */
+ menuarg.iconidx = -1;
+ menuarg.icon_builtin = FALSE;
+ if (menu_is_toolbar(arg))
+ {
+ menu_path = menu_skip_part(arg);
+ if (*menu_path == '.')
+ {
+ p = menu_skip_part(++menu_path);
+ if (STRNCMP(menu_path, "BuiltIn", 7) == 0)
+ {
+ if (skipdigits(menu_path + 7) == p)
+ {
+ menuarg.iconidx = atoi((char *)menu_path + 7);
+ if (menuarg.iconidx >= TOOLBAR_NAME_COUNT)
+ menuarg.iconidx = -1;
+ else
+ menuarg.icon_builtin = TRUE;
+ }
+ }
+ else
+ {
+ for (i = 0; i < TOOLBAR_NAME_COUNT; ++i)
+ if (STRNCMP(toolbar_names[i], menu_path, p - menu_path)
+ == 0)
+ {
+ menuarg.iconidx = i;
+ break;
+ }
+ }
+ }
+ }
+#endif
+
+#ifdef FEAT_MULTI_LANG
+ /*
+ * Translate menu names as specified with ":menutrans" commands.
+ */
+ menu_path = arg;
+ while (*menu_path)
+ {
+ /* find the end of one part and check if it should be translated */
+ p = menu_skip_part(menu_path);
+ map_to = menutrans_lookup(menu_path, (int)(p - menu_path));
+ if (map_to != NULL)
+ {
+ /* found a match: replace with the translated part */
+ i = (int)STRLEN(map_to);
+ new_cmd = alloc((unsigned)STRLEN(arg) + i + 1);
+ if (new_cmd == NULL)
+ break;
+ mch_memmove(new_cmd, arg, menu_path - arg);
+ mch_memmove(new_cmd + (menu_path - arg), map_to, (size_t)i);
+ STRCPY(new_cmd + (menu_path - arg) + i, p);
+ p = new_cmd + (menu_path - arg) + i;
+ vim_free(tofree);
+ tofree = new_cmd;
+ arg = new_cmd;
+ }
+ if (*p != '.')
+ break;
+ menu_path = p + 1;
+ }
+#endif
+
+ /*
+ * Isolate the menu name.
+ * Skip the menu name, and translate <Tab> into a real TAB.
+ */
+ menu_path = arg;
+ if (*menu_path == '.')
+ {
+ EMSG2(_(e_invarg2), menu_path);
+ goto theend;
+ }
+
+ while (*arg && !vim_iswhite(*arg))
+ {
+ if ((*arg == '\\' || *arg == Ctrl_V) && arg[1] != NUL)
+ arg++;
+ else if (STRNICMP(arg, "<TAB>", 5) == 0)
+ {
+ *arg = TAB;
+ mch_memmove(arg + 1, arg + 5, STRLEN(arg + 4));
+ }
+ arg++;
+ }
+ if (*arg != NUL)
+ *arg++ = NUL;
+ arg = skipwhite(arg);
+ map_to = arg;
+
+ /*
+ * If there is only a menu name, display menus with that name.
+ */
+ if (*map_to == NUL && !unmenu && enable == MAYBE)
+ {
+ show_menus(menu_path, modes);
+ goto theend;
+ }
+ else if (*map_to != NUL && (unmenu || enable != MAYBE))
+ {
+ EMSG(_(e_trailing));
+ goto theend;
+ }
+#if defined(FEAT_GUI) && !(defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON))
+ old_menu_height = gui.menu_height;
+# if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32) && !defined(FEAT_GUI_W16)
+ old_toolbar_height = gui.toolbar_height;
+# endif
+#endif
+
+ if (enable != MAYBE)
+ {
+ /*
+ * Change sensitivity of the menu.
+ * For the PopUp menu, remove a menu for each mode separately.
+ * Careful: menu_nable_recurse() changes menu_path.
+ */
+ if (STRCMP(menu_path, "*") == 0) /* meaning: do all menus */
+ menu_path = (char_u *)"";
+
+ if (menu_is_popup(menu_path))
+ {
+ for (i = 0; i < MENU_INDEX_TIP; ++i)
+ if (modes & (1 << i))
+ {
+ p = popup_mode_name(menu_path, i);
+ if (p != NULL)
+ {
+ menu_nable_recurse(root_menu, p, MENU_ALL_MODES,
+ enable);
+ vim_free(p);
+ }
+ }
+ }
+ menu_nable_recurse(root_menu, menu_path, modes, enable);
+ }
+ else if (unmenu)
+ {
+ /*
+ * Delete menu(s).
+ */
+ if (STRCMP(menu_path, "*") == 0) /* meaning: remove all menus */
+ menu_path = (char_u *)"";
+
+ /*
+ * For the PopUp menu, remove a menu for each mode separately.
+ */
+ if (menu_is_popup(menu_path))
+ {
+ for (i = 0; i < MENU_INDEX_TIP; ++i)
+ if (modes & (1 << i))
+ {
+ p = popup_mode_name(menu_path, i);
+ if (p != NULL)
+ {
+ remove_menu(&root_menu, p, MENU_ALL_MODES, TRUE);
+ vim_free(p);
+ }
+ }
+ }
+
+ /* Careful: remove_menu() changes menu_path */
+ remove_menu(&root_menu, menu_path, modes, FALSE);
+ }
+ else
+ {
+ /*
+ * Add menu(s).
+ * Replace special key codes.
+ */
+ if (STRICMP(map_to, "<nop>") == 0) /* "<Nop>" means nothing */
+ {
+ map_to = (char_u *)"";
+ map_buf = NULL;
+ }
+ else
+ map_to = replace_termcodes(map_to, &map_buf, FALSE, TRUE);
+ menuarg.modes = modes;
+#ifdef FEAT_TOOLBAR
+ menuarg.iconfile = icon;
+#endif
+ menuarg.noremap[0] = noremap;
+ menuarg.silent[0] = silent;
+ add_menu_path(menu_path, &menuarg, pri_tab, map_to
+#ifdef FEAT_GUI_W32
+ , TRUE
+#endif
+ );
+
+ /*
+ * For the PopUp menu, add a menu for each mode separately.
+ */
+ if (menu_is_popup(menu_path))
+ {
+ for (i = 0; i < MENU_INDEX_TIP; ++i)
+ if (modes & (1 << i))
+ {
+ p = popup_mode_name(menu_path, i);
+ if (p != NULL)
+ {
+ /* Include all modes, to make ":amenu" work */
+ menuarg.modes = modes;
+#ifdef FEAT_TOOLBAR
+ menuarg.iconfile = NULL;
+ menuarg.iconidx = -1;
+ menuarg.icon_builtin = FALSE;
+#endif
+ add_menu_path(p, &menuarg, pri_tab, map_to
+#ifdef FEAT_GUI_W32
+ , TRUE
+#endif
+ );
+ vim_free(p);
+ }
+ }
+ }
+
+ vim_free(map_buf);
+ }
+
+#if defined(FEAT_GUI) && !defined(FEAT_GUI_GTK)
+ /* If the menubar height changed, resize the window */
+ if (gui.in_use
+ && (gui.menu_height != old_menu_height
+# if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32) && !defined(FEAT_GUI_W16)
+ || gui.toolbar_height != old_toolbar_height
+# endif
+ ))
+ gui_set_shellsize(FALSE, FALSE);
+#endif
+
+theend:
+#ifdef FEAT_MULTI_LANG
+ vim_free(tofree);
+#else
+ ;
+#endif
+}
+
+/*
+ * Add the menu with the given name to the menu hierarchy
+ */
+ static int
+add_menu_path(menu_path, menuarg, pri_tab, call_data
+#ifdef FEAT_GUI_W32
+ , addtearoff
+#endif
+ )
+ char_u *menu_path;
+ vimmenu_T *menuarg; /* passes modes, iconfile, iconidx,
+ icon_builtin, silent[0], noremap[0] */
+ int *pri_tab;
+ char_u *call_data;
+#ifdef FEAT_GUI_W32
+ int addtearoff; /* may add tearoff item */
+#endif
+{
+ char_u *path_name;
+ int modes = menuarg->modes;
+ vimmenu_T **menup;
+ vimmenu_T *menu = NULL;
+ vimmenu_T *parent;
+ vimmenu_T **lower_pri;
+ char_u *p;
+ char_u *name;
+ char_u *dname;
+ char_u *next_name;
+ int i;
+ int c;
+#ifdef FEAT_GUI
+ int idx;
+ int new_idx;
+#endif
+ int pri_idx = 0;
+ int old_modes = 0;
+ int amenu;
+
+ /* Make a copy so we can stuff around with it, since it could be const */
+ path_name = vim_strsave(menu_path);
+ if (path_name == NULL)
+ return FAIL;
+ menup = &root_menu;
+ parent = NULL;
+ name = path_name;
+ while (*name)
+ {
+ /* Get name of this element in the menu hierarchy, and the simplified
+ * name (without mnemonic and accelerator text). */
+ next_name = menu_name_skip(name);
+ dname = menu_text(name, NULL, NULL);
+
+ /* See if it's already there */
+ lower_pri = menup;
+#ifdef FEAT_GUI
+ idx = 0;
+ new_idx = 0;
+#endif
+ menu = *menup;
+ while (menu != NULL)
+ {
+ if (menu_name_equal(name, menu) || menu_name_equal(dname, menu))
+ {
+ if (*next_name == NUL && menu->children != NULL)
+ {
+ if (!sys_menu)
+ EMSG(_("E330: Menu path must not lead to a sub-menu"));
+ goto erret;
+ }
+ if (*next_name != NUL && menu->children == NULL
+#ifdef FEAT_GUI_W32
+ && addtearoff
+#endif
+ )
+ {
+ if (!sys_menu)
+ EMSG(_(e_notsubmenu));
+ goto erret;
+ }
+ break;
+ }
+ menup = &menu->next;
+
+ /* Count menus, to find where this one needs to be inserted.
+ * Ignore menus that are not in the menubar (PopUp and Toolbar) */
+ if (parent != NULL || menu_is_menubar(menu->name))
+ {
+#ifdef FEAT_GUI
+ ++idx;
+#endif
+ if (menu->priority <= pri_tab[pri_idx])
+ {
+ lower_pri = menup;
+#ifdef FEAT_GUI
+ new_idx = idx;
+#endif
+ }
+ }
+ menu = menu->next;
+ }
+
+ if (menu == NULL)
+ {
+ if (*next_name == NUL && parent == NULL)
+ {
+ EMSG(_("E331: Must not add menu items directly to menu bar"));
+ goto erret;
+ }
+
+ if (menu_is_separator(dname) && *next_name != NUL)
+ {
+ EMSG(_("E332: Separator cannot be part of a menu path"));
+ goto erret;
+ }
+
+ /* Not already there, so lets add it */
+ menu = (vimmenu_T *)alloc_clear((unsigned)sizeof(vimmenu_T));
+ if (menu == NULL)
+ goto erret;
+
+ menu->modes = modes;
+ menu->enabled = MENU_ALL_MODES;
+ menu->name = vim_strsave(name);
+ /* separate mnemonic and accelerator text from actual menu name */
+ menu->dname = menu_text(name, &menu->mnemonic, &menu->actext);
+ menu->priority = pri_tab[pri_idx];
+ menu->parent = parent;
+#ifdef FEAT_GUI_MOTIF
+ menu->sensitive = TRUE; /* the default */
+#endif
+#ifdef FEAT_BEVAL_TIP
+ menu->tip = NULL;
+#endif
+#ifdef FEAT_GUI_ATHENA
+ menu->image = None; /* X-Windows definition for NULL*/
+#endif
+
+ /*
+ * Add after menu that has lower priority.
+ */
+ menu->next = *lower_pri;
+ *lower_pri = menu;
+
+ old_modes = 0;
+
+#ifdef FEAT_TOOLBAR
+ menu->iconidx = menuarg->iconidx;
+ menu->icon_builtin = menuarg->icon_builtin;
+ if (*next_name == NUL && menuarg->iconfile != NULL)
+ menu->iconfile = vim_strsave(menuarg->iconfile);
+#endif
+#if defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF)
+ /* the tearoff item must be present in the modes of each item. */
+ if (parent != NULL && menu_is_tearoff(parent->children->dname))
+ parent->children->modes |= modes;
+#endif
+ }
+ else
+ {
+ old_modes = menu->modes;
+
+ /*
+ * If this menu option was previously only available in other
+ * modes, then make sure it's available for this one now
+ * Also enable a menu when it's created or changed.
+ */
+#ifdef FEAT_GUI_W32
+ /* If adding a tearbar (addtearoff == FALSE) don't update modes */
+ if (addtearoff)
+#endif
+ {
+ menu->modes |= modes;
+ menu->enabled |= modes;
+ }
+ }
+
+#ifdef FEAT_GUI
+ /*
+ * Add the menu item when it's used in one of the modes, but not when
+ * only a tooltip is defined.
+ */
+ if ((old_modes & MENU_ALL_MODES) == 0
+ && (menu->modes & MENU_ALL_MODES) != 0)
+ {
+ if (gui.in_use) /* Otherwise it will be added when GUI starts */
+ {
+ if (*next_name == NUL)
+ {
+ /* Real menu item, not sub-menu */
+ gui_mch_add_menu_item(menu, new_idx);
+
+ /* Want to update menus now even if mode not changed */
+ force_menu_update = TRUE;
+ }
+ else
+ {
+ /* Sub-menu (not at end of path yet) */
+ gui_mch_add_menu(menu, new_idx);
+ }
+ }
+
+# if defined(FEAT_GUI_W32) & defined(FEAT_TEAROFF)
+ /* When adding a new submenu, may add a tearoff item */
+ if ( addtearoff
+ && *next_name
+ && vim_strchr(p_go, GO_TEAROFF) != NULL
+ && menu_is_menubar(name))
+ {
+ char_u *tearpath;
+
+ /*
+ * The pointers next_name & path_name refer to a string with
+ * \'s and ^V's stripped out. But menu_path is a "raw"
+ * string, so we must correct for special characters.
+ */
+ tearpath = alloc((unsigned int)STRLEN(menu_path) + TEAR_LEN + 2);
+ if (tearpath != NULL)
+ {
+ char_u *s;
+ int idx;
+
+ STRCPY(tearpath, menu_path);
+ idx = (int)(next_name - path_name - 1);
+ for (s = tearpath; *s && s < tearpath + idx; ++s)
+ {
+ if ((*s == '\\' || *s == Ctrl_V) && s[1])
+ {
+ ++idx;
+ ++s;
+ }
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ s += (*mb_ptr2len_check)(s) - 1;
+# endif
+ }
+ tearpath[idx] = NUL;
+ gui_add_tearoff(tearpath, pri_tab, pri_idx);
+ vim_free(tearpath);
+ }
+ }
+# endif
+ }
+#endif /* FEAT_GUI */
+
+ menup = &menu->children;
+ parent = menu;
+ name = next_name;
+ vim_free(dname);
+ if (pri_tab[pri_idx + 1] != -1)
+ ++pri_idx;
+ }
+ vim_free(path_name);
+
+ /*
+ * Only add system menu items which have not been defined yet.
+ * First check if this was an ":amenu".
+ */
+ amenu = ((modes & (MENU_NORMAL_MODE | MENU_INSERT_MODE)) ==
+ (MENU_NORMAL_MODE | MENU_INSERT_MODE));
+ if (sys_menu)
+ modes &= ~old_modes;
+
+ if (menu != NULL && modes)
+ {
+#ifdef FEAT_GUI
+ menu->cb = gui_menu_cb;
+#endif
+ p = (call_data == NULL) ? NULL : vim_strsave(call_data);
+
+ /* loop over all modes, may add more than one */
+ for (i = 0; i < MENU_MODES; ++i)
+ {
+ if (modes & (1 << i))
+ {
+ /* free any old menu */
+ free_menu_string(menu, i);
+
+ /* For "amenu", may insert an extra character.
+ * Don't do this if adding a tearbar (addtearoff == FALSE).
+ * Don't do this for "<Nop>". */
+ c = 0;
+ if (amenu && call_data != NULL && *call_data != NUL
+#ifdef FEAT_GUI_W32
+ && addtearoff
+#endif
+ )
+ {
+ switch (1 << i)
+ {
+ case MENU_VISUAL_MODE:
+ case MENU_OP_PENDING_MODE:
+ case MENU_CMDLINE_MODE:
+ c = Ctrl_C;
+ break;
+ case MENU_INSERT_MODE:
+ c = Ctrl_O;
+ break;
+ }
+ }
+
+ if (c)
+ {
+ menu->strings[i] = alloc((unsigned)(STRLEN(call_data) + 4));
+ if (menu->strings[i] != NULL)
+ {
+ menu->strings[i][0] = c;
+ STRCPY(menu->strings[i] + 1, call_data);
+ if (c == Ctrl_C)
+ {
+ int len = STRLEN(menu->strings[i]);
+
+ /* Append CTRL-\ CTRL-G to obey 'insertmode'. */
+ menu->strings[i][len] = Ctrl_BSL;
+ menu->strings[i][len + 1] = Ctrl_G;
+ menu->strings[i][len + 2] = NUL;
+ }
+ }
+ }
+ else
+ menu->strings[i] = p;
+ menu->noremap[i] = menuarg->noremap[0];
+ menu->silent[i] = menuarg->silent[0];
+ }
+ }
+#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32) \
+ && (defined(FEAT_BEVAL) || defined(FEAT_GUI_GTK))
+ /* Need to update the menu tip. */
+ if (modes & MENU_TIP_MODE)
+ gui_mch_menu_set_tip(menu);
+#endif
+ }
+ return OK;
+
+erret:
+ vim_free(path_name);
+ vim_free(dname);
+ return FAIL;
+}
+
+/*
+ * Set the (sub)menu with the given name to enabled or disabled.
+ * Called recursively.
+ */
+ static int
+menu_nable_recurse(menu, name, modes, enable)
+ vimmenu_T *menu;
+ char_u *name;
+ int modes;
+ int enable;
+{
+ char_u *p;
+
+ if (menu == NULL)
+ return OK; /* Got to bottom of hierarchy */
+
+ /* Get name of this element in the menu hierarchy */
+ p = menu_name_skip(name);
+
+ /* Find the menu */
+ while (menu != NULL)
+ {
+ if (*name == NUL || *name == '*' || menu_name_equal(name, menu))
+ {
+ if (*p != NUL)
+ {
+ if (menu->children == NULL)
+ {
+ EMSG(_(e_notsubmenu));
+ return FAIL;
+ }
+ if (menu_nable_recurse(menu->children, p, modes, enable)
+ == FAIL)
+ return FAIL;
+ }
+ else
+ if (enable)
+ menu->enabled |= modes;
+ else
+ menu->enabled &= ~modes;
+
+ /*
+ * When name is empty, we are doing all menu items for the given
+ * modes, so keep looping, otherwise we are just doing the named
+ * menu item (which has been found) so break here.
+ */
+ if (*name != NUL && *name != '*')
+ break;
+ }
+ menu = menu->next;
+ }
+ if (*name != NUL && *name != '*' && menu == NULL)
+ {
+ EMSG(_(e_nomenu));
+ return FAIL;
+ }
+
+#ifdef FEAT_GUI
+ /* Want to update menus now even if mode not changed */
+ force_menu_update = TRUE;
+#endif
+
+ return OK;
+}
+
+/*
+ * Remove the (sub)menu with the given name from the menu hierarchy
+ * Called recursively.
+ */
+ static int
+remove_menu(menup, name, modes, silent)
+ vimmenu_T **menup;
+ char_u *name;
+ int modes;
+ int silent; /* don't give error messages */
+{
+ vimmenu_T *menu;
+ vimmenu_T *child;
+ char_u *p;
+
+ if (*menup == NULL)
+ return OK; /* Got to bottom of hierarchy */
+
+ /* Get name of this element in the menu hierarchy */
+ p = menu_name_skip(name);
+
+ /* Find the menu */
+ while ((menu = *menup) != NULL)
+ {
+ if (*name == NUL || menu_name_equal(name, menu))
+ {
+ if (*p != NUL && menu->children == NULL)
+ {
+ if (!silent)
+ EMSG(_(e_notsubmenu));
+ return FAIL;
+ }
+ if ((menu->modes & modes) != 0x0)
+ {
+#if defined(FEAT_GUI_W32) & defined(FEAT_TEAROFF)
+ /*
+ * If we are removing all entries for this menu,MENU_ALL_MODES,
+ * Then kill any tearoff before we start
+ */
+ if (*p == NUL && modes == MENU_ALL_MODES)
+ {
+ if (IsWindow(menu->tearoff_handle))
+ DestroyWindow(menu->tearoff_handle);
+ }
+#endif
+ if (remove_menu(&menu->children, p, modes, silent) == FAIL)
+ return FAIL;
+ }
+ else if (*name != NUL)
+ {
+ if (!silent)
+ EMSG(_(e_othermode));
+ return FAIL;
+ }
+
+ /*
+ * When name is empty, we are removing all menu items for the given
+ * modes, so keep looping, otherwise we are just removing the named
+ * menu item (which has been found) so break here.
+ */
+ if (*name != NUL)
+ break;
+
+ /* Remove the menu item for the given mode[s]. If the menu item
+ * is no longer valid in ANY mode, delete it */
+ menu->modes &= ~modes;
+ if (modes & MENU_TIP_MODE)
+ free_menu_string(menu, MENU_INDEX_TIP);
+ if ((menu->modes & MENU_ALL_MODES) == 0)
+ free_menu(menup);
+ else
+ menup = &menu->next;
+ }
+ else
+ menup = &menu->next;
+ }
+ if (*name != NUL)
+ {
+ if (menu == NULL)
+ {
+ if (!silent)
+ EMSG(_(e_nomenu));
+ return FAIL;
+ }
+
+
+ /* Recalculate modes for menu based on the new updated children */
+ menu->modes &= ~modes;
+#if defined(FEAT_GUI_W32) & defined(FEAT_TEAROFF)
+ if ((s_tearoffs) && (menu->children != NULL)) /* there's a tear bar.. */
+ child = menu->children->next; /* don't count tearoff bar */
+ else
+#endif
+ child = menu->children;
+ for ( ; child != NULL; child = child->next)
+ menu->modes |= child->modes;
+ if (modes & MENU_TIP_MODE)
+ {
+ free_menu_string(menu, MENU_INDEX_TIP);
+#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32) \
+ && (defined(FEAT_BEVAL) || defined(FEAT_GUI_GTK))
+ /* Need to update the menu tip. */
+ if (gui.in_use)
+ gui_mch_menu_set_tip(menu);
+#endif
+ }
+ if ((menu->modes & MENU_ALL_MODES) == 0)
+ {
+ /* The menu item is no longer valid in ANY mode, so delete it */
+#if defined(FEAT_GUI_W32) & defined(FEAT_TEAROFF)
+ if (s_tearoffs && menu->children != NULL) /* there's a tear bar.. */
+ free_menu(&menu->children);
+#endif
+ *menup = menu;
+ free_menu(menup);
+ }
+ }
+
+ return OK;
+}
+
+/*
+ * Free the given menu structure and remove it from the linked list.
+ */
+ static void
+free_menu(menup)
+ vimmenu_T **menup;
+{
+ int i;
+ vimmenu_T *menu;
+
+ menu = *menup;
+
+#ifdef FEAT_GUI
+ /* Free machine specific menu structures (only when already created) */
+ /* Also may rebuild a tearoff'ed menu */
+ if (gui.in_use)
+ gui_mch_destroy_menu(menu);
+#endif
+
+ /* Don't change *menup until after calling gui_mch_destroy_menu(). The
+ * MacOS code needs the original structure to properly delete the menu. */
+ *menup = menu->next;
+ vim_free(menu->name);
+ vim_free(menu->dname);
+ vim_free(menu->actext);
+#ifdef FEAT_TOOLBAR
+ vim_free(menu->iconfile);
+#endif
+ for (i = 0; i < MENU_MODES; i++)
+ free_menu_string(menu, i);
+ vim_free(menu);
+
+#ifdef FEAT_GUI
+ /* Want to update menus now even if mode not changed */
+ force_menu_update = TRUE;
+#endif
+}
+
+/*
+ * Free the menu->string with the given index.
+ */
+ static void
+free_menu_string(menu, idx)
+ vimmenu_T *menu;
+ int idx;
+{
+ int count = 0;
+ int i;
+
+ for (i = 0; i < MENU_MODES; i++)
+ if (menu->strings[i] == menu->strings[idx])
+ count++;
+ if (count == 1)
+ vim_free(menu->strings[idx]);
+ menu->strings[idx] = NULL;
+}
+
+/*
+ * Show the mapping associated with a menu item or hierarchy in a sub-menu.
+ */
+ static int
+show_menus(path_name, modes)
+ char_u *path_name;
+ int modes;
+{
+ char_u *p;
+ char_u *name;
+ vimmenu_T *menu;
+ vimmenu_T *parent = NULL;
+
+ menu = root_menu;
+ name = path_name = vim_strsave(path_name);
+ if (path_name == NULL)
+ return FAIL;
+
+ /* First, find the (sub)menu with the given name */
+ while (*name)
+ {
+ p = menu_name_skip(name);
+ while (menu != NULL)
+ {
+ if (menu_name_equal(name, menu))
+ {
+ /* Found menu */
+ if (*p != NUL && menu->children == NULL)
+ {
+ EMSG(_(e_notsubmenu));
+ vim_free(path_name);
+ return FAIL;
+ }
+ else if ((menu->modes & modes) == 0x0)
+ {
+ EMSG(_(e_othermode));
+ vim_free(path_name);
+ return FAIL;
+ }
+ break;
+ }
+ menu = menu->next;
+ }
+ if (menu == NULL)
+ {
+ EMSG(_(e_nomenu));
+ vim_free(path_name);
+ return FAIL;
+ }
+ name = p;
+ parent = menu;
+ menu = menu->children;
+ }
+
+ /* Now we have found the matching menu, and we list the mappings */
+ /* Highlight title */
+ MSG_PUTS_TITLE(_("\n--- Menus ---"));
+
+ show_menus_recursive(parent, modes, 0);
+ return OK;
+}
+
+/*
+ * Recursively show the mappings associated with the menus under the given one
+ */
+ static void
+show_menus_recursive(menu, modes, depth)
+ vimmenu_T *menu;
+ int modes;
+ int depth;
+{
+ int i;
+ int bit;
+
+ if (menu != NULL && (menu->modes & modes) == 0x0)
+ return;
+
+ if (menu != NULL)
+ {
+ msg_putchar('\n');
+ if (got_int) /* "q" hit for "--more--" */
+ return;
+ for (i = 0; i < depth; i++)
+ MSG_PUTS(" ");
+ if (menu->priority)
+ {
+ msg_outnum((long)menu->priority);
+ MSG_PUTS(" ");
+ }
+ /* Same highlighting as for directories!? */
+ msg_outtrans_attr(menu->name, hl_attr(HLF_D));
+ }
+
+ if (menu != NULL && menu->children == NULL)
+ {
+ for (bit = 0; bit < MENU_MODES; bit++)
+ if ((menu->modes & modes & (1 << bit)) != 0)
+ {
+ msg_putchar('\n');
+ if (got_int) /* "q" hit for "--more--" */
+ return;
+ for (i = 0; i < depth + 2; i++)
+ MSG_PUTS(" ");
+ msg_putchar(menu_mode_chars[bit]);
+ if (menu->noremap[bit] == REMAP_NONE)
+ msg_putchar('*');
+ else if (menu->noremap[bit] == REMAP_SCRIPT)
+ msg_putchar('&');
+ else
+ msg_putchar(' ');
+ if (menu->silent[bit])
+ msg_putchar('s');
+ else
+ msg_putchar(' ');
+ if ((menu->modes & menu->enabled & (1 << bit)) == 0)
+ msg_putchar('-');
+ else
+ msg_putchar(' ');
+ MSG_PUTS(" ");
+ if (*menu->strings[bit] == NUL)
+ msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8));
+ else
+ msg_outtrans_special(menu->strings[bit], FALSE);
+ }
+ }
+ else
+ {
+ if (menu == NULL)
+ {
+ menu = root_menu;
+ depth--;
+ }
+ else
+ menu = menu->children;
+
+ /* recursively show all children. Skip PopUp[nvoci]. */
+ for (; menu != NULL && !got_int; menu = menu->next)
+ if (!menu_is_hidden(menu->dname))
+ show_menus_recursive(menu, modes, depth + 1);
+ }
+}
+
+#ifdef FEAT_CMDL_COMPL
+
+/*
+ * Used when expanding menu names.
+ */
+static vimmenu_T *expand_menu = NULL;
+static int expand_modes = 0x0;
+static int expand_emenu; /* TRUE for ":emenu" command */
+
+/*
+ * Work out what to complete when doing command line completion of menu names.
+ */
+ char_u *
+set_context_in_menu_cmd(xp, cmd, arg, forceit)
+ expand_T *xp;
+ char_u *cmd;
+ char_u *arg;
+ int forceit;
+{
+ char_u *after_dot;
+ char_u *p;
+ char_u *path_name = NULL;
+ char_u *name;
+ int unmenu;
+ vimmenu_T *menu;
+ int expand_menus;
+
+ xp->xp_context = EXPAND_UNSUCCESSFUL;
+
+
+ /* Check for priority numbers, enable and disable */
+ for (p = arg; *p; ++p)
+ if (!VIM_ISDIGIT(*p) && *p != '.')
+ break;
+
+ if (!vim_iswhite(*p))
+ {
+ if (STRNCMP(arg, "enable", 6) == 0
+ && (arg[6] == NUL || vim_iswhite(arg[6])))
+ p = arg + 6;
+ else if (STRNCMP(arg, "disable", 7) == 0
+ && (arg[7] == NUL || vim_iswhite(arg[7])))
+ p = arg + 7;
+ else
+ p = arg;
+ }
+
+ while (*p != NUL && vim_iswhite(*p))
+ ++p;
+
+ arg = after_dot = p;
+
+ for (; *p && !vim_iswhite(*p); ++p)
+ {
+ if ((*p == '\\' || *p == Ctrl_V) && p[1] != NUL)
+ p++;
+ else if (*p == '.')
+ after_dot = p + 1;
+ }
+
+ /* ":tearoff" and ":popup" only use menus, not entries */
+ expand_menus = !((*cmd == 't' && cmd[1] == 'e') || *cmd == 'p');
+ expand_emenu = (*cmd == 'e');
+ if (expand_menus && vim_iswhite(*p))
+ return NULL; /* TODO: check for next command? */
+ if (*p == NUL) /* Complete the menu name */
+ {
+ /*
+ * With :unmenu, you only want to match menus for the appropriate mode.
+ * With :menu though you might want to add a menu with the same name as
+ * one in another mode, so match menus from other modes too.
+ */
+ expand_modes = get_menu_cmd_modes(cmd, forceit, NULL, &unmenu);
+ if (!unmenu)
+ expand_modes = MENU_ALL_MODES;
+
+ menu = root_menu;
+ if (after_dot != arg)
+ {
+ path_name = alloc((unsigned)(after_dot - arg));
+ if (path_name == NULL)
+ return NULL;
+ STRNCPY(path_name, arg, after_dot - arg - 1);
+ path_name[after_dot - arg - 1] = NUL;
+ }
+ name = path_name;
+ while (name != NULL && *name)
+ {
+ p = menu_name_skip(name);
+ while (menu != NULL)
+ {
+ if (menu_name_equal(name, menu))
+ {
+ /* Found menu */
+ if ((*p != NUL && menu->children == NULL)
+ || ((menu->modes & expand_modes) == 0x0))
+ {
+ /*
+ * Menu path continues, but we have reached a leaf.
+ * Or menu exists only in another mode.
+ */
+ vim_free(path_name);
+ return NULL;
+ }
+ break;
+ }
+ menu = menu->next;
+ }
+ if (menu == NULL)
+ {
+ /* No menu found with the name we were looking for */
+ vim_free(path_name);
+ return NULL;
+ }
+ name = p;
+ menu = menu->children;
+ }
+
+ xp->xp_context = expand_menus ? EXPAND_MENUNAMES : EXPAND_MENUS;
+ xp->xp_pattern = after_dot;
+ expand_menu = menu;
+ }
+ else /* We're in the mapping part */
+ xp->xp_context = EXPAND_NOTHING;
+ return NULL;
+}
+
+/*
+ * Function given to ExpandGeneric() to obtain the list of (sub)menus (not
+ * entries).
+ */
+/*ARGSUSED*/
+ char_u *
+get_menu_name(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ static vimmenu_T *menu = NULL;
+ char_u *str;
+
+ if (idx == 0) /* first call: start at first item */
+ menu = expand_menu;
+
+ /* Skip PopUp[nvoci]. */
+ while (menu != NULL && (menu_is_hidden(menu->dname)
+ || menu_is_separator(menu->dname)
+ || menu_is_tearoff(menu->dname)
+ || menu->children == NULL))
+ menu = menu->next;
+
+ if (menu == NULL) /* at end of linked list */
+ return NULL;
+
+ if (menu->modes & expand_modes)
+ str = menu->dname;
+ else
+ str = (char_u *)"";
+
+ /* Advance to next menu entry. */
+ menu = menu->next;
+
+ return str;
+}
+
+/*
+ * Function given to ExpandGeneric() to obtain the list of menus and menu
+ * entries.
+ */
+/*ARGSUSED*/
+ char_u *
+get_menu_names(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ static vimmenu_T *menu = NULL;
+ static char_u tbuffer[256]; /*hack*/
+ char_u *str;
+
+ if (idx == 0) /* first call: start at first item */
+ menu = expand_menu;
+
+ /* Skip Browse-style entries, popup menus and separators. */
+ while (menu != NULL
+ && ( menu_is_hidden(menu->dname)
+ || (expand_emenu && menu_is_separator(menu->dname))
+ || menu_is_tearoff(menu->dname)
+#ifndef FEAT_BROWSE
+ || menu->dname[STRLEN(menu->dname) - 1] == '.'
+#endif
+ ))
+ menu = menu->next;
+
+ if (menu == NULL) /* at end of linked list */
+ return NULL;
+
+ if (menu->modes & expand_modes)
+ {
+ if (menu->children != NULL)
+ {
+ STRCPY(tbuffer, menu->dname);
+ /* hack on menu separators: use a 'magic' char for the separator
+ * so that '.' in names gets escaped properly */
+ STRCAT(tbuffer, "\001");
+ str = tbuffer;
+ }
+ else
+ str = menu->dname;
+ }
+ else
+ str = (char_u *)"";
+
+ /* Advance to next menu entry. */
+ menu = menu->next;
+
+ return str;
+}
+#endif /* FEAT_CMDL_COMPL */
+
+/*
+ * Skip over this element of the menu path and return the start of the next
+ * element. Any \ and ^Vs are removed from the current element.
+ */
+ char_u *
+menu_name_skip(name)
+ char_u *name;
+{
+ char_u *p;
+
+ for (p = name; *p && *p != '.'; p++)
+ {
+ if (*p == '\\' || *p == Ctrl_V)
+ {
+ mch_memmove(p, p + 1, STRLEN(p));
+ if (*p == NUL)
+ break;
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1; /* skip multibyte char */
+#endif
+ }
+ if (*p)
+ *p++ = NUL;
+ return p;
+}
+
+/*
+ * Return TRUE when "name" matches with menu "menu". The name is compared in
+ * two ways: raw menu name and menu name without '&'. ignore part after a TAB.
+ */
+ static int
+menu_name_equal(name, menu)
+ char_u *name;
+ vimmenu_T *menu;
+{
+ return (menu_namecmp(name, menu->name) || menu_namecmp(name, menu->dname));
+}
+
+ static int
+menu_namecmp(name, mname)
+ char_u *name;
+ char_u *mname;
+{
+ int i;
+
+ for (i = 0; name[i] != NUL && name[i] != TAB; ++i)
+ if (name[i] != mname[i])
+ break;
+ return ((name[i] == NUL || name[i] == TAB)
+ && (mname[i] == NUL || mname[i] == TAB));
+}
+
+/*
+ * Return the modes specified by the given menu command (eg :menu! returns
+ * MENU_CMDLINE_MODE | MENU_INSERT_MODE).
+ * If "noremap" is not NULL, then the flag it points to is set according to
+ * whether the command is a "nore" command.
+ * If "unmenu" is not NULL, then the flag it points to is set according to
+ * whether the command is an "unmenu" command.
+ */
+ static int
+get_menu_cmd_modes(cmd, forceit, noremap, unmenu)
+ char_u *cmd;
+ int forceit; /* Was there a "!" after the command? */
+ int *noremap;
+ int *unmenu;
+{
+ int modes;
+
+ switch (*cmd++)
+ {
+ case 'v': /* vmenu, vunmenu, vnoremenu */
+ modes = MENU_VISUAL_MODE;
+ break;
+ case 'o': /* omenu */
+ modes = MENU_OP_PENDING_MODE;
+ break;
+ case 'i': /* imenu */
+ modes = MENU_INSERT_MODE;
+ break;
+ case 't':
+ modes = MENU_TIP_MODE; /* tmenu */
+ break;
+ case 'c': /* cmenu */
+ modes = MENU_CMDLINE_MODE;
+ break;
+ case 'a': /* amenu */
+ modes = MENU_INSERT_MODE | MENU_CMDLINE_MODE | MENU_NORMAL_MODE
+ | MENU_VISUAL_MODE | MENU_OP_PENDING_MODE;
+ break;
+ case 'n':
+ if (*cmd != 'o') /* nmenu, not noremenu */
+ {
+ modes = MENU_NORMAL_MODE;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ --cmd;
+ if (forceit) /* menu!! */
+ modes = MENU_INSERT_MODE | MENU_CMDLINE_MODE;
+ else /* menu */
+ modes = MENU_NORMAL_MODE | MENU_VISUAL_MODE
+ | MENU_OP_PENDING_MODE;
+ }
+
+ if (noremap != NULL)
+ *noremap = (*cmd == 'n' ? REMAP_NONE : REMAP_YES);
+ if (unmenu != NULL)
+ *unmenu = (*cmd == 'u');
+ return modes;
+}
+
+/*
+ * Modify a menu name starting with "PopUp" to include the mode character.
+ * Returns the name in allocated memory (NULL for failure).
+ */
+ static char_u *
+popup_mode_name(name, idx)
+ char_u *name;
+ int idx;
+{
+ char_u *p;
+ int len = (int)STRLEN(name);
+
+ p = vim_strnsave(name, len + 1);
+ if (p != NULL)
+ {
+ mch_memmove(p + 6, p + 5, (size_t)(len - 4));
+ p[5] = menu_mode_chars[idx];
+ }
+ return p;
+}
+
+#if defined(FEAT_GUI) || defined(PROTO)
+/*
+ * Return the index into the menu->strings or menu->noremap arrays for the
+ * current state. Returns MENU_INDEX_INVALID if there is no mapping for the
+ * given menu in the current mode.
+ */
+ int
+get_menu_index(menu, state)
+ vimmenu_T *menu;
+ int state;
+{
+ int idx;
+
+ if ((state & INSERT))
+ idx = MENU_INDEX_INSERT;
+ else if (state & CMDLINE)
+ idx = MENU_INDEX_CMDLINE;
+#ifdef FEAT_VISUAL
+ else if (VIsual_active)
+ idx = MENU_INDEX_VISUAL;
+#endif
+ else if (state == HITRETURN || state == ASKMORE)
+ idx = MENU_INDEX_CMDLINE;
+ else if (finish_op)
+ idx = MENU_INDEX_OP_PENDING;
+ else if ((state & NORMAL))
+ idx = MENU_INDEX_NORMAL;
+ else
+ idx = MENU_INDEX_INVALID;
+
+ if (idx != MENU_INDEX_INVALID && menu->strings[idx] == NULL)
+ idx = MENU_INDEX_INVALID;
+ return idx;
+}
+#endif
+
+/*
+ * Duplicate the menu item text and then process to see if a mnemonic key
+ * and/or accelerator text has been identified.
+ * Returns a pointer to allocated memory, or NULL for failure.
+ * If mnemonic != NULL, *mnemonic is set to the character after the first '&'.
+ * If actext != NULL, *actext is set to the text after the first TAB.
+ */
+ static char_u *
+menu_text(str, mnemonic, actext)
+ char_u *str;
+ int *mnemonic;
+ char_u **actext;
+{
+ char_u *p;
+ char_u *text;
+
+ /* Locate accelerator text, after the first TAB */
+ p = vim_strchr(str, TAB);
+ if (p != NULL)
+ {
+ if (actext != NULL)
+ *actext = vim_strsave(p + 1);
+ text = vim_strnsave(str, (int)(p - str));
+ }
+ else
+ text = vim_strsave(str);
+
+ /* Find mnemonic characters "&a" and reduce "&&" to "&". */
+ for (p = text; p != NULL; )
+ {
+ p = vim_strchr(p, '&');
+ if (p != NULL)
+ {
+ if (p[1] == NUL) /* trailing "&" */
+ break;
+ if (mnemonic != NULL && p[1] != '&')
+#if !defined(__MVS__) || defined(MOTIF390_MNEMONIC_FIXED)
+ *mnemonic = p[1];
+#else
+ {
+ /*
+ * Well there is a bug in the Motif libraries on OS390 Unix.
+ * The mnemonic keys needs to be converted to ASCII values
+ * first.
+ * This behavior has been seen in 2.8 and 2.9.
+ */
+ char c = p[1];
+ __etoa_l(&c, 1);
+ *mnemonic = c;
+ }
+#endif
+ mch_memmove(p, p + 1, STRLEN(p));
+ p = p + 1;
+ }
+ }
+ return text;
+}
+
+/*
+ * Return TRUE if "name" can be a menu in the MenuBar.
+ */
+ int
+menu_is_menubar(name)
+ char_u *name;
+{
+ return (!menu_is_popup(name)
+ && !menu_is_toolbar(name)
+ && *name != MNU_HIDDEN_CHAR);
+}
+
+/*
+ * Return TRUE if "name" is a popup menu name.
+ */
+ int
+menu_is_popup(name)
+ char_u *name;
+{
+ return (STRNCMP(name, "PopUp", 5) == 0);
+}
+
+#if (defined(FEAT_GUI_MOTIF) && (XmVersion <= 1002)) || defined(PROTO)
+/*
+ * Return TRUE if "name" is part of a popup menu.
+ */
+ int
+menu_is_child_of_popup(menu)
+ vimmenu_T *menu;
+{
+ while (menu->parent != NULL)
+ menu = menu->parent;
+ return menu_is_popup(menu->name);
+}
+#endif
+
+/*
+ * Return TRUE if "name" is a toolbar menu name.
+ */
+ int
+menu_is_toolbar(name)
+ char_u *name;
+{
+ return (STRNCMP(name, "ToolBar", 7) == 0);
+}
+
+/*
+ * Return TRUE if the name is a menu separator identifier: Starts and ends
+ * with '-'
+ */
+ int
+menu_is_separator(name)
+ char_u *name;
+{
+ return (name[0] == '-' && name[STRLEN(name) - 1] == '-');
+}
+
+/*
+ * Return TRUE if the menu is hidden: Starts with ']'
+ */
+ static int
+menu_is_hidden(name)
+ char_u *name;
+{
+ return (name[0] == ']') || (menu_is_popup(name) && name[5] != NUL);
+}
+
+#if defined(FEAT_CMDL_COMPL) \
+ || (defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF))
+/*
+ * Return TRUE if the menu is the tearoff menu.
+ */
+/*ARGSUSED*/
+ static int
+menu_is_tearoff(name)
+ char_u *name;
+{
+#ifdef FEAT_GUI
+ return (STRCMP(name, TEAR_STRING) == 0);
+#else
+ return FALSE;
+#endif
+}
+#endif
+
+#ifdef FEAT_GUI
+
+ static int
+get_menu_mode()
+{
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ return MENU_INDEX_VISUAL;
+#endif
+ if (State & INSERT)
+ return MENU_INDEX_INSERT;
+ if ((State & CMDLINE) || State == ASKMORE || State == HITRETURN)
+ return MENU_INDEX_CMDLINE;
+ if (finish_op)
+ return MENU_INDEX_OP_PENDING;
+ if (State & NORMAL)
+ return MENU_INDEX_NORMAL;
+ if (State & LANGMAP) /* must be a "r" command, like Insert mode */
+ return MENU_INDEX_INSERT;
+ return MENU_INDEX_INVALID;
+}
+
+/*
+ * After we have started the GUI, then we can create any menus that have been
+ * defined. This is done once here. add_menu_path() may have already been
+ * called to define these menus, and may be called again. This function calls
+ * itself recursively. Should be called at the top level with:
+ * gui_create_initial_menus(root_menu, NULL);
+ */
+ void
+gui_create_initial_menus(menu)
+ vimmenu_T *menu;
+{
+ int idx = 0;
+
+ while (menu != NULL)
+ {
+ /* Don't add a menu when only a tip was defined. */
+ if (menu->modes & MENU_ALL_MODES)
+ {
+ if (menu->children != NULL)
+ {
+ gui_mch_add_menu(menu, idx);
+ gui_create_initial_menus(menu->children);
+ }
+ else
+ gui_mch_add_menu_item(menu, idx);
+ }
+ menu = menu->next;
+ ++idx;
+ }
+}
+
+/*
+ * Used recursively by gui_update_menus (see below)
+ */
+ static void
+gui_update_menus_recurse(menu, mode)
+ vimmenu_T *menu;
+ int mode;
+{
+ int grey;
+
+ while (menu)
+ {
+ if ((menu->modes & menu->enabled & mode)
+#if defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF)
+ || menu_is_tearoff(menu->dname)
+#endif
+ )
+ grey = FALSE;
+ else
+ grey = TRUE;
+#ifdef FEAT_GUI_ATHENA
+ /* Hiding menus doesn't work for Athena, it can cause a crash. */
+ gui_mch_menu_grey(menu, grey);
+#else
+ /* Never hide a toplevel menu, it may make the menubar resize or
+ * disappear. Same problem for ToolBar items. */
+ if (vim_strchr(p_go, GO_GREY) != NULL || menu->parent == NULL
+# ifdef FEAT_TOOLBAR
+ || menu_is_toolbar(menu->parent->name)
+# endif
+ )
+ gui_mch_menu_grey(menu, grey);
+ else
+ gui_mch_menu_hidden(menu, grey);
+#endif
+ gui_update_menus_recurse(menu->children, mode);
+ menu = menu->next;
+ }
+}
+
+/*
+ * Make sure only the valid menu items appear for this mode. If
+ * force_menu_update is not TRUE, then we only do this if the mode has changed
+ * since last time. If "modes" is not 0, then we use these modes instead.
+ */
+ void
+gui_update_menus(modes)
+ int modes;
+{
+ static int prev_mode = -1;
+ int mode = 0;
+
+ if (modes != 0x0)
+ mode = modes;
+ else
+ {
+ mode = get_menu_mode();
+ if (mode == MENU_INDEX_INVALID)
+ mode = 0;
+ else
+ mode = (1 << mode);
+ }
+
+ if (force_menu_update || mode != prev_mode)
+ {
+ gui_update_menus_recurse(root_menu, mode);
+ gui_mch_draw_menubar();
+ prev_mode = mode;
+ force_menu_update = FALSE;
+#ifdef FEAT_GUI_W32
+ /* This can leave a tearoff as active window - make sure we
+ * have the focus <negri>*/
+ gui_mch_activate_window();
+#endif
+ }
+}
+
+#if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
+ || defined(FEAT_GUI_PHOTON) || defined(PROTO)
+/*
+ * Check if a key is used as a mnemonic for a toplevel menu.
+ * Case of the key is ignored.
+ */
+ int
+gui_is_menu_shortcut(key)
+ int key;
+{
+ vimmenu_T *menu;
+
+ if (key < 256)
+ key = TOLOWER_LOC(key);
+ for (menu = root_menu; menu != NULL; menu = menu->next)
+ if (menu->mnemonic == key
+ || (menu->mnemonic < 256 && TOLOWER_LOC(menu->mnemonic) == key))
+ return TRUE;
+ return FALSE;
+}
+#endif
+
+/*
+ * Display the Special "PopUp" menu as a pop-up at the current mouse
+ * position. The "PopUpn" menu is for Normal mode, "PopUpi" for Insert mode,
+ * etc.
+ */
+ void
+gui_show_popupmenu()
+{
+ vimmenu_T *menu;
+ int mode;
+
+ mode = get_menu_mode();
+ if (mode == MENU_INDEX_INVALID)
+ return;
+ mode = menu_mode_chars[mode];
+
+ for (menu = root_menu; menu != NULL; menu = menu->next)
+ if (STRNCMP("PopUp", menu->name, 5) == 0 && menu->name[5] == mode)
+ break;
+
+ /* Only show a popup when it is defined and has entries */
+ if (menu != NULL && menu->children != NULL)
+ gui_mch_show_popupmenu(menu);
+}
+#endif /* FEAT_GUI */
+
+#if (defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF)) || defined(PROTO)
+
+/*
+ * Deal with tearoff items that are added like a menu item.
+ * Currently only for Win32 GUI. Others may follow later.
+ */
+
+ void
+gui_mch_toggle_tearoffs(int enable)
+{
+ int pri_tab[MENUDEPTH + 1];
+ int i;
+
+ if (enable)
+ {
+ for (i = 0; i < MENUDEPTH; ++i)
+ pri_tab[i] = 500;
+ pri_tab[MENUDEPTH] = -1;
+ gui_create_tearoffs_recurse(root_menu, (char_u *)"", pri_tab, 0);
+ }
+ else
+ gui_destroy_tearoffs_recurse(root_menu);
+ s_tearoffs = enable;
+}
+
+/*
+ * Recursively add tearoff items
+ */
+ static void
+gui_create_tearoffs_recurse(menu, pname, pri_tab, pri_idx)
+ vimmenu_T *menu;
+ const char_u *pname;
+ int *pri_tab;
+ int pri_idx;
+{
+ char_u *newpname = NULL;
+ int len;
+ char_u *s;
+ char_u *d;
+
+ if (pri_tab[pri_idx + 1] != -1)
+ ++pri_idx;
+ while (menu != NULL)
+ {
+ if (menu->children != NULL && menu_is_menubar(menu->name))
+ {
+ /* Add the menu name to the menu path. Insert a backslash before
+ * dots (it's used to separate menu names). */
+ len = (int)STRLEN(pname) + (int)STRLEN(menu->name);
+ for (s = menu->name; *s; ++s)
+ if (*s == '.' || *s == '\\')
+ ++len;
+ newpname = alloc(len + TEAR_LEN + 2);
+ if (newpname != NULL)
+ {
+ STRCPY(newpname, pname);
+ d = newpname + STRLEN(newpname);
+ for (s = menu->name; *s; ++s)
+ {
+ if (*s == '.' || *s == '\\')
+ *d++ = '\\';
+ *d++ = *s;
+ }
+ *d = NUL;
+
+ /* check if tearoff already exists */
+ if (STRCMP(menu->children->name, TEAR_STRING) != 0)
+ {
+ gui_add_tearoff(newpname, pri_tab, pri_idx - 1);
+ *d = NUL; /* remove TEAR_STRING */
+ }
+
+ STRCAT(newpname, ".");
+ gui_create_tearoffs_recurse(menu->children, newpname,
+ pri_tab, pri_idx);
+ vim_free(newpname);
+ }
+ }
+ menu = menu->next;
+ }
+}
+
+/*
+ * Add tear-off menu item for a submenu.
+ * "tearpath" is the menu path, and must have room to add TEAR_STRING.
+ */
+ static void
+gui_add_tearoff(tearpath, pri_tab, pri_idx)
+ char_u *tearpath;
+ int *pri_tab;
+ int pri_idx;
+{
+ char_u *tbuf;
+ int t;
+ vimmenu_T menuarg;
+
+ tbuf = alloc(5 + (unsigned int)STRLEN(tearpath));
+ if (tbuf != NULL)
+ {
+ tbuf[0] = K_SPECIAL;
+ tbuf[1] = K_SECOND(K_TEAROFF);
+ tbuf[2] = K_THIRD(K_TEAROFF);
+ STRCPY(tbuf + 3, tearpath);
+ STRCAT(tbuf + 3, "\r");
+
+ STRCAT(tearpath, ".");
+ STRCAT(tearpath, TEAR_STRING);
+
+ /* Priority of tear-off is always 1 */
+ t = pri_tab[pri_idx + 1];
+ pri_tab[pri_idx + 1] = 1;
+
+#ifdef FEAT_TOOLBAR
+ menuarg.iconfile = NULL;
+ menuarg.iconidx = -1;
+ menuarg.icon_builtin = FALSE;
+#endif
+ menuarg.noremap[0] = REMAP_NONE;
+ menuarg.silent[0] = TRUE;
+
+ menuarg.modes = MENU_ALL_MODES;
+ add_menu_path(tearpath, &menuarg, pri_tab, tbuf, FALSE);
+
+ menuarg.modes = MENU_TIP_MODE;
+ add_menu_path(tearpath, &menuarg, pri_tab,
+ (char_u *)_("Tear off this menu"), FALSE);
+
+ pri_tab[pri_idx + 1] = t;
+ vim_free(tbuf);
+ }
+}
+
+/*
+ * Recursively destroy tearoff items
+ */
+ static void
+gui_destroy_tearoffs_recurse(menu)
+ vimmenu_T *menu;
+{
+ while (menu)
+ {
+ if (menu->children)
+ {
+ /* check if tearoff exists */
+ if (STRCMP(menu->children->name, TEAR_STRING) == 0)
+ {
+ /* Disconnect the item and free the memory */
+ free_menu(&menu->children);
+ }
+ if (menu->children != NULL) /* if not the last one */
+ gui_destroy_tearoffs_recurse(menu->children);
+ }
+ menu = menu->next;
+ }
+}
+
+#endif /* FEAT_GUI_W32 && FEAT_TEAROFF */
+
+/*
+ * Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy and
+ * execute it.
+ */
+ void
+ex_emenu(eap)
+ exarg_T *eap;
+{
+ vimmenu_T *menu;
+ char_u *name;
+ char_u *saved_name;
+ char_u *p;
+ int idx;
+ char_u *mode;
+
+ saved_name = vim_strsave(eap->arg);
+ if (saved_name == NULL)
+ return;
+
+ menu = root_menu;
+ name = saved_name;
+ while (*name)
+ {
+ /* Find in the menu hierarchy */
+ p = menu_name_skip(name);
+
+ while (menu != NULL)
+ {
+ if (menu_name_equal(name, menu))
+ {
+ if (*p == NUL && menu->children != NULL)
+ {
+ EMSG(_("E333: Menu path must lead to a menu item"));
+ menu = NULL;
+ }
+ else if (*p != NUL && menu->children == NULL)
+ {
+ EMSG(_(e_notsubmenu));
+ menu = NULL;
+ }
+ break;
+ }
+ menu = menu->next;
+ }
+ if (menu == NULL || *p == NUL)
+ break;
+ menu = menu->children;
+ name = p;
+ }
+ vim_free(saved_name);
+ if (menu == NULL)
+ {
+ EMSG2(_("E334: Menu not found: %s"), eap->arg);
+ return;
+ }
+
+ /* Found the menu, so execute. */
+ if (restart_edit)
+ {
+ mode = (char_u *)"Insert";
+ idx = MENU_INDEX_INSERT;
+ }
+ else if (eap->addr_count)
+ {
+ pos_T tpos;
+
+ mode = (char_u *)"Visual";
+ idx = MENU_INDEX_VISUAL;
+
+ /* GEDDES: This is not perfect - but it is a
+ * quick way of detecting whether we are doing this from a
+ * selection - see if the range matches up with the visual
+ * select start and end.
+ */
+ if ((curbuf->b_visual_start.lnum == eap->line1)
+ && (curbuf->b_visual_end.lnum) == eap->line2)
+ {
+ /* Set it up for visual mode - equivalent to gv. */
+ VIsual_mode = curbuf->b_visual_mode;
+ tpos = curbuf->b_visual_end;
+ curwin->w_cursor = curbuf->b_visual_start;
+ curwin->w_curswant = curbuf->b_visual_curswant;
+ }
+ else
+ {
+ /* Set it up for line-wise visual mode */
+ VIsual_mode = 'V';
+ curwin->w_cursor.lnum = eap->line1;
+ curwin->w_cursor.col = 1;
+ tpos.lnum = eap->line2;
+ tpos.col = MAXCOL;
+ }
+
+ /* Activate visual mode
+ */
+ VIsual_active = TRUE;
+ VIsual_reselect = TRUE;
+ check_cursor();
+ VIsual = curwin->w_cursor;
+ curwin->w_cursor = tpos;
+
+ check_cursor();
+
+ /* Adjust the cursor to make sure it is in the correct pos
+ * for exclusive mode
+ */
+ if (*p_sel == 'e' && gchar_cursor() != NUL)
+ ++curwin->w_cursor.col;
+ }
+ else
+ {
+ mode = (char_u *)"Normal";
+ idx = MENU_INDEX_NORMAL;
+ }
+
+ if (idx != MENU_INDEX_INVALID && menu->strings[idx] != NULL)
+ {
+ ins_typebuf(menu->strings[idx], menu->noremap[idx], 0,
+ TRUE, menu->silent[idx]);
+ }
+ else
+ EMSG2(_("E335: Menu not defined for %s mode"), mode);
+}
+
+#if defined(FEAT_GUI_MSWIN) \
+ || (defined(FEAT_GUI_GTK) && defined(FEAT_MENU)) \
+ || defined(FEAT_BEVAL_TIP) || defined(PROTO)
+/*
+ * Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy.
+ */
+ vimmenu_T *
+gui_find_menu(path_name)
+ char_u *path_name;
+{
+ vimmenu_T *menu = NULL;
+ char_u *name;
+ char_u *saved_name;
+ char_u *p;
+
+ menu = root_menu;
+
+ saved_name = vim_strsave(path_name);
+ if (saved_name == NULL)
+ return NULL;
+
+ name = saved_name;
+ while (*name)
+ {
+ /* find the end of one dot-separated name and put a NUL at the dot */
+ p = menu_name_skip(name);
+
+ while (menu != NULL)
+ {
+ if (STRCMP(name, menu->name) == 0 || STRCMP(name, menu->dname) == 0)
+ {
+ if (menu->children == NULL)
+ {
+ /* found a menu item instead of a sub-menu */
+ if (*p == NUL)
+ EMSG(_("E336: Menu path must lead to a sub-menu"));
+ else
+ EMSG(_(e_notsubmenu));
+ menu = NULL;
+ goto theend;
+ }
+ if (*p == NUL) /* found a full match */
+ goto theend;
+ break;
+ }
+ menu = menu->next;
+ }
+ if (menu == NULL) /* didn't find it */
+ break;
+
+ /* Found a match, search the sub-menu. */
+ menu = menu->children;
+ name = p;
+ }
+
+ if (menu == NULL)
+ EMSG(_("E337: Menu not found - check menu names"));
+theend:
+ vim_free(saved_name);
+ return menu;
+}
+#endif
+
+#ifdef FEAT_MULTI_LANG
+/*
+ * Translation of menu names. Just a simple lookup table.
+ */
+
+typedef struct
+{
+ char_u *from; /* English name */
+ char_u *from_noamp; /* same, without '&' */
+ char_u *to; /* translated name */
+} menutrans_T;
+
+static garray_T menutrans_ga = {0, 0, 0, 0, NULL};
+#endif
+
+/*
+ * ":menutrans".
+ * This function is also defined without the +multi_lang feature, in which
+ * case the commands are ignored.
+ */
+/*ARGSUSED*/
+ void
+ex_menutranslate(eap)
+ exarg_T *eap;
+{
+#ifdef FEAT_MULTI_LANG
+ char_u *arg = eap->arg;
+ menutrans_T *tp;
+ int i;
+ char_u *from, *from_noamp, *to;
+
+ if (menutrans_ga.ga_itemsize == 0)
+ ga_init2(&menutrans_ga, (int)sizeof(menutrans_T), 5);
+
+ /*
+ * ":menutrans clear": clear all translations.
+ */
+ if (STRNCMP(arg, "clear", 5) == 0 && ends_excmd(*skipwhite(arg + 5)))
+ {
+ tp = (menutrans_T *)menutrans_ga.ga_data;
+ for (i = 0; i < menutrans_ga.ga_len; ++i)
+ {
+ vim_free(tp[i].from);
+ vim_free(tp[i].from_noamp);
+ vim_free(tp[i].to);
+ }
+ ga_clear(&menutrans_ga);
+# ifdef FEAT_EVAL
+ /* Delete all "menutrans_" global variables. */
+ del_menutrans_vars();
+# endif
+ }
+ else
+ {
+ /* ":menutrans from to": add translation */
+ from = arg;
+ arg = menu_skip_part(arg);
+ to = skipwhite(arg);
+ *arg = NUL;
+ arg = menu_skip_part(to);
+ if (arg == to)
+ EMSG(_(e_invarg));
+ else
+ {
+ if (ga_grow(&menutrans_ga, 1) == OK)
+ {
+ tp = (menutrans_T *)menutrans_ga.ga_data;
+ from = vim_strsave(from);
+ from_noamp = menu_text(from, NULL, NULL);
+ to = vim_strnsave(to, (int)(arg - to));
+ if (from != NULL && from_noamp != NULL && to != NULL)
+ {
+ tp[menutrans_ga.ga_len].from = from;
+ tp[menutrans_ga.ga_len].from_noamp = from_noamp;
+ tp[menutrans_ga.ga_len].to = to;
+ ++menutrans_ga.ga_len;
+ --menutrans_ga.ga_room;
+ }
+ else
+ {
+ vim_free(from);
+ vim_free(from_noamp);
+ vim_free(to);
+ }
+ }
+ }
+ }
+#endif
+}
+
+#if defined(FEAT_MULTI_LANG) || defined(FEAT_TOOLBAR)
+/*
+ * Find the character just after one part of a menu name.
+ */
+ static char_u *
+menu_skip_part(p)
+ char_u *p;
+{
+ while (*p != NUL && *p != '.' && !vim_iswhite(*p))
+ {
+ if ((*p == '\\' || *p == Ctrl_V) && p[1] != NUL)
+ ++p;
+ ++p;
+ }
+ return p;
+}
+#endif
+
+#ifdef FEAT_MULTI_LANG
+/*
+ * Lookup part of a menu name in the translations.
+ * Return a pointer to the translation or NULL if not found.
+ */
+ static char_u *
+menutrans_lookup(name, len)
+ char_u *name;
+ int len;
+{
+ menutrans_T *tp = (menutrans_T *)menutrans_ga.ga_data;
+ int i;
+ char_u *dname;
+
+ for (i = 0; i < menutrans_ga.ga_len; ++i)
+ if (STRNCMP(name, tp[i].from, len) == 0 && tp[i].from[len] == NUL)
+ return tp[i].to;
+
+ /* Now try again while ignoring '&' characters. */
+ i = name[len];
+ name[len] = NUL;
+ dname = menu_text(name, NULL, NULL);
+ name[len] = i;
+ if (dname != NULL)
+ {
+ for (i = 0; i < menutrans_ga.ga_len; ++i)
+ if (STRCMP(dname, tp[i].from_noamp) == 0)
+ {
+ vim_free(dname);
+ return tp[i].to;
+ }
+ vim_free(dname);
+ }
+
+ return NULL;
+}
+#endif /* FEAT_MULTI_LANG */
+
+#endif /* FEAT_MENU */
diff --git a/src/message.c b/src/message.c
new file mode 100644
index 000000000..405ae6e03
--- /dev/null
+++ b/src/message.c
@@ -0,0 +1,3165 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * message.c: functions for displaying messages on the command line
+ */
+
+#define MESSAGE_FILE /* don't include prototype for smsg() */
+
+#include "vim.h"
+
+#ifdef HAVE_STDARG_H
+# include <stdarg.h>
+#endif
+
+static void reset_last_sourcing __ARGS((void));
+static char_u *get_emsg_source __ARGS((int other));
+static char_u *get_emsg_lnum __ARGS((int other));
+static void add_msg_hist __ARGS((char_u *s, int len, int attr));
+static void hit_return_msg __ARGS((void));
+static void msg_home_replace_attr __ARGS((char_u *fname, int attr));
+#ifdef FEAT_MBYTE
+static char_u *screen_puts_mbyte __ARGS((char_u *s, int l, int attr));
+#endif
+static void msg_puts_attr_len __ARGS((char_u *str, int maxlen, int attr));
+static void t_puts __ARGS((int t_col, char_u *t_s, char_u *s, int attr));
+static void msg_screen_putchar __ARGS((int c, int attr));
+static int msg_check_screen __ARGS((void));
+static void redir_write __ARGS((char_u *s, int maxlen));
+#ifdef FEAT_CON_DIALOG
+static char_u *msg_show_console_dialog __ARGS((char_u *message, char_u *buttons, int dfltbutton));
+static int confirm_msg_used = FALSE; /* displaying confirm_msg */
+static char_u *confirm_msg = NULL; /* ":confirm" message */
+static char_u *confirm_msg_tail; /* tail of confirm_msg */
+#endif
+
+struct msg_hist
+{
+ struct msg_hist *next;
+ char_u *msg;
+ int attr;
+};
+
+static struct msg_hist *first_msg_hist = NULL;
+static struct msg_hist *last_msg_hist = NULL;
+static int msg_hist_len = 0;
+static int msg_hist_off = FALSE; /* don't add messages to history */
+
+/*
+ * When writing messages to the screen, there are many different situations.
+ * A number of variables is used to remember the current state:
+ * msg_didany TRUE when messages were written since the last time the
+ * user reacted to a prompt.
+ * Reset: After hitting a key for the hit-return prompt,
+ * hitting <CR> for the command line or input().
+ * Set: When any message is written to the screen.
+ * msg_didout TRUE when something was written to the current line.
+ * Reset: When advancing to the next line, when the current
+ * text can be overwritten.
+ * Set: When any message is written to the screen.
+ * msg_nowait No extra delay for the last drawn message.
+ * Used in normal_cmd() before the mode message is drawn.
+ * emsg_on_display There was an error message recently. Indicates that there
+ * should be a delay before redrawing.
+ * msg_scroll The next message should not overwrite the current one.
+ * msg_scrolled How many lines the screen has been scrolled (because of
+ * messages). Used in update_screen() to scroll the screen
+ * back. Incremented each time the screen scrolls a line.
+ * msg_scrolled_ign TRUE when msg_scrolled is non-zero and msg_puts_attr()
+ * writes something without scrolling should not make
+ * need_wait_return to be set. This is a hack to make ":ts"
+ * work without an extra prompt.
+ * lines_left Number of lines available for messages before the
+ * more-prompt is to be given.
+ * need_wait_return TRUE when the hit-return prompt is needed.
+ * Reset: After giving the hit-return prompt, when the user
+ * has answered some other prompt.
+ * Set: When the ruler or typeahead display is overwritten,
+ * scrolling the screen for some message.
+ * keep_msg Message to be displayed after redrawing the screen, in
+ * main_loop().
+ * This is an allocated string or NULL when not used.
+ */
+
+/*
+ * msg(s) - displays the string 's' on the status line
+ * When terminal not initialized (yet) mch_errmsg(..) is used.
+ * return TRUE if wait_return not called
+ */
+ int
+msg(s)
+ char_u *s;
+{
+ return msg_attr_keep(s, 0, FALSE);
+}
+
+ int
+msg_attr(s, attr)
+ char_u *s;
+ int attr;
+{
+ return msg_attr_keep(s, attr, FALSE);
+}
+
+ int
+msg_attr_keep(s, attr, keep)
+ char_u *s;
+ int attr;
+ int keep; /* TRUE: set keep_msg if it doesn't scroll */
+{
+ static int entered = 0;
+ int retval;
+ char_u *buf = NULL;
+
+#ifdef FEAT_EVAL
+ if (attr == 0)
+ set_vim_var_string(VV_STATUSMSG, s, -1);
+#endif
+
+ /*
+ * It is possible that displaying a messages causes a problem (e.g.,
+ * when redrawing the window), which causes another message, etc.. To
+ * break this loop, limit the recursiveness to 3 levels.
+ */
+ if (entered >= 3)
+ return TRUE;
+ ++entered;
+
+ /* Add message to history (unless it's a repeated kept message or a
+ * truncated message) */
+ if (s != keep_msg
+ || (*s != '<'
+ && last_msg_hist != NULL
+ && last_msg_hist->msg != NULL
+ && STRCMP(s, last_msg_hist->msg)))
+ add_msg_hist(s, -1, attr);
+
+ /* When displaying keep_msg, don't let msg_start() free it, caller must do
+ * that. */
+ if (s == keep_msg)
+ keep_msg = NULL;
+
+ /* Truncate the message if needed. */
+ buf = msg_strtrunc(s);
+ if (buf != NULL)
+ s = buf;
+
+ msg_start();
+ msg_outtrans_attr(s, attr);
+ msg_clr_eos();
+ retval = msg_end();
+
+ if (keep && retval && vim_strsize(s) < (int)(Rows - cmdline_row - 1)
+ * Columns + sc_col)
+ {
+ set_keep_msg(s);
+ keep_msg_attr = 0;
+ }
+
+ vim_free(buf);
+ --entered;
+ return retval;
+}
+
+/*
+ * Truncate a string such that it can be printed without causing a scroll.
+ * Returns an allocated string or NULL when no truncating is done.
+ */
+ char_u *
+msg_strtrunc(s)
+ char_u *s;
+{
+ char_u *buf = NULL;
+ int len;
+ int room;
+
+ /* May truncate message to avoid a hit-return prompt */
+ if (!msg_scroll && !need_wait_return && shortmess(SHM_TRUNCALL)
+ && !exmode_active)
+ {
+ len = vim_strsize(s);
+ room = (int)(Rows - cmdline_row - 1) * Columns + sc_col - 1;
+ if (len > room && room > 0)
+ {
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ /* may have up to 18 bytes per cell (6 per char, up to two
+ * composing chars) */
+ buf = alloc((room + 2) * 18);
+ else if (enc_dbcs == DBCS_JPNU)
+ /* may have up to 2 bytes per cell for euc-jp */
+ buf = alloc((room + 2) * 2);
+ else
+#endif
+ buf = alloc(room + 2);
+ if (buf != NULL)
+ trunc_string(s, buf, room);
+ }
+ }
+ return buf;
+}
+
+/*
+ * Truncate a string "s" to "buf" with cell width "room".
+ * "s" and "buf" may be equal.
+ */
+ void
+trunc_string(s, buf, room)
+ char_u *s;
+ char_u *buf;
+ int room;
+{
+ int half;
+ int len;
+ int e;
+ int i;
+ int n;
+
+ room -= 3;
+ half = room / 2;
+ len = 0;
+
+ /* First part: Start of the string. */
+ for (e = 0; len < half; ++e)
+ {
+ if (s[e] == NUL)
+ {
+ /* text fits without truncating! */
+ buf[e] = NUL;
+ return;
+ }
+ n = ptr2cells(s + e);
+ if (len + n >= half)
+ break;
+ len += n;
+ buf[e] = s[e];
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ for (n = (*mb_ptr2len_check)(s + e); --n > 0; )
+ {
+ ++e;
+ buf[e] = s[e];
+ }
+#endif
+ }
+
+ /* Last part: End of the string. */
+ i = e;
+#ifdef FEAT_MBYTE
+ if (enc_dbcs != 0)
+ {
+ /* For DBCS going backwards in a string is slow, but
+ * computing the cell width isn't too slow: go forward
+ * until the rest fits. */
+ n = vim_strsize(s + i);
+ while (len + n > room)
+ {
+ n -= ptr2cells(s + i);
+ i += (*mb_ptr2len_check)(s + i);
+ }
+ }
+ else if (enc_utf8)
+ {
+ /* For UTF-8 we can go backwards easily. */
+ i = (int)STRLEN(s);
+ for (;;)
+ {
+ half = i - (*mb_head_off)(s, s + i - 1) - 1;
+ n = ptr2cells(s + half);
+ if (len + n > room)
+ break;
+ len += n;
+ i = half;
+ }
+ }
+ else
+#endif
+ {
+ for (i = (int)STRLEN(s); len + (n = ptr2cells(s + i - 1)) <= room; --i)
+ len += n;
+ }
+
+ /* Set the middle and copy the last part. */
+ mch_memmove(buf + e, "...", (size_t)3);
+ mch_memmove(buf + e + 3, s + i, STRLEN(s + i) + 1);
+}
+
+/*
+ * Automatic prototype generation does not understand this function.
+ * Note: Caller of smgs() and smsg_attr() must check the resulting string is
+ * shorter than IOSIZE!!!
+ */
+#ifndef PROTO
+# ifndef HAVE_STDARG_H
+
+int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+smsg __ARGS((char_u *, long, long, long,
+ long, long, long, long, long, long, long));
+int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+smsg_attr __ARGS((int, char_u *, long, long, long,
+ long, long, long, long, long, long, long));
+
+/* VARARGS */
+ int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
+ char_u *s;
+ long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
+{
+ return smsg_attr(0, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
+}
+
+/* VARARGS */
+ int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+smsg_attr(attr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
+ int attr;
+ char_u *s;
+ long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
+{
+ sprintf((char *)IObuff, (char *)s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
+ return msg_attr(IObuff, attr);
+}
+
+# else /* HAVE_STDARG_H */
+
+ int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+smsg(char_u *s, ...)
+{
+ va_list arglist;
+
+ va_start(arglist, s);
+# ifdef HAVE_VSNPRINTF
+ vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist);
+# else
+ vsprintf((char *)IObuff, (char *)s, arglist);
+# endif
+ va_end(arglist);
+ return msg(IObuff);
+}
+
+ int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+smsg_attr(int attr, char_u *s, ...)
+{
+ va_list arglist;
+
+ va_start(arglist, s);
+# ifdef HAVE_VSNPRINTF
+ vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist);
+# else
+ vsprintf((char *)IObuff, (char *)s, arglist);
+# endif
+ va_end(arglist);
+ return msg_attr(IObuff, attr);
+}
+
+# endif /* HAVE_STDARG_H */
+#endif
+
+/*
+ * Remember the last sourcing name/lnum used in an error message, so that it
+ * isn't printed each time when it didn't change.
+ */
+static int last_sourcing_lnum = 0;
+static char_u *last_sourcing_name = NULL;
+
+/*
+ * Reset the last used sourcing name/lnum. Makes sure it is displayed again
+ * for the next error message;
+ */
+ static void
+reset_last_sourcing()
+{
+ vim_free(last_sourcing_name);
+ last_sourcing_name = NULL;
+ last_sourcing_lnum = 0;
+}
+
+/*
+ * Get the message about the source, as used for an error message.
+ * Returns an allocated string with room for one more character.
+ * Returns NULL when no message is to be given.
+ */
+ static char_u *
+get_emsg_source(other)
+ int other; /* TRUE when "sourcing_name" differs from last time */
+{
+ char_u *Buf, *p;
+
+ if (sourcing_name != NULL && other)
+ {
+ p = (char_u *)_("Error detected while processing %s:");
+ Buf = alloc((unsigned)(STRLEN(sourcing_name) + STRLEN(p)));
+ if (Buf != NULL)
+ sprintf((char *)Buf, (char *)p, sourcing_name);
+ return Buf;
+ }
+ return NULL;
+}
+
+/*
+ * Get the message about the source lnum, as used for an error message.
+ * Returns an allocated string with room for one more character.
+ * Returns NULL when no message is to be given.
+ */
+ static char_u *
+get_emsg_lnum(other)
+ int other; /* TRUE when "sourcing_name" differs from last time */
+{
+ char_u *Buf, *p;
+
+ /* lnum is 0 when executing a command from the command line
+ * argument, we don't want a line number then */
+ if (sourcing_name != NULL
+ && (other || sourcing_lnum != last_sourcing_lnum)
+ && sourcing_lnum != 0)
+ {
+ p = (char_u *)_("line %4ld:");
+ Buf = alloc((unsigned)(STRLEN(p) + 20));
+ if (Buf != NULL)
+ sprintf((char *)Buf, (char *)p, (long)sourcing_lnum);
+ return Buf;
+ }
+ return NULL;
+}
+
+/*
+ * emsg() - display an error message
+ *
+ * Rings the bell, if appropriate, and calls message() to do the real work
+ * When terminal not initialized (yet) mch_errmsg(..) is used.
+ *
+ * return TRUE if wait_return not called
+ */
+ int
+emsg(s)
+ char_u *s;
+{
+ int attr;
+ int other_sourcing_name;
+ char_u *p;
+#ifdef FEAT_EVAL
+ int ignore = FALSE;
+ int severe;
+#endif
+
+ called_emsg = TRUE;
+
+ /*
+ * If "emsg_severe" is TRUE: When an error exception is to be thrown, prefer
+ * this message over previous messages for the same command.
+ */
+#ifdef FEAT_EVAL
+ severe = emsg_severe;
+ emsg_severe = FALSE;
+#endif
+
+ /*
+ * If "emsg_off" is set: no error messages at the moment.
+ * If 'debug' is set: do error message anyway, but without side effects.
+ * If "emsg_skip" is set: never do error messages.
+ */
+ if ((emsg_off > 0 && *p_debug == NUL)
+#ifdef FEAT_EVAL
+ || emsg_skip > 0
+#endif
+ )
+ return TRUE;
+
+ if (sourcing_name != NULL)
+ {
+ if (last_sourcing_name != NULL)
+ other_sourcing_name = STRCMP(sourcing_name, last_sourcing_name);
+ else
+ other_sourcing_name = TRUE;
+ }
+ else
+ other_sourcing_name = FALSE;
+
+ if (!emsg_off)
+ {
+#ifdef FEAT_EVAL
+ /*
+ * Cause a throw of an error exception if appropriate. Don't display
+ * the error message in this case. (If no matching catch clause will
+ * be found, the message will be displayed later on.) "ignore" is set
+ * when the message should be ignored completely (used for the
+ * interrupt message).
+ */
+ if (cause_errthrow(s, severe, &ignore) == TRUE)
+ {
+ if (!ignore)
+ did_emsg = TRUE;
+ return TRUE;
+ }
+
+ /* set "v:errmsg", also when using ":silent! cmd" */
+ set_vim_var_string(VV_ERRMSG, s, -1);
+#endif
+
+ /*
+ * When using ":silent! cmd" ignore error messsages.
+ * But do write it to the redirection file.
+ */
+ if (emsg_silent != 0)
+ {
+ msg_start();
+ p = get_emsg_source(other_sourcing_name);
+ if (p != NULL)
+ {
+ STRCAT(p, "\n");
+ redir_write(p, -1);
+ vim_free(p);
+ }
+ p = get_emsg_lnum(other_sourcing_name);
+ if (p != NULL)
+ {
+ STRCAT(p, "\n");
+ redir_write(p, -1);
+ vim_free(p);
+ }
+ redir_write(s, -1);
+ return TRUE;
+ }
+
+ /* Reset msg_silent, an error causes messages to be switched back on. */
+ msg_silent = 0;
+ cmd_silent = FALSE;
+
+ if (global_busy) /* break :global command */
+ ++global_busy;
+
+ if (p_eb)
+ beep_flush(); /* also includes flush_buffers() */
+ else
+ flush_buffers(FALSE); /* flush internal buffers */
+ did_emsg = TRUE; /* flag for DoOneCmd() */
+
+#ifdef VIMBUDDY
+ if (sourcing_name == NULL)
+ {
+ VimBuddyText(s, 2);
+ return TRUE;
+ }
+#endif
+ }
+
+ emsg_on_display = TRUE; /* remember there is an error message */
+ ++msg_scroll; /* don't overwrite a previous message */
+ attr = hl_attr(HLF_E); /* set highlight mode for error messages */
+ if (msg_scrolled)
+ need_wait_return = TRUE; /* needed in case emsg() is called after
+ * wait_return has reset need_wait_return
+ * and a redraw is expected because
+ * msg_scrolled is non-zero */
+
+ /*
+ * Display name and line number for the source of the error.
+ */
+ ++no_wait_return;
+ p = get_emsg_source(other_sourcing_name);
+ if (p != NULL)
+ {
+ msg_attr(p, attr);
+ vim_free(p);
+ }
+ p = get_emsg_lnum(other_sourcing_name);
+ if (p != NULL)
+ {
+ msg_attr(p, hl_attr(HLF_N));
+ vim_free(p);
+ last_sourcing_lnum = sourcing_lnum; /* only once for each line */
+ }
+ --no_wait_return;
+
+ /* remember the last sourcing name printed, also when it's empty */
+ if (sourcing_name == NULL || other_sourcing_name)
+ {
+ vim_free(last_sourcing_name);
+ if (sourcing_name == NULL)
+ last_sourcing_name = NULL;
+ else
+ last_sourcing_name = vim_strsave(sourcing_name);
+ }
+ msg_nowait = FALSE; /* wait for this msg */
+
+ /*
+ * Display the error message itself.
+ */
+ return msg_attr(s, attr);
+}
+
+/*
+ * Print an error message with one "%s" and one string argument.
+ */
+ int
+emsg2(s, a1)
+ char_u *s, *a1;
+{
+ return emsg3(s, a1, NULL);
+}
+
+/*
+ * Print an error message with one or two "%s" and one or two string arguments.
+ */
+ int
+emsg3(s, a1, a2)
+ char_u *s, *a1, *a2;
+{
+ if ((emsg_off > 0 && *p_debug == NUL)
+#ifdef FEAT_EVAL
+ || emsg_skip > 0
+#endif
+ )
+ return TRUE; /* no error messages at the moment */
+
+ /* Check for NULL strings (just in case) */
+ if (a1 == NULL)
+ a1 = (char_u *)"[NULL]";
+ if (a2 == NULL)
+ a2 = (char_u *)"[NULL]";
+
+ /* Check for very long strings (can happen with ":help ^A<CR>"). */
+ if (STRLEN(s) + STRLEN(a1) + STRLEN(a2) >= (size_t)IOSIZE)
+ a1 = a2 = (char_u *)_("[string too long]");
+
+ sprintf((char *)IObuff, (char *)s, (char *)a1, (char *)a2);
+ return emsg(IObuff);
+}
+
+/*
+ * Print an error message with one "%ld" and one long int argument.
+ */
+ int
+emsgn(s, n)
+ char_u *s;
+ long n;
+{
+ if ((emsg_off > 0 && *p_debug == NUL)
+#ifdef FEAT_EVAL
+ || emsg_skip > 0
+#endif
+ )
+ return TRUE; /* no error messages at the moment */
+ sprintf((char *)IObuff, (char *)s, n);
+ return emsg(IObuff);
+}
+
+/*
+ * Like msg(), but truncate to a single line if p_shm contains 't', or when
+ * "force" is TRUE. This truncates in another way as for normal messages.
+ * Careful: The string may be changed by msg_may_trunc()!
+ * Returns a pointer to the printed message, if wait_return() not called.
+ */
+ char_u *
+msg_trunc_attr(s, force, attr)
+ char_u *s;
+ int force;
+ int attr;
+{
+ int n;
+
+ /* Add message to history before truncating */
+ add_msg_hist(s, -1, attr);
+
+ s = msg_may_trunc(force, s);
+
+ msg_hist_off = TRUE;
+ n = msg_attr(s, attr);
+ msg_hist_off = FALSE;
+
+ if (n)
+ return s;
+ return NULL;
+}
+
+/*
+ * Check if message "s" should be truncated at the start (for filenames).
+ * Return a pointer to where the truncated message starts.
+ * Note: May change the message by replacing a character with '<'.
+ */
+ char_u *
+msg_may_trunc(force, s)
+ int force;
+ char_u *s;
+{
+ int n;
+ int room;
+
+ room = (int)(Rows - cmdline_row - 1) * Columns + sc_col - 1;
+ if ((force || (shortmess(SHM_TRUNC) && !exmode_active))
+ && (n = (int)STRLEN(s) - room) > 0)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int size = vim_strsize(s);
+
+ for (n = 0; size >= room; )
+ {
+ size -= (*mb_ptr2cells)(s + n);
+ n += (*mb_ptr2len_check)(s + n);
+ }
+ --n;
+ }
+#endif
+ s += n;
+ *s = '<';
+ }
+ return s;
+}
+
+ static void
+add_msg_hist(s, len, attr)
+ char_u *s;
+ int len; /* -1 for undetermined length */
+ int attr;
+{
+ struct msg_hist *p;
+
+ if (msg_hist_off || msg_silent != 0)
+ return;
+
+ /* Don't let the message history get too big */
+ while (msg_hist_len > 20)
+ {
+ p = first_msg_hist;
+ first_msg_hist = p->next;
+ vim_free(p->msg);
+ vim_free(p);
+ --msg_hist_len;
+ }
+ /* allocate an entry and add the message at the end of the history */
+ p = (struct msg_hist *)alloc((int)sizeof(struct msg_hist));
+ if (p != NULL)
+ {
+ if (len < 0)
+ len = (int)STRLEN(s);
+ /* remove leading and trailing newlines */
+ while (len > 0 && *s == '\n')
+ {
+ ++s;
+ --len;
+ }
+ while (len > 0 && s[len - 1] == '\n')
+ --len;
+ p->msg = vim_strnsave(s, len);
+ p->next = NULL;
+ p->attr = attr;
+ if (last_msg_hist != NULL)
+ last_msg_hist->next = p;
+ last_msg_hist = p;
+ if (first_msg_hist == NULL)
+ first_msg_hist = last_msg_hist;
+ ++msg_hist_len;
+ }
+}
+
+/*
+ * ":messages" command.
+ */
+/*ARGSUSED*/
+ void
+ex_messages(eap)
+ exarg_T *eap;
+{
+ struct msg_hist *p;
+ char_u *s;
+
+ msg_hist_off = TRUE;
+
+ s = mch_getenv((char_u *)"LANG");
+ if (s != NULL && *s != NUL)
+ msg_attr((char_u *)
+ _("Messages maintainer: Bram Moolenaar <Bram@vim.org>"),
+ hl_attr(HLF_T));
+
+ for (p = first_msg_hist; p != NULL; p = p->next)
+ if (p->msg != NULL)
+ msg_attr(p->msg, p->attr);
+
+ msg_hist_off = FALSE;
+}
+
+#if defined(FEAT_CON_DIALOG) || defined(PROTO)
+static void msg_end_prompt __ARGS((void));
+
+/*
+ * Call this after prompting the user. This will avoid a hit-return message
+ * and a delay.
+ */
+ static void
+msg_end_prompt()
+{
+ need_wait_return = FALSE;
+ emsg_on_display = FALSE;
+ cmdline_row = msg_row;
+ msg_col = 0;
+ msg_clr_eos();
+}
+#endif
+
+/*
+ * wait for the user to hit a key (normally a return)
+ * if 'redraw' is TRUE, clear and redraw the screen
+ * if 'redraw' is FALSE, just redraw the screen
+ * if 'redraw' is -1, don't redraw at all
+ */
+ void
+wait_return(redraw)
+ int redraw;
+{
+ int c;
+ int oldState;
+ int tmpState;
+#ifndef ORG_HITRETURN
+ int had_got_int;
+#endif
+
+ if (redraw == TRUE)
+ must_redraw = CLEAR;
+
+ /* If using ":silent cmd", don't wait for a return. Also don't set
+ * need_wait_return to do it later. */
+ if (msg_silent != 0)
+ return;
+
+/*
+ * With the global command (and some others) we only need one return at the
+ * end. Adjust cmdline_row to avoid the next message overwriting the last one.
+ * When inside vgetc(), we can't wait for a typed character at all.
+ */
+ if (vgetc_busy)
+ return;
+ if (no_wait_return)
+ {
+ need_wait_return = TRUE;
+ if (!exmode_active)
+ cmdline_row = msg_row;
+ return;
+ }
+
+ redir_off = TRUE; /* don't redirect this message */
+ oldState = State;
+ if (quit_more)
+ {
+ c = CAR; /* just pretend CR was hit */
+ quit_more = FALSE;
+ got_int = FALSE;
+ }
+ else if (exmode_active)
+ {
+ MSG_PUTS(" "); /* make sure the cursor is on the right line */
+ c = CAR; /* no need for a return in ex mode */
+ got_int = FALSE;
+ }
+ else
+ {
+ /* Make sure the hit-return prompt is on screen when 'guioptions' was
+ * just changed. */
+ screenalloc(FALSE);
+
+ State = HITRETURN;
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = TRUE; /* disallow scrolling here */
+#endif
+ hit_return_msg();
+
+#ifdef ORG_HITRETURN
+ do
+ {
+ c = safe_vgetc();
+ } while (vim_strchr((char_u *)"\r\n: ", c) == NULL);
+ if (c == ':') /* this can vi too (but not always!) */
+ stuffcharReadbuff(c);
+#else
+ do
+ {
+ /* Remember "got_int", if it is set vgetc() probably returns a
+ * CTRL-C, but we need to loop then. */
+ had_got_int = got_int;
+ c = safe_vgetc();
+ if (!global_busy)
+ got_int = FALSE;
+#ifdef FEAT_CLIPBOARD
+ /* Strange way to allow copying (yanking) a modeless selection at
+ * the hit-enter prompt. Use CTRL-Y, because the same is used in
+ * Cmdline-mode and it's harmless when there is no selection. */
+ if (c == Ctrl_Y && clip_star.state == SELECT_DONE)
+ {
+ clip_copy_modeless_selection(TRUE);
+ c = K_IGNORE;
+ }
+#endif
+ } while ((had_got_int && c == Ctrl_C)
+ || c == K_IGNORE
+#ifdef FEAT_GUI
+ || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR
+#endif
+#ifdef FEAT_MOUSE
+ || c == K_LEFTDRAG || c == K_LEFTRELEASE
+ || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
+ || c == K_RIGHTDRAG || c == K_RIGHTRELEASE
+ || c == K_MOUSEDOWN || c == K_MOUSEUP
+ || (!mouse_has(MOUSE_RETURN)
+ && mouse_row < msg_row
+ && (c == K_LEFTMOUSE
+ || c == K_MIDDLEMOUSE
+ || c == K_RIGHTMOUSE
+ || c == K_X1MOUSE
+ || c == K_X2MOUSE))
+#endif
+ );
+ ui_breakcheck();
+#ifdef FEAT_MOUSE
+ /*
+ * Avoid that the mouse-up event causes visual mode to start.
+ */
+ if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE
+ || c == K_X1MOUSE || c == K_X2MOUSE)
+ (void)jump_to_mouse(MOUSE_SETPOS, NULL, 0);
+ else
+#endif
+ if (vim_strchr((char_u *)"\r\n ", c) == NULL && c != Ctrl_C)
+ {
+ stuffcharReadbuff(c);
+ do_redraw = TRUE; /* need a redraw even though there is
+ something in the stuff buffer */
+ }
+#endif
+ }
+ redir_off = FALSE;
+
+ /*
+ * If the user hits ':', '?' or '/' we get a command line from the next
+ * line.
+ */
+ if (c == ':' || c == '?' || c == '/')
+ {
+ if (!exmode_active)
+ cmdline_row = msg_row;
+ skip_redraw = TRUE; /* skip redraw once */
+ do_redraw = FALSE;
+ }
+
+ /*
+ * If the window size changed set_shellsize() will redraw the screen.
+ * Otherwise the screen is only redrawn if 'redraw' is set and no ':'
+ * typed.
+ */
+ tmpState = State;
+ State = oldState; /* restore State before set_shellsize */
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+ msg_check();
+
+#if defined(UNIX) || defined(VMS)
+ /*
+ * When switching screens, we need to output an extra newline on exit.
+ */
+ if (swapping_screen() && !termcap_active)
+ newline_on_exit = TRUE;
+#endif
+
+ need_wait_return = FALSE;
+ did_wait_return = TRUE;
+ emsg_on_display = FALSE; /* can delete error message now */
+ lines_left = -1; /* reset lines_left at next msg_start() */
+ reset_last_sourcing();
+ if (keep_msg != NULL && vim_strsize(keep_msg) >=
+ (Rows - cmdline_row - 1) * Columns + sc_col)
+ {
+ vim_free(keep_msg);
+ keep_msg = NULL; /* don't redisplay message, it's too long */
+ }
+
+ if (tmpState == SETWSIZE) /* got resize event while in vgetc() */
+ {
+ starttermcap(); /* start termcap before redrawing */
+ shell_resized();
+ }
+ else if (!skip_redraw
+ && (redraw == TRUE || (msg_scrolled != 0 && redraw != -1)))
+ {
+ starttermcap(); /* start termcap before redrawing */
+ redraw_later(VALID);
+ }
+}
+
+/*
+ * Write the hit-return prompt.
+ */
+ static void
+hit_return_msg()
+{
+ if (msg_didout) /* start on a new line */
+ msg_putchar('\n');
+ if (got_int)
+ MSG_PUTS(_("Interrupt: "));
+
+#ifdef ORG_HITRETURN
+ MSG_PUTS_ATTR(_("Hit ENTER to continue"), hl_attr(HLF_R));
+#else
+ MSG_PUTS_ATTR(_("Hit ENTER or type command to continue"), hl_attr(HLF_R));
+#endif
+ if (!msg_use_printf())
+ msg_clr_eos();
+}
+
+/*
+ * Set "keep_msg" to "s". Free the old value and check for NULL pointer.
+ */
+ void
+set_keep_msg(s)
+ char_u *s;
+{
+ vim_free(keep_msg);
+ if (s != NULL && msg_silent == 0)
+ keep_msg = vim_strsave(s);
+ else
+ keep_msg = NULL;
+}
+
+/*
+ * Prepare for outputting characters in the command line.
+ */
+ void
+msg_start()
+{
+ int did_return = FALSE;
+
+ vim_free(keep_msg);
+ keep_msg = NULL; /* don't display old message now */
+ if (!msg_scroll && full_screen) /* overwrite last message */
+ {
+ msg_row = cmdline_row;
+ msg_col =
+#ifdef FEAT_RIGHTLEFT
+ cmdmsg_rl ? Columns - 1 :
+#endif
+ 0;
+ }
+ else if (msg_didout) /* start message on next line */
+ {
+ msg_putchar('\n');
+ did_return = TRUE;
+ if (exmode_active != EXMODE_NORMAL)
+ cmdline_row = msg_row;
+ }
+ if (!msg_didany || lines_left < 0)
+ msg_starthere();
+ if (msg_silent == 0)
+ {
+ msg_didout = FALSE; /* no output on current line yet */
+ cursor_off();
+ }
+
+ /* when redirecting, may need to start a new line. */
+ if (!did_return)
+ redir_write((char_u *)"\n", -1);
+}
+
+/*
+ * Note that the current msg position is where messages start.
+ */
+ void
+msg_starthere()
+{
+ lines_left = cmdline_row;
+ msg_didany = FALSE;
+}
+
+ void
+msg_putchar(c)
+ int c;
+{
+ msg_putchar_attr(c, 0);
+}
+
+ void
+msg_putchar_attr(c, attr)
+ int c;
+ int attr;
+{
+#ifdef FEAT_MBYTE
+ char_u buf[MB_MAXBYTES + 1];
+#else
+ char_u buf[4];
+#endif
+
+ if (IS_SPECIAL(c))
+ {
+ buf[0] = K_SPECIAL;
+ buf[1] = K_SECOND(c);
+ buf[2] = K_THIRD(c);
+ buf[3] = NUL;
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ buf[(*mb_char2bytes)(c, buf)] = NUL;
+#else
+ buf[0] = c;
+ buf[1] = NUL;
+#endif
+ }
+ msg_puts_attr(buf, attr);
+}
+
+ void
+msg_outnum(n)
+ long n;
+{
+ char_u buf[20];
+
+ sprintf((char *)buf, "%ld", n);
+ msg_puts(buf);
+}
+
+ void
+msg_home_replace(fname)
+ char_u *fname;
+{
+ msg_home_replace_attr(fname, 0);
+}
+
+#if defined(FEAT_FIND_ID) || defined(PROTO)
+ void
+msg_home_replace_hl(fname)
+ char_u *fname;
+{
+ msg_home_replace_attr(fname, hl_attr(HLF_D));
+}
+#endif
+
+ static void
+msg_home_replace_attr(fname, attr)
+ char_u *fname;
+ int attr;
+{
+ char_u *name;
+
+ name = home_replace_save(NULL, fname);
+ if (name != NULL)
+ msg_outtrans_attr(name, attr);
+ vim_free(name);
+}
+
+/*
+ * Output 'len' characters in 'str' (including NULs) with translation
+ * if 'len' is -1, output upto a NUL character.
+ * Use attributes 'attr'.
+ * Return the number of characters it takes on the screen.
+ */
+ int
+msg_outtrans(str)
+ char_u *str;
+{
+ return msg_outtrans_attr(str, 0);
+}
+
+ int
+msg_outtrans_attr(str, attr)
+ char_u *str;
+ int attr;
+{
+ return msg_outtrans_len_attr(str, (int)STRLEN(str), attr);
+}
+
+ int
+msg_outtrans_len(str, len)
+ char_u *str;
+ int len;
+{
+ return msg_outtrans_len_attr(str, len, 0);
+}
+
+/*
+ * Output one character at "p". Return pointer to the next character.
+ * Handles multi-byte characters.
+ */
+ char_u *
+msg_outtrans_one(p, attr)
+ char_u *p;
+ int attr;
+{
+#ifdef FEAT_MBYTE
+ int l;
+
+ if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
+ {
+ msg_outtrans_len_attr(p, l, attr);
+ return p + l;
+ }
+#endif
+ msg_puts_attr(transchar_byte(*p), attr);
+ return p + 1;
+}
+
+ int
+msg_outtrans_len_attr(msgstr, len, attr)
+ char_u *msgstr;
+ int len;
+ int attr;
+{
+ int retval = 0;
+ char_u *str = msgstr;
+ char_u *plain_start = msgstr;
+ char_u *s;
+#ifdef FEAT_MBYTE
+ int mb_l;
+ int c;
+#endif
+
+ /* if MSG_HIST flag set, add message to history */
+ if (attr & MSG_HIST)
+ {
+ add_msg_hist(str, len, attr);
+ attr &= ~MSG_HIST;
+ }
+
+#ifdef FEAT_MBYTE
+ /* If the string starts with a composing character first draw a space on
+ * which the composing char can be drawn. */
+ if (enc_utf8 && utf_iscomposing(utf_ptr2char(msgstr)))
+ msg_puts_attr((char_u *)" ", attr);
+#endif
+
+ /*
+ * Go over the string. Special characters are translated and printed.
+ * Normal characters are printed several at a time.
+ */
+ while (--len >= 0)
+ {
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ /* Don't include composing chars after the end. */
+ mb_l = utfc_ptr2len_check_len(str, len + 1);
+ else if (has_mbyte)
+ mb_l = (*mb_ptr2len_check)(str);
+ else
+ mb_l = 1;
+ if (has_mbyte && mb_l > 1)
+ {
+ c = (*mb_ptr2char)(str);
+ if (vim_isprintc(c))
+ /* printable multi-byte char: count the cells. */
+ retval += (*mb_ptr2cells)(str);
+ else
+ {
+ /* unprintable multi-byte char: print the printable chars so
+ * far and the translation of the unprintable char. */
+ if (str > plain_start)
+ msg_puts_attr_len(plain_start, (int)(str - plain_start),
+ attr);
+ plain_start = str + mb_l;
+ msg_puts_attr(transchar(c), attr == 0 ? hl_attr(HLF_8) : attr);
+ retval += char2cells(c);
+ }
+ len -= mb_l - 1;
+ str += mb_l;
+ }
+ else
+#endif
+ {
+ s = transchar_byte(*str);
+ if (s[1] != NUL)
+ {
+ /* unprintable char: print the printable chars so far and the
+ * translation of the unprintable char. */
+ if (str > plain_start)
+ msg_puts_attr_len(plain_start, (int)(str - plain_start),
+ attr);
+ plain_start = str + 1;
+ msg_puts_attr(s, attr == 0 ? hl_attr(HLF_8) : attr);
+ }
+ retval += ptr2cells(str);
+ ++str;
+ }
+ }
+
+ if (str > plain_start)
+ /* print the printable chars at the end */
+ msg_puts_attr_len(plain_start, (int)(str - plain_start), attr);
+
+ return retval;
+}
+
+#if defined(FEAT_QUICKFIX) || defined(PROTO)
+ void
+msg_make(arg)
+ char_u *arg;
+{
+ int i;
+ static char_u *str = (char_u *)"eeffoc", *rs = (char_u *)"Plon#dqg#vxjduB";
+
+ arg = skipwhite(arg);
+ for (i = 5; *arg && i >= 0; --i)
+ if (*arg++ != str[i])
+ break;
+ if (i < 0)
+ {
+ msg_putchar('\n');
+ for (i = 0; rs[i]; ++i)
+ msg_putchar(rs[i] - 3);
+ }
+}
+#endif
+
+/*
+ * Output the string 'str' upto a NUL character.
+ * Return the number of characters it takes on the screen.
+ *
+ * If K_SPECIAL is encountered, then it is taken in conjunction with the
+ * following character and shown as <F1>, <S-Up> etc. Any other character
+ * which is not printable shown in <> form.
+ * If 'from' is TRUE (lhs of a mapping), a space is shown as <Space>.
+ * If a character is displayed in one of these special ways, is also
+ * highlighted (its highlight name is '8' in the p_hl variable).
+ * Otherwise characters are not highlighted.
+ * This function is used to show mappings, where we want to see how to type
+ * the character/string -- webb
+ */
+ int
+msg_outtrans_special(strstart, from)
+ char_u *strstart;
+ int from; /* TRUE for lhs of a mapping */
+{
+ char_u *str = strstart;
+ int retval = 0;
+ char_u *string;
+ int attr;
+ int len;
+
+ attr = hl_attr(HLF_8);
+ while (*str != NUL)
+ {
+ /* Leading and trailing spaces need to be displayed in <> form. */
+ if ((str == strstart || str[1] == NUL) && *str == ' ')
+ {
+ string = (char_u *)"<Space>";
+ ++str;
+ }
+ else
+ string = str2special(&str, from);
+ len = vim_strsize(string);
+ /* Highlight special keys */
+ msg_puts_attr(string, len > 1
+#ifdef FEAT_MBYTE
+ && (*mb_ptr2len_check)(string) <= 1
+#endif
+ ? attr : 0);
+ retval += len;
+ }
+ return retval;
+}
+
+/*
+ * Return the printable string for the key codes at "*sp".
+ * Used for translating the lhs or rhs of a mapping to printable chars.
+ * Advances "sp" to the next code.
+ */
+ char_u *
+str2special(sp, from)
+ char_u **sp;
+ int from; /* TRUE for lhs of mapping */
+{
+ int c;
+ static char_u buf[7];
+ char_u *str = *sp;
+ int modifiers = 0;
+ int special = FALSE;
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ char_u *p;
+
+ /* Try to un-escape a multi-byte character. Return the un-escaped
+ * string if it is a multi-byte character. */
+ p = mb_unescape(sp);
+ if (p != NULL)
+ return p;
+ }
+#endif
+
+ c = *str;
+ if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
+ {
+ if (str[1] == KS_MODIFIER)
+ {
+ modifiers = str[2];
+ str += 3;
+ c = *str;
+ }
+ if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
+ {
+ c = TO_SPECIAL(str[1], str[2]);
+ str += 2;
+ if (c == K_ZERO) /* display <Nul> as ^@ */
+ c = NUL;
+ }
+ if (IS_SPECIAL(c) || modifiers) /* special key */
+ special = TRUE;
+ }
+ *sp = str + 1;
+
+#ifdef FEAT_MBYTE
+ /* For multi-byte characters check for an illegal byte. */
+ if (has_mbyte && MB_BYTE2LEN(*str) > (*mb_ptr2len_check)(str))
+ {
+ transchar_nonprint(buf, c);
+ return buf;
+ }
+#endif
+
+ /* Make unprintable characters in <> form, also <M-Space> and <Tab>.
+ * Use <Space> only for lhs of a mapping. */
+ if (special || char2cells(c) > 1 || (from && c == ' '))
+ return get_special_key_name(c, modifiers);
+ buf[0] = c;
+ buf[1] = NUL;
+ return buf;
+}
+
+/*
+ * Translate a key sequence into special key names.
+ */
+ void
+str2specialbuf(sp, buf, len)
+ char_u *sp;
+ char_u *buf;
+ int len;
+{
+ char_u *s;
+
+ *buf = NUL;
+ while (*sp)
+ {
+ s = str2special(&sp, FALSE);
+ if ((int)(STRLEN(s) + STRLEN(buf)) < len)
+ STRCAT(buf, s);
+ }
+}
+
+/*
+ * print line for :print or :list command
+ */
+ void
+msg_prt_line(s)
+ char_u *s;
+{
+ int c;
+ int col = 0;
+ int n_extra = 0;
+ int c_extra = 0;
+ char_u *p_extra = NULL; /* init to make SASC shut up */
+ int n;
+ int attr= 0;
+ char_u *trail = NULL;
+#ifdef FEAT_MBYTE
+ int l;
+ char_u buf[MB_MAXBYTES + 1];
+#endif
+
+ /* find start of trailing whitespace */
+ if (curwin->w_p_list && lcs_trail)
+ {
+ trail = s + STRLEN(s);
+ while (trail > s && vim_iswhite(trail[-1]))
+ --trail;
+ }
+
+ /* output a space for an empty line, otherwise the line will be
+ * overwritten */
+ if (*s == NUL && !(curwin->w_p_list && lcs_eol != NUL))
+ msg_putchar(' ');
+
+ for (;;)
+ {
+ if (n_extra)
+ {
+ --n_extra;
+ if (c_extra)
+ c = c_extra;
+ else
+ c = *p_extra++;
+ }
+#ifdef FEAT_MBYTE
+ else if (has_mbyte && (l = (*mb_ptr2len_check)(s)) > 1)
+ {
+ col += (*mb_ptr2cells)(s);
+ mch_memmove(buf, s, (size_t)l);
+ buf[l] = NUL;
+ msg_puts_attr(buf, attr);
+ s += l;
+ continue;
+ }
+#endif
+ else
+ {
+ attr = 0;
+ c = *s++;
+ if (c == TAB && (!curwin->w_p_list || lcs_tab1))
+ {
+ /* tab amount depends on current column */
+ n_extra = curbuf->b_p_ts - col % curbuf->b_p_ts - 1;
+ if (!curwin->w_p_list)
+ {
+ c = ' ';
+ c_extra = ' ';
+ }
+ else
+ {
+ c = lcs_tab1;
+ c_extra = lcs_tab2;
+ attr = hl_attr(HLF_8);
+ }
+ }
+ else if (c == NUL && curwin->w_p_list && lcs_eol != NUL)
+ {
+ p_extra = (char_u *)"";
+ c_extra = NUL;
+ n_extra = 1;
+ c = lcs_eol;
+ attr = hl_attr(HLF_AT);
+ --s;
+ }
+ else if (c != NUL && (n = byte2cells(c)) > 1)
+ {
+ n_extra = n - 1;
+ p_extra = transchar_byte(c);
+ c_extra = NUL;
+ c = *p_extra++;
+ }
+ else if (c == ' ' && trail != NULL && s > trail)
+ {
+ c = lcs_trail;
+ attr = hl_attr(HLF_8);
+ }
+ }
+
+ if (c == NUL)
+ break;
+
+ msg_putchar_attr(c, attr);
+ col++;
+ }
+ msg_clr_eos();
+}
+
+#ifdef FEAT_MBYTE
+/*
+ * Use screen_puts() to output one multi-byte character.
+ * Return the pointer "s" advanced to the next character.
+ */
+ static char_u *
+screen_puts_mbyte(s, l, attr)
+ char_u *s;
+ int l;
+ int attr;
+{
+ int cw;
+
+ msg_didout = TRUE; /* remember that line is not empty */
+ cw = (*mb_ptr2cells)(s);
+ if (cw > 1 && (
+#ifdef FEAT_RIGHTLEFT
+ cmdmsg_rl ? msg_col <= 1 :
+#endif
+ msg_col == Columns - 1))
+ {
+ /* Doesn't fit, print a highlighted '>' to fill it up. */
+ msg_screen_putchar('>', hl_attr(HLF_AT));
+ return s;
+ }
+
+ screen_puts_len(s, l, msg_row, msg_col, attr);
+#ifdef FEAT_RIGHTLEFT
+ if (cmdmsg_rl)
+ {
+ msg_col -= cw;
+ if (msg_col == 0)
+ {
+ msg_col = Columns;
+ ++msg_row;
+ }
+ }
+ else
+#endif
+ {
+ msg_col += cw;
+ if (msg_col >= Columns)
+ {
+ msg_col = 0;
+ ++msg_row;
+ }
+ }
+ return s + l;
+}
+#endif
+
+/*
+ * Output a string to the screen at position msg_row, msg_col.
+ * Update msg_row and msg_col for the next message.
+ */
+ void
+msg_puts(s)
+ char_u *s;
+{
+ msg_puts_attr(s, 0);
+}
+
+ void
+msg_puts_title(s)
+ char_u *s;
+{
+ msg_puts_attr(s, hl_attr(HLF_T));
+}
+
+#if defined(FEAT_CSCOPE) || defined(PROTO)
+/*
+ * if printing a string will exceed the screen width, print "..." in the
+ * middle.
+ */
+ void
+msg_puts_long(longstr)
+ char_u *longstr;
+{
+ msg_puts_long_len_attr(longstr, (int)strlen((char *)longstr), 0);
+}
+#endif
+
+/*
+ * Show a message in such a way that it always fits in the line. Cut out a
+ * part in the middle and replace it with "..." when necessary.
+ * Does not handle multi-byte characters!
+ */
+ void
+msg_puts_long_attr(longstr, attr)
+ char_u *longstr;
+ int attr;
+{
+ msg_puts_long_len_attr(longstr, (int)strlen((char *)longstr), attr);
+}
+
+ void
+msg_puts_long_len_attr(longstr, len, attr)
+ char_u *longstr;
+ int len;
+ int attr;
+{
+ int slen = len;
+ int room;
+
+ room = Columns - msg_col;
+ if (len > room && room >= 20)
+ {
+ slen = (room - 3) / 2;
+ msg_outtrans_len_attr(longstr, slen, attr);
+ msg_puts_attr((char_u *)"...", hl_attr(HLF_8));
+ }
+ msg_outtrans_len_attr(longstr + len - slen, slen, attr);
+}
+
+/*
+ * Basic function for writing a message with highlight attributes.
+ */
+ void
+msg_puts_attr(s, attr)
+ char_u *s;
+ int attr;
+{
+ msg_puts_attr_len(s, -1, attr);
+}
+
+/*
+ * Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes).
+ * When "maxlen" is -1 there is no maximum length.
+ * When "maxlen" is >= 0 the message is not put in the history.
+ */
+ static void
+msg_puts_attr_len(str, maxlen, attr)
+ char_u *str;
+ int maxlen;
+ int attr;
+{
+ int oldState;
+ char_u *s = str;
+ char_u *p;
+ char_u buf[4];
+ char_u *t_s = str; /* string from "t_s" to "s" is still todo */
+ int t_col = 0; /* screen cells todo, 0 when "t_s" not used */
+#ifdef FEAT_MBYTE
+ int l;
+ int cw;
+#endif
+ int c;
+
+ /*
+ * If redirection is on, also write to the redirection file.
+ */
+ redir_write(s, maxlen);
+
+ /*
+ * Don't print anything when using ":silent cmd".
+ */
+ if (msg_silent != 0)
+ return;
+
+ /* if MSG_HIST flag set, add message to history */
+ if ((attr & MSG_HIST) && maxlen < 0)
+ {
+ add_msg_hist(s, -1, attr);
+ attr &= ~MSG_HIST;
+ }
+
+ /*
+ * When writing something to the screen after it has scrolled, requires a
+ * wait-return prompt later. Needed when scrolling, resetting
+ * need_wait_return after some prompt, and then outputting something
+ * without scrolling
+ */
+ if (msg_scrolled && !msg_scrolled_ign)
+ need_wait_return = TRUE;
+ msg_didany = TRUE; /* remember that something was outputted */
+
+ /*
+ * If there is no valid screen, use fprintf so we can see error messages.
+ * If termcap is not active, we may be writing in an alternate console
+ * window, cursor positioning may not work correctly (window size may be
+ * different, e.g. for Win32 console) or we just don't know where the
+ * cursor is.
+ */
+ if (msg_use_printf())
+ {
+#ifdef WIN3264
+ if (!(silent_mode && p_verbose == 0))
+ mch_settmode(TMODE_COOK); /* handle '\r' and '\n' correctly */
+#endif
+ while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
+ {
+ if (!(silent_mode && p_verbose == 0))
+ {
+ p = &buf[0];
+ /* NL --> CR NL translation (for Unix, not for "--version") */
+ /* NL --> CR translation (for Mac) */
+ if (*s == '\n' && !info_message)
+ *p++ = '\r';
+#if defined(USE_CR) && !defined(MACOS_X_UNIX)
+ else
+#endif
+ *p++ = *s;
+ *p = '\0';
+ if (info_message) /* informative message, not an error */
+ mch_msg((char *)buf);
+ else
+ mch_errmsg((char *)buf);
+ }
+
+ /* primitive way to compute the current column */
+#ifdef FEAT_RIGHTLEFT
+ if (cmdmsg_rl)
+ {
+ if (*s == '\r' || *s == '\n')
+ msg_col = Columns - 1;
+ else
+ --msg_col;
+ }
+ else
+#endif
+ {
+ if (*s == '\r' || *s == '\n')
+ msg_col = 0;
+ else
+ ++msg_col;
+ }
+ ++s;
+ }
+ msg_didout = TRUE; /* assume that line is not empty */
+
+#ifdef WIN3264
+ if (!(silent_mode && p_verbose == 0))
+ mch_settmode(TMODE_RAW);
+#endif
+ return;
+ }
+
+ did_wait_return = FALSE;
+ while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
+ {
+ /*
+ * The screen is scrolled up when:
+ * - When outputting a newline in the last row
+ * - when outputting a character in the last column of the last row
+ * (some terminals scroll automatically, some don't. To avoid
+ * problems we scroll ourselves)
+ */
+ if (msg_row >= Rows - 1
+ && (*s == '\n'
+ || (
+#ifdef FEAT_RIGHTLEFT
+ cmdmsg_rl
+ ? (
+ msg_col <= 1
+ || (*s == TAB && msg_col <= 7)
+# ifdef FEAT_MBYTE
+ || (has_mbyte && (*mb_ptr2cells)(s) > 1 && msg_col <= 2)
+# endif
+ )
+ :
+#endif
+ (msg_col + t_col >= Columns - 1
+ || (*s == TAB && msg_col + t_col >= ((Columns - 1) & ~7))
+# ifdef FEAT_MBYTE
+ || (has_mbyte && (*mb_ptr2cells)(s) > 1
+ && msg_col + t_col >= Columns - 2)
+# endif
+ ))))
+ {
+ if (t_col > 0)
+ {
+ /* output postponed text */
+ t_puts(t_col, t_s, s, attr);
+ t_col = 0;
+ }
+
+ /* When no more prompt an no more room, truncate here */
+ if (msg_no_more && lines_left == 0)
+ break;
+#ifdef FEAT_GUI
+ /* Remove the cursor before scrolling, ScreenLines[] is going to
+ * become invalid. */
+ if (gui.in_use)
+ gui_undraw_cursor();
+#endif
+ /* scrolling up always works */
+ screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL);
+
+ if (!can_clear((char_u *)" "))
+ {
+ /* Scrolling up doesn't result in the right background. Set
+ * the background here. It's not efficient, but avoids that
+ * we have to do it all over the code. */
+ screen_fill((int)Rows - 1, (int)Rows, 0,
+ (int)Columns, ' ', ' ', 0);
+
+ /* Also clear the last char of the last but one line if it was
+ * not cleared before to avoid a scroll-up. */
+ if (ScreenAttrs[LineOffset[Rows - 2] + Columns - 1]
+ == (sattr_T)-1)
+ screen_fill((int)Rows - 2, (int)Rows - 1,
+ (int)Columns - 1, (int)Columns, ' ', ' ', 0);
+ }
+
+ msg_row = Rows - 2;
+ if (msg_col >= Columns) /* can happen after screen resize */
+ msg_col = Columns - 1;
+
+ ++msg_scrolled;
+ need_wait_return = TRUE; /* may need wait_return in main() */
+ if (must_redraw < VALID)
+ must_redraw = VALID;
+ redraw_cmdline = TRUE;
+ if (cmdline_row > 0 && !exmode_active)
+ --cmdline_row;
+
+ /*
+ * if screen is completely filled wait for a character
+ */
+ if (p_more && --lines_left == 0 && State != HITRETURN
+ && !msg_no_more && !exmode_active)
+ {
+ oldState = State;
+ State = ASKMORE;
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+ msg_moremsg(FALSE);
+ for (;;)
+ {
+ /*
+ * Get a typed character directly from the user.
+ */
+ c = get_keystroke();
+
+#if defined(FEAT_MENU) && defined(FEAT_GUI)
+ if (c == K_MENU)
+ {
+ int idx = get_menu_index(current_menu, ASKMORE);
+
+ /* Used a menu. If it starts with CTRL-Y, it must
+ * be a "Copy" for the clipboard. Otherwise
+ * assume that we end */
+ if (idx == MENU_INDEX_INVALID)
+ continue;
+ c = *current_menu->strings[idx];
+ if (c != NUL && current_menu->strings[idx][1] != NUL)
+ ins_typebuf(current_menu->strings[idx] + 1,
+ current_menu->noremap[idx], 0, TRUE,
+ current_menu->silent[idx]);
+ }
+#endif
+
+ switch (c)
+ {
+ case BS:
+ case 'k':
+ case K_UP:
+ if (!more_back_used)
+ {
+ msg_moremsg(TRUE);
+ continue;
+ }
+ more_back = 1;
+ lines_left = 1;
+ break;
+ case CAR: /* one extra line */
+ case NL:
+ case 'j':
+ case K_DOWN:
+ lines_left = 1;
+ break;
+ case ':': /* start new command line */
+#ifdef FEAT_CON_DIALOG
+ if (!confirm_msg_used)
+#endif
+ {
+ /* Since got_int is set all typeahead will be
+ * flushed, but we want to keep this ':', remember
+ * that in a special way. */
+ typeahead_noflush(':');
+ cmdline_row = Rows - 1; /* put ':' on this line */
+ skip_redraw = TRUE; /* skip redraw once */
+ need_wait_return = FALSE; /* don't wait in main() */
+ }
+ /*FALLTHROUGH*/
+ case 'q': /* quit */
+ case Ctrl_C:
+ case ESC:
+#ifdef FEAT_CON_DIALOG
+ if (confirm_msg_used)
+ {
+ /* Jump to the choices of the dialog. */
+ s = confirm_msg_tail;
+ lines_left = Rows - 1;
+ }
+ else
+#endif
+ {
+ got_int = TRUE;
+ quit_more = TRUE;
+ }
+ break;
+ case 'u': /* Up half a page */
+ case K_PAGEUP:
+ if (!more_back_used)
+ {
+ msg_moremsg(TRUE);
+ continue;
+ }
+ more_back = Rows / 2;
+ /*FALLTHROUGH*/
+ case 'd': /* Down half a page */
+ lines_left = Rows / 2;
+ break;
+ case 'b': /* one page back */
+ if (!more_back_used)
+ {
+ msg_moremsg(TRUE);
+ continue;
+ }
+ more_back = Rows - 1;
+ /*FALLTHROUGH*/
+ case ' ': /* one extra page */
+ case K_PAGEDOWN:
+ case K_LEFTMOUSE:
+ lines_left = Rows - 1;
+ break;
+
+#ifdef FEAT_CLIPBOARD
+ case Ctrl_Y:
+ /* Strange way to allow copying (yanking) a modeless
+ * selection at the more prompt. Use CTRL-Y,
+ * because the same is used in Cmdline-mode and at the
+ * hit-enter prompt. However, scrolling one line up
+ * might be expected... */
+ if (clip_star.state == SELECT_DONE)
+ clip_copy_modeless_selection(TRUE);
+ continue;
+#endif
+ default: /* no valid response */
+ msg_moremsg(TRUE);
+ continue;
+ }
+ break;
+ }
+
+ /* clear the --more-- message */
+ screen_fill((int)Rows - 1, (int)Rows,
+ 0, (int)Columns, ' ', ' ', 0);
+ State = oldState;
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+ if (quit_more)
+ {
+ msg_row = Rows - 1;
+ msg_col = 0;
+ return; /* the string is not displayed! */
+ }
+#ifdef FEAT_RIGHTLEFT
+ if (cmdmsg_rl)
+ msg_col = Columns - 1;
+#endif
+ }
+ }
+
+ if (t_col > 0
+ && (vim_strchr((char_u *)"\n\r\b\t", *s) != NULL
+ || *s == BELL
+ || msg_col + t_col >= Columns
+#ifdef FEAT_MBYTE
+ || (has_mbyte && (*mb_ptr2cells)(s) > 1
+ && msg_col + t_col >= Columns - 1)
+#endif
+ ))
+ {
+ /* output any postponed text */
+ t_puts(t_col, t_s, s, attr);
+ t_col = 0;
+ }
+
+ if (*s == '\n') /* go to next line */
+ {
+ msg_didout = FALSE; /* remember that line is empty */
+ msg_col = 0;
+ if (++msg_row >= Rows) /* safety check */
+ msg_row = Rows - 1;
+ }
+ else if (*s == '\r') /* go to column 0 */
+ {
+ msg_col = 0;
+ }
+ else if (*s == '\b') /* go to previous char */
+ {
+ if (msg_col)
+ --msg_col;
+ }
+ else if (*s == TAB) /* translate into spaces */
+ {
+ do
+ msg_screen_putchar(' ', attr);
+ while (msg_col & 7);
+ }
+ else if (*s == BELL) /* beep (from ":sh") */
+ vim_beep();
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ cw = (*mb_ptr2cells)(s);
+ if (enc_utf8 && maxlen >= 0)
+ /* avoid including composing chars after the end */
+ l = utfc_ptr2len_check_len(s, (int)((str + maxlen) - s));
+ else
+ l = (*mb_ptr2len_check)(s);
+ }
+ else
+ {
+ cw = 1;
+ l = 1;
+ }
+#endif
+ /* When drawing from right to left or when a double-wide character
+ * doesn't fit, draw a single character here. Otherwise collect
+ * characters and draw them all at once later. */
+#if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE)
+ if (
+# ifdef FEAT_RIGHTLEFT
+ cmdmsg_rl
+# ifdef FEAT_MBYTE
+ ||
+# endif
+# endif
+# ifdef FEAT_MBYTE
+ (cw > 1 && msg_col + t_col >= Columns - 1)
+# endif
+ )
+ {
+# ifdef FEAT_MBYTE
+ if (l > 1)
+ s = screen_puts_mbyte(s, l, attr) - 1;
+ else
+# endif
+ msg_screen_putchar(*s, attr);
+ }
+ else
+#endif
+ {
+ /* postpone this character until later */
+ if (t_col == 0)
+ t_s = s;
+#ifdef FEAT_MBYTE
+ t_col += cw;
+ s += l - 1;
+#else
+ ++t_col;
+#endif
+ }
+ }
+ ++s;
+ }
+
+ /* output any postponed text */
+ if (t_col > 0)
+ t_puts(t_col, t_s, s, attr);
+
+ msg_check();
+}
+
+/*
+ * Output any postponed text for msg_puts_attr_len().
+ */
+ static void
+t_puts(t_col, t_s, s, attr)
+ int t_col;
+ char_u *t_s;
+ char_u *s;
+ int attr;
+{
+ /* output postponed text */
+ msg_didout = TRUE; /* remember that line is not empty */
+ screen_puts_len(t_s, (int)(s - t_s), msg_row, msg_col, attr);
+ msg_col += t_col;
+#ifdef FEAT_MBYTE
+ /* If the string starts with a composing character don't increment the
+ * column position for it. */
+ if (enc_utf8 && utf_iscomposing(utf_ptr2char(t_s)))
+ --msg_col;
+#endif
+ if (msg_col >= Columns)
+ {
+ msg_col = 0;
+ ++msg_row;
+ }
+}
+
+
+/*
+ * Returns TRUE when messages should be printed with mch_errmsg().
+ * This is used when there is no valid screen, so we can see error messages.
+ * If termcap is not active, we may be writing in an alternate console
+ * window, cursor positioning may not work correctly (window size may be
+ * different, e.g. for Win32 console) or we just don't know where the
+ * cursor is.
+ */
+ int
+msg_use_printf()
+{
+ return (!msg_check_screen()
+#if defined(WIN3264) && !defined(FEAT_GUI_MSWIN)
+ || !termcap_active
+#endif
+ || (swapping_screen() && !termcap_active)
+ );
+}
+
+#if defined(USE_MCH_ERRMSG) || defined(PROTO)
+
+#ifdef mch_errmsg
+# undef mch_errmsg
+#endif
+#ifdef mch_msg
+# undef mch_msg
+#endif
+
+/*
+ * Give an error message. To be used when the screen hasn't been initialized
+ * yet. When stderr can't be used, collect error messages until the GUI has
+ * started and they can be displayed in a message box.
+ */
+ void
+mch_errmsg(str)
+ char *str;
+{
+ int len;
+
+#if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI)
+ /* On Unix use stderr if it's a tty.
+ * When not going to start the GUI also use stderr.
+ * On Mac, when started from Finder, stderr is the console. */
+ if (
+# ifdef UNIX
+# ifdef MACOS_X_UNIX
+ (isatty(2) && strcmp("/dev/console", ttyname(2)) != 0)
+# else
+ isatty(2)
+# endif
+# ifdef FEAT_GUI
+ ||
+# endif
+# endif
+# ifdef FEAT_GUI
+ !(gui.in_use || gui.starting)
+# endif
+ )
+ {
+ fprintf(stderr, "%s", str);
+ return;
+ }
+#endif
+
+ /* avoid a delay for a message that isn't there */
+ emsg_on_display = FALSE;
+
+ len = (int)STRLEN(str) + 1;
+ if (error_ga.ga_growsize == 0)
+ {
+ error_ga.ga_growsize = 80;
+ error_ga.ga_itemsize = 1;
+ }
+ if (ga_grow(&error_ga, len) == OK)
+ {
+ mch_memmove((char_u *)error_ga.ga_data + error_ga.ga_len,
+ (char_u *)str, len);
+#ifdef UNIX
+ /* remove CR characters, they are displayed */
+ {
+ char_u *p;
+
+ p = (char_u *)error_ga.ga_data + error_ga.ga_len;
+ for (;;)
+ {
+ p = vim_strchr(p, '\r');
+ if (p == NULL)
+ break;
+ *p = ' ';
+ }
+ }
+#endif
+ --len; /* don't count the NUL at the end */
+ error_ga.ga_len += len;
+ error_ga.ga_room -= len;
+ }
+}
+
+/*
+ * Give a message. To be used when the screen hasn't been initialized yet.
+ * When there is no tty, collect messages until the GUI has started and they
+ * can be displayed in a message box.
+ */
+ void
+mch_msg(str)
+ char *str;
+{
+#if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI)
+ /* On Unix use stdout if we have a tty. This allows "vim -h | more" and
+ * uses mch_errmsg() when started from the desktop.
+ * When not going to start the GUI also use stdout.
+ * On Mac, when started from Finder, stderr is the console. */
+ if (
+# ifdef UNIX
+# ifdef MACOS_X_UNIX
+ (isatty(2) && strcmp("/dev/console", ttyname(2)) != 0)
+# else
+ isatty(2)
+# endif
+# ifdef FEAT_GUI
+ ||
+# endif
+# endif
+# ifdef FEAT_GUI
+ !(gui.in_use || gui.starting)
+# endif
+ )
+ {
+ printf("%s", str);
+ return;
+ }
+# endif
+ mch_errmsg(str);
+}
+#endif /* USE_MCH_ERRMSG */
+
+/*
+ * Put a character on the screen at the current message position and advance
+ * to the next position. Only for printable ASCII!
+ */
+ static void
+msg_screen_putchar(c, attr)
+ int c;
+ int attr;
+{
+ msg_didout = TRUE; /* remember that line is not empty */
+ screen_putchar(c, msg_row, msg_col, attr);
+#ifdef FEAT_RIGHTLEFT
+ if (cmdmsg_rl)
+ {
+ if (--msg_col == 0)
+ {
+ msg_col = Columns;
+ ++msg_row;
+ }
+ }
+ else
+#endif
+ {
+ if (++msg_col >= Columns)
+ {
+ msg_col = 0;
+ ++msg_row;
+ }
+ }
+}
+
+ void
+msg_moremsg(full)
+ int full;
+{
+ int attr;
+
+ attr = hl_attr(HLF_M);
+ screen_puts((char_u *)_("-- More --"), (int)Rows - 1, 0, attr);
+ if (full)
+ screen_puts(more_back_used
+ ? (char_u *)_(" (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)")
+ : (char_u *)_(" (RET: line, SPACE: page, d: half page, q: quit)"),
+ (int)Rows - 1, 10, attr);
+}
+
+/*
+ * Repeat the message for the current mode: ASKMORE, EXTERNCMD, CONFIRM or
+ * exmode_active.
+ */
+ void
+repeat_message()
+{
+ if (State == ASKMORE)
+ {
+ msg_moremsg(TRUE); /* display --more-- message again */
+ msg_row = Rows - 1;
+ }
+#ifdef FEAT_CON_DIALOG
+ else if (State == CONFIRM)
+ {
+ display_confirm_msg(); /* display ":confirm" message again */
+ msg_row = Rows - 1;
+ }
+#endif
+ else if (State == EXTERNCMD)
+ {
+ windgoto(msg_row, msg_col); /* put cursor back */
+ }
+ else if (State == HITRETURN || State == SETWSIZE)
+ {
+ hit_return_msg();
+ msg_row = Rows - 1;
+ }
+}
+
+/*
+ * msg_check_screen - check if the screen is initialized.
+ * Also check msg_row and msg_col, if they are too big it may cause a crash.
+ * While starting the GUI the terminal codes will be set for the GUI, but the
+ * output goes to the terminal. Don't use the terminal codes then.
+ */
+ static int
+msg_check_screen()
+{
+ if (!full_screen || !screen_valid(FALSE))
+ return FALSE;
+
+ if (msg_row >= Rows)
+ msg_row = Rows - 1;
+ if (msg_col >= Columns)
+ msg_col = Columns - 1;
+ return TRUE;
+}
+
+/*
+ * Clear from current message position to end of screen.
+ * Skip this when ":silent" was used, no need to clear for redirection.
+ */
+ void
+msg_clr_eos()
+{
+ if (msg_silent == 0)
+ msg_clr_eos_force();
+}
+
+/*
+ * Clear from current message position to end of screen.
+ * Note: msg_col is not updated, so we remember the end of the message
+ * for msg_check().
+ */
+ void
+msg_clr_eos_force()
+{
+ if (msg_use_printf())
+ {
+ if (full_screen) /* only when termcap codes are valid */
+ {
+ if (*T_CD)
+ out_str(T_CD); /* clear to end of display */
+ else if (*T_CE)
+ out_str(T_CE); /* clear to end of line */
+ }
+ }
+ else
+ {
+#ifdef FEAT_RIGHTLEFT
+ if (cmdmsg_rl)
+ {
+ screen_fill(msg_row, msg_row + 1, 0, msg_col + 1, ' ', ' ', 0);
+ screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
+ }
+ else
+#endif
+ {
+ screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns,
+ ' ', ' ', 0);
+ screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
+ }
+ }
+}
+
+/*
+ * Clear the command line.
+ */
+ void
+msg_clr_cmdline()
+{
+ msg_row = cmdline_row;
+ msg_col = 0;
+ msg_clr_eos_force();
+}
+
+/*
+ * end putting a message on the screen
+ * call wait_return if the message does not fit in the available space
+ * return TRUE if wait_return not called.
+ */
+ int
+msg_end()
+{
+ /*
+ * if the string is larger than the window,
+ * or the ruler option is set and we run into it,
+ * we have to redraw the window.
+ * Do not do this if we are abandoning the file or editing the command line.
+ */
+ if (!exiting && need_wait_return && !(State & CMDLINE))
+ {
+ wait_return(FALSE);
+ return FALSE;
+ }
+ out_flush();
+ return TRUE;
+}
+
+/*
+ * If the written message runs into the shown command or ruler, we have to
+ * wait for hit-return and redraw the window later.
+ */
+ void
+msg_check()
+{
+ if (msg_row == Rows - 1 && msg_col >= sc_col)
+ {
+ need_wait_return = TRUE;
+ redraw_cmdline = TRUE;
+ }
+}
+
+/*
+ * May write a string to the redirection file.
+ * When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes.
+ */
+ static void
+redir_write(str, maxlen)
+ char_u *str;
+ int maxlen;
+{
+ char_u *s = str;
+ static int cur_col = 0;
+
+ if ((redir_fd != NULL
+#ifdef FEAT_EVAL
+ || redir_reg
+#endif
+ ) && !redir_off)
+ {
+ /* If the string doesn't start with CR or NL, go to msg_col */
+ if (*s != '\n' && *s != '\r')
+ {
+ while (cur_col < msg_col)
+ {
+#ifdef FEAT_EVAL
+ if (redir_reg)
+ write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE);
+ else if (redir_fd)
+#endif
+ fputs(" ", redir_fd);
+ ++cur_col;
+ }
+ }
+
+#ifdef FEAT_EVAL
+ if (redir_reg)
+ write_reg_contents(redir_reg, s, maxlen, TRUE);
+#endif
+
+ /* Adjust the current column */
+ while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
+ {
+#ifdef FEAT_EVAL
+ if (!redir_reg && redir_fd != NULL)
+#endif
+ putc(*s, redir_fd);
+ if (*s == '\r' || *s == '\n')
+ cur_col = 0;
+ else if (*s == '\t')
+ cur_col += (8 - cur_col % 8);
+ else
+ ++cur_col;
+ ++s;
+ }
+
+ if (msg_silent != 0) /* should update msg_col */
+ msg_col = cur_col;
+ }
+}
+
+/*
+ * Give a warning message (for searching).
+ * Use 'w' highlighting and may repeat the message after redrawing
+ */
+ void
+give_warning(message, hl)
+ char_u *message;
+ int hl;
+{
+ /* Don't do this for ":silent". */
+ if (msg_silent != 0)
+ return;
+
+ /* Don't want a hit-enter prompt here. */
+ ++no_wait_return;
+#ifdef FEAT_EVAL
+ set_vim_var_string(VV_WARNINGMSG, message, -1);
+#endif
+#ifdef VIMBUDDY
+ VimBuddyText(message, 1);
+#else
+ vim_free(keep_msg);
+ keep_msg = NULL;
+ if (hl)
+ keep_msg_attr = hl_attr(HLF_W);
+ else
+ keep_msg_attr = 0;
+ if (msg_attr(message, keep_msg_attr) && msg_scrolled == 0)
+ set_keep_msg(message);
+ msg_didout = FALSE; /* overwrite this message */
+ msg_nowait = TRUE; /* don't wait for this message */
+ msg_col = 0;
+#endif
+ --no_wait_return;
+}
+
+/*
+ * Advance msg cursor to column "col".
+ */
+ void
+msg_advance(col)
+ int col;
+{
+ if (msg_silent != 0) /* nothing to advance to */
+ {
+ msg_col = col; /* for redirection, may fill it up later */
+ return;
+ }
+ if (col >= Columns) /* not enough room */
+ col = Columns - 1;
+ while (msg_col < col)
+ msg_putchar(' ');
+}
+
+#if defined(FEAT_CON_DIALOG) || defined(PROTO)
+/*
+ * Used for "confirm()" function, and the :confirm command prefix.
+ * Versions which haven't got flexible dialogs yet, and console
+ * versions, get this generic handler which uses the command line.
+ *
+ * type = one of:
+ * VIM_QUESTION, VIM_INFO, VIM_WARNING, VIM_ERROR or VIM_GENERIC
+ * title = title string (can be NULL for default)
+ * (neither used in console dialogs at the moment)
+ *
+ * Format of the "buttons" string:
+ * "Button1Name\nButton2Name\nButton3Name"
+ * The first button should normally be the default/accept
+ * The second button should be the 'Cancel' button
+ * Other buttons- use your imagination!
+ * A '&' in a button name becomes a shortcut, so each '&' should be before a
+ * different letter.
+ */
+/* ARGSUSED */
+ int
+do_dialog(type, title, message, buttons, dfltbutton, textfield)
+ int type;
+ char_u *title;
+ char_u *message;
+ char_u *buttons;
+ int dfltbutton;
+ char_u *textfield; /* IObuff for inputdialog(), NULL otherwise */
+{
+ int oldState;
+ int retval = 0;
+ char_u *hotkeys;
+ int c;
+ int i;
+
+#ifndef NO_CONSOLE
+ /* Don't output anything in silent mode ("ex -s") */
+ if (silent_mode)
+ return dfltbutton; /* return default option */
+#endif
+
+#ifdef FEAT_GUI_DIALOG
+ /* When GUI is running and 'c' not in 'guioptions', use the GUI dialog */
+ if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
+ {
+ c = gui_mch_dialog(type, title, message, buttons, dfltbutton,
+ textfield);
+ msg_end_prompt();
+
+ /* Flush output to avoid that further messages and redrawing is done
+ * in the wrong order. */
+ out_flush();
+ gui_mch_update();
+
+ return c;
+ }
+#endif
+
+ oldState = State;
+ State = CONFIRM;
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+
+ /*
+ * Since we wait for a keypress, don't make the
+ * user press RETURN as well afterwards.
+ */
+ ++no_wait_return;
+ hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
+
+ if (hotkeys != NULL)
+ {
+ for (;;)
+ {
+ /* Get a typed character directly from the user. */
+ c = get_keystroke();
+ switch (c)
+ {
+ case CAR: /* User accepts default option */
+ case NL:
+ retval = dfltbutton;
+ break;
+ case Ctrl_C: /* User aborts/cancels */
+ case ESC:
+ retval = 0;
+ break;
+ default: /* Could be a hotkey? */
+ if (c < 0) /* special keys are ignored here */
+ continue;
+ /* Make the character lowercase, as chars in "hotkeys" are. */
+ c = MB_TOLOWER(c);
+ retval = 1;
+ for (i = 0; hotkeys[i]; ++i)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ if ((*mb_ptr2char)(hotkeys + i) == c)
+ break;
+ i += (*mb_ptr2len_check)(hotkeys + i) - 1;
+ }
+ else
+#endif
+ if (hotkeys[i] == c)
+ break;
+ ++retval;
+ }
+ if (hotkeys[i])
+ break;
+ /* No hotkey match, so keep waiting */
+ continue;
+ }
+ break;
+ }
+
+ vim_free(hotkeys);
+ }
+
+ State = oldState;
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+ --no_wait_return;
+ msg_end_prompt();
+
+ return retval;
+}
+
+static int copy_char __ARGS((char_u *from, char_u *to, int lowercase));
+
+/*
+ * Copy one character from "*from" to "*to", taking care of multi-byte
+ * characters. Return the length of the character in bytes.
+ */
+ static int
+copy_char(from, to, lowercase)
+ char_u *from;
+ char_u *to;
+ int lowercase; /* make character lower case */
+{
+#ifdef FEAT_MBYTE
+ int len;
+ int c;
+
+ if (has_mbyte)
+ {
+ if (lowercase)
+ {
+ c = MB_TOLOWER((*mb_ptr2char)(from));
+ return (*mb_char2bytes)(c, to);
+ }
+ else
+ {
+ len = (*mb_ptr2len_check)(from);
+ mch_memmove(to, from, (size_t)len);
+ return len;
+ }
+ }
+ else
+#endif
+ {
+ if (lowercase)
+ *to = (char_u)TOLOWER_LOC(*from);
+ else
+ *to = *from;
+ return 1;
+ }
+}
+
+/*
+ * Format the dialog string, and display it at the bottom of
+ * the screen. Return a string of hotkey chars (if defined) for
+ * each 'button'. If a button has no hotkey defined, the first character of
+ * the button is used.
+ * The hotkeys can be multi-byte characters, but without combining chars.
+ *
+ * Returns an allocated string with hotkeys, or NULL for error.
+ */
+ static char_u *
+msg_show_console_dialog(message, buttons, dfltbutton)
+ char_u *message;
+ char_u *buttons;
+ int dfltbutton;
+{
+ int len = 0;
+#ifdef FEAT_MBYTE
+# define HOTK_LEN (has_mbyte ? MB_MAXBYTES : 1)
+#else
+# define HOTK_LEN 1
+#endif
+ int lenhotkey = HOTK_LEN; /* count first button */
+ char_u *hotk = NULL;
+ char_u *msgp = NULL;
+ char_u *hotkp = NULL;
+ char_u *r;
+ int copy;
+#define HAS_HOTKEY_LEN 30
+ char_u has_hotkey[HAS_HOTKEY_LEN];
+ int first_hotkey = FALSE; /* first char of button is hotkey */
+ int idx;
+
+ has_hotkey[0] = FALSE;
+
+ /*
+ * First loop: compute the size of memory to allocate.
+ * Second loop: copy to the allocated memory.
+ */
+ for (copy = 0; copy <= 1; ++copy)
+ {
+ r = buttons;
+ idx = 0;
+ while (*r)
+ {
+ if (*r == DLG_BUTTON_SEP)
+ {
+ if (copy)
+ {
+ *msgp++ = ',';
+ *msgp++ = ' '; /* '\n' -> ', ' */
+
+ /* advance to next hotkey and set default hotkey */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ hotkp += (*mb_ptr2len_check)(hotkp);
+ else
+#endif
+ ++hotkp;
+ (void)copy_char(r + 1, hotkp, TRUE);
+ if (dfltbutton)
+ --dfltbutton;
+
+ /* If no hotkey is specified first char is used. */
+ if (idx < HAS_HOTKEY_LEN - 1 && !has_hotkey[++idx])
+ first_hotkey = TRUE;
+ }
+ else
+ {
+ len += 3; /* '\n' -> ', '; 'x' -> '(x)' */
+ lenhotkey += HOTK_LEN; /* each button needs a hotkey */
+ if (idx < HAS_HOTKEY_LEN - 1)
+ has_hotkey[++idx] = FALSE;
+ }
+ }
+ else if (*r == DLG_HOTKEY_CHAR || first_hotkey)
+ {
+ if (*r == DLG_HOTKEY_CHAR)
+ ++r;
+ first_hotkey = FALSE;
+ if (copy)
+ {
+ if (*r == DLG_HOTKEY_CHAR) /* '&&a' -> '&a' */
+ *msgp++ = *r;
+ else
+ {
+ /* '&a' -> '[a]' */
+ *msgp++ = (dfltbutton == 1) ? '[' : '(';
+ msgp += copy_char(r, msgp, FALSE);
+ *msgp++ = (dfltbutton == 1) ? ']' : ')';
+
+ /* redefine hotkey */
+ (void)copy_char(r, hotkp, TRUE);
+ }
+ }
+ else
+ {
+ ++len; /* '&a' -> '[a]' */
+ if (idx < HAS_HOTKEY_LEN - 1)
+ has_hotkey[idx] = TRUE;
+ }
+ }
+ else
+ {
+ /* everything else copy literally */
+ if (copy)
+ msgp += copy_char(r, msgp, FALSE);
+ }
+
+ /* advance to the next character */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ r += (*mb_ptr2len_check)(r);
+ else
+#endif
+ ++r;
+ }
+
+ if (copy)
+ {
+ *msgp++ = ':';
+ *msgp++ = ' ';
+ *msgp = NUL;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ hotkp += (*mb_ptr2len_check)(hotkp);
+ else
+#endif
+ ++hotkp;
+ *hotkp = NUL;
+ }
+ else
+ {
+ len += STRLEN(message)
+ + 2 /* for the NL's */
+ + STRLEN(buttons)
+ + 3; /* for the ": " and NUL */
+ lenhotkey++; /* for the NUL */
+
+ /* If no hotkey is specified first char is used. */
+ if (!has_hotkey[0])
+ {
+ first_hotkey = TRUE;
+ len += 2; /* "x" -> "[x]" */
+ }
+
+ /*
+ * Now allocate and load the strings
+ */
+ vim_free(confirm_msg);
+ confirm_msg = alloc(len);
+ if (confirm_msg == NULL)
+ return NULL;
+ *confirm_msg = NUL;
+ hotk = alloc(lenhotkey);
+ if (hotk == NULL)
+ return NULL;
+
+ *confirm_msg = '\n';
+ STRCPY(confirm_msg + 1, message);
+
+ msgp = confirm_msg + 1 + STRLEN(message);
+ hotkp = hotk;
+
+ /* define first default hotkey */
+ (void)copy_char(buttons, hotkp, TRUE);
+
+ /* Remember where the choices start, displaying starts here when
+ * "hotkp" typed at the more prompt. */
+ confirm_msg_tail = msgp;
+ *msgp++ = '\n';
+ }
+ }
+
+ display_confirm_msg();
+ return hotk;
+}
+
+/*
+ * Display the ":confirm" message. Also called when screen resized.
+ */
+ void
+display_confirm_msg()
+{
+ /* avoid that 'q' at the more prompt truncates the message here */
+ ++confirm_msg_used;
+ if (confirm_msg != NULL)
+ msg_puts_attr(confirm_msg, hl_attr(HLF_M));
+ --confirm_msg_used;
+}
+
+#endif /* FEAT_CON_DIALOG */
+
+#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
+
+ int
+vim_dialog_yesno(type, title, message, dflt)
+ int type;
+ char_u *title;
+ char_u *message;
+ int dflt;
+{
+ if (do_dialog(type,
+ title == NULL ? (char_u *)_("Question") : title,
+ message,
+ (char_u *)_("&Yes\n&No"), dflt, NULL) == 1)
+ return VIM_YES;
+ return VIM_NO;
+}
+
+ int
+vim_dialog_yesnocancel(type, title, message, dflt)
+ int type;
+ char_u *title;
+ char_u *message;
+ int dflt;
+{
+ switch (do_dialog(type,
+ title == NULL ? (char_u *)_("Question") : title,
+ message,
+ (char_u *)_("&Yes\n&No\n&Cancel"), dflt, NULL))
+ {
+ case 1: return VIM_YES;
+ case 2: return VIM_NO;
+ }
+ return VIM_CANCEL;
+}
+
+ int
+vim_dialog_yesnoallcancel(type, title, message, dflt)
+ int type;
+ char_u *title;
+ char_u *message;
+ int dflt;
+{
+ switch (do_dialog(type,
+ title == NULL ? (char_u *)"Question" : title,
+ message,
+ (char_u *)_("&Yes\n&No\nSave &All\n&Discard All\n&Cancel"),
+ dflt, NULL))
+ {
+ case 1: return VIM_YES;
+ case 2: return VIM_NO;
+ case 3: return VIM_ALL;
+ case 4: return VIM_DISCARDALL;
+ }
+ return VIM_CANCEL;
+}
+
+#endif /* FEAT_GUI_DIALOG || FEAT_CON_DIALOG */
+
+#if defined(FEAT_BROWSE) || defined(PROTO)
+/*
+ * Generic browse function. Calls gui_mch_browse() when possible.
+ * Later this may pop-up a non-GUI file selector (external command?).
+ */
+ char_u *
+do_browse(saving, title, dflt, ext, initdir, filter, buf)
+ int saving; /* write action */
+ char_u *title; /* title for the window */
+ char_u *dflt; /* default file name (may include directory) */
+ char_u *ext; /* extension added */
+ char_u *initdir; /* initial directory, NULL for current dir or
+ when using path from "dflt" */
+ char_u *filter; /* file name filter */
+ buf_T *buf; /* buffer to read/write for */
+{
+ char_u *fname;
+ static char_u *last_dir = NULL; /* last used directory */
+ char_u *tofree = NULL;
+ int save_browse = cmdmod.browse;
+
+ /* Must turn off browse to avoid that autocommands will get the
+ * flag too! */
+ cmdmod.browse = FALSE;
+
+ if (title == NULL)
+ {
+ if (saving)
+ title = (char_u *)_("Save File dialog");
+ else
+ title = (char_u *)_("Open File dialog");
+ }
+
+ /* When no directory specified, use default file name, default dir, buffer
+ * dir, last dir or current dir */
+ if ((initdir == NULL || *initdir == NUL) && dflt != NULL && *dflt != NUL)
+ {
+ if (mch_isdir(dflt)) /* default file name is a directory */
+ {
+ initdir = dflt;
+ dflt = NULL;
+ }
+ else if (gettail(dflt) != dflt) /* default file name includes a path */
+ {
+ tofree = vim_strsave(dflt);
+ if (tofree != NULL)
+ {
+ initdir = tofree;
+ *gettail(initdir) = NUL;
+ dflt = gettail(dflt);
+ }
+ }
+ }
+
+ if (initdir == NULL || *initdir == NUL)
+ {
+ /* When 'browsedir' is a directory, use it */
+ if (mch_isdir(p_bsdir))
+ initdir = p_bsdir;
+ /* When saving or 'browsedir' is "buffer", use buffer fname */
+ else if ((saving || *p_bsdir == 'b')
+ && buf != NULL && buf->b_ffname != NULL)
+ {
+ if (dflt == NULL || *dflt == NUL)
+ dflt = gettail(curbuf->b_ffname);
+ tofree = vim_strsave(curbuf->b_ffname);
+ if (tofree != NULL)
+ {
+ initdir = tofree;
+ *gettail(initdir) = NUL;
+ }
+ }
+ /* When 'browsedir' is "last", use dir from last browse */
+ else if (*p_bsdir == 'l')
+ initdir = last_dir;
+ /* When 'browsedir is "current", use current directory. This is the
+ * default already, leave initdir empty. */
+ }
+
+# ifdef FEAT_GUI
+ if (gui.in_use) /* when this changes, also adjust f_has()! */
+ {
+ if (filter == NULL
+# ifdef FEAT_EVAL
+ && (filter = get_var_value((char_u *)"b:browsefilter")) == NULL
+ && (filter = get_var_value((char_u *)"g:browsefilter")) == NULL
+# endif
+ )
+ filter = BROWSE_FILTER_DEFAULT;
+ fname = gui_mch_browse(saving, title, dflt, ext, initdir, filter);
+
+ /* We hang around in the dialog for a while, the user might do some
+ * things to our files. The Win32 dialog allows deleting or renaming
+ * a file, check timestamps. */
+ need_check_timestamps = TRUE;
+ did_check_timestamps = FALSE;
+ }
+ else
+# endif
+ {
+ /* TODO: non-GUI file selector here */
+ EMSG(_("E338: Sorry, no file browser in console mode"));
+ fname = NULL;
+ }
+
+ /* keep the directory for next time */
+ if (fname != NULL)
+ {
+ vim_free(last_dir);
+ last_dir = vim_strsave(fname);
+ if (last_dir != NULL)
+ {
+ *gettail(last_dir) = NUL;
+ if (*last_dir == NUL)
+ {
+ /* filename only returned, must be in current dir */
+ vim_free(last_dir);
+ last_dir = alloc(MAXPATHL);
+ if (last_dir != NULL)
+ mch_dirname(last_dir, MAXPATHL);
+ }
+ }
+ }
+
+ vim_free(tofree);
+ cmdmod.browse = save_browse;
+
+ return fname;
+}
+#endif
diff --git a/src/misc1.c b/src/misc1.c
new file mode 100644
index 000000000..0e0705dbd
--- /dev/null
+++ b/src/misc1.c
@@ -0,0 +1,8455 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * misc1.c: functions that didn't seem to fit elsewhere
+ */
+
+#include "vim.h"
+#include "version.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h> /* for chdir() */
+#endif
+
+static char_u *vim_version_dir __ARGS((char_u *vimdir));
+static char_u *remove_tail __ARGS((char_u *p, char_u *pend, char_u *name));
+#if defined(USE_EXE_NAME) && defined(MACOS_X)
+static char_u *remove_tail_with_ext __ARGS((char_u *p, char_u *pend, char_u *ext));
+#endif
+static int get_indent_str __ARGS((char_u *ptr, int ts));
+static int copy_indent __ARGS((int size, char_u *src));
+
+/*
+ * Count the size (in window cells) of the indent in the current line.
+ */
+ int
+get_indent()
+{
+ return get_indent_str(ml_get_curline(), (int)curbuf->b_p_ts);
+}
+
+/*
+ * Count the size (in window cells) of the indent in line "lnum".
+ */
+ int
+get_indent_lnum(lnum)
+ linenr_T lnum;
+{
+ return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts);
+}
+
+#if defined(FEAT_FOLDING) || defined(PROTO)
+/*
+ * Count the size (in window cells) of the indent in line "lnum" of buffer
+ * "buf".
+ */
+ int
+get_indent_buf(buf, lnum)
+ buf_T *buf;
+ linenr_T lnum;
+{
+ return get_indent_str(ml_get_buf(buf, lnum, FALSE), (int)buf->b_p_ts);
+}
+#endif
+
+/*
+ * count the size (in window cells) of the indent in line "ptr", with
+ * 'tabstop' at "ts"
+ */
+ static int
+get_indent_str(ptr, ts)
+ char_u *ptr;
+ int ts;
+{
+ int count = 0;
+
+ for ( ; *ptr; ++ptr)
+ {
+ if (*ptr == TAB) /* count a tab for what it is worth */
+ count += ts - (count % ts);
+ else if (*ptr == ' ')
+ ++count; /* count a space for one */
+ else
+ break;
+ }
+ return (count);
+}
+
+/*
+ * Set the indent of the current line.
+ * Leaves the cursor on the first non-blank in the line.
+ * Caller must take care of undo.
+ * "flags":
+ * SIN_CHANGED: call changed_bytes() if the line was changed.
+ * SIN_INSERT: insert the indent in front of the line.
+ * SIN_UNDO: save line for undo before changing it.
+ * Returns TRUE if the line was changed.
+ */
+ int
+set_indent(size, flags)
+ int size;
+ int flags;
+{
+ char_u *p;
+ char_u *newline;
+ char_u *oldline;
+ char_u *s;
+ int todo;
+ int ind_len;
+ int line_len;
+ int doit = FALSE;
+ int ind_done;
+ int tab_pad;
+
+ /*
+ * First check if there is anything to do and compute the number of
+ * characters needed for the indent.
+ */
+ todo = size;
+ ind_len = 0;
+ p = oldline = ml_get_curline();
+
+ /* Calculate the buffer size for the new indent, and check to see if it
+ * isn't already set */
+
+ /* if 'expandtab' isn't set: use TABs */
+ if (!curbuf->b_p_et)
+ {
+ /* If 'preserveindent' is set then reuse as much as possible of
+ * the existing indent structure for the new indent */
+ if (!(flags & SIN_INSERT) && curbuf->b_p_pi)
+ {
+ ind_done = 0;
+
+ /* count as many characters as we can use */
+ while (todo > 0 && vim_iswhite(*p))
+ {
+ if (*p == TAB)
+ {
+ tab_pad = (int)curbuf->b_p_ts
+ - (ind_done % (int)curbuf->b_p_ts);
+ /* stop if this tab will overshoot the target */
+ if (todo < tab_pad)
+ break;
+ todo -= tab_pad;
+ ++ind_len;
+ ind_done += tab_pad;
+ }
+ else
+ {
+ --todo;
+ ++ind_len;
+ ++ind_done;
+ }
+ ++p;
+ }
+
+ /* Fill to next tabstop with a tab, if possible */
+ tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
+ if (todo >= tab_pad)
+ {
+ doit = TRUE;
+ todo -= tab_pad;
+ ++ind_len;
+ /* ind_done += tab_pad; */
+ }
+ }
+
+ /* count tabs required for indent */
+ while (todo >= (int)curbuf->b_p_ts)
+ {
+ if (*p != TAB)
+ doit = TRUE;
+ else
+ ++p;
+ todo -= (int)curbuf->b_p_ts;
+ ++ind_len;
+ /* ind_done += (int)curbuf->b_p_ts; */
+ }
+ }
+ /* count spaces required for indent */
+ while (todo > 0)
+ {
+ if (*p != ' ')
+ doit = TRUE;
+ else
+ ++p;
+ --todo;
+ ++ind_len;
+ /* ++ind_done; */
+ }
+
+ /* Return if the indent is OK already. */
+ if (!doit && !vim_iswhite(*p) && !(flags & SIN_INSERT))
+ return FALSE;
+
+ /* Allocate memory for the new line. */
+ if (flags & SIN_INSERT)
+ p = oldline;
+ else
+ p = skipwhite(p);
+ line_len = (int)STRLEN(p) + 1;
+ newline = alloc(ind_len + line_len);
+ if (newline == NULL)
+ return FALSE;
+
+ /* Put the characters in the new line. */
+ s = newline;
+ todo = size;
+ /* if 'expandtab' isn't set: use TABs */
+ if (!curbuf->b_p_et)
+ {
+ /* If 'preserveindent' is set then reuse as much as possible of
+ * the existing indent structure for the new indent */
+ if (!(flags & SIN_INSERT) && curbuf->b_p_pi)
+ {
+ p = oldline;
+ ind_done = 0;
+
+ while (todo > 0 && vim_iswhite(*p))
+ {
+ if (*p == TAB)
+ {
+ tab_pad = (int)curbuf->b_p_ts
+ - (ind_done % (int)curbuf->b_p_ts);
+ /* stop if this tab will overshoot the target */
+ if (todo < tab_pad)
+ break;
+ todo -= tab_pad;
+ ind_done += tab_pad;
+ }
+ else
+ {
+ --todo;
+ ++ind_done;
+ }
+ *s++ = *p++;
+ }
+
+ /* Fill to next tabstop with a tab, if possible */
+ tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
+ if (todo >= tab_pad)
+ {
+ *s++ = TAB;
+ todo -= tab_pad;
+ }
+
+ p = skipwhite(p);
+ }
+
+ while (todo >= (int)curbuf->b_p_ts)
+ {
+ *s++ = TAB;
+ todo -= (int)curbuf->b_p_ts;
+ }
+ }
+ while (todo > 0)
+ {
+ *s++ = ' ';
+ --todo;
+ }
+ mch_memmove(s, p, (size_t)line_len);
+
+ /* Replace the line (unless undo fails). */
+ if (!(flags & SIN_UNDO) || u_savesub(curwin->w_cursor.lnum) == OK)
+ {
+ ml_replace(curwin->w_cursor.lnum, newline, FALSE);
+ if (flags & SIN_CHANGED)
+ changed_bytes(curwin->w_cursor.lnum, 0);
+ /* Correct saved cursor position if it's after the indent. */
+ if (saved_cursor.lnum == curwin->w_cursor.lnum
+ && saved_cursor.col >= (colnr_T)(p - oldline))
+ saved_cursor.col += ind_len - (p - oldline);
+ }
+ else
+ vim_free(newline);
+
+ curwin->w_cursor.col = ind_len;
+ return TRUE;
+}
+
+/*
+ * Copy the indent from ptr to the current line (and fill to size)
+ * Leaves the cursor on the first non-blank in the line.
+ * Returns TRUE if the line was changed.
+ */
+ static int
+copy_indent(size, src)
+ int size;
+ char_u *src;
+{
+ char_u *p = NULL;
+ char_u *line = NULL;
+ char_u *s;
+ int todo;
+ int ind_len;
+ int line_len = 0;
+ int tab_pad;
+ int ind_done;
+ int round;
+
+ /* Round 1: compute the number of characters needed for the indent
+ * Round 2: copy the characters. */
+ for (round = 1; round <= 2; ++round)
+ {
+ todo = size;
+ ind_len = 0;
+ ind_done = 0;
+ s = src;
+
+ /* Count/copy the usable portion of the source line */
+ while (todo > 0 && vim_iswhite(*s))
+ {
+ if (*s == TAB)
+ {
+ tab_pad = (int)curbuf->b_p_ts
+ - (ind_done % (int)curbuf->b_p_ts);
+ /* Stop if this tab will overshoot the target */
+ if (todo < tab_pad)
+ break;
+ todo -= tab_pad;
+ ind_done += tab_pad;
+ }
+ else
+ {
+ --todo;
+ ++ind_done;
+ }
+ ++ind_len;
+ if (round == 2)
+ *p++ = *s;
+ ++s;
+ }
+
+ /* Fill to next tabstop with a tab, if possible */
+ tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
+ if (todo >= tab_pad)
+ {
+ todo -= tab_pad;
+ ++ind_len;
+ if (round == 2)
+ *p++ = TAB;
+ }
+
+ /* Add tabs required for indent */
+ while (todo >= (int)curbuf->b_p_ts)
+ {
+ todo -= (int)curbuf->b_p_ts;
+ ++ind_len;
+ if (round == 2)
+ *p++ = TAB;
+ }
+
+ /* Count/add spaces required for indent */
+ while (todo > 0)
+ {
+ --todo;
+ ++ind_len;
+ if (round == 2)
+ *p++ = ' ';
+ }
+
+ if (round == 1)
+ {
+ /* Allocate memory for the result: the copied indent, new indent
+ * and the rest of the line. */
+ line_len = (int)STRLEN(ml_get_curline()) + 1;
+ line = alloc(ind_len + line_len);
+ if (line == NULL)
+ return FALSE;
+ p = line;
+ }
+ }
+
+ /* Append the original line */
+ mch_memmove(p, ml_get_curline(), (size_t)line_len);
+
+ /* Replace the line */
+ ml_replace(curwin->w_cursor.lnum, line, FALSE);
+
+ /* Put the cursor after the indent. */
+ curwin->w_cursor.col = ind_len;
+ return TRUE;
+}
+
+/*
+ * Return the indent of the current line after a number. Return -1 if no
+ * number was found. Used for 'n' in 'formatoptions': numbered list.
+ */
+ int
+get_number_indent(lnum)
+ linenr_T lnum;
+{
+ char_u *line;
+ char_u *p;
+ colnr_T col;
+ pos_T pos;
+
+ if (lnum > curbuf->b_ml.ml_line_count)
+ return -1;
+ line = ml_get(lnum);
+ p = skipwhite(line);
+ if (!VIM_ISDIGIT(*p))
+ return -1;
+ p = skipdigits(p);
+ if (vim_strchr((char_u *)":.)]}\t ", *p) == NULL)
+ return -1;
+ p = skipwhite(p + 1);
+ if (*p == NUL)
+ return -1;
+ pos.lnum = lnum;
+ pos.col = (colnr_T)(p - line);
+ getvcol(curwin, &pos, &col, NULL, NULL);
+ return (int)col;
+}
+
+#if defined(FEAT_CINDENT) || defined(FEAT_SMARTINDENT)
+
+static int cin_is_cinword __ARGS((char_u *line));
+
+/*
+ * Return TRUE if the string "line" starts with a word from 'cinwords'.
+ */
+ static int
+cin_is_cinword(line)
+ char_u *line;
+{
+ char_u *cinw;
+ char_u *cinw_buf;
+ int cinw_len;
+ int retval = FALSE;
+ int len;
+
+ cinw_len = (int)STRLEN(curbuf->b_p_cinw) + 1;
+ cinw_buf = alloc((unsigned)cinw_len);
+ if (cinw_buf != NULL)
+ {
+ line = skipwhite(line);
+ for (cinw = curbuf->b_p_cinw; *cinw; )
+ {
+ len = copy_option_part(&cinw, cinw_buf, cinw_len, ",");
+ if (STRNCMP(line, cinw_buf, len) == 0
+ && (!vim_iswordc(line[len]) || !vim_iswordc(line[len - 1])))
+ {
+ retval = TRUE;
+ break;
+ }
+ }
+ vim_free(cinw_buf);
+ }
+ return retval;
+}
+#endif
+
+/*
+ * open_line: Add a new line below or above the current line.
+ *
+ * For VREPLACE mode, we only add a new line when we get to the end of the
+ * file, otherwise we just start replacing the next line.
+ *
+ * Caller must take care of undo. Since VREPLACE may affect any number of
+ * lines however, it may call u_save_cursor() again when starting to change a
+ * new line.
+ * "flags": OPENLINE_DELSPACES delete spaces after cursor
+ * OPENLINE_DO_COM format comments
+ * OPENLINE_KEEPTRAIL keep trailing spaces
+ * OPENLINE_MARKFIX adjust mark positions after the line break
+ *
+ * Return TRUE for success, FALSE for failure
+ */
+ int
+open_line(dir, flags, old_indent)
+ int dir; /* FORWARD or BACKWARD */
+ int flags;
+ int old_indent; /* indent for after ^^D in Insert mode */
+{
+ char_u *saved_line; /* copy of the original line */
+ char_u *next_line = NULL; /* copy of the next line */
+ char_u *p_extra = NULL; /* what goes to next line */
+ int less_cols = 0; /* less columns for mark in new line */
+ int less_cols_off = 0; /* columns to skip for mark adjust */
+ pos_T old_cursor; /* old cursor position */
+ int newcol = 0; /* new cursor column */
+ int newindent = 0; /* auto-indent of the new line */
+ int n;
+ int trunc_line = FALSE; /* truncate current line afterwards */
+ int retval = FALSE; /* return value, default is FAIL */
+#ifdef FEAT_COMMENTS
+ int extra_len = 0; /* length of p_extra string */
+ int lead_len; /* length of comment leader */
+ char_u *lead_flags; /* position in 'comments' for comment leader */
+ char_u *leader = NULL; /* copy of comment leader */
+#endif
+ char_u *allocated = NULL; /* allocated memory */
+#if defined(FEAT_SMARTINDENT) || defined(FEAT_VREPLACE) || defined(FEAT_LISP) \
+ || defined(FEAT_CINDENT) || defined(FEAT_COMMENTS)
+ char_u *p;
+#endif
+ int saved_char = NUL; /* init for GCC */
+#if defined(FEAT_SMARTINDENT) || defined(FEAT_COMMENTS)
+ pos_T *pos;
+#endif
+#ifdef FEAT_SMARTINDENT
+ int do_si = (!p_paste && curbuf->b_p_si
+# ifdef FEAT_CINDENT
+ && !curbuf->b_p_cin
+# endif
+ );
+ int no_si = FALSE; /* reset did_si afterwards */
+ int first_char = NUL; /* init for GCC */
+#endif
+#if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT))
+ int vreplace_mode;
+#endif
+ int did_append; /* appended a new line */
+ int saved_pi = curbuf->b_p_pi; /* copy of preserveindent setting */
+
+ /*
+ * make a copy of the current line so we can mess with it
+ */
+ saved_line = vim_strsave(ml_get_curline());
+ if (saved_line == NULL) /* out of memory! */
+ return FALSE;
+
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ {
+ /*
+ * With VREPLACE we make a copy of the next line, which we will be
+ * starting to replace. First make the new line empty and let vim play
+ * with the indenting and comment leader to its heart's content. Then
+ * we grab what it ended up putting on the new line, put back the
+ * original line, and call ins_char() to put each new character onto
+ * the line, replacing what was there before and pushing the right
+ * stuff onto the replace stack. -- webb.
+ */
+ if (curwin->w_cursor.lnum < orig_line_count)
+ next_line = vim_strsave(ml_get(curwin->w_cursor.lnum + 1));
+ else
+ next_line = vim_strsave((char_u *)"");
+ if (next_line == NULL) /* out of memory! */
+ goto theend;
+
+ /*
+ * In VREPLACE mode, a NL replaces the rest of the line, and starts
+ * replacing the next line, so push all of the characters left on the
+ * line onto the replace stack. We'll push any other characters that
+ * might be replaced at the start of the next line (due to autoindent
+ * etc) a bit later.
+ */
+ replace_push(NUL); /* Call twice because BS over NL expects it */
+ replace_push(NUL);
+ p = saved_line + curwin->w_cursor.col;
+ while (*p != NUL)
+ replace_push(*p++);
+ saved_line[curwin->w_cursor.col] = NUL;
+ }
+#endif
+
+ if ((State & INSERT)
+#ifdef FEAT_VREPLACE
+ && !(State & VREPLACE_FLAG)
+#endif
+ )
+ {
+ p_extra = saved_line + curwin->w_cursor.col;
+#ifdef FEAT_SMARTINDENT
+ if (do_si) /* need first char after new line break */
+ {
+ p = skipwhite(p_extra);
+ first_char = *p;
+ }
+#endif
+#ifdef FEAT_COMMENTS
+ extra_len = (int)STRLEN(p_extra);
+#endif
+ saved_char = *p_extra;
+ *p_extra = NUL;
+ }
+
+ u_clearline(); /* cannot do "U" command when adding lines */
+#ifdef FEAT_SMARTINDENT
+ did_si = FALSE;
+#endif
+ ai_col = 0;
+
+ /*
+ * If we just did an auto-indent, then we didn't type anything on
+ * the prior line, and it should be truncated. Do this even if 'ai' is not
+ * set because automatically inserting a comment leader also sets did_ai.
+ */
+ if (dir == FORWARD && did_ai)
+ trunc_line = TRUE;
+
+ /*
+ * If 'autoindent' and/or 'smartindent' is set, try to figure out what
+ * indent to use for the new line.
+ */
+ if (curbuf->b_p_ai
+#ifdef FEAT_SMARTINDENT
+ || do_si
+#endif
+ )
+ {
+ /*
+ * count white space on current line
+ */
+ newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts);
+ if (newindent == 0)
+ newindent = old_indent; /* for ^^D command in insert mode */
+
+#ifdef FEAT_SMARTINDENT
+ /*
+ * Do smart indenting.
+ * In insert/replace mode (only when dir == FORWARD)
+ * we may move some text to the next line. If it starts with '{'
+ * don't add an indent. Fixes inserting a NL before '{' in line
+ * "if (condition) {"
+ */
+ if (!trunc_line && do_si && *saved_line != NUL
+ && (p_extra == NULL || first_char != '{'))
+ {
+ char_u *ptr;
+ char_u last_char;
+
+ old_cursor = curwin->w_cursor;
+ ptr = saved_line;
+# ifdef FEAT_COMMENTS
+ if (flags & OPENLINE_DO_COM)
+ lead_len = get_leader_len(ptr, NULL, FALSE);
+ else
+ lead_len = 0;
+# endif
+ if (dir == FORWARD)
+ {
+ /*
+ * Skip preprocessor directives, unless they are
+ * recognised as comments.
+ */
+ if (
+# ifdef FEAT_COMMENTS
+ lead_len == 0 &&
+# endif
+ ptr[0] == '#')
+ {
+ while (ptr[0] == '#' && curwin->w_cursor.lnum > 1)
+ ptr = ml_get(--curwin->w_cursor.lnum);
+ newindent = get_indent();
+ }
+# ifdef FEAT_COMMENTS
+ if (flags & OPENLINE_DO_COM)
+ lead_len = get_leader_len(ptr, NULL, FALSE);
+ else
+ lead_len = 0;
+ if (lead_len > 0)
+ {
+ /*
+ * This case gets the following right:
+ * \*
+ * * A comment (read '\' as '/').
+ * *\
+ * #define IN_THE_WAY
+ * This should line up here;
+ */
+ p = skipwhite(ptr);
+ if (p[0] == '/' && p[1] == '*')
+ p++;
+ if (p[0] == '*')
+ {
+ for (p++; *p; p++)
+ {
+ if (p[0] == '/' && p[-1] == '*')
+ {
+ /*
+ * End of C comment, indent should line up
+ * with the line containing the start of
+ * the comment
+ */
+ curwin->w_cursor.col = (colnr_T)(p - ptr);
+ if ((pos = findmatch(NULL, NUL)) != NULL)
+ {
+ curwin->w_cursor.lnum = pos->lnum;
+ newindent = get_indent();
+ }
+ }
+ }
+ }
+ }
+ else /* Not a comment line */
+# endif
+ {
+ /* Find last non-blank in line */
+ p = ptr + STRLEN(ptr) - 1;
+ while (p > ptr && vim_iswhite(*p))
+ --p;
+ last_char = *p;
+
+ /*
+ * find the character just before the '{' or ';'
+ */
+ if (last_char == '{' || last_char == ';')
+ {
+ if (p > ptr)
+ --p;
+ while (p > ptr && vim_iswhite(*p))
+ --p;
+ }
+ /*
+ * Try to catch lines that are split over multiple
+ * lines. eg:
+ * if (condition &&
+ * condition) {
+ * Should line up here!
+ * }
+ */
+ if (*p == ')')
+ {
+ curwin->w_cursor.col = (colnr_T)(p - ptr);
+ if ((pos = findmatch(NULL, '(')) != NULL)
+ {
+ curwin->w_cursor.lnum = pos->lnum;
+ newindent = get_indent();
+ ptr = ml_get_curline();
+ }
+ }
+ /*
+ * If last character is '{' do indent, without
+ * checking for "if" and the like.
+ */
+ if (last_char == '{')
+ {
+ did_si = TRUE; /* do indent */
+ no_si = TRUE; /* don't delete it when '{' typed */
+ }
+ /*
+ * Look for "if" and the like, use 'cinwords'.
+ * Don't do this if the previous line ended in ';' or
+ * '}'.
+ */
+ else if (last_char != ';' && last_char != '}'
+ && cin_is_cinword(ptr))
+ did_si = TRUE;
+ }
+ }
+ else /* dir == BACKWARD */
+ {
+ /*
+ * Skip preprocessor directives, unless they are
+ * recognised as comments.
+ */
+ if (
+# ifdef FEAT_COMMENTS
+ lead_len == 0 &&
+# endif
+ ptr[0] == '#')
+ {
+ int was_backslashed = FALSE;
+
+ while ((ptr[0] == '#' || was_backslashed) &&
+ curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
+ {
+ if (*ptr && ptr[STRLEN(ptr) - 1] == '\\')
+ was_backslashed = TRUE;
+ else
+ was_backslashed = FALSE;
+ ptr = ml_get(++curwin->w_cursor.lnum);
+ }
+ if (was_backslashed)
+ newindent = 0; /* Got to end of file */
+ else
+ newindent = get_indent();
+ }
+ p = skipwhite(ptr);
+ if (*p == '}') /* if line starts with '}': do indent */
+ did_si = TRUE;
+ else /* can delete indent when '{' typed */
+ can_si_back = TRUE;
+ }
+ curwin->w_cursor = old_cursor;
+ }
+ if (do_si)
+ can_si = TRUE;
+#endif /* FEAT_SMARTINDENT */
+
+ did_ai = TRUE;
+ }
+
+#ifdef FEAT_COMMENTS
+ /*
+ * Find out if the current line starts with a comment leader.
+ * This may then be inserted in front of the new line.
+ */
+ end_comment_pending = NUL;
+ if (flags & OPENLINE_DO_COM)
+ lead_len = get_leader_len(saved_line, &lead_flags, dir == BACKWARD);
+ else
+ lead_len = 0;
+ if (lead_len > 0)
+ {
+ char_u *lead_repl = NULL; /* replaces comment leader */
+ int lead_repl_len = 0; /* length of *lead_repl */
+ char_u lead_middle[COM_MAX_LEN]; /* middle-comment string */
+ char_u lead_end[COM_MAX_LEN]; /* end-comment string */
+ char_u *comment_end = NULL; /* where lead_end has been found */
+ int extra_space = FALSE; /* append extra space */
+ int current_flag;
+ int require_blank = FALSE; /* requires blank after middle */
+ char_u *p2;
+
+ /*
+ * If the comment leader has the start, middle or end flag, it may not
+ * be used or may be replaced with the middle leader.
+ */
+ for (p = lead_flags; *p && *p != ':'; ++p)
+ {
+ if (*p == COM_BLANK)
+ {
+ require_blank = TRUE;
+ continue;
+ }
+ if (*p == COM_START || *p == COM_MIDDLE)
+ {
+ current_flag = *p;
+ if (*p == COM_START)
+ {
+ /*
+ * Doing "O" on a start of comment does not insert leader.
+ */
+ if (dir == BACKWARD)
+ {
+ lead_len = 0;
+ break;
+ }
+
+ /* find start of middle part */
+ (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ",");
+ require_blank = FALSE;
+ }
+
+ /*
+ * Isolate the strings of the middle and end leader.
+ */
+ while (*p && p[-1] != ':') /* find end of middle flags */
+ {
+ if (*p == COM_BLANK)
+ require_blank = TRUE;
+ ++p;
+ }
+ (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ",");
+
+ while (*p && p[-1] != ':') /* find end of end flags */
+ {
+ /* Check whether we allow automatic ending of comments */
+ if (*p == COM_AUTO_END)
+ end_comment_pending = -1; /* means we want to set it */
+ ++p;
+ }
+ n = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
+
+ if (end_comment_pending == -1) /* we can set it now */
+ end_comment_pending = lead_end[n - 1];
+
+ /*
+ * If the end of the comment is in the same line, don't use
+ * the comment leader.
+ */
+ if (dir == FORWARD)
+ {
+ for (p = saved_line + lead_len; *p; ++p)
+ if (STRNCMP(p, lead_end, n) == 0)
+ {
+ comment_end = p;
+ lead_len = 0;
+ break;
+ }
+ }
+
+ /*
+ * Doing "o" on a start of comment inserts the middle leader.
+ */
+ if (lead_len > 0)
+ {
+ if (current_flag == COM_START)
+ {
+ lead_repl = lead_middle;
+ lead_repl_len = (int)STRLEN(lead_middle);
+ }
+
+ /*
+ * If we have hit RETURN immediately after the start
+ * comment leader, then put a space after the middle
+ * comment leader on the next line.
+ */
+ if (!vim_iswhite(saved_line[lead_len - 1])
+ && ((p_extra != NULL
+ && (int)curwin->w_cursor.col == lead_len)
+ || (p_extra == NULL
+ && saved_line[lead_len] == NUL)
+ || require_blank))
+ extra_space = TRUE;
+ }
+ break;
+ }
+ if (*p == COM_END)
+ {
+ /*
+ * Doing "o" on the end of a comment does not insert leader.
+ * Remember where the end is, might want to use it to find the
+ * start (for C-comments).
+ */
+ if (dir == FORWARD)
+ {
+ comment_end = skipwhite(saved_line);
+ lead_len = 0;
+ break;
+ }
+
+ /*
+ * Doing "O" on the end of a comment inserts the middle leader.
+ * Find the string for the middle leader, searching backwards.
+ */
+ while (p > curbuf->b_p_com && *p != ',')
+ --p;
+ for (lead_repl = p; lead_repl > curbuf->b_p_com
+ && lead_repl[-1] != ':'; --lead_repl)
+ ;
+ lead_repl_len = (int)(p - lead_repl);
+
+ /* We can probably always add an extra space when doing "O" on
+ * the comment-end */
+ extra_space = TRUE;
+
+ /* Check whether we allow automatic ending of comments */
+ for (p2 = p; *p2 && *p2 != ':'; p2++)
+ {
+ if (*p2 == COM_AUTO_END)
+ end_comment_pending = -1; /* means we want to set it */
+ }
+ if (end_comment_pending == -1)
+ {
+ /* Find last character in end-comment string */
+ while (*p2 && *p2 != ',')
+ p2++;
+ end_comment_pending = p2[-1];
+ }
+ break;
+ }
+ if (*p == COM_FIRST)
+ {
+ /*
+ * Comment leader for first line only: Don't repeat leader
+ * when using "O", blank out leader when using "o".
+ */
+ if (dir == BACKWARD)
+ lead_len = 0;
+ else
+ {
+ lead_repl = (char_u *)"";
+ lead_repl_len = 0;
+ }
+ break;
+ }
+ }
+ if (lead_len)
+ {
+ /* allocate buffer (may concatenate p_exta later) */
+ leader = alloc(lead_len + lead_repl_len + extra_space +
+ extra_len + 1);
+ allocated = leader; /* remember to free it later */
+
+ if (leader == NULL)
+ lead_len = 0;
+ else
+ {
+ STRNCPY(leader, saved_line, lead_len);
+ leader[lead_len] = NUL;
+
+ /*
+ * Replace leader with lead_repl, right or left adjusted
+ */
+ if (lead_repl != NULL)
+ {
+ int c = 0;
+ int off = 0;
+
+ for (p = lead_flags; *p && *p != ':'; ++p)
+ {
+ if (*p == COM_RIGHT || *p == COM_LEFT)
+ c = *p;
+ else if (VIM_ISDIGIT(*p) || *p == '-')
+ off = getdigits(&p);
+ }
+ if (c == COM_RIGHT) /* right adjusted leader */
+ {
+ /* find last non-white in the leader to line up with */
+ for (p = leader + lead_len - 1; p > leader
+ && vim_iswhite(*p); --p)
+ ;
+
+ ++p;
+ if (p < leader + lead_repl_len)
+ p = leader;
+ else
+ p -= lead_repl_len;
+ mch_memmove(p, lead_repl, (size_t)lead_repl_len);
+ if (p + lead_repl_len > leader + lead_len)
+ p[lead_repl_len] = NUL;
+
+ /* blank-out any other chars from the old leader. */
+ while (--p >= leader)
+ if (!vim_iswhite(*p))
+ *p = ' ';
+ }
+ else /* left adjusted leader */
+ {
+ p = skipwhite(leader);
+ mch_memmove(p, lead_repl, (size_t)lead_repl_len);
+
+ /* Replace any remaining non-white chars in the old
+ * leader by spaces. Keep Tabs, the indent must
+ * remain the same. */
+ for (p += lead_repl_len; p < leader + lead_len; ++p)
+ if (!vim_iswhite(*p))
+ {
+ /* Don't put a space before a TAB. */
+ if (p + 1 < leader + lead_len && p[1] == TAB)
+ {
+ --lead_len;
+ mch_memmove(p, p + 1,
+ (leader + lead_len) - p);
+ }
+ else
+ *p = ' ';
+ }
+ *p = NUL;
+ }
+
+ /* Recompute the indent, it may have changed. */
+ if (curbuf->b_p_ai
+#ifdef FEAT_SMARTINDENT
+ || do_si
+#endif
+ )
+ newindent = get_indent_str(leader, (int)curbuf->b_p_ts);
+
+ /* Add the indent offset */
+ if (newindent + off < 0)
+ {
+ off = -newindent;
+ newindent = 0;
+ }
+ else
+ newindent += off;
+
+ /* Correct trailing spaces for the shift, so that
+ * alignment remains equal. */
+ while (off > 0 && lead_len > 0
+ && leader[lead_len - 1] == ' ')
+ {
+ /* Don't do it when there is a tab before the space */
+ if (vim_strchr(skipwhite(leader), '\t') != NULL)
+ break;
+ --lead_len;
+ --off;
+ }
+
+ /* If the leader ends in white space, don't add an
+ * extra space */
+ if (lead_len > 0 && vim_iswhite(leader[lead_len - 1]))
+ extra_space = FALSE;
+ leader[lead_len] = NUL;
+ }
+
+ if (extra_space)
+ {
+ leader[lead_len++] = ' ';
+ leader[lead_len] = NUL;
+ }
+
+ newcol = lead_len;
+
+ /*
+ * if a new indent will be set below, remove the indent that
+ * is in the comment leader
+ */
+ if (newindent
+#ifdef FEAT_SMARTINDENT
+ || did_si
+#endif
+ )
+ {
+ while (lead_len && vim_iswhite(*leader))
+ {
+ --lead_len;
+ --newcol;
+ ++leader;
+ }
+ }
+
+ }
+#ifdef FEAT_SMARTINDENT
+ did_si = can_si = FALSE;
+#endif
+ }
+ else if (comment_end != NULL)
+ {
+ /*
+ * We have finished a comment, so we don't use the leader.
+ * If this was a C-comment and 'ai' or 'si' is set do a normal
+ * indent to align with the line containing the start of the
+ * comment.
+ */
+ if (comment_end[0] == '*' && comment_end[1] == '/' &&
+ (curbuf->b_p_ai
+#ifdef FEAT_SMARTINDENT
+ || do_si
+#endif
+ ))
+ {
+ old_cursor = curwin->w_cursor;
+ curwin->w_cursor.col = (colnr_T)(comment_end - saved_line);
+ if ((pos = findmatch(NULL, NUL)) != NULL)
+ {
+ curwin->w_cursor.lnum = pos->lnum;
+ newindent = get_indent();
+ }
+ curwin->w_cursor = old_cursor;
+ }
+ }
+ }
+#endif
+
+ /* (State == INSERT || State == REPLACE), only when dir == FORWARD */
+ if (p_extra != NULL)
+ {
+ *p_extra = saved_char; /* restore char that NUL replaced */
+
+ /*
+ * When 'ai' set or "flags" has OPENLINE_DELSPACES, skip to the first
+ * non-blank.
+ *
+ * When in REPLACE mode, put the deleted blanks on the replace stack,
+ * preceded by a NUL, so they can be put back when a BS is entered.
+ */
+ if (REPLACE_NORMAL(State))
+ replace_push(NUL); /* end of extra blanks */
+ if (curbuf->b_p_ai || (flags & OPENLINE_DELSPACES))
+ {
+ while ((*p_extra == ' ' || *p_extra == '\t')
+#ifdef FEAT_MBYTE
+ && (!enc_utf8
+ || !utf_iscomposing(utf_ptr2char(p_extra + 1)))
+#endif
+ )
+ {
+ if (REPLACE_NORMAL(State))
+ replace_push(*p_extra);
+ ++p_extra;
+ ++less_cols_off;
+ }
+ }
+ if (*p_extra != NUL)
+ did_ai = FALSE; /* append some text, don't truncate now */
+
+ /* columns for marks adjusted for removed columns */
+ less_cols = (int)(p_extra - saved_line);
+ }
+
+ if (p_extra == NULL)
+ p_extra = (char_u *)""; /* append empty line */
+
+#ifdef FEAT_COMMENTS
+ /* concatenate leader and p_extra, if there is a leader */
+ if (lead_len)
+ {
+ STRCAT(leader, p_extra);
+ p_extra = leader;
+ did_ai = TRUE; /* So truncating blanks works with comments */
+ less_cols -= lead_len;
+ }
+ else
+ end_comment_pending = NUL; /* turns out there was no leader */
+#endif
+
+ old_cursor = curwin->w_cursor;
+ if (dir == BACKWARD)
+ --curwin->w_cursor.lnum;
+#ifdef FEAT_VREPLACE
+ if (!(State & VREPLACE_FLAG) || old_cursor.lnum >= orig_line_count)
+#endif
+ {
+ if (ml_append(curwin->w_cursor.lnum, p_extra, (colnr_T)0, FALSE)
+ == FAIL)
+ goto theend;
+ /* Postpone calling changed_lines(), because it would mess up folding
+ * with markers. */
+ mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L);
+ did_append = TRUE;
+ }
+#ifdef FEAT_VREPLACE
+ else
+ {
+ /*
+ * In VREPLACE mode we are starting to replace the next line.
+ */
+ curwin->w_cursor.lnum++;
+ if (curwin->w_cursor.lnum >= Insstart.lnum + vr_lines_changed)
+ {
+ /* In case we NL to a new line, BS to the previous one, and NL
+ * again, we don't want to save the new line for undo twice.
+ */
+ (void)u_save_cursor(); /* errors are ignored! */
+ vr_lines_changed++;
+ }
+ ml_replace(curwin->w_cursor.lnum, p_extra, TRUE);
+ changed_bytes(curwin->w_cursor.lnum, 0);
+ curwin->w_cursor.lnum--;
+ did_append = FALSE;
+ }
+#endif
+
+ if (newindent
+#ifdef FEAT_SMARTINDENT
+ || did_si
+#endif
+ )
+ {
+ ++curwin->w_cursor.lnum;
+#ifdef FEAT_SMARTINDENT
+ if (did_si)
+ {
+ if (p_sr)
+ newindent -= newindent % (int)curbuf->b_p_sw;
+ newindent += (int)curbuf->b_p_sw;
+ }
+#endif
+ /* Copy the indent only if expand tab is disabled */
+ if (curbuf->b_p_ci && !curbuf->b_p_et)
+ {
+ (void)copy_indent(newindent, saved_line);
+
+ /*
+ * Set the 'preserveindent' option so that any further screwing
+ * with the line doesn't entirely destroy our efforts to preserve
+ * it. It gets restored at the function end.
+ */
+ curbuf->b_p_pi = TRUE;
+ }
+ else
+ (void)set_indent(newindent, SIN_INSERT);
+ less_cols -= curwin->w_cursor.col;
+
+ ai_col = curwin->w_cursor.col;
+
+ /*
+ * In REPLACE mode, for each character in the new indent, there must
+ * be a NUL on the replace stack, for when it is deleted with BS
+ */
+ if (REPLACE_NORMAL(State))
+ for (n = 0; n < (int)curwin->w_cursor.col; ++n)
+ replace_push(NUL);
+ newcol += curwin->w_cursor.col;
+#ifdef FEAT_SMARTINDENT
+ if (no_si)
+ did_si = FALSE;
+#endif
+ }
+
+#ifdef FEAT_COMMENTS
+ /*
+ * In REPLACE mode, for each character in the extra leader, there must be
+ * a NUL on the replace stack, for when it is deleted with BS.
+ */
+ if (REPLACE_NORMAL(State))
+ while (lead_len-- > 0)
+ replace_push(NUL);
+#endif
+
+ curwin->w_cursor = old_cursor;
+
+ if (dir == FORWARD)
+ {
+ if (trunc_line || (State & INSERT))
+ {
+ /* truncate current line at cursor */
+ saved_line[curwin->w_cursor.col] = NUL;
+ /* Remove trailing white space, unless OPENLINE_KEEPTRAIL used. */
+ if (trunc_line && !(flags & OPENLINE_KEEPTRAIL))
+ truncate_spaces(saved_line);
+ ml_replace(curwin->w_cursor.lnum, saved_line, FALSE);
+ saved_line = NULL;
+ if (did_append)
+ {
+ changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col,
+ curwin->w_cursor.lnum + 1, 1L);
+ did_append = FALSE;
+
+ /* Move marks after the line break to the new line. */
+ if (flags & OPENLINE_MARKFIX)
+ mark_col_adjust(curwin->w_cursor.lnum,
+ curwin->w_cursor.col + less_cols_off,
+ 1L, (long)-less_cols);
+ }
+ else
+ changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
+ }
+
+ /*
+ * Put the cursor on the new line. Careful: the scrollup() above may
+ * have moved w_cursor, we must use old_cursor.
+ */
+ curwin->w_cursor.lnum = old_cursor.lnum + 1;
+ }
+ if (did_append)
+ changed_lines(curwin->w_cursor.lnum, 0, curwin->w_cursor.lnum, 1L);
+
+ curwin->w_cursor.col = newcol;
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+
+#if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT))
+ /*
+ * In VREPLACE mode, we are handling the replace stack ourselves, so stop
+ * fixthisline() from doing it (via change_indent()) by telling it we're in
+ * normal INSERT mode.
+ */
+ if (State & VREPLACE_FLAG)
+ {
+ vreplace_mode = State; /* So we know to put things right later */
+ State = INSERT;
+ }
+ else
+ vreplace_mode = 0;
+#endif
+#ifdef FEAT_LISP
+ /*
+ * May do lisp indenting.
+ */
+ if (!p_paste
+# ifdef FEAT_COMMENTS
+ && leader == NULL
+# endif
+ && curbuf->b_p_lisp
+ && curbuf->b_p_ai)
+ {
+ fixthisline(get_lisp_indent);
+ p = ml_get_curline();
+ ai_col = (colnr_T)(skipwhite(p) - p);
+ }
+#endif
+#ifdef FEAT_CINDENT
+ /*
+ * May do indenting after opening a new line.
+ */
+ if (!p_paste
+ && (curbuf->b_p_cin
+# ifdef FEAT_EVAL
+ || *curbuf->b_p_inde != NUL
+# endif
+ )
+ && in_cinkeys(dir == FORWARD
+ ? KEY_OPEN_FORW
+ : KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum)))
+ {
+ do_c_expr_indent();
+ p = ml_get_curline();
+ ai_col = (colnr_T)(skipwhite(p) - p);
+ }
+#endif
+#if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT))
+ if (vreplace_mode != 0)
+ State = vreplace_mode;
+#endif
+
+#ifdef FEAT_VREPLACE
+ /*
+ * Finally, VREPLACE gets the stuff on the new line, then puts back the
+ * original line, and inserts the new stuff char by char, pushing old stuff
+ * onto the replace stack (via ins_char()).
+ */
+ if (State & VREPLACE_FLAG)
+ {
+ /* Put new line in p_extra */
+ p_extra = vim_strsave(ml_get_curline());
+ if (p_extra == NULL)
+ goto theend;
+
+ /* Put back original line */
+ ml_replace(curwin->w_cursor.lnum, next_line, FALSE);
+
+ /* Insert new stuff into line again */
+ curwin->w_cursor.col = 0;
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ ins_bytes(p_extra); /* will call changed_bytes() */
+ vim_free(p_extra);
+ next_line = NULL;
+ }
+#endif
+
+ retval = TRUE; /* success! */
+theend:
+ curbuf->b_p_pi = saved_pi;
+ vim_free(saved_line);
+ vim_free(next_line);
+ vim_free(allocated);
+ return retval;
+}
+
+#if defined(FEAT_COMMENTS) || defined(PROTO)
+/*
+ * get_leader_len() returns the length of the prefix of the given string
+ * which introduces a comment. If this string is not a comment then 0 is
+ * returned.
+ * When "flags" is not NULL, it is set to point to the flags of the recognized
+ * comment leader.
+ * "backward" must be true for the "O" command.
+ */
+ int
+get_leader_len(line, flags, backward)
+ char_u *line;
+ char_u **flags;
+ int backward;
+{
+ int i, j;
+ int got_com = FALSE;
+ int found_one;
+ char_u part_buf[COM_MAX_LEN]; /* buffer for one option part */
+ char_u *string; /* pointer to comment string */
+ char_u *list;
+
+ i = 0;
+ while (vim_iswhite(line[i])) /* leading white space is ignored */
+ ++i;
+
+ /*
+ * Repeat to match several nested comment strings.
+ */
+ while (line[i])
+ {
+ /*
+ * scan through the 'comments' option for a match
+ */
+ found_one = FALSE;
+ for (list = curbuf->b_p_com; *list; )
+ {
+ /*
+ * Get one option part into part_buf[]. Advance list to next one.
+ * put string at start of string.
+ */
+ if (!got_com && flags != NULL) /* remember where flags started */
+ *flags = list;
+ (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
+ string = vim_strchr(part_buf, ':');
+ if (string == NULL) /* missing ':', ignore this part */
+ continue;
+ *string++ = NUL; /* isolate flags from string */
+
+ /*
+ * When already found a nested comment, only accept further
+ * nested comments.
+ */
+ if (got_com && vim_strchr(part_buf, COM_NEST) == NULL)
+ continue;
+
+ /* When 'O' flag used don't use for "O" command */
+ if (backward && vim_strchr(part_buf, COM_NOBACK) != NULL)
+ continue;
+
+ /*
+ * Line contents and string must match.
+ * When string starts with white space, must have some white space
+ * (but the amount does not need to match, there might be a mix of
+ * TABs and spaces).
+ */
+ if (vim_iswhite(string[0]))
+ {
+ if (i == 0 || !vim_iswhite(line[i - 1]))
+ continue;
+ while (vim_iswhite(string[0]))
+ ++string;
+ }
+ for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j)
+ ;
+ if (string[j] != NUL)
+ continue;
+
+ /*
+ * When 'b' flag used, there must be white space or an
+ * end-of-line after the string in the line.
+ */
+ if (vim_strchr(part_buf, COM_BLANK) != NULL
+ && !vim_iswhite(line[i + j]) && line[i + j] != NUL)
+ continue;
+
+ /*
+ * We have found a match, stop searching.
+ */
+ i += j;
+ got_com = TRUE;
+ found_one = TRUE;
+ break;
+ }
+
+ /*
+ * No match found, stop scanning.
+ */
+ if (!found_one)
+ break;
+
+ /*
+ * Include any trailing white space.
+ */
+ while (vim_iswhite(line[i]))
+ ++i;
+
+ /*
+ * If this comment doesn't nest, stop here.
+ */
+ if (vim_strchr(part_buf, COM_NEST) == NULL)
+ break;
+ }
+ return (got_com ? i : 0);
+}
+#endif
+
+/*
+ * Return the number of window lines occupied by buffer line "lnum".
+ */
+ int
+plines(lnum)
+ linenr_T lnum;
+{
+ return plines_win(curwin, lnum, TRUE);
+}
+
+ int
+plines_win(wp, lnum, winheight)
+ win_T *wp;
+ linenr_T lnum;
+ int winheight; /* when TRUE limit to window height */
+{
+#if defined(FEAT_DIFF) || defined(PROTO)
+ /* Check for filler lines above this buffer line. When folded the result
+ * is one line anyway. */
+ return plines_win_nofill(wp, lnum, winheight) + diff_check_fill(wp, lnum);
+}
+
+ int
+plines_nofill(lnum)
+ linenr_T lnum;
+{
+ return plines_win_nofill(curwin, lnum, TRUE);
+}
+
+ int
+plines_win_nofill(wp, lnum, winheight)
+ win_T *wp;
+ linenr_T lnum;
+ int winheight; /* when TRUE limit to window height */
+{
+#endif
+ int lines;
+
+ if (!wp->w_p_wrap)
+ return 1;
+
+#ifdef FEAT_VERTSPLIT
+ if (wp->w_width == 0)
+ return 1;
+#endif
+
+#ifdef FEAT_FOLDING
+ /* A folded lines is handled just like an empty line. */
+ /* NOTE: Caller must handle lines that are MAYBE folded. */
+ if (lineFolded(wp, lnum) == TRUE)
+ return 1;
+#endif
+
+ lines = plines_win_nofold(wp, lnum);
+ if (winheight > 0 && lines > wp->w_height)
+ return (int)wp->w_height;
+ return lines;
+}
+
+/*
+ * Return number of window lines physical line "lnum" will occupy in window
+ * "wp". Does not care about folding, 'wrap' or 'diff'.
+ */
+ int
+plines_win_nofold(wp, lnum)
+ win_T *wp;
+ linenr_T lnum;
+{
+ char_u *s;
+ long col;
+ int width;
+
+ s = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ if (*s == NUL) /* empty line */
+ return 1;
+ col = win_linetabsize(wp, s, (colnr_T)MAXCOL);
+
+ /*
+ * If list mode is on, then the '$' at the end of the line may take up one
+ * extra column.
+ */
+ if (wp->w_p_list && lcs_eol != NUL)
+ col += 1;
+
+ /*
+ * Add column offset for 'number' and 'foldcolumn'.
+ */
+ width = W_WIDTH(wp) - win_col_off(wp);
+ if (width <= 0)
+ return 32000;
+ if (col <= width)
+ return 1;
+ col -= width;
+ width += win_col_off2(wp);
+ return (col + (width - 1)) / width + 1;
+}
+
+/*
+ * Like plines_win(), but only reports the number of physical screen lines
+ * used from the start of the line to the given column number.
+ */
+ int
+plines_win_col(wp, lnum, column)
+ win_T *wp;
+ linenr_T lnum;
+ long column;
+{
+ long col;
+ char_u *s;
+ int lines = 0;
+ int width;
+
+#ifdef FEAT_DIFF
+ /* Check for filler lines above this buffer line. When folded the result
+ * is one line anyway. */
+ lines = diff_check_fill(wp, lnum);
+#endif
+
+ if (!wp->w_p_wrap)
+ return lines + 1;
+
+#ifdef FEAT_VERTSPLIT
+ if (wp->w_width == 0)
+ return lines + 1;
+#endif
+
+ s = ml_get_buf(wp->w_buffer, lnum, FALSE);
+
+ col = 0;
+ while (*s != NUL && --column >= 0)
+ {
+ col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ s += (*mb_ptr2len_check)(s);
+ else
+#endif
+ ++s;
+ }
+
+ /*
+ * If *s is a TAB, and the TAB is not displayed as ^I, and we're not in
+ * INSERT mode, then col must be adjusted so that it represents the last
+ * screen position of the TAB. This only fixes an error when the TAB wraps
+ * from one screen line to the next (when 'columns' is not a multiple of
+ * 'ts') -- webb.
+ */
+ if (*s == TAB && (State & NORMAL) && (!wp->w_p_list || lcs_tab1))
+ col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL) - 1;
+
+ /*
+ * Add column offset for 'number', 'foldcolumn', etc.
+ */
+ width = W_WIDTH(wp) - win_col_off(wp);
+ if (width > 0)
+ {
+ lines += 1;
+ if (col >= width)
+ lines += (col - width) / (width + win_col_off2(wp));
+ if (lines <= wp->w_height)
+ return lines;
+ }
+ return (int)(wp->w_height); /* maximum length */
+}
+
+ int
+plines_m_win(wp, first, last)
+ win_T *wp;
+ linenr_T first, last;
+{
+ int count = 0;
+
+ while (first <= last)
+ {
+#ifdef FEAT_FOLDING
+ int x;
+
+ /* Check if there are any really folded lines, but also included lines
+ * that are maybe folded. */
+ x = foldedCount(wp, first, NULL);
+ if (x > 0)
+ {
+ ++count; /* count 1 for "+-- folded" line */
+ first += x;
+ }
+ else
+#endif
+ {
+#ifdef FEAT_DIFF
+ if (first == wp->w_topline)
+ count += plines_win_nofill(wp, first, TRUE) + wp->w_topfill;
+ else
+#endif
+ count += plines_win(wp, first, TRUE);
+ ++first;
+ }
+ }
+ return (count);
+}
+
+#if defined(FEAT_VREPLACE) || defined(FEAT_INS_EXPAND) || defined(PROTO)
+/*
+ * Insert string "p" at the cursor position. Stops at a NUL byte.
+ * Handles Replace mode and multi-byte characters.
+ */
+ void
+ins_bytes(p)
+ char_u *p;
+{
+ ins_bytes_len(p, (int)STRLEN(p));
+}
+#endif
+
+#if defined(FEAT_VREPLACE) || defined(FEAT_INS_EXPAND) \
+ || defined(FEAT_COMMENTS) || defined(FEAT_MBYTE) || defined(PROTO)
+/*
+ * Insert string "p" with length "len" at the cursor position.
+ * Handles Replace mode and multi-byte characters.
+ */
+ void
+ins_bytes_len(p, len)
+ char_u *p;
+ int len;
+{
+ int i;
+# ifdef FEAT_MBYTE
+ int n;
+
+ for (i = 0; i < len; i += n)
+ {
+ n = (*mb_ptr2len_check)(p + i);
+ ins_char_bytes(p + i, n);
+ }
+# else
+ for (i = 0; i < len; ++i)
+ ins_char(p[i]);
+# endif
+}
+#endif
+
+/*
+ * Insert or replace a single character at the cursor position.
+ * When in REPLACE or VREPLACE mode, replace any existing character.
+ * Caller must have prepared for undo.
+ * For multi-byte characters we get the whole character, the caller must
+ * convert bytes to a character.
+ */
+ void
+ins_char(c)
+ int c;
+{
+#if defined(FEAT_MBYTE) || defined(PROTO)
+ char_u buf[MB_MAXBYTES];
+ int n;
+
+ n = (*mb_char2bytes)(c, buf);
+
+ /* When "c" is 0x100, 0x200, etc. we don't want to insert a NUL byte.
+ * Happens for CTRL-Vu9900. */
+ if (buf[0] == 0)
+ buf[0] = '\n';
+
+ ins_char_bytes(buf, n);
+}
+
+ void
+ins_char_bytes(buf, charlen)
+ char_u *buf;
+ int charlen;
+{
+ int c = buf[0];
+ int l, j;
+#endif
+ int newlen; /* nr of bytes inserted */
+ int oldlen; /* nr of bytes deleted (0 when not replacing) */
+ char_u *p;
+ char_u *newp;
+ char_u *oldp;
+ int linelen; /* length of old line including NUL */
+ colnr_T col;
+ linenr_T lnum = curwin->w_cursor.lnum;
+ int i;
+
+#ifdef FEAT_VIRTUALEDIT
+ /* Break tabs if needed. */
+ if (virtual_active() && curwin->w_cursor.coladd > 0)
+ coladvance_force(getviscol());
+#endif
+
+ col = curwin->w_cursor.col;
+ oldp = ml_get(lnum);
+ linelen = (int)STRLEN(oldp) + 1;
+
+ /* The lengths default to the values for when not replacing. */
+ oldlen = 0;
+#ifdef FEAT_MBYTE
+ newlen = charlen;
+#else
+ newlen = 1;
+#endif
+
+ if (State & REPLACE_FLAG)
+ {
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ {
+ colnr_T new_vcol = 0; /* init for GCC */
+ colnr_T vcol;
+ int old_list;
+#ifndef FEAT_MBYTE
+ char_u buf[2];
+#endif
+
+ /*
+ * Disable 'list' temporarily, unless 'cpo' contains the 'L' flag.
+ * Returns the old value of list, so when finished,
+ * curwin->w_p_list should be set back to this.
+ */
+ old_list = curwin->w_p_list;
+ if (old_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL)
+ curwin->w_p_list = FALSE;
+
+ /*
+ * In virtual replace mode each character may replace one or more
+ * characters (zero if it's a TAB). Count the number of bytes to
+ * be deleted to make room for the new character, counting screen
+ * cells. May result in adding spaces to fill a gap.
+ */
+ getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL);
+#ifndef FEAT_MBYTE
+ buf[0] = c;
+ buf[1] = NUL;
+#endif
+ new_vcol = vcol + chartabsize(buf, vcol);
+ while (oldp[col + oldlen] != NUL && vcol < new_vcol)
+ {
+ vcol += chartabsize(oldp + col + oldlen, vcol);
+ /* Don't need to remove a TAB that takes us to the right
+ * position. */
+ if (vcol > new_vcol && oldp[col + oldlen] == TAB)
+ break;
+#ifdef FEAT_MBYTE
+ oldlen += (*mb_ptr2len_check)(oldp + col + oldlen);
+#else
+ ++oldlen;
+#endif
+ /* Deleted a bit too much, insert spaces. */
+ if (vcol > new_vcol)
+ newlen += vcol - new_vcol;
+ }
+ curwin->w_p_list = old_list;
+ }
+ else
+#endif
+ if (oldp[col] != NUL)
+ {
+ /* normal replace */
+#ifdef FEAT_MBYTE
+ oldlen = (*mb_ptr2len_check)(oldp + col);
+#else
+ oldlen = 1;
+#endif
+ }
+
+
+ /* Push the replaced bytes onto the replace stack, so that they can be
+ * put back when BS is used. The bytes of a multi-byte character are
+ * done the other way around, so that the first byte is popped off
+ * first (it tells the byte length of the character). */
+ replace_push(NUL);
+ for (i = 0; i < oldlen; ++i)
+ {
+#ifdef FEAT_MBYTE
+ l = (*mb_ptr2len_check)(oldp + col + i) - 1;
+ for (j = l; j >= 0; --j)
+ replace_push(oldp[col + i + j]);
+ i += l;
+#else
+ replace_push(oldp[col + i]);
+#endif
+ }
+ }
+
+ newp = alloc_check((unsigned)(linelen + newlen - oldlen));
+ if (newp == NULL)
+ return;
+
+ /* Copy bytes before the cursor. */
+ if (col > 0)
+ mch_memmove(newp, oldp, (size_t)col);
+
+ /* Copy bytes after the changed character(s). */
+ p = newp + col;
+ mch_memmove(p + newlen, oldp + col + oldlen,
+ (size_t)(linelen - col - oldlen));
+
+ /* Insert or overwrite the new character. */
+#ifdef FEAT_MBYTE
+ mch_memmove(p, buf, charlen);
+ i = charlen;
+#else
+ *p = c;
+ i = 1;
+#endif
+
+ /* Fill with spaces when necessary. */
+ while (i < newlen)
+ p[i++] = ' ';
+
+ /* Replace the line in the buffer. */
+ ml_replace(lnum, newp, FALSE);
+
+ /* mark the buffer as changed and prepare for displaying */
+ changed_bytes(lnum, col);
+
+ /*
+ * If we're in Insert or Replace mode and 'showmatch' is set, then briefly
+ * show the match for right parens and braces.
+ */
+ if (p_sm && (State & INSERT)
+ && msg_silent == 0
+#ifdef FEAT_MBYTE
+ && charlen == 1
+#endif
+ )
+ showmatch(c);
+
+#ifdef FEAT_RIGHTLEFT
+ if (!p_ri || (State & REPLACE_FLAG))
+#endif
+ {
+ /* Normal insert: move cursor right */
+#ifdef FEAT_MBYTE
+ curwin->w_cursor.col += charlen;
+#else
+ ++curwin->w_cursor.col;
+#endif
+ }
+ /*
+ * TODO: should try to update w_row here, to avoid recomputing it later.
+ */
+}
+
+/*
+ * Insert a string at the cursor position.
+ * Note: Does NOT handle Replace mode.
+ * Caller must have prepared for undo.
+ */
+ void
+ins_str(s)
+ char_u *s;
+{
+ char_u *oldp, *newp;
+ int newlen = (int)STRLEN(s);
+ int oldlen;
+ colnr_T col;
+ linenr_T lnum = curwin->w_cursor.lnum;
+
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_active() && curwin->w_cursor.coladd > 0)
+ coladvance_force(getviscol());
+#endif
+
+ col = curwin->w_cursor.col;
+ oldp = ml_get(lnum);
+ oldlen = (int)STRLEN(oldp);
+
+ newp = alloc_check((unsigned)(oldlen + newlen + 1));
+ if (newp == NULL)
+ return;
+ if (col > 0)
+ mch_memmove(newp, oldp, (size_t)col);
+ mch_memmove(newp + col, s, (size_t)newlen);
+ mch_memmove(newp + col + newlen, oldp + col, (size_t)(oldlen - col + 1));
+ ml_replace(lnum, newp, FALSE);
+ changed_bytes(lnum, col);
+ curwin->w_cursor.col += newlen;
+}
+
+/*
+ * Delete one character under the cursor.
+ * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line.
+ * Caller must have prepared for undo.
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+del_char(fixpos)
+ int fixpos;
+{
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ /* Make sure the cursor is at the start of a character. */
+ mb_adjust_cursor();
+ if (*ml_get_cursor() == NUL)
+ return FAIL;
+ return del_chars(1L, fixpos);
+ }
+#endif
+ return del_bytes(1L, fixpos);
+}
+
+#if defined(FEAT_MBYTE) || defined(PROTO)
+/*
+ * Like del_bytes(), but delete characters instead of bytes.
+ */
+ int
+del_chars(count, fixpos)
+ long count;
+ int fixpos;
+{
+ long bytes = 0;
+ long i;
+ char_u *p;
+ int l;
+
+ p = ml_get_cursor();
+ for (i = 0; i < count && *p != NUL; ++i)
+ {
+ l = (*mb_ptr2len_check)(p);
+ bytes += l;
+ p += l;
+ }
+ return del_bytes(bytes, fixpos);
+}
+#endif
+
+/*
+ * Delete "count" bytes under the cursor.
+ * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line.
+ * Caller must have prepared for undo.
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+del_bytes(count, fixpos)
+ long count;
+ int fixpos;
+{
+ char_u *oldp, *newp;
+ colnr_T oldlen;
+ linenr_T lnum = curwin->w_cursor.lnum;
+ colnr_T col = curwin->w_cursor.col;
+ int was_alloced;
+ long movelen;
+
+ oldp = ml_get(lnum);
+ oldlen = (int)STRLEN(oldp);
+
+ /*
+ * Can't do anything when the cursor is on the NUL after the line.
+ */
+ if (col >= oldlen)
+ return FAIL;
+
+#ifdef FEAT_MBYTE
+ /* If 'delcombine' is set and deleting (less than) one character, only
+ * delete the last combining character. */
+ if (p_deco && enc_utf8 && (*mb_ptr2len_check)(oldp + col) <= count)
+ {
+ int c1, c2;
+ int n;
+
+ (void)utfc_ptr2char(oldp + col, &c1, &c2);
+ if (c1 != NUL)
+ {
+ /* Find the last composing char, there can be several. */
+ n = col;
+ do
+ {
+ col = n;
+ count = utf_ptr2len_check(oldp + n);
+ n += count;
+ } while (UTF_COMPOSINGLIKE(oldp + col, oldp + n));
+ fixpos = 0;
+ }
+ }
+#endif
+
+ /*
+ * When count is too big, reduce it.
+ */
+ movelen = (long)oldlen - (long)col - count + 1; /* includes trailing NUL */
+ if (movelen <= 1)
+ {
+ /*
+ * If we just took off the last character of a non-blank line, and
+ * fixpos is TRUE, we don't want to end up positioned at the NUL.
+ */
+ if (col > 0 && fixpos)
+ {
+ --curwin->w_cursor.col;
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ curwin->w_cursor.col -=
+ (*mb_head_off)(oldp, oldp + curwin->w_cursor.col);
+#endif
+ }
+ count = oldlen - col;
+ movelen = 1;
+ }
+
+ /*
+ * If the old line has been allocated the deletion can be done in the
+ * existing line. Otherwise a new line has to be allocated
+ */
+ was_alloced = ml_line_alloced(); /* check if oldp was allocated */
+#ifdef FEAT_NETBEANS_INTG
+ if (was_alloced && usingNetbeans)
+ netbeans_removed(curbuf, lnum, col, count);
+ /* else is handled by ml_replace() */
+#endif
+ if (was_alloced)
+ newp = oldp; /* use same allocated memory */
+ else
+ { /* need to allocate a new line */
+ newp = alloc((unsigned)(oldlen + 1 - count));
+ if (newp == NULL)
+ return FAIL;
+ mch_memmove(newp, oldp, (size_t)col);
+ }
+ mch_memmove(newp + col, oldp + col + count, (size_t)movelen);
+ if (!was_alloced)
+ ml_replace(lnum, newp, FALSE);
+
+ /* mark the buffer as changed and prepare for displaying */
+ changed_bytes(lnum, curwin->w_cursor.col);
+
+ return OK;
+}
+
+/*
+ * Delete from cursor to end of line.
+ * Caller must have prepared for undo.
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+truncate_line(fixpos)
+ int fixpos; /* if TRUE fix the cursor position when done */
+{
+ char_u *newp;
+ linenr_T lnum = curwin->w_cursor.lnum;
+ colnr_T col = curwin->w_cursor.col;
+
+ if (col == 0)
+ newp = vim_strsave((char_u *)"");
+ else
+ newp = vim_strnsave(ml_get(lnum), col);
+
+ if (newp == NULL)
+ return FAIL;
+
+ ml_replace(lnum, newp, FALSE);
+
+ /* mark the buffer as changed and prepare for displaying */
+ changed_bytes(lnum, curwin->w_cursor.col);
+
+ /*
+ * If "fixpos" is TRUE we don't want to end up positioned at the NUL.
+ */
+ if (fixpos && curwin->w_cursor.col > 0)
+ --curwin->w_cursor.col;
+
+ return OK;
+}
+
+/*
+ * Delete "nlines" lines at the cursor.
+ * Saves the lines for undo first if "undo" is TRUE.
+ */
+ void
+del_lines(nlines, undo)
+ long nlines; /* number of lines to delete */
+ int undo; /* if TRUE, prepare for undo */
+{
+ long n;
+
+ if (nlines <= 0)
+ return;
+
+ /* save the deleted lines for undo */
+ if (undo && u_savedel(curwin->w_cursor.lnum, nlines) == FAIL)
+ return;
+
+ for (n = 0; n < nlines; )
+ {
+ if (curbuf->b_ml.ml_flags & ML_EMPTY) /* nothing to delete */
+ break;
+
+ ml_delete(curwin->w_cursor.lnum, TRUE);
+ ++n;
+
+ /* If we delete the last line in the file, stop */
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
+ break;
+ }
+ /* adjust marks, mark the buffer as changed and prepare for displaying */
+ deleted_lines_mark(curwin->w_cursor.lnum, n);
+
+ curwin->w_cursor.col = 0;
+ check_cursor_lnum();
+}
+
+ int
+gchar_pos(pos)
+ pos_T *pos;
+{
+ char_u *ptr = ml_get_pos(pos);
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ return (*mb_ptr2char)(ptr);
+#endif
+ return (int)*ptr;
+}
+
+ int
+gchar_cursor()
+{
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ return (*mb_ptr2char)(ml_get_cursor());
+#endif
+ return (int)*ml_get_cursor();
+}
+
+/*
+ * Write a character at the current cursor position.
+ * It is directly written into the block.
+ */
+ void
+pchar_cursor(c)
+ int c;
+{
+ *(ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE)
+ + curwin->w_cursor.col) = c;
+}
+
+#if 0 /* not used */
+/*
+ * Put *pos at end of current buffer
+ */
+ void
+goto_endofbuf(pos)
+ pos_T *pos;
+{
+ char_u *p;
+
+ pos->lnum = curbuf->b_ml.ml_line_count;
+ pos->col = 0;
+ p = ml_get(pos->lnum);
+ while (*p++)
+ ++pos->col;
+}
+#endif
+
+/*
+ * When extra == 0: Return TRUE if the cursor is before or on the first
+ * non-blank in the line.
+ * When extra == 1: Return TRUE if the cursor is before the first non-blank in
+ * the line.
+ */
+ int
+inindent(extra)
+ int extra;
+{
+ char_u *ptr;
+ colnr_T col;
+
+ for (col = 0, ptr = ml_get_curline(); vim_iswhite(*ptr); ++col)
+ ++ptr;
+ if (col >= curwin->w_cursor.col + extra)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*
+ * Skip to next part of an option argument: Skip space and comma.
+ */
+ char_u *
+skip_to_option_part(p)
+ char_u *p;
+{
+ if (*p == ',')
+ ++p;
+ while (*p == ' ')
+ ++p;
+ return p;
+}
+
+/*
+ * changed() is called when something in the current buffer is changed.
+ *
+ * Most often called through changed_bytes() and changed_lines(), which also
+ * mark the area of the display to be redrawn.
+ */
+ void
+changed()
+{
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+ /* The text of the preediting area is inserted, but this doesn't
+ * mean a change of the buffer yet. That is delayed until the
+ * text is committed. (this means preedit becomes empty) */
+ if (im_is_preediting() && !xim_changed_while_preediting)
+ return;
+ xim_changed_while_preediting = FALSE;
+#endif
+
+ if (!curbuf->b_changed)
+ {
+ int save_msg_scroll = msg_scroll;
+
+ change_warning(0);
+ /* Create a swap file if that is wanted.
+ * Don't do this for "nofile" and "nowrite" buffer types. */
+ if (curbuf->b_may_swap
+#ifdef FEAT_QUICKFIX
+ && !bt_dontwrite(curbuf)
+#endif
+ )
+ {
+ ml_open_file(curbuf);
+
+ /* The ml_open_file() can cause an ATTENTION message.
+ * Wait two seconds, to make sure the user reads this unexpected
+ * message. Since we could be anywhere, call wait_return() now,
+ * and don't let the emsg() set msg_scroll. */
+ if (need_wait_return && emsg_silent == 0)
+ {
+ out_flush();
+ ui_delay(2000L, TRUE);
+ wait_return(TRUE);
+ msg_scroll = save_msg_scroll;
+ }
+ }
+ curbuf->b_changed = TRUE;
+ ml_setdirty(curbuf, TRUE);
+#ifdef FEAT_WINDOWS
+ check_status(curbuf);
+#endif
+#ifdef FEAT_TITLE
+ need_maketitle = TRUE; /* set window title later */
+#endif
+ }
+ ++curbuf->b_changedtick;
+ ++global_changedtick;
+}
+
+static void changedOneline __ARGS((linenr_T lnum));
+static void changed_common __ARGS((linenr_T lnum, colnr_T col, linenr_T lnume, long xtra));
+
+/*
+ * Changed bytes within a single line for the current buffer.
+ * - marks the windows on this buffer to be redisplayed
+ * - marks the buffer changed by calling changed()
+ * - invalidates cached values
+ */
+ void
+changed_bytes(lnum, col)
+ linenr_T lnum;
+ colnr_T col;
+{
+ changedOneline(lnum);
+ changed_common(lnum, col, lnum + 1, 0L);
+}
+
+ static void
+changedOneline(lnum)
+ linenr_T lnum;
+{
+ if (curbuf->b_mod_set)
+ {
+ /* find the maximum area that must be redisplayed */
+ if (lnum < curbuf->b_mod_top)
+ curbuf->b_mod_top = lnum;
+ else if (lnum >= curbuf->b_mod_bot)
+ curbuf->b_mod_bot = lnum + 1;
+ }
+ else
+ {
+ /* set the area that must be redisplayed to one line */
+ curbuf->b_mod_set = TRUE;
+ curbuf->b_mod_top = lnum;
+ curbuf->b_mod_bot = lnum + 1;
+ curbuf->b_mod_xlines = 0;
+ }
+}
+
+/*
+ * Appended "count" lines below line "lnum" in the current buffer.
+ * Must be called AFTER the change and after mark_adjust().
+ * Takes care of marking the buffer to be redrawn and sets the changed flag.
+ */
+ void
+appended_lines(lnum, count)
+ linenr_T lnum;
+ long count;
+{
+ changed_lines(lnum + 1, 0, lnum + 1, count);
+}
+
+/*
+ * Like appended_lines(), but adjust marks first.
+ */
+ void
+appended_lines_mark(lnum, count)
+ linenr_T lnum;
+ long count;
+{
+ mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L);
+ changed_lines(lnum + 1, 0, lnum + 1, count);
+}
+
+/*
+ * Deleted "count" lines at line "lnum" in the current buffer.
+ * Must be called AFTER the change and after mark_adjust().
+ * Takes care of marking the buffer to be redrawn and sets the changed flag.
+ */
+ void
+deleted_lines(lnum, count)
+ linenr_T lnum;
+ long count;
+{
+ changed_lines(lnum, 0, lnum + count, -count);
+}
+
+/*
+ * Like deleted_lines(), but adjust marks first.
+ */
+ void
+deleted_lines_mark(lnum, count)
+ linenr_T lnum;
+ long count;
+{
+ mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM, -count);
+ changed_lines(lnum, 0, lnum + count, -count);
+}
+
+/*
+ * Changed lines for the current buffer.
+ * Must be called AFTER the change and after mark_adjust().
+ * - mark the buffer changed by calling changed()
+ * - mark the windows on this buffer to be redisplayed
+ * - invalidate cached values
+ * "lnum" is the first line that needs displaying, "lnume" the first line
+ * below the changed lines (BEFORE the change).
+ * When only inserting lines, "lnum" and "lnume" are equal.
+ * Takes care of calling changed() and updating b_mod_*.
+ */
+ void
+changed_lines(lnum, col, lnume, xtra)
+ linenr_T lnum; /* first line with change */
+ colnr_T col; /* column in first line with change */
+ linenr_T lnume; /* line below last changed line */
+ long xtra; /* number of extra lines (negative when deleting) */
+{
+ if (curbuf->b_mod_set)
+ {
+ /* find the maximum area that must be redisplayed */
+ if (lnum < curbuf->b_mod_top)
+ curbuf->b_mod_top = lnum;
+ if (lnum < curbuf->b_mod_bot)
+ {
+ /* adjust old bot position for xtra lines */
+ curbuf->b_mod_bot += xtra;
+ if (curbuf->b_mod_bot < lnum)
+ curbuf->b_mod_bot = lnum;
+ }
+ if (lnume + xtra > curbuf->b_mod_bot)
+ curbuf->b_mod_bot = lnume + xtra;
+ curbuf->b_mod_xlines += xtra;
+ }
+ else
+ {
+ /* set the area that must be redisplayed */
+ curbuf->b_mod_set = TRUE;
+ curbuf->b_mod_top = lnum;
+ curbuf->b_mod_bot = lnume + xtra;
+ curbuf->b_mod_xlines = xtra;
+ }
+
+ changed_common(lnum, col, lnume, xtra);
+}
+
+ static void
+changed_common(lnum, col, lnume, xtra)
+ linenr_T lnum;
+ colnr_T col;
+ linenr_T lnume;
+ long xtra;
+{
+ win_T *wp;
+ int i;
+#ifdef FEAT_JUMPLIST
+ int cols;
+ pos_T *p;
+ int add;
+#endif
+
+ /* mark the buffer as modified */
+ changed();
+
+ /* set the '. mark */
+ if (!cmdmod.keepjumps)
+ {
+ curbuf->b_last_change.lnum = lnum;
+ curbuf->b_last_change.col = col;
+
+#ifdef FEAT_JUMPLIST
+ /* Create a new entry if a new undo-able change was started or we
+ * don't have an entry yet. */
+ if (curbuf->b_new_change || curbuf->b_changelistlen == 0)
+ {
+ if (curbuf->b_changelistlen == 0)
+ add = TRUE;
+ else
+ {
+ /* Don't create a new entry when the line number is the same
+ * as the last one and the column is not too far away. Avoids
+ * creating many entries for typing "xxxxx". */
+ p = &curbuf->b_changelist[curbuf->b_changelistlen - 1];
+ if (p->lnum != lnum)
+ add = TRUE;
+ else
+ {
+ cols = comp_textwidth(FALSE);
+ if (cols == 0)
+ cols = 79;
+ add = (p->col + cols < col || col + cols < p->col);
+ }
+ }
+ if (add)
+ {
+ /* This is the first of a new sequence of undo-able changes
+ * and it's at some distance of the last change. Use a new
+ * position in the changelist. */
+ curbuf->b_new_change = FALSE;
+
+ if (curbuf->b_changelistlen == JUMPLISTSIZE)
+ {
+ /* changelist is full: remove oldest entry */
+ curbuf->b_changelistlen = JUMPLISTSIZE - 1;
+ mch_memmove(curbuf->b_changelist, curbuf->b_changelist + 1,
+ sizeof(pos_T) * (JUMPLISTSIZE - 1));
+ FOR_ALL_WINDOWS(wp)
+ {
+ /* Correct position in changelist for other windows on
+ * this buffer. */
+ if (wp->w_buffer == curbuf && wp->w_changelistidx > 0)
+ --wp->w_changelistidx;
+ }
+ }
+ FOR_ALL_WINDOWS(wp)
+ {
+ /* For other windows, if the position in the changelist is
+ * at the end it stays at the end. */
+ if (wp->w_buffer == curbuf
+ && wp->w_changelistidx == curbuf->b_changelistlen)
+ ++wp->w_changelistidx;
+ }
+ ++curbuf->b_changelistlen;
+ }
+ }
+ curbuf->b_changelist[curbuf->b_changelistlen - 1] =
+ curbuf->b_last_change;
+ /* The current window is always after the last change, so that "g,"
+ * takes you back to it. */
+ curwin->w_changelistidx = curbuf->b_changelistlen;
+#endif
+ }
+
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_buffer == curbuf)
+ {
+ /* Mark this window to be redrawn later. */
+ if (wp->w_redr_type < VALID)
+ wp->w_redr_type = VALID;
+
+ /* Check if a change in the buffer has invalidated the cached
+ * values for the cursor. */
+#ifdef FEAT_FOLDING
+ /*
+ * Update the folds for this window. Can't postpone this, because
+ * a following operator might work on the whole fold: ">>dd".
+ */
+ foldUpdate(wp, lnum, lnume + xtra - 1);
+
+ /* The change may cause lines above or below the change to become
+ * included in a fold. Set lnum/lnume to the first/last line that
+ * might be displayed differently.
+ * Set w_cline_folded here as an efficient way to update it when
+ * inserting lines just above a closed fold. */
+ i = hasFoldingWin(wp, lnum, &lnum, NULL, FALSE, NULL);
+ if (wp->w_cursor.lnum == lnum)
+ wp->w_cline_folded = i;
+ i = hasFoldingWin(wp, lnume, NULL, &lnume, FALSE, NULL);
+ if (wp->w_cursor.lnum == lnume)
+ wp->w_cline_folded = i;
+
+ /* If the changed line is in a range of previously folded lines,
+ * compare with the first line in that range. */
+ if (wp->w_cursor.lnum <= lnum)
+ {
+ i = find_wl_entry(wp, lnum);
+ if (i >= 0 && wp->w_cursor.lnum > wp->w_lines[i].wl_lnum)
+ changed_line_abv_curs_win(wp);
+ }
+#endif
+
+ if (wp->w_cursor.lnum > lnum)
+ changed_line_abv_curs_win(wp);
+ else if (wp->w_cursor.lnum == lnum && wp->w_cursor.col >= col)
+ changed_cline_bef_curs_win(wp);
+ if (wp->w_botline >= lnum)
+ {
+ /* Assume that botline doesn't change (inserted lines make
+ * other lines scroll down below botline). */
+ approximate_botline_win(wp);
+ }
+
+ /* Check if any w_lines[] entries have become invalid.
+ * For entries below the change: Correct the lnums for
+ * inserted/deleted lines. Makes it possible to stop displaying
+ * after the change. */
+ for (i = 0; i < wp->w_lines_valid; ++i)
+ if (wp->w_lines[i].wl_valid)
+ {
+ if (wp->w_lines[i].wl_lnum >= lnum)
+ {
+ if (wp->w_lines[i].wl_lnum < lnume)
+ {
+ /* line included in change */
+ wp->w_lines[i].wl_valid = FALSE;
+ }
+ else if (xtra != 0)
+ {
+ /* line below change */
+ wp->w_lines[i].wl_lnum += xtra;
+#ifdef FEAT_FOLDING
+ wp->w_lines[i].wl_lastlnum += xtra;
+#endif
+ }
+ }
+#ifdef FEAT_FOLDING
+ else if (wp->w_lines[i].wl_lastlnum >= lnum)
+ {
+ /* change somewhere inside this range of folded lines,
+ * may need to be redrawn */
+ wp->w_lines[i].wl_valid = FALSE;
+ }
+#endif
+ }
+ }
+ }
+
+ /* Call update_screen() later, which checks out what needs to be redrawn,
+ * since it notices b_mod_set and then uses b_mod_*. */
+ if (must_redraw < VALID)
+ must_redraw = VALID;
+}
+
+/*
+ * unchanged() is called when the changed flag must be reset for buffer 'buf'
+ */
+ void
+unchanged(buf, ff)
+ buf_T *buf;
+ int ff; /* also reset 'fileformat' */
+{
+ if (buf->b_changed || (ff && file_ff_differs(buf)))
+ {
+ buf->b_changed = 0;
+ ml_setdirty(buf, FALSE);
+ if (ff)
+ save_file_ff(buf);
+#ifdef FEAT_WINDOWS
+ check_status(buf);
+#endif
+#ifdef FEAT_TITLE
+ need_maketitle = TRUE; /* set window title later */
+#endif
+ }
+ ++buf->b_changedtick;
+ ++global_changedtick;
+#ifdef FEAT_NETBEANS_INTG
+ netbeans_unmodified(buf);
+#endif
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * check_status: called when the status bars for the buffer 'buf'
+ * need to be updated
+ */
+ void
+check_status(buf)
+ buf_T *buf;
+{
+ win_T *wp;
+
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_buffer == buf && wp->w_status_height)
+ {
+ wp->w_redr_status = TRUE;
+ if (must_redraw < VALID)
+ must_redraw = VALID;
+ }
+}
+#endif
+
+/*
+ * If the file is readonly, give a warning message with the first change.
+ * Don't do this for autocommands.
+ * Don't use emsg(), because it flushes the macro buffer.
+ * If we have undone all changes b_changed will be FALSE, but b_did_warn
+ * will be TRUE.
+ */
+ void
+change_warning(col)
+ int col; /* column for message; non-zero when in insert
+ mode and 'showmode' is on */
+{
+ if (curbuf->b_did_warn == FALSE
+ && curbufIsChanged() == 0
+#ifdef FEAT_AUTOCMD
+ && !autocmd_busy
+#endif
+ && curbuf->b_p_ro)
+ {
+#ifdef FEAT_AUTOCMD
+ apply_autocmds(EVENT_FILECHANGEDRO, NULL, NULL, FALSE, curbuf);
+ if (!curbuf->b_p_ro)
+ return;
+#endif
+ /*
+ * Do what msg() does, but with a column offset if the warning should
+ * be after the mode message.
+ */
+ msg_start();
+ if (msg_row == Rows - 1)
+ msg_col = col;
+ MSG_PUTS_ATTR(_("W10: Warning: Changing a readonly file"),
+ hl_attr(HLF_W) | MSG_HIST);
+ msg_clr_eos();
+ (void)msg_end();
+ if (msg_silent == 0 && !silent_mode)
+ {
+ out_flush();
+ ui_delay(1000L, TRUE); /* give the user time to think about it */
+ }
+ curbuf->b_did_warn = TRUE;
+ redraw_cmdline = FALSE; /* don't redraw and erase the message */
+ if (msg_row < Rows - 1)
+ showmode();
+ }
+}
+
+/*
+ * Ask for a reply from the user, a 'y' or a 'n'.
+ * No other characters are accepted, the message is repeated until a valid
+ * reply is entered or CTRL-C is hit.
+ * If direct is TRUE, don't use vgetc() but ui_inchar(), don't get characters
+ * from any buffers but directly from the user.
+ *
+ * return the 'y' or 'n'
+ */
+ int
+ask_yesno(str, direct)
+ char_u *str;
+ int direct;
+{
+ int r = ' ';
+ int save_State = State;
+
+ if (exiting) /* put terminal in raw mode for this question */
+ settmode(TMODE_RAW);
+ ++no_wait_return;
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = TRUE; /* disallow scrolling here */
+#endif
+ State = CONFIRM; /* mouse behaves like with :confirm */
+#ifdef FEAT_MOUSE
+ setmouse(); /* disables mouse for xterm */
+#endif
+ ++no_mapping;
+ ++allow_keys; /* no mapping here, but recognize keys */
+
+ while (r != 'y' && r != 'n')
+ {
+ /* same highlighting as for wait_return */
+ smsg_attr(hl_attr(HLF_R), (char_u *)"%s (y/n)?", str);
+ if (direct)
+ r = get_keystroke();
+ else
+ r = safe_vgetc();
+ if (r == Ctrl_C || r == ESC)
+ r = 'n';
+ msg_putchar(r); /* show what you typed */
+ out_flush();
+ }
+ --no_wait_return;
+ State = save_State;
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+ --no_mapping;
+ --allow_keys;
+
+ return r;
+}
+
+/*
+ * Get a key stroke directly from the user.
+ * Ignores mouse clicks and scrollbar events, except a click for the left
+ * button (used at the more prompt).
+ * Doesn't use vgetc(), because it syncs undo and eats mapped characters.
+ * Disadvantage: typeahead is ignored.
+ * Translates the interrupt character for unix to ESC.
+ */
+ int
+get_keystroke()
+{
+#define CBUFLEN 151
+ char_u buf[CBUFLEN];
+ int len = 0;
+ int n;
+ int save_mapped_ctrl_c = mapped_ctrl_c;
+
+ mapped_ctrl_c = FALSE; /* mappings are not used here */
+ for (;;)
+ {
+ cursor_on();
+ out_flush();
+
+ /* First time: blocking wait. Second time: wait up to 100ms for a
+ * terminal code to complete. Leave some room for check_termcode() to
+ * insert a key code into (max 5 chars plus NUL). And
+ * fix_input_buffer() can triple the number of bytes. */
+ n = ui_inchar(buf + len, (CBUFLEN - 6 - len) / 3,
+ len == 0 ? -1L : 100L, 0);
+ if (n > 0)
+ {
+ /* Replace zero and CSI by a special key code. */
+ n = fix_input_buffer(buf + len, n, FALSE);
+ len += n;
+ }
+
+ /* incomplete termcode: get more characters */
+ if ((n = check_termcode(1, buf, len)) < 0)
+ continue;
+ /* found a termcode: adjust length */
+ if (n > 0)
+ len = n;
+ if (len == 0) /* nothing typed yet */
+ continue;
+
+ /* Handle modifier and/or special key code. */
+ n = buf[0];
+ if (n == K_SPECIAL)
+ {
+ n = TO_SPECIAL(buf[1], buf[2]);
+ if (buf[1] == KS_MODIFIER
+ || n == K_IGNORE
+#ifdef FEAT_MOUSE
+ || n == K_LEFTMOUSE_NM
+ || n == K_LEFTDRAG
+ || n == K_LEFTRELEASE
+ || n == K_LEFTRELEASE_NM
+ || n == K_MIDDLEMOUSE
+ || n == K_MIDDLEDRAG
+ || n == K_MIDDLERELEASE
+ || n == K_RIGHTMOUSE
+ || n == K_RIGHTDRAG
+ || n == K_RIGHTRELEASE
+ || n == K_MOUSEDOWN
+ || n == K_MOUSEUP
+ || n == K_X1MOUSE
+ || n == K_X1DRAG
+ || n == K_X1RELEASE
+ || n == K_X2MOUSE
+ || n == K_X2DRAG
+ || n == K_X2RELEASE
+# ifdef FEAT_GUI
+ || n == K_VER_SCROLLBAR
+ || n == K_HOR_SCROLLBAR
+# endif
+#endif
+ )
+ {
+ if (buf[1] == KS_MODIFIER)
+ mod_mask = buf[2];
+ len -= 3;
+ if (len > 0)
+ mch_memmove(buf, buf + 3, (size_t)len);
+ continue;
+ }
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ if (MB_BYTE2LEN(n) > len)
+ continue; /* more bytes to get */
+ buf[len >= CBUFLEN ? CBUFLEN - 1 : len] = NUL;
+ n = (*mb_ptr2char)(buf);
+ }
+#endif
+#ifdef UNIX
+ if (n == intr_char)
+ n = ESC;
+#endif
+ break;
+ }
+
+ mapped_ctrl_c = save_mapped_ctrl_c;
+ return n;
+}
+
+/*
+ * get a number from the user
+ */
+ int
+get_number(colon)
+ int colon; /* allow colon to abort */
+{
+ int n = 0;
+ int c;
+
+ /* When not printing messages, the user won't know what to type, return a
+ * zero (as if CR was hit). */
+ if (msg_silent != 0)
+ return 0;
+
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = TRUE; /* disallow scrolling here */
+#endif
+ ++no_mapping;
+ ++allow_keys; /* no mapping here, but recognize keys */
+ for (;;)
+ {
+ windgoto(msg_row, msg_col);
+ c = safe_vgetc();
+ if (VIM_ISDIGIT(c))
+ {
+ n = n * 10 + c - '0';
+ msg_putchar(c);
+ }
+ else if (c == K_DEL || c == K_KDEL || c == K_BS || c == Ctrl_H)
+ {
+ n /= 10;
+ MSG_PUTS("\b \b");
+ }
+ else if (n == 0 && c == ':' && colon)
+ {
+ stuffcharReadbuff(':');
+ if (!exmode_active)
+ cmdline_row = msg_row;
+ skip_redraw = TRUE; /* skip redraw once */
+ do_redraw = FALSE;
+ break;
+ }
+ else if (c == CAR || c == NL || c == Ctrl_C || c == ESC)
+ break;
+ }
+ --no_mapping;
+ --allow_keys;
+ return n;
+}
+
+ void
+msgmore(n)
+ long n;
+{
+ long pn;
+
+ if (global_busy /* no messages now, wait until global is finished */
+ || keep_msg != NULL /* there is a message already, skip this one */
+ || !messaging()) /* 'lazyredraw' set, don't do messages now */
+ return;
+
+ if (n > 0)
+ pn = n;
+ else
+ pn = -n;
+
+ if (pn > p_report)
+ {
+ if (pn == 1)
+ {
+ if (n > 0)
+ STRCPY(msg_buf, _("1 more line"));
+ else
+ STRCPY(msg_buf, _("1 line less"));
+ }
+ else
+ {
+ if (n > 0)
+ sprintf((char *)msg_buf, _("%ld more lines"), pn);
+ else
+ sprintf((char *)msg_buf, _("%ld fewer lines"), pn);
+ }
+ if (got_int)
+ STRCAT(msg_buf, _(" (Interrupted)"));
+ if (msg(msg_buf))
+ {
+ set_keep_msg(msg_buf);
+ keep_msg_attr = 0;
+ }
+ }
+}
+
+/*
+ * flush map and typeahead buffers and give a warning for an error
+ */
+ void
+beep_flush()
+{
+ if (emsg_silent == 0)
+ {
+ flush_buffers(FALSE);
+ vim_beep();
+ }
+}
+
+/*
+ * give a warning for an error
+ */
+ void
+vim_beep()
+{
+ if (emsg_silent == 0)
+ {
+ if (p_vb
+#ifdef FEAT_GUI
+ /* While the GUI is starting up the termcap is set for the GUI
+ * but the output still goes to a terminal. */
+ && !(gui.in_use && gui.starting)
+#endif
+ )
+ {
+ out_str(T_VB);
+ }
+ else
+ {
+#ifdef MSDOS
+ /*
+ * The number of beeps outputted is reduced to avoid having to wait
+ * for all the beeps to finish. This is only a problem on systems
+ * where the beeps don't overlap.
+ */
+ if (beep_count == 0 || beep_count == 10)
+ {
+ out_char(BELL);
+ beep_count = 1;
+ }
+ else
+ ++beep_count;
+#else
+ out_char(BELL);
+#endif
+ }
+ }
+}
+
+/*
+ * To get the "real" home directory:
+ * - get value of $HOME
+ * For Unix:
+ * - go to that directory
+ * - do mch_dirname() to get the real name of that directory.
+ * This also works with mounts and links.
+ * Don't do this for MS-DOS, it will change the "current dir" for a drive.
+ */
+static char_u *homedir = NULL;
+
+ void
+init_homedir()
+{
+ char_u *var;
+
+#ifdef VMS
+ var = mch_getenv((char_u *)"SYS$LOGIN");
+#else
+ var = mch_getenv((char_u *)"HOME");
+#endif
+
+ if (var != NULL && *var == NUL) /* empty is same as not set */
+ var = NULL;
+
+#ifdef WIN3264
+ /*
+ * Weird but true: $HOME may contain an indirect reference to another
+ * variable, esp. "%USERPROFILE%". Happens when $USERPROFILE isn't set
+ * when $HOME is being set.
+ */
+ if (var != NULL && *var == '%')
+ {
+ char_u *p;
+ char_u *exp;
+
+ p = vim_strchr(var + 1, '%');
+ if (p != NULL)
+ {
+ STRNCPY(NameBuff, var + 1, p - (var + 1));
+ NameBuff[p - (var + 1)] = NUL;
+ exp = mch_getenv(NameBuff);
+ if (exp != NULL && *exp != NUL
+ && STRLEN(exp) + STRLEN(p) < MAXPATHL)
+ {
+ sprintf((char *)NameBuff, "%s%s", exp, p + 1);
+ var = NameBuff;
+ /* Also set $HOME, it's needed for _viminfo. */
+ vim_setenv((char_u *)"HOME", NameBuff);
+ }
+ }
+ }
+
+ /*
+ * Typically, $HOME is not defined on Windows, unless the user has
+ * specifically defined it for Vim's sake. However, on Windows NT
+ * platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for
+ * each user. Try constructing $HOME from these.
+ */
+ if (var == NULL)
+ {
+ char_u *homedrive, *homepath;
+
+ homedrive = mch_getenv((char_u *)"HOMEDRIVE");
+ homepath = mch_getenv((char_u *)"HOMEPATH");
+ if (homedrive != NULL && homepath != NULL
+ && STRLEN(homedrive) + STRLEN(homepath) < MAXPATHL)
+ {
+ sprintf((char *)NameBuff, "%s%s", homedrive, homepath);
+ if (NameBuff[0] != NUL)
+ {
+ var = NameBuff;
+ /* Also set $HOME, it's needed for _viminfo. */
+ vim_setenv((char_u *)"HOME", NameBuff);
+ }
+ }
+ }
+#endif
+
+#if defined(OS2) || defined(MSDOS) || defined(MSWIN)
+ /*
+ * Default home dir is C:/
+ * Best assumption we can make in such a situation.
+ */
+ if (var == NULL)
+ var = "C:/";
+#endif
+ if (var != NULL)
+ {
+#ifdef UNIX
+ /*
+ * Change to the directory and get the actual path. This resolves
+ * links. Don't do it when we can't return.
+ */
+ if (mch_dirname(NameBuff, MAXPATHL) == OK
+ && mch_chdir((char *)NameBuff) == 0)
+ {
+ if (!mch_chdir((char *)var) && mch_dirname(IObuff, IOSIZE) == OK)
+ var = IObuff;
+ if (mch_chdir((char *)NameBuff) != 0)
+ EMSG(_(e_prev_dir));
+ }
+#endif
+ homedir = vim_strsave(var);
+ }
+}
+
+/*
+ * Expand environment variable with path name.
+ * "~/" is also expanded, using $HOME. For Unix "~user/" is expanded.
+ * Skips over "\ ", "\~" and "\$".
+ * If anything fails no expansion is done and dst equals src.
+ */
+ void
+expand_env(src, dst, dstlen)
+ char_u *src; /* input string e.g. "$HOME/vim.hlp" */
+ char_u *dst; /* where to put the result */
+ int dstlen; /* maximum length of the result */
+{
+ expand_env_esc(src, dst, dstlen, FALSE);
+}
+
+ void
+expand_env_esc(src, dst, dstlen, esc)
+ char_u *src; /* input string e.g. "$HOME/vim.hlp" */
+ char_u *dst; /* where to put the result */
+ int dstlen; /* maximum length of the result */
+ int esc; /* escape spaces in expanded variables */
+{
+ char_u *tail;
+ int c;
+ char_u *var;
+ int copy_char;
+ int mustfree; /* var was allocated, need to free it later */
+ int at_start = TRUE; /* at start of a name */
+
+ src = skipwhite(src);
+ --dstlen; /* leave one char space for "\," */
+ while (*src && dstlen > 0)
+ {
+ copy_char = TRUE;
+ if (*src == '$'
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
+ || *src == '%'
+#endif
+ || (*src == '~' && at_start))
+ {
+ mustfree = FALSE;
+
+ /*
+ * The variable name is copied into dst temporarily, because it may
+ * be a string in read-only memory and a NUL needs to be appended.
+ */
+ if (*src != '~') /* environment var */
+ {
+ tail = src + 1;
+ var = dst;
+ c = dstlen - 1;
+
+#ifdef UNIX
+ /* Unix has ${var-name} type environment vars */
+ if (*tail == '{' && !vim_isIDc('{'))
+ {
+ tail++; /* ignore '{' */
+ while (c-- > 0 && *tail && *tail != '}')
+ *var++ = *tail++;
+ }
+ else
+#endif
+ {
+ while (c-- > 0 && *tail != NUL && ((vim_isIDc(*tail))
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
+ || (*src == '%' && *tail != '%')
+#endif
+ ))
+ {
+#ifdef OS2 /* env vars only in uppercase */
+ *var++ = TOUPPER_LOC(*tail);
+ tail++; /* toupper() may be a macro! */
+#else
+ *var++ = *tail++;
+#endif
+ }
+ }
+
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2) || defined(UNIX)
+# ifdef UNIX
+ if (src[1] == '{' && *tail != '}')
+# else
+ if (*src == '%' && *tail != '%')
+# endif
+ var = NULL;
+ else
+ {
+# ifdef UNIX
+ if (src[1] == '{')
+# else
+ if (*src == '%')
+#endif
+ ++tail;
+#endif
+ *var = NUL;
+ var = vim_getenv(dst, &mustfree);
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2) || defined(UNIX)
+ }
+#endif
+ }
+ /* home directory */
+ else if ( src[1] == NUL
+ || vim_ispathsep(src[1])
+ || vim_strchr((char_u *)" ,\t\n", src[1]) != NULL)
+ {
+ var = homedir;
+ tail = src + 1;
+ }
+ else /* user directory */
+ {
+#if defined(UNIX) || (defined(VMS) && defined(USER_HOME))
+ /*
+ * Copy ~user to dst[], so we can put a NUL after it.
+ */
+ tail = src;
+ var = dst;
+ c = dstlen - 1;
+ while ( c-- > 0
+ && *tail
+ && vim_isfilec(*tail)
+ && !vim_ispathsep(*tail))
+ *var++ = *tail++;
+ *var = NUL;
+# ifdef UNIX
+ /*
+ * If the system supports getpwnam(), use it.
+ * Otherwise, or if getpwnam() fails, the shell is used to
+ * expand ~user. This is slower and may fail if the shell
+ * does not support ~user (old versions of /bin/sh).
+ */
+# if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H)
+ {
+ struct passwd *pw;
+
+ pw = getpwnam((char *)dst + 1);
+ if (pw != NULL)
+ var = (char_u *)pw->pw_dir;
+ else
+ var = NULL;
+ }
+ if (var == NULL)
+# endif
+ {
+ expand_T xpc;
+
+ ExpandInit(&xpc);
+ xpc.xp_context = EXPAND_FILES;
+ var = ExpandOne(&xpc, dst, NULL,
+ WILD_ADD_SLASH|WILD_SILENT, WILD_EXPAND_FREE);
+ ExpandCleanup(&xpc);
+ mustfree = TRUE;
+ }
+
+# else /* !UNIX, thus VMS */
+ /*
+ * USER_HOME is a comma-separated list of
+ * directories to search for the user account in.
+ */
+ {
+ char_u test[MAXPATHL], paths[MAXPATHL];
+ char_u *path, *next_path, *ptr;
+ struct stat st;
+
+ STRCPY(paths, USER_HOME);
+ next_path = paths;
+ while (*next_path)
+ {
+ for (path = next_path; *next_path && *next_path != ',';
+ next_path++);
+ if (*next_path)
+ *next_path++ = NUL;
+ STRCPY(test, path);
+ STRCAT(test, "/");
+ STRCAT(test, dst + 1);
+ if (mch_stat(test, &st) == 0)
+ {
+ var = alloc(STRLEN(test) + 1);
+ STRCPY(var, test);
+ mustfree = TRUE;
+ break;
+ }
+ }
+ }
+# endif /* UNIX */
+#else
+ /* cannot expand user's home directory, so don't try */
+ var = NULL;
+ tail = (char_u *)""; /* for gcc */
+#endif /* UNIX || VMS */
+ }
+
+#ifdef BACKSLASH_IN_FILENAME
+ /* If 'shellslash' is set change backslashes to forward slashes.
+ * Can't use slash_adjust(), p_ssl may be set temporarily. */
+ if (p_ssl && var != NULL && vim_strchr(var, '\\') != NULL)
+ {
+ char_u *p = vim_strsave(var);
+
+ if (p != NULL)
+ {
+ if (mustfree)
+ vim_free(var);
+ var = p;
+ mustfree = TRUE;
+ forward_slash(var);
+ }
+ }
+#endif
+
+ /* If "var" contains white space, escape it with a backslash.
+ * Required for ":e ~/tt" when $HOME includes a space. */
+ if (esc && var != NULL && vim_strpbrk(var, (char_u *)" \t") != NULL)
+ {
+ char_u *p = vim_strsave_escaped(var, (char_u *)" \t");
+
+ if (p != NULL)
+ {
+ if (mustfree)
+ vim_free(var);
+ var = p;
+ mustfree = TRUE;
+ }
+ }
+
+ if (var != NULL && *var != NUL
+ && (STRLEN(var) + STRLEN(tail) + 1 < (unsigned)dstlen))
+ {
+ STRCPY(dst, var);
+ dstlen -= (int)STRLEN(var);
+ dst += STRLEN(var);
+ /* if var[] ends in a path separator and tail[] starts
+ * with it, skip a character */
+ if (*var != NUL && vim_ispathsep(dst[-1])
+#if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA)
+ && dst[-1] != ':'
+#endif
+ && vim_ispathsep(*tail))
+ ++tail;
+ src = tail;
+ copy_char = FALSE;
+ }
+ if (mustfree)
+ vim_free(var);
+ }
+
+ if (copy_char) /* copy at least one char */
+ {
+ /*
+ * Recogize the start of a new name, for '~'.
+ */
+ at_start = FALSE;
+ if (src[0] == '\\' && src[1] != NUL)
+ {
+ *dst++ = *src++;
+ --dstlen;
+ }
+ else if (src[0] == ' ' || src[0] == ',')
+ at_start = TRUE;
+ *dst++ = *src++;
+ --dstlen;
+ }
+ }
+ *dst = NUL;
+}
+
+/*
+ * Vim's version of getenv().
+ * Special handling of $HOME, $VIM and $VIMRUNTIME.
+ */
+ char_u *
+vim_getenv(name, mustfree)
+ char_u *name;
+ int *mustfree; /* set to TRUE when returned is allocated */
+{
+ char_u *p;
+ char_u *pend;
+ int vimruntime;
+
+#if defined(OS2) || defined(MSDOS) || defined(MSWIN)
+ /* use "C:/" when $HOME is not set */
+ if (STRCMP(name, "HOME") == 0)
+ return homedir;
+#endif
+
+ p = mch_getenv(name);
+ if (p != NULL && *p == NUL) /* empty is the same as not set */
+ p = NULL;
+
+ if (p != NULL)
+ return p;
+
+ vimruntime = (STRCMP(name, "VIMRUNTIME") == 0);
+ if (!vimruntime && STRCMP(name, "VIM") != 0)
+ return NULL;
+
+ /*
+ * When expanding $VIMRUNTIME fails, try using $VIM/vim<version> or $VIM.
+ * Don't do this when default_vimruntime_dir is non-empty.
+ */
+ if (vimruntime
+#ifdef HAVE_PATHDEF
+ && *default_vimruntime_dir == NUL
+#endif
+ )
+ {
+ p = mch_getenv((char_u *)"VIM");
+ if (p != NULL && *p == NUL) /* empty is the same as not set */
+ p = NULL;
+ if (p != NULL)
+ {
+ p = vim_version_dir(p);
+ if (p != NULL)
+ *mustfree = TRUE;
+ else
+ p = mch_getenv((char_u *)"VIM");
+ }
+ }
+
+ /*
+ * When expanding $VIM or $VIMRUNTIME fails, try using:
+ * - the directory name from 'helpfile' (unless it contains '$')
+ * - the executable name from argv[0]
+ */
+ if (p == NULL)
+ {
+ if (p_hf != NULL && vim_strchr(p_hf, '$') == NULL)
+ p = p_hf;
+#ifdef USE_EXE_NAME
+ /*
+ * Use the name of the executable, obtained from argv[0].
+ */
+ else
+ p = exe_name;
+#endif
+ if (p != NULL)
+ {
+ /* remove the file name */
+ pend = gettail(p);
+
+ /* remove "doc/" from 'helpfile', if present */
+ if (p == p_hf)
+ pend = remove_tail(p, pend, (char_u *)"doc");
+
+#ifdef USE_EXE_NAME
+# ifdef MACOS_X
+ /* remove "build/..." from exe_name, if present */
+ if (p == exe_name)
+ {
+ char_u *pend1;
+ char_u *pend2;
+
+ pend1 = remove_tail(p, pend, (char_u *)"Contents/MacOS");
+ pend2 = remove_tail_with_ext(p, pend1, (char_u *)".app");
+ pend = remove_tail(p, pend2, (char_u *)"build");
+ /* When runnig from project builder get rid of the
+ * build/???.app, otherwise keep the ???.app */
+ if (pend2 == pend)
+ pend = pend1;
+ }
+# endif
+ /* remove "src/" from exe_name, if present */
+ if (p == exe_name)
+ pend = remove_tail(p, pend, (char_u *)"src");
+#endif
+
+ /* for $VIM, remove "runtime/" or "vim54/", if present */
+ if (!vimruntime)
+ {
+ pend = remove_tail(p, pend, (char_u *)RUNTIME_DIRNAME);
+ pend = remove_tail(p, pend, (char_u *)VIM_VERSION_NODOT);
+ }
+
+ /* remove trailing path separator */
+#ifndef MACOS_CLASSIC
+ /* With MacOS path (with colons) the final colon is required */
+ /* to avoid confusion between absoulute and relative path */
+ if (pend > p && vim_ispathsep(*(pend - 1)))
+ --pend;
+#endif
+
+ /* check that the result is a directory name */
+ p = vim_strnsave(p, (int)(pend - p));
+
+ if (p != NULL && !mch_isdir(p))
+ {
+ vim_free(p);
+ p = NULL;
+ }
+ else
+ {
+#ifdef USE_EXE_NAME
+ /* may add "/vim54" or "/runtime" if it exists */
+ if (vimruntime && (pend = vim_version_dir(p)) != NULL)
+ {
+ vim_free(p);
+ p = pend;
+ }
+#endif
+ *mustfree = TRUE;
+ }
+ }
+ }
+
+#ifdef HAVE_PATHDEF
+ /* When there is a pathdef.c file we can use default_vim_dir and
+ * default_vimruntime_dir */
+ if (p == NULL)
+ {
+ /* Only use default_vimruntime_dir when it is not empty */
+ if (vimruntime && *default_vimruntime_dir != NUL)
+ {
+ p = default_vimruntime_dir;
+ *mustfree = FALSE;
+ }
+ else if (*default_vim_dir != NUL)
+ {
+ if (vimruntime && (p = vim_version_dir(default_vim_dir)) != NULL)
+ *mustfree = TRUE;
+ else
+ {
+ p = default_vim_dir;
+ *mustfree = FALSE;
+ }
+ }
+ }
+#endif
+
+ /*
+ * Set the environment variable, so that the new value can be found fast
+ * next time, and others can also use it (e.g. Perl).
+ */
+ if (p != NULL)
+ {
+ if (vimruntime)
+ {
+ vim_setenv((char_u *)"VIMRUNTIME", p);
+ didset_vimruntime = TRUE;
+#ifdef FEAT_GETTEXT
+ {
+ char_u *buf = alloc((unsigned int)STRLEN(p) + 6);
+
+ if (buf != NULL)
+ {
+ STRCPY(buf, p);
+ STRCAT(buf, "/lang");
+ bindtextdomain(VIMPACKAGE, (char *)buf);
+ vim_free(buf);
+ }
+ }
+#endif
+ }
+ else
+ {
+ vim_setenv((char_u *)"VIM", p);
+ didset_vim = TRUE;
+ }
+ }
+ return p;
+}
+
+/*
+ * Check if the directory "vimdir/<version>" or "vimdir/runtime" exists.
+ * Return NULL if not, return its name in allocated memory otherwise.
+ */
+ static char_u *
+vim_version_dir(vimdir)
+ char_u *vimdir;
+{
+ char_u *p;
+
+ if (vimdir == NULL || *vimdir == NUL)
+ return NULL;
+ p = concat_fnames(vimdir, (char_u *)VIM_VERSION_NODOT, TRUE);
+ if (p != NULL && mch_isdir(p))
+ return p;
+ vim_free(p);
+ p = concat_fnames(vimdir, (char_u *)RUNTIME_DIRNAME, TRUE);
+ if (p != NULL && mch_isdir(p))
+ return p;
+ vim_free(p);
+ return NULL;
+}
+
+/*
+ * If the string between "p" and "pend" ends in "name/", return "pend" minus
+ * the length of "name/". Otherwise return "pend".
+ */
+ static char_u *
+remove_tail(p, pend, name)
+ char_u *p;
+ char_u *pend;
+ char_u *name;
+{
+ int len = (int)STRLEN(name) + 1;
+ char_u *newend = pend - len;
+
+ if (newend >= p
+ && fnamencmp(newend, name, len - 1) == 0
+ && (newend == p || vim_ispathsep(*(newend - 1))))
+ return newend;
+ return pend;
+}
+
+#if defined(USE_EXE_NAME) && defined(MACOS_X)
+/*
+ * If the string between "p" and "pend" ends in "???.ext/", return "pend"
+ * minus the length of "???.ext/". Otherwise return "pend".
+ */
+ static char_u *
+remove_tail_with_ext(p, pend, ext)
+ char_u *p;
+ char_u *pend;
+ char_u *ext;
+{
+ int len = (int)STRLEN(ext) + 1;
+ char_u *newend = pend - len;
+
+ if (newend >= p && fnamencmp(newend, ext, len - 1) == 0)
+ while (newend != p && !vim_ispathsep(*(newend - 1)))
+ --newend;
+ if (newend == p || vim_ispathsep(*(newend - 1)))
+ return newend;
+ return pend;
+}
+#endif
+
+/*
+ * Call expand_env() and store the result in an allocated string.
+ * This is not very memory efficient, this expects the result to be freed
+ * again soon.
+ */
+ char_u *
+expand_env_save(src)
+ char_u *src;
+{
+ char_u *p;
+
+ p = alloc(MAXPATHL);
+ if (p != NULL)
+ expand_env(src, p, MAXPATHL);
+ return p;
+}
+
+/*
+ * Our portable version of setenv.
+ */
+ void
+vim_setenv(name, val)
+ char_u *name;
+ char_u *val;
+{
+#ifdef HAVE_SETENV
+ mch_setenv((char *)name, (char *)val, 1);
+#else
+ char_u *envbuf;
+
+ /*
+ * Putenv does not copy the string, it has to remain
+ * valid. The allocated memory will never be freed.
+ */
+ envbuf = alloc((unsigned)(STRLEN(name) + STRLEN(val) + 2));
+ if (envbuf != NULL)
+ {
+ sprintf((char *)envbuf, "%s=%s", name, val);
+ putenv((char *)envbuf);
+ }
+#endif
+}
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+/*
+ * Function given to ExpandGeneric() to obtain an environment variable name.
+ */
+/*ARGSUSED*/
+ char_u *
+get_env_name(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+# if defined(AMIGA) || defined(__MRC__) || defined(__SC__)
+ /*
+ * No environ[] on the Amiga and on the Mac (using MPW).
+ */
+ return NULL;
+# else
+# ifndef __WIN32__
+ /* Borland C++ 5.2 has this in a header file. */
+ extern char **environ;
+# endif
+ static char_u name[100];
+ char_u *str;
+ int n;
+
+ str = (char_u *)environ[idx];
+ if (str == NULL)
+ return NULL;
+
+ for (n = 0; n < 99; ++n)
+ {
+ if (str[n] == '=' || str[n] == NUL)
+ break;
+ name[n] = str[n];
+ }
+ name[n] = NUL;
+ return name;
+# endif
+}
+#endif
+
+/*
+ * Replace home directory by "~" in each space or comma separated file name in
+ * 'src'.
+ * If anything fails (except when out of space) dst equals src.
+ */
+ void
+home_replace(buf, src, dst, dstlen, one)
+ buf_T *buf; /* when not NULL, check for help files */
+ char_u *src; /* input file name */
+ char_u *dst; /* where to put the result */
+ int dstlen; /* maximum length of the result */
+ int one; /* if TRUE, only replace one file name, include
+ spaces and commas in the file name. */
+{
+ size_t dirlen = 0, envlen = 0;
+ size_t len;
+ char_u *homedir_env;
+ char_u *p;
+
+ if (src == NULL)
+ {
+ *dst = NUL;
+ return;
+ }
+
+ /*
+ * If the file is a help file, remove the path completely.
+ */
+ if (buf != NULL && buf->b_help)
+ {
+ STRCPY(dst, gettail(src));
+ return;
+ }
+
+ /*
+ * We check both the value of the $HOME environment variable and the
+ * "real" home directory.
+ */
+ if (homedir != NULL)
+ dirlen = STRLEN(homedir);
+
+#ifdef VMS
+ homedir_env = mch_getenv((char_u *)"SYS$LOGIN");
+#else
+ homedir_env = mch_getenv((char_u *)"HOME");
+#endif
+
+ if (homedir_env != NULL && *homedir_env == NUL)
+ homedir_env = NULL;
+ if (homedir_env != NULL)
+ envlen = STRLEN(homedir_env);
+
+ if (!one)
+ src = skipwhite(src);
+ while (*src && dstlen > 0)
+ {
+ /*
+ * Here we are at the beginning of a file name.
+ * First, check to see if the beginning of the file name matches
+ * $HOME or the "real" home directory. Check that there is a '/'
+ * after the match (so that if e.g. the file is "/home/pieter/bla",
+ * and the home directory is "/home/piet", the file does not end up
+ * as "~er/bla" (which would seem to indicate the file "bla" in user
+ * er's home directory)).
+ */
+ p = homedir;
+ len = dirlen;
+ for (;;)
+ {
+ if ( len
+ && fnamencmp(src, p, len) == 0
+ && (vim_ispathsep(src[len])
+ || (!one && (src[len] == ',' || src[len] == ' '))
+ || src[len] == NUL))
+ {
+ src += len;
+ if (--dstlen > 0)
+ *dst++ = '~';
+
+ /*
+ * If it's just the home directory, add "/".
+ */
+ if (!vim_ispathsep(src[0]) && --dstlen > 0)
+ *dst++ = '/';
+ break;
+ }
+ if (p == homedir_env)
+ break;
+ p = homedir_env;
+ len = envlen;
+ }
+
+ /* if (!one) skip to separator: space or comma */
+ while (*src && (one || (*src != ',' && *src != ' ')) && --dstlen > 0)
+ *dst++ = *src++;
+ /* skip separator */
+ while ((*src == ' ' || *src == ',') && --dstlen > 0)
+ *dst++ = *src++;
+ }
+ /* if (dstlen == 0) out of space, what to do??? */
+
+ *dst = NUL;
+}
+
+/*
+ * Like home_replace, store the replaced string in allocated memory.
+ * When something fails, NULL is returned.
+ */
+ char_u *
+home_replace_save(buf, src)
+ buf_T *buf; /* when not NULL, check for help files */
+ char_u *src; /* input file name */
+{
+ char_u *dst;
+ unsigned len;
+
+ len = 3; /* space for "~/" and trailing NUL */
+ if (src != NULL) /* just in case */
+ len += (unsigned)STRLEN(src);
+ dst = alloc(len);
+ if (dst != NULL)
+ home_replace(buf, src, dst, len, TRUE);
+ return dst;
+}
+
+/*
+ * Compare two file names and return:
+ * FPC_SAME if they both exist and are the same file.
+ * FPC_SAMEX if they both don't exist and have the same file name.
+ * FPC_DIFF if they both exist and are different files.
+ * FPC_NOTX if they both don't exist.
+ * FPC_DIFFX if one of them doesn't exist.
+ * For the first name environment variables are expanded
+ */
+ int
+fullpathcmp(s1, s2, checkname)
+ char_u *s1, *s2;
+ int checkname; /* when both don't exist, check file names */
+{
+#ifdef UNIX
+ char_u exp1[MAXPATHL];
+ char_u full1[MAXPATHL];
+ char_u full2[MAXPATHL];
+ struct stat st1, st2;
+ int r1, r2;
+
+ expand_env(s1, exp1, MAXPATHL);
+ r1 = mch_stat((char *)exp1, &st1);
+ r2 = mch_stat((char *)s2, &st2);
+ if (r1 != 0 && r2 != 0)
+ {
+ /* if mch_stat() doesn't work, may compare the names */
+ if (checkname)
+ {
+ if (fnamecmp(exp1, s2) == 0)
+ return FPC_SAMEX;
+ r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE);
+ r2 = vim_FullName(s2, full2, MAXPATHL, FALSE);
+ if (r1 == OK && r2 == OK && fnamecmp(full1, full2) == 0)
+ return FPC_SAMEX;
+ }
+ return FPC_NOTX;
+ }
+ if (r1 != 0 || r2 != 0)
+ return FPC_DIFFX;
+ if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
+ return FPC_SAME;
+ return FPC_DIFF;
+#else
+ char_u *exp1; /* expanded s1 */
+ char_u *full1; /* full path of s1 */
+ char_u *full2; /* full path of s2 */
+ int retval = FPC_DIFF;
+ int r1, r2;
+
+ /* allocate one buffer to store three paths (alloc()/free() is slow!) */
+ if ((exp1 = alloc(MAXPATHL * 3)) != NULL)
+ {
+ full1 = exp1 + MAXPATHL;
+ full2 = full1 + MAXPATHL;
+
+ expand_env(s1, exp1, MAXPATHL);
+ r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE);
+ r2 = vim_FullName(s2, full2, MAXPATHL, FALSE);
+
+ /* If vim_FullName() fails, the file probably doesn't exist. */
+ if (r1 != OK && r2 != OK)
+ {
+ if (checkname && fnamecmp(exp1, s2) == 0)
+ retval = FPC_SAMEX;
+ else
+ retval = FPC_NOTX;
+ }
+ else if (r1 != OK || r2 != OK)
+ retval = FPC_DIFFX;
+ else if (fnamecmp(full1, full2))
+ retval = FPC_DIFF;
+ else
+ retval = FPC_SAME;
+ vim_free(exp1);
+ }
+ return retval;
+#endif
+}
+
+/*
+ * get the tail of a path: the file name.
+ */
+ char_u *
+gettail(fname)
+ char_u *fname;
+{
+ char_u *p1, *p2;
+
+ if (fname == NULL)
+ return (char_u *)"";
+ for (p1 = p2 = fname; *p2; ) /* find last part of path */
+ {
+ if (vim_ispathsep(*p2))
+ p1 = p2 + 1;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p2 += (*mb_ptr2len_check)(p2);
+ else
+#endif
+ ++p2;
+ }
+ return p1;
+}
+
+/*
+ * get the next path component (just after the next path separator).
+ */
+ char_u *
+getnextcomp(fname)
+ char_u *fname;
+{
+ while (*fname && !vim_ispathsep(*fname))
+ ++fname;
+ if (*fname)
+ ++fname;
+ return fname;
+}
+
+#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \
+ || defined(FEAT_SESSION) || defined(MSWIN) \
+ || (defined(FEAT_GUI_GTK) \
+ && (defined(FEAT_WINDOWS) || defined(FEAT_DND))) \
+ || defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \
+ || defined(PROTO)
+/*
+ * Get a pointer to one character past the head of a path name.
+ * Unix: after "/"; DOS: after "c:\"; Amiga: after "disk:/"; Mac: no head.
+ * If there is no head, path is returned.
+ */
+ char_u *
+get_past_head(path)
+ char_u *path;
+{
+ char_u *retval;
+
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
+ /* may skip "c:" */
+ if (isalpha(path[0]) && path[1] == ':')
+ retval = path + 2;
+ else
+ retval = path;
+#else
+# if defined(AMIGA)
+ /* may skip "label:" */
+ retval = vim_strchr(path, ':');
+ if (retval == NULL)
+ retval = path;
+# else /* Unix */
+ retval = path;
+# endif
+#endif
+
+ while (vim_ispathsep(*retval))
+ ++retval;
+
+ return retval;
+}
+#endif
+
+/*
+ * return TRUE if 'c' is a path separator.
+ */
+ int
+vim_ispathsep(c)
+ int c;
+{
+#ifdef RISCOS
+ return (c == '.' || c == ':');
+#else
+# ifdef UNIX
+ return (c == '/'); /* UNIX has ':' inside file names */
+# else
+# ifdef BACKSLASH_IN_FILENAME
+ return (c == ':' || c == '/' || c == '\\');
+# else
+# ifdef VMS
+ /* server"user passwd"::device:[full.path.name]fname.extension;version" */
+ return (c == ':' || c == '[' || c == ']' || c == '/'
+ || c == '<' || c == '>' || c == '"' );
+# else
+# ifdef COLON_AS_PATHSEP
+ return (c == ':');
+# else /* Amiga */
+ return (c == ':' || c == '/');
+# endif
+# endif /* VMS */
+# endif
+# endif
+#endif /* RISC OS */
+}
+
+#if defined(FEAT_SEARCHPATH) || defined(PROTO)
+/*
+ * return TRUE if 'c' is a path list separator.
+ */
+ int
+vim_ispathlistsep(c)
+ int c;
+{
+#ifdef UNIX
+ return (c == ':');
+#else
+ return (c == ';'); /* might not be rigth for every system... */
+#endif
+}
+#endif
+
+#if (defined(CASE_INSENSITIVE_FILENAME) && defined(BACKSLASH_IN_FILENAME)) \
+ || defined(PROTO)
+/*
+ * Versions of fnamecmp() and fnamencmp() that handle '/' and '\' equally.
+ */
+ int
+vim_fnamecmp(x, y)
+ char_u *x, *y;
+{
+ return vim_fnamencmp(x, y, MAXPATHL);
+}
+
+ int
+vim_fnamencmp(x, y, len)
+ char_u *x, *y;
+ size_t len;
+{
+ while (len > 0 && *x && *y)
+ {
+ if (TOLOWER_LOC(*x) != TOLOWER_LOC(*y)
+ && !(*x == '/' && *y == '\\')
+ && !(*x == '\\' && *y == '/'))
+ break;
+ ++x;
+ ++y;
+ --len;
+ }
+ if (len == 0)
+ return 0;
+ return (*x - *y);
+}
+#endif
+
+/*
+ * Concatenate file names fname1 and fname2 into allocated memory.
+ * Only add a '/' or '\\' when 'sep' is TRUE and it is neccesary.
+ */
+ char_u *
+concat_fnames(fname1, fname2, sep)
+ char_u *fname1;
+ char_u *fname2;
+ int sep;
+{
+ char_u *dest;
+
+ dest = alloc((unsigned)(STRLEN(fname1) + STRLEN(fname2) + 3));
+ if (dest != NULL)
+ {
+ STRCPY(dest, fname1);
+ if (sep)
+ add_pathsep(dest);
+ STRCAT(dest, fname2);
+ }
+ return dest;
+}
+
+/*
+ * Add a path separator to a file name, unless it already ends in a path
+ * separator.
+ */
+ void
+add_pathsep(p)
+ char_u *p;
+{
+ if (*p != NUL && !vim_ispathsep(*(p + STRLEN(p) - 1)))
+ STRCAT(p, PATHSEPSTR);
+}
+
+/*
+ * FullName_save - Make an allocated copy of a full file name.
+ * Returns NULL when out of memory.
+ */
+ char_u *
+FullName_save(fname, force)
+ char_u *fname;
+ int force; /* force expansion, even when it already looks
+ like a full path name */
+{
+ char_u *buf;
+ char_u *new_fname = NULL;
+
+ if (fname == NULL)
+ return NULL;
+
+ buf = alloc((unsigned)MAXPATHL);
+ if (buf != NULL)
+ {
+ if (vim_FullName(fname, buf, MAXPATHL, force) != FAIL)
+ new_fname = vim_strsave(buf);
+ else
+ new_fname = vim_strsave(fname);
+ vim_free(buf);
+ }
+ return new_fname;
+}
+
+#if defined(FEAT_CINDENT) || defined(FEAT_SYN_HL)
+
+static char_u *skip_string __ARGS((char_u *p));
+
+/*
+ * Find the start of a comment, not knowing if we are in a comment right now.
+ * Search starts at w_cursor.lnum and goes backwards.
+ */
+ pos_T *
+find_start_comment(ind_maxcomment) /* XXX */
+ int ind_maxcomment;
+{
+ pos_T *pos;
+ char_u *line;
+ char_u *p;
+
+ if ((pos = findmatchlimit(NULL, '*', FM_BACKWARD, ind_maxcomment)) == NULL)
+ return NULL;
+
+ /*
+ * Check if the comment start we found is inside a string.
+ */
+ line = ml_get(pos->lnum);
+ for (p = line; *p && (unsigned)(p - line) < pos->col; ++p)
+ p = skip_string(p);
+ if ((unsigned)(p - line) > pos->col)
+ return NULL;
+ return pos;
+}
+
+/*
+ * Skip to the end of a "string" and a 'c' character.
+ * If there is no string or character, return argument unmodified.
+ */
+ static char_u *
+skip_string(p)
+ char_u *p;
+{
+ int i;
+
+ /*
+ * We loop, because strings may be concatenated: "date""time".
+ */
+ for ( ; ; ++p)
+ {
+ if (p[0] == '\'') /* 'c' or '\n' or '\000' */
+ {
+ if (!p[1]) /* ' at end of line */
+ break;
+ i = 2;
+ if (p[1] == '\\') /* '\n' or '\000' */
+ {
+ ++i;
+ while (vim_isdigit(p[i - 1])) /* '\000' */
+ ++i;
+ }
+ if (p[i] == '\'') /* check for trailing ' */
+ {
+ p += i;
+ continue;
+ }
+ }
+ else if (p[0] == '"') /* start of string */
+ {
+ for (++p; p[0]; ++p)
+ {
+ if (p[0] == '\\' && p[1] != NUL)
+ ++p;
+ else if (p[0] == '"') /* end of string */
+ break;
+ }
+ if (p[0] == '"')
+ continue;
+ }
+ break; /* no string found */
+ }
+ if (!*p)
+ --p; /* backup from NUL */
+ return p;
+}
+#endif /* FEAT_CINDENT || FEAT_SYN_HL */
+
+#if defined(FEAT_CINDENT) || defined(PROTO)
+
+/*
+ * Do C or expression indenting on the current line.
+ */
+ void
+do_c_expr_indent()
+{
+# ifdef FEAT_EVAL
+ if (*curbuf->b_p_inde != NUL)
+ fixthisline(get_expr_indent);
+ else
+# endif
+ fixthisline(get_c_indent);
+}
+
+/*
+ * Functions for C-indenting.
+ * Most of this originally comes from Eric Fischer.
+ */
+/*
+ * Below "XXX" means that this function may unlock the current line.
+ */
+
+static char_u *cin_skipcomment __ARGS((char_u *));
+static int cin_nocode __ARGS((char_u *));
+static pos_T *find_line_comment __ARGS((void));
+static int cin_islabel_skip __ARGS((char_u **));
+static int cin_isdefault __ARGS((char_u *));
+static char_u *after_label __ARGS((char_u *l));
+static int get_indent_nolabel __ARGS((linenr_T lnum));
+static int skip_label __ARGS((linenr_T, char_u **pp, int ind_maxcomment));
+static int cin_first_id_amount __ARGS((void));
+static int cin_get_equal_amount __ARGS((linenr_T lnum));
+static int cin_ispreproc __ARGS((char_u *));
+static int cin_ispreproc_cont __ARGS((char_u **pp, linenr_T *lnump));
+static int cin_iscomment __ARGS((char_u *));
+static int cin_islinecomment __ARGS((char_u *));
+static int cin_isterminated __ARGS((char_u *, int, int));
+static int cin_isinit __ARGS((void));
+static int cin_isfuncdecl __ARGS((char_u **, linenr_T));
+static int cin_isif __ARGS((char_u *));
+static int cin_iselse __ARGS((char_u *));
+static int cin_isdo __ARGS((char_u *));
+static int cin_iswhileofdo __ARGS((char_u *, linenr_T, int));
+static int cin_isbreak __ARGS((char_u *));
+static int cin_is_cpp_baseclass __ARGS((char_u *line, colnr_T *col));
+static int cin_ends_in __ARGS((char_u *, char_u *, char_u *));
+static int cin_skip2pos __ARGS((pos_T *trypos));
+static pos_T *find_start_brace __ARGS((int));
+static pos_T *find_match_paren __ARGS((int, int));
+static int corr_ind_maxparen __ARGS((int ind_maxparen, pos_T *startpos));
+static int find_last_paren __ARGS((char_u *l, int start, int end));
+static int find_match __ARGS((int lookfor, linenr_T ourscope, int ind_maxparen, int ind_maxcomment));
+
+/*
+ * Skip over white space and C comments within the line.
+ */
+ static char_u *
+cin_skipcomment(s)
+ char_u *s;
+{
+ while (*s)
+ {
+ s = skipwhite(s);
+ if (*s != '/')
+ break;
+ ++s;
+ if (*s == '/') /* slash-slash comment continues till eol */
+ {
+ s += STRLEN(s);
+ break;
+ }
+ if (*s != '*')
+ break;
+ for (++s; *s; ++s) /* skip slash-star comment */
+ if (s[0] == '*' && s[1] == '/')
+ {
+ s += 2;
+ break;
+ }
+ }
+ return s;
+}
+
+/*
+ * Return TRUE if there there is no code at *s. White space and comments are
+ * not considered code.
+ */
+ static int
+cin_nocode(s)
+ char_u *s;
+{
+ return *cin_skipcomment(s) == NUL;
+}
+
+/*
+ * Check previous lines for a "//" line comment, skipping over blank lines.
+ */
+ static pos_T *
+find_line_comment() /* XXX */
+{
+ static pos_T pos;
+ char_u *line;
+ char_u *p;
+
+ pos = curwin->w_cursor;
+ while (--pos.lnum > 0)
+ {
+ line = ml_get(pos.lnum);
+ p = skipwhite(line);
+ if (cin_islinecomment(p))
+ {
+ pos.col = (int)(p - line);
+ return &pos;
+ }
+ if (*p != NUL)
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * Check if string matches "label:"; move to character after ':' if true.
+ */
+ static int
+cin_islabel_skip(s)
+ char_u **s;
+{
+ if (!vim_isIDc(**s)) /* need at least one ID character */
+ return FALSE;
+
+ while (vim_isIDc(**s))
+ (*s)++;
+
+ *s = cin_skipcomment(*s);
+
+ /* "::" is not a label, it's C++ */
+ return (**s == ':' && *++*s != ':');
+}
+
+/*
+ * Recognize a label: "label:".
+ * Note: curwin->w_cursor must be where we are looking for the label.
+ */
+ int
+cin_islabel(ind_maxcomment) /* XXX */
+ int ind_maxcomment;
+{
+ char_u *s;
+
+ s = cin_skipcomment(ml_get_curline());
+
+ /*
+ * Exclude "default" from labels, since it should be indented
+ * like a switch label. Same for C++ scope declarations.
+ */
+ if (cin_isdefault(s))
+ return FALSE;
+ if (cin_isscopedecl(s))
+ return FALSE;
+
+ if (cin_islabel_skip(&s))
+ {
+ /*
+ * Only accept a label if the previous line is terminated or is a case
+ * label.
+ */
+ pos_T cursor_save;
+ pos_T *trypos;
+ char_u *line;
+
+ cursor_save = curwin->w_cursor;
+ while (curwin->w_cursor.lnum > 1)
+ {
+ --curwin->w_cursor.lnum;
+
+ /*
+ * If we're in a comment now, skip to the start of the comment.
+ */
+ curwin->w_cursor.col = 0;
+ if ((trypos = find_start_comment(ind_maxcomment)) != NULL) /* XXX */
+ curwin->w_cursor = *trypos;
+
+ line = ml_get_curline();
+ if (cin_ispreproc(line)) /* ignore #defines, #if, etc. */
+ continue;
+ if (*(line = cin_skipcomment(line)) == NUL)
+ continue;
+
+ curwin->w_cursor = cursor_save;
+ if (cin_isterminated(line, TRUE, FALSE)
+ || cin_isscopedecl(line)
+ || cin_iscase(line)
+ || (cin_islabel_skip(&line) && cin_nocode(line)))
+ return TRUE;
+ return FALSE;
+ }
+ curwin->w_cursor = cursor_save;
+ return TRUE; /* label at start of file??? */
+ }
+ return FALSE;
+}
+
+/*
+ * Recognize structure initialization and enumerations.
+ * Q&D-Implementation:
+ * check for "=" at end or "[typedef] enum" at beginning of line.
+ */
+ static int
+cin_isinit(void)
+{
+ char_u *s;
+
+ s = cin_skipcomment(ml_get_curline());
+
+ if (STRNCMP(s, "typedef", 7) == 0 && !vim_isIDc(s[7]))
+ s = cin_skipcomment(s + 7);
+
+ if (STRNCMP(s, "enum", 4) == 0 && !vim_isIDc(s[4]))
+ return TRUE;
+
+ if (cin_ends_in(s, (char_u *)"=", (char_u *)"{"))
+ return TRUE;
+
+ return FALSE;
+}
+
+/*
+ * Recognize a switch label: "case .*:" or "default:".
+ */
+ int
+cin_iscase(s)
+ char_u *s;
+{
+ s = cin_skipcomment(s);
+ if (STRNCMP(s, "case", 4) == 0 && !vim_isIDc(s[4]))
+ {
+ for (s += 4; *s; ++s)
+ {
+ s = cin_skipcomment(s);
+ if (*s == ':')
+ {
+ if (s[1] == ':') /* skip over "::" for C++ */
+ ++s;
+ else
+ return TRUE;
+ }
+ if (*s == '\'' && s[1] && s[2] == '\'')
+ s += 2; /* skip over '.' */
+ else if (*s == '/' && (s[1] == '*' || s[1] == '/'))
+ return FALSE; /* stop at comment */
+ else if (*s == '"')
+ return FALSE; /* stop at string */
+ }
+ return FALSE;
+ }
+
+ if (cin_isdefault(s))
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Recognize a "default" switch label.
+ */
+ static int
+cin_isdefault(s)
+ char_u *s;
+{
+ return (STRNCMP(s, "default", 7) == 0
+ && *(s = cin_skipcomment(s + 7)) == ':'
+ && s[1] != ':');
+}
+
+/*
+ * Recognize a "public/private/proctected" scope declaration label.
+ */
+ int
+cin_isscopedecl(s)
+ char_u *s;
+{
+ int i;
+
+ s = cin_skipcomment(s);
+ if (STRNCMP(s, "public", 6) == 0)
+ i = 6;
+ else if (STRNCMP(s, "protected", 9) == 0)
+ i = 9;
+ else if (STRNCMP(s, "private", 7) == 0)
+ i = 7;
+ else
+ return FALSE;
+ return (*(s = cin_skipcomment(s + i)) == ':' && s[1] != ':');
+}
+
+/*
+ * Return a pointer to the first non-empty non-comment character after a ':'.
+ * Return NULL if not found.
+ * case 234: a = b;
+ * ^
+ */
+ static char_u *
+after_label(l)
+ char_u *l;
+{
+ for ( ; *l; ++l)
+ {
+ if (*l == ':')
+ {
+ if (l[1] == ':') /* skip over "::" for C++ */
+ ++l;
+ else if (!cin_iscase(l + 1))
+ break;
+ }
+ else if (*l == '\'' && l[1] && l[2] == '\'')
+ l += 2; /* skip over 'x' */
+ }
+ if (*l == NUL)
+ return NULL;
+ l = cin_skipcomment(l + 1);
+ if (*l == NUL)
+ return NULL;
+ return l;
+}
+
+/*
+ * Get indent of line "lnum", skipping a label.
+ * Return 0 if there is nothing after the label.
+ */
+ static int
+get_indent_nolabel(lnum) /* XXX */
+ linenr_T lnum;
+{
+ char_u *l;
+ pos_T fp;
+ colnr_T col;
+ char_u *p;
+
+ l = ml_get(lnum);
+ p = after_label(l);
+ if (p == NULL)
+ return 0;
+
+ fp.col = (colnr_T)(p - l);
+ fp.lnum = lnum;
+ getvcol(curwin, &fp, &col, NULL, NULL);
+ return (int)col;
+}
+
+/*
+ * Find indent for line "lnum", ignoring any case or jump label.
+ * Also return a pointer to the text (after the label).
+ * label: if (asdf && asdfasdf)
+ * ^
+ */
+ static int
+skip_label(lnum, pp, ind_maxcomment)
+ linenr_T lnum;
+ char_u **pp;
+ int ind_maxcomment;
+{
+ char_u *l;
+ int amount;
+ pos_T cursor_save;
+
+ cursor_save = curwin->w_cursor;
+ curwin->w_cursor.lnum = lnum;
+ l = ml_get_curline();
+ /* XXX */
+ if (cin_iscase(l) || cin_isscopedecl(l) || cin_islabel(ind_maxcomment))
+ {
+ amount = get_indent_nolabel(lnum);
+ l = after_label(ml_get_curline());
+ if (l == NULL) /* just in case */
+ l = ml_get_curline();
+ }
+ else
+ {
+ amount = get_indent();
+ l = ml_get_curline();
+ }
+ *pp = l;
+
+ curwin->w_cursor = cursor_save;
+ return amount;
+}
+
+/*
+ * Return the indent of the first variable name after a type in a declaration.
+ * int a, indent of "a"
+ * static struct foo b, indent of "b"
+ * enum bla c, indent of "c"
+ * Returns zero when it doesn't look like a declaration.
+ */
+ static int
+cin_first_id_amount()
+{
+ char_u *line, *p, *s;
+ int len;
+ pos_T fp;
+ colnr_T col;
+
+ line = ml_get_curline();
+ p = skipwhite(line);
+ len = skiptowhite(p) - p;
+ if (len == 6 && STRNCMP(p, "static", 6) == 0)
+ {
+ p = skipwhite(p + 6);
+ len = skiptowhite(p) - p;
+ }
+ if (len == 6 && STRNCMP(p, "struct", 6) == 0)
+ p = skipwhite(p + 6);
+ else if (len == 4 && STRNCMP(p, "enum", 4) == 0)
+ p = skipwhite(p + 4);
+ else if ((len == 8 && STRNCMP(p, "unsigned", 8) == 0)
+ || (len == 6 && STRNCMP(p, "signed", 6) == 0))
+ {
+ s = skipwhite(p + len);
+ if ((STRNCMP(s, "int", 3) == 0 && vim_iswhite(s[3]))
+ || (STRNCMP(s, "long", 4) == 0 && vim_iswhite(s[4]))
+ || (STRNCMP(s, "short", 5) == 0 && vim_iswhite(s[5]))
+ || (STRNCMP(s, "char", 4) == 0 && vim_iswhite(s[4])))
+ p = s;
+ }
+ for (len = 0; vim_isIDc(p[len]); ++len)
+ ;
+ if (len == 0 || !vim_iswhite(p[len]) || cin_nocode(p))
+ return 0;
+
+ p = skipwhite(p + len);
+ fp.lnum = curwin->w_cursor.lnum;
+ fp.col = (colnr_T)(p - line);
+ getvcol(curwin, &fp, &col, NULL, NULL);
+ return (int)col;
+}
+
+/*
+ * Return the indent of the first non-blank after an equal sign.
+ * char *foo = "here";
+ * Return zero if no (useful) equal sign found.
+ * Return -1 if the line above "lnum" ends in a backslash.
+ * foo = "asdf\
+ * asdf\
+ * here";
+ */
+ static int
+cin_get_equal_amount(lnum)
+ linenr_T lnum;
+{
+ char_u *line;
+ char_u *s;
+ colnr_T col;
+ pos_T fp;
+
+ if (lnum > 1)
+ {
+ line = ml_get(lnum - 1);
+ if (*line != NUL && line[STRLEN(line) - 1] == '\\')
+ return -1;
+ }
+
+ line = s = ml_get(lnum);
+ while (*s != NUL && vim_strchr((char_u *)"=;{}\"'", *s) == NULL)
+ {
+ if (cin_iscomment(s)) /* ignore comments */
+ s = cin_skipcomment(s);
+ else
+ ++s;
+ }
+ if (*s != '=')
+ return 0;
+
+ s = skipwhite(s + 1);
+ if (cin_nocode(s))
+ return 0;
+
+ if (*s == '"') /* nice alignment for continued strings */
+ ++s;
+
+ fp.lnum = lnum;
+ fp.col = (colnr_T)(s - line);
+ getvcol(curwin, &fp, &col, NULL, NULL);
+ return (int)col;
+}
+
+/*
+ * Recognize a preprocessor statement: Any line that starts with '#'.
+ */
+ static int
+cin_ispreproc(s)
+ char_u *s;
+{
+ s = skipwhite(s);
+ if (*s == '#')
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Return TRUE if line "*pp" at "*lnump" is a preprocessor statement or a
+ * continuation line of a preprocessor statement. Decrease "*lnump" to the
+ * start and return the line in "*pp".
+ */
+ static int
+cin_ispreproc_cont(pp, lnump)
+ char_u **pp;
+ linenr_T *lnump;
+{
+ char_u *line = *pp;
+ linenr_T lnum = *lnump;
+ int retval = FALSE;
+
+ while (1)
+ {
+ if (cin_ispreproc(line))
+ {
+ retval = TRUE;
+ *lnump = lnum;
+ break;
+ }
+ if (lnum == 1)
+ break;
+ line = ml_get(--lnum);
+ if (*line == NUL || line[STRLEN(line) - 1] != '\\')
+ break;
+ }
+
+ if (lnum != *lnump)
+ *pp = ml_get(*lnump);
+ return retval;
+}
+
+/*
+ * Recognize the start of a C or C++ comment.
+ */
+ static int
+cin_iscomment(p)
+ char_u *p;
+{
+ return (p[0] == '/' && (p[1] == '*' || p[1] == '/'));
+}
+
+/*
+ * Recognize the start of a "//" comment.
+ */
+ static int
+cin_islinecomment(p)
+ char_u *p;
+{
+ return (p[0] == '/' && p[1] == '/');
+}
+
+/*
+ * Recognize a line that starts with '{' or '}', or ends with ';', '{' or '}'.
+ * Don't consider "} else" a terminated line.
+ * Return the character terminating the line (ending char's have precedence if
+ * both apply in order to determine initializations).
+ */
+ static int
+cin_isterminated(s, incl_open, incl_comma)
+ char_u *s;
+ int incl_open; /* include '{' at the end as terminator */
+ int incl_comma; /* recognize a trailing comma */
+{
+ char_u found_start = 0;
+
+ s = cin_skipcomment(s);
+
+ if (*s == '{' || (*s == '}' && !cin_iselse(s)))
+ found_start = *s;
+
+ while (*s)
+ {
+ /* skip over comments, "" strings and 'c'haracters */
+ s = skip_string(cin_skipcomment(s));
+ if ((*s == ';' || (incl_open && *s == '{') || *s == '}'
+ || (incl_comma && *s == ','))
+ && cin_nocode(s + 1))
+ return *s;
+
+ if (*s)
+ s++;
+ }
+ return found_start;
+}
+
+/*
+ * Recognize the basic picture of a function declaration -- it needs to
+ * have an open paren somewhere and a close paren at the end of the line and
+ * no semicolons anywhere.
+ * When a line ends in a comma we continue looking in the next line.
+ * "sp" points to a string with the line. When looking at other lines it must
+ * be restored to the line. When it's NULL fetch lines here.
+ * "lnum" is where we start looking.
+ */
+ static int
+cin_isfuncdecl(sp, first_lnum)
+ char_u **sp;
+ linenr_T first_lnum;
+{
+ char_u *s;
+ linenr_T lnum = first_lnum;
+ int retval = FALSE;
+
+ if (sp == NULL)
+ s = ml_get(lnum);
+ else
+ s = *sp;
+
+ while (*s && *s != '(' && *s != ';' && *s != '\'' && *s != '"')
+ {
+ if (cin_iscomment(s)) /* ignore comments */
+ s = cin_skipcomment(s);
+ else
+ ++s;
+ }
+ if (*s != '(')
+ return FALSE; /* ';', ' or " before any () or no '(' */
+
+ while (*s && *s != ';' && *s != '\'' && *s != '"')
+ {
+ if (*s == ')' && cin_nocode(s + 1))
+ {
+ /* ')' at the end: may have found a match
+ * Check for he previous line not to end in a backslash:
+ * #if defined(x) && \
+ * defined(y)
+ */
+ lnum = first_lnum - 1;
+ s = ml_get(lnum);
+ if (*s == NUL || s[STRLEN(s) - 1] != '\\')
+ retval = TRUE;
+ goto done;
+ }
+ if (*s == ',' && cin_nocode(s + 1))
+ {
+ /* ',' at the end: continue looking in the next line */
+ if (lnum >= curbuf->b_ml.ml_line_count)
+ break;
+
+ s = ml_get(++lnum);
+ }
+ else if (cin_iscomment(s)) /* ignore comments */
+ s = cin_skipcomment(s);
+ else
+ ++s;
+ }
+
+done:
+ if (lnum != first_lnum && sp != NULL)
+ *sp = ml_get(first_lnum);
+
+ return retval;
+}
+
+ static int
+cin_isif(p)
+ char_u *p;
+{
+ return (STRNCMP(p, "if", 2) == 0 && !vim_isIDc(p[2]));
+}
+
+ static int
+cin_iselse(p)
+ char_u *p;
+{
+ if (*p == '}') /* accept "} else" */
+ p = cin_skipcomment(p + 1);
+ return (STRNCMP(p, "else", 4) == 0 && !vim_isIDc(p[4]));
+}
+
+ static int
+cin_isdo(p)
+ char_u *p;
+{
+ return (STRNCMP(p, "do", 2) == 0 && !vim_isIDc(p[2]));
+}
+
+/*
+ * Check if this is a "while" that should have a matching "do".
+ * We only accept a "while (condition) ;", with only white space between the
+ * ')' and ';'. The condition may be spread over several lines.
+ */
+ static int
+cin_iswhileofdo(p, lnum, ind_maxparen) /* XXX */
+ char_u *p;
+ linenr_T lnum;
+ int ind_maxparen;
+{
+ pos_T cursor_save;
+ pos_T *trypos;
+ int retval = FALSE;
+
+ p = cin_skipcomment(p);
+ if (*p == '}') /* accept "} while (cond);" */
+ p = cin_skipcomment(p + 1);
+ if (STRNCMP(p, "while", 5) == 0 && !vim_isIDc(p[5]))
+ {
+ cursor_save = curwin->w_cursor;
+ curwin->w_cursor.lnum = lnum;
+ curwin->w_cursor.col = 0;
+ p = ml_get_curline();
+ while (*p && *p != 'w') /* skip any '}', until the 'w' of the "while" */
+ {
+ ++p;
+ ++curwin->w_cursor.col;
+ }
+ if ((trypos = findmatchlimit(NULL, 0, 0, ind_maxparen)) != NULL
+ && *cin_skipcomment(ml_get_pos(trypos) + 1) == ';')
+ retval = TRUE;
+ curwin->w_cursor = cursor_save;
+ }
+ return retval;
+}
+
+ static int
+cin_isbreak(p)
+ char_u *p;
+{
+ return (STRNCMP(p, "break", 5) == 0 && !vim_isIDc(p[5]));
+}
+
+/* Find the position of a C++ base-class declaration or
+ * constructor-initialization. eg:
+ *
+ * class MyClass :
+ * baseClass <-- here
+ * class MyClass : public baseClass,
+ * anotherBaseClass <-- here (should probably lineup ??)
+ * MyClass::MyClass(...) :
+ * baseClass(...) <-- here (constructor-initialization)
+ */
+ static int
+cin_is_cpp_baseclass(line, col)
+ char_u *line;
+ colnr_T *col;
+{
+ char_u *s;
+ int class_or_struct, lookfor_ctor_init, cpp_base_class;
+
+ *col = 0;
+
+ s = cin_skipcomment(line);
+ if (*s == NUL)
+ return FALSE;
+
+ cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE;
+
+ while(*s != NUL)
+ {
+ if (s[0] == ':')
+ {
+ if (s[1] == ':')
+ {
+ /* skip double colon. It can't be a constructor
+ * initialization any more */
+ lookfor_ctor_init = FALSE;
+ s = cin_skipcomment(s + 2);
+ }
+ else if (lookfor_ctor_init || class_or_struct)
+ {
+ /* we have something found, that looks like the start of
+ * cpp-base-class-declaration or contructor-initialization */
+ cpp_base_class = TRUE;
+ lookfor_ctor_init = class_or_struct = FALSE;
+ *col = 0;
+ s = cin_skipcomment(s + 1);
+ }
+ else
+ s = cin_skipcomment(s + 1);
+ }
+ else if ((STRNCMP(s, "class", 5) == 0 && !vim_isIDc(s[5]))
+ || (STRNCMP(s, "struct", 6) == 0 && !vim_isIDc(s[6])))
+ {
+ class_or_struct = TRUE;
+ lookfor_ctor_init = FALSE;
+
+ if (*s == 'c')
+ s = cin_skipcomment(s + 5);
+ else
+ s = cin_skipcomment(s + 6);
+ }
+ else
+ {
+ if (s[0] == '{' || s[0] == '}' || s[0] == ';')
+ {
+ cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE;
+ }
+ else if (s[0] == ')')
+ {
+ /* Constructor-initialization is assumed if we come across
+ * something like "):" */
+ class_or_struct = FALSE;
+ lookfor_ctor_init = TRUE;
+ }
+ else if (!vim_isIDc(s[0]))
+ {
+ /* if it is not an identifier, we are wrong */
+ class_or_struct = FALSE;
+ lookfor_ctor_init = FALSE;
+ }
+ else if (*col == 0)
+ {
+ /* it can't be a constructor-initialization any more */
+ lookfor_ctor_init = FALSE;
+
+ /* the first statement starts here: lineup with this one... */
+ if (cpp_base_class && *col == 0)
+ *col = (colnr_T)(s - line);
+ }
+
+ s = cin_skipcomment(s + 1);
+ }
+ }
+
+ return cpp_base_class;
+}
+
+/*
+ * Return TRUE if string "s" ends with the string "find", possibly followed by
+ * white space and comments. Skip strings and comments.
+ * Ignore "ignore" after "find" if it's not NULL.
+ */
+ static int
+cin_ends_in(s, find, ignore)
+ char_u *s;
+ char_u *find;
+ char_u *ignore;
+{
+ char_u *p = s;
+ char_u *r;
+ int len = (int)STRLEN(find);
+
+ while (*p != NUL)
+ {
+ p = cin_skipcomment(p);
+ if (STRNCMP(p, find, len) == 0)
+ {
+ r = skipwhite(p + len);
+ if (ignore != NULL && STRNCMP(r, ignore, STRLEN(ignore)) == 0)
+ r = skipwhite(r + STRLEN(ignore));
+ if (cin_nocode(r))
+ return TRUE;
+ }
+ if (*p != NUL)
+ ++p;
+ }
+ return FALSE;
+}
+
+/*
+ * Skip strings, chars and comments until at or past "trypos".
+ * Return the column found.
+ */
+ static int
+cin_skip2pos(trypos)
+ pos_T *trypos;
+{
+ char_u *line;
+ char_u *p;
+
+ p = line = ml_get(trypos->lnum);
+ while (*p && (colnr_T)(p - line) < trypos->col)
+ {
+ if (cin_iscomment(p))
+ p = cin_skipcomment(p);
+ else
+ {
+ p = skip_string(p);
+ ++p;
+ }
+ }
+ return (int)(p - line);
+}
+
+/*
+ * Find the '{' at the start of the block we are in.
+ * Return NULL if no match found.
+ * Ignore a '{' that is in a comment, makes indenting the next three lines
+ * work. */
+/* foo() */
+/* { */
+/* } */
+
+ static pos_T *
+find_start_brace(ind_maxcomment) /* XXX */
+ int ind_maxcomment;
+{
+ pos_T cursor_save;
+ pos_T *trypos;
+ pos_T *pos;
+ static pos_T pos_copy;
+
+ cursor_save = curwin->w_cursor;
+ while ((trypos = findmatchlimit(NULL, '{', FM_BLOCKSTOP, 0)) != NULL)
+ {
+ pos_copy = *trypos; /* copy pos_T, next findmatch will change it */
+ trypos = &pos_copy;
+ curwin->w_cursor = *trypos;
+ pos = NULL;
+ /* ignore the { if it's in a // comment */
+ if ((colnr_T)cin_skip2pos(trypos) == trypos->col
+ && (pos = find_start_comment(ind_maxcomment)) == NULL) /* XXX */
+ break;
+ if (pos != NULL)
+ curwin->w_cursor.lnum = pos->lnum;
+ }
+ curwin->w_cursor = cursor_save;
+ return trypos;
+}
+
+/*
+ * Find the matching '(', failing if it is in a comment.
+ * Return NULL of no match found.
+ */
+ static pos_T *
+find_match_paren(ind_maxparen, ind_maxcomment) /* XXX */
+ int ind_maxparen;
+ int ind_maxcomment;
+{
+ pos_T cursor_save;
+ pos_T *trypos;
+ static pos_T pos_copy;
+
+ cursor_save = curwin->w_cursor;
+ if ((trypos = findmatchlimit(NULL, '(', 0, ind_maxparen)) != NULL)
+ {
+ /* check if the ( is in a // comment */
+ if ((colnr_T)cin_skip2pos(trypos) > trypos->col)
+ trypos = NULL;
+ else
+ {
+ pos_copy = *trypos; /* copy trypos, findmatch will change it */
+ trypos = &pos_copy;
+ curwin->w_cursor = *trypos;
+ if (find_start_comment(ind_maxcomment) != NULL) /* XXX */
+ trypos = NULL;
+ }
+ }
+ curwin->w_cursor = cursor_save;
+ return trypos;
+}
+
+/*
+ * Return ind_maxparen corrected for the difference in line number between the
+ * cursor position and "startpos". This makes sure that searching for a
+ * matching paren above the cursor line doesn't find a match because of
+ * looking a few lines further.
+ */
+ static int
+corr_ind_maxparen(ind_maxparen, startpos)
+ int ind_maxparen;
+ pos_T *startpos;
+{
+ long n = (long)startpos->lnum - (long)curwin->w_cursor.lnum;
+
+ if (n > 0 && n < ind_maxparen / 2)
+ return ind_maxparen - (int)n;
+ return ind_maxparen;
+}
+
+/*
+ * Set w_cursor.col to the column number of the last unmatched ')' or '{' in
+ * line "l".
+ */
+ static int
+find_last_paren(l, start, end)
+ char_u *l;
+ int start, end;
+{
+ int i;
+ int retval = FALSE;
+ int open_count = 0;
+
+ curwin->w_cursor.col = 0; /* default is start of line */
+
+ for (i = 0; l[i]; i++)
+ {
+ i = (int)(cin_skipcomment(l + i) - l); /* ignore parens in comments */
+ i = (int)(skip_string(l + i) - l); /* ignore parens in quotes */
+ if (l[i] == start)
+ ++open_count;
+ else if (l[i] == end)
+ {
+ if (open_count > 0)
+ --open_count;
+ else
+ {
+ curwin->w_cursor.col = i;
+ retval = TRUE;
+ }
+ }
+ }
+ return retval;
+}
+
+ int
+get_c_indent()
+{
+ /*
+ * spaces from a block's opening brace the prevailing indent for that
+ * block should be
+ */
+ int ind_level = curbuf->b_p_sw;
+
+ /*
+ * spaces from the edge of the line an open brace that's at the end of a
+ * line is imagined to be.
+ */
+ int ind_open_imag = 0;
+
+ /*
+ * spaces from the prevailing indent for a line that is not precededof by
+ * an opening brace.
+ */
+ int ind_no_brace = 0;
+
+ /*
+ * column where the first { of a function should be located }
+ */
+ int ind_first_open = 0;
+
+ /*
+ * spaces from the prevailing indent a leftmost open brace should be
+ * located
+ */
+ int ind_open_extra = 0;
+
+ /*
+ * spaces from the matching open brace (real location for one at the left
+ * edge; imaginary location from one that ends a line) the matching close
+ * brace should be located
+ */
+ int ind_close_extra = 0;
+
+ /*
+ * spaces from the edge of the line an open brace sitting in the leftmost
+ * column is imagined to be
+ */
+ int ind_open_left_imag = 0;
+
+ /*
+ * spaces from the switch() indent a "case xx" label should be located
+ */
+ int ind_case = curbuf->b_p_sw;
+
+ /*
+ * spaces from the "case xx:" code after a switch() should be located
+ */
+ int ind_case_code = curbuf->b_p_sw;
+
+ /*
+ * lineup break at end of case in switch() with case label
+ */
+ int ind_case_break = 0;
+
+ /*
+ * spaces from the class declaration indent a scope declaration label
+ * should be located
+ */
+ int ind_scopedecl = curbuf->b_p_sw;
+
+ /*
+ * spaces from the scope declaration label code should be located
+ */
+ int ind_scopedecl_code = curbuf->b_p_sw;
+
+ /*
+ * amount K&R-style parameters should be indented
+ */
+ int ind_param = curbuf->b_p_sw;
+
+ /*
+ * amount a function type spec should be indented
+ */
+ int ind_func_type = curbuf->b_p_sw;
+
+ /*
+ * amount a cpp base class declaration or constructor initialization
+ * should be indented
+ */
+ int ind_cpp_baseclass = curbuf->b_p_sw;
+
+ /*
+ * additional spaces beyond the prevailing indent a continuation line
+ * should be located
+ */
+ int ind_continuation = curbuf->b_p_sw;
+
+ /*
+ * spaces from the indent of the line with an unclosed parentheses
+ */
+ int ind_unclosed = curbuf->b_p_sw * 2;
+
+ /*
+ * spaces from the indent of the line with an unclosed parentheses, which
+ * itself is also unclosed
+ */
+ int ind_unclosed2 = curbuf->b_p_sw;
+
+ /*
+ * suppress ignoring spaces from the indent of a line starting with an
+ * unclosed parentheses.
+ */
+ int ind_unclosed_noignore = 0;
+
+ /*
+ * If the opening paren is the last nonwhite character on the line, and
+ * ind_unclosed_wrapped is nonzero, use this indent relative to the outer
+ * context (for very long lines).
+ */
+ int ind_unclosed_wrapped = 0;
+
+ /*
+ * suppress ignoring white space when lining up with the character after
+ * an unclosed parentheses.
+ */
+ int ind_unclosed_whiteok = 0;
+
+ /*
+ * indent a closing parentheses under the line start of the matching
+ * opening parentheses.
+ */
+ int ind_matching_paren = 0;
+
+ /*
+ * Extra indent for comments.
+ */
+ int ind_comment = 0;
+
+ /*
+ * spaces from the comment opener when there is nothing after it.
+ */
+ int ind_in_comment = 3;
+
+ /*
+ * boolean: if non-zero, use ind_in_comment even if there is something
+ * after the comment opener.
+ */
+ int ind_in_comment2 = 0;
+
+ /*
+ * max lines to search for an open paren
+ */
+ int ind_maxparen = 20;
+
+ /*
+ * max lines to search for an open comment
+ */
+ int ind_maxcomment = 70;
+
+ /*
+ * handle braces for java code
+ */
+ int ind_java = 0;
+
+ /*
+ * handle blocked cases correctly
+ */
+ int ind_keep_case_label = 0;
+
+ pos_T cur_curpos;
+ int amount;
+ int scope_amount;
+ int cur_amount;
+ colnr_T col;
+ char_u *theline;
+ char_u *linecopy;
+ pos_T *trypos;
+ pos_T *tryposBrace = NULL;
+ pos_T our_paren_pos;
+ char_u *start;
+ int start_brace;
+#define BRACE_IN_COL0 1 /* '{' is in comumn 0 */
+#define BRACE_AT_START 2 /* '{' is at start of line */
+#define BRACE_AT_END 3 /* '{' is at end of line */
+ linenr_T ourscope;
+ char_u *l;
+ char_u *look;
+ char_u terminated;
+ int lookfor;
+#define LOOKFOR_INITIAL 0
+#define LOOKFOR_IF 1
+#define LOOKFOR_DO 2
+#define LOOKFOR_CASE 3
+#define LOOKFOR_ANY 4
+#define LOOKFOR_TERM 5
+#define LOOKFOR_UNTERM 6
+#define LOOKFOR_SCOPEDECL 7
+#define LOOKFOR_NOBREAK 8
+#define LOOKFOR_CPP_BASECLASS 9
+#define LOOKFOR_ENUM_OR_INIT 10
+
+ int whilelevel;
+ linenr_T lnum;
+ char_u *options;
+ int fraction = 0; /* init for GCC */
+ int divider;
+ int n;
+ int iscase;
+ int lookfor_break;
+ int cont_amount = 0; /* amount for continuation line */
+
+ for (options = curbuf->b_p_cino; *options; )
+ {
+ l = options++;
+ if (*options == '-')
+ ++options;
+ n = getdigits(&options);
+ divider = 0;
+ if (*options == '.') /* ".5s" means a fraction */
+ {
+ fraction = atol((char *)++options);
+ while (VIM_ISDIGIT(*options))
+ {
+ ++options;
+ if (divider)
+ divider *= 10;
+ else
+ divider = 10;
+ }
+ }
+ if (*options == 's') /* "2s" means two times 'shiftwidth' */
+ {
+ if (n == 0 && fraction == 0)
+ n = curbuf->b_p_sw; /* just "s" is one 'shiftwidth' */
+ else
+ {
+ n *= curbuf->b_p_sw;
+ if (divider)
+ n += (curbuf->b_p_sw * fraction + divider / 2) / divider;
+ }
+ ++options;
+ }
+ if (l[1] == '-')
+ n = -n;
+ /* When adding an entry here, also update the default 'cinoptions' in
+ * change.txt, and add explanation for it! */
+ switch (*l)
+ {
+ case '>': ind_level = n; break;
+ case 'e': ind_open_imag = n; break;
+ case 'n': ind_no_brace = n; break;
+ case 'f': ind_first_open = n; break;
+ case '{': ind_open_extra = n; break;
+ case '}': ind_close_extra = n; break;
+ case '^': ind_open_left_imag = n; break;
+ case ':': ind_case = n; break;
+ case '=': ind_case_code = n; break;
+ case 'b': ind_case_break = n; break;
+ case 'p': ind_param = n; break;
+ case 't': ind_func_type = n; break;
+ case '/': ind_comment = n; break;
+ case 'c': ind_in_comment = n; break;
+ case 'C': ind_in_comment2 = n; break;
+ case 'i': ind_cpp_baseclass = n; break;
+ case '+': ind_continuation = n; break;
+ case '(': ind_unclosed = n; break;
+ case 'u': ind_unclosed2 = n; break;
+ case 'U': ind_unclosed_noignore = n; break;
+ case 'W': ind_unclosed_wrapped = n; break;
+ case 'w': ind_unclosed_whiteok = n; break;
+ case 'm': ind_matching_paren = n; break;
+ case ')': ind_maxparen = n; break;
+ case '*': ind_maxcomment = n; break;
+ case 'g': ind_scopedecl = n; break;
+ case 'h': ind_scopedecl_code = n; break;
+ case 'j': ind_java = n; break;
+ case 'l': ind_keep_case_label = n; break;
+ }
+ }
+
+ /* remember where the cursor was when we started */
+ cur_curpos = curwin->w_cursor;
+
+ /* Get a copy of the current contents of the line.
+ * This is required, because only the most recent line obtained with
+ * ml_get is valid! */
+ linecopy = vim_strsave(ml_get(cur_curpos.lnum));
+ if (linecopy == NULL)
+ return 0;
+
+ /*
+ * In insert mode and the cursor is on a ')' truncate the line at the
+ * cursor position. We don't want to line up with the matching '(' when
+ * inserting new stuff.
+ * For unknown reasons the cursor might be past the end of the line, thus
+ * check for that.
+ */
+ if ((State & INSERT)
+ && curwin->w_cursor.col < STRLEN(linecopy)
+ && linecopy[curwin->w_cursor.col] == ')')
+ linecopy[curwin->w_cursor.col] = NUL;
+
+ theline = skipwhite(linecopy);
+
+ /* move the cursor to the start of the line */
+
+ curwin->w_cursor.col = 0;
+
+ /*
+ * #defines and so on always go at the left when included in 'cinkeys'.
+ */
+ if (*theline == '#' && (*linecopy == '#' || in_cinkeys('#', ' ', TRUE)))
+ {
+ amount = 0;
+ }
+
+ /*
+ * Is it a non-case label? Then that goes at the left margin too.
+ */
+ else if (cin_islabel(ind_maxcomment)) /* XXX */
+ {
+ amount = 0;
+ }
+
+ /*
+ * If we're inside a "//" comment and there is a "//" comment in a
+ * previous line, lineup with that one.
+ */
+ else if (cin_islinecomment(theline)
+ && (trypos = find_line_comment()) != NULL) /* XXX */
+ {
+ /* find how indented the line beginning the comment is */
+ getvcol(curwin, trypos, &col, NULL, NULL);
+ amount = col;
+ }
+
+ /*
+ * If we're inside a comment and not looking at the start of the
+ * comment, try using the 'comments' option.
+ */
+ else if (!cin_iscomment(theline)
+ && (trypos = find_start_comment(ind_maxcomment)) != NULL) /* XXX */
+ {
+ int lead_start_len = 2;
+ int lead_middle_len = 1;
+ char_u lead_start[COM_MAX_LEN]; /* start-comment string */
+ char_u lead_middle[COM_MAX_LEN]; /* middle-comment string */
+ char_u lead_end[COM_MAX_LEN]; /* end-comment string */
+ char_u *p;
+ int start_align = 0;
+ int start_off = 0;
+ int done = FALSE;
+
+ /* find how indented the line beginning the comment is */
+ getvcol(curwin, trypos, &col, NULL, NULL);
+ amount = col;
+
+ p = curbuf->b_p_com;
+ while (*p != NUL)
+ {
+ int align = 0;
+ int off = 0;
+ int what = 0;
+
+ while (*p != NUL && *p != ':')
+ {
+ if (*p == COM_START || *p == COM_END || *p == COM_MIDDLE)
+ what = *p++;
+ else if (*p == COM_LEFT || *p == COM_RIGHT)
+ align = *p++;
+ else if (VIM_ISDIGIT(*p) || *p == '-')
+ off = getdigits(&p);
+ else
+ ++p;
+ }
+
+ if (*p == ':')
+ ++p;
+ (void)copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
+ if (what == COM_START)
+ {
+ STRCPY(lead_start, lead_end);
+ lead_start_len = (int)STRLEN(lead_start);
+ start_off = off;
+ start_align = align;
+ }
+ else if (what == COM_MIDDLE)
+ {
+ STRCPY(lead_middle, lead_end);
+ lead_middle_len = (int)STRLEN(lead_middle);
+ }
+ else if (what == COM_END)
+ {
+ /* If our line starts with the middle comment string, line it
+ * up with the comment opener per the 'comments' option. */
+ if (STRNCMP(theline, lead_middle, lead_middle_len) == 0
+ && STRNCMP(theline, lead_end, STRLEN(lead_end)) != 0)
+ {
+ done = TRUE;
+ if (curwin->w_cursor.lnum > 1)
+ {
+ /* If the start comment string matches in the previous
+ * line, use the indent of that line pluss offset. If
+ * the middle comment string matches in the previous
+ * line, use the indent of that line. XXX */
+ look = skipwhite(ml_get(curwin->w_cursor.lnum - 1));
+ if (STRNCMP(look, lead_start, lead_start_len) == 0)
+ amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
+ else if (STRNCMP(look, lead_middle,
+ lead_middle_len) == 0)
+ {
+ amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
+ break;
+ }
+ /* If the start comment string doesn't match with the
+ * start of the comment, skip this entry. XXX */
+ else if (STRNCMP(ml_get(trypos->lnum) + trypos->col,
+ lead_start, lead_start_len) != 0)
+ continue;
+ }
+ if (start_off != 0)
+ amount += start_off;
+ else if (start_align == COM_RIGHT)
+ amount += lead_start_len - lead_middle_len;
+ break;
+ }
+
+ /* If our line starts with the end comment string, line it up
+ * with the middle comment */
+ if (STRNCMP(theline, lead_middle, lead_middle_len) != 0
+ && STRNCMP(theline, lead_end, STRLEN(lead_end)) == 0)
+ {
+ amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
+ /* XXX */
+ if (off != 0)
+ amount += off;
+ else if (align == COM_RIGHT)
+ amount += lead_start_len - lead_middle_len;
+ done = TRUE;
+ break;
+ }
+ }
+ }
+
+ /* If our line starts with an asterisk, line up with the
+ * asterisk in the comment opener; otherwise, line up
+ * with the first character of the comment text.
+ */
+ if (done)
+ ;
+ else if (theline[0] == '*')
+ amount += 1;
+ else
+ {
+ /*
+ * If we are more than one line away from the comment opener, take
+ * the indent of the previous non-empty line. If 'cino' has "CO"
+ * and we are just below the comment opener and there are any
+ * white characters after it line up with the text after it;
+ * otherwise, add the amount specified by "c" in 'cino'
+ */
+ amount = -1;
+ for (lnum = cur_curpos.lnum - 1; lnum > trypos->lnum; --lnum)
+ {
+ if (linewhite(lnum)) /* skip blank lines */
+ continue;
+ amount = get_indent_lnum(lnum); /* XXX */
+ break;
+ }
+ if (amount == -1) /* use the comment opener */
+ {
+ if (!ind_in_comment2)
+ {
+ start = ml_get(trypos->lnum);
+ look = start + trypos->col + 2; /* skip / and * */
+ if (*look != NUL) /* if something after it */
+ trypos->col = (colnr_T)(skipwhite(look) - start);
+ }
+ getvcol(curwin, trypos, &col, NULL, NULL);
+ amount = col;
+ if (ind_in_comment2 || *look == NUL)
+ amount += ind_in_comment;
+ }
+ }
+ }
+
+ /*
+ * Are we inside parentheses or braces?
+ */ /* XXX */
+ else if (((trypos = find_match_paren(ind_maxparen, ind_maxcomment)) != NULL
+ && ind_java == 0)
+ || (tryposBrace = find_start_brace(ind_maxcomment)) != NULL
+ || trypos != NULL)
+ {
+ if (trypos != NULL && tryposBrace != NULL)
+ {
+ /* Both an unmatched '(' and '{' is found. Use the one which is
+ * closer to the current cursor position, set the other to NULL. */
+ if (trypos->lnum != tryposBrace->lnum
+ ? trypos->lnum < tryposBrace->lnum
+ : trypos->col < tryposBrace->col)
+ trypos = NULL;
+ else
+ tryposBrace = NULL;
+ }
+
+ if (trypos != NULL)
+ {
+ /*
+ * If the matching paren is more than one line away, use the indent of
+ * a previous non-empty line that matches the same paren.
+ */
+ amount = -1;
+ cur_amount = MAXCOL;
+ our_paren_pos = *trypos;
+ for (lnum = cur_curpos.lnum - 1; lnum > our_paren_pos.lnum; --lnum)
+ {
+ l = skipwhite(ml_get(lnum));
+ if (cin_nocode(l)) /* skip comment lines */
+ continue;
+ if (cin_ispreproc_cont(&l, &lnum)) /* ignore #defines, #if, etc. */
+ continue;
+ curwin->w_cursor.lnum = lnum;
+
+ /* Skip a comment. XXX */
+ if ((trypos = find_start_comment(ind_maxcomment)) != NULL)
+ {
+ lnum = trypos->lnum + 1;
+ continue;
+ }
+
+ /* XXX */
+ if ((trypos = find_match_paren(
+ corr_ind_maxparen(ind_maxparen, &cur_curpos),
+ ind_maxcomment)) != NULL
+ && trypos->lnum == our_paren_pos.lnum
+ && trypos->col == our_paren_pos.col)
+ {
+ amount = get_indent_lnum(lnum); /* XXX */
+
+ if (theline[0] == ')')
+ {
+ if (our_paren_pos.lnum != lnum && cur_amount > amount)
+ cur_amount = amount;
+ amount = -1;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Line up with line where the matching paren is. XXX
+ * If the line starts with a '(' or the indent for unclosed
+ * parentheses is zero, line up with the unclosed parentheses.
+ */
+ if (amount == -1)
+ {
+ amount = skip_label(our_paren_pos.lnum, &look, ind_maxcomment);
+ if (theline[0] == ')' || ind_unclosed == 0
+ || (!ind_unclosed_noignore && *skipwhite(look) == '('))
+ {
+ /*
+ * If we're looking at a close paren, line up right there;
+ * otherwise, line up with the next (non-white) character.
+ * When ind_unclosed_wrapped is set and the matching paren is
+ * the last nonwhite character of the line, use either the
+ * indent of the current line or the indentation of the next
+ * outer paren and add ind_unclosed_wrapped (for very long
+ * lines).
+ */
+ if (theline[0] != ')')
+ {
+ cur_amount = MAXCOL;
+ l = ml_get(our_paren_pos.lnum);
+ if (ind_unclosed_wrapped
+ && cin_ends_in(l, (char_u *)"(", NULL))
+ {
+ /* look for opening unmatched paren, indent one level
+ * for each additional level */
+ n = 1;
+ for (col = 0; col < our_paren_pos.col; ++col)
+ {
+ switch (l[col])
+ {
+ case '(':
+ case '{': ++n;
+ break;
+
+ case ')':
+ case '}': if (n > 1)
+ --n;
+ break;
+ }
+ }
+
+ our_paren_pos.col = 0;
+ amount += n * ind_unclosed_wrapped;
+ }
+ else if (ind_unclosed_whiteok)
+ our_paren_pos.col++;
+ else
+ {
+ col = our_paren_pos.col + 1;
+ while (vim_iswhite(l[col]))
+ col++;
+ if (l[col] != NUL) /* In case of trailing space */
+ our_paren_pos.col = col;
+ else
+ our_paren_pos.col++;
+ }
+ }
+
+ /*
+ * Find how indented the paren is, or the character after it
+ * if we did the above "if".
+ */
+ if (our_paren_pos.col > 0)
+ {
+ getvcol(curwin, &our_paren_pos, &col, NULL, NULL);
+ if (cur_amount > (int)col)
+ cur_amount = col;
+ }
+ }
+
+ if (theline[0] == ')' && ind_matching_paren)
+ {
+ /* Line up with the start of the matching paren line. */
+ }
+ else if (ind_unclosed == 0 || (!ind_unclosed_noignore
+ && *skipwhite(look) == '('))
+ {
+ if (cur_amount != MAXCOL)
+ amount = cur_amount;
+ }
+ else
+ {
+ /* add ind_unclosed2 for each '(' before our matching one */
+ col = our_paren_pos.col;
+ while (our_paren_pos.col > 0)
+ {
+ --our_paren_pos.col;
+ switch (*ml_get_pos(&our_paren_pos))
+ {
+ case '(': amount += ind_unclosed2;
+ col = our_paren_pos.col;
+ break;
+ case ')': amount -= ind_unclosed2;
+ col = MAXCOL;
+ break;
+ }
+ }
+
+ /* Use ind_unclosed once, when the first '(' is not inside
+ * braces */
+ if (col == MAXCOL)
+ amount += ind_unclosed;
+ else
+ {
+ curwin->w_cursor.lnum = our_paren_pos.lnum;
+ curwin->w_cursor.col = col;
+ if ((trypos = find_match_paren(ind_maxparen,
+ ind_maxcomment)) != NULL)
+ amount += ind_unclosed2;
+ else
+ amount += ind_unclosed;
+ }
+ /*
+ * For a line starting with ')' use the minimum of the two
+ * positions, to avoid giving it more indent than the previous
+ * lines:
+ * func_long_name( if (x
+ * arg && yy
+ * ) ^ not here ) ^ not here
+ */
+ if (cur_amount < amount)
+ amount = cur_amount;
+ }
+ }
+
+ /* add extra indent for a comment */
+ if (cin_iscomment(theline))
+ amount += ind_comment;
+ }
+
+ /*
+ * Are we at least inside braces, then?
+ */
+ else
+ {
+ trypos = tryposBrace;
+
+ ourscope = trypos->lnum;
+ start = ml_get(ourscope);
+
+ /*
+ * Now figure out how indented the line is in general.
+ * If the brace was at the start of the line, we use that;
+ * otherwise, check out the indentation of the line as
+ * a whole and then add the "imaginary indent" to that.
+ */
+ look = skipwhite(start);
+ if (*look == '{')
+ {
+ getvcol(curwin, trypos, &col, NULL, NULL);
+ amount = col;
+ if (*start == '{')
+ start_brace = BRACE_IN_COL0;
+ else
+ start_brace = BRACE_AT_START;
+ }
+ else
+ {
+ /*
+ * that opening brace might have been on a continuation
+ * line. if so, find the start of the line.
+ */
+ curwin->w_cursor.lnum = ourscope;
+
+ /*
+ * position the cursor over the rightmost paren, so that
+ * matching it will take us back to the start of the line.
+ */
+ lnum = ourscope;
+ if (find_last_paren(start, '(', ')')
+ && (trypos = find_match_paren(ind_maxparen,
+ ind_maxcomment)) != NULL)
+ lnum = trypos->lnum;
+
+ /*
+ * It could have been something like
+ * case 1: if (asdf &&
+ * ldfd) {
+ * }
+ */
+ if (ind_keep_case_label && cin_iscase(skipwhite(ml_get_curline())))
+ amount = get_indent();
+ else
+ amount = skip_label(lnum, &l, ind_maxcomment);
+
+ start_brace = BRACE_AT_END;
+ }
+
+ /*
+ * if we're looking at a closing brace, that's where
+ * we want to be. otherwise, add the amount of room
+ * that an indent is supposed to be.
+ */
+ if (theline[0] == '}')
+ {
+ /*
+ * they may want closing braces to line up with something
+ * other than the open brace. indulge them, if so.
+ */
+ amount += ind_close_extra;
+ }
+ else
+ {
+ /*
+ * If we're looking at an "else", try to find an "if"
+ * to match it with.
+ * If we're looking at a "while", try to find a "do"
+ * to match it with.
+ */
+ lookfor = LOOKFOR_INITIAL;
+ if (cin_iselse(theline))
+ lookfor = LOOKFOR_IF;
+ else if (cin_iswhileofdo(theline, cur_curpos.lnum, ind_maxparen))
+ /* XXX */
+ lookfor = LOOKFOR_DO;
+ if (lookfor != LOOKFOR_INITIAL)
+ {
+ curwin->w_cursor.lnum = cur_curpos.lnum;
+ if (find_match(lookfor, ourscope, ind_maxparen,
+ ind_maxcomment) == OK)
+ {
+ amount = get_indent(); /* XXX */
+ goto theend;
+ }
+ }
+
+ /*
+ * We get here if we are not on an "while-of-do" or "else" (or
+ * failed to find a matching "if").
+ * Search backwards for something to line up with.
+ * First set amount for when we don't find anything.
+ */
+
+ /*
+ * if the '{' is _really_ at the left margin, use the imaginary
+ * location of a left-margin brace. Otherwise, correct the
+ * location for ind_open_extra.
+ */
+
+ if (start_brace == BRACE_IN_COL0) /* '{' is in column 0 */
+ {
+ amount = ind_open_left_imag;
+ }
+ else
+ {
+ if (start_brace == BRACE_AT_END) /* '{' is at end of line */
+ amount += ind_open_imag;
+ else
+ {
+ /* Compensate for adding ind_open_extra later. */
+ amount -= ind_open_extra;
+ if (amount < 0)
+ amount = 0;
+ }
+ }
+
+ lookfor_break = FALSE;
+
+ if (cin_iscase(theline)) /* it's a switch() label */
+ {
+ lookfor = LOOKFOR_CASE; /* find a previous switch() label */
+ amount += ind_case;
+ }
+ else if (cin_isscopedecl(theline)) /* private:, ... */
+ {
+ lookfor = LOOKFOR_SCOPEDECL; /* class decl is this block */
+ amount += ind_scopedecl;
+ }
+ else
+ {
+ if (ind_case_break && cin_isbreak(theline)) /* break; ... */
+ lookfor_break = TRUE;
+
+ lookfor = LOOKFOR_INITIAL;
+ amount += ind_level; /* ind_level from start of block */
+ }
+ scope_amount = amount;
+ whilelevel = 0;
+
+ /*
+ * Search backwards. If we find something we recognize, line up
+ * with that.
+ *
+ * if we're looking at an open brace, indent
+ * the usual amount relative to the conditional
+ * that opens the block.
+ */
+ curwin->w_cursor = cur_curpos;
+ for (;;)
+ {
+ curwin->w_cursor.lnum--;
+ curwin->w_cursor.col = 0;
+
+ /*
+ * If we went all the way back to the start of our scope, line
+ * up with it.
+ */
+ if (curwin->w_cursor.lnum <= ourscope)
+ {
+ /* we reached end of scope:
+ * if looking for a enum or structure initialization
+ * go further back:
+ * if it is an initializer (enum xxx or xxx =), then
+ * don't add ind_continuation, otherwise it is a variable
+ * declaration:
+ * int x,
+ * here; <-- add ind_continuation
+ */
+ if (lookfor == LOOKFOR_ENUM_OR_INIT)
+ {
+ if (curwin->w_cursor.lnum == 0
+ || curwin->w_cursor.lnum
+ < ourscope - ind_maxparen)
+ {
+ /* nothing found (abuse ind_maxparen as limit)
+ * assume terminated line (i.e. a variable
+ * initialization) */
+ if (cont_amount > 0)
+ amount = cont_amount;
+ else
+ amount += ind_continuation;
+ break;
+ }
+
+ l = ml_get_curline();
+
+ /*
+ * If we're in a comment now, skip to the start of the
+ * comment.
+ */
+ trypos = find_start_comment(ind_maxcomment);
+ if (trypos != NULL)
+ {
+ curwin->w_cursor.lnum = trypos->lnum + 1;
+ continue;
+ }
+
+ /*
+ * Skip preprocessor directives and blank lines.
+ */
+ if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum))
+ continue;
+
+ if (cin_nocode(l))
+ continue;
+
+ terminated = cin_isterminated(l, FALSE, TRUE);
+
+ /*
+ * If we are at top level and the line looks like a
+ * function declaration, we are done
+ * (it's a variable declaration).
+ */
+ if (start_brace != BRACE_IN_COL0
+ || !cin_isfuncdecl(&l, curwin->w_cursor.lnum))
+ {
+ /* if the line is terminated with another ','
+ * it is a continued variable initialization.
+ * don't add extra indent.
+ * TODO: does not work, if a function
+ * declaration is split over multiple lines:
+ * cin_isfuncdecl returns FALSE then.
+ */
+ if (terminated == ',')
+ break;
+
+ /* if it es a enum declaration or an assignment,
+ * we are done.
+ */
+ if (terminated != ';' && cin_isinit())
+ break;
+
+ /* nothing useful found */
+ if (terminated == 0 || terminated == '{')
+ continue;
+ }
+
+ if (terminated != ';')
+ {
+ /* Skip parens and braces. Position the cursor
+ * over the rightmost paren, so that matching it
+ * will take us back to the start of the line.
+ */ /* XXX */
+ trypos = NULL;
+ if (find_last_paren(l, '(', ')'))
+ trypos = find_match_paren(ind_maxparen,
+ ind_maxcomment);
+
+ if (trypos == NULL && find_last_paren(l, '{', '}'))
+ trypos = find_start_brace(ind_maxcomment);
+
+ if (trypos != NULL)
+ {
+ curwin->w_cursor.lnum = trypos->lnum + 1;
+ continue;
+ }
+ }
+
+ /* it's a variable declaration, add indentation
+ * like in
+ * int a,
+ * b;
+ */
+ if (cont_amount > 0)
+ amount = cont_amount;
+ else
+ amount += ind_continuation;
+ }
+ else if (lookfor == LOOKFOR_UNTERM)
+ {
+ if (cont_amount > 0)
+ amount = cont_amount;
+ else
+ amount += ind_continuation;
+ }
+ else if (lookfor != LOOKFOR_TERM
+ && lookfor != LOOKFOR_CPP_BASECLASS)
+ {
+ amount = scope_amount;
+ if (theline[0] == '{')
+ amount += ind_open_extra;
+ }
+ break;
+ }
+
+ /*
+ * If we're in a comment now, skip to the start of the comment.
+ */ /* XXX */
+ if ((trypos = find_start_comment(ind_maxcomment)) != NULL)
+ {
+ curwin->w_cursor.lnum = trypos->lnum + 1;
+ continue;
+ }
+
+ l = ml_get_curline();
+
+ /*
+ * If this is a switch() label, may line up relative to that.
+ * if this is a C++ scope declaration, do the same.
+ */
+ iscase = cin_iscase(l);
+ if (iscase || cin_isscopedecl(l))
+ {
+ /* we are only looking for cpp base class
+ * declaration/initialization any longer */
+ if (lookfor == LOOKFOR_CPP_BASECLASS)
+ break;
+
+ /* When looking for a "do" we are not interested in
+ * labels. */
+ if (whilelevel > 0)
+ continue;
+
+ /*
+ * case xx:
+ * c = 99 + <- this indent plus continuation
+ *-> here;
+ */
+ if (lookfor == LOOKFOR_UNTERM
+ || lookfor == LOOKFOR_ENUM_OR_INIT)
+ {
+ if (cont_amount > 0)
+ amount = cont_amount;
+ else
+ amount += ind_continuation;
+ break;
+ }
+
+ /*
+ * case xx: <- line up with this case
+ * x = 333;
+ * case yy:
+ */
+ if ( (iscase && lookfor == LOOKFOR_CASE)
+ || (iscase && lookfor_break)
+ || (!iscase && lookfor == LOOKFOR_SCOPEDECL))
+ {
+ /*
+ * Check that this case label is not for another
+ * switch()
+ */ /* XXX */
+ if ((trypos = find_start_brace(ind_maxcomment)) ==
+ NULL || trypos->lnum == ourscope)
+ {
+ amount = get_indent(); /* XXX */
+ break;
+ }
+ continue;
+ }
+
+ n = get_indent_nolabel(curwin->w_cursor.lnum); /* XXX */
+
+ /*
+ * case xx: if (cond) <- line up with this if
+ * y = y + 1;
+ * -> s = 99;
+ *
+ * case xx:
+ * if (cond) <- line up with this line
+ * y = y + 1;
+ * -> s = 99;
+ */
+ if (lookfor == LOOKFOR_TERM)
+ {
+ if (n)
+ amount = n;
+
+ if (!lookfor_break)
+ break;
+ }
+
+ /*
+ * case xx: x = x + 1; <- line up with this x
+ * -> y = y + 1;
+ *
+ * case xx: if (cond) <- line up with this if
+ * -> y = y + 1;
+ */
+ if (n)
+ {
+ amount = n;
+ l = after_label(ml_get_curline());
+ if (l != NULL && cin_is_cinword(l))
+ amount += ind_level + ind_no_brace;
+ break;
+ }
+
+ /*
+ * Try to get the indent of a statement before the switch
+ * label. If nothing is found, line up relative to the
+ * switch label.
+ * break; <- may line up with this line
+ * case xx:
+ * -> y = 1;
+ */
+ scope_amount = get_indent() + (iscase /* XXX */
+ ? ind_case_code : ind_scopedecl_code);
+ lookfor = ind_case_break ? LOOKFOR_NOBREAK : LOOKFOR_ANY;
+ continue;
+ }
+
+ /*
+ * Looking for a switch() label or C++ scope declaration,
+ * ignore other lines, skip {}-blocks.
+ */
+ if (lookfor == LOOKFOR_CASE || lookfor == LOOKFOR_SCOPEDECL)
+ {
+ if (find_last_paren(l, '{', '}') && (trypos =
+ find_start_brace(ind_maxcomment)) != NULL)
+ curwin->w_cursor.lnum = trypos->lnum + 1;
+ continue;
+ }
+
+ /*
+ * Ignore jump labels with nothing after them.
+ */
+ if (cin_islabel(ind_maxcomment))
+ {
+ l = after_label(ml_get_curline());
+ if (l == NULL || cin_nocode(l))
+ continue;
+ }
+
+ /*
+ * Ignore #defines, #if, etc.
+ * Ignore comment and empty lines.
+ * (need to get the line again, cin_islabel() may have
+ * unlocked it)
+ */
+ l = ml_get_curline();
+ if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum)
+ || cin_nocode(l))
+ continue;
+
+ /*
+ * Are we at the start of a cpp base class declaration or
+ * constructor initialization?
+ */ /* XXX */
+ if (lookfor != LOOKFOR_TERM && ind_cpp_baseclass
+ && cin_is_cpp_baseclass(l, &col))
+ {
+ if (lookfor == LOOKFOR_UNTERM)
+ {
+ if (cont_amount > 0)
+ amount = cont_amount;
+ else
+ amount += ind_continuation;
+ }
+ else if (col == 0 || theline[0] == '{')
+ {
+ amount = get_indent();
+ if (find_last_paren(l, '(', ')')
+ && (trypos = find_match_paren(ind_maxparen,
+ ind_maxcomment)) != NULL)
+ amount = get_indent_lnum(trypos->lnum); /* XXX */
+ if (theline[0] != '{')
+ amount += ind_cpp_baseclass;
+ }
+ else
+ {
+ curwin->w_cursor.col = col;
+ getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL);
+ amount = (int)col;
+ }
+ break;
+ }
+ else if (lookfor == LOOKFOR_CPP_BASECLASS)
+ {
+ /* only look, whether there is a cpp base class
+ * declaration or initialization before the opening brace. */
+ if (cin_isterminated(l, TRUE, FALSE))
+ break;
+ else
+ continue;
+ }
+
+ /*
+ * What happens next depends on the line being terminated.
+ * If terminated with a ',' only consider it terminating if
+ * there is anoter unterminated statement behind, eg:
+ * 123,
+ * sizeof
+ * here
+ * Otherwise check whether it is a enumeration or structure
+ * initialisation (not indented) or a variable declaration
+ * (indented).
+ */
+ terminated = cin_isterminated(l, FALSE, TRUE);
+
+ if (terminated == 0 || (lookfor != LOOKFOR_UNTERM
+ && terminated == ','))
+ {
+ /*
+ * if we're in the middle of a paren thing,
+ * go back to the line that starts it so
+ * we can get the right prevailing indent
+ * if ( foo &&
+ * bar )
+ */
+ /*
+ * position the cursor over the rightmost paren, so that
+ * matching it will take us back to the start of the line.
+ */
+ (void)find_last_paren(l, '(', ')');
+ trypos = find_match_paren(
+ corr_ind_maxparen(ind_maxparen, &cur_curpos),
+ ind_maxcomment);
+
+ /*
+ * If we are looking for ',', we also look for matching
+ * braces.
+ */
+ if (trypos == NULL && find_last_paren(l, '{', '}'))
+ trypos = find_start_brace(ind_maxcomment);
+
+ if (trypos != NULL)
+ {
+ /*
+ * Check if we are on a case label now. This is
+ * handled above.
+ * case xx: if ( asdf &&
+ * asdf)
+ */
+ curwin->w_cursor.lnum = trypos->lnum;
+ l = ml_get_curline();
+ if (cin_iscase(l) || cin_isscopedecl(l))
+ {
+ ++curwin->w_cursor.lnum;
+ continue;
+ }
+ }
+
+ /*
+ * Skip over continuation lines to find the one to get the
+ * indent from
+ * char *usethis = "bla\
+ * bla",
+ * here;
+ */
+ if (terminated == ',')
+ {
+ while (curwin->w_cursor.lnum > 1)
+ {
+ l = ml_get(curwin->w_cursor.lnum - 1);
+ if (*l == NUL || l[STRLEN(l) - 1] != '\\')
+ break;
+ --curwin->w_cursor.lnum;
+ }
+ }
+
+ /*
+ * Get indent and pointer to text for current line,
+ * ignoring any jump label. XXX
+ */
+ cur_amount = skip_label(curwin->w_cursor.lnum,
+ &l, ind_maxcomment);
+
+ /*
+ * If this is just above the line we are indenting, and it
+ * starts with a '{', line it up with this line.
+ * while (not)
+ * -> {
+ * }
+ */
+ if (terminated != ',' && lookfor != LOOKFOR_TERM
+ && theline[0] == '{')
+ {
+ amount = cur_amount;
+ /*
+ * Only add ind_open_extra when the current line
+ * doesn't start with a '{', which must have a match
+ * in the same line (scope is the same). Probably:
+ * { 1, 2 },
+ * -> { 3, 4 }
+ */
+ if (*skipwhite(l) != '{')
+ amount += ind_open_extra;
+
+ if (ind_cpp_baseclass)
+ {
+ /* have to look back, whether it is a cpp base
+ * class declaration or initialization */
+ lookfor = LOOKFOR_CPP_BASECLASS;
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * Check if we are after an "if", "while", etc.
+ * Also allow " } else".
+ */
+ if (cin_is_cinword(l) || cin_iselse(skipwhite(l)))
+ {
+ /*
+ * Found an unterminated line after an if (), line up
+ * with the last one.
+ * if (cond)
+ * 100 +
+ * -> here;
+ */
+ if (lookfor == LOOKFOR_UNTERM
+ || lookfor == LOOKFOR_ENUM_OR_INIT)
+ {
+ if (cont_amount > 0)
+ amount = cont_amount;
+ else
+ amount += ind_continuation;
+ break;
+ }
+
+ /*
+ * If this is just above the line we are indenting, we
+ * are finished.
+ * while (not)
+ * -> here;
+ * Otherwise this indent can be used when the line
+ * before this is terminated.
+ * yyy;
+ * if (stat)
+ * while (not)
+ * xxx;
+ * -> here;
+ */
+ amount = cur_amount;
+ if (theline[0] == '{')
+ amount += ind_open_extra;
+ if (lookfor != LOOKFOR_TERM)
+ {
+ amount += ind_level + ind_no_brace;
+ break;
+ }
+
+ /*
+ * Special trick: when expecting the while () after a
+ * do, line up with the while()
+ * do
+ * x = 1;
+ * -> here
+ */
+ l = skipwhite(ml_get_curline());
+ if (cin_isdo(l))
+ {
+ if (whilelevel == 0)
+ break;
+ --whilelevel;
+ }
+
+ /*
+ * When searching for a terminated line, don't use the
+ * one between the "if" and the "else".
+ * Need to use the scope of this "else". XXX
+ * If whilelevel != 0 continue looking for a "do {".
+ */
+ if (cin_iselse(l)
+ && whilelevel == 0
+ && ((trypos = find_start_brace(ind_maxcomment))
+ == NULL
+ || find_match(LOOKFOR_IF, trypos->lnum,
+ ind_maxparen, ind_maxcomment) == FAIL))
+ break;
+ }
+
+ /*
+ * If we're below an unterminated line that is not an
+ * "if" or something, we may line up with this line or
+ * add someting for a continuation line, depending on
+ * the line before this one.
+ */
+ else
+ {
+ /*
+ * Found two unterminated lines on a row, line up with
+ * the last one.
+ * c = 99 +
+ * 100 +
+ * -> here;
+ */
+ if (lookfor == LOOKFOR_UNTERM)
+ {
+ /* When line ends in a comma add extra indent */
+ if (terminated == ',')
+ amount += ind_continuation;
+ break;
+ }
+
+ if (lookfor == LOOKFOR_ENUM_OR_INIT)
+ {
+ /* Found two lines ending in ',', lineup with the
+ * lowest one, but check for cpp base class
+ * declaration/initialization, if it is an
+ * opening brace or we are looking just for
+ * enumerations/initializations. */
+ if (terminated == ',')
+ {
+ if (ind_cpp_baseclass == 0)
+ break;
+
+ lookfor = LOOKFOR_CPP_BASECLASS;
+ continue;
+ }
+
+ /* Ignore unterminated lines in between, but
+ * reduce indent. */
+ if (amount > cur_amount)
+ amount = cur_amount;
+ }
+ else
+ {
+ /*
+ * Found first unterminated line on a row, may
+ * line up with this line, remember its indent
+ * 100 +
+ * -> here;
+ */
+ amount = cur_amount;
+
+ /*
+ * If previous line ends in ',', check whether we
+ * are in an initialization or enum
+ * struct xxx =
+ * {
+ * sizeof a,
+ * 124 };
+ * or a normal possible continuation line.
+ * but only, of no other statement has been found
+ * yet.
+ */
+ if (lookfor == LOOKFOR_INITIAL && terminated == ',')
+ {
+ lookfor = LOOKFOR_ENUM_OR_INIT;
+ cont_amount = cin_first_id_amount();
+ }
+ else
+ {
+ if (lookfor == LOOKFOR_INITIAL
+ && *l != NUL
+ && l[STRLEN(l) - 1] == '\\')
+ /* XXX */
+ cont_amount = cin_get_equal_amount(
+ curwin->w_cursor.lnum);
+ if (lookfor != LOOKFOR_TERM)
+ lookfor = LOOKFOR_UNTERM;
+ }
+ }
+ }
+ }
+
+ /*
+ * Check if we are after a while (cond);
+ * If so: Ignore until the matching "do".
+ */
+ /* XXX */
+ else if (cin_iswhileofdo(l,
+ curwin->w_cursor.lnum, ind_maxparen))
+ {
+ /*
+ * Found an unterminated line after a while ();, line up
+ * with the last one.
+ * while (cond);
+ * 100 + <- line up with this one
+ * -> here;
+ */
+ if (lookfor == LOOKFOR_UNTERM
+ || lookfor == LOOKFOR_ENUM_OR_INIT)
+ {
+ if (cont_amount > 0)
+ amount = cont_amount;
+ else
+ amount += ind_continuation;
+ break;
+ }
+
+ if (whilelevel == 0)
+ {
+ lookfor = LOOKFOR_TERM;
+ amount = get_indent(); /* XXX */
+ if (theline[0] == '{')
+ amount += ind_open_extra;
+ }
+ ++whilelevel;
+ }
+
+ /*
+ * We are after a "normal" statement.
+ * If we had another statement we can stop now and use the
+ * indent of that other statement.
+ * Otherwise the indent of the current statement may be used,
+ * search backwards for the next "normal" statement.
+ */
+ else
+ {
+ /*
+ * Skip single break line, if before a switch label. It
+ * may be lined up with the case label.
+ */
+ if (lookfor == LOOKFOR_NOBREAK
+ && cin_isbreak(skipwhite(ml_get_curline())))
+ {
+ lookfor = LOOKFOR_ANY;
+ continue;
+ }
+
+ /*
+ * Handle "do {" line.
+ */
+ if (whilelevel > 0)
+ {
+ l = cin_skipcomment(ml_get_curline());
+ if (cin_isdo(l))
+ {
+ amount = get_indent(); /* XXX */
+ --whilelevel;
+ continue;
+ }
+ }
+
+ /*
+ * Found a terminated line above an unterminated line. Add
+ * the amount for a continuation line.
+ * x = 1;
+ * y = foo +
+ * -> here;
+ * or
+ * int x = 1;
+ * int foo,
+ * -> here;
+ */
+ if (lookfor == LOOKFOR_UNTERM
+ || lookfor == LOOKFOR_ENUM_OR_INIT)
+ {
+ if (cont_amount > 0)
+ amount = cont_amount;
+ else
+ amount += ind_continuation;
+ break;
+ }
+
+ /*
+ * Found a terminated line above a terminated line or "if"
+ * etc. line. Use the amount of the line below us.
+ * x = 1; x = 1;
+ * if (asdf) y = 2;
+ * while (asdf) ->here;
+ * here;
+ * ->foo;
+ */
+ if (lookfor == LOOKFOR_TERM)
+ {
+ if (!lookfor_break && whilelevel == 0)
+ break;
+ }
+
+ /*
+ * First line above the one we're indenting is terminated.
+ * To know what needs to be done look further backward for
+ * a terminated line.
+ */
+ else
+ {
+ /*
+ * position the cursor over the rightmost paren, so
+ * that matching it will take us back to the start of
+ * the line. Helps for:
+ * func(asdr,
+ * asdfasdf);
+ * here;
+ */
+term_again:
+ l = ml_get_curline();
+ if (find_last_paren(l, '(', ')')
+ && (trypos = find_match_paren(ind_maxparen,
+ ind_maxcomment)) != NULL)
+ {
+ /*
+ * Check if we are on a case label now. This is
+ * handled above.
+ * case xx: if ( asdf &&
+ * asdf)
+ */
+ curwin->w_cursor.lnum = trypos->lnum;
+ l = ml_get_curline();
+ if (cin_iscase(l) || cin_isscopedecl(l))
+ {
+ ++curwin->w_cursor.lnum;
+ continue;
+ }
+ }
+
+ /* When aligning with the case statement, don't align
+ * with a statement after it.
+ * case 1: { <-- don't use this { position
+ * stat;
+ * }
+ * case 2:
+ * stat;
+ * }
+ */
+ iscase = (ind_keep_case_label && cin_iscase(l));
+
+ /*
+ * Get indent and pointer to text for current line,
+ * ignoring any jump label.
+ */
+ amount = skip_label(curwin->w_cursor.lnum,
+ &l, ind_maxcomment);
+
+ if (theline[0] == '{')
+ amount += ind_open_extra;
+ /* See remark above: "Only add ind_open_extra.." */
+ if (*skipwhite(l) == '{')
+ amount -= ind_open_extra;
+ lookfor = iscase ? LOOKFOR_ANY : LOOKFOR_TERM;
+
+ /*
+ * If we're at the end of a block, skip to the start of
+ * that block.
+ */
+ curwin->w_cursor.col = 0;
+ if (*cin_skipcomment(l) == '}'
+ && (trypos = find_start_brace(ind_maxcomment))
+ != NULL) /* XXX */
+ {
+ curwin->w_cursor.lnum = trypos->lnum;
+ /* if not "else {" check for terminated again */
+ /* but skip block for "} else {" */
+ l = cin_skipcomment(ml_get_curline());
+ if (*l == '}' || !cin_iselse(l))
+ goto term_again;
+ ++curwin->w_cursor.lnum;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* add extra indent for a comment */
+ if (cin_iscomment(theline))
+ amount += ind_comment;
+ }
+
+ /*
+ * ok -- we're not inside any sort of structure at all!
+ *
+ * this means we're at the top level, and everything should
+ * basically just match where the previous line is, except
+ * for the lines immediately following a function declaration,
+ * which are K&R-style parameters and need to be indented.
+ */
+ else
+ {
+ /*
+ * if our line starts with an open brace, forget about any
+ * prevailing indent and make sure it looks like the start
+ * of a function
+ */
+
+ if (theline[0] == '{')
+ {
+ amount = ind_first_open;
+ }
+
+ /*
+ * If the NEXT line is a function declaration, the current
+ * line needs to be indented as a function type spec.
+ * Don't do this if the current line looks like a comment
+ * or if the current line is terminated, ie. ends in ';'.
+ */
+ else if (cur_curpos.lnum < curbuf->b_ml.ml_line_count
+ && !cin_nocode(theline)
+ && !cin_ends_in(theline, (char_u *)":", NULL)
+ && !cin_ends_in(theline, (char_u *)",", NULL)
+ && cin_isfuncdecl(NULL, cur_curpos.lnum + 1)
+ && !cin_isterminated(theline, FALSE, TRUE))
+ {
+ amount = ind_func_type;
+ }
+ else
+ {
+ amount = 0;
+ curwin->w_cursor = cur_curpos;
+
+ /* search backwards until we find something we recognize */
+
+ while (curwin->w_cursor.lnum > 1)
+ {
+ curwin->w_cursor.lnum--;
+ curwin->w_cursor.col = 0;
+
+ l = ml_get_curline();
+
+ /*
+ * If we're in a comment now, skip to the start of the comment.
+ */ /* XXX */
+ if ((trypos = find_start_comment(ind_maxcomment)) != NULL)
+ {
+ curwin->w_cursor.lnum = trypos->lnum + 1;
+ continue;
+ }
+
+ /*
+ * Are we at the start of a cpp base class declaration or constructor
+ * initialization?
+ */ /* XXX */
+ if (ind_cpp_baseclass != 0 && theline[0] != '{'
+ && cin_is_cpp_baseclass(l, &col))
+ {
+ if (col == 0)
+ {
+ amount = get_indent() + ind_cpp_baseclass; /* XXX */
+ if (find_last_paren(l, '(', ')')
+ && (trypos = find_match_paren(ind_maxparen,
+ ind_maxcomment)) != NULL)
+ amount = get_indent_lnum(trypos->lnum)
+ + ind_cpp_baseclass; /* XXX */
+ }
+ else
+ {
+ curwin->w_cursor.col = col;
+ getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL);
+ amount = (int)col;
+ }
+ break;
+ }
+
+ /*
+ * Skip preprocessor directives and blank lines.
+ */
+ if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum))
+ continue;
+
+ if (cin_nocode(l))
+ continue;
+
+ /*
+ * If the previous line ends in ',', use one level of
+ * indentation:
+ * int foo,
+ * bar;
+ * do this before checking for '}' in case of eg.
+ * enum foobar
+ * {
+ * ...
+ * } foo,
+ * bar;
+ */
+ n = 0;
+ if (cin_ends_in(l, (char_u *)",", NULL)
+ || (*l != NUL && (n = l[STRLEN(l) - 1]) == '\\'))
+ {
+ /* take us back to opening paren */
+ if (find_last_paren(l, '(', ')')
+ && (trypos = find_match_paren(ind_maxparen,
+ ind_maxcomment)) != NULL)
+ curwin->w_cursor.lnum = trypos->lnum;
+
+ /* For a line ending in ',' that is a continuation line go
+ * back to the first line with a backslash:
+ * char *foo = "bla\
+ * bla",
+ * here;
+ */
+ while (n == 0 && curwin->w_cursor.lnum > 1)
+ {
+ l = ml_get(curwin->w_cursor.lnum - 1);
+ if (*l == NUL || l[STRLEN(l) - 1] != '\\')
+ break;
+ --curwin->w_cursor.lnum;
+ }
+
+ amount = get_indent(); /* XXX */
+
+ if (amount == 0)
+ amount = cin_first_id_amount();
+ if (amount == 0)
+ amount = ind_continuation;
+ break;
+ }
+
+ /*
+ * If the line looks like a function declaration, and we're
+ * not in a comment, put it the left margin.
+ */
+ if (cin_isfuncdecl(NULL, cur_curpos.lnum)) /* XXX */
+ break;
+ l = ml_get_curline();
+
+ /*
+ * Finding the closing '}' of a previous function. Put
+ * current line at the left margin. For when 'cino' has "fs".
+ */
+ if (*skipwhite(l) == '}')
+ break;
+
+ /* (matching {)
+ * If the previous line ends on '};' (maybe followed by
+ * comments) align at column 0. For example:
+ * char *string_array[] = { "foo",
+ * / * x * / "b};ar" }; / * foobar * /
+ */
+ if (cin_ends_in(l, (char_u *)"};", NULL))
+ break;
+
+ /*
+ * If the PREVIOUS line is a function declaration, the current
+ * line (and the ones that follow) needs to be indented as
+ * parameters.
+ */
+ if (cin_isfuncdecl(&l, curwin->w_cursor.lnum))
+ {
+ amount = ind_param;
+ break;
+ }
+
+ /*
+ * If the previous line ends in ';' and the line before the
+ * previous line ends in ',' or '\', ident to column zero:
+ * int foo,
+ * bar;
+ * indent_to_0 here;
+ */
+ if (cin_ends_in(l, (char_u*)";", NULL))
+ {
+ l = ml_get(curwin->w_cursor.lnum - 1);
+ if (cin_ends_in(l, (char_u *)",", NULL)
+ || (*l != NUL && l[STRLEN(l) - 1] == '\\'))
+ break;
+ l = ml_get_curline();
+ }
+
+ /*
+ * Doesn't look like anything interesting -- so just
+ * use the indent of this line.
+ *
+ * Position the cursor over the rightmost paren, so that
+ * matching it will take us back to the start of the line.
+ */
+ find_last_paren(l, '(', ')');
+
+ if ((trypos = find_match_paren(ind_maxparen,
+ ind_maxcomment)) != NULL)
+ curwin->w_cursor.lnum = trypos->lnum;
+ amount = get_indent(); /* XXX */
+ break;
+ }
+
+ /* add extra indent for a comment */
+ if (cin_iscomment(theline))
+ amount += ind_comment;
+
+ /* add extra indent if the previous line ended in a backslash:
+ * "asdfasdf\
+ * here";
+ * char *foo = "asdf\
+ * here";
+ */
+ if (cur_curpos.lnum > 1)
+ {
+ l = ml_get(cur_curpos.lnum - 1);
+ if (*l != NUL && l[STRLEN(l) - 1] == '\\')
+ {
+ cur_amount = cin_get_equal_amount(cur_curpos.lnum - 1);
+ if (cur_amount > 0)
+ amount = cur_amount;
+ else if (cur_amount == 0)
+ amount += ind_continuation;
+ }
+ }
+ }
+ }
+
+theend:
+ /* put the cursor back where it belongs */
+ curwin->w_cursor = cur_curpos;
+
+ vim_free(linecopy);
+
+ if (amount < 0)
+ return 0;
+ return amount;
+}
+
+ static int
+find_match(lookfor, ourscope, ind_maxparen, ind_maxcomment)
+ int lookfor;
+ linenr_T ourscope;
+ int ind_maxparen;
+ int ind_maxcomment;
+{
+ char_u *look;
+ pos_T *theirscope;
+ char_u *mightbeif;
+ int elselevel;
+ int whilelevel;
+
+ if (lookfor == LOOKFOR_IF)
+ {
+ elselevel = 1;
+ whilelevel = 0;
+ }
+ else
+ {
+ elselevel = 0;
+ whilelevel = 1;
+ }
+
+ curwin->w_cursor.col = 0;
+
+ while (curwin->w_cursor.lnum > ourscope + 1)
+ {
+ curwin->w_cursor.lnum--;
+ curwin->w_cursor.col = 0;
+
+ look = cin_skipcomment(ml_get_curline());
+ if (cin_iselse(look)
+ || cin_isif(look)
+ || cin_isdo(look) /* XXX */
+ || cin_iswhileofdo(look, curwin->w_cursor.lnum, ind_maxparen))
+ {
+ /*
+ * if we've gone outside the braces entirely,
+ * we must be out of scope...
+ */
+ theirscope = find_start_brace(ind_maxcomment); /* XXX */
+ if (theirscope == NULL)
+ break;
+
+ /*
+ * and if the brace enclosing this is further
+ * back than the one enclosing the else, we're
+ * out of luck too.
+ */
+ if (theirscope->lnum < ourscope)
+ break;
+
+ /*
+ * and if they're enclosed in a *deeper* brace,
+ * then we can ignore it because it's in a
+ * different scope...
+ */
+ if (theirscope->lnum > ourscope)
+ continue;
+
+ /*
+ * if it was an "else" (that's not an "else if")
+ * then we need to go back to another if, so
+ * increment elselevel
+ */
+ look = cin_skipcomment(ml_get_curline());
+ if (cin_iselse(look))
+ {
+ mightbeif = cin_skipcomment(look + 4);
+ if (!cin_isif(mightbeif))
+ ++elselevel;
+ continue;
+ }
+
+ /*
+ * if it was a "while" then we need to go back to
+ * another "do", so increment whilelevel. XXX
+ */
+ if (cin_iswhileofdo(look, curwin->w_cursor.lnum, ind_maxparen))
+ {
+ ++whilelevel;
+ continue;
+ }
+
+ /* If it's an "if" decrement elselevel */
+ look = cin_skipcomment(ml_get_curline());
+ if (cin_isif(look))
+ {
+ elselevel--;
+ /*
+ * When looking for an "if" ignore "while"s that
+ * get in the way.
+ */
+ if (elselevel == 0 && lookfor == LOOKFOR_IF)
+ whilelevel = 0;
+ }
+
+ /* If it's a "do" decrement whilelevel */
+ if (cin_isdo(look))
+ whilelevel--;
+
+ /*
+ * if we've used up all the elses, then
+ * this must be the if that we want!
+ * match the indent level of that if.
+ */
+ if (elselevel <= 0 && whilelevel <= 0)
+ {
+ return OK;
+ }
+ }
+ }
+ return FAIL;
+}
+
+# if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Get indent level from 'indentexpr'.
+ */
+ int
+get_expr_indent()
+{
+ int indent;
+ pos_T pos;
+ int save_State;
+
+ pos = curwin->w_cursor;
+ set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
+ ++sandbox;
+ indent = eval_to_number(curbuf->b_p_inde);
+ --sandbox;
+
+ /* Restore the cursor position so that 'indentexpr' doesn't need to.
+ * Pretend to be in Insert mode, allow cursor past end of line for "o"
+ * command. */
+ save_State = State;
+ State = INSERT;
+ curwin->w_cursor = pos;
+ check_cursor();
+ State = save_State;
+
+ /* If there is an error, just keep the current indent. */
+ if (indent < 0)
+ indent = get_indent();
+
+ return indent;
+}
+# endif
+
+#endif /* FEAT_CINDENT */
+
+#if defined(FEAT_LISP) || defined(PROTO)
+
+static int lisp_match __ARGS((char_u *p));
+
+ static int
+lisp_match(p)
+ char_u *p;
+{
+ char_u buf[LSIZE];
+ int len;
+ char_u *word = p_lispwords;
+
+ while (*word != NUL)
+ {
+ (void)copy_option_part(&word, buf, LSIZE, ",");
+ len = (int)STRLEN(buf);
+ if (STRNCMP(buf, p, len) == 0 && p[len] == ' ')
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * When 'p' is present in 'cpoptions, a Vi compatible method is used.
+ * The incompatible newer method is quite a bit better at indenting
+ * code in lisp-like languages than the traditional one; it's still
+ * mostly heuristics however -- Dirk van Deun, dirk@rave.org
+ *
+ * TODO:
+ * Findmatch() should be adapted for lisp, also to make showmatch
+ * work correctly: now (v5.3) it seems all C/C++ oriented:
+ * - it does not recognize the #\( and #\) notations as character literals
+ * - it doesn't know about comments starting with a semicolon
+ * - it incorrectly interprets '(' as a character literal
+ * All this messes up get_lisp_indent in some rare cases.
+ */
+ int
+get_lisp_indent()
+{
+ pos_T *pos, realpos;
+ int amount;
+ char_u *that;
+ colnr_T col;
+ colnr_T firsttry;
+ int parencount, quotecount;
+ int vi_lisp;
+
+ /* Set vi_lisp to use the vi-compatible method */
+ vi_lisp = (vim_strchr(p_cpo, CPO_LISP) != NULL);
+
+ realpos = curwin->w_cursor;
+ curwin->w_cursor.col = 0;
+
+ if ((pos = findmatch(NULL, '(')) != NULL)
+ {
+ /* Extra trick: Take the indent of the first previous non-white
+ * line that is at the same () level. */
+ amount = -1;
+ parencount = 0;
+
+ while (--curwin->w_cursor.lnum >= pos->lnum)
+ {
+ if (linewhite(curwin->w_cursor.lnum))
+ continue;
+ for (that = ml_get_curline(); *that != NUL; ++that)
+ {
+ if (*that == ';')
+ {
+ while (*(that + 1) != NUL)
+ ++that;
+ continue;
+ }
+ if (*that == '\\')
+ {
+ if (*(that + 1) != NUL)
+ ++that;
+ continue;
+ }
+ if (*that == '"' && *(that + 1) != NUL)
+ {
+ that++;
+ while (*that && (*that != '"' || *(that - 1) == '\\'))
+ ++that;
+ }
+ if (*that == '(')
+ ++parencount;
+ else if (*that == ')')
+ --parencount;
+ }
+ if (parencount == 0)
+ {
+ amount = get_indent();
+ break;
+ }
+ }
+
+ if (amount == -1)
+ {
+ curwin->w_cursor.lnum = pos->lnum;
+ curwin->w_cursor.col = pos->col;
+ col = pos->col;
+
+ that = ml_get_curline();
+
+ if (vi_lisp && get_indent() == 0)
+ amount = 2;
+ else
+ {
+ amount = 0;
+ while (*that && col)
+ {
+ amount += lbr_chartabsize_adv(&that, (colnr_T)amount);
+ col--;
+ }
+
+ /*
+ * Some keywords require "body" indenting rules (the
+ * non-standard-lisp ones are Scheme special forms):
+ *
+ * (let ((a 1)) instead (let ((a 1))
+ * (...)) of (...))
+ */
+
+ if (!vi_lisp && *that == '(' && lisp_match(that + 1))
+ amount += 2;
+ else
+ {
+ that++;
+ amount++;
+ firsttry = amount;
+
+ while (vim_iswhite(*that))
+ {
+ amount += lbr_chartabsize(that, (colnr_T)amount);
+ ++that;
+ }
+
+ if (*that && *that != ';') /* not a comment line */
+ {
+ /* test *that != '(' to accomodate first let/do
+ * argument if it is more than one line */
+ if (!vi_lisp && *that != '(')
+ firsttry++;
+
+ parencount = 0;
+ quotecount = 0;
+
+ if (vi_lisp
+ || (*that != '"'
+ && *that != '\''
+ && *that != '#'
+ && (*that < '0' || *that > '9')))
+ {
+ while (*that
+ && (!vim_iswhite(*that)
+ || quotecount
+ || parencount)
+ && (!(*that == '('
+ && !quotecount
+ && !parencount
+ && vi_lisp)))
+ {
+ if (*that == '"')
+ quotecount = !quotecount;
+ if (*that == '(' && !quotecount)
+ ++parencount;
+ if (*that == ')' && !quotecount)
+ --parencount;
+ if (*that == '\\' && *(that+1) != NUL)
+ amount += lbr_chartabsize_adv(&that,
+ (colnr_T)amount);
+ amount += lbr_chartabsize_adv(&that,
+ (colnr_T)amount);
+ }
+ }
+ while (vim_iswhite(*that))
+ {
+ amount += lbr_chartabsize(that, (colnr_T)amount);
+ that++;
+ }
+ if (!*that || *that == ';')
+ amount = firsttry;
+ }
+ }
+ }
+ }
+ }
+ else
+ amount = 0; /* no matching '(' found, use zero indent */
+
+ curwin->w_cursor = realpos;
+
+ return amount;
+}
+#endif /* FEAT_LISP */
+
+ void
+prepare_to_exit()
+{
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ gui.dying = TRUE;
+ out_trash(); /* trash any pending output */
+ }
+ else
+#endif
+ {
+ windgoto((int)Rows - 1, 0);
+
+ /*
+ * Switch terminal mode back now, so messages end up on the "normal"
+ * screen (if there are two screens).
+ */
+ settmode(TMODE_COOK);
+#ifdef WIN3264
+ if (can_end_termcap_mode(FALSE) == TRUE)
+#endif
+ stoptermcap();
+ out_flush();
+ }
+}
+
+/*
+ * Preserve files and exit.
+ * When called IObuff must contain a message.
+ */
+ void
+preserve_exit()
+{
+ buf_T *buf;
+
+ prepare_to_exit();
+
+ out_str(IObuff);
+ screen_start(); /* don't know where cursor is now */
+ out_flush();
+
+ ml_close_notmod(); /* close all not-modified buffers */
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL)
+ {
+ OUT_STR(_("Vim: preserving files...\n"));
+ screen_start(); /* don't know where cursor is now */
+ out_flush();
+ ml_sync_all(FALSE, FALSE); /* preserve all swap files */
+ break;
+ }
+ }
+
+ ml_close_all(FALSE); /* close all memfiles, without deleting */
+
+ OUT_STR(_("Vim: Finished.\n"));
+
+ getout(1);
+}
+
+/*
+ * return TRUE if "fname" exists.
+ */
+ int
+vim_fexists(fname)
+ char_u *fname;
+{
+ struct stat st;
+
+ if (mch_stat((char *)fname, &st))
+ return FALSE;
+ return TRUE;
+}
+
+/*
+ * Check for CTRL-C pressed, but only once in a while.
+ * Should be used instead of ui_breakcheck() for functions that check for
+ * each line in the file. Calling ui_breakcheck() each time takes too much
+ * time, because it can be a system call.
+ */
+
+#ifndef BREAKCHECK_SKIP
+# ifdef FEAT_GUI /* assume the GUI only runs on fast computers */
+# define BREAKCHECK_SKIP 200
+# else
+# define BREAKCHECK_SKIP 32
+# endif
+#endif
+
+static int breakcheck_count = 0;
+
+ void
+line_breakcheck()
+{
+ if (++breakcheck_count >= BREAKCHECK_SKIP)
+ {
+ breakcheck_count = 0;
+ ui_breakcheck();
+ }
+}
+
+/*
+ * Like line_breakcheck() but check 10 times less often.
+ */
+ void
+fast_breakcheck()
+{
+ if (++breakcheck_count >= BREAKCHECK_SKIP * 10)
+ {
+ breakcheck_count = 0;
+ ui_breakcheck();
+ }
+}
+
+/*
+ * Expand wildcards. Calls gen_expand_wildcards() and removes files matching
+ * 'wildignore'.
+ */
+ int
+expand_wildcards(num_pat, pat, num_file, file, flags)
+ int num_pat; /* number of input patterns */
+ char_u **pat; /* array of input patterns */
+ int *num_file; /* resulting number of files */
+ char_u ***file; /* array of resulting files */
+ int flags; /* EW_DIR, etc. */
+{
+ int retval;
+ int i, j;
+ char_u *p;
+ int non_suf_match; /* number without matching suffix */
+
+ retval = gen_expand_wildcards(num_pat, pat, num_file, file, flags);
+
+ /* When keeping all matches, return here */
+ if (flags & EW_KEEPALL)
+ return retval;
+
+#ifdef FEAT_WILDIGN
+ /*
+ * Remove names that match 'wildignore'.
+ */
+ if (*p_wig)
+ {
+ char_u *ffname;
+
+ /* check all files in (*file)[] */
+ for (i = 0; i < *num_file; ++i)
+ {
+ ffname = FullName_save((*file)[i], FALSE);
+ if (ffname == NULL) /* out of memory */
+ break;
+# ifdef VMS
+ vms_remove_version(ffname);
+# endif
+ if (match_file_list(p_wig, (*file)[i], ffname))
+ {
+ /* remove this matching file from the list */
+ vim_free((*file)[i]);
+ for (j = i; j + 1 < *num_file; ++j)
+ (*file)[j] = (*file)[j + 1];
+ --*num_file;
+ --i;
+ }
+ vim_free(ffname);
+ }
+ }
+#endif
+
+ /*
+ * Move the names where 'suffixes' match to the end.
+ */
+ if (*num_file > 1)
+ {
+ non_suf_match = 0;
+ for (i = 0; i < *num_file; ++i)
+ {
+ if (!match_suffix((*file)[i]))
+ {
+ /*
+ * Move the name without matching suffix to the front
+ * of the list.
+ */
+ p = (*file)[i];
+ for (j = i; j > non_suf_match; --j)
+ (*file)[j] = (*file)[j - 1];
+ (*file)[non_suf_match++] = p;
+ }
+ }
+ }
+
+ return retval;
+}
+
+/*
+ * Return TRUE if "fname" matches with an entry in 'suffixes'.
+ */
+ int
+match_suffix(fname)
+ char_u *fname;
+{
+ int fnamelen, setsuflen;
+ char_u *setsuf;
+#define MAXSUFLEN 30 /* maximum length of a file suffix */
+ char_u suf_buf[MAXSUFLEN];
+
+ fnamelen = (int)STRLEN(fname);
+ setsuflen = 0;
+ for (setsuf = p_su; *setsuf; )
+ {
+ setsuflen = copy_option_part(&setsuf, suf_buf, MAXSUFLEN, ".,");
+ if (fnamelen >= setsuflen
+ && fnamencmp(suf_buf, fname + fnamelen - setsuflen,
+ (size_t)setsuflen) == 0)
+ break;
+ setsuflen = 0;
+ }
+ return (setsuflen != 0);
+}
+
+#if !defined(NO_EXPANDPATH) || defined(PROTO)
+
+# ifdef VIM_BACKTICK
+static int vim_backtick __ARGS((char_u *p));
+static int expand_backtick __ARGS((garray_T *gap, char_u *pat, int flags));
+# endif
+
+# if defined(MSDOS) || defined(FEAT_GUI_W16) || defined(WIN3264)
+/*
+ * File name expansion code for MS-DOS, Win16 and Win32. It's here because
+ * it's shared between these systems.
+ */
+# if defined(DJGPP) || defined(PROTO)
+# define _cdecl /* DJGPP doesn't have this */
+# else
+# ifdef __BORLANDC__
+# define _cdecl _RTLENTRYF
+# endif
+# endif
+
+/*
+ * comparison function for qsort in dos_expandpath()
+ */
+ static int _cdecl
+pstrcmp(const void *a, const void *b)
+{
+ return (pathcmp(*(char **)a, *(char **)b));
+}
+
+# ifndef WIN3264
+ static void
+namelowcpy(
+ char_u *d,
+ char_u *s)
+{
+# ifdef DJGPP
+ if (USE_LONG_FNAME) /* don't lower case on Windows 95/NT systems */
+ while (*s)
+ *d++ = *s++;
+ else
+# endif
+ while (*s)
+ *d++ = TOLOWER_LOC(*s++);
+ *d = NUL;
+}
+# endif
+
+/*
+ * Recursively build up a list of files in "gap" matching the first wildcard
+ * in `path'. Called by expand_wildcards().
+ * Return the number of matches found.
+ * "path" has backslashes before chars that are not to be expanded, starting
+ * at "path[wildoff]".
+ */
+ static int
+dos_expandpath(
+ garray_T *gap,
+ char_u *path,
+ int wildoff,
+ int flags) /* EW_* flags */
+{
+ char_u *buf;
+ char_u *path_end;
+ char_u *p, *s, *e;
+ int start_len = gap->ga_len;
+ int ok;
+#ifdef WIN3264
+ WIN32_FIND_DATA fb;
+ HANDLE hFind = (HANDLE)0;
+# ifdef FEAT_MBYTE
+ WIN32_FIND_DATAW wfb;
+ WCHAR *wn = NULL; /* UCS-2 name, NULL when not used. */
+# endif
+#else
+ struct ffblk fb;
+#endif
+ int matches;
+ int starts_with_dot;
+ int len;
+ char_u *pat;
+ regmatch_T regmatch;
+ char_u *matchname;
+
+ /* make room for file name */
+ buf = alloc((unsigned int)STRLEN(path) + BASENAMELEN + 5);
+ if (buf == NULL)
+ return 0;
+
+ /*
+ * Find the first part in the path name that contains a wildcard or a ~1.
+ * Copy it into buf, including the preceding characters.
+ */
+ p = buf;
+ s = buf;
+ e = NULL;
+ path_end = path;
+ while (*path_end != NUL)
+ {
+ /* May ignore a wildcard that has a backslash before it; it will
+ * be removed by rem_backslash() or file_pat_to_reg_pat() below. */
+ if (path_end >= path + wildoff && rem_backslash(path_end))
+ *p++ = *path_end++;
+ else if (*path_end == '\\' || *path_end == ':' || *path_end == '/')
+ {
+ if (e != NULL)
+ break;
+ s = p + 1;
+ }
+ else if (path_end >= path + wildoff
+ && vim_strchr((char_u *)"*?[~", *path_end) != NULL)
+ e = p;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ len = (*mb_ptr2len_check)(path_end);
+ STRNCPY(p, path_end, len);
+ p += len;
+ path_end += len;
+ }
+ else
+#endif
+ *p++ = *path_end++;
+ }
+ e = p;
+ *e = NUL;
+
+ /* now we have one wildcard component between s and e */
+ /* Remove backslashes between "wildoff" and the start of the wildcard
+ * component. */
+ for (p = buf + wildoff; p < s; ++p)
+ if (rem_backslash(p))
+ {
+ STRCPY(p, p + 1);
+ --e;
+ --s;
+ }
+
+ starts_with_dot = (*s == '.');
+ pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
+ if (pat == NULL)
+ {
+ vim_free(buf);
+ return 0;
+ }
+
+ /* compile the regexp into a program */
+ regmatch.rm_ic = TRUE; /* Always ignore case */
+ regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
+ vim_free(pat);
+
+ if (regmatch.regprog == NULL)
+ {
+ vim_free(buf);
+ return 0;
+ }
+
+ /* remember the pattern or file name being looked for */
+ matchname = vim_strsave(s);
+
+ /* Scan all files in the directory with "dir/ *.*" */
+ STRCPY(s, "*.*");
+#ifdef WIN3264
+# ifdef FEAT_MBYTE
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+ /* The active codepage differs from 'encoding'. Attempt using the
+ * wide function. If it fails because it is not implemented fall back
+ * to the non-wide version (for Windows 98) */
+ wn = enc_to_ucs2(buf, NULL);
+ if (wn != NULL)
+ {
+ hFind = FindFirstFileW(wn, &wfb);
+ if (hFind == INVALID_HANDLE_VALUE
+ && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ vim_free(wn);
+ wn = NULL;
+ }
+ }
+ }
+
+ if (wn == NULL)
+# endif
+ hFind = FindFirstFile(buf, &fb);
+ ok = (hFind != INVALID_HANDLE_VALUE);
+#else
+ /* If we are expanding wildcards we try both files and directories */
+ ok = (findfirst((char *)buf, &fb,
+ (*path_end != NUL || (flags & EW_DIR)) ? FA_DIREC : 0) == 0);
+#endif
+
+ while (ok)
+ {
+#ifdef WIN3264
+# ifdef FEAT_MBYTE
+ if (wn != NULL)
+ p = ucs2_to_enc(wfb.cFileName, NULL); /* p is allocated here */
+ else
+# endif
+ p = (char_u *)fb.cFileName;
+#else
+ p = (char_u *)fb.ff_name;
+#endif
+ /* Ignore entries starting with a dot, unless when asked for. Accept
+ * all entries found with "matchname". */
+ if ((p[0] != '.' || starts_with_dot)
+ && (matchname == NULL
+ || vim_regexec(&regmatch, p, (colnr_T)0)))
+ {
+#ifdef WIN3264
+ STRCPY(s, p);
+#else
+ namelowcpy(s, p);
+#endif
+ len = (int)STRLEN(buf);
+ STRCPY(buf + len, path_end);
+ if (mch_has_exp_wildcard(path_end))
+ {
+ /* need to expand another component of the path */
+ /* remove backslashes for the remaining components only */
+ (void)dos_expandpath(gap, buf, len + 1, flags);
+ }
+ else
+ {
+ /* no more wildcards, check if there is a match */
+ /* remove backslashes for the remaining components only */
+ if (*path_end != 0)
+ backslash_halve(buf + len + 1);
+ if (mch_getperm(buf) >= 0) /* add existing file */
+ addfile(gap, buf, flags);
+ }
+ }
+
+#ifdef WIN3264
+# ifdef FEAT_MBYTE
+ if (wn != NULL)
+ {
+ vim_free(p);
+ ok = FindNextFileW(hFind, &wfb);
+ }
+ else
+# endif
+ ok = FindNextFile(hFind, &fb);
+#else
+ ok = (findnext(&fb) == 0);
+#endif
+
+ /* If no more matches and no match was used, try expanding the name
+ * itself. Finds the long name of a short filename. */
+ if (!ok && matchname != NULL && gap->ga_len == start_len)
+ {
+ STRCPY(s, matchname);
+#ifdef WIN3264
+ FindClose(hFind);
+# ifdef FEAT_MBYTE
+ if (wn != NULL)
+ {
+ vim_free(wn);
+ wn = enc_to_ucs2(buf, NULL);
+ if (wn != NULL)
+ hFind = FindFirstFileW(wn, &wfb);
+ }
+ if (wn == NULL)
+# endif
+ hFind = FindFirstFile(buf, &fb);
+ ok = (hFind != INVALID_HANDLE_VALUE);
+#else
+ ok = (findfirst((char *)buf, &fb,
+ (*path_end != NUL || (flags & EW_DIR)) ? FA_DIREC : 0) == 0);
+#endif
+ vim_free(matchname);
+ matchname = NULL;
+ }
+ }
+
+#ifdef WIN3264
+ FindClose(hFind);
+# ifdef FEAT_MBYTE
+ vim_free(wn);
+# endif
+#endif
+ vim_free(buf);
+ vim_free(regmatch.regprog);
+ vim_free(matchname);
+
+ matches = gap->ga_len - start_len;
+ if (matches > 0)
+ qsort(((char_u **)gap->ga_data) + start_len, (size_t)matches,
+ sizeof(char_u *), pstrcmp);
+ return matches;
+}
+
+ int
+mch_expandpath(
+ garray_T *gap,
+ char_u *path,
+ int flags) /* EW_* flags */
+{
+ return dos_expandpath(gap, path, 0, flags);
+}
+# endif /* MSDOS || FEAT_GUI_W16 || WIN3264 */
+
+/*
+ * Generic wildcard expansion code.
+ *
+ * Characters in "pat" that should not be expanded must be preceded with a
+ * backslash. E.g., "/path\ with\ spaces/my\*star*"
+ *
+ * Return FAIL when no single file was found. In this case "num_file" is not
+ * set, and "file" may contain an error message.
+ * Return OK when some files found. "num_file" is set to the number of
+ * matches, "file" to the array of matches. Call FreeWild() later.
+ */
+ int
+gen_expand_wildcards(num_pat, pat, num_file, file, flags)
+ int num_pat; /* number of input patterns */
+ char_u **pat; /* array of input patterns */
+ int *num_file; /* resulting number of files */
+ char_u ***file; /* array of resulting files */
+ int flags; /* EW_* flags */
+{
+ int i;
+ garray_T ga;
+ char_u *p;
+ static int recursive = FALSE;
+ int add_pat;
+
+ /*
+ * expand_env() is called to expand things like "~user". If this fails,
+ * it calls ExpandOne(), which brings us back here. In this case, always
+ * call the machine specific expansion function, if possible. Otherwise,
+ * return FAIL.
+ */
+ if (recursive)
+#ifdef SPECIAL_WILDCHAR
+ return mch_expand_wildcards(num_pat, pat, num_file, file, flags);
+#else
+ return FAIL;
+#endif
+
+#ifdef SPECIAL_WILDCHAR
+ /*
+ * If there are any special wildcard characters which we cannot handle
+ * here, call machine specific function for all the expansion. This
+ * avoids starting the shell for each argument separately.
+ * For `=expr` do use the internal function.
+ */
+ for (i = 0; i < num_pat; i++)
+ {
+ if (vim_strpbrk(pat[i], (char_u *)SPECIAL_WILDCHAR) != NULL
+# ifdef VIM_BACKTICK
+ && !(vim_backtick(pat[i]) && pat[i][1] == '=')
+# endif
+ )
+ return mch_expand_wildcards(num_pat, pat, num_file, file, flags);
+ }
+#endif
+
+ recursive = TRUE;
+
+ /*
+ * The matching file names are stored in a growarray. Init it empty.
+ */
+ ga_init2(&ga, (int)sizeof(char_u *), 30);
+
+ for (i = 0; i < num_pat; ++i)
+ {
+ add_pat = -1;
+ p = pat[i];
+
+#ifdef VIM_BACKTICK
+ if (vim_backtick(p))
+ add_pat = expand_backtick(&ga, p, flags);
+ else
+#endif
+ {
+ /*
+ * First expand environment variables, "~/" and "~user/".
+ */
+ if (vim_strpbrk(p, (char_u *)"$~") != NULL)
+ {
+ p = expand_env_save(p);
+ if (p == NULL)
+ p = pat[i];
+#ifdef UNIX
+ /*
+ * On Unix, if expand_env() can't expand an environment
+ * variable, use the shell to do that. Discard previously
+ * found file names and start all over again.
+ */
+ else if (vim_strpbrk(p, (char_u *)"$~") != NULL)
+ {
+ vim_free(p);
+ ga_clear(&ga);
+ i = mch_expand_wildcards(num_pat, pat, num_file, file,
+ flags);
+ recursive = FALSE;
+ return i;
+ }
+#endif
+ }
+
+ /*
+ * If there are wildcards: Expand file names and add each match to
+ * the list. If there is no match, and EW_NOTFOUND is given, add
+ * the pattern.
+ * If there are no wildcards: Add the file name if it exists or
+ * when EW_NOTFOUND is given.
+ */
+ if (mch_has_exp_wildcard(p))
+ add_pat = mch_expandpath(&ga, p, flags);
+ }
+
+ if (add_pat == -1 || (add_pat == 0 && (flags & EW_NOTFOUND)))
+ {
+ char_u *t = backslash_halve_save(p);
+
+#if defined(MACOS_CLASSIC)
+ slash_to_colon(t);
+#endif
+ /* When EW_NOTFOUND is used, always add files and dirs. Makes
+ * "vim c:/" work. */
+ if (flags & EW_NOTFOUND)
+ addfile(&ga, t, flags | EW_DIR | EW_FILE);
+ else if (mch_getperm(t) >= 0)
+ addfile(&ga, t, flags);
+ vim_free(t);
+ }
+
+ if (p != pat[i])
+ vim_free(p);
+ }
+
+ *num_file = ga.ga_len;
+ *file = (ga.ga_data != NULL) ? (char_u **)ga.ga_data : (char_u **)"";
+
+ recursive = FALSE;
+
+ return (ga.ga_data != NULL) ? OK : FAIL;
+}
+
+# ifdef VIM_BACKTICK
+
+/*
+ * Return TRUE if we can expand this backtick thing here.
+ */
+ static int
+vim_backtick(p)
+ char_u *p;
+{
+ return (*p == '`' && *(p + 1) != NUL && *(p + STRLEN(p) - 1) == '`');
+}
+
+/*
+ * Expand an item in `backticks` by executing it as a command.
+ * Currently only works when pat[] starts and ends with a `.
+ * Returns number of file names found.
+ */
+ static int
+expand_backtick(gap, pat, flags)
+ garray_T *gap;
+ char_u *pat;
+ int flags; /* EW_* flags */
+{
+ char_u *p;
+ char_u *cmd;
+ char_u *buffer;
+ int cnt = 0;
+ int i;
+
+ /* Create the command: lop off the backticks. */
+ cmd = vim_strnsave(pat + 1, (int)STRLEN(pat) - 2);
+ if (cmd == NULL)
+ return 0;
+
+#ifdef FEAT_EVAL
+ if (*cmd == '=') /* `={expr}`: Expand expression */
+ buffer = eval_to_string(cmd + 1, &p);
+ else
+#endif
+ buffer = get_cmd_output(cmd, (flags & EW_SILENT) ? SHELL_SILENT : 0);
+ vim_free(cmd);
+ if (buffer == NULL)
+ return 0;
+
+ cmd = buffer;
+ while (*cmd != NUL)
+ {
+ cmd = skipwhite(cmd); /* skip over white space */
+ p = cmd;
+ while (*p != NUL && *p != '\r' && *p != '\n') /* skip over entry */
+ ++p;
+ /* add an entry if it is not empty */
+ if (p > cmd)
+ {
+ i = *p;
+ *p = NUL;
+ addfile(gap, cmd, flags);
+ *p = i;
+ ++cnt;
+ }
+ cmd = p;
+ while (*cmd != NUL && (*cmd == '\r' || *cmd == '\n'))
+ ++cmd;
+ }
+
+ vim_free(buffer);
+ return cnt;
+}
+# endif /* VIM_BACKTICK */
+
+/*
+ * Add a file to a file list. Accepted flags:
+ * EW_DIR add directories
+ * EW_FILE add files
+ * EW_NOTFOUND add even when it doesn't exist
+ * EW_ADDSLASH add slash after directory name
+ */
+ void
+addfile(gap, f, flags)
+ garray_T *gap;
+ char_u *f; /* filename */
+ int flags;
+{
+ char_u *p;
+ int isdir;
+
+ /* if the file/dir doesn't exist, may not add it */
+ if (!(flags & EW_NOTFOUND) && mch_getperm(f) < 0)
+ return;
+
+#ifdef FNAME_ILLEGAL
+ /* if the file/dir contains illegal characters, don't add it */
+ if (vim_strpbrk(f, (char_u *)FNAME_ILLEGAL) != NULL)
+ return;
+#endif
+
+ isdir = mch_isdir(f);
+ if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE)))
+ return;
+
+ /* Make room for another item in the file list. */
+ if (ga_grow(gap, 1) == FAIL)
+ return;
+
+ p = alloc((unsigned)(STRLEN(f) + 1 + isdir));
+ if (p == NULL)
+ return;
+
+ STRCPY(p, f);
+#ifdef BACKSLASH_IN_FILENAME
+ slash_adjust(p);
+#endif
+ /*
+ * Append a slash or backslash after directory names if none is present.
+ */
+#ifndef DONT_ADD_PATHSEP_TO_DIR
+ if (isdir && (flags & EW_ADDSLASH))
+ add_pathsep(p);
+#endif
+ ((char_u **)gap->ga_data)[gap->ga_len++] = p;
+ --gap->ga_room;
+}
+#endif /* !NO_EXPANDPATH */
+
+#if defined(VIM_BACKTICK) || defined(FEAT_EVAL) || defined(PROTO)
+
+#ifndef SEEK_SET
+# define SEEK_SET 0
+#endif
+#ifndef SEEK_END
+# define SEEK_END 2
+#endif
+
+/*
+ * Get the stdout of an external command.
+ * Returns an allocated string, or NULL for error.
+ */
+ char_u *
+get_cmd_output(cmd, flags)
+ char_u *cmd;
+ int flags; /* can be SHELL_SILENT */
+{
+ char_u *tempname;
+ char_u *command;
+ char_u *buffer = NULL;
+ int len;
+ int i = 0;
+ FILE *fd;
+
+ if (check_restricted() || check_secure())
+ return NULL;
+
+ /* get a name for the temp file */
+ if ((tempname = vim_tempname('o')) == NULL)
+ {
+ EMSG(_(e_notmp));
+ return NULL;
+ }
+
+ /* Add the redirection stuff */
+ command = make_filter_cmd(cmd, NULL, tempname);
+ if (command == NULL)
+ goto done;
+
+ /*
+ * Call the shell to execute the command (errors are ignored).
+ * Don't check timestamps here.
+ */
+ ++no_check_timestamps;
+ call_shell(command, SHELL_DOOUT | SHELL_EXPAND | flags);
+ --no_check_timestamps;
+
+ vim_free(command);
+
+ /*
+ * read the names from the file into memory
+ */
+# ifdef VMS
+ /* created temporary file is not allways readable as binary */
+ fd = mch_fopen((char *)tempname, "r");
+# else
+ fd = mch_fopen((char *)tempname, READBIN);
+# endif
+
+ if (fd == NULL)
+ {
+ EMSG2(_(e_notopen), tempname);
+ goto done;
+ }
+
+ fseek(fd, 0L, SEEK_END);
+ len = ftell(fd); /* get size of temp file */
+ fseek(fd, 0L, SEEK_SET);
+
+ buffer = alloc(len + 1);
+ if (buffer != NULL)
+ i = (int)fread((char *)buffer, (size_t)1, (size_t)len, fd);
+ fclose(fd);
+ mch_remove(tempname);
+ if (buffer == NULL)
+ goto done;
+#ifdef VMS
+ len = i; /* VMS doesn't give us what we asked for... */
+#endif
+ if (i != len)
+ {
+ EMSG2(_(e_notread), tempname);
+ vim_free(buffer);
+ buffer = NULL;
+ }
+ else
+ buffer[len] = '\0'; /* make sure the buffer is terminated */
+
+done:
+ vim_free(tempname);
+ return buffer;
+}
+#endif
+
+/*
+ * Free the list of files returned by expand_wildcards() or other expansion
+ * functions.
+ */
+ void
+FreeWild(count, files)
+ int count;
+ char_u **files;
+{
+ if (files == NULL || count <= 0)
+ return;
+#if defined(__EMX__) && defined(__ALWAYS_HAS_TRAILING_NULL_POINTER) /* XXX */
+ /*
+ * Is this still OK for when other functions than expand_wildcards() have
+ * been used???
+ */
+ _fnexplodefree((char **)files);
+#else
+ while (count--)
+ vim_free(files[count]);
+ vim_free(files);
+#endif
+}
+
+/*
+ * return TRUE when need to go to Insert mode because of 'insertmode'.
+ * Don't do this when still processing a command or a mapping.
+ * Don't do this when inside a ":normal" command.
+ */
+ int
+goto_im()
+{
+ return (p_im && stuff_empty() && typebuf_typed());
+}
diff --git a/src/misc2.c b/src/misc2.c
new file mode 100644
index 000000000..55c44a865
--- /dev/null
+++ b/src/misc2.c
@@ -0,0 +1,5556 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * misc2.c: Various functions.
+ */
+#include "vim.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h> /* for chdir() */
+#endif
+
+#if defined(FEAT_VIRTUALEDIT) || defined(PROTO)
+static int coladvance2 __ARGS((pos_T *pos, int addspaces, int finetune, colnr_T wcol));
+
+/*
+ * Return TRUE if in the current mode we need to use virtual.
+ */
+ int
+virtual_active()
+{
+ /* While an operator is being executed we return "virtual_op", because
+ * VIsual_active has already been reset, thus we can't check for "block"
+ * being used. */
+ if (virtual_op != MAYBE)
+ return virtual_op;
+ return (ve_flags == VE_ALL
+# ifdef FEAT_VISUAL
+ || ((ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V)
+# endif
+ || ((ve_flags & VE_INSERT) && (State & INSERT)));
+}
+
+/*
+ * Get the screen position of the cursor.
+ */
+ int
+getviscol()
+{
+ colnr_T x;
+
+ getvvcol(curwin, &curwin->w_cursor, &x, NULL, NULL);
+ return (int)x;
+}
+
+/*
+ * Get the screen position of character col with a coladd in the cursor line.
+ */
+ int
+getviscol2(col, coladd)
+ colnr_T col;
+ colnr_T coladd;
+{
+ colnr_T x;
+ pos_T pos;
+
+ pos.lnum = curwin->w_cursor.lnum;
+ pos.col = col;
+ pos.coladd = coladd;
+ getvvcol(curwin, &pos, &x, NULL, NULL);
+ return (int)x;
+}
+
+/*
+ * Go to column "wcol", and add/insert white space as neccessary to get the
+ * cursor in that column.
+ * The caller must have saved the cursor line for undo!
+ */
+ int
+coladvance_force(wcol)
+ colnr_T wcol;
+{
+ int rc = coladvance2(&curwin->w_cursor, TRUE, FALSE, wcol);
+
+ if (wcol == MAXCOL)
+ curwin->w_valid &= ~VALID_VIRTCOL;
+ else
+ {
+ /* Virtcol is valid */
+ curwin->w_valid |= VALID_VIRTCOL;
+ curwin->w_virtcol = wcol;
+ }
+ return rc;
+}
+#endif
+
+/*
+ * Try to advance the Cursor to the specified screen column.
+ * If virtual editing: fine tune the cursor position.
+ * Note that all virtual positions off the end of a line should share
+ * a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)),
+ * beginning at coladd 0.
+ *
+ * return OK if desired column is reached, FAIL if not
+ */
+ int
+coladvance(wcol)
+ colnr_T wcol;
+{
+ int rc = getvpos(&curwin->w_cursor, wcol);
+
+ if (wcol == MAXCOL || rc == FAIL)
+ curwin->w_valid &= ~VALID_VIRTCOL;
+ else
+ {
+ /* Virtcol is valid */
+ curwin->w_valid |= VALID_VIRTCOL;
+ curwin->w_virtcol = wcol;
+ }
+ return rc;
+}
+
+/*
+ * Return in "pos" the position of the cursor advanced to screen column "wcol".
+ * return OK if desired column is reached, FAIL if not
+ */
+ int
+getvpos(pos, wcol)
+ pos_T *pos;
+ colnr_T wcol;
+{
+#ifdef FEAT_VIRTUALEDIT
+ return coladvance2(pos, FALSE, virtual_active(), wcol);
+}
+
+ static int
+coladvance2(pos, addspaces, finetune, wcol)
+ pos_T *pos;
+ int addspaces; /* change the text to achieve our goal? */
+ int finetune; /* change char offset for the excact column */
+ colnr_T wcol; /* column to move to */
+{
+#endif
+ int idx;
+ char_u *ptr;
+ char_u *line;
+ colnr_T col = 0;
+ int csize = 0;
+ int one_more;
+#ifdef FEAT_LINEBREAK
+ int head = 0;
+#endif
+
+ one_more = (State & INSERT) || restart_edit != NUL
+#ifdef FEAT_VISUAL
+ || (VIsual_active && *p_sel != 'o')
+#endif
+ ;
+ line = ml_get_curline();
+
+ if (wcol >= MAXCOL)
+ {
+ idx = (int)STRLEN(line) - 1 + one_more;
+ col = wcol;
+
+#ifdef FEAT_VIRTUALEDIT
+ if ((addspaces || finetune) && !VIsual_active)
+ {
+ curwin->w_curswant = linetabsize(line) + one_more;
+ if (curwin->w_curswant > 0)
+ --curwin->w_curswant;
+ }
+#endif
+ }
+ else
+ {
+#ifdef FEAT_VIRTUALEDIT
+ int width = W_WIDTH(curwin) - win_col_off(curwin);
+
+ if ((addspaces || finetune)
+ && curwin->w_p_wrap
+# ifdef FEAT_VERTSPLIT
+ && curwin->w_width != 0
+# endif
+ && wcol >= (colnr_T)width)
+ {
+ csize = linetabsize(line);
+ if (csize > 0)
+ csize--;
+
+ if (wcol / width > (colnr_T)csize / width)
+ {
+ /* In case of line wrapping don't move the cursor beyond the
+ * right screen edge. */
+ wcol = (csize / width + 1) * width - 1;
+ }
+ }
+#endif
+
+ idx = -1;
+ ptr = line;
+ while (col <= wcol && *ptr != NUL)
+ {
+ /* Count a tab for what it's worth (if list mode not on) */
+#ifdef FEAT_LINEBREAK
+ csize = win_lbr_chartabsize(curwin, ptr, col, &head);
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ ptr += (*mb_ptr2len_check)(ptr);
+ else
+# endif
+ ++ptr;
+#else
+ csize = lbr_chartabsize_adv(&ptr, col);
+#endif
+ col += csize;
+ }
+ idx = (int)(ptr - line);
+ /*
+ * Handle all the special cases. The virtual_active() check
+ * is needed to ensure that a virtual position off the end of
+ * a line has the correct indexing. The one_more comparison
+ * replaces an explicit add of one_more later on.
+ */
+ if (col > wcol || (!virtual_active() && one_more == 0))
+ {
+ idx -= 1;
+# ifdef FEAT_LINEBREAK
+ /* Don't count the chars from 'showbreak'. */
+ csize -= head;
+# endif
+ col -= csize;
+ }
+
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_active()
+ && addspaces
+ && ((col != wcol && col != wcol + 1) || csize > 1))
+ {
+ /* 'virtualedit' is set: The difference between wcol and col is
+ * filled with spaces. */
+
+ if (line[idx] == NUL)
+ {
+ /* Append spaces */
+ int correct = wcol - col;
+ char_u *newline = alloc(idx + correct + 1);
+ int t;
+
+ if (newline == NULL)
+ return FAIL;
+
+ for (t = 0; t < idx; ++t)
+ newline[t] = line[t];
+
+ for (t = 0; t < correct; ++t)
+ newline[t + idx] = ' ';
+
+ newline[idx + correct] = NUL;
+
+ ml_replace(pos->lnum, newline, FALSE);
+ changed_bytes(pos->lnum, (colnr_T)idx);
+ idx += correct;
+ col = wcol;
+ }
+ else
+ {
+ /* Break a tab */
+ int linelen = (int)STRLEN(line);
+ int correct = wcol - col - csize + 1; /* negative!! */
+ char_u *newline = alloc(linelen + csize);
+ int t, s = 0;
+ int v;
+
+ /*
+ * break a tab
+ */
+ if (newline == NULL || -correct > csize)
+ return FAIL;
+
+ for (t = 0; t < linelen; t++)
+ {
+ if (t != idx)
+ newline[s++] = line[t];
+ else
+ for (v = 0; v < csize; v++)
+ newline[s++] = ' ';
+ }
+
+ newline[linelen + csize - 1] = NUL;
+
+ ml_replace(pos->lnum, newline, FALSE);
+ changed_bytes(pos->lnum, idx);
+ idx += (csize - 1 + correct);
+ col += correct;
+ }
+ }
+#endif
+ }
+
+ if (idx < 0)
+ pos->col = 0;
+ else
+ pos->col = idx;
+
+#ifdef FEAT_VIRTUALEDIT
+ pos->coladd = 0;
+
+ if (finetune)
+ {
+ if (wcol == MAXCOL)
+ {
+ /* The width of the last character is used to set coladd. */
+ if (!one_more)
+ {
+ colnr_T scol, ecol;
+
+ getvcol(curwin, pos, &scol, NULL, &ecol);
+ pos->coladd = ecol - scol;
+ }
+ }
+ else
+ {
+ int b = (int)wcol - (int)col;
+
+ /* The difference between wcol and col is used to set coladd. */
+ if (b > 0 && b < (MAXCOL - 2 * W_WIDTH(curwin)))
+ pos->coladd = b;
+
+ col += b;
+ }
+ }
+#endif
+
+#ifdef FEAT_MBYTE
+ /* prevent cursor from moving on the trail byte */
+ if (has_mbyte)
+ mb_adjust_cursor();
+#endif
+
+ if (col < wcol)
+ return FAIL;
+ return OK;
+}
+
+/*
+ * inc(p)
+ *
+ * Increment the line pointer 'p' crossing line boundaries as necessary.
+ * Return 1 when going to the next line.
+ * Return 2 when moving forward onto a NUL at the end of the line).
+ * Return -1 when at the end of file.
+ * Return 0 otherwise.
+ */
+ int
+inc_cursor()
+{
+ return inc(&curwin->w_cursor);
+}
+
+ int
+inc(lp)
+ pos_T *lp;
+{
+ char_u *p = ml_get_pos(lp);
+
+ if (*p != NUL) /* still within line, move to next char (may be NUL) */
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int l = (*mb_ptr2len_check)(p);
+
+ lp->col += l;
+ return ((p[l] != NUL) ? 0 : 2);
+ }
+#endif
+ lp->col++;
+#ifdef FEAT_VIRTUALEDIT
+ lp->coladd = 0;
+#endif
+ return ((p[1] != NUL) ? 0 : 2);
+ }
+ if (lp->lnum != curbuf->b_ml.ml_line_count) /* there is a next line */
+ {
+ lp->col = 0;
+ lp->lnum++;
+#ifdef FEAT_VIRTUALEDIT
+ lp->coladd = 0;
+#endif
+ return 1;
+ }
+ return -1;
+}
+
+/*
+ * incl(lp): same as inc(), but skip the NUL at the end of non-empty lines
+ */
+ int
+incl(lp)
+ pos_T *lp;
+{
+ int r;
+
+ if ((r = inc(lp)) >= 1 && lp->col)
+ r = inc(lp);
+ return r;
+}
+
+/*
+ * dec(p)
+ *
+ * Decrement the line pointer 'p' crossing line boundaries as necessary.
+ * Return 1 when crossing a line, -1 when at start of file, 0 otherwise.
+ */
+ int
+dec_cursor()
+{
+ return dec(&curwin->w_cursor);
+}
+
+ int
+dec(lp)
+ pos_T *lp;
+{
+ char_u *p;
+
+#ifdef FEAT_VIRTUALEDIT
+ lp->coladd = 0;
+#endif
+ if (lp->col > 0) /* still within line */
+ {
+ lp->col--;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ p = ml_get(lp->lnum);
+ lp->col -= (*mb_head_off)(p, p + lp->col);
+ }
+#endif
+ return 0;
+ }
+ if (lp->lnum > 1) /* there is a prior line */
+ {
+ lp->lnum--;
+ p = ml_get(lp->lnum);
+ lp->col = (colnr_T)STRLEN(p);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ lp->col -= (*mb_head_off)(p, p + lp->col);
+#endif
+ return 1;
+ }
+ return -1; /* at start of file */
+}
+
+/*
+ * decl(lp): same as dec(), but skip the NUL at the end of non-empty lines
+ */
+ int
+decl(lp)
+ pos_T *lp;
+{
+ int r;
+
+ if ((r = dec(lp)) == 1 && lp->col)
+ r = dec(lp);
+ return r;
+}
+
+/*
+ * Make sure curwin->w_cursor.lnum is valid.
+ */
+ void
+check_cursor_lnum()
+{
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
+ {
+#ifdef FEAT_FOLDING
+ /* If there is a closed fold at the end of the file, put the cursor in
+ * its first line. Otherwise in the last line. */
+ if (!hasFolding(curbuf->b_ml.ml_line_count,
+ &curwin->w_cursor.lnum, NULL))
+#endif
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ }
+ if (curwin->w_cursor.lnum <= 0)
+ curwin->w_cursor.lnum = 1;
+}
+
+/*
+ * Make sure curwin->w_cursor.col is valid.
+ */
+ void
+check_cursor_col()
+{
+ colnr_T len;
+#ifdef FEAT_VIRTUALEDIT
+ colnr_T oldcol = curwin->w_cursor.col + curwin->w_cursor.coladd;
+#endif
+
+ len = (colnr_T)STRLEN(ml_get_curline());
+ if (len == 0)
+ curwin->w_cursor.col = 0;
+ else if (curwin->w_cursor.col >= len)
+ {
+ /* Allow cursor past end-of-line in Insert mode, restarting Insert
+ * mode or when in Visual mode and 'selection' isn't "old" */
+ if (State & INSERT || restart_edit
+#ifdef FEAT_VISUAL
+ || (VIsual_active && *p_sel != 'o')
+#endif
+ || virtual_active())
+ curwin->w_cursor.col = len;
+ else
+ curwin->w_cursor.col = len - 1;
+ }
+
+#ifdef FEAT_VIRTUALEDIT
+ /* If virtual editing is on, we can leave the cursor on the old position,
+ * only we must set it to virtual. But don't do it when at the end of the
+ * line. */
+ if (oldcol == MAXCOL)
+ curwin->w_cursor.coladd = 0;
+ else if (ve_flags == VE_ALL)
+ curwin->w_cursor.coladd = oldcol - curwin->w_cursor.col;
+#endif
+}
+
+/*
+ * make sure curwin->w_cursor in on a valid character
+ */
+ void
+check_cursor()
+{
+ check_cursor_lnum();
+ check_cursor_col();
+}
+
+#if defined(FEAT_TEXTOBJ) || defined(PROTO)
+/*
+ * Make sure curwin->w_cursor is not on the NUL at the end of the line.
+ * Allow it when in Visual mode and 'selection' is not "old".
+ */
+ void
+adjust_cursor_col()
+{
+ if (curwin->w_cursor.col > 0
+# ifdef FEAT_VISUAL
+ && (!VIsual_active || *p_sel == 'o')
+# endif
+ && gchar_cursor() == NUL)
+ --curwin->w_cursor.col;
+}
+#endif
+
+/*
+ * When curwin->w_leftcol has changed, adjust the cursor position.
+ * Return TRUE if the cursor was moved.
+ */
+ int
+leftcol_changed()
+{
+ long lastcol;
+ colnr_T s, e;
+ int retval = FALSE;
+
+ changed_cline_bef_curs();
+ lastcol = curwin->w_leftcol + W_WIDTH(curwin) - curwin_col_off() - 1;
+ validate_virtcol();
+
+ /*
+ * If the cursor is right or left of the screen, move it to last or first
+ * character.
+ */
+ if (curwin->w_virtcol > (colnr_T)(lastcol - p_siso))
+ {
+ retval = TRUE;
+ coladvance((colnr_T)(lastcol - p_siso));
+ }
+ else if (curwin->w_virtcol < curwin->w_leftcol + p_siso)
+ {
+ retval = TRUE;
+ (void)coladvance((colnr_T)(curwin->w_leftcol + p_siso));
+ }
+
+ /*
+ * If the start of the character under the cursor is not on the screen,
+ * advance the cursor one more char. If this fails (last char of the
+ * line) adjust the scrolling.
+ */
+ getvvcol(curwin, &curwin->w_cursor, &s, NULL, &e);
+ if (e > (colnr_T)lastcol)
+ {
+ retval = TRUE;
+ coladvance(s - 1);
+ }
+ else if (s < curwin->w_leftcol)
+ {
+ retval = TRUE;
+ if (coladvance(e + 1) == FAIL) /* there isn't another character */
+ {
+ curwin->w_leftcol = s; /* adjust w_leftcol instead */
+ changed_cline_bef_curs();
+ }
+ }
+
+ if (retval)
+ curwin->w_set_curswant = TRUE;
+ redraw_later(NOT_VALID);
+ return retval;
+}
+
+/**********************************************************************
+ * Various routines dealing with allocation and deallocation of memory.
+ */
+
+#if defined(MEM_PROFILE) || defined(PROTO)
+
+# define MEM_SIZES 8200
+static long_u mem_allocs[MEM_SIZES];
+static long_u mem_frees[MEM_SIZES];
+static long_u mem_allocated;
+static long_u mem_freed;
+static long_u mem_peak;
+static long_u num_alloc;
+static long_u num_freed;
+
+static void mem_pre_alloc_s __ARGS((size_t *sizep));
+static void mem_pre_alloc_l __ARGS((long_u *sizep));
+static void mem_post_alloc __ARGS((void **pp, size_t size));
+static void mem_pre_free __ARGS((void **pp));
+
+ static void
+mem_pre_alloc_s(sizep)
+ size_t *sizep;
+{
+ *sizep += sizeof(size_t);
+}
+
+ static void
+mem_pre_alloc_l(sizep)
+ long_u *sizep;
+{
+ *sizep += sizeof(size_t);
+}
+
+ static void
+mem_post_alloc(pp, size)
+ void **pp;
+ size_t size;
+{
+ if (*pp == NULL)
+ return;
+ size -= sizeof(size_t);
+ *(long_u *)*pp = size;
+ if (size <= MEM_SIZES-1)
+ mem_allocs[size-1]++;
+ else
+ mem_allocs[MEM_SIZES-1]++;
+ mem_allocated += size;
+ if (mem_allocated - mem_freed > mem_peak)
+ mem_peak = mem_allocated - mem_freed;
+ num_alloc++;
+ *pp = (void *)((char *)*pp + sizeof(size_t));
+}
+
+ static void
+mem_pre_free(pp)
+ void **pp;
+{
+ long_u size;
+
+ *pp = (void *)((char *)*pp - sizeof(size_t));
+ size = *(size_t *)*pp;
+ if (size <= MEM_SIZES-1)
+ mem_frees[size-1]++;
+ else
+ mem_frees[MEM_SIZES-1]++;
+ mem_freed += size;
+ num_freed++;
+}
+
+/*
+ * called on exit via atexit()
+ */
+ void
+vim_mem_profile_dump()
+{
+ int i, j;
+
+ printf("\r\n");
+ j = 0;
+ for (i = 0; i < MEM_SIZES - 1; i++)
+ {
+ if (mem_allocs[i] || mem_frees[i])
+ {
+ if (mem_frees[i] > mem_allocs[i])
+ printf("\r\n%s", _("ERROR: "));
+ printf("[%4d / %4lu-%-4lu] ", i + 1, mem_allocs[i], mem_frees[i]);
+ j++;
+ if (j > 3)
+ {
+ j = 0;
+ printf("\r\n");
+ }
+ }
+ }
+
+ i = MEM_SIZES - 1;
+ if (mem_allocs[i])
+ {
+ printf("\r\n");
+ if (mem_frees[i] > mem_allocs[i])
+ printf(_("ERROR: "));
+ printf("[>%d / %4lu-%-4lu]", i, mem_allocs[i], mem_frees[i]);
+ }
+
+ printf(_("\n[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"),
+ mem_allocated, mem_freed, mem_allocated - mem_freed, mem_peak);
+ printf(_("[calls] total re/malloc()'s %lu, total free()'s %lu\n\n"),
+ num_alloc, num_freed);
+}
+
+#endif /* MEM_PROFILE */
+
+/*
+ * Some memory is reserved for error messages and for being able to
+ * call mf_release_all(), which needs some memory for mf_trans_add().
+ */
+#if defined(MSDOS) && !defined(DJGPP)
+# define SMALL_MEM
+# define KEEP_ROOM 8192L
+#else
+# define KEEP_ROOM (2 * 8192L)
+#endif
+
+/*
+ * Note: if unsinged is 16 bits we can only allocate up to 64K with alloc().
+ * Use lalloc for larger blocks.
+ */
+ char_u *
+alloc(size)
+ unsigned size;
+{
+ return (lalloc((long_u)size, TRUE));
+}
+
+/*
+ * Allocate memory and set all bytes to zero.
+ */
+ char_u *
+alloc_clear(size)
+ unsigned size;
+{
+ char_u *p;
+
+ p = (lalloc((long_u)size, TRUE));
+ if (p != NULL)
+ (void)vim_memset(p, 0, (size_t)size);
+ return p;
+}
+
+/*
+ * alloc() with check for maximum line length
+ */
+ char_u *
+alloc_check(size)
+ unsigned size;
+{
+#if !defined(UNIX) && !defined(__EMX__)
+ if (sizeof(int) == 2 && size > 0x7fff)
+ {
+ /* Don't hide this message */
+ emsg_silent = 0;
+ EMSG(_("E340: Line is becoming too long"));
+ return NULL;
+ }
+#endif
+ return (lalloc((long_u)size, TRUE));
+}
+
+/*
+ * Allocate memory like lalloc() and set all bytes to zero.
+ */
+ char_u *
+lalloc_clear(size, message)
+ long_u size;
+ int message;
+{
+ char_u *p;
+
+ p = (lalloc(size, message));
+ if (p != NULL)
+ (void)vim_memset(p, 0, (size_t)size);
+ return p;
+}
+
+/*
+ * Low level memory allocation function.
+ * This is used often, KEEP IT FAST!
+ */
+ char_u *
+lalloc(size, message)
+ long_u size;
+ int message;
+{
+ char_u *p; /* pointer to new storage space */
+ static int releasing = FALSE; /* don't do mf_release_all() recursive */
+ int try_again;
+#if defined(HAVE_AVAIL_MEM) && !defined(SMALL_MEM)
+ static long_u allocated = 0; /* allocated since last avail check */
+#endif
+
+ /* Safety check for allocating zero bytes */
+ if (size == 0)
+ {
+ /* Don't hide this message */
+ emsg_silent = 0;
+ EMSGN(_("E341: Internal error: lalloc(%ld, )"), size);
+ return NULL;
+ }
+
+#ifdef MEM_PROFILE
+ mem_pre_alloc_l(&size);
+#endif
+
+#if defined(MSDOS) && !defined(DJGPP)
+ if (size >= 0xfff0) /* in MSDOS we can't deal with >64K blocks */
+ p = NULL;
+ else
+#endif
+
+ /*
+ * Loop when out of memory: Try to release some memfile blocks and
+ * if some blocks are released call malloc again.
+ */
+ for (;;)
+ {
+ /*
+ * Handle three kind of systems:
+ * 1. No check for available memory: Just return.
+ * 2. Slow check for available memory: call mch_avail_mem() after
+ * allocating KEEP_ROOM amount of memory.
+ * 3. Strict check for available memory: call mch_avail_mem()
+ */
+ if ((p = (char_u *)malloc((size_t)size)) != NULL)
+ {
+#ifndef HAVE_AVAIL_MEM
+ /* 1. No check for available memory: Just return. */
+ goto theend;
+#else
+# ifndef SMALL_MEM
+ /* 2. Slow check for available memory: call mch_avail_mem() after
+ * allocating (KEEP_ROOM / 2) amount of memory. */
+ allocated += size;
+ if (allocated < KEEP_ROOM / 2)
+ goto theend;
+ allocated = 0;
+# endif
+ /* 3. check for available memory: call mch_avail_mem() */
+ if (mch_avail_mem(TRUE) < KEEP_ROOM && !releasing)
+ {
+ vim_free((char *)p); /* System is low... no go! */
+ p = NULL;
+ }
+ else
+ goto theend;
+#endif
+ }
+ /*
+ * Remember that mf_release_all() is being called to avoid an endless
+ * loop, because mf_release_all() may call alloc() recursively.
+ */
+ if (releasing)
+ break;
+ releasing = TRUE;
+ try_again = mf_release_all();
+ releasing = FALSE;
+ if (!try_again)
+ break;
+ }
+
+ if (message && p == NULL)
+ do_outofmem_msg(size);
+
+theend:
+#ifdef MEM_PROFILE
+ mem_post_alloc((void **)&p, (size_t)size);
+#endif
+ return p;
+}
+
+#if defined(MEM_PROFILE) || defined(PROTO)
+/*
+ * realloc() with memory profiling.
+ */
+ void *
+mem_realloc(ptr, size)
+ void *ptr;
+ size_t size;
+{
+ void *p;
+
+ mem_pre_free(&ptr);
+ mem_pre_alloc_s(&size);
+
+ p = realloc(ptr, size);
+
+ mem_post_alloc(&p, size);
+
+ return p;
+}
+#endif
+
+/*
+* Avoid repeating the error message many times (they take 1 second each).
+* Did_outofmem_msg is reset when a character is read.
+*/
+ void
+do_outofmem_msg(size)
+ long_u size;
+{
+ if (!did_outofmem_msg)
+ {
+ /* Don't hide this message */
+ emsg_silent = 0;
+ EMSGN(_("E342: Out of memory! (allocating %lu bytes)"), size);
+ did_outofmem_msg = TRUE;
+ }
+}
+
+/*
+ * copy a string into newly allocated memory
+ */
+ char_u *
+vim_strsave(string)
+ char_u *string;
+{
+ char_u *p;
+ unsigned len;
+
+ len = (unsigned)STRLEN(string) + 1;
+ p = alloc(len);
+ if (p != NULL)
+ mch_memmove(p, string, (size_t)len);
+ return p;
+}
+
+ char_u *
+vim_strnsave(string, len)
+ char_u *string;
+ int len;
+{
+ char_u *p;
+
+ p = alloc((unsigned)(len + 1));
+ if (p != NULL)
+ {
+ STRNCPY(p, string, len);
+ p[len] = NUL;
+ }
+ return p;
+}
+
+#if 0 /* not used */
+/*
+ * like vim_strnsave(), but remove backslashes from the string.
+ */
+ char_u *
+vim_strnsave_esc(string, len)
+ char_u *string;
+ int len;
+{
+ char_u *p1, *p2;
+
+ p1 = alloc((unsigned) (len + 1));
+ if (p1 != NULL)
+ {
+ STRNCPY(p1, string, len);
+ p1[len] = NUL;
+ for (p2 = p1; *p2; ++p2)
+ if (*p2 == '\\' && *(p2 + 1) != NUL)
+ STRCPY(p2, p2 + 1);
+ }
+ return p1;
+}
+#endif
+
+/*
+ * Same as vim_strsave(), but any characters found in esc_chars are preceded
+ * by a backslash.
+ */
+ char_u *
+vim_strsave_escaped(string, esc_chars)
+ char_u *string;
+ char_u *esc_chars;
+{
+ return vim_strsave_escaped_ext(string, esc_chars, FALSE);
+}
+
+/*
+ * Same as vim_strsave_escaped(), but when "bsl" is TRUE also escape
+ * characters where rem_backslash() would remove the backslash.
+ */
+ char_u *
+vim_strsave_escaped_ext(string, esc_chars, bsl)
+ char_u *string;
+ char_u *esc_chars;
+ int bsl;
+{
+ char_u *p;
+ char_u *p2;
+ char_u *escaped_string;
+ unsigned length;
+#ifdef FEAT_MBYTE
+ int l;
+#endif
+
+ /*
+ * First count the number of backslashes required.
+ * Then allocate the memory and insert them.
+ */
+ length = 1; /* count the trailing NUL */
+ for (p = string; *p; p++)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
+ {
+ length += l; /* count a multibyte char */
+ p += l - 1;
+ continue;
+ }
+#endif
+ if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p)))
+ ++length; /* count a backslash */
+ ++length; /* count an ordinary char */
+ }
+ escaped_string = alloc(length);
+ if (escaped_string != NULL)
+ {
+ p2 = escaped_string;
+ for (p = string; *p; p++)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
+ {
+ mch_memmove(p2, p, (size_t)l);
+ p2 += l;
+ p += l - 1; /* skip multibyte char */
+ continue;
+ }
+#endif
+ if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p)))
+ *p2++ = '\\';
+ *p2++ = *p;
+ }
+ *p2 = NUL;
+ }
+ return escaped_string;
+}
+
+/*
+ * Like vim_strsave(), but make all characters uppercase.
+ * This uses ASCII lower-to-upper case translation, language independent.
+ */
+ char_u *
+vim_strsave_up(string)
+ char_u *string;
+{
+ char_u *p1;
+
+ p1 = vim_strsave(string);
+ vim_strup(p1);
+ return p1;
+}
+
+/*
+ * Like vim_strnsave(), but make all characters uppercase.
+ * This uses ASCII lower-to-upper case translation, language independent.
+ */
+ char_u *
+vim_strnsave_up(string, len)
+ char_u *string;
+ int len;
+{
+ char_u *p1;
+
+ p1 = vim_strnsave(string, len);
+ vim_strup(p1);
+ return p1;
+}
+
+/*
+ * ASCII lower-to-upper case translation, language independent.
+ */
+ void
+vim_strup(p)
+ char_u *p;
+{
+ char_u *p2;
+ int c;
+
+ if (p != NULL)
+ {
+ p2 = p;
+ while ((c = *p2) != NUL)
+#ifdef EBCDIC
+ *p2++ = isalpha(c) ? toupper(c) : c;
+#else
+ *p2++ = (c < 'a' || c > 'z') ? c : (c - 0x20);
+#endif
+ }
+}
+
+/*
+ * copy a space a number of times
+ */
+ void
+copy_spaces(ptr, count)
+ char_u *ptr;
+ size_t count;
+{
+ size_t i = count;
+ char_u *p = ptr;
+
+ while (i--)
+ *p++ = ' ';
+}
+
+#if defined(FEAT_VISUALEXTRA) || defined(PROTO)
+/*
+ * Copy a character a number of times.
+ * Does not work for multi-byte charactes!
+ */
+ void
+copy_chars(ptr, count, c)
+ char_u *ptr;
+ size_t count;
+ int c;
+{
+ size_t i = count;
+ char_u *p = ptr;
+
+ while (i--)
+ *p++ = c;
+}
+#endif
+
+/*
+ * delete spaces at the end of a string
+ */
+ void
+del_trailing_spaces(ptr)
+ char_u *ptr;
+{
+ char_u *q;
+
+ q = ptr + STRLEN(ptr);
+ while (--q > ptr && vim_iswhite(q[0]) && q[-1] != '\\' && q[-1] != Ctrl_V)
+ *q = NUL;
+}
+
+/*
+ * This is here because strncpy() does not guarantee successful results when
+ * the to and from strings overlap. It is only currently called from
+ * nextwild() which copies part of the command line to another part of the
+ * command line. This produced garbage when expanding files etc in the middle
+ * of the command line (on my terminal, anyway) -- webb.
+ * Note: strncpy() pads the remainder of the buffer with NUL bytes,
+ * vim_strncpy() doesn't do that.
+ */
+ void
+vim_strncpy(to, from, len)
+ char_u *to;
+ char_u *from;
+ int len;
+{
+ int i;
+
+ if (to <= from)
+ {
+ while (len-- && *from)
+ *to++ = *from++;
+ if (len >= 0)
+ *to = *from; /* Copy NUL */
+ }
+ else
+ {
+ for (i = 0; i < len; i++)
+ {
+ to++;
+ if (*from++ == NUL)
+ {
+ i++;
+ break;
+ }
+ }
+ for (; i > 0; i--)
+ *--to = *--from;
+ }
+}
+
+/*
+ * Isolate one part of a string option where parts are separated with
+ * "sep_chars".
+ * The part is copied into buf[maxlen].
+ * "*option" is advanced to the next part.
+ * The length is returned.
+ */
+ int
+copy_option_part(option, buf, maxlen, sep_chars)
+ char_u **option;
+ char_u *buf;
+ int maxlen;
+ char *sep_chars;
+{
+ int len = 0;
+ char_u *p = *option;
+
+ /* skip '.' at start of option part, for 'suffixes' */
+ if (*p == '.')
+ buf[len++] = *p++;
+ while (*p != NUL && vim_strchr((char_u *)sep_chars, *p) == NULL)
+ {
+ /*
+ * Skip backslash before a separator character and space.
+ */
+ if (p[0] == '\\' && vim_strchr((char_u *)sep_chars, p[1]) != NULL)
+ ++p;
+ if (len < maxlen - 1)
+ buf[len++] = *p;
+ ++p;
+ }
+ buf[len] = NUL;
+
+ if (*p != NUL && *p != ',') /* skip non-standard separator */
+ ++p;
+ p = skip_to_option_part(p); /* p points to next file name */
+
+ *option = p;
+ return len;
+}
+
+/*
+ * replacement for free() that ignores NULL pointers
+ */
+ void
+vim_free(x)
+ void *x;
+{
+ if (x != NULL)
+ {
+#ifdef MEM_PROFILE
+ mem_pre_free(&x);
+#endif
+ free(x);
+ }
+}
+
+#ifndef HAVE_MEMSET
+ void *
+vim_memset(ptr, c, size)
+ void *ptr;
+ int c;
+ size_t size;
+{
+ char *p = ptr;
+
+ while (size-- > 0)
+ *p++ = c;
+ return ptr;
+}
+#endif
+
+#ifdef VIM_MEMCMP
+/*
+ * Return zero when "b1" and "b2" are the same for "len" bytes.
+ * Return non-zero otherwise.
+ */
+ int
+vim_memcmp(b1, b2, len)
+ void *b1;
+ void *b2;
+ size_t len;
+{
+ char_u *p1 = (char_u *)b1, *p2 = (char_u *)b2;
+
+ for ( ; len > 0; --len)
+ {
+ if (*p1 != *p2)
+ return 1;
+ ++p1;
+ ++p2;
+ }
+ return 0;
+}
+#endif
+
+#ifdef VIM_MEMMOVE
+/*
+ * Version of memmove() that handles overlapping source and destination.
+ * For systems that don't have a function that is guaranteed to do that (SYSV).
+ */
+ void
+mch_memmove(dst_arg, src_arg, len)
+ void *src_arg, *dst_arg;
+ size_t len;
+{
+ /*
+ * A void doesn't have a size, we use char pointers.
+ */
+ char *dst = dst_arg, *src = src_arg;
+
+ /* overlap, copy backwards */
+ if (dst > src && dst < src + len)
+ {
+ src += len;
+ dst += len;
+ while (len-- > 0)
+ *--dst = *--src;
+ }
+ else /* copy forwards */
+ while (len-- > 0)
+ *dst++ = *src++;
+}
+#endif
+
+#if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) || defined(PROTO)
+/*
+ * Compare two strings, ignoring case, using current locale.
+ * Doesn't work for multi-byte characters.
+ * return 0 for match, < 0 for smaller, > 0 for bigger
+ */
+ int
+vim_stricmp(s1, s2)
+ char *s1;
+ char *s2;
+{
+ int i;
+
+ for (;;)
+ {
+ i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2);
+ if (i != 0)
+ return i; /* this character different */
+ if (*s1 == NUL)
+ break; /* strings match until NUL */
+ ++s1;
+ ++s2;
+ }
+ return 0; /* strings match */
+}
+#endif
+
+#if (!defined(HAVE_STRNCASECMP) && !defined(HAVE_STRNICMP)) || defined(PROTO)
+/*
+ * Compare two strings, for length "len", ignoring case, using current locale.
+ * Doesn't work for multi-byte characters.
+ * return 0 for match, < 0 for smaller, > 0 for bigger
+ */
+ int
+vim_strnicmp(s1, s2, len)
+ char *s1;
+ char *s2;
+ size_t len;
+{
+ int i;
+
+ while (len > 0)
+ {
+ i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2);
+ if (i != 0)
+ return i; /* this character different */
+ if (*s1 == NUL)
+ break; /* strings match until NUL */
+ ++s1;
+ ++s2;
+ --len;
+ }
+ return 0; /* strings match */
+}
+#endif
+
+#if 0 /* currently not used */
+/*
+ * Check if string "s2" appears somewhere in "s1" while ignoring case.
+ * Return NULL if not, a pointer to the first occurrence if it does.
+ */
+ char_u *
+vim_stristr(s1, s2)
+ char_u *s1;
+ char_u *s2;
+{
+ char_u *p;
+ int len = STRLEN(s2);
+ char_u *end = s1 + STRLEN(s1) - len;
+
+ for (p = s1; p <= end; ++p)
+ if (STRNICMP(p, s2, len) == 0)
+ return p;
+ return NULL;
+}
+#endif
+
+/*
+ * Version of strchr() and strrchr() that handle unsigned char strings
+ * with characters above 128 correctly. Also it doesn't return a pointer to
+ * the NUL at the end of the string.
+ */
+ char_u *
+vim_strchr(string, c)
+ char_u *string;
+ int c;
+{
+ char_u *p;
+ int b;
+
+ p = string;
+#ifdef FEAT_MBYTE
+ if (enc_utf8 && c >= 0x80)
+ {
+ while (*p != NUL)
+ {
+ if (utf_ptr2char(p) == c)
+ return p;
+ p += (*mb_ptr2len_check)(p);
+ }
+ return NULL;
+ }
+ if (enc_dbcs != 0 && c > 255)
+ {
+ int n2 = c & 0xff;
+
+ c = ((unsigned)c >> 8) & 0xff;
+ while ((b = *p) != NUL)
+ {
+ if (b == c && p[1] == n2)
+ return p;
+ p += (*mb_ptr2len_check)(p);
+ }
+ return NULL;
+ }
+ if (has_mbyte)
+ {
+ while ((b = *p) != NUL)
+ {
+ if (b == c)
+ return p;
+ p += (*mb_ptr2len_check)(p);
+ }
+ return NULL;
+ }
+#endif
+ while ((b = *p) != NUL)
+ {
+ if (b == c)
+ return p;
+ ++p;
+ }
+ return NULL;
+}
+
+/*
+ * Search for last occurrence of "c" in "string".
+ * return NULL if not found.
+ * Does not handle multi-byte!
+ */
+ char_u *
+vim_strrchr(string, c)
+ char_u *string;
+ int c;
+{
+ char_u *retval = NULL;
+
+ while (*string)
+ {
+ if (*string == c)
+ retval = string;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ string += (*mb_ptr2len_check)(string);
+ else
+#endif
+ ++string;
+ }
+ return retval;
+}
+
+/*
+ * Vim's version of strpbrk(), in case it's missing.
+ * Don't generate a prototype for this, causes problems when it's not used.
+ */
+#ifndef PROTO
+# ifndef HAVE_STRPBRK
+# ifdef vim_strpbrk
+# undef vim_strpbrk
+# endif
+ char_u *
+vim_strpbrk(s, charset)
+ char_u *s;
+ char_u *charset;
+{
+ while (*s)
+ {
+ if (vim_strchr(charset, *s) != NULL)
+ return s;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ s += (*mb_ptr2len_check)(s);
+ else
+#endif
+ ++s;
+ }
+ return NULL;
+}
+# endif
+#endif
+
+/*
+ * Vim has its own isspace() function, because on some machines isspace()
+ * can't handle characters above 128.
+ */
+ int
+vim_isspace(x)
+ int x;
+{
+ return ((x >= 9 && x <= 13) || x == ' ');
+}
+
+/************************************************************************
+ * Functions for hanlding growing arrays.
+ */
+
+/*
+ * Clear an allocated growing array.
+ */
+ void
+ga_clear(gap)
+ garray_T *gap;
+{
+ vim_free(gap->ga_data);
+ ga_init(gap);
+}
+
+/*
+ * Clear a growing array that contains a list of strings.
+ */
+ void
+ga_clear_strings(gap)
+ garray_T *gap;
+{
+ int i;
+
+ for (i = 0; i < gap->ga_len; ++i)
+ vim_free(((char_u **)(gap->ga_data))[i]);
+ ga_clear(gap);
+}
+
+/*
+ * Initialize a growing array. Don't forget to set ga_itemsize and
+ * ga_growsize! Or use ga_init2().
+ */
+ void
+ga_init(gap)
+ garray_T *gap;
+{
+ gap->ga_data = NULL;
+ gap->ga_room = 0;
+ gap->ga_len = 0;
+}
+
+ void
+ga_init2(gap, itemsize, growsize)
+ garray_T *gap;
+ int itemsize;
+ int growsize;
+{
+ ga_init(gap);
+ gap->ga_itemsize = itemsize;
+ gap->ga_growsize = growsize;
+}
+
+/*
+ * Make room in growing array "gap" for at least "n" items.
+ * Return FAIL for failure, OK otherwise.
+ */
+ int
+ga_grow(gap, n)
+ garray_T *gap;
+ int n;
+{
+ size_t len;
+ char_u *pp;
+
+ if (gap->ga_room < n)
+ {
+ if (n < gap->ga_growsize)
+ n = gap->ga_growsize;
+ len = gap->ga_itemsize * (gap->ga_len + n);
+ pp = alloc_clear((unsigned)len);
+ if (pp == NULL)
+ return FAIL;
+ gap->ga_room = n;
+ if (gap->ga_data != NULL)
+ {
+ mch_memmove(pp, gap->ga_data,
+ (size_t)(gap->ga_itemsize * gap->ga_len));
+ vim_free(gap->ga_data);
+ }
+ gap->ga_data = pp;
+ }
+ return OK;
+}
+
+/*
+ * Concatenate a string to a growarray which contains characters.
+ * Note: Does NOT copy the NUL at the end!
+ */
+ void
+ga_concat(gap, s)
+ garray_T *gap;
+ char_u *s;
+{
+ int len = (int)STRLEN(s);
+
+ if (ga_grow(gap, len) == OK)
+ {
+ mch_memmove((char *)gap->ga_data + gap->ga_len, s, (size_t)len);
+ gap->ga_len += len;
+ gap->ga_room -= len;
+ }
+}
+
+/*
+ * Append one byte to a growarray which contains bytes.
+ */
+ void
+ga_append(gap, c)
+ garray_T *gap;
+ int c;
+{
+ if (ga_grow(gap, 1) == OK)
+ {
+ *((char *)gap->ga_data + gap->ga_len) = c;
+ ++gap->ga_len;
+ --gap->ga_room;
+ }
+}
+
+/************************************************************************
+ * functions that use lookup tables for various things, generally to do with
+ * special key codes.
+ */
+
+/*
+ * Some useful tables.
+ */
+
+static struct modmasktable
+{
+ short mod_mask; /* Bit-mask for particular key modifier */
+ short mod_flag; /* Bit(s) for particular key modifier */
+ char_u name; /* Single letter name of modifier */
+} mod_mask_table[] =
+{
+ {MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'M'},
+ {MOD_MASK_CTRL, MOD_MASK_CTRL, (char_u)'C'},
+ {MOD_MASK_SHIFT, MOD_MASK_SHIFT, (char_u)'S'},
+ {MOD_MASK_MULTI_CLICK, MOD_MASK_2CLICK, (char_u)'2'},
+ {MOD_MASK_MULTI_CLICK, MOD_MASK_3CLICK, (char_u)'3'},
+ {MOD_MASK_MULTI_CLICK, MOD_MASK_4CLICK, (char_u)'4'},
+#ifdef MACOS
+ {MOD_MASK_CMD, MOD_MASK_CMD, (char_u)'D'},
+#endif
+ /* 'A' must be the last one */
+ {MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'A'},
+ {0, 0, NUL}
+};
+
+/*
+ * Shifted key terminal codes and their unshifted equivalent.
+ * Don't add mouse codes here, they are handled seperately!
+ */
+#define MOD_KEYS_ENTRY_SIZE 5
+
+static char_u modifier_keys_table[] =
+{
+/* mod mask with modifier without modifier */
+ MOD_MASK_SHIFT, '&', '9', '@', '1', /* begin */
+ MOD_MASK_SHIFT, '&', '0', '@', '2', /* cancel */
+ MOD_MASK_SHIFT, '*', '1', '@', '4', /* command */
+ MOD_MASK_SHIFT, '*', '2', '@', '5', /* copy */
+ MOD_MASK_SHIFT, '*', '3', '@', '6', /* create */
+ MOD_MASK_SHIFT, '*', '4', 'k', 'D', /* delete char */
+ MOD_MASK_SHIFT, '*', '5', 'k', 'L', /* delete line */
+ MOD_MASK_SHIFT, '*', '7', '@', '7', /* end */
+ MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_END, '@', '7', /* end */
+ MOD_MASK_SHIFT, '*', '9', '@', '9', /* exit */
+ MOD_MASK_SHIFT, '*', '0', '@', '0', /* find */
+ MOD_MASK_SHIFT, '#', '1', '%', '1', /* help */
+ MOD_MASK_SHIFT, '#', '2', 'k', 'h', /* home */
+ MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_HOME, 'k', 'h', /* home */
+ MOD_MASK_SHIFT, '#', '3', 'k', 'I', /* insert */
+ MOD_MASK_SHIFT, '#', '4', 'k', 'l', /* left arrow */
+ MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_LEFT, 'k', 'l', /* left arrow */
+ MOD_MASK_SHIFT, '%', 'a', '%', '3', /* message */
+ MOD_MASK_SHIFT, '%', 'b', '%', '4', /* move */
+ MOD_MASK_SHIFT, '%', 'c', '%', '5', /* next */
+ MOD_MASK_SHIFT, '%', 'd', '%', '7', /* options */
+ MOD_MASK_SHIFT, '%', 'e', '%', '8', /* previous */
+ MOD_MASK_SHIFT, '%', 'f', '%', '9', /* print */
+ MOD_MASK_SHIFT, '%', 'g', '%', '0', /* redo */
+ MOD_MASK_SHIFT, '%', 'h', '&', '3', /* replace */
+ MOD_MASK_SHIFT, '%', 'i', 'k', 'r', /* right arr. */
+ MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_RIGHT, 'k', 'r', /* right arr. */
+ MOD_MASK_SHIFT, '%', 'j', '&', '5', /* resume */
+ MOD_MASK_SHIFT, '!', '1', '&', '6', /* save */
+ MOD_MASK_SHIFT, '!', '2', '&', '7', /* suspend */
+ MOD_MASK_SHIFT, '!', '3', '&', '8', /* undo */
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_UP, 'k', 'u', /* up arrow */
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_DOWN, 'k', 'd', /* down arrow */
+
+ /* vt100 F1 */
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF1, KS_EXTRA, (int)KE_XF1,
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF2, KS_EXTRA, (int)KE_XF2,
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF3, KS_EXTRA, (int)KE_XF3,
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF4, KS_EXTRA, (int)KE_XF4,
+
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F1, 'k', '1', /* F1 */
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F2, 'k', '2',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F3, 'k', '3',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F4, 'k', '4',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F5, 'k', '5',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F6, 'k', '6',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F7, 'k', '7',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F8, 'k', '8',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F9, 'k', '9',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F10, 'k', ';', /* F10 */
+
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F11, 'F', '1',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F12, 'F', '2',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F13, 'F', '3',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F14, 'F', '4',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F15, 'F', '5',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F16, 'F', '6',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F17, 'F', '7',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F18, 'F', '8',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F19, 'F', '9',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F20, 'F', 'A',
+
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F21, 'F', 'B',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F22, 'F', 'C',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F23, 'F', 'D',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F24, 'F', 'E',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F25, 'F', 'F',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F26, 'F', 'G',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F27, 'F', 'H',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F28, 'F', 'I',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F29, 'F', 'J',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F30, 'F', 'K',
+
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F31, 'F', 'L',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F32, 'F', 'M',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F33, 'F', 'N',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F34, 'F', 'O',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F35, 'F', 'P',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F36, 'F', 'Q',
+ MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F37, 'F', 'R',
+
+ /* TAB pseudo code*/
+ MOD_MASK_SHIFT, 'k', 'B', KS_EXTRA, (int)KE_TAB,
+
+ NUL
+};
+
+static struct key_name_entry
+{
+ int key; /* Special key code or ascii value */
+ char_u *name; /* Name of key */
+} key_names_table[] =
+{
+ {' ', (char_u *)"Space"},
+ {TAB, (char_u *)"Tab"},
+ {K_TAB, (char_u *)"Tab"},
+ {NL, (char_u *)"NL"},
+ {NL, (char_u *)"NewLine"}, /* Alternative name */
+ {NL, (char_u *)"LineFeed"}, /* Alternative name */
+ {NL, (char_u *)"LF"}, /* Alternative name */
+ {CAR, (char_u *)"CR"},
+ {CAR, (char_u *)"Return"}, /* Alternative name */
+ {CAR, (char_u *)"Enter"}, /* Alternative name */
+ {K_BS, (char_u *)"BS"},
+ {K_BS, (char_u *)"BackSpace"}, /* Alternative name */
+ {ESC, (char_u *)"Esc"},
+ {CSI, (char_u *)"CSI"},
+ {K_CSI, (char_u *)"xCSI"},
+ {'|', (char_u *)"Bar"},
+ {'\\', (char_u *)"Bslash"},
+ {K_DEL, (char_u *)"Del"},
+ {K_DEL, (char_u *)"Delete"}, /* Alternative name */
+ {K_KDEL, (char_u *)"kDel"},
+ {K_UP, (char_u *)"Up"},
+ {K_DOWN, (char_u *)"Down"},
+ {K_LEFT, (char_u *)"Left"},
+ {K_RIGHT, (char_u *)"Right"},
+
+ {K_F1, (char_u *)"F1"},
+ {K_F2, (char_u *)"F2"},
+ {K_F3, (char_u *)"F3"},
+ {K_F4, (char_u *)"F4"},
+ {K_F5, (char_u *)"F5"},
+ {K_F6, (char_u *)"F6"},
+ {K_F7, (char_u *)"F7"},
+ {K_F8, (char_u *)"F8"},
+ {K_F9, (char_u *)"F9"},
+ {K_F10, (char_u *)"F10"},
+
+ {K_F11, (char_u *)"F11"},
+ {K_F12, (char_u *)"F12"},
+ {K_F13, (char_u *)"F13"},
+ {K_F14, (char_u *)"F14"},
+ {K_F15, (char_u *)"F15"},
+ {K_F16, (char_u *)"F16"},
+ {K_F17, (char_u *)"F17"},
+ {K_F18, (char_u *)"F18"},
+ {K_F19, (char_u *)"F19"},
+ {K_F20, (char_u *)"F20"},
+
+ {K_F21, (char_u *)"F21"},
+ {K_F22, (char_u *)"F22"},
+ {K_F23, (char_u *)"F23"},
+ {K_F24, (char_u *)"F24"},
+ {K_F25, (char_u *)"F25"},
+ {K_F26, (char_u *)"F26"},
+ {K_F27, (char_u *)"F27"},
+ {K_F28, (char_u *)"F28"},
+ {K_F29, (char_u *)"F29"},
+ {K_F30, (char_u *)"F30"},
+
+ {K_F31, (char_u *)"F31"},
+ {K_F32, (char_u *)"F32"},
+ {K_F33, (char_u *)"F33"},
+ {K_F34, (char_u *)"F34"},
+ {K_F35, (char_u *)"F35"},
+ {K_F36, (char_u *)"F36"},
+ {K_F37, (char_u *)"F37"},
+
+ {K_XF1, (char_u *)"xF1"},
+ {K_XF2, (char_u *)"xF2"},
+ {K_XF3, (char_u *)"xF3"},
+ {K_XF4, (char_u *)"xF4"},
+
+ {K_HELP, (char_u *)"Help"},
+ {K_UNDO, (char_u *)"Undo"},
+ {K_INS, (char_u *)"Insert"},
+ {K_INS, (char_u *)"Ins"}, /* Alternative name */
+ {K_KINS, (char_u *)"kInsert"},
+ {K_HOME, (char_u *)"Home"},
+ {K_KHOME, (char_u *)"kHome"},
+ {K_XHOME, (char_u *)"xHome"},
+ {K_END, (char_u *)"End"},
+ {K_KEND, (char_u *)"kEnd"},
+ {K_XEND, (char_u *)"xEnd"},
+ {K_PAGEUP, (char_u *)"PageUp"},
+ {K_PAGEDOWN, (char_u *)"PageDown"},
+ {K_KPAGEUP, (char_u *)"kPageUp"},
+ {K_KPAGEDOWN, (char_u *)"kPageDown"},
+
+ {K_KPLUS, (char_u *)"kPlus"},
+ {K_KMINUS, (char_u *)"kMinus"},
+ {K_KDIVIDE, (char_u *)"kDivide"},
+ {K_KMULTIPLY, (char_u *)"kMultiply"},
+ {K_KENTER, (char_u *)"kEnter"},
+ {K_KPOINT, (char_u *)"kPoint"},
+
+ {K_K0, (char_u *)"k0"},
+ {K_K1, (char_u *)"k1"},
+ {K_K2, (char_u *)"k2"},
+ {K_K3, (char_u *)"k3"},
+ {K_K4, (char_u *)"k4"},
+ {K_K5, (char_u *)"k5"},
+ {K_K6, (char_u *)"k6"},
+ {K_K7, (char_u *)"k7"},
+ {K_K8, (char_u *)"k8"},
+ {K_K9, (char_u *)"k9"},
+
+ {'<', (char_u *)"lt"},
+
+ {K_MOUSE, (char_u *)"Mouse"},
+ {K_NETTERM_MOUSE, (char_u *)"NetMouse"},
+ {K_DEC_MOUSE, (char_u *)"DecMouse"},
+ {K_JSBTERM_MOUSE, (char_u *)"JsbMouse"},
+ {K_PTERM_MOUSE, (char_u *)"PtermMouse"},
+ {K_LEFTMOUSE, (char_u *)"LeftMouse"},
+ {K_LEFTMOUSE_NM, (char_u *)"LeftMouseNM"},
+ {K_LEFTDRAG, (char_u *)"LeftDrag"},
+ {K_LEFTRELEASE, (char_u *)"LeftRelease"},
+ {K_LEFTRELEASE_NM, (char_u *)"LeftReleaseNM"},
+ {K_MIDDLEMOUSE, (char_u *)"MiddleMouse"},
+ {K_MIDDLEDRAG, (char_u *)"MiddleDrag"},
+ {K_MIDDLERELEASE, (char_u *)"MiddleRelease"},
+ {K_RIGHTMOUSE, (char_u *)"RightMouse"},
+ {K_RIGHTDRAG, (char_u *)"RightDrag"},
+ {K_RIGHTRELEASE, (char_u *)"RightRelease"},
+ {K_MOUSEDOWN, (char_u *)"MouseDown"},
+ {K_MOUSEUP, (char_u *)"MouseUp"},
+ {K_X1MOUSE, (char_u *)"X1Mouse"},
+ {K_X1DRAG, (char_u *)"X1Drag"},
+ {K_X1RELEASE, (char_u *)"X1Release"},
+ {K_X2MOUSE, (char_u *)"X2Mouse"},
+ {K_X2DRAG, (char_u *)"X2Drag"},
+ {K_X2RELEASE, (char_u *)"X2Release"},
+ {K_DROP, (char_u *)"Drop"},
+ {K_ZERO, (char_u *)"Nul"},
+#ifdef FEAT_EVAL
+ {K_SNR, (char_u *)"SNR"},
+#endif
+ {K_PLUG, (char_u *)"Plug"},
+ {0, NULL}
+};
+
+#define KEY_NAMES_TABLE_LEN (sizeof(key_names_table) / sizeof(struct key_name_entry))
+
+#ifdef FEAT_MOUSE
+static struct mousetable
+{
+ int pseudo_code; /* Code for pseudo mouse event */
+ int button; /* Which mouse button is it? */
+ int is_click; /* Is it a mouse button click event? */
+ int is_drag; /* Is it a mouse drag event? */
+} mouse_table[] =
+{
+ {(int)KE_LEFTMOUSE, MOUSE_LEFT, TRUE, FALSE},
+#ifdef FEAT_GUI
+ {(int)KE_LEFTMOUSE_NM, MOUSE_LEFT, TRUE, FALSE},
+#endif
+ {(int)KE_LEFTDRAG, MOUSE_LEFT, FALSE, TRUE},
+ {(int)KE_LEFTRELEASE, MOUSE_LEFT, FALSE, FALSE},
+#ifdef FEAT_GUI
+ {(int)KE_LEFTRELEASE_NM, MOUSE_LEFT, FALSE, FALSE},
+#endif
+ {(int)KE_MIDDLEMOUSE, MOUSE_MIDDLE, TRUE, FALSE},
+ {(int)KE_MIDDLEDRAG, MOUSE_MIDDLE, FALSE, TRUE},
+ {(int)KE_MIDDLERELEASE, MOUSE_MIDDLE, FALSE, FALSE},
+ {(int)KE_RIGHTMOUSE, MOUSE_RIGHT, TRUE, FALSE},
+ {(int)KE_RIGHTDRAG, MOUSE_RIGHT, FALSE, TRUE},
+ {(int)KE_RIGHTRELEASE, MOUSE_RIGHT, FALSE, FALSE},
+ {(int)KE_X1MOUSE, MOUSE_X1, TRUE, FALSE},
+ {(int)KE_X1DRAG, MOUSE_X1, FALSE, TRUE},
+ {(int)KE_X1RELEASE, MOUSE_X1, FALSE, FALSE},
+ {(int)KE_X2MOUSE, MOUSE_X2, TRUE, FALSE},
+ {(int)KE_X2DRAG, MOUSE_X2, FALSE, TRUE},
+ {(int)KE_X2RELEASE, MOUSE_X2, FALSE, FALSE},
+ /* DRAG without CLICK */
+ {(int)KE_IGNORE, MOUSE_RELEASE, FALSE, TRUE},
+ /* RELEASE without CLICK */
+ {(int)KE_IGNORE, MOUSE_RELEASE, FALSE, FALSE},
+ {0, 0, 0, 0},
+};
+#endif /* FEAT_MOUSE */
+
+/*
+ * Return the modifier mask bit (MOD_MASK_*) which corresponds to the given
+ * modifier name ('S' for Shift, 'C' for Ctrl etc).
+ */
+ int
+name_to_mod_mask(c)
+ int c;
+{
+ int i;
+
+ c = TOUPPER_ASC(c);
+ for (i = 0; mod_mask_table[i].mod_mask != 0; i++)
+ if (c == mod_mask_table[i].name)
+ return mod_mask_table[i].mod_flag;
+ return 0;
+}
+
+#if 0 /* not used */
+/*
+ * Decide whether the given key code (K_*) is a shifted special
+ * key (by looking at mod_mask). If it is, then return the appropriate shifted
+ * key code, otherwise just return the character as is.
+ */
+ int
+check_shifted_spec_key(c)
+ int c;
+{
+ return simplify_key(c, &mod_mask);
+}
+#endif
+
+/*
+ * Check if if there is a special key code for "key" that includes the
+ * modifiers specified.
+ */
+ int
+simplify_key(key, modifiers)
+ int key;
+ int *modifiers;
+{
+ int i;
+ int key0;
+ int key1;
+
+ if (*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT))
+ {
+ /* TAB is a special case */
+ if (key == TAB && (*modifiers & MOD_MASK_SHIFT))
+ {
+ *modifiers &= ~MOD_MASK_SHIFT;
+ return K_S_TAB;
+ }
+ key0 = KEY2TERMCAP0(key);
+ key1 = KEY2TERMCAP1(key);
+ for (i = 0; modifier_keys_table[i] != NUL; i += MOD_KEYS_ENTRY_SIZE)
+ if (key0 == modifier_keys_table[i + 3]
+ && key1 == modifier_keys_table[i + 4]
+ && (*modifiers & modifier_keys_table[i]))
+ {
+ *modifiers &= ~modifier_keys_table[i];
+ return TERMCAP2KEY(modifier_keys_table[i + 1],
+ modifier_keys_table[i + 2]);
+ }
+ }
+ return key;
+}
+
+/*
+ * Return a string which contains the name of the given key when the given
+ * modifiers are down.
+ */
+ char_u *
+get_special_key_name(c, modifiers)
+ int c;
+ int modifiers;
+{
+ static char_u string[MAX_KEY_NAME_LEN + 1];
+
+ int i, idx;
+ int table_idx;
+ char_u *s;
+
+ string[0] = '<';
+ idx = 1;
+
+ /* Key that stands for a normal character. */
+ if (IS_SPECIAL(c) && KEY2TERMCAP0(c) == KS_KEY)
+ c = KEY2TERMCAP1(c);
+
+ /*
+ * Translate shifted special keys into unshifted keys and set modifier.
+ * Same for CTRL and ALT modifiers.
+ */
+ if (IS_SPECIAL(c))
+ {
+ for (i = 0; modifier_keys_table[i] != 0; i += MOD_KEYS_ENTRY_SIZE)
+ if ( KEY2TERMCAP0(c) == (int)modifier_keys_table[i + 1]
+ && (int)KEY2TERMCAP1(c) == (int)modifier_keys_table[i + 2])
+ {
+ modifiers |= modifier_keys_table[i];
+ c = TERMCAP2KEY(modifier_keys_table[i + 3],
+ modifier_keys_table[i + 4]);
+ break;
+ }
+ }
+
+ /* try to find the key in the special key table */
+ table_idx = find_special_key_in_table(c);
+
+ /*
+ * When not a known special key, and not a printable character, try to
+ * extract modifiers.
+ */
+ if (c > 0
+#ifdef FEAT_MBYTE
+ && (*mb_char2len)(c) == 1
+#endif
+ )
+ {
+ if (table_idx < 0
+ && (!vim_isprintc(c) || (c & 0x7f) == ' ')
+ && (c & 0x80))
+ {
+ c &= 0x7f;
+ modifiers |= MOD_MASK_ALT;
+ /* try again, to find the un-alted key in the special key table */
+ table_idx = find_special_key_in_table(c);
+ }
+ if (table_idx < 0 && !vim_isprintc(c) && c < ' ')
+ {
+#ifdef EBCDIC
+ c = CtrlChar(c);
+#else
+ c += '@';
+#endif
+ modifiers |= MOD_MASK_CTRL;
+ }
+ }
+
+ /* translate the modifier into a string */
+ for (i = 0; mod_mask_table[i].name != 'A'; i++)
+ if ((modifiers & mod_mask_table[i].mod_mask)
+ == mod_mask_table[i].mod_flag)
+ {
+ string[idx++] = mod_mask_table[i].name;
+ string[idx++] = (char_u)'-';
+ }
+
+ if (table_idx < 0) /* unknown special key, may output t_xx */
+ {
+ if (IS_SPECIAL(c))
+ {
+ string[idx++] = 't';
+ string[idx++] = '_';
+ string[idx++] = KEY2TERMCAP0(c);
+ string[idx++] = KEY2TERMCAP1(c);
+ }
+ /* Not a special key, only modifiers, output directly */
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (*mb_char2len)(c) > 1)
+ idx += (*mb_char2bytes)(c, string + idx);
+ else
+#endif
+ if (vim_isprintc(c))
+ string[idx++] = c;
+ else
+ {
+ s = transchar(c);
+ while (*s)
+ string[idx++] = *s++;
+ }
+ }
+ }
+ else /* use name of special key */
+ {
+ STRCPY(string + idx, key_names_table[table_idx].name);
+ idx = (int)STRLEN(string);
+ }
+ string[idx++] = '>';
+ string[idx] = NUL;
+ return string;
+}
+
+/*
+ * Try translating a <> name at (*srcp)[] to dst[].
+ * Return the number of characters added to dst[], zero for no match.
+ * If there is a match, srcp is advanced to after the <> name.
+ * dst[] must be big enough to hold the result (up to six characters)!
+ */
+ int
+trans_special(srcp, dst, keycode)
+ char_u **srcp;
+ char_u *dst;
+ int keycode; /* prefer key code, e.g. K_DEL instead of DEL */
+{
+ int modifiers = 0;
+ int key;
+ int dlen = 0;
+
+ key = find_special_key(srcp, &modifiers, keycode);
+ if (key == 0)
+ return 0;
+
+ /* Put the appropriate modifier in a string */
+ if (modifiers != 0)
+ {
+ dst[dlen++] = K_SPECIAL;
+ dst[dlen++] = KS_MODIFIER;
+ dst[dlen++] = modifiers;
+ }
+
+ if (IS_SPECIAL(key))
+ {
+ dst[dlen++] = K_SPECIAL;
+ dst[dlen++] = KEY2TERMCAP0(key);
+ dst[dlen++] = KEY2TERMCAP1(key);
+ }
+#ifdef FEAT_MBYTE
+ else if (has_mbyte && !keycode)
+ dlen += (*mb_char2bytes)(key, dst + dlen);
+#endif
+ else if (keycode)
+ dlen = (int)(add_char2buf(key, dst + dlen) - dst);
+ else
+ dst[dlen++] = key;
+
+ return dlen;
+}
+
+/*
+ * Try translating a <> name at (*srcp)[], return the key and modifiers.
+ * srcp is advanced to after the <> name.
+ * returns 0 if there is no match.
+ */
+ int
+find_special_key(srcp, modp, keycode)
+ char_u **srcp;
+ int *modp;
+ int keycode; /* prefer key code, e.g. K_DEL instead of DEL */
+{
+ char_u *last_dash;
+ char_u *end_of_name;
+ char_u *src;
+ char_u *bp;
+ int modifiers;
+ int bit;
+ int key;
+ long_u n;
+
+ src = *srcp;
+ if (src[0] != '<')
+ return 0;
+
+ /* Find end of modifier list */
+ last_dash = src;
+ for (bp = src + 1; *bp == '-' || vim_isIDc(*bp); bp++)
+ {
+ if (*bp == '-')
+ {
+ last_dash = bp;
+ if (bp[1] != NUL && bp[2] == '>')
+ ++bp; /* anything accepted, like <C-?> */
+ }
+ if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3])
+ bp += 3; /* skip t_xx, xx may be '-' or '>' */
+ }
+
+ if (*bp == '>') /* found matching '>' */
+ {
+ end_of_name = bp + 1;
+
+ if (STRNICMP(src + 1, "char-", 5) == 0 && VIM_ISDIGIT(src[6]))
+ {
+ /* <Char-123> or <Char-033> or <Char-0x33> */
+ vim_str2nr(src + 6, NULL, NULL, TRUE, TRUE, NULL, &n);
+ *modp = 0;
+ *srcp = end_of_name;
+ return (int)n;
+ }
+
+ /* Which modifiers are given? */
+ modifiers = 0x0;
+ for (bp = src + 1; bp < last_dash; bp++)
+ {
+ if (*bp != '-')
+ {
+ bit = name_to_mod_mask(*bp);
+ if (bit == 0x0)
+ break; /* Illegal modifier name */
+ modifiers |= bit;
+ }
+ }
+
+ /*
+ * Legal modifier name.
+ */
+ if (bp >= last_dash)
+ {
+ /*
+ * Modifier with single letter, or special key name.
+ */
+ if (modifiers != 0 && last_dash[2] == '>')
+ key = last_dash[1];
+ else
+ key = get_special_key_code(last_dash + 1);
+
+ /*
+ * get_special_key_code() may return NUL for invalid
+ * special key name.
+ */
+ if (key != NUL)
+ {
+ /*
+ * Only use a modifier when there is no special key code that
+ * includes the modifier.
+ */
+ key = simplify_key(key, &modifiers);
+
+ if (!keycode)
+ {
+ /* don't want keycode, use single byte code */
+ if (key == K_BS)
+ key = BS;
+ else if (key == K_DEL || key == K_KDEL)
+ key = DEL;
+ }
+
+ /*
+ * Normal Key with modifier: Try to make a single byte code.
+ */
+ if (!IS_SPECIAL(key))
+ key = extract_modifiers(key, &modifiers);
+
+ *modp = modifiers;
+ *srcp = end_of_name;
+ return key;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * Try to include modifiers in the key.
+ * Changes "Shift-a" to 'A', "Alt-A" to 0xc0, etc.
+ */
+ int
+extract_modifiers(key, modp)
+ int key;
+ int *modp;
+{
+ int modifiers = *modp;
+
+#ifdef MACOS
+ /* Command-key really special, No fancynest */
+ if (!(modifiers & MOD_MASK_CMD))
+#endif
+ if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key))
+ {
+ key = TOUPPER_ASC(key);
+ modifiers &= ~MOD_MASK_SHIFT;
+ }
+ if ((modifiers & MOD_MASK_CTRL)
+#ifdef EBCDIC
+ /* * TODO: EBCDIC Better use:
+ * && (Ctrl_chr(key) || key == '?')
+ * ??? */
+ && strchr("?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_", key)
+ != NULL
+#else
+ && ((key >= '?' && key <= '_') || ASCII_ISALPHA(key))
+#endif
+ )
+ {
+ key = Ctrl_chr(key);
+ modifiers &= ~MOD_MASK_CTRL;
+ /* <C-@> is <Nul> */
+ if (key == 0)
+ key = K_ZERO;
+ }
+#ifdef MACOS
+ /* Command-key really special, No fancynest */
+ if (!(modifiers & MOD_MASK_CMD))
+#endif
+ if ((modifiers & MOD_MASK_ALT) && key < 0x80
+#ifdef FEAT_MBYTE
+ && !enc_dbcs /* avoid creating a lead byte */
+#endif
+ )
+ {
+ key |= 0x80;
+ modifiers &= ~MOD_MASK_ALT; /* remove the META modifier */
+ }
+
+ *modp = modifiers;
+ return key;
+}
+
+/*
+ * Try to find key "c" in the special key table.
+ * Return the index when found, -1 when not found.
+ */
+ int
+find_special_key_in_table(c)
+ int c;
+{
+ int i;
+
+ for (i = 0; key_names_table[i].name != NULL; i++)
+ if (c == key_names_table[i].key)
+ break;
+ if (key_names_table[i].name == NULL)
+ i = -1;
+ return i;
+}
+
+/*
+ * Find the special key with the given name (the given string does not have to
+ * end with NUL, the name is assumed to end before the first non-idchar).
+ * If the name starts with "t_" the next two characters are interpreted as a
+ * termcap name.
+ * Return the key code, or 0 if not found.
+ */
+ int
+get_special_key_code(name)
+ char_u *name;
+{
+ char_u *table_name;
+ char_u string[3];
+ int i, j;
+
+ /*
+ * If it's <t_xx> we get the code for xx from the termcap
+ */
+ if (name[0] == 't' && name[1] == '_' && name[2] != NUL && name[3] != NUL)
+ {
+ string[0] = name[2];
+ string[1] = name[3];
+ string[2] = NUL;
+ if (add_termcap_entry(string, FALSE) == OK)
+ return TERMCAP2KEY(name[2], name[3]);
+ }
+ else
+ for (i = 0; key_names_table[i].name != NULL; i++)
+ {
+ table_name = key_names_table[i].name;
+ for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++)
+ if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j]))
+ break;
+ if (!vim_isIDc(name[j]) && table_name[j] == NUL)
+ return key_names_table[i].key;
+ }
+ return 0;
+}
+
+#ifdef FEAT_CMDL_COMPL
+ char_u *
+get_key_name(i)
+ int i;
+{
+ if (i >= KEY_NAMES_TABLE_LEN)
+ return NULL;
+ return key_names_table[i].name;
+}
+#endif
+
+#ifdef FEAT_MOUSE
+/*
+ * Look up the given mouse code to return the relevant information in the other
+ * arguments. Return which button is down or was released.
+ */
+ int
+get_mouse_button(code, is_click, is_drag)
+ int code;
+ int *is_click;
+ int *is_drag;
+{
+ int i;
+
+ for (i = 0; mouse_table[i].pseudo_code; i++)
+ if (code == mouse_table[i].pseudo_code)
+ {
+ *is_click = mouse_table[i].is_click;
+ *is_drag = mouse_table[i].is_drag;
+ return mouse_table[i].button;
+ }
+ return 0; /* Shouldn't get here */
+}
+
+/*
+ * Return the appropriate pseudo mouse event token (KE_LEFTMOUSE etc) based on
+ * the given information about which mouse button is down, and whether the
+ * mouse was clicked, dragged or released.
+ */
+ int
+get_pseudo_mouse_code(button, is_click, is_drag)
+ int button; /* eg MOUSE_LEFT */
+ int is_click;
+ int is_drag;
+{
+ int i;
+
+ for (i = 0; mouse_table[i].pseudo_code; i++)
+ if (button == mouse_table[i].button
+ && is_click == mouse_table[i].is_click
+ && is_drag == mouse_table[i].is_drag)
+ {
+#ifdef FEAT_GUI
+ /* Trick: a non mappable left click and release has mouse_col < 0.
+ * Used for 'mousefocus' in gui_mouse_moved() */
+ if (mouse_col < 0)
+ {
+ mouse_col = 0;
+ if (mouse_table[i].pseudo_code == (int)KE_LEFTMOUSE)
+ return (int)KE_LEFTMOUSE_NM;
+ if (mouse_table[i].pseudo_code == (int)KE_LEFTRELEASE)
+ return (int)KE_LEFTRELEASE_NM;
+ }
+#endif
+ return mouse_table[i].pseudo_code;
+ }
+ return (int)KE_IGNORE; /* not recongnized, ignore it */
+}
+#endif /* FEAT_MOUSE */
+
+/*
+ * Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC.
+ */
+ int
+get_fileformat(buf)
+ buf_T *buf;
+{
+ int c = *buf->b_p_ff;
+
+ if (buf->b_p_bin || c == 'u')
+ return EOL_UNIX;
+ if (c == 'm')
+ return EOL_MAC;
+ return EOL_DOS;
+}
+
+/*
+ * Like get_fileformat(), but override 'fileformat' with "p" for "++opt=val"
+ * argument.
+ */
+ int
+get_fileformat_force(buf, eap)
+ buf_T *buf;
+ exarg_T *eap; /* can be NULL! */
+{
+ int c;
+
+ if (eap != NULL && eap->force_ff != 0)
+ c = eap->cmd[eap->force_ff];
+ else
+ {
+ if ((eap != NULL && eap->force_bin != 0)
+ ? (eap->force_bin == FORCE_BIN) : buf->b_p_bin)
+ return EOL_UNIX;
+ c = *buf->b_p_ff;
+ }
+ if (c == 'u')
+ return EOL_UNIX;
+ if (c == 'm')
+ return EOL_MAC;
+ return EOL_DOS;
+}
+
+/*
+ * Set the current end-of-line type to EOL_DOS, EOL_UNIX or EOL_MAC.
+ * Sets both 'textmode' and 'fileformat'.
+ * Note: Does _not_ set global value of 'textmode'!
+ */
+ void
+set_fileformat(t, opt_flags)
+ int t;
+ int opt_flags; /* OPT_LOCAL and/or OPT_GLOBAL */
+{
+ char *p = NULL;
+
+ switch (t)
+ {
+ case EOL_DOS:
+ p = FF_DOS;
+ curbuf->b_p_tx = TRUE;
+ break;
+ case EOL_UNIX:
+ p = FF_UNIX;
+ curbuf->b_p_tx = FALSE;
+ break;
+ case EOL_MAC:
+ p = FF_MAC;
+ curbuf->b_p_tx = FALSE;
+ break;
+ }
+ if (p != NULL)
+ set_string_option_direct((char_u *)"ff", -1, (char_u *)p,
+ OPT_FREE | opt_flags);
+#ifdef FEAT_WINDOWS
+ check_status(curbuf);
+#endif
+#ifdef FEAT_TITLE
+ need_maketitle = TRUE; /* set window title later */
+#endif
+}
+
+/*
+ * Return the default fileformat from 'fileformats'.
+ */
+ int
+default_fileformat()
+{
+ switch (*p_ffs)
+ {
+ case 'm': return EOL_MAC;
+ case 'd': return EOL_DOS;
+ }
+ return EOL_UNIX;
+}
+
+/*
+ * Call shell. Calls mch_call_shell, with 'shellxquote' added.
+ */
+ int
+call_shell(cmd, opt)
+ char_u *cmd;
+ int opt;
+{
+ char_u *ncmd;
+ int retval;
+
+ if (p_verbose > 3)
+ {
+ msg_str((char_u *)_("Calling shell to execute: \"%s\""),
+ cmd == NULL ? p_sh : cmd);
+ out_char('\n');
+ cursor_on();
+ }
+
+ if (*p_sh == NUL)
+ {
+ EMSG(_(e_shellempty));
+ retval = -1;
+ }
+ else
+ {
+#ifdef FEAT_GUI_MSWIN
+ /* Don't hide the pointer while executing a shell command. */
+ gui_mch_mousehide(FALSE);
+#endif
+#ifdef FEAT_GUI
+ ++hold_gui_events;
+#endif
+ /* The external command may update a tags file, clear cached tags. */
+ tag_freematch();
+
+ if (cmd == NULL || *p_sxq == NUL)
+ retval = mch_call_shell(cmd, opt);
+ else
+ {
+ ncmd = alloc((unsigned)(STRLEN(cmd) + STRLEN(p_sxq) * 2 + 1));
+ if (ncmd != NULL)
+ {
+ STRCPY(ncmd, p_sxq);
+ STRCAT(ncmd, cmd);
+ STRCAT(ncmd, p_sxq);
+ retval = mch_call_shell(ncmd, opt);
+ vim_free(ncmd);
+ }
+ else
+ retval = -1;
+ }
+#ifdef FEAT_GUI
+ --hold_gui_events;
+#endif
+ /*
+ * Check the window size, in case it changed while executing the
+ * external command.
+ */
+ shell_resized_check();
+ }
+
+#ifdef FEAT_EVAL
+ set_vim_var_nr(VV_SHELL_ERROR, (long)retval);
+#endif
+
+ return retval;
+}
+
+/*
+ * VISUAL and OP_PENDING State are never set, they are equal to NORMAL State
+ * with a condition. This function returns the real State.
+ */
+ int
+get_real_state()
+{
+ if (State & NORMAL)
+ {
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ return VISUAL;
+ else
+#endif
+ if (finish_op)
+ return OP_PENDING;
+ }
+ return State;
+}
+
+#if defined(FEAT_SESSION) || defined(MSWIN) || defined(FEAT_GUI_MAC) \
+ || (defined(FEAT_GUI_GTK) \
+ && (defined(FEAT_WINDOWS) || defined(FEAT_DND))) \
+ || defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \
+ || defined(PROTO)
+/*
+ * Change to a file's directory.
+ * Caller must call shorten_fnames()!
+ * Return OK or FAIL.
+ */
+ int
+vim_chdirfile(fname)
+ char_u *fname;
+{
+ char_u temp_string[MAXPATHL];
+ char_u *p;
+ char_u *t;
+
+ STRCPY(temp_string, fname);
+ p = get_past_head(temp_string);
+ t = gettail(temp_string);
+ while (t > p && vim_ispathsep(t[-1]))
+ --t;
+ *t = NUL; /* chop off end of string */
+
+ return mch_chdir((char *)temp_string) == 0 ? OK : FAIL;
+}
+#endif
+
+#if defined(STAT_IGNORES_SLASH) || defined(PROTO)
+/*
+ * Check if "name" ends in a slash and is not a directory.
+ * Used for systems where stat() ignores a trailing slash on a file name.
+ * The Vim code assumes a trailing slash is only ignored for a directory.
+ */
+ int
+illegal_slash(name)
+ char *name;
+{
+ if (name[0] == NUL)
+ return FALSE; /* no file name is not illegal */
+ if (name[strlen(name) - 1] != '/')
+ return FALSE; /* no trailing slash */
+ if (mch_isdir((char_u *)name))
+ return FALSE; /* trailing slash for a directory */
+ return TRUE;
+}
+#endif
+
+#if defined(CURSOR_SHAPE) || defined(PROTO)
+
+/*
+ * Handling of cursor and mouse pointer shapes in various modes.
+ */
+
+cursorentry_T shape_table[SHAPE_IDX_COUNT] =
+{
+ /* The values will be filled in from the 'guicursor' and 'mouseshape'
+ * defaults when Vim starts.
+ * Adjust the SHAPE_IDX_ defines when making changes! */
+ {0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE},
+ {0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE},
+ {0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE},
+ {0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE},
+ {0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE},
+ {0, 0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE},
+ {0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE},
+ {0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE},
+ {0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE},
+ {0, 0, 0, 0L, 0L, 0L, 0, 0, "e", SHAPE_MOUSE},
+ {0, 0, 0, 0L, 0L, 0L, 0, 0, "s", SHAPE_MOUSE},
+ {0, 0, 0, 0L, 0L, 0L, 0, 0, "sd", SHAPE_MOUSE},
+ {0, 0, 0, 0L, 0L, 0L, 0, 0, "vs", SHAPE_MOUSE},
+ {0, 0, 0, 0L, 0L, 0L, 0, 0, "vd", SHAPE_MOUSE},
+ {0, 0, 0, 0L, 0L, 0L, 0, 0, "m", SHAPE_MOUSE},
+ {0, 0, 0, 0L, 0L, 0L, 0, 0, "ml", SHAPE_MOUSE},
+ {0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR},
+};
+
+#ifdef FEAT_MOUSESHAPE
+/*
+ * Table with names for mouse shapes. Keep in sync with all the tables for
+ * mch_set_mouse_shape()!.
+ */
+static char * mshape_names[] =
+{
+ "arrow", /* default, must be the first one */
+ "blank", /* hidden */
+ "beam",
+ "updown",
+ "udsizing",
+ "leftright",
+ "lrsizing",
+ "busy",
+ "no",
+ "crosshair",
+ "hand1",
+ "hand2",
+ "pencil",
+ "question",
+ "rightup-arrow",
+ "up-arrow",
+ NULL
+};
+#endif
+
+/*
+ * Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape'
+ * ("what" is SHAPE_MOUSE).
+ * Returns error message for an illegal option, NULL otherwise.
+ */
+ char_u *
+parse_shape_opt(what)
+ int what;
+{
+ char_u *modep;
+ char_u *colonp;
+ char_u *commap;
+ char_u *slashp;
+ char_u *p, *endp;
+ int idx = 0; /* init for GCC */
+ int all_idx;
+ int len;
+ int i;
+ long n;
+ int found_ve = FALSE; /* found "ve" flag */
+ int round;
+
+ /*
+ * First round: check for errors; second round: do it for real.
+ */
+ for (round = 1; round <= 2; ++round)
+ {
+ /*
+ * Repeat for all comma separated parts.
+ */
+#ifdef FEAT_MOUSESHAPE
+ if (what == SHAPE_MOUSE)
+ modep = p_mouseshape;
+ else
+#endif
+ modep = p_guicursor;
+ while (*modep != NUL)
+ {
+ colonp = vim_strchr(modep, ':');
+ if (colonp == NULL)
+ return (char_u *)N_("E545: Missing colon");
+ if (colonp == modep)
+ return (char_u *)N_("E546: Illegal mode");
+ commap = vim_strchr(modep, ',');
+
+ /*
+ * Repeat for all mode's before the colon.
+ * For the 'a' mode, we loop to handle all the modes.
+ */
+ all_idx = -1;
+ while (modep < colonp || all_idx >= 0)
+ {
+ if (all_idx < 0)
+ {
+ /* Find the mode. */
+ if (modep[1] == '-' || modep[1] == ':')
+ len = 1;
+ else
+ len = 2;
+ if (len == 1 && TOLOWER_ASC(modep[0]) == 'a')
+ all_idx = SHAPE_IDX_COUNT - 1;
+ else
+ {
+ for (idx = 0; idx < SHAPE_IDX_COUNT; ++idx)
+ if (STRNICMP(modep, shape_table[idx].name, len)
+ == 0)
+ break;
+ if (idx == SHAPE_IDX_COUNT
+ || (shape_table[idx].used_for & what) == 0)
+ return (char_u *)N_("E546: Illegal mode");
+ if (len == 2 && modep[0] == 'v' && modep[1] == 'e')
+ found_ve = TRUE;
+ }
+ modep += len + 1;
+ }
+
+ if (all_idx >= 0)
+ idx = all_idx--;
+ else if (round == 2)
+ {
+#ifdef FEAT_MOUSESHAPE
+ if (what == SHAPE_MOUSE)
+ {
+ /* Set the default, for the missing parts */
+ shape_table[idx].mshape = 0;
+ }
+ else
+#endif
+ {
+ /* Set the defaults, for the missing parts */
+ shape_table[idx].shape = SHAPE_BLOCK;
+ shape_table[idx].blinkwait = 700L;
+ shape_table[idx].blinkon = 400L;
+ shape_table[idx].blinkoff = 250L;
+ }
+ }
+
+ /* Parse the part after the colon */
+ for (p = colonp + 1; *p && *p != ','; )
+ {
+#ifdef FEAT_MOUSESHAPE
+ if (what == SHAPE_MOUSE)
+ {
+ for (i = 0; ; ++i)
+ {
+ if (mshape_names[i] == NULL)
+ {
+ if (!VIM_ISDIGIT(*p))
+ return (char_u *)N_("E547: Illegal mouseshape");
+ if (round == 2)
+ shape_table[idx].mshape =
+ getdigits(&p) + MSHAPE_NUMBERED;
+ else
+ (void)getdigits(&p);
+ break;
+ }
+ len = (int)STRLEN(mshape_names[i]);
+ if (STRNICMP(p, mshape_names[i], len) == 0)
+ {
+ if (round == 2)
+ shape_table[idx].mshape = i;
+ p += len;
+ break;
+ }
+ }
+ }
+ else /* if (what == SHAPE_MOUSE) */
+#endif
+ {
+ /*
+ * First handle the ones with a number argument.
+ */
+ i = *p;
+ len = 0;
+ if (STRNICMP(p, "ver", 3) == 0)
+ len = 3;
+ else if (STRNICMP(p, "hor", 3) == 0)
+ len = 3;
+ else if (STRNICMP(p, "blinkwait", 9) == 0)
+ len = 9;
+ else if (STRNICMP(p, "blinkon", 7) == 0)
+ len = 7;
+ else if (STRNICMP(p, "blinkoff", 8) == 0)
+ len = 8;
+ if (len != 0)
+ {
+ p += len;
+ if (!VIM_ISDIGIT(*p))
+ return (char_u *)N_("E548: digit expected");
+ n = getdigits(&p);
+ if (len == 3) /* "ver" or "hor" */
+ {
+ if (n == 0)
+ return (char_u *)N_("E549: Illegal percentage");
+ if (round == 2)
+ {
+ if (TOLOWER_ASC(i) == 'v')
+ shape_table[idx].shape = SHAPE_VER;
+ else
+ shape_table[idx].shape = SHAPE_HOR;
+ shape_table[idx].percentage = n;
+ }
+ }
+ else if (round == 2)
+ {
+ if (len == 9)
+ shape_table[idx].blinkwait = n;
+ else if (len == 7)
+ shape_table[idx].blinkon = n;
+ else
+ shape_table[idx].blinkoff = n;
+ }
+ }
+ else if (STRNICMP(p, "block", 5) == 0)
+ {
+ if (round == 2)
+ shape_table[idx].shape = SHAPE_BLOCK;
+ p += 5;
+ }
+ else /* must be a highlight group name then */
+ {
+ endp = vim_strchr(p, '-');
+ if (commap == NULL) /* last part */
+ {
+ if (endp == NULL)
+ endp = p + STRLEN(p); /* find end of part */
+ }
+ else if (endp > commap || endp == NULL)
+ endp = commap;
+ slashp = vim_strchr(p, '/');
+ if (slashp != NULL && slashp < endp)
+ {
+ /* "group/langmap_group" */
+ i = syn_check_group(p, (int)(slashp - p));
+ p = slashp + 1;
+ }
+ if (round == 2)
+ {
+ shape_table[idx].id = syn_check_group(p,
+ (int)(endp - p));
+ shape_table[idx].id_lm = shape_table[idx].id;
+ if (slashp != NULL && slashp < endp)
+ shape_table[idx].id = i;
+ }
+ p = endp;
+ }
+ } /* if (what != SHAPE_MOUSE) */
+
+ if (*p == '-')
+ ++p;
+ }
+ }
+ modep = p;
+ if (*modep == ',')
+ ++modep;
+ }
+ }
+
+ /* If the 's' flag is not given, use the 'v' cursor for 's' */
+ if (!found_ve)
+ {
+#ifdef FEAT_MOUSESHAPE
+ if (what == SHAPE_MOUSE)
+ {
+ shape_table[SHAPE_IDX_VE].mshape = shape_table[SHAPE_IDX_V].mshape;
+ }
+ else
+#endif
+ {
+ shape_table[SHAPE_IDX_VE].shape = shape_table[SHAPE_IDX_V].shape;
+ shape_table[SHAPE_IDX_VE].percentage =
+ shape_table[SHAPE_IDX_V].percentage;
+ shape_table[SHAPE_IDX_VE].blinkwait =
+ shape_table[SHAPE_IDX_V].blinkwait;
+ shape_table[SHAPE_IDX_VE].blinkon =
+ shape_table[SHAPE_IDX_V].blinkon;
+ shape_table[SHAPE_IDX_VE].blinkoff =
+ shape_table[SHAPE_IDX_V].blinkoff;
+ shape_table[SHAPE_IDX_VE].id = shape_table[SHAPE_IDX_V].id;
+ shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Return the index into shape_table[] for the current mode.
+ * When "mouse" is TRUE, consider indexes valid for the mouse pointer.
+ */
+ int
+get_shape_idx(mouse)
+ int mouse;
+{
+#ifdef FEAT_MOUSESHAPE
+ if (mouse && (State == HITRETURN || State == ASKMORE))
+ {
+# ifdef FEAT_GUI
+ if (Y_2_ROW(gui_mch_get_mouse_y()) == Rows - 1)
+ return SHAPE_IDX_MOREL;
+# endif
+ return SHAPE_IDX_MORE;
+ }
+ if (mouse && drag_status_line)
+ return SHAPE_IDX_SDRAG;
+# ifdef FEAT_VERTSPLIT
+ if (mouse && drag_sep_line)
+ return SHAPE_IDX_VDRAG;
+# endif
+#endif
+ if (!mouse && State == SHOWMATCH)
+ return SHAPE_IDX_SM;
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ return SHAPE_IDX_R;
+#endif
+ if (State & REPLACE_FLAG)
+ return SHAPE_IDX_R;
+ if (State & INSERT)
+ return SHAPE_IDX_I;
+ if (State & CMDLINE)
+ {
+ if (cmdline_at_end())
+ return SHAPE_IDX_C;
+ if (cmdline_overstrike())
+ return SHAPE_IDX_CR;
+ return SHAPE_IDX_CI;
+ }
+ if (finish_op)
+ return SHAPE_IDX_O;
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ if (*p_sel == 'e')
+ return SHAPE_IDX_VE;
+ else
+ return SHAPE_IDX_V;
+ }
+#endif
+ return SHAPE_IDX_N;
+}
+
+# if defined(FEAT_MOUSESHAPE) || defined(PROTO)
+static int old_mouse_shape = 0;
+
+/*
+ * Set the mouse shape:
+ * If "shape" is -1, use shape depending on the current mode,
+ * depending on the current state.
+ * If "shape" is -2, only update the shape when it's CLINE or STATUS (used
+ * when the mouse moves off the status or command line).
+ */
+ void
+update_mouseshape(shape_idx)
+ int shape_idx;
+{
+ int new_mouse_shape;
+
+ /* Only works in GUI mode. */
+ if (!gui.in_use)
+ return;
+
+ /* Postpone the updating when more is to come. Speeds up executing of
+ * mappings. */
+ if (shape_idx == -1 && char_avail())
+ {
+ postponed_mouseshape = TRUE;
+ return;
+ }
+
+ if (shape_idx == -2
+ && old_mouse_shape != shape_table[SHAPE_IDX_CLINE].mshape
+ && old_mouse_shape != shape_table[SHAPE_IDX_STATUS].mshape
+ && old_mouse_shape != shape_table[SHAPE_IDX_VSEP].mshape)
+ return;
+ if (shape_idx < 0)
+ new_mouse_shape = shape_table[get_shape_idx(TRUE)].mshape;
+ else
+ new_mouse_shape = shape_table[shape_idx].mshape;
+ if (new_mouse_shape != old_mouse_shape)
+ {
+ mch_set_mouse_shape(new_mouse_shape);
+ old_mouse_shape = new_mouse_shape;
+ }
+ postponed_mouseshape = FALSE;
+}
+# endif
+
+#endif /* CURSOR_SHAPE */
+
+
+#ifdef FEAT_CRYPT
+/*
+ * Optional encryption suypport.
+ * Mohsin Ahmed, mosh@sasi.com, 98-09-24
+ * Based on zip/crypt sources.
+ *
+ * NOTE FOR USA: Since 2000 exporting this code from the USA is allowed to
+ * most countries. There are a few exceptions, but that still should not be a
+ * problem since this code was originally created in Europe and India.
+ */
+
+/* from zip.h */
+
+typedef unsigned short ush; /* unsigned 16-bit value */
+typedef unsigned long ulg; /* unsigned 32-bit value */
+
+static void make_crc_tab __ARGS((void));
+
+ulg crc_32_tab[256];
+
+/*
+ * Fill the CRC table.
+ */
+ static void
+make_crc_tab()
+{
+ ulg s,t,v;
+ static int done = FALSE;
+
+ if (done)
+ return;
+ for (t = 0; t < 256; t++)
+ {
+ v = t;
+ for (s = 0; s < 8; s++)
+ v = (v >> 1) ^ ((v & 1) * (ulg)0xedb88320L);
+ crc_32_tab[t] = v;
+ }
+ done = TRUE;
+}
+
+#define CRC32(c, b) (crc_32_tab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
+
+
+static ulg keys[3]; /* keys defining the pseudo-random sequence */
+
+/*
+ * Return the next byte in the pseudo-random sequence
+ */
+ int
+decrypt_byte()
+{
+ ush temp;
+
+ temp = (ush)keys[2] | 2;
+ return (int)(((unsigned)(temp * (temp ^ 1)) >> 8) & 0xff);
+}
+
+/*
+ * Update the encryption keys with the next byte of plain text
+ */
+ int
+update_keys(c)
+ int c; /* byte of plain text */
+{
+ keys[0] = CRC32(keys[0], c);
+ keys[1] += keys[0] & 0xff;
+ keys[1] = keys[1] * 134775813L + 1;
+ keys[2] = CRC32(keys[2], (int)(keys[1] >> 24));
+ return c;
+}
+
+/*
+ * Initialize the encryption keys and the random header according to
+ * the given password.
+ * If "passwd" is NULL or empty, don't do anything.
+ */
+ void
+crypt_init_keys(passwd)
+ char_u *passwd; /* password string with which to modify keys */
+{
+ if (passwd != NULL && *passwd != NUL)
+ {
+ make_crc_tab();
+ keys[0] = 305419896L;
+ keys[1] = 591751049L;
+ keys[2] = 878082192L;
+ while (*passwd != '\0')
+ update_keys((int)*passwd++);
+ }
+}
+
+/*
+ * Ask the user for a crypt key.
+ * When "store" is TRUE, the new key in stored in the 'key' option, and the
+ * 'key' option value is returned: Don't free it.
+ * When "store" is FALSE, the typed key is returned in allocated memory.
+ * Returns NULL on failure.
+ */
+ char_u *
+get_crypt_key(store, twice)
+ int store;
+ int twice; /* Ask for the key twice. */
+{
+ char_u *p1, *p2 = NULL;
+ int round;
+
+ for (round = 0; ; ++round)
+ {
+ cmdline_star = TRUE;
+ cmdline_row = msg_row;
+ p1 = getcmdline_prompt(NUL, round == 0
+ ? (char_u *)_("Enter encryption key: ")
+ : (char_u *)_("Enter same key again: "), 0);
+ cmdline_star = FALSE;
+
+ if (p1 == NULL)
+ break;
+
+ if (round == twice)
+ {
+ if (p2 != NULL && STRCMP(p1, p2) != 0)
+ {
+ MSG(_("Keys don't match!"));
+ vim_free(p1);
+ vim_free(p2);
+ p2 = NULL;
+ round = -1; /* do it again */
+ continue;
+ }
+ if (store)
+ {
+ set_option_value((char_u *)"key", 0L, p1, OPT_LOCAL);
+ vim_free(p1);
+ p1 = curbuf->b_p_key;
+ }
+ break;
+ }
+ p2 = p1;
+ }
+
+ /* since the user typed this, no need to wait for return */
+ need_wait_return = FALSE;
+ msg_didout = FALSE;
+
+ vim_free(p2);
+ return p1;
+}
+
+#endif /* FEAT_CRYPT */
+
+/* TODO: make some #ifdef for this */
+/*--------[ file searching ]-------------------------------------------------*/
+/*
+ * File searching functions for 'path', 'tags' and 'cdpath' options.
+ * External visible functions:
+ * vim_findfile_init() creates/initialises the search context
+ * vim_findfile_free_visited() free list of visited files/dirs of search
+ * context
+ * vim_findfile() find a file in the search context
+ * vim_findfile_cleanup() cleanup/free search context created by
+ * vim_findfile_init()
+ *
+ * All static functions and variables start with 'ff_'
+ *
+ * In general it works like this:
+ * First you create yourself a search context by calling vim_findfile_init().
+ * It is possible to give a search context from a previous call to
+ * vim_findfile_init(), so it can be reused. After this you call vim_findfile()
+ * until you are satisfied with the result or it returns NULL. On every call it
+ * returns the next file which matches the conditions given to
+ * vim_findfile_init(). If it doesn't find a next file it returns NULL.
+ *
+ * It is possible to call vim_findfile_init() again to reinitialise your search
+ * with some new parameters. Don't forget to pass your old search context to
+ * it, so it can reuse it and especially reuse the list of already visited
+ * directories. If you want to delete the list of already visited directories
+ * simply call vim_findfile_free_visited().
+ *
+ * When you are done call vim_findfile_cleanup() to free the search context.
+ *
+ * The function vim_findfile_init() has a long comment, which describes the
+ * needed parameters.
+ *
+ *
+ *
+ * ATTENTION:
+ * ==========
+ * Also we use an allocated search context here, this functions ARE NOT
+ * thread-safe!!!!!
+ *
+ * To minimize parameter passing (or because I'm to lazy), only the
+ * external visible functions get a search context as a parameter. This is
+ * then assigned to a static global, which is used throughout the local
+ * functions.
+ */
+
+/*
+ * type for the directory search stack
+ */
+typedef struct ff_stack
+{
+ struct ff_stack *ffs_prev;
+
+ /* the fix part (no wildcards) and the part containing the wildcards
+ * of the search path
+ */
+ char_u *ffs_fix_path;
+#ifdef FEAT_PATH_EXTRA
+ char_u *ffs_wc_path;
+#endif
+
+ /* files/dirs found in the above directory, matched by the first wildcard
+ * of wc_part
+ */
+ char_u **ffs_filearray;
+ int ffs_filearray_size;
+ char_u ffs_filearray_cur; /* needed for partly handled dirs */
+
+ /* to store status of partly handled directories
+ * 0: we work the on this directory for the first time
+ * 1: this directory was partly searched in an earlier step
+ */
+ int ffs_stage;
+
+ /* How deep are we in the directory tree?
+ * Counts backward from value of level parameter to vim_findfile_init
+ */
+ int ffs_level;
+
+ /* Did we already expand '**' to an empty string? */
+ int ffs_star_star_empty;
+} ff_stack_T;
+
+/*
+ * type for already visited directories or files.
+ */
+typedef struct ff_visited
+{
+ struct ff_visited *ffv_next;
+
+#ifdef FEAT_PATH_EXTRA
+ /* Visited directories are different if the wildcard string are
+ * different. So we have to save it.
+ */
+ char_u *ffv_wc_path;
+#endif
+ /* for unix use inode etc for comparison (needed because of links), else
+ * use filename.
+ */
+#ifdef UNIX
+ int ffv_dev; /* device number (-1 if not set) */
+ ino_t ffv_ino; /* inode number */
+#endif
+ /* The memory for this struct is allocated according to the length of
+ * ffv_fname.
+ */
+ char_u ffv_fname[1]; /* actually longer */
+} ff_visited_T;
+
+/*
+ * We might have to manage several visited lists during a search.
+ * This is expecially needed for the tags option. If tags is set to:
+ * "./++/tags,./++/TAGS,++/tags" (replace + with *)
+ * So we have to do 3 searches:
+ * 1) search from the current files directory downward for the file "tags"
+ * 2) search from the current files directory downward for the file "TAGS"
+ * 3) search from Vims current directory downwards for the file "tags"
+ * As you can see, the first and the third search are for the same file, so for
+ * the third search we can use the visited list of the first search. For the
+ * second search we must start from a empty visited list.
+ * The struct ff_visited_list_hdr is used to manage a linked list of already
+ * visited lists.
+ */
+typedef struct ff_visited_list_hdr
+{
+ struct ff_visited_list_hdr *ffvl_next;
+
+ /* the filename the attached visited list is for */
+ char_u *ffvl_filename;
+
+ ff_visited_T *ffvl_visited_list;
+
+} ff_visited_list_hdr_T;
+
+
+/*
+ * '**' can be expanded to several directory levels.
+ * Set the default maximium depth.
+ */
+#define FF_MAX_STAR_STAR_EXPAND ((char_u)30)
+/*
+ * The search context:
+ * ffsc_stack_ptr: the stack for the dirs to search
+ * ffsc_visited_list: the currently active visited list
+ * ffsc_dir_visited_list: the currently active visited list for search dirs
+ * ffsc_visited_lists_list: the list of all visited lists
+ * ffsc_dir_visited_lists_list: the list of all visited lists for search dirs
+ * ffsc_file_to_search: the file to search for
+ * ffsc_start_dir: the starting directory, if search path was relative
+ * ffsc_fix_path: the fix part of the given path (without wildcards)
+ * Needed for upward search.
+ * ffsc_wc_path: the part of the given path containing wildcards
+ * ffsc_level: how many levels of dirs to search downwards
+ * ffsc_stopdirs_v: array of stop directories for upward search
+ * ffsc_need_dir: TRUE if we search for a directory
+ */
+typedef struct ff_search_ctx_T
+{
+ ff_stack_T *ffsc_stack_ptr;
+ ff_visited_list_hdr_T *ffsc_visited_list;
+ ff_visited_list_hdr_T *ffsc_dir_visited_list;
+ ff_visited_list_hdr_T *ffsc_visited_lists_list;
+ ff_visited_list_hdr_T *ffsc_dir_visited_lists_list;
+ char_u *ffsc_file_to_search;
+ char_u *ffsc_start_dir;
+ char_u *ffsc_fix_path;
+#ifdef FEAT_PATH_EXTRA
+ char_u *ffsc_wc_path;
+ int ffsc_level;
+ char_u **ffsc_stopdirs_v;
+#endif
+ int ffsc_need_dir;
+}ff_search_ctx_T;
+static ff_search_ctx_T *ff_search_ctx = NULL;
+
+/* used for expanding filenames */
+static char_u *ff_expand_buffer = NULL;
+
+/* locally needed functions */
+#ifdef FEAT_PATH_EXTRA
+static int ff_check_visited __ARGS((ff_visited_T **, char_u *, char_u *));
+#else
+static int ff_check_visited __ARGS((ff_visited_T **, char_u *));
+#endif
+static void vim_findfile_free_visited_list __ARGS((ff_visited_list_hdr_T **list_headp));
+static void ff_free_visited_list __ARGS((ff_visited_T *vl));
+static ff_visited_list_hdr_T* ff_get_visited_list __ARGS((char_u *, ff_visited_list_hdr_T **list_headp));
+#ifdef FEAT_PATH_EXTRA
+static int ff_wc_equal __ARGS((char_u *s1, char_u *s2));
+#endif
+
+static void ff_push __ARGS((ff_stack_T *));
+static ff_stack_T * ff_pop __ARGS((void));
+static void ff_clear __ARGS((void));
+static void ff_free_stack_element __ARGS((ff_stack_T *));
+#ifdef FEAT_PATH_EXTRA
+static ff_stack_T *ff_create_stack_element __ARGS((char_u *, char_u *, int, int));
+#else
+static ff_stack_T *ff_create_stack_element __ARGS((char_u *, int, int));
+#endif
+#ifdef FEAT_PATH_EXTRA
+static int ff_path_in_stoplist __ARGS((char_u *, int, char_u **));
+#endif
+
+#ifdef FEAT_SEARCHPATH
+static char_u *find_file_in_path_option __ARGS((char_u *ptr, int len, int options, int first, char_u *path_option, int need_dir, char_u *rel_fname));
+#endif
+
+#if 0
+/*
+ * if someone likes findfirst/findnext, here are the functions
+ * NOT TESTED!!
+ */
+
+static void *ff_fn_search_context = NULL;
+
+ char_u *
+vim_findfirst(path, filename, level)
+ char_u *path;
+ char_u *filename;
+ int level;
+{
+ ff_fn_search_context =
+ vim_findfile_init(path, filename, NULL, level, TRUE, FALSE,
+ ff_fn_search_context, rel_fname);
+ if (NULL == ff_fn_search_context)
+ return NULL;
+ else
+ return vim_findnext()
+}
+
+ char_u *
+vim_findnext()
+{
+ char_u *ret = vim_findfile(ff_fn_search_context);
+
+ if (NULL == ret)
+ {
+ vim_findfile_cleanup(ff_fn_search_context);
+ ff_fn_search_context = NULL;
+ }
+ return ret;
+}
+#endif
+
+/*
+ * Initialization routine for vim_findfile.
+ *
+ * Returns the newly allocated search context or NULL if an error occured.
+ *
+ * Don't forget to clean up by calling vim_findfile_cleanup() if you are done
+ * with the search context.
+ *
+ * Find the file 'filename' in the directory 'path'.
+ * The parameter 'path' may contain wildcards. If so only search 'level'
+ * directories deep. The parameter 'level' is the absolute maximum and is
+ * not related to restricts given to the '**' wildcard. If 'level' is 100
+ * and you use '**200' vim_findfile() will stop after 100 levels.
+ *
+ * If 'stopdirs' is not NULL and nothing is found downward, the search is
+ * restarted on the next higher directory level. This is repeated until the
+ * start-directory of a search is contained in 'stopdirs'. 'stopdirs' has the
+ * format ";*<dirname>*\(;<dirname>\)*;\=$".
+ *
+ * If the 'path' is relative, the starting dir for the search is either VIM's
+ * current dir or if the path starts with "./" the current files dir.
+ * If the 'path' is absolut, the starting dir is that part of the path before
+ * the first wildcard.
+ *
+ * Upward search is only done on the starting dir.
+ *
+ * If 'free_visited' is TRUE the list of already visited files/directories is
+ * cleared. Set this to FALSE if you just want to search from another
+ * directory, but want to be sure that no directory from a previous search is
+ * searched again. This is useful if you search for a file at different places.
+ * The list of visited files/dirs can also be cleared with the function
+ * vim_findfile_free_visited().
+ *
+ * Set the parameter 'need_dir' to TRUE if you want to search for a directory
+ * instead of a file.
+ *
+ * A search context returned by a previous call to vim_findfile_init() can be
+ * passed in the parameter 'search_ctx'. This context is than reused and
+ * reinitialized with the new parameters. The list of already viseted
+ * directories from this context is only deleted if the parameter
+ * 'free_visited' is true. Be aware that the passed search_context is freed if
+ * the reinitialization fails.
+ *
+ * If you don't have a search context from a previous call 'search_ctx' must be
+ * NULL.
+ *
+ * This function silently ignores a few errors, vim_findfile() will have
+ * limited functionality then.
+ */
+/*ARGSUSED*/
+ void *
+vim_findfile_init(path, filename, stopdirs, level, free_visited, need_dir,
+ search_ctx, tagfile, rel_fname)
+ char_u *path;
+ char_u *filename;
+ char_u *stopdirs;
+ int level;
+ int free_visited;
+ int need_dir;
+ void *search_ctx;
+ int tagfile;
+ char_u *rel_fname; /* file name to use for "." */
+{
+#ifdef FEAT_PATH_EXTRA
+ char_u *wc_part;
+#endif
+ ff_stack_T *sptr;
+
+ /* If a search context is given by the caller, reuse it, else allocate a
+ * new one.
+ */
+ if (search_ctx != NULL)
+ ff_search_ctx = search_ctx;
+ else
+ {
+ ff_search_ctx = (ff_search_ctx_T*)alloc(
+ (unsigned)sizeof(ff_search_ctx_T));
+ if (ff_search_ctx == NULL)
+ goto error_return;
+ memset(ff_search_ctx, 0, sizeof(ff_search_ctx_T));
+ }
+
+ /* clear the search context, but NOT the visited lists */
+ ff_clear();
+
+ /* clear visited list if wanted */
+ if (free_visited == TRUE)
+ vim_findfile_free_visited(ff_search_ctx);
+ else
+ {
+ /* Reuse old visited lists. Get the visited list for the given
+ * filename. If no list for the current filename exists, creates a new
+ * one.
+ */
+ ff_search_ctx->ffsc_visited_list = ff_get_visited_list(filename,
+ &ff_search_ctx->ffsc_visited_lists_list);
+ if (ff_search_ctx->ffsc_visited_list == NULL)
+ goto error_return;
+ ff_search_ctx->ffsc_dir_visited_list = ff_get_visited_list(filename,
+ &ff_search_ctx->ffsc_dir_visited_lists_list);
+ if (ff_search_ctx->ffsc_dir_visited_list == NULL)
+ goto error_return;
+ }
+
+ if (ff_expand_buffer == NULL)
+ {
+ ff_expand_buffer = (char_u*)alloc(MAXPATHL);
+ if (ff_expand_buffer == NULL)
+ goto error_return;
+ }
+
+ /* Store information on starting dir now if path is relative.
+ * If path is absolute, we do that later.
+ */
+ if (path[0] == '.'
+ && (vim_ispathsep(path[1]) || path[1] == NUL)
+ && (!tagfile || vim_strchr(p_cpo, CPO_DOTTAG) == NULL)
+ && rel_fname != NULL)
+ {
+ int len = (int)(gettail(rel_fname) - rel_fname);
+
+ if (!vim_isAbsName(rel_fname) && len + 1 < MAXPATHL)
+ {
+ /* Make the start dir an absolute path name. */
+ STRNCPY(ff_expand_buffer, rel_fname, len);
+ ff_expand_buffer[len] = NUL;
+ ff_search_ctx->ffsc_start_dir = FullName_save(ff_expand_buffer,
+ FALSE);
+ }
+ else
+ ff_search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len);
+ if (ff_search_ctx->ffsc_start_dir == NULL)
+ goto error_return;
+ if (*++path != NUL)
+ ++path;
+ }
+ else if (*path == NUL || !vim_isAbsName(path))
+ {
+#ifdef BACKSLASH_IN_FILENAME
+ /* "c:dir" needs "c:" to be expanded, otherwise use current dir */
+ if (*path != NUL && path[1] == ':')
+ {
+ char_u drive[3];
+
+ drive[0] = path[0];
+ drive[1] = ':';
+ drive[2] = NUL;
+ if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, TRUE) == FAIL)
+ goto error_return;
+ path += 2;
+ }
+ else
+#endif
+ if (mch_dirname(ff_expand_buffer, MAXPATHL) == FAIL)
+ goto error_return;
+
+ ff_search_ctx->ffsc_start_dir = vim_strsave(ff_expand_buffer);
+ if (ff_search_ctx->ffsc_start_dir == NULL)
+ goto error_return;
+
+#ifdef BACKSLASH_IN_FILENAME
+ /* A path that starts with "/dir" is relative to the drive, not to the
+ * directory (but not for "//machine/dir"). Only use the drive name. */
+ if ((*path == '/' || *path == '\\')
+ && path[1] != path[0]
+ && ff_search_ctx->ffsc_start_dir[1] == ':')
+ ff_search_ctx->ffsc_start_dir[2] = NUL;
+#endif
+ }
+
+#ifdef FEAT_PATH_EXTRA
+ /*
+ * If stopdirs are given, split them into an array of pointers.
+ * If this fails (mem allocation), there is no upward search at all or a
+ * stop directory is not recognized -> continue silently.
+ * If stopdirs just contains a ";" or is empty,
+ * ff_search_ctx->ffsc_stopdirs_v will only contain a NULL pointer. This
+ * is handled as unlimited upward search. See function
+ * ff_path_in_stoplist() for details.
+ */
+ if (stopdirs != NULL)
+ {
+ char_u *walker = stopdirs;
+ int dircount;
+
+ while (*walker == ';')
+ walker++;
+
+ dircount = 1;
+ ff_search_ctx->ffsc_stopdirs_v =
+ (char_u **)alloc((unsigned)sizeof(char_u *));
+
+ if (ff_search_ctx->ffsc_stopdirs_v != NULL)
+ {
+ do
+ {
+ char_u *helper;
+ void *ptr;
+
+ helper = walker;
+ ptr = vim_realloc(ff_search_ctx->ffsc_stopdirs_v,
+ (dircount + 1) * sizeof(char_u *));
+ if (ptr)
+ ff_search_ctx->ffsc_stopdirs_v = ptr;
+ else
+ /* ignore, keep what we have and continue */
+ break;
+ walker = vim_strchr(walker, ';');
+ if (walker)
+ {
+ ff_search_ctx->ffsc_stopdirs_v[dircount-1] =
+ vim_strnsave(helper, (int)(walker - helper));
+ walker++;
+ }
+ else
+ /* this might be "", which means ascent till top
+ * of directory tree.
+ */
+ ff_search_ctx->ffsc_stopdirs_v[dircount-1] =
+ vim_strsave(helper);
+
+ dircount++;
+
+ } while (walker != NULL);
+ ff_search_ctx->ffsc_stopdirs_v[dircount-1] = NULL;
+ }
+ }
+#endif
+
+#ifdef FEAT_PATH_EXTRA
+ ff_search_ctx->ffsc_level = level;
+
+ /* split into:
+ * -fix path
+ * -wildcard_stuff (might be NULL)
+ */
+ wc_part = vim_strchr(path, '*');
+ if (wc_part != NULL)
+ {
+ int llevel;
+ int len;
+ char_u *errpt;
+
+ /* save the fix part of the path */
+ ff_search_ctx->ffsc_fix_path = vim_strnsave(path,
+ (int)(wc_part - path));
+
+ /*
+ * copy wc_path and add restricts to the '**' wildcard.
+ * The octett after a '**' is used as a (binary) counter.
+ * So '**3' is transposed to '**^C' ('^C' is ASCII value 3)
+ * or '**76' is transposed to '**N'( 'N' is ASCII value 76).
+ * For EBCDIC you get different character values.
+ * If no restrict is given after '**' the default is used.
+ * Due to this technic the path looks awful if you print it as a
+ * string.
+ */
+ len = 0;
+ while (*wc_part != NUL)
+ {
+ if (STRNCMP(wc_part, "**", 2) == 0)
+ {
+ ff_expand_buffer[len++] = *wc_part++;
+ ff_expand_buffer[len++] = *wc_part++;
+
+ llevel = strtol((char *)wc_part, (char **)&errpt, 10);
+ if (errpt != wc_part && llevel > 0 && llevel < 255)
+ ff_expand_buffer[len++] = llevel;
+ else if (errpt != wc_part && llevel == 0)
+ /* restrict is 0 -> remove already added '**' */
+ len -= 2;
+ else
+ ff_expand_buffer[len++] = FF_MAX_STAR_STAR_EXPAND;
+ wc_part = errpt;
+ if (*wc_part != PATHSEP && *wc_part != NUL)
+ {
+ EMSG2(_("E343: Invalid path: '**[number]' must be at the end of the path or be followed by '%s'."), PATHSEPSTR);
+ goto error_return;
+ }
+ }
+ else
+ ff_expand_buffer[len++] = *wc_part++;
+ }
+ ff_expand_buffer[len] = NUL;
+ ff_search_ctx->ffsc_wc_path =
+ vim_strsave(ff_expand_buffer);
+
+ if (ff_search_ctx->ffsc_wc_path == NULL)
+ goto error_return;
+ }
+ else
+#endif
+ ff_search_ctx->ffsc_fix_path = vim_strsave(path);
+
+ if (ff_search_ctx->ffsc_start_dir == NULL)
+ {
+ /* store the fix part as startdir.
+ * This is needed if the parameter path is fully qualified.
+ */
+ ff_search_ctx->ffsc_start_dir = vim_strsave(ff_search_ctx->ffsc_fix_path);
+ if (ff_search_ctx->ffsc_start_dir)
+ ff_search_ctx->ffsc_fix_path[0] = NUL;
+ }
+
+ /* create an absolute path */
+ STRCPY(ff_expand_buffer, ff_search_ctx->ffsc_start_dir);
+ add_pathsep(ff_expand_buffer);
+ STRCAT(ff_expand_buffer, ff_search_ctx->ffsc_fix_path);
+ add_pathsep(ff_expand_buffer);
+
+ sptr = ff_create_stack_element(ff_expand_buffer,
+#ifdef FEAT_PATH_EXTRA
+ ff_search_ctx->ffsc_wc_path,
+#endif
+ level, 0);
+
+ if (sptr == NULL)
+ goto error_return;
+
+ ff_push(sptr);
+
+ ff_search_ctx->ffsc_file_to_search = vim_strsave(filename);
+ if (ff_search_ctx->ffsc_file_to_search == NULL)
+ goto error_return;
+
+ return ff_search_ctx;
+
+error_return:
+ /*
+ * We clear the search context now!
+ * Even when the caller gave us a (perhaps valid) context we free it here,
+ * as we might have already destroyed it.
+ */
+ vim_findfile_cleanup(ff_search_ctx);
+ return NULL;
+}
+
+#if defined(FEAT_PATH_EXTRA) || defined(PROTO)
+/*
+ * Get the stopdir string. Check that ';' is not escaped.
+ */
+ char_u *
+vim_findfile_stopdir(buf)
+ char_u *buf;
+{
+ char_u *r_ptr = buf;
+
+ while (*r_ptr != NUL && *r_ptr != ';')
+ {
+ if (r_ptr[0] == '\\' && r_ptr[1] == ';')
+ {
+ /* overwrite the escape char,
+ * use STRLEN(r_ptr) to move the trailing '\0'
+ */
+ mch_memmove(r_ptr, r_ptr + 1, STRLEN(r_ptr));
+ r_ptr++;
+ }
+ r_ptr++;
+ }
+ if (*r_ptr == ';')
+ {
+ *r_ptr = 0;
+ r_ptr++;
+ }
+ else if (*r_ptr == NUL)
+ r_ptr = NULL;
+ return r_ptr;
+}
+#endif
+
+/* Clean up the given search context. Can handle a NULL pointer */
+ void
+vim_findfile_cleanup(ctx)
+ void *ctx;
+{
+ if (NULL == ctx)
+ return;
+
+ ff_search_ctx = ctx;
+
+ vim_findfile_free_visited(ctx);
+ ff_clear();
+ vim_free(ctx);
+ ff_search_ctx = NULL;
+}
+
+/*
+ * Find a file in a search context.
+ * The search context was created with vim_findfile_init() above.
+ * Return a pointer to an allocated file name or NULL if nothing found.
+ * To get all matching files call this function until you get NULL.
+ *
+ * If the passed search_context is NULL, it the returns NULL.
+ *
+ * The search algorithm is depth first. To change this replace the
+ * stack with a list (don't forget to leave partly searched directories on the
+ * top of the list).
+ */
+ char_u *
+vim_findfile(search_ctx)
+ void *search_ctx;
+{
+ char_u *file_path;
+#ifdef FEAT_PATH_EXTRA
+ char_u *rest_of_wildcards;
+ char_u *path_end = NULL;
+#endif
+ ff_stack_T *ctx;
+#if defined(FEAT_SEARCHPATH) || defined(FEAT_PATH_EXTRA)
+ int len;
+#endif
+ int i;
+ char_u *p;
+#ifdef FEAT_SEARCHPATH
+ char_u *suf;
+#endif
+
+ if (search_ctx == NULL)
+ return NULL;
+
+ ff_search_ctx = (ff_search_ctx_T*)search_ctx;
+
+ /*
+ * filepath is used as buffer for various actions and as the storage to
+ * return a found filename.
+ */
+ if ((file_path = alloc((int)MAXPATHL)) == NULL)
+ return NULL;
+
+#ifdef FEAT_PATH_EXTRA
+ /* store the end of the start dir -- needed for upward search */
+ if (ff_search_ctx->ffsc_start_dir != NULL)
+ path_end = &ff_search_ctx->ffsc_start_dir[STRLEN(ff_search_ctx->ffsc_start_dir)];
+#endif
+
+#ifdef FEAT_PATH_EXTRA
+ /* upward search loop */
+ for (;;)
+ {
+#endif
+ /* downward search loop */
+ for (;;)
+ {
+ /* check if user user wants to stop the search*/
+ ui_breakcheck();
+ if (got_int)
+ break;
+
+ /* get directory to work on from stack */
+ ctx = ff_pop();
+ if (ctx == NULL)
+ break;
+
+ /*
+ * TODO: decide if we leave this test in
+ *
+ * GOOD: don't search a directory(-tree) twice.
+ * BAD: - check linked list for every new directory entered.
+ * - check for double files also done below
+ *
+ * Here we check if we already searched this directory.
+ * We already searched a directory if:
+ * 1) The directory is the same.
+ * 2) We would use the same wildcard string.
+ *
+ * Good if you have links on same directory via several ways
+ * or you have selfreferences in directories (e.g. SuSE Linux 6.3:
+ * /etc/rc.d/init.d is linked to /etc/rc.d -> endless loop)
+ *
+ * This check is only needed for directories we work on for the
+ * first time (hence ctx->ff_filearray == NULL)
+ */
+ if (ctx->ffs_filearray == NULL
+ && ff_check_visited(&ff_search_ctx->ffsc_dir_visited_list
+ ->ffvl_visited_list,
+ ctx->ffs_fix_path
+#ifdef FEAT_PATH_EXTRA
+ , ctx->ffs_wc_path
+#endif
+ ) == FAIL)
+ {
+#ifdef FF_VERBOSE
+ if (p_verbose >= 5)
+ {
+ /* always scroll up, don't overwrite */
+ msg_scroll = TRUE;
+ smsg((char_u *)"Already Searched: %s (%s)",
+ ctx->ffs_fix_path, ctx->ffs_wc_path);
+ /* don't overwrite this either */
+ msg_puts((char_u *)"\n");
+ cmdline_row = msg_row;
+ }
+#endif
+ ff_free_stack_element(ctx);
+ continue;
+ }
+#ifdef FF_VERBOSE
+ else if (p_verbose >= 5)
+ {
+ /* always scroll up, don't overwrite */
+ msg_scroll = TRUE;
+ smsg((char_u *)"Searching: %s (%s)", ctx->ffs_fix_path,
+ ctx->ffs_wc_path);
+ /* don't overwrite this either */
+ msg_puts((char_u *)"\n");
+ cmdline_row = msg_row;
+ }
+#endif
+
+ /* check depth */
+ if (ctx->ffs_level <= 0)
+ {
+ ff_free_stack_element(ctx);
+ continue;
+ }
+
+ file_path[0] = NUL;
+
+ /*
+ * If no filearray till now expand wildcards
+ * The function expand_wildcards() can handle an array of paths
+ * and all possible expands are returned in one array. We use this
+ * to handle the expansion of '**' into an empty string.
+ */
+ if (ctx->ffs_filearray == NULL)
+ {
+ char_u *dirptrs[2];
+
+ /* we use filepath to build the path expand_wildcards() should
+ * expand.
+ */
+ dirptrs[0] = file_path;
+ dirptrs[1] = NULL;
+
+ /* if we have a start dir copy it in */
+ if (!vim_isAbsName(ctx->ffs_fix_path)
+ && ff_search_ctx->ffsc_start_dir)
+ {
+ STRCPY(file_path, ff_search_ctx->ffsc_start_dir);
+ add_pathsep(file_path);
+ }
+
+ /* append the fix part of the search path */
+ STRCAT(file_path, ctx->ffs_fix_path);
+ add_pathsep(file_path);
+
+#ifdef FEAT_PATH_EXTRA
+ rest_of_wildcards = ctx->ffs_wc_path;
+ if (*rest_of_wildcards != NUL)
+ {
+ len = (int)STRLEN(file_path);
+ if (STRNCMP(rest_of_wildcards, "**", 2) == 0)
+ {
+ /* pointer to the restrict byte
+ * The restrict byte is not a character!
+ */
+ p = rest_of_wildcards + 2;
+
+ if (*p > 0)
+ {
+ (*p)--;
+ file_path[len++] = '*';
+ }
+
+ if (*p == 0)
+ {
+ /* remove '**<numb> from wildcards */
+ mch_memmove(rest_of_wildcards,
+ rest_of_wildcards + 3,
+ STRLEN(rest_of_wildcards + 3) + 1);
+ }
+ else
+ rest_of_wildcards += 3;
+
+ if (ctx->ffs_star_star_empty == 0)
+ {
+ /* if not done before, expand '**' to empty */
+ ctx->ffs_star_star_empty = 1;
+ dirptrs[1] = ctx->ffs_fix_path;
+ }
+ }
+
+ /*
+ * Here we copy until the next path separator or the end of
+ * the path. If we stop at a path separator, there is
+ * still somthing else left. This is handled below by
+ * pushing every directory returned from expand_wildcards()
+ * on the stack again for further search.
+ */
+ while (*rest_of_wildcards
+ && !vim_ispathsep(*rest_of_wildcards))
+ file_path[len++] = *rest_of_wildcards++;
+
+ file_path[len] = NUL;
+ if (vim_ispathsep(*rest_of_wildcards))
+ rest_of_wildcards++;
+ }
+#endif
+
+ /*
+ * Expand wildcards like "*" and "$VAR".
+ * If the path is a URL don't try this.
+ */
+ if (path_with_url(dirptrs[0]))
+ {
+ ctx->ffs_filearray = (char_u **)
+ alloc((unsigned)sizeof(char *));
+ if (ctx->ffs_filearray != NULL
+ && (ctx->ffs_filearray[0]
+ = vim_strsave(dirptrs[0])) != NULL)
+ ctx->ffs_filearray_size = 1;
+ else
+ ctx->ffs_filearray_size = 0;
+ }
+ else
+ expand_wildcards((dirptrs[1] == NULL) ? 1 : 2, dirptrs,
+ &ctx->ffs_filearray_size,
+ &ctx->ffs_filearray,
+ EW_DIR|EW_ADDSLASH|EW_SILENT);
+
+ ctx->ffs_filearray_cur = 0;
+ ctx->ffs_stage = 0;
+ }
+#ifdef FEAT_PATH_EXTRA
+ else
+ rest_of_wildcards = &ctx->ffs_wc_path[STRLEN(ctx->ffs_wc_path)];
+#endif
+
+ if (ctx->ffs_stage == 0)
+ {
+ /* this is the first time we work on this directory */
+#ifdef FEAT_PATH_EXTRA
+ if (*rest_of_wildcards == NUL)
+#endif
+ {
+ /*
+ * we don't have further wildcards to expand, so we have to
+ * check for the final file now
+ */
+ for (i = ctx->ffs_filearray_cur;
+ i < ctx->ffs_filearray_size; ++i)
+ {
+ if (!path_with_url(ctx->ffs_filearray[i])
+ && !mch_isdir(ctx->ffs_filearray[i]))
+ continue; /* not a directory */
+
+ /* prepare the filename to be checked for existance
+ * below */
+ STRCPY(file_path, ctx->ffs_filearray[i]);
+ add_pathsep(file_path);
+ STRCAT(file_path, ff_search_ctx->ffsc_file_to_search);
+
+ /*
+ * Try without extra suffix and then with suffixes
+ * from 'suffixesadd'.
+ */
+#ifdef FEAT_SEARCHPATH
+ len = (int)STRLEN(file_path);
+ suf = curbuf->b_p_sua;
+ for (;;)
+#endif
+ {
+ /* if file exists and we didn't already find it */
+ if ((path_with_url(file_path)
+ || (mch_getperm(file_path) >= 0
+ && (!ff_search_ctx->ffsc_need_dir
+ || mch_isdir(file_path))))
+#ifndef FF_VERBOSE
+ && (ff_check_visited(
+ &ff_search_ctx->ffsc_visited_list->ffvl_visited_list,
+ file_path
+#ifdef FEAT_PATH_EXTRA
+ , (char_u *)""
+#endif
+ ) == OK)
+#endif
+ )
+ {
+#ifdef FF_VERBOSE
+ if (ff_check_visited(
+ &ff_search_ctx->ffsc_visited_list->ffvl_visited_list,
+ file_path
+#ifdef FEAT_PATH_EXTRA
+ , (char_u *)""
+#endif
+ ) == FAIL)
+ {
+ if (p_verbose >= 5)
+ {
+ /* always scroll up, don't overwrite */
+ msg_scroll = TRUE;
+ msg_str((char_u *)"Already: %s",
+ file_path);
+ /* don't overwrite this either */
+ msg_puts((char_u *)"\n");
+ cmdline_row = msg_row;
+ }
+ continue;
+ }
+#endif
+
+ /* push dir to examine rest of subdirs later */
+ ctx->ffs_filearray_cur = i + 1;
+ ff_push(ctx);
+
+ simplify_filename(file_path);
+ if (mch_dirname(ff_expand_buffer, MAXPATHL)
+ == OK)
+ {
+ p = shorten_fname(file_path,
+ ff_expand_buffer);
+ if (p != NULL)
+ mch_memmove(file_path, p,
+ STRLEN(p) + 1);
+ }
+#ifdef FF_VERBOSE
+ if (p_verbose >= 5)
+ {
+ /* always scroll up, don't overwrite */
+ msg_scroll = TRUE;
+ msg_str((char_u *)"HIT: %s", file_path);
+ /* don't overwrite this either */
+ msg_puts((char_u *)"\n");
+ cmdline_row = msg_row;
+ }
+#endif
+ return file_path;
+ }
+
+#ifdef FEAT_SEARCHPATH
+ /* Not found or found already, try next suffix. */
+ if (*suf == NUL)
+ break;
+ copy_option_part(&suf, file_path + len,
+ MAXPATHL - len, ",");
+#endif
+ }
+ }
+ }
+#ifdef FEAT_PATH_EXTRA
+ else
+ {
+ /*
+ * still wildcards left, push the directories for further
+ * search
+ */
+ for (i = ctx->ffs_filearray_cur; i < ctx->ffs_filearray_size;
+ ++i)
+ {
+ if (!mch_isdir(ctx->ffs_filearray[i]))
+ continue; /* not a directory */
+
+ ff_push(ff_create_stack_element(ctx->ffs_filearray[i],
+ rest_of_wildcards, ctx->ffs_level - 1, 0));
+ }
+ }
+#endif
+ ctx->ffs_filearray_cur = 0;
+ ctx->ffs_stage = 1;
+ }
+
+#ifdef FEAT_PATH_EXTRA
+ /*
+ * if wildcards contains '**' we have to descent till we reach the
+ * leaves of the directory tree.
+ */
+ if (STRNCMP(ctx->ffs_wc_path, "**", 2) == 0)
+ {
+ for (i = ctx->ffs_filearray_cur; i < ctx->ffs_filearray_size; ++i)
+ {
+ if (fnamecmp(ctx->ffs_filearray[i], ctx->ffs_fix_path) == 0)
+ continue; /* don't repush same directory */
+ if (!mch_isdir(ctx->ffs_filearray[i]))
+ continue; /* not a directory */
+ ff_push(ff_create_stack_element(ctx->ffs_filearray[i],
+ ctx->ffs_wc_path, ctx->ffs_level - 1, 1));
+ }
+ }
+#endif
+
+ /* we are done with the current directory */
+ ff_free_stack_element(ctx);
+
+ }
+
+#ifdef FEAT_PATH_EXTRA
+ /* If we reached this, we didn't find anything downwards.
+ * Let's check if we should do an upward search.
+ */
+ if (ff_search_ctx->ffsc_start_dir
+ && ff_search_ctx->ffsc_stopdirs_v != NULL && !got_int)
+ {
+ ff_stack_T *sptr;
+
+ /* is the last starting directory in the stop list? */
+ if (ff_path_in_stoplist(ff_search_ctx->ffsc_start_dir,
+ (int)(path_end - ff_search_ctx->ffsc_start_dir),
+ ff_search_ctx->ffsc_stopdirs_v) == TRUE)
+ break;
+
+ /* cut of last dir */
+ while (path_end > ff_search_ctx->ffsc_start_dir
+ && *path_end == PATHSEP)
+ path_end--;
+ while (path_end > ff_search_ctx->ffsc_start_dir
+ && *(path_end-1) != PATHSEP)
+ path_end--;
+ *path_end = 0;
+ path_end--;
+
+ if (*ff_search_ctx->ffsc_start_dir == 0)
+ break;
+
+ STRCPY(file_path, ff_search_ctx->ffsc_start_dir);
+ add_pathsep(file_path);
+ STRCAT(file_path, ff_search_ctx->ffsc_fix_path);
+
+ /* create a new stack entry */
+ sptr = ff_create_stack_element(file_path,
+ ff_search_ctx->ffsc_wc_path, ff_search_ctx->ffsc_level, 0);
+ if (sptr == NULL)
+ break;
+ ff_push(sptr);
+ }
+ else
+ break;
+ }
+#endif
+
+ vim_free(file_path);
+ return NULL;
+}
+
+/*
+ * Free the list of lists of visited files and directories
+ * Can handle it if the passed search_context is NULL;
+ */
+ void
+vim_findfile_free_visited(search_ctx)
+ void *search_ctx;
+{
+ if (search_ctx == NULL)
+ return;
+
+ ff_search_ctx = (ff_search_ctx_T *)search_ctx;
+
+ vim_findfile_free_visited_list(&ff_search_ctx->ffsc_visited_lists_list);
+ vim_findfile_free_visited_list(&ff_search_ctx->ffsc_dir_visited_lists_list);
+}
+
+ static void
+vim_findfile_free_visited_list(list_headp)
+ ff_visited_list_hdr_T **list_headp;
+{
+ ff_visited_list_hdr_T *vp;
+
+ while (*list_headp != NULL)
+ {
+ vp = (*list_headp)->ffvl_next;
+ ff_free_visited_list((*list_headp)->ffvl_visited_list);
+
+ vim_free((*list_headp)->ffvl_filename);
+ vim_free(*list_headp);
+ *list_headp = vp;
+ }
+ *list_headp = NULL;
+}
+
+ static void
+ff_free_visited_list(vl)
+ ff_visited_T *vl;
+{
+ ff_visited_T *vp;
+
+ while (vl != NULL)
+ {
+ vp = vl->ffv_next;
+#ifdef FEAT_PATH_EXTRA
+ vim_free(vl->ffv_wc_path);
+#endif
+ vim_free(vl);
+ vl = vp;
+ }
+ vl = NULL;
+}
+
+/*
+ * Returns the already visited list for the given filename. If none is found it
+ * allocates a new one.
+ */
+ static ff_visited_list_hdr_T*
+ff_get_visited_list(filename, list_headp)
+ char_u *filename;
+ ff_visited_list_hdr_T **list_headp;
+{
+ ff_visited_list_hdr_T *retptr = NULL;
+
+ /* check if a visited list for the given filename exists */
+ if (*list_headp != NULL)
+ {
+ retptr = *list_headp;
+ while (retptr != NULL)
+ {
+ if (fnamecmp(filename, retptr->ffvl_filename) == 0)
+ {
+#ifdef FF_VERBOSE
+ if (p_verbose >= 5)
+ {
+ /* always scroll up, don't overwrite */
+ msg_scroll = TRUE;
+ msg_str((char_u *)"ff_get_visited_list: FOUND list for %s",
+ filename);
+ /* don't overwrite this either */
+ msg_puts((char_u *)"\n");
+ cmdline_row = msg_row;
+ }
+#endif
+ return retptr;
+ }
+ retptr = retptr->ffvl_next;
+ }
+ }
+
+#ifdef FF_VERBOSE
+ if (p_verbose >= 5)
+ {
+ /* always scroll up, don't overwrite */
+ msg_scroll = TRUE;
+ msg_str((char_u *)"ff_get_visited_list: new list for %s", filename);
+ /* don't overwrite this either */
+ msg_puts((char_u *)"\n");
+ cmdline_row = msg_row;
+ }
+#endif
+
+ /*
+ * if we reach this we didn't find a list and we have to allocate new list
+ */
+ retptr = (ff_visited_list_hdr_T*)alloc((unsigned)sizeof(*retptr));
+ if (retptr == NULL)
+ return NULL;
+
+ retptr->ffvl_visited_list = NULL;
+ retptr->ffvl_filename = vim_strsave(filename);
+ if (retptr->ffvl_filename == NULL)
+ {
+ vim_free(retptr);
+ return NULL;
+ }
+ retptr->ffvl_next = *list_headp;
+ *list_headp = retptr;
+
+ return retptr;
+}
+
+#ifdef FEAT_PATH_EXTRA
+/*
+ * check if two wildcard paths are equal. Returns TRUE or FALSE.
+ * They are equal if:
+ * - both paths are NULL
+ * - they have the same length
+ * - char by char comparison is OK
+ * - the only differences are in the counters behind a '**', so
+ * '**\20' is equal to '**\24'
+ */
+ static int
+ff_wc_equal(s1, s2)
+ char_u *s1;
+ char_u *s2;
+{
+ int i;
+
+ if (s1 == s2)
+ return TRUE;
+
+ if (s1 == NULL || s2 == NULL)
+ return FALSE;
+
+ if (STRLEN(s1) != STRLEN(s2))
+ return FAIL;
+
+ for (i = 0; s1[i] != NUL && s2[i] != NUL; i++)
+ {
+ if (s1[i] != s2[i]
+#ifdef CASE_INSENSITIVE_FILENAME
+ && TOUPPER_LOC(s1[i]) != TOUPPER_LOC(s2[i])
+#endif
+ )
+ {
+ if (i >= 2)
+ if (s1[i-1] == '*' && s1[i-2] == '*')
+ continue;
+ else
+ return FAIL;
+ else
+ return FAIL;
+ }
+ }
+ return TRUE;
+}
+#endif
+
+/*
+ * maintains the list of already visited files and dirs
+ * returns FAIL if the given file/dir is already in the list
+ * returns OK if it is newly added
+ *
+ * TODO: What to do on memory allocation problems?
+ * -> return TRUE - Better the file is found several times instead of
+ * never.
+ */
+ static int
+ff_check_visited(visited_list, fname
+#ifdef FEAT_PATH_EXTRA
+ , wc_path
+#endif
+ )
+ ff_visited_T **visited_list;
+ char_u *fname;
+#ifdef FEAT_PATH_EXTRA
+ char_u *wc_path;
+#endif
+{
+ ff_visited_T *vp;
+#ifdef UNIX
+ struct stat st;
+ int url = FALSE;
+#endif
+
+ /* For an URL we only compare the name, otherwise we compare the
+ * device/inode (unix) or the full path name (not Unix). */
+ if (path_with_url(fname))
+ {
+ STRNCPY(ff_expand_buffer, fname, MAXPATHL);
+#ifdef UNIX
+ url = TRUE;
+#endif
+ }
+ else
+ {
+ ff_expand_buffer[0] = NUL;
+#ifdef UNIX
+ if (mch_stat((char *)fname, &st) < 0)
+#else
+ if (vim_FullName(fname, ff_expand_buffer, MAXPATHL, TRUE) == FAIL)
+#endif
+ return FAIL;
+ }
+
+ /* check against list of already visited files */
+ for (vp = *visited_list; vp != NULL; vp = vp->ffv_next)
+ {
+ if (
+#ifdef UNIX
+ !url
+ ? (vp->ffv_dev == st.st_dev
+ && vp->ffv_ino == st.st_ino)
+ :
+#endif
+ fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0
+ )
+ {
+#ifdef FEAT_PATH_EXTRA
+ /* are the wildcard parts equal */
+ if (ff_wc_equal(vp->ffv_wc_path, wc_path) == TRUE)
+#endif
+ /* already visited */
+ return FAIL;
+ }
+ }
+
+ /*
+ * New file/dir. Add it to the list of visited files/dirs.
+ */
+ vp = (ff_visited_T *)alloc((unsigned)(sizeof(ff_visited_T)
+ + STRLEN(ff_expand_buffer)));
+
+ if (vp != NULL)
+ {
+#ifdef UNIX
+ if (!url)
+ {
+ vp->ffv_ino = st.st_ino;
+ vp->ffv_dev = st.st_dev;
+ vp->ffv_fname[0] = NUL;
+ }
+ else
+ {
+ vp->ffv_ino = 0;
+ vp->ffv_dev = -1;
+#endif
+ STRCPY(vp->ffv_fname, ff_expand_buffer);
+#ifdef UNIX
+ }
+#endif
+#ifdef FEAT_PATH_EXTRA
+ if (wc_path != NULL)
+ vp->ffv_wc_path = vim_strsave(wc_path);
+ else
+ vp->ffv_wc_path = NULL;
+#endif
+
+ vp->ffv_next = *visited_list;
+ *visited_list = vp;
+ }
+
+ return OK;
+}
+
+/*
+ * create stack element from given path pieces
+ */
+ static ff_stack_T *
+ff_create_stack_element(fix_part,
+#ifdef FEAT_PATH_EXTRA
+ wc_part,
+#endif
+ level, star_star_empty)
+ char_u *fix_part;
+#ifdef FEAT_PATH_EXTRA
+ char_u *wc_part;
+#endif
+ int level;
+ int star_star_empty;
+{
+ ff_stack_T *new;
+
+ new = (ff_stack_T *)alloc((unsigned)sizeof(ff_stack_T));
+ if (new == NULL)
+ return NULL;
+
+ new->ffs_prev = NULL;
+ new->ffs_filearray = NULL;
+ new->ffs_filearray_size = 0;
+ new->ffs_filearray_cur = 0;
+ new->ffs_stage = 0;
+ new->ffs_level = level;
+ new->ffs_star_star_empty = star_star_empty;;
+
+ /* the following saves NULL pointer checks in vim_findfile */
+ if (fix_part == NULL)
+ fix_part = (char_u *)"";
+ new->ffs_fix_path = vim_strsave(fix_part);
+
+#ifdef FEAT_PATH_EXTRA
+ if (wc_part == NULL)
+ wc_part = (char_u *)"";
+ new->ffs_wc_path = vim_strsave(wc_part);
+#endif
+
+ if (new->ffs_fix_path == NULL
+#ifdef FEAT_PATH_EXTRA
+ || new->ffs_wc_path == NULL
+#endif
+ )
+ {
+ ff_free_stack_element(new);
+ new = NULL;
+ }
+
+ return new;
+}
+
+/*
+ * push a dir on the directory stack
+ */
+ static void
+ff_push(ctx)
+ ff_stack_T *ctx;
+{
+ /* check for NULL pointer, not to return an error to the user, but
+ * to prevent a crash
+ */
+ if (ctx != NULL)
+ {
+ ctx->ffs_prev = ff_search_ctx->ffsc_stack_ptr;
+ ff_search_ctx->ffsc_stack_ptr = ctx;
+ }
+}
+
+/*
+ * pop a dir from the directory stack
+ * returns NULL if stack is empty
+ */
+ static ff_stack_T *
+ff_pop()
+{
+ ff_stack_T *sptr;
+
+ sptr = ff_search_ctx->ffsc_stack_ptr;
+ if (ff_search_ctx->ffsc_stack_ptr != NULL)
+ ff_search_ctx->ffsc_stack_ptr = ff_search_ctx->ffsc_stack_ptr->ffs_prev;
+
+ return sptr;
+}
+
+/*
+ * free the given stack element
+ */
+ static void
+ff_free_stack_element(ctx)
+ ff_stack_T *ctx;
+{
+ /* vim_free handles possible NULL pointers */
+ vim_free(ctx->ffs_fix_path);
+#ifdef FEAT_PATH_EXTRA
+ vim_free(ctx->ffs_wc_path);
+#endif
+
+ if (ctx->ffs_filearray != NULL)
+ FreeWild(ctx->ffs_filearray_size, ctx->ffs_filearray);
+
+ vim_free(ctx);
+}
+
+/*
+ * clear the search context
+ */
+ static void
+ff_clear()
+{
+ ff_stack_T *sptr;
+
+ /* clear up stack */
+ while ((sptr = ff_pop()) != NULL)
+ ff_free_stack_element(sptr);
+
+ vim_free(ff_search_ctx->ffsc_file_to_search);
+ vim_free(ff_search_ctx->ffsc_start_dir);
+ vim_free(ff_search_ctx->ffsc_fix_path);
+#ifdef FEAT_PATH_EXTRA
+ vim_free(ff_search_ctx->ffsc_wc_path);
+#endif
+
+#ifdef FEAT_PATH_EXTRA
+ if (ff_search_ctx->ffsc_stopdirs_v != NULL)
+ {
+ int i = 0;
+
+ while (ff_search_ctx->ffsc_stopdirs_v[i] != NULL)
+ {
+ vim_free(ff_search_ctx->ffsc_stopdirs_v[i]);
+ i++;
+ }
+ vim_free(ff_search_ctx->ffsc_stopdirs_v);
+ }
+ ff_search_ctx->ffsc_stopdirs_v = NULL;
+#endif
+
+ /* reset everything */
+ ff_search_ctx->ffsc_file_to_search = NULL;
+ ff_search_ctx->ffsc_start_dir = NULL;
+ ff_search_ctx->ffsc_fix_path = NULL;
+#ifdef FEAT_PATH_EXTRA
+ ff_search_ctx->ffsc_wc_path = NULL;
+ ff_search_ctx->ffsc_level = 0;
+#endif
+}
+
+#ifdef FEAT_PATH_EXTRA
+/*
+ * check if the given path is in the stopdirs
+ * returns TRUE if yes else FALSE
+ */
+ static int
+ff_path_in_stoplist(path, path_len, stopdirs_v)
+ char_u *path;
+ int path_len;
+ char_u **stopdirs_v;
+{
+ int i = 0;
+
+ /* eat up trailing path separators, except the first */
+ while (path_len > 1 && path[path_len - 1] == PATHSEP)
+ path_len--;
+
+ /* if no path consider it as match */
+ if (path_len == 0)
+ return TRUE;
+
+ for (i = 0; stopdirs_v[i] != NULL; i++)
+ {
+ if ((int)STRLEN(stopdirs_v[i]) > path_len)
+ {
+ /* match for parent directory. So '/home' also matches
+ * '/home/rks'. Check for PATHSEP in stopdirs_v[i], else
+ * '/home/r' would also match '/home/rks'
+ */
+ if (fnamencmp(stopdirs_v[i], path, path_len) == 0
+ && stopdirs_v[i][path_len] == PATHSEP)
+ return TRUE;
+ }
+ else
+ {
+ if (fnamecmp(stopdirs_v[i], path) == 0)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+#endif
+
+#if defined(FEAT_SEARCHPATH) || defined(PROTO)
+/*
+ * Find the file name "ptr[len]" in the path.
+ *
+ * On the first call set the parameter 'first' to TRUE to initialize
+ * the search. For repeating calls to FALSE.
+ *
+ * Repeating calls will return other files called 'ptr[len]' from the path.
+ *
+ * Only on the first call 'ptr' and 'len' are used. For repeating calls they
+ * don't need valid values.
+ *
+ * If nothing found on the first call the option FNAME_MESS will issue the
+ * message:
+ * 'Can't find file "<file>" in path'
+ * On repeating calls:
+ * 'No more file "<file>" found in path'
+ *
+ * options:
+ * FNAME_MESS give error message when not found
+ *
+ * Uses NameBuff[]!
+ *
+ * Returns an allocated string for the file name. NULL for error.
+ *
+ */
+ char_u *
+find_file_in_path(ptr, len, options, first, rel_fname)
+ char_u *ptr; /* file name */
+ int len; /* length of file name */
+ int options;
+ int first; /* use count'th matching file name */
+ char_u *rel_fname; /* file name searching relative to */
+{
+ return find_file_in_path_option(ptr, len, options, first,
+ *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path,
+ FALSE, rel_fname);
+}
+
+/*
+ * Find the directory name "ptr[len]" in the path.
+ *
+ * options:
+ * FNAME_MESS give error message when not found
+ *
+ * Uses NameBuff[]!
+ *
+ * Returns an allocated string for the file name. NULL for error.
+ */
+ char_u *
+find_directory_in_path(ptr, len, options, rel_fname)
+ char_u *ptr; /* file name */
+ int len; /* length of file name */
+ int options;
+ char_u *rel_fname; /* file name searching relative to */
+{
+ return find_file_in_path_option(ptr, len, options, TRUE, p_cdpath,
+ TRUE, rel_fname);
+}
+
+ static char_u *
+find_file_in_path_option(ptr, len, options, first, path_option, need_dir, rel_fname)
+ char_u *ptr; /* file name */
+ int len; /* length of file name */
+ int options;
+ int first; /* use count'th matching file name */
+ char_u *path_option; /* p_path or p_cdpath */
+ int need_dir; /* looking for directory name */
+ char_u *rel_fname; /* file name we are looking relative to. */
+{
+ static void *search_ctx = NULL;
+ static char_u *dir;
+ static char_u *file_to_find = NULL;
+ static int did_findfile_init = FALSE;
+ char_u save_char;
+ char_u *file_name = NULL;
+ char_u *buf = NULL;
+ int rel_to_curdir;
+#ifdef AMIGA
+ struct Process *proc = (struct Process *)FindTask(0L);
+ APTR save_winptr = proc->pr_WindowPtr;
+
+ /* Avoid a requester here for a volume that doesn't exist. */
+ proc->pr_WindowPtr = (APTR)-1L;
+#endif
+
+ if (first == TRUE)
+ {
+ /* copy file name into NameBuff, expanding environment variables */
+ save_char = ptr[len];
+ ptr[len] = NUL;
+ expand_env(ptr, NameBuff, MAXPATHL);
+ ptr[len] = save_char;
+
+ vim_free(file_to_find);
+ file_to_find = vim_strsave(NameBuff);
+ if (file_to_find == NULL) /* out of memory */
+ {
+ file_name = NULL;
+ goto theend;
+ }
+ }
+
+ rel_to_curdir = (file_to_find[0] == '.'
+ && (file_to_find[1] == NUL
+ || vim_ispathsep(file_to_find[1])
+ || (file_to_find[1] == '.'
+ && (file_to_find[2] == NUL
+ || vim_ispathsep(file_to_find[2])))));
+ if (vim_isAbsName(file_to_find)
+ /* "..", "../path", "." and "./path": don't use the path_option */
+ || rel_to_curdir
+#if defined(MSWIN) || defined(MSDOS) || defined(OS2)
+ /* handle "\tmp" as absolute path */
+ || vim_ispathsep(file_to_find[0])
+ /* handle "c:name" as absulute path */
+ || (file_to_find[0] != NUL && file_to_find[1] == ':')
+#endif
+#ifdef AMIGA
+ /* handle ":tmp" as absolute path */
+ || file_to_find[0] == ':'
+#endif
+ )
+ {
+ /*
+ * Absolute path, no need to use "path_option".
+ * If this is not a first call, return NULL. We already returned a
+ * filename on the first call.
+ */
+ if (first == TRUE)
+ {
+ int l;
+ int run;
+
+ if (path_with_url(file_to_find))
+ {
+ file_name = vim_strsave(file_to_find);
+ goto theend;
+ }
+
+ /* When FNAME_REL flag given first use the directory of the file.
+ * Otherwise or when this fails use the current directory. */
+ for (run = 1; run <= 2; ++run)
+ {
+ l = (int)STRLEN(file_to_find);
+ if (run == 1
+ && rel_to_curdir
+ && (options & FNAME_REL)
+ && rel_fname != NULL
+ && STRLEN(rel_fname) + l < MAXPATHL)
+ {
+ STRCPY(NameBuff, rel_fname);
+ STRCPY(gettail(NameBuff), file_to_find);
+ l = (int)STRLEN(NameBuff);
+ }
+ else
+ {
+ STRCPY(NameBuff, file_to_find);
+ run = 2;
+ }
+
+ /* When the file doesn't exist, try adding parts of
+ * 'suffixesadd'. */
+ buf = curbuf->b_p_sua;
+ for (;;)
+ {
+ if (
+#ifdef DJGPP
+ /* "C:" by itself will fail for mch_getperm(),
+ * assume it's always valid. */
+ (need_dir && NameBuff[0] != NUL
+ && NameBuff[1] == ':'
+ && NameBuff[2] == NUL) ||
+#endif
+ (mch_getperm(NameBuff) >= 0
+ && (!need_dir || mch_isdir(NameBuff))))
+ {
+ file_name = vim_strsave(NameBuff);
+ goto theend;
+ }
+ if (*buf == NUL)
+ break;
+ copy_option_part(&buf, NameBuff + l, MAXPATHL - l, ",");
+ }
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Loop over all paths in the 'path' or 'cdpath' option.
+ * When "first" is set, first setup to the start of the option.
+ * Otherwise continue to find the next match.
+ */
+ if (first == TRUE)
+ {
+ /* vim_findfile_free_visited can handle a possible NULL pointer */
+ vim_findfile_free_visited(search_ctx);
+ dir = path_option;
+ did_findfile_init = FALSE;
+ }
+
+ for (;;)
+ {
+ if (did_findfile_init)
+ {
+ ff_search_ctx->ffsc_need_dir = need_dir;
+ file_name = vim_findfile(search_ctx);
+ ff_search_ctx->ffsc_need_dir = FALSE;
+ if (file_name != NULL)
+ break;
+
+ did_findfile_init = FALSE;
+ }
+ else
+ {
+ char_u *r_ptr;
+
+ if (dir == NULL || *dir == NUL)
+ {
+ /* We searched all paths of the option, now we can
+ * free the search context. */
+ vim_findfile_cleanup(search_ctx);
+ search_ctx = NULL;
+ break;
+ }
+
+ if ((buf = alloc((int)(MAXPATHL))) == NULL)
+ break;
+
+ /* copy next path */
+ buf[0] = 0;
+ copy_option_part(&dir, buf, MAXPATHL, " ,");
+
+#ifdef FEAT_PATH_EXTRA
+ /* get the stopdir string */
+ r_ptr = vim_findfile_stopdir(buf);
+#else
+ r_ptr = NULL;
+#endif
+ search_ctx = vim_findfile_init(buf, file_to_find, r_ptr, 100,
+ FALSE, TRUE, search_ctx, FALSE, rel_fname);
+ if (search_ctx != NULL)
+ did_findfile_init = TRUE;
+ vim_free(buf);
+ }
+ }
+ }
+ if (file_name == NULL && (options & FNAME_MESS))
+ {
+ if (first == TRUE)
+ {
+ if (need_dir)
+ EMSG2(_("E344: Can't find directory \"%s\" in cdpath"),
+ file_to_find);
+ else
+ EMSG2(_("E345: Can't find file \"%s\" in path"),
+ file_to_find);
+ }
+ else
+ {
+ if (need_dir)
+ EMSG2(_("E346: No more directory \"%s\" found in cdpath"),
+ file_to_find);
+ else
+ EMSG2(_("E347: No more file \"%s\" found in path"),
+ file_to_find);
+ }
+ }
+
+theend:
+#ifdef AMIGA
+ proc->pr_WindowPtr = save_winptr;
+#endif
+ return file_name;
+}
+
+#endif /* FEAT_SEARCHPATH */
+
+/*
+ * Change directory to "new_dir". If FEAT_SEARCHPATH is defined, search
+ * 'cdpath' for relative directory names, otherwise just mch_chdir().
+ */
+ int
+vim_chdir(new_dir)
+ char_u *new_dir;
+{
+#ifndef FEAT_SEARCHPATH
+ return mch_chdir((char *)new_dir);
+#else
+ char_u *dir_name;
+ int r;
+
+ dir_name = find_directory_in_path(new_dir, (int)STRLEN(new_dir),
+ FNAME_MESS, curbuf->b_ffname);
+ if (dir_name == NULL)
+ return -1;
+ r = mch_chdir((char *)dir_name);
+ vim_free(dir_name);
+ return r;
+#endif
+}
+
+/*
+ * Get user name from machine-specific function and cache it.
+ * Returns the user name in "buf[len]".
+ * Some systems are quite slow in obtaining the user name (Windows NT).
+ * Returns OK or FAIL.
+ */
+ int
+get_user_name(buf, len)
+ char_u *buf;
+ int len;
+{
+ static char_u *name = NULL;
+
+ if (name == NULL)
+ {
+ if (mch_get_user_name(buf, len) == FAIL)
+ return FAIL;
+ name = vim_strsave(buf);
+ }
+ else
+ STRNCPY(buf, name, len);
+ return OK;
+}
+
+#ifndef HAVE_QSORT
+/*
+ * Our own qsort(), for systems that don't have it.
+ * It's simple and slow. From the K&R C book.
+ */
+ void
+qsort(base, elm_count, elm_size, cmp)
+ void *base;
+ size_t elm_count;
+ size_t elm_size;
+ int (*cmp) __ARGS((const void *, const void *));
+{
+ char_u *buf;
+ char_u *p1;
+ char_u *p2;
+ int i, j;
+ int gap;
+
+ buf = alloc((unsigned)elm_size);
+ if (buf == NULL)
+ return;
+
+ for (gap = elm_count / 2; gap > 0; gap /= 2)
+ for (i = gap; i < elm_count; ++i)
+ for (j = i - gap; j >= 0; j -= gap)
+ {
+ /* Compare the elements. */
+ p1 = (char_u *)base + j * elm_size;
+ p2 = (char_u *)base + (j + gap) * elm_size;
+ if ((*cmp)((void *)p1, (void *)p2) <= 0)
+ break;
+ /* Exchange the elemets. */
+ mch_memmove(buf, p1, elm_size);
+ mch_memmove(p1, p2, elm_size);
+ mch_memmove(p2, buf, elm_size);
+ }
+
+ vim_free(buf);
+}
+#endif
+
+#if defined(FEAT_EX_EXTRA) || defined(FEAT_CMDL_COMPL) || defined(PROTO)
+/*
+ * Sort an array of strings.
+ */
+static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+sort_compare __ARGS((const void *s1, const void *s2));
+
+ static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+sort_compare(s1, s2)
+ const void *s1;
+ const void *s2;
+{
+ return STRCMP(*(char **)s1, *(char **)s2);
+}
+
+ void
+sort_strings(files, count)
+ char_u **files;
+ int count;
+{
+ qsort((void *)files, (size_t)count, sizeof(char_u *), sort_compare);
+}
+#endif
+
+#if !defined(NO_EXPANDPATH) || defined(PROTO)
+/*
+ * Compare path "p[]" to "q[]".
+ * Return value like strcmp(p, q), but consider path separators.
+ */
+ int
+pathcmp(p, q)
+ const char *p, *q;
+{
+ int i;
+ const char *s;
+
+ for (i = 0; ; ++i)
+ {
+ /* End of "p": check if "q" also ends or just has a slash. */
+ if (p[i] == NUL)
+ {
+ if (q[i] == NUL) /* full match */
+ return 0;
+ s = q;
+ break;
+ }
+
+ /* End of "q": check if "p" just has a slash. */
+ if (q[i] == NUL)
+ {
+ s = p;
+ break;
+ }
+
+ if (
+#ifdef CASE_INSENSITIVE_FILENAME
+ TOUPPER_LOC(p[i]) != TOUPPER_LOC(q[i])
+#else
+ p[i] != q[i]
+#endif
+#ifdef BACKSLASH_IN_FILENAME
+ /* consider '/' and '\\' to be equal */
+ && !((p[i] == '/' && q[i] == '\\')
+ || (p[i] == '\\' && q[i] == '/'))
+#endif
+ )
+ {
+ if (vim_ispathsep(p[i]))
+ return -1;
+ if (vim_ispathsep(q[i]))
+ return 1;
+ return ((char_u *)p)[i] - ((char_u *)q)[i]; /* no match */
+ }
+ }
+
+ /* ignore a trailing slash, but not "//" or ":/" */
+ if (s[i + 1] == NUL && i > 0 && !vim_ispathsep(s[i - 1])
+#ifdef BACKSLASH_IN_FILENAME
+ && (s[i] == '/' || s[i] == '\\')
+#else
+ && s[i] == '/'
+#endif
+ )
+ return 0; /* match with trailing slash */
+ if (s == q)
+ return -1; /* no match */
+ return 1;
+}
+#endif
+
+#if defined(FEAT_PRINTER) || defined(PROTO)
+/*
+ * Parse a list of options in the form
+ * option:value,option:value,option:value
+ *
+ * "value" can start with a number which is parsed out, e.g.
+ * margin:12mm
+ *
+ * Returns error message for an illegal option, NULL otherwise.
+ * Only used for the printer at the moment...
+ */
+ char_u *
+parse_list_options(option_str, table, table_size)
+ char_u *option_str;
+ option_table_T *table;
+ int table_size;
+{
+ char_u *stringp;
+ char_u *colonp;
+ char_u *commap;
+ char_u *p;
+ int idx = 0; /* init for GCC */
+ int len;
+
+ for (idx = 0; idx < table_size; ++idx)
+ table[idx].present = FALSE;
+
+ /*
+ * Repeat for all comma separated parts.
+ */
+ stringp = option_str;
+ while (*stringp)
+ {
+ colonp = vim_strchr(stringp, ':');
+ if (colonp == NULL)
+ return (char_u *)N_("E550: Missing colon");
+ commap = vim_strchr(stringp, ',');
+ if (commap == NULL)
+ commap = option_str + STRLEN(option_str);
+
+ len = (int)(colonp - stringp);
+
+ for (idx = 0; idx < table_size; ++idx)
+ if (STRNICMP(stringp, table[idx].name, len) == 0)
+ break;
+
+ if (idx == table_size)
+ return (char_u *)N_("E551: Illegal component");
+
+ p = colonp + 1;
+ table[idx].present = TRUE;
+
+ if (table[idx].hasnum)
+ {
+ if (!VIM_ISDIGIT(*p))
+ return (char_u *)N_("E552: digit expected");
+
+ table[idx].number = getdigits(&p); /*advances p*/
+ }
+
+ table[idx].string = p;
+ table[idx].strlen = (int)(commap - p);
+
+ stringp = commap;
+ if (*stringp == ',')
+ ++stringp;
+ }
+
+ return NULL;
+}
+
+
+#endif /*FEAT_PRINTER*/
+
+/*
+ * The putenv() implementation below comes from the "screen" program.
+ * Included with permission from Juergen Weigert.
+ * See pty.c for the copyright notice.
+ */
+
+/*
+ * putenv -- put value into environment
+ *
+ * Usage: i = putenv (string)
+ * int i;
+ * char *string;
+ *
+ * where string is of the form <name>=<value>.
+ * Putenv returns 0 normally, -1 on error (not enough core for malloc).
+ *
+ * Putenv may need to add a new name into the environment, or to
+ * associate a value longer than the current value with a particular
+ * name. So, to make life simpler, putenv() copies your entire
+ * environment into the heap (i.e. malloc()) from the stack
+ * (i.e. where it resides when your process is initiated) the first
+ * time you call it.
+ *
+ * (history removed, not very interesting. See the "screen" sources.)
+ */
+
+#if !defined(HAVE_SETENV) && !defined(HAVE_PUTENV)
+
+#define EXTRASIZE 5 /* increment to add to env. size */
+
+static int envsize = -1; /* current size of environment */
+#ifndef MACOS_CLASSIC
+extern
+#endif
+ char **environ; /* the global which is your env. */
+
+static int findenv __ARGS((char *name)); /* look for a name in the env. */
+static int newenv __ARGS((void)); /* copy env. from stack to heap */
+static int moreenv __ARGS((void)); /* incr. size of env. */
+
+ int
+putenv(string)
+ const char *string;
+{
+ int i;
+ char *p;
+
+ if (envsize < 0)
+ { /* first time putenv called */
+ if (newenv() < 0) /* copy env. to heap */
+ return -1;
+ }
+
+ i = findenv((char *)string); /* look for name in environment */
+
+ if (i < 0)
+ { /* name must be added */
+ for (i = 0; environ[i]; i++);
+ if (i >= (envsize - 1))
+ { /* need new slot */
+ if (moreenv() < 0)
+ return -1;
+ }
+ p = (char *)alloc((unsigned)(strlen(string) + 1));
+ if (p == NULL) /* not enough core */
+ return -1;
+ environ[i + 1] = 0; /* new end of env. */
+ }
+ else
+ { /* name already in env. */
+ p = vim_realloc(environ[i], strlen(string) + 1);
+ if (p == NULL)
+ return -1;
+ }
+ sprintf(p, "%s", string); /* copy into env. */
+ environ[i] = p;
+
+ return 0;
+}
+
+ static int
+findenv(name)
+ char *name;
+{
+ char *namechar, *envchar;
+ int i, found;
+
+ found = 0;
+ for (i = 0; environ[i] && !found; i++)
+ {
+ envchar = environ[i];
+ namechar = name;
+ while (*namechar && *namechar != '=' && (*namechar == *envchar))
+ {
+ namechar++;
+ envchar++;
+ }
+ found = ((*namechar == '\0' || *namechar == '=') && *envchar == '=');
+ }
+ return found ? i - 1 : -1;
+}
+
+ static int
+newenv()
+{
+ char **env, *elem;
+ int i, esize;
+
+#ifdef MACOS
+ /* for Mac a new, empty environment is created */
+ i = 0;
+#else
+ for (i = 0; environ[i]; i++)
+ ;
+#endif
+ esize = i + EXTRASIZE + 1;
+ env = (char **)alloc((unsigned)(esize * sizeof (elem)));
+ if (env == NULL)
+ return -1;
+
+#ifndef MACOS
+ for (i = 0; environ[i]; i++)
+ {
+ elem = (char *)alloc((unsigned)(strlen(environ[i]) + 1));
+ if (elem == NULL)
+ return -1;
+ env[i] = elem;
+ strcpy(elem, environ[i]);
+ }
+#endif
+
+ env[i] = 0;
+ environ = env;
+ envsize = esize;
+ return 0;
+}
+
+ static int
+moreenv()
+{
+ int esize;
+ char **env;
+
+ esize = envsize + EXTRASIZE;
+ env = (char **)vim_realloc((char *)environ, esize * sizeof (*env));
+ if (env == 0)
+ return -1;
+ environ = env;
+ envsize = esize;
+ return 0;
+}
+
+# ifdef USE_VIMPTY_GETENV
+ char_u *
+vimpty_getenv(string)
+ const char_u *string;
+{
+ int i;
+ char_u *p;
+
+ if (envsize < 0)
+ return NULL;
+
+ i = findenv((char *)string);
+
+ if (i < 0)
+ return NULL;
+
+ p = vim_strchr((char_u *)environ[i], '=');
+ return (p + 1);
+}
+# endif
+
+#endif /* !defined(HAVE_SETENV) && !defined(HAVE_PUTENV) */
+
+/*
+ * Print a message with one string argument.
+ * Make sure that the result fits in IObuff.
+ * This is not in message.c, because the prototype for smsg() isn't used
+ * there.
+ */
+ void
+msg_str(s, arg)
+ char_u *s;
+ char_u *arg;
+{
+ int ls = STRLEN(s);
+ int larg = STRLEN(arg);
+
+ if (ls + larg >= IOSIZE)
+ smsg(s, arg + (ls + larg - IOSIZE));
+ else
+ smsg(s, arg);
+}
diff --git a/src/mkinstalldirs b/src/mkinstalldirs
new file mode 100755
index 000000000..64ae3939c
--- /dev/null
+++ b/src/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id$
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/src/move.c b/src/move.c
new file mode 100644
index 000000000..daa0fb7c1
--- /dev/null
+++ b/src/move.c
@@ -0,0 +1,2796 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * move.c: Functions for moving the cursor and scrolling text.
+ *
+ * There are two ways to move the cursor:
+ * 1. Move the cursor directly, the text is scrolled to keep the cursor in the
+ * window.
+ * 2. Scroll the text, the cursor is moved into the text visible in the
+ * window.
+ * The 'scrolloff' option makes this a bit complicated.
+ */
+
+#include "vim.h"
+
+static void comp_botline __ARGS((win_T *wp));
+static int check_top_offset __ARGS((void));
+static void curs_rows __ARGS((win_T *wp, int do_botline));
+static void validate_botline_win __ARGS((win_T *wp));
+static void validate_cheight __ARGS((void));
+
+typedef struct
+{
+ linenr_T lnum; /* line number */
+#ifdef FEAT_DIFF
+ int fill; /* filler lines */
+#endif
+ int height; /* height of added line */
+} lineoff_T;
+
+static void topline_back __ARGS((lineoff_T *lp));
+static void botline_forw __ARGS((lineoff_T *lp));
+#ifdef FEAT_DIFF
+static void botline_topline __ARGS((lineoff_T *lp));
+static void topline_botline __ARGS((lineoff_T *lp));
+static void max_topfill __ARGS((void));
+#endif
+
+/*
+ * Compute wp->w_botline for the current wp->w_topline. Can be called after
+ * wp->w_topline changed.
+ */
+ static void
+comp_botline(wp)
+ win_T *wp;
+{
+ int n;
+ linenr_T lnum;
+ int done;
+#ifdef FEAT_FOLDING
+ linenr_T last;
+ int folded;
+#endif
+
+ /*
+ * If w_cline_row is valid, start there.
+ * Otherwise have to start at w_topline.
+ */
+ check_cursor_moved(wp);
+ if (wp->w_valid & VALID_CROW)
+ {
+ lnum = wp->w_cursor.lnum;
+ done = wp->w_cline_row;
+ }
+ else
+ {
+ lnum = wp->w_topline;
+ done = 0;
+ }
+
+ for ( ; lnum <= wp->w_buffer->b_ml.ml_line_count; ++lnum)
+ {
+#ifdef FEAT_FOLDING
+ last = lnum;
+ folded = FALSE;
+ if (hasFoldingWin(wp, lnum, NULL, &last, TRUE, NULL))
+ {
+ n = 1;
+ folded = TRUE;
+ }
+ else
+#endif
+#ifdef FEAT_DIFF
+ if (lnum == wp->w_topline)
+ n = plines_win_nofill(wp, lnum, TRUE) + wp->w_topfill;
+ else
+#endif
+ n = plines_win(wp, lnum, TRUE);
+ if (
+#ifdef FEAT_FOLDING
+ lnum <= wp->w_cursor.lnum && last >= wp->w_cursor.lnum
+#else
+ lnum == wp->w_cursor.lnum
+#endif
+ )
+ {
+ wp->w_cline_row = done;
+ wp->w_cline_height = n;
+#ifdef FEAT_FOLDING
+ wp->w_cline_folded = folded;
+#endif
+ wp->w_valid |= (VALID_CROW|VALID_CHEIGHT);
+ }
+ if (done + n > wp->w_height)
+ break;
+ done += n;
+#ifdef FEAT_FOLDING
+ lnum = last;
+#endif
+ }
+
+ /* wp->w_botline is the line that is just below the window */
+ wp->w_botline = lnum;
+ wp->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
+
+ set_empty_rows(wp, done);
+}
+
+/*
+ * Update curwin->w_topline and redraw if necessary.
+ * Used to update the screen before printing a message.
+ */
+ void
+update_topline_redraw()
+{
+ update_topline();
+ if (must_redraw)
+ update_screen(0);
+}
+
+/*
+ * Update curwin->w_topline to move the cursor onto the screen.
+ */
+ void
+update_topline()
+{
+ long line_count;
+ int halfheight;
+ int n;
+ linenr_T old_topline;
+#ifdef FEAT_DIFF
+ int old_topfill;
+#endif
+#ifdef FEAT_FOLDING
+ linenr_T lnum;
+#endif
+ int check_topline = FALSE;
+ int check_botline = FALSE;
+#ifdef FEAT_MOUSE
+ int save_so = p_so;
+#endif
+
+ if (!screen_valid(TRUE))
+ return;
+
+ check_cursor_moved(curwin);
+ if (curwin->w_valid & VALID_TOPLINE)
+ return;
+
+#ifdef FEAT_MOUSE
+ /* When dragging with the mouse, don't scroll that quickly */
+ if (mouse_dragging)
+ p_so = mouse_dragging - 1;
+#endif
+
+ old_topline = curwin->w_topline;
+#ifdef FEAT_DIFF
+ old_topfill = curwin->w_topfill;
+#endif
+
+ /*
+ * If the buffer is empty, always set topline to 1.
+ */
+ if (bufempty()) /* special case - file is empty */
+ {
+ if (curwin->w_topline != 1)
+ redraw_later(NOT_VALID);
+ curwin->w_topline = 1;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = 0;
+#endif
+ curwin->w_botline = 2;
+ curwin->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
+#ifdef FEAT_SCROLLBIND
+ curwin->w_scbind_pos = 1;
+#endif
+ }
+
+ /*
+ * If the cursor is above or near the top of the window, scroll the window
+ * to show the line the cursor is in, with 'scrolloff' context.
+ */
+ else
+ {
+ if (curwin->w_topline > 1)
+ {
+ /* If the cursor is above topline, scrolling is always needed.
+ * If the cursor is far below topline and there is no folding,
+ * scrolling down is never needed. */
+ if (curwin->w_cursor.lnum < curwin->w_topline)
+ check_topline = TRUE;
+ else if (check_top_offset())
+ check_topline = TRUE;
+ }
+#ifdef FEAT_DIFF
+ /* Check if there are more filler lines than allowed. */
+ if (!check_topline && curwin->w_topfill > diff_check_fill(curwin,
+ curwin->w_topline))
+ check_topline = TRUE;
+#endif
+
+ if (check_topline)
+ {
+ halfheight = curwin->w_height / 2 - 1;
+ if (halfheight < 2)
+ halfheight = 2;
+
+#ifdef FEAT_FOLDING
+ if (hasAnyFolding(curwin))
+ {
+ /* Count the number of logical lines between the cursor and
+ * topline + p_so (approximation of how much will be
+ * scrolled). */
+ n = 0;
+ for (lnum = curwin->w_cursor.lnum;
+ lnum < curwin->w_topline + p_so; ++lnum)
+ {
+ ++n;
+ /* stop at end of file or when we know we are far off */
+ if (lnum >= curbuf->b_ml.ml_line_count || n >= halfheight)
+ break;
+ (void)hasFolding(lnum, NULL, &lnum);
+ }
+ }
+ else
+#endif
+ n = curwin->w_topline + p_so - curwin->w_cursor.lnum;
+
+ /* If we weren't very close to begin with, we scroll to put the
+ * cursor in the middle of the window. Otherwise put the cursor
+ * near the top of the window. */
+ if (n >= halfheight)
+ scroll_cursor_halfway(FALSE);
+ else
+ {
+ scroll_cursor_top((int)p_sj, FALSE);
+ check_botline = TRUE;
+ }
+ }
+
+ else
+ {
+#ifdef FEAT_FOLDING
+ /* Make sure topline is the first line of a fold. */
+ (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+#endif
+ check_botline = TRUE;
+ }
+ }
+
+ /*
+ * If the cursor is below the bottom of the window, scroll the window
+ * to put the cursor on the window.
+ * When w_botline is invalid, recompute it first, to avoid a redraw later.
+ * If w_botline was approximated, we might need a redraw later in a few
+ * cases, but we don't want to spend (a lot of) time recomputing w_botline
+ * for every small change.
+ */
+ if (check_botline)
+ {
+ if (!(curwin->w_valid & VALID_BOTLINE_AP))
+ validate_botline();
+
+ if (curwin->w_botline <= curbuf->b_ml.ml_line_count)
+ {
+ if (curwin->w_cursor.lnum < curwin->w_botline
+ && ((long)curwin->w_cursor.lnum
+ >= (long)curwin->w_botline - p_so
+#ifdef FEAT_FOLDING
+ || hasAnyFolding(curwin)
+#endif
+ ))
+ {
+ lineoff_T loff;
+
+ /* Cursor is above botline, check if there are 'scrolloff'
+ * window lines below the cursor. If not, need to scroll. */
+ n = curwin->w_empty_rows;
+ loff.lnum = curwin->w_cursor.lnum;
+#ifdef FEAT_FOLDING
+ /* In a fold go to its last line. */
+ (void)hasFolding(loff.lnum, NULL, &loff.lnum);
+#endif
+#ifdef FEAT_DIFF
+ loff.fill = 0;
+ n += curwin->w_filler_rows;
+#endif
+ loff.height = 0;
+ while (loff.lnum < curwin->w_botline
+#ifdef FEAT_DIFF
+ && (loff.lnum + 1 < curwin->w_botline || loff.fill == 0)
+#endif
+ )
+ {
+ n += loff.height;
+ if (n >= p_so)
+ break;
+ botline_forw(&loff);
+ }
+ if (n >= p_so)
+ /* sufficient context, no need to scroll */
+ check_botline = FALSE;
+ }
+ if (check_botline)
+ {
+#ifdef FEAT_FOLDING
+ if (hasAnyFolding(curwin))
+ {
+ /* Count the number of logical lines between the cursor and
+ * botline - p_so (approximation of how much will be
+ * scrolled). */
+ line_count = 0;
+ for (lnum = curwin->w_cursor.lnum;
+ lnum >= curwin->w_botline - p_so; --lnum)
+ {
+ ++line_count;
+ /* stop at end of file or when we know we are far off */
+ if (lnum <= 0 || line_count > curwin->w_height + 1)
+ break;
+ (void)hasFolding(lnum, &lnum, NULL);
+ }
+ }
+ else
+#endif
+ line_count = curwin->w_cursor.lnum - curwin->w_botline
+ + 1 + p_so;
+ if (line_count <= curwin->w_height + 1)
+ scroll_cursor_bot((int)p_sj, FALSE);
+ else
+ scroll_cursor_halfway(FALSE);
+ }
+ }
+ }
+ curwin->w_valid |= VALID_TOPLINE;
+
+ /*
+ * Need to redraw when topline changed.
+ */
+ if (curwin->w_topline != old_topline
+#ifdef FEAT_DIFF
+ || curwin->w_topfill != old_topfill
+#endif
+ )
+ {
+ dollar_vcol = 0;
+ if (curwin->w_skipcol)
+ {
+ curwin->w_skipcol = 0;
+ redraw_later(NOT_VALID);
+ }
+ else
+ redraw_later(VALID);
+ /* May need to set w_skipcol when cursor in w_topline. */
+ if (curwin->w_cursor.lnum == curwin->w_topline)
+ validate_cursor();
+ }
+
+#ifdef FEAT_MOUSE
+ p_so = save_so;
+#endif
+}
+
+/*
+ * Return TRUE when there are not 'scrolloff' lines above the cursor for the
+ * current window.
+ */
+ static int
+check_top_offset()
+{
+ lineoff_T loff;
+ int n;
+
+ if (curwin->w_cursor.lnum < curwin->w_topline + p_so
+#ifdef FEAT_FOLDING
+ || hasAnyFolding(curwin)
+#endif
+ )
+ {
+ loff.lnum = curwin->w_cursor.lnum;
+#ifdef FEAT_DIFF
+ loff.fill = 0;
+ n = curwin->w_topfill; /* always have this context */
+#else
+ n = 0;
+#endif
+ /* Count the visible screen lines above the cursor line. */
+ while (n < p_so)
+ {
+ topline_back(&loff);
+ /* Stop when included a line above the window. */
+ if (loff.lnum < curwin->w_topline
+#ifdef FEAT_DIFF
+ || (loff.lnum == curwin->w_topline && loff.fill > 0)
+#endif
+ )
+ break;
+ n += loff.height;
+ }
+ if (n < p_so)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+ void
+update_curswant()
+{
+ if (curwin->w_set_curswant)
+ {
+ validate_virtcol();
+ curwin->w_curswant = curwin->w_virtcol;
+ curwin->w_set_curswant = FALSE;
+ }
+}
+
+/*
+ * Check if the cursor has moved. Set the w_valid flag accordingly.
+ */
+ void
+check_cursor_moved(wp)
+ win_T *wp;
+{
+ if (wp->w_cursor.lnum != wp->w_valid_cursor.lnum)
+ {
+ wp->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL
+ |VALID_CHEIGHT|VALID_CROW|VALID_TOPLINE);
+ wp->w_valid_cursor = wp->w_cursor;
+ wp->w_valid_leftcol = wp->w_leftcol;
+ }
+ else if (wp->w_cursor.col != wp->w_valid_cursor.col
+ || wp->w_leftcol != wp->w_valid_leftcol
+#ifdef FEAT_VIRTUALEDIT
+ || wp->w_cursor.coladd != wp->w_valid_cursor.coladd
+#endif
+ )
+ {
+ wp->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
+ wp->w_valid_cursor.col = wp->w_cursor.col;
+ wp->w_valid_leftcol = wp->w_leftcol;
+#ifdef FEAT_VIRTUALEDIT
+ wp->w_valid_cursor.coladd = wp->w_cursor.coladd;
+#endif
+ }
+}
+
+/*
+ * Call this function when some window settings have changed, which require
+ * the cursor position, botline and topline to be recomputed and the window to
+ * be redrawn. E.g, when changing the 'wrap' option or folding.
+ */
+ void
+changed_window_setting()
+{
+ changed_window_setting_win(curwin);
+}
+
+ void
+changed_window_setting_win(wp)
+ win_T *wp;
+{
+ wp->w_lines_valid = 0;
+ changed_line_abv_curs_win(wp);
+ wp->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP|VALID_TOPLINE);
+ redraw_win_later(wp, NOT_VALID);
+}
+
+/*
+ * Set wp->w_topline to a certain number.
+ */
+ void
+set_topline(wp, lnum)
+ win_T *wp;
+ linenr_T lnum;
+{
+#ifdef FEAT_FOLDING
+ /* go to first of folded lines */
+ (void)hasFoldingWin(wp, lnum, &lnum, NULL, TRUE, NULL);
+#endif
+ /* Approximate the value of w_botline */
+ wp->w_botline += lnum - wp->w_topline;
+ wp->w_topline = lnum;
+#ifdef FEAT_DIFF
+ wp->w_topfill = 0;
+#endif
+ wp->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_TOPLINE);
+ /* Don't set VALID_TOPLINE here, 'scrolloff' needs to be checked. */
+ redraw_later(VALID);
+}
+
+/*
+ * Call this function when the length of the cursor line (in screen
+ * characters) has changed, and the change is before the cursor.
+ * Need to take care of w_botline separately!
+ */
+ void
+changed_cline_bef_curs()
+{
+ curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL
+ |VALID_CHEIGHT|VALID_TOPLINE);
+}
+
+ void
+changed_cline_bef_curs_win(wp)
+ win_T *wp;
+{
+ wp->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL
+ |VALID_CHEIGHT|VALID_TOPLINE);
+}
+
+#if 0 /* not used */
+/*
+ * Call this function when the length of the cursor line (in screen
+ * characters) has changed, and the position of the cursor doesn't change.
+ * Need to take care of w_botline separately!
+ */
+ void
+changed_cline_aft_curs()
+{
+ curwin->w_valid &= ~VALID_CHEIGHT;
+}
+#endif
+
+/*
+ * Call this function when the length of a line (in screen characters) above
+ * the cursor have changed.
+ * Need to take care of w_botline separately!
+ */
+ void
+changed_line_abv_curs()
+{
+ curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL|VALID_CROW
+ |VALID_CHEIGHT|VALID_TOPLINE);
+}
+
+ void
+changed_line_abv_curs_win(wp)
+ win_T *wp;
+{
+ wp->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL|VALID_CROW
+ |VALID_CHEIGHT|VALID_TOPLINE);
+}
+
+/*
+ * Make sure the value of curwin->w_botline is valid.
+ */
+ void
+validate_botline()
+{
+ if (!(curwin->w_valid & VALID_BOTLINE))
+ comp_botline(curwin);
+}
+
+/*
+ * Make sure the value of wp->w_botline is valid.
+ */
+ static void
+validate_botline_win(wp)
+ win_T *wp;
+{
+ if (!(wp->w_valid & VALID_BOTLINE))
+ comp_botline(wp);
+}
+
+/*
+ * Mark curwin->w_botline as invalid (because of some change in the buffer).
+ */
+ void
+invalidate_botline()
+{
+ curwin->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP);
+}
+
+ void
+invalidate_botline_win(wp)
+ win_T *wp;
+{
+ wp->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP);
+}
+
+#if 0 /* never used */
+/*
+ * Mark curwin->w_botline as approximated (because of some small change in the
+ * buffer).
+ */
+ void
+approximate_botline()
+{
+ curwin->w_valid &= ~VALID_BOTLINE;
+}
+#endif
+
+ void
+approximate_botline_win(wp)
+ win_T *wp;
+{
+ wp->w_valid &= ~VALID_BOTLINE;
+}
+
+#if 0 /* not used */
+/*
+ * Return TRUE if curwin->w_botline is valid.
+ */
+ int
+botline_valid()
+{
+ return (curwin->w_valid & VALID_BOTLINE);
+}
+#endif
+
+#if 0 /* not used */
+/*
+ * Return TRUE if curwin->w_botline is valid or approximated.
+ */
+ int
+botline_approximated()
+{
+ return (curwin->w_valid & VALID_BOTLINE_AP);
+}
+#endif
+
+/*
+ * Return TRUE if curwin->w_wrow and curwin->w_wcol are valid.
+ */
+ int
+cursor_valid()
+{
+ check_cursor_moved(curwin);
+ return ((curwin->w_valid & (VALID_WROW|VALID_WCOL)) ==
+ (VALID_WROW|VALID_WCOL));
+}
+
+/*
+ * Validate cursor position. Makes sure w_wrow and w_wcol are valid.
+ * w_topline must be valid, you may need to call update_topline() first!
+ */
+ void
+validate_cursor()
+{
+ check_cursor_moved(curwin);
+ if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW))
+ curs_columns(TRUE);
+}
+
+#if defined(FEAT_GUI) || defined(PROTO)
+/*
+ * validate w_cline_row.
+ */
+ void
+validate_cline_row()
+{
+ /*
+ * First make sure that w_topline is valid (after moving the cursor).
+ */
+ update_topline();
+ check_cursor_moved(curwin);
+ if (!(curwin->w_valid & VALID_CROW))
+ curs_rows(curwin, FALSE);
+}
+#endif
+
+/*
+ * Compute wp->w_cline_row and wp->w_cline_height, based on the current value
+ * of wp->w_topine.
+ *
+ * Returns OK when cursor is in the window, FAIL when it isn't.
+ */
+ static void
+curs_rows(wp, do_botline)
+ win_T *wp;
+ int do_botline; /* also compute w_botline */
+{
+ linenr_T lnum;
+ int i;
+ int all_invalid;
+ int valid;
+#ifdef FEAT_FOLDING
+ long fold_count;
+#endif
+
+ /* Check if wp->w_lines[].wl_size is invalid */
+ all_invalid = (!redrawing()
+ || wp->w_lines_valid == 0
+ || wp->w_lines[0].wl_lnum > wp->w_topline);
+ i = 0;
+ wp->w_cline_row = 0;
+ for (lnum = wp->w_topline; lnum < wp->w_cursor.lnum; ++i)
+ {
+ valid = FALSE;
+ if (!all_invalid && i < wp->w_lines_valid)
+ {
+ if (wp->w_lines[i].wl_lnum < lnum || !wp->w_lines[i].wl_valid)
+ continue; /* skip changed or deleted lines */
+ if (wp->w_lines[i].wl_lnum == lnum)
+ {
+#ifdef FEAT_FOLDING
+ /* Check for newly inserted lines below this row, in which
+ * case we need to check for folded lines. */
+ if (!wp->w_buffer->b_mod_set
+ || wp->w_lines[i].wl_lastlnum < wp->w_cursor.lnum
+ || wp->w_buffer->b_mod_top
+ > wp->w_lines[i].wl_lastlnum + 1)
+#endif
+ valid = TRUE;
+ }
+ else if (wp->w_lines[i].wl_lnum > lnum)
+ --i; /* hold at inserted lines */
+ }
+ if (valid
+#ifdef FEAT_DIFF
+ && (lnum != wp->w_topline || !wp->w_p_diff)
+#endif
+ )
+ {
+#ifdef FEAT_FOLDING
+ lnum = wp->w_lines[i].wl_lastlnum + 1;
+ /* Cursor inside folded lines, don't count this row */
+ if (lnum > wp->w_cursor.lnum)
+ break;
+#else
+ ++lnum;
+#endif
+ wp->w_cline_row += wp->w_lines[i].wl_size;
+ }
+ else
+ {
+#ifdef FEAT_FOLDING
+ fold_count = foldedCount(wp, lnum, NULL);
+ if (fold_count)
+ {
+ lnum += fold_count;
+ if (lnum > wp->w_cursor.lnum)
+ break;
+ ++wp->w_cline_row;
+ }
+ else
+#endif
+#ifdef FEAT_DIFF
+ if (lnum == wp->w_topline)
+ wp->w_cline_row += plines_win_nofill(wp, lnum++, TRUE)
+ + wp->w_topfill;
+ else
+#endif
+ wp->w_cline_row += plines_win(wp, lnum++, TRUE);
+ }
+ }
+
+ check_cursor_moved(wp);
+ if (!(wp->w_valid & VALID_CHEIGHT))
+ {
+ if (all_invalid
+ || i == wp->w_lines_valid
+ || (i < wp->w_lines_valid
+ && (!wp->w_lines[i].wl_valid
+ || wp->w_lines[i].wl_lnum != wp->w_cursor.lnum)))
+ {
+#ifdef FEAT_DIFF
+ if (wp->w_cursor.lnum == wp->w_topline)
+ wp->w_cline_height = plines_win_nofill(wp, wp->w_cursor.lnum,
+ TRUE) + wp->w_topfill;
+ else
+#endif
+ wp->w_cline_height = plines_win(wp, wp->w_cursor.lnum, TRUE);
+#ifdef FEAT_FOLDING
+ wp->w_cline_folded = hasFoldingWin(wp, wp->w_cursor.lnum,
+ NULL, NULL, TRUE, NULL);
+#endif
+ }
+ else if (i > wp->w_lines_valid)
+ {
+ /* a line that is too long to fit on the last screen line */
+ wp->w_cline_height = 0;
+#ifdef FEAT_FOLDING
+ wp->w_cline_folded = hasFoldingWin(wp, wp->w_cursor.lnum,
+ NULL, NULL, TRUE, NULL);
+#endif
+ }
+ else
+ {
+ wp->w_cline_height = wp->w_lines[i].wl_size;
+#ifdef FEAT_FOLDING
+ wp->w_cline_folded = wp->w_lines[i].wl_folded;
+#endif
+ }
+ }
+
+ wp->w_valid |= VALID_CROW|VALID_CHEIGHT;
+
+ /* validate botline too, if update_screen doesn't do it */
+ if (do_botline && all_invalid)
+ validate_botline_win(wp);
+}
+
+/*
+ * Validate curwin->w_virtcol only.
+ */
+ void
+validate_virtcol()
+{
+ validate_virtcol_win(curwin);
+}
+
+/*
+ * Validate wp->w_virtcol only.
+ */
+ void
+validate_virtcol_win(wp)
+ win_T *wp;
+{
+ check_cursor_moved(wp);
+ if (!(wp->w_valid & VALID_VIRTCOL))
+ {
+ getvvcol(wp, &wp->w_cursor, NULL, &(wp->w_virtcol), NULL);
+ wp->w_valid |= VALID_VIRTCOL;
+ }
+}
+
+/*
+ * Validate curwin->w_cline_height only.
+ */
+ static void
+validate_cheight()
+{
+ check_cursor_moved(curwin);
+ if (!(curwin->w_valid & VALID_CHEIGHT))
+ {
+#ifdef FEAT_DIFF
+ if (curwin->w_cursor.lnum == curwin->w_topline)
+ curwin->w_cline_height = plines_nofill(curwin->w_cursor.lnum)
+ + curwin->w_topfill;
+ else
+#endif
+ curwin->w_cline_height = plines(curwin->w_cursor.lnum);
+#ifdef FEAT_FOLDING
+ curwin->w_cline_folded = hasFolding(curwin->w_cursor.lnum, NULL, NULL);
+#endif
+ curwin->w_valid |= VALID_CHEIGHT;
+ }
+}
+
+/*
+ * validate w_wcol and w_virtcol only. Only correct when 'wrap' on!
+ */
+ void
+validate_cursor_col()
+{
+ colnr_T off;
+ colnr_T col;
+
+ validate_virtcol();
+ if (!(curwin->w_valid & VALID_WCOL))
+ {
+ col = curwin->w_virtcol;
+ off = curwin_col_off();
+ col += off;
+
+ /* long line wrapping, adjust curwin->w_wrow */
+ if (curwin->w_p_wrap && col >= (colnr_T)W_WIDTH(curwin)
+#ifdef FEAT_VERTSPLIT
+ && curwin->w_width != 0
+#endif
+ )
+ {
+ col -= W_WIDTH(curwin);
+ col = col % (W_WIDTH(curwin) - off + curwin_col_off2());
+ }
+ curwin->w_wcol = col;
+ curwin->w_valid |= VALID_WCOL;
+ }
+}
+
+/*
+ * Compute offset of a window, occupied by line number, fold column and sign
+ * column (these don't move when scrolling horizontally).
+ */
+ int
+win_col_off(wp)
+ win_T *wp;
+{
+ return ((wp->w_p_nu ? 8 : 0)
+#ifdef FEAT_CMDWIN
+ + (cmdwin_type == 0 || wp != curwin ? 0 : 1)
+#endif
+#ifdef FEAT_FOLDING
+ + wp->w_p_fdc
+#endif
+#ifdef FEAT_SIGNS
+ + (
+# ifdef FEAT_NETBEANS_INTG
+ /* always show glyph gutter in netbeans */
+ usingNetbeans ||
+# endif
+ wp->w_buffer->b_signlist != NULL ? 2 : 0)
+#endif
+ );
+}
+
+ int
+curwin_col_off()
+{
+ return win_col_off(curwin);
+}
+
+/*
+ * Return the difference in column offset for the second screen line of a
+ * wrapped line. It's 8 if 'number' is on and 'n' is in 'cpoptions'.
+ */
+ int
+win_col_off2(wp)
+ win_T *wp;
+{
+ if (wp->w_p_nu && vim_strchr(p_cpo, CPO_NUMCOL) != NULL)
+ return 8;
+ return 0;
+}
+
+ int
+curwin_col_off2()
+{
+ return win_col_off2(curwin);
+}
+
+/*
+ * compute curwin->w_wcol and curwin->w_virtcol.
+ * Also updates curwin->w_wrow and curwin->w_cline_row.
+ * Also updates curwin->w_leftcol.
+ */
+ void
+curs_columns(scroll)
+ int scroll; /* when TRUE, may scroll horizontally */
+{
+ int diff;
+ int extra; /* offset for first screen line */
+ int off_left, off_right;
+ int n;
+ int p_lines;
+ int width = 0;
+ int textwidth;
+ int new_leftcol;
+ colnr_T startcol;
+ colnr_T endcol;
+ colnr_T prev_skipcol;
+
+ /*
+ * First make sure that w_topline is valid (after moving the cursor).
+ */
+ update_topline();
+
+ /*
+ * Next make sure that w_cline_row is valid.
+ */
+ if (!(curwin->w_valid & VALID_CROW))
+ curs_rows(curwin, FALSE);
+
+ /*
+ * Compute the number of virtual columns.
+ */
+#ifdef FEAT_FOLDING
+ if (curwin->w_cline_folded)
+ /* In a folded line the cursor is always in the first column */
+ startcol = curwin->w_virtcol = endcol = curwin->w_leftcol;
+ else
+#endif
+ getvvcol(curwin, &curwin->w_cursor,
+ &startcol, &(curwin->w_virtcol), &endcol);
+
+ /* remove '$' from change command when cursor moves onto it */
+ if (startcol > dollar_vcol)
+ dollar_vcol = 0;
+
+ extra = curwin_col_off();
+ curwin->w_wcol = curwin->w_virtcol + extra;
+ endcol += extra;
+
+ /*
+ * Now compute w_wrow, counting screen lines from w_cline_row.
+ */
+ curwin->w_wrow = curwin->w_cline_row;
+
+ textwidth = W_WIDTH(curwin) - extra;
+ if (textwidth <= 0)
+ {
+ /* No room for text, put cursor in last char of window. */
+ curwin->w_wcol = W_WIDTH(curwin) - 1;
+ curwin->w_wrow = curwin->w_height - 1;
+ }
+ else if (curwin->w_p_wrap
+#ifdef FEAT_VERTSPLIT
+ && curwin->w_width != 0
+#endif
+ )
+ {
+ width = textwidth + curwin_col_off2();
+
+ /* long line wrapping, adjust curwin->w_wrow */
+ if (curwin->w_wcol >= W_WIDTH(curwin))
+ {
+ n = (curwin->w_wcol - W_WIDTH(curwin)) / width + 1;
+ curwin->w_wcol -= n * width;
+ curwin->w_wrow += n;
+
+#ifdef FEAT_LINEBREAK
+ /* When cursor wraps to first char of next line in Insert
+ * mode, the 'showbreak' string isn't shown, backup to first
+ * column */
+ if (*p_sbr && *ml_get_cursor() == NUL
+ && curwin->w_wcol == (int)vim_strsize(p_sbr))
+ curwin->w_wcol = 0;
+#endif
+ }
+ }
+
+ /* No line wrapping: compute curwin->w_leftcol if scrolling is on and line
+ * is not folded.
+ * If scrolling is off, curwin->w_leftcol is assumed to be 0 */
+ else if (scroll
+#ifdef FEAT_FOLDING
+ && !curwin->w_cline_folded
+#endif
+ )
+ {
+ /*
+ * If Cursor is left of the screen, scroll rightwards.
+ * If Cursor is right of the screen, scroll leftwards
+ * If we get closer to the edge than 'sidescrolloff', scroll a little
+ * extra
+ */
+ off_left = (int)startcol - (int)curwin->w_leftcol - p_siso;
+ off_right = (int)endcol - (int)(curwin->w_leftcol + W_WIDTH(curwin)
+ - p_siso) + 1;
+ if (off_left < 0 || off_right > 0)
+ {
+ if (off_left < 0)
+ diff = -off_left;
+ else
+ diff = off_right;
+
+ /* When far off or not enough room on either side, put cursor in
+ * middle of window. */
+ if (p_ss == 0 || diff >= textwidth / 2 || off_right >= off_left)
+ new_leftcol = curwin->w_wcol - extra - textwidth / 2;
+ else
+ {
+ if (diff < p_ss)
+ diff = p_ss;
+ if (off_left < 0)
+ new_leftcol = curwin->w_leftcol - diff;
+ else
+ new_leftcol = curwin->w_leftcol + diff;
+ }
+ if (new_leftcol < 0)
+ new_leftcol = 0;
+ if (new_leftcol != (int)curwin->w_leftcol)
+ {
+ curwin->w_leftcol = new_leftcol;
+ /* screen has to be redrawn with new curwin->w_leftcol */
+ redraw_later(NOT_VALID);
+ }
+ }
+ curwin->w_wcol -= curwin->w_leftcol;
+ }
+ else if (curwin->w_wcol > (int)curwin->w_leftcol)
+ curwin->w_wcol -= curwin->w_leftcol;
+ else
+ curwin->w_wcol = 0;
+
+#ifdef FEAT_DIFF
+ /* Skip over filler lines. At the top use w_topfill, there
+ * may be some filler lines above the window. */
+ if (curwin->w_cursor.lnum == curwin->w_topline)
+ curwin->w_wrow += curwin->w_topfill;
+ else
+ curwin->w_wrow += diff_check_fill(curwin, curwin->w_cursor.lnum);
+#endif
+
+ prev_skipcol = curwin->w_skipcol;
+
+ p_lines = 0;
+ if ((curwin->w_wrow >= curwin->w_height
+ || ((prev_skipcol > 0
+ || curwin->w_wrow + p_so >= curwin->w_height)
+ && (p_lines =
+#ifdef FEAT_DIFF
+ plines_win_nofill
+#else
+ plines_win
+#endif
+ (curwin, curwin->w_cursor.lnum, FALSE))
+ - 1 >= curwin->w_height))
+ && curwin->w_height != 0
+ && curwin->w_cursor.lnum == curwin->w_topline
+ && width > 0
+#ifdef FEAT_VERTSPLIT
+ && curwin->w_width != 0
+#endif
+ )
+ {
+ /* Cursor past end of screen. Happens with a single line that does
+ * not fit on screen. Find a skipcol to show the text around the
+ * cursor. Avoid scrolling all the time. compute value of "extra":
+ * 1: Less than "p_so" lines above
+ * 2: Less than "p_so" lines below
+ * 3: both of them */
+ extra = 0;
+ if (curwin->w_skipcol + p_so * width > curwin->w_virtcol)
+ extra = 1;
+ /* Compute last display line of the buffer line that we want at the
+ * bottom of the window. */
+ if (p_lines == 0)
+ p_lines = plines_win(curwin, curwin->w_cursor.lnum, FALSE);
+ --p_lines;
+ if (p_lines > curwin->w_wrow + p_so)
+ n = curwin->w_wrow + p_so;
+ else
+ n = p_lines;
+ if ((colnr_T)n >= curwin->w_height + curwin->w_skipcol / width)
+ extra += 2;
+
+ if (extra == 3 || p_lines < p_so * 2)
+ {
+ /* not enough room for 'scrolloff', put cursor in the middle */
+ n = curwin->w_virtcol / width;
+ if (n > curwin->w_height / 2)
+ n -= curwin->w_height / 2;
+ else
+ n = 0;
+ /* don't skip more than necessary */
+ if (n > p_lines - curwin->w_height + 1)
+ n = p_lines - curwin->w_height + 1;
+ curwin->w_skipcol = n * width;
+ }
+ else if (extra == 1)
+ {
+ /* less then 'scrolloff' lines above, decrease skipcol */
+ extra = (curwin->w_skipcol + p_so * width - curwin->w_virtcol
+ + width - 1) / width;
+ if (extra > 0)
+ {
+ if ((colnr_T)(extra * width) > curwin->w_skipcol)
+ extra = curwin->w_skipcol / width;
+ curwin->w_skipcol -= extra * width;
+ }
+ }
+ else if (extra == 2)
+ {
+ /* less then 'scrolloff' lines below, increase skipcol */
+ endcol = (n - curwin->w_height + 1) * width;
+ while (endcol > curwin->w_virtcol)
+ endcol -= width;
+ if (endcol > curwin->w_skipcol)
+ curwin->w_skipcol = endcol;
+ }
+
+ curwin->w_wrow -= curwin->w_skipcol / width;
+ if (curwin->w_wrow >= curwin->w_height)
+ {
+ /* small window, make sure cursor is in it */
+ extra = curwin->w_wrow - curwin->w_height + 1;
+ curwin->w_skipcol += extra * width;
+ curwin->w_wrow -= extra;
+ }
+
+ extra = ((int)prev_skipcol - (int)curwin->w_skipcol) / width;
+ if (extra > 0)
+ win_ins_lines(curwin, 0, extra, FALSE, FALSE);
+ else if (extra < 0)
+ win_del_lines(curwin, 0, -extra, FALSE, FALSE);
+ }
+ else
+ curwin->w_skipcol = 0;
+ if (prev_skipcol != curwin->w_skipcol)
+ redraw_later(NOT_VALID);
+
+ curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
+}
+
+/*
+ * Scroll the current window down by "line_count" logical lines. "CTRL-Y"
+ */
+/*ARGSUSED*/
+ void
+scrolldown(line_count, byfold)
+ long line_count;
+ int byfold; /* TRUE: count a closed fold as one line */
+{
+ long done = 0; /* total # of physical lines done */
+ int wrow;
+ int moved = FALSE;
+
+#ifdef FEAT_FOLDING
+ linenr_T first;
+
+ /* Make sure w_topline is at the first of a sequence of folded lines. */
+ (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+#endif
+ validate_cursor(); /* w_wrow needs to be valid */
+ while (line_count-- > 0)
+ {
+#ifdef FEAT_DIFF
+ if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
+ {
+ ++curwin->w_topfill;
+ ++done;
+ }
+ else
+#endif
+ {
+ if (curwin->w_topline == 1)
+ break;
+ --curwin->w_topline;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = 0;
+#endif
+#ifdef FEAT_FOLDING
+ /* A sequence of folded lines only counts for one logical line */
+ if (hasFolding(curwin->w_topline, &first, NULL))
+ {
+ ++done;
+ if (!byfold)
+ line_count -= curwin->w_topline - first - 1;
+ curwin->w_botline -= curwin->w_topline - first;
+ curwin->w_topline = first;
+ }
+ else
+#endif
+#ifdef FEAT_DIFF
+ done += plines_nofill(curwin->w_topline);
+#else
+ done += plines(curwin->w_topline);
+#endif
+ }
+ --curwin->w_botline; /* approximate w_botline */
+ invalidate_botline();
+ }
+ curwin->w_wrow += done; /* keep w_wrow updated */
+ curwin->w_cline_row += done; /* keep w_cline_row updated */
+
+#ifdef FEAT_DIFF
+ if (curwin->w_cursor.lnum == curwin->w_topline)
+ curwin->w_cline_row = 0;
+ check_topfill(curwin, TRUE);
+#endif
+
+ /*
+ * Compute the row number of the last row of the cursor line
+ * and move the cursor onto the displayed part of the window.
+ */
+ wrow = curwin->w_wrow;
+ if (curwin->w_p_wrap
+#ifdef FEAT_VERTSPLIT
+ && curwin->w_width != 0
+#endif
+ )
+ {
+ validate_virtcol();
+ validate_cheight();
+ wrow += curwin->w_cline_height - 1 -
+ curwin->w_virtcol / W_WIDTH(curwin);
+ }
+ while (wrow >= curwin->w_height && curwin->w_cursor.lnum > 1)
+ {
+#ifdef FEAT_FOLDING
+ if (hasFolding(curwin->w_cursor.lnum, &first, NULL))
+ {
+ --wrow;
+ if (first == 1)
+ curwin->w_cursor.lnum = 1;
+ else
+ curwin->w_cursor.lnum = first - 1;
+ }
+ else
+#endif
+ wrow -= plines(curwin->w_cursor.lnum--);
+ curwin->w_valid &=
+ ~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
+ moved = TRUE;
+ }
+ if (moved)
+ {
+#ifdef FEAT_FOLDING
+ /* Move cursor to first line of closed fold. */
+ foldAdjustCursor();
+#endif
+ coladvance(curwin->w_curswant);
+ }
+}
+
+/*
+ * Scroll the current window up by "line_count" logical lines. "CTRL-E"
+ */
+/*ARGSUSED*/
+ void
+scrollup(line_count, byfold)
+ long line_count;
+ int byfold; /* TRUE: count a closed fold as one line */
+{
+#if defined(FEAT_FOLDING) || defined(FEAT_DIFF)
+ linenr_T lnum;
+
+ if (
+# ifdef FEAT_FOLDING
+ (byfold && hasAnyFolding(curwin))
+# ifdef FEAT_DIFF
+ ||
+# endif
+# endif
+# ifdef FEAT_DIFF
+ curwin->w_p_diff
+# endif
+ )
+ {
+ /* count each sequence of folded lines as one logical line */
+ lnum = curwin->w_topline;
+ while (line_count--)
+ {
+# ifdef FEAT_DIFF
+ if (curwin->w_topfill > 0)
+ --curwin->w_topfill;
+ else
+# endif
+ {
+# ifdef FEAT_FOLDING
+ if (byfold)
+ (void)hasFolding(lnum, NULL, &lnum);
+# endif
+ if (lnum >= curbuf->b_ml.ml_line_count)
+ break;
+ ++lnum;
+# ifdef FEAT_DIFF
+ curwin->w_topfill = diff_check_fill(curwin, lnum);
+# endif
+ }
+ }
+ /* approximate w_botline */
+ curwin->w_botline += lnum - curwin->w_topline;
+ curwin->w_topline = lnum;
+ }
+ else
+#endif
+ {
+ curwin->w_topline += line_count;
+ curwin->w_botline += line_count; /* approximate w_botline */
+ }
+
+ if (curwin->w_topline > curbuf->b_ml.ml_line_count)
+ curwin->w_topline = curbuf->b_ml.ml_line_count;
+ if (curwin->w_botline > curbuf->b_ml.ml_line_count + 1)
+ curwin->w_botline = curbuf->b_ml.ml_line_count + 1;
+
+#ifdef FEAT_DIFF
+ check_topfill(curwin, FALSE);
+#endif
+
+#ifdef FEAT_FOLDING
+ if (hasAnyFolding(curwin))
+ /* Make sure w_topline is at the first of a sequence of folded lines. */
+ (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+#endif
+
+ curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE);
+ if (curwin->w_cursor.lnum < curwin->w_topline)
+ {
+ curwin->w_cursor.lnum = curwin->w_topline;
+ curwin->w_valid &=
+ ~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
+ coladvance(curwin->w_curswant);
+ }
+}
+
+#ifdef FEAT_DIFF
+/*
+ * Don't end up with too many filler lines in the window.
+ */
+ void
+check_topfill(wp, down)
+ win_T *wp;
+ int down; /* when TRUE scroll down when not enough space */
+{
+ int n;
+
+ if (wp->w_topfill > 0)
+ {
+ n = plines_win_nofill(wp, wp->w_topline, TRUE);
+ if (wp->w_topfill + n > wp->w_height)
+ {
+ if (down && wp->w_topline > 1)
+ {
+ --wp->w_topline;
+ wp->w_topfill = 0;
+ }
+ else
+ {
+ wp->w_topfill = wp->w_height - n;
+ if (wp->w_topfill < 0)
+ wp->w_topfill = 0;
+ }
+ }
+ }
+}
+
+/*
+ * Use as many filler lines as possible for w_topline. Make sure w_topline
+ * is still visible.
+ */
+ static void
+max_topfill()
+{
+ int n;
+
+ n = plines_nofill(curwin->w_topline);
+ if (n >= curwin->w_height)
+ curwin->w_topfill = 0;
+ else
+ {
+ curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline);
+ if (curwin->w_topfill + n > curwin->w_height)
+ curwin->w_topfill = curwin->w_height - n;
+ }
+}
+#endif
+
+#if defined(FEAT_INS_EXPAND) || defined(PROTO)
+/*
+ * Scroll the screen one line down, but don't do it if it would move the
+ * cursor off the screen.
+ */
+ void
+scrolldown_clamp()
+{
+ int end_row;
+#ifdef FEAT_DIFF
+ int can_fill = (curwin->w_topfill
+ < diff_check_fill(curwin, curwin->w_topline));
+#endif
+
+ if (curwin->w_topline <= 1
+#ifdef FEAT_DIFF
+ && !can_fill
+#endif
+ )
+ return;
+
+ validate_cursor(); /* w_wrow needs to be valid */
+
+ /*
+ * Compute the row number of the last row of the cursor line
+ * and make sure it doesn't go off the screen. Make sure the cursor
+ * doesn't go past 'scrolloff' lines from the screen end.
+ */
+ end_row = curwin->w_wrow;
+#ifdef FEAT_DIFF
+ if (can_fill)
+ ++end_row;
+ else
+ end_row += plines_nofill(curwin->w_topline - 1);
+#else
+ end_row += plines(curwin->w_topline - 1);
+#endif
+ if (curwin->w_p_wrap
+#ifdef FEAT_VERTSPLIT
+ && curwin->w_width != 0
+#endif
+ )
+ {
+ validate_cheight();
+ validate_virtcol();
+ end_row += curwin->w_cline_height - 1 -
+ curwin->w_virtcol / W_WIDTH(curwin);
+ }
+ if (end_row < curwin->w_height - p_so)
+ {
+#ifdef FEAT_DIFF
+ if (can_fill)
+ {
+ ++curwin->w_topfill;
+ check_topfill(curwin, TRUE);
+ }
+ else
+ {
+ --curwin->w_topline;
+ curwin->w_topfill = 0;
+ }
+#else
+ --curwin->w_topline;
+#endif
+#ifdef FEAT_FOLDING
+ hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+#endif
+ --curwin->w_botline; /* approximate w_botline */
+ curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE);
+ }
+}
+
+/*
+ * Scroll the screen one line up, but don't do it if it would move the cursor
+ * off the screen.
+ */
+ void
+scrollup_clamp()
+{
+ int start_row;
+
+ if (curwin->w_topline == curbuf->b_ml.ml_line_count
+#ifdef FEAT_DIFF
+ && curwin->w_topfill == 0
+#endif
+ )
+ return;
+
+ validate_cursor(); /* w_wrow needs to be valid */
+
+ /*
+ * Compute the row number of the first row of the cursor line
+ * and make sure it doesn't go off the screen. Make sure the cursor
+ * doesn't go before 'scrolloff' lines from the screen start.
+ */
+#ifdef FEAT_DIFF
+ start_row = curwin->w_wrow - plines_nofill(curwin->w_topline)
+ - curwin->w_topfill;
+#else
+ start_row = curwin->w_wrow - plines(curwin->w_topline);
+#endif
+ if (curwin->w_p_wrap
+#ifdef FEAT_VERTSPLIT
+ && curwin->w_width != 0
+#endif
+ )
+ {
+ validate_virtcol();
+ start_row -= curwin->w_virtcol / W_WIDTH(curwin);
+ }
+ if (start_row >= p_so)
+ {
+#ifdef FEAT_DIFF
+ if (curwin->w_topfill > 0)
+ --curwin->w_topfill;
+ else
+#endif
+ ++curwin->w_topline;
+ ++curwin->w_botline; /* approximate w_botline */
+ curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE);
+ }
+}
+#endif /* FEAT_INS_EXPAND */
+
+/*
+ * Add one line above "lp->lnum". This can be a filler line, a closed fold or
+ * a (wrapped) text line. Uses and sets "lp->fill".
+ * Returns the height of the added line in "lp->height".
+ * Lines above the first one are incredibly high.
+ */
+ static void
+topline_back(lp)
+ lineoff_T *lp;
+{
+#ifdef FEAT_DIFF
+ if (lp->fill < diff_check_fill(curwin, lp->lnum))
+ {
+ /* Add a filler line. */
+ ++lp->fill;
+ lp->height = 1;
+ }
+ else
+#endif
+ {
+ --lp->lnum;
+#ifdef FEAT_DIFF
+ lp->fill = 0;
+#endif
+ if (lp->lnum < 1)
+ lp->height = MAXCOL;
+ else
+#ifdef FEAT_FOLDING
+ if (hasFolding(lp->lnum, &lp->lnum, NULL))
+ /* Add a closed fold */
+ lp->height = 1;
+ else
+#endif
+ {
+#ifdef FEAT_DIFF
+ lp->height = plines_nofill(lp->lnum);
+#else
+ lp->height = plines(lp->lnum);
+#endif
+ }
+ }
+}
+
+/*
+ * Add one line below "lp->lnum". This can be a filler line, a closed fold or
+ * a (wrapped) text line. Uses and sets "lp->fill".
+ * Returns the height of the added line in "lp->height".
+ * Lines below the last one are incredibly high.
+ */
+ static void
+botline_forw(lp)
+ lineoff_T *lp;
+{
+#ifdef FEAT_DIFF
+ if (lp->fill < diff_check_fill(curwin, lp->lnum + 1))
+ {
+ /* Add a filler line. */
+ ++lp->fill;
+ lp->height = 1;
+ }
+ else
+#endif
+ {
+ ++lp->lnum;
+#ifdef FEAT_DIFF
+ lp->fill = 0;
+#endif
+ if (lp->lnum > curbuf->b_ml.ml_line_count)
+ lp->height = MAXCOL;
+ else
+#ifdef FEAT_FOLDING
+ if (hasFolding(lp->lnum, NULL, &lp->lnum))
+ /* Add a closed fold */
+ lp->height = 1;
+ else
+#endif
+ {
+#ifdef FEAT_DIFF
+ lp->height = plines_nofill(lp->lnum);
+#else
+ lp->height = plines(lp->lnum);
+#endif
+ }
+ }
+}
+
+#ifdef FEAT_DIFF
+/*
+ * Switch from including filler lines below lp->lnum to including filler
+ * lines above loff.lnum + 1. This keeps pointing to the same line.
+ * When there are no filler lines nothing changes.
+ */
+ static void
+botline_topline(lp)
+ lineoff_T *lp;
+{
+ if (lp->fill > 0)
+ {
+ ++lp->lnum;
+ lp->fill = diff_check_fill(curwin, lp->lnum) - lp->fill + 1;
+ }
+}
+
+/*
+ * Switch from including filler lines above lp->lnum to including filler
+ * lines below loff.lnum - 1. This keeps pointing to the same line.
+ * When there are no filler lines nothing changes.
+ */
+ static void
+topline_botline(lp)
+ lineoff_T *lp;
+{
+ if (lp->fill > 0)
+ {
+ lp->fill = diff_check_fill(curwin, lp->lnum) - lp->fill + 1;
+ --lp->lnum;
+ }
+}
+#endif
+
+/*
+ * Recompute topline to put the cursor at the top of the window.
+ * Scroll at least "min_scroll" lines.
+ * If "always" is TRUE, always set topline (for "zt").
+ */
+ void
+scroll_cursor_top(min_scroll, always)
+ int min_scroll;
+ int always;
+{
+ int scrolled = 0;
+ int extra = 0;
+ int used;
+ int i;
+ linenr_T top; /* just above displayed lines */
+ linenr_T bot; /* just below displayed lines */
+ linenr_T old_topline = curwin->w_topline;
+#ifdef FEAT_DIFF
+ linenr_T old_topfill = curwin->w_topfill;
+#endif
+ linenr_T new_topline;
+ int off = p_so;
+
+#ifdef FEAT_MOUSE
+ if (mouse_dragging > 0)
+ off = mouse_dragging - 1;
+#endif
+
+ /*
+ * Decrease topline until:
+ * - it has become 1
+ * - (part of) the cursor line is moved off the screen or
+ * - moved at least 'scrolljump' lines and
+ * - at least 'scrolloff' lines above and below the cursor
+ */
+ validate_cheight();
+ used = curwin->w_cline_height;
+ if (curwin->w_cursor.lnum < curwin->w_topline)
+ scrolled = used;
+
+#ifdef FEAT_FOLDING
+ if (hasFolding(curwin->w_cursor.lnum, &top, &bot))
+ {
+ --top;
+ ++bot;
+ }
+ else
+#endif
+ {
+ top = curwin->w_cursor.lnum - 1;
+ bot = curwin->w_cursor.lnum + 1;
+ }
+ new_topline = top + 1;
+
+#ifdef FEAT_DIFF
+ /* count filler lines of the cursor window as context */
+ i = diff_check_fill(curwin, curwin->w_cursor.lnum);
+ used += i;
+ extra += i;
+#endif
+
+ /*
+ * Check if the lines from "top" to "bot" fit in the window. If they do,
+ * set new_topline and advance "top" and "bot" to include more lines.
+ */
+ while (top > 0)
+ {
+#ifdef FEAT_FOLDING
+ if (hasFolding(top, &top, NULL))
+ /* count one logical line for a sequence of folded lines */
+ i = 1;
+ else
+#endif
+ i = plines(top);
+ used += i;
+ if (extra + i <= off && bot < curbuf->b_ml.ml_line_count)
+ {
+#ifdef FEAT_FOLDING
+ if (hasFolding(bot, NULL, &bot))
+ /* count one logical line for a sequence of folded lines */
+ ++used;
+ else
+#endif
+ used += plines(bot);
+ }
+ if (used > curwin->w_height)
+ break;
+ if (top < curwin->w_topline)
+ scrolled += i;
+
+ /*
+ * If scrolling is needed, scroll at least 'sj' lines.
+ */
+ if ((new_topline >= curwin->w_topline || scrolled > min_scroll)
+ && extra >= off)
+ break;
+
+ extra += i;
+ new_topline = top;
+ --top;
+ ++bot;
+ }
+
+ /*
+ * If we don't have enough space, put cursor in the middle.
+ * This makes sure we get the same position when using "k" and "j"
+ * in a small window.
+ */
+ if (used > curwin->w_height)
+ scroll_cursor_halfway(FALSE);
+ else
+ {
+ /*
+ * If "always" is FALSE, only adjust topline to a lower value, higher
+ * value may happen with wrapping lines
+ */
+ if (new_topline < curwin->w_topline || always)
+ curwin->w_topline = new_topline;
+ if (curwin->w_topline > curwin->w_cursor.lnum)
+ curwin->w_topline = curwin->w_cursor.lnum;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline);
+ if (curwin->w_topfill > 0 && extra > off)
+ {
+ curwin->w_topfill -= extra - off;
+ if (curwin->w_topfill < 0)
+ curwin->w_topfill = 0;
+ }
+ check_topfill(curwin, FALSE);
+#endif
+ if (curwin->w_topline != old_topline
+#ifdef FEAT_DIFF
+ || curwin->w_topfill != old_topfill
+#endif
+ )
+ curwin->w_valid &=
+ ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
+ curwin->w_valid |= VALID_TOPLINE;
+ }
+}
+
+/*
+ * Set w_empty_rows and w_filler_rows for window "wp", having used up "used"
+ * screen lines for text lines.
+ */
+ void
+set_empty_rows(wp, used)
+ win_T *wp;
+ int used;
+{
+#ifdef FEAT_DIFF
+ wp->w_filler_rows = 0;
+#endif
+ if (used == 0)
+ wp->w_empty_rows = 0; /* single line that doesn't fit */
+ else
+ {
+ wp->w_empty_rows = wp->w_height - used;
+#ifdef FEAT_DIFF
+ if (wp->w_botline <= wp->w_buffer->b_ml.ml_line_count)
+ {
+ wp->w_filler_rows = diff_check_fill(wp, wp->w_botline);
+ if (wp->w_empty_rows > wp->w_filler_rows)
+ wp->w_empty_rows -= wp->w_filler_rows;
+ else
+ {
+ wp->w_filler_rows = wp->w_empty_rows;
+ wp->w_empty_rows = 0;
+ }
+ }
+#endif
+ }
+}
+
+/*
+ * Recompute topline to put the cursor at the bottom of the window.
+ * Scroll at least "min_scroll" lines.
+ * If "set_topbot" is TRUE, set topline and botline first (for "zb").
+ * This is messy stuff!!!
+ */
+ void
+scroll_cursor_bot(min_scroll, set_topbot)
+ int min_scroll;
+ int set_topbot;
+{
+ int used;
+ int scrolled = 0;
+ int extra = 0;
+ int i;
+ linenr_T line_count;
+ linenr_T old_topline = curwin->w_topline;
+ lineoff_T loff;
+ lineoff_T boff;
+#ifdef FEAT_DIFF
+ int old_topfill = curwin->w_topfill;
+ int fill_below_window;
+#endif
+ linenr_T old_botline = curwin->w_botline;
+ linenr_T old_valid = curwin->w_valid;
+ int old_empty_rows = curwin->w_empty_rows;
+ linenr_T cln; /* Cursor Line Number */
+
+ cln = curwin->w_cursor.lnum;
+ if (set_topbot)
+ {
+ used = 0;
+ curwin->w_botline = cln + 1;
+#ifdef FEAT_DIFF
+ loff.fill = 0;
+#endif
+ for (curwin->w_topline = curwin->w_botline;
+ curwin->w_topline > 1;
+ curwin->w_topline = loff.lnum)
+ {
+ loff.lnum = curwin->w_topline;
+ topline_back(&loff);
+ if (used + loff.height > curwin->w_height)
+ break;
+ used += loff.height;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = loff.fill;
+#endif
+ }
+ set_empty_rows(curwin, used);
+ curwin->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
+ if (curwin->w_topline != old_topline
+#ifdef FEAT_DIFF
+ || curwin->w_topfill != old_topfill
+#endif
+ )
+ curwin->w_valid &= ~(VALID_WROW|VALID_CROW);
+ }
+ else
+ validate_botline();
+
+ /* The lines of the cursor line itself are always used. */
+#ifdef FEAT_DIFF
+ used = plines_nofill(cln);
+#else
+ validate_cheight();
+ used = curwin->w_cline_height;
+#endif
+
+ /* If the cursor is below botline, we will at least scroll by the height
+ * of the cursor line. Correct for empty lines, which are really part of
+ * botline. */
+ if (cln >= curwin->w_botline)
+ {
+ scrolled = used;
+ if (cln == curwin->w_botline)
+ scrolled -= curwin->w_empty_rows;
+ }
+
+ /*
+ * Stop counting lines to scroll when
+ * - hitting start of the file
+ * - scrolled nothing or at least 'sj' lines
+ * - at least 'so' lines below the cursor
+ * - lines between botline and cursor have been counted
+ */
+#ifdef FEAT_FOLDING
+ if (!hasFolding(curwin->w_cursor.lnum, &loff.lnum, &boff.lnum))
+#endif
+ {
+ loff.lnum = cln;
+ boff.lnum = cln;
+ }
+#ifdef FEAT_DIFF
+ loff.fill = 0;
+ boff.fill = 0;
+ fill_below_window = diff_check_fill(curwin, curwin->w_botline)
+ - curwin->w_filler_rows;
+#endif
+
+ while (loff.lnum > 1)
+ {
+ /* Stop when scrolled nothing or at least "min_scroll", found "extra"
+ * context for 'scrolloff' and counted all lines below the window. */
+ if ((((scrolled <= 0 || scrolled >= min_scroll)
+ && extra >= (
+#ifdef FEAT_MOUSE
+ mouse_dragging ? mouse_dragging - 1 :
+#endif
+ p_so))
+ || boff.lnum + 1 > curbuf->b_ml.ml_line_count)
+ && loff.lnum <= curwin->w_botline
+#ifdef FEAT_DIFF
+ && (loff.lnum < curwin->w_botline
+ || loff.fill >= fill_below_window)
+#endif
+ )
+ break;
+
+ /* Add one line above */
+ topline_back(&loff);
+ used += loff.height;
+ if (used > curwin->w_height)
+ break;
+ if (loff.lnum >= curwin->w_botline
+#ifdef FEAT_DIFF
+ && (loff.lnum > curwin->w_botline
+ || loff.fill <= fill_below_window)
+#endif
+ )
+ {
+ /* Count screen lines that are below the window. */
+ scrolled += loff.height;
+ if (loff.lnum == curwin->w_botline
+#ifdef FEAT_DIFF
+ && boff.fill == 0
+#endif
+ )
+ scrolled -= curwin->w_empty_rows;
+ }
+
+ if (boff.lnum < curbuf->b_ml.ml_line_count)
+ {
+ /* Add one line below */
+ botline_forw(&boff);
+ used += boff.height;
+ if (used > curwin->w_height)
+ break;
+ if (extra < (
+#ifdef FEAT_MOUSE
+ mouse_dragging > 0 ? mouse_dragging - 1 :
+#endif
+ p_so) || scrolled < min_scroll)
+ {
+ extra += boff.height;
+ if (boff.lnum >= curwin->w_botline
+#ifdef FEAT_DIFF
+ || (boff.lnum + 1 == curwin->w_botline
+ && boff.fill > curwin->w_filler_rows)
+#endif
+ )
+ {
+ /* Count screen lines that are below the window. */
+ scrolled += boff.height;
+ if (boff.lnum == curwin->w_botline
+#ifdef FEAT_DIFF
+ && boff.fill == 0
+#endif
+ )
+ scrolled -= curwin->w_empty_rows;
+ }
+ }
+ }
+ }
+
+ /* curwin->w_empty_rows is larger, no need to scroll */
+ if (scrolled <= 0)
+ line_count = 0;
+ /* more than a screenfull, don't scroll but redraw */
+ else if (used > curwin->w_height)
+ line_count = used;
+ /* scroll minimal number of lines */
+ else
+ {
+ line_count = 0;
+#ifdef FEAT_DIFF
+ boff.fill = curwin->w_topfill;
+#endif
+ boff.lnum = curwin->w_topline - 1;
+ for (i = 0; i < scrolled && boff.lnum < curwin->w_botline; )
+ {
+ botline_forw(&boff);
+ i += boff.height;
+ ++line_count;
+ }
+ if (i < scrolled) /* below curwin->w_botline, don't scroll */
+ line_count = 9999;
+ }
+
+ /*
+ * Scroll up if the cursor is off the bottom of the screen a bit.
+ * Otherwise put it at 1/2 of the screen.
+ */
+ if (line_count >= curwin->w_height && line_count > min_scroll)
+ scroll_cursor_halfway(FALSE);
+ else
+ scrollup(line_count, TRUE);
+
+ /*
+ * If topline didn't change we need to restore w_botline and w_empty_rows
+ * (we changed them).
+ * If topline did change, update_screen() will set botline.
+ */
+ if (curwin->w_topline == old_topline && set_topbot)
+ {
+ curwin->w_botline = old_botline;
+ curwin->w_empty_rows = old_empty_rows;
+ curwin->w_valid = old_valid;
+ }
+ curwin->w_valid |= VALID_TOPLINE;
+}
+
+/*
+ * Recompute topline to put the cursor halfway the window
+ * If "atend" is TRUE, also put it halfway at the end of the file.
+ */
+ void
+scroll_cursor_halfway(atend)
+ int atend;
+{
+ int above = 0;
+ linenr_T topline;
+#ifdef FEAT_DIFF
+ int topfill = 0;
+#endif
+ int below = 0;
+ int used;
+ lineoff_T loff;
+ lineoff_T boff;
+
+ loff.lnum = boff.lnum = curwin->w_cursor.lnum;
+#ifdef FEAT_FOLDING
+ (void)hasFolding(loff.lnum, &loff.lnum, &boff.lnum);
+#endif
+#ifdef FEAT_DIFF
+ used = plines_nofill(loff.lnum);
+ loff.fill = 0;
+ boff.fill = 0;
+#else
+ used = plines(loff.lnum);
+#endif
+ topline = loff.lnum;
+ while (topline > 1)
+ {
+ if (below <= above) /* add a line below the cursor first */
+ {
+ if (boff.lnum < curbuf->b_ml.ml_line_count)
+ {
+ botline_forw(&boff);
+ used += boff.height;
+ if (used > curwin->w_height)
+ break;
+ below += boff.height;
+ }
+ else
+ {
+ ++below; /* count a "~" line */
+ if (atend)
+ ++used;
+ }
+ }
+
+ if (below > above) /* add a line above the cursor */
+ {
+ topline_back(&loff);
+ used += loff.height;
+ if (used > curwin->w_height)
+ break;
+ above += loff.height;
+ topline = loff.lnum;
+#ifdef FEAT_DIFF
+ topfill = loff.fill;
+#endif
+ }
+ }
+#ifdef FEAT_FOLDING
+ if (!hasFolding(topline, &curwin->w_topline, NULL))
+#endif
+ curwin->w_topline = topline;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = topfill;
+ check_topfill(curwin, FALSE);
+#endif
+ curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
+ curwin->w_valid |= VALID_TOPLINE;
+}
+
+/*
+ * Correct the cursor position so that it is in a part of the screen at least
+ * 'so' lines from the top and bottom, if possible.
+ * If not possible, put it at the same position as scroll_cursor_halfway().
+ * When called topline must be valid!
+ */
+ void
+cursor_correct()
+{
+ int above = 0; /* screen lines above topline */
+ linenr_T topline;
+ int below = 0; /* screen lines below botline */
+ linenr_T botline;
+ int above_wanted, below_wanted;
+ linenr_T cln; /* Cursor Line Number */
+ int max_off;
+
+ /*
+ * How many lines we would like to have above/below the cursor depends on
+ * whether the first/last line of the file is on screen.
+ */
+ above_wanted = p_so;
+ below_wanted = p_so;
+#ifdef FEAT_MOUSE
+ if (mouse_dragging)
+ {
+ above_wanted = mouse_dragging - 1;
+ below_wanted = mouse_dragging - 1;
+ }
+#endif
+ if (curwin->w_topline == 1)
+ {
+ above_wanted = 0;
+ max_off = curwin->w_height / 2;
+ if (below_wanted > max_off)
+ below_wanted = max_off;
+ }
+ validate_botline();
+ if (curwin->w_botline == curbuf->b_ml.ml_line_count + 1
+#ifdef FEAT_MOUSE
+ && !mouse_dragging
+#endif
+ )
+ {
+ below_wanted = 0;
+ max_off = (curwin->w_height - 1) / 2;
+ if (above_wanted > max_off)
+ above_wanted = max_off;
+ }
+
+ /*
+ * If there are sufficient file-lines above and below the cursor, we can
+ * return now.
+ */
+ cln = curwin->w_cursor.lnum;
+ if (cln >= curwin->w_topline + above_wanted
+ && cln < curwin->w_botline - below_wanted
+#ifdef FEAT_FOLDING
+ && !hasAnyFolding(curwin)
+#endif
+ )
+ return;
+
+ /*
+ * Narrow down the area where the cursor can be put by taking lines from
+ * the top and the bottom until:
+ * - the desired context lines are found
+ * - the lines from the top is past the lines from the bottom
+ */
+ topline = curwin->w_topline;
+ botline = curwin->w_botline - 1;
+#ifdef FEAT_DIFF
+ /* count filler lines as context */
+ above = curwin->w_topfill;
+ below = curwin->w_filler_rows;
+#endif
+ while ((above < above_wanted || below < below_wanted) && topline < botline)
+ {
+ if (below < below_wanted && (below <= above || above >= above_wanted))
+ {
+#ifdef FEAT_FOLDING
+ if (hasFolding(botline, &botline, NULL))
+ ++below;
+ else
+#endif
+ below += plines(botline);
+ --botline;
+ }
+ if (above < above_wanted && (above < below || below >= below_wanted))
+ {
+#ifdef FEAT_FOLDING
+ if (hasFolding(topline, NULL, &topline))
+ ++above;
+ else
+#endif
+#ifndef FEAT_DIFF
+ above += plines(topline);
+#else
+ above += plines_nofill(topline);
+
+ /* Count filler lines below this line as context. */
+ if (topline < botline)
+ above += diff_check_fill(curwin, topline + 1);
+#endif
+ ++topline;
+ }
+ }
+ if (topline == botline || botline == 0)
+ curwin->w_cursor.lnum = topline;
+ else if (topline > botline)
+ curwin->w_cursor.lnum = botline;
+ else
+ {
+ if (cln < topline && curwin->w_topline > 1)
+ {
+ curwin->w_cursor.lnum = topline;
+ curwin->w_valid &=
+ ~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW);
+ }
+ if (cln > botline && curwin->w_botline <= curbuf->b_ml.ml_line_count)
+ {
+ curwin->w_cursor.lnum = botline;
+ curwin->w_valid &=
+ ~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW);
+ }
+ }
+ curwin->w_valid |= VALID_TOPLINE;
+}
+
+static void get_scroll_overlap __ARGS((lineoff_T *lp, int dir));
+
+/*
+ * move screen 'count' pages up or down and update screen
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+onepage(dir, count)
+ int dir;
+ long count;
+{
+ long n;
+ int retval = OK;
+ lineoff_T loff;
+ linenr_T old_topline = curwin->w_topline;
+
+ if (curbuf->b_ml.ml_line_count == 1) /* nothing to do */
+ {
+ beep_flush();
+ return FAIL;
+ }
+
+ for ( ; count > 0; --count)
+ {
+ validate_botline();
+ /*
+ * It's an error to move a page up when the first line is already on
+ * the screen. It's an error to move a page down when the last line
+ * is on the screen and the topline is 'scrolloff' lines from the
+ * last line.
+ */
+ if (dir == FORWARD
+ ? ((curwin->w_topline >= curbuf->b_ml.ml_line_count - p_so)
+ && curwin->w_botline > curbuf->b_ml.ml_line_count)
+ : (curwin->w_topline == 1
+#ifdef FEAT_DIFF
+ && curwin->w_topfill ==
+ diff_check_fill(curwin, curwin->w_topline)
+#endif
+ ))
+ {
+ beep_flush();
+ retval = FAIL;
+ break;
+ }
+
+#ifdef FEAT_DIFF
+ loff.fill = 0;
+#endif
+ if (dir == FORWARD)
+ {
+ /* at end of file */
+ if (curwin->w_botline > curbuf->b_ml.ml_line_count)
+ {
+ curwin->w_topline = curbuf->b_ml.ml_line_count;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = 0;
+#endif
+ curwin->w_valid &= ~(VALID_WROW|VALID_CROW);
+ }
+ else
+ {
+ /* For the overlap, start with the line just below the window
+ * and go upwards. */
+ loff.lnum = curwin->w_botline;
+#ifdef FEAT_DIFF
+ loff.fill = diff_check_fill(curwin, loff.lnum)
+ - curwin->w_filler_rows;
+#endif
+ get_scroll_overlap(&loff, -1);
+ curwin->w_topline = loff.lnum;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = loff.fill;
+ check_topfill(curwin, FALSE);
+#endif
+ curwin->w_cursor.lnum = curwin->w_topline;
+ curwin->w_valid &= ~(VALID_WCOL|VALID_CHEIGHT|VALID_WROW|
+ VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
+ }
+ }
+ else /* dir == BACKWARDS */
+ {
+#ifdef FEAT_DIFF
+ if (curwin->w_topline == 1)
+ {
+ /* Include max number of filler lines */
+ max_topfill();
+ continue;
+ }
+#endif
+ /* Find the line at the top of the window that is going to be the
+ * line at the bottom of the window. Make sure this results in
+ * the same line as before doing CTRL-F. */
+ loff.lnum = curwin->w_topline - 1;
+#ifdef FEAT_DIFF
+ loff.fill = diff_check_fill(curwin, loff.lnum + 1)
+ - curwin->w_topfill;
+#endif
+ get_scroll_overlap(&loff, 1);
+
+ if (loff.lnum >= curbuf->b_ml.ml_line_count)
+ {
+ loff.lnum = curbuf->b_ml.ml_line_count;
+#ifdef FEAT_DIFF
+ loff.fill = 0;
+ }
+ else
+ {
+ botline_topline(&loff);
+#endif
+ }
+ curwin->w_cursor.lnum = loff.lnum;
+
+ /* Find the line just above the new topline to get the right line
+ * at the bottom of the window. */
+ n = 0;
+ while (n <= curwin->w_height && loff.lnum >= 1)
+ {
+ topline_back(&loff);
+ n += loff.height;
+ }
+ if (n <= curwin->w_height) /* at begin of file */
+ {
+ curwin->w_topline = 1;
+#ifdef FEAT_DIFF
+ max_topfill();
+#endif
+ curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE);
+ }
+ else
+ {
+ /* Go two lines forward again. */
+#ifdef FEAT_DIFF
+ topline_botline(&loff);
+#endif
+ botline_forw(&loff);
+ botline_forw(&loff);
+#ifdef FEAT_DIFF
+ botline_topline(&loff);
+#endif
+#ifdef FEAT_FOLDING
+ /* We're at the wrong end of a fold now. */
+ (void)hasFolding(loff.lnum, &loff.lnum, NULL);
+#endif
+
+ /* Always scroll at least one line. Avoid getting stuck on
+ * very long lines. */
+ if (loff.lnum >= curwin->w_topline
+#ifdef FEAT_DIFF
+ && (loff.lnum > curwin->w_topline
+ || loff.fill >= curwin->w_topfill)
+#endif
+ )
+ {
+#ifdef FEAT_DIFF
+ /* First try using the maximum number of filler lines. If
+ * that's not enough, backup one line. */
+ loff.fill = curwin->w_topfill;
+ if (curwin->w_topfill < diff_check_fill(curwin,
+ curwin->w_topline))
+ max_topfill();
+ if (curwin->w_topfill == loff.fill)
+#endif
+ {
+ --curwin->w_topline;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = 0;
+#endif
+ }
+ comp_botline(curwin);
+ curwin->w_cursor.lnum = curwin->w_botline - 1;
+ curwin->w_valid &= ~(VALID_WCOL|VALID_CHEIGHT|
+ VALID_WROW|VALID_CROW);
+ }
+ else
+ {
+ curwin->w_topline = loff.lnum;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = loff.fill;
+ check_topfill(curwin, FALSE);
+#endif
+ curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE);
+ }
+ }
+ }
+ }
+#ifdef FEAT_FOLDING
+ foldAdjustCursor();
+#endif
+ cursor_correct();
+ beginline(BL_SOL | BL_FIX);
+ curwin->w_valid &= ~(VALID_WCOL|VALID_WROW|VALID_VIRTCOL);
+
+ /*
+ * Avoid the screen jumping up and down when 'scrolloff' is non-zero.
+ * But make sure we scroll at least one line (happens with mix of long
+ * wrapping lines and non-wrapping line).
+ */
+ if (retval == OK && dir == FORWARD && check_top_offset())
+ {
+ scroll_cursor_top(1, FALSE);
+ if (curwin->w_topline <= old_topline
+ && old_topline < curbuf->b_ml.ml_line_count)
+ {
+ curwin->w_topline = old_topline + 1;
+#ifdef FEAT_FOLDING
+ (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+#endif
+ }
+ }
+
+ redraw_later(VALID);
+ return retval;
+}
+
+/*
+ * Decide how much overlap to use for page-up or page-down scrolling.
+ * This is symmetric, so that doing both keeps the same lines displayed.
+ * Three lines are examined:
+ *
+ * before CTRL-F after CTRL-F / before CTRL-B
+ * etc. l1
+ * l1 last but one line ------------
+ * l2 last text line l2 top text line
+ * ------------- l3 second text line
+ * l3 etc.
+ */
+ static void
+get_scroll_overlap(lp, dir)
+ lineoff_T *lp;
+ int dir;
+{
+ int h1, h2, h3, h4;
+ int min_height = curwin->w_height - 2;
+ lineoff_T loff0, loff1, loff2;
+
+#ifdef FEAT_DIFF
+ if (lp->fill > 0)
+ lp->height = 1;
+ else
+ lp->height = plines_nofill(lp->lnum);
+#else
+ lp->height = plines(lp->lnum);
+#endif
+ h1 = lp->height;
+ if (h1 > min_height)
+ return; /* no overlap */
+
+ loff0 = *lp;
+ if (dir > 0)
+ botline_forw(lp);
+ else
+ topline_back(lp);
+ h2 = lp->height;
+ if (h2 + h1 > min_height)
+ {
+ *lp = loff0; /* no overlap */
+ return;
+ }
+
+ loff1 = *lp;
+ if (dir > 0)
+ botline_forw(lp);
+ else
+ topline_back(lp);
+ h3 = lp->height;
+ if (h3 + h2 > min_height)
+ {
+ *lp = loff0; /* no overlap */
+ return;
+ }
+
+ loff2 = *lp;
+ if (dir > 0)
+ botline_forw(lp);
+ else
+ topline_back(lp);
+ h4 = lp->height;
+ if (h4 + h3 + h2 > min_height || h3 + h2 + h1 > min_height)
+ *lp = loff1; /* 1 line overlap */
+ else
+ *lp = loff2; /* 2 lines overlap */
+ return;
+}
+
+/* #define KEEP_SCREEN_LINE */
+/*
+ * Scroll 'scroll' lines up or down.
+ */
+ void
+halfpage(flag, Prenum)
+ int flag;
+ linenr_T Prenum;
+{
+ long scrolled = 0;
+ int i;
+ int n;
+ int room;
+
+ if (Prenum)
+ curwin->w_p_scr = (Prenum > curwin->w_height) ?
+ curwin->w_height : Prenum;
+ n = (curwin->w_p_scr <= curwin->w_height) ?
+ curwin->w_p_scr : curwin->w_height;
+
+ validate_botline();
+ room = curwin->w_empty_rows;
+#ifdef FEAT_DIFF
+ room += curwin->w_filler_rows;
+#endif
+ if (flag)
+ {
+ /*
+ * scroll the text up
+ */
+ while (n > 0 && curwin->w_botline <= curbuf->b_ml.ml_line_count)
+ {
+#ifdef FEAT_DIFF
+ if (curwin->w_topfill > 0)
+ {
+ i = 1;
+ if (--n < 0 && scrolled > 0)
+ break;
+ --curwin->w_topfill;
+ }
+ else
+#endif
+ {
+#ifdef FEAT_DIFF
+ i = plines_nofill(curwin->w_topline);
+#else
+ i = plines(curwin->w_topline);
+#endif
+ n -= i;
+ if (n < 0 && scrolled > 0)
+ break;
+#ifdef FEAT_FOLDING
+ (void)hasFolding(curwin->w_topline, NULL, &curwin->w_topline);
+#endif
+ ++curwin->w_topline;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline);
+#endif
+
+#ifndef KEEP_SCREEN_LINE
+ if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
+ {
+ ++curwin->w_cursor.lnum;
+ curwin->w_valid &=
+ ~(VALID_VIRTCOL|VALID_CHEIGHT|VALID_WCOL);
+ }
+#endif
+ }
+ curwin->w_valid &= ~(VALID_CROW|VALID_WROW);
+ scrolled += i;
+
+ /*
+ * Correct w_botline for changed w_topline.
+ * Won't work when there are filler lines.
+ */
+#ifdef FEAT_DIFF
+ if (curwin->w_p_diff)
+ curwin->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP);
+ else
+#endif
+ {
+ room += i;
+ do
+ {
+ i = plines(curwin->w_botline);
+ if (i > room)
+ break;
+#ifdef FEAT_FOLDING
+ (void)hasFolding(curwin->w_botline, NULL,
+ &curwin->w_botline);
+#endif
+ ++curwin->w_botline;
+ room -= i;
+ } while (curwin->w_botline <= curbuf->b_ml.ml_line_count);
+ }
+ }
+
+#ifndef KEEP_SCREEN_LINE
+ /*
+ * When hit bottom of the file: move cursor down.
+ */
+ if (n > 0)
+ {
+# ifdef FEAT_FOLDING
+ if (hasAnyFolding(curwin))
+ {
+ while (--n >= 0
+ && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
+ {
+ (void)hasFolding(curwin->w_cursor.lnum, NULL,
+ &curwin->w_cursor.lnum);
+ ++curwin->w_cursor.lnum;
+ }
+ }
+ else
+# endif
+ curwin->w_cursor.lnum += n;
+ check_cursor_lnum();
+ }
+#else
+ /* try to put the cursor in the same screen line */
+ while ((curwin->w_cursor.lnum < curwin->w_topline || scrolled > 0)
+ && curwin->w_cursor.lnum < curwin->w_botline - 1)
+ {
+ scrolled -= plines(curwin->w_cursor.lnum);
+ if (scrolled < 0 && curwin->w_cursor.lnum >= curwin->w_topline)
+ break;
+# ifdef FEAT_FOLDING
+ (void)hasFolding(curwin->w_cursor.lnum, NULL,
+ &curwin->w_cursor.lnum);
+# endif
+ ++curwin->w_cursor.lnum;
+ }
+#endif
+ }
+ else
+ {
+ /*
+ * scroll the text down
+ */
+ while (n > 0 && curwin->w_topline > 1)
+ {
+#ifdef FEAT_DIFF
+ if (curwin->w_topfill < diff_check_fill(curwin, curwin->w_topline))
+ {
+ i = 1;
+ if (--n < 0 && scrolled > 0)
+ break;
+ ++curwin->w_topfill;
+ }
+ else
+#endif
+ {
+#ifdef FEAT_DIFF
+ i = plines_nofill(curwin->w_topline - 1);
+#else
+ i = plines(curwin->w_topline - 1);
+#endif
+ n -= i;
+ if (n < 0 && scrolled > 0)
+ break;
+ --curwin->w_topline;
+#ifdef FEAT_FOLDING
+ (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+#endif
+#ifdef FEAT_DIFF
+ curwin->w_topfill = 0;
+#endif
+ }
+ curwin->w_valid &= ~(VALID_CROW|VALID_WROW|
+ VALID_BOTLINE|VALID_BOTLINE_AP);
+ scrolled += i;
+#ifndef KEEP_SCREEN_LINE
+ if (curwin->w_cursor.lnum > 1)
+ {
+ --curwin->w_cursor.lnum;
+ curwin->w_valid &= ~(VALID_VIRTCOL|VALID_CHEIGHT|VALID_WCOL);
+ }
+#endif
+ }
+#ifndef KEEP_SCREEN_LINE
+ /*
+ * When hit top of the file: move cursor up.
+ */
+ if (n > 0)
+ {
+ if (curwin->w_cursor.lnum <= (linenr_T)n)
+ curwin->w_cursor.lnum = 1;
+ else
+# ifdef FEAT_FOLDING
+ if (hasAnyFolding(curwin))
+ {
+ while (--n >= 0 && curwin->w_cursor.lnum > 1)
+ {
+ --curwin->w_cursor.lnum;
+ (void)hasFolding(curwin->w_cursor.lnum,
+ &curwin->w_cursor.lnum, NULL);
+ }
+ }
+ else
+# endif
+ curwin->w_cursor.lnum -= n;
+ }
+#else
+ /* try to put the cursor in the same screen line */
+ scrolled += n; /* move cursor when topline is 1 */
+ while (curwin->w_cursor.lnum > curwin->w_topline
+ && (scrolled > 0 || curwin->w_cursor.lnum >= curwin->w_botline))
+ {
+ scrolled -= plines(curwin->w_cursor.lnum - 1);
+ if (scrolled < 0 && curwin->w_cursor.lnum < curwin->w_botline)
+ break;
+ --curwin->w_cursor.lnum;
+# ifdef FEAT_FOLDING
+ foldAdjustCursor();
+# endif
+ }
+#endif
+ }
+# ifdef FEAT_FOLDING
+ /* Move cursor to first line of closed fold. */
+ foldAdjustCursor();
+# endif
+#ifdef FEAT_DIFF
+ check_topfill(curwin, !flag);
+#endif
+ cursor_correct();
+ beginline(BL_SOL | BL_FIX);
+ redraw_later(VALID);
+}
diff --git a/src/mysign b/src/mysign
new file mode 100644
index 000000000..1528e109c
--- /dev/null
+++ b/src/mysign
@@ -0,0 +1 @@
+=auto/configure-lastupdate=1084789875.25=configure.in@md5=8f2cf9135e297094c53080c53e541a0f-@buildcheck=2c92a9e4676b2304fab9af16f1664194
diff --git a/src/nbdebug.c b/src/nbdebug.c
new file mode 100644
index 000000000..daf87a856
--- /dev/null
+++ b/src/nbdebug.c
@@ -0,0 +1,182 @@
+/* vi:set ts=8 sts=8 sw=8:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Visual Workshop integration by Gordon Prieur
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * NetBeans Debugging Tools. What are these tools and why are they important?
+ * There are two main tools here. The first tool is a tool for delaying or
+ * stopping gvim during startup. The second tool is a protocol log tool.
+ *
+ * The startup delay tool is called nbdebug_wait(). This is very important for
+ * debugging startup problems because gvim will be started automatically from
+ * netbeans and cannot be run directly from a debugger. The only way to debug
+ * a gvim started by netbeans is by attaching a debugger to it. Without this
+ * tool all starup code will have completed before you can get the pid and
+ * attach.
+ *
+ * The second tool is a log tool.
+ *
+ * This code must have NBDEBUG defined for it to be compiled into vim/gvim.
+ */
+
+#ifdef NBDEBUG
+
+#include <stdarg.h>
+
+#include "vim.h"
+
+FILE *nb_debug = NULL;
+u_int nb_dlevel = 0; /* nb_debug verbosity level */
+
+void nbdb(char *, ...);
+void nbtrace(char *, ...);
+
+static int lookup(char *);
+#ifndef FEAT_GUI_W32
+static int errorHandler(Display *, XErrorEvent *);
+#endif
+
+/*
+ * nbdebug_wait - This function can be used to delay or stop execution of vim.
+ * Its normally used to delay startup while attaching a
+ * debugger to a running process. Since workshop starts gvim
+ * from a background process this is the only way to debug
+ * startup problems.
+ */
+
+void nbdebug_wait(
+ u_int wait_flags, /* tells what to do */
+ char *wait_var, /* wait environment variable */
+ u_int wait_secs) /* how many seconds to wait */
+{
+
+ init_homedir(); /* not inited yet */
+#ifdef USE_WDDUMP
+ WDDump(0, 0, 0);
+#endif
+
+ /* for debugging purposes only */
+ if (wait_flags & WT_ENV && wait_var && getenv(wait_var) != NULL) {
+ sleep(atoi(getenv(wait_var)));
+ } else if (wait_flags & WT_WAIT && lookup("~/.gvimwait")) {
+ sleep(wait_secs > 0 && wait_secs < 120 ? wait_secs : 20);
+ } else if (wait_flags & WT_STOP && lookup("~/.gvimstop")) {
+ int w = 1;
+ while (w) {
+ ;
+ }
+ }
+} /* end nbdebug_wait */
+
+
+void
+nbdebug_log_init(
+ char *log_var, /* env var with log file */
+ char *level_var) /* env var with nb_debug level */
+{
+ char *file; /* possible nb_debug output file */
+ char *cp; /* nb_dlevel pointer */
+
+ if (log_var && (file = getenv(log_var)) != NULL) {
+ time_t now;
+
+ nb_debug = fopen(file, "a");
+ time(&now);
+ fprintf(nb_debug, "%s", asctime(localtime(&now)));
+ if (level_var && (cp = getenv(level_var)) != NULL) {
+ nb_dlevel = strtoul(cp, NULL, 0);
+ } else {
+ nb_dlevel = NB_TRACE; /* default level */
+ }
+ /* XSetErrorHandler(errorHandler); */
+ }
+
+} /* end nbdebug_log_init */
+
+
+
+
+void
+nbtrace(
+ char *fmt,
+ ...)
+{
+ va_list ap;
+
+ if (nb_debug!= NULL && (nb_dlevel & (NB_TRACE | NB_TRACE_VERBOSE))) {
+ va_start(ap, fmt);
+ vfprintf(nb_debug, fmt, ap);
+ va_end(ap);
+ fflush(nb_debug);
+ }
+
+} /* end nbtrace */
+
+
+void
+nbdbg(
+ char *fmt,
+ ...)
+{
+ va_list ap;
+
+ if (nb_debug != NULL) {
+ va_start(ap, fmt);
+ vfprintf(nb_debug, fmt, ap);
+ va_end(ap);
+ fflush(nb_debug);
+ }
+
+} /* end nbdbg */
+
+
+static int
+lookup(
+ char *file)
+{
+ char buf[BUFSIZ];
+
+ expand_env((char_u *) file, (char_u *) buf, BUFSIZ);
+ return
+#ifndef FEAT_GUI_W32
+ (access(buf, F_OK) == 0);
+#else
+ (access(buf, 0) == 0);
+#endif
+
+} /* end lookup */
+
+#ifndef FEAT_GUI_W32
+static int
+errorHandler(
+ Display *dpy,
+ XErrorEvent *err)
+{
+ char msg[256];
+ char buf[256];
+
+ XGetErrorText(dpy, err->error_code, msg, sizeof(msg));
+ nbdbg("\n\nNBDEBUG Vim: X Error of failed request: %s\n", msg);
+
+ sprintf(buf, "%d", err->request_code);
+ XGetErrorDatabaseText(dpy,
+ "XRequest", buf, "Unknown", msg, sizeof(msg));
+ nbdbg("\tMajor opcode of failed request: %d (%s)\n",
+ err->request_code, msg);
+ if (err->request_code > 128) {
+ nbdbg("\tMinor opcode of failed request: %d\n",
+ err->minor_code);
+ }
+
+ return 0;
+}
+#endif
+
+
+#endif /* NBDEBUG */
diff --git a/src/nbdebug.h b/src/nbdebug.h
new file mode 100644
index 000000000..46b2c0833
--- /dev/null
+++ b/src/nbdebug.h
@@ -0,0 +1,81 @@
+/* vi:set ts=8 sts=8 sw=8:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Visual Workshop integration by Gordon Prieur
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+
+#ifndef NBDEBUG_H
+#define NBDEBUG_H
+
+#ifdef NBDEBUG
+
+#ifndef ASSERT
+#define ASSERT(c) \
+ if (!(c)) { \
+ fprintf(stderr, "Assertion failed: line %d, file %s\n", \
+ __LINE__, __FILE__); \
+ fflush(stderr); \
+ abort(); \
+ }
+#endif
+
+#define nbdebug(a) nbdbg##a
+
+#define NB_TRACE 0x00000001
+#define NB_TRACE_VERBOSE 0x00000002
+#define NB_TRACE_COLONCMD 0x00000004
+#define NB_DEBUG_ALL 0xffffffff
+
+#define NBDLEVEL(flags) (nb_debug != NULL && (nb_dlevel & (flags)))
+
+#define NBDEBUG_TRACE 1
+//#define NBDEBUG_SENSE 2
+
+typedef enum {
+ WT_ENV = 1, /* look for env var if set */
+ WT_WAIT, /* look for ~/.gvimwait if set */
+ WT_STOP /* look for ~/.gvimstop if set */
+} WtWait;
+
+
+void nbdbg(char *, ...);
+void nbtrace(char *, ...);
+
+void nbdebug_wait __ARGS((u_int wait_flags, char *wait_var, u_int wait_secs));
+void nbdebug_log_init __ARGS((char *log_var, char *level_var));
+
+extern FILE *nb_debug;
+extern u_int nb_dlevel; /* nb_debug verbosity level */
+
+# else /* not NBDEBUG */
+
+#ifndef ASSERT
+# define ASSERT(c)
+#endif
+
+/*
+ * The following 2 stubs are needed because a macro cannot be used because of
+ * the variable number of arguments.
+ */
+
+void
+nbdbg(
+ char *fmt,
+ ...)
+{
+}
+
+
+void
+nbtrace(
+ char *fmt,
+ ...)
+{
+}
+
+#endif /* NBDEBUG */
+#endif /* NBDEBUG_H */
diff --git a/src/netbeans.c b/src/netbeans.c
new file mode 100644
index 000000000..087f35be2
--- /dev/null
+++ b/src/netbeans.c
@@ -0,0 +1,3185 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Netbeans integration by David Weatherford
+ * Adopted for Win32 by Sergey Khorev
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * Implements client side of org.netbeans.modules.emacs editor
+ * integration protocol. Be careful! The protocol uses offsets
+ * which are *between* characters, whereas vim uses line number
+ * and column number which are *on* characters.
+ * See ":help netbeans-protocol" for explanation.
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_NETBEANS_INTG) || defined(PROTO)
+
+/* Note: when making changes here also adjust configure.in. */
+# include <stdarg.h>
+# include <fcntl.h>
+#ifdef WIN32
+# ifdef DEBUG
+# include <tchar.h> /* for _T definition for TRACEn macros */
+# endif
+# include <io.h>
+/* WinSock API is separated from C API, thus we can't use read(), write(),
+ * errno... */
+# define sock_errno WSAGetLastError()
+# define ECONNREFUSED WSAECONNREFUSED
+# ifdef EINTR
+# undef EINTR
+# endif
+# define EINTR WSAEINTR
+# define sock_write(sd, buf, len) send(sd, buf, len, 0)
+# define sock_read(sd, buf, len) recv(sd, buf, len, 0)
+# define sock_close(sd) closesocket(sd)
+# define sleep(t) Sleep(t*1000) /* WinAPI Sleep() accepts milliseconds */
+#else
+# include <netdb.h>
+# include <netinet/in.h>
+# include <sys/socket.h>
+# ifdef HAVE_LIBGEN_H
+# include <libgen.h>
+# endif
+# define sock_errno errno
+# define sock_write(sd, buf, len) write(sd, buf, len)
+# define sock_read(sd, buf, len) read(sd, buf, len)
+# define sock_close(sd) close(sd)
+#endif
+
+#include "version.h"
+
+#define INET_SOCKETS
+
+#define GUARDED 10000 /* typenr for "guarded" annotation */
+#define GUARDEDOFFSET 1000000 /* base for "guarded" sign id's */
+
+/* The first implementation (working only with Netbeans) returned "1.1". The
+ * protocol implemented here also supports A-A-P. */
+static char *ExtEdProtocolVersion = "2.2";
+
+static long pos2off __ARGS((buf_T *, pos_T *));
+static pos_T *off2pos __ARGS((buf_T *, long));
+static pos_T *get_off_or_lnum __ARGS((buf_T *buf, char_u **argp));
+static long get_buf_size __ARGS((buf_T *));
+
+static void netbeans_connect __ARGS((void));
+static int getConnInfo __ARGS((char *file, char **host, char **port, char **password));
+
+static void nb_init_graphics __ARGS((void));
+static void coloncmd __ARGS((char *cmd, ...));
+#ifdef FEAT_GUI_MOTIF
+static void messageFromNetbeans __ARGS((XtPointer, int *, XtInputId *));
+#endif
+#ifdef FEAT_GUI_GTK
+static void messageFromNetbeans __ARGS((gpointer, gint, GdkInputCondition));
+#endif
+static void nb_parse_cmd __ARGS((char_u *));
+static int nb_do_cmd __ARGS((int, char_u *, int, int, char_u *));
+static void nb_send __ARGS((char *buf, char *fun));
+#ifdef FEAT_BEVAL
+static void netbeans_beval_cb __ARGS((BalloonEval *beval, int state));
+#endif
+
+static int sd = -1; /* socket fd for Netbeans connection */
+#ifdef FEAT_GUI_MOTIF
+static XtInputId inputHandler; /* Cookie for input */
+#endif
+#ifdef FEAT_GUI_GTK
+static gint inputHandler; /* Cookie for input */
+#endif
+#ifdef FEAT_GUI_W32
+static int inputHandler = -1; /* simply ret.value of WSAAsyncSelect() */
+extern HWND s_hwnd; /* Gvim's Window handle */
+#endif
+static int cmdno; /* current command number for reply */
+static int haveConnection = FALSE; /* socket is connected and
+ initialization is done */
+static int oldFire = 1;
+static int exit_delay = 2; /* exit delay in seconds */
+
+#ifdef FEAT_BEVAL
+# if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)
+extern Widget textArea;
+# endif
+BalloonEval *balloonEval = NULL;
+#endif
+
+/*
+ * Include the debugging code if wanted.
+ */
+#ifdef NBDEBUG
+# include "nbdebug.c"
+#endif
+
+/* Connect back to Netbeans process */
+#if defined(FEAT_GUI_MOTIF) || defined(PROTO)
+ void
+netbeans_Xt_connect(void *context)
+{
+ netbeans_connect();
+ if (sd > 0)
+ {
+ /* tell notifier we are interested in being called
+ * when there is input on the editor connection socket
+ */
+ inputHandler = XtAppAddInput((XtAppContext)context, sd,
+ (XtPointer)(XtInputReadMask + XtInputExceptMask),
+ messageFromNetbeans, NULL);
+ }
+}
+
+ static void
+netbeans_disconnect(void)
+{
+ if (inputHandler != (XtInputId)NULL)
+ {
+ XtRemoveInput(inputHandler);
+ inputHandler = (XtInputId)NULL;
+ }
+ sd = -1;
+ haveConnection = FALSE;
+}
+#endif /* FEAT_MOTIF_GUI */
+
+#if defined(FEAT_GUI_GTK) || defined(PROTO)
+ void
+netbeans_gtk_connect(void)
+{
+# ifdef FEAT_BEVAL
+ /*
+ * Set up the Balloon Expression Evaluation area.
+ * Always create it but disable it when 'ballooneval' isn't set.
+ */
+ balloonEval = gui_mch_create_beval_area(gui.drawarea, NULL,
+ &netbeans_beval_cb, NULL);
+ if (!p_beval)
+ gui_mch_disable_beval_area(balloonEval);
+# endif
+
+ netbeans_connect();
+ if (sd > 0)
+ {
+ /*
+ * Tell gdk we are interested in being called when there
+ * is input on the editor connection socket
+ */
+ inputHandler = gdk_input_add(sd, (GdkInputCondition)
+ ((int)GDK_INPUT_READ + (int)GDK_INPUT_EXCEPTION),
+ messageFromNetbeans, NULL);
+ }
+}
+
+ static void
+netbeans_disconnect(void)
+{
+ if (inputHandler != 0)
+ {
+ gdk_input_remove(inputHandler);
+ inputHandler = 0;
+ }
+ sd = -1;
+ haveConnection = FALSE;
+}
+#endif /* FEAT_GUI_GTK */
+
+#if defined(FEAT_GUI_W32) || defined(PROTO)
+ void
+netbeans_w32_connect(void)
+{
+ netbeans_connect();
+ if (sd > 0)
+ {
+ /*
+ * Tell Windows we are interested in receiving message when there
+ * is input on the editor connection socket
+ */
+ inputHandler = WSAAsyncSelect(sd, s_hwnd, WM_NETBEANS, FD_READ);
+ }
+}
+
+ static void
+netbeans_disconnect(void)
+{
+ if (inputHandler == 0)
+ {
+ WSAAsyncSelect(sd, s_hwnd, 0, 0);
+ inputHandler = -1;
+ }
+ sd = -1;
+ haveConnection = FALSE;
+
+ /* It seems that Motif and GTK versions also need this: */
+ gui_mch_destroy_beval_area(balloonEval);
+ balloonEval = NULL;
+}
+#endif /* FEAT_GUI_W32 */
+
+#define NB_DEF_HOST "localhost"
+#define NB_DEF_ADDR "3219"
+#define NB_DEF_PASS "changeme"
+
+ static void
+netbeans_connect(void)
+{
+#ifdef INET_SOCKETS
+ struct sockaddr_in server;
+ struct hostent * host;
+# ifdef FEAT_GUI_W32
+ u_short port;
+# else
+ int port;
+#endif
+#else
+ struct sockaddr_un server;
+#endif
+ char buf[32];
+ char *hostname = NULL;
+ char *address = NULL;
+ char *password = NULL;
+ char *fname;
+ char *arg = NULL;
+
+ if (netbeansArg[3] == '=')
+ {
+ /* "-nb=fname": Read info from specified file. */
+ if (getConnInfo(netbeansArg + 4, &hostname, &address, &password)
+ == FAIL)
+ return;
+ }
+ else
+ {
+ if (netbeansArg[3] == ':')
+ /* "-nb:<host>:<addr>:<password>": get info from argument */
+ arg = netbeansArg + 4;
+ if (arg == NULL && (fname = getenv("__NETBEANS_CONINFO")) != NULL)
+ {
+ /* "-nb": get info from file specified in environment */
+ if (getConnInfo(fname, &hostname, &address, &password) == FAIL)
+ return;
+ }
+ else
+ {
+ if (arg != NULL)
+ {
+ /* "-nb:<host>:<addr>:<password>": get info from argument */
+ hostname = arg;
+ address = strchr(hostname, ':');
+ if (address != NULL)
+ {
+ *address++ = '\0';
+ password = strchr(address, ':');
+ if (password != NULL)
+ *password++ = '\0';
+ }
+ }
+
+ /* Get the missing values from the environment. */
+ if (hostname == NULL || *hostname == '\0')
+ hostname = getenv("__NETBEANS_HOST");
+ if (address == NULL)
+ address = getenv("__NETBEANS_SOCKET");
+ if (password == NULL)
+ password = getenv("__NETBEANS_VIM_PASSWORD");
+
+ /* Move values to allocated memory. */
+ if (hostname != NULL)
+ hostname = (char *)vim_strsave((char_u *)hostname);
+ if (address != NULL)
+ address = (char *)vim_strsave((char_u *)address);
+ if (password != NULL)
+ password = (char *)vim_strsave((char_u *)password);
+ }
+ }
+
+ /* Use the default when a value is missing. */
+ if (hostname == NULL || *hostname == '\0')
+ {
+ vim_free(hostname);
+ hostname = (char *)vim_strsave((char_u *)NB_DEF_HOST);
+ }
+ if (address == NULL || *address == '\0')
+ {
+ vim_free(address);
+ address = (char *)vim_strsave((char_u *)NB_DEF_ADDR);
+ }
+ if (password == NULL || *password == '\0')
+ {
+ vim_free(password);
+ password = (char *)vim_strsave((char_u *)NB_DEF_PASS);
+ }
+ if (hostname == NULL || address == NULL || password == NULL)
+ goto theend; /* out of memory */
+
+#ifdef INET_SOCKETS
+ port = atoi(address);
+
+ if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ {
+ PERROR("socket() in netbeans_connect()");
+ goto theend;
+ }
+
+ /* Get the server internet address and put into addr structure */
+ /* fill in the socket address structure and connect to server */
+ memset((char *)&server, '\0', sizeof(server));
+ server.sin_family = AF_INET;
+ server.sin_port = htons(port);
+ if ((host = gethostbyname(hostname)) == NULL)
+ {
+ if (mch_access(hostname, R_OK) >= 0)
+ {
+ /* DEBUG: input file */
+ sd = mch_open(hostname, O_RDONLY, 0);
+ goto theend;
+ }
+ PERROR("gethostbyname() in netbeans_connect()");
+ sd = -1;
+ goto theend;
+ }
+ memcpy((char *)&server.sin_addr, host->h_addr, host->h_length);
+#else
+ if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ {
+ PERROR("socket()");
+ goto theend;
+ }
+
+ server.sun_family = AF_UNIX;
+ strcpy(server.sun_path, address);
+#endif
+ /* Connect to server */
+ if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
+ {
+ nbdebug(("netbeans_connect: Connect failed with errno %d\n", sock_errno));
+ if (sock_errno == ECONNREFUSED)
+ {
+ sock_close(sd);
+#ifdef INET_SOCKETS
+ if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ {
+ PERROR("socket()#2 in netbeans_connect()");
+ goto theend;
+ }
+#else
+ if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ {
+ PERROR("socket()#2 in netbeans_connect()");
+ goto theend;
+ }
+#endif
+ if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
+ {
+ int retries = 36;
+ int success = FALSE;
+ while (retries--
+ && ((sock_errno == ECONNREFUSED) || (sock_errno == EINTR)))
+ {
+ nbdebug(("retrying...\n"));
+ sleep(5);
+ if (connect(sd, (struct sockaddr *)&server,
+ sizeof(server)) == 0)
+ {
+ success = TRUE;
+ break;
+ }
+ }
+ if (!success)
+ {
+ /* Get here when the server can't be found. */
+ PERROR(_("Cannot connect to Netbeans #2"));
+ getout(1);
+ }
+ }
+
+ }
+ else
+ {
+ PERROR(_("Cannot connect to Netbeans"));
+ getout(1);
+ }
+ }
+
+ sprintf(buf, "AUTH %s\n", password);
+ nb_send(buf, "netbeans_connect");
+
+ sprintf(buf, "0:version=0 \"%s\"\n", ExtEdProtocolVersion);
+ nb_send(buf, "externaleditor_version");
+
+ nbdebug(("netbeans_connect: Connection succeeded\n"));
+
+/* nb_init_graphics(); delay until needed */
+
+ haveConnection = TRUE;
+
+theend:
+ vim_free(hostname);
+ vim_free(address);
+ vim_free(password);
+ return;
+}
+
+/*
+ * Obtain the NetBeans hostname, port address and password from a file.
+ * Return the strings in allocated memory.
+ * Return FAIL if the file could not be read, OK otherwise (no matter what it
+ * contains).
+ */
+ static int
+getConnInfo(char *file, char **host, char **port, char **auth)
+{
+ FILE *fp;
+ char_u buf[BUFSIZ];
+ char_u *lp;
+ char_u *nl;
+#ifdef UNIX
+ struct stat st;
+
+ /*
+ * For Unix only accept the file when it's not accessible by others.
+ * The open will then fail if we don't own the file.
+ */
+ if (mch_stat(file, &st) == 0 && (st.st_mode & 0077) != 0)
+ {
+ EMSG2(_("E668: Wrong access mode for NetBeans connection info file: \"%s\""),
+ file);
+ return FAIL;
+ }
+#endif
+
+ fp = mch_fopen(file, "r");
+ if (fp == NULL)
+ {
+ PERROR("E660: Cannot open NetBeans connection info file");
+ return FAIL;
+ }
+
+ /* Read the file. There should be one of each parameter */
+ while ((lp = (char_u *)fgets((char *)buf, BUFSIZ, fp)) != NULL)
+ {
+ if ((nl = vim_strchr(lp, '\n')) != NULL)
+ *nl = 0; /* strip off the trailing newline */
+
+ if (STRNCMP(lp, "host=", 5) == 0)
+ {
+ vim_free(*host);
+ *host = (char *)vim_strsave(&buf[5]);
+ }
+ else if (STRNCMP(lp, "port=", 5) == 0)
+ {
+ vim_free(*port);
+ *port = (char *)vim_strsave(&buf[5]);
+ }
+ else if (STRNCMP(lp, "auth=", 5) == 0)
+ {
+ vim_free(*auth);
+ *auth = (char *)vim_strsave(&buf[5]);
+ }
+ }
+ fclose(fp);
+
+ return OK;
+}
+
+
+struct keyqueue
+{
+ int key;
+ struct keyqueue *next;
+ struct keyqueue *prev;
+};
+
+typedef struct keyqueue keyQ_T;
+
+static keyQ_T keyHead; /* dummy node, header for circular queue */
+
+
+/*
+ * Queue up key commands sent from netbeans.
+ */
+ static void
+postpone_keycommand(int key)
+{
+ keyQ_T *node;
+
+ node = (keyQ_T *)alloc(sizeof(keyQ_T));
+
+ if (keyHead.next == NULL) /* initialize circular queue */
+ {
+ keyHead.next = &keyHead;
+ keyHead.prev = &keyHead;
+ }
+
+ /* insert node at tail of queue */
+ node->next = &keyHead;
+ node->prev = keyHead.prev;
+ keyHead.prev->next = node;
+ keyHead.prev = node;
+
+ node->key = key;
+}
+
+/*
+ * Handle any queued-up NetBeans keycommands to be send.
+ */
+ static void
+handle_key_queue(void)
+{
+ while (keyHead.next && keyHead.next != &keyHead)
+ {
+ /* first, unlink the node */
+ keyQ_T *node = keyHead.next;
+ keyHead.next = node->next;
+ node->next->prev = node->prev;
+
+ /* now, send the keycommand */
+ netbeans_keycommand(node->key);
+
+ /* Finally, dispose of the node */
+ vim_free(node);
+ }
+}
+
+
+struct cmdqueue
+{
+ char_u *buffer;
+ struct cmdqueue *next;
+ struct cmdqueue *prev;
+};
+
+typedef struct cmdqueue queue_T;
+
+static queue_T head; /* dummy node, header for circular queue */
+
+
+/*
+ * Put the buffer on the work queue; possibly save it to a file as well.
+ */
+ static void
+save(char_u *buf, int len)
+{
+ queue_T *node;
+
+ node = (queue_T *)alloc(sizeof(queue_T));
+ if (node == NULL)
+ return; /* out of memory */
+ node->buffer = alloc(len + 1);
+ if (node->buffer == NULL)
+ {
+ vim_free(node);
+ return; /* out of memory */
+ }
+ mch_memmove(node->buffer, buf, (size_t)len);
+ node->buffer[len] = NUL;
+
+ if (head.next == NULL) /* initialize circular queue */
+ {
+ head.next = &head;
+ head.prev = &head;
+ }
+
+ /* insert node at tail of queue */
+ node->next = &head;
+ node->prev = head.prev;
+ head.prev->next = node;
+ head.prev = node;
+
+#ifdef NBDEBUG
+ {
+ static int outfd = -2;
+
+ /* possibly write buffer out to a file */
+ if (outfd == -3)
+ return;
+
+ if (outfd == -2)
+ {
+ char *file = getenv("__NETBEANS_SAVE");
+ if (file == NULL)
+ outfd = -3;
+ else
+ outfd = mch_open(file, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ }
+
+ if (outfd >= 0)
+ write(outfd, buf, len);
+ }
+#endif
+}
+
+
+/*
+ * While there's still a command in the work queue, parse and execute it.
+ */
+ static void
+nb_parse_messages(void)
+{
+ char_u *p;
+ queue_T *node;
+
+ while (head.next != &head)
+ {
+ node = head.next;
+
+ /* Locate the first line in the first buffer. */
+ p = vim_strchr(node->buffer, '\n');
+ if (p == NULL)
+ {
+ /* Command isn't complete. If there is no following buffer,
+ * return (wait for more). If there is another buffer following,
+ * prepend the text to that buffer and delete this one. */
+ if (node->next == &head)
+ return;
+ p = alloc(STRLEN(node->buffer) + STRLEN(node->next->buffer) + 1);
+ if (p == NULL)
+ return; /* out of memory */
+ STRCPY(p, node->buffer);
+ STRCAT(p, node->next->buffer);
+ vim_free(node->next->buffer);
+ node->next->buffer = p;
+
+ /* dispose of the node and buffer */
+ head.next = node->next;
+ node->next->prev = node->prev;
+ vim_free(node->buffer);
+ vim_free(node);
+ }
+ else
+ {
+ /* There is a complete command at the start of the buffer.
+ * Terminate it with a NUL. When no more text is following unlink
+ * the buffer. Do this before executing, because new buffers can
+ * be added while busy handling the command. */
+ *p++ = NUL;
+ if (*p == NUL)
+ {
+ head.next = node->next;
+ node->next->prev = node->prev;
+ }
+
+ /* now, parse and execute the commands */
+ nb_parse_cmd(node->buffer);
+
+ if (*p == NUL)
+ {
+ /* buffer finished, dispose of the node and buffer */
+ vim_free(node->buffer);
+ vim_free(node);
+ }
+ else
+ {
+ /* more follows, move to the start */
+ mch_memmove(node->buffer, p, STRLEN(p) + 1);
+ }
+ }
+ }
+}
+
+/* Buffer size for reading incoming messages. */
+#define MAXMSGSIZE 4096
+
+/*
+ * Read and process a command from netbeans.
+ */
+/*ARGSUSED*/
+#if defined(FEAT_GUI_W32) || defined(PROTO)
+/* Use this one when generating prototypes, the others are static. */
+ void
+messageFromNetbeansW32()
+#else
+# ifdef FEAT_GUI_MOTIF
+ static void
+messageFromNetbeans(XtPointer clientData, int *unused1, XtInputId *unused2)
+# endif
+# ifdef FEAT_GUI_GTK
+ static void
+messageFromNetbeans(gpointer clientData, gint unused1,
+ GdkInputCondition unused2)
+# endif
+#endif
+{
+ static char_u *buf = NULL;
+ int len;
+ int readlen = 0;
+ static int level = 0;
+
+ if (sd < 0)
+ {
+ nbdebug(("messageFromNetbeans() called without a socket\n"));
+ return;
+ }
+
+ ++level; /* recursion guard; this will be called from the X event loop */
+
+ /* Allocate a buffer to read into. */
+ if (buf == NULL)
+ {
+ buf = alloc(MAXMSGSIZE);
+ if (buf == NULL)
+ return; /* out of memory! */
+ }
+
+ /* Keep on reading for as long as there is something to read. */
+ for (;;)
+ {
+ len = sock_read(sd, buf, MAXMSGSIZE);
+ if (len <= 0)
+ break; /* error or nothing more to read */
+
+ /* Store the read message in the queue. */
+ save(buf, len);
+ readlen += len;
+ if (len < MAXMSGSIZE)
+ break; /* did read everything that's available */
+ }
+
+ if (readlen <= 0)
+ {
+ /* read error or didn't read anything */
+ netbeans_disconnect();
+ nbdebug(("messageFromNetbeans: Error in read() from socket\n"));
+ if (len < 0)
+ PERROR(_("read from Netbeans socket"));
+ return; /* don't try to parse it */;
+ }
+
+ /* Parse the messages, but avoid recursion. */
+ if (level == 1)
+ nb_parse_messages();
+
+ --level;
+}
+
+/*
+ * Handle one NUL terminated command.
+ *
+ * format of a command from netbeans:
+ *
+ * 6:setTitle!84 "a.c"
+ *
+ * bufno
+ * colon
+ * cmd
+ * !
+ * cmdno
+ * args
+ *
+ * for function calls, the ! is replaced by a /
+ */
+ static void
+nb_parse_cmd(char_u *cmd)
+{
+ char_u *verb;
+ char_u *q;
+ int bufno;
+ int isfunc = -1;
+
+ if (STRCMP(cmd, "DISCONNECT") == 0)
+ {
+ /* We assume the server knows that we can safely exit! */
+ if (sd >= 0)
+ sock_close(sd);
+ /* Disconnect before exiting, Motif hangs in a Select error
+ * message otherwise. */
+ netbeans_disconnect();
+ getout(0);
+ /* NOTREACHED */
+ }
+
+ if (STRCMP(cmd, "DETACH") == 0)
+ {
+ /* The IDE is breaking the connection. */
+ if (sd >= 0)
+ sock_close(sd);
+ netbeans_disconnect();
+ return;
+ }
+
+ bufno = strtol((char *)cmd, (char **)&verb, 10);
+
+ if (*verb != ':')
+ {
+ EMSG2("E627: missing colon: %s", cmd);
+ return;
+ }
+ ++verb; /* skip colon */
+
+ for (q = verb; *q; q++)
+ {
+ if (*q == '!')
+ {
+ *q++ = NUL;
+ isfunc = 0;
+ break;
+ }
+ else if (*q == '/')
+ {
+ *q++ = NUL;
+ isfunc = 1;
+ break;
+ }
+ }
+
+ if (isfunc < 0)
+ {
+ EMSG2("E628: missing ! or / in: %s", cmd);
+ return;
+ }
+
+ cmdno = strtol((char *)q, (char **)&q, 10);
+
+ q = skipwhite(q);
+
+ if (nb_do_cmd(bufno, verb, isfunc, cmdno, q) == FAIL)
+ {
+ nbdebug(("nb_parse_cmd: Command error for \"%s\"\n", cmd));
+ EMSG("E629: bad return from nb_do_cmd");
+ }
+}
+
+struct nbbuf_struct
+{
+ buf_T *bufp;
+ unsigned int fireChanges:1;
+ unsigned int initDone:1;
+ unsigned int modified:1;
+ char *displayname;
+ char_u *partial_line;
+ int *signmap;
+ short_u signmaplen;
+ short_u signmapused;
+};
+
+typedef struct nbbuf_struct nbbuf_T;
+
+static nbbuf_T *buf_list = 0;
+int buf_list_size = 0; /* size of buf_list */
+int buf_list_used = 0; /* nr of entries in buf_list actually in use */
+
+static char **globalsignmap;
+static int globalsignmaplen;
+static int globalsignmapused;
+
+static int mapsigntype __ARGS((nbbuf_T *, int localsigntype));
+static void addsigntype __ARGS((nbbuf_T *, int localsigntype, char_u *typeName,
+ char_u *tooltip, char_u *glyphfile,
+ int usefg, int fg, int usebg, int bg));
+
+static int curPCtype = -1;
+
+/*
+ * Get the Netbeans buffer number for the specified buffer.
+ */
+ static int
+nb_getbufno(buf_T *bufp)
+{
+ int i;
+
+ for (i = 0; i < buf_list_used; i++)
+ if (buf_list[i].bufp == bufp)
+ return i;
+ return -1;
+}
+
+/*
+ * Is this a NetBeans-owned buffer?
+ */
+ int
+isNetbeansBuffer(buf_T *bufp)
+{
+ return bufp->b_netbeans_file;
+}
+
+/*
+ * NetBeans and Vim have different undo models. In Vim, the file isn't
+ * changed if changes are undone via the undo command. In NetBeans, once
+ * a change has been made the file is marked as modified until saved. It
+ * doesn't matter if the change was undone.
+ *
+ * So this function is for the corner case where Vim thinks a buffer is
+ * unmodified but NetBeans thinks it IS modified.
+ */
+ int
+isNetbeansModified(buf_T *bufp)
+{
+ int bufno = nb_getbufno(bufp);
+
+ if (bufno > 0)
+ return buf_list[bufno].modified;
+ else
+ return FALSE;
+}
+
+/*
+ * Given a Netbeans buffer number, return the netbeans buffer.
+ * Returns NULL for 0 or a negative number. A 0 bufno means a
+ * non-buffer related command has been sent.
+ */
+ static nbbuf_T *
+nb_get_buf(int bufno)
+{
+ /* find or create a buffer with the given number */
+ int incr;
+
+ if (bufno <= 0)
+ return NULL;
+
+ if (!buf_list)
+ {
+ /* initialize */
+ buf_list = (nbbuf_T *)alloc_clear(100 * sizeof(nbbuf_T));
+ buf_list_size = 100;
+ }
+ if (bufno >= buf_list_used) /* new */
+ {
+ if (bufno >= buf_list_size) /* grow list */
+ {
+ incr = bufno - buf_list_size + 90;
+ buf_list_size += incr;
+ buf_list = (nbbuf_T *)vim_realloc(
+ buf_list, buf_list_size * sizeof(nbbuf_T));
+ memset(buf_list + buf_list_size - incr, 0, incr * sizeof(nbbuf_T));
+ }
+
+ while (buf_list_used <= bufno)
+ {
+ /* Default is to fire text changes. */
+ buf_list[buf_list_used].fireChanges = 1;
+ ++buf_list_used;
+ }
+ }
+
+ return buf_list + bufno;
+}
+
+/*
+ * Return the number of buffers that are modified.
+ */
+ static int
+count_changed_buffers(void)
+{
+ buf_T *bufp;
+ int n;
+
+ n = 0;
+ for (bufp = firstbuf; bufp != NULL; bufp = bufp->b_next)
+ if (bufp->b_changed)
+ ++n;
+ return n;
+}
+
+/*
+ * End the netbeans session.
+ */
+ void
+netbeans_end(void)
+{
+ int i;
+ static char buf[128];
+
+ if (!haveConnection)
+ return;
+
+ for (i = 0; i < buf_list_used; i++)
+ {
+ if (!buf_list[i].bufp)
+ continue;
+ if (netbeansForcedQuit)
+ {
+ /* mark as unmodified so NetBeans won't put up dialog on "killed" */
+ sprintf(buf, "%d:unmodified=%d\n", i, cmdno);
+ nbdebug(("EVT: %s", buf));
+ nb_send(buf, "netbeans_end");
+ }
+ sprintf(buf, "%d:killed=%d\n", i, cmdno);
+ nbdebug(("EVT: %s", buf));
+/* nb_send(buf, "netbeans_end"); avoid "write failed" messages */
+ if (sd >= 0)
+ sock_write(sd, buf, STRLEN(buf)); /* ignore errors */
+ }
+
+ /* Give NetBeans a chance to write some clean-up cmds to the socket before
+ * we close the connection. Other clients may set the delay to zero. */
+ if (exit_delay > 0)
+ sleep(exit_delay);
+}
+
+/*
+ * Send a message to netbeans.
+ */
+ static void
+nb_send(char *buf, char *fun)
+{
+ /* Avoid giving pages full of error messages when the other side has
+ * exited, only mention the first error until the connection works again. */
+ static int did_error = FALSE;
+
+ if (sd < 0)
+ {
+ if (!did_error)
+ EMSG2("E630: %s(): write while not connected", fun);
+ did_error = TRUE;
+ }
+ else if (sock_write(sd, buf, STRLEN(buf)) != (int)STRLEN(buf))
+ {
+ if (!did_error)
+ EMSG2("E631: %s(): write failed", fun);
+ did_error = TRUE;
+ }
+ else
+ did_error = FALSE;
+}
+
+/*
+ * Some input received from netbeans requires a response. This function
+ * handles a response with no information (except the command number).
+ */
+ static void
+nb_reply_nil(int cmdno)
+{
+ char reply[32];
+
+ if (!haveConnection)
+ return;
+
+ sprintf(reply, "%d\n", cmdno);
+
+ nbdebug((" REPLY: %s", reply));
+
+ nb_send(reply, "nb_reply_nil");
+}
+
+
+/*
+ * Send a response with text.
+ * "result" must have been quoted already (using nb_quote()).
+ */
+ static void
+nb_reply_text(int cmdno, char_u *result)
+{
+ char_u *reply;
+
+ if (!haveConnection)
+ return;
+
+ reply = alloc(STRLEN(result) + 32);
+ sprintf((char *)reply, "%d %s\n", cmdno, (char *)result);
+
+ nbdebug((" REPLY: %s", reply));
+ nb_send((char *)reply, "nb_reply_text");
+
+ vim_free(reply);
+}
+
+
+/*
+ * Send a response with a number result code.
+ */
+ static void
+nb_reply_nr(int cmdno, long result)
+{
+ char reply[32];
+
+ if (!haveConnection)
+ return;
+
+ sprintf(reply, "%d %ld\n", cmdno, result);
+
+ nbdebug(("REPLY: %s", reply));
+
+ nb_send(reply, "nb_reply_nr");
+}
+
+
+/*
+ * Encode newline, ret, backslash, double quote for transmission to NetBeans.
+ */
+ static char_u *
+nb_quote(char_u *txt)
+{
+ char_u *buf = alloc(2 * STRLEN(txt) + 1);
+ char_u *p = txt;
+ char_u *q = buf;
+
+ if (buf == NULL)
+ return NULL;
+ for (; *p; p++)
+ {
+ switch (*p)
+ {
+ case '\"':
+ case '\\':
+ *q++ = '\\'; *q++ = *p; break;
+ /* case '\t': */
+ /* *q++ = '\\'; *q++ = 't'; break; */
+ case '\n':
+ *q++ = '\\'; *q++ = 'n'; break;
+ case '\r':
+ *q++ = '\\'; *q++ = 'r'; break;
+ default:
+ *q++ = *p;
+ break;
+ }
+ }
+ *q++ = '\0';
+
+ return buf;
+}
+
+
+/*
+ * Remove top level double quotes; convert backslashed chars.
+ * Returns an allocated string (NULL for failure).
+ * If "endp" is not NULL it is set to the character after the terminating
+ * quote.
+ */
+ static char *
+nb_unquote(char_u *p, char_u **endp)
+{
+ char *result = 0;
+ char *q;
+ int done = 0;
+
+ /* result is never longer than input */
+ result = (char *)alloc_clear(STRLEN(p) + 1);
+ if (result == NULL)
+ return NULL;
+
+ if (*p++ != '"')
+ {
+ nbdebug(("nb_unquote called with string that doesn't start with a quote!: %s\n",
+ p));
+ result[0] = NUL;
+ return result;
+ }
+
+ for (q = result; !done && *p != NUL;)
+ {
+ switch (*p)
+ {
+ case '"':
+ /*
+ * Unbackslashed dquote marks the end, if first char was dquote.
+ */
+ done = 1;
+ break;
+
+ case '\\':
+ ++p;
+ switch (*p)
+ {
+ case '\\': *q++ = '\\'; break;
+ case 'n': *q++ = '\n'; break;
+ case 't': *q++ = '\t'; break;
+ case 'r': *q++ = '\r'; break;
+ case '"': *q++ = '"'; break;
+ case NUL: --p; break;
+ /* default: skip over illegal chars */
+ }
+ ++p;
+ break;
+
+ default:
+ *q++ = *p++;
+ }
+ }
+
+ if (endp != NULL)
+ *endp = p;
+
+ return result;
+}
+
+#define SKIP_STOP 2
+#define streq(a,b) (strcmp(a,b) == 0)
+static int needupdate = 0;
+static int inAtomic = 0;
+
+/*
+ * Do the actual processing of a single netbeans command or function.
+ * The differance between a command and function is that a function
+ * gets a response (its required) but a command does not.
+ * For arguments see comment for nb_parse_cmd().
+ */
+ static int
+nb_do_cmd(
+ int bufno,
+ char_u *cmd,
+ int func,
+ int cmdno,
+ char_u *args) /* points to space before arguments or NUL */
+{
+ int doupdate = 0;
+ long off = 0;
+ nbbuf_T *buf = nb_get_buf(bufno);
+ static int skip = 0;
+ int retval = OK;
+
+ nbdebug(("%s %d: (%d) %s %s\n", (func) ? "FUN" : "CMD", cmdno, bufno, cmd,
+ STRCMP(cmd, "insert") == 0 ? "<text>" : (char *)args));
+
+ if (func)
+ {
+/* =====================================================================*/
+ if (streq((char *)cmd, "getModified"))
+ {
+ if (buf == NULL || buf->bufp == NULL)
+ /* Return the number of buffers that are modified. */
+ nb_reply_nr(cmdno, (long)count_changed_buffers());
+ else
+ /* Return whether the buffer is modified. */
+ nb_reply_nr(cmdno, (long)(buf->bufp->b_changed
+ || isNetbeansModified(buf->bufp)));
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "saveAndExit"))
+ {
+ /* Note: this will exit Vim if successful. */
+ coloncmd(":confirm qall");
+
+ /* We didn't exit: return the number of changed buffers. */
+ nb_reply_nr(cmdno, (long)count_changed_buffers());
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "getCursor"))
+ {
+ char_u text[200];
+
+ /* Note: nb_getbufno() may return -1. This indicates the IDE
+ * didn't assign a number to the current buffer in response to a
+ * fileOpened event. */
+ sprintf((char *)text, "%d %ld %d %ld",
+ nb_getbufno(curbuf),
+ (long)curwin->w_cursor.lnum,
+ (int)curwin->w_cursor.col,
+ pos2off(curbuf, &curwin->w_cursor));
+ nb_reply_text(cmdno, text);
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "getLength"))
+ {
+ long len = 0;
+
+ if (buf == NULL || buf->bufp == NULL)
+ {
+ nbdebug((" null bufp in getLength"));
+ EMSG("E632: null bufp in getLength");
+ retval = FAIL;
+ }
+ else
+ {
+ len = get_buf_size(buf->bufp);
+ /* adjust for a partial last line */
+ if (buf->partial_line != NULL)
+ {
+ nbdebug((" Adjusting buffer len for partial last line: %d\n",
+ STRLEN(buf->partial_line)));
+ len += STRLEN(buf->partial_line);
+ }
+ }
+ nb_reply_nr(cmdno, len);
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "getText"))
+ {
+ long len;
+ linenr_T nlines;
+ char_u *text = NULL;
+ linenr_T lno = 1;
+ char_u *p;
+ char_u *line;
+
+ if (buf == NULL || buf->bufp == NULL)
+ {
+ nbdebug((" null bufp in getText"));
+ EMSG("E633: null bufp in getText");
+ retval = FAIL;
+ }
+ else
+ {
+ len = get_buf_size(buf->bufp);
+ nlines = buf->bufp->b_ml.ml_line_count;
+ text = alloc((unsigned)((len > 0)
+ ? ((len + nlines) * 2) : 4));
+ if (text == NULL)
+ {
+ nbdebug((" nb_do_cmd: getText has null text field\n"));
+ retval = FAIL;
+ }
+ else
+ {
+ p = text;
+ *p++ = '\"';
+ for (; lno <= nlines ; lno++)
+ {
+ line = nb_quote(ml_get_buf(buf->bufp, lno, FALSE));
+ if (line != NULL)
+ {
+ STRCPY(p, line);
+ p += STRLEN(line);
+ *p++ = '\\';
+ *p++ = 'n';
+ }
+ vim_free(line);
+ }
+ *p++ = '\"';
+ *p = '\0';
+ }
+ }
+ if (text == NULL)
+ nb_reply_text(cmdno, (char_u *)"");
+ else
+ {
+ nb_reply_text(cmdno, text);
+ vim_free(text);
+ }
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "remove"))
+ {
+ long count;
+ pos_T first, last;
+ pos_T *pos;
+ int oldFire = netbeansFireChanges;
+ int oldSuppress = netbeansSuppressNoLines;
+ int wasChanged;
+
+ if (skip >= SKIP_STOP)
+ {
+ nbdebug((" Skipping %s command\n", (char *) cmd));
+ nb_reply_nil(cmdno);
+ return OK;
+ }
+
+ if (buf == NULL || buf->bufp == NULL)
+ {
+ nbdebug((" null bufp in remove"));
+ EMSG("E634: null bufp in remove");
+ retval = FAIL;
+ }
+ else
+ {
+ netbeansFireChanges = FALSE;
+ netbeansSuppressNoLines = TRUE;
+
+ if (curbuf != buf->bufp)
+ set_curbuf(buf->bufp, DOBUF_GOTO);
+ wasChanged = buf->bufp->b_changed;
+ off = strtol((char *)args, (char **)&args, 10);
+ count = strtol((char *)args, (char **)&args, 10);
+ /* delete "count" chars, starting at "off" */
+ pos = off2pos(buf->bufp, off);
+ if (!pos)
+ {
+ nb_reply_text(cmdno, (char_u *)"!bad position");
+ netbeansFireChanges = oldFire;
+ netbeansSuppressNoLines = oldSuppress;
+ return FAIL;
+ }
+ first = *pos;
+ nbdebug((" FIRST POS: line %d, col %d\n", first.lnum, first.col));
+ pos = off2pos(buf->bufp, off+count-1);
+ if (!pos)
+ {
+ nb_reply_text(cmdno, (char_u *)"!bad count");
+ netbeansFireChanges = oldFire;
+ netbeansSuppressNoLines = oldSuppress;
+ return FAIL;
+ }
+ last = *pos;
+ nbdebug((" LAST POS: line %d, col %d\n", last.lnum, last.col));
+ curwin->w_cursor = first;
+ doupdate = 1;
+
+ /* keep part of first line */
+ if (first.lnum == last.lnum && first.col != last.col)
+ {
+ /* deletion is within one line */
+ char_u *p = ml_get(first.lnum);
+ mch_memmove(p + first.col, p + last.col + 1, STRLEN(p + last.col) + 1);
+ nbdebug((" NEW LINE %d: %s\n", first.lnum, p));
+ ml_replace(first.lnum, p, TRUE);
+ }
+
+ if (first.lnum < last.lnum)
+ {
+ int i;
+
+ /* delete signs from the lines being deleted */
+ for (i = first.lnum; i <= last.lnum; i++)
+ {
+ int id = buf_findsign_id(buf->bufp, (linenr_T)i);
+ if (id > 0)
+ {
+ nbdebug((" Deleting sign %d on line %d\n", id, i));
+ buf_delsign(buf->bufp, id);
+ }
+ else
+ nbdebug((" No sign on line %d\n", i));
+ }
+
+ /* delete whole lines */
+ nbdebug((" Deleting lines %d through %d\n", first.lnum, last.lnum));
+ del_lines(last.lnum - first.lnum + 1, FALSE);
+ }
+ buf->bufp->b_changed = wasChanged; /* logically unchanged */
+ netbeansFireChanges = oldFire;
+ netbeansSuppressNoLines = oldSuppress;
+
+ u_blockfree(buf->bufp);
+ u_clearall(buf->bufp);
+ }
+ nb_reply_nil(cmdno);
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "insert"))
+ {
+ pos_T *pos;
+ pos_T mypos;
+ char_u *to_free;
+ char_u *nl;
+ int lnum;
+ pos_T old_w_cursor;
+ int old_b_changed;
+
+ if (skip >= SKIP_STOP)
+ {
+ nbdebug((" Skipping %s command\n", (char *) cmd));
+ nb_reply_nil(cmdno);
+ return OK;
+ }
+
+ /* get offset */
+ off = strtol((char *)args, (char **)&args, 10);
+
+ /* get text to be inserted */
+ args = skipwhite(args);
+ args = to_free = (char_u *)nb_unquote(args, NULL);
+
+ if (buf == NULL || buf->bufp == NULL)
+ {
+ nbdebug((" null bufp in insert"));
+ EMSG("E635: null bufp in insert");
+ retval = FAIL;
+ }
+ else if (args != NULL)
+ {
+ /* We need to detect EOL style
+ * because addAnno passes char-offset
+ */
+ int ff_detected = EOL_UNKNOWN;
+ int buf_was_empty = (buf->bufp->b_ml.ml_flags & ML_EMPTY);
+
+ oldFire = netbeansFireChanges;
+ netbeansFireChanges = 0;
+
+ if (curbuf != buf->bufp)
+ set_curbuf(buf->bufp, DOBUF_GOTO);
+ old_b_changed = buf->bufp->b_changed;
+
+ if (buf->partial_line != NULL)
+ {
+ nbdebug((" Combining with partial line\n"));
+ off -= STRLEN(buf->partial_line);
+ pos = off2pos(buf->bufp, off);
+ if (pos && pos->col != 0)
+ off -= pos->col; /* want start of line */
+ buf->partial_line = vim_realloc(buf->partial_line,
+ STRLEN(buf->partial_line) + STRLEN(args) + 1);
+ STRCAT(buf->partial_line, args);
+ vim_free(to_free);
+ args = buf->partial_line;
+ buf->partial_line = NULL;
+ to_free = args;
+ }
+ pos = off2pos(buf->bufp, off);
+ if (pos)
+ {
+ if (pos->lnum == 0)
+ pos->lnum = 1;
+ nbdebug((" POSITION: line = %d, col = %d\n",
+ pos->lnum, pos->col));
+ }
+ else
+ {
+ /* if the given position is not found, assume we want
+ * the end of the file. See setLocAndSize HACK. */
+ pos = &mypos;
+ pos->col = 0;
+#ifdef FEAT_VIRTUALEDIT
+ pos->coladd = 0;
+#endif
+ pos->lnum = buf->bufp->b_ml.ml_line_count;
+ nbdebug((" POSITION: line = %d (EOF)\n", pos->lnum));
+ }
+ lnum = pos->lnum;
+ old_w_cursor = curwin->w_cursor;
+ curwin->w_cursor = *pos;
+
+ doupdate = 1;
+ while (*args)
+ {
+ nl = (char_u *)strchr((char *)args, '\n');
+ if (!nl)
+ {
+ nbdebug((" PARTIAL[%d]: %s\n", lnum, args));
+ break;
+ }
+ /* EOL detecting.
+ * Not sure how to deal with '\n' on Mac
+ * it will fail already in nl = ... above
+ */
+ if (buf_was_empty && /* There is need to detect EOLs */
+ /* AND: string is empty */
+ (args == nl
+ /* OR hasn't '\r' at the end */
+ || *(nl - 1) != '\r'))
+ ff_detected = EOL_UNIX;
+
+ *nl = '\0';
+ nbdebug((" INSERT[%d]: %s\n", lnum, args));
+ ml_append((linenr_T)(lnum++ - 1), args,
+ STRLEN(args) + 1, FALSE);
+ args = nl + 1;
+ }
+
+ appended_lines_mark(pos->lnum - 1, lnum - pos->lnum);
+
+ /* We can change initial ff without consequences
+ * Isn't it a kind of hacking?
+ */
+ if (buf_was_empty)
+ {
+ if (ff_detected == EOL_UNKNOWN)
+ ff_detected = EOL_DOS;
+ set_fileformat(ff_detected, OPT_LOCAL);
+ buf->bufp->b_start_ffc = *buf->bufp->b_p_ff;
+ }
+
+ if (*args)
+ {
+ /*
+ * Incomplete line, squirrel away and wait for next insert.
+ */
+ nbdebug((" PARTIAL-SAVED: %s\n", args));
+ buf->partial_line = vim_realloc(buf->partial_line,
+ STRLEN(args) + 1);
+ STRCPY(buf->partial_line, args);
+ }
+ curwin->w_cursor = old_w_cursor;
+
+ /*
+ * XXX - GRP - Is the next line right? If I've inserted
+ * text the buffer has been updated but not written. Will
+ * netbeans guarantee to write it? Even if I do a :q! ?
+ */
+ buf->bufp->b_changed = old_b_changed; /* logically unchanged */
+ netbeansFireChanges = oldFire;
+
+ u_blockfree(buf->bufp);
+ u_clearall(buf->bufp);
+ }
+ vim_free(to_free);
+ nb_reply_nil(cmdno); /* or !error */
+ }
+ else
+ {
+ nbdebug(("UNIMPLEMENTED FUNCTION: %s\n", cmd));
+ nb_reply_nil(cmdno);
+ retval = FAIL;
+ }
+ }
+ else /* Not a function; no reply required. */
+ {
+/* =====================================================================*/
+ if (streq((char *)cmd, "create"))
+ {
+ /* Create a buffer without a name. */
+ if (buf == NULL)
+ {
+ EMSG("E636: null buf in create");
+ return FAIL;
+ }
+ vim_free(buf->displayname);
+ buf->displayname = NULL;
+ nbdebug((" CREATE %d\n", bufno));
+
+ netbeansReadFile = 0; /* don't try to open disk file */
+ do_ecmd(0, NULL, 0, 0, ECMD_ONE, ECMD_HIDE + ECMD_OLDBUF);
+ netbeansReadFile = 1;
+ buf->bufp = curbuf;
+ maketitle();
+ gui_update_menus(0);
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "startDocumentListen"))
+ {
+ if (buf == NULL)
+ {
+ EMSG("E637: null buf in startDocumentListen");
+ return FAIL;
+ }
+ buf->fireChanges = 1;
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "stopDocumentListen"))
+ {
+ if (buf == NULL)
+ {
+ EMSG("E638: null buf in stopDocumentListen");
+ return FAIL;
+ }
+ buf->fireChanges = 0;
+ if (buf->bufp != NULL
+ && buf->bufp->b_was_netbeans_file
+ && !buf->bufp->b_netbeans_file)
+ EMSGN(_("E658: NetBeans connection lost for buffer %ld"),
+ buf->bufp->b_fnum);
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "setTitle"))
+ {
+ if (buf == NULL)
+ {
+ EMSG("E639: null buf in setTitle");
+ return FAIL;
+ }
+ vim_free(buf->displayname);
+ buf->displayname = nb_unquote(args, NULL);
+ nbdebug((" SETTITLE %d %s\n", bufno, buf->displayname));
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "initDone"))
+ {
+ if (buf == NULL || buf->bufp == NULL)
+ {
+ EMSG("E640: null buf in initDone");
+ return FAIL;
+ }
+ doupdate = 1;
+ buf->initDone = 1;
+ if (curbuf != buf->bufp)
+ set_curbuf(buf->bufp, DOBUF_GOTO);
+#if defined(FEAT_AUTOCMD)
+ apply_autocmds(EVENT_BUFREADPOST, 0, 0, FALSE, buf->bufp);
+#endif
+
+ /* handle any postponed key commands */
+ handle_key_queue();
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "setBufferNumber")
+ || streq((char *)cmd, "putBufferNumber"))
+ {
+ char_u *to_free;
+ buf_T *bufp;
+
+ if (buf == NULL)
+ {
+ EMSG("E641: null buf in setBufferNumber");
+ return FAIL;
+ }
+ to_free = (char_u *)nb_unquote(args, NULL);
+ if (to_free == NULL)
+ return FAIL;
+ bufp = buflist_findname(to_free);
+ vim_free(to_free);
+ if (bufp == NULL)
+ {
+ EMSG2("E642: File %s not found in setBufferNumber", args);
+ return FAIL;
+ }
+ buf->bufp = bufp;
+
+ /* "setBufferNumber" has the side effect of jumping to the buffer
+ * (don't know why!). Don't do that for "putBufferNumber". */
+ if (*cmd != 'p')
+ coloncmd(":buffer %d", bufp->b_fnum);
+ else
+ {
+ buf->initDone = 1;
+
+ /* handle any postponed key commands */
+ handle_key_queue();
+ }
+
+#if 0 /* never used */
+ buf->internalname = (char *)alloc_clear(8);
+ sprintf(buf->internalname, "<%d>", bufno);
+ buf->netbeansOwns = 0;
+#endif
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "setFullName"))
+ {
+ if (buf == NULL)
+ {
+ EMSG("E643: null buf in setFullName");
+ return FAIL;
+ }
+ vim_free(buf->displayname);
+ buf->displayname = nb_unquote(args, NULL);
+ nbdebug((" SETFULLNAME %d %s\n", bufno, buf->displayname));
+
+ netbeansReadFile = 0; /* don't try to open disk file */
+ do_ecmd(0, (char_u *)buf->displayname, 0, 0, ECMD_ONE,
+ ECMD_HIDE + ECMD_OLDBUF);
+ netbeansReadFile = 1;
+ buf->bufp = curbuf;
+ maketitle();
+ gui_update_menus(0);
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "editFile"))
+ {
+ if (buf == NULL)
+ {
+ EMSG("E644: null buf in editFile");
+ return FAIL;
+ }
+ /* Edit a file: like create + setFullName + read the file. */
+ vim_free(buf->displayname);
+ buf->displayname = nb_unquote(args, NULL);
+ nbdebug((" EDITFILE %d %s\n", bufno, buf->displayname));
+ do_ecmd(0, (char_u *)buf->displayname, NULL, NULL, ECMD_ONE,
+ ECMD_HIDE + ECMD_OLDBUF);
+ buf->bufp = curbuf;
+ buf->initDone = 1;
+ doupdate = 1;
+#if defined(FEAT_TITLE)
+ maketitle();
+#endif
+ gui_update_menus(0);
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "setVisible"))
+ {
+ if (buf == NULL || buf->bufp == NULL)
+ {
+/* EMSG("E645: null bufp in setVisible"); */
+ return FAIL;
+ }
+ if (streq((char *)args, "T"))
+ {
+ exarg_T exarg;
+ exarg.cmd = (char_u *)"goto";
+ exarg.forceit = FALSE;
+ goto_buffer(&exarg, DOBUF_FIRST, FORWARD, buf->bufp->b_fnum);
+ doupdate = 1;
+
+ /* Side effect!!!. */
+ if (!gui.starting)
+ gui_mch_set_foreground();
+ }
+ else
+ {
+ /* bury the buffer - not yet */
+ }
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "raise"))
+ {
+ /* Bring gvim to the foreground. */
+ if (!gui.starting)
+ gui_mch_set_foreground();
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "setModified"))
+ {
+ if (buf == NULL || buf->bufp == NULL)
+ {
+/* EMSG("E646: null bufp in setModified"); */
+ return FAIL;
+ }
+ if (streq((char *)args, "T"))
+ buf->bufp->b_changed = 1;
+ else
+ {
+ struct stat st;
+
+ /* Assume NetBeans stored the file. Reset the timestamp to
+ * avoid "file changed" warnings. */
+ if (buf->bufp->b_ffname != NULL
+ && mch_stat((char *)buf->bufp->b_ffname, &st) >= 0)
+ buf_store_time(buf->bufp, &st, buf->bufp->b_ffname);
+ buf->bufp->b_changed = 0;
+ }
+ buf->modified = buf->bufp->b_changed;
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "setMark"))
+ {
+ /* not yet */
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "showBalloon"))
+ {
+#if defined(FEAT_BEVAL)
+ static char *text = NULL;
+
+ /*
+ * Set up the Balloon Expression Evaluation area.
+ * Ignore 'ballooneval' here.
+ * The text pointer must remain valid for a while.
+ */
+ if (balloonEval != NULL)
+ {
+ vim_free(text);
+ text = nb_unquote(args, NULL);
+ if (text != NULL)
+ gui_mch_post_balloon(balloonEval, (char_u *)text);
+ }
+#endif
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "setDot"))
+ {
+ pos_T *pos;
+#ifdef NBDEBUG
+ char_u *s;
+#endif
+
+ if (buf == NULL || buf->bufp == NULL)
+ {
+ EMSG("E647: null bufp in setDot");
+ return FAIL;
+ }
+
+ if (curbuf != buf->bufp)
+ set_curbuf(buf->bufp, DOBUF_GOTO);
+#ifdef FEAT_VISUAL
+ /* Don't want Visual mode now. */
+ if (VIsual_active)
+ end_visual_mode();
+#endif
+#ifdef NBDEBUG
+ s = args;
+#endif
+ pos = get_off_or_lnum(buf->bufp, &args);
+ if (pos)
+ {
+ curwin->w_cursor = *pos;
+ check_cursor();
+#ifdef FEAT_FOLDING
+ foldOpenCursor();
+#endif
+ }
+ else
+ nbdebug((" BAD POSITION in setDot: %s\n", s));
+
+ /* gui_update_cursor(TRUE, FALSE); */
+ /* update_curbuf(NOT_VALID); */
+ update_topline(); /* scroll to show the line */
+ update_screen(VALID);
+ setcursor();
+ out_flush();
+ gui_update_cursor(TRUE, FALSE);
+ gui_mch_flush();
+ /* Quit a hit-return or more prompt. */
+ if (State == HITRETURN || State == ASKMORE)
+ {
+ add_to_input_buf((char_u *)"\003", 1);
+#ifdef FEAT_GUI_GTK
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+#endif
+ }
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "close"))
+ {
+#ifdef NBDEBUG
+ char *name = "<NONE>";
+#endif
+
+ if (buf == NULL)
+ {
+ EMSG("E648: null buf in close");
+ return FAIL;
+ }
+
+#ifdef NBDEBUG
+ if (buf->displayname != NULL)
+ name = buf->displayname;
+#endif
+/* if (buf->bufp == NULL) */
+/* EMSG("E649: null bufp in close"); */
+ nbdebug((" CLOSE %d: %s\n", bufno, name));
+ need_mouse_correct = TRUE;
+ if (buf->bufp != NULL)
+ do_buffer(DOBUF_WIPE, DOBUF_FIRST, FORWARD,
+ buf->bufp->b_fnum, TRUE);
+ doupdate = 1;
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "setStyle")) /* obsolete... */
+ {
+ nbdebug((" setStyle is obsolete!"));
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "setExitDelay"))
+ {
+ /* New in version 2.1. */
+ exit_delay = strtol((char *)args, (char **)&args, 10);
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "defineAnnoType"))
+ {
+#ifdef FEAT_SIGNS
+ int typeNum;
+ char_u *typeName;
+ char_u *tooltip;
+ char_u *p;
+ char_u *glyphFile;
+ int use_fg = 0;
+ int use_bg = 0;
+ int fg = -1;
+ int bg = -1;
+
+ if (buf == NULL)
+ {
+ EMSG("E650: null buf in defineAnnoType");
+ return FAIL;
+ }
+
+ typeNum = strtol((char *)args, (char **)&args, 10);
+ args = skipwhite(args);
+ typeName = (char_u *)nb_unquote(args, &args);
+ args = skipwhite(args + 1);
+ tooltip = (char_u *)nb_unquote(args, &args);
+ args = skipwhite(args + 1);
+
+ p = (char_u *)nb_unquote(args, &args);
+ glyphFile = vim_strsave_escaped(p, escape_chars);
+ vim_free(p);
+
+ args = skipwhite(args + 1);
+ if (STRNCMP(args, "none", 4) == 0)
+ args += 5;
+ else
+ {
+ use_fg = 1;
+ fg = strtol((char *)args, (char **)&args, 10);
+ }
+ if (STRNCMP(args, "none", 4) == 0)
+ args += 5;
+ else
+ {
+ use_bg = 1;
+ bg = strtol((char *)args, (char **)&args, 10);
+ }
+ if (typeName != NULL && tooltip != NULL && glyphFile != NULL)
+ addsigntype(buf, typeNum, typeName, tooltip, glyphFile,
+ use_fg, fg, use_bg, bg);
+ else
+ vim_free(typeName);
+
+ /* don't free typeName; it's used directly in addsigntype() */
+ vim_free(tooltip);
+ vim_free(glyphFile);
+
+#endif
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "addAnno"))
+ {
+#ifdef FEAT_SIGNS
+ int serNum;
+ int localTypeNum;
+ int typeNum;
+# ifdef NBDEBUG
+ int len;
+# endif
+ pos_T *pos;
+
+ if (buf == NULL || buf->bufp == NULL)
+ {
+ EMSG("E651: null bufp in addAnno");
+ return FAIL;
+ }
+
+ doupdate = 1;
+
+ serNum = strtol((char *)args, (char **)&args, 10);
+
+ /* Get the typenr specific for this buffer and convert it to
+ * the global typenumber, as used for the sign name. */
+ localTypeNum = strtol((char *)args, (char **)&args, 10);
+ typeNum = mapsigntype(buf, localTypeNum);
+
+ pos = get_off_or_lnum(buf->bufp, &args);
+
+# ifdef NBDEBUG
+ len =
+# endif
+ strtol((char *)args, (char **)&args, 10);
+# ifdef NBDEBUG
+ if (len != -1)
+ {
+ nbdebug((" partial line annotation -- Not Yet Implemented!"));
+ }
+# endif
+ if (serNum >= GUARDEDOFFSET)
+ {
+ nbdebug((" too many annotations! ignoring..."));
+ return FAIL;
+ }
+ if (pos)
+ {
+ coloncmd(":sign place %d line=%d name=%d buffer=%d",
+ serNum, pos->lnum, typeNum, buf->bufp->b_fnum);
+ if (typeNum == curPCtype)
+ coloncmd(":sign jump %d buffer=%d", serNum,
+ buf->bufp->b_fnum);
+ }
+ /* XXX only redraw what changed. */
+ redraw_later(CLEAR);
+#endif
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "removeAnno"))
+ {
+#ifdef FEAT_SIGNS
+ int serNum;
+
+ if (buf == NULL || buf->bufp == NULL)
+ {
+ nbdebug((" null bufp in removeAnno"));
+ return FAIL;
+ }
+ doupdate = 1;
+ serNum = strtol((char *)args, (char **)&args, 10);
+ coloncmd(":sign unplace %d buffer=%d",
+ serNum, buf->bufp->b_fnum);
+ redraw_buf_later(buf->bufp, NOT_VALID);
+#endif
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "moveAnnoToFront"))
+ {
+#ifdef FEAT_SIGNS
+ nbdebug((" moveAnnoToFront: Not Yet Implemented!"));
+#endif
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "guard") || streq((char *)cmd, "unguard"))
+ {
+ int len;
+ pos_T first;
+ pos_T last;
+ pos_T *pos;
+ int un = (cmd[0] == 'u');
+ static int guardId = GUARDEDOFFSET;
+
+ if (skip >= SKIP_STOP)
+ {
+ nbdebug((" Skipping %s command\n", (char *) cmd));
+ return OK;
+ }
+
+ nb_init_graphics();
+
+ if (buf == NULL || buf->bufp == NULL)
+ {
+ nbdebug((" null bufp in %s command", cmd));
+ return FAIL;
+ }
+ if (curbuf != buf->bufp)
+ set_curbuf(buf->bufp, DOBUF_GOTO);
+ off = strtol((char *)args, (char **)&args, 10);
+ len = strtol((char *)args, 0, 10);
+ pos = off2pos(buf->bufp, off);
+ doupdate = 1;
+ if (!pos)
+ nbdebug((" no such start pos in %s, %ld\n", cmd, off));
+ else
+ {
+ first = *pos;
+ pos = off2pos(buf->bufp, off + len - 1);
+ if (pos != NULL && pos->col == 0) {
+ /*
+ * In Java Swing the offset is a position between 2
+ * characters. If col == 0 then we really want the
+ * previous line as the end.
+ */
+ pos = off2pos(buf->bufp, off + len - 2);
+ }
+ if (!pos)
+ nbdebug((" no such end pos in %s, %ld\n",
+ cmd, off + len - 1));
+ else
+ {
+ long lnum;
+ last = *pos;
+ /* set highlight for region */
+ nbdebug((" %sGUARD %ld,%d to %ld,%d\n", (un) ? "UN" : "",
+ first.lnum, first.col,
+ last.lnum, last.col));
+#ifdef FEAT_SIGNS
+ for (lnum = first.lnum; lnum <= last.lnum; lnum++)
+ {
+ if (un)
+ {
+ /* never used */
+ }
+ else
+ {
+ if (buf_findsigntype_id(buf->bufp, lnum,
+ GUARDED) == 0)
+ {
+ coloncmd(
+ ":sign place %d line=%d name=%d buffer=%d",
+ guardId++, lnum, GUARDED,
+ buf->bufp->b_fnum);
+ }
+ }
+ }
+#endif
+ redraw_buf_later(buf->bufp, NOT_VALID);
+ }
+ }
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "startAtomic"))
+ {
+ inAtomic = 1;
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "endAtomic"))
+ {
+ inAtomic = 0;
+ if (needupdate)
+ {
+ doupdate = 1;
+ needupdate = 0;
+ }
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "save"))
+ {
+ if (buf == NULL || buf->bufp == NULL)
+ {
+ nbdebug((" null bufp in %s command", cmd));
+ return FAIL;
+ }
+
+ /* the following is taken from ex_cmds.c (do_wqall function) */
+ if (bufIsChanged(buf->bufp))
+ {
+ /* Only write if the buffer can be written. */
+ if (p_write
+ && !buf->bufp->b_p_ro
+ && buf->bufp->b_ffname != NULL
+#ifdef FEAT_QUICKFIX
+ && !bt_dontwrite(buf->bufp)
+#endif
+ )
+ {
+ buf_write_all(buf->bufp, FALSE);
+#ifdef FEAT_AUTOCMD
+ /* an autocommand may have deleted the buffer */
+ if (!buf_valid(buf->bufp))
+ buf->bufp = NULL;
+#endif
+ }
+ }
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "netbeansBuffer"))
+ {
+ if (buf == NULL || buf->bufp == NULL)
+ {
+ nbdebug((" null bufp in %s command", cmd));
+ return FAIL;
+ }
+ if (*args == 'T')
+ {
+ buf->bufp->b_netbeans_file = TRUE;
+ buf->bufp->b_was_netbeans_file = TRUE;
+ }
+ else
+ buf->bufp->b_netbeans_file = FALSE;
+/* =====================================================================*/
+ }
+ else if (streq((char *)cmd, "version"))
+ {
+ nbdebug((" Version = %s\n", (char *) args));
+ }
+ /*
+ * Unrecognized command is ignored.
+ */
+ }
+ if (inAtomic && doupdate)
+ {
+ needupdate = 1;
+ doupdate = 0;
+ }
+
+ if (buf != NULL && buf->initDone && doupdate)
+ {
+ update_screen(NOT_VALID);
+ setcursor();
+ out_flush();
+ gui_update_cursor(TRUE, FALSE);
+ gui_mch_flush();
+ /* Quit a hit-return or more prompt. */
+ if (State == HITRETURN || State == ASKMORE)
+ {
+ add_to_input_buf((char_u *)"\003", 1);
+#ifdef FEAT_GUI_GTK
+ if (gtk_main_level() > 0)
+ gtk_main_quit();
+#endif
+ }
+ }
+
+ return retval;
+}
+
+
+/*
+ * Process a vim colon command.
+ */
+ static void
+coloncmd(char *cmd, ...)
+{
+ char buf[1024];
+ va_list ap;
+
+ va_start(ap, cmd);
+ vsprintf(buf, cmd, ap);
+ va_end(ap);
+
+ nbdebug((" COLONCMD %s\n", buf));
+
+/* ALT_INPUT_LOCK_ON; */
+ do_cmdline((char_u *)buf, NULL, NULL, DOCMD_NOWAIT | DOCMD_KEYTYPED);
+/* ALT_INPUT_LOCK_OFF; */
+
+ setcursor(); /* restore the cursor position */
+ out_flush(); /* make sure output has been written */
+
+ gui_update_cursor(TRUE, FALSE);
+ gui_mch_flush();
+}
+
+
+/*
+ * Initialize highlights and signs for use by netbeans (mostly obsolete)
+ */
+ static void
+nb_init_graphics(void)
+{
+ static int did_init = FALSE;
+
+ if (!did_init)
+ {
+ coloncmd(":highlight NBGuarded guibg=Cyan guifg=Black");
+ coloncmd(":sign define %d linehl=NBGuarded", GUARDED);
+
+ did_init = TRUE;
+ }
+}
+
+/*
+ * Convert key to netbeans name.
+ */
+ static void
+netbeans_keyname(int key, char *buf)
+{
+ char *name = 0;
+ char namebuf[2];
+ int ctrl = 0;
+ int shift = 0;
+ int alt = 0;
+
+ if (mod_mask & MOD_MASK_CTRL)
+ ctrl = 1;
+ if (mod_mask & MOD_MASK_SHIFT)
+ shift = 1;
+ if (mod_mask & MOD_MASK_ALT)
+ alt = 1;
+
+
+ switch (key)
+ {
+ case K_F1: name = "F1"; break;
+ case K_S_F1: name = "F1"; shift = 1; break;
+ case K_F2: name = "F2"; break;
+ case K_S_F2: name = "F2"; shift = 1; break;
+ case K_F3: name = "F3"; break;
+ case K_S_F3: name = "F3"; shift = 1; break;
+ case K_F4: name = "F4"; break;
+ case K_S_F4: name = "F4"; shift = 1; break;
+ case K_F5: name = "F5"; break;
+ case K_S_F5: name = "F5"; shift = 1; break;
+ case K_F6: name = "F6"; break;
+ case K_S_F6: name = "F6"; shift = 1; break;
+ case K_F7: name = "F7"; break;
+ case K_S_F7: name = "F7"; shift = 1; break;
+ case K_F8: name = "F8"; break;
+ case K_S_F8: name = "F8"; shift = 1; break;
+ case K_F9: name = "F9"; break;
+ case K_S_F9: name = "F9"; shift = 1; break;
+ case K_F10: name = "F10"; break;
+ case K_S_F10: name = "F10"; shift = 1; break;
+ case K_F11: name = "F11"; break;
+ case K_S_F11: name = "F11"; shift = 1; break;
+ case K_F12: name = "F12"; break;
+ case K_S_F12: name = "F12"; shift = 1; break;
+ default:
+ if (key >= ' ' && key <= '~')
+ {
+ /* Allow ASCII characters. */
+ name = namebuf;
+ namebuf[0] = key;
+ namebuf[1] = NUL;
+ }
+ else
+ name = "X";
+ break;
+ }
+
+ buf[0] = '\0';
+ if (ctrl)
+ strcat(buf, "C");
+ if (shift)
+ strcat(buf, "S");
+ if (alt)
+ strcat(buf, "M"); /* META */
+ if (ctrl || shift || alt)
+ strcat(buf, "-");
+ strcat(buf, name);
+}
+
+#ifdef FEAT_BEVAL
+/*
+ * Function to be called for balloon evaluation. Grabs the text under the
+ * cursor and sends it to the debugger for evaluation. The debugger should
+ * respond with a showBalloon command when there is a useful result.
+ */
+/*ARGSUSED*/
+ static void
+netbeans_beval_cb(
+ BalloonEval *beval,
+ int state)
+{
+ char_u *filename;
+ char_u *text;
+ int line;
+ int col;
+ char buf[MAXPATHL * 2 + 25];
+ char_u *p;
+
+ /* Don't do anything when 'ballooneval' is off, messages scrolled the
+ * windows up or we have no connection. */
+ if (!p_beval || msg_scrolled > 0 || !haveConnection)
+ return;
+
+ if (gui_mch_get_beval_info(beval, &filename, &line, &text, &col) == OK)
+ {
+ /* Send debugger request. Only when the text is of reasonable
+ * length. */
+ if (text != NULL && text[0] != NUL && STRLEN(text) < MAXPATHL)
+ {
+ p = nb_quote(text);
+ if (p != NULL)
+ sprintf(buf, "0:balloonText=%d \"%s\"\n", cmdno, p);
+ vim_free(p);
+ nbdebug(("EVT: %s", buf));
+ nb_send(buf, "netbeans_beval_cb");
+ }
+ vim_free(text);
+ }
+}
+#endif
+
+/*
+ * Tell netbeans that the window was opened, ready for commands.
+ */
+ void
+netbeans_startup_done(void)
+{
+ char *cmd = "0:startupDone=0\n";
+
+ if (!haveConnection)
+ return;
+
+ nbdebug(("EVT: %s", cmd));
+ nb_send(cmd, "netbeans_startup_done");
+
+#ifdef FEAT_BEVAL
+# ifdef FEAT_GUI_MOTIF
+ if (gui.in_use)
+ {
+ /*
+ * Set up the Balloon Expression Evaluation area for Motif.
+ * GTK can do it earlier...
+ * Always create it but disable it when 'ballooneval' isn't set.
+ */
+ balloonEval = gui_mch_create_beval_area(textArea, NULL,
+ &netbeans_beval_cb, NULL);
+ if (!p_beval)
+ gui_mch_disable_beval_area(balloonEval);
+ }
+# else
+# if defined(FEAT_GUI_W32) && defined(FEAT_BEVAL)
+ balloonEval = gui_mch_create_beval_area(NULL, NULL,
+ &netbeans_beval_cb, NULL);
+ if (!p_beval)
+ gui_mch_disable_beval_area(balloonEval);
+# endif
+# endif
+#endif
+}
+
+#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_W32) || defined(PROTO)
+/*
+ * Tell netbeans that the window was moved or resized.
+ */
+ void
+netbeans_frame_moved(int new_x, int new_y)
+{
+ char buf[128];
+
+ if (!haveConnection)
+ return;
+
+ sprintf(buf, "0:geometry=%d %d %d %d %d\n",
+ cmdno, (int)Columns, (int)Rows, new_x, new_y);
+ nbdebug(("EVT: %s", buf));
+ nb_send(buf, "netbeans_frame_moved");
+}
+#endif
+
+/*
+ * Tell netbeans the user opened a file.
+ */
+ void
+netbeans_file_opened(char *filename)
+{
+ char buffer[2*MAXPATHL];
+ char_u *q;
+
+ if (!haveConnection)
+ return;
+
+ q = nb_quote((char_u *)filename);
+ if (q == NULL)
+ return;
+ sprintf(buffer, "0:fileOpened=%d \"%s\" %s %s\n",
+ 0,
+ (char *)q,
+ "T", /* open in NetBeans */
+ "F"); /* modified */
+
+ vim_free(q);
+ nbdebug(("EVT: %s", buffer));
+
+ nb_send(buffer, "netbeans_file_opened");
+ if (p_acd && vim_chdirfile((char_u *)filename) == OK)
+ shorten_fnames(TRUE);
+}
+
+/*
+ * Tell netbeans a file was closed.
+ */
+ void
+netbeans_file_closed(buf_T *bufp)
+{
+ int bufno = nb_getbufno(bufp);
+ nbbuf_T *nbbuf = nb_get_buf(bufno);
+ char buffer[2*MAXPATHL];
+
+ if (!haveConnection || bufno < 0)
+ return;
+
+ if (!netbeansCloseFile)
+ {
+ nbdebug(("ignoring file_closed for %s\n", bufp->b_ffname));
+ return;
+ }
+
+ nbdebug(("netbeans_file_closed() bufno = %d, file = %s, displayname = %s\n",
+ bufno, bufp->b_ffname,
+ (nbbuf != NULL) ? nbbuf->displayname : "<>"));
+
+ if (bufno <= 0)
+ return;
+
+ sprintf(buffer, "%d:killed=%d\n", bufno, cmdno);
+
+ nbdebug(("EVT: %s", buffer));
+
+ nb_send(buffer, "netbeans_file_closed");
+
+ if (nbbuf != NULL)
+ nbbuf->bufp = NULL;
+}
+
+/*
+ * Get a pointer to the Netbeans buffer for Vim buffer "bufp".
+ * Return NULL if there is no such buffer or changes are not to be reported.
+ * Otherwise store the buffer number in "*bufnop".
+ */
+ static nbbuf_T *
+nb_bufp2nbbuf_fire(buf_T *bufp, int *bufnop)
+{
+ int bufno;
+ nbbuf_T *nbbuf;
+
+ if (!haveConnection || !netbeansFireChanges)
+ return NULL; /* changes are not reported at all */
+
+ bufno = nb_getbufno(bufp);
+ if (bufno <= 0)
+ return NULL; /* file is not known to NetBeans */
+
+ nbbuf = nb_get_buf(bufno);
+ if (nbbuf != NULL && !nbbuf->fireChanges)
+ return NULL; /* changes in this buffer are not reported */
+
+ *bufnop = bufno;
+ return nbbuf;
+}
+
+/*
+ * Tell netbeans the user inserted some text.
+ */
+ void
+netbeans_inserted(
+ buf_T *bufp,
+ linenr_T linenr,
+ colnr_T col,
+ int oldlen,
+ char_u *txt,
+ int newlen)
+{
+ char_u *buf;
+ int bufno;
+ nbbuf_T *nbbuf;
+ pos_T pos;
+ long off;
+ char_u *p;
+ char_u *newtxt;
+
+ nbbuf = nb_bufp2nbbuf_fire(bufp, &bufno);
+ if (nbbuf == NULL)
+ return;
+
+ nbbuf->modified = 1;
+
+ pos.lnum = linenr;
+ pos.col = col;
+
+ off = pos2off(bufp, &pos);
+
+/* nbdebug(("linenr = %d, col = %d, off = %ld\n", linenr, col, off)); */
+
+ buf = alloc(128 + 2*newlen);
+
+ if (oldlen > 0)
+ {
+ /* some chars were replaced; send "remove" EVT */
+ sprintf((char *)buf, "%d:remove=%d %ld %d\n",
+ bufno, cmdno, off, oldlen);
+ nbdebug(("EVT: %s", buf));
+ nb_send((char *)buf, "netbeans_inserted");
+ }
+ else if (oldlen < 0)
+ {
+ /* can't happen? */
+ nbdebug(("unexpected: oldlen < 0 in netbeans_inserted"));
+ }
+
+ /* send the "insert" EVT */
+ newtxt = alloc(newlen + 1);
+ STRNCPY(newtxt, txt, newlen);
+ newtxt[newlen] = '\0';
+ p = nb_quote(newtxt);
+ if (p != NULL)
+ {
+ sprintf((char *)buf, "%d:insert=%d %ld \"%s\"\n", bufno, cmdno, off, p);
+ nbdebug(("EVT: %s", buf));
+ nb_send((char *)buf, "netbeans_inserted");
+ }
+ vim_free(p);
+ vim_free(newtxt);
+ vim_free(buf);
+}
+
+/*
+ * Tell netbeans some bytes have been removed.
+ */
+ void
+netbeans_removed(
+ buf_T *bufp,
+ linenr_T linenr,
+ colnr_T col,
+ long len)
+{
+ char_u buf[128];
+ int bufno;
+ nbbuf_T *nbbuf;
+ pos_T pos;
+ long off;
+
+ nbbuf = nb_bufp2nbbuf_fire(bufp, &bufno);
+ if (nbbuf == NULL)
+ return;
+
+ if (len < 0)
+ {
+ nbdebug(("Negative len %ld in netbeans_removed()!", len));
+ return;
+ }
+
+ nbbuf->modified = 1;
+
+ pos.lnum = linenr;
+ pos.col = col;
+
+ off = pos2off(bufp, &pos);
+
+ sprintf((char *)buf, "%d:remove=%d %ld %ld\n", bufno, cmdno, off, len);
+ nbdebug(("EVT: %s", buf));
+ nb_send((char *)buf, "netbeans_removed");
+}
+
+/*
+ * Send netbeans an unmodufied command.
+ */
+/*ARGSUSED*/
+ void
+netbeans_unmodified(buf_T *bufp)
+{
+#if 0
+ char_u buf[128];
+ int bufno;
+ nbbuf_T *nbbuf;
+
+ /* This has been disabled, because NetBeans considers a buffer modified
+ * even when all changes have been undone. */
+ nbbuf = nb_bufp2nbbuf_fire(bufp, &bufno);
+ if (nbbuf == NULL)
+ return;
+
+ nbbuf->modified = 0;
+
+ sprintf((char *)buf, "%d:unmodified=%d\n", bufno, cmdno);
+ nbdebug(("EVT: %s", buf));
+ nb_send((char *)buf, "netbeans_unmodified");
+#endif
+}
+
+/*
+ * Send a button release event back to netbeans. Its up to netbeans
+ * to decide what to do (if anything) with this event.
+ */
+ void
+netbeans_button_release(int button)
+{
+ char buf[128];
+ int bufno;
+
+ bufno = nb_getbufno(curbuf);
+
+ if (bufno >= 0 && curwin != NULL && curwin->w_buffer == curbuf)
+ {
+ int col = mouse_col - curwin->w_wincol - (curwin->w_p_nu ? 9 : 1);
+ long off = pos2off(curbuf, &curwin->w_cursor);
+
+ /* sync the cursor position */
+ sprintf(buf, "%d:newDotAndMark=%d %ld %ld\n", bufno, cmdno, off, off);
+ nbdebug(("EVT: %s", buf));
+ nb_send(buf, "netbeans_button_release[newDotAndMark]");
+
+ sprintf(buf, "%d:buttonRelease=%d %d %ld %d\n", bufno, cmdno,
+ button, (long)curwin->w_cursor.lnum, col);
+ nbdebug(("EVT: %s", buf));
+ nb_send(buf, "netbeans_button_release");
+ }
+}
+
+
+/*
+ * Send a keypress event back to netbeans. This usualy simulates some
+ * kind of function key press.
+ */
+ void
+netbeans_keycommand(int key)
+{
+ char buf[2*MAXPATHL];
+ int bufno;
+ char keyName[60];
+ long off;
+ char_u *q;
+
+ if (!haveConnection)
+ return;
+
+ /* convert key to netbeans name */
+ netbeans_keyname(key, keyName);
+
+ bufno = nb_getbufno(curbuf);
+
+ if (bufno == -1)
+ {
+ nbdebug(("got keycommand for non-NetBeans buffer, opening...\n"));
+ q = curbuf->b_ffname == NULL ? (char_u *)""
+ : nb_quote(curbuf->b_ffname);
+ if (q == NULL)
+ return;
+ sprintf(buf, "0:fileOpened=%d \"%s\" %s %s\n", 0,
+ q,
+ "T", /* open in NetBeans */
+ "F"); /* modified */
+ if (curbuf->b_ffname != NULL)
+ vim_free(q);
+ nbdebug(("EVT: %s", buf));
+ nb_send(buf, "netbeans_keycommand");
+
+ postpone_keycommand(key);
+ return;
+ }
+
+ /* sync the cursor position */
+ off = pos2off(curbuf, &curwin->w_cursor);
+ sprintf(buf, "%d:newDotAndMark=%d %ld %ld\n", bufno, cmdno, off, off);
+ nbdebug(("EVT: %s", buf));
+ nb_send(buf, "netbeans_keycommand");
+
+ /* To work on Win32 you must apply patch to ExtEditor module
+ * from ExtEdCaret.java.diff - make EVT_newDotAndMark handler
+ * more synchronous
+ */
+
+ /* now send keyCommand event */
+ sprintf(buf, "%d:keyCommand=%d \"%s\"\n", bufno, cmdno, keyName);
+ nbdebug(("EVT: %s", buf));
+ nb_send(buf, "netbeans_keycommand");
+
+ /* New: do both at once and include the lnum/col. */
+ sprintf(buf, "%d:keyAtPos=%d \"%s\" %ld %ld/%ld\n", bufno, cmdno, keyName,
+ off, (long)curwin->w_cursor.lnum, (long)curwin->w_cursor.col);
+ nbdebug(("EVT: %s", buf));
+ nb_send(buf, "netbeans_keycommand");
+}
+
+
+/*
+ * Send a save event to netbeans.
+ */
+ void
+netbeans_save_buffer(buf_T *bufp)
+{
+ char_u buf[64];
+ int bufno;
+ nbbuf_T *nbbuf;
+
+ nbbuf = nb_bufp2nbbuf_fire(bufp, &bufno);
+ if (nbbuf == NULL)
+ return;
+
+ nbbuf->modified = 0;
+
+ sprintf((char *)buf, "%d:save=%d\n", bufno, cmdno);
+ nbdebug(("EVT: %s", buf));
+ nb_send((char *)buf, "netbeans_save_buffer");
+}
+
+
+/*
+ * Send remove command to netbeans (this command has been turned off).
+ */
+ void
+netbeans_deleted_all_lines(buf_T *bufp)
+{
+ char_u buf[64];
+ int bufno;
+ nbbuf_T *nbbuf;
+
+ nbbuf = nb_bufp2nbbuf_fire(bufp, &bufno);
+ if (nbbuf == NULL)
+ return;
+
+ nbbuf->modified = 1;
+
+ sprintf((char *)buf, "%d:remove=%d 0 -1\n", bufno, cmdno);
+ nbdebug(("EVT(suppressed): %s", buf));
+/* nb_send(buf, "netbeans_deleted_all_lines"); */
+}
+
+
+/*
+ * See if the lines are guarded. The top and bot parameters are from
+ * u_savecommon(), these are the line above the change and the line below the
+ * change.
+ */
+ int
+netbeans_is_guarded(linenr_T top, linenr_T bot)
+{
+ signlist_T *p;
+ int lnum;
+
+ for (p = curbuf->b_signlist; p != NULL; p = p->next)
+ if (p->id >= GUARDEDOFFSET)
+ for (lnum = top + 1; lnum < bot; lnum++)
+ if (lnum == p->lnum)
+ return TRUE;
+
+ return FALSE;
+}
+
+#if defined(FEAT_GUI_MOTIF) || defined(PROTO)
+/*
+ * We have multiple signs to draw at the same location. Draw the
+ * multi-sign indicator instead. This is the Motif version.
+ */
+ void
+netbeans_draw_multisign_indicator(int row)
+{
+ int i;
+ int y;
+ int x;
+
+ x = 0;
+ y = row * gui.char_height + 2;
+
+ for (i = 0; i < gui.char_height - 3; i++)
+ XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+2, y++);
+
+ XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+0, y);
+ XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+2, y);
+ XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+4, y++);
+ XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+1, y);
+ XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+2, y);
+ XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+3, y++);
+ XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+2, y);
+}
+#endif /* FEAT_GUI_MOTIF */
+
+#ifdef FEAT_GUI_GTK
+/*
+ * We have multiple signs to draw at the same location. Draw the
+ * multi-sign indicator instead. This is the GTK/Gnome version.
+ */
+ void
+netbeans_draw_multisign_indicator(int row)
+{
+ int i;
+ int y;
+ int x;
+ GdkDrawable *drawable = gui.drawarea->window;
+
+ x = 0;
+ y = row * gui.char_height + 2;
+
+ for (i = 0; i < gui.char_height - 3; i++)
+ gdk_draw_point(drawable, gui.text_gc, x+2, y++);
+
+ gdk_draw_point(drawable, gui.text_gc, x+0, y);
+ gdk_draw_point(drawable, gui.text_gc, x+2, y);
+ gdk_draw_point(drawable, gui.text_gc, x+4, y++);
+ gdk_draw_point(drawable, gui.text_gc, x+1, y);
+ gdk_draw_point(drawable, gui.text_gc, x+2, y);
+ gdk_draw_point(drawable, gui.text_gc, x+3, y++);
+ gdk_draw_point(drawable, gui.text_gc, x+2, y);
+}
+#endif /* FEAT_GUI_GTK */
+
+/*
+ * If the mouse is clicked in the gutter of a line with multiple
+ * annotations, cycle through the set of signs.
+ */
+ void
+netbeans_gutter_click(linenr_T lnum)
+{
+ signlist_T *p;
+
+ for (p = curbuf->b_signlist; p != NULL; p = p->next)
+ {
+ if (p->lnum == lnum && p->next && p->next->lnum == lnum)
+ {
+ signlist_T *tail;
+
+ /* remove "p" from list, reinsert it at the tail of the sublist */
+ if (p->prev)
+ p->prev->next = p->next;
+ else
+ curbuf->b_signlist = p->next;
+ p->next->prev = p->prev;
+ /* now find end of sublist and insert p */
+ for (tail = p->next;
+ tail->next && tail->next->lnum == lnum
+ && tail->next->id < GUARDEDOFFSET;
+ tail = tail->next)
+ ;
+ /* tail now points to last entry with same lnum (except
+ * that "guarded" annotations are always last) */
+ p->next = tail->next;
+ if (tail->next)
+ tail->next->prev = p;
+ p->prev = tail;
+ tail->next = p;
+ update_debug_sign(curbuf, lnum);
+ break;
+ }
+ }
+}
+
+
+/*
+ * Add a sign of the reqested type at the requested location.
+ *
+ * Reverse engineering:
+ * Apparently an annotation is defined the first time it is used in a buffer.
+ * When the same annotation is used in two buffers, the second time we do not
+ * need to define a new sign name but reuse the existing one. But since the
+ * ID number used in the second buffer starts counting at one again, a mapping
+ * is made from the ID specifically for the buffer to the global sign name
+ * (which is a number).
+ *
+ * globalsignmap[] stores the signs that have been defined globally.
+ * buf->signmapused[] maps buffer-local annotation IDs to an index in
+ * globalsignmap[].
+ */
+/*ARGSUSED*/
+ static void
+addsigntype(
+ nbbuf_T *buf,
+ int typeNum,
+ char_u *typeName,
+ char_u *tooltip,
+ char_u *glyphFile,
+ int use_fg,
+ int fg,
+ int use_bg,
+ int bg)
+{
+ char fgbuf[32];
+ char bgbuf[32];
+ int i, j;
+
+ for (i = 0; i < globalsignmapused; i++)
+ if (STRCMP(typeName, globalsignmap[i]) == 0)
+ break;
+
+ if (i == globalsignmapused) /* not found; add it to global map */
+ {
+ nbdebug(("DEFINEANNOTYPE(%d,%s,%s,%s,%d,%d)\n",
+ typeNum, typeName, tooltip, glyphFile, fg, bg));
+ if (use_fg || use_bg)
+ {
+ sprintf(fgbuf, "guifg=#%06x", fg & 0xFFFFFF);
+ sprintf(bgbuf, "guibg=#%06x", bg & 0xFFFFFF);
+
+ coloncmd(":highlight NB_%s %s %s", typeName, (use_fg) ? fgbuf : "",
+ (use_bg) ? bgbuf : "");
+ if (*glyphFile == NUL)
+ /* no glyph, line highlighting only */
+ coloncmd(":sign define %d linehl=NB_%s", i + 1, typeName);
+ else if (vim_strsize(glyphFile) <= 2)
+ /* one- or two-character glyph name, use as text glyph with
+ * texthl */
+ coloncmd(":sign define %d text=%s texthl=NB_%s", i + 1,
+ glyphFile, typeName);
+ else
+ /* glyph, line highlighting */
+ coloncmd(":sign define %d icon=%s linehl=NB_%s", i + 1,
+ glyphFile, typeName);
+ }
+ else
+ /* glyph, no line highlighting */
+ coloncmd(":sign define %d icon=%s", i + 1, glyphFile);
+
+ if (STRCMP(typeName,"CurrentPC") == 0)
+ curPCtype = typeNum;
+
+ if (globalsignmapused == globalsignmaplen)
+ {
+ if (globalsignmaplen == 0) /* first allocation */
+ {
+ globalsignmaplen = 20;
+ globalsignmap = (char **)alloc_clear(globalsignmaplen*sizeof(char *));
+ }
+ else /* grow it */
+ {
+ int incr;
+ int oldlen = globalsignmaplen;
+
+ globalsignmaplen *= 2;
+ incr = globalsignmaplen - oldlen;
+ globalsignmap = (char **)vim_realloc(globalsignmap,
+ globalsignmaplen * sizeof(char *));
+ memset(globalsignmap + oldlen, 0, incr * sizeof(char *));
+ }
+ }
+
+ globalsignmap[i] = (char *)typeName;
+ globalsignmapused = i + 1;
+ }
+
+ /* check local map; should *not* be found! */
+ for (j = 0; j < buf->signmapused; j++)
+ if (buf->signmap[j] == i + 1)
+ return;
+
+ /* add to local map */
+ if (buf->signmapused == buf->signmaplen)
+ {
+ if (buf->signmaplen == 0) /* first allocation */
+ {
+ buf->signmaplen = 5;
+ buf->signmap = (int *)alloc_clear(buf->signmaplen * sizeof(int *));
+ }
+ else /* grow it */
+ {
+ int incr;
+ int oldlen = buf->signmaplen;
+ buf->signmaplen *= 2;
+ incr = buf->signmaplen - oldlen;
+ buf->signmap = (int *)vim_realloc(buf->signmap,
+ buf->signmaplen*sizeof(int *));
+ memset(buf->signmap + oldlen, 0, incr * sizeof(int *));
+ }
+ }
+
+ buf->signmap[buf->signmapused++] = i + 1;
+
+}
+
+
+/*
+ * See if we have the requested sign type in the buffer.
+ */
+ static int
+mapsigntype(nbbuf_T *buf, int localsigntype)
+{
+ if (--localsigntype >= 0 && localsigntype < buf->signmapused)
+ return buf->signmap[localsigntype];
+
+ return 0;
+}
+
+
+/*
+ * Compute length of buffer, don't print anything.
+ */
+ static long
+get_buf_size(buf_T *bufp)
+{
+ linenr_T lnum;
+ long char_count = 0;
+ int eol_size;
+ long last_check = 100000L;
+
+ if (bufp->b_ml.ml_flags & ML_EMPTY)
+ return 0;
+ else
+ {
+ if (get_fileformat(bufp) == EOL_DOS)
+ eol_size = 2;
+ else
+ eol_size = 1;
+ for (lnum = 1; lnum <= bufp->b_ml.ml_line_count; ++lnum)
+ {
+ char_count += STRLEN(ml_get(lnum)) + eol_size;
+ /* Check for a CTRL-C every 100000 characters */
+ if (char_count > last_check)
+ {
+ ui_breakcheck();
+ if (got_int)
+ return char_count;
+ last_check = char_count + 100000L;
+ }
+ }
+ /* Correction for when last line doesn't have an EOL. */
+ if (!bufp->b_p_eol && bufp->b_p_bin)
+ char_count -= eol_size;
+ }
+
+ return char_count;
+}
+
+/*
+ * Convert character offset to lnum,col
+ */
+ static pos_T *
+off2pos(buf_T *buf, long offset)
+{
+ linenr_T lnum;
+ static pos_T pos;
+
+ pos.lnum = 0;
+ pos.col = 0;
+#ifdef FEAT_VIRTUALEDIT
+ pos.coladd = 0;
+#endif
+
+ if (!(buf->b_ml.ml_flags & ML_EMPTY))
+ {
+ if ((lnum = ml_find_line_or_offset(buf, (linenr_T)0, &offset)) < 0)
+ return NULL;
+ pos.lnum = lnum;
+ pos.col = offset;
+ }
+
+ return &pos;
+}
+
+/*
+ * Convert an argument in the form "1234" to an offset and compute the
+ * lnum/col from it. Convert an argument in the form "123/12" directly to a
+ * lnum/col.
+ * "argp" is advanced to after the argument.
+ * Return a pointer to the position, NULL if something is wrong.
+ */
+ static pos_T *
+get_off_or_lnum(buf_T *buf, char_u **argp)
+{
+ static pos_T mypos;
+ long off;
+
+ off = strtol((char *)*argp, (char **)argp, 10);
+ if (**argp == '/')
+ {
+ mypos.lnum = (linenr_T)off;
+ ++*argp;
+ mypos.col = strtol((char *)*argp, (char **)argp, 10);
+#ifdef FEAT_VIRTUALEDIT
+ mypos.coladd = 0;
+#endif
+ return &mypos;
+ }
+ return off2pos(buf, off);
+}
+
+
+/*
+ * Convert lnum,col to character offset
+ */
+ static long
+pos2off(buf_T *buf, pos_T *pos)
+{
+ long offset = 0;
+
+ if (!(buf->b_ml.ml_flags & ML_EMPTY))
+ {
+ if ((offset = ml_find_line_or_offset(buf, pos->lnum, 0)) < 0)
+ return 0;
+ offset += pos->col;
+ }
+
+ return offset;
+}
+
+
+#endif /* defined(FEAT_NETBEANS_INTG) */
diff --git a/src/normal.c b/src/normal.c
new file mode 100644
index 000000000..89196da0f
--- /dev/null
+++ b/src/normal.c
@@ -0,0 +1,8508 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * normal.c: Contains the main routine for processing characters in command
+ * mode. Communicates closely with the code in ops.c to handle
+ * the operators.
+ */
+
+#include "vim.h"
+
+#ifdef FEAT_VISUAL
+/*
+ * The Visual area is remembered for reselection.
+ */
+static int resel_VIsual_mode = NUL; /* 'v', 'V', or Ctrl-V */
+static linenr_T resel_VIsual_line_count; /* number of lines */
+static colnr_T resel_VIsual_col; /* nr of cols or end col */
+
+static int restart_VIsual_select = 0;
+#endif
+
+static int
+# ifdef __BORLANDC__
+_RTLENTRYF
+# endif
+ nv_compare __ARGS((const void *s1, const void *s2));
+static int find_command __ARGS((int cmdchar));
+static void op_colon __ARGS((oparg_T *oap));
+#if defined(FEAT_MOUSE) && defined(FEAT_VISUAL)
+static void find_start_of_word __ARGS((pos_T *));
+static void find_end_of_word __ARGS((pos_T *));
+static int get_mouse_class __ARGS((char_u *p));
+#endif
+static void prep_redo_cmd __ARGS((cmdarg_T *cap));
+static void prep_redo __ARGS((int regname, long, int, int, int, int, int));
+static int checkclearop __ARGS((oparg_T *oap));
+static int checkclearopq __ARGS((oparg_T *oap));
+static void clearop __ARGS((oparg_T *oap));
+static void clearopbeep __ARGS((oparg_T *oap));
+#ifdef FEAT_VISUAL
+static void unshift_special __ARGS((cmdarg_T *cap));
+#endif
+#ifdef FEAT_CMDL_INFO
+static void del_from_showcmd __ARGS((int));
+#endif
+
+/*
+ * nv_*(): functions called to handle Normal and Visual mode commands.
+ * n_*(): functions called to handle Normal mode commands.
+ * v_*(): functions called to handle Visual mode commands.
+ */
+static void nv_ignore __ARGS((cmdarg_T *cap));
+static void nv_error __ARGS((cmdarg_T *cap));
+static void nv_help __ARGS((cmdarg_T *cap));
+static void nv_addsub __ARGS((cmdarg_T *cap));
+static void nv_page __ARGS((cmdarg_T *cap));
+static void nv_gd __ARGS((oparg_T *oap, int nchar));
+static int nv_screengo __ARGS((oparg_T *oap, int dir, long dist));
+#ifdef FEAT_MOUSE
+static void nv_mousescroll __ARGS((cmdarg_T *cap));
+static void nv_mouse __ARGS((cmdarg_T *cap));
+#endif
+static void nv_scroll_line __ARGS((cmdarg_T *cap));
+static void nv_zet __ARGS((cmdarg_T *cap));
+#ifdef FEAT_GUI
+static void nv_ver_scrollbar __ARGS((cmdarg_T *cap));
+static void nv_hor_scrollbar __ARGS((cmdarg_T *cap));
+#endif
+static void nv_exmode __ARGS((cmdarg_T *cap));
+static void nv_colon __ARGS((cmdarg_T *cap));
+static void nv_ctrlg __ARGS((cmdarg_T *cap));
+static void nv_ctrlh __ARGS((cmdarg_T *cap));
+static void nv_clear __ARGS((cmdarg_T *cap));
+static void nv_ctrlo __ARGS((cmdarg_T *cap));
+static void nv_hat __ARGS((cmdarg_T *cap));
+static void nv_Zet __ARGS((cmdarg_T *cap));
+static void nv_ident __ARGS((cmdarg_T *cap));
+#ifdef FEAT_VISUAL
+static int get_visual_text __ARGS((cmdarg_T *cap, char_u **pp, int *lenp));
+#endif
+static void nv_tagpop __ARGS((cmdarg_T *cap));
+static void nv_scroll __ARGS((cmdarg_T *cap));
+static void nv_right __ARGS((cmdarg_T *cap));
+static void nv_left __ARGS((cmdarg_T *cap));
+static void nv_up __ARGS((cmdarg_T *cap));
+static void nv_down __ARGS((cmdarg_T *cap));
+#ifdef FEAT_SEARCHPATH
+static void nv_gotofile __ARGS((cmdarg_T *cap));
+#endif
+static void nv_end __ARGS((cmdarg_T *cap));
+static void nv_dollar __ARGS((cmdarg_T *cap));
+static void nv_search __ARGS((cmdarg_T *cap));
+static void nv_next __ARGS((cmdarg_T *cap));
+static void normal_search __ARGS((cmdarg_T *cap, int dir, char_u *pat, int opt));
+static void nv_csearch __ARGS((cmdarg_T *cap));
+static void nv_brackets __ARGS((cmdarg_T *cap));
+static void nv_percent __ARGS((cmdarg_T *cap));
+static void nv_brace __ARGS((cmdarg_T *cap));
+static void nv_mark __ARGS((cmdarg_T *cap));
+static void nv_findpar __ARGS((cmdarg_T *cap));
+static void nv_undo __ARGS((cmdarg_T *cap));
+static void nv_kundo __ARGS((cmdarg_T *cap));
+static void nv_Replace __ARGS((cmdarg_T *cap));
+#ifdef FEAT_VREPLACE
+static void nv_vreplace __ARGS((cmdarg_T *cap));
+#endif
+#ifdef FEAT_VISUAL
+static void v_swap_corners __ARGS((int cmdchar));
+#endif
+static void nv_replace __ARGS((cmdarg_T *cap));
+static void n_swapchar __ARGS((cmdarg_T *cap));
+static void nv_cursormark __ARGS((cmdarg_T *cap, int flag, pos_T *pos));
+#ifdef FEAT_VISUAL
+static void v_visop __ARGS((cmdarg_T *cap));
+#endif
+static void nv_subst __ARGS((cmdarg_T *cap));
+static void nv_abbrev __ARGS((cmdarg_T *cap));
+static void nv_optrans __ARGS((cmdarg_T *cap));
+static void nv_gomark __ARGS((cmdarg_T *cap));
+static void nv_pcmark __ARGS((cmdarg_T *cap));
+static void nv_regname __ARGS((cmdarg_T *cap));
+#ifdef FEAT_VISUAL
+static void nv_visual __ARGS((cmdarg_T *cap));
+static void n_start_visual_mode __ARGS((int c));
+#endif
+static void nv_window __ARGS((cmdarg_T *cap));
+static void nv_suspend __ARGS((cmdarg_T *cap));
+static void nv_g_cmd __ARGS((cmdarg_T *cap));
+static void n_opencmd __ARGS((cmdarg_T *cap));
+static void nv_dot __ARGS((cmdarg_T *cap));
+static void nv_redo __ARGS((cmdarg_T *cap));
+static void nv_Undo __ARGS((cmdarg_T *cap));
+static void nv_tilde __ARGS((cmdarg_T *cap));
+static void nv_operator __ARGS((cmdarg_T *cap));
+static void nv_lineop __ARGS((cmdarg_T *cap));
+static void nv_home __ARGS((cmdarg_T *cap));
+static void nv_pipe __ARGS((cmdarg_T *cap));
+static void nv_bck_word __ARGS((cmdarg_T *cap));
+static void nv_wordcmd __ARGS((cmdarg_T *cap));
+static void nv_beginline __ARGS((cmdarg_T *cap));
+#ifdef FEAT_VISUAL
+static void adjust_for_sel __ARGS((cmdarg_T *cap));
+static int unadjust_for_sel __ARGS((void));
+static void nv_select __ARGS((cmdarg_T *cap));
+#endif
+static void nv_goto __ARGS((cmdarg_T *cap));
+static void nv_normal __ARGS((cmdarg_T *cap));
+static void nv_esc __ARGS((cmdarg_T *oap));
+static void nv_edit __ARGS((cmdarg_T *cap));
+static void invoke_edit __ARGS((cmdarg_T *cap, int repl, int cmd, int startln));
+#ifdef FEAT_TEXTOBJ
+static void nv_object __ARGS((cmdarg_T *cap));
+#endif
+static void nv_record __ARGS((cmdarg_T *cap));
+static void nv_at __ARGS((cmdarg_T *cap));
+static void nv_halfpage __ARGS((cmdarg_T *cap));
+static void nv_join __ARGS((cmdarg_T *cap));
+static void nv_put __ARGS((cmdarg_T *cap));
+static void nv_open __ARGS((cmdarg_T *cap));
+#ifdef FEAT_SNIFF
+static void nv_sniff __ARGS((cmdarg_T *cap));
+#endif
+#ifdef FEAT_NETBEANS_INTG
+static void nv_nbcmd __ARGS((cmdarg_T *cap));
+#endif
+#ifdef FEAT_DND
+static void nv_drop __ARGS((cmdarg_T *cap));
+#endif
+
+/*
+ * Function to be called for a Normal or Visual mode command.
+ * The argument is a cmdarg_T.
+ */
+typedef void (*nv_func_T) __ARGS((cmdarg_T *cap));
+
+/* Values for cmd_flags. */
+#define NV_NCH 0x01 /* may need to get a second char */
+#define NV_NCH_NOP (0x02|NV_NCH) /* get second char when no operator pending */
+#define NV_NCH_ALW (0x04|NV_NCH) /* always get a second char */
+#define NV_LANG 0x08 /* second char needs language adjustment */
+
+#define NV_SS 0x10 /* may start selection */
+#define NV_SSS 0x20 /* may start selection with shift modifier */
+#define NV_STS 0x40 /* may stop selection without shift modif. */
+#define NV_RL 0x80 /* 'rightleft' modifies command */
+#define NV_KEEPREG 0x100 /* don't clear regname */
+#define NV_NCW 0x200 /* not allowed in command-line window */
+
+/*
+ * Generally speaking, every Normal mode command should either clear any
+ * pending operator (with *clearop*()), or set the motion type variable
+ * oap->motion_type.
+ *
+ * When a cursor motion command is made, it is marked as being a character or
+ * line oriented motion. Then, if an operator is in effect, the operation
+ * becomes character or line oriented accordingly.
+ */
+
+/*
+ * This table contains one entry for every Normal or Visual mode command.
+ * The order doesn't matter, init_normal_cmds() will create a sorted index.
+ * It is faster when all keys from zero to '~' are present.
+ */
+static const struct nv_cmd
+{
+ int cmd_char; /* (first) command character */
+ nv_func_T cmd_func; /* function for this command */
+ short_u cmd_flags; /* NV_ flags */
+ short cmd_arg; /* value for ca.arg */
+} nv_cmds[] =
+{
+ {NUL, nv_error, 0, 0},
+ {Ctrl_A, nv_addsub, 0, 0},
+ {Ctrl_B, nv_page, NV_STS, BACKWARD},
+ {Ctrl_C, nv_esc, 0, TRUE},
+ {Ctrl_D, nv_halfpage, 0, 0},
+ {Ctrl_E, nv_scroll_line, 0, TRUE},
+ {Ctrl_F, nv_page, NV_STS, FORWARD},
+ {Ctrl_G, nv_ctrlg, 0, 0},
+ {Ctrl_H, nv_ctrlh, 0, 0},
+ {Ctrl_I, nv_pcmark, 0, 0},
+ {NL, nv_down, 0, FALSE},
+ {Ctrl_K, nv_error, 0, 0},
+ {Ctrl_L, nv_clear, 0, 0},
+ {CAR, nv_down, 0, TRUE},
+ {Ctrl_N, nv_down, NV_STS, FALSE},
+ {Ctrl_O, nv_ctrlo, 0, 0},
+ {Ctrl_P, nv_up, NV_STS, FALSE},
+ {Ctrl_Q, nv_ignore, 0, 0},
+ {Ctrl_R, nv_redo, 0, 0},
+ {Ctrl_S, nv_ignore, 0, 0},
+ {Ctrl_T, nv_tagpop, NV_NCW, 0},
+ {Ctrl_U, nv_halfpage, 0, 0},
+#ifdef FEAT_VISUAL
+ {Ctrl_V, nv_visual, 0, FALSE},
+ {'V', nv_visual, 0, FALSE},
+ {'v', nv_visual, 0, FALSE},
+#else
+ {Ctrl_V, nv_error, 0, 0},
+ {'V', nv_error, 0, 0},
+ {'v', nv_error, 0, 0},
+#endif
+ {Ctrl_W, nv_window, 0, 0},
+ {Ctrl_X, nv_addsub, 0, 0},
+ {Ctrl_Y, nv_scroll_line, 0, FALSE},
+ {Ctrl_Z, nv_suspend, 0, 0},
+ {ESC, nv_esc, 0, FALSE},
+ {Ctrl_BSL, nv_normal, NV_NCH_ALW, 0},
+ {Ctrl_RSB, nv_ident, NV_NCW, 0},
+ {Ctrl_HAT, nv_hat, NV_NCW, 0},
+ {Ctrl__, nv_error, 0, 0},
+ {' ', nv_right, 0, 0},
+ {'!', nv_operator, 0, 0},
+ {'"', nv_regname, NV_NCH_NOP|NV_KEEPREG, 0},
+ {'#', nv_ident, 0, 0},
+ {'$', nv_dollar, 0, 0},
+ {'%', nv_percent, 0, 0},
+ {'&', nv_optrans, 0, 0},
+ {'\'', nv_gomark, NV_NCH_ALW, TRUE},
+ {'(', nv_brace, 0, BACKWARD},
+ {')', nv_brace, 0, FORWARD},
+ {'*', nv_ident, 0, 0},
+ {'+', nv_down, 0, TRUE},
+ {',', nv_csearch, 0, TRUE},
+ {'-', nv_up, 0, TRUE},
+ {'.', nv_dot, NV_KEEPREG, 0},
+ {'/', nv_search, 0, FALSE},
+ {'0', nv_beginline, 0, 0},
+ {'1', nv_ignore, 0, 0},
+ {'2', nv_ignore, 0, 0},
+ {'3', nv_ignore, 0, 0},
+ {'4', nv_ignore, 0, 0},
+ {'5', nv_ignore, 0, 0},
+ {'6', nv_ignore, 0, 0},
+ {'7', nv_ignore, 0, 0},
+ {'8', nv_ignore, 0, 0},
+ {'9', nv_ignore, 0, 0},
+ {':', nv_colon, 0, 0},
+ {';', nv_csearch, 0, FALSE},
+ {'<', nv_operator, NV_RL, 0},
+ {'=', nv_operator, 0, 0},
+ {'>', nv_operator, NV_RL, 0},
+ {'?', nv_search, 0, FALSE},
+ {'@', nv_at, NV_NCH_NOP, FALSE},
+ {'A', nv_edit, 0, 0},
+ {'B', nv_bck_word, 0, 1},
+ {'C', nv_abbrev, NV_KEEPREG, 0},
+ {'D', nv_abbrev, NV_KEEPREG, 0},
+ {'E', nv_wordcmd, 0, TRUE},
+ {'F', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD},
+ {'G', nv_goto, 0, TRUE},
+ {'H', nv_scroll, 0, 0},
+ {'I', nv_edit, 0, 0},
+ {'J', nv_join, 0, 0},
+ {'K', nv_ident, 0, 0},
+ {'L', nv_scroll, 0, 0},
+ {'M', nv_scroll, 0, 0},
+ {'N', nv_next, 0, SEARCH_REV},
+ {'O', nv_open, 0, 0},
+ {'P', nv_put, 0, 0},
+ {'Q', nv_exmode, NV_NCW, 0},
+ {'R', nv_Replace, 0, FALSE},
+ {'S', nv_subst, NV_KEEPREG, 0},
+ {'T', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD},
+ {'U', nv_Undo, 0, 0},
+ {'W', nv_wordcmd, 0, TRUE},
+ {'X', nv_abbrev, NV_KEEPREG, 0},
+ {'Y', nv_abbrev, NV_KEEPREG, 0},
+ {'Z', nv_Zet, NV_NCH_NOP|NV_NCW, 0},
+ {'[', nv_brackets, NV_NCH_ALW, BACKWARD},
+ {'\\', nv_error, 0, 0},
+ {']', nv_brackets, NV_NCH_ALW, FORWARD},
+ {'^', nv_beginline, 0, BL_WHITE | BL_FIX},
+ {'_', nv_lineop, 0, 0},
+ {'`', nv_gomark, NV_NCH_ALW, FALSE},
+ {'a', nv_edit, NV_NCH, 0},
+ {'b', nv_bck_word, 0, 0},
+ {'c', nv_operator, 0, 0},
+ {'d', nv_operator, 0, 0},
+ {'e', nv_wordcmd, 0, FALSE},
+ {'f', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD},
+ {'g', nv_g_cmd, NV_NCH_ALW, FALSE},
+ {'h', nv_left, NV_RL, 0},
+ {'i', nv_edit, NV_NCH, 0},
+ {'j', nv_down, 0, FALSE},
+ {'k', nv_up, 0, FALSE},
+ {'l', nv_right, NV_RL, 0},
+ {'m', nv_mark, NV_NCH_NOP, 0},
+ {'n', nv_next, 0, 0},
+ {'o', nv_open, 0, 0},
+ {'p', nv_put, 0, 0},
+ {'q', nv_record, NV_NCH, 0},
+ {'r', nv_replace, NV_NCH_NOP|NV_LANG, 0},
+ {'s', nv_subst, NV_KEEPREG, 0},
+ {'t', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD},
+ {'u', nv_undo, 0, 0},
+ {'w', nv_wordcmd, 0, FALSE},
+ {'x', nv_abbrev, NV_KEEPREG, 0},
+ {'y', nv_operator, 0, 0},
+ {'z', nv_zet, NV_NCH_ALW, 0},
+ {'{', nv_findpar, 0, BACKWARD},
+ {'|', nv_pipe, 0, 0},
+ {'}', nv_findpar, 0, FORWARD},
+ {'~', nv_tilde, 0, 0},
+
+ /* pound sign */
+ {POUND, nv_ident, 0, 0},
+#ifdef FEAT_MOUSE
+ {K_MOUSEUP, nv_mousescroll, 0, TRUE},
+ {K_MOUSEDOWN, nv_mousescroll, 0, FALSE},
+ {K_LEFTMOUSE, nv_mouse, 0, 0},
+ {K_LEFTMOUSE_NM, nv_mouse, 0, 0},
+ {K_LEFTDRAG, nv_mouse, 0, 0},
+ {K_LEFTRELEASE, nv_mouse, 0, 0},
+ {K_LEFTRELEASE_NM, nv_mouse, 0, 0},
+ {K_MIDDLEMOUSE, nv_mouse, 0, 0},
+ {K_MIDDLEDRAG, nv_mouse, 0, 0},
+ {K_MIDDLERELEASE, nv_mouse, 0, 0},
+ {K_RIGHTMOUSE, nv_mouse, 0, 0},
+ {K_RIGHTDRAG, nv_mouse, 0, 0},
+ {K_RIGHTRELEASE, nv_mouse, 0, 0},
+ {K_X1MOUSE, nv_mouse, 0, 0},
+ {K_X1DRAG, nv_mouse, 0, 0},
+ {K_X1RELEASE, nv_mouse, 0, 0},
+ {K_X2MOUSE, nv_mouse, 0, 0},
+ {K_X2DRAG, nv_mouse, 0, 0},
+ {K_X2RELEASE, nv_mouse, 0, 0},
+#endif
+ {K_IGNORE, nv_ignore, 0, 0},
+ {K_INS, nv_edit, 0, 0},
+ {K_KINS, nv_edit, 0, 0},
+ {K_BS, nv_ctrlh, 0, 0},
+ {K_UP, nv_up, NV_SSS|NV_STS, FALSE},
+ {K_S_UP, nv_page, NV_SS, BACKWARD},
+ {K_DOWN, nv_down, NV_SSS|NV_STS, FALSE},
+ {K_S_DOWN, nv_page, NV_SS, FORWARD},
+ {K_LEFT, nv_left, NV_SSS|NV_STS|NV_RL, 0},
+ {K_S_LEFT, nv_bck_word, NV_SS|NV_RL, 0},
+ {K_C_LEFT, nv_bck_word, NV_SSS|NV_RL|NV_STS, 1},
+ {K_RIGHT, nv_right, NV_SSS|NV_STS|NV_RL, 0},
+ {K_S_RIGHT, nv_wordcmd, NV_SS|NV_RL, FALSE},
+ {K_C_RIGHT, nv_wordcmd, NV_SSS|NV_RL|NV_STS, TRUE},
+ {K_PAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD},
+ {K_KPAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD},
+ {K_PAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD},
+ {K_KPAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD},
+ {K_END, nv_end, NV_SSS|NV_STS, FALSE},
+ {K_KEND, nv_end, NV_SSS|NV_STS, FALSE},
+ {K_XEND, nv_end, NV_SSS|NV_STS, FALSE},
+ {K_S_END, nv_end, NV_SS, FALSE},
+ {K_C_END, nv_end, NV_SSS|NV_STS, TRUE},
+ {K_HOME, nv_home, NV_SSS|NV_STS, 0},
+ {K_KHOME, nv_home, NV_SSS|NV_STS, 0},
+ {K_XHOME, nv_home, NV_SSS|NV_STS, 0},
+ {K_S_HOME, nv_home, NV_SS, 0},
+ {K_C_HOME, nv_goto, NV_SSS|NV_STS, FALSE},
+ {K_DEL, nv_abbrev, 0, 0},
+ {K_KDEL, nv_abbrev, 0, 0},
+ {K_UNDO, nv_kundo, 0, 0},
+ {K_HELP, nv_help, NV_NCW, 0},
+ {K_F1, nv_help, NV_NCW, 0},
+ {K_XF1, nv_help, NV_NCW, 0},
+#ifdef FEAT_VISUAL
+ {K_SELECT, nv_select, 0, 0},
+#endif
+#ifdef FEAT_GUI
+ {K_VER_SCROLLBAR, nv_ver_scrollbar, 0, 0},
+ {K_HOR_SCROLLBAR, nv_hor_scrollbar, 0, 0},
+#endif
+#ifdef FEAT_FKMAP
+ {K_F8, farsi_fkey, 0, 0},
+ {K_F9, farsi_fkey, 0, 0},
+#endif
+#ifdef FEAT_SNIFF
+ {K_SNIFF, nv_sniff, 0, 0},
+#endif
+#ifdef FEAT_NETBEANS_INTG
+ {K_F21, nv_nbcmd, NV_NCH_ALW, 0},
+#endif
+#ifdef FEAT_DND
+ {K_DROP, nv_drop, NV_STS, 0},
+#endif
+};
+
+/* Number of commands in nv_cmds[]. */
+#define NV_CMDS_SIZE (sizeof(nv_cmds) / sizeof(struct nv_cmd))
+
+/* Sorted index of commands in nv_cmds[]. */
+static short nv_cmd_idx[NV_CMDS_SIZE];
+
+/* The highest index for which
+ * nv_cmds[idx].cmd_char == nv_cmd_idx[nv_cmds[idx].cmd_char] */
+static int nv_max_linear;
+
+/*
+ * Compare functions for qsort() below, that checks the command character
+ * through the index in nv_cmd_idx[].
+ */
+ static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+nv_compare(s1, s2)
+ const void *s1;
+ const void *s2;
+{
+ int c1, c2;
+
+ /* The commands are sorted on absolute value. */
+ c1 = nv_cmds[*(const short *)s1].cmd_char;
+ c2 = nv_cmds[*(const short *)s2].cmd_char;
+ if (c1 < 0)
+ c1 = -c1;
+ if (c2 < 0)
+ c2 = -c2;
+ return c1 - c2;
+}
+
+/*
+ * Initialize the nv_cmd_idx[] table.
+ */
+ void
+init_normal_cmds()
+{
+ int i;
+
+ /* Fill the index table with a one to one relation. */
+ for (i = 0; i < NV_CMDS_SIZE; ++i)
+ nv_cmd_idx[i] = i;
+
+ /* Sort the commands by the command character. */
+ qsort((void *)&nv_cmd_idx, (size_t)NV_CMDS_SIZE, sizeof(short), nv_compare);
+
+ /* Find the first entry that can't be indexed by the command character. */
+ for (i = 0; i < NV_CMDS_SIZE; ++i)
+ if (i != nv_cmds[nv_cmd_idx[i]].cmd_char)
+ break;
+ nv_max_linear = i - 1;
+}
+
+/*
+ * Search for a command in the commands table.
+ * Returns -1 for invalid command.
+ */
+ static int
+find_command(cmdchar)
+ int cmdchar;
+{
+ int i;
+ int idx;
+ int top, bot;
+ int c;
+
+#ifdef FEAT_MBYTE
+ /* A multi-byte character is never a command. */
+ if (cmdchar >= 0x100)
+ return -1;
+#endif
+
+ /* We use the absolute value of the character. Special keys have a
+ * negative value, but are sorted on their absolute value. */
+ if (cmdchar < 0)
+ cmdchar = -cmdchar;
+
+ /* If the character is in the first part: The character is the index into
+ * nv_cmd_idx[]. */
+ if (cmdchar <= nv_max_linear)
+ return nv_cmd_idx[cmdchar];
+
+ /* Perform a binary search. */
+ bot = nv_max_linear + 1;
+ top = NV_CMDS_SIZE - 1;
+ idx = -1;
+ while (bot <= top)
+ {
+ i = (top + bot) / 2;
+ c = nv_cmds[nv_cmd_idx[i]].cmd_char;
+ if (c < 0)
+ c = -c;
+ if (cmdchar == c)
+ {
+ idx = nv_cmd_idx[i];
+ break;
+ }
+ if (cmdchar > c)
+ bot = i + 1;
+ else
+ top = i - 1;
+ }
+ return idx;
+}
+
+/*
+ * Execute a command in Normal mode.
+ */
+/*ARGSUSED*/
+ void
+normal_cmd(oap, toplevel)
+ oparg_T *oap;
+ int toplevel; /* TRUE when called from main() */
+{
+ static long opcount = 0; /* ca.opcount saved here */
+ cmdarg_T ca; /* command arguments */
+ int c;
+ int ctrl_w = FALSE; /* got CTRL-W command */
+ int old_col = curwin->w_curswant;
+#ifdef FEAT_CMDL_INFO
+ int need_flushbuf; /* need to call out_flush() */
+#endif
+#ifdef FEAT_VISUAL
+ pos_T old_pos; /* cursor position before command */
+ int mapped_len;
+#endif
+ static int old_mapped_len = 0;
+ int idx;
+
+ vim_memset(&ca, 0, sizeof(ca)); /* also resets ca.retval */
+ ca.oap = oap;
+ ca.opcount = opcount;
+
+#ifdef FEAT_SNIFF
+ want_sniff_request = sniff_connected;
+#endif
+
+ /*
+ * If there is an operator pending, then the command we take this time
+ * will terminate it. Finish_op tells us to finish the operation before
+ * returning this time (unless the operation was cancelled).
+ */
+#ifdef CURSOR_SHAPE
+ c = finish_op;
+#endif
+ finish_op = (oap->op_type != OP_NOP);
+#ifdef CURSOR_SHAPE
+ if (finish_op != c)
+ {
+ ui_cursor_shape(); /* may show different cursor shape */
+# ifdef FEAT_MOUSESHAPE
+ update_mouseshape(-1);
+# endif
+ }
+#endif
+
+ if (!finish_op && !oap->regname)
+ ca.opcount = 0;
+
+#ifdef FEAT_VISUAL
+ mapped_len = typebuf_maplen();
+#endif
+
+ State = NORMAL_BUSY;
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = FALSE; /* allow scrolling here */
+#endif
+
+ /*
+ * Get the command character from the user.
+ */
+ c = safe_vgetc();
+
+#ifdef FEAT_LANGMAP
+ LANGMAP_ADJUST(c, TRUE);
+#endif
+
+ /*
+ * If a mapping was started in Visual or Select mode, remember the length
+ * of the mapping. This is used below to not return to Insert mode for as
+ * long as the mapping is being executed.
+ */
+ if (restart_edit == 0)
+ old_mapped_len = 0;
+ else if (old_mapped_len
+#ifdef FEAT_VISUAL
+ || (VIsual_active && mapped_len == 0 && typebuf_maplen() > 0)
+#endif
+ )
+ old_mapped_len = typebuf_maplen();
+
+ if (c == NUL)
+ c = K_ZERO;
+
+#ifdef FEAT_VISUAL
+ /*
+ * In Select mode, typed text replaces the selection.
+ */
+ if (VIsual_active
+ && VIsual_select
+ && (vim_isprintc(c) || c == NL || c == CAR || c == K_KENTER))
+ {
+# ifdef FEAT_MBYTE
+ char_u buf[MB_MAXBYTES + 1];
+
+ buf[(*mb_char2bytes)(c, buf)] = NUL;
+# else
+ char_u buf[2];
+
+ buf[0] = c;
+ buf[1] = NUL;
+# endif
+ /* Fake a "c"hange command.
+ * Insert the typed character in the typeahead buffer, so that it will
+ * be mapped in Insert mode. Required for ":lmap" to work. May cause
+ * mapping a character from ":vnoremap"... */
+ (void)ins_typebuf(buf, REMAP_YES, 0, !KeyTyped, FALSE);
+ c = 'c';
+ }
+#endif
+
+#ifdef FEAT_CMDL_INFO
+ need_flushbuf = add_to_showcmd(c);
+#endif
+
+getcount:
+#ifdef FEAT_VISUAL
+ if (!(VIsual_active && VIsual_select))
+#endif
+ {
+ /*
+ * Handle a count before a command and compute ca.count0.
+ * Note that '0' is a command and not the start of a count, but it's
+ * part of a count after other digits.
+ */
+ while ( (c >= '1' && c <= '9')
+ || (ca.count0 != 0 && (c == K_DEL || c == K_KDEL || c == '0')))
+ {
+ if (c == K_DEL || c == K_KDEL)
+ {
+ ca.count0 /= 10;
+#ifdef FEAT_CMDL_INFO
+ del_from_showcmd(4); /* delete the digit and ~@% */
+#endif
+ }
+ else
+ ca.count0 = ca.count0 * 10 + (c - '0');
+ if (ca.count0 < 0) /* got too large! */
+ ca.count0 = 999999999L;
+ if (ctrl_w)
+ {
+ ++no_mapping;
+ ++allow_keys; /* no mapping for nchar, but keys */
+ }
+ ++no_zero_mapping; /* don't map zero here */
+ c = safe_vgetc();
+#ifdef FEAT_LANGMAP
+ LANGMAP_ADJUST(c, TRUE);
+#endif
+ --no_zero_mapping;
+ if (ctrl_w)
+ {
+ --no_mapping;
+ --allow_keys;
+ }
+#ifdef FEAT_CMDL_INFO
+ need_flushbuf |= add_to_showcmd(c);
+#endif
+ }
+
+ /*
+ * If we got CTRL-W there may be a/another count
+ */
+ if (c == Ctrl_W && !ctrl_w && oap->op_type == OP_NOP)
+ {
+ ctrl_w = TRUE;
+ ca.opcount = ca.count0; /* remember first count */
+ ca.count0 = 0;
+ ++no_mapping;
+ ++allow_keys; /* no mapping for nchar, but keys */
+ c = safe_vgetc(); /* get next character */
+#ifdef FEAT_LANGMAP
+ LANGMAP_ADJUST(c, TRUE);
+#endif
+ --no_mapping;
+ --allow_keys;
+#ifdef FEAT_CMDL_INFO
+ need_flushbuf |= add_to_showcmd(c);
+#endif
+ goto getcount; /* jump back */
+ }
+ }
+
+ /*
+ * If we're in the middle of an operator (including after entering a yank
+ * buffer with '"') AND we had a count before the operator, then that
+ * count overrides the current value of ca.count0.
+ * What this means effectively, is that commands like "3dw" get turned
+ * into "d3w" which makes things fall into place pretty neatly.
+ * If you give a count before AND after the operator, they are multiplied.
+ */
+ if (ca.opcount != 0)
+ {
+ if (ca.count0)
+ ca.count0 *= ca.opcount;
+ else
+ ca.count0 = ca.opcount;
+ }
+
+ /*
+ * Always remember the count. It will be set to zero (on the next call,
+ * above) when there is no pending operator.
+ * When called from main(), save the count for use by the "count" built-in
+ * variable.
+ */
+ ca.opcount = ca.count0;
+ ca.count1 = (ca.count0 == 0 ? 1 : ca.count0);
+
+#ifdef FEAT_EVAL
+ /*
+ * Only set v:count when called from main() and not a stuffed command.
+ */
+ if (toplevel && stuff_empty())
+ set_vcount(ca.count0, ca.count1);
+#endif
+
+ /*
+ * Find the command character in the table of commands.
+ * For CTRL-W we already got nchar when looking for a count.
+ */
+ if (ctrl_w)
+ {
+ ca.nchar = c;
+ ca.cmdchar = Ctrl_W;
+ }
+ else
+ ca.cmdchar = c;
+ idx = find_command(ca.cmdchar);
+ if (idx < 0)
+ {
+ /* Not a known command: beep. */
+ clearopbeep(oap);
+ goto normal_end;
+ }
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0 && (nv_cmds[idx].cmd_flags & NV_NCW))
+ {
+ /* This command is not allowed in the cmdline window: beep. */
+ clearopbeep(oap);
+ EMSG(_(e_cmdwin));
+ goto normal_end;
+ }
+#endif
+
+#ifdef FEAT_VISUAL
+ /*
+ * In Visual/Select mode, a few keys are handled in a special way.
+ */
+ if (VIsual_active)
+ {
+ /* when 'keymodel' contains "stopsel" may stop Select/Visual mode */
+ if (km_stopsel
+ && (nv_cmds[idx].cmd_flags & NV_STS)
+ && !(mod_mask & MOD_MASK_SHIFT))
+ {
+ end_visual_mode();
+ redraw_curbuf_later(INVERTED);
+ }
+
+ /* Keys that work different when 'keymodel' contains "startsel" */
+ if (km_startsel)
+ {
+ if (nv_cmds[idx].cmd_flags & NV_SS)
+ {
+ unshift_special(&ca);
+ idx = find_command(ca.cmdchar);
+ }
+ else if ((nv_cmds[idx].cmd_flags & NV_SSS)
+ && (mod_mask & MOD_MASK_SHIFT))
+ {
+ mod_mask &= ~MOD_MASK_SHIFT;
+ }
+ }
+ }
+#endif
+
+#ifdef FEAT_RIGHTLEFT
+ if (curwin->w_p_rl && KeyTyped && !KeyStuffed
+ && (nv_cmds[idx].cmd_flags & NV_RL))
+ {
+ /* Invert horizontal movements and operations. Only when typed by the
+ * user directly, not when the result of a mapping or "x" translated
+ * to "dl". */
+ switch (ca.cmdchar)
+ {
+ case 'l': ca.cmdchar = 'h'; break;
+ case K_RIGHT: ca.cmdchar = K_LEFT; break;
+ case K_S_RIGHT: ca.cmdchar = K_S_LEFT; break;
+ case K_C_RIGHT: ca.cmdchar = K_C_LEFT; break;
+ case 'h': ca.cmdchar = 'l'; break;
+ case K_LEFT: ca.cmdchar = K_RIGHT; break;
+ case K_S_LEFT: ca.cmdchar = K_S_RIGHT; break;
+ case K_C_LEFT: ca.cmdchar = K_C_RIGHT; break;
+ case '>': ca.cmdchar = '<'; break;
+ case '<': ca.cmdchar = '>'; break;
+ }
+ idx = find_command(ca.cmdchar);
+ }
+#endif
+
+ /*
+ * Get an additional character if we need one.
+ */
+ if ((nv_cmds[idx].cmd_flags & NV_NCH)
+ && (((nv_cmds[idx].cmd_flags & NV_NCH_NOP) == NV_NCH_NOP
+ && oap->op_type == OP_NOP)
+ || (nv_cmds[idx].cmd_flags & NV_NCH_ALW) == NV_NCH_ALW
+ || (ca.cmdchar == 'q'
+ && oap->op_type == OP_NOP
+ && !Recording
+ && !Exec_reg)
+ || ((ca.cmdchar == 'a' || ca.cmdchar == 'i')
+ && (oap->op_type != OP_NOP
+#ifdef FEAT_VISUAL
+ || VIsual_active
+#endif
+ ))))
+ {
+ int *cp;
+ int repl = FALSE; /* get character for replace mode */
+ int lit = FALSE; /* get extra character literally */
+ int langmap_active = FALSE; /* using :lmap mappings */
+ int lang; /* getting a text character */
+#ifdef USE_IM_CONTROL
+ int save_smd; /* saved value of p_smd */
+#endif
+
+ ++no_mapping;
+ ++allow_keys; /* no mapping for nchar, but allow key codes */
+ if (ca.cmdchar == 'g')
+ {
+ /*
+ * For 'g' get the next character now, so that we can check for
+ * "gr", "g'" and "g`".
+ */
+ ca.nchar = safe_vgetc();
+#ifdef FEAT_LANGMAP
+ LANGMAP_ADJUST(ca.nchar, TRUE);
+#endif
+#ifdef FEAT_CMDL_INFO
+ need_flushbuf |= add_to_showcmd(ca.nchar);
+#endif
+ if (ca.nchar == 'r' || ca.nchar == '\'' || ca.nchar == '`'
+ || ca.nchar == Ctrl_BSL)
+ {
+ cp = &ca.extra_char; /* need to get a third character */
+ if (ca.nchar != 'r')
+ lit = TRUE; /* get it literally */
+ else
+ repl = TRUE; /* get it in replace mode */
+ }
+ else
+ cp = NULL; /* no third character needed */
+ }
+ else
+ {
+ if (ca.cmdchar == 'r') /* get it in replace mode */
+ repl = TRUE;
+ cp = &ca.nchar;
+ }
+ lang = (repl || (nv_cmds[idx].cmd_flags & NV_LANG));
+
+ /*
+ * Get a second or third character.
+ */
+ if (cp != NULL)
+ {
+#ifdef CURSOR_SHAPE
+ if (repl)
+ {
+ State = REPLACE; /* pretend Replace mode */
+ ui_cursor_shape(); /* show different cursor shape */
+ }
+#endif
+ if (lang && curbuf->b_p_iminsert == B_IMODE_LMAP)
+ {
+ /* Allow mappings defined with ":lmap". */
+ --no_mapping;
+ --allow_keys;
+ if (repl)
+ State = LREPLACE;
+ else
+ State = LANGMAP;
+ langmap_active = TRUE;
+ }
+#ifdef USE_IM_CONTROL
+ save_smd = p_smd;
+ p_smd = FALSE; /* Don't let the IM code show the mode here */
+ if (lang && curbuf->b_p_iminsert == B_IMODE_IM)
+ im_set_active(TRUE);
+#endif
+
+ *cp = safe_vgetc();
+
+ if (langmap_active)
+ {
+ /* Undo the decrement done above */
+ ++no_mapping;
+ ++allow_keys;
+ State = NORMAL_BUSY;
+ }
+#ifdef USE_IM_CONTROL
+ if (lang)
+ {
+ if (curbuf->b_p_iminsert != B_IMODE_LMAP)
+ im_save_status(&curbuf->b_p_iminsert);
+ im_set_active(FALSE);
+ }
+ p_smd = save_smd;
+#endif
+#ifdef CURSOR_SHAPE
+ State = NORMAL_BUSY;
+#endif
+#ifdef FEAT_CMDL_INFO
+ need_flushbuf |= add_to_showcmd(*cp);
+#endif
+
+ if (!lit)
+ {
+#ifdef FEAT_DIGRAPHS
+ /* Typing CTRL-K gets a digraph. */
+ if (*cp == Ctrl_K
+ && ((nv_cmds[idx].cmd_flags & NV_LANG)
+ || cp == &ca.extra_char)
+ && vim_strchr(p_cpo, CPO_DIGRAPH) == NULL)
+ {
+ c = get_digraph(FALSE);
+ if (c > 0)
+ {
+ *cp = c;
+# ifdef FEAT_CMDL_INFO
+ /* Guessing how to update showcmd here... */
+ del_from_showcmd(3);
+ need_flushbuf |= add_to_showcmd(*cp);
+# endif
+ }
+ }
+#endif
+
+#ifdef FEAT_LANGMAP
+ /* adjust chars > 127, except after "tTfFr" commands */
+ LANGMAP_ADJUST(*cp, !lang);
+#endif
+#ifdef FEAT_RIGHTLEFT
+ /* adjust Hebrew mapped char */
+ if (p_hkmap && lang && KeyTyped)
+ *cp = hkmap(*cp);
+# ifdef FEAT_FKMAP
+ /* adjust Farsi mapped char */
+ if (p_fkmap && lang && KeyTyped)
+ *cp = fkmap(*cp);
+# endif
+#endif
+ }
+
+ /*
+ * When the next character is CTRL-\ a following CTRL-N means the
+ * command is aborted and we go to Normal mode.
+ */
+ if (cp == &ca.extra_char
+ && ca.nchar == Ctrl_BSL
+ && (ca.extra_char == Ctrl_N || ca.extra_char == Ctrl_G))
+ {
+ ca.cmdchar = Ctrl_BSL;
+ ca.nchar = ca.extra_char;
+ idx = find_command(ca.cmdchar);
+ }
+ else if (*cp == Ctrl_BSL)
+ {
+ long towait = (p_ttm >= 0 ? p_ttm : p_tm);
+
+ /* There is a busy wait here when typing "f<C-\>" and then
+ * something different from CTRL-N. Can't be avoided. */
+ while ((c = vpeekc()) <= 0 && towait > 0L)
+ {
+ do_sleep(towait > 50L ? 50L : towait);
+ towait -= 50L;
+ }
+ if (c > 0)
+ {
+ c = safe_vgetc();
+ if (c != Ctrl_N && c != Ctrl_G)
+ vungetc(c);
+ else
+ {
+ ca.cmdchar = Ctrl_BSL;
+ ca.nchar = c;
+ idx = find_command(ca.cmdchar);
+ }
+ }
+ }
+
+#ifdef FEAT_MBYTE
+ /* When getting a text character and the next character is a
+ * multi-byte character, it could be a composing character.
+ * However, don't wait for it to arrive. */
+ while (enc_utf8 && lang && (c = vpeekc()) > 0
+ && (c >= 0x100 || MB_BYTE2LEN(vpeekc()) > 1))
+ {
+ c = safe_vgetc();
+ if (!utf_iscomposing(c))
+ {
+ vungetc(c); /* it wasn't, put it back */
+ break;
+ }
+ else if (ca.ncharC1 == 0)
+ ca.ncharC1 = c;
+ else
+ ca.ncharC2 = c;
+ }
+#endif
+ }
+ --no_mapping;
+ --allow_keys;
+ }
+
+#ifdef FEAT_CMDL_INFO
+ /*
+ * Flush the showcmd characters onto the screen so we can see them while
+ * the command is being executed. Only do this when the shown command was
+ * actually displayed, otherwise this will slow down a lot when executing
+ * mappings.
+ */
+ if (need_flushbuf)
+ out_flush();
+#endif
+
+ State = NORMAL;
+
+ if (ca.nchar == ESC)
+ {
+ clearop(oap);
+ if (restart_edit == 0 && goto_im())
+ restart_edit = 'a';
+ goto normal_end;
+ }
+
+ msg_didout = FALSE; /* don't scroll screen up for normal command */
+ msg_col = 0;
+
+#ifdef FEAT_VISUAL
+ old_pos = curwin->w_cursor; /* remember where cursor was */
+
+ /* When 'keymodel' contains "startsel" some keys start Select/Visual
+ * mode. */
+ if (!VIsual_active && km_startsel)
+ {
+ if (nv_cmds[idx].cmd_flags & NV_SS)
+ {
+ start_selection();
+ unshift_special(&ca);
+ idx = find_command(ca.cmdchar);
+ }
+ else if ((nv_cmds[idx].cmd_flags & NV_SSS)
+ && (mod_mask & MOD_MASK_SHIFT))
+ {
+ start_selection();
+ mod_mask &= ~MOD_MASK_SHIFT;
+ }
+ }
+#endif
+
+ /*
+ * Execute the command!
+ * Call the command function found in the commands table.
+ */
+ ca.arg = nv_cmds[idx].cmd_arg;
+ (nv_cmds[idx].cmd_func)(&ca);
+
+ /*
+ * If we didn't start or finish an operator, reset oap->regname, unless we
+ * need it later.
+ */
+ if (!finish_op
+ && !oap->op_type
+ && (idx < 0 || !(nv_cmds[idx].cmd_flags & NV_KEEPREG)))
+ {
+ clearop(oap);
+#ifdef FEAT_EVAL
+ set_reg_var('"');
+#endif
+ }
+
+ /*
+ * If an operation is pending, handle it...
+ */
+ do_pending_operator(&ca, old_col, FALSE);
+
+ /*
+ * Wait for a moment when a message is displayed that will be overwritten
+ * by the mode message.
+ * In Visual mode and with "^O" in Insert mode, a short message will be
+ * overwritten by the mode message. Wait a bit, until a key is hit.
+ * In Visual mode, it's more important to keep the Visual area updated
+ * than keeping a message (e.g. from a /pat search).
+ * Only do this if the command was typed, not from a mapping.
+ * Don't wait when emsg_silent is non-zero.
+ * Also wait a bit after an error message, e.g. for "^O:".
+ * Don't redraw the screen, it would remove the message.
+ */
+ if ( ((p_smd
+ && (restart_edit != 0
+#ifdef FEAT_VISUAL
+ || (VIsual_active
+ && old_pos.lnum == curwin->w_cursor.lnum
+ && old_pos.col == curwin->w_cursor.col)
+#endif
+ )
+ && (clear_cmdline
+ || redraw_cmdline)
+ && (msg_didout || (msg_didany && msg_scroll))
+ && !msg_nowait
+ && KeyTyped)
+ || (restart_edit != 0
+#ifdef FEAT_VISUAL
+ && !VIsual_active
+#endif
+ && (msg_scroll
+ || emsg_on_display)))
+ && oap->regname == 0
+ && !(ca.retval & CA_COMMAND_BUSY)
+ && stuff_empty()
+ && typebuf_typed()
+ && emsg_silent == 0
+ && !did_wait_return
+ && oap->op_type == OP_NOP)
+ {
+ int save_State = State;
+
+ /* Draw the cursor with the right shape here */
+ if (restart_edit != 0)
+ State = INSERT;
+
+ /* If need to redraw, and there is a "keep_msg", redraw before the
+ * delay */
+ if (must_redraw && keep_msg != NULL && !emsg_on_display)
+ {
+ char_u *kmsg;
+
+ kmsg = keep_msg;
+ keep_msg = NULL;
+ /* showmode() will clear keep_msg, but we want to use it anyway */
+ update_screen(0);
+ /* now reset it, otherwise it's put in the history again */
+ keep_msg = kmsg;
+ msg_attr(kmsg, keep_msg_attr);
+ vim_free(kmsg);
+ }
+ setcursor();
+ cursor_on();
+ out_flush();
+ if (msg_scroll || emsg_on_display)
+ ui_delay(1000L, TRUE); /* wait at least one second */
+ ui_delay(3000L, FALSE); /* wait up to three seconds */
+ State = save_State;
+
+ msg_scroll = FALSE;
+ emsg_on_display = FALSE;
+ }
+
+ /*
+ * Finish up after executing a Normal mode command.
+ */
+normal_end:
+
+ msg_nowait = FALSE;
+
+ /* Reset finish_op, in case it was set */
+#ifdef CURSOR_SHAPE
+ c = finish_op;
+#endif
+ finish_op = FALSE;
+#ifdef CURSOR_SHAPE
+ /* Redraw the cursor with another shape, if we were in Operator-pending
+ * mode or did a replace command. */
+ if (c || ca.cmdchar == 'r')
+ {
+ ui_cursor_shape(); /* may show different cursor shape */
+# ifdef FEAT_MOUSESHAPE
+ update_mouseshape(-1);
+# endif
+ }
+#endif
+
+#ifdef FEAT_CMDL_INFO
+ if (oap->op_type == OP_NOP && oap->regname == 0)
+ clear_showcmd();
+#endif
+
+ checkpcmark(); /* check if we moved since setting pcmark */
+ vim_free(ca.searchbuf);
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ mb_adjust_cursor();
+#endif
+
+#ifdef FEAT_SCROLLBIND
+ if (curwin->w_p_scb && toplevel)
+ {
+ validate_cursor(); /* may need to update w_leftcol */
+ do_check_scrollbind(TRUE);
+ }
+#endif
+
+ /*
+ * May restart edit(), if we got here with CTRL-O in Insert mode (but not
+ * if still inside a mapping that started in Visual mode).
+ * May switch from Visual to Select mode after CTRL-O command.
+ */
+ if ( oap->op_type == OP_NOP
+#ifdef FEAT_VISUAL
+ && ((restart_edit != 0 && !VIsual_active && old_mapped_len == 0)
+ || restart_VIsual_select == 1)
+#endif
+ && !(ca.retval & CA_COMMAND_BUSY)
+ && stuff_empty()
+ && oap->regname == 0)
+ {
+#ifdef FEAT_VISUAL
+ if (restart_VIsual_select == 1)
+ {
+ VIsual_select = TRUE;
+ showmode();
+ restart_VIsual_select = 0;
+ }
+#endif
+ if (restart_edit != 0
+#ifdef FEAT_VISUAL
+ && !VIsual_active
+#endif
+ && old_mapped_len == 0)
+ (void)edit(restart_edit, FALSE, 1L);
+ }
+
+#ifdef FEAT_VISUAL
+ if (restart_VIsual_select == 2)
+ restart_VIsual_select = 1;
+#endif
+
+ /* Save count before an operator for next time. */
+ opcount = ca.opcount;
+}
+
+/*
+ * Handle an operator after visual mode or when the movement is finished
+ */
+ void
+do_pending_operator(cap, old_col, gui_yank)
+ cmdarg_T *cap;
+ int old_col;
+ int gui_yank;
+{
+ oparg_T *oap = cap->oap;
+ pos_T old_cursor;
+ int empty_region_error;
+ int restart_edit_save;
+
+#ifdef FEAT_VISUAL
+ /* The visual area is remembered for redo */
+ static int redo_VIsual_mode = NUL; /* 'v', 'V', or Ctrl-V */
+ static linenr_T redo_VIsual_line_count; /* number of lines */
+ static colnr_T redo_VIsual_col; /* number of cols or end column */
+ static long redo_VIsual_count; /* count for Visual operator */
+# ifdef FEAT_VIRTUALEDIT
+ int include_line_break = FALSE;
+# endif
+#endif
+
+#if defined(FEAT_CLIPBOARD)
+ /*
+ * Yank the visual area into the GUI selection register before we operate
+ * on it and lose it forever.
+ * Don't do it if a specific register was specified, so that ""x"*P works.
+ * This could call do_pending_operator() recursively, but that's OK
+ * because gui_yank will be TRUE for the nested call.
+ */
+ if (clip_star.available
+ && oap->op_type != OP_NOP
+ && !gui_yank
+# ifdef FEAT_VISUAL
+ && VIsual_active
+ && !redo_VIsual_busy
+# endif
+ && oap->regname == 0)
+ clip_auto_select();
+#endif
+ old_cursor = curwin->w_cursor;
+
+ /*
+ * If an operation is pending, handle it...
+ */
+ if ((finish_op
+#ifdef FEAT_VISUAL
+ || VIsual_active
+#endif
+ ) && oap->op_type != OP_NOP)
+ {
+#ifdef FEAT_VISUAL
+ oap->is_VIsual = VIsual_active;
+ if (oap->motion_force == 'V')
+ oap->motion_type = MLINE;
+ else if (oap->motion_force == 'v')
+ {
+ /* If the motion was linewise, "inclusive" will not have been set.
+ * Use "exclusive" to be consistent. Makes "dvj" work nice. */
+ if (oap->motion_type == MLINE)
+ oap->inclusive = FALSE;
+ /* If the motion already was characterwise, toggle "inclusive" */
+ else if (oap->motion_type == MCHAR)
+ oap->inclusive = !oap->inclusive;
+ oap->motion_type = MCHAR;
+ }
+ else if (oap->motion_force == Ctrl_V)
+ {
+ /* Change line- or characterwise motion into Visual block mode. */
+ VIsual_active = TRUE;
+ VIsual = oap->start;
+ VIsual_mode = Ctrl_V;
+ VIsual_select = FALSE;
+ VIsual_reselect = FALSE;
+ }
+#endif
+
+ /* only redo yank when 'y' flag is in 'cpoptions' */
+ /* never redo "zf" (define fold) */
+ if ((vim_strchr(p_cpo, CPO_YANK) != NULL || oap->op_type != OP_YANK)
+#ifdef FEAT_VISUAL
+ && (!VIsual_active || oap->motion_force)
+#endif
+#ifdef FEAT_FOLDING
+ && oap->op_type != OP_FOLD
+ && oap->op_type != OP_FOLDOPEN
+ && oap->op_type != OP_FOLDOPENREC
+ && oap->op_type != OP_FOLDCLOSE
+ && oap->op_type != OP_FOLDCLOSEREC
+ && oap->op_type != OP_FOLDDEL
+ && oap->op_type != OP_FOLDDELREC
+#endif
+ )
+ {
+ prep_redo(oap->regname, cap->count0,
+ get_op_char(oap->op_type), get_extra_op_char(oap->op_type),
+ oap->motion_force, cap->cmdchar, cap->nchar);
+ if (cap->cmdchar == '/' || cap->cmdchar == '?') /* was a search */
+ {
+ /*
+ * If 'cpoptions' does not contain 'r', insert the search
+ * pattern to really repeat the same command.
+ */
+ if (vim_strchr(p_cpo, CPO_REDO) == NULL)
+ AppendToRedobuffLit(cap->searchbuf);
+ AppendToRedobuff(NL_STR);
+ }
+ else if (cap->cmdchar == ':')
+ {
+ /* do_cmdline() has stored the first typed line in
+ * "repeat_cmdline". When several lines are typed repeating
+ * won't be possible. */
+ if (repeat_cmdline == NULL)
+ ResetRedobuff();
+ else
+ {
+ AppendToRedobuffLit(repeat_cmdline);
+ AppendToRedobuff(NL_STR);
+ vim_free(repeat_cmdline);
+ repeat_cmdline = NULL;
+ }
+ }
+ }
+
+#ifdef FEAT_VISUAL
+ if (redo_VIsual_busy)
+ {
+ oap->start = curwin->w_cursor;
+ curwin->w_cursor.lnum += redo_VIsual_line_count - 1;
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ VIsual_mode = redo_VIsual_mode;
+ if (VIsual_mode == 'v')
+ {
+ if (redo_VIsual_line_count <= 1)
+ curwin->w_cursor.col += redo_VIsual_col - 1;
+ else
+ curwin->w_cursor.col = redo_VIsual_col;
+ }
+ if (redo_VIsual_col == MAXCOL)
+ {
+ curwin->w_curswant = MAXCOL;
+ coladvance((colnr_T)MAXCOL);
+ }
+ cap->count0 = redo_VIsual_count;
+ if (redo_VIsual_count != 0)
+ cap->count1 = redo_VIsual_count;
+ else
+ cap->count1 = 1;
+ }
+ else if (VIsual_active)
+ {
+ /* Save the current VIsual area for '< and '> marks, and "gv" */
+ curbuf->b_visual_start = VIsual;
+ curbuf->b_visual_end = curwin->w_cursor;
+ curbuf->b_visual_mode = VIsual_mode;
+# ifdef FEAT_EVAL
+ curbuf->b_visual_mode_eval = VIsual_mode;
+# endif
+ curbuf->b_visual_curswant = curwin->w_curswant;
+
+ /* In Select mode, a linewise selection is operated upon like a
+ * characterwise selection. */
+ if (VIsual_select && VIsual_mode == 'V')
+ {
+ if (lt(VIsual, curwin->w_cursor))
+ {
+ VIsual.col = 0;
+ curwin->w_cursor.col =
+ (colnr_T)STRLEN(ml_get(curwin->w_cursor.lnum));
+ }
+ else
+ {
+ curwin->w_cursor.col = 0;
+ VIsual.col = (colnr_T)STRLEN(ml_get(VIsual.lnum));
+ }
+ VIsual_mode = 'v';
+ }
+ /* If 'selection' is "exclusive", backup one character for
+ * charwise selections. */
+ else if (VIsual_mode == 'v')
+ {
+# ifdef FEAT_VIRTUALEDIT
+ include_line_break =
+# endif
+ unadjust_for_sel();
+ }
+
+ oap->start = VIsual;
+ if (VIsual_mode == 'V')
+ oap->start.col = 0;
+ }
+#endif /* FEAT_VISUAL */
+
+ /*
+ * Set oap->start to the first position of the operated text, oap->end
+ * to the end of the operated text. w_cursor is equal to oap->start.
+ */
+ if (lt(oap->start, curwin->w_cursor))
+ {
+#ifdef FEAT_FOLDING
+ /* Include folded lines completely. */
+ if (!VIsual_active)
+ {
+ if (hasFolding(oap->start.lnum, &oap->start.lnum, NULL))
+ oap->start.col = 0;
+ if (hasFolding(curwin->w_cursor.lnum, NULL,
+ &curwin->w_cursor.lnum))
+ curwin->w_cursor.col = (colnr_T)STRLEN(ml_get_curline());
+ }
+#endif
+ oap->end = curwin->w_cursor;
+ curwin->w_cursor = oap->start;
+
+ /* w_virtcol may have been updated; if the cursor goes back to its
+ * previous position w_virtcol becomes invalid and isn't updated
+ * automatically. */
+ curwin->w_valid &= ~VALID_VIRTCOL;
+ }
+ else
+ {
+#ifdef FEAT_FOLDING
+ /* Include folded lines completely. */
+ if (!VIsual_active && oap->motion_type == MLINE)
+ {
+ if (hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum,
+ NULL))
+ curwin->w_cursor.col = 0;
+ if (hasFolding(oap->start.lnum, NULL, &oap->start.lnum))
+ oap->start.col = (colnr_T)STRLEN(ml_get(oap->start.lnum));
+ }
+#endif
+ oap->end = oap->start;
+ oap->start = curwin->w_cursor;
+ }
+
+ oap->line_count = oap->end.lnum - oap->start.lnum + 1;
+
+#ifdef FEAT_VIRTUALEDIT
+ /* Set "virtual_op" before resetting VIsual_active. */
+ virtual_op = virtual_active();
+#endif
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active || redo_VIsual_busy)
+ {
+ if (VIsual_mode == Ctrl_V) /* block mode */
+ {
+ colnr_T start, end;
+
+ oap->block_mode = TRUE;
+
+ getvvcol(curwin, &(oap->start),
+ &oap->start_vcol, NULL, &oap->end_vcol);
+ if (!redo_VIsual_busy)
+ {
+ getvvcol(curwin, &(oap->end), &start, NULL, &end);
+
+ if (start < oap->start_vcol)
+ oap->start_vcol = start;
+ if (end > oap->end_vcol)
+ {
+ if (*p_sel == 'e' && start >= 1
+ && start - 1 >= oap->end_vcol)
+ oap->end_vcol = start - 1;
+ else
+ oap->end_vcol = end;
+ }
+ }
+
+ /* if '$' was used, get oap->end_vcol from longest line */
+ if (curwin->w_curswant == MAXCOL)
+ {
+ curwin->w_cursor.col = MAXCOL;
+ oap->end_vcol = 0;
+ for (curwin->w_cursor.lnum = oap->start.lnum;
+ curwin->w_cursor.lnum <= oap->end.lnum;
+ ++curwin->w_cursor.lnum)
+ {
+ getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
+ if (end > oap->end_vcol)
+ oap->end_vcol = end;
+ }
+ }
+ else if (redo_VIsual_busy)
+ oap->end_vcol = oap->start_vcol + redo_VIsual_col - 1;
+ /*
+ * Correct oap->end.col and oap->start.col to be the
+ * upper-left and lower-right corner of the block area.
+ *
+ * (Actually, this does convert column positions into character
+ * positions)
+ */
+ curwin->w_cursor.lnum = oap->end.lnum;
+ coladvance(oap->end_vcol);
+ oap->end = curwin->w_cursor;
+
+ curwin->w_cursor = oap->start;
+ coladvance(oap->start_vcol);
+ oap->start = curwin->w_cursor;
+ }
+
+ if (!redo_VIsual_busy && !gui_yank)
+ {
+ /*
+ * Prepare to reselect and redo Visual: this is based on the
+ * size of the Visual text
+ */
+ resel_VIsual_mode = VIsual_mode;
+ if (curwin->w_curswant == MAXCOL)
+ resel_VIsual_col = MAXCOL;
+ else if (VIsual_mode == Ctrl_V)
+ resel_VIsual_col = oap->end_vcol - oap->start_vcol + 1;
+ else if (oap->line_count > 1)
+ resel_VIsual_col = oap->end.col;
+ else
+ resel_VIsual_col = oap->end.col - oap->start.col + 1;
+ resel_VIsual_line_count = oap->line_count;
+ }
+
+ /* can't redo yank (unless 'y' is in 'cpoptions') and ":" */
+ if ((vim_strchr(p_cpo, CPO_YANK) != NULL || oap->op_type != OP_YANK)
+ && oap->op_type != OP_COLON
+#ifdef FEAT_FOLDING
+ && oap->op_type != OP_FOLD
+ && oap->op_type != OP_FOLDOPEN
+ && oap->op_type != OP_FOLDOPENREC
+ && oap->op_type != OP_FOLDCLOSE
+ && oap->op_type != OP_FOLDCLOSEREC
+ && oap->op_type != OP_FOLDDEL
+ && oap->op_type != OP_FOLDDELREC
+#endif
+ && oap->motion_force == NUL
+ )
+ {
+ /* Prepare for redoing. Only use the nchar field for "r",
+ * otherwise it might be the second char of the operator. */
+ prep_redo(oap->regname, 0L, NUL, 'v',
+ get_op_char(oap->op_type),
+ get_extra_op_char(oap->op_type),
+ oap->op_type == OP_REPLACE ? cap->nchar : NUL);
+ if (!redo_VIsual_busy)
+ {
+ redo_VIsual_mode = resel_VIsual_mode;
+ redo_VIsual_col = resel_VIsual_col;
+ redo_VIsual_line_count = resel_VIsual_line_count;
+ redo_VIsual_count = cap->count0;
+ }
+ }
+
+ /*
+ * oap->inclusive defaults to TRUE.
+ * If oap->end is on a NUL (empty line) oap->inclusive becomes
+ * FALSE. This makes "d}P" and "v}dP" work the same.
+ */
+ if (oap->motion_force == NUL || oap->motion_type == MLINE)
+ oap->inclusive = TRUE;
+ if (VIsual_mode == 'V')
+ oap->motion_type = MLINE;
+ else
+ {
+ oap->motion_type = MCHAR;
+ if (VIsual_mode != Ctrl_V && *ml_get_pos(&(oap->end)) == NUL
+# ifdef FEAT_VIRTUALEDIT
+ && (include_line_break || !virtual_op)
+# endif
+ )
+ {
+ oap->inclusive = FALSE;
+ /* Try to include the newline, unless it's an operator
+ * that works on lines only */
+ if (*p_sel != 'o'
+ && !op_on_lines(oap->op_type)
+ && oap->end.lnum < curbuf->b_ml.ml_line_count)
+ {
+ ++oap->end.lnum;
+ oap->end.col = 0;
+# ifdef FEAT_VIRTUALEDIT
+ oap->end.coladd = 0;
+# endif
+ ++oap->line_count;
+ }
+ }
+ }
+
+ redo_VIsual_busy = FALSE;
+ /*
+ * Switch Visual off now, so screen updating does
+ * not show inverted text when the screen is redrawn.
+ * With OP_YANK and sometimes with OP_COLON and OP_FILTER there is
+ * no screen redraw, so it is done here to remove the inverted
+ * part.
+ */
+ if (!gui_yank)
+ {
+ VIsual_active = FALSE;
+# ifdef FEAT_MOUSE
+ setmouse();
+ mouse_dragging = 0;
+# endif
+ if (p_smd)
+ clear_cmdline = TRUE; /* unshow visual mode later */
+#ifdef FEAT_CMDL_INFO
+ else
+ clear_showcmd();
+#endif
+ if ((oap->op_type == OP_YANK
+ || oap->op_type == OP_COLON
+ || oap->op_type == OP_FILTER)
+ && oap->motion_force == NUL)
+ redraw_curbuf_later(INVERTED);
+ }
+ }
+#endif
+
+#ifdef FEAT_MBYTE
+ /* Include the trailing byte of a multi-byte char. */
+ if (has_mbyte && oap->inclusive)
+ {
+ int l;
+
+ l = (*mb_ptr2len_check)(ml_get_pos(&oap->end));
+ if (l > 1)
+ oap->end.col += l - 1;
+ }
+#endif
+ curwin->w_set_curswant = TRUE;
+
+ /*
+ * oap->empty is set when start and end are the same. The inclusive
+ * flag affects this too, unless yanking and the end is on a NUL.
+ */
+ oap->empty = (oap->motion_type == MCHAR
+ && (!oap->inclusive
+ || (oap->op_type == OP_YANK
+ && gchar_pos(&oap->end) == NUL))
+ && equalpos(oap->start, oap->end)
+#ifdef FEAT_VIRTUALEDIT
+ && !(virtual_op && oap->start.coladd != oap->end.coladd)
+#endif
+ );
+ /*
+ * For delete, change and yank, it's an error to operate on an
+ * empty region, when 'E' included in 'cpoptions' (Vi compatible).
+ */
+ empty_region_error = (oap->empty
+ && vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL);
+
+#ifdef FEAT_VISUAL
+ /* Force a redraw when operating on an empty Visual region, when
+ * 'modifiable is off or creating a fold. */
+ if (oap->is_VIsual && (oap->empty || !curbuf->b_p_ma
+# ifdef FEAT_FOLDING
+ || oap->op_type == OP_FOLD
+# endif
+ ))
+ redraw_curbuf_later(INVERTED);
+#endif
+
+ /*
+ * If the end of an operator is in column one while oap->motion_type
+ * is MCHAR and oap->inclusive is FALSE, we put op_end after the last
+ * character in the previous line. If op_start is on or before the
+ * first non-blank in the line, the operator becomes linewise
+ * (strange, but that's the way vi does it).
+ */
+ if ( oap->motion_type == MCHAR
+ && oap->inclusive == FALSE
+ && !(cap->retval & CA_NO_ADJ_OP_END)
+ && oap->end.col == 0
+#ifdef FEAT_VISUAL
+ && (!oap->is_VIsual || *p_sel == 'o')
+#endif
+ && oap->line_count > 1)
+ {
+ oap->end_adjusted = TRUE; /* remember that we did this */
+ --oap->line_count;
+ --oap->end.lnum;
+ if (inindent(0))
+ oap->motion_type = MLINE;
+ else
+ {
+ oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+ if (oap->end.col)
+ {
+ --oap->end.col;
+ oap->inclusive = TRUE;
+ }
+ }
+ }
+ else
+ oap->end_adjusted = FALSE;
+
+ switch (oap->op_type)
+ {
+ case OP_LSHIFT:
+ case OP_RSHIFT:
+ op_shift(oap, TRUE,
+#ifdef FEAT_VISUAL
+ oap->is_VIsual ? (int)cap->count1 :
+#endif
+ 1);
+ auto_format(FALSE, TRUE);
+ break;
+
+ case OP_JOIN_NS:
+ case OP_JOIN:
+ if (oap->line_count < 2)
+ oap->line_count = 2;
+ if (curwin->w_cursor.lnum + oap->line_count - 1 >
+ curbuf->b_ml.ml_line_count)
+ beep_flush();
+ else
+ {
+ do_do_join(oap->line_count, oap->op_type == OP_JOIN);
+ auto_format(FALSE, TRUE);
+ }
+ break;
+
+ case OP_DELETE:
+#ifdef FEAT_VISUAL
+ VIsual_reselect = FALSE; /* don't reselect now */
+#endif
+ if (empty_region_error)
+ vim_beep();
+ else
+ {
+ (void)op_delete(oap);
+ if (oap->motion_type == MLINE && has_format_option(FO_AUTO))
+ u_save_cursor(); /* cursor line wasn't saved yet */
+ auto_format(FALSE, TRUE);
+ }
+ break;
+
+ case OP_YANK:
+ if (empty_region_error)
+ {
+ if (!gui_yank)
+ vim_beep();
+ }
+ else
+ (void)op_yank(oap, FALSE, !gui_yank);
+ check_cursor_col();
+ break;
+
+ case OP_CHANGE:
+#ifdef FEAT_VISUAL
+ VIsual_reselect = FALSE; /* don't reselect now */
+#endif
+ if (empty_region_error)
+ vim_beep();
+ else
+ {
+ /* This is a new edit command, not a restart. Need to
+ * remember it to make 'insertmode' work with mappings for
+ * Visual mode. But do this only once and not when typed and
+ * 'insertmode' isn't set. */
+ if (p_im || !KeyTyped)
+ restart_edit_save = restart_edit;
+ else
+ restart_edit_save = 0;
+ restart_edit = 0;
+ /* Reset finish_op now, don't want it set inside edit(). */
+ finish_op = FALSE;
+ if (op_change(oap)) /* will call edit() */
+ cap->retval |= CA_COMMAND_BUSY;
+ if (restart_edit == 0)
+ restart_edit = restart_edit_save;
+ }
+ break;
+
+ case OP_FILTER:
+ if (vim_strchr(p_cpo, CPO_FILTER) != NULL)
+ AppendToRedobuff((char_u *)"!\r"); /* use any last used !cmd */
+ else
+ bangredo = TRUE; /* do_bang() will put cmd in redo buffer */
+
+ case OP_INDENT:
+ case OP_COLON:
+
+#if defined(FEAT_LISP) || defined(FEAT_CINDENT)
+ /*
+ * If 'equalprg' is empty, do the indenting internally.
+ */
+ if (oap->op_type == OP_INDENT && *get_equalprg() == NUL)
+ {
+# ifdef FEAT_LISP
+ if (curbuf->b_p_lisp)
+ {
+ op_reindent(oap, get_lisp_indent);
+ break;
+ }
+# endif
+# ifdef FEAT_CINDENT
+ op_reindent(oap,
+# ifdef FEAT_EVAL
+ *curbuf->b_p_inde != NUL ? get_expr_indent :
+# endif
+ get_c_indent);
+ break;
+# endif
+ }
+#endif
+
+ op_colon(oap);
+ break;
+
+ case OP_TILDE:
+ case OP_UPPER:
+ case OP_LOWER:
+ case OP_ROT13:
+ if (empty_region_error)
+ vim_beep();
+ else
+ op_tilde(oap);
+ check_cursor_col();
+ break;
+
+ case OP_FORMAT:
+ if (*p_fp != NUL)
+ op_colon(oap); /* use external command */
+ else
+ op_format(oap, FALSE); /* use internal function */
+ break;
+
+ case OP_FORMAT2:
+ op_format(oap, TRUE); /* use internal function */
+ break;
+
+ case OP_INSERT:
+ case OP_APPEND:
+#ifdef FEAT_VISUAL
+ VIsual_reselect = FALSE; /* don't reselect now */
+#endif
+#ifdef FEAT_VISUALEXTRA
+ if (empty_region_error)
+ vim_beep();
+ else
+ {
+ /* This is a new edit command, not a restart. Need to
+ * remember it to make 'insertmode' work with mappings for
+ * Visual mode. But do this only once. */
+ restart_edit_save = restart_edit;
+ restart_edit = 0;
+
+ op_insert(oap, cap->count1);
+
+ /* TODO: when inserting in several lines, should format all
+ * the lines. */
+ auto_format(FALSE, TRUE);
+
+ if (restart_edit == 0)
+ restart_edit = restart_edit_save;
+ }
+#else
+ vim_beep();
+#endif
+ break;
+
+ case OP_REPLACE:
+#ifdef FEAT_VISUAL
+ VIsual_reselect = FALSE; /* don't reselect now */
+#endif
+#ifdef FEAT_VISUALEXTRA
+ if (empty_region_error)
+#endif
+ vim_beep();
+#ifdef FEAT_VISUALEXTRA
+ else
+ op_replace(oap, cap->nchar);
+#endif
+ break;
+
+#ifdef FEAT_FOLDING
+ case OP_FOLD:
+ VIsual_reselect = FALSE; /* don't reselect now */
+ foldCreate(oap->start.lnum, oap->end.lnum);
+ break;
+
+ case OP_FOLDOPEN:
+ case OP_FOLDOPENREC:
+ case OP_FOLDCLOSE:
+ case OP_FOLDCLOSEREC:
+ VIsual_reselect = FALSE; /* don't reselect now */
+ opFoldRange(oap->start.lnum, oap->end.lnum,
+ oap->op_type == OP_FOLDOPEN
+ || oap->op_type == OP_FOLDOPENREC,
+ oap->op_type == OP_FOLDOPENREC
+ || oap->op_type == OP_FOLDCLOSEREC,
+ oap->is_VIsual);
+ break;
+
+ case OP_FOLDDEL:
+ case OP_FOLDDELREC:
+ VIsual_reselect = FALSE; /* don't reselect now */
+ deleteFold(oap->start.lnum, oap->end.lnum,
+ oap->op_type == OP_FOLDDELREC, oap->is_VIsual);
+ break;
+#endif
+ default:
+ clearopbeep(oap);
+ }
+#ifdef FEAT_VIRTUALEDIT
+ virtual_op = MAYBE;
+#endif
+ if (!gui_yank)
+ {
+ /*
+ * if 'sol' not set, go back to old column for some commands
+ */
+ if (!p_sol && oap->motion_type == MLINE && !oap->end_adjusted
+ && (oap->op_type == OP_LSHIFT || oap->op_type == OP_RSHIFT
+ || oap->op_type == OP_DELETE))
+ coladvance(curwin->w_curswant = old_col);
+ }
+ else
+ {
+ curwin->w_cursor = old_cursor;
+ }
+#ifdef FEAT_VISUAL
+ oap->block_mode = FALSE;
+#endif
+ clearop(oap);
+ }
+}
+
+/*
+ * Handle indent and format operators and visual mode ":".
+ */
+ static void
+op_colon(oap)
+ oparg_T *oap;
+{
+ stuffcharReadbuff(':');
+#ifdef FEAT_VISUAL
+ if (oap->is_VIsual)
+ stuffReadbuff((char_u *)"'<,'>");
+ else
+#endif
+ {
+ /*
+ * Make the range look nice, so it can be repeated.
+ */
+ if (oap->start.lnum == curwin->w_cursor.lnum)
+ stuffcharReadbuff('.');
+ else
+ stuffnumReadbuff((long)oap->start.lnum);
+ if (oap->end.lnum != oap->start.lnum)
+ {
+ stuffcharReadbuff(',');
+ if (oap->end.lnum == curwin->w_cursor.lnum)
+ stuffcharReadbuff('.');
+ else if (oap->end.lnum == curbuf->b_ml.ml_line_count)
+ stuffcharReadbuff('$');
+ else if (oap->start.lnum == curwin->w_cursor.lnum)
+ {
+ stuffReadbuff((char_u *)".+");
+ stuffnumReadbuff((long)oap->line_count - 1);
+ }
+ else
+ stuffnumReadbuff((long)oap->end.lnum);
+ }
+ }
+ if (oap->op_type != OP_COLON)
+ stuffReadbuff((char_u *)"!");
+ if (oap->op_type == OP_INDENT)
+ {
+#ifndef FEAT_CINDENT
+ if (*get_equalprg() == NUL)
+ stuffReadbuff((char_u *)"indent");
+ else
+#endif
+ stuffReadbuff(get_equalprg());
+ stuffReadbuff((char_u *)"\n");
+ }
+ else if (oap->op_type == OP_FORMAT)
+ {
+ if (*p_fp == NUL)
+ stuffReadbuff((char_u *)"fmt");
+ else
+ stuffReadbuff(p_fp);
+ stuffReadbuff((char_u *)"\n");
+ }
+
+ /*
+ * do_cmdline() does the rest
+ */
+}
+
+#if defined(FEAT_MOUSE) || defined(PROTO)
+/*
+ * Do the appropriate action for the current mouse click in the current mode.
+ * Not used for Command-line mode.
+ *
+ * Normal Mode:
+ * event modi- position visual change action
+ * fier cursor window
+ * left press - yes end yes
+ * left press C yes end yes "^]" (2)
+ * left press S yes end yes "*" (2)
+ * left drag - yes start if moved no
+ * left relse - yes start if moved no
+ * middle press - yes if not active no put register
+ * middle press - yes if active no yank and put
+ * right press - yes start or extend yes
+ * right press S yes no change yes "#" (2)
+ * right drag - yes extend no
+ * right relse - yes extend no
+ *
+ * Insert or Replace Mode:
+ * event modi- position visual change action
+ * fier cursor window
+ * left press - yes (cannot be active) yes
+ * left press C yes (cannot be active) yes "CTRL-O^]" (2)
+ * left press S yes (cannot be active) yes "CTRL-O*" (2)
+ * left drag - yes start or extend (1) no CTRL-O (1)
+ * left relse - yes start or extend (1) no CTRL-O (1)
+ * middle press - no (cannot be active) no put register
+ * right press - yes start or extend yes CTRL-O
+ * right press S yes (cannot be active) yes "CTRL-O#" (2)
+ *
+ * (1) only if mouse pointer moved since press
+ * (2) only if click is in same buffer
+ *
+ * Return TRUE if start_arrow() should be called for edit mode.
+ */
+ int
+do_mouse(oap, c, dir, count, fixindent)
+ oparg_T *oap; /* operator argument, can be NULL */
+ int c; /* K_LEFTMOUSE, etc */
+ int dir; /* Direction to 'put' if necessary */
+ long count;
+ int fixindent; /* PUT_FIXINDENT if fixing indent necessary */
+{
+ static int do_always = FALSE; /* ignore 'mouse' setting next time */
+ static int got_click = FALSE; /* got a click some time back */
+
+ int which_button; /* MOUSE_LEFT, _MIDDLE or _RIGHT */
+ int is_click; /* If FALSE it's a drag or release event */
+ int is_drag; /* If TRUE it's a drag event */
+ int jump_flags = 0; /* flags for jump_to_mouse() */
+ pos_T start_visual;
+ int moved; /* Has cursor moved? */
+ int in_status_line; /* mouse in status line */
+#ifdef FEAT_VERTSPLIT
+ int in_sep_line; /* mouse in vertical separator line */
+#endif
+ int c1, c2;
+#if defined(FEAT_FOLDING)
+ pos_T save_cursor;
+#endif
+ win_T *old_curwin = curwin;
+#ifdef FEAT_VISUAL
+ static pos_T orig_cursor;
+ colnr_T leftcol, rightcol;
+ pos_T end_visual;
+ int diff;
+ int old_active = VIsual_active;
+ int old_mode = VIsual_mode;
+#endif
+ int regname;
+
+#if defined(FEAT_FOLDING)
+ save_cursor = curwin->w_cursor;
+#endif
+
+ /*
+ * When GUI is active, always recognize mouse events, otherwise:
+ * - Ignore mouse event in normal mode if 'mouse' doesn't include 'n'.
+ * - Ignore mouse event in visual mode if 'mouse' doesn't include 'v'.
+ * - For command line and insert mode 'mouse' is checked before calling
+ * do_mouse().
+ */
+ if (do_always)
+ do_always = FALSE;
+ else
+#ifdef FEAT_GUI
+ if (!gui.in_use)
+#endif
+ {
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ if (!mouse_has(MOUSE_VISUAL))
+ return FALSE;
+ }
+ else
+#endif
+ if (State == NORMAL && !mouse_has(MOUSE_NORMAL))
+ return FALSE;
+ }
+
+ which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag);
+
+#ifdef FEAT_MOUSESHAPE
+ /* May have stopped dragging the status or separator line. The pointer is
+ * most likely still on the status or separator line. */
+ if (!is_drag && drag_status_line)
+ {
+ drag_status_line = FALSE;
+ update_mouseshape(SHAPE_IDX_STATUS);
+ }
+# ifdef FEAT_VERTSPLIT
+ if (!is_drag && drag_sep_line)
+ {
+ drag_sep_line = FALSE;
+ update_mouseshape(SHAPE_IDX_VSEP);
+ }
+# endif
+#endif
+
+ /*
+ * Ignore drag and release events if we didn't get a click.
+ */
+ if (is_click)
+ got_click = TRUE;
+ else
+ {
+ if (!got_click) /* didn't get click, ignore */
+ return FALSE;
+ if (!is_drag) /* release, reset got_click */
+ got_click = FALSE;
+ }
+
+ /*
+ * ALT is currently ignored
+ */
+ if ((mod_mask & MOD_MASK_ALT))
+ return FALSE;
+
+ /*
+ * CTRL right mouse button does CTRL-T
+ */
+ if (is_click && (mod_mask & MOD_MASK_CTRL) && which_button == MOUSE_RIGHT)
+ {
+ if (State & INSERT)
+ stuffcharReadbuff(Ctrl_O);
+ if (count > 1)
+ stuffnumReadbuff(count);
+ stuffcharReadbuff(Ctrl_T);
+ got_click = FALSE; /* ignore drag&release now */
+ return FALSE;
+ }
+
+ /*
+ * CTRL only works with left mouse button
+ */
+ if ((mod_mask & MOD_MASK_CTRL) && which_button != MOUSE_LEFT)
+ return FALSE;
+
+ /*
+ * When a modifier is down, ignore drag and release events, as well as
+ * multiple clicks and the middle mouse button.
+ * Accept shift-leftmouse drags when 'mousemodel' is "popup.*".
+ */
+ if ((mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT))
+ && (!is_click
+ || (mod_mask & MOD_MASK_MULTI_CLICK)
+ || which_button == MOUSE_MIDDLE)
+ && !((mod_mask & MOD_MASK_SHIFT)
+ && mouse_model_popup()
+ && which_button == MOUSE_LEFT)
+ )
+ return FALSE;
+
+ /*
+ * If the button press was used as the movement command for an operator
+ * (eg "d<MOUSE>"), or it is the middle button that is held down, ignore
+ * drag/release events.
+ */
+ if (!is_click && which_button == MOUSE_MIDDLE)
+ return FALSE;
+
+ if (oap != NULL)
+ regname = oap->regname;
+ else
+ regname = 0;
+
+ /*
+ * Middle mouse button does a 'put' of the selected text
+ */
+ if (which_button == MOUSE_MIDDLE)
+ {
+ if (State == NORMAL)
+ {
+ /*
+ * If an operator was pending, we don't know what the user wanted
+ * to do. Go back to normal mode: Clear the operator and beep().
+ */
+ if (oap != NULL && oap->op_type != OP_NOP)
+ {
+ clearopbeep(oap);
+ return FALSE;
+ }
+
+#ifdef FEAT_VISUAL
+ /*
+ * If visual was active, yank the highlighted text and put it
+ * before the mouse pointer position.
+ */
+ if (VIsual_active)
+ {
+ stuffcharReadbuff('y');
+ stuffcharReadbuff(K_MIDDLEMOUSE);
+ do_always = TRUE; /* ignore 'mouse' setting next time */
+ return FALSE;
+ }
+#endif
+ /*
+ * The rest is below jump_to_mouse()
+ */
+ }
+
+ else if ((State & INSERT) == 0)
+ return FALSE;
+
+ /*
+ * Middle click in insert mode doesn't move the mouse, just insert the
+ * contents of a register. '.' register is special, can't insert that
+ * with do_put().
+ * Also paste at the cursor if the current mode isn't in 'mouse' (only
+ * happens for the GUI).
+ */
+ if ((State & INSERT) || !mouse_has(MOUSE_NORMAL))
+ {
+ if (regname == '.')
+ insert_reg(regname, TRUE);
+ else
+ {
+#ifdef FEAT_CLIPBOARD
+ if (clip_star.available && regname == 0)
+ regname = '*';
+#endif
+ if ((State & REPLACE_FLAG) && !yank_register_mline(regname))
+ insert_reg(regname, TRUE);
+ else
+ {
+ do_put(regname, BACKWARD, 1L, fixindent | PUT_CURSEND);
+
+ /* Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r */
+ AppendCharToRedobuff(Ctrl_R);
+ AppendCharToRedobuff(fixindent ? Ctrl_P : Ctrl_O);
+ AppendCharToRedobuff(regname == 0 ? '"' : regname);
+ }
+ }
+ return FALSE;
+ }
+ }
+
+ /* When dragging or button-up stay in the same window. */
+ if (!is_click)
+ jump_flags |= MOUSE_FOCUS | MOUSE_DID_MOVE;
+
+ start_visual.lnum = 0;
+
+ /*
+ * When 'mousemodel' is "popup" or "popup_setpos", translate mouse events:
+ * right button up -> pop-up menu
+ * shift-left button -> right button
+ */
+ if (mouse_model_popup())
+ {
+ if (which_button == MOUSE_RIGHT
+ && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)))
+ {
+ /*
+ * NOTE: Ignore right button down and drag mouse events.
+ * Windows only shows the popup menu on the button up event.
+ */
+#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON)
+ if (!is_click)
+ return FALSE;
+#endif
+#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN)
+ if (is_click || is_drag)
+ return FALSE;
+#endif
+#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
+ || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
+ || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON)
+ if (gui.in_use)
+ {
+ jump_flags = 0;
+ if (STRCMP(p_mousem, "popup_setpos") == 0)
+ {
+ /* First set the cursor position before showing the popup
+ * menu. */
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ pos_T m_pos;
+
+ /*
+ * set MOUSE_MAY_STOP_VIS if we are outside the
+ * selection or the current window (might have false
+ * negative here)
+ */
+ if (mouse_row < W_WINROW(curwin)
+ || mouse_row
+ > (W_WINROW(curwin) + curwin->w_height))
+ jump_flags = MOUSE_MAY_STOP_VIS;
+ else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER)
+ jump_flags = MOUSE_MAY_STOP_VIS;
+ else
+ {
+ if ((lt(curwin->w_cursor, VIsual)
+ && (lt(m_pos, curwin->w_cursor)
+ || lt(VIsual, m_pos)))
+ || (lt(VIsual, curwin->w_cursor)
+ && (lt(m_pos, VIsual)
+ || lt(curwin->w_cursor, m_pos))))
+ {
+ jump_flags = MOUSE_MAY_STOP_VIS;
+ }
+ else if (VIsual_mode == Ctrl_V)
+ {
+ getvcols(curwin, &curwin->w_cursor, &VIsual,
+ &leftcol, &rightcol);
+ getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL);
+ if (m_pos.col < leftcol || m_pos.col > rightcol)
+ jump_flags = MOUSE_MAY_STOP_VIS;
+ }
+ }
+ }
+ else
+ jump_flags = MOUSE_MAY_STOP_VIS;
+#endif
+ }
+ if (jump_flags)
+ {
+ jump_flags = jump_to_mouse(jump_flags, NULL, which_button);
+ update_curbuf(
+#ifdef FEAT_VISUAL
+ VIsual_active ? INVERTED :
+#endif
+ VALID);
+ setcursor();
+ out_flush(); /* Update before showing popup menu */
+ }
+# ifdef FEAT_MENU
+ gui_show_popupmenu();
+# endif
+ return (jump_flags & CURSOR_MOVED) != 0;
+ }
+ else
+ return FALSE;
+#else
+ return FALSE;
+#endif
+ }
+ if (which_button == MOUSE_LEFT && (mod_mask & MOD_MASK_SHIFT))
+ {
+ which_button = MOUSE_RIGHT;
+ mod_mask &= ~MOD_MASK_SHIFT;
+ }
+ }
+
+#ifdef FEAT_VISUAL
+ if ((State & (NORMAL | INSERT))
+ && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)))
+ {
+ if (which_button == MOUSE_LEFT)
+ {
+ if (is_click)
+ {
+ /* stop Visual mode for a left click in a window, but not when
+ * on a status line */
+ if (VIsual_active)
+ jump_flags |= MOUSE_MAY_STOP_VIS;
+ }
+ else if (mouse_has(MOUSE_VISUAL))
+ jump_flags |= MOUSE_MAY_VIS;
+ }
+ else if (which_button == MOUSE_RIGHT)
+ {
+ if (is_click && VIsual_active)
+ {
+ /*
+ * Remember the start and end of visual before moving the
+ * cursor.
+ */
+ if (lt(curwin->w_cursor, VIsual))
+ {
+ start_visual = curwin->w_cursor;
+ end_visual = VIsual;
+ }
+ else
+ {
+ start_visual = VIsual;
+ end_visual = curwin->w_cursor;
+ }
+ }
+ jump_flags |= MOUSE_FOCUS;
+ if (mouse_has(MOUSE_VISUAL))
+ jump_flags |= MOUSE_MAY_VIS;
+ }
+ }
+#endif
+
+ /*
+ * If an operator is pending, ignore all drags and releases until the
+ * next mouse click.
+ */
+ if (!is_drag && oap != NULL && oap->op_type != OP_NOP)
+ {
+ got_click = FALSE;
+ oap->motion_type = MCHAR;
+ }
+
+ /* When releasing the button let jump_to_mouse() know. */
+ if (!is_click && !is_drag)
+ jump_flags |= MOUSE_RELEASED;
+
+ /*
+ * JUMP!
+ */
+ jump_flags = jump_to_mouse(jump_flags,
+ oap == NULL ? NULL : &(oap->inclusive), which_button);
+ moved = (jump_flags & CURSOR_MOVED);
+ in_status_line = (jump_flags & IN_STATUS_LINE);
+#ifdef FEAT_VERTSPLIT
+ in_sep_line = (jump_flags & IN_SEP_LINE);
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans && isNetbeansBuffer(curbuf)
+ && !(jump_flags & (IN_STATUS_LINE | IN_SEP_LINE)))
+ {
+ int key = KEY2TERMCAP1(c);
+
+ if (key == (int)KE_LEFTRELEASE || key == (int)KE_MIDDLERELEASE
+ || key == (int)KE_RIGHTRELEASE)
+ netbeans_button_release(which_button);
+ }
+#endif
+
+ /* When jumping to another window, clear a pending operator. That's a bit
+ * friendlier than beeping and not jumping to that window. */
+ if (curwin != old_curwin && oap != NULL && oap->op_type != OP_NOP)
+ clearop(oap);
+
+#ifdef FEAT_FOLDING
+ if (mod_mask == 0
+ && !is_drag
+ && (jump_flags & (MOUSE_FOLD_CLOSE | MOUSE_FOLD_OPEN))
+ && which_button == MOUSE_LEFT)
+ {
+ /* open or close a fold at this line */
+ if (jump_flags & MOUSE_FOLD_OPEN)
+ openFold(curwin->w_cursor.lnum, 1L);
+ else
+ closeFold(curwin->w_cursor.lnum, 1L);
+ /* don't move the cursor if still in the same window */
+ if (curwin == old_curwin)
+ curwin->w_cursor = save_cursor;
+ }
+#endif
+
+#if defined(FEAT_CLIPBOARD) && defined(FEAT_CMDWIN)
+ if ((jump_flags & IN_OTHER_WIN) && !VIsual_active && clip_star.available)
+ {
+ clip_modeless(which_button, is_click, is_drag);
+ return FALSE;
+ }
+#endif
+
+#ifdef FEAT_VISUAL
+ /* Set global flag that we are extending the Visual area with mouse
+ * dragging; temporarily mimimize 'scrolloff'. */
+ if (VIsual_active && is_drag && p_so)
+ {
+ /* In the very first line, allow scrolling one line */
+ if (mouse_row == 0)
+ mouse_dragging = 2;
+ else
+ mouse_dragging = 1;
+ }
+
+ /* When dragging the mouse above the window, scroll down. */
+ if (is_drag && mouse_row < 0 && !in_status_line)
+ {
+ scroll_redraw(FALSE, 1L);
+ mouse_row = 0;
+ }
+
+ if (start_visual.lnum) /* right click in visual mode */
+ {
+ /*
+ * In Visual-block mode, divide the area in four, pick up the corner
+ * that is in the quarter that the cursor is in.
+ */
+ if (VIsual_mode == Ctrl_V)
+ {
+ getvcols(curwin, &start_visual, &end_visual, &leftcol, &rightcol);
+ if (curwin->w_curswant > (leftcol + rightcol) / 2)
+ end_visual.col = leftcol;
+ else
+ end_visual.col = rightcol;
+ if (curwin->w_cursor.lnum <
+ (start_visual.lnum + end_visual.lnum) / 2)
+ end_visual.lnum = end_visual.lnum;
+ else
+ end_visual.lnum = start_visual.lnum;
+
+ /* move VIsual to the right column */
+ start_visual = curwin->w_cursor; /* save the cursor pos */
+ curwin->w_cursor = end_visual;
+ coladvance(end_visual.col);
+ VIsual = curwin->w_cursor;
+ curwin->w_cursor = start_visual; /* restore the cursor */
+ }
+ else
+ {
+ /*
+ * If the click is before the start of visual, change the start.
+ * If the click is after the end of visual, change the end. If
+ * the click is inside the visual, change the closest side.
+ */
+ if (lt(curwin->w_cursor, start_visual))
+ VIsual = end_visual;
+ else if (lt(end_visual, curwin->w_cursor))
+ VIsual = start_visual;
+ else
+ {
+ /* In the same line, compare column number */
+ if (end_visual.lnum == start_visual.lnum)
+ {
+ if (curwin->w_cursor.col - start_visual.col >
+ end_visual.col - curwin->w_cursor.col)
+ VIsual = start_visual;
+ else
+ VIsual = end_visual;
+ }
+
+ /* In different lines, compare line number */
+ else
+ {
+ diff = (curwin->w_cursor.lnum - start_visual.lnum) -
+ (end_visual.lnum - curwin->w_cursor.lnum);
+
+ if (diff > 0) /* closest to end */
+ VIsual = start_visual;
+ else if (diff < 0) /* closest to start */
+ VIsual = end_visual;
+ else /* in the middle line */
+ {
+ if (curwin->w_cursor.col <
+ (start_visual.col + end_visual.col) / 2)
+ VIsual = end_visual;
+ else
+ VIsual = start_visual;
+ }
+ }
+ }
+ }
+ }
+ /*
+ * If Visual mode started in insert mode, execute "CTRL-O"
+ */
+ else if ((State & INSERT) && VIsual_active)
+ stuffcharReadbuff(Ctrl_O);
+#endif
+
+ /*
+ * Middle mouse click: Put text before cursor.
+ */
+ if (which_button == MOUSE_MIDDLE)
+ {
+#ifdef FEAT_CLIPBOARD
+ if (clip_star.available && regname == 0)
+ regname = '*';
+#endif
+ if (yank_register_mline(regname))
+ {
+ if (mouse_past_bottom)
+ dir = FORWARD;
+ }
+ else if (mouse_past_eol)
+ dir = FORWARD;
+
+ if (fixindent)
+ {
+ c1 = (dir == BACKWARD) ? '[' : ']';
+ c2 = 'p';
+ }
+ else
+ {
+ c1 = (dir == FORWARD) ? 'p' : 'P';
+ c2 = NUL;
+ }
+ prep_redo(regname, count, NUL, c1, NUL, c2, NUL);
+
+ /*
+ * Remember where the paste started, so in edit() Insstart can be set
+ * to this position
+ */
+ if (restart_edit != 0)
+ where_paste_started = curwin->w_cursor;
+ do_put(regname, dir, count, fixindent | PUT_CURSEND);
+ }
+
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ /*
+ * Ctrl-Mouse click or double click in a quickfix window jumps to the
+ * error under the mouse pointer.
+ */
+ else if (((mod_mask & MOD_MASK_CTRL)
+ || (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
+ && bt_quickfix(curbuf))
+ {
+ if (State & INSERT)
+ stuffcharReadbuff(Ctrl_O);
+ stuffReadbuff((char_u *)":.cc\n");
+ got_click = FALSE; /* ignore drag&release now */
+ }
+#endif
+
+ /*
+ * Ctrl-Mouse click (or double click in a help window) jumps to the tag
+ * under the mouse pointer.
+ */
+ else if ((mod_mask & MOD_MASK_CTRL) || (curbuf->b_help
+ && (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK))
+ {
+ if (State & INSERT)
+ stuffcharReadbuff(Ctrl_O);
+ stuffcharReadbuff(Ctrl_RSB);
+ got_click = FALSE; /* ignore drag&release now */
+ }
+
+ /*
+ * Shift-Mouse click searches for the next occurrence of the word under
+ * the mouse pointer
+ */
+ else if ((mod_mask & MOD_MASK_SHIFT))
+ {
+ if (State & INSERT
+#ifdef FEAT_VISUAL
+ || (VIsual_active && VIsual_select)
+#endif
+ )
+ stuffcharReadbuff(Ctrl_O);
+ if (which_button == MOUSE_LEFT)
+ stuffcharReadbuff('*');
+ else /* MOUSE_RIGHT */
+ stuffcharReadbuff('#');
+ }
+
+ /* Handle double clicks, unless on status line */
+ else if (in_status_line)
+ {
+#ifdef FEAT_MOUSESHAPE
+ if ((is_drag || is_click) && !drag_status_line)
+ {
+ drag_status_line = TRUE;
+ update_mouseshape(-1);
+ }
+#endif
+ }
+#ifdef FEAT_VERTSPLIT
+ else if (in_sep_line)
+ {
+# ifdef FEAT_MOUSESHAPE
+ if ((is_drag || is_click) && !drag_sep_line)
+ {
+ drag_sep_line = TRUE;
+ update_mouseshape(-1);
+ }
+# endif
+ }
+#endif
+#ifdef FEAT_VISUAL
+ else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT))
+ && mouse_has(MOUSE_VISUAL))
+ {
+ if (is_click || !VIsual_active)
+ {
+ if (VIsual_active)
+ orig_cursor = VIsual;
+ else
+ {
+ check_visual_highlight();
+ VIsual = curwin->w_cursor;
+ orig_cursor = VIsual;
+ VIsual_active = TRUE;
+ VIsual_reselect = TRUE;
+ /* start Select mode if 'selectmode' contains "mouse" */
+ may_start_select('o');
+ setmouse();
+ }
+ if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
+ VIsual_mode = 'v';
+ else if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK)
+ VIsual_mode = 'V';
+ else if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK)
+ VIsual_mode = Ctrl_V;
+#ifdef FEAT_CLIPBOARD
+ /* Make sure the clipboard gets updated. Needed because start and
+ * end may still be the same, and the selection needs to be owned */
+ clip_star.vmode = NUL;
+#endif
+ }
+ /*
+ * A double click selects a word or a block.
+ */
+ if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
+ {
+ pos_T *pos = NULL;
+
+ if (is_click)
+ {
+ /* If the character under the cursor (skipping white space) is
+ * not a word character, try finding a match and select a (),
+ * {}, [], #if/#endif, etc. block. */
+ end_visual = curwin->w_cursor;
+ while (vim_iswhite(gchar_pos(&end_visual)))
+ inc(&end_visual);
+ if (oap != NULL)
+ oap->motion_type = MCHAR;
+ if (oap != NULL
+ && VIsual_mode == 'v'
+ && !vim_iswordc(gchar_pos(&end_visual))
+ && equalpos(curwin->w_cursor, VIsual)
+ && (pos = findmatch(oap, NUL)) != NULL)
+ {
+ curwin->w_cursor = *pos;
+ if (oap->motion_type == MLINE)
+ VIsual_mode = 'V';
+ else if (*p_sel == 'e')
+ {
+ if (lt(curwin->w_cursor, VIsual))
+ ++VIsual.col;
+ else
+ ++curwin->w_cursor.col;
+ }
+ }
+ }
+
+ if (pos == NULL && (is_click || is_drag))
+ {
+ /* When not found a match or when dragging: extend to include
+ * a word. */
+ if (lt(curwin->w_cursor, orig_cursor))
+ {
+ find_start_of_word(&curwin->w_cursor);
+ find_end_of_word(&VIsual);
+ }
+ else
+ {
+ find_start_of_word(&VIsual);
+ if (*p_sel == 'e' && *ml_get_cursor() != NUL)
+#ifdef FEAT_MBYTE
+ curwin->w_cursor.col +=
+ (*mb_ptr2len_check)(ml_get_cursor());
+#else
+ ++curwin->w_cursor.col;
+#endif
+ find_end_of_word(&curwin->w_cursor);
+ }
+ }
+ curwin->w_set_curswant = TRUE;
+ }
+ if (is_click)
+ redraw_curbuf_later(INVERTED); /* update the inversion */
+ }
+ else if (VIsual_active && !old_active)
+ VIsual_mode = 'v';
+
+ /* If Visual mode changed show it later. */
+ if (p_smd && (VIsual_active != old_active || VIsual_mode != old_mode))
+ redraw_cmdline = TRUE;
+#endif
+
+ return moved;
+}
+
+#ifdef FEAT_VISUAL
+/*
+ * Move "pos" back to the start of the word it's in.
+ */
+ static void
+find_start_of_word(pos)
+ pos_T *pos;
+{
+ char_u *line;
+ int cclass;
+ int col;
+
+ line = ml_get(pos->lnum);
+ cclass = get_mouse_class(line + pos->col);
+
+ while (pos->col > 0)
+ {
+ col = pos->col - 1;
+#ifdef FEAT_MBYTE
+ col -= (*mb_head_off)(line, line + col);
+#endif
+ if (get_mouse_class(line + col) != cclass)
+ break;
+ pos->col = col;
+ }
+}
+
+/*
+ * Move "pos" forward to the end of the word it's in.
+ * When 'selection' is "exclusive", the position is just after the word.
+ */
+ static void
+find_end_of_word(pos)
+ pos_T *pos;
+{
+ char_u *line;
+ int cclass;
+ int col;
+
+ line = ml_get(pos->lnum);
+ if (*p_sel == 'e' && pos->col > 0)
+ {
+ --pos->col;
+#ifdef FEAT_MBYTE
+ pos->col -= (*mb_head_off)(line, line + pos->col);
+#endif
+ }
+ cclass = get_mouse_class(line + pos->col);
+ while (line[pos->col] != NUL)
+ {
+#ifdef FEAT_MBYTE
+ col = pos->col + (*mb_ptr2len_check)(line + pos->col);
+#else
+ col = pos->col + 1;
+#endif
+ if (get_mouse_class(line + col) != cclass)
+ {
+ if (*p_sel == 'e')
+ pos->col = col;
+ break;
+ }
+ pos->col = col;
+ }
+}
+
+/*
+ * Get class of a character for selection: same class means same word.
+ * 0: blank
+ * 1: punctuation groups
+ * 2: normal word character
+ * >2: multi-byte word character.
+ */
+ static int
+get_mouse_class(p)
+ char_u *p;
+{
+ int c;
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte && MB_BYTE2LEN(p[0]) > 1)
+ return mb_get_class(p);
+#endif
+
+ c = *p;
+ if (c == ' ' || c == '\t')
+ return 0;
+
+ if (vim_iswordc(c))
+ return 2;
+
+ /*
+ * There are a few special cases where we want certain combinations of
+ * characters to be considered as a single word. These are things like
+ * "->", "/ *", "*=", "+=", "&=", "<=", ">=", "!=" etc. Otherwise, each
+ * character is in it's own class.
+ */
+ if (c != NUL && vim_strchr((char_u *)"-+*/%<>&|^!=", c) != NULL)
+ return 1;
+ return c;
+}
+#endif /* FEAT_VISUAL */
+#endif /* FEAT_MOUSE */
+
+#if defined(FEAT_VISUAL) || defined(PROTO)
+/*
+ * Check if highlighting for visual mode is possible, give a warning message
+ * if not.
+ */
+ void
+check_visual_highlight()
+{
+ static int did_check = FALSE;
+
+ if (full_screen)
+ {
+ if (!did_check && hl_attr(HLF_V) == 0)
+ MSG(_("Warning: terminal cannot highlight"));
+ did_check = TRUE;
+ }
+}
+
+/*
+ * End visual mode.
+ * This function should ALWAYS be called to end Visual mode, except from
+ * do_pending_operator().
+ */
+ void
+end_visual_mode()
+{
+#ifdef FEAT_CLIPBOARD
+ /*
+ * If we are using the clipboard, then remember what was selected in case
+ * we need to paste it somewhere while we still own the selection.
+ * Only do this when the clipboard is already owned. Don't want to grab
+ * the selection when hitting ESC.
+ */
+ if (clip_star.available && clip_star.owned)
+ clip_auto_select();
+#endif
+
+ VIsual_active = FALSE;
+#ifdef FEAT_MOUSE
+ setmouse();
+ mouse_dragging = 0;
+#endif
+
+ /* Save the current VIsual area for '< and '> marks, and "gv" */
+ curbuf->b_visual_mode = VIsual_mode;
+#ifdef FEAT_EVAL
+ curbuf->b_visual_mode_eval = VIsual_mode;
+#endif
+ curbuf->b_visual_start = VIsual;
+ curbuf->b_visual_end = curwin->w_cursor;
+ curbuf->b_visual_curswant = curwin->w_curswant;
+#ifdef FEAT_VIRTUALEDIT
+ if (!virtual_active())
+ curwin->w_cursor.coladd = 0;
+#endif
+
+ if (p_smd)
+ clear_cmdline = TRUE; /* unshow visual mode later */
+#ifdef FEAT_CMDL_INFO
+ else
+ clear_showcmd();
+#endif
+
+ /* Don't leave the cursor past the end of the line */
+ if (curwin->w_cursor.col > 0 && *ml_get_cursor() == NUL)
+ --curwin->w_cursor.col;
+}
+
+/*
+ * Reset VIsual_active and VIsual_reselect.
+ */
+ void
+reset_VIsual_and_resel()
+{
+ if (VIsual_active)
+ {
+ end_visual_mode();
+ redraw_curbuf_later(INVERTED); /* delete the inversion later */
+ }
+ VIsual_reselect = FALSE;
+}
+
+/*
+ * Reset VIsual_active and VIsual_reselect if it's set.
+ */
+ void
+reset_VIsual()
+{
+ if (VIsual_active)
+ {
+ end_visual_mode();
+ redraw_curbuf_later(INVERTED); /* delete the inversion later */
+ VIsual_reselect = FALSE;
+ }
+}
+#endif /* FEAT_VISUAL */
+
+#if defined(FEAT_NETBEANS_INTG) && defined(FEAT_BEVAL)
+static int find_is_eval_item __ARGS((char_u *ptr, int *colp, int *nbp, int dir));
+
+/*
+ * Check for a balloon-eval special item to include when searching for an
+ * identifier. When "dir" is BACKWARD "ptr[-1]" must be valid!
+ * Returns TRUE if the character at "*ptr" should be included.
+ * "dir" is FORWARD or BACKWARD, the direction of searching.
+ * "*colp" is in/decremented if "ptr[-dir]" should also be included.
+ * "bnp" points to a counter for square brackets.
+ */
+ static int
+find_is_eval_item(ptr, colp, bnp, dir)
+ char_u *ptr;
+ int *colp;
+ int *bnp;
+ int dir;
+{
+ /* Accept everything inside []. */
+ if ((*ptr == ']' && dir == BACKWARD) || (*ptr == '[' && dir == FORWARD))
+ ++*bnp;
+ if (*bnp > 0)
+ {
+ if ((*ptr == '[' && dir == BACKWARD) || (*ptr == ']' && dir == FORWARD))
+ --*bnp;
+ return TRUE;
+ }
+
+ /* skip over "s.var" */
+ if (*ptr == '.')
+ return TRUE;
+
+ /* two-character item: s->var */
+ if (ptr[dir == BACKWARD ? 0 : 1] == '>'
+ && ptr[dir == BACKWARD ? -1 : 0] == '-')
+ {
+ *colp += dir;
+ return TRUE;
+ }
+ return FALSE;
+}
+#endif
+
+/*
+ * Find the identifier under or to the right of the cursor.
+ * "find_type" can have one of three values:
+ * FIND_IDENT: find an identifier (keyword)
+ * FIND_STRING: find any non-white string
+ * FIND_IDENT + FIND_STRING: find any non-white string, identifier preferred.
+ *
+ * There are three steps:
+ * 1. Search forward for the start of an identifier/string. Doesn't move if
+ * already on one.
+ * 2. Search backward for the start of this identifier/string.
+ * This doesn't match the real Vi but I like it a little better and it
+ * shouldn't bother anyone.
+ * 3. Search forward to the end of this identifier/string.
+ * When FIND_IDENT isn't defined, we backup until a blank.
+ *
+ * Returns the length of the string, or zero if no string is found.
+ * If a string is found, a pointer to the string is put in "*string". This
+ * string is not always NUL terminated.
+ */
+ int
+find_ident_under_cursor(string, find_type)
+ char_u **string;
+ int find_type;
+{
+ return find_ident_at_pos(curwin, curwin->w_cursor.lnum,
+ curwin->w_cursor.col, string, find_type);
+}
+
+/*
+ * Like find_ident_under_cursor(), but for any window and any position.
+ * However: Uses 'iskeyword' from the current window!.
+ */
+ int
+find_ident_at_pos(wp, lnum, startcol, string, find_type)
+ win_T *wp;
+ linenr_T lnum;
+ colnr_T startcol;
+ char_u **string;
+ int find_type;
+{
+ char_u *ptr;
+ int col = 0; /* init to shut up GCC */
+ int i;
+#ifdef FEAT_MBYTE
+ int this_class = 0;
+ int prev_class;
+ int prevcol;
+#endif
+#if defined(FEAT_NETBEANS_INTG) && defined(FEAT_BEVAL)
+ int bn = 0; /* bracket nesting */
+#endif
+
+ /*
+ * if i == 0: try to find an identifier
+ * if i == 1: try to find any non-white string
+ */
+ ptr = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ for (i = (find_type & FIND_IDENT) ? 0 : 1; i < 2; ++i)
+ {
+ /*
+ * 1. skip to start of identifier/string
+ */
+ col = startcol;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ while (ptr[col] != NUL)
+ {
+# if defined(FEAT_NETBEANS_INTG) && defined(FEAT_BEVAL)
+ /* Stop at a ']' to evaluate "a[x]". */
+ if ((find_type & FIND_EVAL) && ptr[col] == ']')
+ break;
+# endif
+ this_class = mb_get_class(ptr + col);
+ if (this_class != 0 && (i == 1 || this_class != 1))
+ break;
+ col += (*mb_ptr2len_check)(ptr + col);
+ }
+ }
+ else
+#endif
+ while (ptr[col] != NUL
+ && (i == 0 ? !vim_iswordc(ptr[col]) : vim_iswhite(ptr[col]))
+# if defined(FEAT_NETBEANS_INTG) && defined(FEAT_BEVAL)
+ && (!(find_type & FIND_EVAL) || ptr[col] != ']')
+# endif
+ )
+ ++col;
+
+#if defined(FEAT_NETBEANS_INTG) && defined(FEAT_BEVAL)
+ /* When starting on a ']' count it, so that we include the '['. */
+ bn = ptr[col] == ']';
+#endif
+
+ /*
+ * 2. Back up to start of identifier/string.
+ */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ /* Remember class of character under cursor. */
+# if defined(FEAT_NETBEANS_INTG) && defined(FEAT_BEVAL)
+ if ((find_type & FIND_EVAL) && ptr[col] == ']')
+ this_class = mb_get_class((char_u *)"a");
+ else
+# endif
+ this_class = mb_get_class(ptr + col);
+ while (col > 0)
+ {
+ prevcol = col - 1 - (*mb_head_off)(ptr, ptr + col - 1);
+ prev_class = mb_get_class(ptr + prevcol);
+ if (this_class != prev_class
+ && (i == 0
+ || prev_class == 0
+ || (find_type & FIND_IDENT))
+# if defined(FEAT_NETBEANS_INTG) && defined(FEAT_BEVAL)
+ && (!(find_type & FIND_EVAL)
+ || prevcol == 0
+ || !find_is_eval_item(ptr + prevcol, &prevcol,
+ &bn, BACKWARD))
+# endif
+ )
+ break;
+ col = prevcol;
+ }
+
+ /* If we don't want just any old string, or we've found an
+ * identifier, stop searching. */
+ if (this_class > 2)
+ this_class = 2;
+ if (!(find_type & FIND_STRING) || this_class == 2)
+ break;
+ }
+ else
+#endif
+ {
+ while (col > 0
+ && ((i == 0
+ ? vim_iswordc(ptr[col - 1])
+ : (!vim_iswhite(ptr[col - 1])
+ && (!(find_type & FIND_IDENT)
+ || !vim_iswordc(ptr[col - 1]))))
+#if defined(FEAT_NETBEANS_INTG) && defined(FEAT_BEVAL)
+ || ((find_type & FIND_EVAL)
+ && col > 1
+ && find_is_eval_item(ptr + col - 1, &col,
+ &bn, BACKWARD))
+#endif
+ ))
+ --col;
+
+ /* If we don't want just any old string, or we've found an
+ * identifier, stop searching. */
+ if (!(find_type & FIND_STRING) || vim_iswordc(ptr[col]))
+ break;
+ }
+ }
+
+ if (ptr[col] == NUL || (i == 0 && (
+#ifdef FEAT_MBYTE
+ has_mbyte ? this_class != 2 :
+#endif
+ !vim_iswordc(ptr[col]))))
+ {
+ /*
+ * didn't find an identifier or string
+ */
+ if (find_type & FIND_STRING)
+ EMSG(_("E348: No string under cursor"));
+ else
+ EMSG(_("E349: No identifier under cursor"));
+ return 0;
+ }
+ ptr += col;
+ *string = ptr;
+
+ /*
+ * 3. Find the end if the identifier/string.
+ */
+#if defined(FEAT_NETBEANS_INTG) && defined(FEAT_BEVAL)
+ bn = 0;
+ startcol -= col;
+#endif
+ col = 0;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ /* Search for point of changing multibyte character class. */
+ this_class = mb_get_class(ptr);
+ while (ptr[col] != NUL
+ && ((i == 0 ? mb_get_class(ptr + col) == this_class
+ : mb_get_class(ptr + col) != 0)
+# if defined(FEAT_NETBEANS_INTG) && defined(FEAT_BEVAL)
+ || ((find_type & FIND_EVAL)
+ && col <= (int)startcol
+ && find_is_eval_item(ptr + col, &col, &bn, FORWARD))
+# endif
+ ))
+ col += (*mb_ptr2len_check)(ptr + col);
+ }
+ else
+#endif
+ while ((i == 0 ? vim_iswordc(ptr[col])
+ : (ptr[col] != NUL && !vim_iswhite(ptr[col])))
+# if defined(FEAT_NETBEANS_INTG) && defined(FEAT_BEVAL)
+ || ((find_type & FIND_EVAL)
+ && col <= (int)startcol
+ && find_is_eval_item(ptr + col, &col, &bn, FORWARD))
+# endif
+ )
+ {
+ ++col;
+ }
+
+ return col;
+}
+
+/*
+ * Prepare for redo of a normal command.
+ */
+ static void
+prep_redo_cmd(cap)
+ cmdarg_T *cap;
+{
+ prep_redo(cap->oap->regname, cap->count0,
+ NUL, cap->cmdchar, NUL, NUL, cap->nchar);
+}
+
+/*
+ * Prepare for redo of any command.
+ * Note that only the last argument can be a multi-byte char.
+ */
+ static void
+prep_redo(regname, num, cmd1, cmd2, cmd3, cmd4, cmd5)
+ int regname;
+ long num;
+ int cmd1;
+ int cmd2;
+ int cmd3;
+ int cmd4;
+ int cmd5;
+{
+ ResetRedobuff();
+ if (regname != 0) /* yank from specified buffer */
+ {
+ AppendCharToRedobuff('"');
+ AppendCharToRedobuff(regname);
+ }
+ if (num)
+ AppendNumberToRedobuff(num);
+
+ if (cmd1 != NUL)
+ AppendCharToRedobuff(cmd1);
+ if (cmd2 != NUL)
+ AppendCharToRedobuff(cmd2);
+ if (cmd3 != NUL)
+ AppendCharToRedobuff(cmd3);
+ if (cmd4 != NUL)
+ AppendCharToRedobuff(cmd4);
+ if (cmd5 != NUL)
+ AppendCharToRedobuff(cmd5);
+}
+
+/*
+ * check for operator active and clear it
+ *
+ * return TRUE if operator was active
+ */
+ static int
+checkclearop(oap)
+ oparg_T *oap;
+{
+ if (oap->op_type == OP_NOP)
+ return FALSE;
+ clearopbeep(oap);
+ return TRUE;
+}
+
+/*
+ * check for operator or Visual active and clear it
+ *
+ * return TRUE if operator was active
+ */
+ static int
+checkclearopq(oap)
+ oparg_T *oap;
+{
+ if (oap->op_type == OP_NOP
+#ifdef FEAT_VISUAL
+ && !VIsual_active
+#endif
+ )
+ return FALSE;
+ clearopbeep(oap);
+ return TRUE;
+}
+
+ static void
+clearop(oap)
+ oparg_T *oap;
+{
+ oap->op_type = OP_NOP;
+ oap->regname = 0;
+ oap->motion_force = NUL;
+ oap->use_reg_one = FALSE;
+}
+
+ static void
+clearopbeep(oap)
+ oparg_T *oap;
+{
+ clearop(oap);
+ beep_flush();
+}
+
+#ifdef FEAT_VISUAL
+/*
+ * Remove the shift modifier from a special key.
+ */
+ static void
+unshift_special(cap)
+ cmdarg_T *cap;
+{
+ switch (cap->cmdchar)
+ {
+ case K_S_RIGHT: cap->cmdchar = K_RIGHT; break;
+ case K_S_LEFT: cap->cmdchar = K_LEFT; break;
+ case K_S_UP: cap->cmdchar = K_UP; break;
+ case K_S_DOWN: cap->cmdchar = K_DOWN; break;
+ case K_S_HOME: cap->cmdchar = K_HOME; break;
+ case K_S_END: cap->cmdchar = K_END; break;
+ }
+ cap->cmdchar = simplify_key(cap->cmdchar, &mod_mask);
+}
+#endif
+
+#if defined(FEAT_CMDL_INFO) || defined(PROTO)
+/*
+ * Routines for displaying a partly typed command
+ */
+
+#ifdef FEAT_VISUAL /* need room for size of Visual area */
+# define SHOWCMD_BUFLEN SHOWCMD_COLS + 1 + 30
+#else
+# define SHOWCMD_BUFLEN SHOWCMD_COLS + 1
+#endif
+static char_u showcmd_buf[SHOWCMD_BUFLEN];
+static char_u old_showcmd_buf[SHOWCMD_BUFLEN]; /* For push_showcmd() */
+static int showcmd_is_clear = TRUE;
+static int showcmd_visual = FALSE;
+
+static void display_showcmd __ARGS((void));
+
+ void
+clear_showcmd()
+{
+ if (!p_sc)
+ return;
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active && !char_avail())
+ {
+ int i = lt(VIsual, curwin->w_cursor);
+ long lines;
+ colnr_T leftcol, rightcol;
+ linenr_T top, bot;
+
+ /* Show the size of the Visual area. */
+ if (i)
+ {
+ top = VIsual.lnum;
+ bot = curwin->w_cursor.lnum;
+ }
+ else
+ {
+ top = curwin->w_cursor.lnum;
+ bot = VIsual.lnum;
+ }
+# ifdef FEAT_FOLDING
+ /* Include closed folds as a whole. */
+ hasFolding(top, &top, NULL);
+ hasFolding(bot, NULL, &bot);
+# endif
+ lines = bot - top + 1;
+
+ if (VIsual_mode == Ctrl_V)
+ {
+ getvcols(curwin, &curwin->w_cursor, &VIsual, &leftcol, &rightcol);
+ sprintf((char *)showcmd_buf, "%ldx%ld", lines,
+ (long)(rightcol - leftcol + 1));
+ }
+ else if (VIsual_mode == 'V' || VIsual.lnum != curwin->w_cursor.lnum)
+ sprintf((char *)showcmd_buf, "%ld", lines);
+ else
+ sprintf((char *)showcmd_buf, "%ld", (long)(i
+ ? curwin->w_cursor.col - VIsual.col
+ : VIsual.col - curwin->w_cursor.col) + (*p_sel != 'e'));
+ showcmd_buf[SHOWCMD_COLS] = NUL; /* truncate */
+ showcmd_visual = TRUE;
+ }
+ else
+#endif
+ {
+ showcmd_buf[0] = NUL;
+ showcmd_visual = FALSE;
+
+ /* Don't actually display something if there is nothing to clear. */
+ if (showcmd_is_clear)
+ return;
+ }
+
+ display_showcmd();
+}
+
+/*
+ * Add 'c' to string of shown command chars.
+ * Return TRUE if output has been written (and setcursor() has been called).
+ */
+ int
+add_to_showcmd(c)
+ int c;
+{
+ char_u *p;
+ int old_len;
+ int extra_len;
+ int overflow;
+#if defined(FEAT_MOUSE)
+ int i;
+ static int ignore[] =
+ {
+#ifdef FEAT_GUI
+ K_VER_SCROLLBAR, K_HOR_SCROLLBAR,
+ K_LEFTMOUSE_NM, K_LEFTRELEASE_NM,
+#endif
+ K_IGNORE,
+ K_LEFTMOUSE, K_LEFTDRAG, K_LEFTRELEASE,
+ K_MIDDLEMOUSE, K_MIDDLEDRAG, K_MIDDLERELEASE,
+ K_RIGHTMOUSE, K_RIGHTDRAG, K_RIGHTRELEASE,
+ K_MOUSEDOWN, K_MOUSEUP,
+ K_X1MOUSE, K_X1DRAG, K_X1RELEASE, K_X2MOUSE, K_X2DRAG, K_X2RELEASE,
+ 0
+ };
+#endif
+
+ if (!p_sc)
+ return FALSE;
+
+ if (showcmd_visual)
+ {
+ showcmd_buf[0] = NUL;
+ showcmd_visual = FALSE;
+ }
+
+#if defined(FEAT_MOUSE)
+ /* Ignore keys that are scrollbar updates and mouse clicks */
+ if (IS_SPECIAL(c))
+ for (i = 0; ignore[i] != 0; ++i)
+ if (ignore[i] == c)
+ return FALSE;
+#endif
+
+ p = transchar(c);
+ old_len = (int)STRLEN(showcmd_buf);
+ extra_len = (int)STRLEN(p);
+ overflow = old_len + extra_len - SHOWCMD_COLS;
+ if (overflow > 0)
+ STRCPY(showcmd_buf, showcmd_buf + overflow);
+ STRCAT(showcmd_buf, p);
+
+ if (char_avail())
+ return FALSE;
+
+ display_showcmd();
+
+ return TRUE;
+}
+
+ void
+add_to_showcmd_c(c)
+ int c;
+{
+ if (!add_to_showcmd(c))
+ setcursor();
+}
+
+/*
+ * Delete 'len' characters from the end of the shown command.
+ */
+ static void
+del_from_showcmd(len)
+ int len;
+{
+ int old_len;
+
+ if (!p_sc)
+ return;
+
+ old_len = (int)STRLEN(showcmd_buf);
+ if (len > old_len)
+ len = old_len;
+ showcmd_buf[old_len - len] = NUL;
+
+ if (!char_avail())
+ display_showcmd();
+}
+
+/*
+ * push_showcmd() and pop_showcmd() are used when waiting for the user to type
+ * something and there is a partial mapping.
+ */
+ void
+push_showcmd()
+{
+ if (p_sc)
+ STRCPY(old_showcmd_buf, showcmd_buf);
+}
+
+ void
+pop_showcmd()
+{
+ if (!p_sc)
+ return;
+
+ STRCPY(showcmd_buf, old_showcmd_buf);
+
+ display_showcmd();
+}
+
+ static void
+display_showcmd()
+{
+ int len;
+
+ cursor_off();
+
+ len = (int)STRLEN(showcmd_buf);
+ if (len == 0)
+ showcmd_is_clear = TRUE;
+ else
+ {
+ screen_puts(showcmd_buf, (int)Rows - 1, sc_col, 0);
+ showcmd_is_clear = FALSE;
+ }
+
+ /*
+ * clear the rest of an old message by outputing up to SHOWCMD_COLS spaces
+ */
+ screen_puts((char_u *)" " + len, (int)Rows - 1, sc_col + len, 0);
+
+ setcursor(); /* put cursor back where it belongs */
+}
+#endif
+
+#ifdef FEAT_SCROLLBIND
+/*
+ * When "check" is FALSE, prepare for commands that scroll the window.
+ * When "check" is TRUE, take care of scroll-binding after the window has
+ * scrolled. Called from normal_cmd() and edit().
+ */
+ void
+do_check_scrollbind(check)
+ int check;
+{
+ static win_T *old_curwin = NULL;
+ static linenr_T old_topline = 0;
+#ifdef FEAT_DIFF
+ static int old_topfill = 0;
+#endif
+ static buf_T *old_buf = NULL;
+ static colnr_T old_leftcol = 0;
+
+ if (check && curwin->w_p_scb)
+ {
+ /* If a ":syncbind" command was just used, don't scroll, only reset
+ * the values. */
+ if (did_syncbind)
+ did_syncbind = FALSE;
+ else if (curwin == old_curwin)
+ {
+ /*
+ * Synchronize other windows, as necessary according to
+ * 'scrollbind'. Don't do this after an ":edit" command, except
+ * when 'diff' is set.
+ */
+ if ((curwin->w_buffer == old_buf
+#ifdef FEAT_DIFF
+ || curwin->w_p_diff
+#endif
+ )
+ && (curwin->w_topline != old_topline
+#ifdef FEAT_DIFF
+ || curwin->w_topfill != old_topfill
+#endif
+ || curwin->w_leftcol != old_leftcol))
+ {
+ check_scrollbind(curwin->w_topline - old_topline,
+ (long)(curwin->w_leftcol - old_leftcol));
+ }
+ }
+ else if (vim_strchr(p_sbo, 'j')) /* jump flag set in 'scrollopt' */
+ {
+ /*
+ * When switching between windows, make sure that the relative
+ * vertical offset is valid for the new window. The relative
+ * offset is invalid whenever another 'scrollbind' window has
+ * scrolled to a point that would force the current window to
+ * scroll past the beginning or end of its buffer. When the
+ * resync is performed, some of the other 'scrollbind' windows may
+ * need to jump so that the current window's relative position is
+ * visible on-screen.
+ */
+ check_scrollbind(curwin->w_topline - curwin->w_scbind_pos, 0L);
+ }
+ curwin->w_scbind_pos = curwin->w_topline;
+ }
+
+ old_curwin = curwin;
+ old_topline = curwin->w_topline;
+#ifdef FEAT_DIFF
+ old_topfill = curwin->w_topfill;
+#endif
+ old_buf = curwin->w_buffer;
+ old_leftcol = curwin->w_leftcol;
+}
+
+/*
+ * Synchronize any windows that have "scrollbind" set, based on the
+ * number of rows by which the current window has changed
+ * (1998-11-02 16:21:01 R. Edward Ralston <eralston@computer.org>)
+ */
+ void
+check_scrollbind(topline_diff, leftcol_diff)
+ linenr_T topline_diff;
+ long leftcol_diff;
+{
+ int want_ver;
+ int want_hor;
+ win_T *old_curwin = curwin;
+ buf_T *old_curbuf = curbuf;
+#ifdef FEAT_VISUAL
+ int old_VIsual_select = VIsual_select;
+ int old_VIsual_active = VIsual_active;
+#endif
+ colnr_T tgt_leftcol = curwin->w_leftcol;
+ long topline;
+ long y;
+
+ /*
+ * check 'scrollopt' string for vertical and horizontal scroll options
+ */
+ want_ver = (vim_strchr(p_sbo, 'v') && topline_diff != 0);
+#ifdef FEAT_DIFF
+ want_ver |= old_curwin->w_p_diff;
+#endif
+ want_hor = (vim_strchr(p_sbo, 'h') && (leftcol_diff || topline_diff != 0));
+
+ /*
+ * loop through the scrollbound windows and scroll accordingly
+ */
+#ifdef FEAT_VISUAL
+ VIsual_select = VIsual_active = 0;
+#endif
+ for (curwin = firstwin; curwin; curwin = curwin->w_next)
+ {
+ curbuf = curwin->w_buffer;
+ /* skip original window and windows with 'noscrollbind' */
+ if (curwin != old_curwin && curwin->w_p_scb)
+ {
+ /*
+ * do the vertical scroll
+ */
+ if (want_ver)
+ {
+#ifdef FEAT_DIFF
+ if (old_curwin->w_p_diff && curwin->w_p_diff)
+ {
+ diff_set_topline(old_curwin, curwin);
+ }
+ else
+#endif
+ {
+ curwin->w_scbind_pos += topline_diff;
+ topline = curwin->w_scbind_pos;
+ if (topline > curbuf->b_ml.ml_line_count)
+ topline = curbuf->b_ml.ml_line_count;
+ if (topline < 1)
+ topline = 1;
+
+ y = topline - curwin->w_topline;
+ if (y > 0)
+ scrollup(y, FALSE);
+ else
+ scrolldown(-y, FALSE);
+ }
+
+ redraw_later(VALID);
+ cursor_correct();
+#ifdef FEAT_WINDOWS
+ curwin->w_redr_status = TRUE;
+#endif
+ }
+
+ /*
+ * do the horizontal scroll
+ */
+ if (want_hor && curwin->w_leftcol != tgt_leftcol)
+ {
+ curwin->w_leftcol = tgt_leftcol;
+ leftcol_changed();
+ }
+ }
+ }
+
+ /*
+ * reset current-window
+ */
+#ifdef FEAT_VISUAL
+ VIsual_select = old_VIsual_select;
+ VIsual_active = old_VIsual_active;
+#endif
+ curwin = old_curwin;
+ curbuf = old_curbuf;
+}
+#endif /* #ifdef FEAT_SCROLLBIND */
+
+/*
+ * Command character that's ignored.
+ * Used for CTRL-Q and CTRL-S to avoid problems with terminals that use
+ * xon/xoff
+ */
+/*ARGSUSED */
+ static void
+nv_ignore(cap)
+ cmdarg_T *cap;
+{
+}
+
+/*
+ * Command character doesn't exist.
+ */
+ static void
+nv_error(cap)
+ cmdarg_T *cap;
+{
+ clearopbeep(cap->oap);
+}
+
+/*
+ * <Help> and <F1> commands.
+ */
+ static void
+nv_help(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearopq(cap->oap))
+ ex_help(NULL);
+}
+
+/*
+ * CTRL-A and CTRL-X: Add or subtract from letter or number under cursor.
+ */
+ static void
+nv_addsub(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearopq(cap->oap)
+ && do_addsub((int)cap->cmdchar, cap->count1) == OK)
+ prep_redo_cmd(cap);
+}
+
+/*
+ * CTRL-F, CTRL-B, etc: Scroll page up or down.
+ */
+ static void
+nv_page(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearop(cap->oap))
+ (void)onepage(cap->arg, cap->count1);
+}
+
+/*
+ * Implementation of "gd" and "gD" command.
+ */
+ static void
+nv_gd(oap, nchar)
+ oparg_T *oap;
+ int nchar;
+{
+ int len;
+ char_u *pat;
+ pos_T old_pos;
+ int t;
+ int save_p_ws;
+ int save_p_scs;
+ char_u *ptr;
+
+ if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0 ||
+ (pat = alloc(len + 5)) == NULL)
+ {
+ clearopbeep(oap);
+ return;
+ }
+ sprintf((char *)pat, vim_iswordp(ptr) ? "\\<%.*s\\>" : "%.*s", len, ptr);
+ old_pos = curwin->w_cursor;
+ save_p_ws = p_ws;
+ save_p_scs = p_scs;
+ p_ws = FALSE; /* don't wrap around end of file now */
+ p_scs = FALSE; /* don't switch ignorecase off now */
+
+ /*
+ * With "gD" go to line 1.
+ * With "gd" Search back for the start of the current function, then go
+ * back until a blank line. If this fails go to line 1.
+ */
+ if (nchar == 'D' || !findpar(oap, BACKWARD, 1L, '{', FALSE))
+ {
+ setpcmark(); /* Set in findpar() otherwise */
+ curwin->w_cursor.lnum = 1;
+ }
+ else
+ {
+ while (curwin->w_cursor.lnum > 1 && *skipwhite(ml_get_curline()) != NUL)
+ --curwin->w_cursor.lnum;
+ }
+ curwin->w_cursor.col = 0;
+
+ /* Search forward for the identifier, ignore comment lines. */
+ while ((t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD, pat, 1L, 0,
+ RE_LAST)) != FAIL
+#ifdef FEAT_COMMENTS
+ && get_leader_len(ml_get_curline(), NULL, FALSE) > 0
+#endif
+ && old_pos.lnum > curwin->w_cursor.lnum)
+ {
+ /* Ignore this line, continue at start of next line. */
+ ++curwin->w_cursor.lnum;
+ curwin->w_cursor.col = 0;
+ }
+ if (t == FAIL || old_pos.lnum <= curwin->w_cursor.lnum)
+ {
+ clearopbeep(oap);
+ curwin->w_cursor = old_pos;
+ }
+ else
+ {
+ curwin->w_set_curswant = TRUE;
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+ /* "n" searches forward now */
+ reset_search_dir();
+ }
+
+ vim_free(pat);
+ p_ws = save_p_ws;
+ p_scs = save_p_scs;
+}
+
+/*
+ * Move 'dist' lines in direction 'dir', counting lines by *screen*
+ * lines rather than lines in the file.
+ * 'dist' must be positive.
+ *
+ * Return OK if able to move cursor, FAIL otherwise.
+ */
+ static int
+nv_screengo(oap, dir, dist)
+ oparg_T *oap;
+ int dir;
+ long dist;
+{
+ int linelen = linetabsize(ml_get_curline());
+ int retval = OK;
+ int atend = FALSE;
+ int n;
+ int col_off1; /* margin offset for first screen line */
+ int col_off2; /* margin offset for wrapped screen line */
+ int width1; /* text width for first screen line */
+ int width2; /* test width for wrapped screen line */
+
+ oap->motion_type = MCHAR;
+ oap->inclusive = FALSE;
+
+ col_off1 = curwin_col_off();
+ col_off2 = col_off1 - curwin_col_off2();
+ width1 = W_WIDTH(curwin) - col_off1;
+ width2 = W_WIDTH(curwin) - col_off2;
+
+#ifdef FEAT_VERTSPLIT
+ if (curwin->w_width != 0)
+ {
+#endif
+ /*
+ * Instead of sticking at the last character of the buffer line we
+ * try to stick in the last column of the screen.
+ */
+ if (curwin->w_curswant == MAXCOL)
+ {
+ atend = TRUE;
+ validate_virtcol();
+ if (width1 <= 0)
+ curwin->w_curswant = 0;
+ else
+ {
+ curwin->w_curswant = width1 - 1;
+ if (curwin->w_virtcol > curwin->w_curswant)
+ curwin->w_curswant += ((curwin->w_virtcol
+ - curwin->w_curswant - 1) / width2 + 1) * width2;
+ }
+ }
+ else
+ {
+ if (linelen > width1)
+ n = ((linelen - width1 - 1) / width2 + 1) * width2 + width1;
+ else
+ n = width1;
+ if (curwin->w_curswant > (colnr_T)n + 1)
+ curwin->w_curswant -= ((curwin->w_curswant - n) / width2 + 1)
+ * width2;
+ }
+
+ while (dist--)
+ {
+ if (dir == BACKWARD)
+ {
+ if ((long)curwin->w_curswant >= width2)
+ /* move back within line */
+ curwin->w_curswant -= width2;
+ else
+ {
+ /* to previous line */
+ if (curwin->w_cursor.lnum == 1)
+ {
+ retval = FAIL;
+ break;
+ }
+ --curwin->w_cursor.lnum;
+#ifdef FEAT_FOLDING
+ /* Move to the start of a closed fold. Don't do that when
+ * 'foldopen' contains "all": it will open in a moment. */
+ if (!(fdo_flags & FDO_ALL))
+ (void)hasFolding(curwin->w_cursor.lnum,
+ &curwin->w_cursor.lnum, NULL);
+#endif
+ linelen = linetabsize(ml_get_curline());
+ if (linelen > width1)
+ curwin->w_curswant += (((linelen - width1 - 1) / width2)
+ + 1) * width2;
+ }
+ }
+ else /* dir == FORWARD */
+ {
+ if (linelen > width1)
+ n = ((linelen - width1 - 1) / width2 + 1) * width2 + width1;
+ else
+ n = width1;
+ if (curwin->w_curswant + width2 < (colnr_T)n)
+ /* move forward within line */
+ curwin->w_curswant += width2;
+ else
+ {
+ /* to next line */
+#ifdef FEAT_FOLDING
+ /* Move to the end of a closed fold. */
+ (void)hasFolding(curwin->w_cursor.lnum, NULL,
+ &curwin->w_cursor.lnum);
+#endif
+ if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
+ {
+ retval = FAIL;
+ break;
+ }
+ curwin->w_cursor.lnum++;
+ curwin->w_curswant %= width2;
+ }
+ }
+ }
+#ifdef FEAT_VERTSPLIT
+ }
+#endif
+
+ coladvance(curwin->w_curswant);
+
+#if defined(FEAT_LINEBREAK) || defined(FEAT_MBYTE)
+ if (curwin->w_cursor.col > 0 && curwin->w_p_wrap)
+ {
+ /*
+ * Check for landing on a character that got split at the end of the
+ * last line. We want to advance a screenline, not end up in the same
+ * screenline or move two screenlines.
+ */
+ validate_virtcol();
+ if (curwin->w_virtcol > curwin->w_curswant
+ && (curwin->w_curswant < (colnr_T)width1
+ ? (curwin->w_curswant > (colnr_T)width1 / 2)
+ : ((curwin->w_curswant - width1) % width2
+ > (colnr_T)width2 / 2)))
+ --curwin->w_cursor.col;
+ }
+#endif
+
+ if (atend)
+ curwin->w_curswant = MAXCOL; /* stick in the last column */
+
+ return retval;
+}
+
+#ifdef FEAT_MOUSE
+/*
+ * Mouse scroll wheel: Default action is to scroll three lines, or one page
+ * when Shift or Ctrl is used.
+ * K_MOUSEUP (cap->arg == TRUE) or K_MOUSEDOWN (cap->arg == FALSE)
+ */
+ static void
+nv_mousescroll(cap)
+ cmdarg_T *cap;
+{
+# if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
+ win_T *old_curwin;
+
+ old_curwin = curwin;
+
+ /* Currently we only get the mouse coordinates in the GUI. */
+ if (gui.in_use && mouse_row >= 0 && mouse_col >= 0)
+ {
+ int row, col;
+
+ row = mouse_row;
+ col = mouse_col;
+
+ /* find the window at the pointer coordinates */
+ curwin = mouse_find_win(&row, &col);
+ curbuf = curwin->w_buffer;
+ }
+# endif
+
+ if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
+ {
+ (void)onepage(cap->arg ? FORWARD : BACKWARD, 1L);
+ }
+ else
+ {
+ cap->count1 = 3;
+ cap->count0 = 3;
+ nv_scroll_line(cap);
+ }
+
+# if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
+ curwin->w_redr_status = TRUE;
+
+ curwin = old_curwin;
+ curbuf = curwin->w_buffer;
+# endif
+}
+
+/*
+ * Mouse clicks and drags.
+ */
+ static void
+nv_mouse(cap)
+ cmdarg_T *cap;
+{
+ (void)do_mouse(cap->oap, cap->cmdchar, BACKWARD, cap->count1, 0);
+}
+#endif
+
+/*
+ * Handle CTRL-E and CTRL-Y commands: scroll a line up or down.
+ * cap->arg must be TRUE for CTRL-E.
+ */
+ static void
+nv_scroll_line(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearop(cap->oap))
+ scroll_redraw(cap->arg, cap->count1);
+}
+
+/*
+ * Scroll "count" lines up or down, and redraw.
+ */
+ void
+scroll_redraw(up, count)
+ int up;
+ long count;
+{
+ linenr_T prev_topline = curwin->w_topline;
+#ifdef FEAT_DIFF
+ int prev_topfill = curwin->w_topfill;
+#endif
+ linenr_T prev_lnum = curwin->w_cursor.lnum;
+
+ if (up)
+ scrollup(count, TRUE);
+ else
+ scrolldown(count, TRUE);
+ if (p_so)
+ {
+ /* Adjust the cursor position for 'scrolloff'. Mark w_topline as
+ * valid, otherwise the screen jumps back at the end of the file. */
+ cursor_correct();
+ check_cursor_moved(curwin);
+ curwin->w_valid |= VALID_TOPLINE;
+
+ /* If moved back to where we were, at least move the cursor, otherwise
+ * we get stuck at one position. Don't move the cursor up if the
+ * first line of the buffer is already on the screen */
+ while (curwin->w_topline == prev_topline
+#ifdef FEAT_DIFF
+ && curwin->w_topfill == prev_topfill
+#endif
+ )
+ {
+ if (up)
+ {
+ if (curwin->w_cursor.lnum > prev_lnum
+ || cursor_down(1L, FALSE) == FAIL)
+ break;
+ }
+ else
+ {
+ if (curwin->w_cursor.lnum < prev_lnum
+ || prev_topline == 1L
+ || cursor_up(1L, FALSE) == FAIL)
+ break;
+ }
+ /* Mark w_topline as valid, otherwise the screen jumps back at the
+ * end of the file. */
+ check_cursor_moved(curwin);
+ curwin->w_valid |= VALID_TOPLINE;
+ }
+ }
+ if (curwin->w_cursor.lnum != prev_lnum)
+ coladvance(curwin->w_curswant);
+ redraw_later(VALID);
+}
+
+/*
+ * Commands that start with "z".
+ */
+ static void
+nv_zet(cap)
+ cmdarg_T *cap;
+{
+ long n;
+ colnr_T col;
+ int nchar = cap->nchar;
+#ifdef FEAT_FOLDING
+ long old_fdl = curwin->w_p_fdl;
+ int old_fen = curwin->w_p_fen;
+#endif
+
+ if (VIM_ISDIGIT(nchar))
+ {
+ /*
+ * "z123{nchar}": edit the count before obtaining {nchar}
+ */
+ if (checkclearop(cap->oap))
+ return;
+ n = nchar - '0';
+ for (;;)
+ {
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = TRUE; /* disallow scrolling here */
+#endif
+ ++no_mapping;
+ ++allow_keys; /* no mapping for nchar, but allow key codes */
+ nchar = safe_vgetc();
+#ifdef FEAT_LANGMAP
+ LANGMAP_ADJUST(nchar, TRUE);
+#endif
+ --no_mapping;
+ --allow_keys;
+#ifdef FEAT_CMDL_INFO
+ (void)add_to_showcmd(nchar);
+#endif
+ if (nchar == K_DEL || nchar == K_KDEL)
+ n /= 10;
+ else if (VIM_ISDIGIT(nchar))
+ n = n * 10 + (nchar - '0');
+ else if (nchar == CAR)
+ {
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ win_setheight((int)n);
+ break;
+ }
+ else if (nchar == 'l'
+ || nchar == 'h'
+ || nchar == K_LEFT
+ || nchar == K_RIGHT)
+ {
+ cap->count1 = n ? n * cap->count1 : cap->count1;
+ goto dozet;
+ }
+ else
+ {
+ clearopbeep(cap->oap);
+ break;
+ }
+ }
+ cap->oap->op_type = OP_NOP;
+ return;
+ }
+
+dozet:
+ if (
+#ifdef FEAT_FOLDING
+ /* "zf" and "zF" are always an operator, "zd", "zo", "zO", "zc"
+ * and "zC" only in Visual mode. "zj" and "zk" are motion
+ * commands. */
+ cap->nchar != 'f' && cap->nchar != 'F'
+ && !(VIsual_active && vim_strchr((char_u *)"dcCoO", cap->nchar))
+ && cap->nchar != 'j' && cap->nchar != 'k'
+ &&
+#endif
+ checkclearop(cap->oap))
+ return;
+
+ /*
+ * For "z+", "z<CR>", "zt", "z.", "zz", "z^", "z-", "zb":
+ * If line number given, set cursor.
+ */
+ if ((vim_strchr((char_u *)"+\r\nt.z^-b", nchar) != NULL)
+ && cap->count0
+ && cap->count0 != curwin->w_cursor.lnum)
+ {
+ setpcmark();
+ if (cap->count0 > curbuf->b_ml.ml_line_count)
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ else
+ curwin->w_cursor.lnum = cap->count0;
+ }
+
+ switch (nchar)
+ {
+ /* "z+", "z<CR>" and "zt": put cursor at top of screen */
+ case '+':
+ if (cap->count0 == 0)
+ {
+ /* No count given: put cursor at the line below screen */
+ validate_botline(); /* make sure w_botline is valid */
+ if (curwin->w_botline > curbuf->b_ml.ml_line_count)
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ else
+ curwin->w_cursor.lnum = curwin->w_botline;
+ }
+ /* FALLTHROUGH */
+ case NL:
+ case CAR:
+ case K_KENTER:
+ beginline(BL_WHITE | BL_FIX);
+ /* FALLTHROUGH */
+
+ case 't': scroll_cursor_top(0, TRUE);
+ redraw_later(VALID);
+ break;
+
+ /* "z." and "zz": put cursor in middle of screen */
+ case '.': beginline(BL_WHITE | BL_FIX);
+ /* FALLTHROUGH */
+
+ case 'z': scroll_cursor_halfway(TRUE);
+ redraw_later(VALID);
+ break;
+
+ /* "z^", "z-" and "zb": put cursor at bottom of screen */
+ case '^': /* Strange Vi behavior: <count>z^ finds line at top of window
+ * when <count> is at bottom of window, and puts that one at
+ * bottom of window. */
+ if (cap->count0 != 0)
+ {
+ scroll_cursor_bot(0, TRUE);
+ curwin->w_cursor.lnum = curwin->w_topline;
+ }
+ else if (curwin->w_topline == 1)
+ curwin->w_cursor.lnum = 1;
+ else
+ curwin->w_cursor.lnum = curwin->w_topline - 1;
+ /* FALLTHROUGH */
+ case '-':
+ beginline(BL_WHITE | BL_FIX);
+ /* FALLTHROUGH */
+
+ case 'b': scroll_cursor_bot(0, TRUE);
+ redraw_later(VALID);
+ break;
+
+ /* "zH" - scroll screen right half-page */
+ case 'H':
+ cap->count1 *= W_WIDTH(curwin) / 2;
+ /* FALLTHROUGH */
+
+ /* "zh" - scroll screen to the right */
+ case 'h':
+ case K_LEFT:
+ if (!curwin->w_p_wrap)
+ {
+ if ((colnr_T)cap->count1 > curwin->w_leftcol)
+ curwin->w_leftcol = 0;
+ else
+ curwin->w_leftcol -= (colnr_T)cap->count1;
+ leftcol_changed();
+ }
+ break;
+
+ /* "zL" - scroll screen left half-page */
+ case 'L': cap->count1 *= W_WIDTH(curwin) / 2;
+ /* FALLTHROUGH */
+
+ /* "zl" - scroll screen to the left */
+ case 'l':
+ case K_RIGHT:
+ if (!curwin->w_p_wrap)
+ {
+ /* scroll the window left */
+ curwin->w_leftcol += (colnr_T)cap->count1;
+ leftcol_changed();
+ }
+ break;
+
+ /* "zs" - scroll screen, cursor at the start */
+ case 's': if (!curwin->w_p_wrap)
+ {
+#ifdef FEAT_FOLDING
+ if (hasFolding(curwin->w_cursor.lnum, NULL, NULL))
+ col = 0; /* like the cursor is in col 0 */
+ else
+#endif
+ getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL);
+ if ((long)col > p_siso)
+ col -= p_siso;
+ else
+ col = 0;
+ if (curwin->w_leftcol != col)
+ {
+ curwin->w_leftcol = col;
+ redraw_later(NOT_VALID);
+ }
+ }
+ break;
+
+ /* "ze" - scroll screen, cursor at the end */
+ case 'e': if (!curwin->w_p_wrap)
+ {
+#ifdef FEAT_FOLDING
+ if (hasFolding(curwin->w_cursor.lnum, NULL, NULL))
+ col = 0; /* like the cursor is in col 0 */
+ else
+#endif
+ getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
+ n = W_WIDTH(curwin) - curwin_col_off();
+ if ((long)col + p_siso < n)
+ col = 0;
+ else
+ col = col + p_siso - n + 1;
+ if (curwin->w_leftcol != col)
+ {
+ curwin->w_leftcol = col;
+ redraw_later(NOT_VALID);
+ }
+ }
+ break;
+
+#ifdef FEAT_FOLDING
+ /* "zF": create fold command */
+ /* "zf": create fold operator */
+ case 'F':
+ case 'f': if (foldManualAllowed(TRUE))
+ {
+ cap->nchar = 'f';
+ nv_operator(cap);
+ curwin->w_p_fen = TRUE;
+
+ /* "zF" is like "zfzf" */
+ if (nchar == 'F' && cap->oap->op_type == OP_FOLD)
+ {
+ nv_operator(cap);
+ finish_op = TRUE;
+ }
+ }
+ else
+ clearopbeep(cap->oap);
+ break;
+
+ /* "zd": delete fold at cursor */
+ /* "zD": delete fold at cursor recursively */
+ case 'd':
+ case 'D': if (foldManualAllowed(FALSE))
+ {
+ if (VIsual_active)
+ nv_operator(cap);
+ else
+ deleteFold(curwin->w_cursor.lnum,
+ curwin->w_cursor.lnum, nchar == 'D', FALSE);
+ }
+ break;
+
+ /* "zE": erease all folds */
+ case 'E': if (foldmethodIsManual(curwin))
+ {
+ clearFolding(curwin);
+ changed_window_setting();
+ }
+ else if (foldmethodIsMarker(curwin))
+ deleteFold((linenr_T)1, curbuf->b_ml.ml_line_count,
+ TRUE, FALSE);
+ else
+ EMSG(_("E352: Cannot erase folds with current 'foldmethod'"));
+ break;
+
+ /* "zn": fold none: reset 'foldenable' */
+ case 'n': curwin->w_p_fen = FALSE;
+ break;
+
+ /* "zN": fold Normal: set 'foldenable' */
+ case 'N': curwin->w_p_fen = TRUE;
+ break;
+
+ /* "zi": invert folding: toggle 'foldenable' */
+ case 'i': curwin->w_p_fen = !curwin->w_p_fen;
+ break;
+
+ /* "za": open closed fold or close open fold at cursor */
+ case 'a': if (hasFolding(curwin->w_cursor.lnum, NULL, NULL))
+ openFold(curwin->w_cursor.lnum, cap->count1);
+ else
+ {
+ closeFold(curwin->w_cursor.lnum, cap->count1);
+ curwin->w_p_fen = TRUE;
+ }
+ break;
+
+ /* "zA": open fold at cursor recursively */
+ case 'A': if (hasFolding(curwin->w_cursor.lnum, NULL, NULL))
+ openFoldRecurse(curwin->w_cursor.lnum);
+ else
+ {
+ closeFoldRecurse(curwin->w_cursor.lnum);
+ curwin->w_p_fen = TRUE;
+ }
+ break;
+
+ /* "zo": open fold at cursor or Visual area */
+ case 'o': if (VIsual_active)
+ nv_operator(cap);
+ else
+ openFold(curwin->w_cursor.lnum, cap->count1);
+ break;
+
+ /* "zO": open fold recursively */
+ case 'O': if (VIsual_active)
+ nv_operator(cap);
+ else
+ openFoldRecurse(curwin->w_cursor.lnum);
+ break;
+
+ /* "zc": close fold at cursor or Visual area */
+ case 'c': if (VIsual_active)
+ nv_operator(cap);
+ else
+ closeFold(curwin->w_cursor.lnum, cap->count1);
+ curwin->w_p_fen = TRUE;
+ break;
+
+ /* "zC": close fold recursively */
+ case 'C': if (VIsual_active)
+ nv_operator(cap);
+ else
+ closeFoldRecurse(curwin->w_cursor.lnum);
+ curwin->w_p_fen = TRUE;
+ break;
+
+ /* "zv": open folds at the cursor */
+ case 'v': foldOpenCursor();
+ break;
+
+ /* "zx": re-apply 'foldlevel' and open folds at the cursor */
+ case 'x': curwin->w_p_fen = TRUE;
+ newFoldLevel(); /* update right now */
+ foldOpenCursor();
+ break;
+
+ /* "zX": undo manual opens/closes, re-apply 'foldlevel' */
+ case 'X': curwin->w_p_fen = TRUE;
+ old_fdl = -1; /* force an update */
+ break;
+
+ /* "zm": fold more */
+ case 'm': if (curwin->w_p_fdl > 0)
+ --curwin->w_p_fdl;
+ old_fdl = -1; /* force an update */
+ curwin->w_p_fen = TRUE;
+ break;
+
+ /* "zM": close all folds */
+ case 'M': curwin->w_p_fdl = 0;
+ old_fdl = -1; /* force an update */
+ curwin->w_p_fen = TRUE;
+ break;
+
+ /* "zr": reduce folding */
+ case 'r': ++curwin->w_p_fdl;
+ break;
+
+ /* "zR": open all folds */
+ case 'R': curwin->w_p_fdl = getDeepestNesting();
+ old_fdl = -1; /* force an update */
+ break;
+
+ case 'j': /* "zj" move to next fold downwards */
+ case 'k': /* "zk" move to next fold upwards */
+ if (foldMoveTo(TRUE, nchar == 'j' ? FORWARD : BACKWARD,
+ cap->count1) == FAIL)
+ clearopbeep(cap->oap);
+ break;
+
+#endif /* FEAT_FOLDING */
+
+ default: clearopbeep(cap->oap);
+ }
+
+#ifdef FEAT_FOLDING
+ /* Redraw when 'foldenable' changed */
+ if (old_fen != curwin->w_p_fen)
+ {
+# ifdef FEAT_DIFF
+ win_T *wp;
+
+ if (foldmethodIsDiff(curwin) && curwin->w_p_scb)
+ {
+ /* Adjust 'foldenable' in diff-synced windows. */
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp != curwin && foldmethodIsDiff(wp) && wp->w_p_scb)
+ {
+ wp->w_p_fen = curwin->w_p_fen;
+ changed_window_setting_win(wp);
+ }
+ }
+ }
+# endif
+ changed_window_setting();
+ }
+
+ /* Redraw when 'foldlevel' changed. */
+ if (old_fdl != curwin->w_p_fdl)
+ newFoldLevel();
+#endif
+}
+
+#ifdef FEAT_GUI
+/*
+ * Vertical scrollbar movement.
+ */
+ static void
+nv_ver_scrollbar(cap)
+ cmdarg_T *cap;
+{
+ if (cap->oap->op_type != OP_NOP)
+ clearopbeep(cap->oap);
+
+ /* Even if an operator was pending, we still want to scroll */
+ gui_do_scroll();
+}
+
+/*
+ * Horizontal scrollbar movement.
+ */
+ static void
+nv_hor_scrollbar(cap)
+ cmdarg_T *cap;
+{
+ if (cap->oap->op_type != OP_NOP)
+ clearopbeep(cap->oap);
+
+ /* Even if an operator was pending, we still want to scroll */
+ gui_do_horiz_scroll();
+}
+#endif
+
+/*
+ * "Q" command.
+ */
+ static void
+nv_exmode(cap)
+ cmdarg_T *cap;
+{
+ /*
+ * Ignore 'Q' in Visual mode, just give a beep.
+ */
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ vim_beep();
+ else
+#endif
+ if (!checkclearop(cap->oap))
+ do_exmode(FALSE);
+}
+
+/*
+ * Handle a ":" command.
+ */
+ static void
+nv_colon(cap)
+ cmdarg_T *cap;
+{
+ int old_p_im;
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ nv_operator(cap);
+ else
+#endif
+ {
+ if (cap->oap->op_type != OP_NOP)
+ {
+ /* Using ":" as a movement is characterwise exclusive. */
+ cap->oap->motion_type = MCHAR;
+ cap->oap->inclusive = FALSE;
+ }
+ else if (cap->count0)
+ {
+ /* translate "count:" into ":.,.+(count - 1)" */
+ stuffcharReadbuff('.');
+ if (cap->count0 > 1)
+ {
+ stuffReadbuff((char_u *)",.+");
+ stuffnumReadbuff((long)cap->count0 - 1L);
+ }
+ }
+
+ /* When typing, don't type below an old message */
+ if (KeyTyped)
+ compute_cmdrow();
+
+ old_p_im = p_im;
+
+ /* get a command line and execute it */
+ do_cmdline(NULL, getexline, NULL,
+ cap->oap->op_type != OP_NOP ? DOCMD_KEEPLINE : 0);
+
+ /* If 'insertmode' changed, enter or exit Insert mode */
+ if (p_im != old_p_im)
+ {
+ if (p_im)
+ restart_edit = 'i';
+ else
+ restart_edit = 0;
+ }
+
+ /* The start of the operator may have become invalid by the Ex
+ * command. */
+ if (cap->oap->op_type != OP_NOP
+ && (cap->oap->start.lnum > curbuf->b_ml.ml_line_count
+ || cap->oap->start.col >
+ STRLEN(ml_get(cap->oap->start.lnum))))
+ clearopbeep(cap->oap);
+ }
+}
+
+/*
+ * Handle CTRL-G command.
+ */
+ static void
+nv_ctrlg(cap)
+ cmdarg_T *cap;
+{
+#ifdef FEAT_VISUAL
+ if (VIsual_active) /* toggle Selection/Visual mode */
+ {
+ VIsual_select = !VIsual_select;
+ showmode();
+ }
+ else
+#endif
+ if (!checkclearop(cap->oap))
+ /* print full name if count given or :cd used */
+ fileinfo((int)cap->count0, FALSE, TRUE);
+}
+
+/*
+ * Handle CTRL-H <Backspace> command.
+ */
+ static void
+nv_ctrlh(cap)
+ cmdarg_T *cap;
+{
+#ifdef FEAT_VISUAL
+ if (VIsual_active && VIsual_select)
+ {
+ cap->cmdchar = 'x'; /* BS key behaves like 'x' in Select mode */
+ v_visop(cap);
+ }
+ else
+#endif
+ nv_left(cap);
+}
+
+/*
+ * CTRL-L: clear screen and redraw.
+ */
+ static void
+nv_clear(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearop(cap->oap))
+ {
+#if defined(__BEOS__) && !USE_THREAD_FOR_INPUT_WITH_TIMEOUT
+ /*
+ * Right now, the BeBox doesn't seem to have an easy way to detect
+ * window resizing, so we cheat and make the user detect it
+ * manually with CTRL-L instead
+ */
+ ui_get_shellsize();
+#endif
+#ifdef FEAT_SYN_HL
+ /* Clear all syntax states to force resyncing. */
+ syn_stack_free_all(curbuf);
+#endif
+ redraw_later(CLEAR);
+ }
+}
+
+/*
+ * CTRL-O: In Select mode: switch to Visual mode for one command.
+ * Otherwise: Go to older pcmark.
+ */
+ static void
+nv_ctrlo(cap)
+ cmdarg_T *cap;
+{
+#ifdef FEAT_VISUAL
+ if (VIsual_active && VIsual_select)
+ {
+ VIsual_select = FALSE;
+ showmode();
+ restart_VIsual_select = 2; /* restart Select mode later */
+ }
+ else
+#endif
+ {
+ cap->count1 = -cap->count1;
+ nv_pcmark(cap);
+ }
+}
+
+/*
+ * CTRL-^ command, short for ":e #"
+ */
+ static void
+nv_hat(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearopq(cap->oap))
+ (void)buflist_getfile((int)cap->count0, (linenr_T)0,
+ GETF_SETMARK|GETF_ALT, FALSE);
+}
+
+/*
+ * "Z" commands.
+ */
+ static void
+nv_Zet(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearopq(cap->oap))
+ {
+ switch (cap->nchar)
+ {
+ /* "ZZ": equivalent to ":x". */
+ case 'Z': do_cmdline_cmd((char_u *)"x");
+ break;
+
+ /* "ZQ": equivalent to ":q!" (Elvis compatible). */
+ case 'Q': do_cmdline_cmd((char_u *)"q!");
+ break;
+
+ default: clearopbeep(cap->oap);
+ }
+ }
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * Call nv_ident() as if "c1" was used, with "c2" as next character.
+ */
+ void
+do_nv_ident(c1, c2)
+ int c1;
+ int c2;
+{
+ oparg_T oa;
+ cmdarg_T ca;
+
+ clear_oparg(&oa);
+ vim_memset(&ca, 0, sizeof(ca));
+ ca.oap = &oa;
+ ca.cmdchar = c1;
+ ca.nchar = c2;
+ nv_ident(&ca);
+}
+#endif
+
+/*
+ * Handle the commands that use the word under the cursor.
+ * [g] CTRL-] :ta to current identifier
+ * [g] 'K' run program for current identifier
+ * [g] '*' / to current identifier or string
+ * [g] '#' ? to current identifier or string
+ * g ']' :tselect for current identifier
+ */
+ static void
+nv_ident(cap)
+ cmdarg_T *cap;
+{
+ char_u *ptr = NULL;
+ char_u *buf;
+ char_u *p;
+ char_u *kp; /* value of 'keywordprg' */
+ int kp_help; /* 'keywordprg' is ":help" */
+ int n = 0; /* init for GCC */
+ int cmdchar;
+ int g_cmd; /* "g" command */
+ char_u *aux_ptr;
+ int isman;
+ int isman_s;
+
+ if (cap->cmdchar == 'g') /* "g*", "g#", "g]" and "gCTRL-]" */
+ {
+ cmdchar = cap->nchar;
+ g_cmd = TRUE;
+ }
+ else
+ {
+ cmdchar = cap->cmdchar;
+ g_cmd = FALSE;
+ }
+
+ if (cmdchar == POUND) /* the pound sign, '#' for English keyboards */
+ cmdchar = '#';
+
+ /*
+ * The "]", "CTRL-]" and "K" commands accept an argument in Visual mode.
+ */
+ if (cmdchar == ']' || cmdchar == Ctrl_RSB || cmdchar == 'K')
+ {
+#ifdef FEAT_VISUAL
+ if (VIsual_active && get_visual_text(cap, &ptr, &n) == FAIL)
+ return;
+#endif
+ if (checkclearopq(cap->oap))
+ return;
+ }
+
+ if (ptr == NULL && (n = find_ident_under_cursor(&ptr,
+ (cmdchar == '*' || cmdchar == '#')
+ ? FIND_IDENT|FIND_STRING : FIND_IDENT)) == 0)
+ {
+ clearop(cap->oap);
+ return;
+ }
+
+ /* Allocate buffer to put the command in. Inserting backslashes can
+ * double the length of the word. p_kp / curbuf->b_p_kp could be added
+ * and some numbers. */
+ kp = (*curbuf->b_p_kp == NUL ? p_kp : curbuf->b_p_kp);
+ kp_help = (*kp == NUL || STRCMP(kp, ":he") == 0
+ || STRCMP(kp, ":help") == 0);
+ buf = alloc((unsigned)(n * 2 + 30 + STRLEN(kp)));
+ if (buf == NULL)
+ return;
+ buf[0] = NUL;
+
+ switch (cmdchar)
+ {
+ case '*':
+ case '#':
+ /*
+ * Put cursor at start of word, makes search skip the word
+ * under the cursor.
+ * Call setpcmark() first, so "*``" puts the cursor back where
+ * it was.
+ */
+ setpcmark();
+ curwin->w_cursor.col = (colnr_T) (ptr - ml_get_curline());
+
+ if (!g_cmd && vim_iswordp(ptr))
+ STRCPY(buf, "\\<");
+ no_smartcase = TRUE; /* don't use 'smartcase' now */
+ break;
+
+ case 'K':
+ if (kp_help)
+ STRCPY(buf, "he! ");
+ else
+ {
+ /* When a count is given, turn it into a range. Is this
+ * really what we want? */
+ isman = (STRCMP(kp, "man") == 0);
+ isman_s = (STRCMP(kp, "man -s") == 0);
+ if (cap->count0 != 0 && !(isman || isman_s))
+ sprintf((char *)buf, ".,.+%ld", cap->count0 - 1);
+
+ STRCAT(buf, "! ");
+ if (cap->count0 == 0 && isman_s)
+ STRCAT(buf, "man");
+ else
+ STRCAT(buf, kp);
+ STRCAT(buf, " ");
+ if (cap->count0 != 0 && (isman || isman_s))
+ {
+ sprintf((char *)buf + STRLEN(buf), "%ld", cap->count0);
+ STRCAT(buf, " ");
+ }
+ }
+ break;
+
+ case ']':
+#ifdef FEAT_CSCOPE
+ if (p_cst)
+ STRCPY(buf, "cstag ");
+ else
+#endif
+ STRCPY(buf, "ts ");
+ break;
+
+ default:
+ if (curbuf->b_help)
+ STRCPY(buf, "he! ");
+ else if (g_cmd)
+ STRCPY(buf, "tj ");
+ else
+ STRCPY(buf, "ta ");
+ }
+
+ /*
+ * Now grab the chars in the identifier
+ */
+ if (cmdchar == '*')
+ aux_ptr = (char_u *)(p_magic ? "/.*~[^$\\" : "/^$\\");
+ else if (cmdchar == '#')
+ aux_ptr = (char_u *)(p_magic ? "/?.*~[^$\\" : "/?^$\\");
+ else if (cmdchar == 'K' && !kp_help)
+ aux_ptr = (char_u *)" \t\\\"|!";
+ else
+ /* Don't escape spaces and Tabs in a tag with a backslash */
+ aux_ptr = (char_u *)"\\|\"";
+
+ p = buf + STRLEN(buf);
+ while (n-- > 0)
+ {
+ /* put a backslash before \ and some others */
+ if (vim_strchr(aux_ptr, *ptr) != NULL)
+ *p++ = '\\';
+#ifdef FEAT_MBYTE
+ /* When current byte is a part of multibyte character, copy all bytes
+ * of that character. */
+ if (has_mbyte)
+ {
+ int i;
+ int len = (*mb_ptr2len_check)(ptr) - 1;
+
+ for (i = 0; i < len && n >= 1; ++i, --n)
+ *p++ = *ptr++;
+ }
+#endif
+ *p++ = *ptr++;
+ }
+ *p = NUL;
+
+ /*
+ * Execute the command.
+ */
+ if (cmdchar == '*' || cmdchar == '#')
+ {
+ if (!g_cmd && (
+#ifdef FEAT_MBYTE
+ has_mbyte ? vim_iswordp(mb_prevptr(ml_get_curline(), ptr)) :
+#endif
+ vim_iswordc(ptr[-1])))
+ STRCAT(buf, "\\>");
+#ifdef FEAT_CMDHIST
+ /* put pattern in search history */
+ add_to_history(HIST_SEARCH, buf, TRUE, NUL);
+#endif
+ normal_search(cap, cmdchar == '*' ? '/' : '?', buf, 0);
+ }
+ else
+ do_cmdline_cmd(buf);
+
+ vim_free(buf);
+}
+
+#ifdef FEAT_VISUAL
+/*
+ * Get visually selected text, within one line only.
+ * Returns FAIL if more than one line selected.
+ */
+ static int
+get_visual_text(cap, pp, lenp)
+ cmdarg_T *cap;
+ char_u **pp; /* return: start of selected text */
+ int *lenp; /* return: length of selected text */
+{
+ if (VIsual_mode != 'V')
+ unadjust_for_sel();
+ if (VIsual.lnum != curwin->w_cursor.lnum)
+ {
+ clearopbeep(cap->oap);
+ return FAIL;
+ }
+ if (VIsual_mode == 'V')
+ {
+ *pp = ml_get_curline();
+ *lenp = (int)STRLEN(*pp);
+ }
+ else
+ {
+ if (lt(curwin->w_cursor, VIsual))
+ {
+ *pp = ml_get_pos(&curwin->w_cursor);
+ *lenp = VIsual.col - curwin->w_cursor.col + 1;
+ }
+ else
+ {
+ *pp = ml_get_pos(&VIsual);
+ *lenp = curwin->w_cursor.col - VIsual.col + 1;
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ /* Correct the length to include the whole last character. */
+ *lenp += (*mb_ptr2len_check)(*pp + (*lenp - 1)) - 1;
+#endif
+ }
+ reset_VIsual_and_resel();
+ return OK;
+}
+#endif
+
+/*
+ * CTRL-T: backwards in tag stack
+ */
+ static void
+nv_tagpop(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearopq(cap->oap))
+ do_tag((char_u *)"", DT_POP, (int)cap->count1, FALSE, TRUE);
+}
+
+/*
+ * Handle scrolling command 'H', 'L' and 'M'.
+ */
+ static void
+nv_scroll(cap)
+ cmdarg_T *cap;
+{
+ int used = 0;
+ long n;
+#ifdef FEAT_FOLDING
+ linenr_T lnum;
+#endif
+ int half;
+
+ cap->oap->motion_type = MLINE;
+ setpcmark();
+
+ if (cap->cmdchar == 'L')
+ {
+ validate_botline(); /* make sure curwin->w_botline is valid */
+ curwin->w_cursor.lnum = curwin->w_botline - 1;
+ if (cap->count1 - 1 >= curwin->w_cursor.lnum)
+ curwin->w_cursor.lnum = 1;
+ else
+ curwin->w_cursor.lnum -= cap->count1 - 1;
+ }
+ else
+ {
+ if (cap->cmdchar == 'M')
+ {
+#ifdef FEAT_DIFF
+ /* Don't count filler lines above the window. */
+ used -= diff_check_fill(curwin, curwin->w_topline)
+ - curwin->w_topfill;
+#endif
+ validate_botline(); /* make sure w_empty_rows is valid */
+ half = (curwin->w_height - curwin->w_empty_rows + 1) / 2;
+ for (n = 0; curwin->w_topline + n < curbuf->b_ml.ml_line_count; ++n)
+ {
+#ifdef FEAT_DIFF
+ /* Count half he number of filler lines to be "below this
+ * line" and half to be "above the next line". */
+ if (n > 0 && used + diff_check_fill(curwin, curwin->w_topline
+ + n) / 2 >= half)
+ {
+ --n;
+ break;
+ }
+#endif
+ used += plines(curwin->w_topline + n);
+ if (used >= half)
+ break;
+#ifdef FEAT_FOLDING
+ if (hasFolding(curwin->w_topline + n, NULL, &lnum))
+ n = lnum - curwin->w_topline;
+#endif
+ }
+ if (n > 0 && used > curwin->w_height)
+ --n;
+ }
+ else
+ n = cap->count1 - 1;
+ curwin->w_cursor.lnum = curwin->w_topline + n;
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ }
+
+ cursor_correct(); /* correct for 'so' */
+ beginline(BL_SOL | BL_FIX);
+}
+
+/*
+ * Cursor right commands.
+ */
+ static void
+nv_right(cap)
+ cmdarg_T *cap;
+{
+ long n;
+#ifdef FEAT_VISUAL
+ int PAST_LINE;
+#else
+# define PAST_LINE 0
+#endif
+
+ cap->oap->motion_type = MCHAR;
+ cap->oap->inclusive = FALSE;
+#ifdef FEAT_VISUAL
+ PAST_LINE = (VIsual_active && *p_sel != 'o');
+
+# ifdef FEAT_VIRTUALEDIT
+ /*
+ * In virtual mode, there's no such thing as "PAST_LINE", as lines are
+ * (theoretically) infinitly long.
+ */
+ if (virtual_active())
+ PAST_LINE = 0;
+# endif
+#endif
+
+ for (n = cap->count1; n > 0; --n)
+ {
+ if ((!PAST_LINE && oneright() == FAIL)
+ || (PAST_LINE && *ml_get_cursor() == NUL))
+ {
+ /*
+ * <Space> wraps to next line if 'whichwrap' bit 1 set.
+ * 'l' wraps to next line if 'whichwrap' bit 2 set.
+ * CURS_RIGHT wraps to next line if 'whichwrap' bit 3 set
+ */
+ if ( ((cap->cmdchar == ' '
+ && vim_strchr(p_ww, 's') != NULL)
+ || (cap->cmdchar == 'l'
+ && vim_strchr(p_ww, 'l') != NULL)
+ || (cap->cmdchar == K_RIGHT
+ && vim_strchr(p_ww, '>') != NULL))
+ && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
+ {
+ /* When deleting we also count the NL as a character.
+ * Set cap->oap->inclusive when last char in the line is
+ * included, move to next line after that */
+ if ( (cap->oap->op_type == OP_DELETE
+ || cap->oap->op_type == OP_CHANGE)
+ && !cap->oap->inclusive
+ && !lineempty(curwin->w_cursor.lnum))
+ cap->oap->inclusive = TRUE;
+ else
+ {
+ ++curwin->w_cursor.lnum;
+ curwin->w_cursor.col = 0;
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ curwin->w_set_curswant = TRUE;
+ cap->oap->inclusive = FALSE;
+ }
+ continue;
+ }
+ if (cap->oap->op_type == OP_NOP)
+ {
+ /* Only beep and flush if not moved at all */
+ if (n == cap->count1)
+ beep_flush();
+ }
+ else
+ {
+ if (!lineempty(curwin->w_cursor.lnum))
+ cap->oap->inclusive = TRUE;
+ }
+ break;
+ }
+#ifdef FEAT_VISUAL
+ else if (PAST_LINE)
+ {
+ curwin->w_set_curswant = TRUE;
+# ifdef FEAT_VIRTUALEDIT
+ if (virtual_active())
+ oneright();
+ else
+# endif
+ {
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ curwin->w_cursor.col +=
+ (*mb_ptr2len_check)(ml_get_cursor());
+ else
+# endif
+ ++curwin->w_cursor.col;
+ }
+ }
+#endif
+ }
+#ifdef FEAT_FOLDING
+ if (n != cap->count1 && (fdo_flags & FDO_HOR) && KeyTyped
+ && cap->oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+}
+
+/*
+ * Cursor left commands.
+ *
+ * Returns TRUE when operator end should not be adjusted.
+ */
+ static void
+nv_left(cap)
+ cmdarg_T *cap;
+{
+ long n;
+
+ cap->oap->motion_type = MCHAR;
+ cap->oap->inclusive = FALSE;
+ for (n = cap->count1; n > 0; --n)
+ {
+ if (oneleft() == FAIL)
+ {
+ /* <BS> and <Del> wrap to previous line if 'whichwrap' has 'b'.
+ * 'h' wraps to previous line if 'whichwrap' has 'h'.
+ * CURS_LEFT wraps to previous line if 'whichwrap' has '<'.
+ */
+ if ( (((cap->cmdchar == K_BS
+ || cap->cmdchar == Ctrl_H)
+ && vim_strchr(p_ww, 'b') != NULL)
+ || (cap->cmdchar == 'h'
+ && vim_strchr(p_ww, 'h') != NULL)
+ || (cap->cmdchar == K_LEFT
+ && vim_strchr(p_ww, '<') != NULL))
+ && curwin->w_cursor.lnum > 1)
+ {
+ --(curwin->w_cursor.lnum);
+ coladvance((colnr_T)MAXCOL);
+ curwin->w_set_curswant = TRUE;
+
+ /* When the NL before the first char has to be deleted we
+ * put the cursor on the NUL after the previous line.
+ * This is a very special case, be careful!
+ * don't adjust op_end now, otherwise it won't work */
+ if ( (cap->oap->op_type == OP_DELETE
+ || cap->oap->op_type == OP_CHANGE)
+ && !lineempty(curwin->w_cursor.lnum))
+ {
+ ++curwin->w_cursor.col;
+ cap->retval |= CA_NO_ADJ_OP_END;
+ }
+ continue;
+ }
+ /* Only beep and flush if not moved at all */
+ else if (cap->oap->op_type == OP_NOP && n == cap->count1)
+ beep_flush();
+ break;
+ }
+ }
+#ifdef FEAT_FOLDING
+ if (n != cap->count1 && (fdo_flags & FDO_HOR) && KeyTyped
+ && cap->oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+}
+
+/*
+ * Cursor up commands.
+ * cap->arg is TRUE for "-": Move cursor to first non-blank.
+ */
+ static void
+nv_up(cap)
+ cmdarg_T *cap;
+{
+ cap->oap->motion_type = MLINE;
+ if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == FAIL)
+ clearopbeep(cap->oap);
+ else if (cap->arg)
+ beginline(BL_WHITE | BL_FIX);
+}
+
+/*
+ * Cursor down commands.
+ * cap->arg is TRUE for CR and "+": Move cursor to first non-blank.
+ */
+ static void
+nv_down(cap)
+ cmdarg_T *cap;
+{
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ /* In a quickfix window a <CR> jumps to the error under the cursor. */
+ if (bt_quickfix(curbuf) && cap->cmdchar == '\r')
+ do_cmdline_cmd((char_u *)".cc");
+ else
+#endif
+ {
+#ifdef FEAT_CMDWIN
+ /* In the cmdline window a <CR> executes the command. */
+ if (cmdwin_type != 0 && cap->cmdchar == '\r')
+ cmdwin_result = CAR;
+ else
+#endif
+ {
+ cap->oap->motion_type = MLINE;
+ if (cursor_down(cap->count1, cap->oap->op_type == OP_NOP) == FAIL)
+ clearopbeep(cap->oap);
+ else if (cap->arg)
+ beginline(BL_WHITE | BL_FIX);
+ }
+ }
+}
+
+#ifdef FEAT_SEARCHPATH
+/*
+ * Grab the file name under the cursor and edit it.
+ */
+ static void
+nv_gotofile(cap)
+ cmdarg_T *cap;
+{
+ char_u *ptr;
+
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ {
+ clearopbeep(cap->oap);
+ return;
+ }
+#endif
+
+# ifdef FEAT_VISUAL
+ /*
+ * In Visual mode, use the selected text as a file name.
+ * Don't allow selection across multiple lines.
+ */
+ if (VIsual_active)
+ {
+ int len;
+
+ if (get_visual_text(cap, &ptr, &len) == FAIL)
+ return;
+ ptr = find_file_name_in_path(ptr, len,
+ FNAME_MESS|FNAME_EXP|FNAME_REL, cap->count1, curbuf->b_ffname);
+ }
+ else
+# endif
+ ptr = file_name_at_cursor(FNAME_MESS|FNAME_HYP|FNAME_EXP|FNAME_REL,
+ cap->count1);
+
+ if (ptr != NULL)
+ {
+ /* do autowrite if necessary */
+ if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !P_HID(curbuf))
+ autowrite(curbuf, FALSE);
+ setpcmark();
+ (void)do_ecmd(0, ptr, NULL, NULL, ECMD_LAST,
+ P_HID(curbuf) ? ECMD_HIDE : 0);
+ vim_free(ptr);
+ }
+ else
+ clearop(cap->oap);
+}
+#endif
+
+/*
+ * <End> command: to end of current line or last line.
+ */
+ static void
+nv_end(cap)
+ cmdarg_T *cap;
+{
+ if (cap->arg) /* CTRL-END = goto last line */
+ {
+ nv_goto(cap);
+ cap->count1 = 1; /* to end of current line */
+ }
+ nv_dollar(cap);
+}
+
+/*
+ * Handle the "$" command.
+ */
+ static void
+nv_dollar(cap)
+ cmdarg_T *cap;
+{
+ cap->oap->motion_type = MCHAR;
+ cap->oap->inclusive = TRUE;
+#ifdef FEAT_VIRTUALEDIT
+ /* In virtual mode when off the edge of a line and an operator
+ * is pending (whew!) keep the cursor where it is.
+ * Otherwise, send it to the end of the line. */
+ if (!virtual_active() || gchar_cursor() != NUL
+ || cap->oap->op_type == OP_NOP)
+#endif
+ curwin->w_curswant = MAXCOL; /* so we stay at the end */
+ if (cursor_down((long)(cap->count1 - 1),
+ cap->oap->op_type == OP_NOP) == FAIL)
+ clearopbeep(cap->oap);
+#ifdef FEAT_FOLDING
+ else if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+}
+
+/*
+ * Implementation of '?' and '/' commands.
+ * If cap->arg is TRUE don't set PC mark.
+ */
+ static void
+nv_search(cap)
+ cmdarg_T *cap;
+{
+ oparg_T *oap = cap->oap;
+
+ if (cap->cmdchar == '?' && cap->oap->op_type == OP_ROT13)
+ {
+ /* Translate "g??" to "g?g?" */
+ cap->cmdchar = 'g';
+ cap->nchar = '?';
+ nv_operator(cap);
+ return;
+ }
+
+ cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0);
+
+ if (cap->searchbuf == NULL)
+ {
+ clearop(oap);
+ return;
+ }
+
+ normal_search(cap, cap->cmdchar, cap->searchbuf,
+ (cap->arg ? 0 : SEARCH_MARK));
+}
+
+/*
+ * Handle "N" and "n" commands.
+ * cap->arg is SEARCH_REV for "N", 0 for "n".
+ */
+ static void
+nv_next(cap)
+ cmdarg_T *cap;
+{
+ normal_search(cap, 0, NULL, SEARCH_MARK | cap->arg);
+}
+
+/*
+ * Search for "pat" in direction "dir" ('/' or '?', 0 for repeat).
+ * Uses only cap->count1 and cap->oap from "cap".
+ */
+ static void
+normal_search(cap, dir, pat, opt)
+ cmdarg_T *cap;
+ int dir;
+ char_u *pat;
+ int opt; /* extra flags for do_search() */
+{
+ int i;
+
+ cap->oap->motion_type = MCHAR;
+ cap->oap->inclusive = FALSE;
+ cap->oap->use_reg_one = TRUE;
+ curwin->w_set_curswant = TRUE;
+
+ i = do_search(cap->oap, dir, pat, cap->count1,
+ opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG);
+ if (i == 0)
+ clearop(cap->oap);
+ else
+ {
+ if (i == 2)
+ cap->oap->motion_type = MLINE;
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+#ifdef FEAT_FOLDING
+ if (cap->oap->op_type == OP_NOP && (fdo_flags & FDO_SEARCH) && KeyTyped)
+ foldOpenCursor();
+#endif
+ }
+
+ /* "/$" will put the cursor after the end of the line, may need to
+ * correct that here */
+ check_cursor();
+}
+
+/*
+ * Character search commands.
+ * cap->arg is BACKWARD for 'F' and 'T', FORWARD for 'f' and 't', TRUE for
+ * ',' and FALSE for ';'.
+ * cap->nchar is NUL for ',' and ';' (repeat the search)
+ */
+ static void
+nv_csearch(cap)
+ cmdarg_T *cap;
+{
+ int t_cmd;
+
+ if (cap->cmdchar == 't' || cap->cmdchar == 'T')
+ t_cmd = TRUE;
+ else
+ t_cmd = FALSE;
+
+ cap->oap->motion_type = MCHAR;
+ if (cap->arg == BACKWARD)
+ cap->oap->inclusive = FALSE;
+ else
+ cap->oap->inclusive = TRUE;
+ if (IS_SPECIAL(cap->nchar) || searchc(cap, t_cmd) == FAIL)
+ clearopbeep(cap->oap);
+ else
+ {
+ curwin->w_set_curswant = TRUE;
+#ifdef FEAT_VIRTUALEDIT
+ /* Include a Tab for "tx" and for "dfx". */
+ if (gchar_cursor() == TAB && virtual_active() && cap->arg == FORWARD
+ && (t_cmd || cap->oap->op_type != OP_NOP))
+ {
+ colnr_T scol, ecol;
+
+ getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
+ curwin->w_cursor.coladd = ecol - scol;
+ }
+ else
+ curwin->w_cursor.coladd = 0;
+#endif
+#ifdef FEAT_VISUAL
+ adjust_for_sel(cap);
+#endif
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+ }
+}
+
+/*
+ * "[" and "]" commands.
+ * cap->arg is BACKWARD for "[" and FORWARD for "]".
+ */
+ static void
+nv_brackets(cap)
+ cmdarg_T *cap;
+{
+ pos_T new_pos;
+ pos_T prev_pos;
+ pos_T *pos = NULL; /* init for GCC */
+ pos_T old_pos; /* cursor position before command */
+ int flag;
+ long n;
+ int findc;
+ int c;
+
+ cap->oap->motion_type = MCHAR;
+ cap->oap->inclusive = FALSE;
+ old_pos = curwin->w_cursor;
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0; /* TODO: don't do this for an error. */
+#endif
+
+#ifdef FEAT_SEARCHPATH
+ /*
+ * "[f" or "]f" : Edit file under the cursor (same as "gf")
+ */
+ if (cap->nchar == 'f')
+ nv_gotofile(cap);
+ else
+#endif
+
+#ifdef FEAT_FIND_ID
+ /*
+ * Find the occurence(s) of the identifier or define under cursor
+ * in current and included files or jump to the first occurence.
+ *
+ * search list jump
+ * fwd bwd fwd bwd fwd bwd
+ * identifier "]i" "[i" "]I" "[I" "]^I" "[^I"
+ * define "]d" "[d" "]D" "[D" "]^D" "[^D"
+ */
+ if (vim_strchr((char_u *)
+#ifdef EBCDIC
+ "iI\005dD\067",
+#else
+ "iI\011dD\004",
+#endif
+ cap->nchar) != NULL)
+ {
+ char_u *ptr;
+ int len;
+
+ if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0)
+ clearop(cap->oap);
+ else
+ {
+ find_pattern_in_path(ptr, 0, len, TRUE,
+ cap->count0 == 0 ? !isupper(cap->nchar) : FALSE,
+ ((cap->nchar & 0xf) == ('d' & 0xf)) ? FIND_DEFINE : FIND_ANY,
+ cap->count1,
+ isupper(cap->nchar) ? ACTION_SHOW_ALL :
+ islower(cap->nchar) ? ACTION_SHOW : ACTION_GOTO,
+ cap->cmdchar == ']' ? curwin->w_cursor.lnum + 1 : (linenr_T)1,
+ (linenr_T)MAXLNUM);
+ curwin->w_set_curswant = TRUE;
+ }
+ }
+ else
+#endif
+
+ /*
+ * "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')'
+ * "[#", "]#": go to start/end of Nth innermost #if..#endif construct.
+ * "[/", "[*", "]/", "]*": go to Nth comment start/end.
+ * "[m" or "]m" search for prev/next start of (Java) method.
+ * "[M" or "]M" search for prev/next end of (Java) method.
+ */
+ if ( (cap->cmdchar == '['
+ && vim_strchr((char_u *)"{(*/#mM", cap->nchar) != NULL)
+ || (cap->cmdchar == ']'
+ && vim_strchr((char_u *)"})*/#mM", cap->nchar) != NULL))
+ {
+ if (cap->nchar == '*')
+ cap->nchar = '/';
+ new_pos.lnum = 0;
+ prev_pos.lnum = 0;
+ if (cap->nchar == 'm' || cap->nchar == 'M')
+ {
+ if (cap->cmdchar == '[')
+ findc = '{';
+ else
+ findc = '}';
+ n = 9999;
+ }
+ else
+ {
+ findc = cap->nchar;
+ n = cap->count1;
+ }
+ for ( ; n > 0; --n)
+ {
+ if ((pos = findmatchlimit(cap->oap, findc,
+ (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD, 0)) == NULL)
+ {
+ if (new_pos.lnum == 0) /* nothing found */
+ {
+ if (cap->nchar != 'm' && cap->nchar != 'M')
+ clearopbeep(cap->oap);
+ }
+ else
+ pos = &new_pos; /* use last one found */
+ break;
+ }
+ prev_pos = new_pos;
+ curwin->w_cursor = *pos;
+ new_pos = *pos;
+ }
+ curwin->w_cursor = old_pos;
+
+ /*
+ * Handle "[m", "]m", "[M" and "[M". The findmatchlimit() only
+ * brought us to the match for "[m" and "]M" when inside a method.
+ * Try finding the '{' or '}' we want to be at.
+ * Also repeat for the given count.
+ */
+ if (cap->nchar == 'm' || cap->nchar == 'M')
+ {
+ /* norm is TRUE for "]M" and "[m" */
+ int norm = ((findc == '{') == (cap->nchar == 'm'));
+
+ n = cap->count1;
+ /* found a match: we were inside a method */
+ if (prev_pos.lnum != 0)
+ {
+ pos = &prev_pos;
+ curwin->w_cursor = prev_pos;
+ if (norm)
+ --n;
+ }
+ else
+ pos = NULL;
+ while (n > 0)
+ {
+ for (;;)
+ {
+ if ((findc == '{' ? dec_cursor() : inc_cursor()) < 0)
+ {
+ /* if not found anything, that's an error */
+ if (pos == NULL)
+ clearopbeep(cap->oap);
+ n = 0;
+ break;
+ }
+ c = gchar_cursor();
+ if (c == '{' || c == '}')
+ {
+ /* Must have found end/start of class: use it.
+ * Or found the place to be at. */
+ if ((c == findc && norm) || (n == 1 && !norm))
+ {
+ new_pos = curwin->w_cursor;
+ pos = &new_pos;
+ n = 0;
+ }
+ /* if no match found at all, we started outside of the
+ * class and we're inside now. Just go on. */
+ else if (new_pos.lnum == 0)
+ {
+ new_pos = curwin->w_cursor;
+ pos = &new_pos;
+ }
+ /* found start/end of other method: go to match */
+ else if ((pos = findmatchlimit(cap->oap, findc,
+ (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD,
+ 0)) == NULL)
+ n = 0;
+ else
+ curwin->w_cursor = *pos;
+ break;
+ }
+ }
+ --n;
+ }
+ curwin->w_cursor = old_pos;
+ if (pos == NULL && new_pos.lnum != 0)
+ clearopbeep(cap->oap);
+ }
+ if (pos != NULL)
+ {
+ setpcmark();
+ curwin->w_cursor = *pos;
+ curwin->w_set_curswant = TRUE;
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_BLOCK) && KeyTyped
+ && cap->oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+ }
+ }
+
+ /*
+ * "[[", "[]", "]]" and "][": move to start or end of function
+ */
+ else if (cap->nchar == '[' || cap->nchar == ']')
+ {
+ if (cap->nchar == cap->cmdchar) /* "]]" or "[[" */
+ flag = '{';
+ else
+ flag = '}'; /* "][" or "[]" */
+
+ curwin->w_set_curswant = TRUE;
+ /*
+ * Imitate strange Vi behaviour: When using "]]" with an operator
+ * we also stop at '}'.
+ */
+ if (!findpar(cap->oap, cap->arg, cap->count1, flag,
+ (cap->oap->op_type != OP_NOP
+ && cap->arg == FORWARD && flag == '{')))
+ clearopbeep(cap->oap);
+ else
+ {
+ if (cap->oap->op_type == OP_NOP)
+ beginline(BL_WHITE | BL_FIX);
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+ }
+ }
+
+ /*
+ * "[p", "[P", "]P" and "]p": put with indent adjustment
+ */
+ else if (cap->nchar == 'p' || cap->nchar == 'P')
+ {
+ if (!checkclearopq(cap->oap))
+ {
+ prep_redo_cmd(cap);
+ do_put(cap->oap->regname,
+ (cap->cmdchar == ']' && cap->nchar == 'p') ? FORWARD : BACKWARD,
+ cap->count1, PUT_FIXINDENT);
+ }
+ }
+
+ /*
+ * "['", "[`", "]'" and "]`": jump to next mark
+ */
+ else if (cap->nchar == '\'' || cap->nchar == '`')
+ {
+ pos = &curwin->w_cursor;
+ for (n = cap->count1; n > 0; --n)
+ {
+ prev_pos = *pos;
+ pos = getnextmark(pos, cap->cmdchar == '[' ? BACKWARD : FORWARD,
+ cap->nchar == '\'');
+ if (pos == NULL)
+ break;
+ }
+ if (pos == NULL)
+ pos = &prev_pos;
+ nv_cursormark(cap, cap->nchar == '\'', pos);
+ }
+
+#ifdef FEAT_MOUSE
+ /*
+ * [ or ] followed by a middle mouse click: put selected text with
+ * indent adjustment. Any other button just does as usual.
+ */
+ else if (cap->nchar >= K_LEFTMOUSE && cap->nchar <= K_RIGHTRELEASE)
+ {
+ (void)do_mouse(cap->oap, cap->nchar,
+ (cap->cmdchar == ']') ? FORWARD : BACKWARD,
+ cap->count1, PUT_FIXINDENT);
+ }
+#endif /* FEAT_MOUSE */
+
+#ifdef FEAT_FOLDING
+ /*
+ * "[z" and "]z": move to start or end of open fold.
+ */
+ else if (cap->nchar == 'z')
+ {
+ if (foldMoveTo(FALSE, cap->cmdchar == ']' ? FORWARD : BACKWARD,
+ cap->count1) == FAIL)
+ clearopbeep(cap->oap);
+ }
+#endif
+
+#ifdef FEAT_DIFF
+ /*
+ * "[c" and "]c": move to next or previous diff-change.
+ */
+ else if (cap->nchar == 'c')
+ {
+ if (diff_move_to(cap->cmdchar == ']' ? FORWARD : BACKWARD,
+ cap->count1) == FAIL)
+ clearopbeep(cap->oap);
+ }
+#endif
+
+ /* Not a valid cap->nchar. */
+ else
+ clearopbeep(cap->oap);
+}
+
+/*
+ * Handle Normal mode "%" command.
+ */
+ static void
+nv_percent(cap)
+ cmdarg_T *cap;
+{
+ pos_T *pos;
+#ifdef FEAT_FOLDING
+ linenr_T lnum = curwin->w_cursor.lnum;
+#endif
+
+ cap->oap->inclusive = TRUE;
+ if (cap->count0) /* {cnt}% : goto {cnt} percentage in file */
+ {
+ if (cap->count0 > 100)
+ clearopbeep(cap->oap);
+ else
+ {
+ cap->oap->motion_type = MLINE;
+ setpcmark();
+ /* Round up, so CTRL-G will give same value. Watch out for a
+ * large line count, the line number must not go negative! */
+ if (curbuf->b_ml.ml_line_count > 1000000)
+ curwin->w_cursor.lnum = (curbuf->b_ml.ml_line_count + 99L)
+ / 100L * cap->count0;
+ else
+ curwin->w_cursor.lnum = (curbuf->b_ml.ml_line_count *
+ cap->count0 + 99L) / 100L;
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ beginline(BL_SOL | BL_FIX);
+ }
+ }
+ else /* "%" : go to matching paren */
+ {
+ cap->oap->motion_type = MCHAR;
+ cap->oap->use_reg_one = TRUE;
+ if ((pos = findmatch(cap->oap, NUL)) == NULL)
+ clearopbeep(cap->oap);
+ else
+ {
+ setpcmark();
+ curwin->w_cursor = *pos;
+ curwin->w_set_curswant = TRUE;
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+#ifdef FEAT_VISUAL
+ adjust_for_sel(cap);
+#endif
+ }
+ }
+#ifdef FEAT_FOLDING
+ if (cap->oap->op_type == OP_NOP
+ && lnum != curwin->w_cursor.lnum
+ && (fdo_flags & FDO_PERCENT)
+ && KeyTyped)
+ foldOpenCursor();
+#endif
+}
+
+/*
+ * Handle "(" and ")" commands.
+ * cap->arg is BACKWARD for "(" and FORWARD for ")".
+ */
+ static void
+nv_brace(cap)
+ cmdarg_T *cap;
+{
+ cap->oap->motion_type = MCHAR;
+ cap->oap->use_reg_one = TRUE;
+ if (cap->cmdchar == ')')
+ cap->oap->inclusive = FALSE;
+ else
+ cap->oap->inclusive = TRUE;
+ curwin->w_set_curswant = TRUE;
+
+ if (findsent(cap->arg, cap->count1) == FAIL)
+ clearopbeep(cap->oap);
+ else
+ {
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+ }
+}
+
+/*
+ * "m" command: Mark a position.
+ */
+ static void
+nv_mark(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearop(cap->oap))
+ {
+ if (setmark(cap->nchar) == FAIL)
+ clearopbeep(cap->oap);
+ }
+}
+
+/*
+ * "{" and "}" commands.
+ * cmd->arg is BACKWARD for "{" and FORWARD for "}".
+ */
+ static void
+nv_findpar(cap)
+ cmdarg_T *cap;
+{
+ cap->oap->motion_type = MCHAR;
+ cap->oap->inclusive = FALSE;
+ cap->oap->use_reg_one = TRUE;
+ curwin->w_set_curswant = TRUE;
+ if (!findpar(cap->oap, cap->arg, cap->count1, NUL, FALSE))
+ clearopbeep(cap->oap);
+ else
+ {
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+ }
+}
+
+/*
+ * "u" command: Undo or make lower case.
+ */
+ static void
+nv_undo(cap)
+ cmdarg_T *cap;
+{
+ if (cap->oap->op_type == OP_LOWER
+#ifdef FEAT_VISUAL
+ || VIsual_active
+#endif
+ )
+ {
+ /* translate "<Visual>u" to "<Visual>gu" and "guu" to "gugu" */
+ cap->cmdchar = 'g';
+ cap->nchar = 'u';
+ nv_operator(cap);
+ }
+ else
+ nv_kundo(cap);
+}
+
+/*
+ * <Undo> command.
+ */
+ static void
+nv_kundo(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearopq(cap->oap))
+ {
+ u_undo((int)cap->count1);
+ curwin->w_set_curswant = TRUE;
+ }
+}
+
+/*
+ * Handle the "r" command.
+ */
+ static void
+nv_replace(cap)
+ cmdarg_T *cap;
+{
+ char_u *ptr;
+ int had_ctrl_v;
+ long n;
+
+ if (checkclearop(cap->oap))
+ return;
+
+ /* get another character */
+ if (cap->nchar == Ctrl_V)
+ {
+ had_ctrl_v = Ctrl_V;
+ cap->nchar = get_literal();
+ /* Don't redo a multibyte character with CTRL-V. */
+ if (cap->nchar > DEL)
+ had_ctrl_v = NUL;
+ }
+ else
+ had_ctrl_v = NUL;
+
+#ifdef FEAT_VISUAL
+ /* Visual mode "r" */
+ if (VIsual_active)
+ {
+ nv_operator(cap);
+ return;
+ }
+#endif
+
+#ifdef FEAT_VIRTUALEDIT
+ /* Break tabs, etc. */
+ if (virtual_active())
+ {
+ if (u_save_cursor() == FAIL)
+ return;
+ if (gchar_cursor() == NUL)
+ {
+ /* Add extra space and put the cursor on the first one. */
+ coladvance_force((colnr_T)(getviscol() + cap->count1));
+ curwin->w_cursor.col -= cap->count1;
+ }
+ else if (gchar_cursor() == TAB)
+ coladvance_force(getviscol());
+ }
+#endif
+
+ /*
+ * Check for a special key or not enough characters to replace.
+ */
+ ptr = ml_get_cursor();
+ if (IS_SPECIAL(cap->nchar) || STRLEN(ptr) < (unsigned)cap->count1
+#ifdef FEAT_MBYTE
+ || (has_mbyte && mb_charlen(ptr) < cap->count1)
+#endif
+ )
+ {
+ clearopbeep(cap->oap);
+ return;
+ }
+
+ /*
+ * Replacing with a TAB is done by edit() when it is complicated because
+ * 'expandtab' or 'smarttab' is set. CTRL-V TAB inserts a literal TAB.
+ * Other characters are done below to avoid problems with things like
+ * CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC).
+ */
+ if (had_ctrl_v != Ctrl_V && cap->nchar == '\t' && (curbuf->b_p_et || p_sta))
+ {
+ stuffnumReadbuff(cap->count1);
+ stuffcharReadbuff('R');
+ stuffcharReadbuff('\t');
+ stuffcharReadbuff(ESC);
+ return;
+ }
+
+ /* save line for undo */
+ if (u_save_cursor() == FAIL)
+ return;
+
+ if (had_ctrl_v != Ctrl_V && (cap->nchar == '\r' || cap->nchar == '\n'))
+ {
+ /*
+ * Replace character(s) by a single newline.
+ * Strange vi behaviour: Only one newline is inserted.
+ * Delete the characters here.
+ * Insert the newline with an insert command, takes care of
+ * autoindent. The insert command depends on being on the last
+ * character of a line or not.
+ */
+#ifdef FEAT_MBYTE
+ (void)del_chars(cap->count1, FALSE); /* delete the characters */
+#else
+ (void)del_bytes(cap->count1, FALSE); /* delete the characters */
+#endif
+ stuffcharReadbuff('\r');
+ stuffcharReadbuff(ESC);
+
+ /* Give 'r' to edit(), to get the redo command right. */
+ invoke_edit(cap, TRUE, 'r', FALSE);
+ }
+ else
+ {
+ prep_redo(cap->oap->regname, cap->count1,
+ NUL, 'r', NUL, had_ctrl_v, cap->nchar);
+
+ curbuf->b_op_start = curwin->w_cursor;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int old_State = State;
+
+ if (cap->ncharC1 != 0)
+ AppendCharToRedobuff(cap->ncharC1);
+ if (cap->ncharC2 != 0)
+ AppendCharToRedobuff(cap->ncharC2);
+
+ /* This is slow, but it handles replacing a single-byte with a
+ * multi-byte and the other way around. Also handles adding
+ * composing characters for utf-8. */
+ for (n = cap->count1; n > 0; --n)
+ {
+ State = REPLACE;
+ ins_char(cap->nchar);
+ State = old_State;
+ if (cap->ncharC1 != 0)
+ ins_char(cap->ncharC1);
+ if (cap->ncharC2 != 0)
+ ins_char(cap->ncharC2);
+ }
+ }
+ else
+#endif
+ {
+ /*
+ * Replace the characters within one line.
+ */
+ for (n = cap->count1; n > 0; --n)
+ {
+ /*
+ * Get ptr again, because u_save and/or showmatch() will have
+ * released the line. At the same time we let know that the
+ * line will be changed.
+ */
+ ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE);
+ ptr[curwin->w_cursor.col] = cap->nchar;
+ if (p_sm && msg_silent == 0)
+ showmatch(cap->nchar);
+ ++curwin->w_cursor.col;
+ }
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ {
+ colnr_T start = (colnr_T)(curwin->w_cursor.col - cap->count1);
+
+ netbeans_inserted(curbuf, curwin->w_cursor.lnum, start,
+ (int)cap->count1, &ptr[start], (int)cap->count1);
+ }
+#endif
+
+ /* mark the buffer as changed and prepare for displaying */
+ changed_bytes(curwin->w_cursor.lnum,
+ (colnr_T)(curwin->w_cursor.col - cap->count1));
+ }
+ --curwin->w_cursor.col; /* cursor on the last replaced char */
+#ifdef FEAT_MBYTE
+ /* if the character on the left of the current cursor is a multi-byte
+ * character, move two characters left */
+ if (has_mbyte)
+ mb_adjust_cursor();
+#endif
+ curbuf->b_op_end = curwin->w_cursor;
+ curwin->w_set_curswant = TRUE;
+ set_last_insert(cap->nchar);
+ }
+}
+
+#ifdef FEAT_VISUAL
+/*
+ * 'o': Exchange start and end of Visual area.
+ * 'O': same, but in block mode exchange left and right corners.
+ */
+ static void
+v_swap_corners(cmdchar)
+ int cmdchar;
+{
+ pos_T old_cursor;
+ colnr_T left, right;
+
+ if (cmdchar == 'O' && VIsual_mode == Ctrl_V)
+ {
+ old_cursor = curwin->w_cursor;
+ getvcols(curwin, &old_cursor, &VIsual, &left, &right);
+ curwin->w_cursor.lnum = VIsual.lnum;
+ coladvance(left);
+ VIsual = curwin->w_cursor;
+
+ curwin->w_cursor.lnum = old_cursor.lnum;
+ curwin->w_curswant = right;
+ /* 'selection "exclusive" and cursor at right-bottom corner: move it
+ * right one column */
+ if (old_cursor.lnum >= VIsual.lnum && *p_sel == 'e')
+ ++curwin->w_curswant;
+ coladvance(curwin->w_curswant);
+ if (curwin->w_cursor.col == old_cursor.col
+#ifdef FEAT_VIRTUALEDIT
+ && (!virtual_active()
+ || curwin->w_cursor.coladd == old_cursor.coladd)
+#endif
+ )
+ {
+ curwin->w_cursor.lnum = VIsual.lnum;
+ if (old_cursor.lnum <= VIsual.lnum && *p_sel == 'e')
+ ++right;
+ coladvance(right);
+ VIsual = curwin->w_cursor;
+
+ curwin->w_cursor.lnum = old_cursor.lnum;
+ coladvance(left);
+ curwin->w_curswant = left;
+ }
+ }
+ else
+ {
+ old_cursor = curwin->w_cursor;
+ curwin->w_cursor = VIsual;
+ VIsual = old_cursor;
+ curwin->w_set_curswant = TRUE;
+ }
+}
+#endif /* FEAT_VISUAL */
+
+/*
+ * "R" (cap->arg is FALSE) and "gR" (cap->arg is TRUE).
+ */
+ static void
+nv_Replace(cap)
+ cmdarg_T *cap;
+{
+#ifdef FEAT_VISUAL
+ if (VIsual_active) /* "R" is replace lines */
+ {
+ cap->cmdchar = 'c';
+ cap->nchar = NUL;
+ VIsual_mode = 'V';
+ nv_operator(cap);
+ }
+ else
+#endif
+ if (!checkclearopq(cap->oap))
+ {
+ if (!curbuf->b_p_ma)
+ EMSG(_(e_modifiable));
+ else
+ {
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_active())
+ coladvance(getviscol());
+#endif
+ invoke_edit(cap, FALSE, cap->arg ? 'V' : 'R', FALSE);
+ }
+ }
+}
+
+#ifdef FEAT_VREPLACE
+/*
+ * "gr".
+ */
+ static void
+nv_vreplace(cap)
+ cmdarg_T *cap;
+{
+# ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ cap->cmdchar = 'r';
+ cap->nchar = cap->extra_char;
+ nv_replace(cap); /* Do same as "r" in Visual mode for now */
+ }
+ else
+# endif
+ if (!checkclearopq(cap->oap))
+ {
+ if (!curbuf->b_p_ma)
+ EMSG(_(e_modifiable));
+ else
+ {
+ if (cap->extra_char == Ctrl_V) /* get another character */
+ cap->extra_char = get_literal();
+ stuffcharReadbuff(cap->extra_char);
+ stuffcharReadbuff(ESC);
+# ifdef FEAT_VIRTUALEDIT
+ if (virtual_active())
+ coladvance(getviscol());
+# endif
+ invoke_edit(cap, TRUE, 'v', FALSE);
+ }
+ }
+}
+#endif
+
+/*
+ * Swap case for "~" command, when it does not work like an operator.
+ */
+ static void
+n_swapchar(cap)
+ cmdarg_T *cap;
+{
+ long n;
+ pos_T startpos;
+ int did_change = 0;
+#ifdef FEAT_NETBEANS_INTG
+ pos_T pos;
+ char_u *ptr;
+ int count;
+#endif
+
+ if (checkclearopq(cap->oap))
+ return;
+
+ if (lineempty(curwin->w_cursor.lnum) && vim_strchr(p_ww, '~') == NULL)
+ {
+ clearopbeep(cap->oap);
+ return;
+ }
+
+ prep_redo_cmd(cap);
+
+ if (u_save_cursor() == FAIL)
+ return;
+
+ startpos = curwin->w_cursor;
+#ifdef FEAT_NETBEANS_INTG
+ pos = startpos;
+#endif
+ for (n = cap->count1; n > 0; --n)
+ {
+ did_change |= swapchar(cap->oap->op_type, &curwin->w_cursor);
+ inc_cursor();
+ if (gchar_cursor() == NUL)
+ {
+ if (vim_strchr(p_ww, '~') != NULL
+ && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
+ {
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ {
+ if (did_change)
+ {
+ ptr = ml_get(pos.lnum);
+ count = STRLEN(ptr) - pos.col;
+ netbeans_inserted(curbuf, pos.lnum, pos.col,
+ count, &ptr[pos.col], count);
+ }
+ pos.col = 0;
+ pos.lnum++;
+ }
+#endif
+ ++curwin->w_cursor.lnum;
+ curwin->w_cursor.col = 0;
+ if (n > 1)
+ {
+ if (u_savesub(curwin->w_cursor.lnum) == FAIL)
+ break;
+ u_clearline();
+ }
+ }
+ else
+ break;
+ }
+ }
+#ifdef FEAT_NETBEANS_INTG
+ if (did_change && usingNetbeans)
+ {
+ ptr = ml_get(pos.lnum);
+ count = curwin->w_cursor.col - pos.col;
+ netbeans_inserted(curbuf, pos.lnum, pos.col,
+ count, &ptr[pos.col], count);
+ }
+#endif
+
+
+ check_cursor();
+ curwin->w_set_curswant = TRUE;
+ if (did_change)
+ {
+ changed_lines(startpos.lnum, startpos.col, curwin->w_cursor.lnum + 1,
+ 0L);
+ curbuf->b_op_start = startpos;
+ curbuf->b_op_end = curwin->w_cursor;
+ if (curbuf->b_op_end.col > 0)
+ --curbuf->b_op_end.col;
+ }
+}
+
+/*
+ * Move cursor to mark.
+ */
+ static void
+nv_cursormark(cap, flag, pos)
+ cmdarg_T *cap;
+ int flag;
+ pos_T *pos;
+{
+ if (check_mark(pos) == FAIL)
+ clearop(cap->oap);
+ else
+ {
+ if (cap->cmdchar == '\''
+ || cap->cmdchar == '`'
+ || cap->cmdchar == '['
+ || cap->cmdchar == ']')
+ setpcmark();
+ curwin->w_cursor = *pos;
+ if (flag)
+ beginline(BL_WHITE | BL_FIX);
+ else
+ check_cursor();
+ }
+ cap->oap->motion_type = flag ? MLINE : MCHAR;
+ if (cap->cmdchar == '`')
+ cap->oap->use_reg_one = TRUE;
+ cap->oap->inclusive = FALSE; /* ignored if not MCHAR */
+ curwin->w_set_curswant = TRUE;
+}
+
+#ifdef FEAT_VISUAL
+/*
+ * Handle commands that are operators in Visual mode.
+ */
+ static void
+v_visop(cap)
+ cmdarg_T *cap;
+{
+ static char_u trans[] = "YyDdCcxdXdAAIIrr";
+
+ /* Uppercase means linewise, except in block mode, then "D" deletes till
+ * the end of the line, and "C" replaces til EOL */
+ if (isupper(cap->cmdchar))
+ {
+ if (VIsual_mode != Ctrl_V)
+ VIsual_mode = 'V';
+ else if (cap->cmdchar == 'C' || cap->cmdchar == 'D')
+ curwin->w_curswant = MAXCOL;
+ }
+ cap->cmdchar = *(vim_strchr(trans, cap->cmdchar) + 1);
+ nv_operator(cap);
+}
+#endif
+
+/*
+ * "s" and "S" commands.
+ */
+ static void
+nv_subst(cap)
+ cmdarg_T *cap;
+{
+#ifdef FEAT_VISUAL
+ if (VIsual_active) /* "vs" and "vS" are the same as "vc" */
+ {
+ if (cap->cmdchar == 'S')
+ VIsual_mode = 'V';
+ cap->cmdchar = 'c';
+ nv_operator(cap);
+ }
+ else
+#endif
+ nv_optrans(cap);
+}
+
+/*
+ * Abbreviated commands.
+ */
+ static void
+nv_abbrev(cap)
+ cmdarg_T *cap;
+{
+ if (cap->cmdchar == K_DEL || cap->cmdchar == K_KDEL)
+ cap->cmdchar = 'x'; /* DEL key behaves like 'x' */
+
+#ifdef FEAT_VISUAL
+ /* in Visual mode these commands are operators */
+ if (VIsual_active)
+ v_visop(cap);
+ else
+#endif
+ nv_optrans(cap);
+}
+
+/*
+ * Translate a command into another command.
+ */
+ static void
+nv_optrans(cap)
+ cmdarg_T *cap;
+{
+ static char_u *(ar[8]) = {(char_u *)"dl", (char_u *)"dh",
+ (char_u *)"d$", (char_u *)"c$",
+ (char_u *)"cl", (char_u *)"cc",
+ (char_u *)"yy", (char_u *)":s\r"};
+ static char_u *str = (char_u *)"xXDCsSY&";
+
+ if (!checkclearopq(cap->oap))
+ {
+ if (cap->count0)
+ stuffnumReadbuff(cap->count0);
+ stuffReadbuff(ar[(int)(vim_strchr(str, cap->cmdchar) - str)]);
+ }
+ cap->opcount = 0;
+}
+
+/*
+ * "'" and "`" commands. Also for "g'" and "g`".
+ * cap->arg is TRUE for "'" and "g'".
+ */
+ static void
+nv_gomark(cap)
+ cmdarg_T *cap;
+{
+ pos_T *pos;
+ int c;
+#ifdef FEAT_FOLDING
+ linenr_T lnum = curwin->w_cursor.lnum;
+ int old_KeyTyped = KeyTyped; /* getting file may reset it */
+#endif
+
+ if (cap->cmdchar == 'g')
+ c = cap->extra_char;
+ else
+ c = cap->nchar;
+ pos = getmark(c, (cap->oap->op_type == OP_NOP));
+ if (pos == (pos_T *)-1) /* jumped to other file */
+ {
+ if (cap->arg)
+ {
+ check_cursor_lnum();
+ beginline(BL_WHITE | BL_FIX);
+ }
+ else
+ check_cursor();
+ }
+ else
+ nv_cursormark(cap, cap->arg, pos);
+
+#ifdef FEAT_VIRTUALEDIT
+ /* May need to clear the coladd that a mark includes. */
+ if (!virtual_active())
+ curwin->w_cursor.coladd = 0;
+#endif
+#ifdef FEAT_FOLDING
+ if (cap->oap->op_type == OP_NOP
+ && (pos == (pos_T *)-1 || lnum != curwin->w_cursor.lnum)
+ && (fdo_flags & FDO_MARK)
+ && old_KeyTyped)
+ foldOpenCursor();
+#endif
+}
+
+/*
+ * Handle CTRL-O, CTRL-I, "g;" and "g," commands.
+ */
+ static void
+nv_pcmark(cap)
+ cmdarg_T *cap;
+{
+#ifdef FEAT_JUMPLIST
+ pos_T *pos;
+# ifdef FEAT_FOLDING
+ linenr_T lnum = curwin->w_cursor.lnum;
+ int old_KeyTyped = KeyTyped; /* getting file may reset it */
+# endif
+
+ if (!checkclearopq(cap->oap))
+ {
+ if (cap->cmdchar == 'g')
+ pos = movechangelist((int)cap->count1);
+ else
+ pos = movemark((int)cap->count1);
+ if (pos == (pos_T *)-1) /* jump to other file */
+ {
+ curwin->w_set_curswant = TRUE;
+ check_cursor();
+ }
+ else if (pos != NULL) /* can jump */
+ nv_cursormark(cap, FALSE, pos);
+ else if (cap->cmdchar == 'g')
+ {
+ if (curbuf->b_changelistlen == 0)
+ EMSG(_("E664: changelist is empty"));
+ else if (cap->count1 < 0)
+ EMSG(_("E662: At start of changelist"));
+ else
+ EMSG(_("E663: At end of changelist"));
+ }
+ else
+ clearopbeep(cap->oap);
+# ifdef FEAT_FOLDING
+ if (cap->oap->op_type == OP_NOP
+ && (pos == (pos_T *)-1 || lnum != curwin->w_cursor.lnum)
+ && (fdo_flags & FDO_MARK)
+ && old_KeyTyped)
+ foldOpenCursor();
+# endif
+ }
+#else
+ clearopbeep(cap->oap);
+#endif
+}
+
+/*
+ * Handle '"' command.
+ */
+ static void
+nv_regname(cap)
+ cmdarg_T *cap;
+{
+ if (checkclearop(cap->oap))
+ return;
+#ifdef FEAT_EVAL
+ if (cap->nchar == '=')
+ cap->nchar = get_expr_register();
+#endif
+ if (cap->nchar != NUL && valid_yank_reg(cap->nchar, FALSE))
+ {
+ cap->oap->regname = cap->nchar;
+ cap->opcount = cap->count0; /* remember count before '"' */
+#ifdef FEAT_EVAL
+ set_reg_var(cap->oap->regname);
+#endif
+ }
+ else
+ clearopbeep(cap->oap);
+}
+
+#ifdef FEAT_VISUAL
+/*
+ * Handle "v", "V" and "CTRL-V" commands.
+ * Also for "gh", "gH" and "g^H" commands: Always start Select mode, cap->arg
+ * is TRUE.
+ */
+ static void
+nv_visual(cap)
+ cmdarg_T *cap;
+{
+ /* 'v', 'V' and CTRL-V can be used while an operator is pending to make it
+ * characterwise, linewise, or blockwise. */
+ if (cap->oap->op_type != OP_NOP)
+ {
+ cap->oap->motion_force = cap->cmdchar;
+ finish_op = FALSE; /* operator doesn't finish now but later */
+ return;
+ }
+
+ VIsual_select = cap->arg;
+ if (VIsual_active) /* change Visual mode */
+ {
+ if (VIsual_mode == cap->cmdchar) /* stop visual mode */
+ end_visual_mode();
+ else /* toggle char/block mode */
+ { /* or char/line mode */
+ VIsual_mode = cap->cmdchar;
+ showmode();
+ }
+ redraw_curbuf_later(INVERTED); /* update the inversion */
+ }
+ else /* start Visual mode */
+ {
+ check_visual_highlight();
+ if (cap->count0) /* use previously selected part */
+ {
+ if (resel_VIsual_mode == NUL) /* there is none */
+ {
+ beep_flush();
+ return;
+ }
+ VIsual = curwin->w_cursor;
+
+ VIsual_active = TRUE;
+ VIsual_reselect = TRUE;
+ if (!cap->arg)
+ /* start Select mode when 'selectmode' contains "cmd" */
+ may_start_select('c');
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+ if (p_smd)
+ redraw_cmdline = TRUE; /* show visual mode later */
+ /*
+ * For V and ^V, we multiply the number of lines even if there
+ * was only one -- webb
+ */
+ if (resel_VIsual_mode != 'v' || resel_VIsual_line_count > 1)
+ {
+ curwin->w_cursor.lnum +=
+ resel_VIsual_line_count * cap->count0 - 1;
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ }
+ VIsual_mode = resel_VIsual_mode;
+ if (VIsual_mode == 'v')
+ {
+ if (resel_VIsual_line_count <= 1)
+ curwin->w_cursor.col += resel_VIsual_col * cap->count0 - 1;
+ else
+ curwin->w_cursor.col = resel_VIsual_col;
+ check_cursor_col();
+ }
+ if (resel_VIsual_col == MAXCOL)
+ {
+ curwin->w_curswant = MAXCOL;
+ coladvance((colnr_T)MAXCOL);
+ }
+ else if (VIsual_mode == Ctrl_V)
+ {
+ validate_virtcol();
+ curwin->w_curswant = curwin->w_virtcol
+ + resel_VIsual_col * cap->count0 - 1;
+ coladvance(curwin->w_curswant);
+ }
+ else
+ curwin->w_set_curswant = TRUE;
+ redraw_curbuf_later(INVERTED); /* show the inversion */
+ }
+ else
+ {
+ if (!cap->arg)
+ /* start Select mode when 'selectmode' contains "cmd" */
+ may_start_select('c');
+ n_start_visual_mode(cap->cmdchar);
+ }
+ }
+}
+
+/*
+ * Start selection for Shift-movement keys.
+ */
+ void
+start_selection()
+{
+ /* if 'selectmode' contains "key", start Select mode */
+ may_start_select('k');
+ n_start_visual_mode('v');
+}
+
+/*
+ * Start Select mode, if "c" is in 'selectmode' and not in a mapping or menu.
+ */
+ void
+may_start_select(c)
+ int c;
+{
+ VIsual_select = (stuff_empty() && typebuf_typed()
+ && (vim_strchr(p_slm, c) != NULL));
+}
+
+/*
+ * Start Visual mode "c".
+ * Should set VIsual_select before calling this.
+ */
+ static void
+n_start_visual_mode(c)
+ int c;
+{
+ VIsual_mode = c;
+ VIsual_active = TRUE;
+ VIsual_reselect = TRUE;
+#ifdef FEAT_VIRTUALEDIT
+ /* Corner case: the 0 position in a tab may change when going into
+ * virtualedit. Recalculate curwin->w_cursor to avoid bad hilighting.
+ */
+ if (c == Ctrl_V && (ve_flags & VE_BLOCK) && gchar_cursor() == TAB)
+ coladvance(curwin->w_virtcol);
+#endif
+ VIsual = curwin->w_cursor;
+
+#ifdef FEAT_FOLDING
+ foldAdjustVisual();
+#endif
+
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+ if (p_smd)
+ redraw_cmdline = TRUE; /* show visual mode later */
+#ifdef FEAT_CLIPBOARD
+ /* Make sure the clipboard gets updated. Needed because start and
+ * end may still be the same, and the selection needs to be owned */
+ clip_star.vmode = NUL;
+#endif
+
+ /* Only need to redraw this line, unless still need to redraw an old
+ * Visual area (when 'lazyredraw' is set). */
+ if (curwin->w_redr_type < INVERTED)
+ {
+ curwin->w_old_cursor_lnum = curwin->w_cursor.lnum;
+ curwin->w_old_visual_lnum = curwin->w_cursor.lnum;
+ }
+}
+
+#endif /* FEAT_VISUAL */
+
+/*
+ * CTRL-W: Window commands
+ */
+ static void
+nv_window(cap)
+ cmdarg_T *cap;
+{
+#ifdef FEAT_WINDOWS
+ if (!checkclearop(cap->oap))
+ do_window(cap->nchar, cap->count0, NUL); /* everything is in window.c */
+#else
+ (void)checkclearop(cap->oap);
+#endif
+}
+
+/*
+ * CTRL-Z: Suspend
+ */
+ static void
+nv_suspend(cap)
+ cmdarg_T *cap;
+{
+ clearop(cap->oap);
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ end_visual_mode(); /* stop Visual mode */
+#endif
+ do_cmdline_cmd((char_u *)"st");
+}
+
+/*
+ * Commands starting with "g".
+ */
+ static void
+nv_g_cmd(cap)
+ cmdarg_T *cap;
+{
+ oparg_T *oap = cap->oap;
+#ifdef FEAT_VISUAL
+ pos_T tpos;
+#endif
+ int i;
+ int flag = FALSE;
+
+ switch (cap->nchar)
+ {
+#ifdef MEM_PROFILE
+ /*
+ * "g^A": dump log of used memory.
+ */
+ case Ctrl_A:
+ vim_mem_profile_dump();
+ break;
+#endif
+
+#ifdef FEAT_VREPLACE
+ /*
+ * "gR": Enter virtual replace mode.
+ */
+ case 'R':
+ cap->arg = TRUE;
+ nv_Replace(cap);
+ break;
+
+ case 'r':
+ nv_vreplace(cap);
+ break;
+#endif
+
+ case '&':
+ do_cmdline_cmd((char_u *)"%s//~/&");
+ break;
+
+#ifdef FEAT_VISUAL
+ /*
+ * "gv": Reselect the previous Visual area. If Visual already active,
+ * exchange previous and current Visual area.
+ */
+ case 'v':
+ if (checkclearop(oap))
+ break;
+
+ if ( curbuf->b_visual_start.lnum == 0
+ || curbuf->b_visual_start.lnum > curbuf->b_ml.ml_line_count
+ || curbuf->b_visual_end.lnum == 0)
+ beep_flush();
+ else
+ {
+ /* set w_cursor to the start of the Visual area, tpos to the end */
+ if (VIsual_active)
+ {
+ i = VIsual_mode;
+ VIsual_mode = curbuf->b_visual_mode;
+ curbuf->b_visual_mode = i;
+# ifdef FEAT_EVAL
+ curbuf->b_visual_mode_eval = i;
+# endif
+ i = curwin->w_curswant;
+ curwin->w_curswant = curbuf->b_visual_curswant;
+ curbuf->b_visual_curswant = i;
+
+ tpos = curbuf->b_visual_end;
+ curbuf->b_visual_end = curwin->w_cursor;
+ curwin->w_cursor = curbuf->b_visual_start;
+ curbuf->b_visual_start = VIsual;
+ }
+ else
+ {
+ VIsual_mode = curbuf->b_visual_mode;
+ curwin->w_curswant = curbuf->b_visual_curswant;
+ tpos = curbuf->b_visual_end;
+ curwin->w_cursor = curbuf->b_visual_start;
+ }
+
+ VIsual_active = TRUE;
+ VIsual_reselect = TRUE;
+
+ /* Set Visual to the start and w_cursor to the end of the Visual
+ * area. Make sure they are on an existing character. */
+ check_cursor();
+ VIsual = curwin->w_cursor;
+ curwin->w_cursor = tpos;
+ check_cursor();
+ update_topline();
+ /*
+ * When called from normal "g" command: start Select mode when
+ * 'selectmode' contains "cmd". When called for K_SELECT, always
+ * start Select mode.
+ */
+ if (cap->arg)
+ VIsual_select = TRUE;
+ else
+ may_start_select('c');
+#ifdef FEAT_MOUSE
+ setmouse();
+#endif
+#ifdef FEAT_CLIPBOARD
+ /* Make sure the clipboard gets updated. Needed because start and
+ * end are still the same, and the selection needs to be owned */
+ clip_star.vmode = NUL;
+#endif
+ redraw_curbuf_later(INVERTED);
+ showmode();
+ }
+ break;
+ /*
+ * "gV": Don't reselect the previous Visual area after a Select mode
+ * mapping of menu.
+ */
+ case 'V':
+ VIsual_reselect = FALSE;
+ break;
+
+ /*
+ * "gh": start Select mode.
+ * "gH": start Select line mode.
+ * "g^H": start Select block mode.
+ */
+ case K_BS:
+ cap->nchar = Ctrl_H;
+ /* FALLTHROUGH */
+ case 'h':
+ case 'H':
+ case Ctrl_H:
+# ifdef EBCDIC
+ /* EBCDIC: 'v'-'h' != '^v'-'^h' */
+ if (cap->nchar == Ctrl_H)
+ cap->cmdchar = Ctrl_V;
+ else
+# endif
+ cap->cmdchar = cap->nchar + ('v' - 'h');
+ cap->arg = TRUE;
+ nv_visual(cap);
+ break;
+#endif /* FEAT_VISUAL */
+
+ /*
+ * "gj" and "gk" two new funny movement keys -- up and down
+ * movement based on *screen* line rather than *file* line.
+ */
+ case 'j':
+ case K_DOWN:
+ /* with 'nowrap' it works just like the normal "j" command; also when
+ * in a closed fold */
+ if (!curwin->w_p_wrap
+#ifdef FEAT_FOLDING
+ || hasFolding(curwin->w_cursor.lnum, NULL, NULL)
+#endif
+ )
+ {
+ oap->motion_type = MLINE;
+ i = cursor_down(cap->count1, oap->op_type == OP_NOP);
+ }
+ else
+ i = nv_screengo(oap, FORWARD, cap->count1);
+ if (i == FAIL)
+ clearopbeep(oap);
+ break;
+
+ case 'k':
+ case K_UP:
+ /* with 'nowrap' it works just like the normal "k" command; also when
+ * in a closed fold */
+ if (!curwin->w_p_wrap
+#ifdef FEAT_FOLDING
+ || hasFolding(curwin->w_cursor.lnum, NULL, NULL)
+#endif
+ )
+ {
+ oap->motion_type = MLINE;
+ i = cursor_up(cap->count1, oap->op_type == OP_NOP);
+ }
+ else
+ i = nv_screengo(oap, BACKWARD, cap->count1);
+ if (i == FAIL)
+ clearopbeep(oap);
+ break;
+
+ /*
+ * "gJ": join two lines without inserting a space.
+ */
+ case 'J':
+ nv_join(cap);
+ break;
+
+ /*
+ * "g0", "g^" and "g$": Like "0", "^" and "$" but for screen lines.
+ * "gm": middle of "g0" and "g$".
+ */
+ case '^':
+ flag = TRUE;
+ /* FALLTHROUGH */
+
+ case '0':
+ case 'm':
+ case K_HOME:
+ case K_KHOME:
+ case K_XHOME:
+ oap->motion_type = MCHAR;
+ oap->inclusive = FALSE;
+ if (curwin->w_p_wrap
+#ifdef FEAT_VERTSPLIT
+ && curwin->w_width != 0
+#endif
+ )
+ {
+ int width1 = W_WIDTH(curwin) - curwin_col_off();
+ int width2 = width1 + curwin_col_off2();
+
+ validate_virtcol();
+ i = 0;
+ if (curwin->w_virtcol >= (colnr_T)width1 && width2 > 0)
+ i = (curwin->w_virtcol - width1) / width2 * width2 + width1;
+ }
+ else
+ i = curwin->w_leftcol;
+ /* Go to the middle of the screen line. When 'number' is on and lines
+ * are wrapping the middle can be more to the left.*/
+ if (cap->nchar == 'm')
+ i += (W_WIDTH(curwin) - curwin_col_off()
+ + ((curwin->w_p_wrap && i > 0)
+ ? curwin_col_off2() : 0)) / 2;
+ coladvance((colnr_T)i);
+ if (flag)
+ {
+ do
+ i = gchar_cursor();
+ while (vim_iswhite(i) && oneright() == OK);
+ }
+ curwin->w_set_curswant = TRUE;
+ break;
+
+ case '_':
+ /* "g_": to the last non-blank character in the line or <count> lines
+ * downward. */
+ cap->oap->motion_type = MCHAR;
+ cap->oap->inclusive = TRUE;
+ curwin->w_curswant = MAXCOL;
+ if (cursor_down((long)(cap->count1 - 1),
+ cap->oap->op_type == OP_NOP) == FAIL)
+ clearopbeep(cap->oap);
+ else
+ {
+ char_u *ptr = ml_get_curline();
+
+ /* In Visual mode we may end up after the line. */
+ if (curwin->w_cursor.col > 0 && ptr[curwin->w_cursor.col] == NUL)
+ --curwin->w_cursor.col;
+
+ /* Decrease the cursor column until it's on a non-blank. */
+ while (curwin->w_cursor.col > 0
+ && vim_iswhite(ptr[curwin->w_cursor.col]))
+ --curwin->w_cursor.col;
+ curwin->w_set_curswant = TRUE;
+ }
+ break;
+
+ case '$':
+ case K_END:
+ case K_KEND:
+ case K_XEND:
+ {
+ int col_off = curwin_col_off();
+
+ oap->motion_type = MCHAR;
+ oap->inclusive = TRUE;
+ if (curwin->w_p_wrap
+#ifdef FEAT_VERTSPLIT
+ && curwin->w_width != 0
+#endif
+ )
+ {
+ curwin->w_curswant = MAXCOL; /* so we stay at the end */
+ if (cap->count1 == 1)
+ {
+ int width1 = W_WIDTH(curwin) - col_off;
+ int width2 = width1 + curwin_col_off2();
+
+ validate_virtcol();
+ i = width1 - 1;
+ if (curwin->w_virtcol >= (colnr_T)width1)
+ i += ((curwin->w_virtcol - width1) / width2 + 1)
+ * width2;
+ coladvance((colnr_T)i);
+#if defined(FEAT_LINEBREAK) || defined(FEAT_MBYTE)
+ if (curwin->w_cursor.col > 0 && curwin->w_p_wrap)
+ {
+ /*
+ * Check for landing on a character that got split at
+ * the end of the line. We do not want to advance to
+ * the next screen line.
+ */
+ validate_virtcol();
+ if (curwin->w_virtcol > (colnr_T)i)
+ --curwin->w_cursor.col;
+ }
+#endif
+ }
+ else if (nv_screengo(oap, FORWARD, cap->count1 - 1) == FAIL)
+ clearopbeep(oap);
+ }
+ else
+ {
+ i = curwin->w_leftcol + W_WIDTH(curwin) - col_off - 1;
+ coladvance((colnr_T)i);
+ curwin->w_set_curswant = TRUE;
+ }
+ }
+ break;
+
+ /*
+ * "g*" and "g#", like "*" and "#" but without using "\<" and "\>"
+ */
+ case '*':
+ case '#':
+#if POUND != '#'
+ case POUND: /* pound sign (sometimes equal to '#') */
+#endif
+ case Ctrl_RSB: /* :tag or :tselect for current identifier */
+ case ']': /* :tselect for current identifier */
+ nv_ident(cap);
+ break;
+
+ /*
+ * ge and gE: go back to end of word
+ */
+ case 'e':
+ case 'E':
+ oap->motion_type = MCHAR;
+ curwin->w_set_curswant = TRUE;
+ oap->inclusive = TRUE;
+ if (bckend_word(cap->count1, cap->nchar == 'E', FALSE) == FAIL)
+ clearopbeep(oap);
+ break;
+
+ /*
+ * "g CTRL-G": display info about cursor position
+ */
+ case Ctrl_G:
+ cursor_pos_info();
+ break;
+
+ /*
+ * "gi": start Insert at the last position.
+ */
+ case 'i':
+ if (curbuf->b_last_insert.lnum != 0)
+ {
+ curwin->w_cursor = curbuf->b_last_insert;
+ check_cursor_lnum();
+ i = (int)STRLEN(ml_get_curline());
+ if (curwin->w_cursor.col > (colnr_T)i)
+ {
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_active())
+ curwin->w_cursor.coladd += curwin->w_cursor.col - i;
+#endif
+ curwin->w_cursor.col = i;
+ }
+ }
+ cap->cmdchar = 'i';
+ nv_edit(cap);
+ break;
+
+ /*
+ * "gI": Start insert in column 1.
+ */
+ case 'I':
+ beginline(0);
+ if (!checkclearopq(oap))
+ invoke_edit(cap, FALSE, 'g', FALSE);
+ break;
+
+#ifdef FEAT_SEARCHPATH
+ /*
+ * "gf": goto file, edit file under cursor
+ * "]f" and "[f": can also be used.
+ */
+ case 'f':
+ nv_gotofile(cap);
+ break;
+#endif
+
+ /* "g'm" and "g`m": jump to mark without setting pcmark */
+ case '\'':
+ cap->arg = TRUE;
+ /*FALLTHROUGH*/
+ case '`':
+ nv_gomark(cap);
+ break;
+
+ /*
+ * "gs": Goto sleep.
+ */
+ case 's':
+ do_sleep(cap->count1 * 1000L);
+ break;
+
+ /*
+ * "ga": Display the ascii value of the character under the
+ * cursor. It is displayed in decimal, hex, and octal. -- webb
+ */
+ case 'a':
+ do_ascii(NULL);
+ break;
+
+#ifdef FEAT_MBYTE
+ /*
+ * "g8": Display the bytes used for the UTF-8 character under the
+ * cursor. It is displayed in hex.
+ */
+ case '8':
+ show_utf8();
+ break;
+#endif
+
+ /*
+ * "gg": Goto the first line in file. With a count it goes to
+ * that line number like for "G". -- webb
+ */
+ case 'g':
+ cap->arg = FALSE;
+ nv_goto(cap);
+ break;
+
+ /*
+ * Two-character operators:
+ * "gq" Format text
+ * "gw" Format text and keep cursor position
+ * "g~" Toggle the case of the text.
+ * "gu" Change text to lower case.
+ * "gU" Change text to upper case.
+ * "g?" rot13 encoding
+ */
+ case 'q':
+ case 'w':
+ oap->cursor_start = curwin->w_cursor;
+ /*FALLTHROUGH*/
+ case '~':
+ case 'u':
+ case 'U':
+ case '?':
+ nv_operator(cap);
+ break;
+
+ /*
+ * "gd": Find first occurence of pattern under the cursor in the
+ * current function
+ * "gD": idem, but in the current file.
+ */
+ case 'd':
+ case 'D':
+ nv_gd(oap, cap->nchar);
+ break;
+
+#ifdef FEAT_MOUSE
+ /*
+ * g<*Mouse> : <C-*mouse>
+ */
+ case K_MIDDLEMOUSE:
+ case K_MIDDLEDRAG:
+ case K_MIDDLERELEASE:
+ case K_LEFTMOUSE:
+ case K_LEFTDRAG:
+ case K_LEFTRELEASE:
+ case K_RIGHTMOUSE:
+ case K_RIGHTDRAG:
+ case K_RIGHTRELEASE:
+ case K_X1MOUSE:
+ case K_X1DRAG:
+ case K_X1RELEASE:
+ case K_X2MOUSE:
+ case K_X2DRAG:
+ case K_X2RELEASE:
+ mod_mask = MOD_MASK_CTRL;
+ (void)do_mouse(oap, cap->nchar, BACKWARD, cap->count1, 0);
+ break;
+#endif
+
+ case K_IGNORE:
+ break;
+
+ /*
+ * "gP" and "gp": same as "P" and "p" but leave cursor just after new text
+ */
+ case 'p':
+ case 'P':
+ nv_put(cap);
+ break;
+
+#ifdef FEAT_BYTEOFF
+ /* "go": goto byte count from start of buffer */
+ case 'o':
+ goto_byte(cap->count0);
+ break;
+#endif
+
+ /* "gQ": improved Ex mode */
+ case 'Q':
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ {
+ clearopbeep(cap->oap);
+ break;
+ }
+#endif
+ if (!checkclearopq(oap))
+ do_exmode(TRUE);
+ break;
+
+#ifdef FEAT_JUMPLIST
+ case ',':
+ nv_pcmark(cap);
+ break;
+
+ case ';':
+ cap->count1 = -cap->count1;
+ nv_pcmark(cap);
+ break;
+#endif
+
+ default:
+ clearopbeep(oap);
+ break;
+ }
+}
+
+/*
+ * Handle "o" and "O" commands.
+ */
+ static void
+n_opencmd(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearopq(cap->oap))
+ {
+#ifdef FEAT_FOLDING
+ if (cap->cmdchar == 'O')
+ /* Open above the first line of a folded sequence of lines */
+ (void)hasFolding(curwin->w_cursor.lnum,
+ &curwin->w_cursor.lnum, NULL);
+ else
+ /* Open below the last line of a folded sequence of lines */
+ (void)hasFolding(curwin->w_cursor.lnum,
+ NULL, &curwin->w_cursor.lnum);
+#endif
+ if (u_save((linenr_T)(curwin->w_cursor.lnum -
+ (cap->cmdchar == 'O' ? 1 : 0)),
+ (linenr_T)(curwin->w_cursor.lnum +
+ (cap->cmdchar == 'o' ? 1 : 0))
+ ) == OK
+ && open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD,
+#ifdef FEAT_COMMENTS
+ has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM :
+#endif
+ 0, 0))
+ {
+ invoke_edit(cap, FALSE, cap->cmdchar, TRUE);
+ }
+ }
+}
+
+/*
+ * "." command: redo last change.
+ */
+ static void
+nv_dot(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearopq(cap->oap))
+ {
+ /*
+ * If "restart_edit" is TRUE, the last but one command is repeated
+ * instead of the last command (inserting text). This is used for
+ * CTRL-O <.> in insert mode.
+ */
+ if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == FAIL)
+ clearopbeep(cap->oap);
+ }
+}
+
+/*
+ * CTRL-R: undo undo
+ */
+ static void
+nv_redo(cap)
+ cmdarg_T *cap;
+{
+ if (!checkclearopq(cap->oap))
+ {
+ u_redo((int)cap->count1);
+ curwin->w_set_curswant = TRUE;
+ }
+}
+
+/*
+ * Handle "U" command.
+ */
+ static void
+nv_Undo(cap)
+ cmdarg_T *cap;
+{
+ /* In Visual mode and typing "gUU" triggers an operator */
+ if (cap->oap->op_type == OP_UPPER
+#ifdef FEAT_VISUAL
+ || VIsual_active
+#endif
+ )
+ {
+ /* translate "gUU" to "gUgU" */
+ cap->cmdchar = 'g';
+ cap->nchar = 'U';
+ nv_operator(cap);
+ }
+ else if (!checkclearopq(cap->oap))
+ {
+ u_undoline();
+ curwin->w_set_curswant = TRUE;
+ }
+}
+
+/*
+ * '~' command: If tilde is not an operator and Visual is off: swap case of a
+ * single character.
+ */
+ static void
+nv_tilde(cap)
+ cmdarg_T *cap;
+{
+ if (!p_to
+#ifdef FEAT_VISUAL
+ && !VIsual_active
+#endif
+ && cap->oap->op_type != OP_TILDE)
+ n_swapchar(cap);
+ else
+ nv_operator(cap);
+}
+
+/*
+ * Handle an operator command.
+ * The actual work is done by do_pending_operator().
+ */
+ static void
+nv_operator(cap)
+ cmdarg_T *cap;
+{
+ int op_type;
+
+ op_type = get_op_type(cap->cmdchar, cap->nchar);
+
+ if (op_type == cap->oap->op_type) /* double operator works on lines */
+ nv_lineop(cap);
+ else if (!checkclearop(cap->oap))
+ {
+ cap->oap->start = curwin->w_cursor;
+ cap->oap->op_type = op_type;
+ }
+}
+
+/*
+ * Handle linewise operator "dd", "yy", etc.
+ *
+ * "_" is is a strange motion command that helps make operators more logical.
+ * It is actually implemented, but not documented in the real Vi. This motion
+ * command actually refers to "the current line". Commands like "dd" and "yy"
+ * are really an alternate form of "d_" and "y_". It does accept a count, so
+ * "d3_" works to delete 3 lines.
+ */
+ static void
+nv_lineop(cap)
+ cmdarg_T *cap;
+{
+ cap->oap->motion_type = MLINE;
+ if (cursor_down(cap->count1 - 1L, cap->oap->op_type == OP_NOP) == FAIL)
+ clearopbeep(cap->oap);
+ else if ( cap->oap->op_type == OP_DELETE
+ || cap->oap->op_type == OP_LSHIFT
+ || cap->oap->op_type == OP_RSHIFT)
+ beginline(BL_SOL | BL_FIX);
+ else if (cap->oap->op_type != OP_YANK) /* 'Y' does not move cursor */
+ beginline(BL_WHITE | BL_FIX);
+}
+
+/*
+ * <Home> command.
+ */
+ static void
+nv_home(cap)
+ cmdarg_T *cap;
+{
+ cap->count0 = 1;
+ nv_pipe(cap);
+}
+
+/*
+ * "|" command.
+ */
+ static void
+nv_pipe(cap)
+ cmdarg_T *cap;
+{
+ cap->oap->motion_type = MCHAR;
+ cap->oap->inclusive = FALSE;
+ beginline(0);
+ if (cap->count0 > 0)
+ {
+ coladvance((colnr_T)(cap->count0 - 1));
+ curwin->w_curswant = (colnr_T)(cap->count0 - 1);
+ }
+ else
+ curwin->w_curswant = 0;
+ /* keep curswant at the column where we wanted to go, not where
+ we ended; differs if line is too short */
+ curwin->w_set_curswant = FALSE;
+}
+
+/*
+ * Handle back-word command "b" and "B".
+ * cap->arg is 1 for "B"
+ */
+ static void
+nv_bck_word(cap)
+ cmdarg_T *cap;
+{
+ cap->oap->motion_type = MCHAR;
+ cap->oap->inclusive = FALSE;
+ curwin->w_set_curswant = TRUE;
+ if (bck_word(cap->count1, cap->arg, FALSE) == FAIL)
+ clearopbeep(cap->oap);
+#ifdef FEAT_FOLDING
+ else if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+}
+
+/*
+ * Handle word motion commands "e", "E", "w" and "W".
+ * cap->arg is TRUE for "E" and "W".
+ */
+ static void
+nv_wordcmd(cap)
+ cmdarg_T *cap;
+{
+ int n;
+ int word_end;
+ int flag = FALSE;
+
+ /*
+ * Set inclusive for the "E" and "e" command.
+ */
+ if (cap->cmdchar == 'e' || cap->cmdchar == 'E')
+ word_end = TRUE;
+ else
+ word_end = FALSE;
+ cap->oap->inclusive = word_end;
+
+ /*
+ * "cw" and "cW" are a special case.
+ */
+ if (!word_end && cap->oap->op_type == OP_CHANGE)
+ {
+ n = gchar_cursor();
+ if (n != NUL) /* not an empty line */
+ {
+ if (vim_iswhite(n))
+ {
+ /*
+ * Reproduce a funny Vi behaviour: "cw" on a blank only
+ * changes one character, not all blanks until the start of
+ * the next word. Only do this when the 'w' flag is included
+ * in 'cpoptions'.
+ */
+ if (cap->count1 == 1 && vim_strchr(p_cpo, CPO_CW) != NULL)
+ {
+ cap->oap->inclusive = TRUE;
+ cap->oap->motion_type = MCHAR;
+ return;
+ }
+ }
+ else
+ {
+ /*
+ * This is a little strange. To match what the real Vi does,
+ * we effectively map 'cw' to 'ce', and 'cW' to 'cE', provided
+ * that we are not on a space or a TAB. This seems impolite
+ * at first, but it's really more what we mean when we say
+ * 'cw'.
+ * Another strangeness: When standing on the end of a word
+ * "ce" will change until the end of the next wordt, but "cw"
+ * will change only one character! This is done by setting
+ * flag.
+ */
+ cap->oap->inclusive = TRUE;
+ word_end = TRUE;
+ flag = TRUE;
+ }
+ }
+ }
+
+ cap->oap->motion_type = MCHAR;
+ curwin->w_set_curswant = TRUE;
+ if (word_end)
+ n = end_word(cap->count1, cap->arg, flag, FALSE);
+ else
+ n = fwd_word(cap->count1, cap->arg, cap->oap->op_type != OP_NOP);
+
+ /* Don't leave the cursor on the NUL past a line */
+ if (curwin->w_cursor.col && gchar_cursor() == NUL)
+ {
+ --curwin->w_cursor.col;
+ cap->oap->inclusive = TRUE;
+ }
+
+ if (n == FAIL && cap->oap->op_type == OP_NOP)
+ clearopbeep(cap->oap);
+ else
+ {
+#ifdef FEAT_VISUAL
+ adjust_for_sel(cap);
+#endif
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+ }
+}
+
+/*
+ * "0" and "^" commands.
+ * cap->arg is the argument for beginline().
+ */
+ static void
+nv_beginline(cap)
+ cmdarg_T *cap;
+{
+ cap->oap->motion_type = MCHAR;
+ cap->oap->inclusive = FALSE;
+ beginline(cap->arg);
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+}
+
+#ifdef FEAT_VISUAL
+/*
+ * In exclusive Visual mode, may include the last character.
+ */
+ static void
+adjust_for_sel(cap)
+ cmdarg_T *cap;
+{
+ if (VIsual_active && cap->oap->inclusive && *p_sel == 'e'
+ && gchar_cursor() != NUL && lt(VIsual, curwin->w_cursor))
+ {
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ inc_cursor();
+ else
+# endif
+ ++curwin->w_cursor.col;
+ cap->oap->inclusive = FALSE;
+ }
+}
+
+/*
+ * Exclude last character at end of Visual area for 'selection' == "exclusive".
+ * Should check VIsual_mode before calling this.
+ * Returns TRUE when backed up to the previous line.
+ */
+ static int
+unadjust_for_sel()
+{
+ pos_T *pp;
+
+ if (*p_sel == 'e' && !equalpos(VIsual, curwin->w_cursor))
+ {
+ if (lt(VIsual, curwin->w_cursor))
+ pp = &curwin->w_cursor;
+ else
+ pp = &VIsual;
+#ifdef FEAT_VIRTUALEDIT
+ if (pp->coladd > 0)
+ --pp->coladd;
+ else
+#endif
+ if (pp->col > 0)
+ {
+ --pp->col;
+#ifdef FEAT_MBYTE
+ mb_adjustpos(pp);
+#endif
+ }
+ else if (pp->lnum > 1)
+ {
+ --pp->lnum;
+ pp->col = (colnr_T)STRLEN(ml_get(pp->lnum));
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * SELECT key in Normal or Visual mode: end of Select mode mapping.
+ */
+ static void
+nv_select(cap)
+ cmdarg_T *cap;
+{
+ if (VIsual_active)
+ VIsual_select = TRUE;
+ else if (VIsual_reselect)
+ {
+ cap->nchar = 'v'; /* fake "gv" command */
+ cap->arg = TRUE;
+ nv_g_cmd(cap);
+ }
+}
+
+#endif
+
+/*
+ * "G", "gg", CTRL-END, CTRL-HOME.
+ * cap->arg is TRUE for "G".
+ */
+ static void
+nv_goto(cap)
+ cmdarg_T *cap;
+{
+ linenr_T lnum;
+
+ if (cap->arg)
+ lnum = curbuf->b_ml.ml_line_count;
+ else
+ lnum = 1L;
+ cap->oap->motion_type = MLINE;
+ setpcmark();
+
+ /* When a count is given, use it instead of the default lnum */
+ if (cap->count0 != 0)
+ lnum = cap->count0;
+ if (lnum < 1L)
+ lnum = 1L;
+ else if (lnum > curbuf->b_ml.ml_line_count)
+ lnum = curbuf->b_ml.ml_line_count;
+ curwin->w_cursor.lnum = lnum;
+ beginline(BL_SOL | BL_FIX);
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_JUMP) && KeyTyped && cap->oap->op_type == OP_NOP)
+ foldOpenCursor();
+#endif
+}
+
+/*
+ * CTRL-\ in Normal mode.
+ */
+ static void
+nv_normal(cap)
+ cmdarg_T *cap;
+{
+ if (cap->nchar == Ctrl_N || cap->nchar == Ctrl_G)
+ {
+ clearop(cap->oap);
+ if (restart_edit != 0 && p_smd)
+ clear_cmdline = TRUE; /* unshow mode later */
+ restart_edit = 0;
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ cmdwin_result = Ctrl_C;
+#endif
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ end_visual_mode(); /* stop Visual */
+ redraw_curbuf_later(INVERTED);
+ }
+#endif
+ /* CTRL-\ CTRL-G restarts Insert mode when 'insertmode' is set. */
+ if (cap->nchar == Ctrl_G && p_im)
+ restart_edit = 'a';
+ }
+ else
+ clearopbeep(cap->oap);
+}
+
+/*
+ * ESC in Normal mode: beep, but don't flush buffers.
+ * Don't even beep if we are canceling a command.
+ */
+ static void
+nv_esc(cap)
+ cmdarg_T *cap;
+{
+ int no_reason;
+
+ no_reason = (cap->oap->op_type == OP_NOP
+ && cap->opcount == 0
+ && cap->count0 == 0
+ && cap->oap->regname == 0
+ && !p_im);
+
+ if (cap->arg) /* TRUE for CTRL-C */
+ {
+ if (restart_edit == 0
+#ifdef FEAT_CMDWIN
+ && cmdwin_type == 0
+#endif
+#ifdef FEAT_VISUAL
+ && !VIsual_active
+#endif
+ && no_reason)
+ MSG(_("Type :quit<Enter> to exit Vim"));
+
+ /* Don't reset "restart_edit" when 'insertmode' is set, it won't be
+ * set again below when halfway a mapping. */
+ if (!p_im)
+ restart_edit = 0;
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ {
+ cmdwin_result = K_IGNORE;
+ got_int = FALSE; /* don't stop executing autocommands et al. */
+ return;
+ }
+#endif
+ }
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ end_visual_mode(); /* stop Visual */
+ check_cursor_col(); /* make sure cursor is not beyond EOL */
+ curwin->w_set_curswant = TRUE;
+ redraw_curbuf_later(INVERTED);
+ }
+ else
+#endif
+ if (no_reason)
+ vim_beep();
+ clearop(cap->oap);
+
+ /* A CTRL-C is often used at the start of a menu. When 'insertmode' is
+ * set return to Insert mode afterwards. */
+ if (restart_edit == 0 && goto_im()
+#ifdef FEAT_EX_EXTRA
+ && ex_normal_busy == 0
+#endif
+ )
+ restart_edit = 'a';
+}
+
+/*
+ * Handle "A", "a", "I", "i" and <Insert> commands.
+ */
+ static void
+nv_edit(cap)
+ cmdarg_T *cap;
+{
+ /* <Insert> is equal to "i" */
+ if (cap->cmdchar == K_INS || cap->cmdchar == K_KINS)
+ cap->cmdchar = 'i';
+
+#ifdef FEAT_VISUAL
+ /* in Visual mode "A" and "I" are an operator */
+ if (VIsual_active && (cap->cmdchar == 'A' || cap->cmdchar == 'I'))
+ v_visop(cap);
+
+ /* in Visual mode and after an operator "a" and "i" are for text objects */
+ else
+#endif
+ if ((cap->cmdchar == 'a' || cap->cmdchar == 'i')
+ && (cap->oap->op_type != OP_NOP
+#ifdef FEAT_VISUAL
+ || VIsual_active
+#endif
+ ))
+ {
+#ifdef FEAT_TEXTOBJ
+ nv_object(cap);
+#else
+ clearopbeep(cap->oap);
+#endif
+ }
+ else if (!curbuf->b_p_ma && !p_im)
+ {
+ /* Only give this error when 'insertmode' is off. */
+ EMSG(_(e_modifiable));
+ clearop(cap->oap);
+ }
+ else if (!checkclearopq(cap->oap))
+ {
+ switch (cap->cmdchar)
+ {
+ case 'A': /* "A"ppend after the line */
+ curwin->w_set_curswant = TRUE;
+#ifdef FEAT_VIRTUALEDIT
+ if (ve_flags == VE_ALL)
+ {
+ int save_State = State;
+
+ /* Pretent Insert mode here to allow the cursor on the
+ * character past the end of the line */
+ State = INSERT;
+ coladvance((colnr_T)MAXCOL);
+ State = save_State;
+ }
+ else
+#endif
+ curwin->w_cursor.col += (colnr_T)STRLEN(ml_get_cursor());
+ break;
+
+ case 'I': /* "I"nsert before the first non-blank */
+ beginline(BL_WHITE);
+ break;
+
+ case 'a': /* "a"ppend is like "i"nsert on the next character. */
+#ifdef FEAT_VIRTUALEDIT
+ /* increment coladd when in virtual space, increment the
+ * column otherwise, also to append after an unprintable char */
+ if (virtual_active()
+ && (curwin->w_cursor.coladd > 0
+ || *ml_get_cursor() == NUL
+ || *ml_get_cursor() == TAB))
+ curwin->w_cursor.coladd++;
+ else
+#endif
+ if (*ml_get_cursor() != NUL)
+ inc_cursor();
+ break;
+ }
+
+#ifdef FEAT_VIRTUALEDIT
+ if (curwin->w_cursor.coladd && cap->cmdchar != 'A')
+ {
+ int save_State = State;
+
+ /* Pretent Insert mode here to allow the cursor on the
+ * character past the end of the line */
+ State = INSERT;
+ coladvance(getviscol());
+ State = save_State;
+ }
+#endif
+
+ invoke_edit(cap, FALSE, cap->cmdchar, FALSE);
+ }
+}
+
+/*
+ * Invoke edit() and take care of "restart_edit" and the return value.
+ */
+ static void
+invoke_edit(cap, repl, cmd, startln)
+ cmdarg_T *cap;
+ int repl; /* "r" or "gr" command */
+ int cmd;
+ int startln;
+{
+ int restart_edit_save = 0;
+
+ /* Complicated: When the user types "a<C-O>a" we don't want to do Insert
+ * mode recursively. But when doing "a<C-O>." or "a<C-O>rx" we do allow
+ * it. */
+ if (repl || !stuff_empty())
+ restart_edit_save = restart_edit;
+ else
+ restart_edit_save = 0;
+
+ /* Always reset "restart_edit", this is not a restarted edit. */
+ restart_edit = 0;
+
+ if (edit(cmd, startln, cap->count1))
+ cap->retval |= CA_COMMAND_BUSY;
+
+ if (restart_edit == 0)
+ restart_edit = restart_edit_save;
+}
+
+#ifdef FEAT_TEXTOBJ
+/*
+ * "a" or "i" while an operator is pending or in Visual mode: object motion.
+ */
+ static void
+nv_object(cap)
+ cmdarg_T *cap;
+{
+ int flag;
+ int include;
+ char_u *mps_save;
+
+ if (cap->cmdchar == 'i')
+ include = FALSE; /* "ix" = inner object: exclude white space */
+ else
+ include = TRUE; /* "ax" = an object: include white space */
+
+ /* Make sure (), [], {} and <> are in 'matchpairs' */
+ mps_save = curbuf->b_p_mps;
+ curbuf->b_p_mps = (char_u *)"(:),{:},[:],<:>";
+
+ switch (cap->nchar)
+ {
+ case 'w': /* "aw" = a word */
+ flag = current_word(cap->oap, cap->count1, include, FALSE);
+ break;
+ case 'W': /* "aW" = a WORD */
+ flag = current_word(cap->oap, cap->count1, include, TRUE);
+ break;
+ case 'b': /* "ab" = a braces block */
+ case '(':
+ case ')':
+ flag = current_block(cap->oap, cap->count1, include, '(', ')');
+ break;
+ case 'B': /* "aB" = a Brackets block */
+ case '{':
+ case '}':
+ flag = current_block(cap->oap, cap->count1, include, '{', '}');
+ break;
+ case '[': /* "a[" = a [] block */
+ case ']':
+ flag = current_block(cap->oap, cap->count1, include, '[', ']');
+ break;
+ case '<': /* "a<" = a <> block */
+ case '>':
+ flag = current_block(cap->oap, cap->count1, include, '<', '>');
+ break;
+ case 'p': /* "ap" = a paragraph */
+ flag = current_par(cap->oap, cap->count1, include, 'p');
+ break;
+ case 's': /* "as" = a sentence */
+ flag = current_sent(cap->oap, cap->count1, include);
+ break;
+#if 0 /* TODO */
+ case 'S': /* "aS" = a section */
+ case 'f': /* "af" = a filename */
+ case 'u': /* "au" = a URL */
+#endif
+ default:
+ flag = FAIL;
+ break;
+ }
+
+ curbuf->b_p_mps = mps_save;
+ if (flag == FAIL)
+ clearopbeep(cap->oap);
+ adjust_cursor_col();
+ curwin->w_set_curswant = TRUE;
+}
+#endif
+
+/*
+ * "q" command: Start/stop recording.
+ * "q:", "q/", "q?": edit command-line in command-line window.
+ */
+ static void
+nv_record(cap)
+ cmdarg_T *cap;
+{
+ if (cap->oap->op_type == OP_FORMAT)
+ {
+ /* "gqq" is the same as "gqgq": format line */
+ cap->cmdchar = 'g';
+ cap->nchar = 'q';
+ nv_operator(cap);
+ }
+ else if (!checkclearop(cap->oap))
+ {
+#ifdef FEAT_CMDWIN
+ if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?')
+ {
+ stuffcharReadbuff(cap->nchar);
+ stuffcharReadbuff(K_CMDWIN);
+ }
+ else
+#endif
+ /* (stop) recording into a named register, unless executing a
+ * register */
+ if (!Exec_reg && do_record(cap->nchar) == FAIL)
+ clearopbeep(cap->oap);
+ }
+}
+
+/*
+ * Handle the "@r" command.
+ */
+ static void
+nv_at(cap)
+ cmdarg_T *cap;
+{
+ if (checkclearop(cap->oap))
+ return;
+#ifdef FEAT_EVAL
+ if (cap->nchar == '=')
+ {
+ if (get_expr_register() == NUL)
+ return;
+ }
+#endif
+ while (cap->count1-- && !got_int)
+ {
+ if (do_execreg(cap->nchar, FALSE, FALSE) == FAIL)
+ {
+ clearopbeep(cap->oap);
+ break;
+ }
+ line_breakcheck();
+ }
+}
+
+/*
+ * Handle the CTRL-U and CTRL-D commands.
+ */
+ static void
+nv_halfpage(cap)
+ cmdarg_T *cap;
+{
+ if ((cap->cmdchar == Ctrl_U && curwin->w_cursor.lnum == 1)
+ || (cap->cmdchar == Ctrl_D
+ && curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count))
+ clearopbeep(cap->oap);
+ else if (!checkclearop(cap->oap))
+ halfpage(cap->cmdchar == Ctrl_D, cap->count0);
+}
+
+/*
+ * Handle "J" or "gJ" command.
+ */
+ static void
+nv_join(cap)
+ cmdarg_T *cap;
+{
+#ifdef FEAT_VISUAL
+ if (VIsual_active) /* join the visual lines */
+ nv_operator(cap);
+ else
+#endif
+ if (!checkclearop(cap->oap))
+ {
+ if (cap->count0 <= 1)
+ cap->count0 = 2; /* default for join is two lines! */
+ if (curwin->w_cursor.lnum + cap->count0 - 1 >
+ curbuf->b_ml.ml_line_count)
+ clearopbeep(cap->oap); /* beyond last line */
+ else
+ {
+ prep_redo(cap->oap->regname, cap->count0,
+ NUL, cap->cmdchar, NUL, NUL, cap->nchar);
+ do_do_join(cap->count0, cap->nchar == NUL);
+ }
+ }
+}
+
+/*
+ * "P", "gP", "p" and "gp" commands.
+ */
+ static void
+nv_put(cap)
+ cmdarg_T *cap;
+{
+#ifdef FEAT_VISUAL
+ int regname = 0;
+ void *reg1 = NULL, *reg2 = NULL;
+#endif
+ int dir;
+ int flags = 0;
+
+ if (cap->oap->op_type != OP_NOP)
+ {
+#ifdef FEAT_DIFF
+ /* "dp" is ":diffput" */
+ if (cap->oap->op_type == OP_DELETE && cap->cmdchar == 'p')
+ {
+ clearop(cap->oap);
+ nv_diffgetput(TRUE);
+ }
+ else
+#endif
+ clearopbeep(cap->oap);
+ }
+ else
+ {
+ dir = (cap->cmdchar == 'P'
+ || (cap->cmdchar == 'g' && cap->nchar == 'P'))
+ ? BACKWARD : FORWARD;
+ prep_redo_cmd(cap);
+ if (cap->cmdchar == 'g')
+ flags |= PUT_CURSEND;
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ /* Putting in Visual mode: The put text replaces the selected
+ * text. First delete the selected text, then put the new text.
+ * Need to save and restore the registers that the delete
+ * overwrites if the old contents is being put.
+ */
+ regname = cap->oap->regname;
+# ifdef FEAT_CLIPBOARD
+ adjust_clip_reg(&regname);
+# endif
+ if (regname == 0 || VIM_ISDIGIT(regname)
+# ifdef FEAT_CLIPBOARD
+ || (clip_unnamed && (regname == '*' || regname == '+'))
+# endif
+
+ )
+ {
+ /* the delete is going to overwrite the register we want to
+ * put, save it first. */
+ reg1 = get_register(regname, TRUE);
+ }
+
+ /* Now delete the selected text. */
+ cap->cmdchar = 'd';
+ cap->nchar = NUL;
+ cap->oap->regname = NUL;
+ nv_operator(cap);
+ do_pending_operator(cap, 0, FALSE);
+
+ /* delete PUT_LINE_BACKWARD; */
+ cap->oap->regname = regname;
+
+ if (reg1 != NULL)
+ {
+ /* Delete probably changed the register we want to put, save
+ * it first. Then put back what was there before the delete. */
+ reg2 = get_register(regname, FALSE);
+ put_register(regname, reg1);
+ }
+
+ /* When deleted a linewise Visual area, put the register as
+ * lines to avoid it joined with the next line. When deletion was
+ * characterwise, split a line when putting lines. */
+ if (VIsual_mode == 'V')
+ flags |= PUT_LINE;
+ else if (VIsual_mode == 'v')
+ flags |= PUT_LINE_SPLIT;
+ if (VIsual_mode == Ctrl_V && dir == FORWARD)
+ flags |= PUT_LINE_FORWARD;
+ dir = BACKWARD;
+ if ((VIsual_mode != 'V'
+ && curwin->w_cursor.col < curbuf->b_op_start.col)
+ || (VIsual_mode == 'V'
+ && curwin->w_cursor.lnum < curbuf->b_op_start.lnum))
+ /* cursor is at the end of the line or end of file, put
+ * forward. */
+ dir = FORWARD;
+ }
+#endif
+ do_put(cap->oap->regname, dir, cap->count1, flags);
+
+#ifdef FEAT_VISUAL
+ /* If a register was saved, put it back now. */
+ if (reg2 != NULL)
+ put_register(regname, reg2);
+#endif
+ auto_format(FALSE, TRUE);
+ }
+}
+
+/*
+ * "o" and "O" commands.
+ */
+ static void
+nv_open(cap)
+ cmdarg_T *cap;
+{
+#ifdef FEAT_DIFF
+ /* "do" is ":diffget" */
+ if (cap->oap->op_type == OP_DELETE && cap->cmdchar == 'o')
+ {
+ clearop(cap->oap);
+ nv_diffgetput(FALSE);
+ }
+ else
+#endif
+#ifdef FEAT_VISUAL
+ if (VIsual_active) /* switch start and end of visual */
+ v_swap_corners(cap->cmdchar);
+ else
+#endif
+ n_opencmd(cap);
+}
+
+#ifdef FEAT_SNIFF
+/*ARGSUSED*/
+ static void
+nv_sniff(cap)
+ cmdarg_T *cap;
+{
+ ProcessSniffRequests();
+}
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+ static void
+nv_nbcmd(cap)
+ cmdarg_T *cap;
+{
+ netbeans_keycommand(cap->nchar);
+}
+#endif
+
+#ifdef FEAT_DND
+/*ARGSUSED*/
+ static void
+nv_drop(cap)
+ cmdarg_T *cap;
+{
+ do_put('~', BACKWARD, 1L, PUT_CURSEND);
+}
+#endif
diff --git a/src/ops.c b/src/ops.c
new file mode 100644
index 000000000..e240c45f3
--- /dev/null
+++ b/src/ops.c
@@ -0,0 +1,6114 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * ops.c: implementation of various operators: op_shift, op_delete, op_tilde,
+ * op_change, op_yank, do_put, do_join
+ */
+
+#include "vim.h"
+
+/*
+ * Number of registers.
+ * 0 = unnamed register, for normal yanks and puts
+ * 1..9 = registers '1' to '9', for deletes
+ * 10..35 = registers 'a' to 'z'
+ * 36 = delete register '-'
+ * 37 = Selection register '*'. Only if FEAT_CLIPBOARD defined
+ * 38 = Clipboard register '+'. Only if FEAT_CLIPBOARD and FEAT_X11 defined
+ */
+/*
+ * Symbolic names for some registers.
+ */
+#define DELETION_REGISTER 36
+#ifdef FEAT_CLIPBOARD
+# define STAR_REGISTER 37
+# ifdef FEAT_X11
+# define PLUS_REGISTER 38
+# else
+# define PLUS_REGISTER STAR_REGISTER /* there is only one */
+# endif
+#endif
+#ifdef FEAT_DND
+# define TILDE_REGISTER (PLUS_REGISTER + 1)
+#endif
+
+#ifdef FEAT_CLIPBOARD
+# ifdef FEAT_DND
+# define NUM_REGISTERS (TILDE_REGISTER + 1)
+# else
+# define NUM_REGISTERS (PLUS_REGISTER + 1)
+# endif
+#else
+# define NUM_REGISTERS 37
+#endif
+
+/*
+ * Each yank register is an array of pointers to lines.
+ */
+static struct yankreg
+{
+ char_u **y_array; /* pointer to array of line pointers */
+ linenr_T y_size; /* number of lines in y_array */
+ char_u y_type; /* MLINE, MCHAR or MBLOCK */
+#ifdef FEAT_VISUAL
+ colnr_T y_width; /* only set if y_type == MBLOCK */
+#endif
+} y_regs[NUM_REGISTERS];
+
+static struct yankreg *y_current; /* ptr to current yankreg */
+static int y_append; /* TRUE when appending */
+static struct yankreg *y_previous = NULL; /* ptr to last written yankreg */
+
+/*
+ * structure used by block_prep, op_delete and op_yank for blockwise operators
+ * also op_change, op_shift, op_insert, op_replace - AKelly
+ */
+struct block_def
+{
+ int startspaces; /* 'extra' cols of first char */
+ int endspaces; /* 'extra' cols of first char */
+ int textlen; /* chars in block */
+ char_u *textstart; /* pointer to 1st char in block */
+ colnr_T textcol; /* cols of chars (at least part.) in block */
+ colnr_T start_vcol; /* start col of 1st char wholly inside block */
+ colnr_T end_vcol; /* start col of 1st char wholly after block */
+#ifdef FEAT_VISUALEXTRA
+ int is_short; /* TRUE if line is too short to fit in block */
+ int is_MAX; /* TRUE if curswant==MAXCOL when starting */
+ int is_oneChar; /* TRUE if block within one character */
+ int pre_whitesp; /* screen cols of ws before block */
+ int pre_whitesp_c; /* chars of ws before block */
+ colnr_T end_char_vcols; /* number of vcols of post-block char */
+#endif
+ colnr_T start_char_vcols; /* number of vcols of pre-block char */
+};
+
+#ifdef FEAT_VISUALEXTRA
+static void shift_block __ARGS((oparg_T *oap, int amount));
+static void block_insert __ARGS((oparg_T *oap, char_u *s, int b_insert, struct block_def*bdp));
+#endif
+static void get_yank_register __ARGS((int regname, int writing));
+static int stuff_yank __ARGS((int, char_u *));
+static void put_reedit_in_typebuf __ARGS((void));
+static int put_in_typebuf __ARGS((char_u *s, int colon));
+static void stuffescaped __ARGS((char_u *arg, int literally));
+static int get_spec_reg __ARGS((int regname, char_u **argp, int *allocated, int errmsg));
+static void cmdline_paste_str __ARGS((char_u *s, int literally));
+#ifdef FEAT_MBYTE
+static void mb_adjust_opend __ARGS((oparg_T *oap));
+#endif
+static void free_yank __ARGS((long));
+static void free_yank_all __ARGS((void));
+static int yank_copy_line __ARGS((struct block_def *bd, long y_idx));
+#ifdef FEAT_CLIPBOARD
+static void copy_yank_reg __ARGS((struct yankreg *reg));
+# if defined(FEAT_VISUAL) || defined(FEAT_EVAL)
+static void may_set_selection __ARGS((void));
+# endif
+#endif
+static void dis_msg __ARGS((char_u *p, int skip_esc));
+#ifdef FEAT_VISUAL
+static void block_prep __ARGS((oparg_T *oap, struct block_def *, linenr_T, int));
+#endif
+#if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
+static void str_to_reg __ARGS((struct yankreg *y_ptr, int type, char_u *str, long len, long blocklen));
+#endif
+static int ends_in_white __ARGS((linenr_T lnum));
+#ifdef FEAT_COMMENTS
+static int same_leader __ARGS((linenr_T lnum, int, char_u *, int, char_u *));
+static int fmt_check_par __ARGS((linenr_T, int *, char_u **, int do_comments));
+#else
+static int fmt_check_par __ARGS((linenr_T));
+#endif
+
+/*
+ * The names of operators.
+ * IMPORTANT: Index must correspond with defines in vim.h!!!
+ * The third field indicates whether the operator always works on lines.
+ */
+static char opchars[][3] =
+{
+ {NUL, NUL, FALSE}, /* OP_NOP */
+ {'d', NUL, FALSE}, /* OP_DELETE */
+ {'y', NUL, FALSE}, /* OP_YANK */
+ {'c', NUL, FALSE}, /* OP_CHANGE */
+ {'<', NUL, TRUE}, /* OP_LSHIFT */
+ {'>', NUL, TRUE}, /* OP_RSHIFT */
+ {'!', NUL, TRUE}, /* OP_FILTER */
+ {'g', '~', FALSE}, /* OP_TILDE */
+ {'=', NUL, TRUE}, /* OP_INDENT */
+ {'g', 'q', TRUE}, /* OP_FORMAT */
+ {':', NUL, TRUE}, /* OP_COLON */
+ {'g', 'U', FALSE}, /* OP_UPPER */
+ {'g', 'u', FALSE}, /* OP_LOWER */
+ {'J', NUL, TRUE}, /* DO_JOIN */
+ {'g', 'J', TRUE}, /* DO_JOIN_NS */
+ {'g', '?', FALSE}, /* OP_ROT13 */
+ {'r', NUL, FALSE}, /* OP_REPLACE */
+ {'I', NUL, FALSE}, /* OP_INSERT */
+ {'A', NUL, FALSE}, /* OP_APPEND */
+ {'z', 'f', TRUE}, /* OP_FOLD */
+ {'z', 'o', TRUE}, /* OP_FOLDOPEN */
+ {'z', 'O', TRUE}, /* OP_FOLDOPENREC */
+ {'z', 'c', TRUE}, /* OP_FOLDCLOSE */
+ {'z', 'C', TRUE}, /* OP_FOLDCLOSEREC */
+ {'z', 'd', TRUE}, /* OP_FOLDDEL */
+ {'z', 'D', TRUE}, /* OP_FOLDDELREC */
+ {'g', 'w', TRUE}, /* OP_FORMAT2 */
+};
+
+/*
+ * Translate a command name into an operator type.
+ * Must only be called with a valid operator name!
+ */
+ int
+get_op_type(char1, char2)
+ int char1;
+ int char2;
+{
+ int i;
+
+ if (char1 == 'r') /* ignore second character */
+ return OP_REPLACE;
+ if (char1 == '~') /* when tilde is an operator */
+ return OP_TILDE;
+ for (i = 0; ; ++i)
+ if (opchars[i][0] == char1 && opchars[i][1] == char2)
+ break;
+ return i;
+}
+
+#if defined(FEAT_VISUAL) || defined(PROTO)
+/*
+ * Return TRUE if operator "op" always works on whole lines.
+ */
+ int
+op_on_lines(op)
+ int op;
+{
+ return opchars[op][2];
+}
+#endif
+
+/*
+ * Get first operator command character.
+ * Returns 'g' or 'z' if there is another command character.
+ */
+ int
+get_op_char(optype)
+ int optype;
+{
+ return opchars[optype][0];
+}
+
+/*
+ * Get second operator command character.
+ */
+ int
+get_extra_op_char(optype)
+ int optype;
+{
+ return opchars[optype][1];
+}
+
+/*
+ * op_shift - handle a shift operation
+ */
+ void
+op_shift(oap, curs_top, amount)
+ oparg_T *oap;
+ int curs_top;
+ int amount;
+{
+ long i;
+ int first_char;
+ char_u *s;
+#ifdef FEAT_VISUAL
+ int block_col = 0;
+#endif
+
+ if (u_save((linenr_T)(oap->start.lnum - 1),
+ (linenr_T)(oap->end.lnum + 1)) == FAIL)
+ return;
+
+#ifdef FEAT_VISUAL
+ if (oap->block_mode)
+ block_col = curwin->w_cursor.col;
+#endif
+
+ for (i = oap->line_count; --i >= 0; )
+ {
+ first_char = *ml_get_curline();
+ if (first_char == NUL) /* empty line */
+ curwin->w_cursor.col = 0;
+#ifdef FEAT_VISUALEXTRA
+ else if (oap->block_mode)
+ shift_block(oap, amount);
+#endif
+ else
+ /* Move the line right if it doesn't start with '#', 'smartindent'
+ * isn't set or 'cindent' isn't set or '#' isn't in 'cino'. */
+#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
+ if (first_char != '#' || !preprocs_left())
+#endif
+ {
+ shift_line(oap->op_type == OP_LSHIFT, p_sr, amount);
+ }
+ ++curwin->w_cursor.lnum;
+ }
+
+ changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L);
+
+#ifdef FEAT_VISUAL
+ if (oap->block_mode)
+ {
+ curwin->w_cursor.lnum = oap->start.lnum;
+ curwin->w_cursor.col = block_col;
+ }
+ else
+#endif
+ if (curs_top) /* put cursor on first line, for ">>" */
+ {
+ curwin->w_cursor.lnum = oap->start.lnum;
+ beginline(BL_SOL | BL_FIX); /* shift_line() may have set cursor.col */
+ }
+ else
+ --curwin->w_cursor.lnum; /* put cursor on last line, for ":>" */
+
+ if (oap->line_count > p_report)
+ {
+ if (oap->op_type == OP_RSHIFT)
+ s = (char_u *)">";
+ else
+ s = (char_u *)"<";
+ if (oap->line_count == 1)
+ {
+ if (amount == 1)
+ sprintf((char *)IObuff, _("1 line %sed 1 time"), s);
+ else
+ sprintf((char *)IObuff, _("1 line %sed %d times"), s, amount);
+ }
+ else
+ {
+ if (amount == 1)
+ sprintf((char *)IObuff, _("%ld lines %sed 1 time"),
+ oap->line_count, s);
+ else
+ sprintf((char *)IObuff, _("%ld lines %sed %d times"),
+ oap->line_count, s, amount);
+ }
+ msg(IObuff);
+ }
+
+ /*
+ * Set "'[" and "']" marks.
+ */
+ curbuf->b_op_start = oap->start;
+ curbuf->b_op_end.lnum = oap->end.lnum;
+ curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+ if (curbuf->b_op_end.col > 0)
+ --curbuf->b_op_end.col;
+}
+
+/*
+ * shift the current line one shiftwidth left (if left != 0) or right
+ * leaves cursor on first blank in the line
+ */
+ void
+shift_line(left, round, amount)
+ int left;
+ int round;
+ int amount;
+{
+ int count;
+ int i, j;
+ int p_sw = (int)curbuf->b_p_sw;
+
+ count = get_indent(); /* get current indent */
+
+ if (round) /* round off indent */
+ {
+ i = count / p_sw; /* number of p_sw rounded down */
+ j = count % p_sw; /* extra spaces */
+ if (j && left) /* first remove extra spaces */
+ --amount;
+ if (left)
+ {
+ i -= amount;
+ if (i < 0)
+ i = 0;
+ }
+ else
+ i += amount;
+ count = i * p_sw;
+ }
+ else /* original vi indent */
+ {
+ if (left)
+ {
+ count -= p_sw * amount;
+ if (count < 0)
+ count = 0;
+ }
+ else
+ count += p_sw * amount;
+ }
+
+ /* Set new indent */
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ change_indent(INDENT_SET, count, FALSE, NUL);
+ else
+#endif
+ (void)set_indent(count, SIN_CHANGED);
+}
+
+#if defined(FEAT_VISUALEXTRA) || defined(PROTO)
+/*
+ * Shift one line of the current block one shiftwidth right or left.
+ * Leaves cursor on first character in block.
+ */
+ static void
+shift_block(oap, amount)
+ oparg_T *oap;
+ int amount;
+{
+ int left = (oap->op_type == OP_LSHIFT);
+ int oldstate = State;
+ int total, split;
+ char_u *newp, *oldp, *midp, *ptr;
+ int oldcol = curwin->w_cursor.col;
+ int p_sw = (int)curbuf->b_p_sw;
+ int p_ts = (int)curbuf->b_p_ts;
+ struct block_def bd;
+ int internal = 0;
+ int incr;
+ colnr_T vcol, col = 0, ws_vcol;
+ int i = 0, j = 0;
+ int len;
+
+#ifdef FEAT_RIGHTLEFT
+ int old_p_ri = p_ri;
+
+ p_ri = 0; /* don't want revins in ident */
+#endif
+
+ State = INSERT; /* don't want REPLACE for State */
+ block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE);
+ if (bd.is_short)
+ return;
+
+ /* total is number of screen columns to be inserted/removed */
+ total = amount * p_sw;
+ oldp = ml_get_curline();
+
+ if (!left)
+ {
+ /*
+ * 1. Get start vcol
+ * 2. Total ws vcols
+ * 3. Divvy into TABs & spp
+ * 4. Construct new string
+ */
+ total += bd.pre_whitesp; /* all virtual WS upto & incl a split TAB */
+ ws_vcol = bd.start_vcol - bd.pre_whitesp;
+ if (bd.startspaces)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ bd.textstart += (*mb_ptr2len_check)(bd.textstart);
+#endif
+ ++bd.textstart;
+ }
+ for ( ; vim_iswhite(*bd.textstart); )
+ {
+ incr = lbr_chartabsize_adv(&bd.textstart, (colnr_T)(bd.start_vcol));
+ total += incr;
+ bd.start_vcol += incr;
+ }
+ /* OK, now total=all the VWS reqd, and textstart points at the 1st
+ * non-ws char in the block. */
+ if (!curbuf->b_p_et)
+ i = ((ws_vcol % p_ts) + total) / p_ts; /* number of tabs */
+ if (i)
+ j = ((ws_vcol % p_ts) + total) % p_ts; /* number of spp */
+ else
+ j = total;
+ /* if we're splitting a TAB, allow for it */
+ bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0);
+ len = (int)STRLEN(bd.textstart) + 1;
+ newp = alloc_check((unsigned)(bd.textcol + i + j + len));
+ if (newp == NULL)
+ return;
+ vim_memset(newp, NUL, (size_t)(bd.textcol + i + j + len));
+ mch_memmove(newp, oldp, (size_t)bd.textcol);
+ copy_chars(newp + bd.textcol, (size_t)i, TAB);
+ copy_spaces(newp + bd.textcol + i, (size_t)j);
+ /* the end */
+ mch_memmove(newp + bd.textcol + i + j, bd.textstart, (size_t)len);
+ }
+ else /* left */
+ {
+ vcol = oap->start_vcol;
+ /* walk vcol past ws to be removed */
+ for (midp = oldp + bd.textcol;
+ vcol < (oap->start_vcol + total) && vim_iswhite(*midp); )
+ {
+ incr = lbr_chartabsize_adv(&midp, (colnr_T)vcol);
+ vcol += incr;
+ }
+ /* internal is the block-internal ws replacing a split TAB */
+ if (vcol > (oap->start_vcol + total))
+ {
+ /* we have to split the TAB *(midp-1) */
+ internal = vcol - (oap->start_vcol + total);
+ }
+ /* if 'expandtab' is not set, use TABs */
+
+ split = bd.startspaces + internal;
+ if (split > 0)
+ {
+ if (!curbuf->b_p_et)
+ {
+ for (ptr = oldp, col = 0; ptr < oldp+bd.textcol; )
+ col += lbr_chartabsize_adv(&ptr, (colnr_T)col);
+
+ /* col+1 now equals the start col of the first char of the
+ * block (may be < oap.start_vcol if we're splitting a TAB) */
+ i = ((col % p_ts) + split) / p_ts; /* number of tabs */
+ }
+ if (i)
+ j = ((col % p_ts) + split) % p_ts; /* number of spp */
+ else
+ j = split;
+ }
+
+ newp = alloc_check(bd.textcol + i + j + (unsigned)STRLEN(midp) + 1);
+ if (newp == NULL)
+ return;
+ vim_memset(newp, NUL, (size_t)(bd.textcol + i + j + STRLEN(midp) + 1));
+
+ /* copy first part we want to keep */
+ mch_memmove(newp, oldp, (size_t)bd.textcol);
+ /* Now copy any TABS and spp to ensure correct alignment! */
+ while (vim_iswhite(*midp))
+ {
+ if (*midp == TAB)
+ i++;
+ else /*space */
+ j++;
+ midp++;
+ }
+ /* We might have an extra TAB worth of spp now! */
+ if (j / p_ts && !curbuf->b_p_et)
+ {
+ i++;
+ j -= p_ts;
+ }
+ copy_chars(newp + bd.textcol, (size_t)i, TAB);
+ copy_spaces(newp + bd.textcol + i, (size_t)j);
+
+ /* the end */
+ mch_memmove(newp + STRLEN(newp), midp, (size_t)STRLEN(midp) + 1);
+ }
+ /* replace the line */
+ ml_replace(curwin->w_cursor.lnum, newp, FALSE);
+ changed_bytes(curwin->w_cursor.lnum, (colnr_T)bd.textcol);
+ State = oldstate;
+ curwin->w_cursor.col = oldcol;
+#ifdef FEAT_RIGHTLEFT
+ p_ri = old_p_ri;
+#endif
+}
+#endif
+
+#ifdef FEAT_VISUALEXTRA
+/*
+ * Insert string "s" (b_insert ? before : after) block :AKelly
+ * Caller must prepare for undo.
+ */
+ static void
+block_insert(oap, s, b_insert, bdp)
+ oparg_T *oap;
+ char_u *s;
+ int b_insert;
+ struct block_def *bdp;
+{
+ int p_ts;
+ int count = 0; /* extra spaces to replace a cut TAB */
+ int spaces = 0; /* non-zero if cutting a TAB */
+ colnr_T offset; /* pointer along new line */
+ unsigned s_len; /* STRLEN(s) */
+ char_u *newp, *oldp; /* new, old lines */
+ linenr_T lnum; /* loop var */
+ int oldstate = State;
+
+ State = INSERT; /* don't want REPLACE for State */
+ s_len = (unsigned)STRLEN(s);
+
+ for (lnum = oap->start.lnum + 1; lnum <= oap->end.lnum; lnum++)
+ {
+ block_prep(oap, bdp, lnum, TRUE);
+ if (bdp->is_short && b_insert)
+ continue; /* OP_INSERT, line ends before block start */
+
+ oldp = ml_get(lnum);
+
+ if (b_insert)
+ {
+ p_ts = bdp->start_char_vcols;
+ spaces = bdp->startspaces;
+ if (spaces != 0)
+ count = p_ts - 1; /* we're cutting a TAB */
+ offset = bdp->textcol;
+ }
+ else /* append */
+ {
+ p_ts = bdp->end_char_vcols;
+ if (!bdp->is_short) /* spaces = padding after block */
+ {
+ spaces = (bdp->endspaces ? p_ts - bdp->endspaces : 0);
+ if (spaces != 0)
+ count = p_ts - 1; /* we're cutting a TAB */
+ offset = bdp->textcol + bdp->textlen - (spaces != 0);
+ }
+ else /* spaces = padding to block edge */
+ {
+ /* if $ used, just append to EOL (ie spaces==0) */
+ if (!bdp->is_MAX)
+ spaces = (oap->end_vcol - bdp->end_vcol) + 1;
+ count = spaces;
+ offset = bdp->textcol + bdp->textlen;
+ }
+ }
+
+ newp = alloc_check((unsigned)(STRLEN(oldp)) + s_len + count + 1);
+ if (newp == NULL)
+ continue;
+
+ /* copy up to shifted part */
+ mch_memmove(newp, oldp, (size_t)(offset));
+ oldp += offset;
+
+ /* insert pre-padding */
+ copy_spaces(newp + offset, (size_t)spaces);
+
+ /* copy the new text */
+ mch_memmove(newp + offset + spaces, s, (size_t)s_len);
+ offset += s_len;
+
+ if (spaces && !bdp->is_short)
+ {
+ /* insert post-padding */
+ copy_spaces(newp + offset + spaces, (size_t)(p_ts - spaces));
+ /* We're splitting a TAB, don't copy it. */
+ oldp++;
+ /* We allowed for that TAB, remember this now */
+ count++;
+ }
+
+ if (spaces > 0)
+ offset += count;
+ mch_memmove(newp + offset, oldp, (size_t)(STRLEN(oldp) + 1));
+
+ ml_replace(lnum, newp, FALSE);
+
+ if (lnum == oap->end.lnum)
+ {
+ /* Set "']" mark to the end of the block instead of the end of
+ * the insert in the first line. */
+ curbuf->b_op_end.lnum = oap->end.lnum;
+ curbuf->b_op_end.col = offset;
+ }
+ } /* for all lnum */
+
+ changed_lines(oap->start.lnum + 1, 0, oap->end.lnum + 1, 0L);
+
+ State = oldstate;
+}
+#endif
+
+#if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(PROTO)
+/*
+ * op_reindent - handle reindenting a block of lines.
+ */
+ void
+op_reindent(oap, how)
+ oparg_T *oap;
+ int (*how) __ARGS((void));
+{
+ long i;
+ char_u *l;
+ int count;
+ linenr_T first_changed = 0;
+ linenr_T last_changed = 0;
+ linenr_T start_lnum = curwin->w_cursor.lnum;
+
+ for (i = oap->line_count; --i >= 0 && !got_int; )
+ {
+ /* it's a slow thing to do, so give feedback so there's no worry that
+ * the computer's just hung. */
+
+ if (i > 1
+ && (i % 50 == 0 || i == oap->line_count - 1)
+ && oap->line_count > p_report)
+ smsg((char_u *)_("%ld lines to indent... "), i);
+
+ /*
+ * Be vi-compatible: For lisp indenting the first line is not
+ * indented, unless there is only one line.
+ */
+#ifdef FEAT_LISP
+ if (i != oap->line_count - 1 || oap->line_count == 1
+ || how != get_lisp_indent)
+#endif
+ {
+ l = skipwhite(ml_get_curline());
+ if (*l == NUL) /* empty or blank line */
+ count = 0;
+ else
+ count = how(); /* get the indent for this line */
+
+ if (set_indent(count, SIN_UNDO))
+ {
+ /* did change the indent, call changed_lines() later */
+ if (first_changed == 0)
+ first_changed = curwin->w_cursor.lnum;
+ last_changed = curwin->w_cursor.lnum;
+ }
+ }
+ ++curwin->w_cursor.lnum;
+ }
+
+ /* put cursor on first non-blank of indented line */
+ curwin->w_cursor.lnum = start_lnum;
+ beginline(BL_SOL | BL_FIX);
+
+ /* Mark changed lines so that they will be redrawn. When Visual
+ * highlighting was present, need to continue until the last line. When
+ * there is no change still need to remove the Visual highlighting. */
+ if (last_changed != 0)
+ changed_lines(first_changed, 0,
+#ifdef FEAT_VISUAL
+ oap->is_VIsual ? start_lnum + oap->line_count :
+#endif
+ last_changed + 1, 0L);
+#ifdef FEAT_VISUAL
+ else if (oap->is_VIsual)
+ redraw_curbuf_later(INVERTED);
+#endif
+
+ if (oap->line_count > p_report)
+ {
+ i = oap->line_count - (i + 1);
+ if (i == 1)
+ MSG(_("1 line indented "));
+ else
+ smsg((char_u *)_("%ld lines indented "), i);
+ }
+ /* set '[ and '] marks */
+ curbuf->b_op_start = oap->start;
+ curbuf->b_op_end = oap->end;
+}
+#endif /* defined(FEAT_LISP) || defined(FEAT_CINDENT) */
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Keep the last expression line here, for repeating.
+ */
+static char_u *expr_line = NULL;
+
+/*
+ * Get an expression for the "\"=expr1" or "CTRL-R =expr1"
+ * Returns '=' when OK, NUL otherwise.
+ */
+ int
+get_expr_register()
+{
+ char_u *new_line;
+
+ new_line = getcmdline('=', 0L, 0);
+ if (new_line == NULL)
+ return NUL;
+ if (*new_line == NUL) /* use previous line */
+ vim_free(new_line);
+ else
+ set_expr_line(new_line);
+ return '=';
+}
+
+/*
+ * Set the expression for the '=' register.
+ * Argument must be an allocated string.
+ */
+ void
+set_expr_line(new_line)
+ char_u *new_line;
+{
+ vim_free(expr_line);
+ expr_line = new_line;
+}
+
+/*
+ * Get the result of the '=' register expression.
+ * Returns a pointer to allocated memory, or NULL for failure.
+ */
+ char_u *
+get_expr_line()
+{
+ char_u *expr_copy;
+ char_u *rv;
+
+ if (expr_line == NULL)
+ return NULL;
+
+ /* Make a copy of the expression, because evaluating it may cause it to be
+ * changed. */
+ expr_copy = vim_strsave(expr_line);
+ if (expr_copy == NULL)
+ return NULL;
+
+ rv = eval_to_string(expr_copy, NULL);
+ vim_free(expr_copy);
+ return rv;
+}
+#endif /* FEAT_EVAL */
+
+/*
+ * Check if 'regname' is a valid name of a yank register.
+ * Note: There is no check for 0 (default register), caller should do this
+ */
+ int
+valid_yank_reg(regname, writing)
+ int regname;
+ int writing; /* if TRUE check for writable registers */
+{
+ if ( (regname > 0 && ASCII_ISALNUM(regname))
+ || (!writing && vim_strchr((char_u *)
+#ifdef FEAT_EVAL
+ "/.%#:="
+#else
+ "/.%#:"
+#endif
+ , regname) != NULL)
+ || regname == '"'
+ || regname == '-'
+ || regname == '_'
+#ifdef FEAT_CLIPBOARD
+ || regname == '*'
+ || regname == '+'
+#endif
+#ifdef FEAT_DND
+ || (!writing && regname == '~')
+#endif
+ )
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Set y_current and y_append, according to the value of "regname".
+ * Cannot handle the '_' register.
+ *
+ * If regname is 0 and writing, use register 0
+ * If regname is 0 and reading, use previous register
+ */
+ static void
+get_yank_register(regname, writing)
+ int regname;
+ int writing;
+{
+ int i;
+
+ y_append = FALSE;
+ if ((regname == 0 || regname == '"') && !writing && y_previous != NULL)
+ {
+ y_current = y_previous;
+ return;
+ }
+ i = regname;
+ if (VIM_ISDIGIT(i))
+ i -= '0';
+ else if (ASCII_ISLOWER(i))
+ i = CharOrdLow(i) + 10;
+ else if (ASCII_ISUPPER(i))
+ {
+ i = CharOrdUp(i) + 10;
+ y_append = TRUE;
+ }
+ else if (regname == '-')
+ i = DELETION_REGISTER;
+#ifdef FEAT_CLIPBOARD
+ /* When selection is not available, use register 0 instead of '*' */
+ else if (clip_star.available && regname == '*')
+ i = STAR_REGISTER;
+ /* When clipboard is not available, use register 0 instead of '+' */
+ else if (clip_plus.available && regname == '+')
+ i = PLUS_REGISTER;
+#endif
+#ifdef FEAT_DND
+ else if (!writing && regname == '~')
+ i = TILDE_REGISTER;
+#endif
+ else /* not 0-9, a-z, A-Z or '-': use register 0 */
+ i = 0;
+ y_current = &(y_regs[i]);
+ if (writing) /* remember the register we write into for do_put() */
+ y_previous = y_current;
+}
+
+#ifdef FEAT_CLIPBOARD
+/*
+ * When "regname" is a clipboard register, obtain the selection. If it's not
+ * available return zero, otherwise return "regname".
+ */
+static int may_get_selection __ARGS((int regname));
+
+ static int
+may_get_selection(regname)
+ int regname;
+{
+ if (regname == '*')
+ {
+ if (!clip_star.available)
+ regname = 0;
+ else
+ clip_get_selection(&clip_star);
+ }
+ else if (regname == '+')
+ {
+ if (!clip_plus.available)
+ regname = 0;
+ else
+ clip_get_selection(&clip_plus);
+ }
+ return regname;
+}
+#endif
+
+#if defined(FEAT_VISUAL) || defined(PROTO)
+/*
+ * Obtain the contents of a "normal" register. The register is made empty.
+ * The returned pointer has allocated memory, use put_register() later.
+ */
+ void *
+get_register(name, copy)
+ int name;
+ int copy; /* make a copy, if FALSE make register empty. */
+{
+ static struct yankreg *reg;
+ int i;
+
+#ifdef FEAT_CLIPBOARD
+ /* When Visual area changed, may have to update selection. Obtain the
+ * selection too. */
+ if (name == '*' && clip_star.available && clip_isautosel())
+ {
+ clip_update_selection();
+ may_get_selection(name);
+ }
+#endif
+
+ get_yank_register(name, 0);
+ reg = (struct yankreg *)alloc((unsigned)sizeof(struct yankreg));
+ if (reg != NULL)
+ {
+ *reg = *y_current;
+ if (copy)
+ {
+ /* If we run out of memory some or all of the lines are empty. */
+ if (reg->y_size == 0)
+ reg->y_array = NULL;
+ else
+ reg->y_array = (char_u **)alloc((unsigned)(sizeof(char_u *)
+ * reg->y_size));
+ if (reg->y_array != NULL)
+ {
+ for (i = 0; i < reg->y_size; ++i)
+ reg->y_array[i] = vim_strsave(y_current->y_array[i]);
+ }
+ }
+ else
+ y_current->y_array = NULL;
+ }
+ return (void *)reg;
+}
+
+/*
+ * Put "reg" into register "name". Free any previous contents.
+ */
+ void
+put_register(name, reg)
+ int name;
+ void *reg;
+{
+ get_yank_register(name, 0);
+ free_yank_all();
+ *y_current = *(struct yankreg *)reg;
+
+# ifdef FEAT_CLIPBOARD
+ /* Send text written to clipboard register to the clipboard. */
+ may_set_selection();
+# endif
+}
+#endif
+
+#if defined(FEAT_MOUSE) || defined(PROTO)
+/*
+ * return TRUE if the current yank register has type MLINE
+ */
+ int
+yank_register_mline(regname)
+ int regname;
+{
+ if (regname != 0 && !valid_yank_reg(regname, FALSE))
+ return FALSE;
+ if (regname == '_') /* black hole is always empty */
+ return FALSE;
+ get_yank_register(regname, FALSE);
+ return (y_current->y_type == MLINE);
+}
+#endif
+
+/*
+ * start or stop recording into a yank register
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+do_record(c)
+ int c;
+{
+ char_u *p;
+ static int regname;
+ struct yankreg *old_y_previous, *old_y_current;
+ int retval;
+
+ if (Recording == FALSE) /* start recording */
+ {
+ /* registers 0-9, a-z and " are allowed */
+ if (c < 0 || (!ASCII_ISALNUM(c) && c != '"'))
+ retval = FAIL;
+ else
+ {
+ Recording = TRUE;
+ showmode();
+ regname = c;
+ retval = OK;
+ }
+ }
+ else /* stop recording */
+ {
+ /*
+ * Get the recorded key hits. K_SPECIAL and CSI will be escaped, so
+ * that the register can be put into the typeahead buffer without
+ * translation.
+ */
+ Recording = FALSE;
+ MSG("");
+ p = get_recorded();
+ if (p == NULL)
+ retval = FAIL;
+ else
+ {
+ /*
+ * We don't want to change the default register here, so save and
+ * restore the current register name.
+ */
+ old_y_previous = y_previous;
+ old_y_current = y_current;
+
+ retval = stuff_yank(regname, p);
+
+ y_previous = old_y_previous;
+ y_current = old_y_current;
+ }
+ }
+ return retval;
+}
+
+/*
+ * Stuff string "p" into yank register "regname" as a single line (append if
+ * uppercase). "p" must have been alloced.
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ static int
+stuff_yank(regname, p)
+ int regname;
+ char_u *p;
+{
+ char_u *lp;
+ char_u **pp;
+
+ /* check for read-only register */
+ if (regname != 0 && !valid_yank_reg(regname, TRUE))
+ {
+ vim_free(p);
+ return FAIL;
+ }
+ if (regname == '_') /* black hole: don't do anything */
+ {
+ vim_free(p);
+ return OK;
+ }
+ get_yank_register(regname, TRUE);
+ if (y_append && y_current->y_array != NULL)
+ {
+ pp = &(y_current->y_array[y_current->y_size - 1]);
+ lp = lalloc((long_u)(STRLEN(*pp) + STRLEN(p) + 1), TRUE);
+ if (lp == NULL)
+ {
+ vim_free(p);
+ return FAIL;
+ }
+ STRCPY(lp, *pp);
+ STRCAT(lp, p);
+ vim_free(p);
+ vim_free(*pp);
+ *pp = lp;
+ }
+ else
+ {
+ free_yank_all();
+ if ((y_current->y_array =
+ (char_u **)alloc((unsigned)sizeof(char_u *))) == NULL)
+ {
+ vim_free(p);
+ return FAIL;
+ }
+ y_current->y_array[0] = p;
+ y_current->y_size = 1;
+ y_current->y_type = MCHAR; /* used to be MLINE, why? */
+ }
+ return OK;
+}
+
+/*
+ * execute a yank register: copy it into the stuff buffer
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+do_execreg(regname, colon, addcr)
+ int regname;
+ int colon; /* insert ':' before each line */
+ int addcr; /* always add '\n' to end of line */
+{
+ static int lastc = NUL;
+ long i;
+ char_u *p;
+ int retval = OK;
+ int remap;
+
+ if (regname == '@') /* repeat previous one */
+ regname = lastc;
+ /* check for valid regname */
+ if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
+ return FAIL;
+ lastc = regname;
+
+#ifdef FEAT_CLIPBOARD
+ regname = may_get_selection(regname);
+#endif
+
+ if (regname == '_') /* black hole: don't stuff anything */
+ return OK;
+
+#ifdef FEAT_CMDHIST
+ if (regname == ':') /* use last command line */
+ {
+ if (last_cmdline == NULL)
+ {
+ EMSG(_(e_nolastcmd));
+ return FAIL;
+ }
+ vim_free(new_last_cmdline); /* don't keep the cmdline containing @: */
+ new_last_cmdline = NULL;
+ retval = put_in_typebuf(last_cmdline, TRUE);
+ }
+#endif
+#ifdef FEAT_EVAL
+ else if (regname == '=')
+ {
+ p = get_expr_line();
+ if (p == NULL)
+ return FAIL;
+ retval = put_in_typebuf(p, colon);
+ vim_free(p);
+ }
+#endif
+ else if (regname == '.') /* use last inserted text */
+ {
+ p = get_last_insert_save();
+ if (p == NULL)
+ {
+ EMSG(_(e_noinstext));
+ return FAIL;
+ }
+ retval = put_in_typebuf(p, colon);
+ vim_free(p);
+ }
+ else
+ {
+ get_yank_register(regname, FALSE);
+ if (y_current->y_array == NULL)
+ return FAIL;
+
+ /* Disallow remaping for ":@r". */
+ remap = colon ? REMAP_NONE : REMAP_YES;
+
+ /*
+ * Insert lines into typeahead buffer, from last one to first one.
+ */
+ put_reedit_in_typebuf();
+ for (i = y_current->y_size; --i >= 0; )
+ {
+ /* insert NL between lines and after last line if type is MLINE */
+ if (y_current->y_type == MLINE || i < y_current->y_size - 1
+ || addcr)
+ {
+ if (ins_typebuf((char_u *)"\n", remap, 0, TRUE, FALSE) == FAIL)
+ return FAIL;
+ }
+ if (ins_typebuf(y_current->y_array[i], remap, 0, TRUE, FALSE)
+ == FAIL)
+ return FAIL;
+ if (colon && ins_typebuf((char_u *)":", remap, 0, TRUE, FALSE)
+ == FAIL)
+ return FAIL;
+ }
+ Exec_reg = TRUE; /* disable the 'q' command */
+ }
+ return retval;
+}
+
+/*
+ * If "restart_edit" is not zero, put it in the typeahead buffer, so that it's
+ * used only after other typeahead has been processed.
+ */
+ static void
+put_reedit_in_typebuf()
+{
+ char_u buf[3];
+
+ if (restart_edit != NUL)
+ {
+ if (restart_edit == 'V')
+ {
+ buf[0] = 'g';
+ buf[1] = 'R';
+ buf[2] = NUL;
+ }
+ else
+ {
+ buf[0] = restart_edit == 'I' ? 'i' : restart_edit;
+ buf[1] = NUL;
+ }
+ if (ins_typebuf(buf, REMAP_NONE, 0, TRUE, FALSE) == OK)
+ restart_edit = NUL;
+ }
+}
+
+ static int
+put_in_typebuf(s, colon)
+ char_u *s;
+ int colon; /* add ':' before the line */
+{
+ int retval = OK;
+
+ put_reedit_in_typebuf();
+ if (colon)
+ retval = ins_typebuf((char_u *)"\n", REMAP_YES, 0, TRUE, FALSE);
+ if (retval == OK)
+ retval = ins_typebuf(s, REMAP_YES, 0, TRUE, FALSE);
+ if (colon && retval == OK)
+ retval = ins_typebuf((char_u *)":", REMAP_YES, 0, TRUE, FALSE);
+ return retval;
+}
+
+/*
+ * Insert a yank register: copy it into the Read buffer.
+ * Used by CTRL-R command and middle mouse button in insert mode.
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+insert_reg(regname, literally)
+ int regname;
+ int literally; /* insert literally, not as if typed */
+{
+ long i;
+ int retval = OK;
+ char_u *arg;
+ int allocated;
+
+ /*
+ * It is possible to get into an endless loop by having CTRL-R a in
+ * register a and then, in insert mode, doing CTRL-R a.
+ * If you hit CTRL-C, the loop will be broken here.
+ */
+ ui_breakcheck();
+ if (got_int)
+ return FAIL;
+
+ /* check for valid regname */
+ if (regname != NUL && !valid_yank_reg(regname, FALSE))
+ return FAIL;
+
+#ifdef FEAT_CLIPBOARD
+ regname = may_get_selection(regname);
+#endif
+
+ if (regname == '.') /* insert last inserted text */
+ retval = stuff_inserted(NUL, 1L, TRUE);
+ else if (get_spec_reg(regname, &arg, &allocated, TRUE))
+ {
+ if (arg == NULL)
+ return FAIL;
+ stuffescaped(arg, literally);
+ if (allocated)
+ vim_free(arg);
+ }
+ else /* name or number register */
+ {
+ get_yank_register(regname, FALSE);
+ if (y_current->y_array == NULL)
+ retval = FAIL;
+ else
+ {
+ for (i = 0; i < y_current->y_size; ++i)
+ {
+ stuffescaped(y_current->y_array[i], literally);
+ /*
+ * Insert a newline between lines and after last line if
+ * y_type is MLINE.
+ */
+ if (y_current->y_type == MLINE || i < y_current->y_size - 1)
+ stuffcharReadbuff('\n');
+ }
+ }
+ }
+
+ return retval;
+}
+
+/*
+ * Stuff a string into the typeahead buffer, such that edit() will insert it
+ * literally ("literally" TRUE) or interpret is as typed characters.
+ */
+ static void
+stuffescaped(arg, literally)
+ char_u *arg;
+ int literally;
+{
+ int c;
+ char_u *start;
+
+ while (*arg != NUL)
+ {
+ /* Stuff a sequence of normal ASCII characters, that's fast. Also
+ * stuff K_SPECIAL to get the effect of a special key when "literally"
+ * is TRUE. */
+ start = arg;
+ while ((*arg >= ' '
+#ifndef EBCDIC
+ && *arg < DEL /* EBCDIC: chars above space are normal */
+#endif
+ )
+ || (*arg == K_SPECIAL && !literally))
+ ++arg;
+ if (arg > start)
+ stuffReadbuffLen(start, (long)(arg - start));
+
+ /* stuff a single special character */
+ if (*arg != NUL)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ c = mb_ptr2char_adv(&arg);
+ else
+#endif
+ c = *arg++;
+ if (literally && ((c < ' ' && c != TAB) || c == DEL))
+ stuffcharReadbuff(Ctrl_V);
+ stuffcharReadbuff(c);
+ }
+ }
+}
+
+/*
+ * If "regname" is a special register, return a pointer to its value.
+ */
+ static int
+get_spec_reg(regname, argp, allocated, errmsg)
+ int regname;
+ char_u **argp;
+ int *allocated;
+ int errmsg; /* give error message when failing */
+{
+ int cnt;
+
+ *argp = NULL;
+ *allocated = FALSE;
+ switch (regname)
+ {
+ case '%': /* file name */
+ if (errmsg)
+ check_fname(); /* will give emsg if not set */
+ *argp = curbuf->b_fname;
+ return TRUE;
+
+ case '#': /* alternate file name */
+ *argp = getaltfname(errmsg); /* may give emsg if not set */
+ return TRUE;
+
+#ifdef FEAT_EVAL
+ case '=': /* result of expression */
+ *argp = get_expr_line();
+ *allocated = TRUE;
+ return TRUE;
+#endif
+
+ case ':': /* last command line */
+ if (last_cmdline == NULL && errmsg)
+ EMSG(_(e_nolastcmd));
+ *argp = last_cmdline;
+ return TRUE;
+
+ case '/': /* last search-pattern */
+ if (last_search_pat() == NULL && errmsg)
+ EMSG(_(e_noprevre));
+ *argp = last_search_pat();
+ return TRUE;
+
+ case '.': /* last inserted text */
+ *argp = get_last_insert_save();
+ *allocated = TRUE;
+ if (*argp == NULL && errmsg)
+ EMSG(_(e_noinstext));
+ return TRUE;
+
+#ifdef FEAT_SEARCHPATH
+ case Ctrl_F: /* Filename under cursor */
+ case Ctrl_P: /* Path under cursor, expand via "path" */
+ if (!errmsg)
+ return FALSE;
+ *argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP
+ | (regname == Ctrl_P ? FNAME_EXP : 0), 1L);
+ *allocated = TRUE;
+ return TRUE;
+#endif
+
+ case Ctrl_W: /* word under cursor */
+ case Ctrl_A: /* WORD (mnemonic All) under cursor */
+ if (!errmsg)
+ return FALSE;
+ cnt = find_ident_under_cursor(argp, regname == Ctrl_W
+ ? (FIND_IDENT|FIND_STRING) : FIND_STRING);
+ *argp = cnt ? vim_strnsave(*argp, cnt) : NULL;
+ *allocated = TRUE;
+ return TRUE;
+
+ case '_': /* black hole: always empty */
+ *argp = (char_u *)"";
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * paste a yank register into the command line.
+ * used by CTRL-R command in command-line mode
+ * insert_reg() can't be used here, because special characters from the
+ * register contents will be interpreted as commands.
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+cmdline_paste(regname, literally)
+ int regname;
+ int literally; /* Insert text literally instead of "as typed" */
+{
+ long i;
+ char_u *arg;
+ int allocated;
+
+ /* check for valid regname; also accept special characters for CTRL-R in
+ * the command line */
+ if (regname != Ctrl_F && regname != Ctrl_P && regname != Ctrl_W
+ && regname != Ctrl_A && !valid_yank_reg(regname, FALSE))
+ return FAIL;
+
+ /* A register containing CTRL-R can cause an endless loop. Allow using
+ * CTRL-C to break the loop. */
+ line_breakcheck();
+ if (got_int)
+ return FAIL;
+
+#ifdef FEAT_CLIPBOARD
+ regname = may_get_selection(regname);
+#endif
+
+ if (get_spec_reg(regname, &arg, &allocated, TRUE))
+ {
+ if (arg == NULL)
+ return FAIL;
+ cmdline_paste_str(arg, literally);
+ if (allocated)
+ vim_free(arg);
+ return OK;
+ }
+
+ get_yank_register(regname, FALSE);
+ if (y_current->y_array == NULL)
+ return FAIL;
+
+ for (i = 0; i < y_current->y_size; ++i)
+ {
+ cmdline_paste_str(y_current->y_array[i], literally);
+
+ /* insert ^M between lines and after last line if type is MLINE */
+ if (y_current->y_type == MLINE || i < y_current->y_size - 1)
+ cmdline_paste_str((char_u *)"\r", literally);
+
+ /* Check for CTRL-C, in case someone tries to paste a few thousand
+ * lines and gets bored. */
+ ui_breakcheck();
+ if (got_int)
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
+ * Put a string on the command line.
+ * When "literally" is TRUE, insert literally.
+ * When "literally" is FALSE, insert as typed, but don't leave the command
+ * line.
+ */
+ static void
+cmdline_paste_str(s, literally)
+ char_u *s;
+ int literally;
+{
+ int c, cv;
+
+ if (literally)
+ put_on_cmdline(s, -1, TRUE);
+ else
+ while (*s != NUL)
+ {
+ cv = *s;
+ if (cv == Ctrl_V && s[1])
+ ++s;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ c = mb_ptr2char(s);
+ s += mb_char2len(c);
+ }
+ else
+#endif
+ c = *s++;
+ if (cv == Ctrl_V || c == ESC || c == Ctrl_C || c == CAR || c == NL
+#ifdef UNIX
+ || c == intr_char
+#endif
+ || (c == Ctrl_BSL && *s == Ctrl_N))
+ stuffcharReadbuff(Ctrl_V);
+ stuffcharReadbuff(c);
+ }
+}
+
+#if defined(FEAT_CLIPBOARD) || defined(PROTO)
+/*
+ * Adjust the register name pointed to with "rp" for the clipboard being
+ * used always and the clipboard being available.
+ */
+ void
+adjust_clip_reg(rp)
+ int *rp;
+{
+ /* If no reg. specified, and "unnamed" is in 'clipboard', use '*' reg. */
+ if (*rp == 0 && clip_unnamed)
+ *rp = '*';
+ if (!clip_star.available && *rp == '*')
+ *rp = 0;
+ if (!clip_plus.available && *rp == '+')
+ *rp = 0;
+}
+#endif
+
+/*
+ * op_delete - handle a delete operation
+ *
+ * return FAIL if undo failed, OK otherwise.
+ */
+ int
+op_delete(oap)
+ oparg_T *oap;
+{
+ int n;
+ linenr_T lnum;
+ char_u *ptr;
+#ifdef FEAT_VISUAL
+ char_u *newp, *oldp;
+ struct block_def bd;
+#endif
+ linenr_T old_lcount = curbuf->b_ml.ml_line_count;
+ int did_yank = FALSE;
+
+ if (curbuf->b_ml.ml_flags & ML_EMPTY) /* nothing to do */
+ return OK;
+
+ /* Nothing to delete, return here. Do prepare undo, for op_change(). */
+ if (oap->empty)
+ return u_save_cursor();
+
+ if (!curbuf->b_p_ma)
+ {
+ EMSG(_(e_modifiable));
+ return FAIL;
+ }
+
+#ifdef FEAT_CLIPBOARD
+ adjust_clip_reg(&oap->regname);
+#endif
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ mb_adjust_opend(oap);
+#endif
+
+/*
+ * Imitate the strange Vi behaviour: If the delete spans more than one line
+ * and motion_type == MCHAR and the result is a blank line, make the delete
+ * linewise. Don't do this for the change command or Visual mode.
+ */
+ if ( oap->motion_type == MCHAR
+#ifdef FEAT_VISUAL
+ && !oap->is_VIsual
+#endif
+ && oap->line_count > 1
+ && oap->op_type == OP_DELETE)
+ {
+ ptr = ml_get(oap->end.lnum) + oap->end.col + oap->inclusive;
+ ptr = skipwhite(ptr);
+ if (*ptr == NUL && inindent(0))
+ oap->motion_type = MLINE;
+ }
+
+/*
+ * Check for trying to delete (e.g. "D") in an empty line.
+ * Note: For the change operator it is ok.
+ */
+ if ( oap->motion_type == MCHAR
+ && oap->line_count == 1
+ && oap->op_type == OP_DELETE
+ && *ml_get(oap->start.lnum) == NUL)
+ {
+ /*
+ * It's an error to operate on an empty region, when 'E' inclucded in
+ * 'cpoptions' (Vi compatible).
+ */
+ if (vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL)
+ beep_flush();
+ return OK;
+ }
+
+/*
+ * Do a yank of whatever we're about to delete.
+ * If a yank register was specified, put the deleted text into that register.
+ * For the black hole register '_' don't yank anything.
+ */
+ if (oap->regname != '_')
+ {
+ if (oap->regname != 0)
+ {
+ /* check for read-only register */
+ if (!valid_yank_reg(oap->regname, TRUE))
+ {
+ beep_flush();
+ return OK;
+ }
+ get_yank_register(oap->regname, TRUE); /* yank into specif'd reg. */
+ if (op_yank(oap, TRUE, FALSE) == OK) /* yank without message */
+ did_yank = TRUE;
+ }
+
+ /*
+ * Put deleted text into register 1 and shift number registers if the
+ * delete contains a line break, or when a regname has been specified.
+ */
+ if (oap->regname != 0 || oap->motion_type == MLINE
+ || oap->line_count > 1 || oap->use_reg_one)
+ {
+ y_current = &y_regs[9];
+ free_yank_all(); /* free register nine */
+ for (n = 9; n > 1; --n)
+ y_regs[n] = y_regs[n - 1];
+ y_previous = y_current = &y_regs[1];
+ y_regs[1].y_array = NULL; /* set register one to empty */
+ if (op_yank(oap, TRUE, FALSE) == OK)
+ did_yank = TRUE;
+ }
+
+ /* Yank into small delete register when no register specified and the
+ * delete is within one line. */
+ if (oap->regname == 0 && oap->motion_type != MLINE
+ && oap->line_count == 1)
+ {
+ oap->regname = '-';
+ get_yank_register(oap->regname, TRUE);
+ if (op_yank(oap, TRUE, FALSE) == OK)
+ did_yank = TRUE;
+ oap->regname = 0;
+ }
+
+ /*
+ * If there's too much stuff to fit in the yank register, then get a
+ * confirmation before doing the delete. This is crude, but simple.
+ * And it avoids doing a delete of something we can't put back if we
+ * want.
+ */
+ if (!did_yank)
+ {
+ int msg_silent_save = msg_silent;
+
+ msg_silent = 0; /* must display the prompt */
+ n = ask_yesno((char_u *)_("cannot yank; delete anyway"), TRUE);
+ msg_silent = msg_silent_save;
+ if (n != 'y')
+ {
+ EMSG(_(e_abort));
+ return FAIL;
+ }
+ }
+ }
+
+#ifdef FEAT_VISUAL
+/*
+ * block mode delete
+ */
+ if (oap->block_mode)
+ {
+ if (u_save((linenr_T)(oap->start.lnum - 1),
+ (linenr_T)(oap->end.lnum + 1)) == FAIL)
+ return FAIL;
+
+ for (lnum = curwin->w_cursor.lnum; lnum <= oap->end.lnum; ++lnum)
+ {
+ block_prep(oap, &bd, lnum, TRUE);
+ if (bd.textlen == 0) /* nothing to delete */
+ continue;
+
+ /* Adjust cursor position for tab replaced by spaces and 'lbr'. */
+ if (lnum == curwin->w_cursor.lnum)
+ {
+ curwin->w_cursor.col = bd.textcol + bd.startspaces;
+# ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+# endif
+ }
+
+ /* n == number of chars deleted
+ * If we delete a TAB, it may be replaced by several characters.
+ * Thus the number of characters may increase!
+ */
+ n = bd.textlen - bd.startspaces - bd.endspaces;
+ oldp = ml_get(lnum);
+ newp = alloc_check((unsigned)STRLEN(oldp) + 1 - n);
+ if (newp == NULL)
+ continue;
+ /* copy up to deleted part */
+ mch_memmove(newp, oldp, (size_t)bd.textcol);
+ /* insert spaces */
+ copy_spaces(newp + bd.textcol,
+ (size_t)(bd.startspaces + bd.endspaces));
+ /* copy the part after the deleted part */
+ oldp += bd.textcol + bd.textlen;
+ mch_memmove(newp + bd.textcol + bd.startspaces + bd.endspaces,
+ oldp, STRLEN(oldp) + 1);
+ /* replace the line */
+ ml_replace(lnum, newp, FALSE);
+ }
+
+ check_cursor_col();
+ changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col,
+ oap->end.lnum + 1, 0L);
+ oap->line_count = 0; /* no lines deleted */
+ }
+ else
+#endif
+ if (oap->motion_type == MLINE)
+ {
+ if (oap->op_type == OP_CHANGE)
+ {
+ /* Delete the lines except the first one. Temporarily move the
+ * cursor to the next line. Save the current line number, if the
+ * last line is deleted it may be changed.
+ */
+ if (oap->line_count > 1)
+ {
+ lnum = curwin->w_cursor.lnum;
+ ++curwin->w_cursor.lnum;
+ del_lines((long)(oap->line_count - 1), TRUE);
+ curwin->w_cursor.lnum = lnum;
+ }
+ if (u_save_cursor() == FAIL)
+ return FAIL;
+ if (curbuf->b_p_ai) /* don't delete indent */
+ {
+ beginline(BL_WHITE); /* cursor on first non-white */
+ did_ai = TRUE; /* delete the indent when ESC hit */
+ ai_col = curwin->w_cursor.col;
+ }
+ else
+ beginline(0); /* cursor in column 0 */
+ truncate_line(FALSE); /* delete the rest of the line */
+ /* leave cursor past last char in line */
+ if (oap->line_count > 1)
+ u_clearline(); /* "U" command not possible after "2cc" */
+ }
+ else
+ {
+ del_lines(oap->line_count, TRUE);
+ beginline(BL_WHITE | BL_FIX);
+ u_clearline(); /* "U" command not possible after "dd" */
+ }
+ }
+ else
+ {
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_op)
+ {
+ int endcol = 0;
+
+ /* For virtualedit: break the tabs that are partly included. */
+ if (gchar_pos(&oap->start) == '\t')
+ {
+ if (u_save_cursor() == FAIL) /* save first line for undo */
+ return FAIL;
+ if (oap->line_count == 1)
+ endcol = getviscol2(oap->end.col, oap->end.coladd);
+ coladvance_force(getviscol2(oap->start.col, oap->start.coladd));
+ oap->start = curwin->w_cursor;
+ if (oap->line_count == 1)
+ {
+ coladvance(endcol);
+ oap->end.col = curwin->w_cursor.col;
+ oap->end.coladd = curwin->w_cursor.coladd;
+ curwin->w_cursor = oap->start;
+ }
+ }
+
+ /* Break a tab only when it's included in the area. */
+ if (gchar_pos(&oap->end) == '\t'
+ && (int)oap->end.coladd < oap->inclusive)
+ {
+ /* save last line for undo */
+ if (u_save((linenr_T)(oap->end.lnum - 1),
+ (linenr_T)(oap->end.lnum + 1)) == FAIL)
+ return FAIL;
+ curwin->w_cursor = oap->end;
+ coladvance_force(getviscol2(oap->end.col, oap->end.coladd));
+ oap->end = curwin->w_cursor;
+ curwin->w_cursor = oap->start;
+ }
+ }
+#endif
+
+ if (oap->line_count == 1) /* delete characters within one line */
+ {
+ if (u_save_cursor() == FAIL) /* save line for undo */
+ return FAIL;
+
+ /* if 'cpoptions' contains '$', display '$' at end of change */
+ if ( vim_strchr(p_cpo, CPO_DOLLAR) != NULL
+ && oap->op_type == OP_CHANGE
+ && oap->end.lnum == curwin->w_cursor.lnum
+#ifdef FEAT_VISUAL
+ && !oap->is_VIsual
+#endif
+ )
+ display_dollar(oap->end.col - !oap->inclusive);
+
+ n = oap->end.col - oap->start.col + 1 - !oap->inclusive;
+
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_op)
+ {
+ /* fix up things for virtualedit-delete:
+ * break the tabs which are going to get in our way
+ */
+ char_u *curline = ml_get_curline();
+ int len = (int)STRLEN(curline);
+
+ if (oap->end.coladd != 0
+ && (int)oap->end.col >= len - 1
+ && !(oap->start.coladd && (int)oap->end.col >= len - 1))
+ n++;
+ /* Delete at least one char (e.g, when on a control char). */
+ if (n == 0 && oap->start.coladd != oap->end.coladd)
+ n = 1;
+
+ /* When deleted a char in the line, reset coladd. */
+ if (gchar_cursor() != NUL)
+ curwin->w_cursor.coladd = 0;
+ }
+#endif
+ (void)del_bytes((long)n, restart_edit == NUL && !virtual_op);
+ }
+ else /* delete characters between lines */
+ {
+ pos_T curpos;
+
+ /* save deleted and changed lines for undo */
+ if (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
+ (linenr_T)(curwin->w_cursor.lnum + oap->line_count)) == FAIL)
+ return FAIL;
+
+ truncate_line(TRUE); /* delete from cursor to end of line */
+
+ curpos = curwin->w_cursor; /* remember curwin->w_cursor */
+ ++curwin->w_cursor.lnum;
+ del_lines((long)(oap->line_count - 2), FALSE);
+
+ /* delete from start of line until op_end */
+ curwin->w_cursor.col = 0;
+ (void)del_bytes((long)(oap->end.col + 1 - !oap->inclusive),
+ restart_edit == NUL && !virtual_op);
+ curwin->w_cursor = curpos; /* restore curwin->w_cursor */
+
+ (void)do_join(FALSE);
+ }
+ }
+
+ msgmore(curbuf->b_ml.ml_line_count - old_lcount);
+
+#ifdef FEAT_VISUAL
+ if (oap->block_mode)
+ {
+ curbuf->b_op_end.lnum = oap->end.lnum;
+ curbuf->b_op_end.col = oap->start.col;
+ }
+ else
+#endif
+ curbuf->b_op_end = oap->start;
+ curbuf->b_op_start = oap->start;
+
+ return OK;
+}
+
+#ifdef FEAT_MBYTE
+/*
+ * Adjust end of operating area for ending on a multi-byte character.
+ * Used for deletion.
+ */
+ static void
+mb_adjust_opend(oap)
+ oparg_T *oap;
+{
+ char_u *p;
+
+ if (oap->inclusive)
+ {
+ p = ml_get(oap->end.lnum);
+ oap->end.col += mb_tail_off(p, p + oap->end.col);
+ }
+}
+#endif
+
+#if defined(FEAT_VISUALEXTRA) || defined(PROTO)
+/*
+ * Replace a whole area with one character.
+ */
+ int
+op_replace(oap, c)
+ oparg_T *oap;
+ int c;
+{
+ int n, numc;
+#ifdef FEAT_MBYTE
+ int num_chars;
+#endif
+ char_u *newp, *oldp;
+ size_t oldlen;
+ struct block_def bd;
+
+ if ((curbuf->b_ml.ml_flags & ML_EMPTY ) || oap->empty)
+ return OK; /* nothing to do */
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ mb_adjust_opend(oap);
+#endif
+
+ if (u_save((linenr_T)(oap->start.lnum - 1),
+ (linenr_T)(oap->end.lnum + 1)) == FAIL)
+ return FAIL;
+
+ /*
+ * block mode replace
+ */
+ if (oap->block_mode)
+ {
+ bd.is_MAX = (curwin->w_curswant == MAXCOL);
+ for ( ; curwin->w_cursor.lnum <= oap->end.lnum; ++curwin->w_cursor.lnum)
+ {
+ block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE);
+ if (bd.textlen == 0 && (!virtual_op || bd.is_MAX))
+ continue; /* nothing to replace */
+
+ /* n == number of extra chars required
+ * If we split a TAB, it may be replaced by several characters.
+ * Thus the number of characters may increase!
+ */
+#ifdef FEAT_VIRTUALEDIT
+ /* If the range starts in virtual space, count the initial
+ * coladd offset as part of "startspaces" */
+ if (virtual_op && bd.is_short && *bd.textstart == NUL)
+ {
+ pos_T vpos;
+
+ getvpos(&vpos, oap->start_vcol);
+ bd.startspaces += vpos.coladd;
+ n = bd.startspaces;
+ }
+ else
+#endif
+ /* allow for pre spaces */
+ n = (bd.startspaces ? bd.start_char_vcols - 1 : 0);
+
+ /* allow for post spp */
+ n += (bd.endspaces
+#ifdef FEAT_VIRTUALEDIT
+ && !bd.is_oneChar
+#endif
+ && bd.end_char_vcols > 0) ? bd.end_char_vcols - 1 : 0;
+ /* Figure out how many characters to replace. */
+ numc = oap->end_vcol - oap->start_vcol + 1;
+ if (bd.is_short && (!virtual_op || bd.is_MAX))
+ numc -= (oap->end_vcol - bd.end_vcol) + 1;
+
+#ifdef FEAT_MBYTE
+ /* A double-wide character can be replaced only up to half the
+ * times. */
+ if ((*mb_char2cells)(c) > 1)
+ {
+ if ((numc & 1) && !bd.is_short)
+ {
+ ++bd.endspaces;
+ ++n;
+ }
+ numc = numc / 2;
+ }
+
+ /* Compute bytes needed, move character count to num_chars. */
+ num_chars = numc;
+ numc *= (*mb_char2len)(c);
+#endif
+ /* oldlen includes textlen, so don't double count */
+ n += numc - bd.textlen;
+
+ oldp = ml_get_curline();
+ oldlen = STRLEN(oldp);
+ newp = alloc_check((unsigned)oldlen + 1 + n);
+ if (newp == NULL)
+ continue;
+ vim_memset(newp, NUL, (size_t)(oldlen + 1 + n));
+ /* copy up to deleted part */
+ mch_memmove(newp, oldp, (size_t)bd.textcol);
+ oldp += bd.textcol + bd.textlen;
+ /* insert pre-spaces */
+ copy_spaces(newp + bd.textcol, (size_t)bd.startspaces);
+ /* insert replacement chars CHECK FOR ALLOCATED SPACE */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ n = STRLEN(newp);
+ while (--num_chars >= 0)
+ n += (*mb_char2bytes)(c, newp + n);
+ }
+ else
+#endif
+ copy_chars(newp + STRLEN(newp), (size_t)numc, c);
+ if (!bd.is_short)
+ {
+ /* insert post-spaces */
+ copy_spaces(newp + STRLEN(newp), (size_t)bd.endspaces);
+ /* copy the part after the changed part */
+ mch_memmove(newp + STRLEN(newp), oldp, STRLEN(oldp) + 1);
+ }
+ /* replace the line */
+ ml_replace(curwin->w_cursor.lnum, newp, FALSE);
+ }
+ }
+ else
+ {
+ /*
+ * MCHAR and MLINE motion replace.
+ */
+ if (oap->motion_type == MLINE)
+ {
+ oap->start.col = 0;
+ curwin->w_cursor.col = 0;
+ oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+ if (oap->end.col)
+ --oap->end.col;
+ }
+ else if (!oap->inclusive)
+ dec(&(oap->end));
+
+ while (ltoreq(curwin->w_cursor, oap->end))
+ {
+ n = gchar_cursor();
+ if (n != NUL)
+ {
+#ifdef FEAT_MBYTE
+ if ((*mb_char2len)(c) > 1 || (*mb_char2len)(n) > 1)
+ {
+ /* This is slow, but it handles replacing a single-byte
+ * with a multi-byte and the other way around. */
+ oap->end.col += (*mb_char2len)(c) - (*mb_char2len)(n);
+ n = State;
+ State = REPLACE;
+ ins_char(c);
+ State = n;
+ /* Backup to the replaced character. */
+ dec_cursor();
+ }
+ else
+#endif
+ {
+#ifdef FEAT_VIRTUALEDIT
+ if (n == TAB)
+ {
+ int end_vcol = 0;
+
+ if (curwin->w_cursor.lnum == oap->end.lnum)
+ {
+ /* oap->end has to be recalculated when
+ * the tab breaks */
+ end_vcol = getviscol2(oap->end.col,
+ oap->end.coladd);
+ }
+ coladvance_force(getviscol());
+ if (curwin->w_cursor.lnum == oap->end.lnum)
+ getvpos(&oap->end, end_vcol);
+ }
+#endif
+ pchar(curwin->w_cursor, c);
+ }
+ }
+#ifdef FEAT_VIRTUALEDIT
+ else if (virtual_op && curwin->w_cursor.lnum == oap->end.lnum)
+ {
+ int virtcols = oap->end.coladd;
+
+ if (curwin->w_cursor.lnum == oap->start.lnum
+ && oap->start.col == oap->end.col && oap->start.coladd)
+ virtcols -= oap->start.coladd;
+
+ /* oap->end has been trimmed so it's effectively inclusive;
+ * as a result an extra +1 must be counted so we don't
+ * trample the NUL byte. */
+ coladvance_force(getviscol2(oap->end.col, oap->end.coladd) + 1);
+ curwin->w_cursor.col -= (virtcols + 1);
+ for (; virtcols >= 0; virtcols--)
+ {
+ pchar(curwin->w_cursor, c);
+ if (inc(&curwin->w_cursor) == -1)
+ break;
+ }
+ }
+#endif
+
+ /* Advance to next character, stop at the end of the file. */
+ if (inc_cursor() == -1)
+ break;
+ }
+ }
+
+ curwin->w_cursor = oap->start;
+ check_cursor();
+ changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1, 0L);
+
+ /* Set "'[" and "']" marks. */
+ curbuf->b_op_start = oap->start;
+ curbuf->b_op_end = oap->end;
+
+ return OK;
+}
+#endif
+
+/*
+ * Handle the (non-standard vi) tilde operator. Also for "gu", "gU" and "g?".
+ */
+ void
+op_tilde(oap)
+ oparg_T *oap;
+{
+ pos_T pos;
+#ifdef FEAT_VISUAL
+ struct block_def bd;
+ int done;
+#endif
+ int did_change = 0;
+#ifdef FEAT_MBYTE
+ colnr_T col;
+#endif
+
+ if (u_save((linenr_T)(oap->start.lnum - 1),
+ (linenr_T)(oap->end.lnum + 1)) == FAIL)
+ return;
+
+ pos = oap->start;
+#ifdef FEAT_VISUAL
+ if (oap->block_mode) /* Visual block mode */
+ {
+ for (; pos.lnum <= oap->end.lnum; ++pos.lnum)
+ {
+ block_prep(oap, &bd, pos.lnum, FALSE);
+ pos.col = bd.textcol;
+ for (done = 0; done < bd.textlen; ++done)
+ {
+ did_change |= swapchar(oap->op_type, &pos);
+# ifdef FEAT_MBYTE
+ col = pos.col + 1;
+# endif
+ if (inc(&pos) == -1) /* at end of file */
+ break;
+# ifdef FEAT_MBYTE
+ if (pos.col > col)
+ /* Count extra bytes of a multi-byte character. */
+ done += pos.col - col;
+# endif
+ }
+# ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans && did_change)
+ {
+ char_u *ptr = ml_get_buf(curbuf, pos.lnum, FALSE);
+
+ netbeans_inserted(curbuf, pos.lnum, bd.textcol,
+ bd.textlen, &ptr[bd.textcol], bd.textlen);
+ }
+# endif
+ }
+ if (did_change)
+ changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L);
+ }
+ else /* not block mode */
+#endif
+ {
+ if (oap->motion_type == MLINE)
+ {
+ oap->start.col = 0;
+ pos.col = 0;
+ oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+ if (oap->end.col)
+ --oap->end.col;
+ }
+ else if (!oap->inclusive)
+ dec(&(oap->end));
+
+ while (ltoreq(pos, oap->end))
+ {
+ did_change |= swapchar(oap->op_type, &pos);
+ if (inc(&pos) == -1) /* at end of file */
+ break;
+ }
+ if (did_change)
+ {
+ changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1,
+ 0L);
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans && did_change)
+ {
+ char_u *ptr;
+ int count;
+
+ pos = oap->start;
+ while (pos.lnum < oap->end.lnum)
+ {
+ ptr = ml_get_buf(curbuf, pos.lnum, FALSE);
+ count = STRLEN(ptr) - pos.col;
+ netbeans_inserted(curbuf, pos.lnum, pos.col,
+ count, &ptr[pos.col], count);
+ pos.col = 0;
+ pos.lnum++;
+ }
+ ptr = ml_get_buf(curbuf, pos.lnum, FALSE);
+ count = oap->end.col - pos.col + 1;
+ netbeans_inserted(curbuf, pos.lnum, pos.col,
+ count, &ptr[pos.col], count);
+ }
+#endif
+ }
+ }
+
+#ifdef FEAT_VISUAL
+ if (!did_change && oap->is_VIsual)
+ /* No change: need to remove the Visual selection */
+ redraw_curbuf_later(INVERTED);
+#endif
+
+ /*
+ * Set '[ and '] marks.
+ */
+ curbuf->b_op_start = oap->start;
+ curbuf->b_op_end = oap->end;
+
+ if (oap->line_count > p_report)
+ {
+ if (oap->line_count == 1)
+ MSG(_("1 line changed"));
+ else
+ smsg((char_u *)_("%ld lines changed"), oap->line_count);
+ }
+}
+
+/*
+ * If op_type == OP_UPPER: make uppercase,
+ * if op_type == OP_LOWER: make lowercase,
+ * if op_type == OP_ROT13: do rot13 encoding,
+ * else swap case of character at 'pos'
+ * returns TRUE when something actually changed.
+ */
+ int
+swapchar(op_type, pos)
+ int op_type;
+ pos_T *pos;
+{
+ int c;
+ int nc;
+
+ c = gchar_pos(pos);
+
+ /* Only do rot13 encoding for ASCII characters. */
+ if (c >= 0x80 && op_type == OP_ROT13)
+ return FALSE;
+
+#ifdef FEAT_MBYTE
+ if (enc_dbcs != 0 && c >= 0x100) /* No lower/uppercase letter */
+ return FALSE;
+#endif
+ nc = c;
+ if (MB_ISLOWER(c))
+ {
+ if (op_type == OP_ROT13)
+ nc = ROT13(c, 'a');
+ else if (op_type != OP_LOWER)
+ nc = MB_TOUPPER(c);
+ }
+ else if (MB_ISUPPER(c))
+ {
+ if (op_type == OP_ROT13)
+ nc = ROT13(c, 'A');
+ else if (op_type != OP_UPPER)
+ nc = MB_TOLOWER(c);
+ }
+ if (nc != c)
+ {
+#ifdef FEAT_MBYTE
+ if (enc_utf8 && (c >= 0x80 || nc >= 0x80))
+ {
+ pos_T sp = curwin->w_cursor;
+
+ curwin->w_cursor = *pos;
+ del_char(FALSE);
+ ins_char(nc);
+ curwin->w_cursor = sp;
+ }
+ else
+#endif
+ pchar(*pos, nc);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#if defined(FEAT_VISUALEXTRA) || defined(PROTO)
+/*
+ * op_insert - Insert and append operators for Visual mode.
+ */
+ void
+op_insert(oap, count1)
+ oparg_T *oap;
+ long count1;
+{
+ long ins_len, pre_textlen = 0;
+ char_u *firstline, *ins_text;
+ struct block_def bd;
+ int i;
+
+ /* edit() changes this - record it for OP_APPEND */
+ bd.is_MAX = (curwin->w_curswant == MAXCOL);
+
+ /* vis block is still marked. Get rid of it now. */
+ curwin->w_cursor.lnum = oap->start.lnum;
+ update_screen(INVERTED);
+
+ if (oap->block_mode)
+ {
+#ifdef FEAT_VIRTUALEDIT
+ /* When 'virtualedit' is used, need to insert the extra spaces before
+ * doing block_prep(). When only "block" is used, virtual edit is
+ * already disabled, but still need it when calling
+ * coladvance_force(). */
+ if (curwin->w_cursor.coladd > 0)
+ {
+ int old_ve_flags = ve_flags;
+
+ ve_flags = VE_ALL;
+ if (u_save_cursor() == FAIL)
+ return;
+ coladvance_force(oap->op_type == OP_APPEND
+ ? oap->end_vcol + 1 : getviscol());
+ if (oap->op_type == OP_APPEND)
+ --curwin->w_cursor.col;
+ ve_flags = old_ve_flags;
+ }
+#endif
+ /* Get the info about the block before entering the text */
+ block_prep(oap, &bd, oap->start.lnum, TRUE);
+ firstline = ml_get(oap->start.lnum) + bd.textcol;
+ if (oap->op_type == OP_APPEND)
+ firstline += bd.textlen;
+ pre_textlen = (long)STRLEN(firstline);
+ }
+
+ if (oap->op_type == OP_APPEND)
+ {
+ if (oap->block_mode
+#ifdef FEAT_VIRTUALEDIT
+ && curwin->w_cursor.coladd == 0
+#endif
+ )
+ {
+ /* Move the cursor to the character right of the block. */
+ curwin->w_set_curswant = TRUE;
+ while (*ml_get_cursor() != NUL
+ && (curwin->w_cursor.col < bd.textcol + bd.textlen))
+ ++curwin->w_cursor.col;
+ if (bd.is_short && !bd.is_MAX)
+ {
+ /* First line was too short, make it longer and adjust the
+ * values in "bd". */
+ if (u_save_cursor() == FAIL)
+ return;
+ for (i = 0; i < bd.endspaces; ++i)
+ ins_char(' ');
+ bd.textlen += bd.endspaces;
+ }
+ }
+ else
+ {
+ curwin->w_cursor = oap->end;
+
+ /* Works just like an 'i'nsert on the next character. */
+ if (!lineempty(curwin->w_cursor.lnum)
+ && oap->start_vcol != oap->end_vcol)
+ inc_cursor();
+ }
+ }
+
+ edit(NUL, FALSE, (linenr_T)count1);
+
+ /* if user has moved off this line, we don't know what to do, so do
+ * nothing */
+ if (curwin->w_cursor.lnum != oap->start.lnum)
+ return;
+
+ if (oap->block_mode)
+ {
+ struct block_def bd2;
+
+ /*
+ * Spaces and tabs in the indent may have changed to other spaces and
+ * tabs. Get the starting column again and correct the lenght.
+ * Don't do this when "$" used, end-of-line will have changed.
+ */
+ block_prep(oap, &bd2, oap->start.lnum, TRUE);
+ if (!bd.is_MAX || bd2.textlen < bd.textlen)
+ {
+ if (oap->op_type == OP_APPEND)
+ {
+ pre_textlen += bd2.textlen - bd.textlen;
+ if (bd2.endspaces)
+ --bd2.textlen;
+ }
+ bd.textcol = bd2.textcol;
+ bd.textlen = bd2.textlen;
+ }
+
+ /*
+ * Subsequent calls to ml_get() flush the firstline data - take a
+ * copy of the required string.
+ */
+ firstline = ml_get(oap->start.lnum) + bd.textcol;
+ if (oap->op_type == OP_APPEND)
+ firstline += bd.textlen;
+ if ((ins_len = (long)STRLEN(firstline) - pre_textlen) > 0)
+ {
+ ins_text = vim_strnsave(firstline, (int)ins_len);
+ if (ins_text != NULL)
+ {
+ /* block handled here */
+ if (u_save(oap->start.lnum,
+ (linenr_T)(oap->end.lnum + 1)) == OK)
+ block_insert(oap, ins_text, (oap->op_type == OP_INSERT),
+ &bd);
+
+ curwin->w_cursor.col = oap->start.col;
+ check_cursor();
+ vim_free(ins_text);
+ }
+ }
+ }
+}
+#endif
+
+/*
+ * op_change - handle a change operation
+ *
+ * return TRUE if edit() returns because of a CTRL-O command
+ */
+ int
+op_change(oap)
+ oparg_T *oap;
+{
+ colnr_T l;
+ int retval;
+#ifdef FEAT_VISUALEXTRA
+ long offset;
+ linenr_T linenr;
+ long ins_len, pre_textlen = 0;
+ char_u *firstline;
+ char_u *ins_text, *newp, *oldp;
+ struct block_def bd;
+#endif
+
+ l = oap->start.col;
+ if (oap->motion_type == MLINE)
+ {
+ l = 0;
+#ifdef FEAT_SMARTINDENT
+ if (!p_paste && curbuf->b_p_si
+# ifdef FEAT_CINDENT
+ && !curbuf->b_p_cin
+# endif
+ )
+ can_si = TRUE; /* It's like opening a new line, do si */
+#endif
+ }
+
+ /* First delete the text in the region. In an empty buffer only need to
+ * save for undo */
+ if (curbuf->b_ml.ml_flags & ML_EMPTY)
+ {
+ if (u_save_cursor() == FAIL)
+ return FALSE;
+ }
+ else if (op_delete(oap) == FAIL)
+ return FALSE;
+
+ if ((l > curwin->w_cursor.col) && !lineempty(curwin->w_cursor.lnum)
+ && !virtual_op)
+ inc_cursor();
+
+#ifdef FEAT_VISUALEXTRA
+ /* check for still on same line (<CR> in inserted text meaningless) */
+ /* skip blank lines too */
+ if (oap->block_mode)
+ {
+# ifdef FEAT_VIRTUALEDIT
+ /* Add spaces before getting the current line length. */
+ if (virtual_op && (curwin->w_cursor.coladd > 0
+ || gchar_cursor() == NUL))
+ coladvance_force(getviscol());
+# endif
+ pre_textlen = (long)STRLEN(ml_get(oap->start.lnum));
+ bd.textcol = curwin->w_cursor.col;
+ }
+#endif
+
+#if defined(FEAT_LISP) || defined(FEAT_CINDENT)
+ if (oap->motion_type == MLINE)
+ fix_indent();
+#endif
+
+ retval = edit(NUL, FALSE, (linenr_T)1);
+
+#ifdef FEAT_VISUALEXTRA
+ /*
+ * In Visual block mode, handle copying the next text to all lines of the
+ * block.
+ */
+ if (oap->block_mode && oap->start.lnum != oap->end.lnum)
+ {
+ firstline = ml_get(oap->start.lnum);
+ /*
+ * Subsequent calls to ml_get() flush the firstline data - take a
+ * copy of the required bit.
+ */
+ if ((ins_len = (long)STRLEN(firstline) - pre_textlen) > 0)
+ {
+ if ((ins_text = alloc_check((unsigned)(ins_len + 1))) != NULL)
+ {
+ STRNCPY(ins_text, firstline + bd.textcol, ins_len);
+ ins_text[ins_len] = NUL;
+ for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum;
+ linenr++)
+ {
+ block_prep(oap, &bd, linenr, TRUE);
+ if (!bd.is_short || virtual_op)
+ {
+# ifdef FEAT_VIRTUALEDIT
+ pos_T vpos;
+
+ /* If the block starts in virtual space, count the
+ * initial coladd offset as part of "startspaces" */
+ if (bd.is_short)
+ {
+ linenr_T lnum = curwin->w_cursor.lnum;
+
+ curwin->w_cursor.lnum = linenr;
+ (void)getvpos(&vpos, oap->start_vcol);
+ curwin->w_cursor.lnum = lnum;
+ }
+ else
+ vpos.coladd = 0;
+# endif
+ oldp = ml_get(linenr);
+ newp = alloc_check((unsigned)(STRLEN(oldp)
+# ifdef FEAT_VIRTUALEDIT
+ + vpos.coladd
+# endif
+ + ins_len + 1));
+ if (newp == NULL)
+ continue;
+ /* copy up to block start */
+ mch_memmove(newp, oldp, (size_t)bd.textcol);
+ offset = bd.textcol;
+# ifdef FEAT_VIRTUALEDIT
+ copy_spaces(newp + offset, (size_t)vpos.coladd);
+ offset += vpos.coladd;
+# endif
+ mch_memmove(newp + offset, ins_text, (size_t)ins_len);
+ offset += ins_len;
+ oldp += bd.textcol;
+ mch_memmove(newp + offset, oldp, STRLEN(oldp) + 1);
+ ml_replace(linenr, newp, FALSE);
+ }
+ }
+ check_cursor();
+
+ changed_lines(oap->start.lnum + 1, 0, oap->end.lnum + 1, 0L);
+ }
+ vim_free(ins_text);
+ }
+ }
+#endif
+
+ return retval;
+}
+
+/*
+ * set all the yank registers to empty (called from main())
+ */
+ void
+init_yank()
+{
+ int i;
+
+ for (i = 0; i < NUM_REGISTERS; ++i)
+ y_regs[i].y_array = NULL;
+}
+
+/*
+ * Free "n" lines from the current yank register.
+ * Called for normal freeing and in case of error.
+ */
+ static void
+free_yank(n)
+ long n;
+{
+ if (y_current->y_array != NULL)
+ {
+ long i;
+
+ for (i = n; --i >= 0; )
+ {
+#ifdef AMIGA /* only for very slow machines */
+ if ((i & 1023) == 1023) /* this may take a while */
+ {
+ /*
+ * This message should never cause a hit-return message.
+ * Overwrite this message with any next message.
+ */
+ ++no_wait_return;
+ smsg((char_u *)_("freeing %ld lines"), i + 1);
+ --no_wait_return;
+ msg_didout = FALSE;
+ msg_col = 0;
+ }
+#endif
+ vim_free(y_current->y_array[i]);
+ }
+ vim_free(y_current->y_array);
+ y_current->y_array = NULL;
+#ifdef AMIGA
+ if (n >= 1000)
+ MSG("");
+#endif
+ }
+}
+
+ static void
+free_yank_all()
+{
+ free_yank(y_current->y_size);
+}
+
+/*
+ * Yank the text between "oap->start" and "oap->end" into a yank register.
+ * If we are to append (uppercase register), we first yank into a new yank
+ * register and then concatenate the old and the new one (so we keep the old
+ * one in case of out-of-memory).
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+op_yank(oap, deleting, mess)
+ oparg_T *oap;
+ int deleting;
+ int mess;
+{
+ long y_idx; /* index in y_array[] */
+ struct yankreg *curr; /* copy of y_current */
+ struct yankreg newreg; /* new yank register when appending */
+ char_u **new_ptr;
+ linenr_T lnum; /* current line number */
+ long j;
+ int yanktype = oap->motion_type;
+ long yanklines = oap->line_count;
+ linenr_T yankendlnum = oap->end.lnum;
+ char_u *p;
+ char_u *pnew;
+ struct block_def bd;
+
+ /* check for read-only register */
+ if (oap->regname != 0 && !valid_yank_reg(oap->regname, TRUE))
+ {
+ beep_flush();
+ return FAIL;
+ }
+ if (oap->regname == '_') /* black hole: nothing to do */
+ return OK;
+
+#ifdef FEAT_CLIPBOARD
+ if (!clip_star.available && oap->regname == '*')
+ oap->regname = 0;
+ else if (!clip_plus.available && oap->regname == '+')
+ oap->regname = 0;
+#endif
+
+ if (!deleting) /* op_delete() already set y_current */
+ get_yank_register(oap->regname, TRUE);
+
+ curr = y_current;
+ /* append to existing contents */
+ if (y_append && y_current->y_array != NULL)
+ y_current = &newreg;
+ else
+ free_yank_all(); /* free previously yanked lines */
+
+/*
+ * If the cursor was in column 1 before and after the movement, and the
+ * operator is not inclusive, the yank is always linewise.
+ */
+ if ( oap->motion_type == MCHAR
+ && oap->start.col == 0
+ && !oap->inclusive
+#ifdef FEAT_VISUAL
+ && (!oap->is_VIsual || *p_sel == 'o')
+#endif
+ && oap->end.col == 0
+ && yanklines > 1)
+ {
+ yanktype = MLINE;
+ --yankendlnum;
+ --yanklines;
+ }
+
+ y_current->y_size = yanklines;
+ y_current->y_type = yanktype; /* set the yank register type */
+#ifdef FEAT_VISUAL
+ y_current->y_width = 0;
+#endif
+ y_current->y_array = (char_u **)lalloc_clear((long_u)(sizeof(char_u *) *
+ yanklines), TRUE);
+
+ if (y_current->y_array == NULL)
+ {
+ y_current = curr;
+ return FAIL;
+ }
+
+ y_idx = 0;
+ lnum = oap->start.lnum;
+
+#ifdef FEAT_VISUAL
+ if (oap->block_mode)
+ {
+ /* Visual block mode */
+ y_current->y_type = MBLOCK; /* set the yank register type */
+ y_current->y_width = oap->end_vcol - oap->start_vcol;
+
+ if (curwin->w_curswant == MAXCOL && y_current->y_width > 0)
+ y_current->y_width--;
+ }
+#endif
+
+ for ( ; lnum <= yankendlnum; lnum++, y_idx++)
+ {
+ switch (y_current->y_type)
+ {
+#ifdef FEAT_VISUAL
+ case MBLOCK:
+ block_prep(oap, &bd, lnum, FALSE);
+ if (yank_copy_line(&bd, y_idx) == FAIL)
+ goto fail;
+ break;
+#endif
+
+ case MLINE:
+ if ((y_current->y_array[y_idx] =
+ vim_strsave(ml_get(lnum))) == NULL)
+ goto fail;
+ break;
+
+ case MCHAR:
+ {
+ colnr_T startcol = 0, endcol = MAXCOL;
+#ifdef FEAT_VIRTUALEDIT
+ int is_oneChar = FALSE;
+ colnr_T cs, ce;
+#endif
+ p = ml_get(lnum);
+ bd.startspaces = 0;
+ bd.endspaces = 0;
+
+ if (lnum == oap->start.lnum)
+ {
+ startcol = oap->start.col;
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_op)
+ {
+ getvcol(curwin, &oap->start, &cs, NULL, &ce);
+ if (ce != cs && oap->start.coladd > 0)
+ {
+ /* Part of a tab selected -- but don't
+ * double-count it. */
+ bd.startspaces = (ce - cs + 1)
+ - oap->start.coladd;
+ startcol++;
+ }
+ }
+#endif
+ }
+
+ if (lnum == oap->end.lnum)
+ {
+ endcol = oap->end.col;
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_op)
+ {
+ getvcol(curwin, &oap->end, &cs, NULL, &ce);
+ if (p[endcol] == NUL || (cs + oap->end.coladd < ce
+# ifdef FEAT_MBYTE
+ /* Don't add space for double-wide
+ * char; endcol will be on last byte
+ * of multi-byte char. */
+ && (*mb_head_off)(p, p + endcol) == 0
+# endif
+ ))
+ {
+ if (oap->start.lnum == oap->end.lnum
+ && oap->start.col == oap->end.col)
+ {
+ /* Special case: inside a single char */
+ is_oneChar = TRUE;
+ bd.startspaces = oap->end.coladd
+ - oap->start.coladd + oap->inclusive;
+ endcol = startcol;
+ }
+ else
+ {
+ bd.endspaces = oap->end.coladd
+ + oap->inclusive;
+ endcol -= oap->inclusive;
+ }
+ }
+ }
+#endif
+ }
+ if (startcol > endcol
+#ifdef FEAT_VIRTUALEDIT
+ || is_oneChar
+#endif
+ )
+ bd.textlen = 0;
+ else
+ {
+ if (endcol == MAXCOL)
+ endcol = STRLEN(p);
+ bd.textlen = endcol - startcol + oap->inclusive;
+ }
+ bd.textstart = p + startcol;
+ if (yank_copy_line(&bd, y_idx) == FAIL)
+ goto fail;
+ break;
+ }
+ /* NOTREACHED */
+ }
+ }
+
+ if (curr != y_current) /* append the new block to the old block */
+ {
+ new_ptr = (char_u **)lalloc((long_u)(sizeof(char_u *) *
+ (curr->y_size + y_current->y_size)), TRUE);
+ if (new_ptr == NULL)
+ goto fail;
+ for (j = 0; j < curr->y_size; ++j)
+ new_ptr[j] = curr->y_array[j];
+ vim_free(curr->y_array);
+ curr->y_array = new_ptr;
+
+ if (yanktype == MLINE) /* MLINE overrides MCHAR and MBLOCK */
+ curr->y_type = MLINE;
+
+ /* concatenate the last line of the old block with the first line of
+ * the new block */
+ if (curr->y_type == MCHAR)
+ {
+ pnew = lalloc((long_u)(STRLEN(curr->y_array[curr->y_size - 1])
+ + STRLEN(y_current->y_array[0]) + 1), TRUE);
+ if (pnew == NULL)
+ {
+ y_idx = y_current->y_size - 1;
+ goto fail;
+ }
+ STRCPY(pnew, curr->y_array[--j]);
+ STRCAT(pnew, y_current->y_array[0]);
+ vim_free(curr->y_array[j]);
+ vim_free(y_current->y_array[0]);
+ curr->y_array[j++] = pnew;
+ y_idx = 1;
+ }
+ else
+ y_idx = 0;
+ while (y_idx < y_current->y_size)
+ curr->y_array[j++] = y_current->y_array[y_idx++];
+ curr->y_size = j;
+ vim_free(y_current->y_array);
+ y_current = curr;
+ }
+ if (mess) /* Display message about yank? */
+ {
+ if (yanktype == MCHAR
+#ifdef FEAT_VISUAL
+ && !oap->block_mode
+#endif
+ && yanklines == 1)
+ yanklines = 0;
+ /* Some versions of Vi use ">=" here, some don't... */
+ if (yanklines > p_report)
+ {
+ /* redisplay now, so message is not deleted */
+ update_topline_redraw();
+ if (yanklines == 1)
+ MSG(_("1 line yanked"));
+ else
+ smsg((char_u *)_("%ld lines yanked"), yanklines);
+ }
+ }
+
+ /*
+ * Set "'[" and "']" marks.
+ */
+ curbuf->b_op_start = oap->start;
+ curbuf->b_op_end = oap->end;
+
+#ifdef FEAT_CLIPBOARD
+ /*
+ * If we were yanking to the '*' register, send result to clipboard.
+ * If no register was specified, and "unnamed" in 'clipboard', make a copy
+ * to the '*' register.
+ */
+ if (clip_star.available
+ && (curr == &(y_regs[STAR_REGISTER])
+ || (!deleting && oap->regname == 0 && clip_unnamed)))
+ {
+ if (curr != &(y_regs[STAR_REGISTER]))
+ /* Copy the text from register 0 to the clipboard register. */
+ copy_yank_reg(&(y_regs[STAR_REGISTER]));
+
+ clip_own_selection(&clip_star);
+ clip_gen_set_selection(&clip_star);
+ }
+
+# ifdef FEAT_X11
+ /*
+ * If we were yanking to the '+' register, send result to selection.
+ * Also copy to the '*' register, in case auto-select is off.
+ */
+ else if (clip_plus.available && curr == &(y_regs[PLUS_REGISTER]))
+ {
+ /* No need to copy to * register upon 'unnamed' now - see below */
+ clip_own_selection(&clip_plus);
+ clip_gen_set_selection(&clip_plus);
+ if (!clip_isautosel())
+ {
+ copy_yank_reg(&(y_regs[STAR_REGISTER]));
+ clip_own_selection(&clip_star);
+ clip_gen_set_selection(&clip_star);
+ }
+ }
+# endif
+#endif
+
+ return OK;
+
+fail: /* free the allocated lines */
+ free_yank(y_idx + 1);
+ y_current = curr;
+ return FAIL;
+}
+
+ static int
+yank_copy_line(bd, y_idx)
+ struct block_def *bd;
+ long y_idx;
+{
+ char_u *pnew;
+
+ if ((pnew = alloc(bd->startspaces + bd->endspaces + bd->textlen + 1))
+ == NULL)
+ return FAIL;
+ y_current->y_array[y_idx] = pnew;
+ copy_spaces(pnew, (size_t)bd->startspaces);
+ pnew += bd->startspaces;
+ mch_memmove(pnew, bd->textstart, (size_t)bd->textlen);
+ pnew += bd->textlen;
+ copy_spaces(pnew, (size_t)bd->endspaces);
+ pnew += bd->endspaces;
+ *pnew = NUL;
+ return OK;
+}
+
+#ifdef FEAT_CLIPBOARD
+/*
+ * Make a copy of the y_current register to register "reg".
+ */
+ static void
+copy_yank_reg(reg)
+ struct yankreg *reg;
+{
+ struct yankreg *curr = y_current;
+ long j;
+
+ y_current = reg;
+ free_yank_all();
+ *y_current = *curr;
+ y_current->y_array = (char_u **)lalloc_clear(
+ (long_u)(sizeof(char_u *) * y_current->y_size), TRUE);
+ if (y_current->y_array == NULL)
+ y_current->y_size = 0;
+ else
+ for (j = 0; j < y_current->y_size; ++j)
+ if ((y_current->y_array[j] = vim_strsave(curr->y_array[j])) == NULL)
+ {
+ free_yank(j);
+ y_current->y_size = 0;
+ break;
+ }
+ y_current = curr;
+}
+#endif
+
+/*
+ * put contents of register "regname" into the text
+ * flags: PUT_FIXINDENT make indent look nice
+ * PUT_CURSEND leave cursor after end of new text
+ * PUT_LINE force linewise put (":put")
+ */
+ void
+do_put(regname, dir, count, flags)
+ int regname;
+ int dir; /* BACKWARD for 'P', FORWARD for 'p' */
+ long count;
+ int flags;
+{
+ char_u *ptr;
+ char_u *newp, *oldp;
+ int yanklen;
+ int totlen = 0; /* init for gcc */
+ linenr_T lnum;
+ colnr_T col;
+ long i; /* index in y_array[] */
+ int y_type;
+ long y_size;
+#ifdef FEAT_VISUAL
+ int oldlen;
+ long y_width = 0;
+ colnr_T vcol;
+ int delcount;
+ int incr = 0;
+ long j;
+ struct block_def bd;
+#endif
+ char_u **y_array = NULL;
+ long nr_lines = 0;
+ pos_T new_cursor;
+ int indent;
+ int orig_indent = 0; /* init for gcc */
+ int indent_diff = 0; /* init for gcc */
+ int first_indent = TRUE;
+ int lendiff = 0;
+ pos_T old_pos;
+ char_u *insert_string = NULL;
+ int allocated = FALSE;
+ long cnt;
+
+#ifdef FEAT_CLIPBOARD
+ /* Adjust register name for "unnamed" in 'clipboard'. */
+ adjust_clip_reg(&regname);
+ (void)may_get_selection(regname);
+#endif
+
+ if (flags & PUT_FIXINDENT)
+ orig_indent = get_indent();
+
+ curbuf->b_op_start = curwin->w_cursor; /* default for '[ mark */
+ curbuf->b_op_end = curwin->w_cursor; /* default for '] mark */
+
+ /*
+ * Using inserted text works differently, because the register includes
+ * special characters (newlines, etc.).
+ */
+ if (regname == '.')
+ {
+ (void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') :
+ (count == -1 ? 'O' : 'i')), count, FALSE);
+ /* Putting the text is done later, so can't really move the cursor to
+ * the next character. Use "l" to simulate it. */
+ if ((flags & PUT_CURSEND) && gchar_cursor() != NUL)
+ stuffcharReadbuff('l');
+ return;
+ }
+
+ /*
+ * For special registers '%' (file name), '#' (alternate file name) and
+ * ':' (last command line), etc. we have to create a fake yank register.
+ */
+ if (get_spec_reg(regname, &insert_string, &allocated, TRUE))
+ {
+ if (insert_string == NULL)
+ return;
+ }
+
+ if (insert_string != NULL)
+ {
+ y_type = MCHAR;
+#ifdef FEAT_EVAL
+ if (regname == '=')
+ {
+ /* For the = register we need to split the string at NL
+ * characters. */
+ /* Loop twice: count the number of lines and save them. */
+ for (;;)
+ {
+ y_size = 0;
+ ptr = insert_string;
+ while (ptr != NULL)
+ {
+ if (y_array != NULL)
+ y_array[y_size] = ptr;
+ ++y_size;
+ ptr = vim_strchr(ptr, '\n');
+ if (ptr != NULL)
+ {
+ if (y_array != NULL)
+ *ptr = NUL;
+ ++ptr;
+ /* A trailing '\n' makes the string linewise */
+ if (*ptr == NUL)
+ {
+ y_type = MLINE;
+ break;
+ }
+ }
+ }
+ if (y_array != NULL)
+ break;
+ y_array = (char_u **)alloc((unsigned)
+ (y_size * sizeof(char_u *)));
+ if (y_array == NULL)
+ goto end;
+ }
+ }
+ else
+#endif
+ {
+ y_size = 1; /* use fake one-line yank register */
+ y_array = &insert_string;
+ }
+ }
+ else
+ {
+ get_yank_register(regname, FALSE);
+
+ y_type = y_current->y_type;
+#ifdef FEAT_VISUAL
+ y_width = y_current->y_width;
+#endif
+ y_size = y_current->y_size;
+ y_array = y_current->y_array;
+ }
+
+#ifdef FEAT_VISUAL
+ if (y_type == MLINE)
+ {
+ if (flags & PUT_LINE_SPLIT)
+ {
+ /* "p" or "P" in Visual mode: split the lines to put the text in
+ * between. */
+ if (u_save_cursor() == FAIL)
+ goto end;
+ ptr = vim_strsave(ml_get_cursor());
+ if (ptr == NULL)
+ goto end;
+ ml_append(curwin->w_cursor.lnum, ptr, (colnr_T)0, FALSE);
+ vim_free(ptr);
+
+ ptr = vim_strnsave(ml_get_curline(), curwin->w_cursor.col);
+ if (ptr == NULL)
+ goto end;
+ ml_replace(curwin->w_cursor.lnum, ptr, FALSE);
+ ++nr_lines;
+ dir = FORWARD;
+ }
+ if (flags & PUT_LINE_FORWARD)
+ {
+ /* Must be "p" for a Visual block, put lines below the block. */
+ curwin->w_cursor = curbuf->b_visual_end;
+ dir = FORWARD;
+ }
+ curbuf->b_op_start = curwin->w_cursor; /* default for '[ mark */
+ curbuf->b_op_end = curwin->w_cursor; /* default for '] mark */
+ }
+#endif
+
+ if (flags & PUT_LINE) /* :put command or "p" in Visual line mode. */
+ y_type = MLINE;
+
+ if (y_size == 0 || y_array == NULL)
+ {
+ EMSG2(_("E353: Nothing in register %s"),
+ regname == 0 ? (char_u *)"\"" : transchar(regname));
+ goto end;
+ }
+
+#ifdef FEAT_VISUAL
+ if (y_type == MBLOCK)
+ {
+ lnum = curwin->w_cursor.lnum + y_size + 1;
+ if (lnum > curbuf->b_ml.ml_line_count)
+ lnum = curbuf->b_ml.ml_line_count + 1;
+ if (u_save(curwin->w_cursor.lnum - 1, lnum) == FAIL)
+ goto end;
+ }
+ else
+#endif
+ if (y_type == MLINE)
+ {
+ lnum = curwin->w_cursor.lnum;
+#ifdef FEAT_FOLDING
+ /* Correct line number for closed fold. Don't move the cursor yet,
+ * u_save() uses it. */
+ if (dir == BACKWARD)
+ (void)hasFolding(lnum, &lnum, NULL);
+ else
+ (void)hasFolding(lnum, NULL, &lnum);
+#endif
+ if (dir == FORWARD)
+ ++lnum;
+ if (u_save(lnum - 1, lnum) == FAIL)
+ goto end;
+#ifdef FEAT_FOLDING
+ if (dir == FORWARD)
+ curwin->w_cursor.lnum = lnum - 1;
+ else
+ curwin->w_cursor.lnum = lnum;
+ curbuf->b_op_start = curwin->w_cursor; /* for mark_adjust() */
+#endif
+ }
+ else if (u_save_cursor() == FAIL)
+ goto end;
+
+ yanklen = (int)STRLEN(y_array[0]);
+
+#ifdef FEAT_VIRTUALEDIT
+ if (ve_flags == VE_ALL && y_type == MCHAR)
+ {
+ if (gchar_cursor() == TAB)
+ {
+ /* Don't need to insert spaces when "p" on the last position of a
+ * tab or "P" on the first position. */
+ if (dir == FORWARD
+ ? (int)curwin->w_cursor.coladd < curbuf->b_p_ts - 1
+ : curwin->w_cursor.coladd > 0)
+ coladvance_force(getviscol());
+ else
+ curwin->w_cursor.coladd = 0;
+ }
+ else if (curwin->w_cursor.coladd > 0 || gchar_cursor() == NUL)
+ coladvance_force(getviscol() + (dir == FORWARD));
+ }
+#endif
+
+ lnum = curwin->w_cursor.lnum;
+ col = curwin->w_cursor.col;
+
+#ifdef FEAT_VISUAL
+ /*
+ * Block mode
+ */
+ if (y_type == MBLOCK)
+ {
+ char c = gchar_cursor();
+ colnr_T endcol2 = 0;
+
+ if (dir == FORWARD && c != NUL)
+ {
+#ifdef FEAT_VIRTUALEDIT
+ if (ve_flags == VE_ALL)
+ getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
+ else
+#endif
+ getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ /* move to start of next multi-byte character */
+ curwin->w_cursor.col += (*mb_ptr2len_check)(ml_get_cursor());
+ else
+#endif
+#ifdef FEAT_VIRTUALEDIT
+ if (c != TAB || ve_flags != VE_ALL)
+#endif
+ ++curwin->w_cursor.col;
+ ++col;
+ }
+ else
+ getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
+
+#ifdef FEAT_VIRTUALEDIT
+ col += curwin->w_cursor.coladd;
+ if (ve_flags == VE_ALL && curwin->w_cursor.coladd > 0)
+ {
+ if (dir == FORWARD && c == NUL)
+ ++col;
+ if (dir != FORWARD && c != NUL)
+ ++curwin->w_cursor.col;
+ if (c == TAB)
+ {
+ if (dir == BACKWARD && curwin->w_cursor.col)
+ curwin->w_cursor.col--;
+ if (dir == FORWARD && col - 1 == endcol2)
+ curwin->w_cursor.col++;
+ }
+ }
+ curwin->w_cursor.coladd = 0;
+#endif
+ for (i = 0; i < y_size; ++i)
+ {
+ int spaces;
+ char shortline;
+
+ bd.startspaces = 0;
+ bd.endspaces = 0;
+ bd.textcol = 0;
+ vcol = 0;
+ delcount = 0;
+
+ /* add a new line */
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
+ {
+ if (ml_append(curbuf->b_ml.ml_line_count, (char_u *)"",
+ (colnr_T)1, FALSE) == FAIL)
+ break;
+ ++nr_lines;
+ }
+ /* get the old line and advance to the position to insert at */
+ oldp = ml_get_curline();
+ oldlen = (int)STRLEN(oldp);
+ for (ptr = oldp; vcol < col && *ptr; )
+ {
+ /* Count a tab for what it's worth (if list mode not on) */
+ incr = lbr_chartabsize_adv(&ptr, (colnr_T)vcol);
+ vcol += incr;
+ }
+ bd.textcol = (colnr_T)(ptr - oldp);
+
+ shortline = (vcol < col) || (vcol == col && !*ptr) ;
+
+ if (vcol < col) /* line too short, padd with spaces */
+ bd.startspaces = col - vcol;
+ else if (vcol > col)
+ {
+ bd.endspaces = vcol - col;
+ bd.startspaces = incr - bd.endspaces;
+ --bd.textcol;
+ delcount = 1;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ bd.textcol -= (*mb_head_off)(oldp, oldp + bd.textcol);
+#endif
+ if (oldp[bd.textcol] != TAB)
+ {
+ /* Only a Tab can be split into spaces. Other
+ * characters will have to be moved to after the
+ * block, causing misalignment. */
+ delcount = 0;
+ bd.endspaces = 0;
+ }
+ }
+
+ yanklen = (int)STRLEN(y_array[i]);
+
+ /* calculate number of spaces required to fill right side of block*/
+ spaces = y_width + 1;
+ for (j = 0; j < yanklen; j++)
+ spaces -= lbr_chartabsize(&y_array[i][j], 0);
+ if (spaces < 0)
+ spaces = 0;
+
+ /* insert the new text */
+ totlen = count * (yanklen + spaces) + bd.startspaces + bd.endspaces;
+ newp = alloc_check((unsigned)totlen + oldlen + 1);
+ if (newp == NULL)
+ break;
+ /* copy part up to cursor to new line */
+ ptr = newp;
+ mch_memmove(ptr, oldp, (size_t)bd.textcol);
+ ptr += bd.textcol;
+ /* may insert some spaces before the new text */
+ copy_spaces(ptr, (size_t)bd.startspaces);
+ ptr += bd.startspaces;
+ /* insert the new text */
+ for (j = 0; j < count; ++j)
+ {
+ mch_memmove(ptr, y_array[i], (size_t)yanklen);
+ ptr += yanklen;
+
+ /* insert block's trailing spaces only if there's text behind */
+ if ((j < count - 1 || !shortline) && spaces)
+ {
+ copy_spaces(ptr, (size_t)spaces);
+ ptr += spaces;
+ }
+ }
+ /* may insert some spaces after the new text */
+ copy_spaces(ptr, (size_t)bd.endspaces);
+ ptr += bd.endspaces;
+ /* move the text after the cursor to the end of the line. */
+ mch_memmove(ptr, oldp + bd.textcol + delcount,
+ (size_t)(oldlen - bd.textcol - delcount + 1));
+ ml_replace(curwin->w_cursor.lnum, newp, FALSE);
+
+ ++curwin->w_cursor.lnum;
+ if (i == 0)
+ curwin->w_cursor.col += bd.startspaces;
+ }
+
+ changed_lines(lnum, 0, curwin->w_cursor.lnum, nr_lines);
+
+ /* Set '[ mark. */
+ curbuf->b_op_start = curwin->w_cursor;
+ curbuf->b_op_start.lnum = lnum;
+
+ /* adjust '] mark */
+ curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1;
+ curbuf->b_op_end.col = bd.textcol + totlen - 1;
+#ifdef FEAT_VIRTUALEDIT
+ curbuf->b_op_end.coladd = 0;
+#endif
+ if (flags & PUT_CURSEND)
+ {
+ curwin->w_cursor = curbuf->b_op_end;
+ curwin->w_cursor.col++;
+ }
+ else
+ curwin->w_cursor.lnum = lnum;
+ }
+ else
+#endif
+ {
+ /*
+ * Character or Line mode
+ */
+ if (y_type == MCHAR)
+ {
+ /* if type is MCHAR, FORWARD is the same as BACKWARD on the next
+ * char */
+ if (dir == FORWARD && gchar_cursor() != NUL)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int bytelen = (*mb_ptr2len_check)(ml_get_cursor());
+
+ /* put it on the next of the multi-byte character. */
+ col += bytelen;
+ if (yanklen)
+ {
+ curwin->w_cursor.col += bytelen;
+ curbuf->b_op_end.col += bytelen;
+ }
+ }
+ else
+#endif
+ {
+ ++col;
+ if (yanklen)
+ {
+ ++curwin->w_cursor.col;
+ ++curbuf->b_op_end.col;
+ }
+ }
+ }
+ new_cursor = curwin->w_cursor;
+ curbuf->b_op_start = curwin->w_cursor;
+ }
+ /*
+ * Line mode: BACKWARD is the same as FORWARD on the previous line
+ */
+ else if (dir == BACKWARD)
+ --lnum;
+
+ /*
+ * simple case: insert into current line
+ */
+ if (y_type == MCHAR && y_size == 1)
+ {
+ totlen = count * yanklen;
+ if (totlen)
+ {
+ oldp = ml_get(lnum);
+ newp = alloc_check((unsigned)(STRLEN(oldp) + totlen + 1));
+ if (newp == NULL)
+ goto end; /* alloc() will give error message */
+ mch_memmove(newp, oldp, (size_t)col);
+ ptr = newp + col;
+ for (i = 0; i < count; ++i)
+ {
+ mch_memmove(ptr, y_array[0], (size_t)yanklen);
+ ptr += yanklen;
+ }
+ mch_memmove(ptr, oldp + col, STRLEN(oldp + col) + 1);
+ ml_replace(lnum, newp, FALSE);
+ /* Put cursor on last putted char. */
+ curwin->w_cursor.col += (colnr_T)(totlen - 1);
+ }
+ curbuf->b_op_end = curwin->w_cursor;
+ /* For "CTRL-O p" in Insert mode, put cursor after last char */
+ if (totlen && (restart_edit != 0 || (flags & PUT_CURSEND)))
+ ++curwin->w_cursor.col;
+ changed_bytes(lnum, col);
+ }
+ else
+ {
+ /*
+ * Insert at least one line. When y_type is MCHAR, break the first
+ * line in two.
+ */
+ for (cnt = 1; cnt <= count; ++cnt)
+ {
+ i = 0;
+ if (y_type == MCHAR)
+ {
+ /*
+ * Split the current line in two at the insert position.
+ * First insert y_array[size - 1] in front of second line.
+ * Then append y_array[0] to first line.
+ */
+ lnum = new_cursor.lnum;
+ ptr = ml_get(lnum) + col;
+ totlen = (int)STRLEN(y_array[y_size - 1]);
+ newp = alloc_check((unsigned)(STRLEN(ptr) + totlen + 1));
+ if (newp == NULL)
+ goto error;
+ STRCPY(newp, y_array[y_size - 1]);
+ STRCAT(newp, ptr);
+ /* insert second line */
+ ml_append(lnum, newp, (colnr_T)0, FALSE);
+ vim_free(newp);
+
+ oldp = ml_get(lnum);
+ newp = alloc_check((unsigned)(col + yanklen + 1));
+ if (newp == NULL)
+ goto error;
+ /* copy first part of line */
+ mch_memmove(newp, oldp, (size_t)col);
+ /* append to first line */
+ mch_memmove(newp + col, y_array[0], (size_t)(yanklen + 1));
+ ml_replace(lnum, newp, FALSE);
+
+ curwin->w_cursor.lnum = lnum;
+ i = 1;
+ }
+
+ for (; i < y_size; ++i)
+ {
+ if ((y_type != MCHAR || i < y_size - 1)
+ && ml_append(lnum, y_array[i], (colnr_T)0, FALSE)
+ == FAIL)
+ goto error;
+ lnum++;
+ ++nr_lines;
+ if (flags & PUT_FIXINDENT)
+ {
+ old_pos = curwin->w_cursor;
+ curwin->w_cursor.lnum = lnum;
+ ptr = ml_get(lnum);
+ if (cnt == count && i == y_size - 1)
+ lendiff = (int)STRLEN(ptr);
+#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
+ if (*ptr == '#' && preprocs_left())
+ indent = 0; /* Leave # lines at start */
+ else
+#endif
+ if (*ptr == NUL)
+ indent = 0; /* Ignore empty lines */
+ else if (first_indent)
+ {
+ indent_diff = orig_indent - get_indent();
+ indent = orig_indent;
+ first_indent = FALSE;
+ }
+ else if ((indent = get_indent() + indent_diff) < 0)
+ indent = 0;
+ (void)set_indent(indent, 0);
+ curwin->w_cursor = old_pos;
+ /* remember how many chars were removed */
+ if (cnt == count && i == y_size - 1)
+ lendiff -= (int)STRLEN(ml_get(lnum));
+ }
+ }
+ }
+
+error:
+ /* Adjust marks. */
+ if (y_type == MLINE)
+ {
+ curbuf->b_op_start.col = 0;
+ if (dir == FORWARD)
+ curbuf->b_op_start.lnum++;
+ }
+ mark_adjust(curbuf->b_op_start.lnum + (y_type == MCHAR),
+ (linenr_T)MAXLNUM, nr_lines, 0L);
+
+ /* note changed text for displaying and folding */
+ if (y_type == MCHAR)
+ changed_lines(curwin->w_cursor.lnum, col,
+ curwin->w_cursor.lnum + 1, nr_lines);
+ else
+ changed_lines(curbuf->b_op_start.lnum, 0,
+ curbuf->b_op_start.lnum, nr_lines);
+
+ /* put '] mark at last inserted character */
+ curbuf->b_op_end.lnum = lnum;
+ /* correct length for change in indent */
+ col = (colnr_T)STRLEN(y_array[y_size - 1]) - lendiff;
+ if (col > 1)
+ curbuf->b_op_end.col = col - 1;
+ else
+ curbuf->b_op_end.col = 0;
+
+ if (flags & PUT_CURSEND)
+ {
+ /* put cursor after inserted text */
+ if (y_type == MLINE)
+ {
+ if (lnum >= curbuf->b_ml.ml_line_count)
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ else
+ curwin->w_cursor.lnum = lnum + 1;
+ curwin->w_cursor.col = 0;
+ }
+ else
+ {
+ curwin->w_cursor.lnum = lnum;
+ curwin->w_cursor.col = col;
+ }
+ }
+ else if (y_type == MLINE)
+ {
+ /* put cursor onfirst non-blank in first inserted line */
+ curwin->w_cursor.col = 0;
+ if (dir == FORWARD)
+ ++curwin->w_cursor.lnum;
+ beginline(BL_WHITE | BL_FIX);
+ }
+ else /* put cursor on first inserted character */
+ curwin->w_cursor = new_cursor;
+ }
+ }
+
+ msgmore(nr_lines);
+ curwin->w_set_curswant = TRUE;
+
+end:
+ if (allocated)
+ {
+ vim_free(insert_string);
+ if (regname == '=')
+ vim_free(y_array);
+ }
+ if (gchar_cursor() == NUL
+ && curwin->w_cursor.col > 0
+ && !(restart_edit || (State & INSERT)))
+ {
+ --curwin->w_cursor.col;
+#ifdef FEAT_VIRTUALEDIT
+ if (ve_flags == VE_ALL)
+ ++curwin->w_cursor.coladd;
+#endif
+ }
+}
+
+#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) || defined(PROTO)
+/*
+ * Return TRUE if lines starting with '#' should be left aligned.
+ */
+ int
+preprocs_left()
+{
+ return
+# ifdef FEAT_SMARTINDENT
+# ifdef FEAT_CINDENT
+ (curbuf->b_p_si && !curbuf->b_p_cin) ||
+# else
+ curbuf->b_p_si
+# endif
+# endif
+# ifdef FEAT_CINDENT
+ (curbuf->b_p_cin && in_cinkeys('#', ' ', TRUE))
+# endif
+ ;
+}
+#endif
+
+/* Return the character name of the register with the given number */
+ int
+get_register_name(num)
+ int num;
+{
+ if (num == -1)
+ return '"';
+ else if (num < 10)
+ return num + '0';
+ else if (num == DELETION_REGISTER)
+ return '-';
+#ifdef FEAT_CLIPBOARD
+ else if (num == STAR_REGISTER)
+ return '*';
+ else if (num == PLUS_REGISTER)
+ return '+';
+#endif
+ else
+ {
+#ifdef EBCDIC
+ int i;
+
+ /* EBCDIC is really braindead ... */
+ i = 'a' + (num - 10);
+ if (i > 'i')
+ i += 7;
+ if (i > 'r')
+ i += 8;
+ return i;
+#else
+ return num + 'a' - 10;
+#endif
+ }
+}
+
+/*
+ * ":dis" and ":registers": Display the contents of the yank registers.
+ */
+ void
+ex_display(eap)
+ exarg_T *eap;
+{
+ int i, n;
+ long j;
+ char_u *p;
+ struct yankreg *yb;
+ int name;
+ int attr;
+ char_u *arg = eap->arg;
+
+ if (arg != NULL && *arg == NUL)
+ arg = NULL;
+ attr = hl_attr(HLF_8);
+
+ /* Highlight title */
+ MSG_PUTS_TITLE(_("\n--- Registers ---"));
+ for (i = -1; i < NUM_REGISTERS && !got_int; ++i)
+ {
+ name = get_register_name(i);
+ if (arg != NULL && vim_strchr(arg, name) == NULL)
+ continue; /* did not ask for this register */
+
+#ifdef FEAT_CLIPBOARD
+ /* Adjust register name for "unnamed" in 'clipboard'.
+ * When it's a clipboard register, fill it with the current contents
+ * of the clipboard. */
+ adjust_clip_reg(&name);
+ (void)may_get_selection(name);
+#endif
+
+ if (i == -1)
+ {
+ if (y_previous != NULL)
+ yb = y_previous;
+ else
+ yb = &(y_regs[0]);
+ }
+ else
+ yb = &(y_regs[i]);
+ if (yb->y_array != NULL)
+ {
+ msg_putchar('\n');
+ msg_putchar('"');
+ msg_putchar(name);
+ MSG_PUTS(" ");
+
+ n = (int)Columns - 6;
+ for (j = 0; j < yb->y_size && n > 1; ++j)
+ {
+ if (j)
+ {
+ MSG_PUTS_ATTR("^J", attr);
+ n -= 2;
+ }
+ for (p = yb->y_array[j]; *p && (n -= ptr2cells(p)) >= 0; ++p)
+ {
+ msg_outtrans_len(p, 1);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ }
+ if (n > 1 && yb->y_type == MLINE)
+ MSG_PUTS_ATTR("^J", attr);
+ out_flush(); /* show one line at a time */
+ }
+ ui_breakcheck();
+ }
+
+ /*
+ * display last inserted text
+ */
+ if ((p = get_last_insert()) != NULL
+ && (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int)
+ {
+ MSG_PUTS("\n\". ");
+ dis_msg(p, TRUE);
+ }
+
+ /*
+ * display last command line
+ */
+ if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL)
+ && !got_int)
+ {
+ MSG_PUTS("\n\": ");
+ dis_msg(last_cmdline, FALSE);
+ }
+
+ /*
+ * display current file name
+ */
+ if (curbuf->b_fname != NULL
+ && (arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int)
+ {
+ MSG_PUTS("\n\"% ");
+ dis_msg(curbuf->b_fname, FALSE);
+ }
+
+ /*
+ * display alternate file name
+ */
+ if ((arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int)
+ {
+ char_u *fname;
+ linenr_T dummy;
+
+ if (buflist_name_nr(0, &fname, &dummy) != FAIL)
+ {
+ MSG_PUTS("\n\"# ");
+ dis_msg(fname, FALSE);
+ }
+ }
+
+ /*
+ * display last search pattern
+ */
+ if (last_search_pat() != NULL
+ && (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int)
+ {
+ MSG_PUTS("\n\"/ ");
+ dis_msg(last_search_pat(), FALSE);
+ }
+
+#ifdef FEAT_EVAL
+ /*
+ * display last used expression
+ */
+ if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL)
+ && !got_int)
+ {
+ MSG_PUTS("\n\"= ");
+ dis_msg(expr_line, FALSE);
+ }
+#endif
+}
+
+/*
+ * display a string for do_dis()
+ * truncate at end of screen line
+ */
+ static void
+dis_msg(p, skip_esc)
+ char_u *p;
+ int skip_esc; /* if TRUE, ignore trailing ESC */
+{
+ int n;
+#ifdef FEAT_MBYTE
+ int l;
+#endif
+
+ n = (int)Columns - 6;
+ while (*p != NUL
+ && !(*p == ESC && skip_esc && *(p + 1) == NUL)
+ && (n -= ptr2cells(p)) >= 0)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
+ {
+ msg_outtrans_len(p, l);
+ p += l;
+ }
+ else
+#endif
+ msg_outtrans_len(p++, 1);
+ }
+ ui_breakcheck();
+}
+
+/*
+ * join 'count' lines (minimal 2), including u_save()
+ */
+ void
+do_do_join(count, insert_space)
+ long count;
+ int insert_space;
+{
+ if (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
+ (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL)
+ return;
+
+ while (--count > 0)
+ {
+ line_breakcheck();
+ if (got_int || do_join(insert_space) == FAIL)
+ {
+ beep_flush();
+ break;
+ }
+ }
+
+#if 0
+ /*
+ * Need to update the screen if the line where the cursor is became too
+ * long to fit on the screen.
+ */
+ update_topline_redraw();
+#endif
+}
+
+/*
+ * Join two lines at the cursor position.
+ * "redraw" is TRUE when the screen should be updated.
+ * Caller must have setup for undo.
+ *
+ * return FAIL for failure, OK ohterwise
+ */
+ int
+do_join(insert_space)
+ int insert_space;
+{
+ char_u *curr;
+ char_u *next, *next_start;
+ char_u *newp;
+ int endcurr1, endcurr2;
+ int currsize; /* size of the current line */
+ int nextsize; /* size of the next line */
+ int spaces; /* number of spaces to insert */
+ linenr_T t;
+
+ if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
+ return FAIL; /* can't join on last line */
+
+ curr = ml_get_curline();
+ currsize = (int)STRLEN(curr);
+ endcurr1 = endcurr2 = NUL;
+ if (insert_space && currsize > 0)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ next = curr + currsize - 1;
+ next -= (*mb_head_off)(curr, next);
+ endcurr1 = (*mb_ptr2char)(next);
+ if (next > curr)
+ {
+ --next;
+ next -= (*mb_head_off)(curr, next);
+ endcurr2 = (*mb_ptr2char)(next);
+ }
+ }
+ else
+#endif
+ {
+ endcurr1 = *(curr + currsize - 1);
+ if (currsize > 1)
+ endcurr2 = *(curr + currsize - 2);
+ }
+ }
+
+ next = next_start = ml_get((linenr_T)(curwin->w_cursor.lnum + 1));
+ spaces = 0;
+ if (insert_space)
+ {
+ next = skipwhite(next);
+ if (*next != ')' && currsize != 0 && endcurr1 != TAB
+#ifdef FEAT_MBYTE
+ && (!has_format_option(FO_MBYTE_JOIN)
+ || (mb_ptr2char(next) < 0x100 && endcurr1 < 0x100))
+ && (!has_format_option(FO_MBYTE_JOIN2)
+ || mb_ptr2char(next) < 0x100 || endcurr1 < 0x100)
+#endif
+ )
+ {
+ /* don't add a space if the line is ending in a space */
+ if (endcurr1 == ' ')
+ endcurr1 = endcurr2;
+ else
+ ++spaces;
+ /* extra space when 'joinspaces' set and line ends in '.' */
+ if ( p_js
+ && (endcurr1 == '.'
+ || (vim_strchr(p_cpo, CPO_JOINSP) == NULL
+ && (endcurr1 == '?' || endcurr1 == '!'))))
+ ++spaces;
+ }
+ }
+ nextsize = (int)STRLEN(next);
+
+ newp = alloc_check((unsigned)(currsize + nextsize + spaces + 1));
+ if (newp == NULL)
+ return FAIL;
+
+ /*
+ * Insert the next line first, because we already have that pointer.
+ * Curr has to be obtained again, because getting next will have
+ * invalidated it.
+ */
+ mch_memmove(newp + currsize + spaces, next, (size_t)(nextsize + 1));
+
+ curr = ml_get_curline();
+ mch_memmove(newp, curr, (size_t)currsize);
+
+ copy_spaces(newp + currsize, (size_t)spaces);
+
+ ml_replace(curwin->w_cursor.lnum, newp, FALSE);
+
+ /* Only report the change in the first line here, del_lines() will report
+ * the deleted line. */
+ changed_lines(curwin->w_cursor.lnum, currsize,
+ curwin->w_cursor.lnum + 1, 0L);
+
+ /*
+ * Delete the following line. To do this we move the cursor there
+ * briefly, and then move it back. After del_lines() the cursor may
+ * have moved up (last line deleted), so the current lnum is kept in t.
+ *
+ * Move marks from the deleted line to the joined line, adjusting the
+ * column. This is not Vi compatible, but Vi deletes the marks, thus that
+ * should not really be a problem.
+ */
+ t = curwin->w_cursor.lnum;
+ mark_col_adjust(t + 1, (colnr_T)0, (linenr_T)-1,
+ (long)(currsize + spaces - (next - next_start)));
+ ++curwin->w_cursor.lnum;
+ del_lines(1L, FALSE);
+ curwin->w_cursor.lnum = t;
+
+ /*
+ * go to first character of the joined line
+ */
+ curwin->w_cursor.col = currsize;
+ check_cursor_col();
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ curwin->w_set_curswant = TRUE;
+
+ return OK;
+}
+
+#ifdef FEAT_COMMENTS
+/*
+ * Return TRUE if the two comment leaders given are the same. "lnum" is
+ * the first line. White-space is ignored. Note that the whole of
+ * 'leader1' must match 'leader2_len' characters from 'leader2' -- webb
+ */
+ static int
+same_leader(lnum, leader1_len, leader1_flags, leader2_len, leader2_flags)
+ linenr_T lnum;
+ int leader1_len;
+ char_u *leader1_flags;
+ int leader2_len;
+ char_u *leader2_flags;
+{
+ int idx1 = 0, idx2 = 0;
+ char_u *p;
+ char_u *line1;
+ char_u *line2;
+
+ if (leader1_len == 0)
+ return (leader2_len == 0);
+
+ /*
+ * If first leader has 'f' flag, the lines can be joined only if the
+ * second line does not have a leader.
+ * If first leader has 'e' flag, the lines can never be joined.
+ * If fist leader has 's' flag, the lines can only be joined if there is
+ * some text after it and the second line has the 'm' flag.
+ */
+ if (leader1_flags != NULL)
+ {
+ for (p = leader1_flags; *p && *p != ':'; ++p)
+ {
+ if (*p == COM_FIRST)
+ return (leader2_len == 0);
+ if (*p == COM_END)
+ return FALSE;
+ if (*p == COM_START)
+ {
+ if (*(ml_get(lnum) + leader1_len) == NUL)
+ return FALSE;
+ if (leader2_flags == NULL || leader2_len == 0)
+ return FALSE;
+ for (p = leader2_flags; *p && *p != ':'; ++p)
+ if (*p == COM_MIDDLE)
+ return TRUE;
+ return FALSE;
+ }
+ }
+ }
+
+ /*
+ * Get current line and next line, compare the leaders.
+ * The first line has to be saved, only one line can be locked at a time.
+ */
+ line1 = vim_strsave(ml_get(lnum));
+ if (line1 != NULL)
+ {
+ for (idx1 = 0; vim_iswhite(line1[idx1]); ++idx1)
+ ;
+ line2 = ml_get(lnum + 1);
+ for (idx2 = 0; idx2 < leader2_len; ++idx2)
+ {
+ if (!vim_iswhite(line2[idx2]))
+ {
+ if (line1[idx1++] != line2[idx2])
+ break;
+ }
+ else
+ while (vim_iswhite(line1[idx1]))
+ ++idx1;
+ }
+ vim_free(line1);
+ }
+ return (idx2 == leader2_len && idx1 == leader1_len);
+}
+#endif
+
+/*
+ * implementation of the format operator 'gq'
+ */
+ void
+op_format(oap, keep_cursor)
+ oparg_T *oap;
+ int keep_cursor; /* keep cursor on same text char */
+{
+ long old_line_count = curbuf->b_ml.ml_line_count;
+
+ /* Place the cursor where the "gq" or "gw" command was given, so that "u"
+ * can put it back there. */
+ curwin->w_cursor = oap->cursor_start;
+
+ if (u_save((linenr_T)(oap->start.lnum - 1),
+ (linenr_T)(oap->end.lnum + 1)) == FAIL)
+ return;
+ curwin->w_cursor = oap->start;
+
+#ifdef FEAT_VISUAL
+ if (oap->is_VIsual)
+ /* When there is no change: need to remove the Visual selection */
+ redraw_curbuf_later(INVERTED);
+#endif
+
+ /* Set '[ mark at the start of the formatted area */
+ curbuf->b_op_start = oap->start;
+
+ /* For "gw" remember the cursor position and put it back below (adjusted
+ * for joined and split lines). */
+ if (keep_cursor)
+ saved_cursor = oap->cursor_start;
+
+ format_lines(oap->line_count);
+
+ /*
+ * Leave the cursor at the first non-blank of the last formatted line.
+ * If the cursor was moved one line back (e.g. with "Q}") go to the next
+ * line, so "." will do the next lines.
+ */
+ if (oap->end_adjusted && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
+ ++curwin->w_cursor.lnum;
+ beginline(BL_WHITE | BL_FIX);
+ old_line_count = curbuf->b_ml.ml_line_count - old_line_count;
+ msgmore(old_line_count);
+
+ /* put '] mark on the end of the formatted area */
+ curbuf->b_op_end = curwin->w_cursor;
+
+ if (keep_cursor)
+ {
+ curwin->w_cursor = saved_cursor;
+ saved_cursor.lnum = 0;
+ }
+
+#ifdef FEAT_VISUAL
+ if (oap->is_VIsual)
+ {
+ win_T *wp;
+
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_old_cursor_lnum != 0)
+ {
+ /* When lines have been inserted or deleted, adjust the end of
+ * the Visual area to be redrawn. */
+ if (wp->w_old_cursor_lnum > wp->w_old_visual_lnum)
+ wp->w_old_cursor_lnum += old_line_count;
+ else
+ wp->w_old_visual_lnum += old_line_count;
+ }
+ }
+ }
+#endif
+}
+
+/*
+ * Format "line_count" lines, starting at the cursor position.
+ * When "line_count" is negative, format until the end of the paragraph.
+ * Lines after the cursor line are saved for undo, caller must have saved the
+ * first line.
+ */
+ void
+format_lines(line_count)
+ linenr_T line_count;
+{
+ int max_len;
+ int is_not_par; /* current line not part of parag. */
+ int next_is_not_par; /* next line not part of paragraph */
+ int is_end_par; /* at end of paragraph */
+ int prev_is_end_par = FALSE;/* prev. line not part of parag. */
+ int next_is_start_par = FALSE;
+#ifdef FEAT_COMMENTS
+ int leader_len = 0; /* leader len of current line */
+ int next_leader_len; /* leader len of next line */
+ char_u *leader_flags = NULL; /* flags for leader of current line */
+ char_u *next_leader_flags; /* flags for leader of next line */
+ int do_comments; /* format comments */
+#endif
+ int advance = TRUE;
+ int second_indent = -1;
+ int do_second_indent;
+ int do_number_indent;
+ int do_trail_white;
+ int first_par_line = TRUE;
+ int smd_save;
+ long count;
+ int need_set_indent = TRUE; /* set indent of next paragraph */
+ int force_format = FALSE;
+ int old_State = State;
+
+ /* length of a line to force formatting: 3 * 'tw' */
+ max_len = comp_textwidth(TRUE) * 3;
+
+ /* check for 'q', '2' and '1' in 'formatoptions' */
+#ifdef FEAT_COMMENTS
+ do_comments = has_format_option(FO_Q_COMS);
+#endif
+ do_second_indent = has_format_option(FO_Q_SECOND);
+ do_number_indent = has_format_option(FO_Q_NUMBER);
+ do_trail_white = has_format_option(FO_WHITE_PAR);
+
+ /*
+ * Get info about the previous and current line.
+ */
+ if (curwin->w_cursor.lnum > 1)
+ is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1
+#ifdef FEAT_COMMENTS
+ , &leader_len, &leader_flags, do_comments
+#endif
+ );
+ else
+ is_not_par = TRUE;
+ next_is_not_par = fmt_check_par(curwin->w_cursor.lnum
+#ifdef FEAT_COMMENTS
+ , &next_leader_len, &next_leader_flags, do_comments
+#endif
+ );
+ is_end_par = (is_not_par || next_is_not_par);
+ if (!is_end_par && do_trail_white)
+ is_end_par = !ends_in_white(curwin->w_cursor.lnum - 1);
+
+ curwin->w_cursor.lnum--;
+ for (count = line_count; count != 0 && !got_int; --count)
+ {
+ /*
+ * Advance to next paragraph.
+ */
+ if (advance)
+ {
+ curwin->w_cursor.lnum++;
+ prev_is_end_par = is_end_par;
+ is_not_par = next_is_not_par;
+#ifdef FEAT_COMMENTS
+ leader_len = next_leader_len;
+ leader_flags = next_leader_flags;
+#endif
+ }
+
+ /*
+ * The last line to be formatted.
+ */
+ if (count == 1 || curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
+ {
+ next_is_not_par = TRUE;
+#ifdef FEAT_COMMENTS
+ next_leader_len = 0;
+ next_leader_flags = NULL;
+#endif
+ }
+ else
+ {
+ next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1
+#ifdef FEAT_COMMENTS
+ , &next_leader_len, &next_leader_flags, do_comments
+#endif
+ );
+ if (do_number_indent)
+ next_is_start_par =
+ (get_number_indent(curwin->w_cursor.lnum + 1) > 0);
+ }
+ advance = TRUE;
+ is_end_par = (is_not_par || next_is_not_par || next_is_start_par);
+ if (!is_end_par && do_trail_white)
+ is_end_par = !ends_in_white(curwin->w_cursor.lnum);
+
+ /*
+ * Skip lines that are not in a paragraph.
+ */
+ if (is_not_par)
+ {
+ if (line_count < 0)
+ break;
+ }
+ else
+ {
+ /*
+ * For the first line of a paragraph, check indent of second line.
+ * Don't do this for comments and empty lines.
+ */
+ if (first_par_line
+ && (do_second_indent || do_number_indent)
+ && prev_is_end_par
+ && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
+#ifdef FEAT_COMMENTS
+ && leader_len == 0
+ && next_leader_len == 0
+#endif
+ )
+ {
+ if (do_second_indent
+ && !lineempty(curwin->w_cursor.lnum + 1))
+ second_indent = get_indent_lnum(curwin->w_cursor.lnum + 1);
+ else if (do_number_indent)
+ second_indent = get_number_indent(curwin->w_cursor.lnum);
+ }
+
+ /*
+ * When the comment leader changes, it's the end of the paragraph.
+ */
+ if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count
+#ifdef FEAT_COMMENTS
+ || !same_leader(curwin->w_cursor.lnum,
+ leader_len, leader_flags,
+ next_leader_len, next_leader_flags)
+#endif
+ )
+ is_end_par = TRUE;
+
+ /*
+ * If we have got to the end of a paragraph, or the line is
+ * getting long, format it.
+ */
+ if (is_end_par || force_format)
+ {
+ if (need_set_indent)
+ /* replace indent in first line with minimal number of
+ * tabs and spaces, according to current options */
+ (void)set_indent(get_indent(), SIN_CHANGED);
+
+ /* put cursor on last non-space */
+ State = NORMAL; /* don't go past end-of-line */
+ coladvance((colnr_T)MAXCOL);
+ while (curwin->w_cursor.col && vim_isspace(gchar_cursor()))
+ dec_cursor();
+
+ /* do the formatting, without 'showmode' */
+ State = INSERT; /* for open_line() */
+ smd_save = p_smd;
+ p_smd = FALSE;
+ insertchar(NUL, INSCHAR_FORMAT
+#ifdef FEAT_COMMENTS
+ + (do_comments ? INSCHAR_DO_COM : 0)
+#endif
+ , second_indent);
+ State = old_State;
+ p_smd = smd_save;
+ second_indent = -1;
+ /* at end of par.: need to set indent of next par. */
+ need_set_indent = is_end_par;
+ if (is_end_par)
+ {
+ /* When called with a negative line count, break at the
+ * end of the paragraph. */
+ if (line_count < 0)
+ break;
+ first_par_line = TRUE;
+ }
+ force_format = FALSE;
+ }
+
+ /*
+ * When still in same paragraph, join the lines together. But
+ * first delete the comment leader from the second line.
+ */
+ if (!is_end_par)
+ {
+ advance = FALSE;
+ curwin->w_cursor.lnum++;
+ curwin->w_cursor.col = 0;
+ if (line_count < 0 && u_save_cursor() == FAIL)
+ break;
+#ifdef FEAT_COMMENTS
+ (void)del_bytes((long)next_leader_len, FALSE);
+ if (next_leader_len > 0)
+ mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L,
+ (long)-next_leader_len);
+#endif
+ curwin->w_cursor.lnum--;
+ if (do_join(TRUE) == FAIL)
+ {
+ beep_flush();
+ break;
+ }
+ first_par_line = FALSE;
+ /* If the line is getting long, format it next time */
+ if (STRLEN(ml_get_curline()) > (size_t)max_len)
+ force_format = TRUE;
+ else
+ force_format = FALSE;
+ }
+ }
+ line_breakcheck();
+ }
+}
+
+/*
+ * Return TRUE if line "lnum" ends in a white character.
+ */
+ static int
+ends_in_white(lnum)
+ linenr_T lnum;
+{
+ char_u *s = ml_get(lnum);
+ size_t l;
+
+ if (*s == NUL)
+ return FALSE;
+ /* Don't use STRLEN() inside vim_iswhite(), SAS/C complains: "macro
+ * invocation may call function multiple times". */
+ l = STRLEN(s) - 1;
+ return vim_iswhite(s[l]);
+}
+
+/*
+ * Blank lines, and lines containing only the comment leader, are left
+ * untouched by the formatting. The function returns TRUE in this
+ * case. It also returns TRUE when a line starts with the end of a comment
+ * ('e' in comment flags), so that this line is skipped, and not joined to the
+ * previous line. A new paragraph starts after a blank line, or when the
+ * comment leader changes -- webb.
+ */
+#ifdef FEAT_COMMENTS
+ static int
+fmt_check_par(lnum, leader_len, leader_flags, do_comments)
+ linenr_T lnum;
+ int *leader_len;
+ char_u **leader_flags;
+ int do_comments;
+{
+ char_u *flags = NULL; /* init for GCC */
+ char_u *ptr;
+
+ ptr = ml_get(lnum);
+ if (do_comments)
+ *leader_len = get_leader_len(ptr, leader_flags, FALSE);
+ else
+ *leader_len = 0;
+
+ if (*leader_len > 0)
+ {
+ /*
+ * Search for 'e' flag in comment leader flags.
+ */
+ flags = *leader_flags;
+ while (*flags && *flags != ':' && *flags != COM_END)
+ ++flags;
+ }
+
+ return (*skipwhite(ptr + *leader_len) == NUL
+ || (*leader_len > 0 && *flags == COM_END)
+ || startPS(lnum, NUL, FALSE));
+}
+#else
+ static int
+fmt_check_par(lnum)
+ linenr_T lnum;
+{
+ return (*skipwhite(ml_get(lnum)) == NUL || startPS(lnum, NUL, FALSE));
+}
+#endif
+
+/*
+ * Return TRUE when a paragraph starts in line "lnum". Return FALSE when the
+ * previous line is in the same paragraph. Used for auto-formatting.
+ */
+ int
+paragraph_start(lnum)
+ linenr_T lnum;
+{
+ char_u *p;
+#ifdef FEAT_COMMENTS
+ int leader_len = 0; /* leader len of current line */
+ char_u *leader_flags = NULL; /* flags for leader of current line */
+ int next_leader_len; /* leader len of next line */
+ char_u *next_leader_flags; /* flags for leader of next line */
+ int do_comments; /* format comments */
+#endif
+
+ if (lnum <= 1)
+ return TRUE; /* start of the file */
+
+ p = ml_get(lnum - 1);
+ if (*p == NUL)
+ return TRUE; /* after empty line */
+
+#ifdef FEAT_COMMENTS
+ do_comments = has_format_option(FO_Q_COMS);
+#endif
+ if (fmt_check_par(lnum - 1
+#ifdef FEAT_COMMENTS
+ , &leader_len, &leader_flags, do_comments
+#endif
+ ))
+ return TRUE; /* after non-paragraph line */
+
+ if (fmt_check_par(lnum
+#ifdef FEAT_COMMENTS
+ , &next_leader_len, &next_leader_flags, do_comments
+#endif
+ ))
+ return TRUE; /* "lnum" is not a paragraph line */
+
+ if (has_format_option(FO_WHITE_PAR) && !ends_in_white(lnum - 1))
+ return TRUE; /* missing trailing space in previous line. */
+
+ if (has_format_option(FO_Q_NUMBER) && (get_number_indent(lnum) > 0))
+ return TRUE; /* numbered item starts in "lnum". */
+
+#ifdef FEAT_COMMENTS
+ if (!same_leader(lnum - 1, leader_len, leader_flags,
+ next_leader_len, next_leader_flags))
+ return TRUE; /* change of comment leader. */
+#endif
+
+ return FALSE;
+}
+
+#ifdef FEAT_VISUAL
+/*
+ * prepare a few things for block mode yank/delete/tilde
+ *
+ * for delete:
+ * - textlen includes the first/last char to be (partly) deleted
+ * - start/endspaces is the number of columns that are taken by the
+ * first/last deleted char minus the number of columns that have to be
+ * deleted. for yank and tilde:
+ * - textlen includes the first/last char to be wholly yanked
+ * - start/endspaces is the number of columns of the first/last yanked char
+ * that are to be yanked.
+ */
+ static void
+block_prep(oap, bdp, lnum, is_del)
+ oparg_T *oap;
+ struct block_def *bdp;
+ linenr_T lnum;
+ int is_del;
+{
+ int incr = 0;
+ char_u *pend;
+ char_u *pstart;
+ char_u *line;
+ char_u *prev_pstart;
+ char_u *prev_pend;
+
+ bdp->startspaces = 0;
+ bdp->endspaces = 0;
+ bdp->textlen = 0;
+ bdp->start_vcol = 0;
+ bdp->end_vcol = 0;
+#ifdef FEAT_VISUALEXTRA
+ bdp->is_short = FALSE;
+ bdp->is_oneChar = FALSE;
+ bdp->pre_whitesp = 0;
+ bdp->pre_whitesp_c = 0;
+ bdp->end_char_vcols = 0;
+#endif
+ bdp->start_char_vcols = 0;
+
+ line = ml_get(lnum);
+ pstart = line;
+ prev_pstart = line;
+ while (bdp->start_vcol < oap->start_vcol && *pstart)
+ {
+ /* Count a tab for what it's worth (if list mode not on) */
+ incr = lbr_chartabsize(pstart, (colnr_T)bdp->start_vcol);
+ bdp->start_vcol += incr;
+#ifdef FEAT_VISUALEXTRA
+ if (vim_iswhite(*pstart))
+ {
+ bdp->pre_whitesp += incr;
+ bdp->pre_whitesp_c++;
+ }
+ else
+ {
+ bdp->pre_whitesp = 0;
+ bdp->pre_whitesp_c = 0;
+ }
+#endif
+ prev_pstart = pstart;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ pstart += (*mb_ptr2len_check)(pstart);
+ else
+#endif
+ ++pstart;
+ }
+ bdp->start_char_vcols = incr;
+ if (bdp->start_vcol < oap->start_vcol) /* line too short */
+ {
+ bdp->end_vcol = bdp->start_vcol;
+#ifdef FEAT_VISUALEXTRA
+ bdp->is_short = TRUE;
+#endif
+ if (!is_del || oap->op_type == OP_APPEND)
+ bdp->endspaces = oap->end_vcol - oap->start_vcol + 1;
+ }
+ else
+ {
+ /* notice: this converts partly selected Multibyte characters to
+ * spaces, too. */
+ bdp->startspaces = bdp->start_vcol - oap->start_vcol;
+ if (is_del && bdp->startspaces)
+ bdp->startspaces = bdp->start_char_vcols - bdp->startspaces;
+ pend = pstart;
+ bdp->end_vcol = bdp->start_vcol;
+ if (bdp->end_vcol > oap->end_vcol) /* it's all in one character */
+ {
+#ifdef FEAT_VISUALEXTRA
+ bdp->is_oneChar = TRUE;
+#endif
+ if (oap->op_type == OP_INSERT)
+ bdp->endspaces = bdp->start_char_vcols - bdp->startspaces;
+ else if (oap->op_type == OP_APPEND)
+ {
+ bdp->startspaces += oap->end_vcol - oap->start_vcol + 1;
+ bdp->endspaces = bdp->start_char_vcols - bdp->startspaces;
+ }
+ else
+ {
+ bdp->startspaces = oap->end_vcol - oap->start_vcol + 1;
+ if (is_del && oap->op_type != OP_LSHIFT)
+ {
+ /* just putting the sum of those two into
+ * bdp->startspaces doesn't work for Visual replace,
+ * so we have to split the tab in two */
+ bdp->startspaces = bdp->start_char_vcols
+ - (bdp->start_vcol - oap->start_vcol);
+ bdp->endspaces = bdp->end_vcol - oap->end_vcol - 1;
+ }
+ }
+ }
+ else
+ {
+ prev_pend = pend;
+ while (bdp->end_vcol <= oap->end_vcol && *pend != NUL)
+ {
+ /* Count a tab for what it's worth (if list mode not on) */
+ prev_pend = pend;
+ incr = lbr_chartabsize_adv(&pend, (colnr_T)bdp->end_vcol);
+ bdp->end_vcol += incr;
+ }
+ if (bdp->end_vcol <= oap->end_vcol
+ && (!is_del
+ || oap->op_type == OP_APPEND
+ || oap->op_type == OP_REPLACE)) /* line too short */
+ {
+#ifdef FEAT_VISUALEXTRA
+ bdp->is_short = TRUE;
+#endif
+ /* Alternative: include spaces to fill up the block.
+ * Disadvantage: can lead to trailing spaces when the line is
+ * short where the text is put */
+ /* if (!is_del || oap->op_type == OP_APPEND) */
+ if (oap->op_type == OP_APPEND || virtual_op)
+ bdp->endspaces = oap->end_vcol - bdp->end_vcol
+ + oap->inclusive;
+ else
+ bdp->endspaces = 0; /* replace doesn't add characters */
+ }
+ else if (bdp->end_vcol > oap->end_vcol)
+ {
+ bdp->endspaces = bdp->end_vcol - oap->end_vcol - 1;
+ if (!is_del && bdp->endspaces)
+ {
+ bdp->endspaces = incr - bdp->endspaces;
+ if (pend != pstart)
+ pend = prev_pend;
+ }
+ }
+ }
+#ifdef FEAT_VISUALEXTRA
+ bdp->end_char_vcols = incr;
+#endif
+ if (is_del && bdp->startspaces)
+ pstart = prev_pstart;
+ bdp->textlen = (int)(pend - pstart);
+ }
+ bdp->textcol = (colnr_T) (pstart - line);
+ bdp->textstart = pstart;
+}
+#endif /* FEAT_VISUAL */
+
+#ifdef FEAT_RIGHTLEFT
+static void reverse_line __ARGS((char_u *s));
+
+ static void
+reverse_line(s)
+ char_u *s;
+{
+ int i, j;
+ char_u c;
+
+ if ((i = (int)STRLEN(s) - 1) <= 0)
+ return;
+
+ curwin->w_cursor.col = i - curwin->w_cursor.col;
+ for (j = 0; j < i; j++, i--)
+ {
+ c = s[i]; s[i] = s[j]; s[j] = c;
+ }
+}
+
+# define RLADDSUBFIX(ptr) if (curwin->w_p_rl) reverse_line(ptr);
+#else
+# define RLADDSUBFIX(ptr)
+#endif
+
+/*
+ * add or subtract 'Prenum1' from a number in a line
+ * 'command' is CTRL-A for add, CTRL-X for subtract
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+do_addsub(command, Prenum1)
+ int command;
+ linenr_T Prenum1;
+{
+ int col;
+ char_u *buf1;
+ char_u buf2[NUMBUFLEN];
+ int hex; /* 'X' or 'x': hex; '0': octal */
+ static int hexupper = FALSE; /* 0xABC */
+ long_u n;
+ long_u oldn;
+ char_u *ptr;
+ int c;
+ int length = 0; /* character length of the number */
+ int todel;
+ int dohex;
+ int dooct;
+ int doalp;
+ int firstdigit;
+ int negative;
+ int subtract;
+
+ dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); /* "heX" */
+ dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); /* "Octal" */
+ doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); /* "alPha" */
+
+ ptr = ml_get_curline();
+ RLADDSUBFIX(ptr);
+
+ /*
+ * First check if we are on a hexadecimal number, after the "0x".
+ */
+ col = curwin->w_cursor.col;
+ if (dohex)
+ while (col > 0 && vim_isxdigit(ptr[col]))
+ --col;
+ if ( dohex
+ && col > 0
+ && (ptr[col] == 'X'
+ || ptr[col] == 'x')
+ && ptr[col - 1] == '0'
+ && vim_isxdigit(ptr[col + 1]))
+ {
+ /*
+ * Found hexadecimal number, move to its start.
+ */
+ --col;
+ }
+ else
+ {
+ /*
+ * Search forward and then backward to find the start of number.
+ */
+ col = curwin->w_cursor.col;
+
+ while (ptr[col] != NUL
+ && !vim_isdigit(ptr[col])
+ && !(doalp && ASCII_ISALPHA(ptr[col])))
+ ++col;
+
+ while (col > 0
+ && vim_isdigit(ptr[col - 1])
+ && !(doalp && ASCII_ISALPHA(ptr[col])))
+ --col;
+ }
+
+ /* truncate to max length of a number */
+ if (length >= NUMBUFLEN - 1)
+ length = NUMBUFLEN - 2;
+
+ /*
+ * If a number was found, and saving for undo works, replace the number.
+ */
+ firstdigit = ptr[col];
+ RLADDSUBFIX(ptr);
+ if ((!VIM_ISDIGIT(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit)))
+ || u_save_cursor() != OK)
+ {
+ beep_flush();
+ return FAIL;
+ }
+
+ /* get ptr again, because u_save() may have changed it */
+ ptr = ml_get_curline();
+ RLADDSUBFIX(ptr);
+
+ if (doalp && ASCII_ISALPHA(firstdigit))
+ {
+ /* decrement or increment alphabetic character */
+ if (command == Ctrl_X)
+ {
+ if (CharOrd(firstdigit) < Prenum1)
+ {
+ if (isupper(firstdigit))
+ firstdigit = 'A';
+ else
+ firstdigit = 'a';
+ }
+ else
+#ifdef EBCDIC
+ firstdigit = EBCDIC_CHAR_ADD(firstdigit, -Prenum1);
+#else
+ firstdigit -= Prenum1;
+#endif
+ }
+ else
+ {
+ if (26 - CharOrd(firstdigit) - 1 < Prenum1)
+ {
+ if (isupper(firstdigit))
+ firstdigit = 'Z';
+ else
+ firstdigit = 'z';
+ }
+ else
+#ifdef EBCDIC
+ firstdigit = EBCDIC_CHAR_ADD(firstdigit, Prenum1);
+#else
+ firstdigit += Prenum1;
+#endif
+ }
+ curwin->w_cursor.col = col;
+ (void)del_char(FALSE);
+ ins_char(firstdigit);
+ }
+ else
+ {
+ negative = FALSE;
+ if (col > 0 && ptr[col - 1] == '-') /* negative number */
+ {
+ --col;
+ negative = TRUE;
+ }
+
+ /* get the number value (unsigned) */
+ vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n);
+
+ /* ignore leading '-' for hex and octal numbers */
+ if (hex && negative)
+ {
+ ++col;
+ --length;
+ negative = FALSE;
+ }
+
+ /* add or subtract */
+ subtract = FALSE;
+ if (command == Ctrl_X)
+ subtract ^= TRUE;
+ if (negative)
+ subtract ^= TRUE;
+
+ oldn = n;
+ if (subtract)
+ n -= (unsigned long)Prenum1;
+ else
+ n += (unsigned long)Prenum1;
+
+ /* handle wraparound for decimal numbers */
+ if (!hex)
+ {
+ if (subtract)
+ {
+ if (n > oldn)
+ {
+ n = 1 + (n ^ (unsigned long)-1);
+ negative ^= TRUE;
+ }
+ }
+ else /* add */
+ {
+ if (n < oldn)
+ {
+ n = (n ^ (unsigned long)-1);
+ negative ^= TRUE;
+ }
+ }
+ if (n == 0)
+ negative = FALSE;
+ }
+
+ /*
+ * Delete the old number.
+ */
+ curwin->w_cursor.col = col;
+ todel = length;
+ c = gchar_cursor();
+ /*
+ * Don't include the '-' in the length, only the length of the part
+ * after it is kept the same.
+ */
+ if (c == '-')
+ --length;
+ while (todel-- > 0)
+ {
+ if (c < 0x100 && isalpha(c))
+ {
+ if (isupper(c))
+ hexupper = TRUE;
+ else
+ hexupper = FALSE;
+ }
+ /* del_char() will mark line needing displaying */
+ (void)del_char(FALSE);
+ c = gchar_cursor();
+ }
+
+ /*
+ * Prepare the leading characters in buf1[].
+ * When there are many leading zeros it could be very long. Allocate
+ * a bit too much.
+ */
+ buf1 = alloc((unsigned)length + NUMBUFLEN);
+ if (buf1 == NULL)
+ return FAIL;
+ ptr = buf1;
+ if (negative)
+ {
+ *ptr++ = '-';
+ }
+ if (hex)
+ {
+ *ptr++ = '0';
+ --length;
+ }
+ if (hex == 'x' || hex == 'X')
+ {
+ *ptr++ = hex;
+ --length;
+ }
+
+ /*
+ * Put the number characters in buf2[].
+ */
+ if (hex == 0)
+ sprintf((char *)buf2, "%lu", n);
+ else if (hex == '0')
+ sprintf((char *)buf2, "%lo", n);
+ else if (hex && hexupper)
+ sprintf((char *)buf2, "%lX", n);
+ else
+ sprintf((char *)buf2, "%lx", n);
+ length -= (int)STRLEN(buf2);
+
+ /*
+ * adjust number of zeros to the new number of digits, so the
+ * total length of the number remains the same
+ */
+ if (firstdigit == '0')
+ while (length-- > 0)
+ *ptr++ = '0';
+ *ptr = NUL;
+ STRCAT(buf1, buf2);
+ ins_str(buf1); /* insert the new number */
+ vim_free(buf1);
+ }
+ --curwin->w_cursor.col;
+ curwin->w_set_curswant = TRUE;
+#ifdef FEAT_RIGHTLEFT
+ ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE);
+ RLADDSUBFIX(ptr);
+#endif
+ return OK;
+}
+
+#ifdef FEAT_VIMINFO
+ int
+read_viminfo_register(virp, force)
+ vir_T *virp;
+ int force;
+{
+ int eof;
+ int do_it = TRUE;
+ int size;
+ int limit;
+ int i;
+ int set_prev = FALSE;
+ char_u *str;
+ char_u **array = NULL;
+
+ /* We only get here (hopefully) if line[0] == '"' */
+ str = virp->vir_line + 1;
+ if (*str == '"')
+ {
+ set_prev = TRUE;
+ str++;
+ }
+ if (!ASCII_ISALNUM(*str) && *str != '-')
+ {
+ if (viminfo_error("E577: ", _("Illegal register name"), virp->vir_line))
+ return TRUE; /* too many errors, pretend end-of-file */
+ do_it = FALSE;
+ }
+ get_yank_register(*str++, FALSE);
+ if (!force && y_current->y_array != NULL)
+ do_it = FALSE;
+ size = 0;
+ limit = 100; /* Optimized for registers containing <= 100 lines */
+ if (do_it)
+ {
+ if (set_prev)
+ y_previous = y_current;
+ vim_free(y_current->y_array);
+ array = y_current->y_array =
+ (char_u **)alloc((unsigned)(limit * sizeof(char_u *)));
+ str = skipwhite(str);
+ if (STRNCMP(str, "CHAR", 4) == 0)
+ y_current->y_type = MCHAR;
+#ifdef FEAT_VISUAL
+ else if (STRNCMP(str, "BLOCK", 5) == 0)
+ y_current->y_type = MBLOCK;
+#endif
+ else
+ y_current->y_type = MLINE;
+ /* get the block width; if it's missing we get a zero, which is OK */
+ str = skipwhite(skiptowhite(str));
+#ifdef FEAT_VISUAL
+ y_current->y_width = getdigits(&str);
+#else
+ (void)getdigits(&str);
+#endif
+ }
+
+ while (!(eof = viminfo_readline(virp))
+ && (virp->vir_line[0] == TAB || virp->vir_line[0] == '<'))
+ {
+ if (do_it)
+ {
+ if (size >= limit)
+ {
+ y_current->y_array = (char_u **)
+ alloc((unsigned)(limit * 2 * sizeof(char_u *)));
+ for (i = 0; i < limit; i++)
+ y_current->y_array[i] = array[i];
+ vim_free(array);
+ limit *= 2;
+ array = y_current->y_array;
+ }
+ str = viminfo_readstring(virp, 1, TRUE);
+ if (str != NULL)
+ array[size++] = str;
+ else
+ do_it = FALSE;
+ }
+ }
+ if (do_it)
+ {
+ if (size == 0)
+ {
+ vim_free(array);
+ y_current->y_array = NULL;
+ }
+ else if (size < limit)
+ {
+ y_current->y_array =
+ (char_u **)alloc((unsigned)(size * sizeof(char_u *)));
+ for (i = 0; i < size; i++)
+ y_current->y_array[i] = array[i];
+ vim_free(array);
+ }
+ y_current->y_size = size;
+ }
+ return eof;
+}
+
+ void
+write_viminfo_registers(fp)
+ FILE *fp;
+{
+ int i, j;
+ char_u *type;
+ char_u c;
+ int num_lines;
+ int max_num_lines;
+ int max_kbyte;
+ long len;
+
+ fprintf(fp, _("\n# Registers:\n"));
+
+ /* Get '<' value, use old '"' value if '<' is not found. */
+ max_num_lines = get_viminfo_parameter('<');
+ if (max_num_lines < 0)
+ max_num_lines = get_viminfo_parameter('"');
+ if (max_num_lines == 0)
+ return;
+ max_kbyte = get_viminfo_parameter('s');
+ if (max_kbyte == 0)
+ return;
+ for (i = 0; i < NUM_REGISTERS; i++)
+ {
+ if (y_regs[i].y_array == NULL)
+ continue;
+#ifdef FEAT_CLIPBOARD
+ /* Skip '*'/'+' register, we don't want them back next time */
+ if (i == STAR_REGISTER || i == PLUS_REGISTER)
+ continue;
+#endif
+#ifdef FEAT_DND
+ /* Neither do we want the '~' register */
+ if (i == TILDE_REGISTER)
+ continue;
+#endif
+ num_lines = y_regs[i].y_size;
+ if (max_kbyte > 0)
+ {
+ /* Skip register if there is more text than the maximum size. */
+ len = 0;
+ for (j = 0; j < num_lines; j++)
+ len += STRLEN(y_regs[i].y_array[j]) + 1L;
+ if (len > (long)max_kbyte * 1024L)
+ continue;
+ }
+
+ switch (y_regs[i].y_type)
+ {
+ case MLINE:
+ type = (char_u *)"LINE";
+ break;
+ case MCHAR:
+ type = (char_u *)"CHAR";
+ break;
+#ifdef FEAT_VISUAL
+ case MBLOCK:
+ type = (char_u *)"BLOCK";
+ break;
+#endif
+ default:
+ sprintf((char *)IObuff, _("E574: Unknown register type %d"),
+ y_regs[i].y_type);
+ emsg(IObuff);
+ type = (char_u *)"LINE";
+ break;
+ }
+ if (y_previous == &y_regs[i])
+ fprintf(fp, "\"");
+ c = get_register_name(i);
+ fprintf(fp, "\"%c\t%s\t%d\n", c, type,
+#ifdef FEAT_VISUAL
+ (int)y_regs[i].y_width
+#else
+ 0
+#endif
+ );
+
+ /* If max_num_lines < 0, then we save ALL the lines in the register */
+ if (max_num_lines > 0 && num_lines > max_num_lines)
+ num_lines = max_num_lines;
+ for (j = 0; j < num_lines; j++)
+ {
+ putc('\t', fp);
+ viminfo_writestring(fp, y_regs[i].y_array[j]);
+ }
+ }
+}
+#endif /* FEAT_VIMINFO */
+
+#if defined(FEAT_CLIPBOARD) || defined(PROTO)
+/*
+ * SELECTION / PRIMARY ('*')
+ *
+ * Text selection stuff that uses the GUI selection register '*'. When using a
+ * GUI this may be text from another window, otherwise it is the last text we
+ * had highlighted with VIsual mode. With mouse support, clicking the middle
+ * button performs the paste, otherwise you will need to do <"*p>. "
+ * If not under X, it is synonymous with the clipboard register '+'.
+ *
+ * X CLIPBOARD ('+')
+ *
+ * Text selection stuff that uses the GUI clipboard register '+'.
+ * Under X, this matches the standard cut/paste buffer CLIPBOARD selection.
+ * It will be used for unnamed cut/pasting is 'clipboard' contains "unnamed",
+ * otherwise you will need to do <"+p>. "
+ * If not under X, it is synonymous with the selection register '*'.
+ */
+
+/*
+ * Routine to export any final X selection we had to the environment
+ * so that the text is still available after vim has exited. X selections
+ * only exist while the owning application exists, so we write to the
+ * permanent (while X runs) store CUT_BUFFER0.
+ * Dump the CLIPBOARD selection if we own it (it's logically the more
+ * 'permanent' of the two), otherwise the PRIMARY one.
+ * For now, use a hard-coded sanity limit of 1Mb of data.
+ */
+#if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
+ void
+x11_export_final_selection()
+{
+ Display *dpy;
+ char_u *str = NULL;
+ long_u len = 0;
+ int motion_type = -1;
+
+# ifdef FEAT_GUI
+ if (gui.in_use)
+ dpy = X_DISPLAY;
+ else
+# endif
+# ifdef FEAT_XCLIPBOARD
+ dpy = xterm_dpy;
+# else
+ return;
+# endif
+
+ /* Get selection to export */
+ if (clip_plus.owned)
+ motion_type = clip_convert_selection(&str, &len, &clip_plus);
+ else if (clip_star.owned)
+ motion_type = clip_convert_selection(&str, &len, &clip_star);
+
+ /* Check it's OK */
+ if (dpy != NULL && str != NULL && motion_type >= 0
+ && len < 1024*1024 && len > 0)
+ {
+ XStoreBuffer(dpy, (char *)str, (int)len, 0);
+ XFlush(dpy);
+ }
+
+ vim_free(str);
+}
+#endif
+
+ void
+clip_free_selection(cbd)
+ VimClipboard *cbd;
+{
+ struct yankreg *y_ptr = y_current;
+
+ if (cbd == &clip_plus)
+ y_current = &y_regs[PLUS_REGISTER];
+ else
+ y_current = &y_regs[STAR_REGISTER];
+ free_yank_all();
+ y_current->y_size = 0;
+ y_current = y_ptr;
+}
+
+/*
+ * Get the selected text and put it in the gui selection register '*' or '+'.
+ */
+ void
+clip_get_selection(cbd)
+ VimClipboard *cbd;
+{
+ struct yankreg *old_y_previous, *old_y_current;
+ pos_T old_cursor;
+#ifdef FEAT_VISUAL
+ pos_T old_visual;
+ int old_visual_mode;
+#endif
+ colnr_T old_curswant;
+ int old_set_curswant;
+ pos_T old_op_start, old_op_end;
+ oparg_T oa;
+ cmdarg_T ca;
+
+ if (cbd->owned)
+ {
+ if ((cbd == &clip_plus && y_regs[PLUS_REGISTER].y_array != NULL)
+ || (cbd == &clip_star && y_regs[STAR_REGISTER].y_array != NULL))
+ return;
+
+ /* Get the text between clip_star.start & clip_star.end */
+ old_y_previous = y_previous;
+ old_y_current = y_current;
+ old_cursor = curwin->w_cursor;
+ old_curswant = curwin->w_curswant;
+ old_set_curswant = curwin->w_set_curswant;
+ old_op_start = curbuf->b_op_start;
+ old_op_end = curbuf->b_op_end;
+#ifdef FEAT_VISUAL
+ old_visual = VIsual;
+ old_visual_mode = VIsual_mode;
+#endif
+ clear_oparg(&oa);
+ oa.regname = (cbd == &clip_plus ? '+' : '*');
+ oa.op_type = OP_YANK;
+ vim_memset(&ca, 0, sizeof(ca));
+ ca.oap = &oa;
+ ca.cmdchar = 'y';
+ ca.count1 = 1;
+ ca.retval = CA_NO_ADJ_OP_END;
+ do_pending_operator(&ca, 0, TRUE);
+ y_previous = old_y_previous;
+ y_current = old_y_current;
+ curwin->w_cursor = old_cursor;
+ curwin->w_curswant = old_curswant;
+ curwin->w_set_curswant = old_set_curswant;
+ curbuf->b_op_start = old_op_start;
+ curbuf->b_op_end = old_op_end;
+#ifdef FEAT_VISUAL
+ VIsual = old_visual;
+ VIsual_mode = old_visual_mode;
+#endif
+ }
+ else
+ {
+ clip_free_selection(cbd);
+
+ /* Try to get selected text from another window */
+ clip_gen_request_selection(cbd);
+ }
+}
+
+/* Convert from the GUI selection string into the '*'/'+' register */
+ void
+clip_yank_selection(type, str, len, cbd)
+ int type;
+ char_u *str;
+ long len;
+ VimClipboard *cbd;
+{
+ struct yankreg *y_ptr;
+
+ if (cbd == &clip_plus)
+ y_ptr = &y_regs[PLUS_REGISTER];
+ else
+ y_ptr = &y_regs[STAR_REGISTER];
+
+ clip_free_selection(cbd);
+
+ str_to_reg(y_ptr, type, str, len, 0L);
+}
+
+/*
+ * Convert the '*'/'+' register into a GUI selection string returned in *str
+ * with length *len.
+ * Returns the motion type, or -1 for failure.
+ */
+ int
+clip_convert_selection(str, len, cbd)
+ char_u **str;
+ long_u *len;
+ VimClipboard *cbd;
+{
+ char_u *p;
+ int lnum;
+ int i, j;
+ int_u eolsize;
+ struct yankreg *y_ptr;
+
+ if (cbd == &clip_plus)
+ y_ptr = &y_regs[PLUS_REGISTER];
+ else
+ y_ptr = &y_regs[STAR_REGISTER];
+
+#ifdef USE_CRNL
+ eolsize = 2;
+#else
+ eolsize = 1;
+#endif
+
+ *str = NULL;
+ *len = 0;
+ if (y_ptr->y_array == NULL)
+ return -1;
+
+ for (i = 0; i < y_ptr->y_size; i++)
+ *len += (long_u)STRLEN(y_ptr->y_array[i]) + eolsize;
+
+ /*
+ * Don't want newline character at end of last line if we're in MCHAR mode.
+ */
+ if (y_ptr->y_type == MCHAR && *len >= eolsize)
+ *len -= eolsize;
+
+ p = *str = lalloc(*len + 1, TRUE); /* add one to avoid zero */
+ if (p == NULL)
+ return -1;
+ lnum = 0;
+ for (i = 0, j = 0; i < (int)*len; i++, j++)
+ {
+ if (y_ptr->y_array[lnum][j] == '\n')
+ p[i] = NUL;
+ else if (y_ptr->y_array[lnum][j] == NUL)
+ {
+#ifdef USE_CRNL
+ p[i++] = '\r';
+#endif
+#ifdef USE_CR
+ p[i] = '\r';
+#else
+ p[i] = '\n';
+#endif
+ lnum++;
+ j = -1;
+ }
+ else
+ p[i] = y_ptr->y_array[lnum][j];
+ }
+ return y_ptr->y_type;
+}
+
+
+# if defined(FEAT_VISUAL) || defined(FEAT_EVAL)
+/*
+ * If we have written to a clipboard register, send the text to the clipboard.
+ */
+ static void
+may_set_selection()
+{
+ if (y_current == &(y_regs[STAR_REGISTER]) && clip_star.available)
+ {
+ clip_own_selection(&clip_star);
+ clip_gen_set_selection(&clip_star);
+ }
+ else if (y_current == &(y_regs[PLUS_REGISTER]) && clip_plus.available)
+ {
+ clip_own_selection(&clip_plus);
+ clip_gen_set_selection(&clip_plus);
+ }
+}
+# endif
+
+#endif /* FEAT_CLIPBOARD || PROTO */
+
+
+#if defined(FEAT_DND) || defined(PROTO)
+/*
+ * Replace the contents of the '~' register with str.
+ */
+ void
+dnd_yank_drag_data(str, len)
+ char_u *str;
+ long len;
+{
+ struct yankreg *curr;
+
+ curr = y_current;
+ y_current = &y_regs[TILDE_REGISTER];
+ free_yank_all();
+ str_to_reg(y_current, MCHAR, str, len, 0L);
+ y_current = curr;
+}
+#endif
+
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return the type of a register.
+ * Used for getregtype()
+ * Returns MAUTO for error.
+ */
+ char_u
+get_reg_type(regname, reglen)
+ int regname;
+ long *reglen;
+{
+ switch (regname)
+ {
+ case '%': /* file name */
+ case '#': /* alternate file name */
+ case '=': /* expression */
+ case ':': /* last command line */
+ case '/': /* last search-pattern */
+ case '.': /* last inserted text */
+#ifdef FEAT_SEARCHPATH
+ case Ctrl_F: /* Filename under cursor */
+ case Ctrl_P: /* Path under cursor, expand via "path" */
+#endif
+ case Ctrl_W: /* word under cursor */
+ case Ctrl_A: /* WORD (mnemonic All) under cursor */
+ case '_': /* black hole: always empty */
+ return MCHAR;
+ }
+
+#ifdef FEAT_CLIPBOARD
+ regname = may_get_selection(regname);
+#endif
+
+ /* Should we check for a valid name? */
+ get_yank_register(regname, FALSE);
+
+ if (y_current->y_array != NULL)
+ {
+#ifdef FEAT_VISUAL
+ if (reglen != NULL && y_current->y_type == MBLOCK)
+ *reglen = y_current->y_width;
+#endif
+ return y_current->y_type;
+ }
+ return MAUTO;
+}
+
+/*
+ * Return the contents of a register as a single allocated string.
+ * Used for "@r" in expressions and for getreg().
+ * Returns NULL for error.
+ */
+ char_u *
+get_reg_contents(regname, allowexpr)
+ int regname;
+ int allowexpr; /* allow "=" register. */
+{
+ long i;
+ char_u *retval;
+ int allocated;
+ long len;
+
+ /* Don't allow using an expression register inside an expression */
+ if (regname == '=')
+ {
+ if (allowexpr)
+ return get_expr_line();
+ return NULL;
+ }
+
+ if (regname == '@') /* "@@" is used for unnamed register */
+ regname = '"';
+
+ /* check for valid regname */
+ if (regname != NUL && !valid_yank_reg(regname, FALSE))
+ return NULL;
+
+#ifdef FEAT_CLIPBOARD
+ regname = may_get_selection(regname);
+#endif
+
+ if (get_spec_reg(regname, &retval, &allocated, FALSE))
+ {
+ if (retval == NULL)
+ return NULL;
+ if (!allocated)
+ retval = vim_strsave(retval);
+ return retval;
+ }
+
+ get_yank_register(regname, FALSE);
+ if (y_current->y_array == NULL)
+ return NULL;
+
+ /*
+ * Compute length of resulting string.
+ */
+ len = 0;
+ for (i = 0; i < y_current->y_size; ++i)
+ {
+ len += (long)STRLEN(y_current->y_array[i]);
+ /*
+ * Insert a newline between lines and after last line if
+ * y_type is MLINE.
+ */
+ if (y_current->y_type == MLINE || i < y_current->y_size - 1)
+ ++len;
+ }
+
+ retval = lalloc(len + 1, TRUE);
+
+ /*
+ * Copy the lines of the yank register into the string.
+ */
+ if (retval != NULL)
+ {
+ len = 0;
+ for (i = 0; i < y_current->y_size; ++i)
+ {
+ STRCPY(retval + len, y_current->y_array[i]);
+ len += (long)STRLEN(retval + len);
+
+ /*
+ * Insert a NL between lines and after the last line if y_type is
+ * MLINE.
+ */
+ if (y_current->y_type == MLINE || i < y_current->y_size - 1)
+ retval[len++] = '\n';
+ }
+ retval[len] = NUL;
+ }
+
+ return retval;
+}
+
+/*
+ * Store string "str" in register "name".
+ * "maxlen" is the maximum number of bytes to use, -1 for all bytes.
+ * If "must_append" is TRUE, always append to the register. Otherwise append
+ * if "name" is an uppercase letter.
+ * Note: "maxlen" and "must_append" don't work for the "/" register.
+ * Careful: 'str' is modified, you may have to use a copy!
+ * If "str" ends in '\n' or '\r', use linewise, otherwise use characterwise.
+ */
+ void
+write_reg_contents(name, str, maxlen, must_append)
+ int name;
+ char_u *str;
+ int maxlen;
+ int must_append;
+{
+ write_reg_contents_ex(name, str, maxlen, must_append, MAUTO, 0L);
+}
+
+ void
+write_reg_contents_ex(name, str, maxlen, must_append, yank_type, block_len)
+ int name;
+ char_u *str;
+ int maxlen;
+ int must_append;
+ int yank_type;
+ long block_len;
+{
+ struct yankreg *old_y_previous, *old_y_current;
+ long len;
+
+ /* Special case: '/' search pattern */
+ if (name == '/')
+ {
+ set_last_search_pat(str, RE_SEARCH, TRUE, TRUE);
+ return;
+ }
+
+ if (!valid_yank_reg(name, TRUE)) /* check for valid reg name */
+ {
+ EMSG2(_("E354: Invalid register name: '%s'"), transchar(name));
+ return;
+ }
+
+ if (name == '_') /* black hole: nothing to do */
+ return;
+
+ /* Don't want to change the current (unnamed) register */
+ old_y_previous = y_previous;
+ old_y_current = y_current;
+
+ get_yank_register(name, TRUE);
+ if (!y_append && !must_append)
+ free_yank_all();
+ if (maxlen >= 0)
+ len = maxlen;
+ else
+ len = (long)STRLEN(str);
+#ifndef FEAT_VISUAL
+ /* Just in case - make sure we don't use MBLOCK */
+ if (yank_type == MBLOCK)
+ yank_type = MAUTO;
+#endif
+ if (yank_type == MAUTO)
+ yank_type = ((len > 0 && (str[len - 1] == '\n' || str[len - 1] == '\r'))
+ ? MLINE : MCHAR);
+ str_to_reg(y_current, yank_type, str, len, block_len);
+
+# ifdef FEAT_CLIPBOARD
+ /* Send text of clipboard register to the clipboard. */
+ may_set_selection();
+# endif
+
+ /* ':let @" = "val"' should change the meaning of the "" register */
+ if (name != '"')
+ y_previous = old_y_previous;
+ y_current = old_y_current;
+}
+#endif /* FEAT_EVAL */
+
+#if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
+/*
+ * Put a string into a register. When the register is not empty, the string
+ * is appended.
+ */
+ static void
+str_to_reg(y_ptr, type, str, len, blocklen)
+ struct yankreg *y_ptr; /* pointer to yank register */
+ int type; /* MCHAR, MLINE or MBLOCK */
+ char_u *str; /* string to put in register */
+ long len; /* length of string */
+ long blocklen; /* width of Visual block */
+{
+ int lnum;
+ long start;
+ long i;
+ int extra;
+ int newlines; /* number of lines added */
+ int extraline = 0; /* extra line at the end */
+ int append = FALSE; /* append to last line in register */
+ char_u *s;
+ char_u **pp;
+#ifdef FEAT_VISUAL
+ long maxlen;
+#endif
+
+ if (y_ptr->y_array == NULL) /* NULL means emtpy register */
+ y_ptr->y_size = 0;
+
+ /*
+ * Count the number of lines within the string
+ */
+ newlines = 0;
+ for (i = 0; i < len; i++)
+ if (str[i] == '\n')
+ ++newlines;
+ if (type == MCHAR || len == 0 || str[len - 1] != '\n')
+ {
+ extraline = 1;
+ ++newlines; /* count extra newline at the end */
+ }
+ if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR)
+ {
+ append = TRUE;
+ --newlines; /* uncount newline when appending first line */
+ }
+
+ /*
+ * Allocate an array to hold the pointers to the new register lines.
+ * If the register was not empty, move the existing lines to the new array.
+ */
+ pp = (char_u **)lalloc_clear((y_ptr->y_size + newlines)
+ * sizeof(char_u *), TRUE);
+ if (pp == NULL) /* out of memory */
+ return;
+ for (lnum = 0; lnum < y_ptr->y_size; ++lnum)
+ pp[lnum] = y_ptr->y_array[lnum];
+ vim_free(y_ptr->y_array);
+ y_ptr->y_array = pp;
+#ifdef FEAT_VISUAL
+ maxlen = 0;
+#endif
+
+ /*
+ * Find the end of each line and save it into the array.
+ */
+ for (start = 0; start < len + extraline; start += i + 1)
+ {
+ for (i = start; i < len; ++i) /* find the end of the line */
+ if (str[i] == '\n')
+ break;
+ i -= start; /* i is now length of line */
+#ifdef FEAT_VISUAL
+ if (i > maxlen)
+ maxlen = i;
+#endif
+ if (append)
+ {
+ --lnum;
+ extra = (int)STRLEN(y_ptr->y_array[lnum]);
+ }
+ else
+ extra = 0;
+ s = alloc((unsigned)(i + extra + 1));
+ if (s == NULL)
+ break;
+ if (extra)
+ mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra);
+ if (append)
+ vim_free(y_ptr->y_array[lnum]);
+ if (i)
+ mch_memmove(s + extra, str + start, (size_t)i);
+ extra += i;
+ s[extra] = NUL;
+ y_ptr->y_array[lnum++] = s;
+ while (--extra >= 0)
+ {
+ if (*s == NUL)
+ *s = '\n'; /* replace NUL with newline */
+ ++s;
+ }
+ append = FALSE; /* only first line is appended */
+ }
+ y_ptr->y_type = type;
+ y_ptr->y_size = lnum;
+# ifdef FEAT_VISUAL
+ if (type == MBLOCK)
+ y_ptr->y_width = (blocklen < 0 ? maxlen - 1 : blocklen);
+ else
+ y_ptr->y_width = 0;
+# endif
+}
+#endif /* FEAT_CLIPBOARD || FEAT_EVAL || PROTO */
+
+ void
+clear_oparg(oap)
+ oparg_T *oap;
+{
+ vim_memset(oap, 0, sizeof(oparg_T));
+}
+
+static long line_count_info __ARGS((char_u *line, long *wc, long limit, int eol_size));
+
+/*
+ * Count the number of characters and "words" in a line.
+ *
+ * "Words" are counted by looking for boundaries between non-space and
+ * space characters. (it seems to produce results that match 'wc'.)
+ *
+ * Return value is character count; word count for the line is ADDED
+ * to "*wc".
+ *
+ * The function will only examine the first "limit" characters in the
+ * line, stopping if it encounters an end-of-line (NUL byte). In that
+ * case, eol_size will be added to the character count to account for
+ * the size of the EOL character.
+ */
+ static long
+line_count_info(line, wc, limit, eol_size)
+ char_u *line;
+ long *wc;
+ long limit;
+ int eol_size;
+{
+ long i, words = 0;
+ int is_word = 0;
+
+ for (i = 0; line[i] && i < limit; i++)
+ {
+ if (is_word)
+ {
+ if (vim_isspace(line[i]))
+ {
+ words++;
+ is_word = 0;
+ }
+ }
+ else if (!vim_isspace(line[i]))
+ is_word = 1;
+ }
+
+ if (is_word)
+ words++;
+ *wc += words;
+
+ /* Add eol_size if the end of line was reached before hitting limit. */
+ if (!line[i] && i < limit)
+ i += eol_size;
+ return i;
+}
+
+/*
+ * Give some info about the position of the cursor (for "g CTRL-G").
+ * In Visual mode, give some info about the selected region. (In this case,
+ * the *_count_cursor variables store running totals for the selection.)
+ */
+ void
+cursor_pos_info()
+{
+ char_u *p;
+ char_u buf1[20];
+ char_u buf2[20];
+ linenr_T lnum;
+ long char_count = 0;
+ long char_count_cursor = 0;
+ int eol_size;
+ long last_check = 100000L;
+ long word_count = 0;
+ long word_count_cursor = 0;
+#ifdef FEAT_VISUAL
+ long line_count_selected = 0;
+ pos_T min_pos, max_pos;
+ oparg_T oparg;
+ struct block_def bd;
+#endif
+
+ /*
+ * Compute the length of the file in characters.
+ */
+ if (curbuf->b_ml.ml_flags & ML_EMPTY)
+ {
+ MSG(_(no_lines_msg));
+ }
+ else
+ {
+ if (get_fileformat(curbuf) == EOL_DOS)
+ eol_size = 2;
+ else
+ eol_size = 1;
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ if (lt(VIsual, curwin->w_cursor))
+ {
+ min_pos = VIsual;
+ max_pos = curwin->w_cursor;
+ }
+ else
+ {
+ min_pos = curwin->w_cursor;
+ max_pos = VIsual;
+ }
+ if (*p_sel == 'e' && max_pos.col > 0)
+ --max_pos.col;
+
+ if (VIsual_mode == Ctrl_V)
+ {
+ oparg.is_VIsual = 1;
+ oparg.block_mode = TRUE;
+ oparg.op_type = OP_NOP;
+ getvcols(curwin, &min_pos, &max_pos,
+ &oparg.start_vcol, &oparg.end_vcol);
+ /* Swap the start, end vcol if needed */
+ if (oparg.end_vcol < oparg.start_vcol)
+ {
+ oparg.end_vcol += oparg.start_vcol;
+ oparg.start_vcol = oparg.end_vcol - oparg.start_vcol;
+ oparg.end_vcol -= oparg.start_vcol;
+ }
+ }
+ line_count_selected = max_pos.lnum - min_pos.lnum + 1;
+ }
+#endif
+
+ for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
+ {
+ /* Check for a CTRL-C every 100000 characters. */
+ if (char_count > last_check)
+ {
+ ui_breakcheck();
+ if (got_int)
+ return;
+ last_check = char_count + 100000L;
+ }
+
+#ifdef FEAT_VISUAL
+ /* Do extra processing for VIsual mode. */
+ if (VIsual_active
+ && lnum >= min_pos.lnum && lnum <= max_pos.lnum)
+ {
+ switch (VIsual_mode)
+ {
+ case Ctrl_V:
+# ifdef FEAT_VIRTUALEDIT
+ virtual_op = virtual_active();
+# endif
+ block_prep(&oparg, &bd, lnum, 0);
+# ifdef FEAT_VIRTUALEDIT
+ virtual_op = MAYBE;
+# endif
+ char_count_cursor += line_count_info(bd.textstart,
+ &word_count_cursor, (long)bd.textlen, eol_size);
+ break;
+ case 'V':
+ char_count_cursor += line_count_info(ml_get(lnum),
+ &word_count_cursor, (long)MAXCOL, eol_size);
+ break;
+ case 'v':
+ {
+ colnr_T start_col = (lnum == min_pos.lnum)
+ ? min_pos.col : 0;
+ colnr_T end_col = (lnum == max_pos.lnum)
+ ? max_pos.col - start_col + 1 : MAXCOL;
+
+ char_count_cursor +=
+ line_count_info(ml_get(lnum) + start_col,
+ &word_count_cursor, (long)end_col, eol_size);
+ }
+ break;
+ }
+ }
+ else
+#endif
+ {
+ /* In non-visual mode, check for the line the cursor is on */
+ if (lnum == curwin->w_cursor.lnum)
+ {
+ word_count_cursor += word_count;
+ char_count_cursor = char_count +
+ line_count_info(ml_get(lnum), &word_count_cursor,
+ (long)(curwin->w_cursor.col + 1), eol_size);
+ }
+ }
+ /* Add to the running totals */
+ char_count += line_count_info(ml_get(lnum), &word_count,
+ (long)MAXCOL, eol_size);
+ }
+
+ /* Correction for when last line doesn't have an EOL. */
+ if (!curbuf->b_p_eol && curbuf->b_p_bin)
+ char_count -= eol_size;
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ if (VIsual_mode == Ctrl_V)
+ {
+ getvcols(curwin, &min_pos, &max_pos, &min_pos.col,
+ &max_pos.col);
+ sprintf((char *)buf1, _("%ld Cols; "),
+ (long)(oparg.end_vcol - oparg.start_vcol + 1));
+ }
+ else
+ buf1[0] = NUL;
+
+ sprintf((char *)IObuff,
+ _("Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"),
+ buf1, line_count_selected,
+ (long)curbuf->b_ml.ml_line_count,
+ word_count_cursor, word_count,
+ char_count_cursor, char_count);
+ }
+ else
+#endif
+ {
+ p = ml_get_curline();
+ validate_virtcol();
+ col_print(buf1, (int)curwin->w_cursor.col + 1,
+ (int)curwin->w_virtcol + 1);
+ col_print(buf2, (int)STRLEN(p), linetabsize(p));
+
+ sprintf((char *)IObuff,
+ _("Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"),
+ (char *)buf1, (char *)buf2,
+ (long)curwin->w_cursor.lnum,
+ (long)curbuf->b_ml.ml_line_count,
+ word_count_cursor, word_count,
+ char_count_cursor, char_count);
+ }
+
+#ifdef FEAT_MBYTE
+ char_count = bomb_size();
+ if (char_count > 0)
+ sprintf((char *)IObuff + STRLEN(IObuff), _("(+%ld for BOM)"),
+ char_count);
+#endif
+ /* Don't shorten this message, the user asked for it. */
+ p = p_shm;
+ p_shm = (char_u *)"";
+ msg(IObuff);
+ p_shm = p;
+ }
+}
diff --git a/src/option.c b/src/option.c
new file mode 100644
index 000000000..b87005e19
--- /dev/null
+++ b/src/option.c
@@ -0,0 +1,9383 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * Code to handle user-settable options. This is all pretty much table-
+ * driven. Checklist for adding a new option:
+ * - Put it in the options array below (copy an existing entry).
+ * - For a global option: Add a variable for it in option.h.
+ * - For a buffer or window local option:
+ * - Add a PV_XX entry to the enum below.
+ * - Add a variable to the window or buffer struct in structs.h.
+ * - For a window option, add some code to copy_winopt().
+ * - For a buffer option, add some code to buf_copy_options().
+ * - For a buffer string option, add code to check_buf_options().
+ * - If it's a numeric option, add any necessary bounds checks to do_set().
+ * - If it's a list of flags, add some code in do_set(), search for WW_ALL.
+ * - When adding an option with expansion (P_EXPAND), but with a different
+ * default for Vi and Vim (no P_VI_DEF), add some code at VIMEXP.
+ * - Add documentation! One line in doc/help.txt, full description in
+ * options.txt, and any other related places.
+ * - Add an entry in runtime/optwin.vim.
+ * When making changes:
+ * - Adjust the help for the option in doc/option.txt.
+ * - When an entry has the P_VIM flag, or is lacking the P_VI_DEF flag, add a
+ * comment at the help for the 'compatible' option.
+ */
+
+#define IN_OPTION_C
+#include "vim.h"
+
+/*
+ * The options that are local to a window or buffer have "indir" set to one of
+ * these values. Special values:
+ * PV_NONE: global option.
+ * PV_BOTH is added: global option which also has a local value.
+ */
+#define PV_BOTH 0x1000
+#define OPT_BOTH(x) (idopt_T)(PV_BOTH + (int)(x))
+
+typedef enum
+{
+ PV_NONE = 0
+ , PV_AI
+ , PV_AR
+ , PV_ARAB
+ , PV_BH
+ , PV_BIN
+ , PV_BL
+ , PV_BOMB
+ , PV_BT
+ , PV_CI
+ , PV_CIN
+ , PV_CINK
+ , PV_CINO
+ , PV_CINW
+ , PV_CMS
+ , PV_COM
+ , PV_CPT
+ , PV_DEF
+ , PV_DICT
+ , PV_DIFF
+ , PV_EFM
+ , PV_EOL
+ , PV_EP
+ , PV_ET
+ , PV_FDC
+ , PV_FDE
+ , PV_FDI
+ , PV_FDL
+ , PV_FDM
+ , PV_FDN
+ , PV_FDT
+ , PV_FEN
+ , PV_FENC
+ , PV_FF
+ , PV_FML
+ , PV_FMR
+ , PV_FO
+ , PV_FT
+ , PV_GP
+ , PV_IMI
+ , PV_IMS
+ , PV_INC
+ , PV_INDE
+ , PV_INDK
+ , PV_INEX
+ , PV_INF
+ , PV_ISK
+ , PV_KEY
+ , PV_KMAP
+ , PV_KP
+ , PV_LBR
+ , PV_LISP
+ , PV_LIST
+ , PV_MA
+ , PV_ML
+ , PV_MOD
+ , PV_MP
+ , PV_MPS
+ , PV_NF
+ , PV_NU
+ , PV_OFT
+ , PV_PATH
+ , PV_PI
+ , PV_PVW
+ , PV_RL
+ , PV_RLC
+ , PV_RO
+ , PV_SCBIND
+ , PV_SCROLL
+ , PV_SI
+ , PV_SN
+ , PV_STS
+ , PV_SUA
+ , PV_SW
+ , PV_SWF
+ , PV_SYN
+ , PV_TAGS
+ , PV_TS
+ , PV_TSR
+ , PV_TW
+ , PV_TX
+ , PV_WFH
+ , PV_WM
+ , PV_WRAP
+} idopt_T;
+
+/*
+ * Options local to a window have a value local to a buffer and global to all
+ * buffers. Indicate this by setting "var" to VAR_WIN.
+ */
+#define VAR_WIN ((char_u *)-1)
+
+/*
+ * These the global values for options which are also local to a buffer.
+ * Only to be used in option.c!
+ */
+static int p_ai;
+static int p_bin;
+#ifdef FEAT_MBYTE
+static int p_bomb;
+#endif
+#if defined(FEAT_QUICKFIX)
+static char_u *p_bh;
+static char_u *p_bt;
+#endif
+static int p_bl;
+static int p_ci;
+#ifdef FEAT_CINDENT
+static int p_cin;
+static char_u *p_cink;
+static char_u *p_cino;
+#endif
+#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
+static char_u *p_cinw;
+#endif
+#ifdef FEAT_COMMENTS
+static char_u *p_com;
+#endif
+#ifdef FEAT_FOLDING
+static char_u *p_cms;
+#endif
+#ifdef FEAT_INS_EXPAND
+static char_u *p_cpt;
+#endif
+static int p_eol;
+static int p_et;
+#ifdef FEAT_MBYTE
+static char_u *p_fenc;
+#endif
+static char_u *p_ff;
+static char_u *p_fo;
+#ifdef FEAT_AUTOCMD
+static char_u *p_ft;
+#endif
+static long p_iminsert;
+static long p_imsearch;
+#if defined(FEAT_FIND_ID) && defined(FEAT_EVAL)
+static char_u *p_inex;
+#endif
+#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
+static char_u *p_inde;
+static char_u *p_indk;
+#endif
+static int p_inf;
+static char_u *p_isk;
+#ifdef FEAT_CRYPT
+static char_u *p_key;
+#endif
+#ifdef FEAT_LISP
+static int p_lisp;
+#endif
+static int p_ml;
+static int p_ma;
+static int p_mod;
+static char_u *p_mps;
+static char_u *p_nf;
+#ifdef FEAT_OSFILETYPE
+static char_u *p_oft;
+#endif
+static int p_pi;
+static int p_ro;
+#ifdef FEAT_SMARTINDENT
+static int p_si;
+#endif
+#ifndef SHORT_FNAME
+static int p_sn;
+#endif
+static long p_sts;
+#if defined(FEAT_SEARCHPATH)
+static char_u *p_sua;
+#endif
+static long p_sw;
+static int p_swf;
+#ifdef FEAT_SYN_HL
+static char_u *p_syn;
+#endif
+static long p_ts;
+static long p_tw;
+static int p_tx;
+static long p_wm;
+#ifdef FEAT_KEYMAP
+static char_u *p_keymap;
+#endif
+
+/* Saved values for when 'bin' is set. */
+static int p_et_nobin;
+static int p_ml_nobin;
+static long p_tw_nobin;
+static long p_wm_nobin;
+
+/* Saved values for when 'paste' is set */
+static long p_tw_nopaste;
+static long p_wm_nopaste;
+static long p_sts_nopaste;
+static int p_ai_nopaste;
+
+struct vimoption
+{
+ char *fullname; /* full option name */
+ char *shortname; /* permissible abbreviation */
+ long_u flags; /* see below */
+ char_u *var; /* global option: pointer to variable;
+ * window-local option: VAR_WIN;
+ * buffer-local option: global value */
+ idopt_T indir; /* global option: PV_NONE;
+ * local option: indirect option index */
+ char_u *def_val[2]; /* default values for variable (vi and vim) */
+#ifdef FEAT_EVAL
+ scid_T scriptID; /* script in which the option was last set */
+#endif
+};
+
+#define VI_DEFAULT 0 /* def_val[VI_DEFAULT] is Vi default value */
+#define VIM_DEFAULT 1 /* def_val[VIM_DEFAULT] is Vim default value */
+
+/*
+ * Flags
+ */
+#define P_BOOL 0x01 /* the option is boolean */
+#define P_NUM 0x02 /* the option is numeric */
+#define P_STRING 0x04 /* the option is a string */
+#define P_ALLOCED 0x08 /* the string option is in allocated memory,
+ must use vim_free() when assigning new
+ value. Not set if default is the same. */
+#define P_EXPAND 0x10 /* environment expansion. NOTE: P_EXPAND can
+ never be used for local or hidden options! */
+#define P_NODEFAULT 0x40 /* don't set to default value */
+#define P_DEF_ALLOCED 0x80 /* default value is in allocated memory, must
+ use vim_free() when assigning new value */
+#define P_WAS_SET 0x100 /* option has been set/reset */
+#define P_NO_MKRC 0x200 /* don't include in :mkvimrc output */
+#define P_VI_DEF 0x400 /* Use Vi default for Vim */
+#define P_VIM 0x800 /* Vim option, reset when 'cp' set */
+
+ /* when option changed, what to display: */
+#define P_RSTAT 0x1000 /* redraw status lines */
+#define P_RWIN 0x2000 /* redraw current window */
+#define P_RBUF 0x4000 /* redraw current buffer */
+#define P_RALL 0x6000 /* redraw all windows */
+#define P_RCLR 0x7000 /* clear and redraw all */
+
+#define P_COMMA 0x8000 /* comma separated list */
+#define P_NODUP 0x10000L/* don't allow duplicate strings */
+#define P_FLAGLIST 0x20000L/* list of single-char flags */
+
+#define P_SECURE 0x40000L/* cannot change in modeline or secure mode */
+#define P_GETTEXT 0x80000L/* expand default value with _() */
+#define P_NOGLOB 0x100000L/* do not use local value for global vimrc */
+
+/*
+ * options[] is initialized here.
+ * The order of the options MUST be alphabetic for ":set all" and findoption().
+ * All option names MUST start with a lowercase letter (for findoption()).
+ * Exception: "t_" options are at the end.
+ * The options with a NULL variable are 'hidden': a set command for them is
+ * ignored and they are not printed.
+ */
+static struct vimoption
+#ifdef FEAT_GUI_W16
+ _far
+#endif
+ options[] =
+{
+ {"aleph", "al", P_NUM|P_VI_DEF,
+#ifdef FEAT_RIGHTLEFT
+ (char_u *)&p_aleph, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {
+#if (defined(MSDOS) || defined(WIN3264) || defined(OS2)) && !defined(FEAT_GUI_W32)
+ (char_u *)128L,
+#else
+ (char_u *)224L,
+#endif
+ (char_u *)0L}},
+ {"antialias", "anti", P_BOOL|P_VI_DEF|P_VIM|P_RCLR,
+#if defined(FEAT_GUI) && defined(MACOS_X)
+ (char_u *)&p_antialias, PV_NONE,
+ {(char_u *)FALSE, (char_u *)FALSE}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)FALSE}
+#endif
+ },
+ {"arabic", "arab", P_BOOL|P_VI_DEF|P_VIM,
+#ifdef FEAT_ARABIC
+ (char_u *)VAR_WIN, PV_ARAB,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"arabicshape", "arshape", P_BOOL|P_VI_DEF|P_VIM|P_RCLR,
+#ifdef FEAT_ARABIC
+ (char_u *)&p_arshape, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"allowrevins", "ari", P_BOOL|P_VI_DEF|P_VIM,
+#ifdef FEAT_RIGHTLEFT
+ (char_u *)&p_ari, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"altkeymap", "akm", P_BOOL|P_VI_DEF,
+#ifdef FEAT_FKMAP
+ (char_u *)&p_altkeymap, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"ambiwidth", "ambw", P_STRING|P_VI_DEF|P_RCLR,
+#if defined(FEAT_MBYTE)
+ (char_u *)&p_ambw, PV_NONE,
+ {(char_u *)"single", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+#if defined(FEAT_NETBEANS_INTG) || defined(FEAT_SUN_WORKSHOP)
+ {"autochdir", "acd", P_BOOL|P_VI_DEF,
+ (char_u *)&p_acd, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+#endif
+ {"autoindent", "ai", P_BOOL|P_VI_DEF,
+ (char_u *)&p_ai, PV_AI,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"autoprint", "ap", P_BOOL|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"autoread", "ar", P_BOOL|P_VI_DEF,
+ (char_u *)&p_ar, OPT_BOTH(PV_AR),
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"autowrite", "aw", P_BOOL|P_VI_DEF,
+ (char_u *)&p_aw, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"autowriteall","awa", P_BOOL|P_VI_DEF,
+ (char_u *)&p_awa, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"background", "bg", P_STRING|P_VI_DEF|P_RCLR,
+ (char_u *)&p_bg, PV_NONE,
+ {
+#if (defined(MSDOS) || defined(OS2) || defined(WIN3264)) && !defined(FEAT_GUI)
+ (char_u *)"dark",
+#else
+ (char_u *)"light",
+#endif
+ (char_u *)0L}},
+ {"backspace", "bs", P_STRING|P_VI_DEF|P_VIM|P_COMMA|P_NODUP,
+ (char_u *)&p_bs, PV_NONE,
+ {(char_u *)"", (char_u *)0L}},
+ {"backup", "bk", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_bk, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"backupcopy", "bkc", P_STRING|P_VIM|P_COMMA|P_NODUP,
+ (char_u *)&p_bkc, PV_NONE,
+#ifdef UNIX
+ {(char_u *)"yes", (char_u *)"auto"}
+#else
+ {(char_u *)"auto", (char_u *)"auto"}
+#endif
+ },
+ {"backupdir", "bdir", P_STRING|P_EXPAND|P_VI_DEF|P_COMMA|P_NODUP|P_SECURE,
+ (char_u *)&p_bdir, PV_NONE,
+ {(char_u *)DFLT_BDIR, (char_u *)0L}},
+ {"backupext", "bex", P_STRING|P_VI_DEF,
+ (char_u *)&p_bex, PV_NONE,
+ {
+#ifdef VMS
+ (char_u *)"_",
+#else
+ (char_u *)"~",
+#endif
+ (char_u *)0L}},
+ {"backupskip", "bsk", P_STRING|P_VI_DEF|P_COMMA,
+#ifdef FEAT_WILDIGN
+ (char_u *)&p_bsk, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+#ifdef FEAT_BEVAL
+ {"balloondelay","bdlay",P_NUM|P_VI_DEF,
+ (char_u *)&p_bdlay, PV_NONE,
+ {(char_u *)600L, (char_u *)0L}},
+#endif
+#if defined(FEAT_BEVAL) && (defined(FEAT_SUN_WORKSHOP) \
+ || defined(FEAT_NETBEANS_INTG))
+ {"ballooneval", "beval",P_BOOL|P_VI_DEF|P_NO_MKRC,
+ (char_u *)&p_beval, PV_NONE,
+ {(char_u*)FALSE, (char_u *)0L}},
+#endif
+ {"beautify", "bf", P_BOOL|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"binary", "bin", P_BOOL|P_VI_DEF|P_RSTAT,
+ (char_u *)&p_bin, PV_BIN,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"bioskey", "biosk",P_BOOL|P_VI_DEF,
+#ifdef MSDOS
+ (char_u *)&p_biosk, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"bomb", NULL, P_BOOL|P_NO_MKRC|P_VI_DEF|P_RSTAT,
+#ifdef FEAT_MBYTE
+ (char_u *)&p_bomb, PV_BOMB,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"breakat", "brk", P_STRING|P_VI_DEF|P_RALL|P_FLAGLIST,
+#ifdef FEAT_LINEBREAK
+ (char_u *)&p_breakat, PV_NONE,
+ {(char_u *)" \t!@*-+;:,./?", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"browsedir", "bsdir",P_STRING|P_VI_DEF,
+#ifdef FEAT_BROWSE
+ (char_u *)&p_bsdir, PV_NONE,
+ {(char_u *)"last", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"bufhidden", "bh", P_STRING|P_ALLOCED|P_VI_DEF|P_NOGLOB,
+#if defined(FEAT_QUICKFIX)
+ (char_u *)&p_bh, PV_BH,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"buflisted", "bl", P_BOOL|P_VI_DEF|P_NOGLOB,
+ (char_u *)&p_bl, PV_BL,
+ {(char_u *)1L, (char_u *)0L}
+ },
+ {"buftype", "bt", P_STRING|P_ALLOCED|P_VI_DEF|P_NOGLOB,
+#if defined(FEAT_QUICKFIX)
+ (char_u *)&p_bt, PV_BT,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"casemap", "cmp", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+ (char_u *)&p_cmp, PV_NONE,
+ {(char_u *)"internal,keepascii", (char_u *)0L}
+ },
+ {"cdpath", "cd", P_STRING|P_EXPAND|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_SEARCHPATH
+ (char_u *)&p_cdpath, PV_NONE,
+ {(char_u *)",,", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"cedit", NULL, P_STRING,
+#ifdef FEAT_CMDWIN
+ (char_u *)&p_cedit, PV_NONE,
+ {(char_u *)"", (char_u *)CTRL_F_STR}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"charconvert", "ccv", P_STRING|P_VI_DEF|P_SECURE,
+#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
+ (char_u *)&p_ccv, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"cindent", "cin", P_BOOL|P_VI_DEF|P_VIM,
+#ifdef FEAT_CINDENT
+ (char_u *)&p_cin, PV_CIN,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"cinkeys", "cink", P_STRING|P_ALLOCED|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_CINDENT
+ (char_u *)&p_cink, PV_CINK,
+ {(char_u *)"0{,0},0),:,0#,!^F,o,O,e", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"cinoptions", "cino", P_STRING|P_ALLOCED|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_CINDENT
+ (char_u *)&p_cino, PV_CINO,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"cinwords", "cinw", P_STRING|P_ALLOCED|P_VI_DEF|P_COMMA|P_NODUP,
+#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
+ (char_u *)&p_cinw, PV_CINW,
+ {(char_u *)"if,else,while,do,for,switch",
+ (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"clipboard", "cb", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_CLIPBOARD
+ (char_u *)&p_cb, PV_NONE,
+# ifdef FEAT_XCLIPBOARD
+ {(char_u *)"autoselect,exclude:cons\\|linux",
+ (char_u *)0L}
+# else
+ {(char_u *)"", (char_u *)0L}
+# endif
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#endif
+ },
+ {"cmdheight", "ch", P_NUM|P_VI_DEF|P_RALL,
+ (char_u *)&p_ch, PV_NONE,
+ {(char_u *)1L, (char_u *)0L}},
+ {"cmdwinheight", "cwh", P_NUM|P_VI_DEF,
+#ifdef FEAT_CMDWIN
+ (char_u *)&p_cwh, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)7L, (char_u *)0L}},
+ {"columns", "co", P_NUM|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RCLR,
+ (char_u *)&Columns, PV_NONE,
+ {(char_u *)80L, (char_u *)0L}},
+ {"comments", "com", P_STRING|P_ALLOCED|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_COMMENTS
+ (char_u *)&p_com, PV_COM,
+ {(char_u *)"s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:-",
+ (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"commentstring", "cms", P_STRING|P_ALLOCED|P_VI_DEF,
+#ifdef FEAT_FOLDING
+ (char_u *)&p_cms, PV_CMS,
+ {(char_u *)"/*%s*/", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"compatible", "cp", P_BOOL|P_RALL,
+ (char_u *)&p_cp, PV_NONE,
+ {(char_u *)TRUE, (char_u *)FALSE}},
+ {"complete", "cpt", P_STRING|P_ALLOCED|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_INS_EXPAND
+ (char_u *)&p_cpt, PV_CPT,
+ {(char_u *)".,w,b,u,t,i", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"confirm", "cf", P_BOOL|P_VI_DEF,
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ (char_u *)&p_confirm, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"conskey", "consk",P_BOOL|P_VI_DEF,
+#ifdef MSDOS
+ (char_u *)&p_consk, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"copyindent", "ci", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_ci, PV_CI,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"cpoptions", "cpo", P_STRING|P_VIM|P_RALL|P_FLAGLIST,
+ (char_u *)&p_cpo, PV_NONE,
+ {(char_u *)CPO_ALL, (char_u *)CPO_DEFAULT}},
+ {"cscopepathcomp", "cspc", P_NUM|P_VI_DEF|P_VIM,
+#ifdef FEAT_CSCOPE
+ (char_u *)&p_cspc, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)0L, (char_u *)0L}},
+ {"cscopeprg", "csprg", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
+#ifdef FEAT_CSCOPE
+ (char_u *)&p_csprg, PV_NONE,
+ {(char_u *)"cscope", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"cscopequickfix", "csqf", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#if defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)
+ (char_u *)&p_csqf, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"cscopetag", "cst", P_BOOL|P_VI_DEF|P_VIM,
+#ifdef FEAT_CSCOPE
+ (char_u *)&p_cst, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)0L, (char_u *)0L}},
+ {"cscopetagorder", "csto", P_NUM|P_VI_DEF|P_VIM,
+#ifdef FEAT_CSCOPE
+ (char_u *)&p_csto, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)0L, (char_u *)0L}},
+ {"cscopeverbose", "csverb", P_BOOL|P_VI_DEF|P_VIM,
+#ifdef FEAT_CSCOPE
+ (char_u *)&p_csverbose, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)0L, (char_u *)0L}},
+ {"debug", NULL, P_STRING|P_VI_DEF,
+ (char_u *)&p_debug, PV_NONE,
+ {(char_u *)"", (char_u *)0L}},
+ {"define", "def", P_STRING|P_ALLOCED|P_VI_DEF,
+#ifdef FEAT_FIND_ID
+ (char_u *)&p_def, OPT_BOTH(PV_DEF),
+ {(char_u *)"^\\s#\\s*define", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"delcombine", "deco", P_BOOL|P_VI_DEF|P_VIM,
+#ifdef FEAT_MBYTE
+ (char_u *)&p_deco, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}
+ },
+ {"dictionary", "dict", P_STRING|P_EXPAND|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_INS_EXPAND
+ (char_u *)&p_dict, OPT_BOTH(PV_DICT),
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"diff", NULL, P_BOOL|P_VI_DEF|P_RWIN|P_NOGLOB,
+#ifdef FEAT_DIFF
+ (char_u *)VAR_WIN, PV_DIFF,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"diffexpr", "dex", P_STRING|P_VI_DEF|P_SECURE,
+#if defined(FEAT_DIFF) && defined(FEAT_EVAL)
+ (char_u *)&p_dex, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"diffopt", "dip", P_STRING|P_ALLOCED|P_VI_DEF|P_RWIN|P_COMMA|P_NODUP,
+#ifdef FEAT_DIFF
+ (char_u *)&p_dip, PV_NONE,
+ {(char_u *)"filler", (char_u *)NULL}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)"", (char_u *)NULL}
+#endif
+ },
+ {"digraph", "dg", P_BOOL|P_VI_DEF|P_VIM,
+#ifdef FEAT_DIGRAPHS
+ (char_u *)&p_dg, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"directory", "dir", P_STRING|P_EXPAND|P_VI_DEF|P_COMMA|P_NODUP|P_SECURE,
+ (char_u *)&p_dir, PV_NONE,
+ {(char_u *)DFLT_DIR, (char_u *)0L}},
+ {"display", "dy", P_STRING|P_VI_DEF|P_COMMA|P_RALL|P_NODUP,
+ (char_u *)&p_dy, PV_NONE,
+ {(char_u *)"", (char_u *)0L}},
+ {"eadirection", "ead", P_STRING|P_VI_DEF,
+#ifdef FEAT_VERTSPLIT
+ (char_u *)&p_ead, PV_NONE,
+ {(char_u *)"both", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"edcompatible","ed", P_BOOL|P_VI_DEF,
+ (char_u *)&p_ed, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"encoding", "enc", P_STRING|P_VI_DEF|P_RCLR,
+#ifdef FEAT_MBYTE
+ (char_u *)&p_enc, PV_NONE,
+ {(char_u *)ENC_DFLT, (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"endofline", "eol", P_BOOL|P_NO_MKRC|P_VI_DEF|P_RSTAT,
+ (char_u *)&p_eol, PV_EOL,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"equalalways", "ea", P_BOOL|P_VI_DEF|P_RALL,
+ (char_u *)&p_ea, PV_NONE,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"equalprg", "ep", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
+ (char_u *)&p_ep, OPT_BOTH(PV_EP),
+ {(char_u *)"", (char_u *)0L}},
+ {"errorbells", "eb", P_BOOL|P_VI_DEF,
+ (char_u *)&p_eb, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"errorfile", "ef", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
+#ifdef FEAT_QUICKFIX
+ (char_u *)&p_ef, PV_NONE,
+ {(char_u *)DFLT_ERRORFILE, (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"errorformat", "efm", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_QUICKFIX
+ (char_u *)&p_efm, OPT_BOTH(PV_EFM),
+ {(char_u *)DFLT_EFM, (char_u *)0L},
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"esckeys", "ek", P_BOOL|P_VIM,
+ (char_u *)&p_ek, PV_NONE,
+ {(char_u *)FALSE, (char_u *)TRUE}},
+ {"eventignore", "ei", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_AUTOCMD
+ (char_u *)&p_ei, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"expandtab", "et", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_et, PV_ET,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"exrc", "ex", P_BOOL|P_VI_DEF|P_SECURE,
+ (char_u *)&p_exrc, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"fileencoding","fenc", P_STRING|P_ALLOCED|P_VI_DEF|P_RSTAT|P_RBUF|P_NO_MKRC,
+#ifdef FEAT_MBYTE
+ (char_u *)&p_fenc, PV_FENC,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"fileencodings","fencs", P_STRING|P_VI_DEF|P_COMMA,
+#ifdef FEAT_MBYTE
+ (char_u *)&p_fencs, PV_NONE,
+ {(char_u *)"ucs-bom", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"fileformat", "ff", P_STRING|P_ALLOCED|P_VI_DEF|P_RSTAT|P_NO_MKRC,
+ (char_u *)&p_ff, PV_FF,
+ {(char_u *)DFLT_FF, (char_u *)0L}},
+ {"fileformats", "ffs", P_STRING|P_VIM|P_COMMA|P_NODUP,
+ (char_u *)&p_ffs, PV_NONE,
+ {(char_u *)DFLT_FFS_VI, (char_u *)DFLT_FFS_VIM}},
+ {"filetype", "ft", P_STRING|P_ALLOCED|P_VI_DEF|P_NOGLOB,
+#ifdef FEAT_AUTOCMD
+ (char_u *)&p_ft, PV_FT,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"fillchars", "fcs", P_STRING|P_VI_DEF|P_RALL|P_COMMA|P_NODUP,
+#if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING)
+ (char_u *)&p_fcs, PV_NONE,
+ {(char_u *)"vert:|,fold:-", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#endif
+ },
+ {"fkmap", "fk", P_BOOL|P_VI_DEF,
+#ifdef FEAT_FKMAP
+ (char_u *)&p_fkmap, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"flash", "fl", P_BOOL|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+#ifdef FEAT_FOLDING
+ {"foldclose", "fcl", P_STRING|P_VI_DEF|P_COMMA|P_NODUP|P_RWIN,
+ (char_u *)&p_fcl, PV_NONE,
+ {(char_u *)"", (char_u *)0L}},
+ {"foldcolumn", "fdc", P_NUM|P_VI_DEF|P_RWIN,
+ (char_u *)VAR_WIN, PV_FDC,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"foldenable", "fen", P_BOOL|P_VI_DEF|P_RWIN,
+ (char_u *)VAR_WIN, PV_FEN,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"foldexpr", "fde", P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN,
+# ifdef FEAT_EVAL
+ (char_u *)VAR_WIN, PV_FDE,
+ {(char_u *)"0", (char_u *)NULL}
+# else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+# endif
+ },
+ {"foldignore", "fdi", P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN,
+ (char_u *)VAR_WIN, PV_FDI,
+ {(char_u *)"#", (char_u *)NULL}},
+ {"foldlevel", "fdl", P_NUM|P_VI_DEF|P_RWIN,
+ (char_u *)VAR_WIN, PV_FDL,
+ {(char_u *)0L, (char_u *)0L}},
+ {"foldlevelstart","fdls", P_NUM|P_VI_DEF,
+ (char_u *)&p_fdls, PV_NONE,
+ {(char_u *)-1L, (char_u *)0L}},
+ {"foldmarker", "fmr", P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|
+ P_RWIN|P_COMMA|P_NODUP,
+ (char_u *)VAR_WIN, PV_FMR,
+ {(char_u *)"{{{,}}}", (char_u *)NULL}},
+ {"foldmethod", "fdm", P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN,
+ (char_u *)VAR_WIN, PV_FDM,
+ {(char_u *)"manual", (char_u *)NULL}},
+ {"foldminlines","fml", P_NUM|P_VI_DEF|P_RWIN,
+ (char_u *)VAR_WIN, PV_FML,
+ {(char_u *)1L, (char_u *)0L}},
+ {"foldnestmax", "fdn", P_NUM|P_VI_DEF|P_RWIN,
+ (char_u *)VAR_WIN, PV_FDN,
+ {(char_u *)20L, (char_u *)0L}},
+ {"foldopen", "fdo", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+ (char_u *)&p_fdo, PV_NONE,
+ {(char_u *)"block,hor,mark,percent,quickfix,search,tag,undo",
+ (char_u *)0L}},
+ {"foldtext", "fdt", P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN,
+# ifdef FEAT_EVAL
+ (char_u *)VAR_WIN, PV_FDT,
+ {(char_u *)"foldtext()", (char_u *)NULL}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+#endif
+ {"formatoptions","fo", P_STRING|P_ALLOCED|P_VIM|P_FLAGLIST,
+ (char_u *)&p_fo, PV_FO,
+ {(char_u *)DFLT_FO_VI, (char_u *)DFLT_FO_VIM}},
+ {"formatprg", "fp", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
+ (char_u *)&p_fp, PV_NONE,
+ {(char_u *)"", (char_u *)0L}},
+ {"gdefault", "gd", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_gd, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"graphic", "gr", P_BOOL|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"grepformat", "gfm", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_QUICKFIX
+ (char_u *)&p_gefm, PV_NONE,
+ {(char_u *)DFLT_GREPFORMAT, (char_u *)0L},
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"grepprg", "gp", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
+#ifdef FEAT_QUICKFIX
+ (char_u *)&p_gp, OPT_BOTH(PV_GP),
+ {
+# ifdef WIN3264
+ /* may be changed to "grep -n" in os_win32.c */
+ (char_u *)"findstr /n",
+# else
+# ifdef UNIX
+ /* Add an extra file name so that grep will always
+ * insert a file name in the match line. */
+ (char_u *)"grep -n $* /dev/null",
+# else
+# ifdef VMS
+ (char_u *)"SEARCH/NUMBERS ",
+# else
+ (char_u *)"grep -n ",
+#endif
+#endif
+# endif
+ (char_u *)0L},
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"guicursor", "gcr", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef CURSOR_SHAPE
+ (char_u *)&p_guicursor, PV_NONE,
+ {
+# ifdef FEAT_GUI
+ (char_u *)"n-v-c:block-Cursor/lCursor,ve:ver35-Cursor,o:hor50-Cursor,i-ci:ver25-Cursor/lCursor,r-cr:hor20-Cursor/lCursor,sm:block-Cursor-blinkwait175-blinkoff150-blinkon175",
+# else /* MSDOS or Win32 console */
+ (char_u *)"n-v-c:block,o:hor50,i-ci:hor15,r-cr:hor30,sm:block",
+# endif
+ (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"guifont", "gfn", P_STRING|P_VI_DEF|P_RCLR|P_COMMA|P_NODUP,
+#ifdef FEAT_GUI
+ (char_u *)&p_guifont, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"guifontset", "gfs", P_STRING|P_VI_DEF|P_RCLR|P_COMMA,
+#if defined(FEAT_GUI) && defined(FEAT_XFONTSET)
+ (char_u *)&p_guifontset, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"guifontwide", "gfw", P_STRING|P_VI_DEF|P_RCLR|P_COMMA|P_NODUP,
+#if defined(FEAT_GUI) && defined(FEAT_MBYTE)
+ (char_u *)&p_guifontwide, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"guiheadroom", "ghr", P_NUM|P_VI_DEF,
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11)
+ (char_u *)&p_ghr, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)50L, (char_u *)0L}},
+ {"guioptions", "go", P_STRING|P_VI_DEF|P_RALL|P_FLAGLIST,
+#if defined(FEAT_GUI)
+ (char_u *)&p_go, PV_NONE,
+# if defined(UNIX) && !defined(MACOS)
+ {(char_u *)"agimrLtT", (char_u *)0L}
+# else
+ {(char_u *)"gmrLtT", (char_u *)0L}
+# endif
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"guipty", NULL, P_BOOL|P_VI_DEF,
+#if defined(FEAT_GUI)
+ (char_u *)&p_guipty, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"hardtabs", "ht", P_NUM|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}},
+ {"helpfile", "hf", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
+ (char_u *)&p_hf, PV_NONE,
+ {(char_u *)DFLT_HELPFILE, (char_u *)0L}},
+ {"helpheight", "hh", P_NUM|P_VI_DEF,
+#ifdef FEAT_WINDOWS
+ (char_u *)&p_hh, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)20L, (char_u *)0L}},
+ {"helplang", "hlg", P_STRING|P_VI_DEF|P_COMMA,
+#ifdef FEAT_MULTI_LANG
+ (char_u *)&p_hlg, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"hidden", "hid", P_BOOL|P_VI_DEF,
+ (char_u *)&p_hid, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"highlight", "hl", P_STRING|P_VI_DEF|P_RCLR|P_COMMA|P_NODUP,
+ (char_u *)&p_hl, PV_NONE,
+ {(char_u *)"8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn",
+ (char_u *)0L}},
+ {"history", "hi", P_NUM|P_VIM,
+ (char_u *)&p_hi, PV_NONE,
+ {(char_u *)0L, (char_u *)20L}},
+ {"hkmap", "hk", P_BOOL|P_VI_DEF|P_VIM,
+#ifdef FEAT_RIGHTLEFT
+ (char_u *)&p_hkmap, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"hkmapp", "hkp", P_BOOL|P_VI_DEF|P_VIM,
+#ifdef FEAT_RIGHTLEFT
+ (char_u *)&p_hkmapp, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"hlsearch", "hls", P_BOOL|P_VI_DEF|P_VIM|P_RALL,
+ (char_u *)&p_hls, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"icon", NULL, P_BOOL|P_VI_DEF,
+#ifdef FEAT_TITLE
+ (char_u *)&p_icon, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"iconstring", NULL, P_STRING|P_VI_DEF,
+#ifdef FEAT_TITLE
+ (char_u *)&p_iconstring, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"ignorecase", "ic", P_BOOL|P_VI_DEF,
+ (char_u *)&p_ic, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"imactivatekey","imak",P_STRING|P_VI_DEF,
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+ (char_u *)&p_imak, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"imcmdline", "imc", P_BOOL|P_VI_DEF,
+#ifdef USE_IM_CONTROL
+ (char_u *)&p_imcmdline, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"imdisable", "imd", P_BOOL|P_VI_DEF,
+#ifdef USE_IM_CONTROL
+ (char_u *)&p_imdisable, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+#ifdef __sgi
+ {(char_u *)TRUE, (char_u *)0L}
+#else
+ {(char_u *)FALSE, (char_u *)0L}
+#endif
+ },
+ {"iminsert", "imi", P_NUM|P_VI_DEF,
+ (char_u *)&p_iminsert, PV_IMI,
+#ifdef B_IMODE_IM
+ {(char_u *)B_IMODE_IM, (char_u *)0L}
+#else
+ {(char_u *)B_IMODE_NONE, (char_u *)0L}
+#endif
+ },
+ {"imsearch", "ims", P_NUM|P_VI_DEF,
+ (char_u *)&p_imsearch, PV_IMS,
+#ifdef B_IMODE_IM
+ {(char_u *)B_IMODE_IM, (char_u *)0L}
+#else
+ {(char_u *)B_IMODE_NONE, (char_u *)0L}
+#endif
+ },
+ {"include", "inc", P_STRING|P_ALLOCED|P_VI_DEF,
+#ifdef FEAT_FIND_ID
+ (char_u *)&p_inc, OPT_BOTH(PV_INC),
+ {(char_u *)"^\\s*#\\s*include", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"includeexpr", "inex", P_STRING|P_ALLOCED|P_VI_DEF,
+#if defined(FEAT_FIND_ID) && defined(FEAT_EVAL)
+ (char_u *)&p_inex, PV_INEX,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"incsearch", "is", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_is, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"indentexpr", "inde", P_STRING|P_ALLOCED|P_VI_DEF|P_VIM,
+#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
+ (char_u *)&p_inde, PV_INDE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"indentkeys", "indk", P_STRING|P_ALLOCED|P_VI_DEF|P_COMMA|P_NODUP,
+#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
+ (char_u *)&p_indk, PV_INDK,
+ {(char_u *)"0{,0},:,0#,!^F,o,O,e", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"infercase", "inf", P_BOOL|P_VI_DEF,
+ (char_u *)&p_inf, PV_INF,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"insertmode", "im", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_im, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"isfname", "isf", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+ (char_u *)&p_isf, PV_NONE,
+ {
+#ifdef BACKSLASH_IN_FILENAME
+ /* Excluded are: & and ^ are special in cmd.exe
+ * ( and ) are used in text separating fnames */
+ (char_u *)"@,48-57,/,\\,.,-,_,+,,,#,$,%,{,},[,],:,@-@,!,~,=",
+#else
+# ifdef AMIGA
+ (char_u *)"@,48-57,/,.,-,_,+,,,$,:",
+# else
+# ifdef VMS
+ (char_u *)"@,48-57,/,.,-,_,+,,,#,$,%,<,>,[,],:,;,~",
+# else /* UNIX et al. */
+# ifdef EBCDIC
+ (char_u *)"@,240-249,/,.,-,_,+,,,#,$,%,~,=",
+# else
+ (char_u *)"@,48-57,/,.,-,_,+,,,#,$,%,~,=",
+# endif
+# endif
+# endif
+#endif
+ (char_u *)0L}},
+ {"isident", "isi", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+ (char_u *)&p_isi, PV_NONE,
+ {
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
+ (char_u *)"@,48-57,_,128-167,224-235",
+#else
+# ifdef EBCDIC
+ /* TODO: EBCDIC Check this! @ == isalpha()*/
+ (char_u *)"@,240-249,_,66-73,81-89,98-105,"
+ "112-120,128,140-142,156,158,172,"
+ "174,186,191,203-207,219-225,235-239,"
+ "251-254",
+# else
+ (char_u *)"@,48-57,_,192-255",
+# endif
+#endif
+ (char_u *)0L}},
+ {"iskeyword", "isk", P_STRING|P_ALLOCED|P_VIM|P_COMMA|P_NODUP,
+ (char_u *)&p_isk, PV_ISK,
+ {
+#ifdef EBCDIC
+ (char_u *)"@,240-249,_",
+ /* TODO: EBCDIC Check this! @ == isalpha()*/
+ (char_u *)"@,240-249,_,66-73,81-89,98-105,"
+ "112-120,128,140-142,156,158,172,"
+ "174,186,191,203-207,219-225,235-239,"
+ "251-254",
+#else
+ (char_u *)"@,48-57,_",
+# if defined(MSDOS) || defined(MSWIN) || defined(OS2)
+ (char_u *)"@,48-57,_,128-167,224-235"
+# else
+ (char_u *)"@,48-57,_,192-255"
+# endif
+#endif
+ }},
+ {"isprint", "isp", P_STRING|P_VI_DEF|P_RALL|P_COMMA|P_NODUP,
+ (char_u *)&p_isp, PV_NONE,
+ {
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2) || defined(MACOS) \
+ || defined(VMS)
+ (char_u *)"@,~-255",
+#else
+# ifdef EBCDIC
+ /* all chars above 63 are printable */
+ (char_u *)"63-255",
+# else
+ (char_u *)"@,161-255",
+# endif
+#endif
+ (char_u *)0L}},
+ {"joinspaces", "js", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_js, PV_NONE,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"key", NULL, P_STRING|P_ALLOCED|P_VI_DEF|P_NO_MKRC,
+#ifdef FEAT_CRYPT
+ (char_u *)&p_key, PV_KEY,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"keymap", "kmp", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_RSTAT,
+#ifdef FEAT_KEYMAP
+ (char_u *)&p_keymap, PV_KMAP,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#endif
+ },
+ {"keymodel", "km", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_VISUAL
+ (char_u *)&p_km, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"keywordprg", "kp", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
+ (char_u *)&p_kp, OPT_BOTH(PV_KP),
+ {
+#if defined(MSDOS) || defined(MSWIN)
+ (char_u *)":help",
+#else
+#ifdef VMS
+ (char_u *)"help",
+#else
+# if defined(OS2)
+ (char_u *)"view /",
+# else
+# ifdef USEMAN_S
+ (char_u *)"man -s",
+# else
+ (char_u *)"man",
+# endif
+# endif
+#endif
+#endif
+ (char_u *)0L}},
+ {"langmap", "lmap", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_LANGMAP
+ (char_u *)&p_langmap, PV_NONE,
+ {(char_u *)"", /* unmatched } */
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL,
+#endif
+ (char_u *)0L}},
+ {"langmenu", "lm", P_STRING|P_VI_DEF,
+#if defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)
+ (char_u *)&p_lm, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"laststatus", "ls", P_NUM|P_VI_DEF|P_RALL,
+#ifdef FEAT_WINDOWS
+ (char_u *)&p_ls, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)1L, (char_u *)0L}},
+ {"lazyredraw", "lz", P_BOOL|P_VI_DEF,
+ (char_u *)&p_lz, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"linebreak", "lbr", P_BOOL|P_VI_DEF|P_RWIN,
+#ifdef FEAT_LINEBREAK
+ (char_u *)VAR_WIN, PV_LBR,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"lines", NULL, P_NUM|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RCLR,
+ (char_u *)&Rows, PV_NONE,
+ {
+#if defined(MSDOS) || defined(WIN3264) || defined(OS2)
+ (char_u *)25L,
+#else
+ (char_u *)24L,
+#endif
+ (char_u *)0L}},
+ {"linespace", "lsp", P_NUM|P_VI_DEF|P_RCLR,
+#ifdef FEAT_GUI
+ (char_u *)&p_linespace, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+#ifdef FEAT_GUI_W32
+ {(char_u *)1L, (char_u *)0L}
+#else
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"lisp", NULL, P_BOOL|P_VI_DEF,
+#ifdef FEAT_LISP
+ (char_u *)&p_lisp, PV_LISP,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"lispwords", "lw", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_LISP
+ (char_u *)&p_lispwords, PV_NONE,
+ {(char_u *)LISPWORD_VALUE, (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#endif
+ },
+ {"list", NULL, P_BOOL|P_VI_DEF|P_RWIN,
+ (char_u *)VAR_WIN, PV_LIST,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"listchars", "lcs", P_STRING|P_VI_DEF|P_RALL|P_COMMA|P_NODUP,
+ (char_u *)&p_lcs, PV_NONE,
+ {(char_u *)"eol:$", (char_u *)0L}},
+ {"loadplugins", "lpl", P_BOOL|P_VI_DEF,
+ (char_u *)&p_lpl, PV_NONE,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"magic", NULL, P_BOOL|P_VI_DEF,
+ (char_u *)&p_magic, PV_NONE,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"makeef", "mef", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
+#ifdef FEAT_QUICKFIX
+ (char_u *)&p_mef, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"makeprg", "mp", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
+#ifdef FEAT_QUICKFIX
+ (char_u *)&p_mp, OPT_BOTH(PV_MP),
+# ifdef VMS
+ {(char_u *)"MMS", (char_u *)0L}
+# else
+ {(char_u *)"make", (char_u *)0L}
+# endif
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"matchpairs", "mps", P_STRING|P_ALLOCED|P_VI_DEF|P_COMMA|P_NODUP,
+ (char_u *)&p_mps, PV_MPS,
+ {(char_u *)"(:),{:},[:]", (char_u *)0L}},
+ {"matchtime", "mat", P_NUM|P_VI_DEF,
+ (char_u *)&p_mat, PV_NONE,
+ {(char_u *)5L, (char_u *)0L}},
+ {"maxfuncdepth", "mfd", P_NUM|P_VI_DEF,
+#ifdef FEAT_EVAL
+ (char_u *)&p_mfd, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)100L, (char_u *)0L}},
+ {"maxmapdepth", "mmd", P_NUM|P_VI_DEF,
+ (char_u *)&p_mmd, PV_NONE,
+ {(char_u *)1000L, (char_u *)0L}},
+ {"maxmem", "mm", P_NUM|P_VI_DEF,
+ (char_u *)&p_mm, PV_NONE,
+ {(char_u *)DFLT_MAXMEM, (char_u *)0L}},
+ {"maxmemtot", "mmt", P_NUM|P_VI_DEF,
+ (char_u *)&p_mmt, PV_NONE,
+ {(char_u *)DFLT_MAXMEMTOT, (char_u *)0L}},
+ {"menuitems", "mis", P_NUM|P_VI_DEF,
+#ifdef FEAT_MENU
+ (char_u *)&p_mis, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)25L, (char_u *)0L}},
+ {"mesg", NULL, P_BOOL|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"modeline", "ml", P_BOOL|P_VIM,
+ (char_u *)&p_ml, PV_ML,
+ {(char_u *)FALSE, (char_u *)TRUE}},
+ {"modelines", "mls", P_NUM|P_VI_DEF,
+ (char_u *)&p_mls, PV_NONE,
+ {(char_u *)5L, (char_u *)0L}},
+ {"modifiable", "ma", P_BOOL|P_VI_DEF|P_NOGLOB,
+ (char_u *)&p_ma, PV_MA,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"modified", "mod", P_BOOL|P_NO_MKRC|P_VI_DEF|P_RSTAT,
+ (char_u *)&p_mod, PV_MOD,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"more", NULL, P_BOOL|P_VIM,
+ (char_u *)&p_more, PV_NONE,
+ {(char_u *)FALSE, (char_u *)TRUE}},
+ {"mouse", NULL, P_STRING|P_VI_DEF|P_FLAGLIST,
+ (char_u *)&p_mouse, PV_NONE,
+ {
+#if defined(MSDOS) || defined(WIN3264)
+ (char_u *)"a",
+#else
+ (char_u *)"",
+#endif
+ (char_u *)0L}},
+ {"mousefocus", "mousef", P_BOOL|P_VI_DEF,
+#ifdef FEAT_GUI
+ (char_u *)&p_mousef, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"mousehide", "mh", P_BOOL|P_VI_DEF,
+#ifdef FEAT_GUI
+ (char_u *)&p_mh, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"mousemodel", "mousem", P_STRING|P_VI_DEF,
+ (char_u *)&p_mousem, PV_NONE,
+ {
+#if defined(MSDOS) || defined(MSWIN)
+ (char_u *)"popup",
+#else
+# if defined(MACOS)
+ (char_u *)"popup_setpos",
+# else
+ (char_u *)"extend",
+# endif
+#endif
+ (char_u *)0L}},
+ {"mouseshape", "mouses", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_MOUSESHAPE
+ (char_u *)&p_mouseshape, PV_NONE,
+ {(char_u *)"i-r:beam,s:updown,sd:udsizing,vs:leftright,vd:lrsizing,m:no,ml:up-arrow,v:rightup-arrow", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"mousetime", "mouset", P_NUM|P_VI_DEF,
+ (char_u *)&p_mouset, PV_NONE,
+ {(char_u *)500L, (char_u *)0L}},
+ {"novice", NULL, P_BOOL|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"nrformats", "nf", P_STRING|P_ALLOCED|P_VI_DEF|P_COMMA|P_NODUP,
+ (char_u *)&p_nf, PV_NF,
+ {(char_u *)"octal,hex", (char_u *)0L}},
+ {"number", "nu", P_BOOL|P_VI_DEF|P_RWIN,
+ (char_u *)VAR_WIN, PV_NU,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"open", NULL, P_BOOL|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"optimize", "opt", P_BOOL|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"osfiletype", "oft", P_STRING|P_ALLOCED|P_VI_DEF,
+#ifdef FEAT_OSFILETYPE
+ (char_u *)&p_oft, PV_OFT,
+ {(char_u *)DFLT_OFT, (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"paragraphs", "para", P_STRING|P_VI_DEF,
+ (char_u *)&p_para, PV_NONE,
+ {(char_u *)"IPLPPPQPP LIpplpipbp", (char_u *)0L}},
+ {"paste", NULL, P_BOOL|P_VI_DEF,
+ (char_u *)&p_paste, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"pastetoggle", "pt", P_STRING|P_VI_DEF,
+ (char_u *)&p_pt, PV_NONE,
+ {(char_u *)"", (char_u *)0L}},
+ {"patchexpr", "pex", P_STRING|P_VI_DEF|P_SECURE,
+#if defined(FEAT_DIFF) && defined(FEAT_EVAL)
+ (char_u *)&p_pex, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"patchmode", "pm", P_STRING|P_VI_DEF,
+ (char_u *)&p_pm, PV_NONE,
+ {(char_u *)"", (char_u *)0L}},
+ {"path", "pa", P_STRING|P_EXPAND|P_VI_DEF|P_COMMA|P_NODUP,
+ (char_u *)&p_path, OPT_BOTH(PV_PATH),
+ {
+#if defined AMIGA || defined MSDOS || defined MSWIN
+ (char_u *)".,,",
+#else
+# if defined(__EMX__)
+ (char_u *)".,/emx/include,,",
+# else /* Unix, probably */
+ (char_u *)".,/usr/include,,",
+# endif
+#endif
+ (char_u *)0L}},
+ {"preserveindent", "pi", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_pi, PV_PI,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"previewheight", "pvh",P_NUM|P_VI_DEF,
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ (char_u *)&p_pvh, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)12L, (char_u *)0L}},
+ {"previewwindow", "pvw", P_BOOL|P_VI_DEF|P_RSTAT|P_NOGLOB,
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ (char_u *)VAR_WIN, PV_PVW,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"printdevice", "pdev", P_STRING|P_VI_DEF,
+#ifdef FEAT_PRINTER
+ (char_u *)&p_pdev, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"printencoding", "penc", P_STRING|P_VI_DEF,
+#ifdef FEAT_POSTSCRIPT
+ (char_u *)&p_penc, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"printexpr", "pexpr", P_STRING|P_VI_DEF,
+#ifdef FEAT_POSTSCRIPT
+ (char_u *)&p_pexpr, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"printfont", "pfn", P_STRING|P_VI_DEF,
+#ifdef FEAT_PRINTER
+ (char_u *)&p_pfn, PV_NONE,
+ {
+# ifdef MSWIN
+ (char_u *)"Courier_New:h10",
+# else
+ (char_u *)"courier",
+# endif
+ (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"printheader", "pheader", P_STRING|P_VI_DEF|P_GETTEXT,
+#ifdef FEAT_PRINTER
+ (char_u *)&p_header, PV_NONE,
+ {(char_u *)N_("%<%f%h%m%=Page %N"), (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"printoptions", "popt", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_PRINTER
+ (char_u *)&p_popt, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"prompt", NULL, P_BOOL|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"readonly", "ro", P_BOOL|P_VI_DEF|P_RSTAT|P_NOGLOB,
+ (char_u *)&p_ro, PV_RO,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"redraw", NULL, P_BOOL|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"remap", NULL, P_BOOL|P_VI_DEF,
+ (char_u *)&p_remap, PV_NONE,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"report", NULL, P_NUM|P_VI_DEF,
+ (char_u *)&p_report, PV_NONE,
+ {(char_u *)2L, (char_u *)0L}},
+ {"restorescreen", "rs", P_BOOL|P_VI_DEF,
+#ifdef WIN3264
+ (char_u *)&p_rs, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"revins", "ri", P_BOOL|P_VI_DEF|P_VIM,
+#ifdef FEAT_RIGHTLEFT
+ (char_u *)&p_ri, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"rightleft", "rl", P_BOOL|P_VI_DEF|P_RWIN,
+#ifdef FEAT_RIGHTLEFT
+ (char_u *)VAR_WIN, PV_RL,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"rightleftcmd", "rlc", P_STRING|P_ALLOCED|P_VI_DEF|P_RWIN,
+#ifdef FEAT_RIGHTLEFT
+ (char_u *)VAR_WIN, PV_RLC,
+ {(char_u *)"search", (char_u *)NULL}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"ruler", "ru", P_BOOL|P_VI_DEF|P_VIM|P_RSTAT,
+#ifdef FEAT_CMDL_INFO
+ (char_u *)&p_ru, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"rulerformat", "ruf", P_STRING|P_VI_DEF|P_ALLOCED|P_RSTAT,
+#ifdef FEAT_STL_OPT
+ (char_u *)&p_ruf, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"runtimepath", "rtp", P_STRING|P_VI_DEF|P_EXPAND|P_COMMA|P_NODUP|P_SECURE,
+ (char_u *)&p_rtp, PV_NONE,
+ {(char_u *)DFLT_RUNTIMEPATH, (char_u *)0L}},
+ {"scroll", "scr", P_NUM|P_NO_MKRC|P_VI_DEF,
+ (char_u *)VAR_WIN, PV_SCROLL,
+ {(char_u *)12L, (char_u *)0L}},
+ {"scrollbind", "scb", P_BOOL|P_VI_DEF,
+#ifdef FEAT_SCROLLBIND
+ (char_u *)VAR_WIN, PV_SCBIND,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"scrolljump", "sj", P_NUM|P_VI_DEF|P_VIM,
+ (char_u *)&p_sj, PV_NONE,
+ {(char_u *)1L, (char_u *)0L}},
+ {"scrolloff", "so", P_NUM|P_VI_DEF|P_VIM|P_RALL,
+ (char_u *)&p_so, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}},
+ {"scrollopt", "sbo", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_SCROLLBIND
+ (char_u *)&p_sbo, PV_NONE,
+ {(char_u *)"ver,jump", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"sections", "sect", P_STRING|P_VI_DEF,
+ (char_u *)&p_sections, PV_NONE,
+ {(char_u *)"SHNHH HUnhsh", (char_u *)0L}},
+ {"secure", NULL, P_BOOL|P_VI_DEF|P_SECURE,
+ (char_u *)&p_secure, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"selection", "sel", P_STRING|P_VI_DEF,
+#ifdef FEAT_VISUAL
+ (char_u *)&p_sel, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"inclusive", (char_u *)0L}},
+ {"selectmode", "slm", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_VISUAL
+ (char_u *)&p_slm, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"sessionoptions", "ssop", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_SESSION
+ (char_u *)&p_ssop, PV_NONE,
+ {(char_u *)"blank,buffers,curdir,folds,help,options,winsize",
+ (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"shell", "sh", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
+ (char_u *)&p_sh, PV_NONE,
+ {
+#ifdef VMS
+ (char_u *)"-",
+#else
+# if defined(MSDOS)
+ (char_u *)"command",
+# else
+# if defined(WIN16)
+ (char_u *)"command.com",
+# else
+# if defined(WIN3264)
+ (char_u *)"", /* set in set_init_1() */
+# else
+# if defined(OS2)
+ (char_u *)"cmd.exe",
+# else
+# if defined(ARCHIE)
+ (char_u *)"gos",
+# else
+ (char_u *)"sh",
+# endif
+# endif
+# endif
+# endif
+# endif
+#endif /* VMS */
+ (char_u *)0L}},
+ {"shellcmdflag","shcf", P_STRING|P_VI_DEF|P_SECURE,
+ (char_u *)&p_shcf, PV_NONE,
+ {
+#if defined(MSDOS) || defined(MSWIN)
+ (char_u *)"/c",
+#else
+# if defined(OS2)
+ (char_u *)"/c",
+# else
+ (char_u *)"-c",
+# endif
+#endif
+ (char_u *)0L}},
+ {"shellpipe", "sp", P_STRING|P_VI_DEF|P_SECURE,
+#ifdef FEAT_QUICKFIX
+ (char_u *)&p_sp, PV_NONE,
+ {
+#if defined(UNIX) || defined(OS2)
+# ifdef ARCHIE
+ (char_u *)"2>",
+# else
+ (char_u *)"| tee",
+# endif
+#else
+ (char_u *)">",
+#endif
+ (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"shellquote", "shq", P_STRING|P_VI_DEF|P_SECURE,
+ (char_u *)&p_shq, PV_NONE,
+ {(char_u *)"", (char_u *)0L}},
+ {"shellredir", "srr", P_STRING|P_VI_DEF|P_SECURE,
+ (char_u *)&p_srr, PV_NONE,
+ {(char_u *)">", (char_u *)0L}},
+ {"shellslash", "ssl", P_BOOL|P_VI_DEF,
+#ifdef BACKSLASH_IN_FILENAME
+ (char_u *)&p_ssl, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"shelltype", "st", P_NUM|P_VI_DEF,
+#ifdef AMIGA
+ (char_u *)&p_st, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)0L, (char_u *)0L}},
+ {"shellxquote", "sxq", P_STRING|P_VI_DEF|P_SECURE,
+ (char_u *)&p_sxq, PV_NONE,
+ {
+#if defined(UNIX) && defined(USE_SYSTEM) && !defined(__EMX__)
+ (char_u *)"\"",
+#else
+ (char_u *)"",
+#endif
+ (char_u *)0L}},
+ {"shiftround", "sr", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_sr, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"shiftwidth", "sw", P_NUM|P_VI_DEF,
+ (char_u *)&p_sw, PV_SW,
+ {(char_u *)8L, (char_u *)0L}},
+ {"shortmess", "shm", P_STRING|P_VIM|P_FLAGLIST,
+ (char_u *)&p_shm, PV_NONE,
+ {(char_u *)"", (char_u *)"filnxtToO"}},
+ {"shortname", "sn", P_BOOL|P_VI_DEF,
+#ifdef SHORT_FNAME
+ (char_u *)NULL, PV_NONE,
+#else
+ (char_u *)&p_sn, PV_SN,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"showbreak", "sbr", P_STRING|P_VI_DEF|P_RALL,
+#ifdef FEAT_LINEBREAK
+ (char_u *)&p_sbr, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"showcmd", "sc", P_BOOL|P_VIM,
+#ifdef FEAT_CMDL_INFO
+ (char_u *)&p_sc, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE,
+#ifdef UNIX
+ (char_u *)FALSE
+#else
+ (char_u *)TRUE
+#endif
+ }},
+ {"showfulltag", "sft", P_BOOL|P_VI_DEF,
+ (char_u *)&p_sft, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"showmatch", "sm", P_BOOL|P_VI_DEF,
+ (char_u *)&p_sm, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"showmode", "smd", P_BOOL|P_VIM,
+ (char_u *)&p_smd, PV_NONE,
+ {(char_u *)FALSE, (char_u *)TRUE}},
+ {"sidescroll", "ss", P_NUM|P_VI_DEF,
+ (char_u *)&p_ss, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}},
+ {"sidescrolloff", "siso", P_NUM|P_VI_DEF|P_VIM|P_RBUF,
+ (char_u *)&p_siso, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}},
+ {"slowopen", "slow", P_BOOL|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"smartcase", "scs", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_scs, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"smartindent", "si", P_BOOL|P_VI_DEF|P_VIM,
+#ifdef FEAT_SMARTINDENT
+ (char_u *)&p_si, PV_SI,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"smarttab", "sta", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_sta, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"softtabstop", "sts", P_NUM|P_VI_DEF|P_VIM,
+ (char_u *)&p_sts, PV_STS,
+ {(char_u *)0L, (char_u *)0L}},
+ {"sourceany", NULL, P_BOOL|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"splitbelow", "sb", P_BOOL|P_VI_DEF,
+#ifdef FEAT_WINDOWS
+ (char_u *)&p_sb, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"splitright", "spr", P_BOOL|P_VI_DEF,
+#ifdef FEAT_VERTSPLIT
+ (char_u *)&p_spr, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"startofline", "sol", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_sol, PV_NONE,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"statusline" ,"stl", P_STRING|P_VI_DEF|P_ALLOCED|P_RSTAT,
+#ifdef FEAT_STL_OPT
+ (char_u *)&p_stl, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"suffixes", "su", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+ (char_u *)&p_su, PV_NONE,
+ {(char_u *)".bak,~,.o,.h,.info,.swp,.obj",
+ (char_u *)0L}},
+ {"suffixesadd", "sua", P_STRING|P_VI_DEF|P_ALLOCED|P_COMMA|P_NODUP,
+#if defined(FEAT_SEARCHPATH)
+ (char_u *)&p_sua, PV_SUA,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"swapfile", "swf", P_BOOL|P_VI_DEF|P_RSTAT,
+ (char_u *)&p_swf, PV_SWF,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"swapsync", "sws", P_STRING|P_VI_DEF,
+ (char_u *)&p_sws, PV_NONE,
+ {(char_u *)"fsync", (char_u *)0L}},
+ {"switchbuf", "swb", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+ (char_u *)&p_swb, PV_NONE,
+ {(char_u *)"", (char_u *)0L}},
+ {"syntax", "syn", P_STRING|P_ALLOCED|P_VI_DEF|P_NOGLOB,
+#ifdef FEAT_SYN_HL
+ (char_u *)&p_syn, PV_SYN,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"tabstop", "ts", P_NUM|P_VI_DEF|P_RBUF,
+ (char_u *)&p_ts, PV_TS,
+ {(char_u *)8L, (char_u *)0L}},
+ {"tagbsearch", "tbs", P_BOOL|P_VI_DEF,
+ (char_u *)&p_tbs, PV_NONE,
+#ifdef VMS /* binary searching doesn't appear to work on VMS */
+ {(char_u *)0L, (char_u *)0L}
+#else
+ {(char_u *)TRUE, (char_u *)0L}
+#endif
+ },
+ {"taglength", "tl", P_NUM|P_VI_DEF,
+ (char_u *)&p_tl, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}},
+ {"tagrelative", "tr", P_BOOL|P_VIM,
+ (char_u *)&p_tr, PV_NONE,
+ {(char_u *)FALSE, (char_u *)TRUE}},
+ {"tags", "tag", P_STRING|P_EXPAND|P_VI_DEF|P_COMMA|P_NODUP,
+ (char_u *)&p_tags, OPT_BOTH(PV_TAGS),
+ {
+#if defined(FEAT_EMACS_TAGS) && !defined(CASE_INSENSITIVE_FILENAME)
+ (char_u *)"./tags,./TAGS,tags,TAGS",
+#else
+ (char_u *)"./tags,tags",
+#endif
+ (char_u *)0L}},
+ {"tagstack", "tgst", P_BOOL|P_VI_DEF,
+ (char_u *)&p_tgst, PV_NONE,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"term", NULL, P_STRING|P_EXPAND|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RALL,
+ (char_u *)&T_NAME, PV_NONE,
+ {(char_u *)"", (char_u *)0L}},
+ {"termbidi", "tbidi", P_BOOL|P_VI_DEF,
+#ifdef FEAT_ARABIC
+ (char_u *)&p_tbidi, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"termencoding", "tenc", P_STRING|P_VI_DEF|P_RCLR,
+#ifdef FEAT_MBYTE
+ (char_u *)&p_tenc, PV_NONE,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"terse", NULL, P_BOOL|P_VI_DEF,
+ (char_u *)&p_terse, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"textauto", "ta", P_BOOL|P_VIM,
+ (char_u *)&p_ta, PV_NONE,
+ {(char_u *)DFLT_TEXTAUTO, (char_u *)TRUE}},
+ {"textmode", "tx", P_BOOL|P_VI_DEF|P_NO_MKRC,
+ (char_u *)&p_tx, PV_TX,
+ {
+#ifdef USE_CRNL
+ (char_u *)TRUE,
+#else
+ (char_u *)FALSE,
+#endif
+ (char_u *)0L}},
+ {"textwidth", "tw", P_NUM|P_VI_DEF|P_VIM,
+ (char_u *)&p_tw, PV_TW,
+ {(char_u *)0L, (char_u *)0L}},
+ {"thesaurus", "tsr", P_STRING|P_EXPAND|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_INS_EXPAND
+ (char_u *)&p_tsr, OPT_BOTH(PV_TSR),
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"tildeop", "top", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_to, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"timeout", "to", P_BOOL|P_VI_DEF,
+ (char_u *)&p_timeout, PV_NONE,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"timeoutlen", "tm", P_NUM|P_VI_DEF,
+ (char_u *)&p_tm, PV_NONE,
+ {(char_u *)1000L, (char_u *)0L}},
+ {"title", NULL, P_BOOL|P_VI_DEF,
+#ifdef FEAT_TITLE
+ (char_u *)&p_title, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"titlelen", NULL, P_NUM|P_VI_DEF,
+#ifdef FEAT_TITLE
+ (char_u *)&p_titlelen, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)85L, (char_u *)0L}},
+ {"titleold", NULL, P_STRING|P_VI_DEF|P_GETTEXT,
+#ifdef FEAT_TITLE
+ (char_u *)&p_titleold, PV_NONE,
+ {(char_u *)N_("Thanks for flying Vim"),
+ (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"titlestring", NULL, P_STRING|P_VI_DEF,
+#ifdef FEAT_TITLE
+ (char_u *)&p_titlestring, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32)
+ {"toolbar", "tb", P_STRING|P_COMMA|P_VI_DEF|P_NODUP,
+ (char_u *)&p_toolbar, PV_NONE,
+ {(char_u *)"icons,tooltips", (char_u *)0L}},
+#endif
+#if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK) && defined(HAVE_GTK2)
+ {"toolbariconsize", "tbis", P_STRING|P_VI_DEF,
+ (char_u *)&p_tbis, PV_NONE,
+ {(char_u *)"small", (char_u *)0L}},
+#endif
+ {"ttimeout", NULL, P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_ttimeout, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"ttimeoutlen", "ttm", P_NUM|P_VI_DEF,
+ (char_u *)&p_ttm, PV_NONE,
+ {(char_u *)-1L, (char_u *)0L}},
+ {"ttybuiltin", "tbi", P_BOOL|P_VI_DEF,
+ (char_u *)&p_tbi, PV_NONE,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"ttyfast", "tf", P_BOOL|P_NO_MKRC|P_VI_DEF,
+ (char_u *)&p_tf, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"ttymouse", "ttym", P_STRING|P_NODEFAULT|P_NO_MKRC|P_VI_DEF,
+#if defined(FEAT_MOUSE) && (defined(UNIX) || defined(VMS))
+ (char_u *)&p_ttym, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"ttyscroll", "tsl", P_NUM|P_VI_DEF,
+ (char_u *)&p_ttyscroll, PV_NONE,
+ {(char_u *)999L, (char_u *)0L}},
+ {"ttytype", "tty", P_STRING|P_EXPAND|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RALL,
+ (char_u *)&T_NAME, PV_NONE,
+ {(char_u *)"", (char_u *)0L}},
+ {"undolevels", "ul", P_NUM|P_VI_DEF,
+ (char_u *)&p_ul, PV_NONE,
+ {
+#if defined(UNIX) || defined(WIN3264) || defined(OS2) || defined(VMS)
+ (char_u *)1000L,
+#else
+ (char_u *)100L,
+#endif
+ (char_u *)0L}},
+ {"updatecount", "uc", P_NUM|P_VI_DEF,
+ (char_u *)&p_uc, PV_NONE,
+ {(char_u *)200L, (char_u *)0L}},
+ {"updatetime", "ut", P_NUM|P_VI_DEF,
+ (char_u *)&p_ut, PV_NONE,
+ {(char_u *)4000L, (char_u *)0L}},
+ {"verbose", "vbs", P_NUM|P_VI_DEF,
+ (char_u *)&p_verbose, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}},
+ {"viewdir", "vdir", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
+#ifdef FEAT_SESSION
+ (char_u *)&p_vdir, PV_NONE,
+ {(char_u *)DFLT_VDIR, (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"viewoptions", "vop", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_SESSION
+ (char_u *)&p_vop, PV_NONE,
+ {(char_u *)"folds,options,cursor", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"viminfo", "vi", P_STRING|P_COMMA|P_NODUP|P_SECURE,
+#ifdef FEAT_VIMINFO
+ (char_u *)&p_viminfo, PV_NONE,
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
+ {(char_u *)"", (char_u *)"'20,<50,s10,h,rA:,rB:"}
+#else
+# ifdef AMIGA
+ {(char_u *)"",
+ (char_u *)"'20,<50,s10,h,rdf0:,rdf1:,rdf2:"}
+# else
+ {(char_u *)"", (char_u *)"'20,<50,s10,h"}
+# endif
+#endif
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"virtualedit", "ve", P_STRING|P_COMMA|P_NODUP|P_VI_DEF|P_VIM,
+#ifdef FEAT_VIRTUALEDIT
+ (char_u *)&p_ve, PV_NONE,
+ {(char_u *)"", (char_u *)""}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ },
+ {"visualbell", "vb", P_BOOL|P_VI_DEF,
+ (char_u *)&p_vb, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"w300", NULL, P_NUM|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}},
+ {"w1200", NULL, P_NUM|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}},
+ {"w9600", NULL, P_NUM|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}},
+ {"warn", NULL, P_BOOL|P_VI_DEF,
+ (char_u *)&p_warn, PV_NONE,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"weirdinvert", "wiv", P_BOOL|P_VI_DEF|P_RCLR,
+ (char_u *)&p_wiv, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"whichwrap", "ww", P_STRING|P_VIM|P_COMMA|P_FLAGLIST,
+ (char_u *)&p_ww, PV_NONE,
+ {(char_u *)"", (char_u *)"b,s"}},
+ {"wildchar", "wc", P_NUM|P_VIM,
+ (char_u *)&p_wc, PV_NONE,
+ {(char_u *)(long)Ctrl_E, (char_u *)(long)TAB}},
+ {"wildcharm", "wcm", P_NUM|P_VI_DEF,
+ (char_u *)&p_wcm, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}},
+ {"wildignore", "wig", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+#ifdef FEAT_WILDIGN
+ (char_u *)&p_wig, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)"", (char_u *)0L}},
+ {"wildmenu", "wmnu", P_BOOL|P_VI_DEF,
+#ifdef FEAT_WILDMENU
+ (char_u *)&p_wmnu, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"wildmode", "wim", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
+ (char_u *)&p_wim, PV_NONE,
+ {(char_u *)"full", (char_u *)0L}},
+ {"winaltkeys", "wak", P_STRING|P_VI_DEF,
+#ifdef FEAT_WAK
+ (char_u *)&p_wak, PV_NONE,
+ {(char_u *)"menu", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L}
+#endif
+ },
+ {"window", "wi", P_NUM|P_VI_DEF,
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}},
+ {"winheight", "wh", P_NUM|P_VI_DEF,
+#ifdef FEAT_WINDOWS
+ (char_u *)&p_wh, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)1L, (char_u *)0L}},
+ {"winfixheight", "wfh", P_BOOL|P_VI_DEF|P_RSTAT,
+#if defined(FEAT_WINDOWS)
+ (char_u *)VAR_WIN, PV_WFH,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"winminheight", "wmh", P_NUM|P_VI_DEF,
+#ifdef FEAT_WINDOWS
+ (char_u *)&p_wmh, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)1L, (char_u *)0L}},
+ {"winminwidth", "wmw", P_NUM|P_VI_DEF,
+#ifdef FEAT_VERTSPLIT
+ (char_u *)&p_wmw, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)1L, (char_u *)0L}},
+ {"winwidth", "wiw", P_NUM|P_VI_DEF,
+#ifdef FEAT_VERTSPLIT
+ (char_u *)&p_wiw, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)20L, (char_u *)0L}},
+ {"wrap", NULL, P_BOOL|P_VI_DEF|P_RWIN,
+ (char_u *)VAR_WIN, PV_WRAP,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"wrapmargin", "wm", P_NUM|P_VI_DEF,
+ (char_u *)&p_wm, PV_WM,
+ {(char_u *)0L, (char_u *)0L}},
+ {"wrapscan", "ws", P_BOOL|P_VI_DEF,
+ (char_u *)&p_ws, PV_NONE,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"write", NULL, P_BOOL|P_VI_DEF,
+ (char_u *)&p_write, PV_NONE,
+ {(char_u *)TRUE, (char_u *)0L}},
+ {"writeany", "wa", P_BOOL|P_VI_DEF,
+ (char_u *)&p_wa, PV_NONE,
+ {(char_u *)FALSE, (char_u *)0L}},
+ {"writebackup", "wb", P_BOOL|P_VI_DEF|P_VIM,
+ (char_u *)&p_wb, PV_NONE,
+ {
+#ifdef FEAT_WRITEBACKUP
+ (char_u *)TRUE,
+#else
+ (char_u *)FALSE,
+#endif
+ (char_u *)0L}},
+ {"writedelay", "wd", P_NUM|P_VI_DEF,
+ (char_u *)&p_wd, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}},
+
+/* terminal output codes */
+#define p_term(sss, vvv) {sss, NULL, P_STRING|P_VI_DEF|P_RALL, \
+ (char_u *)&vvv, PV_NONE, \
+ {(char_u *)"", (char_u *)0L}},
+
+ p_term("t_AB", T_CAB)
+ p_term("t_AF", T_CAF)
+ p_term("t_AL", T_CAL)
+ p_term("t_al", T_AL)
+ p_term("t_bc", T_BC)
+ p_term("t_cd", T_CD)
+ p_term("t_ce", T_CE)
+ p_term("t_cl", T_CL)
+ p_term("t_cm", T_CM)
+ p_term("t_Co", T_CCO)
+ p_term("t_CS", T_CCS)
+ p_term("t_cs", T_CS)
+#ifdef FEAT_VERTSPLIT
+ p_term("t_CV", T_CSV)
+#endif
+ p_term("t_ut", T_UT)
+ p_term("t_da", T_DA)
+ p_term("t_db", T_DB)
+ p_term("t_DL", T_CDL)
+ p_term("t_dl", T_DL)
+ p_term("t_fs", T_FS)
+ p_term("t_IE", T_CIE)
+ p_term("t_IS", T_CIS)
+ p_term("t_ke", T_KE)
+ p_term("t_ks", T_KS)
+ p_term("t_le", T_LE)
+ p_term("t_mb", T_MB)
+ p_term("t_md", T_MD)
+ p_term("t_me", T_ME)
+ p_term("t_mr", T_MR)
+ p_term("t_ms", T_MS)
+ p_term("t_nd", T_ND)
+ p_term("t_op", T_OP)
+ p_term("t_RI", T_CRI)
+ p_term("t_RV", T_CRV)
+ p_term("t_Sb", T_CSB)
+ p_term("t_Sf", T_CSF)
+ p_term("t_se", T_SE)
+ p_term("t_so", T_SO)
+ p_term("t_sr", T_SR)
+ p_term("t_ts", T_TS)
+ p_term("t_te", T_TE)
+ p_term("t_ti", T_TI)
+ p_term("t_ue", T_UE)
+ p_term("t_us", T_US)
+ p_term("t_vb", T_VB)
+ p_term("t_ve", T_VE)
+ p_term("t_vi", T_VI)
+ p_term("t_vs", T_VS)
+ p_term("t_WP", T_CWP)
+ p_term("t_WS", T_CWS)
+ p_term("t_xs", T_XS)
+ p_term("t_ZH", T_CZH)
+ p_term("t_ZR", T_CZR)
+
+/* terminal key codes are not in here */
+
+ {NULL, NULL, 0, NULL, PV_NONE, {NULL, NULL}} /* end marker */
+};
+
+#define PARAM_COUNT (sizeof(options) / sizeof(struct vimoption))
+
+#ifdef FEAT_MBYTE
+static char *(p_ambw_values[]) = {"single", "double", NULL};
+#endif
+static char *(p_bg_values[]) = {"light", "dark", NULL};
+static char *(p_nf_values[]) = {"octal", "hex", "alpha", NULL};
+static char *(p_ff_values[]) = {FF_UNIX, FF_DOS, FF_MAC, NULL};
+#ifdef FEAT_WAK
+static char *(p_wak_values[]) = {"yes", "menu", "no", NULL};
+#endif
+static char *(p_mousem_values[]) = {"extend", "popup", "popup_setpos", "mac", NULL};
+#ifdef FEAT_VISUAL
+static char *(p_sel_values[]) = {"inclusive", "exclusive", "old", NULL};
+static char *(p_slm_values[]) = {"mouse", "key", "cmd", NULL};
+#endif
+#ifdef FEAT_VISUAL
+static char *(p_km_values[]) = {"startsel", "stopsel", NULL};
+#endif
+#ifdef FEAT_BROWSE
+static char *(p_bsdir_values[]) = {"current", "last", "buffer", NULL};
+#endif
+#ifdef FEAT_SCROLLBIND
+static char *(p_scbopt_values[]) = {"ver", "hor", "jump", NULL};
+#endif
+static char *(p_swb_values[]) = {"useopen", "split", NULL};
+static char *(p_debug_values[]) = {"msg", NULL};
+#ifdef FEAT_VERTSPLIT
+static char *(p_ead_values[]) = {"both", "ver", "hor", NULL};
+#endif
+#if defined(FEAT_QUICKFIX)
+static char *(p_buftype_values[]) = {"nofile", "nowrite", "quickfix", "help", NULL};
+static char *(p_bufhidden_values[]) = {"hide", "unload", "delete", "wipe", NULL};
+#endif
+static char *(p_bs_values[]) = {"indent", "eol", "start", NULL};
+#ifdef FEAT_FOLDING
+static char *(p_fdm_values[]) = {"manual", "expr", "marker", "indent", "syntax",
+#ifdef FEAT_DIFF
+ "diff",
+#endif
+ NULL};
+static char *(p_fcl_values[]) = {"all", NULL};
+#endif
+
+static void set_option_default __ARGS((int, int opt_flags, int compatible));
+static void set_options_default __ARGS((int opt_flags));
+static char_u *illegal_char __ARGS((char_u *, int));
+static int string_to_key __ARGS((char_u *arg));
+#ifdef FEAT_CMDWIN
+static char_u *check_cedit __ARGS((void));
+#endif
+#ifdef FEAT_TITLE
+static void did_set_title __ARGS((int icon));
+#endif
+static char_u *option_expand __ARGS((int opt_idx, char_u *val));
+static void didset_options __ARGS((void));
+static void check_string_option __ARGS((char_u **pp));
+static void set_string_option_global __ARGS((int opt_idx, char_u **varp));
+static void set_string_option __ARGS((int opt_idx, char_u *value, int opt_flags));
+static char_u *did_set_string_option __ARGS((int opt_idx, char_u **varp, int new_value_alloced, char_u *oldval, char_u *errbuf, int opt_flags));
+static char_u *set_chars_option __ARGS((char_u **varp));
+#ifdef FEAT_CLIPBOARD
+static char_u *check_clipboard_option __ARGS((void));
+#endif
+static char_u *set_bool_option __ARGS((int opt_idx, char_u *varp, int value, int opt_flags));
+static char_u *set_num_option __ARGS((int opt_idx, char_u *varp, long value, char_u *errbuf, int opt_flags));
+static void check_redraw __ARGS((long_u flags));
+static int findoption __ARGS((char_u *));
+static int find_key_option __ARGS((char_u *));
+static void showoptions __ARGS((int all, int opt_flags));
+static int optval_default __ARGS((struct vimoption *, char_u *varp));
+static void showoneopt __ARGS((struct vimoption *, int opt_flags));
+static int put_setstring __ARGS((FILE *fd, char *cmd, char *name, char_u **valuep, int expand));
+static int put_setnum __ARGS((FILE *fd, char *cmd, char *name, long *valuep));
+static int put_setbool __ARGS((FILE *fd, char *cmd, char *name, int value));
+static int istermoption __ARGS((struct vimoption *));
+static char_u *get_varp_scope __ARGS((struct vimoption *p, int opt_flags));
+static char_u *get_varp __ARGS((struct vimoption *));
+static void option_value2string __ARGS((struct vimoption *, int opt_flags));
+static int wc_use_keyname __ARGS((char_u *varp, long *wcp));
+#ifdef FEAT_LANGMAP
+static void langmap_init __ARGS((void));
+static void langmap_set __ARGS((void));
+#endif
+static void paste_option_changed __ARGS((void));
+static void compatible_set __ARGS((void));
+#ifdef FEAT_LINEBREAK
+static void fill_breakat_flags __ARGS((void));
+#endif
+static int opt_strings_flags __ARGS((char_u *val, char **values, unsigned *flagp, int list));
+static int check_opt_strings __ARGS((char_u *val, char **values, int));
+static int check_opt_wim __ARGS((void));
+
+/*
+ * Initialize the options, first part.
+ *
+ * Called only once from main(), just after creating the first buffer.
+ */
+ void
+set_init_1()
+{
+ char_u *p;
+ int opt_idx;
+ long n;
+
+#ifdef FEAT_LANGMAP
+ langmap_init();
+#endif
+
+ /* Be Vi compatible by default */
+ p_cp = TRUE;
+
+ /*
+ * Find default value for 'shell' option.
+ */
+ if ((p = mch_getenv((char_u *)"SHELL")) != NULL
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
+# ifdef __EMX__
+ || (p = mch_getenv((char_u *)"EMXSHELL")) != NULL
+# endif
+ || (p = mch_getenv((char_u *)"COMSPEC")) != NULL
+# ifdef WIN3264
+ || (p = default_shell()) != NULL
+# endif
+#endif
+ )
+ set_string_default("sh", p);
+
+#ifdef FEAT_WILDIGN
+ /*
+ * Set the default for 'backupskip' to include environment variables for
+ * temp files.
+ */
+ {
+# ifdef UNIX
+ static char *(names[4]) = {"", "TMPDIR", "TEMP", "TMP"};
+# else
+ static char *(names[3]) = {"TMPDIR", "TEMP", "TMP"};
+# endif
+ int len;
+ garray_T ga;
+
+ ga_init2(&ga, 1, 100);
+ for (n = 0; n < (long)(sizeof(names) / sizeof(char *)); ++n)
+ {
+# ifdef UNIX
+ if (*names[n] == NUL)
+ p = (char_u *)"/tmp";
+ else
+# endif
+ p = mch_getenv((char_u *)names[n]);
+ if (p != NULL && *p != NUL)
+ {
+ /* First time count the NUL, otherwise count the ','. */
+ len = STRLEN(p) + 3;
+ if (ga_grow(&ga, len) == OK)
+ {
+ if (ga.ga_len > 0)
+ STRCAT(ga.ga_data, ",");
+ STRCAT(ga.ga_data, p);
+ add_pathsep(ga.ga_data);
+ STRCAT(ga.ga_data, "*");
+ ga.ga_room -= len;
+ ga.ga_len += len;
+ }
+ }
+ }
+ if (ga.ga_data != NULL)
+ {
+ set_string_default("bsk", ga.ga_data);
+ vim_free(ga.ga_data);
+ }
+ }
+#endif
+
+ /*
+ * 'maxmemtot' and 'maxmem' may have to be adjusted for available memory
+ */
+ opt_idx = findoption((char_u *)"maxmemtot");
+#if !defined(HAVE_AVAIL_MEM) && !defined(HAVE_TOTAL_MEM)
+ if (options[opt_idx].def_val[VI_DEFAULT] == (char_u *)0L)
+#endif
+ {
+#ifdef HAVE_AVAIL_MEM
+ /* Use amount of memory available at this moment. */
+ n = (mch_avail_mem(FALSE) >> 11);
+#else
+# ifdef HAVE_TOTAL_MEM
+ /* Use amount of memory available to Vim. */
+ n = (mch_total_mem(FALSE) >> 11);
+# else
+ n = (0x7fffffff >> 11);
+# endif
+#endif
+ options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n;
+ opt_idx = findoption((char_u *)"maxmem");
+#if !defined(HAVE_AVAIL_MEM) && !defined(HAVE_TOTAL_MEM)
+ if ((long)options[opt_idx].def_val[VI_DEFAULT] > n
+ || (long)options[opt_idx].def_val[VI_DEFAULT] == 0L)
+#endif
+ options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n;
+ }
+
+#ifdef FEAT_GUI_W32
+ /* force 'shortname' for Win32s */
+ if (gui_is_win32s())
+ options[findoption((char_u *)"shortname")].def_val[VI_DEFAULT] =
+ (char_u *)TRUE;
+#endif
+
+#ifdef FEAT_SEARCHPATH
+ {
+ char_u *cdpath;
+ char_u *buf;
+ int i;
+ int j;
+
+ /* Initialize the 'cdpath' option's default value. */
+ cdpath = mch_getenv((char_u *)"CDPATH");
+ if (cdpath != NULL)
+ {
+ buf = alloc((unsigned)((STRLEN(cdpath) << 1) + 2));
+ if (buf != NULL)
+ {
+ buf[0] = ','; /* start with ",", current dir first */
+ j = 1;
+ for (i = 0; cdpath[i] != NUL; ++i)
+ {
+ if (vim_ispathlistsep(cdpath[i]))
+ buf[j++] = ',';
+ else
+ {
+ if (cdpath[i] == ' ' || cdpath[i] == ',')
+ buf[j++] = '\\';
+ buf[j++] = cdpath[i];
+ }
+ }
+ buf[j] = NUL;
+ opt_idx = findoption((char_u *)"cdpath");
+ options[opt_idx].def_val[VI_DEFAULT] = buf;
+ options[opt_idx].flags |= P_DEF_ALLOCED;
+ }
+ }
+ }
+#endif
+
+#if defined(FEAT_POSTSCRIPT) && (defined(MSWIN) || defined(OS2) || defined(VMS) || defined(EBCDIC) || defined(MAC) || defined(hpux))
+ /* Set print encoding on platforms that don't default to latin1 */
+ set_string_default("penc",
+# if defined(MSWIN) || defined(OS2)
+ (char_u *)"cp1252"
+# else
+# ifdef VMS
+ (char_u *)"dec-mcs"
+# else
+# ifdef EBCDIC
+ (char_u *)"ebcdic-uk"
+# else
+# ifdef MAC
+ (char_u *)"mac-roman"
+# else /* HPUX */
+ (char_u *)"hp-roman8"
+# endif
+# endif
+# endif
+# endif
+ );
+#endif
+
+#ifdef FEAT_POSTSCRIPT
+ /* 'printexpr' must be allocated to be able to evaluate it. */
+ set_string_default("pexpr",
+# ifdef MSWIN
+ (char_u *)"system('copy' . ' ' . v:fname_in . ' \"' . &printdevice . '\"') . delete(v:fname_in)"
+# else
+# ifdef VMS
+ (char_u *)"system('print/delete' . (&printdevice == '' ? '' : ' /queue=' . &printdevice) . ' ' . v:fname_in)"
+
+# else
+ (char_u *)"system('lpr' . (&printdevice == '' ? '' : ' -P' . &printdevice) . ' ' . v:fname_in) . delete(v:fname_in) + v:shell_error"
+# endif
+# endif
+ );
+#endif
+
+ /*
+ * Set all the options (except the terminal options) to their default
+ * value. Also set the global value for local options.
+ */
+ set_options_default(0);
+
+#ifdef FEAT_GUI
+ if (found_reverse_arg)
+ set_option_value((char_u *)"bg", 0L, (char_u *)"dark", 0);
+#endif
+
+ curbuf->b_p_initialized = TRUE;
+ curbuf->b_p_ar = -1; /* no local 'autoread' value */
+ check_buf_options(curbuf);
+ check_win_options(curwin);
+ check_options();
+
+ /* Must be before option_expand(), because that one needs vim_isIDc() */
+ didset_options();
+
+#ifdef FEAT_LINEBREAK
+ /*
+ * initialize the table for 'breakat'.
+ */
+ fill_breakat_flags();
+#endif
+
+ /*
+ * Expand environment variables and things like "~" for the defaults.
+ * If option_expand() returns non-NULL the variable is expanded. This can
+ * only happen for non-indirect options.
+ * Also set the default to the expanded value, so ":set" does not list
+ * them.
+ * Don't set the P_ALLOCED flag, because we don't want to free the
+ * default.
+ */
+ for (opt_idx = 0; !istermoption(&options[opt_idx]); opt_idx++)
+ {
+ if ((options[opt_idx].flags & P_GETTEXT)
+ && options[opt_idx].var != NULL)
+ p = (char_u *)_(*(char **)options[opt_idx].var);
+ else
+ p = option_expand(opt_idx, NULL);
+ if (p != NULL && (p = vim_strsave(p)) != NULL)
+ {
+ *(char_u **)options[opt_idx].var = p;
+ /* VIMEXP
+ * Defaults for all expanded options are currently the same for Vi
+ * and Vim. When this changes, add some code here! Also need to
+ * split P_DEF_ALLOCED in two.
+ */
+ if (options[opt_idx].flags & P_DEF_ALLOCED)
+ vim_free(options[opt_idx].def_val[VI_DEFAULT]);
+ options[opt_idx].def_val[VI_DEFAULT] = p;
+ options[opt_idx].flags |= P_DEF_ALLOCED;
+ }
+ }
+
+ /* Initialize the highlight_attr[] table. */
+ highlight_changed();
+
+ save_file_ff(curbuf); /* Buffer is unchanged */
+
+ /* Parse default for 'wildmode' */
+ check_opt_wim();
+
+#if defined(FEAT_ARABIC)
+ /* Detect use of mlterm.
+ * Mlterm is a terminal emulator akin to xterm that has some special
+ * abilities (bidi namely).
+ * NOTE: mlterm's author is being asked to 'set' a variable
+ * instead of an environment variable due to inheritance.
+ */
+ if (mch_getenv((char_u *)"MLTERM") != NULL)
+ set_option_value((char_u *)"tbidi", 1L, NULL, 0);
+#endif
+
+#if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING)
+ /* Parse default for 'fillchars'. */
+ (void)set_chars_option(&p_fcs);
+#endif
+
+#ifdef FEAT_CLIPBOARD
+ /* Parse default for 'clipboard' */
+ (void)check_clipboard_option();
+#endif
+
+#ifdef FEAT_MBYTE
+# if defined(WIN3264) && defined(FEAT_GETTEXT)
+ /*
+ * If $LANG isn't set, try to get a good value for it. This makes the
+ * right language be used automatically. Don't do this for English.
+ */
+ if (mch_getenv((char_u *)"LANG") == NULL)
+ {
+ char buf[20];
+
+ /* Could use LOCALE_SISO639LANGNAME, but it's not in Win95.
+ * LOCALE_SABBREVLANGNAME gives us three letters, like "enu", we use
+ * only the first two. */
+ n = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVLANGNAME,
+ (LPTSTR)buf, 20);
+ if (n >= 2 && STRNICMP(buf, "en", 2) != 0)
+ {
+ /* There are a few exceptions (probably more) */
+ if (STRNICMP(buf, "cht", 3) == 0 || STRNICMP(buf, "zht", 3) == 0)
+ STRCPY(buf, "zh_TW");
+ else if (STRNICMP(buf, "chs", 3) == 0
+ || STRNICMP(buf, "zhc", 3) == 0)
+ STRCPY(buf, "zh_CN");
+ else if (STRNICMP(buf, "jp", 2) == 0)
+ STRCPY(buf, "ja");
+ else
+ buf[2] = NUL; /* truncate to two-letter code */
+ vim_setenv("LANG", buf);
+ }
+ }
+# endif
+
+ /* enc_locale() will try to find the encoding of the current locale. */
+ p = enc_locale();
+ if (p != NULL)
+ {
+ char_u *save_enc;
+
+ /* Try setting 'encoding' and check if the value is valid.
+ * If not, go back to the default "latin1". */
+ save_enc = p_enc;
+ p_enc = p;
+ if (mb_init() == NULL)
+ {
+ opt_idx = findoption((char_u *)"encoding");
+ options[opt_idx].def_val[VI_DEFAULT] = p_enc;
+ options[opt_idx].flags |= P_DEF_ALLOCED;
+
+# if defined(WIN3264) && !defined(FEAT_GUI)
+ /* Win32 console: When GetACP() returns a different value from
+ * GetConsoleCP() set 'termencoding'. */
+ if (GetACP() != GetConsoleCP())
+ {
+ char buf[50];
+
+ sprintf(buf, "cp%ld", (long)GetConsoleCP());
+ p_tenc = vim_strsave((char_u *)buf);
+ if (p_tenc != NULL)
+ {
+ opt_idx = findoption((char_u *)"termencoding");
+ options[opt_idx].def_val[VI_DEFAULT] = p_tenc;
+ options[opt_idx].flags |= P_DEF_ALLOCED;
+ convert_setup(&input_conv, p_tenc, p_enc);
+ convert_setup(&output_conv, p_enc, p_tenc);
+ }
+ else
+ p_tenc = empty_option;
+ }
+# endif
+ }
+ else
+ {
+ vim_free(p_enc);
+ p_enc = save_enc;
+ }
+ }
+#endif
+
+#ifdef FEAT_MULTI_LANG
+ /* Set the default for 'helplang'. */
+ set_helplang_default(get_mess_lang());
+#endif
+}
+
+/*
+ * Set an option to its default value.
+ * This does not take care of side effects!
+ */
+ static void
+set_option_default(opt_idx, opt_flags, compatible)
+ int opt_idx;
+ int opt_flags; /* OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL */
+ int compatible; /* use Vi default value */
+{
+ char_u *varp; /* pointer to variable for current option */
+ int dvi; /* index in def_val[] */
+ long_u flags;
+ int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
+
+ varp = get_varp_scope(&(options[opt_idx]), both ? OPT_LOCAL : opt_flags);
+ flags = options[opt_idx].flags;
+ if (varp != NULL) /* nothing to do for hidden option */
+ {
+ dvi = ((flags & P_VI_DEF) || compatible) ? VI_DEFAULT : VIM_DEFAULT;
+ if (flags & P_STRING)
+ {
+ /* Use set_string_option_direct() for local options to handle
+ * freeing and allocating the value. */
+ if (options[opt_idx].indir != PV_NONE)
+ set_string_option_direct(NULL, opt_idx,
+ options[opt_idx].def_val[dvi], opt_flags);
+ else
+ {
+ if ((opt_flags & OPT_FREE) && (flags & P_ALLOCED))
+ free_string_option(*(char_u **)(varp));
+ *(char_u **)varp = options[opt_idx].def_val[dvi];
+ options[opt_idx].flags &= ~P_ALLOCED;
+ }
+ }
+ else if (flags & P_NUM)
+ {
+ if (varp == (char_u *)PV_SCROLL)
+ win_comp_scroll(curwin);
+ else
+ {
+ *(long *)varp = (long)options[opt_idx].def_val[dvi];
+ /* May also set global value for local option. */
+ if (both)
+ *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
+ *(long *)varp;
+ }
+ }
+ else /* P_BOOL */
+ {
+ /* the cast to long is required for Manx C */
+ *(int *)varp = (int)(long)options[opt_idx].def_val[dvi];
+ /* May also set global value for local option. */
+ if (both)
+ *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
+ *(int *)varp;
+ }
+ }
+
+#ifdef FEAT_EVAL
+ /* Remember where the option was set. */
+ options[opt_idx].scriptID = current_SID;
+#endif
+}
+
+/*
+ * Set all options (except terminal options) to their default value.
+ */
+ static void
+set_options_default(opt_flags)
+ int opt_flags; /* OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL */
+{
+ int i;
+#ifdef FEAT_WINDOWS
+ win_T *wp;
+#endif
+
+ for (i = 0; !istermoption(&options[i]); i++)
+ if (!(options[i].flags & P_NODEFAULT))
+ set_option_default(i, opt_flags, p_cp);
+
+#ifdef FEAT_WINDOWS
+ /* The 'scroll' option must be computed for all windows. */
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ win_comp_scroll(wp);
+#else
+ win_comp_scroll(curwin);
+#endif
+}
+
+/*
+ * Set the Vi-default value of a string option.
+ * Used for 'sh', 'backupskip' and 'term'.
+ */
+ void
+set_string_default(name, val)
+ char *name;
+ char_u *val;
+{
+ char_u *p;
+ int opt_idx;
+
+ p = vim_strsave(val);
+ if (p != NULL) /* we don't want a NULL */
+ {
+ opt_idx = findoption((char_u *)name);
+ if (options[opt_idx].flags & P_DEF_ALLOCED)
+ vim_free(options[opt_idx].def_val[VI_DEFAULT]);
+ options[opt_idx].def_val[VI_DEFAULT] = p;
+ options[opt_idx].flags |= P_DEF_ALLOCED;
+ }
+}
+
+/*
+ * Set the Vi-default value of a number option.
+ * Used for 'lines' and 'columns'.
+ */
+ void
+set_number_default(name, val)
+ char *name;
+ long val;
+{
+ options[findoption((char_u *)name)].def_val[VI_DEFAULT] = (char_u *)val;
+}
+
+/*
+ * Initialize the options, part two: After getting Rows and Columns and
+ * setting 'term'.
+ */
+ void
+set_init_2()
+{
+ /*
+ * 'scroll' defaults to half the window height. Note that this default is
+ * wrong when the window height changes.
+ */
+ options[findoption((char_u *)"scroll")].def_val[VI_DEFAULT]
+ = (char_u *)((long_u)Rows >> 1);
+ comp_col();
+
+#if !((defined(MSDOS) || defined(OS2) || defined(WIN3264)) && !defined(FEAT_GUI))
+ {
+ int idx4;
+
+ /*
+ * If 'background' wasn't set by the user, try guessing the value,
+ * depending on the terminal name. Only need to check for terminals
+ * with a dark background, that can handle color. Only "linux"
+ * console at the moment.
+ */
+ idx4 = findoption((char_u *)"bg");
+ if (!(options[idx4].flags & P_WAS_SET) && STRCMP(T_NAME, "linux") == 0)
+ {
+ set_string_option_direct(NULL, idx4, (char_u *)"dark", OPT_FREE);
+ /* don't mark it as set, when starting the GUI it may be changed
+ * again */
+ options[idx4].flags &= ~P_WAS_SET;
+ }
+ }
+#endif
+}
+
+/*
+ * Initialize the options, part three: After reading the .vimrc
+ */
+ void
+set_init_3()
+{
+#if defined(UNIX) || defined(OS2) || defined(WIN3264)
+/*
+ * Set 'shellpipe' and 'shellredir', depending on the 'shell' option.
+ * This is done after other initializations, where 'shell' might have been
+ * set, but only if they have not been set before.
+ */
+ char_u *p;
+ int idx_srr;
+ int do_srr;
+#ifdef FEAT_QUICKFIX
+ int idx_sp;
+ int do_sp;
+#endif
+
+ idx_srr = findoption((char_u *)"srr");
+ do_srr = !(options[idx_srr].flags & P_WAS_SET);
+#ifdef FEAT_QUICKFIX
+ idx_sp = findoption((char_u *)"sp");
+ do_sp = !(options[idx_sp].flags & P_WAS_SET);
+#endif
+
+ /*
+ * Isolate the name of the shell:
+ * - Skip beyond any path. E.g., "/usr/bin/csh -f" -> "csh -f".
+ * - Remove any argument. E.g., "csh -f" -> "csh".
+ */
+ p = gettail(p_sh);
+ p = vim_strnsave(p, (int)(skiptowhite(p) - p));
+ if (p != NULL)
+ {
+ /*
+ * Default for p_sp is "| tee", for p_srr is ">".
+ * For known shells it is changed here to include stderr.
+ */
+ if ( fnamecmp(p, "csh") == 0
+ || fnamecmp(p, "tcsh") == 0
+# if defined(OS2) || defined(WIN3264) /* also check with .exe extension */
+ || fnamecmp(p, "csh.exe") == 0
+ || fnamecmp(p, "tcsh.exe") == 0
+# endif
+ )
+ {
+#if defined(FEAT_QUICKFIX)
+ if (do_sp)
+ {
+# ifdef WIN3264
+ p_sp = (char_u *)">&";
+# else
+ p_sp = (char_u *)"|& tee";
+# endif
+ options[idx_sp].def_val[VI_DEFAULT] = p_sp;
+ }
+#endif
+ if (do_srr)
+ {
+ p_srr = (char_u *)">&";
+ options[idx_srr].def_val[VI_DEFAULT] = p_srr;
+ }
+ }
+ else
+# ifndef OS2 /* Always use bourne shell style redirection if we reach this */
+ if ( fnamecmp(p, "sh") == 0
+ || fnamecmp(p, "ksh") == 0
+ || fnamecmp(p, "zsh") == 0
+ || fnamecmp(p, "bash") == 0
+# ifdef WIN3264
+ || fnamecmp(p, "cmd") == 0
+ || fnamecmp(p, "sh.exe") == 0
+ || fnamecmp(p, "ksh.exe") == 0
+ || fnamecmp(p, "zsh.exe") == 0
+ || fnamecmp(p, "bash.exe") == 0
+ || fnamecmp(p, "cmd.exe") == 0
+# endif
+ )
+# endif
+ {
+#if defined(FEAT_QUICKFIX)
+ if (do_sp)
+ {
+# ifdef WIN3264
+ p_sp = (char_u *)">%s 2>&1";
+# else
+ p_sp = (char_u *)"2>&1| tee";
+# endif
+ options[idx_sp].def_val[VI_DEFAULT] = p_sp;
+ }
+#endif
+ if (do_srr)
+ {
+ p_srr = (char_u *)">%s 2>&1";
+ options[idx_srr].def_val[VI_DEFAULT] = p_srr;
+ }
+ }
+ vim_free(p);
+ }
+#endif
+
+#if defined(MSDOS) || defined(WIN3264) || defined(OS2)
+ /*
+ * Set 'shellcmdflag and 'shellquote' depending on the 'shell' option.
+ * This is done after other initializations, where 'shell' might have been
+ * set, but only if they have not been set before. Default for p_shcf is
+ * "/c", for p_shq is "". For "sh" like shells it is changed here to
+ * "-c" and "\"", but not for DJGPP, because it starts the shell without
+ * command.com. And for Win32 we need to set p_sxq instead.
+ */
+ if (strstr((char *)p_sh, "sh") != NULL)
+ {
+ int idx3;
+
+ idx3 = findoption((char_u *)"shcf");
+ if (!(options[idx3].flags & P_WAS_SET))
+ {
+ p_shcf = (char_u *)"-c";
+ options[idx3].def_val[VI_DEFAULT] = p_shcf;
+ }
+
+# ifndef DJGPP
+# ifdef WIN3264
+ /* Somehow Win32 requires the quotes around the redirection too */
+ idx3 = findoption((char_u *)"sxq");
+ if (!(options[idx3].flags & P_WAS_SET))
+ {
+ p_sxq = (char_u *)"\"";
+ options[idx3].def_val[VI_DEFAULT] = p_sxq;
+ }
+# else
+ idx3 = findoption((char_u *)"shq");
+ if (!(options[idx3].flags & P_WAS_SET))
+ {
+ p_shq = (char_u *)"\"";
+ options[idx3].def_val[VI_DEFAULT] = p_shq;
+ }
+# endif
+# endif
+ }
+#endif
+
+#ifdef FEAT_TITLE
+ set_title_defaults();
+#endif
+}
+
+#if defined(FEAT_MULTI_LANG) || defined(PROTO)
+/*
+ * When 'helplang' is still at its default value, set it to "lang".
+ * Only the first two characters of "lang" are used.
+ */
+ void
+set_helplang_default(lang)
+ char_u *lang;
+{
+ int idx;
+
+ if (lang == NULL || STRLEN(lang) < 2) /* safety check */
+ return;
+ idx = findoption((char_u *)"hlg");
+ if (!(options[idx].flags & P_WAS_SET))
+ {
+ if (options[idx].flags & P_ALLOCED)
+ free_string_option(p_hlg);
+ p_hlg = vim_strsave(lang);
+ if (p_hlg == NULL)
+ p_hlg = empty_option;
+ else
+ p_hlg[2] = NUL;
+ options[idx].flags |= P_ALLOCED;
+ }
+}
+#endif
+
+#ifdef FEAT_GUI
+static char_u *gui_bg_default __ARGS((void));
+
+ static char_u *
+gui_bg_default()
+{
+ if (gui_get_lightness(gui.back_pixel) < 127)
+ return (char_u *)"dark";
+ return (char_u *)"light";
+}
+
+/*
+ * Option initializations that can only be done after opening the GUI window.
+ */
+ void
+init_gui_options()
+{
+ /* Set the 'background' option according to the lightness of the
+ * background color, unless the user has set it already. */
+ if (!option_was_set((char_u *)"bg") && STRCMP(p_bg, gui_bg_default()) != 0)
+ {
+ set_option_value((char_u *)"bg", 0L, gui_bg_default(), 0);
+ highlight_changed();
+ }
+}
+#endif
+
+#ifdef FEAT_TITLE
+/*
+ * 'title' and 'icon' only default to true if they have not been set or reset
+ * in .vimrc and we can read the old value.
+ * When 'title' and 'icon' have been reset in .vimrc, we won't even check if
+ * they can be reset. This reduces startup time when using X on a remote
+ * machine.
+ */
+ void
+set_title_defaults()
+{
+ int idx1;
+ long val;
+
+ /*
+ * If GUI is (going to be) used, we can always set the window title and
+ * icon name. Saves a bit of time, because the X11 display server does
+ * not need to be contacted.
+ */
+ idx1 = findoption((char_u *)"title");
+ if (!(options[idx1].flags & P_WAS_SET))
+ {
+#ifdef FEAT_GUI
+ if (gui.starting || gui.in_use)
+ val = TRUE;
+ else
+#endif
+ val = mch_can_restore_title();
+ options[idx1].def_val[VI_DEFAULT] = (char_u *)val;
+ p_title = val;
+ }
+ idx1 = findoption((char_u *)"icon");
+ if (!(options[idx1].flags & P_WAS_SET))
+ {
+#ifdef FEAT_GUI
+ if (gui.starting || gui.in_use)
+ val = TRUE;
+ else
+#endif
+ val = mch_can_restore_icon();
+ options[idx1].def_val[VI_DEFAULT] = (char_u *)val;
+ p_icon = val;
+ }
+}
+#endif
+
+/*
+ * Parse 'arg' for option settings.
+ *
+ * 'arg' may be IObuff, but only when no errors can be present and option
+ * does not need to be expanded with option_expand().
+ * "opt_flags":
+ * 0 for ":set"
+ * OPT_GLOBAL for ":setglobal"
+ * OPT_LOCAL for ":setlocal" and a modeline
+ * OPT_MODELINE for a modeline
+ *
+ * returns FAIL if an error is detected, OK otherwise
+ */
+ int
+do_set(arg, opt_flags)
+ char_u *arg; /* option string (may be written to!) */
+ int opt_flags;
+{
+ int opt_idx;
+ char_u *errmsg;
+ char_u errbuf[80];
+ char_u *startarg;
+ int prefix; /* 1: nothing, 0: "no", 2: "inv" in front of name */
+ int nextchar; /* next non-white char after option name */
+ int afterchar; /* character just after option name */
+ int len;
+ int i;
+ long value;
+ int key;
+ long_u flags; /* flags for current option */
+ char_u *varp = NULL; /* pointer to variable for current option */
+ int did_show = FALSE; /* already showed one value */
+ int adding; /* "opt+=arg" */
+ int prepending; /* "opt^=arg" */
+ int removing; /* "opt-=arg" */
+ int cp_val = 0;
+ char_u key_name[2];
+
+ if (*arg == NUL)
+ {
+ showoptions(0, opt_flags);
+ return OK;
+ }
+
+ while (*arg != NUL) /* loop to process all options */
+ {
+ errmsg = NULL;
+ startarg = arg; /* remember for error message */
+
+ if (STRNCMP(arg, "all", 3) == 0 && !isalpha(arg[3]))
+ {
+ /*
+ * ":set all" show all options.
+ * ":set all&" set all options to their default value.
+ */
+ arg += 3;
+ if (*arg == '&')
+ {
+ ++arg;
+ /* Only for :set command set global value of local options. */
+ set_options_default(OPT_FREE | opt_flags);
+ }
+ else
+ showoptions(1, opt_flags);
+ }
+ else if (STRNCMP(arg, "termcap", 7) == 0)
+ {
+ showoptions(2, opt_flags);
+ show_termcodes();
+ arg += 7;
+ }
+ else
+ {
+ prefix = 1;
+ if (STRNCMP(arg, "no", 2) == 0)
+ {
+ prefix = 0;
+ arg += 2;
+ }
+ else if (STRNCMP(arg, "inv", 3) == 0)
+ {
+ prefix = 2;
+ arg += 3;
+ }
+
+ /* find end of name */
+ key = 0;
+ if (*arg == '<')
+ {
+ nextchar = 0;
+ opt_idx = -1;
+ /* look out for <t_>;> */
+ if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4])
+ len = 5;
+ else
+ {
+ len = 1;
+ while (arg[len] != NUL && arg[len] != '>')
+ ++len;
+ }
+ if (arg[len] != '>')
+ {
+ errmsg = e_invarg;
+ goto skip;
+ }
+ arg[len] = NUL; /* put NUL after name */
+ if (arg[1] == 't' && arg[2] == '_') /* could be term code */
+ opt_idx = findoption(arg + 1);
+ arg[len++] = '>'; /* restore '>' */
+ if (opt_idx == -1)
+ key = find_key_option(arg + 1);
+ }
+ else
+ {
+ len = 0;
+ /*
+ * The two characters after "t_" may not be alphanumeric.
+ */
+ if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
+ len = 4;
+ else
+ while (ASCII_ISALNUM(arg[len]) || arg[len] == '_')
+ ++len;
+ nextchar = arg[len];
+ arg[len] = NUL; /* put NUL after name */
+ opt_idx = findoption(arg);
+ arg[len] = nextchar; /* restore nextchar */
+ if (opt_idx == -1)
+ key = find_key_option(arg);
+ }
+
+ /* remember character after option name */
+ afterchar = arg[len];
+
+ /* skip white space, allow ":set ai ?" */
+ while (vim_iswhite(arg[len]))
+ ++len;
+
+ adding = FALSE;
+ prepending = FALSE;
+ removing = FALSE;
+ if (arg[len] != NUL && arg[len + 1] == '=')
+ {
+ if (arg[len] == '+')
+ {
+ adding = TRUE; /* "+=" */
+ ++len;
+ }
+ else if (arg[len] == '^')
+ {
+ prepending = TRUE; /* "^=" */
+ ++len;
+ }
+ else if (arg[len] == '-')
+ {
+ removing = TRUE; /* "-=" */
+ ++len;
+ }
+ }
+ nextchar = arg[len];
+
+ if (opt_idx == -1 && key == 0) /* found a mismatch: skip */
+ {
+ errmsg = (char_u *)N_("E518: Unknown option");
+ goto skip;
+ }
+
+ if (opt_idx >= 0)
+ {
+ if (options[opt_idx].var == NULL) /* hidden option: skip */
+ {
+ /* Only give an error message when requesting the value of
+ * a hidden option, ignore setting it. */
+ if (vim_strchr((char_u *)"=:!&<", nextchar) == NULL
+ && (!(options[opt_idx].flags & P_BOOL)
+ || nextchar == '?'))
+ errmsg = (char_u *)N_("E519: Option not supported");
+ goto skip;
+ }
+
+ flags = options[opt_idx].flags;
+ varp = get_varp_scope(&(options[opt_idx]), opt_flags);
+ }
+ else
+ {
+ flags = P_STRING;
+ if (key < 0)
+ {
+ key_name[0] = KEY2TERMCAP0(key);
+ key_name[1] = KEY2TERMCAP1(key);
+ }
+ else
+ {
+ key_name[0] = KS_KEY;
+ key_name[1] = (key & 0xff);
+ }
+ }
+
+ /* Disallow changing some options from modelines */
+ if ((opt_flags & OPT_MODELINE) && (flags & P_SECURE))
+ {
+ errmsg = (char_u *)_("E520: Not allowed in a modeline");
+ goto skip;
+ }
+
+#ifdef HAVE_SANDBOX
+ /* Disallow changing some options in the sandbox */
+ if (sandbox > 0 && (flags & P_SECURE))
+ {
+ errmsg = (char_u *)_(e_sandbox);
+ goto skip;
+ }
+#endif
+
+ if (vim_strchr((char_u *)"?=:!&<", nextchar) != NULL)
+ {
+ arg += len;
+ cp_val = p_cp;
+ if (nextchar == '&' && arg[1] == 'v' && arg[2] == 'i')
+ {
+ if (arg[3] == 'm') /* "opt&vim": set to Vim default */
+ {
+ cp_val = FALSE;
+ arg += 3;
+ }
+ else /* "opt&vi": set to Vi default */
+ {
+ cp_val = TRUE;
+ arg += 2;
+ }
+ }
+ if (vim_strchr((char_u *)"?!&<", nextchar) != NULL
+ && arg[1] != NUL && !vim_iswhite(arg[1]))
+ {
+ errmsg = e_trailing;
+ goto skip;
+ }
+ }
+
+ /*
+ * allow '=' and ':' as MSDOS command.com allows only one
+ * '=' character per "set" command line. grrr. (jw)
+ */
+ if (nextchar == '?'
+ || (prefix == 1
+ && vim_strchr((char_u *)"=:&<", nextchar) == NULL
+ && !(flags & P_BOOL)))
+ {
+ /*
+ * print value
+ */
+ if (did_show)
+ msg_putchar('\n'); /* cursor below last one */
+ else
+ {
+ gotocmdline(TRUE); /* cursor at status line */
+ did_show = TRUE; /* remember that we did a line */
+ }
+ if (opt_idx >= 0)
+ {
+ showoneopt(&options[opt_idx], opt_flags);
+#ifdef FEAT_EVAL
+ if (p_verbose > 0)
+ {
+ if (options[opt_idx].scriptID != 0)
+ {
+ MSG_PUTS(_("\n\tLast set from "));
+ MSG_PUTS(get_scriptname(options[opt_idx].scriptID));
+ }
+ }
+#endif
+ }
+ else
+ {
+ char_u *p;
+
+ p = find_termcode(key_name);
+ if (p == NULL)
+ {
+ errmsg = (char_u *)N_("E518: Unknown option");
+ goto skip;
+ }
+ else
+ (void)show_one_termcode(key_name, p, TRUE);
+ }
+ if (nextchar != '?'
+ && nextchar != NUL && !vim_iswhite(afterchar))
+ errmsg = e_trailing;
+ }
+ else
+ {
+ if (flags & P_BOOL) /* boolean */
+ {
+ if (nextchar == '=' || nextchar == ':')
+ {
+ errmsg = e_invarg;
+ goto skip;
+ }
+
+ /*
+ * ":set opt!": invert
+ * ":set opt&": reset to default value
+ * ":set opt<": reset to global value
+ */
+ if (nextchar == '!')
+ value = *(int *)(varp) ^ 1;
+ else if (nextchar == '&')
+ value = (int)(long)options[opt_idx].def_val[
+ ((flags & P_VI_DEF) || cp_val)
+ ? VI_DEFAULT : VIM_DEFAULT];
+ else if (nextchar == '<')
+ {
+ /* For 'autoread' -1 means to use global value. */
+ if ((int *)varp == &curbuf->b_p_ar
+ && opt_flags == OPT_LOCAL)
+ value = -1;
+ else
+ value = *(int *)get_varp_scope(&(options[opt_idx]),
+ OPT_GLOBAL);
+ }
+ else
+ {
+ /*
+ * ":set invopt": invert
+ * ":set opt" or ":set noopt": set or reset
+ */
+ if (nextchar != NUL && !vim_iswhite(afterchar))
+ {
+ errmsg = e_trailing;
+ goto skip;
+ }
+ if (prefix == 2) /* inv */
+ value = *(int *)(varp) ^ 1;
+ else
+ value = prefix;
+ }
+
+ errmsg = set_bool_option(opt_idx, varp, (int)value,
+ opt_flags);
+ }
+ else /* numeric or string */
+ {
+ if (vim_strchr((char_u *)"=:&<", nextchar) == NULL
+ || prefix != 1)
+ {
+ errmsg = e_invarg;
+ goto skip;
+ }
+
+ if (flags & P_NUM) /* numeric */
+ {
+ /*
+ * Different ways to set a number option:
+ * & set to default value
+ * < set to global value
+ * <xx> accept special key codes for 'wildchar'
+ * c accept any non-digit for 'wildchar'
+ * [-]0-9 set number
+ * other error
+ */
+ ++arg;
+ if (nextchar == '&')
+ value = (long)options[opt_idx].def_val[
+ ((flags & P_VI_DEF) || cp_val)
+ ? VI_DEFAULT : VIM_DEFAULT];
+ else if (nextchar == '<')
+ value = *(long *)get_varp_scope(&(options[opt_idx]),
+ OPT_GLOBAL);
+ else if (((long *)varp == &p_wc
+ || (long *)varp == &p_wcm)
+ && (*arg == '<'
+ || *arg == '^'
+ || ((!arg[1] || vim_iswhite(arg[1]))
+ && !VIM_ISDIGIT(*arg))))
+ {
+ value = string_to_key(arg);
+ if (value == 0 && (long *)varp != &p_wcm)
+ {
+ errmsg = e_invarg;
+ goto skip;
+ }
+ }
+ /* allow negative numbers (for 'undolevels') */
+ else if (*arg == '-' || VIM_ISDIGIT(*arg))
+ {
+ i = 0;
+ if (*arg == '-')
+ i = 1;
+#ifdef HAVE_STRTOL
+ value = strtol((char *)arg, NULL, 0);
+ if (arg[i] == '0' && TOLOWER_ASC(arg[i + 1]) == 'x')
+ i += 2;
+#else
+ value = atol((char *)arg);
+#endif
+ while (VIM_ISDIGIT(arg[i]))
+ ++i;
+ if (arg[i] != NUL && !vim_iswhite(arg[i]))
+ {
+ errmsg = e_invarg;
+ goto skip;
+ }
+ }
+ else
+ {
+ errmsg = (char_u *)N_("E521: Number required after =");
+ goto skip;
+ }
+
+ if (adding)
+ value = *(long *)varp + value;
+ if (prepending)
+ value = *(long *)varp * value;
+ if (removing)
+ value = *(long *)varp - value;
+ errmsg = set_num_option(opt_idx, varp, value,
+ errbuf, opt_flags);
+ }
+ else if (opt_idx >= 0) /* string */
+ {
+ char_u *save_arg = NULL;
+ char_u *s = NULL;
+ char_u *oldval; /* previous value if *varp */
+ char_u *newval;
+ char_u *origval;
+ unsigned newlen;
+ int comma;
+ int bs;
+ int new_value_alloced; /* new string option
+ was allocated */
+
+ /* When using ":set opt=val" for a global option
+ * with a local value the local value will be
+ * reset, use the global value here. */
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
+ && (int)options[opt_idx].indir >= PV_BOTH)
+ varp = options[opt_idx].var;
+
+ /* The old value is kept until we are sure that the
+ * new value is valid. */
+ oldval = *(char_u **)varp;
+ if (nextchar == '&') /* set to default val */
+ {
+ newval = options[opt_idx].def_val[
+ ((flags & P_VI_DEF) || cp_val)
+ ? VI_DEFAULT : VIM_DEFAULT];
+ if ((char_u **)varp == &p_bg)
+ {
+ /* guess the value of 'background' */
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ newval = gui_bg_default();
+ else
+#endif
+ if (STRCMP(T_NAME, "linux") == 0)
+ newval = (char_u *)"dark";
+ }
+
+ /* expand environment variables and ~ (since the
+ * default value was already expanded, only
+ * required when an environment variable was set
+ * later */
+ if (newval == NULL)
+ newval = empty_option;
+ else
+ {
+ s = option_expand(opt_idx, newval);
+ if (s == NULL)
+ s = newval;
+ newval = vim_strsave(s);
+ }
+ new_value_alloced = TRUE;
+ }
+ else if (nextchar == '<') /* set to global val */
+ {
+ newval = vim_strsave(*(char_u **)get_varp_scope(
+ &(options[opt_idx]), OPT_GLOBAL));
+ new_value_alloced = TRUE;
+ }
+ else
+ {
+ ++arg; /* jump to after the '=' or ':' */
+
+ /*
+ * Set 'keywordprg' to ":help" if an empty
+ * value was passed to :set by the user.
+ * Misuse errbuf[] for the resulting string.
+ */
+ if (varp == (char_u *)&p_kp
+ && (*arg == NUL || *arg == ' '))
+ {
+ STRCPY(errbuf, ":help");
+ save_arg = arg;
+ arg = errbuf;
+ }
+ /*
+ * Convert 'whichwrap' number to string, for
+ * backwards compatibility with Vim 3.0.
+ * Misuse errbuf[] for the resulting string.
+ */
+ else if (varp == (char_u *)&p_ww
+ && VIM_ISDIGIT(*arg))
+ {
+ *errbuf = NUL;
+ i = getdigits(&arg);
+ if (i & 1)
+ STRCAT(errbuf, "b,");
+ if (i & 2)
+ STRCAT(errbuf, "s,");
+ if (i & 4)
+ STRCAT(errbuf, "h,l,");
+ if (i & 8)
+ STRCAT(errbuf, "<,>,");
+ if (i & 16)
+ STRCAT(errbuf, "[,],");
+ if (*errbuf != NUL) /* remove trailing , */
+ errbuf[STRLEN(errbuf) - 1] = NUL;
+ save_arg = arg;
+ arg = errbuf;
+ }
+ /*
+ * Remove '>' before 'dir' and 'bdir', for
+ * backwards compatibility with version 3.0
+ */
+ else if ( *arg == '>'
+ && (varp == (char_u *)&p_dir
+ || varp == (char_u *)&p_bdir))
+ {
+ ++arg;
+ }
+
+ /* When setting the local value of a global
+ * option, the old value may be the global value. */
+ if ((int)options[opt_idx].indir >= PV_BOTH
+ && (opt_flags & OPT_LOCAL))
+ origval = *(char_u **)get_varp(
+ &options[opt_idx]);
+ else
+ origval = oldval;
+
+ /*
+ * Copy the new string into allocated memory.
+ * Can't use set_string_option_direct(), because
+ * we need to remove the backslashes.
+ */
+ /* get a bit too much */
+ newlen = (unsigned)STRLEN(arg) + 1;
+ if (adding || prepending || removing)
+ newlen += (unsigned)STRLEN(origval) + 1;
+ newval = alloc(newlen);
+ if (newval == NULL) /* out of mem, don't change */
+ break;
+ s = newval;
+
+ /*
+ * Copy the string, skip over escaped chars.
+ * For MS-DOS and WIN32 backslashes before normal
+ * file name characters are not removed, and keep
+ * backslash at start, for "\\machine\path", but
+ * do remove it for "\\\\machine\\path".
+ * The reverse is found in ExpandOldSetting().
+ */
+ while (*arg && !vim_iswhite(*arg))
+ {
+ if (*arg == '\\' && arg[1] != NUL
+#ifdef BACKSLASH_IN_FILENAME
+ && !((flags & P_EXPAND)
+ && vim_isfilec(arg[1])
+ && (arg[1] != '\\'
+ || (s == newval
+ && arg[2] != '\\')))
+#endif
+ )
+ ++arg; /* remove backslash */
+#ifdef FEAT_MBYTE
+ if (has_mbyte
+ && (i = (*mb_ptr2len_check)(arg)) > 1)
+ {
+ /* copy multibyte char */
+ mch_memmove(s, arg, (size_t)i);
+ arg += i;
+ s += i;
+ }
+ else
+#endif
+ *s++ = *arg++;
+ }
+ *s = NUL;
+
+ /*
+ * Expand environment variables and ~.
+ * Don't do it when adding without inserting a
+ * comma.
+ */
+ if (!(adding || prepending || removing)
+ || (flags & P_COMMA))
+ {
+ s = option_expand(opt_idx, newval);
+ if (s != NULL)
+ {
+ vim_free(newval);
+ newlen = (unsigned)STRLEN(s) + 1;
+ if (adding || prepending || removing)
+ newlen += (unsigned)STRLEN(origval) + 1;
+ newval = alloc(newlen);
+ if (newval == NULL)
+ break;
+ STRCPY(newval, s);
+ }
+ }
+
+ /* locate newval[] in origval[] when removing it
+ * and when adding to avoid duplicates */
+ i = 0; /* init for GCC */
+ if (removing || (flags & P_NODUP))
+ {
+ i = (int)STRLEN(newval);
+ bs = 0;
+ for (s = origval; *s; ++s)
+ {
+ if ((!(flags & P_COMMA)
+ || s == origval
+ || (s[-1] == ',' && !(bs & 1)))
+ && STRNCMP(s, newval, i) == 0
+ && (!(flags & P_COMMA)
+ || s[i] == ','
+ || s[i] == NUL))
+ break;
+ /* Count backspaces. Only a comma with an
+ * even number of backspaces before it is
+ * recognized as a separator */
+ if (s > origval && s[-1] == '\\')
+ ++bs;
+ else
+ bs = 0;
+ }
+
+ /* do not add if already there */
+ if ((adding || prepending) && *s)
+ {
+ prepending = FALSE;
+ adding = FALSE;
+ STRCPY(newval, origval);
+ }
+ }
+
+ /* concatenate the two strings; add a ',' if
+ * needed */
+ if (adding || prepending)
+ {
+ comma = ((flags & P_COMMA) && *origval != NUL
+ && *newval != NUL);
+ if (adding)
+ {
+ i = (int)STRLEN(origval);
+ mch_memmove(newval + i + comma, newval,
+ STRLEN(newval) + 1);
+ mch_memmove(newval, origval, (size_t)i);
+ }
+ else
+ {
+ i = (int)STRLEN(newval);
+ mch_memmove(newval + i + comma, origval,
+ STRLEN(origval) + 1);
+ }
+ if (comma)
+ newval[i] = ',';
+ }
+
+ /* Remove newval[] from origval[]. (Note: "i" has
+ * been set above and is used here). */
+ if (removing)
+ {
+ STRCPY(newval, origval);
+ if (*s)
+ {
+ /* may need to remove a comma */
+ if (flags & P_COMMA)
+ {
+ if (s == origval)
+ {
+ /* include comma after string */
+ if (s[i] == ',')
+ ++i;
+ }
+ else
+ {
+ /* include comma before string */
+ --s;
+ ++i;
+ }
+ }
+ mch_memmove(newval + (s - origval), s + i,
+ STRLEN(s + i) + 1);
+ }
+ }
+
+ if (flags & P_FLAGLIST)
+ {
+ /* Remove flags that appear twice. */
+ for (s = newval; *s; ++s)
+ if ((!(flags & P_COMMA) || *s != ',')
+ && vim_strchr(s + 1, *s) != NULL)
+ {
+ STRCPY(s, s + 1);
+ --s;
+ }
+ }
+
+ if (save_arg != NULL) /* number for 'whichwrap' */
+ arg = save_arg;
+ new_value_alloced = TRUE;
+ }
+
+ /* Set the new value. */
+ *(char_u **)(varp) = newval;
+
+ /* Handle side effects, and set the global value for
+ * ":set" on local options. */
+ errmsg = did_set_string_option(opt_idx, (char_u **)varp,
+ new_value_alloced, oldval, errbuf, opt_flags);
+
+ /* If error detected, print the error message. */
+ if (errmsg != NULL)
+ goto skip;
+ }
+ else /* key code option */
+ {
+ char_u *p;
+
+ if (nextchar == '&')
+ {
+ if (add_termcap_entry(key_name, TRUE) == FAIL)
+ errmsg = (char_u *)N_("E522: Not found in termcap");
+ }
+ else
+ {
+ ++arg; /* jump to after the '=' or ':' */
+ for (p = arg; *p && !vim_iswhite(*p); ++p)
+ if (*p == '\\' && p[1] != NUL)
+ ++p;
+ nextchar = *p;
+ *p = NUL;
+ add_termcode(key_name, arg, FALSE);
+ *p = nextchar;
+ }
+ if (full_screen)
+ ttest(FALSE);
+ redraw_all_later(CLEAR);
+ }
+ }
+ if (opt_idx >= 0)
+ options[opt_idx].flags |= P_WAS_SET;
+ }
+
+skip:
+ /*
+ * Advance to next argument.
+ * - skip until a blank found, taking care of backslashes
+ * - skip blanks
+ * - skip one "=val" argument (for hidden options ":set gfn =xx")
+ */
+ for (i = 0; i < 2 ; ++i)
+ {
+ while (*arg != NUL && !vim_iswhite(*arg))
+ if (*arg++ == '\\' && *arg != NUL)
+ ++arg;
+ arg = skipwhite(arg);
+ if (*arg != '=')
+ break;
+ }
+ }
+
+ if (errmsg != NULL)
+ {
+ STRNCPY(IObuff, _(errmsg), IOSIZE - 1);
+ IObuff[IOSIZE - 1] = NUL;
+ i = STRLEN(IObuff) + 2;
+ if (i + (arg - startarg) < IOSIZE)
+ {
+ /* append the argument with the error */
+ STRCAT(IObuff, ": ");
+ mch_memmove(IObuff + i, startarg, (arg - startarg));
+ IObuff[i + (arg - startarg)] = NUL;
+ }
+ /* make sure all characters are printable */
+ trans_characters(IObuff, IOSIZE);
+
+ ++no_wait_return; /* wait_return done later */
+ emsg(IObuff); /* show error highlighted */
+ --no_wait_return;
+
+ return FAIL;
+ }
+
+ arg = skipwhite(arg);
+ }
+
+ return OK;
+}
+
+ static char_u *
+illegal_char(errbuf, c)
+ char_u *errbuf;
+ int c;
+{
+ if (errbuf == NULL)
+ return (char_u *)"";
+ sprintf((char *)errbuf, _("E539: Illegal character <%s>"),
+ (char *)transchar(c));
+ return errbuf;
+}
+
+/*
+ * Convert a key name or string into a key value.
+ * Used for 'wildchar' and 'cedit' options.
+ */
+ static int
+string_to_key(arg)
+ char_u *arg;
+{
+ if (*arg == '<')
+ return find_key_option(arg + 1);
+ if (*arg == '^')
+ return Ctrl_chr(arg[1]);
+ return *arg;
+}
+
+#ifdef FEAT_CMDWIN
+/*
+ * Check value of 'cedit' and set cedit_key.
+ * Returns NULL if value is OK, error message otherwise.
+ */
+ static char_u *
+check_cedit()
+{
+ int n;
+
+ if (*p_cedit == NUL)
+ cedit_key = -1;
+ else
+ {
+ n = string_to_key(p_cedit);
+ if (vim_isprintc(n))
+ return e_invarg;
+ cedit_key = n;
+ }
+ return NULL;
+}
+#endif
+
+#ifdef FEAT_TITLE
+/*
+ * When changing 'title', 'titlestring', 'icon' or 'iconstring', call
+ * maketitle() to create and display it.
+ * When switching the title or icon off, call mch_restore_title() to get
+ * the old value back.
+ */
+ static void
+did_set_title(icon)
+ int icon; /* Did set icon instead of title */
+{
+ if (starting != NO_SCREEN
+#ifdef FEAT_GUI
+ && !gui.starting
+#endif
+ )
+ {
+ maketitle();
+ if (icon)
+ {
+ if (!p_icon)
+ mch_restore_title(2);
+ }
+ else
+ {
+ if (!p_title)
+ mch_restore_title(1);
+ }
+ }
+}
+#endif
+
+/*
+ * set_options_bin - called when 'bin' changes value.
+ */
+ void
+set_options_bin(oldval, newval, opt_flags)
+ int oldval;
+ int newval;
+ int opt_flags; /* OPT_LOCAL and/or OPT_GLOBAL */
+{
+ /*
+ * The option values that are changed when 'bin' changes are
+ * copied when 'bin is set and restored when 'bin' is reset.
+ */
+ if (newval)
+ {
+ if (!oldval) /* switched on */
+ {
+ if (!(opt_flags & OPT_GLOBAL))
+ {
+ curbuf->b_p_tw_nobin = curbuf->b_p_tw;
+ curbuf->b_p_wm_nobin = curbuf->b_p_wm;
+ curbuf->b_p_ml_nobin = curbuf->b_p_ml;
+ curbuf->b_p_et_nobin = curbuf->b_p_et;
+ }
+ if (!(opt_flags & OPT_LOCAL))
+ {
+ p_tw_nobin = p_tw;
+ p_wm_nobin = p_wm;
+ p_ml_nobin = p_ml;
+ p_et_nobin = p_et;
+ }
+ }
+
+ if (!(opt_flags & OPT_GLOBAL))
+ {
+ curbuf->b_p_tw = 0; /* no automatic line wrap */
+ curbuf->b_p_wm = 0; /* no automatic line wrap */
+ curbuf->b_p_ml = 0; /* no modelines */
+ curbuf->b_p_et = 0; /* no expandtab */
+ }
+ if (!(opt_flags & OPT_LOCAL))
+ {
+ p_tw = 0;
+ p_wm = 0;
+ p_ml = FALSE;
+ p_et = FALSE;
+ p_bin = TRUE; /* needed when called for the "-b" argument */
+ }
+ }
+ else if (oldval) /* switched off */
+ {
+ if (!(opt_flags & OPT_GLOBAL))
+ {
+ curbuf->b_p_tw = curbuf->b_p_tw_nobin;
+ curbuf->b_p_wm = curbuf->b_p_wm_nobin;
+ curbuf->b_p_ml = curbuf->b_p_ml_nobin;
+ curbuf->b_p_et = curbuf->b_p_et_nobin;
+ }
+ if (!(opt_flags & OPT_LOCAL))
+ {
+ p_tw = p_tw_nobin;
+ p_wm = p_wm_nobin;
+ p_ml = p_ml_nobin;
+ p_et = p_et_nobin;
+ }
+ }
+}
+
+#ifdef FEAT_VIMINFO
+/*
+ * Find the parameter represented by the given character (eg ', :, ", or /),
+ * and return its associated value in the 'viminfo' string.
+ * Only works for number parameters, not for 'r' or 'n'.
+ * If the parameter is not specified in the string, return -1.
+ */
+ int
+get_viminfo_parameter(type)
+ int type;
+{
+ char_u *p;
+
+ p = find_viminfo_parameter(type);
+ if (p != NULL && VIM_ISDIGIT(*p))
+ return atoi((char *)p);
+ return -1;
+}
+
+/*
+ * Find the parameter represented by the given character (eg ''', ':', '"', or
+ * '/') in the 'viminfo' option and return a pointer to the string after it.
+ * Return NULL if the parameter is not specified in the string.
+ */
+ char_u *
+find_viminfo_parameter(type)
+ int type;
+{
+ char_u *p;
+
+ for (p = p_viminfo; *p; ++p)
+ {
+ if (*p == type)
+ return p + 1;
+ if (*p == 'n') /* 'n' is always the last one */
+ break;
+ p = vim_strchr(p, ','); /* skip until next ',' */
+ if (p == NULL) /* hit the end without finding parameter */
+ break;
+ }
+ return NULL;
+}
+#endif
+
+/*
+ * Expand environment variables for some string options.
+ * These string options cannot be indirect!
+ * If "val" is NULL expand the current value of the option.
+ * Return pointer to NameBuff, or NULL when not expanded.
+ */
+ static char_u *
+option_expand(opt_idx, val)
+ int opt_idx;
+ char_u *val;
+{
+ /* if option doesn't need expansion nothing to do */
+ if (!(options[opt_idx].flags & P_EXPAND) || options[opt_idx].var == NULL)
+ return NULL;
+
+ /* If val is longer than MAXPATHL no meaningful expansion can be done,
+ * expand_env() would truncate the string. */
+ if (val != NULL && STRLEN(val) > MAXPATHL)
+ return NULL;
+
+ if (val == NULL)
+ val = *(char_u **)options[opt_idx].var;
+
+ /*
+ * Expanding this with NameBuff, expand_env() must not be passed IObuff.
+ * Escape spaces when expanding 'tags', they are used to separate file
+ * names.
+ */
+ expand_env_esc(val, NameBuff, MAXPATHL,
+ (char_u **)options[opt_idx].var == &p_tags);
+ if (STRCMP(NameBuff, val) == 0) /* they are the same */
+ return NULL;
+
+ return NameBuff;
+}
+
+/*
+ * After setting various option values: recompute variables that depend on
+ * option values.
+ */
+ static void
+didset_options()
+{
+ /* initialize the table for 'iskeyword' et.al. */
+ (void)init_chartab();
+
+ (void)opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE);
+ (void)opt_strings_flags(p_bkc, p_bkc_values, &bkc_flags, TRUE);
+#ifdef FEAT_SESSION
+ (void)opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, TRUE);
+ (void)opt_strings_flags(p_vop, p_ssop_values, &vop_flags, TRUE);
+#endif
+#ifdef FEAT_FOLDING
+ (void)opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE);
+#endif
+ (void)opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE);
+#ifdef FEAT_VIRTUALEDIT
+ (void)opt_strings_flags(p_ve, p_ve_values, &ve_flags, TRUE);
+#endif
+#if defined(FEAT_MOUSE) && (defined(UNIX) || defined(VMS))
+ (void)opt_strings_flags(p_ttym, p_ttym_values, &ttym_flags, FALSE);
+#endif
+#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32)
+ (void)opt_strings_flags(p_toolbar, p_toolbar_values, &toolbar_flags, TRUE);
+#endif
+#if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK) && defined(HAVE_GTK2)
+ (void)opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE);
+#endif
+#ifdef FEAT_CMDWIN
+ /* set cedit_key */
+ (void)check_cedit();
+#endif
+}
+
+/*
+ * Check for string options that are NULL (normally only termcap options).
+ */
+ void
+check_options()
+{
+ int opt_idx;
+
+ for (opt_idx = 0; options[opt_idx].fullname != NULL; opt_idx++)
+ if ((options[opt_idx].flags & P_STRING) && options[opt_idx].var != NULL)
+ check_string_option((char_u **)get_varp(&(options[opt_idx])));
+}
+
+/*
+ * Check string options in a buffer for NULL value.
+ */
+ void
+check_buf_options(buf)
+ buf_T *buf;
+{
+#if defined(FEAT_QUICKFIX)
+ check_string_option(&buf->b_p_bh);
+ check_string_option(&buf->b_p_bt);
+#endif
+#ifdef FEAT_MBYTE
+ check_string_option(&buf->b_p_fenc);
+#endif
+ check_string_option(&buf->b_p_ff);
+#ifdef FEAT_FIND_ID
+ check_string_option(&buf->b_p_def);
+ check_string_option(&buf->b_p_inc);
+# ifdef FEAT_EVAL
+ check_string_option(&buf->b_p_inex);
+# endif
+#endif
+#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
+ check_string_option(&buf->b_p_inde);
+ check_string_option(&buf->b_p_indk);
+#endif
+#ifdef FEAT_CRYPT
+ check_string_option(&buf->b_p_key);
+#endif
+ check_string_option(&buf->b_p_kp);
+ check_string_option(&buf->b_p_mps);
+ check_string_option(&buf->b_p_fo);
+ check_string_option(&buf->b_p_isk);
+#ifdef FEAT_COMMENTS
+ check_string_option(&buf->b_p_com);
+#endif
+#ifdef FEAT_FOLDING
+ check_string_option(&buf->b_p_cms);
+#endif
+ check_string_option(&buf->b_p_nf);
+#ifdef FEAT_SYN_HL
+ check_string_option(&buf->b_p_syn);
+#endif
+#ifdef FEAT_SEARCHPATH
+ check_string_option(&buf->b_p_sua);
+#endif
+#ifdef FEAT_CINDENT
+ check_string_option(&buf->b_p_cink);
+ check_string_option(&buf->b_p_cino);
+#endif
+#ifdef FEAT_AUTOCMD
+ check_string_option(&buf->b_p_ft);
+#endif
+#ifdef FEAT_OSFILETYPE
+ check_string_option(&buf->b_p_oft);
+#endif
+#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
+ check_string_option(&buf->b_p_cinw);
+#endif
+#ifdef FEAT_INS_EXPAND
+ check_string_option(&buf->b_p_cpt);
+#endif
+#ifdef FEAT_KEYMAP
+ check_string_option(&buf->b_p_keymap);
+#endif
+#ifdef FEAT_QUICKFIX
+ check_string_option(&buf->b_p_gp);
+ check_string_option(&buf->b_p_mp);
+ check_string_option(&buf->b_p_efm);
+#endif
+ check_string_option(&buf->b_p_ep);
+ check_string_option(&buf->b_p_path);
+ check_string_option(&buf->b_p_tags);
+#ifdef FEAT_INS_EXPAND
+ check_string_option(&buf->b_p_dict);
+ check_string_option(&buf->b_p_tsr);
+#endif
+}
+
+/*
+ * Free the string allocated for an option.
+ * Checks for the string being empty_option. This may happen if we're out of
+ * memory, vim_strsave() returned NULL, which was replaced by empty_option by
+ * check_options().
+ * Does NOT check for P_ALLOCED flag!
+ */
+ void
+free_string_option(p)
+ char_u *p;
+{
+ if (p != empty_option)
+ vim_free(p);
+}
+
+ void
+clear_string_option(pp)
+ char_u **pp;
+{
+ if (*pp != empty_option)
+ vim_free(*pp);
+ *pp = empty_option;
+}
+
+ static void
+check_string_option(pp)
+ char_u **pp;
+{
+ if (*pp == NULL)
+ *pp = empty_option;
+}
+
+/*
+ * Mark a terminal option as allocated, found by a pointer into term_strings[].
+ */
+ void
+set_term_option_alloced(p)
+ char_u **p;
+{
+ int opt_idx;
+
+ for (opt_idx = 1; options[opt_idx].fullname != NULL; opt_idx++)
+ if (options[opt_idx].var == (char_u *)p)
+ {
+ options[opt_idx].flags |= P_ALLOCED;
+ return;
+ }
+ return; /* cannot happen: didn't find it! */
+}
+
+/*
+ * Set a string option to a new value (without checking the effect).
+ * The string is copied into allocated memory.
+ * if ("opt_idx" == -1) "name" is used, otherwise "opt_idx" is used.
+ */
+ void
+set_string_option_direct(name, opt_idx, val, opt_flags)
+ char_u *name;
+ int opt_idx;
+ char_u *val;
+ int opt_flags; /* OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL */
+{
+ char_u *s;
+ char_u **varp;
+ int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
+
+ if (opt_idx == -1) /* use name */
+ {
+ opt_idx = findoption(name);
+ if (opt_idx == -1) /* not found (should not happen) */
+ return;
+ }
+
+ if (options[opt_idx].var == NULL) /* can't set hidden option */
+ return;
+
+ s = vim_strsave(val);
+ if (s != NULL)
+ {
+ varp = (char_u **)get_varp_scope(&(options[opt_idx]),
+ both ? OPT_LOCAL : opt_flags);
+ if ((opt_flags & OPT_FREE) && (options[opt_idx].flags & P_ALLOCED))
+ free_string_option(*varp);
+ *varp = s;
+
+ /* For buffer/window local option may also set the global value. */
+ if (both)
+ set_string_option_global(opt_idx, varp);
+
+ options[opt_idx].flags |= P_ALLOCED;
+
+ /* When setting both values of a global option with a local value,
+ * make the local value empty, so that the global value is used. */
+ if ((int)options[opt_idx].indir >= PV_BOTH && both)
+ {
+ free_string_option(*varp);
+ *varp = empty_option;
+ }
+ }
+}
+
+/*
+ * Set global value for string option when it's a local option.
+ */
+ static void
+set_string_option_global(opt_idx, varp)
+ int opt_idx; /* option index */
+ char_u **varp; /* pointer to option variable */
+{
+ char_u **p, *s;
+
+ /* the global value is always allocated */
+ if (options[opt_idx].var == VAR_WIN)
+ p = (char_u **)GLOBAL_WO(varp);
+ else
+ p = (char_u **)options[opt_idx].var;
+ if (options[opt_idx].indir != PV_NONE
+ && p != varp
+ && (s = vim_strsave(*varp)) != NULL)
+ {
+ free_string_option(*p);
+ *p = s;
+ }
+}
+
+/*
+ * Set a string option to a new value, and handle the effects.
+ */
+ static void
+set_string_option(opt_idx, value, opt_flags)
+ int opt_idx;
+ char_u *value;
+ int opt_flags; /* OPT_LOCAL and/or OPT_GLOBAL */
+{
+ char_u *s;
+ char_u **varp;
+ char_u *oldval;
+
+ if (options[opt_idx].var == NULL) /* don't set hidden option */
+ return;
+
+ s = vim_strsave(value);
+ if (s != NULL)
+ {
+ varp = (char_u **)get_varp_scope(&(options[opt_idx]),
+ (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
+ ? ((int)options[opt_idx].indir >= PV_BOTH
+ ? OPT_GLOBAL : OPT_LOCAL)
+ : opt_flags);
+ oldval = *varp;
+ *varp = s;
+ options[opt_idx].flags |= P_WAS_SET;
+ (void)did_set_string_option(opt_idx, varp, TRUE, oldval, NULL,
+ opt_flags);
+ }
+}
+
+/*
+ * Handle string options that need some action to perform when changed.
+ * Returns NULL for success, or an error message for an error.
+ */
+ static char_u *
+did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf,
+ opt_flags)
+ int opt_idx; /* index in options[] table */
+ char_u **varp; /* pointer to the option variable */
+ int new_value_alloced; /* new value was allocated */
+ char_u *oldval; /* previous value of the option */
+ char_u *errbuf; /* buffer for errors, or NULL */
+ int opt_flags; /* OPT_LOCAL and/or OPT_GLOBAL */
+{
+ char_u *errmsg = NULL;
+ char_u *s, *p;
+ int did_chartab = FALSE;
+ char_u **gvarp;
+
+ /* Get the global option to compare with, otherwise we would have to check
+ * two values for all local options. */
+ gvarp = (char_u **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
+
+ /* Disallow changing some options from secure mode */
+ if ((secure
+#ifdef HAVE_SANDBOX
+ || sandbox != 0
+#endif
+ ) && (options[opt_idx].flags & P_SECURE))
+ {
+ errmsg = e_secure;
+ }
+
+ /* 'term' */
+ else if (varp == &T_NAME)
+ {
+ if (T_NAME[0] == NUL)
+ errmsg = (char_u *)N_("E529: Cannot set 'term' to empty string");
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ errmsg = (char_u *)N_("E530: Cannot change term in GUI");
+ else if (term_is_gui(T_NAME))
+ errmsg = (char_u *)N_("E531: Use \":gui\" to start the GUI");
+#endif
+ else if (set_termname(T_NAME) == FAIL)
+ errmsg = (char_u *)N_("E522: Not found in termcap");
+ else
+ /* Screen colors may have changed. */
+ redraw_later_clear();
+ }
+
+ /* 'backupcopy' */
+ else if (varp == &p_bkc)
+ {
+ if (opt_strings_flags(p_bkc, p_bkc_values, &bkc_flags, TRUE) != OK)
+ errmsg = e_invarg;
+ if (((bkc_flags & BKC_AUTO) != 0)
+ + ((bkc_flags & BKC_YES) != 0)
+ + ((bkc_flags & BKC_NO) != 0) != 1)
+ {
+ /* Must have exactly one of "auto", "yes" and "no". */
+ (void)opt_strings_flags(oldval, p_bkc_values, &bkc_flags, TRUE);
+ errmsg = e_invarg;
+ }
+ }
+
+ /* 'backupext' and 'patchmode' */
+ else if (varp == &p_bex || varp == &p_pm)
+ {
+ if (STRCMP(*p_bex == '.' ? p_bex + 1 : p_bex,
+ *p_pm == '.' ? p_pm + 1 : p_pm) == 0)
+ errmsg = (char_u *)N_("E589: 'backupext' and 'patchmode' are equal");
+ }
+
+ /*
+ * 'isident', 'iskeyword', 'isprint or 'isfname' option: refill chartab[]
+ * If the new option is invalid, use old value. 'lisp' option: refill
+ * chartab[] for '-' char
+ */
+ else if ( varp == &p_isi
+ || varp == &(curbuf->b_p_isk)
+ || varp == &p_isp
+ || varp == &p_isf)
+ {
+ if (init_chartab() == FAIL)
+ {
+ did_chartab = TRUE; /* need to restore it below */
+ errmsg = e_invarg; /* error in value */
+ }
+ }
+
+ /* 'helpfile' */
+ else if (varp == &p_hf)
+ {
+ /* May compute new values for $VIM and $VIMRUNTIME */
+ if (didset_vim)
+ {
+ vim_setenv((char_u *)"VIM", (char_u *)"");
+ didset_vim = FALSE;
+ }
+ if (didset_vimruntime)
+ {
+ vim_setenv((char_u *)"VIMRUNTIME", (char_u *)"");
+ didset_vimruntime = FALSE;
+ }
+ }
+
+#ifdef FEAT_MULTI_LANG
+ /* 'helplang' */
+ else if (varp == &p_hlg)
+ {
+ /* Check for "", "ab", "ab,cd", etc. */
+ for (s = p_hlg; *s != NUL; s += 3)
+ {
+ if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL))
+ {
+ errmsg = e_invarg;
+ break;
+ }
+ if (s[2] == NUL)
+ break;
+ }
+ }
+#endif
+
+ /* 'highlight' */
+ else if (varp == &p_hl)
+ {
+ if (highlight_changed() == FAIL)
+ errmsg = e_invarg; /* invalid flags */
+ }
+
+ /* 'nrformats' */
+ else if (gvarp == &p_nf)
+ {
+ if (check_opt_strings(*varp, p_nf_values, TRUE) != OK)
+ errmsg = e_invarg;
+ }
+
+#ifdef FEAT_SESSION
+ /* 'sessionoptions' */
+ else if (varp == &p_ssop)
+ {
+ if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, TRUE) != OK)
+ errmsg = e_invarg;
+ if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR))
+ {
+ /* Don't allow both "sesdir" and "curdir". */
+ (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, TRUE);
+ errmsg = e_invarg;
+ }
+ }
+ /* 'viewoptions' */
+ else if (varp == &p_vop)
+ {
+ if (opt_strings_flags(p_vop, p_ssop_values, &vop_flags, TRUE) != OK)
+ errmsg = e_invarg;
+ }
+#endif
+
+ /* 'scrollopt' */
+#ifdef FEAT_SCROLLBIND
+ else if (varp == &p_sbo)
+ {
+ if (check_opt_strings(p_sbo, p_scbopt_values, TRUE) != OK)
+ errmsg = e_invarg;
+ }
+#endif
+
+ /* 'ambiwidth' */
+#ifdef FEAT_MBYTE
+ else if (varp == &p_ambw)
+ {
+ if (check_opt_strings(p_ambw, p_ambw_values, FALSE) != OK)
+ errmsg = e_invarg;
+ }
+#endif
+
+ /* 'background' */
+ else if (varp == &p_bg)
+ {
+ if (check_opt_strings(p_bg, p_bg_values, FALSE) == OK)
+ {
+#ifdef FEAT_EVAL
+ int dark = (*p_bg == 'd');
+#endif
+
+ init_highlight(FALSE, FALSE);
+
+#ifdef FEAT_EVAL
+ if (dark != (*p_bg == 'd')
+ && get_var_value((char_u *)"g:colors_name") != NULL)
+ {
+ /* The color scheme must have set 'background' back to another
+ * value, that's not what we want here. Disable the color
+ * scheme and set the colors again. */
+ do_unlet((char_u *)"g:colors_name");
+ free_string_option(p_bg);
+ p_bg = vim_strsave((char_u *)(dark ? "dark" : "light"));
+ check_string_option(&p_bg);
+ init_highlight(FALSE, FALSE);
+ }
+#endif
+ }
+ else
+ errmsg = e_invarg;
+ }
+
+ /* 'wildmode' */
+ else if (varp == &p_wim)
+ {
+ if (check_opt_wim() == FAIL)
+ errmsg = e_invarg;
+ }
+
+#ifdef FEAT_WAK
+ /* 'winaltkeys' */
+ else if (varp == &p_wak)
+ {
+ if (*p_wak == NUL
+ || check_opt_strings(p_wak, p_wak_values, FALSE) != OK)
+ errmsg = e_invarg;
+# ifdef FEAT_MENU
+# ifdef FEAT_GUI_MOTIF
+ else if (gui.in_use)
+ gui_motif_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm');
+# else
+# ifdef FEAT_GUI_GTK
+ else if (gui.in_use)
+ gui_gtk_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm');
+# endif
+# endif
+# endif
+ }
+#endif
+
+#ifdef FEAT_AUTOCMD
+ /* 'eventignore' */
+ else if (varp == &p_ei)
+ {
+ if (check_ei() == FAIL)
+ errmsg = e_invarg;
+ }
+#endif
+
+#ifdef FEAT_MBYTE
+ /* 'encoding' and 'fileencoding' */
+ else if (varp == &p_enc || gvarp == &p_fenc || varp == &p_tenc)
+ {
+ if (gvarp == &p_fenc)
+ {
+ if (!curbuf->b_p_ma)
+ errmsg = e_modifiable;
+ else if (vim_strchr(*varp, ',') != NULL)
+ /* No comma allowed in 'fileencoding'; catches confusing it
+ * with 'fileencodings'. */
+ errmsg = e_invarg;
+# ifdef FEAT_TITLE
+ else
+ /* May show a "+" in the title now. */
+ need_maketitle = TRUE;
+# endif
+ }
+ if (errmsg == NULL)
+ {
+ /* canonize the value, so that STRCMP() can be used on it */
+ p = enc_canonize(*varp);
+ if (p != NULL)
+ {
+ vim_free(*varp);
+ *varp = p;
+ }
+ if (varp == &p_enc)
+ {
+ errmsg = mb_init();
+# ifdef FEAT_TITLE
+ need_maketitle = TRUE;
+# endif
+ }
+ }
+
+# if defined(FEAT_GUI_GTK) && defined(HAVE_GTK2)
+ if (errmsg == NULL && varp == &p_tenc && gui.in_use)
+ {
+ /* GTK+ 2 uses only a single encoding, and that is UTF-8. */
+ if (STRCMP(p_tenc, "utf-8") != 0)
+ errmsg = (char_u *)N_("E617: Cannot be changed in the GTK+ 2 GUI");
+ }
+# endif
+
+ if (errmsg == NULL)
+ {
+# ifdef FEAT_KEYMAP
+ /* When 'keymap' is used and 'encoding' changes, reload the keymap
+ * (with another encoding). */
+ if (varp == &p_enc && *curbuf->b_p_keymap != NUL)
+ (void)keymap_init();
+# endif
+
+ /* When 'termencoding' is not empty and 'encoding' changes or when
+ * 'termencoding' changes, need to setup for keyboard input and
+ * display output conversion. */
+ if (((varp == &p_enc && *p_tenc != NUL) || varp == &p_tenc))
+ {
+ convert_setup(&input_conv, p_tenc, p_enc);
+ convert_setup(&output_conv, p_enc, p_tenc);
+ }
+ }
+ }
+#endif
+
+#if defined(FEAT_POSTSCRIPT)
+ else if (varp == &p_penc)
+ {
+ /* Canonize printencoding if VIM standard one */
+ p = enc_canonize(p_penc);
+ if (p != NULL)
+ {
+ vim_free(p_penc);
+ p_penc = p;
+ }
+ else
+ {
+ /* Ensure lower case and '-' for '_' */
+ for (s = p_penc; *s != NUL; s++)
+ {
+ if (*s == '_')
+ *s = '-';
+ else
+ *s = TOLOWER_ASC(*s);
+ }
+ }
+ }
+#endif
+
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+ else if (varp == &p_imak)
+ {
+ if (gui.in_use && !im_xim_isvalid_imactivate())
+ errmsg = e_invarg;
+ }
+#endif
+
+#ifdef FEAT_KEYMAP
+ else if (varp == &curbuf->b_p_keymap)
+ {
+ /* load or unload key mapping tables */
+ errmsg = keymap_init();
+
+ /* When successfully installed a new keymap switch on using it. */
+ if (*curbuf->b_p_keymap != NUL && errmsg == NULL)
+ {
+ curbuf->b_p_iminsert = B_IMODE_LMAP;
+ if (curbuf->b_p_imsearch != B_IMODE_USE_INSERT)
+ curbuf->b_p_imsearch = B_IMODE_LMAP;
+ set_iminsert_global();
+ set_imsearch_global();
+# ifdef FEAT_WINDOWS
+ status_redraw_curbuf();
+# endif
+ }
+ }
+#endif
+
+ /* 'fileformat' */
+ else if (gvarp == &p_ff)
+ {
+ if (!curbuf->b_p_ma && !(opt_flags & OPT_GLOBAL))
+ errmsg = e_modifiable;
+ else if (check_opt_strings(*varp, p_ff_values, FALSE) != OK)
+ errmsg = e_invarg;
+ else
+ {
+ /* may also change 'textmode' */
+ if (get_fileformat(curbuf) == EOL_DOS)
+ curbuf->b_p_tx = TRUE;
+ else
+ curbuf->b_p_tx = FALSE;
+#ifdef FEAT_TITLE
+ need_maketitle = TRUE;
+#endif
+ }
+ }
+
+ /* 'fileformats' */
+ else if (varp == &p_ffs)
+ {
+ if (check_opt_strings(p_ffs, p_ff_values, TRUE) != OK)
+ errmsg = e_invarg;
+ else
+ {
+ /* also change 'textauto' */
+ if (*p_ffs == NUL)
+ p_ta = FALSE;
+ else
+ p_ta = TRUE;
+ }
+ }
+
+#if defined(FEAT_CRYPT) && defined(FEAT_CMDHIST)
+ /* 'cryptkey' */
+ else if (gvarp == &p_key)
+ {
+ /* Make sure the ":set" command doesn't show the new value in the
+ * history. */
+ remove_key_from_history();
+ }
+#endif
+
+ /* 'matchpairs' */
+ else if (gvarp == &p_mps)
+ {
+ /* Check for "x:y,x:y" */
+ for (p = *varp; *p != NUL; p += 4)
+ {
+ if (p[1] != ':' || p[2] == NUL || (p[3] != NUL && p[3] != ','))
+ {
+ errmsg = e_invarg;
+ break;
+ }
+ if (p[3] == NUL)
+ break;
+ }
+ }
+
+#ifdef FEAT_COMMENTS
+ /* 'comments' */
+ else if (gvarp == &p_com)
+ {
+ for (s = *varp; *s; )
+ {
+ while (*s && *s != ':')
+ {
+ if (vim_strchr((char_u *)COM_ALL, *s) == NULL
+ && !VIM_ISDIGIT(*s) && *s != '-')
+ {
+ errmsg = illegal_char(errbuf, *s);
+ break;
+ }
+ ++s;
+ }
+ if (*s++ == NUL)
+ errmsg = (char_u *)N_("E524: Missing colon");
+ else if (*s == ',' || *s == NUL)
+ errmsg = (char_u *)N_("E525: Zero length string");
+ if (errmsg != NULL)
+ break;
+ while (*s && *s != ',')
+ {
+ if (*s == '\\' && s[1] != NUL)
+ ++s;
+ ++s;
+ }
+ s = skip_to_option_part(s);
+ }
+ }
+#endif
+
+ /* 'listchars' */
+ else if (varp == &p_lcs)
+ {
+ errmsg = set_chars_option(varp);
+ }
+
+#if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING)
+ /* 'fillchars' */
+ else if (varp == &p_fcs)
+ {
+ errmsg = set_chars_option(varp);
+ }
+#endif
+
+#ifdef FEAT_CMDWIN
+ /* 'cedit' */
+ else if (varp == &p_cedit)
+ {
+ errmsg = check_cedit();
+ }
+#endif
+
+#ifdef FEAT_VIMINFO
+ /* 'viminfo' */
+ else if (varp == &p_viminfo)
+ {
+ for (s = p_viminfo; *s;)
+ {
+ /* Check it's a valid character */
+ if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL)
+ {
+ errmsg = illegal_char(errbuf, *s);
+ break;
+ }
+ if (*s == 'n') /* name is always last one */
+ {
+ break;
+ }
+ else if (*s == 'r') /* skip until next ',' */
+ {
+ while (*++s && *s != ',')
+ ;
+ }
+ else if (*s == '%' || *s == '!' || *s == 'h' || *s == 'c')
+ ++s; /* no extra chars */
+ else /* must have a number */
+ {
+ while (vim_isdigit(*++s))
+ ;
+
+ if (!VIM_ISDIGIT(*(s - 1)))
+ {
+ if (errbuf != NULL)
+ {
+ sprintf((char *)errbuf, _("E526: Missing number after <%s>"),
+ transchar_byte(*(s - 1)));
+ errmsg = errbuf;
+ }
+ else
+ errmsg = (char_u *)"";
+ break;
+ }
+ }
+ if (*s == ',')
+ ++s;
+ else if (*s)
+ {
+ if (errbuf != NULL)
+ errmsg = (char_u *)N_("E527: Missing comma");
+ else
+ errmsg = (char_u *)"";
+ break;
+ }
+ }
+ if (*p_viminfo && errmsg == NULL && get_viminfo_parameter('\'') < 0)
+ errmsg = (char_u *)N_("E528: Must specify a ' value");
+ }
+#endif /* FEAT_VIMINFO */
+
+ /* terminal options */
+ else if (istermoption(&options[opt_idx]) && full_screen)
+ {
+ /* ":set t_Co=0" and ":set t_Co=1" do ":set t_Co=" */
+ if (varp == &T_CCO)
+ {
+ t_colors = atoi((char *)T_CCO);
+ if (t_colors <= 1)
+ {
+ if (new_value_alloced)
+ vim_free(T_CCO);
+ T_CCO = empty_option;
+ }
+ /* We now have a different color setup, initialize it again. */
+ init_highlight(TRUE, FALSE);
+ }
+ ttest(FALSE);
+ if (varp == &T_ME)
+ {
+ out_str(T_ME);
+ redraw_later(CLEAR);
+#if defined(MSDOS) || (defined(WIN3264) && !defined(FEAT_GUI_W32))
+ /* Since t_me has been set, this probably means that the user
+ * wants to use this as default colors. Need to reset default
+ * background/foreground colors. */
+ mch_set_normal_colors();
+#endif
+ }
+ }
+
+#ifdef FEAT_LINEBREAK
+ /* 'showbreak' */
+ else if (varp == &p_sbr)
+ {
+ for (s = p_sbr; *s; )
+ {
+ if (ptr2cells(s) != 1)
+ errmsg = (char_u *)N_("E595: contains unprintable or wide character");
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ s += (*mb_ptr2len_check)(s);
+ else
+# endif
+ ++s;
+ }
+ }
+#endif
+
+#ifdef FEAT_GUI
+ /* 'guifont' */
+ else if (varp == &p_guifont)
+ {
+ if (gui.in_use)
+ {
+ p = p_guifont;
+# ifdef FEAT_GUI_GTK
+ /*
+ * Put up a font dialog and let the user select a new value.
+ * If this is cancelled go back to the old value but don't
+ * give an error message.
+ */
+ if (STRCMP(p, "*") == 0)
+ {
+ p = gui_mch_font_dialog(oldval);
+
+ if (new_value_alloced)
+ free_string_option(p_guifont);
+
+ p_guifont = (p != NULL) ? p : vim_strsave(oldval);
+ new_value_alloced = TRUE;
+ }
+# endif
+ if (p != NULL && gui_init_font(p_guifont, FALSE) != OK)
+ {
+# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON)
+ if (STRCMP(p_guifont, "*") == 0)
+ {
+ /* Dialog was cancelled: Keep the old value without giving
+ * an error message. */
+ if (new_value_alloced)
+ free_string_option(p_guifont);
+ p_guifont = vim_strsave(oldval);
+ new_value_alloced = TRUE;
+ }
+ else
+# endif
+ errmsg = (char_u *)N_("E596: Invalid font(s)");
+ }
+ }
+ }
+# ifdef FEAT_XFONTSET
+ else if (varp == &p_guifontset)
+ {
+ if (STRCMP(p_guifontset, "*") == 0)
+ errmsg = (char_u *)N_("E597: can't select fontset");
+ else if (gui.in_use && gui_init_font(p_guifontset, TRUE) != OK)
+ errmsg = (char_u *)N_("E598: Invalid fontset");
+ }
+# endif
+# ifdef FEAT_MBYTE
+ else if (varp == &p_guifontwide)
+ {
+ if (STRCMP(p_guifontwide, "*") == 0)
+ errmsg = (char_u *)N_("E533: can't select wide font");
+ else if (gui_get_wide_font() == FAIL)
+ errmsg = (char_u *)N_("E534: Invalid wide font");
+ }
+# endif
+#endif
+
+#ifdef CURSOR_SHAPE
+ /* 'guicursor' */
+ else if (varp == &p_guicursor)
+ errmsg = parse_shape_opt(SHAPE_CURSOR);
+#endif
+
+#ifdef FEAT_MOUSESHAPE
+ /* 'mouseshape' */
+ else if (varp == &p_mouseshape)
+ {
+ errmsg = parse_shape_opt(SHAPE_MOUSE);
+ update_mouseshape(-1);
+ }
+#endif
+
+#ifdef FEAT_PRINTER
+ else if (varp == &p_popt)
+ errmsg = parse_list_options(p_popt, printer_opts, OPT_PRINT_NUM_OPTIONS);
+#endif
+
+#ifdef FEAT_LANGMAP
+ /* 'langmap' */
+ else if (varp == &p_langmap)
+ langmap_set();
+#endif
+
+#ifdef FEAT_LINEBREAK
+ /* 'breakat' */
+ else if (varp == &p_breakat)
+ fill_breakat_flags();
+#endif
+
+#ifdef FEAT_TITLE
+ /* 'titlestring' and 'iconstring' */
+ else if (varp == &p_titlestring || varp == &p_iconstring)
+ {
+# ifdef FEAT_STL_OPT
+ int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON;
+
+ /* NULL => statusline syntax */
+ if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL)
+ stl_syntax |= flagval;
+ else
+ stl_syntax &= ~flagval;
+# endif
+ did_set_title(varp == &p_iconstring);
+
+ }
+#endif
+
+#ifdef FEAT_GUI
+ /* 'guioptions' */
+ else if (varp == &p_go)
+ gui_init_which_components(oldval);
+#endif
+
+#if defined(FEAT_MOUSE_TTY) && (defined(UNIX) || defined(VMS))
+ /* 'ttymouse' */
+ else if (varp == &p_ttym)
+ {
+ if (opt_strings_flags(p_ttym, p_ttym_values, &ttym_flags, FALSE) != OK)
+ errmsg = e_invarg;
+ else
+ check_mouse_termcode();
+ }
+#endif
+
+#ifdef FEAT_VISUAL
+ /* 'selection' */
+ else if (varp == &p_sel)
+ {
+ if (*p_sel == NUL
+ || check_opt_strings(p_sel, p_sel_values, FALSE) != OK)
+ errmsg = e_invarg;
+ }
+
+ /* 'selectmode' */
+ else if (varp == &p_slm)
+ {
+ if (check_opt_strings(p_slm, p_slm_values, TRUE) != OK)
+ errmsg = e_invarg;
+ }
+#endif
+
+#ifdef FEAT_BROWSE
+ /* 'browsedir' */
+ else if (varp == &p_bsdir)
+ {
+ if (check_opt_strings(p_bsdir, p_bsdir_values, FALSE) != OK
+ && !mch_isdir(p_bsdir))
+ errmsg = e_invarg;
+ }
+#endif
+
+#ifdef FEAT_VISUAL
+ /* 'keymodel' */
+ else if (varp == &p_km)
+ {
+ if (check_opt_strings(p_km, p_km_values, TRUE) != OK)
+ errmsg = e_invarg;
+ else
+ {
+ km_stopsel = (vim_strchr(p_km, 'o') != NULL);
+ km_startsel = (vim_strchr(p_km, 'a') != NULL);
+ }
+ }
+#endif
+
+ /* 'mousemodel' */
+ else if (varp == &p_mousem)
+ {
+ if (check_opt_strings(p_mousem, p_mousem_values, FALSE) != OK)
+ errmsg = e_invarg;
+#if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU) && (XmVersion <= 1002)
+ else if (*p_mousem != *oldval)
+ /* Changed from "extend" to "popup" or "popup_setpos" or vv: need
+ * to create or delete the popup menus. */
+ gui_motif_update_mousemodel(root_menu);
+#endif
+ }
+
+ /* 'switchbuf' */
+ else if (varp == &p_swb)
+ {
+ if (check_opt_strings(p_swb, p_swb_values, TRUE) != OK)
+ errmsg = e_invarg;
+ }
+
+ /* 'debug' */
+ else if (varp == &p_debug)
+ {
+ if (check_opt_strings(p_debug, p_debug_values, FALSE) != OK)
+ errmsg = e_invarg;
+ }
+
+ /* 'display' */
+ else if (varp == &p_dy)
+ {
+ if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE) != OK)
+ errmsg = e_invarg;
+ else
+ (void)init_chartab();
+
+ }
+
+#ifdef FEAT_VERTSPLIT
+ /* 'eadirection' */
+ else if (varp == &p_ead)
+ {
+ if (check_opt_strings(p_ead, p_ead_values, FALSE) != OK)
+ errmsg = e_invarg;
+ }
+#endif
+
+#ifdef FEAT_CLIPBOARD
+ /* 'clipboard' */
+ else if (varp == &p_cb)
+ errmsg = check_clipboard_option();
+#endif
+
+#ifdef FEAT_AUTOCMD
+# ifdef FEAT_SYN_HL
+ /* When 'syntax' is set, load the syntax of that name */
+ else if (varp == &(curbuf->b_p_syn))
+ {
+ apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
+ curbuf->b_fname, TRUE, curbuf);
+ }
+# endif
+
+ /* When 'filetype' is set, trigger the FileType autocommands of that name */
+ else if (varp == &(curbuf->b_p_ft))
+ {
+ did_filetype = TRUE;
+ apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft,
+ curbuf->b_fname, TRUE, curbuf);
+ }
+#endif
+
+#ifdef FEAT_QUICKFIX
+ /* When 'bufhidden' is set, check for valid value. */
+ else if (gvarp == &p_bh)
+ {
+ if (check_opt_strings(curbuf->b_p_bh, p_bufhidden_values, FALSE) != OK)
+ errmsg = e_invarg;
+ }
+
+ /* When 'buftype' is set, check for valid value. */
+ else if (gvarp == &p_bt)
+ {
+ if (check_opt_strings(curbuf->b_p_bt, p_buftype_values, FALSE) != OK)
+ errmsg = e_invarg;
+ else
+ {
+# ifdef FEAT_WINDOWS
+ if (curwin->w_status_height)
+ {
+ curwin->w_redr_status = TRUE;
+ redraw_later(VALID);
+ }
+# endif
+ curbuf->b_help = (curbuf->b_p_bt[0] == 'h');
+ }
+ }
+#endif
+
+#ifdef FEAT_STL_OPT
+ /* 'statusline' or 'rulerformat' */
+ else if (varp == &p_stl || varp == &p_ruf)
+ {
+ int wid;
+
+ if (varp == &p_ruf) /* reset ru_wid first */
+ ru_wid = 0;
+ s = *varp;
+ if (varp == &p_ruf && *s == '%')
+ {
+ /* set ru_wid if 'ruf' starts with "%99(" */
+ if (*++s == '-') /* ignore a '-' */
+ s++;
+ wid = getdigits(&s);
+ if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL)
+ ru_wid = wid;
+ else
+ errmsg = check_stl_option(p_ruf);
+ }
+ else
+ errmsg = check_stl_option(s);
+ if (varp == &(p_ruf) && errmsg == NULL)
+ comp_col();
+ }
+#endif
+
+#ifdef FEAT_INS_EXPAND
+ /* check if it is a valid value for 'complete' -- Acevedo */
+ else if (gvarp == &p_cpt)
+ {
+ for (s = *varp; *s;)
+ {
+ while(*s == ',' || *s == ' ')
+ s++;
+ if (!*s)
+ break;
+ if (vim_strchr((char_u *)".wbuksid]tU", *s) == NULL)
+ {
+ errmsg = illegal_char(errbuf, *s);
+ break;
+ }
+ if (*++s != NUL && *s != ',' && *s != ' ')
+ {
+ if (s[-1] == 'k' || s[-1] == 's')
+ {
+ /* skip optional filename after 'k' and 's' */
+ while (*s && *s != ',' && *s != ' ')
+ {
+ if (*s == '\\')
+ ++s;
+ ++s;
+ }
+ }
+ else
+ {
+ if (errbuf != NULL)
+ {
+ sprintf((char *)errbuf,
+ _("E535: Illegal character after <%c>"),
+ *--s);
+ errmsg = errbuf;
+ }
+ else
+ errmsg = (char_u *)"";
+ break;
+ }
+ }
+ }
+ }
+#endif /* FEAT_INS_EXPAND */
+
+
+#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32)
+ else if (varp == &p_toolbar)
+ {
+ if (opt_strings_flags(p_toolbar, p_toolbar_values,
+ &toolbar_flags, TRUE) != OK)
+ errmsg = e_invarg;
+ else
+ {
+ out_flush();
+ gui_mch_show_toolbar((toolbar_flags &
+ (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0);
+ }
+ }
+#endif
+
+#if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK) && defined(HAVE_GTK2)
+ /* 'toolbariconsize': GTK+ 2 only */
+ else if (varp == &p_tbis)
+ {
+ if (opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE) != OK)
+ errmsg = e_invarg;
+ else
+ {
+ out_flush();
+ gui_mch_show_toolbar((toolbar_flags &
+ (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0);
+ }
+ }
+#endif
+
+ /* 'pastetoggle': translate key codes like in a mapping */
+ else if (varp == &p_pt)
+ {
+ if (*p_pt)
+ {
+ (void)replace_termcodes(p_pt, &p, TRUE, TRUE);
+ if (p != NULL)
+ {
+ if (new_value_alloced)
+ free_string_option(p_pt);
+ p_pt = p;
+ new_value_alloced = TRUE;
+ }
+ }
+ }
+
+ /* 'backspace' */
+ else if (varp == &p_bs)
+ {
+ if (VIM_ISDIGIT(*p_bs))
+ {
+ if (*p_bs >'2' || p_bs[1] != NUL)
+ errmsg = e_invarg;
+ }
+ else if (check_opt_strings(p_bs, p_bs_values, TRUE) != OK)
+ errmsg = e_invarg;
+ }
+
+ /* 'casemap' */
+ else if (varp == &p_cmp)
+ {
+ if (opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE) != OK)
+ errmsg = e_invarg;
+ }
+
+#ifdef FEAT_DIFF
+ /* 'diffopt' */
+ else if (varp == &p_dip)
+ {
+ if (diffopt_changed() == FAIL)
+ errmsg = e_invarg;
+ }
+#endif
+
+#ifdef FEAT_FOLDING
+ /* 'foldmethod' */
+ else if (gvarp == &curwin->w_allbuf_opt.wo_fdm)
+ {
+ if (check_opt_strings(*varp, p_fdm_values, FALSE) != OK
+ || *curwin->w_p_fdm == NUL)
+ errmsg = e_invarg;
+ else
+ foldUpdateAll(curwin);
+ }
+# ifdef FEAT_EVAL
+ /* 'foldexpr' */
+ else if (varp == &curwin->w_p_fde)
+ {
+ if (foldmethodIsExpr(curwin))
+ foldUpdateAll(curwin);
+ }
+# endif
+ /* 'foldmarker' */
+ else if (gvarp == &curwin->w_allbuf_opt.wo_fmr)
+ {
+ p = vim_strchr(*varp, ',');
+ if (p == NULL)
+ errmsg = (char_u *)N_("E536: comma required");
+ else if (p == *varp || p[1] == NUL)
+ errmsg = e_invarg;
+ else if (foldmethodIsMarker(curwin))
+ foldUpdateAll(curwin);
+ }
+ /* 'commentstring' */
+ else if (gvarp == &p_cms)
+ {
+ if (**varp != NUL && strstr((char *)*varp, "%s") == NULL)
+ errmsg = (char_u *)N_("E537: 'commentstring' must be empty or contain %s");
+ }
+ /* 'foldopen' */
+ else if (varp == &p_fdo)
+ {
+ if (opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE) != OK)
+ errmsg = e_invarg;
+ }
+ /* 'foldclose' */
+ else if (varp == &p_fcl)
+ {
+ if (check_opt_strings(p_fcl, p_fcl_values, TRUE) != OK)
+ errmsg = e_invarg;
+ }
+#endif
+
+#ifdef FEAT_VIRTUALEDIT
+ /* 'virtualedit' */
+ else if (varp == &p_ve)
+ {
+ if (opt_strings_flags(p_ve, p_ve_values, &ve_flags, TRUE) != OK)
+ errmsg = e_invarg;
+ else if (STRCMP(p_ve, oldval) != 0)
+ {
+ /* Recompute cursor position in case the new 've' setting
+ * changes something. */
+ validate_virtcol();
+ coladvance(curwin->w_virtcol);
+ }
+ }
+#endif
+
+#if defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)
+ else if (varp == &p_csqf)
+ {
+ if (p_csqf != NULL)
+ {
+ p = p_csqf;
+ while (*p != NUL)
+ {
+ if (vim_strchr((char_u *)CSQF_CMDS, *p) == NULL
+ || p[1] == NUL
+ || vim_strchr((char_u *)CSQF_FLAGS, p[1]) == NULL
+ || (p[2] != NUL && p[2] != ','))
+ {
+ errmsg = e_invarg;
+ break;
+ }
+ else if (p[2] == NUL)
+ break;
+ else
+ p += 3;
+ }
+ }
+ }
+#endif
+
+ /* Options that are a list of flags. */
+ else
+ {
+ p = NULL;
+ if (varp == &p_ww)
+ p = (char_u *)WW_ALL;
+ if (varp == &p_shm)
+ p = (char_u *)SHM_ALL;
+ else if (varp == &(p_cpo))
+ p = (char_u *)CPO_ALL;
+ else if (varp == &(curbuf->b_p_fo))
+ p = (char_u *)FO_ALL;
+ else if (varp == &p_mouse)
+ {
+#ifdef FEAT_MOUSE
+ p = (char_u *)MOUSE_ALL;
+#else
+ if (*p_mouse != NUL)
+ errmsg = (char_u *)N_("E538: No mouse support");
+#endif
+ }
+#if defined(FEAT_GUI)
+ else if (varp == &p_go)
+ p = (char_u *)GO_ALL;
+#endif
+ if (p != NULL)
+ {
+ for (s = *varp; *s; ++s)
+ if (vim_strchr(p, *s) == NULL)
+ {
+ errmsg = illegal_char(errbuf, *s);
+ break;
+ }
+ }
+ }
+
+ /*
+ * If error detected, restore the previous value.
+ */
+ if (errmsg != NULL)
+ {
+ if (new_value_alloced)
+ free_string_option(*varp);
+ *varp = oldval;
+ /*
+ * When resetting some values, need to act on it.
+ */
+ if (did_chartab)
+ (void)init_chartab();
+ if (varp == &p_hl)
+ (void)highlight_changed();
+ }
+ else
+ {
+#ifdef FEAT_EVAL
+ /* Remember where the option was set. */
+ options[opt_idx].scriptID = current_SID;
+#endif
+ /*
+ * Free string options that are in allocated memory.
+ */
+ if (options[opt_idx].flags & P_ALLOCED)
+ free_string_option(oldval);
+ if (new_value_alloced)
+ options[opt_idx].flags |= P_ALLOCED;
+ else
+ options[opt_idx].flags &= ~P_ALLOCED;
+
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
+ && (int)options[opt_idx].indir >= PV_BOTH)
+ {
+ /* global option with local value set to use global value; free
+ * the local value and make it empty */
+ p = get_varp_scope(&(options[opt_idx]), OPT_LOCAL);
+ free_string_option(*(char_u **)p);
+ *(char_u **)p = empty_option;
+ }
+
+ /* May set global value for local option. */
+ else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL)
+ set_string_option_global(opt_idx, varp);
+ }
+
+#ifdef FEAT_MOUSE
+ if (varp == &p_mouse)
+ {
+# ifdef FEAT_MOUSE_TTY
+ if (*p_mouse == NUL)
+ mch_setmouse(FALSE); /* switch mouse off */
+ else
+# endif
+ setmouse(); /* in case 'mouse' changed */
+ }
+#endif
+
+ if (curwin->w_curswant != MAXCOL)
+ curwin->w_set_curswant = TRUE; /* in case 'showbreak' changed */
+ check_redraw(options[opt_idx].flags);
+
+ return errmsg;
+}
+
+/*
+ * Handle setting 'listchars' or 'fillchars'.
+ * Returns error message, NULL if it's OK.
+ */
+ static char_u *
+set_chars_option(varp)
+ char_u **varp;
+{
+ int round, i, len, entries;
+ char_u *p, *s;
+ int c1, c2 = 0;
+ struct charstab
+ {
+ int *cp;
+ char *name;
+ };
+#if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING)
+ static struct charstab filltab[] =
+ {
+ {&fill_stl, "stl"},
+ {&fill_stlnc, "stlnc"},
+ {&fill_vert, "vert"},
+ {&fill_fold, "fold"},
+ {&fill_diff, "diff"},
+ };
+#endif
+ static struct charstab lcstab[] =
+ {
+ {&lcs_eol, "eol"},
+ {&lcs_ext, "extends"},
+ {&lcs_prec, "precedes"},
+ {&lcs_tab2, "tab"},
+ {&lcs_trail, "trail"},
+ };
+ struct charstab *tab;
+
+#if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING)
+ if (varp == &p_lcs)
+#endif
+ {
+ tab = lcstab;
+ entries = sizeof(lcstab) / sizeof(struct charstab);
+ }
+#if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING)
+ else
+ {
+ tab = filltab;
+ entries = sizeof(filltab) / sizeof(struct charstab);
+ }
+#endif
+
+ /* first round: check for valid value, second round: assign values */
+ for (round = 0; round <= 1; ++round)
+ {
+ if (round)
+ {
+ /* After checking that the value is valid: set defaults: space for
+ * 'fillchars', NUL for 'listchars' */
+ for (i = 0; i < entries; ++i)
+ *(tab[i].cp) = (varp == &p_lcs ? NUL : ' ');
+ if (varp == &p_lcs)
+ lcs_tab1 = NUL;
+#if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING)
+ else
+ fill_diff = '-';
+#endif
+ }
+ p = *varp;
+ while (*p)
+ {
+ for (i = 0; i < entries; ++i)
+ {
+ len = (int)STRLEN(tab[i].name);
+ if (STRNCMP(p, tab[i].name, len) == 0
+ && p[len] == ':'
+ && p[len + 1] != NUL)
+ {
+ s = p + len + 1;
+#ifdef FEAT_MBYTE
+ c1 = mb_ptr2char_adv(&s);
+#else
+ c1 = *s++;
+#endif
+ if (tab[i].cp == &lcs_tab2)
+ {
+ if (*s == NUL)
+ continue;
+#ifdef FEAT_MBYTE
+ c2 = mb_ptr2char_adv(&s);
+#else
+ c2 = *s++;
+#endif
+ }
+ if (*s == ',' || *s == NUL)
+ {
+ if (round)
+ {
+ if (tab[i].cp == &lcs_tab2)
+ {
+ lcs_tab1 = c1;
+ lcs_tab2 = c2;
+ }
+ else
+ *(tab[i].cp) = c1;
+
+ }
+ p = s;
+ break;
+ }
+ }
+ }
+
+ if (i == entries)
+ return e_invarg;
+ if (*p == ',')
+ ++p;
+ }
+ }
+
+ return NULL; /* no error */
+}
+
+#ifdef FEAT_STL_OPT
+/*
+ * Check validity of options with the 'statusline' format.
+ * Return error message or NULL.
+ */
+ char_u *
+check_stl_option(s)
+ char_u *s;
+{
+ int itemcnt = 0;
+ int groupdepth = 0;
+ static char_u errbuf[80];
+
+ while (*s && itemcnt < STL_MAX_ITEM)
+ {
+ /* Check for valid keys after % sequences */
+ while (*s && *s != '%')
+ s++;
+ if (!*s)
+ break;
+ s++;
+ if (*s != '%' && *s != ')')
+ ++itemcnt;
+ if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_MIDDLEMARK)
+ {
+ s++;
+ continue;
+ }
+ if (*s == ')')
+ {
+ s++;
+ if (--groupdepth < 0)
+ break;
+ continue;
+ }
+ if (*s == '-')
+ s++;
+ while (VIM_ISDIGIT(*s))
+ s++;
+ if (*s == STL_HIGHLIGHT)
+ continue;
+ if (*s == '.')
+ {
+ s++;
+ while (*s && VIM_ISDIGIT(*s))
+ s++;
+ }
+ if (*s == '(')
+ {
+ groupdepth++;
+ continue;
+ }
+ if (vim_strchr(STL_ALL, *s) == NULL)
+ {
+ return illegal_char(errbuf, *s);
+ }
+ if (*s == '{')
+ {
+ s++;
+ while (*s != '}' && *s)
+ s++;
+ if (*s != '}')
+ return (char_u *)N_("E540: Unclosed expression sequence");
+ }
+ }
+ if (itemcnt >= STL_MAX_ITEM)
+ return (char_u *)N_("E541: too many items");
+ if (groupdepth != 0)
+ return (char_u *)N_("E542: unbalanced groups");
+ return NULL;
+}
+#endif
+
+#ifdef FEAT_CLIPBOARD
+/*
+ * Extract the items in the 'clipboard' option and set global values.
+ */
+ static char_u *
+check_clipboard_option()
+{
+ int new_unnamed = FALSE;
+ int new_autoselect = FALSE;
+ int new_autoselectml = FALSE;
+ regprog_T *new_exclude_prog = NULL;
+ char_u *errmsg = NULL;
+ char_u *p;
+
+ for (p = p_cb; *p != NUL; )
+ {
+ if (STRNCMP(p, "unnamed", 7) == 0 && (p[7] == ',' || p[7] == NUL))
+ {
+ new_unnamed = TRUE;
+ p += 7;
+ }
+ else if (STRNCMP(p, "autoselect", 10) == 0
+ && (p[10] == ',' || p[10] == NUL))
+ {
+ new_autoselect = TRUE;
+ p += 10;
+ }
+ else if (STRNCMP(p, "autoselectml", 12) == 0
+ && (p[12] == ',' || p[12] == NUL))
+ {
+ new_autoselectml = TRUE;
+ p += 12;
+ }
+ else if (STRNCMP(p, "exclude:", 8) == 0 && new_exclude_prog == NULL)
+ {
+ p += 8;
+ new_exclude_prog = vim_regcomp(p, RE_MAGIC);
+ if (new_exclude_prog == NULL)
+ errmsg = e_invarg;
+ break;
+ }
+ else
+ {
+ errmsg = e_invarg;
+ break;
+ }
+ if (*p == ',')
+ ++p;
+ }
+ if (errmsg == NULL)
+ {
+ clip_unnamed = new_unnamed;
+ clip_autoselect = new_autoselect;
+ clip_autoselectml = new_autoselectml;
+ vim_free(clip_exclude_prog);
+ clip_exclude_prog = new_exclude_prog;
+ }
+ else
+ vim_free(new_exclude_prog);
+
+ return errmsg;
+}
+#endif
+
+/*
+ * Set the value of a boolean option, and take care of side effects.
+ * Returns NULL for success, or an error message for an error.
+ */
+ static char_u *
+set_bool_option(opt_idx, varp, value, opt_flags)
+ int opt_idx; /* index in options[] table */
+ char_u *varp; /* pointer to the option variable */
+ int value; /* new value */
+ int opt_flags; /* OPT_LOCAL and/or OPT_GLOBAL */
+{
+ int old_value = *(int *)varp;
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+
+ /* Disallow changing some options from secure mode */
+ if ((secure
+#ifdef HAVE_SANDBOX
+ || sandbox != 0
+#endif
+ ) && (options[opt_idx].flags & P_SECURE))
+ return e_secure;
+
+ *(int *)varp = value; /* set the new value */
+#ifdef FEAT_EVAL
+ /* Remember where the option was set. */
+ options[opt_idx].scriptID = current_SID;
+#endif
+
+ /* May set global value for local option. */
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+ *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = value;
+
+ /*
+ * Handle side effects of changing a bool option.
+ */
+
+ /* 'compatible' */
+ if ((int *)varp == &p_cp)
+ {
+ compatible_set();
+ }
+
+ /* when 'readonly' is reset globally, also reset readonlymode */
+ else if ((int *)varp == &curbuf->b_p_ro)
+ {
+ if (!curbuf->b_p_ro && (opt_flags & OPT_LOCAL) == 0)
+ readonlymode = FALSE;
+#ifdef FEAT_TITLE
+ need_maketitle = TRUE;
+#endif
+ }
+
+#ifdef FEAT_TITLE
+ /* when 'modifiable' is changed, redraw the window title */
+ else if ((int *)varp == &curbuf->b_p_ma)
+ need_maketitle = TRUE;
+ /* when 'endofline' is changed, redraw the window title */
+ else if ((int *)varp == &curbuf->b_p_eol)
+ need_maketitle = TRUE;
+#endif
+
+ /* when 'bin' is set also set some other options */
+ else if ((int *)varp == &curbuf->b_p_bin)
+ {
+ set_options_bin(old_value, curbuf->b_p_bin, opt_flags);
+#ifdef FEAT_TITLE
+ need_maketitle = TRUE;
+#endif
+ }
+
+#ifdef FEAT_AUTOCMD
+ /* when 'buflisted' changes, trigger autocommands */
+ else if ((int *)varp == &curbuf->b_p_bl && old_value != curbuf->b_p_bl)
+ {
+ apply_autocmds(curbuf->b_p_bl ? EVENT_BUFADD : EVENT_BUFDELETE,
+ NULL, NULL, TRUE, curbuf);
+ }
+#endif
+
+ /* when 'swf' is set, create swapfile, when reset remove swapfile */
+ else if ((int *)varp == &curbuf->b_p_swf)
+ {
+ if (curbuf->b_p_swf && p_uc)
+ ml_open_file(curbuf); /* create the swap file */
+ else
+ mf_close_file(curbuf, TRUE); /* remove the swap file */
+ }
+
+ /* when 'terse' is set change 'shortmess' */
+ else if ((int *)varp == &p_terse)
+ {
+ char_u *p;
+
+ p = vim_strchr(p_shm, SHM_SEARCH);
+
+ /* insert 's' in p_shm */
+ if (p_terse && p == NULL)
+ {
+ STRCPY(IObuff, p_shm);
+ STRCAT(IObuff, "s");
+ set_string_option_direct((char_u *)"shm", -1, IObuff, OPT_FREE);
+ }
+ /* remove 's' from p_shm */
+ else if (!p_terse && p != NULL)
+ mch_memmove(p, p + 1, STRLEN(p));
+ }
+
+ /* when 'paste' is set or reset also change other options */
+ else if ((int *)varp == &p_paste)
+ {
+ paste_option_changed();
+ }
+
+ /* when 'insertmode' is set from an autocommand need to do work here */
+ else if ((int *)varp == &p_im)
+ {
+ if (p_im)
+ {
+ if ((State & INSERT) == 0)
+ need_start_insertmode = TRUE;
+ stop_insert_mode = FALSE;
+ }
+ else
+ {
+ need_start_insertmode = FALSE;
+ stop_insert_mode = TRUE;
+ if (p_smd && restart_edit != 0)
+ clear_cmdline = TRUE; /* remove "(insert)" */
+ restart_edit = 0;
+ }
+ }
+
+ /* when 'ignorecase' is set or reset and 'hlsearch' is set, redraw */
+ else if ((int *)varp == &p_ic && p_hls)
+ {
+ redraw_all_later(NOT_VALID);
+ }
+
+#ifdef FEAT_SEARCH_EXTRA
+ /* when 'hlsearch' is set or reset: reset no_hlsearch */
+ else if ((int *)varp == &p_hls)
+ {
+ no_hlsearch = FALSE;
+ }
+#endif
+
+#ifdef FEAT_SCROLLBIND
+ /* when 'scrollbind' is set: snapshot the current position to avoid a jump
+ * at the end of normal_cmd() */
+ else if ((int *)varp == &curwin->w_p_scb)
+ {
+ if (curwin->w_p_scb)
+ do_check_scrollbind(FALSE);
+ }
+#endif
+
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ /* There can be only one window with 'previewwindow' set. */
+ else if ((int *)varp == &curwin->w_p_pvw)
+ {
+ if (curwin->w_p_pvw)
+ {
+ win_T *win;
+
+ for (win = firstwin; win != NULL; win = win->w_next)
+ if (win->w_p_pvw && win != curwin)
+ {
+ curwin->w_p_pvw = FALSE;
+ return (char_u *)N_("E590: A preview window already exists");
+ }
+ }
+ }
+#endif
+
+ /* when 'textmode' is set or reset also change 'fileformat' */
+ else if ((int *)varp == &curbuf->b_p_tx)
+ {
+ set_fileformat(curbuf->b_p_tx ? EOL_DOS : EOL_UNIX, opt_flags);
+ }
+
+ /* when 'textauto' is set or reset also change 'fileformats' */
+ else if ((int *)varp == &p_ta)
+ {
+ set_string_option_direct((char_u *)"ffs", -1,
+ p_ta ? (char_u *)DFLT_FFS_VIM : (char_u *)"",
+ OPT_FREE | opt_flags);
+ }
+
+ /*
+ * When 'lisp' option changes include/exclude '-' in
+ * keyword characters.
+ */
+#ifdef FEAT_LISP
+ else if (varp == (char_u *)&(curbuf->b_p_lisp))
+ {
+ (void)buf_init_chartab(curbuf, FALSE); /* ignore errors */
+ }
+#endif
+
+#ifdef FEAT_TITLE
+ /* when 'title' changed, may need to change the title; same for 'icon' */
+ else if ((int *)varp == &p_title)
+ {
+ did_set_title(FALSE);
+ }
+
+ else if ((int *)varp == &p_icon)
+ {
+ did_set_title(TRUE);
+ }
+#endif
+
+ else if ((int *)varp == &curbuf->b_changed)
+ {
+ if (!value)
+ save_file_ff(curbuf); /* Buffer is unchanged */
+#ifdef FEAT_TITLE
+ need_maketitle = TRUE;
+#endif
+#ifdef FEAT_AUTOCMD
+ modified_was_set = value;
+#endif
+ }
+
+#ifdef BACKSLASH_IN_FILENAME
+ else if ((int *)varp == &p_ssl)
+ {
+ if (p_ssl)
+ {
+ psepc = '/';
+ psepcN = '\\';
+ pseps[0] = '/';
+ psepsN[0] = '\\';
+ }
+ else
+ {
+ psepc = '\\';
+ psepcN = '/';
+ pseps[0] = '\\';
+ psepsN[0] = '/';
+ }
+
+ /* need to adjust the file name arguments and buffer names. */
+ buflist_slash_adjust();
+ alist_slash_adjust();
+# ifdef FEAT_EVAL
+ scriptnames_slash_adjust();
+# endif
+ }
+#endif
+
+ /* If 'wrap' is set, set w_leftcol to zero. */
+ else if ((int *)varp == &curwin->w_p_wrap)
+ {
+ if (curwin->w_p_wrap)
+ curwin->w_leftcol = 0;
+ }
+
+#ifdef FEAT_WINDOWS
+ else if ((int *)varp == &p_ea)
+ {
+ if (p_ea && !old_value)
+ win_equal(curwin, FALSE, 0);
+ }
+#endif
+
+ else if ((int *)varp == &p_wiv)
+ {
+ /*
+ * When 'weirdinvert' changed, set/reset 't_xs'.
+ * Then set 'weirdinvert' according to value of 't_xs'.
+ */
+ if (p_wiv && !old_value)
+ T_XS = (char_u *)"y";
+ else if (!p_wiv && old_value)
+ T_XS = empty_option;
+ p_wiv = (*T_XS != NUL);
+ }
+
+#if defined(FEAT_BEVAL) && (defined(FEAT_SUN_WORKSHOP) \
+ || defined(FEAT_NETBEANS_INTG))
+ else if ((int *)varp == &p_beval)
+ {
+ extern BalloonEval *balloonEval;
+
+ if (p_beval == TRUE)
+ gui_mch_enable_beval_area(balloonEval);
+ else
+ gui_mch_disable_beval_area(balloonEval);
+ }
+
+ else if ((int *)varp == &p_acd)
+ {
+ if (p_acd && curbuf->b_ffname != NULL
+ && vim_chdirfile(curbuf->b_ffname) == OK)
+ shorten_fnames(TRUE);
+ }
+#endif
+
+#ifdef FEAT_DIFF
+ /* 'diff' */
+ else if ((int *)varp == &curwin->w_p_diff)
+ {
+ win_T *wp;
+
+ if (!curwin->w_p_diff)
+ {
+ /* When there is no window showing a diff for this buffer, remove
+ * it from the diffs. */
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_buffer == curwin->w_buffer && wp->w_p_diff)
+ break;
+ if (wp == NULL)
+ diff_buf_delete(curwin->w_buffer);
+ }
+ else
+ diff_buf_add(curwin->w_buffer);
+#ifdef FEAT_FOLDING
+ if (foldmethodIsDiff(curwin))
+ foldUpdateAll(curwin);
+#endif
+ }
+#endif
+
+#ifdef USE_IM_CONTROL
+ /* 'imdisable' */
+ else if ((int *)varp == &p_imdisable)
+ {
+ /* Only de-activate it here, it will be enabled when changing mode. */
+ if (p_imdisable)
+ im_set_active(FALSE);
+ }
+#endif
+
+#ifdef FEAT_FKMAP
+ else if ((int *)varp == &p_altkeymap)
+ {
+ if (old_value != p_altkeymap)
+ {
+ if (!p_altkeymap)
+ {
+ p_hkmap = p_fkmap;
+ p_fkmap = 0;
+ }
+ else
+ {
+ p_fkmap = p_hkmap;
+ p_hkmap = 0;
+ }
+ (void)init_chartab();
+ }
+ }
+
+ /*
+ * In case some second language keymapping options have changed, check
+ * and correct the setting in a consistent way.
+ */
+
+ /*
+ * If hkmap or fkmap are set, reset Arabic keymapping.
+ */
+ if ((p_hkmap || p_fkmap) && p_altkeymap)
+ {
+ p_altkeymap = p_fkmap;
+# ifdef FEAT_ARABIC
+ curwin->w_p_arab = FALSE;
+# endif
+ (void)init_chartab();
+ }
+
+ /*
+ * If hkmap set, reset Farsi keymapping.
+ */
+ if (p_hkmap && p_altkeymap)
+ {
+ p_altkeymap = 0;
+ p_fkmap = 0;
+# ifdef FEAT_ARABIC
+ curwin->w_p_arab = FALSE;
+# endif
+ (void)init_chartab();
+ }
+
+ /*
+ * If fkmap set, reset Hebrew keymapping.
+ */
+ if (p_fkmap && !p_altkeymap)
+ {
+ p_altkeymap = 1;
+ p_hkmap = 0;
+# ifdef FEAT_ARABIC
+ curwin->w_p_arab = FALSE;
+# endif
+ (void)init_chartab();
+ }
+#endif
+
+#ifdef FEAT_ARABIC
+ if ((int *)varp == &curwin->w_p_arab)
+ {
+ if (curwin->w_p_arab)
+ {
+ /*
+ * 'arabic' is set, handle various sub-settings.
+ */
+ if (!p_tbidi)
+ {
+ /* set rightleft mode */
+ if (!curwin->w_p_rl)
+ {
+ curwin->w_p_rl = TRUE;
+ changed_window_setting();
+ }
+
+ /* Enable Arabic shaping (major part of what Arabic requires) */
+ if (!p_arshape)
+ {
+ p_arshape = TRUE;
+ redraw_later_clear();
+ }
+ }
+
+ /* Arabic requires a utf-8 encoding, inform the user if its not
+ * set. */
+ if (STRCMP(p_enc, "utf-8") != 0)
+ MSG_ATTR(_("W17: Arabic requires UTF-8, do ':set encoding=utf-8'"),
+ hl_attr(HLF_W));
+
+# ifdef FEAT_MBYTE
+ /* set 'delcombine' */
+ p_deco = TRUE;
+# endif
+
+# ifdef FEAT_KEYMAP
+ /* Force-set the necessary keymap for arabic */
+ set_option_value((char_u *)"keymap", 0L, (char_u *)"arabic",
+ OPT_LOCAL);
+# endif
+# ifdef FEAT_FKMAP
+ p_altkeymap = 0;
+ p_hkmap = 0;
+ p_fkmap = 0;
+ (void)init_chartab();
+# endif
+ }
+ else
+ {
+ /*
+ * 'arabic' is reset, handle various sub-settings.
+ */
+ if (!p_tbidi)
+ {
+ /* reset rightleft mode */
+ if (curwin->w_p_rl)
+ {
+ curwin->w_p_rl = FALSE;
+ changed_window_setting();
+ }
+
+ /* 'arabicshape' isn't reset, it is a global option and
+ * another window may still need it "on". */
+ }
+
+ /* 'delcombine' isn't reset, it is a global option and another
+ * window may still want it "on". */
+
+# ifdef FEAT_KEYMAP
+ /* Revert to the default keymap */
+ curbuf->b_p_iminsert = B_IMODE_NONE;
+ curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
+# endif
+ }
+ }
+#endif
+
+ /*
+ * End of handling side effects for bool options.
+ */
+
+ options[opt_idx].flags |= P_WAS_SET;
+
+ comp_col(); /* in case 'ruler' or 'showcmd' changed */
+ if (curwin->w_curswant != MAXCOL)
+ curwin->w_set_curswant = TRUE; /* in case 'list' changed */
+ check_redraw(options[opt_idx].flags);
+
+ return NULL;
+}
+
+/*
+ * Set the value of a number option, and take care of side effects.
+ * Returns NULL for success, or an error message for an error.
+ */
+ static char_u *
+set_num_option(opt_idx, varp, value, errbuf, opt_flags)
+ int opt_idx; /* index in options[] table */
+ char_u *varp; /* pointer to the option variable */
+ long value; /* new value */
+ char_u *errbuf; /* buffer for error messages */
+ int opt_flags; /* OPT_LOCAL, OPT_GLOBAL and
+ OPT_MODELINE */
+{
+ char_u *errmsg = NULL;
+ long old_value = *(long *)varp;
+ long old_Rows = Rows; /* remember old Rows */
+ long old_Columns = Columns; /* remember old Columns */
+ long *pp = (long *)varp;
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+
+ *pp = value;
+#ifdef FEAT_EVAL
+ /* Remember where the option was set. */
+ options[opt_idx].scriptID = current_SID;
+#endif
+
+ if (curbuf->b_p_sw <= 0)
+ {
+ errmsg = e_positive;
+ curbuf->b_p_sw = curbuf->b_p_ts;
+ }
+
+ /*
+ * Number options that need some action when changed
+ */
+#ifdef FEAT_WINDOWS
+ if (pp == &p_wh || pp == &p_hh)
+ {
+ if (p_wh < 1)
+ {
+ errmsg = e_positive;
+ p_wh = 1;
+ }
+ if (p_wmh > p_wh)
+ {
+ errmsg = e_winheight;
+ p_wh = p_wmh;
+ }
+ if (p_hh < 0)
+ {
+ errmsg = e_positive;
+ p_hh = 0;
+ }
+
+ /* Change window height NOW */
+ if (lastwin != firstwin)
+ {
+ if (pp == &p_wh && curwin->w_height < p_wh)
+ win_setheight((int)p_wh);
+ if (pp == &p_hh && curbuf->b_help && curwin->w_height < p_hh)
+ win_setheight((int)p_hh);
+ }
+ }
+
+ /* 'winminheight' */
+ else if (pp == &p_wmh)
+ {
+ if (p_wmh < 0)
+ {
+ errmsg = e_positive;
+ p_wmh = 0;
+ }
+ if (p_wmh > p_wh)
+ {
+ errmsg = e_winheight;
+ p_wmh = p_wh;
+ }
+ win_setminheight();
+ }
+
+# ifdef FEAT_VERTSPLIT
+ if (pp == &p_wiw)
+ {
+ if (p_wiw < 1)
+ {
+ errmsg = e_positive;
+ p_wiw = 1;
+ }
+ if (p_wmw > p_wiw)
+ {
+ errmsg = e_winwidth;
+ p_wiw = p_wmw;
+ }
+
+ /* Change window width NOW */
+ if (lastwin != firstwin && curwin->w_width < p_wiw)
+ win_setwidth((int)p_wiw);
+ }
+
+ /* 'winminwidth' */
+ else if (pp == &p_wmw)
+ {
+ if (p_wmw < 0)
+ {
+ errmsg = e_positive;
+ p_wmw = 0;
+ }
+ if (p_wmw > p_wiw)
+ {
+ errmsg = e_winwidth;
+ p_wmw = p_wiw;
+ }
+ win_setminheight();
+ }
+# endif
+
+#endif
+
+#ifdef FEAT_WINDOWS
+ /* (re)set last window status line */
+ else if (pp == &p_ls)
+ {
+ last_status(FALSE);
+ }
+#endif
+
+#ifdef FEAT_GUI
+ else if (pp == &p_linespace)
+ {
+ if (gui.in_use && gui_mch_adjust_charsize() == OK)
+ gui_set_shellsize(FALSE, FALSE);
+ }
+#endif
+
+#ifdef FEAT_FOLDING
+ /* 'foldlevel' */
+ else if (pp == &curwin->w_p_fdl)
+ {
+ if (curwin->w_p_fdl < 0)
+ curwin->w_p_fdl = 0;
+ newFoldLevel();
+ }
+
+ /* 'foldminlevel' */
+ else if (pp == &curwin->w_p_fml)
+ {
+ foldUpdateAll(curwin);
+ }
+
+ /* 'foldnestmax' */
+ else if (pp == &curwin->w_p_fdn)
+ {
+ if (foldmethodIsSyntax(curwin) || foldmethodIsIndent(curwin))
+ foldUpdateAll(curwin);
+ }
+
+ /* 'foldcolumn' */
+ else if (pp == &curwin->w_p_fdc)
+ {
+ if (curwin->w_p_fdc < 0)
+ {
+ errmsg = e_positive;
+ curwin->w_p_fdc = 0;
+ }
+ else if (curwin->w_p_fdc > 12)
+ {
+ errmsg = e_invarg;
+ curwin->w_p_fdc = 12;
+ }
+ }
+
+ /* 'shiftwidth' or 'tabstop' */
+ else if (pp == &curbuf->b_p_sw || pp == &curbuf->b_p_ts)
+ {
+ if (foldmethodIsIndent(curwin))
+ foldUpdateAll(curwin);
+ }
+#endif /* FEAT_FOLDING */
+
+ else if (pp == &curbuf->b_p_iminsert)
+ {
+ if (curbuf->b_p_iminsert < 0 || curbuf->b_p_iminsert > B_IMODE_LAST)
+ {
+ errmsg = e_invarg;
+ curbuf->b_p_iminsert = B_IMODE_NONE;
+ }
+ p_iminsert = curbuf->b_p_iminsert;
+ if (termcap_active) /* don't do this in the alternate screen */
+ showmode();
+#if defined(FEAT_WINDOWS) && defined(FEAT_KEYMAP)
+ /* Show/unshow value of 'keymap' in status lines. */
+ status_redraw_curbuf();
+#endif
+ }
+
+ else if (pp == &curbuf->b_p_imsearch)
+ {
+ if (curbuf->b_p_imsearch < -1 || curbuf->b_p_imsearch > B_IMODE_LAST)
+ {
+ errmsg = e_invarg;
+ curbuf->b_p_imsearch = B_IMODE_NONE;
+ }
+ p_imsearch = curbuf->b_p_imsearch;
+ }
+
+#ifdef FEAT_TITLE
+ /* if 'titlelen' has changed, redraw the title */
+ else if (pp == &p_titlelen)
+ {
+ if (p_titlelen < 0)
+ {
+ errmsg = e_positive;
+ p_titlelen = 85;
+ }
+ if (starting != NO_SCREEN && old_value != p_titlelen)
+ need_maketitle = TRUE;
+ }
+#endif
+
+ /* if p_ch changed value, change the command line height */
+ else if (pp == &p_ch)
+ {
+ if (p_ch < 1)
+ {
+ errmsg = e_positive;
+ p_ch = 1;
+ }
+
+ /* Only compute the new window layout when startup has been
+ * completed. Otherwise the frame sizes may be wrong. */
+ if (p_ch != old_value && full_screen
+#ifdef FEAT_GUI
+ && !gui.starting
+#endif
+ )
+ command_height(old_value);
+ }
+
+ /* when 'updatecount' changes from zero to non-zero, open swap files */
+ else if (pp == &p_uc)
+ {
+ if (p_uc < 0)
+ {
+ errmsg = e_positive;
+ p_uc = 100;
+ }
+ if (p_uc && !old_value)
+ ml_open_files();
+ }
+
+ /* sync undo before 'undolevels' changes */
+ else if (pp == &p_ul)
+ {
+ /* use the old value, otherwise u_sync() may not work properly */
+ p_ul = old_value;
+ u_sync();
+ p_ul = value;
+ }
+
+ /*
+ * Check the bounds for numeric options here
+ */
+ if (Rows < min_rows() && full_screen)
+ {
+ if (errbuf != NULL)
+ {
+ sprintf((char *)errbuf, _("E593: Need at least %d lines"),
+ min_rows());
+ errmsg = errbuf;
+ }
+ Rows = min_rows();
+ }
+ if (Columns < MIN_COLUMNS && full_screen)
+ {
+ if (errbuf != NULL)
+ {
+ sprintf((char *)errbuf, _("E594: Need at least %d columns"),
+ MIN_COLUMNS);
+ errmsg = errbuf;
+ }
+ Columns = MIN_COLUMNS;
+ }
+
+#ifdef DJGPP
+ /* avoid a crash by checking for a too large value of 'columns' */
+ if (old_Columns != Columns && full_screen && term_console)
+ mch_check_columns();
+#endif
+
+ /*
+ * If the screen (shell) height has been changed, assume it is the
+ * physical screenheight.
+ */
+ if (old_Rows != Rows || old_Columns != Columns)
+ {
+ /* Changing the screen size is not allowed while updating the screen. */
+ if (updating_screen)
+ *pp = old_value;
+ else if (full_screen
+#ifdef FEAT_GUI
+ && !gui.starting
+#endif
+ )
+ set_shellsize((int)Columns, (int)Rows, TRUE);
+ else
+ {
+ /* Postpone the resizing; check the size and cmdline position for
+ * messages. */
+ check_shellsize();
+ if (cmdline_row > Rows - p_ch && Rows > p_ch)
+ cmdline_row = Rows - p_ch;
+ }
+ }
+
+ if (curbuf->b_p_sts < 0)
+ {
+ errmsg = e_positive;
+ curbuf->b_p_sts = 0;
+ }
+ if (curbuf->b_p_ts <= 0)
+ {
+ errmsg = e_positive;
+ curbuf->b_p_ts = 8;
+ }
+ if (curbuf->b_p_tw < 0)
+ {
+ errmsg = e_positive;
+ curbuf->b_p_tw = 0;
+ }
+ if (p_tm < 0)
+ {
+ errmsg = e_positive;
+ p_tm = 0;
+ }
+ if ((curwin->w_p_scr <= 0
+ || (curwin->w_p_scr > curwin->w_height
+ && curwin->w_height > 0))
+ && full_screen)
+ {
+ if (pp == &(curwin->w_p_scr))
+ {
+ if (curwin->w_p_scr != 0)
+ errmsg = e_scroll;
+ win_comp_scroll(curwin);
+ }
+ /* If 'scroll' became invalid because of a side effect silently adjust
+ * it. */
+ else if (curwin->w_p_scr <= 0)
+ curwin->w_p_scr = 1;
+ else /* curwin->w_p_scr > curwin->w_height */
+ curwin->w_p_scr = curwin->w_height;
+ }
+ if (p_report < 0)
+ {
+ errmsg = e_positive;
+ p_report = 1;
+ }
+ if ((p_sj < 0 || p_sj >= Rows) && full_screen)
+ {
+ if (Rows != old_Rows) /* Rows changed, just adjust p_sj */
+ p_sj = Rows / 2;
+ else
+ {
+ errmsg = e_scroll;
+ p_sj = 1;
+ }
+ }
+ if (p_so < 0 && full_screen)
+ {
+ errmsg = e_scroll;
+ p_so = 0;
+ }
+ if (p_siso < 0 && full_screen)
+ {
+ errmsg = e_positive;
+ p_siso = 0;
+ }
+#ifdef FEAT_CMDWIN
+ if (p_cwh < 1)
+ {
+ errmsg = e_positive;
+ p_cwh = 1;
+ }
+#endif
+ if (p_ut < 0)
+ {
+ errmsg = e_positive;
+ p_ut = 2000;
+ }
+ if (p_ss < 0)
+ {
+ errmsg = e_positive;
+ p_ss = 0;
+ }
+
+ /* May set global value for local option. */
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+ *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = *pp;
+
+ options[opt_idx].flags |= P_WAS_SET;
+
+ comp_col(); /* in case 'columns' or 'ls' changed */
+ if (curwin->w_curswant != MAXCOL)
+ curwin->w_set_curswant = TRUE; /* in case 'tabstop' changed */
+ check_redraw(options[opt_idx].flags);
+
+ return errmsg;
+}
+
+/*
+ * Called after an option changed: check if something needs to be redrawn.
+ */
+ static void
+check_redraw(flags)
+ long_u flags;
+{
+ /* Careful: P_RCLR and P_RALL are a combination of other P_ flags */
+ int clear = (flags & P_RCLR) == P_RCLR;
+ int all = ((flags & P_RALL) == P_RALL || clear);
+
+#ifdef FEAT_WINDOWS
+ if ((flags & P_RSTAT) || all) /* mark all status lines dirty */
+ status_redraw_all();
+#endif
+
+ if ((flags & P_RBUF) || (flags & P_RWIN) || all)
+ changed_window_setting();
+ if (flags & P_RBUF)
+ redraw_curbuf_later(NOT_VALID);
+ if (clear)
+ redraw_all_later(CLEAR);
+ else if (all)
+ redraw_all_later(NOT_VALID);
+}
+
+/*
+ * Find index for option 'arg'.
+ * Return -1 if not found.
+ */
+ static int
+findoption(arg)
+ char_u *arg;
+{
+ int opt_idx;
+ char *s, *p;
+ static short quick_tab[27] = {0, 0}; /* quick access table */
+ int is_term_opt;
+
+ /*
+ * For first call: Initialize the quick-access table.
+ * It contains the index for the first option that starts with a certain
+ * letter. There are 26 letters, plus the first "t_" option.
+ */
+ if (quick_tab[1] == 0)
+ {
+ p = options[0].fullname;
+ for (opt_idx = 1; (s = options[opt_idx].fullname) != NULL; opt_idx++)
+ {
+ if (s[0] != p[0])
+ {
+ if (s[0] == 't' && s[1] == '_')
+ quick_tab[26] = opt_idx;
+ else
+ quick_tab[CharOrdLow(s[0])] = opt_idx;
+ }
+ p = s;
+ }
+ }
+
+ /*
+ * Check for name starting with an illegal character.
+ */
+#ifdef EBCDIC
+ if (!islower(arg[0]))
+#else
+ if (arg[0] < 'a' || arg[0] > 'z')
+#endif
+ return -1;
+
+ is_term_opt = (arg[0] == 't' && arg[1] == '_');
+ if (is_term_opt)
+ opt_idx = quick_tab[26];
+ else
+ opt_idx = quick_tab[CharOrdLow(arg[0])];
+ for ( ; (s = options[opt_idx].fullname) != NULL; opt_idx++)
+ {
+ if (STRCMP(arg, s) == 0) /* match full name */
+ break;
+ }
+ if (s == NULL && !is_term_opt)
+ {
+ opt_idx = quick_tab[CharOrdLow(arg[0])];
+ for ( ; options[opt_idx].fullname != NULL; opt_idx++)
+ {
+ s = options[opt_idx].shortname;
+ if (s != NULL && STRCMP(arg, s) == 0) /* match short name */
+ break;
+ s = NULL;
+ }
+ }
+ if (s == NULL)
+ opt_idx = -1;
+ return opt_idx;
+}
+
+#if defined(FEAT_EVAL) || defined(FEAT_TCL)
+/*
+ * Get the value for an option.
+ *
+ * Returns:
+ * Number or Toggle option: 1, *numval gets value.
+ * String option: 0, *stringval gets allocated string.
+ * Hidden Number or Toggle option: -1.
+ * hidden String option: -2.
+ * unknown option: -3.
+ */
+ int
+get_option_value(name, numval, stringval, opt_flags)
+ char_u *name;
+ long *numval;
+ char_u **stringval; /* NULL when only checking existance */
+ int opt_flags;
+{
+ int opt_idx;
+ char_u *varp;
+
+ opt_idx = findoption(name);
+ if (opt_idx < 0) /* unknown option */
+ return -3;
+
+ varp = get_varp_scope(&(options[opt_idx]), opt_flags);
+
+ if (options[opt_idx].flags & P_STRING)
+ {
+ if (varp == NULL) /* hidden option */
+ return -2;
+ if (stringval != NULL)
+ {
+#ifdef FEAT_CRYPT
+ /* never return the value of the crypt key */
+ if ((char_u **)varp == &curbuf->b_p_key)
+ *stringval = vim_strsave((char_u *)"*****");
+ else
+#endif
+ *stringval = vim_strsave(*(char_u **)(varp));
+ }
+ return 0;
+ }
+
+ if (varp == NULL) /* hidden option */
+ return -1;
+ if (options[opt_idx].flags & P_NUM)
+ *numval = *(long *)varp;
+ else
+ {
+ /* Special case: 'modified' is b_changed, but we also want to consider
+ * it set when 'ff' or 'fenc' changed. */
+ if ((int *)varp == &curbuf->b_changed)
+ *numval = curbufIsChanged();
+ else
+ *numval = *(int *)varp;
+ }
+ return 1;
+}
+#endif
+
+/*
+ * Set the value of option "name".
+ * Use "string" for string options, use "number" for other options.
+ */
+ void
+set_option_value(name, number, string, opt_flags)
+ char_u *name;
+ long number;
+ char_u *string;
+ int opt_flags; /* OPT_LOCAL or 0 (both) */
+{
+ int opt_idx;
+ char_u *varp;
+ int flags;
+
+ opt_idx = findoption(name);
+ if (opt_idx == -1)
+ EMSG2(_("E355: Unknown option: %s"), name);
+ else
+ {
+ flags = options[opt_idx].flags;
+#ifdef HAVE_SANDBOX
+ /* Disallow changing some options in the sandbox */
+ if (sandbox > 0 && (flags & P_SECURE))
+ EMSG(_(e_sandbox));
+ else
+#endif
+ if (flags & P_STRING)
+ set_string_option(opt_idx, string, opt_flags);
+ else
+ {
+ varp = get_varp(&options[opt_idx]);
+ if (varp != NULL) /* hidden option is not changed */
+ {
+ if (flags & P_NUM)
+ (void)set_num_option(opt_idx, varp, number, NULL, opt_flags);
+ else
+ (void)set_bool_option(opt_idx, varp, (int)number, opt_flags);
+ }
+ }
+ }
+}
+
+/*
+ * Get the terminal code for a terminal option.
+ * Returns NULL when not found.
+ */
+ char_u *
+get_term_code(tname)
+ char_u *tname;
+{
+ int opt_idx;
+ char_u *varp;
+
+ if (tname[0] != 't' || tname[1] != '_' ||
+ tname[2] == NUL || tname[3] == NUL)
+ return NULL;
+ if ((opt_idx = findoption(tname)) >= 0)
+ {
+ varp = get_varp(&(options[opt_idx]));
+ if (varp != NULL)
+ varp = *(char_u **)(varp);
+ return varp;
+ }
+ return find_termcode(tname + 2);
+}
+
+ char_u *
+get_highlight_default()
+{
+ int i;
+
+ i = findoption((char_u *)"hl");
+ if (i >= 0)
+ return options[i].def_val[VI_DEFAULT];
+ return (char_u *)NULL;
+}
+
+/*
+ * Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number.
+ */
+ static int
+find_key_option(arg)
+ char_u *arg;
+{
+ int key;
+ int modifiers;
+
+ /*
+ * Don't use get_special_key_code() for t_xx, we don't want it to call
+ * add_termcap_entry().
+ */
+ if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
+ key = TERMCAP2KEY(arg[2], arg[3]);
+ else
+ {
+ --arg; /* put arg at the '<' */
+ modifiers = 0;
+ key = find_special_key(&arg, &modifiers, TRUE);
+ if (modifiers) /* can't handle modifiers here */
+ key = 0;
+ }
+ return key;
+}
+
+/*
+ * if 'all' == 0: show changed options
+ * if 'all' == 1: show all normal options
+ * if 'all' == 2: show all terminal options
+ */
+ static void
+showoptions(all, opt_flags)
+ int all;
+ int opt_flags; /* OPT_LOCAL and/or OPT_GLOBAL */
+{
+ struct vimoption *p;
+ int col;
+ int isterm;
+ char_u *varp;
+ struct vimoption **items;
+ int item_count;
+ int run;
+ int row, rows;
+ int cols;
+ int i;
+ int len;
+
+#define INC 20
+#define GAP 3
+
+ items = (struct vimoption **)alloc((unsigned)(sizeof(struct vimoption *) *
+ PARAM_COUNT));
+ if (items == NULL)
+ return;
+
+ /* Highlight title */
+ if (all == 2)
+ MSG_PUTS_TITLE(_("\n--- Terminal codes ---"));
+ else if (opt_flags & OPT_GLOBAL)
+ MSG_PUTS_TITLE(_("\n--- Global option values ---"));
+ else if (opt_flags & OPT_LOCAL)
+ MSG_PUTS_TITLE(_("\n--- Local option values ---"));
+ else
+ MSG_PUTS_TITLE(_("\n--- Options ---"));
+
+ /*
+ * do the loop two times:
+ * 1. display the short items
+ * 2. display the long items (only strings and numbers)
+ */
+ for (run = 1; run <= 2 && !got_int; ++run)
+ {
+ /*
+ * collect the items in items[]
+ */
+ item_count = 0;
+ for (p = &options[0]; p->fullname != NULL; p++)
+ {
+ varp = NULL;
+ isterm = istermoption(p);
+ if (opt_flags != 0)
+ {
+ if (p->indir != PV_NONE && !isterm)
+ varp = get_varp_scope(p, opt_flags);
+ }
+ else
+ varp = get_varp(p);
+ if (varp != NULL
+ && ((all == 2 && isterm)
+ || (all == 1 && !isterm)
+ || (all == 0 && !optval_default(p, varp))))
+ {
+ if (p->flags & P_BOOL)
+ len = 1; /* a toggle option fits always */
+ else
+ {
+ option_value2string(p, opt_flags);
+ len = (int)STRLEN(p->fullname) + vim_strsize(NameBuff) + 1;
+ }
+ if ((len <= INC - GAP && run == 1) ||
+ (len > INC - GAP && run == 2))
+ items[item_count++] = p;
+ }
+ }
+
+ /*
+ * display the items
+ */
+ if (run == 1)
+ {
+ cols = (Columns + GAP - 3) / INC;
+ if (cols == 0)
+ cols = 1;
+ rows = (item_count + cols - 1) / cols;
+ }
+ else /* run == 2 */
+ rows = item_count;
+ for (row = 0; row < rows && !got_int; ++row)
+ {
+ msg_putchar('\n'); /* go to next line */
+ if (got_int) /* 'q' typed in more */
+ break;
+ col = 0;
+ for (i = row; i < item_count; i += rows)
+ {
+ msg_col = col; /* make columns */
+ showoneopt(items[i], opt_flags);
+ col += INC;
+ }
+ out_flush();
+ ui_breakcheck();
+ }
+ }
+ vim_free(items);
+}
+
+/*
+ * Return TRUE if option "p" has its default value.
+ */
+ static int
+optval_default(p, varp)
+ struct vimoption *p;
+ char_u *varp;
+{
+ int dvi;
+
+ if (varp == NULL)
+ return TRUE; /* hidden option is always at default */
+ dvi = ((p->flags & P_VI_DEF) || p_cp) ? VI_DEFAULT : VIM_DEFAULT;
+ if (p->flags & P_NUM)
+ return (*(long *)varp == (long)p->def_val[dvi]);
+ if (p->flags & P_BOOL)
+ /* the cast to long is required for Manx C */
+ return (*(int *)varp == (int)(long)p->def_val[dvi]);
+ /* P_STRING */
+ return (STRCMP(*(char_u **)varp, p->def_val[dvi]) == 0);
+}
+
+/*
+ * showoneopt: show the value of one option
+ * must not be called with a hidden option!
+ */
+ static void
+showoneopt(p, opt_flags)
+ struct vimoption *p;
+ int opt_flags; /* OPT_LOCAL or OPT_GLOBAL */
+{
+ char_u *varp;
+
+ varp = get_varp_scope(p, opt_flags);
+
+ /* for 'modified' we also need to check if 'ff' or 'fenc' changed. */
+ if ((p->flags & P_BOOL) && ((int *)varp == &curbuf->b_changed
+ ? !curbufIsChanged() : !*(int *)varp))
+ MSG_PUTS("no");
+ else if ((p->flags & P_BOOL) && *(int *)varp < 0)
+ MSG_PUTS("--");
+ else
+ MSG_PUTS(" ");
+ MSG_PUTS(p->fullname);
+ if (!(p->flags & P_BOOL))
+ {
+ msg_putchar('=');
+ /* put value string in NameBuff */
+ option_value2string(p, opt_flags);
+ msg_outtrans(NameBuff);
+ }
+}
+
+/*
+ * Write modified options as ":set" commands to a file.
+ *
+ * There are three values for "opt_flags":
+ * OPT_GLOBAL: Write global option values and fresh values of
+ * buffer-local options (used for start of a session
+ * file).
+ * OPT_GLOBAL + OPT_LOCAL: Idem, add fresh values of window-local options for
+ * curwin (used for a vimrc file).
+ * OPT_LOCAL: Write buffer-local option values for curbuf, fresh
+ * and local values for window-local options of
+ * curwin. Local values are also written when at the
+ * default value, because a modeline or autocommand
+ * may have set them when doing ":edit file" and the
+ * user has set them back at the default or fresh
+ * value.
+ * When "local_only" is TRUE, don't write fresh
+ * values, only local values (for ":mkview").
+ * (fresh value = value used for a new buffer or window for a local option).
+ *
+ * Return FAIL on error, OK otherwise.
+ */
+ int
+makeset(fd, opt_flags, local_only)
+ FILE *fd;
+ int opt_flags;
+ int local_only;
+{
+ struct vimoption *p;
+ char_u *varp; /* currently used value */
+ char_u *varp_fresh; /* local value */
+ char_u *varp_local = NULL; /* fresh value */
+ char *cmd;
+ int round;
+
+ /*
+ * The options that don't have a default (terminal name, columns, lines)
+ * are never written. Terminal options are also not written.
+ */
+ for (p = &options[0]; !istermoption(p); p++)
+ if (!(p->flags & P_NO_MKRC) && !istermoption(p))
+ {
+ /* skip global option when only doing locals */
+ if (p->indir == PV_NONE && !(opt_flags & OPT_GLOBAL))
+ continue;
+
+ /* Do not store options like 'bufhidden' and 'syntax' in a vimrc
+ * file, they are always buffer-specific. */
+ if ((opt_flags & OPT_GLOBAL) && (p->flags & P_NOGLOB))
+ continue;
+
+ /* Global values are only written when not at the default value. */
+ varp = get_varp_scope(p, opt_flags);
+ if ((opt_flags & OPT_GLOBAL) && optval_default(p, varp))
+ continue;
+
+ round = 2;
+ if (p->indir != PV_NONE)
+ {
+ if (p->var == VAR_WIN)
+ {
+ /* skip window-local option when only doing globals */
+ if (!(opt_flags & OPT_LOCAL))
+ continue;
+ /* When fresh value of window-local option is not at the
+ * default, need to write it too. */
+ if (!(opt_flags & OPT_GLOBAL) && !local_only)
+ {
+ varp_fresh = get_varp_scope(p, OPT_GLOBAL);
+ if (!optval_default(p, varp_fresh))
+ {
+ round = 1;
+ varp_local = varp;
+ varp = varp_fresh;
+ }
+ }
+ }
+ }
+
+ /* Round 1: fresh value for window-local options.
+ * Round 2: other values */
+ for ( ; round <= 2; varp = varp_local, ++round)
+ {
+ if (round == 1 || (opt_flags & OPT_GLOBAL))
+ cmd = "set";
+ else
+ cmd = "setlocal";
+
+ if (p->flags & P_BOOL)
+ {
+ if (put_setbool(fd, cmd, p->fullname, *(int *)varp) == FAIL)
+ return FAIL;
+ }
+ else if (p->flags & P_NUM)
+ {
+ if (put_setnum(fd, cmd, p->fullname, (long *)varp) == FAIL)
+ return FAIL;
+ }
+ else /* P_STRING */
+ {
+ /* Don't set 'syntax' and 'filetype' again if the value is
+ * already right, avoids reloading the syntax file. */
+ if (p->indir == PV_SYN || p->indir == PV_FT)
+ {
+ if (fprintf(fd, "if &%s != '%s'", p->fullname,
+ *(char_u **)(varp)) < 0
+ || put_eol(fd) < 0)
+ return FAIL;
+ }
+ if (put_setstring(fd, cmd, p->fullname, (char_u **)varp,
+ (p->flags & P_EXPAND) != 0) == FAIL)
+ return FAIL;
+ if (p->indir == PV_SYN || p->indir == PV_FT)
+ {
+ if (put_line(fd, "endif") == FAIL)
+ return FAIL;
+ }
+ }
+ }
+ }
+ return OK;
+}
+
+#if defined(FEAT_FOLDING) || defined(PROTO)
+/*
+ * Generate set commands for the local fold options only. Used when
+ * 'sessionoptions' or 'viewoptions' contains "folds" but not "options".
+ */
+ int
+makefoldset(fd)
+ FILE *fd;
+{
+ if (put_setstring(fd, "setlocal", "fdm", &curwin->w_p_fdm, FALSE) == FAIL
+# ifdef FEAT_EVAL
+ || put_setstring(fd, "setlocal", "fde", &curwin->w_p_fde, FALSE)
+ == FAIL
+# endif
+ || put_setstring(fd, "setlocal", "fmr", &curwin->w_p_fmr, FALSE)
+ == FAIL
+ || put_setstring(fd, "setlocal", "fdi", &curwin->w_p_fdi, FALSE)
+ == FAIL
+ || put_setnum(fd, "setlocal", "fdl", &curwin->w_p_fdl) == FAIL
+ || put_setnum(fd, "setlocal", "fml", &curwin->w_p_fml) == FAIL
+ || put_setnum(fd, "setlocal", "fdn", &curwin->w_p_fdn) == FAIL
+ || put_setbool(fd, "setlocal", "fen", curwin->w_p_fen) == FAIL
+ )
+ return FAIL;
+
+ return OK;
+}
+#endif
+
+ static int
+put_setstring(fd, cmd, name, valuep, expand)
+ FILE *fd;
+ char *cmd;
+ char *name;
+ char_u **valuep;
+ int expand;
+{
+ char_u *s;
+ char_u buf[MAXPATHL];
+
+ if (fprintf(fd, "%s %s=", cmd, name) < 0)
+ return FAIL;
+ if (*valuep != NULL)
+ {
+ /* Output 'pastetoggle' as key names. For other
+ * options some characters have to be escaped with
+ * CTRL-V or backslash */
+ if (valuep == &p_pt)
+ {
+ s = *valuep;
+ while (*s != NUL)
+ if (fputs((char *)str2special(&s, FALSE), fd) < 0)
+ return FAIL;
+ }
+ else if (expand)
+ {
+ home_replace(NULL, *valuep, buf, MAXPATHL, FALSE);
+ if (put_escstr(fd, buf, 2) == FAIL)
+ return FAIL;
+ }
+ else if (put_escstr(fd, *valuep, 2) == FAIL)
+ return FAIL;
+ }
+ if (put_eol(fd) < 0)
+ return FAIL;
+ return OK;
+}
+
+ static int
+put_setnum(fd, cmd, name, valuep)
+ FILE *fd;
+ char *cmd;
+ char *name;
+ long *valuep;
+{
+ long wc;
+
+ if (fprintf(fd, "%s %s=", cmd, name) < 0)
+ return FAIL;
+ if (wc_use_keyname((char_u *)valuep, &wc))
+ {
+ /* print 'wildchar' and 'wildcharm' as a key name */
+ if (fputs((char *)get_special_key_name((int)wc, 0), fd) < 0)
+ return FAIL;
+ }
+ else if (fprintf(fd, "%ld", *valuep) < 0)
+ return FAIL;
+ if (put_eol(fd) < 0)
+ return FAIL;
+ return OK;
+}
+
+ static int
+put_setbool(fd, cmd, name, value)
+ FILE *fd;
+ char *cmd;
+ char *name;
+ int value;
+{
+ if (fprintf(fd, "%s %s%s", cmd, value ? "" : "no", name) < 0
+ || put_eol(fd) < 0)
+ return FAIL;
+ return OK;
+}
+
+/*
+ * Clear all the terminal options.
+ * If the option has been allocated, free the memory.
+ * Terminal options are never hidden or indirect.
+ */
+ void
+clear_termoptions()
+{
+ struct vimoption *p;
+
+ /*
+ * Reset a few things before clearing the old options. This may cause
+ * outputting a few things that the terminal doesn't understand, but the
+ * screen will be cleared later, so this is OK.
+ */
+#ifdef FEAT_MOUSE_TTY
+ mch_setmouse(FALSE); /* switch mouse off */
+#endif
+#ifdef FEAT_TITLE
+ mch_restore_title(3); /* restore window titles */
+#endif
+#if defined(FEAT_XCLIPBOARD) && defined(FEAT_GUI)
+ /* When starting the GUI close the display opened for the clipboard.
+ * After restoring the title, because that will need the display. */
+ if (gui.starting)
+ clear_xterm_clip();
+#endif
+#ifdef WIN3264
+ /*
+ * Check if this is allowed now.
+ */
+ if (can_end_termcap_mode(FALSE) == TRUE)
+#endif
+ stoptermcap(); /* stop termcap mode */
+
+ for (p = &options[0]; p->fullname != NULL; p++)
+ if (istermoption(p))
+ {
+ if (p->flags & P_ALLOCED)
+ free_string_option(*(char_u **)(p->var));
+ if (p->flags & P_DEF_ALLOCED)
+ free_string_option(p->def_val[VI_DEFAULT]);
+ *(char_u **)(p->var) = empty_option;
+ p->def_val[VI_DEFAULT] = empty_option;
+ p->flags &= ~(P_ALLOCED|P_DEF_ALLOCED);
+ }
+ clear_termcodes();
+}
+
+/*
+ * Set the terminal option defaults to the current value.
+ * Used after setting the terminal name.
+ */
+ void
+set_term_defaults()
+{
+ struct vimoption *p;
+
+ for (p = &options[0]; p->fullname != NULL; p++)
+ {
+ if (istermoption(p) && p->def_val[VI_DEFAULT] != *(char_u **)(p->var))
+ {
+ if (p->flags & P_DEF_ALLOCED)
+ {
+ free_string_option(p->def_val[VI_DEFAULT]);
+ p->flags &= ~P_DEF_ALLOCED;
+ }
+ p->def_val[VI_DEFAULT] = *(char_u **)(p->var);
+ if (p->flags & P_ALLOCED)
+ {
+ p->flags |= P_DEF_ALLOCED;
+ p->flags &= ~P_ALLOCED; /* don't free the value now */
+ }
+ }
+ }
+}
+
+/*
+ * return TRUE if 'p' starts with 't_'
+ */
+ static int
+istermoption(p)
+ struct vimoption *p;
+{
+ return (p->fullname[0] == 't' && p->fullname[1] == '_');
+}
+
+/*
+ * Compute columns for ruler and shown command. 'sc_col' is also used to
+ * decide what the maximum length of a message on the status line can be.
+ * If there is a status line for the last window, 'sc_col' is independent
+ * of 'ru_col'.
+ */
+
+#define COL_RULER 17 /* columns needed by standard ruler */
+
+ void
+comp_col()
+{
+#if defined(FEAT_CMDL_INFO) && defined(FEAT_WINDOWS)
+ int last_has_status = (p_ls == 2 || (p_ls == 1 && firstwin != lastwin));
+
+ sc_col = 0;
+ ru_col = 0;
+ if (p_ru)
+ {
+#ifdef FEAT_STL_OPT
+ ru_col = (ru_wid ? ru_wid : COL_RULER) + 1;
+#else
+ ru_col = COL_RULER + 1;
+#endif
+ /* no last status line, adjust sc_col */
+ if (!last_has_status)
+ sc_col = ru_col;
+ }
+ if (p_sc)
+ {
+ sc_col += SHOWCMD_COLS;
+ if (!p_ru || last_has_status) /* no need for separating space */
+ ++sc_col;
+ }
+ sc_col = Columns - sc_col;
+ ru_col = Columns - ru_col;
+ if (sc_col <= 0) /* screen too narrow, will become a mess */
+ sc_col = 1;
+ if (ru_col <= 0)
+ ru_col = 1;
+#else
+ sc_col = Columns;
+ ru_col = Columns;
+#endif
+}
+
+/*
+ * Get pointer to option variable, depending on local or global scope.
+ */
+ static char_u *
+get_varp_scope(p, opt_flags)
+ struct vimoption *p;
+ int opt_flags;
+{
+ if ((opt_flags & OPT_GLOBAL) && p->indir != PV_NONE)
+ {
+ if (p->var == VAR_WIN)
+ return (char_u *)GLOBAL_WO(get_varp(p));
+ return p->var;
+ }
+ if ((opt_flags & OPT_LOCAL) && (int)p->indir >= PV_BOTH)
+ {
+ switch ((int)p->indir)
+ {
+#ifdef FEAT_QUICKFIX
+ case OPT_BOTH(PV_GP): return (char_u *)&(curbuf->b_p_gp);
+ case OPT_BOTH(PV_MP): return (char_u *)&(curbuf->b_p_mp);
+ case OPT_BOTH(PV_EFM): return (char_u *)&(curbuf->b_p_efm);
+#endif
+ case OPT_BOTH(PV_EP): return (char_u *)&(curbuf->b_p_ep);
+ case OPT_BOTH(PV_KP): return (char_u *)&(curbuf->b_p_kp);
+ case OPT_BOTH(PV_PATH): return (char_u *)&(curbuf->b_p_path);
+ case OPT_BOTH(PV_AR): return (char_u *)&(curbuf->b_p_ar);
+ case OPT_BOTH(PV_TAGS): return (char_u *)&(curbuf->b_p_tags);
+#ifdef FEAT_FIND_ID
+ case OPT_BOTH(PV_DEF): return (char_u *)&(curbuf->b_p_def);
+ case OPT_BOTH(PV_INC): return (char_u *)&(curbuf->b_p_inc);
+#endif
+#ifdef FEAT_INS_EXPAND
+ case OPT_BOTH(PV_DICT): return (char_u *)&(curbuf->b_p_dict);
+ case OPT_BOTH(PV_TSR): return (char_u *)&(curbuf->b_p_tsr);
+#endif
+ }
+ return NULL; /* "cannot happen" */
+ }
+ return get_varp(p);
+}
+
+/*
+ * Get pointer to option variable.
+ */
+ static char_u *
+get_varp(p)
+ struct vimoption *p;
+{
+ /* hidden option, always return NULL */
+ if (p->var == NULL)
+ return NULL;
+
+ switch ((int)p->indir)
+ {
+ case PV_NONE: return p->var;
+
+ /* global option with local value: use local value if it's been set */
+ case OPT_BOTH(PV_EP): return *curbuf->b_p_ep != NUL
+ ? (char_u *)&curbuf->b_p_ep : p->var;
+ case OPT_BOTH(PV_KP): return *curbuf->b_p_kp != NUL
+ ? (char_u *)&curbuf->b_p_kp : p->var;
+ case OPT_BOTH(PV_PATH): return *curbuf->b_p_path != NUL
+ ? (char_u *)&(curbuf->b_p_path) : p->var;
+ case OPT_BOTH(PV_AR): return curbuf->b_p_ar >= 0
+ ? (char_u *)&(curbuf->b_p_ar) : p->var;
+ case OPT_BOTH(PV_TAGS): return *curbuf->b_p_tags != NUL
+ ? (char_u *)&(curbuf->b_p_tags) : p->var;
+#ifdef FEAT_FIND_ID
+ case OPT_BOTH(PV_DEF): return *curbuf->b_p_def != NUL
+ ? (char_u *)&(curbuf->b_p_def) : p->var;
+ case OPT_BOTH(PV_INC): return *curbuf->b_p_inc != NUL
+ ? (char_u *)&(curbuf->b_p_inc) : p->var;
+#endif
+#ifdef FEAT_INS_EXPAND
+ case OPT_BOTH(PV_DICT): return *curbuf->b_p_dict != NUL
+ ? (char_u *)&(curbuf->b_p_dict) : p->var;
+ case OPT_BOTH(PV_TSR): return *curbuf->b_p_tsr != NUL
+ ? (char_u *)&(curbuf->b_p_tsr) : p->var;
+#endif
+#ifdef FEAT_QUICKFIX
+ case OPT_BOTH(PV_GP): return *curbuf->b_p_gp != NUL
+ ? (char_u *)&(curbuf->b_p_gp) : p->var;
+ case OPT_BOTH(PV_MP): return *curbuf->b_p_mp != NUL
+ ? (char_u *)&(curbuf->b_p_mp) : p->var;
+ case OPT_BOTH(PV_EFM): return *curbuf->b_p_efm != NUL
+ ? (char_u *)&(curbuf->b_p_efm) : p->var;
+#endif
+
+#ifdef FEAT_ARABIC
+ case PV_ARAB: return (char_u *)&(curwin->w_p_arab);
+#endif
+ case PV_LIST: return (char_u *)&(curwin->w_p_list);
+#ifdef FEAT_DIFF
+ case PV_DIFF: return (char_u *)&(curwin->w_p_diff);
+#endif
+#ifdef FEAT_FOLDING
+ case PV_FDC: return (char_u *)&(curwin->w_p_fdc);
+ case PV_FEN: return (char_u *)&(curwin->w_p_fen);
+ case PV_FDI: return (char_u *)&(curwin->w_p_fdi);
+ case PV_FDL: return (char_u *)&(curwin->w_p_fdl);
+ case PV_FDM: return (char_u *)&(curwin->w_p_fdm);
+ case PV_FML: return (char_u *)&(curwin->w_p_fml);
+ case PV_FDN: return (char_u *)&(curwin->w_p_fdn);
+# ifdef FEAT_EVAL
+ case PV_FDE: return (char_u *)&(curwin->w_p_fde);
+ case PV_FDT: return (char_u *)&(curwin->w_p_fdt);
+# endif
+ case PV_FMR: return (char_u *)&(curwin->w_p_fmr);
+#endif
+ case PV_NU: return (char_u *)&(curwin->w_p_nu);
+#if defined(FEAT_WINDOWS)
+ case PV_WFH: return (char_u *)&(curwin->w_p_wfh);
+#endif
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ case PV_PVW: return (char_u *)&(curwin->w_p_pvw);
+#endif
+#ifdef FEAT_RIGHTLEFT
+ case PV_RL: return (char_u *)&(curwin->w_p_rl);
+ case PV_RLC: return (char_u *)&(curwin->w_p_rlc);
+#endif
+ case PV_SCROLL: return (char_u *)&(curwin->w_p_scr);
+ case PV_WRAP: return (char_u *)&(curwin->w_p_wrap);
+#ifdef FEAT_LINEBREAK
+ case PV_LBR: return (char_u *)&(curwin->w_p_lbr);
+#endif
+#ifdef FEAT_SCROLLBIND
+ case PV_SCBIND: return (char_u *)&(curwin->w_p_scb);
+#endif
+
+ case PV_AI: return (char_u *)&(curbuf->b_p_ai);
+ case PV_BIN: return (char_u *)&(curbuf->b_p_bin);
+#ifdef FEAT_MBYTE
+ case PV_BOMB: return (char_u *)&(curbuf->b_p_bomb);
+#endif
+#if defined(FEAT_QUICKFIX)
+ case PV_BH: return (char_u *)&(curbuf->b_p_bh);
+ case PV_BT: return (char_u *)&(curbuf->b_p_bt);
+#endif
+ case PV_BL: return (char_u *)&(curbuf->b_p_bl);
+ case PV_CI: return (char_u *)&(curbuf->b_p_ci);
+#ifdef FEAT_CINDENT
+ case PV_CIN: return (char_u *)&(curbuf->b_p_cin);
+ case PV_CINK: return (char_u *)&(curbuf->b_p_cink);
+ case PV_CINO: return (char_u *)&(curbuf->b_p_cino);
+#endif
+#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
+ case PV_CINW: return (char_u *)&(curbuf->b_p_cinw);
+#endif
+#ifdef FEAT_COMMENTS
+ case PV_COM: return (char_u *)&(curbuf->b_p_com);
+#endif
+#ifdef FEAT_FOLDING
+ case PV_CMS: return (char_u *)&(curbuf->b_p_cms);
+#endif
+#ifdef FEAT_INS_EXPAND
+ case PV_CPT: return (char_u *)&(curbuf->b_p_cpt);
+#endif
+ case PV_EOL: return (char_u *)&(curbuf->b_p_eol);
+ case PV_ET: return (char_u *)&(curbuf->b_p_et);
+#ifdef FEAT_MBYTE
+ case PV_FENC: return (char_u *)&(curbuf->b_p_fenc);
+#endif
+ case PV_FF: return (char_u *)&(curbuf->b_p_ff);
+#ifdef FEAT_AUTOCMD
+ case PV_FT: return (char_u *)&(curbuf->b_p_ft);
+#endif
+ case PV_FO: return (char_u *)&(curbuf->b_p_fo);
+ case PV_IMI: return (char_u *)&(curbuf->b_p_iminsert);
+ case PV_IMS: return (char_u *)&(curbuf->b_p_imsearch);
+ case PV_INF: return (char_u *)&(curbuf->b_p_inf);
+ case PV_ISK: return (char_u *)&(curbuf->b_p_isk);
+#ifdef FEAT_FIND_ID
+# ifdef FEAT_EVAL
+ case PV_INEX: return (char_u *)&(curbuf->b_p_inex);
+# endif
+#endif
+#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
+ case PV_INDE: return (char_u *)&(curbuf->b_p_inde);
+ case PV_INDK: return (char_u *)&(curbuf->b_p_indk);
+#endif
+#ifdef FEAT_CRYPT
+ case PV_KEY: return (char_u *)&(curbuf->b_p_key);
+#endif
+#ifdef FEAT_LISP
+ case PV_LISP: return (char_u *)&(curbuf->b_p_lisp);
+#endif
+ case PV_ML: return (char_u *)&(curbuf->b_p_ml);
+ case PV_MPS: return (char_u *)&(curbuf->b_p_mps);
+ case PV_MA: return (char_u *)&(curbuf->b_p_ma);
+ case PV_MOD: return (char_u *)&(curbuf->b_changed);
+ case PV_NF: return (char_u *)&(curbuf->b_p_nf);
+#ifdef FEAT_OSFILETYPE
+ case PV_OFT: return (char_u *)&(curbuf->b_p_oft);
+#endif
+ case PV_PI: return (char_u *)&(curbuf->b_p_pi);
+ case PV_RO: return (char_u *)&(curbuf->b_p_ro);
+#ifdef FEAT_SMARTINDENT
+ case PV_SI: return (char_u *)&(curbuf->b_p_si);
+#endif
+#ifndef SHORT_FNAME
+ case PV_SN: return (char_u *)&(curbuf->b_p_sn);
+#endif
+ case PV_STS: return (char_u *)&(curbuf->b_p_sts);
+#ifdef FEAT_SEARCHPATH
+ case PV_SUA: return (char_u *)&(curbuf->b_p_sua);
+#endif
+ case PV_SWF: return (char_u *)&(curbuf->b_p_swf);
+#ifdef FEAT_SYN_HL
+ case PV_SYN: return (char_u *)&(curbuf->b_p_syn);
+#endif
+ case PV_SW: return (char_u *)&(curbuf->b_p_sw);
+ case PV_TS: return (char_u *)&(curbuf->b_p_ts);
+ case PV_TW: return (char_u *)&(curbuf->b_p_tw);
+ case PV_TX: return (char_u *)&(curbuf->b_p_tx);
+ case PV_WM: return (char_u *)&(curbuf->b_p_wm);
+#ifdef FEAT_KEYMAP
+ case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap);
+#endif
+ default: EMSG(_("E356: get_varp ERROR"));
+ }
+ /* always return a valid pointer to avoid a crash! */
+ return (char_u *)&(curbuf->b_p_wm);
+}
+
+/*
+ * Get the value of 'equalprg', either the buffer-local one or the global one.
+ */
+ char_u *
+get_equalprg()
+{
+ if (*curbuf->b_p_ep == NUL)
+ return p_ep;
+ return curbuf->b_p_ep;
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * Copy options from one window to another.
+ * Used when splitting a window.
+ */
+ void
+win_copy_options(wp_from, wp_to)
+ win_T *wp_from;
+ win_T *wp_to;
+{
+ copy_winopt(&wp_from->w_onebuf_opt, &wp_to->w_onebuf_opt);
+ copy_winopt(&wp_from->w_allbuf_opt, &wp_to->w_allbuf_opt);
+# ifdef FEAT_RIGHTLEFT
+# ifdef FEAT_FKMAP
+ /* Is this right? */
+ wp_to->w_farsi = wp_from->w_farsi;
+# endif
+# endif
+}
+#endif
+
+/*
+ * Copy the options from one winopt_T to another.
+ * Doesn't free the old option values in "to", use clear_winopt() for that.
+ * The 'scroll' option is not copied, because it depends on the window height.
+ * The 'previewwindow' option is reset, there can be only one preview window.
+ */
+ void
+copy_winopt(from, to)
+ winopt_T *from;
+ winopt_T *to;
+{
+#ifdef FEAT_ARABIC
+ to->wo_arab = from->wo_arab;
+#endif
+ to->wo_list = from->wo_list;
+ to->wo_nu = from->wo_nu;
+#ifdef FEAT_RIGHTLEFT
+ to->wo_rl = from->wo_rl;
+ to->wo_rlc = vim_strsave(from->wo_rlc);
+#endif
+ to->wo_wrap = from->wo_wrap;
+#ifdef FEAT_LINEBREAK
+ to->wo_lbr = from->wo_lbr;
+#endif
+#ifdef FEAT_SCROLLBIND
+ to->wo_scb = from->wo_scb;
+#endif
+#ifdef FEAT_DIFF
+ to->wo_diff = from->wo_diff;
+#endif
+#ifdef FEAT_FOLDING
+ to->wo_fdc = from->wo_fdc;
+ to->wo_fen = from->wo_fen;
+ to->wo_fdi = vim_strsave(from->wo_fdi);
+ to->wo_fml = from->wo_fml;
+ to->wo_fdl = from->wo_fdl;
+ to->wo_fdm = vim_strsave(from->wo_fdm);
+ to->wo_fdn = from->wo_fdn;
+# ifdef FEAT_EVAL
+ to->wo_fde = vim_strsave(from->wo_fde);
+ to->wo_fdt = vim_strsave(from->wo_fdt);
+# endif
+ to->wo_fmr = vim_strsave(from->wo_fmr);
+#endif
+ check_winopt(to); /* don't want NULL pointers */
+}
+
+/*
+ * Check string options in a window for a NULL value.
+ */
+ void
+check_win_options(win)
+ win_T *win;
+{
+ check_winopt(&win->w_onebuf_opt);
+ check_winopt(&win->w_allbuf_opt);
+}
+
+/*
+ * Check for NULL pointers in a winopt_T and replace them with empty_option.
+ */
+/*ARGSUSED*/
+ void
+check_winopt(wop)
+ winopt_T *wop;
+{
+#ifdef FEAT_FOLDING
+ check_string_option(&wop->wo_fdi);
+ check_string_option(&wop->wo_fdm);
+# ifdef FEAT_EVAL
+ check_string_option(&wop->wo_fde);
+ check_string_option(&wop->wo_fdt);
+# endif
+ check_string_option(&wop->wo_fmr);
+#endif
+#ifdef FEAT_RIGHTLEFT
+ check_string_option(&wop->wo_rlc);
+#endif
+}
+
+/*
+ * Free the allocated memory inside a winopt_T.
+ */
+/*ARGSUSED*/
+ void
+clear_winopt(wop)
+ winopt_T *wop;
+{
+#ifdef FEAT_FOLDING
+ clear_string_option(&wop->wo_fdi);
+ clear_string_option(&wop->wo_fdm);
+# ifdef FEAT_EVAL
+ clear_string_option(&wop->wo_fde);
+ clear_string_option(&wop->wo_fdt);
+# endif
+ clear_string_option(&wop->wo_fmr);
+#endif
+#ifdef FEAT_RIGHTLEFT
+ clear_string_option(&wop->wo_rlc);
+#endif
+}
+
+/*
+ * Copy global option values to local options for one buffer.
+ * Used when creating a new buffer and sometimes when entering a buffer.
+ * flags:
+ * BCO_ENTER We will enter the buf buffer.
+ * BCO_ALWAYS Always copy the options, but only set b_p_initialized when
+ * appropriate.
+ * BCO_NOHELP Don't copy the values to a help buffer.
+ */
+ void
+buf_copy_options(buf, flags)
+ buf_T *buf;
+ int flags;
+{
+ int should_copy = TRUE;
+ char_u *save_p_isk = NULL; /* init for GCC */
+ int dont_do_help;
+ int did_isk = FALSE;
+
+ /*
+ * Don't do anything of the buffer is invalid.
+ */
+ if (buf == NULL || !buf_valid(buf))
+ return;
+
+ /*
+ * Skip this when the option defaults have not been set yet. Happens when
+ * main() allocates the first buffer.
+ */
+ if (p_cpo != NULL)
+ {
+ /*
+ * Always copy when entering and 'cpo' contains 'S'.
+ * Don't copy when already initialized.
+ * Don't copy when 'cpo' contains 's' and not entering.
+ * 'S' BCO_ENTER initialized 's' should_copy
+ * yes yes X X TRUE
+ * yes no yes X FALSE
+ * no X yes X FALSE
+ * X no no yes FALSE
+ * X no no no TRUE
+ * no yes no X TRUE
+ */
+ if ((vim_strchr(p_cpo, CPO_BUFOPTGLOB) == NULL || !(flags & BCO_ENTER))
+ && (buf->b_p_initialized
+ || (!(flags & BCO_ENTER)
+ && vim_strchr(p_cpo, CPO_BUFOPT) != NULL)))
+ should_copy = FALSE;
+
+ if (should_copy || (flags & BCO_ALWAYS))
+ {
+ /* Don't copy the options specific to a help buffer when
+ * BCO_NOHELP is given or the options were initialized already
+ * (jumping back to a help file with CTRL-T or CTRL-O) */
+ dont_do_help = ((flags & BCO_NOHELP) && buf->b_help)
+ || buf->b_p_initialized;
+ if (dont_do_help) /* don't free b_p_isk */
+ {
+ save_p_isk = buf->b_p_isk;
+ buf->b_p_isk = NULL;
+ }
+ /*
+ * Always free the allocated strings.
+ * If not already initialized, set 'readonly' and copy 'fileformat'.
+ */
+ if (!buf->b_p_initialized)
+ {
+ free_buf_options(buf, TRUE);
+ buf->b_p_ro = FALSE; /* don't copy readonly */
+ buf->b_p_tx = p_tx;
+#ifdef FEAT_MBYTE
+ buf->b_p_fenc = vim_strsave(p_fenc);
+#endif
+ buf->b_p_ff = vim_strsave(p_ff);
+#if defined(FEAT_QUICKFIX)
+ buf->b_p_bh = empty_option;
+ buf->b_p_bt = empty_option;
+#endif
+ }
+ else
+ free_buf_options(buf, FALSE);
+
+ buf->b_p_ai = p_ai;
+ buf->b_p_ai_nopaste = p_ai_nopaste;
+ buf->b_p_sw = p_sw;
+ buf->b_p_tw = p_tw;
+ buf->b_p_tw_nopaste = p_tw_nopaste;
+ buf->b_p_tw_nobin = p_tw_nobin;
+ buf->b_p_wm = p_wm;
+ buf->b_p_wm_nopaste = p_wm_nopaste;
+ buf->b_p_wm_nobin = p_wm_nobin;
+ buf->b_p_bin = p_bin;
+ buf->b_p_et = p_et;
+ buf->b_p_et_nobin = p_et_nobin;
+ buf->b_p_ml = p_ml;
+ buf->b_p_ml_nobin = p_ml_nobin;
+ buf->b_p_inf = p_inf;
+ buf->b_p_swf = p_swf;
+#ifdef FEAT_INS_EXPAND
+ buf->b_p_cpt = vim_strsave(p_cpt);
+#endif
+ buf->b_p_sts = p_sts;
+ buf->b_p_sts_nopaste = p_sts_nopaste;
+#ifndef SHORT_FNAME
+ buf->b_p_sn = p_sn;
+#endif
+#ifdef FEAT_COMMENTS
+ buf->b_p_com = vim_strsave(p_com);
+#endif
+#ifdef FEAT_FOLDING
+ buf->b_p_cms = vim_strsave(p_cms);
+#endif
+ buf->b_p_fo = vim_strsave(p_fo);
+ buf->b_p_nf = vim_strsave(p_nf);
+ buf->b_p_mps = vim_strsave(p_mps);
+#ifdef FEAT_SMARTINDENT
+ buf->b_p_si = p_si;
+#endif
+ buf->b_p_ci = p_ci;
+#ifdef FEAT_CINDENT
+ buf->b_p_cin = p_cin;
+ buf->b_p_cink = vim_strsave(p_cink);
+ buf->b_p_cino = vim_strsave(p_cino);
+#endif
+#ifdef FEAT_AUTOCMD
+ /* Don't copy 'filetype', it must be detected */
+ buf->b_p_ft = empty_option;
+#endif
+#ifdef FEAT_OSFILETYPE
+ buf->b_p_oft = vim_strsave(p_oft);
+#endif
+ buf->b_p_pi = p_pi;
+#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
+ buf->b_p_cinw = vim_strsave(p_cinw);
+#endif
+#ifdef FEAT_LISP
+ buf->b_p_lisp = p_lisp;
+#endif
+#ifdef FEAT_SYN_HL
+ /* Don't copy 'syntax', it must be set */
+ buf->b_p_syn = empty_option;
+#endif
+#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
+ buf->b_p_inde = vim_strsave(p_inde);
+ buf->b_p_indk = vim_strsave(p_indk);
+#endif
+#ifdef FEAT_CRYPT
+ buf->b_p_key = vim_strsave(p_key);
+#endif
+#ifdef FEAT_SEARCHPATH
+ buf->b_p_sua = vim_strsave(p_sua);
+#endif
+#ifdef FEAT_KEYMAP
+ buf->b_p_keymap = vim_strsave(p_keymap);
+ buf->b_kmap_state |= KEYMAP_INIT;
+#endif
+ /* This isn't really an option, but copying the langmap and IME
+ * state from the current buffer is better than resetting it. */
+ buf->b_p_iminsert = p_iminsert;
+ buf->b_p_imsearch = p_imsearch;
+
+ /* options that are normally global but also have a local value
+ * are not copied, start using the global value */
+ buf->b_p_ar = -1;
+#ifdef FEAT_QUICKFIX
+ buf->b_p_gp = empty_option;
+ buf->b_p_mp = empty_option;
+ buf->b_p_efm = empty_option;
+#endif
+ buf->b_p_ep = empty_option;
+ buf->b_p_kp = empty_option;
+ buf->b_p_path = empty_option;
+ buf->b_p_tags = empty_option;
+#ifdef FEAT_FIND_ID
+ buf->b_p_def = empty_option;
+ buf->b_p_inc = empty_option;
+# ifdef FEAT_EVAL
+ buf->b_p_inex = vim_strsave(p_inex);
+# endif
+#endif
+#ifdef FEAT_INS_EXPAND
+ buf->b_p_dict = empty_option;
+ buf->b_p_tsr = empty_option;
+#endif
+
+ /*
+ * Don't copy the options set by ex_help(), use the saved values,
+ * when going from a help buffer to a non-help buffer.
+ * Don't touch these at all when BCO_NOHELP is used and going from
+ * or to a help buffer.
+ */
+ if (dont_do_help)
+ buf->b_p_isk = save_p_isk;
+ else
+ {
+ buf->b_p_isk = vim_strsave(p_isk);
+ did_isk = TRUE;
+ buf->b_p_ts = p_ts;
+ buf->b_help = FALSE;
+#ifdef FEAT_QUICKFIX
+ if (buf->b_p_bt[0] == 'h')
+ clear_string_option(&buf->b_p_bt);
+#endif
+ buf->b_p_ma = p_ma;
+ }
+ }
+
+ /*
+ * When the options should be copied (ignoring BCO_ALWAYS), set the
+ * flag that indicates that the options have been initialized.
+ */
+ if (should_copy)
+ buf->b_p_initialized = TRUE;
+ }
+
+ check_buf_options(buf); /* make sure we don't have NULLs */
+ if (did_isk)
+ (void)buf_init_chartab(buf, FALSE);
+}
+
+/*
+ * Reset the 'modifiable' option and its default value.
+ */
+ void
+reset_modifiable()
+{
+ int opt_idx;
+
+ curbuf->b_p_ma = FALSE;
+ p_ma = FALSE;
+ opt_idx = findoption((char_u *)"ma");
+ options[opt_idx].def_val[VI_DEFAULT] = FALSE;
+}
+
+/*
+ * Set the global value for 'iminsert' to the local value.
+ */
+ void
+set_iminsert_global()
+{
+ p_iminsert = curbuf->b_p_iminsert;
+}
+
+/*
+ * Set the global value for 'imsearch' to the local value.
+ */
+ void
+set_imsearch_global()
+{
+ p_imsearch = curbuf->b_p_imsearch;
+}
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+static int expand_option_idx = -1;
+static char_u expand_option_name[5] = {'t', '_', NUL, NUL, NUL};
+static int expand_option_flags = 0;
+
+ void
+set_context_in_set_cmd(xp, arg, opt_flags)
+ expand_T *xp;
+ char_u *arg;
+ int opt_flags; /* OPT_GLOBAL and/or OPT_LOCAL */
+{
+ int nextchar;
+ long_u flags = 0; /* init for GCC */
+ int opt_idx = 0; /* init for GCC */
+ char_u *p;
+ char_u *s;
+ int is_term_option = FALSE;
+ int key;
+
+ expand_option_flags = opt_flags;
+
+ xp->xp_context = EXPAND_SETTINGS;
+ if (*arg == NUL)
+ {
+ xp->xp_pattern = arg;
+ return;
+ }
+ p = arg + STRLEN(arg) - 1;
+ if (*p == ' ' && *(p - 1) != '\\')
+ {
+ xp->xp_pattern = p + 1;
+ return;
+ }
+ while (p > arg)
+ {
+ s = p;
+ /* count number of backslashes before ' ' or ',' */
+ if (*p == ' ' || *p == ',')
+ {
+ while (s > arg && *(s - 1) == '\\')
+ --s;
+ }
+ /* break at a space with an even number of backslashes */
+ if (*p == ' ' && ((p - s) & 1) == 0)
+ {
+ ++p;
+ break;
+ }
+ --p;
+ }
+ if (STRNCMP(p, "no", 2) == 0)
+ {
+ xp->xp_context = EXPAND_BOOL_SETTINGS;
+ p += 2;
+ }
+ if (STRNCMP(p, "inv", 3) == 0)
+ {
+ xp->xp_context = EXPAND_BOOL_SETTINGS;
+ p += 3;
+ }
+ xp->xp_pattern = arg = p;
+ if (*arg == '<')
+ {
+ while (*p != '>')
+ if (*p++ == NUL) /* expand terminal option name */
+ return;
+ key = get_special_key_code(arg + 1);
+ if (key == 0) /* unknown name */
+ {
+ xp->xp_context = EXPAND_NOTHING;
+ return;
+ }
+ nextchar = *++p;
+ is_term_option = TRUE;
+ expand_option_name[2] = KEY2TERMCAP0(key);
+ expand_option_name[3] = KEY2TERMCAP1(key);
+ }
+ else
+ {
+ if (p[0] == 't' && p[1] == '_')
+ {
+ p += 2;
+ if (*p != NUL)
+ ++p;
+ if (*p == NUL)
+ return; /* expand option name */
+ nextchar = *++p;
+ is_term_option = TRUE;
+ expand_option_name[2] = p[-2];
+ expand_option_name[3] = p[-1];
+ }
+ else
+ {
+ /* Allow * wildcard */
+ while (ASCII_ISALNUM(*p) || *p == '_' || *p == '*')
+ p++;
+ if (*p == NUL)
+ return;
+ nextchar = *p;
+ *p = NUL;
+ opt_idx = findoption(arg);
+ *p = nextchar;
+ if (opt_idx == -1 || options[opt_idx].var == NULL)
+ {
+ xp->xp_context = EXPAND_NOTHING;
+ return;
+ }
+ flags = options[opt_idx].flags;
+ if (flags & P_BOOL)
+ {
+ xp->xp_context = EXPAND_NOTHING;
+ return;
+ }
+ }
+ }
+ /* handle "-=" and "+=" */
+ if ((nextchar == '-' || nextchar == '+' || nextchar == '^') && p[1] == '=')
+ {
+ ++p;
+ nextchar = '=';
+ }
+ if ((nextchar != '=' && nextchar != ':')
+ || xp->xp_context == EXPAND_BOOL_SETTINGS)
+ {
+ xp->xp_context = EXPAND_UNSUCCESSFUL;
+ return;
+ }
+ if (xp->xp_context != EXPAND_BOOL_SETTINGS && p[1] == NUL)
+ {
+ xp->xp_context = EXPAND_OLD_SETTING;
+ if (is_term_option)
+ expand_option_idx = -1;
+ else
+ expand_option_idx = opt_idx;
+ xp->xp_pattern = p + 1;
+ return;
+ }
+ xp->xp_context = EXPAND_NOTHING;
+ if (is_term_option || (flags & P_NUM))
+ return;
+
+ xp->xp_pattern = p + 1;
+
+ if (flags & P_EXPAND)
+ {
+ p = options[opt_idx].var;
+ if (p == (char_u *)&p_bdir
+ || p == (char_u *)&p_dir
+ || p == (char_u *)&p_path
+ || p == (char_u *)&p_rtp
+#ifdef FEAT_SEARCHPATH
+ || p == (char_u *)&p_cdpath
+#endif
+#ifdef FEAT_SESSION
+ || p == (char_u *)&p_vdir
+#endif
+ )
+ {
+ xp->xp_context = EXPAND_DIRECTORIES;
+ if (p == (char_u *)&p_path
+#ifdef FEAT_SEARCHPATH
+ || p == (char_u *)&p_cdpath
+#endif
+ )
+ xp->xp_backslash = XP_BS_THREE;
+ else
+ xp->xp_backslash = XP_BS_ONE;
+ }
+ else
+ {
+ xp->xp_context = EXPAND_FILES;
+ /* for 'tags' need three backslashes for a space */
+ if (p == (char_u *)&p_tags)
+ xp->xp_backslash = XP_BS_THREE;
+ else
+ xp->xp_backslash = XP_BS_ONE;
+ }
+ }
+
+ /* For an option that is a list of file names, find the start of the
+ * last file name. */
+ for (p = arg + STRLEN(arg) - 1; p > xp->xp_pattern; --p)
+ {
+ /* count number of backslashes before ' ' or ',' */
+ if (*p == ' ' || *p == ',')
+ {
+ s = p;
+ while (s > xp->xp_pattern && *(s - 1) == '\\')
+ --s;
+ if ((*p == ' ' && (xp->xp_backslash == XP_BS_THREE && (p - s) < 3))
+ || (*p == ',' && (flags & P_COMMA) && ((p - s) & 1) == 0))
+ {
+ xp->xp_pattern = p + 1;
+ break;
+ }
+ }
+ }
+
+ return;
+}
+
+ int
+ExpandSettings(xp, regmatch, num_file, file)
+ expand_T *xp;
+ regmatch_T *regmatch;
+ int *num_file;
+ char_u ***file;
+{
+ int num_normal = 0; /* Nr of matching non-term-code settings */
+ int num_term = 0; /* Nr of matching terminal code settings */
+ int opt_idx;
+ int match;
+ int count = 0;
+ char_u *str;
+ int loop;
+ int is_term_opt;
+ char_u name_buf[MAX_KEY_NAME_LEN];
+ static char *(names[]) = {"all", "termcap"};
+ int ic = regmatch->rm_ic; /* remember the ignore-case flag */
+
+ /* do this loop twice:
+ * loop == 0: count the number of matching options
+ * loop == 1: copy the matching options into allocated memory
+ */
+ for (loop = 0; loop <= 1; ++loop)
+ {
+ regmatch->rm_ic = ic;
+ if (xp->xp_context != EXPAND_BOOL_SETTINGS)
+ {
+ for (match = 0; match < sizeof(names) / sizeof(char *); ++match)
+ if (vim_regexec(regmatch, (char_u *)names[match], (colnr_T)0))
+ {
+ if (loop == 0)
+ num_normal++;
+ else
+ (*file)[count++] = vim_strsave((char_u *)names[match]);
+ }
+ }
+ for (opt_idx = 0; (str = (char_u *)options[opt_idx].fullname) != NULL;
+ opt_idx++)
+ {
+ if (options[opt_idx].var == NULL)
+ continue;
+ if (xp->xp_context == EXPAND_BOOL_SETTINGS
+ && !(options[opt_idx].flags & P_BOOL))
+ continue;
+ is_term_opt = istermoption(&options[opt_idx]);
+ if (is_term_opt && num_normal > 0)
+ continue;
+ match = FALSE;
+ if (vim_regexec(regmatch, str, (colnr_T)0)
+ || (options[opt_idx].shortname != NULL
+ && vim_regexec(regmatch,
+ (char_u *)options[opt_idx].shortname, (colnr_T)0)))
+ match = TRUE;
+ else if (is_term_opt)
+ {
+ name_buf[0] = '<';
+ name_buf[1] = 't';
+ name_buf[2] = '_';
+ name_buf[3] = str[2];
+ name_buf[4] = str[3];
+ name_buf[5] = '>';
+ name_buf[6] = NUL;
+ if (vim_regexec(regmatch, name_buf, (colnr_T)0))
+ {
+ match = TRUE;
+ str = name_buf;
+ }
+ }
+ if (match)
+ {
+ if (loop == 0)
+ {
+ if (is_term_opt)
+ num_term++;
+ else
+ num_normal++;
+ }
+ else
+ (*file)[count++] = vim_strsave(str);
+ }
+ }
+ /*
+ * Check terminal key codes, these are not in the option table
+ */
+ if (xp->xp_context != EXPAND_BOOL_SETTINGS && num_normal == 0)
+ {
+ for (opt_idx = 0; (str = get_termcode(opt_idx)) != NULL; opt_idx++)
+ {
+ if (!isprint(str[0]) || !isprint(str[1]))
+ continue;
+
+ name_buf[0] = 't';
+ name_buf[1] = '_';
+ name_buf[2] = str[0];
+ name_buf[3] = str[1];
+ name_buf[4] = NUL;
+
+ match = FALSE;
+ if (vim_regexec(regmatch, name_buf, (colnr_T)0))
+ match = TRUE;
+ else
+ {
+ name_buf[0] = '<';
+ name_buf[1] = 't';
+ name_buf[2] = '_';
+ name_buf[3] = str[0];
+ name_buf[4] = str[1];
+ name_buf[5] = '>';
+ name_buf[6] = NUL;
+
+ if (vim_regexec(regmatch, name_buf, (colnr_T)0))
+ match = TRUE;
+ }
+ if (match)
+ {
+ if (loop == 0)
+ num_term++;
+ else
+ (*file)[count++] = vim_strsave(name_buf);
+ }
+ }
+
+ /*
+ * Check special key names.
+ */
+ regmatch->rm_ic = TRUE; /* ignore case here */
+ for (opt_idx = 0; (str = get_key_name(opt_idx)) != NULL; opt_idx++)
+ {
+ name_buf[0] = '<';
+ STRCPY(name_buf + 1, str);
+ STRCAT(name_buf, ">");
+
+ if (vim_regexec(regmatch, name_buf, (colnr_T)0))
+ {
+ if (loop == 0)
+ num_term++;
+ else
+ (*file)[count++] = vim_strsave(name_buf);
+ }
+ }
+ }
+ if (loop == 0)
+ {
+ if (num_normal > 0)
+ *num_file = num_normal;
+ else if (num_term > 0)
+ *num_file = num_term;
+ else
+ return OK;
+ *file = (char_u **)alloc((unsigned)(*num_file * sizeof(char_u *)));
+ if (*file == NULL)
+ {
+ *file = (char_u **)"";
+ return FAIL;
+ }
+ }
+ }
+ return OK;
+}
+
+ int
+ExpandOldSetting(num_file, file)
+ int *num_file;
+ char_u ***file;
+{
+ char_u *var = NULL; /* init for GCC */
+ char_u *buf;
+
+ *num_file = 0;
+ *file = (char_u **)alloc((unsigned)sizeof(char_u *));
+ if (*file == NULL)
+ return FAIL;
+
+ /*
+ * For a terminal key code expand_option_idx is < 0.
+ */
+ if (expand_option_idx < 0)
+ {
+ var = find_termcode(expand_option_name + 2);
+ if (var == NULL)
+ expand_option_idx = findoption(expand_option_name);
+ }
+
+ if (expand_option_idx >= 0)
+ {
+ /* put string of option value in NameBuff */
+ option_value2string(&options[expand_option_idx], expand_option_flags);
+ var = NameBuff;
+ }
+ else if (var == NULL)
+ var = (char_u *)"";
+
+ /* A backslash is required before some characters. This is the reverse of
+ * what happens in do_set(). */
+ buf = vim_strsave_escaped(var, escape_chars);
+
+ if (buf == NULL)
+ {
+ vim_free(*file);
+ *file = NULL;
+ return FAIL;
+ }
+
+#ifdef BACKSLASH_IN_FILENAME
+ /* For MS-Windows et al. we don't double backslashes at the start and
+ * before a file name character. */
+ for (var = buf; *var != NUL; )
+ {
+ if (var[0] == '\\' && var[1] == '\\'
+ && expand_option_idx >= 0
+ && (options[expand_option_idx].flags & P_EXPAND)
+ && vim_isfilec(var[2])
+ && (var[2] != '\\' || (var == buf && var[4] != '\\')))
+ mch_memmove(var, var + 1, STRLEN(var));
+#ifdef FEAT_MBYTE
+ else if (has_mbyte)
+ var += (*mb_ptr2len_check)(var) - 1;
+#endif
+ ++var;
+ }
+#endif
+
+ *file[0] = buf;
+ *num_file = 1;
+ return OK;
+}
+#endif
+
+/*
+ * Get the value for the numeric or string option *opp in a nice format into
+ * NameBuff[]. Must not be called with a hidden option!
+ */
+ static void
+option_value2string(opp, opt_flags)
+ struct vimoption *opp;
+ int opt_flags; /* OPT_GLOBAL and/or OPT_LOCAL */
+{
+ char_u *varp;
+
+ varp = get_varp_scope(opp, opt_flags);
+
+ if (opp->flags & P_NUM)
+ {
+ long wc = 0;
+
+ if (wc_use_keyname(varp, &wc))
+ STRCPY(NameBuff, get_special_key_name((int)wc, 0));
+ else if (wc != 0)
+ STRCPY(NameBuff, transchar((int)wc));
+ else
+ sprintf((char *)NameBuff, "%ld", *(long *)varp);
+ }
+ else /* P_STRING */
+ {
+ varp = *(char_u **)(varp);
+ if (varp == NULL) /* just in case */
+ NameBuff[0] = NUL;
+#ifdef FEAT_CRYPT
+ /* don't show the actual value of 'key', only that it's set */
+ if (opp->var == (char_u *)&p_key && *varp)
+ STRCPY(NameBuff, "*****");
+#endif
+ else if (opp->flags & P_EXPAND)
+ home_replace(NULL, varp, NameBuff, MAXPATHL, FALSE);
+ /* Translate 'pastetoggle' into special key names */
+ else if ((char_u **)opp->var == &p_pt)
+ str2specialbuf(p_pt, NameBuff, MAXPATHL);
+ else
+ STRNCPY(NameBuff, varp, MAXPATHL);
+ }
+}
+
+/*
+ * Return TRUE if "varp" points to 'wildchar' or 'wildcharm' and it can be
+ * printed as a keyname.
+ * "*wcp" is set to the value of the option if it's 'wildchar' or 'wildcharm'.
+ */
+ static int
+wc_use_keyname(varp, wcp)
+ char_u *varp;
+ long *wcp;
+{
+ if (((long *)varp == &p_wc) || ((long *)varp == &p_wcm))
+ {
+ *wcp = *(long *)varp;
+ if (IS_SPECIAL(*wcp) || find_special_key_in_table((int)*wcp) >= 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#ifdef FEAT_LANGMAP
+/*
+ * Any character has an equivalent character. This is used for keyboards that
+ * have a special language mode that sends characters above 128 (although
+ * other characters can be translated too).
+ */
+
+/*
+ * char_u langmap_mapchar[256];
+ * Normally maps each of the 128 upper chars to an <128 ascii char; used to
+ * "translate" native lang chars in normal mode or some cases of
+ * insert mode without having to tediously switch lang mode back&forth.
+ */
+
+ static void
+langmap_init()
+{
+ int i;
+
+ for (i = 0; i < 256; i++) /* we init with a-one-to one map */
+ langmap_mapchar[i] = i;
+}
+
+/*
+ * Called when langmap option is set; the language map can be
+ * changed at any time!
+ */
+ static void
+langmap_set()
+{
+ char_u *p;
+ char_u *p2;
+ int from, to;
+
+ langmap_init(); /* back to one-to-one map first */
+
+ for (p = p_langmap; p[0] != NUL; )
+ {
+ for (p2 = p; p2[0] != NUL && p2[0] != ',' && p2[0] != ';'; ++p2)
+ {
+ if (p2[0] == '\\' && p2[1] != NUL)
+ ++p2;
+#ifdef FEAT_MBYTE
+ p2 += (*mb_ptr2len_check)(p2) - 1;
+#endif
+ }
+ if (p2[0] == ';')
+ ++p2; /* abcd;ABCD form, p2 points to A */
+ else
+ p2 = NULL; /* aAbBcCdD form, p2 is NULL */
+ while (p[0])
+ {
+ if (p[0] == '\\' && p[1] != NUL)
+ ++p;
+#ifdef FEAT_MBYTE
+ from = (*mb_ptr2char)(p);
+#else
+ from = p[0];
+#endif
+ if (p2 == NULL)
+ {
+#ifdef FEAT_MBYTE
+ p += (*mb_ptr2len_check)(p);
+#else
+ ++p;
+#endif
+ if (p[0] == '\\')
+ ++p;
+#ifdef FEAT_MBYTE
+ to = (*mb_ptr2char)(p);
+#else
+ to = p[0];
+#endif
+ }
+ else
+ {
+ if (p2[0] == '\\')
+ ++p2;
+#ifdef FEAT_MBYTE
+ to = (*mb_ptr2char)(p2);
+#else
+ to = p2[0];
+#endif
+ }
+ if (to == NUL)
+ {
+ EMSG2(_("E357: 'langmap': Matching character missing for %s"),
+ transchar(from));
+ return;
+ }
+ langmap_mapchar[from & 255] = to;
+
+ /* Advance to next pair */
+#ifdef FEAT_MBYTE
+ p += (*mb_ptr2len_check)(p);
+#else
+ ++p;
+#endif
+ if (p2 == NULL)
+ {
+ if (p[0] == ',')
+ {
+ ++p;
+ break;
+ }
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ p2 += (*mb_ptr2len_check)(p2);
+#else
+ ++p2;
+#endif
+ if (*p == ';')
+ {
+ p = p2;
+ if (p[0] != NUL)
+ {
+ if (p[0] != ',')
+ {
+ EMSG2(_("E358: 'langmap': Extra characters after semicolon: %s"), p);
+ return;
+ }
+ ++p;
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+#endif
+
+/*
+ * Return TRUE if format option 'x' is in effect.
+ * Take care of no formatting when 'paste' is set.
+ */
+ int
+has_format_option(x)
+ int x;
+{
+ if (p_paste)
+ return FALSE;
+ return (vim_strchr(curbuf->b_p_fo, x) != NULL);
+}
+
+/*
+ * Return TRUE if "x" is present in 'shortmess' option, or
+ * 'shortmess' contains 'a' and "x" is present in SHM_A.
+ */
+ int
+shortmess(x)
+ int x;
+{
+ return ( vim_strchr(p_shm, x) != NULL
+ || (vim_strchr(p_shm, 'a') != NULL
+ && vim_strchr((char_u *)SHM_A, x) != NULL));
+}
+
+/*
+ * paste_option_changed() - Called after p_paste was set or reset.
+ */
+ static void
+paste_option_changed()
+{
+ static int old_p_paste = FALSE;
+ static int save_sm = 0;
+#ifdef FEAT_CMDL_INFO
+ static int save_ru = 0;
+#endif
+#ifdef FEAT_RIGHTLEFT
+ static int save_ri = 0;
+ static int save_hkmap = 0;
+#endif
+ buf_T *buf;
+
+ if (p_paste)
+ {
+ /*
+ * Paste switched from off to on.
+ * Save the current values, so they can be restored later.
+ */
+ if (!old_p_paste)
+ {
+ /* save options for each buffer */
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ buf->b_p_tw_nopaste = buf->b_p_tw;
+ buf->b_p_wm_nopaste = buf->b_p_wm;
+ buf->b_p_sts_nopaste = buf->b_p_sts;
+ buf->b_p_ai_nopaste = buf->b_p_ai;
+ }
+
+ /* save global options */
+ save_sm = p_sm;
+#ifdef FEAT_CMDL_INFO
+ save_ru = p_ru;
+#endif
+#ifdef FEAT_RIGHTLEFT
+ save_ri = p_ri;
+ save_hkmap = p_hkmap;
+#endif
+ /* save global values for local buffer options */
+ p_tw_nopaste = p_tw;
+ p_wm_nopaste = p_wm;
+ p_sts_nopaste = p_sts;
+ p_ai_nopaste = p_ai;
+ }
+
+ /*
+ * Always set the option values, also when 'paste' is set when it is
+ * already on.
+ */
+ /* set options for each buffer */
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ buf->b_p_tw = 0; /* textwidth is 0 */
+ buf->b_p_wm = 0; /* wrapmargin is 0 */
+ buf->b_p_sts = 0; /* softtabstop is 0 */
+ buf->b_p_ai = 0; /* no auto-indent */
+ }
+
+ /* set global options */
+ p_sm = 0; /* no showmatch */
+#ifdef FEAT_CMDL_INFO
+# ifdef FEAT_WINDOWS
+ if (p_ru)
+ status_redraw_all(); /* redraw to remove the ruler */
+# endif
+ p_ru = 0; /* no ruler */
+#endif
+#ifdef FEAT_RIGHTLEFT
+ p_ri = 0; /* no reverse insert */
+ p_hkmap = 0; /* no Hebrew keyboard */
+#endif
+ /* set global values for local buffer options */
+ p_tw = 0;
+ p_wm = 0;
+ p_sts = 0;
+ p_ai = 0;
+ }
+
+ /*
+ * Paste switched from on to off: Restore saved values.
+ */
+ else if (old_p_paste)
+ {
+ /* restore options for each buffer */
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ buf->b_p_tw = buf->b_p_tw_nopaste;
+ buf->b_p_wm = buf->b_p_wm_nopaste;
+ buf->b_p_sts = buf->b_p_sts_nopaste;
+ buf->b_p_ai = buf->b_p_ai_nopaste;
+ }
+
+ /* restore global options */
+ p_sm = save_sm;
+#ifdef FEAT_CMDL_INFO
+# ifdef FEAT_WINDOWS
+ if (p_ru != save_ru)
+ status_redraw_all(); /* redraw to draw the ruler */
+# endif
+ p_ru = save_ru;
+#endif
+#ifdef FEAT_RIGHTLEFT
+ p_ri = save_ri;
+ p_hkmap = save_hkmap;
+#endif
+ /* set global values for local buffer options */
+ p_tw = p_tw_nopaste;
+ p_wm = p_wm_nopaste;
+ p_sts = p_sts_nopaste;
+ p_ai = p_ai_nopaste;
+ }
+
+ old_p_paste = p_paste;
+}
+
+/*
+ * vimrc_found() - Called when a ".vimrc" or "VIMINIT" has been found.
+ *
+ * Reset 'compatible' and set the values for options that didn't get set yet
+ * to the Vim defaults.
+ * Don't do this if the 'compatible' option has been set or reset before.
+ */
+ void
+vimrc_found()
+{
+ int opt_idx;
+
+ if (!option_was_set((char_u *)"cp"))
+ {
+ p_cp = FALSE;
+ for (opt_idx = 0; !istermoption(&options[opt_idx]); opt_idx++)
+ if (!(options[opt_idx].flags & (P_WAS_SET|P_VI_DEF)))
+ set_option_default(opt_idx, OPT_FREE, FALSE);
+ didset_options();
+ }
+}
+
+/*
+ * Set 'compatible' on or off. Called for "-C" and "-N" command line arg.
+ */
+ void
+change_compatible(on)
+ int on;
+{
+ if (p_cp != on)
+ {
+ p_cp = on;
+ compatible_set();
+ }
+ options[findoption((char_u *)"cp")].flags |= P_WAS_SET;
+}
+
+/*
+ * Return TRUE when option "name" has been set.
+ */
+ int
+option_was_set(name)
+ char_u *name;
+{
+ int idx;
+
+ idx = findoption(name);
+ if (idx < 0) /* unknown option */
+ return FALSE;
+ if (options[idx].flags & P_WAS_SET)
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * compatible_set() - Called when 'compatible' has been set or unset.
+ *
+ * When 'compatible' set: Set all relevant options (those that have the P_VIM)
+ * flag) to a Vi compatible value.
+ * When 'compatible' is unset: Set all options that have a different default
+ * for Vim (without the P_VI_DEF flag) to that default.
+ */
+ static void
+compatible_set()
+{
+ int opt_idx;
+
+ for (opt_idx = 0; !istermoption(&options[opt_idx]); opt_idx++)
+ if ( ((options[opt_idx].flags & P_VIM) && p_cp)
+ || (!(options[opt_idx].flags & P_VI_DEF) && !p_cp))
+ set_option_default(opt_idx, OPT_FREE, p_cp);
+ didset_options();
+}
+
+#ifdef FEAT_LINEBREAK
+
+# if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+ /* Borland C++ screws up loop optimisation here (negri) */
+# pragma option -O-l
+# endif
+
+/*
+ * fill_breakat_flags() -- called when 'breakat' changes value.
+ */
+ static void
+fill_breakat_flags()
+{
+ char_u *c;
+ int i;
+
+ for (i = 0; i < 256; i++)
+ breakat_flags[i] = FALSE;
+
+ if (p_breakat != NULL)
+ for (c = p_breakat; *c; c++)
+ breakat_flags[*c] = TRUE;
+}
+
+# if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+# pragma option -O.l
+# endif
+
+#endif
+
+/*
+ * Check an option that can be a range of string values.
+ *
+ * Return OK for correct value, FAIL otherwise.
+ * Empty is always OK.
+ */
+ static int
+check_opt_strings(val, values, list)
+ char_u *val;
+ char **values;
+ int list; /* when TRUE: accept a list of values */
+{
+ return opt_strings_flags(val, values, NULL, list);
+}
+
+/*
+ * Handle an option that can be a range of string values.
+ * Set a flag in "*flagp" for each string present.
+ *
+ * Return OK for correct value, FAIL otherwise.
+ * Empty is always OK.
+ */
+ static int
+opt_strings_flags(val, values, flagp, list)
+ char_u *val; /* new value */
+ char **values; /* array of valid string values */
+ unsigned *flagp;
+ int list; /* when TRUE: accept a list of values */
+{
+ int i;
+ int len;
+ unsigned new_flags = 0;
+
+ while (*val)
+ {
+ for (i = 0; ; ++i)
+ {
+ if (values[i] == NULL) /* val not found in values[] */
+ return FAIL;
+
+ len = (int)STRLEN(values[i]);
+ if (STRNCMP(values[i], val, len) == 0
+ && ((list && val[len] == ',') || val[len] == NUL))
+ {
+ val += len + (val[len] == ',');
+ new_flags |= (1 << i);
+ break; /* check next item in val list */
+ }
+ }
+ }
+ if (flagp != NULL)
+ *flagp = new_flags;
+
+ return OK;
+}
+
+/*
+ * Read the 'wildmode' option, fill wim_flags[].
+ */
+ static int
+check_opt_wim()
+{
+ char_u new_wim_flags[4];
+ char_u *p;
+ int i;
+ int idx = 0;
+
+ for (i = 0; i < 4; ++i)
+ new_wim_flags[i] = 0;
+
+ for (p = p_wim; *p; ++p)
+ {
+ for (i = 0; ASCII_ISALPHA(p[i]); ++i)
+ ;
+ if (p[i] != NUL && p[i] != ',' && p[i] != ':')
+ return FAIL;
+ if (i == 7 && STRNCMP(p, "longest", 7) == 0)
+ new_wim_flags[idx] |= WIM_LONGEST;
+ else if (i == 4 && STRNCMP(p, "full", 4) == 0)
+ new_wim_flags[idx] |= WIM_FULL;
+ else if (i == 4 && STRNCMP(p, "list", 4) == 0)
+ new_wim_flags[idx] |= WIM_LIST;
+ else
+ return FAIL;
+ p += i;
+ if (*p == NUL)
+ break;
+ if (*p == ',')
+ {
+ if (idx == 3)
+ return FAIL;
+ ++idx;
+ }
+ }
+
+ /* fill remaining entries with last flag */
+ while (idx < 3)
+ {
+ new_wim_flags[idx + 1] = new_wim_flags[idx];
+ ++idx;
+ }
+
+ /* only when there are no errors, wim_flags[] is changed */
+ for (i = 0; i < 4; ++i)
+ wim_flags[i] = new_wim_flags[i];
+ return OK;
+}
+
+/*
+ * Check if backspacing over something is allowed.
+ */
+ int
+can_bs(what)
+ int what; /* BS_INDENT, BS_EOL or BS_START */
+{
+ switch (*p_bs)
+ {
+ case '2': return TRUE;
+ case '1': return (what != BS_START);
+ case '0': return FALSE;
+ }
+ return vim_strchr(p_bs, what) != NULL;
+}
+
+/*
+ * Save the current values of 'fileformat' and 'fileencoding', so that we know
+ * the file must be considered changed when the value is different.
+ */
+ void
+save_file_ff(buf)
+ buf_T *buf;
+{
+ buf->b_start_ffc = *buf->b_p_ff;
+ buf->b_start_eol = buf->b_p_eol;
+#ifdef FEAT_MBYTE
+ /* Only use free/alloc when necessary, they take time. */
+ if (buf->b_start_fenc == NULL
+ || STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0)
+ {
+ vim_free(buf->b_start_fenc);
+ buf->b_start_fenc = vim_strsave(buf->b_p_fenc);
+ }
+#endif
+}
+
+/*
+ * Return TRUE if 'fileformat' and/or 'fileencoding' has a different value
+ * from when editing started (save_file_ff() called).
+ * Also when 'endofline' was changed and 'binary' is set.
+ * Don't consider a new, empty buffer to be changed.
+ */
+ int
+file_ff_differs(buf)
+ buf_T *buf;
+{
+ if ((buf->b_flags & BF_NEW)
+ && buf->b_ml.ml_line_count == 1
+ && *ml_get_buf(buf, (linenr_T)1, FALSE) == NUL)
+ return FALSE;
+ if (buf->b_start_ffc != *buf->b_p_ff)
+ return TRUE;
+ if (buf->b_p_bin && buf->b_start_eol != buf->b_p_eol)
+ return TRUE;
+#ifdef FEAT_MBYTE
+ if (buf->b_start_fenc == NULL)
+ return (*buf->b_p_fenc != NUL);
+ return (STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0);
+#else
+ return FALSE;
+#endif
+}
+
+/*
+ * return OK if "p" is a valid fileformat name, FAIL otherwise.
+ */
+ int
+check_ff_value(p)
+ char_u *p;
+{
+ return check_opt_strings(p, p_ff_values, FALSE);
+}
diff --git a/src/option.h b/src/option.h
new file mode 100644
index 000000000..f3985e50e
--- /dev/null
+++ b/src/option.h
@@ -0,0 +1,802 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * option.h: definition of global variables for settable options
+ */
+
+#ifndef EXTERN
+# define EXTERN extern
+# define INIT(x)
+#else
+# ifndef INIT
+# define INIT(x) x
+# endif
+#endif
+
+/* default values for p_efm 'errorformat' */
+#ifdef AMIGA
+# define DFLT_EFM "%f>%l:%c:%t:%n:%m,%f:%l: %t%*\\D%n: %m,%f %l %t%*\\D%n: %m,%*[^\"]\"%f\"%*\\D%l: %m,%f:%l:%m"
+#else
+# if defined(MSDOS) || defined(WIN3264)
+# define DFLT_EFM "%f(%l) : %t%*\\D%n: %m,%*[^\"]\"%f\"%*\\D%l: %m,%f(%l) : %m,%*[^ ] %f %l: %m,%f:%l:%m"
+# else
+# if defined(__EMX__) /* put most common here (i.e. gcc format) at front */
+# define DFLT_EFM "%f:%l:%m,%*[^\"]\"%f\"%*\\D%l: %m,\"%f\"%*\\D%l: %m,%f(%l:%c) : %m"
+# else
+# if defined(__QNX__)
+# define DFLT_EFM "%f(%l):%*[^WE]%t%*\\D%n:%m"
+# else
+# ifdef VMS
+# define DFLT_EFM "%A%p^,%C%%CC-%t-%m,%Cat line number %l in file %f"
+# else /* Unix, probably */
+# ifdef EBCDIC
+#define DFLT_EFM "%*[^ ] %*[^ ] %f:%l%*[ ]%m,%*[^\"]\"%f\"%*\\D%l: %m,\"%f\"%*\\D%l: %m,%f:%l:%m,\"%f\"\\, line %l%*\\D%c%*[^ ] %m,%D%*\\a[%*\\d]: Entering directory `%f',%X%*\\a[%*\\d]: Leaving directory `%f',%DMaking %*\\a in %f"
+# else
+#define DFLT_EFM "%*[^\"]\"%f\"%*\\D%l: %m,\"%f\"%*\\D%l: %m,%-G%f:%l: (Each undeclared identifier is reported only once,%-G%f:%l: for each function it appears in.),%f:%l:%m,\"%f\"\\, line %l%*\\D%c%*[^ ] %m,%D%*\\a[%*\\d]: Entering directory `%f',%X%*\\a[%*\\d]: Leaving directory `%f',%DMaking %*\\a in %f"
+# endif
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#define DFLT_GREPFORMAT "%f:%l:%m,%f:%l%m,%f %l%m"
+
+/* default values for b_p_ff 'fileformat' and p_ffs 'fileformats' */
+#define FF_DOS "dos"
+#define FF_MAC "mac"
+#define FF_UNIX "unix"
+
+#ifdef USE_CRNL
+# define DFLT_FF "dos"
+# define DFLT_FFS_VIM "dos,unix"
+# define DFLT_FFS_VI "dos,unix" /* also autodetect in compatible mode */
+# define DFLT_TEXTAUTO TRUE
+#else
+# ifdef USE_CR
+# define DFLT_FF "mac"
+# define DFLT_FFS_VIM "mac,unix,dos"
+# define DFLT_FFS_VI "mac,unix,dos"
+# define DFLT_TEXTAUTO TRUE
+# else
+# define DFLT_FF "unix"
+# define DFLT_FFS_VIM "unix,dos"
+# ifdef __CYGWIN__
+# define DFLT_FFS_VI "unix,dos" /* Cygwin always needs file detection */
+# define DFLT_TEXTAUTO TRUE
+# else
+# define DFLT_FFS_VI ""
+# define DFLT_TEXTAUTO FALSE
+# endif
+# endif
+#endif
+
+
+#ifdef FEAT_MBYTE
+/* Possible values for 'encoding' */
+# define ENC_UCSBOM "ucs-bom" /* check for BOM at start of file */
+
+/* default value for 'encoding' */
+# define ENC_DFLT "latin1"
+#endif
+
+/* end-of-line style */
+#define EOL_UNKNOWN -1 /* not defined yet */
+#define EOL_UNIX 0 /* NL */
+#define EOL_DOS 1 /* CR NL */
+#define EOL_MAC 2 /* CR */
+
+/* Formatting options for p_fo 'formatoptions' */
+#define FO_WRAP 't'
+#define FO_WRAP_COMS 'c'
+#define FO_RET_COMS 'r'
+#define FO_OPEN_COMS 'o'
+#define FO_Q_COMS 'q'
+#define FO_Q_NUMBER 'n'
+#define FO_Q_SECOND '2'
+#define FO_INS_VI 'v'
+#define FO_INS_LONG 'l'
+#define FO_INS_BLANK 'b'
+#define FO_MBYTE_BREAK 'm' /* break before/after multi-byte char */
+#define FO_MBYTE_JOIN 'M' /* no space before/after multi-byte char */
+#define FO_MBYTE_JOIN2 'B' /* no space between multi-byte chars */
+#define FO_ONE_LETTER '1'
+#define FO_WHITE_PAR 'w' /* trailing white space continues paragr. */
+#define FO_AUTO 'a' /* automatic formatting */
+
+#define DFLT_FO_VI "vt"
+#define DFLT_FO_VIM "tcq"
+#define FO_ALL "tcroq2vlb1mMBn,aw" /* for do_set() */
+
+/* characters for the p_cpo option: */
+#define CPO_ALTREAD 'a' /* ":read" sets alternate file name */
+#define CPO_ALTWRITE 'A' /* ":write" sets alternate file name */
+#define CPO_BAR 'b' /* "\|" ends a mapping */
+#define CPO_BSLASH 'B' /* backslash in mapping is not special */
+#define CPO_SEARCH 'c'
+#define CPO_CONCAT 'C' /* Don't concatenate sourced lines */
+#define CPO_DOTTAG 'd' /* "./tags" in 'tags' is in current dir */
+#define CPO_DIGRAPH 'D' /* No digraph after "r", "f", etc. */
+#define CPO_EXECBUF 'e'
+#define CPO_EMPTYREGION 'E' /* operating on empty region is an error */
+#define CPO_FNAMER 'f' /* set file name for ":r file" */
+#define CPO_FNAMEW 'F' /* set file name for ":w file" */
+#define CPO_GOTO1 'g' /* goto line 1 for ":edit" */
+#define CPO_INTMOD 'i' /* interrupt a read makes buffer modified */
+#define CPO_JOINSP 'j' /* only use two spaces for join after '.' */
+#define CPO_ENDOFSENT 'J' /* need two spaces to detect end of sentence */
+#define CPO_KEYCODE 'k' /* don't recognize raw key code in mappings */
+#define CPO_KOFFSET 'K' /* don't wait for key code in mappings */
+#define CPO_LITERAL 'l' /* take char after backslash in [] literal */
+#define CPO_LISTWM 'L' /* 'list' changes wrapmargin */
+#define CPO_SHOWMATCH 'm'
+#define CPO_MATCHBSL 'M' /* "%" ignores use of backslashes */
+#define CPO_NUMCOL 'n' /* 'number' column also used for text */
+#define CPO_LINEOFF 'o'
+#define CPO_OVERNEW 'O' /* silently overwrite new file */
+#define CPO_LISP 'p' /* 'lisp' indenting */
+#define CPO_REDO 'r'
+#define CPO_REMMARK 'R' /* remove marks when filtering */
+#define CPO_BUFOPT 's'
+#define CPO_BUFOPTGLOB 'S'
+#define CPO_TAGPAT 't'
+#define CPO_UNDO 'u' /* "u" undoes itself */
+#define CPO_BACKSPACE 'v' /* "v" keep deleted text */
+#define CPO_CW 'w' /* "cw" only changes one blank */
+#define CPO_FWRITE 'W' /* "w!" doesn't overwrite readonly files */
+#define CPO_ESC 'x'
+#define CPO_YANK 'y'
+#define CPO_DOLLAR '$'
+#define CPO_FILTER '!'
+#define CPO_MATCH '%'
+#define CPO_STAR '*' /* ":*" means ":@" */
+#define CPO_SPECI '<' /* don't recognize <> in mappings */
+#define CPO_DEFAULT "aABceFs"
+#define CPO_ALL "aAbBcCdDeEfFgijJkKlLmMnoOprRsStuvwWxy$!%*<"
+
+/* characters for p_ww option: */
+#define WW_ALL "bshl<>[],~"
+
+/* characters for p_mouse option: */
+#define MOUSE_NORMAL 'n' /* use mouse in Normal mode */
+#define MOUSE_VISUAL 'v' /* use mouse in Visual/Select mode */
+#define MOUSE_INSERT 'i' /* use mouse in Insert mode */
+#define MOUSE_COMMAND 'c' /* use mouse in Command-line mode */
+#define MOUSE_HELP 'h' /* use mouse in help buffers */
+#define MOUSE_RETURN 'r' /* use mouse for hit-return message */
+#define MOUSE_A "nvich" /* used for 'a' flag */
+#define MOUSE_ALL "anvichr" /* all possible characters */
+#define MOUSE_NONE ' ' /* don't use Visual selection */
+#define MOUSE_NONEF 'x' /* forced modeless selection */
+
+/* characters for p_shm option: */
+#define SHM_RO 'r' /* readonly */
+#define SHM_MOD 'm' /* modified */
+#define SHM_FILE 'f' /* (file 1 of 2) */
+#define SHM_LAST 'i' /* last line incomplete */
+#define SHM_TEXT 'x' /* tx instead of textmode */
+#define SHM_LINES 'l' /* "L" instead of "lines" */
+#define SHM_NEW 'n' /* "[New]" instead of "[New file]" */
+#define SHM_WRI 'w' /* "[w]" instead of "written" */
+#define SHM_A "rmfixlnw" /* represented by 'a' flag */
+#define SHM_WRITE 'W' /* don't use "written" at all */
+#define SHM_TRUNC 't' /* trunctate file messages */
+#define SHM_TRUNCALL 'T' /* trunctate all messages */
+#define SHM_OVER 'o' /* overwrite file messages */
+#define SHM_OVERALL 'O' /* overwrite more messages */
+#define SHM_SEARCH 's' /* no search hit bottom messages */
+#define SHM_ATTENTION 'A' /* no ATTENTION messages */
+#define SHM_INTRO 'I' /* intro messages */
+#define SHM_ALL "rmfixlnwaWtToOsAI" /* all possible flags for 'shm' */
+
+/* characters for p_go: */
+#define GO_ASEL 'a' /* autoselect */
+#define GO_ASELML 'A' /* autoselect modeless selection */
+#define GO_BOT 'b' /* use bottom scrollbar */
+#define GO_CONDIALOG 'c' /* use console dialog */
+#define GO_FORG 'f' /* start GUI in foreground */
+#define GO_GREY 'g' /* use grey menu items */
+#define GO_HORSCROLL 'h' /* flexible horizontal scrolling */
+#define GO_ICON 'i' /* use Vim icon */
+#define GO_LEFT 'l' /* use left scrollbar */
+#define GO_VLEFT 'L' /* left scrollbar with vert split */
+#define GO_MENUS 'm' /* use menu bar */
+#define GO_NOSYSMENU 'M' /* don't source system menu */
+#define GO_POINTER 'p' /* pointer enter/leave callbacks */
+#define GO_RIGHT 'r' /* use right scrollbar */
+#define GO_VRIGHT 'R' /* right scrollbar with vert split */
+#define GO_TEAROFF 't' /* add tear-off menu items */
+#define GO_TOOLBAR 'T' /* add toolbar */
+#define GO_FOOTER 'F' /* add footer */
+#define GO_VERTICAL 'v' /* arrange dialog buttons vertically */
+#define GO_ALL "aAbcfFghilmMprtTv" /* all possible flags for 'go' */
+
+/* flags for 'comments' option */
+#define COM_NEST 'n' /* comments strings nest */
+#define COM_BLANK 'b' /* needs blank after string */
+#define COM_START 's' /* start of comment */
+#define COM_MIDDLE 'm' /* middle of comment */
+#define COM_END 'e' /* end of comment */
+#define COM_AUTO_END 'x' /* last char of end closes comment */
+#define COM_FIRST 'f' /* first line comment only */
+#define COM_LEFT 'l' /* left adjusted */
+#define COM_RIGHT 'r' /* right adjusted */
+#define COM_NOBACK 'O' /* don't use for "O" command */
+#define COM_ALL "nbsmexflrO" /* all flags for 'comments' option */
+#define COM_MAX_LEN 50 /* maximum length of a part */
+
+/* flags for 'statusline' option */
+#define STL_FILEPATH 'f' /* path of file in buffer */
+#define STL_FULLPATH 'F' /* full path of file in buffer */
+#define STL_FILENAME 't' /* last part (tail) of file path */
+#define STL_COLUMN 'c' /* column og cursor*/
+#define STL_VIRTCOL 'v' /* virtual column */
+#define STL_VIRTCOL_ALT 'V' /* - with 'if different' display */
+#define STL_LINE 'l' /* line number of cursor */
+#define STL_NUMLINES 'L' /* number of lines in buffer */
+#define STL_BUFNO 'n' /* current buffer number */
+#define STL_KEYMAP 'k' /* 'keymap' when active */
+#define STL_OFFSET 'o' /* offset of character under cursor*/
+#define STL_OFFSET_X 'O' /* - in hexadecimal */
+#define STL_BYTEVAL 'b' /* byte value of character */
+#define STL_BYTEVAL_X 'B' /* - in hexadecimal */
+#define STL_ROFLAG 'r' /* readonly flag */
+#define STL_ROFLAG_ALT 'R' /* - other display */
+#define STL_HELPFLAG 'h' /* window is showing a help file */
+#define STL_HELPFLAG_ALT 'H' /* - other display */
+#define STL_FILETYPE 'y' /* 'filetype' */
+#define STL_FILETYPE_ALT 'Y' /* - other display */
+#define STL_PREVIEWFLAG 'w' /* window is showing the preview buf */
+#define STL_PREVIEWFLAG_ALT 'W' /* - other display */
+#define STL_MODIFIED 'm' /* modified flag */
+#define STL_MODIFIED_ALT 'M' /* - other display */
+#define STL_PERCENTAGE 'p' /* percentage through file */
+#define STL_ALTPERCENT 'P' /* percentage as TOP BOT ALL or NN% */
+#define STL_ARGLISTSTAT 'a' /* argument list status as (x of y) */
+#define STL_PAGENUM 'N' /* page number (when printing)*/
+#define STL_VIM_EXPR '{' /* start of expression to substitute */
+#define STL_MIDDLEMARK '=' /* separation between left and right */
+#define STL_TRUNCMARK '<' /* truncation mark if line is too long*/
+#define STL_HIGHLIGHT '*' /* highlight from (User)1..9 or 0 */
+#define STL_ALL ((char_u *) "fFtcvVlLknoObBrRhHmYyWwMpPaN{")
+
+/* flags used for parsed 'wildmode' */
+#define WIM_FULL 1
+#define WIM_LONGEST 2
+#define WIM_LIST 4
+
+/* arguments for can_bs() */
+#define BS_INDENT 'i' /* "Indent" */
+#define BS_EOL 'o' /* "eOl" */
+#define BS_START 's' /* "Start" */
+
+#define LISPWORD_VALUE "defun,define,defmacro,set!,lambda,if,case,let,flet,let*,letrec,do,do*,define-syntax,let-syntax,letrec-syntax,destructuring-bind,defpackage,defparameter,defstruct,deftype,defvar,do-all-symbols,do-external-symbols,do-symbols,dolist,dotimes,ecase,etypecase,eval-when,labels,macrolet,multiple-value-bind,multiple-value-call,multiple-value-prog1,multiple-value-setq,prog1,progv,typecase,unless,unwind-protect,when,with-input-from-string,with-open-file,with-open-stream,with-output-to-string,with-package-iterator,define-condition,handler-bind,handler-case,restart-bind,restart-case,with-simple-restart,store-value,use-value,muffle-warning,abort,continue,with-slots,with-slots*,with-accessors,with-accessors*,defclass,defmethod,print-unreadable-object"
+
+/*
+ * The following are actual variabables for the options
+ */
+
+#ifdef FEAT_RIGHTLEFT
+EXTERN long p_aleph; /* 'aleph' */
+#endif
+#if defined(FEAT_NETBEANS_INTG) || defined(FEAT_SUN_WORKSHOP)
+EXTERN int p_acd; /* 'autochdir' */
+#endif
+#ifdef FEAT_MBYTE
+EXTERN char_u *p_ambw; /* 'ambiwidth' */
+#endif
+#if defined(FEAT_GUI) && defined(MACOS_X)
+EXTERN int *p_antialias; /* 'antialias' */
+#endif
+EXTERN int p_ar; /* 'autoread' */
+EXTERN int p_aw; /* 'autowrite' */
+EXTERN int p_awa; /* 'autowriteall' */
+EXTERN char_u *p_bs; /* 'backspace' */
+EXTERN char_u *p_bg; /* 'background' */
+EXTERN int p_bk; /* 'backup' */
+EXTERN char_u *p_bkc; /* 'backupcopy' */
+EXTERN unsigned bkc_flags;
+#ifdef IN_OPTION_C
+static char *(p_bkc_values[]) = {"yes", "auto", "no", "breaksymlink", "breakhardlink", NULL};
+#endif
+# define BKC_YES 0x001
+# define BKC_AUTO 0x002
+# define BKC_NO 0x004
+# define BKC_BREAKSYMLINK 0x008
+# define BKC_BREAKHARDLINK 0x010
+EXTERN char_u *p_bdir; /* 'backupdir' */
+EXTERN char_u *p_bex; /* 'backupext' */
+#ifdef FEAT_WILDIGN
+EXTERN char_u *p_bsk; /* 'backupskip' */
+#endif
+#ifdef FEAT_BEVAL
+EXTERN long p_bdlay; /* 'balloondelay' */
+# if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG)
+EXTERN int p_beval; /* 'ballooneval' */
+# endif
+#endif
+#ifdef FEAT_BROWSE
+EXTERN char_u *p_bsdir; /* 'browsedir' */
+#endif
+#ifdef MSDOS
+EXTERN int p_biosk; /* 'bioskey' */
+EXTERN int p_consk; /* 'conskey' */
+#endif
+#ifdef FEAT_LINEBREAK
+EXTERN char_u *p_breakat; /* 'breakat' */
+#endif
+EXTERN char_u *p_cmp; /* 'casemap' */
+EXTERN unsigned cmp_flags;
+#ifdef IN_OPTION_C
+static char *(p_cmp_values[]) = {"internal", "keepascii", NULL};
+#endif
+#define CMP_INTERNAL 0x001
+#define CMP_KEEPASCII 0x002
+#ifdef FEAT_MBYTE
+EXTERN char_u *p_enc; /* 'encoding' */
+EXTERN int p_deco; /* 'delcombine' */
+# ifdef FEAT_EVAL
+EXTERN char_u *p_ccv; /* 'charconvert' */
+# endif
+#endif
+#ifdef FEAT_CMDWIN
+EXTERN char_u *p_cedit; /* 'cedit' */
+EXTERN long p_cwh; /* 'cmdwinheight' */
+#endif
+#ifdef FEAT_CLIPBOARD
+EXTERN char_u *p_cb; /* 'clipboard' */
+EXTERN int clip_unnamed INIT(= FALSE);
+EXTERN int clip_autoselect INIT(= FALSE);
+EXTERN int clip_autoselectml INIT(= FALSE);
+EXTERN regprog_T *clip_exclude_prog INIT(= NULL);
+#endif
+EXTERN long p_ch; /* 'cmdheight' */
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+EXTERN int p_confirm; /* 'confirm' */
+#endif
+EXTERN int p_cp; /* 'compatible' */
+EXTERN char_u *p_cpo; /* 'cpoptions' */
+#ifdef FEAT_CSCOPE
+EXTERN char_u *p_csprg; /* 'cscopeprg' */
+# ifdef FEAT_QUICKFIX
+EXTERN char_u *p_csqf; /* 'cscopequickfix' */
+# define CSQF_CMDS "sgdctefi"
+# define CSQF_FLAGS "+-0"
+# endif
+EXTERN int p_cst; /* 'cscopetag' */
+EXTERN long p_csto; /* 'cscopetagorder' */
+EXTERN long p_cspc; /* 'cscopepathcomp' */
+EXTERN int p_csverbose; /* 'cscopeverbose' */
+#endif
+EXTERN char_u *p_debug; /* 'debug' */
+#ifdef FEAT_FIND_ID
+EXTERN char_u *p_def; /* 'define' */
+EXTERN char_u *p_inc;
+#endif
+#ifdef FEAT_DIFF
+EXTERN char_u *p_dip; /* 'diffopt' */
+# ifdef FEAT_EVAL
+EXTERN char_u *p_dex; /* 'diffexpr' */
+# endif
+#endif
+#ifdef FEAT_INS_EXPAND
+EXTERN char_u *p_dict; /* 'dictionary' */
+#endif
+#ifdef FEAT_DIGRAPHS
+EXTERN int p_dg; /* 'digraph' */
+#endif
+EXTERN char_u *p_dir; /* 'directory' */
+EXTERN char_u *p_dy; /* 'display' */
+EXTERN unsigned dy_flags;
+#ifdef IN_OPTION_C
+static char *(p_dy_values[]) = {"lastline", "uhex", NULL};
+#endif
+#define DY_LASTLINE 0x001
+#define DY_UHEX 0x002
+EXTERN int p_ed; /* 'edcompatible' */
+#ifdef FEAT_VERTSPLIT
+EXTERN char_u *p_ead; /* 'eadirection' */
+#endif
+EXTERN int p_ea; /* 'equalalways' */
+EXTERN char_u *p_ep; /* 'equalprg' */
+EXTERN int p_eb; /* 'errorbells' */
+#ifdef FEAT_QUICKFIX
+EXTERN char_u *p_ef; /* 'errorfile' */
+EXTERN char_u *p_efm; /* 'errorformat' */
+EXTERN char_u *p_gefm; /* 'grepformat' */
+EXTERN char_u *p_gp; /* 'grepprg' */
+#endif
+#ifdef FEAT_AUTOCMD
+EXTERN char_u *p_ei; /* 'eventignore' */
+#endif
+EXTERN int p_ek; /* 'esckeys' */
+EXTERN int p_exrc; /* 'exrc' */
+#ifdef FEAT_MBYTE
+EXTERN char_u *p_fencs; /* 'fileencodings' */
+#endif
+EXTERN char_u *p_ffs; /* 'fileformats' */
+#ifdef FEAT_FOLDING
+EXTERN char_u *p_fcl; /* 'foldclose' */
+EXTERN long p_fdls; /* 'foldlevelstart' */
+EXTERN char_u *p_fdo; /* 'foldopen' */
+EXTERN unsigned fdo_flags;
+# ifdef IN_OPTION_C
+static char *(p_fdo_values[]) = {"all", "block", "hor", "mark", "percent",
+ "quickfix", "search", "tag", "insert",
+ "undo", "jump", NULL};
+# endif
+# define FDO_ALL 0x001
+# define FDO_BLOCK 0x002
+# define FDO_HOR 0x004
+# define FDO_MARK 0x008
+# define FDO_PERCENT 0x010
+# define FDO_QUICKFIX 0x020
+# define FDO_SEARCH 0x040
+# define FDO_TAG 0x080
+# define FDO_INSERT 0x100
+# define FDO_UNDO 0x200
+# define FDO_JUMP 0x400
+#endif
+EXTERN char_u *p_fp; /* 'formatprg' */
+EXTERN int p_gd; /* 'gdefault' */
+#ifdef FEAT_PRINTER
+EXTERN char_u *p_pdev; /* 'printdevice' */
+# ifdef FEAT_POSTSCRIPT
+EXTERN char_u *p_penc; /* 'printencoding' */
+EXTERN char_u *p_pexpr; /* 'printexpr' */
+# endif
+EXTERN char_u *p_pfn; /* 'printfont' */
+EXTERN char_u *p_popt; /* 'printoptions' */
+EXTERN char_u *p_header; /* 'printheader' */
+#endif
+#ifdef FEAT_GUI
+EXTERN char_u *p_guifont; /* 'guifont' */
+# ifdef FEAT_XFONTSET
+EXTERN char_u *p_guifontset; /* 'guifontset' */
+# endif
+# ifdef FEAT_MBYTE
+EXTERN char_u *p_guifontwide; /* 'guifontwide' */
+# endif
+EXTERN int p_guipty; /* 'guipty' */
+#endif
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11)
+EXTERN long p_ghr; /* 'guiheadroom' */
+#endif
+#ifdef CURSOR_SHAPE
+EXTERN char_u *p_guicursor; /* 'guicursor' */
+#endif
+#ifdef FEAT_MOUSESHAPE
+EXTERN char_u *p_mouseshape; /* 'mouseshape' */
+#endif
+#if defined(FEAT_GUI)
+EXTERN char_u *p_go; /* 'guioptions' */
+#endif
+EXTERN char_u *p_hf; /* 'helpfile' */
+#ifdef FEAT_WINDOWS
+EXTERN long p_hh; /* 'helpheight' */
+#endif
+#ifdef FEAT_MULTI_LANG
+EXTERN char_u *p_hlg; /* 'helplang' */
+#endif
+EXTERN int p_hid; /* 'hidden' */
+/* Use P_HID to check if a buffer is to be hidden when it is no longer
+ * visible in a window. */
+#ifndef FEAT_QUICKFIX
+# define P_HID(dummy) (p_hid || cmdmod.hide)
+#else
+# define P_HID(buf) (buf_hide(buf))
+#endif
+EXTERN char_u *p_hl; /* 'highlight' */
+EXTERN int p_hls; /* 'hlsearch' */
+EXTERN long p_hi; /* 'history' */
+#ifdef FEAT_RIGHTLEFT
+EXTERN int p_hkmap; /* 'hkmap' */
+EXTERN int p_hkmapp; /* 'hkmapp' */
+# ifdef FEAT_FKMAP
+EXTERN int p_fkmap; /* 'fkmap' */
+EXTERN int p_altkeymap; /* 'altkeymap' */
+# endif
+# ifdef FEAT_ARABIC
+EXTERN int p_arshape; /* 'arabicshape' */
+# endif
+#endif
+#ifdef FEAT_TITLE
+EXTERN int p_icon; /* 'icon' */
+EXTERN char_u *p_iconstring; /* 'iconstring' */
+#endif
+EXTERN int p_ic; /* 'ignorecase' */
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+EXTERN char_u *p_imak; /* 'imactivatekey' */
+#endif
+#ifdef USE_IM_CONTROL
+EXTERN int p_imcmdline; /* 'imcmdline' */
+EXTERN int p_imdisable; /* 'imdisable' */
+#endif
+EXTERN int p_is; /* 'incsearch' */
+EXTERN int p_im; /* 'insertmode' */
+EXTERN char_u *p_isf; /* 'isfname' */
+EXTERN char_u *p_isi; /* 'isident' */
+EXTERN char_u *p_isp; /* 'isprint' */
+EXTERN int p_js; /* 'joinspaces' */
+EXTERN char_u *p_kp; /* 'keywordprg' */
+#ifdef FEAT_VISUAL
+EXTERN char_u *p_km; /* 'keymodel' */
+#endif
+#ifdef FEAT_LANGMAP
+EXTERN char_u *p_langmap; /* 'langmap'*/
+#endif
+#if defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)
+EXTERN char_u *p_lm; /* 'langmenu' */
+#endif
+#ifdef FEAT_GUI
+EXTERN long p_linespace; /* 'linespace' */
+#endif
+#ifdef FEAT_LISP
+EXTERN char_u *p_lispwords; /* 'lispwords' */
+#endif
+#ifdef FEAT_WINDOWS
+EXTERN long p_ls; /* 'laststatus' */
+#endif
+EXTERN char_u *p_lcs; /* 'listchars' */
+
+EXTERN int p_lz; /* 'lazyredraw' */
+EXTERN int p_lpl; /* 'loadplugins' */
+EXTERN int p_magic; /* 'magic' */
+#ifdef FEAT_QUICKFIX
+EXTERN char_u *p_mef; /* 'makeef' */
+EXTERN char_u *p_mp; /* 'makeprg' */
+#endif
+EXTERN long p_mat; /* 'matchtime' */
+#ifdef FEAT_EVAL
+EXTERN long p_mfd; /* 'maxfuncdepth' */
+#endif
+EXTERN long p_mmd; /* 'maxmapdepth' */
+EXTERN long p_mm; /* 'maxmem' */
+EXTERN long p_mmt; /* 'maxmemtot' */
+#ifdef FEAT_MENU
+EXTERN long p_mis; /* 'menuitems' */
+#endif
+EXTERN long p_mls; /* 'modelines' */
+EXTERN char_u *p_mouse; /* 'mouse' */
+#ifdef FEAT_GUI
+EXTERN int p_mousef; /* 'mousefocus' */
+EXTERN int p_mh; /* 'mousehide' */
+#endif
+EXTERN char_u *p_mousem; /* 'mousemodel' */
+EXTERN long p_mouset; /* 'mousetime' */
+EXTERN int p_more; /* 'more' */
+EXTERN char_u *p_para; /* 'paragraphs' */
+EXTERN int p_paste; /* 'paste' */
+EXTERN char_u *p_pt; /* 'pastetoggle' */
+#if defined(FEAT_EVAL) && defined(FEAT_DIFF)
+EXTERN char_u *p_pex; /* 'patchexpr' */
+#endif
+EXTERN char_u *p_pm; /* 'patchmode' */
+EXTERN char_u *p_path; /* 'path' */
+#ifdef FEAT_SEARCHPATH
+EXTERN char_u *p_cdpath; /* 'cdpath' */
+#endif
+EXTERN int p_remap; /* 'remap' */
+EXTERN long p_report; /* 'report' */
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+EXTERN long p_pvh; /* 'previewheight' */
+#endif
+#ifdef WIN3264
+EXTERN int p_rs; /* 'restorescreen' */
+#endif
+#ifdef FEAT_RIGHTLEFT
+EXTERN int p_ari; /* 'allowrevins' */
+EXTERN int p_ri; /* 'revins' */
+#endif
+#ifdef FEAT_CMDL_INFO
+EXTERN int p_ru; /* 'ruler' */
+#endif
+#ifdef FEAT_STL_OPT
+EXTERN char_u *p_ruf; /* 'rulerformat' */
+#endif
+EXTERN char_u *p_rtp; /* 'runtimepath' */
+EXTERN long p_sj; /* 'scrolljump' */
+EXTERN long p_so; /* 'scrolloff' */
+#ifdef FEAT_SCROLLBIND
+EXTERN char_u *p_sbo; /* 'scrollopt' */
+#endif
+EXTERN char_u *p_sections; /* 'sections' */
+EXTERN int p_secure; /* 'secure' */
+#ifdef FEAT_VISUAL
+EXTERN char_u *p_sel; /* 'selection' */
+EXTERN char_u *p_slm; /* 'selectmode' */
+#endif
+#ifdef FEAT_SESSION
+EXTERN char_u *p_ssop; /* 'sessionoptions' */
+EXTERN unsigned ssop_flags;
+# ifdef IN_OPTION_C
+/* Also used for 'viewoptions'! */
+static char *(p_ssop_values[]) = {"buffers", "winpos", "resize", "winsize",
+ "localoptions", "options", "help", "blank", "globals", "slash", "unix",
+ "sesdir", "curdir", "folds", "cursor", NULL};
+# endif
+# define SSOP_BUFFERS 0x001
+# define SSOP_WINPOS 0x002
+# define SSOP_RESIZE 0x004
+# define SSOP_WINSIZE 0x008
+# define SSOP_LOCALOPTIONS 0x010
+# define SSOP_OPTIONS 0x020
+# define SSOP_HELP 0x040
+# define SSOP_BLANK 0x080
+# define SSOP_GLOBALS 0x100
+# define SSOP_SLASH 0x200
+# define SSOP_UNIX 0x400
+# define SSOP_SESDIR 0x800
+# define SSOP_CURDIR 0x1000
+# define SSOP_FOLDS 0x2000
+# define SSOP_CURSOR 0x4000
+#endif
+EXTERN char_u *p_sh; /* 'shell' */
+EXTERN char_u *p_shcf; /* 'shellcmdflag' */
+#ifdef FEAT_QUICKFIX
+EXTERN char_u *p_sp; /* 'shellpipe' */
+#endif
+EXTERN char_u *p_shq; /* 'shellquote' */
+EXTERN char_u *p_sxq; /* 'shellxquote' */
+EXTERN char_u *p_srr; /* 'shellredir' */
+#ifdef AMIGA
+EXTERN long p_st; /* 'shelltype' */
+#endif
+#ifdef BACKSLASH_IN_FILENAME
+EXTERN int p_ssl; /* 'shellslash' */
+#endif
+#ifdef FEAT_STL_OPT
+EXTERN char_u *p_stl; /* 'statusline' */
+#endif
+EXTERN int p_sr; /* 'shiftround' */
+EXTERN char_u *p_shm; /* 'shortmess' */
+#ifdef FEAT_LINEBREAK
+EXTERN char_u *p_sbr; /* 'showbreak' */
+#endif
+#ifdef FEAT_CMDL_INFO
+EXTERN int p_sc; /* 'showcmd' */
+#endif
+EXTERN int p_sft; /* 'showfulltag' */
+EXTERN int p_sm; /* 'showmatch' */
+EXTERN int p_smd; /* 'showmode' */
+EXTERN long p_ss; /* 'sidescroll' */
+EXTERN long p_siso; /* 'sidescrolloff' */
+EXTERN int p_scs; /* 'smartcase' */
+EXTERN int p_sta; /* 'smarttab' */
+#ifdef FEAT_WINDOWS
+EXTERN int p_sb; /* 'splitbelow' */
+#endif
+#ifdef FEAT_VERTSPLIT
+EXTERN int p_spr; /* 'splitright' */
+#endif
+EXTERN int p_sol; /* 'startofline' */
+EXTERN char_u *p_su; /* 'suffixes' */
+EXTERN char_u *p_sws; /* 'swapsync' */
+EXTERN char_u *p_swb; /* 'switchbuf' */
+EXTERN int p_tbs; /* 'tagbsearch' */
+EXTERN long p_tl; /* 'taglength' */
+EXTERN int p_tr; /* 'tagrelative' */
+EXTERN char_u *p_tags; /* 'tags' */
+EXTERN int p_tgst; /* 'tagstack' */
+#ifdef FEAT_ARABIC
+EXTERN int p_tbidi; /* 'termbidi' */
+#endif
+#ifdef FEAT_MBYTE
+EXTERN char_u *p_tenc; /* 'termencoding' */
+#endif
+EXTERN int p_terse; /* 'terse' */
+EXTERN int p_ta; /* 'textauto' */
+EXTERN int p_to; /* 'tildeop' */
+EXTERN int p_timeout; /* 'timeout' */
+EXTERN long p_tm; /* 'timeoutlen' */
+#ifdef FEAT_TITLE
+EXTERN int p_title; /* 'title' */
+EXTERN long p_titlelen; /* 'titlelen' */
+EXTERN char_u *p_titleold; /* 'titleold' */
+EXTERN char_u *p_titlestring; /* 'titlestring' */
+#endif
+#ifdef FEAT_INS_EXPAND
+EXTERN char_u *p_tsr; /* 'thesaurus' */
+#endif
+EXTERN int p_ttimeout; /* 'ttimeout' */
+EXTERN long p_ttm; /* 'ttimeoutlen' */
+EXTERN int p_tbi; /* 'ttybuiltin' */
+EXTERN int p_tf; /* 'ttyfast' */
+#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32)
+EXTERN char_u *p_toolbar; /* 'toolbar' */
+EXTERN unsigned toolbar_flags;
+# ifdef IN_OPTION_C
+static char *(p_toolbar_values[]) = {"text", "icons", "tooltips", "horiz", NULL};
+# endif
+# define TOOLBAR_TEXT 0x01
+# define TOOLBAR_ICONS 0x02
+# define TOOLBAR_TOOLTIPS 0x04
+# define TOOLBAR_HORIZ 0x08
+#endif
+#if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK) && defined(HAVE_GTK2)
+EXTERN char_u *p_tbis; /* 'toolbariconsize' */
+EXTERN unsigned tbis_flags;
+# ifdef IN_OPTION_C
+static char *(p_tbis_values[]) = {"tiny", "small", "medium", "large", NULL};
+# endif
+# define TBIS_TINY 0x01
+# define TBIS_SMALL 0x02
+# define TBIS_MEDIUM 0x04
+# define TBIS_LARGE 0x08
+#endif
+EXTERN long p_ttyscroll; /* 'ttyscroll' */
+#if defined(FEAT_MOUSE) && (defined(UNIX) || defined(VMS))
+EXTERN char_u *p_ttym; /* 'ttymouse' */
+EXTERN unsigned ttym_flags;
+# ifdef IN_OPTION_C
+static char *(p_ttym_values[]) = {"xterm", "xterm2", "dec", "netterm", "jsbterm", "pterm", NULL};
+# endif
+# define TTYM_XTERM 0x01
+# define TTYM_XTERM2 0x02
+# define TTYM_DEC 0x04
+# define TTYM_NETTERM 0x08
+# define TTYM_JSBTERM 0x10
+# define TTYM_PTERM 0x20
+#endif
+EXTERN long p_ul; /* 'undolevels' */
+EXTERN long p_uc; /* 'updatecount' */
+EXTERN long p_ut; /* 'updatetime' */
+#if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING)
+EXTERN char_u *p_fcs; /* 'fillchar' */
+#endif
+#ifdef FEAT_VIMINFO
+EXTERN char_u *p_viminfo; /* 'viminfo' */
+#endif
+#ifdef FEAT_SESSION
+EXTERN char_u *p_vdir; /* 'viewdir' */
+EXTERN char_u *p_vop; /* 'viewoptions' */
+EXTERN unsigned vop_flags; /* uses SSOP_ flags */
+#endif
+EXTERN int p_vb; /* 'visualbell' */
+#ifdef FEAT_VIRTUALEDIT
+EXTERN char_u *p_ve; /* 'virtualedit' */
+EXTERN unsigned ve_flags;
+# ifdef IN_OPTION_C
+static char *(p_ve_values[]) = {"block", "insert", "all", NULL};
+# endif
+# define VE_BLOCK 5 /* includes "all" */
+# define VE_INSERT 6 /* includes "all" */
+# define VE_ALL 4
+#endif
+EXTERN long p_verbose; /* 'verbose' */
+EXTERN int p_warn; /* 'warn' */
+#if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(LINT) \
+ || defined (FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON)
+#define FEAT_WAK
+EXTERN char_u *p_wak; /* 'winaltkeys' */
+#endif
+#ifdef FEAT_WILDIGN
+EXTERN char_u *p_wig; /* 'wildignore' */
+#endif
+EXTERN int p_wiv; /* 'weirdinvert' */
+EXTERN char_u *p_ww; /* 'whichwrap' */
+EXTERN long p_wc; /* 'wildchar' */
+EXTERN long p_wcm; /* 'wildcharm' */
+EXTERN char_u *p_wim; /* 'wildmode' */
+#ifdef FEAT_WILDMENU
+EXTERN int p_wmnu; /* 'wildmenu' */
+#endif
+#ifdef FEAT_WINDOWS
+EXTERN long p_wh; /* 'winheight' */
+EXTERN long p_wmh; /* 'winminheight' */
+#endif
+#ifdef FEAT_VERTSPLIT
+EXTERN long p_wmw; /* 'winminwidth' */
+EXTERN long p_wiw; /* 'winwidth' */
+#endif
+EXTERN int p_ws; /* 'wrapscan' */
+EXTERN int p_write; /* 'write' */
+EXTERN int p_wa; /* 'writeany' */
+EXTERN int p_wb; /* 'writebackup' */
+EXTERN long p_wd; /* 'writedelay' */
diff --git a/src/os_amiga.c b/src/os_amiga.c
new file mode 100644
index 000000000..f462ccc59
--- /dev/null
+++ b/src/os_amiga.c
@@ -0,0 +1,1619 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * os_amiga.c
+ *
+ * Amiga system-dependent routines.
+ */
+
+#include "vim.h"
+
+#ifdef Window
+# undef Window /* Amiga has its own Window definition */
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#undef TRUE /* will be redefined by exec/types.h */
+#undef FALSE
+
+#ifndef LATTICE
+# include <exec/types.h>
+# include <exec/exec.h>
+# include <libraries/dos.h>
+# include <libraries/dosextens.h>
+# include <intuition/intuition.h>
+#else
+# include <proto/dos.h>
+# include <libraries/dosextens.h>
+# include <proto/intuition.h>
+# include <proto/exec.h>
+#endif
+
+#include <exec/memory.h>
+
+#include <dos/dostags.h> /* for 2.0 functions */
+#include <dos/dosasl.h>
+
+#if defined(LATTICE) && !defined(SASC) && defined(FEAT_ARP)
+# include <libraries/arp_pragmas.h>
+#endif
+
+/*
+ * At this point TRUE and FALSE are defined as 1L and 0L, but we want 1 and 0.
+ */
+#undef TRUE
+#define TRUE (1)
+#undef FALSE
+#define FALSE (0)
+
+#if !defined(AZTEC_C) && !defined(__AROS__)
+static long dos_packet __ARGS((struct MsgPort *, long, long));
+#endif
+static int lock2name __ARGS((BPTR lock, char_u *buf, long len));
+static void out_num __ARGS((long n));
+static struct FileInfoBlock *get_fib __ARGS((char_u *));
+static int sortcmp __ARGS((const void *a, const void *b));
+
+static BPTR raw_in = (BPTR)NULL;
+static BPTR raw_out = (BPTR)NULL;
+static int close_win = FALSE; /* set if Vim opened the window */
+
+struct IntuitionBase *IntuitionBase = NULL;
+#ifdef FEAT_ARP
+struct ArpBase *ArpBase = NULL;
+#endif
+
+static struct Window *wb_window;
+static char_u *oldwindowtitle = NULL;
+
+#ifdef FEAT_ARP
+int dos2 = FALSE; /* Amiga DOS 2.0x or higher */
+#endif
+int size_set = FALSE; /* set to TRUE if window size was set */
+
+ void
+win_resize_on()
+{
+ OUT_STR_NF("\033[12{");
+}
+
+ void
+win_resize_off()
+{
+ OUT_STR_NF("\033[12}");
+}
+
+ void
+mch_write(p, len)
+ char_u *p;
+ int len;
+{
+ Write(raw_out, (char *)p, (long)len);
+}
+
+/*
+ * mch_inchar(): low level input funcion.
+ * Get a characters from the keyboard.
+ * If time == 0 do not wait for characters.
+ * If time == n wait a short time for characters.
+ * If time == -1 wait forever for characters.
+ *
+ * Return number of characters read.
+ */
+ int
+mch_inchar(buf, maxlen, time, tb_change_cnt)
+ char_u *buf;
+ int maxlen;
+ long time; /* milli seconds */
+ int tb_change_cnt;
+{
+ int len;
+ long utime;
+#ifdef FEAT_AUTOCMD
+ static int once_already = 0;
+#endif
+
+ if (time >= 0)
+ {
+ if (time == 0)
+ utime = 100L; /* time = 0 causes problems in DOS 1.2 */
+ else
+ utime = time * 1000L; /* convert from milli to micro secs */
+ if (WaitForChar(raw_in, utime) == 0) /* no character available */
+ {
+#ifdef FEAT_AUTOCMD
+ once_already = 0;
+#endif
+ return 0;
+ }
+ }
+ else /* time == -1 */
+ {
+#ifdef FEAT_AUTOCMD
+ if (once_already == 2)
+ updatescript(0);
+ else if (once_already == 1)
+ {
+ setcursor();
+ once_already = 2;
+ return 0;
+ }
+ else
+#endif
+ /*
+ * If there is no character available within 2 seconds (default)
+ * write the autoscript file to disk
+ */
+ if (WaitForChar(raw_in, p_ut * 1000L) == 0)
+ {
+#ifdef FEAT_AUTOCMD
+ if (has_cursorhold() && get_real_state() == NORMAL_BUSY)
+ {
+ apply_autocmds(EVENT_CURSORHOLD, NULL, NULL, FALSE, curbuf);
+ update_screen(VALID);
+ once_already = 1;
+ return 0;
+ }
+ else
+#endif
+ updatescript(0);
+ }
+ }
+
+ for (;;) /* repeat until we got a character */
+ {
+# ifdef FEAT_MBYTE
+ len = Read(raw_in, (char *)buf, (long)maxlen / input_conv.vc_factor);
+# else
+ len = Read(raw_in, (char *)buf, (long)maxlen);
+# endif
+ if (len > 0)
+ {
+#ifdef FEAT_AUTOCMD
+ once_already = 0;
+#endif
+#ifdef FEAT_MBYTE
+ /* Convert from 'termencoding' to 'encoding'. */
+ if (input_conv.vc_type != CONV_NONE)
+ len = convert_input(buf, len, maxlen);
+#endif
+ return len;
+ }
+ }
+}
+
+/*
+ * return non-zero if a character is available
+ */
+ int
+mch_char_avail()
+{
+ return (WaitForChar(raw_in, 100L) != 0);
+}
+
+/*
+ * Return amount of memory still available.
+ */
+ long_u
+mch_avail_mem(special)
+ int special;
+{
+ return (long_u)AvailMem(special ? (long)MEMF_CHIP : (long)MEMF_ANY);
+}
+
+ void
+mch_delay(msec, ignoreinput)
+ long msec;
+ int ignoreinput;
+{
+#ifndef LATTICE /* SAS declares void Delay(UNLONG) */
+ void Delay __ARGS((long));
+#endif
+
+ if (msec > 0)
+ {
+ if (ignoreinput)
+ Delay(msec / 20L); /* Delay works with 20 msec intervals */
+ else
+ WaitForChar(raw_in, msec * 1000L);
+ }
+}
+
+/*
+ * We have no job control, fake it by starting a new shell.
+ */
+ void
+mch_suspend()
+{
+ suspend_shell();
+}
+
+#ifndef DOS_LIBRARY
+# define DOS_LIBRARY ((UBYTE *)"dos.library")
+#endif
+
+ void
+mch_init()
+{
+ static char intlibname[] = "intuition.library";
+
+#ifdef AZTEC_C
+ Enable_Abort = 0; /* disallow vim to be aborted */
+#endif
+ Columns = 80;
+ Rows = 24;
+
+ /*
+ * Set input and output channels, unless we have opened our own window
+ */
+ if (raw_in == (BPTR)NULL)
+ {
+ raw_in = Input();
+ raw_out = Output();
+ /*
+ * If Input() is not interactive, then Output() will be (because of
+ * check in mch_check_win()). Used for "Vim -".
+ * Also check the other way around, for "Vim -h | more".
+ */
+ if (!IsInteractive(raw_in))
+ raw_in = raw_out;
+ else if (!IsInteractive(raw_out))
+ raw_out = raw_in;
+ }
+
+ out_flush();
+
+ wb_window = NULL;
+ if ((IntuitionBase = (struct IntuitionBase *)
+ OpenLibrary((UBYTE *)intlibname, 0L)) == NULL)
+ {
+ mch_errmsg(_("cannot open "));
+ mch_errmsg(intlibname);
+ mch_errmsg("!?\n");
+ mch_exit(3);
+ }
+}
+
+#include <workbench/startup.h>
+
+/*
+ * Check_win checks whether we have an interactive window.
+ * If not, a new window is opened with the newcli command.
+ * If we would open a window ourselves, the :sh and :! commands would not
+ * work properly (Why? probably because we are then running in a background
+ * CLI). This also is the best way to assure proper working in a next
+ * Workbench release.
+ *
+ * For the -f option (foreground mode) we open our own window and disable :sh.
+ * Otherwise the calling program would never know when editing is finished.
+ */
+#define BUF2SIZE 320 /* length of buffer for argument with complete path */
+
+ int
+mch_check_win(argc, argv)
+ int argc;
+ char **argv;
+{
+ int i;
+ BPTR nilfh, fh;
+ char_u buf1[20];
+ char_u buf2[BUF2SIZE];
+ static char_u *(constrings[3]) = {(char_u *)"con:0/0/662/210/",
+ (char_u *)"con:0/0/640/200/",
+ (char_u *)"con:0/0/320/200/"};
+ static char_u *winerr = (char_u *)N_("VIM: Can't open window!\n");
+ struct WBArg *argp;
+ int ac;
+ char *av;
+ char_u *device = NULL;
+ int exitval = 4;
+ struct Library *DosBase;
+ int usewin = FALSE;
+
+/*
+ * check if we are running under DOS 2.0x or higher
+ */
+ DosBase = OpenLibrary(DOS_LIBRARY, 37L);
+ if (DosBase != NULL)
+ /* if (((struct Library *)DOSBase)->lib_Version >= 37) */
+ {
+ CloseLibrary(DosBase);
+#ifdef FEAT_ARP
+ dos2 = TRUE;
+#endif
+ }
+ else /* without arp functions we NEED 2.0 */
+ {
+#ifndef FEAT_ARP
+ mch_errmsg(_("Need Amigados version 2.04 or later\n"));
+ exit(3);
+#else
+ /* need arp functions for dos 1.x */
+ if (!(ArpBase = (struct ArpBase *) OpenLibrary((UBYTE *)ArpName, ArpVersion)))
+ {
+ fprintf(stderr, _("Need %s version %ld\n"), ArpName, ArpVersion);
+ exit(3);
+ }
+#endif
+ }
+
+ /*
+ * scan argv[] for the "-f" and "-d" arguments
+ */
+ for (i = 1; i < argc; ++i)
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'f':
+ usewin = TRUE;
+ break;
+
+ case 'd':
+ if (i < argc - 1
+#ifdef FEAT_DIFF
+ /* require using "-dev", "-d" means diff mode */
+ && argv[i][2] == 'e' && argv[i][3] == 'v'
+#endif
+ )
+ device = (char_u *)argv[i + 1];
+ break;
+ }
+ }
+
+/*
+ * If we were not started from workbench, do not have a "-d" or "-dev"
+ * argument and we have been started with an interactive window, use that
+ * window.
+ */
+ if (argc != 0
+ && device == NULL
+ && (IsInteractive(Input()) || IsInteractive(Output())))
+ return OK;
+
+/*
+ * When given the "-f" argument, we open our own window. We can't use the
+ * newcli trick below, because the calling program (mail, rn, etc.) would not
+ * know when we are finished.
+ */
+ if (usewin)
+ {
+ /*
+ * Try to open a window. First try the specified device.
+ * Then try a 24 line 80 column window.
+ * If that fails, try two smaller ones.
+ */
+ for (i = -1; i < 3; ++i)
+ {
+ if (i >= 0)
+ device = constrings[i];
+ if (device != NULL && (raw_in = Open((UBYTE *)device,
+ (long)MODE_NEWFILE)) != (BPTR)NULL)
+ break;
+ }
+ if (raw_in == (BPTR)NULL) /* all three failed */
+ {
+ mch_errmsg(_(winerr));
+ goto exit;
+ }
+ raw_out = raw_in;
+ close_win = TRUE;
+ return OK;
+ }
+
+ if ((nilfh = Open((UBYTE *)"NIL:", (long)MODE_NEWFILE)) == (BPTR)NULL)
+ {
+ mch_errmsg(_("Cannot open NIL:\n"));
+ goto exit;
+ }
+
+ /*
+ * Make a unique name for the temp file (which we will not delete!).
+ * Use a pointer on the stack (nobody else will be using it).
+ */
+ sprintf((char *)buf1, "t:nc%ld", (long)buf1);
+ if ((fh = Open((UBYTE *)buf1, (long)MODE_NEWFILE)) == (BPTR)NULL)
+ {
+ mch_errmsg(_("Cannot create "));
+ mch_errmsg((char *)buf1);
+ mch_errmsg("\n");
+ goto exit;
+ }
+ /*
+ * Write the command into the file, put quotes around the arguments that
+ * have a space in them.
+ */
+ if (argc == 0) /* run from workbench */
+ ac = ((struct WBStartup *)argv)->sm_NumArgs;
+ else
+ ac = argc;
+ for (i = 0; i < ac; ++i)
+ {
+ if (argc == 0)
+ {
+ *buf2 = NUL;
+ argp = &(((struct WBStartup *)argv)->sm_ArgList[i]);
+ if (argp->wa_Lock)
+ (void)lock2name(argp->wa_Lock, buf2, (long)(BUF2SIZE - 1));
+#ifdef FEAT_ARP
+ if (dos2) /* use 2.0 function */
+#endif
+ AddPart((UBYTE *)buf2, (UBYTE *)argp->wa_Name, (long)(BUF2SIZE - 1));
+#ifdef FEAT_ARP
+ else /* use arp function */
+ TackOn((char *)buf2, argp->wa_Name);
+#endif
+ av = (char *)buf2;
+ }
+ else
+ av = argv[i];
+
+ /* skip '-d' or "-dev" option */
+ if (av[0] == '-' && av[1] == 'd'
+#ifdef FEAT_DIFF
+ && av[2] == 'e' && av[3] == 'v'
+#endif
+ )
+ {
+ ++i;
+ continue;
+ }
+ if (vim_strchr((char_u *)av, ' '))
+ Write(fh, "\"", 1L);
+ Write(fh, av, (long)strlen(av));
+ if (vim_strchr((char_u *)av, ' '))
+ Write(fh, "\"", 1L);
+ Write(fh, " ", 1L);
+ }
+ Write(fh, "\nendcli\n", 8L);
+ Close(fh);
+
+/*
+ * Try to open a new cli in a window. If "-d" or "-dev" argument was given try
+ * to open the specified device. Then try a 24 line 80 column window. If that
+ * fails, try two smaller ones.
+ */
+ for (i = -1; i < 3; ++i)
+ {
+ if (i >= 0)
+ device = constrings[i];
+ else if (device == NULL)
+ continue;
+ sprintf((char *)buf2, "newcli <nil: >nil: %s from %s", (char *)device, (char *)buf1);
+#ifdef FEAT_ARP
+ if (dos2)
+ {
+#endif
+ if (!SystemTags((UBYTE *)buf2, SYS_UserShell, TRUE, TAG_DONE))
+ break;
+#ifdef FEAT_ARP
+ }
+ else
+ {
+ if (Execute((UBYTE *)buf2, nilfh, nilfh))
+ break;
+ }
+#endif
+ }
+ if (i == 3) /* all three failed */
+ {
+ DeleteFile((UBYTE *)buf1);
+ mch_errmsg(_(winerr));
+ goto exit;
+ }
+ exitval = 0; /* The Execute succeeded: exit this program */
+
+exit:
+#ifdef FEAT_ARP
+ if (ArpBase)
+ CloseLibrary((struct Library *) ArpBase);
+#endif
+ exit(exitval);
+ /* NOTREACHED */
+ return FAIL;
+}
+
+/*
+ * Return TRUE if the input comes from a terminal, FALSE otherwise.
+ * We fake there is a window, because we can always open one!
+ */
+ int
+mch_input_isatty()
+{
+ return TRUE;
+}
+
+/*
+ * fname_case(): Set the case of the file name, if it already exists.
+ * This will cause the file name to remain exactly the same.
+ */
+/*ARGSUSED*/
+ void
+fname_case(name, len)
+ char_u *name;
+ int len; /* buffer size, ignored here */
+{
+ struct FileInfoBlock *fib;
+ size_t flen;
+
+ fib = get_fib(name);
+ if (fib != NULL)
+ {
+ flen = STRLEN(name);
+ if (flen == strlen(fib->fib_FileName)) /* safety check */
+ mch_memmove(name, fib->fib_FileName, flen);
+ vim_free(fib);
+ }
+}
+
+/*
+ * Get the FileInfoBlock for file "fname"
+ * The returned structure has to be free()d.
+ * Returns NULL on error.
+ */
+ static struct FileInfoBlock *
+get_fib(fname)
+ char_u *fname;
+{
+ BPTR flock;
+ struct FileInfoBlock *fib;
+
+ if (fname == NULL) /* safety check */
+ return NULL;
+ fib = (struct FileInfoBlock *)malloc(sizeof(struct FileInfoBlock));
+ if (fib != NULL)
+ {
+ flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
+ if (flock == (BPTR)NULL || !Examine(flock, fib))
+ {
+ vim_free(fib); /* in case of an error the memory is freed here */
+ fib = NULL;
+ }
+ if (flock)
+ UnLock(flock);
+ }
+ return fib;
+}
+
+#ifdef FEAT_TITLE
+/*
+ * set the title of our window
+ * icon name is not set
+ */
+ void
+mch_settitle(title, icon)
+ char_u *title;
+ char_u *icon;
+{
+ if (wb_window != NULL && title != NULL)
+ SetWindowTitles(wb_window, (UBYTE *)title, (UBYTE *)-1L);
+}
+
+/*
+ * Restore the window/icon title.
+ * which is one of:
+ * 1 Just restore title
+ * 2 Just restore icon (which we don't have)
+ * 3 Restore title and icon (which we don't have)
+ */
+ void
+mch_restore_title(which)
+ int which;
+{
+ if (which & 1)
+ mch_settitle(oldwindowtitle, NULL);
+}
+
+ int
+mch_can_restore_title()
+{
+ return (wb_window != NULL);
+}
+
+ int
+mch_can_restore_icon()
+{
+ return FALSE;
+}
+#endif
+
+/*
+ * Insert user name in s[len].
+ */
+ int
+mch_get_user_name(s, len)
+ char_u *s;
+ int len;
+{
+ *s = NUL;
+ return FAIL;
+}
+
+/*
+ * Insert host name is s[len].
+ */
+ void
+mch_get_host_name(s, len)
+ char_u *s;
+ int len;
+{
+ STRNCPY(s, "Amiga", len);
+}
+
+/*
+ * return process ID
+ */
+ long
+mch_get_pid()
+{
+ return (long)0;
+}
+
+/*
+ * Get name of current directory into buffer 'buf' of length 'len' bytes.
+ * Return OK for success, FAIL for failure.
+ */
+ int
+mch_dirname(buf, len)
+ char_u *buf;
+ int len;
+{
+ return mch_FullName((char_u *)"", buf, len, FALSE);
+}
+
+/*
+ * get absolute file name into buffer 'buf' of length 'len' bytes
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+mch_FullName(fname, buf, len, force)
+ char_u *fname, *buf;
+ int len;
+ int force;
+{
+ BPTR l;
+ int retval = FAIL;
+ int i;
+
+ /* Lock the file. If it exists, we can get the exact name. */
+ if ((l = Lock((UBYTE *)fname, (long)ACCESS_READ)) != (BPTR)0)
+ {
+ retval = lock2name(l, buf, (long)len - 1);
+ UnLock(l);
+ }
+ else if (force || !mch_isFullName(fname)) /* not a full path yet */
+ {
+ /*
+ * If the file cannot be locked (doesn't exist), try to lock the
+ * current directory and concatenate the file name.
+ */
+ if ((l = Lock((UBYTE *)"", (long)ACCESS_READ)) != (BPTR)NULL)
+ {
+ retval = lock2name(l, buf, (long)len);
+ UnLock(l);
+ if (retval == OK)
+ {
+ i = STRLEN(buf);
+ /* Concatenate the fname to the directory. Don't add a slash
+ * if fname is empty, but do change "" to "/". */
+ if (i == 0 || *fname != NUL)
+ {
+ if (i < len - 1 && (i == 0 || buf[i - 1] != ':'))
+ buf[i++] = '/';
+ STRNCPY(buf + i, fname, len - i);
+ }
+ }
+ }
+ }
+ if (*buf == 0 || *buf == ':')
+ retval = FAIL; /* something failed; use the file name */
+ return retval;
+}
+
+/*
+ * Return TRUE if "fname" does not depend on the current directory.
+ */
+ int
+mch_isFullName(fname)
+ char_u *fname;
+{
+ return (vim_strchr(fname, ':') != NULL && *fname != ':');
+}
+
+/*
+ * Get the full file name from a lock. Use 2.0 function if possible, because
+ * the arp function has more restrictions on the path length.
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ static int
+lock2name(lock, buf, len)
+ BPTR lock;
+ char_u *buf;
+ long len;
+{
+#ifdef FEAT_ARP
+ if (dos2) /* use 2.0 function */
+#endif
+ return ((int)NameFromLock(lock, (UBYTE *)buf, len) ? OK : FAIL);
+#ifdef FEAT_ARP
+ else /* use arp function */
+ return ((int)PathName(lock, (char *)buf, (long)(len/32)) ? OK : FAIL);
+#endif
+}
+
+/*
+ * get file permissions for 'name'
+ * Returns -1 when it doesn't exist.
+ */
+ long
+mch_getperm(name)
+ char_u *name;
+{
+ struct FileInfoBlock *fib;
+ long retval = -1;
+
+ fib = get_fib(name);
+ if (fib != NULL)
+ {
+ retval = fib->fib_Protection;
+ vim_free(fib);
+ }
+ return retval;
+}
+
+/*
+ * set file permission for 'name' to 'perm'
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+mch_setperm(name, perm)
+ char_u *name;
+ long perm;
+{
+ perm &= ~FIBF_ARCHIVE; /* reset archived bit */
+ return (SetProtection((UBYTE *)name, (long)perm) ? OK : FAIL);
+}
+
+/*
+ * Set hidden flag for "name".
+ */
+ void
+mch_hide(name)
+ char_u *name;
+{
+ /* can't hide a file */
+}
+
+/*
+ * return FALSE if "name" is not a directory
+ * return TRUE if "name" is a directory.
+ * return FALSE for error.
+ */
+ int
+mch_isdir(name)
+ char_u *name;
+{
+ struct FileInfoBlock *fib;
+ int retval = FALSE;
+
+ fib = get_fib(name);
+ if (fib != NULL)
+ {
+ retval = ((fib->fib_DirEntryType >= 0) ? TRUE : FALSE);
+ vim_free(fib);
+ }
+ return retval;
+}
+
+/*
+ * Create directory "name".
+ */
+ void
+mch_mkdir(name)
+ char_u *name;
+{
+ BPTR lock;
+
+ lock = CreateDir(name);
+ if (lock != NULL)
+ UnLock(lock);
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return 1 if "name" can be executed, 0 if not.
+ * Return -1 if unknown.
+ */
+ int
+mch_can_exe(name)
+ char_u *name;
+{
+ /* TODO */
+ return -1;
+}
+#endif
+
+/*
+ * Check what "name" is:
+ * NODE_NORMAL: file or directory (or doesn't exist)
+ * NODE_WRITABLE: writable device, socket, fifo, etc.
+ * NODE_OTHER: non-writable things
+ */
+ int
+mch_nodetype(name)
+ char_u *name;
+{
+ /* TODO */
+ return NODE_NORMAL;
+}
+
+ void
+mch_early_init()
+{
+}
+
+/*
+ * Careful: mch_exit() may be called before mch_init()!
+ */
+ void
+mch_exit(r)
+ int r;
+{
+ if (raw_in) /* put terminal in 'normal' mode */
+ {
+ settmode(TMODE_COOK);
+ stoptermcap();
+ }
+ out_char('\n');
+ if (raw_out)
+ {
+ if (term_console)
+ {
+ win_resize_off(); /* window resize events de-activated */
+ if (size_set)
+ OUT_STR("\233t\233u"); /* reset window size (CSI t CSI u) */
+ }
+ out_flush();
+ }
+
+#ifdef FEAT_TITLE
+ mch_restore_title(3); /* restore window title */
+#endif
+
+ ml_close_all(TRUE); /* remove all memfiles */
+
+#ifdef FEAT_ARP
+ if (ArpBase)
+ CloseLibrary((struct Library *) ArpBase);
+#endif
+ if (close_win)
+ Close(raw_in);
+ if (r)
+ printf(_("Vim exiting with %d\n"), r); /* somehow this makes :cq work!? */
+ exit(r);
+}
+
+/*
+ * This is a routine for setting a given stream to raw or cooked mode on the
+ * Amiga . This is useful when you are using Lattice C to produce programs
+ * that want to read single characters with the "getch()" or "fgetc" call.
+ *
+ * Written : 18-Jun-87 By Chuck McManis.
+ */
+
+#define MP(xx) ((struct MsgPort *)((struct FileHandle *) (BADDR(xx)))->fh_Type)
+
+/*
+ * Function mch_settmode() - Convert the specified file pointer to 'raw' or
+ * 'cooked' mode. This only works on TTY's.
+ *
+ * Raw: keeps DOS from translating keys for you, also (BIG WIN) it means
+ * getch() will return immediately rather than wait for a return. You
+ * lose editing features though.
+ *
+ * Cooked: This function returns the designate file pointer to it's normal,
+ * wait for a <CR> mode. This is exactly like raw() except that
+ * it sends a 0 to the console to make it back into a CON: from a RAW:
+ */
+ void
+mch_settmode(tmode)
+ int tmode;
+{
+#ifdef __AROS__
+ if (!SetMode(raw_in, tmode == TMODE_RAW ? 1 : 0))
+#else
+ if (dos_packet(MP(raw_in), (long)ACTION_SCREEN_MODE,
+ tmode == TMODE_RAW ? -1L : 0L) == 0)
+#endif
+ mch_errmsg(_("cannot change console mode ?!\n"));
+}
+
+/*
+ * set screen mode, always fails.
+ */
+ int
+mch_screenmode(arg)
+ char_u *arg;
+{
+ EMSG(_(e_screenmode));
+ return FAIL;
+}
+
+/*
+ * Code for this routine came from the following :
+ *
+ * ConPackets.c - C. Scheppner, A. Finkel, P. Lindsay CBM
+ * DOS packet example
+ * Requires 1.2
+ *
+ * Found on Fish Disk 56.
+ *
+ * Heavely modified by mool.
+ */
+
+#include <devices/conunit.h>
+
+/*
+ * try to get the real window size
+ * return FAIL for failure, OK otherwise
+ */
+ int
+mch_get_shellsize()
+{
+ struct ConUnit *conUnit;
+ char id_a[sizeof(struct InfoData) + 3];
+ struct InfoData *id;
+
+ if (!term_console) /* not an amiga window */
+ return FAIL;
+
+ /* insure longword alignment */
+ id = (struct InfoData *)(((long)id_a + 3L) & ~3L);
+
+ /*
+ * Should make console aware of real window size, not the one we set.
+ * Unfortunately, under DOS 2.0x this redraws the window and it
+ * is rarely needed, so we skip it now, unless we changed the size.
+ */
+ if (size_set)
+ OUT_STR("\233t\233u"); /* CSI t CSI u */
+ out_flush();
+
+#ifdef __AROS__
+ if (!Info(raw_out, id)
+ || (wb_window = (struct Window *) id->id_VolumeNode) == NULL)
+#else
+ if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0
+ || (wb_window = (struct Window *)id->id_VolumeNode) == NULL)
+#endif
+ {
+ /* it's not an amiga window, maybe aux device */
+ /* terminal type should be set */
+ term_console = FALSE;
+ return FAIL;
+ }
+ if (oldwindowtitle == NULL)
+ oldwindowtitle = (char_u *)wb_window->Title;
+ if (id->id_InUse == (BPTR)NULL)
+ {
+ mch_errmsg(_("mch_get_shellsize: not a console??\n"));
+ return FAIL;
+ }
+ conUnit = (struct ConUnit *) ((struct IOStdReq *) id->id_InUse)->io_Unit;
+
+ /* get window size */
+ Rows = conUnit->cu_YMax + 1;
+ Columns = conUnit->cu_XMax + 1;
+ if (Rows < 0 || Rows > 200) /* cannot be an amiga window */
+ {
+ Columns = 80;
+ Rows = 24;
+ term_console = FALSE;
+ return FAIL;
+ }
+
+ return OK;
+}
+
+/*
+ * Try to set the real window size to Rows and Columns.
+ */
+ void
+mch_set_shellsize()
+{
+ if (term_console)
+ {
+ size_set = TRUE;
+ out_char(CSI);
+ out_num((long)Rows);
+ out_char('t');
+ out_char(CSI);
+ out_num((long)Columns);
+ out_char('u');
+ out_flush();
+ }
+}
+
+/*
+ * Rows and/or Columns has changed.
+ */
+ void
+mch_new_shellsize()
+{
+ /* Nothing to do. */
+}
+
+/*
+ * out_num - output a (big) number fast
+ */
+ static void
+out_num(n)
+ long n;
+{
+ OUT_STR_NF(tltoa((unsigned long)n));
+}
+
+#if !defined(AZTEC_C) && !defined(__AROS__)
+/*
+ * Sendpacket.c
+ *
+ * An invaluable addition to your Amiga.lib file. This code sends a packet to
+ * the given message port. This makes working around DOS lots easier.
+ *
+ * Note, I didn't write this, those wonderful folks at CBM did. I do suggest
+ * however that you may wish to add it to Amiga.Lib, to do so, compile it and
+ * say 'oml lib:amiga.lib -r sendpacket.o'
+ */
+
+/* #include <proto/exec.h> */
+/* #include <proto/dos.h> */
+#include <exec/memory.h>
+
+/*
+ * Function - dos_packet written by Phil Lindsay, Carolyn Scheppner, and Andy
+ * Finkel. This function will send a packet of the given type to the Message
+ * Port supplied.
+ */
+
+ static long
+dos_packet(pid, action, arg)
+ struct MsgPort *pid; /* process indentifier ... (handlers message port) */
+ long action, /* packet type ... (what you want handler to do) */
+ arg; /* single argument */
+{
+# ifdef FEAT_ARP
+ struct MsgPort *replyport;
+ struct StandardPacket *packet;
+ long res1;
+
+ if (dos2)
+# endif
+ return DoPkt(pid, action, arg, 0L, 0L, 0L, 0L); /* use 2.0 function */
+# ifdef FEAT_ARP
+
+ replyport = (struct MsgPort *) CreatePort(NULL, 0); /* use arp function */
+ if (!replyport)
+ return (0);
+
+ /* Allocate space for a packet, make it public and clear it */
+ packet = (struct StandardPacket *)
+ AllocMem((long) sizeof(struct StandardPacket), MEMF_PUBLIC | MEMF_CLEAR);
+ if (!packet) {
+ DeletePort(replyport);
+ return (0);
+ }
+ packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);
+ packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
+ packet->sp_Pkt.dp_Port = replyport;
+ packet->sp_Pkt.dp_Type = action;
+ packet->sp_Pkt.dp_Arg1 = arg;
+
+ PutMsg(pid, (struct Message *)packet); /* send packet */
+
+ WaitPort(replyport);
+ GetMsg(replyport);
+
+ res1 = packet->sp_Pkt.dp_Res1;
+
+ FreeMem(packet, (long) sizeof(struct StandardPacket));
+ DeletePort(replyport);
+
+ return (res1);
+# endif
+}
+#endif /* !defined(AZTEC_C) && !defined(__AROS__) */
+
+/*
+ * Call shell.
+ * Return error number for failure, 0 otherwise
+ */
+ int
+mch_call_shell(cmd, options)
+ char_u *cmd;
+ int options; /* SHELL_*, see vim.h */
+{
+ BPTR mydir;
+ int x;
+ int tmode = cur_tmode;
+#ifdef AZTEC_C
+ int use_execute;
+ char_u *shellcmd = NULL;
+ char_u *shellarg;
+#endif
+ int retval = 0;
+
+ if (close_win)
+ {
+ /* if Vim opened a window: Executing a shell may cause crashes */
+ EMSG(_("E360: Cannot execute shell with -f option"));
+ return -1;
+ }
+
+ if (term_console)
+ win_resize_off(); /* window resize events de-activated */
+ out_flush();
+
+ if (options & SHELL_COOKED)
+ settmode(TMODE_COOK); /* set to normal mode */
+ mydir = Lock((UBYTE *)"", (long)ACCESS_READ); /* remember current dir */
+
+#if !defined(AZTEC_C) /* not tested very much */
+ if (cmd == NULL)
+ {
+# ifdef FEAT_ARP
+ if (dos2)
+# endif
+ x = SystemTags(p_sh, SYS_UserShell, TRUE, TAG_DONE);
+# ifdef FEAT_ARP
+ else
+ x = Execute(p_sh, raw_in, raw_out);
+# endif
+ }
+ else
+ {
+# ifdef FEAT_ARP
+ if (dos2)
+# endif
+ x = SystemTags((char *)cmd, SYS_UserShell, TRUE, TAG_DONE);
+# ifdef FEAT_ARP
+ else
+ x = Execute((char *)cmd, 0L, raw_out);
+# endif
+ }
+# ifdef FEAT_ARP
+ if ((dos2 && x < 0) || (!dos2 && !x))
+# else
+ if (x < 0)
+# endif
+ {
+ MSG_PUTS(_("Cannot execute "));
+ if (cmd == NULL)
+ {
+ MSG_PUTS(_("shell "));
+ msg_outtrans(p_sh);
+ }
+ else
+ msg_outtrans(cmd);
+ msg_putchar('\n');
+ retval = -1;
+ }
+# ifdef FEAT_ARP
+ else if (!dos2 || x)
+# else
+ else if (x)
+# endif
+ {
+ if ((x = IoErr()) != 0)
+ {
+ if (!(options & SHELL_SILENT))
+ {
+ msg_putchar('\n');
+ msg_outnum((long)x);
+ MSG_PUTS(_(" returned\n"));
+ }
+ retval = x;
+ }
+ }
+#else /* else part is for AZTEC_C */
+ if (p_st >= 4 || (p_st >= 2 && !(options & SHELL_FILTER)))
+ use_execute = 1;
+ else
+ use_execute = 0;
+ if (!use_execute)
+ {
+ /*
+ * separate shell name from argument
+ */
+ shellcmd = vim_strsave(p_sh);
+ if (shellcmd == NULL) /* out of memory, use Execute */
+ use_execute = 1;
+ else
+ {
+ shellarg = skiptowhite(shellcmd); /* find start of arguments */
+ if (*shellarg != NUL)
+ {
+ *shellarg++ = NUL;
+ shellarg = skipwhite(shellarg);
+ }
+ }
+ }
+ if (cmd == NULL)
+ {
+ if (use_execute)
+ {
+# ifdef FEAT_ARP
+ if (dos2)
+# endif
+ x = SystemTags((UBYTE *)p_sh, SYS_UserShell, TRUE, TAG_DONE);
+# ifdef FEAT_ARP
+ else
+ x = !Execute((UBYTE *)p_sh, raw_in, raw_out);
+# endif
+ }
+ else
+ x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, NULL);
+ }
+ else if (use_execute)
+ {
+# ifdef FEAT_ARP
+ if (dos2)
+# endif
+ x = SystemTags((UBYTE *)cmd, SYS_UserShell, TRUE, TAG_DONE);
+# ifdef FEAT_ARP
+ else
+ x = !Execute((UBYTE *)cmd, 0L, raw_out);
+# endif
+ }
+ else if (p_st & 1)
+ x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg,
+ (char *)cmd, NULL);
+ else
+ x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg,
+ (char *)p_shcf, (char *)cmd, NULL);
+# ifdef FEAT_ARP
+ if ((dos2 && x < 0) || (!dos2 && x))
+# else
+ if (x < 0)
+# endif
+ {
+ MSG_PUTS(_("Cannot execute "));
+ if (use_execute)
+ {
+ if (cmd == NULL)
+ msg_outtrans(p_sh);
+ else
+ msg_outtrans(cmd);
+ }
+ else
+ {
+ MSG_PUTS(_("shell "));
+ msg_outtrans(shellcmd);
+ }
+ msg_putchar('\n');
+ retval = -1;
+ }
+ else
+ {
+ if (use_execute)
+ {
+# ifdef FEAT_ARP
+ if (!dos2 || x)
+# else
+ if (x)
+# endif
+ x = IoErr();
+ }
+ else
+ x = wait();
+ if (x)
+ {
+ if (!(options & SHELL_SILENT) && !emsg_silent)
+ {
+ msg_putchar('\n');
+ msg_outnum((long)x);
+ MSG_PUTS(_(" returned\n"));
+ }
+ retval = x;
+ }
+ }
+ vim_free(shellcmd);
+#endif /* AZTEC_C */
+
+ if ((mydir = CurrentDir(mydir)) != 0) /* make sure we stay in the same directory */
+ UnLock(mydir);
+ if (tmode == TMODE_RAW)
+ settmode(TMODE_RAW); /* set to raw mode */
+#ifdef FEAT_TITLE
+ resettitle();
+#endif
+ if (term_console)
+ win_resize_on(); /* window resize events activated */
+ return retval;
+}
+
+/*
+ * check for an "interrupt signal"
+ * We only react to a CTRL-C, but also clear the other break signals to avoid
+ * trouble with lattice-c programs.
+ */
+ void
+mch_breakcheck()
+{
+ if (SetSignal(0L, (long)(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)) & SIGBREAKF_CTRL_C)
+ got_int = TRUE;
+}
+
+/* this routine causes manx to use this Chk_Abort() rather than it's own */
+/* otherwise it resets our ^C when doing any I/O (even when Enable_Abort */
+/* is zero). Since we want to check for our own ^C's */
+
+#ifdef _DCC
+#define Chk_Abort chkabort
+#endif
+
+#ifdef LATTICE
+void __regargs __chkabort(void);
+
+void __regargs __chkabort(void)
+{}
+
+#else
+ long
+Chk_Abort(void)
+{
+ return(0L);
+}
+#endif
+
+/*
+ * mch_expandpath() - this code does wild-card pattern matching using the arp
+ * routines.
+ *
+ * "pat" has backslashes before chars that are not to be expanded.
+ * Returns the number of matches found.
+ *
+ * This is based on WildDemo2.c (found in arp1.1 distribution).
+ * That code's copyright follows:
+ * Copyright (c) 1987, Scott Ballantyne
+ * Use and abuse as you please.
+ */
+
+#define ANCHOR_BUF_SIZE (512)
+#define ANCHOR_SIZE (sizeof(struct AnchorPath) + ANCHOR_BUF_SIZE)
+
+ int
+mch_expandpath(gap, pat, flags)
+ garray_T *gap;
+ char_u *pat;
+ int flags; /* EW_* flags */
+{
+ struct AnchorPath *Anchor;
+ LONG Result;
+ char_u *starbuf, *sp, *dp;
+ int start_len;
+ int matches;
+
+ start_len = gap->ga_len;
+
+ /* Get our AnchorBase */
+ Anchor = (struct AnchorPath *)alloc_clear((unsigned)ANCHOR_SIZE);
+ if (Anchor == NULL)
+ return 0;
+
+ Anchor->ap_Strlen = ANCHOR_BUF_SIZE; /* ap_Length not supported anymore */
+#ifdef APF_DODOT
+ Anchor->ap_Flags = APF_DODOT | APF_DOWILD; /* allow '.' for current dir */
+#else
+ Anchor->ap_Flags = APF_DoDot | APF_DoWild; /* allow '.' for current dir */
+#endif
+
+#ifdef FEAT_ARP
+ if (dos2)
+ {
+#endif
+ /* hack to replace '*' by '#?' */
+ starbuf = alloc((unsigned)(2 * STRLEN(pat) + 1));
+ if (starbuf == NULL)
+ goto Return;
+ for (sp = pat, dp = starbuf; *sp; ++sp)
+ {
+ if (*sp == '*')
+ {
+ *dp++ = '#';
+ *dp++ = '?';
+ }
+ else
+ *dp++ = *sp;
+ }
+ *dp = NUL;
+ Result = MatchFirst((UBYTE *)starbuf, Anchor);
+ vim_free(starbuf);
+#ifdef FEAT_ARP
+ }
+ else
+ Result = FindFirst((char *)pat, Anchor);
+#endif
+
+ /*
+ * Loop to get all matches.
+ */
+ while (Result == 0)
+ {
+ addfile(gap, (char_u *)Anchor->ap_Buf, flags);
+#ifdef FEAT_ARP
+ if (dos2)
+#endif
+ Result = MatchNext(Anchor);
+#ifdef FEAT_ARP
+ else
+ Result = FindNext(Anchor);
+#endif
+ }
+ matches = gap->ga_len - start_len;
+
+ if (Result == ERROR_BUFFER_OVERFLOW)
+ EMSG(_("ANCHOR_BUF_SIZE too small."));
+ else if (matches == 0 && Result != ERROR_OBJECT_NOT_FOUND
+ && Result != ERROR_DEVICE_NOT_MOUNTED
+ && Result != ERROR_NO_MORE_ENTRIES)
+ EMSG(_("I/O ERROR"));
+
+ /*
+ * Sort the files for this pattern.
+ */
+ if (matches)
+ qsort((void *)(((char_u **)gap->ga_data) + start_len),
+ (size_t)matches, sizeof(char_u *), sortcmp);
+
+ /* Free the wildcard stuff */
+#ifdef FEAT_ARP
+ if (dos2)
+#endif
+ MatchEnd(Anchor);
+#ifdef FEAT_ARP
+ else
+ FreeAnchorChain(Anchor);
+#endif
+
+Return:
+ vim_free(Anchor);
+
+ return matches;
+}
+
+ static int
+sortcmp(a, b)
+ const void *a, *b;
+{
+ char *s = *(char **)a;
+ char *t = *(char **)b;
+
+ return pathcmp(s, t);
+}
+
+/*
+ * Return TRUE if "p" has wildcards that can be expanded by mch_expandpath().
+ */
+ int
+mch_has_exp_wildcard(p)
+ char_u *p;
+{
+ for ( ; *p; ++p)
+ {
+ if (*p == '\\' && p[1] != NUL)
+ ++p;
+ else if (vim_strchr((char_u *)"*?[(#", *p) != NULL)
+ return TRUE;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ return FALSE;
+}
+
+ int
+mch_has_wildcard(p)
+ char_u *p;
+{
+ for ( ; *p; ++p)
+ {
+ if (*p == '\\' && p[1] != NUL)
+ ++p;
+ else
+ if (vim_strchr((char_u *)
+# ifdef VIM_BACKTICK
+ "*?[(#$`"
+# else
+ "*?[(#$"
+# endif
+ , *p) != NULL
+ || (*p == '~' && p[1] != NUL))
+ return TRUE;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ return FALSE;
+}
+
+/*
+ * With AmigaDOS 2.0 support for reading local environment variables
+ *
+ * Two buffers are allocated:
+ * - A big one to do the expansion into. It is freed before returning.
+ * - A small one to hold the return value. It is kept until the next call.
+ */
+ char_u *
+mch_getenv(var)
+ char_u *var;
+{
+ int len;
+ UBYTE *buf; /* buffer to expand in */
+ char_u *retval; /* return value */
+ static char_u *alloced = NULL; /* allocated memory */
+
+#ifdef FEAT_ARP
+ if (!dos2)
+ retval = (char_u *)getenv((char *)var);
+ else
+#endif
+ {
+ vim_free(alloced);
+ alloced = NULL;
+ retval = NULL;
+
+ buf = alloc(IOSIZE);
+ if (buf == NULL)
+ return NULL;
+
+ len = GetVar((UBYTE *)var, buf, (long)(IOSIZE - 1), (long)0);
+ if (len >= 0)
+ {
+ retval = vim_strsave((char_u *)buf);
+ alloced = retval;
+ }
+
+ vim_free(buf);
+ }
+
+ /* if $VIM is not defined, use "vim:" instead */
+ if (retval == NULL && STRCMP(var, "VIM") == 0)
+ retval = (char_u *)"vim:";
+
+ return retval;
+}
+
+/*
+ * Amiga version of setenv() with AmigaDOS 2.0 support.
+ */
+/* ARGSUSED */
+ int
+mch_setenv(var, value, x)
+ char *var;
+ char *value;
+ int x;
+{
+#ifdef FEAT_ARP
+ if (!dos2)
+ return setenv(var, value);
+#endif
+
+ if (SetVar((UBYTE *)var, (UBYTE *)value, (LONG)-1, (ULONG)GVF_LOCAL_ONLY))
+ return 0; /* success */
+ return -1; /* failure */
+}
diff --git a/src/os_amiga.h b/src/os_amiga.h
new file mode 100644
index 000000000..06e4d1cb9
--- /dev/null
+++ b/src/os_amiga.h
@@ -0,0 +1,201 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * Amiga Machine-dependent things
+ */
+
+#define CASE_INSENSITIVE_FILENAME /* ignore case when comparing file names */
+#define SPACE_IN_FILENAME
+#define USE_FNAME_CASE /* adjust case of file names */
+#define USE_TERM_CONSOLE
+#define HAVE_AVAIL_MEM
+
+#ifndef HAVE_CONFIG_H
+# ifdef AZTEC_C
+# define HAVE_STAT_H
+# endif
+# define HAVE_STDLIB_H
+# define HAVE_STRING_H
+# define HAVE_FCNTL_H
+# define HAVE_STRCSPN
+# define HAVE_STRICMP
+# define HAVE_STRNICMP
+# define HAVE_STRFTIME /* guessed */
+# define HAVE_SETENV
+# define HAVE_MEMSET
+# define HAVE_QSORT
+# if defined(__DATE__) && defined(__TIME__)
+# define HAVE_DATE_TIME
+# endif
+
+#define DFLT_ERRORFILE "AztecC.Err"
+#define DFLT_RUNTIMEPATH "home:vimfiles,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,home:vimfiles/after"
+
+#define BASENAMELEN 26 /* Amiga */
+
+#define TEMPNAME "t:v?XXXXXX"
+#define TEMPNAMELEN 12
+
+#endif /* HAVE_CONFIG_H */
+
+#include <exec/types.h>
+#include <libraries/dos.h>
+#include <libraries/dosextens.h>
+
+/* Currently, all Amiga compilers except AZTEC C have these... */
+#ifndef AZTEC_C
+# include <proto/exec.h>
+# include <proto/dos.h>
+# include <proto/intuition.h>
+#endif
+
+#define FNAME_ILLEGAL ";*?`#%" /* illegal characters in a file name */
+
+/*
+ * Manx doesn't have off_t, define it here.
+ */
+#ifdef AZTEC_C
+typedef long off_t;
+#endif
+
+#ifdef LATTICE
+# define USE_TMPNAM /* use tmpnam() instead of mktemp() */
+#endif
+
+#ifdef __GNUC__
+# include <sys/stat.h>
+# include <unistd.h>
+#endif
+
+/*
+ * arpbase.h must be included before functions.h
+ */
+#ifdef FEAT_ARP
+# include <libraries/arpbase.h>
+#endif
+
+/*
+ * This won't be needed if you have a version of Lattice 4.01 without broken
+ * break signal handling.
+ */
+#include <signal.h>
+
+/*
+ * Names for the EXRC, HELP and temporary files.
+ * Some of these may have been defined in the makefile.
+ */
+#ifndef SYS_VIMRC_FILE
+# define SYS_VIMRC_FILE "$VIM/vimrc"
+#endif
+#ifndef SYS_GVIMRC_FILE
+# define SYS_GVIMRC_FILE "$VIM/gvimrc"
+#endif
+#ifndef SYS_MENU_FILE
+# define SYS_MENU_FILE "$VIMRUNTIME/menu.vim"
+#endif
+#ifndef DFLT_HELPFILE
+# define DFLT_HELPFILE "$VIMRUNTIME/doc/help.txt"
+#endif
+#ifndef FILETYPE_FILE
+# define FILETYPE_FILE "filetype.vim"
+#endif
+#ifndef FTPLUGIN_FILE
+# define FTPLUGIN_FILE "ftplugin.vim"
+#endif
+#ifndef INDENT_FILE
+# define INDENT_FILE "indent.vim"
+#endif
+#ifndef FTOFF_FILE
+# define FTOFF_FILE "ftoff.vim"
+#endif
+#ifndef FTPLUGOF_FILE
+# define FTPLUGOF_FILE "ftplugof.vim"
+#endif
+#ifndef INDOFF_FILE
+# define INDOFF_FILE "indoff.vim"
+#endif
+#ifndef SYNTAX_FNAME
+# define SYNTAX_FNAME "$VIMRUNTIME/syntax/%s.vim"
+#endif
+
+#ifndef USR_EXRC_FILE
+# define USR_EXRC_FILE "s:.exrc"
+#endif
+#ifndef USR_EXRC_FILE2
+# define USR_EXRC_FILE2 "home:.exrc"
+#endif
+
+#ifndef USR_VIMRC_FILE
+# define USR_VIMRC_FILE "s:.vimrc"
+#endif
+#ifndef USR_VIMRC_FILE2
+# define USR_VIMRC_FILE2 "home:.vimrc"
+#endif
+#ifndef USR_VIMRC_FILE3
+# define USR_VIMRC_FILE3 "$VIM/.vimrc"
+#endif
+#ifndef EVIM_FILE
+# define EVIM_FILE "$VIMRUNTIME/evim.vim"
+#endif
+
+#ifndef USR_GVIMRC_FILE
+# define USR_GVIMRC_FILE "s:.gvimrc"
+#endif
+#ifndef USR_GVIMRC_FILE2
+# define USR_GVIMRC_FILE2 "home:.gvimrc"
+#endif
+#ifndef USR_GVIMRC_FILE3
+# define USR_GVIMRC_FILE3 "$VIM/.gvimrc"
+#endif
+
+#ifdef FEAT_VIMINFO
+#ifndef VIMINFO_FILE
+# define VIMINFO_FILE "s:.viminfo"
+#endif
+#endif /* FEAT_VIMINFO */
+
+#ifndef EXRC_FILE
+# define EXRC_FILE ".exrc"
+#endif
+
+#ifndef VIMRC_FILE
+# define VIMRC_FILE ".vimrc"
+#endif
+
+#ifndef GVIMRC_FILE
+# define GVIMRC_FILE ".gvimrc"
+#endif
+
+#ifndef DFLT_BDIR
+# define DFLT_BDIR ".,t:" /* default for 'backupdir' */
+#endif
+
+#ifndef DFLT_DIR
+# define DFLT_DIR ".,t:" /* default for 'directory' */
+#endif
+
+#ifndef DFLT_VDIR
+# define DFLT_VDIR "$VIM/vimfiles/view" /* default for 'viewdir' */
+#endif
+
+#ifndef DFLT_MAXMEM
+# define DFLT_MAXMEM 256 /* use up to 256Kbyte for buffer */
+#endif
+#ifndef DFLT_MAXMEMTOT
+# define DFLT_MAXMEMTOT 0 /* decide in set_init */
+#endif
+
+#if defined(SASC)
+int setenv(const char *, const char *);
+#endif
+
+#define mch_remove(x) remove((char *)(x))
+#define mch_rename(src, dst) rename(src, dst)
+#define mch_chdir(s) chdir(s)
+#define vim_mkdir(x, y) mch_mkdir(x)
diff --git a/src/os_beos.c b/src/os_beos.c
new file mode 100644
index 000000000..e492cab45
--- /dev/null
+++ b/src/os_beos.c
@@ -0,0 +1,206 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * BeBox port Copyright 1997 by Olaf Seibert.
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * os_beos.c Additional stuff for BeOS (rest is in os_unix.c)
+ */
+
+#include <float.h>
+#include <termios.h>
+#include <kernel/OS.h>
+#include "vim.h"
+
+#if USE_THREAD_FOR_INPUT_WITH_TIMEOUT
+
+#ifdef PROTO /* making prototypes on Unix */
+#define sem_id int
+#define thread_id int
+#endif
+
+char_u charbuf;
+signed char charcount;
+sem_id character_present;
+sem_id character_wanted;
+thread_id read_thread_id;
+
+#define TRY_ABORT 0 /* This code does not work so turn it off. */
+
+#if TRY_ABORT
+ static void
+mostly_ignore(int sig)
+{
+}
+#endif
+
+ static long
+read_thread(void *dummy)
+{
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+#if TRY_ABORT
+ signal(SIGUSR1, mostly_ignore);
+#endif
+
+ for (;;) {
+ if (acquire_sem(character_wanted) != B_NO_ERROR)
+ break;
+ charcount = read(read_cmd_fd, &charbuf, 1);
+ release_sem(character_present);
+ }
+
+ return 0;
+}
+
+ void
+beos_cleanup_read_thread(void)
+{
+ if (character_present > 0)
+ delete_sem(character_present);
+ character_present = 0;
+ if (read_thread_id > 0)
+ kill_thread(read_thread_id);
+ read_thread_id = 0;
+}
+
+#endif
+
+/*
+ * select() emulation. Hopefully, in DR9 there will be something
+ * useful supplied by the system. ... Alas, not. Not in AAPR, nor
+ * in PR or even PR2... R3 then maybe? I don't think so!
+ */
+
+ int
+beos_select(int nbits,
+ struct fd_set *rbits,
+ struct fd_set *wbits,
+ struct fd_set *ebits,
+ struct timeval *timeout)
+{
+ bigtime_t tmo;
+
+ if (nbits == 0) {
+ /* select is purely being used for delay */
+ snooze(timeout->tv_sec * 1e6 + timeout->tv_usec);
+ return 0;
+ }
+#if 0
+ /*
+ * This does not seem to work either. Reads here are not supposed to
+ * block indefinitely, yet they do. This is most annoying.
+ */
+ if (FD_ISSET(0, rbits)) {
+ char cbuf[1];
+ int count;
+ struct termios told;
+ struct termios tnew;
+ tcgetattr(0, &told);
+ tnew = told;
+ tnew.c_lflag &= ~ICANON;
+ tnew.c_cc[VMIN] = 0;
+ tnew.c_cc[VTIME] = timeout->tv_sec * 10 + timeout->tv_usec / 100000;
+ tcsetattr(0, TCSANOW, &tnew);
+
+ count = read(0, &cbuf, sizeof(cbuf));
+ tcsetattr(0, TCSANOW, &told);
+ if (count > 0) {
+ add_to_input_buf(&cbuf[0], count);
+ return 1;
+ }
+ return 0;
+ }
+#endif
+#if USE_THREAD_FOR_INPUT_WITH_TIMEOUT
+ /*
+ * Check if the operation is really on stdin...
+ */
+ if (FD_ISSET(read_cmd_fd, rbits))
+ {
+ int acquired;
+
+ /*
+ * Is this the first time through?
+ * Then start up the thread and initialise the semaphores.
+ */
+ if (character_present == 0) {
+ character_present = create_sem(0, "vim character_present");
+ character_wanted = create_sem(1, "vim character_wanted");
+ read_thread_id = spawn_thread(read_thread, "vim async read",
+ B_NORMAL_PRIORITY, NULL);
+ atexit(beos_cleanup_read_thread);
+ resume_thread(read_thread_id);
+ }
+
+ /* timeout == NULL means "indefinitely" */
+ if (timeout) {
+ tmo = timeout->tv_sec * 1e6 + timeout->tv_usec;
+ /* 0 means "don't wait, which is impossible to do exactly. */
+ if (tmo == 0)
+ tmo = 1.0;
+ }
+#if TRY_ABORT
+ release_sem(character_wanted);
+#endif
+ if (timeout)
+ acquired = acquire_sem_etc(character_present, 1, B_TIMEOUT, tmo);
+ else
+ acquired = acquire_sem(character_present);
+ if (acquired == B_NO_ERROR) {
+ if (charcount > 0) {
+ add_to_input_buf(&charbuf, 1);
+#if !TRY_ABORT
+ release_sem(character_wanted);
+#endif
+
+ return 1;
+ } else {
+#if !TRY_ABORT
+ release_sem(character_wanted);
+#endif
+
+ return 0;
+ }
+ }
+#if TRY_ABORT
+ else {
+ /*
+ * Timeout occurred. Break the read() call by sending
+ * a signal. Problem: it may be just read()ing it now.
+ * Therefore we still have to finish the handshake with
+ * the thread and maybe remember the character.
+ */
+ kill(read_thread_id, SIGUSR1);
+ /*
+ * If some other error occurred, don't hang now.
+ * (We will most likely hang later anyway...)
+ */
+ if (acquired == B_TIMED_OUT)
+ acquire_sem(character_present);
+ if (charcount > 0) {
+ add_to_input_buf(&charbuf, 1);
+ return 1;
+ }
+ return 0;
+ }
+#endif
+ }
+#endif
+
+#if FEAT_GUI_BEOS
+ /*
+ * If not reading from terminal, pretend there is input.
+ * This makes the pty reading (for the GUI) "work" for
+ * :!ls but not for :r !ls ... weird.
+ */
+ if (gui.in_use && State == EXTERNCMD)
+ return 1;
+#endif
+ return 0;
+}
+
diff --git a/src/os_beos.h b/src/os_beos.h
new file mode 100644
index 000000000..260834e60
--- /dev/null
+++ b/src/os_beos.h
@@ -0,0 +1,25 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * BeBox port by Olaf Seibert
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * os_beos.h
+ */
+
+#undef USE_SYSTEM
+#define USE_THREAD_FOR_INPUT_WITH_TIMEOUT 1
+#define USE_TERM_CONSOLE
+
+#define HAVE_DROP_FILE
+
+#undef BEOS_DR8
+#define BEOS_PR_OR_BETTER
+
+/* select emulation */
+
+#include <net/socket.h> /* for typedefs and #defines only */
diff --git a/src/os_beos.rsrc b/src/os_beos.rsrc
new file mode 100644
index 000000000..f6443cd60
--- /dev/null
+++ b/src/os_beos.rsrc
Binary files differ
diff --git a/src/os_dos.h b/src/os_dos.h
new file mode 100644
index 000000000..103cded5a
--- /dev/null
+++ b/src/os_dos.h
@@ -0,0 +1,125 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * Common MS-DOS and Win32 (Windows NT and Windows 95) defines.
+ *
+ * Names for the EXRC, HELP and temporary files.
+ * Some of these may have been defined in the makefile or feature.h.
+ */
+
+#ifndef SYS_VIMRC_FILE
+# define SYS_VIMRC_FILE "$VIM\\vimrc"
+#endif
+#ifndef USR_VIMRC_FILE
+# define USR_VIMRC_FILE "$HOME\\_vimrc"
+#endif
+#ifndef USR_VIMRC_FILE2
+# define USR_VIMRC_FILE2 "$VIM\\_vimrc"
+#endif
+#ifndef EVIM_FILE
+# define EVIM_FILE "$VIMRUNTIME\\evim.vim"
+#endif
+
+#ifndef USR_EXRC_FILE
+# define USR_EXRC_FILE "$HOME\\_exrc"
+#endif
+#ifndef USR_EXRC_FILE2
+# define USR_EXRC_FILE2 "$VIM\\_exrc"
+#endif
+
+#ifdef FEAT_GUI
+# ifndef SYS_GVIMRC_FILE
+# define SYS_GVIMRC_FILE "$VIM\\gvimrc"
+# endif
+# ifndef USR_GVIMRC_FILE
+# define USR_GVIMRC_FILE "$HOME\\_gvimrc"
+# endif
+# ifndef USR_GVIMRC_FILE2
+# define USR_GVIMRC_FILE2 "$VIM\\_gvimrc"
+# endif
+# ifndef SYS_MENU_FILE
+# define SYS_MENU_FILE "$VIMRUNTIME\\menu.vim"
+# endif
+#endif
+
+#ifndef SYS_OPTWIN_FILE
+# define SYS_OPTWIN_FILE "$VIMRUNTIME\\optwin.vim"
+#endif
+
+#ifdef FEAT_VIMINFO
+# ifndef VIMINFO_FILE
+# define VIMINFO_FILE "$HOME\\_viminfo"
+# endif
+# ifndef VIMINFO_FILE2
+# define VIMINFO_FILE2 "$VIM\\_viminfo"
+# endif
+#endif
+
+#ifndef VIMRC_FILE
+# define VIMRC_FILE "_vimrc"
+#endif
+
+#ifndef EXRC_FILE
+# define EXRC_FILE "_exrc"
+#endif
+
+#ifdef FEAT_GUI
+# ifndef GVIMRC_FILE
+# define GVIMRC_FILE "_gvimrc"
+# endif
+#endif
+
+#ifndef DFLT_HELPFILE
+# define DFLT_HELPFILE "$VIMRUNTIME\\doc\\help.txt"
+#endif
+
+#ifndef FILETYPE_FILE
+# define FILETYPE_FILE "filetype.vim"
+#endif
+#ifndef FTPLUGIN_FILE
+# define FTPLUGIN_FILE "ftplugin.vim"
+#endif
+#ifndef INDENT_FILE
+# define INDENT_FILE "indent.vim"
+#endif
+#ifndef FTOFF_FILE
+# define FTOFF_FILE "ftoff.vim"
+#endif
+#ifndef FTPLUGOF_FILE
+# define FTPLUGOF_FILE "ftplugof.vim"
+#endif
+#ifndef INDOFF_FILE
+# define INDOFF_FILE "indoff.vim"
+#endif
+
+#ifndef SYNTAX_FNAME
+# define SYNTAX_FNAME "$VIMRUNTIME\\syntax\\%s.vim"
+#endif
+
+#ifndef DFLT_BDIR
+# define DFLT_BDIR ".,c:\\tmp,c:\\temp" /* default for 'backupdir' */
+#endif
+
+#ifndef DFLT_VDIR
+# define DFLT_VDIR "$VIM/vimfiles/view" /* default for 'viewdir' */
+#endif
+
+#ifndef DFLT_DIR
+# define DFLT_DIR ".,c:\\tmp,c:\\temp" /* default for 'directory' */
+#endif
+
+#define DFLT_ERRORFILE "errors.err"
+#define DFLT_RUNTIMEPATH "$HOME/vimfiles,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,$HOME/vimfiles/after"
+
+#define CASE_INSENSITIVE_FILENAME /* ignore case when comparing file names */
+#define SPACE_IN_FILENAME
+#define BACKSLASH_IN_FILENAME
+#define USE_CRNL /* lines end in CR-NL instead of NL */
+#define HAVE_DUP /* have dup() */
+#define HAVE_ST_MODE /* have stat.st_mode */
diff --git a/src/os_mac.build b/src/os_mac.build
new file mode 100644
index 000000000..014c037de
--- /dev/null
+++ b/src/os_mac.build
@@ -0,0 +1,91 @@
+set 68kTarget "68k"
+set ppcTarget "ppc"
+set carbonTarget "carbon"
+set vimTargets "`getlistitem -m " Select the vim target platform" -c -q "{68kTarget}" "{ppcTarget}" "{carbonTarget}"`"
+if !"{vimTargets}"
+ echo "No Makefile created"
+ exit 0
+end
+#
+set generalSources "buffer.c charset.c diff.c digraph.c edit.c eval.c ex_cmds.c ex_cmds2.c ex_docmd.c ex_eval.c ex_getln.c fileio.c fold.c getchar.c gui.c gui_mac.c if_cscope.c main.c mark.c memfile.c memline.c menu.c message.c misc1.c misc2.c move.c mbyte.c normal.c ops.c option.c os_mac.c pty.c quickfix.c regexp.c screen.c search.c tag.c term.c termlib.c ui.c undo.c version.c window.c"
+set generalOpts "-app -c 'VIM!' -t 'APPL' -i :proto"
+set generalCOpts "-w 2,35 -enum int"
+set generalLOpts "-mf -d"
+set generalLibs ""
+#
+#
+set 68kSources ""
+set 68kOpts "-model far"
+set 68kCOpts ""
+set 68kLOpts ""
+set 68kLibs ""
+#
+set ppcSources "syntax.c"
+set ppcOpts "-powerpc"
+set ppcCOpts ""
+set ppcLOpts "{SharedLibraries}AppearanceLib"
+set ppcLibs "{SharedLibraries}ContextualMenu"
+#
+set carbonSources ""
+set carbonOpts "-carbon"
+set carbonCOpts "-d TARGET_API_MAC_CARBON"
+set carbonLOpts ""
+set carbonLibs "{SharedLibraries}CarbonLib"
+#
+for vTarget in {vimTargets}
+ set vSources "{generalSources}"
+ set vLibs "{generalLibs}"
+ set vOpts "{generalOpts}"
+ set vCOpts "{generalCOpts}"
+ set vLOpts "{generalLOpts}"
+ set ppc ""
+ if "{vTarget}" == "{68kTarget}"
+ set vSources "{vSources} {68kSources}"
+ set vOpts "{vOpts} {68kOpts}"
+ set vLibs "{vLibs} {68kLibs}"
+ if "{68kCOpts}"
+ set vCOpts "{vCOpts} {68kCOpts}"
+ end
+ if "{68kLOpts}"
+ set vLOpts "{vLOpts} {68kLOpts}"
+ end
+ else
+ set ppc "ppc"
+ set vSources "{vSources} {ppcSources}"
+ set vOpts "{vOpts} {ppcOpts}"
+ set vLibs "{vLibs} {ppcLibs}"
+ if "{ppcCOpts}"
+ set vCOpts "{vCOpts} {ppcCOpts}"
+ end
+ if "{ppcLOpts}"
+ set vLOpts "{vLOpts} {ppcLOpts}"
+ end
+ if "{vTarget}" == "{carbonTarget}"
+ set vSources "{vSources} {carbonSources}"
+ set vLibs "{vLibs} {carbonLibs}"
+ set vOpts "{vOpts} {carbonOpts}"
+ if "{carbonCOpts}"
+ set vCOpts "{vCOpts} {carbonCOpts}"
+ end
+ if "{carbonLOpts}"
+ set vLOpts "{vLOpts} {carbonLOpts}"
+ end
+ end
+ end
+ set vODir :obj-{vTarget}:
+ if !"`exists -d {vOdir}`"
+ newFolder {vODir}
+ end
+ set vApp vim-{vTarget}
+ if "{vCOpts}"
+ set vOpts "{vOpts} -{ppc}COptions '{vCOpts}'"
+ end
+ if "{vLOpts}"
+ set vOpts "{vOpts} -{ppc}LinkOptions '{vLOpts}'"
+ end
+ set vOpts "{vOpts} -objdir {vODir}"
+ createmake {vApp} {vOpts} {vSources} {vLibs}
+ if !{Status}
+ echo "Makefile for {vApp} successfully created"
+ end
+end
diff --git a/src/os_mac.c b/src/os_mac.c
new file mode 100644
index 000000000..0f6a76ceb
--- /dev/null
+++ b/src/os_mac.c
@@ -0,0 +1,1451 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * os_mac.c -- code for the MacOS
+ *
+ * This file is mainly based on os_unix.c.
+ */
+
+#include "vim.h"
+
+#if defined(__MRC__) || defined(__SC__) /* for Apple MPW Compilers */
+
+#include "StandardFile.h"
+
+/*
+ * Implements the corresponding unix function
+ */
+ int
+stat(
+ char *p,
+ struct stat *p_st)
+{
+ /*
+ TODO: Use functions which fill the FileParam struct (Files.h)
+ and copy these contents to our self-defined stat struct
+ */
+ return 0;
+}
+#endif
+
+/*
+ * change the current working directory
+ */
+ int
+mch_chdir(char *p_name)
+{
+#if defined(__MRC__) || defined(__SC__) /* for Apple MPW Compilers */
+ /* TODO */
+ return FAIL;
+#else
+ return chdir(p_name);
+#endif
+}
+
+
+/*
+ * Recursively build up a list of files in "gap" matching the first wildcard
+ * in `path'. Called by mch_expandpath().
+ * "path" has backslashes before chars that are not to be expanded.
+ */
+ int
+mac_expandpath(
+ garray_T *gap,
+ char_u *path,
+ int flags, /* EW_* flags */
+ short start_at,
+ short as_full)
+{
+ /*
+ * TODO:
+ * +Get Volumes (when looking for files in current dir)
+ * +Make it work when working dir not on select volume
+ * +Cleanup
+ */
+ short index = 1;
+ OSErr gErr;
+ char_u dirname[256];
+ char_u cfilename[256];
+ long dirID;
+ char_u *new_name;
+ CInfoPBRec gMyCPB;
+ HParamBlockRec gMyHPBlock;
+ FSSpec usedDir;
+
+ char_u *buf;
+ char_u *p, *s, *e, dany;
+ int start_len, c;
+ char_u *pat;
+ regmatch_T regmatch;
+
+ start_len = gap->ga_len;
+ buf = alloc(STRLEN(path) + BASENAMELEN + 5);/* make room for file name */
+ if (buf == NULL)
+ return 0;
+
+/*
+ * Find the first part in the path name that contains a wildcard.
+ * Copy it into buf, including the preceding characters.
+ */
+ p = buf;
+ s = buf;
+ e = NULL;
+#if 1
+ STRNCPY(buf, path, start_at);
+ p += start_at;
+ path += start_at;
+#endif
+
+ while (*path)
+ {
+ if (*path == ':')
+ {
+ if (e)
+ break;
+ else
+ s = p + 1;
+ }
+ /* should use WILCARDLIST but what about ` */
+ /* if (vim_strchr((char_u *)"*?[{~$", *path) != NULL)*/
+ else if (vim_strchr((char_u *)WILDCHAR_LIST, *path) != NULL)
+ e = p;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int len = (*mb_ptr2len_check)(path);
+
+ STRNCPY(p, path, len);
+ p += len;
+ path += len;
+ }
+ else
+#endif
+ *p++ = *path++;
+ }
+ e = p;
+
+ /* now we have one wildcard component between s and e */
+ *e = NUL;
+
+#if 1
+ dany = *s;
+ *s = NUL;
+ backslash_halve(buf);
+ *s = dany;
+#endif
+
+ /* convert the file pattern to a regexp pattern */
+ pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
+ if (pat == NULL)
+ {
+ vim_free(buf);
+ return 0;
+ }
+
+ /* compile the regexp into a program */
+ regmatch.rm_ic = FALSE; /* Don't ever ignore case */
+ regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
+ vim_free(pat);
+
+ if (regmatch.regprog == NULL)
+ {
+ vim_free(buf);
+ return 0;
+ }
+
+ /* open the directory for scanning */
+ c = *s;
+ *s = NUL;
+
+ if (*buf == NUL)
+ {
+ as_full = TRUE;
+#if 0
+ (void) mch_dirname (&dirname[1], 254);
+ dirname[0] = STRLEN(&dirname[1]);
+#endif
+ }
+ else
+ {
+ if (*buf == ':') /* relative path */
+ {
+ (void)mch_dirname(&dirname[1], 254);
+ new_name = concat_fnames(&dirname[1], buf+1, TRUE);
+ STRCPY(&dirname[1], new_name);
+ dirname[0] = STRLEN(new_name);
+ vim_free(new_name);
+ }
+ else
+ {
+ STRCPY(&dirname[1], buf);
+ backslash_halve(&dirname[1]);
+ dirname[0] = STRLEN(buf);
+ }
+ }
+ *s = c;
+
+ FSMakeFSSpec (0, 0, dirname, &usedDir);
+
+ gMyCPB.dirInfo.ioNamePtr = dirname;
+ gMyCPB.dirInfo.ioVRefNum = usedDir.vRefNum;
+ gMyCPB.dirInfo.ioFDirIndex = 0;
+ gMyCPB.dirInfo.ioDrDirID = 0;
+
+ gErr = PBGetCatInfo(&gMyCPB, false);
+
+ gMyCPB.dirInfo.ioCompletion = NULL;
+ dirID = gMyCPB.dirInfo.ioDrDirID;
+ do
+ {
+ gMyCPB.hFileInfo.ioFDirIndex = index;
+ gMyCPB.hFileInfo.ioDirID = dirID;
+
+ gErr = PBGetCatInfo(&gMyCPB,false);
+
+ if (gErr == noErr)
+ {
+ STRNCPY (cfilename, &dirname[1], dirname[0]);
+ cfilename[dirname[0]] = 0;
+ if (vim_regexec(&regmatch, cfilename, (colnr_T)0))
+ {
+ if (s[-1] != ':')
+ {
+ /* TODO: need to copy with cleaned name */
+ STRCPY(s+1, cfilename);
+ s[0] = ':';
+ }
+ else
+ { /* TODO: need to copy with cleeaned name */
+ STRCPY(s, cfilename);
+ }
+ start_at = STRLEN(buf);
+ STRCAT(buf, path);
+ if (mch_has_exp_wildcard(path)) /* handle more wildcards */
+ (void)mac_expandpath(gap, buf, flags, start_at, FALSE);
+ else
+ {
+#ifdef DONT_ADD_PATHSEP_TO_DIR
+ if ((gMyCPB.hFileInfo.ioFlAttrib & ioDirMask) !=0 )
+ STRCAT(buf, PATHSEPSTR);
+#endif
+ addfile(gap, buf, flags);
+ }
+ }
+ if ((gMyCPB.hFileInfo.ioFlAttrib & ioDirMask) !=0 )
+ {
+ }
+ else
+ {
+ }
+ }
+ index++;
+ }
+ while (gErr == noErr);
+
+ if (as_full)
+ {
+ index = 1;
+ do
+ {
+ gMyHPBlock.volumeParam.ioNamePtr = (char_u *) dirname;
+ gMyHPBlock.volumeParam.ioVRefNum =0;
+ gMyHPBlock.volumeParam.ioVolIndex = index;
+
+ gErr = PBHGetVInfo (&gMyHPBlock,false);
+ if (gErr == noErr)
+ {
+ STRNCPY (cfilename, &dirname[1], dirname[0]);
+ cfilename[dirname[0]] = 0;
+ if (vim_regexec(&regmatch, cfilename, (colnr_T)0))
+ {
+ STRCPY(s, cfilename);
+ STRCAT(buf, path);
+ if (mch_has_exp_wildcard(path)) /* handle more wildcards */
+ (void)mac_expandpath(gap, s, flags, 0, FALSE);
+ else
+ {
+#ifdef DONT_ADD_PATHSEP_TO_DIR
+/* if ((gMyCPB.hFileInfo.ioFlAttrib & ioDirMask) !=0 )
+*/ STRCAT(buf, PATHSEPSTR);
+#endif
+ addfile(gap, s, flags);
+ }
+#if 0
+ STRCAT(cfilename, PATHSEPSTR);
+ addfile (gap, cfilename, flags);
+#endif
+ }
+ }
+ index++;
+ }
+ while (gErr == noErr);
+ }
+
+ vim_free(regmatch.regprog);
+
+ return gap->ga_len - start_len;
+}
+
+
+#ifdef USE_UNIXFILENAME
+ static int
+pstrcmp(a, b)
+ const void *a, *b;
+{
+ return (pathcmp(*(char **)a, *(char **)b));
+}
+
+ static int
+unix_expandpath(gap, path, wildoff, flags)
+ garray_T *gap;
+ char_u *path;
+ int wildoff;
+ int flags; /* EW_* flags */
+{
+ char_u *buf;
+ char_u *path_end;
+ char_u *p, *s, *e;
+ int start_len, c;
+ char_u *pat;
+ DIR *dirp;
+ regmatch_T regmatch;
+ struct dirent *dp;
+ int starts_with_dot;
+ int matches;
+ int len;
+
+ start_len = gap->ga_len;
+ buf = alloc(STRLEN(path) + BASENAMELEN + 5);/* make room for file name */
+ if (buf == NULL)
+ return 0;
+
+/*
+ * Find the first part in the path name that contains a wildcard.
+ * Copy it into buf, including the preceding characters.
+ */
+ p = buf;
+ s = buf;
+ e = NULL;
+ path_end = path;
+ while (*path_end)
+ {
+ /* May ignore a wildcard that has a backslash before it */
+ if (path_end >= path + wildoff && rem_backslash(path_end))
+ *p++ = *path_end++;
+ else if (*path_end == '/')
+ {
+ if (e != NULL)
+ break;
+ else
+ s = p + 1;
+ }
+ else if (vim_strchr((char_u *)"*?[{~$", *path_end) != NULL)
+ e = p;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ len = (*mb_ptr2len_check)(path_end);
+ STRNCPY(p, path_end, len);
+ p += len;
+ path_end += len;
+ }
+ else
+#endif
+ *p++ = *path_end++;
+ }
+ e = p;
+ *e = NUL;
+
+ /* now we have one wildcard component between s and e */
+ /* Remove backslashes between "wildoff" and the start of the wildcard
+ * component. */
+ for (p = buf + wildoff; p < s; ++p)
+ if (rem_backslash(p))
+ {
+ STRCPY(p, p + 1);
+ --e;
+ --s;
+ }
+
+ /* convert the file pattern to a regexp pattern */
+ starts_with_dot = (*s == '.');
+ pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
+ if (pat == NULL)
+ {
+ vim_free(buf);
+ return 0;
+ }
+
+ /* compile the regexp into a program */
+#ifdef MACOS_X
+ /* We want to behave like Terminal.app */
+ regmatch.rm_ic = TRUE;
+#else
+ regmatch.rm_ic = FALSE; /* Don't ever ignore case */
+#endif
+ regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
+ vim_free(pat);
+
+ if (regmatch.regprog == NULL)
+ {
+ vim_free(buf);
+ return 0;
+ }
+
+ /* open the directory for scanning */
+ c = *s;
+ *s = NUL;
+ dirp = opendir(*buf == NUL ? "." : (char *)buf);
+ *s = c;
+
+ /* Find all matching entries */
+ if (dirp != NULL)
+ {
+ for (;;)
+ {
+ dp = readdir(dirp);
+ if (dp == NULL)
+ break;
+ if ((dp->d_name[0] != '.' || starts_with_dot)
+ && vim_regexec(&regmatch, (char_u *)dp->d_name, (colnr_T)0))
+ {
+ STRCPY(s, dp->d_name);
+ len = STRLEN(buf);
+ STRCPY(buf + len, path_end);
+ if (mch_has_exp_wildcard(path_end)) /* handle more wildcards */
+ {
+ /* need to expand another component of the path */
+ /* remove backslashes for the remaining components only */
+ (void)unix_expandpath(gap, buf, len + 1, flags);
+ }
+ else
+ {
+ /* no more wildcards, check if there is a match */
+ /* remove backslashes for the remaining components only */
+ if (*path_end)
+ backslash_halve(buf + len + 1);
+ if (mch_getperm(buf) >= 0) /* add existing file */
+ addfile(gap, buf, flags);
+ }
+ }
+ }
+
+ closedir(dirp);
+ }
+
+ vim_free(buf);
+ vim_free(regmatch.regprog);
+
+ matches = gap->ga_len - start_len;
+ if (matches)
+ qsort(((char_u **)gap->ga_data) + start_len, matches,
+ sizeof(char_u *), pstrcmp);
+ return matches;
+}
+#endif
+
+/*
+ * Recursively build up a list of files in "gap" matching the first wildcard
+ * in `path'. Called by expand_wildcards().
+ * "pat" has backslashes before chars that are not to be expanded.
+ */
+ int
+mch_expandpath(
+ garray_T *gap,
+ char_u *path,
+ int flags) /* EW_* flags */
+{
+#ifdef USE_UNIXFILENAME
+ return unix_expandpath(gap, path, 0, flags);
+#else
+ char_u first = *path;
+ short scan_volume;
+
+ slash_n_colon_adjust(path);
+
+ scan_volume = (first != *path);
+
+ return mac_expandpath(gap, path, flags, 0, scan_volume);
+#endif
+}
+
+ void
+fname_case(name, len)
+ char_u *name;
+ int len; /* buffer size, ignored here */
+{
+ /*
+ * TODO: get the real casing for the file
+ * make it called
+ * with USE_FNAME_CASE & USE_LONG_FNAME
+ * CASE_INSENSITIVE_FILENAME
+ * within setfname, fix_fname, do_ecmd
+ */
+#ifdef USE_UNIXFILENAME
+ OSStatus status;
+ FSRef refFile;
+ UInt32 pathSize = STRLEN(name) + 1;
+ char_u *path;
+ Boolean isDirectory;
+
+ path = alloc(pathSize);
+ if (path == NULL)
+ return;
+
+ status = FSPathMakeRef((UInt8 *)name, &refFile, &isDirectory);
+ if (status)
+ return;
+
+ status = FSRefMakePath(&refFile, (UInt8 *)path, pathSize);
+ if (status)
+ return;
+
+ /* Paranoid: Update the name if only the casing differ.*/
+ if (STRICMP(name, path) == 0)
+ STRCPY(name, path);
+#endif
+}
+static char_u *oldtitle = (char_u *) "gVim";
+
+/*
+ * check for an "interrupt signal": CTRL-break or CTRL-C
+ */
+ void
+mch_breakcheck()
+{
+ /*
+ * TODO: Scan event for a CTRL-C or COMMAND-. and do: got_int=TRUE;
+ * or only go proccess event?
+ * or do nothing
+ */
+ EventRecord theEvent;
+
+ if (EventAvail (keyDownMask, &theEvent))
+ if ((theEvent.message & charCodeMask) == Ctrl_C && ctrl_c_interrupts)
+ got_int = TRUE;
+#if 0
+ short i = 0;
+ Boolean found = false;
+ EventRecord theEvent;
+
+ while ((i < 10) && (!found))
+ {
+ found = EventAvail (keyDownMask, &theEvent);
+ if (found)
+ {
+ if ((theEvent.modifiers & controlKey) != 0)
+ found = false;
+ if ((theEvent.what == keyDown))
+ found = false;
+ if ((theEvent.message & charCodeMask) == Ctrl_C)
+ {
+ found = false;
+ got_int = TRUE;
+ }
+ }
+ i++;
+ }
+#endif
+
+}
+
+/*
+ * Return amount of memory currently available.
+ */
+ long_u
+mch_avail_mem(special)
+ int special;
+{
+ /*
+ * TODO: Use MaxBlock, FreeMeM, PurgeSpace, MaxBlockSys FAQ-266
+ * figure out what the special is for
+ *
+ * FreeMem -> returns all avail memory is application heap
+ * MaxBlock -> returns the biggest contigeous block in application heap
+ * PurgeSpace ->
+ */
+ return MaxBlock();
+}
+
+ void
+mch_delay(msec, ignoreinput)
+ long msec;
+ int ignoreinput;
+{
+#if (defined(__MWERKS__) && __MWERKS__ >= 0x2000) \
+ || defined(__MRC__) || defined(__SC__)
+ unsigned
+#endif
+ long finalTick;
+
+ if (ignoreinput)
+ Delay (60*msec/1000, &finalTick);
+ else
+ /* even thougth we should call gui stuff from here
+ it the simplest way to be safe */
+ gui_mch_wait_for_chars(msec);
+}
+
+ void
+mch_init()
+{
+ /*
+ * TODO: Verify if needed, or override later.
+ */
+ Columns = 80;
+ Rows = 24;
+}
+
+/*
+ * Check_win checks whether we have an interactive stdout.
+ */
+ int
+mch_check_win(argc, argv)
+ int argc;
+ char **argv;
+{
+ /*
+ * TODO: Maybe to be remove through NO_CONSOLE
+ */
+ return OK;
+}
+
+/*
+ * Return TRUE if the input comes from a terminal, FALSE otherwise.
+ */
+ int
+mch_input_isatty()
+{
+ /*
+ * TODO: Maybe to be remove through NO_CONSOLE
+ */
+ return OK;
+}
+
+#ifdef FEAT_TITLE
+/*
+ * Set the window title and icon.
+ * (The icon is not taken care of).
+ */
+ void
+mch_settitle(title, icon)
+ char_u *title;
+ char_u *icon;
+{
+ gui_mch_settitle(title, icon);
+}
+
+/*
+ * Restore the window/icon title.
+ * which is one of:
+ * 1 Just restore title
+ * 2 Just restore icon
+ * 3 Restore title and icon
+ * but don't care about the icon.
+ */
+ void
+mch_restore_title(which)
+ int which;
+{
+ mch_settitle((which & 1) ? oldtitle : NULL, NULL);
+}
+#endif
+
+/*
+ * Insert user name in s[len].
+ * Return OK if a name found.
+ */
+ int
+mch_get_user_name(s, len)
+ char_u *s;
+ int len;
+{
+#if !(defined(__MRC__) || defined(__SC__)) /* No solution yet */
+ /*
+ * TODO: clean up and try getlogin ()
+ */
+#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
+ struct passwd *pw;
+#endif
+ uid_t uid;
+
+ uid = getuid();
+#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
+ if ((pw = getpwuid(uid)) != NULL
+ && pw->pw_name != NULL && *(pw->pw_name) != NUL)
+ {
+ STRNCPY(s, pw->pw_name, len);
+ return OK;
+ }
+#endif
+ sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
+#endif
+ return FAIL; /* a number is not a name */
+}
+
+/*
+ * Copy host name into s[len].
+ */
+ void
+mch_get_host_name(s, len)
+ char_u *s;
+ int len;
+{
+#if defined(__MRC__) || defined(__SC__) || defined(__APPLE_CC__)
+ STRNCPY(s, "Mac", len); /* TODO: use Gestalt information */
+#else
+ struct utsname vutsname;
+
+ if (uname(&vutsname) < 0)
+ *s = NUL;
+ else
+ STRNCPY(s, vutsname.nodename, len);
+#endif
+ s[len - 1] = NUL; /* make sure it's terminated */
+}
+
+/*
+ * return process ID
+ */
+ long
+mch_get_pid()
+{
+ return (long)getpid();
+}
+
+/*
+ * Get name of current directory into buffer 'buf' of length 'len' bytes.
+ * Return OK for success, FAIL for failure.
+ */
+ int
+mch_dirname(buf, len)
+ char_u *buf;
+ int len;
+{
+#if defined(__MRC__) || defined(__SC__)
+ return FAIL; /* No solution yet */
+#else
+ /* The last : is already put by getcwd */
+ if (getcwd((char *)buf, len) == NULL)
+ {
+ STRCPY(buf, strerror(errno));
+ return FAIL;
+ }
+# ifndef USE_UNIXFILENAME
+ else if (*buf != NUL && buf[STRLEN(buf) - 1] == ':')
+ buf[STRLEN(buf) - 1] = NUL; /* remove trailing ':' */
+# endif
+ return OK;
+#endif
+}
+
+ void
+slash_to_colon(p)
+ char_u *p;
+{
+ for ( ; *p; ++p)
+ if (*p == '/')
+ *p = ':';
+}
+
+ char_u *
+slash_to_colon_save (p)
+ char_u *p;
+{
+ char_u *res;
+
+ res = vim_strsave(p);
+ if (res == NULL)
+ return p;
+ slash_to_colon(res);
+ return res;
+}
+
+ void
+slash_n_colon_adjust (buf)
+ char_u *buf;
+{
+ /*
+ * TODO: Make it faster
+ */
+#ifndef USE_UNIXFILENAME
+ char_u temp[MAXPATHL];
+ char_u *first_colon = vim_strchr(buf, ':');
+ char_u *first_slash = vim_strchr(buf, '/');
+ int full = TRUE;
+ char_u *scanning;
+ char_u *filling;
+ char_u last_copied = NUL;
+
+ if (*buf == NUL)
+ return ;
+
+ if ((first_colon == NULL) && (first_slash == NULL))
+ full = FALSE;
+ if ((first_slash == NULL) && (first_colon != NULL))
+ full = TRUE;
+ if ((first_colon == NULL) && (first_slash != NULL))
+ full = FALSE;
+ if ((first_slash < first_colon) && (first_slash != NULL))
+ full = FALSE;
+ if ((first_colon < first_slash) && (first_colon != NULL))
+ full = TRUE;
+ if (first_slash == buf)
+ full = TRUE;
+ if (first_colon == buf)
+ full = FALSE;
+
+ scanning = buf;
+ filling = temp;
+
+ while (*scanning != NUL)
+ {
+ if (*scanning == '/')
+ {
+ if ((scanning[1] != '/') && (scanning[-1] != ':'))
+ {
+ *filling++ = ':';
+ scanning++;
+ }
+ else
+ scanning++;
+ }
+ else if (*scanning == '.')
+ {
+ if ((scanning[1] == NUL) || scanning[1] == '/')
+ {
+ if (scanning[1] == NUL)
+ scanning += 1;
+ else
+ scanning += 2;
+ }
+ else if (scanning[1] == '.')
+ {
+ if ((scanning[2] == NUL) || scanning[2] == '/')
+ {
+ *filling++ = ':';
+ if (scanning[2] == NUL)
+ scanning +=2;
+ else
+ scanning += 3;
+ }
+ else
+ {
+ *filling++ = *scanning++;
+ }
+ }
+ else
+ {
+ *filling++ = *scanning++;
+ }
+
+ }
+ else
+ {
+ *filling++ = *scanning++;
+ }
+
+ }
+
+ *filling = 0;
+ filling = temp;
+
+ if (!full)
+ {
+ if (buf[0] != ':')
+ {
+ buf[0] = ':';
+ buf[1] = NUL;
+ }
+ else
+ buf[0] = NUL;
+ }
+ else
+ {
+ buf[0] = NUL;
+ if (filling[0] == ':')
+ filling++;
+ }
+
+ STRCAT (buf, filling);
+#endif
+}
+
+/*
+ * Get absolute filename into buffer 'buf' of length 'len' bytes.
+ *
+ * return FAIL for failure, OK for success
+ */
+ int
+mch_FullName(fname, buf, len, force)
+ char_u *fname, *buf;
+ int len;
+ int force; /* also expand when already absolute path name */
+{
+ /*
+ * TODO: Find what TODO
+ */
+ int l;
+ char_u olddir[MAXPATHL];
+ char_u newdir[MAXPATHL];
+ char_u *p;
+ char_u c;
+ int retval = OK;
+
+ if (force || !mch_isFullName(fname))
+ {
+ /*
+ * Forced or not an absolute path.
+ * If the file name has a path, change to that directory for a moment,
+ * and then do the getwd() (and get back to where we were).
+ * This will get the correct path name with "../" things.
+ */
+ if ((p = vim_strrchr(fname, ':')) != NULL)
+ {
+ p++;
+ if (mch_dirname(olddir, MAXPATHL) == FAIL)
+ {
+ p = NULL; /* can't get current dir: don't chdir */
+ retval = FAIL;
+ }
+ else
+ {
+ c = *p;
+ *p = NUL;
+ if (mch_chdir((char *)fname))
+ retval = FAIL;
+ else
+ fname = p; /* + 1;*/
+ *p = c;
+ }
+ }
+ if (mch_dirname(buf, len) == FAIL)
+ {
+ retval = FAIL;
+ *newdir = NUL;
+ }
+ l = STRLEN(buf);
+ if (STRCMP(fname, ".") != 0)
+ {
+#ifdef USE_UNIXFILENAME
+ if (l > 0 && buf[l - 1] != '/' && *fname != NUL)
+ STRCAT(buf, "/");
+#else
+ if (l > 0 && buf[l - 1] != ':' && *fname != NUL)
+ STRCAT(buf, ":");
+#endif
+ }
+ if (p != NULL)
+ mch_chdir((char *)olddir);
+ if (STRCMP(fname, ".") != 0)
+ STRCAT(buf, fname);
+ }
+ else
+ {
+ STRNCPY(buf, fname, len);
+ buf[len - 1] = NUL;
+ slash_n_colon_adjust(buf);
+ }
+
+ return retval;
+}
+
+/*
+ * Return TRUE if "fname" does not depend on the current directory.
+ */
+ int
+mch_isFullName(fname)
+ char_u *fname;
+{
+#ifdef USE_UNIXFILENAME
+ return ((fname[0] == '/') || (fname[0] == '~'));
+#else
+ /*
+ * TODO: Make sure fname is always of mac still
+ * i.e: passed throught slash_n_colon_adjust
+ */
+ char_u *first_colon = vim_strchr(fname, ':');
+ char_u *first_slash = vim_strchr(fname, '/');
+
+ if (first_colon == fname)
+ return FALSE;
+ if (first_slash == fname)
+ return TRUE;
+ if ((first_colon < first_slash) && (first_colon != NULL))
+ return TRUE;
+ if ((first_slash < first_colon) && (first_slash != NULL))
+ return FALSE;
+ if ((first_colon == NULL) && (first_slash != NULL))
+ return FALSE;
+ if ((first_slash == NULL) && (first_colon != NULL))
+ return TRUE;
+ if ((first_colon == NULL) && (first_slash == NULL))
+ return FALSE;
+ return TRUE;
+#endif
+}
+
+/*
+ * Replace all slashes by colons.
+ */
+ void
+slash_adjust(p)
+ char_u *p;
+{
+#ifndef USE_UNIXFILENAME
+ /*
+ * TODO: keep escaped '/'
+ */
+
+ while (*p)
+ {
+ if (*p == '/')
+ *p = ':';
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p);
+ else
+#endif
+ ++p;
+ }
+#endif
+}
+
+/*
+ * Get file permissions for 'name'.
+ * Returns -1 when it doesn't exist.
+ */
+ long
+mch_getperm(name)
+ char_u *name;
+{
+ /*
+ * TODO: Maybe use AppleShare info??
+ * Use locked for non writable
+ */
+
+ struct stat statb;
+
+ if (stat((char *)name, &statb))
+ return -1;
+ return statb.st_mode;
+}
+
+/*
+ * set file permission for 'name' to 'perm'
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+mch_setperm(name, perm)
+ char_u *name;
+ long perm;
+{
+ /*
+ * TODO: Maybe use AppleShare info??
+ * Use locked for non writable
+ */
+ return (OK);
+}
+
+/*
+ * Set hidden flag for "name".
+ */
+ void
+mch_hide(name)
+ char_u *name;
+{
+ /*
+ * TODO: Hide the file throught FileManager FAQ 8-34
+ *
+ * *name is mac style start with : for relative
+ */
+}
+
+
+/*
+ * return TRUE if "name" is a directory
+ * return FALSE if "name" is not a directory
+ * return FALSE for error
+ */
+ int
+mch_isdir(name)
+ char_u *name;
+{
+ /*
+ * TODO: Find out by FileManager calls ...
+ */
+ struct stat statb;
+
+#if defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON
+ /* For some reason the name is sometimes empty,
+ * (such as for a not yet named file). An empty
+ * filename is interpreted by the MacOS version
+ * of stat (at least under Codewarrior) as the
+ * current directory.
+ */
+ /* AK 20020413
+ * This is required for Carbon but breaks the
+ * explorer plugin in Classic
+ */
+ if (name[0] == NULL)
+ return FALSE;
+#endif
+
+ if (stat((char *)name, &statb))
+ return FALSE;
+#if defined(__MRC__) || defined(__SC__)
+ return FALSE; /* definitely TODO */
+#else
+ return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
+#endif
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return 1 if "name" can be executed, 0 if not.
+ * Return -1 if unknown.
+ */
+ int
+mch_can_exe(name)
+ char_u *name;
+{
+ /* TODO */
+ return -1;
+}
+#endif
+
+/*
+ * Check what "name" is:
+ * NODE_NORMAL: file or directory (or doesn't exist)
+ * NODE_WRITABLE: writable device, socket, fifo, etc.
+ * NODE_OTHER: non-writable things
+ */
+ int
+mch_nodetype(name)
+ char_u *name;
+{
+ /* TODO */
+ return NODE_NORMAL;
+}
+
+ void
+mch_early_init()
+{
+}
+
+ void
+mch_exit(r)
+ int r;
+{
+ display_errors();
+
+ ml_close_all(TRUE); /* remove all memfiles */
+ exit(r);
+}
+
+
+ void
+mch_settmode(tmode)
+ int tmode;
+{
+ /*
+ * TODO: remove the needs of it.
+ */
+}
+
+#ifdef FEAT_MOUSE
+/*
+ * set mouse clicks on or off (only works for xterms)
+ */
+ void
+mch_setmouse(on)
+ int on;
+{
+ /*
+ * TODO: remove the needs of it.
+ */
+}
+#endif
+
+/*
+ * set screen mode, always fails.
+ */
+ int
+mch_screenmode(arg)
+ char_u *arg;
+{
+ EMSG(_(e_screenmode));
+ return FAIL;
+}
+
+ int
+mch_call_shell(cmd, options)
+ char_u *cmd;
+ int options; /* SHELL_*, see vim.h */
+{
+ /*
+ * TODO: find a shell or pseudo-shell to call
+ * for some simple useful command
+ */
+
+ return (-1);
+}
+
+/*
+ * Return TRUE if "p" contains a wildcard that can be expanded by
+ * mch_expandpath().
+ */
+ int
+mch_has_exp_wildcard(p)
+ char_u *p;
+{
+ for ( ; *p; ++p)
+ {
+ if (*p == '\\' && p[1] != NUL)
+ ++p;
+ else if (vim_strchr((char_u *)WILDCHAR_LIST, *p) != NULL)
+ return TRUE;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ return FALSE;
+}
+
+ int
+mch_has_wildcard(p)
+ char_u *p;
+{
+#ifdef USE_UNIXFILENAME
+ if (*p == '~' && p[1] != NUL)
+ return TRUE;
+#endif
+ return mch_has_exp_wildcard(p);
+}
+
+
+/*
+ * This procedure duplicate a file, it is used in order to keep
+ * the footprint of the previous file, when some info can be easily
+ * restored with set_perm().
+ *
+ * Return -1 for failure, 0 for success.
+ */
+ int
+mch_copy_file(from, to)
+ char_u *from;
+ char_u *to;
+{
+ char_u from_str[256];
+ char_u to_str[256];
+ char_u to_name[256];
+
+ HParamBlockRec paramBlock;
+ char_u *char_ptr;
+ int len;
+
+ /*
+ * Convert C string to Pascal string
+ */
+ char_ptr = from;
+ len = 1;
+ for (; (*char_ptr != 0) && (len < 255); len++, char_ptr++)
+ from_str[len] = *char_ptr;
+ from_str[0] = len-1;
+
+ char_ptr = to;
+ len = 1;
+ for (; (*char_ptr != 0) && (len < 255); len++, char_ptr++)
+ to_str[len] = *char_ptr;
+ to_str[0] = len-1;
+
+ paramBlock.copyParam.ioCompletion = NULL;
+ paramBlock.copyParam.ioNamePtr = from_str;
+ /* paramBlock.copyParam.ioVRefnum = overided by ioFilename; */
+ /* paramBlock.copyParam.ioDirI = overided by ioFilename; */
+
+ paramBlock.copyParam.ioNewName = to_str;
+ paramBlock.copyParam.ioCopyName = to_name; /* NIL */
+ /* paramBlock.copyParam.ioDstVRefNum = overided by ioNewName; */
+ /* paramBlock.copyParam.ioNewDirID = overided by ioNewName; */
+
+
+
+ /*
+ * First delete the "to" file, this is required on some systems to make
+ * the rename() work, on other systems it makes sure that we don't have
+ * two files when the rename() fails.
+ */
+ mch_remove(to);
+
+ /*
+ * First try a normal rename, return if it works.
+ */
+ (void) PBHCopyFile(&paramBlock, false);
+ return 0;
+
+}
+
+
+ int
+mch_copy_file_attribute(from, to)
+ char_u *from;
+ char_u *to;
+{
+ FSSpec frFSSpec;
+ FSSpec toFSSpec;
+ FInfo fndrInfo;
+ Str255 name;
+ ResType type;
+ ResType sink;
+ Handle resource;
+ short idxTypes;
+ short nbTypes;
+ short idxResources;
+ short nbResources;
+ short ID;
+ short frRFid;
+ short toRFid;
+ short attrs_orig;
+ short attrs_copy;
+ short temp;
+
+ /* TODO: Handle error */
+ (void) GetFSSpecFromPath (from, &frFSSpec);
+ (void) GetFSSpecFromPath (to , &toFSSpec);
+
+ /* Copy resource fork */
+ temp = 0;
+
+#if 1
+ frRFid = FSpOpenResFile (&frFSSpec, fsCurPerm);
+
+ if (frRFid != -1)
+ {
+ FSpCreateResFile(&toFSSpec, 'TEXT', UNKNOWN_CREATOR, 0);
+ toRFid = FSpOpenResFile (&toFSSpec, fsRdWrPerm);
+
+ UseResFile (frRFid);
+
+ nbTypes = Count1Types();
+
+ for (idxTypes = 1; idxTypes <= nbTypes; idxTypes++)
+ {
+ Get1IndType (&type, idxTypes);
+ nbResources = Count1Resources(type);
+
+ for (idxResources = 1; idxResources <= nbResources; idxResources++)
+ {
+ attrs_orig = 0; /* in case GetRes fails */
+ attrs_copy = 0; /* in case GetRes fails */
+ resource = Get1IndResource(type, idxResources);
+ GetResInfo (resource, &ID, &sink, name);
+ HLock (resource);
+ attrs_orig = GetResAttrs (resource);
+ DetachResource (resource);
+
+
+ UseResFile (toRFid);
+ AddResource (resource, type, ID, name);
+ attrs_copy = GetResAttrs (resource);
+ attrs_copy = (attrs_copy & 0x2) | (attrs_orig & 0xFD);
+ SetResAttrs (resource, attrs_copy);
+ WriteResource (resource);
+ UpdateResFile (toRFid);
+
+ temp = GetResAttrs (resource);
+
+ /*SetResAttrs (resource, 0);*/
+ HUnlock(resource);
+ ReleaseResource (resource);
+ UseResFile (frRFid);
+ }
+ }
+ CloseResFile (toRFid);
+ CloseResFile (frRFid);
+ }
+#endif
+ /* Copy Finder Info */
+ (void) FSpGetFInfo (&frFSSpec, &fndrInfo);
+ (void) FSpSetFInfo (&toFSSpec, &fndrInfo);
+
+ return (temp == attrs_copy);
+}
+
+ int
+mch_has_resource_fork (file)
+ char_u *file;
+{
+ FSSpec fileFSSpec;
+ short fileRFid;
+
+ /* TODO: Handle error */
+ (void) GetFSSpecFromPath (file, &fileFSSpec);
+ fileRFid = FSpOpenResFile (&fileFSSpec, fsCurPerm);
+ if (fileRFid != -1)
+ CloseResFile (fileRFid);
+
+ return (fileRFid != -1);
+}
+
+ int
+mch_get_shellsize(void)
+{
+ /* never used */
+ return OK;
+}
+
+ void
+mch_set_shellsize(void)
+{
+ /* never used */
+}
+
+/*
+ * Rows and/or Columns has changed.
+ */
+ void
+mch_new_shellsize(void)
+{
+ /* never used */
+}
+
+/*
+ * Those function were set as #define before, but in order
+ * to allow an easier us of os_unix.c for the MacOS X port,
+ * they are change to procedure. Thec ompile whould optimize
+ * them out.
+ */
+
+ int
+mch_can_restore_title()
+{
+ return TRUE;
+}
+
+ int
+mch_can_restore_icon()
+{
+ return TRUE;
+}
+
+/*
+ * If the machine has job control, use it to suspend the program,
+ * otherwise fake it by starting a new shell.
+ */
+ void
+mch_suspend()
+{
+ /* TODO: get calle in #ifndef NO_CONSOLE */
+ gui_mch_iconify();
+};
+
diff --git a/src/os_mac.h b/src/os_mac.h
new file mode 100644
index 000000000..799176967
--- /dev/null
+++ b/src/os_mac.h
@@ -0,0 +1,411 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/* Before Including the MacOS specific files,
+ * lets set the OPAQUE_TOOLBOX_STRUCTS to 0 so we
+ * can access the internal structures.
+ * (Until fully Carbon compliant)
+ * TODO: Can we remove this? (Dany)
+ */
+#if 0
+# define OPAQUE_TOOLBOX_STRUCTS 0
+#endif
+
+/*
+ * Macintosh machine-dependent things.
+ */
+#include <QuickDraw.h>
+#include <ToolUtils.h>
+#include <LowMem.h>
+#include <Scrap.h>
+#include <Sound.h>
+#include <TextUtils.h>
+#include <Memory.h>
+#include <OSUtils.h>
+#include <Files.h>
+#ifdef FEAT_MBYTE
+# include <Script.h>
+#endif
+
+/*
+ * Unix interface
+ */
+#if defined(__MWERKS__) /* for CodeWarrior */
+# include <unistd.h>
+# include <utsname.h>
+# include <unix.h>
+#endif
+#if defined(__APPLE_CC__) /* for Project Builder and ... */
+# include <unistd.h>
+#endif
+/* Get stat.h or something similar. Comment: How come some OS get in in vim.h */
+#if defined(__MWERKS__)
+# include <stat.h>
+#endif
+#if defined(__APPLE_CC__)
+# include <sys/stat.h>
+#endif
+#if defined(__MRC__) || defined(__SC__) /* for Apple MPW Compilers */
+/* There's no stat.h for MPW? */
+# ifdef powerc
+# pragma options align=power
+# endif
+ struct stat
+ {
+ UInt32 st_mtime;
+ UInt32 st_mode;
+ UInt32 st_size;
+ };
+# ifdef powerc
+# pragma options align=reset
+# endif
+#endif
+#if defined(__APPLE_CC__) /* && defined(HAVE_CURSE) */
+/* The curses.h from MacOS X provides by default some BACKWARD compatibilty
+ * definition which can cause us problem later on. So we undefine a few of them. */
+# include <curses.h>
+# undef reg
+# undef ospeed
+/* OK defined to 0 in MacOS X 10.2 curses! Remove it, we define it to be 1. */
+# undef OK
+#endif
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#ifdef MACOS_X
+# include <dirent.h>
+#endif
+
+/*
+ * Incompatibility checks
+ */
+
+/* Got problem trying to use shared library in 68k */
+#if !defined(__POWERPC__) && defined(FEAT_PYTHON)
+# undef FEAT_PYTHON
+# warning Auto-disabling Python. Not yet supported in 68k.
+#endif
+
+#if !defined(__POWERPC__) && !defined(__ppc__)
+# if !__option(enumsalwaysint)
+# error "You must compile with enums always int!"
+# endif
+# if defined(__MWERKS__) && !defined(__fourbyteints__)
+# error "You must compile the project with 4-byte ints"
+/* MPW ints are always 4 byte long */
+# endif
+#endif
+
+/*
+ * MacOS specific #define
+ */
+
+/* This will go away when CMD_KEY fully tested */
+#define USE_CMD_KEY
+/* On MacOS X use the / not the : */
+/* TODO: Should file such as ~/.vimrc reside instead in
+ * ~/Library/Vim or ~/Library/Preferences/org.vim.vim/ ? (Dany)
+ */
+/* When compiled under MacOS X (including CARBON version)
+ * we use the Unix File path style */
+#if defined(TARGET_API_MAC_OSX) && TARGET_API_MAC_OSX
+# undef COLON_AS_PATHSEP
+# define USE_UNIXFILENAME
+#else
+# define COLON_AS_PATHSEP
+# define DONT_ADD_PATHSEP_TO_DIR
+#endif
+
+
+/*
+ * Generic Vim #define
+ */
+
+#define FEAT_SOURCE_FFS
+#define FEAT_SOURCE_FF_MAC
+
+#define USE_EXE_NAME /* to find $VIM */
+#define CASE_INSENSITIVE_FILENAME /* ignore case when comparing file names */
+#define SPACE_IN_FILENAME
+#define BREAKCHECK_SKIP 32 /* call mch_breakcheck() each time, it's
+ quite fast. Did I forgot to update the comment */
+
+
+#undef USE_FNAME_CASE /* So that :e os_Mac.c, :w, save back the file as os_mac.c */
+#define BINARY_FILE_IO
+#define EOL_DEFAULT EOL_MAC
+#ifndef MACOS_X_UNIX /* I hope that switching these two lines */
+# define USE_CR /* does what I want -- BNF */
+# define NO_CONSOLE /* don't include console mode */
+#endif
+#define HAVE_AVAIL_MEM
+
+#ifndef HAVE_CONFIG_H
+/* #define SYNC_DUP_CLOSE sync() a file with dup() and close() */
+# define HAVE_STRING_H
+# define HAVE_STRCSPN
+# define HAVE_MEMSET
+# define USE_TMPNAM /* use tmpnam() instead of mktemp() */
+# define HAVE_FCNTL_H
+# define HAVE_QSORT
+# define HAVE_ST_MODE /* have stat.st_mode */
+
+# if defined(__DATE__) && defined(__TIME__)
+# define HAVE_DATE_TIME
+# endif
+# define HAVE_STRFTIME
+#endif
+
+
+/*
+ * Names for the EXRC, HELP and temporary files.
+ * Some of these may have been defined in the makefile.
+ */
+
+#ifndef SYS_VIMRC_FILE
+# ifdef COLON_AS_PATHSEP
+# define SYS_VIMRC_FILE "$VIM:vimrc"
+# else
+# define SYS_VIMRC_FILE "$VIM/vimrc"
+# endif
+#endif
+#ifndef SYS_GVIMRC_FILE
+# ifdef COLON_AS_PATHSEP
+# define SYS_GVIMRC_FILE "$VIM:gvimrc"
+# else
+# define SYS_GVIMRC_FILE "$VIM/gvimrc"
+# endif
+#endif
+#ifndef SYS_MENU_FILE
+# ifdef COLON_AS_PATHSEP
+# define SYS_MENU_FILE "$VIMRUNTIME:menu.vim"
+# else
+# define SYS_MENU_FILE "$VIMRUNTIME/menu.vim"
+# endif
+#endif
+#ifndef SYS_OPTWIN_FILE
+# ifdef COLON_AS_PATHSEP
+# define SYS_OPTWIN_FILE "$VIMRUNTIME:optwin.vim"
+# else
+# define SYS_OPTWIN_FILE "$VIMRUNTIME/optwin.vim"
+# endif
+#endif
+#ifndef EVIM_FILE
+# ifdef COLON_AS_PATHSEP
+# define EVIM_FILE "$VIMRUNTIME:evim.vim"
+# else
+# define EVIM_FILE "$VIMRUNTIME/evim.vim"
+# endif
+#endif
+
+#ifdef FEAT_GUI
+# ifndef USR_GVIMRC_FILE
+# ifdef COLON_AS_PATHSEP
+# define USR_GVIMRC_FILE "$VIM:.gvimrc"
+# else
+# define USR_GVIMRC_FILE "~/.gvimrc"
+# endif
+# endif
+# ifndef GVIMRC_FILE
+# define GVIMRC_FILE "_gvimrc"
+# endif
+#endif
+#ifndef USR_VIMRC_FILE
+# ifdef COLON_AS_PATHSEP
+# define USR_VIMRC_FILE "$VIM:.vimrc"
+# else
+# define USR_VIMRC_FILE "~/.vimrc"
+# endif
+#endif
+
+#ifndef USR_EXRC_FILE
+# ifdef COLON_AS_PATHSEP
+# define USR_EXRC_FILE "$VIM:.exrc"
+# else
+# define USR_EXRC_FILE "~/.exrc"
+# endif
+#endif
+
+#ifndef VIMRC_FILE
+# define VIMRC_FILE "_vimrc"
+#endif
+
+#ifndef EXRC_FILE
+# define EXRC_FILE "_exrc"
+#endif
+
+#ifndef DFLT_HELPFILE
+# ifdef COLON_AS_PATHSEP
+# define DFLT_HELPFILE "$VIMRUNTIME:doc:help.txt"
+# else
+# define DFLT_HELPFILE "$VIMRUNTIME/doc/help.txt"
+# endif
+#endif
+
+#ifndef FILETYPE_FILE
+# define FILETYPE_FILE "filetype.vim"
+#endif
+#ifndef FTPLUGIN_FILE
+# define FTPLUGIN_FILE "ftplugin.vim"
+#endif
+#ifndef INDENT_FILE
+# define INDENT_FILE "indent.vim"
+#endif
+#ifndef FTOFF_FILE
+# define FTOFF_FILE "ftoff.vim"
+#endif
+#ifndef FTPLUGOF_FILE
+# define FTPLUGOF_FILE "ftplugof.vim"
+#endif
+#ifndef INDOFF_FILE
+# define INDOFF_FILE "indoff.vim"
+#endif
+
+#ifndef SYNTAX_FNAME
+# ifdef COLON_AS_PATHSEP
+# define SYNTAX_FNAME "$VIMRUNTIME:syntax:%s.vim"
+# else
+# define SYNTAX_FNAME "$VIMRUNTIME/syntax/%s.vim"
+# endif
+#endif
+
+#ifdef FEAT_VIMINFO
+# ifndef VIMINFO_FILE
+# ifdef COLON_AS_PATHSEP
+# define VIMINFO_FILE "$VIM:viminfo"
+# else
+# define VIMINFO_FILE "~/.viminfo"
+# endif
+# endif
+#endif /* FEAT_VIMINFO */
+
+#ifndef DFLT_BDIR
+# define DFLT_BDIR "." /* default for 'backupdir' */
+#endif
+
+#ifndef DFLT_DIR
+# define DFLT_DIR "." /* default for 'directory' */
+#endif
+
+#ifndef DFLT_VDIR
+# ifdef COLON_AS_PATHSEP
+# define DFLT_VDIR "$VIM:vimfiles:view" /* default for 'viewdir' */
+# else
+# define DFLT_VDIR "$VIM/vimfiles/view" /* default for 'viewdir' */
+# endif
+#endif
+
+#define DFLT_ERRORFILE "errors.err"
+#ifdef COLON_AS_PATHSEP
+# define DFLT_RUNTIMEPATH "$VIM:vimfiles,$VIMRUNTIME,$VIM:vimfiles:after"
+#else
+# define DFLT_RUNTIMEPATH "~/.vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,~/.vim/after"
+#endif
+
+/*
+ * Macintosh has plenty of memory, use large buffers
+ */
+#define CMDBUFFSIZE 1024 /* size of the command processing buffer */
+
+#if defined(MACOS_X_UNIX)
+# define MAXPATHL 1024
+# define BASENAMELEN (MAXNAMLEN - 5) /* length of base of filename */
+#else
+# define MAXPATHL 256 /* Limited by the Pascal Strings */
+# define BASENAMELEN (32-5-1) /* length of base of filename */
+#endif
+
+#ifndef DFLT_MAXMEM
+# define DFLT_MAXMEM 512 /* use up to 512 Kbyte for buffer */
+#endif
+
+#ifndef DFLT_MAXMEMTOT
+# define DFLT_MAXMEMTOT 2048 /* use up to 2048 Kbyte for Vim */
+#endif
+
+#define WILDCHAR_LIST "*?[{`$"
+
+/**************/
+#define mch_rename(src, dst) rename(src, dst)
+#define mch_remove(x) unlink((char *)(x))
+#ifndef mch_getenv
+# if defined(__MRC__) || defined(__SC__)
+# define mch_getenv(name) ((char_u *)getenv((char *)(name)))
+# define mch_setenv(name, val, x) setenv((name), (val))
+# elif defined(__APPLE_CC__)
+# define mch_getenv(name) ((char_u *)getenv((char *)(name)))
+/*# define mch_setenv(name, val, x) setenv((name), (val)) */ /* Obsoleted by Dany on Oct 30, 2001 */
+# define mch_setenv(name, val, x) setenv(name, val, x)
+# else
+ /* vim_getenv() is in pty.c */
+# define USE_VIMPTY_GETENV
+# define mch_getenv(x) vimpty_getenv(x)
+# define mch_setenv(name, val, x) setenv(name, val, x)
+# endif
+#endif
+
+#ifndef HAVE_CONFIG_H
+# ifdef __APPLE_CC__
+/* Assuming compiling for MacOS X */
+/* Trying to take advantage of the prebinding */
+# define HAVE_TGETENT
+# define OSPEED_EXTERN
+# define UP_BC_PC_EXTERN
+# endif
+#endif
+
+/* Some "prep work" definition to be able to compile the MacOS X
+ * version with os_unix.x instead of os_mac.c. Based on the result
+ * of ./configure for console MacOS X.
+ */
+
+#ifdef MACOS_X_UNIX
+# define SIGPROTOARG (int)
+# define SIGDEFARG(s) (s) int s;
+# define SIGDUMMYARG 0
+# undef HAVE_AVAIL_MEM
+# ifndef HAVE_CONFIG_H
+# define RETSIGTYPE void
+# define SIGRETURN return
+/*# define USE_SYSTEM */ /* Output ship do debugger :(, but ot compile */
+# define HAVE_SYS_WAIT_H 1 /* Attempt */
+# define HAVE_TERMIOS_H 1
+# define SYS_SELECT_WITH_SYS_TIME 1
+# define HAVE_SELECT 1
+# define HAVE_SYS_SELECT_H 1
+# define HAVE_PUTENV
+# define HAVE_SETENV
+# define HAVE_RENAME
+# endif
+# define mch_chdir(s) chdir(s)
+#endif
+
+#if defined(MACOS_X) && !defined(HAVE_CONFIG_H)
+# define HAVE_PUTENV
+#endif
+
+/* A Mac constant causing big problem to syntax highlighting */
+#define UNKNOWN_CREATOR '\?\?\?\?'
+
+/*
+ * for debugging
+ */
+#ifdef MACOS_X
+# ifdef _DEBUG
+# define TRACE Trace
+ void Trace(char *fmt, ...);
+# else
+# define TRACE 1 ? (void)0 : printf
+# endif
+#endif
+
+#ifdef MACOS_CLASSIC
+# define TRACE 1 ? (int)0 : printf
+#endif
diff --git a/src/os_mac.rsr.hqx b/src/os_mac.rsr.hqx
new file mode 100644
index 000000000..04e99723f
--- /dev/null
+++ b/src/os_mac.rsr.hqx
@@ -0,0 +1,659 @@
+(This file must be converted with BinHex 4.0)
+
+:$'GeD9pYB@-ZFR0bB`"58e*$8P0&4!%!!!!!!!!!HUUk%`!!!!!"!!!!GJX!!(8
+,!!!%R`!!$Ed,Eh0IGc-bC'aX,Q-#!!!!9%9B9%0A588"!2rr#hCTE9"33bjbFh*
+MFLe%EfYeE@9ZG'9PEL"%BA4PER8!!(*cFQ058d9%!3lrrrrr!!!!!!!!!!!!!!!
+!!!!!!!!!X3N1a!!!!!!!!%'-!!!!!!!!!!!4!!!!$Ed,Eh0IGc-bCAKP,Q-#!!!
+!9%9B9%0A588"!2rrrrm!!!!!$NN!!!!!$hi!!%)!!!!!!!!!!!!!!,#`81D`X&$
+Q!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'6Y!!%!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!3!!!!!#a@58dK!!!!!8C548B!!J!!!)!!!3#"!!)!JNP$6L-!!J!!!))!!3#
+$!!)!!!!!!!G"8&"-!!!!!!!!"e4&@&3!!3!!!!!(+LSU+J!#!!!!!J!!!2rrrrr
+rrrrrrrm!!!!!!!$m$!`-$!`-$!`2m!!!!!!!m-$!`-E!`-$!cpm!!!!!!2`-$!`
+-$!`-$!r0m!!!!!$`aX$'aXCJB-$2$0m!!!!!r!B-"JB'"JB-$rrrm!!!!2$!B'$
+'aXE'`-$!c[!!!!$m$'aX"JB'"J`-$!l`!!!!m-$'`-E'aXE!`-$1m!!!!2`-$!`
+-$!`-$!`-$[!!!!$``-$!`-$!`-$!`-l`!!!!r!`-$!`-$!`-$!`1m!!!!2$!`-$
+!`-$!`-$!c[!!!!$m$!`-$!`-$!`-$!l`!!!!m-$!`-$!`-$!`-$1m!!!!2`-CJB
+-$!`-$!`-$[!!!!$`aXCJ`-$!`-$!`-l`!!!!r!`-$!`-$!`-$!`1m!!!!2$!`-$
+!`-$!`-$!c[!!!!$m$!`-$!`-$!`-$!l`!!!!m-$!`-$!`-$!`-$1m!!!!2`-$!`
+-$!`-$!`-$[!!!!$``-$!`-$!`-$!`-l`!!!!r!`-$!`-$!`-$!`1m!!!!2$!CXE
+!`-$!`-$!c[!!!!$m"JCX$!`-$!`-$!l`!!!!m-$!`-$!`-$!`-$1m!!!!2`-$!`
+-$!`-$!`-$[!!!!$``-$!`-$!`-$!`-l`!!!!r!`-$!`-$!`-$!`1m!!!!2lZlZl
+ZlZlZlZlZl[!!!!$rrrrrrrrrrrrrrrr`!!!!!J$rrrrrrrrrrrrrrrrrrrr`m!!
+!!!!!!!!!!!!!!!!!m2!!!!!!!!!!!!!!!!!!!2$`!!!!!!!!!!!!!!!!!!$`m!!
+!!!!!!!!2rrr`!!!!m2!!CJB!!!!!mJ)#$`!!!2$`"JCJ!!!!$b!J)#$`!!$`m!!
+!!!!!!2)2mJ)#$`!!m2!!!!!!!!$rrGmJ)#$`!2$`!!!!!!rr![rrrrm#$rrrm!!
+!!!!!$b![m#!J)#$fEr!!!!!!$Ghb!J)#!J)#pQr`!!!!!!!0hb!J)#!J)2C[m!!
+!!!!!!0hr!J)#!J,fEr!!CJB!!!!0hIrrrrmJpQr`"JCJ!!!!!0hGhGhGrrC[m!!
+!!!!!!!!!hGhGhGhIrr!!!!!!!!!!!!!!!!hGhI$`!!!!!!!!!!!!!!!!!!$`m!!
+!!!!!!!!!!!!'CQCJm2!!!!!!!!!!!!!!"QCQB2$`!!!!!!!'!!!!!!CQCQ$`m!!
+!!!!!!!!!!!!'CQCJm2!'B'!!B'B!CJB!"QCQB2$`"Q"J!'!'!'"JB!CQCQ$`m!!
+!"JB!"J"JB'!'CQCJm2!!!!B'!!B!B'"J"QCQB2$`"Q!'"J!'!'"JB!CQCQ$`m!C
+J!'!!"Q"JB'!'CQCJm2!!!!!!!!!!!!!!"QCQB2$`!!!!!!!!!!!!!!!!!!$`rrr
+rrrrrrrrrrrrrrrrrm!!!!J!!$rrrrrrrrrrrrrrrrr!!!2!!!!!!!!!!!!!!!!!
+2!!m!c-c-c-c-c-c-c-c-c[!2$-lZlZlZlZlZlZlZl-l`$`cZrrrrrrrrrrrrrq$
+1m!m-lrL2Mrrrrrrrrrr`c[!2$1q2L2rrrrrrrrrrm-l`$`c[rrrrrrrrrrrrrr$
+1m!m-lrrrrrrrrrrrrrr`c[!2$1rrrrrrrrrrrrrrm-l`$`c[rrrrrrrrrrrrrr$
+1m!m-lrL2Mrrrrrrrrrr`c[!2$1q2L2rrrrrrrrrrm-l`$`c[rrrrrrrrrrrrrr$
+1m!m-lrrrrrrrrrriL)M`c[!2$1rrrrrirrrrq)L)m-l`$`c[rrrrrrrrrrL)L2$
+1m!m-liq2q2MiMiriL)M`c[!2$1rrMrMiq2Miq)L)m-l`$`c[riq2q2Miq2L)L2$
+1m!m-liq)rrMiq2MiL)M`c[!2$1rrrrrrrrrrrrrrm-l`$`cZrrrrrrrrrrrrr`$
+1m!m-`!!!!!!!!!!!!!!-c[!2$-c-c-c-c-c-c-c-c1l`!2lZlZlZlZlZlZlZlZl
+[!!!2c1c1c1c1c1c1c1c1m!!!rmlXlXlXlXlXlXlXl[m!$rc1c1c1c1c1c1c1c1c
+1m2rmlXlXlXlXlXlXlXlXl[rrrrrrrrrrrrrrrrrrrrrr$rrrrrrrrrrrrrrrrrr
+rm!!!!J!!!!$rrrrrrrrrrrrrm!!!!!!!r!`-$!`-$!`-$2m!!!!!!2$!`-$!`-$
+!`-$qm!!!!!$m$!`-$!`-$!`-rHm!!!!!m-$!`-$!`-$!`2cHm!!!!2`-$!`-$!`
+-$!crrrm!rrrrrrrrrrrrrm$!`-$2$mc-c-c-c-c-c-cm$!`-$rcGhGhGhGhGhGh
+Glm$!`-rmhZlZlZlZlZlZlHm-$!`2r0lrrrrrrrq)Mmh[d-$!crcHMiq2L2MrL)r
+0lmd-$!rmhSq2Miq2MiL2cHrF`-$2r0k)riq2Miq)Mmh[c3`-$rcHrrrrrrrrrrr
+0lpc!`-rmh[rrrrrrrrrrcHr0$!`2r0liMirrrrrrrmh[h-$!crcHMiMrrrrrrrr
+0lmd-$!rmh[rrrrrrrrrrcHrF`-$2r0lrrrrrrrrrrmh[c3`-$rcHq)q2rrrrrrr
+0lpc!`-rmhSq)rrrrrrrrcHr0$!`2r0lrrrrrrrrrrmh[h-$!crcHc-c-c-c-c-c
+0lmd-$!rmhGhGhGhGhGhGhHrF`-$2$qlZlZlZlZlZlZlpc3`-$`$rrrrrrrrrrrr
+rh0$!`-m!!!$pcFh0cFh0cFd-$!`2!!!!r0cFh0cFh0c3`-$!c`!!!2`-$!`-$!`
+-$!`-$!m!!!$``-$!`-$!`-$!`-$2!!!!rrrrrrrrrrrrrrrrr`!!"!!!!!!!rrr
+rrrrrrrrrrrrrrrrrrrrrrrm!!!!!!!!!!!!!!!$rpIAepIAepIAepIAepIAepIA
+errm!!!!!!!!!!!!!!2repIAepIAepHcepIAepIAepIArq[m!!!!!!!!!!!!!rrA
+epIAepIAepIAepIAepIAepIrhq[m!!!!!!!!!!!$rpIAXpIAel2AXpHcXpHcepIA
+errAhq[m!!!!!!!!!!2repHcepIAXpHcel2AXpHcepIArrrrrrrm!!!!!!!!!rrA
+epHcel2Ael2AXpHcel2AepIAepIAlr`!!!!!!!!$rpIAel2AXpIAXpHcel2AXpIA
+epIAepI[r!!!!!!!!!2repIAel2AepHcel2AXpHcepIAepIAeqrm!!!!!!!!!rrA
+epIAepIAepIAepIAepIAepIAepIAlr`!!!!!!!!$rpIAepIAepIAepIAepIAepIA
+epIAepI[r!!!!!!!!!2repIAepIAepIAepIAepIAepIAepIAeqrm!!!!!!!!!rrA
+epIAepIAepIAepIAepIAepIAepIAlr`!!!!!!!!$rpIAepIAepIAepIAepIAepIA
+epIAepI[r!!!!!!!!!2repIAepIAepIAepIAepIAepIAepIAeqrm!!!!!!!!!rrA
+epHcXpHcepIAepIAepIAepIAepIAlr`!!!!!!!!$rpIAXpHcXpIAepIAepIAepIA
+epIAepI[r!!!!!!!!!2repIAepIAepIAepIAepIAepIAepIAeqrm!!!!!!!!!rrA
+epIAepIAepIAepIAepIAepIAepIAlr`!!!!!!!!$rpIAepIAepIAepIAepIAepIA
+epIAepI[r!!!!!!!!!2repIAepIAepIAepIAepIAepIAepIAeqrm!!!!!!!!!rrA
+epIAepIAepIAepIAepIAepIAepIAlr`!!!!!!!!$rpIAepIAepIAepIAepIAepIA
+epIAepI[r!!!!!!!!!2repIAepIAepIAepIAepIAepIAepIAeqrm!!!!!!!!!rrA
+epHcXpHcepIAepIAepIAepIAepIAlr`!!!!!!!!$rpIAXpHcXpIAepIAepIAepIA
+epIAepI[r!!!!!!!!!2repIAepIAepIAepIAepIAepIAepIAeqrm!!!!!!!!!rrA
+epIAepIAepIAepIAepIAepIAepIAlr`!!!!!!!!$rpIAepIAepIAepIAepIAepIA
+epIAepI[r!!!!!!!!!2repIAepIAepIAepIAepIAepIAepIAeqrm!!!!!!!!!rr[
+lqr[lqr[lqr[lqr[lqr[lqr[lqr[lr`!!!!!!!!$rrrrrrrrrrrrrrrrrrrrrrrr
+rrrrrrrrr!!!!!!!%!2rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrm!rdK
+)5%K)5%K)5%K)5%K)5%K)5%K)5%K)5%K)5%K)r`$r5%K)5%K)5%K)5%K)5%K)5%K
+)5%K)5%K)5%K)5%Mr!2p)5%K)5%K)5%K)5%K)5%K)5%K)5%K)5%K)5%K)52m!rdK
+)5%K)5%K)5%K)5%K)5%Mrrrrrrrp)5%K)5%K)r`$r5%K)l1a)l%K)5%K)5%K)r`J
+)#!J)#2p)5%K)5%Mr!2p)51a)l1a)5%K)5%K)52m)#!J)#!J)#2p)5%K)52m!rdK
+)5%K)5%K)5%K)5%Mr#!Mrr`J)#!J)#2p)5%K)r`$r5%K)5%K)5%K)5%K)52rrrhp
+rr`J)#!J)#2p)5%Mr!2p)5%K)5%K)5%K)rrrr#!Mrrrrrrrrrr`J)#2rrrrrrrdK
+)5%K)5%K)5%K)52m)#!Mrr`J)#!J)#!J)#2rXl2rr5%K)5%K)5%K)5(prIrm)#!J
+)#!J)#!J)#!J)rqcXrrp)5%K)5%K)5%K)5%KrIrm)#!J)#!J)#!J)#!Mrl1crrdK
+)5%K)5%K)5%K)5%KrIrrr#!J)#!J)#!J)#2rXl2rr5%K)l1a)l%K)5%K)5%KrIhr
+rrrrrrrrrr`J)rqcXrrp)51a)l1a)5%K)5%K)5%KrIhprIhprIhprrrrrl1crrdK
+)5%K)5%K)5%K)5%K)5%K)IhprIhprIhprIhrrrrrr5%K)5%K)5%K)5%K)5%K)5%K
+)5%K)5%K)IhprIhrr!2p)5%K)5%K)5%K)5%K)5%K)5%K)5%K)5%K)5%K)52m!rdK
+)5%K)5%K)5%K)5%K)5%K)5%K)5%MXl1cXl1a)r`$r5%K)5%K)5%K)5%K)5%K)5%K
+)5%K)51cXl1cXl%Mr!2p)5%K)5%K)5%K)5%MX5%K)5%K)5%K)l1cXl1cX52m!rdK
+)5%K)5%K)5%K)5%K)5%K)5%K)5%MXl1cXl1a)r`$r5%MXl%MX5%K)l%MXl%K)l1a
+)l%K)51cXl1cXl%Mr!2p)51cX51a)5%MX5%MX5%MX51a)l%K)l1cXl1cX52m!rdK
+)5%K)51a)l%K)51a)51a)l%MX5%MXl1cXl1a)r`$r5%K)5%K)l%MX5%K)l%K)l%M
+X51a)51cXl1cXl%Mr!2p)51cX5%MX51a)5%MX5%MX51a)l%K)l1cXl1cX52m!rdK
+)l1a)5%MX5%K)51cX51a)l%MX5%MXl1cXl1a)r`$r5%K)5%K)5%K)5%K)5%K)5%K
+)5%K)51cXl1cXl%Mr!2p)5%K)5%K)5%K)5%K)5%K)5%K)5%K)5%K)5%K)52m!rrr
+rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr`!!!!3!!!!!rrrrrrrrrrrrrrr
+rrrrrrrrrrrrrrrrrrrm!!!!!!2repIAepIAepIAepIAepIAepIAepIAepIAepIm
+!!!$rpIAiq2Miq2Miq2Miq2Miq2Miq2Miq2Miq2Mir2m!!2req2Mmr2cmr2cmr2c
+mr2cmr2cmr2cmr2cmq2Mmr`!!rrAir2crrrrrrrrrrrrrrrrrrrrrrrrrrrceq2c
+r!!$rpIMmrrrMirrMrrrrrrrrrrrrrrrrrrrrrrAir2m!!2req2crirrMirrrrrr
+rrrrrrrrrrrrrrrrrpIMmr`!!rrAir2rrrrrrrrrrrrrrrrrrrrrrrrrrrrreq2c
+r!!$rpIMmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrAir2m!!2req2crrrrrrrrrrrr
+rrrrrrrrrrrrrrrrrpIMmr`!!rrAir2rrrrrrrrrrrrrrrrrrrrrrrrrrrrreq2c
+r!!$rpIMmrrrMirrMrrrrrrrrrrrrrrrrrrrrrrAir2m!!2req2crirrMirrrrrr
+rrrrrrrrrrrrrrrrrpIMmr`!!rrAir2rrrrrrrrrrrrrrrrrrrrrrrrrrrrreq2c
+r!!$rpIMmrrrrrrrrrrrrrrrrrrrrrq2Miq2MrrAir2m!!2req2crrrrrrrrrrq2
+rrrrrrrrriq2Miq2rpIMmr`!!rrAir2rrrrrrrrrrrrrrrrrrrrrMiq2Mirreq2c
+r!!$rpIMmrq2rirrrirrMrq2Mrq2rrq2Miq2MrrAir2m!!2req2crrrrMrrrMrq2
+rirrMrq2riq2Miq2rpIMmr`!!rrAir2rrrq2rirrrirrMrq2rirrMiq2Mirreq2c
+r!!$rpIMmrq2riq2rrrrMrq2rirrMrq2Miq2MrrAir2m!!2req2crrrrrrrrrrrr
+rrrrrrrrrrrrrrrrrpIMmr`!!rrAir2crrrrrrrrrrrrrrrrrrrrrrrrrrrAeq2c
+r!!$rpIMipIAepIAepIAepIAepIAepIAepIAepIMir2m!!2req2Miq2Miq2Miq2M
+iq2Miq2Miq2Miq2Miq2cmr`!!!2rmr2cmr2cmr2cmr2cmr2cmr2cmr2cmr2cmr2m
+!!!!!!2rhpr[hpr[hpr[hpr[hpr[hpr[hpr[hpr[r!!!!!!$rrrIlqrIlqrIlqrI
+lqrIlqrIlqrIlqrIlqrrr!!!!rrrhpr[hpr[hpr[hpr[hpr[hpr[hpr[hpr[hpr[
+r!2rrrrIlqrIlqrIlqrIlqrIlqrIlqrIlqrIlqrIlqrrrrrrrrrrrrrrrrrrrrrr
+rrrrrrrrrrrrrrrrrrrrrrrm!rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
+r!!!!"!!!!!!!!!$rrrrrrrrrrrrrrrrrrrrrrrrrrrm!!!!!!!!!!!!!!2rfp[E
+fp[Efp[Efp[Efp[Efp[Efrrm!!!!!!!!!!!!!rrEfp[Efp[Efp[Efp[Efp[Efp[E
+rr2m!!!!!!!!!!!$rp[Efp[Efp[Efp[Efp[Efp[Efp[rjr2m!!!!!!!!!!2rfp[E
+fp[Efp[Efp[Efp[Efp[EfrrMjr2m!!!!!!!!!rrEfp[Efp[Efp[Efp[Efp[Efp[E
+rrrrrrrm!!2rrrrrrrrrrrrrrrrrrrrrrrrrrp[Efp[Efp[Efr`$r+bXV+bXV+bX
+V+bXV+bXV+bXV+b[rp[Efp[Efp[Errb[jqIRjqIRjqIRjqIRjqIRjqIRjqIcrp[E
+fp[Efp[rr+rRmr2cmr2cmr2cmr2cmr2cmr2cjr2rfp[Efp[EfrrmVqIcrrrrrrrr
+rrrrrrrrMiq2r+rRmrrMfp[Efp[Errb[jr12rirrMrq2Mrq2rrq2MirmVqIcrq2M
+fp[Efp[rr+rRmirrMrq2rirrMrq2riq2Mrb[jr2riq2Efp[EfrrmVqIcMirrrirr
+Mrq2rirrMiq2r+rRmrrMip[Efp[Errb[jr2rrrrrrrrrrrrrrrrrrrrmVqIcrq2M
+fp[Efp[rr+rRmrrrrrrrrrrrrrrrrrrrrrb[jr2riq2Efp[EfrrmVqIcriq2rirr
+rrrrrrrrrrrrr+rRmrrMip[Efp[Errb[jr12riq2rrrrrrrrrrrrrrrmVqIcrq2M
+fp[Efp[rr+rRmrrrrrrrrrrrrrrrrrrrrrb[jr2riq2Efp[EfrrmVqIcrrrrrrrr
+rrrrrrrrrrrrr+rRmrrMip[Efp[Errb[jr2rMirrMrrrrrrrrrrrrrrmVqIcrq2M
+fp[Efp[rr+rRmirrMirrrrrrrrrrrrrrrrb[jr2riq2Efp[EfrrmVqIcrrrrrrrr
+rrrrrrrrrrrrr+rRmrrMip[Efp[Errb[jr#XV+bXV+bXV+bXV+bXV+bXVqIcrq2M
+fp[Efp[rr+rRjqIRjqIRjqIRjqIRjqIRjqIRjr2riq2Efp[Efr`$rr2cmr2cmr2c
+mr2cmr2cmr2cmr2crq2Mip[Efp[Er!!$rrrrrrrrrrrrrrrrrrrrrrrrrrrMiq2M
+fp[Efp[m!!!!!!!$rq2Miq2Miq2Miq2Miq2Miq2Mip[Efp[Efr`!!!!!!!2riq2M
+iq2Miq2Miq2Miq2Miq2Efp[Efp[Er!!!!!!!!rrEfp[Efp[Efp[Efp[Efp[Efp[E
+fp[Efp[m!!!!!!!$rp[Efp[Efp[Efp[Efp[Efp[Efp[Efp[Efr`!!!!!!!2rrrrr
+rrrrrrrrrrrrrrrrrrrrrrrrrrrrr!!!"!2rrrrk!!!!#J!!!!S!!!!+!!(i#M3#
+"!TB"!)+!!Q"#J!13!#+!(2mIJ!4J$i!#!!q!!3!2J!$!$id!2mq@!!!rJ!!!$i!
+!!!+!!!!#J!!"qS!!!IU!"!(kJ!!"qTSXdIUD*+RkJ85TqS&%UIUC4+RkQ)DTqS!
+!!IU!!!!#rrrrr[rrrrlrrrrqrrrrr[rrrrlrrrrqrrrrr[rrrrlrrrrqrrrrr[r
+rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr[rrrrlrrrrqrrrrr[r
+rrrlrrrrqrrrrr[rrrrlrrrrqrrrrr[rrrrlrrrrqrrrrr[rrrrlrrrrq!!!"!!r
+rr`!)!!'!#!3"3!J!!5!*&D%3#494q!LP8!J)T9!)#%93#!J!!!J)!!!)#!!!#!J
+!!!J)!!!)#!!!#!M3!!J*B!!)#!!!#!J!!!J)!!!)#!!!#!J!!!J)!!!)#!!!#!M
+3!!J*B!!)#!!!#!J!!!J)!!!)#!!!#!J!!!J2rrri$rrr!!rrri!2rrr!$rrri!r
+rrr!2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!r
+rrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!r
+rrrJ2rrri$rrrq!rrrrJ!!!%!(rrrq#!!!!4!!!!#4rrriNJ!!"*)!!!55D!!%NV
+!!"*)!!!55!!!%NJ!!"**S!!55X!!%NJ!!"*)!!I55!3(dNJ!"p*+PDI55*9AdNL
+P9p*+a9I55!!!%NJ!!"*(rrrL3!!!!M!!!!`Irrri0YYY['5555EYYYY[rrrrrhr
+rrriIrrri2rrrr(rrrrjrrrrqIrrrrRrrrrjrrrrqIrrrrRrrrrjrrrrqIrrrrRr
+rrrjrrrrqIrrrrRrrrrjrrrrqIrrrrRrrrrjrrrrqIrrrrRrrrrjrrrrqIrrrrRr
+rrrjrrrrq2rrrr"rrrrJrrrrmIrrrr[rrrrrrrrrrIrrrrJ!!!3!$rrrJ!J!!-!)
+!!#J#!!!N!J!!)J)!!$mrrr`"3!!#!Crrq3'J!!8"S!$P!DUdj3'UUZ8"V+VP!D!
+!"3'J!!8"TS!&!DX!"3'J!!8"S!!&!DD!"3'V!!8"S!!&!D!!"3'IrrN"3!!#!6r
+rr!%#!!!"!J!!!3)!!!%#!!!"!rrrr`2rrq!$rrr`!rrrq!2rrr`$rrrq!rrrrcr
+rrrprrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
+rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrprrrrr2rrrr`2rrrm$rrrr!rrrr`2
+rrrm$rrrr!!!!32rrJ!'8!DJ"J!'!!C3"U!'!!B#"J!'UXBUjT+Q!!Irrrrrrrrr
+rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrm!!!"!Ir"!'%S89"j!!N!#5J*8!N!
+#3!*9BP9b9A**8N!#Irjrm(riIrarrRrqIrjrrRrqIrjrrRrqIrjrrRrqIrjrrJ!
+!!%"rrS!"RrQP"DS&S!@U[DUpT+fJ"CrjJ!&rrM9@DUYrrhrqrrrrrrrrrrrrrrr
+rrrrrrrrrrrrrrhrq2rjrrhrr!!!!3"ri%!`3#RrrJ!QIbD!TTUQV+D!TS#QIbB!
+*Ir%3!4rr(rJIr"rqIrrrrrrrrrrrrrrrrrrrrrrrrrprrarr(rm!!!#!rrrrrrr
+rrrrmc-c-c-c-crc2cmc-c-c2r2cmc-c-c-rmc-c-c-c-crc-c-c-c-c2r-r2c-c
+-c-rmr2c-c-c-crc-c-c-c-c2r-c-c2c-c-rmc-c-c-c-crcmr2cmrmc2r-cmr2c
+rr-rmr-r-r2cmcrc-c-c-c-c2rrrrrrrrrrm!!!#!$rrrrrrr!!!2$!`-$!r`!!r
+!B'$!cmm!$`B'$!`2rr!2`-$!`-$1m!m-$!`-$!l`$m"JB-$!c[!2"JB-$!`1m!r
+!`-$!`-l`$``-$!`-$[!2aXE'aQ$1m!m'"JB'CJl`$m"JaXCQc[!2$!`-$!`1m!r
+ZlZlZlZl`$rrrrrrrrr!!!!#!$rrrrrrrrr$mc-c-c-c-crcZlZlZlZl[r1q2Mrr
+rr1rmk2Mrrrrmlrc[rrrrrrc[r1Miq2L)r1rmk2Miq)Mmlrc[MrMiq2c[r1rrrrr
+rr1rml-c-c-c-lrlZlZlZlZl[$rrrrrrrrr!!rXl1cXl1m!rXl1cXl1cr$rrrrrr
+rrrm!!!#!!!rrrrrrm!!!$``-$!cr!!!2`-$!`2h`$rrrrrrrrrrmc-c-c-c`crc
+GhGhGh[`2r0rrrrrHm-rmhrL2Mplm$rcIMiMrh[$2r0rrrrrHr!rmhrrrrpl`crc
+GhGhGh[`2r1lZlZlZm-m2rrrrrrm-$`!2`-$!`-$2!!rrrrrrrrm!!!%!rrrrrrr
+rrrrrrrrrrrrrrrmU+LSU+LSU+LSU+LSU+[rr+LVr+[mU+LSU+LSU+LVrrbVr+[m
+U+LSU+LSU+LSUrrmU+LSU+LSU+LSU+LSU+[rr+LSU+LSU+LSU+LSU+LVrrbSUrbV
+r+LSU+LSU+LSUrrmUrbVr+LSU+LSU+LSU+[rr+LSU+LSU+LSU+LSU+LVrrbSU+LS
+U+LVr+LSU+LSUrrmU+LSU+LSU+LSU+LSU+[rr+[mUrbVr+[mUrrmU+LVrrbSU+[m
+UrbVr+[rrrbSUrrmUrbSUrbSUrbVr+[mU+[rr+LSU+LSU+LSU+LSU+LVrrrrrrrr
+rrrrrrrrrrrrrr`!!!3!!rrrrrrrrrrrrrrm!!!!!!2repIAepIAepIArr`!!!!$
+rpIAXpHcepIAerrIr!!!!rrAXpHcepIAepIrrrrm!!2repIAepIAepIAepI[r!!$
+rpIAepIAepIAepIAlr`!!rrAel2AXpIAepIAeqrm!!2rel2AXpIAepIAepI[r!!$
+rpIAepIAepIAepIAlr`!!rrAepIAepIAepIAeqrm!!2rel2AXpHcel1cepI[r!!$
+rpHcel2AXpHcXl2Alr`!!rrAel2Ael2AXl1ceqrm!!2repIAepIAepIAepI[r!!$
+rqr[lqr[lqr[lqr[lr`!!rrrrrrrrrrrrrrrrrrm!!!!"!!$rrrrrrrrrrrrrrrr
+rr`$rp[Efp[Efp[Efp[Efp[ErrrElqr[lqr[lqr[lqr[lrrrfqrrMrq2rrrrrrrr
+fqrrrp[[Mrq2rrrrrrrrrp[[rrrElrrrrrrrrrrrrrrElrrrfqq2rirrMrq2Mirr
+fqrrrp[[Mrq2rirrMiq2rp[[rrrElrq2rrq2rirrMrrElrrrfqrrrrrrrrrrrrrr
+fqrrrp[[fp[Efp[Efp[Efp[[rrr[lqr[lqr[lqr[lqr[lr`$rrrrrrrrrrrrrrrr
+rr`!!!2rlp[[fqrElp[[fqrm!!2rlp[[fqrElp[[fqrErr`$rrrrrrrrrrrrrrrr
+rrrm!!!%!!!!!rrrrrrrrrrrrr`!!!!!!!2mV+bXV+bXV+rrr!!!!!!$r+bXV+bX
+V+b[rqrm!!2rrrrrrrrrrrrrrrrrrrrmV+bXV+bXV+bXV+rmV+rrr+rVkq[Vkq[V
+kq[cr+b[rrb[krrrrrrrrrrVmrbXVrrmVq[rriq2rirrkr2mV+rrr+rVrirrMirr
+rq[cr+b[rrb[krrrrrrrrrrVmrbXVrrmVq[rrrrrrrrrkr2mV+rrr+rVkq[Vkq[V
+kq[cr+b[rrb[mr2cmr2cmr2cmrbXVr`$rrrrrrrrrrrrrrbXV+rm!!!$r+bXV+bX
+V+bXV+b[r!!!!rrrrrrrrrrrrrrrrr`!!!"SC9QPY)$8Z-b`J)%eKBdp6)(*PE'9
+KFf8J-J!!!!`!+!!S!43"S`#!998!!!!L!!%!!!!!!-N")3$G!9X%!Np,!!!!!!!
+8!#3!Y`&CL!*H-!!!!!,rr`!!!"B!!!!!!!!!E3!D!)%!9!3'3R9dG'pZ!!!!%J!
+!!!!!!!!0!"F!,3!hS!)!J!!!!"`!!!!!!!!!$3"1!'B"CSJ,8h4KG'PM)&4PH(3
+!!!!!&3!S!#J"%!'R!!!"!!%!!!!!!!#!!!!!!"8!43"-!'S!G`!&!3!"!!!!!!!
+!J3!!!!!9!*8!J!%P!1`!"3%!!3!!!!!!!))!!!!!&3!Z!#B!D3"d!!8"!!%!!!!
+!!!#$!!!!!"8!13!m!-B"Z3!!!3!"!!!!!!!!K!!!!!%!!!'!!!!#3!!IrDri)!2
+3"#!"m!)3!rJ'#!rm#JJ(q"3)$r!S#!IJ8!J2`+!)"i&`'!m"q#J'!raB$![qZ!!
+ArlJ),rpB!&rq+!$rr"J"2rJ)!6r`#!2rq!J')L3)!c!##"jc0!JZCQ3)IQCN#,c
+-b!6-6-3$Kr-i!!2!!!!"J!!!!B!!!!2!!"rrlrJrrrrm2rrrrKrrrri2rrrq$rr
+rr!rrrrJ2rrr`$rrri!rrrr!Irrri2rrrr(rrrrlrrrrrrrrrrhrrrrirrrrm(rr
+rq!rrrr!2rrri$rrrr!rrrri2rrrm$rrrr!rrrr`2rrri"mrrr!1(mcJ!!m!!!!'
+!!!!!!J!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!!2L2!!!!!!!!!!!2rrrrrrq*Q2$
+rrrrrm!!!m!!!!!!!qCQ2!!!!!!m!!2$-c-c-c-qCR`c-c-c-m!!2c-c-c-cIQCR
+mc-c-cI!!!2h-c-cGqCQCRpc-c0h`!!$`c-c-hjQCQI$-c-hI!!!!m-c-c0qCQCm
+!c-cGm!!!!2$-c-cIQCR`$-c0h`!!!!$`c-c-hjQI!-c-hI!!!!!!m-c-c0qCm!c
+-cGp[!!!!$r$-c-cIR`$-c0hjP[!!!2M`c-c-hr!-c-hIQCP[!!q*m-c-c0m!c-c
+GqCQCP[$iQI$-c-c3$-c0hjQCQCP[q*R`c-c-d-c-hIQCQCQCE`q*m-c-c0c-cGq
+CQCQCP[!!q2$-c-c-c2rjQCQCQ@m!!!r`c-c-c-r-qCQCQCE`!!!!m-c-c-c2c2Q
+CQCP[!!!!!2$-c-c-hrqIrjrrrr!!!!$`c-c-cIc-r-cmc2c2!!!!m-c-c0hrc2r
+-c-c-c2!!!2$-c-hIr-rrc'E-rmm!!!$`c-cGqIc2r-Emcrc2!!!!m-c0hjRmcrc
+2r-rmc`!!!2$-hIqIc2r-rmcrc2!!!!!2cGm!rmc2c2r-rmc2!!!!!2r`!!rrp[m
+!r`$rm!!!!!!!!!!!pQm!!!!!!!!!!!!!!!!!!!r`!!!!!!!!!!!!!%!q[%(#3--
+KaL1-)4`L2Q!ri2jKI#(+)N%R95p9'P8"UMqmIrjrrcrq2r`rr(rqrrrrrRrm2ri
+rrcrr2rmEr`'U!!!!J!$rrrM`rrm!$`!!$jm!!2!2c-c0rmc-h`$mc0qI$-h`!2c
+-hr$-h`!!r-cI$-hr!!Mmc0$-hjR`LIc-$-hjQCrjr-c-rjQCB!rmc-r2rjm!!2c
+-crr-r2!!r-cmcmc-c`$mcIr2cmr2!2cIRmr2cmm!$r$mcmr2c`!!!!r`m2$`!!!
+%!!!!!!$rrrrrrrrrrrrrrrrrrrrrrrrr!!!!!!!!!!!!!!!!!2repIAepIAepIA
+epIAepIAepIrr!!!!!!!!!!!!!!!!rrAepIAepIAepIAepIAepIAerb[r!!!!!!!
+!!!!!!!$rpIAepIAepIAepIAepIAepIAr+b[r!!!!!!!!!!!!!2repIAepIAepIA
+epIAepIAepImV+b[r!!!!!!!!!!!!rrAepIAepIAepIAepIAepIAerbXV+b[r!!!
+!!!!!!!$rpIAepIAepIAepIAepIAepIArrrrrrrrr!!!!!!!!!2repIAepIAepIA
+epIAepIAepIAepIAepIm!!!!!!!!!rrAepIAepIAepIAepIAepIAepIAepIAer`!
+!!!!!!!$rpIAerrrrpIrrrrArrrrerrrerrrepIAr!!!!!!!!!2repIAepIAepIA
+epIAepIAepIAepIAepIm!!!!!!!!!rrAepIAepIAepIAepIAepIAepIAepIAer`!
+!!!!!!!$rpIAerrrrpIrrrrrerrrrrrArrrrepIAr!!!!!!!!!2repIAepIAepIA
+epIAepIAepIAepIAepIm!!!!!!2rrrrrrpIrerrrrrrAepIAepIAepIAepIAer`!
+!!!$r!!!!!!$rpIm!!!!!rrAerrArrrrerrrepIAr!!!!!2mVprFVprRrrb[hpb[
+krrAepIAepIAepIAepIm!!!!!!2rh+rIjrrAr!2FVq[repIAepIAepIAepIAer`!
+!!!!!rb[hprVrr`$h+rVrpIAepIAepIAepIAepIAr!!!!!!$rprIhqIm!pb[krrr
+epIAepIAepIAepIAepIm!!!!!!2mVpb[k!#[hq[repIAepIAepIAepIAepIAer`!
+!!!!!rrFVp`$hprRrpIAepIAepIAepIAepIAepIAr!!!!!!$rprFVpb[rrrAepIA
+epIAepIAepIAepIAepIm!!!!!!2mVprFVrb[rrrrerrAepIAepIAepIAepIAer`!
+!!!!!rrFVprIrrrmVprmVrrAepIAepIAepIAepIAr!!!!!!$r+rIhrrFVrrFVprF
+VrrAepIAepIAepIAepIm!!!!!!2rh+rVrrrIrprmVrrIrpIAepIAepIAepIAer`!
+!!!!!rb[kr`$r+rmVrrIr+rrepIAepIAepIAepIAr!!!!!!!!rrrerb[hrrIr+rr
+hrrAepIAepIAepIAepIm!!!!!!!!!rrAerrrerrArpIrepIAepIAepIAepIAer`!
+!!!!!!!$rpIAepIAepIAepIAepIAepIAepIAepIAr!!!!!!!!!2rrrrrrrrrrrrr
+rrrrrrrrrrrrrrrrrrrm!!!!!!!%!$rrq!!J!!`!)!!+!#!!#3!J!!L!)!!)3#!!
+$q!J!!!J)!!!)#1lYL!J!!!J)!!!)#1plL!J!!!Jq[!!)38*GL%$$!!JK4J!))i`
+!##%F!!JL-!!))#!!##$!!!JKG!!))FS!##*"!!JR93!),98!#"T9!!J*UJ!)#!!
+!#!rrrrJ2rri!$rrr!!rrri!2rrr!$rrri!rrrr!2rrri$rrrq!rrrrJ2rrri$rr
+rq!rrrrJ2rrri$rrrq$rrrrKrrrriIrrrq$rrrrJrrrri2rrrq$rrrrJrrrri2rr
+rq$rrrrJrrrri2rrrq$rrrrJrrrri(rrrq!rrrrJ2rrri$rrrq!!!!J!!!2rrrrr
+rrrrrrr!!!!!!!!$m$!`-$!`-$!cr!!!!!!!!m-$!`-$!`-$!r2!!!!!!!2`-$!`
+-$!`-$2c2!!!!!!$``-$!`-$!`-$mc2!!!!!!r!`-$!`-$!`-r-c2!!!!!2$!`-$
+!`-$!`2rrrr!!!!$m$!`-$!`-$!`-$!c`!!!!m-$!`-$!`-$!`-$!m!!!!2`-rrc
+rr2rmr`rm$2!!!!$``-$!`-$!`-$!`-$`!!!!r!`-$!`-$!`-$!`-m!!!!2$!rr$
+rrmrrm2r``2!!!!$m$!`-$!`-$!`-$!c`!!$rrr$`rrr!`-$!`-$!m!!2!!!2$`!
+!r!m2r`rm$2!!$mc-cIr-c0r!`-$!`-$`!!$mc0m2$-hm$!`-$!`-m!!!r-cIm-c
+I`-$!`-$!`2!!!2c-h`c0r``-$!`-$!c`!!$mc0$-hm$!`-$!`-$!m!!!r-`-cI`
+-$!`-$!`-$2!!!2c-c2r!`-$!`-$!`-$`!!$mc-r2r`m-$!`-$!`-m!!!r-c2rmc
+mm-$!`-$!`2!!!2c-r-r-c-m-$!`-$!c`!!$mcIr2cmr2`-$!`-$!m!!!r0m2cmr
+2c``-$!`-$2!!!!r`r-r2cmr!`-$!`-$`!!!!r!rmr2cm$!`-$!`-m!!!!2$!`-$
+!`-$!`-$!`2!!!!$rrrrrrrrrrrrrrrr`!!!!!)!!rrrrrrm!!!$`!!!!$r!!!2!
+!!!!2c`!!m!!!!!rrm!$`!!!!!!$`!2!2$r$r!2!!m!!!!!!!m!$r!2m2$`$`$mc
+rc2!!!2!2c2r-m2m!m!r-r-m!!!$`$mr-m!m2!2!2c-m!!!!!m!r-m!!!!!$`$mm
+!!!!!!2!!rrrrrrrrm!!!!%!rm#!B)"3J(L!#*E)J!M056)*-XNN#8P*%!NJ#8!)
+rrMr`2rJrr$rq2rirrMrq2rjrrRrqIrjrrRrqIrjrrMrq!!!%!!!!!!!!!!!!!!!
+!!!!!!2rr!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$rZERr!!!!!!!!!!!
+!!!!!!!!!!!$rrrrrrrrrrrrrrlRPjVRr!2rrrrrrrrrrr`!!!!!!r`!!!!!!!!!
+!!!!!rqAQjERr!!!!!!!!!!!!r`!!!!$r!#[hpb[h+rIh+rFVrqAQjIm!+rIh+rF
+VprFVr`!!!!$rprFVprIh+rIh+rVrjZAQjIrhpb[hprIh+rVr!!!!!!$rqIIh+rI
+h+rVkrqAQjHEQjIrjprFVpb[kqIm!!!!!!2m!+rIh+rIhqIrPjZAQjHAr!2FVprF
+Vq[Rr!!!!!!!!r`$h+rIhpb[krqEPjZAQr`!!prFVprVjr`!!!!!!!!$r!2Ihpb[
+hprRrjHEPj[m!!#[h+rIkqIm!!!!!!!!!!2m!+rIhpb[hq[rPjHEr!!$hpb[hq[R
+r!!!!!!!!!!!!r`$hprFVprIjrqAQr`!!+rFVprVjrqrr!!!!!!!!!2rr!#[h+rI
+h+rVrj[m!!2IhprIjq[rPjZrr!!!!!!$rZIm!pb[hprIhqIrr!!$h+rFVqIVrjZA
+QjHrr!!!!rlRPr`$hpb[h+rIkr`!!+rIhprVjrqAPjZAQjHrr!2qjjHEr!#[hpb[
+hprN!!2Ihpb[kqIrQjHEPjZAQjHrrrlRQjIm!pb[hprFVqJ!Vpb[hq[RrjHEPjZA
+QjHEQm2m!rlRQr`!VprIh+rIjprFVprVjrqAQjHEPjZAQjHrr!!!!rlRr!2Ih+rI
+hprFVprIrrrrPjZAQjHEPjZA[r`!!!!!!rrm!pb[hpb[h+rIhrrFVrqEPjZAQjHE
+Plrm!!!!!!!!!r`$hpb[hpb[hpb[r+rIrjHEPjZAQjHrr!!!!!!!!!!$r!#[hpb[
+hprFVq[rrrqArrrrPrrrrrrrr!!!!!!!!!2m!pb[hpb[hprVr+rFVrb[hprmVpb[
+r+rIr!!!!!!!!r`$hprFVprIjqIrrprIrrrFVprFVprIhpb[r!!!!!!$r!#[hprF
+Vq[Vrrb[hrrrr+rI`lrFVrrmVr`!!!!!!!2m!pb[h+rVjrqArpb[rrb[hm2rh+rr
+rprIr!!!!!!!!r`$hpb[kq[rPj[rhprrrprIrrb[hrrmVprm!!!!!!!$r!#[hq[R
+rrqErpb[rrrFVrrmVprrr+rIr!!!!!!!!!!$rprRkr`!!rrmVprIr+rIrrrIhrrr
+h+rIr!!!!!!!!!!$rrrm!!!!!rrrrrqrrr`!!rrm!!2rrr`!!!!!!!!!!!!!!!!!
+!!!!!rqr`r`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!rrm!!!!!!!!!!!!
+!!!!!!!!!!!3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!rrrrrrre!!$rrrrr!!!!!!!!!!!
+!!!!!!!!!!!!!!2m!!!!!!2m!r`!!!!$r!!!!!!!!!!!!!!!!!!!!!!!!rb[hpb[
+hqIrr+rIh+rVr!!!!!!!!!!!!!!!!!!!!!!!!rrFVprRrpIm!pb[kr`!!!!!!!!!
+!!!!!!!!!!!!!!!$r+rIhq[rr!2FVq[m!!!!!!!!!!!!!!!!!!!!!!!!!!2rhprI
+jr`$h+rVr!!!!!!!!!!!!!!!!!!!!!!!!!!!!rb[h+rS!+rIkr`!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!$rpb[h!2IhqIm!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!2rhpb[
+h+rIrp3$r!2m!!2m!r`!!!!!!!2m!!!!!!!!!rb[hpb[hr`!!!2rrrrrrrrrrrrr
+rrrrrr`!!!!!!!!$rpb[hprm!!!!!!!!!!!!!!2m!!!!!!!!!!!!!!!!!!2mVprI
+r!!$rr`!!rrrrrrre!!$rrrrr!!!!!!!!!!!!rrFVr`!!!2m!!2m!!!!!!2m!!!!
+!!!$r!!!!!!!!!!$r+rm!!!!!rrm!!!!!!!!!!!!!!2Ih+rVr!!!!!!!!!!$r!!!
+!!!$r!!!!rrrr!!$rr`!!pb[kr`!!!!!!!!!!!!!!!!!!!2m!!2m!!!$rr`!!r`!
+Vq[m!!!!!!!!!!!!!!!!!!!!!rrm!!2m!r`$r!!$r!2Vr!!!!!!!!!!!!!!!!!!!
+!!!$r!!!!r`$rr`!!r`!!r`!!!!!!!!!!!!!!!!!!!!!!!2rrr`$r!2m!!2m!!2m
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!2m!!!$r!!$rp3!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!r`!!r`!!!!!!!2rr!!$rr`!!!!!!!!!!!!!!!!!!!!$r!2m!!!!!!!$
+rprIrrrIhr`!!!!!!!!!!!!!!!!!!!!$r!!!!!!!!!2rhprrrprIr!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!rrIhrrIhr`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$
+rprrhprm!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!2rhprIr!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!rrIhr`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$
+rprm!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!3!!!2rrrrrrZIm!rrrrr`!!!2m
+!!!!!!2rPr`!!!!$r!!$r+rIh+rIjrrmVprFVq[m!!2rh+rIjrqAr!2FVq[m!!!$
+r+rIhq[rr!2FVq[m!!!!!rrIhprRr!2FVq[rr!!!!ZImVpb[k!#[hq[rPj[m!ZHA
+rpb[h!2IhqIrPjZAPrrrQrrIh+rFVrrrPjZAQl`!!rrmVprFVrb[rrrrQr`!!!!$
+rpb[hprrrrb[hrb[r!!!!rb[hprrh+rrh+rIh+rm!!2rh+rVrrrIrprmVrrIr!!$
+r+rVrjImVrb[rprmVr`!!!2rr!2mVprrhrb[rprm!!!!!!!!!rrm!r`$r!2m!!!!
+"!!!!rrrrrrrrrrrrr`!!!!!!!2repIAepIAepIrr!!!!!!$rpIAepIAepIAr+rm
+!!!!!rrAepIAepIAerrrrr`!!!2repIAepIAepIAepIm!!!$rpIArpIrrpIrrpIA
+r!!!!rrAepIAepIAepIAer`!!!2rrpIArrrArpIrepIm!!2rhprrrprIrpIAepIA
+r!!$rprIrrrIhrrArrrAer`!!rrIhrrIhrrAepIAepIm!!2rhrrIhrrAerrArpIA
+r!!$rprIhrrAepIAepIAer`!!rrIhrrAepIAepIAepIm!!2rhrrAepIAepIAepIA
+r!!!!rrrrrrrrrrrrrrrrr`!!!!%#!!S!!!!!!"3"@J!S!E`%"%CTEQ3!!!!!!$!
+"@3"%!EX%"e*PF'aKBf9M!!!!!!"0!9S!B3'm"!j5CA"XB@0P)#BJ4QPZC!!!!!!
+!D3&D!(d"[!3,8Q9`E'&MC5""E'bQ!!!!!!"h!&)!L3#m"3Y*Cfj[FQ8J3f&cCAF
+!!!!!!(J!a!#+!5i&"P*PCf9iF!!!!!!!M`"5!+%![!8,4@jdDA*P)&G[FQ4%!!!
+!!!!8!&8!0J%l%!P&C'Pd)&4PH(5m!!!!!!"#!&8!C!%l%!P&C'Pd)&4PH(4D!!!
+!!!!6!#d!)`"5L!9'D@jN1UB!!!!!!%3!&J"8!&+)#&*PF'aKBf8k!!!!&3"&!#)
+!m!(Y!!3"!!%!!!!!!!#&!!!!!1J!!!!!!1J!!J!"#%GKFQCTC@aN!!!!!!!!!!!
+!!!!!!!!!!!!!!,%1([G#4!!!!!![fJa3HA4SEfiJ-5ie,M%!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#rEX@T1)J"
+h!&B"qJ'$rrrrr`!!!!!!!!!!!!!!!!!!!!!!!!!8T8aKEQGeB@GPFbp6Bh*TF(4
+TEQF!!3!%!!![fJ!#!#T(BA*QD@9XC$UP6'&ZCh9KCf9c,e0MFQP`G'PZCcT3HA4
+SEfiJ-5ie,M(rr`!!!!!!%&4&@&4dG(Kd!+J`-6Ja!!!!!!)!!!!!!!!!!!!!!!!
+!!!!!!!$rrrrrm!!!!!!!!!!!!!!!m!!!!2m!!!!!!!!!!!!!!2$r!!$`m!!!!!!
+!!!!!!!$Xrq!!rrm!!!!!!!!!!!!!c`r`!!!2!!!!!!!!!!!!!1rrrJ!!$q!!!!!
+!!!!!!!$`!2m!!!rJ!!!!!!!!!!!2rJlrm!!2i!!!!!!!!!!!!-!!!!!!$1!!!!!
+!!!!!!!$`-`!`!2rr`!!!!!!!!!!!m1-!-`$q$r!!!!!!!!!!!2!1-c-`rrr!!!!
+!!!!!!!$`!!!c!2i2m!!!!!!!!!!!m!!!-!$q$r!!!!!!!!!!!2rrrmrmrrr!!!!
+!!!!!!!!!$ZlZlXc-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%!!!!!!$rJ!!!J-!!!,#J!!#`m!!!@"!!
+!2JB!!#-'!!"MKJ!!!!)!!#b2!!!XcB!!*qm!!#$0J!!JMB!!2fm!!!I`!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!2q!!!$r`!!!rq!!!2r`!!$rm!!!rrJ!!2ri!!(rq!!!rrJ!
+!2rq!!$rrJ!!rri!!2rq!!$rrJ!!rri!!"rm!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!3$rrm!
+!J!"!!)!!3!#!!%!!J!"!!)!!3!#!!%!!J!"!!)!!3!#!!%!!J!"!!)!!3!#!!%!
+!J!"!!)!!3!#!!%!!J!"!!2rr`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!2rr`!$rrm!!rrr!!2rr`!$rrm!
+!rrr!!2rr`!$rrm!!rrr!!2rr`!$rrm!!rrr!!2rr`!$rrm!!rrr!!2rr`!$rrm!
+!rrr!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!#!2rrrrrrrrrrr`!!!!!!!!$`!!!!!!!!!!m!!!!!!!!
+!m!!!!!!!!!!2!!!!!!!!!2!!!!!!!!!!$`!!!!!!!!$`!!!!!!!!!!m!!!!!!!!
+!m!!!!!!!!!!2!!!!!!!!!2!!!!!!!!!!$`!!!!!!!!$`!!!!!!!!!!m!!!!!!!!
+!m!!!!!!!!!!2!!!!!!!!!2!!!!!!!!!!$`!!!!!!!!$`!!!!!!!!!!m!!!!!!!!
+!m!!!!!!!!!!2!!!!!!!!!2!!!!!!!!!!$`!!!!!!!!$`!!!!!!!!!!m!!!!!!!!
+!m!!!!!!!!!!2!!!!!!!!!2!!!!!!!!!!$`!!!!!!!!$`!!!!!!!!!!m!!!!!!!!
+!rrrrrrrrrrrr!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!#!!!!!!!!!!!!!!!!!!!!!!!!!+!!!!#J!!!!!!!!!!!!!!Skrrrk1[!!!!!
+!!!!!!!#M-kc-Sc1Z!!!!!!!!!!!!#M-kbM-krJ!!!!!!!!!!!!qM-k-cS2i!!!!
+!!!!!!!!2bM-c1X$q!!!!!!!!!!!!$mbM-cc!rJ!!!!!!!!!!!!r+-c-c`2i!!!!
+!!!!!!!!2Sc1M-k$q!!!!!!!!!!!!#M-kbM-krJ!!!!!!!!!!!+-cV-bM-ki!!!!
+!!!!!!!!+1Xc-bM-k!!!!!!!!!!!!$kc-c-bMVJ!!!!!!!!!!!!m!!!!!b[i!!!!
+!!!!!!!!2rrrrrrrq!!!!!!!!!!!!!!$ZlZlZlJ!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"!!!!!!!)#!!
+!(ri!!$iq!!!IIJ!!(rS!!"Ib!!!6iJ!!&r)!!"rk!!!IIJ!!2Mi!!"`I!!!B$J!
+!%!B!!"rq!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!J)!!!IrJ!!2rm!!"rr!!!Ir`!
+!(rm!!"rr!!!Ir`!!(rm!!"rr!!!rr`!!(rm!!"rr!!!Ir`!!(rm!!!2r!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!2rrr
+rrr!!!!!!!!!!!!!!$`!!!!$q!!!!!!!!!!!!!!m2rrrrrrrr!!!!!!!!!!!2!!$
+`!!!!$`!!!!!!!!!!$`rrm2rrr`rJ!!!!!!!!!!m!!2!!!!!2i!!!!!!!!!!2$rr
+`rrrr$q!!!!!!!!!!$`!!m!!!!!rJ!!!!!!!!!!m2m2$rrrm2i!!!!!!!!!!2!!$
+`!!!!$q!!!!!!!!!!$rrrm2m!!!rJ!!!!!!!!!!$Zl[!!!!!2i!!!!!!!!!!!!!$
+rrrrrrq!!!!!!!!!!!!!!!1lZlZlJ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%
+!!!!!!!!!!!"ri!!!3$!!!&rr!!"#!3!!A[f!!%)"J!"HrB!!3J'!!&VpJ!"#!B!
+!IX'!!$i"J!!$ri!!!2q!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!(rJ!!"rm!!
+!Irm!!(rr!!"rri!!Irq!!(rrJ!"rri!!Irq!!(rrJ!"rri!!2rq!!!2rJ!!!ri!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!3!'q!!!#33!!!J#!!!*$3!!"[X!!"rrJ!!`H-!
+!B(M!!0ai`!#FH-!!R(M!!-"i`!"JH-!!2rr!!"rr`!!!H!!!!(J!!!!i!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!Ei!!!2r!!!$ri!!!rr!!!'q`!!(rq!!$rr`!"rrm!!rrr!!2rr`!$rrm!
+!rrr!!(rr`!!rrm!!(rr!!!"i!!!!H!!!!$J!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#!!!!$r$rrr!
+!!!!!!!!!!!!!!2!2!!!2!!!!!!!!!!!!!!$`!!!!!2!!!!!!!!!!!!!!m!m!!2m
+2!!!!!!!!!!!!!!r`rrr3r`!!!!!!!!!!!!%F`Frr`Fr3!!!!!!!!!!!G%4%Irp%
+4r3!!!!!!!!!"d4%4(rr4%Id!!!!!!!!!(4cF%4rrd4(p!!!!!!!!!"%Gr4%Irp%
+4r3!!!!!!!!$4(0`4(rr4%Id!!!!!!!!!ha%4%4rrd4(p!!!!!!!!!!ha%4%Irp%
+4r3!!!!!!!!!!hrrrrrrIrrd!!!!!!!!!!!hGhGrrhGhG!!!!!!!!!!!!!!!2rp!
+!!!!!!!!!!!!!!!!!$rr3!!!!!!!!!!!!!!!!!!$Gd!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!$rrrrrrrrrrrm!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!2m
+!!!!!!!!!rrm!!!!!!!!!!!!!!!!!!!!!!!!!!!!!r`$rr`!!!!$r!2m!!!!!!!!
+!!!!!!!!!!!!!!!!!!!$j+rrrq3!!!2rrrrm!!!!!!!!!!!!!!!!!!!!!!!!!!#[
+r!2rr!!!!!!!!r`!!!!!!!!!!!!!!!!!!!!!!!!!!qIrrrrrj!!!!!!$rq3!!!!!
+!!!!!!!!!!!!!!!!!!!$r!!!!rrm!!!!!!2rj!!!!!!!!!!!!!!!!!!!!!!!!rrr
+j!2Rrrrm!!!!!rrN!!!!!!!!!!!!!!!!!!!!!!!!!+`!!!!!!!!!!!!!Vq3!!!!!
+!!!!!!!!!!!!!!!!!!!$r!0MB!!$B!!!!rrrrrbX!!!!!!!!!!!!!!!!!!!!!!2m
+!qGJ!!0MB!!$rr!$rr`!!!!!!!!!!!!!!!!!!!!!!r`!!qGMBf0MB!2rrrrmV!!!
+!!!!!!!!!!!!!!!!!!!$r!!!!!!$Bf!!!rr`!rrm!!!!!!!!!!!!!!!!!!!!!!2m
+!!!!!!0J!!!$rr!$rr`!!!!!!!!!!!!!!!!!!!!!!rrrrrrrr+rrr+rrrrrmV!!!
+!!!!!!!!!!!!!!!!!!!!!!!$jqIRjqIRj+bXV+`!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!3
+!rrrrrrrrrrrrrrrrrrrrrrrr!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!!
+!!2m!!!!!!!!!!!!!!!!!!2m!!!!!!!!!!!!!!!!!!!!!r`!!!!!!!!!!!!!!!!!
+!r`!!!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!!
+!!2m!!!!!!!!!!!!!!!!!!2m!!!!!!!!!!!!!!!!!!!!!r`!!!!!!!!!!!!!!!!!
+!r`!!!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!!
+!!2m!!!!!!!!!!!!!!!!!!2m!!!!!!!!!!!!!!!!!!!!!r`!!!!!!!!!!!!!!!!!
+!r`!!!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!!
+!!2m!!!!!!!!!!!!!!!!!!2m!!!!!!!!!!!!!!!!!!!!!r`!!!!!!!!!!!!!!!!!
+!r`!!!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!!
+!!2m!!!!!!!!!!!!!!!!!!2m!!!!!!!!!!!!!!!!!!!!!r`!!!!!!!!!!!!!!!!!
+!r`!!!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!!
+!!2m!!!!!!!!!!!!!!!!!!2rrrrrrrrrrrrrrrrrrrrrrr`!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!$F!!!!!!!!!0`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!h#2Errrrrrr
+E)pcr!!!!!!!!!!!!!!!!!!!!!!!!!0XM)b2E+bXVfb-M)p[j!!!!!!!!!!!!!!!
+!!!!!!!!!!0`M)b2F+p`M)b2FrrN!!!!!!!!!!!!!!!!!!!!!!!!!rp`M)b2F)b-
+Mh!$rq3!!!!!!!!!!!!!!!!!!!!!!!!$r+p`M)b-M)p`V!2rj!!!!!!!!!!!!!!!
+!!!!!!!!!!2mV+p`M)b2E+bX!rrN!!!!!!!!!!!!!!!!!!!!!!!!!rb[F)b-M)b2
+E+`$rq3!!!!!!!!!!!!!!!!!!!!!!!!$rfb-M)p`M)b2F!2rj!!!!!!!!!!!!!!!
+!!!!!!!!!!0XM)b2F+p`M)b2FrrN!!!!!!!!!!!!!!!!!!!!!!!$F)b-MfbXV+pX
+M)b2Eq3!!!!!!!!!!!!!!!!!!!!!!!!$F)p`V+bXV+p`M)b2F!!!!!!!!!!!!!!!
+!!!!!!!!!!2rF+bXV+bXV+p`MfrN!!!!!!!!!!!!!!!!!!!!!!!!!r`!!!!!!!!!
+!+p[rq3!!!!!!!!!!!!!!!!!!!!!!!!$rrrrrrrrrrrrrrrrj!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!2RjqIRjqIRjqIN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!rrrrrrrrrrrrr`!!!!!!!!!!!!!!!!!!!!!!!!!!!!$r!!!!!!!
+!!!$rq3!!!!!!!!!!!!!!!!!!!!!!!!!!!2m!rrrrrrrrrrrrrrrrr`!!!!!!!!!
+!!!!!!!!!!!!!r`!!!!$r!!!!!!!!!!$r!!!!!!!!!!!!!!!!!!!!!!$r!2rrrrm
+!rrrrrrrr!2rj!!!!!!!!!!!!!!!!!!!!!2m!!!!!r`!!!!!!!!!!rrN!!!!!!!!
+!!!!!!!!!!!!!r`$rrrrr!2rrrrrrr`$rq3!!!!!!!!!!!!!!!!!!!!$r!!!!!2m
+!!!!!!!!!!2rj!!!!!!!!!!!!!!!!!!!!!2m!rrm!r`$rrrrrrrm!rrN!!!!!!!!
+!!!!!!!!!!!!!r`!!!!$r!!!!!!!!!!$rq3!!!!!!!!!!!!!!!!!!!!$rrrrrrrm
+!rrm!!!!!!2rj!!!!!!!!!!!!!!!!!!!!!!$jqIRjr`!!!!!!!!!!rrN!!!!!!!!
+!!!!!!!!!!!!!!!!!!!$rrrrrrrrrrrrrq3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!qIRjqIRjqIRj!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!3!!!!!!!$rr`$rrrrrr`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!r`!!r`!!!!!!r`!!!!!!!!!!!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!r`!!!!!
+!!!!!!!!!!!!!!!!!!!!!!2m!!2m!!!!!rrm!r`!!!!!!!!!!!!!!!!!!!!!!!!!
+!!2rr!2rrrrrj!2rr!!!!!!!!!!!!!!!!!!!!!!!!!!%"+bX"+rrrrbX"+rqI!!!
+!!!!!!!!!!!!!!!!!!!!"q38&"38&rrrrq38&"Irj!!!!!!!!!!!!!!!!!!!!!IN
+&"38&"3Arrrrj"38&rrN!!!!!!!!!!!!!!!!!!!(j"5[j+`8&"IrrrrN&"3Arq3!
+!!!!!!!!!!!!!!!!!!38&qIrj"38&rrrrq38&"Irj!!!!!!!!!!!!!!!!!!$j"38
+Vq5X&"3Arrrrj"38&rrN!!!!!!!!!!!!!!!!!!2Rr"38&"38&"IrrrrN&"3Arq3!
+!!!!!!!!!!!!!!!!!!2Rr"38&"38&rrrrq38&"Irj!!!!!!!!!!!!!!!!!!!!!2R
+rrrrrrrrrrrrjrrrrrrN!!!!!!!!!!!!!!!!!!!!!!2RjqIRjqIrrrrRjqIRjq3!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!rrrrq3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!$rrrrj!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$jqIN!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!J!!!!!!!!!!!!!!!!!!!!!
+!!!!2!!!2i!!!!!!!!!!!!!!!$q!!$q!!!!!!!!!!!!!!!!$`!2i!!!!!!!!!!!!
+!!!!!rJ$q!!!!!!!!!!!!!!!!!!m2i!!!!!!!!!!!!!!!!!!2lq!!!!!!!!!!!!!
+!!!!!!2i!!!!!!!!!!!!!!!!!!!rri!!!!!!!!!!!!!!!!!lq!2i!!!!!!!!!!!!
+!!!$rrJ$rm!!!!!!!!!!!!!!2l[i!rJm!!!!!!!!!!!!!$`$q!2i2i!!!!!!!!!!
+!!!m!rJ$q$q!!!!!!!!!!!!!!rqi!$ri!!!!!!!!!!!!!!1i!!!lJ!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!3!!!!!!""!!!!33!!!#)!!!!L!!!!&!!!!"3!!
+!!)!!!!(!!!!#)!!!$MJ!!")N!!!5*!!!%L3!!!`B!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!%'!!!"KJ!!!)`!!!$-!!!!@!!!!(J!!!!`!!!!H!!!!F`!!!21!!
+!(c`!!"mq!!!I2J!!$a`!!!`B!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"!!!!!!!!!!!
+!!2q!!!#"J!!!JB!!!i'!!!1"J!"rcB!!Iqf!!(rKJ!"r`B!!!i'!!!1"J!!!Ki!
+!!*q!!!$rJ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!ri!!!2q!!!$rJ!!$ri!
+!!rq!!(rrJ!"rri!!Irq!!(rrJ!!$ri!!!rq!!!$rJ!!!ri!!!2q!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!rrrrrr!!!!!!!!!!!!!!!2!!!!r`!!!!!!!!!!!!!!$`!!!2m!!!!!!!!!!!!!$
+rm!!!$r!!!!!!!!!!!!!!mr!!!!r`!!!!!!!!!!rrrr-r!2m2m!!!!!!!!!!2-c-
+c-r$r$r!!!!!!!!!!$c-c-c2`!!r`!!!!!!!!!!rrrr-r!!!2m!!!!!!!!!!!!!$
+cm!!!$r!!!!!!!!!!!!!!rr!!!!r`!!!!!!!!!!!!!!$`!!rrm!!!!!!!!!!!!!!
+!m!rrrr!!!!!!!!!!!!!!!2rrrrr`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)
+!!!!!!!!!!!!!!!!!!!!!!!rrrrrr!!!!!!!!!!!!!!!2!!!!$r!!!!!!!!!!!!!
+!$`!!!!r2!!!!!!!!!!!!!!m!!!!2rr!!!!!!!!!!!!!2!!!!!!$`!!!!!!!!!!!
+!$`!!!!rrm!!!!!!!!!!!!!m!!!$mc-m!!!!!!!!!!!!2!!!2`!c-m!!!!!!!!!!
+!$`!!$m$-c2!!!!!!!!!!!!m!!!r-c-c`!!!!!!!!!!!2!!!2c-$-m!!!!!!!!!!
+!$`!!!2c-cm!!!!!!!!!!!!m!!!!2rrcr!!!!!!!!!!!2!!!!!!$`rr!!!!!!!!!
+!$rrrrrrrm!r`!!!!!!!!!!!!hGhGhGd!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%!!!!!!(r!!!"!B!!
+!3&!!!%"i!!"!#!!!3(J!!%#%!!""!J!!33)!!%%#!!""!J!!3)3!!%"l!!"!#i!
+!IrQ!!!US!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Im!!!(rJ!!"rm!!!IrJ!!(ri!!"rq!!
+!Ir`!!(rq!!"rrJ!!Iri!!(rq!!"rrJ!!Irm!!(rlJ!"rqB!!$r`!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!r`!
+!!!!!rrN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$rq3!!!!$rq3!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!$r!!!!rrN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!2r
+j!!$rq3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!2m!rrN!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!rrRrq3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!rrN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!2rrrrN!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!2Rrq3!!rrN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$rrrr
+j!!$rrrm!!!!!!!!!!!!!!!!!!!!!!!!!!!!!rrRjrrN!!2rj!2m!!!!!!!!!!!!
+!!!!!!!!!!!!!!!$r!!$rq3!!rrN!rrN!!!!!!!!!!!!!!!!!!!!!!!!!!2m!!2r
+j!!$rq3$rq3!!!!!!!!!!!!!!!!!!!!!!!!!!!2rrqIN!!!$rrrN!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!qIN!!!!!!2Rj!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!2rrrrrrrrrrr`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!r`!!!!!!!2rr!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!$r!!!!!!!!rrm!!!!!!!!!!!!!!!!!!!!!!!!
+!!!$rrrm!!!!!!!$rr`!!!!!!!!!!!!!!!!!!!!!!!!!!!2rBr`!!!!!!!2rr!!!
+!!!!!!!!!!!!!!!!!!2rrrrrrrpMBr`!!rrm!rrm!!!!!!!!!!!!!!!!!!!!!rpM
+Bf0MBf0MBr`$rr`$rr`!!!!!!!!!!!!!!!!!!!!$rf0MBf0MBf0Mr!!!!!2rr!!!
+!!!!!!!!!!!!!!!!!!2rrrrrrrpMBr`!!!!!!rrm!!!!!!!!!!!!!!!!!!!!!!!!
+!!!$rf2m!!!!!!!$rr`!!!!!!!!!!!!!!!!!!!!!!!!!!!2rrr`!!!!!!!2rr!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!$r!!!!!2rrrrm!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!2m!!2rrrrrrr`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!rrrrrrrrrrrr!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!3
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!rrrrrrrrrrrr!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!$r!!!!!!!!!2rr!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!2m!!!!!!!!!rb[r!!!!!!!!!!!!!!!!!!!!!!!!!!!!r`!!!!!!!!$rrrrr!!!
+!!!!!!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!2m!!!!!!!!!!!!!!!!!!!!!!!!
+!!2m!!!!!!!!!rrrrr`!!!!!!!!!!!!!!!!!!!!!!!!!!r`!!!!!!!2mVprFVr`!
+!!!!!!!!!!!!!!!!!!!!!!!$r!!!!!!$r+`!!prFVr`!!!!!!!!!!!!!!!!!!!!!
+!!2m!!!!!!2rh!2FVprIr!!!!!!!!!!!!!!!!!!!!!!!!r`!!!!!!rrIh+rIh+rm
+!!!!!!!!!!!!!!!!!!!!!!!$r!!!!!!$rpb[h!#[hr`!!!!!!!!!!!!!!!!!!!!!
+!!2m!!!!!!!$rprIhprmV!!!!!!!!!!!!!!!!!!!!!!!!r`!!!!!!!!$rrrrr+rr
+r!!!!!!!!!!!!!!!!!!!!!!$r!!!!!!!!!!!!!2m!rrrr!!!!!!!!!!!!!!!!!!!
+!!2rrrrrrrrrrrrrrr`!!rrm!!!!!!!!!!!!!!!!!!!!!!!!!q[RkqIVjq[Rkq3!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!3!!!(B,!!"e#`!!"*m,65PN"2i!!!!F"&S!$8*
+14%`!!!"b4P*&4J!#!(jTBf`d!!d!SQPME$J!$J&+5801)`!0!IjTBh-M!!8#TQP
+MFc3!"3,ZD@0c1!!&!cC@58dK!!!$IN&-8P3!!!1+4%P86!!&!jC%6%p(!!8$hQ&
+XDA-!!!3Q4e@h53!!"$)!J2rr!!!!!!!!!!!!J2rr!!!!-!!!!!!!JIrr!!!!1`!
+!!!!!J[rr!!!!4J!!!!!%DIrr!!!!83!!!!!%D2rr!!!#93!!!!!!J2rr!!!%@3!
+!!!!!JIrr!!!'A3!!!!!!J[rr!!!Ph!!!!!!!Jrrr!!!YX!!!!!!!KIrr!!!mU`!
+!!!!!K[rr!!"!Y`!!!!!!Krrr!!"#Z`!!!!!!L2rr!!"&``!!!!!!LIrr!!"*c`Y
+0*f3!L[rr!!"Ij`Y0*ZJ!Lrrr!!"Mm`Y0)q3!M2rr!!"Pp`Y0*c`%DIrr!!!)B3Y
+0*q!%D2rr!!!-C3Y0*m!!J2rr!!!3D3Y0*m`!JIrr!!!8E3Y0*lJ!J[rr!!!`I!Y
+0*mJ!Jrrr!!!SU!Y0*m3!K2rr!!!dJ!Y0*l`!KIrr!!",d`Y0)$!!KJ!d!!"2e`Y
+0*l!!K`!V!!"6f`Y0*k`!L!!p!!"Ah`Y0*kJ!LIrr!!"Ei`Y0*k3!L[rr!!"Sr`Y
+0(ZJ!Lrrr!!"Y!`Y0*d`!M2rr!!"a"`Y0(Z3%D2rr!!!BF3Y0#ZJ%DIrr!!!CG3Y
+0+!J!J2rr!!!DH3Y0+"3!JIrr!!!EI3Y0+$`!J[rr!!!Nf!Y0+!`!Jrrr!!!XV!Y
+0+"!!KIrr!!!qV`!!!!!!K[rr!!!rX`Y0+4J!Krrr!!"%[`Y0+"J!L2rr!!"(a`Y
+0+!3!LIrr!!")b`Y0*hJ!L[rr!!"Kk`Y0*Z!!Lrrr!!"Ll`Y0)r3!M2rr!!"Rq`Y
+0*#`%D2rr!!!FJ3Y0+#3%DIrr!!!Fa3Y0+#`!J2rr!!!G#3Y0+'3!JIrr!!!G63Y
+0+#!!J[rr!!!Ri!Y-+X3!Jrrr!!!`1!Y0+$!%D2rr!!!GN3Y0)X3%DIrr!!!H&3Y
+0(P`!J2rr!!!HQ3Y0*!3!JIrr!!!I(3Y0*`3!J[rr!!!S*!Y0(Q`!Jrrr!!![Y!Y
+0(P!%D2rr!!!IS3Y0)P`%DIrr!!!JT3Y0)P!!J2rr!!!KU3Y0)Q!!JIrr!!!LV3Y
+0(i!!J[rr!!!iK!Y0)P3!Jrrr!!!jL!Y0)Q3!!!!!!!!MX3!!!!!!J2rr!!!Mc`!
+!!!!!J2rr!!!Mh`!!!!!!JIrr!!!N"3!!!!!!J[rr!!!N#`!!!!!!Jrrr!!!N*3!
+!!!!!K2rr!!!N1`!!!!!!KIrr!!!kM!!!!!!!J2rr!!!N@`!!!!!!J3!2!!!NG!!
+!!!!!JJ!8!!!NM3!!!!!!J`!F!!!NTJ!!!!!!K!!K!!!N[`!!!!!!K3!Q!!!lNJ!
+!!!!!jIrr!!!lU`!!!!!S!Irr!!!mP`!!!!!16hGZCA)JFQ9cEh9bBf8%6@&TEJG
+#GA4dEfjc"%PMEfi%9'9iG!4'D@jN#(4LAf0XEh0P#(4LAf*XB@jV"h4LAf0[F(R
+VL!:
+
diff --git a/src/os_mac.sit.hqx b/src/os_mac.sit.hqx
new file mode 100644
index 000000000..50088b359
--- /dev/null
+++ b/src/os_mac.sit.hqx
@@ -0,0 +1,439 @@
+(This file must be converted with BinHex 4.0)
+:$hCTE5de,MBZE@0`,R0TG!"6593e8dP8)3#3"&'B!*!%ZHK6G(9QCNPd)#KM+6%
+j16FY-6Nj1#""E'&NC'PZ)&0jFh4PEA-X)%PZBbiX)'KdG(!k,bphN!-ZB@aKC'4
+TER0jFbjMEfd[8h4eCQC*G#m0#KS!"4!!!&'B!*!$FJ!"!*!$FPrf$D@P8Q9cCA*
+fC@5PT3#PN!3"!!!l!!#`q3D&Y+rST3#3$3[QD3!$hFd!!&$(!*!%$`"fD@dY05i
+f,QeMF!!!GjK069"b3eG*43%1!#J!j!#3#S!!N!G#`G5QH4&%pRa-K%E4UkZTaQU
+"-+X6)&,K$@Ym*hGC)9h[D9T)ZEHSeeHe%$lr48T9p$Np&PbAqU*p#C!!+pBqC2$
++(31mjb(d"cp6ITbIbU"PqNF#%Zi9$cAX6!'AN!!&&V4DC$iT%SSTLC!!c[YQl9D
+Qp5MRKAG)535FVqmN!N4lI[%(AZ,B"D)MXT!!6J!&d6Fk[m%mTSS,%0c&qK```4N
+bpANj3J1'Ri`LH5iFih`cfqU9r6PHD1(l0VT"db(a3fJ6KjSFJ1M&"SD3!03-kbd
+,5qaVNFl5chH'Bhm1C&IbETH!f-ZD8iX)pZCmMd3XC&&2l9G30%#AcQ(G)e!QUZU
+pip2FGeAjlM9,MfZ,`@@ldcQUDE9'XpUYMTRS0fI*d53$Ib5VUfMFB+Gc88)H2$M
+N[@Y((@0LD8J[M3ai'1(aILiJ+lCe@aMFqA$*NI)X4MG'K2*k0FFf9!m%%GJb+`5
+''M#,ZNDd%5hkISBL"*rq,cI`",@IljEQ*d)8Rl1J+Abc@emj6Qf6JYN@@-j`p+G
+XN!#ZYM,Jh-QjI(),d%P*XDb2If5!Pb'"##K98jjh6bdhX*2'rVU@ZEB4fNaUUkh
+%d2QZLU'aEP$&-CDA4Y`a$2hR2iUi%2-3!J05TbBe"1q[pBhBQXN1r"K04H2RR"K
+4ikr*J8k9[0aZI9k4+'""l8"&m9V6Ue9QSUrrrcfSL-eK+X*$BCmLTl8qa8dldDj
+!Ilr2lerNCca$`Uf($,TN0r2CT$GNUSKDlRS1`"4%KjqF#kA[BmZ3!0"CIV2%PZa
+aM-Zr[k*l)DPRTC,KpXJFVp6Vkqj13aQ`lLQ#Fq,hYF12[6#!DLfNVBQYQc@(0&`
+rlr9&%Ubmp+X(&PE-b1V+U`2BhMI`V"hZ!N#9(P6,I6bla-Qh,#X-a4m!JbMJ&#'
+'PTMHN!#PlXkZB$0ES)L([`YeUk3HG9-)!-HKVYC,Em1BB%j)d`8m-i,*10U*NTa
+L(6qMI`fBX#V2DIka'l`r2L#2&956a"UBXHVbG&%dX%G*AG3JE-3ZbT%fFF+kI`V
+P`LP`)Tjb`(S&K#S,3*a+l0@L%8Y!TqL5'fbhrQjlB"KGDFfP@Q+3!+hcE!pR[Mp
+-i'r&IN5-YNG["E+[P#NFm*!!r-jDTIB[A)A`q%T!SIr*0U4(26LGUQ,NNQUmG93
+d$FNZC(+BK)`lR&'$'fD#NR'TV&F5%`EH"XeEPQHcZlj[bqimQK,21l**B63Ef@,
+Z)U0dlQ,V`J+BB)'&+b5DijN49#LEI!a34hJ&Sj[`AP#p`&D0&rjTfhGIfFS[k0!
+[[d0(F5,ePc!kc-hR1P!dK`h!5PIjZr"EqX9#dJpU4(2VbSc8ee861++3!#SrcY#
+ma3XfbAq,br4qk1[G9fdh*hi$q$P3i`Q4[rDBe%8jVCjSkiaGXR&ma@jp&Y3lbUI
+9(kC&I@eH$-b1,&CUZFDYiZ1rDG-Mb2ek(K1Fdp"-(5@Q&8$J""&"H"1V2qFD4D9
+1i[3SKAkA3-J%dN`UXBSJ)P9QmRR&GiFrN8MJdQAjb*2'pUre0AGcm5rmU96%$kr
+k6!i6HKfU5&8fIhP8,'"*@plIf'"FQS2r'8dqHYfYYZ4f4e,Q[hKRreYV'6$0B$F
+@`KlYiHFMVbASScJM&eHLZ`pi6`XX!aia[0bA,3pF$)f*-J3F(XJU1Ir%P$k*'!Q
+mcI56lRH#S+2G#fB2q*A#[l6C2DP9qU6i#8(Z2b*@J@9&Y"jq'biC`P8*Ya%#-FB
+,"kFaJR"rP5&[hpfDeIfUjb0M31#Q9DJR(E8Z$'[hjVU+#(MR"9cY($"H6mJfhr`
+!Y+`ApCV#'i*I(i,afTp6k#R9-63ZVe%J-'GP*Lb"b'3i2N4#E1@+GM`AXYR"c`P
+*'+J8`qTDG*!!9S+0U1U%@39EB&#-eSci4Xc30m"FJZLZVi2Y!)cBK$'b@E"2j@B
+)*hfbclr&'3%&1)@$4l6RmH4#`"@Z1aV)"fm8qZ9%%0*9@!P`Kk'Slc#,0Tr+0'U
+Ei-r&1)i-+H8&HqMr9M3)3[)cJM"qQe6*R[ZPf'9IQLEY+lbELHU*5DH#[N$L(V8
+h%P"6@e"q)KL"EZUVL!3+V"&)Y+b"RJ4HEI[dbCi,%j!!Vh"-b&JMKVAbYa!Lk"6
+b55IDV8j"qa5#B2E,L%H6ZehmmIfAB4QK!UXEMBe-Fd2pFm2!'qcqBd82mp6X1)6
+HEIQhIGX#$B9i19`i+$C')T,ri4%aThaK3Z"6'!fM09N+!bKV"26+'!H*jL1Fb%f
+SVi4c#,&iqY8&RVd6+S"K$$!fY`i3(FXklKRT6,rK8%G*a*!!dV4X"I1DjI)"SjP
+5IR1Y2ThmlNcl8NGTP02A'')`-!MlIE"qq#@UP),p""S(c,#daeR#Da'%R@cM5lE
+j-(3q,%aSrc8f#@lNiV3H@Xm#VPJMRTXPYC5+#Re15)HH*+CZ[+S!e3,D)eMT#FX
+B@h8fZmBLAM')6a0kI*jKATFHfAcRd59c945E(q+5l4T%GMI4h!!9,j2Lm$rKcJV
+'H3cHFZl-kMiMKVSFFKk3!#Tji55j$R#`(qP83-I"jQF`fQK1B'2E)EZepHC&X)L
+-rSST[HYS4,NrDq'IKd0"4S"A$kE`A0kj*m@flkF%ABJ8-9ZFH93dU,I(k)RdmC1
+1*"l`1Ed&f!Vic(D`r$4)CfkaJl[GBmd#%iZ!,c0QK#$M3f`(&9p9$9Y+*-b$lLV
+-4PDm1d$136*-lX68MXFlMSkCl'ZNeGDCE)TdbU#'#[4rdr2h1@@'&r3SDqQSPh'
+5'k1EL39k3q(2&erTqAT+"9maP2kAIi5Dq&e8VqYBJj[FV`,'&FH%`kClMA&*1h1
+SS$2Y`T,Z%KY&DYTkD4R%Rh&2cY!L*G5+[#4[8*C%B,pICjICr1qV4ZcFj[9S$0T
+R`NL3!+HNCZ+rEla(#b4i('4H&J'BKY'PUe!&bqpf%YjTPMq2JQ)[NK4+SKKAG,Q
+NY44SIZXK-ZP!AL6T2hQhqD9iU[TD9Hi*lC2Iak1qr9Hi%iF0rjiG+N[UER2QLmA
+b9kENc3ib*2E&c,#qZ95+Q"4!4lkb4NbahS',@"JaN!$[d6"B@2C&VT[h1FDLiri
+c-c$@JI`ITFq-p1CI`Gll6B0(0,!Dh#2C5Y)Pl'-iZPc38`h81jUahRd6lX(X`Vb
+9'C0-U$eAQ-YVCXp2*2rLp91@Ck[RSr#hKeGTB+&`S!6l!k+!9G"iPiP0#%5251*
+8PL2fNMCp[riemVeK0(m&YT!!!QQFkfl!r[@`p2%L*ZZhU"@!YM'-$j5H'DCN#(j
+S1*81mXZaf*,-mUe*@*2+2Q'ai+jJC[m@C*e)A"l@jaH!fE![ULZmeLp(h@TBii!
+lkbG+2pjT@iZXcB5I0KL0@e%rlRIQYeRN)@MPhBLFJfcErQ$Mbji'@F["RiR[)%e
+"p5-UHM$PA0"8P"eHT*UpI[SMi+,BF[$EZRXbU"@"f)1VEcaAU,UbTK-A)lf,&Yf
+(DARP8@Hf[pV3@llMq!fMb5i1hDj-4)IF15S-cb)"cA#Di'`4pX2K8!iP[rrQPel
+i@42$5fP+*G$$dS!p5@)GQ4%LKCpN`5S9lif-!c(#&5p0iI[FNUJFi6%Y&T@LD&`
+[QVK34ih,J5Za5cYBll[#cPG@+2Ir-D&)NT!!Uq[85RK`Lk!3a"aC#SDmZ#@Q[Mr
+bTbb"[!Q0f-1rkBIpL%C-[eUFPX!''D+F,*YV$phA&bM15X(6hD"TBSS2PVE[h%%
+jcFTPc5k0q5A9-X`6QfZbIk"h+MH"6&Q[*Cr&CHkBkZY4GMJc6*JP#QfFbrB,fMm
+5`Qk@2L,bhT6$%c#q&q64I@`CIGZKRK0%G)V"S9m9+6&aIl&6RCIm`3ce102(VBM
+"D#A)kjifd$"dmFjJFbTVk`ZXb#5l9hG1ZFVGVV[`$(Z09"G8XB5p53E#X@j[R%m
+IH%-L3U'l%PMZhAXAmk[GL`cKT%)2$dSi4[QFSeYG)#hp4LN+f`"V9!k[kUTiC%8
+M`Pak-MH9,r)46d(L@!#!V)N@YQaX'4VJ4Af4keK%U)IC4UUD,iNGq!'0c@8Qp0Z
+@8!Pd+E4"V0b0kCDC'(VJffU4'%BT2j[P&)@JBmZj-T9kc4,JpcH-bALAhR4Q6`f
+"3Hi#pP#Km`6VGYMJ0@cCKRB,$I*T&4Z$V%AppP",T4HMSI2S&DH8M9P5%*qJ'r0
+JKRZZr4A0JX%-B'aE5XJCreK@*cp)YjdEYRN'3LiFGNXr!PXKikVM%0GHGUM!1Gj
+Tj`,Z%YAKT[AZ%a-IlqkbGF!'m#2V4+INhN,B,8j#%XRDerk[J)KU9"ebP)TQbX#
+R#$8kpQ$A(V`U+#'[rUVr8eFiEC8DLSp)qMNdK$(ZS`e(52&FkIR-#,ahL1F4I`k
+l"-9MIS+LSrUfQeYIG*JC!+1@46$AHcVPrPk#lCQEd%i1+*(fTUm4UE-`hcM'$b@
+#QD[[bb32PS8`-d-@Xj6dZI88re+BjYa2hD-e@#A+M&ejCSAX%&Fa2mq!YSjA@!E
+)K0kkke9QeQNlkrKMp$1SCKr$,&pj2!q40`j8(!%D(1%AUq+*QLS5L[%c,`*S[Ej
+XfbQjI#5C$BqK[rFl%43+UUSX-BL&9KYp"HVfZRe*XRaq"G*44fe8D9l#%Hbp,L*
+PC3$1XBGhDKSm6"1C,iiFbUQ3!%#`Y8D83YqrL1V3+CT!+F!8XUfk`#!G0AFkNPe
+%EMMr84@[G0Ql2C92G+,-4Y-3628+"NKTRHdhd#'iHrTemmEhIdb(G)lPAcPN$@-
+(hrpAc`a,+N3m(V#3!,4K,`H0dP6q611[XBe"r%hX5)0['Cd"`8rlqXACI,KQ5SN
+#[ZmD2@1J$'bXkEC&Qr%M8+KX"T8'E8r03T2Jha-JQ5VC'32RNrefVb9Ge#'pf[b
+J3!QCr92HRr%4GaDP@X`'G,Ciq)NL%j6T,2VVG"e)LBKL5hlP$kErE(@4+R'Cc4l
+I3)KMD63ITDeThSJ"HiZ1XP%5-4XQ@b@KbRTkYXU5rAGIqVRLf'B2jI,GUV(0i49
+Q0-PJk16'$Fi0VE3b"YM,'j`!@6PZ,Q!DIlAmE0K(p52r[SPCRl(j'SM6m'0E$Z1
+Ed$M%SbGc6Mhm(L'a*TrE3Q1Ehije3'ah,M#SfbpqUBS+`ZLq)F#S4aX`*jB#l"+
+PpmSj"[%3b5&Q-VFe0r8SZUVY4D(ir9kQqqXHK1&m%p'VI6Gjmdmk-0T'b4Bi,%A
+Tfj[JYITBrSE)F$'`mqI@*1**!'#NjrAh@+UYi[barS*0h9HYdmKcajNY$+qeXDI
+b&2a0)3M[DQ$M(iI#-cZ"GRaVdZD9pSCbbL9r1*!!la!V9I+0rK2K`)!q+4*qjTK
+'SHBU26rh4l,dCYDI`bRM-q`-(VR2ICB,SYT0f+FK!L)R@@PcYKR'%ipA&4aP2(S
+N4!CeIqpXE##XRjDmjLVqZT68+V#ZLHl"LZ1@6L&TV*5VYEBpGk-LG`%1*faeq!j
+,jYjpqrdr+5[YQ14*Y&QKS6kCHX5([Y"XXG(jL3iU@CQ3!%*S$$Z")1cfG19mfG0
+8[XjB@Ge,&"rG$DZ(+![lQNC3-+2Je6XHdrYJN!!la660#Ua5i3c'"4TC3RN,8h5
+KJQcKaa$8A8UCk3%ilT!!(c*b5$ALB"JDkf@@YVcB`%lq(Jh@+Gb-LI1kIRRdS#T
+m""fdXpFj4Ihfe5%`#QZkcq)f+N$4BY1$L*a#m$Kq95PLb9S%jVi04-(Pr*Lchac
+ppF%Yl0+faU8BQU$[fAjQ--5D&R5iiZJ&kX2#X(H'`Ua$m6ZPLe"%1UBiZAHpd-R
+K1$R)Y(iZU"d"MPI'ZCS6T,bPjK0'N!$`cNFi0b`c093dMX'F*G*kkI![6PCUL21
+AQ)Kp#TjUH,e4eSK[@P'Vd(c3M6,SpaqpVE'h*1%ZVTrR3*J8S)$C*eeQSc*PYe*
+C,25V4XaPRh!Dq4#&-KB6*#@YKC,N(GpQi)X6F*ZT5[-EhHYAEJ(X9HC5MHr9$AB
+Y"EMHqq"+9rN04J'ElFG-KYE,&q+06Gh$2Ih++$J#-Q4$IkdqC)S+!5aG5*-1dfp
+jUkdIB3,AKI3DT$E*YY2!%"phc9QSkd!TmEbMeTR8)Al5fXI0EqV5fC5[P!(JLY#
+8@RGkF"6rqbHTMXRL))88cT84LFKf+`SDPk-36'65B`af3[PD*P[EG&[H4'TZ'VP
+&qB)5)m!r$bJITKDSfAJ%@QGR!"X0EU,rM1R"9m9YNLi45)fhQ2hj8T!!U'8)'QN
+kLS-H`NZ%%X`'H%hE%I183I8kjE[iddHSfm1qY8dJiFb''3'%Ik!f4q[46f#h$mY
+qfZdc$!C9hFII2DrA+`rEP`3imIX8!3km"$EUbSB&T[1X$RN1BX`#Cj,`0)"I29*
+(iST%406dR-(E6!,"5AQF8KNXE*XmEbDHJIb&6Slm3q-icI(4N4YkLe$e&@rM8I1
+-"Fla%lkH*`--pB`3!8X`8pJ'Jf'[GfCC93IhUAhBL'XX6ITZ!ZSJi[Gh%98fA9F
+[Z$2Vk2iE[FAQ$TT'B)khrNG0b8bl`kKl9"M&22'[-1$l@&mE5dF'63#-L3I@Z`Z
+CA*90X`!bYTNX2p5C'&&qC8*9fPI3+Bc[fXGpm&r!Y*%l+rA23*&D1LeYVBNqTke
+qPL+PC1"%L*c-NKJ(rYUpVHZH,AmbcT[U[$*BLj-"a!S@@cHh!&m&b#E+YE)J5Ek
+K+aERLVI(3A4D`GcLk5,i2'-2QAJ-A&qFHCI@)q3XPC@*M-pd$a[dcdaK3i`&cU*
+aA-`p'I40YPkEdL%m@5cd*V8Re4Zq"BS&QPNpCHcJ5b+&Q$rFrV9kR#rLfYAhi[)
+BZd6pfSjQ'Sp8UE@Lr"jL)CmD+X-6AS,PDQ"Yla*%M'DCKmFl+Q)8GRm&c)Fa(aa
+&rFQL66EI1+"Kd9(GGI8FBPq!%!EL4ahk$leYN9-6V(mTQ6!k9ji@TI4Z%bHe%GS
+R'h5&#V9G1if+XV8N(-Lf3NmKKH08era)8IBFekSm`$4!KaKk[J'm5&dkkpY&*Ni
+N0b)MdR[5!(%UK,`TlRLS&-AEkqUAe1I)+3#2`V-h6KcB+6r&$,`0mUh[FIVB6C%
+KM91cdBPB1caqYhrlaUrEjUjRE3!GMiaL400Kl!T4$eAEG'+VT3Q*`e!*iXY9XRZ
+a94)9Tj[qReVHpp-j*J12Z1X5`QY&Vh3GKq!rN``4@,DRHJ@ppZ-B@2G)9admKSr
+&TqK1mU'a@Zd2@rN$6Kq,-)FY[Z-MQDpEX8ZRL3,AkL3-j&c6#!DPPbFSK&XC*6`
+mD!Lh-DqD@1j%GCJ%D'6L8cJbN!"(8GH*+eS4f+$M62a%IZqfr)Lk4cCAl0Xdj%m
+bm1Zi`IVl"YT9*jLC2Y8c+6G[JFbIE3D%KIqpVCe23Va3jAXlkYZB6Fp!!G#@rk)
+ekD8$Ic[25f2k)rb@,40ADmp6MEd)IPik0fXL2f`*Q6j,bmQZ8CY90fDV2+*XGc1
+V4&PUQTckPP'bkD81cPM9A24"NlGN*BjkM$2#!ETr!&[EqYcRR%BJ-hqqb$lr8L2
+$XKTUMD35HBl8N9X&*bI6!FS0&c)Y+%%NmN3bG)eA30dYP6T,B`1PVEjV#2d3i`3
+8[e04Dr9aqcU2%jCi#3"&6U&D&PTK(LMIi(cMUPm)aR1P'6lRF[M,reK0NDG9`,!
+i2e2P2he4'CZ8'2,V*c(I8ae+G,GiDS+MpEH'pTC9Cb*Ar4Nh0p9I(F*kNf43TRH
+KiUG[J!dN-e#-dKZ)RpXi`[!cI#i`"d8569`6Lc[eLRT#6pC1MH5j$m&k$Fk)dak
+4mf-Fr$k5Lm3Yi#rePr@G%[X3D"aB9bdcYYB9MlXh*ebL29#I!Ve2KBA&JVi6T'e
+a4h3Bk-,-Z[c5IVTY)aV05-q#rF,fXUZ[H4PZf!q4Gk")jmF$5Ic$L@[-,c`P#5T
+ahTfKYP-2(X45Ap2&f@&f'5Chh(IA1EcETV6Fpd5b85M2,c3GGpK#r-a(rbqKKSE
+#B4c+30$4XqL@rQmGLQ+%eEK6l-&E-Zi+GpEeddaTUI(MK@1X*13q,U2-rYGaDKq
+DLFY`GU`ZQ4&m15bYi@PYD&Q-#4dmEK(%HdXS!6!!SeL4*@m[%+HjhAL!14JlcI9
+m2hU5V%'Q-r-eG`c%#iSDp1p@ED!%eNY1qk$C0kQ1K0$iD!fk&@,$[Br[+H5+URq
+pJV1R,EZ)1FFeEebfB$*L'LfkT,NAhq48HpPCrr!I-Id4`r8ih!,F)Ml"&+3+T%c
+&DNYYGKm#U0hGB$89f'VScHUCE"&13j+q3H@RkIY9ABPbe"3#SP)ifR#"r5JeSJ9
+GQhR"4k&r)+!C52GTJI05,2ikDVC@S6&M6a#9K"Ur@#m3K`@)ZpUdB(VM38Z[LL(
+c3ShP0j1"0@BV4`P#2Rj!r[%@e&l"3-Di!9JaR`kMZh`cD5J2YDBeFb+Fq+%-fNI
+%aDTpV1"1X`3Zk!Q-fhl9NMeb3-@QbcR&9b3ecCe8mDE9p$rZmM[l"IPlBI64,ak
+i4-`rM%ia[F+qHI1G8UR3Fj'IL2IZ0DDh8V`&pld*DbE21FVrahZF"Y1b)hYm5UZ
+HVBEmB3%35l4kR(j+1B"@LF8%rMfUrPAQ6YkX%[I8AN'IfUbR*XG'h6D!T9"jQpB
+C5KKZDD4c`22)LlLe[qCe2jf9qm-*("0+0qBDS4El*1G(9[%Q--d[*"f'@UNc)5p
+@*HYZCJAYCV5bBFU,E!%3KB#A5lPXHNQ%,Ph,GQUF"hTUe-Ip#jmYp#cJC#6ZUiU
+QH*HK2d"HfU'lr3M@i&&!f8%0+T'`T,@,K1dhlf+2)+G1aNbTY+"*+*j@G(HSQh8
+%H"8CY03#P96e6C`RNDVRifP,T1m%ep$HI1JS!%6KKCB3@!X*SNhK-Sf*`A"&4KF
+N)9#UmM-hM2-rSaBPM%8*B&*rcpIES"Y&e4Z,@rd5bX629%G!6BRh6IHaL'qA3L%
+ANSHXRimH(c*VhX+qa6&,e86Y2DA@cF1hC![,,""0X)rDbM1ACAC04#C9ZNFBjc2
+SSM%0&NYV*@d4RV(BfXCK[&rVaSjE(X8E$Z+&iL88P5r63(0G(XDiEqfFDCjUS[L
+qDE9Q,B$HY)[!3Rb3!$8Ecja5*Q4923S#'XDRi8pG'm4fBJ(qE'Cjk6J6"q5,AI4
+ba`+4V0L`ZQdKPlTQ)bCG5hkXPDMBrFE$a0PNeM!25$l1HX+!BK4bMbQRJ$%I%c+
+Lr5qR*%PjY9QNMNYdeHcNj[rL("8Sr$'DeZ(kj)H*CEa2YeSF)p*TF3Uj[S[-5'5
+IJHA)p4KeCd1EM0Np$Q0+XKiRG`r,hUMCk3V@5eeI%6&5G5K98dY$Mhr0##,C6M,
+mfJ0FefV-i$RZ"##G9iF5Yq'ARiT1#0+)%3hPCb,*EE#83BTZYP`Rl$Rai5+k-K!
+kQ-eS!q#p9)380G!j6JdL,Gjd"$pXGP*khaKZ8h91Y'Lfq"6FrXar9&`58SDP0)6
+'pJ+T&NH*m+[#SJfNlP@ie6lL3b#1'$I)YrLU3LKj$VqK(`8CpN2Q@%SUA6a-[&)
+M)je#%R8Uf5Yr&GAaG6FA-"`"L`Vb`K@fej1Secle0&9%I95ieLVQb(b1+MJ%G6M
+!6d1c0CfL6,56bL1`D*RGK5PG6[NH&fTKhkpJr38-4Y5DQrAU[clBp9Cb,'qrU@Q
+lm-mj1HBCkN#5,#0`Yfc$kL40XpcHd[D@I*6&TUXY(8C8S,T6!a,T-C,Sm3cDXh4
+M3MjU@&'G8jeja8XK0UJ9,-aYAK@arhPPX4Zq[YqGNi#FI*%e4ZpcG8&pTBj9D9H
+*9TL3!!896UQ3!-EPR1+iX6A!%,iq"hf,8cPjPJ+N%8k`P$ZEEpM5*Yd4)mGUD,+
++kHB8-+A-UcckpC8ZNY3VC-h$Ni)klehBHE`1"rEH1I-I(qLFK6UC8LH5P3T50,m
+1I4jFeL,9G)DM'dmN'$+I[+h!JM3A&r65019a"A!XF*mRqZMqj4eP$Pkp+h%prcF
+bd+Z1RFXN!8Rp*E@priFrIC++Fl*Q"`IFVr[0pYK*8CXFiZXKGMekMI28HDKb`RZ
+)bZ@cTkMMJRBf)km0UYAUC[)k(Br6KT)aaQ'@M25%)ThRk#I'#+fme$RcU@rh#MU
+P2JEpKkr@cfC0810Q9dhD0)QZb&P-C#f"1f(CGNJ%,8cMYMk2Ba4p!rL[@DL$#Uc
+3BkpA1-&mi-AjHq,5Ah1l-p3Z-J55FS!E6PIbjRR6&P6C#Z@&HiaLC(&$(Hr[4FL
+H5ZaiZaKCGU-"33a%,YehNk&$(X39qqUk`!r"UBb6R5)U9HIDXmG!(`[ZTH`qQeb
+-,i+!4&)U!N`[qRSBJP-0@*,a"e3qXRa8M('$X!f[L#HA+%ARI,QX$RcEHP($B3F
+a@qrI(d"61KiQa1F)k8Gm14'RE+NakhDcCJL*keS*+AdjU68d@Na#3A'SZ%5AQdp
+Lp&*aBmI[ZaD00XYePLp#'F(f+XZd()%2$1ZUl%S'lLmF)1%R'M6MN!$)cr0I4$J
+H!Al$I8k*Lj&Af*AHMTEI8kCZ!Gj8-QepBb1f%5T&Hr`((3YMG+,YbJ-,&S3Zi3%
+E9r`6T0TNQ@,*AXpYD`R2RH[8q(kcVQ5*2qqk'l-ABIeeK4h'@Y[3#K2hY5AL6)p
+@jc!HJ)KT8XM!(ZRCV8'D&I5U##[N2TA&!6Z&Je*Y*Ub0@11LGU!U0)PqJE-qiHM
+45c"SpGmZ"rLp5QppEIK9hi"L`k!UVT%'ZYhH0E61fY*++Ak@MbpK021bTMX*5RC
+Gd&lJCM5hQZHa26hP,D"-F"(#-'A`E2"ZhiFRbHh"'5Z(h"`mk%11C,&EeFr%9+9
+Nf%N2bmV+AD692RA-K)66+22,b1(SAFeN#%+'qf(K[jpA0c+SbSfC)mI0JLL9Yc,
+GhHAh%BS`U21(E$CRBrMkimX6PV5lJZqR@MJKqFkpHl6DR4&diEMmhTK-HAM)fS'
+$@)5I)FPYPA+hJh3flDM0ck0ah(E,QMY0MU3L8qhY+R'3!#ELP`M-cX9l'6eI3Qe
+hS1T4aPZ$arXr"J0Im'HdT'6%)4BJe%$JpXjb8aVPjArZ!`JP8$LaN8Q!$XI*f+*
+0RF19c$NfEhAJ9'8(*&lph`([3LCFcpJEQF8IF-3[SFB2[e$($lbbCA-1c&2)KHZ
+p&kYSV#S5UKE@*[9+(%(i#iVir(1DAV2,NjX0M1r8*X(b@+F*8,+@4'-Q%rEF33F
+p8NKJf+H%03VjIQGPf&Q8*kU"[QpC@p8dpCh)qfmZlS&!B1ABJ4G`)H+mCZSaD+6
+`5TM[1p2SKkQR,pM@bidm`8XC5$&jB$GZE#"P9ljb%2[d5K!DAe[4Ia*,p#%edP5
+MIGKmUP&-`IUc$%+qrC(kc5T!ehdi-Mp[%b@Zppf0[EH($YFmmMCC+"GifH8p*Aj
+V81[IGd5P(9er(!T(lYE9EJF5@ik*6[VpEV1BlZB!e%eRk5DARXMh,JrVKRIJ4iQ
+P[Y+ACKr5N!!,!$EJ'`V1Q%NL,-aL+Tc59dS#-%90Bk#9m4bP[FKbC5Rleq'-beY
+NrT`6%RU([)`Ij4G(GkTaG%"XEQZmeKNQ*rIjkCdjm@RCr%-"+HK(SH9ZDa0&H-r
+CL6Tp#)L4*&fJlpa'$!*q!hXNbQj[33P8fP)-P%)d&(JV,R'BSj'$3*fUNDd#!1Y
+Gk(j'!pMM+erB9kpHeAUpKDe`VU!HRq%rmPRL6Q+eD*Vi)1JQprE%bbD*+DYSJFI
+E!AfQ3%HHKZP%1'qVFHJX&l*jAQ`#G[[Me`+&Yp,df5FNSJ-Q1hhJlhGf&K1Lca2
+ZppT2)1V$#i3ZC4iXaUhI-EGTU+-rN!$iplk0e,blq38!HpM3aPX6,Q*0HS5b&l&
+-&)p+2"*Nr,b)%iSN[P1rVYa*`&[8$b[`Kp$)9TQ"#QcpSU4RU(b8&SBp!j4(+Fd
+P@Y#cR4j5CLmG5qdARMeEeK2Ki4TG$FkkJ-`"D8-A,Jc*k,rL')A`K"Rr@-im`[p
+@+jC+20IV#+b-L5kJ14Am!9mCm@kN+aH,XUilTZXi&Vq`3XHMc3!CaVUZEqjd'c*
+8aNYMq5-ie-5P8m$6'Kc'pa0)l$ZkHkRKQiRZEXFF1'@F6Zi&AI!@c%4dPK@jBb`
+"IB+E`2[2*JcXT)fjJ"NKk"b*%ACF2"T6X5'DHYbZ!CBqG2dI#b`&"%P08hhef14
+@3ZkMV$rN9e*JkVZ"TJLd%PLlfU02@j!!K6b!2Y$`(`aPk3P#+qZF$`5hhpPh)B$
+G&&24F&pS+lA4VDA5@Z"eQJ90Q*!!$TIAS&F4VJUU`Dfdk4!HhS'5KVSAb+V"Y4k
+Xa+3@e3KFDlA3NeUcm)!Qfe4GS&2,S5NA!I52XSjmd&hi@U('&6)cTE+$X85-V+H
+2A*cqkA'@JR`lbiP*+P1S90CqqURQ9i`ZQ`405aJZ59&N1NGSIS"pZ!-TI4+3!(L
+'J`hRqU-"'!'05b1hi`ClF3[IMifbbQPN"5`#1#GF'%f&"ZAIhCX-e`(Yrfmk2k-
+`HYpRZ-H5XciCA#pESdX-QR5!SH#Z(br2VLTYG&5-[G-Ij1"96EPQd#r3Xr`rV&b
+l#+Ir$KC1+HHbL&3kqV90R"BF%ijd"Ja9L4Q!X*bCK+&Ya42h!6IkPdY[FY1R!Rj
+8,bD(3rac%,TBi&hI-lKic+lm933)96AlBiU3!$Hf*D+$rP[pR[%Vi&U`,8JYU3J
+C9Aa#i1-bEIBcE'a"2VRcF*Gp5ZkE$hG"SkANeDe-*iR!+[S2lDq!JP2`L`CrhUA
+p1l&BR#05440)mmlA$+q"q%)%,FI@pa"5BV!dB&YI&heV2M`G0P8Y#fL5pm!MCF5
+ljiV@Z1-"U*!!pr@,i,Cl4IBbL"[TchEG0R44%P!5E(i9FqQ`rVi919I'52@)8b"
+cRRpZe6dXe5'B3jlJ`,M9J5L6A9lqLcq3!'pQmkSBMc)k$Xbfh9-Nfl)+-E*21K0
+m[UYV,[1%V9a,XqfjiafhVIB$hab`qL1lcV51(L!4CZ8r1qiaJp0PrM-eA1[0hZH
+*)D2RVZ*9@e4#H6JQU9M4hDV,!RMRD0Z$Qlq(eQ#Zd8&XRZMrmb6GMi-PM3icGU9
+PPp"Mj(P#*lR'd3ALqlQ,GGG,0@UkS*!!!R(Y(j)P0VKc"P%Iacm13G"&*$k3!,D
+cPjidXlANCp56BGYiNKXf9Q3QHl2NTiNNBL$HVGMd"h+i*l"YA%VS@CA,8[S#3dX
+Nr9aklVUh0aH5i92S*2rXih*38bNH3`5(kiU3!*fD2I[I5hDACqdD[ZAj)MbV9lr
+Q,$"ica(YXVj0Q-IZi!`CANR-+dBdq[p,[r'N[lj+eDDR,#BilU0b)`@k!b)Y2-"
+B"`Q[5IfZA"Gqk('r`rM6C8p``fm%9MU+,L#aabIaLX6jDFP@i*JlreL4A0C0F`k
+E%FP+$fK,AG-9Ce6[R92p9*kkH(S&rD$V5RCGZqNliB&"P,TKKHKZBH6rj*P6'JH
+kp1N2a4Pe[mcRkN#**L1%rKp'Ci*8+3(+K2E5NN$YQ6&,JA9[R*IZ9!('@lU6`Ee
+K`@JQQd[BC$KlddRA9C-aHAmF-eqhk4eEK20C+9S6J[`E&K5[$)MDIj1MB64")p%
+LPK0Y,$l44,VM34Pe4!4X-mTm6*9(FS%Jk@K'eAJ$c%+d-+bE0+`diY%ie)0&$@A
+6QiL8dQ"[fAT+ML-KkR-13lfi8lZfCe,Pp(j%(d"4i!)'bCCFd(U-'*S9!q2jJ@h
+A,%BU9AL3!!+BipF["Di$CkbJ`(#$)HRZrc$1$&F3#Jj%+EGef0(f9["8*LHq)dS
+#L('21F0kNH)$R9Z+Uq-80k&rcPS&AdD*-%q3!'q%rQ63a+d!!&qHDmCh8MB5a)*
+Tf5ZT0!'Q$YiGA+rAN5f[-aT1IaJ4%kaj&9Sj2i55j5TiENDTf+0c%EESjZRc9Hb
+EjeaPC,PGb1a0X0a$EP@MhZNb@mej`![M`5RLdc4c5ii#lkFP*I-DM)3P)j@L'-Q
+kmV1)@1H''59LdI3IBc,Z!D0h$fZ[X2`h3L(pTS0kl)2Gf0*RV43FJb0J$LKqUP9
+N5&e[mYIQ5HUji4hk!(MGh(FbN!#@pCQ)!PAFJIUX)M*2-mUe#BLA53*5e'lqcR)
+c0$*'3!'F-Lr$VHZf0cbPf-qZ#aK4fS3kQqVh@U##i!!GYmrl[KUP5d0h&IC-+pN
+aIQHPCa%+b(C88Ji)AFljFRVTC#'M5P1`K&)jKU),9")LaJmXMAGrAjPfEPI('$Y
+ka9aIK&Z*ULAkMaNL(`d12mU&63kjd*'G)R!YQC@JFIAPYL'R3)jP8hU4AdhrPXA
+LZZB$'EZUm!he21D#emhr&D`d[Ll8XKYm#QEkhYeH3XUL8P9Uihipr`I9"9#5BSL
++U6DR9G$E`0+`Sq-eGm"@h[[[rL4N,,-N-cALcQf*dUT)mL3d5F!9Jf@b%p,-!"c
+9%l$M6jjS#cpJBr*9ba4IJI+Be&k"pTm@qdZZ+*!!5-',M9ZL#FGdRp5@%fU5e42
+(N!$Vp1N5P`0(jr`G$108h9VhSGTf@E"01SVFIXp935VT#iBqeMbZ)ckXLcbhe'Q
+F[kV)qqKQP)GBi+d,&c%U69iV@R)IA%G09PC1,qVAe5rp9FYP0e)@ZmkMP64"L52
+Ve`6@EPS[+3mH09ALYZYcGE%BCQ@244V[rI%"%%Q#YK'QL8D"cc$EpFdLZkA&4Hi
+rK3eZmM6'!`Pl6NM%4dH8#&lGIp$*H[Y-!-`Ed2*&AQFjr9&JI1TYG@GLQp52TVP
+3Fbl&,MPBMBFA8@2K,ADl8U%08A(U#,IRXaNcfT&Q"S"T,hr2+hGP9kL-Zrr0BH,
+2rG1N-b@KAa-#`KB(U5Vd9+aMbeh@B&0fF,1S%SL&SGqhT88UfE,VVJVN1kY,6LM
+heP%SF2EK$bk4&(1IIj2MC*[c+H1XRV##@T)%XFBGTld!GRi2Z*cjd+U)V"#+%dp
+R+("DaSQ%5SBI`Ni8b$jLMleEDJ1bK#mTVRBK(jbA$Fh4C)4+VS""p$J%X'Ek!kR
+CDhA4',$R&b6jdP!B*qcYX*hHY[jYY95l`@pG!-C@I,`piZm&6c)-TQaIY#ZhM+L
+[YDL6Ucf4*KZ**!6*[S"-"FG2iFfA0r40B`&iK!kAl9LY4VRb'BMdhf"Q&pR*Lrf
+PpJrV!AZX`E5hF!r"DCD"#3pf4$fpM+-&L'h$K[U@q$#(eX5#%,rl&j-K!b[m(q)
+9h&3*Cqb6FVDq@Tj,Cp9)QYfBHN)Seb0IjK[S%Mrc0h2i68c42r9PB1BL,DMpEk(
+lMa#PprQeSRN9"P-8%mbJ16"J!m'93pR'E6b&&)p-H$FZV-q!IAfl5KQIpS6lR,G
+LK1ji5ID5Di%GNYPjDV`F%Zj[bm)q#%(TGJSH-R2ApZXi4RR(S[GkAe6GqN`dNdG
+cpGXQ"IC#M$HrQ3PFCVRS!(AF@RSH`'BEY`e*QbZ`5Q$5pZ!EmPU1%5D`+Sr@L+L
+MeSZIcaR#(2GSD%$$Le6*iGqrLVP@[HbCIr,XPe&ZUk@hfqcbqZ0S+@#NdKL82j5
+"X8dJP&er`10iP&N'RjC0-NNNRb"9(Dp"Kb%CT("MMSRVfQDerUEiam3Re(hK#!$
+%N!!ABfCmBj2GZ(qAh03K-B1p&!TIi$Q("Pr)S((,qpqdc-V`kBl0LdIBa5q3!29
+DC$JpSlTHG``5Ha89qEf+jXNj`(m%2Cbe)2R8jfqXNHM4M4kEYScC#KEA3a+0!GP
+QZRUGXB[JCE!a!ZcLpe`I0G[QqPiG0pF[TC!!9fTU$VQP9RehYShR#M$RUbP9M5-
+bIRY25[@&5m8M+ibGiNPp0N21(q`1kQPj!Ci0*YKATpAMiAd@Z[&QX$1-R9RLB)p
+VmQj5II#qh(Rk,DAFr%NPII,m,'Fp!40IGhPaM!a-ifH[mNF"akR-0&+i&d(U*cA
+jQb'+K2KY%IQX%qGrEXX`SqNI,6qja3qR1C2'S8`cHa5V32@A)$,Y!9ci!XkhLND
+S$ZqLGMaIrcq2RN@+-rkHQ02+$5+F`C8M-ZkFCJC#rr'L6CpD0DRD1Va*Z($9k#Y
+@9+&(G!L%1jmke@JBHpH$6kTreTkk2d3eR0a5P(CKBl![`CU+'aah*#9LaiZcYh4
+5"Xe[MB*p$@SeShKF[(r#Zr3JqB4MlQX'jJRqHa'*'iU$D&,@IZd"m50acrD[rN3
+KN!!$"LKlkbR"9CGJ,,qG)rZJQ2C*5rN,4I2ldTXi*c+I4$[,N`rGr@c68jTAfNN
+cLMf6DNYb2GiKa-Y3kTJM&),me@"'QECkaVTrbL`Y)D(`B4rl!0``GE5mFV2fmdV
+rb+!hQLNjbXTj[5e40Ea(!$fqM'I(8`XB*F,#[KCERLE,ZG9Ifd6[#L9GN!"U-*d
+8ENU2m5[Pc65'kSUlG[L!9P&LPS'*(5%2FZZ6HP3B`GX`dPkUm6jTki0)TqX(jq,
+m+X`-6%$@"C9`r`5X2G(PUN@)bhC!#G+)DH1RL!plT`Mflj8cX+'pUC4#IU4Zfha
+3rRG!S(GJeTd!2,U#G"4V#2h2p[iNHk-iD0B0#pMJd@2X2$fTre"ZIAYIR&pHTmi
+!6&*P[#0ea3D4*R[B4*YcepR%$TJb`(P%YB9+CN[p@A[FkX%q@`["Bd0#D+Rr+'(
++D6UqVEJU0!k@!eakBj(c5e8%T-p5Tfe,GjaH,l(b+[+bbhqNd5KM(pBhSc9XciU
+%GPAZ$CRa&$lF6'AlD4KjfpKZd&4[3V$11JIAP*PQi6*-r8MLh%!hJSZbHjH,L(m
+Lq+9RVIUb%1d%IRZ*5X'p'R'alh(#-%RS5p3d[(-H1UNQYYUiH49kXmcr6NqJ(jc
+p2(39%R0KP"Ykk5YRTf'!kqqDSFj&YcZ'mcaIcZVV&QUBR,(6m"*l"TqYk'b"Qe(
+M5cS#RqPl'%#%hrQ(D4DFS#0Zbjr$8ldKV3-"0FQGG4XXHHf9$5e[M#2VQZqIC6G
+G1&jF3EB5SHkAEZ*6-jbjA*YBEcFeGhfrTi4c(iFilaDk9Y#RC,)GbAU0FRHB@[j
+iY$R4L5pDFH'TYlLISJ26"(H3!%HXr2[F,eii3i(@DU-0,h$"c,dRc)@mj&8-PV3
+b!6Y,r#'8T!e(dPdSl)mqK38Q2i$(YBe6ikFNi6"rpKpPrf+cL1D)T2BV%p5M-59
+(#`NHh$6GqDqYGcdm*IPih5l-QjKUkeKm8MYX+"U`U3CliB@9Ch4V0kl['YTkj%L
+l@J4cSp2b3CCZpbjbS*Pii34"BNf+YR[ZK+`hH$,+$1YeK+#5qXpYVIcacG,"QJ3
+F'qSrL3jr*0+D%BdL[&D6K&cc#AKdZ8&$V)a"BHL-T8rcKKGqUR8'NBcSHZ2L)'4
+[kKm")@I$@I#YiUqaCLaB'bLl30MJLeeVUB05bEcqm1DZeX10)!'[5XIRCB+[`46
+Z&eLmf*XdTH)Tf%$kU6$!C)&4P1B%q4Djk`YP(Yq%c4E"HFqh($q,TReP[afBf*8
+Kq&4Qj1,%da$328iPHrYcT-l45FNfGd)*N!$*L5FCQai1[X+TI`$LNk,36lb))hS
+c!j9X*m-,A1ZTVdXA+r@eeJ4HN!"N-Xhf'*Nka$Q%U@dF!k+Z80'Shb%FDhHH(P+
+EVD"!,dD8"9#iBk$&!KSJKjb1fkb1DrkZMej)Gr8qZ+4l'3A`!+pk16JZM!PdlKr
+J$cU5!6dYblU&LKkBTKEh6b3HdAZrB[23f@iqmA5UFj&,m-91Si)39,mrep`45$d
+E8TR-J1S"TAjkDZbRhK@'bK,eZ@5RA80@QACaShVD$aJ@Z"ddL"qGe6rS[C!!)3C
+0UE--&8jd4N-l%Q8%r$1FQrh3R3RH"EjNq*,ZcJ[dGFI1aUbUi+)NIb#%0@ea)-0
+Z1Fh9NQhq1k+4C%9MhaMdCalfq69Fm##'ZUG`VAMdKK1lL**+-4ZFq+*9!#hA'm)
+&I,CS`KX-@*&l,ZF,ird8qTi9iplZeBE2)%hjdRlhp*L'X64$*&,6AJiaj!!CNAG
+Ge3QI#!e8*NVV&-mj`rd&%*TL4m1BC`0qHE*$EXcbP`UPIN%p*MV(e(3EG0[3"e0
+3B%I,TjDX1be"baD8G20EB30EjV&bBQUBYD+18eEHp!@C5'(4(C!!CH5dqI9[[V"
+H$6E[[(F&me0JY)rUl%k26e@!aUk1ZB@$@HA*Y@b,)FL#NfV,R[,qSIX82%hp5-D
+eR1TlY(8a'CmieeB3rBPcKA&YQDP(rALbSqaq51)H6T1XPpbRV2hF"08dFG4A8pG
+@@03IM+rYjPaC*L!P&[d`"NjD)V4h2+Ykp@,N1p16)HGq)-$2@'Qqc[TU$U'mj!U
+"IZaB0Y#[!`epUj8q+YCi3$&MCBdbh$G+T,Y($,@Q*9QF$G5J"FGL2Zm-J6@YDea
+'`J&+!@H8Nlm'f1IPi111JpV!I!Xh8EV"c5r++Y)A"`k[#j9YBcfA&qJbKM0L&$"
+NE54Tq&I4U,,,'apRYa1)M4AlbcECl9M*EA!DK5rrMrYa1dk'AiS9FrX5+Udim"6
+,KURTAQ+,a9B)VC,bMpkdFmD-(68%0fKkfPRYaL#4*H3(eU2jaR"'le9'-H6fpK&
+AH%pKF3+b3phc$UQ2qG[K)#eH["!X#D0(2Pd![%FrE%R)ldMKF#FH3B$MS5TYEVZ
+'$N4DIH5Rr8TKYVF49EQCMV2lh-Xk68VT@jHZ$)D3!*S(fk*4`TB[llbRC%99(Xm
+CE!0843m1ZaX&C+mY8,&2*K&bcP2`VjU63qbaAIj5pNP%h9)bDiGXJF`1FeSjQS(
+`*U2ANB4-LN-!)$MR9'Lh"@BqR%@af!mRke")BQZ2kY)H0Q"bbCjJNRrN'$0hTf!
+5Pr+)$84,+UBH6ihr45DGP2%dFfA-%aFALk+6TUC!fI`#RPF6("irmVj3(+-@5p&
+VB@0jpqCh99ZSmefEKZG(Y9Ie2"9REZ[F,Aj!$Cj[r&@YlQDpS2a)MKA5aeKDR'F
+%*iTcL#jaR99pKMA[)V(@2)3"lBUiAk6DCrJ",hR0erF)N!!q`&Ip+c&51l(*(B1
+Kp,1CNBj%&hDfYEH%Gf6eAP2E4@VpDk'lbE([R,@aM3*V0VVXerUJJf,HlC3Q!%)
+CPeqJ`QCc(01lNJ53!1j[*Nra*5A[c`Rrbj-J,DJEP5A"3V"*+E)jefedm+pB[DC
+0hQc6q*Epf&e6MSC@kQM9lH[G0%&8#5Elq[QGS!@9d+4'SH14[+Q6a4&L2(J3Mc0
+5q2(R&RfYIAEj**-pXIMD,Y*R++GZYh@p[Y)`-("&c*[CJUFYMIkcm'rTSNZ"44l
+`B(&FeN&AEVM29)jKFirh5ESqRCJ1hl*4NRiBY4-'S+GZ!XC1R"ck68p!(9dAN4b
+"9kJ1MieH'+M6@!ipE(kaTB1Cc%rHY834pEmc1'-ZeZ@S)(14dEh,qjX8GL#C3%6
+%0djYrfl2`X@YCHQ9bc2jZcH,Lpl`hU$NkAe(,h085IN9QJa-U&X1Api2M-39GKR
+IUBfImmL*F(CKaBFQ#N"A0LraMKXf+Q1cD$MDc6NZ&"FIRAF`Ef@MPBYYfD6`b+9
+QEKB38A1XLRhU[eAV"T,+J3UF*d1JD[R`PPe[*(ZD-HC#HDZ*-'!fUq,q&EB(R)T
+Qh9QG@A+f#f"K`eREGa#eG1&8L*2M#Q[3$TPe(XL(0hmb(CNAp*KP1N@2[R1ZB[a
+GLV'`fKXkJ(f[RU""8$lbPh4FaaY0FQGjQEYd+5&JTDm@lp`4FF%[#r(I,"[)BZE
+Gl#NN3V3@al"dbBKak)pG6pM)FZ3cji(2pZBr*j@"%*HMb4+A%YN3QiESFaA29-e
+!9N['iC`E#0#qC&8j0Um1UDPj61R9N9dF`dad+RMS)'Kb2mV&*$@(q,(Y5BN-))Q
+iPMZ)4+Dq'V9!P0QeiC!!K,bCbMLI*"ee)*)V4pHcAh0*H8Iq1"XljiB4VJc&58&
+*eY+C[6`lEh0T*V0+Lp5)Sm`j+eNRf3X$KTMG+LFdhHe-IK"GBhJjNfXa9lH(Apk
+b$`2GE3kaZU,REa)eT0Rk-T!!LC'Y`bXF4RVmHLMBL[-H`b"0J(iDrN6LT"Ei8!T
+I1IVZ'l9KUHjQDDSpE#fN3AA5D2E%V)Z)''XQ-(qLIV3JP!i3J0f1VQ#ll)Q+!$B
+80F(Lm0,Fi,r+@P"eT49Z64A"2l[@fXB$URH8&#)Y14$$SLd2%,IU#2[55eL8T$4
+83$QlG5FE+SrSI[S[9PrT)P9kh,BQ*#&RAK035$0*Zr1%@r&m19JEkAHSd*lQfMr
+`U(d(06L%DVEE)61biid06MB*pp%!9jc#E*S41YQC9A@)JiU+Pm#Sf!P5fi$0V1D
+-F+XbHiIL59d@G8M3TN!5+D52`5!'J1VeG&bE@alFmF)kmA2eMl36`4DQC-[l0*`
+)cIDhRjl(%QaL,,lXV[0*J)2kQ%!SN!!qS(h8jFSIkqa$1E%#Ed[*d6*kH3GVf[Z
+Zf$N[Q#*aCpiq"NP(QXa8qi,JjL!+e0`M-bh*0EJ21bPE813+qRRD,Fb3!)Y`C&A
+4['YL4DEpdL'4UY#)HI[!hf'CJ"d!llq6p9Z3!,!CKpF5SKHd3pPfF"'Umd6!h(&
+&8mqXU)rCY3j6L9jciYPTSHI$2[6'G8'G#+FBG@Eb+U,Z0mAbP#!*U,m(*K9#V8'
+4i'PNM"IqCh2S1Ja,&&cRA86V[D%ZI)3%P$-jAd*Qk[IIBkY3$5")VYY(bkA@,8)
+ZfD62fl4B$'92$%Afm4XFNQ)#ZSP46(Y!P*8[qTE%-Q9Eff0kI)b'+f2-TijG-0%
+Yb`BqZS2`mm6-6c+FD1cehE5k('L+P5B1I5%B3U61BEU!8D8VG268d@Z#am-)ipZ
+JRd+cDIpldhTKc+kD9&-0@AaQ0ZipA'mY`q[+1L[)&9(c+FF`Gp6+)F3VP$cPY0J
+3`b+`%%fllhP,bE$I8&fh&!3-hSDbhHZ+6`PcY&1!r(*)pfcmZ-9[-YB2B5i@d!H
+X%eDk$UUQV*hidj(DIfGdTMMqZl)SX!,r5Ym`G$4)1Xida&j+pE**T+8l!B)9Y`"
+m#`SGB8M%NZ,4CQ4jZ)L@+@+kU3-'lIcSkK#F1dr`Z8bG'hVkdhQi-Yd0JZQrM8E
+%Gm+QKP[qN3S#N!"e!H[kNM3Q@D-JJPjj4P+6%"B40$[V"dRq4MR8*VhNY"0Q4dE
+b-qcUKfJI!S'k&dp,aFX%JkJS'hhTbR-`*RGdXd`k0D!4J2d1Y1D`h$G#Lf9P&`j
+hHi&qa5$Xck(hN!#D)Diaq3qX%&96BbaKV$'56ChapRc,fkp`!&D9A@4jpaJFBd#
+cFZT2*RM"qTZJih'"`qjS0plp,'0-GC13!+pbehAR0UU"P+f*HcK4#'YDBUi!,MH
+Aa5X`'bm(@e2M'5Yf)0"CCk`Y*!N#"C96pfq8#aAc&Mljrc[mk1[2dM&@fc`J%A%
+$"T'rFVB8@ZQlN!"a'l96JS1PCNU&@b6hC2I)JHQ*j""1pQD'1RJKXCd5$d4GMCN
+[#c28VPM@rmD%KC!![,&3$-k+he(XcNQMpN#NX[f)Z"&F,Z`5(jYrL)r)XikKq#6
+U(286'dGc@$a!Mf-Ykb(22(bG),b1G9@rh9hlr`#Y+h0@AHPV-6HRICT6VpiVCdb
+YZ69i9[pbT[J2h5lBp![rSGS1Gf)C'C%1pZj@@[@dl65@pjQ,00PE"E1M)BDY&)Q
+Kal5b+lIq*Ye+@aSHYa`[%eZb1",l'hYFFcPRJUaYAE"NccIP"G#I6``2+VYA$[9
+'c-`Aql`HQUmb5@4%C@1Gq#U[4"V)ES*U,%IX&L"!A-kJb'5q+HaT)(Jb%RZerpr
+4NXCGfLbR+-2[@Ce-"e-pF4"DZRBR%A4[-[A66Be$5V(fJ&Drk5%*UiXleair[%f
+QKiL%*`63I2jM,Z%6NAMrIQaUV#TRm""!HSFBkTJ9B$j#e)ebCHN6b`L8VM)$Z)L
+MccU0m'E+-liS'&5R-V`abGiGq@G+Lq-q"&$4LjqN(#91NC`A*[fH8pG@b(DTL*N
+0IX!VdVj+f65KVE!3#R$rlCG,(TXJi,GN[([Nr&bPm-5'*RFm3jh&jXF-q")+2"G
+#XL4EKNq1#)S$$Xd3-RhFG18Z5"M22jq@9%60CI$leE!QKaB@Vf@1`iH[`CSKZdb
+hqY[ZY09ZP[4RF[3P6RNAPA&jFG`l6IKiCc`KPjik4UXCQ%!a%,dLajXLH0XLCTX
+I%9`1#kYDJG"SCE(IkHreE#K#9dX`J%[IL&[8Ab+4,Rp'iUPI9Q%U`rh6jT5JCLF
+qdHkJ,(6(!iF`H(`jYD9`NZ58Hc@#aiMCD10@l,`Pdi8Yb((fe"e`q4R3E6EC,BT
+lEhm!9R$i-+&XQcaml3P[jH[&6%Ffi*Ci$d@1@$95qjQhNb$YdPIdk&%ar3FkNKc
+0l5$aL@`$3pcp#GHZM`'&Kcr8(Xp8AYc3HBAJ,5QjC(d-MIre9FehjUBI,`f(9A-
+-6qZd@XPaIG*ql*!!*U5"4h8DHZkh5P(9Q4lf"#%V,bVKZSDfQ,%cX931`r6VkNB
+4AE,&XTD`Vd(NkV!V9BE-CRVJ)#iM2!R9L`pBGD-PQpIVRX6PLT`SlL$+fTK'p6F
+IcGD'q@H%*c2Ebq1G3h"!2qU`&`UBEqS3I4mY@l!P'@M+d65l)Ge*,``#%lJ@`mr
+Hq*6eA[9l`Yr0r-AikAPEL&6)!GVhF*NI2UaVHEa)YX2mCIG*bP8MMr#YG-XHKIR
+*ep)(4P-"kjAlTVm@%(A*U-VlI3m"d##96!!LNh83TUNK$Jh-a2N8-dfYT(&cV9h
+$G,j`k-XmX06q@Mr&(kV$d"-51!-T*N,VSQX-II3$4TCALh&YkVlETPfa4pd*bD2
+F2q$L'A-1YmVrBBjfr9Kl"l0`fDSq(*!!Df`jGq$-EYGKM4C*ap-)k#YZMm#`MYT
+K0%T[IVJJ!bc%qq`k[)Jr[HK#cQm`QM`(J"kAFm*"cKr@rib[K+-)"S8lXj[ik50
+IDm0i!U86"4HZL(qjah20C9A2bQQiAYcFH-KRhZfN!0Lk04-jX21Nm'THZPqDqB*
+-5YHQ)+S#(,Eq#eUe"@@6RZqCqcf%JPkdr%Al#lEYJlmKMRlhV'Y2TF`H6fa9(c0
+Vq%A6rHIh4aDbdqUG3DQ-*LIGcqarG4f[TE*,rRZ*-K1i&iKEp0G)eZrP5c'0LR"
+SUIQUU0,DD58&f6rf5P-HF!LL22BKBDI)iqX0+(1X"))VYJX@pedNL"iL!LT"%h0
+9r(i)1S@ZU"j&9$X3@&edJ"Mi1'*llBIfeDK*#`jQAYQ`ET!!6aQU+Q&k!G[NDIE
+2!16Xe42l#'`pa+Vh"&"iNQ[[@r+)(cRr&2#TaieT,9!*lDAUfUSH&dJp9Y!#4Vc
+QL'ZTQIfU)XIT)ZAI"YR,X*BLR41UPcDlV(kZBa8)3J30k%F1i-L9K)iR+Vc(,&(
+pV,JR12rQffrcEHcJ%$fK(c(%lm@d!fXX(qdd*1@hiFTr-5qSaf$eS1jl)ci#%Jc
+j%@ArSrBNpZ+h6''De4EQ+Uf%%Fd$flKkGTUHZ8%!IaVLrj!!e&Y0`,j-!SY5e`$
+SRBcED$'F!p1pAI6PHfj1FKF#mc"b"HbS$!+@Xj'N94d9[N28fIUF`hN6bip)9)Q
+,8(V(!9II+N+DZ1riTL+h[*4QkH*rFer"*G("mp@Ll3ENK'h,P(ZpD&piM)5N8bE
+E%l"[Z)$bbeqC%S1L&CPIGPIdC!lT`eqX*&-%!3[iLM+#r8@hj3[8TC3H+!*IHf3
+dr,j$E@rFVNAQFaed`U$G$N%lS&IPD3,TcJDS-8Uql0pp*cY8r%f3!(6ec1,V,@K
+fVM6Di[[--&N`1)fN46fqh`ArA+2@DUNeIrC"G5&i,9S#-)U'T`(,`aRqHPV18S!
+kQ5HcMhqCF)D%82ZD*lI@rJCj&95i@NQFM[la5rbch,pdG1S2Pak#mpa3c1)YP4D
+kj$i8BS`U0a9b1cjL[rrXD*UV!0(pZSV-SE2(4$aJ!$#Fc#MISMI0TTIdAk89BYF
+!-F#DZ4BN(`S0YkUi+FPA&&@eI5bIL#mFZi8+AjLFX(C"#5eL!mM4#,p(RaD@CkI
+$$&C&bfP6F46RiBM$%#1cX@Ib81Pp(-&,Nfb8ZkM9T&,c+@#j$e+abQVj"3Y,FZk
+*8PVHD3VhAH`pB,S%elkc9LTj!4&[Pcacr99MAIc,J3SB(TMeG&GkpV@4a4J-S,*
+QL4fBf*(3SZ5JqVePR9BrEYYYTeX,IqJ@D[H4M#MlU*rDDa-jY4M,XD1LA*SGV),
+cQ[Ilal+91$#aRKrU'RQYJ5bM&K$'ZGULXIp6Y`rYN!"MjKM[%AA*)HeQA[6bFIV
+UF6)0VaDKd*ipSiMac8('ia"mbZ(qceF0hp3aXfcK@k0NdK`NV)ej%U&b#)LbD-)
+3r(#VLKVHl4"e8mCc8aB+KGG@-XjP2ECK@*L"C!()iIeD-XQZI"(m($!ka+EVbT`
+l+[h&9#iKQl`3+R9-+jhbr0VE(bVKfrERV$3jN62)r2KM8EA+(`D(ifYa-'bMHp(
+r#5&2aam4VVXfXSi*EB4d1pX$B&J!Y--*B,b6#A6'&XpDr)bf@PHBK(,TR(p&-!$
+A5`cL1T5@2P,C8dbA@F&)`Bbi(`#55GS&l#laa"%@VR*kDcjNX@)iJ!'par5!M@Q
+LeRZj'*j6)$TefKYdT$'2"LZbIUF6M(-![Fqkdk8d6$E6REf`bXMk&#d[6Z`BQ!!
+Z)+DjbKEh-"[J-#2TH+FhLC184iGLX,h2&EG-J*BeGRraQPcK(pQ8VjiJHP3&YN'
+3!&CG0qb[qqGbNq+lSN+IXKS-#ea",(D8,Cdd)&(ZC41BZ%,E`0`SCE(b4d*mR(C
+Lkpd&,'-p9AD#6bMThGU)&G8R[Y!$hI&d5"lST3'q"R&9b'aAYZ#!@5R!bklLLjj
+!lcq`RZ4pa`[K,#l`0cX&0cEH*D!IJ@+6m%kJ6rqkTJXGHjpddhPqYDNSN93X(a&
+S,b*5N9`LDCm%BQpJM'),EJ!Jd&c2V,$%LPlTYPc*,EM&!A"R*YLA+HNdSf"5(a[
+G#ZR,(a&D[-0GHVKrY,IlXK8rfl4+4DFUG$`RIcFhhkQ$0d3$GAR$kTa#p`)1br3
+JbBBl$!h0*j@Rjp'!'QSXf3@RC"b'ZUC,@!DSM+Pr4MjAX-4ZPj2dkK-e&$LZK`d
+hi#6CC0TLQa'hAbrFFNJRZ0kkmRHd3iaFN!!3HV"&a6Y[3R0GBE[*`&)pNTIXS!#
+lVh@6EE9l)d+P#2$Y+k0Q1DJ4ZE18!G*VUj!!9!CG&*!!l'lML26,1ejDk`%IpP5
+HHZQ$"B2i(ej6h`RASbS+CkR,*48Akm-*[q0h@lXYZ8fUBl$4-lkG!dN[&$#[F$J
+ciqVG2@h09B,ebNr%1mI0BKeIU"YDI,fV`5YY"#d@6@[Q%3e4J`8#1@#+jrR(`Il
+b(IdE*IpJh%D`!q,TV$SlKkP`-eKD3(@0bhZ'l0Ra991l2DI'ah4cXfV6d&D%`Ip
+M%%b4Y4JVj)d)h+Bq(0pLbHfq@k+E5PVLQr6EN9TqMaUeNNipa5ZfLDPep+il&le
+348C(ZYHS-VC4Ri+,$[R[C3GLqYim`RXffDaT9+6+Ei%U)kbFkQ@RU0j3f1)blh3
+%!`3XALpD&`9H)3c[&DZr+fpbe,e!M@!Z2kHp!2P94JZ3!#UUi*q"f98p-SCb'ih
+"kjk$V&*ekMG$[TMd$TH@4rS%PXbR2#JE24"@)fYrMXPM0Vl$&M#MZHd6Y!f+U)H
+kYk)XYHB25iM3BjhafdI3dJeVC8dhTFDH&))GjN8($$j@LXH6[j8+2m&cc,mC1+%
+TLikErejUUc+9Vc@AiD$I(lI2IS("m0$%L[q$&pfjEH@UUL"ND*6TUfF`,AM'Lca
+`L9Gf$XChI3Qr@[`(QT*jN4TjM8b9Q&j,%H)[#Er`p46%'k[Y+21S%YMda-)!T4&
+iF(l1GjS&rIVmeh8-F`R*d3ei0N(@L66M$$20@Y@0j,mh[Jd'GP$'G(%(&V)2Qe!
+B[80E(NVpG6m`@J&eFp",FSh1$X#,L*aSlVl181$fr,A)1T1SAbaReE%JFkbmKp4
+M8Gi0+EK&ABIh5I9%`&!%VAC6iB,VQFf4XeQ"d9qpp34kmJATLIiXe2VN4EPe0&c
+Zh)P($[4pfAI,CXdc9YaH1bmDRLX1c1XBSa!4Y'AdB-$I3a)%)lM*mDdS%!Flmh9
+N+KY%mAe[dEl1hGXEif&ER8NP2pRX"[bAG'K[kEL#!jkrS+bb44JdlXkk4jlkBIf
++(eaJF6iJJ2QR%)XeSYF%I(X!-6%6fjehppcBE5T3*9Ze#d%ATF0C+T!!R&E9DFf
+Dc))dJ2hjkYA--f51LjcPB'-a-ZklX+*XMKRABT2`RCK%c!!#d*0jP#fSqEYJCM+
+MdC6lZPPDY056@k9X)JR3R3D*$f-lPFV6!3b,6Y@ES@h6N9N)4'Q@B5Lc&T*Bqb'
+Abp+bY@*%+SF#-%`!NS%r'b2'%!"ZV63h%``0UN(($A)HRVed(A!qMfR(`jppK31
+f+XG28-)3NfqAX3'Y3R(0cSXDqXeXGeI,1*NHFdd#AZepE2QKD#Y0!@j3*'CZP'R
+McZqB+4%$`3P#@'rH!fTFQ&PA0fdPGh"Jca,Iq0$hjm21l-+JLZ1T*5cURR$FN!#
+`$AHYJE`9m&K31!Y@pkaPSbVI*PPa'-@M2YJb&1c92(c9FT'D)L*dp%lZ&"Z3!')
+8V0TT4URQE$6hLNaY84'9#qJp`M!Sl1[F5p305"1-(9P*&R@6*2ETSYmjaPG4(55
+)PPSe`K*$Je$KfeL9iKN6QBHIL[Q2%rpjaDM!HT&4l0l5%-QhT6bG45A'QP"'V1@
+4qRXS*#FK#jKqG%0RAV1)(@2rk,qqrh(de-"YY%Sh)dFMTTfUZ)EdqEHlG"k"RjP
+rkP[C%@j(4"iq3h,AUrra1Zk-KpcI+i`R'SIfX10VNJ3G@m$FdY`0[c4%P%lMZNq
+D3H8L*N!I)+Yb@Y@1*XFh!C*N$3J9k4mqi-P*#lI)XMlDjTS@f536ddC$6P5,Tm[
+PF"XP)kTc14Z4ha'3!*J5hQTl&c#5dFZH55R-3PdSiPPh6JE$XElBhYQ4HJEF6T2
+EKUk&M&h1D13&'PilPLrCZiL8F2!0%SXlPPpI#b!@BESJ!@X-!'mZNjJ0%5eY(R5
+"DeIZah1,(E9A3@Lk@Jc!e'Lk"9aL-D'4U3)e+'#aK2lH9l@Mjijb+UK"ar@+pra
+9(!VE,IP@VHqD-'i@U#"TLCmClZMc9K[6lSVr5jIVFRC,Rc9aCfB6,92M&6fkPdC
+R6CNHJX$%G$(AD80pV"dHNNm)a(mf-BU%,D@+3YbpNDLU#KhDcPJHPS!RKTQ[Fhr
+a9)0I1R+rH8hj8J(X-L9DXhHL+)VbX"2#rZ-34(e'+QHC"689B&Lc8!kaihkZcr$
+MfYr8hlPG&dN@9c)XeC`B1`a**XZNF%Z`mCi,lBDXpL&FpK1KF(UZZFm(%4+m9XF
+FjYpfU[6RN!$$[V(2F+6kGd!aKh3kVMA"6a$c@$l'-2ZJ3f1)m2@E08m$2rK)T5a
+F'1kGPFq1!ArkHDM1FbTX2,*Je@2fhm),d2Ep`k"jSQC%UQ$jDj&1+IFc*9R05$Q
+$pRrF,%5Lef-%@4CqB2p(SqL`hrUa*JA$r,$j["BjLm9#[PFKfGrhQJlB*BPdNf#
+k[PYEVCCYL44Kcd*EmDNNRiX+@b4MlB3qR,RIUMY5EZJiC4i`i(p#@&i`-,!%$bJ
+@I)leJLF"(`hl[c%5ASX5I`%GjrG(k33+fDiRf@C&,ek-(fl4qfHM+J2CSqc3@H4
+3kY"D"DQP(*Le,DV5Y(-0!-,+%mcJT)lH#PeD55&Z'Vck@aULj"+CTDY8A9E&`2%
+KRFqfZb'0P634A0J!bK)!!!:
diff --git a/src/os_macosx.c b/src/os_macosx.c
new file mode 100644
index 000000000..871eb7e5c
--- /dev/null
+++ b/src/os_macosx.c
@@ -0,0 +1,612 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * os_macosx.c -- election of os_mac.c or os_unix.c
+ *
+ */
+
+#ifdef MACOS_X_UNIX
+# ifdef HAVE_CONFIG_H /* Using Makefile. */
+# include "vim.h"
+# else
+# include "os_unix.c" /* Using Project Builder */
+# endif
+#else
+# include "os_mac.c"
+# include <TextEncodingConverter.h>
+#endif
+
+#ifdef _DEBUG
+ void
+Trace(char* fmt, ...)
+{
+ char buf[2048];
+ va_list args;
+
+ va_start(args, fmt);
+ /* vsnprintf(buf, sizeof(buf), fmt, args);*/
+ fprintf(stderr, "%s", buf);
+ va_end(args);
+}
+#endif
+
+#ifdef MACOS_X_ICONVEMU
+/*
+ * Libiconv emulation layer
+ */
+
+struct _iconv_t
+{
+ TECObjectRef tec;
+ TECObjectRef tecReverse;
+ TECSnifferObjectRef sniff;
+ TextEncoding from;
+ TextEncoding to;
+};
+/* typedef struct _iconv_t *iconv_t; */
+
+
+static int last_errno = 0;
+
+/*
+ * Get TextEncoding from iconv's encoding name
+ */
+ static TextEncoding
+get_textencoding(const char* encodename)
+{
+ static struct {
+ const char* name;
+ TextEncoding encode;
+ } encodetable[] = {
+ /* ISO-8859 encodings family */
+ {"latin1", kTextEncodingISOLatin1},
+ {"latin2", kTextEncodingISOLatin2},
+ {"latin3", kTextEncodingISOLatin3},
+ {"latin4", kTextEncodingISOLatin4},
+ {"latin5", kTextEncodingISOLatin5},
+ {"latin6", kTextEncodingISOLatin6},
+ {"latin7", kTextEncodingISOLatin7},
+ {"latin8", kTextEncodingISOLatin8},
+ {"latin9", kTextEncodingISOLatin9},
+ {"iso-8859-1", kTextEncodingISOLatin1},
+ {"iso-8859-2", kTextEncodingISOLatin2},
+ {"iso-8859-3", kTextEncodingISOLatin3},
+ {"iso-8859-4", kTextEncodingISOLatin4},
+ {"iso-8859-5", kTextEncodingISOLatinCyrillic},
+ {"iso-8859-6", kTextEncodingISOLatinArabic},
+ {"iso-8859-7", kTextEncodingISOLatinGreek},
+ {"iso-8859-8", kTextEncodingISOLatinHebrew},
+ {"iso-8859-9", kTextEncodingISOLatin5},
+ {"iso-8859-10", kTextEncodingISOLatin6},
+
+ /* Unicode encodings. */
+ /* TODO: Add other type of unicode */
+ {"ucs-2", kTextEncodingMacUnicode},
+
+ /* Japanese encoding aliases */
+ {"cp932", kTextEncodingShiftJIS},
+ {"shift-jis", kTextEncodingShiftJIS},
+ {"euc-jp", kTextEncodingEUC_JP},
+ {"iso-2022-jp", kTextEncodingISO_2022_JP},
+ {"iso-2022-jp-1", kTextEncodingISO_2022_JP_1},
+ {"iso-2022-jp-2", kTextEncodingISO_2022_JP_2},
+ {"iso-2022-jp-3", kTextEncodingISO_2022_JP_3},
+
+ /* Other aliases. These aliases in this block are just guessed. */
+ /* TODO: Must be verified. */
+ {"gb2312", kTextEncodingGB_2312_80},
+ {"cp936", kTextEncodingMacChineseSimp},
+ {"euc-cn", kTextEncodingEUC_CN},
+ {"cp950", kTextEncodingMacChineseTrad},
+ {"euc-tw", kTextEncodingEUC_TW},
+ {"cp949", kTextEncodingMacKorean},
+ {"euc-kr", kTextEncodingEUC_KR},
+
+ /*
+ * All encodings supported by Macintosh. You can find these values
+ * in a file:
+ * /System/Library/Frameworks/CoreServices.framework/Versions/A/
+ * Frameworks/CarbonCore.framework/Versions/A/Headers/TextCommon.h
+ */
+ {"MacRoman", kTextEncodingMacRoman},
+ {"MacJapanese", kTextEncodingMacJapanese},
+ {"MacChineseTrad", kTextEncodingMacChineseTrad},
+ {"MacKorean", kTextEncodingMacKorean},
+ {"MacArabic", kTextEncodingMacArabic},
+ {"MacHebrew", kTextEncodingMacHebrew},
+ {"MacGreek", kTextEncodingMacGreek},
+ {"MacCyrillic", kTextEncodingMacCyrillic},
+ {"MacDevanagari", kTextEncodingMacDevanagari},
+ {"MacGurmukhi", kTextEncodingMacGurmukhi},
+ {"MacGujarati", kTextEncodingMacGujarati},
+ {"MacOriya", kTextEncodingMacOriya},
+ {"MacBengali", kTextEncodingMacBengali},
+ {"MacTamil", kTextEncodingMacTamil},
+ {"MacTelugu", kTextEncodingMacTelugu},
+ {"MacKannada", kTextEncodingMacKannada},
+ {"MacMalayalam", kTextEncodingMacMalayalam},
+ {"MacSinhalese", kTextEncodingMacSinhalese},
+ {"MacBurmese", kTextEncodingMacBurmese},
+ {"MacKhmer", kTextEncodingMacKhmer},
+ {"MacThai", kTextEncodingMacThai},
+ {"MacLaotian", kTextEncodingMacLaotian},
+ {"MacGeorgian", kTextEncodingMacGeorgian},
+ {"MacArmenian", kTextEncodingMacArmenian},
+ {"MacChineseSimp", kTextEncodingMacChineseSimp},
+ {"MacTibetan", kTextEncodingMacTibetan},
+ {"MacMongolian", kTextEncodingMacMongolian},
+ {"MacEthiopic", kTextEncodingMacEthiopic},
+ {"MacCentralEurRoman", kTextEncodingMacCentralEurRoman},
+ {"MacVietnamese", kTextEncodingMacVietnamese},
+ {"MacExtArabic", kTextEncodingMacExtArabic},
+ {"MacSymbol", kTextEncodingMacSymbol},
+ {"MacDingbats", kTextEncodingMacDingbats},
+ {"MacTurkish", kTextEncodingMacTurkish},
+ {"MacCroatian", kTextEncodingMacCroatian},
+ {"MacIcelandic", kTextEncodingMacIcelandic},
+ {"MacRomanian", kTextEncodingMacRomanian},
+ {"MacCeltic", kTextEncodingMacCeltic},
+ {"MacGaelic", kTextEncodingMacGaelic},
+ {"MacKeyboardGlyphs", kTextEncodingMacKeyboardGlyphs},
+ {"MacTradChinese", kTextEncodingMacTradChinese},
+ {"MacRSymbol", kTextEncodingMacRSymbol},
+ {"MacSimpChinese", kTextEncodingMacSimpChinese},
+ {"MacGeez", kTextEncodingMacGeez},
+ {"MacEastEurRoman", kTextEncodingMacEastEurRoman},
+ {"MacUninterp", kTextEncodingMacUninterp},
+ {"MacUnicode", kTextEncodingMacUnicode},
+ {"MacFarsi", kTextEncodingMacFarsi},
+ {"MacUkrainian", kTextEncodingMacUkrainian},
+ {"MacInuit", kTextEncodingMacInuit},
+ {"MacVT100", kTextEncodingMacVT100},
+ {"MacHFS", kTextEncodingMacHFS},
+ {"UnicodeDefault", kTextEncodingUnicodeDefault},
+ {"UnicodeV1_1", kTextEncodingUnicodeV1_1},
+ {"ISO10646_1993", kTextEncodingISO10646_1993},
+ {"UnicodeV2_0", kTextEncodingUnicodeV2_0},
+ {"UnicodeV2_1", kTextEncodingUnicodeV2_1},
+ {"UnicodeV3_0", kTextEncodingUnicodeV3_0},
+ {"UnicodeV3_1", kTextEncodingUnicodeV3_1},
+ {"UnicodeV3_2", kTextEncodingUnicodeV3_2},
+ {"ISOLatin1", kTextEncodingISOLatin1},
+ {"ISOLatin2", kTextEncodingISOLatin2},
+ {"ISOLatin3", kTextEncodingISOLatin3},
+ {"ISOLatin4", kTextEncodingISOLatin4},
+ {"ISOLatinCyrillic", kTextEncodingISOLatinCyrillic},
+ {"ISOLatinArabic", kTextEncodingISOLatinArabic},
+ {"ISOLatinGreek", kTextEncodingISOLatinGreek},
+ {"ISOLatinHebrew", kTextEncodingISOLatinHebrew},
+ {"ISOLatin5", kTextEncodingISOLatin5},
+ {"ISOLatin6", kTextEncodingISOLatin6},
+ {"ISOLatin7", kTextEncodingISOLatin7},
+ {"ISOLatin8", kTextEncodingISOLatin8},
+ {"ISOLatin9", kTextEncodingISOLatin9},
+ {"DOSLatinUS", kTextEncodingDOSLatinUS},
+ {"DOSGreek", kTextEncodingDOSGreek},
+ {"DOSBalticRim", kTextEncodingDOSBalticRim},
+ {"DOSLatin1", kTextEncodingDOSLatin1},
+ {"DOSGreek1", kTextEncodingDOSGreek1},
+ {"DOSLatin2", kTextEncodingDOSLatin2},
+ {"DOSCyrillic", kTextEncodingDOSCyrillic},
+ {"DOSTurkish", kTextEncodingDOSTurkish},
+ {"DOSPortuguese", kTextEncodingDOSPortuguese},
+ {"DOSIcelandic", kTextEncodingDOSIcelandic},
+ {"DOSHebrew", kTextEncodingDOSHebrew},
+ {"DOSCanadianFrench", kTextEncodingDOSCanadianFrench},
+ {"DOSArabic", kTextEncodingDOSArabic},
+ {"DOSNordic", kTextEncodingDOSNordic},
+ {"DOSRussian", kTextEncodingDOSRussian},
+ {"DOSGreek2", kTextEncodingDOSGreek2},
+ {"DOSThai", kTextEncodingDOSThai},
+ {"DOSJapanese", kTextEncodingDOSJapanese},
+ {"DOSChineseSimplif", kTextEncodingDOSChineseSimplif},
+ {"DOSKorean", kTextEncodingDOSKorean},
+ {"DOSChineseTrad", kTextEncodingDOSChineseTrad},
+ {"WindowsLatin1", kTextEncodingWindowsLatin1},
+ {"WindowsANSI", kTextEncodingWindowsANSI},
+ {"WindowsLatin2", kTextEncodingWindowsLatin2},
+ {"WindowsCyrillic", kTextEncodingWindowsCyrillic},
+ {"WindowsGreek", kTextEncodingWindowsGreek},
+ {"WindowsLatin5", kTextEncodingWindowsLatin5},
+ {"WindowsHebrew", kTextEncodingWindowsHebrew},
+ {"WindowsArabic", kTextEncodingWindowsArabic},
+ {"WindowsBalticRim", kTextEncodingWindowsBalticRim},
+ {"WindowsVietnamese", kTextEncodingWindowsVietnamese},
+ {"WindowsKoreanJohab", kTextEncodingWindowsKoreanJohab},
+ {"US_ASCII", kTextEncodingUS_ASCII},
+ {"JIS_X0201_76", kTextEncodingJIS_X0201_76},
+ {"JIS_X0208_83", kTextEncodingJIS_X0208_83},
+ {"JIS_X0208_90", kTextEncodingJIS_X0208_90},
+ {"JIS_X0212_90", kTextEncodingJIS_X0212_90},
+ {"JIS_C6226_78", kTextEncodingJIS_C6226_78},
+ {"ShiftJIS_X0213_00", kTextEncodingShiftJIS_X0213_00},
+ {"GB_2312_80", kTextEncodingGB_2312_80},
+ {"GBK_95", kTextEncodingGBK_95},
+ {"GB_18030_2000", kTextEncodingGB_18030_2000},
+ {"KSC_5601_87", kTextEncodingKSC_5601_87},
+ {"KSC_5601_92_Johab", kTextEncodingKSC_5601_92_Johab},
+ {"CNS_11643_92_P1", kTextEncodingCNS_11643_92_P1},
+ {"CNS_11643_92_P2", kTextEncodingCNS_11643_92_P2},
+ {"CNS_11643_92_P3", kTextEncodingCNS_11643_92_P3},
+ {"ISO_2022_JP", kTextEncodingISO_2022_JP},
+ {"ISO_2022_JP_2", kTextEncodingISO_2022_JP_2},
+ {"ISO_2022_JP_1", kTextEncodingISO_2022_JP_1},
+ {"ISO_2022_JP_3", kTextEncodingISO_2022_JP_3},
+ {"ISO_2022_CN", kTextEncodingISO_2022_CN},
+ {"ISO_2022_CN_EXT", kTextEncodingISO_2022_CN_EXT},
+ {"ISO_2022_KR", kTextEncodingISO_2022_KR},
+ {"EUC_JP", kTextEncodingEUC_JP},
+ {"EUC_CN", kTextEncodingEUC_CN},
+ {"EUC_TW", kTextEncodingEUC_TW},
+ {"EUC_KR", kTextEncodingEUC_KR},
+ {"ShiftJIS", kTextEncodingShiftJIS},
+ {"KOI8_R", kTextEncodingKOI8_R},
+ {"Big5", kTextEncodingBig5},
+ {"MacRomanLatin1", kTextEncodingMacRomanLatin1},
+ {"HZ_GB_2312", kTextEncodingHZ_GB_2312},
+ {"Big5_HKSCS_1999", kTextEncodingBig5_HKSCS_1999},
+ {"NextStepLatin", kTextEncodingNextStepLatin},
+ {"EBCDIC_US", kTextEncodingEBCDIC_US},
+ {"EBCDIC_CP037", kTextEncodingEBCDIC_CP037},
+ {"MultiRun", kTextEncodingMultiRun},
+
+ /* Terminator */
+ {NULL, -1},
+ };
+ int i;
+
+ i = 0;
+ for (i = 0; encodetable[i].name != NULL; ++i)
+ {
+ if (STRICMP(encodename, encodetable[i].name) == 0)
+ break;
+ }
+ return encodetable[i].encode;
+}
+
+/*
+ * iconv interfaces
+ */
+
+ iconv_t
+iconv_open(const char* tocode, const char* fromcode)
+{
+ TextEncoding toEnc, fromEnc;
+ iconv_t cd = NULL;
+ OSStatus st;
+
+ /* Verify to/from encoding name */
+ toEnc = get_textencoding(tocode);
+ fromEnc = get_textencoding(fromcode);
+ if (toEnc < 0 || fromEnc < 0)
+ goto ICONV_OPEN_ERR;
+
+ /* Allocate memory to object */
+ cd = (iconv_t)alloc(sizeof(struct _iconv_t));
+ if (!cd)
+ goto ICONV_OPEN_ERR;
+ memset(cd, 0, sizeof(struct _iconv_t));
+
+ /* Create converter */
+ if (fromEnc != toEnc)
+ {
+ TRACE("*** fromEnc=%d toEnc=%d\n", (int)fromEnc, (int)toEnc);
+ st = TECCreateConverter(&cd->tec, fromEnc, toEnc);
+ if (st != 0)
+ {
+ TRACE("*** TECCreateConverter()=%d\n", (int)st);
+ goto ICONV_OPEN_ERR;
+ }
+ /* Create reverse converter */
+ st = TECCreateConverter(&cd->tecReverse, toEnc, fromEnc);
+ if (st != 0)
+ {
+ TRACE("*** TECCreateConverter()=%d (reverse)\n", (int)st);
+ goto ICONV_OPEN_ERR;
+ }
+ /* Create Sniffer */
+ st = TECCreateSniffer(&cd->sniff, &fromEnc, 1);
+ if (st != 0)
+ {
+ TRACE("*** TECCreateSniffer()=%d\n", (int)st);
+ goto ICONV_OPEN_ERR;
+ }
+ }
+
+ cd->from = fromEnc;
+ cd->to = toEnc;
+ last_errno = 0;
+ return cd;
+
+ICONV_OPEN_ERR:
+ if (cd)
+ iconv_close(cd);
+ last_errno = EINVAL;
+ return (iconv_t)-1;
+}
+
+/*
+ * Used when there are same value in 'from encoding' and 'to encoding'.
+ * TEC doesn't support conversion between same encodings, and
+ * TECCreateConverter() failed.
+ */
+ static size_t
+null_conv(iconv_t cd, const char** inbuf, size_t *inbytesleft,
+ char** outbuf, size_t *outbytesleft)
+{
+ const char* buf_in = inbuf && *inbuf ? *inbuf : NULL;
+ char* buf_out = outbuf && *outbuf ? *outbuf : NULL;
+
+ if (buf_in)
+ {
+ int in_len = inbytesleft ? *inbytesleft : 0;
+ int out_len = outbytesleft ? *outbytesleft : 0;
+
+ if (!buf_out || out_len <= 0)
+ {
+ last_errno = E2BIG;
+ return -1;
+ }
+ else if (in_len > 0)
+ {
+ int len = in_len < out_len ? in_len : out_len;
+
+ memcpy (buf_out, buf_in, len);
+ *inbuf += len;
+ *outbuf += len;
+ *inbytesleft -= len;
+ *outbytesleft -= len;
+ if (*outbytesleft <= 0)
+ {
+ last_errno = E2BIG;
+ return -1;
+ }
+ }
+ }
+ last_errno = 0;
+ return 0;
+}
+
+ size_t
+iconv(iconv_t cd, const char** inbuf, size_t *inbytesleft,
+ char** outbuf, size_t *outbytesleft)
+{
+ ConstTextPtr buf_in;
+ TextPtr buf_out;
+ ByteCount out_len, out_true;
+ ByteCount in_len, in_true;
+ OSStatus st;
+
+ if (!cd)
+ {
+ last_errno = ENOENT; /* TODO: Another error code should be set */
+ return -1;
+ }
+ if (cd->from == cd->to)
+ return null_conv(cd, inbuf, inbytesleft, outbuf, outbytesleft) ;
+
+ buf_in = (TextPtr) inbuf ;
+ buf_out = (TextPtr) outbuf ;
+ out_len = out_true = -1;
+ in_len = in_true = -1;
+
+ if (buf_in && buf_out)
+ {
+ ItemCount error, feature;
+
+ /* Normal convert mode */
+ if (!inbytesleft || !outbytesleft)
+ {
+ last_errno = EFAULT;
+ return -1;
+ }
+ in_len = *inbytesleft;
+ out_len = *outbytesleft;
+
+ /* Check stream is form in expected encoding or not */
+ st = TECSniffTextEncoding(cd->sniff, (TextPtr)buf_in, in_len,
+ &cd->from, 1, &error, 1, &feature, 1);
+ TRACE("TECSniffTextEncoding()=%d error=%d feature=%d\n",
+ (int)st, (int)error, (int)feature);
+ if ((error != 0 || feature == 0)
+ && !(error == 0xffffffff && feature == 0xffffffff))
+ /* Not expected encoding */
+ st = kTECUnmappableElementErr;
+ else
+ {
+ /* Do convert */
+ st = TECConvertText(cd->tec,
+ buf_in, in_len, &in_true,
+ buf_out, out_len, &out_true);
+ /* Verify converted text. Compare original text with reverse
+ * converted text. If not match, there is some problem on
+ * converting. */
+ if (st == 0 && in_true > 0)
+ {
+ ByteCount rev_in, rev_out;
+ TextPtr buf_rev = (TextPtr)alloc(in_true);
+
+ if (buf_rev)
+ {
+ st = TECConvertText(cd->tecReverse,
+ buf_out, out_true, &rev_in,
+ buf_rev, in_true, &rev_out);
+ if (st != 0 || rev_in != out_true || rev_out != in_true
+ || memcmp(buf_rev, buf_in, rev_out) != 0)
+ {
+#ifdef ICONVOSX_DEBUG
+ fprintf(stderr, " reverse conversion failed.\n");
+#endif
+ st = kTECUnmappableElementErr;
+ }
+ vim_free(buf_rev);
+ }
+ else
+ st = kTECUnmappableElementErr;
+ }
+ }
+ }
+ else if (!buf_in && buf_out)
+ {
+ /* Flush all buffered strings to buffer, and reset status */
+ if (!outbytesleft)
+ {
+ last_errno = EFAULT;
+ return -1;
+ }
+ out_len = *outbytesleft;
+ st = TECFlushText(cd->tec,
+ buf_out, out_len, &out_true);
+ }
+ else if (!buf_in && !buf_out)
+ {
+ /* Reset cd's status and cancel buffered strings */
+ unsigned char tmp_out[256];
+
+ buf_out = tmp_out;
+ out_len = sizeof(tmp_out);
+ st = TECFlushText(cd->tec,
+ buf_out, out_len, &out_true);
+ }
+ else
+ {
+ last_errno = EFAULT;
+ return -1;
+ }
+ TRACE("st=%d, buf_in=%p, in_len=%d, in_true=%d\n"
+ " buf_out=%p, out_len=%d, out_true=%d\n", (int)st,
+ buf_in, (int)in_len, (int)in_true,
+ buf_out, (int)out_len, (int)out_true);
+
+ switch (st)
+ {
+ case 0:
+ /* No error */
+ if (inbytesleft)
+ *inbytesleft -= in_true;
+ if (outbytesleft)
+ *outbytesleft -= out_true;
+ if (inbuf && *inbuf)
+ *inbuf += in_true;
+ if (outbuf && *outbuf)
+ *outbuf += out_true;
+ last_errno = 0;
+ return 0; /* No error */
+ case kTECUnmappableElementErr:
+ last_errno = EILSEQ;
+ case kTECIncompleteElementErr:
+ last_errno = EINVAL;
+ case kTECOutputBufferFullStatus:
+ last_errno = E2BIG;
+ return -1;
+ default:
+ TRACE("iconv(%p, %p, %p, %p, %p) failed. (%d)\n",
+ cd, inbuf, inbytesleft, outbuf, outbytesleft, (int)st);
+ last_errno = EFAULT;
+ return -1;
+ }
+}
+
+ int
+iconv_close(iconv_t cd)
+{
+ if (cd)
+ {
+ /* Free all elements of iconv_t */
+ if (cd->tec)
+ TECDisposeConverter(cd->tec);
+ if (cd->tecReverse)
+ TECDisposeConverter(cd->tecReverse);
+ if (cd->sniff)
+ TECDisposeSniffer(cd->sniff);
+ vim_free(cd);
+ last_errno = 0;
+ return 0;
+ }
+ else
+ {
+ last_errno = EINVAL;
+ return -1;
+ }
+}
+
+ int*
+iconv_errno()
+{
+ return &last_errno;
+}
+#endif /* MACOS_X_ICONVEMU */
+
+#ifdef USE_MCH_GETTEXT
+
+#define GETTEXT_BUFNUM 64
+#define GETTEXT_BUFSIZE 256
+
+ char*
+mch_gettext(const char* msgid)
+{
+ static char buf[GETTEXT_BUFNUM][GETTEXT_BUFSIZE];
+ static int bufnum = 0;
+ const char *msg = NULL;
+ CFStringRef strkey = NULL, strmsg = NULL;
+ CFStringEncoding enc;
+
+ if (!msgid)
+ goto MCH_GETTEXT_FINISH;
+ enc = CFStringGetSystemEncoding();
+ TRACE("mch_gettext(%s)\n", msgid);
+
+ strkey = CFStringCreateWithCString(NULL, msgid, enc);
+ if (!strkey)
+ {
+ TRACE(" Can't create a CFString for msgid.\n");
+ goto MCH_GETTEXT_FINISH;
+ }
+
+ strmsg = CFCopyLocalizedString(strkey, NULL);
+ if (!strmsg)
+ {
+ TRACE(" No localized strings for msgid.\n");
+ goto MCH_GETTEXT_FINISH;
+ }
+
+ msg = CFStringGetCStringPtr(strmsg, enc);
+ if (!msg)
+ {
+ /* This is as backup when CFStringGetCStringPtr was failed */
+ CFStringGetCString(strmsg, buf[bufnum], GETTEXT_BUFSIZE, enc);
+ msg = buf[bufnum];
+ if (++bufnum >= GETTEXT_BUFNUM)
+ bufnum = 0;
+ }
+ TRACE(" Localized to: %s\n", msg);
+
+MCH_GETTEXT_FINISH:
+ if (strkey)
+ CFRelease(strkey);
+ if (strmsg)
+ CFRelease(strmsg);
+ return (char*)(msg ? msg : msgid);
+}
+
+ char*
+mch_bindtextdomain(const char* domain, const char* dirname)
+{
+ TRACE("mch_bindtextdomain(%s, %s)\n", domain, dirname);
+ return (char*)dirname;
+}
+
+ char*
+mch_textdomain(const char* domain)
+{
+ TRACE("mch_textdomain(%s)\n", domain);
+ return (char*)domain;
+}
+#endif
diff --git a/src/os_mint.h b/src/os_mint.h
new file mode 100644
index 000000000..94419b389
--- /dev/null
+++ b/src/os_mint.h
@@ -0,0 +1,13 @@
+/* vim:ts=8 sts=4:sw=4
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * Atari MiNT Machine-dependent things.
+ */
+
+#define BINARY_FILE_IO
diff --git a/src/os_msdos.c b/src/os_msdos.c
new file mode 100644
index 000000000..2d8b127e6
--- /dev/null
+++ b/src/os_msdos.c
@@ -0,0 +1,3114 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * os_msdos.c
+ *
+ * MSDOS system-dependent routines.
+ * A cheap plastic imitation of the amiga dependent code.
+ * A lot in this file was made by Juergen Weigert (jw).
+ *
+ * DJGPP changes by Gert van Antwerpen
+ * Faster text screens by John Lange (jlange@zilker.net)
+ * Windows clipboard functionality added by David Kotchan (dk)
+ *
+ * Some functions are also used for Win16 (MS-Windows 3.1).
+ */
+
+#include <io.h>
+#include "vim.h"
+
+#include <conio.h>
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+/*
+ * MS-DOS only code, not used for Win16.
+ */
+#ifndef WIN16
+
+
+#include <bios.h>
+#ifdef DJGPP
+# include <dpmi.h>
+# include <signal.h>
+# include <sys/movedata.h>
+# include <crt0.h>
+# ifdef FEAT_CLIPBOARD
+# include <sys/segments.h>
+# endif
+#else
+# include <alloc.h>
+#endif
+
+#if defined(DJGPP) || defined(PROTO)
+# define _cdecl /* DJGPP doesn't have this */
+#endif
+
+static int cbrk_pressed = FALSE; /* set by ctrl-break interrupt */
+static int ctrlc_pressed = FALSE; /* set when ctrl-C or ctrl-break detected */
+static int delayed_redraw = FALSE; /* set when ctrl-C detected */
+
+static int bioskey_read = _NKEYBRD_READ; /* bioskey() argument: read key */
+static int bioskey_ready = _NKEYBRD_READY; /* bioskey() argument: key ready? */
+
+#ifdef FEAT_MOUSE
+static int mouse_avail = FALSE; /* mouse present */
+static int mouse_active; /* mouse enabled */
+static int mouse_hidden; /* mouse not shown */
+static int mouse_click = -1; /* mouse status */
+static int mouse_last_click = -1; /* previous status at click */
+static int mouse_x = -1; /* mouse x coodinate */
+static int mouse_y = -1; /* mouse y coodinate */
+static long mouse_click_time = 0; /* biostime() of last click */
+static int mouse_click_count = 0; /* count for multi-clicks */
+static int mouse_click_x = 0; /* x of previous mouse click */
+static int mouse_click_y = 0; /* y of previous mouse click */
+static linenr_T mouse_topline = 0; /* w_topline at previous mouse click */
+#ifdef FEAT_DIFF
+static int mouse_topfill = 0; /* w_topfill at previous mouse click */
+#endif
+static int mouse_x_div = 8; /* column = x coord / mouse_x_div */
+static int mouse_y_div = 8; /* line = y coord / mouse_y_div */
+#endif
+
+#define BIOSTICK 55 /* biostime() increases one tick about
+ every 55 msec */
+
+static int orig_attr = 0x0700; /* video attributes when starting */
+
+static int S_iLeft = 0; /* Scroll window; these are 1 offset */
+static int S_iTop = 0;
+static int S_iRight = 0;
+static int S_iBottom = 0;
+
+/*
+ * Need to remember the values, because we set horizontal and vertical
+ * edges separately.
+ */
+ static void
+mywindow(int iLeft, int iTop, int iRight, int iBottom)
+{
+ S_iLeft = iLeft;
+ S_iTop = iTop;
+ S_iRight = iRight;
+ S_iBottom = iBottom;
+ window(iLeft, iTop, iRight, iBottom);
+}
+
+#ifdef DJGPP
+/*
+ * For DJGPP, use our own functions for fast text screens. JML 1/18/98
+ */
+
+unsigned long S_ulScreenBase = 0xb8000;
+unsigned short S_uiAttribute = 0;
+int S_iCurrentRow = 0; /* These are 0 offset */
+int S_iCurrentColumn = 0;
+short S_selVideo; /* Selector for DJGPP direct video transfers */
+
+/*
+ * Use burst writes to improve mch_write speed - VJN 01/10/99
+ */
+unsigned short S_linebuffer[8000]; /* <VN> enough for 160x50 */
+unsigned short S_blankbuffer[256]; /* <VN> max length of console line */
+unsigned short *S_linebufferpos = S_linebuffer;
+int S_iBufferRow;
+int S_iBufferColumn;
+
+ static void
+myflush(void)
+{
+ if (S_linebufferpos != S_linebuffer)
+ {
+ _dosmemputw(S_linebuffer, (S_linebufferpos - S_linebuffer),
+ S_ulScreenBase
+ + S_iBufferRow * (Columns << 1) + (S_iBufferColumn << 1));
+ S_linebufferpos = S_linebuffer;
+ }
+}
+
+ static void
+mygotoxy(int x, int y)
+{
+ S_iCurrentRow = y - 1;
+ S_iCurrentColumn = x - 1;
+}
+
+/*
+ * Set the system cursor to our cursor position.
+ */
+ static void
+set_sys_cursor(void)
+{
+ if (term_console && full_screen)
+ {
+ myflush();
+ gotoxy(S_iCurrentColumn + 1, S_iCurrentRow + 1);
+ }
+}
+
+ static void
+setblankbuffer(unsigned short uiValue)
+{
+ int i;
+ static unsigned short olduiValue = 0;
+
+ if (olduiValue != uiValue)
+ {
+ /* Load blank line buffer with spaces */
+ for (i = 0; i < Columns; ++i)
+ S_blankbuffer[i] = uiValue;
+ olduiValue = uiValue;
+ }
+}
+
+ static void
+myclreol(void)
+{
+ /* Clear to end of line */
+ setblankbuffer(S_uiAttribute | ' ');
+ _dosmemputw(S_blankbuffer, S_iRight - S_iCurrentColumn, S_ulScreenBase
+ + (S_iCurrentRow) * (Columns << 1)
+ + (S_iCurrentColumn << 1));
+}
+
+ static void
+myclrscr(void)
+{
+ /* Clear whole screen */
+ short iColumn;
+ int endpoint = (Rows * Columns) << 1;
+
+ setblankbuffer(S_uiAttribute | ' ');
+
+ for (iColumn = 0; iColumn < endpoint; iColumn += (Columns << 1))
+ _dosmemputw(S_blankbuffer, Columns, S_ulScreenBase + iColumn);
+}
+
+ static void
+mydelline(void)
+{
+ short iRow, iColumn;
+
+ iColumn = (S_iLeft - 1) << 1;
+
+ /* Copy the lines underneath */
+ for (iRow = S_iCurrentRow; iRow < S_iBottom - 1; iRow++)
+ movedata(S_selVideo, (((iRow + 1) * Columns) << 1) + iColumn,
+ S_selVideo, ((iRow * Columns) << 1) + iColumn,
+ (S_iRight - S_iLeft + 1) << 1);
+
+ /* Clear the new row */
+ setblankbuffer(S_uiAttribute | ' ');
+
+ _dosmemputw(S_blankbuffer, (S_iRight - S_iLeft) + 1, S_ulScreenBase
+ + (S_iBottom - 1) * (Columns << 1) + iColumn);
+}
+
+ static void
+myinsline(void)
+{
+ short iRow, iColumn;
+
+ iColumn = (S_iLeft - 1) << 1;
+
+ /* Copy the lines underneath */
+ for (iRow = S_iBottom - 1; iRow >= S_iTop; iRow--)
+ movedata(S_selVideo, (((iRow - 1) * Columns) << 1) + iColumn,
+ S_selVideo, ((iRow * Columns) << 1) + iColumn,
+ (S_iRight - S_iLeft + 1) << 1);
+
+ /* Clear the new row */
+ setblankbuffer(S_uiAttribute | ' ');
+
+ _dosmemputw(S_blankbuffer, (S_iRight - S_iLeft) + 1, S_ulScreenBase
+ + (S_iTop - 1) * (Columns << 1) + iColumn);
+}
+
+/*
+ * Scroll the screen one line up, clear the last line.
+ */
+ static void
+myscroll(void)
+{
+ short iRow, iColumn;
+
+ iColumn = (S_iLeft - 1) << 1;
+
+ /* Copy the screen */
+ for (iRow = S_iTop; iRow < S_iBottom; iRow++)
+ movedata(S_selVideo, ((iRow * Columns) << 1) + iColumn,
+ S_selVideo, (((iRow - 1) * Columns) << 1) + iColumn,
+ (S_iRight - S_iLeft + 1) << 1);
+
+ /* Clear the bottom row */
+ setblankbuffer(S_uiAttribute | ' ');
+
+ _dosmemputw(S_blankbuffer, (S_iRight - S_iLeft) + 1, S_ulScreenBase
+ + (S_iBottom - 1) * (Columns << 1) + iColumn);
+}
+
+ static int
+myputch(int iChar)
+{
+ unsigned short uiValue;
+
+ if (iChar == '\n')
+ {
+ myflush();
+ if (S_iCurrentRow >= S_iBottom - S_iTop)
+ myscroll();
+ else
+ {
+ S_iCurrentColumn = S_iLeft - 1;
+ S_iCurrentRow++;
+ }
+ }
+ else if (iChar == '\r')
+ {
+ myflush();
+ S_iCurrentColumn = S_iLeft - 1;
+ }
+ else if (iChar == '\b')
+ {
+ myflush();
+ if (S_iCurrentColumn >= S_iLeft)
+ S_iCurrentColumn--;
+ }
+ else if (iChar == 7)
+ {
+ sound(440); /* short beep */
+ delay(200);
+ nosound();
+ }
+ else
+ {
+ uiValue = S_uiAttribute | (unsigned char)iChar;
+
+ /*
+ * Normal char - are we starting to buffer?
+ */
+ if (S_linebufferpos == S_linebuffer)
+ {
+ S_iBufferColumn = S_iCurrentColumn;
+ S_iBufferRow = S_iCurrentRow;
+ }
+
+ *S_linebufferpos++ = uiValue;
+
+ S_iCurrentColumn++;
+ if (S_iCurrentColumn >= S_iRight && S_iCurrentRow >= S_iBottom - S_iTop)
+ {
+ myflush();
+ myscroll();
+ S_iCurrentColumn = S_iLeft - 1;
+ S_iCurrentRow++;
+ }
+ }
+
+ return 0;
+}
+
+ static void
+mytextinit(struct text_info *pTextinfo)
+{
+ S_selVideo = __dpmi_segment_to_descriptor(S_ulScreenBase >> 4);
+ S_uiAttribute = pTextinfo->normattr << 8;
+}
+
+ static void
+get_screenbase(void)
+{
+ static union REGS regs;
+
+ /* old Hercules grafic card has different base address (Macewicz) */
+ regs.h.ah = 0x0f;
+ (void)int86(0x10, &regs, &regs); /* int 10 0f */
+ if (regs.h.al == 0x07) /* video mode 7 -- hercules mono */
+ S_ulScreenBase = 0xb0000;
+ else
+ S_ulScreenBase = 0xb8000;
+}
+
+ static void
+mytextattr(int iAttribute)
+{
+ S_uiAttribute = (unsigned short)iAttribute << 8;
+}
+
+ static void
+mynormvideo(void)
+{
+ mytextattr(orig_attr);
+}
+
+ static void
+mytextcolor(int iTextColor)
+{
+ S_uiAttribute = (unsigned short)((S_uiAttribute & 0xf000)
+ | (unsigned short)iTextColor << 8);
+}
+
+ static void
+mytextbackground(int iBkgColor)
+{
+ S_uiAttribute = (unsigned short)((S_uiAttribute & 0x0f00)
+ | (unsigned short)(iBkgColor << 12));
+}
+/*
+ * Getdigits: Get a number from a string and skip over it.
+ * Note: the argument is a pointer to a char_u pointer!
+ */
+
+ static long
+mygetdigits(pp)
+ char_u **pp;
+{
+ char_u *p;
+ long retval = 0;
+
+ p = *pp;
+ if (*p == '-') /* skip negative sign */
+ ++p;
+ while (VIM_ISDIGIT(*p))
+ {
+ retval = (retval * 10) + (*p - '0');
+ ++p;
+ }
+ if (**pp == '-') /* process negative sign */
+ retval = -retval;
+
+ *pp = p;
+ return retval;
+}
+#else
+# define mygotoxy gotoxy
+# define myputch putch
+# define myscroll scroll
+# define mynormvideo normvideo
+# define mytextattr textattr
+# define mytextcolor textcolor
+# define mytextbackground textbackground
+# define mygetdigits getdigits
+# define myclreol clreol
+# define myclrscr clrscr
+# define myinsline insline
+# define mydelline delline
+#endif
+
+static const struct
+{
+ char_u scancode;
+ char_u metakey;
+} altkey_table[] =
+{
+ {0x1e, 0xe1}, /* a */
+ {0x30, 0xe2}, /* b */
+ {0x2e, 0xe3}, /* c */
+ {0x20, 0xe4}, /* d */
+ {0x12, 0xe5}, /* e */
+ {0x21, 0xe6}, /* f */
+ {0x22, 0xe7}, /* g */
+ {0x23, 0xe8}, /* h */
+ {0x17, 0xe9}, /* i */
+ {0x24, 0xea}, /* j */
+ {0x25, 0xeb}, /* k */
+ {0x26, 0xec}, /* l */
+ {0x32, 0xed}, /* m */
+ {0x31, 0xee}, /* n */
+ {0x18, 0xef}, /* o */
+ {0x19, 0xf0}, /* p */
+ {0x10, 0xf1}, /* q */
+ {0x13, 0xf2}, /* r */
+ {0x1f, 0xf3}, /* s */
+ {0x14, 0xf4}, /* t */
+ {0x16, 0xf5}, /* u */
+ {0x2f, 0xf6}, /* v */
+ {0x11, 0xf7}, /* w */
+ {0x2d, 0xf8}, /* x */
+ {0x15, 0xf9}, /* y */
+ {0x2c, 0xfa}, /* z */
+ {0x78, 0xb1}, /* 1 */
+ {0x79, 0xb2}, /* 2 */
+ {0x7a, 0xb3}, /* 3 */
+ {0x7b, 0xb4}, /* 4 */
+ {0x7c, 0xb5}, /* 5 */
+ {0x7d, 0xb6}, /* 6 */
+ {0x7e, 0xb7}, /* 7 */
+ {0x7f, 0xb8}, /* 8 */
+ {0x80, 0xb9}, /* 9 */
+ {0x81, 0xb0}, /* 0 */
+};
+
+/*
+ * Translate extended keycodes into meta-chars where applicable
+ */
+ static int
+translate_altkeys(int rawkey)
+{
+ int i, c;
+
+ if ((rawkey & 0xff) == 0)
+ {
+ c = (rawkey >> 8);
+ for (i = sizeof(altkey_table) / sizeof(altkey_table[0]); --i >= 0; )
+ {
+ if (c == altkey_table[i].scancode)
+ return (int)altkey_table[i].metakey;
+ }
+ }
+ return rawkey;
+}
+
+/*
+ * Set normal fg/bg color, based on T_ME. Called whem t_me has been set.
+ */
+ void
+mch_set_normal_colors()
+{
+ char_u *p;
+ int n;
+
+ cterm_normal_fg_color = (orig_attr & 0xf) + 1;
+ cterm_normal_bg_color = ((orig_attr >> 4) & 0xf) + 1;
+ if (T_ME[0] == ESC && T_ME[1] == '|')
+ {
+ p = T_ME + 2;
+ n = getdigits(&p);
+ if (*p == 'm' && n > 0)
+ {
+ cterm_normal_fg_color = (n & 0xf) + 1;
+ cterm_normal_bg_color = ((n >> 4) & 0xf) + 1;
+ }
+ }
+}
+
+#if defined(MCH_CURSOR_SHAPE) || defined(PROTO)
+/*
+ * Save/restore the shape of the cursor.
+ * call with FALSE to save, TRUE to restore
+ */
+ static void
+mch_restore_cursor_shape(int restore)
+{
+ static union REGS regs;
+ static int saved = FALSE;
+
+ if (restore)
+ {
+ if (saved)
+ regs.h.ah = 0x01; /*Set Cursor*/
+ else
+ return;
+ }
+ else
+ {
+ regs.h.ah = 0x03; /*Get Cursor*/
+ regs.h.bh = 0x00; /*Page */
+ saved = TRUE;
+ }
+
+ (void)int86(0x10, &regs, &regs);
+}
+
+/*
+ * Set the shape of the cursor.
+ * 'thickness' can be from 0 (thin) to 7 (block)
+ */
+ static void
+mch_set_cursor_shape(int thickness)
+{
+ union REGS regs;
+
+ regs.h.ch = 7 - thickness; /*Starting Line*/
+ regs.h.cl = 7; /*Ending Line*/
+ regs.h.ah = 0x01; /*Set Cursor*/
+ (void)int86(0x10, &regs, &regs);
+}
+
+ void
+mch_update_cursor(void)
+{
+ int idx;
+ int thickness;
+
+ /*
+ * How the cursor is drawn depends on the current mode.
+ */
+ idx = get_shape_idx(FALSE);
+
+ if (shape_table[idx].shape == SHAPE_BLOCK)
+ thickness = 7;
+ else
+ thickness = (7 * shape_table[idx].percentage + 90) / 100;
+ mch_set_cursor_shape(thickness);
+}
+#endif
+
+/*
+ * Return amount of memory currently available.
+ */
+ long_u
+mch_avail_mem(int special)
+{
+#ifdef DJGPP
+ return _go32_dpmi_remaining_virtual_memory();
+#else
+ return coreleft();
+#endif
+}
+
+#ifdef FEAT_MOUSE
+
+/*
+ * Set area where mouse can be moved to: The whole screen.
+ * Rows and Columns must be valid when calling!
+ */
+ static void
+mouse_area(void)
+{
+ union REGS regs;
+
+ if (mouse_avail)
+ {
+ regs.x.cx = 0; /* mouse visible between cx and dx */
+ regs.x.dx = Columns * mouse_x_div - 1;
+ regs.x.ax = 7;
+ (void)int86(0x33, &regs, &regs);
+
+ regs.x.cx = 0; /* mouse visible between cx and dx */
+ regs.x.dx = Rows * mouse_y_div - 1;
+ regs.x.ax = 8;
+ (void)int86(0x33, &regs, &regs);
+ }
+}
+
+ static void
+show_mouse(int on)
+{
+ static int was_on = FALSE;
+ union REGS regs;
+
+ if (mouse_avail)
+ {
+ if (!mouse_active || mouse_hidden)
+ on = FALSE;
+ /*
+ * Careful: Each switch on must be compensated by exactly one switch
+ * off
+ */
+ if ((on && !was_on) || (!on && was_on))
+ {
+ was_on = on;
+ regs.x.ax = on ? 1 : 2;
+ int86(0x33, &regs, &regs); /* show mouse */
+ if (on)
+ mouse_area();
+ }
+ }
+}
+
+#endif
+
+/*
+ * Version of kbhit() and getch() that use direct console I/O.
+ * This avoids trouble with CTRL-P and the like, and should work over a telnet
+ * connection (it works for Xvi).
+ */
+
+static int cons_key = -1;
+
+/*
+ * Try to get one character directly from the console.
+ * If there is a key, it is stored in cons_key.
+ * Only call when cons_key is -1!
+ */
+ static void
+cons_getkey(void)
+{
+ union REGS regs;
+
+ /* call DOS function 6: Direct console I/O */
+ regs.h.ah = 0x06;
+ regs.h.dl = 0xff;
+ (void)intdos(&regs, &regs);
+ if ((regs.x.flags & 0x40) == 0) /* zero flag not set? */
+ cons_key = (regs.h.al & 0xff);
+}
+
+/*
+ * Return TRUE if a character is available.
+ */
+ static int
+cons_kbhit(void)
+{
+ if (cons_key < 0)
+ cons_getkey();
+ return (cons_key >= 0);
+}
+
+/*
+ * Return a character from the console.
+ * Should only be called when vim_kbhit() returns TRUE.
+ */
+ static int
+cons_getch(void)
+{
+ int c = -1;
+
+ if (cons_key < 0)
+ cons_getkey();
+ c = cons_key;
+ cons_key = -1;
+ return c;
+}
+
+
+#ifdef DJGPP
+/*
+ * DJGPP provides a kbhit() function that goes to the BIOS instead of DOS.
+ * This doesn't work for terminals connected to a serial port.
+ * Redefine kbhit() here to make it work.
+ */
+ static int
+vim_kbhit(void)
+{
+ union REGS regs;
+
+ regs.h.ah = 0x0b;
+ (void)intdos(&regs, &regs);
+ return regs.h.al;
+}
+
+#ifdef kbhit
+# undef kbhit /* might have been defined in conio.h */
+#endif
+#define kbhit() vim_kbhit()
+
+#endif
+
+/*
+ * Simulate WaitForChar() by slowly polling with bioskey(1) or kbhit().
+ *
+ * If Vim should work over the serial line after a 'ctty com1' we must use
+ * kbhit() and getch(). (jw)
+ * Usually kbhit() is not used, because then CTRL-C and CTRL-P
+ * will be catched by DOS (mool).
+ *
+ * return TRUE if a character is available, FALSE otherwise
+ */
+
+#define FOREVER 1999999999L
+
+ static int
+WaitForChar(long msec)
+{
+ union REGS regs;
+ long starttime = 0;
+ int x, y;
+
+ if (msec != 0)
+ starttime = biostime(0, 0L);
+
+ for (;;)
+ {
+#ifdef FEAT_MOUSE
+ long clicktime;
+ static int old_status = 0;
+
+ if (mouse_avail && mouse_active && mouse_click < 0)
+ {
+ regs.x.ax = 3;
+ int86(0x33, &regs, &regs); /* check mouse status */
+ /* only recognize button-down and button-up event */
+ x = regs.x.cx / mouse_x_div;
+ y = regs.x.dx / mouse_y_div;
+ if ((old_status == 0) != (regs.x.bx == 0))
+ {
+ if (old_status) /* button up */
+ mouse_click = MOUSE_RELEASE;
+ else /* button down */
+ {
+ /*
+ * Translate MSDOS mouse events to Vim mouse events.
+ * TODO: should handle middle mouse button, by pressing
+ * left and right at the same time.
+ */
+ if (regs.x.bx & MSDOS_MOUSE_LEFT)
+ mouse_click = MOUSE_LEFT;
+ else if (regs.x.bx & MSDOS_MOUSE_RIGHT)
+ mouse_click = MOUSE_RIGHT;
+ else if (regs.x.bx & MSDOS_MOUSE_MIDDLE)
+ mouse_click = MOUSE_MIDDLE;
+
+ /*
+ * Find out if this is a multi-click
+ */
+ clicktime = biostime(0, 0L);
+ if (mouse_click_x == x && mouse_click_y == y
+ && mouse_topline == curwin->w_topline
+#ifdef FEAT_DIFF
+ && mouse_topfill == curwin->w_topfill
+#endif
+ && mouse_click_count != 4
+ && mouse_click == mouse_last_click
+ && clicktime < mouse_click_time
+ + p_mouset / BIOSTICK)
+ ++mouse_click_count;
+ else
+ mouse_click_count = 1;
+ mouse_click_time = clicktime;
+ mouse_last_click = mouse_click;
+ mouse_click_x = x;
+ mouse_click_y = y;
+ mouse_topline = curwin->w_topline;
+#ifdef FEAT_DIFF
+ mouse_topfill = curwin->w_topfill;
+#endif
+ SET_NUM_MOUSE_CLICKS(mouse_click, mouse_click_count);
+ }
+ }
+ else if (old_status && (x != mouse_x || y != mouse_y))
+ mouse_click = MOUSE_DRAG;
+ old_status = regs.x.bx;
+ if (mouse_hidden && mouse_x >= 0 && (mouse_x != x || mouse_y != y))
+ {
+ mouse_hidden = FALSE;
+ show_mouse(TRUE);
+ }
+ mouse_x = x;
+ mouse_y = y;
+ }
+#endif
+
+ if ((p_consk ? cons_kbhit()
+ : p_biosk ? bioskey(bioskey_ready) : kbhit())
+ || cbrk_pressed
+#ifdef FEAT_MOUSE
+ || mouse_click >= 0
+#endif
+ )
+ return TRUE;
+ /*
+ * Use biostime() to wait until our time is done.
+ * We busy-wait here. Unfortunately, delay() and usleep() have been
+ * reported to give problems with the original Windows 95. This is
+ * fixed in service pack 1, but not everybody installed that.
+ * The DJGPP implementation of usleep() uses a busy-wait loop too.
+ */
+ if (msec == 0 || (msec != FOREVER
+ && biostime(0, 0L) > starttime + msec / BIOSTICK))
+ break;
+
+#ifdef DJGPP
+ /* Yield the CPU to the next process. */
+ __dpmi_yield();
+#endif
+ }
+ return FALSE;
+}
+
+/*
+ * don't do anything for about "msec" msec
+ */
+ void
+mch_delay(
+ long msec,
+ int ignoreinput)
+{
+ long starttime;
+
+ if (ignoreinput)
+ {
+ /*
+ * We busy-wait here. Unfortunately, delay() and usleep() have been
+ * reported to give problems with the original Windows 95. This is
+ * fixed in service pack 1, but not everybody installed that.
+ */
+ starttime = biostime(0, 0L);
+ while (biostime(0, 0L) < starttime + msec / BIOSTICK)
+ ;
+ }
+ else
+ WaitForChar(msec);
+}
+
+/*
+ * mch_write(): write the output buffer to the screen
+ */
+ void
+mch_write(
+ char_u *s,
+ int len)
+{
+ char_u *p;
+ int row, col;
+
+ if (term_console && full_screen)
+ while (len--)
+ {
+ /* translate ESC | sequences into bios calls */
+ if (p_wd) /* testing: wait a bit for each char */
+ WaitForChar(p_wd);
+
+ if (s[0] == '\n')
+#ifdef DJGPP
+ {
+ myflush();
+ S_iCurrentColumn = S_iLeft - 1;
+ }
+#else
+ myputch('\r');
+#endif
+ else if (s[0] == ESC && len > 1 && s[1] == '|')
+ {
+ switch (s[2])
+ {
+#ifdef DJGPP
+ case 'B': ScreenVisualBell();
+ goto got3;
+#endif
+ case 'J':
+#ifdef DJGPP
+ myflush();
+#endif
+ myclrscr();
+ goto got3;
+
+ case 'K':
+#ifdef DJGPP
+ myflush();
+#endif
+ myclreol();
+ goto got3;
+
+ case 'L':
+#ifdef DJGPP
+ myflush();
+#endif
+ myinsline();
+ goto got3;
+
+ case 'M':
+#ifdef DJGPP
+ myflush();
+#endif
+ mydelline();
+got3: s += 3;
+ len -= 2;
+ continue;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': p = s + 2;
+ row = mygetdigits(&p); /* no check for length! */
+ if (p > s + len)
+ break;
+ if (*p == ';')
+ {
+ ++p;
+ col = mygetdigits(&p); /* no check for length! */
+ if (p > s + len)
+ break;
+ if (*p == 'H' || *p == 'r' || *p == 'V')
+ {
+#ifdef DJGPP
+ myflush();
+#endif
+ if (*p == 'H') /* set cursor position */
+ mygotoxy(col, row);
+ else if (*p == 'V')
+ mywindow(row, S_iTop, col, S_iBottom);
+ else /* set scroll region */
+ mywindow(S_iLeft, row, S_iRight, col);
+ len -= p - s;
+ s = p + 1;
+ continue;
+ }
+ }
+ else if (*p == 'm' || *p == 'f' || *p == 'b')
+ {
+ if (*p == 'm') /* set color */
+ {
+ if (row == 0)
+ mynormvideo();/* reset color */
+ else
+ mytextattr(row);
+ }
+ else if (*p == 'f') /* set foreground color */
+ mytextcolor(row);
+ else /* set background color */
+ mytextbackground(row);
+
+ len -= p - s;
+ s = p + 1;
+ continue;
+ }
+ }
+ }
+ myputch(*s++);
+ }
+ else
+ {
+ write(1, s, (unsigned)len);
+ }
+}
+
+/*
+ * mch_inchar(): low level input funcion.
+ * Get a characters from the keyboard.
+ * If time == 0 do not wait for characters.
+ * If time == n wait a short time for characters.
+ * If time == -1 wait forever for characters.
+ *
+ * return the number of characters obtained
+ */
+ int
+mch_inchar(
+ char_u *buf,
+ int maxlen,
+ long time,
+ int tb_change_cnt)
+{
+ int len = 0;
+ int c;
+ int tmp_c;
+ static int nextchar = 0; /* may keep character when maxlen == 1 */
+#ifdef FEAT_AUTOCMD
+ static int once_already = 0;
+#endif
+
+ /*
+ * if we got a ctrl-C when we were busy, there will be a "^C" somewhere
+ * on the sceen, so we need to redisplay it.
+ */
+ if (delayed_redraw)
+ {
+ delayed_redraw = FALSE;
+ update_screen(CLEAR);
+ setcursor();
+ out_flush();
+ }
+
+ /* return remaining character from last call */
+ if (nextchar)
+ {
+ *buf = nextchar;
+ nextchar = 0;
+ return 1;
+ }
+
+#ifdef FEAT_MOUSE
+ if (time != 0)
+ show_mouse(TRUE);
+#endif
+#ifdef DJGPP
+ set_sys_cursor();
+#endif
+ if (time >= 0)
+ {
+ if (WaitForChar(time) == 0) /* no character available */
+ {
+#ifdef FEAT_MOUSE
+ show_mouse(FALSE);
+#endif
+#ifdef FEAT_AUTOCMD
+ once_already = 0;
+#endif
+ return 0;
+ }
+ }
+ else /* time == -1 */
+ {
+#ifdef FEAT_AUTOCMD
+ if (once_already == 2)
+ updatescript(0);
+ else if (once_already == 1)
+ {
+ setcursor();
+ once_already = 2;
+ return 0;
+ }
+ else
+#endif
+ /*
+ * If there is no character available within 2 seconds (default)
+ * write the autoscript file to disk
+ */
+ if (WaitForChar(p_ut) == 0)
+ {
+#ifdef FEAT_AUTOCMD
+ if (has_cursorhold() && get_real_state() == NORMAL_BUSY)
+ {
+ apply_autocmds(EVENT_CURSORHOLD, NULL, NULL, FALSE, curbuf);
+ update_screen(VALID);
+ once_already = 1;
+ return 0;
+ }
+ else
+#endif
+ updatescript(0);
+ }
+ }
+ WaitForChar(FOREVER); /* wait for key or mouse click */
+
+/*
+ * Try to read as many characters as there are, until the buffer is full.
+ */
+ /*
+ * we will get at least one key. Get more if they are available
+ * After a ctrl-break we have to read a 0 (!) from the buffer.
+ * bioskey(1) will return 0 if no key is available and when a
+ * ctrl-break was typed. When ctrl-break is hit, this does not always
+ * implies a key hit.
+ */
+ cbrk_pressed = FALSE;
+#ifdef FEAT_MOUSE
+ if (mouse_click >= 0 && maxlen >= 5)
+ {
+ len = 5;
+ *buf++ = ESC + 128;
+ *buf++ = 'M';
+ *buf++ = mouse_click;
+ *buf++ = mouse_x + '!';
+ *buf++ = mouse_y + '!';
+ mouse_click = -1;
+ }
+ else
+#endif
+ {
+#ifdef FEAT_MOUSE
+ mouse_hidden = TRUE;
+#endif
+ if (p_biosk && !p_consk)
+ {
+ while ((len == 0 || bioskey(bioskey_ready)) && len < maxlen)
+ {
+ c = translate_altkeys(bioskey(bioskey_read)); /* get the key */
+ /*
+ * translate a few things for inchar():
+ * 0x0000 == CTRL-break -> 3 (CTRL-C)
+ * 0x0300 == CTRL-@ -> NUL
+ * 0xnn00 == extended key code -> K_NUL, nn
+ * 0xnne0 == enhanced keyboard -> K_NUL, nn
+ * K_NUL -> K_NUL, 3
+ */
+ if (c == 0)
+ c = 3;
+ else if (c == 0x0300)
+ c = NUL;
+ else if ((c & 0xff) == 0
+ || c == K_NUL
+ || c == 0x4e2b
+ || c == 0x4a2d
+ || c == 0x372a
+ || ((c & 0xff) == 0xe0 && c != 0xe0))
+ {
+ if (c == K_NUL)
+ c = 3;
+ else
+ c >>= 8;
+ *buf++ = K_NUL;
+ ++len;
+ }
+
+ if (len < maxlen)
+ {
+ *buf++ = c;
+ len++;
+#ifdef FEAT_MBYTE
+ /* Convert from 'termencoding' to 'encoding'. Only
+ * translate normal characters, not key codes. */
+ if (input_conv.vc_type != CONV_NONE
+ && (len == 1 || buf[-2] != K_NUL))
+ len += convert_input(buf - 1, 1, maxlen - len + 1) - 1;
+#endif
+ }
+ else
+ nextchar = c;
+ }
+ }
+ else
+ {
+ while ((len == 0 || (p_consk ? cons_kbhit() : kbhit()))
+ && len < maxlen)
+ {
+ switch (c = (p_consk ? cons_getch() : getch()))
+ {
+ case 0:
+ /* NUL means that there is another character.
+ * Get it immediately, because kbhit() doesn't always
+ * return TRUE for the second character.
+ */
+ if (p_consk)
+ c = cons_getch();
+ else
+ c = getch();
+ tmp_c = translate_altkeys(c << 8);
+ if (tmp_c == (c << 8))
+ {
+ *buf++ = K_NUL;
+ ++len;
+ }
+ else
+ c = tmp_c;
+ break;
+ case K_NUL:
+ *buf++ = K_NUL;
+ ++len;
+ c = 3;
+ break;
+ case 3:
+ cbrk_pressed = TRUE;
+ /*FALLTHROUGH*/
+ default:
+ break;
+ }
+ if (len < maxlen)
+ {
+ *buf++ = c;
+ ++len;
+ }
+ else
+ nextchar = c;
+ }
+ }
+ }
+#ifdef FEAT_MOUSE
+ show_mouse(FALSE);
+#endif
+
+ beep_count = 0; /* may beep again now that we got some chars */
+#ifdef FEAT_AUTOCMD
+ once_already = 0;
+#endif
+ return len;
+}
+
+/*
+ * return non-zero if a character is available
+ */
+ int
+mch_char_avail(void)
+{
+ return WaitForChar(0L);
+}
+
+#ifdef DJGPP
+# define INT_ARG int
+#else
+# define INT_ARG
+#endif
+
+/*
+ * function for ctrl-break interrupt
+ */
+ static void interrupt
+#ifdef DJGPP
+catch_cbrk(int a)
+#else
+catch_cbrk(void)
+#endif
+{
+ cbrk_pressed = TRUE;
+ ctrlc_pressed = TRUE;
+}
+
+#ifndef DJGPP
+/*
+ * ctrl-break handler for DOS. Never called when a ctrl-break is typed, because
+ * we catch interrupt 1b. If you type ctrl-C while Vim is waiting for a
+ * character this function is not called. When a ctrl-C is typed while Vim is
+ * busy this function may be called. By that time a ^C has been displayed on
+ * the screen, so we have to redisplay the screen. We can't do that here,
+ * because we may be called by DOS. The redraw is in mch_inchar().
+ */
+ static int _cdecl
+cbrk_handler(void)
+{
+ delayed_redraw = TRUE;
+ return 1; /* resume operation after ctrl-break */
+}
+
+/*
+ * function for critical error interrupt
+ * For DOS 1 and 2 return 0 (Ignore).
+ * For DOS 3 and later return 3 (Fail)
+ */
+ static void interrupt
+catch_cint(bp, di, si, ds, es, dx, cx, bx, ax)
+ unsigned bp, di, si, ds, es, dx, cx, bx, ax;
+{
+ ax = (ax & 0xff00); /* set AL to 0 */
+ if (_osmajor >= 3)
+ ax |= 3; /* set AL to 3 */
+}
+#endif
+
+/*
+ * Set the interrupt vectors for use with Vim on or off.
+ * on == TRUE means as used within Vim
+ */
+ static void
+set_interrupts(int on)
+{
+ static int saved_cbrk;
+#ifndef DJGPP
+ static void interrupt (*old_cint)();
+#endif
+ static void interrupt (*old_cbrk)(INT_ARG);
+
+ if (on)
+ {
+ saved_cbrk = getcbrk(); /* save old ctrl-break setting */
+ setcbrk(0); /* do not check for ctrl-break */
+#ifdef DJGPP
+ old_cbrk = signal(SIGINT, catch_cbrk); /* critical error interrupt */
+#else
+ old_cint = getvect(0x24); /* save old critical error interrupt */
+ setvect(0x24, catch_cint); /* install our critical error interrupt */
+ old_cbrk = getvect(0x1B); /* save old ctrl-break interrupt */
+ setvect(0x1B, catch_cbrk); /* install our ctrl-break interrupt */
+ ctrlbrk(cbrk_handler); /* vim's ctrl-break handler */
+#endif
+ if (term_console)
+ out_str(T_ME); /* set colors */
+ }
+ else
+ {
+ setcbrk(saved_cbrk); /* restore ctrl-break setting */
+#ifdef DJGPP
+ signal(SIGINT,old_cbrk); /* critical error interrupt */
+#else
+ setvect(0x24, old_cint); /* restore critical error interrupt */
+ setvect(0x1B, old_cbrk); /* restore ctrl-break interrupt */
+#endif
+ /* restore ctrl-break handler, how ??? */
+ if (term_console)
+ mynormvideo(); /* restore screen colors */
+ }
+}
+
+/*
+ * We have no job control, fake it by starting a new shell.
+ */
+ void
+mch_suspend(void)
+{
+ suspend_shell();
+}
+
+extern int _fmode;
+
+/*
+ * Prepare window for use by Vim.
+ */
+ void
+mch_init(void)
+{
+ union REGS regs;
+
+#if defined(DJGPP) && defined(FEAT_CLIPBOARD)
+ __dpmi_regs dpmi_regs;
+#endif
+
+ /*
+ * Get the video attributes at the cursor. These will be used as the
+ * default attributes.
+ */
+ regs.h.ah = 0x08;
+ regs.h.bh = 0x00; /* video page 0 */
+ int86(0x10, &regs, &regs);
+ orig_attr = regs.h.ah;
+ mynormvideo();
+ if (cterm_normal_fg_color == 0)
+ cterm_normal_fg_color = (orig_attr & 0xf) + 1;
+ if (cterm_normal_bg_color == 0)
+ cterm_normal_bg_color = ((orig_attr >> 4) & 0xf) + 1;
+
+ term_console = TRUE; /* assume using the console for the things here */
+ _fmode = O_BINARY; /* we do our own CR-LF translation */
+ out_flush();
+ set_interrupts(TRUE); /* catch interrupts */
+
+#ifdef DJGPP
+ /*
+ * Use Long File Names by default, if $LFN not set.
+ */
+ if (getenv("LFN") == NULL)
+ putenv("LFN=y");
+
+ get_screenbase();
+#endif
+
+#ifdef FEAT_MOUSE
+/* find out if a MS compatible mouse is available */
+ regs.x.ax = 0;
+ (void)int86(0x33, &regs, &regs);
+ mouse_avail = regs.x.ax;
+ /* best guess for mouse coordinate computations */
+ mch_get_shellsize();
+ if (Columns <= 40)
+ mouse_x_div = 16;
+ if (Rows == 30)
+ mouse_y_div = 16;
+#endif
+
+ /*
+ * Try switching to 16 colors for background, instead of 8 colors and
+ * blinking. Does this always work? Can the old value be restored?
+ */
+ regs.x.ax = 0x1003;
+ regs.h.bl = 0x00;
+ regs.h.bh = 0x00;
+ int86(0x10, &regs, &regs);
+
+ /*
+ * Test if we have an enhanced AT keyboard. Write 0xFFFF to the keyboard
+ * buffer and try to read it back. If we can't in 16 tries, it's an old
+ * type XT keyboard.
+ */
+ regs.h.ah = 0x05;
+ regs.x.cx = 0xffff;
+ int86(0x16, &regs, &regs);
+ if (regs.h.al != 1) /* skip this when keyboard buffer is full */
+ {
+ int i;
+
+ for (i = 0; i < 16; ++i)
+ {
+ regs.h.ah = 0x10;
+ int86(0x16, &regs, &regs);
+ if (regs.x.ax == 0xffff)
+ break;
+ }
+ if (i == 16) /* 0xffff not read, must be old keyboard */
+ {
+ bioskey_read = 0;
+ bioskey_ready = 1;
+ }
+ }
+
+#ifdef MCH_CURSOR_SHAPE
+ /* Save the old cursor shape */
+ mch_restore_cursor_shape(FALSE);
+ /* Initialise the cursor shape */
+ mch_update_cursor();
+#endif
+
+#if defined(DJGPP) && defined(FEAT_CLIPBOARD)
+ /*
+ * Check to see if the Windows clipboard is available, ie. are we
+ * running from a DOS session within Windows. Obviously, the Windows
+ * clipboard will not be available if we're running under pure DOS.
+ *
+ * int 0x2f, AX = 0x1700 identifies the Windows version we're running
+ * under. Upon return from the interrupt, if AX is unchanged, we're
+ * running under pure DOS and no Windows clipboard is available.
+ *
+ * Remark: could use int86() here but __dpmi_int() is recommended in
+ * the DJGPP docs, since int86() doesn't cover all available interrupts.
+ */
+ dpmi_regs.x.ax = 0x1700;
+ if (__dpmi_int(0x2f, &dpmi_regs) == -1)
+ /* real-mode interrupt failed? */
+ dpmi_regs.x.ax = 0x1700; /* force failure */
+
+ if (dpmi_regs.x.ax == 0x1700) /* no change in AX? */
+ clip_init(FALSE); /* no clipboard available, too bad */
+ else /* else, running under Windows, OK */
+ clip_init(TRUE); /* clipboard is available */
+#endif
+}
+
+ int
+mch_check_win(
+ int argc,
+ char **argv)
+{
+ /* store argv[0], may be used for $VIM */
+ if (*argv[0] != NUL)
+ exe_name = FullName_save((char_u *)argv[0], FALSE);
+
+ /*
+ * Try the DOS search path. The executable may in
+ * fact be called differently, so try this last.
+ */
+ if (exe_name == NULL || *exe_name == NUL)
+ exe_name = searchpath("vim.exe");
+
+ if (isatty(1))
+ return OK;
+ return FAIL;
+}
+
+/*
+ * Return TRUE if the input comes from a terminal, FALSE otherwise.
+ */
+ int
+mch_input_isatty(void)
+{
+ if (isatty(read_cmd_fd))
+ return TRUE;
+ return FALSE;
+}
+
+#if defined(USE_FNAME_CASE) || defined(PROTO)
+/*
+ * fname_case(): Set the case of the file name, if it already exists.
+ * TODO: should expand short to long file names. Need to use DOS interrupts,
+ * see DJGPP sources libc/dos/dir/findfirs.c.
+ */
+ void
+fname_case(char_u *name, int len)
+{
+ char_u *tail;
+ struct ffblk fb;
+
+ slash_adjust(name);
+ if (findfirst(name, &fb, 0) == 0)
+ {
+ tail = gettail(name);
+ if (len == 0 ? STRLEN(tail) == STRLEN(fb.ff_name)
+ : (tail - name) + STRLEN(fb.ff_name) < len)
+ STRCPY(tail, fb.ff_name);
+ }
+}
+#endif
+
+/*
+ * return process ID
+ */
+ long
+mch_get_pid(void)
+{
+ return (long)0;
+}
+
+/*
+ * Change default drive (just like _chdrive of Borland C 3.1)
+ */
+ static int
+change_drive(int drive)
+{
+ union REGS regs;
+
+ regs.h.ah = 0x0e;
+ regs.h.dl = drive - 1;
+ intdos(&regs, &regs); /* set default drive */
+ regs.h.ah = 0x19;
+ intdos(&regs, &regs); /* get default drive */
+ if (regs.h.al == drive - 1)
+ return 0;
+ return -1;
+}
+
+/*
+ * Get absolute file name into buffer 'buf' of length 'len' bytes.
+ * All slashes are replaced with backslashes, to avoid trouble when comparing
+ * file names. When 'shellslash' set do it the other way around.
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+mch_FullName(
+ char_u *fname,
+ char_u *buf,
+ int len,
+ int force)
+{
+ if (!force && mch_isFullName(fname)) /* already expanded */
+ {
+ STRNCPY(buf, fname, len);
+ buf[len - 1] = NUL;
+ slash_adjust(buf);
+ return OK;
+ }
+
+#ifdef __BORLANDC__ /* Only Borland C++ has this */
+ if (_fullpath((char *)buf, (char *)fname, len - 1) == NULL)
+ return FAIL;
+ return OK;
+#else /* almost the same as mch_FullName() in os_unix.c */
+ {
+# if 1
+ char_u fullpath[MAXPATHL];
+
+ if (!_truename(fname, fullpath))
+ return FAIL;
+ slash_adjust(fullpath); /* Only needed when 'shellslash' set */
+ STRNCPY(buf, fullpath, len);
+ buf[len - 1] = NUL;
+ return OK;
+
+# else /* Old code, to be deleted... */
+ int l;
+ char_u olddir[MAXPATHL];
+ char_u *p, *q;
+ int c;
+ int retval = OK;
+
+ *buf = 0;
+ /*
+ * change to the directory for a moment,
+ * and then do the getwd() (and get back to where we were).
+ * This will get the correct path name with "../" things.
+ */
+ p = vim_strrchr(fname, '/');
+ q = vim_strrchr(fname, '\\');
+ if (q != NULL && (p == NULL || q > p))
+ p = q;
+ q = vim_strrchr(fname, ':');
+ if (q != NULL && (p == NULL || q > p))
+ p = q;
+ if (p != NULL)
+ {
+ if (getcwd(olddir, MAXPATHL) == NULL)
+ {
+ p = NULL; /* can't get current dir: don't chdir */
+ retval = FAIL;
+ }
+ else
+ {
+ if (p == fname) /* /fname */
+ q = p + 1; /* -> / */
+ else if (q + 1 == p) /* ... c:\foo */
+ q = p + 1; /* -> c:\ */
+ else /* but c:\foo\bar */
+ q = p; /* -> c:\foo */
+
+ c = *q; /* truncate at start of fname */
+ *q = NUL;
+# ifdef DJGPP
+ STRCPY(buf, fname);
+ slash_adjust(buf); /* needed when fname starts with \ */
+ if (mch_chdir(buf)) /* change to the directory */
+# else
+ if (mch_chdir(fname)) /* change to the directory */
+# endif
+ retval = FAIL;
+ else
+ {
+ fname = q;
+ if (c == psepc) /* if we cut the name at a */
+ fname++; /* '\', don't add it again */
+ }
+ *q = c;
+ }
+ }
+ if (getcwd(buf, len) == NULL)
+ {
+ retval = FAIL;
+ *buf = NUL;
+ }
+# ifdef USE_FNAME_CASE
+ else
+ {
+ char_u *head;
+ char_u *tail;
+ struct ffblk fb;
+ int c;
+ int added;
+
+ /* Apparently "longna~1" isn't expanded by getcwd(), at least not
+ * for DJGPP. Expand it here. Have to do each dirname
+ * separately. */
+ slash_adjust(buf);
+ head = buf;
+ if (isalpha(*head) && head[1] == ':')
+ head += 2; /* skip "c:" */
+ while (*head != NUL)
+ {
+ /* Advance "head" to the start of a dirname and "tail" to just
+ * after it. */
+ while (*head == '/' || *head == '\\')
+ ++head;
+ for (tail = head; *tail != NUL; ++tail)
+ if (*tail == '/' || *tail == '\\')
+ break;
+ c = *tail;
+ *tail = NUL;
+
+ if (findfirst(buf, &fb, FA_DIREC) == 0)
+ {
+ added = STRLEN(fb.ff_name);
+ if ((head - buf) + added + STRLEN(tail + 1) + 2 < len)
+ {
+ added -= (tail - head);
+ if (added != 0)
+ mch_memmove(tail + 1 + added, tail + 1,
+ STRLEN(tail + 1) + 1);
+ STRCPY(head, fb.ff_name);
+ tail += added;
+ }
+ }
+ *tail = c;
+ head = tail;
+ }
+ }
+# endif
+ if (p != NULL)
+ mch_chdir(olddir);
+ /*
+ * Concatenate the file name to the path.
+ */
+ if (*fname != NUL)
+ {
+ l = STRLEN(buf);
+ if (l > 0 && buf[l - 1] != '/' && buf[l - 1] != '\\')
+ strcat(buf, pseps);
+ strcat(buf, fname);
+ }
+ return retval;
+# endif
+ }
+#endif
+}
+
+/*
+ * Replace all slashes by backslashes.
+ * This used to be the other way around, but MS-DOS sometimes has problems
+ * with slashes (e.g. in a command name). We can't have mixed slashes and
+ * backslashes, because comparing file names will not work correctly. The
+ * commands that use a file name should try to avoid the need to type a
+ * backslash twice.
+ * When 'shellslash' set do it the other way around.
+ */
+ void
+slash_adjust(char_u *p)
+{
+#ifdef OLD_DJGPP /* this seems to have been fixed in DJGPP 2.01 */
+ /* DJGPP can't handle a file name that starts with a backslash, and when it
+ * starts with a slash there should be no backslashes */
+ if (*p == '\\' || *p == '/')
+ while (*p)
+ {
+ if (*p == '\\')
+ *p = '/';
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p);
+ else
+#endif
+ ++p;
+ }
+ else
+#endif
+ while (*p)
+ {
+ if (*p == psepcN)
+ *p = psepc;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p);
+ else
+#endif
+ ++p;
+ }
+}
+
+/*
+ * Return TRUE if "fname" does not depend on the current directory.
+ */
+ int
+mch_isFullName(char_u *fname)
+{
+ /* A name like "d:/foo" and "//server/share" is absolute */
+ return (fname[0] != NUL && fname[1] == ':'
+ && (fname[2] == '/' || fname[2] == '\\'))
+ || (fname[0] == fname[1] && (fname[0] == '/' || fname[0] == '\\'));
+}
+
+
+ void
+mch_early_init(void)
+{
+}
+
+/*
+ * Careful: mch_exit() may be called before mch_init()!
+ */
+ void
+mch_exit(int r)
+{
+ settmode(TMODE_COOK);
+ stoptermcap();
+ set_interrupts(FALSE); /* restore interrupts */
+#ifdef DJGPP
+ set_sys_cursor();
+#endif
+ /* Somehow outputting CR-NL causes the original colors to be restored */
+ out_char('\r');
+ out_char('\n');
+ out_flush();
+ ml_close_all(TRUE); /* remove all memfiles */
+#ifdef MCH_CURSOR_SHAPE
+ mch_restore_cursor_shape(TRUE);
+#endif
+ exit(r);
+}
+
+/*
+ * set the tty in (raw) ? "raw" : "cooked" mode
+ * Does not change the tty, as bioskey() and kbhit() work raw all the time.
+ */
+ void
+mch_settmode(int tmode)
+{
+}
+
+#ifdef FEAT_MOUSE
+ void
+mch_setmouse(int on)
+{
+ mouse_active = on;
+ mouse_hidden = TRUE; /* dont show it until moved */
+}
+#endif
+
+/*
+ * set screen mode
+ * return FAIL for failure, OK otherwise
+ */
+ int
+mch_screenmode(char_u *arg)
+{
+ int mode;
+ int i;
+ static char *(names[]) = {"BW40", "C40", "BW80", "C80", "MONO", "C4350"};
+ static int modes[] = { BW40, C40, BW80, C80, MONO, C4350};
+
+ mode = -1;
+ if (VIM_ISDIGIT(*arg)) /* mode number given */
+ mode = atoi((char *)arg);
+ else
+ {
+ for (i = 0; i < sizeof(names) / sizeof(char_u *); ++i)
+ if (stricmp(names[i], (char *)arg) == 0)
+ {
+ mode = modes[i];
+ break;
+ }
+ }
+ if (mode == -1)
+ {
+ EMSG("E362: Unsupported screen mode");
+ return FAIL;
+ }
+ textmode(mode); /* use Borland function */
+#ifdef DJGPP
+ /* base address may have changed */
+ get_screenbase();
+#endif
+
+ /* Screen colors may have changed. */
+ out_str(T_ME);
+
+#ifdef FEAT_MOUSE
+ if (mode <= 1 || mode == 4 || mode == 5 || mode == 13 || mode == 0x13)
+ mouse_x_div = 16;
+ else
+ mouse_x_div = 8;
+ if (mode == 0x11 || mode == 0x12)
+ mouse_y_div = 16;
+ else if (mode == 0x10)
+ mouse_y_div = 14;
+ else
+ mouse_y_div = 8;
+ shell_resized();
+#endif
+ return OK;
+}
+
+/*
+ * Structure used by Turbo-C/Borland-C to store video parameters.
+ */
+#ifndef DJGPP
+extern struct text_info _video;
+#endif
+
+/*
+ * try to get the real window size
+ * return FAIL for failure, OK otherwise
+ */
+ int
+mch_get_shellsize(void)
+{
+ struct text_info textinfo;
+
+ /*
+ * The screenwidth is returned by the BIOS OK.
+ * The screenheight is in a location in the bios RAM, if the display is
+ * EGA or VGA.
+ */
+ if (!term_console)
+ return FAIL;
+ gettextinfo(&textinfo);
+ Columns = textinfo.screenwidth;
+ Rows = textinfo.screenheight;
+#ifndef DJGPP
+ if (textinfo.currmode > 10)
+ Rows = *(char far *)MK_FP(0x40, 0x84) + 1;
+#endif
+
+ if (Columns < MIN_COLUMNS || Rows < MIN_LINES)
+ {
+ /* these values are overwritten by termcap size or default */
+ Columns = 80;
+ Rows = 25;
+ return FAIL;
+ }
+#ifdef DJGPP
+ mytextinit(&textinfo); /* Added by JML, 1/15/98 */
+#endif
+
+ return OK;
+}
+
+/*
+ * Set the active window for delline/insline.
+ */
+ static void
+set_window(void)
+{
+ if (term_console)
+ {
+#ifndef DJGPP
+ _video.screenheight = Rows;
+#endif
+ mywindow(1, 1, Columns, Rows);
+ }
+ screen_start();
+}
+
+ void
+mch_set_shellsize(void)
+{
+ /* Should try to set the window size to Rows and Columns.
+ * May involve switching display mode....
+ * We assume the user knows the size and just use it. */
+}
+
+/*
+ * Rows and/or Columns has changed.
+ */
+ void
+mch_new_shellsize()
+{
+#ifdef FEAT_MOUSE
+ /* best guess for mouse coordinate computations */
+ if (Columns <= 40)
+ mouse_x_div = 16;
+ if (Rows == 30)
+ mouse_y_div = 16;
+#endif
+ set_window();
+#ifdef FEAT_MOUSE
+ mouse_area(); /* set area where mouse can go */
+#endif
+}
+
+#if defined(DJGPP) || defined(PROTO)
+/*
+ * Check the number of Columns with a BIOS call. This avoids a crash of the
+ * DOS console when 'columns' is set to a too large value.
+ */
+ void
+mch_check_columns()
+{
+ static union REGS regs;
+
+ regs.h.ah = 0x0f;
+ (void)int86(0x10, &regs, &regs);
+ if ((unsigned)Columns > (unsigned)regs.h.ah)
+ Columns = (unsigned)regs.h.ah;
+}
+#endif
+
+/*
+ * call shell, return FAIL for failure, OK otherwise
+ * options: SHELL_*, see vim.h.
+ */
+ int
+mch_call_shell(
+ char_u *cmd,
+ int options)
+{
+ int x;
+ int tmode = cur_tmode;
+#ifndef DJGPP
+ char_u *newcmd;
+#endif
+
+ out_flush();
+#ifdef DJGPP
+ set_sys_cursor();
+#endif
+
+ if (options & SHELL_COOKED)
+ settmode(TMODE_COOK); /* set to normal mode */
+ set_interrupts(FALSE); /* restore interrupts */
+
+#ifdef DJGPP
+ /* ignore signals while external command is running */
+ signal(SIGINT, SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+#endif
+ if (cmd == NULL)
+ x = system((char *)p_sh);
+ else
+ {
+#ifdef DJGPP
+ /*
+ * Use 'shell' for system().
+ */
+ setenv("SHELL", (char *)p_sh, 1);
+ x = system(cmd);
+#else
+ /* we use "command" to start the shell, slow but easy */
+ newcmd = alloc(STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 3);
+ if (newcmd == NULL)
+ x = -1;
+ else
+ {
+ sprintf((char *)newcmd, "%s %s %s", p_sh, p_shcf, cmd);
+ x = system((char *)newcmd);
+ vim_free(newcmd);
+ }
+#endif
+ }
+#ifdef DJGPP
+ signal(SIGINT, SIG_DFL);
+ signal(SIGHUP, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+#endif
+ if (tmode == TMODE_RAW)
+ settmode(TMODE_RAW); /* set to raw mode */
+ set_interrupts(TRUE); /* catch interrupts */
+
+ if (x && !(options & SHELL_SILENT) && !emsg_silent)
+ {
+ MSG_PUTS("\nshell returned ");
+ msg_outnum((long)x);
+ msg_putchar('\n');
+ }
+
+ return x;
+}
+
+/*
+ * check for an "interrupt signal": CTRL-break or CTRL-C
+ */
+ void
+mch_breakcheck(void)
+{
+ if (ctrlc_pressed)
+ {
+ ctrlc_pressed = FALSE;
+ got_int = TRUE;
+ }
+}
+
+/*
+ * Return TRUE if "p" contain a wildcard that can be expanded by
+ * dos_expandpath().
+ */
+ int
+mch_has_exp_wildcard(char_u *p)
+{
+ for ( ; *p; ++p)
+ {
+ if (vim_strchr((char_u *)"?*[", *p) != NULL
+ || (*p == '~' && p[1] != NUL))
+ return TRUE;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ return FALSE;
+}
+
+/*
+ * Return TRUE if "p" contain a wildcard or a "~1" kind of thing (could be a
+ * shortened file name).
+ */
+ int
+mch_has_wildcard(char_u *p)
+{
+ for ( ; *p; ++p)
+ {
+ if (vim_strchr((char_u *)
+# ifdef VIM_BACKTICK
+ "?*$[`"
+# else
+ "?*$["
+# endif
+ , *p) != NULL
+ || (*p == '~' && p[1] != NUL))
+ return TRUE;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ return FALSE;
+}
+
+/*
+ * Change directory to "path".
+ * The normal chdir() does not change the default drive. This one does.
+ * Return 0 for success, -1 for failure.
+ */
+ int
+mch_chdir(char *path)
+{
+ if (path[0] == NUL) /* just checking... */
+ return 0;
+ if (path[1] == ':') /* has a drive name */
+ {
+ if (change_drive(TOLOWER_ASC(path[0]) - 'a' + 1))
+ return -1; /* invalid drive name */
+ path += 2;
+ }
+ if (*path == NUL) /* drive name only */
+ return 0;
+ return chdir(path); /* let the normal chdir() do the rest */
+}
+
+#ifdef DJGPP
+/*
+ * mch_rename() works around a bug in rename (aka MoveFile) in
+ * Windows 95: rename("foo.bar", "foo.bar~") will generate a
+ * file whose short file name is "FOO.BAR" (its long file name will
+ * be correct: "foo.bar~"). Because a file can be accessed by
+ * either its SFN or its LFN, "foo.bar" has effectively been
+ * renamed to "foo.bar", which is not at all what was wanted. This
+ * seems to happen only when renaming files with three-character
+ * extensions by appending a suffix that does not include ".".
+ * Windows NT gets it right, however, with an SFN of "FOO~1.BAR".
+ * This works like mch_rename in os_win32.c, but is a bit simpler.
+ *
+ * Like rename(), returns 0 upon success, non-zero upon failure.
+ * Should probably set errno appropriately when errors occur.
+ */
+
+ int
+mch_rename(const char *OldFile, const char *NewFile)
+{
+ char_u *TempFile;
+ int retval;
+ int fd;
+
+ /* rename() works correctly without long file names, so use that */
+ if (!_USE_LFN)
+ return rename(OldFile, NewFile);
+
+ if ((TempFile = alloc((unsigned)(STRLEN(OldFile) + 13))) == NULL)
+ return -1;
+
+ STRCPY(TempFile, OldFile);
+ STRCPY(gettail(TempFile), "axlqwqhy.ba~");
+ if (rename(OldFile, TempFile))
+ retval = -1;
+ else
+ {
+ /* now create an empty file called OldFile; this prevents
+ * the operating system using OldFile as an alias (SFN)
+ * if we're renaming within the same directory. For example,
+ * we're editing a file called filename.asc.txt by its SFN,
+ * filena~1.txt. If we rename filena~1.txt to filena~1.txt~
+ * (i.e., we're making a backup while writing it), the SFN
+ * for filena~1.txt~ will be filena~1.txt, by default, which
+ * will cause all sorts of problems later in buf_write. So, we
+ * create an empty file called filena~1.txt and the system will have
+ * to find some other SFN for filena~1.txt~, such as filena~2.txt
+ */
+ if ((fd = open(OldFile, O_RDWR|O_CREAT|O_EXCL, 0444)) < 0)
+ return -1;
+ retval = rename(TempFile, NewFile);
+ close(fd);
+ mch_remove((char_u *)OldFile);
+
+ /* If renaming to NewFile failed, rename TempFile back to OldFile, so
+ * that it looks like nothing happened. */
+ if (retval)
+ rename(TempFile, OldFile);
+ }
+ vim_free(TempFile);
+
+ return retval; /* success */
+}
+#endif
+
+#if defined(DJGPP) || defined(PROTO)
+/*
+ * setlocale() for DJGPP with MS-DOS codepage support
+ * Author: Cyril Slobin <slobin@fe.msk.ru>
+ *
+ * Scaled down a lot for use by Vim: Only support setlocale(LC_ALL, "").
+ */
+
+#undef setlocale
+
+#include <go32.h>
+#include <inlines/ctype.ha>
+#include <locale.h>
+
+#define UPCASE (__dj_ISALNUM | __dj_ISALPHA | __dj_ISGRAPH | __dj_ISPRINT | __dj_ISUPPER)
+#define LOCASE (__dj_ISALNUM | __dj_ISALPHA | __dj_ISGRAPH | __dj_ISPRINT | __dj_ISLOWER)
+
+ char *
+djgpp_setlocale(void)
+{
+ __dpmi_regs regs;
+ struct { char id; unsigned short off, seg; } __attribute__ ((packed)) info;
+ unsigned char buffer[0x82], lower, upper;
+ int i;
+
+ regs.x.ax = 0x6502;
+ regs.x.bx = 0xffff;
+ regs.x.dx = 0xffff;
+ regs.x.cx = 5;
+ regs.x.es = __tb >> 4;
+ regs.x.di = __tb & 0xf;
+
+ __dpmi_int(0x21, &regs);
+
+ if (regs.x.flags & 1)
+ return NULL;
+
+ dosmemget(__tb, 5, &info);
+ dosmemget((info.seg << 4) + info.off, 0x82, buffer);
+
+ if (*(short *)buffer != 0x80)
+ return NULL;
+
+ /* Fix problem of underscores being replaced with y-umlaut. (Levin) */
+ if (buffer[26] == 0x5f)
+ buffer[26] = 0x98;
+
+ for (i = 0; i < 0x80; i++)
+ {
+ lower = i + 0x80;
+ upper = (buffer+2)[i];
+ if (lower != upper)
+ {
+ __dj_ctype_flags[lower+1] = LOCASE;
+ __dj_ctype_toupper[lower+1] = upper;
+ if (__dj_ctype_flags[upper+1] == 0)
+ __dj_ctype_flags[upper+1] = UPCASE;
+ if (__dj_ctype_tolower[upper+1] == upper)
+ __dj_ctype_tolower[upper+1] = lower;
+ }
+ }
+
+ return "C";
+}
+
+#if defined(FEAT_CLIPBOARD) || defined(PROTO)
+
+/*
+ * Clipboard stuff, for cutting and pasting text to other windows.
+ *
+ * Implementation of DOS/Windows clipboard data transfer
+ * by David Kotchan (dkotchan@sympatico.ca)
+ */
+
+#define CF_TEXT 0x01 /* Windows clipboard format: Windows (ANSI) text */
+#define CF_OEMTEXT 0x07 /* Windows clipboard format: OEM (DOS) text */
+#define CF_VIMCLIP 0x04 /* trick: SYLK clipboard format for VimClipboard */
+
+static int Win16OpenClipboard(void);
+static int Win16CloseClipboard(void);
+static int Win16EmptyClipboard(void);
+static char_u *Win16GetClipboardData(int clip_data_format);
+static int Win16SetClipboardData(int clip_data_format, char_u *clip_data, int clip_data_size, int clip_data_type);
+
+/*
+ * Make vim the owner of the current selection. Return OK upon success.
+ */
+ int
+clip_mch_own_selection(VimClipboard *cbd)
+{
+ /*
+ * Never actually own the clipboard. If another application sets the
+ * clipboard, we don't want to think that we still own it.
+ */
+ return FAIL;
+}
+
+/*
+ * Make vim NOT the owner of the current selection.
+ */
+ void
+clip_mch_lose_selection(VimClipboard *cbd)
+{
+ /* Nothing needs to be done here */
+}
+
+/*
+ * Read the Windows clipboard text and put it in Vim's clipboard register.
+ */
+ void
+clip_mch_request_selection(VimClipboard *cbd)
+{
+ int type = MCHAR;
+ char_u *pAllocated = NULL;
+ char_u *pClipText = NULL;
+ int clip_data_format = 0;
+
+ if (Win16OpenClipboard())
+ {
+ /* Check for Vim's own clipboard format first. The CF_VIMCLIP format
+ * is just ordinary text (like CF_TEXT) except prepended by the
+ * selection type (as a single character). Note that under DOS we
+ * actually cannot define a custom CF_VIMCLIP clipboard format; we
+ * use instead one of the existing Windows-defined formats, usually
+ * "DIF" or "SYLK". See Win16GetClipboardData() for details.
+ *
+ * Note that Win16GetClipboardData() returns the address of the memory
+ * block it allocated. This is not necessary the start of the
+ * clipboard text data: there may be other bytes ahead of the
+ * text (particularly for CF_VIMCLIP) which are used for data
+ * management. So pClipText is not necessarily == pAllocated.
+ */
+
+ if ((pAllocated = Win16GetClipboardData(CF_VIMCLIP)) != NULL)
+ {
+ clip_data_format = CF_VIMCLIP;
+ pClipText = pAllocated;
+
+ switch (*pClipText++) /* after ++, pClipText points to text */
+ {
+ default:
+ case 'L': type = MLINE; break;
+ case 'C': type = MCHAR; break;
+#ifdef FEAT_VISUAL
+ case 'B': type = MBLOCK; break;
+#endif
+ }
+ }
+
+ /* Otherwise, check for the normal Windows text formats. There are
+ * two of these: CF_TEXT (common) and CF_OEMTEXT (used for DOS
+ * compatibility). Experiments show that, under the DOS/Windows
+ * clipboard interface, writing CF_TEXT data to the clipboard
+ * automatically creates a CF_OEMTEXT format as well.
+ */
+
+ else if ((pAllocated = Win16GetClipboardData(CF_TEXT)) != NULL)
+ {
+ clip_data_format = CF_TEXT;
+ pClipText = pAllocated;
+ type = (vim_strchr((char*)pClipText, '\r') != NULL) ? MLINE : MCHAR;
+ }
+
+ else if ((pAllocated = Win16GetClipboardData(CF_OEMTEXT)) != NULL)
+ {
+ clip_data_format = CF_OEMTEXT;
+ pClipText = pAllocated;
+ type = (vim_strchr((char*)pClipText, '\r') != NULL) ? MLINE : MCHAR;
+ }
+
+ /* Did we get anything? */
+
+ if (pClipText != NULL)
+ {
+ char_u *pDest;
+ char_u *pStart;
+ char_u *pEnd;
+
+ long_u clip_data_size = 0;
+
+ /* The Windows clipboard normally stores its text lines terminated
+ * by <CR><NL>. But Vim uses only <NL>, so translate the <CR><NL>
+ * into <NL>. Also, watch for possible null bytes at the end of
+ * pClipText. These are padding added by "get_clipboard_data"
+ * (int 0x2f, AX= 0x1705) in order to round the data size up to the
+ * next multiple of 32 bytes. See Win16GetClipboardData() for
+ * details.
+ */
+
+ pDest = strstr( pClipText, "\r\n" ); /* find first <CR><NL> */
+
+ if (pDest != NULL) /* found one? */
+ {
+ pStart = pDest + 1; /* points to <NL> after <CR> */
+ pEnd = strstr( pStart, "\r\n" );/* find next <CR><NL> */
+
+ while (pEnd != NULL) /* found one? */
+ {
+ memmove(pDest, pStart, (long)(pEnd - pStart));
+ /* exclude <CR> */
+ pDest += (long)(pEnd - pStart); /* new destination */
+ pStart = pEnd + 1; /* new starting point */
+ pEnd = strstr(pStart, "\r\n"); /* find next <CR><NL> */
+ }
+
+ /* Fell out of while() loop: no more <CR><NL> pairs. Just copy
+ * the rest of the data, up to the first null byte. */
+ pEnd = strchr(pStart, '\0'); /* find first null */
+
+ memmove(pDest, pStart, (long)(pEnd - pStart)); /* exclude nul */
+ pDest += (long)(pEnd - pStart);
+ *pDest = '\0'; /* terminate */
+
+ /* Now that all <CR><NL> pairs have been "compressed" into just
+ * <NL>'s, determine the true text length. */
+ clip_data_size = (long_u)(pDest - pClipText);
+ }
+ else
+ {
+ /* no <CR><NL> pairs at all */
+ /* Since the data may have been padded with trailing nulls,
+ * determine the true string length. */
+ clip_data_size = STRLEN(pClipText); /* true data length */
+ }
+
+ /* Copy the cleaned-up data over to Vim's clipboard "*" register. */
+ clip_yank_selection(type, pClipText, clip_data_size, cbd);
+
+ /* Free the memory that Win16GetClipboardData() allocated. */
+ vim_free(pAllocated);
+ }
+
+ Win16CloseClipboard();
+
+ } // end if (Win16OpenClipboard())
+}
+
+/*
+ * Send the currently selected Vim text to the Windows clipboard.
+ */
+ void
+clip_mch_set_selection( VimClipboard *cbd )
+{
+ char_u *pClipData = NULL;
+ long_u clip_data_size;
+ int clip_data_type;
+
+ /* If the '*' register isn't already filled in, fill it in now. */
+ cbd->owned = TRUE;
+ clip_get_selection(cbd);
+ cbd->owned = FALSE;
+
+ /*
+ * clip_convert_selection() returns a pointer to a buffer containing
+ * the text to send to the Windows clipboard, together with a count
+ * of the number of characters (bytes) in the buffer. The function's
+ * return value is the 'type' of selection: MLINE, MCHAR, or MBLOCK;
+ * or -1 for failure.
+ */
+ clip_data_type = clip_convert_selection(&pClipData, &clip_data_size, cbd);
+
+ if (clip_data_type < 0) /* could not convert? */
+ return; /* early exit */
+
+ if (Win16OpenClipboard())
+ {
+ if (Win16EmptyClipboard())
+ {
+ int sentOK;
+
+ sentOK = Win16SetClipboardData(CF_TEXT, pClipData,
+ clip_data_size, clip_data_type);
+ sentOK = Win16SetClipboardData(CF_VIMCLIP,
+ pClipData, clip_data_size, clip_data_type) && sentOK;
+
+ if (!sentOK)
+ {
+ /* one or both of Win16SetClipboardData() failed. */
+ /* Technically we don't know why Win16SetClipboardData()
+ * failed, but almost always it will be because there wasn't
+ * enough DOS memory to bufer the data, so report that as the
+ * problem.
+ *
+ * We report the error here (instead of in
+ * Win16SetClipboardData()) because we don't want the error
+ * reported twice.
+ */
+ EMSG("E450: Selection too large, cannot allocate DOS buffer");
+ }
+ }
+
+ Win16CloseClipboard();
+ }
+
+ /* release memory allocated by clip_convert_selection() */
+ vim_free(pClipData);
+
+ return;
+}
+
+/*
+ * Win16OpenClipboard: open the Windows clipboard. The clipboard must be open
+ * before it can be communicated with at all. Return TRUE on success,
+ * FALSE on failure.
+ */
+ static int
+Win16OpenClipboard(void)
+{
+ __dpmi_regs dpmi_regs;
+
+ long start_time;
+ int tick_count;
+
+ /* int 02xf, AX = 0x1701 attempts to open the Windows clipboard. Upon
+ * return from the interrupt, if AX is non-zero, the clipboard was
+ * successfully opened. If AX is zero, the clipboard could not be opened
+ * because it is currently in use by another process.
+ *
+ * Remark: other DOS programs I (dk) have written that use the Windows
+ * clipboard sometimes encounter the problem that the clipboard cannot
+ * be opened even though it is demonstrably not in use by any other
+ * process. In all cases, repeated attempts to open the clipboard
+ * eventually succeed, but the initial attempt occasionally fails.
+ *
+ * The problem is intermittent and appears to be related to DOS being
+ * "busy" at certain unpredictable times. DOS maintains two internal
+ * flags that indicate whether it's busy: InDOS and CritErr. The
+ * location of InDOS can be found by calling int 0x21, AH = 0x34. The
+ * location of CritErr can be found by calling int 0x21, AX = 0x5d06.
+ * If either of these flags is set, DOS is "busy" and cannot be
+ * interrupted. See "Undocumented DOS" by Schulman et al for details.
+ *
+ * However here I take the easier approach that if the first call to open
+ * the clipboard does not succeed, just try again. In fact, try once per
+ * biostime() clock tick, up to 18 times (about one second).
+ */
+
+ tick_count = 0;
+
+ dpmi_regs.x.ax = 0x1701; /* open Windows clipboard */
+ if (__dpmi_int(0x2f, &dpmi_regs) == -1)
+ {
+ /* real-mode interrupt failed? */
+ return FALSE; /* FALSE --> clipboard not open */
+ }
+
+ /* wait up to one second */
+ while (dpmi_regs.x.ax == 0 && tick_count++ < 18)
+ {
+ /* Wait one clock tick (18.2 ticks/sec = 55 msec per tick).
+ *
+ * We busy-wait here. Unfortunately, delay() and usleep() have been
+ * reported to give problems with the original Windows 95. This is
+ * fixed in service pack 1, but not everybody installed that.
+ */
+ start_time = biostime(0, 0L);
+ while (biostime(0, 0L) == start_time)
+ ;
+
+ dpmi_regs.x.ax = 0x1701; /* open Windows clipboard */
+ if (__dpmi_int(0x2f, &dpmi_regs) == -1)
+ {
+ /* real-mode interrupt failed? */
+ return FALSE; /* FALSE --> clipboard not open */
+ }
+ }
+
+ /* Couldn't open the clipboard, even after 18 attempts? */
+
+ if (tick_count >= 18 && dpmi_regs.x.ax == 0)
+ return FALSE; /* FALSE --> clipboard not open */
+
+ return TRUE; /* TRUE --> clipboard opened successfully, OK */
+}
+
+/*
+ * Win16CloseClipboard: close the Windows clipboard. Return TRUE on
+ * success, FALSE on failure. This function can always be called,
+ * whether the clipboard is open or not.
+ */
+ static int
+Win16CloseClipboard(void)
+{
+ __dpmi_regs dpmi_regs;
+
+ /* Close the clipboard. This interrupt can always be called, even
+ * if the clipboard is already closed.
+ */
+
+ dpmi_regs.x.ax = 0x1708; /* close the clipboard */
+ if (__dpmi_int(0x2f, &dpmi_regs) == -1)
+ {
+ /* real-mode interrupt failed? */
+ return FALSE; /* FALSE --> clipboard could not be closed */
+ }
+
+ return TRUE; /* TRUE --> clipboard closed successfully, OK */
+}
+
+/*
+ * Win16EmptyClipboard: empty the (previously opened) Windows clipboard.
+ * Return TRUE on success, FALSE on failure.
+ */
+ static int
+Win16EmptyClipboard(void)
+{
+ __dpmi_regs dpmi_regs;
+
+ /* int 02xf, AX = 0x1702 attempts to empty the Windows clipboard. Upon
+ * return from the interrupt, if AX == 0, the clipboard could not be
+ * emptied (for some reason).
+ */
+ dpmi_regs.x.ax = 0x1702; /* empty the Windows clipboard */
+ if (__dpmi_int(0x2f, &dpmi_regs) == -1)
+ {
+ /* real-mode interrupt failed? */
+ return FALSE; /* FALSE --> clipboard could not be emptied */
+ }
+
+ /* Did we succeed in clearing the clipboard? */
+ if (dpmi_regs.x.ax == 0)
+ return FALSE; /* FALSE --> clipboard could not be emptied */
+
+ return TRUE; /* TRUE --> clipboard was emptied, OK */
+}
+
+/*
+ * FreeDOSMemory: a helper function to free memory previously
+ * allocated by a call to __dpmi_allocate_dos_memory().
+ */
+ static void
+FreeDOSMemory(int protected_mode_selector)
+{
+ /* Free the DOS buffer and release the DPMI prot-mode selector.
+ *
+ * It's important that DOS memory be properly released because
+ * there's only a limited amount of it. Therefore, if the call
+ * to __dpmi_free_dos_memory() fails, emit an error message
+ * unconditionally.
+ */
+ if (__dpmi_free_dos_memory(protected_mode_selector) == -1)
+ EMSG("E451: could not free DOS memory buffer (DJGPP)");
+}
+
+/*
+ * Win16GetClipboardData: query the Windows clipboard as to whether data
+ * is available in a particular clipboard format. If data is
+ * available, allocate a buffer for it and read the data from the
+ * clipboard into the buffer. Return a pointer to the buffer. If
+ * no data is available in the requested format, return NULL.
+ *
+ * This routine allocates memory to hold the retrieved clipboard
+ * data. It's the caller's responsibility to free this memory
+ * once it's finished using it. The memory should be freed by
+ * calling vim_free().
+ */
+ static char_u *
+Win16GetClipboardData(int clip_data_format)
+{
+ __dpmi_regs dpmi_regs;
+
+ int real_mode_segment_address;
+ int protected_mode_selector;
+
+ char_u *clip_data_buffer;
+ long_u clip_data_size;
+
+ /* We only handle clipboard formats we recognize, others are ignored.
+ *
+ * It's not possible to create a custom clipboard format for VimClipboard
+ * data under DOS, so one of the predefined Windows formats had to be
+ * used for CF_VIMCLIP. Two obscure formats, popular when Windows 3.0
+ * came out but no longer in much use today, are the DIF and SYLK formats.
+ * DIF is the Data Interchange Format, SYLK is the Symbolic Link format.
+ * They are both text formats and either one can be hijacked for use as
+ * "the VimClipboard format". Of course, this conflicts with anyone who
+ * still *is* using DIF or SYLK data formats, but that will be very few
+ * people.
+ *
+ * I (dk) chose SYLK as the more obscure format because it was used
+ * mostly for Microsoft Multiplan (the pre-cursor to Excel) and it's not
+ * likely Multiplan is used anywhere much anymore. Mind you, Excel can
+ * still export to both DIF and SYLK formats.
+ */
+
+ switch (clip_data_format)
+ {
+ case CF_VIMCLIP: /* Vim's own special clipboard format */
+ case CF_TEXT: /* Windows text */
+ case CF_OEMTEXT: /* DOS (OEM) text */
+
+ /* int 02xf, AX = 0x1704 returns the number of bytes of data currently
+ * on the Windows clipboard, for the specified format. Upon return
+ * from the interrupt, DX:AX = the number of bytes, rounded up to the
+ * nearest multiple of 32.
+ */
+
+ dpmi_regs.x.ax = 0x1704; /* get size of clipbd data */
+ dpmi_regs.x.dx = clip_data_format;
+ if (__dpmi_int(0x2f, &dpmi_regs) == -1)
+ {
+ /* real-mode interrupt failed? */
+ return NULL; /* early exit */
+ }
+
+ /* Did we get anything? If not, this is not an error. */
+ if (dpmi_regs.x.dx == 0 && dpmi_regs.x.ax == 0)
+ {
+ /* no CF_VIMCLIP data? */
+ return NULL; /* early exit */
+ }
+
+ /* There is data available in the requested clipboard format.
+ *
+ * Calculate data size. Remember this is rounded up to the nearest
+ * multiple of 32, so clip_data_size is actually an upper limit.
+ * The extra bytes, if any, are set to null (0x00) when the data is
+ * read from the clipboard. (Later:) actually I'm no longer sure
+ * this is strictly true: the end-of-data is marked by a null, but
+ * the extra bytes appear to sometimes be null, sometimes not.
+ * They may just be garbage.
+ */
+ clip_data_size = dpmi_regs.x.ax + (dpmi_regs.x.dx << 16);
+
+ /* Allocate memory to retrieve the data. The buffer has to lie in the
+ * DOS memory region (in the first 1 MByte of address space) because
+ * the Windows clipboard interface expects a 16-bit segment:offset
+ * pointer to a buffer address within the DOS region. Must therefore
+ * use __dpmi_allocate_dos_memory() instead of lalloc() or alloc().
+ */
+ real_mode_segment_address = __dpmi_allocate_dos_memory(
+ (clip_data_size + 15) >> 4, /* buffer size, in 16-byte paragraphs */
+ &protected_mode_selector); /* prot-mode selector for the address */
+
+ if (real_mode_segment_address == -1)
+ {
+ /* memory allocation failed. */
+
+ /* Technically we don't know why the allocation failed, but
+ * almost always it will be because there wasn't enough DOS
+ * memory to satisfy the request, so report that as the problem.
+ * On my system, DJGPP is able to satisfy a DOS allocation request
+ * up to about 600K in size. This depends on your HIMEM.SYS and
+ * EMM386.EXE settings however.
+ */
+ EMSG("E452: Clipboard data too large, cannot allocate DOS buffer");
+ return NULL; /* early exit */
+ }
+
+ /* Copy data from the clipboard into the buffer. Experiments show that
+ * the Windows clipboard is smart enough to handle data transfers
+ * larger than 64K properly, even though the buffer address is a 16-bit
+ * segment:offset (which would normally limit the block size to 64K
+ * unless ES gets incremented).
+ */
+ dpmi_regs.x.ax = 0x1705; /* get clipboard data */
+ dpmi_regs.x.dx = clip_data_format; /* CF_VIMCLIP */
+ dpmi_regs.x.es = real_mode_segment_address; /* buffer ad: segment */
+ dpmi_regs.x.bx = 0; /* buffer ad: offset */
+ if (__dpmi_int( 0x2f, &dpmi_regs) == -1)
+ {
+ /* real-mode interrupt failed? */
+ EMSG("E453: could not copy clipboard data to DOS buffer");
+ FreeDOSMemory(protected_mode_selector); /* clean up DOS mem */
+ return NULL; /* early exit */
+ }
+
+ /* Clipboard data is now in DOS memory in the buffer pointed to by
+ * ES:BX. Copy this into ordinary memory that Vim can access (ie.
+ * prot-mode memory). Allocate one extra byte to ensure the text
+ * is terminated properly (in case it was somehow corrupted).
+ */
+ clip_data_buffer = (char_u *)lalloc(clip_data_size + 1, TRUE);
+
+ if (clip_data_buffer == NULL)
+ {
+ /* allocation failed? */
+ EMSG("E454: could not allocate clipboard memory buffer");
+ FreeDOSMemory(protected_mode_selector); /* clean up DOS mem */
+ return NULL; /* early exit */
+ }
+
+ *(clip_data_buffer + clip_data_size) = '\0'; /* ensure terminated */
+
+ /* Copy the data from DOS memory to Vim-accessible memory. */
+ movedata( /* DJGPP version of memcpy() */
+ protected_mode_selector, 0, /* source: DOS ad (via selector) */
+ _my_ds(), (unsigned)clip_data_buffer,
+ /* target: normal mem address */
+ clip_data_size); /* how many bytes */
+
+ /* Free the DOS buffer and release the DPMI prot-mode selector. */
+ FreeDOSMemory(protected_mode_selector); /* clean up DOS memory */
+
+ return clip_data_buffer; /* return pointer to allocated buffer */
+
+ default: /* unknown clipboard format */
+ return NULL;
+ }
+}
+
+/*
+ * Win16SetClipboardData: send 'clip_data_size' bytes of data from the buffer
+ * pointed to by 'clip_data', to the Windows clipboard. The data is
+ * registered with the clipboard as being in the 'clip_data_format'
+ * format.
+ */
+ static int
+Win16SetClipboardData(
+ int clip_data_format,
+ char_u *clip_data,
+ int clip_data_size,
+ int clip_data_type)
+{
+ __dpmi_regs dpmi_regs;
+
+ int real_mode_segment_address;
+ int protected_mode_selector;
+ long_u protected_mode_offset = 0L;
+ int total_size = clip_data_size;
+
+ char_u *clip_sel_type;
+
+ /* If we're using the CF_VIMCLIP custom format, allocate an extra
+ * byte for clip_sel_type, which is a character indicating the type
+ * of text selection: MLINE, MCHAR, or MBLOCK.
+ */
+ if (clip_data_format == CF_VIMCLIP)
+ total_size++; /* extra byte for marker */
+
+ /* Data cannot be sent directly from a Vim string (pClipData) to
+ * the Windows clipboard, because the Windows clipboard interface
+ * expects a 16-bit (DOS) segment:offset address for the source
+ * buffer. Therefore we must create a "transfer buffer" in the DOS
+ * memory region (in the first 1 MByte of address space) and copy
+ * the Vim string into that. From there, the data can then be sent
+ * to the Windows clipboard.
+ *
+ * To allocate DOS memory, we must use __dpmi_allocate_dos_memory()
+ * instead of lalloc() or alloc(). If the allocation fails, it will
+ * almost invariably be because there is not enough DOS memory
+ * available to accommodate the size of clip_data. There is nothing
+ * we can do about this, we simply have to fail.
+ */
+ real_mode_segment_address = __dpmi_allocate_dos_memory(
+ (total_size + 15) >> 4, /* buffer size, in 16-byte paragraphs */
+ &protected_mode_selector); /* prot-mode selector for the address */
+
+ if (real_mode_segment_address == -1)
+ {
+ /* memory allocation failed. */
+ /* Technically we don't know why the allocation failed, but
+ * almost always it will be because there wasn't enough DOS
+ * memory to satisfy the request. On my system, DJGPP is able
+ * to satisfy a DOS allocation request up to about 600K in size.
+ * This depends however on HIMEM.SYS and EMM386.EXE settings.
+ */
+ return FALSE; /* early exit */
+ }
+
+ /* Copy data from Vim's buffer (clip_data) into the DOS transfer buffer.
+ * This can be larger than 64K; movedata() takes care of crossing any
+ * 16-bit segment boundaries.
+ *
+ * If we're using Vim's custom clipboard format, we must copy one extra
+ * byte to indicate the type of selection: line, character, or block.
+ */
+ if (clip_data_format == CF_VIMCLIP)
+ {
+ switch (clip_data_type)
+ {
+ default:
+ case MLINE: clip_sel_type = "L"; break;
+ case MCHAR: clip_sel_type = "C"; break;
+#ifdef FEAT_VISUAL
+ case MBLOCK: clip_sel_type = "B"; break;
+#endif
+ }
+
+ movedata(
+ _my_ds(), (unsigned)clip_sel_type,
+ /* source: normal memory address */
+ protected_mode_selector, 0, /* target: DOS ad (via selector) */
+ 1); /* how many bytes to copy */
+
+ protected_mode_offset += STRLEN(clip_sel_type); /* allow for marker */
+ }
+
+ movedata(
+ _my_ds(), (unsigned)clip_data, /* source: normal memory address */
+ protected_mode_selector, /* target: DOS address (via selector) */
+ protected_mode_offset, /* non-zero, if using clip_sel_type */
+ clip_data_size); /* how many bytes to copy */
+
+ /* Send data from the DOS transfer buffer to the Windows clipboard.
+ * int 02xf, AX = 0x1703 sends SI:CX bytes of data from the buffer
+ * at ES:BX, to the clipboard.
+ */
+ dpmi_regs.x.ax = 0x1703; /* send clipboard data */
+ dpmi_regs.x.dx = clip_data_format; /* flag: format of the data */
+ dpmi_regs.x.si = ((total_size >> 16)
+ & 0x0000ffffL); /* hi word of data size */
+ dpmi_regs.x.cx = (total_size & 0x0000ffffL);
+ /* lo word of data size */
+ dpmi_regs.x.es = real_mode_segment_address; /* buffer address: segment */
+ dpmi_regs.x.bx = 0; /* buffer address: offset */
+ if (__dpmi_int(0x2f, &dpmi_regs) == -1)
+ {
+ /* real-mode interrupt failed. */
+ FreeDOSMemory(protected_mode_selector); /* clean up DOS memory */
+ return FALSE; /* early exit */
+ }
+
+ /* Free the DOS buffer and release the DPMI prot-mode selector. */
+ FreeDOSMemory(protected_mode_selector); /* clean up DOS memory */
+
+ return TRUE; /* TRUE --> data successfully sent to clipboard */
+}
+
+#endif /* FEAT_CLIPBOARD */
+#endif /* DJGPP */
+
+/*
+ * End of MS-DOS only code
+ */
+#endif /* WIN16 */
+
+/* common MS-DOS and Win16 code follows */
+
+ static int
+vim_chmod(char_u *name)
+{
+ char_u *p;
+ int f;
+ int c = 0;
+
+ /* chmod() can't handle a file name with a trailing slash, remove it.
+ * But don't remove it for "/" or "c:/". */
+ p = name + STRLEN(name);
+ if (p > name)
+ --p;
+ if (p > name && (*p == '\\' || *p == '/') && p[-1] != ':')
+ {
+ c = *p; /* remove trailing (back)slash */
+ *p = NUL;
+ }
+ else
+ p = NULL;
+#if defined(__BORLANDC__) && (__BORLANDC__ > 0x410)
+ /* this also sets the archive bit, supported by Borland C 4.0 and later,
+ * where __BORLANDC__ is 0x450 (3.1 is 0x410) */
+ f = _rtl_chmod((char *)name, 0, 0);
+#else
+ f = _chmod((char *)name, 0, 0);
+#endif
+ if (p != NULL)
+ *p = c; /* put back (back)slash */
+ return f;
+}
+
+/*
+ * get file permissions for 'name'
+ * Returns -1 for error.
+ * Returns FA_attributes defined in dos.h
+ */
+ long
+mch_getperm(char_u *name)
+{
+ return (long)vim_chmod(name); /* get file mode */
+}
+
+/*
+ * set file permission for 'name' to 'perm'
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+mch_setperm(
+ char_u *name,
+ long perm)
+{
+ perm |= FA_ARCH; /* file has changed, set archive bit */
+#if defined(__BORLANDC__) && (__BORLANDC__ > 0x410)
+ return (_rtl_chmod((char *)name, 1, (int)perm) == -1 ? FAIL : OK);
+#else
+ return (_chmod((char *)name, 1, (int)perm) == -1 ? FAIL : OK);
+#endif
+}
+
+/*
+ * Set hidden flag for "name".
+ */
+ void
+mch_hide(char_u *name)
+{
+ /* DOS 6.2 share.exe causes "seek error on file write" errors when making
+ * the swap file hidden. Thus don't do it. */
+}
+
+/*
+ * return TRUE if "name" is a directory
+ * return FALSE if "name" is not a directory
+ * return FALSE for error
+ *
+ * beware of a trailing (back)slash
+ */
+ int
+mch_isdir(char_u *name)
+{
+ int f;
+
+ f = vim_chmod(name);
+ if (f == -1)
+ return FALSE; /* file does not exist at all */
+ if ((f & FA_DIREC) == 0)
+ return FALSE; /* not a directory */
+ return TRUE;
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return 1 if "name" can be executed, 0 if not.
+ * Return -1 if unknown.
+ */
+ int
+mch_can_exe(name)
+ char_u *name;
+{
+ return (searchpath(name) != NULL);
+}
+#endif
+
+/*
+ * Check what "name" is:
+ * NODE_NORMAL: file or directory (or doesn't exist)
+ * NODE_WRITABLE: writable device, socket, fifo, etc.
+ * NODE_OTHER: non-writable things
+ */
+ int
+mch_nodetype(char_u *name)
+{
+ if (STRICMP(name, "AUX") == 0
+ || STRICMP(name, "CON") == 0
+ || STRICMP(name, "CLOCK$") == 0
+ || STRICMP(name, "NUL") == 0
+ || STRICMP(name, "PRN") == 0
+ || ((STRNICMP(name, "COM", 3) == 0
+ || STRNICMP(name, "LPT", 3) == 0)
+ && VIM_ISDIGIT(name[3])
+ && name[4] == NUL))
+ return NODE_WRITABLE;
+ /* TODO: NODE_OTHER? */
+ return NODE_NORMAL;
+}
+
+/*
+ * Get name of current directory into buffer 'buf' of length 'len' bytes.
+ * Return OK for success, FAIL for failure.
+ */
+ int
+mch_dirname(
+ char_u *buf,
+ int len)
+{
+#ifdef DJGPP
+ if (getcwd((char *)buf, len) == NULL)
+ return FAIL;
+ /* turn the '/'s returned by DJGPP into '\'s */
+ slash_adjust(buf);
+ return OK;
+#else
+ return (getcwd((char *)buf, len) != NULL ? OK : FAIL);
+#endif
+}
+
+/*
+ * this version of remove is not scared by a readonly (backup) file
+ *
+ * returns -1 on error, 0 otherwise (just like remove())
+ */
+ int
+mch_remove(char_u *name)
+{
+ (void)mch_setperm(name, 0); /* default permissions */
+ return unlink((char *)name);
+}
+
+/*
+ * Special version of getenv(): Use uppercase name.
+ */
+ char_u *
+mch_getenv(char_u *name)
+{
+ int i;
+#define MAXENVLEN 50
+ char_u var_copy[MAXENVLEN + 1];
+ char_u *p;
+ char_u *res;
+
+ /*
+ * Take a copy of the argument, and force it to upper case before passing
+ * to getenv(). On DOS systems, getenv() doesn't like lower-case argument
+ * (unlike Win32 et al.) If the name is too long to fit in var_copy[]
+ * allocate memory.
+ */
+ if ((i = STRLEN(name)) > MAXENVLEN)
+ p = alloc(i + 1);
+ else
+ p = var_copy;
+ if (p == NULL)
+ p = name; /* out of memory, fall back to unmodified name */
+ else
+ {
+ for (i = 0; name[i] != NUL; ++i)
+ p[i] = toupper(name[i]);
+ p[i] = NUL;
+ }
+
+ res = (char_u *)getenv((char *)p);
+
+ if (p != var_copy && p != name)
+ vim_free(p);
+
+ return res;
+}
+
+/*
+ * Insert user name in s[len].
+ */
+ int
+mch_get_user_name(
+ char_u *s,
+ int len)
+{
+ *s = NUL;
+ return FAIL;
+}
+
+/*
+ * Insert host name is s[len].
+ */
+ void
+mch_get_host_name(
+ char_u *s,
+ int len)
+{
+#ifdef DJGPP
+ STRNCPY(s, "PC (32 bits Vim)", len);
+#else
+ STRNCPY(s, "PC (16 bits Vim)", len);
+#endif
+ s[len - 1] = NUL; /* make sure it's terminated */
+}
diff --git a/src/os_msdos.h b/src/os_msdos.h
new file mode 100644
index 000000000..576b2383c
--- /dev/null
+++ b/src/os_msdos.h
@@ -0,0 +1,106 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * MSDOS Machine-dependent things.
+ */
+
+#include "os_dos.h" /* common MS-DOS and Win32 stuff */
+
+#define BINARY_FILE_IO
+#define USE_EXE_NAME /* use argv[0] for $VIM */
+#define NO_COOKED_INPUT /* mch_inchar() doesn't return whole lines */
+#define SYNC_DUP_CLOSE /* sync() a file with dup() and close() */
+#define USE_TERM_CONSOLE
+#ifdef DJGPP
+# include <fcntl.h> /* defines _USE_LFN */
+# define USE_LONG_FNAME _USE_LFN /* decide at run time */
+# define USE_FNAME_CASE
+# define HAVE_PUTENV
+#else
+# define SHORT_FNAME /* always 8.3 file name */
+#endif
+#define HAVE_STDLIB_H
+#define HAVE_STRING_H
+#define HAVE_FCNTL_H
+#define HAVE_STRCSPN
+#define HAVE_STRICMP
+#define HAVE_STRFTIME /* guessed */
+#define HAVE_STRNICMP
+#define HAVE_MEMSET
+#define HAVE_QSORT
+#define HAVE_ST_MODE /* have stat.st_mode */
+#if defined(__DATE__) && defined(__TIME__)
+# define HAVE_DATE_TIME
+#endif
+#define BREAKCHECK_SKIP 1 /* call mch_breakcheck() each time, it's fast */
+#define HAVE_AVAIL_MEM
+
+/*
+ * Borland C++ 3.1 doesn't have _RTLENTRYF
+ */
+#ifdef __BORLANDC__
+# if __BORLANDC__ < 0x450
+# define _RTLENTRYF
+# endif
+#endif
+
+#define FNAME_ILLEGAL "\"*?><|" /* illegal characters in a file name */
+
+#include <dos.h>
+#include <dir.h>
+#include <time.h>
+
+#ifdef DJGPP
+# include <unistd.h>
+# define HAVE_LOCALE_H
+# define setlocale(c, p) djgpp_setlocale()
+#endif
+
+#ifndef DJGPP
+typedef long off_t;
+#endif
+
+/*
+ * Try several directories to put the temp files.
+ */
+#define TEMPDIRNAMES "$TMP", "$TEMP", "c:\\TMP", "c:\\TEMP", ""
+#define TEMPNAMELEN 128
+
+#ifndef DFLT_MAXMEM
+# define DFLT_MAXMEM 256 /* use up to 256Kbyte for buffer */
+#endif
+#ifndef DFLT_MAXMEMTOT
+# define DFLT_MAXMEMTOT 0 /* decide in set_init */
+#endif
+
+#ifdef DJGPP
+# define BASENAMELEN (_USE_LFN?250:8) /* length of base of file name */
+#else
+# define BASENAMELEN 8 /* length of base of file name */
+#endif
+
+/* codes for msdos mouse event */
+#define MSDOS_MOUSE_LEFT 0x01
+#define MSDOS_MOUSE_RIGHT 0x02
+#define MSDOS_MOUSE_MIDDLE 0x04
+
+#ifdef DJGPP
+int mch_rename(const char *OldFile, const char *NewFile);
+#else
+# define mch_rename(src, dst) rename(src, dst)
+#endif
+
+#ifdef DJGPP
+# define vim_mkdir(x, y) mkdir((char *)(x), y)
+#else
+# define vim_mkdir(x, y) mkdir((char *)(x))
+#endif
+#define mch_rmdir(x) rmdir((char *)(x))
+
+#define mch_setenv(name, val, x) setenv(name, val, x)
diff --git a/src/os_mswin.c b/src/os_mswin.c
new file mode 100644
index 000000000..97803a89d
--- /dev/null
+++ b/src/os_mswin.c
@@ -0,0 +1,3245 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * os_mswin.c
+ *
+ * Routines common to both Win16 and Win32.
+ */
+
+#ifdef WIN16
+# ifdef __BORLANDC__
+# pragma warn -par
+# pragma warn -ucp
+# pragma warn -use
+# pragma warn -aus
+# endif
+#endif
+
+#include <io.h>
+#include "vim.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#ifdef WIN16
+# define SHORT_FNAME /* always 8.3 file name */
+# include <dos.h>
+# include <string.h>
+#endif
+#include <sys/types.h>
+#include <errno.h>
+#include <signal.h>
+#include <limits.h>
+#include <process.h>
+
+#undef chdir
+#ifdef __GNUC__
+# ifndef __MINGW32__
+# include <dirent.h>
+# endif
+#else
+# include <direct.h>
+#endif
+
+#if defined(FEAT_TITLE) && !defined(FEAT_GUI_W32)
+# include <shellapi.h>
+#endif
+
+#if defined(FEAT_PRINTER) && !defined(FEAT_POSTSCRIPT)
+# include <dlgs.h>
+# ifdef WIN3264
+# include <winspool.h>
+# else
+# include <print.h>
+# endif
+# include <commdlg.h>
+#endif
+
+#ifdef __MINGW32__
+# ifndef FROM_LEFT_1ST_BUTTON_PRESSED
+# define FROM_LEFT_1ST_BUTTON_PRESSED 0x0001
+# endif
+# ifndef RIGHTMOST_BUTTON_PRESSED
+# define RIGHTMOST_BUTTON_PRESSED 0x0002
+# endif
+# ifndef FROM_LEFT_2ND_BUTTON_PRESSED
+# define FROM_LEFT_2ND_BUTTON_PRESSED 0x0004
+# endif
+# ifndef FROM_LEFT_3RD_BUTTON_PRESSED
+# define FROM_LEFT_3RD_BUTTON_PRESSED 0x0008
+# endif
+# ifndef FROM_LEFT_4TH_BUTTON_PRESSED
+# define FROM_LEFT_4TH_BUTTON_PRESSED 0x0010
+# endif
+
+/*
+ * EventFlags
+ */
+# ifndef MOUSE_MOVED
+# define MOUSE_MOVED 0x0001
+# endif
+# ifndef DOUBLE_CLICK
+# define DOUBLE_CLICK 0x0002
+# endif
+#endif
+
+/*
+ * When generating prototypes for Win32 on Unix, these lines make the syntax
+ * errors disappear. They do not need to be correct.
+ */
+#ifdef PROTO
+#define WINAPI
+#define WINBASEAPI
+typedef int BOOL;
+typedef int CALLBACK;
+typedef int COLORREF;
+typedef int CONSOLE_CURSOR_INFO;
+typedef int COORD;
+typedef int DWORD;
+typedef int ENUMLOGFONT;
+typedef int HANDLE;
+typedef int HDC;
+typedef int HFONT;
+typedef int HICON;
+typedef int HWND;
+typedef int INPUT_RECORD;
+typedef int KEY_EVENT_RECORD;
+typedef int LOGFONT;
+typedef int LPARAM;
+typedef int LPBOOL;
+typedef int LPCSTR;
+typedef int LPCWSTR;
+typedef int LPSTR;
+typedef int LPTSTR;
+typedef int LPWSTR;
+typedef int LRESULT;
+typedef int MOUSE_EVENT_RECORD;
+typedef int NEWTEXTMETRIC;
+typedef int PACL;
+typedef int PRINTDLG;
+typedef int PSECURITY_DESCRIPTOR;
+typedef int PSID;
+typedef int SECURITY_INFORMATION;
+typedef int SHORT;
+typedef int SMALL_RECT;
+typedef int TEXTMETRIC;
+typedef int UINT;
+typedef int WCHAR;
+typedef int WORD;
+typedef int WPARAM;
+typedef void VOID;
+#endif
+
+/* Record all output and all keyboard & mouse input */
+/* #define MCH_WRITE_DUMP */
+
+#ifdef MCH_WRITE_DUMP
+FILE* fdDump = NULL;
+#endif
+
+#ifdef WIN3264
+extern DWORD g_PlatformId;
+#endif
+
+#ifndef FEAT_GUI_MSWIN
+extern char g_szOrigTitle[];
+#endif
+
+#ifdef FEAT_GUI
+extern HWND s_hwnd;
+#else
+# if (defined(FEAT_PRINTER) && !defined(FEAT_POSTSCRIPT)) \
+ || defined(FEAT_CLIENTSERVER) \
+ || (defined(FEAT_EVAL) && !defined(FEAT_GUI))
+# define HAVE_GETCONSOLEHWND
+static HWND s_hwnd = 0; /* console window handle, set by GetConsoleHwnd() */
+# endif
+#endif
+
+extern int WSInitialized;
+
+/* Don't generate prototypes here, because some systems do have these
+ * functions. */
+#if defined(__GNUC__) && !defined(PROTO)
+# ifndef __MINGW32__
+int _stricoll(char *a, char *b)
+{
+ // the ANSI-ish correct way is to use strxfrm():
+ char a_buff[512], b_buff[512]; // file names, so this is enough on Win32
+ strxfrm(a_buff, a, 512);
+ strxfrm(b_buff, b, 512);
+ return strcoll(a_buff, b_buff);
+}
+
+char * _fullpath(char *buf, char *fname, int len)
+{
+ LPTSTR toss;
+
+ return (char *)GetFullPathName(fname, len, buf, &toss);
+}
+# endif
+
+int _chdrive(int drive)
+{
+ char temp [3] = "-:";
+ temp[0] = drive + 'A' - 1;
+ return !SetCurrentDirectory(temp);
+}
+#else
+# ifdef __BORLANDC__
+/* being a more ANSI compliant compiler, BorlandC doesn't define _stricoll:
+ * but it does in BC 5.02! */
+# if __BORLANDC__ < 0x502
+int _stricoll(char *a, char *b)
+{
+# if 1
+ // this is fast but not correct:
+ return stricmp(a, b);
+# else
+ // the ANSI-ish correct way is to use strxfrm():
+ char a_buff[512], b_buff[512]; // file names, so this is enough on Win32
+ strxfrm(a_buff, a, 512);
+ strxfrm(b_buff, b, 512);
+ return strcoll(a_buff, b_buff);
+# endif
+}
+# endif
+# endif
+#endif
+
+
+#if defined(FEAT_GUI_MSWIN) || defined(PROTO)
+/*
+ * GUI version of mch_exit().
+ * Shut down and exit with status `r'
+ * Careful: mch_exit() may be called before mch_init()!
+ */
+ void
+mch_exit(int r)
+{
+ display_errors();
+
+ ml_close_all(TRUE); /* remove all memfiles */
+
+# ifdef FEAT_OLE
+ UninitOLE();
+# endif
+# ifdef FEAT_NETBEANS_INTG
+ if (WSInitialized)
+ {
+ WSInitialized = FALSE;
+ WSACleanup();
+ }
+# endif
+#ifdef DYNAMIC_GETTEXT
+ dyn_libintl_end();
+#endif
+
+ if (gui.in_use)
+ gui_exit(r);
+ exit(r);
+}
+
+#endif /* FEAT_GUI_MSWIN */
+
+
+/*
+ * Init the tables for toupper() and tolower().
+ */
+ void
+mch_early_init(void)
+{
+ int i;
+
+#ifdef WIN3264
+ PlatformId();
+#endif
+
+ /* Init the tables for toupper() and tolower() */
+ for (i = 0; i < 256; ++i)
+ toupper_tab[i] = tolower_tab[i] = i;
+#ifdef WIN3264
+ CharUpperBuff(toupper_tab, 256);
+ CharLowerBuff(tolower_tab, 256);
+#else
+ AnsiUpperBuff(toupper_tab, 256);
+ AnsiLowerBuff(tolower_tab, 256);
+#endif
+}
+
+
+/*
+ * Return TRUE if the input comes from a terminal, FALSE otherwise.
+ */
+ int
+mch_input_isatty()
+{
+#ifdef FEAT_GUI_MSWIN
+ return OK; /* GUI always has a tty */
+#else
+ if (isatty(read_cmd_fd))
+ return TRUE;
+ return FALSE;
+#endif
+}
+
+#ifdef FEAT_TITLE
+/*
+ * mch_settitle(): set titlebar of our window
+ */
+ void
+mch_settitle(
+ char_u *title,
+ char_u *icon)
+{
+# ifdef FEAT_GUI_MSWIN
+ gui_mch_settitle(title, icon);
+# else
+ if (title != NULL)
+ SetConsoleTitle(title);
+# endif
+}
+
+
+/*
+ * Restore the window/icon title.
+ * which is one of:
+ * 1: Just restore title
+ * 2: Just restore icon (which we don't have)
+ * 3: Restore title and icon (which we don't have)
+ */
+ void
+mch_restore_title(
+ int which)
+{
+#ifndef FEAT_GUI_MSWIN
+ mch_settitle((which & 1) ? g_szOrigTitle : NULL, NULL);
+#endif
+}
+
+
+/*
+ * Return TRUE if we can restore the title (we can)
+ */
+ int
+mch_can_restore_title()
+{
+ return TRUE;
+}
+
+
+/*
+ * Return TRUE if we can restore the icon title (we can't)
+ */
+ int
+mch_can_restore_icon()
+{
+ return FALSE;
+}
+#endif /* FEAT_TITLE */
+
+
+/*
+ * Get absolute file name into buffer 'buf' of length 'len' bytes,
+ * turning all '/'s into '\\'s and getting the correct case of each
+ * component of the file name. Append a backslash to a directory name.
+ * When 'shellslash' set do it the other way around.
+ * Return OK or FAIL.
+ */
+ int
+mch_FullName(
+ char_u *fname,
+ char_u *buf,
+ int len,
+ int force)
+{
+ int nResult = FAIL;
+
+#ifdef __BORLANDC__
+ if (*fname == NUL) /* Borland behaves badly here - make it consistent */
+ nResult = mch_dirname(buf, len);
+ else
+#endif
+ if (_fullpath(buf, fname, len - 1) == NULL)
+ {
+ STRNCPY(buf, fname, len); /* failed, use the relative path name */
+ buf[len - 1] = NUL;
+#ifndef USE_FNAME_CASE
+ slash_adjust(buf);
+#endif
+ }
+ else
+ nResult = OK;
+
+#ifdef USE_FNAME_CASE
+ fname_case(buf, len);
+#endif
+
+ return nResult;
+}
+
+
+/*
+ * Return TRUE if "fname" does not depend on the current directory.
+ */
+ int
+mch_isFullName(char_u *fname)
+{
+ char szName[_MAX_PATH + 1];
+
+ /* A name like "d:/foo" and "//server/share" is absolute */
+ if ((fname[0] && fname[1] == ':' && (fname[2] == '/' || fname[2] == '\\'))
+ || (fname[0] == fname[1] && (fname[0] == '/' || fname[0] == '\\')))
+ return TRUE;
+
+ /* A name that can't be made absolute probably isn't absolute. */
+ if (mch_FullName(fname, szName, _MAX_PATH, FALSE) == FAIL)
+ return FALSE;
+
+ return pathcmp(fname, szName) == 0;
+}
+
+/*
+ * Replace all slashes by backslashes.
+ * This used to be the other way around, but MS-DOS sometimes has problems
+ * with slashes (e.g. in a command name). We can't have mixed slashes and
+ * backslashes, because comparing file names will not work correctly. The
+ * commands that use a file name should try to avoid the need to type a
+ * backslash twice.
+ * When 'shellslash' set do it the other way around.
+ */
+ void
+slash_adjust(p)
+ char_u *p;
+{
+ if (p != NULL)
+ while (*p)
+ {
+ if (*p == psepcN)
+ *p = psepc;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p);
+ else
+#endif
+ ++p;
+ }
+}
+
+
+/*
+ * stat() can't handle a trailing '/' or '\', remove it first.
+ */
+ int
+vim_stat(const char *name, struct stat *stp)
+{
+ char buf[_MAX_PATH + 1];
+ char *p;
+
+ STRNCPY(buf, name, _MAX_PATH);
+ buf[_MAX_PATH] = NUL;
+ p = buf + strlen(buf);
+ if (p > buf)
+ --p;
+ if (p > buf && (*p == '\\' || *p == '/') && p[-1] != ':')
+ *p = NUL;
+#ifdef FEAT_MBYTE
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage
+# ifdef __BORLANDC__
+ /* Wide functions of Borland C 5.5 do not work on Windows 98. */
+ && g_PlatformId == VER_PLATFORM_WIN32_NT
+# endif
+ )
+ {
+ WCHAR *wp = enc_to_ucs2(buf, NULL);
+ int n;
+
+ if (wp != NULL)
+ {
+ n = _wstat(wp, (struct _stat *)stp);
+ vim_free(wp);
+ if (n >= 0)
+ return n;
+ /* Retry with non-wide function (for Windows 98). Can't use
+ * GetLastError() here and it's unclear what errno gets set to if
+ * the _wstat() fails for missing wide functions. */
+ }
+ }
+#endif
+ return stat(buf, stp);
+}
+
+#if defined(FEAT_GUI_MSWIN) || defined(PROTO)
+ void
+mch_settmode(int tmode)
+{
+ /* nothing to do */
+}
+
+ int
+mch_get_shellsize(void)
+{
+ /* never used */
+ return OK;
+}
+
+ void
+mch_set_shellsize(void)
+{
+ /* never used */
+}
+
+/*
+ * Rows and/or Columns has changed.
+ */
+ void
+mch_new_shellsize(void)
+{
+ /* never used */
+}
+
+#endif
+
+/*
+ * We have no job control, so fake it by starting a new shell.
+ */
+ void
+mch_suspend()
+{
+ suspend_shell();
+}
+
+#if defined(USE_MCH_ERRMSG) || defined(PROTO)
+
+#ifdef display_errors
+# undef display_errors
+#endif
+
+/*
+ * Display the saved error message(s).
+ */
+ void
+display_errors()
+{
+ char *p;
+
+ if (error_ga.ga_data != NULL)
+ {
+ /* avoid putting up a message box with blanks only */
+ for (p = (char *)error_ga.ga_data; *p; ++p)
+ if (!isspace(*p))
+ {
+ /* Truncate a very long message, it will go off-screen. */
+ if (STRLEN(p) > 2000)
+ {
+ char_u *s = p + 2000 - 14;
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ s -= (*mb_head_off)(p, s);
+#endif
+ STRCPY(s, _("...(truncated)"));
+ }
+#ifdef WIN3264
+ MessageBox(NULL, p, "Vim", MB_TASKMODAL|MB_SETFOREGROUND);
+#else
+ MessageBox(NULL, p, "Vim", MB_TASKMODAL);
+#endif
+ break;
+ }
+ ga_clear(&error_ga);
+ }
+}
+#endif
+
+
+/*
+ * Return TRUE if "p" contain a wildcard that can be expanded by
+ * dos_expandpath().
+ */
+ int
+mch_has_exp_wildcard(char_u *p)
+{
+ for ( ; *p; ++p)
+ {
+ if (vim_strchr((char_u *)"?*[", *p) != NULL
+ || (*p == '~' && p[1] != NUL))
+ return TRUE;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ return FALSE;
+}
+
+/*
+ * Return TRUE if "p" contain a wildcard or a "~1" kind of thing (could be a
+ * shortened file name).
+ */
+ int
+mch_has_wildcard(char_u *p)
+{
+ for ( ; *p; ++p)
+ {
+ if (vim_strchr((char_u *)
+# ifdef VIM_BACKTICK
+ "?*$[`"
+# else
+ "?*$["
+# endif
+ , *p) != NULL
+ || (*p == '~' && p[1] != NUL))
+ return TRUE;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ return FALSE;
+}
+
+
+/*
+ * The normal _chdir() does not change the default drive. This one does.
+ * Returning 0 implies success; -1 implies failure.
+ */
+ int
+mch_chdir(char *path)
+{
+ if (path[0] == NUL) /* just checking... */
+ return -1;
+
+ if (isalpha(path[0]) && path[1] == ':') /* has a drive name */
+ {
+ /* If we can change to the drive, skip that part of the path. If we
+ * can't then the current directory may be invalid, try using chdir()
+ * with the whole path. */
+ if (_chdrive(TOLOWER_ASC(path[0]) - 'a' + 1) == 0)
+ path += 2;
+ }
+
+ if (*path == NUL) /* drive name only */
+ return 0;
+
+ return chdir(path); /* let the normal chdir() do the rest */
+}
+
+
+/*
+ * Switching off termcap mode is only allowed when Columns is 80, otherwise a
+ * crash may result. It's always allowed on NT or when running the GUI.
+ */
+ int
+can_end_termcap_mode(
+ int give_msg)
+{
+#ifdef FEAT_GUI_MSWIN
+ return TRUE; /* GUI starts a new console anyway */
+#else
+ if (g_PlatformId == VER_PLATFORM_WIN32_NT || Columns == 80)
+ return TRUE;
+ if (give_msg)
+ msg(_("'columns' is not 80, cannot execute external commands"));
+ return FALSE;
+#endif
+}
+
+#ifdef FEAT_GUI_MSWIN
+/*
+ * return non-zero if a character is available
+ */
+ int
+mch_char_avail()
+{
+ /* never used */
+ return TRUE;
+}
+#endif
+
+
+/*
+ * set screen mode, always fails.
+ */
+ int
+mch_screenmode(
+ char_u *arg)
+{
+ EMSG(_(e_screenmode));
+ return FAIL;
+}
+
+
+#if defined(FEAT_LIBCALL) || defined(PROTO)
+/*
+ * Call a DLL routine which takes either a string or int param
+ * and returns an allocated string.
+ * Return OK if it worked, FAIL if not.
+ */
+# ifdef WIN3264
+typedef LPTSTR (*MYSTRPROCSTR)(LPTSTR);
+typedef LPTSTR (*MYINTPROCSTR)(int);
+typedef int (*MYSTRPROCINT)(LPTSTR);
+typedef int (*MYINTPROCINT)(int);
+# else
+typedef LPSTR (*MYSTRPROCSTR)(LPSTR);
+typedef LPSTR (*MYINTPROCSTR)(int);
+typedef int (*MYSTRPROCINT)(LPSTR);
+typedef int (*MYINTPROCINT)(int);
+# endif
+
+# ifndef WIN16
+/*
+ * Check if a pointer points to a valid NUL terminated string.
+ * Return the length of the string, including terminating NUL.
+ * Returns 0 for an invalid pointer, 1 for an empty string.
+ */
+ static size_t
+check_str_len(char_u *str)
+{
+ SYSTEM_INFO si;
+ MEMORY_BASIC_INFORMATION mbi;
+ size_t length = 0;
+ size_t i;
+ const char *p;
+
+ /* get page size */
+ GetSystemInfo(&si);
+
+ /* get memory information */
+ if (VirtualQuery(str, &mbi, sizeof(mbi)))
+ {
+ /* pre cast these (typing savers) */
+ DWORD dwStr = (DWORD)str;
+ DWORD dwBaseAddress = (DWORD)mbi.BaseAddress;
+
+ /* get start address of page that str is on */
+ DWORD strPage = dwStr - (dwStr - dwBaseAddress) % si.dwPageSize;
+
+ /* get length from str to end of page */
+ DWORD pageLength = si.dwPageSize - (dwStr - strPage);
+
+ for (p = str; !IsBadReadPtr(p, pageLength);
+ p += pageLength, pageLength = si.dwPageSize)
+ for (i = 0; i < pageLength; ++i, ++length)
+ if (p[i] == NUL)
+ return length + 1;
+ }
+
+ return 0;
+}
+# endif
+
+ int
+mch_libcall(
+ char_u *libname,
+ char_u *funcname,
+ char_u *argstring, /* NULL when using a argint */
+ int argint,
+ char_u **string_result,/* NULL when using number_result */
+ int *number_result)
+{
+ HINSTANCE hinstLib;
+ MYSTRPROCSTR ProcAdd;
+ MYINTPROCSTR ProcAddI;
+ char_u *retval_str = NULL;
+ int retval_int = 0;
+ size_t len;
+
+ BOOL fRunTimeLinkSuccess = FALSE;
+
+ // Get a handle to the DLL module.
+ hinstLib = LoadLibrary(libname);
+
+ // If the handle is valid, try to get the function address.
+ if (hinstLib != NULL)
+ {
+#ifdef HAVE_TRY_EXCEPT
+ __try
+ {
+#endif
+ if (argstring != NULL)
+ {
+ /* Call with string argument */
+ ProcAdd = (MYSTRPROCSTR) GetProcAddress(hinstLib, funcname);
+ if ((fRunTimeLinkSuccess = (ProcAdd != NULL)) != 0)
+ {
+ if (string_result == NULL)
+ retval_int = ((MYSTRPROCINT)ProcAdd)(argstring);
+ else
+ retval_str = (ProcAdd)(argstring);
+ }
+ }
+ else
+ {
+ /* Call with number argument */
+ ProcAddI = (MYINTPROCSTR) GetProcAddress(hinstLib, funcname);
+ if ((fRunTimeLinkSuccess = (ProcAddI != NULL)) != 0)
+ {
+ if (string_result == NULL)
+ retval_int = ((MYINTPROCINT)ProcAddI)(argint);
+ else
+ retval_str = (ProcAddI)(argint);
+ }
+ }
+
+ // Save the string before we free the library.
+ // Assume that a "1" result is an illegal pointer.
+ if (string_result == NULL)
+ *number_result = retval_int;
+ else if (retval_str != NULL
+# ifdef WIN16
+ && retval_str != (char_u *)1
+ && retval_str != (char_u *)-1
+ && !IsBadStringPtr(retval_str, INT_MAX)
+ && (len = strlen(retval_str) + 1) > 0
+# else
+ && (len = check_str_len(retval_str)) > 0
+# endif
+ )
+ {
+ *string_result = lalloc((long_u)len, TRUE);
+ if (*string_result != NULL)
+ mch_memmove(*string_result, retval_str, len);
+ }
+
+#ifdef HAVE_TRY_EXCEPT
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW)
+ RESETSTKOFLW();
+ fRunTimeLinkSuccess = 0;
+ }
+#endif
+
+ // Free the DLL module.
+ (void)FreeLibrary(hinstLib);
+ }
+
+ if (!fRunTimeLinkSuccess)
+ {
+ EMSG2(_(e_libcall), funcname);
+ return FAIL;
+ }
+
+ return OK;
+}
+#endif
+
+#if defined(FEAT_MBYTE) || defined(PROTO)
+/*
+ * Convert an UTF-8 string to UCS-2.
+ * "instr[inlen]" is the input. "inlen" is in bytes.
+ * When "outstr" is NULL only return the number of UCS-2 words produced.
+ * Otherwise "outstr" must be a buffer of sufficient size.
+ * Returns the number of UCS-2 words produced.
+ */
+ int
+utf8_to_ucs2(char_u *instr, int inlen, short_u *outstr, int *unconvlenp)
+{
+ int outlen = 0;
+ char_u *p = instr;
+ int todo = inlen;
+ int l;
+
+ while (todo > 0)
+ {
+ /* Only convert if we have a complete sequence. */
+ l = utf_ptr2len_check_len(p, todo);
+ if (l > todo)
+ {
+ /* Return length of incomplete sequence. */
+ if (unconvlenp != NULL)
+ *unconvlenp = todo;
+ break;
+ }
+
+ if (outstr != NULL)
+ *outstr++ = utf_ptr2char(p);
+ ++outlen;
+ p += l;
+ todo -= l;
+ }
+
+ return outlen;
+}
+
+/*
+ * Convert an UCS-2 string to UTF-8.
+ * The input is "instr[inlen]" with "inlen" in number of ucs-2 words.
+ * When "outstr" is NULL only return the required number of bytes.
+ * Otherwise "outstr" must be a buffer of sufficient size.
+ * Return the number of bytes produced.
+ */
+ int
+ucs2_to_utf8(short_u *instr, int inlen, char_u *outstr)
+{
+ int outlen = 0;
+ int todo = inlen;
+ short_u *p = instr;
+ int l;
+
+ while (todo > 0)
+ {
+ if (outstr != NULL)
+ {
+ l = utf_char2bytes(*p, outstr);
+ outstr += l;
+ }
+ else
+ l = utf_char2len(*p);
+ ++p;
+ outlen += l;
+ --todo;
+ }
+
+ return outlen;
+}
+
+/*
+ * Call MultiByteToWideChar() and allocate memory for the result.
+ * Returns the result in "*out[*outlen]" with an extra zero appended.
+ * "outlen" is in words.
+ */
+ void
+MultiByteToWideChar_alloc(UINT cp, DWORD flags,
+ LPCSTR in, int inlen,
+ LPWSTR *out, int *outlen)
+{
+ *outlen = MultiByteToWideChar(cp, flags, in, inlen, 0, 0);
+ /* Add one one word to avoid a zero-length alloc(). */
+ *out = (LPWSTR)alloc(sizeof(WCHAR) * (*outlen + 1));
+ if (*out != NULL)
+ {
+ MultiByteToWideChar(cp, flags, in, inlen, *out, *outlen);
+ (*out)[*outlen] = 0;
+ }
+}
+
+/*
+ * Call WideCharToMultiByte() and allocate memory for the result.
+ * Returns the result in "*out[*outlen]" with an extra NUL appended.
+ */
+ void
+WideCharToMultiByte_alloc(UINT cp, DWORD flags,
+ LPCWSTR in, int inlen,
+ LPSTR *out, int *outlen,
+ LPCSTR def, LPBOOL useddef)
+{
+ *outlen = WideCharToMultiByte(cp, flags, in, inlen, NULL, 0, def, useddef);
+ /* Add one one byte to avoid a zero-length alloc(). */
+ *out = alloc((unsigned)*outlen + 1);
+ if (*out != NULL)
+ {
+ WideCharToMultiByte(cp, flags, in, inlen, *out, *outlen, def, useddef);
+ (*out)[*outlen] = 0;
+ }
+}
+
+#endif /* FEAT_MBYTE */
+
+#ifdef FEAT_CLIPBOARD
+/*
+ * Clipboard stuff, for cutting and pasting text to other windows.
+ */
+
+/* Type used for the clipboard type of Vim's data. */
+typedef struct
+{
+ int type; /* MCHAR, MBLOCK or MLINE */
+ int txtlen; /* length of CF_TEXT in bytes */
+ int ucslen; /* length of CF_UNICODETEXT in words */
+ int rawlen; /* length of clip_star.format_raw, including encoding,
+ excluding terminating NUL */
+} VimClipType_t;
+
+/*
+ * Make vim the owner of the current selection. Return OK upon success.
+ */
+ int
+clip_mch_own_selection(VimClipboard *cbd)
+{
+ /*
+ * Never actually own the clipboard. If another application sets the
+ * clipboard, we don't want to think that we still own it.
+ */
+ return FAIL;
+}
+
+/*
+ * Make vim NOT the owner of the current selection.
+ */
+ void
+clip_mch_lose_selection(VimClipboard *cbd)
+{
+ /* Nothing needs to be done here */
+}
+
+/*
+ * Copy "str[*size]" into allocated memory, changing CR-NL to NL.
+ * Return the allocated result and the size in "*size".
+ * Returns NULL when out of memory.
+ */
+ static char_u *
+crnl_to_nl(const char_u *str, int *size)
+{
+ int pos = 0;
+ int str_len = *size;
+ char_u *ret;
+ char_u *retp;
+
+ /* Avoid allocating zero bytes, it generates an error message. */
+ ret = lalloc((long_u)(str_len == 0 ? 1 : str_len), TRUE);
+ if (ret != NULL)
+ {
+ retp = ret;
+ for (pos = 0; pos < str_len; ++pos)
+ {
+ if (str[pos] == '\r' && str[pos + 1] == '\n')
+ {
+ ++pos;
+ --(*size);
+ }
+ *retp++ = str[pos];
+ }
+ }
+
+ return ret;
+}
+
+#if defined(FEAT_MBYTE) || defined(PROTO)
+/*
+ * Note: the following two functions are only guaranteed to work when using
+ * valid MS-Windows codepages or when iconv() is available.
+ */
+
+/*
+ * Convert "str" from 'encoding' to UCS-2.
+ * Input in "str" with length "*lenp". When "lenp" is NULL, use strlen().
+ * Output is returned as an allocated string. "*lenp" is set to the length of
+ * the result. A trailing NUL is always added.
+ * Returns NULL when out of memory.
+ */
+ short_u *
+enc_to_ucs2(char_u *str, int *lenp)
+{
+ vimconv_T conv;
+ WCHAR *ret;
+ char_u *allocbuf = NULL;
+ int len_loc;
+ int length;
+
+ if (lenp == NULL)
+ {
+ len_loc = STRLEN(str) + 1;
+ lenp = &len_loc;
+ }
+
+ if (enc_codepage > 0)
+ {
+ /* We can do any CP### -> UCS-2 in one pass, and we can do it
+ * without iconv() (convert_* may need iconv). */
+ MultiByteToWideChar_alloc(enc_codepage, 0, str, *lenp, &ret, &length);
+ }
+ else
+ {
+ /* Use "latin1" by default, we might be called before we have p_enc
+ * set up. Convert to utf-8 first, works better with iconv(). Does
+ * nothing if 'encoding' is "utf-8". */
+ conv.vc_type = CONV_NONE;
+ if (convert_setup(&conv, p_enc ? p_enc : (char_u *)"latin1",
+ (char_u *)"utf-8") == FAIL)
+ return NULL;
+ if (conv.vc_type != CONV_NONE)
+ {
+ str = allocbuf = string_convert(&conv, str, lenp);
+ if (str == NULL)
+ return NULL;
+ }
+ convert_setup(&conv, NULL, NULL);
+
+ length = utf8_to_ucs2(str, *lenp, NULL, NULL);
+ ret = (WCHAR *)alloc((unsigned)((length + 1) * sizeof(WCHAR)));
+ if (ret != NULL)
+ {
+ utf8_to_ucs2(str, *lenp, (short_u *)ret, NULL);
+ ret[length] = 0;
+ }
+
+ vim_free(allocbuf);
+ }
+
+ *lenp = length;
+ return (short_u *)ret;
+}
+
+/*
+ * Convert an UCS-2 string to 'encoding'.
+ * Input in "str" with length (counted in wide characters) "*lenp". When
+ * "lenp" is NULL, use wcslen().
+ * Output is returned as an allocated string. If "*lenp" is not NULL it is
+ * set to the length of the result.
+ * Returns NULL when out of memory.
+ */
+ char_u *
+ucs2_to_enc(short_u *str, int *lenp)
+{
+ vimconv_T conv;
+ char_u *utf8_str = NULL, *enc_str = NULL;
+ int len_loc;
+
+ if (lenp == NULL)
+ {
+ len_loc = wcslen(str) + 1;
+ lenp = &len_loc;
+ }
+
+ if (enc_codepage > 0)
+ {
+ /* We can do any UCS-2 -> CP### in one pass. */
+ int length;
+
+ WideCharToMultiByte_alloc(enc_codepage, 0, str, *lenp,
+ (LPSTR *)&enc_str, &length, 0, 0);
+ *lenp = length;
+ return enc_str;
+ }
+
+ /* Avoid allocating zero bytes, it generates an error message. */
+ utf8_str = alloc(ucs2_to_utf8(str, *lenp == 0 ? 1 : *lenp, NULL));
+ if (utf8_str != NULL)
+ {
+ *lenp = ucs2_to_utf8(str, *lenp, utf8_str);
+
+ /* We might be called before we have p_enc set up. */
+ conv.vc_type = CONV_NONE;
+ convert_setup(&conv, (char_u *)"utf-8",
+ p_enc? p_enc: (char_u *)"latin1");
+ if (conv.vc_type == CONV_NONE)
+ {
+ /* p_enc is utf-8, so we're done. */
+ enc_str = utf8_str;
+ }
+ else
+ {
+ enc_str = string_convert(&conv, utf8_str, lenp);
+ vim_free(utf8_str);
+ }
+
+ convert_setup(&conv, NULL, NULL);
+ }
+
+ return enc_str;
+}
+#endif /* FEAT_MBYTE */
+
+/*
+ * Get the current selection and put it in the clipboard register.
+ *
+ * NOTE: Must use GlobalLock/Unlock here to ensure Win32s compatibility.
+ * On NT/W95 the clipboard data is a fixed global memory object and
+ * so its handle = its pointer.
+ * On Win32s, however, co-operation with the Win16 system means that
+ * the clipboard data is moveable and its handle is not a pointer at all,
+ * so we can't just cast the return value of GetClipboardData to (char_u*).
+ * <VN>
+ */
+ void
+clip_mch_request_selection(VimClipboard *cbd)
+{
+ VimClipType_t metadata = { -1, -1, -1, -1 };
+ HGLOBAL hMem = NULL;
+ char_u *str = NULL;
+#if defined(FEAT_MBYTE) && defined(WIN3264)
+ char_u *to_free = NULL;
+#endif
+#ifdef FEAT_MBYTE
+ HGLOBAL rawh = NULL;
+#endif
+ char_u *hMemStr = NULL;
+ int str_size = 0;
+ int maxlen;
+ size_t n;
+
+ /*
+ * Don't pass GetActiveWindow() as an argument to OpenClipboard() because
+ * then we can't paste back into the same window for some reason - webb.
+ */
+ if (!OpenClipboard(NULL))
+ return;
+
+ /* Check for vim's own clipboard format first. This only gets the type of
+ * the data, still need to use CF_UNICODETEXT or CF_TEXT for the text. */
+ if (IsClipboardFormatAvailable(cbd->format))
+ {
+ VimClipType_t *meta_p;
+ HGLOBAL meta_h;
+
+ /* We have metadata on the clipboard; try to get it. */
+ if ((meta_h = GetClipboardData(cbd->format)) != NULL
+ && (meta_p = (VimClipType_t *)GlobalLock(meta_h)) != NULL)
+ {
+ /* The size of "VimClipType_t" changed, "rawlen" was added later.
+ * Only copy what is available for backwards compatibility. */
+ n = sizeof(VimClipType_t);
+ if (GlobalSize(meta_h) < n)
+ n = GlobalSize(meta_h);
+ memcpy(&metadata, meta_p, n);
+ GlobalUnlock(meta_h);
+ }
+ }
+
+#ifdef FEAT_MBYTE
+ /* Check for Vim's raw clipboard format first. This is used without
+ * conversion, but only if 'encoding' matches. */
+ if (IsClipboardFormatAvailable(cbd->format_raw)
+ && metadata.rawlen > (int)STRLEN(p_enc))
+ {
+ /* We have raw data on the clipboard; try to get it. */
+ if ((rawh = GetClipboardData(cbd->format_raw)) != NULL)
+ {
+ char_u *rawp;
+
+ rawp = (char_u *)GlobalLock(rawh);
+ if (rawp != NULL && STRCMP(p_enc, rawp) == 0)
+ {
+ n = STRLEN(p_enc) + 1;
+ str = rawp + n;
+ str_size = metadata.rawlen - n;
+ }
+ else
+ {
+ GlobalUnlock(rawh);
+ rawh = NULL;
+ }
+ }
+ }
+ if (str == NULL)
+ {
+#endif
+
+#if defined(FEAT_MBYTE) && defined(WIN3264)
+ /* Try to get the clipboard in Unicode if it's not an empty string. */
+ if (IsClipboardFormatAvailable(CF_UNICODETEXT) && metadata.ucslen != 0)
+ {
+ HGLOBAL hMemW;
+
+ if ((hMemW = GetClipboardData(CF_UNICODETEXT)) != NULL)
+ {
+ WCHAR *hMemWstr = (WCHAR *)GlobalLock(hMemW);
+
+ /* Use the length of our metadata if possible, but limit it to the
+ * GlobalSize() for safety. */
+ maxlen = GlobalSize(hMemW) / sizeof(WCHAR);
+ if (metadata.ucslen >= 0)
+ {
+ if (metadata.ucslen > maxlen)
+ str_size = maxlen;
+ else
+ str_size = metadata.ucslen;
+ }
+ else
+ {
+ for (str_size = 0; str_size < maxlen; ++str_size)
+ if (hMemWstr[str_size] == NUL)
+ break;
+ }
+ to_free = str = ucs2_to_enc((short_u *)hMemWstr, &str_size);
+ GlobalUnlock(hMemW);
+ }
+ }
+ else
+#endif
+ /* Get the clipboard in the Active codepage. */
+ if (IsClipboardFormatAvailable(CF_TEXT))
+ {
+ if ((hMem = GetClipboardData(CF_TEXT)) != NULL)
+ {
+ str = hMemStr = (char_u *)GlobalLock(hMem);
+
+ /* The length is either what our metadata says or the strlen().
+ * But limit it to the GlobalSize() for safety. */
+ maxlen = GlobalSize(hMem);
+ if (metadata.txtlen >= 0)
+ {
+ if (metadata.txtlen > maxlen)
+ str_size = maxlen;
+ else
+ str_size = metadata.txtlen;
+ }
+ else
+ {
+ for (str_size = 0; str_size < maxlen; ++str_size)
+ if (str[str_size] == NUL)
+ break;
+ }
+
+#if defined(FEAT_MBYTE) && defined(WIN3264)
+ /* The text is in the active codepage. Convert to 'encoding',
+ * going through UCS-2. */
+ MultiByteToWideChar_alloc(GetACP(), 0, str, str_size,
+ (LPWSTR *)&to_free, &maxlen);
+ if (to_free != NULL)
+ {
+ str_size = maxlen;
+ str = ucs2_to_enc((short_u *)to_free, &str_size);
+ if (str != NULL)
+ {
+ vim_free(to_free);
+ to_free = str;
+ }
+ }
+#endif
+ }
+ }
+#ifdef FEAT_MBYTE
+ }
+#endif
+
+ if (str != NULL && *str != NUL)
+ {
+ char_u *temp_clipboard;
+
+ /* If the type is not known guess it. */
+ if (metadata.type == -1)
+ metadata.type = (vim_strchr(str, '\n') == NULL) ? MCHAR : MLINE;
+
+ /* Translate <CR><NL> into <NL>. */
+ temp_clipboard = crnl_to_nl(str, &str_size);
+ if (temp_clipboard != NULL)
+ {
+ clip_yank_selection(metadata.type, temp_clipboard, str_size, cbd);
+ vim_free(temp_clipboard);
+ }
+ }
+
+ /* unlock the global object */
+ if (hMem != NULL)
+ GlobalUnlock(hMem);
+#ifdef FEAT_MBYTE
+ if (rawh != NULL)
+ GlobalUnlock(rawh);
+#endif
+ CloseClipboard();
+#if defined(FEAT_MBYTE) && defined(WIN3264)
+ vim_free(to_free);
+#endif
+}
+
+/*
+ * Send the current selection to the clipboard.
+ */
+ void
+clip_mch_set_selection(VimClipboard *cbd)
+{
+ char_u *str = NULL;
+ VimClipType_t metadata;
+ long_u txtlen;
+ HGLOBAL hMemRaw = NULL;
+ HGLOBAL hMem = NULL;
+ HGLOBAL hMemVim = NULL;
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+ HGLOBAL hMemW = NULL;
+# endif
+
+ /* If the '*' register isn't already filled in, fill it in now */
+ cbd->owned = TRUE;
+ clip_get_selection(cbd);
+ cbd->owned = FALSE;
+
+ /* Get the text to be put on the clipboard, with CR-LF. */
+ metadata.type = clip_convert_selection(&str, &txtlen, cbd);
+ if (metadata.type < 0)
+ return;
+ metadata.txtlen = (int)txtlen;
+ metadata.ucslen = 0;
+ metadata.rawlen = 0;
+
+#ifdef FEAT_MBYTE
+ /* Always set the raw bytes: 'encoding', NUL and the text. This is used
+ * when copy/paste from/to Vim with the same 'encoding', so that illegal
+ * bytes can also be copied and no conversion is needed. */
+ {
+ LPSTR lpszMemRaw;
+
+ metadata.rawlen = txtlen + STRLEN(p_enc) + 1;
+ hMemRaw = (LPSTR)GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
+ metadata.rawlen + 1);
+ lpszMemRaw = (LPSTR)GlobalLock(hMemRaw);
+ if (lpszMemRaw != NULL)
+ {
+ STRCPY(lpszMemRaw, p_enc);
+ memcpy(lpszMemRaw + STRLEN(p_enc) + 1, str, txtlen + 1);
+ GlobalUnlock(hMemRaw);
+ }
+ else
+ metadata.rawlen = 0;
+ }
+#endif
+
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+ {
+ WCHAR *out;
+ int len = metadata.txtlen;
+
+ /* Convert the text to UCS-2. This is put on the clipboard as
+ * CF_UNICODETEXT. */
+ out = (WCHAR *)enc_to_ucs2(str, &len);
+ if (out != NULL)
+ {
+ WCHAR *lpszMemW;
+
+ /* Convert the text for CF_TEXT to Active codepage. Otherwise it's
+ * p_enc, which has no relation to the Active codepage. */
+ metadata.txtlen = WideCharToMultiByte(GetACP(), 0, out, len,
+ NULL, 0, 0, 0);
+ vim_free(str);
+ str = (char_u *)alloc((unsigned)(metadata.txtlen == 0 ? 1
+ : metadata.txtlen));
+ if (str == NULL)
+ {
+ vim_free(out);
+ return; /* out of memory */
+ }
+ WideCharToMultiByte(GetACP(), 0, out, len,
+ str, metadata.txtlen, 0, 0);
+
+ /* Allocate memory for the UCS-2 text, add one NUL word to
+ * terminate the string. */
+ hMemW = (LPSTR)GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
+ (len + 1) * sizeof(WCHAR));
+ lpszMemW = (WCHAR *)GlobalLock(hMemW);
+ if (lpszMemW != NULL)
+ {
+ memcpy(lpszMemW, out, len * sizeof(WCHAR));
+ lpszMemW[len] = NUL;
+ GlobalUnlock(hMemW);
+ }
+ vim_free(out);
+ metadata.ucslen = len;
+ }
+ }
+# endif
+
+ /* Allocate memory for the text, add one NUL byte to terminate the string.
+ */
+ hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, metadata.txtlen + 1);
+ {
+ LPSTR lpszMem = (LPSTR)GlobalLock(hMem);
+
+ if (lpszMem)
+ {
+ STRNCPY(lpszMem, str, metadata.txtlen);
+ lpszMem[metadata.txtlen] = NUL;
+ GlobalUnlock(hMem);
+ }
+ }
+
+ /* Set up metadata: */
+ {
+ VimClipType_t *lpszMemVim = NULL;
+
+ hMemVim = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
+ sizeof(VimClipType_t));
+ lpszMemVim = (VimClipType_t *)GlobalLock(hMemVim);
+ memcpy(lpszMemVim, &metadata, sizeof(metadata));
+ GlobalUnlock(hMemVim);
+ }
+
+ /*
+ * Open the clipboard, clear it and put our text on it.
+ * Always set our Vim format. Put Unicode and plain text on it.
+ *
+ * Don't pass GetActiveWindow() as an argument to OpenClipboard()
+ * because then we can't paste back into the same window for some
+ * reason - webb.
+ */
+ if (OpenClipboard(NULL))
+ {
+ if (EmptyClipboard())
+ {
+ SetClipboardData(cbd->format, hMemVim);
+ hMemVim = 0;
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+ if (hMemW != NULL)
+ {
+ if (SetClipboardData(CF_UNICODETEXT, hMemW) != NULL)
+ hMemW = NULL;
+ }
+# endif
+ /* Always use CF_TEXT. On Win98 Notepad won't obtain the
+ * CF_UNICODETEXT text, only CF_TEXT. */
+ SetClipboardData(CF_TEXT, hMem);
+ hMem = 0;
+ }
+ CloseClipboard();
+ }
+
+ vim_free(str);
+ /* Free any allocations we didn't give to the clipboard: */
+ if (hMemRaw)
+ GlobalFree(hMemRaw);
+ if (hMem)
+ GlobalFree(hMem);
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+ if (hMemW)
+ GlobalFree(hMemW);
+# endif
+ if (hMemVim)
+ GlobalFree(hMemVim);
+}
+
+#endif /* FEAT_CLIPBOARD */
+
+
+/*
+ * Debugging helper: expose the MCH_WRITE_DUMP stuff to other modules
+ */
+ void
+DumpPutS(
+ const char *psz)
+{
+# ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ {
+ fputs(psz, fdDump);
+ if (psz[strlen(psz) - 1] != '\n')
+ fputc('\n', fdDump);
+ fflush(fdDump);
+ }
+# endif
+}
+
+#ifdef _DEBUG
+
+void __cdecl
+Trace(
+ char *pszFormat,
+ ...)
+{
+ CHAR szBuff[2048];
+ va_list args;
+
+ va_start(args, pszFormat);
+ vsprintf(szBuff, pszFormat, args);
+ va_end(args);
+
+ OutputDebugString(szBuff);
+}
+
+#endif //_DEBUG
+
+#ifdef HAVE_GETCONSOLEHWND
+# if defined(FEAT_TITLE) && defined(WIN3264)
+extern HWND g_hWnd; /* This is in os_win32.c. */
+# endif
+
+/*
+ * Showing the printer dialog is tricky since we have no GUI
+ * window to parent it. The following routines are needed to
+ * get the window parenting and Z-order to work properly.
+ */
+ static void
+GetConsoleHwnd(void)
+{
+# define MY_BUFSIZE 1024 // Buffer size for console window titles.
+
+ char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated WindowTitle.
+ char pszOldWindowTitle[MY_BUFSIZE]; // Contains original WindowTitle.
+
+ /* Skip if it's already set. */
+ if (s_hwnd != 0)
+ return;
+
+# if defined(FEAT_TITLE) && defined(WIN3264)
+ /* Window handle may have been found by init code (Windows NT only) */
+ if (g_hWnd != 0)
+ {
+ s_hwnd = g_hWnd;
+ return;
+ }
+# endif
+
+ GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
+
+ wsprintf(pszNewWindowTitle, "%s/%d/%d",
+ pszOldWindowTitle,
+ GetTickCount(),
+ GetCurrentProcessId());
+ SetConsoleTitle(pszNewWindowTitle);
+ Sleep(40);
+ s_hwnd = FindWindow(NULL, pszNewWindowTitle);
+
+ SetConsoleTitle(pszOldWindowTitle);
+}
+#endif
+
+#if (defined(FEAT_PRINTER) && !defined(FEAT_POSTSCRIPT)) || defined(PROTO)
+
+# ifdef WIN16
+# define TEXT(a) a
+# endif
+/*=================================================================
+ * Win32 printer stuff
+ */
+
+static HFONT prt_font_handles[2][2][2];
+static PRINTDLG prt_dlg;
+static const int boldface[2] = {FW_REGULAR, FW_BOLD};
+static TEXTMETRIC prt_tm;
+static int prt_line_height;
+static int prt_number_width;
+static int prt_left_margin;
+static int prt_right_margin;
+static int prt_top_margin;
+static char_u szAppName[] = TEXT("VIM");
+static HWND hDlgPrint;
+static int *bUserAbort = NULL;
+static char_u *prt_name = NULL;
+
+/* Defines which are also in vim.rc. */
+#define IDC_BOX1 400
+#define IDC_PRINTTEXT1 401
+#define IDC_PRINTTEXT2 402
+#define IDC_PROGRESS 403
+
+/*
+ * Convert BGR to RGB for Windows GDI calls
+ */
+ static COLORREF
+swap_me(COLORREF colorref)
+{
+ int temp;
+ char *ptr = (char *)&colorref;
+
+ temp = *(ptr);
+ *(ptr ) = *(ptr + 2);
+ *(ptr + 2) = temp;
+ return colorref;
+}
+
+ static BOOL CALLBACK
+PrintDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+#ifdef FEAT_GETTEXT
+ NONCLIENTMETRICS nm;
+ static HFONT hfont;
+#endif
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+#ifdef FEAT_GETTEXT
+ nm.cbSize = sizeof(NONCLIENTMETRICS);
+ if (SystemParametersInfo(
+ SPI_GETNONCLIENTMETRICS,
+ sizeof(NONCLIENTMETRICS),
+ &nm,
+ 0))
+ {
+ char buff[MAX_PATH];
+ int i;
+
+ /* Translate the dialog texts */
+ hfont = CreateFontIndirect(&nm.lfMessageFont);
+ for (i = IDC_PRINTTEXT1; i <= IDC_PROGRESS; i++)
+ {
+ SendDlgItemMessage(hDlg, i, WM_SETFONT, (WPARAM)hfont, 1);
+ if (GetDlgItemText(hDlg,i, buff, sizeof(buff)))
+ SetDlgItemText(hDlg,i, _(buff));
+ }
+ SendDlgItemMessage(hDlg, IDCANCEL,
+ WM_SETFONT, (WPARAM)hfont, 1);
+ if (GetDlgItemText(hDlg,IDCANCEL, buff, sizeof(buff)))
+ SetDlgItemText(hDlg,IDCANCEL, _(buff));
+ }
+#endif
+ SetWindowText(hDlg, szAppName);
+ if (prt_name != NULL)
+ {
+ SetDlgItemText(hDlg, IDC_PRINTTEXT2, (LPSTR)prt_name);
+ vim_free(prt_name);
+ prt_name = NULL;
+ }
+ EnableMenuItem(GetSystemMenu(hDlg, FALSE), SC_CLOSE, MF_GRAYED);
+#ifndef FEAT_GUI
+ BringWindowToTop(s_hwnd);
+#endif
+ return TRUE;
+
+ case WM_COMMAND:
+ *bUserAbort = TRUE;
+ EnableWindow(GetParent(hDlg), TRUE);
+ DestroyWindow(hDlg);
+ hDlgPrint = NULL;
+#ifdef FEAT_GETTEXT
+ DeleteObject(hfont);
+#endif
+ return TRUE;
+ }
+ return FALSE;
+}
+
+ static BOOL CALLBACK
+AbortProc(HDC hdcPrn, int iCode)
+{
+ MSG msg;
+
+ while (!*bUserAbort && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ if (!hDlgPrint || !IsDialogMessage(hDlgPrint, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ return !*bUserAbort;
+}
+
+#ifndef FEAT_GUI
+
+ static UINT CALLBACK
+PrintHookProc(
+ HWND hDlg, // handle to dialog box
+ UINT uiMsg, // message identifier
+ WPARAM wParam, // message parameter
+ LPARAM lParam // message parameter
+ )
+{
+ HWND hwndOwner;
+ RECT rc, rcDlg, rcOwner;
+ PRINTDLG *pPD;
+
+ if (uiMsg == WM_INITDIALOG)
+ {
+ // Get the owner window and dialog box rectangles.
+ if ((hwndOwner = GetParent(hDlg)) == NULL)
+ hwndOwner = GetDesktopWindow();
+
+ GetWindowRect(hwndOwner, &rcOwner);
+ GetWindowRect(hDlg, &rcDlg);
+ CopyRect(&rc, &rcOwner);
+
+ // Offset the owner and dialog box rectangles so that
+ // right and bottom values represent the width and
+ // height, and then offset the owner again to discard
+ // space taken up by the dialog box.
+
+ OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
+ OffsetRect(&rc, -rc.left, -rc.top);
+ OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
+
+ // The new position is the sum of half the remaining
+ // space and the owner's original position.
+
+ SetWindowPos(hDlg,
+ HWND_TOP,
+ rcOwner.left + (rc.right / 2),
+ rcOwner.top + (rc.bottom / 2),
+ 0, 0, // ignores size arguments
+ SWP_NOSIZE);
+
+ /* tackle the printdlg copiesctrl problem */
+ pPD = (PRINTDLG *)lParam;
+ pPD->nCopies = (WORD)pPD->lCustData;
+ SetDlgItemInt( hDlg, edt3, pPD->nCopies, FALSE );
+ /* Bring the window to top */
+ BringWindowToTop(GetParent(hDlg));
+ SetForegroundWindow(hDlg);
+ }
+
+ return FALSE;
+}
+#endif
+
+ void
+mch_print_cleanup(void)
+{
+ int pifItalic;
+ int pifBold;
+ int pifUnderline;
+
+ for (pifBold = 0; pifBold <= 1; pifBold++)
+ for (pifItalic = 0; pifItalic <= 1; pifItalic++)
+ for (pifUnderline = 0; pifUnderline <= 1; pifUnderline++)
+ DeleteObject(prt_font_handles[pifBold][pifItalic][pifUnderline]);
+
+ if (prt_dlg.hDC != NULL)
+ DeleteDC(prt_dlg.hDC);
+ if (!*bUserAbort)
+ SendMessage(hDlgPrint, WM_COMMAND, 0, 0);
+}
+
+ static int
+to_device_units(int idx, int dpi, int physsize, int offset, int def_number)
+{
+ int ret = 0;
+ int u;
+ int nr;
+
+ u = prt_get_unit(idx);
+ if (u == PRT_UNIT_NONE)
+ {
+ u = PRT_UNIT_PERC;
+ nr = def_number;
+ }
+ else
+ nr = printer_opts[idx].number;
+
+ switch (u)
+ {
+ case PRT_UNIT_PERC:
+ ret = (physsize * nr) / 100;
+ break;
+ case PRT_UNIT_INCH:
+ ret = (nr * dpi);
+ break;
+ case PRT_UNIT_MM:
+ ret = (nr * 10 * dpi) / 254;
+ break;
+ case PRT_UNIT_POINT:
+ ret = (nr * 10 * dpi) / 720;
+ break;
+ }
+
+ if (ret < offset)
+ return 0;
+ else
+ return ret - offset;
+}
+
+ static int
+prt_get_cpl(void)
+{
+ int hr;
+ int phyw;
+ int dvoff;
+ int rev_offset;
+ int dpi;
+#ifdef WIN16
+ POINT pagesize;
+#endif
+
+ GetTextMetrics(prt_dlg.hDC, &prt_tm);
+ prt_line_height = prt_tm.tmHeight + prt_tm.tmExternalLeading;
+
+ hr = GetDeviceCaps(prt_dlg.hDC, HORZRES);
+#ifdef WIN16
+ Escape(prt_dlg.hDC, GETPHYSPAGESIZE, NULL, NULL, &pagesize);
+ phyw = pagesize.x;
+ Escape(prt_dlg.hDC, GETPRINTINGOFFSET, NULL, NULL, &pagesize);
+ dvoff = pagesize.x;
+#else
+ phyw = GetDeviceCaps(prt_dlg.hDC, PHYSICALWIDTH);
+ dvoff = GetDeviceCaps(prt_dlg.hDC, PHYSICALOFFSETX);
+#endif
+ dpi = GetDeviceCaps(prt_dlg.hDC, LOGPIXELSX);
+
+ rev_offset = phyw - (dvoff + hr);
+
+ prt_left_margin = to_device_units(OPT_PRINT_LEFT, dpi, phyw, dvoff, 10);
+ if (prt_use_number())
+ {
+ prt_number_width = PRINT_NUMBER_WIDTH * prt_tm.tmAveCharWidth;
+ prt_left_margin += prt_number_width;
+ }
+ else
+ prt_number_width = 0;
+
+ prt_right_margin = hr - to_device_units(OPT_PRINT_RIGHT, dpi, phyw,
+ rev_offset, 5);
+
+ return (prt_right_margin - prt_left_margin) / prt_tm.tmAveCharWidth;
+}
+
+ static int
+prt_get_lpp(void)
+{
+ int vr;
+ int phyw;
+ int dvoff;
+ int rev_offset;
+ int bottom_margin;
+ int dpi;
+#ifdef WIN16
+ POINT pagesize;
+#endif
+
+ vr = GetDeviceCaps(prt_dlg.hDC, VERTRES);
+#ifdef WIN16
+ Escape(prt_dlg.hDC, GETPHYSPAGESIZE, NULL, NULL, &pagesize);
+ phyw = pagesize.y;
+ Escape(prt_dlg.hDC, GETPRINTINGOFFSET, NULL, NULL, &pagesize);
+ dvoff = pagesize.y;
+#else
+ phyw = GetDeviceCaps(prt_dlg.hDC, PHYSICALHEIGHT);
+ dvoff = GetDeviceCaps(prt_dlg.hDC, PHYSICALOFFSETY);
+#endif
+ dpi = GetDeviceCaps(prt_dlg.hDC, LOGPIXELSY);
+
+ rev_offset = phyw - (dvoff + vr);
+
+ prt_top_margin = to_device_units(OPT_PRINT_TOP, dpi, phyw, dvoff, 5);
+
+ /* adjust top margin if there is a header */
+ prt_top_margin += prt_line_height * prt_header_height();
+
+ bottom_margin = vr - to_device_units(OPT_PRINT_BOT, dpi, phyw,
+ rev_offset, 5);
+
+ return (bottom_margin - prt_top_margin) / prt_line_height;
+}
+
+ int
+mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
+{
+ static HGLOBAL stored_dm = NULL;
+ static HGLOBAL stored_devn = NULL;
+ static int stored_nCopies = 1;
+ static int stored_nFlags = 0;
+
+ LOGFONT fLogFont;
+ int pifItalic;
+ int pifBold;
+ int pifUnderline;
+
+ DEVMODE *mem;
+ DEVNAMES *devname;
+ int i;
+
+ bUserAbort = &(psettings->user_abort);
+ memset(&prt_dlg, 0, sizeof(PRINTDLG));
+ prt_dlg.lStructSize = sizeof(PRINTDLG);
+#ifndef FEAT_GUI
+ GetConsoleHwnd(); /* get value of s_hwnd */
+#endif
+ prt_dlg.hwndOwner = s_hwnd;
+ prt_dlg.Flags = PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC;
+ if (!forceit)
+ {
+ prt_dlg.hDevMode = stored_dm;
+ prt_dlg.hDevNames = stored_devn;
+ prt_dlg.lCustData = stored_nCopies; // work around bug in print dialog
+#ifndef FEAT_GUI
+ /*
+ * Use hook to prevent console window being sent to back
+ */
+ prt_dlg.lpfnPrintHook = PrintHookProc;
+ prt_dlg.Flags |= PD_ENABLEPRINTHOOK;
+#endif
+ prt_dlg.Flags |= stored_nFlags;
+ }
+
+ /*
+ * If bang present, return default printer setup with no dialog
+ * never show dialog if we are running over telnet
+ */
+ if (forceit
+#ifndef FEAT_GUI
+ || !term_console
+#endif
+ )
+ {
+ prt_dlg.Flags |= PD_RETURNDEFAULT;
+#ifdef WIN3264
+ /*
+ * MSDN suggests setting the first parameter to WINSPOOL for
+ * NT, but NULL appears to work just as well.
+ */
+ if (*p_pdev != NUL)
+ prt_dlg.hDC = CreateDC(NULL, p_pdev, NULL, NULL);
+ else
+#endif
+ {
+ prt_dlg.Flags |= PD_RETURNDEFAULT;
+ if (PrintDlg(&prt_dlg) == 0)
+ goto init_fail_dlg;
+ }
+ }
+ else if (PrintDlg(&prt_dlg) == 0)
+ goto init_fail_dlg;
+ else
+ {
+ /*
+ * keep the previous driver context
+ */
+ stored_dm = prt_dlg.hDevMode;
+ stored_devn = prt_dlg.hDevNames;
+ stored_nFlags = prt_dlg.Flags;
+ stored_nCopies = prt_dlg.nCopies;
+ }
+
+ if (prt_dlg.hDC == NULL)
+ {
+ EMSG(_("E237: Printer selection failed"));
+ mch_print_cleanup();
+ return FALSE;
+ }
+
+ /* Not all printer drivers report the support of color (or grey) in the
+ * same way. Let's set has_color if there appears to be some way to print
+ * more than B&W. */
+ i = GetDeviceCaps(prt_dlg.hDC, NUMCOLORS);
+ psettings->has_color = (GetDeviceCaps(prt_dlg.hDC, BITSPIXEL) > 1
+ || GetDeviceCaps(prt_dlg.hDC, PLANES) > 1
+ || i > 2 || i == -1);
+
+ /* Ensure all font styles are baseline aligned */
+ SetTextAlign(prt_dlg.hDC, TA_BASELINE|TA_LEFT);
+
+ /*
+ * On some windows systems the nCopies parameter is not
+ * passed back correctly. It must be retrieved from the
+ * hDevMode struct.
+ */
+ mem = (DEVMODE *)GlobalLock(prt_dlg.hDevMode);
+ if (mem != NULL)
+ {
+#ifdef WIN3264
+ if (mem->dmCopies != 1)
+ stored_nCopies = mem->dmCopies;
+#endif
+ if ((mem->dmFields & DM_DUPLEX) && (mem->dmDuplex & ~DMDUP_SIMPLEX))
+ psettings->duplex = TRUE;
+ if ((mem->dmFields & DM_COLOR) && (mem->dmColor & DMCOLOR_COLOR))
+ psettings->has_color = TRUE;
+ }
+ GlobalUnlock(prt_dlg.hDevMode);
+
+ devname = (DEVNAMES *)GlobalLock(prt_dlg.hDevNames);
+ if (devname != 0)
+ {
+ char_u *printer_name = (char_u *)devname + devname->wDeviceOffset;
+ char_u *port_name = (char_u *)devname +devname->wOutputOffset;
+ char_u *text = _("to %s on %s");
+
+ prt_name = alloc(STRLEN(printer_name) + STRLEN(port_name)
+ + STRLEN(text));
+ if (prt_name != NULL)
+ wsprintf(prt_name, text, printer_name, port_name);
+ }
+ GlobalUnlock(prt_dlg.hDevNames);
+
+ /*
+ * Initialise the font according to 'printfont'
+ */
+ memset(&fLogFont, 0, sizeof(fLogFont));
+ if (!get_logfont(&fLogFont, p_pfn, prt_dlg.hDC))
+ {
+ EMSG2(_("E613: Unknown printer font: %s"), p_pfn);
+ mch_print_cleanup();
+ return FALSE;
+ }
+
+ for (pifBold = 0; pifBold <= 1; pifBold++)
+ for (pifItalic = 0; pifItalic <= 1; pifItalic++)
+ for (pifUnderline = 0; pifUnderline <= 1; pifUnderline++)
+ {
+ fLogFont.lfWeight = boldface[pifBold];
+ fLogFont.lfItalic = pifItalic;
+ fLogFont.lfUnderline = pifUnderline;
+ prt_font_handles[pifBold][pifItalic][pifUnderline]
+ = CreateFontIndirect(&fLogFont);
+ }
+
+ SetBkMode(prt_dlg.hDC, OPAQUE);
+ SelectObject(prt_dlg.hDC, prt_font_handles[0][0][0]);
+
+ /*
+ * Fill in the settings struct
+ */
+ psettings->chars_per_line = prt_get_cpl();
+ psettings->lines_per_page = prt_get_lpp();
+ psettings->n_collated_copies = (prt_dlg.Flags & PD_COLLATE)
+ ? prt_dlg.nCopies : 1;
+ psettings->n_uncollated_copies = (prt_dlg.Flags & PD_COLLATE)
+ ? 1 : prt_dlg.nCopies;
+
+ if (psettings->n_collated_copies == 0)
+ psettings->n_collated_copies = 1;
+
+ if (psettings->n_uncollated_copies == 0)
+ psettings->n_uncollated_copies = 1;
+
+ psettings->jobname = jobname;
+
+ return TRUE;
+
+init_fail_dlg:
+ {
+ DWORD err = CommDlgExtendedError();
+
+ if (err)
+ {
+#ifdef WIN16
+ char buf[20];
+
+ sprintf(buf, "%ld", err);
+ EMSG2(_("E238: Print error: %s"), buf);
+#else
+ char_u *buf;
+
+ /* I suspect FormatMessage() doesn't work for values returned by
+ * CommDlgExtendedError(). What does? */
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, 0, (LPTSTR)(&buf), 0, NULL);
+ EMSG2(_("E238: Print error: %s"),
+ buf == NULL ? (char_u *)_("Unknown") : buf);
+ LocalFree((LPVOID)(buf));
+#endif
+ }
+ else
+ msg_clr_eos(); /* Maybe canceled */
+
+ mch_print_cleanup();
+ return FALSE;
+ }
+}
+
+
+ int
+mch_print_begin(prt_settings_T *psettings)
+{
+ int ret;
+ static DOCINFO di;
+ char szBuffer[300];
+
+ hDlgPrint = CreateDialog(GetModuleHandle(NULL), TEXT("PrintDlgBox"),
+ prt_dlg.hwndOwner, PrintDlgProc);
+#ifdef WIN16
+ Escape(prt_dlg.hDC, SETABORTPROC, 0, (LPSTR)AbortProc, NULL);
+#else
+ SetAbortProc(prt_dlg.hDC, AbortProc);
+#endif
+ wsprintf(szBuffer, _("Printing '%s'"), gettail(psettings->jobname));
+ SetDlgItemText(hDlgPrint, IDC_PRINTTEXT1, (LPSTR)szBuffer);
+
+ memset(&di, 0, sizeof(DOCINFO));
+ di.cbSize = sizeof(DOCINFO);
+ di.lpszDocName = psettings->jobname;
+ ret = StartDoc(prt_dlg.hDC, &di);
+
+#ifdef FEAT_GUI
+ /* Give focus back to main window (when using MDI). */
+ SetFocus(s_hwnd);
+#endif
+
+ return (ret > 0);
+}
+
+ void
+mch_print_end(prt_settings_T *psettings)
+{
+ EndDoc(prt_dlg.hDC);
+ if (!*bUserAbort)
+ SendMessage(hDlgPrint, WM_COMMAND, 0, 0);
+}
+
+ int
+mch_print_end_page(void)
+{
+ return (EndPage(prt_dlg.hDC) > 0);
+}
+
+ int
+mch_print_begin_page(char_u *msg)
+{
+ if (msg != NULL)
+ SetDlgItemText(hDlgPrint, IDC_PROGRESS, (LPSTR)msg);
+ return (StartPage(prt_dlg.hDC) > 0);
+}
+
+ int
+mch_print_blank_page(void)
+{
+ return (mch_print_begin_page(NULL) ? (mch_print_end_page()) : FALSE);
+}
+
+static int prt_pos_x = 0;
+static int prt_pos_y = 0;
+
+ void
+mch_print_start_line(margin, page_line)
+ int margin;
+ int page_line;
+{
+ if (margin)
+ prt_pos_x = -prt_number_width;
+ else
+ prt_pos_x = 0;
+ prt_pos_y = page_line * prt_line_height
+ + prt_tm.tmAscent + prt_tm.tmExternalLeading;
+}
+
+ int
+mch_print_text_out(char_u *p, int len)
+{
+#ifdef FEAT_PROPORTIONAL_FONTS
+ SIZE sz;
+#endif
+
+ TextOut(prt_dlg.hDC, prt_pos_x + prt_left_margin,
+ prt_pos_y + prt_top_margin, p, len);
+#ifndef FEAT_PROPORTIONAL_FONTS
+ prt_pos_x += len * prt_tm.tmAveCharWidth;
+ return (prt_pos_x + prt_left_margin + prt_tm.tmAveCharWidth
+ + prt_tm.tmOverhang > prt_right_margin);
+#else
+# ifdef WIN16
+ GetTextExtentPoint(prt_dlg.hDC, p, len, &sz);
+# else
+ GetTextExtentPoint32(prt_dlg.hDC, p, len, &sz);
+# endif
+ prt_pos_x += (sz.cx - prt_tm.tmOverhang);
+ /* This is wrong when printing spaces for a TAB. */
+ if (p[len] == NUL)
+ return FALSE;
+# ifdef WIN16
+ GetTextExtentPoint(prt_dlg.hDC, p + len, 1, &sz);
+# else
+ GetTextExtentPoint32(prt_dlg.hDC, p + len, 1, &sz);
+# endif
+ return (prt_pos_x + prt_left_margin + sz.cx > prt_right_margin);
+#endif
+}
+
+ void
+mch_print_set_font(int iBold, int iItalic, int iUnderline)
+{
+ SelectObject(prt_dlg.hDC, prt_font_handles[iBold][iItalic][iUnderline]);
+}
+
+ void
+mch_print_set_bg(unsigned long bgcol)
+{
+ SetBkColor(prt_dlg.hDC, GetNearestColor(prt_dlg.hDC, swap_me(bgcol)));
+ /*
+ * With a white background we can draw characters transparent, which is
+ * good for italic characters that overlap to the next char cell.
+ */
+ if (bgcol == 0xffffffUL)
+ SetBkMode(prt_dlg.hDC, TRANSPARENT);
+ else
+ SetBkMode(prt_dlg.hDC, OPAQUE);
+}
+
+ void
+mch_print_set_fg(unsigned long fgcol)
+{
+ SetTextColor(prt_dlg.hDC, GetNearestColor(prt_dlg.hDC, swap_me(fgcol)));
+}
+
+#endif /*FEAT_PRINTER && !FEAT_POSTSCRIPT*/
+
+#if defined(FEAT_SHORTCUT) || defined(PROTO)
+# include <shlobj.h>
+
+/*
+ * When "fname" is the name of a shortcut (*.lnk) resolve the file it points
+ * to and return that name in allocated memory.
+ * Otherwise NULL is returned.
+ */
+ char_u *
+mch_resolve_shortcut(char_u *fname)
+{
+ HRESULT hr;
+ IShellLink *psl = NULL;
+ IPersistFile *ppf = NULL;
+ OLECHAR wsz[MAX_PATH];
+ WIN32_FIND_DATA ffd; // we get those free of charge
+ TCHAR buf[MAX_PATH]; // could have simply reused 'wsz'...
+ char_u *rfname = NULL;
+ int len;
+
+ /* Check if the file name ends in ".lnk". Avoid calling
+ * CoCreateInstance(), it's quite slow. */
+ if (fname == NULL)
+ return rfname;
+ len = STRLEN(fname);
+ if (len <= 4 || STRNICMP(fname + len - 4, ".lnk", 4) != 0)
+ return rfname;
+
+ CoInitialize(NULL);
+
+ // create a link manager object and request its interface
+ hr = CoCreateInstance(
+ &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IShellLink, (void**)&psl);
+ if (hr != S_OK)
+ goto shortcut_error;
+
+ // Get a pointer to the IPersistFile interface.
+ hr = psl->lpVtbl->QueryInterface(
+ psl, &IID_IPersistFile, (void**)&ppf);
+ if (hr != S_OK)
+ goto shortcut_error;
+
+ // full path string must be in Unicode.
+ MultiByteToWideChar(CP_ACP, 0, fname, -1, wsz, MAX_PATH);
+
+ // "load" the name and resove the link
+ hr = ppf->lpVtbl->Load(ppf, wsz, STGM_READ);
+ if (hr != S_OK)
+ goto shortcut_error;
+#if 0 // This makes Vim wait a long time if the target doesn't exist.
+ hr = psl->lpVtbl->Resolve(psl, NULL, SLR_NO_UI);
+ if (hr != S_OK)
+ goto shortcut_error;
+#endif
+
+ // Get the path to the link target.
+ ZeroMemory(buf, MAX_PATH);
+ hr = psl->lpVtbl->GetPath(psl, buf, MAX_PATH, &ffd, 0);
+ if (hr == S_OK && buf[0] != NUL)
+ rfname = vim_strsave(buf);
+
+shortcut_error:
+ // Release all interface pointers (both belong to the same object)
+ if (ppf != NULL)
+ ppf->lpVtbl->Release(ppf);
+ if (psl != NULL)
+ psl->lpVtbl->Release(psl);
+
+ CoUninitialize();
+ return rfname;
+}
+#endif
+
+#if (defined(FEAT_EVAL) && !defined(FEAT_GUI)) || defined(PROTO)
+/*
+ * Bring ourselves to the foreground. Does work if the OS doesn't allow it.
+ */
+ void
+win32_set_foreground()
+{
+# ifndef FEAT_GUI
+ GetConsoleHwnd(); /* get value of s_hwnd */
+# endif
+ if (s_hwnd != 0)
+ SetForegroundWindow(s_hwnd);
+}
+#endif
+
+#if defined(FEAT_CLIENTSERVER) || defined(PROTO)
+/*
+ * Client-server code for Vim
+ *
+ * Originally written by Paul Moore
+ */
+
+/* In order to handle inter-process messages, we need to have a window. But
+ * the functions in this module can be called before the main GUI window is
+ * created (and may also be called in the console version, where there is no
+ * GUI window at all).
+ *
+ * So we create a hidden window, and arrange to destroy it on exit.
+ */
+HWND message_window = 0; /* window that's handling messsages */
+
+#define VIM_CLASSNAME "VIM_MESSAGES"
+#define VIM_CLASSNAME_LEN (sizeof(VIM_CLASSNAME) - 1)
+
+/* Communication is via WM_COPYDATA messages. The message type is send in
+ * the dwData parameter. Types are defined here. */
+#define COPYDATA_KEYS 0
+#define COPYDATA_REPLY 1
+#define COPYDATA_EXPR 10
+#define COPYDATA_RESULT 11
+#define COPYDATA_ERROR_RESULT 12
+
+/* This is a structure containing a server HWND and its name. */
+struct server_id
+{
+ HWND hwnd;
+ char_u *name;
+};
+
+/*
+ * Clean up on exit. This destroys the hidden message window.
+ */
+ static void
+#ifdef __BORLANDC__
+ _RTLENTRYF
+#endif
+CleanUpMessaging(void)
+{
+ if (message_window != 0)
+ {
+ DestroyWindow(message_window);
+ message_window = 0;
+ }
+}
+
+static int save_reply(HWND server, char_u *reply, int expr);
+
+/*s
+ * The window procedure for the hidden message window.
+ * It handles callback messages and notifications from servers.
+ * In order to process these messages, it is necessary to run a
+ * message loop. Code which may run before the main message loop
+ * is started (in the GUI) is careful to pump messages when it needs
+ * to. Features which require message delivery during normal use will
+ * not work in the console version - this basically means those
+ * features which allow Vim to act as a server, rather than a client.
+ */
+ static LRESULT CALLBACK
+Messaging_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (msg == WM_COPYDATA)
+ {
+ /* This is a message from another Vim. The dwData member of the
+ * COPYDATASTRUCT determines the type of message:
+ * COPYDATA_KEYS:
+ * A key sequence. We are a server, and a client wants these keys
+ * adding to the input queue.
+ * COPYDATA_REPLY:
+ * A reply. We are a client, and a server has sent this message
+ * in response to a request. (server2client())
+ * COPYDATA_EXPR:
+ * An expression. We are a server, and a client wants us to
+ * evaluate this expression.
+ * COPYDATA_RESULT:
+ * A reply. We are a client, and a server has sent this message
+ * in response to a COPYDATA_EXPR.
+ * COPYDATA_ERROR_RESULT:
+ * A reply. We are a client, and a server has sent this message
+ * in response to a COPYDATA_EXPR that failed to evaluate.
+ */
+ COPYDATASTRUCT *data = (COPYDATASTRUCT*)lParam;
+ HWND sender = (HWND)wParam;
+ COPYDATASTRUCT reply;
+ char_u *res;
+ char_u winstr[30];
+ int retval;
+
+ switch (data->dwData)
+ {
+ case COPYDATA_KEYS:
+ /* Remember who sent this, for <client> */
+ clientWindow = sender;
+
+ /* Add the received keys to the input buffer. The loop waiting
+ * for the user to do something should check the input buffer. */
+ server_to_input_buf((char_u *)(data->lpData));
+
+# ifdef FEAT_GUI
+ /* Wake up the main GUI loop. */
+ if (s_hwnd != 0)
+ PostMessage(s_hwnd, WM_NULL, 0, 0);
+# endif
+ return 1;
+
+ case COPYDATA_EXPR:
+ /* Remember who sent this, for <client> */
+ clientWindow = sender;
+
+ res = eval_client_expr_to_string(data->lpData);
+ if (res == NULL)
+ {
+ res = vim_strsave(_(e_invexprmsg));
+ reply.dwData = COPYDATA_ERROR_RESULT;
+ }
+ else
+ reply.dwData = COPYDATA_RESULT;
+ reply.lpData = res;
+ reply.cbData = STRLEN(res) + 1;
+
+ retval = SendMessage(sender, WM_COPYDATA, (WPARAM)message_window,
+ (LPARAM)(&reply));
+ vim_free(res);
+ return retval;
+
+ case COPYDATA_REPLY:
+ case COPYDATA_RESULT:
+ case COPYDATA_ERROR_RESULT:
+ if (data->lpData != NULL)
+ {
+ save_reply(sender, data->lpData,
+ (data->dwData == COPYDATA_REPLY ? 0 :
+ (data->dwData == COPYDATA_RESULT ? 1 :
+ 2)));
+#ifdef FEAT_AUTOCMD
+ if (data->dwData == COPYDATA_REPLY)
+ {
+ sprintf((char *)winstr, "0x%x", (unsigned)sender);
+ apply_autocmds(EVENT_REMOTEREPLY, winstr, data->lpData,
+ TRUE, curbuf);
+ }
+#endif
+ }
+ return 1;
+ }
+
+ return 0;
+ }
+
+ else if (msg == WM_ACTIVATE && wParam == WA_ACTIVE)
+ {
+ /* When the message window is activated (brought to the foreground),
+ * this actually applies to the text window. */
+#ifndef FEAT_GUI
+ GetConsoleHwnd(); /* get value of s_hwnd */
+#endif
+ if (s_hwnd != 0)
+ {
+ SetForegroundWindow(s_hwnd);
+ return 0;
+ }
+ }
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+/*
+ * Initialise the message handling process. This involves creating a window
+ * to handle messages - the window will not be visible.
+ */
+ void
+serverInitMessaging(void)
+{
+ WNDCLASS wndclass;
+ HINSTANCE s_hinst;
+
+ /* Clean up on exit */
+ atexit(CleanUpMessaging);
+
+ /* Register a window class - we only really care
+ * about the window procedure
+ */
+ s_hinst = (HINSTANCE)GetModuleHandle(0);
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = Messaging_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = s_hinst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = NULL;
+ wndclass.hbrBackground = NULL;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = VIM_CLASSNAME;
+ RegisterClass(&wndclass);
+
+ /* Create the message window. It will be hidden, so the details don't
+ * matter. Don't use WS_OVERLAPPEDWINDOW, it will make a shortcut remove
+ * focus from gvim. */
+ message_window = CreateWindow(VIM_CLASSNAME, "",
+ WS_POPUPWINDOW | WS_CAPTION,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ 100, 100, NULL, NULL,
+ s_hinst, NULL);
+}
+
+/*
+ * Get the title of the window "hwnd", which is the Vim server name, in
+ * "name[namelen]" and return the length.
+ * Returns zero if window "hwnd" is not a Vim server.
+ */
+ static int
+getVimServerName(HWND hwnd, char *name, int namelen)
+{
+ int len;
+ char buffer[VIM_CLASSNAME_LEN + 1];
+
+ /* Ignore windows which aren't Vim message windows */
+ len = GetClassName(hwnd, buffer, sizeof(buffer));
+ if (len != VIM_CLASSNAME_LEN || STRCMP(buffer, VIM_CLASSNAME) != 0)
+ return 0;
+
+ /* Get the title of the window */
+ return GetWindowText(hwnd, name, namelen);
+}
+
+ static BOOL CALLBACK
+enumWindowsGetServer(HWND hwnd, LPARAM lparam)
+{
+ struct server_id *id = (struct server_id *)lparam;
+ char server[MAX_PATH];
+
+ /* Get the title of the window */
+ if (getVimServerName(hwnd, server, sizeof(server)) == 0)
+ return TRUE;
+
+ /* If this is the server we're looking for, return its HWND */
+ if (STRICMP(server, id->name) == 0)
+ {
+ id->hwnd = hwnd;
+ return FALSE;
+ }
+
+ /* Otherwise, keep looking */
+ return TRUE;
+}
+
+ static BOOL CALLBACK
+enumWindowsGetNames(HWND hwnd, LPARAM lparam)
+{
+ garray_T *ga = (garray_T *)lparam;
+ char server[MAX_PATH];
+
+ /* Get the title of the window */
+ if (getVimServerName(hwnd, server, sizeof(server)) == 0)
+ return TRUE;
+
+ /* Add the name to the list */
+ ga_concat(ga, server);
+ ga_concat(ga, "\n");
+ return TRUE;
+}
+
+ static HWND
+findServer(char_u *name)
+{
+ struct server_id id;
+
+ id.name = name;
+ id.hwnd = 0;
+
+ EnumWindows(enumWindowsGetServer, (LPARAM)(&id));
+
+ return id.hwnd;
+}
+
+ void
+serverSetName(char_u *name)
+{
+ char_u *ok_name;
+ HWND hwnd = 0;
+ int i = 0;
+ char_u *p;
+
+ /* Leave enough space for a 9-digit suffix to ensure uniqueness! */
+ ok_name = alloc(STRLEN(name) + 10);
+
+ STRCPY(ok_name, name);
+ p = ok_name + STRLEN(name);
+
+ for (;;)
+ {
+ /* This is inefficient - we're doing an EnumWindows loop for each
+ * possible name. It would be better to grab all names in one go,
+ * and scan the list each time...
+ */
+ hwnd = findServer(ok_name);
+ if (hwnd == 0)
+ break;
+
+ ++i;
+ if (i >= 1000)
+ break;
+
+ sprintf((char *)p, "%d", i);
+ }
+
+ if (hwnd != 0)
+ vim_free(ok_name);
+ else
+ {
+ /* Remember the name */
+ serverName = ok_name;
+#ifdef FEAT_TITLE
+ need_maketitle = TRUE; /* update Vim window title later */
+#endif
+
+ /* Update the message window title */
+ SetWindowText(message_window, ok_name);
+
+#ifdef FEAT_EVAL
+ /* Set the servername variable */
+ set_vim_var_string(VV_SEND_SERVER, serverName, -1);
+#endif
+ }
+}
+
+ char_u *
+serverGetVimNames(void)
+{
+ garray_T ga;
+
+ ga_init2(&ga, 1, 100);
+
+ EnumWindows(enumWindowsGetNames, (LPARAM)(&ga));
+
+ return ga.ga_data;
+}
+
+ int
+serverSendReply(name, reply)
+ char_u *name; /* Where to send. */
+ char_u *reply; /* What to send. */
+{
+ HWND target;
+ COPYDATASTRUCT data;
+ int n = 0;
+
+ /* The "name" argument is a magic cookie obtained from expand("<client>").
+ * It should be of the form 0xXXXXX - i.e. a C hex literal, which is the
+ * value of the client's message window HWND.
+ */
+ sscanf((char *)name, "%x", &n);
+ if (n == 0)
+ return -1;
+
+ target = (HWND)n;
+ if (!IsWindow(target))
+ return -1;
+
+ data.dwData = COPYDATA_REPLY;
+ data.cbData = STRLEN(reply) + 1;
+ data.lpData = reply;
+
+ if (SendMessage(target, WM_COPYDATA, (WPARAM)message_window,
+ (LPARAM)(&data)))
+ return 0;
+
+ return -1;
+}
+
+ int
+serverSendToVim(name, cmd, result, ptarget, asExpr, silent)
+ char_u *name; /* Where to send. */
+ char_u *cmd; /* What to send. */
+ char_u **result; /* Result of eval'ed expression */
+ void *ptarget; /* HWND of server */
+ int asExpr; /* Expression or keys? */
+ int silent; /* don't complain about no server */
+{
+ HWND target = findServer(name);
+ COPYDATASTRUCT data;
+ char_u *retval = NULL;
+ int retcode = 0;
+
+ if (target == 0)
+ {
+ if (!silent)
+ EMSG2(_(e_noserver), name);
+ return -1;
+ }
+
+ if (ptarget)
+ *(HWND *)ptarget = target;
+
+ data.dwData = asExpr ? COPYDATA_EXPR : COPYDATA_KEYS;
+ data.cbData = STRLEN(cmd) + 1;
+ data.lpData = cmd;
+
+ if (SendMessage(target, WM_COPYDATA, (WPARAM)message_window,
+ (LPARAM)(&data)) == 0)
+ return -1;
+
+ if (asExpr)
+ retval = serverGetReply(target, &retcode, TRUE, TRUE);
+
+ if (result == NULL)
+ vim_free(retval);
+ else
+ *result = retval; /* Caller assumes responsibility for freeing */
+
+ return retcode;
+}
+
+/*
+ * Bring the server to the foreground.
+ */
+ void
+serverForeground(name)
+ char_u *name;
+{
+ HWND target = findServer(name);
+
+ if (target != 0)
+ SetForegroundWindow(target);
+}
+
+/* Replies from server need to be stored until the client picks them up via
+ * remote_read(). So we maintain a list of server-id/reply pairs.
+ * Note that there could be multiple replies from one server pending if the
+ * client is slow picking them up.
+ * We just store the replies in a simple list. When we remove an entry, we
+ * move list entries down to fill the gap.
+ * The server ID is simply the HWND.
+ */
+typedef struct
+{
+ HWND server; /* server window */
+ char_u *reply; /* reply string */
+ int expr_result; /* 0 for REPLY, 1 for RESULT 2 for error */
+}
+reply_T;
+
+static garray_T reply_list = {0, 0, sizeof(reply_T), 5, 0};
+
+#define REPLY_ITEM(i) ((reply_T *)(reply_list.ga_data) + (i))
+#define REPLY_COUNT (reply_list.ga_len)
+#define REPLY_ROOM (reply_list.ga_room)
+
+/* Flag which is used to wait for a reply */
+static int reply_received = 0;
+
+ static int
+save_reply(HWND server, char_u *reply, int expr)
+{
+ reply_T *rep;
+
+ if (ga_grow(&reply_list, 1) == FAIL)
+ return FAIL;
+
+ rep = REPLY_ITEM(REPLY_COUNT);
+ rep->server = server;
+ rep->reply = vim_strsave(reply);
+ rep->expr_result = expr;
+ if (rep->reply == NULL)
+ return FAIL;
+
+ ++REPLY_COUNT;
+ --REPLY_ROOM;
+ reply_received = 1;
+ return OK;
+}
+
+/*
+ * Get a reply from server "server".
+ * When "expr_res" is non NULL, get the result of an expression, otherwise a
+ * server2client() message.
+ * When non NULL, point to return code. 0 => OK, -1 => ERROR
+ * If "remove" is TRUE, consume the message, the caller must free it then.
+ * if "wait" is TRUE block until a message arrives (or the server exits).
+ */
+ char_u *
+serverGetReply(HWND server, int *expr_res, int remove, int wait)
+{
+ int i;
+ char_u *reply;
+ reply_T *rep;
+
+ /* When waiting, loop until the message waiting for is received. */
+ for (;;)
+ {
+ /* Reset this here, in case a message arrives while we are going
+ * through the already received messages. */
+ reply_received = 0;
+
+ for (i = 0; i < REPLY_COUNT; ++i)
+ {
+ rep = REPLY_ITEM(i);
+ if (rep->server == server
+ && ((rep->expr_result != 0) == (expr_res != NULL)))
+ {
+ /* Save the values we've found for later */
+ reply = rep->reply;
+ if (expr_res != NULL)
+ *expr_res = rep->expr_result == 1 ? 0 : -1;
+
+ if (remove)
+ {
+ /* Move the rest of the list down to fill the gap */
+ mch_memmove(rep, rep + 1,
+ (REPLY_COUNT - i - 1) * sizeof(reply_T));
+ --REPLY_COUNT;
+ ++REPLY_ROOM;
+ }
+
+ /* Return the reply to the caller, who takes on responsibility
+ * for freeing it if "remove" is TRUE. */
+ return reply;
+ }
+ }
+
+ /* If we got here, we didn't find a reply. Return immediately if the
+ * "wait" parameter isn't set. */
+ if (!wait)
+ break;
+
+ /* We need to wait for a reply. Enter a message loop until the
+ * "reply_received" flag gets set. */
+
+ /* Loop until we receive a reply */
+ while (reply_received == 0)
+ {
+ /* Wait for a SendMessage() call to us. This could be the reply
+ * we are waiting for. Use a timeout of a second, to catch the
+ * situation that the server died unexpectedly. */
+ MsgWaitForMultipleObjects(0, NULL, TRUE, 1000, QS_ALLINPUT);
+
+ /* If the server has died, give up */
+ if (!IsWindow(server))
+ return NULL;
+
+ serverProcessPendingMessages();
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Process any messages in the Windows message queue.
+ */
+ void
+serverProcessPendingMessages(void)
+{
+ MSG msg;
+
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+}
+
+#endif /* FEAT_CLIENTSERVER */
+
+#if defined(FEAT_GUI) || (defined(FEAT_PRINTER) && !defined(FEAT_POSTSCRIPT)) \
+ || defined(PROTO)
+
+struct charset_pair
+{
+ char *name;
+ BYTE charset;
+};
+
+static struct charset_pair
+charset_pairs[] =
+{
+ {"ANSI", ANSI_CHARSET},
+ {"CHINESEBIG5", CHINESEBIG5_CHARSET},
+ {"DEFAULT", DEFAULT_CHARSET},
+ {"HANGEUL", HANGEUL_CHARSET},
+ {"OEM", OEM_CHARSET},
+ {"SHIFTJIS", SHIFTJIS_CHARSET},
+ {"SYMBOL", SYMBOL_CHARSET},
+#ifdef WIN3264
+ {"ARABIC", ARABIC_CHARSET},
+ {"BALTIC", BALTIC_CHARSET},
+ {"EASTEUROPE", EASTEUROPE_CHARSET},
+ {"GB2312", GB2312_CHARSET},
+ {"GREEK", GREEK_CHARSET},
+ {"HEBREW", HEBREW_CHARSET},
+ {"JOHAB", JOHAB_CHARSET},
+ {"MAC", MAC_CHARSET},
+ {"RUSSIAN", RUSSIAN_CHARSET},
+ {"THAI", THAI_CHARSET},
+ {"TURKISH", TURKISH_CHARSET},
+# if (!defined(_MSC_VER) || (_MSC_VER > 1010)) \
+ && (!defined(__BORLANDC__) || (__BORLANDC__ > 0x0500))
+ {"VIETNAMESE", VIETNAMESE_CHARSET},
+# endif
+#endif
+ {NULL, 0}
+};
+
+/*
+ * Convert a charset ID to a name.
+ * Return NULL when not recognized.
+ */
+ char *
+charset_id2name(int id)
+{
+ struct charset_pair *cp;
+
+ for (cp = charset_pairs; cp->name != NULL; ++cp)
+ if ((BYTE)id == cp->charset)
+ break;
+ return cp->name;
+}
+
+static const LOGFONT s_lfDefault =
+{
+ -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
+ OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
+ PROOF_QUALITY, FIXED_PITCH | FF_DONTCARE,
+ "Fixedsys" /* see _ReadVimIni */
+};
+
+/* Initialise the "current height" to -12 (same as s_lfDefault) just
+ * in case the user specifies a font in "guifont" with no size before a font
+ * with an explicit size has been set. This defaults the size to this value
+ * (-12 equates to roughly 9pt).
+ */
+int current_font_height = -12; /* also used in gui_w48.c */
+
+/* Convert a string representing a point size into pixels. The string should
+ * be a positive decimal number, with an optional decimal point (eg, "12", or
+ * "10.5"). The pixel value is returned, and a pointer to the next unconverted
+ * character is stored in *end. The flag "vertical" says whether this
+ * calculation is for a vertical (height) size or a horizontal (width) one.
+ */
+ static int
+points_to_pixels(char_u *str, char_u **end, int vertical, int pprinter_dc)
+{
+ int pixels;
+ int points = 0;
+ int divisor = 0;
+ HWND hwnd = (HWND)0;
+ HDC hdc;
+ HDC printer_dc = (HDC)pprinter_dc;
+
+ while (*str != NUL)
+ {
+ if (*str == '.' && divisor == 0)
+ {
+ /* Start keeping a divisor, for later */
+ divisor = 1;
+ }
+ else
+ {
+ if (!VIM_ISDIGIT(*str))
+ break;
+
+ points *= 10;
+ points += *str - '0';
+ divisor *= 10;
+ }
+ ++str;
+ }
+
+ if (divisor == 0)
+ divisor = 1;
+
+ if (printer_dc == NULL)
+ {
+ hwnd = GetDesktopWindow();
+ hdc = GetWindowDC(hwnd);
+ }
+ else
+ hdc = printer_dc;
+
+ pixels = MulDiv(points,
+ GetDeviceCaps(hdc, vertical ? LOGPIXELSY : LOGPIXELSX),
+ 72 * divisor);
+
+ if (printer_dc == NULL)
+ ReleaseDC(hwnd, hdc);
+
+ *end = str;
+ return pixels;
+}
+
+ static int CALLBACK
+font_enumproc(
+ ENUMLOGFONT *elf,
+ NEWTEXTMETRIC *ntm,
+ int type,
+ LPARAM lparam)
+{
+ /* Return value:
+ * 0 = terminate now (monospace & ANSI)
+ * 1 = continue, still no luck...
+ * 2 = continue, but we have an acceptable LOGFONT
+ * (monospace, not ANSI)
+ * We use these values, as EnumFontFamilies returns 1 if the
+ * callback function is never called. So, we check the return as
+ * 0 = perfect, 2 = OK, 1 = no good...
+ * It's not pretty, but it works!
+ */
+
+ LOGFONT *lf = (LOGFONT *)(lparam);
+
+#ifndef FEAT_PROPORTIONAL_FONTS
+ /* Ignore non-monospace fonts without further ado */
+ if ((ntm->tmPitchAndFamily & 1) != 0)
+ return 1;
+#endif
+
+ /* Remember this LOGFONT as a "possible" */
+ *lf = elf->elfLogFont;
+
+ /* Terminate the scan as soon as we find an ANSI font */
+ if (lf->lfCharSet == ANSI_CHARSET
+ || lf->lfCharSet == OEM_CHARSET
+ || lf->lfCharSet == DEFAULT_CHARSET)
+ return 0;
+
+ /* Continue the scan - we have a non-ANSI font */
+ return 2;
+}
+
+ static int
+init_logfont(LOGFONT *lf)
+{
+ int n;
+ HWND hwnd = GetDesktopWindow();
+ HDC hdc = GetWindowDC(hwnd);
+
+ n = EnumFontFamilies(hdc,
+ (LPCSTR)lf->lfFaceName,
+ (FONTENUMPROC)font_enumproc,
+ (LPARAM)lf);
+
+ ReleaseDC(hwnd, hdc);
+
+ /* If we couldn't find a useable font, return failure */
+ if (n == 1)
+ return FAIL;
+
+ /* Tidy up the rest of the LOGFONT structure. We set to a basic
+ * font - get_logfont() sets bold, italic, etc based on the user's
+ * input.
+ */
+ lf->lfHeight = current_font_height;
+ lf->lfWidth = 0;
+ lf->lfItalic = FALSE;
+ lf->lfUnderline = FALSE;
+ lf->lfStrikeOut = FALSE;
+ lf->lfWeight = FW_NORMAL;
+
+ /* Return success */
+ return OK;
+}
+
+ int
+get_logfont(
+ LOGFONT *lf,
+ char_u *name,
+ HDC printer_dc)
+{
+ char_u *p;
+ int i;
+ static LOGFONT *lastlf = NULL;
+
+ *lf = s_lfDefault;
+ if (name == NULL)
+ return 1;
+
+ if (STRCMP(name, "*") == 0)
+ {
+#if defined(FEAT_GUI_W32)
+ CHOOSEFONT cf;
+ /* if name is "*", bring up std font dialog: */
+ memset(&cf, 0, sizeof(cf));
+ cf.lStructSize = sizeof(cf);
+ cf.hwndOwner = s_hwnd;
+ cf.Flags = CF_SCREENFONTS | CF_FIXEDPITCHONLY | CF_INITTOLOGFONTSTRUCT;
+ if (lastlf != NULL)
+ *lf = *lastlf;
+ cf.lpLogFont = lf;
+ cf.nFontType = 0 ; //REGULAR_FONTTYPE;
+ if (ChooseFont(&cf))
+ goto theend;
+#else
+ return 0;
+#endif
+ }
+
+ /*
+ * Split name up, it could be <name>:h<height>:w<width> etc.
+ */
+ for (p = name; *p && *p != ':'; p++)
+ {
+ if (p - name + 1 > LF_FACESIZE)
+ return 0; /* Name too long */
+ lf->lfFaceName[p - name] = *p;
+ }
+ if (p != name)
+ lf->lfFaceName[p - name] = NUL;
+
+ /* First set defaults */
+ lf->lfHeight = -12;
+ lf->lfWidth = 0;
+ lf->lfWeight = FW_NORMAL;
+ lf->lfItalic = FALSE;
+ lf->lfUnderline = FALSE;
+ lf->lfStrikeOut = FALSE;
+
+ /*
+ * If the font can't be found, try replacing '_' by ' '.
+ */
+ if (init_logfont(lf) == FAIL)
+ {
+ int did_replace = FALSE;
+
+ for (i = 0; lf->lfFaceName[i]; ++i)
+ if (lf->lfFaceName[i] == '_')
+ {
+ lf->lfFaceName[i] = ' ';
+ did_replace = TRUE;
+ }
+ if (!did_replace || init_logfont(lf) == FAIL)
+ return 0;
+ }
+
+ while (*p == ':')
+ p++;
+
+ /* Set the values found after ':' */
+ while (*p)
+ {
+ switch (*p++)
+ {
+ case 'h':
+ lf->lfHeight = - points_to_pixels(p, &p, TRUE, (int)printer_dc);
+ break;
+ case 'w':
+ lf->lfWidth = points_to_pixels(p, &p, FALSE, (int)printer_dc);
+ break;
+ case 'b':
+#ifndef MSWIN16_FASTTEXT
+ lf->lfWeight = FW_BOLD;
+#endif
+ break;
+ case 'i':
+#ifndef MSWIN16_FASTTEXT
+ lf->lfItalic = TRUE;
+#endif
+ break;
+ case 'u':
+ lf->lfUnderline = TRUE;
+ break;
+ case 's':
+ lf->lfStrikeOut = TRUE;
+ break;
+ case 'c':
+ {
+ struct charset_pair *cp;
+
+ for (cp = charset_pairs; cp->name != NULL; ++cp)
+ if (STRNCMP(p, cp->name, strlen(cp->name)) == 0)
+ {
+ lf->lfCharSet = cp->charset;
+ p += strlen(cp->name);
+ break;
+ }
+ if (cp->name == NULL)
+ {
+ sprintf((char *)IObuff, _("E244: Illegal charset name \"%s\" in font name \"%s\""), p, name);
+ EMSG(IObuff);
+ break;
+ }
+ break;
+ }
+ default:
+ sprintf((char *)IObuff,
+ _("E245: Illegal char '%c' in font name \"%s\""),
+ p[-1], name);
+ EMSG(IObuff);
+ break;
+ }
+ while (*p == ':')
+ p++;
+ }
+
+#if defined(FEAT_GUI_W32)
+theend:
+#endif
+ /* ron: init lastlf */
+ if (printer_dc == NULL)
+ {
+ vim_free(lastlf);
+ lastlf = (LOGFONT *)alloc(sizeof(LOGFONT));
+ if (lastlf != NULL)
+ mch_memmove(lastlf, lf, sizeof(LOGFONT));
+ }
+
+ return 1;
+}
+
+#endif /* defined(FEAT_GUI) || defined(FEAT_PRINTER) */
diff --git a/src/os_os2_cfg.h b/src/os_os2_cfg.h
new file mode 100644
index 000000000..ce3b4bbde
--- /dev/null
+++ b/src/os_os2_cfg.h
@@ -0,0 +1,251 @@
+/* os_os2_cfg.h */
+/* vi:set ts=8 sts=4 sw=4: */
+
+#define CASE_INSENSITIVE_FILENAME /* ignore case when comparing file names */
+#define SPACE_IN_FILENAME
+#define BACKSLASH_IN_FILENAME
+#define BINARY_FILE_IO
+#define USE_CRNL /* lines end in CR-NL instead of NL */
+#define NO_EXPANDPATH /* always call mch_expand_wildcards */
+#define USE_EXE_NAME /* use argv[0] for $VIM */
+#define USE_TERM_CONSOLE
+#define HAVE_DUP /* have dup() */
+
+#define FNAME_ILLEGAL "\"*?><|" /* illegal characters in a file name */
+
+/*
+ * The rest is manually generated from configure.in by Paul Slootman.
+ */
+
+/* Define unless no X support found */
+#undef HAVE_X11
+
+/* Define when terminfo support found */
+#undef TERMINFO
+
+/* Define when termcap.h contains ospeed */
+#define HAVE_OSPEED 1
+
+#define HAVE_STRICMP
+#define HAVE_STRNICMP
+
+/* Define when ospeed can be extern */
+#define OSPEED_EXTERN
+
+/* Define when termcap.h contains UP, BC and PC */
+#define HAVE_UP_BC_PC 1
+
+/* Define when UP, BC and PC can be extern */
+#define UP_BC_PC_EXTERN
+
+/* Define when termcap.h defines outfuntype */
+#undef HAVE_OUTFUNTYPE
+
+/* Define when __DATE__ " " __TIME__ can be used */
+#define HAVE_DATE_TIME 1
+
+#undef UNIX /* define always by current configure script */
+
+/* Defined to the size of an int */
+#define SIZEOF_INT 4
+
+/*
+ * If we cannot trust one of the following from the libraries, we use our
+ * own safe but probably slower mch_memmove().
+ */
+#define USEBCOPY 1
+#undef USEMEMMOVE
+#undef USEMEMCPY
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef mode_t
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef off_t
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef pid_t
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define if you can safely include both <sys/time.h> and <sys/select.h>. */
+#define SYS_SELECT_WITH_SYS_TIME 1
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define as the command at the end of signal handlers ("" or "return 0;"). */
+#define SIGRETURN
+
+/* Define if touuper/tolower only work on lower/upercase characters */
+#undef BROKEN_TOUPPER
+
+/* Define if tgetstr() has a second argument that is (char *) */
+#undef TGETSTR_CHAR_P
+
+/* Define if you have the sigset() function. */
+#undef HAVE_SIGSET
+
+/* Define if the getcwd() function should not be used. */
+#undef BAD_GETCWD
+
+/* Define if you have the getcwd() function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getwd() function. */
+#define HAVE_GETWD 1
+
+/* Define if you have the select() function. */
+#define HAVE_SELECT 1
+
+/* Define if you have the strcspn() function. */
+#define HAVE_STRCSPN 1
+
+/* Define if you have the strtol() function. */
+#define HAVE_STRTOL 1
+
+/* Define if you have the tgetent() function. */
+#define HAVE_TGETENT 1
+
+#define HAVE_STRFTIME /* guessed */
+
+/* Define if you have the memset() function. */
+#define HAVE_MEMSET 1
+
+/* Define if you have the strerror() function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strcasecmp() function. */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the fchown() function. */
+#undef HAVE_FCHOWN
+
+/* Define if you have the rename() function. */
+#define HAVE_RENAME 1
+
+/* Define if you have the fsync() function. */
+#undef HAVE_FSYNC /* exists, but apparently Bad Things happen when used */
+
+/* Define if you have the fchdir() function. */
+#undef HAVE_FCHDIR
+
+/* Define if you have the setenv() function. */
+#undef HAVE_SETENV
+
+/* Define if you have the putenv() function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the gettimeofday() function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define if you have the getpwuid() function. */
+#undef HAVE_GETPWUID
+
+/* Define if you have the getpwnam() function. */
+#undef HAVE_GETPWNAM
+
+/* Define if you have the qsort() function. */
+#define HAVE_QSORT 1
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <sys/ndir.h> header file. */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if you have the <sys/dir.h> header file. */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have the <ndir.h> header file. */
+#undef HAVE_NDIR_H
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if you have a <sys/wait.h> that is not POSIX.1 compatible. */
+#undef HAVE_UNION_WAIT
+
+/* This is currently unused in vim: */
+/* Define if you have the ANSI C header files. */
+/* #undef STDC_HEADERS */
+
+/* instead, we check a few STDC things ourselves */
+#define HAVE_STDLIB_H 1
+#undef HAVE_STRING_H /* On EMX it is better to use strings.h */
+
+/* Define if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define if you have the <termcap.h> header file. */
+#define HAVE_TERMCAP_H 1
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H
+
+/* Define if you have the <termio.h> header file. */
+#undef HAVE_TERMIO_H
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <stropts.h> header file. */
+#undef HAVE_STROPTS_H
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/systeminfo.h> header file. */
+#undef HAVE_SYS_SYSTEMINFO_H
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <sys/stream.h> header file. */
+#undef HAVE_SYS_STREAM_H
+
+/* Define if you have the <sys/ptem.h> header file. */
+#undef HAVE_SYS_PTEM_H
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <libc.h> header file. */
+#undef HAVE_LIBC_H
+
+/* Define if you have the <sys/statfs.h> header file. */
+#undef HAVE_SYS_STATFS_H
+
+/* Define if you have the <sys/poll.h> header file. */
+#undef HAVE_SYS_POLL_H
+
+/* Define if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
diff --git a/src/os_qnx.c b/src/os_qnx.c
new file mode 100644
index 000000000..704061a4e
--- /dev/null
+++ b/src/os_qnx.c
@@ -0,0 +1,162 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * QNX port by Julian Kinraid
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * os_qnx.c
+ */
+
+#include "vim.h"
+
+
+#if defined(FEAT_GUI_PHOTON)
+int is_photon_available;
+#endif
+
+void qnx_init()
+{
+#if defined(FEAT_GUI_PHOTON)
+ PhChannelParms_t parms;
+
+ memset( &parms, 0, sizeof( parms ) );
+ parms.flags = Ph_DYNAMIC_BUFFER;
+
+ is_photon_available = (PhAttach( NULL, &parms ) != NULL) ? TRUE : FALSE;
+#endif
+}
+
+#if (defined(FEAT_GUI_PHOTON) && defined(FEAT_CLIPBOARD)) || defined(PROTO)
+
+#define CLIP_TYPE_VIM "VIMTYPE"
+#define CLIP_TYPE_TEXT "TEXT"
+
+/* Turn on the clipboard for a console vim when photon is running */
+void qnx_clip_init()
+{
+ if( is_photon_available == TRUE && !gui.in_use)
+ clip_init( TRUE );
+}
+
+/*****************************************************************************/
+/* Clipboard */
+
+/* No support for owning the clipboard */
+int
+clip_mch_own_selection( VimClipboard *cbd )
+{
+ return FALSE;
+}
+
+void
+clip_mch_lose_selection( VimClipboard *cbd )
+{
+}
+
+void
+clip_mch_request_selection( VimClipboard *cbd )
+{
+ int type = MLINE, clip_length = 0, is_type_set = FALSE;
+ void *cbdata;
+ PhClipHeader *clip_header;
+ char_u *clip_text = NULL;
+
+ cbdata = PhClipboardPasteStart( PhInputGroup( NULL ));
+ if( cbdata != NULL )
+ {
+ /* Look for the vim specific clip first */
+ clip_header = PhClipboardPasteType( cbdata, CLIP_TYPE_VIM );
+ if( clip_header != NULL && clip_header->data != NULL )
+ {
+ switch( *(char *) clip_header->data )
+ {
+ default: /* fallthrough to line type */
+ case 'L': type = MLINE; break;
+ case 'C': type = MCHAR; break;
+#ifdef FEAT_VISUAL
+ case 'B': type = MBLOCK; break;
+#endif
+ }
+ is_type_set = TRUE;
+ }
+
+ /* Try for just normal text */
+ clip_header = PhClipboardPasteType( cbdata, CLIP_TYPE_TEXT );
+ if( clip_header != NULL )
+ {
+ clip_text = clip_header->data;
+ clip_length = clip_header->length - 1;
+
+ if( clip_text != NULL && is_type_set == FALSE )
+ type = (strchr( clip_text, '\r' ) != NULL) ? MLINE : MCHAR;
+ }
+
+ if( (clip_text != NULL) && (clip_length > 0) )
+ {
+ clip_yank_selection( type, clip_text, clip_length, cbd );
+ }
+
+ PhClipboardPasteFinish( cbdata );
+ }
+}
+
+void
+clip_mch_set_selection( VimClipboard *cbd )
+{
+ int type;
+ long_u len;
+ char_u *text_clip, vim_clip[2], *str = NULL;
+ PhClipHeader clip_header[2];
+
+ /* Prevent recursion from clip_get_selection() */
+ if( cbd->owned == TRUE )
+ return;
+
+ cbd->owned = TRUE;
+ clip_get_selection( cbd );
+ cbd->owned = FALSE;
+
+ type = clip_convert_selection( &str, &len, cbd );
+ if( type >= 0 )
+ {
+ text_clip = lalloc( len + 1, TRUE ); /* Normal text */
+
+ if( text_clip && vim_clip )
+ {
+ memset( clip_header, 0, sizeof( clip_header ) );
+
+ STRNCPY( clip_header[0].type, CLIP_TYPE_VIM, 8 );
+ clip_header[0].length = sizeof( vim_clip );
+ clip_header[0].data = vim_clip;
+
+ STRNCPY( clip_header[1].type, CLIP_TYPE_TEXT, 8 );
+ clip_header[1].length = len + 1;
+ clip_header[1].data = text_clip;
+
+ switch( type )
+ {
+ default: /* fallthrough to MLINE */
+ case MLINE: *vim_clip = 'L'; break;
+ case MCHAR: *vim_clip = 'C'; break;
+#ifdef FEAT_VISUAL
+ case MBLOCK: *vim_clip = 'B'; break;
+#endif
+ }
+
+ STRNCPY( text_clip, str, len );
+ text_clip[ len ] = NUL;
+
+ vim_clip[ 1 ] = NUL;
+
+ PhClipboardCopy( PhInputGroup( NULL ), 2, clip_header);
+ }
+ vim_free( text_clip );
+ }
+ vim_free( str );
+}
+#endif
diff --git a/src/os_qnx.h b/src/os_qnx.h
new file mode 100644
index 000000000..cddc68db9
--- /dev/null
+++ b/src/os_qnx.h
@@ -0,0 +1,19 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+#ifdef __QNXNTO__
+# include <sys/procmgr.h>
+#endif
+
+#define USE_TMPNAM
+
+#define POSIX /* Used by pty.c */
+
+#if defined(FEAT_GUI_PHOTON)
+extern int is_photon_available;
+#endif
diff --git a/src/os_riscos.c b/src/os_riscos.c
new file mode 100644
index 000000000..a1cdab403
--- /dev/null
+++ b/src/os_riscos.c
@@ -0,0 +1,1288 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+
+/*
+ * os_riscos.c
+ *
+ * Thomas Leonard <tal197@ecs.soton.ac.uk>
+ */
+
+const char *__dynamic_da_name = "Vim heap"; /* Enable and name our dynamic area */
+int ro_line_mode = TRUE; /* For Ex mode we much echo chars to the screen ourselves */
+int windowed; /* Flag - are we running inside a text window? */
+int WinLeft, WinTop; /* We might be started inside a text window */
+int ScrollTop; /* Make cursor movements relative to ScrollTop. */
+
+int old_escape_state = -1;
+int old_cursor_state = -1;
+
+#define rgb(r,g,b) ((b<<24) + (g<<16) + (r<<8))
+#define NORMAL_FG 0x00000000
+#define NORMAL_BG 0xffffffff
+
+/* Convert a DOS colour number to an RGB palette entry.
+ * Mappings from X11 rgb/txt file.
+ */
+ static int
+map_colour(dos)
+ int dos; /* Standard DOS colour number. */
+{
+ switch (dos)
+ {
+ case 0: return 0; /* Black */
+ case 1: return rgb(0,0,139); /* DarkBlue */
+ case 2: return rgb(0,100,0); /* DarkGreen */
+ case 3: return rgb(0,139,139); /* DarkCyan */
+ case 4: return rgb(139,0,0); /* DarkRed */
+ case 5: return rgb(139,0,139); /* DarkMagenta */
+ case 6: return rgb(165,42,42); /* Brown, DarkYellow */
+ case 7: return rgb(211,211,211); /* LightGray, LightGrey, Gray, Grey */
+ case 8: return rgb(169,169,169); /* DarkGray, DarkGrey */
+ case 9: return rgb(173,216,230); /* Blue, LightBlue */
+ case 10: return rgb(144,238,144); /* Green, LightGreen */
+ case 11: return rgb(224,255,255); /* Cyan, LightCyan */
+ case 12: return rgb(255,0,0); /* Red, LightRed */
+ case 13: return rgb(255,0,255); /* Magenta, LightMagenta */
+ case 14: return rgb(255,255,0); /* Yellow, LightYellow */
+ case 15: return rgb(255,255,255); /* White */
+ }
+ return rgb(100,100,100);
+}
+
+ static void
+text_fg(fg)
+ int fg; /* Foregound colour in the form &BBGGRR00 */
+{
+ xswi(ColourTrans_SetTextColour, fg, 0, 0, 0);
+}
+
+ static void
+text_bg(bg)
+ int bg; /* Backgound colour in the form &BBGGRR00 */
+{
+ xswi(ColourTrans_SetTextColour, bg, 0, 0, 1 << 7);
+}
+
+#define OUT_NORMAL 0
+#define OUT_NUMBER 1 /* Reading in a number */
+
+ void
+mch_write(s, len)
+ char_u *s;
+ int len;
+{
+ static int mode = OUT_NORMAL;
+ static int x, y; /* For reading numbers in. */
+
+ if (!term_console)
+ {
+ /* Maybe we are running Vim remotely - don't interpret chars */
+ while (len--)
+ {
+ char_u c = *s++;
+ swi(OS_WriteC, c);
+ /* We might need to send a CR too. This shouldn't
+ * hurt if we don't need it, should it?
+ */
+ if (c == 10)
+ swi(OS_WriteI + 13);
+ }
+ return;
+ }
+
+ while (len--)
+ {
+ char_u c = *s++;
+ switch (mode)
+ {
+ case OUT_NUMBER:
+ if (c < '0' || c > '9')
+ {
+ mode = OUT_NORMAL;
+ }
+ else
+ {
+ x = (x * 10) + c - '0';
+ continue;
+ }
+ /* note: no break here! */
+
+ case OUT_NORMAL:
+ switch (c)
+ {
+ case 1:
+ /* Number (in decimal) follows. */
+ mode = OUT_NUMBER;
+ y = x;
+ x = 0;
+ break;
+ case 2:
+ /* Position cursor. */
+ swi(OS_WriteI + 31);
+ swi(OS_WriteC, x);
+ swi(OS_WriteC, y - ScrollTop);
+ break;
+ case 3:
+ /* Set scroll region. */
+ if (x == Rows -1 && y == 0 && !windowed)
+ {
+ /* Whole screen - remove text window.
+ * This is MUCH faster.
+ */
+ swi(OS_WriteI + 26);
+ }
+ else
+ {
+ /* Create a text window. */
+ swi(OS_WriteI + 28);
+ swi(OS_WriteC, WinLeft);
+ swi(OS_WriteC, WinTop + x);
+ swi(OS_WriteC, WinLeft + Columns - 1);
+ swi(OS_WriteC, WinTop + y);
+ }
+ ScrollTop = y;
+ break;
+ case 4:
+ /* Normal mode. */
+ text_fg(NORMAL_FG);
+ text_bg(NORMAL_BG);
+ break;
+ case 5:
+ /* Reverse mode. */
+ text_fg(NORMAL_BG);
+ text_bg(NORMAL_FG);
+ break;
+ case 10:
+ swi(OS_NewLine);
+ break;
+ case 14:
+ /* Cursor invisible. */
+ swi(OS_WriteN,
+ "\027\001\000\000\000\000\000\000\000\000",
+ 10);
+ break;
+ case 15:
+ /* Cursor visible. */
+ swi(OS_WriteN,
+ "\027\001\002\000\000\000\000\000\000\000",
+ 10);
+ break;
+ case 16:
+ /* Cursor very visible (flash) */
+ swi(OS_WriteN,
+ "\027\001\003\000\000\000\000\000\000\000",
+ 10);
+ case 17:
+ /* Set foreground colour. */
+ text_fg(map_colour(x));
+ break;
+ case 18:
+ /* Set background colour. */
+ text_bg(map_colour(x));
+ break;
+ case 19:
+ /* Scroll text down. */
+ swi(OS_WriteN,
+ "\027\007\000\002\000\000\000\000\000\000",
+ 10);
+ break;
+ default:
+ swi(OS_WriteC, c);
+ }
+ continue;
+
+ default:
+ printf("[output error]");
+ mode = OUT_NORMAL;
+ }
+ }
+}
+
+/*
+ * mch_inchar(): low level input funcion.
+ * Get a characters from the keyboard.
+ * Return the number of characters that are available.
+ * If wtime == 0 do not wait for characters.
+ * If wtime == n wait n msecs for characters.
+ * If wtime == -1 wait forever for characters.
+ *
+ * TODO: call convert_input() for 'fileencoding' to 'encoding' conversion.
+ */
+ int
+mch_inchar(buf, maxlen, wtime, tb_change_cnt)
+ char_u *buf;
+ int maxlen;
+ long wtime;
+ int tb_change_cnt;
+{
+ int got=0;
+ unsigned int start_time = clock();
+
+ if (ro_line_mode)
+ {
+ /* We're probably in Ex mode - get whole lines at a time. */
+
+ static char_u line_buffer[256];
+ static int remaining_chars = 0;
+ static int buf_pos = 0;
+
+ /* Do we need to fetch another line? */
+ if (remaining_chars == 0)
+ {
+ int old_esc_state;
+ swi(OS_Byte, 200, 1, 0xfe);
+ old_esc_state = r1;
+
+ buf_pos = 0;
+ if (xswi(OS_ReadLine, line_buffer, 255, 0, 255) & (c_flag | v_flag))
+ {
+ got_int = TRUE; /* ESC pressed */
+ r1 = 0;
+ }
+ line_buffer[r1] = 13;
+ remaining_chars = r1 + 1; /* Count CR as part of input */
+
+ swi(OS_Byte, 200, old_esc_state, 0);
+ }
+
+ /* Can we send the rest of the buffer back in one go? */
+ if (remaining_chars <= maxlen)
+ {
+ int got = remaining_chars;
+
+ memcpy(buf, line_buffer + buf_pos, got);
+ remaining_chars = 0;
+ return got;
+ }
+
+ /* Send as much as we can */
+ memcpy(buf, line_buffer + buf_pos, maxlen);
+ buf_pos += maxlen;
+ remaining_chars -= maxlen;
+
+ return maxlen;
+ }
+
+ if (!term_console)
+ {
+ /* Use OS_ReadC for all input.
+ * Avoids problems with remote access getting interference from
+ * the keyboard.
+ */
+ if (wtime == 0)
+ return 0; /* Ignore quick key checks */
+
+ if (xswi(OS_ReadC) & c_flag)
+ {
+ got_int = TRUE; /* ESC pressed - can this happen? */
+ swi(OS_Byte, 124); /* Clear Escape state */
+ r0 = 0x1b; /* It *might* not have been Escape! */
+ }
+ buf[0] = r0;
+ return 1;
+ }
+
+ /*
+ * OK, here's the plan:
+ *
+ * 1) Wait until wtime expires or we get a key
+ * 2) Get keys until the keyboard buffer is empty or buf is full
+ */
+
+ while (xswi(OS_Byte,145,0) & c_flag)
+ {
+ /* Nothing at all in the keyboard buffer.
+ * Has our time expired yet?
+ */
+ if ( (wtime != -1) && (clock() - start_time) >= wtime )
+ return 0; /* Nothing read - giving up */
+ }
+
+ /* We've got one char (in r2) - are there any more? */
+
+ while (got < maxlen)
+ {
+ buf[got++] = r2;
+
+ if (xswi(OS_Byte,145,0) & c_flag)
+ return got; /* Keyboard buffer empty */
+ }
+ return got; /* buf is full */
+}
+
+/*
+ * return non-zero if a character is available
+ */
+ int
+mch_char_avail()
+{
+ if (!term_console)
+ return 0; /* Can't tell */
+ if (xswi(OS_Byte, 152, 0) & c_flag)
+ return 0;
+ return 1;
+}
+
+/* Find out how much free memory we have.
+ * I don't know how to work this out exactly but, since we can claim
+ * more memory from the OS, let's just report the free pool size.
+ * Dynamic area 6 doesn't exist pre 3.6 according to StrongHelp, so
+ * we'll use Wimp_SlotSize. If that fails (outside the desktop?)
+ * then just return a big number and hope.
+ */
+ long_u
+mch_avail_mem(special)
+ int special;
+{
+ if (xswi(Wimp_SlotSize, -1, -1) & v_flag)
+ return 0x7fffffff;
+ return r2;
+}
+
+ void
+mch_delay(msec, ignoreinput)
+ long msec;
+ int ignoreinput;
+{
+ int start_time, time_now;
+ int csec = msec / 10;
+
+ swi(OS_ReadMonotonicTime);
+ start_time = r0;
+
+ for (;;)
+ {
+ swi(OS_ReadMonotonicTime);
+ time_now = r0;
+ if (time_now - start_time > csec)
+ return;
+#ifdef FEAT_GUI
+ /* In the GUI, allow other programs to run while waiting. */
+ if (gui.in_use)
+ gui_mch_wait_for_chars(start_time + csec);
+#endif
+ }
+}
+
+/*
+ * If the machine has job control, use it to suspend the program,
+ * otherwise fake it by starting a new shell.
+ */
+ void
+mch_suspend()
+{
+ suspend_shell();
+}
+
+ void
+mch_init()
+{
+ /*
+ * Read window size first. Calls to mch_get_shellsize() will
+ * simply return these values in future so that setting the
+ * text window (used for scrolling) won't give strange results.
+ */
+
+ int buf[7] = {132, 135, 256, 257, 1, 2, -1};
+
+ /* Command windows are no longer forced open, since if we are
+ * in the desktop then we'll use the GUI version.
+ * Opening a command window here messes up the GUI version startup
+ */
+#ifndef FEAT_GUI
+ swi(OS_WriteI);
+#endif
+ swi(OS_ReadVduVariables, buf, buf);
+ WinLeft = buf[0];
+ WinTop = buf[1];
+ Columns = buf[2];
+ Rows = buf[3] + 1; /* Seems to be one off (VduVars wrong?) */
+ ScrollTop = 0;
+
+ /* Are we running in a textwindow? */
+ if (Rows == buf[5] + 1 && Columns == buf[4] + 1)
+ windowed = 0;
+ else
+ windowed = 1;
+
+ /* Choose a nice colour scheme. */
+ text_fg(NORMAL_FG);
+ text_bg(NORMAL_BG);
+}
+
+/*
+ * Check_win checks whether we have an interactive stdout.
+ */
+/* ARGSUSED */
+ int
+mch_check_win(argc, argv)
+ int argc;
+ char **argv;
+{
+ return OK;
+}
+
+/*
+ * Return TRUE if the input comes from a terminal, FALSE otherwise.
+ */
+ int
+mch_input_isatty()
+{
+ if (xswi(OS_ChangeRedirection, -1, -1) & v_flag)
+ return TRUE; /* Error - TRUE is probably correct though */
+ if (r0 == 0)
+ return TRUE;
+ return FALSE;
+}
+
+#ifdef FEAT_TITLE
+ int
+mch_can_restore_title()
+{
+ return FALSE;
+}
+
+ int
+mch_can_restore_icon()
+{
+ return FALSE;
+}
+
+
+/*
+ * Set the window title and icon.
+ */
+ void
+mch_settitle(title, icon)
+ char_u *title;
+ char_u *icon;
+{
+ if (title == NULL)
+ title = (char_u *) "<untitled>";
+#ifdef FEAT_GUI
+ if (gui.in_use && strcmp(title, gui.window_title))
+ {
+ int length;
+ length = strlen(title);
+ if (length >= gui.window_title_size)
+ length = gui.window_title_size - 1;
+ strncpy(gui.window_title, title, length);
+ gui.window_title[length] = 0;
+ ro_redraw_title(gui.window_handle);
+ }
+#endif
+ return;
+}
+
+/*
+ * Restore the window/icon title.
+ * "which" is one of:
+ * 1 only restore title
+ * 2 only restore icon
+ * 3 restore title and icon
+ */
+ void
+mch_restore_title(which)
+ int which;
+{
+ return;
+}
+#endif
+
+/*
+ * Insert user name in s[len].
+ * Return OK if a name found.
+ */
+ int
+mch_get_user_name(s, len)
+ char_u *s;
+ int len;
+{
+ /* RISC OS doesn't support user names. */
+ *s = NUL;
+ return FAIL;
+}
+
+/*
+ * Insert host name in s[len].
+ */
+
+ void
+mch_get_host_name(s, len)
+ char_u *s;
+ int len;
+{
+ if (xswi(OS_ReadVarVal, "Machine$Name", s, len, 0, 3) & v_flag)
+ {
+ /* Variable does not exist (normal operation) */
+ STRNCPY(s, "(unknown)", len);
+ }
+}
+
+/*
+ * return process ID
+ */
+ long
+mch_get_pid()
+{
+ if (xswi(Wimp_ReadSysInfo, 5) & v_flag)
+ return 0;
+ return r0;
+}
+
+/*
+ * Get name of current directory into buffer 'buf' of length 'len' bytes.
+ * Return OK for success, FAIL for failure.
+ */
+ int
+mch_dirname(buf, len)
+ char_u *buf;
+ int len;
+{
+ if (xswi(OS_FSControl, 37, "@", buf, 0, 0, len) & v_flag)
+ return FAIL;
+ return OK;
+}
+
+/*
+ * Get absolute file name into buffer 'buf' of length 'len' bytes.
+ *
+ * return FAIL for failure, OK for success
+ */
+ int
+mch_FullName(fname, buf, len, force)
+ char_u *fname, *buf;
+ int len;
+ int force; /* Also expand when already absolute path name.
+ * Not used under RISC OS.
+ */
+{
+ if (xswi(OS_FSControl, 37, fname, buf, 0, 0, len) & v_flag)
+ return FAIL;
+ return OK;
+}
+
+/*
+ * Return TRUE if "fname" does not depend on the current directory.
+ */
+ int
+mch_isFullName(fname)
+ char_u *fname;
+{
+ if (strstr(fname, "::") && strstr(fname,".$."))
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Get file permissions for 'name'.
+ * Returns -1 when it doesn't exist.
+ */
+ long
+mch_getperm(name)
+ char_u *name;
+{
+ struct stat statb;
+
+ if (stat((char *)name, &statb))
+ return -1;
+ return statb.st_mode;
+}
+
+/*
+ * set file permission for 'name' to 'perm'
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+mch_setperm(name, perm)
+ char_u *name;
+ long perm;
+{
+ return (chmod((char *)name, (mode_t)perm) == 0 ? OK : FAIL);
+}
+
+/*
+ * Set hidden flag for "name".
+ */
+/* ARGSUSED */
+ void
+mch_hide(name)
+ char_u *name;
+{
+ /* can't hide a file */
+}
+
+/*
+ * return TRUE if "name" is a directory
+ * return FALSE if "name" is not a directory
+ * return FALSE for error
+ */
+ int
+mch_isdir(name)
+ char_u *name;
+{
+ if (xswi(OS_File, 17, name) & v_flag)
+ return FALSE;
+ if (r0 == 2 || r0 == 3)
+ return TRUE; /* Count image files as directories. */
+ return FALSE;
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return 1 if "name" can be executed, 0 if not.
+ * Return -1 if unknown. Requires which to work.
+ */
+ int
+mch_can_exe(name)
+ char_u *name;
+{
+ char_u *buf;
+ char_u *p;
+ int retval;
+
+ buf = alloc((unsigned)STRLEN(name) + 7);
+ if (buf == NULL)
+ return -1;
+ sprintf((char *)buf, "which %s", name);
+ p = get_cmd_output(buf, SHELL_SILENT);
+ vim_free(buf);
+ if (p == NULL)
+ return -1;
+ /* result can be: "name: Command not found" */
+ retval = (*p != NUL && strstr((char *)p, "not found") == NULL);
+ vim_free(p);
+ return retval;
+}
+#endif
+
+/*
+ * Check what "name" is:
+ * NODE_NORMAL: file or directory (or doesn't exist)
+ * NODE_WRITABLE: writable device, socket, fifo, etc.
+ * NODE_OTHER: non-writable things
+ */
+ int
+mch_nodetype(name)
+ char_u *name;
+{
+ /* TODO */
+ return NODE_NORMAL;
+}
+
+ void
+mch_early_init()
+{
+ /* Turn off all the horrible filename munging in UnixLib. */
+ __riscosify_control = __RISCOSIFY_NO_PROCESS;
+}
+
+ void
+mch_exit(r)
+ int r;
+{
+ settmode(TMODE_COOK);
+ exiting = TRUE;
+ out_flush();
+ ml_close_all(TRUE); /* remove all memfiles */
+
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_exit(r);
+#endif
+ swi(OS_NewLine);
+ if (old_escape_state != -1)
+ swi(OS_Byte, 229, old_escape_state, 0);
+ if (old_cursor_state != -1)
+ swi(OS_Byte, 4, old_cursor_state);
+ exit(r);
+}
+
+ void
+mch_settmode(tmode)
+ int tmode; /* TMODE_RAW or TMODE_COOK */
+{
+ if (tmode == TMODE_COOK)
+ {
+ ro_line_mode = TRUE;
+ return;
+ }
+
+ ro_line_mode = FALSE;
+
+ if (term_console)
+ {
+ /* Block cursor. */
+ swi(OS_WriteN,
+ "\027\000\012\000\000\000\000\000\000\000",
+ 10);
+
+ /* Disable the standard cursor key actions. */
+ swi(OS_Byte, 4, 1);
+ if (old_cursor_state == -1)
+ old_cursor_state = r1;
+ }
+
+ /* Stop Escape from quitting Vim! */
+ swi(OS_Byte, 229, 1, 0);
+ if (old_escape_state == -1)
+ old_escape_state = r1;
+}
+
+/*
+ * set mouse clicks on or off (only works for xterms)
+ */
+ void
+mch_setmouse(on)
+ int on;
+{
+}
+
+/*
+ * set screen mode, always fails.
+ */
+/* ARGSUSED */
+ int
+mch_screenmode(arg)
+ char_u *arg;
+{
+ EMSG(_(e_screnmode));
+ return FAIL;
+}
+
+/*
+ * Try to get the current window size.
+ * Return OK when size could be determined, FAIL otherwise.
+ * Simply return results stored by mch_init() if we are the
+ * machine's console. If not, we don't know how big the screen is.
+ */
+ int
+mch_get_shellsize()
+{
+ /* if size changed: screenalloc will allocate new screen buffers */
+ return term_console ? OK : FAIL;
+}
+
+/*
+ * Can't change the size.
+ * Assume the user knows what he's doing and use the new values.
+ */
+ void
+mch_set_shellsize()
+{
+ /* Assume the user knows what he's doing and use the new values. */
+}
+
+/*
+ * Rows and/or Columns has changed.
+ */
+ void
+mch_new_shellsize()
+{
+ /* Nothing to do. */
+}
+
+ int
+mch_call_shell(cmd, options)
+ char_u *cmd;
+ int options; /* SHELL_*, see vim.h */
+{
+ int retval;
+ int tmode = cur_tmode;
+
+ if (cmd == NULL)
+ cmd = (char_u *) "GOS";
+
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ return gui_mch_call_shell(cmd, options);
+#endif
+ if (options & SHELL_COOKED)
+ settmode(TMODE_COOK); /* set to normal mode */
+ MSG_PUTS("\n");
+
+ /* I don't even want to think about what UnixLib must
+ * be doing to allow this to work...
+ */
+ retval = system(cmd);
+ if (retval && !(options & SHELL_SILENT))
+ EMSG(strerror(EOPSYS)); /* Doesn't seem to set errno? */
+
+ swi(OS_Byte, 229, 1, 0); /* Re-disable escape */
+ if (tmode == TMODE_RAW)
+ settmode(TMODE_RAW); /* set to raw mode */
+ return retval ? FAIL : OK;
+}
+
+/*
+ * Check for Escape being pressed right now.
+ * [ different if !term_console? ]
+ */
+ void
+mch_breakcheck()
+{
+ if (xswi(OS_Byte, 121, 0xf0) & v_flag)
+ return;
+ if (r1 == 0xff)
+ {
+ got_int = TRUE;
+ swi(OS_Byte, 15, 1); /* Flush input buffer */
+ }
+}
+
+/*
+ * Recursively expand one path component into all matching files and/or
+ * directories.
+ * "path" has backslashes before chars that are not to be expanded.
+ * Return the number of matches found.
+ */
+ int
+mch_expandpath(gap, path, flags)
+ garray_T *gap; /* Grow array for results. */
+ char_u *path;
+ int flags; /* EW_* flags */
+{
+ int got; /* Number of matches. */
+ char_u *pattern;
+
+ /* Plan:
+ *
+ * 1) Get first part of path - no wildcards
+ * 2) Get next path element (wildcarded)
+ * 3) Get rest of path
+ *
+ * If (3) is nothing then only the leaf is wildcarded - add to gap
+ * Otherwise call recursively for each path in (2), passing (3)
+ *
+ * This is just the header function.
+ */
+
+ /* We must be able to modifiy path, so make a copy */
+ pattern = vim_strsave(path);
+ if (pattern == NULL)
+ return 0;
+ got = expand_section(gap, (char_u *)"", pattern, flags);
+ vim_free(pattern);
+ return got;
+}
+
+/*
+ * expand_section(gap, "$.Dir1.Dir2", "ABBA*.myleaf##")
+ *
+ * calls expand_section(gap, "$.Dir1.Dir2.ABBA_Gold", "myleaf##")
+ * and expand_section(gap, "$.Dir1.Dir2.ABBA_Live", "myleaf##")
+ *
+ * If rest is just a leaf then all matches are added to gap.
+ *
+ * Returns number of items added to gap.
+ */
+ int
+expand_section(gap, root, rest, flags)
+ garray_T *gap;
+ char_u *root; /* Non-wildcarded path to search */
+ char_u *rest; /* Wildcarded remainder of path */
+ int flags; /* Add dirs/files/missing objects. */
+{
+ static char_u buf[MAXPATHL]; /* Temporary buffer. */
+ char_u dir[MAXPATHL];
+ int start_element = -1; /* Start of wildcarded element */
+ char_u c;
+ int i;
+ int got, dir_pos;
+ int buflen; /* Chars used in buf[] */
+ int colon = 0; /* Dir ends in ':' */
+
+ buflen = strlen(root);
+ STRNCPY(buf, root, buflen); /* Copy root into buffer. */
+
+ /*
+ * Find end of nonwildcarded section.
+ * Count ':' as a path sep since Vim:Bug* is a valid pathname.
+ */
+
+ for (i = 0; c = rest[i]; i++)
+ {
+ if (c == PATHSEP)
+ {
+ start_element = i;
+ colon = 0;
+ }
+ if (c == ':')
+ {
+ start_element = i + 1;
+ colon = 1;
+ }
+ if (c == '#' || c == '*')
+ break;
+ }
+ if (c == 0)
+ start_element = i;
+
+ /*
+ * start_element +> terminator for non-wildcarded section.
+ * Transfer this bit into buf.
+ */
+ if (buflen + start_element + 4 >= MAXPATHL)
+ return 0; /* Buffer full */
+ if (start_element >= 0)
+ {
+ if (*root && !colon)
+ buf[buflen++] = PATHSEP;
+ strncpy(buf + buflen, rest, start_element);
+ buflen += start_element;
+ }
+ buf[buflen] = 0;
+
+ /*
+ * Did we reach the end of the string without hitting any wildcards?
+ */
+ if (c == 0)
+ {
+ /* Yes - add combined path to grow array and return. */
+ addfile(gap, buf, flags);
+ return 1;
+ }
+
+ if (start_element < 0 || !colon)
+ start_element++;
+ rest += start_element;
+
+ /*
+ * rest does contain wildcards if we get here.
+ *
+ * Now : have we reached the leaf names part yet?
+ * If so, add all matches (files and dirs) to gap.
+ * If not, get next path element and scan all matching directories.
+ */
+
+ start_element = -1;
+ for (i = 0; rest[i]; i++)
+ {
+ if (rest[i] == '.')
+ {
+ start_element = i;
+ rest[i] = 0; /* Break string here. */
+ break;
+ }
+ }
+
+ /* If start_element is -1 then we are matching leaf names */
+
+ r3 = 0; /* Number of objs read. */
+ dir_pos = 0; /* Position through directory. */
+ got = 0; /* Files added so far. */
+ while (dir_pos != -1)
+ {
+ buf[buflen] = 0;
+ if (xswi(OS_GBPB, 9,
+ buf, /* Directory to scan. */
+ buf + buflen + (1 - colon), /* Buffer for result. */
+ 1, /* Number of objects to read. */
+ dir_pos, /* Search position. */
+ MAXPATHL - 2 - buflen, /* Size of result buffer. */
+ rest) /* Wildcarded leafname. */
+ & v_flag)
+ {
+ EMSG(r0 + 4);
+ r4 = -1;
+ }
+ dir_pos = r4; /* r4 corrupted by addfile() */
+ if (r3 > 0)
+ {
+ char_u *path = buf;
+ if (buflen == 0)
+ path++; /* Don't do '.File' */
+ else if (!colon)
+ buf[buflen] = '.'; /* Join path and leaf */
+
+ /* Path -> full path of object found */
+ if (start_element == -1)
+ {
+ addfile(gap, path, flags);
+ got++;
+ }
+ else
+ {
+ /* Scan into subdirectories and images; ignore files */
+ swi(OS_File, 17, path);
+ if (r0 == 2 || r0 == 3)
+ got += expand_section(gap,
+ path,
+ rest + start_element + 1,
+ flags);
+ }
+ }
+ }
+
+ /* Restore the dot if we removed it. */
+ if (start_element >= 0)
+ rest[start_element] = '.';
+ return got;
+}
+
+/*
+ * mch_expand_wildcards() - this code does wild-card pattern matching using
+ * the shell. It isn't used under RISC OS.
+ *
+ * return OK for success, FAIL for error (you may lose some memory) and put
+ * an error message in *file.
+ *
+ * num_pat is number of input patterns
+ * pat is array of pointers to input patterns
+ * num_file is pointer to number of matched file names
+ * file is pointer to array of pointers to matched file names
+ */
+ int
+mch_expand_wildcards(num_pat, pat, num_file, file, flags)
+ int num_pat;
+ char_u **pat;
+ int *num_file;
+ char_u ***file;
+ int flags; /* EW_* flags */
+{
+ /* This doesn't get called unless SPECIAL_WILDCHAR is defined. */
+ return FAIL;
+}
+
+/*
+ * Return TRUE if "p" contains wildcards which can be expanded by
+ * mch_expandpath().
+ */
+ int
+mch_has_exp_wildcard(p)
+ char_u *p;
+{
+ if (vim_strpbrk((char_u *)"*#", p))
+ return TRUE;
+ return FALSE;
+}
+
+/* Return TRUE if "p" contains wildcards. */
+ int
+mch_has_wildcard(p)
+ char_u *p;
+{
+ if (vim_strpbrk((char_u *)"*#`", p))
+ return TRUE;
+ return FALSE;
+}
+
+ int /* see Unix unlink(2) */
+mch_remove(file)
+ char_u *file; /* Name of file to delete. */
+{
+ if (xswi(OS_FSControl, 27, file, 0, 0) & v_flag)
+ return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+}
+
+/* Try to make existing scripts work without modification.
+ * Return a pointer to the new string (freed by caller), or NULL
+ *
+ * Two main cases:
+ * - Absolute : $VIM/syntax/help.vim
+ * - Relative : Adfs::4.$.!Vim.Resources.Syntax/help.vim
+ */
+ char_u *
+mch_munge_fname(fname)
+ char_u *fname;
+{
+ char_u c;
+ int len;
+ char_u *retval;
+
+ retval = fname = vim_strsave(fname);
+ if (fname == NULL)
+ return NULL;
+
+ if (strncmp(fname, "$VIM/", 5) == 0)
+ {
+ strncpy(fname, "Vim:", 4);
+ for (fname += 5; c = *fname; fname++)
+ {
+ if (c == '.')
+ break;
+ if (c == '/')
+ fname[-1] = '.';
+ else
+ fname[-1] = c;
+ }
+ fname[-1] = '\0';
+ }
+ else
+ {
+ /* Check to see if the file exists without modification. */
+ if (xswi(OS_File, 17, fname) & v_flag)
+ r0 == 0; /* Invalid filename? */
+ if (r0)
+ return retval;
+
+ len = strlen(fname);
+ if (strcmp(fname + len - 4, ".vim") == 0)
+ {
+ fname[len - 4] = '\0';
+ for (; c = *fname; fname++)
+ {
+ if (c == '/')
+ *fname = '.';
+ }
+ }
+ }
+ return retval;
+}
+
+/* QuickFix reads munged names from the error file.
+ * Correct them.
+ */
+ int
+ro_buflist_add(old_name)
+ char_u *old_name; /* Name of file found by quickfix */
+{
+ char_u *fname;
+ char_u *leaf; /* Pointer to start of leaf in old_name */
+ char_u *ptr;
+ char_u c;
+ int retval;
+
+ if (old_name == NULL)
+ return buflist_add(NULL, 0);
+
+ /* Copy the name so we can mess around with it. */
+ fname = vim_strsave(old_name);
+ if (fname == NULL)
+ /* Out of memory - can't modify name */
+ return buflist_add(old_name, 0);
+
+ /* Change `dir/main.c' into `dir.c.main' */
+ leaf = fname;
+ for (ptr = fname; c = *ptr; ptr++)
+ {
+ if (c == '/')
+ {
+ leaf = ptr + 1;
+ *ptr = '.';
+ }
+ else if (c == '.')
+ break;
+ }
+ if (c == '.')
+ {
+ /* Change `main.c' into `c.main'
+ * | |
+ * leaf ptr
+ */
+ ptr += old_name - fname;
+ *ptr = '\0';
+ sprintf(leaf,
+ "%s.%s",
+ ptr + 1,
+ leaf - fname + old_name);
+ }
+
+ retval = buflist_add(fname, 0);
+ free(fname);
+ return retval;
+}
+
+/* Change the current directory.
+ * Strip trailing dots to make it easier to use with filename completion.
+ * Return 0 for success, -1 for failure.
+ */
+ int
+mch_chdir(dir)
+ char_u *dir;
+{
+ int length;
+ int retval;
+ char_u *new_dir;
+
+ length = strlen(dir);
+ if (dir[length - 1] != '.')
+ return chdir(dir); /* No trailing dots - nothing to do. */
+ new_dir = vim_strsave(dir);
+ if (new_dir == NULL)
+ return chdir(dir); /* Can't allocate memory. */
+
+ while (new_dir[--length] == '.')
+ new_dir[length] = '\0';
+
+ retval = chdir(new_dir);
+ vim_free(new_dir);
+ return retval;
+}
+
+/* Examine the named file, and set the 'osfiletype' option
+ * (in curbuf) to the file's type.
+ */
+ void
+mch_read_filetype(file)
+ char_u *file;
+{
+ int type;
+ char_u type_string[9];
+ int i;
+
+ if (xswi(OS_File, 23, file) & v_flag)
+ type = 0xfff; /* Default to Text */
+ else
+ type = r6;
+
+ /* Type is the numerical value - see if we have a textual equivalent */
+ swi(OS_FSControl, 18, 0, type);
+ ((int *) type_string)[0] = r2;
+ ((int *) type_string)[1] = r3;
+ type_string[8] = 0;
+ for (i = 0; type_string[i] > ' '; i++)
+ ;
+ type_string[i] = 0;
+
+ set_string_option_direct("osfiletype", -1, type_string, OPT_FREE);
+ return;
+}
+
+ void
+mch_set_filetype(file, type)
+ char_u *file;
+ char_u *type;
+{
+ if (xswi(OS_FSControl, 31, type) & v_flag)
+ {
+ EMSG(_("E366: Invalid 'osfiletype' option - using Text"));
+ r2 = 0xfff;
+ }
+
+ swi(OS_File, 18, file, r2);
+}
+
+/* Return TRUE if the file's type matches 'type'
+ * RISC OS types always start with '&'
+ */
+ int
+mch_check_filetype(fname, type)
+ char_u *fname;
+ char_u *type;
+{
+ int value;
+ char *end;
+
+ if (*type != '&')
+ return FALSE;
+
+ value = strtol(type + 1, &end, 16);
+ if (*end)
+ return FALSE; /* Invalid type (report error?) */
+
+ if (xswi(OS_File, 23, fname) & v_flag)
+ return FALSE; /* Invalid filename? */
+
+ return (r0 && r6 == value);
+}
diff --git a/src/os_riscos.h b/src/os_riscos.h
new file mode 100644
index 000000000..e7501d7f8
--- /dev/null
+++ b/src/os_riscos.h
@@ -0,0 +1,169 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <stdlib.h>
+#include <unixlib/local.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#define CASE_INSENSITIVE_FILENAME
+#define FEAT_MODIFY_FNAME
+#define FEAT_OSFILETYPE
+#define DFLT_OFT "Text"
+#define USE_TERM_CONSOLE
+#define HAVE_AVAIL_MEM
+
+/* Longer filenames now accessible to all */
+#ifndef BASENAMELEN
+# define BASENAMELEN 64 /* Same length as unzip */
+#endif
+
+#ifndef TEMNAME
+# define TEMPNAME "<Wimp$ScrapDir>.v?XXXXXX"
+# define TEMPNAMELEN 25
+#endif
+
+#ifndef DFLT_HELPFILE
+# define DFLT_HELPFILE "Vim:doc.help"
+#endif
+
+#ifndef DFLT_BDIR
+# define DFLT_BDIR ".,<Wimp$ScrapDir>." /* default for 'backupdir' */
+#endif
+
+/* Paths to try putting swap file in. */
+#ifndef DFLT_DIR
+# define DFLT_DIR "<Wimp$ScrapDir>.,." /* default for 'directory' */
+#endif
+
+#ifndef DFLT_VDIR
+# define DFLT_VDIR "Choices:Vim.view" /* default for 'viewdir' */
+#endif
+
+#ifndef TERMCAPFILE
+# define TERMCAPFILE "Vim:TermCap"
+#endif
+#define HAVE_TGETENT
+
+#ifndef SYNTAX_FNAME
+# define SYNTAX_FNAME "Vim:Syntax.%s"
+#endif
+
+#ifndef EVIM_FILE
+# define EVIM_FILE "Vim:Evim"
+#endif
+
+#define FEAT_VIMINFO
+
+#ifndef VIMINFO_FILE
+# define VIMINFO_FILE "<Choices$Write>.Vim.VimInfo"
+#endif
+#ifndef VIMINFO_FILE2
+# define VIMINFO_FILE2 "Choices:Vim.VimInfo"
+#endif
+
+#ifndef VIMRC_FILE
+# define VIMRC_FILE "/vimrc"
+#endif
+#ifndef EXRC_FILE
+# define EXRC_FILE "/exrc"
+#endif
+#ifndef GVIMRC_FILE
+# define GVIMRC_FILE "/gvimrc"
+#endif
+#ifndef VIEW_FILE
+# define VIEW_FILE "/View"
+#endif
+#ifndef USR_VIMRC_FILE
+# define USR_VIMRC_FILE "Vim:Evim"
+#endif
+#ifndef SESSION_FILE
+# define SESSION_FILE "/Session.vim"
+#endif
+#ifndef USR_VIMRC_FILE
+# define USR_VIMRC_FILE "Choices:Vim.VimRC"
+#endif
+#ifndef USR_GVIMRC_FILE
+# define USR_GVIMRC_FILE "Choices:Vim.GVimRC"
+#endif
+#ifndef USR_EXRC_FILE
+# define USR_EXRC_FILE "Choices:Vim.ExRC"
+#endif
+#ifndef SYS_VIMRC_FILE
+# define SYS_VIMRC_FILE "Vim:VimRC"
+#endif
+#ifndef SYS_GVIMRC_FILE
+# define SYS_GVIMRC_FILE "Vim:GVimRC"
+#endif
+#ifndef SYS_MENU_FILE
+# define SYS_MENU_FILE "Vim:Menu"
+#endif
+#ifndef SYS_OPTWIN_FILE
+# define SYS_OPTWIN_FILE "Vim:Optwin"
+#endif
+#ifndef FILETYPE_FILE
+# define FILETYPE_FILE "Vim:Filetype"
+#endif
+#ifndef FTPLUGIN_FILE
+# define FTPLUGIN_FILE "Vim:Ftplugin/vim"
+#endif
+#ifndef INDENT_FILE
+# define INDENT_FILE "Vim:Indent/vim"
+#endif
+#ifndef FTOFF_FILE
+# define FTOFF_FILE "Vim:Ftoff"
+#endif
+#ifndef FTPLUGOF_FILE
+# define FTPLUGOF_FILE "Vim:Ftplugof"
+#endif
+#ifndef INDOFF_FILE
+# define INDOFF_FILE "Vim:Indoff"
+#endif
+
+#define DFLT_ERRORFILE "errors/vim"
+#define DFLT_RUNTIMEPATH "Choices:Vim,Vim:,Choices:Vim.after"
+
+/*
+ * RISC PCs have plenty of memory, use large buffers
+ */
+#define CMDBUFFSIZE 1024 /* size of the command processing buffer */
+#define MAXPATHL 256 /* paths are always quite short though */
+
+#ifndef DFLT_MAXMEM
+# define DFLT_MAXMEM (5*1024) /* use up to 5 Mbyte for a buffer */
+#endif
+
+#ifndef DFLT_MAXMEMTOT
+# define DFLT_MAXMEMTOT (10*1024) /* use up to 10 Mbyte for Vim */
+#endif
+
+#ifdef HAVE_SIGSET
+# define signal sigset
+#endif
+
+#define n_flag (1<<31)
+#define z_flag (1<<30)
+#define c_flag (1<<29)
+#define v_flag (1<<28)
+
+/* These take r0-r7 as inputs, returns r0-r7 in global variables. */
+void swi(int swinum, ...); /* Handles errors itself */
+int xswi(int swinum, ...); /* Returns errors using v flag */
+extern int r0, r1, r2, r3, r4, r5, r6, r7; /* For return values */
+
+#include <kernel.h>
+#include <swis.h>
+
+#define mch_memmove(to, from, len) memmove((char *)(to), (char *)(from), len)
+#define mch_rename(src, dst) rename(src, dst)
+#define mch_getenv(x) (char_u *)getenv((char *)x)
+#define mch_setenv(name, val, x) setenv(name, val, x)
diff --git a/src/os_unix.c b/src/os_unix.c
new file mode 100644
index 000000000..b59d8ff5d
--- /dev/null
+++ b/src/os_unix.c
@@ -0,0 +1,6189 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * OS/2 port by Paul Slootman
+ * VMS merge by Zoltan Arpadffy
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * os_unix.c -- code for all flavors of Unix (BSD, SYSV, SVR4, POSIX, ...)
+ * Also for OS/2, using the excellent EMX package!!!
+ * Also for BeOS and Atari MiNT.
+ *
+ * A lot of this file was originally written by Juergen Weigert and later
+ * changed beyond recognition.
+ */
+
+/*
+ * Some systems have a prototype for select() that has (int *) instead of
+ * (fd_set *), which is wrong. This define removes that prototype. We define
+ * our own prototype below.
+ * Don't use it for the Mac, it causes a warning for precompiled headers.
+ * TODO: use a configure check for precompiled headers?
+ */
+#ifndef __APPLE__
+# define select select_declared_wrong
+#endif
+
+#include "vim.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#include "os_unixx.h" /* unix includes for os_unix.c only */
+
+#ifdef USE_XSMP
+# include <X11/SM/SMlib.h>
+#endif
+
+/*
+ * Use this prototype for select, some include files have a wrong prototype
+ */
+#undef select
+#ifdef __BEOS__
+# define select beos_select
+#endif
+
+#if defined(HAVE_SELECT)
+extern int select __ARGS((int, fd_set *, fd_set *, fd_set *, struct timeval *));
+#endif
+
+#ifdef FEAT_MOUSE_GPM
+# include <gpm.h>
+/* <linux/keyboard.h> contains defines conflicting with "keymap.h",
+ * I just copied relevant defines here. A cleaner solution would be to put gpm
+ * code into separate file and include there linux/keyboard.h
+ */
+/* #include <linux/keyboard.h> */
+# define KG_SHIFT 0
+# define KG_CTRL 2
+# define KG_ALT 3
+# define KG_ALTGR 1
+# define KG_SHIFTL 4
+# define KG_SHIFTR 5
+# define KG_CTRLL 6
+# define KG_CTRLR 7
+# define KG_CAPSSHIFT 8
+
+static void gpm_close __ARGS((void));
+static int gpm_open __ARGS((void));
+static int mch_gpm_process __ARGS((void));
+#endif
+
+/*
+ * end of autoconf section. To be extended...
+ */
+
+/* Are the following #ifdefs still required? And why? Is that for X11? */
+
+#if defined(ESIX) || defined(M_UNIX) && !defined(SCO)
+# ifdef SIGWINCH
+# undef SIGWINCH
+# endif
+# ifdef TIOCGWINSZ
+# undef TIOCGWINSZ
+# endif
+#endif
+
+#if defined(SIGWINDOW) && !defined(SIGWINCH) /* hpux 9.01 has it */
+# define SIGWINCH SIGWINDOW
+#endif
+
+#ifdef FEAT_X11
+# include <X11/Xlib.h>
+# include <X11/Xutil.h>
+# include <X11/Xatom.h>
+# ifdef FEAT_XCLIPBOARD
+# include <X11/Intrinsic.h>
+# include <X11/Shell.h>
+# include <X11/StringDefs.h>
+static Widget xterm_Shell = (Widget)0;
+static void xterm_update __ARGS((void));
+# endif
+
+# if defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE)
+Window x11_window = 0;
+# endif
+Display *x11_display = NULL;
+
+# ifdef FEAT_TITLE
+static int get_x11_windis __ARGS((void));
+static void set_x11_title __ARGS((char_u *));
+static void set_x11_icon __ARGS((char_u *));
+# endif
+#endif
+
+#ifdef FEAT_TITLE
+static int get_x11_title __ARGS((int));
+static int get_x11_icon __ARGS((int));
+
+static char_u *oldtitle = NULL;
+static int did_set_title = FALSE;
+static char_u *oldicon = NULL;
+static int did_set_icon = FALSE;
+#endif
+
+static void may_core_dump __ARGS((void));
+
+static int WaitForChar __ARGS((long));
+#if defined(__BEOS__)
+int RealWaitForChar __ARGS((int, long, int *));
+#else
+static int RealWaitForChar __ARGS((int, long, int *));
+#endif
+
+#ifdef FEAT_XCLIPBOARD
+static int do_xterm_trace __ARGS((void));
+#define XT_TRACE_DELAY 50 /* delay for xterm tracing */
+#endif
+
+static void handle_resize __ARGS((void));
+
+#if defined(SIGWINCH)
+static RETSIGTYPE sig_winch __ARGS(SIGPROTOARG);
+#endif
+#if defined(SIGINT)
+static RETSIGTYPE catch_sigint __ARGS(SIGPROTOARG);
+#endif
+#if defined(SIGPWR)
+static RETSIGTYPE catch_sigpwr __ARGS(SIGPROTOARG);
+#endif
+#if defined(SIGALRM) && defined(FEAT_X11) \
+ && defined(FEAT_TITLE) && !defined(FEAT_GUI_GTK)
+# define SET_SIG_ALARM
+static RETSIGTYPE sig_alarm __ARGS(SIGPROTOARG);
+static int sig_alarm_called;
+#endif
+static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
+
+static void set_signals __ARGS((void));
+static void catch_signals __ARGS((RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()));
+#ifndef __EMX__
+static int have_wildcard __ARGS((int, char_u **));
+static int have_dollars __ARGS((int, char_u **));
+#endif
+
+#ifndef NO_EXPANDPATH
+static int pstrcmp __ARGS((const void *, const void *));
+static int unix_expandpath __ARGS((garray_T *gap, char_u *path, int wildoff, int flags));
+#endif
+
+#ifndef __EMX__
+static int save_patterns __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file));
+#endif
+
+#ifndef SIG_ERR
+# define SIG_ERR ((RETSIGTYPE (*)())-1)
+#endif
+
+static int do_resize = FALSE;
+#ifndef __EMX__
+static char_u *extra_shell_arg = NULL;
+static int show_shell_mess = TRUE;
+#endif
+static int deadly_signal = 0; /* The signal we caught */
+
+static int curr_tmode = TMODE_COOK; /* contains current terminal mode */
+
+#ifdef USE_XSMP
+typedef struct
+{
+ SmcConn smcconn; /* The SM connection ID */
+ IceConn iceconn; /* The ICE connection ID */
+ Bool save_yourself; /* If we're in the middle of a save_yourself */
+ Bool shutdown; /* If we're in shutdown mode */
+} xsmp_config_T;
+
+static xsmp_config_T xsmp;
+#endif
+
+#ifdef SYS_SIGLIST_DECLARED
+/*
+ * I have seen
+ * extern char *_sys_siglist[NSIG];
+ * on Irix, Linux, NetBSD and Solaris. It contains a nice list of strings
+ * that describe the signals. That is nearly what we want here. But
+ * autoconf does only check for sys_siglist (without the underscore), I
+ * do not want to change everything today.... jw.
+ * This is why AC_DECL_SYS_SIGLIST is commented out in configure.in
+ */
+#endif
+
+static struct signalinfo
+{
+ int sig; /* Signal number, eg. SIGSEGV etc */
+ char *name; /* Signal name (not char_u!). */
+ char deadly; /* Catch as a deadly signal? */
+} signal_info[] =
+{
+#ifdef SIGHUP
+ {SIGHUP, "HUP", TRUE},
+#endif
+#ifdef SIGQUIT
+ {SIGQUIT, "QUIT", TRUE},
+#endif
+#ifdef SIGILL
+ {SIGILL, "ILL", TRUE},
+#endif
+#ifdef SIGTRAP
+ {SIGTRAP, "TRAP", TRUE},
+#endif
+#ifdef SIGABRT
+ {SIGABRT, "ABRT", TRUE},
+#endif
+#ifdef SIGEMT
+ {SIGEMT, "EMT", TRUE},
+#endif
+#ifdef SIGFPE
+ {SIGFPE, "FPE", TRUE},
+#endif
+#ifdef SIGBUS
+ {SIGBUS, "BUS", TRUE},
+#endif
+#ifdef SIGSEGV
+ {SIGSEGV, "SEGV", TRUE},
+#endif
+#ifdef SIGSYS
+ {SIGSYS, "SYS", TRUE},
+#endif
+#ifdef SIGALRM
+ {SIGALRM, "ALRM", FALSE}, /* Perl's alarm() can trigger it */
+#endif
+#ifdef SIGTERM
+ {SIGTERM, "TERM", TRUE},
+#endif
+#ifdef SIGVTALRM
+ {SIGVTALRM, "VTALRM", TRUE},
+#endif
+#ifdef SIGPROF
+ {SIGPROF, "PROF", TRUE},
+#endif
+#ifdef SIGXCPU
+ {SIGXCPU, "XCPU", TRUE},
+#endif
+#ifdef SIGXFSZ
+ {SIGXFSZ, "XFSZ", TRUE},
+#endif
+#ifdef SIGUSR1
+ {SIGUSR1, "USR1", TRUE},
+#endif
+#ifdef SIGUSR2
+ {SIGUSR2, "USR2", TRUE},
+#endif
+#ifdef SIGINT
+ {SIGINT, "INT", FALSE},
+#endif
+#ifdef SIGWINCH
+ {SIGWINCH, "WINCH", FALSE},
+#endif
+#ifdef SIGTSTP
+ {SIGTSTP, "TSTP", FALSE},
+#endif
+#ifdef SIGPIPE
+ {SIGPIPE, "PIPE", FALSE},
+#endif
+ {-1, "Unknown!", FALSE}
+};
+
+ void
+mch_write(s, len)
+ char_u *s;
+ int len;
+{
+ write(1, (char *)s, len);
+ if (p_wd) /* Unix is too fast, slow down a bit more */
+ RealWaitForChar(read_cmd_fd, p_wd, NULL);
+}
+
+/*
+ * mch_inchar(): low level input funcion.
+ * Get a characters from the keyboard.
+ * Return the number of characters that are available.
+ * If wtime == 0 do not wait for characters.
+ * If wtime == n wait a short time for characters.
+ * If wtime == -1 wait forever for characters.
+ */
+ int
+mch_inchar(buf, maxlen, wtime, tb_change_cnt)
+ char_u *buf;
+ int maxlen;
+ long wtime; /* don't use "time", MIPS cannot handle it */
+ int tb_change_cnt;
+{
+ int len;
+#ifdef FEAT_AUTOCMD
+ static int once_already = 0;
+#endif
+
+ /* Check if window changed size while we were busy, perhaps the ":set
+ * columns=99" command was used. */
+ while (do_resize)
+ handle_resize();
+
+ if (wtime >= 0)
+ {
+ while (WaitForChar(wtime) == 0) /* no character available */
+ {
+ if (!do_resize) /* return if not interrupted by resize */
+ {
+#ifdef FEAT_AUTOCMD
+ once_already = 0;
+#endif
+ return 0;
+ }
+ handle_resize();
+ }
+ }
+ else /* wtime == -1 */
+ {
+#ifdef FEAT_AUTOCMD
+ if (once_already == 2)
+ updatescript(0);
+ else if (once_already == 1)
+ {
+ setcursor();
+ once_already = 2;
+ return 0;
+ }
+ else
+#endif
+ /*
+ * If there is no character available within 'updatetime' seconds
+ * flush all the swap files to disk
+ * Also done when interrupted by SIGWINCH.
+ */
+ if (WaitForChar(p_ut) == 0)
+ {
+#ifdef FEAT_AUTOCMD
+ if (has_cursorhold() && get_real_state() == NORMAL_BUSY)
+ {
+ apply_autocmds(EVENT_CURSORHOLD, NULL, NULL, FALSE, curbuf);
+ update_screen(VALID);
+ once_already = 1;
+ return 0;
+ }
+ else
+#endif
+ updatescript(0);
+ }
+ }
+
+ for (;;) /* repeat until we got a character */
+ {
+ while (do_resize) /* window changed size */
+ handle_resize();
+ /*
+ * we want to be interrupted by the winch signal
+ */
+ WaitForChar(-1L);
+ if (do_resize) /* interrupted by SIGWINCH signal */
+ continue;
+
+ /* If input was put directly in typeahead buffer bail out here. */
+ if (typebuf_changed(tb_change_cnt))
+ return 0;
+
+ /*
+ * For some terminals we only get one character at a time.
+ * We want the get all available characters, so we could keep on
+ * trying until none is available
+ * For some other terminals this is quite slow, that's why we don't do
+ * it.
+ */
+ len = read_from_input_buf(buf, (long)maxlen);
+ if (len > 0)
+ {
+#ifdef OS2
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (buf[i] == 0)
+ buf[i] = K_NUL;
+#endif
+#ifdef FEAT_AUTOCMD
+ once_already = 0;
+#endif
+ return len;
+ }
+ }
+}
+
+ static void
+handle_resize()
+{
+ do_resize = FALSE;
+ shell_resized();
+}
+
+/*
+ * return non-zero if a character is available
+ */
+ int
+mch_char_avail()
+{
+ return WaitForChar(0L);
+}
+
+#if defined(HAVE_TOTAL_MEM) || defined(PROTO)
+# ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+# endif
+# if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTL)
+# include <sys/sysctl.h>
+# endif
+# if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
+# include <sys/sysinfo.h>
+# endif
+
+/*
+ * Return total amount of memory available. Doesn't change when memory has
+ * been allocated.
+ */
+/* ARGSUSED */
+ long_u
+mch_total_mem(special)
+ int special;
+{
+# ifdef __EMX__
+ return ulimit(3, 0L); /* always 32MB? */
+# else
+ long_u mem = 0;
+
+# ifdef HAVE_SYSCTL
+ int mib[2], physmem;
+ size_t len;
+
+ /* BSD way of getting the amount of RAM available. */
+ mib[0] = CTL_HW;
+ mib[1] = HW_USERMEM;
+ len = sizeof(physmem);
+ if (sysctl(mib, 2, &physmem, &len, NULL, 0) == 0)
+ mem = (long_u)physmem;
+# endif
+
+# if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
+ if (mem == 0)
+ {
+ struct sysinfo sinfo;
+
+ /* Linux way of getting amount of RAM available */
+ if (sysinfo(&sinfo) == 0)
+ mem = sinfo.totalram;
+ }
+# endif
+
+# ifdef HAVE_SYSCONF
+ if (mem == 0)
+ {
+ long pagesize, pagecount;
+
+ /* Solaris way of getting amount of RAM available */
+ pagesize = sysconf(_SC_PAGESIZE);
+ pagecount = sysconf(_SC_PHYS_PAGES);
+ if (pagesize > 0 && pagecount > 0)
+ mem = (long_u)pagesize * pagecount;
+ }
+# endif
+
+ /* Return the minimum of the physical memory and the user limit, because
+ * using more than the user limit may cause Vim to be terminated. */
+# if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT)
+ {
+ struct rlimit rlp;
+
+ if (getrlimit(RLIMIT_DATA, &rlp) == 0
+ && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
+# ifdef RLIM_INFINITY
+ && rlp.rlim_cur != RLIM_INFINITY
+# endif
+ && (long_u)rlp.rlim_cur < mem
+ )
+ return (long_u)rlp.rlim_cur;
+ }
+# endif
+
+ if (mem > 0)
+ return mem;
+ return (long_u)0x7fffffff;
+# endif
+}
+#endif
+
+ void
+mch_delay(msec, ignoreinput)
+ long msec;
+ int ignoreinput;
+{
+ int old_tmode;
+
+ if (ignoreinput)
+ {
+ /* Go to cooked mode without echo, to allow SIGINT interrupting us
+ * here */
+ old_tmode = curr_tmode;
+ if (curr_tmode == TMODE_RAW)
+ settmode(TMODE_SLEEP);
+
+ /*
+ * Everybody sleeps in a different way...
+ * Prefer nanosleep(), some versions of usleep() can only sleep up to
+ * one second.
+ */
+#ifdef HAVE_NANOSLEEP
+ {
+ struct timespec ts;
+
+ ts.tv_sec = msec / 1000;
+ ts.tv_nsec = (msec % 1000) * 1000000;
+ (void)nanosleep(&ts, NULL);
+ }
+#else
+# ifdef HAVE_USLEEP
+ while (msec >= 1000)
+ {
+ usleep((unsigned int)(999 * 1000));
+ msec -= 999;
+ }
+ usleep((unsigned int)(msec * 1000));
+# else
+# ifndef HAVE_SELECT
+ poll(NULL, 0, (int)msec);
+# else
+# ifdef __EMX__
+ _sleep2(msec);
+# else
+ {
+ struct timeval tv;
+
+ tv.tv_sec = msec / 1000;
+ tv.tv_usec = (msec % 1000) * 1000;
+ /*
+ * NOTE: Solaris 2.6 has a bug that makes select() hang here. Get
+ * a patch from Sun to fix this. Reported by Gunnar Pedersen.
+ */
+ select(0, NULL, NULL, NULL, &tv);
+ }
+# endif /* __EMX__ */
+# endif /* HAVE_SELECT */
+# endif /* HAVE_NANOSLEEP */
+#endif /* HAVE_USLEEP */
+
+ settmode(old_tmode);
+ }
+ else
+ WaitForChar(msec);
+}
+
+#if defined(HAVE_GETRLIMIT) \
+ || (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK))
+# define HAVE_CHECK_STACK_GROWTH
+/*
+ * Support for checking for an almost-out-of-stack-space situation.
+ */
+
+/*
+ * Return a pointer to an item on the stack. Used to find out if the stack
+ * grows up or down.
+ */
+static void check_stack_growth __ARGS((char *p));
+static int stack_grows_downwards;
+
+/*
+ * Find out if the stack grows upwards or downwards.
+ * "p" points to a variable on the stack of the caller.
+ */
+ static void
+check_stack_growth(p)
+ char *p;
+{
+ int i;
+
+ stack_grows_downwards = (p > (char *)&i);
+}
+#endif
+
+#if defined(HAVE_GETRLIMIT) || defined(PROTO)
+static char *stack_limit = NULL;
+
+#if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
+# include <pthread.h>
+# include <pthread_np.h>
+#endif
+
+/*
+ * Find out until how var the stack can grow without getting into trouble.
+ * Called when starting up and when switching to the signal stack in
+ * deathtrap().
+ */
+ static void
+get_stack_limit()
+{
+ struct rlimit rlp;
+ int i;
+ long lim;
+
+ /* Set the stack limit to 15/16 of the allowable size. Skip this when the
+ * limit doesn't fit in a long (rlim_cur might be "long long"). */
+ if (getrlimit(RLIMIT_STACK, &rlp) == 0
+ && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
+# ifdef RLIM_INFINITY
+ && rlp.rlim_cur != RLIM_INFINITY
+# endif
+ )
+ {
+ lim = (long)rlp.rlim_cur;
+#if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
+ {
+ pthread_attr_t attr;
+ size_t size;
+
+ /* On FreeBSD the initial thread always has a fixed stack size, no
+ * matter what the limits are set to. Normally it's 1 Mbyte. */
+ pthread_attr_init(&attr);
+ if (pthread_attr_get_np(pthread_self(), &attr) == 0)
+ {
+ pthread_attr_getstacksize(&attr, &size);
+ if (lim > (long)size)
+ lim = (long)size;
+ }
+ pthread_attr_destroy(&attr);
+ }
+#endif
+ if (stack_grows_downwards)
+ {
+ stack_limit = (char *)((long)&i - (lim / 16L * 15L));
+ if (stack_limit >= (char *)&i)
+ /* overflow, set to 1/16 of current stack position */
+ stack_limit = (char *)((long)&i / 16L);
+ }
+ else
+ {
+ stack_limit = (char *)((long)&i + (lim / 16L * 15L));
+ if (stack_limit <= (char *)&i)
+ stack_limit = NULL; /* overflow */
+ }
+ }
+}
+
+/*
+ * Return FAIL when running out of stack space.
+ * "p" must point to any variable local to the caller that's on the stack.
+ */
+ int
+mch_stackcheck(p)
+ char *p;
+{
+ if (stack_limit != NULL)
+ {
+ if (stack_grows_downwards)
+ {
+ if (p < stack_limit)
+ return FAIL;
+ }
+ else if (p > stack_limit)
+ return FAIL;
+ }
+ return OK;
+}
+#endif
+
+#if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
+/*
+ * Support for using the signal stack.
+ * This helps when we run out of stack space, which causes a SIGSEGV. The
+ * signal handler then must run on another stack, since the normal stack is
+ * completely full.
+ */
+
+#ifndef SIGSTKSZ
+# define SIGSTKSZ 8000 /* just a guess of how much stack is needed... */
+#endif
+
+# ifdef HAVE_SIGALTSTACK
+static stack_t sigstk; /* for sigaltstack() */
+# else
+static struct sigstack sigstk; /* for sigstack() */
+# endif
+
+static void init_signal_stack __ARGS((void));
+static char *signal_stack;
+
+ static void
+init_signal_stack()
+{
+ if (signal_stack != NULL)
+ {
+# ifdef HAVE_SIGALTSTACK
+# ifdef __APPLE__
+ /* missing prototype. Adding it to osdef?.h.in doesn't work, because
+ * "struct sigaltstack" needs to be declared. */
+ extern int sigaltstack __ARGS((const struct sigaltstack *ss, struct sigaltstack *oss));
+# endif
+
+# ifdef HAVE_SS_BASE
+ sigstk.ss_base = signal_stack;
+# else
+ sigstk.ss_sp = signal_stack;
+# endif
+ sigstk.ss_size = SIGSTKSZ;
+ sigstk.ss_flags = 0;
+ (void)sigaltstack(&sigstk, NULL);
+# else
+ sigstk.ss_sp = signal_stack;
+ if (stack_grows_downwards)
+ sigstk.ss_sp += SIGSTKSZ - 1;
+ sigstk.ss_onstack = 0;
+ (void)sigstack(&sigstk, NULL);
+# endif
+ }
+}
+#endif
+
+/*
+ * We need correct potatotypes for a signal function, otherwise mean compilers
+ * will barf when the second argument to signal() is ``wrong''.
+ * Let me try it with a few tricky defines from my own osdef.h (jw).
+ */
+#if defined(SIGWINCH)
+/* ARGSUSED */
+ static RETSIGTYPE
+sig_winch SIGDEFARG(sigarg)
+{
+ /* this is not required on all systems, but it doesn't hurt anybody */
+ signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
+ do_resize = TRUE;
+ SIGRETURN;
+}
+#endif
+
+#if defined(SIGINT)
+/* ARGSUSED */
+ static RETSIGTYPE
+catch_sigint SIGDEFARG(sigarg)
+{
+ /* this is not required on all systems, but it doesn't hurt anybody */
+ signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
+ got_int = TRUE;
+ SIGRETURN;
+}
+#endif
+
+#if defined(SIGPWR)
+/* ARGSUSED */
+ static RETSIGTYPE
+catch_sigpwr SIGDEFARG(sigarg)
+{
+ /*
+ * I'm not sure we get the SIGPWR signal when the system is really going
+ * down or when the batteries are almost empty. Just preserve the swap
+ * files and don't exit, that can't do any harm.
+ */
+ ml_sync_all(FALSE, FALSE);
+ SIGRETURN;
+}
+#endif
+
+#ifdef SET_SIG_ALARM
+/*
+ * signal function for alarm().
+ */
+/* ARGSUSED */
+ static RETSIGTYPE
+sig_alarm SIGDEFARG(sigarg)
+{
+ /* doesn't do anything, just to break a system call */
+ sig_alarm_called = TRUE;
+ SIGRETURN;
+}
+#endif
+
+#if defined(HAVE_SETJMP_H) || defined(PROTO)
+/*
+ * A simplistic version of setjmp() that only allows one level of using.
+ * Don't call twice before calling mch_endjmp()!.
+ * Usage:
+ * mch_startjmp();
+ * if (SETJMP(lc_jump_env) != 0)
+ * {
+ * mch_didjmp();
+ * EMSG("crash!");
+ * }
+ * else
+ * {
+ * do_the_work;
+ * mch_endjmp();
+ * }
+ * Note: Can't move SETJMP() here, because a function calling setjmp() must
+ * not return before the saved environment is used.
+ * Returns OK for normal return, FAIL when the protected code caused a
+ * problem and LONGJMP() was used.
+ */
+ void
+mch_startjmp()
+{
+#ifdef SIGHASARG
+ lc_signal = 0;
+#endif
+ lc_active = TRUE;
+}
+
+ void
+mch_endjmp()
+{
+ lc_active = FALSE;
+}
+
+ void
+mch_didjmp()
+{
+# if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
+ /* On FreeBSD the signal stack has to be reset after using siglongjmp(),
+ * otherwise catching the signal only works once. */
+ init_signal_stack();
+# endif
+}
+#endif
+
+/*
+ * This function handles deadly signals.
+ * It tries to preserve any swap file and exit properly.
+ * (partly from Elvis).
+ */
+ static RETSIGTYPE
+deathtrap SIGDEFARG(sigarg)
+{
+ static int entered = 0; /* count the number of times we got here.
+ Note: when memory has been corrupted
+ this may get an arbitrary value! */
+#ifdef SIGHASARG
+ int i;
+#endif
+
+#if defined(HAVE_SETJMP_H)
+ /*
+ * Catch a crash in protected code.
+ * Restores the environment saved in lc_jump_env, which looks like
+ * SETJMP() returns 1.
+ */
+ if (lc_active)
+ {
+# if defined(SIGHASARG)
+ lc_signal = sigarg;
+# endif
+ lc_active = FALSE; /* don't jump again */
+ LONGJMP(lc_jump_env, 1);
+ /* NOTREACHED */
+ }
+#endif
+
+ /* Remember how often we have been called. */
+ ++entered;
+
+#ifdef FEAT_EVAL
+ /* Set the v:dying variable. */
+ set_vim_var_nr(VV_DYING, (long)entered);
+#endif
+
+#ifdef HAVE_GETRLIMIT
+ /* Since we are now using the signal stack, need to reset the stack
+ * limit. Otherwise using a regexp will fail. */
+ get_stack_limit();
+#endif
+
+#ifdef SIGHASARG
+ /* try to find the name of this signal */
+ for (i = 0; signal_info[i].sig != -1; i++)
+ if (sigarg == signal_info[i].sig)
+ break;
+ deadly_signal = sigarg;
+#endif
+
+ full_screen = FALSE; /* don't write message to the GUI, it might be
+ * part of the problem... */
+ /*
+ * If something goes wrong after entering here, we may get here again.
+ * When this happens, give a message and try to exit nicely (resetting the
+ * terminal mode, etc.)
+ * When this happens twice, just exit, don't even try to give a message,
+ * stack may be corrupt or something weird.
+ * When this still happens again (or memory was corrupted in such a way
+ * that "entered" was clobbered) use _exit(), don't try freeing resources.
+ */
+ if (entered >= 3)
+ {
+ reset_signals(); /* don't catch any signals anymore */
+ may_core_dump();
+ if (entered >= 4)
+ _exit(8);
+ exit(7);
+ }
+ if (entered == 2)
+ {
+ OUT_STR(_("Vim: Double signal, exiting\n"));
+ out_flush();
+ getout(1);
+ }
+
+#ifdef SIGHASARG
+ sprintf((char *)IObuff, _("Vim: Caught deadly signal %s\n"),
+ signal_info[i].name);
+#else
+ sprintf((char *)IObuff, _("Vim: Caught deadly signal\n"));
+#endif
+ preserve_exit(); /* preserve files and exit */
+
+ SIGRETURN;
+}
+
+#ifdef _REENTRANT
+/*
+ * On Solaris with multi-threading, suspending might not work immediately.
+ * Catch the SIGCONT signal, which will be used as an indication whether the
+ * suspending has been done or not.
+ */
+static int sigcont_received;
+static RETSIGTYPE sigcont_handler __ARGS(SIGPROTOARG);
+
+/*
+ * signal handler for SIGCONT
+ */
+/* ARGSUSED */
+ static RETSIGTYPE
+sigcont_handler SIGDEFARG(sigarg)
+{
+ sigcont_received = TRUE;
+ SIGRETURN;
+}
+#endif
+
+/*
+ * If the machine has job control, use it to suspend the program,
+ * otherwise fake it by starting a new shell.
+ */
+ void
+mch_suspend()
+{
+ /* BeOS does have SIGTSTP, but it doesn't work. */
+#if defined(SIGTSTP) && !defined(__BEOS__)
+ out_flush(); /* needed to make cursor visible on some systems */
+ settmode(TMODE_COOK);
+ out_flush(); /* needed to disable mouse on some systems */
+
+# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
+ /* Since we are going to sleep, we can't respond to requests for the X
+ * selections. Lose them, otherwise other applications will hang. But
+ * first copy the text to cut buffer 0. */
+ if (clip_star.owned || clip_plus.owned)
+ {
+ x11_export_final_selection();
+ if (clip_star.owned)
+ clip_lose_selection(&clip_star);
+ if (clip_plus.owned)
+ clip_lose_selection(&clip_plus);
+ if (x11_display != NULL)
+ XFlush(x11_display);
+ }
+# endif
+
+# ifdef _REENTRANT
+ sigcont_received = FALSE;
+# endif
+ kill(0, SIGTSTP); /* send ourselves a STOP signal */
+# ifdef _REENTRANT
+ /* When we didn't suspend immediately in the kill(), do it now. Happens
+ * on multi-threaded Solaris. */
+ if (!sigcont_received)
+ pause();
+# endif
+
+# ifdef FEAT_TITLE
+ /*
+ * Set oldtitle to NULL, so the current title is obtained again.
+ */
+ vim_free(oldtitle);
+ oldtitle = NULL;
+# endif
+ settmode(TMODE_RAW);
+ need_check_timestamps = TRUE;
+ did_check_timestamps = FALSE;
+#else
+ suspend_shell();
+#endif
+}
+
+ void
+mch_init()
+{
+ Columns = 80;
+ Rows = 24;
+
+ out_flush();
+ set_signals();
+}
+
+ static void
+set_signals()
+{
+#if defined(SIGWINCH)
+ /*
+ * WINDOW CHANGE signal is handled with sig_winch().
+ */
+ signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
+#endif
+
+ /*
+ * We want the STOP signal to work, to make mch_suspend() work.
+ * For "rvim" the STOP signal is ignored.
+ */
+#ifdef SIGTSTP
+ signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
+#endif
+#ifdef _REENTRANT
+ signal(SIGCONT, sigcont_handler);
+#endif
+
+ /*
+ * We want to ignore breaking of PIPEs.
+ */
+#ifdef SIGPIPE
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ /*
+ * We want to catch CTRL-C (only works while in Cooked mode).
+ */
+#ifdef SIGINT
+ signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
+#endif
+
+ /*
+ * Ignore alarm signals (Perl's alarm() generates it).
+ */
+#ifdef SIGALRM
+ signal(SIGALRM, SIG_IGN);
+#endif
+
+ /*
+ * Catch SIGPWR (power failure?) to preserve the swap files, so that no
+ * work will be lost.
+ */
+#ifdef SIGPWR
+ signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
+#endif
+
+ /*
+ * Arrange for other signals to gracefully shutdown Vim.
+ */
+ catch_signals(deathtrap, SIG_ERR);
+
+#if defined(FEAT_GUI) && defined(SIGHUP)
+ /*
+ * When the GUI is running, ignore the hangup signal.
+ */
+ if (gui.in_use)
+ signal(SIGHUP, SIG_IGN);
+#endif
+}
+
+ void
+reset_signals()
+{
+ catch_signals(SIG_DFL, SIG_DFL);
+#ifdef _REENTRANT
+ /* SIGCONT isn't in the list, because its default action is ignore */
+ signal(SIGCONT, SIG_DFL);
+#endif
+}
+
+ static void
+catch_signals(func_deadly, func_other)
+ RETSIGTYPE (*func_deadly)();
+ RETSIGTYPE (*func_other)();
+{
+ int i;
+
+ for (i = 0; signal_info[i].sig != -1; i++)
+ if (signal_info[i].deadly)
+ {
+#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
+ struct sigaction sa;
+
+ /* Setup to use the alternate stack for the signal function. */
+ sa.sa_handler = func_deadly;
+ sigemptyset(&sa.sa_mask);
+# if defined(__linux__) && defined(_REENTRANT)
+ /* On Linux, with glibc compiled for kernel 2.2, there is a bug in
+ * thread handling in combination with using the alternate stack:
+ * pthread library functions try to use the stack pointer to
+ * identify the current thread, causing a SEGV signal, which
+ * recursively calls deathtrap() and hangs. */
+ sa.sa_flags = 0;
+# else
+ sa.sa_flags = SA_ONSTACK;
+# endif
+ sigaction(signal_info[i].sig, &sa, NULL);
+#else
+# if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGVEC)
+ struct sigvec sv;
+
+ /* Setup to use the alternate stack for the signal function. */
+ sv.sv_handler = func_deadly;
+ sv.sv_mask = 0;
+ sv.sv_flags = SV_ONSTACK;
+ sigvec(signal_info[i].sig, &sv, NULL);
+# else
+ signal(signal_info[i].sig, func_deadly);
+# endif
+#endif
+ }
+ else if (func_other != SIG_ERR)
+ signal(signal_info[i].sig, func_other);
+}
+
+/*
+ * Check_win checks whether we have an interactive stdout.
+ */
+/* ARGSUSED */
+ int
+mch_check_win(argc, argv)
+ int argc;
+ char **argv;
+{
+#ifdef OS2
+ /*
+ * Store argv[0], may be used for $VIM. Only use it if it is an absolute
+ * name, mostly it's just "vim" and found in the path, which is unusable.
+ */
+ if (mch_isFullName(argv[0]))
+ exe_name = vim_strsave((char_u *)argv[0]);
+#endif
+ if (isatty(1))
+ return OK;
+ return FAIL;
+}
+
+/*
+ * Return TRUE if the input comes from a terminal, FALSE otherwise.
+ */
+ int
+mch_input_isatty()
+{
+ if (isatty(read_cmd_fd))
+ return TRUE;
+ return FALSE;
+}
+
+#ifdef FEAT_X11
+
+# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \
+ && (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE))
+
+static void xopen_message __ARGS((struct timeval *tvp));
+
+/*
+ * Give a message about the elapsed time for opening the X window.
+ */
+ static void
+xopen_message(tvp)
+ struct timeval *tvp; /* must contain start time */
+{
+ struct timeval end_tv;
+
+ /* Compute elapsed time. */
+ gettimeofday(&end_tv, NULL);
+ smsg((char_u *)_("Opening the X display took %ld msec"),
+ (end_tv.tv_sec - tvp->tv_sec) * 1000L
+ + (end_tv.tv_usec - tvp->tv_usec) / 1000L);
+}
+# endif
+#endif
+
+#if defined(FEAT_X11) && (defined(FEAT_TITLE) || defined(FEAT_XCLIPBOARD))
+/*
+ * A few functions shared by X11 title and clipboard code.
+ */
+static int x_error_handler __ARGS((Display *dpy, XErrorEvent *error_event));
+static int x_error_check __ARGS((Display *dpy, XErrorEvent *error_event));
+static int x_connect_to_server __ARGS((void));
+static int test_x11_window __ARGS((Display *dpy));
+
+static int got_x_error = FALSE;
+
+/*
+ * X Error handler, otherwise X just exits! (very rude) -- webb
+ */
+ static int
+x_error_handler(dpy, error_event)
+ Display *dpy;
+ XErrorEvent *error_event;
+{
+ XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
+ STRCAT(IObuff, _("\nVim: Got X error\n"));
+
+ /* We cannot print a message and continue, because no X calls are allowed
+ * here (causes my system to hang). Silently continuing might be an
+ * alternative... */
+ preserve_exit(); /* preserve files and exit */
+
+ return 0; /* NOTREACHED */
+}
+
+/*
+ * Another X Error handler, just used to check for errors.
+ */
+/* ARGSUSED */
+ static int
+x_error_check(dpy, error_event)
+ Display *dpy;
+ XErrorEvent *error_event;
+{
+ got_x_error = TRUE;
+ return 0;
+}
+
+#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
+# if defined(HAVE_SETJMP_H)
+/*
+ * An X IO Error handler, used to catch error while opening the display.
+ */
+static int x_IOerror_check __ARGS((Display *dpy));
+
+/* ARGSUSED */
+ static int
+x_IOerror_check(dpy)
+ Display *dpy;
+{
+ /* This function should not return, it causes exit(). Longjump instead. */
+ LONGJMP(lc_jump_env, 1);
+ /*NOTREACHED*/
+ return 0;
+}
+# endif
+
+/*
+ * An X IO Error handler, used to catch terminal errors.
+ */
+static int x_IOerror_handler __ARGS((Display *dpy));
+
+/* ARGSUSED */
+ static int
+x_IOerror_handler(dpy)
+ Display *dpy;
+{
+ xterm_dpy = NULL;
+ x11_window = 0;
+ x11_display = NULL;
+ xterm_Shell = (Widget)0;
+
+ /* This function should not return, it causes exit(). Longjump instead. */
+ LONGJMP(x_jump_env, 1);
+ /*NOTREACHED*/
+ return 0;
+}
+#endif
+
+/*
+ * Return TRUE when connection to the X server is desired.
+ */
+ static int
+x_connect_to_server()
+{
+ regmatch_T regmatch;
+
+#if defined(FEAT_CLIENTSERVER)
+ if (x_force_connect)
+ return TRUE;
+#endif
+ if (x_no_connect)
+ return FALSE;
+
+ /* Check for a match with "exclude:" from 'clipboard'. */
+ if (clip_exclude_prog != NULL)
+ {
+ regmatch.rm_ic = FALSE; /* Don't ignore case */
+ regmatch.regprog = clip_exclude_prog;
+ if (vim_regexec(&regmatch, T_NAME, (colnr_T)0))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Test if "dpy" and x11_window are valid by getting the window title.
+ * I don't actually want it yet, so there may be a simpler call to use, but
+ * this will cause the error handler x_error_check() to be called if anything
+ * is wrong, such as the window pointer being invalid (as can happen when the
+ * user changes his DISPLAY, but not his WINDOWID) -- webb
+ */
+ static int
+test_x11_window(dpy)
+ Display *dpy;
+{
+ int (*old_handler)();
+ XTextProperty text_prop;
+
+ old_handler = XSetErrorHandler(x_error_check);
+ got_x_error = FALSE;
+ if (XGetWMName(dpy, x11_window, &text_prop))
+ XFree((void *)text_prop.value);
+ XSync(dpy, False);
+ (void)XSetErrorHandler(old_handler);
+
+ if (p_verbose > 0 && got_x_error)
+ MSG(_("Testing the X display failed"));
+
+ return (got_x_error ? FAIL : OK);
+}
+#endif
+
+#ifdef FEAT_TITLE
+
+#ifdef FEAT_X11
+
+static int get_x11_thing __ARGS((int get_title, int test_only));
+
+/*
+ * try to get x11 window and display
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ static int
+get_x11_windis()
+{
+ char *winid;
+ static int result = -1;
+#define XD_NONE 0 /* x11_display not set here */
+#define XD_HERE 1 /* x11_display opened here */
+#define XD_GUI 2 /* x11_display used from gui.dpy */
+#define XD_XTERM 3 /* x11_display used from xterm_dpy */
+ static int x11_display_from = XD_NONE;
+ static int did_set_error_handler = FALSE;
+
+ if (!did_set_error_handler)
+ {
+ /* X just exits if it finds an error otherwise! */
+ (void)XSetErrorHandler(x_error_handler);
+ did_set_error_handler = TRUE;
+ }
+
+#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
+ if (gui.in_use)
+ {
+ /*
+ * If the X11 display was opened here before, for the window where Vim
+ * was started, close that one now to avoid a memory leak.
+ */
+ if (x11_display_from == XD_HERE && x11_display != NULL)
+ {
+ XCloseDisplay(x11_display);
+ x11_display_from = XD_NONE;
+ }
+ if (gui_get_x11_windis(&x11_window, &x11_display) == OK)
+ {
+ x11_display_from = XD_GUI;
+ return OK;
+ }
+ x11_display = NULL;
+ return FAIL;
+ }
+ else if (x11_display_from == XD_GUI)
+ {
+ /* GUI must have stopped somehow, clear x11_display */
+ x11_window = 0;
+ x11_display = NULL;
+ x11_display_from = XD_NONE;
+ }
+#endif
+
+ /* When started with the "-X" argument, don't try connecting. */
+ if (!x_connect_to_server())
+ return FAIL;
+
+ /*
+ * If WINDOWID not set, should try another method to find out
+ * what the current window number is. The only code I know for
+ * this is very complicated.
+ * We assume that zero is invalid for WINDOWID.
+ */
+ if (x11_window == 0 && (winid = getenv("WINDOWID")) != NULL)
+ x11_window = (Window)atol(winid);
+
+#ifdef FEAT_XCLIPBOARD
+ if (xterm_dpy != NULL && x11_window != 0)
+ {
+ /* Checked it already. */
+ if (x11_display_from == XD_XTERM)
+ return OK;
+
+ /*
+ * If the X11 display was opened here before, for the window where Vim
+ * was started, close that one now to avoid a memory leak.
+ */
+ if (x11_display_from == XD_HERE && x11_display != NULL)
+ XCloseDisplay(x11_display);
+ x11_display = xterm_dpy;
+ x11_display_from = XD_XTERM;
+ if (test_x11_window(x11_display) == FAIL)
+ {
+ /* probably bad $WINDOWID */
+ x11_window = 0;
+ x11_display = NULL;
+ x11_display_from = XD_NONE;
+ return FAIL;
+ }
+ return OK;
+ }
+#endif
+
+ if (x11_window == 0 || x11_display == NULL)
+ result = -1;
+
+ if (result != -1) /* Have already been here and set this */
+ return result; /* Don't do all these X calls again */
+
+ if (x11_window != 0 && x11_display == NULL)
+ {
+#ifdef SET_SIG_ALARM
+ RETSIGTYPE (*sig_save)();
+#endif
+#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
+ struct timeval start_tv;
+
+ if (p_verbose > 0)
+ gettimeofday(&start_tv, NULL);
+#endif
+
+#ifdef SET_SIG_ALARM
+ /*
+ * Opening the Display may hang if the DISPLAY setting is wrong, or
+ * the network connection is bad. Set an alarm timer to get out.
+ */
+ sig_alarm_called = FALSE;
+ sig_save = (RETSIGTYPE (*)())signal(SIGALRM,
+ (RETSIGTYPE (*)())sig_alarm);
+ alarm(2);
+#endif
+ x11_display = XOpenDisplay(NULL);
+
+#ifdef SET_SIG_ALARM
+ alarm(0);
+ signal(SIGALRM, (RETSIGTYPE (*)())sig_save);
+ if (p_verbose > 0 && sig_alarm_called)
+ MSG(_("Opening the X display timed out"));
+#endif
+ if (x11_display != NULL)
+ {
+# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
+ if (p_verbose > 0)
+ xopen_message(&start_tv);
+# endif
+ if (test_x11_window(x11_display) == FAIL)
+ {
+ /* Maybe window id is bad */
+ x11_window = 0;
+ XCloseDisplay(x11_display);
+ x11_display = NULL;
+ }
+ else
+ x11_display_from = XD_HERE;
+ }
+ }
+ if (x11_window == 0 || x11_display == NULL)
+ return (result = FAIL);
+ return (result = OK);
+}
+
+/*
+ * Determine original x11 Window Title
+ */
+ static int
+get_x11_title(test_only)
+ int test_only;
+{
+ int retval;
+
+ retval = get_x11_thing(TRUE, test_only);
+
+ /* could not get old title: oldtitle == NULL */
+
+ return retval;
+}
+
+/*
+ * Determine original x11 Window icon
+ */
+ static int
+get_x11_icon(test_only)
+ int test_only;
+{
+ int retval = FALSE;
+
+ retval = get_x11_thing(FALSE, test_only);
+
+ /* could not get old icon, use terminal name */
+ if (oldicon == NULL && !test_only)
+ {
+ if (STRNCMP(T_NAME, "builtin_", 8) == 0)
+ oldicon = T_NAME + 8;
+ else
+ oldicon = T_NAME;
+ }
+
+ return retval;
+}
+
+ static int
+get_x11_thing(get_title, test_only)
+ int get_title; /* get title string */
+ int test_only;
+{
+ XTextProperty text_prop;
+ int retval = FALSE;
+ Status status;
+
+ if (get_x11_windis() == OK)
+ {
+ /* Get window/icon name if any */
+ if (get_title)
+ status = XGetWMName(x11_display, x11_window, &text_prop);
+ else
+ status = XGetWMIconName(x11_display, x11_window, &text_prop);
+
+ /*
+ * If terminal is xterm, then x11_window may be a child window of the
+ * outer xterm window that actually contains the window/icon name, so
+ * keep traversing up the tree until a window with a title/icon is
+ * found.
+ */
+ /* Previously this was only done for xterm and alikes. I don't see a
+ * reason why it would fail for other terminal emulators.
+ * if (term_is_xterm) */
+ {
+ Window root;
+ Window parent;
+ Window win = x11_window;
+ Window *children;
+ unsigned int num_children;
+
+ while (!status || text_prop.value == NULL)
+ {
+ if (!XQueryTree(x11_display, win, &root, &parent, &children,
+ &num_children))
+ break;
+ if (children)
+ XFree((void *)children);
+ if (parent == root || parent == 0)
+ break;
+
+ win = parent;
+ if (get_title)
+ status = XGetWMName(x11_display, win, &text_prop);
+ else
+ status = XGetWMIconName(x11_display, win, &text_prop);
+ }
+ }
+ if (status && text_prop.value != NULL)
+ {
+ retval = TRUE;
+ if (!test_only)
+ {
+#ifdef FEAT_XFONTSET
+ if (text_prop.encoding == XA_STRING)
+ {
+#endif
+ if (get_title)
+ oldtitle = vim_strsave((char_u *)text_prop.value);
+ else
+ oldicon = vim_strsave((char_u *)text_prop.value);
+#ifdef FEAT_XFONTSET
+ }
+ else
+ {
+ char **cl;
+ Status transform_status;
+ int n = 0;
+
+ transform_status = XmbTextPropertyToTextList(x11_display,
+ &text_prop,
+ &cl, &n);
+ if (transform_status >= Success && n > 0 && cl[0])
+ {
+ if (get_title)
+ oldtitle = vim_strsave((char_u *) cl[0]);
+ else
+ oldicon = vim_strsave((char_u *) cl[0]);
+ XFreeStringList(cl);
+ }
+ else
+ {
+ if (get_title)
+ oldtitle = vim_strsave((char_u *)text_prop.value);
+ else
+ oldicon = vim_strsave((char_u *)text_prop.value);
+ }
+ }
+#endif
+ }
+ XFree((void *)text_prop.value);
+ }
+ }
+ return retval;
+}
+
+/* Are Xutf8 functions available? Avoid error from old compilers. */
+#if defined(X_HAVE_UTF8_STRING) && defined(FEAT_MBYTE)
+# if X_HAVE_UTF8_STRING
+# define USE_UTF8_STRING
+# endif
+#endif
+
+/*
+ * Set x11 Window Title
+ *
+ * get_x11_windis() must be called before this and have returned OK
+ */
+ static void
+set_x11_title(title)
+ char_u *title;
+{
+ /* XmbSetWMProperties() and Xutf8SetWMProperties() should use a STRING
+ * when possible, COMPOUND_TEXT otherwise. COMPOUND_TEXT isn't
+ * supported everywhere and STRING doesn't work for multi-byte titles.
+ */
+#ifdef USE_UTF8_STRING
+ if (enc_utf8)
+ Xutf8SetWMProperties(x11_display, x11_window, (const char *)title,
+ NULL, NULL, 0, NULL, NULL, NULL);
+ else
+#endif
+ {
+#if XtSpecificationRelease >= 4
+# ifdef FEAT_XFONTSET
+ XmbSetWMProperties(x11_display, x11_window, (const char *)title,
+ NULL, NULL, 0, NULL, NULL, NULL);
+# else
+ XTextProperty text_prop;
+
+ /* directly from example 3-18 "basicwin" of Xlib Programming Manual */
+ (void)XStringListToTextProperty((char **)&title, 1, &text_prop);
+ XSetWMProperties(x11_display, x11_window, &text_prop,
+ NULL, NULL, 0, NULL, NULL, NULL);
+# endif
+#else
+ XStoreName(x11_display, x11_window, (char *)title);
+#endif
+ }
+ XFlush(x11_display);
+}
+
+/*
+ * Set x11 Window icon
+ *
+ * get_x11_windis() must be called before this and have returned OK
+ */
+ static void
+set_x11_icon(icon)
+ char_u *icon;
+{
+ /* See above for comments about using X*SetWMProperties(). */
+#ifdef USE_UTF8_STRING
+ if (enc_utf8)
+ Xutf8SetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
+ NULL, 0, NULL, NULL, NULL);
+ else
+#endif
+ {
+#if XtSpecificationRelease >= 4
+# ifdef FEAT_XFONTSET
+ XmbSetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
+ NULL, 0, NULL, NULL, NULL);
+# else
+ XTextProperty text_prop;
+
+ (void)XStringListToTextProperty((char **)&icon, 1, &text_prop);
+ XSetWMProperties(x11_display, x11_window, NULL, &text_prop,
+ NULL, 0, NULL, NULL, NULL);
+# endif
+#else
+ XSetIconName(x11_display, x11_window, (char *)icon);
+#endif
+ }
+ XFlush(x11_display);
+}
+
+#else /* FEAT_X11 */
+
+/*ARGSUSED*/
+ static int
+get_x11_title(test_only)
+ int test_only;
+{
+ return FALSE;
+}
+
+ static int
+get_x11_icon(test_only)
+ int test_only;
+{
+ if (!test_only)
+ {
+ if (STRNCMP(T_NAME, "builtin_", 8) == 0)
+ oldicon = T_NAME + 8;
+ else
+ oldicon = T_NAME;
+ }
+ return FALSE;
+}
+
+#endif /* FEAT_X11 */
+
+ int
+mch_can_restore_title()
+{
+ return get_x11_title(TRUE);
+}
+
+ int
+mch_can_restore_icon()
+{
+ return get_x11_icon(TRUE);
+}
+
+/*
+ * Set the window title and icon.
+ */
+ void
+mch_settitle(title, icon)
+ char_u *title;
+ char_u *icon;
+{
+ int type = 0;
+ static int recursive = 0;
+
+ if (T_NAME == NULL) /* no terminal name (yet) */
+ return;
+ if (title == NULL && icon == NULL) /* nothing to do */
+ return;
+
+ /* When one of the X11 functions causes a deadly signal, we get here again
+ * recursively. Avoid hanging then (something is probably locked). */
+ if (recursive)
+ return;
+ ++recursive;
+
+ /*
+ * if the window ID and the display is known, we may use X11 calls
+ */
+#ifdef FEAT_X11
+ if (get_x11_windis() == OK)
+ type = 1;
+#else
+# if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK)
+ if (gui.in_use)
+ type = 1;
+# endif
+# ifdef FEAT_GUI_BEOS
+ /* TODO: If this means (gui.in_use) why not merge with above? (Dany) */
+ /* we always have a 'window' */
+ type = 1;
+# endif
+#endif
+
+ /*
+ * Note: if "t_TS" is set, title is set with escape sequence rather
+ * than x11 calls, because the x11 calls don't always work
+ */
+
+ if ((type || *T_TS != NUL) && title != NULL)
+ {
+ if (oldtitle == NULL
+#ifdef FEAT_GUI
+ && !gui.in_use
+#endif
+ ) /* first call but not in GUI, save title */
+ (void)get_x11_title(FALSE);
+
+ if (*T_TS != NUL) /* it's OK if t_fs is empty */
+ term_settitle(title);
+#ifdef FEAT_X11
+ else
+# ifdef FEAT_GUI_GTK
+ if (!gui.in_use) /* don't do this if GTK+ is running */
+# endif
+ set_x11_title(title); /* x11 */
+#endif
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_BEOS) \
+ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
+ else
+ gui_mch_settitle(title, icon);
+#endif
+ did_set_title = TRUE;
+ }
+
+ if ((type || *T_CIS != NUL) && icon != NULL)
+ {
+ if (oldicon == NULL
+#ifdef FEAT_GUI
+ && !gui.in_use
+#endif
+ ) /* first call, save icon */
+ get_x11_icon(FALSE);
+
+ if (*T_CIS != NUL)
+ {
+ out_str(T_CIS); /* set icon start */
+ out_str_nf(icon);
+ out_str(T_CIE); /* set icon end */
+ out_flush();
+ }
+#ifdef FEAT_X11
+ else
+# ifdef FEAT_GUI_GTK
+ if (!gui.in_use) /* don't do this if GTK+ is running */
+# endif
+ set_x11_icon(icon); /* x11 */
+#endif
+ did_set_icon = TRUE;
+ }
+ --recursive;
+}
+
+/*
+ * Restore the window/icon title.
+ * "which" is one of:
+ * 1 only restore title
+ * 2 only restore icon
+ * 3 restore title and icon
+ */
+ void
+mch_restore_title(which)
+ int which;
+{
+ /* only restore the title or icon when it has been set */
+ mch_settitle(((which & 1) && did_set_title) ?
+ (oldtitle ? oldtitle : p_titleold) : NULL,
+ ((which & 2) && did_set_icon) ? oldicon : NULL);
+}
+
+#endif /* FEAT_TITLE */
+
+/*
+ * Return TRUE if "name" looks like some xterm name.
+ */
+ int
+vim_is_xterm(name)
+ char_u *name;
+{
+ if (name == NULL)
+ return FALSE;
+ return (STRNICMP(name, "xterm", 5) == 0
+ || STRNICMP(name, "nxterm", 6) == 0
+ || STRNICMP(name, "kterm", 5) == 0
+ || STRNICMP(name, "rxvt", 4) == 0
+ || STRCMP(name, "builtin_xterm") == 0);
+}
+
+#if defined(FEAT_MOUSE_TTY) || defined(PROTO)
+/*
+ * Return non-zero when using an xterm mouse, according to 'ttymouse'.
+ * Return 1 for "xterm".
+ * Return 2 for "xterm2".
+ */
+ int
+use_xterm_mouse()
+{
+ if (ttym_flags == TTYM_XTERM2)
+ return 2;
+ if (ttym_flags == TTYM_XTERM)
+ return 1;
+ return 0;
+}
+#endif
+
+ int
+vim_is_iris(name)
+ char_u *name;
+{
+ if (name == NULL)
+ return FALSE;
+ return (STRNICMP(name, "iris-ansi", 9) == 0
+ || STRCMP(name, "builtin_iris-ansi") == 0);
+}
+
+ int
+vim_is_vt300(name)
+ char_u *name;
+{
+ if (name == NULL)
+ return FALSE; /* actually all ANSI comp. terminals should be here */
+ return (STRNICMP(name, "vt3", 3) == 0 /* it will cover all from VT100-VT300 */
+ || STRNICMP(name, "vt2", 3) == 0 /* TODO: from VT340 can hanle colors */
+ || STRNICMP(name, "vt1", 3) == 0
+ || STRCMP(name, "builtin_vt320") == 0);
+}
+
+/*
+ * Return TRUE if "name" is a terminal for which 'ttyfast' should be set.
+ * This should include all windowed terminal emulators.
+ */
+ int
+vim_is_fastterm(name)
+ char_u *name;
+{
+ if (name == NULL)
+ return FALSE;
+ if (vim_is_xterm(name) || vim_is_vt300(name) || vim_is_iris(name))
+ return TRUE;
+ return ( STRNICMP(name, "hpterm", 6) == 0
+ || STRNICMP(name, "sun-cmd", 7) == 0
+ || STRNICMP(name, "screen", 6) == 0
+ || STRNICMP(name, "dtterm", 6) == 0);
+}
+
+/*
+ * Insert user name in s[len].
+ * Return OK if a name found.
+ */
+ int
+mch_get_user_name(s, len)
+ char_u *s;
+ int len;
+{
+#ifdef VMS
+ STRNCPY((char *)s, cuserid(NULL), len);
+ return OK;
+#else
+ return mch_get_uname(getuid(), s, len);
+#endif
+}
+
+/*
+ * Insert user name for "uid" in s[len].
+ * Return OK if a name found.
+ */
+ int
+mch_get_uname(uid, s, len)
+ uid_t uid;
+ char_u *s;
+ int len;
+{
+#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
+ struct passwd *pw;
+
+ if ((pw = getpwuid(uid)) != NULL
+ && pw->pw_name != NULL && *(pw->pw_name) != NUL)
+ {
+ STRNCPY(s, pw->pw_name, len);
+ return OK;
+ }
+#endif
+ sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
+ return FAIL; /* a number is not a name */
+}
+
+/*
+ * Insert host name is s[len].
+ */
+
+#ifdef HAVE_SYS_UTSNAME_H
+ void
+mch_get_host_name(s, len)
+ char_u *s;
+ int len;
+{
+ struct utsname vutsname;
+
+ if (uname(&vutsname) < 0)
+ *s = NUL;
+ else
+ STRNCPY(s, vutsname.nodename, len);
+ s[len - 1] = NUL; /* make sure it's terminated */
+}
+#else /* HAVE_SYS_UTSNAME_H */
+
+# ifdef HAVE_SYS_SYSTEMINFO_H
+# define gethostname(nam, len) sysinfo(SI_HOSTNAME, nam, len)
+# endif
+
+ void
+mch_get_host_name(s, len)
+ char_u *s;
+ int len;
+{
+# ifdef VAXC
+ vaxc$gethostname((char *)s, len);
+# else
+ gethostname((char *)s, len);
+# endif
+ s[len - 1] = NUL; /* make sure it's terminated */
+}
+#endif /* HAVE_SYS_UTSNAME_H */
+
+/*
+ * return process ID
+ */
+ long
+mch_get_pid()
+{
+ return (long)getpid();
+}
+
+#if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
+static char *strerror __ARGS((int));
+
+ static char *
+strerror(err)
+ int err;
+{
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ static char er[20];
+
+ if (err > 0 && err < sys_nerr)
+ return (sys_errlist[err]);
+ sprintf(er, "Error %d", err);
+ return er;
+}
+#endif
+
+/*
+ * Get name of current directory into buffer 'buf' of length 'len' bytes.
+ * Return OK for success, FAIL for failure.
+ */
+ int
+mch_dirname(buf, len)
+ char_u *buf;
+ int len;
+{
+#if defined(USE_GETCWD)
+ if (getcwd((char *)buf, len) == NULL)
+ {
+ STRCPY(buf, strerror(errno));
+ return FAIL;
+ }
+ return OK;
+#else
+ return (getwd((char *)buf) != NULL ? OK : FAIL);
+#endif
+}
+
+#if defined(OS2) || defined(PROTO)
+/*
+ * Replace all slashes by backslashes.
+ * When 'shellslash' set do it the other way around.
+ */
+ void
+slash_adjust(p)
+ char_u *p;
+{
+ while (*p)
+ {
+ if (*p == psepcN)
+ *p = psepc;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p);
+ else
+#endif
+ ++p;
+ }
+}
+#endif
+
+/*
+ * Get absolute file name into buffer 'buf' of length 'len' bytes.
+ *
+ * return FAIL for failure, OK for success
+ */
+ int
+mch_FullName(fname, buf, len, force)
+ char_u *fname, *buf;
+ int len;
+ int force; /* also expand when already absolute path */
+{
+ int l;
+#ifdef OS2
+ int only_drive; /* file name is only a drive letter */
+#endif
+#ifdef HAVE_FCHDIR
+ int fd = -1;
+ static int dont_fchdir = FALSE; /* TRUE when fchdir() doesn't work */
+#endif
+ char_u olddir[MAXPATHL];
+ char_u *p;
+ int retval = OK;
+
+#ifdef VMS
+ fname = vms_fixfilename(fname);
+#endif
+
+ /* expand it if forced or not an absolute path */
+ if (force || !mch_isFullName(fname))
+ {
+ /*
+ * If the file name has a path, change to that directory for a moment,
+ * and then do the getwd() (and get back to where we were).
+ * This will get the correct path name with "../" things.
+ */
+#ifdef OS2
+ only_drive = 0;
+ if (((p = vim_strrchr(fname, '/')) != NULL)
+ || ((p = vim_strrchr(fname, '\\')) != NULL)
+ || (((p = vim_strchr(fname, ':')) != NULL) && ++only_drive))
+#else
+ if ((p = vim_strrchr(fname, '/')) != NULL)
+#endif
+ {
+#ifdef HAVE_FCHDIR
+ /*
+ * Use fchdir() if possible, it's said to be faster and more
+ * reliable. But on SunOS 4 it might not work. Check this by
+ * doing a fchdir() right now.
+ */
+ if (!dont_fchdir)
+ {
+ fd = open(".", O_RDONLY | O_EXTRA, 0);
+ if (fd >= 0 && fchdir(fd) < 0)
+ {
+ close(fd);
+ fd = -1;
+ dont_fchdir = TRUE; /* don't try again */
+ }
+ }
+#endif
+
+ /* Only change directory when we are sure we can return to where
+ * we are now. After doing "su" chdir(".") might not work. */
+ if (
+#ifdef HAVE_FCHDIR
+ fd < 0 &&
+#endif
+ (mch_dirname(olddir, MAXPATHL) == FAIL
+ || mch_chdir((char *)olddir) != 0))
+ {
+ p = NULL; /* can't get current dir: don't chdir */
+ retval = FAIL;
+ }
+ else
+ {
+#ifdef OS2
+ /*
+ * compensate for case where ':' from "D:" was the only
+ * path separator detected in the file name; the _next_
+ * character has to be removed, and then restored later.
+ */
+ if (only_drive)
+ p++;
+#endif
+ /* The directory is copied into buf[], to be able to remove
+ * the file name without changing it (could be a string in
+ * read-only memory) */
+ if (p - fname >= len)
+ retval = FAIL;
+ else
+ {
+ STRNCPY(buf, fname, p - fname);
+ buf[p - fname] = NUL;
+ if (mch_chdir((char *)buf))
+ retval = FAIL;
+ else
+ fname = p + 1;
+ *buf = NUL;
+ }
+#ifdef OS2
+ if (only_drive)
+ {
+ p--;
+ if (retval != FAIL)
+ fname--;
+ }
+#endif
+ }
+ }
+ if (mch_dirname(buf, len) == FAIL)
+ {
+ retval = FAIL;
+ *buf = NUL;
+ }
+ if (p != NULL)
+ {
+#ifdef HAVE_FCHDIR
+ if (fd >= 0)
+ {
+ l = fchdir(fd);
+ close(fd);
+ }
+ else
+#endif
+ l = mch_chdir((char *)olddir);
+ if (l != 0)
+ EMSG(_(e_prev_dir));
+ }
+
+ l = STRLEN(buf);
+ if (l >= len)
+ retval = FAIL;
+#ifndef VMS
+ else
+ {
+ if (l > 0 && buf[l - 1] != '/' && *fname != NUL
+ && STRCMP(fname, ".") != 0)
+ STRCAT(buf, "/");
+ }
+#endif
+ }
+ /* Catch file names which are too long. */
+ if (retval == FAIL || STRLEN(buf) + STRLEN(fname) >= len)
+ return FAIL;
+
+ /* Do not append ".", "/dir/." is equal to "/dir". */
+ if (STRCMP(fname, ".") != 0)
+ STRCAT(buf, fname);
+
+ return OK;
+}
+
+/*
+ * Return TRUE if "fname" does not depend on the current directory.
+ */
+ int
+mch_isFullName(fname)
+ char_u *fname;
+{
+#ifdef __EMX__
+ return _fnisabs(fname);
+#else
+# ifdef VMS
+ return ( fname[0] == '/' || fname[0] == '.' ||
+ strchr((char *)fname,':') || strchr((char *)fname,'"') ||
+ (strchr((char *)fname,'[') && strchr((char *)fname,']'))||
+ (strchr((char *)fname,'<') && strchr((char *)fname,'>')) );
+# else
+ return (*fname == '/' || *fname == '~');
+# endif
+#endif
+}
+
+/*
+ * Get file permissions for 'name'.
+ * Returns -1 when it doesn't exist.
+ */
+ long
+mch_getperm(name)
+ char_u *name;
+{
+ struct stat statb;
+
+ /* Keep the #ifdef outside of stat(), it may be a macro. */
+#ifdef VMS
+ if (stat((char *)vms_fixfilename(name), &statb))
+#else
+ if (stat((char *)name, &statb))
+#endif
+ return -1;
+ return statb.st_mode;
+}
+
+/*
+ * set file permission for 'name' to 'perm'
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+mch_setperm(name, perm)
+ char_u *name;
+ long perm;
+{
+ return (chmod((char *)
+#ifdef VMS
+ vms_fixfilename(name),
+#else
+ name,
+#endif
+ (mode_t)perm) == 0 ? OK : FAIL);
+}
+
+#if defined(HAVE_ACL) || defined(PROTO)
+# ifdef HAVE_SYS_ACL_H
+# include <sys/acl.h>
+# endif
+# ifdef HAVE_SYS_ACCESS_H
+# include <sys/access.h>
+# endif
+
+# ifdef HAVE_SOLARIS_ACL
+typedef struct vim_acl_solaris_T {
+ int acl_cnt;
+ aclent_t *acl_entry;
+} vim_acl_solaris_T;
+# endif
+
+/*
+ * Return a pointer to the ACL of file "fname" in allocated memory.
+ * Return NULL if the ACL is not available for whatever reason.
+ */
+ vim_acl_T
+mch_get_acl(fname)
+ char_u *fname;
+{
+ vim_acl_T ret = NULL;
+#ifdef HAVE_POSIX_ACL
+ ret = (vim_acl_T)acl_get_file((char *)fname, ACL_TYPE_ACCESS);
+#else
+#ifdef HAVE_SOLARIS_ACL
+ vim_acl_solaris_T *aclent;
+
+ aclent = malloc(sizeof(vim_acl_solaris_T));
+ if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
+ {
+ free(aclent);
+ return NULL;
+ }
+ aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
+ if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
+ {
+ free(aclent->acl_entry);
+ free(aclent);
+ return NULL;
+ }
+ ret = (vim_acl_T)aclent;
+#else
+#if defined(HAVE_AIX_ACL)
+ int aclsize;
+ struct acl *aclent;
+
+ aclsize = sizeof(struct acl);
+ aclent = malloc(aclsize);
+ if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
+ {
+ if (errno == ENOSPC)
+ {
+ aclsize = aclent->acl_len;
+ aclent = realloc(aclent, aclsize);
+ if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
+ {
+ free(aclent);
+ return NULL;
+ }
+ }
+ else
+ {
+ free(aclent);
+ return NULL;
+ }
+ }
+ ret = (vim_acl_T)aclent;
+#endif /* HAVE_AIX_ACL */
+#endif /* HAVE_SOLARIS_ACL */
+#endif /* HAVE_POSIX_ACL */
+ return ret;
+}
+
+/*
+ * Set the ACL of file "fname" to "acl" (unless it's NULL).
+ */
+ void
+mch_set_acl(fname, aclent)
+ char_u *fname;
+ vim_acl_T aclent;
+{
+ if (aclent == NULL)
+ return;
+#ifdef HAVE_POSIX_ACL
+ acl_set_file((char *)fname, ACL_TYPE_ACCESS, (acl_t)aclent);
+#else
+#ifdef HAVE_SOLARIS_ACL
+ acl((char *)fname, SETACL, ((vim_acl_solaris_T *)aclent)->acl_cnt,
+ ((vim_acl_solaris_T *)aclent)->acl_entry);
+#else
+#ifdef HAVE_AIX_ACL
+ chacl((char *)fname, aclent, ((struct acl *)aclent)->acl_len);
+#endif /* HAVE_AIX_ACL */
+#endif /* HAVE_SOLARIS_ACL */
+#endif /* HAVE_POSIX_ACL */
+}
+
+ void
+mch_free_acl(aclent)
+ vim_acl_T aclent;
+{
+ if (aclent == NULL)
+ return;
+#ifdef HAVE_POSIX_ACL
+ acl_free((acl_t)aclent);
+#else
+#ifdef HAVE_SOLARIS_ACL
+ free(((vim_acl_solaris_T *)aclent)->acl_entry);
+ free(aclent);
+#else
+#ifdef HAVE_AIX_ACL
+ free(aclent);
+#endif /* HAVE_AIX_ACL */
+#endif /* HAVE_SOLARIS_ACL */
+#endif /* HAVE_POSIX_ACL */
+}
+#endif
+
+/*
+ * Set hidden flag for "name".
+ */
+/* ARGSUSED */
+ void
+mch_hide(name)
+ char_u *name;
+{
+ /* can't hide a file */
+}
+
+/*
+ * return TRUE if "name" is a directory
+ * return FALSE if "name" is not a directory
+ * return FALSE for error
+ */
+ int
+mch_isdir(name)
+ char_u *name;
+{
+ struct stat statb;
+
+ if (*name == NUL) /* Some stat()s don't flag "" as an error. */
+ return FALSE;
+ if (stat((char *)name, &statb))
+ return FALSE;
+#ifdef _POSIX_SOURCE
+ return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
+#else
+ return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
+#endif
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+
+static int executable_file __ARGS((char_u *name));
+
+/*
+ * Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
+ */
+ static int
+executable_file(name)
+ char_u *name;
+{
+ struct stat st;
+
+ if (stat((char *)name, &st))
+ return 0;
+ return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
+}
+
+/*
+ * Return 1 if "name" can be found in $PATH and executed, 0 if not.
+ * Return -1 if unknown.
+ */
+ int
+mch_can_exe(name)
+ char_u *name;
+{
+ char_u *buf;
+ char_u *p, *e;
+ int retval;
+
+ /* If it's an absolute or relative path don't need to use $PATH. */
+ if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/'
+ || (name[1] == '.' && name[2] == '/'))))
+ return executable_file(name);
+
+ p = (char_u *)getenv("PATH");
+ if (p == NULL || *p == NUL)
+ return -1;
+ buf = alloc((unsigned)(STRLEN(name) + STRLEN(p) + 2));
+ if (buf == NULL)
+ return -1;
+
+ /*
+ * Walk through all entries in $PATH to check if "name" exists there and
+ * is an executable file.
+ */
+ for (;;)
+ {
+ e = (char_u *)strchr((char *)p, ':');
+ if (e == NULL)
+ e = p + STRLEN(p);
+ if (e - p <= 1) /* empty entry means current dir */
+ STRCPY(buf, "./");
+ else
+ {
+ STRNCPY(buf, p, e - p);
+ buf[e - p] = NUL;
+ add_pathsep(buf);
+ }
+ STRCAT(buf, name);
+ retval = executable_file(buf);
+ if (retval == 1)
+ break;
+
+ if (*e != ':')
+ break;
+ p = e + 1;
+ }
+
+ vim_free(buf);
+ return retval;
+}
+#endif
+
+/*
+ * Check what "name" is:
+ * NODE_NORMAL: file or directory (or doesn't exist)
+ * NODE_WRITABLE: writable device, socket, fifo, etc.
+ * NODE_OTHER: non-writable things
+ */
+ int
+mch_nodetype(name)
+ char_u *name;
+{
+ struct stat st;
+
+ if (stat((char *)name, &st))
+ return NODE_NORMAL;
+ if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
+ return NODE_NORMAL;
+#ifndef OS2
+ if (S_ISBLK(st.st_mode)) /* block device isn't writable */
+ return NODE_OTHER;
+#endif
+ /* Everything else is writable? */
+ return NODE_WRITABLE;
+}
+
+ void
+mch_early_init()
+{
+#ifdef HAVE_CHECK_STACK_GROWTH
+ int i;
+#endif
+
+#ifdef HAVE_CHECK_STACK_GROWTH
+ check_stack_growth((char *)&i);
+
+# ifdef HAVE_GETRLIMIT
+ get_stack_limit();
+# endif
+
+#endif
+
+ /*
+ * Setup an alternative stack for signals. Helps to catch signals when
+ * running out of stack space.
+ * Use of sigaltstack() is preferred, it's more portable.
+ * Ignore any errors.
+ */
+#if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
+ signal_stack = malloc(SIGSTKSZ);
+ init_signal_stack();
+#endif
+}
+
+static void exit_scroll __ARGS((void));
+
+/*
+ * Output a newline when exiting.
+ * Make sure the newline goes to the same stream as the text.
+ */
+ static void
+exit_scroll()
+{
+ if (newline_on_exit || msg_didout)
+ {
+ if (msg_use_printf())
+ {
+ if (info_message)
+ mch_msg("\n");
+ else
+ mch_errmsg("\r\n");
+ }
+ else
+ out_char('\n');
+ }
+ else
+ {
+ restore_cterm_colors(); /* get original colors back */
+ msg_clr_eos_force(); /* clear the rest of the display */
+ windgoto((int)Rows - 1, 0); /* may have moved the cursor */
+ }
+}
+
+ void
+mch_exit(r)
+ int r;
+{
+ exiting = TRUE;
+
+#if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
+ x11_export_final_selection();
+#endif
+
+#ifdef FEAT_GUI
+ if (!gui.in_use)
+#endif
+ {
+ settmode(TMODE_COOK);
+#ifdef FEAT_TITLE
+ mch_restore_title(3); /* restore xterm title and icon name */
+#endif
+ /*
+ * When t_ti is not empty but it doesn't cause swapping terminal
+ * pages, need to output a newline when msg_didout is set. But when
+ * t_ti does swap pages it should not go to the shell page. Do this
+ * before stoptermcap().
+ */
+ if (swapping_screen() && !newline_on_exit)
+ exit_scroll();
+
+ /* Stop termcap: May need to check for T_CRV response, which
+ * requires RAW mode. */
+ stoptermcap();
+
+ /*
+ * A newline is only required after a message in the alternate screen.
+ * This is set to TRUE by wait_return().
+ */
+ if (!swapping_screen() || newline_on_exit)
+ exit_scroll();
+
+ /* Cursor may have been switched off without calling starttermcap()
+ * when doing "vim -u vimrc" and vimrc contains ":q". */
+ if (full_screen)
+ cursor_on();
+ }
+ out_flush();
+ ml_close_all(TRUE); /* remove all memfiles */
+ may_core_dump();
+#ifdef FEAT_GUI
+# ifndef FEAT_GUI_BEOS /* BeOS always has GUI */
+ if (gui.in_use)
+# endif
+ gui_exit(r);
+#endif
+#ifdef __QNX__
+ /* A core dump won't be created if the signal handler
+ * doesn't return, so we can't call exit() */
+ if (deadly_signal != 0)
+ return;
+#endif
+
+ exit(r);
+}
+
+ static void
+may_core_dump()
+{
+ if (deadly_signal != 0)
+ {
+ signal(deadly_signal, SIG_DFL);
+ kill(getpid(), deadly_signal); /* Die using the signal we caught */
+ }
+}
+
+#ifndef VMS
+
+ void
+mch_settmode(tmode)
+ int tmode;
+{
+ static int first = TRUE;
+
+ /* Why is NeXT excluded here (and not in os_unixx.h)? */
+#if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
+ /*
+ * for "new" tty systems
+ */
+# ifdef HAVE_TERMIOS_H
+ static struct termios told;
+ struct termios tnew;
+# else
+ static struct termio told;
+ struct termio tnew;
+# endif
+
+ if (first)
+ {
+ first = FALSE;
+# if defined(HAVE_TERMIOS_H)
+ tcgetattr(read_cmd_fd, &told);
+# else
+ ioctl(read_cmd_fd, TCGETA, &told);
+# endif
+ }
+
+ tnew = told;
+ if (tmode == TMODE_RAW)
+ {
+ /*
+ * ~ICRNL enables typing ^V^M
+ */
+ tnew.c_iflag &= ~ICRNL;
+ tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
+# if defined(IEXTEN) && !defined(__MINT__)
+ | IEXTEN /* IEXTEN enables typing ^V on SOLARIS */
+ /* but it breaks function keys on MINT */
+# endif
+ );
+# ifdef ONLCR /* don't map NL -> CR NL, we do it ourselves */
+ tnew.c_oflag &= ~ONLCR;
+# endif
+ tnew.c_cc[VMIN] = 1; /* return after 1 char */
+ tnew.c_cc[VTIME] = 0; /* don't wait */
+ }
+ else if (tmode == TMODE_SLEEP)
+ tnew.c_lflag &= ~(ECHO);
+
+# if defined(HAVE_TERMIOS_H)
+ {
+ int n = 10;
+
+ /* A signal may cause tcsetattr() to fail (e.g., SIGCONT). Retry a
+ * few times. */
+ while (tcsetattr(read_cmd_fd, TCSANOW, &tnew) == -1
+ && errno == EINTR && n > 0)
+ --n;
+ }
+# else
+ ioctl(read_cmd_fd, TCSETA, &tnew);
+# endif
+
+#else
+
+ /*
+ * for "old" tty systems
+ */
+# ifndef TIOCSETN
+# define TIOCSETN TIOCSETP /* for hpux 9.0 */
+# endif
+ static struct sgttyb ttybold;
+ struct sgttyb ttybnew;
+
+ if (first)
+ {
+ first = FALSE;
+ ioctl(read_cmd_fd, TIOCGETP, &ttybold);
+ }
+
+ ttybnew = ttybold;
+ if (tmode == TMODE_RAW)
+ {
+ ttybnew.sg_flags &= ~(CRMOD | ECHO);
+ ttybnew.sg_flags |= RAW;
+ }
+ else if (tmode == TMODE_SLEEP)
+ ttybnew.sg_flags &= ~(ECHO);
+ ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
+#endif
+ curr_tmode = tmode;
+}
+
+/*
+ * Try to get the code for "t_kb" from the stty setting
+ *
+ * Even if termcap claims a backspace key, the user's setting *should*
+ * prevail. stty knows more about reality than termcap does, and if
+ * somebody's usual erase key is DEL (which, for most BSD users, it will
+ * be), they're going to get really annoyed if their erase key starts
+ * doing forward deletes for no reason. (Eric Fischer)
+ */
+ void
+get_stty()
+{
+ char_u buf[2];
+ char_u *p;
+
+ /* Why is NeXT excluded here (and not in os_unixx.h)? */
+#if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
+ /* for "new" tty systems */
+# ifdef HAVE_TERMIOS_H
+ struct termios keys;
+# else
+ struct termio keys;
+# endif
+
+# if defined(HAVE_TERMIOS_H)
+ if (tcgetattr(read_cmd_fd, &keys) != -1)
+# else
+ if (ioctl(read_cmd_fd, TCGETA, &keys) != -1)
+# endif
+ {
+ buf[0] = keys.c_cc[VERASE];
+ intr_char = keys.c_cc[VINTR];
+#else
+ /* for "old" tty systems */
+ struct sgttyb keys;
+
+ if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1)
+ {
+ buf[0] = keys.sg_erase;
+ intr_char = keys.sg_kill;
+#endif
+ buf[1] = NUL;
+ add_termcode((char_u *)"kb", buf, FALSE);
+
+ /*
+ * If <BS> and <DEL> are now the same, redefine <DEL>.
+ */
+ p = find_termcode((char_u *)"kD");
+ if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
+ do_fixdel(NULL);
+ }
+#if 0
+ } /* to keep cindent happy */
+#endif
+}
+
+#endif /* VMS */
+
+#if defined(FEAT_MOUSE_TTY) || defined(PROTO)
+/*
+ * Set mouse clicks on or off.
+ */
+ void
+mch_setmouse(on)
+ int on;
+{
+ static int ison = FALSE;
+ int xterm_mouse_vers;
+
+ if (on == ison) /* return quickly if nothing to do */
+ return;
+
+ xterm_mouse_vers = use_xterm_mouse();
+ if (xterm_mouse_vers > 0)
+ {
+ if (on) /* enable mouse events, use mouse tracking if available */
+ out_str_nf((char_u *)
+ (xterm_mouse_vers > 1
+ ? IF_EB("\033[?1002h", ESC_STR "[?1002h")
+ : IF_EB("\033[?1000h", ESC_STR "[?1000h")));
+ else /* disable mouse events, could probably always send the same */
+ out_str_nf((char_u *)
+ (xterm_mouse_vers > 1
+ ? IF_EB("\033[?1002l", ESC_STR "[?1002l")
+ : IF_EB("\033[?1000l", ESC_STR "[?1000l")));
+ ison = on;
+ }
+
+# ifdef FEAT_MOUSE_DEC
+ else if (ttym_flags == TTYM_DEC)
+ {
+ if (on) /* enable mouse events */
+ out_str_nf((char_u *)"\033[1;2'z\033[1;3'{");
+ else /* disable mouse events */
+ out_str_nf((char_u *)"\033['z");
+ ison = on;
+ }
+# endif
+
+# ifdef FEAT_MOUSE_GPM
+ else
+ {
+ if (on)
+ {
+ if (gpm_open())
+ ison = TRUE;
+ }
+ else
+ {
+ gpm_close();
+ ison = FALSE;
+ }
+ }
+# endif
+
+# ifdef FEAT_MOUSE_JSB
+ else
+ {
+ if (on)
+ {
+ /* D - Enable Mouse up/down messages
+ * L - Enable Left Button Reporting
+ * M - Enable Middle Button Reporting
+ * R - Enable Right Button Reporting
+ * K - Enable SHIFT and CTRL key Reporting
+ * + - Enable Advanced messaging of mouse moves and up/down messages
+ * Q - Quiet No Ack
+ * # - Numeric value of mouse pointer required
+ * 0 = Multiview 2000 cursor, used as standard
+ * 1 = Windows Arrow
+ * 2 = Windows I Beam
+ * 3 = Windows Hour Glass
+ * 4 = Windows Cross Hair
+ * 5 = Windows UP Arrow
+ */
+#ifdef JSBTERM_MOUSE_NONADVANCED /* Disables full feedback of pointer movements */
+ out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK1Q\033\\",
+ ESC_STR "[0~ZwLMRK1Q" ESC_STR "\\"));
+#else
+ out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\",
+ ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\"));
+#endif
+ ison = TRUE;
+ }
+ else
+ {
+ out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
+ ESC_STR "[0~ZwQ" ESC_STR "\\"));
+ ison = FALSE;
+ }
+ }
+# endif
+# ifdef FEAT_MOUSE_PTERM
+ else
+ {
+ /* 1 = button press, 6 = release, 7 = drag, 1h...9l = right button */
+ if (on)
+ out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l");
+ else
+ out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h");
+ ison = on;
+ }
+# endif
+}
+
+/*
+ * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
+ */
+ void
+check_mouse_termcode()
+{
+# ifdef FEAT_MOUSE_XTERM
+ if (use_xterm_mouse()
+# ifdef FEAT_GUI
+ && !gui.in_use
+# endif
+ )
+ {
+ set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
+ ? IF_EB("\233M", CSI_STR "M") : IF_EB("\033[M", ESC_STR "[M")));
+ if (*p_mouse != NUL)
+ {
+ /* force mouse off and maybe on to send possibly new mouse
+ * activation sequence to the xterm, with(out) drag tracing. */
+ mch_setmouse(FALSE);
+ setmouse();
+ }
+ }
+ else
+ del_mouse_termcode(KS_MOUSE);
+# endif
+
+# ifdef FEAT_MOUSE_GPM
+ if (!use_xterm_mouse()
+# ifdef FEAT_GUI
+ && !gui.in_use
+# endif
+ )
+ set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MG", ESC_STR "MG"));
+# endif
+
+# ifdef FEAT_MOUSE_JSB
+ /* conflicts with xterm mouse: "\033[" and "\033[M" ??? */
+ if (!use_xterm_mouse()
+# ifdef FEAT_GUI
+ && !gui.in_use
+# endif
+ )
+ set_mouse_termcode(KS_JSBTERM_MOUSE,
+ (char_u *)IF_EB("\033[0~zw", ESC_STR "[0~zw"));
+ else
+ del_mouse_termcode(KS_JSBTERM_MOUSE);
+# endif
+
+# ifdef FEAT_MOUSE_NET
+ /* There is no conflict, but one may type ESC } from Insert mode. Don't
+ * define it in the GUI or when using an xterm. */
+ if (!use_xterm_mouse()
+# ifdef FEAT_GUI
+ && !gui.in_use
+# endif
+ )
+ set_mouse_termcode(KS_NETTERM_MOUSE,
+ (char_u *)IF_EB("\033}", ESC_STR "}"));
+ else
+ del_mouse_termcode(KS_NETTERM_MOUSE);
+# endif
+
+# ifdef FEAT_MOUSE_DEC
+ /* conflicts with xterm mouse: "\033[" and "\033[M" */
+ if (!use_xterm_mouse()
+# ifdef FEAT_GUI
+ && !gui.in_use
+# endif
+ )
+ set_mouse_termcode(KS_DEC_MOUSE,
+ (char_u *)IF_EB("\033[", ESC_STR "["));
+ else
+ del_mouse_termcode(KS_DEC_MOUSE);
+# endif
+# ifdef FEAT_MOUSE_PTERM
+ /* same as the dec mouse */
+ if (!use_xterm_mouse()
+# ifdef FEAT_GUI
+ && !gui.in_use
+# endif
+ )
+ set_mouse_termcode(KS_PTERM_MOUSE,
+ (char_u *) IF_EB("\033[", ESC_STR "["));
+ else
+ del_mouse_termcode(KS_PTERM_MOUSE);
+# endif
+}
+#endif
+
+/*
+ * set screen mode, always fails.
+ */
+/* ARGSUSED */
+ int
+mch_screenmode(arg)
+ char_u *arg;
+{
+ EMSG(_(e_screenmode));
+ return FAIL;
+}
+
+#ifndef VMS
+
+/*
+ * Try to get the current window size:
+ * 1. with an ioctl(), most accurate method
+ * 2. from the environment variables LINES and COLUMNS
+ * 3. from the termcap
+ * 4. keep using the old values
+ * Return OK when size could be determined, FAIL otherwise.
+ */
+ int
+mch_get_shellsize()
+{
+ long rows = 0;
+ long columns = 0;
+ char_u *p;
+
+ /*
+ * For OS/2 use _scrsize().
+ */
+# ifdef __EMX__
+ {
+ int s[2];
+
+ _scrsize(s);
+ columns = s[0];
+ rows = s[1];
+ }
+# endif
+
+ /*
+ * 1. try using an ioctl. It is the most accurate method.
+ *
+ * Try using TIOCGWINSZ first, some systems that have it also define
+ * TIOCGSIZE but don't have a struct ttysize.
+ */
+# ifdef TIOCGWINSZ
+ {
+ struct winsize ws;
+ int fd = 1;
+
+ /* When stdout is not a tty, use stdin for the ioctl(). */
+ if (!isatty(fd) && isatty(read_cmd_fd))
+ fd = read_cmd_fd;
+ if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
+ {
+ columns = ws.ws_col;
+ rows = ws.ws_row;
+ }
+ }
+# else /* TIOCGWINSZ */
+# ifdef TIOCGSIZE
+ {
+ struct ttysize ts;
+ int fd = 1;
+
+ /* When stdout is not a tty, use stdin for the ioctl(). */
+ if (!isatty(fd) && isatty(read_cmd_fd))
+ fd = read_cmd_fd;
+ if (ioctl(fd, TIOCGSIZE, &ts) == 0)
+ {
+ columns = ts.ts_cols;
+ rows = ts.ts_lines;
+ }
+ }
+# endif /* TIOCGSIZE */
+# endif /* TIOCGWINSZ */
+
+ /*
+ * 2. get size from environment
+ */
+ if (columns == 0 || rows == 0)
+ {
+ if ((p = (char_u *)getenv("LINES")))
+ rows = atoi((char *)p);
+ if ((p = (char_u *)getenv("COLUMNS")))
+ columns = atoi((char *)p);
+ }
+
+#ifdef HAVE_TGETENT
+ /*
+ * 3. try reading "co" and "li" entries from termcap
+ */
+ if (columns == 0 || rows == 0)
+ getlinecol(&columns, &rows);
+#endif
+
+ /*
+ * 4. If everything fails, use the old values
+ */
+ if (columns <= 0 || rows <= 0)
+ return FAIL;
+
+ Rows = rows;
+ Columns = columns;
+ return OK;
+}
+
+/*
+ * Try to set the window size to Rows and Columns.
+ */
+ void
+mch_set_shellsize()
+{
+ if (*T_CWS)
+ {
+ /*
+ * NOTE: if you get an error here that term_set_winsize() is
+ * undefined, check the output of configure. It could probably not
+ * find a ncurses, termcap or termlib library.
+ */
+ term_set_winsize((int)Rows, (int)Columns);
+ out_flush();
+ screen_start(); /* don't know where cursor is now */
+ }
+}
+
+#endif /* VMS */
+
+/*
+ * Rows and/or Columns has changed.
+ */
+ void
+mch_new_shellsize()
+{
+ /* Nothing to do. */
+}
+
+ int
+mch_call_shell(cmd, options)
+ char_u *cmd;
+ int options; /* SHELL_*, see vim.h */
+{
+#ifdef VMS
+ char *ifn = NULL;
+ char *ofn = NULL;
+#endif
+ int tmode = cur_tmode;
+#ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
+ int x;
+# ifndef __EMX__
+ char_u *newcmd; /* only needed for unix */
+# else
+ /*
+ * Set the preferred shell in the EMXSHELL environment variable (but
+ * only if it is different from what is already in the environment).
+ * Emx then takes care of whether to use "/c" or "-c" in an
+ * intelligent way. Simply pass the whole thing to emx's system() call.
+ * Emx also starts an interactive shell if system() is passed an empty
+ * string.
+ */
+ char_u *p, *old;
+
+ if (((old = (char_u *)getenv("EMXSHELL")) == NULL) || STRCMP(old, p_sh))
+ {
+ /* should check HAVE_SETENV, but I know we don't have it. */
+ p = alloc(10 + strlen(p_sh));
+ if (p)
+ {
+ sprintf((char *)p, "EMXSHELL=%s", p_sh);
+ putenv((char *)p); /* don't free the pointer! */
+ }
+ }
+# endif
+
+ out_flush();
+
+ if (options & SHELL_COOKED)
+ settmode(TMODE_COOK); /* set to normal mode */
+
+# ifdef __EMX__
+ if (cmd == NULL)
+ x = system(""); /* this starts an interactive shell in emx */
+ else
+ x = system((char *)cmd);
+ /* system() returns -1 when error occurs in starting shell */
+ if (x == -1 && !emsg_silent)
+ {
+ MSG_PUTS(_("\nCannot execute shell "));
+ msg_outtrans(p_sh);
+ msg_putchar('\n');
+ }
+# else /* not __EMX__ */
+ if (cmd == NULL)
+ x = system((char *)p_sh);
+ else
+ {
+# ifdef VMS
+ if (ofn = strchr((char *)cmd, '>'))
+ *ofn++ = '\0';
+ if (ifn = strchr((char *)cmd, '<'))
+ {
+ char *p;
+
+ *ifn++ = '\0';
+ p = strchr(ifn,' '); /* chop off any trailing spaces */
+ if (p)
+ *p = '\0';
+ }
+ if (ofn)
+ x = vms_sys((char *)cmd, ofn, ifn);
+ else
+ x = system((char *)cmd);
+# else
+ newcmd = lalloc(STRLEN(p_sh)
+ + (extra_shell_arg == NULL ? 0 : STRLEN(extra_shell_arg))
+ + STRLEN(p_shcf) + STRLEN(cmd) + 4, TRUE);
+ if (newcmd == NULL)
+ x = 0;
+ else
+ {
+ sprintf((char *)newcmd, "%s %s %s %s", p_sh,
+ extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
+ (char *)p_shcf,
+ (char *)cmd);
+ x = system((char *)newcmd);
+ vim_free(newcmd);
+ }
+# endif
+ }
+# ifdef VMS
+ x = vms_sys_status(x);
+# endif
+ if (emsg_silent)
+ ;
+ else if (x == 127)
+ MSG_PUTS(_("\nCannot execute shell sh\n"));
+# endif /* __EMX__ */
+ else if (x && !(options & SHELL_SILENT))
+ {
+ MSG_PUTS(_("\nshell returned "));
+ msg_outnum((long)x);
+ msg_putchar('\n');
+ }
+
+ if (tmode == TMODE_RAW)
+ settmode(TMODE_RAW); /* set to raw mode */
+# ifdef FEAT_TITLE
+ resettitle();
+# endif
+ return x;
+
+#else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
+
+#define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
+ 127, some shell use that already */
+
+ char_u *newcmd = NULL;
+ pid_t pid;
+ pid_t wait_pid = 0;
+# ifdef HAVE_UNION_WAIT
+ union wait status;
+# else
+ int status = -1;
+# endif
+ int retval = -1;
+ char **argv = NULL;
+ int argc;
+ int i;
+ char_u *p;
+ int inquote;
+# ifdef FEAT_GUI
+ int pty_master_fd = -1; /* for pty's */
+ int pty_slave_fd = -1;
+ char *tty_name;
+ int fd_toshell[2]; /* for pipes */
+ int fd_fromshell[2];
+ int pipe_error = FALSE;
+# ifdef HAVE_SETENV
+ char envbuf[50];
+# else
+ static char envbuf_Rows[20];
+ static char envbuf_Columns[20];
+# endif
+# endif
+ int did_settmode = FALSE; /* TRUE when settmode(TMODE_RAW) called */
+
+ out_flush();
+ if (options & SHELL_COOKED)
+ settmode(TMODE_COOK); /* set to normal mode */
+
+ /*
+ * 1: find number of arguments
+ * 2: separate them and built argv[]
+ */
+ newcmd = vim_strsave(p_sh);
+ if (newcmd == NULL) /* out of memory */
+ goto error;
+ for (i = 0; i < 2; ++i)
+ {
+ p = newcmd;
+ inquote = FALSE;
+ argc = 0;
+ for (;;)
+ {
+ if (i == 1)
+ argv[argc] = (char *)p;
+ ++argc;
+ while (*p && (inquote || (*p != ' ' && *p != TAB)))
+ {
+ if (*p == '"')
+ inquote = !inquote;
+ ++p;
+ }
+ if (*p == NUL)
+ break;
+ if (i == 1)
+ *p++ = NUL;
+ p = skipwhite(p);
+ }
+ if (i == 0)
+ {
+ argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
+ if (argv == NULL) /* out of memory */
+ goto error;
+ }
+ }
+ if (cmd != NULL)
+ {
+ if (extra_shell_arg != NULL)
+ argv[argc++] = (char *)extra_shell_arg;
+ argv[argc++] = (char *)p_shcf;
+ argv[argc++] = (char *)cmd;
+ }
+ argv[argc] = NULL;
+
+# ifdef FEAT_GUI
+ /*
+ * For the GUI: Try using a pseudo-tty to get the stdin/stdout of the
+ * executed command into the Vim window. Or use a pipe.
+ */
+ if (gui.in_use && show_shell_mess)
+ {
+ /*
+ * Try to open a master pty.
+ * If this works, open the slave pty.
+ * If the slave can't be opened, close the master pty.
+ */
+ if (p_guipty)
+ {
+ pty_master_fd = OpenPTY(&tty_name); /* open pty */
+ if (pty_master_fd >= 0 && ((pty_slave_fd =
+ open(tty_name, O_RDWR | O_EXTRA, 0)) < 0))
+ {
+ close(pty_master_fd);
+ pty_master_fd = -1;
+ }
+ }
+ /*
+ * If not opening a pty or it didn't work, try using pipes.
+ */
+ if (pty_master_fd < 0)
+ {
+ pipe_error = (pipe(fd_toshell) < 0);
+ if (!pipe_error) /* pipe create OK */
+ {
+ pipe_error = (pipe(fd_fromshell) < 0);
+ if (pipe_error) /* pipe create failed */
+ {
+ close(fd_toshell[0]);
+ close(fd_toshell[1]);
+ }
+ }
+ if (pipe_error)
+ {
+ MSG_PUTS(_("\nCannot create pipes\n"));
+ out_flush();
+ }
+ }
+ }
+
+ if (!pipe_error) /* pty or pipe opened or not used */
+# endif
+
+ {
+# ifdef __BEOS__
+ beos_cleanup_read_thread();
+# endif
+ if ((pid = fork()) == -1) /* maybe we should use vfork() */
+ {
+ MSG_PUTS(_("\nCannot fork\n"));
+# ifdef FEAT_GUI
+ if (gui.in_use && show_shell_mess)
+ {
+ if (pty_master_fd >= 0) /* close the pseudo tty */
+ {
+ close(pty_master_fd);
+ close(pty_slave_fd);
+ }
+ else /* close the pipes */
+ {
+ close(fd_toshell[0]);
+ close(fd_toshell[1]);
+ close(fd_fromshell[0]);
+ close(fd_fromshell[1]);
+ }
+ }
+# endif
+ }
+ else if (pid == 0) /* child */
+ {
+ reset_signals(); /* handle signals normally */
+
+ if (!show_shell_mess || (options & SHELL_EXPAND))
+ {
+ int fd;
+
+ /*
+ * Don't want to show any message from the shell. Can't just
+ * close stdout and stderr though, because some systems will
+ * break if you try to write to them after that, so we must
+ * use dup() to replace them with something else -- webb
+ * Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
+ * waiting for input.
+ */
+ fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
+ fclose(stdin);
+ fclose(stdout);
+ fclose(stderr);
+
+ /*
+ * If any of these open()'s and dup()'s fail, we just continue
+ * anyway. It's not fatal, and on most systems it will make
+ * no difference at all. On a few it will cause the execvp()
+ * to exit with a non-zero status even when the completion
+ * could be done, which is nothing too serious. If the open()
+ * or dup() failed we'd just do the same thing ourselves
+ * anyway -- webb
+ */
+ if (fd >= 0)
+ {
+ dup(fd); /* To replace stdin (file descriptor 0) */
+ dup(fd); /* To replace stdout (file descriptor 1) */
+ dup(fd); /* To replace stderr (file descriptor 2) */
+
+ /* Don't need this now that we've duplicated it */
+ close(fd);
+ }
+ }
+# ifdef FEAT_GUI
+ else if (gui.in_use)
+ {
+
+# ifdef HAVE_SETSID
+ (void)setsid();
+# endif
+ /* push stream discipline modules */
+ if (options & SHELL_COOKED)
+ SetupSlavePTY(pty_slave_fd);
+# ifdef TIOCSCTTY
+ /* try to become controlling tty (probably doesn't work,
+ * unless run by root) */
+ ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
+# endif
+ /* Simulate to have a dumb terminal (for now) */
+# ifdef HAVE_SETENV
+ setenv("TERM", "dumb", 1);
+ sprintf((char *)envbuf, "%ld", Rows);
+ setenv("ROWS", (char *)envbuf, 1);
+ sprintf((char *)envbuf, "%ld", Rows);
+ setenv("LINES", (char *)envbuf, 1);
+ sprintf((char *)envbuf, "%ld", Columns);
+ setenv("COLUMNS", (char *)envbuf, 1);
+# else
+ /*
+ * Putenv does not copy the string, it has to remain valid.
+ * Use a static array to avoid loosing allocated memory.
+ */
+ putenv("TERM=dumb");
+ sprintf(envbuf_Rows, "ROWS=%ld", Rows);
+ putenv(envbuf_Rows);
+ sprintf(envbuf_Rows, "LINES=%ld", Rows);
+ putenv(envbuf_Rows);
+ sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
+ putenv(envbuf_Columns);
+# endif
+
+ if (pty_master_fd >= 0)
+ {
+ close(pty_master_fd); /* close master side of pty */
+
+ /* set up stdin/stdout/stderr for the child */
+ close(0);
+ dup(pty_slave_fd);
+ close(1);
+ dup(pty_slave_fd);
+ close(2);
+ dup(pty_slave_fd);
+
+ close(pty_slave_fd); /* has been dupped, close it now */
+ }
+ else
+ {
+ /* set up stdin for the child */
+ close(fd_toshell[1]);
+ close(0);
+ dup(fd_toshell[0]);
+ close(fd_toshell[0]);
+
+ /* set up stdout for the child */
+ close(fd_fromshell[0]);
+ close(1);
+ dup(fd_fromshell[1]);
+ close(fd_fromshell[1]);
+
+ /* set up stderr for the child */
+ close(2);
+ dup(1);
+ }
+ }
+# endif /* FEAT_GUI */
+ /*
+ * There is no type cast for the argv, because the type may be
+ * different on different machines. This may cause a warning
+ * message with strict compilers, don't worry about it.
+ * Call _exit() instead of exit() to avoid closing the connection
+ * to the X server (esp. with GTK, which uses atexit()).
+ */
+ execvp(argv[0], argv);
+ _exit(EXEC_FAILED); /* exec failed, return failure code */
+ }
+ else /* parent */
+ {
+ /*
+ * While child is running, ignore terminating signals.
+ */
+ catch_signals(SIG_IGN, SIG_ERR);
+
+# ifdef FEAT_GUI
+
+ /*
+ * For the GUI we redirect stdin, stdout and stderr to our window.
+ */
+ if (gui.in_use && show_shell_mess)
+ {
+# define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
+ char_u buffer[BUFLEN + 1];
+# ifdef FEAT_MBYTE
+ int buffer_off = 0; /* valid bytes in buffer[] */
+# endif
+ char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
+ int ta_len = 0; /* valid bytes in ta_buf[] */
+ int len;
+ int p_more_save;
+ int old_State;
+ int c;
+ int toshell_fd;
+ int fromshell_fd;
+
+ if (pty_master_fd >= 0)
+ {
+ close(pty_slave_fd); /* close slave side of pty */
+ fromshell_fd = pty_master_fd;
+ toshell_fd = dup(pty_master_fd);
+ }
+ else
+ {
+ close(fd_toshell[0]);
+ close(fd_fromshell[1]);
+ toshell_fd = fd_toshell[1];
+ fromshell_fd = fd_fromshell[0];
+ }
+
+ /*
+ * Write to the child if there are typed characters.
+ * Read from the child if there are characters available.
+ * Repeat the reading a few times if more characters are
+ * available. Need to check for typed keys now and then, but
+ * not too often (delays when no chars are available).
+ * This loop is quit if no characters can be read from the pty
+ * (WaitForChar detected special condition), or there are no
+ * characters available and the child has exited.
+ * Only check if the child has exited when there is no more
+ * output. The child may exit before all the output has
+ * been printed.
+ *
+ * Currently this busy loops!
+ * This can probably dead-lock when the write blocks!
+ */
+ p_more_save = p_more;
+ p_more = FALSE;
+ old_State = State;
+ State = EXTERNCMD; /* don't redraw at window resize */
+
+ for (;;)
+ {
+ /*
+ * Check if keys have been typed, write them to the child
+ * if there are any. Don't do this if we are expanding
+ * wild cards (would eat typeahead). Don't get extra
+ * characters when we already have one.
+ */
+ len = 0;
+ if (!(options & SHELL_EXPAND)
+ && (ta_len > 0
+ || (len = ui_inchar(ta_buf, BUFLEN, 10L,
+ 0)) > 0))
+ {
+ /*
+ * For pipes:
+ * Check for CTRL-C: send interrupt signal to child.
+ * Check for CTRL-D: EOF, close pipe to child.
+ */
+ if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
+ {
+# ifdef SIGINT
+ /*
+ * Send SIGINT to the child's group or all
+ * processes in our group.
+ */
+ if (ta_buf[ta_len] == Ctrl_C
+ || ta_buf[ta_len] == intr_char)
+# ifdef HAVE_SETSID
+ kill(-pid, SIGINT);
+# else
+ kill(0, SIGINT);
+# endif
+# endif
+ if (pty_master_fd < 0 && toshell_fd >= 0
+ && ta_buf[ta_len] == Ctrl_D)
+ {
+ close(toshell_fd);
+ toshell_fd = -1;
+ }
+ }
+
+ /* replace K_BS by <BS> and K_DEL by <DEL> */
+ for (i = ta_len; i < ta_len + len; ++i)
+ {
+ if (ta_buf[i] == CSI && len - i > 2)
+ {
+ c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
+ if (c == K_DEL || c == K_KDEL || c == K_BS)
+ {
+ mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
+ (size_t)(len - i - 2));
+ if (c == K_DEL || c == K_KDEL)
+ ta_buf[i] = DEL;
+ else
+ ta_buf[i] = Ctrl_H;
+ len -= 2;
+ }
+ }
+ else if (ta_buf[i] == '\r')
+ ta_buf[i] = '\n';
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ i += (*mb_ptr2len_check)(ta_buf + i) - 1;
+# endif
+ }
+
+ /*
+ * For pipes: echo the typed characters.
+ * For a pty this does not seem to work.
+ */
+ if (pty_master_fd < 0)
+ {
+ for (i = ta_len; i < ta_len + len; ++i)
+ {
+ if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
+ msg_putchar(ta_buf[i]);
+# ifdef FEAT_MBYTE
+ else if (has_mbyte)
+ {
+ int l = (*mb_ptr2len_check)(ta_buf + i);
+
+ msg_outtrans_len(ta_buf + i, l);
+ i += l - 1;
+ }
+# endif
+ else
+ msg_outtrans_len(ta_buf + i, 1);
+ }
+ windgoto(msg_row, msg_col);
+ out_flush();
+ }
+
+ ta_len += len;
+
+ /*
+ * Write the characters to the child, unless EOF has
+ * been typed for pipes. Write one character at a
+ * time, to avoid loosing too much typeahead.
+ */
+ if (toshell_fd >= 0)
+ {
+ len = write(toshell_fd, (char *)ta_buf, (size_t)1);
+ if (len > 0)
+ {
+ ta_len -= len;
+ mch_memmove(ta_buf, ta_buf + len, ta_len);
+ }
+ }
+ }
+
+ /*
+ * Check if the child has any characters to be printed.
+ * Read them and write them to our window. Repeat this as
+ * long as there is something to do, avoid the 10ms wait
+ * for mch_inchar(), or sending typeahead characters to
+ * the external process.
+ * TODO: This should handle escape sequences, compatible
+ * to some terminal (vt52?).
+ */
+ while (RealWaitForChar(fromshell_fd, 10L, NULL))
+ {
+ len = read(fromshell_fd, (char *)buffer
+# ifdef FEAT_MBYTE
+ + buffer_off, (size_t)(BUFLEN - buffer_off)
+# else
+ , (size_t)BUFLEN
+# endif
+ );
+ if (len <= 0) /* end of file or error */
+ goto finished;
+# ifdef FEAT_MBYTE
+ len += buffer_off;
+ buffer[len] = NUL;
+ if (has_mbyte)
+ {
+ int l;
+
+ /* Check if the last character in buffer[] is
+ * incomplete, keep these bytes for the next
+ * round. */
+ for (p = buffer; p < buffer + len; p += l)
+ {
+ if (enc_utf8) /* exclude composing chars */
+ l = utf_ptr2len_check(p);
+ else
+ l = (*mb_ptr2len_check)(p);
+ if (l == 0)
+ l = 1; /* NUL byte? */
+ else if (MB_BYTE2LEN(*p) != l)
+ break;
+ }
+ if (p == buffer) /* no complete character */
+ {
+ /* avoid getting stuck at an illegal byte */
+ if (len >= 12)
+ ++p;
+ else
+ {
+ buffer_off = len;
+ continue;
+ }
+ }
+ c = *p;
+ *p = NUL;
+ msg_puts(buffer);
+ if (p < buffer + len)
+ {
+ *p = c;
+ buffer_off = (buffer + len) - p;
+ mch_memmove(buffer, p, buffer_off);
+ continue;
+ }
+ buffer_off = 0;
+ }
+ else
+# endif /* FEAT_MBYTE */
+ {
+ buffer[len] = NUL;
+ msg_puts(buffer);
+ }
+
+ windgoto(msg_row, msg_col);
+ cursor_on();
+ out_flush();
+ if (got_int)
+ break;
+ }
+
+ /*
+ * Check if the child still exists, before checking for
+ * typed characters (otherwise we would loose typeahead).
+ */
+# ifdef __NeXT__
+ wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
+# else
+ wait_pid = waitpid(pid, &status, WNOHANG);
+# endif
+ if ((wait_pid == (pid_t)-1 && errno == ECHILD)
+ || (wait_pid == pid && WIFEXITED(status)))
+ {
+ wait_pid = pid;
+ break;
+ }
+ wait_pid = 0;
+ }
+finished:
+ p_more = p_more_save;
+
+# ifndef MACOS_X_UNIX /* TODO: Is it needed for MACOS_X ? */
+ /*
+ * Give all typeahead that wasn't used back to ui_inchar().
+ */
+ if (ta_len)
+ ui_inchar_undo(ta_buf, ta_len);
+# endif
+ State = old_State;
+ if (toshell_fd >= 0)
+ close(toshell_fd);
+ close(fromshell_fd);
+ }
+# endif /* FEAT_GUI */
+
+ /*
+ * Wait until our child has exited.
+ * Ignore wait() returning pids of other children and returning
+ * because of some signal like SIGWINCH.
+ * Don't wait if wait_pid was already set above, indicating the
+ * child already exited.
+ */
+ while (wait_pid != pid)
+ {
+#ifdef _THREAD_SAFE
+ /* Ugly hack: when compiled with Python threads are probably
+ * used, in which case wait() sometimes hangs for no obvious
+ * reason. Use waitpid() instead and loop (like the GUI). */
+# ifdef __NeXT__
+ wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
+# else
+ wait_pid = waitpid(pid, &status, WNOHANG);
+# endif
+ if (wait_pid == 0)
+ {
+ /* Wait for 1/100 sec before trying again. */
+ mch_delay(10L, TRUE);
+ continue;
+ }
+#else
+ wait_pid = wait(&status);
+#endif
+ if (wait_pid <= 0
+# ifdef ECHILD
+ && errno == ECHILD
+# endif
+ )
+ break;
+ }
+
+ /*
+ * Set to raw mode right now, otherwise a CTRL-C after
+ * catch_signals() will kill Vim.
+ */
+ if (tmode == TMODE_RAW)
+ settmode(TMODE_RAW);
+ did_settmode = TRUE;
+ set_signals();
+
+ if (WIFEXITED(status))
+ {
+ retval = WEXITSTATUS(status);
+ if (retval && !emsg_silent)
+ {
+ if (retval == EXEC_FAILED)
+ {
+ MSG_PUTS(_("\nCannot execute shell "));
+ msg_outtrans(p_sh);
+ msg_putchar('\n');
+ }
+ else if (!(options & SHELL_SILENT))
+ {
+ MSG_PUTS(_("\nshell returned "));
+ msg_outnum((long)retval);
+ msg_putchar('\n');
+ }
+ }
+ }
+ else
+ MSG_PUTS(_("\nCommand terminated\n"));
+ }
+ }
+ vim_free(argv);
+
+error:
+ if (!did_settmode)
+ if (tmode == TMODE_RAW)
+ settmode(TMODE_RAW); /* set to raw mode */
+# ifdef FEAT_TITLE
+ resettitle();
+# endif
+ vim_free(newcmd);
+
+ return retval;
+
+#endif /* USE_SYSTEM */
+}
+
+/*
+ * Check for CTRL-C typed by reading all available characters.
+ * In cooked mode we should get SIGINT, no need to check.
+ */
+ void
+mch_breakcheck()
+{
+ if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
+ fill_input_buf(FALSE);
+}
+
+/*
+ * Wait "msec" msec until a character is available from the keyboard or from
+ * inbuf[]. msec == -1 will block forever.
+ * When a GUI is being used, this will never get called -- webb
+ */
+ static int
+WaitForChar(msec)
+ long msec;
+{
+#ifdef FEAT_MOUSE_GPM
+ int gpm_process_wanted;
+#endif
+#ifdef FEAT_XCLIPBOARD
+ int rest;
+#endif
+ int avail;
+
+ if (input_available()) /* something in inbuf[] */
+ return 1;
+
+#if defined(FEAT_MOUSE_DEC)
+ /* May need to query the mouse position. */
+ if (WantQueryMouse)
+ {
+ WantQueryMouse = 0;
+ mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
+ }
+#endif
+
+ /*
+ * For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
+ * events. This is a bit complicated, because they might both be defined.
+ */
+#if defined(FEAT_MOUSE_GPM) || defined(FEAT_XCLIPBOARD)
+# ifdef FEAT_XCLIPBOARD
+ rest = 0;
+ if (do_xterm_trace())
+ rest = msec;
+# endif
+ do
+ {
+# ifdef FEAT_XCLIPBOARD
+ if (rest != 0)
+ {
+ msec = XT_TRACE_DELAY;
+ if (rest >= 0 && rest < XT_TRACE_DELAY)
+ msec = rest;
+ if (rest >= 0)
+ rest -= msec;
+ }
+# endif
+# ifdef FEAT_MOUSE_GPM
+ gpm_process_wanted = 0;
+ avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted);
+# else
+ avail = RealWaitForChar(read_cmd_fd, msec, NULL);
+# endif
+ if (!avail)
+ {
+ if (input_available())
+ return 1;
+# ifdef FEAT_XCLIPBOARD
+ if (rest == 0 || !do_xterm_trace())
+# endif
+ break;
+ }
+ }
+ while (FALSE
+# ifdef FEAT_MOUSE_GPM
+ || (gpm_process_wanted && mch_gpm_process() == 0)
+# endif
+# ifdef FEAT_XCLIPBOARD
+ || (!avail && rest != 0)
+# endif
+ );
+
+#else
+ avail = RealWaitForChar(read_cmd_fd, msec, NULL);
+#endif
+ return avail;
+}
+
+/*
+ * Wait "msec" msec until a character is available from file descriptor "fd".
+ * Time == -1 will block forever.
+ * When a GUI is being used, this will not be used for input -- webb
+ * Returns also, when a request from Sniff is waiting -- toni.
+ * Or when a Linux GPM mouse event is waiting.
+ */
+/* ARGSUSED */
+#if defined(__BEOS__)
+ int
+#else
+ static int
+#endif
+RealWaitForChar(fd, msec, check_for_gpm)
+ int fd;
+ long msec;
+ int *check_for_gpm;
+{
+ int ret;
+#if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP)
+ static int busy = FALSE;
+
+ /* May retry getting characters after an event was handled. */
+# define MAY_LOOP
+
+# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
+ /* Remember at what time we started, so that we know how much longer we
+ * should wait after being interrupted. */
+# define USE_START_TV
+ struct timeval start_tv;
+
+ if (msec > 0 && (
+# ifdef FEAT_XCLIPBOARD
+ xterm_Shell != (Widget)0
+# ifdef USE_XSMP
+ ||
+# endif
+# endif
+# ifdef USE_XSMP
+ xsmp_icefd != -1
+# endif
+ ))
+ gettimeofday(&start_tv, NULL);
+# endif
+
+ /* Handle being called recursively. This may happen for the session
+ * manager stuff, it may save the file, which does a breakcheck. */
+ if (busy)
+ return 0;
+#endif
+
+#ifdef MAY_LOOP
+ while (1)
+#endif
+ {
+#ifdef MAY_LOOP
+ int finished = TRUE; /* default is to 'loop' just once */
+#endif
+#ifndef HAVE_SELECT
+ struct pollfd fds[5];
+ int nfd;
+# ifdef FEAT_XCLIPBOARD
+ int xterm_idx = -1;
+# endif
+# ifdef FEAT_MOUSE_GPM
+ int gpm_idx = -1;
+# endif
+# ifdef USE_XSMP
+ int xsmp_idx = -1;
+# endif
+
+ fds[0].fd = fd;
+ fds[0].events = POLLIN;
+ nfd = 1;
+
+# ifdef FEAT_SNIFF
+# define SNIFF_IDX 1
+ if (want_sniff_request)
+ {
+ fds[SNIFF_IDX].fd = fd_from_sniff;
+ fds[SNIFF_IDX].events = POLLIN;
+ nfd++;
+ }
+# endif
+# ifdef FEAT_XCLIPBOARD
+ if (xterm_Shell != (Widget)0)
+ {
+ xterm_idx = nfd;
+ fds[nfd].fd = ConnectionNumber(xterm_dpy);
+ fds[nfd].events = POLLIN;
+ nfd++;
+ }
+# endif
+# ifdef FEAT_MOUSE_GPM
+ if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
+ {
+ gpm_idx = nfd;
+ fds[nfd].fd = gpm_fd;
+ fds[nfd].events = POLLIN;
+ nfd++;
+ }
+# endif
+# ifdef USE_XSMP
+ if (xsmp_icefd != -1)
+ {
+ xsmp_idx = nfd;
+ fds[nfd].fd = xsmp_icefd;
+ fds[nfd].events = POLLIN;
+ nfd++;
+ }
+# endif
+
+ ret = poll(fds, nfd, (int)msec);
+
+# ifdef FEAT_SNIFF
+ if (ret < 0)
+ sniff_disconnect(1);
+ else if (want_sniff_request)
+ {
+ if (fds[SNIFF_IDX].revents & POLLHUP)
+ sniff_disconnect(1);
+ if (fds[SNIFF_IDX].revents & POLLIN)
+ sniff_request_waiting = 1;
+ }
+# endif
+# ifdef FEAT_XCLIPBOARD
+ if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
+ {
+ xterm_update(); /* Maybe we should hand out clipboard */
+ if (--ret == 0 && !input_available())
+ /* Try again */
+ finished = FALSE;
+ }
+# endif
+# ifdef FEAT_MOUSE_GPM
+ if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
+ {
+ *check_for_gpm = 1;
+ }
+# endif
+# ifdef USE_XSMP
+ if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
+ {
+ if (fds[xsmp_idx].revents & POLLIN)
+ {
+ busy = TRUE;
+ xsmp_handle_requests();
+ busy = FALSE;
+ }
+ else if (fds[xsmp_idx].revents & POLLHUP)
+ {
+ if (p_verbose > 0)
+ MSG(_("XSMP lost ICE connection"));
+ xsmp_close();
+ }
+ if (--ret == 0)
+ /* Try again */
+ finished = FALSE;
+ }
+# endif
+
+
+#else /* HAVE_SELECT */
+
+ struct timeval tv;
+ fd_set rfds, efds;
+ int maxfd;
+
+# ifdef __EMX__
+ /* don't check for incoming chars if not in raw mode, because select()
+ * always returns TRUE then (in some version of emx.dll) */
+ if (curr_tmode != TMODE_RAW)
+ return 0;
+# endif
+
+ if (msec >= 0)
+ {
+ tv.tv_sec = msec / 1000;
+ tv.tv_usec = (msec % 1000) * (1000000/1000);
+ }
+
+ /*
+ * Select on ready for reading and exceptional condition (end of file).
+ */
+ FD_ZERO(&rfds); /* calls bzero() on a sun */
+ FD_ZERO(&efds);
+ FD_SET(fd, &rfds);
+# if !defined(__QNX__) && !defined(__CYGWIN32__)
+ /* For QNX select() always returns 1 if this is set. Why? */
+ FD_SET(fd, &efds);
+# endif
+ maxfd = fd;
+
+# ifdef FEAT_SNIFF
+ if (want_sniff_request)
+ {
+ FD_SET(fd_from_sniff, &rfds);
+ FD_SET(fd_from_sniff, &efds);
+ if (maxfd < fd_from_sniff)
+ maxfd = fd_from_sniff;
+ }
+# endif
+# ifdef FEAT_XCLIPBOARD
+ if (xterm_Shell != (Widget)0)
+ {
+ FD_SET(ConnectionNumber(xterm_dpy), &rfds);
+ if (maxfd < ConnectionNumber(xterm_dpy))
+ maxfd = ConnectionNumber(xterm_dpy);
+ }
+# endif
+# ifdef FEAT_MOUSE_GPM
+ if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
+ {
+ FD_SET(gpm_fd, &rfds);
+ FD_SET(gpm_fd, &efds);
+ if (maxfd < gpm_fd)
+ maxfd = gpm_fd;
+ }
+# endif
+# ifdef USE_XSMP
+ if (xsmp_icefd != -1)
+ {
+ FD_SET(xsmp_icefd, &rfds);
+ FD_SET(xsmp_icefd, &efds);
+ if (maxfd < xsmp_icefd)
+ maxfd = xsmp_icefd;
+ }
+# endif
+
+# ifdef OLD_VMS
+ /* Old VMS as v6.2 and older have broken select(). It waits more than
+ * required. Should not be used */
+ ret = 0;
+# else
+ ret = select(maxfd + 1, &rfds, NULL, &efds, (msec >= 0) ? &tv : NULL);
+# endif
+
+# ifdef FEAT_SNIFF
+ if (ret < 0 )
+ sniff_disconnect(1);
+ else if (ret > 0 && want_sniff_request)
+ {
+ if (FD_ISSET(fd_from_sniff, &efds))
+ sniff_disconnect(1);
+ if (FD_ISSET(fd_from_sniff, &rfds))
+ sniff_request_waiting = 1;
+ }
+# endif
+# ifdef FEAT_XCLIPBOARD
+ if (ret > 0 && xterm_Shell != (Widget)0
+ && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
+ {
+ xterm_update(); /* Maybe we should hand out clipboard */
+ /* continue looping when we only got the X event and the input
+ * buffer is empty */
+ if (--ret == 0 && !input_available())
+ {
+ /* Try again */
+ finished = FALSE;
+ }
+ }
+# endif
+# ifdef FEAT_MOUSE_GPM
+ if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
+ {
+ if (FD_ISSET(gpm_fd, &efds))
+ gpm_close();
+ else if (FD_ISSET(gpm_fd, &rfds))
+ *check_for_gpm = 1;
+ }
+# endif
+# ifdef USE_XSMP
+ if (ret > 0 && xsmp_icefd != -1)
+ {
+ if (FD_ISSET(xsmp_icefd, &efds))
+ {
+ if (p_verbose > 0)
+ MSG(_("XSMP lost ICE connection"));
+ xsmp_close();
+ if (--ret == 0)
+ finished = FALSE; /* keep going if event was only one */
+ }
+ else if (FD_ISSET(xsmp_icefd, &rfds))
+ {
+ busy = TRUE;
+ xsmp_handle_requests();
+ busy = FALSE;
+ if (--ret == 0)
+ finished = FALSE; /* keep going if event was only one */
+ }
+ }
+# endif
+
+#endif /* HAVE_SELECT */
+
+#ifdef MAY_LOOP
+ if (finished || msec == 0)
+ break;
+
+ /* We're going to loop around again, find out for how long */
+ if (msec > 0)
+ {
+# ifdef USE_START_TV
+ struct timeval mtv;
+
+ /* Compute remaining wait time. */
+ gettimeofday(&mtv, NULL);
+ msec -= (mtv.tv_sec - start_tv.tv_sec) * 1000L
+ + (mtv.tv_usec - start_tv.tv_usec) / 1000L;
+# else
+ /* Guess we got interrupted halfway. */
+ msec = msec / 2;
+# endif
+ if (msec <= 0)
+ break; /* waited long enough */
+ }
+#endif
+ }
+
+ return (ret > 0);
+}
+
+#ifndef VMS
+
+#ifndef NO_EXPANDPATH
+ static int
+pstrcmp(a, b)
+ const void *a, *b;
+{
+ return (pathcmp(*(char **)a, *(char **)b));
+}
+
+/*
+ * Recursively expand one path component into all matching files and/or
+ * directories.
+ * "path" has backslashes before chars that are not to be expanded, starting
+ * at "path + wildoff".
+ * Return the number of matches found.
+ */
+ int
+mch_expandpath(gap, path, flags)
+ garray_T *gap;
+ char_u *path;
+ int flags; /* EW_* flags */
+{
+ return unix_expandpath(gap, path, 0, flags);
+}
+
+ static int
+unix_expandpath(gap, path, wildoff, flags)
+ garray_T *gap;
+ char_u *path;
+ int wildoff;
+ int flags; /* EW_* flags */
+{
+ char_u *buf;
+ char_u *path_end;
+ char_u *p, *s, *e;
+ int start_len, c;
+ char_u *pat;
+ DIR *dirp;
+ regmatch_T regmatch;
+ struct dirent *dp;
+ int starts_with_dot;
+ int matches;
+ int len;
+
+ start_len = gap->ga_len;
+ buf = alloc(STRLEN(path) + BASENAMELEN + 5);/* make room for file name */
+ if (buf == NULL)
+ return 0;
+
+/*
+ * Find the first part in the path name that contains a wildcard.
+ * Copy it into buf, including the preceding characters.
+ */
+ p = buf;
+ s = buf;
+ e = NULL;
+ path_end = path;
+ while (*path_end != NUL)
+ {
+ /* May ignore a wildcard that has a backslash before it; it will
+ * be removed by rem_backslash() or file_pat_to_reg_pat() below. */
+ if (path_end >= path + wildoff && rem_backslash(path_end))
+ *p++ = *path_end++;
+ else if (*path_end == '/')
+ {
+ if (e != NULL)
+ break;
+ s = p + 1;
+ }
+ else if (path_end >= path + wildoff
+ && vim_strchr((char_u *)"*?[{~$", *path_end) != NULL)
+ e = p;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ len = (*mb_ptr2len_check)(path_end);
+ STRNCPY(p, path_end, len);
+ p += len;
+ path_end += len;
+ }
+ else
+#endif
+ *p++ = *path_end++;
+ }
+ e = p;
+ *e = NUL;
+
+ /* now we have one wildcard component between s and e */
+ /* Remove backslashes between "wildoff" and the start of the wildcard
+ * component. */
+ for (p = buf + wildoff; p < s; ++p)
+ if (rem_backslash(p))
+ {
+ STRCPY(p, p + 1);
+ --e;
+ --s;
+ }
+
+ /* convert the file pattern to a regexp pattern */
+ starts_with_dot = (*s == '.');
+ pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
+ if (pat == NULL)
+ {
+ vim_free(buf);
+ return 0;
+ }
+
+ /* compile the regexp into a program */
+#ifdef MACOS_X /* Can/Should we use CASE_INSENSITIVE_FILENAME instead ?*/
+ regmatch.rm_ic = TRUE; /* Behave like Terminal.app */
+#else
+ regmatch.rm_ic = FALSE; /* Don't ever ignore case */
+#endif
+ regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
+ vim_free(pat);
+
+ if (regmatch.regprog == NULL)
+ {
+ vim_free(buf);
+ return 0;
+ }
+
+ /* open the directory for scanning */
+ c = *s;
+ *s = NUL;
+ dirp = opendir(*buf == NUL ? "." : (char *)buf);
+ *s = c;
+
+ /* Find all matching entries */
+ if (dirp != NULL)
+ {
+ for (;;)
+ {
+ dp = readdir(dirp);
+ if (dp == NULL)
+ break;
+ if ((dp->d_name[0] != '.' || starts_with_dot)
+ && vim_regexec(&regmatch, (char_u *)dp->d_name, (colnr_T)0))
+ {
+ STRCPY(s, dp->d_name);
+ len = STRLEN(buf);
+ STRCPY(buf + len, path_end);
+ if (mch_has_exp_wildcard(path_end)) /* handle more wildcards */
+ {
+ /* need to expand another component of the path */
+ /* remove backslashes for the remaining components only */
+ (void)unix_expandpath(gap, buf, len + 1, flags);
+ }
+ else
+ {
+ /* no more wildcards, check if there is a match */
+ /* remove backslashes for the remaining components only */
+ if (*path_end != NUL)
+ backslash_halve(buf + len + 1);
+ if (mch_getperm(buf) >= 0) /* add existing file */
+ addfile(gap, buf, flags);
+ }
+ }
+ }
+
+ closedir(dirp);
+ }
+
+ vim_free(buf);
+ vim_free(regmatch.regprog);
+
+ matches = gap->ga_len - start_len;
+ if (matches > 0)
+ qsort(((char_u **)gap->ga_data) + start_len, matches,
+ sizeof(char_u *), pstrcmp);
+ return matches;
+}
+#endif
+
+/*
+ * mch_expand_wildcards() - this code does wild-card pattern matching using
+ * the shell
+ *
+ * return OK for success, FAIL for error (you may lose some memory) and put
+ * an error message in *file.
+ *
+ * num_pat is number of input patterns
+ * pat is array of pointers to input patterns
+ * num_file is pointer to number of matched file names
+ * file is pointer to array of pointers to matched file names
+ */
+
+#ifndef SEEK_SET
+# define SEEK_SET 0
+#endif
+#ifndef SEEK_END
+# define SEEK_END 2
+#endif
+
+/* ARGSUSED */
+ int
+mch_expand_wildcards(num_pat, pat, num_file, file, flags)
+ int num_pat;
+ char_u **pat;
+ int *num_file;
+ char_u ***file;
+ int flags; /* EW_* flags */
+{
+ int i;
+ size_t len;
+ char_u *p;
+ int dir;
+#ifdef __EMX__
+# define EXPL_ALLOC_INC 16
+ char_u **expl_files;
+ size_t files_alloced, files_free;
+ char_u *buf;
+ int has_wildcard;
+
+ *num_file = 0; /* default: no files found */
+ files_alloced = EXPL_ALLOC_INC; /* how much space is allocated */
+ files_free = EXPL_ALLOC_INC; /* how much space is not used */
+ *file = (char_u **)alloc(sizeof(char_u **) * files_alloced);
+ if (*file == NULL)
+ return FAIL;
+
+ for (; num_pat > 0; num_pat--, pat++)
+ {
+ expl_files = NULL;
+ if (vim_strchr(*pat, '$') || vim_strchr(*pat, '~'))
+ /* expand environment var or home dir */
+ buf = expand_env_save(*pat);
+ else
+ buf = vim_strsave(*pat);
+ expl_files = NULL;
+ has_wildcard = mch_has_exp_wildcard(buf); /* (still) wildcards in there? */
+ if (has_wildcard) /* yes, so expand them */
+ expl_files = (char_u **)_fnexplode(buf);
+
+ /*
+ * return value of buf if no wildcards left,
+ * OR if no match AND EW_NOTFOUND is set.
+ */
+ if ((!has_wildcard && ((flags & EW_NOTFOUND) || mch_getperm(buf) >= 0))
+ || (expl_files == NULL && (flags & EW_NOTFOUND)))
+ { /* simply save the current contents of *buf */
+ expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
+ if (expl_files != NULL)
+ {
+ expl_files[0] = vim_strsave(buf);
+ expl_files[1] = NULL;
+ }
+ }
+ vim_free(buf);
+
+ /*
+ * Count number of names resulting from expansion,
+ * At the same time add a backslash to the end of names that happen to
+ * be directories, and replace slashes with backslashes.
+ */
+ if (expl_files)
+ {
+ for (i = 0; (p = expl_files[i]) != NULL; i++)
+ {
+ dir = mch_isdir(p);
+ /* If we don't want dirs and this is one, skip it */
+ if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
+ continue;
+
+ if (--files_free == 0)
+ {
+ /* need more room in table of pointers */
+ files_alloced += EXPL_ALLOC_INC;
+ *file = (char_u **)vim_realloc(*file,
+ sizeof(char_u **) * files_alloced);
+ if (*file == NULL)
+ {
+ EMSG(_(e_outofmem));
+ *num_file = 0;
+ return FAIL;
+ }
+ files_free = EXPL_ALLOC_INC;
+ }
+ slash_adjust(p);
+ if (dir)
+ {
+ /* For a directory we add a '/', unless it's already
+ * there. */
+ len = STRLEN(p);
+ if (((*file)[*num_file] = alloc(len + 2)) != NULL)
+ {
+ STRCPY((*file)[*num_file], p);
+ if (!vim_ispathsep((*file)[*num_file][len - 1]))
+ {
+ (*file)[*num_file][len] = psepc;
+ (*file)[*num_file][len + 1] = 0;
+ }
+ }
+ }
+ else
+ {
+ (*file)[*num_file] = vim_strsave(p);
+ }
+
+ /*
+ * Error message already given by either alloc or vim_strsave.
+ * Should return FAIL, but returning OK works also.
+ */
+ if ((*file)[*num_file] == NULL)
+ break;
+ (*num_file)++;
+ }
+ _fnexplodefree((char **)expl_files);
+ }
+ }
+ return OK;
+
+#else /* __EMX__ */
+
+ int j;
+ char_u *tempname;
+ char_u *command;
+ FILE *fd;
+ char_u *buffer;
+#define STYLE_ECHO 0 /* use "echo" to expand */
+#define STYLE_GLOB 1 /* use "glob" to expand, for csh */
+#define STYLE_PRINT 2 /* use "print -N" to expand, for zsh */
+#define STYLE_BT 3 /* `cmd` expansion, execute the pattern directly */
+ int shell_style = STYLE_ECHO;
+ int check_spaces;
+ static int did_find_nul = FALSE;
+ int ampersent = FALSE;
+
+ *num_file = 0; /* default: no files found */
+ *file = NULL;
+
+ /*
+ * If there are no wildcards, just copy the names to allocated memory.
+ * Saves a lot of time, because we don't have to start a new shell.
+ */
+ if (!have_wildcard(num_pat, pat))
+ return save_patterns(num_pat, pat, num_file, file);
+
+ /*
+ * Don't allow the use of backticks in secure and restricted mode.
+ */
+ if (secure || restricted)
+ for (i = 0; i < num_pat; ++i)
+ if (vim_strchr(pat[i], '`') != NULL
+ && (check_restricted() || check_secure()))
+ return FAIL;
+
+ /*
+ * get a name for the temp file
+ */
+ if ((tempname = vim_tempname('o')) == NULL)
+ {
+ EMSG(_(e_notmp));
+ return FAIL;
+ }
+
+ /*
+ * Let the shell expand the patterns and write the result into the temp
+ * file. if expanding `cmd` execute it directly.
+ * If we use csh, glob will work better than echo.
+ * If we use zsh, print -N will work better than glob.
+ */
+ if (num_pat == 1 && *pat[0] == '`'
+ && (len = STRLEN(pat[0])) > 2
+ && *(pat[0] + len - 1) == '`')
+ shell_style = STYLE_BT;
+ else if ((len = STRLEN(p_sh)) >= 3)
+ {
+ if (STRCMP(p_sh + len - 3, "csh") == 0)
+ shell_style = STYLE_GLOB;
+ else if (STRCMP(p_sh + len - 3, "zsh") == 0)
+ shell_style = STYLE_PRINT;
+ }
+
+ /* "unset nonomatch; print -N >" plus two is 29 */
+ len = STRLEN(tempname) + 29;
+ for (i = 0; i < num_pat; ++i) /* count the length of the patterns */
+ len += STRLEN(pat[i]) + 3; /* add space and two quotes */
+ command = alloc(len);
+ if (command == NULL)
+ {
+ /* out of memory */
+ vim_free(tempname);
+ return FAIL;
+ }
+
+ /*
+ * Build the shell command:
+ * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
+ * recognizes this).
+ * - Add the shell command to print the expanded names.
+ * - Add the temp file name.
+ * - Add the file name patterns.
+ */
+ if (shell_style == STYLE_BT)
+ {
+ STRCPY(command, pat[0] + 1); /* exclude first backtick */
+ p = command + STRLEN(command) - 1;
+ *p = ' '; /* remove last backtick */
+ while (p > command && vim_iswhite(*p))
+ --p;
+ if (*p == '&') /* remove trailing '&' */
+ {
+ ampersent = TRUE;
+ *p = ' ';
+ }
+ STRCAT(command, ">");
+ }
+ else
+ {
+ if (flags & EW_NOTFOUND)
+ STRCPY(command, "set nonomatch; ");
+ else
+ STRCPY(command, "unset nonomatch; ");
+ if (shell_style == STYLE_GLOB)
+ STRCAT(command, "glob >");
+ else if (shell_style == STYLE_PRINT)
+ STRCAT(command, "print -N >");
+ else
+ STRCAT(command, "echo >");
+ }
+ STRCAT(command, tempname);
+ if (shell_style != STYLE_BT)
+ for (i = 0; i < num_pat; ++i)
+ {
+ /* When using system() always add extra quotes, because the shell
+ * is started twice. Otherwise only put quotes around spaces and
+ * single quotes. */
+#ifdef USE_SYSTEM
+ STRCAT(command, " \"");
+ STRCAT(command, pat[i]);
+ STRCAT(command, "\"");
+#else
+ p = command + STRLEN(command);
+ *p++ = ' ';
+ for (j = 0; pat[i][j] != NUL; )
+ if (vim_strchr((char_u *)" '", pat[i][j]) != NULL)
+ {
+ *p++ = '"';
+ while (pat[i][j] != NUL
+ && vim_strchr((char_u *)" '", pat[i][j]) != NULL)
+ *p++ = pat[i][j++];
+ *p++ = '"';
+ }
+ else
+ *p++ = pat[i][j++];
+ *p = NUL;
+#endif
+ }
+ if (flags & EW_SILENT)
+ show_shell_mess = FALSE;
+ if (ampersent)
+ STRCAT(command, "&"); /* put the '&' back after the
+ redirection */
+
+ /*
+ * Using zsh -G: If a pattern has no matches, it is just deleted from
+ * the argument list, otherwise zsh gives an error message and doesn't
+ * expand any other pattern.
+ */
+ if (shell_style == STYLE_PRINT)
+ extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */
+
+ /*
+ * If we use -f then shell variables set in .cshrc won't get expanded.
+ * vi can do it, so we will too, but it is only necessary if there is a "$"
+ * in one of the patterns, otherwise we can still use the fast option.
+ */
+ else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
+ extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */
+
+ /*
+ * execute the shell command
+ */
+ i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
+
+ /* When running in the background, give it some time to create the temp
+ * file, but don't wait for it to finish. */
+ if (ampersent)
+ mch_delay(10L, TRUE);
+
+ extra_shell_arg = NULL; /* cleanup */
+ show_shell_mess = TRUE;
+ vim_free(command);
+
+ if (i) /* mch_call_shell() failed */
+ {
+ mch_remove(tempname);
+ vim_free(tempname);
+ /*
+ * With interactive completion, the error message is not printed.
+ * However with USE_SYSTEM, I don't know how to turn off error messages
+ * from the shell, so screen may still get messed up -- webb.
+ */
+#ifndef USE_SYSTEM
+ if (!(flags & EW_SILENT))
+#endif
+ {
+ redraw_later_clear(); /* probably messed up screen */
+ msg_putchar('\n'); /* clear bottom line quickly */
+ cmdline_row = Rows - 1; /* continue on last line */
+#ifdef USE_SYSTEM
+ if (!(flags & EW_SILENT))
+#endif
+ {
+ MSG(_(e_wildexpand));
+ msg_start(); /* don't overwrite this message */
+ }
+ }
+ /* If a `cmd` expansion failed, don't list `cmd` as a match, even when
+ * EW_NOTFOUND is given */
+ if (shell_style == STYLE_BT)
+ return FAIL;
+ goto notfound;
+ }
+
+ /*
+ * read the names from the file into memory
+ */
+ fd = fopen((char *)tempname, READBIN);
+ if (fd == NULL)
+ {
+ /* Something went wrong, perhaps a file name with a special char. */
+ if (!(flags & EW_SILENT))
+ {
+ MSG(_(e_wildexpand));
+ msg_start(); /* don't overwrite this message */
+ }
+ vim_free(tempname);
+ goto notfound;
+ }
+ fseek(fd, 0L, SEEK_END);
+ len = ftell(fd); /* get size of temp file */
+ fseek(fd, 0L, SEEK_SET);
+ buffer = alloc(len + 1);
+ if (buffer == NULL)
+ {
+ /* out of memory */
+ mch_remove(tempname);
+ vim_free(tempname);
+ fclose(fd);
+ return FAIL;
+ }
+ i = fread((char *)buffer, 1, len, fd);
+ fclose(fd);
+ mch_remove(tempname);
+ if (i != len)
+ {
+ /* unexpected read error */
+ EMSG2(_(e_notread), tempname);
+ vim_free(tempname);
+ vim_free(buffer);
+ return FAIL;
+ }
+ vim_free(tempname);
+
+#if defined(__CYGWIN__) || defined(__CYGWIN32__)
+ /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */
+ p = buffer;
+ for (i = 0; i < len; ++i)
+ if (!(buffer[i] == CAR && buffer[i + 1] == NL))
+ *p++ = buffer[i];
+ len = p - buffer;
+# endif
+
+
+ /* file names are separated with Space */
+ if (shell_style == STYLE_ECHO)
+ {
+ buffer[len] = '\n'; /* make sure the buffer ends in NL */
+ p = buffer;
+ for (i = 0; *p != '\n'; ++i) /* count number of entries */
+ {
+ while (*p != ' ' && *p != '\n')
+ ++p;
+ p = skipwhite(p); /* skip to next entry */
+ }
+ }
+ /* file names are separated with NL */
+ else if (shell_style == STYLE_BT)
+ {
+ buffer[len] = NUL; /* make sure the buffer ends in NUL */
+ p = buffer;
+ for (i = 0; *p != NUL; ++i) /* count number of entries */
+ {
+ while (*p != '\n' && *p != NUL)
+ ++p;
+ if (*p != NUL)
+ ++p;
+ p = skipwhite(p); /* skip leading white space */
+ }
+ }
+ /* file names are separated with NUL */
+ else
+ {
+ /*
+ * Some versions of zsh use spaces instead of NULs to separate
+ * results. Only do this when there is no NUL before the end of the
+ * buffer, otherwise we would never be able to use file names with
+ * embedded spaces when zsh does use NULs.
+ * When we found a NUL once, we know zsh is OK, set did_find_nul and
+ * don't check for spaces again.
+ */
+ check_spaces = FALSE;
+ if (shell_style == STYLE_PRINT && !did_find_nul)
+ {
+ /* If there is a NUL, set did_find_nul, else set check_spaces */
+ if (len && (int)STRLEN(buffer) < len - 1)
+ did_find_nul = TRUE;
+ else
+ check_spaces = TRUE;
+ }
+
+ /*
+ * Make sure the buffer ends with a NUL. For STYLE_PRINT there
+ * already is one, for STYLE_GLOB it needs to be added.
+ */
+ if (len && buffer[len - 1] == NUL)
+ --len;
+ else
+ buffer[len] = NUL;
+ i = 0;
+ for (p = buffer; p < buffer + len; ++p)
+ if (*p == NUL || (*p == ' ' && check_spaces)) /* count entry */
+ {
+ ++i;
+ *p = NUL;
+ }
+ if (len)
+ ++i; /* count last entry */
+ }
+ if (i == 0)
+ {
+ /*
+ * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
+ * /bin/sh will happily expand it to nothing rather than returning an
+ * error; and hey, it's good to check anyway -- webb.
+ */
+ vim_free(buffer);
+ goto notfound;
+ }
+ *num_file = i;
+ *file = (char_u **)alloc(sizeof(char_u *) * i);
+ if (*file == NULL)
+ {
+ /* out of memory */
+ vim_free(buffer);
+ return FAIL;
+ }
+
+ /*
+ * Isolate the individual file names.
+ */
+ p = buffer;
+ for (i = 0; i < *num_file; ++i)
+ {
+ (*file)[i] = p;
+ /* Space or NL separates */
+ if (shell_style == STYLE_ECHO || shell_style == STYLE_BT)
+ {
+ while (!(shell_style == STYLE_ECHO && *p == ' ') && *p != '\n')
+ ++p;
+ if (p == buffer + len) /* last entry */
+ *p = NUL;
+ else
+ {
+ *p++ = NUL;
+ p = skipwhite(p); /* skip to next entry */
+ }
+ }
+ else /* NUL separates */
+ {
+ while (*p && p < buffer + len) /* skip entry */
+ ++p;
+ ++p; /* skip NUL */
+ }
+ }
+
+ /*
+ * Move the file names to allocated memory.
+ */
+ for (j = 0, i = 0; i < *num_file; ++i)
+ {
+ /* Require the files to exist. Helps when using /bin/sh */
+ if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
+ continue;
+
+ /* check if this entry should be included */
+ dir = (mch_isdir((*file)[i]));
+ if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
+ continue;
+
+ p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
+ if (p)
+ {
+ STRCPY(p, (*file)[i]);
+ if (dir)
+ STRCAT(p, "/"); /* add '/' to a directory name */
+ (*file)[j++] = p;
+ }
+ }
+ vim_free(buffer);
+ *num_file = j;
+
+ if (*num_file == 0) /* rejected all entries */
+ {
+ vim_free(*file);
+ *file = NULL;
+ goto notfound;
+ }
+
+ return OK;
+
+notfound:
+ if (flags & EW_NOTFOUND)
+ return save_patterns(num_pat, pat, num_file, file);
+ return FAIL;
+
+#endif /* __EMX__ */
+}
+
+#endif /* VMS */
+
+#ifndef __EMX__
+ static int
+save_patterns(num_pat, pat, num_file, file)
+ int num_pat;
+ char_u **pat;
+ int *num_file;
+ char_u ***file;
+{
+ int i;
+
+ *file = (char_u **)alloc(num_pat * sizeof(char_u *));
+ if (*file == NULL)
+ return FAIL;
+ for (i = 0; i < num_pat; i++)
+ (*file)[i] = vim_strsave(pat[i]);
+ *num_file = num_pat;
+ return OK;
+}
+#endif
+
+
+/*
+ * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
+ * expand.
+ */
+ int
+mch_has_exp_wildcard(p)
+ char_u *p;
+{
+ for ( ; *p; ++p)
+ {
+#ifndef OS2
+ if (*p == '\\' && p[1] != NUL)
+ ++p;
+ else
+#endif
+ if (vim_strchr((char_u *)
+#ifdef VMS
+ "*?%"
+#else
+# ifdef OS2
+ "*?"
+# else
+ "*?[{'"
+# endif
+#endif
+ , *p) != NULL)
+ return TRUE;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ return FALSE;
+}
+
+/*
+ * Return TRUE if the string "p" contains a wildcard.
+ * Don't recognize '~' at the end as a wildcard.
+ */
+ int
+mch_has_wildcard(p)
+ char_u *p;
+{
+ for ( ; *p; ++p)
+ {
+#ifndef OS2
+ if (*p == '\\' && p[1] != NUL)
+ ++p;
+ else
+#endif
+ if (vim_strchr((char_u *)
+#ifdef VMS
+ "*?%$"
+#else
+# ifdef OS2
+# ifdef VIM_BACKTICK
+ "*?$`"
+# else
+ "*?$"
+# endif
+# else
+ "*?[{`'$"
+# endif
+#endif
+ , *p) != NULL
+ || (*p == '~' && p[1] != NUL))
+ return TRUE;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ return FALSE;
+}
+
+#ifndef __EMX__
+ static int
+have_wildcard(num, file)
+ int num;
+ char_u **file;
+{
+ int i;
+
+ for (i = 0; i < num; i++)
+ if (mch_has_wildcard(file[i]))
+ return 1;
+ return 0;
+}
+
+ static int
+have_dollars(num, file)
+ int num;
+ char_u **file;
+{
+ int i;
+
+ for (i = 0; i < num; i++)
+ if (vim_strchr(file[i], '$') != NULL)
+ return TRUE;
+ return FALSE;
+}
+#endif /* ifndef __EMX__ */
+
+#ifndef HAVE_RENAME
+/*
+ * Scaled-down version of rename(), which is missing in Xenix.
+ * This version can only move regular files and will fail if the
+ * destination exists.
+ */
+ int
+mch_rename(src, dest)
+ const char *src, *dest;
+{
+ struct stat st;
+
+ if (stat(dest, &st) >= 0) /* fail if destination exists */
+ return -1;
+ if (link(src, dest) != 0) /* link file to new name */
+ return -1;
+ if (mch_remove(src) == 0) /* delete link to old name */
+ return 0;
+ return -1;
+}
+#endif /* !HAVE_RENAME */
+
+#ifdef FEAT_MOUSE_GPM
+/*
+ * Initializes connection with gpm (if it isn't already opened)
+ * Return 1 if succeeded (or connection already opened), 0 if failed
+ */
+ static int
+gpm_open()
+{
+ static Gpm_Connect gpm_connect; /* Must it be kept till closing ? */
+
+ if (!gpm_flag)
+ {
+ gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
+ gpm_connect.defaultMask = ~GPM_HARD;
+ /* Default handling for mouse move*/
+ gpm_connect.minMod = 0; /* Handle any modifier keys */
+ gpm_connect.maxMod = 0xffff;
+ if (Gpm_Open(&gpm_connect, 0) > 0)
+ {
+ /* gpm library tries to handling TSTP causes
+ * problems. Anyways, we close connection to Gpm whenever
+ * we are going to suspend or starting an external process
+ * so we should'nt have problem with this
+ */
+ signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
+ return 1; /* succeed */
+ }
+ if (gpm_fd == -2)
+ Gpm_Close(); /* We don't want to talk to xterm via gpm */
+ return 0;
+ }
+ return 1; /* already open */
+}
+
+/*
+ * Closes connection to gpm
+ * returns non-zero if connection succesfully closed
+ */
+ static void
+gpm_close()
+{
+ if (gpm_flag && gpm_fd >= 0) /* if Open */
+ Gpm_Close();
+}
+
+/* Reads gpm event and adds special keys to input buf. Returns length of
+ * generated key sequence.
+ * This function is made after gui_send_mouse_event
+ */
+ static int
+mch_gpm_process()
+{
+ int button;
+ static Gpm_Event gpm_event;
+ char_u string[6];
+ int_u vim_modifiers;
+ int row,col;
+ unsigned char buttons_mask;
+ unsigned char gpm_modifiers;
+ static unsigned char old_buttons = 0;
+
+ Gpm_GetEvent(&gpm_event);
+
+#ifdef FEAT_GUI
+ /* Don't put events in the input queue now. */
+ if (hold_gui_events)
+ return 0;
+#endif
+
+ row = gpm_event.y - 1;
+ col = gpm_event.x - 1;
+
+ string[0] = ESC; /* Our termcode */
+ string[1] = 'M';
+ string[2] = 'G';
+ switch (GPM_BARE_EVENTS(gpm_event.type))
+ {
+ case GPM_DRAG:
+ string[3] = MOUSE_DRAG;
+ break;
+ case GPM_DOWN:
+ buttons_mask = gpm_event.buttons & ~old_buttons;
+ old_buttons = gpm_event.buttons;
+ switch (buttons_mask)
+ {
+ case GPM_B_LEFT:
+ button = MOUSE_LEFT;
+ break;
+ case GPM_B_MIDDLE:
+ button = MOUSE_MIDDLE;
+ break;
+ case GPM_B_RIGHT:
+ button = MOUSE_RIGHT;
+ break;
+ default:
+ return 0;
+ /*Don't know what to do. Can more than one button be
+ * reported in one event? */
+ }
+ string[3] = (char_u)(button | 0x20);
+ SET_NUM_MOUSE_CLICKS(string[3], gpm_event.clicks + 1);
+ break;
+ case GPM_UP:
+ string[3] = MOUSE_RELEASE;
+ old_buttons &= ~gpm_event.buttons;
+ break;
+ default:
+ return 0;
+ }
+ /*This code is based on gui_x11_mouse_cb in gui_x11.c */
+ gpm_modifiers = gpm_event.modifiers;
+ vim_modifiers = 0x0;
+ /* I ignore capslock stats. Aren't we all just hate capslock mixing with
+ * Vim commands ? Besides, gpm_event.modifiers is unsigned char, and
+ * K_CAPSSHIFT is defined 8, so it probably isn't even reported
+ */
+ if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
+ vim_modifiers |= MOUSE_SHIFT;
+
+ if (gpm_modifiers & ((1 << KG_CTRL) | (1 << KG_CTRLR) | (1 << KG_CTRLL)))
+ vim_modifiers |= MOUSE_CTRL;
+ if (gpm_modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)))
+ vim_modifiers |= MOUSE_ALT;
+ string[3] |= vim_modifiers;
+ string[4] = (char_u)(col + ' ' + 1);
+ string[5] = (char_u)(row + ' ' + 1);
+ add_to_input_buf(string, 6);
+ return 6;
+}
+#endif /* FEAT_MOUSE_GPM */
+
+#if defined(FEAT_LIBCALL) || defined(PROTO)
+typedef char_u * (*STRPROCSTR)__ARGS((char_u *));
+typedef char_u * (*INTPROCSTR)__ARGS((int));
+typedef int (*STRPROCINT)__ARGS((char_u *));
+typedef int (*INTPROCINT)__ARGS((int));
+
+/*
+ * Call a DLL routine which takes either a string or int param
+ * and returns an allocated string.
+ */
+ int
+mch_libcall(libname, funcname, argstring, argint, string_result, number_result)
+ char_u *libname;
+ char_u *funcname;
+ char_u *argstring; /* NULL when using a argint */
+ int argint;
+ char_u **string_result;/* NULL when using number_result */
+ int *number_result;
+{
+# if defined(USE_DLOPEN)
+ void *hinstLib;
+# else
+ shl_t hinstLib;
+# endif
+ STRPROCSTR ProcAdd;
+ INTPROCSTR ProcAddI;
+ char_u *retval_str = NULL;
+ int retval_int = 0;
+ int success = FALSE;
+
+ /* Get a handle to the DLL module. */
+# if defined(USE_DLOPEN)
+ hinstLib = dlopen((char *)libname, RTLD_LAZY
+# ifdef RTLD_LOCAL
+ | RTLD_LOCAL
+# endif
+ );
+# else
+ hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
+# endif
+
+ /* If the handle is valid, try to get the function address. */
+ if (hinstLib != NULL)
+ {
+# ifdef HAVE_SETJMP_H
+ /*
+ * Catch a crash when calling the library function. For example when
+ * using a number where a string pointer is expected.
+ */
+ mch_startjmp();
+ if (SETJMP(lc_jump_env) != 0)
+ {
+ success = FALSE;
+ mch_didjmp();
+ }
+ else
+# endif
+ {
+ retval_str = NULL;
+ retval_int = 0;
+
+ if (argstring != NULL)
+ {
+# if defined(USE_DLOPEN)
+ ProcAdd = (STRPROCSTR)dlsym(hinstLib, (const char *)funcname);
+# else
+ if (shl_findsym(&hinstLib, (const char *)funcname,
+ TYPE_PROCEDURE, (void *)&ProcAdd) < 0)
+ ProcAdd = NULL;
+# endif
+ if ((success = (ProcAdd != NULL)))
+ {
+ if (string_result == NULL)
+ retval_int = ((STRPROCINT)ProcAdd)(argstring);
+ else
+ retval_str = (ProcAdd)(argstring);
+ }
+ }
+ else
+ {
+# if defined(USE_DLOPEN)
+ ProcAddI = (INTPROCSTR)dlsym(hinstLib, (const char *)funcname);
+# else
+ if (shl_findsym(&hinstLib, (const char *)funcname,
+ TYPE_PROCEDURE, (void *)&ProcAddI) < 0)
+ ProcAddI = NULL;
+# endif
+ if ((success = (ProcAddI != NULL)))
+ {
+ if (string_result == NULL)
+ retval_int = ((INTPROCINT)ProcAddI)(argint);
+ else
+ retval_str = (ProcAddI)(argint);
+ }
+ }
+
+ /* Save the string before we free the library. */
+ /* Assume that a "1" or "-1" result is an illegal pointer. */
+ if (string_result == NULL)
+ *number_result = retval_int;
+ else if (retval_str != NULL
+ && retval_str != (char_u *)1
+ && retval_str != (char_u *)-1)
+ *string_result = vim_strsave(retval_str);
+ }
+
+# ifdef HAVE_SETJMP_H
+ mch_endjmp();
+# ifdef SIGHASARG
+ if (lc_signal != 0)
+ {
+ int i;
+
+ /* try to find the name of this signal */
+ for (i = 0; signal_info[i].sig != -1; i++)
+ if (lc_signal == signal_info[i].sig)
+ break;
+ EMSG2("E368: got SIG%s in libcall()", signal_info[i].name);
+ }
+# endif
+# endif
+
+ /* Free the DLL module. */
+# if defined(USE_DLOPEN)
+ (void)dlclose(hinstLib);
+# else
+ (void)shl_unload(hinstLib);
+# endif
+ }
+
+ if (!success)
+ {
+ EMSG2(_(e_libcall), funcname);
+ return FAIL;
+ }
+
+ return OK;
+}
+#endif
+
+#if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
+static int xterm_trace = -1; /* default: disabled */
+static int xterm_button;
+
+/*
+ * Setup a dummy window for X selections in a terminal.
+ */
+ void
+setup_term_clip()
+{
+ int z = 0;
+ char *strp = "";
+ Widget AppShell;
+
+ if (!x_connect_to_server())
+ return;
+
+ open_app_context();
+ if (app_context != NULL && xterm_Shell == (Widget)0)
+ {
+ int (*oldhandler)();
+#if defined(HAVE_SETJMP_H)
+ int (*oldIOhandler)();
+#endif
+# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
+ struct timeval start_tv;
+
+ if (p_verbose > 0)
+ gettimeofday(&start_tv, NULL);
+# endif
+
+ /* Ignore X errors while opening the display */
+ oldhandler = XSetErrorHandler(x_error_check);
+
+#if defined(HAVE_SETJMP_H)
+ /* Ignore X IO errors while opening the display */
+ oldIOhandler = XSetIOErrorHandler(x_IOerror_check);
+ mch_startjmp();
+ if (SETJMP(lc_jump_env) != 0)
+ {
+ mch_didjmp();
+ xterm_dpy = NULL;
+ }
+ else
+#endif
+ {
+ xterm_dpy = XtOpenDisplay(app_context, xterm_display,
+ "vim_xterm", "Vim_xterm", NULL, 0, &z, &strp);
+#if defined(HAVE_SETJMP_H)
+ mch_endjmp();
+#endif
+ }
+
+#if defined(HAVE_SETJMP_H)
+ /* Now handle X IO errors normally. */
+ (void)XSetIOErrorHandler(oldIOhandler);
+#endif
+ /* Now handle X errors normally. */
+ (void)XSetErrorHandler(oldhandler);
+
+ if (xterm_dpy == NULL)
+ {
+ if (p_verbose > 0)
+ MSG(_("Opening the X display failed"));
+ return;
+ }
+
+ /* Catch terminating error of the X server connection. */
+ (void)XSetIOErrorHandler(x_IOerror_handler);
+
+# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
+ if (p_verbose > 0)
+ xopen_message(&start_tv);
+# endif
+
+ /* Create a Shell to make converters work. */
+ AppShell = XtVaAppCreateShell("vim_xterm", "Vim_xterm",
+ applicationShellWidgetClass, xterm_dpy,
+ NULL);
+ if (AppShell == (Widget)0)
+ return;
+ xterm_Shell = XtVaCreatePopupShell("VIM",
+ topLevelShellWidgetClass, AppShell,
+ XtNmappedWhenManaged, 0,
+ XtNwidth, 1,
+ XtNheight, 1,
+ NULL);
+ if (xterm_Shell == (Widget)0)
+ return;
+
+ x11_setup_atoms(xterm_dpy);
+ if (x11_display == NULL)
+ x11_display = xterm_dpy;
+
+ XtRealizeWidget(xterm_Shell);
+ XSync(xterm_dpy, False);
+ xterm_update();
+ }
+ if (xterm_Shell != (Widget)0)
+ {
+ clip_init(TRUE);
+ if (x11_window == 0 && (strp = getenv("WINDOWID")) != NULL)
+ x11_window = (Window)atol(strp);
+ /* Check if $WINDOWID is valid. */
+ if (test_x11_window(xterm_dpy) == FAIL)
+ x11_window = 0;
+ if (x11_window != 0)
+ xterm_trace = 0;
+ }
+}
+
+ void
+start_xterm_trace(button)
+ int button;
+{
+ if (x11_window == 0 || xterm_trace < 0 || xterm_Shell == (Widget)0)
+ return;
+ xterm_trace = 1;
+ xterm_button = button;
+ do_xterm_trace();
+}
+
+
+ void
+stop_xterm_trace()
+{
+ if (xterm_trace < 0)
+ return;
+ xterm_trace = 0;
+}
+
+/*
+ * Query the xterm pointer and generate mouse termcodes if necessary
+ * return TRUE if dragging is active, else FALSE
+ */
+ static int
+do_xterm_trace()
+{
+ Window root, child;
+ int root_x, root_y;
+ int win_x, win_y;
+ int row, col;
+ int_u mask_return;
+ char_u buf[50];
+ char_u *strp;
+ long got_hints;
+ static char_u *mouse_code;
+ static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER};
+ static int prev_row = 0, prev_col = 0;
+ static XSizeHints xterm_hints;
+
+ if (xterm_trace <= 0)
+ return FALSE;
+
+ if (xterm_trace == 1)
+ {
+ /* Get the hints just before tracking starts. The font size might
+ * have changed recently */
+ XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints);
+ if (!(got_hints & PResizeInc)
+ || xterm_hints.width_inc <= 1
+ || xterm_hints.height_inc <= 1)
+ {
+ xterm_trace = -1; /* Not enough data -- disable tracing */
+ return FALSE;
+ }
+
+ /* Rely on the same mouse code for the duration of this */
+ mouse_code = find_termcode(mouse_name);
+ prev_row = mouse_row;
+ prev_row = mouse_col;
+ xterm_trace = 2;
+
+ /* Find the offset of the chars, there might be a scrollbar on the
+ * left of the window and/or a menu on the top (eterm etc.) */
+ XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
+ &win_x, &win_y, &mask_return);
+ xterm_hints.y = win_y - (xterm_hints.height_inc * mouse_row)
+ - (xterm_hints.height_inc / 2);
+ if (xterm_hints.y <= xterm_hints.height_inc / 2)
+ xterm_hints.y = 2;
+ xterm_hints.x = win_x - (xterm_hints.width_inc * mouse_col)
+ - (xterm_hints.width_inc / 2);
+ if (xterm_hints.x <= xterm_hints.width_inc / 2)
+ xterm_hints.x = 2;
+ return TRUE;
+ }
+ if (mouse_code == NULL)
+ {
+ xterm_trace = 0;
+ return FALSE;
+ }
+
+ XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
+ &win_x, &win_y, &mask_return);
+
+ row = check_row((win_y - xterm_hints.y) / xterm_hints.height_inc);
+ col = check_col((win_x - xterm_hints.x) / xterm_hints.width_inc);
+ if (row == prev_row && col == prev_col)
+ return TRUE;
+
+ STRCPY(buf, mouse_code);
+ strp = buf + STRLEN(buf);
+ *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
+ *strp++ = (char_u)(col + ' ' + 1);
+ *strp++ = (char_u)(row + ' ' + 1);
+ *strp = 0;
+ add_to_input_buf(buf, STRLEN(buf));
+
+ prev_row = row;
+ prev_col = col;
+ return TRUE;
+}
+
+# if defined(FEAT_GUI) || defined(PROTO)
+/*
+ * Destroy the display, window and app_context. Required for GTK.
+ */
+ void
+clear_xterm_clip()
+{
+ if (xterm_Shell != (Widget)0)
+ {
+ XtDestroyWidget(xterm_Shell);
+ xterm_Shell = (Widget)0;
+ }
+ if (xterm_dpy != NULL)
+ {
+#if 0
+ /* Lesstif and Solaris crash here, lose some memory */
+ XtCloseDisplay(xterm_dpy);
+#endif
+ if (x11_display == xterm_dpy)
+ x11_display = NULL;
+ xterm_dpy = NULL;
+ }
+#if 0
+ if (app_context != (XtAppContext)NULL)
+ {
+ /* Lesstif and Solaris crash here, lose some memory */
+ XtDestroyApplicationContext(app_context);
+ app_context = (XtAppContext)NULL;
+ }
+#endif
+}
+# endif
+
+/*
+ * Catch up with any queued X events. This may put keyboard input into the
+ * input buffer, call resize call-backs, trigger timers etc. If there is
+ * nothing in the X event queue (& no timers pending), then we return
+ * immediately.
+ */
+ static void
+xterm_update()
+{
+ XEvent event;
+
+ while (XtAppPending(app_context) && !vim_is_input_buf_full())
+ {
+ XtAppNextEvent(app_context, &event);
+#ifdef FEAT_CLIENTSERVER
+ {
+ XPropertyEvent *e = (XPropertyEvent *)&event;
+
+ if (e->type == PropertyNotify && e->window == commWindow
+ && e->atom == commProperty && e->state == PropertyNewValue)
+ serverEventProc(xterm_dpy, &event);
+ }
+#endif
+ XtDispatchEvent(&event);
+ }
+}
+
+ int
+clip_xterm_own_selection(cbd)
+ VimClipboard *cbd;
+{
+ if (xterm_Shell != (Widget)0)
+ return clip_x11_own_selection(xterm_Shell, cbd);
+ return FAIL;
+}
+
+ void
+clip_xterm_lose_selection(cbd)
+ VimClipboard *cbd;
+{
+ if (xterm_Shell != (Widget)0)
+ clip_x11_lose_selection(xterm_Shell, cbd);
+}
+
+ void
+clip_xterm_request_selection(cbd)
+ VimClipboard *cbd;
+{
+ if (xterm_Shell != (Widget)0)
+ clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
+}
+
+ void
+clip_xterm_set_selection(cbd)
+ VimClipboard *cbd;
+{
+ clip_x11_set_selection(cbd);
+}
+#endif
+
+
+#if defined(USE_XSMP) || defined(PROTO)
+/*
+ * Code for X Session Management Protocol.
+ */
+static void xsmp_handle_save_yourself __ARGS((SmcConn smc_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast));
+static void xsmp_die __ARGS((SmcConn smc_conn, SmPointer client_data));
+static void xsmp_save_complete __ARGS((SmcConn smc_conn, SmPointer client_data));
+static void xsmp_shutdown_cancelled __ARGS((SmcConn smc_conn, SmPointer client_data));
+static void xsmp_ice_connection __ARGS((IceConn iceConn, IcePointer clientData, Bool opening, IcePointer *watchData));
+
+
+# if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
+static void xsmp_handle_interaction __ARGS((SmcConn smc_conn, SmPointer client_data));
+
+/*
+ * This is our chance to ask the user if they want to save,
+ * or abort the logout
+ */
+/*ARGSUSED*/
+ static void
+xsmp_handle_interaction(smc_conn, client_data)
+ SmcConn smc_conn;
+ SmPointer client_data;
+{
+ cmdmod_T save_cmdmod;
+ int cancel_shutdown = False;
+
+ save_cmdmod = cmdmod;
+ cmdmod.confirm = TRUE;
+ if (check_changed_any(FALSE))
+ /* Mustn't logout */
+ cancel_shutdown = True;
+ cmdmod = save_cmdmod;
+ setcursor(); /* position cursor */
+ out_flush();
+
+ /* Done interaction */
+ SmcInteractDone(smc_conn, cancel_shutdown);
+
+ /* Finish off
+ * Only end save-yourself here if we're not cancelling shutdown;
+ * we'll get a cancelled callback later in which we'll end it.
+ * Hopefully get around glitchy SMs (like GNOME-1)
+ */
+ if (!cancel_shutdown)
+ {
+ xsmp.save_yourself = False;
+ SmcSaveYourselfDone(smc_conn, True);
+ }
+}
+# endif
+
+/*
+ * Callback that starts save-yourself.
+ */
+/*ARGSUSED*/
+ static void
+xsmp_handle_save_yourself(smc_conn, client_data, save_type,
+ shutdown, interact_style, fast)
+ SmcConn smc_conn;
+ SmPointer client_data;
+ int save_type;
+ Bool shutdown;
+ int interact_style;
+ Bool fast;
+{
+ /* Handle already being in saveyourself */
+ if (xsmp.save_yourself)
+ SmcSaveYourselfDone(smc_conn, True);
+ xsmp.save_yourself = True;
+ xsmp.shutdown = shutdown;
+
+ /* First up, preserve all files */
+ out_flush();
+ ml_sync_all(FALSE, FALSE); /* preserve all swap files */
+
+ if (p_verbose > 0)
+ MSG(_("XSMP handling save-yourself request"));
+
+# if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
+ /* Now see if we can ask about unsaved files */
+ if (shutdown && !fast && gui.in_use)
+ /* Need to interact with user, but need SM's permission */
+ SmcInteractRequest(smc_conn, SmDialogError,
+ xsmp_handle_interaction, client_data);
+ else
+# endif
+ {
+ /* Can stop the cycle here */
+ SmcSaveYourselfDone(smc_conn, True);
+ xsmp.save_yourself = False;
+ }
+}
+
+
+/*
+ * Callback to warn us of imminent death.
+ */
+/*ARGSUSED*/
+ static void
+xsmp_die(smc_conn, client_data)
+ SmcConn smc_conn;
+ SmPointer client_data;
+{
+ xsmp_close();
+
+ /* quit quickly leaving swapfiles for modified buffers behind */
+ getout_preserve_modified(0);
+}
+
+
+/*
+ * Callback to tell us that save-yourself has completed.
+ */
+/*ARGSUSED*/
+ static void
+xsmp_save_complete(smc_conn, client_data)
+ SmcConn smc_conn;
+ SmPointer client_data;
+{
+ xsmp.save_yourself = False;
+}
+
+
+/*
+ * Callback to tell us that an instigated shutdown was cancelled
+ * (maybe even by us)
+ */
+/*ARGSUSED*/
+ static void
+xsmp_shutdown_cancelled(smc_conn, client_data)
+ SmcConn smc_conn;
+ SmPointer client_data;
+{
+ if (xsmp.save_yourself)
+ SmcSaveYourselfDone(smc_conn, True);
+ xsmp.save_yourself = False;
+ xsmp.shutdown = False;
+}
+
+
+/*
+ * Callback to tell us that a new ICE connection has been established.
+ */
+/*ARGSUSED*/
+ static void
+xsmp_ice_connection(iceConn, clientData, opening, watchData)
+ IceConn iceConn;
+ IcePointer clientData;
+ Bool opening;
+ IcePointer *watchData;
+{
+ /* Intercept creation of ICE connection fd */
+ if (opening)
+ {
+ xsmp_icefd = IceConnectionNumber(iceConn);
+ IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
+ }
+}
+
+
+/* Handle any ICE processing that's required; return FAIL if SM lost */
+ int
+xsmp_handle_requests()
+{
+ Bool rep;
+
+ if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
+ == IceProcessMessagesIOError)
+ {
+ /* Lost ICE */
+ if (p_verbose > 0)
+ MSG(_("XSMP lost ICE connection"));
+ xsmp_close();
+ return FAIL;
+ }
+ else
+ return OK;
+}
+
+static int dummy;
+
+/* Set up X Session Management Protocol */
+ void
+xsmp_init(void)
+{
+ char errorstring[80];
+ char *clientid;
+ SmcCallbacks smcallbacks;
+#if 0
+ SmPropValue smname;
+ SmProp smnameprop;
+ SmProp *smprops[1];
+#endif
+
+ if (p_verbose > 0)
+ MSG(_("XSMP opening connection"));
+
+ xsmp.save_yourself = xsmp.shutdown = False;
+
+ /* Set up SM callbacks - must have all, even if they're not used */
+ smcallbacks.save_yourself.callback = xsmp_handle_save_yourself;
+ smcallbacks.save_yourself.client_data = NULL;
+ smcallbacks.die.callback = xsmp_die;
+ smcallbacks.die.client_data = NULL;
+ smcallbacks.save_complete.callback = xsmp_save_complete;
+ smcallbacks.save_complete.client_data = NULL;
+ smcallbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
+ smcallbacks.shutdown_cancelled.client_data = NULL;
+
+ /* Set up a watch on ICE connection creations. The "dummy" argument is
+ * apparently required for FreeBSD (we get a BUS error when using NULL). */
+ if (IceAddConnectionWatch(xsmp_ice_connection, &dummy) == 0)
+ {
+ if (p_verbose > 0)
+ MSG(_("XSMP ICE connection watch failed"));
+ return;
+ }
+
+ /* Create an SM connection */
+ xsmp.smcconn = SmcOpenConnection(
+ NULL,
+ NULL,
+ SmProtoMajor,
+ SmProtoMinor,
+ SmcSaveYourselfProcMask | SmcDieProcMask
+ | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
+ &smcallbacks,
+ NULL,
+ &clientid,
+ sizeof(errorstring),
+ errorstring);
+ if (xsmp.smcconn == NULL)
+ {
+ char errorreport[132];
+ sprintf(errorreport, _("XSMP SmcOpenConnection failed: %s"),
+ errorstring);
+ if (p_verbose > 0)
+ MSG(errorreport);
+ return;
+ }
+ xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
+
+#if 0
+ /* ID ourselves */
+ smname.value = "vim";
+ smname.length = 3;
+ smnameprop.name = "SmProgram";
+ smnameprop.type = "SmARRAY8";
+ smnameprop.num_vals = 1;
+ smnameprop.vals = &smname;
+
+ smprops[0] = &smnameprop;
+ SmcSetProperties(xsmp.smcconn, 1, smprops);
+#endif
+}
+
+
+/* Shut down XSMP comms. */
+ void
+xsmp_close()
+{
+ if (xsmp_icefd != -1)
+ {
+ SmcCloseConnection(xsmp.smcconn, 0, NULL);
+ xsmp_icefd = -1;
+ }
+}
+#endif /* USE_XSMP */
+
+
+#ifdef EBCDIC
+/* Translate character to its CTRL- value */
+char CtrlTable[] =
+{
+/* 00 - 5E */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* ^ */ 0x1E,
+/* - */ 0x1F,
+/* 61 - 6C */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* _ */ 0x1F,
+/* 6E - 80 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* a */ 0x01,
+/* b */ 0x02,
+/* c */ 0x03,
+/* d */ 0x37,
+/* e */ 0x2D,
+/* f */ 0x2E,
+/* g */ 0x2F,
+/* h */ 0x16,
+/* i */ 0x05,
+/* 8A - 90 */
+ 0, 0, 0, 0, 0, 0, 0,
+/* j */ 0x15,
+/* k */ 0x0B,
+/* l */ 0x0C,
+/* m */ 0x0D,
+/* n */ 0x0E,
+/* o */ 0x0F,
+/* p */ 0x10,
+/* q */ 0x11,
+/* r */ 0x12,
+/* 9A - A1 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/* s */ 0x13,
+/* t */ 0x3C,
+/* u */ 0x3D,
+/* v */ 0x32,
+/* w */ 0x26,
+/* x */ 0x18,
+/* y */ 0x19,
+/* z */ 0x3F,
+/* AA - AC */
+ 0, 0, 0,
+/* [ */ 0x27,
+/* AE - BC */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* ] */ 0x1D,
+/* BE - C0 */ 0, 0, 0,
+/* A */ 0x01,
+/* B */ 0x02,
+/* C */ 0x03,
+/* D */ 0x37,
+/* E */ 0x2D,
+/* F */ 0x2E,
+/* G */ 0x2F,
+/* H */ 0x16,
+/* I */ 0x05,
+/* CA - D0 */ 0, 0, 0, 0, 0, 0, 0,
+/* J */ 0x15,
+/* K */ 0x0B,
+/* L */ 0x0C,
+/* M */ 0x0D,
+/* N */ 0x0E,
+/* O */ 0x0F,
+/* P */ 0x10,
+/* Q */ 0x11,
+/* R */ 0x12,
+/* DA - DF */ 0, 0, 0, 0, 0, 0,
+/* \ */ 0x1C,
+/* E1 */ 0,
+/* S */ 0x13,
+/* T */ 0x3C,
+/* U */ 0x3D,
+/* V */ 0x32,
+/* W */ 0x26,
+/* X */ 0x18,
+/* Y */ 0x19,
+/* Z */ 0x3F,
+/* EA - FF*/ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+char MetaCharTable[]=
+{/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ 0, 0, 0, 0,'\\', 0,'F', 0,'W','M','N', 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,']', 0, 0,'G', 0, 0,'R','O', 0, 0, 0, 0,
+ '@','A','B','C','D','E', 0, 0,'H','I','J','K','L', 0, 0, 0,
+ 'P','Q', 0,'S','T','U','V', 0,'X','Y','Z','[', 0, 0,'^', 0
+};
+
+
+/* TODO: Use characters NOT numbers!!! */
+char CtrlCharTable[]=
+{/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ 124,193,194,195, 0,201, 0, 0, 0, 0, 0,210,211,212,213,214,
+ 215,216,217,226, 0,209,200, 0,231,232, 0, 0,224,189, 95,109,
+ 0, 0, 0, 0, 0, 0,230,173, 0, 0, 0, 0, 0,197,198,199,
+ 0, 0,229, 0, 0, 0, 0,196, 0, 0, 0, 0,227,228, 0,233,
+};
+
+
+#endif
diff --git a/src/os_unix.h b/src/os_unix.h
new file mode 100644
index 000000000..b78b23e7b
--- /dev/null
+++ b/src/os_unix.h
@@ -0,0 +1,531 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * NextStep has a problem with configure, undefine a few things:
+ */
+#ifdef NeXT
+# ifdef HAVE_UTIME
+# undef HAVE_UTIME
+# endif
+# ifdef HAVE_SYS_UTSNAME_H
+# undef HAVE_SYS_UTSNAME_H
+# endif
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef VAXC
+# include <types.h>
+# include <stat.h>
+#else
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef __EMX__
+# define HAVE_TOTAL_MEM
+#endif
+
+#if defined(__CYGWIN__) || defined(__CYGWIN32__)
+# define WIN32UNIX /* Compiling for Win32 using Unix files. */
+# define BINARY_FILE_IO
+#endif
+
+/* On AIX 4.2 there is a conflicting prototype for ioctl() in stropts.h and
+ * unistd.h. This hack should fix that (suggested by Jeff George).
+ * But on AIX 4.3 it's alright (suggested by Jake Hamby). */
+#if defined(FEAT_GUI) && defined(_AIX) && !defined(_AIX43) && !defined(_NO_PROTO)
+# define _NO_PROTO
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_LIBC_H
+# include <libc.h> /* for NeXT */
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h> /* defines BSD, if it's a BSD system */
+#endif
+
+/*
+ * Sun defines FILE on SunOS 4.x.x, Solaris has a typedef for FILE
+ */
+#if defined(sun) && !defined(FILE)
+# define SOLARIS
+#endif
+
+/*
+ * Using getcwd() is preferred, because it checks for a buffer overflow.
+ * Don't use getcwd() on systems do use system("sh -c pwd"). There is an
+ * autoconf check for this.
+ * Use getcwd() anyway if getwd() isn't present.
+ */
+#if defined(HAVE_GETCWD) && !(defined(BAD_GETCWD) && defined(HAVE_GETWD))
+# define USE_GETCWD
+#endif
+
+#ifndef __ARGS
+ /* The AIX VisualAge cc compiler defines __EXTENDED__ instead of __STDC__
+ * because it includes pre-ansi features. */
+# if defined(__STDC__) || defined(__GNUC__) || defined(__EXTENDED__)
+# define __ARGS(x) x
+# else
+# define __ARGS(x) ()
+# endif
+#endif
+
+/* always use unlink() to remove files */
+#ifndef PROTO
+# ifdef VMS
+# define mch_remove(x) delete((char *)(x))
+# define vim_mkdir(x, y) mkdir((char *)(x), y)
+# ifdef VAX
+# else
+# define mch_rmdir(x) rmdir((char *)(x))
+# endif
+# else
+# define vim_mkdir(x, y) mkdir((char *)(x), y)
+# define mch_rmdir(x) rmdir((char *)(x))
+# define mch_remove(x) unlink((char *)(x))
+# endif
+#endif
+
+/* The number of arguments to a signal handler is configured here. */
+/* It used to be a long list of almost all systems. Any system that doesn't
+ * have an argument??? */
+#define SIGHASARG
+
+/* List 3 arg systems here. I guess __sgi, please test and correct me. jw. */
+#if defined(__sgi) && defined(HAVE_SIGCONTEXT)
+# define SIGHAS3ARGS
+#endif
+
+#ifdef SIGHASARG
+# ifdef SIGHAS3ARGS
+# define SIGPROTOARG (int, int, struct sigcontext *)
+# define SIGDEFARG(s) (s, sig2, scont) int s, sig2; struct sigcontext *scont;
+# define SIGDUMMYARG 0, 0, (struct sigcontext *)0
+# else
+# define SIGPROTOARG (int)
+# define SIGDEFARG(s) (s) int s;
+# define SIGDUMMYARG 0
+# endif
+#else
+# define SIGPROTOARG (void)
+# define SIGDEFARG(s) ()
+# define SIGDUMMYARG
+#endif
+
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+# ifndef NAMLEN
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+# endif
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#if !defined(HAVE_SYS_TIME_H) || defined(TIME_WITH_SYS_TIME)
+# include <time.h> /* on some systems time.h should not be
+ included together with sys/time.h */
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#include <signal.h>
+
+#if defined(DIRSIZ) && !defined(MAXNAMLEN)
+# define MAXNAMLEN DIRSIZ
+#endif
+
+#if defined(UFS_MAXNAMLEN) && !defined(MAXNAMLEN)
+# define MAXNAMLEN UFS_MAXNAMLEN /* for dynix/ptx */
+#endif
+
+#if defined(NAME_MAX) && !defined(MAXNAMLEN)
+# define MAXNAMLEN NAME_MAX /* for Linux before .99p3 */
+#endif
+
+/*
+ * Note: if MAXNAMLEN has the wrong value, you will get error messages
+ * for not being able to open the swap file.
+ */
+#if !defined(MAXNAMLEN)
+# define MAXNAMLEN 512 /* for all other Unix */
+#endif
+
+#define BASENAMELEN (MAXNAMLEN - 5)
+
+#ifdef HAVE_ERRNO_H
+# include <errno.h>
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+#ifdef __COHERENT__
+# undef __ARGS
+#endif
+
+#if (defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT)) \
+ || (defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)) \
+ || defined(HAVE_SYSCTL) || defined(HAVE_SYSCONF)
+# define HAVE_TOTAL_MEM
+#endif
+
+#ifdef VMS
+#include <unixio.h>
+#include <unixlib.h>
+#include <signal.h>
+#include <file.h>
+#include <ssdef.h>
+#include <descrip.h>
+#include <libclidef.h>
+#include <lnmdef.h>
+#include <psldef.h>
+#include <prvdef.h>
+#include <dvidef.h>
+#include <dcdef.h>
+#include <stsdef.h>
+#include <iodef.h>
+#include <ttdef.h>
+#include <tt2def.h>
+#include <jpidef.h>
+#include <rms.h>
+#include <trmdef.h>
+#include <string.h>
+#include <starlet.h>
+#include <socket.h>
+#include <lib$routines.h>
+
+typedef struct dsc$descriptor DESC;
+#endif
+
+/*
+ * Unix system-dependent file names
+ */
+#ifndef SYS_VIMRC_FILE
+# define SYS_VIMRC_FILE "$VIM/vimrc"
+#endif
+#ifndef SYS_GVIMRC_FILE
+# define SYS_GVIMRC_FILE "$VIM/gvimrc"
+#endif
+#ifndef DFLT_HELPFILE
+# define DFLT_HELPFILE "$VIMRUNTIME/doc/help.txt"
+#endif
+#ifndef FILETYPE_FILE
+# define FILETYPE_FILE "filetype.vim"
+#endif
+#ifndef FTPLUGIN_FILE
+# define FTPLUGIN_FILE "ftplugin.vim"
+#endif
+#ifndef INDENT_FILE
+# define INDENT_FILE "indent.vim"
+#endif
+#ifndef FTOFF_FILE
+# define FTOFF_FILE "ftoff.vim"
+#endif
+#ifndef FTPLUGOF_FILE
+# define FTPLUGOF_FILE "ftplugof.vim"
+#endif
+#ifndef INDOFF_FILE
+# define INDOFF_FILE "indoff.vim"
+#endif
+#ifndef SYS_MENU_FILE
+# define SYS_MENU_FILE "$VIMRUNTIME/menu.vim"
+#endif
+
+#ifndef USR_EXRC_FILE
+# ifdef VMS
+# define USR_EXRC_FILE "sys$login:.exrc"
+# else
+# define USR_EXRC_FILE "$HOME/.exrc"
+# endif
+#endif
+
+#if !defined(USR_EXRC_FILE2) && defined(OS2)
+# define USR_EXRC_FILE2 "$VIM/.exrc"
+#endif
+#if !defined(USR_EXRC_FILE2) && defined(VMS)
+# define USR_EXRC_FILE2 "sys$login:_exrc"
+#endif
+
+#ifndef USR_VIMRC_FILE
+# ifdef VMS
+# define USR_VIMRC_FILE "sys$login:.vimrc"
+# else
+# define USR_VIMRC_FILE "$HOME/.vimrc"
+# endif
+#endif
+
+#if !defined(USR_VIMRC_FILE2) && defined(OS2)
+# define USR_VIMRC_FILE2 "$VIM/.vimrc"
+#endif
+#if !defined(USR_VIMRC_FILE2) && defined(VMS)
+# define USR_VIMRC_FILE2 "sys$login:_vimrc"
+#endif
+
+#ifndef USR_GVIMRC_FILE
+# ifdef VMS
+# define USR_GVIMRC_FILE "sys$login:.gvimrc"
+# else
+# define USR_GVIMRC_FILE "$HOME/.gvimrc"
+# endif
+#endif
+
+#ifdef VMS
+# ifndef USR_GVIMRC_FILE2
+# define USR_GVIMRC_FILE2 "sys$login:_gvimrc"
+# endif
+#endif
+
+#ifndef EVIM_FILE
+# define EVIM_FILE "$VIMRUNTIME/evim.vim"
+#endif
+
+#ifdef FEAT_VIMINFO
+# ifndef VIMINFO_FILE
+# ifdef VMS
+# define VIMINFO_FILE "sys$login:.viminfo"
+# else
+# define VIMINFO_FILE "$HOME/.viminfo"
+# endif
+# endif
+# if !defined(VIMINFO_FILE2) && defined(OS2)
+# define VIMINFO_FILE2 "$VIM/.viminfo"
+# endif
+# if !defined(VIMINFO_FILE2) && defined(VMS)
+# define VIMINFO_FILE2 "sys$login:_viminfo"
+# endif
+#endif
+
+#ifndef EXRC_FILE
+# define EXRC_FILE ".exrc"
+#endif
+
+#ifndef VIMRC_FILE
+# define VIMRC_FILE ".vimrc"
+#endif
+
+#ifdef FEAT_GUI
+# ifndef GVIMRC_FILE
+# define GVIMRC_FILE ".gvimrc"
+# endif
+#endif
+
+#ifndef SYNTAX_FNAME
+# define SYNTAX_FNAME "$VIMRUNTIME/syntax/%s.vim"
+#endif
+
+#ifndef DFLT_BDIR
+# ifdef OS2
+# define DFLT_BDIR ".,c:/tmp,~/tmp,~/"
+# else
+# ifdef VMS
+# define DFLT_BDIR "./,sys$login:,tmp:"
+# else
+# define DFLT_BDIR ".,~/tmp,~/" /* default for 'backupdir' */
+# endif
+# endif
+#endif
+
+#ifndef DFLT_DIR
+# ifdef OS2
+# define DFLT_DIR ".,~/tmp,c:/tmp,/tmp"
+# else
+# ifdef VMS
+# define DFLT_DIR "./,sys$login:,tmp:"
+# else
+# define DFLT_DIR ".,~/tmp,/var/tmp,/tmp" /* default for 'directory' */
+# endif
+# endif
+#endif
+
+#ifndef DFLT_VDIR
+# ifdef OS2
+# define DFLT_VDIR "$VIM/vimfiles/view"
+# else
+# ifdef VMS
+# define DFLT_VDIR "sys$login:vimfiles/view"
+# else
+# define DFLT_VDIR "$HOME/.vim/view" /* default for 'viewdir' */
+# endif
+# endif
+#endif
+
+#define DFLT_ERRORFILE "errors.err"
+
+#ifdef OS2
+# define DFLT_RUNTIMEPATH "$HOME/vimfiles,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,$HOME/vimfiles/after"
+#else
+# ifdef VMS
+# define DFLT_RUNTIMEPATH "sys$login:vimfiles,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,sys$login:vimfiles/after"
+# else
+# ifdef RUNTIME_GLOBAL
+# define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after,~/.vim/after"
+# else
+# define DFLT_RUNTIMEPATH "~/.vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,~/.vim/after"
+# endif
+# endif
+#endif
+
+#ifdef OS2
+/*
+ * Try several directories to put the temp files.
+ */
+# define TEMPDIRNAMES "$TMP", "$TEMP", "c:\\TMP", "c:\\TEMP", ""
+# define TEMPNAMELEN 128
+#else
+# ifdef VMS
+# ifndef VAX
+# define VMS_TEMPNAM /* to fix default .LIS extension */
+# endif
+# define TEMPNAME "TMP:v?XXXXXX.txt"
+# define TEMPNAMELEN 28
+# else
+# define TEMPDIRNAMES "$TMPDIR", "/tmp", ".", "$HOME"
+# define TEMPNAMELEN 256
+# endif
+#endif
+
+/* Special wildcards that need to be handled by the shell */
+#define SPECIAL_WILDCHAR "`'{"
+
+#ifndef HAVE_OPENDIR
+# define NO_EXPANDPATH
+#endif
+
+/*
+ * Unix has plenty of memory, use large buffers
+ */
+#define CMDBUFFSIZE 1024 /* size of the command processing buffer */
+#define MAXPATHL 1024 /* Unix has long paths and plenty of memory */
+
+#define CHECK_INODE /* used when checking if a swap file already
+ exists for a file */
+#ifdef VMS /* Use less memory because of older systems */
+# ifndef DFLT_MAXMEM
+# define DFLT_MAXMEM (2*1024)
+# endif
+# ifndef DFLT_MAXMEMTOT
+# define DFLT_MAXMEMTOT (5*1024)
+# endif
+#else
+# ifndef DFLT_MAXMEM
+# define DFLT_MAXMEM (5*1024) /* use up to 5 Mbyte for a buffer */
+# endif
+# ifndef DFLT_MAXMEMTOT
+# define DFLT_MAXMEMTOT (10*1024) /* use up to 10 Mbyte for Vim */
+# endif
+#endif
+
+/* memmove is not present on all systems, use memmove, bcopy, memcpy or our
+ * own version */
+/* Some systems have (void *) arguments, some (char *). If we use (char *) it
+ * works for all */
+#ifdef USEMEMMOVE
+# define mch_memmove(to, from, len) memmove((char *)(to), (char *)(from), len)
+#else
+# ifdef USEBCOPY
+# define mch_memmove(to, from, len) bcopy((char *)(from), (char *)(to), len)
+# else
+# ifdef USEMEMCPY
+# define mch_memmove(to, from, len) memcpy((char *)(to), (char *)(from), len)
+# else
+# define VIM_MEMMOVE /* found in misc2.c */
+# endif
+# endif
+#endif
+
+#ifndef PROTO
+# ifdef HAVE_RENAME
+# define mch_rename(src, dst) rename(src, dst)
+# else
+int mch_rename __ARGS((const char *src, const char *dest));
+# endif
+# ifdef VMS
+# define mch_chdir(s) chdir(vms_fixfilename(s))
+# else
+# define mch_chdir(s) chdir(s)
+# endif
+# ifndef VMS
+# ifdef __MVS__
+ /* on OS390 Unix getenv() doesn't return a pointer to persistant
+ * storage -> use __getenv() */
+# define mch_getenv(x) (char_u *)__getenv((char *)(x))
+# else
+# define mch_getenv(x) (char_u *)getenv((char *)(x))
+# endif
+# define mch_setenv(name, val, x) setenv(name, val, x)
+# endif
+#endif
+
+#if !defined(S_ISDIR) && defined(S_IFDIR)
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG) && defined(S_IFREG)
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISBLK) && defined(S_IFBLK)
+# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#endif
+#if !defined(S_ISSOCK) && defined(S_IFSOCK)
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISFIFO) && defined(S_IFIFO)
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#endif
+
+/* Note: Some systems need both string.h and strings.h (Savage). However,
+ * some systems can't handle both, only use string.h in that case. */
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#if defined(HAVE_STRINGS_H) && !defined(NO_STRINGS_WITH_STRING_H)
+# include <strings.h>
+#endif
+
+#if defined(HAVE_SETJMP_H)
+# include <setjmp.h>
+# ifdef HAVE_SIGSETJMP
+# define JMP_BUF sigjmp_buf
+# define SETJMP(x) sigsetjmp((x), 1)
+# define LONGJMP siglongjmp
+# else
+# define JMP_BUF jmp_buf
+# define SETJMP(x) setjmp(x)
+# define LONGJMP longjmp
+# endif
+#endif
+
+#define HAVE_DUP /* have dup() */
+#define HAVE_ST_MODE /* have stat.st_mode */
+
+/* We have three kinds of ACL support. */
+#define HAVE_ACL (HAVE_POSIX_ACL || HAVE_SOLARIS_ACL || HAVE_AIX_ACL)
diff --git a/src/os_unixx.h b/src/os_unixx.h
new file mode 100644
index 000000000..9f4f7eb60
--- /dev/null
+++ b/src/os_unixx.h
@@ -0,0 +1,130 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * os_unixx.h -- include files that are only used in os_unix.c
+ */
+
+/*
+ * Stuff for signals
+ */
+#if defined(HAVE_SIGSET) && !defined(signal)
+# define signal sigset
+#endif
+
+ /* sun's sys/ioctl.h redefines symbols from termio world */
+#if defined(HAVE_SYS_IOCTL_H) && !defined(sun)
+# include <sys/ioctl.h>
+#endif
+
+#ifndef USE_SYSTEM /* use fork/exec to start the shell */
+
+# if defined(HAVE_SYS_WAIT_H) || defined(HAVE_UNION_WAIT)
+# include <sys/wait.h>
+# endif
+
+# if defined(HAVE_SYS_SELECT_H) && \
+ (!defined(HAVE_SYS_TIME_H) || defined(SYS_SELECT_WITH_SYS_TIME))
+# include <sys/select.h>
+# endif
+
+# ifndef WEXITSTATUS
+# ifdef HAVE_UNION_WAIT
+# define WEXITSTATUS(stat_val) ((stat_val).w_T.w_Retcode)
+# else
+# define WEXITSTATUS(stat_val) (((stat_val) >> 8) & 0377)
+# endif
+# endif
+
+# ifndef WIFEXITED
+# ifdef HAVE_UNION_WAIT
+# define WIFEXITED(stat_val) ((stat_val).w_T.w_Termsig == 0)
+# else
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+# endif
+# endif
+
+#endif /* !USE_SYSTEM */
+
+#ifdef HAVE_STROPTS_H
+#ifdef sinix
+#define buf_T __system_buf_t__
+#endif
+# include <stropts.h>
+#ifdef sinix
+#undef buf_T
+#endif
+#endif
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+
+#ifndef HAVE_SELECT
+# ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+# else
+# ifdef HAVE_POLL_H
+# include <poll.h>
+# endif
+# endif
+#endif
+
+#ifdef HAVE_SYS_STREAM_H
+# include <sys/stream.h>
+#endif
+
+#ifdef HAVE_SYS_UTSNAME_H
+# include <sys/utsname.h>
+#endif
+
+#ifdef HAVE_SYS_SYSTEMINFO_H
+/*
+ * foolish Sinix <sys/systeminfo.h> uses SYS_NMLN but doesn't include
+ * <limits.h>, where it is defined. Perhaps other systems have the same
+ * problem? Include it here. -- Slootman
+ */
+# if defined(HAVE_LIMITS_H) && !defined(_LIMITS_H)
+# include <limits.h> /* for SYS_NMLN (Sinix 5.41 / Unix SysV.4) */
+# endif
+# include <sys/systeminfo.h> /* for sysinfo */
+#endif
+
+/*
+ * We use termios.h if both termios.h and termio.h are available.
+ * Termios is supposed to be a superset of termio.h. Don't include them both,
+ * it may give problems on some systems (e.g. hpux).
+ * I don't understand why we don't want termios.h for apollo.
+ */
+#if defined(HAVE_TERMIOS_H) && !defined(apollo)
+# include <termios.h>
+#else
+# ifdef HAVE_TERMIO_H
+# include <termio.h>
+# else
+# ifdef HAVE_SGTTY_H
+# include <sgtty.h>
+# endif
+# endif
+#endif
+
+#ifdef HAVE_SYS_PTEM_H
+# include <sys/ptem.h> /* must be after termios.h for Sinix */
+# ifndef _IO_PTEM_H /* For UnixWare that should check for _IO_PT_PTEM_H */
+# define _IO_PTEM_H
+# endif
+#endif
+
+/* shared library access */
+#if defined(HAVE_DLFCN_H) && defined(USE_DLOPEN)
+# include <dlfcn.h>
+#else
+# if defined(HAVE_DL_H) && defined(HAVE_SHL_LOAD)
+# include <dl.h>
+# endif
+#endif
diff --git a/src/os_vms.c b/src/os_vms.c
new file mode 100644
index 000000000..ab5eca4e1
--- /dev/null
+++ b/src/os_vms.c
@@ -0,0 +1,657 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * VMS port by Henk Elbers
+ * VMS deport by Zoltan Arpadffy
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+
+typedef struct
+{
+ char class;
+ char type;
+ short width;
+ union
+ {
+ struct
+ {
+ char _basic[3];
+ char length;
+ } y;
+ int basic;
+ } x;
+ int extended;
+} TT_MODE;
+
+typedef struct
+{
+ short buflen;
+ short itemcode;
+ char *bufadrs;
+ int *retlen;
+} ITEM;
+
+typedef struct
+{
+ ITEM equ;
+ int nul;
+} ITMLST1;
+
+typedef struct
+{
+ ITEM index;
+ ITEM string;
+ int nul;
+} ITMLST2;
+
+static TT_MODE orgmode;
+static short iochan; /* TTY I/O channel */
+static short iosb[4]; /* IO status block */
+
+static int vms_match_num = 0;
+static int vms_match_free = 0;
+static char_u **vms_fmatch = NULL;
+static char *Fspec_Rms; /* rms file spec, passed implicitly between routines */
+
+
+
+static TT_MODE get_tty __ARGS((void));
+static void set_tty __ARGS((int row, int col));
+
+#define EXPL_ALLOC_INC 64
+
+#define EQN(S1,S2,LN) (strncmp(S1,S2,LN) == 0)
+#define SKIP_FOLLOWING_SLASHES(Str) while (Str[1] == '/') ++Str
+
+
+/*
+ * vul_desc vult een descriptor met een string en de lengte
+ * hier van.
+ */
+ static void
+vul_desc(DESC *des, char *str)
+{
+ des->dsc$b_dtype = DSC$K_DTYPE_T;
+ des->dsc$b_class = DSC$K_CLASS_S;
+ des->dsc$a_pointer = str;
+ des->dsc$w_length = str ? strlen(str) : 0;
+}
+
+/*
+ * vul_item vult een item met een aantal waarden
+ */
+ static void
+vul_item(ITEM *itm, short len, short cod, char *adr, int *ret)
+{
+ itm->buflen = len;
+ itm->itemcode = cod;
+ itm->bufadrs = adr;
+ itm->retlen = ret;
+}
+
+ void
+mch_settmode(int tmode)
+{
+ int status;
+
+ if ( tmode == TMODE_RAW )
+ set_tty(0, 0);
+ else{
+ switch (orgmode.width)
+ {
+ case 132: OUT_STR_NF((char_u *)"\033[?3h\033>"); break;
+ case 80: OUT_STR_NF((char_u *)"\033[?3l\033>"); break;
+ default: break;
+ }
+ out_flush();
+ status = sys$qiow(0, iochan, IO$_SETMODE, iosb, 0, 0,
+ &orgmode, sizeof(TT_MODE), 0,0,0,0);
+ if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
+ return;
+ (void)sys$dassgn(iochan);
+ iochan = 0;
+ }
+}
+
+ static void
+set_tty(int row, int col)
+{
+ int status;
+ TT_MODE newmode; /* New TTY mode bits */
+ static short first_time = TRUE;
+
+ if (first_time)
+ {
+ orgmode = get_tty();
+ first_time = FALSE;
+ }
+ newmode = get_tty();
+ if (col)
+ newmode.width = col;
+ if (row)
+ newmode.x.y.length = row;
+ newmode.x.basic |= (TT$M_NOECHO | TT$M_HOSTSYNC);
+ newmode.x.basic &= ~TT$M_TTSYNC;
+ newmode.extended |= TT2$M_PASTHRU;
+ status = sys$qiow(0, iochan, IO$_SETMODE, iosb, 0, 0,
+ &newmode, sizeof(newmode), 0, 0, 0, 0);
+ if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
+ return;
+}
+
+ static TT_MODE
+get_tty(void)
+{
+
+ static $DESCRIPTOR(odsc,"SYS$OUTPUT"); /* output descriptor */
+
+ int status;
+ TT_MODE tt_mode;
+
+ if (!iochan)
+ status = sys$assign(&odsc,&iochan,0,0);
+
+ status = sys$qiow(0, iochan, IO$_SENSEMODE, iosb, 0, 0,
+ &tt_mode, sizeof(tt_mode), 0, 0, 0, 0);
+ if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL)
+ {
+ tt_mode.width = 0;
+ tt_mode.type = 0;
+ tt_mode.class = 0;
+ tt_mode.x.basic = 0;
+ tt_mode.x.y.length = 0;
+ tt_mode.extended = 0;
+ }
+ return(tt_mode);
+}
+
+/*
+ * Get the current window size in Rows and Columns.
+ */
+ int
+mch_get_shellsize(void)
+{
+ TT_MODE tmode;
+
+ tmode = get_tty(); /* get size from VMS */
+ Columns = tmode.width;
+ Rows = tmode.x.y.length;
+ return OK;
+}
+
+/*
+ * Try to set the window size to Rows and new_Columns.
+ */
+ void
+mch_set_shellsize(void)
+{
+ set_tty(Rows, Columns);
+ switch (Columns)
+ {
+ case 132: OUT_STR_NF((char_u *)"\033[?3h\033>"); break;
+ case 80: OUT_STR_NF((char_u *)"\033[?3l\033>"); break;
+ default: break;
+ }
+ out_flush();
+ screen_start();
+}
+
+ char_u *
+mch_getenv(char_u *lognam)
+{
+ DESC d_file_dev, d_lognam ;
+ static char buffer[LNM$C_NAMLENGTH+1];
+ char_u *cp = NULL;
+ unsigned long attrib;
+ int lengte = 0, dum = 0, idx = 0;
+ ITMLST2 itmlst;
+ char *sbuf = NULL;
+
+ vul_desc(&d_lognam, (char *)lognam);
+ vul_desc(&d_file_dev, "LNM$FILE_DEV");
+ attrib = LNM$M_CASE_BLIND;
+ vul_item(&itmlst.index, sizeof(int), LNM$_INDEX, (char *)&idx, &dum);
+ vul_item(&itmlst.string, LNM$C_NAMLENGTH, LNM$_STRING, buffer, &lengte);
+ itmlst.nul = 0;
+ if (sys$trnlnm(&attrib, &d_file_dev, &d_lognam, NULL,&itmlst) == SS$_NORMAL)
+ {
+ buffer[lengte] = '\0';
+ if (cp = (char_u *)alloc((unsigned)(lengte+1)))
+ strcpy((char *)cp, buffer);
+ return(cp);
+ }
+ else if ((sbuf = getenv((char *)lognam)))
+ {
+ lengte = strlen(sbuf) + 1;
+ cp = (char_u *)malloc((size_t)lengte);
+ if (cp)
+ strcpy((char *)cp, sbuf);
+ return cp;
+ }
+ else
+ return(NULL);
+}
+
+/*
+ * mch_setenv VMS version of setenv()
+ */
+ int
+mch_setenv(char *var, char *value, int x)
+{
+ int res, dum;
+ long attrib = 0L;
+ char acmode = PSL$C_SUPER; /* needs SYSNAM privilege */
+ DESC tabnam, lognam;
+ ITMLST1 itmlst;
+
+ vul_desc(&tabnam, "LNM$JOB");
+ vul_desc(&lognam, var);
+ vul_item(&itmlst.equ, value ? strlen(value) : 0, value ? LNM$_STRING : 0,
+ value, &dum);
+ itmlst.nul = 0;
+ res = sys$crelnm(&attrib, &tabnam, &lognam, &acmode, &itmlst);
+ return((res == 1) ? 0 : -1);
+}
+
+ int
+vms_sys(char *cmd, char *out, char *inp)
+{
+ DESC cdsc, odsc, idsc;
+ long status;
+
+ if (cmd)
+ vul_desc(&cdsc, cmd);
+ if (out)
+ vul_desc(&odsc, out);
+ if (inp)
+ vul_desc(&idsc, inp);
+
+ lib$spawn(cmd ? &cdsc : NULL, /* command string */
+ inp ? &idsc : NULL, /* input file */
+ out ? &odsc : NULL, /* output file */
+ 0, 0, 0, &status, 0, 0, 0, 0, 0, 0);
+ return status;
+}
+
+/*
+ * Convert VMS system() or lib$spawn() return code to Unix-like exit value.
+ */
+ int
+vms_sys_status(int status)
+{
+ if (status != SS$_NORMAL && (status & STS$M_SUCCESS) == 0)
+ return status; /* Command failed. */
+ return 0;
+}
+
+/*
+ * vms_read()
+ * function for low level char input
+ *
+ * Returns: input length
+ */
+ int
+vms_read(char *inbuf, size_t nbytes)
+{
+ int status, function, len;
+ TT_MODE tt_mode;
+ ITEM itmlst[2];
+ static long trm_mask[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
+
+ /* whatever happened earlier we need an iochan here */
+ if (!iochan)
+ tt_mode = get_tty();
+
+ vul_item(&itmlst[0], 0, TRM$_MODIFIERS,
+ (char *)(TRM$M_TM_ESCAPE | TRM$M_TM_NOECHO | TRM$M_TM_NOEDIT |
+ TRM$M_TM_NOFILTR | TRM$M_TM_NORECALL | TRM$M_TM_TRMNOECHO), 0);
+ vul_item(&itmlst[1], sizeof(trm_mask), TRM$_TERM, (char *)&trm_mask, 0);
+
+ function = (IO$_READLBLK | IO$M_EXTEND);
+ memset(inbuf, 0, nbytes);
+
+ while (1)
+ {
+ status = sys$qiow(0, iochan, function, &iosb, 0, 0, inbuf, nbytes - 1,
+ 0, 0, &itmlst, sizeof(itmlst));
+ len = strlen(inbuf);
+ if (len > 0)
+ break;
+ }
+ return len;
+}
+
+/*
+ * vms_wproc() is called for each matching filename by decc$to_vms().
+ * We want to save each match for later retrieval.
+ *
+ * Returns: 1 - continue finding matches
+ * 0 - stop trying to find any further mathces
+ */
+ static int
+vms_wproc(char *name, int val)
+{
+ int i;
+ int nlen;
+ static int vms_match_alloced = 0;
+
+ if (val != DECC$K_FILE) /* Directories and foreing non VMS files are not counting */
+ return 1;
+
+ if (vms_match_num == 0) {
+ /* first time through, setup some things */
+ if (NULL == vms_fmatch) {
+ vms_fmatch = (char_u **)alloc(EXPL_ALLOC_INC * sizeof(char *));
+ if (!vms_fmatch)
+ return 0;
+ vms_match_alloced = EXPL_ALLOC_INC;
+ vms_match_free = EXPL_ALLOC_INC;
+ }
+ else {
+ /* re-use existing space */
+ vms_match_free = vms_match_alloced;
+ }
+ }
+
+ vms_remove_version(name);
+
+ /* convert filename to lowercase */
+ nlen = strlen(name);
+ for (i = 0; i < nlen; i++)
+ name[i] = TOLOWER_ASC(name[i]);
+
+ /* if name already exists, don't add it */
+ for (i = 0; i<vms_match_num; i++) {
+ if (0 == STRCMP((char_u *)name,vms_fmatch[i]))
+ return 1;
+ }
+ if (--vms_match_free == 0) {
+ /* add more space to store matches */
+ vms_match_alloced += EXPL_ALLOC_INC;
+ vms_fmatch = (char_u **)realloc(vms_fmatch,
+ sizeof(char **) * vms_match_alloced);
+ if (!vms_fmatch)
+ return 0;
+ vms_match_free = EXPL_ALLOC_INC;
+ }
+ vms_fmatch[vms_match_num] = vim_strsave((char_u *)name);
+
+ ++vms_match_num;
+ return 1;
+}
+
+/*
+ * mch_expand_wildcards this code does wild-card pattern
+ * matching NOT using the shell
+ *
+ * return OK for success, FAIL for error (you may loose some
+ * memory) and put an error message in *file.
+ *
+ * num_pat number of input patterns
+ * pat array of pointers to input patterns
+ * num_file pointer to number of matched file names
+ * file pointer to array of pointers to matched file names
+ *
+ */
+ int
+mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file, int flags)
+{
+ int i, j = 0, cnt = 0;
+ char *cp;
+ char_u buf[MAXPATHL];
+ int dir;
+ int files_alloced, files_free;
+
+ *num_file = 0; /* default: no files found */
+ files_alloced = EXPL_ALLOC_INC;
+ files_free = EXPL_ALLOC_INC;
+ *file = (char_u **) alloc(sizeof(char_u **) * files_alloced);
+ if (*file == NULL)
+ {
+ *num_file = 0;
+ return FAIL;
+ }
+ for (i = 0; i < num_pat; i++)
+ {
+ /* expand environment var or home dir */
+ if (vim_strchr(pat[i],'$') || vim_strchr(pat[i],'~'))
+ expand_env(pat[i],buf,MAXPATHL);
+ else
+ STRCPY(buf,pat[i]);
+
+ vms_match_num = 0; /* reset collection counter */
+ cnt = decc$to_vms(decc$translate_vms(vms_fixfilename(buf)), vms_wproc, 1, 0);
+ /* allow wild, no dir */
+ if (cnt > 0)
+ cnt = vms_match_num;
+
+ if (cnt < 1)
+ continue;
+
+ for (i = 0; i < cnt; i++)
+ {
+ /* files should exist if expanding interactively */
+ if (!(flags & EW_NOTFOUND) && mch_getperm(vms_fmatch[i]) < 0)
+ continue;
+ /* do not include directories */
+ dir = (mch_isdir(vms_fmatch[i]));
+ if (( dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
+ continue;
+ /* allocate memory for pointers */
+ if (--files_free < 1)
+ {
+ files_alloced += EXPL_ALLOC_INC;
+ *file = (char_u **)realloc(*file,
+ sizeof(char_u **) * files_alloced);
+ if (*file == NULL)
+ {
+ *file = (char_u **)"";
+ *num_file = 0;
+ return(FAIL);
+ }
+ files_free = EXPL_ALLOC_INC;
+ }
+
+ (*file)[*num_file++] = vms_fmatch[i];
+ }
+ }
+ return OK;
+}
+
+ int
+mch_expandpath(garray_T *gap, char_u *path, int flags)
+{
+ int i,cnt = 0;
+ char *cp;
+ vms_match_num = 0;
+
+ cnt = decc$to_vms(decc$translate_vms(vms_fixfilename(path)), vms_wproc, 1, 0);
+ /* allow wild, no dir */
+ if (cnt > 0)
+ cnt = vms_match_num;
+ for (i = 0; i < cnt; i++)
+ {
+ if (mch_getperm(vms_fmatch[i]) >= 0) /* add existing file */
+ addfile(gap, vms_fmatch[i], flags);
+ }
+ return cnt;
+}
+
+/*
+ * attempt to translate a mixed unix-vms file specification to pure vms
+ */
+ static void
+vms_unix_mixed_filespec(char *in, char *out)
+{
+ char *lastcolon;
+ char *end_of_dir;
+ char ch;
+ int len;
+
+ /* copy vms filename portion up to last colon
+ * (node and/or disk)
+ */
+ lastcolon = strrchr(in, ':'); /* find last colon */
+ if (lastcolon != NULL) {
+ len = lastcolon - in + 1;
+ strncpy(out, in, len);
+ out += len;
+ in += len;
+ }
+
+ end_of_dir = NULL; /* default: no directory */
+
+ /* start of directory portion */
+ ch = *in;
+ if ((ch == '[') || (ch == '/') || (ch == '<') ) { /* start of directory(s) ? */
+ ch = '[';
+ SKIP_FOLLOWING_SLASHES(in);
+ } else if (EQN(in, "../", 3)) { /* Unix parent directory? */
+ *out++ = '[';
+ *out++ = '-';
+ end_of_dir = out;
+ ch = '.';
+ in += 2;
+ SKIP_FOLLOWING_SLASHES(in);
+ } else { /* not a special character */
+ while (EQN(in, "./", 2)) { /* Ignore Unix "current dir" */
+ in += 2;
+ SKIP_FOLLOWING_SLASHES(in);
+ }
+ if (strchr(in, '/') == NULL) { /* any more Unix directories ? */
+ strcpy(out, in); /* No - get rest of the spec */
+ return;
+ } else {
+ *out++ = '['; /* Yes, denote a Vms subdirectory */
+ ch = '.';
+ --in;
+ }
+ }
+
+ /* if we get here, there is a directory part of the filename */
+
+ /* initialize output file spec */
+ *out++ = ch;
+ ++in;
+
+ while (*in != '\0') {
+ ch = *in;
+ if ((ch == ']') || (ch == '/') || (ch == '>') ) { /* end of (sub)directory ? */
+ end_of_dir = out;
+ ch = '.';
+ SKIP_FOLLOWING_SLASHES(in);
+ }
+ else if (EQN(in, "../", 3)) { /* Unix parent directory? */
+ *out++ = '-';
+ end_of_dir = out;
+ ch = '.';
+ in += 2;
+ SKIP_FOLLOWING_SLASHES(in);
+ }
+ else {
+ while (EQN(in, "./", 2)) { /* Ignore Unix "current dir" */
+ end_of_dir = out;
+ in += 2;
+ SKIP_FOLLOWING_SLASHES(in);
+ ch = *in;
+ }
+ }
+
+ /* Place next character into output file spec */
+ *out++ = ch;
+ ++in;
+ }
+
+ *out = '\0'; /* Terminate output file spec */
+
+ if (end_of_dir != NULL) /* Terminate directory portion */
+ *end_of_dir = ']';
+}
+
+
+/*
+ * for decc$to_vms in vms_fixfilename
+ */
+ static int
+vms_fspec_proc(char *fil, int val)
+{
+ strcpy(Fspec_Rms,fil);
+ return(1);
+}
+
+/*
+ * change unix and mixed filenames to VMS
+ */
+ void *
+vms_fixfilename(void *instring)
+{
+ static char *buf = NULL;
+ static size_t buflen = 0;
+ size_t len;
+
+ /* get a big-enough buffer */
+ len = strlen(instring) + 1;
+ if (len > buflen)
+ {
+ buflen = len + 128;
+ if (buf)
+ buf = (char *)realloc(buf, buflen);
+ else
+ buf = (char *)calloc(buflen, sizeof(char));
+ }
+
+#ifdef DEBUG
+ char *tmpbuf = NULL;
+ tmpbuf = (char *)calloc(buflen, sizeof(char));
+ strcpy(tmpbuf, instring);
+#endif
+
+ Fspec_Rms = buf; /* for decc$to_vms */
+
+ if ( strchr(instring,'/') == NULL )
+ /* It is already a VMS file spec */
+ strcpy(buf, instring);
+ else if ( strchr(instring,'"') == NULL ){ /* password in the path ? */
+ /* Seems it is a regular file, let guess that it is pure Unix fspec */
+ if ( decc$to_vms(instring, vms_fspec_proc, 0, 0) <= 0 )
+ /* No... it must be mixed */
+ vms_unix_mixed_filespec(instring, buf);
+ }
+ else
+ /* we have a password in the path */
+ /* decc$ functions can not handle */
+ /* this is our only hope to resolv */
+ vms_unix_mixed_filespec(instring, buf);
+
+ return buf;
+}
+/*
+ * Remove version number from file name
+ * we need it in some special cases as:
+ * creating swap file name and writing new file
+ */
+ void
+vms_remove_version(void * fname)
+{
+ char_u *cp;
+ char_u *fp;
+
+ if ((cp = vim_strchr( fname, ';')) != NULL) /* remove version */
+ *cp = '\0';
+ else if ((cp = vim_strrchr( fname, '.')) != NULL )
+ {
+ if ((fp = vim_strrchr( fname, ']')) != NULL ) {;}
+ else if ((fp = vim_strrchr( fname, '>')) != NULL ) {;}
+ else fp = fname;
+
+ while ( *fp != '\0' && fp < cp )
+ if ( *fp++ == '.' )
+ *cp = '\0';
+ }
+ return ;
+}
diff --git a/src/os_vms_conf.h b/src/os_vms_conf.h
new file mode 100644
index 000000000..006460824
--- /dev/null
+++ b/src/os_vms_conf.h
@@ -0,0 +1,185 @@
+/* os_vms_conf.h. Replaces auto/config.h for VMS */
+
+#define CASE_INSENSITIVE_FILENAME /* Open VMS is case insensitive */
+#define SPACE_IN_FILENAME /* There could be space between user and passwd */
+#define FNAME_ILLEGAL "|*#?%" /* Illegal characters in a file name */
+#define BINARY_FILE_IO /* Use binary fileio */
+#define USE_GETCWD
+#define USE_SYSTEM
+
+/* Define when terminfo support found */
+#undef TERMINFO
+
+/* Define when termcap.h contains ospeed */
+/* #define HAVE_OSPEED */
+
+/* Define when termcap.h contains UP, BC and PC */
+/* #define HAVE_UP_BC_PC */
+
+/* Define when termcap.h defines outfuntype */
+/*#define HAVE_OUTFUNTYPE */
+
+/* Define when __DATE__ " " __TIME__ can be used */
+#define HAVE_DATE_TIME
+
+/* Defined to the size of an int */
+#define SIZEOF_INT 4
+
+/* #undef USEBCOPY */
+#define USEMEMMOVE
+/* #undef USEMEMCPY */
+
+/* Define when "man -s 2" is to be used */
+/* #undef USEMAN_S */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef ino_t */
+
+/* Define if you have the nanosleep() function. */
+/* #undef HAVE_NANOSLEEP */
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME
+
+/* Define if you can safely include both <sys/time.h> and <sys/select.h>. */
+/* #undef SYS_SELECT_WITH_SYS_TIME */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define as the command at the end of signal handlers ("" or "return 0;"). */
+#define SIGRETURN return
+
+/* Define if struct sigcontext is present */
+#define HAVE_SIGCONTEXT
+
+/* Define if toupper/tolower only work on lower/upercase characters */
+/* #define BROKEN_TOUPPER */
+
+/* Define if tgetstr() has a second argument that is (char *) */
+/* #undef TGETSTR_CHAR_P */
+
+/* Define if you have the sigset() function. */
+/* #undef HAVE_SIGSET */
+
+/* Define if you have the setpgid() function. */
+/* #undef HAVE_SETPGID */
+
+/* Define if you have the setsid() function. */
+/* #undef HAVE_SETSID */
+
+/* Define if you have the sigset() function. */
+/* #undef HAVE_SIGSET */
+
+#define TGETENT_ZERO_ERR
+#define HAVE_GETCWD
+#define HAVE_STRCSPN
+#define HAVE_STRTOL
+#define HAVE_TGETENT
+#define HAVE_MEMSET
+#define HAVE_MEMCMP
+#define HAVE_STRERROR
+#define HAVE_FCHOWN
+#define HAVE_RENAME
+#define HAVE_QSORT
+#define HAVE_FSYNC
+#define HAVE_GETPWUID
+#define HAVE_GETPWNAM
+#define HAVE_STDLIB_H
+#define HAVE_STRING_H
+#define HAVE_ERRNO_H
+#define HAVE_OPENDIR
+#define HAVE_PUTENV
+#define HAVE_SETENV
+#define HAVE_SETJMP_H
+
+#undef HAVE_DIRENT_H
+#undef HAVE_SYS_NDIR_H
+#undef HAVE_SYS_DIR_H
+#undef HAVE_NDIR_H
+#undef HAVE_SYS_WAIT_H
+#undef HAVE_UNION_WAIT
+#undef HAVE_SYS_SELECT_H
+#undef HAVE_SYS_UTSNAME_H
+#undef HAVE_SYS_SYSTEMINFO_H
+#undef HAVE_TERMCAP_H
+#undef HAVE_SGTTY_H
+#undef HAVE_SYS_IOCTL_H
+#undef HAVE_TERMIO_H
+#undef HAVE_STROPTS_H
+#undef HAVE_SYS_STREAM_H
+#undef HAVE_SYS_PTEM_H
+#undef HAVE_TERMIOS_H
+#undef HAVE_LIBC_H
+#undef HAVE_SYS_STATFS_H
+#undef HAVE_SYS_POLL_H
+#undef HAVE_PWD_H
+#undef HAVE_FCHDIR
+
+/* Hardware specific */
+#ifdef VAX
+#undef HAVE_GETTIMEOFDAY
+#undef HAVE_USLEEP
+#undef HAVE_STRCASECMP
+#undef HAVE_STRINGS_H
+#undef HAVE_SIGSETJMP
+#else
+#define HAVE_GETTIMEOFDAY
+#define HAVE_USLEEP
+#define HAVE_STRCASECMP
+#define HAVE_STRINGS_H
+#define HAVE_SIGSETJMP
+#endif
+
+/* Compiler specific */
+#ifdef VAXC
+#undef HAVE_SELECT
+#undef HAVE_FCNTL_H
+#undef HAVE_UNISTD_H
+#undef HAVE_SYS_TIME_H
+#undef HAVE_LOCALE_H
+#define BROKEN_LOCALE
+#undef HAVE_ICONV_H
+#undef HAVE_ICONV
+#undef DYNAMIC_ICONV
+#undef HAVE_STRFTIME
+#else
+#define HAVE_SELECT
+#define HAVE_FCNTL_H
+#define HAVE_UNISTD_H 1
+#define HAVE_SYS_TIME_H
+#define HAVE_LOCALE_H
+#define BROKEN_LOCALE
+#undef HAVE_ICONV_H
+#undef HAVE_ICONV
+#undef DYNAMIC_ICONV
+#define HAVE_STRFTIME
+#endif
+
+/* GUI support defines */
+#ifdef FEAT_GUI_MOTIF
+#define HAVE_X11
+#define USE_FONTSET
+#undef X_LOCALE
+#endif
diff --git a/src/os_vms_fix.com b/src/os_vms_fix.com
new file mode 100644
index 000000000..8355a352d
--- /dev/null
+++ b/src/os_vms_fix.com
@@ -0,0 +1,276 @@
+$!
+$! OS_VMS_FIX.COM
+$! Copyright (C) 2000, Stephen P. Wall
+$!
+$! Filter files for "#if" line continuations using a '\' and convert
+$! them to use comments for the continuation. Necessary for VAXC - it
+$! doesn't understand the '\'.
+$!
+$! Yes, this is honkin' ugly code, but I deliberately avoided
+$! if ...
+$! then
+$! ....
+$! endif
+$! and call/subroutine/endsubroutine constructs, because I can still
+$! remember when DCL didn't have them, and I wanted this to be as
+$! portable as possible, so... If you want to structure it nicer for
+$! your own use, please feel free to do so. However, please only
+$! distribute it in it's original form.
+$!
+$! I wrote it in DCL for portability and ease of use - a C version
+$! would definitely run faster, but then I'd have to deal with compiler
+$! differences, and users would have to deal with configuring and
+$! building it. With DCL, it runs out-of-the-box.
+$!
+$! Note that if you use this from a VMS system to modify files on a
+$! mounted network drive, f$search() may return only the first matching
+$! file when it tries to resolve wildcards. I have been unable to find
+$! a way around this. Either copy the files to a local disk, or specify
+$! each file individually (Keep in mind if you do this that VMS limits
+$! you to eight parameters, so you'll only be able to filter eight files
+$! at a time).
+$!
+$! Ideas...
+$! - Use 'search filespec "#","if","\"/mat=and' to quickly eliminate
+$! files that definitely don't need filtering. This should speed
+$! things up considerable. Reading and writing every line from every
+$! file takes quite a bit of time...
+$! - Error handling isn't great. Come up with something better....
+$!
+$! E-mail addresses:
+$! Steve Wall hitched97@velnet.com
+$! Zoltan Arpadffy arpadffy@polarhome.com
+$! John W. Hamill jhamill3@ford.com
+$!
+$! Modification History:
+$! 13Jul00 SWall Initial Version
+$! 14Jul00 ZArpadffy Display usage
+$! 06Mar01 JHamill Ctrl-M problem fix
+$!
+$! If no parameters, or "-h" for a parameter, print usage and exit
+$
+$ all = "''p1'''p2'''p3'''p4'''p5'''p6'''p7'''p8'"
+$ if (all .nes. "") .and. (p1 .nes. "-h") .and. (p1 .nes. "-H") then goto startup
+$
+$ write sys$output "OS_VMS_FIX - DECC->VAXC pre-processor directive convert script"
+$ write sys$output "Usage: @OS_VMS_FIX <filename_1> <filename_2> <...>"
+$ write sys$output " @OS_VMS_FIX <filename with wildcard> <...>"
+$ write sys$output ""
+$ write sys$output "Example: @OS_VMS_FIX *.c *.h [.proto]*.pro"
+$ write sys$output "Please note, you can define up to 8 parameters."
+$ write sys$output ""
+$ exit
+$
+$! Create an FDL file to convert VFC format files to Stream_LF.
+$! VMS OPEN/WRITE command creates VFC files. When VFC files are read
+$! out under unix, they appear to have binary data embedded in them.
+$! To be friendly, we'll convert them to Stream_LF, which reads just
+$! file on unix.
+$
+$startup:
+$ on control_y then goto stopfdl
+$ open/write fdl []convert.fdl
+$ write fdl "SYSTEM"
+$ write fdl " SOURCE VAX/VMS"
+$ write fdl "FILE"
+$ write fdl " ORGANIZATION SEQUENTIAL"
+$ write fdl "RECORD"
+$ write fdl " BLOCK_SPAN YES"
+$ write fdl " CARRIAGE_CONTROL CARRIAGE_RETURN"
+$ write fdl " FORMAT STREAM"
+$ write fdl " SIZE 0"
+$ close fdl
+$ on control_y then goto endparamloop
+$
+$! Some symbols for use later on...
+$
+$ spc = ""
+$ spc[0,8] = 32
+$ tab = ""
+$ tab[0,8] = 9
+$
+$! Scan all positional arguments, do wildcard expansion, and call the
+$! filter routine on each resulting filename.
+$
+$ cnt = 0
+$paramloop:
+$ cnt = cnt + 1
+$
+$! VMS only allows command line parameters P1 - P8, so stop after
+$! processing 8 arguments.
+$
+$ if cnt .eq. 9 then goto endparamloop
+$
+$! Skip any empty parameter.
+$
+$ if P'cnt' .eqs. "" then goto paramloop
+$
+$! Got a parameter - do wildcard expansion.
+$
+$ arg = f$parse(P'cnt')
+$ write sys$output "Parsing ''arg'..."
+$ last = ""
+$fileloop:
+$ file = f$search(arg, 1)
+$
+$! f$search() returns "" after the last of multiple matches.
+$
+$ if file .eqs. "" then goto endfileloop
+$
+$! Strip the version number.
+$
+$ file = f$parse(file,,,"DEVICE") + f$parse(file,,,"DIRECTORY") + -
+ f$parse(file,,,"NAME") + f$parse(file,,,"TYPE")
+$
+$! f$search() returns the same filename over and over if there are no
+$! wildcards in it.
+$
+$ if file .eqs. last then goto endfileloop
+$ last = file
+$
+$! Got a valid file - filter it.
+$
+$ gosub filter
+$
+$! Reset our error handling.
+$
+$ on control_y then goto endparamloop
+$
+$! See if there's another matching filename.
+$
+$ goto fileloop
+$endfileloop:
+$
+$! Check for another parameter.
+$
+$ goto paramloop
+$endparamloop:
+$
+$! Finished - delete the FDL file.
+$
+$ delete []convert.fdl;
+$
+$! So long, and thanks for all the fish...
+$
+$ exit
+$
+$
+$! User aborted with Control-Y during creation of FDL file.
+$! Close the file, delete it, and exit with an error status.
+$
+$stopfdl:
+$ close fdl
+$ delete []convert.fdl;
+$ exit %X10000000
+$
+$
+$! Filter a file.
+$
+$filter:
+$ write sys$output "Filtering ''file'..."
+$
+$! Get a temporary filename from the subroutine parameter.
+$
+$ tmp = f$parse(file,,,"DEVICE") + f$parse(file,,,"DIRECTORY") + -
+ "tmp_" + f$parse(file,,,"NAME") + f$parse(file,,,"TYPE")
+$ on control_y then goto aborted
+$ open /read input 'file'
+$ open /write output 'tmp'
+$ changed = 0
+$readloop:
+$ read/end_of_file=endreadloop/error=readlooperror input line
+$
+$! Get the first 3 non-blank character on the line.
+$
+$ start = f$extract(0,3,f$edit(line,"COLLAPSE,LOWERCASE"))
+$
+$! If the line doesn't start with some form of "#if", just write it to
+$! the temp file.
+$
+$ if start .nes. "#if" then goto writeit
+$chkbkslsh:
+$
+$! See if the line ends in a backslash. If not, write it to the temp file.
+$
+$ if f$extract(f$length(line)-1,1,line) .nes. "\" then goto writeit
+$
+$! Ok, got a line that needs to be modified. Mark this file as changed,
+$! then replace the backslash at the end with the beginning of a comment
+$! (/*), and write it to the temp file.
+$
+$ changed = 1
+$ line = f$extract(0,f$length(line)-1,line) + "/*"
+$ write/symbol output line
+$
+$! Get another line from the input.
+$
+$ read/end_of_file=endreadloop/error=readlooperror input line
+$
+$! Grab all the blank space from the beginning of the line.
+$
+$ spaces = ""
+$spaceloop:
+$ if (f$extract(0,1,line) .nes. spc) .and. (f$extract(0,1,line) .nes. tab) -
+ then goto endspaceloop
+$ spaces = spaces + f$extract(0,1,line)
+$ line = f$extract(1,f$length(line)-1,line)
+$ goto spaceloop
+$endspaceloop:
+$
+$! Stick an end-comment (*/) after the leading blanks, then go back and
+$! check for a trailing backslash again, to catch code that continues
+$! across multiple lines.
+$
+$ line = spaces + "*/ " + line
+$ goto chkbkslsh
+$
+$! Write the current line, (will either be an untouched line, or the
+$! last line of a continuation) to the temp file, and go back to look
+$! for more input.
+$!
+$writeit:
+$ write/symbol output line
+$ goto readloop
+$
+$! Hit EOF. Close the input & output, and if the file was marked as
+$! changed, convert it from VMS VFC format, to the more common Stream_LF
+$! format, so it doesn't show up full of garbage if someone tries to
+$! edit it on another OS.
+$!
+$endreadloop:
+$ close input
+$ close output
+$ if changed .eq. 0 then goto nocopy
+$ convert 'tmp' 'file' /fdl=[]convert.fdl
+$nocopy:
+$ delete 'tmp';
+$
+$! Exit this subroutine.
+$
+$ goto endfunc
+$
+$! Got a read error. Say so, and trash the temp file.
+$
+$readlooperror:
+$ write sys$error "Error processing file ''file'"
+$ goto errorend
+$
+$! Got an interrupt. Say so, and trash the temp file.
+$
+$aborted:
+$ write sys$error "Aborted while processing file ''file'"
+$
+$! Common code for read errors and interrupts.
+$
+$errorend:
+$ close input
+$ close output
+$ delete 'tmp';
+$ return %X10000000
+$
+$! End of filter subroutine.
+$
+$endfunc:
+$ return
+$
+$! EOF
diff --git a/src/os_vms_mms.c b/src/os_vms_mms.c
new file mode 100644
index 000000000..d653860be
--- /dev/null
+++ b/src/os_vms_mms.c
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unixio.h>
+#include "vim.h"
+int main(int argc, char *argv[])
+{
+ FILE *fpi, *fpo;
+ char cmd[132], buf[BUFSIZ], *argp, *error_file, target[132], *mms;
+ int err = 0, err_line = 0;
+
+ mms = "mms";
+ argc--;
+ argv++;
+ while (argc-- > 0)
+ {
+ argp = *argv++;
+ if (*argp == '-')
+ {
+ switch (*++argp)
+ {
+ case 'm':
+ mms = ++argp;
+ break;
+ case 'e':
+ if (!*(error_file = ++argp))
+ {
+ error_file = *argv++;
+ argc--;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ if (*target)
+ strcat(target, " ");
+ strcat(target, argp);
+ }
+ }
+ sprintf(cmd, "%s/output=tmp:errors.vim_tmp %s", mms, target);
+ system(cmd);
+ fpi = fopen("tmp:errors.vim_tmp", "r");
+ fpo = fopen(error_file, "w");
+ while (fgets(buf, BUFSIZ, fpi))
+ {
+ if (!memcmp(buf, "%CC-", 4))
+ {
+ err_line++;
+ buf[strlen(buf)-1] = '\0';
+ err++;
+ }
+ else
+ {
+ if (err_line)
+ {
+ if (strstr(buf, _("At line")))
+ {
+ err_line = 0;
+ fprintf(fpo, "@");
+ }
+ else
+ buf[strlen(buf)-1] = '\0';
+ }
+ }
+ fprintf(fpo, "%s", buf);
+ }
+ fclose(fpi);
+ fclose(fpo);
+ while (!delete("tmp:errors.vim_tmp"))
+ /*nop*/;
+ exit(err ? 44 : 1);
+ return(0);
+}
diff --git a/src/os_w32dll.c b/src/os_w32dll.c
new file mode 100644
index 000000000..9cfec1aa5
--- /dev/null
+++ b/src/os_w32dll.c
@@ -0,0 +1,24 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI support by Robert Webb
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * Windows GUI: main program (DLL) entry point:
+ *
+ * Ron Aaron <ronaharon@yahoo.com> wrote this and the DLL support code.
+ */
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ return TRUE;
+}
+
diff --git a/src/os_w32exe.c b/src/os_w32exe.c
new file mode 100644
index 000000000..e37873b76
--- /dev/null
+++ b/src/os_w32exe.c
@@ -0,0 +1,136 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI support by Robert Webb
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * Windows GUI: main program (EXE) entry point:
+ *
+ * Ron Aaron <ronaharon@yahoo.com> wrote this and the DLL support code.
+ */
+#include "vim.h"
+
+#ifdef __MINGW32__
+# ifndef _cdecl
+# define _cdecl
+# endif
+#endif
+
+/* cproto doesn't create a prototype for main() */
+int _cdecl
+#if defined(FEAT_GUI_W32)
+VimMain
+#else
+ main
+#endif
+ __ARGS((int argc, char **argv));
+int (_cdecl *pmain)(int, char **);
+
+#ifndef PROTO
+#ifdef FEAT_GUI
+#ifndef VIMDLL
+void _cdecl SaveInst(HINSTANCE hInst);
+#endif
+void (_cdecl *pSaveInst)(HINSTANCE);
+#endif
+
+ int WINAPI
+WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInst,
+ LPSTR lpszCmdLine,
+ int nCmdShow)
+{
+ int argc;
+ char **argv;
+ char *tofree;
+ char prog[256];
+#ifdef VIMDLL
+ char *p;
+ HANDLE hLib;
+#endif
+
+ /* Ron: added full path name so that the $VIM variable will get set to our
+ * startup path (so the .vimrc file can be found w/o a VIM env. var.) */
+ GetModuleFileName(NULL, prog, 255);
+
+ /* Separate the command line into arguments. */
+ argc = get_cmd_args(prog, (char *)lpszCmdLine, &argv, &tofree);
+ if (argc == 0)
+ {
+ MessageBox(0, _("Could not allocate memory for command line."),
+ _("VIM Error"), 0);
+ return 0;
+ }
+
+#ifdef DYNAMIC_GETTEXT
+ /* Initialize gettext library */
+ dyn_libintl_init(NULL);
+#endif
+
+#ifdef VIMDLL
+ // LoadLibrary - get name of dll to load in here:
+ p = strrchr(prog, '\\');
+ if (p != NULL)
+ {
+# ifdef DEBUG
+ strcpy(p+1, "vim32d.dll");
+# else
+ strcpy(p+1, "vim32.dll");
+# endif
+ }
+ hLib = LoadLibrary(prog);
+ if (hLib == NULL)
+ {
+ MessageBox(0, _("Could not load vim32.dll!"), _("VIM Error"), 0);
+ goto errout;
+ }
+ // fix up the function pointers
+# ifdef FEAT_GUI
+ pSaveInst = GetProcAddress(hLib, (LPCSTR)2);
+# endif
+ pmain = GetProcAddress(hLib, (LPCSTR)1);
+ if (pmain == NULL)
+ {
+ MessageBox(0, _("Could not fix up function pointers to the DLL!"),
+ _("VIM Error"),0);
+ goto errout;
+ }
+#else
+# ifdef FEAT_GUI
+ pSaveInst = SaveInst;
+# endif
+ pmain =
+# if defined(FEAT_GUI_W32)
+ //&& defined(__MINGW32__)
+ VimMain
+# else
+ main
+# endif
+ ;
+#endif
+#ifdef FEAT_GUI
+ pSaveInst(
+#ifdef __MINGW32__
+ GetModuleHandle(NULL)
+#else
+ hInstance
+#endif
+ );
+#endif
+ pmain(argc, argv);
+
+#ifdef VIMDLL
+ FreeLibrary(hLib);
+errout:
+#endif
+ free(argv);
+ free(tofree);
+
+ return 0;
+}
+#endif
diff --git a/src/os_win16.c b/src/os_win16.c
new file mode 100644
index 000000000..1b1ccd700
--- /dev/null
+++ b/src/os_win16.c
@@ -0,0 +1,424 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * os_win16.c
+ *
+ * Win16 (Windows 3.1x) system-dependent routines.
+ * Carved brutally from os_win32.c by Vince Negri <vn@aslnet.co.uk>
+ */
+#ifdef __BORLANDC__
+# pragma warn -par
+# pragma warn -ucp
+# pragma warn -use
+# pragma warn -aus
+# pragma warn -obs
+#endif
+
+#include <io.h>
+#include "vim.h"
+
+#include <fcntl.h>
+#include <dos.h>
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <signal.h>
+#include <limits.h>
+#include <process.h>
+
+#undef chdir
+#include <direct.h>
+#include <shellapi.h> /* required for FindExecutable() */
+
+
+/* Record all output and all keyboard & mouse input */
+/* #define MCH_WRITE_DUMP */
+
+#ifdef MCH_WRITE_DUMP
+FILE* fdDump = NULL;
+#endif
+
+
+/*
+ * When generating prototypes for Win32 on Unix, these lines make the syntax
+ * errors disappear. They do not need to be correct.
+ */
+#ifdef PROTO
+typedef int HANDLE;
+typedef int SMALL_RECT;
+typedef int COORD;
+typedef int SHORT;
+typedef int WORD;
+typedef int DWORD;
+typedef int BOOL;
+typedef int LPSTR;
+typedef int LPTSTR;
+typedef int KEY_EVENT_RECORD;
+typedef int MOUSE_EVENT_RECORD;
+# define WINAPI
+typedef int CONSOLE_CURSOR_INFO;
+typedef char * LPCSTR;
+# define WINBASEAPI
+typedef int INPUT_RECORD;
+# define _cdecl
+#endif
+
+#ifdef __BORLANDC__
+/* being a more ANSI compliant compiler, BorlandC doesn't define _stricoll:
+ * but it does in BC 5.02! */
+# if __BORLANDC__ < 0x502
+int _stricoll(char *a, char *b);
+# endif
+#endif
+
+/* cproto doesn't create a prototype for main() */
+int _cdecl
+VimMain
+__ARGS((int argc, char **argv));
+int (_cdecl *pmain)(int, char **);
+
+#ifndef PROTO
+void _cdecl SaveInst(HINSTANCE hInst);
+void (_cdecl *pSaveInst)(HINSTANCE);
+
+int WINAPI
+WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInst,
+ LPSTR lpszCmdLine,
+ int nCmdShow)
+{
+ int argc;
+ char **argv;
+ char *tofree;
+ char prog[256];
+
+ /*
+ * Ron: added full path name so that the $VIM variable will get set to our
+ * startup path (so the .vimrc file can be found w/o a VIM env. var.)
+ * Remove the ".exe" extension, and find the 1st non-space.
+ */
+ GetModuleFileName(hInstance, prog, 255);
+ if (*prog != NUL)
+ exe_name = FullName_save((char_u *)prog, FALSE);
+
+ /* Separate the command line into arguments. */
+ argc = get_cmd_args(prog, (char *)lpszCmdLine, &argv, &tofree);
+ if (argc == 0)
+ {
+ /* Error message? */
+ return 0;
+ }
+
+ pSaveInst = SaveInst;
+ pmain = VimMain;
+ pSaveInst(hInstance);
+ pmain(argc, argv);
+
+ free(argv);
+ free(tofree);
+
+ return 0;
+}
+#endif
+
+
+
+
+
+
+#ifdef FEAT_MOUSE
+
+/*
+ * For the GUI the mouse handling is in gui_w32.c.
+ */
+ void
+mch_setmouse(
+ int on)
+{
+}
+#endif /* FEAT_MOUSE */
+
+
+
+/*
+ * GUI version of mch_init().
+ */
+ void
+mch_init()
+{
+ extern int _fmode;
+
+
+ /* Let critical errors result in a failure, not in a dialog box. Required
+ * for the timestamp test to work on removed floppies. */
+ SetErrorMode(SEM_FAILCRITICALERRORS);
+
+ _fmode = O_BINARY; /* we do our own CR-LF translation */
+
+ /* Specify window size. Is there a place to get the default from? */
+ Rows = 25;
+ Columns = 80;
+
+
+ set_option_value((char_u *)"grepprg", 0, (char_u *)"grep -n", 0);
+
+#ifdef FEAT_CLIPBOARD
+ clip_init(TRUE);
+
+ /*
+ * Vim's own clipboard format recognises whether the text is char, line,
+ * or rectangular block. Only useful for copying between two Vims.
+ * "VimClipboard" was used for previous versions, using the first
+ * character to specify MCHAR, MLINE or MBLOCK.
+ */
+ clip_star.format = RegisterClipboardFormat("VimClipboard2");
+ clip_star.format_raw = RegisterClipboardFormat("VimRawBytes");
+#endif
+}
+
+
+
+/*
+ * Do we have an interactive window?
+ */
+ int
+mch_check_win(
+ int argc,
+ char **argv)
+{
+ int i;
+
+ return OK; /* GUI always has a tty */
+}
+
+
+/*
+ * return process ID
+ */
+ long
+mch_get_pid()
+{
+ return (long)GetCurrentTask();
+}
+
+
+/*
+ * Specialised version of system().
+ * This version proceeds as follows:
+ * 1. Start the program with WinExec
+ * 2. Wait for the module use count of the program to go to 0
+ * (This is the best way of detecting the program has finished)
+ */
+
+ static int
+mch_system(char *cmd, int options)
+{
+ DWORD ret = 0;
+ UINT wShowWindow;
+ UINT h_module;
+ MSG msg;
+ BOOL again = TRUE;
+
+ /*
+ * It's nicer to run a filter command in a minimized window, but in
+ */
+ if (options & SHELL_DOOUT)
+ wShowWindow = SW_SHOWMINIMIZED;
+ else
+ wShowWindow = SW_SHOWNORMAL;
+
+ /* Now, run the command */
+ h_module = WinExec((LPCSTR)cmd, wShowWindow);
+
+ if (h_module < 32)
+ {
+ /*error*/
+ ret = -h_module;
+ }
+ else
+ {
+ /* Wait for the command to terminate before continuing */
+ while (GetModuleUsage((HINSTANCE)h_module) > 0 && again )
+ {
+ while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) && again )
+ {
+ if(msg.message == WM_QUIT)
+
+ {
+ PostQuitMessage(msg.wParam);
+ again = FALSE;
+ }
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Either execute a command by calling the shell or start a new shell
+ */
+ int
+mch_call_shell(
+ char_u *cmd,
+ int options) /* SHELL_, see vim.h */
+{
+ int x;
+ int tmode = cur_tmode;
+
+ out_flush();
+
+
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ {
+ fprintf(fdDump, "mch_call_shell(\"%s\", %d)\n", cmd, options);
+ fflush(fdDump);
+ }
+#endif
+
+ /*
+ * Catch all deadly signals while running the external command, because a
+ * CTRL-C, Ctrl-Break or illegal instruction might otherwise kill us.
+ */
+ signal(SIGINT, SIG_IGN);
+ signal(SIGILL, SIG_IGN);
+ signal(SIGFPE, SIG_IGN);
+ signal(SIGSEGV, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+ signal(SIGABRT, SIG_IGN);
+
+ if (options & SHELL_COOKED)
+ settmode(TMODE_COOK); /* set to normal mode */
+
+ if (cmd == NULL)
+ {
+ x = mch_system(p_sh, options);
+ }
+ else
+ {
+ /* we use "command" or "cmd" to start the shell; slow but easy */
+ char_u *newcmd;
+
+ newcmd = lalloc(
+ STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10, TRUE);
+ if (newcmd != NULL)
+ {
+ if (STRNICMP(cmd, "start ", 6) == 0)
+ {
+ sprintf((char *)newcmd, "%s\0", cmd+6);
+ if (WinExec((LPCSTR)newcmd, SW_SHOWNORMAL) > 31)
+ x = 0;
+ else
+ x = -1;
+ }
+ else
+ {
+ sprintf((char *)newcmd, "%s%s %s %s",
+ "",
+ p_sh,
+ p_shcf,
+ cmd);
+ x = mch_system((char *)newcmd, options);
+ }
+ vim_free(newcmd);
+ }
+ }
+
+ if (tmode == TMODE_RAW)
+ settmode(TMODE_RAW); /* set to raw mode */
+
+ if (x && !(options & SHELL_SILENT) && !emsg_silent)
+ {
+ smsg(_("shell returned %d"), x);
+ msg_putchar('\n');
+ }
+#ifdef FEAT_TITLE
+ resettitle();
+#endif
+
+ signal(SIGINT, SIG_DFL);
+ signal(SIGILL, SIG_DFL);
+ signal(SIGFPE, SIG_DFL);
+ signal(SIGSEGV, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGABRT, SIG_DFL);
+
+
+ return x;
+}
+
+
+/*
+ * Delay for half a second.
+ */
+ void
+mch_delay(
+ long msec,
+ int ignoreinput)
+{
+#ifdef MUST_FIX
+ Sleep((int)msec); /* never wait for input */
+#endif
+}
+
+
+/*
+ * check for an "interrupt signal": CTRL-break or CTRL-C
+ */
+ void
+mch_breakcheck()
+{
+ /* never used */
+}
+
+
+/*
+ * How much memory is available?
+ */
+ long_u
+mch_avail_mem(
+ int special)
+{
+ return GetFreeSpace(0);
+}
+
+
+/*
+ * Like rename(), returns 0 upon success, non-zero upon failure.
+ * Should probably set errno appropriately when errors occur.
+ */
+ int
+mch_rename(
+ const char *pszOldFile,
+ const char *pszNewFile)
+{
+
+ /*
+ * No need to play tricks, this isn't rubbish like Windows 95 <g>
+ */
+ return rename(pszOldFile, pszNewFile);
+
+}
+
+/*
+ * Get the default shell for the current hardware platform
+ */
+ char*
+default_shell()
+{
+ char* psz = NULL;
+
+ psz = "command.com";
+
+ return psz;
+}
diff --git a/src/os_win16.h b/src/os_win16.h
new file mode 100644
index 000000000..93b5891f6
--- /dev/null
+++ b/src/os_win16.h
@@ -0,0 +1,142 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * Win16 (Windows 3.1x) machine-dependent things.
+ */
+
+#include "os_dos.h" /* common MS-DOS and Windows stuff */
+
+#define BINARY_FILE_IO
+#define USE_EXE_NAME /* use argv[0] for $VIM */
+#define NO_COOKED_INPUT /* mch_inchar() doesn't return whole lines */
+#define SYNC_DUP_CLOSE /* sync() a file with dup() and close() */
+#define USE_TERM_CONSOLE
+#define HAVE_STRING_H
+#define HAVE_STRCSPN
+#define HAVE_STRICMP
+#define HAVE_STRNICMP
+#define HAVE_STRFTIME /* guessed */
+#define HAVE_MEMSET
+#define USE_TMPNAM /* use tmpnam() instead of mktemp() */
+#define HAVE_LOCALE_H
+#define HAVE_FCNTL_H
+#define HAVE_QSORT
+#define HAVE_ST_MODE /* have stat.st_mode */
+//#define USE_FNAME_CASE /* adjust case of file names */
+#ifndef FEAT_CLIPBOARD
+# define FEAT_CLIPBOARD /* include clipboard support */
+#endif
+#if defined(__DATE__) && defined(__TIME__)
+# define HAVE_DATE_TIME
+#endif
+#define HAVE_AVAIL_MEM
+
+#define SHORT_FNAME /* always 8.3 file name */
+
+#define SMALL_MALLOC /* 16 bit storage allocation */
+
+#ifdef __BORLANDC__
+# define HAVE_PUTENV /* at least Bcc 5.2 has it */
+#endif
+
+#ifdef FEAT_GUI_W16
+# define NO_CONSOLE /* don't included console-only code */
+#endif
+
+/* toupper() is not really broken, but it's very slow. Probably because of
+ * using unicde characters on Windows NT */
+#define BROKEN_TOUPPER
+
+#define FNAME_ILLEGAL "\"*?><|" /* illegal characters in a file name */
+
+#ifndef SIZEOF_INT
+# define SIZEOF_INT 2
+#endif
+
+typedef long off_t;
+
+#include <stdlib.h>
+#include <time.h>
+#include <dos.h>
+#include <dir.h>
+
+#ifndef STRICT
+# define STRICT
+#endif
+#ifndef COBJMACROS
+# define COBJMACROS /* For OLE: Enable "friendlier" access to objects */
+#endif
+#include <windows.h>
+
+/*
+ * plenty of memory, use large buffers
+ */
+#define CMDBUFFSIZE 1024 /* size of the command processing buffer */
+
+
+#define BASENAMELEN (MAXPATHL-5) /* length of base of file name */
+
+#ifndef DFLT_MAXMEM
+# define DFLT_MAXMEM (256) /* use up to 256K for a buffer*/
+#endif
+
+#ifndef DFLT_MAXMEMTOT
+# define DFLT_MAXMEMTOT (5*1024) /* use up to 5 Mbyte for Vim */
+#endif
+
+/*
+ * Some simple debugging macros that look and behave a lot like their
+ * namesakes in MFC.
+ */
+
+#ifdef _DEBUG
+
+# if defined(_MSC_VER) && (_MSC_VER >= 1000)
+ /* Use the new debugging tools in Visual C++ 4.x */
+# include <crtdbg.h>
+# define ASSERT(f) _ASSERT(f)
+# else
+# include <assert.h>
+# define ASSERT(f) assert(f)
+# endif
+
+# define VERIFY(f) ASSERT(f)
+# define DEBUG_ONLY(f) (f)
+# define TRACE Trace
+# define TRACE0(sz) Trace(_T("%s"), _T(sz))
+# define TRACE1(sz, p1) Trace(_T(sz), p1)
+# define TRACE2(sz, p1, p2) Trace(_T(sz), p1, p2)
+# define TRACE3(sz, p1, p2, p3) Trace(_T(sz), p1, p2, p3)
+
+/* In debug version, writes trace messages to debug stream */
+void __cdecl
+Trace(char *pszFormat, ...);
+
+#else /* !_DEBUG */
+
+ /* These macros should all compile away to nothing */
+# define ASSERT(f) ((void)0)
+# define VERIFY(f) ((void)f)
+# define DEBUG_ONLY(f) ((void)0)
+# define TRACE 1 ? (void)0 : printf
+# define TRACE0(sz)
+# define TRACE1(sz, p1)
+# define TRACE2(sz, p1, p2)
+# define TRACE3(sz, p1, p2, p3)
+
+#endif /* !_DEBUG */
+
+
+#define ASSERT_POINTER(p, type) \
+ ASSERT(((p) != NULL) && IsValidAddress((p), sizeof(type), FALSE))
+
+#define ASSERT_NULL_OR_POINTER(p, type) \
+ ASSERT(((p) == NULL) || IsValidAddress((p), sizeof(type), FALSE))
+
+#define mch_setenv(name, val, x) setenv(name, val, x)
diff --git a/src/os_win32.c b/src/os_win32.c
new file mode 100644
index 000000000..74b896032
--- /dev/null
+++ b/src/os_win32.c
@@ -0,0 +1,4790 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * os_win32.c
+ *
+ * Used for both the console version and the Win32 GUI. A lot of code is for
+ * the console version only, so there is a lot of "#ifndef FEAT_GUI_W32".
+ *
+ * Win32 (Windows NT and Windows 95) system-dependent routines.
+ * Portions lifted from the Win32 SDK samples, the MSDOS-dependent code,
+ * NetHack 3.1.3, GNU Emacs 19.30, and Vile 5.5.
+ *
+ * George V. Reilly <george@reilly.org> wrote most of this.
+ * Roger Knobbe <rogerk@wonderware.com> did the initial port of Vim 3.0.
+ */
+
+#include <io.h>
+#include "vim.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#include <sys/types.h>
+#include <errno.h>
+#include <signal.h>
+#include <limits.h>
+#include <process.h>
+
+#undef chdir
+#ifdef __GNUC__
+# ifndef __MINGW32__
+# include <dirent.h>
+# endif
+#else
+# include <direct.h>
+#endif
+
+#if defined(FEAT_TITLE) && !defined(FEAT_GUI_W32)
+# include <shellapi.h>
+#endif
+
+#ifdef __MINGW32__
+# ifndef FROM_LEFT_1ST_BUTTON_PRESSED
+# define FROM_LEFT_1ST_BUTTON_PRESSED 0x0001
+# endif
+# ifndef RIGHTMOST_BUTTON_PRESSED
+# define RIGHTMOST_BUTTON_PRESSED 0x0002
+# endif
+# ifndef FROM_LEFT_2ND_BUTTON_PRESSED
+# define FROM_LEFT_2ND_BUTTON_PRESSED 0x0004
+# endif
+# ifndef FROM_LEFT_3RD_BUTTON_PRESSED
+# define FROM_LEFT_3RD_BUTTON_PRESSED 0x0008
+# endif
+# ifndef FROM_LEFT_4TH_BUTTON_PRESSED
+# define FROM_LEFT_4TH_BUTTON_PRESSED 0x0010
+# endif
+
+/*
+ * EventFlags
+ */
+# ifndef MOUSE_MOVED
+# define MOUSE_MOVED 0x0001
+# endif
+# ifndef DOUBLE_CLICK
+# define DOUBLE_CLICK 0x0002
+# endif
+#endif
+
+/* Record all output and all keyboard & mouse input */
+/* #define MCH_WRITE_DUMP */
+
+#ifdef MCH_WRITE_DUMP
+FILE* fdDump = NULL;
+#endif
+
+/*
+ * When generating prototypes for Win32 on Unix, these lines make the syntax
+ * errors disappear. They do not need to be correct.
+ */
+#ifdef PROTO
+#define WINAPI
+#define WINBASEAPI
+typedef char * LPCSTR;
+typedef int ACCESS_MASK;
+typedef int BOOL;
+typedef int COLORREF;
+typedef int CONSOLE_CURSOR_INFO;
+typedef int COORD;
+typedef int DWORD;
+typedef int HANDLE;
+typedef int HDC;
+typedef int HFONT;
+typedef int HICON;
+typedef int HINSTANCE;
+typedef int HWND;
+typedef int INPUT_RECORD;
+typedef int KEY_EVENT_RECORD;
+typedef int LOGFONT;
+typedef int LPBOOL;
+typedef int LPCTSTR;
+typedef int LPDWORD;
+typedef int LPSTR;
+typedef int LPTSTR;
+typedef int LPVOID;
+typedef int MOUSE_EVENT_RECORD;
+typedef int PACL;
+typedef int PDWORD;
+typedef int PHANDLE;
+typedef int PRINTDLG;
+typedef int PSECURITY_DESCRIPTOR;
+typedef int PSID;
+typedef int SECURITY_INFORMATION;
+typedef int SHORT;
+typedef int SMALL_RECT;
+typedef int TEXTMETRIC;
+typedef int TOKEN_INFORMATION_CLASS;
+typedef int TRUSTEE;
+typedef int WORD;
+typedef int WCHAR;
+typedef void VOID;
+#endif
+
+#ifndef FEAT_GUI_W32
+/* Undocumented API in kernel32.dll needed to work around dead key bug in
+ * console-mode applications in NT 4.0. If you switch keyboard layouts
+ * in a console app to a layout that includes dead keys and then hit a
+ * dead key, a call to ToAscii will trash the stack. My thanks to Ian James
+ * and Michael Dietrich for helping me figure out this workaround.
+ */
+
+/* WINBASEAPI BOOL WINAPI GetConsoleKeyboardLayoutNameA(LPSTR); */
+#ifndef WINBASEAPI
+# define WINBASEAPI __stdcall
+#endif
+#if defined(__BORLANDC__)
+typedef BOOL (__stdcall *PFNGCKLN)(LPSTR);
+#else
+typedef WINBASEAPI BOOL (WINAPI *PFNGCKLN)(LPSTR);
+#endif
+PFNGCKLN s_pfnGetConsoleKeyboardLayoutName = NULL;
+#endif
+
+#if defined(__BORLANDC__)
+/* Strangely Borland uses a non-standard name. */
+# define wcsicmp(a, b) wcscmpi((a), (b))
+#endif
+
+#ifndef FEAT_GUI_W32
+/* Win32 Console handles for input and output */
+static HANDLE g_hConIn = INVALID_HANDLE_VALUE;
+static HANDLE g_hConOut = INVALID_HANDLE_VALUE;
+
+/* Win32 Screen buffer,coordinate,console I/O information */
+static SMALL_RECT g_srScrollRegion;
+static COORD g_coord; /* 0-based, but external coords are 1-based */
+
+/* The attribute of the screen when the editor was started */
+static WORD g_attrDefault = 7; /* lightgray text on black background */
+static WORD g_attrCurrent;
+
+static int g_fCBrkPressed = FALSE; /* set by ctrl-break interrupt */
+static int g_fCtrlCPressed = FALSE; /* set when ctrl-C or ctrl-break detected */
+static int g_fForceExit = FALSE; /* set when forcefully exiting */
+
+static void termcap_mode_start(void);
+static void termcap_mode_end(void);
+static void clear_chars(COORD coord, DWORD n);
+static void clear_screen(void);
+static void clear_to_end_of_display(void);
+static void clear_to_end_of_line(void);
+static void scroll(unsigned cLines);
+static void set_scroll_region(unsigned left, unsigned top,
+ unsigned right, unsigned bottom);
+static void insert_lines(unsigned cLines);
+static void delete_lines(unsigned cLines);
+static void gotoxy(unsigned x, unsigned y);
+static void normvideo(void);
+static void textattr(WORD wAttr);
+static void textcolor(WORD wAttr);
+static void textbackground(WORD wAttr);
+static void standout(void);
+static void standend(void);
+static void visual_bell(void);
+static void cursor_visible(BOOL fVisible);
+static BOOL write_chars(LPCSTR pchBuf, DWORD cchToWrite);
+static char_u tgetch(int *pmodifiers, char_u *pch2);
+static void create_conin(void);
+static int s_cursor_visible = TRUE;
+static int did_create_conin = FALSE;
+#else
+static int s_dont_use_vimrun = TRUE;
+static int need_vimrun_warning = FALSE;
+static char *vimrun_path = "vimrun ";
+#endif
+
+#ifndef FEAT_GUI_W32
+static int suppress_winsize = 1; /* don't fiddle with console */
+#endif
+
+ static void
+get_exe_name(void)
+{
+ char temp[256];
+
+ if (exe_name == NULL)
+ {
+ /* store the name of the executable, may be used for $VIM */
+ GetModuleFileName(NULL, temp, 255);
+ if (*temp != NUL)
+ exe_name = FullName_save((char_u *)temp, FALSE);
+ }
+}
+
+#if defined(DYNAMIC_GETTEXT) || defined(PROTO)
+# ifndef GETTEXT_DLL
+# define GETTEXT_DLL "libintl.dll"
+# endif
+/* Dummy funcitons */
+static char* null_libintl_gettext(const char *);
+static char* null_libintl_textdomain(const char *);
+static char* null_libintl_bindtextdomain(const char *, const char *);
+
+static HINSTANCE hLibintlDLL = 0;
+char* (*dyn_libintl_gettext)(const char *) = null_libintl_gettext;
+char* (*dyn_libintl_textdomain)(const char *) = null_libintl_textdomain;
+char* (*dyn_libintl_bindtextdomain)(const char *, const char *)
+ = null_libintl_bindtextdomain;
+
+ int
+dyn_libintl_init(char *libname)
+{
+ int i;
+ static struct
+ {
+ char *name;
+ FARPROC *ptr;
+ } libintl_entry[] =
+ {
+ {"gettext", (FARPROC*)&dyn_libintl_gettext},
+ {"textdomain", (FARPROC*)&dyn_libintl_textdomain},
+ {"bindtextdomain", (FARPROC*)&dyn_libintl_bindtextdomain},
+ {NULL, NULL}
+ };
+
+ /* No need to initialize twice. */
+ if (hLibintlDLL)
+ return 1;
+ /* Load gettext library (libintl.dll) */
+ hLibintlDLL = LoadLibrary(libname != NULL ? libname : GETTEXT_DLL);
+ if (!hLibintlDLL)
+ {
+ char_u dirname[_MAX_PATH];
+
+ /* Try using the path from gvim.exe to find the .dll there. */
+ get_exe_name();
+ STRCPY(dirname, exe_name);
+ STRCPY(gettail(dirname), GETTEXT_DLL);
+ hLibintlDLL = LoadLibrary((char *)dirname);
+ if (!hLibintlDLL)
+ {
+ if (p_verbose > 0)
+ EMSG2(_(e_loadlib), GETTEXT_DLL);
+ return 0;
+ }
+ }
+ for (i = 0; libintl_entry[i].name != NULL
+ && libintl_entry[i].ptr != NULL; ++i)
+ {
+ if ((*libintl_entry[i].ptr = (FARPROC)GetProcAddress(hLibintlDLL,
+ libintl_entry[i].name)) == NULL)
+ {
+ dyn_libintl_end();
+ if (p_verbose > 0)
+ EMSG2(_(e_loadfunc), libintl_entry[i].name);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+ void
+dyn_libintl_end()
+{
+ if (hLibintlDLL)
+ FreeLibrary(hLibintlDLL);
+ hLibintlDLL = NULL;
+ dyn_libintl_gettext = null_libintl_gettext;
+ dyn_libintl_textdomain = null_libintl_textdomain;
+ dyn_libintl_bindtextdomain = null_libintl_bindtextdomain;
+}
+
+ static char *
+null_libintl_gettext(const char* msgid)
+{
+ return (char*)msgid;
+}
+
+ static char *
+null_libintl_bindtextdomain(const char* domainname, const char* dirname)
+{
+ return NULL;
+}
+
+ static char *
+null_libintl_textdomain(const char* domainname)
+{
+ return NULL;
+}
+
+#endif /* DYNAMIC_GETTEXT */
+
+/* This symbol is not defined in older versions of the SDK or Visual C++ */
+
+#ifndef VER_PLATFORM_WIN32_WINDOWS
+# define VER_PLATFORM_WIN32_WINDOWS 1
+#endif
+
+DWORD g_PlatformId;
+
+#ifdef HAVE_ACL
+# include <aclapi.h>
+/*
+ * These are needed to dynamically load the ADVAPI DLL, which is not
+ * implemented under Windows 95 (and causes VIM to crash)
+ */
+typedef DWORD (WINAPI *PSNSECINFO) (LPTSTR, enum SE_OBJECT_TYPE,
+ SECURITY_INFORMATION, PSID, PSID, PACL, PACL);
+typedef DWORD (WINAPI *PGNSECINFO) (LPSTR, enum SE_OBJECT_TYPE,
+ SECURITY_INFORMATION, PSID *, PSID *, PACL *, PACL *,
+ PSECURITY_DESCRIPTOR *);
+
+static HANDLE advapi_lib = NULL; /* Handle for ADVAPI library */
+static PSNSECINFO pSetNamedSecurityInfo;
+static PGNSECINFO pGetNamedSecurityInfo;
+#endif
+
+/*
+ * Set g_PlatformId to VER_PLATFORM_WIN32_NT (NT) or
+ * VER_PLATFORM_WIN32_WINDOWS (Win95).
+ */
+ void
+PlatformId(void)
+{
+ static int done = FALSE;
+
+ if (!done)
+ {
+ OSVERSIONINFO ovi;
+
+ ovi.dwOSVersionInfoSize = sizeof(ovi);
+ GetVersionEx(&ovi);
+
+ g_PlatformId = ovi.dwPlatformId;
+
+#ifdef HAVE_ACL
+ /*
+ * Load the ADVAPI runtime if we are on anything
+ * other than Windows 95
+ */
+ if (g_PlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ /*
+ * do this load. Problems: Doesn't unload at end of run (this is
+ * theoretically okay, since Windows should unload it when VIM
+ * terminates). Should we be using the 'mch_libcall' routines?
+ * Seems like a lot of overhead to load/unload ADVAPI32.DLL each
+ * time we verify security...
+ */
+ advapi_lib = LoadLibrary("ADVAPI32.DLL");
+ if (advapi_lib != NULL)
+ {
+ pSetNamedSecurityInfo = (PSNSECINFO)GetProcAddress(advapi_lib,
+ "SetNamedSecurityInfoA");
+ pGetNamedSecurityInfo = (PGNSECINFO)GetProcAddress(advapi_lib,
+ "GetNamedSecurityInfoA");
+ if (pSetNamedSecurityInfo == NULL
+ || pGetNamedSecurityInfo == NULL)
+ {
+ /* If we can't get the function addresses, set advapi_lib
+ * to NULL so that we don't use them. */
+ FreeLibrary(advapi_lib);
+ advapi_lib = NULL;
+ }
+ }
+ }
+#endif
+ done = TRUE;
+ }
+}
+
+/*
+ * Return TRUE when running on Windows 95 (or 98 or ME).
+ * Only to be used after mch_init().
+ */
+ int
+mch_windows95(void)
+{
+ return g_PlatformId == VER_PLATFORM_WIN32_WINDOWS;
+}
+
+#ifdef FEAT_GUI_W32
+/*
+ * Used to work around the "can't do synchronous spawn"
+ * problem on Win32s, without resorting to Universal Thunk.
+ */
+static int old_num_windows;
+static int num_windows;
+
+ static BOOL CALLBACK
+win32ssynch_cb(HWND hwnd, LPARAM lparam)
+{
+ num_windows++;
+ return TRUE;
+}
+#endif
+
+#ifndef FEAT_GUI_W32
+
+#define SHIFT (SHIFT_PRESSED)
+#define CTRL (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)
+#define ALT (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)
+#define ALT_GR (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)
+
+
+/* When uChar.AsciiChar is 0, then we need to look at wVirtualKeyCode.
+ * We map function keys to their ANSI terminal equivalents, as produced
+ * by ANSI.SYS, for compatibility with the MS-DOS version of Vim. Any
+ * ANSI key with a value >= '\300' is nonstandard, but provided anyway
+ * so that the user can have access to all SHIFT-, CTRL-, and ALT-
+ * combinations of function/arrow/etc keys.
+ */
+
+const static struct
+{
+ WORD wVirtKey;
+ BOOL fAnsiKey;
+ int chAlone;
+ int chShift;
+ int chCtrl;
+ int chAlt;
+} VirtKeyMap[] =
+{
+
+/* Key ANSI alone shift ctrl alt */
+ { VK_ESCAPE,FALSE, ESC, ESC, ESC, ESC, },
+
+ { VK_F1, TRUE, ';', 'T', '^', 'h', },
+ { VK_F2, TRUE, '<', 'U', '_', 'i', },
+ { VK_F3, TRUE, '=', 'V', '`', 'j', },
+ { VK_F4, TRUE, '>', 'W', 'a', 'k', },
+ { VK_F5, TRUE, '?', 'X', 'b', 'l', },
+ { VK_F6, TRUE, '@', 'Y', 'c', 'm', },
+ { VK_F7, TRUE, 'A', 'Z', 'd', 'n', },
+ { VK_F8, TRUE, 'B', '[', 'e', 'o', },
+ { VK_F9, TRUE, 'C', '\\', 'f', 'p', },
+ { VK_F10, TRUE, 'D', ']', 'g', 'q', },
+ { VK_F11, TRUE, '\205', '\207', '\211', '\213', },
+ { VK_F12, TRUE, '\206', '\210', '\212', '\214', },
+
+ { VK_HOME, TRUE, 'G', '\302', 'w', '\303', },
+ { VK_UP, TRUE, 'H', '\304', '\305', '\306', },
+ { VK_PRIOR, TRUE, 'I', '\307', '\204', '\310', }, /*PgUp*/
+ { VK_LEFT, TRUE, 'K', '\311', 's', '\312', },
+ { VK_RIGHT, TRUE, 'M', '\313', 't', '\314', },
+ { VK_END, TRUE, 'O', '\315', 'u', '\316', },
+ { VK_DOWN, TRUE, 'P', '\317', '\320', '\321', },
+ { VK_NEXT, TRUE, 'Q', '\322', 'v', '\323', }, /*PgDn*/
+ { VK_INSERT,TRUE, 'R', '\324', '\325', '\326', },
+ { VK_DELETE,TRUE, 'S', '\327', '\330', '\331', },
+
+ { VK_SNAPSHOT,TRUE, 0, 0, 0, 'r', }, /*PrtScrn*/
+
+#if 0
+ /* Most people don't have F13-F20, but what the hell... */
+ { VK_F13, TRUE, '\332', '\333', '\334', '\335', },
+ { VK_F14, TRUE, '\336', '\337', '\340', '\341', },
+ { VK_F15, TRUE, '\342', '\343', '\344', '\345', },
+ { VK_F16, TRUE, '\346', '\347', '\350', '\351', },
+ { VK_F17, TRUE, '\352', '\353', '\354', '\355', },
+ { VK_F18, TRUE, '\356', '\357', '\360', '\361', },
+ { VK_F19, TRUE, '\362', '\363', '\364', '\365', },
+ { VK_F20, TRUE, '\366', '\367', '\370', '\371', },
+#endif
+ { VK_ADD, TRUE, 'N', 'N', 'N', 'N', }, /* keyp '+' */
+ { VK_SUBTRACT, TRUE,'J', 'J', 'J', 'J', }, /* keyp '-' */
+ /* { VK_DIVIDE, TRUE,'N', 'N', 'N', 'N', }, keyp '/' */
+ { VK_MULTIPLY, TRUE,'7', '7', '7', '7', }, /* keyp '*' */
+
+ { VK_NUMPAD0,TRUE, '\332', '\333', '\334', '\335', },
+ { VK_NUMPAD1,TRUE, '\336', '\337', '\340', '\341', },
+ { VK_NUMPAD2,TRUE, '\342', '\343', '\344', '\345', },
+ { VK_NUMPAD3,TRUE, '\346', '\347', '\350', '\351', },
+ { VK_NUMPAD4,TRUE, '\352', '\353', '\354', '\355', },
+ { VK_NUMPAD5,TRUE, '\356', '\357', '\360', '\361', },
+ { VK_NUMPAD6,TRUE, '\362', '\363', '\364', '\365', },
+ { VK_NUMPAD7,TRUE, '\366', '\367', '\370', '\371', },
+ { VK_NUMPAD8,TRUE, '\372', '\373', '\374', '\375', },
+ /* Sorry, out of number space! <negri>*/
+ { VK_NUMPAD9,TRUE, '\376', '\377', '\377', '\367', },
+
+};
+
+
+#ifdef _MSC_VER
+// The ToAscii bug destroys several registers. Need to turn off optimization
+// or the GetConsoleKeyboardLayoutName hack will fail in non-debug versions
+# pragma optimize("", off)
+#endif
+
+#if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+# define AChar AsciiChar
+#else
+# define AChar uChar.AsciiChar
+#endif
+
+/* The return code indicates key code size. */
+ static int
+#ifdef __BORLANDC__
+ __stdcall
+#endif
+win32_kbd_patch_key(
+ KEY_EVENT_RECORD* pker)
+{
+ UINT uMods = pker->dwControlKeyState;
+ static int s_iIsDead = 0;
+ static WORD awAnsiCode[2];
+ static BYTE abKeystate[256];
+
+
+ if (s_iIsDead == 2)
+ {
+ pker->AChar = (CHAR) awAnsiCode[1];
+ s_iIsDead = 0;
+ return 1;
+ }
+
+ if (pker->AChar != 0)
+ return 1;
+
+ memset(abKeystate, 0, sizeof (abKeystate));
+
+ // Should only be non-NULL on NT 4.0
+ if (s_pfnGetConsoleKeyboardLayoutName != NULL)
+ {
+ CHAR szKLID[KL_NAMELENGTH];
+
+ if ((*s_pfnGetConsoleKeyboardLayoutName)(szKLID))
+ (void)LoadKeyboardLayout(szKLID, KLF_ACTIVATE);
+ }
+
+ /* Clear any pending dead keys */
+ ToAscii(VK_SPACE, MapVirtualKey(VK_SPACE, 0), abKeystate, awAnsiCode, 0);
+
+ if (uMods & SHIFT_PRESSED)
+ abKeystate[VK_SHIFT] = 0x80;
+ if (uMods & CAPSLOCK_ON)
+ abKeystate[VK_CAPITAL] = 1;
+
+ if ((uMods & ALT_GR) == ALT_GR)
+ {
+ abKeystate[VK_CONTROL] = abKeystate[VK_LCONTROL] =
+ abKeystate[VK_MENU] = abKeystate[VK_RMENU] = 0x80;
+ }
+
+ s_iIsDead = ToAscii(pker->wVirtualKeyCode, pker->wVirtualScanCode,
+ abKeystate, awAnsiCode, 0);
+
+ if (s_iIsDead > 0)
+ pker->AChar = (CHAR) awAnsiCode[0];
+
+ return s_iIsDead;
+}
+
+#ifdef _MSC_VER
+/* MUST switch optimization on again here, otherwise a call to
+ * decode_key_event() may crash (e.g. when hitting caps-lock) */
+# pragma optimize("", on)
+
+# if (_MSC_VER < 1100)
+/* MUST turn off global optimisation for this next function, or
+ * pressing ctrl-minus in insert mode crashes Vim when built with
+ * VC4.1. -- negri. */
+# pragma optimize("g", off)
+# endif
+#endif
+
+static BOOL g_fJustGotFocus = FALSE;
+
+/*
+ * Decode a KEY_EVENT into one or two keystrokes
+ */
+ static BOOL
+decode_key_event(
+ KEY_EVENT_RECORD *pker,
+ char_u *pch,
+ char_u *pch2,
+ int *pmodifiers,
+ BOOL fDoPost)
+{
+ int i;
+ const int nModifs = pker->dwControlKeyState & (SHIFT | ALT | CTRL);
+
+ *pch = *pch2 = NUL;
+ g_fJustGotFocus = FALSE;
+
+ /* ignore key up events */
+ if (!pker->bKeyDown)
+ return FALSE;
+
+ /* ignore some keystrokes */
+ switch (pker->wVirtualKeyCode)
+ {
+ /* modifiers */
+ case VK_SHIFT:
+ case VK_CONTROL:
+ case VK_MENU: /* Alt key */
+ return FALSE;
+
+ default:
+ break;
+ }
+
+ /* special cases */
+ if ((nModifs & CTRL) != 0 && (nModifs & ~CTRL) == 0 && pker->AChar == NUL)
+ {
+ /* Ctrl-6 is Ctrl-^ */
+ if (pker->wVirtualKeyCode == '6')
+ {
+ *pch = Ctrl_HAT;
+ return TRUE;
+ }
+ /* Ctrl-2 is Ctrl-@ */
+ else if (pker->wVirtualKeyCode == '2')
+ {
+ *pch = NUL;
+ return TRUE;
+ }
+ /* Ctrl-- is Ctrl-_ */
+ else if (pker->wVirtualKeyCode == 0xBD)
+ {
+ *pch = Ctrl__;
+ return TRUE;
+ }
+ }
+
+ /* Shift-TAB */
+ if (pker->wVirtualKeyCode == VK_TAB && (nModifs & SHIFT_PRESSED))
+ {
+ *pch = K_NUL;
+ *pch2 = '\017';
+ return TRUE;
+ }
+
+ for (i = sizeof(VirtKeyMap) / sizeof(VirtKeyMap[0]); --i >= 0; )
+ {
+ if (VirtKeyMap[i].wVirtKey == pker->wVirtualKeyCode)
+ {
+ if (nModifs == 0)
+ *pch = VirtKeyMap[i].chAlone;
+ else if ((nModifs & SHIFT) != 0 && (nModifs & ~SHIFT) == 0)
+ *pch = VirtKeyMap[i].chShift;
+ else if ((nModifs & CTRL) != 0 && (nModifs & ~CTRL) == 0)
+ *pch = VirtKeyMap[i].chCtrl;
+ else if ((nModifs & ALT) != 0 && (nModifs & ~ALT) == 0)
+ *pch = VirtKeyMap[i].chAlt;
+
+ if (*pch != 0)
+ {
+ if (VirtKeyMap[i].fAnsiKey)
+ {
+ *pch2 = *pch;
+ *pch = K_NUL;
+ }
+
+ return TRUE;
+ }
+ }
+ }
+
+ i = win32_kbd_patch_key(pker);
+
+ if (i < 0)
+ *pch = NUL;
+ else
+ {
+ *pch = (i > 0) ? pker->AChar : NUL;
+
+ if (pmodifiers != NULL)
+ {
+ /* Pass on the ALT key as a modifier, but only when not combined
+ * with CTRL (which is ALTGR). */
+ if ((nModifs & ALT) != 0 && (nModifs & CTRL) == 0)
+ *pmodifiers |= MOD_MASK_ALT;
+
+ /* Pass on SHIFT only for special keys, because we don't know when
+ * it's already included with the character. */
+ if ((nModifs & SHIFT) != 0 && *pch <= 0x20)
+ *pmodifiers |= MOD_MASK_SHIFT;
+
+ /* Pass on CTRL only for non-special keys, because we don't know
+ * when it's already included with the character. And not when
+ * combined with ALT (which is ALTGR). */
+ if ((nModifs & CTRL) != 0 && (nModifs & ALT) == 0
+ && *pch >= 0x20 && *pch < 0x80)
+ *pmodifiers |= MOD_MASK_CTRL;
+ }
+ }
+
+ return (*pch != NUL);
+}
+
+#ifdef _MSC_VER
+# pragma optimize("", on)
+#endif
+
+#endif /* FEAT_GUI_W32 */
+
+
+#ifdef FEAT_MOUSE
+
+/*
+ * For the GUI the mouse handling is in gui_w32.c.
+ */
+# ifdef FEAT_GUI_W32
+ void
+mch_setmouse(
+ int on)
+{
+}
+# else
+static int g_fMouseAvail = FALSE; /* mouse present */
+static int g_fMouseActive = FALSE; /* mouse enabled */
+static int g_nMouseClick = -1; /* mouse status */
+static int g_xMouse; /* mouse x coordinate */
+static int g_yMouse; /* mouse y coordinate */
+
+/*
+ * Enable or disable mouse input
+ */
+ void
+mch_setmouse(
+ int on)
+{
+ DWORD cmodein;
+
+ if (!g_fMouseAvail)
+ return;
+
+ g_fMouseActive = on;
+ GetConsoleMode(g_hConIn, &cmodein);
+
+ if (g_fMouseActive)
+ cmodein |= ENABLE_MOUSE_INPUT;
+ else
+ cmodein &= ~ENABLE_MOUSE_INPUT;
+
+ SetConsoleMode(g_hConIn, cmodein);
+}
+
+
+/*
+ * Decode a MOUSE_EVENT. If it's a valid event, return MOUSE_LEFT,
+ * MOUSE_MIDDLE, or MOUSE_RIGHT for a click; MOUSE_DRAG for a mouse
+ * move with a button held down; and MOUSE_RELEASE after a MOUSE_DRAG
+ * or a MOUSE_LEFT, _MIDDLE, or _RIGHT. We encode the button type,
+ * the number of clicks, and the Shift/Ctrl/Alt modifiers in g_nMouseClick,
+ * and we return the mouse position in g_xMouse and g_yMouse.
+ *
+ * Every MOUSE_LEFT, _MIDDLE, or _RIGHT will be followed by zero or more
+ * MOUSE_DRAGs and one MOUSE_RELEASE. MOUSE_RELEASE will be followed only
+ * by MOUSE_LEFT, _MIDDLE, or _RIGHT.
+ *
+ * For multiple clicks, we send, say, MOUSE_LEFT/1 click, MOUSE_RELEASE,
+ * MOUSE_LEFT/2 clicks, MOUSE_RELEASE, MOUSE_LEFT/3 clicks, MOUSE_RELEASE, ....
+ *
+ * Windows will send us MOUSE_MOVED notifications whenever the mouse
+ * moves, even if it stays within the same character cell. We ignore
+ * all MOUSE_MOVED messages if the position hasn't really changed, and
+ * we ignore all MOUSE_MOVED messages where no button is held down (i.e.,
+ * we're only interested in MOUSE_DRAG).
+ *
+ * All of this is complicated by the code that fakes MOUSE_MIDDLE on
+ * 2-button mouses by pressing the left & right buttons simultaneously.
+ * In practice, it's almost impossible to click both at the same time,
+ * so we need to delay a little. Also, we tend not to get MOUSE_RELEASE
+ * in such cases, if the user is clicking quickly.
+ */
+ static BOOL
+decode_mouse_event(
+ MOUSE_EVENT_RECORD* pmer)
+{
+ static int s_nOldButton = -1;
+ static int s_nOldMouseClick = -1;
+ static int s_xOldMouse = -1;
+ static int s_yOldMouse = -1;
+ static linenr_T s_old_topline = 0;
+#ifdef FEAT_DIFF
+ static int s_old_topfill = 0;
+#endif
+ static int s_cClicks = 1;
+ static BOOL s_fReleased = TRUE;
+ static DWORD s_dwLastClickTime = 0;
+ static BOOL s_fNextIsMiddle = FALSE;
+
+ static DWORD cButtons = 0; /* number of buttons supported */
+
+ const DWORD LEFT = FROM_LEFT_1ST_BUTTON_PRESSED;
+ const DWORD MIDDLE = FROM_LEFT_2ND_BUTTON_PRESSED;
+ const DWORD RIGHT = RIGHTMOST_BUTTON_PRESSED;
+ const DWORD LEFT_RIGHT = LEFT | RIGHT;
+
+ int nButton;
+
+ if (cButtons == 0 && !GetNumberOfConsoleMouseButtons(&cButtons))
+ cButtons = 2;
+
+ if (!g_fMouseAvail || !g_fMouseActive)
+ {
+ g_nMouseClick = -1;
+ return FALSE;
+ }
+
+ /* get a spurious MOUSE_EVENT immediately after receiving focus; ignore */
+ if (g_fJustGotFocus)
+ {
+ g_fJustGotFocus = FALSE;
+ return FALSE;
+ }
+
+ /* unprocessed mouse click? */
+ if (g_nMouseClick != -1)
+ return TRUE;
+
+ nButton = -1;
+ g_xMouse = pmer->dwMousePosition.X;
+ g_yMouse = pmer->dwMousePosition.Y;
+
+ if (pmer->dwEventFlags == MOUSE_MOVED)
+ {
+ /* ignore MOUSE_MOVED events if (x, y) hasn't changed. (We get these
+ * events even when the mouse moves only within a char cell.) */
+ if (s_xOldMouse == g_xMouse && s_yOldMouse == g_yMouse)
+ return FALSE;
+ }
+
+ /* If no buttons are pressed... */
+ if ((pmer->dwButtonState & ((1 << cButtons) - 1)) == 0)
+ {
+ /* If the last thing returned was MOUSE_RELEASE, ignore this */
+ if (s_fReleased)
+ return FALSE;
+
+ nButton = MOUSE_RELEASE;
+ s_fReleased = TRUE;
+ }
+ else /* one or more buttons pressed */
+ {
+ /* on a 2-button mouse, hold down left and right buttons
+ * simultaneously to get MIDDLE. */
+
+ if (cButtons == 2 && s_nOldButton != MOUSE_DRAG)
+ {
+ DWORD dwLR = (pmer->dwButtonState & LEFT_RIGHT);
+
+ /* if either left or right button only is pressed, see if the
+ * the next mouse event has both of them pressed */
+ if (dwLR == LEFT || dwLR == RIGHT)
+ {
+ for (;;)
+ {
+ /* wait a short time for next input event */
+ if (WaitForSingleObject(g_hConIn, p_mouset / 3)
+ != WAIT_OBJECT_0)
+ break;
+ else
+ {
+ DWORD cRecords = 0;
+ INPUT_RECORD ir;
+ MOUSE_EVENT_RECORD* pmer2 = &ir.Event.MouseEvent;
+
+ PeekConsoleInput(g_hConIn, &ir, 1, &cRecords);
+
+ if (cRecords == 0 || ir.EventType != MOUSE_EVENT
+ || !(pmer2->dwButtonState & LEFT_RIGHT))
+ break;
+ else
+ {
+ if (pmer2->dwEventFlags != MOUSE_MOVED)
+ {
+ ReadConsoleInput(g_hConIn, &ir, 1, &cRecords);
+
+ return decode_mouse_event(pmer2);
+ }
+ else if (s_xOldMouse == pmer2->dwMousePosition.X &&
+ s_yOldMouse == pmer2->dwMousePosition.Y)
+ {
+ /* throw away spurious mouse move */
+ ReadConsoleInput(g_hConIn, &ir, 1, &cRecords);
+
+ /* are there any more mouse events in queue? */
+ PeekConsoleInput(g_hConIn, &ir, 1, &cRecords);
+
+ if (cRecords==0 || ir.EventType != MOUSE_EVENT)
+ break;
+ }
+ else
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (s_fNextIsMiddle)
+ {
+ nButton = (pmer->dwEventFlags == MOUSE_MOVED)
+ ? MOUSE_DRAG : MOUSE_MIDDLE;
+ s_fNextIsMiddle = FALSE;
+ }
+ else if (cButtons == 2 &&
+ ((pmer->dwButtonState & LEFT_RIGHT) == LEFT_RIGHT))
+ {
+ nButton = MOUSE_MIDDLE;
+
+ if (! s_fReleased && pmer->dwEventFlags != MOUSE_MOVED)
+ {
+ s_fNextIsMiddle = TRUE;
+ nButton = MOUSE_RELEASE;
+ }
+ }
+ else if ((pmer->dwButtonState & LEFT) == LEFT)
+ nButton = MOUSE_LEFT;
+ else if ((pmer->dwButtonState & MIDDLE) == MIDDLE)
+ nButton = MOUSE_MIDDLE;
+ else if ((pmer->dwButtonState & RIGHT) == RIGHT)
+ nButton = MOUSE_RIGHT;
+
+ if (! s_fReleased && ! s_fNextIsMiddle
+ && nButton != s_nOldButton && s_nOldButton != MOUSE_DRAG)
+ return FALSE;
+
+ s_fReleased = s_fNextIsMiddle;
+ }
+
+ if (pmer->dwEventFlags == 0 || pmer->dwEventFlags == DOUBLE_CLICK)
+ {
+ /* button pressed or released, without mouse moving */
+ if (nButton != -1 && nButton != MOUSE_RELEASE)
+ {
+ DWORD dwCurrentTime = GetTickCount();
+
+ if (s_xOldMouse != g_xMouse
+ || s_yOldMouse != g_yMouse
+ || s_nOldButton != nButton
+ || s_old_topline != curwin->w_topline
+#ifdef FEAT_DIFF
+ || s_old_topfill != curwin->w_topfill
+#endif
+ || (int)(dwCurrentTime - s_dwLastClickTime) > p_mouset)
+ {
+ s_cClicks = 1;
+ }
+ else if (++s_cClicks > 4)
+ {
+ s_cClicks = 1;
+ }
+
+ s_dwLastClickTime = dwCurrentTime;
+ }
+ }
+ else if (pmer->dwEventFlags == MOUSE_MOVED)
+ {
+ if (nButton != -1 && nButton != MOUSE_RELEASE)
+ nButton = MOUSE_DRAG;
+
+ s_cClicks = 1;
+ }
+
+ if (nButton == -1)
+ return FALSE;
+
+ if (nButton != MOUSE_RELEASE)
+ s_nOldButton = nButton;
+
+ g_nMouseClick = nButton;
+
+ if (pmer->dwControlKeyState & SHIFT_PRESSED)
+ g_nMouseClick |= MOUSE_SHIFT;
+ if (pmer->dwControlKeyState & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
+ g_nMouseClick |= MOUSE_CTRL;
+ if (pmer->dwControlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
+ g_nMouseClick |= MOUSE_ALT;
+
+ if (nButton != MOUSE_DRAG && nButton != MOUSE_RELEASE)
+ SET_NUM_MOUSE_CLICKS(g_nMouseClick, s_cClicks);
+
+ /* only pass on interesting (i.e., different) mouse events */
+ if (s_xOldMouse == g_xMouse
+ && s_yOldMouse == g_yMouse
+ && s_nOldMouseClick == g_nMouseClick)
+ {
+ g_nMouseClick = -1;
+ return FALSE;
+ }
+
+ s_xOldMouse = g_xMouse;
+ s_yOldMouse = g_yMouse;
+ s_old_topline = curwin->w_topline;
+#ifdef FEAT_DIFF
+ s_old_topfill = curwin->w_topfill;
+#endif
+ s_nOldMouseClick = g_nMouseClick;
+
+ return TRUE;
+}
+
+# endif /* FEAT_GUI_W32 */
+#endif /* FEAT_MOUSE */
+
+
+#ifdef MCH_CURSOR_SHAPE
+/*
+ * Set the shape of the cursor.
+ * 'thickness' can be from 1 (thin) to 99 (block)
+ */
+ static void
+mch_set_cursor_shape(int thickness)
+{
+ CONSOLE_CURSOR_INFO ConsoleCursorInfo;
+ ConsoleCursorInfo.dwSize = thickness;
+ ConsoleCursorInfo.bVisible = s_cursor_visible;
+
+ SetConsoleCursorInfo(g_hConOut, &ConsoleCursorInfo);
+ if (s_cursor_visible)
+ SetConsoleCursorPosition(g_hConOut, g_coord);
+}
+
+ void
+mch_update_cursor(void)
+{
+ int idx;
+ int thickness;
+
+ /*
+ * How the cursor is drawn depends on the current mode.
+ */
+ idx = get_shape_idx(FALSE);
+
+ if (shape_table[idx].shape == SHAPE_BLOCK)
+ thickness = 99; /* 100 doesn't work on W95 */
+ else
+ thickness = shape_table[idx].percentage;
+ mch_set_cursor_shape(thickness);
+}
+#endif
+
+#ifndef FEAT_GUI_W32 /* this isn't used for the GUI */
+/*
+ * Handle FOCUS_EVENT.
+ */
+ static void
+handle_focus_event(INPUT_RECORD ir)
+{
+ g_fJustGotFocus = ir.Event.FocusEvent.bSetFocus;
+ ui_focus_change((int)g_fJustGotFocus);
+}
+
+/*
+ * Wait until console input from keyboard or mouse is available,
+ * or the time is up.
+ * Return TRUE if something is available FALSE if not.
+ */
+ static int
+WaitForChar(long msec)
+{
+ DWORD dwNow = 0, dwEndTime = 0;
+ INPUT_RECORD ir;
+ DWORD cRecords;
+ char_u ch, ch2;
+
+ if (msec > 0)
+ /* Wait until the specified time has elapsed. */
+ dwEndTime = GetTickCount() + msec;
+ else if (msec < 0)
+ /* Wait forever. */
+ dwEndTime = INFINITE;
+
+ /* We need to loop until the end of the time period, because
+ * we might get multiple unusable mouse events in that time.
+ */
+ for (;;)
+ {
+#ifdef FEAT_CLIENTSERVER
+ serverProcessPendingMessages();
+#endif
+ if (0
+#ifdef FEAT_MOUSE
+ || g_nMouseClick != -1
+#endif
+#ifdef FEAT_CLIENTSERVER
+ || input_available()
+#endif
+ )
+ return TRUE;
+
+ if (msec > 0)
+ {
+ /* If the specified wait time has passed, return. */
+ dwNow = GetTickCount();
+ if (dwNow >= dwEndTime)
+ break;
+ }
+ if (msec != 0)
+ {
+#ifdef FEAT_CLIENTSERVER
+ /* Wait for either an event on the console input or a message in
+ * the client-server window. */
+ if (MsgWaitForMultipleObjects(1, &g_hConIn, FALSE,
+ dwEndTime - dwNow, QS_SENDMESSAGE) != WAIT_OBJECT_0)
+#else
+ if (WaitForSingleObject(g_hConIn, dwEndTime - dwNow)
+ != WAIT_OBJECT_0)
+#endif
+ continue;
+ }
+
+ cRecords = 0;
+ PeekConsoleInput(g_hConIn, &ir, 1, &cRecords);
+
+#ifdef FEAT_MBYTE_IME
+ if (State & CMDLINE && msg_row == Rows - 1)
+ {
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+ if (GetConsoleScreenBufferInfo(g_hConOut, &csbi))
+ {
+ if (csbi.dwCursorPosition.Y != msg_row)
+ {
+ /* The screen is now messed up, must redraw the
+ * command line and later all the windows. */
+ redraw_all_later(CLEAR);
+ cmdline_row -= (msg_row - csbi.dwCursorPosition.Y);
+ redrawcmd();
+ }
+ }
+ }
+#endif
+
+ if (cRecords > 0)
+ {
+ if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown)
+ {
+#ifdef FEAT_MBYTE_IME
+ /* Windows IME sends two '\n's with only one 'ENTER'. First:
+ * wVirtualKeyCode == 13. second: wVirtualKeyCode == 0 */
+ if (ir.Event.KeyEvent.uChar.UnicodeChar == 0
+ && ir.Event.KeyEvent.wVirtualKeyCode == 13)
+ {
+ ReadConsoleInput(g_hConIn, &ir, 1, &cRecords);
+ continue;
+ }
+#endif
+ if (decode_key_event(&ir.Event.KeyEvent, &ch, &ch2,
+ NULL, FALSE))
+ return TRUE;
+ }
+
+ ReadConsoleInput(g_hConIn, &ir, 1, &cRecords);
+
+ if (ir.EventType == FOCUS_EVENT)
+ handle_focus_event(ir);
+ else if (ir.EventType == WINDOW_BUFFER_SIZE_EVENT)
+ shell_resized();
+#ifdef FEAT_MOUSE
+ else if (ir.EventType == MOUSE_EVENT
+ && decode_mouse_event(&ir.Event.MouseEvent))
+ return TRUE;
+#endif
+ }
+ else if (msec == 0)
+ break;
+ }
+
+#ifdef FEAT_CLIENTSERVER
+ /* Something might have been received while we were waiting. */
+ if (input_available())
+ return TRUE;
+#endif
+ return FALSE;
+}
+
+#ifndef FEAT_GUI_MSWIN
+/*
+ * return non-zero if a character is available
+ */
+ int
+mch_char_avail()
+{
+ return WaitForChar(0L);
+}
+#endif
+
+/*
+ * Create the console input. Used when reading stdin doesn't work.
+ */
+ static void
+create_conin(void)
+{
+ g_hConIn = CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ (LPSECURITY_ATTRIBUTES) NULL,
+ OPEN_EXISTING, (DWORD)NULL, (HANDLE)NULL);
+ did_create_conin = TRUE;
+}
+
+/*
+ * Get a keystroke or a mouse event
+ */
+ static char_u
+tgetch(int *pmodifiers, char_u *pch2)
+{
+ char_u ch;
+
+ for (;;)
+ {
+ INPUT_RECORD ir;
+ DWORD cRecords = 0;
+
+#ifdef FEAT_CLIENTSERVER
+ (void)WaitForChar(-1L);
+ if (input_available())
+ return 0;
+# ifdef FEAT_MOUSE
+ if (g_nMouseClick != -1)
+ return 0;
+# endif
+#endif
+ if (ReadConsoleInput(g_hConIn, &ir, 1, &cRecords) == 0)
+ {
+ if (did_create_conin)
+ read_error_exit();
+ create_conin();
+ continue;
+ }
+
+ if (ir.EventType == KEY_EVENT)
+ {
+ if (decode_key_event(&ir.Event.KeyEvent, &ch, pch2,
+ pmodifiers, TRUE))
+ return ch;
+ }
+ else if (ir.EventType == FOCUS_EVENT)
+ handle_focus_event(ir);
+ else if (ir.EventType == WINDOW_BUFFER_SIZE_EVENT)
+ shell_resized();
+#ifdef FEAT_MOUSE
+ else if (ir.EventType == MOUSE_EVENT)
+ {
+ if (decode_mouse_event(&ir.Event.MouseEvent))
+ return 0;
+ }
+#endif
+ }
+}
+#endif /* !FEAT_GUI_W32 */
+
+
+/*
+ * mch_inchar(): low-level input funcion.
+ * Get one or more characters from the keyboard or the mouse.
+ * If time == 0, do not wait for characters.
+ * If time == n, wait a short time for characters.
+ * If time == -1, wait forever for characters.
+ * Returns the number of characters read into buf.
+ */
+ int
+mch_inchar(
+ char_u *buf,
+ int maxlen,
+ long time,
+ int tb_change_cnt)
+{
+#ifndef FEAT_GUI_W32 /* this isn't used for the GUI */
+
+ int len;
+ int c;
+#ifdef FEAT_AUTOCMD
+ static int once_already = 0;
+#endif
+#define TYPEAHEADLEN 20
+ static char_u typeahead[TYPEAHEADLEN]; /* previously typed bytes. */
+ static int typeaheadlen = 0;
+
+ /* First use any typeahead that was kept because "buf" was too small. */
+ if (typeaheadlen > 0)
+ goto theend;
+
+#ifdef FEAT_SNIFF
+ if (want_sniff_request)
+ {
+ if (sniff_request_waiting)
+ {
+ /* return K_SNIFF */
+ typeahead[typeaheadlen++] = CSI;
+ typeahead[typeaheadlen++] = (char_u)KS_EXTRA;
+ typeahead[typeaheadlen++] = (char_u)KE_SNIFF;
+ sniff_request_waiting = 0;
+ want_sniff_request = 0;
+ goto theend;
+ }
+ else if (time < 0 || time > 250)
+ {
+ /* don't wait too long, a request might be pending */
+ time = 250;
+ }
+ }
+#endif
+
+ if (time >= 0)
+ {
+ if (!WaitForChar(time)) /* no character available */
+ {
+#ifdef FEAT_AUTOCMD
+ once_already = 0;
+#endif
+ return 0;
+ }
+ }
+ else /* time == -1, wait forever */
+ {
+ mch_set_winsize_now(); /* Allow winsize changes from now on */
+
+#ifdef FEAT_AUTOCMD
+ /* If there is no character available within 2 seconds (default),
+ * write the autoscript file to disk */
+ if (once_already == 2)
+ updatescript(0);
+ else if (once_already == 1)
+ {
+ setcursor();
+ once_already = 2;
+ return 0;
+ }
+ else
+#endif
+ if (!WaitForChar(p_ut))
+ {
+#ifdef FEAT_AUTOCMD
+ if (has_cursorhold() && get_real_state() == NORMAL_BUSY)
+ {
+ apply_autocmds(EVENT_CURSORHOLD, NULL, NULL, FALSE, curbuf);
+ update_screen(VALID);
+ once_already = 1;
+ return 0;
+ }
+#endif
+ updatescript(0);
+ }
+ }
+
+ /*
+ * Try to read as many characters as there are, until the buffer is full.
+ */
+
+ /* we will get at least one key. Get more if they are available. */
+ g_fCBrkPressed = FALSE;
+
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ fputc('[', fdDump);
+#endif
+
+ /* Keep looping until there is something in the typeahead buffer and more
+ * to get and still room in the buffer (up to two bytes for a char and
+ * three bytes for a modifier). */
+ while ((typeaheadlen == 0 || WaitForChar(0L))
+ && typeaheadlen + 5 <= TYPEAHEADLEN)
+ {
+ if (typebuf_changed(tb_change_cnt))
+ {
+ /* "buf" may be invalid now if a client put something in the
+ * typeahead buffer and "buf" is in the typeahead buffer. */
+ typeaheadlen = 0;
+ break;
+ }
+#ifdef FEAT_MOUSE
+ if (g_nMouseClick != -1)
+ {
+# ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ fprintf(fdDump, "{%02x @ %d, %d}",
+ g_nMouseClick, g_xMouse, g_yMouse);
+# endif
+ typeahead[typeaheadlen++] = ESC + 128;
+ typeahead[typeaheadlen++] = 'M';
+ typeahead[typeaheadlen++] = g_nMouseClick;
+ typeahead[typeaheadlen++] = g_xMouse + '!';
+ typeahead[typeaheadlen++] = g_yMouse + '!';
+ g_nMouseClick = -1;
+ }
+ else
+#endif
+ {
+ char_u ch2 = NUL;
+ int modifiers = 0;
+
+ c = tgetch(&modifiers, &ch2);
+
+ if (typebuf_changed(tb_change_cnt))
+ {
+ /* "buf" may be invalid now if a client put something in the
+ * typeahead buffer and "buf" is in the typeahead buffer. */
+ typeaheadlen = 0;
+ break;
+ }
+
+ if (c == Ctrl_C && ctrl_c_interrupts)
+ {
+#if defined(FEAT_CLIENTSERVER)
+ trash_input_buf();
+#endif
+ got_int = TRUE;
+ }
+
+#ifdef FEAT_MOUSE
+ if (g_nMouseClick == -1)
+#endif
+ {
+ int n = 1;
+
+ /* A key may have one or two bytes. */
+ typeahead[typeaheadlen] = c;
+ if (ch2 != NUL)
+ {
+ typeahead[typeaheadlen + 1] = ch2;
+ ++n;
+ }
+#ifdef FEAT_MBYTE
+ /* Only convert normal characters, not special keys. Need to
+ * convert before applying ALT, otherwise mapping <M-x> breaks
+ * when 'tenc' is set. */
+ if (input_conv.vc_type != CONV_NONE
+ && (ch2 == NUL || c != K_NUL))
+ n = convert_input(typeahead + typeaheadlen, n,
+ TYPEAHEADLEN - typeaheadlen);
+#endif
+
+ /* Use the ALT key to set the 8th bit of the character
+ * when it's one byte, the 8th bit isn't set yet and not
+ * using a double-byte encoding (would become a lead
+ * byte). */
+ if ((modifiers & MOD_MASK_ALT)
+ && n == 1
+ && (typeahead[typeaheadlen] & 0x80) == 0
+#ifdef FEAT_MBYTE
+ && !enc_dbcs
+#endif
+ )
+ {
+ typeahead[typeaheadlen] |= 0x80;
+ modifiers &= ~MOD_MASK_ALT;
+ }
+
+ if (modifiers != 0)
+ {
+ /* Prepend modifiers to the character. */
+ mch_memmove(typeahead + typeaheadlen + 3,
+ typeahead + typeaheadlen, n);
+ typeahead[typeaheadlen++] = K_SPECIAL;
+ typeahead[typeaheadlen++] = (char_u)KS_MODIFIER;
+ typeahead[typeaheadlen++] = modifiers;
+ }
+
+ typeaheadlen += n;
+
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ fputc(c, fdDump);
+#endif
+ }
+ }
+ }
+
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ {
+ fputs("]\n", fdDump);
+ fflush(fdDump);
+ }
+#endif
+
+#ifdef FEAT_AUTOCMD
+ once_already = 0;
+#endif
+
+theend:
+ /* Move typeahead to "buf", as much as fits. */
+ len = 0;
+ while (len < maxlen && typeaheadlen > 0)
+ {
+ buf[len++] = typeahead[0];
+ mch_memmove(typeahead, typeahead + 1, --typeaheadlen);
+ }
+ return len;
+
+#else /* FEAT_GUI_W32 */
+ return 0;
+#endif /* FEAT_GUI_W32 */
+}
+
+#ifndef __MINGW32__
+# include <shellapi.h> /* required for FindExecutable() */
+#endif
+
+ static int
+executable_exists(char *name)
+{
+ char location[2 * _MAX_PATH + 2];
+ char widename[2 * _MAX_PATH];
+
+ /* There appears to be a bug in FindExecutableA() on Windows NT.
+ * Use FindExecutableW() instead... */
+ if (g_PlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)name, -1,
+ (LPWSTR)widename, _MAX_PATH);
+ if (FindExecutableW((LPCWSTR)widename, (LPCWSTR)"",
+ (LPWSTR)location) > (HINSTANCE)32)
+ return TRUE;
+ }
+ else
+ {
+ if (FindExecutableA((LPCTSTR)name, (LPCTSTR)"",
+ (LPTSTR)location) > (HINSTANCE)32)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#ifdef FEAT_GUI_W32
+
+/*
+ * GUI version of mch_init().
+ */
+ void
+mch_init()
+{
+#ifndef __MINGW32__
+ extern int _fmode;
+#endif
+
+ /* Let critical errors result in a failure, not in a dialog box. Required
+ * for the timestamp test to work on removed floppies. */
+ SetErrorMode(SEM_FAILCRITICALERRORS);
+
+ _fmode = O_BINARY; /* we do our own CR-LF translation */
+
+ /* Specify window size. Is there a place to get the default from? */
+ Rows = 25;
+ Columns = 80;
+
+ /* Look for 'vimrun' */
+ if (!gui_is_win32s())
+ {
+ char_u vimrun_location[_MAX_PATH + 4];
+
+ /* First try in same directory as gvim.exe */
+ STRCPY(vimrun_location, exe_name);
+ STRCPY(gettail(vimrun_location), "vimrun.exe");
+ if (mch_getperm(vimrun_location) >= 0)
+ {
+ if (*skiptowhite(vimrun_location) != NUL)
+ {
+ /* Enclose path with white space in double quotes. */
+ mch_memmove(vimrun_location + 1, vimrun_location,
+ STRLEN(vimrun_location) + 1);
+ *vimrun_location = '"';
+ STRCPY(gettail(vimrun_location), "vimrun\" ");
+ }
+ else
+ STRCPY(gettail(vimrun_location), "vimrun ");
+
+ vimrun_path = (char *)vim_strsave(vimrun_location);
+ s_dont_use_vimrun = FALSE;
+ }
+ else if (executable_exists("vimrun.exe"))
+ s_dont_use_vimrun = FALSE;
+
+ /* Don't give the warning for a missing vimrun.exe right now, but only
+ * when vimrun was supposed to be used. Don't bother people that do
+ * not need vimrun.exe. */
+ if (s_dont_use_vimrun)
+ need_vimrun_warning = TRUE;
+ }
+
+ /*
+ * If "finstr.exe" doesn't exist, use "grep -n" for 'grepprg'.
+ * Otherwise the default "findstr /n" is used.
+ */
+ if (!executable_exists("findstr.exe"))
+ set_option_value((char_u *)"grepprg", 0, (char_u *)"grep -n", 0);
+
+#ifdef FEAT_CLIPBOARD
+ clip_init(TRUE);
+
+ /*
+ * Vim's own clipboard format recognises whether the text is char, line, or
+ * rectangular block. Only useful for copying between two Vims.
+ * "VimClipboard" was used for previous versions, using the first
+ * character to specify MCHAR, MLINE or MBLOCK.
+ */
+ clip_star.format = RegisterClipboardFormat("VimClipboard2");
+ clip_star.format_raw = RegisterClipboardFormat("VimRawBytes");
+#endif
+}
+
+
+#else /* FEAT_GUI_W32 */
+
+#define SRWIDTH(sr) ((sr).Right - (sr).Left + 1)
+#define SRHEIGHT(sr) ((sr).Bottom - (sr).Top + 1)
+
+/*
+ * ClearConsoleBuffer()
+ * Description:
+ * Clears the entire contents of the console screen buffer, using the
+ * specified attribute.
+ * Returns:
+ * TRUE on success
+ */
+ static BOOL
+ClearConsoleBuffer(WORD wAttribute)
+{
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ COORD coord;
+ DWORD NumCells, dummy;
+
+ if (!GetConsoleScreenBufferInfo(g_hConOut, &csbi))
+ return FALSE;
+
+ NumCells = csbi.dwSize.X * csbi.dwSize.Y;
+ coord.X = 0;
+ coord.Y = 0;
+ if (!FillConsoleOutputCharacter(g_hConOut, ' ', NumCells,
+ coord, &dummy))
+ {
+ return FALSE;
+ }
+ if (!FillConsoleOutputAttribute(g_hConOut, wAttribute, NumCells,
+ coord, &dummy))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * FitConsoleWindow()
+ * Description:
+ * Checks if the console window will fit within given buffer dimensions.
+ * Also, if requested, will shrink the window to fit.
+ * Returns:
+ * TRUE on success
+ */
+ static BOOL
+FitConsoleWindow(
+ COORD dwBufferSize,
+ BOOL WantAdjust)
+{
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ COORD dwWindowSize;
+ BOOL NeedAdjust = FALSE;
+
+ if (GetConsoleScreenBufferInfo(g_hConOut, &csbi))
+ {
+ /*
+ * A buffer resize will fail if the current console window does
+ * not lie completely within that buffer. To avoid this, we might
+ * have to move and possibly shrink the window.
+ */
+ if (csbi.srWindow.Right >= dwBufferSize.X)
+ {
+ dwWindowSize.X = SRWIDTH(csbi.srWindow);
+ if (dwWindowSize.X > dwBufferSize.X)
+ dwWindowSize.X = dwBufferSize.X;
+ csbi.srWindow.Right = dwBufferSize.X - 1;
+ csbi.srWindow.Left = dwBufferSize.X - dwWindowSize.X;
+ NeedAdjust = TRUE;
+ }
+ if (csbi.srWindow.Bottom >= dwBufferSize.Y)
+ {
+ dwWindowSize.Y = SRHEIGHT(csbi.srWindow);
+ if (dwWindowSize.Y > dwBufferSize.Y)
+ dwWindowSize.Y = dwBufferSize.Y;
+ csbi.srWindow.Bottom = dwBufferSize.Y - 1;
+ csbi.srWindow.Top = dwBufferSize.Y - dwWindowSize.Y;
+ NeedAdjust = TRUE;
+ }
+ if (NeedAdjust && WantAdjust)
+ {
+ if (!SetConsoleWindowInfo(g_hConOut, TRUE, &csbi.srWindow))
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+typedef struct ConsoleBufferStruct
+{
+ BOOL IsValid;
+ CONSOLE_SCREEN_BUFFER_INFO Info;
+ PCHAR_INFO Buffer;
+ COORD BufferSize;
+} ConsoleBuffer;
+
+/*
+ * SaveConsoleBuffer()
+ * Description:
+ * Saves important information about the console buffer, including the
+ * actual buffer contents. The saved information is suitable for later
+ * restoration by RestoreConsoleBuffer().
+ * Returns:
+ * TRUE if all information was saved; FALSE otherwise
+ * If FALSE, still sets cb->IsValid if buffer characteristics were saved.
+ */
+ static BOOL
+SaveConsoleBuffer(
+ ConsoleBuffer *cb)
+{
+ DWORD NumCells;
+ COORD BufferCoord;
+ SMALL_RECT ReadRegion;
+ WORD Y, Y_incr;
+
+ if (cb == NULL)
+ return FALSE;
+
+ if (!GetConsoleScreenBufferInfo(g_hConOut, &cb->Info))
+ {
+ cb->IsValid = FALSE;
+ return FALSE;
+ }
+ cb->IsValid = TRUE;
+
+ /*
+ * Allocate a buffer large enough to hold the entire console screen
+ * buffer. If this ConsoleBuffer structure has already been initialized
+ * with a buffer of the correct size, then just use that one.
+ */
+ if (!cb->IsValid || cb->Buffer == NULL ||
+ cb->BufferSize.X != cb->Info.dwSize.X ||
+ cb->BufferSize.Y != cb->Info.dwSize.Y)
+ {
+ cb->BufferSize.X = cb->Info.dwSize.X;
+ cb->BufferSize.Y = cb->Info.dwSize.Y;
+ NumCells = cb->BufferSize.X * cb->BufferSize.Y;
+ if (cb->Buffer != NULL)
+ vim_free(cb->Buffer);
+ cb->Buffer = (PCHAR_INFO)alloc(NumCells * sizeof(CHAR_INFO));
+ if (cb->Buffer == NULL)
+ return FALSE;
+ }
+
+ /*
+ * We will now copy the console screen buffer into our buffer.
+ * ReadConsoleOutput() seems to be limited as far as how much you
+ * can read at a time. Empirically, this number seems to be about
+ * 12000 cells (rows * columns). Start at position (0, 0) and copy
+ * in chunks until it is all copied. The chunks will all have the
+ * same horizontal characteristics, so initialize them now. The
+ * height of each chunk will be (12000 / width).
+ */
+ BufferCoord.X = 0;
+ ReadRegion.Left = 0;
+ ReadRegion.Right = cb->Info.dwSize.X - 1;
+ Y_incr = 12000 / cb->Info.dwSize.X;
+ for (Y = 0; Y < cb->BufferSize.Y; Y += Y_incr)
+ {
+ /*
+ * Read into position (0, Y) in our buffer.
+ */
+ BufferCoord.Y = Y;
+ /*
+ * Read the region whose top left corner is (0, Y) and whose bottom
+ * right corner is (width - 1, Y + Y_incr - 1). This should define
+ * a region of size width by Y_incr. Don't worry if this region is
+ * too large for the remaining buffer; it will be cropped.
+ */
+ ReadRegion.Top = Y;
+ ReadRegion.Bottom = Y + Y_incr - 1;
+ if (!ReadConsoleOutput(g_hConOut, /* output handle */
+ cb->Buffer, /* our buffer */
+ cb->BufferSize, /* dimensions of our buffer */
+ BufferCoord, /* offset in our buffer */
+ &ReadRegion)) /* region to save */
+ {
+ vim_free(cb->Buffer);
+ cb->Buffer = NULL;
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ * RestoreConsoleBuffer()
+ * Description:
+ * Restores important information about the console buffer, including the
+ * actual buffer contents, if desired. The information to restore is in
+ * the same format used by SaveConsoleBuffer().
+ * Returns:
+ * TRUE on success
+ */
+ static BOOL
+RestoreConsoleBuffer(
+ ConsoleBuffer *cb,
+ BOOL RestoreScreen)
+{
+ COORD BufferCoord;
+ SMALL_RECT WriteRegion;
+
+ if (cb == NULL || !cb->IsValid)
+ return FALSE;
+
+ /*
+ * Before restoring the buffer contents, clear the current buffer, and
+ * restore the cursor position and window information. Doing this now
+ * prevents old buffer contents from "flashing" onto the screen.
+ */
+ if (RestoreScreen)
+ ClearConsoleBuffer(cb->Info.wAttributes);
+
+ FitConsoleWindow(cb->Info.dwSize, TRUE);
+ if (!SetConsoleScreenBufferSize(g_hConOut, cb->Info.dwSize))
+ return FALSE;
+ if (!SetConsoleTextAttribute(g_hConOut, cb->Info.wAttributes))
+ return FALSE;
+
+ if (!RestoreScreen)
+ {
+ /*
+ * No need to restore the screen buffer contents, so we're done.
+ */
+ return TRUE;
+ }
+
+ if (!SetConsoleCursorPosition(g_hConOut, cb->Info.dwCursorPosition))
+ return FALSE;
+ if (!SetConsoleWindowInfo(g_hConOut, TRUE, &cb->Info.srWindow))
+ return FALSE;
+
+ /*
+ * Restore the screen buffer contents.
+ */
+ if (cb->Buffer != NULL)
+ {
+ BufferCoord.X = 0;
+ BufferCoord.Y = 0;
+ WriteRegion.Left = 0;
+ WriteRegion.Top = 0;
+ WriteRegion.Right = cb->Info.dwSize.X - 1;
+ WriteRegion.Bottom = cb->Info.dwSize.Y - 1;
+ if (!WriteConsoleOutput(g_hConOut, /* output handle */
+ cb->Buffer, /* our buffer */
+ cb->BufferSize, /* dimensions of our buffer */
+ BufferCoord, /* offset in our buffer */
+ &WriteRegion)) /* region to restore */
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+#ifdef FEAT_RESTORE_ORIG_SCREEN
+static ConsoleBuffer g_cbOrig = { 0 };
+#endif
+static ConsoleBuffer g_cbNonTermcap = { 0 };
+static ConsoleBuffer g_cbTermcap = { 0 };
+
+#ifdef FEAT_TITLE
+#ifdef __BORLANDC__
+typedef HWND (__stdcall *GETCONSOLEWINDOWPROC)(VOID);
+#else
+typedef WINBASEAPI HWND (WINAPI *GETCONSOLEWINDOWPROC)(VOID);
+#endif
+char g_szOrigTitle[256] = { 0 };
+HWND g_hWnd = NULL; /* also used in os_mswin.c */
+static HICON g_hOrigIconSmall = NULL;
+static HICON g_hOrigIcon = NULL;
+static HICON g_hVimIcon = NULL;
+static BOOL g_fCanChangeIcon = FALSE;
+
+/* ICON* are not defined in VC++ 4.0 */
+#ifndef ICON_SMALL
+#define ICON_SMALL 0
+#endif
+#ifndef ICON_BIG
+#define ICON_BIG 1
+#endif
+/*
+ * GetConsoleIcon()
+ * Description:
+ * Attempts to retrieve the small icon and/or the big icon currently in
+ * use by a given window.
+ * Returns:
+ * TRUE on success
+ */
+ static BOOL
+GetConsoleIcon(
+ HWND hWnd,
+ HICON *phIconSmall,
+ HICON *phIcon)
+{
+ if (hWnd == NULL)
+ return FALSE;
+
+ if (phIconSmall != NULL)
+ {
+ *phIconSmall = (HICON) SendMessage(hWnd, WM_GETICON,
+ (WPARAM) ICON_SMALL, (LPARAM) 0);
+ }
+ if (phIcon != NULL)
+ {
+ *phIcon = (HICON) SendMessage(hWnd, WM_GETICON,
+ (WPARAM) ICON_BIG, (LPARAM) 0);
+ }
+ return TRUE;
+}
+
+/*
+ * SetConsoleIcon()
+ * Description:
+ * Attempts to change the small icon and/or the big icon currently in
+ * use by a given window.
+ * Returns:
+ * TRUE on success
+ */
+ static BOOL
+SetConsoleIcon(
+ HWND hWnd,
+ HICON hIconSmall,
+ HICON hIcon)
+{
+ HICON hPrevIconSmall;
+ HICON hPrevIcon;
+
+ if (hWnd == NULL)
+ return FALSE;
+
+ if (hIconSmall != NULL)
+ {
+ hPrevIconSmall = (HICON) SendMessage(hWnd, WM_SETICON,
+ (WPARAM) ICON_SMALL, (LPARAM) hIconSmall);
+ }
+ if (hIcon != NULL)
+ {
+ hPrevIcon = (HICON) SendMessage(hWnd, WM_SETICON,
+ (WPARAM) ICON_BIG, (LPARAM) hIcon);
+ }
+ return TRUE;
+}
+
+/*
+ * SaveConsoleTitleAndIcon()
+ * Description:
+ * Saves the current console window title in g_szOrigTitle, for later
+ * restoration. Also, attempts to obtain a handle to the console window,
+ * and use it to save the small and big icons currently in use by the
+ * console window. This is not always possible on some versions of Windows;
+ * nor is it possible when running Vim remotely using Telnet (since the
+ * console window the user sees is owned by a remote process).
+ */
+ static void
+SaveConsoleTitleAndIcon(void)
+{
+ GETCONSOLEWINDOWPROC GetConsoleWindowProc;
+
+ /* Save the original title. */
+ if (!GetConsoleTitle(g_szOrigTitle, sizeof(g_szOrigTitle)))
+ return;
+
+ /*
+ * Obtain a handle to the console window using GetConsoleWindow() from
+ * KERNEL32.DLL; we need to handle in order to change the window icon.
+ * This function only exists on NT-based Windows, starting with Windows
+ * 2000. On older operating systems, we can't change the window icon
+ * anyway.
+ */
+ if ((GetConsoleWindowProc = (GETCONSOLEWINDOWPROC)
+ GetProcAddress(GetModuleHandle("KERNEL32.DLL"),
+ "GetConsoleWindow")) != NULL)
+ {
+ g_hWnd = (*GetConsoleWindowProc)();
+ }
+ if (g_hWnd == NULL)
+ return;
+
+ /* Save the original console window icon. */
+ GetConsoleIcon(g_hWnd, &g_hOrigIconSmall, &g_hOrigIcon);
+ if (g_hOrigIconSmall == NULL || g_hOrigIcon == NULL)
+ return;
+
+ /* Extract the first icon contained in the Vim executable. */
+ g_hVimIcon = ExtractIcon(NULL, exe_name, 0);
+ if (g_hVimIcon != NULL)
+ g_fCanChangeIcon = TRUE;
+}
+#endif
+
+static int g_fWindInitCalled = FALSE;
+static int g_fTermcapMode = FALSE;
+static CONSOLE_CURSOR_INFO g_cci;
+static DWORD g_cmodein = 0;
+static DWORD g_cmodeout = 0;
+
+/*
+ * non-GUI version of mch_init().
+ */
+ void
+mch_init()
+{
+#ifndef FEAT_RESTORE_ORIG_SCREEN
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+#endif
+#ifndef __MINGW32__
+ extern int _fmode;
+#endif
+
+ /* Let critical errors result in a failure, not in a dialog box. Required
+ * for the timestamp test to work on removed floppies. */
+ SetErrorMode(SEM_FAILCRITICALERRORS);
+
+ _fmode = O_BINARY; /* we do our own CR-LF translation */
+ out_flush();
+
+ /* Obtain handles for the standard Console I/O devices */
+ if (read_cmd_fd == 0)
+ g_hConIn = GetStdHandle(STD_INPUT_HANDLE);
+ else
+ create_conin();
+ g_hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
+
+#ifdef FEAT_RESTORE_ORIG_SCREEN
+ /* Save the initial console buffer for later restoration */
+ SaveConsoleBuffer(&g_cbOrig);
+ g_attrCurrent = g_attrDefault = g_cbOrig.Info.wAttributes;
+#else
+ /* Get current text attributes */
+ GetConsoleScreenBufferInfo(g_hConOut, &csbi);
+ g_attrCurrent = g_attrDefault = csbi.wAttributes;
+#endif
+ if (cterm_normal_fg_color == 0)
+ cterm_normal_fg_color = (g_attrCurrent & 0xf) + 1;
+ if (cterm_normal_bg_color == 0)
+ cterm_normal_bg_color = ((g_attrCurrent >> 4) & 0xf) + 1;
+
+ /* set termcap codes to current text attributes */
+ update_tcap(g_attrCurrent);
+
+ GetConsoleCursorInfo(g_hConOut, &g_cci);
+ GetConsoleMode(g_hConIn, &g_cmodein);
+ GetConsoleMode(g_hConOut, &g_cmodeout);
+
+#ifdef FEAT_TITLE
+ SaveConsoleTitleAndIcon();
+ /*
+ * Set both the small and big icons of the console window to Vim's icon.
+ * Note that Vim presently only has one size of icon (32x32), but it
+ * automatically gets scaled down to 16x16 when setting the small icon.
+ */
+ if (g_fCanChangeIcon)
+ SetConsoleIcon(g_hWnd, g_hVimIcon, g_hVimIcon);
+#endif
+
+ ui_get_shellsize();
+
+#ifdef MCH_WRITE_DUMP
+ fdDump = fopen("dump", "wt");
+
+ if (fdDump)
+ {
+ time_t t;
+
+ time(&t);
+ fputs(ctime(&t), fdDump);
+ fflush(fdDump);
+ }
+#endif
+
+ g_fWindInitCalled = TRUE;
+
+#ifdef FEAT_MOUSE
+ g_fMouseAvail = GetSystemMetrics(SM_MOUSEPRESENT);
+#endif
+
+#ifdef FEAT_CLIPBOARD
+ clip_init(TRUE);
+
+ /*
+ * Vim's own clipboard format recognises whether the text is char, line, or
+ * rectangular block. Only useful for copying between two Vims.
+ * "VimClipboard" was used for previous versions, using the first
+ * character to specify MCHAR, MLINE or MBLOCK.
+ */
+ clip_star.format = RegisterClipboardFormat("VimClipboard2");
+ clip_star.format_raw = RegisterClipboardFormat("VimRawBytes");
+#endif
+
+ /* This will be NULL on anything but NT 4.0 */
+ s_pfnGetConsoleKeyboardLayoutName =
+ (PFNGCKLN) GetProcAddress(GetModuleHandle("kernel32.dll"),
+ "GetConsoleKeyboardLayoutNameA");
+}
+
+/*
+ * non-GUI version of mch_exit().
+ * Shut down and exit with status `r'
+ * Careful: mch_exit() may be called before mch_init()!
+ */
+ void
+mch_exit(int r)
+{
+ stoptermcap();
+
+ if (g_fWindInitCalled)
+ settmode(TMODE_COOK);
+
+ ml_close_all(TRUE); /* remove all memfiles */
+
+ if (g_fWindInitCalled)
+ {
+#ifdef FEAT_TITLE
+ mch_restore_title(3);
+ /*
+ * Restore both the small and big icons of the console window to
+ * what they were at startup. Don't do this when the window is
+ * closed, Vim would hang here.
+ */
+ if (g_fCanChangeIcon && !g_fForceExit)
+ SetConsoleIcon(g_hWnd, g_hOrigIconSmall, g_hOrigIcon);
+#endif
+
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ {
+ time_t t;
+
+ time(&t);
+ fputs(ctime(&t), fdDump);
+ fclose(fdDump);
+ }
+ fdDump = NULL;
+#endif
+ }
+
+ SetConsoleCursorInfo(g_hConOut, &g_cci);
+ SetConsoleMode(g_hConIn, g_cmodein);
+ SetConsoleMode(g_hConOut, g_cmodeout);
+
+#ifdef DYNAMIC_GETTEXT
+ dyn_libintl_end();
+#endif
+
+ exit(r);
+}
+#endif /* !FEAT_GUI_W32 */
+
+
+/*
+ * Do we have an interactive window?
+ */
+ int
+mch_check_win(
+ int argc,
+ char **argv)
+{
+ get_exe_name();
+
+#ifdef FEAT_GUI_W32
+ return OK; /* GUI always has a tty */
+#else
+ if (isatty(1))
+ return OK;
+ return FAIL;
+#endif
+}
+
+
+/*
+ * fname_case(): Set the case of the file name, if it already exists.
+ * When "len" is > 0, also expand short to long filenames.
+ */
+ void
+fname_case(
+ char_u *name,
+ int len)
+{
+ char szTrueName[_MAX_PATH + 2];
+ char *ptrue, *ptruePrev;
+ char *porig, *porigPrev;
+ int flen;
+ WIN32_FIND_DATA fb;
+ HANDLE hFind;
+ int c;
+
+ flen = (name != NULL) ? (int)STRLEN(name) : 0;
+ if (flen == 0 || flen > _MAX_PATH)
+ return;
+
+ slash_adjust(name);
+
+ /* Build the new name in szTrueName[] one component at a time. */
+ porig = name;
+ ptrue = szTrueName;
+
+ if (isalpha(porig[0]) && porig[1] == ':')
+ {
+ /* copy leading drive letter */
+ *ptrue++ = *porig++;
+ *ptrue++ = *porig++;
+ *ptrue = NUL; /* in case nothing follows */
+ }
+
+ while (*porig != NUL)
+ {
+ /* copy \ characters */
+ while (*porig == psepc)
+ *ptrue++ = *porig++;
+
+ ptruePrev = ptrue;
+ porigPrev = porig;
+ while (*porig != NUL && *porig != psepc)
+ {
+#ifdef FEAT_MBYTE
+ int l;
+
+ if (enc_dbcs)
+ {
+ l = (*mb_ptr2len_check)(porig);
+ while (--l >= 0)
+ *ptrue++ = *porig++;
+ }
+ else
+#endif
+ *ptrue++ = *porig++;
+ }
+ *ptrue = NUL;
+
+ /* Skip "", "." and "..". */
+ if (ptrue > ptruePrev
+ && (ptruePrev[0] != '.'
+ || (ptruePrev[1] != NUL
+ && (ptruePrev[1] != '.' || ptruePrev[2] != NUL)))
+ && (hFind = FindFirstFile(szTrueName, &fb))
+ != INVALID_HANDLE_VALUE)
+ {
+ c = *porig;
+ *porig = NUL;
+
+ /* Only use the match when it's the same name (ignoring case) or
+ * expansion is allowed and there is a match with the short name
+ * and there is enough room. */
+ if (_stricoll(porigPrev, fb.cFileName) == 0
+ || (len > 0
+ && (_stricoll(porigPrev, fb.cAlternateFileName) == 0
+ && (int)(ptruePrev - szTrueName)
+ + (int)strlen(fb.cFileName) < len)))
+ {
+ STRCPY(ptruePrev, fb.cFileName);
+
+ /* Look for exact match and prefer it if found. Must be a
+ * long name, otherwise there would be only one match. */
+ while (FindNextFile(hFind, &fb))
+ {
+ if (*fb.cAlternateFileName != NUL
+ && (strcoll(porigPrev, fb.cFileName) == 0
+ || (len > 0
+ && (_stricoll(porigPrev,
+ fb.cAlternateFileName) == 0
+ && (int)(ptruePrev - szTrueName)
+ + (int)strlen(fb.cFileName) < len))))
+ {
+ STRCPY(ptruePrev, fb.cFileName);
+ break;
+ }
+ }
+ }
+ FindClose(hFind);
+ *porig = c;
+ ptrue = ptruePrev + strlen(ptruePrev);
+ }
+ }
+
+ STRCPY(name, szTrueName);
+}
+
+
+/*
+ * Insert user name in s[len].
+ */
+ int
+mch_get_user_name(
+ char_u *s,
+ int len)
+{
+ char szUserName[MAX_COMPUTERNAME_LENGTH + 1];
+ DWORD cch = sizeof szUserName;
+
+ if (GetUserName(szUserName, &cch))
+ {
+ STRNCPY(s, szUserName, len);
+ return OK;
+ }
+ s[0] = NUL;
+ return FAIL;
+}
+
+
+/*
+ * Insert host name in s[len].
+ */
+ void
+mch_get_host_name(
+ char_u *s,
+ int len)
+{
+ DWORD cch = len;
+
+ if (!GetComputerName(s, &cch))
+ {
+ STRNCPY(s, "PC (Win32 Vim)", len);
+ s[len - 1] = NUL; /* make sure it's terminated */
+ }
+}
+
+
+/*
+ * return process ID
+ */
+ long
+mch_get_pid()
+{
+ return (long)GetCurrentProcessId();
+}
+
+
+/*
+ * Get name of current directory into buffer 'buf' of length 'len' bytes.
+ * Return OK for success, FAIL for failure.
+ */
+ int
+mch_dirname(
+ char_u *buf,
+ int len)
+{
+ /*
+ * Originally this was:
+ * return (getcwd(buf, len) != NULL ? OK : FAIL);
+ * But the Win32s known bug list says that getcwd() doesn't work
+ * so use the Win32 system call instead. <Negri>
+ */
+#ifdef FEAT_MBYTE
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+ WCHAR wbuf[_MAX_PATH + 1];
+
+ if (GetCurrentDirectoryW(_MAX_PATH, wbuf) != 0)
+ {
+ char_u *p = ucs2_to_enc(wbuf, NULL);
+
+ if (p != NULL)
+ {
+ STRNCPY(buf, p, len - 1);
+ buf[len - 1] = NUL;
+ vim_free(p);
+ return OK;
+ }
+ }
+ /* Retry with non-wide function (for Windows 98). */
+ }
+#endif
+ return (GetCurrentDirectory(len, buf) != 0 ? OK : FAIL);
+}
+
+/*
+ * get file permissions for `name'
+ * -1 : error
+ * else FILE_ATTRIBUTE_* defined in winnt.h
+ */
+ long
+mch_getperm(
+ char_u *name)
+{
+#ifdef FEAT_MBYTE
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+ WCHAR *p = enc_to_ucs2(name, NULL);
+ long n;
+
+ if (p != NULL)
+ {
+ n = (long)GetFileAttributesW(p);
+ vim_free(p);
+ if (n >= 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return n;
+ /* Retry with non-wide function (for Windows 98). */
+ }
+ }
+#endif
+ return (long)GetFileAttributes((char *)name);
+}
+
+
+/*
+ * set file permission for `name' to `perm'
+ */
+ int
+mch_setperm(
+ char_u *name,
+ long perm)
+{
+ perm |= FILE_ATTRIBUTE_ARCHIVE; /* file has changed, set archive bit */
+#ifdef FEAT_MBYTE
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+ WCHAR *p = enc_to_ucs2(name, NULL);
+ long n;
+
+ if (p != NULL)
+ {
+ n = (long)SetFileAttributesW(p, perm);
+ vim_free(p);
+ if (n || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return n ? OK : FAIL;
+ /* Retry with non-wide function (for Windows 98). */
+ }
+ }
+#endif
+ return SetFileAttributes((char *)name, perm) ? OK : FAIL;
+}
+
+/*
+ * Set hidden flag for "name".
+ */
+ void
+mch_hide(char_u *name)
+{
+ int perm;
+#ifdef FEAT_MBYTE
+ WCHAR *p = NULL;
+
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ p = enc_to_ucs2(name, NULL);
+#endif
+
+#ifdef FEAT_MBYTE
+ if (p != NULL)
+ {
+ perm = GetFileAttributesW(p);
+ if (perm < 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ /* Retry with non-wide function (for Windows 98). */
+ vim_free(p);
+ p = NULL;
+ }
+ }
+ if (p == NULL)
+#endif
+ perm = GetFileAttributes((char *)name);
+ if (perm >= 0)
+ {
+ perm |= FILE_ATTRIBUTE_HIDDEN;
+#ifdef FEAT_MBYTE
+ if (p != NULL)
+ {
+ if (SetFileAttributesW(p, perm) == 0
+ && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ /* Retry with non-wide function (for Windows 98). */
+ vim_free(p);
+ p = NULL;
+ }
+ }
+ if (p == NULL)
+#endif
+ SetFileAttributes((char *)name, perm);
+ }
+#ifdef FEAT_MBYTE
+ vim_free(p);
+#endif
+}
+
+/*
+ * return TRUE if "name" is a directory
+ * return FALSE if "name" is not a directory or upon error
+ */
+ int
+mch_isdir(char_u *name)
+{
+ int f = mch_getperm(name);
+
+ if (f == -1)
+ return FALSE; /* file does not exist at all */
+
+ return (f & FILE_ATTRIBUTE_DIRECTORY) != 0;
+}
+
+/*
+ * Return TRUE if file or directory "name" is writable (not readonly).
+ * Strange semantics of Win32: a readonly directory is writable, but you can't
+ * delete a file. Let's say this means it is writable.
+ */
+ int
+mch_writable(char_u *name)
+{
+ int perm = mch_getperm(name);
+
+ return (perm != -1 && (!(perm & FILE_ATTRIBUTE_READONLY)
+ || (perm & FILE_ATTRIBUTE_DIRECTORY)));
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return 1 if "name" can be executed, 0 if not.
+ * Return -1 if unknown.
+ */
+ int
+mch_can_exe(char_u *name)
+{
+ return executable_exists((char *)name);
+}
+#endif
+
+/*
+ * Check what "name" is:
+ * NODE_NORMAL: file or directory (or doesn't exist)
+ * NODE_WRITABLE: writable device, socket, fifo, etc.
+ * NODE_OTHER: non-writable things
+ */
+ int
+mch_nodetype(char_u *name)
+{
+ HANDLE hFile;
+ int type;
+
+ hFile = CreateFile(name, /* file name */
+ GENERIC_WRITE, /* access mode */
+ 0, /* share mode */
+ NULL, /* security descriptor */
+ OPEN_EXISTING, /* creation disposition */
+ 0, /* file attributes */
+ NULL); /* handle to template file */
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return NODE_NORMAL;
+
+ type = GetFileType(hFile);
+ CloseHandle(hFile);
+ if (type == FILE_TYPE_CHAR)
+ return NODE_WRITABLE;
+ if (type == FILE_TYPE_DISK)
+ return NODE_NORMAL;
+ return NODE_OTHER;
+}
+
+#ifdef HAVE_ACL
+struct my_acl
+{
+ PSECURITY_DESCRIPTOR pSecurityDescriptor;
+ PSID pSidOwner;
+ PSID pSidGroup;
+ PACL pDacl;
+ PACL pSacl;
+};
+#endif
+
+/*
+ * Return a pointer to the ACL of file "fname" in allocated memory.
+ * Return NULL if the ACL is not available for whatever reason.
+ */
+ vim_acl_T
+mch_get_acl(fname)
+ char_u *fname;
+{
+#ifndef HAVE_ACL
+ return (vim_acl_T)NULL;
+#else
+ struct my_acl *p = NULL;
+
+ /* This only works on Windows NT and 2000. */
+ if (g_PlatformId == VER_PLATFORM_WIN32_NT && advapi_lib != NULL)
+ {
+ p = (struct my_acl *)alloc_clear((unsigned)sizeof(struct my_acl));
+ if (p != NULL)
+ {
+ if (pGetNamedSecurityInfo(
+ (LPTSTR)fname, // Abstract filename
+ SE_FILE_OBJECT, // File Object
+ // Retrieve the entire security descriptor.
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION |
+ SACL_SECURITY_INFORMATION,
+ &p->pSidOwner, // Ownership information.
+ &p->pSidGroup, // Group membership.
+ &p->pDacl, // Discretionary information.
+ &p->pSacl, // For auditing purposes.
+ &p->pSecurityDescriptor
+ ) != ERROR_SUCCESS)
+ {
+ mch_free_acl((vim_acl_T)p);
+ p = NULL;
+ }
+ }
+ }
+
+ return (vim_acl_T)p;
+#endif
+}
+
+/*
+ * Set the ACL of file "fname" to "acl" (unless it's NULL).
+ * Errors are ignored.
+ * This must only be called with "acl" equal to what mch_get_acl() returned.
+ */
+ void
+mch_set_acl(fname, acl)
+ char_u *fname;
+ vim_acl_T acl;
+{
+#ifdef HAVE_ACL
+ struct my_acl *p = (struct my_acl *)acl;
+
+ if (p != NULL && advapi_lib != NULL)
+ (void)pSetNamedSecurityInfo(
+ (LPTSTR)fname, // Abstract filename
+ SE_FILE_OBJECT, // File Object
+ // Retrieve the entire security descriptor.
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION |
+ SACL_SECURITY_INFORMATION,
+ p->pSidOwner, // Ownership information.
+ p->pSidGroup, // Group membership.
+ p->pDacl, // Discretionary information.
+ p->pSacl // For auditing purposes.
+ );
+#endif
+}
+
+ void
+mch_free_acl(acl)
+ vim_acl_T acl;
+{
+#ifdef HAVE_ACL
+ struct my_acl *p = (struct my_acl *)acl;
+
+ if (p != NULL)
+ {
+ LocalFree(p->pSecurityDescriptor); // Free the memory just in case
+ vim_free(p);
+ }
+#endif
+}
+
+#ifndef FEAT_GUI_W32
+
+/*
+ * handler for ctrl-break, ctrl-c interrupts, and fatal events.
+ */
+ static BOOL WINAPI
+handler_routine(
+ DWORD dwCtrlType)
+{
+ switch (dwCtrlType)
+ {
+ case CTRL_C_EVENT:
+ if (ctrl_c_interrupts)
+ g_fCtrlCPressed = TRUE;
+ return TRUE;
+
+ case CTRL_BREAK_EVENT:
+ g_fCBrkPressed = TRUE;
+ return TRUE;
+
+ /* fatal events: shut down gracefully */
+ case CTRL_CLOSE_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ windgoto((int)Rows - 1, 0);
+ g_fForceExit = TRUE;
+
+ sprintf((char *)IObuff, _("Vim: Caught %s event\n"),
+ (dwCtrlType == CTRL_CLOSE_EVENT
+ ? _("close")
+ : dwCtrlType == CTRL_LOGOFF_EVENT
+ ? _("logoff")
+ : _("shutdown")));
+#ifdef DEBUG
+ OutputDebugString(IObuff);
+#endif
+
+ preserve_exit(); /* output IObuff, preserve files and exit */
+
+ return TRUE; /* not reached */
+
+ default:
+ return FALSE;
+ }
+}
+
+
+/*
+ * set the tty in (raw) ? "raw" : "cooked" mode
+ */
+ void
+mch_settmode(
+ int tmode)
+{
+ DWORD cmodein;
+ DWORD cmodeout;
+ BOOL bEnableHandler;
+
+ GetConsoleMode(g_hConIn, &cmodein);
+ GetConsoleMode(g_hConOut, &cmodeout);
+ if (tmode == TMODE_RAW)
+ {
+ cmodein &= ~(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT |
+ ENABLE_ECHO_INPUT);
+#ifdef FEAT_MOUSE
+ if (g_fMouseActive)
+ cmodein |= ENABLE_MOUSE_INPUT;
+#endif
+ cmodeout &= ~(ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
+ bEnableHandler = TRUE;
+ }
+ else /* cooked */
+ {
+ cmodein |= (ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT |
+ ENABLE_ECHO_INPUT);
+ cmodeout |= (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
+ bEnableHandler = FALSE;
+ }
+ SetConsoleMode(g_hConIn, cmodein);
+ SetConsoleMode(g_hConOut, cmodeout);
+ SetConsoleCtrlHandler(handler_routine, bEnableHandler);
+
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ {
+ fprintf(fdDump, "mch_settmode(%s, in = %x, out = %x)\n",
+ tmode == TMODE_RAW ? "raw" :
+ tmode == TMODE_COOK ? "cooked" : "normal",
+ cmodein, cmodeout);
+ fflush(fdDump);
+ }
+#endif
+}
+
+
+/*
+ * Get the size of the current window in `Rows' and `Columns'
+ * Return OK when size could be determined, FAIL otherwise.
+ */
+ int
+mch_get_shellsize()
+{
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+ if (!g_fTermcapMode && g_cbTermcap.IsValid)
+ {
+ /*
+ * For some reason, we are trying to get the screen dimensions
+ * even though we are not in termcap mode. The 'Rows' and 'Columns'
+ * variables are really intended to mean the size of Vim screen
+ * while in termcap mode.
+ */
+ Rows = g_cbTermcap.Info.dwSize.Y;
+ Columns = g_cbTermcap.Info.dwSize.X;
+ }
+ else if (GetConsoleScreenBufferInfo(g_hConOut, &csbi))
+ {
+ Rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
+ Columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
+ }
+ else
+ {
+ Rows = 25;
+ Columns = 80;
+ }
+ return OK;
+}
+
+/*
+ * Set a console window to `xSize' * `ySize'
+ */
+ static void
+ResizeConBufAndWindow(
+ HANDLE hConsole,
+ int xSize,
+ int ySize)
+{
+ CONSOLE_SCREEN_BUFFER_INFO csbi; /* hold current console buffer info */
+ SMALL_RECT srWindowRect; /* hold the new console size */
+ COORD coordScreen;
+
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ {
+ fprintf(fdDump, "ResizeConBufAndWindow(%d, %d)\n", xSize, ySize);
+ fflush(fdDump);
+ }
+#endif
+
+ /* get the largest size we can size the console window to */
+ coordScreen = GetLargestConsoleWindowSize(hConsole);
+
+ /* define the new console window size and scroll position */
+ srWindowRect.Left = srWindowRect.Top = (SHORT) 0;
+ srWindowRect.Right = (SHORT) (min(xSize, coordScreen.X) - 1);
+ srWindowRect.Bottom = (SHORT) (min(ySize, coordScreen.Y) - 1);
+
+ if (GetConsoleScreenBufferInfo(g_hConOut, &csbi))
+ {
+ int sx, sy;
+
+ sx = csbi.srWindow.Right - csbi.srWindow.Left + 1;
+ sy = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
+ if (sy < ySize || sx < xSize)
+ {
+ /*
+ * Increasing number of lines/columns, do buffer first.
+ * Use the maximal size in x and y direction.
+ */
+ if (sy < ySize)
+ coordScreen.Y = ySize;
+ else
+ coordScreen.Y = sy;
+ if (sx < xSize)
+ coordScreen.X = xSize;
+ else
+ coordScreen.X = sx;
+ SetConsoleScreenBufferSize(hConsole, coordScreen);
+ }
+ }
+
+ if (!SetConsoleWindowInfo(g_hConOut, TRUE, &srWindowRect))
+ {
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ {
+ fprintf(fdDump, "SetConsoleWindowInfo failed: %lx\n",
+ GetLastError());
+ fflush(fdDump);
+ }
+#endif
+ }
+
+ /* define the new console buffer size */
+ coordScreen.X = xSize;
+ coordScreen.Y = ySize;
+
+ if (!SetConsoleScreenBufferSize(hConsole, coordScreen))
+ {
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ {
+ fprintf(fdDump, "SetConsoleScreenBufferSize failed: %lx\n",
+ GetLastError());
+ fflush(fdDump);
+ }
+#endif
+ }
+}
+
+
+/*
+ * Set the console window to `Rows' * `Columns'
+ */
+ void
+mch_set_shellsize()
+{
+ COORD coordScreen;
+
+ /* Don't change window size while still starting up */
+ if (suppress_winsize != 0)
+ {
+ suppress_winsize = 2;
+ return;
+ }
+
+ if (term_console)
+ {
+ coordScreen = GetLargestConsoleWindowSize(g_hConOut);
+
+ /* Clamp Rows and Columns to reasonable values */
+ if (Rows > coordScreen.Y)
+ Rows = coordScreen.Y;
+ if (Columns > coordScreen.X)
+ Columns = coordScreen.X;
+
+ ResizeConBufAndWindow(g_hConOut, Columns, Rows);
+ }
+}
+
+/*
+ * Rows and/or Columns has changed.
+ */
+ void
+mch_new_shellsize()
+{
+ set_scroll_region(0, 0, Columns - 1, Rows - 1);
+}
+
+
+/*
+ * Called when started up, to set the winsize that was delayed.
+ */
+ void
+mch_set_winsize_now()
+{
+ if (suppress_winsize == 2)
+ {
+ suppress_winsize = 0;
+ mch_set_shellsize();
+ shell_resized();
+ }
+ suppress_winsize = 0;
+}
+#endif /* FEAT_GUI_W32 */
+
+
+
+#if defined(FEAT_GUI_W32) || defined(PROTO)
+
+/*
+ * Specialised version of system() for Win32 GUI mode.
+ * This version proceeds as follows:
+ * 1. Create a console window for use by the subprocess
+ * 2. Run the subprocess (it gets the allocated console by default)
+ * 3. Wait for the subprocess to terminate and get its exit code
+ * 4. Prompt the user to press a key to close the console window
+ */
+ static int
+mch_system(char *cmd, int options)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ DWORD ret = 0;
+ HWND hwnd = GetFocus();
+
+ si.cb = sizeof(si);
+ si.lpReserved = NULL;
+ si.lpDesktop = NULL;
+ si.lpTitle = NULL;
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ /*
+ * It's nicer to run a filter command in a minimized window, but in
+ * Windows 95 this makes the command MUCH slower. We can't do it under
+ * Win32s either as it stops the synchronous spawn workaround working.
+ */
+ if ((options & SHELL_DOOUT) && !mch_windows95() && !gui_is_win32s())
+ si.wShowWindow = SW_SHOWMINIMIZED;
+ else
+ si.wShowWindow = SW_SHOWNORMAL;
+ si.cbReserved2 = 0;
+ si.lpReserved2 = NULL;
+
+ /* There is a strange error on Windows 95 when using "c:\\command.com".
+ * When the "c:\\" is left out it works OK...? */
+ if (mch_windows95()
+ && (STRNICMP(cmd, "c:/command.com", 14) == 0
+ || STRNICMP(cmd, "c:\\command.com", 14) == 0))
+ cmd += 3;
+
+ /* Now, run the command */
+ CreateProcess(NULL, /* Executable name */
+ cmd, /* Command to execute */
+ NULL, /* Process security attributes */
+ NULL, /* Thread security attributes */
+ FALSE, /* Inherit handles */
+ CREATE_DEFAULT_ERROR_MODE | /* Creation flags */
+ CREATE_NEW_CONSOLE,
+ NULL, /* Environment */
+ NULL, /* Current directory */
+ &si, /* Startup information */
+ &pi); /* Process information */
+
+
+ /* Wait for the command to terminate before continuing */
+ if (g_PlatformId != VER_PLATFORM_WIN32s)
+ {
+#ifdef FEAT_GUI
+ int delay = 1;
+
+ /* Keep updating the window while waiting for the shell to finish. */
+ for (;;)
+ {
+ MSG msg;
+
+ if (PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ if (WaitForSingleObject(pi.hProcess, delay) != WAIT_TIMEOUT)
+ break;
+
+ /* We start waiting for a very short time and then increase it, so
+ * that we respond quickly when the process is quick, and don't
+ * consume too much overhead when it's slow. */
+ if (delay < 50)
+ delay += 10;
+ }
+#else
+ WaitForSingleObject(pi.hProcess, INFINITE);
+#endif
+
+ /* Get the command exit code */
+ GetExitCodeProcess(pi.hProcess, &ret);
+ }
+ else
+ {
+ /*
+ * This ugly code is the only quick way of performing
+ * a synchronous spawn under Win32s. Yuk.
+ */
+ num_windows = 0;
+ EnumWindows(win32ssynch_cb, 0);
+ old_num_windows = num_windows;
+ do
+ {
+ Sleep(1000);
+ num_windows = 0;
+ EnumWindows(win32ssynch_cb, 0);
+ } while (num_windows == old_num_windows);
+ ret = 0;
+ }
+
+ /* Close the handles to the subprocess, so that it goes away */
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ /* Try to get input focus back. Doesn't always work though. */
+ PostMessage(hwnd, WM_SETFOCUS, 0, 0);
+
+ return ret;
+}
+#else
+
+# define mch_system(c, o) system(c)
+
+#endif
+
+/*
+ * Either execute a command by calling the shell or start a new shell
+ */
+ int
+mch_call_shell(
+ char_u *cmd,
+ int options) /* SHELL_*, see vim.h */
+{
+ int x = 0;
+ int tmode = cur_tmode;
+#ifdef FEAT_TITLE
+ char szShellTitle[512];
+
+ /* Change the title to reflect that we are in a subshell. */
+ if (GetConsoleTitle(szShellTitle, sizeof(szShellTitle) - 4) > 0)
+ {
+ if (cmd == NULL)
+ strcat(szShellTitle, " :sh");
+ else
+ {
+ strcat(szShellTitle, " - !");
+ if ((strlen(szShellTitle) + strlen(cmd) < sizeof(szShellTitle)))
+ strcat(szShellTitle, cmd);
+ }
+ mch_settitle(szShellTitle, NULL);
+ }
+#endif
+
+ out_flush();
+
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ {
+ fprintf(fdDump, "mch_call_shell(\"%s\", %d)\n", cmd, options);
+ fflush(fdDump);
+ }
+#endif
+
+ /*
+ * Catch all deadly signals while running the external command, because a
+ * CTRL-C, Ctrl-Break or illegal instruction might otherwise kill us.
+ */
+ signal(SIGINT, SIG_IGN);
+#if defined(__GNUC__) && !defined(__MINGW32__)
+ signal(SIGKILL, SIG_IGN);
+#else
+ signal(SIGBREAK, SIG_IGN);
+#endif
+ signal(SIGILL, SIG_IGN);
+ signal(SIGFPE, SIG_IGN);
+ signal(SIGSEGV, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+ signal(SIGABRT, SIG_IGN);
+
+ if (options & SHELL_COOKED)
+ settmode(TMODE_COOK); /* set to normal mode */
+
+ if (cmd == NULL)
+ {
+ x = mch_system(p_sh, options);
+ }
+ else
+ {
+ /* we use "command" or "cmd" to start the shell; slow but easy */
+ char_u *newcmd;
+
+ newcmd = lalloc((long_u) (
+#ifdef FEAT_GUI_W32
+ STRLEN(vimrun_path) +
+#endif
+ STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10), TRUE);
+ if (newcmd != NULL)
+ {
+ char_u *cmdbase = (*cmd == '"' ? cmd + 1 : cmd);
+
+ if ((STRNICMP(cmdbase, "start", 5) == 0) && vim_iswhite(cmdbase[5]))
+ {
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ si.cb = sizeof(si);
+ si.lpReserved = NULL;
+ si.lpDesktop = NULL;
+ si.lpTitle = NULL;
+ si.dwFlags = 0;
+ si.cbReserved2 = 0;
+ si.lpReserved2 = NULL;
+
+ cmdbase = skipwhite(cmdbase + 5);
+ if ((STRNICMP(cmdbase, "/min", 4) == 0)
+ && vim_iswhite(cmdbase[4]))
+ {
+ cmdbase = skipwhite(cmdbase + 4);
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_SHOWMINNOACTIVE;
+ }
+
+ /* When the command is in double quotes, but 'shellxquote' is
+ * empty, keep the double quotes around the command.
+ * Otherwise remove the double quotes, they aren't needed
+ * here, because we don't use a shell to run the command. */
+ if (*cmd == '"' && *p_sxq == NUL)
+ {
+ newcmd[0] = '"';
+ STRCPY(newcmd + 1, cmdbase);
+ }
+ else
+ {
+ STRCPY(newcmd, cmdbase);
+ if (*cmd == '"' && *newcmd != NUL)
+ newcmd[STRLEN(newcmd) - 1] = NUL;
+ }
+
+ /*
+ * Now, start the command as a process, so that it doesn't
+ * inherit our handles which causes unpleasant dangling swap
+ * files if we exit before the spawned process
+ */
+ if (CreateProcess (NULL, // Executable name
+ newcmd, // Command to execute
+ NULL, // Process security attributes
+ NULL, // Thread security attributes
+ FALSE, // Inherit handles
+ CREATE_NEW_CONSOLE, // Creation flags
+ NULL, // Environment
+ NULL, // Current directory
+ &si, // Startup information
+ &pi)) // Process information
+ x = 0;
+ else
+ {
+ x = -1;
+#ifdef FEAT_GUI_W32
+ EMSG(_("E371: Command not found"));
+#endif
+ }
+ /* Close the handles to the subprocess, so that it goes away */
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ }
+ else
+ {
+#if defined(FEAT_GUI_W32)
+ if (need_vimrun_warning)
+ {
+ MessageBox(NULL,
+ _("VIMRUN.EXE not found in your $PATH.\n"
+ "External commands will not pause after completion.\n"
+ "See :help win32-vimrun for more information."),
+ _("Vim Warning"),
+ MB_ICONWARNING);
+ need_vimrun_warning = FALSE;
+ }
+ if (!s_dont_use_vimrun)
+ /* Use vimrun to execute the command. It opens a console
+ * window, which can be closed without killing Vim. */
+ sprintf((char *)newcmd, "%s%s%s %s %s",
+ vimrun_path,
+ (msg_silent != 0 || (options & SHELL_DOOUT))
+ ? "-s " : "",
+ p_sh, p_shcf, cmd);
+ else
+#endif
+ sprintf((char *)newcmd, "%s %s %s", p_sh, p_shcf, cmd);
+ x = mch_system((char *)newcmd, options);
+ }
+ vim_free(newcmd);
+ }
+ }
+
+ if (tmode == TMODE_RAW)
+ settmode(TMODE_RAW); /* set to raw mode */
+
+ /* Print the return value, unless "vimrun" was used. */
+ if (x != 0 && !(options & SHELL_SILENT) && !emsg_silent
+#if defined(FEAT_GUI_W32)
+ && ((options & SHELL_DOOUT) || s_dont_use_vimrun)
+#endif
+ )
+ {
+ smsg(_("shell returned %d"), x);
+ msg_putchar('\n');
+ }
+#ifdef FEAT_TITLE
+ resettitle();
+#endif
+
+ signal(SIGINT, SIG_DFL);
+#if defined(__GNUC__) && !defined(__MINGW32__)
+ signal(SIGKILL, SIG_DFL);
+#else
+ signal(SIGBREAK, SIG_DFL);
+#endif
+ signal(SIGILL, SIG_DFL);
+ signal(SIGFPE, SIG_DFL);
+ signal(SIGSEGV, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGABRT, SIG_DFL);
+
+ return x;
+}
+
+
+#ifndef FEAT_GUI_W32
+
+/*
+ * Start termcap mode
+ */
+ static void
+termcap_mode_start(void)
+{
+ DWORD cmodein;
+
+ if (g_fTermcapMode)
+ return;
+
+ SaveConsoleBuffer(&g_cbNonTermcap);
+
+ if (g_cbTermcap.IsValid)
+ {
+ /*
+ * We've been in termcap mode before. Restore certain screen
+ * characteristics, including the buffer size and the window
+ * size. Since we will be redrawing the screen, we don't need
+ * to restore the actual contents of the buffer.
+ */
+ RestoreConsoleBuffer(&g_cbTermcap, FALSE);
+ SetConsoleWindowInfo(g_hConOut, TRUE, &g_cbTermcap.Info.srWindow);
+ Rows = g_cbTermcap.Info.dwSize.Y;
+ Columns = g_cbTermcap.Info.dwSize.X;
+ }
+ else
+ {
+ /*
+ * This is our first time entering termcap mode. Clear the console
+ * screen buffer, and resize the buffer to match the current window
+ * size. We will use this as the size of our editing environment.
+ */
+ ClearConsoleBuffer(g_attrCurrent);
+ ResizeConBufAndWindow(g_hConOut, Columns, Rows);
+ }
+
+#ifdef FEAT_TITLE
+ resettitle();
+#endif
+
+ GetConsoleMode(g_hConIn, &cmodein);
+#ifdef FEAT_MOUSE
+ if (g_fMouseActive)
+ cmodein |= ENABLE_MOUSE_INPUT;
+ else
+ cmodein &= ~ENABLE_MOUSE_INPUT;
+#endif
+ cmodein |= ENABLE_WINDOW_INPUT;
+ SetConsoleMode(g_hConIn, cmodein);
+
+ redraw_later_clear();
+ g_fTermcapMode = TRUE;
+}
+
+
+/*
+ * End termcap mode
+ */
+ static void
+termcap_mode_end(void)
+{
+ DWORD cmodein;
+ ConsoleBuffer *cb;
+ COORD coord;
+ DWORD dwDummy;
+
+ if (!g_fTermcapMode)
+ return;
+
+ SaveConsoleBuffer(&g_cbTermcap);
+
+ GetConsoleMode(g_hConIn, &cmodein);
+ cmodein &= ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
+ SetConsoleMode(g_hConIn, cmodein);
+
+#ifdef FEAT_RESTORE_ORIG_SCREEN
+ cb = exiting ? &g_cbOrig : &g_cbNonTermcap;
+#else
+ cb = &g_cbNonTermcap;
+#endif
+ RestoreConsoleBuffer(cb, p_rs);
+ SetConsoleCursorInfo(g_hConOut, &g_cci);
+
+ if (p_rs || exiting)
+ {
+ /*
+ * Clear anything that happens to be on the current line.
+ */
+ coord.X = 0;
+ coord.Y = (SHORT) (p_rs ? cb->Info.dwCursorPosition.Y : (Rows - 1));
+ FillConsoleOutputCharacter(g_hConOut, ' ',
+ cb->Info.dwSize.X, coord, &dwDummy);
+ /*
+ * The following is just for aesthetics. If we are exiting without
+ * restoring the screen, then we want to have a prompt string
+ * appear at the bottom line. However, the command interpreter
+ * seems to always advance the cursor one line before displaying
+ * the prompt string, which causes the screen to scroll. To
+ * counter this, move the cursor up one line before exiting.
+ */
+ if (exiting && !p_rs)
+ coord.Y--;
+ /*
+ * Position the cursor at the leftmost column of the desired row.
+ */
+ SetConsoleCursorPosition(g_hConOut, coord);
+ }
+
+ g_fTermcapMode = FALSE;
+}
+#endif /* FEAT_GUI_W32 */
+
+
+#ifdef FEAT_GUI_W32
+ void
+mch_write(
+ char_u *s,
+ int len)
+{
+ /* never used */
+}
+
+#else
+
+/*
+ * clear `n' chars, starting from `coord'
+ */
+ static void
+clear_chars(
+ COORD coord,
+ DWORD n)
+{
+ DWORD dwDummy;
+
+ FillConsoleOutputCharacter(g_hConOut, ' ', n, coord, &dwDummy);
+ FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, n, coord, &dwDummy);
+}
+
+
+/*
+ * Clear the screen
+ */
+ static void
+clear_screen(void)
+{
+ g_coord.X = g_coord.Y = 0;
+ clear_chars(g_coord, Rows * Columns);
+}
+
+
+/*
+ * Clear to end of display
+ */
+ static void
+clear_to_end_of_display(void)
+{
+ clear_chars(g_coord, (Rows - g_coord.Y - 1)
+ * Columns + (Columns - g_coord.X));
+}
+
+
+/*
+ * Clear to end of line
+ */
+ static void
+clear_to_end_of_line(void)
+{
+ clear_chars(g_coord, Columns - g_coord.X);
+}
+
+
+/*
+ * Scroll the scroll region up by `cLines' lines
+ */
+ static void
+scroll(
+ unsigned cLines)
+{
+ COORD oldcoord = g_coord;
+
+ gotoxy(g_srScrollRegion.Left + 1, g_srScrollRegion.Top + 1);
+ delete_lines(cLines);
+
+ g_coord = oldcoord;
+}
+
+
+/*
+ * Set the scroll region
+ */
+ static void
+set_scroll_region(
+ unsigned left,
+ unsigned top,
+ unsigned right,
+ unsigned bottom)
+{
+ if (left >= right
+ || top >= bottom
+ || right > (unsigned) Columns - 1
+ || bottom > (unsigned) Rows - 1)
+ return;
+
+ g_srScrollRegion.Left = left;
+ g_srScrollRegion.Top = top;
+ g_srScrollRegion.Right = right;
+ g_srScrollRegion.Bottom = bottom;
+}
+
+
+/*
+ * Insert `cLines' lines at the current cursor position
+ */
+ static void
+insert_lines(
+ unsigned cLines)
+{
+ SMALL_RECT source;
+ COORD dest;
+ CHAR_INFO fill;
+
+ dest.X = 0;
+ dest.Y = g_coord.Y + cLines;
+
+ source.Left = 0;
+ source.Top = g_coord.Y;
+ source.Right = g_srScrollRegion.Right;
+ source.Bottom = g_srScrollRegion.Bottom - cLines;
+
+ fill.Char.AsciiChar = ' ';
+ fill.Attributes = g_attrCurrent;
+
+ ScrollConsoleScreenBuffer(g_hConOut, &source, NULL, dest, &fill);
+
+ /* Here we have to deal with a win32 console flake: If the scroll
+ * region looks like abc and we scroll c to a and fill with d we get
+ * cbd... if we scroll block c one line at a time to a, we get cdd...
+ * vim expects cdd consistently... So we have to deal with that
+ * here... (this also occurs scrolling the same way in the other
+ * direction). */
+
+ if (source.Bottom < dest.Y)
+ {
+ COORD coord;
+
+ coord.X = 0;
+ coord.Y = source.Bottom;
+ clear_chars(coord, Columns * (dest.Y - source.Bottom));
+ }
+}
+
+
+/*
+ * Delete `cLines' lines at the current cursor position
+ */
+ static void
+delete_lines(
+ unsigned cLines)
+{
+ SMALL_RECT source;
+ COORD dest;
+ CHAR_INFO fill;
+ int nb;
+
+ dest.X = 0;
+ dest.Y = g_coord.Y;
+
+ source.Left = 0;
+ source.Top = g_coord.Y + cLines;
+ source.Right = g_srScrollRegion.Right;
+ source.Bottom = g_srScrollRegion.Bottom;
+
+ fill.Char.AsciiChar = ' ';
+ fill.Attributes = g_attrCurrent;
+
+ ScrollConsoleScreenBuffer(g_hConOut, &source, NULL, dest, &fill);
+
+ /* Here we have to deal with a win32 console flake: If the scroll
+ * region looks like abc and we scroll c to a and fill with d we get
+ * cbd... if we scroll block c one line at a time to a, we get cdd...
+ * vim expects cdd consistently... So we have to deal with that
+ * here... (this also occurs scrolling the same way in the other
+ * direction). */
+
+ nb = dest.Y + (source.Bottom - source.Top) + 1;
+
+ if (nb < source.Top)
+ {
+ COORD coord;
+
+ coord.X = 0;
+ coord.Y = nb;
+ clear_chars(coord, Columns * (source.Top - nb));
+ }
+}
+
+
+/*
+ * Set the cursor position
+ */
+ static void
+gotoxy(
+ unsigned x,
+ unsigned y)
+{
+ if (x < 1 || x > (unsigned)Columns || y < 1 || y > (unsigned)Rows)
+ return;
+
+ /* external cursor coords are 1-based; internal are 0-based */
+ g_coord.X = x - 1;
+ g_coord.Y = y - 1;
+ SetConsoleCursorPosition(g_hConOut, g_coord);
+}
+
+
+/*
+ * Set the current text attribute = (foreground | background)
+ * See ../doc/os_win32.txt for the numbers.
+ */
+ static void
+textattr(
+ WORD wAttr)
+{
+ g_attrCurrent = wAttr;
+
+ SetConsoleTextAttribute(g_hConOut, wAttr);
+}
+
+
+ static void
+textcolor(
+ WORD wAttr)
+{
+ g_attrCurrent = (g_attrCurrent & 0xf0) + wAttr;
+
+ SetConsoleTextAttribute(g_hConOut, g_attrCurrent);
+}
+
+
+ static void
+textbackground(
+ WORD wAttr)
+{
+ g_attrCurrent = (g_attrCurrent & 0x0f) + (wAttr << 4);
+
+ SetConsoleTextAttribute(g_hConOut, g_attrCurrent);
+}
+
+
+/*
+ * restore the default text attribute (whatever we started with)
+ */
+ static void
+normvideo()
+{
+ textattr(g_attrDefault);
+}
+
+
+static WORD g_attrPreStandout = 0;
+
+/*
+ * Make the text standout, by brightening it
+ */
+ static void
+standout(void)
+{
+ g_attrPreStandout = g_attrCurrent;
+ textattr((WORD) (g_attrCurrent|FOREGROUND_INTENSITY|BACKGROUND_INTENSITY));
+}
+
+
+/*
+ * Turn off standout mode
+ */
+ static void
+standend()
+{
+ if (g_attrPreStandout)
+ {
+ textattr(g_attrPreStandout);
+ g_attrPreStandout = 0;
+ }
+}
+
+
+/*
+ * Set normal fg/bg color, based on T_ME. Called whem t_me has been set.
+ */
+ void
+mch_set_normal_colors()
+{
+ char_u *p;
+ int n;
+
+ cterm_normal_fg_color = (g_attrDefault & 0xf) + 1;
+ cterm_normal_bg_color = ((g_attrDefault >> 4) & 0xf) + 1;
+ if (T_ME[0] == ESC && T_ME[1] == '|')
+ {
+ p = T_ME + 2;
+ n = getdigits(&p);
+ if (*p == 'm' && n > 0)
+ {
+ cterm_normal_fg_color = (n & 0xf) + 1;
+ cterm_normal_bg_color = ((n >> 4) & 0xf) + 1;
+ }
+ }
+}
+
+
+/*
+ * visual bell: flash the screen
+ */
+ static void
+visual_bell()
+{
+ COORD coordOrigin = {0, 0};
+ WORD attrFlash = ~g_attrCurrent & 0xff;
+
+ DWORD dwDummy;
+ LPWORD oldattrs = (LPWORD)alloc(Rows * Columns * sizeof(WORD));
+
+ if (oldattrs == NULL)
+ return;
+ ReadConsoleOutputAttribute(g_hConOut, oldattrs, Rows * Columns,
+ coordOrigin, &dwDummy);
+ FillConsoleOutputAttribute(g_hConOut, attrFlash, Rows * Columns,
+ coordOrigin, &dwDummy);
+
+ Sleep(15); /* wait for 15 msec */
+ WriteConsoleOutputAttribute(g_hConOut, oldattrs, Rows * Columns,
+ coordOrigin, &dwDummy);
+ vim_free(oldattrs);
+}
+
+
+/*
+ * Make the cursor visible or invisible
+ */
+ static void
+cursor_visible(
+ BOOL fVisible)
+{
+ s_cursor_visible = fVisible;
+#ifdef MCH_CURSOR_SHAPE
+ mch_update_cursor();
+#endif
+}
+
+
+/*
+ * write `cchToWrite' characters in `pchBuf' to the screen
+ * Returns the number of characters actually written (at least one).
+ */
+ static BOOL
+write_chars(
+ LPCSTR pchBuf,
+ DWORD cchToWrite)
+{
+ COORD coord = g_coord;
+ DWORD written;
+
+ FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cchToWrite,
+ coord, &written);
+ /* When writing fails or didn't write a single character, pretend one
+ * character was written, otherwise we get stuck. */
+ if (WriteConsoleOutputCharacter(g_hConOut, pchBuf, cchToWrite,
+ coord, &written) == 0
+ || written == 0)
+ written = 1;
+
+ g_coord.X += (SHORT) written;
+
+ while (g_coord.X > g_srScrollRegion.Right)
+ {
+ g_coord.X -= (SHORT) Columns;
+ if (g_coord.Y < g_srScrollRegion.Bottom)
+ g_coord.Y++;
+ }
+
+ gotoxy(g_coord.X + 1, g_coord.Y + 1);
+
+ return written;
+}
+
+
+/*
+ * mch_write(): write the output buffer to the screen, translating ESC
+ * sequences into calls to console output routines.
+ */
+ void
+mch_write(
+ char_u *s,
+ int len)
+{
+ s[len] = NUL;
+
+ if (!term_console)
+ {
+ write(1, s, (unsigned)len);
+ return;
+ }
+
+ /* translate ESC | sequences into faked bios calls */
+ while (len--)
+ {
+ /* optimization: use one single write_chars for runs of text,
+ * rather than once per character It ain't curses, but it helps. */
+ DWORD prefix = strcspn(s, "\n\r\b\a\033");
+
+ if (p_wd)
+ {
+ WaitForChar(p_wd);
+ if (prefix != 0)
+ prefix = 1;
+ }
+
+ if (prefix != 0)
+ {
+ DWORD nWritten;
+
+ nWritten = write_chars(s, prefix);
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ {
+ fputc('>', fdDump);
+ fwrite(s, sizeof(char_u), nWritten, fdDump);
+ fputs("<\n", fdDump);
+ }
+#endif
+ len -= (nWritten - 1);
+ s += nWritten;
+ }
+ else if (s[0] == '\n')
+ {
+ /* \n, newline: go to the beginning of the next line or scroll */
+ if (g_coord.Y == g_srScrollRegion.Bottom)
+ {
+ scroll(1);
+ gotoxy(g_srScrollRegion.Left + 1, g_srScrollRegion.Bottom + 1);
+ }
+ else
+ {
+ gotoxy(g_srScrollRegion.Left + 1, g_coord.Y + 2);
+ }
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ fputs("\\n\n", fdDump);
+#endif
+ s++;
+ }
+ else if (s[0] == '\r')
+ {
+ /* \r, carriage return: go to beginning of line */
+ gotoxy(g_srScrollRegion.Left+1, g_coord.Y + 1);
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ fputs("\\r\n", fdDump);
+#endif
+ s++;
+ }
+ else if (s[0] == '\b')
+ {
+ /* \b, backspace: move cursor one position left */
+ if (g_coord.X > g_srScrollRegion.Left)
+ g_coord.X--;
+ else if (g_coord.Y > g_srScrollRegion.Top)
+ {
+ g_coord.X = g_srScrollRegion.Right;
+ g_coord.Y--;
+ }
+ gotoxy(g_coord.X + 1, g_coord.Y + 1);
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ fputs("\\b\n", fdDump);
+#endif
+ s++;
+ }
+ else if (s[0] == '\a')
+ {
+ /* \a, bell */
+ MessageBeep(0xFFFFFFFF);
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ fputs("\\a\n", fdDump);
+#endif
+ s++;
+ }
+ else if (s[0] == ESC && len >= 3-1 && s[1] == '|')
+ {
+#ifdef MCH_WRITE_DUMP
+ char_u* old_s = s;
+#endif
+ char_u* p;
+ int arg1 = 0, arg2 = 0;
+
+ switch (s[2])
+ {
+ /* one or two numeric arguments, separated by ';' */
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ p = s + 2;
+ arg1 = getdigits(&p); /* no check for length! */
+ if (p > s + len)
+ break;
+
+ if (*p == ';')
+ {
+ ++p;
+ arg2 = getdigits(&p); /* no check for length! */
+ if (p > s + len)
+ break;
+
+ if (*p == 'H')
+ gotoxy(arg2, arg1);
+ else if (*p == 'r')
+ set_scroll_region(0, arg1 - 1, Columns - 1, arg2 - 1);
+ }
+ else if (*p == 'A')
+ {
+ /* move cursor up arg1 lines in same column */
+ gotoxy(g_coord.X + 1,
+ max(g_srScrollRegion.Top, g_coord.Y - arg1) + 1);
+ }
+ else if (*p == 'C')
+ {
+ /* move cursor right arg1 columns in same line */
+ gotoxy(min(g_srScrollRegion.Right, g_coord.X + arg1) + 1,
+ g_coord.Y + 1);
+ }
+ else if (*p == 'H')
+ {
+ gotoxy(1, arg1);
+ }
+ else if (*p == 'L')
+ {
+ insert_lines(arg1);
+ }
+ else if (*p == 'm')
+ {
+ if (arg1 == 0)
+ normvideo();
+ else
+ textattr((WORD) arg1);
+ }
+ else if (*p == 'f')
+ {
+ textcolor((WORD) arg1);
+ }
+ else if (*p == 'b')
+ {
+ textbackground((WORD) arg1);
+ }
+ else if (*p == 'M')
+ {
+ delete_lines(arg1);
+ }
+
+ len -= p - s;
+ s = p + 1;
+ break;
+
+
+ /* Three-character escape sequences */
+
+ case 'A':
+ /* move cursor up one line in same column */
+ gotoxy(g_coord.X + 1,
+ max(g_srScrollRegion.Top, g_coord.Y - 1) + 1);
+ goto got3;
+
+ case 'B':
+ visual_bell();
+ goto got3;
+
+ case 'C':
+ /* move cursor right one column in same line */
+ gotoxy(min(g_srScrollRegion.Right, g_coord.X + 1) + 1,
+ g_coord.Y + 1);
+ goto got3;
+
+ case 'E':
+ termcap_mode_end();
+ goto got3;
+
+ case 'F':
+ standout();
+ goto got3;
+
+ case 'f':
+ standend();
+ goto got3;
+
+ case 'H':
+ gotoxy(1, 1);
+ goto got3;
+
+ case 'j':
+ clear_to_end_of_display();
+ goto got3;
+
+ case 'J':
+ clear_screen();
+ goto got3;
+
+ case 'K':
+ clear_to_end_of_line();
+ goto got3;
+
+ case 'L':
+ insert_lines(1);
+ goto got3;
+
+ case 'M':
+ delete_lines(1);
+ goto got3;
+
+ case 'S':
+ termcap_mode_start();
+ goto got3;
+
+ case 'V':
+ cursor_visible(TRUE);
+ goto got3;
+
+ case 'v':
+ cursor_visible(FALSE);
+ goto got3;
+
+ got3:
+ s += 3;
+ len -= 2;
+ }
+
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ {
+ fputs("ESC | ", fdDump);
+ fwrite(old_s + 2, sizeof(char_u), s - old_s - 2, fdDump);
+ fputc('\n', fdDump);
+ }
+#endif
+ }
+ else
+ {
+ /* Write a single character */
+ DWORD nWritten;
+
+ nWritten = write_chars(s, 1);
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ {
+ fputc('>', fdDump);
+ fwrite(s, sizeof(char_u), nWritten, fdDump);
+ fputs("<\n", fdDump);
+ }
+#endif
+
+ len -= (nWritten - 1);
+ s += nWritten;
+ }
+ }
+
+#ifdef MCH_WRITE_DUMP
+ if (fdDump)
+ fflush(fdDump);
+#endif
+}
+
+#endif /* FEAT_GUI_W32 */
+
+
+/*
+ * Delay for half a second.
+ */
+ void
+mch_delay(
+ long msec,
+ int ignoreinput)
+{
+#ifdef FEAT_GUI_W32
+ Sleep((int)msec); /* never wait for input */
+#else
+ if (ignoreinput)
+ Sleep((int)msec);
+ else
+ WaitForChar(msec);
+#endif
+}
+
+
+/*
+ * this version of remove is not scared by a readonly (backup) file
+ * Return 0 for success, -1 for failure.
+ */
+ int
+mch_remove(char_u *name)
+{
+#ifdef FEAT_MBYTE
+ WCHAR *wn = NULL;
+ int n;
+
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+ wn = enc_to_ucs2(name, NULL);
+ if (wn != NULL)
+ {
+ SetFileAttributesW(wn, FILE_ATTRIBUTE_NORMAL);
+ n = DeleteFileW(wn) ? 0 : -1;
+ vim_free(wn);
+ if (n == 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return n;
+ /* Retry with non-wide function (for Windows 98). */
+ }
+ }
+#endif
+ SetFileAttributes(name, FILE_ATTRIBUTE_NORMAL);
+ return DeleteFile(name) ? 0 : -1;
+}
+
+
+/*
+ * check for an "interrupt signal": CTRL-break or CTRL-C
+ */
+ void
+mch_breakcheck()
+{
+#ifndef FEAT_GUI_W32 /* never used */
+ if (g_fCtrlCPressed || g_fCBrkPressed)
+ {
+ g_fCtrlCPressed = g_fCBrkPressed = FALSE;
+ got_int = TRUE;
+ }
+#endif
+}
+
+
+/*
+ * How much memory is available?
+ * Return sum of available physical and page file memory.
+ */
+ long_u
+mch_avail_mem(
+ int special)
+{
+ MEMORYSTATUS ms;
+
+ ms.dwLength = sizeof(MEMORYSTATUS);
+ GlobalMemoryStatus(&ms);
+ return (long_u) (ms.dwAvailPhys + ms.dwAvailPageFile);
+}
+
+#ifdef FEAT_MBYTE
+/*
+ * Same code as below, but with wide functions and no comments.
+ * Return 0 for success, non-zero for failure.
+ */
+ int
+mch_wrename(WCHAR *wold, WCHAR *wnew)
+{
+ WCHAR *p;
+ int i;
+ WCHAR szTempFile[_MAX_PATH + 1];
+ WCHAR szNewPath[_MAX_PATH + 1];
+ HANDLE hf;
+
+ if (!mch_windows95())
+ {
+ p = wold;
+ for (i = 0; wold[i] != NUL; ++i)
+ if ((wold[i] == '/' || wold[i] == '\\' || wold[i] == ':')
+ && wold[i + 1] != 0)
+ p = wold + i + 1;
+ if ((int)(wold + i - p) < 8 || p[6] != '~')
+ return (MoveFileW(wold, wnew) == 0);
+ }
+
+ if (GetFullPathNameW(wnew, _MAX_PATH, szNewPath, &p) == 0 || p == NULL)
+ return -1;
+ *p = NUL;
+
+ if (GetTempFileNameW(szNewPath, L"VIM", 0, szTempFile) == 0)
+ return -2;
+
+ if (!DeleteFileW(szTempFile))
+ return -3;
+
+ if (!MoveFileW(wold, szTempFile))
+ return -4;
+
+ if ((hf = CreateFileW(wold, GENERIC_WRITE, 0, NULL, CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
+ return -5;
+ if (!CloseHandle(hf))
+ return -6;
+
+ if (!MoveFileW(szTempFile, wnew))
+ {
+ (void)MoveFileW(szTempFile, wold);
+ return -7;
+ }
+
+ DeleteFileW(szTempFile);
+
+ if (!DeleteFileW(wold))
+ return -8;
+
+ return 0;
+}
+#endif
+
+
+/*
+ * mch_rename() works around a bug in rename (aka MoveFile) in
+ * Windows 95: rename("foo.bar", "foo.bar~") will generate a
+ * file whose short file name is "FOO.BAR" (its long file name will
+ * be correct: "foo.bar~"). Because a file can be accessed by
+ * either its SFN or its LFN, "foo.bar" has effectively been
+ * renamed to "foo.bar", which is not at all what was wanted. This
+ * seems to happen only when renaming files with three-character
+ * extensions by appending a suffix that does not include ".".
+ * Windows NT gets it right, however, with an SFN of "FOO~1.BAR".
+ *
+ * There is another problem, which isn't really a bug but isn't right either:
+ * When renaming "abcdef~1.txt" to "abcdef~1.txt~", the short name can be
+ * "abcdef~1.txt" again. This has been reported on Windows NT 4.0 with
+ * service pack 6. Doesn't seem to happen on Windows 98.
+ *
+ * Like rename(), returns 0 upon success, non-zero upon failure.
+ * Should probably set errno appropriately when errors occur.
+ */
+ int
+mch_rename(
+ const char *pszOldFile,
+ const char *pszNewFile)
+{
+ char szTempFile[_MAX_PATH+1];
+ char szNewPath[_MAX_PATH+1];
+ char *pszFilePart;
+ HANDLE hf;
+#ifdef FEAT_MBYTE
+ WCHAR *wold = NULL;
+ WCHAR *wnew = NULL;
+ int retval = -1;
+
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+ wold = enc_to_ucs2((char_u *)pszOldFile, NULL);
+ wnew = enc_to_ucs2((char_u *)pszNewFile, NULL);
+ if (wold != NULL && wnew != NULL)
+ retval = mch_wrename(wold, wnew);
+ vim_free(wold);
+ vim_free(wnew);
+ if (retval == 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return retval;
+ /* Retry with non-wide function (for Windows 98). */
+ }
+#endif
+
+ /*
+ * No need to play tricks if not running Windows 95, unless the file name
+ * contains a "~" as the seventh character.
+ */
+ if (!mch_windows95())
+ {
+ pszFilePart = (char *)gettail((char_u *)pszOldFile);
+ if (STRLEN(pszFilePart) < 8 || pszFilePart[6] != '~')
+ return rename(pszOldFile, pszNewFile);
+ }
+
+ /* Get base path of new file name. Undocumented feature: If pszNewFile is
+ * a directory, no error is returned and pszFilePart will be NULL. */
+ if (GetFullPathName(pszNewFile, _MAX_PATH, szNewPath, &pszFilePart) == 0
+ || pszFilePart == NULL)
+ return -1;
+ *pszFilePart = NUL;
+
+ /* Get (and create) a unique temporary file name in directory of new file */
+ if (GetTempFileName(szNewPath, "VIM", 0, szTempFile) == 0)
+ return -2;
+
+ /* blow the temp file away */
+ if (!DeleteFile(szTempFile))
+ return -3;
+
+ /* rename old file to the temp file */
+ if (!MoveFile(pszOldFile, szTempFile))
+ return -4;
+
+ /* now create an empty file called pszOldFile; this prevents the operating
+ * system using pszOldFile as an alias (SFN) if we're renaming within the
+ * same directory. For example, we're editing a file called
+ * filename.asc.txt by its SFN, filena~1.txt. If we rename filena~1.txt
+ * to filena~1.txt~ (i.e., we're making a backup while writing it), the
+ * SFN for filena~1.txt~ will be filena~1.txt, by default, which will
+ * cause all sorts of problems later in buf_write. So, we create an empty
+ * file called filena~1.txt and the system will have to find some other
+ * SFN for filena~1.txt~, such as filena~2.txt
+ */
+ if ((hf = CreateFile(pszOldFile, GENERIC_WRITE, 0, NULL, CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
+ return -5;
+ if (!CloseHandle(hf))
+ return -6;
+
+ /* rename the temp file to the new file */
+ if (!MoveFile(szTempFile, pszNewFile))
+ {
+ /* Renaming failed. Rename the file back to its old name, so that it
+ * looks like nothing happened. */
+ (void)MoveFile(szTempFile, pszOldFile);
+
+ return -7;
+ }
+
+ /* Seems to be left around on Novell filesystems */
+ DeleteFile(szTempFile);
+
+ /* finally, remove the empty old file */
+ if (!DeleteFile(pszOldFile))
+ return -8;
+
+ return 0; /* success */
+}
+
+/*
+ * Get the default shell for the current hardware platform
+ */
+ char *
+default_shell()
+{
+ char* psz = NULL;
+
+ PlatformId();
+
+ if (g_PlatformId == VER_PLATFORM_WIN32_NT) /* Windows NT */
+ psz = "cmd.exe";
+ else if (g_PlatformId == VER_PLATFORM_WIN32_WINDOWS) /* Windows 95 */
+ psz = "command.com";
+
+ return psz;
+}
+
+/*
+ * mch_access() extends access() to do more detailed check on network drives.
+ * Returns 0 if file "n" has access rights according to "p", -1 otherwise.
+ */
+ int
+mch_access(char *n, int p)
+{
+ HANDLE hFile;
+ DWORD am;
+ int retval = -1; /* default: fail */
+#ifdef FEAT_MBYTE
+ WCHAR *wn = NULL;
+
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ wn = enc_to_ucs2(n, NULL);
+#endif
+
+ if (mch_isdir(n))
+ {
+ char TempName[_MAX_PATH + 16] = "";
+#ifdef FEAT_MBYTE
+ WCHAR TempNameW[_MAX_PATH + 16] = L"";
+#endif
+
+ if (p & R_OK)
+ {
+ /* Read check is performed by seeing if we can do a find file on
+ * the directory for any file. */
+#ifdef FEAT_MBYTE
+ if (wn != NULL)
+ {
+ int i;
+ WIN32_FIND_DATAW d;
+
+ for (i = 0; i < _MAX_PATH && wn[i] != 0; ++i)
+ TempNameW[i] = wn[i];
+ if (TempNameW[i - 1] != '\\' && TempNameW[i - 1] != '/')
+ TempNameW[i++] = '\\';
+ TempNameW[i++] = '*';
+ TempNameW[i++] = 0;
+
+ hFile = FindFirstFileW(TempNameW, &d);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ goto getout;
+
+ /* Retry with non-wide function (for Windows 98). */
+ vim_free(wn);
+ wn = NULL;
+ }
+ else
+ (void)FindClose(hFile);
+ }
+ if (wn == NULL)
+#endif
+ {
+ char *pch;
+ WIN32_FIND_DATA d;
+
+ STRNCPY(TempName, n, _MAX_PATH);
+ pch = TempName + STRLEN(TempName) - 1;
+ if (*pch != '\\' && *pch != '/')
+ *++pch = '\\';
+ *++pch = '*';
+ *++pch = NUL;
+
+ hFile = FindFirstFile(TempName, &d);
+ if (hFile == INVALID_HANDLE_VALUE)
+ goto getout;
+ (void)FindClose(hFile);
+ }
+ }
+
+ if (p & W_OK)
+ {
+ /* Trying to create a temporary file in the directory should catch
+ * directories on read-only network shares. However, in
+ * directories whose ACL allows writes but denies deletes will end
+ * up keeping the temporary file :-(. */
+#ifdef FEAT_MBYTE
+ if (wn != NULL)
+ {
+ if (!GetTempFileNameW(wn, L"VIM", 0, TempNameW))
+ {
+ if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ goto getout;
+
+ /* Retry with non-wide function (for Windows 98). */
+ vim_free(wn);
+ wn = NULL;
+ }
+ else
+ DeleteFileW(TempNameW);
+ }
+ if (wn == NULL)
+#endif
+ {
+ if (!GetTempFileName(n, "VIM", 0, TempName))
+ goto getout;
+ mch_remove((char_u *)TempName);
+ }
+ }
+ }
+ else
+ {
+ /* Trying to open the file for the required access does ACL, read-only
+ * network share, and file attribute checks. */
+ am = ((p & W_OK) ? GENERIC_WRITE : 0)
+ | ((p & R_OK) ? GENERIC_READ : 0);
+#ifdef FEAT_MBYTE
+ if (wn != NULL)
+ {
+ hFile = CreateFileW(wn, am, 0, NULL, OPEN_EXISTING, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE
+ && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ /* Retry with non-wide function (for Windows 98). */
+ vim_free(wn);
+ wn = NULL;
+ }
+ }
+ if (wn == NULL)
+#endif
+ hFile = CreateFile(n, am, 0, NULL, OPEN_EXISTING, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ goto getout;
+ CloseHandle(hFile);
+ }
+
+ retval = 0; /* success */
+getout:
+#ifdef FEAT_MBYTE
+ vim_free(wn);
+#endif
+ return retval;
+}
+
+#if defined(FEAT_MBYTE) || defined(PROTO)
+/*
+ * Version of open() that may use ucs2 file name.
+ */
+ int
+mch_open(char *name, int flags, int mode)
+{
+ WCHAR *wn;
+ int f;
+
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage
+# ifdef __BORLANDC__
+ /* Wide functions of Borland C 5.5 do not work on Windows 98. */
+ && g_PlatformId == VER_PLATFORM_WIN32_NT
+# endif
+ )
+ {
+ wn = enc_to_ucs2(name, NULL);
+ if (wn != NULL)
+ {
+ f = _wopen(wn, flags, mode);
+ vim_free(wn);
+ if (f >= 0)
+ return f;
+ /* Retry with non-wide function (for Windows 98). Can't use
+ * GetLastError() here and it's unclear what errno gets set to if
+ * the _wopen() fails for missing wide functions. */
+ }
+ }
+
+ return open(name, flags, mode);
+}
+
+/*
+ * Version of fopen() that may use ucs2 file name.
+ */
+ FILE *
+mch_fopen(char *name, char *mode)
+{
+ WCHAR *wn, *wm;
+ FILE *f = NULL;
+
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage
+# ifdef __BORLANDC__
+ /* Wide functions of Borland C 5.5 do not work on Windows 98. */
+ && g_PlatformId == VER_PLATFORM_WIN32_NT
+# endif
+ )
+ {
+ wn = enc_to_ucs2(name, NULL);
+ wm = enc_to_ucs2(mode, NULL);
+ if (wn != NULL && wm != NULL)
+ f = _wfopen(wn, wm);
+ vim_free(wn);
+ vim_free(wm);
+ if (f != NULL)
+ return f;
+ /* Retry with non-wide function (for Windows 98). Can't use
+ * GetLastError() here and it's unclear what errno gets set to if
+ * the _wfopen() fails for missing wide functions. */
+ }
+
+ return fopen(name, mode);
+}
+#endif
+
+#ifdef FEAT_MBYTE
+/*
+ * SUB STREAM (aka info stream) handling:
+ *
+ * NTFS can have sub streams for each file. Normal contents of file is
+ * stored in the main stream, and extra contents (author information and
+ * title and so on) can be stored in sub stream. After Windows 2000, user
+ * can access and store those informations in sub streams via explorer's
+ * property menuitem in right click menu. Those informations in sub streams
+ * were lost when copying only the main stream. So we have to copy sub
+ * streams.
+ *
+ * Incomplete explanation:
+ * http://msdn.microsoft.com/library/en-us/dnw2k/html/ntfs5.asp
+ * More useful info and an example:
+ * http://www.sysinternals.com/ntw2k/source/misc.shtml#streams
+ */
+
+/*
+ * Copy info stream data "substream". Read from the file with BackupRead(sh)
+ * and write to stream "substream" of file "to".
+ * Errors are ignored.
+ */
+ static void
+copy_substream(HANDLE sh, void *context, WCHAR *to, WCHAR *substream, long len)
+{
+ HANDLE hTo;
+ WCHAR *to_name;
+
+ to_name = malloc((wcslen(to) + wcslen(substream) + 1) * sizeof(WCHAR));
+ wcscpy(to_name, to);
+ wcscat(to_name, substream);
+
+ hTo = CreateFileW(to_name, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hTo != INVALID_HANDLE_VALUE)
+ {
+ long done;
+ DWORD todo;
+ DWORD readcnt, written;
+ char buf[4096];
+
+ /* Copy block of bytes at a time. Abort when something goes wrong. */
+ for (done = 0; done < len; done += written)
+ {
+ /* (size_t) cast for Borland C 5.5 */
+ todo = (size_t)(len - done) > sizeof(buf) ? sizeof(buf)
+ : (size_t)(len - done);
+ if (!BackupRead(sh, (LPBYTE)buf, todo, &readcnt,
+ FALSE, FALSE, context)
+ || readcnt != todo
+ || !WriteFile(hTo, buf, todo, &written, NULL)
+ || written != todo)
+ break;
+ }
+ CloseHandle(hTo);
+ }
+
+ free(to_name);
+}
+
+/*
+ * Copy info streams from file "from" to file "to".
+ */
+ static void
+copy_infostreams(char_u *from, char_u *to)
+{
+ WCHAR *fromw;
+ WCHAR *tow;
+ HANDLE sh;
+ WIN32_STREAM_ID sid;
+ int headersize;
+ WCHAR streamname[_MAX_PATH];
+ DWORD readcount;
+ void *context = NULL;
+ DWORD lo, hi;
+ int len;
+
+ /* Convert the file names to wide characters. */
+ fromw = enc_to_ucs2(from, NULL);
+ tow = enc_to_ucs2(to, NULL);
+ if (fromw != NULL && tow != NULL)
+ {
+ /* Open the file for reading. */
+ sh = CreateFileW(fromw, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (sh != INVALID_HANDLE_VALUE)
+ {
+ /* Use BackupRead() to find the info streams. Repeat until we
+ * have done them all.*/
+ for (;;)
+ {
+ /* Get the header to find the length of the stream name. If
+ * the "readcount" is zero we have done all info streams. */
+ ZeroMemory(&sid, sizeof(WIN32_STREAM_ID));
+ headersize = (char *)&sid.cStreamName - (char *)&sid.dwStreamId;
+ if (!BackupRead(sh, (LPBYTE)&sid, headersize,
+ &readcount, FALSE, FALSE, &context)
+ || readcount == 0)
+ break;
+
+ /* We only deal with streams that have a name. The normal
+ * file data appears to be without a name, even though docs
+ * suggest it is called "::$DATA". */
+ if (sid.dwStreamNameSize > 0)
+ {
+ /* Read the stream name. */
+ if (!BackupRead(sh, (LPBYTE)streamname,
+ sid.dwStreamNameSize,
+ &readcount, FALSE, FALSE, &context))
+ break;
+
+ /* Copy an info stream with a name ":anything:$DATA".
+ * Skip "::$DATA", it has no stream name (examples suggest
+ * it might be used for the normal file contents).
+ * Note that BackupRead() counts bytes, but the name is in
+ * wide characters. */
+ len = readcount / sizeof(WCHAR);
+ streamname[len] = 0;
+ if (len > 7 && wcsicmp(streamname + len - 6,
+ L":$DATA") == 0)
+ {
+ streamname[len - 6] = 0;
+ copy_substream(sh, &context, tow, streamname,
+ (long)sid.Size.LowPart);
+ }
+ }
+
+ /* Advance to the next stream. We might try seeking too far,
+ * but BackupSeek() doesn't skip over stream borders, thus
+ * that's OK. */
+ (void)BackupSeek(sh, sid.Size.LowPart, sid.Size.HighPart,
+ &lo, &hi, &context);
+ }
+
+ /* Clear the context. */
+ (void)BackupRead(sh, NULL, 0, &readcount, TRUE, FALSE, &context);
+
+ CloseHandle(sh);
+ }
+ }
+ vim_free(fromw);
+ vim_free(tow);
+}
+#endif
+
+/*
+ * Copy file attributes from file "from" to file "to".
+ * For Windows NT and later we copy info streams.
+ * Always returns zero, errors are ignored.
+ */
+ int
+mch_copy_file_attribute(char_u *from, char_u *to)
+{
+#ifdef FEAT_MBYTE
+ /* File streams only work on Windows NT and later. */
+ PlatformId();
+ if (g_PlatformId == VER_PLATFORM_WIN32_NT)
+ copy_infostreams(from, to);
+#endif
+ return 0;
+}
+
+#if defined(MYRESETSTKOFLW) || defined(PROTO)
+/*
+ * Recreate a destroyed stack guard page in win32.
+ * Written by Benjamin Peterson.
+ */
+
+/* These magic numbers are from the MS header files */
+#define MIN_STACK_WIN9X 17
+#define MIN_STACK_WINNT 2
+
+/*
+ * This function does the same thing as _resetstkoflw(), which is only
+ * available in DevStudio .net and later.
+ * Returns 0 for failure, 1 for success.
+ */
+ int
+myresetstkoflw(void)
+{
+ BYTE *pStackPtr;
+ BYTE *pGuardPage;
+ BYTE *pStackBase;
+ BYTE *pLowestPossiblePage;
+ MEMORY_BASIC_INFORMATION mbi;
+ SYSTEM_INFO si;
+ DWORD nPageSize;
+ DWORD dummy;
+
+ /* This code will not work on win32s. */
+ PlatformId();
+ if (g_PlatformId == VER_PLATFORM_WIN32s)
+ return 0;
+
+ /* We need to know the system page size. */
+ GetSystemInfo(&si);
+ nPageSize = si.dwPageSize;
+
+ /* ...and the current stack pointer */
+ pStackPtr = (BYTE*)_alloca(1);
+
+ /* ...and the base of the stack. */
+ if (VirtualQuery(pStackPtr, &mbi, sizeof mbi) == 0)
+ return 0;
+ pStackBase = (BYTE*)mbi.AllocationBase;
+
+ /* ...and the page thats min_stack_req pages away from stack base; this is
+ * the lowest page we could use. */
+ pLowestPossiblePage = pStackBase + ((g_PlatformId == VER_PLATFORM_WIN32_NT)
+ ? MIN_STACK_WINNT : MIN_STACK_WIN9X) * nPageSize;
+
+ /* On Win95, we want the next page down from the end of the stack. */
+ if (g_PlatformId == VER_PLATFORM_WIN32_WINDOWS)
+ {
+ /* Find the page that's only 1 page down from the page that the stack
+ * ptr is in. */
+ pGuardPage = (BYTE*)((DWORD)nPageSize * (((DWORD)pStackPtr
+ / (DWORD)nPageSize) - 1));
+ if (pGuardPage < pLowestPossiblePage)
+ return 0;
+
+ /* Apply the noaccess attribute to the page -- there's no guard
+ * attribute in win95-type OSes. */
+ if (!VirtualProtect(pGuardPage, nPageSize, PAGE_NOACCESS, &dummy))
+ return 0;
+ }
+ else
+ {
+ /* On NT, however, we want the first committed page in the stack Start
+ * at the stack base and move forward through memory until we find a
+ * committed block. */
+ BYTE *pBlock = pStackBase;
+
+ while (1)
+ {
+ if (VirtualQuery(pBlock, &mbi, sizeof mbi) == 0)
+ return 0;
+
+ pBlock += mbi.RegionSize;
+
+ if (mbi.State & MEM_COMMIT)
+ break;
+ }
+
+ /* mbi now describes the first committed block in the stack. */
+ if (mbi.Protect & PAGE_GUARD)
+ return 1;
+
+ /* decide where the guard page should start */
+ if ((long_u)(mbi.BaseAddress) < (long_u)pLowestPossiblePage)
+ pGuardPage = pLowestPossiblePage;
+ else
+ pGuardPage = (BYTE*)mbi.BaseAddress;
+
+ /* allocate the guard page */
+ if (!VirtualAlloc(pGuardPage, nPageSize, MEM_COMMIT, PAGE_READWRITE))
+ return 0;
+
+ /* apply the guard attribute to the page */
+ if (!VirtualProtect(pGuardPage, nPageSize, PAGE_READWRITE | PAGE_GUARD,
+ &dummy))
+ return 0;
+ }
+
+ return 1;
+}
+
+#endif
diff --git a/src/os_win32.h b/src/os_win32.h
new file mode 100644
index 000000000..d9aaa6e54
--- /dev/null
+++ b/src/os_win32.h
@@ -0,0 +1,190 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * Win32 (Windows NT and Windows 95) machine-dependent things.
+ */
+
+#include "os_dos.h" /* common MS-DOS and Win32 stuff */
+#ifndef __CYGWIN__
+#include <direct.h> /* for _mkdir() */
+#endif
+
+#define BINARY_FILE_IO
+#define USE_EXE_NAME /* use argv[0] for $VIM */
+#define NO_COOKED_INPUT /* mch_inchar() doesn't return whole lines */
+#define SYNC_DUP_CLOSE /* sync() a file with dup() and close() */
+#define USE_TERM_CONSOLE
+#ifndef HAVE_STRING_H
+# define HAVE_STRING_H
+#endif
+#define HAVE_STRCSPN
+#ifndef __GNUC__
+#define HAVE_STRICMP
+#define HAVE_STRNICMP
+#endif
+#ifndef HAVE_STRFTIME
+# define HAVE_STRFTIME /* guessed */
+#endif
+#define HAVE_MEMSET
+#ifndef HAVE_LOCALE_H
+# define HAVE_LOCALE_H 1
+#endif
+#ifndef HAVE_FCNTL_H
+# define HAVE_FCNTL_H
+#endif
+#ifndef HAVE_STDARG_H
+# define HAVE_STDARG_H
+#endif
+#define HAVE_QSORT
+#define HAVE_ST_MODE /* have stat.st_mode */
+
+#define FEAT_SHORTCUT /* resolve shortcuts */
+
+#if !defined(__MINGW32__) \
+ && !defined(__CYGWIN__) \
+ && (!defined(__BORLANDC__) || __BORLANDC__ >= 0x550) \
+ && (!defined(_MSC_VER) || _MSC_VER > 1020)
+/*
+ * Access Control List (actually security info).
+ * Mingw and Cygwin don't have the acl stuff.
+ * Borland only in version 5.5 and later.
+ * MSVC in 5.0, not in 4.2, don't know about 4.3.
+ */
+# define HAVE_ACL
+#endif
+
+#define USE_FNAME_CASE /* adjust case of file names */
+#if !defined(FEAT_CLIPBOARD) && defined(FEAT_VISUAL) && defined(FEAT_MOUSE)
+# define FEAT_CLIPBOARD /* include clipboard support */
+#endif
+#if defined(__DATE__) && defined(__TIME__)
+# define HAVE_DATE_TIME
+#endif
+#ifndef FEAT_GUI_W32 /* GUI works different */
+# define BREAKCHECK_SKIP 1 /* call mch_breakcheck() each time, it's fast */
+#endif
+#define HAVE_AVAIL_MEM
+
+#define HAVE_PUTENV /* at least Bcc 5.2 and MSC have it */
+
+#ifdef FEAT_GUI_W32
+# define NO_CONSOLE /* don't included console-only code */
+#endif
+
+/* toupper() is not really broken, but it's very slow. Probably because of
+ * using Unicode characters on Windows NT */
+#define BROKEN_TOUPPER
+
+#define FNAME_ILLEGAL "\"*?><|" /* illegal characters in a file name */
+
+#include <stdlib.h>
+#include <time.h>
+
+#ifndef STRICT
+# define STRICT
+#endif
+#ifndef COBJMACROS
+# define COBJMACROS /* For OLE: Enable "friendlier" access to objects */
+#endif
+#include <windows.h>
+
+/*
+ * Win32 has plenty of memory, use large buffers
+ */
+#define CMDBUFFSIZE 1024 /* size of the command processing buffer */
+
+/* _MAX_PATH is only 256 (stdlib.h), but we want more for the 'path' option,
+ * thus use a larger number. */
+#define MAXPATHL 1024
+
+#ifndef BASENAMELEN
+# define BASENAMELEN (_MAX_PATH - 5) /* length of base of file name */
+#endif
+
+#define TEMPNAMELEN _MAX_PATH /* length of temp file name path */
+
+#ifndef DFLT_MAXMEM
+# define DFLT_MAXMEM (2*1024) /* use up to 2 Mbyte for a buffer */
+#endif
+
+#ifndef DFLT_MAXMEMTOT
+# define DFLT_MAXMEMTOT (5*1024) /* use up to 5 Mbyte for Vim */
+#endif
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+ /* Support for __try / __except. All versions of MSVC and Borland C are
+ * expected to have this. Any other compilers that support it? */
+# define HAVE_TRY_EXCEPT 1
+# include <malloc.h> /* for _resetstkoflw() */
+# if defined(_MSC_VER) && (_MSC_VER >= 1300)
+# define RESETSTKOFLW _resetstkoflw
+# else
+# define RESETSTKOFLW myresetstkoflw
+# define MYRESETSTKOFLW
+# endif
+#endif
+
+/*
+ * Some simple debugging macros that look and behave a lot like their
+ * namesakes in MFC.
+ */
+
+#ifdef _DEBUG
+
+# if defined(_MSC_VER) && (_MSC_VER >= 1000)
+ /* Use the new debugging tools in Visual C++ 4.x */
+# include <crtdbg.h>
+# define ASSERT(f) _ASSERT(f)
+# else
+# include <assert.h>
+# define ASSERT(f) assert(f)
+# endif
+
+# define VERIFY(f) ASSERT(f)
+# define DEBUG_ONLY(f) (f)
+# define TRACE Trace
+# define TRACE0(sz) Trace(_T("%s"), _T(sz))
+# define TRACE1(sz, p1) Trace(_T(sz), p1)
+# define TRACE2(sz, p1, p2) Trace(_T(sz), p1, p2)
+# define TRACE3(sz, p1, p2, p3) Trace(_T(sz), p1, p2, p3)
+# define TRACE4(sz, p1, p2, p3, p4) Trace(_T(sz), p1, p2, p3, p4)
+
+/* In debug version, writes trace messages to debug stream */
+void __cdecl
+Trace(char *pszFormat, ...);
+
+#else /* !_DEBUG */
+
+ /* These macros should all compile away to nothing */
+# define ASSERT(f) ((void)0)
+# define VERIFY(f) ((void)f)
+# define DEBUG_ONLY(f) ((void)0)
+# define TRACE 1 ? (void)0 : printf
+# define TRACE0(sz)
+# define TRACE1(sz, p1)
+# define TRACE2(sz, p1, p2)
+# define TRACE3(sz, p1, p2, p3)
+# define TRACE4(sz, p1, p2, p3, p4)
+
+#endif /* !_DEBUG */
+
+
+#define ASSERT_POINTER(p, type) \
+ ASSERT(((p) != NULL) && IsValidAddress((p), sizeof(type), FALSE))
+
+#define ASSERT_NULL_OR_POINTER(p, type) \
+ ASSERT(((p) == NULL) || IsValidAddress((p), sizeof(type), FALSE))
+
+#define mch_setenv(name, val, x) setenv(name, val, x)
+#define mch_getenv(x) (char_u *)getenv((char *)(x))
+#ifdef __BORLANDC__
+# define vim_mkdir(x, y) mkdir(x)
+#else
+# define vim_mkdir(x, y) _mkdir(x)
+#endif
diff --git a/src/osdef.sh b/src/osdef.sh
new file mode 100755
index 000000000..d7d4f2ac2
--- /dev/null
+++ b/src/osdef.sh
@@ -0,0 +1,99 @@
+#! /bin/sh
+#
+# osdef.sh -- copy osdef.h.in to osdef.h while removing declarations
+# found in the system header files. Caution: weird sed magic going on here.
+# Warnings are printed if sed did not survive.
+#
+# (C) Michael Schroeder, Juergen Weigert
+#
+# osdef.h.in has been split into osdef1.h.in and osdef2.h.in, because some
+# sed's could not handle the amount of commands (is 50 commands the limit?).
+#
+# 31.10.95 jw.
+
+if test -z "$CC"; then
+ CC=cc
+fi
+if test -z "$srcdir"; then
+ srcdir=.
+fi
+
+rm -f core* *.core
+
+cat << EOF > osdef0.c
+#ifndef __APPLE__
+# define select select_declared_wrong
+#endif
+#define tgetstr tgetstr_declared_wrong
+#include "auto/config.h"
+#include "os_unix.h" /* bring in most header files, more follow below */
+#include "os_unixx.h" /* bring in header files for os_unix.c */
+
+#ifdef HAVE_TERMCAP_H
+# include <termcap.h> /* only for term.c */
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h> /* only used in a few files */
+#endif
+
+#ifdef HAVE_SYS_STATFS_H
+# include <sys/types.h>
+# include <sys/statfs.h> /* only for memfile.c */
+#endif
+
+#ifdef HAVE_X11
+# include <X11/Intrinsic.h>
+#endif
+EOF
+
+# Mac uses precompiled headers, but we need real headers here.
+case `uname` in
+ Darwin) $CC -I. -I$srcdir -E -no-cpp-precomp osdef0.c >osdef0.cc;;
+ *) $CC -I. -I$srcdir -E osdef0.c >osdef0.cc;;
+esac
+
+# insert a space in front of each line, so that a function name at the
+# start of the line is matched with "[)*, ]\1[ (]"
+sed < osdef0.cc -e '/\(..*\)/s// \1/' > osdef0.ccc
+
+sed < $srcdir/osdef1.h.in -n -e '/^extern/s@.*[)* ][)* ]*\([a-zA-Z_][a-zA-Z0-9_]*\) __ARGS.*@/[)*, ][(]*\1[)]*[ (]/i\\\
+\\/\\[^a-zA-Z_\\]\1 __ARGS\\/d@p' > osdef11.sed
+
+sed < $srcdir/osdef2.h.in -n -e '/^extern/s@.*[)* ][)* ]*\([a-zA-Z_][a-zA-Z0-9_]*\) __ARGS.*@/[)*, ][(]*\1[)]*[ (]/i\\\
+\\/\\[^a-zA-Z_\\]\1 __ARGS\\/d@p' > osdef21.sed
+
+cat << EOF > osdef2.sed
+1i\\
+/*
+1i\\
+ * osdef.h is automagically created from osdef?.h.in by osdef.sh -- DO NOT EDIT
+1i\\
+ */
+EOF
+
+cat osdef0.ccc | sed -n -f osdef11.sed >> osdef2.sed
+sed -f osdef2.sed < $srcdir/osdef1.h.in > auto/osdef.h
+
+cat osdef0.ccc | sed -n -f osdef21.sed > osdef2.sed
+sed -f osdef2.sed < $srcdir/osdef2.h.in >> auto/osdef.h
+
+rm osdef0.c osdef0.cc osdef0.ccc osdef11.sed osdef21.sed osdef2.sed
+
+if test -f core*; then
+ file core*
+ echo " Sorry, your sed is broken. Call the system administrator."
+ echo " Meanwhile, you may try to compile Vim with an empty osdef.h file."
+ echo " If you compiler complains about missing prototypes, move the needed"
+ echo " ones from osdef1.h.in and osdef2.h.in to osdef.h."
+ exit 1
+fi
+cat $srcdir/osdef1.h.in $srcdir/osdef2.h.in >osdefX.h.in
+if eval test "`diff auto/osdef.h osdefX.h.in | wc -l`" -eq 4; then
+ echo " Hmm, sed is very pessimistic about your system header files."
+ echo " But it did not dump core -- strange! Let's continue carefully..."
+ echo " If this fails, you may want to remove offending lines from osdef.h"
+ echo " or try with an empty osdef.h file, if your compiler can do without"
+ echo " function declarations."
+fi
+rm osdefX.h.in
diff --git a/src/osdef1.h.in b/src/osdef1.h.in
new file mode 100644
index 000000000..fac78e001
--- /dev/null
+++ b/src/osdef1.h.in
@@ -0,0 +1,137 @@
+/* autoconf cannot fiddle out declarations. Use our homebrewn tools. (jw) */
+/*
+ * Declarations that may cause conflicts belong here so that osdef.sh
+ * can clean out the forest. Everything else belongs in os_unix.h
+ *
+ * How this works:
+ * - This file contains all unix prototypes that Vim might need.
+ * - The shell script osdef.sh is executed at compile time to remove all the
+ * prototypes that are in an include file. This results in osdef.h.
+ * - osdef.h is included in vim.h.
+ *
+ * sed cannot always handle so many commands, this is file 1 of 2
+ */
+
+extern int printf __ARGS((char *, ...));
+extern int fprintf __ARGS((FILE *, char *, ...));
+extern int sprintf __ARGS((char *, char *, ...));
+extern int sscanf __ARGS((char *, char *, ...));
+#ifndef fopen /* could be redefined to fopen64() */
+extern FILE *fopen __ARGS((const char *, const char *));
+#endif
+extern int fclose __ARGS((FILE *));
+extern int fseek __ARGS((FILE *, long, int));
+#ifdef HAVE_FSEEKO
+extern int fseeko __ARGS((FILE *, off_t, int));
+#endif
+extern long ftell __ARGS((FILE *));
+#ifdef HAVE_FTELLO
+extern off_t ftello __ARGS((FILE *));
+#endif
+extern void rewind __ARGS((FILE *));
+extern int fread __ARGS((char *, int, int, FILE *));
+extern int fwrite __ARGS((char *, int, int, FILE *));
+extern int fputs __ARGS((char *, FILE *));
+#ifndef ferror /* let me say it again: "macros should never have prototypes" */
+extern int ferror __ARGS((FILE *));
+#endif
+extern int fflush __ARGS((FILE *));
+#if defined(sun) || defined(_SEQUENT_)
+/* used inside of stdio macros getc(), puts(), putchar()... */
+extern int _flsbuf __ARGS((int, FILE *));
+extern int _filbuf __ARGS((FILE *));
+#endif
+
+#if !defined(HAVE_SELECT)
+struct pollfd; /* for poll __ARGS */
+extern int poll __ARGS((struct pollfd *, long, int));
+#endif
+
+#ifdef HAVE_MEMSET
+extern void *memset __ARGS((void *, int, size_t));
+#endif
+#ifdef HAVE_BCMP
+extern int bcmp __ARGS((void *, void *, size_t));
+#endif
+#ifdef HAVE_MEMCMP
+extern int memcmp __ARGS((const void *, const void *, size_t));
+#endif
+#ifdef HAVE_STRPBRK
+extern char *strpbrk __ARGS((const char *, const char *));
+#endif
+#ifdef USEBCOPY
+extern void bcopy __ARGS((char *, char *, int));
+#else
+# ifdef USEMEMCPY
+extern void memcpy __ARGS((char *, char *, int));
+# else
+# ifdef USEMEMMOVE
+extern void memmove __ARGS((char *, char *, int));
+# endif
+# endif
+#endif
+/* used inside of FD_ZERO macro: */
+extern void bzero __ARGS((void *, size_t));
+#ifdef HAVE_SETSID
+extern pid_t setsid __ARGS((void));
+#endif
+#ifdef HAVE_SETPGID
+extern int setpgid __ARGS((pid_t, pid_t));
+#endif
+#ifdef HAVE_STRTOL
+extern int strtol __ARGS((char *, char **, int));
+#endif
+#ifdef HAVE_STRFTIME
+extern size_t strftime __ARGS((char *, size_t, char *, struct tm *));
+#endif
+#ifdef HAVE_STRCASECMP
+extern int strcasecmp __ARGS((char *, char *));
+#endif
+#ifdef HAVE_STRNCASECMP
+extern int strncasecmp __ARGS((char *, char *, size_t));
+#endif
+#ifndef strdup
+extern char *strdup __ARGS((const char *));
+#endif
+extern int atoi __ARGS((char *));
+extern int atol __ARGS((char *));
+
+#ifndef USE_SYSTEM
+extern int fork __ARGS((void));
+extern int execvp __ARGS((const char *, const char **));
+extern int wait __ARGS((int *)); /* will this break things ...? */
+extern int waitpid __ARGS((pid_t, int *, int));
+#endif
+
+extern int toupper __ARGS((int));
+extern int tolower __ARGS((int));
+
+extern RETSIGTYPE (*signal __ARGS((int, RETSIGTYPE (*func) SIGPROTOARG))) __ARGS(SIGPROTOARG);
+#ifdef HAVE_SIGSET
+extern RETSIGTYPE (*sigset __ARGS((int, RETSIGTYPE (*func) SIGPROTOARG))) __ARGS(SIGPROTOARG);
+#endif
+
+#if defined(HAVE_SETJMP_H)
+# ifdef HAVE_SIGSETJMP
+extern int sigsetjmp __ARGS((sigjmp_buf, int));
+extern void siglongjmp __ARGS((sigjmp_buf, int));
+# else
+extern int setjmp __ARGS((jmp_buf));
+extern void longjmp __ARGS((jmp_buf, int));
+# endif
+#endif
+
+extern int kill __ARGS((int, int));
+
+extern int access __ARGS((char *, int));
+extern int fsync __ARGS((int));
+extern int fchown __ARGS((int, int, int));
+#if defined(HAVE_GETCWD) && !defined(sun)
+extern char *getcwd __ARGS((char *, int));
+#else
+extern char *getwd __ARGS((char *));
+#endif
+#ifndef __alpha /* suggested by Campbell */
+extern int ioctl __ARGS((int, int, ...));
+#endif
+extern int chmod __ARGS((const char *, mode_t));
diff --git a/src/osdef2.h.in b/src/osdef2.h.in
new file mode 100644
index 000000000..cca78b07c
--- /dev/null
+++ b/src/osdef2.h.in
@@ -0,0 +1,88 @@
+/*
+ * osdef2.h.in - See osdef1.h.in for a description.
+ */
+
+extern int remove __ARGS((const char *));
+extern int rename __ARGS((const char *, const char *));
+extern int free __ARGS((char *));
+extern char *malloc __ARGS((unsigned int));
+extern char *realloc __ARGS((char *, int));
+extern char *getenv __ARGS((char *));
+extern int setenv __ARGS((char *, char *, int));
+extern int putenv __ARGS((const char *));
+
+extern int gethostname __ARGS((char *, int));
+extern void perror __ARGS((char *));
+
+extern int sleep __ARGS((int));
+extern int usleep __ARGS((unsigned int));
+extern unsigned int alarm __ARGS((unsigned int));
+extern int chdir __ARGS((char *));
+extern int fchdir __ARGS((int));
+#ifndef stat /* could be redefined to stat64() */
+extern int stat __ARGS((const char *, struct stat *));
+#endif
+#ifndef lstat /* could be redefined to lstat64() */
+extern int lstat __ARGS((const char *, struct stat *));
+#endif
+extern int fstat __ARGS((int, struct stat *));
+extern int open __ARGS((const char *, int, ...));
+extern int close __ARGS((int));
+extern int read __ARGS((int, char *, size_t));
+extern int write __ARGS((int, char *, size_t));
+extern int pipe __ARGS((int *));
+extern off_t lseek __ARGS((int, off_t, int));
+extern void sync __ARGS((void));
+extern uid_t getuid __ARGS((void));
+extern gid_t getgid __ARGS((void));
+extern void qsort __ARGS((void *, size_t, size_t, int (*)(const void *, const void *)));
+
+extern int isatty __ARGS((int));
+extern int getpid __ARGS((void));
+extern int dup __ARGS((int));
+extern int unlink __ARGS((const char *));
+extern int link __ARGS((const char *, const char *));
+extern int mkdir __ARGS((const char *, mode_t));
+extern int rmdir __ARGS((const char *));
+
+extern int tgetent __ARGS((char *, char *));
+extern int tgetnum __ARGS((char *));
+extern int tgetflag __ARGS((char *));
+extern char *tgoto __ARGS((char *, int, int));
+extern int tputs __ARGS((char *, int, int (*)(int)));
+
+#ifdef HAVE_TERMIOS_H
+struct termios; /* for tcgetattr __ARGS */
+extern int tcgetattr __ARGS((int, struct termios *));
+extern int tcsetattr __ARGS((int, int, const struct termios *));
+#endif
+
+#ifdef HAVE_SYS_STATFS_H
+struct statfs; /* for fstatfs __ARGS */
+extern int fstatfs __ARGS((int, struct statfs *, int, int));
+#endif
+
+#ifdef HAVE_GETTIMEOFDAY
+struct timeval; /* for gettimeofday __ARGS */
+struct timezone; /* for gettimeofday __ARGS */
+extern int gettimeofday __ARGS((struct timeval *tp, struct timezone *tzp));
+extern time_t time __ARGS((time_t *));
+#endif
+
+#ifdef HAVE_GETPWNAM
+struct passwd; /* for getpwnam __ARGS */
+extern struct passwd *getpwnam __ARGS((const char *));
+#endif
+
+#ifdef USE_TMPNAM
+extern char *tmpnam __ARGS((char *));
+#else
+extern char *mktemp __ARGS((char *));
+#endif
+
+#ifdef ISC
+extern int _Xmblen __ARGS((char const *, size_t));
+#else
+ /* This is different from the header but matches mblen() */
+extern int _Xmblen __ARGS((char *, size_t));
+#endif
diff --git a/src/pathdef.sh b/src/pathdef.sh
new file mode 100755
index 000000000..b2a83a017
--- /dev/null
+++ b/src/pathdef.sh
@@ -0,0 +1,11 @@
+#! /bin/sh
+#
+# pathdef.sh: adjust pathdef.c for auto/link.sed, if it exists
+#
+if test -s auto/link.sed; then
+ cp auto/pathdef.c auto/pathdef.tmp
+ sed -f auto/link.sed <auto/pathdef.tmp >auto/pathdef.c
+ rm -f auto/pathdef.tmp
+fi
+
+# vim:set sw=2 et:
diff --git a/src/po/Make_ming.mak b/src/po/Make_ming.mak
new file mode 100644
index 000000000..810efb036
--- /dev/null
+++ b/src/po/Make_ming.mak
@@ -0,0 +1,67 @@
+# Makefile for the Vim message translations for mingw32
+#
+# Eduardo F. Amatria <eferna1@platea.pntic.mec.es>
+#
+# Read the README_ming.txt file before using it.
+#
+# Use at your own risk but with care, it could even kill your canary.
+#
+# Previous to all you must have the environment variable LANGUAGE set to your
+# language (xx) and add it to the next three lines.
+#
+
+LANGUAGES = af ca cs de en_GB es fr it ja ko no pl ru sk sv uk zh_TW \
+ zh_TW.UTF-8 zh_CN zh_CN.UTF-8
+MOFILES = af.mo ca.mo cs.mo de.mo en_GB.mo es.mo fr.mo it.mo ja.mo \
+ ko.mo no.mo pl.mo ru.mo sk.mo sv.mo uk.mo \
+ zh_TW.mo zh_TW.UTF-8.mo zh_CN.mo zh_CN.UTF-8.mo
+
+PACKAGE = vim
+
+# Uncomment one of the lines below or modify it to put the path to your
+# gettex binaries; I use the first
+#GETTEXT_PATH = C:/gettext.win32/bin/
+#GETTEXT_PATH = C:/gettext-0.10.35-w32/win32/Release/
+#GETTEXT_PATH = C:/cygwin/bin/
+
+MSGFMT = $(GETTEXT_PATH)msgfmt
+XGETTEXT = $(GETTEXT_PATH)xgettext
+MSGMERGE = $(GETTEXT_PATH)msgmerge
+
+MV = move
+CP = copy
+RM = del
+MKD = mkdir
+
+.SUFFIXES:
+.SUFFIXES: .po .mo .pot
+.PHONY: first_time all install clean $(LANGUAGES)
+
+.po.mo:
+ $(MSGFMT) -o $@ $<
+
+all: $(MOFILES)
+
+first_time:
+ $(XGETTEXT) --default-domain=$(LANGUAGE) \
+ --add-comments --keyword=_ --keyword=N_ $(wildcard ../*.c) ../if_perl.xs $(wildcard ../globals.h)
+
+$(LANGUAGES):
+ $(XGETTEXT) --default-domain=$(PACKAGE) \
+ --add-comments --keyword=_ --keyword=N_ $(wildcard ../*.c) ../if_perl.xs $(wildcard ../globals.h)
+ $(MV) $(PACKAGE).po $(PACKAGE).pot
+ $(CP) $@.po $@.po.orig
+ $(MV) $@.po $@.po.old
+ $(MSGMERGE) $@.po.old $(PACKAGE).pot -o $@.po
+ $(RM) $@.po.old
+
+install:
+ $(MKD) $(VIMRUNTIME)\lang\$(LANGUAGE)
+ $(MKD) $(VIMRUNTIME)\lang\$(LANGUAGE)\LC_MESSAGES
+ $(CP) $(LANGUAGE).mo $(VIMRUNTIME)\lang\$(LANGUAGE)\LC_MESSAGES\$(PACKAGE).mo
+
+clean:
+ $(RM) *.mo
+ $(RM) *.pot
+
+
diff --git a/src/po/Make_mvc.mak b/src/po/Make_mvc.mak
new file mode 100644
index 000000000..b69b5abc5
--- /dev/null
+++ b/src/po/Make_mvc.mak
@@ -0,0 +1,62 @@
+# Makefile for the Vim message translations for MSVC
+# (based on make_ming.mak)
+#
+# Mike Williams <mrw@eandem.co.uk>
+#
+# Please read README_mvc.txt before using this file.
+#
+
+LANGUAGES = af ca cs de en_GB es fr it ja ko no pl ru sk sv uk zh_TW \
+ zh_TW.UTF-8 zh_CN zh_CN.UTF-8
+MOFILES = af.mo ca.mo cs.mo de.mo en_GB.mo es.mo fr.mo it.mo ja.mo \
+ ko.mo no.mo pl.mo ru.mo sk.mo sv.mo uk.mo \
+ zh_TW.mo zh_TW.UTF-8.mo zh_CN.mo zh_CN.UTF-8.mo
+
+PACKAGE = vim
+
+# Correct the following line for the installation directory of gettext
+GETTEXT_PATH = H:\gettext.win32.msvcrt\bin
+
+MSGFMT = $(GETTEXT_PATH)\msgfmt
+XGETTEXT = $(GETTEXT_PATH)\xgettext
+MSGMERGE = $(GETTEXT_PATH)\msgmerge
+
+MV = move
+CP = copy
+RM = del
+MKD = mkdir
+LS = dir
+
+LSFLAGS = /b /on /l /s
+
+INSTALLDIR = $(VIMRUNTIME)\lang\$(LANGUAGE)\LC_MESSAGES
+
+.SUFFIXES:
+.SUFFIXES: .po .mo .pot
+
+.po.mo:
+ $(MSGFMT) -o $@ $<
+
+all: $(MOFILES)
+
+files:
+ $(LS) $(LSFLAGS) ..\*.c ..\if_perl.xs ..\globals.h > .\files
+
+first_time: files
+ $(XGETTEXT) --default-domain=$(LANGUAGE) --add-comments --keyword=_ --keyword=N_ --files-from=.\files
+
+$(LANGUAGES): files
+ $(XGETTEXT) --default-domain=$(PACKAGE) --add-comments --keyword=_ --keyword=N_ --files-from=.\files
+ $(MV) $(PACKAGE).po $(PACKAGE).pot
+ $(CP) $@.po $@.po.orig
+ $(MV) $@.po $@.po.old
+ $(MSGMERGE) $@.po.old $(PACKAGE).pot -o $@.po
+ $(RM) $@.po.old
+
+install:
+ if not exist $(INSTALLDIR) $(MKD) $(INSTALLDIR)
+ $(CP) $(LANGUAGE).mo $(INSTALLDIR)\$(PACKAGE).mo
+
+clean:
+ $(RM) *.mo
+ $(RM) *.pot
diff --git a/src/po/Makefile b/src/po/Makefile
new file mode 100644
index 000000000..d54913062
--- /dev/null
+++ b/src/po/Makefile
@@ -0,0 +1,135 @@
+# Makefile for the Vim message translations.
+
+# TODO make this configurable
+# Note: ja.sjis, *.cp1250 and zh_CN.cp936 are only for MS-Windows, they are
+# not installed on Unix
+
+LANGUAGES = af ca cs de en_GB es fr it ja ko no pl ru sk sv uk zh_TW \
+ zh_TW.UTF-8 zh_CN zh_CN.UTF-8
+MOFILES = af.mo ca.mo cs.mo de.mo en_GB.mo es.mo fr.mo it.mo ja.mo \
+ ko.mo no.mo pl.mo ru.mo sk.mo sv.mo uk.mo \
+ zh_TW.mo zh_TW.UTF-8.mo zh_CN.mo zh_CN.UTF-8.mo
+
+PACKAGE = vim
+SHELL = /bin/sh
+
+# The OLD_PO_FILE_INPUT and OLD_PO_FILE_OUTPUT are for the new GNU gettext
+# tools 0.10.37, which use a slightly different .po file format that is not
+# compatible with Solaris (and old gettext implementations) unless these are
+# set. gettext 0.10.36 will not work!
+MSGFMT = OLD_PO_FILE_INPUT=yes msgfmt -v
+XGETTEXT = OLD_PO_FILE_INPUT=yes OLD_PO_FILE_OUTPUT=yes xgettext
+MSGMERGE = OLD_PO_FILE_INPUT=yes OLD_PO_FILE_OUTPUT=yes msgmerge
+
+.SUFFIXES:
+.SUFFIXES: .po .mo .pot
+.PHONY: all install uninstall check clean distclean $(LANGUAGES)
+
+.po.mo:
+ $(MSGFMT) -o $@ $<
+
+all: $(MOFILES)
+
+install: $(MOFILES)
+ @$(MAKE) check
+ for lang in $(LANGUAGES); do \
+ dir=$(LOCALEDIR)/$$lang/; \
+ if test ! -x "$$dir"; then \
+ mkdir $$dir; chmod 755 $$dir; \
+ fi; \
+ dir=$(LOCALEDIR)/$$lang/LC_MESSAGES; \
+ if test ! -x "$$dir"; then \
+ mkdir $$dir; chmod 755 $$dir; \
+ fi; \
+ if test -r $$lang.mo; then \
+ $(INSTALL_DATA) $$lang.mo $$dir/$(PACKAGE).mo; \
+ chmod $(FILEMOD) $$dir/$(PACKAGE).mo; \
+ fi; \
+ done
+
+uninstall:
+ @$(MAKE) check
+ for cat in $(MOFILES); do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+ rm -f $(LOCALEDIR)/$$lang/LC_MESSAGES/$(PACKAGE).mo; \
+ done
+
+converted: ja.sjis.mo cs.cp1250.mo pl.cp1250.mo sk.cp1250.mo zh_CN.cp936.mo \
+ ru.cp1251.mo
+
+# Convert ja.po to create ja.sjis.po. Requires doubling backslashes in the
+# second byte. Don't depend on sjiscorr, it should only be compiled when
+# ja.sjis.po is outdated.
+ja.sjis.po: ja.po
+ @$(MAKE) sjiscorr
+ rm -f ja.sjis.po
+ iconv -f euc-jp -t cp932 ja.po | ./sjiscorr > ja.sjis.po
+
+sjiscorr: sjiscorr.c
+ $(CC) -o sjiscorr sjiscorr.c
+
+# Convert cs.po to create cs.cp1250.po.
+cs.cp1250.po: cs.po
+ rm -f cs.cp1250.po
+ iconv -f iso-8859-2 -t cp1250 cs.po | \
+ sed -e 's/charset=ISO-8859-2/charset=cp1250/' -e 's/# Original translations/# Generated from cs.po, DO NOT EDIT/' > cs.cp1250.po
+
+# Convert pl.po to create pl.cp1250.po.
+pl.cp1250.po: pl.po
+ rm -f pl.cp1250.po
+ iconv -f iso-8859-2 -t cp1250 pl.po | \
+ sed -e 's/charset=ISO-8859-2/charset=cp1250/' -e 's/# Original translations/# Generated from pl.po, DO NOT EDIT/' > pl.cp1250.po
+
+# Convert sk.po to create sk.cp1250.po.
+sk.cp1250.po: sk.po
+ rm -f sk.cp1250.po
+ iconv -f iso-8859-2 -t cp1250 sk.po | \
+ sed -e 's/charset=ISO-8859-2/charset=cp1250/' -e 's/# Original translations/# Generated from sk.po, DO NOT EDIT/' > sk.cp1250.po
+
+# Convert zh_CN.po to create zh_CN.cp936.po.
+# set 'charset' to gbk to avoid that msfmt generates a warning
+zh_CN.cp936.po: zh_CN.po
+ rm -f zh_CN.cp936.po
+ iconv -f gb2312 -t cp936 zh_CN.po | \
+ sed -e 's/charset=gb2312/charset=gbk/' -e 's/# Original translations/# Generated from zh_CN.po, DO NOT EDIT/' > zh_CN.cp936.po
+
+# Convert ru.po to create ru.cp1251.po.
+ru.cp1251.po: ru.po
+ rm -f ru.cp1251.po
+ iconv -f koi8-r -t cp1251 ru.po | \
+ sed -e 's/charset=koi8-r/charset=cp1251/' -e 's/# Original translations/# Generated from ru.po, DO NOT EDIT/' > ru.cp1251.po
+
+check:
+ @if test "x" = "x$(prefix)"; then \
+ echo "******************************************"; \
+ echo " please use make from the src directory "; \
+ echo "******************************************"; \
+ exit 1; \
+ fi
+
+clean:
+ rm -f core core.* *.old.po *.mo *.pot sjiscorr
+
+distclean: clean
+
+#
+# NOTE: If you get an error for gvimext.cpp not found, you need to unpack the
+# extra archive.
+#
+$(PACKAGE).pot: ../*.c ../if_perl.xs ../GvimExt/gvimext.cpp ../globals.h
+ cd ..; $(XGETTEXT) --default-domain=$(PACKAGE) \
+ --add-comments --keyword=_ --keyword=N_ \
+ *.c if_perl.xs GvimExt/gvimext.cpp globals.h
+ mv -f ../$(PACKAGE).po $(PACKAGE).pot
+
+# Don't add a dependency here, we only want to update the .po files manually
+$(LANGUAGES):
+ @$(MAKE) $(PACKAGE).pot
+ if test ! -f $@.po.orig; then cp $@.po $@.po.orig; fi
+ mv $@.po $@.po.old
+ if $(MSGMERGE) $@.po.old $(PACKAGE).pot -o $@.po; then \
+ rm -f $@.po.old; \
+ else \
+ echo "msgmerge for $@.po failed!"; mv $@.po.old $@.po; \
+ fi
diff --git a/src/po/README.txt b/src/po/README.txt
new file mode 100644
index 000000000..b023ef364
--- /dev/null
+++ b/src/po/README.txt
@@ -0,0 +1,104 @@
+TRANSLATING VIM MESSAGES
+
+In this directory you will find xx.po files, where "xx" is a language code.
+Each file contains the translation of English Vim messages for one language.
+The files are in "po" format, used by the gettext package. Please refer to
+the gettext documentation for more information.
+
+The GNU gettext library, starting with version 0.10.37, supports converting
+messages from one encoding to another. This requires that it was compiled
+with HAVE_ICONV. The result is that the messages may be in any encoding
+supported by iconv and will be automatically converted to the currently used
+encoding.
+
+The GNU gettext library, starting with version 0.10.36, uses a new format for
+some encodings. This folows the C99 standard for strings. It means that when
+a multi-byte character includes the 0x5c byte, this is not recognized as a
+backslash. Since this format is incompatible with Solaris, Vim uses the old
+format. This is done by setting the OLD_PO_FILE_OUTPUT and OLD_PO_FILE_INPUT
+environment variables. When you use the Makefile in this directory that will
+be done for you. This does NOT work with gettext 0.10.36. Don't use it, get
+0.10.37.
+
+
+ON MS-WINDOWS
+
+The distributed files are generated on Unix, but this should also be possible
+on MS-Windows. Download the gettext packages, for example from:
+
+ http://sourceforge.net/projects/gettext
+
+You might have to do the commands manually. Example:
+
+ cd c:\vim\vim60
+ mkdir runtime\lang\ja\LC_MESSAGES
+ msgfmt -o runtime\lang\ja\LC_MESSAGES\vim.mo src\po\ja.po
+
+
+WHEN THERE IS A MISTAKE
+
+If you find there is a mistake in one of the translations, please report this
+to the maintainer of the translation. His/her E-mail address is in the
+comments at the start of the file. You can also see this with the ":messages"
+command in Vim when the translation is being used.
+
+
+CREATING A NEW PO FILE
+
+We will use "xx.po" as an example here, replace "xx" with the name of your
+language.
+
+- Edit Makefile to add xx to LANGUAGES and xx.mo to MOFILES.
+- Copy the header of an existing file, e.g., de.po, to xx.po. Do not copy any
+ of the translated messages, delete everything after the "msgstr".
+- The remaining work is like updating, see the next section.
+
+
+UPDATING A PO FILE
+
+If you are the maintainer of a .po file, this is how you update the file. We
+will use "xx.po" as an example here, replace "xx" with the name of your
+language.
+
+(1) Add new and changed messages from the Vim sources:
+
+ make xx
+
+ This will extract all the strings from Vim and merge them in with the
+ existing translations. Requires the GNU gettext utilities. Also requires
+ unpacking the extra archive.
+ Your original xx.po file will be copied to xx.po.orig
+
+ -- After you do this, you MUST do the next three steps! --
+
+(2) Translate
+ See the gettext documentation on how to do this. You can also find
+ examples in the other po files.
+ Search the po file for items that require translation:
+
+ /fuzzy\|^msgstr ""\(\n"\)\@!
+
+ Remove the "#, fuzzy" line after adding the translation.
+
+ There is one special message:
+ msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+ You should include your name and E-mail address instead, for example:
+ msgstr "Berichten übersetzt bei: John Doe <john@doe.org>"
+
+(3) Clean up
+ This is very important to make sure the translation works on all systems.
+ Comment-out all non-translated strings. There are two types:
+ - items marked with "#, fuzzy"
+ - items with an empty msgstr
+ You can do this with the cleanup.vim script:
+
+ :source cleanup.vim
+
+ Background: on Solaris an empty msgstr results in an empty message; GNU
+ gettext ignores empty strings and items marked with "#, fuzzy".
+
+(4) Check:
+
+ make xx.mo
+
+ Look out for syntax errors and fix them.
diff --git a/src/po/README_mingw.txt b/src/po/README_mingw.txt
new file mode 100644
index 000000000..7ba98e607
--- /dev/null
+++ b/src/po/README_mingw.txt
@@ -0,0 +1,101 @@
+TRANSLATING VIM MESSAGES
+
+This file explains how to create and maintain po files using
+gnu-gettext.win32, a MINGW32 Windows port of gettext by Franco Bez
+<franco.bez@gmx.de>. You can find it at:
+
+ http://home.a-city.de/franco.bez/gettext/gettext_win32_en.html
+
+First read the README.txt file for the general remarks
+
+
+The file that does the work is Make_ming.mak in the po directory. It is an
+adaptation of the Unix Makefile, but it does NOT test the presence of any po,
+pot, or mo files, so use it at your own risk but with care: it could even kill
+your canary. It has been tested by me several times (and with different
+languages) with success.
+
+The make utility must be run from the po directory.
+
+First of all you must set the enviroment variable LANGUAGE to xx, where xx is
+the name of your language. You can do it from the command line or adding a
+line to your autoexec.bat file: set LANGUAGE=xx. You must also add your
+language to the Make_ming.mak file in the lines LANGUAGES, MOFILES, AND
+POFILES.
+
+If you don't have a xx.po file, you must create it with the command:
+
+ make -f Make_ming.mak first_time
+
+This will produce a new brand xx.po file with all the messages in Vim ready
+for translation. Then you must source the cleanup.vim script from inside Vim;
+it will comment the untranslated messages (now, all). I recommend to use
+syntax highlighting so you can identify the untranslated messages easily.
+You also must remove the '..\' that prepends the name of the source files.
+(I don't no why, but make is unable to change the directory from po to src and
+back to po, so all the work must be done from the po dir, hence the '..\')
+
+Then you must go step (2) below.
+
+If you are updating a po file you must follow the next steps (they are nearly
+the same as in the Unix case, only the commands change):
+
+(1) Add new and changed messages from the Vim sources:
+
+ make -f Make_ming.mak xx
+
+ This will extract all the strings from Vim and merge them in with the
+ existing translations. Requires the GNU gettext utilities. Also requires
+ unpacking the extra archive.
+ Your original xx.po file will be copied to xx.po.orig
+
+ -- After you do this, you MUST do the next three steps! --
+
+(2) Translate
+ See the gettext documentation on how to do this. You can also find
+ examples in the other po files.
+ Search the po file for items that require translation:
+ /\#\~ and also the fuzzy translations, /\#, fuzzy
+ Remove "#~" and "#, fuzzy" after adding the translation.
+
+ There is one special message:
+ msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+ You should include your name and E-mail address instead, for example:
+ msgstr "Berichten übersetzt bei: John Doe <john@doe.org>"
+
+(3) Clean up
+ This is very important to make sure the translation works on all systems.
+ Comment-out all non-translated strings. There are two types:
+ - items marked with "#, fuzzy"
+ - items with an empty msgstr
+ You can do this with the cleanup.vim script:
+
+ :source cleanup.vim
+
+(4) Check:
+
+ make -f Make_ming.mak xx.mo
+
+ Look out for syntax errors and fix them.
+
+(5) This is an extra step, ;-). If you want the vim.mo file installed in your
+ system you must run:
+
+ make -f Make_ming.mak install
+
+ This will create the xx\LC_MESSAGES directory (if it does not exist) and
+ will copy vim.po to it.
+
+(6) Another extra step ;-)). The command:
+
+ make -f Make_ming.mak clean
+
+ will delete the temp files created during the process.
+
+Suggestions will be welcomed.
+
+Eduardo F. Amatria <eferna1@platea.pntic.mec.es>
+
+Happy Vimming with NLS!!
+
+vim:tw=78:
diff --git a/src/po/README_mvc.txt b/src/po/README_mvc.txt
new file mode 100644
index 000000000..cd107debf
--- /dev/null
+++ b/src/po/README_mvc.txt
@@ -0,0 +1,94 @@
+TRANSLATING VIM MESSAGES
+
+This file explains how to create and maintain po files using
+gnu-gettext.win32, a Windows port of gettext by Franco Bez
+<franco.bez@gmx.de>. You can find it at:
+
+ http://home.a-city.de/franco.bez/gettext/gettext_win32_en.html
+
+First read the README.txt file in this directory for general remarks on
+translating Vim messages.
+
+
+SETUP
+
+Set the enviroment variable LANGUAGE to the language code for the language you
+are translating Vim messages to. Languagde codes are typically two characters
+and you can find a list of them at:
+
+ http://www.geocities.com/click2speak/languages.html
+
+The LANGUAGE environment variable can be set from the command line, by adding
+a line to your autoexec.bat file, or by defining a user variable from the
+Advanced tab in the System control panel.
+
+Next, edit Make_mvc.mak so that GETTEXT_PATH points the binary directory of
+the intallation.
+
+
+CREATING A NEW TRANSLATION
+
+When creating a new translation you must add your language code to the
+Make_mvc.mak file in the lines defining LANGUAGES and MOFILES. To create the
+initial .po file for your language you must use the command:
+
+ make -f make_mvc.mak first_time
+
+Note: You need to be in the po directory when using this makefile.
+
+Once you have your new .po file load it into Vim and source cleanup.vim, this
+will convert untranslated messages to comments. If you have syntax
+highlighting turned on then untranslated messages will stand out more easily.
+
+You will also need to edit the file names in the comments in the .po file.
+You need to remove the absolute directory specification (which has the form
+c:\vim61\src\). You can do this in Vim with the following command with the
+appropriate directory specfication for where you have installed the Vim
+source:
+
+ %s/c:\\vim61\\src\\//g
+
+
+UPDATING A TRANSLATION
+
+If there are new or changed messages in Vim that need translating, then the
+first thing to do is merge them into the existing translations. This is done
+with the following command:
+
+ nmake -f Make_mvc.mak xx.po
+
+where xx is the langauge code for the language needing translations. The
+original .po file is copied to xx.po.orig.
+
+
+DOING THE TRANSLATION
+
+Now that you have a .po file you can do the translations for all messages that
+need it. See README.txt for specific instructions.
+
+Once you have finished translating the messages you should make sure all
+non-translated strings are commented out. This can be done by sourcing
+cleanup.vim once again.
+
+
+CHECKING THE TRANSLATION
+
+Check the translation with the following command:
+
+ nmake -f make_mvc.mak xx.mo
+
+Correct any syntax errors reported. When there are no more errors, the
+translation is ready to be installed.
+
+
+INSTALLING THE TRANSLATION
+
+Install your translation with the following command:
+
+ nmake -f make_mvc.mak install
+
+This will create the xx\LC_MESSAGES directory in runtime\lang if it does not
+already exist.
+
+
+vim:tw=78:
diff --git a/src/po/af.po b/src/po/af.po
new file mode 100644
index 000000000..3828481f1
--- /dev/null
+++ b/src/po/af.po
@@ -0,0 +1,6244 @@
+# Afrikaans translation for Vim
+# Do ":help uganda" in Vim to read copying and usage conditions.
+# Do ":help credits" in Vim to see a list of people who contributed.
+# Danie Roux <droux@tuks.co.za>, 2001
+# Edited: Jean Jordaan (njj) <jean@upfrontsystems.co.za>, 10/01/2001
+# Edited by Danie on 10/31/2001
+#
+# njj: Save == Stoor. Write == Skryf.
+# njj: "deleted" == "geskrap"; "remove" == "verwyder"
+# njj: "source" == "uitvoer", want "sourced" lêers word uitgevoer
+# njj: "abort" == "staak"
+# close == sluit
+# Onseker:
+# X Display - vertoonskerm? (njj: ek dink dis reg.)
+# open vim in another GTK Widget - het vertaal as element (njj: OK, maar
+# 'n element is algemener as 'n widget: mens kry byvoorbeeld HTML
+# en XML elemente. Maar ek kan nie nou aan 'n spesifieker woord dink
+# nie.)
+# Printing aborted - drukkery gestaak? (njj: ek dink dis reg.)
+
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim 6.0\n"
+"POT-Creation-Date: 2001-10-31 12:43+0200\n"
+"PO-Revision-Date: Wed Oct 31 13:41 SAST 2001\n"
+"Last-Translator: Danie Roux <droux@tuks.co.za>\n"
+"Language-Team: Danie Roux <droux@tuks.co.za>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO_8859-1\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Kan nie buffer toeken nie, program sluit..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: Kan nie buffer toeken nie, gaan ander een gebruik..."
+
+#: buffer.c:698
+msgid "No buffers were unloaded"
+msgstr "Geen buffers is uitgelaai nie"
+
+#: buffer.c:700
+msgid "No buffers were deleted"
+msgstr "Geen buffers is geskrap nie"
+
+#: buffer.c:702
+msgid "No buffers were wiped out"
+msgstr "Geen buffers is geskrap nie"
+
+#: buffer.c:710
+msgid "1 buffer unloaded"
+msgstr "1 buffer uitgelaai"
+
+#: buffer.c:712
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "%d buffers uitgelaai"
+
+#: buffer.c:717
+msgid "1 buffer deleted"
+msgstr "1 buffer geskrap"
+
+#: buffer.c:719
+#, c-format
+msgid "%d buffers deleted"
+msgstr "%d buffers geskrap"
+
+#: buffer.c:724
+msgid "1 buffer wiped out"
+msgstr "1 buffer geskrap"
+
+#: buffer.c:726
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "%d buffers geskrap"
+
+#: buffer.c:783
+msgid "E84: No modified buffer found"
+msgstr "E84: Geen veranderde buffer gevind nie"
+
+#. back where we started, didn't find anything.
+#: buffer.c:822
+msgid "E85: There is no listed buffer"
+msgstr "E85: Daar is geen gelyste buffer nie"
+
+#: buffer.c:834
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: Kan nie na buffer %ld gaan nie"
+
+#: buffer.c:837
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Kan nie verby laaste buffer gaan nie"
+
+#: buffer.c:839
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Kan nie vóór eerste buffer gaan nie"
+
+#: buffer.c:863
+#, c-format
+msgid "E89: No write since last change for buffer %ld (use ! to override)"
+msgstr ""
+"E89: Buffer %ld nog ongestoor sedert vorige wysiging (gebruik ! om te dwing)"
+
+#: buffer.c:879
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: Kan nie laaste buffer uitlaai nie"
+
+#: buffer.c:1314
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Waarskuwing: Lêerlys loop oor"
+
+#: buffer.c:1480
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: buffer %ld kon nie gevind word nie"
+
+#: buffer.c:1700
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Meer as een treffer vir %s"
+
+#: buffer.c:1702
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: Geen buffer wat by %s pas nie"
+
+#: buffer.c:2105 ex_docmd.c:6065
+#, c-format
+msgid "line %ld"
+msgstr "reël %ld"
+
+#: buffer.c:2188
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Buffer met hierdie naam bestaan alreeds"
+
+#: buffer.c:2481
+msgid " [Modified]"
+msgstr " [Gewysig]"
+
+#: buffer.c:2486
+msgid "[Not edited]"
+msgstr "[Ongewysig]"
+
+#: buffer.c:2491
+msgid "[New file]"
+msgstr "[Nuwe lêer]"
+
+#: buffer.c:2492
+msgid "[Read errors]"
+msgstr "[Leesfoute]"
+
+#: buffer.c:2494 fileio.c:1754
+msgid "[readonly]"
+msgstr "[lees alleen]"
+
+#: buffer.c:2510
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 reël --%d%%--"
+
+#: buffer.c:2510
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld reëls --%d%%--"
+
+#: buffer.c:2518
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "reël %ld van %ld --%d%%-- kolom "
+
+#: buffer.c:2606
+msgid "[No file]"
+msgstr "[Geen lêer]"
+
+#. must be a help buffer
+#: buffer.c:2646
+msgid "help"
+msgstr "help"
+
+#: buffer.c:3151 screen.c:4671
+msgid "[help]"
+msgstr "[help]"
+
+#: buffer.c:3183 screen.c:4677
+msgid "[Preview]"
+msgstr "[Voorskou]"
+
+#: buffer.c:3389
+msgid "All"
+msgstr "Alles"
+
+#: buffer.c:3389
+msgid "Bot"
+msgstr "Ond"
+
+#: buffer.c:3391
+msgid "Top"
+msgstr "Bo"
+
+#: buffer.c:4127
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# Buffer lys:\n"
+
+#: buffer.c:4160
+msgid "[Error List]"
+msgstr "[Foutlys]"
+
+#: buffer.c:4173 memline.c:1513
+msgid "[No File]"
+msgstr "[Geen lêer]"
+
+#: buffer.c:4393
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Tekens ---"
+
+#: buffer.c:4403
+#, c-format
+msgid "Signs for %s:"
+msgstr "Tekens vir %s:"
+
+#: buffer.c:4409
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " reël=%ld id=%d naam=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: Kan nie meer as %ld buffers 'diff' nie"
+
+#: diff.c:648
+msgid "E97: Cannot create diffs"
+msgstr "E97: Kan nie 'diffs' skep nie "
+
+#: diff.c:747
+msgid "Patch file"
+msgstr "Laslap lêer"
+
+#: diff.c:991
+msgid "E98: Cannot read diff output"
+msgstr "E98: Kan nie 'diff' afvoer lees nie"
+
+#: diff.c:1704
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Huidige buffer is nie in 'diff' modus nie"
+
+#: diff.c:1716
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: Geen ander buffer in 'diff' modus nie"
+
+#: diff.c:1724
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr ""
+"E101: Meer as twee buffers in 'diff' modus, weet nie watter een om te "
+"gebruik nie"
+
+#: diff.c:1747
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Kan buffer %s nie vind nie"
+
+#: diff.c:1753
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Buffer \"%s\" is nie in 'diff' modus nie"
+
+#: digraph.c:2168
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: 'Escape' nie toegelaat in digraaf nie"
+
+#: digraph.c:2340
+msgid "Keymap file not found"
+msgstr "Sleutelbindinglêer nie gevind nie"
+
+#: digraph.c:2367
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: :loadkeymap word buite 'n uitvoerlêer gebruik"
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " Sleutelwoord voltooiing (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " ^X modus (^E/^Y/^L/^]/^F/^I/^K/^D/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " Sleutelwoord Lokale voltooiing (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " Hele-reël voltooiing (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " Lêernaam voltooiing (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " Etiketvoltooiing (^]/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " Gidspatroon voltooiing (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " Definisievoltooiing (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " Woordeboekvoltooiing (^K/^N/^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Tesourusvoltooiing (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " Bevelreëlvoltooiing (^V/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Het einde van paragraaf getref"
+
+#: edit.c:894
+msgid "'thesaurus' option is empty"
+msgstr "'thesaurus' opsie is leeg"
+
+#: edit.c:1070
+msgid "'dictionary' option is empty"
+msgstr "'dictionary' opsie is leeg"
+
+#: edit.c:1992
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Deursoek woordeboek: %s"
+
+#: edit.c:2183
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (invoeg) Rol (^E/^Y)"
+
+#: edit.c:2185
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (vervang) Rol (^E/^Y)"
+
+#: edit.c:2496
+#, c-format
+msgid "Scanning: %s"
+msgstr "Soek vir: %s"
+
+#: edit.c:2531
+msgid "Scanning tags."
+msgstr "Deursoek etikette."
+
+#: edit.c:3189
+msgid " Adding"
+msgstr " Word bygevoeg"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3238
+msgid "-- Searching..."
+msgstr "-- Soekend..."
+
+#: edit.c:3294
+msgid "Back at original"
+msgstr "Terug by oorspronklike"
+
+#: edit.c:3299
+msgid "Word from other line"
+msgstr "Woord van ander reël"
+
+#: edit.c:3304
+msgid "The only match"
+msgstr "Die enigste treffer"
+
+#: edit.c:3363
+#, c-format
+msgid "match %d of %d"
+msgstr "treffer %d van %d"
+
+#: edit.c:3366
+#, c-format
+msgid "match %d"
+msgstr "treffer %d"
+
+#: eval.c:696
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Onbekende veranderlike: \"%s\""
+
+#: eval.c:975
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Ontbrekende hakies: %s"
+
+#: eval.c:1043
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Geen veranderlike: \"%s\""
+
+#: eval.c:1284
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Ontbrekende ':' na '?'"
+
+#: eval.c:1898
+msgid "E110: Missing ')'"
+msgstr "E110: Ontbrekende ')'"
+
+#: eval.c:1948
+msgid "E111: Missing ']'"
+msgstr "E111: Ontbrekende ']'"
+
+#: eval.c:2023
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Opsienaam ontbreek: %s"
+
+#: eval.c:2041
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Onbekende opsie: %s"
+
+#: eval.c:2103
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Ontbrekende aanhalingsteken: %s"
+
+#: eval.c:2220
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Ontbrekende aanhalingsteken: %s"
+
+#: eval.c:2537
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Ongeldige parameters vir funksie %s"
+
+#: eval.c:2538
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Onbekende funksie: %s"
+
+#: eval.c:2539
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: Te veel parameters vir funksie: %s"
+
+#: eval.c:2540
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Te min parameters vir funksie: %s"
+
+#: eval.c:2541
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: <SID> word buite skripkonteks gebruik: %s"
+
+#: eval.c:3575
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld reëls: "
+
+#: eval.c:4690
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&OK\n"
+"&Kanselleer"
+
+#: eval.c:5513
+msgid "E240: No connection to Vim server"
+msgstr "E240: Geen verbinding met Vim bediener"
+
+#: eval.c:5603
+msgid "E277: Unable to read a server reply"
+msgstr "E277: Kon bediener-terugvoer nie lees nie"
+
+#: eval.c:5628
+msgid "E258: Unable to send to client"
+msgstr "E258: Kan nie na kliënt stuur nie"
+
+#: eval.c:5669
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Kan nie na %s stuur nie"
+
+#: eval.c:5767
+msgid "(Invalid)"
+msgstr "(Ongeldig)"
+
+#: eval.c:6770
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Ongedefinieerde veranderlike: %s"
+
+#: eval.c:7468
+#, c-format
+msgid "E122: Function %s already exists, use ! to replace"
+msgstr "E122: Funksie %s bestaan alreeds, gebruik ! om te vervang"
+
+#: eval.c:7510
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Ongedefinieerde funksie: %s"
+
+#: eval.c:7523
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Ontbrekende '(': %s"
+
+#: eval.c:7555
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Ongeldige parameter: %s"
+
+#: eval.c:7641
+msgid "E126: Missing :endfunction"
+msgstr "E126: Ontbrekende ':endfunction'"
+
+#: eval.c:7720
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Kan funksie %s nie herdefinieer nie: Dit is in gebruik"
+
+#: eval.c:7777
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: Funksienaam moet met 'n hoofletter begin: %s"
+
+#: eval.c:7783
+msgid "E129: Function name required"
+msgstr "E129: Funksienaam vereis"
+
+#: eval.c:7876
+msgid "function "
+msgstr "funksie "
+
+#: eval.c:7991
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Ongedefinieerde funksie: %s"
+
+#: eval.c:7996
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Kan funksie %s nie verwyder nie: Dit is in gebruik"
+
+#: eval.c:8043
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: Funksieroepdiepte is groter as 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:8094
+#, c-format
+msgid "calling %s"
+msgstr "roep %s"
+
+#. always scroll up, don't overwrite
+#: eval.c:8119 ex_cmds2.c:1973
+#, c-format
+msgid "continuing in %s"
+msgstr "vervolg in %s"
+
+#: eval.c:8173
+msgid "E133: :return not inside a function"
+msgstr "E133: ':return' buite funksie"
+
+#: eval.c:8251
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s lewer #%ld op"
+
+#: eval.c:8254
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s lewer \"%s\" op"
+
+#: eval.c:8395
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# globale veranderlikes:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Hex %02x, Oktaal %03o"
+
+#: ex_cmds.c:428
+msgid "E134: Move lines into themselves"
+msgstr "E134: Skuif reëls in hulself in"
+
+#: ex_cmds.c:497
+msgid "1 line moved"
+msgstr "1 reël geskuif"
+
+#: ex_cmds.c:499
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld reëls geskuif"
+
+#: ex_cmds.c:890
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld reëls filtreer"
+
+#: ex_cmds.c:918
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *Filter* Outobevele mag nie die huidige buffer verander nie"
+
+#: ex_cmds.c:1003
+msgid "[No write since last change]\n"
+msgstr "[Ongestoor sedert vorige verandering]\n"
+
+#: ex_cmds.c:1248
+#, c-format
+msgid "viminfo: %s in line: "
+msgstr "viminfo: %s in reël: "
+
+#: ex_cmds.c:1253
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: Te veel foute, slaan die res van die lêer oor"
+
+#: ex_cmds.c:1282
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Besig om viminfo lêer \"%s\"%s%s%s te lees"
+
+#: ex_cmds.c:1283
+msgid " info"
+msgstr " inligting"
+
+#: ex_cmds.c:1284
+msgid " marks"
+msgstr " merkers"
+
+#: ex_cmds.c:1285
+msgid " FAILED"
+msgstr " GEFAAL"
+
+#: ex_cmds.c:1376
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Viminfo lêer is nie skryfbaar nie: %s"
+
+#: ex_cmds.c:1501
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Kan nie viminfo lêer %s stoor nie!"
+
+#: ex_cmds.c:1509
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Besig om viminfo lêer \"%s\" te stoor"
+
+#. Write the info:
+#: ex_cmds.c:1610
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Hierdie viminfo lêer is gegenereer deur Vim %s.\n"
+
+#: ex_cmds.c:1612
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Jy mag dit wysig as jy versigtig is!\n"
+"\n"
+
+#: ex_cmds.c:1614
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Waarde van 'encoding' toe hierdie lêer gestoor is\n"
+
+#: ex_cmds.c:1713
+msgid "Illegal starting char"
+msgstr "Ongeldige beginkarakter"
+
+#: ex_cmds.c:2053 ex_cmds.c:2289 ex_cmds2.c:602
+msgid "Save As"
+msgstr "Stoor As"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2096
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Lêer is gelaai in ander buffer"
+
+#: ex_cmds.c:2130
+msgid "Write partial file?"
+msgstr "Skryf gedeeltelike lêer?"
+
+#: ex_cmds.c:2137
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Gebruik ! om gedeeltelike buffer te skryf"
+
+#: ex_cmds.c:2223
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Oorskryf bestaande lêer \"%.*s\"?"
+
+#: ex_cmds.c:2294
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: Geen lêernaam vir buffer %ld nie"
+
+#: ex_cmds.c:2332
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: Lêer nie gestoor nie: Stoor is afgeskakel deur die 'write' opsie"
+
+#: ex_cmds.c:2352
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"'readonly' opsie is aan vir \"%.*s\".\n"
+"Wil jy dit forseer?"
+
+#: ex_cmds.c:2517
+msgid "Edit File"
+msgstr "Verander lêer"
+
+#: ex_cmds.c:3024
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Outobevele het nuwe buffer %s onverwags geskrap"
+
+#: ex_cmds.c:3156
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: nie-numeriese parameter vir :z"
+
+#: ex_cmds.c:3241
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: Dop bevele nie toegelaat in rvim"
+
+#: ex_cmds.c:3348
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Patrone kan nie deur letters afgebaken word nie"
+
+#: ex_cmds.c:3686
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "vervang met %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4050
+msgid "(Interrupted) "
+msgstr "(Onderbreek) "
+
+#: ex_cmds.c:4054
+msgid "1 substitution"
+msgstr "1 vervanging"
+
+#: ex_cmds.c:4056
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld vervangings"
+
+#: ex_cmds.c:4059
+msgid " on 1 line"
+msgstr " op 1 reël"
+
+#: ex_cmds.c:4061
+#, c-format
+msgid " on %ld lines"
+msgstr " op %ld reëls"
+
+#: ex_cmds.c:4112
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: Kan nie :global rekursief doen nie "
+
+#: ex_cmds.c:4147
+msgid "E148: Regular expression missing from global"
+msgstr "E148: Patroon ontbreek uit globaal"
+
+#: ex_cmds.c:4196
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Patroon gevind in elke reël: %s"
+
+#: ex_cmds.c:4277
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Vorige Vervangstring:\n"
+"$"
+
+#: ex_cmds.c:4376
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Jammer, geen hulp vir %s nie"
+
+#: ex_cmds.c:4410
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Jammer, hulplêer \"%s\" kan nie gevind word nie"
+
+#: ex_cmds.c:4856
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: Nie 'n gids nie: %s"
+
+#: ex_cmds.c:4884
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: Kan nie %s oopmaak om te skryf nie"
+
+#: ex_cmds.c:4898
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Kan nie %s oop maak om te lees nie"
+
+#: ex_cmds.c:4977
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: Duplikaat etiket \"%s\" in lêer %s"
+
+#: ex_cmds.c:5078
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Onbekende funksie: %s"
+
+#: ex_cmds.c:5098
+msgid "E156: Missing sign name"
+msgstr "E156: Ontbrekende tekennaam"
+
+#: ex_cmds.c:5144
+msgid "E255: Too many signs defined"
+msgstr "E77: Te veel tekens gedefinieer"
+
+#: ex_cmds.c:5186
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Ongeldige tekenteks: %s"
+
+#: ex_cmds.c:5210 ex_cmds.c:5396
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Onbekende opsie: %s"
+
+#: ex_cmds.c:5256
+msgid "E159: Missing sign number"
+msgstr "E159: Ontbrekende tekennommer"
+
+#: ex_cmds.c:5336
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: Ongeldige buffernaam: %s"
+
+#: ex_cmds.c:5375
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Ongeldige teken ID: %ld"
+
+#: ex_cmds.c:5546
+msgid "[Deleted]"
+msgstr "[Geskrap]"
+
+#: ex_cmds2.c:70
+msgid "Entering Debug mode. Type \"cont\" to leave."
+msgstr "Ontfoutmodus begin nou. Tik \"cont\" om te verlaat."
+
+#: ex_cmds2.c:74 ex_docmd.c:771
+#, c-format
+msgid "line %ld: %s"
+msgstr "reël %ld: %s"
+
+#: ex_cmds2.c:76
+#, c-format
+msgid "cmd: %s"
+msgstr "cmd: %s"
+
+#: ex_cmds2.c:224
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Inspeksiepunt in \"%s%s\" reël %ld"
+
+#: ex_cmds2.c:388
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Inspeksiepunt kon nie gevind word nie: %s"
+
+#: ex_cmds2.c:414
+msgid "No breakpoints defined"
+msgstr "Geen inspeksiepunte gedefinieer nie"
+
+#: ex_cmds2.c:419
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s reël %ld"
+
+#: ex_cmds2.c:625
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Stoor veranderinge na \"%.*s\"?"
+
+#: ex_cmds2.c:627 ex_docmd.c:8612
+msgid "Untitled"
+msgstr "Ongetiteld"
+
+#: ex_cmds2.c:763
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Buffer \"%s\" is nie geskryf sedert vorige wysiging nie"
+
+#: ex_cmds2.c:832
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "Waarskuwing: Ander buffer onverwags betree (kyk na outobevele)"
+
+#: ex_cmds2.c:1208
+msgid "E163: There is only one file to edit"
+msgstr "E163: Daar is net een lêer om te bewerk"
+
+#: ex_cmds2.c:1210
+msgid "E164: Cannot go before first file"
+msgstr "E164: Kan nie vóór die eerste lêer gaan nie"
+
+#: ex_cmds2.c:1212
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Kan nie verby die laaste lêer gaan nie"
+
+#: ex_cmds2.c:1632
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Besig om te soek vir \"%s\" in \"%s\""
+
+#: ex_cmds2.c:1654
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Besig om te soek vir \"%s\""
+
+#: ex_cmds2.c:1678
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "kon nie in 'runtimepath' gevind word nie: \"%s\""
+
+#: ex_cmds2.c:1712
+msgid "Run Macro"
+msgstr "Voer Makro uit"
+
+#: ex_cmds2.c:1817
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "Kan nie gids uitvoer nie: \"%s\""
+
+#: ex_cmds2.c:1847
+#, c-format
+msgid "could not source \"%s\""
+msgstr "kon nie \"%s\" uitvoer nie"
+
+#: ex_cmds2.c:1849
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "reël %ld: kon nie \"%s\" uitvoer nie"
+
+#: ex_cmds2.c:1863
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "besig om \"%s\" uit te voer"
+
+#: ex_cmds2.c:1865
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "reël %ld: voer nou \"%s\" uit"
+
+#: ex_cmds2.c:1971
+#, c-format
+msgid "finished sourcing %s"
+msgstr "%s klaar uitgevoer"
+
+#: ex_cmds2.c:2272
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Waarskuwing: Verkeerde reëlskeiding, ^M ontbreek dalk"
+
+#: ex_cmds2.c:2321
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: ':scriptencoding' buite 'n uitvoerlêer gebruik"
+
+#: ex_cmds2.c:2354
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: ':finish' buite 'n uitvoerlêer gebruik"
+
+#: ex_cmds2.c:2820
+msgid "No text to be printed"
+msgstr "Geen teks om te druk nie"
+
+#: ex_cmds2.c:2898
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "Druk nou bladsy %d (%d%%)"
+
+#: ex_cmds2.c:2907
+#, c-format
+msgid " Copy %d of %d"
+msgstr " Kopie %d van %d"
+
+#: ex_cmds2.c:2959
+#, c-format
+msgid "Printed: %s"
+msgstr "Gedruk: %s"
+
+#: ex_cmds2.c:2966
+msgid "Printing aborted"
+msgstr "Drukkery gestaak"
+
+#: ex_cmds2.c:3344
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Kan nie na 'PostScript' afvoerlêer skryf nie"
+
+#: ex_cmds2.c:4019
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Kan nie 'PostScript' afvoerlêer oopmaak nie"
+
+#: ex_cmds2.c:4057
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Kan nie lêer %s oopmaak nie"
+
+#: ex_cmds2.c:4068
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Kan nie 'PostScript' hulpbron-lêer \"%s\" lees nie"
+
+#: ex_cmds2.c:4266
+msgid "Sending to printer..."
+msgstr "Besig om te stuur na drukker..."
+
+#: ex_cmds2.c:4270
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: Kon nie 'PostScript' lêer druk nie"
+
+#: ex_cmds2.c:4272
+msgid "Print job sent."
+msgstr "Druktaak gestuur."
+
+#: ex_cmds2.c:4651
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Huidige %staal: \"%s\""
+
+#: ex_cmds2.c:4658
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Kan nie taal na \"%s\" verander nie"
+
+#: ex_docmd.c:491
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Betree Ex modus. Tik \"visual\" om na Normale modus terug te keer."
+
+#. must be at EOF
+#: ex_docmd.c:527
+msgid "At end-of-file"
+msgstr "By lêereinde"
+
+#: ex_docmd.c:602
+msgid "E169: Command too recursive"
+msgstr "E169: Bevel te rekursief"
+
+#: ex_docmd.c:911
+msgid "E170: Missing :endwhile"
+msgstr "E170: Ontbrekende ':endwhile'"
+
+#: ex_docmd.c:913
+msgid "E171: Missing :endif"
+msgstr "E171: Ontbrekende ':endif'"
+
+#: ex_docmd.c:923
+msgid "End of sourced file"
+msgstr "Einde van uitvoerlêer"
+
+#: ex_docmd.c:924
+msgid "End of function"
+msgstr "Einde van funksie "
+
+#: ex_docmd.c:1344
+msgid "Ambiguous use of user-defined command"
+msgstr "Dubbelsinnige gebruik van gebruiker-gedefinieerde bevel"
+
+#: ex_docmd.c:1358
+msgid "Not an editor command"
+msgstr "Nie 'n verwerkerbevel nie"
+
+#: ex_docmd.c:1441
+msgid "Don't panic!"
+msgstr "Bly kalm!"
+
+#: ex_docmd.c:1460
+msgid "Backwards range given"
+msgstr "Terugwaardse omvang gegee"
+
+#: ex_docmd.c:1469
+msgid "Backwards range given, OK to swap"
+msgstr "Terugwaardse omvang gegee, OK om te ruil"
+
+#: ex_docmd.c:1580
+msgid "Use w or w>>"
+msgstr "Gebruik w of w>>"
+
+#: ex_docmd.c:3086
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Jammer, die bevel is nie geïmplementeer nie"
+
+#: ex_docmd.c:3256
+msgid "E172: Only one file name allowed"
+msgstr "E172: Slegs een lêernaam toegelaat"
+
+#: ex_docmd.c:3810
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "Nog %d lêers om te bewerk. Stop in elk geval?"
+
+#: ex_docmd.c:3817
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: Nog %ld lêers om te bewerk"
+
+#: ex_docmd.c:3911
+msgid "E174: Command already exists: use ! to redefine"
+msgstr "E174: Bevel bestaan alreeds: gebruik ! om te herdefinieer"
+
+#: ex_docmd.c:4016
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Naam Args Reeks Klaar Definisie"
+
+#: ex_docmd.c:4105
+msgid "No user-defined commands found"
+msgstr "Geen gebruiker-gedefinieerde bevele gevind nie"
+
+#: ex_docmd.c:4136
+msgid "E175: No attribute specified"
+msgstr "E175: Geen eienskappe gespesifiseer nie"
+
+#: ex_docmd.c:4188
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Ongeldige aantal parameters"
+
+#: ex_docmd.c:4203
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: Telling kan nie twee keer gespesifiseer word nie"
+
+#: ex_docmd.c:4213
+msgid "E178: Invalid default value for count"
+msgstr "E178: Ongeldige verstekwaarde vir telling"
+
+#: ex_docmd.c:4241
+msgid "E179: argument required for complete"
+msgstr "E179: parameter nodig vir voltooiing"
+
+#: ex_docmd.c:4260
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Ongeldige voltooiingswaarde: %s"
+
+#: ex_docmd.c:4268
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Ongeldige eienskap: %s"
+
+#: ex_docmd.c:4309
+msgid "E182: Invalid command name"
+msgstr "E182: Ongeldige bevelnaam"
+
+#: ex_docmd.c:4324
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: Gebruiker-gedefinieerde bevele moet met 'n hoofletter begin"
+
+#: ex_docmd.c:4393
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: Geen gebruiker-gedefinieerde bevel nie: %s"
+
+#: ex_docmd.c:4844
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Kan nie kleurskema %s vind nie"
+
+#: ex_docmd.c:4852
+msgid "Greetings, Vim user!"
+msgstr "Goeiedag, Vim gebruiker!"
+
+#: ex_docmd.c:5549
+msgid "Edit File in new window"
+msgstr "Bewerk lêer in nuwe venster"
+
+#: ex_docmd.c:5815
+msgid "No swap file"
+msgstr "Geen ruillêer"
+
+#: ex_docmd.c:5919
+msgid "Append File"
+msgstr "Las aan by lêer"
+
+#: ex_docmd.c:5978
+msgid "E186: No previous directory"
+msgstr "E186: Geen vorige gids nie"
+
+#: ex_docmd.c:6055
+msgid "E187: Unknown"
+msgstr "E187: Onbekend"
+
+#: ex_docmd.c:6173
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Vensterposisie: X %d, Y %d"
+
+#: ex_docmd.c:6178
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr ""
+"E188: Verkryging van vensterposisie is nie vir hierdie platform "
+"geïmplementeer nie"
+
+#: ex_docmd.c:6444
+msgid "Save Redirection"
+msgstr "Stoor Herversturing"
+
+#: ex_docmd.c:6593
+msgid "Save View"
+msgstr "Stoor Oorsig"
+
+#: ex_docmd.c:6594
+msgid "Save Session"
+msgstr "Stoor Sessie"
+
+#: ex_docmd.c:6596
+msgid "Save Setup"
+msgstr "Stoor konfigurasie"
+
+#: ex_docmd.c:6745
+#, c-format
+msgid "E189: \"%s\" exists (use ! to override)"
+msgstr "E189: \"%s\" bestaan (gebruik ! om te dwing)"
+
+#: ex_docmd.c:6750
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: Kan \"%s\" nie oopmaak vir skryf nie"
+
+#. set mark
+#: ex_docmd.c:6774
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr ""
+"E191: Parameter moet 'n letter of 'n terug/vorentoe aanhalingsteken wees"
+
+#: ex_docmd.c:6803
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Rekursiewe gebruik van ':normal' te diep"
+
+#: ex_docmd.c:7171
+msgid ":if nesting too deep"
+msgstr "geneste ':if' te diep"
+
+#: ex_docmd.c:7206
+msgid ":endif without :if"
+msgstr "':endif' sonder ':if'"
+
+#: ex_docmd.c:7226
+msgid ":else without :if"
+msgstr "':else' sonder ':if'"
+
+#: ex_docmd.c:7228
+msgid ":elseif without :if"
+msgstr "':elseif' sonder ':if'"
+
+#: ex_docmd.c:7280
+msgid ":while nesting too deep"
+msgstr "':while' te diep genes"
+
+#: ex_docmd.c:7326
+msgid ":continue without :while"
+msgstr "':continue' sonder ':while'"
+
+#: ex_docmd.c:7353
+msgid ":break without :while"
+msgstr "':break' sonder ':while'"
+
+#: ex_docmd.c:7376 ex_docmd.c:7381
+msgid ":endwhile without :while"
+msgstr "':endwhile' sonder ':while'"
+
+#: ex_docmd.c:7402
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: ':endfunction' nie in 'n funksie nie"
+
+#: ex_docmd.c:7582
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: Geen alternatiewe lêernaam vir '#' nie"
+
+#: ex_docmd.c:7613
+msgid "no autocommand file name to substitute for \"<afile>\""
+msgstr "geen outobevel-lêernaam om \"<afile>\" mee te vervang nie"
+
+#: ex_docmd.c:7621
+msgid "no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "geen outobevel buffernommer om \"<abuf>\" mee te vervang nie"
+
+#: ex_docmd.c:7632
+msgid "no autocommand match name to substitute for \"<amatch>\""
+msgstr "geen outobevel treffernaam om \"<amatch>\" mee te vervang nie"
+
+#: ex_docmd.c:7642
+msgid "no :source file name to substitute for \"<sfile>\""
+msgstr "geen ':source' lêernaam om \"<sfile>\" mee te vervang nie"
+
+#: ex_docmd.c:7683
+#, no-c-format
+msgid "Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "Leë lêernaam vir '%' of '#', werk slegs met \":p:h\""
+
+#: ex_docmd.c:7685
+msgid "Evaluates to an empty string"
+msgstr "Evalueer na 'n leë string"
+
+#: ex_docmd.c:8594
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: Kan 'viminfo' lêer nie oopmaak om te lees nie"
+
+#: ex_docmd.c:8767
+msgid "E196: No digraphs in this version"
+msgstr "E196: Geen digrawe in hierdie weergawe nie"
+
+#: ex_getln.c:2785
+msgid "tagname"
+msgstr "etiketnaam"
+
+#: ex_getln.c:2788
+msgid " kind file\n"
+msgstr " tipe lêer\n"
+
+#: ex_getln.c:3997
+msgid "'history' option is zero"
+msgstr "'history' opsie is nul"
+
+#: ex_getln.c:4237
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s Geskiedenis (van nuutste na oudste):\n"
+
+#: ex_getln.c:4238
+msgid "Command Line"
+msgstr "Bevelreël"
+
+#: ex_getln.c:4239
+msgid "Search String"
+msgstr "Soekstring"
+
+#: ex_getln.c:4240
+msgid "Expression"
+msgstr "Uitdrukking"
+
+#: ex_getln.c:4241
+msgid "Input Line"
+msgstr "Invoer Lyn"
+
+#: ex_getln.c:4271
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: 'cmd_pchar' verby die einde van opdraglengte"
+
+#: ex_getln.c:4435
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Aktiewe venster of buffer geskrap"
+
+#: fileio.c:347
+msgid "Illegal file name"
+msgstr "Ongeldige lêernaam"
+
+#: fileio.c:371 fileio.c:495 fileio.c:2491 fileio.c:2529
+msgid "is a directory"
+msgstr "is 'n gids"
+
+#: fileio.c:373
+msgid "is not a file"
+msgstr "is nie 'n lêer nie"
+
+#: fileio.c:515 fileio.c:3581
+msgid "[New File]"
+msgstr "[Nuwe lêer]"
+
+#: fileio.c:532
+msgid "[Permission Denied]"
+msgstr "[Toestemming Geweier]"
+
+#: fileio.c:624
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: '*ReadPre' outobevele het die lêer onleesbaar gemaak"
+
+#: fileio.c:626
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: '*ReadPre' outobevele mag nie die huidige buffer verander nie"
+
+#: fileio.c:646
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: Lees nou vanaf 'stdin'...\n"
+
+#: fileio.c:652
+msgid "Reading from stdin..."
+msgstr "Lees nou vanaf stdin... "
+
+#. Re-opening the original file failed!
+#: fileio.c:876
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: Omsetting het lêer onleesbaar gemaak!"
+
+#: fileio.c:1732
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:1739
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:1746
+msgid "[socket]"
+msgstr "[socket]"
+
+#: fileio.c:1754
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:1764
+msgid "[CR missing]"
+msgstr "[CR ontbreek]"
+
+#: fileio.c:1769
+msgid "[NL found]"
+msgstr "[NL gevind]"
+
+#: fileio.c:1774
+msgid "[long lines split]"
+msgstr "[lang reëls verdeel]"
+
+#: fileio.c:1780 fileio.c:3565
+msgid "[NOT converted]"
+msgstr "[NIE omgesit nie]"
+
+#: fileio.c:1785 fileio.c:3570
+msgid "[converted]"
+msgstr "[omgesit]"
+
+#: fileio.c:1792 fileio.c:3595
+msgid "[crypted]"
+msgstr "[gekodeer]"
+
+#: fileio.c:1799
+msgid "[CONVERSION ERROR]"
+msgstr "[OMSETTINGSFOUT]"
+
+#: fileio.c:1806
+msgid "[READ ERRORS]"
+msgstr "[LEESFOUTE]"
+
+#: fileio.c:2013
+msgid "Can't find temp file for conversion"
+msgstr "Kan nie tydelike lêer vir omsetting vind nie"
+
+#: fileio.c:2020
+msgid "Conversion with 'charconvert' failed"
+msgstr "Omsetting met 'charconvert' het gefaal"
+
+#: fileio.c:2023
+msgid "can't read output of 'charconvert'"
+msgstr "kan afvoer van 'charconvert' nie lees nie"
+
+#: fileio.c:2407
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Outobevele het die skryfbuffer geskrap of uitgelaai"
+
+#: fileio.c:2430
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Outobevel het etlike reëls op onverwagse wyse verander "
+
+#: fileio.c:2496 fileio.c:2513
+msgid "is not a file or writable device"
+msgstr "is nie 'n lêer of 'n skryfbare toestel nie"
+
+#: fileio.c:2555
+msgid "is read-only (use ! to override)"
+msgstr "is lees-alleen (gebruik ! om te dwing)"
+
+#: fileio.c:2851
+msgid "Can't write to backup file (use ! to override)"
+msgstr "Kan nie na rugsteunlêer skryf nie (gebruik ! om te dwing)"
+
+#: fileio.c:2863
+msgid "Close error for backup file (use ! to override)"
+msgstr "Sluitfout vir rugsteunlêer (gebruik ! om te dwing)"
+
+#: fileio.c:2865
+msgid "Can't read file for backup (use ! to override)"
+msgstr "Kan rugsteunlêer nie lees nie (gebruik ! om te dwing)"
+
+#: fileio.c:2881
+msgid "Cannot create backup file (use ! to override)"
+msgstr "Kan rugsteunlêer nie skep nie (gebruik ! om te dwing)"
+
+#: fileio.c:2970
+msgid "Can't make backup file (use ! to override)"
+msgstr "Kan rugsteunlêer nie skep nie (gebruik ! om te dwing)"
+
+#: fileio.c:3032
+msgid "The resource fork will be lost (use ! to override)"
+msgstr "Die hulpbronvurk sal verlore gaan (gebruik ! om te dwing)"
+
+#: fileio.c:3121
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: Kan nie tydelike lêer vind vir skryf nie"
+
+#: fileio.c:3139
+msgid "E213: Cannot convert (use ! to write without conversion)"
+msgstr "E213: Kan nie omsit nie (gebruik ! om te skryf sonder omsetting)"
+
+#: fileio.c:3176
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Kan lêer nie oopmaak vir skryf nie"
+
+#: fileio.c:3180
+msgid "E212: Can't open file for writing"
+msgstr "E212: Kan lêer nie oopmaak vir skryf nie"
+
+#: fileio.c:3423
+msgid "Close failed"
+msgstr "Sluiting gefaal"
+
+#: fileio.c:3481
+msgid "write error, conversion failed"
+msgstr "skryffout, omsetting gefaal"
+
+#: fileio.c:3487
+msgid "write error (file system full?)"
+msgstr "skryffout (lêerstelsel vol?)"
+
+#: fileio.c:3560
+msgid " CONVERSION ERROR"
+msgstr " OMSETTINGSFOUT"
+
+#: fileio.c:3576
+msgid "[Device]"
+msgstr "[Toestel]"
+
+#: fileio.c:3581
+msgid "[New]"
+msgstr "[Nuut]"
+
+#: fileio.c:3603
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:3603
+msgid " appended"
+msgstr " bygevoeg"
+
+#: fileio.c:3605
+msgid " [w]"
+msgstr " [w]"
+
+#: fileio.c:3605
+msgid " written"
+msgstr " geskryf"
+
+#: fileio.c:3655
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: patchmode: kan oorspronklike lêer nie stoor nie"
+
+#: fileio.c:3677
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: kan leë oorspronglêer nie 'touch' nie"
+
+#: fileio.c:3692
+msgid "E207: Can't delete backup file"
+msgstr "E207: Kan rugsteunlêer nie verwyder nie"
+
+#: fileio.c:3744
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"WAARSKUWING: Oorspronklike lêer mag verlore of beskadig wees\n"
+
+#: fileio.c:3746
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "moenie die verwerker verlaat voor die lêer suksesvol geskryf is nie!"
+
+#: fileio.c:3826
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:3826
+msgid "[dos format]"
+msgstr "[dos formaat]"
+
+#: fileio.c:3833
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:3833
+msgid "[mac format]"
+msgstr "[mac formaat]"
+
+#: fileio.c:3840
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:3840
+msgid "[unix format]"
+msgstr "[unix formaat]"
+
+#: fileio.c:3867
+msgid "1 line, "
+msgstr "1 reël, "
+
+#: fileio.c:3869
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld reëls, "
+
+#: fileio.c:3872
+msgid "1 character"
+msgstr "1 karakter"
+
+#: fileio.c:3874
+#, c-format
+msgid "%ld characters"
+msgstr "%ld karakters"
+
+#: fileio.c:3884
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:3884
+msgid "[Incomplete last line]"
+msgstr "[Onvoltooide laaste reël]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:3903
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "WAARSKUWING: Die lêer het verander sedert dit gelees is!!!"
+
+#: fileio.c:3905
+msgid "Do you really want to write to it"
+msgstr "Wil jy regtig soontoe skryf?"
+
+#: fileio.c:4861
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Kan nie skryf na \"%s\""
+
+#: fileio.c:4868
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Kan \"%s\" nie sluit nie"
+
+#: fileio.c:4871
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Kan \"%s\" nie lees nie"
+
+#: fileio.c:5035
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: 'FileChangedShell' outobevel het buffer verwyder"
+
+#: fileio.c:5043
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: Waarskuwing: Lêer \"%s\" is nie meer beskikbaar nie"
+
+#: fileio.c:5056
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: Waarskuwing: Lêer \"%s\" het verander sedert bewerking begin het en die "
+"buffer in Vim het ook verander"
+
+#: fileio.c:5059
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: Waarskuwing: Lêer \"%s\" het verander sedert bewerking begin het"
+
+#: fileio.c:5061
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr ""
+"W16: Waarskuwing: Modus van lêer \"%s\" het verander sedert bewerking begin "
+"het"
+
+#: fileio.c:5071
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: Waarskuwing: Lêer \"%s\" is geskep sedert bewerking begin het"
+
+#: fileio.c:5088
+msgid "Warning"
+msgstr "Waarskuwing"
+
+#: fileio.c:5089
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Laai Lêer"
+
+#: fileio.c:5165
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: Kon nie \"%s\" herlaai nie"
+
+#: fileio.c:5670
+msgid "--Deleted--"
+msgstr "--Geskrap--"
+
+#. the group doesn't exist
+#: fileio.c:5830
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Geen sodanige groep nie: \"%s\""
+
+#: fileio.c:5955
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Ongeldige karakter na *: %s"
+
+#: fileio.c:5966
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Geen sodanige gebeurtenis nie: %s"
+
+#. Highlight title
+#: fileio.c:6115
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Outobevele ---"
+
+#: fileio.c:6386
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Kan nie outobevele uitvoer vir 'ALL' gebeurtenisse nie"
+
+#: fileio.c:6409
+msgid "No matching autocommands"
+msgstr "Geen passende outobevele nie"
+
+#: fileio.c:6681
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: outobevele te diep genes"
+
+#: fileio.c:6968
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s outobevele vir \"%s\""
+
+#: fileio.c:6976
+#, c-format
+msgid "Executing %s"
+msgstr "Voer %s uit"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7044
+#, c-format
+msgid "autocommand %s"
+msgstr "outobevel %s"
+
+#: fileio.c:7566
+msgid "E219: Missing {."
+msgstr "E219: Ontbrekende {."
+
+#: fileio.c:7568
+msgid "E220: Missing }."
+msgstr "E220: Ontbrekende }."
+
+#: fold.c:66
+msgid "No fold found"
+msgstr "Geen vou gevind nie"
+
+#: fold.c:554
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: Kan nie vou skep met huidige 'foldmethod' nie"
+
+#: fold.c:556
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: Kan nie vou skrap met huidige 'foldmethod' nie"
+
+#: fold.c:1700
+msgid "E221: 'commentstring' is empty"
+msgstr "E221: 'commentstring' opsie is leeg"
+
+#: getchar.c:268
+msgid "E222: Add to read buffer"
+msgstr "E222: Voeg by leesbuffer"
+
+#: getchar.c:2114
+msgid "E223: recursive mapping"
+msgstr "E223: rekursiewe binding"
+
+#: getchar.c:2966
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: globale afkorting bestaan alreeds vir %s"
+
+#: getchar.c:2969
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: globale binding bestaan alreeds vir %s"
+
+#: getchar.c:3096
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: afkorting bestaan already vir %s"
+
+#: getchar.c:3099
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: binding bestaan alreeds vir %s"
+
+#: getchar.c:3163
+msgid "No abbreviation found"
+msgstr "Geen afkorting gevind nie"
+
+#: getchar.c:3165
+msgid "No mapping found"
+msgstr "Geen binding gevind nie"
+
+#: getchar.c:3990
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: Ongeldige modus"
+
+#: gui.c:181
+msgid "E229: Cannot start the GUI"
+msgstr "E229: Kan nie die GUI begin nie"
+
+#: gui.c:306
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Kan nie lees uit \"%s\" nie"
+
+#: gui.c:431
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: 'guifontwide' ongeldig"
+
+#: gui.c:3926
+msgid "Error"
+msgstr "Fout"
+
+#: gui.c:3927
+msgid "&Ok"
+msgstr "&Ok"
+
+#: gui_at_fs.c:290
+msgid "<cannot open> "
+msgstr "<kan nie oopmaak nie> "
+
+#: gui_at_fs.c:1115
+#, c-format
+msgid "vim_SelFile: can't get font %s"
+msgstr "'vim_SelFile': kan font %s nie kry nie"
+
+#: gui_at_fs.c:2538
+msgid "vim_SelFile: can't return to current directory"
+msgstr "'vim_SelFile': Kan nie terugkeer na huidige gids nie"
+
+#: gui_at_fs.c:2557
+msgid "Pathname:"
+msgstr "Gidsnaam:"
+
+#: gui_at_fs.c:2563
+msgid "vim_SelFile: can't get current directory"
+msgstr "vim_SelFile: Kan nie huidige gids verkry nie"
+
+#: gui_at_fs.c:2571 gui_motif.c:1607
+msgid "OK"
+msgstr "OK"
+
+#. 'Cancel' button
+#: gui_at_fs.c:2571 gui_gtk.c:1683 gui_motif.c:1602 gui_motif.c:2823
+msgid "Cancel"
+msgstr "Kanselleer"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Rolstaafelement: Kon nie pikselmatriks-duimnael se geometrie kry nie"
+
+#: gui_athena.c:1928 gui_motif.c:1855
+msgid "Vim dialog"
+msgstr "Vim dialooghokkie"
+
+#: gui_beval.c:68
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: Kan nie BalloonEval skep met beide boodskap en terugroep nie"
+
+#: gui_gtk.c:1144
+msgid "Vim dialog..."
+msgstr "Vim dialooghokkie..."
+
+#: gui_gtk.c:1519 gui_motif.c:2742
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Soek en Vervang..."
+
+#: gui_gtk.c:1524 gui_motif.c:2744
+msgid "VIM - Search..."
+msgstr "VIM - Soek..."
+
+#: gui_gtk.c:1547 gui_motif.c:2862
+msgid "Find what:"
+msgstr "Soek na:"
+
+#: gui_gtk.c:1565 gui_motif.c:2894
+msgid "Replace with:"
+msgstr "Vervang met:"
+
+#. exact match only button
+#: gui_gtk.c:1597 gui_motif.c:2996
+msgid "Match exact word only"
+msgstr "Tref slegs presiese woord"
+
+#: gui_gtk.c:1609 gui_motif.c:2964
+msgid "Direction"
+msgstr "Rigting"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:1621 gui_motif.c:2976
+msgid "Up"
+msgstr "Op"
+
+#: gui_gtk.c:1625 gui_motif.c:2984
+msgid "Down"
+msgstr "Af"
+
+#. 'Find Next' button
+#: gui_gtk.c:1647 gui_motif.c:2766
+msgid "Find Next"
+msgstr "Vind volgende"
+
+#. 'Replace' button
+#: gui_gtk.c:1664 gui_motif.c:2783
+msgid "Replace"
+msgstr "Vervang"
+
+#. 'Replace All' button
+#: gui_gtk.c:1673 gui_motif.c:2796
+msgid "Replace All"
+msgstr "Vervang alles"
+
+#: gui_gtk_x11.c:1076 gui_x11.c:1199
+msgid "E233: cannot open display"
+msgstr "E233: kan nie vertoonskerm oopmaak nie"
+
+#: gui_gtk_x11.c:2433 gui_x11.c:2002
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Onbekende fontstel: %s"
+
+#: gui_gtk_x11.c:2460
+msgid "Font Selection"
+msgstr "Fontkeuse"
+
+#: gui_gtk_x11.c:2702 gui_mac.c:2780 gui_w48.c:1197 gui_x11.c:1838
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Onbekende font: %s"
+
+#: gui_gtk_x11.c:2713 gui_x11.c:1862
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: Font \"%s\" is nie 'n vaste-wydte font nie"
+
+#: gui_gtk_x11.c:2843
+#, c-format
+msgid "E242: Color name not recognized: %s"
+msgstr "E242: Kleurnaam is onbekend: %s"
+
+#: gui_gtk_x11.c:3519 ui.c:1929
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "'CUT_BUFFER0' is gebruik in plaas van leë seleksie"
+
+#: gui_motif.c:1601 gui_motif.c:1604
+msgid "Filter"
+msgstr "Filter"
+
+#: gui_motif.c:1603
+msgid "Directories"
+msgstr "Gidse"
+
+#: gui_motif.c:1605
+msgid "Help"
+msgstr "Hulp"
+
+#: gui_motif.c:1606
+msgid "Files"
+msgstr "Lêers"
+
+#: gui_motif.c:1608
+msgid "Selection"
+msgstr "Seleksie"
+
+#: gui_motif.c:2809
+msgid "Undo"
+msgstr "Herroep"
+
+#: gui_riscos.c:951
+#, c-format
+msgid "E235: Can't load Zap font '%s'"
+msgstr "E235: Kan nie Zap font '%s' laai nie"
+
+#: gui_riscos.c:1047
+#, c-format
+msgid "E235: Can't use font %s"
+msgstr "E235: Kan nie font %s gebruik nie"
+
+#: gui_riscos.c:1167
+#, c-format
+msgid "E242: Missing color: %s"
+msgstr "E242: Ontbrekende kleur: %s"
+
+#: gui_riscos.c:3269
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Besig om doodsboodskap aan kindproses te stuur.\n"
+
+#: gui_w32.c:823
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Parameter nie bekend: \"-%s\"; Gebruik die OLE weergawe."
+
+#: gui_w48.c:2068
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Vind string (gebruik '\\\\' om 'n '\\' te vind"
+
+#: gui_w48.c:2093
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Vind & vervang string (gebruik '\\\\' om 'n '\\' te vind"
+
+#: gui_x11.c:1419
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: Kan nie kleurkaart-inskrywing toeken nie, sommige kleure mag "
+"verkeerd wees"
+
+#: gui_x11.c:1992
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr ""
+"E250: Fonte vir die volgende karakterstelle ontbreek in fontversameling %s:"
+
+#: gui_x11.c:2035
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Fontstel naam: %s"
+
+#: gui_x11.c:2036
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "Font '%s' is nie 'n vaste-wydte font nie"
+
+#: gui_x11.c:2055
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Fonstel naam: %s\n"
+
+#: gui_x11.c:2056
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Font0: %s\n"
+
+#: gui_x11.c:2057
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Font1: %s\n"
+
+#: gui_x11.c:2058
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "Font%d wydte is nie twee keer díe van font0 nie\n"
+
+#: gui_x11.c:2059
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "Font0 wydte: %ld\n"
+
+#: gui_x11.c:2060
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"Font1 wydte: %ld\n"
+"\n"
+
+#: gui_x11.c:2206
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: Kan nie kleur %s toeken nie"
+
+#: gui_x11.c:3256
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Fout -- kon nie tekendata lees nie!"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: Hangul outomatiserings FOUT"
+
+#: if_cscope.c:26
+#, c-format
+msgid "Usage: cs[cope] %s"
+msgstr "Gebruik: cs[cope] %s"
+
+#: if_cscope.c:67
+msgid "Add a new database"
+msgstr "Voeg 'n nuwe databasis by"
+
+#: if_cscope.c:69
+msgid "Query for a pattern"
+msgstr "Soek vir 'n patroon"
+
+#: if_cscope.c:71
+msgid "Show this message"
+msgstr "Wys hierdie boodskap"
+
+#: if_cscope.c:73
+msgid "Kill a connection"
+msgstr "Sluit 'n verbinding"
+
+#: if_cscope.c:75
+msgid "Reinit all connections"
+msgstr "Herstel alle verbindings"
+
+#: if_cscope.c:77
+msgid "Show connections"
+msgstr "Wys verbindings"
+
+#: if_cscope.c:108
+msgid "This cscope command does not support splitting the window.\n"
+msgstr ""
+"Hierdie 'cscope' bevel ondersteun nie die splitsing van die venster nie.\n"
+
+#: if_cscope.c:143
+msgid "Usage: cstag <ident>"
+msgstr "Gebruik: 'cstag <ident>'"
+
+#: if_cscope.c:199
+msgid "E257: cstag: tag not found"
+msgstr "E257: 'cstag': etiket nie gevind nie"
+
+#: if_cscope.c:407 if_cscope.c:451
+#, c-format
+msgid "stat(%s) error: %d"
+msgstr "'stat(%s)' fout: %d"
+
+#: if_cscope.c:460 if_cscope.c:467
+#, c-format
+msgid "Added cscope database %s"
+msgstr "'cscope' databasis %s bygevoeg"
+
+#: if_cscope.c:474
+#, c-format
+msgid "%s is not a directory or a valid cscope database"
+msgstr "%s is nie 'n gids of 'n geldige 'cscope' databasis nie"
+
+#: if_cscope.c:557
+#, c-format
+msgid "error reading cscope connection %d"
+msgstr "'cscope' verbinding %d kon nie gelees word nie"
+
+#: if_cscope.c:633
+msgid "unknown cscope search type"
+msgstr "onbekende 'cscope' soektipe"
+
+#: if_cscope.c:680
+msgid "Could not create cscope pipes"
+msgstr "Kon nie 'cscope' pype skep nie"
+
+#: if_cscope.c:745
+msgid "cs_create_connection exec failed"
+msgstr "'cs_create_connection' uitvoering het misluk"
+
+#: if_cscope.c:755
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "'cs_create_connection': 'fdopen' vir 'to_fp' het misluk"
+
+#: if_cscope.c:757
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "'cs_create_connection': 'fdopen' vir 'fr_fp' het misluk"
+
+#: if_cscope.c:785
+msgid "no cscope connections"
+msgstr "geen 'cscope' verbindings nie"
+
+#: if_cscope.c:855
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: geen treffers gevind vir 'cscope' versoek %s van %s nie"
+
+#: if_cscope.c:899
+msgid "cscope commands:\n"
+msgstr "'cscope' bevele:\n"
+
+#: if_cscope.c:902
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)\n"
+msgstr "%-5s: %-30s (Gebruik: %s)\n"
+
+#: if_cscope.c:970
+msgid "duplicate cscope database not added"
+msgstr "duplikaat 'cscope' databasis nie bygevoeg nie"
+
+#: if_cscope.c:981
+msgid "maximum number of cscope connections reached"
+msgstr "maksimum aantal 'cscope' verbindings bereik"
+
+#: if_cscope.c:1102
+msgid "E260: cscope connection not found"
+msgstr "E260: 'cscope' verbinding nie gevind nie"
+
+#: if_cscope.c:1105
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: 'cscope' verbinding %s nie gevind nie"
+
+#: if_cscope.c:1141
+msgid "cscope connection closed"
+msgstr "'cscope' verbinding gesluit"
+
+#: if_cscope.c:1149
+#, c-format
+msgid "cscope connection %s closed\n"
+msgstr "'cscope' verbinding %s gesluit\n"
+
+#. should not reach here
+#: if_cscope.c:1290
+msgid "fatal error in cs_manage_matches"
+msgstr "fatale fout in 'cs_manage_matches'"
+
+#: if_cscope.c:1341
+#, c-format
+msgid "E262: error reading cscope connection %d"
+msgstr "E262: 'cscope' verbinding %d kon nie gelees word nie"
+
+# njj: dalk 'verbinding' ipv 'verbinding' orals?
+#: if_cscope.c:1449
+msgid "couldn't malloc\n"
+msgstr "kon nie 'malloc' nie\n"
+
+#: if_cscope.c:1454
+#, c-format
+msgid "Cscope tag: %s\n"
+msgstr "Cscope etiket: %s\n"
+
+#: if_cscope.c:1458
+msgid " # line"
+msgstr " # reël"
+
+#: if_cscope.c:1460
+msgid "filename / context / line\n"
+msgstr "lêernaam / konteks / reël\n"
+
+#: if_cscope.c:1718
+msgid "All cscope databases reset"
+msgstr "Alle 'cscope' databasisse herstel"
+
+#: if_cscope.c:1785
+msgid "no cscope connections\n"
+msgstr "geen 'cscope' verbindings nie\n"
+
+#: if_cscope.c:1789
+msgid " # pid database name prepend path\n"
+msgstr " # pid databasis naam gidsvoorvoegsel\n"
+
+#: if_cscope.c:1800
+#, c-format
+msgid "%2d %-5ld %-34s <none>\n"
+msgstr "%2d %-5ld %-34s <geen>\n"
+
+#: if_python.c:376
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: Jammer, hierdie bevel is afgeskakel, die Python biblioteek lêer kon "
+"nie gelaai word nie."
+
+#: if_python.c:576
+msgid "can't delete OutputObject attributes"
+msgstr "kan nie 'OutputObject' eienskappe skrap nie"
+
+#: if_python.c:583
+msgid "softspace must be an integer"
+msgstr "'softspace' moet 'n heelgetal wees"
+
+#: if_python.c:591
+msgid "invalid attribute"
+msgstr "ongeldige eienskap"
+
+#: if_python.c:630 if_python.c:644
+msgid "writelines() requires list of strings"
+msgstr "'writelines()' benodig 'n lys van stringe"
+
+#: if_python.c:770
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: Kon nie I/O objekte inwy nie"
+
+# njj: net 'n voorstel ..
+#: if_python.c:955 if_tcl.c:1391
+msgid "invalid expression"
+msgstr "ongeldige uitdrukking"
+
+#: if_python.c:969 if_tcl.c:1396
+msgid "expressions disabled at compile time"
+msgstr "uitdrukkings afgeskakel tydens kompilering"
+
+#: if_python.c:982
+msgid "attempt to refer to deleted buffer"
+msgstr "poging om na 'n geskrapte buffer te verwys"
+
+#: if_python.c:997 if_python.c:1038 if_python.c:1102 if_tcl.c:1203
+msgid "line number out of range"
+msgstr "reëlnommer buite omvang"
+
+#: if_python.c:1235
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<buffervoorwerp (geskrap) by %8lX>"
+
+#: if_python.c:1326 if_tcl.c:825
+msgid "invalid mark name"
+msgstr "onbekende merknaam"
+
+#: if_python.c:1601
+msgid "no such buffer"
+msgstr "buffer bestaan nie"
+
+#: if_python.c:1689
+msgid "attempt to refer to deleted window"
+msgstr "poging om na geskrapte venster te verwys"
+
+#: if_python.c:1734
+msgid "readonly attribute"
+msgstr "leesalleen eienskap"
+
+#: if_python.c:1747
+msgid "cursor position outside buffer"
+msgstr "loperposisie buite buffer"
+
+#: if_python.c:1824
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<venster voorwerp (geskrap) by %.8lX>"
+
+#: if_python.c:1836
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<verwyder voorwerp (onbekend) by %.8lX>"
+
+#: if_python.c:1838
+#, c-format
+msgid "<window %d>"
+msgstr "<venster %d>"
+
+#: if_python.c:1914
+msgid "no such window"
+msgstr "geen sodanige venster nie"
+
+#: if_python.c:2144 if_python.c:2175 if_python.c:2225 if_python.c:2285
+#: if_python.c:2402 if_python.c:2454 if_tcl.c:673 if_tcl.c:718 if_tcl.c:792
+#: if_tcl.c:862 if_tcl.c:1987
+msgid "cannot save undo information"
+msgstr "kan nie herwin-inligting stoor nie"
+
+#: if_python.c:2146 if_python.c:2232 if_python.c:2296
+msgid "cannot delete line"
+msgstr "kan reël nie verwyder nie"
+
+#: if_python.c:2177 if_python.c:2312 if_tcl.c:679 if_tcl.c:2009
+msgid "cannot replace line"
+msgstr "kan reël nie vervang nie"
+
+#: if_python.c:2328 if_python.c:2404 if_python.c:2462
+msgid "cannot insert line"
+msgstr "kan reël nie byvoeg nie"
+
+#: if_python.c:2566
+msgid "string cannot contain newlines"
+msgstr "string kan nie 'newlines' bevat nie"
+
+#: if_ruby.c:394
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: Jammer, hierdie bevel is afgeskakel, die Ruby biblioteeklêer kon nie "
+"gelaai word nie."
+
+#: if_ruby.c:457
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: Onbekende 'longjmp' status %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Stel en herstel implimentasie/definisie"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Wys basisklas van"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Wys vervangde lidfunksie"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Gaan haal uit lêer"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Gaan haal uit projek"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Gaan haal uit alle projekte"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Gaan haal"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Wys kode van"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Vind simbool"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Kyk klas deur"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Wys klas in hiërargie"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Wys klas in beperkte hiërargie"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref verwys na"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref verwys deur"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref het 'n"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref gebruik deur"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Wys 'docu' van"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Genereer 'docu' vir"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"Kan nie 'n verbinding met 'SNiFF+' maak nie. Kyk of die omgewing reg is "
+"('sniffemacs' moet in '$PATH' gevind word).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Fout gedurende lees. Verbinding gebreek"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ is tans"
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "nie "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "gekonnekteer"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Onbekende SNiFF+ versoek: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Fout in konnekteer met SNiFF+"
+
+#: if_sniff.c:1010
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ is nie gekonnekteer nie"
+
+#: if_sniff.c:1019
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Nie 'n SNiFF+ buffer nie"
+
+#: if_sniff.c:1084
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: Fout gedurende stoor. Verbinding gebreek"
+
+#: if_tcl.c:407
+msgid "invalid buffer number"
+msgstr "ongeldige buffernommer"
+
+#: if_tcl.c:453 if_tcl.c:920 if_tcl.c:1099
+msgid "not implemented yet"
+msgstr "nog nie geïmplementeer nie"
+
+#: if_tcl.c:490
+msgid "unknown option"
+msgstr "onbekende opsie"
+
+#. ???
+#: if_tcl.c:763
+msgid "cannot set line(s)"
+msgstr "kan nie reël(s) stel nie"
+
+#: if_tcl.c:834
+msgid "mark not set"
+msgstr "merker nie gestel nie"
+
+#: if_tcl.c:840 if_tcl.c:1055
+#, c-format
+msgid "row %d column %d"
+msgstr "ry %d kolom %d"
+
+#: if_tcl.c:870
+msgid "cannot insert/append line"
+msgstr "kan nie reël invoeg/aanlas nie"
+
+#: if_tcl.c:1257
+msgid "unknown flag: "
+msgstr "onbekende vlag: "
+
+#: if_tcl.c:1327
+msgid "unknown vimOption"
+msgstr "onbekende 'vimOption'"
+
+#: if_tcl.c:1412
+msgid "keyboard interrupt"
+msgstr "sleutelbordonderbreking"
+
+#: if_tcl.c:1417
+msgid "vim error"
+msgstr "vim fout"
+
+#: if_tcl.c:1460
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "kan nie buffer/venster bevel skep nie: voorwerp word geskrap"
+
+#: if_tcl.c:1534
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"kan nie terugroepbevel registreer nie: buffer/venster word alreeds geskrap"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1551
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: TCL FATALE FOUT: verwlys korrup!? Rapporteer dit asb. aan <vim-dev@vim."
+"org>"
+
+#: if_tcl.c:1552
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"kan terugroepbevel nie registreer nie: buffer/vensterverwysing nie gevind nie"
+
+#: if_tcl.c:1713
+msgid "Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"Jammer, hierdie bevel is afgeskakel, die Tcl biblioteek kon nie gelaai "
+"wordnie."
+
+#: if_tcl.c:1875
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: TCL FOUT: verlaatkode is nie 'n 'int'!? Rapporteer dit asb. aan <vim-"
+"dev@vim.org>"
+
+#: if_tcl.c:1995
+msgid "cannot get line"
+msgstr "kan nie reël kry nie"
+
+#: if_xcmdsrv.c:204
+msgid "Unable to register a command server name"
+msgstr "Kon nie bevelbediener naam registreer nie"
+
+#: if_xcmdsrv.c:417
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: geen geregistreerde bediener genaamd \"%s\""
+
+#: if_xcmdsrv.c:446
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Het gefaal om bevel na doel program te stuur"
+
+#: if_xcmdsrv.c:714
+#, c-format
+msgid "Invalid server id used: %s"
+msgstr "Ongeldige bediener-id gebruik: %s"
+
+#: if_xcmdsrv.c:1061
+msgid "E249: couldn't read VIM instance registry property"
+msgstr "E249: kon nie VIM instansie register-kenmerk lees nie"
+
+#: if_xcmdsrv.c:1072
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: VIM instansie register-kenmerk is swak gevorm. Geskrap!"
+
+#: main.c:53 option.c:3162 option.c:3269
+msgid "Unknown option"
+msgstr "Onbekende opsie"
+
+#: main.c:55
+msgid "Too many edit arguments"
+msgstr "Te veel redigeer-parameters"
+
+#: main.c:57
+msgid "Argument missing after"
+msgstr "Parameter ontbreek na"
+
+#: main.c:59
+msgid "Garbage after option"
+msgstr "Gemors na opsie"
+
+#: main.c:61
+msgid "Too many \"+command\" or \"-c command\" arguments"
+msgstr "Te veel \"+command\" of \"-c command\" parameters"
+
+#: main.c:63
+msgid "Invalid argument for"
+msgstr "Ongeldige parameter vir"
+
+#: main.c:436
+msgid "This Vim was not compiled with the diff feature."
+msgstr "Hierdie Vim is nie gekompileer met 'diff' funksionaliteit nie."
+
+#: main.c:858
+msgid "Attempt to open script file again: \""
+msgstr "Probeer weer om skriplêer oop te maak: \""
+
+#: main.c:862 main.c:869 main.c:913 memline.c:3673 memline.c:3677
+#: version.c:816 version.c:821 version.c:826 version.c:831 version.c:836
+#: version.c:841 version.c:847 version.c:851 version.c:855 version.c:860
+#: version.c:867 version.c:875 version.c:881
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:867
+msgid "Cannot open for reading: \""
+msgstr "Kan nie oopmaak om te lees nie: \""
+
+#: main.c:911
+msgid "Cannot open for script output: \""
+msgstr "Kan nie oopmaak vir skrip-afvoer nie: \""
+
+#: main.c:1020
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d lêers om te bewerk\n"
+
+#: main.c:1094
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Waarskuwing: Afvoer gaan nie na 'n terminaal nie\n"
+
+#: main.c:1096
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Waarskuwing: Invoer kom nie vanaf 'n terminaal nie\n"
+
+#. just in case..
+#: main.c:1171
+msgid "pre-vimrc command line"
+msgstr "vóór-'vimrc' bevelreël"
+
+#: main.c:1206
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Kan nie lees uit \"%s\" nie"
+
+#: main.c:2157
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Meer inligting met: \"vim -h\"\n"
+
+#: main.c:2190
+msgid "[file ..] edit specified file(s)"
+msgstr "[lêer ..] bewerk lêer(s)"
+
+#: main.c:2191
+msgid "- read text from stdin"
+msgstr "- lees teks uit 'stdin'"
+
+#: main.c:2192
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tag bewerk lêer waar etiket gedefinieer is"
+
+#: main.c:2194
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [foutlêer] bewerk lêer met eerste fout"
+
+#: main.c:2203
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"gebruik:"
+
+#: main.c:2206
+msgid " vim [arguments] "
+msgstr " vim [parameters] "
+
+#: main.c:2210
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" of:"
+
+#: main.c:2213
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Parameters:\n"
+
+#: main.c:2214
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tSlegs lêername hierna"
+
+#: main.c:2216
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tRegistreer hierdie gvim vir OLE"
+
+#: main.c:2217
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tOnregistreer gvim vir OLE"
+
+#: main.c:2220
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tVoer uit met die GUI (soos \"gvim\")"
+
+#: main.c:2221
+msgid "-f\t\t\tForeground: Don't fork when starting GUI"
+msgstr "-f\t\t\tVoorgrond: Moenie vurk wanneer GUI begin nie"
+
+#: main.c:2223
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi modus (soos \"vi\")"
+
+#: main.c:2224
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx modus (soos \"ex\")"
+
+#: main.c:2225
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tStil (bondel) modus (slegs vir \"ex\")"
+
+#: main.c:2227
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tDiff modus (soos \"vimdiff\")"
+
+#: main.c:2229
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tEasy modus (soos \"evim\", modusloos)"
+
+#: main.c:2230
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tLeesalleen modus (soos \"view\")"
+
+#: main.c:2231
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tBeperkte modus (soos \"rvim\")"
+
+#: main.c:2232
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tVeranderings (skryf van lêers) nie toegelaat nie"
+
+#: main.c:2233
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tVeranderings aan teks nie toegelaat nie"
+
+#: main.c:2234
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tBinêre modus"
+
+#: main.c:2236
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp modus"
+
+#: main.c:2238
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tVersoenbaar met Vi: 'compatible'"
+
+#: main.c:2239
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tNie ten volle Vi-versoenbaar nie: 'nocompatible'"
+
+#: main.c:2240
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tOmslagtigheidsgraad"
+
+#: main.c:2241
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tOntfoutmodus"
+
+#: main.c:2242
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tGeen ruillêer, gebruik slegs geheue"
+
+#: main.c:2243
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tLys ruillêers en verlaat vim"
+
+#: main.c:2244
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (met lêer naam)\tHerwin ineengestorte sessie"
+
+#: main.c:2245
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tSelfde as -r"
+
+#: main.c:2247
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tMoet nie 'newcli' gebruik om venster oop te maak nie"
+
+#: main.c:2248
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <toestel>\t\tGebruik <toestel> vir I/O"
+
+#: main.c:2251
+msgid "-H\t\t\tstart in Hebrew mode"
+msgstr "-H\t\t\tbegin in Hebreeuse modus"
+
+#: main.c:2254
+msgid "-F\t\t\tstart in Farsi mode"
+msgstr "-F\t\t\tbegin in Farsi modus"
+
+#: main.c:2256
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminaal>\tStel terminaaltipe na <terminaal>"
+
+#: main.c:2257
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tGebruik <vimrc> in plaas van enige ander .vimrc"
+
+#: main.c:2259
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tGebruik <gvimrc> in plaas van enige .gvimrc"
+
+#: main.c:2261
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tMoet nie inpropskripte laai nie"
+
+#: main.c:2262
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tMaak N vensters oop (verstek: een vir elke lêer)"
+
+#: main.c:2263
+msgid "-O[N]\t\tlike -o but split vertically"
+msgstr "-O[N]\t\tsoos -o maar verdeel vertikaal"
+
+#: main.c:2264
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tBegin by einde van lêer"
+
+#: main.c:2265
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\tBegin by reël <lnum>"
+
+#: main.c:2267
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <bevel>\tVoer <bevel> uit voor enige .vimrc-lêer gelaai word"
+
+#: main.c:2269
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <bevel>\t\tVoer <bevel> uit na eerste lêer gelaai is"
+
+#: main.c:2270
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr ""
+"-S <sessie>\t\tVoer bevele in lêer <sessie> uit na eerste lêer gelaai is"
+
+#: main.c:2271
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <skripin>\t\tLees Normale-modus bevele van lêer <skripin>"
+
+#: main.c:2272
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <skripuit>\tLas alle getikte bevele aan by lêer <skripuit>"
+
+#: main.c:2273
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <skripuit>\tSkryf alle getikte bevele na lêer <skripuit>"
+
+#: main.c:2275
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tBewerk geënkripteerde lêers"
+
+#: main.c:2279
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\tKoppel vim aan hierdie X-bediener"
+
+#: main.c:2281
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tMoet nie verbinding met X-bediener maak nie"
+
+#: main.c:2283
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tMaak Vim in 'n ander GTK element oop"
+
+#: main.c:2287
+msgid "--remote <files>\tEdit <files> in a Vim server and exit"
+msgstr "--remote <lêers>\tWysig die <lêers> in a Vim bediener en verlaat"
+
+#: main.c:2288
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr ""
+"--remote-wait <lêers> Soos '--remote', maar wag vir lêers om gewysigte word"
+
+#: main.c:2289
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr ""
+"--remote-send <sleutels>\tStuur <sleutels> na 'n Vim-bediener en verlaat"
+
+#: main.c:2290
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr ""
+"--remote-expr <expr>\tEvalueer <expr> in 'n Vim-bediener en druk resultaat"
+
+#: main.c:2291
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tLys beskikbare Vim-bediener name en verlaat"
+
+#: main.c:2292
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <naam>\tStuur na/word die Vim-bediener <naam>"
+
+#: main.c:2295
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tGebruik <viminfo> in plaas van .viminfo"
+
+#: main.c:2297
+msgid "-h\t\t\tprint Help (this message) and exit"
+msgstr "-h\t\t\tskryf Hulp (hierdie boodskap) en sluit"
+
+#: main.c:2298
+msgid "--version\t\tprint version information and exit"
+msgstr "--version\t\tskryf weergawe-inligting en sluit"
+
+#: main.c:2302
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Parameters deur gvim herken (Motif weergawe):\n"
+
+#: main.c:2305
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Parameters deur gvim herken (Athena weergawe):\n"
+
+#: main.c:2308
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\tVoer vim op <display> uit"
+
+#: main.c:2309
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tBegin vim as ikoon"
+
+#: main.c:2311
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <name>\t\tGebruik hulpbron asof vim <name> was"
+
+#: main.c:2312
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (Nog nie geïmplementeer nie)\n"
+
+#: main.c:2314
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <kleur>\tGebruik <kleur> vir die agtergrond (ook: -bg)"
+
+#: main.c:2315
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-voorgrond <kleur>\tGebruik <kleur> vir normale teks (ook: -fg)"
+
+#: main.c:2316 main.c:2336
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <font>\t\tGebruik <font> vir normale teks (ook -fn)"
+
+#: main.c:2317
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "­boldfont <font>\t Gebruik <font> vir vetletter teks"
+
+#: main.c:2318
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <font>\tGebruik <font> vir kursiewe teks"
+
+#: main.c:2319 main.c:2337
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\tGebruik <geom> vir aanvanklike geometrie"
+
+#: main.c:2320
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <wydte>\tGebruik 'n grenswydte van <wydte> (ook: -bw)"
+
+#: main.c:2321
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr ""
+"-scrollbarwidth <wydte>\tGebruik 'n rolstaafwydte van <wydte> (ook: -sw>"
+
+#: main.c:2323
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr ""
+"-menuheight <hoogte>\tGebruik a kieslysstaafhoogte van <hoogte> (ook: -mh)"
+
+#: main.c:2325 main.c:2338
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tGebruik tru-video (ook: -rv)"
+
+#: main.c:2326
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tMoet nie tru-video gebruik nie (ook: +rv)"
+
+#: main.c:2327
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <hulpbron>\tStel die gespesifiseerde hulpbron"
+
+#: main.c:2330
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Parameters wat gvim verstaan (RISC OS weergawe):\n"
+
+#: main.c:2331
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <aantal>\tAanvanklike wydte van venster in kolomme"
+
+#: main.c:2332
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <aantal>\tAanvanklike hoogte van venster in rye"
+
+#: main.c:2335
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Parameters wat gvim verstaan (GTK+ weergawe):\n"
+
+#: main.c:2339
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <skerm>\tVoer vim op <skerm> uit: (ook --display)"
+
+#: main.c:2341
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tWys Gnome parameters"
+
+#. Failed to send, abort.
+#: main.c:2566
+msgid ""
+"\n"
+"Send failed.\n"
+msgstr ""
+"\n"
+"Stuur het gefaal.\n"
+
+#. Let vim start normally.
+#: main.c:2571
+msgid ""
+"\n"
+"Send failed. Trying to execute locally\n"
+msgstr ""
+"\n"
+"Stuur het gefaal. Probeer om lokaal uit te voer\n"
+
+#: main.c:2604 main.c:2625
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d van %d lêers bewerk"
+
+#: main.c:2648
+msgid "Send expression failed.\n"
+msgstr "Stuur van uitdrukking het gefaal.\n"
+
+#: mark.c:660
+msgid "No marks set"
+msgstr "Geen merkers gestel nie"
+
+#: mark.c:662
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: Geen merkers pas op \"%s\" nie"
+
+#. Highlight title
+#: mark.c:673
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"merk reël kol lêer/teks"
+
+#. Highlight title
+#: mark.c:711
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" spring reël kol lêer/teks"
+
+#: mark.c:1073
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Lêermerkers:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1108
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Springlys (nuutste eerste):\n"
+
+#: mark.c:1203
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Geskiedenis van merkers in lêers (nuutste tot oudste):\n"
+
+#: mark.c:1286
+msgid "Missing '>'"
+msgstr "Ontbrekende '>'"
+
+#: mbyte.c:395
+msgid "Not a valid codepage"
+msgstr "Nie 'n geldige kodeblad nie"
+
+#: mbyte.c:3014
+msgid "E284: Cannot set IC values"
+msgstr "E284: Kan nie IC waardes stel nie"
+
+#: mbyte.c:3166
+msgid "E285: Failed to create input context"
+msgstr "E285: Gefaal met die skep van invoerkonteks"
+
+#: mbyte.c:3313
+msgid "E286: Failed to open input method"
+msgstr "E286: Gefaal om invoermetode oop te maak"
+
+#: mbyte.c:3324
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: Waarskuwing: Kon nie uitwis-terugroep na IM stel nie"
+
+#: mbyte.c:3330
+msgid "E288: input method doesn't support any style"
+msgstr "E288: invoermetode ondersteun geen styl nie"
+
+#: mbyte.c:3387
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: invoermetode ondersteun nie my voor-bewerking tipe nie"
+
+#: mbyte.c:3461
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: oor-die-plek styl vereis fontstel"
+
+#: mbyte.c:3489
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: Jou GTK+ is ouer as 1.2.3. Statusarea afgeskakel"
+
+#: mbyte.c:3726
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Invoermetodebediener voer nie uit nie"
+
+#: memfile.c:473
+msgid "E293: block was not locked"
+msgstr "E293: blok was nie gesluit nie"
+
+#: memfile.c:972
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Soekfout in lees van ruillêer"
+
+#: memfile.c:977
+msgid "E295: Read error in swap file"
+msgstr "E295: Leesfout in ruillêer"
+
+#: memfile.c:1029
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Soekfout in skryf van ruillêer"
+
+#: memfile.c:1047
+msgid "E297: Write error in swap file"
+msgstr "E297: Skryffout in ruillêer"
+
+#: memfile.c:1244
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: Ruillêer bestaan alreeds! ('symlink' probleem?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Het nie blok no 0 gekry nie?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Het nie blok no 1 gekry nie?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: Het nie blok no 2 gekry nie?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Hiert, die ruillêer is weg!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: Kon nie ruillêer vernoem nie"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: Kon nie ruillêer oopmaak vir \"%s\" nie, herwinning onmoontlik"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: 'ml_timestamp': Het nie blok 0 gekry nie??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Geen ruillêer gevind vir %s nie"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "Tik die nommer van die ruillêer om te gebruik (0 om te stop)"
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: Kan %s nie oopmaak nie"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "Kan nie blok 0 lees vanaf "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Vim het die ruillêer nie opgedateer nie. Dalk was niks verander nie."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " kan nie gebruik word met hierdie weergawe van Vim nie.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Gebruik Vim weergawe 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s lyk nie soos 'n Vim ruillêer nie"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " kan nie gebruik word op hierdie rekenaar nie.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "Die lêer is geskep op "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"of die lêer is beskadig."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "Gebruik ruillêer \"%s\""
+
+#: memline.c:915
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Oorspronklike lêer \"%s\""
+
+#: memline.c:934
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Waarskuwing: Oorspronklike lêer is dalk gewysig"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Kan nie block 1 lees van %s"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???BAIE REËLS WEG"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???REËLTELLING FOUTIEF"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???LEË BLOK"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???REËLS WEG"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: Blok 1 se ID is foutief (%s nie 'n .swp lêer nie?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???BLOK WEG"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? van hier tot ???END mag reëls deurmekaar wees"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? van hier tot ???END mag daar reëls ingevoeg/geskrap wees"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???END"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Herwinning onderbreek"
+
+#: memline.c:1145
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr ""
+"E312: Foute raakgesien gedurende herwinning; soek vir reëls wat begin met ???"
+
+#: memline.c:1148
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Herwinning is klaar. Kyk of alles reg is."
+
+#: memline.c:1149
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Jy wil dalk die lêer stoor onder 'n ander naam\n"
+
+#: memline.c:1150
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "en dit \"diff\" teen die oorspronklike lêer om wysigings te soek)\n"
+
+#: memline.c:1151
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"Verwyder die .swp-lêer na die tyd.\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1207
+msgid "Swap files found:"
+msgstr "Ruillêers gevind:"
+
+#: memline.c:1385
+msgid " In current directory:\n"
+msgstr " In huidige gids:\n"
+
+#: memline.c:1387
+msgid " Using specified name:\n"
+msgstr " Wat gespesifiseerde naam gebruik:\n"
+
+#: memline.c:1391
+msgid " In directory "
+msgstr " In gids "
+
+#: memline.c:1409
+msgid " -- none --\n"
+msgstr " -- geen --\n"
+
+#: memline.c:1481
+msgid " owned by: "
+msgstr " eienaar: "
+
+#: memline.c:1483
+msgid " dated: "
+msgstr " gedateer: "
+
+#: memline.c:1487 memline.c:3680
+msgid " dated: "
+msgstr " gedateer: "
+
+#: memline.c:1503
+msgid " [from Vim version 3.0]"
+msgstr " [van Vim weergawe 3.0]"
+
+#: memline.c:1507
+msgid " [does not look like a Vim swap file]"
+msgstr " [lyk nie soos 'n Vim ruillêer nie]"
+
+#: memline.c:1511
+msgid " file name: "
+msgstr " lêernaam: "
+
+#: memline.c:1523
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" gewysig: "
+
+#: memline.c:1524
+msgid "YES"
+msgstr "JA"
+
+#: memline.c:1524
+msgid "no"
+msgstr "nee"
+
+#: memline.c:1528
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" gebruikersnaam: "
+
+#: memline.c:1535
+msgid " host name: "
+msgstr " gasheernaam: "
+
+#: memline.c:1537
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" gasheernaam: "
+
+#: memline.c:1543
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" proses ID: "
+
+#: memline.c:1549
+msgid " (still running)"
+msgstr " (nog steeds aan die uitvoer)"
+
+#: memline.c:1561
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [nie bruikbaar met hierdie weergawe van Vim nie]"
+
+#: memline.c:1564
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [nie bruikbaar op hierdie rekenaar nie]"
+
+#: memline.c:1569
+msgid " [cannot be read]"
+msgstr " [kan nie gelees word nie]"
+
+#: memline.c:1573
+msgid " [cannot be opened]"
+msgstr " [kan nie oopgemaak word nie]"
+
+#: memline.c:1763
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Kan nie bewaar nie, daar is geen ruillêer nie"
+
+#: memline.c:1816
+msgid "File preserved"
+msgstr "Lêer bewaar"
+
+#: memline.c:1818
+msgid "E314: Preserve failed"
+msgstr "E314: Kon nie bewaar nie"
+
+#: memline.c:1889
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: 'ml_get': ongeldige 'lnum': %ld"
+
+#: memline.c:1915
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: 'ml_get': kan reël %ld nie vind nie"
+
+#: memline.c:2303
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: wyser blok id verkeerd 3"
+
+#: memline.c:2383
+msgid "stack_idx should be 0"
+msgstr "'stack_idx' moet 0 wees"
+
+#: memline.c:2445
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Te veel blokke opgedateer?"
+
+#: memline.c:2602
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: wyser blok id verkeerd 4"
+
+#: memline.c:2629
+msgid "deleted block 1?"
+msgstr "verwyder blok 1?"
+
+#: memline.c:2829
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Kan nie reël %ld vind nie"
+
+#: memline.c:3072
+msgid "E317: pointer block id wrong"
+msgstr "E317: wyser blok id verkeerd"
+
+#: memline.c:3088
+msgid "pe_line_count is zero"
+msgstr "'pe_line_count' is nul"
+
+#: memline.c:3117
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: reëlnommer buite perke: %ld verby die einde"
+
+#: memline.c:3121
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: reëltelling mag verkeerd wees in blok %ld"
+
+#: memline.c:3170
+msgid "Stack size increases"
+msgstr "Stapel grootte verhoog"
+
+#: memline.c:3216
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: wyser blok id verkeerd 2"
+
+#: memline.c:3670
+msgid "E325: ATTENTION"
+msgstr "E325: LET OP"
+
+#: memline.c:3671
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Het 'n ruillêer gevind met die naam \""
+
+#: memline.c:3675
+msgid "While opening file \""
+msgstr "Tydens oopmaak van lêer \""
+
+#: memline.c:3684
+msgid " NEWER than swap file!\n"
+msgstr " NUWER as die ruillêer!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3688
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) 'n Ander program mag besig wees met hierdie lêer.\n"
+" Indien wel, pas op om nie met twee verskillende weergawes\n"
+" van dieselfde lêer te sit wanneer veranderinge gemaak word nie.\n"
+
+#: memline.c:3689
+msgid " Quit, or continue with caution.\n"
+msgstr " Stop, of gaan versigtig voort.\n"
+
+#: memline.c:3690
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) 'n Bewerkingsessie van hierdie lêer het ineengestort.\n"
+
+#: memline.c:3691
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Indien wel, gebruik \":recover\" of \"vim -r"
+
+#: memline.c:3693
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" om die veranderinge te herwin (sien \":help recovery\").\n"
+
+#: memline.c:3694
+msgid " If you did this already, delete the swap file \""
+msgstr " Indien jy dit alreeds gedoen het, verwyder die ruillêer \""
+
+#: memline.c:3696
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" om hierdie boodskap te vermy.\n"
+
+#: memline.c:3710 memline.c:3714
+msgid "Swap file \""
+msgstr "Ruillêer \""
+
+#: memline.c:3711 memline.c:3717
+msgid "\" already exists!"
+msgstr "\" bestaan alreeds!"
+
+#: memline.c:3720
+msgid "VIM - ATTENTION"
+msgstr "VIM - LET OP"
+
+#: memline.c:3722
+msgid "Swap file already exists!"
+msgstr "Ruillêer bestaan alreeds!"
+
+#: memline.c:3726
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"&Maak as lees-alleen oop\n"
+"&Bewerk in elk geval\n"
+"&Herwin\n"
+"&Stop"
+
+#: memline.c:3728
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"&Maak as lees-alleen oop\n"
+"&Bewerk in elk geval\n"
+"&Herwin\n"
+"&Stop\n"
+"S&krap dit"
+
+#: memline.c:3781
+msgid "E326: Too many swap files found"
+msgstr "E326: Te veel ruillêers gevind"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Deel van kieslys-item pad is nie 'n sub-kieslys nie"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Kieslys bestaan slegs in 'n ander modus"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Geen kieslys met daardie naam nie"
+
+#: menu.c:503
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Kieslyspad moenie lei na 'n sub-kieslys nie"
+
+#: menu.c:542
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: Moenie kieslysitems direk by kieslysstaaf voeg nie"
+
+#: menu.c:548
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Verdeler kan nie deel wees van kieslyspad nie"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1063
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Kieslyste ---"
+
+#: menu.c:1989
+msgid "Tear off this menu"
+msgstr "Skeur die kieslys af"
+
+#: menu.c:2054
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Kieslyspad moet lei na 'n kieslysitem"
+
+#: menu.c:2074
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Kieslys nie gevind nie: %s"
+
+#: menu.c:2143
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: Kieslys nie gedefinieer vir %s modus nie"
+
+#: menu.c:2181
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Kieslyspad moet lei na 'n sub-kieslys"
+
+#: menu.c:2202
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Kieslys nie gevind nie - maak seker oor die kieslys name"
+
+#: message.c:467
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Fout ontdek tydens verwerking van %s: "
+
+#: message.c:483
+#, c-format
+msgid "line %4ld:"
+msgstr "reël %4ld:"
+
+#: message.c:523
+msgid "[string too long]"
+msgstr "[string te lank]"
+
+#: message.c:669
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "Boodskappe onderhouers: Danie Roux en Jean Jordaan <droux@tuks.co.za>"
+
+#: message.c:881
+msgid "Interrupt: "
+msgstr "Onderbreek: "
+
+#: message.c:884
+msgid "Hit ENTER to continue"
+msgstr "Druk ENTER om voort te gaan"
+
+#: message.c:886
+msgid "Hit ENTER or type command to continue"
+msgstr "Druk ENTER of tik 'n bevel om voort te gaan"
+
+#: message.c:1940
+msgid "-- More --"
+msgstr "-- Meer --"
+
+#: message.c:1943
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: reël, SPACE/b: bladsy, d/u: halwe bladsy, q: los dit"
+
+#: message.c:1944
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: reël, SPACE: bladsy, d: halwe bladsy, q: los dit"
+
+#: message.c:2419 message.c:2434
+msgid "Question"
+msgstr "Vraag"
+
+#: message.c:2421
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Ja\n"
+"&Nee"
+
+#: message.c:2436
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Ja\n"
+"&Nee\n"
+"&Kanselleer"
+
+#: message.c:2454
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Ja\n"
+"&Nee\n"
+"Stoor &alles\n"
+"&Gooi alles weg\n"
+"&Kanselleer"
+
+#: message.c:2494
+msgid "Save File dialog"
+msgstr "Stoor Lêer dialooghokkie"
+
+#: message.c:2496
+msgid "Open File dialog"
+msgstr "Maak lêer oop dialooghokkie"
+
+#. TODO: non-GUI file selector here
+#: message.c:2547
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: Jammer, lêerblaaier nie beskikbaar in konsole-modus nie"
+
+#: misc1.c:2449
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: Waarskuwing: Jy wysig aan 'n leesalleen lêer"
+
+#: misc1.c:2678
+msgid "1 more line"
+msgstr "1 reël meer"
+
+#: misc1.c:2680
+msgid "1 line less"
+msgstr "1 reël minder"
+
+#: misc1.c:2685
+#, c-format
+msgid "%ld more lines"
+msgstr "%ld meer reëls"
+
+#: misc1.c:2687
+#, c-format
+msgid "%ld fewer lines"
+msgstr "%ld minder reëls"
+
+#: misc1.c:2690
+msgid " (Interrupted)"
+msgstr " (Onderbreek)"
+
+#: misc1.c:6245
+msgid "Vim: preserving files...\n"
+msgstr "Vim: bewaar lêers...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6255
+msgid "Vim: Finished.\n"
+msgstr "Vim: Klaar.\n"
+
+#: misc2.c:647 misc2.c:663
+msgid "ERROR: "
+msgstr "FOUT: "
+
+#: misc2.c:667
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[grepe] totaal 'alloc'-vrygelaat %lu-%lu, in gebruik %lu, piekgebruik %lu\n"
+
+#: misc2.c:669
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[roepe] totaal re/malloc()'s %lu, totale free()'s %lu\n"
+"\n"
+
+#: misc2.c:724
+msgid "E340: Line is becoming too long"
+msgstr "E340: Rëel word te lank"
+
+#: misc2.c:768
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Interne fout: 'lalloc(%ld, )'"
+
+#: misc2.c:876
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Geheue is op! (ken %lu grepe toe)"
+
+#: misc2.c:2511
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Roep dop om uit te voer: \"%s\""
+
+#: misc2.c:2706 misc2.c:5148 option.c:4584
+msgid "Missing colon"
+msgstr "Ontbrekende dubbelpunt"
+
+#: misc2.c:2708 misc2.c:2735
+msgid "Illegal mode"
+msgstr "Ongeldige modus"
+
+#: misc2.c:2774
+msgid "Illegal mouseshape"
+msgstr "Ongeldige muisvorm"
+
+#: misc2.c:2814 misc2.c:5168
+msgid "digit expected"
+msgstr "syfer verwag"
+
+#: misc2.c:2819
+msgid "Illegal percentage"
+msgstr "Ongeldige persentasie"
+
+#: misc2.c:3123
+msgid "Enter encryption key: "
+msgstr "Voer enkripsie-sleutel in: "
+
+#: misc2.c:3124
+msgid "Enter same key again: "
+msgstr "Voer die sleutel weer in: "
+
+#: misc2.c:3134
+msgid "Keys don't match!"
+msgstr "Sleutels verskil!"
+
+#: misc2.c:3648
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Ongeldige pad: '**[nommer]' moet aan die einde van 'n pad wees of "
+"gevolg wees deur %s'."
+
+#: misc2.c:4905
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Kan nie gids \"%s\" in 'cdpath' vind nie"
+
+#: misc2.c:4908
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Kan lêer \"%s\" nie vind in pad nie"
+
+#: misc2.c:4914
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: Geen gids \"%s\" meer gevind in 'cdpath' nie"
+
+#: misc2.c:4917
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: Geen lêer \"%s\" meer gevind in pad nie"
+
+#: misc2.c:5160
+msgid "Illegal component"
+msgstr "Ongeldige komponent"
+
+#: normal.c:2813
+msgid "Warning: terminal cannot highlight"
+msgstr "Waarskuwing: terminaal kan nie teks uitlig nie"
+
+#: normal.c:3008
+msgid "E348: No string under cursor"
+msgstr "E348: Geen string onder loper nie"
+
+#: normal.c:3010
+msgid "E349: No identifier under cursor"
+msgstr "E349: Geen identifiseerder onder loper nie"
+
+#: normal.c:4175
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: Kan nie voue verwyder met huidige 'foldmethod' nie"
+
+# Het te doen met < en >
+#: ops.c:271
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "1 reël 1 keer ge-%s"
+
+#: ops.c:273
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 reël ge-%s %d keer"
+
+#: ops.c:278
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld reëls 1 keer ge-%s"
+
+#: ops.c:281
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld reëls ge-%s %d keer"
+
+#: ops.c:638
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld reëls om in te keep..."
+
+#: ops.c:688
+msgid "1 line indented "
+msgstr "1 reël ingekeep "
+
+#: ops.c:690
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld reëls ingekeep "
+
+#. must display the prompt
+#: ops.c:1528
+msgid "cannot yank; delete anyway"
+msgstr "kan nie pluk nie: verwyder in elk geval"
+
+#: ops.c:2018
+msgid "1 line ~ed"
+msgstr "1 reël ge-~"
+
+#: ops.c:2020
+#, c-format
+msgid "%ld lines ~ed"
+msgstr "%ld reëls ge-~"
+
+#: ops.c:2381
+#, c-format
+msgid "freeing %ld lines"
+msgstr "laat %ld reëls gaan"
+
+#: ops.c:2658
+msgid "1 line yanked"
+msgstr "1 reël gepluk"
+
+#: ops.c:2660
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld reëls gepluk"
+
+#: ops.c:2916
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: Niks in register %s nie"
+
+#. Highlight title
+#: ops.c:3454
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Registers ---"
+
+#: ops.c:4565
+msgid "Illegal register name"
+msgstr "Ongeldige registernaam"
+
+#: ops.c:4645
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Registers:\n"
+
+#: ops.c:4671
+#, c-format
+msgid "Unknown register type %d"
+msgstr "Onbekende registertipe %d"
+
+#: ops.c:5052
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: Ongeldige registernaam: '%s'"
+
+#: ops.c:5393
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Kolomme; "
+
+#: ops.c:5400
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "%s%ld van %ld reëls gekies; %ld van %ld Woorde; %ld van %ld Grepe"
+
+# njj: Karakters kan meerdere grepe wees, sien ':h multibyte'
+#: ops.c:5416
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Kol %s van %s; Reël %ld van %ld; Woord %ld van %ld; Greep %ld van %ld"
+
+#: ops.c:5427
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld vir 'BOM')"
+
+#: option.c:1989
+msgid "Thanks for flying Vim"
+msgstr "Dankie dat jy vlieg met Vim"
+
+#: option.c:3175
+msgid "Option not supported"
+msgstr "Opsie is nie ondersteun nie"
+
+#: option.c:3200
+msgid "Not allowed in a modeline"
+msgstr "Nie toegelaat in 'n moduslyn nie"
+
+#: option.c:3256
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tLaas gestel vanaf "
+
+#: option.c:3395
+msgid "Number required after ="
+msgstr "Nommer vereis na ="
+
+#: option.c:3702 option.c:4309
+msgid "Not found in termcap"
+msgstr "Nie gevind in 'termcap' nie"
+
+#: option.c:3768
+#, c-format
+msgid "Illegal character <%s>"
+msgstr "Ongeldige karakter <%s>"
+
+#: option.c:4294 option.c:5497
+msgid "Not allowed here"
+msgstr "Nie hier toegelaat nie"
+
+#: option.c:4301
+msgid "Cannot set 'term' to empty string"
+msgstr "Kan nie 'term' stel na leë string nie"
+
+#: option.c:4304
+msgid "Cannot change term in GUI"
+msgstr "Kan nie 'term' verander in GUI nie"
+
+#: option.c:4306
+msgid "Use \":gui\" to start the GUI"
+msgstr "Gebruik \":gui\" om die GUI te begin"
+
+#: option.c:4327
+msgid "'backupext' and 'patchmode' are equal"
+msgstr "'backupext' en 'patchmode' is dieselfde"
+
+#: option.c:4586
+msgid "Zero length string"
+msgstr "Nul-lengte string"
+
+#: option.c:4654
+#, c-format
+msgid "Missing number after <%s>"
+msgstr "Ontbrekende nommer na <%s>"
+
+#: option.c:4668
+msgid "Missing comma"
+msgstr "Ontbrekende komma"
+
+#: option.c:4675
+msgid "Must specify a ' value"
+msgstr "Moet 'n ' waarde spesifiseer"
+
+#: option.c:4715
+msgid "contains unprintable character"
+msgstr "bevat 'n ondrukbare karakter"
+
+#: option.c:4728
+msgid "Invalid font(s)"
+msgstr "Ongeldige font(e)"
+
+#: option.c:4734
+msgid "can't select fontset"
+msgstr "kan nie fontstel kies nie"
+
+#: option.c:4736
+msgid "Invalid fontset"
+msgstr "Ongeldige fontstel"
+
+#: option.c:4743
+msgid "can't select wide font"
+msgstr "kan nie wye font kies nie"
+
+#: option.c:4745
+msgid "Invalid wide font"
+msgstr "Ongeldige wye font"
+
+#: option.c:5014
+#, c-format
+msgid "Illegal character after <%c>"
+msgstr "Ongeldige karakter na <%c>"
+
+#: option.c:5097
+msgid "comma required"
+msgstr "komma benodig"
+
+#: option.c:5106
+#, c-format
+msgid "'commentstring' must be empty or contain %s"
+msgstr "'commentstring' moet leeg wees of %s bevat"
+
+#: option.c:5153
+msgid "No mouse support"
+msgstr "Geen muisondersteuning nie"
+
+#: option.c:5399
+msgid "Unclosed expression sequence"
+msgstr "Onvoltooide uitdrukkingreeks"
+
+#: option.c:5403
+msgid "too many items"
+msgstr "te veel items"
+
+#: option.c:5405
+msgid "unbalanced groups"
+msgstr "ongebalanseerde groepe"
+
+#: option.c:5620
+msgid "A preview window already exists"
+msgstr "Daar bestaan reeds 'n voorskouvenster"
+
+#: option.c:5881 option.c:5910
+msgid "'winheight' cannot be smaller than 'winminheight'"
+msgstr "'winheight' kan nie kleiner as 'winminheight' wees nie"
+
+#: option.c:5926 option.c:5945
+msgid "'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "'winwidth' kan nie kleiner as 'winminwidth' wees nie"
+
+#: option.c:6085
+#, c-format
+msgid "Need at least %d lines"
+msgstr "Benodig ten minste %d reëls"
+
+#: option.c:6094
+#, c-format
+msgid "Need at least %d columns"
+msgstr "Benodig ten minste %d kolomme"
+
+#: option.c:6391
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Onbekende opsie: %s"
+
+#: option.c:6500
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Terminaal kodes ---"
+
+#: option.c:6502
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Globale opsie waardes ---"
+
+#: option.c:6504
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Lokale opsie waardes ---"
+
+#: option.c:6506
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Opsies ---"
+
+#: option.c:7196
+msgid "E356: get_varp ERROR"
+msgstr "E356: 'get_varp' FOUT"
+
+#: option.c:8112
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': Passende karakter ontbreek vir %s"
+
+#: option.c:8146
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap: Ekstra karakters na kommapunt: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "kan nie oopmaak nie "
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Kan nie venster oopmaak nie!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Benodig Amigados weergawe 2.04 of later\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Benodig %s weergawe %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "Kan nie NIL: oopmaak nie\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr "Kan nie skep nie: "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim stop met %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "kan konsole-modus nie verander nie ?!\n"
+
+#: os_amiga.c:938 os_mac.c:1168 os_mswin.c:619 os_riscos.c:728 os_unix.c:2726
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Skermmodus instelling nie ondersteun nie"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "'mch_get_shellsize': nie 'n konsole nie??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1142
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Kan nie dop met -f opsie uitvoer nie"
+
+#: os_amiga.c:1183 os_amiga.c:1273
+msgid "Cannot execute "
+msgstr "Kan nie uitvoer nie "
+
+#: os_amiga.c:1186 os_amiga.c:1283
+msgid "shell "
+msgstr "dop "
+
+#: os_amiga.c:1206 os_amiga.c:1308
+msgid " returned\n"
+msgstr " teruggekeer\n"
+
+#: os_amiga.c:1448
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "'ANCHOR_BUF_SIZE' is te klein"
+
+#: os_amiga.c:1452
+msgid "I/O ERROR"
+msgstr "I/O FOUT"
+
+#: os_mswin.c:503
+msgid "...(truncated)"
+msgstr "...(afgekap)"
+
+#: os_mswin.c:594
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' is nie 80 nie, kan nie eksterne bevele uitvoer nie"
+
+#: os_mswin.c:706 os_unix.c:4945
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Biblioteekroep het gefaal vir \"%s\"()"
+
+#: os_mswin.c:1340
+msgid "E237: Printer selection failed"
+msgstr "E237: Drukker-seleksie het gefaal"
+
+#: os_mswin.c:1388
+#, c-format
+msgid "to %s on %s"
+msgstr "na %s op %s"
+
+#: os_mswin.c:1449 os_mswin.c:1459
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Drukfout: %s"
+
+#: os_mswin.c:1460
+msgid "Unknown"
+msgstr "Onbekend"
+
+#: os_mswin.c:1487
+#, c-format
+msgid "Printing '%s'"
+msgstr "Druk nou '%s'"
+
+#: os_mswin.c:2551
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Ongeldige karakterstelnaam \"%s\" in fontnaam \"%s\""
+
+#: os_mswin.c:2559
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Ongeldige karakter '%c' in fontnaam \"%s\""
+
+#: os_riscos.c:1227
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Ongeldige 'osfiletype' opsie - gaan Text gebruik"
+
+#: os_unix.c:800
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: Dubbel sein, staak\n"
+
+#: os_unix.c:806
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Het dodelike sein %s gevang\n"
+
+#: os_unix.c:809
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Het dodelike sein gevang\n"
+
+#: os_unix.c:1063
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Om die X-vertoonskerm oop te maak het %ld msek gevat"
+
+#: os_unix.c:1090
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: Het X fout ontvang\n"
+
+#: os_unix.c:1157
+msgid "Testing the X display failed"
+msgstr "Toetsing van die X-vertoonskerm het gefaal"
+
+#: os_unix.c:1301
+msgid "Opening the X display timed out"
+msgstr "Oopmaak van die X-vertoonskerm het uitgetel"
+
+#: os_unix.c:2899 os_unix.c:3483
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"Kan nie dop uitvoer nie "
+
+#: os_unix.c:2944
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Kan nie dop 'sh' uitvoer nie\n"
+
+#: os_unix.c:2948 os_unix.c:3489
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"dop lewer "
+
+#: os_unix.c:3082
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Kan nie pype skep nie\n"
+
+#: os_unix.c:3097
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"Kan nie vurk nie\n"
+
+#: os_unix.c:3496
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Bevel beëindig\n"
+
+#: os_unix.c:4993
+msgid "Opening the X display failed"
+msgstr "Oopmaak van die X vertoonskerm het gefaal"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "By reël"
+
+#: os_w32exe.c:169
+msgid "Could not load vim32.dll!"
+msgstr "Kon nie 'vim32.dll' laai nie!"
+
+#: os_w32exe.c:169 os_w32exe.c:179
+msgid "VIM Error"
+msgstr "VIM Fout"
+
+#: os_w32exe.c:179
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Kon nie funksiewysers na die DLL opstel nie!"
+
+#: os_win16.c:578 os_win32.c:3021
+#, c-format
+msgid "shell returned %d"
+msgstr "dop het %d gelewer"
+
+#: os_win32.c:2489
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Het %s gebeurtenis gevang\n"
+
+#: os_win32.c:2491
+msgid "close"
+msgstr "maak toe"
+
+#: os_win32.c:2493
+msgid "logoff"
+msgstr "teken uit"
+
+#: os_win32.c:2494
+msgid "shutdown"
+msgstr "sit af"
+
+#: os_win32.c:2975
+msgid "E371: Command not found"
+msgstr "E371: Bevel nie gevind nie"
+
+#: os_win32.c:2988
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"'VIMRUN.EXE' nie gevind in '$PATH' nie.\n"
+"Eksterne opdragte sal nie wag na voltooiing nie\n"
+"Sien ':help win32-vimrun' vir meer inligting."
+
+#: os_win32.c:2991
+msgid "Vim Warning"
+msgstr "Vim Waarskuwing"
+
+#: quickfix.c:281
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Te veel %%%c in formaatstring"
+
+#: quickfix.c:294
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: Onverwagte %%%c in formaatstring"
+
+#: quickfix.c:348
+msgid "E374: Missing ] in format string"
+msgstr "E374: Ontbrekende ] in formaatstring"
+
+#: quickfix.c:362
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: Ongesteunde %%%c in formaatstring"
+
+#: quickfix.c:380
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: Ongeldige %%%c in formaatstringvoorvoegsel"
+
+#: quickfix.c:388
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: Ongeldige %%%c in formaatstring"
+
+#: quickfix.c:414
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' bevat geen patroon nie"
+
+#: quickfix.c:520
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Ontbrekende of leë gidsnaam"
+
+#: quickfix.c:931
+msgid "No more items"
+msgstr "Geen items meer nie"
+
+#: quickfix.c:1152
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d van %d)%s%s: "
+
+#: quickfix.c:1154
+msgid " (line deleted)"
+msgstr " (reël verwyder)"
+
+#: quickfix.c:1360
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Onder aan 'quickfix' stapel"
+
+#: quickfix.c:1369
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Bo aan 'quickfix' stapel"
+
+#: quickfix.c:1381
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "foutelys %d van %d; %d foute"
+
+#: quickfix.c:1842
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: Kan nie skryf nie, 'buftype' opsie is aan"
+
+#: regexp.c:801
+msgid "E339: Pattern too long"
+msgstr "E339: Patroon te lank"
+
+#: regexp.c:1315
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: Geneste %s*"
+
+#: regexp.c:1318
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: Geneste %s%c"
+
+#: regexp.c:1467
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c volg niks"
+
+#: regexp.c:2469
+#, c-format
+msgid "Syntax error in %s{...}"
+msgstr "Sintaksfout in %s{...}"
+
+#: regexp.c:2716
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Ineenstorting onderskep. Patroon te kompleks?"
+
+#: regexp.c:2851
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: patroon het lëe-stapel fout veroorsaak"
+
+#: regexp.c:3087
+msgid "External submatches:\n"
+msgstr "Eksterne subtreffers:\n"
+
+#: screen.c:2054
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld reëls gevou "
+
+#: screen.c:7426
+msgid " VREPLACE"
+msgstr " VVERVANG"
+
+#: screen.c:7430
+msgid " REPLACE"
+msgstr " VERVANG"
+
+#: screen.c:7435
+msgid " REVERSE"
+msgstr " OMKEER"
+
+#: screen.c:7437
+msgid " INSERT"
+msgstr " INVOEG"
+
+#: screen.c:7440
+msgid " (insert)"
+msgstr " (invoeg)"
+
+#: screen.c:7442
+msgid " (replace)"
+msgstr " (vervang)"
+
+#: screen.c:7444
+msgid " (vreplace)"
+msgstr " (vvervang)"
+
+#: screen.c:7447
+msgid " Hebrew"
+msgstr " Hebreeus"
+
+#: screen.c:7455
+msgid " (lang)"
+msgstr " (taal)"
+
+#: screen.c:7458
+msgid " (paste)"
+msgstr " (plak)"
+
+#: screen.c:7464
+msgid " SELECT"
+msgstr " KIES"
+
+#: screen.c:7466
+msgid " VISUAL"
+msgstr " VISUELE"
+
+#: screen.c:7468
+msgid " BLOCK"
+msgstr " BLOK"
+
+#: screen.c:7470
+msgid " LINE"
+msgstr " REËL"
+
+#: screen.c:7483 screen.c:7537
+msgid "recording"
+msgstr "besig om op te neem"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "soektog het BO getref, gaan voort van ONDER af"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "soektog het ONDER getref, gaan voort van BO af"
+
+#: search.c:440
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Ongeldige soekstring: %s"
+
+#: search.c:747
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: soektog het BO getref sonder treffer vir: %s"
+
+#: search.c:749
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: soektog het ONDER getref sonder treffer vir: %s"
+
+#: search.c:1107
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: Verwag '?' of '/' na ';'"
+
+#: search.c:3476
+msgid " (includes previously listed match)"
+msgstr " (sluit in vorige gelyste treffer)"
+
+#. cursor at status line
+#: search.c:3496
+msgid "--- Included files "
+msgstr "--- Ingeslote lêers"
+
+#: search.c:3498
+msgid "not found "
+msgstr "nie gevind nie "
+
+#: search.c:3499
+msgid "in path ---\n"
+msgstr "in pad ---\n"
+
+#: search.c:3538
+msgid " (Already listed)"
+msgstr " (Alreeds gelys)"
+
+#: search.c:3540
+msgid " NOT FOUND"
+msgstr " NIE GEVIND NIE"
+
+#: search.c:3592
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Deursoek ingeslote lêer: %s"
+
+#: search.c:3810
+msgid "E387: Match is on current line"
+msgstr "E387: Treffer is op huidige reël"
+
+#: search.c:3950
+msgid "All included files were found"
+msgstr "Alle ingeslote lêers is gevind"
+
+#: search.c:3952
+msgid "No included files"
+msgstr "Geen ingeslote lêers nie"
+
+#: search.c:3968
+msgid "E388: Couldn't find definition"
+msgstr "E388: Kon definisie nie vind nie"
+
+#: search.c:3970
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Kon patroon nie vind nie"
+
+#: syntax.c:2991
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: Ongeldige parameter: %s"
+
+#: syntax.c:3168
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: Geen sodanige sintakskluster nie: %s"
+
+#: syntax.c:3332
+msgid "No Syntax items defined for this buffer"
+msgstr "Geen Sintaks-items gedefinieer vir hierdie buffer nie"
+
+#: syntax.c:3340
+msgid "syncing on C-style comments"
+msgstr "sinchroniseer met C-styl kommentaar"
+
+#: syntax.c:3348
+msgid "no syncing"
+msgstr "geen sinchronisering"
+
+#: syntax.c:3351
+msgid "syncing starts "
+msgstr "sinchronisasie begin "
+
+#: syntax.c:3353 syntax.c:3422
+msgid " lines before top line"
+msgstr " reëls voor boonste lyn"
+
+#: syntax.c:3357
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Sintaks sync items ---"
+
+#: syntax.c:3360
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"sinchronisering met items"
+
+#: syntax.c:3365
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Sintaks items ---"
+
+#: syntax.c:3388
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: Geen sodanige sintakskluster nie: %s"
+
+#: syntax.c:3412
+msgid "minimal "
+msgstr "minimaal "
+
+#: syntax.c:3419
+msgid "maximal "
+msgstr "maksimaal "
+
+#: syntax.c:4047
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: 'group[t]here' nie hier aanvaar nie"
+
+#: syntax.c:4071
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: Kon nie omgewingsitem vind vir %s nie"
+
+#: syntax.c:4099
+msgid "E395: contains argument not accepted here"
+msgstr "E395: bevat parameters nie hier aanvaar nie"
+
+#: syntax.c:4110
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: 'containedin' parameter nie hier aanvaar nie"
+
+#: syntax.c:4188
+msgid "E397: Filename required"
+msgstr "E397: Lêernaam benodig"
+
+#: syntax.c:4524
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Ontbrekende '=': %s"
+
+#: syntax.c:4680
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Nie genoeg parameters nie: sintaksomgewing %s"
+
+#: syntax.c:5011
+msgid "E400: No cluster specified"
+msgstr "E400: Geen kluster gespesifiseer nie"
+
+#: syntax.c:5048
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Patroonbegrenser nie gevind nie: %s"
+
+#: syntax.c:5123
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Gemors na patroon: %s"
+
+#: syntax.c:5205
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: sintaks sync: reëlvoortgaanpatroon twee keer gespesifiseer"
+
+#: syntax.c:5262
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Ongeldige parameters: %s"
+
+#: syntax.c:5312
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Ontbrekende gelykaanteken: %s"
+
+#: syntax.c:5318
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Leë parameter: %s"
+
+#: syntax.c:5345
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s nie toegelaat hier nie"
+
+#: syntax.c:5352
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s moet vóór in 'contains' lys wees"
+
+#: syntax.c:5422
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Onbekende groepnaam: %s"
+
+#: syntax.c:5645
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Ongeldige :syntax subbevel %s"
+
+#: syntax.c:6024
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: uitliggroep nie gevind nie: %s"
+
+#: syntax.c:6048
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Te min parameters: \":highlight link %s\""
+
+#: syntax.c:6055
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: Te veel parameters: \":highlight link %s\""
+
+#: syntax.c:6075
+msgid "E414: group has settings, highlight link ignored"
+msgstr ""
+"E414: groep het instellings, uitligskakel ('highlight link') geïgnoreer"
+
+#: syntax.c:6204
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: onverwagte gelykaanteken: %s"
+
+#: syntax.c:6240
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: ontbrekende gelykaanteken: %s"
+
+#: syntax.c:6262
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: ontbrekende parameter: %s"
+
+#: syntax.c:6299
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: Ongeldige waarde: %s"
+
+#: syntax.c:6418
+msgid "E419: FG color unknown"
+msgstr "E419: FG kleur onbekend"
+
+#: syntax.c:6429
+msgid "E420: BG color unknown"
+msgstr "E420: BG kleur onbekend"
+
+#: syntax.c:6484
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Kleurnaam of -nommer nie herken nie: %s"
+
+#: syntax.c:6688
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: terminaalkode te lank: %s"
+
+#: syntax.c:6735
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: Ongeldige parameter: %s"
+
+#: syntax.c:7264
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: Te veel verskillende uitlig-eienskappe in gebruik"
+
+# njj: 'inkleur' vir 'uitlig'? net 'n idee ..
+#: tag.c:90
+msgid "at bottom of tag stack"
+msgstr "onderaan etiketstapel"
+
+#: tag.c:91
+msgid "at top of tag stack"
+msgstr "bo-aan etiketstapel"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Kan nie vóór eerste etiket-treffer gaan nie"
+
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: etiket nie gevind nie: %s"
+
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr " # pri tipe etiket"
+
+#: tag.c:548
+msgid "file\n"
+msgstr "lêer\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Sleutel nommer van keuse in (<CR> om te stop): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: Daar is slegs een etiket-treffer"
+
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Kan nie verby laaste etiket-treffer gaan nie"
+
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Lêer \"%s\" bestaan nie"
+
+#. Give an indication of the number of matching tags
+#: tag.c:780
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "etiket %d van %d%s"
+
+#: tag.c:783
+msgid " or more"
+msgstr " of meer"
+
+#: tag.c:785
+msgid " Using tag with different case!"
+msgstr " Gaan etiket met ander kas gebruik!"
+
+#: tag.c:828
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Lêer \"%s\" bestaan nie"
+
+#. Highlight title
+#: tag.c:897
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # NA etiket VAN reël in lêer/teks"
+
+#: tag.c:1144
+msgid "Linear tag search"
+msgstr "Liniêre etiketsoek"
+
+#: tag.c:1146
+msgid "Binary tag search"
+msgstr "Binêre etiketsoek"
+
+#: tag.c:1172
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Deursoek etiketlêer %s"
+
+#: tag.c:1356
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Etiketlêergids afgekap vir %s\n"
+
+#: tag.c:1847
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Formaatfout in etiketlêer \"%s\""
+
+#: tag.c:1851
+#, c-format
+msgid "Before byte %ld"
+msgstr "Voor greep %ld"
+
+#: tag.c:1872
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Etiketlêer ongesorteer: %s"
+
+#. never opened any tags file
+#: tag.c:1911
+msgid "E433: No tags file"
+msgstr "E433: Geen etiketlêer nie"
+
+#: tag.c:2583
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Kan nie etiketpatroon vind nie"
+
+#: tag.c:2594
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Kon nie etiket vind nie, ek raai maar!"
+
+#: term.c:1723
+msgid "' not known. Available builtin terminals are:"
+msgstr "' onbekend. Beskikbare ingeboude terminale is:"
+
+#: term.c:1747
+msgid "defaulting to '"
+msgstr "gebruik verstek '"
+
+#: term.c:2100
+msgid "Cannot open termcap file"
+msgstr "Kan nie 'termcap'-lêer oopmaak nie"
+
+#: term.c:2103
+msgid "Terminal entry not found in terminfo"
+msgstr "Terminaalinskrywing nie in 'terminfo' gevind nie"
+
+#: term.c:2105
+msgid "Terminal entry not found in termcap"
+msgstr "Terminaalinskrywing nie in 'termcap' gevind nie"
+
+#: term.c:2264
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Geen \"%s\" inskrywing in termcap nie"
+
+#: term.c:2738
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: terminaalvermoë \"cm\" vereis"
+
+#. Highlight title
+#: term.c:4878
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Terminaal sleutels ---"
+
+#: ui.c:240
+msgid "new shell started\n"
+msgstr "nuwe dop begin\n"
+
+#: ui.c:1705
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: Fout met lees van invoer, verlaat...\n"
+
+#. must display the prompt
+#: undo.c:351
+msgid "No undo possible; continue anyway"
+msgstr "Geen herstel moontlik; gaan in elk geval voort"
+
+#: undo.c:506
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: reëlnommers foutief"
+
+#: undo.c:675
+msgid "1 change"
+msgstr "1 verandering"
+
+#: undo.c:677
+#, c-format
+msgid "%ld changes"
+msgstr "%ld veranderinge"
+
+#: undo.c:721
+msgid "E439: undo list corrupt"
+msgstr "E439: herstellys korrup"
+
+#: undo.c:751
+msgid "E440: undo line missing"
+msgstr "E440: herstelreël ontbreek"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:655
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 16/32-bis GUI weergawe"
+
+#: version.c:657
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 32-bis GUI version"
+
+#: version.c:660
+msgid " in Win32s mode"
+msgstr " in Win32s modus"
+
+#: version.c:662
+msgid " with OLE support"
+msgstr " met OLE ondersteuning"
+
+#: version.c:665
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"MS-Windows 32-bis konsole weergawe"
+
+#: version.c:669
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"MS-Windows 16-bis weergawe"
+
+#: version.c:673
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32-bis MS-DOS weergawe"
+
+#: version.c:675
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16-bis MS-DOS weergawe"
+
+#: version.c:681
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) weergawe"
+
+#: version.c:683
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X weergawe"
+
+#: version.c:686
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS weergawe"
+
+#: version.c:691
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS weergawe"
+
+#: version.c:701
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Ingeslote laslappies:"
+
+#: version.c:728
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Gekompileer op "
+
+#: version.c:731
+msgid "by "
+msgstr "deur "
+
+#: version.c:743
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Enorme weergawe "
+
+#: version.c:746
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Groot weergawe "
+
+#: version.c:749
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Normale weergawe "
+
+#: version.c:752
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Klein weergawe "
+
+#: version.c:754
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Piepklein weergawe "
+
+#: version.c:760
+msgid "without GUI."
+msgstr "sonder GUI."
+
+#: version.c:764
+msgid "with GTK-GNOME GUI."
+msgstr "met GTK-GNOME GUI."
+
+#: version.c:766
+msgid "with GTK GUI."
+msgstr "met GTK GUI"
+
+#: version.c:770
+msgid "with X11-Motif GUI."
+msgstr "met X11-Motif GUI."
+
+#: version.c:773
+msgid "with X11-Athena GUI."
+msgstr "met X11-Athena GUI"
+
+#: version.c:776
+msgid "with BeOS GUI."
+msgstr "met BeOS GUI"
+
+#: version.c:779
+msgid "with Photon GUI."
+msgstr "met Photon GUI."
+
+#: version.c:782
+msgid "with GUI."
+msgstr "met GUI."
+
+#: version.c:785
+msgid "with Carbon GUI."
+msgstr "met Carbon GUI."
+
+#: version.c:788
+msgid "with Cocoa GUI."
+msgstr "met Cocoa GUI."
+
+#: version.c:791
+msgid "with (classic) GUI."
+msgstr "met (klassieke) GUI."
+
+#: version.c:802
+msgid " Features included (+) or not (-):\n"
+msgstr " Kenmerke in- (+) of uitgesluit (-):\n"
+
+#: version.c:814
+msgid " system vimrc file: \""
+msgstr " stelsel vimrc-lêer: \""
+
+#: version.c:819
+msgid " user vimrc file: \""
+msgstr " gebruiker vimrc-lêer: \""
+
+#: version.c:824
+msgid " 2nd user vimrc file: \""
+msgstr " 2de gebruiker vimrc-lêer \""
+
+#: version.c:829
+msgid " 3rd user vimrc file: \""
+msgstr " 3de gebruiker vimrc-lêer \""
+
+#: version.c:834
+msgid " user exrc file: \""
+msgstr " gebruiker exrc-lêer: \""
+
+#: version.c:839
+msgid " 2nd user exrc file: \""
+msgstr " 2de gebruiker exrc-lêer: \""
+
+#: version.c:845
+msgid " system gvimrc file: \""
+msgstr " stelsel gvimrc-lêer: \""
+
+#: version.c:849
+msgid " user gvimrc file: \""
+msgstr " gebruiker gvimrc-lêer: \""
+
+#: version.c:853
+msgid "2nd user gvimrc file: \""
+msgstr "2de gebruiker gvimrc-lêer: \""
+
+#: version.c:858
+msgid "3rd user gvimrc file: \""
+msgstr "3de gebruiker gvimrc-lêer: \""
+
+#: version.c:865
+msgid " system menu file: \""
+msgstr " stelsel kieslys-lêer: \""
+
+#: version.c:873
+msgid " fall-back for $VIM: \""
+msgstr " bystand vir $VIM: \""
+
+#: version.c:879
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " bystand vir $VIMRUNTIME: \""
+
+#: version.c:883
+msgid "Compilation: "
+msgstr "Kompilering: "
+
+#: version.c:889
+msgid "Compiler: "
+msgstr "Kompileerder: "
+
+#: version.c:894
+msgid "Linking: "
+msgstr "Koppeling: "
+
+#: version.c:899
+msgid " DEBUG BUILD"
+msgstr " ONTFOUTINGS-KOMPILERING"
+
+#: version.c:934
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi Met skop"
+
+# njj: :))
+#: version.c:936
+msgid "version "
+msgstr "Weergawe "
+
+#: version.c:937
+msgid "by Bram Moolenaar et al."
+msgstr "deur Bram Moolenaar et al."
+
+#: version.c:938
+msgid "Vim is open source and freely distributable"
+msgstr "Vim is vryekode, en vrylik verspreibaar"
+
+#: version.c:940
+msgid "Help poor children in Uganda!"
+msgstr "Help arm kinders in Uganda!"
+
+#: version.c:941
+msgid "type :help iccf<Enter> for information "
+msgstr "tik :help iccf<Enter> vir meer inligting hieroor "
+
+#: version.c:943
+msgid "type :q<Enter> to exit "
+msgstr "tik :q<Enter> om program verlaat "
+
+#: version.c:944
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "tik :help<Enter> of <F1> vir aanlyn hulp "
+
+#: version.c:945
+msgid "type :help version6<Enter> for version info"
+msgstr "tik :help version6<Enter> vir weergawe-inligting"
+
+#: version.c:948
+msgid "Running in Vi compatible mode"
+msgstr "Voer tans uit in Vi-versoenbare modus"
+
+#: version.c:949
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "tik :set nocp<Enter> vir Vim verstekwaardes "
+
+#: version.c:950
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "tik :help cp-default<Enter> vir meer inligting hieroor"
+
+#: version.c:990
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "WAARSKUWING: Windows 95/98/ME bespeur"
+
+#: version.c:993
+msgid "type :help windows95<Enter> for info on this"
+msgstr "tik :help windows95<Enter> vir meer inligting hieroor"
+
+#: window.c:201
+msgid "E441: There is no preview window"
+msgstr "E441: Daar is nie 'n voorskou-venster nie"
+
+#: window.c:568
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: Kan nie bo-links en onder-regs terselfdertyd verdeel nie"
+
+#: window.c:1327
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Kan nie roteer terwyl 'n ander venster verdeel is nie"
+
+#: window.c:1810
+msgid "E444: Cannot close last window"
+msgstr "E444: Kan nie laaste venster toemaak nie"
+
+#: window.c:2474
+msgid "Already only one window"
+msgstr "Daar is alreeds slegs een venster"
+
+#: window.c:2521
+msgid "E445: Other window contains changes"
+msgstr "E445: Die ander venster bevat veranderinge"
+
+#: window.c:4341
+msgid "E446: No file name under cursor"
+msgstr "E446: Geen lêernaam onder loper"
+
+#: window.c:4460
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Kan lêer \"%s\" nie vind in pad nie"
+
+#: ../GvimExt/gvimext.cpp:586
+msgid "Edit with &multiple Vims"
+msgstr "Wysig met &meer as een Vim"
+
+#: ../GvimExt/gvimext.cpp:592
+msgid "Edit with single &Vim"
+msgstr "Wysig met 'n enkel &Vim"
+
+#: ../GvimExt/gvimext.cpp:604
+msgid "Edit with &Vim"
+msgstr "Wysig met &Vim"
+
+#. Now concatenate
+#: ../GvimExt/gvimext.cpp:628
+msgid "Edit with existing Vim - &"
+msgstr "Wysig met bestaande Vim - &"
+
+#: ../GvimExt/gvimext.cpp:752
+msgid "Edits the selected file(s) with Vim"
+msgstr "Wysig die gekose lêer(s) met Vim"
+
+#: ../GvimExt/gvimext.cpp:891 ../GvimExt/gvimext.cpp:969
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "FOut met die skep van proses: Kyk of gvim in jou pad is!"
+
+#: ../GvimExt/gvimext.cpp:892 ../GvimExt/gvimext.cpp:906
+#: ../GvimExt/gvimext.cpp:970
+msgid "gvimext.dll error"
+msgstr "'gvimext.dll' fout"
+
+#: ../GvimExt/gvimext.cpp:905
+msgid "Path length too long!"
+msgstr "Pad-lengte te lank"
+
+#: globals.h:878
+msgid "--No lines in buffer--"
+msgstr "--Geen reëls in buffer--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1019
+msgid "Command aborted"
+msgstr "Bevel gekansellleer"
+
+#: globals.h:1020
+msgid "Argument required"
+msgstr "Parameter benodig"
+
+#: globals.h:1021
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ moet gevolg word deur /, ? of &"
+
+#: globals.h:1023
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: Ongeldig in bevelreël venster: <CR> voer uit, CTRL-C stop"
+
+#: globals.h:1025
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Bevel uit exrc/vimrc nie toegelaat in huidige gids- of etiketsoektog nie"
+
+#: globals.h:1026
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Lêer bestaan (gebruik ! om te dwing)"
+
+#: globals.h:1027
+msgid "Command failed"
+msgstr "Bevel het gefaal"
+
+#: globals.h:1028
+msgid "Internal error"
+msgstr "Interne fout"
+
+#: globals.h:1029
+msgid "Interrupted"
+msgstr "Onderbreek"
+
+#: globals.h:1030
+msgid "E14: Invalid address"
+msgstr "E14: Ongeldige adres"
+
+#: globals.h:1031
+msgid "Invalid argument"
+msgstr "Ongeldige parameter"
+
+#: globals.h:1032
+#, c-format
+msgid "Invalid argument: %s"
+msgstr "Ongeldige parameter: %s"
+
+#: globals.h:1034
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Ongeldige uitdrukking: %s"
+
+#: globals.h:1036
+msgid "E16: Invalid range"
+msgstr "E16: Ongeldige omvang"
+
+#: globals.h:1037
+msgid "Invalid command"
+msgstr "Ongeldige bevel"
+
+#: globals.h:1039
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" is 'n gids"
+
+#: globals.h:1042
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Onverwagte karakters voor '='"
+
+#: globals.h:1044
+msgid "E19: Mark has invalid line number"
+msgstr "E19: Merker het ongeldige reëlnommer"
+
+#: globals.h:1045
+msgid "E20: Mark not set"
+msgstr "E20: Merker nie gestel nie"
+
+#: globals.h:1046
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Kan nie wysig nie, 'modifiable' is af"
+
+#: globals.h:1047
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Skripte te diep ge-nes"
+
+#: globals.h:1048
+msgid "E23: No alternate file"
+msgstr "E23: Geen alternatiewe lêer nie"
+
+#: globals.h:1049
+msgid "E24: No such abbreviation"
+msgstr "E24: Afkorting bestaan nie"
+
+#: globals.h:1050
+msgid "No ! allowed"
+msgstr "Geen ! toegelaat nie"
+
+#: globals.h:1052
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: GUI kan nie gebruik word nie: Nie tydens kompilering gekies nie"
+
+#: globals.h:1055
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr ""
+"E26: Hebreeus kan nie gebruik word nie: Nie tydens kompilering gekies nie\n"
+
+#: globals.h:1058
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr ""
+"E27: Farsi kan nie gebruik word nie: Nie tydens kompilering gekies nie\n"
+
+#: globals.h:1061
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Geen sodanige uitliggroepnaam nie: %s"
+
+#: globals.h:1063
+msgid "E29: No inserted text yet"
+msgstr "E29: Nog geen ingevoegde teks nie"
+
+#: globals.h:1064
+msgid "E30: No previous command line"
+msgstr "E30: Geen vorige bevelreël nie"
+
+#: globals.h:1065
+msgid "E31: No such mapping"
+msgstr "E31: Geen so 'n binding nie"
+
+#: globals.h:1066
+msgid "No match"
+msgstr "Geen treffer nie"
+
+#: globals.h:1067
+#, c-format
+msgid "No match: %s"
+msgstr "Geen treffer: %s"
+
+#: globals.h:1068
+msgid "E32: No file name"
+msgstr "E32: Geen lêernaam"
+
+#: globals.h:1069
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: Geen vorige vervangingspatroon nie"
+
+#: globals.h:1070
+msgid "E34: No previous command"
+msgstr "E34: Geen vorige bevel nie"
+
+#: globals.h:1071
+msgid "E35: No previous regular expression"
+msgstr "E35: Geen vorige patroon nie"
+
+#: globals.h:1072
+msgid "No range allowed"
+msgstr "Geen omvang toegelaat nie"
+
+#: globals.h:1074
+msgid "E36: Not enough room"
+msgstr "E36: Te min plek"
+
+#: globals.h:1076
+#, c-format
+msgid "Can't create file %s"
+msgstr "Kan nie lêer %s skep nie"
+
+#: globals.h:1077
+msgid "Can't get temp file name"
+msgstr "Kan nie tydelike lêernaam kry nie"
+
+#: globals.h:1078
+#, c-format
+msgid "Can't open file %s"
+msgstr "Kan nie lêer %s oopmaak nie"
+
+#: globals.h:1079
+#, c-format
+msgid "Can't read file %s"
+msgstr "Kan nie lêer %s lees nie"
+
+#: globals.h:1080
+msgid "E37: No write since last change (use ! to override)"
+msgstr "E37: Ongeskryf sedert vorige verandering (gebruik ! om te dwing)"
+
+#: globals.h:1081
+msgid "E38: Null argument"
+msgstr "E38: Nul parameter"
+
+# njj: hmm, hoe hanteer mens die onderskeid tussen 'Null' (afwesig) en
+# njj: 'Zero' (die nommer)?
+#: globals.h:1083
+msgid "E39: Number expected"
+msgstr "E39: Nommer verwag"
+
+#: globals.h:1086
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Kan nie foutlêer %s oopmaak nie"
+
+#: globals.h:1089
+msgid "E41: Out of memory!"
+msgstr "E41: Geheue op!"
+
+#: globals.h:1092
+msgid "Pattern not found"
+msgstr "Patroon nie gevind nie"
+
+#: globals.h:1094
+#, c-format
+msgid "Pattern not found: %s"
+msgstr "Patroon nie gevind nie: %s"
+
+#: globals.h:1095
+msgid "Argument must be positive"
+msgstr "Parameter moet positief wees"
+
+#: globals.h:1097
+msgid "E42: No Errors"
+msgstr "E42: Geen Foute"
+
+#: globals.h:1099
+msgid "E43: Damaged match string"
+msgstr "E43: Beskadige trefferstring"
+
+#: globals.h:1100
+msgid "E44: Corrupted regexp program"
+msgstr "E44: Korrupte patroonprogram"
+
+#: globals.h:1101
+msgid "E45: 'readonly' option is set (use ! to override)"
+msgstr "E45: 'readonly' opsie is aan (gebruik ! om te dwing)"
+
+#: globals.h:1103
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Kan nie lees-alleen veranderlike stel nie \"%s\""
+
+#: globals.h:1106
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Fout tydens lees van 'errorfile'"
+
+#: globals.h:1109
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: Nie toegelaat in sandput nie"
+
+#: globals.h:1111
+msgid "E49: Invalid scroll size"
+msgstr "E49: Ongeldige rolgrootte"
+
+#: globals.h:1112
+msgid "E91: 'shell' option is empty"
+msgstr "E91: 'shell' (dop) opsie is leeg"
+
+#: globals.h:1113
+msgid "E72: Close error on swap file"
+msgstr "E72: Sluitfout met ruillêer"
+
+#: globals.h:1114
+msgid "E73: tag stack empty"
+msgstr "E73: etiketstapel leeg"
+
+#: globals.h:1115
+msgid "E74: Command too complex"
+msgstr "E74: Bevel te kompleks"
+
+#: globals.h:1116
+msgid "E75: Name too long"
+msgstr "E75: Naam te lank"
+
+#: globals.h:1117
+msgid "E76: Too many ["
+msgstr "E76: Te veel ["
+
+#: globals.h:1118
+msgid "E77: Too many file names"
+msgstr "E77: Te veel lêername"
+
+#: globals.h:1119
+msgid "Trailing characters"
+msgstr "Oorbodige karakters"
+
+#: globals.h:1120
+msgid "E78: Unknown mark"
+msgstr "E78: Onbekende merker"
+
+#: globals.h:1121
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Kan nie plekhouers uitbrei nie"
+
+#: globals.h:1122
+msgid "E80: Error while writing"
+msgstr "E80: Fout tydens skryfoperasie"
+
+#: globals.h:1123
+msgid "Zero count"
+msgstr "Nul telling"
+
+#: globals.h:1125
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: Gebruik van '<SID>' buite skripkonteks"
+
+#~ msgid "E258: no matches found in cscope connections"
+#~ msgstr "E258: geen treffers gevind in 'cscope' verbindings nie"
+
+#~ msgid "No servers found for this display"
+#~ msgstr "Geen bedieners gevind vir die 'display' nie"
+
+#~ msgid "Missing filename"
+#~ msgstr "Ontbrekende lêernaam"
+
+#~ msgid "Invalid line number: %ld"
+#~ msgstr "Ongeldige reëlnommer: %ld"
+
+#~ msgid "Cannot use :normal from event handler"
+#~ msgstr "Kan ':normal' nie vanuit gebeurtenishanteerder gebruik nie"
+
+#~ msgid "%ldL, %ldC"
+#~ msgstr "%ldR, %ldK"
+
+#~ msgid "VIM - Help on..."
+#~ msgstr "VIM - Hulp met.."
+
+#~ msgid "Topic:"
+#~ msgstr "Onderwerp:"
+
+#~ msgid "Error: During loading fontset %s"
+#~ msgstr "Fout: Gedurende die laai van fontstel %s"
+
+#~ msgid "locale is not set correctly"
+#~ msgstr "lokaal is nie korrek gestel nie"
+
+#~ msgid "Set LANG environment variable to your locale"
+#~ msgstr "Stel die 'LANG' omgewingsveranderlike na jou lokaal toe"
+
+#~ msgid "For korean:"
+#~ msgstr "Vir Afrikaans:"
+
+#~ msgid " csh: setenv LANG ko"
+#~ msgstr " csh: setenv LANG af"
+
+#~ msgid " sh : export LANG=ko"
+#~ msgstr " sh: export LANG=af"
+
+#~ msgid "fontset name: %s"
+#~ msgstr "fontstel naam: %s"
+
+#~ msgid "Your language Font missing"
+#~ msgstr "Jou taal Font ontbreek"
+
+#~ msgid "loaded fontname: %s"
+#~ msgstr "gelaaide fontnaam: %s"
+
+#~ msgid "Cannot allocate memory for debugger sign"
+#~ msgstr "Kan nie geheue toeken vir ontfouterteken nie"
+
+#~ msgid "automata ERROR: internal"
+#~ msgstr "automata FOUT: intern"
+
+#~ msgid "cs_add_common: alloc fail #1"
+#~ msgstr "'cs_add_common': toeken onsuksesvol #1"
+
+#~ msgid "cs_add_common: alloc fail #2"
+#~ msgstr "'cs_add_common': toeken onsuksesvol #2"
+
+#~ msgid "cs_add_common: alloc fail #3"
+#~ msgstr "'cs_add_common': toeken onsuksesvol #3"
+
+#~ msgid "cs_add_common: alloc fail #4"
+#~ msgstr "'cs_add_common': toeken onsuksesvol #4"
+
+#~ msgid "Retrieve next symbol"
+#~ msgstr "Kry volgende simbool"
+
+#~ msgid "-- SNiFF+ commands --"
+#~ msgstr "-- SNiFF+ bevele --"
+
+#~ msgid "Unrecognized sniff request [%s]"
+#~ msgstr "Onbekende sniff versoek [%s]"
+
+#~ msgid "Can't create input context."
+#~ msgstr "Kan nie invoerkonteks skep nie."
+
+#~ msgid "Sorry, deleting a menu is not possible in the Athena version"
+#~ msgstr ""
+#~ "Jammer, in die Athena weergawe is dit onmoontlik om 'n kieslys te skrap"
+
+#~ msgid "Out of memory"
+#~ msgstr "Geheue op"
+
+#~ msgid "PC (32 bits Vim)"
+#~ msgstr "PC (32 bisse Vim)"
+
+#~ msgid "PC (16 bits Vim)"
+#~ msgstr "PC (16 bisse Vim)"
+
+#~ msgid "Unsupported screen mode"
+#~ msgstr "Ongesteunde skermmodus"
+
+#~ msgid "deadly signal"
+#~ msgstr "dodelike sein"
+
+#~ msgid "some"
+#~ msgstr "sommige"
+
+#~ msgid "Library call failed"
+#~ msgstr "Biblioteekfunksieroep het gefaal"
+
+#~ msgid "Cannot clear all highlight groups"
+#~ msgstr "Kan nie alle uitliggroepe leegmaak nie"
+
+#~ msgid "GUI is not running"
+#~ msgstr "GUI voer nie uit nie"
+
+#~ msgid "Command too long"
+#~ msgstr "Bevel te lank"
+
+#~ msgid "Ambiguous mapping"
+#~ msgstr "Dubbelsinnige binding"
+
+#~ msgid "Ambiguous mapping, conflicts with \"%s\""
+#~ msgstr "Dubbelsinnige binding, bots met \"%s\""
+
+#~ msgid "Too many \\z("
+#~ msgstr "Te veel \\z("
+
+#~ msgid "Too many \\("
+#~ msgstr "Te veel \\("
+
+#~ msgid "Unmatched \\z("
+#~ msgstr "Onpaar \\z("
+
+#~ msgid "Unmatched \\%("
+#~ msgstr "Onpaar \\z"
+
+#~ msgid "Unmatched \\("
+#~ msgstr "Onpaar \\("
+
+#~ msgid "Unmatched \\)"
+#~ msgstr "Onpaar \\)"
+
+#~ msgid "*, \\+ or \\{ operand could be empty"
+#~ msgstr "*, \\+ of \\{ operand mag leeg wees"
+
+#~ msgid "invalid character after \\@"
+#~ msgstr "ongeldige karakter na \\@"
+
+#~ msgid "Too many complex \\{...}s"
+#~ msgstr "Te veel komplekse \\{...}ies"
+
+#~ msgid "Nested *, \\=, \\+, \\! or \\{"
+#~ msgstr "Geneste *, \\=, \\+, \\! of \\{"
+
+#~ msgid "invalid use of \\_"
+#~ msgstr "ongeldige gebruik van \\_"
+
+#~ msgid "\\= follows nothing"
+#~ msgstr "\\= volg niks"
+
+#~ msgid "\\+ follows nothing"
+#~ msgstr "\\+ volg niks"
+
+#~ msgid "\\@ follows nothing"
+#~ msgstr "\\@ volg niks"
+
+#~ msgid "\\{ follows nothing"
+#~ msgstr "\\{ volg niks"
+
+#~ msgid "\\* follows nothing"
+#~ msgstr "\\* volg niks"
+
+#~ msgid "Illegal back reference"
+#~ msgstr "Ongeldige tru-verwysing"
+
+#~ msgid "\\z( not allowed here"
+#~ msgstr "\\z( nie hier toegelaat nie"
+
+#~ msgid "\\z1 et al. not allowed here"
+#~ msgstr "\\z1 e.a. nie hier toegelaat nie"
+
+#~ msgid "Invalid character after \\z"
+#~ msgstr "ongeldige karakter na \\z"
+
+#~ msgid "Missing ] after \\%["
+#~ msgstr "Ontbrekende ] na \\%["
+
+#~ msgid "Empty \\%[]"
+#~ msgstr "Leë \\%[]"
+
+#~ msgid "Invalid character after \\%"
+#~ msgstr "ongeldige karakter na \\%"
+
+#~ msgid "Unexpected magic character; check META."
+#~ msgstr "Onverwagte toorkarakter; kyk na META."
+
+#~ msgid "type :help uganda<Enter> if you like Vim "
+#~ msgstr "tik :help uganda<Enter> as jy hou van Vim "
+
+#~ msgid " WARNING: Intel CPU detected. "
+#~ msgstr " WAARSKUWING: Intel SVE bespeur. "
+
+#~ msgid " PPC has a much better architecture. "
+#~ msgstr " PPC het 'n veel beter argitektuur. "
+
+#~ msgid "Security error: new viminfo file is a symbolic link"
+#~ msgstr "Sekuriteitsfout: nuwe viminfo lêer is a simboliese skakel"
+
+#~ msgid "line ~%ld: %s"
+#~ msgstr "reël ~%ld: %s"
+
+#~ msgid "makeef option not set"
+#~ msgstr "'makeef' opsie nie aan nie"
+
+#~ msgid "Security error: filter output is a symbolic link: %s"
+#~ msgstr "Sekuriteitsfout: filter afvoer is 'n simboliese skakel"
+
+#~ msgid "Security error: 'charconvert' output is a symbolic link"
+#~ msgstr "Sekuriteitsfout: 'charconvert' afvoer is 'n simboliese skakel"
+
+#~ msgid "Security error: filter input is a symbolic link: %s"
+#~ msgstr "Sekuriteitsfout: filter invoer is 'n simboliese skakel"
+
+#~ msgid "Fold must be at least two lines"
+#~ msgstr "'n Vou moet ten minste 2 reëls wees"
+
+#~ msgid "No fold at this line"
+#~ msgstr "Geen vou by hierdie reël nie"
+
+#~ msgid "Security error: shell command output is a symbolic link"
+#~ msgstr "Sekuriteitsfout: Dop-bevel afvoer is 'n simboliese skakel"
+
+#~ msgid "Warning: %s option changed from modeline"
+#~ msgstr "Waarskuwing: %s opsie verander vanaf moduslyn"
+
+#~ msgid "Change dir debugging enabled."
+#~ msgstr "Verandergids ontfouting in staat gestel"
+
+#~ msgid "Not a proper file name: '%s'"
+#~ msgstr "Nie 'n geldige lêernaam nie: '%s'"
+
+#~ msgid "File name '%s' is valid"
+#~ msgstr "lêernaam '%s is ongeldig"
+
+#~ msgid "Leave: %s"
+#~ msgstr "Verlaat: %s"
+
+#~ msgid "WARNING: tag command changed a buffer!!!"
+#~ msgstr "WAARSKUWING: etiketbevel het buffer verander!!!"
diff --git a/src/po/ca.po b/src/po/ca.po
new file mode 100644
index 000000000..6a50ef6c1
--- /dev/null
+++ b/src/po/ca.po
@@ -0,0 +1,6341 @@
+# Catalan messages for vim.
+# Copyright (C) 2003, 2004, Ernest Adrogué <eadrogue@gmx.net>.
+# This file is distributed under the GNU General Public License.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: vim 6.2\n"
+"POT-Creation-Date: 2003-11-01 20:10+0100\n"
+"PO-Revision-Date: 2004-01-19 13:57+0100\n"
+"Last-Translator: Ernest Adrogué <eadrogue@gmx.net>\n"
+"Language-Team: Catalan <ca@dodds.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: No s'ha pogut assignar memòria per cap buffer, sortint..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: No s'ha pogut assignar memòria pel buffer, usant-ne un altre..."
+
+# unload: Treu el buffer de la memòria però el deixa a la llista
+# delete: Treu el buffer de la memòria i de la llista de buffers
+# wipe out: Elimina el buffer amb totes les opcions, marques, etc.
+#
+#: buffer.c:797
+msgid "E515: No buffers were unloaded"
+msgstr "E515: No s'ha alliberat cap buffer"
+
+#: buffer.c:799
+msgid "E516: No buffers were deleted"
+msgstr "E516: No s'ha eliminat cap buffer"
+
+#: buffer.c:801
+msgid "E517: No buffers were wiped out"
+msgstr "E517: No s'ha destruït cap buffer"
+
+#: buffer.c:809
+msgid "1 buffer unloaded"
+msgstr "S'ha alliberat 1 buffer"
+
+#: buffer.c:811
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "S'han alliberat %d buffers"
+
+#: buffer.c:816
+msgid "1 buffer deleted"
+msgstr "S'ha eliminat 1 buffer"
+
+#: buffer.c:818
+#, c-format
+msgid "%d buffers deleted"
+msgstr "S'han eliminat %d buffers"
+
+#: buffer.c:823
+msgid "1 buffer wiped out"
+msgstr "S'ha destruït 1 buffer"
+
+#: buffer.c:825
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "S'han destruït %d buffers"
+
+#: buffer.c:886
+msgid "E84: No modified buffer found"
+msgstr "E84: No s'ha trobat cap buffer modificat"
+
+#. back where we started, didn't find anything.
+#: buffer.c:925
+msgid "E85: There is no listed buffer"
+msgstr "E85: No hi ha cap buffer a la llista"
+
+#: buffer.c:937
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: No s'ha pogut anar al buffer %ld"
+
+#: buffer.c:940
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: No es pot anar més enllà de l'últim buffer"
+
+#: buffer.c:942
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: No es pot anar més enllà del primer buffer"
+
+#: buffer.c:966
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr "E89: No s'ha desat el buffer %ld (afegiu ! per confirmar)"
+
+#: buffer.c:982
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: No es pot alliberar l'últim buffer"
+
+#: buffer.c:1500
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Atenció: S'ha desbordat la llista de noms de fitxers"
+
+#: buffer.c:1671
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: No s'ha trobat el buffer %ld"
+
+#: buffer.c:1902
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Hi ha més d'una coincidència per %s"
+
+#: buffer.c:1904
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: No hi ha cap coincidència per %s"
+
+#: buffer.c:2299 ex_docmd.c:6560
+#, c-format
+msgid "line %ld"
+msgstr "línia %ld"
+
+#: buffer.c:2382
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Ja existeix un buffer amb aquest nom"
+
+#: buffer.c:2675
+msgid " [Modified]"
+msgstr " [Modificat]"
+
+#: buffer.c:2680
+msgid "[Not edited]"
+msgstr "[No editat]"
+
+#: buffer.c:2685
+msgid "[New file]"
+msgstr "[Fitxer nou]"
+
+#: buffer.c:2686
+msgid "[Read errors]"
+msgstr "[Lectura errònia]"
+
+#: buffer.c:2688 fileio.c:1918
+msgid "[readonly]"
+msgstr "[només lectura]"
+
+#: buffer.c:2703
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 línia --%d%%--"
+
+#: buffer.c:2705
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld línies --%d%%--"
+
+#: buffer.c:2712
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "línia %ld de %ld --%d%%-- col "
+
+#: buffer.c:2813
+msgid "[No file]"
+msgstr "[Cap fitxer]"
+
+#. must be a help buffer
+#: buffer.c:2853
+msgid "help"
+msgstr "ajuda"
+
+#: buffer.c:3412 screen.c:4996
+msgid "[help]"
+msgstr "[ajuda]"
+
+#: buffer.c:3444 screen.c:5002
+msgid "[Preview]"
+msgstr "[Vista prèvia]"
+
+#: buffer.c:3724
+msgid "All"
+msgstr "Tot"
+
+#: buffer.c:3724
+msgid "Bot"
+msgstr "Baix"
+
+#: buffer.c:3726
+msgid "Top"
+msgstr "Dalt"
+
+#: buffer.c:4470
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr "\n# Llista de buffers:\n"
+
+#: buffer.c:4503
+msgid "[Error List]"
+msgstr "[Llista d'errors]"
+
+#: buffer.c:4516 memline.c:1501
+msgid "[No File]"
+msgstr "[Cap fitxer]"
+
+#: buffer.c:4819
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr "\n--- Senyals ---"
+
+#: buffer.c:4838
+#, c-format
+msgid "Signs for %s:"
+msgstr "Senyals per %s:"
+
+#: buffer.c:4844
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " línia=%ld id=%d nom=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: No es poden mostrar diferències amb més de %ld buffers"
+
+#: diff.c:651
+msgid "E97: Cannot create diffs"
+msgstr "E97: No s'han pogut mostrar les diferències"
+
+# És el nom d'un diàleg. Menú "Split patched by..."
+#: diff.c:750
+msgid "Patch file"
+msgstr "Fitxer de diferències"
+
+#: diff.c:1001
+msgid "E98: Cannot read diff output"
+msgstr "E98: No s'ha pogut llegir la sortida de diff"
+
+#: diff.c:1742
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: El buffer actual no es troba en mode diff"
+
+#: diff.c:1754
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: No hi ha cap altre buffer en mode diff"
+
+#: diff.c:1762
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: Hi ha més de 2 buffers en mode diff, no se sap quin usar"
+
+#: diff.c:1785
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: No s'ha trobat el buffer \"%s\""
+
+#: diff.c:1791
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: El buffer \"%s\" no es troba en mode diff"
+
+#: digraph.c:2172
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: No es permeten caràcters d'escapada en un dígraf"
+
+#: digraph.c:2344
+msgid "E544: Keymap file not found"
+msgstr "E544: No s'ha trobat el fitxer de mapa de tecles"
+
+# traducció de «sourced file». eac
+#: digraph.c:2371
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: L'ordre :loadkeymap només es pot usar en fitxers"
+
+# buscar un nom, en lloc del verb «completar». eac
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " Completar paraules clau (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " Mode ^X (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+
+# buscar un nom, en lloc del verb «completar». eac
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " Completar paraules clau locals (^N/^P)"
+
+# buscar un nom, en lloc del verb «completar». eac
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " Completar línies senceres (^L/^N/^P)"
+
+# buscar un nom, en lloc del verb «completar». eac
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " Completar noms de fitxer (^F/^N/^P)"
+
+# buscar un nom, en lloc del verb «completar». eac
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " Completar etiquetes (^]/^N/^P)"
+
+# buscar un nom, en lloc del verb «completar». eac
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " Completar ubicacions (^N/^P)"
+
+# buscar un nom, en lloc del verb «completar». eac
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " Completar definicions (^D/^N/^P)"
+
+# buscar un nom, en lloc del verb «completar». eac
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " Completar paraules de diccionari (^K/^N/^P)"
+
+# buscar un nom, en lloc del verb «completar». eac
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Completar sinònims (^T/^N/^P)"
+
+# buscar un nom, en lloc del verb «completar». eac
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " Completar ordres (^V/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "S'ha arribat al final del paràgraf"
+
+#: edit.c:955
+msgid "'thesaurus' option is empty"
+msgstr "L'opció 'thesaurus' no està definida"
+
+#: edit.c:1159
+msgid "'dictionary' option is empty"
+msgstr "L'opció 'dictionary' no està definida"
+
+#: edit.c:2144
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "S'està examinant el diccionari: %s"
+
+#: edit.c:2350
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (inserir) Desplaçar (^E/^Y)"
+
+#: edit.c:2352
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (substituir) Desplaçar (^E/^Y)"
+
+#: edit.c:2666
+#, c-format
+msgid "Scanning: %s"
+msgstr "Examinant: %s"
+
+#: edit.c:2701
+msgid "Scanning tags."
+msgstr "S'estan examinant les etiquetes."
+
+#: edit.c:3363
+msgid " Adding"
+msgstr " Afegint"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3412
+msgid "-- Searching..."
+msgstr "-- Cercant..."
+
+#: edit.c:3468
+msgid "Back at original"
+msgstr "Original"
+
+#: edit.c:3473
+msgid "Word from other line"
+msgstr "Paraula d'una altra línia"
+
+#: edit.c:3478
+msgid "The only match"
+msgstr "Única coincidència"
+
+#: edit.c:3537
+#, c-format
+msgid "match %d of %d"
+msgstr "coincidència %d de %d"
+
+#: edit.c:3540
+#, c-format
+msgid "match %d"
+msgstr "coincidència %d"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:979
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: La variable és desconeguda: \"%s\""
+
+#: eval.c:1275
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Falten parèntesis: %s"
+
+#: eval.c:1380 eval.c:1394
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: No existeix tal variable: \"%s\""
+
+#: eval.c:1650
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Falta un ':' després de '?'"
+
+#: eval.c:2266
+msgid "E110: Missing ')'"
+msgstr "E110: Falta un ')'"
+
+#: eval.c:2323
+msgid "E111: Missing ']'"
+msgstr "E111: Falta un ']'"
+
+#: eval.c:2399
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Falta el nom de l'opció: %s"
+
+#: eval.c:2417
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: L'opció és desconeguda: %s"
+
+#: eval.c:2481
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Falten cometes: %s"
+
+#: eval.c:2613
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Falten cometes: %s"
+
+#: eval.c:2964
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Arguments no vàlids per la funció %s"
+
+#: eval.c:2993
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: La funció és desconeguda: %s"
+
+#: eval.c:2994
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: Massa arguments per la funció: %s"
+
+#: eval.c:2995
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Falten arguments per la funció: %s"
+
+# traducció "lliure". eac
+#: eval.c:2996
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: Heu usat <SID> en un context no vàlid: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3586 gui.c:4254 gui_gtk.c:1997
+msgid "&Ok"
+msgstr "&D'acord"
+
+#: eval.c:4121
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld línies: "
+
+#: eval.c:5346
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&D'acord\n"
+"&Cancel·la"
+
+#: eval.c:5386
+msgid "called inputrestore() more often than inputsave()"
+msgstr "s'ha cridat inputrestore() més sovint que inputsave()"
+
+#: eval.c:6301
+msgid "E240: No connection to Vim server"
+msgstr "E240: No hi ha connexió amb el servidor Vim"
+
+#: eval.c:6398
+msgid "E277: Unable to read a server reply"
+msgstr "E277: No s'ha pogut llegir la resposta del servidor"
+
+# «res» ? eac
+#: eval.c:6426
+msgid "E258: Unable to send to client"
+msgstr "E258: No s'ha pogut enviar res al client"
+
+# «res» ? eac
+#: eval.c:6474
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: No s'ha pogut enviar res a %s"
+
+#: eval.c:6574
+msgid "(Invalid)"
+msgstr "(No vàlid)"
+
+#: eval.c:7689
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: La variable no està definida: %s"
+
+#: eval.c:8121
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E461: El nom de la variable és il·legal: %s"
+
+#: eval.c:8409
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: La funció %s ja existeix, afegiu ! per substituir-la"
+
+#: eval.c:8476
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: La funció no està definida: %s"
+
+#: eval.c:8489
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Falta un '(': %s"
+
+#: eval.c:8522
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: L'argument és il·legal: %s"
+
+#: eval.c:8601
+msgid "E126: Missing :endfunction"
+msgstr "E126: Falta una declaració :endfunction"
+
+#: eval.c:8684
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: No s'ha pogut redefinir la funció %s: s'està utilitzant"
+
+#: eval.c:8752
+msgid "E129: Function name required"
+msgstr "E129: Es requereix un nom de funció"
+
+#: eval.c:8803
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: El nom de la funció ha de començar en majúscula: %s"
+
+#: eval.c:8995
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: La funció no està definida: %s"
+
+#: eval.c:9000
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: No s'ha pogut eliminar la funció %s: s'està utilitzant"
+
+#: eval.c:9048
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: La profunditat de crides a funcions és superior a 'maxfuncdeptg'"
+
+#. always scroll up, don't overwrite
+#: eval.c:9101
+#, c-format
+msgid "calling %s"
+msgstr "cridant a %s"
+
+#: eval.c:9163
+#, c-format
+msgid "%s aborted"
+msgstr "s'ha avortat %s"
+
+#: eval.c:9165
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s ha retornat #%ld"
+
+#: eval.c:9172
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s ha retornat \"%s\""
+
+#. always scroll up, don't overwrite
+#: eval.c:9188 ex_cmds2.c:2244
+#, c-format
+msgid "continuing in %s"
+msgstr "continuant a %s"
+
+#: eval.c:9214
+msgid "E133: :return not inside a function"
+msgstr "E133: L'ordre :return no es troba dins d'una funció"
+
+#: eval.c:9545
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr "\n# variables globals:\n"
+
+#: ex_cmds2.c:83
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "Mode de depuració. Escriviu \"cont\" per continuar."
+
+#: ex_cmds2.c:87 ex_docmd.c:854
+#, c-format
+msgid "line %ld: %s"
+msgstr "línia %ld: %s"
+
+#: ex_cmds2.c:89
+#, c-format
+msgid "cmd: %s"
+msgstr "ordre: %s"
+
+#: ex_cmds2.c:281
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Punt de ruptura a \"%s%s\" línia %ld"
+
+#: ex_cmds2.c:531
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: No s'ha trobat el punt de ruptura: %s"
+
+#: ex_cmds2.c:557
+msgid "No breakpoints defined"
+msgstr "No s'han definit punts de ruptura"
+
+#: ex_cmds2.c:562
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s línia %ld"
+
+# Títol d'un diàleg [:browse w]. eac
+#: ex_cmds.c:2082 ex_cmds.c:2347 ex_cmds2.c:754
+msgid "Save As"
+msgstr "Anomena i desa"
+
+#: ex_cmds2.c:777
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Voleu desar els canvis a \"%.*s\"?"
+
+#: ex_cmds2.c:779 ex_docmd.c:8917
+msgid "Untitled"
+msgstr "Sense-nom"
+
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: No s'han desat els canvis en el buffer \"%s\""
+
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "Atenció: S'ha canviat de buffer inesperadament (reviseu les auto-ordres)"
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: Només hi ha un fitxer per editar"
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: No es pot anar més enllà del primer fitxer"
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: No es pot anar més enllà de l'últim fitxer"
+
+#: ex_cmds2.c:1841
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Cercant \"%s\" a \"%s\""
+
+#: ex_cmds2.c:1863
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Cercant \"%s\""
+
+# «runtimepath». eac
+#: ex_cmds2.c:1884
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "no s'ha trobat en el 'runtimepath': \"%s\""
+
+# Títol d'un diàleg [:browse source]. eac
+#: ex_cmds2.c:1918
+msgid "Source Vim script"
+msgstr "Executa un script Vim"
+
+#: ex_cmds2.c:2069
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "No es pot executar un directori: \"%s\""
+
+#: ex_cmds2.c:2099
+#, c-format
+msgid "could not source \"%s\""
+msgstr "no s'ha pogut executar \"%s\""
+
+#: ex_cmds2.c:2101
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "línia %ld: no s'ha pogut executar \"%s\""
+
+#: ex_cmds2.c:2115
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "executant \"%s\""
+
+#: ex_cmds2.c:2117
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "línia %ld: executant \"%s\""
+
+#: ex_cmds2.c:2242
+#, c-format
+msgid "finished sourcing %s"
+msgstr "ha finalitzat l'execució de %s"
+
+#: ex_cmds2.c:2580
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Atenció: El separador de línia no és vàlid, potser falta un ^M"
+
+# «sourced file». eac
+#: ex_cmds2.c:2629
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: L'ordre :scriptencoding només es pot utilitzar en scripts"
+
+# «sourced file». eac
+#: ex_cmds2.c:2662
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: L'ordre :finish només es pot utilitzar en scripts"
+
+#: ex_cmds2.c:3105
+#, c-format
+msgid "Page %d"
+msgstr "Pàgina %d"
+
+#: ex_cmds2.c:3261
+msgid "No text to be printed"
+msgstr "No hi ha text per imprimir"
+
+#: ex_cmds2.c:3339
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "S'està imprimint la pàgina %d (%d%%)"
+
+#: ex_cmds2.c:3348
+#, c-format
+msgid " Copy %d of %d"
+msgstr " Còpia %d de %d"
+
+#: ex_cmds2.c:3406
+#, c-format
+msgid "Printed: %s"
+msgstr "S'ha imprès: %s"
+
+#: ex_cmds2.c:3413
+msgid "Printing aborted"
+msgstr "S'ha avortat l'impressió"
+
+#: ex_cmds2.c:3778
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Error en escriure el fitxer PostScript"
+
+#: ex_cmds2.c:4053
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E624: No s'ha pogut obrir el fitxer \"%s\""
+
+#: ex_cmds2.c:4063 ex_cmds2.c:4688
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: No s'ha pogut llegir el fitxer de recursos PostScript \"%s\""
+
+#: ex_cmds2.c:4071
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: El fitxer \"%s\" no és un fitxer de recursos PostScript"
+
+#: ex_cmds2.c:4086 ex_cmds2.c:4106 ex_cmds2.c:4121 ex_cmds2.c:4143
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: El fitxer de recursos PostScript \"%s\" no està suportat"
+
+#: ex_cmds2.c:4173
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: La versió del fitxer de recursos \"%s\" no és vàlida"
+
+#: ex_cmds2.c:4640
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: No s'ha pogut obrir el fitxer PostScript generat"
+
+#: ex_cmds2.c:4673
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: No s'ha pogut obrir el fitxer \"%s\""
+
+#: ex_cmds2.c:4792
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr "E456: No s'ha trobat el fitxer de recursos PostScript \"prolog.ps\""
+
+#: ex_cmds2.c:4823
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: No s'ha trobat el fitxer de recursos PostScript \"%s.ps\""
+
+#: ex_cmds2.c:4841
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr "E620: No s'ha pogut convertir la codificació multi-octet a \"%s\""
+
+#: ex_cmds2.c:4966
+msgid "Sending to printer..."
+msgstr "S'està enviant a la impressora..."
+
+#: ex_cmds2.c:4970
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: Error en imprimir el fitxer PostScript"
+
+#: ex_cmds2.c:4972
+msgid "Print job sent."
+msgstr "S'ha enviat la tasca d'impressió."
+
+# les cadenes substituïdes no es poden traduïr. eac
+#: ex_cmds2.c:5381
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Idioma actual ( %s): \"%s\""
+
+#: ex_cmds2.c:5392
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: No s'ha pogut canviar l'idioma a \"%s\""
+
+# E.G: :ascii
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Hex %02x, Octal %03o"
+
+#: ex_cmds.c:433
+msgid "E134: Move lines into themselves"
+msgstr "E134: No es poden moure línies cap a elles mateixes"
+
+#: ex_cmds.c:502
+msgid "1 line moved"
+msgstr "1 línia desplaçada"
+
+#: ex_cmds.c:504
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld línies desplaçades"
+
+#: ex_cmds.c:909
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld línies filtrades"
+
+#: ex_cmds.c:937
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: Les auto-ordres *Filter* no poden canviar el buffer actual"
+
+#: ex_cmds.c:1022
+msgid "[No write since last change]\n"
+msgstr "[No s'han desat els últims canvis]\n"
+
+#: ex_cmds.c:1268
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s a la línia: "
+
+#: ex_cmds.c:1273
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: Hi han massa errors, s'omet la resta del fitxer"
+
+# les tres següents van juntes. eac
+#: ex_cmds.c:1308
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Llegint el fitxer viminfo \"%s\"%s%s%s"
+
+#: ex_cmds.c:1309
+msgid " info"
+msgstr " per info"
+
+#: ex_cmds.c:1310
+msgid " marks"
+msgstr " per marques"
+
+#: ex_cmds.c:1311
+msgid " FAILED"
+msgstr " ERROR"
+
+#: ex_cmds.c:1403
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: El fitxer viminfo no es pot escriure: %s"
+
+#: ex_cmds.c:1528
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: No s'ha pogut escriure el fitxer viminfo %s!"
+
+#: ex_cmds.c:1536
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Escrivint el fitxer viminfo \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1634
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Aquest fitxer viminfo ha estat generat pel Vim %s.\n"
+
+#: ex_cmds.c:1636
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr "# El podeu editar, si aneu amb compte!\n\n"
+
+#: ex_cmds.c:1638
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Valor de 'encoding' en el moment d'escriure aquest fitxer\n"
+
+#: ex_cmds.c:1737
+msgid "Illegal starting char"
+msgstr "Caràcter inicial il·legal"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2125
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: El fitxer està carregat en un altre buffer"
+
+#: ex_cmds.c:2159
+msgid "Write partial file?"
+msgstr "Voleu escriure un fitxer parcial?"
+
+#: ex_cmds.c:2166
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Useu ! per desar una part del buffer"
+
+#: ex_cmds.c:2281
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Voleu sobrescriure el fitxer existent \"%.*s\"?"
+
+#: ex_cmds.c:2352
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: No hi ha nom de fitxer pel buffer %ld"
+
+#: ex_cmds.c:2390
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: No s'ha escrit el fitxer: L'opció 'write' ho impedeix"
+
+#: ex_cmds.c:2410
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"L'opció 'readonly' està activa per \"%.*s\",\n"
+"Voleu escriure'l de totes maneres?"
+
+# és un títol de diàleg [:browse edit]. eac
+#: ex_cmds.c:2575
+msgid "Edit File"
+msgstr "Edita un fitxer"
+
+#: ex_cmds.c:3147
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Una auto-ordre ha eliminat el buffer nou %s inesperadament"
+
+#: ex_cmds.c:3279
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: Argument no numèric per :z"
+
+#: ex_cmds.c:3364
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: Les ordres shell no estan permeses en rvim"
+
+#: ex_cmds.c:3471
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Les expressions regulars no poden estar delimitades per lletres"
+
+# «amb» o «per» + tecles. eac
+#: ex_cmds.c:3817
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "substituir amb %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4189
+msgid "(Interrupted) "
+msgstr "(Interromput) "
+
+#: ex_cmds.c:4193
+msgid "1 substitution"
+msgstr "1 substitució"
+
+#: ex_cmds.c:4195
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld substitucions"
+
+#: ex_cmds.c:4198
+msgid " on 1 line"
+msgstr " en 1 línia"
+
+#: ex_cmds.c:4200
+#, c-format
+msgid " on %ld lines"
+msgstr " en %ld línies"
+
+#: ex_cmds.c:4251
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: No es pot executar una ordre global de forma recursiva"
+
+#: ex_cmds.c:4286
+msgid "E148: Regular expression missing from global"
+msgstr "E148: Les ordres globals requereixen una expressió regular"
+
+#: ex_cmds.c:4335
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "S'ha trobat el patró a cada línia: %s"
+
+#: ex_cmds.c:4416
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Última cadena substituïda:\n"
+"$"
+
+#: ex_cmds.c:4529
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: No hi ha ajuda per %s"
+
+#: ex_cmds.c:4563
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "El fitxer d'ajuda \"%s\" no s'ha trobat"
+
+#: ex_cmds.c:5039
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: No és un directori: %s"
+
+#: ex_cmds.c:5067
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: No s'ha pogut obrir %s amb permís d'escriptura"
+
+#: ex_cmds.c:5102
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: No s'ha pogut obrir %s amb permís de lectura"
+
+#: ex_cmds.c:5181
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: L'etiqueta \"%s\" està duplicada en el fitxer %s"
+
+#: ex_cmds.c:5288
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Ordre de senyalització desconeguda: %s"
+
+#: ex_cmds.c:5308
+msgid "E156: Missing sign name"
+msgstr "E156: Falta el nom del senyal"
+
+#: ex_cmds.c:5354
+msgid "E612: Too many signs defined"
+msgstr "E612: Hi han massa senyals definits"
+
+#: ex_cmds.c:5421
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: El text del senyal no és vàlid: %s"
+
+#: ex_cmds.c:5452 ex_cmds.c:5638
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: El senyal és desconegut: %s"
+
+#: ex_cmds.c:5498
+msgid "E159: Missing sign number"
+msgstr "E159: Falta el número del senyal"
+
+#: ex_cmds.c:5578
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: El nom del buffer no és vàlid: %s"
+
+#: ex_cmds.c:5617
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: L'ID del senyal no és vàlida: %ld"
+
+#: ex_cmds.c:5788
+msgid "[Deleted]"
+msgstr "[Eliminat]"
+
+#: ex_docmd.c:489
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Mode Ex. Escriviu \"visual\" per tornar al mode Normal."
+
+#. must be at EOF
+#: ex_docmd.c:525
+msgid "E501: At end-of-file"
+msgstr "E501: Final del fitxer"
+
+#: ex_docmd.c:627
+msgid "E169: Command too recursive"
+msgstr "E169: L'ordre és massa recursiva"
+
+#: ex_docmd.c:1094
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: No s'ha interceptat l'excepció: %s"
+
+#: ex_docmd.c:1180
+msgid "End of sourced file"
+msgstr "Final del fitxer executat"
+
+#: ex_docmd.c:1181
+msgid "End of function"
+msgstr "Final de la funció"
+
+#: ex_docmd.c:1633
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: Ús ambigu d'una ordre definida per l'usuari"
+
+#: ex_docmd.c:1647
+msgid "E492: Not an editor command"
+msgstr "E492: No és una ordre d'edició"
+
+#: ex_docmd.c:1737
+msgid "E478: Don't panic!"
+msgstr "E478: Calma!"
+
+#: ex_docmd.c:1756
+msgid "E493: Backwards range given"
+msgstr "E493: Heu especificat un interval decreixent"
+
+# és una pregunta. eac
+#: ex_docmd.c:1765
+msgid "Backwards range given, OK to swap"
+msgstr "Heu especificat un interval decreixent. El voleu invertir"
+
+#: ex_docmd.c:1876
+msgid "E494: Use w or w>>"
+msgstr "E494: Useu w o bé w>>"
+
+#: ex_docmd.c:3463
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Aquesta ordre no està disponible en aquesta versió"
+
+#: ex_docmd.c:3649
+msgid "E172: Only one file name allowed"
+msgstr "E172: Només està permès un nom de fitxer"
+
+#: ex_docmd.c:4211
+msgid "1 more file to edit. Quit anyway?"
+msgstr "Queda 1 fitxer per editar. Voleu sortir de totes maneres?"
+
+#: ex_docmd.c:4214
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "Queden %d fitxers per editar. Voleu sortir de totes maneres?"
+
+#: ex_docmd.c:4221
+msgid "E173: 1 more file to edit"
+msgstr "E173: Queda 1 fitxer per editar"
+
+#: ex_docmd.c:4223
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: Queden %ld fitxers per editar"
+
+#: ex_docmd.c:4318
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: L'ordre ja existeix: afegiu ! per substituir-la"
+
+#: ex_docmd.c:4428
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr "\n Nom Args Abast Completar Definició"
+
+#: ex_docmd.c:4517
+msgid "No user-defined commands found"
+msgstr "No s'han trobat ordres definides per l'usuari"
+
+#: ex_docmd.c:4549
+msgid "E175: No attribute specified"
+msgstr "E175: No heu especificat cap atribut"
+
+#: ex_docmd.c:4601
+msgid "E176: Invalid number of arguments"
+msgstr "E176: El nombre d'arguments no és vàlid"
+
+#: ex_docmd.c:4616
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: El comptador no es pot especificar dos cops"
+
+#: ex_docmd.c:4626
+msgid "E178: Invalid default value for count"
+msgstr "E178: El valor per omissió del comptador no és vàlid"
+
+# «completar» eac
+#: ex_docmd.c:4657
+msgid "E179: argument required for complete"
+msgstr "E179: La funció completar requereix un argument"
+
+# «completar» eac
+#: ex_docmd.c:4689
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: El valor per la funció completar no és vàlid: %s"
+
+# «completar» eac
+#: ex_docmd.c:4694
+msgid "E467: Custom completion requires a function argument"
+msgstr "E467: Els esquemes de completar requereixen una funció com a argument"
+
+# «completar» eac
+#: ex_docmd.c:4699
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr "E468: L'argument de completar només està permès en esquemes personalitzats"
+
+#: ex_docmd.c:4709
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: L'atribut no és vàlid: %s"
+
+#: ex_docmd.c:4752
+msgid "E182: Invalid command name"
+msgstr "E182: El nom de l'ordre no és vàlid"
+
+#: ex_docmd.c:4767
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: Les ordres definides per l'usuari han de començar en majúscula"
+
+#: ex_docmd.c:4837
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: No existeix tal ordre definida per l'usuari: %s"
+
+#: ex_docmd.c:5294
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: No s'ha trobat l'esquema de colors %s"
+
+#: ex_docmd.c:5302
+msgid "Greetings, Vim user!"
+msgstr "Salutacions, usuari de Vim!"
+
+# Títol d'un diàleg [:browse split] eac
+#: ex_docmd.c:6013
+msgid "Edit File in new window"
+msgstr "Edita un fitxer en una finestra nova"
+
+#: ex_docmd.c:6300
+msgid "No swap file"
+msgstr "No hi ha fitxer d'intercanvi"
+
+# És un títol d'un diàleg [:browse read] eac
+#: ex_docmd.c:6404
+msgid "Append File"
+msgstr "Afegeix un fitxer"
+
+#: ex_docmd.c:6468
+msgid "E186: No previous directory"
+msgstr "E186: No hi ha cap directori anterior"
+
+#: ex_docmd.c:6550
+msgid "E187: Unknown"
+msgstr "E187: Desconegut"
+
+#: ex_docmd.c:6635
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: L'ordre :winsize requereix dos arguments numèrics"
+
+#: ex_docmd.c:6686
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Posició de la finestra: X %d, Y %d"
+
+#: ex_docmd.c:6691
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: En aquesta plataforma no es pot obtenir la posició de la finestra"
+
+#: ex_docmd.c:6701
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: L'ordre :winpos requereix dos arguments numèrics"
+
+# És el títol d'un diàleg. eac
+#: ex_docmd.c:6980
+msgid "Save Redirection"
+msgstr "Desa la redirecció"
+
+# És el títol d'un diàleg. eac
+#: ex_docmd.c:7131
+msgid "Save View"
+msgstr "Desa la vista"
+
+# És el títol d'un diàleg. eac
+#: ex_docmd.c:7132
+msgid "Save Session"
+msgstr "Desa la sessió"
+
+# És el títol d'un diàleg. eac
+#: ex_docmd.c:7134
+msgid "Save Setup"
+msgstr "Desa la configuració"
+
+#: ex_docmd.c:7285
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" existeix (afegiu ! per confirmar)"
+
+#: ex_docmd.c:7290
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: No s'ha pogut obrir \"%s\" amb permís d'escriptura"
+
+#. set mark
+#: ex_docmd.c:7314
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: L'argument ha de ser una lletra o bé un accent obert o tancat"
+
+#: ex_docmd.c:7356
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Ús recursiu de :normal massa profund"
+
+#: ex_docmd.c:7869
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: No hi ha cap nom de fitxer alternatiu per substituir '#'"
+
+#: ex_docmd.c:7900
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: No hi ha cap nom de fitxer d'auto-ordres per substituir \"<afile>\""
+
+#: ex_docmd.c:7908
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "E496: No hi ha cap nombre de buffer d'auto-ordres per substituir \"<abuf>\""
+
+#: ex_docmd.c:7919
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr "E497: No hi ha cap nom d'auto-ordre per substituir \"<amatch>\""
+
+#: ex_docmd.c:7929
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr "E498: No hi ha cap script per substituir \"<sfile>\""
+
+#: ex_docmd.c:7970
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: El nom de fitxer per '%' o '#' està buit, només funciona amb \":p:h\""
+
+#: ex_docmd.c:7972
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: S'evalua com a cadena buida"
+
+#: ex_docmd.c:8899
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: No s'ha pogut obrir el fitxer viminfo amb permís de lectura"
+
+#: ex_docmd.c:9072
+msgid "E196: No digraphs in this version"
+msgstr "E196: Aquesta versió no suporta dígrafs"
+
+#: ex_eval.c:423
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr "E608: No es poden generar exepcions amb el prefix 'Vim'"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:509
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "Excepció generada: %s"
+
+#: ex_eval.c:556
+#, c-format
+msgid "Exception finished: %s"
+msgstr "Exepció finalitzada: %s"
+
+#: ex_eval.c:557
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "Exepció descartada: %s"
+
+#: ex_eval.c:600 ex_eval.c:644
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, línia %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:618
+#, c-format
+msgid "Exception caught: %s"
+msgstr "Excepció interceptada: %s"
+
+#: ex_eval.c:693
+#, c-format
+msgid "%s made pending"
+msgstr "%s està pendent"
+
+#: ex_eval.c:696
+#, c-format
+msgid "%s resumed"
+msgstr "%s s'ha continuat"
+
+#: ex_eval.c:700
+#, c-format
+msgid "%s discarded"
+msgstr "%s s'ha descartat"
+
+#: ex_eval.c:726
+msgid "Exception"
+msgstr "Exepció"
+
+#: ex_eval.c:732
+msgid "Error and interrupt"
+msgstr "Error i interrupció"
+
+#: ex_eval.c:734 gui.c:4253
+msgid "Error"
+msgstr "Error"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:736
+msgid "Interrupt"
+msgstr "Interrupció"
+
+#: ex_eval.c:810
+msgid "E579: :if nesting too deep"
+msgstr "E579: Imbricació de :if massa profunda"
+
+#: ex_eval.c:847
+msgid "E580: :endif without :if"
+msgstr "E580: Declaració :endif sense :if"
+
+#: ex_eval.c:891
+msgid "E581: :else without :if"
+msgstr "E581: Declaració :else sense :if"
+
+#: ex_eval.c:894
+msgid "E582: :elseif without :if"
+msgstr "E582: Declaració :elseif sense :if"
+
+#: ex_eval.c:901
+msgid "E583: multiple :else"
+msgstr "E583: Múltiples :else"
+
+#: ex_eval.c:904
+msgid "E584: :elseif after :else"
+msgstr "E584: Declaració :elseif després de :else"
+
+#: ex_eval.c:971
+msgid "E585: :while nesting too deep"
+msgstr "E585: Imbricació de :while massa profunda"
+
+#: ex_eval.c:1027
+msgid "E586: :continue without :while"
+msgstr "E586: Declaració :continue sense :while"
+
+#: ex_eval.c:1067
+msgid "E587: :break without :while"
+msgstr "E587: Declaració :break sense :while"
+
+#: ex_eval.c:1266
+msgid "E601: :try nesting too deep"
+msgstr "E601: Imbricació de :try massa profunda"
+
+#: ex_eval.c:1346
+msgid "E603: :catch without :try"
+msgstr "E603: Declaració :catch sense :try"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1368
+msgid "E604: :catch after :finally"
+msgstr "E604: Declaració :catch després de :finally"
+
+#: ex_eval.c:1501
+msgid "E606: :finally without :try"
+msgstr "E606: Declaració :finally sense :try"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1525
+msgid "E607: multiple :finally"
+msgstr "E607: Múltiples :finally"
+
+#: ex_eval.c:1634
+msgid "E602: :endtry without :try"
+msgstr "E602: Declaració :endtry sense :try"
+
+#: ex_eval.c:1966
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: Declaració :endfunction fora d'una funció"
+
+# context? eac
+#: ex_getln.c:3153
+msgid "tagname"
+msgstr "nom de l'etiqueta"
+
+# context? eac
+#: ex_getln.c:3156
+msgid " kind file\n"
+msgstr " tipus de fitxer\n"
+
+#: ex_getln.c:4507
+msgid "'history' option is zero"
+msgstr "l'opció 'history' és zero"
+
+#: ex_getln.c:4747
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr "\n# Historial %s (de més a menys recent):\n"
+
+#: ex_getln.c:4748
+msgid "Command Line"
+msgstr "d'ordres"
+
+#: ex_getln.c:4749
+msgid "Search String"
+msgstr "de cadenes cercades"
+
+#: ex_getln.c:4750
+msgid "Expression"
+msgstr "d'expressions"
+
+#: ex_getln.c:4751
+msgid "Input Line"
+msgstr "de línies d'entrada"
+
+#: ex_getln.c:4781
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar fora de l'àrea de l'ordre"
+
+#: ex_getln.c:4958
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: S'ha eliminat la finestra o el buffer actiu"
+
+#: fileio.c:373
+msgid "Illegal file name"
+msgstr "El nom de fitxer és il·legal"
+
+#: fileio.c:397 fileio.c:522 fileio.c:2690 fileio.c:2731
+msgid "is a directory"
+msgstr "és un directori"
+
+#: fileio.c:399
+msgid "is not a file"
+msgstr "no és un fitxer"
+
+#: fileio.c:544 fileio.c:3840
+msgid "[New File]"
+msgstr "[Fitxer nou]"
+
+#: fileio.c:566
+msgid "[Permission Denied]"
+msgstr "[Permís denegat]"
+
+#: fileio.c:670
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: Auto-ordres *ReadPre han deixat el fitxer illegible"
+
+#: fileio.c:672
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: Les auto-ordres *ReadPre no poden canviar el buffer actual"
+
+#: fileio.c:693
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: Llegint l'entrada estàndard...\n"
+
+#: fileio.c:699
+msgid "Reading from stdin..."
+msgstr "Llegint l'entrada estàndard..."
+
+#. Re-opening the original file failed!
+#: fileio.c:944
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: La conversió ha deixat el fitxer illegible!"
+
+#: fileio.c:1896
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:1903
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:1910
+msgid "[socket]"
+msgstr "[socket]"
+
+# eac només-lectura (nl)
+#: fileio.c:1918
+msgid "[RO]"
+msgstr "[NL]"
+
+#: fileio.c:1928
+msgid "[CR missing]"
+msgstr "[falten caràcters CR]"
+
+# entra en conflicte amb NL (només lectura)
+#: fileio.c:1933
+msgid "[NL found]"
+msgstr "[s'han trobat caràcters NL]"
+
+#: fileio.c:1938
+msgid "[long lines split]"
+msgstr "[línies llargues partides]"
+
+#: fileio.c:1944 fileio.c:3824
+msgid "[NOT converted]"
+msgstr "[NO convertit]"
+
+#: fileio.c:1949 fileio.c:3829
+msgid "[converted]"
+msgstr "[convertit]"
+
+#: fileio.c:1956 fileio.c:3854
+msgid "[crypted]"
+msgstr "[xifrat]"
+
+#: fileio.c:1963
+msgid "[CONVERSION ERROR]"
+msgstr "[ERROR DE CONVERSIÓ]"
+
+#: fileio.c:1969
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[OCTET IL·LEGAL a la línia %ld]"
+
+#: fileio.c:1976
+msgid "[READ ERRORS]"
+msgstr "[ERRORS DE LECTURA]"
+
+#: fileio.c:2192
+msgid "Can't find temp file for conversion"
+msgstr "No s'ha trobat el fitxer temporal per la conversió"
+
+#: fileio.c:2199
+msgid "Conversion with 'charconvert' failed"
+msgstr "La conversió amb 'charconvert' ha fallat"
+
+#: fileio.c:2202
+msgid "can't read output of 'charconvert'"
+msgstr "No s'ha pogut llegir la sortida de 'charconvert'"
+
+#: fileio.c:2605
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Auto-ordres han eliminat o alliberat el buffer a escriure"
+
+#: fileio.c:2628
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Una auto-ordre ha canviat el nombre de línies de forma inesperada"
+
+#: fileio.c:2696 fileio.c:2714
+msgid "is not a file or writable device"
+msgstr "no és un fitxer o dispositiu que es pugui escriure"
+
+#: fileio.c:2766
+msgid "is read-only (add ! to override)"
+msgstr "és un fitxer de només lectura (afegiu ! per confirmar)"
+
+#: fileio.c:3072
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: No s'ha pogut escriure la còpia de seguretat (afegiu ! per confirmar)"
+
+#: fileio.c:3084
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr "E507: Error en tancar el fitxer còpia de seguretat (afegiu ! per confirmar)"
+
+#: fileio.c:3086
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr "E508: Error de lectura en fer la còpia de seguretat (afegiu ! per confirmar)"
+
+#: fileio.c:3102
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: No s'ha pogut crear la còpia de seguretat (afegiu ! per confirmar)"
+
+#: fileio.c:3205
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: No s'ha pogut fer la còpia de seguretat (afegiu ! per confirmar)"
+
+# «resource fork» (MacOS) ?
+#: fileio.c:3267
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr "E460: La bifurcació de recursos es perdrà (afegiu ! per confirmar)"
+
+#: fileio.c:3368
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: No s'ha trobat el fitxer temporal per escriure-hi"
+
+#: fileio.c:3386
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr "E213: No s'ha pogut convertir (afegiu ! per desar sense conversió)"
+
+#: fileio.c:3421
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: No s'ha pogut obrir el fitxer enllaçat per escriure-hi"
+
+#: fileio.c:3425
+msgid "E212: Can't open file for writing"
+msgstr "E212: No s'ha pogut obrir el fitxer amb permís d'escriptura"
+
+#: fileio.c:3675
+msgid "E512: Close failed"
+msgstr "E512: Error en tancar"
+
+#: fileio.c:3746
+msgid "E513: write error, conversion failed"
+msgstr "E512: Error d'escriptura, ha fallat la conversió"
+
+#: fileio.c:3752
+msgid "E514: write error (file system full?)"
+msgstr "E514: Error d'escriptura (sistema de fitxers ple?)"
+
+#: fileio.c:3819
+msgid " CONVERSION ERROR"
+msgstr " ERROR DE CONVERSIÓ"
+
+#: fileio.c:3835
+msgid "[Device]"
+msgstr "[Dispositiu]"
+
+#: fileio.c:3840
+msgid "[New]"
+msgstr "[Nou]"
+
+#: fileio.c:3862
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:3862
+msgid " appended"
+msgstr " afegits"
+
+#: fileio.c:3864
+msgid " [w]"
+msgstr " [e]"
+
+#: fileio.c:3864
+msgid " written"
+msgstr " escrits"
+
+#: fileio.c:3917
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: patchmode: no s'ha pogut desar el fitxer original"
+
+#: fileio.c:3939
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: no s'ha pogut tocar el fitxer original buit"
+
+#: fileio.c:3954
+msgid "E207: Can't delete backup file"
+msgstr "E207: No s'ha pogut eliminar la còpia de seguretat"
+
+#: fileio.c:4018
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr "\nATENCIÓ: El fitxer original es pot haver fet malbé\n"
+
+#: fileio.c:4020
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "no sortiu de l'editor fins que s'hagi desat el fitxer amb èxit!"
+
+#: fileio.c:4109
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:4109
+msgid "[dos format]"
+msgstr "[format dos]"
+
+#: fileio.c:4116
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:4116
+msgid "[mac format]"
+msgstr "[format mac]"
+
+#: fileio.c:4123
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:4123
+msgid "[unix format]"
+msgstr "[format unix]"
+
+#: fileio.c:4150
+msgid "1 line, "
+msgstr "1 línia, "
+
+#: fileio.c:4152
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld línies, "
+
+#: fileio.c:4155
+msgid "1 character"
+msgstr "1 caràcter"
+
+#: fileio.c:4157
+#, c-format
+msgid "%ld characters"
+msgstr "%ld caràcters"
+
+# «no final de línia» eac
+#: fileio.c:4167
+msgid "[noeol]"
+msgstr "[nofl]"
+
+#: fileio.c:4167
+msgid "[Incomplete last line]"
+msgstr "[Última línia incompleta]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4186
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "ATENCIÓ: El fitxer ha canviat des de que s'ha llegit!!!"
+
+# pregunta ask_yesno() eac
+#: fileio.c:4188
+msgid "Do you really want to write to it"
+msgstr "Esteu segurs que voleu escriure'l"
+
+#: fileio.c:5229
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Error en escriure \"%s\""
+
+#: fileio.c:5236
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Error en tancar \"%s\""
+
+#: fileio.c:5239
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Error en llegir \"%s\""
+
+#: fileio.c:5459
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: L'auto-ordre FileChangedShell ha eliminat el buffer"
+
+#: fileio.c:5467
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: Atenció: El fitxer \"%s\" ha deixat d'estar disponible"
+
+#: fileio.c:5480
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr "W12: Atenció: Tant el fitxer \"%s\" com el buffer del Vim han canviat"
+
+# massa llarg? eac
+#: fileio.c:5483
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: Atenció: El fitxer \"%s\" ha canviat des de que s'ha començat a editar"
+
+# massa llarg? eac
+#: fileio.c:5485
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: Atenció: Els permisos de \"%s\" han canviat des que s'ha començat a editar"
+
+# massa llarg? eac
+#: fileio.c:5495
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: Atenció: El fitxer \"%s\" ha estat creat després que s'ha començat a editar"
+
+#: fileio.c:5512
+msgid "Warning"
+msgstr "Atenció"
+
+#: fileio.c:5513
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&D'acord\n"
+"&Carrega el fitxer"
+
+#: fileio.c:5611
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: No s'han pogut fer les preparacions per rellegir \"%s\""
+
+#: fileio.c:5630
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: No s'ha pogut rellegir \"%s\""
+
+#: fileio.c:6212
+msgid "--Deleted--"
+msgstr "--Eliminat--"
+
+#. the group doesn't exist
+#: fileio.c:6372
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: No existeix tal grup: \"%s\""
+
+#: fileio.c:6497
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Caràcter il·legal després de *: %s"
+
+#: fileio.c:6508
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: No existeix tal esdeveniment: %s"
+
+#. Highlight title
+#: fileio.c:6657
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr "\n--- Auto-ordres ---"
+
+#: fileio.c:6928
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: No es poden executar auto-ordres per TOTS els esdeveniments"
+
+#: fileio.c:6951
+msgid "No matching autocommands"
+msgstr "No coincideix cap auto-ordre"
+
+#: fileio.c:7271
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: Imbricació d'auto-ordres massa profunda"
+
+#: fileio.c:7539
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "auto-ordres %s per \"%s\""
+
+#: fileio.c:7547
+#, c-format
+msgid "Executing %s"
+msgstr "Executant %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7615
+#, c-format
+msgid "autocommand %s"
+msgstr "auto-ordre %s"
+
+#: fileio.c:8182
+msgid "E219: Missing {."
+msgstr "E219: Falta un {."
+
+#: fileio.c:8184
+msgid "E220: Missing }."
+msgstr "E220: Falta un }."
+
+#: fold.c:66
+msgid "E490: No fold found"
+msgstr "E490: No s'ha trobat cap plec"
+
+#: fold.c:553
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: No es pot crear cap plec amb el 'foldmethod' actual"
+
+#: fold.c:555
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: No pot eliminar el plec amb el 'foldmethod' actual"
+
+#: getchar.c:246
+msgid "E222: Add to read buffer"
+msgstr "E222: No es pot modificar un buffer de lectura"
+
+#: getchar.c:2156
+msgid "E223: recursive mapping"
+msgstr "E223: assignació recursiva"
+
+#: getchar.c:3022
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: ja existeix una abreviació global per %s"
+
+#: getchar.c:3025
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: ja existeix una assignació global per %s"
+
+#: getchar.c:3152
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: ja existeix una abreviació per %s"
+
+#: getchar.c:3155
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: ja existeix una assignació per %s"
+
+#: getchar.c:3219
+msgid "No abbreviation found"
+msgstr "No s'ha trobat cap abreviació"
+
+#: getchar.c:3221
+msgid "No mapping found"
+msgstr "No s'ha trobat cap assignació"
+
+#: getchar.c:4111
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: Mode il·legal"
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<no es pot obrir> "
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: no s'ha pogut obtenir la font %s"
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: no s'ha pogut tornar al directori actual"
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "Ubicació:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: no s'ha pogut obtenir el directori actual"
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "D'acord"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2634 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "Cancel·la"
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "Diàleg del Vim"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Barra de desplaçament: No s'ha pogut obtenir la mida del mapa de bits."
+
+#: gui_beval.c:98
+#~ msgid "E232: Cannot create BalloonEval with both message and callback"
+#~ msgstr ""
+
+#: gui.c:219
+msgid "E229: Cannot start the GUI"
+msgstr "E229: No s'ha pogut iniciar l'interfície gràfica"
+
+#: gui.c:348
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: No s'ha pogut llegir \"%s\""
+
+#: gui.c:473
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: El valor de 'guifontwide' no és vàlid"
+
+#: gui.c:3939
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: No s'ha pogut assignar memòria pel color %s"
+
+#: gui_gtk.c:1563
+msgid "Vim dialog..."
+msgstr "Diàleg del Vim..."
+
+#: gui_gtk.c:1998 message.c:2766
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Sí\n"
+"&No\n"
+"&Cancel·la"
+
+#: gui_gtk.c:2161
+msgid "Input _Methods"
+msgstr "_Mètodes d'entrada"
+
+#: gui_gtk.c:2427 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Cerca i substitueix..."
+
+#: gui_gtk.c:2435 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "VIM - Cerca..."
+
+#: gui_gtk.c:2467 gui_motif.c:2888
+msgid "Find what:"
+msgstr "Cerca:"
+
+#: gui_gtk.c:2487 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "Substituieix amb:"
+
+#. whole word only button
+#: gui_gtk.c:2519 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "Només paraules senceres"
+
+#. match case button
+#: gui_gtk.c:2532 gui_motif.c:3048
+msgid "Match case"
+msgstr "Sensible a les majúscules"
+
+#: gui_gtk.c:2544 gui_motif.c:2990
+msgid "Direction"
+msgstr "Direcció"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2556 gui_motif.c:3002
+msgid "Up"
+msgstr "Amunt"
+
+#: gui_gtk.c:2560 gui_motif.c:3010
+msgid "Down"
+msgstr "Avall"
+
+#: gui_gtk.c:2586 gui_gtk.c:2588 gui_motif.c:2792
+msgid "Find Next"
+msgstr "Cerca el següent"
+
+#: gui_gtk.c:2605 gui_gtk.c:2607 gui_motif.c:2809
+msgid "Replace"
+msgstr "Substitueix"
+
+#: gui_gtk.c:2618 gui_gtk.c:2620 gui_motif.c:2822
+msgid "Replace All"
+msgstr "Substitueix-les totes"
+
+#: gui_gtk_x11.c:2285
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: S'ha rebut una petició \"die\" del gestor de sessions\n"
+
+#: gui_gtk_x11.c:3474
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: La finestra principal ha estat destruïda inesperadament\n"
+
+#: gui_gtk_x11.c:4088
+msgid "Font Selection"
+msgstr "Selecció de tipus de lletra"
+
+#: gui_gtk_x11.c:5944 ui.c:2009
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "S'ha usat CUT_BUFFER0 en lloc d'una selecció buida"
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "Filtre"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "Directoris"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "Ajuda"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "Fitxers"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "Selecció"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "Desfés"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: No s'ha pogut carregar el tipus Zap '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: No es pot utilitzar el tipus %s"
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr "\nEnviant un missatge per finalitzar el procés fill.\n"
+
+#: gui_w32.c:760
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Argument no suportat: \"-%s\"; Useu la versió OLE."
+
+#: gui_w48.c:2048
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Cerca una cadena (useu '\\\\' per cercar '\\')"
+
+#: gui_w48.c:2073
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Cerca i substitueix (useu '\\\\' per cercar '\\')"
+
+#: gui_x11.c:1479
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr "Vim E458: No s'ha pogut assignar memòria per colors, poden ser incorrectes"
+
+#: gui_x11.c:2060
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: En el conjunt %s falten tipus pels següents jocs de caràcters:"
+
+#: gui_x11.c:2103
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Nom del conjunt de tipus: %s"
+
+#: gui_x11.c:2104
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "El tipus '%s' no és d'amplada fixa"
+
+#: gui_x11.c:2123
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Nom del conjunt de tipus: %s\n"
+
+#: gui_x11.c:2124
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Tipus0: %s\n"
+
+#: gui_x11.c:2125
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Tipus1: %s\n"
+
+#: gui_x11.c:2126
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "L'amplada del tipus%d no és el doble que la del tipus0\n"
+
+#: gui_x11.c:2127
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "Amplada del tipus0: %ld\n"
+
+#: gui_x11.c:2128
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr "Amplada del tipus1: %ld\n\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: ERROR de l'autòmata hangul"
+
+#: if_cscope.c:77
+msgid "Add a new database"
+msgstr "Afegeix una base de dades nova"
+
+#: if_cscope.c:79
+msgid "Query for a pattern"
+msgstr "Consulta un patró"
+
+#: if_cscope.c:81
+msgid "Show this message"
+msgstr "Mostra aquest missatge"
+
+#: if_cscope.c:83
+msgid "Kill a connection"
+msgstr "Talla una connexió"
+
+#: if_cscope.c:85
+msgid "Reinit all connections"
+msgstr "Reinicia totes les connexions"
+
+#: if_cscope.c:87
+msgid "Show connections"
+msgstr "Mostra les connexions"
+
+#: if_cscope.c:95
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: Forma d'ús: cs[cope] %s"
+
+#: if_cscope.c:124
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Aquesta ordre de cscope no suporta divisió de finestres.\n"
+
+#: if_cscope.c:170
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: Forma d'ús: cstag <despl>"
+
+#: if_cscope.c:226
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: No s'ha trobat l'etiqueta"
+
+#: if_cscope.c:404
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: Error de stat(%s): %d"
+
+#: if_cscope.c:414
+msgid "E563: stat error"
+msgstr "E563: Error de stat()"
+
+#: if_cscope.c:511
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s no és un directori o una base de dades de cscope vàlida"
+
+#: if_cscope.c:526
+#, c-format
+msgid "Added cscope database %s"
+msgstr "S'ha afegit la base de dades cscope %s"
+
+#: if_cscope.c:581
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: Error en llegir la connexió cscope %ld"
+
+#: if_cscope.c:686
+msgid "E561: unknown cscope search type"
+msgstr "E561: Tipus de cerca cscope desconeguda"
+
+#: if_cscope.c:728
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: No s'han pogut crear canonades cscope"
+
+#: if_cscope.c:745
+msgid "E622: Could not fork for cscope"
+msgstr "E622: No s'ha pogut bifurcar el procés cscope"
+
+#: if_cscope.c:839 if_cscope.c:889
+msgid "cs_create_connection exec failed"
+msgstr "l'execució de cs_create_connection ha fallat"
+
+#: if_cscope.c:890
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: No s'ha pogut generar un procés per cscope"
+
+#: if_cscope.c:903
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen per to_fp ha fallat"
+
+#: if_cscope.c:905
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen per fr_fp ha fallat"
+
+#: if_cscope.c:943
+msgid "E567: no cscope connections"
+msgstr "E567: No hi han connexions cscope"
+
+#: if_cscope.c:1017
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: Cap resultat per la consulta cscope %s de %s"
+
+#: if_cscope.c:1074
+#, c-format
+msgid "E469: invalid cscopequickfix flag %c for %c"
+msgstr "E469: El senyal cscopequickfix %c no és vàlid per %c"
+
+#: if_cscope.c:1131
+msgid "cscope commands:\n"
+msgstr "ordres de cscope:\n"
+
+#: if_cscope.c:1134
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (Forma d'ús: %s)"
+
+#: if_cscope.c:1232
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: No s'ha pogut obrir la base de dades cscope: %s"
+
+#: if_cscope.c:1250
+msgid "E626: cannot get cscope database information"
+msgstr "E626: No s'ha pogut obtenir l'informació de la base de dades cscope"
+
+#: if_cscope.c:1275
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: No s'ha afegit una base de dades cscope duplicada"
+
+#: if_cscope.c:1286
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: S'ha assolit el màxim nombre de connexions cscope"
+
+#: if_cscope.c:1402
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: No s'ha trobat la connexió cscope %s"
+
+#: if_cscope.c:1436
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "s'ha tancat la connexió cscope %s"
+
+#. should not reach here
+#: if_cscope.c:1576
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: Error fatal a cs_manage_matches"
+
+#: if_cscope.c:1836
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "Etiqueta cscope: %s"
+
+#: if_cscope.c:1840
+msgid ""
+"\n"
+" # line"
+msgstr "\n # línia"
+
+#: if_cscope.c:1842
+msgid "filename / context / line\n"
+msgstr "fitxer / context / línia\n"
+
+#: if_cscope.c:1993
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: Error de cscope: %s"
+
+#: if_cscope.c:2155
+msgid "All cscope databases reset"
+msgstr "S'han reiniciat totes les bases de dades cscope"
+
+#: if_cscope.c:2223
+msgid "no cscope connections\n"
+msgstr "no hi ha connexions cscope\n"
+
+#: if_cscope.c:2227
+msgid " # pid database name prepend path\n"
+msgstr " # pid base de dades prefix d'ubicació\n"
+
+#: if_python.c:394
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr "E263: Aquesta ordre està deshabilitada, no s'ha pogut carregar Python."
+
+#: if_python.c:596
+msgid "can't delete OutputObject attributes"
+msgstr "no s'han pogut eliminar els atributs de l'OutputObject"
+
+#: if_python.c:603
+msgid "softspace must be an integer"
+msgstr "'softspace' ha de ser un nombre enter"
+
+#: if_python.c:611
+msgid "invalid attribute"
+msgstr "l'atribut no és vàlid"
+
+#: if_python.c:650 if_python.c:664
+msgid "writelines() requires list of strings"
+msgstr "la funció writelines() requereix una llista de cadenes"
+
+#: if_python.c:790
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: Error en inicialitzar els objectes d'E/S"
+
+#: if_python.c:975 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "l'expressió no és vàlida"
+
+#: if_python.c:989 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "no s'ha compilat suport per expressions"
+
+#: if_python.c:1002
+msgid "attempt to refer to deleted buffer"
+msgstr "intent de referència a un buffer eliminat"
+
+#: if_python.c:1017 if_python.c:1058 if_python.c:1122 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "nombre de línia fora d'abast"
+
+#: if_python.c:1257
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<objecte buffer (eliminat) a %8lX>"
+
+#: if_python.c:1348 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "nom de marca no vàlid"
+
+#: if_python.c:1623
+msgid "no such buffer"
+msgstr "no existeix tal buffer"
+
+#: if_python.c:1711
+msgid "attempt to refer to deleted window"
+msgstr "intent de referir-se a una finestra eliminada"
+
+#: if_python.c:1756
+msgid "readonly attribute"
+msgstr "atribut de només lectura"
+
+#: if_python.c:1769
+msgid "cursor position outside buffer"
+msgstr "posició del cursor fora del buffer"
+
+#: if_python.c:1846
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<objecte finestra (eliminat) a %.8lX>"
+
+#: if_python.c:1858
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<objecte finestra (desconegut) a %.8lX>"
+
+#: if_python.c:1860
+#, c-format
+msgid "<window %d>"
+msgstr "<finestra %d>"
+
+#: if_python.c:1936
+msgid "no such window"
+msgstr "no existeix tal finestra"
+
+#: if_python.c:2193 if_python.c:2228 if_python.c:2278 if_python.c:2346
+#: if_python.c:2466 if_python.c:2518 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1998
+msgid "cannot save undo information"
+msgstr "no s'ha pogut desar l'informació de desfer"
+
+#: if_python.c:2195 if_python.c:2285 if_python.c:2357
+msgid "cannot delete line"
+msgstr "no s'ha pogut esborrar la línia"
+
+#: if_python.c:2230 if_python.c:2373 if_tcl.c:690 if_tcl.c:2020
+msgid "cannot replace line"
+msgstr "no s'ha pogut substituir la línia"
+
+#: if_python.c:2389 if_python.c:2468 if_python.c:2526
+msgid "cannot insert line"
+msgstr "no s'ha pogut inserir la línia"
+
+#: if_python.c:2630
+msgid "string cannot contain newlines"
+msgstr "la cadena no pot contenir salts de línia"
+
+#: if_ruby.c:396
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr "E266: Ordre deshabilitada, no s'ha pogut carregar la biblioteca Ruby."
+
+#: if_ruby.c:459
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: estat de longjmp desconegut %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Commuta implementació/definició"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Mostra la classe base de"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Mostra el membre de la funció invalidat"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Obtenir d'un fitxer"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Obtenir d'un projecte"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Obtenir de tots els projectes"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Obtenir"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Mostra el codi font de"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Cerca un símbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Explora les classes"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Mostra la jerarquia de classes"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Mostra la jerarquia de classes restringida"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref es refereix a"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref referenciada per"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref té un"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref usada per"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Mostra docu de"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Genera docu per"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr "No s'ha pogut connectar amb SNiFF+. Reviseu l'entorn (sniffemacs ha d'estar en el $PATH).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Error de lectura. Desconnectat"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "no "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "està connectat"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Petició SNiFF+ desconeguda: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Error en connectar a SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ no connectat"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: No és un buffer SNiFF+"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: Error d'escriptura. Desconnectat"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "nombre de buffer no vàlid"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "no implementat (encara)"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "opció desconeguda"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "no s'ha pogut establir el nombre de línies"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "marca no establerta"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "fila %d columna %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "no s'ha pogut inserir/afegir la línia"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "senyal desconegut: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "vimOption desconeguda"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "interrupció de teclat"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "error de vim"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "no s'ha pogut crear l'ordre de buffer/finestra: l'objecte està siguent eliminat"
+
+#: if_tcl.c:1545
+#~ msgid ""
+#~ "cannot register callback command: buffer/window is already being deleted"
+#~ msgstr ""
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr "E280: ERROR FATAL DE TCL: llista de referències corrupta!? Comuniqueu-ho a vim-dev@vim.org."
+
+#: if_tcl.c:1563
+#~ msgid "cannot register callback command: buffer/window reference not found"
+#~ msgstr ""
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr "E571: Aquesta ordre està deshabilitada: No s'ha pogut carregar la llibreria Tcl."
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr "E281: ERROR DE TCL: el codi de retorn no és un enter!? Comuniqueu-ho a vim-dev@vim.org."
+
+#: if_tcl.c:2006
+msgid "cannot get line"
+msgstr "no s'ha pogut obtenir la línia"
+
+#: if_xcmdsrv.c:215
+msgid "Unable to register a command server name"
+msgstr "No s'ha pogut registrar un nom de servidor d'ordres"
+
+#: if_xcmdsrv.c:465
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: No s'ha pogut enviar l'ordre al programa destinatari"
+
+#: if_xcmdsrv.c:735
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: S'ha usat una ID de servidor no vàlida: %s"
+
+#: if_xcmdsrv.c:1098
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: El registre de l'instància de VIM està mal format. S'ha esborrat!"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "L'opció és desconeguda"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "Massa arguments d'edició"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "Falta un argument després de"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "Porqueria després de l'opció"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr "Massa arguments \"+ordre\", \"-c ordre\" o \"--cmd ordre\""
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "Argument no vàlid per"
+
+#: main.c:469
+msgid "This Vim was not compiled with the diff feature."
+msgstr "Aquest Vim no ha estat compilat amb suport per diff."
+
+#: main.c:928
+msgid "Attempt to open script file again: \""
+msgstr "Reintent d'obrir l'script: \""
+
+#: main.c:932 main.c:939 main.c:983 memline.c:3682 memline.c:3686
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:937
+msgid "Cannot open for reading: \""
+msgstr "No s'ha pogut obrir amb permís de lectura: \""
+
+#: main.c:981
+msgid "Cannot open for script output: \""
+msgstr "No s'ha pogut obrir per desar-hi l'exida de l'script: \""
+
+#: main.c:1115
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d fitxers per editar\n"
+
+#: main.c:1205
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Atenció: La sortida no està connectada a un terminal\n"
+
+#: main.c:1207
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Atenció: L'entrada no està connectada a un terminal\n"
+
+#. just in case..
+#: main.c:1269
+msgid "pre-vimrc command line"
+msgstr "línia d'ordres pre-vimrc"
+
+#: main.c:1304
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: No s'ha pogut llegir \"%s\""
+
+#: main.c:2346
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr "\nMés informació amb: \"vim -h\"\n"
+
+#: main.c:2379
+msgid "[file ..] edit specified file(s)"
+msgstr "[fitxer ...] edita el(s) fitxer(s) especificat(s)"
+
+#: main.c:2380
+msgid "- read text from stdin"
+msgstr "- edita el text de l'entrada estàndard"
+
+#: main.c:2381
+msgid "-t tag edit file where tag is defined"
+msgstr "-t etiqueta edita el fitxer on hi ha l'etiqueta"
+
+#: main.c:2383
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [ftxerrors] edita el fitxer on hi ha el primer error"
+
+#: main.c:2392
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr "\n\n ús:"
+
+#: main.c:2395
+msgid " vim [arguments] "
+msgstr " vim [arguments] "
+
+#: main.c:2399
+msgid ""
+"\n"
+" or:"
+msgstr "\no bé:"
+
+#: main.c:2402
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr "\n\nArguments:\n"
+
+#: main.c:2403
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tDesprés d'això només noms de fitxers"
+
+#: main.c:2405
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tNo expandeix patrons de noms"
+
+#: main.c:2408
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tRegistra aquest gvim per OLE"
+
+#: main.c:2409
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tDesregistra aquest gvim per OLE"
+
+#: main.c:2412
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tUsa una interfície gràfica (com \"gvim\")"
+
+#: main.c:2413
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f o --nofork\tNo crea un procés nou per la GUI"
+
+#: main.c:2415
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tMode Vi (com \"vi\")"
+
+#: main.c:2416
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tMode Ex (com \"ex\")"
+
+#: main.c:2417
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tMode silenciós (només per \"ex\")"
+
+#: main.c:2419
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tMode diff (com \"vimdiff\")"
+
+#: main.c:2421
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tMode senzill (com \"evim\", sense modes)"
+
+#: main.c:2422
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tMode només lectura (com \"view\")"
+
+#: main.c:2423
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tMode restringit (com \"rvim)"
+
+#: main.c:2424
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tNo permet modificar (escriure) fitxers"
+
+#: main.c:2425
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tNo permet modificar el text"
+
+#: main.c:2426
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tMode binari"
+
+#: main.c:2428
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tMode Lisp"
+
+#: main.c:2430
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tCompatible amb Vi"
+
+#: main.c:2431
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tNo del tot compatible amb Vi"
+
+#: main.c:2432
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tNivell de loquacitat"
+
+#: main.c:2433
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tMode de depuració"
+
+#: main.c:2434
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tNo usa fitxers d'intercanvi, només memòria"
+
+#: main.c:2435
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tLlista els fitxers d'intercanvi i surt"
+
+#: main.c:2436
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (amb nom de fitxer) Recupera una sessió accidentada"
+
+#: main.c:2437
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tIgual que -r"
+
+#: main.c:2439
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tNo obre una finestra nova amb newcli"
+
+#: main.c:2440
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <dispositiu>\t\tUsa <dispositiu> per l'E/S"
+
+#: main.c:2443
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\t\tComença en mode àrab"
+
+#: main.c:2446
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\tComença en mode hebreu"
+
+#: main.c:2449
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\t Comença en mode farsi"
+
+#: main.c:2451
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\tDefineix el tipus de terminal"
+
+#: main.c:2452
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tUsa <vimrc> en lloc de qualsevol altre .vimrc"
+
+#: main.c:2454
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tUsa <gvimrc> en lloc de qualsevol altre .gvimrc"
+
+#: main.c:2456
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tNo carrega cap plugin"
+
+#: main.c:2457
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tObre N finestres (per omissió: una per fitxer)"
+
+#: main.c:2458
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\tCom -o però amb divisions verticals"
+
+#: main.c:2459
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tComença al final del fitxer"
+
+#: main.c:2460
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnúm>\t\tComença a la línia <lnúm>"
+
+#: main.c:2462
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <ordre>\tExecuta <ordre> abans de llegir els fitxers vimrc"
+
+#: main.c:2464
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <ordre>\t\tExecuta <ordre> després de carregar el primer fitxer"
+
+#: main.c:2465
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <fitxer>\t\tEvalua <fitxer> un cop carregat el primer fitxer"
+
+#: main.c:2466
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <script>\t\tLlegeix ordres del mode Normal del fitxer <script>"
+
+#: main.c:2467
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <script>\t\tAfegeix totes les ordres executades al fitxer <script>"
+
+#: main.c:2468
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <script>\t\tEscriu totes les ordres executades al fitxer <script>"
+
+#: main.c:2470
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tEdita fitxers amb xifrat"
+
+#: main.c:2474
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <pantalla>\tConnecta el Vim a un servidor X particular"
+
+#: main.c:2476
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tNo es connecta a cap servidor X"
+
+#: main.c:2479
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <fitxers>\tEdita <fitxers> en un servidor Vim, si és possible"
+
+#: main.c:2480
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-silent <fitxers> Igual, no es queixa si no hi ha servidor"
+
+#: main.c:2481
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <fitxers> Com --remote, però espera que s'editin els fitxers"
+
+#: main.c:2482
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-wait-silent <fitxers> Igual, no es queixa si no hi ha servidor"
+
+#: main.c:2483
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <tecles> Envia <tecles> a un servidor Vim i surt"
+
+#: main.c:2484
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <expr>\tEvaula <expr> en un servidor Vim i mostra el resultat"
+
+#: main.c:2485
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tLlista els noms dels servidors Vim accessibles"
+
+#: main.c:2486
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <nom>\tEnvia a o es converteix en servidor Vim <nom>"
+
+#: main.c:2489
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tUsa <viminfo> en lloc de .viminfo"
+
+#: main.c:2491
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h o --help\tMostra aquesta ajuda i surt"
+
+#: main.c:2492
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\tMostra informació sobre la versió i surt"
+
+#: main.c:2496
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr "\nArguments reconeguts pel gvim (versió Motif):\n"
+
+#: main.c:2500
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr "\nArguments reconeguts pel gvim (versió neXtaw>:\n"
+
+#: main.c:2502
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr "\nArguments reconeguts pel gvim (versió Athena):\n"
+
+#: main.c:2506
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <pantalla>\tExecuta vim a <pantalla>"
+
+#: main.c:2507
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tComença iconificat"
+
+#: main.c:2509
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <nom>\t\tUsa els recursos com si vim fós <nom>"
+
+#: main.c:2510
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (No implementat)\n"
+
+#: main.c:2512
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <color>\tUsa <color> pel fons (també: -bg)"
+
+#: main.c:2513
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <color>\tUsa <color> pel text normal (també: -fg)"
+
+#: main.c:2514 main.c:2534
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <tipus>\tUsa <tipus> pel text normal (també: -fn)"
+
+#: main.c:2515
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <tipus>\tUsa <tipus> pel text en negreta"
+
+#: main.c:2516
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <tipus>\tUsa <tipus> pel text en cursiva"
+
+#: main.c:2517 main.c:2535
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\tUsa <geom> com a geometria inicial (també: -geom)"
+
+#: main.c:2518
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <amplada>\tUsa un marge d'amplada <amplada> (també: -bw)"
+
+#: main.c:2519
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <amplada> Amplada de la barra de desplaçament (també: -sw)"
+
+#: main.c:2521
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <alçada>\tAlçada de la barra de menú (també: -mh)"
+
+#: main.c:2523 main.c:2536
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tUsa el mode de video invers (també: -rv)"
+
+#: main.c:2524
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tNo usa el mode de video invers (també: +rv)"
+
+#: main.c:2525
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <recurs>\tEstableix el recurs especificat"
+
+#: main.c:2528
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr "\nArguments reconeguts pel gvim (versió RISC OS):\n"
+
+#: main.c:2529
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <nombre>\tAmplada inicial de la finestra en columnes"
+
+#: main.c:2530
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <nombre>\tAlçada inicial de la finestra en files"
+
+#: main.c:2533
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr "\nArguments reconeguts pel gvim (versió GTK+):\n"
+
+#: main.c:2537
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <pantalla>\tExecuta vim a <pantalla> (també: --display)"
+
+#: main.c:2539
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr "--role <rol>\t\tUsa un únic rol per identificar la finestra principal"
+
+#: main.c:2541
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tObre el vim dins d'una altra aplicació GTK"
+
+#: main.c:2543
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tMostra els arguments per Gnome"
+
+#: main.c:2775
+msgid "No display"
+msgstr "No hi ha cap pantalla"
+
+#. Failed to send, abort.
+#: main.c:2790
+msgid ": Send failed.\n"
+msgstr ": Error en enviar.\n"
+
+#. Let vim start normally.
+#: main.c:2796
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": Error en enviar. Intentant l'execució local\n"
+
+#: main.c:2834 main.c:2855
+#, c-format
+msgid "%d of %d edited"
+msgstr "editat %d de %d"
+
+#: main.c:2877
+msgid "No display: Send expression failed.\n"
+msgstr "No hi ha cap pantalla: Error en enviar l'expressió.\n"
+
+#: main.c:2889
+msgid ": Send expression failed.\n"
+msgstr ": Error en enviar l'expressió.\n"
+
+#: mark.c:656
+msgid "No marks set"
+msgstr "No hi ha marques definides"
+
+#: mark.c:658
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: Cap marca coincideix amb \"%s\""
+
+#. Highlight title
+#: mark.c:669
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr "\nmarca lín col fitxer/text"
+
+#. Highlight title
+#: mark.c:707
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr "\n salt lín col fitxer/text"
+
+#: mark.c:1072
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr "\n# Marques de fitxer:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1107
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr "\n# Llista de salts (de més a menys recent):\n"
+
+#: mark.c:1202
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr "\n# Historial de marques en fitxers (de més a menys recent):\n"
+
+#: mark.c:1285
+msgid "Missing '>'"
+msgstr "Falta un '>'"
+
+#: mbyte.c:409
+msgid "E543: Not a valid codepage"
+msgstr "E543: No és un codi de pàgina vàlid"
+
+#: mbyte.c:4081
+msgid "E284: Cannot set IC values"
+msgstr "E284: No s'han pogut establir els valors del context d'entrada"
+
+#: mbyte.c:4233
+msgid "E285: Failed to create input context"
+msgstr "E285: Error en crear el context d'entrada"
+
+#: mbyte.c:4380
+msgid "E286: Failed to open input method"
+msgstr "E286: Error en obrir el mètode d'entrada"
+
+#: mbyte.c:4391
+#~ msgid "E287: Warning: Could not set destroy callback to IM"
+#~ msgstr ""
+
+#: mbyte.c:4397
+msgid "E288: input method doesn't support any style"
+msgstr "E288: el mètode d'entrada no suporta cap estil"
+
+#: mbyte.c:4454
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: el mètode d'entrada no suporta el tipus de preedició"
+
+#: mbyte.c:4528
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: L'estil over-the-spot requereix un conjunt de tipus"
+
+#: mbyte.c:4560
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: La llibreria GTK+ és anterior a 1.2.3. Es deshabilita l'àrea d'estat"
+
+#: mbyte.c:4839
+msgid "E292: Input Method Server is not running"
+msgstr "E292: El servidor de mètodes d'entrada (IMS) no està funcionant"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: El bloc no estava bloquejat"
+
+#: memfile.c:989
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Error de posició quan es llegia el fitxer d'intercanvi"
+
+#: memfile.c:994
+msgid "E295: Read error in swap file"
+msgstr "E295: Error de lectura en el fitxer d'intercanvi"
+
+#: memfile.c:1046
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Error de posició quan s'escrivia el fitxer d'intercanvi"
+
+#: memfile.c:1064
+msgid "E297: Write error in swap file"
+msgstr "E297: Error d'escriptura en el fitxer d'intercanvi"
+
+#: memfile.c:1261
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: El fitxer d'intercanvi encara existeix"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: No s'ha pogut obtenir el bloc 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: No s'ha pogut obtenir el bloc 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: No s'ha pogut obtenir el bloc 3?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Ep! El fitxer d'intercanvi s'ha perdut!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: No s'ha pogut reanomenar el fitxer d'intercanvi"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: Error en obrir el fitxer d'intercanvi de \"%s\", no es podrà recuperar"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: No s'ha pogut obtenir el bloc 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: No s'ha trobat el fitxer d'intercanvi de %s"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "Entreu el número del fitxer d'intercanvi a utilitzar (0 per sortir): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: No s'ha pogut obrir %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "No s'ha pogut llegir el bloc 0 de "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr "\nO bé no s'han fet canvis, o el Vim no ha actualitzat el fitxer d'intercanvi."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " no es pot utilitzar amb aquesta versió de Vim.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Useu Vim versió 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s no sembla un fitxer d'intercanvi de Vim"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " no es pot utilitzar en aquest ordinador.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "El fitxer va ser creat el "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"o el fitxer està fet malbé."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "S'està utilitzant el fitxer d'intercanvi \"%s\""
+
+#: memline.c:909
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Fitxer original \"%s\""
+
+#: memline.c:922
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Atenció: El fitxer original pot haver canviat"
+
+#: memline.c:963
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: No s'ha pogut llegir el bloc 1 de %s"
+
+#: memline.c:967
+msgid "???MANY LINES MISSING"
+msgstr "???FALTEN MOLTES LÍNIES"
+
+#: memline.c:983
+msgid "???LINE COUNT WRONG"
+msgstr "???COMPTADOR DE LÍNIA INCORRECTE"
+
+#: memline.c:990
+msgid "???EMPTY BLOCK"
+msgstr "???BLOC BUIT"
+
+#: memline.c:1016
+msgid "???LINES MISSING"
+msgstr "???FALTEN LÍNIES"
+
+#: memline.c:1048
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: L'ID del bloc 1 no és correcta (%s no és un fitxer .swp?)"
+
+#: memline.c:1053
+msgid "???BLOCK MISSING"
+msgstr "???FALTA UN BLOC"
+
+#: memline.c:1069
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? Des d'aquí fins ???FINAL les línies poden estar equivocades"
+
+#: memline.c:1085
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? Des d'aquí fins ???FINAL hi pot haver línies inserides/eliminades"
+
+#: memline.c:1105
+msgid "???END"
+msgstr "???FINAL"
+
+#: memline.c:1131
+msgid "E311: Recovery Interrupted"
+msgstr "E311: S'ha interromput la recuperació"
+
+#: memline.c:1133
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: S'han detectat errors en la recuperació; busqueu línies amb ???"
+
+#: memline.c:1136
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "S'ha completat la recuperació. Haurieu de revisar que tot sigui correcte."
+
+#: memline.c:1137
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr "\n(Potser voleu desar aquest fitxer amb un altre nom\n"
+
+#: memline.c:1138
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "i fer un diff amb el fitxer original per veure els canvis)\n"
+
+#: memline.c:1139
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr "Elimina el fitxer .swp tot seguit.\n\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1195
+msgid "Swap files found:"
+msgstr "Fitxers d'intercanvi trobats:"
+
+#: memline.c:1373
+msgid " In current directory:\n"
+msgstr " En el directori actual:\n"
+
+#: memline.c:1375
+msgid " Using specified name:\n"
+msgstr " Usant el nom especificat:\n"
+
+#: memline.c:1379
+msgid " In directory "
+msgstr " En el directori "
+
+#: memline.c:1397
+msgid " -- none --\n"
+msgstr " -- cap --\n"
+
+#: memline.c:1469
+msgid " owned by: "
+msgstr " propietat de: "
+
+#: memline.c:1471
+msgid " dated: "
+msgstr " amb data: "
+
+#: memline.c:1475 memline.c:3689
+msgid " dated: "
+msgstr " amb data: "
+
+#: memline.c:1491
+msgid " [from Vim version 3.0]"
+msgstr " [del Vim versió 3.0]"
+
+#: memline.c:1495
+msgid " [does not look like a Vim swap file]"
+msgstr " [no sembla un fitxer d'intercanvi de Vim]"
+
+#: memline.c:1499
+msgid " file name: "
+msgstr " nom del fitxer: "
+
+#: memline.c:1505
+msgid ""
+"\n"
+" modified: "
+msgstr "\n modificat: "
+
+#: memline.c:1506
+msgid "YES"
+msgstr "SÍ"
+
+#: memline.c:1506
+msgid "no"
+msgstr "no"
+
+#: memline.c:1510
+msgid ""
+"\n"
+" user name: "
+msgstr "\n nom de l'usuari: "
+
+#: memline.c:1517
+msgid " host name: "
+msgstr " màquina: "
+
+#: memline.c:1519
+msgid ""
+"\n"
+" host name: "
+msgstr "\n màquina: "
+
+#: memline.c:1525
+msgid ""
+"\n"
+" process ID: "
+msgstr "\n ID del procés: "
+
+#: memline.c:1531
+msgid " (still running)"
+msgstr " (encara funcionant)"
+
+#: memline.c:1543
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr "\n [no usable amb aquesta versió de Vim]"
+
+#: memline.c:1546
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr "\n [no usable en aquesta computadora]"
+
+#: memline.c:1551
+msgid " [cannot be read]"
+msgstr " [no es pot llegir]"
+
+#: memline.c:1555
+msgid " [cannot be opened]"
+msgstr " [no es pot obrir]"
+
+#: memline.c:1745
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: No s'ha pogut preservar, no hi ha fitxer d'intercanvi"
+
+#: memline.c:1798
+msgid "File preserved"
+msgstr "S'ha preservat el fitxer"
+
+#: memline.c:1800
+msgid "E314: Preserve failed"
+msgstr "E314: La preservació ha fallat"
+
+#: memline.c:1871
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: lnum no vàlid: %ld"
+
+#: memline.c:1897
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: no s'ha trobat la línia %ld"
+
+#: memline.c:2287
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: Punter a la id d'un bloc incorrecte 3"
+
+#: memline.c:2367
+msgid "stack_idx should be 0"
+msgstr "stack_idx hauria de ser 0"
+
+#: memline.c:2429
+msgid "E318: Updated too many blocks?"
+msgstr "E318: S'han actualitzat massa blocs?"
+
+#: memline.c:2611
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: Punter a la id d'un bloc incorrecte 4"
+
+#: memline.c:2638
+msgid "deleted block 1?"
+msgstr "s'ha eliminat el bloc 1?"
+
+#: memline.c:2838
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: No s'ha trobat la línia %ld"
+
+#: memline.c:3081
+msgid "E317: pointer block id wrong"
+msgstr "E317: Punter a la id d'un bloc incorrecte"
+
+#: memline.c:3097
+msgid "pe_line_count is zero"
+msgstr "po_line_count és zero"
+
+#: memline.c:3126
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: Nombre de línia fora d'abast: %ld passat el final"
+
+#: memline.c:3130
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: Comptador de línia incorrecte al bloc %ld"
+
+#: memline.c:3179
+msgid "Stack size increases"
+msgstr "La mida de la pila s'incrementa"
+
+#: memline.c:3225
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: Punter a la id d'un bloc incorrecte 2"
+
+#: memline.c:3679
+msgid "E325: ATTENTION"
+msgstr "E325: ATENCIÓ"
+
+#: memline.c:3680
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr "\nS'ha trobat un fitxer d'intercanvi de nom \""
+
+#: memline.c:3684
+msgid "While opening file \""
+msgstr "Mentre s'obria el fitxer \""
+
+#: memline.c:3693
+msgid " NEWER than swap file!\n"
+msgstr " MÉS NOU que el fitxer d'intercanvi!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3697
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Un altre programa pot estar editant aquest mateix fitxer.\n"
+" En aquest cas, aneu amb compte de no acabar amb dues\n"
+" instàncies diferents del mateix fitxer quan feu canvis.\n"
+
+#: memline.c:3698
+msgid " Quit, or continue with caution.\n"
+msgstr " Sortiu, o continueu amb precaució.\n"
+
+#: memline.c:3699
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr "\n(2) El Vim s'ha estrellat mentre s'editava aquest fitxer.\n"
+
+#: memline.c:3700
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " En aquest cas, useu \":recover\" o bé \"vim -r "
+
+#: memline.c:3702
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" per recuperar els canvis (vegeu \":help recovery\").\n"
+
+#: memline.c:3703
+msgid " If you did this already, delete the swap file \""
+msgstr " Si ja ho heu fet, elimineu el fitxer \""
+
+#: memline.c:3705
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" per evitar aquest missatge.\n"
+
+#: memline.c:3719 memline.c:3723
+msgid "Swap file \""
+msgstr "El fitxer d'intercanvi \""
+
+#: memline.c:3720 memline.c:3726
+msgid "\" already exists!"
+msgstr "\" ja existeix!"
+
+#: memline.c:3729
+msgid "VIM - ATTENTION"
+msgstr "VIM - ATENCIÓ"
+
+#: memline.c:3731
+msgid "Swap file already exists!"
+msgstr "El fitxer d'intercanvi ja existeix!"
+
+#: memline.c:3735
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"&Obre en mode només lectura\n"
+"&Edita\n"
+"&Recupera\n"
+"&Surt"
+
+#: memline.c:3737
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"&Obre en mode només lectura\n"
+"&Edita\n"
+"&Recupera\n"
+"&Surt\n"
+"E&limina'l"
+
+#: memline.c:3790
+msgid "E326: Too many swap files found"
+msgstr "E326: S'han trobat massa fitxers d'intercanvi"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Part de l'ubicació del menú no és submenú"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: El menú només existeix en un altre mode"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: No hi ha cap menú amb aquest nom"
+
+#: menu.c:509
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: L'ubicació del menú no pot portar a un submenú"
+
+#: menu.c:548
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: No es poden afegir ítems de menú directament a la barra de menú"
+
+#: menu.c:554
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Un separador no pot formar part de l'ubicació de menú"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1079
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr "\n--- Menús ---"
+
+#: menu.c:1996
+msgid "Tear off this menu"
+msgstr "Estripa aquest menú"
+
+#: menu.c:2061
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: L'ubicació de menú ha de portar a un ítem de menú"
+
+#: menu.c:2081
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: No s'ha trobat el menú: %s"
+
+#: menu.c:2150
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: El menú no està definit pel mode %s"
+
+#: menu.c:2188
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: L'ubicació de menú ha de portar a un submenú"
+
+#: menu.c:2209
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: No s'ha trobat el menú - reviseu els noms dels menús"
+
+#: message.c:519
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "S'ha detectat un error en processar %s:"
+
+#: message.c:535
+#, c-format
+msgid "line %4ld:"
+msgstr "línia %4ld:"
+
+#: message.c:575
+msgid "[string too long]"
+msgstr "[cadena massa llarga]"
+
+#: message.c:721
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "Traducció dels missatges: Ernest Adrogué <eadrogue@gmx.net>"
+
+#: message.c:945
+msgid "Interrupt: "
+msgstr "Interrupció: "
+
+#: message.c:948
+msgid "Hit ENTER to continue"
+msgstr "Premeu ENTRAR per continuar"
+
+#: message.c:950
+msgid "Hit ENTER or type command to continue"
+msgstr "Premeu ENTRAR o introduïu una ordre per continuar"
+
+#: message.c:2253
+msgid "-- More --"
+msgstr "-- Més --"
+
+#: message.c:2256
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (ENTRAR/RETROCÉS: línia, ESPAI/b; pàgina, d/u; mitja pàgina, q: surt)"
+
+#: message.c:2257
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (ENTRAR: línia, ESPAI: pàgina, d: mitja pàgina, q: surt)"
+
+#: message.c:2749 message.c:2764
+msgid "Question"
+msgstr "Pregunta"
+
+#: message.c:2751
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Sí\n"
+"&No"
+
+#: message.c:2784
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Sí\n"
+"&No\n"
+"Desa-ho &tot\n"
+"&Descarta-ho tot\n"
+"&Cancel·la"
+
+#: message.c:2825
+msgid "Save File dialog"
+msgstr "Diàleg de desar fitxer"
+
+#: message.c:2827
+msgid "Open File dialog"
+msgstr "Diàleg d'obrir fitxer"
+
+#. TODO: non-GUI file selector here
+#: message.c:2898
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: No hi ha un explorador de fitxers en mode consola"
+
+#: misc1.c:2681
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: Atenció: S'està canviant un fitxer de només lectura"
+
+#: misc1.c:2916
+msgid "1 more line"
+msgstr "1 línia més"
+
+#: misc1.c:2918
+msgid "1 line less"
+msgstr "1 línia menys"
+
+#: misc1.c:2923
+#, c-format
+msgid "%ld more lines"
+msgstr "%ld línies més"
+
+#: misc1.c:2925
+#, c-format
+msgid "%ld fewer lines"
+msgstr "%ld línies menys"
+
+#: misc1.c:2928
+msgid " (Interrupted)"
+msgstr " (Interromput)"
+
+#: misc1.c:6620
+msgid "Vim: preserving files...\n"
+msgstr "Vim: preservant els fitxers...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6630
+msgid "Vim: Finished.\n"
+msgstr "Vim: Finalitzat.\n"
+
+#: misc2.c:670 misc2.c:686
+msgid "ERROR: "
+msgstr "ERROR: "
+
+#: misc2.c:690
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr "\n[octets] total assignat-alliberat %lu-%lu, en ús %lu, màxim ús %lu\n"
+
+#: misc2.c:692
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr "[crides] total re/malloc() %lu, total free() %lu\n\n"
+
+#: misc2.c:747
+msgid "E340: Line is becoming too long"
+msgstr "E340: La línia s'està tornant massa llarga"
+
+#: misc2.c:791
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Error intern: lalloc(%ld, )"
+
+#: misc2.c:899
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Memòria exhaurida! (assignant %lu octets)"
+
+#: misc2.c:2565
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "S'està cridant l'intèrpret d'ordres per executar: \"%s\""
+
+#: misc2.c:2786
+msgid "E545: Missing colon"
+msgstr "E545: Falta un caràcter \":\""
+
+#: misc2.c:2788 misc2.c:2815
+msgid "E546: Illegal mode"
+msgstr "E546: Mode il·legal"
+
+#: misc2.c:2854
+msgid "E547: Illegal mouseshape"
+msgstr "E547: La forma del punter del ratolí és il·legal"
+
+#: misc2.c:2894
+msgid "E548: digit expected"
+msgstr "E548: S'esperava un dígit"
+
+#: misc2.c:2899
+msgid "E549: Illegal percentage"
+msgstr "E549: Percentatge il·legal"
+
+#: misc2.c:3209
+msgid "Enter encryption key: "
+msgstr "Introduïu la clau de xifrat: "
+
+#: misc2.c:3210
+msgid "Enter same key again: "
+msgstr "Introduïu la mateixa clau un altre cop: "
+
+#: misc2.c:3220
+msgid "Keys don't match!"
+msgstr "La claus no coincideixen!"
+
+#: misc2.c:3769
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr "E343: Path no vàlid: '**[núm]' ha d'estar al final del path, o seguit de '%s'"
+
+#: misc2.c:5045
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: No s'ha trobat el directori \"%s\" en el cdpath"
+
+#: misc2.c:5048
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: No s'ha trobat el fitxer \"%s\" en el path"
+
+#: misc2.c:5054
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: No s'ha trobat cap més directori \"%s\" en el cdpath"
+
+#: misc2.c:5057
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: No s'ha trobat cap més fitxer \"%s\" en el path"
+
+#: misc2.c:5291
+msgid "E550: Missing colon"
+msgstr "E550: Falta un caràcter \":\""
+
+#: misc2.c:5303
+msgid "E551: Illegal component"
+msgstr "E551: Component il·legal"
+
+#: misc2.c:5311
+msgid "E552: digit expected"
+msgstr "E552: S'esperava un dígit"
+
+#. Get here when the server can't be found.
+#: netbeans.c:282
+msgid "Cannot connect to Netbeans #2"
+msgstr "No s'ha pogut connectar amb Netbeans #2"
+
+#: netbeans.c:290
+msgid "Cannot connect to Netbeans"
+msgstr "No s'ha pogut connectar amb Netbeans"
+
+#: netbeans.c:564
+msgid "read from Netbeans socket"
+msgstr "lectura d'un socket Netbeans"
+
+#: normal.c:2916
+msgid "Warning: terminal cannot highlight"
+msgstr "Atenció: el terminal no suporta ressalt"
+
+#: normal.c:3131
+msgid "E348: No string under cursor"
+msgstr "E348: No hi ha cap cadena sota el cursor"
+
+#: normal.c:3133
+msgid "E349: No identifier under cursor"
+msgstr "E349: No hi ha cap identificador sota el cursor"
+
+#: normal.c:4351
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: No es poden eliminar plecs amb el 'foldmethod' actual"
+
+#: ops.c:295
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "1 línia %sada 1 vegada"
+
+#: ops.c:297
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 línia %sada %d vegades"
+
+#: ops.c:302
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld línies %sades 1 vegada"
+
+#: ops.c:305
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld línies %sades %d vegades"
+
+#: ops.c:663
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld línies a sagnar... "
+
+#: ops.c:713
+msgid "1 line indented "
+msgstr "1 línia sagnada "
+
+#: ops.c:715
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld línies sagnades "
+
+#. must display the prompt
+#: ops.c:1647
+msgid "cannot yank; delete anyway"
+msgstr "no s'ha pogut copiar; voleu elimiar el text de totes maneres"
+
+#: ops.c:2155
+msgid "1 line changed"
+msgstr "1 línia canviada"
+
+#: ops.c:2157
+#, c-format
+msgid "%ld lines changed"
+msgstr "%ld línies canviades"
+
+#: ops.c:2541
+#, c-format
+msgid "freeing %ld lines"
+msgstr "alliberant %ld línies"
+
+#: ops.c:2822
+msgid "1 line yanked"
+msgstr "1 línia copiada"
+
+#: ops.c:2824
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld línies copiades"
+
+#: ops.c:3109
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: No hi ha res en el registre %s"
+
+#. Highlight title
+#: ops.c:3666
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr "\n--- Registres ---"
+
+#: ops.c:4875
+msgid "Illegal register name"
+msgstr "El nom de registre és il·legal"
+
+#: ops.c:4961
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr "\n# Registres:\n"
+
+#: ops.c:4994
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: El tipus de registre %d és desconegut"
+
+#: ops.c:5480
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: El nom de registre no és vàlid: '%s'"
+
+#: ops.c:5841
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Cols; "
+
+#: ops.c:5848
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "%s%ld de %ld Línies seleccionades; %ld de %ld Paraules; %ld de %ld Octets"
+
+#: ops.c:5864
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Col %s de %s; Línia %ld de %ld; Paraula %ld de %ld; Octet %ld de %ld"
+
+#: ops.c:5875
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld per la BOM)"
+
+#: option.c:1623
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=Pàgina %N"
+
+#: option.c:2072
+msgid "Thanks for flying Vim"
+msgstr "Gràcies per utilitzar el Vim"
+
+#: option.c:3344 option.c:3451
+msgid "E518: Unknown option"
+msgstr "E518: L'opció és desconeguda"
+
+#: option.c:3357
+msgid "E519: Option not supported"
+msgstr "E519: L'opció no està suportada"
+
+#: option.c:3382
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: No està permès en una línia de mode"
+
+#: option.c:3438
+msgid ""
+"\n"
+"\tLast set from "
+msgstr "\n Definit per últim cop a "
+
+#: option.c:3577
+msgid "E521: Number required after ="
+msgstr "E521: Es requereix un número després de ="
+
+#: option.c:3903 option.c:4520
+msgid "E522: Not found in termcap"
+msgstr "E522: No s'ha trobat a la base de dades termcap"
+
+#: option.c:3969
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: Caràcter il·legal <%s>"
+
+#: option.c:4512
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: No es pot definir 'term' com a cadena buida"
+
+#: option.c:4515
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: No es pot canviar de terminal en mode GUI"
+
+#: option.c:4517
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: Useu \":gui\" per ininciar l'interfície d'usuari gràfica"
+
+#: option.c:4538
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: Les opcions 'backupext' i 'patchmode' coincideixen"
+
+#: option.c:4723
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: L'interfície GTK+ 2 no permet canviar la codificació"
+
+#: option.c:4879
+msgid "E524: Missing colon"
+msgstr "E524: Falta un caràcter \":\""
+
+#: option.c:4881
+msgid "E525: Zero length string"
+msgstr "E525: La llargada de la cadena és zero"
+
+#: option.c:4949
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: Falta un número després de <%s>"
+
+#: option.c:4963
+msgid "E527: Missing comma"
+msgstr "E527: Falta una coma"
+
+#: option.c:4970
+msgid "E528: Must specify a ' value"
+msgstr "E528: Heu d'especificar un valor '"
+
+#: option.c:5011
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: Conté un caràcter no imprimible o ample"
+
+#: option.c:5060
+msgid "E596: Invalid font(s)"
+msgstr "E596: El tipus de lletra no és vàlid"
+
+#: option.c:5068
+msgid "E597: can't select fontset"
+msgstr "E597: No s'ha pogut seleccionar el conjunt de tipus"
+
+#: option.c:5070
+msgid "E598: Invalid fontset"
+msgstr "E598: El conjunt de tipus de lletra no és vàlid"
+
+#: option.c:5077
+msgid "E533: can't select wide font"
+msgstr "E533: No s'ha pogut seleccionar el tipus de lletra ample"
+
+#: option.c:5079
+msgid "E534: Invalid wide font"
+msgstr "E534: El tipus de lletra ample no és vàlid"
+
+#: option.c:5349
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: Caràcter il·legal després de <%c>"
+
+#: option.c:5454
+msgid "E536: comma required"
+msgstr "E536: Es requereix una coma"
+
+#: option.c:5464
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: L'opció 'commentstring' ha d'estar indefinida o contenir %s"
+
+#: option.c:5537
+msgid "E538: No mouse support"
+msgstr "E538: No hi ha suport per ratolí"
+
+#: option.c:5805
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: La seqüència d'expressions no està acabada"
+
+#: option.c:5809
+msgid "E541: too many items"
+msgstr "E541: Hi han massa ítems"
+
+#: option.c:5811
+msgid "E542: unbalanced groups"
+msgstr "E542: Grups desequilibrats"
+
+#: option.c:6032
+msgid "E590: A preview window already exists"
+msgstr "E590: Ja hi ha una finestra de vista prèvia"
+
+#: option.c:6289
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr "W17: L'àrab requereix UTF-8, feu ':set encoding=utf-8'"
+
+#: option.c:6606
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: Es necessiten com a mínim %d línies"
+
+#: option.c:6615
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: Es necessiten com a mínim %d columnes"
+
+#: option.c:6920
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: L'opció és desconeguda: %s"
+
+#: option.c:7029
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr "\n--- Codis de terminal ---"
+
+#: option.c:7031
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr "\n--- Valors de les opcions globals ---"
+
+#: option.c:7033
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr "\n--- Valors de les opcions locals ---"
+
+#: option.c:7035
+msgid ""
+"\n"
+"--- Options ---"
+msgstr "\n--- Opcions ---"
+
+#: option.c:7736
+msgid "E356: get_varp ERROR"
+msgstr "E356: Error en get_varp()"
+
+#: option.c:8707
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': No s'ha trobat el caràcter corresponent a %s"
+
+#: option.c:8741
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': Sobren caràcters després del punt i coma: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "no s'ha pogut obrir "
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: No s'ha pogut obrir la finestra!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Es requereix Amigados versió 2.04 o posterior\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Es requereix %s versió %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "No s'ha pogut obrir NIL:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr "No s'ha pogut crear "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim ha finalitzat amb %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "no s'ha pogut canviar el mode de consola ?!\n"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: no és una consola??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1143
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: No s'ha pogut executar l'intèrpret d'ordres amb l'opció -f"
+
+#: os_amiga.c:1184 os_amiga.c:1274
+msgid "Cannot execute "
+msgstr "No s'ha pogut executar "
+
+#: os_amiga.c:1187 os_amiga.c:1284
+msgid "shell "
+msgstr "l'intèrpret d'ordres "
+
+#: os_amiga.c:1207 os_amiga.c:1309
+msgid " returned\n"
+msgstr " ha retornat\n"
+
+#: os_amiga.c:1450
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "un valor ANCHOR_BUF_SIZE massa petit."
+
+#: os_amiga.c:1454
+msgid "I/O ERROR"
+msgstr "ERROR d'E/S"
+
+#: os_mswin.c:517
+msgid "...(truncated)"
+msgstr "...(truncat)"
+
+#: os_mswin.c:619
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "L'opció 'columns' no és 80, no es poden executar ordres externes"
+
+#: os_mswin.c:1854
+msgid "E237: Printer selection failed"
+msgstr "E237: La selecció d'impressora ha fallat"
+
+# a IMPRESSORA a PORT ?
+#: os_mswin.c:1894
+#, c-format
+msgid "to %s on %s"
+msgstr "a %s a %s"
+
+#: os_mswin.c:1909
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: Tipus de lletra d'impressió desconegut: %s"
+
+#: os_mswin.c:1959 os_mswin.c:1969
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Error d'impressió: %s"
+
+#: os_mswin.c:1970
+msgid "Unknown"
+msgstr "Desconegut"
+
+#: os_mswin.c:1997
+#, c-format
+msgid "Printing '%s'"
+msgstr "S'està imprimint '%s'"
+
+#: os_mswin.c:3083
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Conjunt de caràcters \"%s\" il·legal en el tipus \"%s\""
+
+#: os_mswin.c:3091
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Caràcter '%c' il·legal en el tipus \"%s\""
+
+#: os_riscos.c:1258
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: L'opció 'osfiletype' no és vàlida - s'usa Text"
+
+#: os_unix.c:887
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: S'ha rebut un doble senyal, sortint\n"
+
+#: os_unix.c:893
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: S'ha rebut un senyal letal %s\n"
+
+#: os_unix.c:896
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: S'ha rebut un senyal letal\n"
+
+# display
+#: os_unix.c:1159
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "S'ha trigat %ld mseg en obrir el display X"
+
+#: os_unix.c:1186
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr "\nVim: Error de X\n"
+
+# display
+#: os_unix.c:1294
+msgid "Testing the X display failed"
+msgstr "Ha fallat la comprovació del display X"
+
+# display
+#: os_unix.c:1433
+msgid "Opening the X display timed out"
+msgstr "S'ha esgotat el temps mentre es tractava d'obrir el display X"
+
+#: os_unix.c:3173 os_unix.c:3853
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr "\nNo s'ha pogut executar la shell "
+
+#: os_unix.c:3221
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr "\nNo s'ha pogut executar la shell sh\n"
+
+#: os_unix.c:3225 os_unix.c:3859
+msgid ""
+"\n"
+"shell returned "
+msgstr "\nla shell ha retornat "
+
+#: os_unix.c:3360
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr "\nNo s'han pogut crear canonades\n"
+
+#: os_unix.c:3375
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr "\nNo s'ha pogut bifurcar\n"
+
+#: os_unix.c:3866
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr "\nL'ordre ha finalitzat\n"
+
+#: os_unix.c:4119 os_unix.c:4244 os_unix.c:5902
+msgid "XSMP lost ICE connection"
+msgstr "XSMP: s'ha perdut la connexió ICE"
+
+# display
+#: os_unix.c:5486
+msgid "Opening the X display failed"
+msgstr "Ha fallat l'obertura del display X"
+
+#: os_unix.c:5808
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP: s'està duent a terme la petició save-yourself"
+
+#: os_unix.c:5925
+msgid "XSMP opening connection"
+msgstr "XSMP: obrint la connexió"
+
+#: os_unix.c:5943
+msgid "XSMP ICE connection watch failed"
+msgstr "XSMP: Ha fallat l'inspecció de la connexió ICE"
+
+#: os_unix.c:5963
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP: Ha fallat la rutina SmcOpenConnection: %s"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "A la línia"
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "No s'ha pogut assignar memòria per la línia d'ordres."
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "Error del VIM"
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "No s'ha pogut carregar vim32.dll!"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "No s'han pogut reassignar els punters de funcions a la DLL!"
+
+#: os_win16.c:341 os_win32.c:3049
+#, c-format
+msgid "shell returned %d"
+msgstr "la shell ha retornat %d"
+
+#: os_win32.c:2507
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: S'ha rebut un event %s\n"
+
+#: os_win32.c:2509
+msgid "close"
+msgstr "de finalització"
+
+#: os_win32.c:2511
+msgid "logoff"
+msgstr "de final de sessió"
+
+#: os_win32.c:2512
+msgid "shutdown"
+msgstr "d'apagament del sistema"
+
+#: os_win32.c:3002
+msgid "E371: Command not found"
+msgstr "E371: No s'ha trobat l'ordre"
+
+#: os_win32.c:3015
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"El programa VIMRUN.EXE no es troba en el $PATH.\n"
+"Les ordres externes no faran una pausa un cop finalitzades.\n"
+"Vegeu :help win32-vimrun per a més informació."
+
+#: os_win32.c:3018
+msgid "Vim Warning"
+msgstr "Vim Atenció"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Sobren %%%c a la cadena de format"
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: %%%c inesperat a la cadena de format"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E364: Falta un ] a la cadena de format"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: %%%c no suportat a la cadena de format"
+
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: %%%c no vàlid en el prefix de la cadena de format"
+
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: %%%c no vàlid a la cadena de format"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: L'opció 'errorformat' no conté cap patró"
+
+#: quickfix.c:497
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Falta un nom de directori"
+
+#: quickfix.c:984
+msgid "E553: No more items"
+msgstr "E553: No hi ha més ítems"
+
+#: quickfix.c:1221
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d de %d)%s%s: "
+
+#: quickfix.c:1223
+msgid " (line deleted)"
+msgstr " (línia eliminada)"
+
+#: quickfix.c:1432
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Baix de la pila quickfix"
+
+#: quickfix.c:1441
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Dalt de la pila quickfix"
+
+#: quickfix.c:1453
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "llista d'errors %d de %d; %d errors"
+
+#: quickfix.c:1927
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: No s'ha pogut escriure, l'opció 'buftype' no està definida"
+
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: Ítem no vàlid a %s%%[]"
+
+#: regexp.c:827
+msgid "E339: Pattern too long"
+msgstr "E339: El patró és massa llarg"
+
+#: regexp.c:996
+msgid "E50: Too many \\z("
+msgstr "E50: Sobren \\z("
+
+#: regexp.c:1007
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: Sobren %s("
+
+#: regexp.c:1064
+msgid "E52: Unmatched \\z("
+msgstr "E52: \\z( desequilibrat"
+
+#: regexp.c:1068
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: %s%%( desequilibrat"
+
+#: regexp.c:1070
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: %s( desequilibrat"
+
+#: regexp.c:1075
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: %s) desequilibrat"
+
+#: regexp.c:1244
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: L'operand %s* podria estar buit"
+
+#: regexp.c:1247
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: L'operand %s+ podria estar buit"
+
+#: regexp.c:1301
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: Hi ha un caràcter no vàlid després de %s@"
+
+#: regexp.c:1326
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: L'operand %s{ podria estar buit"
+
+#: regexp.c:1336
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: La construcció %s{...} és massa complexa"
+
+#: regexp.c:1352
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: %s* imbricats"
+
+#: regexp.c:1355
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: %s%c imbricats"
+
+#: regexp.c:1473
+msgid "E63: invalid use of \\_"
+msgstr "E63: Ús no vàlid de \\_"
+
+#: regexp.c:1518
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E46: No ha ha res abans de %s%c"
+
+#: regexp.c:1574
+msgid "E65: Illegal back reference"
+msgstr "E65: Referència il·legal a l'element anterior"
+
+#: regexp.c:1587
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z( no està permès aquí"
+
+#: regexp.c:1606
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 et al. no estan permesos aquí"
+
+#: regexp.c:1617
+msgid "E68: Invalid character after \\z"
+msgstr "E68: Hi ha un caràcter no vàlid després de \\z"
+
+#: regexp.c:1666
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: Falta un ] després de %s%%["
+
+#: regexp.c:1682
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: Element %s%%[] buit"
+
+#: regexp.c:1742
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: Hi ha un caràcter invàlid després de %s%%"
+
+#: regexp.c:2539
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: Error de sintaxi a %s{...}"
+
+#: regexp.c:2800
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Programa inestable; expressió regular massa complexa?"
+
+#: regexp.c:2941
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: El patró ha provocat un error de desbordament de pila"
+
+#: regexp.c:3180
+msgid "External submatches:\n"
+msgstr "Subcoincidències externes:\n"
+
+#: screen.c:2113
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld línies plegades "
+
+#: screen.c:7892
+msgid " VREPLACE"
+msgstr " SUBSTITUIRV"
+
+#: screen.c:7896
+msgid " REPLACE"
+msgstr " SUBSTITUIR"
+
+# En el mode d'escriptura de dreta a esquerra
+# surt el missatge «REVERSE INSERT»
+#: screen.c:7901
+msgid " REVERSE"
+msgstr " INVERS"
+
+#: screen.c:7903
+msgid " INSERT"
+msgstr " INSERIR"
+
+#: screen.c:7906
+msgid " (insert)"
+msgstr " (inserir)"
+
+#: screen.c:7908
+msgid " (replace)"
+msgstr " (substituir)"
+
+#: screen.c:7910
+msgid " (vreplace)"
+msgstr " (substituirv)"
+
+#: screen.c:7913
+msgid " Hebrew"
+msgstr " Hebreu"
+
+#: screen.c:7924
+msgid " Arabic"
+msgstr " Àrab"
+
+#: screen.c:7927
+msgid " (lang)"
+msgstr " (lang)"
+
+#: screen.c:7931
+msgid " (paste)"
+msgstr " (enganxar)"
+
+#: screen.c:7937
+msgid " SELECT"
+msgstr " SELECCIONAR"
+
+#: screen.c:7939
+msgid " VISUAL"
+msgstr " VISUAL"
+
+#: screen.c:7941
+msgid " BLOCK"
+msgstr " BLOC"
+
+#: screen.c:7943
+msgid " LINE"
+msgstr " LÍNIA"
+
+#: screen.c:7956 screen.c:8016
+msgid "recording"
+msgstr "enregistrant"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "la cerca ha arribat a DALT, es continua a BAIX"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "la cerca ha arribat a BAIX, es continua a DALT"
+
+#: search.c:525
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Cadena de cerca no vàlida: %s"
+
+#: search.c:852
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: la cerca ha arribat a DALT sense resultats per: %s"
+
+#: search.c:855
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: la cerca ha arribat a BAIX sense resultats per: %s"
+
+#: search.c:1247
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: S'esperava '?' o '/' després de ';'"
+
+#: search.c:3685
+msgid " (includes previously listed match)"
+msgstr " (inclou resultats llistats anteriorment)"
+
+#. cursor at status line
+#: search.c:3705
+msgid "--- Included files "
+msgstr "--- Fitxers inclosos "
+
+#: search.c:3707
+msgid "not found "
+msgstr "no s'ha trobat"
+
+#: search.c:3708
+msgid "in path ---\n"
+msgstr "en el path ---\n"
+
+#: search.c:3747
+msgid " (Already listed)"
+msgstr " (Ja s'havia llistat)"
+
+#: search.c:3749
+msgid " NOT FOUND"
+msgstr " NO TROBAT"
+
+#: search.c:3801
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Examinant el fitxer inclòs: %s"
+
+#: search.c:4019
+msgid "E387: Match is on current line"
+msgstr "E387: El resultat es troba a la línia actual"
+
+#: search.c:4162
+msgid "All included files were found"
+msgstr "S'han trobat tots els fitxers inclosos"
+
+#: search.c:4164
+msgid "No included files"
+msgstr "No hi han fitxers inclosos"
+
+#: search.c:4180
+msgid "E388: Couldn't find definition"
+msgstr "E388: No s'ha trobat la definició"
+
+#: search.c:4182
+msgid "E389: Couldn't find pattern"
+msgstr "E389: No s'ha trobat el patró"
+
+#: syntax.c:3015
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: L'argument és il·legal: %s"
+
+#: syntax.c:3195
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: No existeix tal grup de sintaxi: %s"
+
+#: syntax.c:3359
+msgid "No Syntax items defined for this buffer"
+msgstr "No hi ha ítems de sintaxi definits en aquest buffer"
+
+#: syntax.c:3367
+msgid "syncing on C-style comments"
+msgstr "s'està sincronitzant a partir de comentaris estil C"
+
+#: syntax.c:3375
+msgid "no syncing"
+msgstr "no es sincronitza"
+
+# va junta amb la següent
+#: syntax.c:3378
+msgid "syncing starts "
+msgstr "comença la sincronització"
+
+# va junta amb l'anterior
+#: syntax.c:3380 syntax.c:3455
+msgid " lines before top line"
+msgstr " línies abans de la línia superior"
+
+#: syntax.c:3385
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr "\n--- Ítems de sincronització de sintaxi ---"
+
+#: syntax.c:3390
+msgid ""
+"\n"
+"syncing on items"
+msgstr "\ns'està sincronitzant a partir d'ítems"
+
+#: syntax.c:3396
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr "\n--- Ítems de sintaxi ---"
+
+#: syntax.c:3419
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: No existeix tal grup de sintaxi: %s"
+
+#: syntax.c:3445
+msgid "minimal "
+msgstr "mínim "
+
+#: syntax.c:3452
+msgid "maximal "
+msgstr "màxim "
+
+#: syntax.c:3464
+msgid "; match "
+msgstr "; coincidència "
+
+#: syntax.c:3466
+msgid " line breaks"
+msgstr " salts de línia"
+
+#: syntax.c:4100
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: L'opció group[t]here no s'accepta aquí"
+
+#: syntax.c:4124
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: No s'ha trobat cap regió d'ítems per %s"
+
+#: syntax.c:4152
+msgid "E395: contains argument not accepted here"
+msgstr "E395: Conté un argument que no s'accepta aquí"
+
+#: syntax.c:4163
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: L'argument 'containedin' no s'accepta aquí"
+
+#: syntax.c:4241
+msgid "E397: Filename required"
+msgstr "E397: Es requereix un nom de fitxer"
+
+#: syntax.c:4579
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Falta un '=': %s"
+
+# 'syntax region' és una ordre
+#: syntax.c:4737
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Falten arguments: syntax region %s"
+
+#: syntax.c:5068
+msgid "E400: No cluster specified"
+msgstr "E400: No heu especificat cap grup"
+
+#: syntax.c:5105
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: No s'ha trobat el patró de delimitació: %s"
+
+#: syntax.c:5180
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Hi ha porqueria després del patró: %s"
+
+#: syntax.c:5270
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: syntax sync: el patró de continuació de línia està repetit"
+
+#: syntax.c:5327
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Arguments il·legals: %s"
+
+#: syntax.c:5377
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Falta un signe d'igual: %s"
+
+#: syntax.c:5383
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Argument buit: %s"
+
+#: syntax.c:5410
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E402: %s no està permès aquí"
+
+#: syntax.c:5417
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s ha d'anar al principi de la llista 'contains'"
+
+#: syntax.c:5487
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: El nom del grup és desconegut: %s"
+
+#: syntax.c:5720
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Sub-ordre de sintaxi no vàlida: %s"
+
+#: syntax.c:6099
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: No s'ha trobat el grup de ressalt: %s"
+
+#: syntax.c:6123
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Falten arguments: \":highlight link %s\""
+
+#: syntax.c:6130
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: Sobren arguments: \":highlight link %s\""
+
+#: syntax.c:6150
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: El grup ja ha estat definit, s'ignora l'enllaç de ressalt"
+
+#: syntax.c:6279
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: Signe d'igual inesperat: %s"
+
+#: syntax.c:6315
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: Falta un signe d'igual: %s"
+
+#: syntax.c:6337
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: Falta un argument: %s"
+
+#: syntax.c:6374
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: El valor és il·legal: %s"
+
+#: syntax.c:6493
+msgid "E419: FG color unknown"
+msgstr "E419: Color de primer terme desconegut"
+
+#: syntax.c:6504
+msgid "E420: BG color unknown"
+msgstr "E420: Color de fons desconegut"
+
+#: syntax.c:6565
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Nom o número de color no identificat: %s"
+
+#: syntax.c:6771
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: El codi de terminal és massa llarg: %s"
+
+#: syntax.c:6818
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: L'argument és il·legal: %s"
+
+#: syntax.c:7347
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: Hi ha massa atributs de ressalt diferents en ús"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: Baix de la pila d'etiquetes"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: Dalt de la pila d'etiquetes"
+
+#: tag.c:396
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: No es pot anar abans de la primera etiqueta coincident"
+
+#: tag.c:516
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: No s'ha trobat l'etiqueta: %s"
+
+#: tag.c:549
+msgid " # pri kind tag"
+msgstr " # pri tip etiqueta"
+
+#: tag.c:552
+msgid "file\n"
+msgstr "fitxer\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:710
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Entreu un número (<Entrar> per avortar): "
+
+#: tag.c:750
+msgid "E427: There is only one matching tag"
+msgstr "E427: Només hi ha una sola etiqueta que coincideixi"
+
+#: tag.c:752
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: No es pot anar més enllà de l'última etiqueta coincident"
+
+#: tag.c:772
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "El fitxer \"%s\" no existeix"
+
+#. Give an indication of the number of matching tags
+#: tag.c:785
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "etiqueta %d de %d%s"
+
+#: tag.c:788
+msgid " or more"
+msgstr " o més"
+
+#: tag.c:790
+msgid " Using tag with different case!"
+msgstr " No es fa distinció entre majúscules i minúscules!"
+
+#: tag.c:834
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: El fitxer \"%s\" no existeix"
+
+#. Highlight title
+#: tag.c:903
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr "\n # A etiq DES DE línia en fitxer/text"
+
+#: tag.c:1204
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Cercant en el fitxer d'etiquetes %s"
+
+#: tag.c:1388
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: S'ha truncat l'ubicació del fitxer d'etiquetes per %s\n"
+
+#: tag.c:1918
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Error de format en el fitxer d'etiquetes \"%s\""
+
+#: tag.c:1922
+#, c-format
+msgid "Before byte %ld"
+msgstr "Abans de l'octet %ld"
+
+#: tag.c:1943
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: El fitxer d'etiquetes no està ordenat: %s"
+
+#. never opened any tags file
+#: tag.c:1983
+msgid "E433: No tags file"
+msgstr "E433: No hi ha cap fitxer d'etiquetes"
+
+#: tag.c:2684
+msgid "E434: Can't find tag pattern"
+msgstr "E434: No s'ha trobat l'etiqueta"
+
+#: tag.c:2695
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: No s'ha trobat l'etiqueta exacta!"
+
+# «terminal» és masculí
+#: term.c:1745
+msgid "' not known. Available builtin terminals are:"
+msgstr "' no identificat. Els terminals disponibles són:"
+
+#: term.c:1769
+msgid "defaulting to '"
+msgstr "per omissió '"
+
+#: term.c:2127
+msgid "E557: Cannot open termcap file"
+msgstr "E557: No s'ha pogut obrir el fitxer termcap"
+
+#: term.c:2131
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: No s'ha trobat l'informació del terminal a terminfo"
+
+#: term.c:2133
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: No s'ha trobat l'informació del terminal a termcap"
+
+#: term.c:2292
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: No hi ha cap entrada \"%s\" a termcap"
+
+#: term.c:2766
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: Es requereix la capacitat \"cm\" per part del terminal"
+
+#. Highlight title
+#: term.c:4970
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr "\n--- Tecles del terminal ---"
+
+#: ui.c:252
+msgid "new shell started\n"
+msgstr "s'ha iniciat una nova shell\n"
+
+#: ui.c:1784
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: Error en llegir l'entrada, sortint...\n"
+
+#. must display the prompt
+#: undo.c:394
+msgid "No undo possible; continue anyway"
+msgstr "No es pot desfer res; voleu continuar"
+
+#: undo.c:549
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: els nombres de línia no són correctes"
+
+#: undo.c:718
+msgid "1 change"
+msgstr "1 canvi"
+
+#: undo.c:720
+#, c-format
+msgid "%ld changes"
+msgstr "%ld canvis"
+
+#: undo.c:764
+msgid "E439: undo list corrupt"
+msgstr "E439: La llista de desfer està corrompuda"
+
+#: undo.c:796
+msgid "E440: undo line missing"
+msgstr "E440: Falta una línia de desfer"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:696
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr "\nVersió GUI per MS-Windows 16/32 bits"
+
+#: version.c:698
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr "\nVersió GUI per MS-Windows 32 bits"
+
+#: version.c:701
+msgid " in Win32s mode"
+msgstr " en mode Win32s"
+
+#: version.c:703
+msgid " with OLE support"
+msgstr " amb suport per OLE"
+
+#: version.c:706
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr "\nVersió consola per MS-Windows 32 bits"
+
+#: version.c:710
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr "\nVersió per MS-Windows 16 bits"
+
+#: version.c:714
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr "\nVersió per MS-DOS 32 bits"
+
+#: version.c:716
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr "\nVersió per MS-DOS 16 bits"
+
+#: version.c:722
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr "\nVersió per MacOS X (Unix)"
+
+#: version.c:724
+msgid ""
+"\n"
+"MacOS X version"
+msgstr "\nVersió per MacOS X"
+
+#: version.c:727
+msgid ""
+"\n"
+"MacOS version"
+msgstr "\nVersió per MacOS"
+
+#: version.c:732
+msgid ""
+"\n"
+"RISC OS version"
+msgstr "\nVersió per RISC OS"
+
+#: version.c:742
+msgid ""
+"\n"
+"Included patches: "
+msgstr "\nModificacions incloses: "
+
+#: version.c:768 version.c:1117
+msgid "Modified by "
+msgstr "Modificat per "
+
+#: version.c:775
+msgid ""
+"\n"
+"Compiled "
+msgstr "\nCompilat "
+
+#: version.c:778
+msgid "by "
+msgstr "per "
+
+#: version.c:790
+msgid ""
+"\n"
+"Huge version "
+msgstr "\nVersió enorme "
+
+#: version.c:793
+msgid ""
+"\n"
+"Big version "
+msgstr "\nVersió gran "
+
+#: version.c:796
+msgid ""
+"\n"
+"Normal version "
+msgstr "\nVersió normal "
+
+#: version.c:799
+msgid ""
+"\n"
+"Small version "
+msgstr "\nVersió reduïda "
+
+#: version.c:801
+msgid ""
+"\n"
+"Tiny version "
+msgstr "\nVersió mínima "
+
+#: version.c:807
+msgid "without GUI."
+msgstr "sense GUI."
+
+#: version.c:812
+msgid "with GTK2-GNOME GUI."
+msgstr "amb GUI GTK2-GNOME."
+
+#: version.c:814
+msgid "with GTK-GNOME GUI."
+msgstr "amb GUI GTK-GNOME."
+
+#: version.c:818
+msgid "with GTK2 GUI."
+msgstr "amb GUI GTK2."
+
+#: version.c:820
+msgid "with GTK GUI."
+msgstr "amb GUI GTK."
+
+#: version.c:825
+msgid "with X11-Motif GUI."
+msgstr "amb GUI X11-Motif."
+
+#: version.c:829
+msgid "with X11-neXtaw GUI."
+msgstr "amb GUI X11-neXtaw."
+
+#: version.c:831
+msgid "with X11-Athena GUI."
+msgstr "amb GUI X11-Athena."
+
+#: version.c:835
+msgid "with BeOS GUI."
+msgstr "amb GUI BeOS."
+
+#: version.c:838
+msgid "with Photon GUI."
+msgstr "amb GUI Photon."
+
+#: version.c:841
+msgid "with GUI."
+msgstr "amb GUI."
+
+#: version.c:844
+msgid "with Carbon GUI."
+msgstr "amb GUI Carbon."
+
+#: version.c:847
+msgid "with Cocoa GUI."
+msgstr "amb GUI Cocoa."
+
+#: version.c:850
+msgid "with (classic) GUI."
+msgstr "amb GUI (clàssic)."
+
+#: version.c:861
+msgid " Features included (+) or not (-):\n"
+msgstr " Funcions incloses (+) o excloses (-):\n"
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:873
+msgid " system vimrc file: \""
+msgstr " fitxer vimrc del sistema: \""
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:878
+msgid " user vimrc file: \""
+msgstr " fitxer vimrc de l'usuari: \""
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:883
+msgid " 2nd user vimrc file: \""
+msgstr " 2n fitxer vimrc de l'usuari: \""
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:888
+msgid " 3rd user vimrc file: \""
+msgstr " 3r fitxer vimrc de l'usuari: \""
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:893
+msgid " user exrc file: \""
+msgstr " fitxer exrc de l'usuari: \""
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:898
+msgid " 2nd user exrc file: \""
+msgstr " 2n fitxer exrc de l'usuari: \""
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:904
+msgid " system gvimrc file: \""
+msgstr " fitxer gvimrc del sistema: \""
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:908
+msgid " user gvimrc file: \""
+msgstr " fitxer gvimrc de l'usuari: \""
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:912
+msgid "2nd user gvimrc file: \""
+msgstr "2n fitxer gvimrc de l'usuari: \""
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:917
+msgid "3rd user gvimrc file: \""
+msgstr "3r fitxer gvimrc de l'usuari: \""
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:924
+msgid " system menu file: \""
+msgstr " fitxer de menú del sistema: \""
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:932
+msgid " fall-back for $VIM: \""
+msgstr " alternativa per a $VIM: \""
+
+# 29 caràcters fins el ":" (inclòs)
+#: version.c:938
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " alt per a $VIMRUNTIME: \""
+
+#: version.c:942
+msgid "Compilation: "
+msgstr "Compilat amb: "
+
+#: version.c:948
+msgid "Compiler: "
+msgstr "Compilador: "
+
+#: version.c:953
+msgid "Linking: "
+msgstr "Enllaçat amb: "
+
+#: version.c:958
+msgid " DEBUG BUILD"
+msgstr " VERSIÓ DE DEPURACIÓ"
+
+#: version.c:996
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved"
+
+#: version.c:998
+msgid "version "
+msgstr "versió "
+
+#: version.c:999
+msgid "by Bram Moolenaar et al."
+msgstr "per Bram Moolenaar et al."
+
+#: version.c:1003
+msgid "Vim is open source and freely distributable"
+msgstr "Vim és un programa de codi obert i lliure distribució"
+
+#: version.c:1005
+msgid "Help poor children in Uganda!"
+msgstr "Ajudeu els nens pobres d'Uganda!"
+
+# amplada 53 caràcters
+#: version.c:1006
+msgid "type :help iccf<Enter> for information "
+msgstr "feu :help iccf<Entrar> per més informació "
+
+# amplada 53 caràcters
+#: version.c:1008
+msgid "type :q<Enter> to exit "
+msgstr "feu :q<Entrar> per sortir "
+
+# amplada 53 caràcters
+#: version.c:1009
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "feu :help<Entrar> o <F1> per obtenir ajuda "
+
+# amplada 53 caràcters
+#: version.c:1010
+msgid "type :help version6<Enter> for version info"
+msgstr "feu :help version6<Entrar> per info de la versió "
+
+#: version.c:1013
+msgid "Running in Vi compatible mode"
+msgstr "Funcionant en mode compatible amb Vi"
+
+# amplada 53 caràcters
+#: version.c:1014
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "feu :set nocp<Entrar> pels valors per omissió"
+
+# amplada 53 caràcters
+#: version.c:1015
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "feu :help cp-default<Entrar> per info sobre el tema "
+
+# amplada 53 caràcters
+#: version.c:1030
+msgid "menu Help->Orphans for information "
+msgstr "menú Ajuda->Orfes per informació"
+
+#: version.c:1032
+msgid "Running modeless, typed text is inserted"
+msgstr "Funcionant sense modes, el text escrit s'insereix"
+
+# Això ha de lligar amb la traducció del menú
+# amplada 53 caràcters
+#: version.c:1033
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "menú Edita->Opcions globals->Mode d'inserció "
+
+# amplada 53 caràcters
+#: version.c:1034
+msgid " for two modes "
+msgstr " per dos modes"
+
+# Això ha de lligar amb la traducció del menú
+# amplada 53 caràcters
+#: version.c:1038
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "menú Edita->Opcions globals->Compatible amb Vi "
+
+# amplada 53 caràcters
+#: version.c:1039
+msgid " for Vim defaults "
+msgstr " pels valors per omissió"
+
+#: version.c:1085
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "ATENCIÓ: S'ha detectat Windows 95/98/ME"
+
+# amplada 53 caràcters
+#: version.c:1088
+msgid "type :help windows95<Enter> for info on this"
+msgstr "feu :help windows95<Entrar> per info sobre el tema "
+
+#: window.c:204
+msgid "E441: There is no preview window"
+msgstr "E441: No hi ha cap finestra de previsualització"
+
+#: window.c:582
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: No es pot dividir horitzontal i verticalment al mateix temps"
+
+#: window.c:1341
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E442: No hi pot haver rotació quan hi ha finestres dividides"
+
+#: window.c:1836
+msgid "E444: Cannot close last window"
+msgstr "E444: No es pot tancar l'última finestra"
+
+#: window.c:2567
+msgid "Already only one window"
+msgstr "Només hi ha una finestra"
+
+#: window.c:2614
+msgid "E445: Other window contains changes"
+msgstr "E445: Hi han altres finestres que contenen canvis"
+
+#: window.c:4460
+msgid "E446: No file name under cursor"
+msgstr "E446: No hi ha cap nom de fitxer sota el cursor"
+
+#: window.c:4579
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: No s'ha trobat el fitxer \"%s\" en el path"
+
+#: globals.h:1208 if_perl.xs:363
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: No s'ha pogut carregar la biblioteca %s"
+
+#: if_perl.xs:591
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr "Aquesta ordre no està habilitada: no s'ha pogut carregar la biblioteca Perl."
+
+#: if_perl.xs:637
+#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+#~ msgstr ""
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "Edita en &múltiples Vims"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "Edita en un sol &Vim"
+
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "Mostra les &diferències amb Vim"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "Edita amb el &Vim"
+
+#. Now concatenate
+#: GvimExt/gvimext.cpp:633
+msgid "Edit with existing Vim - &"
+msgstr "Edita amb el Vim existent - &"
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "Edita el(s) fitxer(s) seleccionat(s) amb el Vim"
+
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "Error en crear el procés: Comproveu que gvim es trobi en el path!"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "error de la biblioteca gvimext.dll"
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "La llargada del path és excessiva"
+
+#: globals.h:998
+msgid "--No lines in buffer--"
+msgstr "--Cap línia en el buffer--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1161
+msgid "E470: Command aborted"
+msgstr "E470: S'ha avortat l'ordre"
+
+#: globals.h:1162
+msgid "E471: Argument required"
+msgstr "E471: Es requereix un argument"
+
+#: globals.h:1163
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ hauria de continuar amb /, ? o &"
+
+#: globals.h:1165
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: No és vàlid a la línia d'ordres: <ENTRAR> executa, CTRL-C surt"
+
+#: globals.h:1167
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr "E12: Ordre en exrc/vimrc no permesa en l'actual cerca d'etiquetes o directoris"
+
+#: globals.h:1169
+msgid "E171: Missing :endif"
+msgstr "E171: Falta una declaració :endif"
+
+#: globals.h:1170
+msgid "E600: Missing :endtry"
+msgstr "E600: Falta una declaració :endtry"
+
+#: globals.h:1171
+msgid "E170: Missing :endwhile"
+msgstr "E170: Falta una declaració :endwhile"
+
+#: globals.h:1172
+msgid "E588: :endwhile without :while"
+msgstr "E588: Declaració :endwhile sense :while"
+
+#: globals.h:1174
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: El fitxer existeix (afegiu ! per confirmar)"
+
+#: globals.h:1175
+msgid "E472: Command failed"
+msgstr "E472: L'ordre ha fallat"
+
+#: globals.h:1177
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Conjunt de tipus desconegut: %s"
+
+#: globals.h:1181
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Tipus de lletra desconegut: %s"
+
+#: globals.h:1184
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: El tipus de lletra \"%s\" no és d'amplada fixa"
+
+#: globals.h:1186
+msgid "E473: Internal error"
+msgstr "E473: Error intern"
+
+#: globals.h:1187
+msgid "Interrupted"
+msgstr "Interromput"
+
+#: globals.h:1188
+msgid "E14: Invalid address"
+msgstr "E14: L'adreça no és vàlida"
+
+#: globals.h:1189
+msgid "E474: Invalid argument"
+msgstr "E474: L'argument no és vàlid"
+
+#: globals.h:1190
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: L'argument no és vàlid: %s"
+
+#: globals.h:1192
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: L'expressió no és vàlida: %s"
+
+#: globals.h:1194
+msgid "E16: Invalid range"
+msgstr "E16: L'interval no és vàlid"
+
+#: globals.h:1195
+msgid "E476: Invalid command"
+msgstr "E476: L'ordre no és vàlida"
+
+#: globals.h:1197
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" és un directori"
+
+#: globals.h:1200
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Caràcters inesperats abans de '='"
+
+#: globals.h:1203
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: La crida a la biblioteca a fallat per \"%s()\""
+
+#: globals.h:1209
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: No s'ha pogut carregar la funció %s"
+
+#: globals.h:1211
+msgid "E19: Mark has invalid line number"
+msgstr "E19: Marca amb un número de línia no vàlid"
+
+#: globals.h:1212
+msgid "E20: Mark not set"
+msgstr "E20: Marca no establerta"
+
+#: globals.h:1213
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: No es poden fer canvis, l'opció 'modifiable' està desactivada"
+
+#: globals.h:1214
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Imbricació d'scripts massa profunda"
+
+#: globals.h:1215
+msgid "E23: No alternate file"
+msgstr "E23: No hi ha cap fitxer alternatiu"
+
+#: globals.h:1216
+msgid "E24: No such abbreviation"
+msgstr "E24: No existeix tal abreviació"
+
+#: globals.h:1217
+msgid "E477: No ! allowed"
+msgstr "E477: ! no permès"
+
+#: globals.h:1219
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: No es pot usar la GUI: No ha estat compilada"
+
+#: globals.h:1222
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: No es pot usar el mode Hebreu: No ha estat compilat\n"
+
+#: globals.h:1225
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: No es pot usar el mode Farsi: No ha estat compilat\n"
+
+#: globals.h:1228
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: No es pot usar el mode àrab: No ha estat compilat\n"
+
+#: globals.h:1231
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: No existeix tal grup de ressalt: %s"
+
+#: globals.h:1233
+msgid "E29: No inserted text yet"
+msgstr "E29: Encara no s'ha inserit text"
+
+#: globals.h:1234
+msgid "E30: No previous command line"
+msgstr "E30: No hi ha cap ordre anterior"
+
+#: globals.h:1235
+msgid "E31: No such mapping"
+msgstr "E31: No existeix tal assignació"
+
+#: globals.h:1236
+msgid "E479: No match"
+msgstr "E479: Cap coincidència"
+
+#: globals.h:1237
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: Cap coincidència: %s"
+
+#: globals.h:1238
+msgid "E32: No file name"
+msgstr "E32: Falta un nom de fitxer"
+
+#: globals.h:1239
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: No hi ha cap expressió de substitució anterior"
+
+#: globals.h:1240
+msgid "E34: No previous command"
+msgstr "E34: No hi ha cap ordre anterior"
+
+#: globals.h:1241
+msgid "E35: No previous regular expression"
+msgstr "E35: No hi ha cap expressió regular anterior"
+
+#: globals.h:1242
+msgid "E481: No range allowed"
+msgstr "E481: No es permet cap interval"
+
+#: globals.h:1244
+msgid "E36: Not enough room"
+msgstr "E36: No hi ha prou espai"
+
+#: globals.h:1247
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: No hi ha cap servidor registrat amb aquest nom \"%s\""
+
+#: globals.h:1249
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: No es pot crear el fitxer %s"
+
+#: globals.h:1250
+msgid "E483: Can't get temp file name"
+msgstr "E483: No s'ha pogut obtenir el nom del fitxer temporal"
+
+#: globals.h:1251
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: No es pot obrir el fitxer %s"
+
+#: globals.h:1252
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: No es pot llegir el fitxer %s"
+
+#: globals.h:1253
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: No s'han desat els canvis (afegiu ! per confirmar)"
+
+#: globals.h:1254
+msgid "E38: Null argument"
+msgstr "E38: Argument nul"
+
+#: globals.h:1256
+msgid "E39: Number expected"
+msgstr "E39: S'esperava un número"
+
+#: globals.h:1259
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: No s'ha pogut obrir el fitxer d'errors %s"
+
+#: globals.h:1262
+msgid "E233: cannot open display"
+msgstr "E233: No s'ha pogut obrir la pantalla"
+
+#: globals.h:1264
+msgid "E41: Out of memory!"
+msgstr "E41: Memòria exhaurida!"
+
+#: globals.h:1266
+msgid "Pattern not found"
+msgstr "No s'ha trobat el patró"
+
+#: globals.h:1268
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: No s'ha trobat el patró: %s"
+
+#: globals.h:1269
+msgid "E487: Argument must be positive"
+msgstr "E487: L'argument ha de ser un número positiu"
+
+#: globals.h:1271
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: No es pot tornar al directori anterior"
+
+#: globals.h:1275
+msgid "E42: No Errors"
+msgstr "E42: No hi han errors"
+
+#: globals.h:1277
+msgid "E43: Damaged match string"
+msgstr "E43: S'ha corromput la cadena amb l'expressió regular"
+
+#: globals.h:1278
+msgid "E44: Corrupted regexp program"
+msgstr "E44: S'ha corromput el programa d'expressió regular"
+
+#: globals.h:1279
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: L'opció 'readonly' està definida (afegiu ! per confirmar)"
+
+#: globals.h:1281
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: No s'ha pogut definir la variable de només lectura \"%s\""
+
+#: globals.h:1284
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Error en llegir el fitxer d'errors"
+
+#: globals.h:1287
+#~ msgid "E48: Not allowed in sandbox"
+#~ msgstr ""
+
+#: globals.h:1289
+msgid "E523: Not allowed here"
+msgstr "E523: No està permès aquí"
+
+#: globals.h:1292
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: La funció d'ajustar el mode de pantalla no està suportada"
+
+#: globals.h:1294
+msgid "E49: Invalid scroll size"
+msgstr "E49: La distància de desplaçament no és vàlida"
+
+#: globals.h:1295
+msgid "E91: 'shell' option is empty"
+msgstr "E91: L'opció 'shell' no conté res"
+
+#: globals.h:1297
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: No s'han pogut llegir les dades del senyal!"
+
+#: globals.h:1299
+msgid "E72: Close error on swap file"
+msgstr "E72: Error en tancar el fitxer d'intercanvi"
+
+#: globals.h:1300
+msgid "E73: tag stack empty"
+msgstr "E73: La pila d'etiquetes està buida"
+
+#: globals.h:1301
+msgid "E74: Command too complex"
+msgstr "E74: L'ordre és massa complexa"
+
+#: globals.h:1302
+msgid "E75: Name too long"
+msgstr "E75: El nom és massa llarg"
+
+#: globals.h:1303
+msgid "E76: Too many ["
+msgstr "E76: Sobren caràcters ["
+
+#: globals.h:1304
+msgid "E77: Too many file names"
+msgstr "E77: Sobren noms de fitxer"
+
+#: globals.h:1305
+msgid "E488: Trailing characters"
+msgstr "E488: Sobren caràcters"
+
+#: globals.h:1306
+msgid "E78: Unknown mark"
+msgstr "E78: La marca és desconeguda"
+
+#: globals.h:1307
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: No s'ha pogut expandir el nom de fitxer"
+
+#: globals.h:1309
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: L'opció 'winheight' no pot ser menor que 'winminheight'"
+
+#: globals.h:1311
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: L'opció 'winwidth' no pot ser menor que 'winminwidth'"
+
+#: globals.h:1314
+msgid "E80: Error while writing"
+msgstr "E80: Error d'escriptura"
+
+#: globals.h:1315
+msgid "Zero count"
+msgstr "Comptador a zero"
+
+#: globals.h:1317
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: Ús de <SID> en un context equivocat"
+
+#: globals.h:1320
+msgid "E449: Invalid expression received"
+msgstr "E449: S'ha rebut una expressió no vàlida"
+
+#: globals.h:1323
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: La regió està protegida, no es pot modificar"
diff --git a/src/po/cleanup.vim b/src/po/cleanup.vim
new file mode 100644
index 000000000..cb697e8b1
--- /dev/null
+++ b/src/po/cleanup.vim
@@ -0,0 +1,7 @@
+" Vim script to cleanup a .po file: comment-out fuzzy and empty messages.
+" Make sure there is a space before the string (required for Solaris).
+" Requires Vim 6.0 (because of multi-line search patterns).
+g/^#, fuzzy\(, .*\)\=\nmsgid ""\@!/.+1,/^$/-1s/^/#\~ /
+g/^msgstr"/s//msgstr "/
+g/^msgid"/s//msgid "/
+g/^msgstr ""\(\n"\)\@!/?^msgid?,.s/^/#\~ /
diff --git a/src/po/cs.cp1250.po b/src/po/cs.cp1250.po
new file mode 100644
index 000000000..04370dc07
--- /dev/null
+++ b/src/po/cs.cp1250.po
@@ -0,0 +1,5954 @@
+# Czech translation of vim
+# Jiøí Pavlovský <jpavlovsky@mbox.vol.cz>, 2000 - 2002.
+# Some completion for vim6.0 added by Jiøí Bøezina <brz@centrum.cz>
+# Some bugfixes by Tomáš Zellerin <zellerin@volny.cz>
+#
+# Generated from cs.po, DO NOT EDIT.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: vim-6.0\n"
+"POT-Creation-Date: 2001-10-08 08:27-0700\n"
+"PO-Revision-Date: 2002-02-06 22:29+0100\n"
+"Last-Translator: Jiøí Pavlovský <jpavlovsky@mbox.vol.cz>\n"
+"Language-Team: Czech <cs@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=cp1250\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Nelze alokovat žádný buffer, konèím..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: Nelze alokovat buffer, použiji jiný..."
+
+#: buffer.c:698
+msgid "No buffers were unloaded"
+msgstr "Žádný buffer nebyl deaktivován"
+
+#: buffer.c:700
+msgid "No buffers were deleted"
+msgstr "Žádný buffer nebyl smazán"
+
+#: buffer.c:702
+msgid "No buffers were wiped out"
+msgstr "Žádný buffer nebyl zahozen"
+
+#: buffer.c:710
+msgid "1 buffer unloaded"
+msgstr "Poèet deaktivovaných bufferù: 1"
+
+#: buffer.c:712
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "Poèet deaktivovaných bufferù: %d"
+
+#: buffer.c:717
+msgid "1 buffer deleted"
+msgstr "Poèet smazaných bufferù: 1"
+
+#: buffer.c:719
+#, c-format
+msgid "%d buffers deleted"
+msgstr "Poèet smazaných bufferù: %d"
+
+#: buffer.c:724
+msgid "1 buffer wiped out"
+msgstr "Poèet zahozených bufferù: 1"
+
+#: buffer.c:726
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "Poèet zahozených bufferù: %d"
+
+#: buffer.c:783
+msgid "E84: No modified buffer found"
+msgstr "E84: Nebyl nalezen žádný zmìnìný buffer"
+
+#. back where we started, didn't find anything.
+#: buffer.c:822
+msgid "E85: There is no listed buffer"
+msgstr "E85: Seznam bufferù je prázdný"
+
+#: buffer.c:834
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: Nelze pøeskoèit na buffer %ld"
+
+#: buffer.c:837
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Za poslední buffer nelze pøeskoèit"
+
+#: buffer.c:839
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Pøed první buffer nelze pøeskoèit"
+
+#: buffer.c:863
+#, c-format
+msgid "E89: No write since last change for buffer %ld (use ! to override)"
+msgstr "E89: Zmìny v bufferu %ld nebyly uloženy (! pro vynucení)"
+
+#: buffer.c:879
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: Poslední buffer nelze deaktivovat"
+
+#: buffer.c:1314
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Varování: pøeteèení seznamu s názvy souborù"
+
+#: buffer.c:1480
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: Buffer %ld nenalezen"
+
+#: buffer.c:1700
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Vzoru %s vyhovuje více bufferù"
+
+#: buffer.c:1702
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: Vzoru %s nevyhovuje žádný buffer"
+
+#: buffer.c:2105 ex_docmd.c:6065
+#, c-format
+msgid "line %ld"
+msgstr "øádek %ld"
+
+#: buffer.c:2188
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Buffer tohoto jména již existuje"
+
+#: buffer.c:2481
+msgid " [Modified]"
+msgstr " [Zmìnìný]"
+
+#: buffer.c:2486
+msgid "[Not edited]"
+msgstr "[Needitovaný]"
+
+#: buffer.c:2491
+msgid "[New file]"
+msgstr "[Nový soubor]"
+
+#: buffer.c:2492
+msgid "[Read errors]"
+msgstr "[Chyby pøi ètení]"
+
+#: buffer.c:2494 fileio.c:1754
+msgid "[readonly]"
+msgstr "[Pouze pro ètení]"
+
+#: buffer.c:2510
+msgid "1 line --%d%%--"
+msgstr "øádkù: --%d%%--"
+
+#: buffer.c:2510
+msgid "%ld lines --%d%%--"
+msgstr "øádkù: %ld --%d%%--"
+
+#: buffer.c:2518
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "øádek %ld/%ld --%d%%-- sloupec"
+
+#: buffer.c:2606
+msgid "[No file]"
+msgstr "[Žádný soubor]"
+
+#. must be a help buffer
+#: buffer.c:2646
+msgid "help"
+msgstr "nápovìda"
+
+#: buffer.c:3151 screen.c:4671
+msgid "[help]"
+msgstr "[nápovìda]"
+
+#: buffer.c:3183 screen.c:4677
+msgid "[Preview]"
+msgstr "[náhled]"
+
+#: buffer.c:3389
+msgid "All"
+msgstr "Vše"
+
+#: buffer.c:3389
+msgid "Bot"
+msgstr "Konec"
+
+#: buffer.c:3391
+msgid "Top"
+msgstr "Zaèátek"
+
+#: buffer.c:4127
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# Seznam bufferù:\n"
+
+#: buffer.c:4160
+msgid "[Error List]"
+msgstr "[seznam chyb]"
+
+#: buffer.c:4173 memline.c:1513
+msgid "[No File]"
+msgstr "[žádný soubor]"
+
+#: buffer.c:4393
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Znaky ---"
+
+#: buffer.c:4403
+#, c-format
+msgid "Signs for %s:"
+msgstr "Znaky pro %s:"
+
+#: buffer.c:4409
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " øádek=%ld id=%d jméno=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: Nelze pøekroèit maximální poèet %ld diff bufferù"
+
+#: diff.c:648
+msgid "E97: Cannot create diffs"
+msgstr "E97: Nelze vytvoøit diffy"
+
+#: diff.c:747
+msgid "Patch file"
+msgstr "Soubor se záplatou"
+
+#: diff.c:991
+msgid "E98: Cannot read diff output"
+msgstr "E98: Nelze èíst výstup programu diff"
+
+#: diff.c:1704
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Aktuální buffer není v diff režimu"
+
+#: diff.c:1716
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: To byl poslední buffer v diff režimu"
+
+#: diff.c:1724
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: V diff režimu jsou více než dva buffery. Nevím, který mám použít."
+
+#: diff.c:1747
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Nelze nalézt buffer \"%s\""
+
+#: diff.c:1753
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Buffer \"%s\" není v diff režimu"
+
+#: digraph.c:2168
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: digraph nesmí obsahovat Escape"
+
+#: digraph.c:2340
+msgid "Keymap file not found"
+msgstr "Soubor s mapou klávesnice nebyl nalezen"
+
+#: digraph.c:2367
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: :loadkeymap mimo interpretovaný soubor"
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " Doplòování klíèových slov (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " ^X režim (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " Lokální doplòování klíèových slov (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " Doplòování celých øádkù (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " Doplòování názvù souborù (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " Doplòování tagù (^I/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " Doplòování vzoru cest (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " Doplòování definic (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " Doplòování podle slovníku (^K/^N/^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Doplòování podle tezauru (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " Doplòování pøíkazové øádky (^I/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Konec odstavce"
+
+#: edit.c:894
+msgid "'thesaurus' option is empty"
+msgstr "volba 'thesaurus' je prázdná"
+
+#: edit.c:1070
+msgid "'dictionary' option is empty"
+msgstr "volba 'dictionary' je prázdná"
+
+#: edit.c:1992
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Prohledávám slovník %s"
+
+#: edit.c:2183
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (insert) Rolování (^E/^Y)"
+
+#: edit.c:2185
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (replace) Rolování (^E/^Y)"
+
+#: edit.c:2496
+#, c-format
+msgid "Scanning: %s"
+msgstr "Prohledávám %s"
+
+#: edit.c:2531
+msgid "Scanning tags."
+msgstr "Prohledávám tagy"
+
+#: edit.c:3189
+msgid " Adding"
+msgstr "Pøidávám"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3238
+msgid "-- Searching..."
+msgstr "-- Hledám..."
+
+#: edit.c:3294
+msgid "Back at original"
+msgstr "Výchozí podoba"
+
+#: edit.c:3299
+msgid "Word from other line"
+msgstr "Slovo z jiného øádku"
+
+#: edit.c:3304
+msgid "The only match"
+msgstr "Jediná shoda"
+
+#: edit.c:3363
+#, c-format
+msgid "match %d of %d"
+msgstr "shoda %d/%d"
+
+#: edit.c:3366
+#, c-format
+msgid "match %d"
+msgstr "shoda %d"
+
+#: eval.c:696
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Neznámá promìnná: \"%s\""
+
+#: eval.c:975
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Chybí závorky: %s"
+
+#: eval.c:1043
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Promìnná \"%s\" neexistuje"
+
+#: eval.c:1284
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Po '?' chybí ':'"
+
+#: eval.c:1898
+msgid "E110: Missing ')'"
+msgstr "E110: Chybìjící ')'"
+
+#: eval.c:1948
+msgid "E111: Missing ']'"
+msgstr "E111: Chybìjící ']'"
+
+#: eval.c:2023
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Chybí jméno volby: %s"
+
+#: eval.c:2041
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Neznámá volba: %s"
+
+#: eval.c:2103
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Chybí uvozovky: %s"
+
+#: eval.c:2220
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Chybí uvozovky: %s"
+
+#: eval.c:2537
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Chybné argumenty pro funkci %s"
+
+#: eval.c:2538
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Neznámá funkce: %s"
+
+#: eval.c:2539
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: Pøíliš mnoho argumentù pro funkci %s"
+
+#: eval.c:2540
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Pøíliš málo argumentù pro funkci %s"
+
+#: eval.c:2541
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: Použití <SID> mimo kontext skriptu: %s"
+
+#: eval.c:3575
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld øádkù:"
+
+#: eval.c:4690
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&OK\n"
+"&Zrušit"
+
+#: eval.c:5513
+msgid "E240: No connection to Vim server"
+msgstr "E240: Neexistuje pøipojení k Vim serveru"
+
+#: eval.c:5603
+msgid "E277: Unable to read a server reply"
+msgstr "E277: Nelze èíst odpovìï serveru"
+
+#: eval.c:5628
+msgid "E258: Unable to send to client"
+msgstr "E258: Nelze pøedat klientovi"
+
+#: eval.c:5669
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Nelze pøedat do %s"
+
+#: eval.c:5767
+msgid "(Invalid)"
+msgstr "(Chybný)"
+
+#: eval.c:6770
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Nedefinovaná promìnná: %s"
+
+#: eval.c:7468
+#, c-format
+msgid "E122: Function %s already exists, use ! to replace"
+msgstr "E122: Funkce %s již existuje. Použijte ! pro její nahrazení."
+
+#: eval.c:7510
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Nedefinovaná funkce: %s"
+
+#: eval.c:7523
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Chybí '(': %s"
+
+#: eval.c:7555
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Nepøípustný argument: %s"
+
+#: eval.c:7641
+msgid "E126: Missing :endfunction"
+msgstr "E126: Chybí :endfunction"
+
+#: eval.c:7720
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Nelze pøedefinovat funkci %s: je používána"
+
+#: eval.c:7777
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: Název funkce musí zaèínat velkým písmenem: %s"
+
+#: eval.c:7783
+msgid "E129: Function name required"
+msgstr "E129: Je vyžadováno jméno funkce"
+
+#: eval.c:7876
+msgid "function "
+msgstr "funkce "
+
+#: eval.c:7991
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Nedefinovaná funkce: %s"
+
+#: eval.c:7996
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Nelze smazat funkci %s: je již používána"
+
+#: eval.c:8043
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: Zanoøení funkce je hlubší než 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:8094
+#, c-format
+msgid "calling %s"
+msgstr "volám %s"
+
+#. always scroll up, don't overwrite
+#: eval.c:8119 ex_cmds2.c:1973
+#, c-format
+msgid "continuing in %s"
+msgstr "pokraèuji v %s"
+
+#: eval.c:8173
+msgid "E133: :return not inside a function"
+msgstr "E133: :return mimo funkci"
+
+#: eval.c:8251
+#, c-format
+msgid "%s returning #%ld"
+msgstr "dokonèeno provádìní %s. Návratová hodnota #%ld"
+
+#: eval.c:8254
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "dokonèeno provádìní %s. Návratová hodnota \"%s\""
+
+#: eval.c:8395
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# globální promìnné:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, šestnáctkovì %02x, osmièkovì %03o"
+
+#: ex_cmds.c:428
+msgid "E134: Move lines into themselves"
+msgstr "E134: Nelze pøesunout øádky na pùvodní místo"
+
+#: ex_cmds.c:497
+msgid "1 line moved"
+msgstr "poèet pøesunutých øádkù: 1"
+
+#: ex_cmds.c:499
+#, c-format
+msgid "%ld lines moved"
+msgstr "Poèet pøesunutých øádkù: %ld"
+
+#: ex_cmds.c:890
+#, c-format
+msgid "%ld lines filtered"
+msgstr "Poèet filtrovaných øádkù: %ld"
+
+#: ex_cmds.c:918
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: Automatické pøíkazy *Filter* nesmí mìnit aktuální buffer"
+
+#: ex_cmds.c:1003
+msgid "[No write since last change]\n"
+msgstr "[Neuložené zmìny]\n"
+
+#: ex_cmds.c:1248
+#, c-format
+msgid "viminfo: %s in line: "
+msgstr "viminfo: %s na øádku: "
+
+#: ex_cmds.c:1253
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: pøíliš mnoho chyb, pøeskakuji zbytek souboru"
+
+#: ex_cmds.c:1282
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Ètu viminfo soubor \"%s\"%s%s%s"
+
+#: ex_cmds.c:1283
+msgid " info"
+msgstr " informace"
+
+#: ex_cmds.c:1284
+msgid " marks"
+msgstr " znaèky"
+
+#: ex_cmds.c:1285
+msgid " FAILED"
+msgstr " se nezdaøilo"
+
+#: ex_cmds.c:1376
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: do viminfo souboru %s nelze zapisovat"
+
+#: ex_cmds.c:1501
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Nelze uložit viminfo soubor %s!"
+
+#: ex_cmds.c:1509
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Ukládám viminfo souboru \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1610
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Tento viminfo soubor byl vytvoøen editorem Vim %s.\n"
+
+#: ex_cmds.c:1612
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Pokud budete opatrný, mùžete jej upravovat.\n"
+"\n"
+
+#: ex_cmds.c:1614
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Hodnota volby 'encoding' v dobì uložení tohoto souboru\n"
+
+#: ex_cmds.c:1713
+msgid "Illegal starting char"
+msgstr "Nepøípustný poèáteèní znak"
+
+#: ex_cmds.c:2053 ex_cmds.c:2289 ex_cmds2.c:602
+msgid "Save As"
+msgstr "Uložit jako"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2096
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Soubor je nahrán v jiném bufferu"
+
+#: ex_cmds.c:2130
+msgid "Write partial file?"
+msgstr "Uložit neúplný soubor?"
+
+#: ex_cmds.c:2137
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Použijte ! pro uložení neúplného bufferu"
+
+#: ex_cmds.c:2223
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Pøepsat soubor \"%.*s\"?"
+
+#: ex_cmds.c:2294
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: Žádný název souboru pro buffer %ld"
+
+#: ex_cmds.c:2332
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: Soubor nebyl uložen: Ukládání je zakázáno volbou 'write'"
+
+#: ex_cmds.c:2352
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"Pro \"%.*s\" je nastavena volba 'readonly'.\n"
+"Pøejete si ji potlaèit?"
+
+#: ex_cmds.c:2517
+msgid "Edit File"
+msgstr "Editovat soubor"
+
+#: ex_cmds.c:3024
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Automatické pøíkazy neoèekávanì smazaly nový buffer %s"
+
+#: ex_cmds.c:3156
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: neèíselný argument pro :z"
+
+#: ex_cmds.c:3241
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: rvim nepovoluje použití pøíkazù shellu"
+
+#: ex_cmds.c:3348
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Regulární výrazy nesmí být oddìleny písmeny"
+
+#: ex_cmds.c:3686
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "nahradit za %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4050
+msgid "(Interrupted) "
+msgstr "(Pøerušeno) "
+
+#: ex_cmds.c:4054
+msgid "1 substitution"
+msgstr "1 nahrazení"
+
+#: ex_cmds.c:4056
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld nahrazení"
+
+#: ex_cmds.c:4059
+msgid " on 1 line"
+msgstr " na jednom øádku"
+
+#: ex_cmds.c:4061
+#, c-format
+msgid " on %ld lines"
+msgstr " na %ld øádcích"
+
+#: ex_cmds.c:4112
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :global nelze volat rekurzivnì"
+
+#: ex_cmds.c:4147
+msgid "E148: Regular expression missing from global"
+msgstr "E148: U pøíkazu 'global' chybí regulární výraz"
+
+#: ex_cmds.c:4196
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Vzor nalezen na každém øádku: %s"
+
+#: ex_cmds.c:4277
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Poslední nahrazující øetìzec:\n"
+"$"
+
+#: ex_cmds.c:4376
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Lituji, pro %s není žádná nápovìda"
+
+#: ex_cmds.c:4410
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Lituji, soubor \"%s\" s nápovìdou nebyl nalezen"
+
+#: ex_cmds.c:4856
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s není adresáøem"
+
+#: ex_cmds.c:4884
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: Nelze otevøít %s pro zápis"
+
+#: ex_cmds.c:4898
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Nelze otevøít %s pro zápis"
+
+#: ex_cmds.c:4977
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: Duplicitní tag \"%s\" v souboru %s"
+
+#: ex_cmds.c:5078
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Neznámá volba pøíkazu: %s"
+
+#: ex_cmds.c:5098
+msgid "E156: Missing sign name"
+msgstr "E156: Chybí jméno volby"
+
+#: ex_cmds.c:5144
+msgid "E255: Too many signs defined"
+msgstr "E255: Nastaveno pøíliš mnoho voleb"
+
+#: ex_cmds.c:5186
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Neplatný text volby: %s"
+
+#: ex_cmds.c:5210 ex_cmds.c:5396
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Neznámá volba: %s"
+
+#: ex_cmds.c:5256
+msgid "E159: Missing sign number"
+msgstr "E159: Chybí identifikátor volby"
+
+#: ex_cmds.c:5336
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: chybné jméno bufferu: %s"
+
+#: ex_cmds.c:5375
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Chybné ID volby: %ld"
+
+#: ex_cmds.c:5546
+msgid "[Deleted]"
+msgstr "[Vymazáno]"
+
+#: ex_cmds2.c:70
+msgid "Entering Debug mode. Type \"cont\" to leave."
+msgstr "Spouštím ladící režim. Pro ukonèení napište \"cont\"."
+
+#: ex_cmds2.c:74 ex_docmd.c:771
+#, c-format
+msgid "line %ld: %s"
+msgstr "øádek %ld: %s"
+
+#: ex_cmds2.c:76
+#, c-format
+msgid "cmd: %s"
+msgstr "pøíkaz: %s"
+
+#: ex_cmds2.c:224
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Bod pøerušení v \"%s%s\" na øádku %ld"
+
+#: ex_cmds2.c:388
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Bod pøerušení nenalezen: %s"
+
+#: ex_cmds2.c:414
+msgid "No breakpoints defined"
+msgstr "Nebyly definovánu žádné body pøerušení"
+
+#: ex_cmds2.c:419
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s øádek %ld"
+
+#: ex_cmds2.c:625
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Uložit zmìny do \"%.*s\"?"
+
+#: ex_cmds2.c:627 ex_docmd.c:8612
+msgid "Untitled"
+msgstr "Nepojmenováno"
+
+#: ex_cmds2.c:763
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Buffer \"%s\" obsahuje neuložené zmìny"
+
+#: ex_cmds2.c:832
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr ""
+"Varování: Neèekaný vstup do jiného bufferu (zkontrolujte automatické pøíkazy)"
+
+#: ex_cmds2.c:1208
+msgid "E163: There is only one file to edit"
+msgstr "E163: Pro editaci byl zadán pouze jeden soubor"
+
+#: ex_cmds2.c:1210
+msgid "E164: Cannot go before first file"
+msgstr "E164: Pøed první soubor nelze pøeskoèit"
+
+#: ex_cmds2.c:1212
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Za poslední soubor nelze pøeskoèit"
+
+#: ex_cmds2.c:1632
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Hledám \"%s\" v \"%s\""
+
+#: ex_cmds2.c:1654
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Hledám \"%s\""
+
+#: ex_cmds2.c:1678
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "soubor \"%s\" nebyl nalezen v 'runtimepath'"
+
+#: ex_cmds2.c:1712
+msgid "Run Macro"
+msgstr "Spustit makro"
+
+#: ex_cmds2.c:1817
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "nelze interpretovat adresáø: \"%s\""
+
+#: ex_cmds2.c:1847
+#, c-format
+msgid "could not source \"%s\""
+msgstr "nelze interpretovat \"%s\""
+
+#: ex_cmds2.c:1849
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "øádek %ld: nelze interpretovat \"%s\""
+
+#: ex_cmds2.c:1863
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "interpretuji \"%s\""
+
+#: ex_cmds2.c:1865
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "øádek %ld: interpretuji %s"
+
+#: ex_cmds2.c:1971
+#, c-format
+msgid "finished sourcing %s"
+msgstr "dokonèena interpretace %s"
+
+#: ex_cmds2.c:2272
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Varování: chybný oddìlovaè øádkù. Možná chybí ^M."
+
+#: ex_cmds2.c:2321
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :scriptencoding použito mimo interpretovaný soubor"
+
+#: ex_cmds2.c:2354
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish použito mimo interpretovaný soubor"
+
+#: ex_cmds2.c:2820
+msgid "No text to be printed"
+msgstr "Žádný text k vytištìní"
+
+#: ex_cmds2.c:2898
+msgid "Printing page %d (%d%%)"
+msgstr "Tisknu stranu %d (%d%%)"
+
+#: ex_cmds2.c:2907
+#, c-format
+msgid " Copy %d of %d"
+msgstr " Kopie %d z %d"
+
+#: ex_cmds2.c:2959
+#, c-format
+msgid "Printed: %s"
+msgstr "Vytištìno: %s"
+
+#: ex_cmds2.c:2966
+msgid "Printing aborted"
+msgstr "Tisk zrušen"
+
+#: ex_cmds2.c:3344
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Nelze zapisovat do výstupního PostScriptového souboru"
+
+#: ex_cmds2.c:4019
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Nelze otevøít výstupní PostScriptový soubor"
+
+#: ex_cmds2.c:4057
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Nelze otevøít soubor \"%s\""
+
+#: ex_cmds2.c:4068
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Nelze èíst zdrojový PostScriptový soubor \"%s\""
+
+#: ex_cmds2.c:4266
+msgid "Sending to printer..."
+msgstr "Odesílám na tiskárnu..."
+
+#: ex_cmds2.c:4270
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: Selhal tisk PostScriptového souboru"
+
+#: ex_cmds2.c:4272
+msgid "Print job sent."
+msgstr "Tisková úloha odeslána."
+
+#: ex_cmds2.c:4651
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Aktuální %sjazyk: \"%s\""
+
+#: ex_cmds2.c:4658
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Nelze nastavit jazyk na \"%s\""
+
+#: ex_docmd.c:491
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Spouštím Ex mód. Napište \"visual\" pro návrat do normálního módu."
+
+#. must be at EOF
+#: ex_docmd.c:527
+msgid "At end-of-file"
+msgstr "Konec souboru"
+
+#: ex_docmd.c:602
+msgid "E169: Command too recursive"
+msgstr "E169: Pøíkaz je pøíliš rekurzivní"
+
+#: ex_docmd.c:911
+msgid "E170: Missing :endwhile"
+msgstr "E170: Chybí :endwhile"
+
+#: ex_docmd.c:913
+msgid "E171: Missing :endif"
+msgstr "E171: Chybí :endif"
+
+#: ex_docmd.c:923
+msgid "End of sourced file"
+msgstr "Konec interpretovaného souboru"
+
+#: ex_docmd.c:924
+msgid "End of function"
+msgstr "Konec funkce"
+
+#: ex_docmd.c:1344
+msgid "Ambiguous use of user-defined command"
+msgstr "Nejednoznaèné použití uživatelsky definovaného pøíkazu"
+
+#: ex_docmd.c:1358
+msgid "Not an editor command"
+msgstr "Není pøíkazem editoru"
+
+#: ex_docmd.c:1441
+msgid "Don't panic!"
+msgstr "Nepanikaøte!"
+
+#: ex_docmd.c:1460
+msgid "Backwards range given"
+msgstr "Zadán zpìtný rozsah"
+
+#: ex_docmd.c:1469
+msgid "Backwards range given, OK to swap"
+msgstr "Zadán zpìtný rozsah. Prohodit hranice"
+
+#: ex_docmd.c:1580
+msgid "Use w or w>>"
+msgstr "Použijte w èi w>>"
+
+#: ex_docmd.c:3086
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Pøíkaz není této verzi bohužel implementován"
+
+#: ex_docmd.c:3256
+msgid "E172: Only one file name allowed"
+msgstr "E172: Pøípustný je pouze jeden název souboru"
+
+#: ex_docmd.c:3810
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "Ještì zbývají soubory k editaci (%d). Chcete pøesto ukonèit editor?"
+
+#: ex_docmd.c:3817
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: Ještì zbývají soubory k editaci (%ld)."
+
+#: ex_docmd.c:3911
+msgid "E174: Command already exists: use ! to redefine"
+msgstr "E174: Pøíkaz již existuje: použijte ! pro pøedefinování"
+
+#: ex_docmd.c:4016
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Jméno Args Rozsah Úplnost Definice"
+
+#: ex_docmd.c:4105
+msgid "No user-defined commands found"
+msgstr "Nebyly nalezeny žádné uživatelsky definované pøíkazy"
+
+#: ex_docmd.c:4136
+msgid "E175: No attribute specified"
+msgstr "E175: Nebyly zadány žádné atributy"
+
+#: ex_docmd.c:4188
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Chybný poèet argumentù"
+
+#: ex_docmd.c:4203
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: Opakování nemùže být zadáno dvakrát"
+
+#: ex_docmd.c:4213
+msgid "E178: Invalid default value for count"
+msgstr "E178: Chybná implicitní hodnota pro poèet"
+
+#: ex_docmd.c:4241
+msgid "E179: argument required for complete"
+msgstr "E179: chybná implicitní hodnota pro opakování"
+
+#: ex_docmd.c:4260
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Chybná hodnota doplnìní: %s"
+
+#: ex_docmd.c:4268
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Chybný atribut: %s"
+
+#: ex_docmd.c:4309
+msgid "E182: Invalid command name"
+msgstr "E182: Chybné jméno pøíkazu"
+
+#: ex_docmd.c:4324
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: Uživatelsky definované pøíkazy musí zaèínat velikým písmenem."
+
+#: ex_docmd.c:4393
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: Uživatelsky definovaný pøíkaz %s neexistuje"
+
+#: ex_docmd.c:4844
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Nelze nalézt barevné schéma %s"
+
+#: ex_docmd.c:4852
+msgid "Greetings, Vim user!"
+msgstr "Blahopøeji, uživateli Vimu!"
+
+#: ex_docmd.c:5549
+msgid "Edit File in new window"
+msgstr "Editovat soubor v novém oknì"
+
+#: ex_docmd.c:5815
+msgid "No swap file"
+msgstr "Žádný odkládací soubor"
+
+#: ex_docmd.c:5919
+msgid "Append File"
+msgstr "Uložit soubor"
+
+#: ex_docmd.c:5978
+msgid "E186: No previous directory"
+msgstr "E186: Žádný pøedchozí adresáø"
+
+#: ex_docmd.c:6055
+msgid "E187: Unknown"
+msgstr "E187: Neznámý"
+
+#: ex_docmd.c:6173
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Umístìní okna: X %d, Y %d"
+
+#: ex_docmd.c:6178
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: Na této platformì nelze umístìní okna zjistit"
+
+#: ex_docmd.c:6444
+msgid "Save Redirection"
+msgstr "Uložit pøesmìrování"
+
+#: ex_docmd.c:6593
+msgid "Save View"
+msgstr "Uložit pohled"
+
+#: ex_docmd.c:6594
+msgid "Save Session"
+msgstr "Uložit sezení"
+
+#: ex_docmd.c:6596
+msgid "Save Setup"
+msgstr "Uložit nastavení"
+
+#: ex_docmd.c:6745
+#, c-format
+msgid "E189: \"%s\" exists (use ! to override)"
+msgstr "E189: \"%s\" existuje (použijte ! pro vynucení)"
+
+#: ex_docmd.c:6750
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: Nelze otevøít \"%s\" pro zápis"
+
+#. set mark
+#: ex_docmd.c:6774
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: Argumentem mùže být pouze písmeno nebo pravý èi levý apostrof"
+
+#: ex_docmd.c:6803
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Vnoøení :normal je pøíliš hluboké"
+
+#: ex_docmd.c:7171
+msgid ":if nesting too deep"
+msgstr "vnoøení :if je pøíliš hluboké"
+
+#: ex_docmd.c:7206
+msgid ":endif without :if"
+msgstr ":endif bez odpovídajícího :if"
+
+#: ex_docmd.c:7226
+msgid ":else without :if"
+msgstr ":else bez odpovídajícího :if"
+
+#: ex_docmd.c:7228
+msgid ":elseif without :if"
+msgstr ":elseif bez odpovídajícího :if"
+
+#: ex_docmd.c:7280
+msgid ":while nesting too deep"
+msgstr "vnoøení :while je pøíliš hluboké"
+
+#: ex_docmd.c:7326
+msgid ":continue without :while"
+msgstr ":continue bez odpovídajícího :while"
+
+#: ex_docmd.c:7353
+msgid ":break without :while"
+msgstr ":break bez odpovídajícího :while"
+
+#: ex_docmd.c:7376 ex_docmd.c:7381
+msgid ":endwhile without :while"
+msgstr ":endwhile bez odpovídajícího :while"
+
+#: ex_docmd.c:7402
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction mimo funkci"
+
+#: ex_docmd.c:7582
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr ""
+"E194: Žádný alternativní název souboru, kterým by bylo možné nahradit '#'"
+
+#: ex_docmd.c:7613
+msgid "no autocommand file name to substitute for \"<afile>\""
+msgstr "Žádný název souboru, kterým by bylo možné nahradit \"<afile>\""
+
+#: ex_docmd.c:7621
+msgid "no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "Žádné èíslo bufferu, kterým by bylo možné nahradit \"<abuf>\""
+
+#: ex_docmd.c:7632
+msgid "no autocommand match name to substitute for \"<amatch>\""
+msgstr ""
+"Žádná shoda automatických pøíkazù, kterou by bylo možné nahradit \"<amatch>\""
+
+#: ex_docmd.c:7642
+msgid "no :source file name to substitute for \"<sfile>\""
+msgstr "Žádný interpretovaný soubor, kterým by bylo možné nahradit \"<sfile>\""
+
+#: ex_docmd.c:7683
+#, no-c-format
+msgid "Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "Prázdný název souboru pro '%' èi '#' funguje pouze s \":p:h\""
+
+#: ex_docmd.c:7685
+msgid "Evaluates to an empty string"
+msgstr "Výsledkem vyhodnocení je prázdný øetìzec"
+
+#: ex_docmd.c:8594
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: Nelze otevøít pro ètení viminfo soubor"
+
+#: ex_docmd.c:8767
+msgid "E196: No digraphs in this version"
+msgstr "E196: V této verzi nejsou spøežky podporovány"
+
+#: ex_getln.c:2785
+msgid "tagname"
+msgstr "jméno tagu"
+
+#: ex_getln.c:2788
+msgid " kind file\n"
+msgstr " typ soubor\n"
+
+#: ex_getln.c:3997
+msgid "'history' option is zero"
+msgstr "'volba 'history' je nastavena na nulu"
+
+#: ex_getln.c:4237
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Historie %s (poèínaje nejnovìjší položkou):\n"
+
+#: ex_getln.c:4238
+msgid "Command Line"
+msgstr "pøíkazové øádky"
+
+#: ex_getln.c:4239
+msgid "Search String"
+msgstr "vyhledávaných øetìzcù"
+
+#: ex_getln.c:4240
+msgid "Expression"
+msgstr "výrazù"
+
+#: ex_getln.c:4241
+msgid "Input Line"
+msgstr "vstupní øádky"
+
+#: ex_getln.c:4271
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar pøekraèuje délku pøíkazu"
+
+#: ex_getln.c:4435
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Smazáno aktivní okno èi buffer"
+
+#: fileio.c:347
+msgid "Illegal file name"
+msgstr "nepøípustný název souboru"
+
+#: fileio.c:371 fileio.c:495 fileio.c:2491 fileio.c:2529
+msgid "is a directory"
+msgstr "je adresáøem"
+
+#: fileio.c:373
+msgid "is not a file"
+msgstr "není souborem"
+
+#: fileio.c:515 fileio.c:3581
+msgid "[New File]"
+msgstr "[nový soubor]"
+
+#: fileio.c:532
+msgid "[Permission Denied]"
+msgstr "[pøístup odmítnut]"
+
+#: fileio.c:624
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre automatické pøíkazy uèinily soubor neèitelným"
+
+#: fileio.c:626
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *ReadPre automatické pøíkazy nesmí mìnit aktuální buffer"
+
+#: fileio.c:646
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: Ètu ze standardního vstupu...\n"
+
+#: fileio.c:652
+msgid "Reading from stdin..."
+msgstr "Ètu ze standardního vstupu..."
+
+#. Re-opening the original file failed!
+#: fileio.c:876
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: Po konverzi je soubor neèitelný!"
+
+#: fileio.c:1732
+msgid "[fifo/socket]"
+msgstr "[pojmenovaná roura/soket]"
+
+#: fileio.c:1739
+msgid "[fifo]"
+msgstr "[pojmenovaná roura]"
+
+#: fileio.c:1746
+msgid "[socket]"
+msgstr "[soket]"
+
+#: fileio.c:1754
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:1764
+msgid "[CR missing]"
+msgstr "[chybí CR]"
+
+#: fileio.c:1769
+msgid "[NL found]"
+msgstr "[nalezeno NL]"
+
+#: fileio.c:1774
+msgid "[long lines split]"
+msgstr "[dlouhé øádky zalomeny]"
+
+#: fileio.c:1780 fileio.c:3565
+msgid "[NOT converted]"
+msgstr "[nezkonvertován]"
+
+#: fileio.c:1785 fileio.c:3570
+msgid "[converted]"
+msgstr "[zkonvertován]"
+
+#: fileio.c:1792 fileio.c:3595
+msgid "[crypted]"
+msgstr "[zašifrován]"
+
+#: fileio.c:1799
+msgid "[CONVERSION ERROR]"
+msgstr "[CHYBA PØEVODU]"
+
+#: fileio.c:1806
+msgid "[READ ERRORS]"
+msgstr "[CHYBY ÈTENÍ]"
+
+#: fileio.c:2013
+msgid "Can't find temp file for conversion"
+msgstr "Nelze nalézt doèasný soubor pro konverzi"
+
+#: fileio.c:2020
+msgid "Conversion with 'charconvert' failed"
+msgstr "Konverze s 'charconvert' se nezdaøila"
+
+#: fileio.c:2023
+msgid "can't read output of 'charconvert'"
+msgstr "nelze èíst výstup 'charconvert'"
+
+#: fileio.c:2407
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr ""
+"E203: Automatické pøíkazy smazaly èi deaktivovaly buffer, který mìl být "
+"uložen"
+
+#: fileio.c:2430
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Automatický pøíkaz neèekaným zpùsobem zmìnil poèet øádkù"
+
+#: fileio.c:2496 fileio.c:2513
+msgid "is not a file or writable device"
+msgstr "není souborem ani zaøízením na nìž lze zapisovat"
+
+#: fileio.c:2555
+msgid "is read-only (use ! to override)"
+msgstr "je pouze pro ètení (použijte ! pro vynucení)"
+
+#: fileio.c:2851
+msgid "Can't write to backup file (use ! to override)"
+msgstr "Nelze zapisovat do záložního souboru (použijte ! pro vynucení)"
+
+#: fileio.c:2863
+msgid "Close error for backup file (use ! to override)"
+msgstr "Chyba pøi uzavírání záložního souboru (použijte ! pro vynucení)"
+
+#: fileio.c:2865
+msgid "Can't read file for backup (use ! to override)"
+msgstr "Nelze naèíst soubor pro zálohu (použijte ! pro vynucení)"
+
+#: fileio.c:2881
+msgid "Cannot create backup file (use ! to override)"
+msgstr "Nelze vytvoøit záložní soubor (použijte ! pro vynucení)"
+
+#: fileio.c:2970
+msgid "Can't make backup file (use ! to override)"
+msgstr "Nelze vytvoøit záložní soubor (použijte ! pro vynucení)"
+
+# resource fork ?!
+#: fileio.c:3032
+msgid "The resource fork will be lost (use ! to override)"
+msgstr "'Resource fork' bude ztracen (použijte ! pro vynucení)"
+
+#: fileio.c:3121
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: Nelze najít doèasný temp soubor pro zápis"
+
+#: fileio.c:3139
+msgid "E213: Cannot convert (use ! to write without conversion)"
+msgstr "E213: Nelze pøevést (použijte ! pro zápis bez pøevodu)"
+
+#: fileio.c:3176
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Nelze otevøít pøipojený soubor pro zápis"
+
+#: fileio.c:3180
+msgid "E212: Can't open file for writing"
+msgstr "E212: Nelze otevøít soubor pro zápis"
+
+#: fileio.c:3423
+msgid "Close failed"
+msgstr "Volání close selhalo"
+
+#: fileio.c:3481
+msgid "write error, conversion failed"
+msgstr "chyba pøi zápisu, konverze se nezdaøila"
+
+#: fileio.c:3487
+msgid "write error (file system full?)"
+msgstr "chyba pøi ukládání (je volné místo na disku?)"
+
+#: fileio.c:3560
+msgid " CONVERSION ERROR"
+msgstr " CHYBA PØEVODU"
+
+#: fileio.c:3576
+msgid "[Device]"
+msgstr "[zaøízení]"
+
+#: fileio.c:3581
+msgid "[New]"
+msgstr "[Nový]"
+
+#: fileio.c:3603
+msgid " [a]"
+msgstr " [p]"
+
+#: fileio.c:3603
+msgid " appended"
+msgstr " pøipojen"
+
+#: fileio.c:3605
+msgid " [w]"
+msgstr " [u]"
+
+#: fileio.c:3605
+msgid " written"
+msgstr " uložen"
+
+#: fileio.c:3655
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: patchmode: nelze uložit pùvodní soubor"
+
+#: fileio.c:3677
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: nelze zapisovat do prázdného pùvodního souboru"
+
+#: fileio.c:3692
+msgid "E207: Can't delete backup file"
+msgstr "E207: Nelze smazat záložní soubor"
+
+#: fileio.c:3744
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"VAROVÁNÍ: Obsah pùvodního souboru mùže být ztracen èi poškozen\n"
+
+#: fileio.c:3746
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "neukonèujte editor døíve, než bude soubor úspìšnì uložen!"
+
+#: fileio.c:3826
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:3826
+msgid "[dos format]"
+msgstr "[dos formát]"
+
+#: fileio.c:3833
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:3833
+msgid "[mac format]"
+msgstr "[mac formát]"
+
+#: fileio.c:3840
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:3840
+msgid "[unix format]"
+msgstr "[unix formát]"
+
+#: fileio.c:3867
+msgid "1 line, "
+msgstr "1 øádek, "
+
+#: fileio.c:3869
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld øádkù, "
+
+#: fileio.c:3872
+msgid "1 character"
+msgstr "1 znak"
+
+#: fileio.c:3874
+#, c-format
+msgid "%ld characters"
+msgstr "%ld znakù, "
+
+#: fileio.c:3884
+msgid "[noeol]"
+msgstr "[žádný eol]"
+
+#: fileio.c:3884
+msgid "[Incomplete last line]"
+msgstr "[neúplný poslední øádek]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:3903
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "VAROVÁNÍ: od jeho naètení byl obsah souboru zmìnìn!!!!"
+
+#: fileio.c:3905
+msgid "Do you really want to write to it"
+msgstr "Chcete jej opravdu uložit"
+
+#: fileio.c:4861
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Chyba pøi zápisu do \"%s\""
+
+#: fileio.c:4868
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Chyb pøi uzavírání \"%s\""
+
+#: fileio.c:4871
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Chyba pøi ètení \"%s\""
+
+#: fileio.c:5035
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: FileChangedShell autocommand zrušil buffer"
+
+#: fileio.c:5043
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: wa1: soubor \"%s\" již není dostupný"
+
+#: fileio.c:5056
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: Varování: soubor \"%s\" byl po poèátku editace zmìnìn a buffer ve Vim "
+"také"
+
+#: fileio.c:5059
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: wc2: soubor \"%s\" byl po poèátku editace zmìnìn"
+
+#: fileio.c:5061
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: Varování: Mód souboru \"%s\" byl zmìnìn od zapoènutí editace"
+
+#: fileio.c:5071
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: wc4: po poèátku editace vytvoøen soubor \"%s\""
+
+#: fileio.c:5088
+msgid "Warning"
+msgstr "Varování"
+
+#: fileio.c:5089
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Nahrát soubor"
+
+#: fileio.c:5165
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: Nelze znovuotevøít \"%s\""
+
+#: fileio.c:5670
+msgid "--Deleted--"
+msgstr "--Vymazáno--"
+
+#. the group doesn't exist
+#: fileio.c:5830
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Skupina \"%s\" neexistuje"
+
+#: fileio.c:5955
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Nepøípustný znak po *: %s"
+
+#: fileio.c:5966
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Událost %s neexistuje"
+
+#. Highlight title
+#: fileio.c:6115
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Automatické pøíkazy ---"
+
+#: fileio.c:6386
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Automatické pøíkazy nelze spustit pro VŠECHNY události"
+
+#: fileio.c:6409
+msgid "No matching autocommands"
+msgstr "Žádné vyhovující automatické pøíkazy"
+
+#: fileio.c:6681
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: vnoøení automatického pøíkazu pøíliš hluboká"
+
+#: fileio.c:6968
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s automatické pøíkazy pro \"%s\""
+
+#: fileio.c:6976
+#, c-format
+msgid "Executing %s"
+msgstr "spouštím %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7044
+#, c-format
+msgid "autocommand %s"
+msgstr "Automatický pøíkaz %s"
+
+#: fileio.c:7566
+msgid "E219: Missing {."
+msgstr "E219: Chybí {."
+
+#: fileio.c:7568
+msgid "E220: Missing }."
+msgstr "E220: Chybí }."
+
+#: fold.c:66
+msgid "No fold found"
+msgstr "Žádný záhyb nebyl nalezen"
+
+#: fold.c:554
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: pomocí aktuální 'foldmethod' nelze vytvoøit záhyb"
+
+#: fold.c:556
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: pomocí aktuální 'foldmethod' nelze vytvoøit záhyb"
+
+#: fold.c:1700
+msgid "E221: 'commentstring' is empty"
+msgstr "E221: volba 'commentstring' je prázdná"
+
+#: getchar.c:268
+msgid "E222: Add to read buffer"
+msgstr "E222: Pøidat do bufferu pro ètení"
+
+#: getchar.c:2114
+msgid "E223: recursive mapping"
+msgstr "E223: rekurzivní mapování"
+
+#: getchar.c:2966
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: pro %s již globální zkratka již existuje"
+
+#: getchar.c:2969
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: pro %s již globální mapování již existuje"
+
+#: getchar.c:3096
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: pro %s již zkratka již existuje"
+
+#: getchar.c:3099
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: pro %s již mapování již existuje"
+
+#: getchar.c:3163
+msgid "No abbreviation found"
+msgstr "Žádná zkratka nebyl nalezena"
+
+#: getchar.c:3165
+msgid "No mapping found"
+msgstr "Žádné mapování nebylo nalezeno"
+
+#: getchar.c:3990
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: nepøípustný mód"
+
+#: gui.c:181
+msgid "E229: Cannot start the GUI"
+msgstr "E229: Nelze spustit GUI"
+
+#: gui.c:306
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Nelze èíst z \"%s\""
+
+#: gui.c:431
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: volba 'guifontwide' je chybnì nastavena"
+
+#: gui.c:3926
+msgid "Error"
+msgstr "Chyba"
+
+#: gui.c:3927
+msgid "&Ok"
+msgstr "&Ok"
+
+#: gui_at_fs.c:290
+msgid "<cannot open> "
+msgstr "<nelze otevøít> "
+
+#: gui_at_fs.c:1115
+#, c-format
+msgid "vim_SelFile: can't get font %s"
+msgstr "vim_SelFile: písmo %s není dostupné"
+
+#: gui_at_fs.c:2538
+msgid "vim_SelFile: can't return to current directory"
+msgstr "vim_SelFile: nelze se vrátit do aktuálního adresáøe"
+
+#: gui_at_fs.c:2557
+msgid "Pathname:"
+msgstr "Název cesty:"
+
+#: gui_at_fs.c:2563
+msgid "vim_SelFile: can't get current directory"
+msgstr "vim_SelFile: nelze zjistit aktuální adresáø"
+
+#: gui_at_fs.c:2571 gui_motif.c:1607
+msgid "OK"
+msgstr "OK"
+
+#. 'Cancel' button
+#: gui_at_fs.c:2571 gui_gtk.c:1683 gui_motif.c:1602 gui_motif.c:2823
+msgid "Cancel"
+msgstr "Zrušit"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Pøípravek posunovací lišty: nelze zjistit geometrii obrázku"
+
+#: gui_athena.c:1928 gui_motif.c:1855
+msgid "Vim dialog"
+msgstr "Vim dialog"
+
+#: gui_beval.c:68
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: BalloonEval nelze vytvoøit se zprávou a zároveò zpìtným voláním"
+
+#: gui_gtk.c:1144
+msgid "Vim dialog..."
+msgstr "Vim dialog.."
+
+#: gui_gtk.c:1519 gui_motif.c:2742
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Nalézt a nahradit..."
+
+#: gui_gtk.c:1524 gui_motif.c:2744
+msgid "VIM - Search..."
+msgstr "VIM - Nalézt..."
+
+#: gui_gtk.c:1547 gui_motif.c:2862
+msgid "Find what:"
+msgstr "Vyhledat:"
+
+#: gui_gtk.c:1565 gui_motif.c:2894
+msgid "Replace with:"
+msgstr "Nový text:"
+
+#. exact match only button
+#: gui_gtk.c:1597 gui_motif.c:2996
+msgid "Match exact word only"
+msgstr "hledat pouze celá slova"
+
+#: gui_gtk.c:1609 gui_motif.c:2964
+msgid "Direction"
+msgstr "Smìr"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:1621 gui_motif.c:2976
+msgid "Up"
+msgstr "Nahoru"
+
+#: gui_gtk.c:1625 gui_motif.c:2984
+msgid "Down"
+msgstr "Dolù"
+
+#. 'Find Next' button
+#: gui_gtk.c:1647 gui_motif.c:2766
+msgid "Find Next"
+msgstr "Najít další"
+
+#. 'Replace' button
+#: gui_gtk.c:1664 gui_motif.c:2783
+msgid "Replace"
+msgstr "Nahradit"
+
+#. 'Replace All' button
+#: gui_gtk.c:1673 gui_motif.c:2796
+msgid "Replace All"
+msgstr "Nahradit vše"
+
+#: gui_gtk_x11.c:1076 gui_x11.c:1199
+msgid "E233: cannot open display"
+msgstr "E233: nelze otevøít display"
+
+#: gui_gtk_x11.c:2433 gui_x11.c:2002
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Neznámá sada písem: %s"
+
+#: gui_gtk_x11.c:2460
+msgid "Font Selection"
+msgstr "Výbìr písma"
+
+#: gui_gtk_x11.c:2702 gui_mac.c:2780 gui_w48.c:1197 gui_x11.c:1838
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Neznámé písmo: %s"
+
+#: gui_gtk_x11.c:2713 gui_x11.c:1862
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: Písmo \"%s\" nemá pevnou šíøku"
+
+#: gui_gtk_x11.c:2843
+#, c-format
+msgid "E242: Color name not recognized: %s"
+msgstr "E242: Neznámé jméno barvy: %s"
+
+#: gui_gtk_x11.c:3519 ui.c:1929
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "Místo prádné schránky použito CUT_BUFFER0"
+
+#: gui_motif.c:1601 gui_motif.c:1604
+msgid "Filter"
+msgstr "Filtr"
+
+#: gui_motif.c:1603
+msgid "Directories"
+msgstr "Adresáøe"
+
+#: gui_motif.c:1605
+msgid "Help"
+msgstr "Nápovìda"
+
+#: gui_motif.c:1606
+msgid "Files"
+msgstr "Soubory"
+
+#: gui_motif.c:1608
+msgid "Selection"
+msgstr "Výbìr"
+
+#: gui_motif.c:2809
+msgid "Undo"
+msgstr "Zpìt"
+
+#: gui_riscos.c:951
+#, c-format
+msgid "E235: Can't load Zap font '%s'"
+msgstr "E235: Nelze naèíst Zap font '%s'"
+
+#: gui_riscos.c:1047
+#, c-format
+msgid "E235: Can't use font %s"
+msgstr "E235: Nelze použít font %s"
+
+#: gui_riscos.c:1167
+#, c-format
+msgid "E242: Missing color: %s"
+msgstr "E242: Chybí barva: %s"
+
+#: gui_riscos.c:3269
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Posílám signál k ukonèení synovského procesu.\n"
+
+#: gui_w32.c:823
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Argument nepodporován: \"-%s\"; Použijte OLE verzi."
+
+#: gui_w48.c:2068
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Najít øetìzec (použijte '\\\\' k nalezení '\\')"
+
+#: gui_w48.c:2093
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Najít & Nahradit (použijte '\\\\' k nalezení '\\')"
+
+#: gui_x11.c:1419
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: nelze alokovat položku barevné mapy. Nìkteré barvy mohou být "
+"nesprávné"
+
+#: gui_x11.c:1992
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: písma pro následující znakové sady chybí v sadì písem %s:"
+
+#: gui_x11.c:2035
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: název sady písem: %s"
+
+#: gui_x11.c:2036
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "Písmo '%s' nemá pevnou šíøku"
+
+#: gui_x11.c:2055
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: název sady písem: %s\n"
+
+#: gui_x11.c:2056
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Písmo0: %s\n"
+
+#: gui_x11.c:2057
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Písmo1: %s\n"
+
+#: gui_x11.c:2058
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "Šíøka písma%d není dvojnásoblem šíøky písma0\n"
+
+#: gui_x11.c:2059
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "Šíøka písma0: %ld\n"
+
+#: gui_x11.c:2060
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"Šíøka písma1: %ld\n"
+"\n"
+
+#: gui_x11.c:2206
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: nelze alokovat barvu %s"
+
+#: gui_x11.c:3256
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Chyba -- nelze pøeèíst sign data!"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: CYBA Hangul automatu"
+
+#: if_cscope.c:67
+msgid "Add a new database"
+msgstr "Pøidat novou databázi"
+
+#: if_cscope.c:69
+msgid "Query for a pattern"
+msgstr "Hledání vzorku"
+
+#: if_cscope.c:71
+msgid "Show this message"
+msgstr "Zobrazit tuto zprávu"
+
+#: if_cscope.c:73
+msgid "Kill a connection"
+msgstr "Ukonèit spojení"
+
+#: if_cscope.c:75
+msgid "Reinit all connections"
+msgstr "Znovu inicializovat všechna spojení"
+
+#: if_cscope.c:77
+msgid "Show connections"
+msgstr "Zobrazit spojení"
+
+#: if_cscope.c:108
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Tento cscope pøíkaz nepodporuje rozdìlení okna.\n"
+
+#: if_cscope.c:143
+msgid "Usage: cstag <ident>"
+msgstr "Použití: cstag <odsazení>"
+
+#: if_cscope.c:199
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: tag nenalezen"
+
+#: if_cscope.c:407 if_cscope.c:451
+#, c-format
+msgid "stat(%s) error: %d"
+msgstr "stat(%s) chyba: %d"
+
+#: if_cscope.c:460 if_cscope.c:467
+#, c-format
+msgid "Added cscope database %s"
+msgstr "Pøidána cscope databáze %s"
+
+#: if_cscope.c:474
+#, c-format
+msgid "%s is not a directory or a valid cscope database"
+msgstr "%s není ani adresáøem ani správnou cscope databází"
+
+#: if_cscope.c:557
+#, c-format
+msgid "error reading cscope connection %d"
+msgstr "chyba pøi ètení cscope spojení %d"
+
+#: if_cscope.c:633
+msgid "unknown cscope search type"
+msgstr "neznámý typ cscope hledání"
+
+#: if_cscope.c:680
+msgid "Could not create cscope pipes"
+msgstr "nelze vytvoøit cscope roury"
+
+#: if_cscope.c:745
+msgid "cs_create_connection exec failed"
+msgstr "spuštìní cs_create_connection selhalo"
+
+#: if_cscope.c:755
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: volání fdopen pro to_fp selhalo"
+
+#: if_cscope.c:757
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: volání fdopen pro fr_fp selhalo"
+
+#: if_cscope.c:785
+msgid "no cscope connections"
+msgstr "žádná cscope spojení"
+
+#: if_cscope.c:855
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: cscope hledání %s vzorku %s nenašlo žádnou shodu"
+
+#: if_cscope.c:899
+msgid "cscope commands:\n"
+msgstr "pøíkazy cscope:\n"
+
+#: if_cscope.c:902
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)\n"
+msgstr "%-5s: %-30s (Použití: %s)\n"
+
+#: if_cscope.c:970
+msgid "duplicate cscope database not added"
+msgstr "duplicitní cscope databáze nebyla pøidána"
+
+#: if_cscope.c:981
+msgid "maximum number of cscope connections reached"
+msgstr "dosažen maximální poèet cscope spojení"
+
+#: if_cscope.c:1102
+msgid "E260: cscope connection not found"
+msgstr "E260: connection spojení nenalezeno"
+
+#: if_cscope.c:1105
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: connection spojení %s nenalezeno"
+
+#: if_cscope.c:1141
+msgid "cscope connection closed"
+msgstr "closed spojení uzavøeno"
+
+#: if_cscope.c:1149
+#, c-format
+msgid "cscope connection %s closed\n"
+msgstr "cscope spojení %s uzavøeno\n"
+
+#. should not reach here
+#: if_cscope.c:1290
+msgid "fatal error in cs_manage_matches"
+msgstr "osudová chyba v cs_manage_matches"
+
+#: if_cscope.c:1341
+#, c-format
+msgid "E262: error reading cscope connection %d"
+msgstr "E262: pøi ètení cscope spojení %d"
+
+#: if_cscope.c:1449
+msgid "couldn't malloc\n"
+msgstr "volání malloc selhalo\n"
+
+#: if_cscope.c:1454
+#, c-format
+msgid "Cscope tag: %s\n"
+msgstr "Cscope tag: %s\n"
+
+#: if_cscope.c:1458
+msgid " # line"
+msgstr " # øádek"
+
+#: if_cscope.c:1460
+msgid "filename / context / line\n"
+msgstr "název souboru/ kontext/ øádek\n"
+
+#: if_cscope.c:1718
+msgid "All cscope databases reset"
+msgstr "Všechny cscope databáze resetovány"
+
+#: if_cscope.c:1785
+msgid "no cscope connections\n"
+msgstr "žádné cscope spojení\n"
+
+#: if_cscope.c:1789
+msgid " # pid database name prepend path\n"
+msgstr " # pid název databáze pøedpona cesty\n"
+
+#: if_cscope.c:1800
+#, c-format
+msgid "%2d %-5ld %-34s <none>\n"
+msgstr "%2d %-5ld %-34s <žádný>\n"
+
+#: if_python.c:376
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: Lituji, tento pøíkaz je deaktivován; knihovnu jazyka Python nelze "
+"nahrát."
+
+#: if_python.c:576
+msgid "can't delete OutputObject attributes"
+msgstr "nelze smazat atributy OutputObject"
+
+#: if_python.c:583
+msgid "softspace must be an integer"
+msgstr "softspace musí být kladné celé èíslo"
+
+#: if_python.c:591
+msgid "invalid attribute"
+msgstr "chybný atribut"
+
+#: if_python.c:630 if_python.c:644
+msgid "writelines() requires list of strings"
+msgstr "writelines() vyžaduje seznam øetìzcù"
+
+#: if_python.c:770
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: chyba pøi inicializaci I/O objektù"
+
+#: if_python.c:955 if_tcl.c:1391
+msgid "invalid expression"
+msgstr "Chybný výraz"
+
+#: if_python.c:969 if_tcl.c:1396
+msgid "expressions disabled at compile time"
+msgstr "podpora výrazù byla vypnuta pøi pøekladu programu"
+
+#: if_python.c:982
+msgid "attempt to refer to deleted buffer"
+msgstr "pokus o odkaz na smazaný buffer"
+
+#: if_python.c:997 if_python.c:1038 if_python.c:1102 if_tcl.c:1203
+msgid "line number out of range"
+msgstr "èíslo øádku mimo rozsah"
+
+#: if_python.c:1235
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<buffer objekt (smazán) na %8lX>"
+
+#: if_python.c:1326 if_tcl.c:825
+msgid "invalid mark name"
+msgstr "chybné jméno znaèky"
+
+#: if_python.c:1601
+msgid "no such buffer"
+msgstr "žádný takový buffer"
+
+#: if_python.c:1689
+msgid "attempt to refer to deleted window"
+msgstr "pokus o odkaz na smazané okno"
+
+#: if_python.c:1734
+msgid "readonly attribute"
+msgstr "atribut pouze_pro_ètení"
+
+#: if_python.c:1747
+msgid "cursor position outside buffer"
+msgstr "umístìní kurzoru mimo buffer"
+
+#: if_python.c:1824
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<objekt okna (smazán) na %8lX>"
+
+#: if_python.c:1836
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<objekt okna (neznámý) na %8lX>"
+
+#: if_python.c:1838
+#, c-format
+msgid "<window %d>"
+msgstr "<okno %d>"
+
+#: if_python.c:1914
+msgid "no such window"
+msgstr "žádné takové okno"
+
+#: if_python.c:2144 if_python.c:2175 if_python.c:2225 if_python.c:2285
+#: if_python.c:2402 if_python.c:2454 if_tcl.c:673 if_tcl.c:718 if_tcl.c:792
+#: if_tcl.c:862 if_tcl.c:1987
+msgid "cannot save undo information"
+msgstr "nelze uložit informace pro pøíkaz undo"
+
+#: if_python.c:2146 if_python.c:2232 if_python.c:2296
+msgid "cannot delete line"
+msgstr "nelze smazat øádek"
+
+#: if_python.c:2177 if_python.c:2312 if_tcl.c:679 if_tcl.c:2009
+msgid "cannot replace line"
+msgstr "nelze nahradit øádek"
+
+#: if_python.c:2328 if_python.c:2404 if_python.c:2462
+msgid "cannot insert line"
+msgstr "nelze vložit øádek"
+
+#: if_python.c:2566
+msgid "string cannot contain newlines"
+msgstr "øetìzec nesmí obsahovat znaky nového øádku"
+
+#: if_ruby.c:394
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: Lituji, ale tento pøíkaz je deaktivován; knihovnu jazyka Ruby nelze "
+"nahrát."
+
+#: if_ruby.c:457
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: neznámý longjmp stav %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Prohození implementace/definice"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Zobrazení base class z"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Zobrazení overridden member funkce"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Znovuzískáno ze souboru"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Znovuzískáno z projektu"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Znovzískáno ze všech projektù"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Znovuzískáno"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Zobrazení zdroje"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Najít symbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Prohlížet class"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Zobrazení class v hierarchii"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Zobrazení class v restricted hierarchii"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref odkazuje na"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref odkazoval na"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref má"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref použit"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Zobrazení documentace"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Generována dokumentace pro"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"Nelze se pøipojit k SNiFF+. Zkontrolujte promìnné (sniffemacs musí "
+"být)uvedena v $PATH.\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Chyba pøi ètení. Odpojeno"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ je právì "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "ne "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "pøipojen"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Neznámý požadavek SNiFF+: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Chybné pøipojení k SNiFF+"
+
+#: if_sniff.c:1010
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ nepøipojen"
+
+#: if_sniff.c:1019
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Není SNiFF+ buffer"
+
+#: if_sniff.c:1084
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: Chyba pøi zápisu. Odpojeno."
+
+#: if_tcl.c:407
+msgid "invalid buffer number"
+msgstr "chybný název bufferu"
+
+#: if_tcl.c:453 if_tcl.c:920 if_tcl.c:1099
+msgid "not implemented yet"
+msgstr "není ještì podporováno"
+
+#: if_tcl.c:490
+msgid "unknown option"
+msgstr "neznámá volba"
+
+#. ???
+#: if_tcl.c:763
+msgid "cannot set line(s)"
+msgstr "nelze nastavit øádky"
+
+#: if_tcl.c:834
+msgid "mark not set"
+msgstr "znaèka není nastavena"
+
+#: if_tcl.c:840 if_tcl.c:1055
+#, c-format
+msgid "row %d column %d"
+msgstr "øádek %d sloupec %d"
+
+#: if_tcl.c:870
+msgid "cannot insert/append line"
+msgstr "nelze vložit/pøipojit øádek"
+
+#: if_tcl.c:1257
+msgid "unknown flag: "
+msgstr "neznámý pøíznak: "
+
+#: if_tcl.c:1327
+msgid "unknown vimOption"
+msgstr "neznámá vimOption"
+
+#: if_tcl.c:1412
+msgid "keyboard interrupt"
+msgstr "pøerušení z klávesnice"
+
+#: if_tcl.c:1417
+msgid "vim error"
+msgstr "chyba vim"
+
+#: if_tcl.c:1460
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "nelze vytvoøit pøíkaz bufferu/okna: objekt smazán"
+
+#: if_tcl.c:1534
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"nelze zaregistrovat pøíkaz zpìtného volání: buffer/okno již bylo smazáno"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1551
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to "
+"vim-dev@vim.org"
+msgstr ""
+"E280: TCL FATAL ERROR: reflist poškozen!? Oznamte, prosím, tuto chybu na "
+"vim-dev@vim.org"
+
+#: if_tcl.c:1552
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"nelze zaregistrovat pøíkaz zpìtného volání: odkaz na buffer/okno nenalezen"
+
+#: if_tcl.c:1713
+msgid "Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"Lituji, ale tento pøíkaz je deaktivován; knihovnu jazyka Tcl nelze nahrát."
+
+#: if_tcl.c:1875
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: TCL CHYBA: návratový kód není celé èíslo!? Oznamte, prosím, tuto chybu "
+"na vim-dev@vim.org"
+
+#: if_tcl.c:1995
+msgid "cannot get line"
+msgstr "nelze pøeèíst øádek"
+
+#: if_xcmdsrv.c:204
+msgid "Unable to register a command server name"
+msgstr "Není možné zaznamenat jméno command serveru"
+
+#: if_xcmdsrv.c:417
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: Neexistuje registrovaný server jménem \"%s\""
+
+#: if_xcmdsrv.c:446
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Selhalo zaslání pøíkazu urèenému programu"
+
+#: if_xcmdsrv.c:714
+#, c-format
+msgid "Invalid server id used: %s"
+msgstr "Použit chybný id serveru: %s"
+
+#: if_xcmdsrv.c:1061
+msgid "E249: couldn't read VIM instance registry property"
+msgstr "E249: nelze èíst VIM instanci registry property"
+
+#: if_xcmdsrv.c:1072
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr ""
+"E251: VIM instance registry property byla špatnì vytvoøenaa byla smazána!"
+
+#: main.c:53 option.c:3162 option.c:3269
+msgid "Unknown option"
+msgstr "Neznámá volba"
+
+#: main.c:55
+msgid "Too many edit arguments"
+msgstr "Pøíliš mnoho edit argumentù"
+
+#: main.c:57
+msgid "Argument missing after"
+msgstr "Chybí argument po"
+
+#: main.c:59
+msgid "Garbage after option"
+msgstr "Chyby za volbou"
+
+#: main.c:61
+msgid "Too many \"+command\" or \"-c command\" arguments"
+msgstr "Pøíliš mnoho \"+pøíkaz\" èi \"-c pøíkaz\" argumentù"
+
+#: main.c:63
+msgid "Invalid argument for"
+msgstr "Chybný argument pro"
+
+#: main.c:436
+msgid "This Vim was not compiled with the diff feature."
+msgstr "VIM nebyl pøeložen s volbou +diff"
+
+#: main.c:858
+msgid "Attempt to open script file again: \""
+msgstr "Pokus o opìtovné otevøení skriptu: \""
+
+#: main.c:862 main.c:869 main.c:913 memline.c:3673 memline.c:3677
+#: version.c:816 version.c:821 version.c:826 version.c:831 version.c:836
+#: version.c:841 version.c:847 version.c:851 version.c:855 version.c:860
+#: version.c:867 version.c:875 version.c:881
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:867
+msgid "Cannot open for reading: \""
+msgstr "Nelze otevøít pro zápis: \""
+
+#: main.c:911
+msgid "Cannot open for script output: \""
+msgstr "Nelze otevøít pro výstup skriptu: \""
+
+#: main.c:1020
+#, c-format
+msgid "%d files to edit\n"
+msgstr "poèet souborù pro editaci: %d\n"
+
+#: main.c:1094
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Varování: výstup nesmìøuje na terminál\n"
+
+#: main.c:1096
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Varování: vstup nepochází z terminálu\n"
+
+#. just in case..
+#: main.c:1171
+msgid "pre-vimrc command line"
+msgstr "pre-vimrc pøíkazový øádek"
+
+#: main.c:1206
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Nelze èíst z \"%s\""
+
+#: main.c:2157
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Podrobnìjší informace získáte pomocí \"vim -h\"\n"
+
+#: main.c:2190
+msgid "[file ..] edit specified file(s)"
+msgstr "[SOUBOR] .. editovat SOUBOR(y)"
+
+#: main.c:2191
+msgid "- read text from stdin"
+msgstr "- èíst text ze standardního vstupu"
+
+#: main.c:2192
+msgid "-t tag edit file where tag is defined"
+msgstr "-t TAG editovat soubor na místì definice TAGU"
+
+#: main.c:2194
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [chybový soubor] editovat soubor na místì výskytu první chyby"
+
+#: main.c:2203
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"použití:"
+
+#: main.c:2206
+msgid " vim [arguments] "
+msgstr "vim [pøepínaèe] "
+
+#: main.c:2210
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" nebo"
+
+#: main.c:2213
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Argumenty:\n"
+
+#: main.c:2214
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tMohou následovat pouze názvy souborù"
+
+#: main.c:2216
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tpøihlásit gvim na OLE"
+
+#: main.c:2217
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-register\t\todhlásit gvim z OLE"
+
+#: main.c:2220
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tspustit v GUI režimu (stejné jako \"gvim\")"
+
+#: main.c:2221
+msgid "-f\t\t\tForeground: Don't fork when starting GUI"
+msgstr "-f\t\t\tPopøedí: pøi startu GUI se neoddìlí od shellu"
+
+#: main.c:2223
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi mód (stejné jako \"vi\")"
+
+#: main.c:2224
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-v\t\t\tEx mód (stejné jako \"ex\")"
+
+#: main.c:2225
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tTichý (dávkový) režim (pouze pro \"ex\")"
+
+#: main.c:2227
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tDiff režim (stejné jako \"vimdiff\")"
+
+#: main.c:2229
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-v\t\t\tSnadný režim (stejné jako \"evim\", žádné módy )"
+
+#: main.c:2230
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tRežim pouze_pro_ètení (jako \"view\")"
+
+#: main.c:2231
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tOmezený režim (stejné jako \"rvim\")"
+
+#: main.c:2232
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tZmìny (ukládání souborù) zakázány"
+
+#: main.c:2233
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tZmìny (ukládání souborù) zakázány"
+
+#: main.c:2234
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tBinární režim"
+
+#: main.c:2236
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp režim"
+
+#: main.c:2238
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tKompatabilní s Vi: 'compatible'"
+
+#: main.c:2239
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tKompatibilita s Vi vypnuta: 'nocompatible'"
+
+#: main.c:2240
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tÚroveò výpisu hlášek"
+
+#: main.c:2241
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tLadící režim"
+
+#: main.c:2242
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tNebude vytváøet odkládací soubor, bude používat pouze pamì"
+
+#: main.c:2243
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tVypíše seznam odkládacích souborù a skonèí"
+
+#: main.c:2244
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r název souboru\tObnoví pøerušené sezení"
+
+#: main.c:2245
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tStejné jako -r"
+
+#: main.c:2247
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tNebude používat newcli pro otevøení okna"
+
+#: main.c:2248
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <zaøízení>\t\tPoužít <zaøízení> pro I/O"
+
+#: main.c:2251
+msgid "-H\t\t\tstart in Hebrew mode"
+msgstr "-H\t\t\tnastartuje v hebrejském režimu"
+
+#: main.c:2254
+msgid "-F\t\t\tstart in Farsi mode"
+msgstr "-F\t\t\tnastartuje ve Farsi režimu"
+
+#: main.c:2256
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminál>\tNastaví typ terminálu na <terminál>"
+
+#: main.c:2257
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tPoužije <vimrc> místo jakéhokoliv .vimrc"
+
+#: main.c:2259
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tPoužije <gvimrc> místo jakéhokoliv .gvimrc"
+
+#: main.c:2261
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tNenahraje 'plugin' skripty"
+
+#: main.c:2262
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tOtevøe N oken (implicitnì jedno pro každý soubor)"
+
+#: main.c:2263
+msgid "-O[N]\t\tlike -o but split vertically"
+msgstr "-O[N]\t\tJako -o but split vertically"
+
+#: main.c:2264
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tNastaví kurzor na konec souboru"
+
+#: main.c:2265
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<øádek>\t\tNastaví kurzor na <øádek>"
+
+#: main.c:2267
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <pøíkaz>\tPo nahrání prvního souboru vykoná <pøíkaz>"
+
+#: main.c:2269
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <pøíkaz>\t\tPo nahrání prvního souboru vykoná <pøíkaz>"
+
+#: main.c:2270
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr ""
+"-S <sezení>\t\tPo nahrání prvního souboru vykoná pøíkazy v souboru <sezení>"
+
+#: main.c:2271
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <skript>\t\tNaète pøíkazy normálního módu ze <skriptu>"
+
+#: main.c:2272
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <skript>\t\tPøipojí všechny napsané pøíkazy do souboru <skript>"
+
+#: main.c:2273
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <skript>\t\tUloží všechny napsané pøíkazy do souboru <skript>"
+
+#: main.c:2275
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tEditace zašifrovaných souborù"
+
+#: main.c:2279
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\tSpustí vim na daný X-server"
+
+#: main.c:2281
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tNepøipojí se k X serveru"
+
+#: main.c:2283
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tOtevøe Vim uvnitø jiného GTK widgetu"
+
+#: main.c:2287
+msgid "--remote <files>\tEdit <files> in a Vim server and exit"
+msgstr "--remote <soubory>\tEdituje <soubory> na Vim serveru a skonèí"
+
+#: main.c:2288
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr ""
+"--remote-wait <soubory> Jako --remote, ale èeká na soubory k editaci"
+
+#: main.c:2289
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <klávesy>\tPøedá <klávesy> Vim serveru a skonèí"
+
+#: main.c:2290
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <výraz>\tProvede <výraz> na serveru a zobrazí výsledek"
+
+#: main.c:2291
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tVypíše seznam dostupných Vim serverù a skonèí"
+
+#: main.c:2292
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr ""
+"--servername <jméno>\tZašle serveru <jméno>/stane se Vim serverem <jméno>"
+
+#: main.c:2295
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tPoužije <viminfo> místo jakéhokoliv .viminfo"
+
+#: main.c:2297
+msgid "-h\t\t\tprint Help (this message) and exit"
+msgstr "-h\t\t\tVypíše tuto nápovìdu a skonèí"
+
+#: main.c:2298
+msgid "--version\t\tprint version information and exit"
+msgstr "--version\t\tvypíše informace o verzi a skonèí"
+
+#: main.c:2302
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Pøepínaèe pro gvim (Motif verzi):\n"
+
+#: main.c:2305
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Pøepínaèe pro gvim (Athena verzi):\n"
+
+#: main.c:2308
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\tSpustí vim na <display>"
+
+#: main.c:2309
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tSpustí vim minimalizované"
+
+#: main.c:2311
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <název>\t\tPoužije resource jako by vim mìl <název>"
+
+#: main.c:2312
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (není implementováno)\n"
+
+#: main.c:2314
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <barva>\tNastaví <barvu> pozadí (také -bg)"
+
+#: main.c:2315
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <barva>\tNastaví <barvu> popøedí (také -fg)"
+
+#: main.c:2316 main.c:2336
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <písmo>\t\tNastaví <písmo> normálního textu (také -fn)"
+
+#: main.c:2317
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <písmo>\tNastaví <písmo> pro zvýraznìný text"
+
+#: main.c:2318
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <písmo>\tNastaví <písmo> pro kurzívu"
+
+#: main.c:2319 main.c:2337
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geometrie>\tNastaví <geometrii> (také -geom)"
+
+#: main.c:2320
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <šíøka>\tNastaví <šíøku> okrajù (také -bw)"
+
+#: main.c:2321
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <šíøku> Nastaví <šíøku> posunovací lišty (také: -sw)"
+
+#: main.c:2323
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <výška>\tNastaví <výšku> nabídky (také -mh)"
+
+#: main.c:2325 main.c:2338
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tPoužije reverzní barvy (také -rv)"
+
+#: main.c:2326
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tNepoužije reverzní barvy (také +rv)"
+
+#: main.c:2327
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\tNastaví zadaný <resource>"
+
+#: main.c:2330
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Pøepínaèe pro gvim (RISC OS verzi):\n"
+
+#: main.c:2331
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <poèet>\t<poèet> sloupcù na okno"
+
+#: main.c:2332
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <poèet>\t<poèet> øádkù na okno"
+
+#: main.c:2335
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Pøepínaèe pro gvim (GTK+ verzi):\n"
+
+#: main.c:2339
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\tSpustí vim na <display> (také --display)"
+
+#: main.c:2341
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tVypíše Gnome pøepínaèe"
+
+#. Failed to send, abort.
+#: main.c:2566
+msgid ""
+"\n"
+"Send failed.\n"
+msgstr ""
+"\n"
+"Pøedání výrazu selhalo.\n"
+
+#. Let vim start normally.
+#: main.c:2571
+msgid ""
+"\n"
+"Send failed. Trying to execute locally\n"
+msgstr ""
+"\n"
+"Pøedání selhalo. Zkouším provést lokálnì\n"
+
+#: main.c:2604 main.c:2625
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d z %d editováno"
+
+#: main.c:2648
+msgid "Send expression failed.\n"
+msgstr "Pøedání výrazu selhalo.\n"
+
+#: mark.c:660
+msgid "No marks set"
+msgstr "Nejsou nastaveny žádné znaèky"
+
+#: mark.c:662
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: \"%s\" nevyhovují žádné znaèky"
+
+#. Highlight title
+#: mark.c:673
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"znaèka øádek sloupec soubor/text"
+
+#. Highlight title
+#: mark.c:711
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" skok øádek sloupec soubor/text"
+
+#: mark.c:1073
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Souborové znaèky:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1108
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Seznam skokù (poèínaje nejnovìjší položkou):\n"
+
+#: mark.c:1203
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Historie znaèek v souborech (poèínaje nejnovìjší položkou):\n"
+
+#: mark.c:1286
+msgid "Missing '>'"
+msgstr "Chybí '>'"
+
+#: mbyte.c:395
+msgid "Not a valid codepage"
+msgstr "Chybná kódová stránka"
+
+#: mbyte.c:3014
+msgid "E284: Cannot set IC values"
+msgstr "E284: Nelze nastavit IC hodnoty"
+
+#: mbyte.c:3166
+msgid "E285: Failed to create input context"
+msgstr "E285: Nepodaøilo se vytvoøit vstupní kontext"
+
+#: mbyte.c:3313
+msgid "E286: Failed to open input method"
+msgstr "E286: Nepodaøilo se otevøít vstupní metodu"
+
+#: mbyte.c:3324
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: Varování: likvidaèní zpìtné volání nelze nastavit na IM"
+
+#: mbyte.c:3330
+msgid "E288: input method doesn't support any style"
+msgstr "E288: vstupní metoda nepodporuje žádný styl"
+
+#: mbyte.c:3387
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: vstupní metoda nepodporuje mùj 'preedit' typ"
+
+#: mbyte.c:3461
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: Nadbodový styl vyžaduje fontset"
+
+#: mbyte.c:3489
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: Máte GTK+ verze starší než 1.2.3. Stavová plocha vypnuta."
+
+#: mbyte.c:3726
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Server vstupních metod nebìží"
+
+#: memfile.c:473
+msgid "E293: block was not locked"
+msgstr "E293: blok nebyl zamknut"
+
+#: memfile.c:972
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Chyba posunu ukazovátka pøi ètení odkládacího souboru"
+
+#: memfile.c:977
+msgid "E295: Read error in swap file"
+msgstr "E295: Chyba pøi ètení odkládacího souboru"
+
+#: memfile.c:1029
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Chyba posunu ukazovátka pøi ukládání do odkládacího souboru"
+
+#: memfile.c:1047
+msgid "E297: Write error in swap file"
+msgstr "E297: Chyba pøi ukládání do odkládacího souboru"
+
+#: memfile.c:1244
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr ""
+"E300: Odkládací soubor již existuje! (Nìkdo hackujepøes nastražený symlink?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Nelze získat blok 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Nelze získat blok 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: nelze získat blok 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Jéje, odkládací soubor byl ztracen!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: Nelze pøejmenovat odkládací soubor"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: Nelze otevøít odkládací soubor pro \"%s\""
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: nelze získat blok 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Odkládací soubor pro %s nebyl nalezen"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr ""
+"Zadejte èíslo odkládacího souboru, který se má použít (0 pro ukonèení): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: Nelze otevøít %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "Nelze èíst blok 0 z "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Možná nedošlo k žádným zmìnám, nebo Vim neaktualizoval odkládací soubor."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " nelze použít s touto verzí Vim.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Použijte Vim verze 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s se nezdá být odkládacím souborem Vim"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " nelze použít na tomto poèítaèi.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "Soubor byl vytvoøen "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"nebo byl soubor poškozen."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "Používám odkládací soubor \"%s\""
+
+#: memline.c:915
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Pùvodní soubor \"%s\""
+
+#: memline.c:934
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Varování: Pùvodní soubor mohl být zmìnìn"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Nelze èíst blok 1 z %s"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???CHYBÍ MNOHO ØÁDKÙ"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???CHYBNÝ POÈET ØÁDKÙ"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???PRÁZDNÝ BLOK"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???CHYBÌJÍCÍ ØÁDKY"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ID bloku 1 je chybné (je %s odkládacím souborem?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???CHYBÍ BLOK"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "od ??? po ???END mohou být øádky pomíchané"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "od ??? po ???END mohou být vložené/smazané øádky"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???KONEC"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Obnova pøerušena"
+
+#: memline.c:1145
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr ""
+"E312: V prùbìhu obnovy došlo k chybám; zkontrolujte øádky zaèínající na ???"
+
+#: memline.c:1148
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Obnova dokonèena. Zkontrolujte, zda je vše v poøádku."
+
+#: memline.c:1149
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Zvažte uložení tohoto souboru pod jiným názvem\n"
+
+#: memline.c:1150
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "a kontrolu zmìn pomocí programu diff.)\n"
+
+#: memline.c:1151
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr "Poté smažte odkládací soubor.\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1207
+msgid "Swap files found:"
+msgstr "Nalezené odkládací soubory:"
+
+#: memline.c:1385
+msgid " In current directory:\n"
+msgstr " V aktuálním adresáøi:\n"
+
+#: memline.c:1387
+msgid " Using specified name:\n"
+msgstr " Se zadaným názvem:\n"
+
+#: memline.c:1391
+msgid " In directory "
+msgstr " V adresáøi "
+
+#: memline.c:1409
+msgid " -- none --\n"
+msgstr " -- žádné --\n"
+
+#: memline.c:1481
+msgid " owned by: "
+msgstr " vlastník: "
+
+#: memline.c:1483
+msgid " dated: "
+msgstr " datum vytvoøení: "
+
+#: memline.c:1487 memline.c:3680
+msgid " dated: "
+msgstr " datum vytvoøení: "
+
+#: memline.c:1503
+msgid " [from Vim version 3.0]"
+msgstr " [od Vim verze 3.0]"
+
+#: memline.c:1507
+msgid " [does not look like a Vim swap file]"
+msgstr " [nevypadá jako odkládací soubor Vim]"
+
+#: memline.c:1511
+msgid " file name: "
+msgstr " název souboru: "
+
+#: memline.c:1523
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" datum zmìny: "
+
+#: memline.c:1524
+msgid "YES"
+msgstr "ANO"
+
+#: memline.c:1524
+msgid "no"
+msgstr "ne"
+
+#: memline.c:1528
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" uživatelské jméno: "
+
+#: memline.c:1535
+msgid " host name: "
+msgstr " název poèítaèe: "
+
+#: memline.c:1537
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" název poèítaèe: "
+
+#: memline.c:1543
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ID procesu : "
+
+#: memline.c:1549
+msgid " (still running)"
+msgstr " (stále aktivní)"
+
+#: memline.c:1561
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [nepoužitelné s touto verzí Vim]"
+
+#: memline.c:1564
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [nepoužitelné na tomto poèítaèi]"
+
+#: memline.c:1569
+msgid " [cannot be read]"
+msgstr " [nelze pøeèíst]"
+
+#: memline.c:1573
+msgid " [cannot be opened]"
+msgstr " [nelze otevøít]"
+
+#: memline.c:1763
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Nelze zachovat - odkládací soubor neexistuje."
+
+#: memline.c:1816
+msgid "File preserved"
+msgstr "Soubor zachován"
+
+#: memline.c:1818
+msgid "E314: Preserve failed"
+msgstr "E314: Uchování se nezdaøilo"
+
+#: memline.c:1889
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: chybné èíslo øádku: %ld"
+
+#: memline.c:1915
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: nelze nalézt øádek %ld"
+
+#: memline.c:2303
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: chybné id ukazatele na blok 3"
+
+#: memline.c:2383
+msgid "stack_idx should be 0"
+msgstr "stack_idx by mìlo mít hodnotu 3"
+
+#: memline.c:2445
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Aktualizováno pøíliš mnoho blokù?"
+
+#: memline.c:2602
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: chybné id ukazatele na blok 4"
+
+#: memline.c:2629
+msgid "deleted block 1?"
+msgstr "smazán blok 1?"
+
+#: memline.c:2829
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Nelze nalézt øádek %ld"
+
+#: memline.c:3072
+msgid "E317: pointer block id wrong"
+msgstr "E317: chybné id ukazatele na blok"
+
+#: memline.c:3088
+msgid "pe_line_count is zero"
+msgstr "pe_line_count má nulovou hodnotu"
+
+#: memline.c:3117
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: poèet øádkù mimo rozsah: %ld > celkový poèet øádkù"
+
+#: memline.c:3121
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: chybný poèet øádkù v bloku %ld"
+
+#: memline.c:3170
+msgid "Stack size increases"
+msgstr "Nárùst velikosti zásobníku"
+
+#: memline.c:3216
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: chybné id ukazatele na blok 2"
+
+#: memline.c:3670
+msgid "E325: ATTENTION"
+msgstr "E325: POZOR"
+
+#: memline.c:3671
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Nalezen odkládací soubor se jménem \""
+
+#: memline.c:3675
+msgid "While opening file \""
+msgstr "Pøi otevírání souboru\""
+
+#: memline.c:3684
+msgid " NEWER than swap file!\n"
+msgstr " NOVÌJŠÍ než odkládací soubor!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3688
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Soubor mùže být editován jiným programem.\n"
+" Je-li tomu tak, pak si dejte pozor, aby jste po uložení zmìn\n"
+" nemìli dvì rùzné verze téhož souboru.\n"
+
+#: memline.c:3689
+msgid " Quit, or continue with caution.\n"
+msgstr " Ukonèete program, nebo opatrnì pokraèujte v editaci.\n"
+
+#: memline.c:3690
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) Editace tohoto souboru byla pøerušena neèekaným ukonèením programu.\n"
+
+#: memline.c:3691
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Je-li tomu tak, pak použijte \":recover\" èi \"vim -r "
+
+#: memline.c:3693
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" pro odstranìní zmìn (viz \":help recovery)\".\n"
+
+#: memline.c:3694
+msgid " If you did this already, delete the swap file \""
+msgstr " Pokud jste tak již uèinil, tak smažte odkládací soubor \""
+
+#: memline.c:3696
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" a tato zpráva se již nebude objevovat.\n"
+
+#: memline.c:3710 memline.c:3714
+msgid "Swap file \""
+msgstr "Odkládací soubor \""
+
+#: memline.c:3711 memline.c:3717
+msgid "\" already exists!"
+msgstr "\" již existuje!"
+
+#: memline.c:3720
+msgid "VIM - ATTENTION"
+msgstr "VIM - POZOR"
+
+#: memline.c:3722
+msgid "Swap file already exists!"
+msgstr "Odkládací soubor již existuje!"
+
+#: memline.c:3726
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"&Otevøít pouze pro ètení\n"
+"&Pokraèovat v editaci\n"
+"O&bnovit soubor\n"
+"&Konec"
+
+#: memline.c:3728
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"&Otevøít pouze pro ètení\n"
+"&Pokraèovat v editaci\n"
+"O&bnovit soubor\n"
+"&Konec\n"
+"&Smazat"
+
+#: memline.c:3781
+msgid "E326: Too many swap files found"
+msgstr "E326: Pøíliš mnoho odkládacích souborù"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Èásti cesty k pøedmìtu nabídky není podnabídkou"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Nabídka existuje pouze v jiném módu"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Nabídka tohoto jména neexistuje"
+
+#: menu.c:503
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Cesta nabídkou nesmí vést do podnabídky"
+
+#: menu.c:542
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: Položky nabídky nelze pøidávat pøímo na lištu"
+
+#: menu.c:548
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Oddìlovaè nesmí být èástí cesty nabídkou"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1063
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Nabídky ---"
+
+#: menu.c:1989
+msgid "Tear off this menu"
+msgstr "Odtrhnout tuto nabídku"
+
+#: menu.c:2054
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Cesta nabídkou musí vést k položce nabídky"
+
+#: menu.c:2074
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Vzor nenalezen: %s"
+
+#: menu.c:2143
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: V %s módu není nabídka definována"
+
+#: menu.c:2181
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Cesta nabídkou musí vést do podnabídky"
+
+#: menu.c:2202
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Nabídka nenalezena - zkontrolujte názvy nabídek"
+
+#: message.c:467
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Chyba pøi zpracování %s:"
+
+#: message.c:483
+#, c-format
+msgid "line %4ld:"
+msgstr "øádek %4ld:"
+
+#: message.c:523
+msgid "[string too long]"
+msgstr "[pøíliš dlouhý øetìzec]"
+
+#: message.c:669
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "Správce zpráv: Bram Moolenaar <Bram@vim.org>"
+
+#: message.c:881
+msgid "Interrupt: "
+msgstr "Pøerušení: "
+
+#: message.c:884
+msgid "Hit ENTER to continue"
+msgstr "pokraèování stiskem ENTER"
+
+#: message.c:886
+msgid "Hit ENTER or type command to continue"
+msgstr "Pro pokraèování stisknìte ENTER nebo zadejte pøíkaz"
+
+#: message.c:1940
+msgid "-- More --"
+msgstr "-- Pokraèování --"
+
+#: message.c:1943
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: øádek, MEZERNÍK/b: stránka, d/u: 0.5 stránky, q: konec)"
+
+#: message.c:1944
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: øádek, MEZERNÍK: stránka, d: 0.5 stránky, q: konec)"
+
+#: message.c:2419 message.c:2434
+msgid "Question"
+msgstr "Otázka"
+
+#: message.c:2421
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Ano\n"
+"&Ne"
+
+#: message.c:2436
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Ano\n"
+"&Ne\n"
+"&Zrušit"
+
+#: message.c:2454
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Ano\n"
+"&Ne\n"
+"&Uložit vše\n"
+"Zahodit &vše\n"
+"&Zrušit"
+
+#: message.c:2494
+msgid "Save File dialog"
+msgstr "Dialog pro ukládání souborù"
+
+#: message.c:2496
+msgid "Open File dialog"
+msgstr "Dialog pro otevírání souborù"
+
+#. TODO: non-GUI file selector here
+#: message.c:2547
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: Lituji, ale konzolová verze nepodporuje prohlížeè souborù"
+
+#: misc1.c:2449
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: wc1: mìním soubor pouze_pro_ètení"
+
+#: misc1.c:2678
+msgid "1 more line"
+msgstr "poèet nových øádkù: 1"
+
+#: misc1.c:2680
+msgid "1 line less"
+msgstr "poèet smazaných øádkù: 1"
+
+#: misc1.c:2685
+#, c-format
+msgid "%ld more lines"
+msgstr "poèet nových øádkù: %ld"
+
+#: misc1.c:2687
+#, c-format
+msgid "%ld fewer lines"
+msgstr "poèet smazaných øádkù: %ld"
+
+#: misc1.c:2690
+msgid " (Interrupted)"
+msgstr "(Pøerušeno)"
+
+#: misc1.c:6245
+msgid "Vim: preserving files...\n"
+msgstr "Vim: zachovávám soubory...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6255
+msgid "Vim: Finished.\n"
+msgstr "Vim: ukonèen\n"
+
+#: misc2.c:647 misc2.c:663
+msgid "ERROR: "
+msgstr "CHYBA: "
+
+#: misc2.c:667
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bajtù] celkem uvolnìno-alokováno %lu-%lu, využito %lu, maximální využití "
+"%lu\n"
+
+#: misc2.c:669
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[volání] celkem re/malloc(): %lu, celkem free() %lu\n"
+"\n"
+
+#: misc2.c:724
+msgid "E340: Line is becoming too long"
+msgstr "E340: Øádek se stává pøíliš dlouhým"
+
+#: misc2.c:768
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Vnitøní chyba: lalloc(%ld, )"
+
+#: misc2.c:876
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Nedostatek pamìti! (potøebuji alokovat bajtù: %lu)"
+
+#: misc2.c:2511
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Spouštím pøíkaz \"%s\" pomocí shellu"
+
+#: misc2.c:2706 misc2.c:5148 option.c:4584
+msgid "Missing colon"
+msgstr "Chybí dvojteèka"
+
+#: misc2.c:2708 misc2.c:2735
+msgid "Illegal mode"
+msgstr "nepøípustný mód"
+
+#: misc2.c:2774
+msgid "Illegal mouseshape"
+msgstr "Chybný tvar myši"
+
+#: misc2.c:2814 misc2.c:5168
+msgid "digit expected"
+msgstr "oèekávána èíslice"
+
+#: misc2.c:2819
+msgid "Illegal percentage"
+msgstr "nepøípustné procento"
+
+#: misc2.c:3123
+msgid "Enter encryption key: "
+msgstr "Zadejte šifrovací klíè: "
+
+#: misc2.c:3124
+msgid "Enter same key again: "
+msgstr "Zadejte ještì jednou tentýž klíè:"
+
+#: misc2.c:3134
+msgid "Keys don't match!"
+msgstr "Klíèe se neshodují"
+
+#: misc2.c:3648
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Chybná cesta: '**[èíslo] musí být buï na konci cesty, nebo musí být\n"
+"následováno'%s. Viz :help path."
+
+#: misc2.c:4905
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Adresáø \"%s\" nelze v cdpath nalézt"
+
+#: misc2.c:4908
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Soubor \"%s\" nelze v path nalézt"
+
+#: misc2.c:4914
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: Žádný další adresáø \"%s\" nebyl v cdpath nalezen"
+
+#: misc2.c:4917
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: Žádný další soubor \"%s\" nebyl v cestì nalezen"
+
+#: misc2.c:5160
+msgid "Illegal component"
+msgstr "nepøípustná souèást"
+
+#: normal.c:2813
+msgid "Warning: terminal cannot highlight"
+msgstr "Varování: terminál nepodporuje zvýrazòování"
+
+#: normal.c:3008
+msgid "E348: No string under cursor"
+msgstr "E348: pod kurzorem není žádný øetìzec"
+
+#: normal.c:3010
+msgid "E349: No identifier under cursor"
+msgstr "E349: pod kurzorem není žádný identifikátor"
+
+#: normal.c:4175
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: pomocí aktuální 'foldmethod' nelze mazat záhyby"
+
+#: ops.c:271
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "poèet øádkù posunutých jednou pomocí %s : 1"
+
+#: ops.c:273
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "Poèet øádkù posunutých pomocí %s %d-krát : 1"
+
+#: ops.c:278
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "Poèet øádkù: %ld (posunutých jednou pomocí %s)"
+
+#: ops.c:281
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "Poèet øádkù: %ld (posunutých pomocí %s %d-krát)"
+
+#: ops.c:638
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "poèet øádkù k odsazení: %ld"
+
+#: ops.c:688
+msgid "1 line indented "
+msgstr "poèet øádkù k odsazení: 1"
+
+#: ops.c:690
+#, c-format
+msgid "%ld lines indented "
+msgstr "poèet odsazených øádkù: %ld"
+
+#. must display the prompt
+#: ops.c:1528
+msgid "cannot yank; delete anyway"
+msgstr "nelze kopírovat; pøesto smazáno"
+
+#: ops.c:2018
+msgid "1 line changed"
+msgstr "poèet øádek se zmìnìnou velikostí písmen: 1"
+
+#: ops.c:2020
+#, c-format
+msgid "%ld lines changed"
+msgstr "poèet øádek se zmìnìnou velikostí písmen: %ld"
+
+#: ops.c:2381
+#, c-format
+msgid "freeing %ld lines"
+msgstr "poèet uvolòovaných øádkù: %ld"
+
+#: ops.c:2658
+msgid "1 line yanked"
+msgstr "poèet zkopírovaných øádkù: 1"
+
+#: ops.c:2660
+#, c-format
+msgid "%ld lines yanked"
+msgstr "poèet zkopírovaných øádkù: %ld"
+
+#: ops.c:2916
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: Registr %s je prázdný"
+
+#. Highlight title
+#: ops.c:3454
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Registry ---"
+
+#: ops.c:4565
+msgid "Illegal register name"
+msgstr "nepøípustný název registru"
+
+#: ops.c:4645
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Registry:\n"
+
+#: ops.c:4671
+#, c-format
+msgid "Unknown register type %d"
+msgstr "%d není známým typem registru"
+
+#: ops.c:5052
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: '%s' není pøípustné jméno registru"
+
+#: ops.c:5393
+#, c-format
+msgid "%ld Cols; "
+msgstr "øádkù: %ld;"
+
+#: ops.c:5400
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Vybráno %s%ld z %ld øádkù; %ld z %ld slov; %ld z %ld Bytù"
+
+#: ops.c:5416
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Sloupec %s z %s; Øádek %ld z %ld; Slovo %ld z %ld; Byte %ld z %ld"
+
+#: ops.c:5427
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld pro BOM)"
+
+#: option.c:1989
+msgid "Thanks for flying Vim"
+msgstr "Dìkuji za použití Vim"
+
+#: option.c:3175
+msgid "Option not supported"
+msgstr "Volba není podporována"
+
+#: option.c:3200
+msgid "Not allowed in a modeline"
+msgstr "Není v modeline povoleno"
+
+#: option.c:3256
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tNaposledy nastavena z "
+
+#: option.c:3395
+msgid "Number required after ="
+msgstr "Po = je vyžadováno èíslo"
+
+#: option.c:3702 option.c:4309
+msgid "Not found in termcap"
+msgstr "Nenalezen v termcapu"
+
+#: option.c:3768
+#, c-format
+msgid "Illegal character <%s>"
+msgstr "Nepøípustný znak <%s>"
+
+#: option.c:4294 option.c:5497
+msgid "Not allowed here"
+msgstr "Toto zde není povoleno"
+
+#: option.c:4301
+msgid "Cannot set 'term' to empty string"
+msgstr "volba 'term' nemùže být prázdná"
+
+#: option.c:4304
+msgid "Cannot change term in GUI"
+msgstr "V GUI nelze mìnit term"
+
+#: option.c:4306
+msgid "Use \":gui\" to start the GUI"
+msgstr "Použijte \"gui\" pro spuštìní GUI"
+
+#: option.c:4327
+msgid "'backupext' and 'patchmode' are equal"
+msgstr "volby 'backupext' a 'patchmode' mají stejnou hodnotu"
+
+#: option.c:4586
+msgid "Zero length string"
+msgstr "øetìzec o nulové délce"
+
+#: option.c:4654
+#, c-format
+msgid "Missing number after <%s>"
+msgstr "Po <%s> chybí èíslo"
+
+#: option.c:4668
+msgid "Missing comma"
+msgstr "Chybí èárka"
+
+#: option.c:4675
+msgid "Must specify a ' value"
+msgstr "Je nutné zadat hodnotu '"
+
+#: option.c:4715
+msgid "contains unprintable character"
+msgstr "obsahuje netisknutelné znaky"
+
+#: option.c:4728
+msgid "Invalid font(s)"
+msgstr "Chybná písma"
+
+#: option.c:4734
+msgid "can't select fontset"
+msgstr "nelze vybrat sadu písem"
+
+#: option.c:4736
+msgid "Invalid fontset"
+msgstr "chybná sada písem"
+
+#: option.c:4743
+msgid "can't select wide font"
+msgstr "nelze vybrat široký font"
+
+#: option.c:4745
+msgid "Invalid wide font"
+msgstr "Chybné široké písmo"
+
+#: option.c:5014
+#, c-format
+msgid "Illegal character after <%c>"
+msgstr "Nepøípustný znak po <%c>"
+
+#: option.c:5097
+msgid "comma required"
+msgstr "je nutná èárka"
+
+#: option.c:5106
+#, c-format
+msgid "'commentstring' must be empty or contain %s"
+msgstr "volba `commentstring` musí být buï prázdná nebo nastavená na %s"
+
+#: option.c:5153
+msgid "No mouse support"
+msgstr "Bez podpory myši"
+
+#: option.c:5399
+msgid "Unclosed expression sequence"
+msgstr "neuzavøená sekvence výrazù"
+
+#: option.c:5403
+msgid "too many items"
+msgstr "pøíliš mnoho položek"
+
+#: option.c:5405
+msgid "unbalanced groups"
+msgstr "nevyvážené skupiny"
+
+#: option.c:5620
+msgid "A preview window already exists"
+msgstr "Okno náhledu již existuje"
+
+#: option.c:5881 option.c:5910
+msgid "'winheight' cannot be smaller than 'winminheight'"
+msgstr ""
+"hodnota volby 'winheight' nesmí být menší než hodnota volby 'winminheight'"
+
+#: option.c:5926 option.c:5945
+msgid "'winwidth' cannot be smaller than 'winminwidth'"
+msgstr ""
+"hodnota volby 'winwidth' nesmí být menší než hodnota volby 'winminwidth'"
+
+#: option.c:6085
+#, c-format
+msgid "Need at least %d lines"
+msgstr "minimální potøebný poèet øádkù: %d"
+
+#: option.c:6094
+#, c-format
+msgid "Need at least %d columns"
+msgstr "minimální potøebný poèet sloupcù: %d"
+
+#: option.c:6391
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Neznámá volba: %s"
+
+#: option.c:6500
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Kódy terminálu ---"
+
+#: option.c:6502
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Nastavení globálních voleb ---"
+
+#: option.c:6504
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Nastavení lokálních voleb ---"
+
+#: option.c:6506
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Volby ---"
+
+#: option.c:7196
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp CHYBA"
+
+#: option.c:8112
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': pro %s chybí vyhovující znak"
+
+#: option.c:8146
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': nadbyteèné znaky po støedníku: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "nelze otevøít "
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Nelze otevøít nové okno!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Vyžaduje Amigados verze 2.04 nebo vyšší\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Vyžaduje %s verze %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "Nelze otevøít NIL:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr " Nelze vytvoøit "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim bude ukonèen %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "Nelze zmìnit mód konzole ?!\n"
+
+#: os_amiga.c:938 os_mac.c:1168 os_mswin.c:619 os_riscos.c:728 os_unix.c:2726
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Nastavování režimu obrazovky není podporováno"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: neni konzole??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1142
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Nelze spustit shell s parametrem -f"
+
+#: os_amiga.c:1183 os_amiga.c:1273
+msgid "Cannot execute "
+msgstr "Nelze spustit "
+
+#: os_amiga.c:1186 os_amiga.c:1283
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1206 os_amiga.c:1308
+msgid " returned\n"
+msgstr " návratová hodnota shellu\n"
+
+#: os_amiga.c:1448
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE je pøíliš malá."
+
+#: os_amiga.c:1452
+msgid "I/O ERROR"
+msgstr "I/O CHYBA"
+
+#: os_mswin.c:503
+msgid "...(truncated)"
+msgstr "...(kráceno)"
+
+#: os_mswin.c:594
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' není 80, nelze spustit externí pøíkaz"
+
+#: os_mswin.c:706 os_unix.c:4945
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Volání knihovní funkce \"%s()\" selhalo"
+
+#: os_mswin.c:1340
+msgid "E237: Printer selection failed"
+msgstr "E237: Nelze zvolit tiskárnu"
+
+#: os_mswin.c:1388
+#, c-format
+msgid "to %s on %s"
+msgstr "do %s v %s"
+
+#: os_mswin.c:1449 os_mswin.c:1459
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Chyba tisku: %s"
+
+#: os_mswin.c:1460
+msgid "Unknown"
+msgstr "Neznámý"
+
+#: os_mswin.c:1487
+#, c-format
+msgid "Printing '%s'"
+msgstr "Vytištìno '%s'"
+
+#: os_mswin.c:2551
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Nepøípustná jméno znakové sady \"%s\" ve fontu \"%s\""
+
+#: os_mswin.c:2559
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Nepøípustný znak '%c' ve fontu \"%s\""
+
+#: os_riscos.c:1227
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Neplatný 'osfiletype' - použit Text"
+
+#: os_unix.c:800
+msgid "Vim: Double signal, exiting\n"
+msgstr "VIm: dvojitý signál, konèím\n"
+
+#: os_unix.c:806
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Zachycen smrtelný signál %s\n"
+
+#: os_unix.c:809
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Zachycen smrtelný signál\n"
+
+#: os_unix.c:1063
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Doba otevírání X displeje (v ms): %ld"
+
+#: os_unix.c:1090
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: chyba X11\n"
+
+#: os_unix.c:1157
+msgid "Testing the X display failed"
+msgstr "Test X displeje se nezdaøil"
+
+#: os_unix.c:1301
+msgid "Opening the X display timed out"
+msgstr "Vypršel èas pøi èekání na otevøení X displeje"
+
+#: os_unix.c:2899 os_unix.c:3483
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"nelze spustit shell "
+
+#: os_unix.c:2944
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Nelze spustit sh shell\n"
+
+#: os_unix.c:2948 os_unix.c:3489
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+" návratová hodnota shellu "
+
+#: os_unix.c:3082
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Nelze vytvoøit roury\n"
+
+#: os_unix.c:3097
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"Volání fork selhalo\n"
+
+#: os_unix.c:3496
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Pøíkaz ukonèen\n"
+
+#: os_unix.c:4993
+msgid "Opening the X display failed"
+msgstr "Otevøení X displeje se nezdaøilo"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "Na øádku"
+
+#: os_w32exe.c:169
+msgid "Could not load vim32.dll!"
+msgstr "Nelze naèíst vim32.dll!"
+
+#: os_w32exe.c:169 os_w32exe.c:179
+msgid "VIM Error"
+msgstr "Chyba VIMu"
+
+#: os_w32exe.c:179
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Nelze nastavit ukazatele funkcí na DLL"
+
+#: os_win16.c:578 os_win32.c:3021
+#, c-format
+msgid "shell returned %d"
+msgstr "návratová hodnota shellu %d"
+
+#: os_win32.c:2489
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Zachycen %s signál\n"
+
+#: os_win32.c:2491
+msgid "close"
+msgstr "zavøít"
+
+#: os_win32.c:2493
+msgid "logoff"
+msgstr "logoff"
+
+#: os_win32.c:2494
+msgid "shutdown"
+msgstr "shutdown"
+
+#: os_win32.c:2975
+msgid "E371: Command not found"
+msgstr "E371: Pøíkaz není k dispozici"
+
+#: os_win32.c:2988
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE se nevyskytuje ve Vaší $PATH.\n"
+"Externí pøíkazy nebudou "
+
+#: os_win32.c:2991
+msgid "Vim Warning"
+msgstr "Varování"
+
+#: quickfix.c:281
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Pøíliš mnoho %%%c ve formátovacím øetìzci"
+
+#: quickfix.c:294
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: Neoèekávaný výskyt %%%c ve formátovacím øetìzci"
+
+#: quickfix.c:348
+msgid "E374: Missing ] in format string"
+msgstr "E374: Ve formátovacím øetìzci chybí ]"
+
+#: quickfix.c:362
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: %%%c Nepodporovaná formátová specifikace ve formátovacím øetìzci"
+
+#: quickfix.c:380
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: Nepøípustné %%%c v prefixu formátovacího øetìzce"
+
+#: quickfix.c:388
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: Nepøípustné %%%c ve formátovacím øetìzci"
+
+#: quickfix.c:414
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' neobsahuje žádný vzorek"
+
+#: quickfix.c:520
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Chybìjící nebo prázdný název adresáøe"
+
+#: quickfix.c:931
+msgid "No more items"
+msgstr "Žádné další položky"
+
+#: quickfix.c:1152
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d/%d)%s%s: "
+
+#: quickfix.c:1154
+msgid " (line deleted)"
+msgstr " (øádek smazán)"
+
+#: quickfix.c:1360
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Konec quickfix seznamu"
+
+#: quickfix.c:1369
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Zaèátek quickfix seznamu"
+
+#: quickfix.c:1381
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "seznam chyb %d z %d; poèet chyb: %d"
+
+#: quickfix.c:1842
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: Nelze uložit, je nastavena volba 'buftype'"
+
+#: regexp.c:801
+msgid "E339: Pattern too long"
+msgstr "E339: Vzor je pøíliš dlouhý"
+
+#: regexp.c:1315
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: %s*"
+
+#: regexp.c:1318
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: %s%c"
+
+#: regexp.c:1467
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c nic není"
+
+#: regexp.c:2469
+#, c-format
+msgid "Syntax error in %s{...}"
+msgstr "Chyba syntaxe v %s{...}"
+
+#: regexp.c:2716
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Zachyceno pøeteèení zásobníku: pøíliš složitý regulární výraz?"
+
+#: regexp.c:2851
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: vzorek zpùsobil pøeteèení zásobníku"
+
+#: regexp.c:3087
+msgid "External submatches:\n"
+msgstr "Vnìjší podøazené shody:\n"
+
+#: screen.c:2054
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "poèet øádkù v záhybu: %3ld"
+
+#: screen.c:7426
+msgid " VREPLACE"
+msgstr " VREPLACE"
+
+#: screen.c:7430
+msgid " REPLACE"
+msgstr " REPLACE"
+
+#: screen.c:7435
+msgid " REVERSE"
+msgstr " REVERSE"
+
+#: screen.c:7437
+msgid " INSERT"
+msgstr " INSERT"
+
+#: screen.c:7440
+msgid " (insert)"
+msgstr " (insert)"
+
+#: screen.c:7442
+msgid " (replace)"
+msgstr " (replace)"
+
+#: screen.c:7444
+msgid " (vreplace)"
+msgstr " (vreplace)"
+
+#: screen.c:7447
+msgid " Hebrew"
+msgstr " hebrejský"
+
+#: screen.c:7455
+msgid " (lang)"
+msgstr " (lang)"
+
+#: screen.c:7458
+msgid " (paste)"
+msgstr " (paste)"
+
+#: screen.c:7464
+msgid " SELECT"
+msgstr " SHODY"
+
+#: screen.c:7466
+msgid " VISUAL"
+msgstr " VIZUÁLNÍ"
+
+#: screen.c:7468
+msgid " BLOCK"
+msgstr " BLOK"
+
+#: screen.c:7470
+msgid " LINE"
+msgstr " ØÁDEK"
+
+#: screen.c:7483 screen.c:7537
+msgid "recording"
+msgstr "nahrávám"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "hledání dosáhlo zaèátku, pokraèování od konce"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "hledání dosáhlo konce, pokraèování od zaèátku"
+
+#: search.c:440
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Nepøípustný hledaný øetìzec: %s"
+
+#: search.c:747
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: hledaný dosáhlo zaèátku bez nalezení %s"
+
+#: search.c:749
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: hledaný dosáhlo konce bez nalezení %s"
+
+#: search.c:1107
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: Po ';' oèekávám '?' nebo '/'"
+
+#: search.c:3476
+msgid " (includes previously listed match)"
+msgstr " (vèetnì již vypsaných shod)"
+
+#. cursor at status line
+#: search.c:3496
+msgid "--- Included files "
+msgstr "--- Vložené soubory"
+
+#: search.c:3498
+msgid "not found "
+msgstr " nenalezeny"
+
+#: search.c:3499
+msgid "in path ---\n"
+msgstr "v cestì ---\n"
+
+#: search.c:3538
+msgid " (Already listed)"
+msgstr " (Již vypsáno)"
+
+#: search.c:3540
+msgid " NOT FOUND"
+msgstr " NENALEZENY"
+
+#: search.c:3592
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Prohledávám vložené soubory: %s"
+
+#: search.c:3810
+msgid "E387: Match is on current line"
+msgstr "E387: Shoda je na aktuálním øádku"
+
+#: search.c:3950
+msgid "All included files were found"
+msgstr "Všechny vložené soubory byly nalezeny"
+
+#: search.c:3952
+msgid "No included files"
+msgstr "Žádné vložené soubory"
+
+#: search.c:3968
+msgid "E388: Couldn't find definition"
+msgstr "E388: Nelze nalézt definici"
+
+#: search.c:3970
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Nelze nalézt vzorek"
+
+#: syntax.c:2991
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: nepøípustný argument: %s"
+
+#: syntax.c:3168
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: Syntaktická sestava %s neexistuje"
+
+#: syntax.c:3332
+msgid "No Syntax items defined for this buffer"
+msgstr "Pro tento buffer nejsou definovány žádné pøedmìty syntaxe"
+
+#: syntax.c:3340
+msgid "syncing on C-style comments"
+msgstr "synchronizuji komentáøe v C stylu"
+
+#: syntax.c:3348
+msgid "no syncing"
+msgstr "žádná synchronizace"
+
+#: syntax.c:3351
+msgid "syncing starts "
+msgstr "synchronizace zaèíná "
+
+#: syntax.c:3353 syntax.c:3422
+msgid " lines before top line"
+msgstr " øádkù pøed zaèátkem"
+
+#: syntax.c:3357
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Položky synchronizace syntaxe ---"
+
+#: syntax.c:3360
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"synchronizuji pøedmìty"
+
+#: syntax.c:3365
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Pøedmìty syntaxe ---"
+
+#: syntax.c:3388
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: Syntaktická sestava %s neexistuje"
+
+#: syntax.c:3412
+msgid "minimal "
+msgstr "minimální "
+
+#: syntax.c:3419
+msgid "maximal "
+msgstr "maximální "
+
+#: syntax.c:4047
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: group[t]here nesmí být na tomto místì"
+
+#: syntax.c:4071
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: Pro %s chybí položka regionu"
+
+#: syntax.c:4099
+msgid "E395: contains argument not accepted here"
+msgstr "E395: obsahuje argumenty, které zde nejsou povoleny"
+
+#: syntax.c:4110
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: obsahuje argumenty, které zde nejsou povoleny"
+
+#: syntax.c:4188
+msgid "E397: Filename required"
+msgstr "E397: Vyžadován název souboru"
+
+#: syntax.c:4524
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Chybí '=': %s"
+
+#: syntax.c:4680
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Pøíliš málo argumentù: oblast syntaxe %s"
+
+#: syntax.c:5011
+msgid "E400: No cluster specified"
+msgstr "E400: Nebyla zadána žádná sestava"
+
+#: syntax.c:5048
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Oddìlovaè vzorku %s nenalezen"
+
+#: syntax.c:5123
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Chyba za vzorkem %s"
+
+#: syntax.c:5205
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: synchronizace syntaxe: vzorek pokraèování øádkù zadán dvakrát"
+
+#: syntax.c:5262
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: nepøípustný argument: %s"
+
+#: syntax.c:5312
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Chybí rovnítko: %s"
+
+#: syntax.c:5318
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Prázdný argument: %s"
+
+#: syntax.c:5345
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s zde není povoleno"
+
+#: syntax.c:5352
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s musí být první v 'contains' seznamu"
+
+#: syntax.c:5422
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Neznámá název skupiny: %s"
+
+#: syntax.c:5645
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: chybný podøazený pøíkaz :syntax : %s "
+
+#: syntax.c:6024
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: skupina zvýraznìní %s nebyla nalezena"
+
+#: syntax.c:6048
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Pøíliš málo argumentù: \":highlight link %s\""
+
+#: syntax.c:6055
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: Pøíliš mnoho argumentù: \":highlight link %s\""
+
+#: syntax.c:6075
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: skupina je nastavena, odkaz na zvýrazòovací skupinu ignorován"
+
+#: syntax.c:6204
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: neèekané rovnítko : %s"
+
+#: syntax.c:6240
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: chybné rovnítko: %s"
+
+#: syntax.c:6262
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: chybí argument: %s"
+
+#: syntax.c:6299
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: nepøípustná hodnota: %s"
+
+#: syntax.c:6418
+msgid "E419: FG color unknown"
+msgstr "E419: barva popøedí není známá"
+
+#: syntax.c:6429
+msgid "E420: BG color unknown"
+msgstr "E420: barva popøedí není známá"
+
+#: syntax.c:6484
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: název èi èíslo barvy %s nebylo rozpoznáno"
+
+#: syntax.c:6688
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: terminálový kód %s je pøíliš dlouhý"
+
+#: syntax.c:6735
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: nepøípustný argument: %s"
+
+#: syntax.c:7264
+msgid "E424: Too many different highlighting attributes in use"
+msgstr ""
+"E424: Je používáno pøíliš velké množství odlišných zvýrazòovacích atributù"
+
+#: tag.c:90
+msgid "at bottom of tag stack"
+msgstr "konec seznamu tagù"
+
+#: tag.c:91
+msgid "at top of tag stack"
+msgstr "zaèátek seznamu tagù"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Pøed první vyhovující tag nelze pøeskoèit"
+
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: tag %s nenalezen"
+
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr " # pri typ tag"
+
+#: tag.c:548
+msgid "file\n"
+msgstr "soubor\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Zadejte èíslo (<CR> pro ukonèení): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: Vyhovuje pouze jeden tag"
+
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Za poslední vyhovující tag nelze pøeskoèit"
+
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Soubor \"%s\" neexistuje"
+
+#. Give an indication of the number of matching tags
+#: tag.c:780
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "tag %d z celkového poètu %d%s"
+
+#: tag.c:783
+msgid " or more"
+msgstr " nebo více"
+
+#: tag.c:785
+msgid " Using tag with different case!"
+msgstr " Používám tag s písmeny jiné velikosti!"
+
+#: tag.c:828
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: \"%s\" neexistuje"
+
+#. Highlight title
+#: tag.c:897
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # CÍL tag START øádek v souboru/textu"
+
+#: tag.c:1144
+msgid "Linear tag search"
+msgstr "Lineární hledání tagu"
+
+#: tag.c:1146
+msgid "Binary tag search"
+msgstr "Binární hledání tagu"
+
+#: tag.c:1172
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Prohledávám soubor tagù %s"
+
+#: tag.c:1356
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Soubor tagù %s byl oøezán\n"
+
+#: tag.c:1847
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Chyba formátu v souboru tagù \"%s\""
+
+#: tag.c:1851
+#, c-format
+msgid "Before byte %ld"
+msgstr "Pøed bajtem %ld"
+
+#: tag.c:1872
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Obsah soubor tagù %s není seøazen"
+
+#. never opened any tags file
+#: tag.c:1911
+msgid "E433: No tags file"
+msgstr "E433: Žádný soubor tagù"
+
+#: tag.c:2583
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Nelze najít vzorek tagù"
+
+#: tag.c:2594
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Tag nelze nalézt, pouze hádám!"
+
+#: term.c:1723
+msgid "' not known. Available builtin terminals are:"
+msgstr "' není znám. Dostupné vestavìné terminály:"
+
+#: term.c:1747
+msgid "defaulting to '"
+msgstr "implicitní terminál '"
+
+#: term.c:2100
+msgid "Cannot open termcap file"
+msgstr "Nelze otevøít termcap"
+
+#: term.c:2103
+msgid "Terminal entry not found in terminfo"
+msgstr "Terminfo neobsahuje položku pro tento terminál"
+
+#: term.c:2105
+msgid "Terminal entry not found in termcap"
+msgstr "Termcap neobsahuje položku pro tento terminál"
+
+#: term.c:2264
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Termcap neobsahuje položku pro \"%s\""
+
+#: term.c:2738
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: Terminál musí mít schopnost \"cm\""
+
+#. Highlight title
+#: term.c:4878
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Klávesy terminálu ---"
+
+#: ui.c:240
+msgid "new shell started\n"
+msgstr "spuštìn nový shell\n"
+
+#: ui.c:1705
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: chyba pøi ètení vstupu, konèím...\n"
+
+#. must display the prompt
+#: undo.c:351
+msgid "No undo possible; continue anyway"
+msgstr "odstranìní zmìn není možné; chcete pøesto pokraèovat"
+
+#: undo.c:506
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: èísla øádkù jsou chybná"
+
+#: undo.c:675
+msgid "1 change"
+msgstr "poèet zmìn: 1"
+
+#: undo.c:677
+#, c-format
+msgid "%ld changes"
+msgstr "poèet zmìn: %ld"
+
+#: undo.c:721
+msgid "E439: undo list corrupt"
+msgstr "E439: záznam o zmìnách poškozen"
+
+#: undo.c:751
+msgid "E440: undo line missing"
+msgstr "E440: chybí undo øádek"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:655
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"16/32 bitová GUI verze pro MS Windows"
+
+#: version.c:657
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"32 bitová GUI verze pro MS Windows"
+
+#: version.c:660
+msgid " in Win32s mode"
+msgstr " ve Win32s režimu"
+
+#: version.c:662
+msgid " with OLE support"
+msgstr " s OLE podporou"
+
+#: version.c:665
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"32 bitová verze pro MS Windows konzolu"
+
+#: version.c:669
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"16 bitová verze pro MS Windows"
+
+#: version.c:673
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 bitová verze pro MS Windows"
+
+#: version.c:675
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 bitová MS-DOS verze"
+
+#: version.c:681
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) verze"
+
+#: version.c:683
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X verze"
+
+#: version.c:686
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS verze"
+
+#: version.c:691
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS verze"
+
+#: version.c:701
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Použité záplaty: "
+
+#: version.c:728
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"pøeložil "
+
+#: version.c:731
+msgid "by "
+msgstr " "
+
+#: version.c:743
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"maximální verze"
+
+#: version.c:746
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"velká verze "
+
+#: version.c:749
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"normální verze"
+
+#: version.c:752
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"malá verze "
+
+#: version.c:754
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"minimální verze"
+
+#: version.c:760
+msgid "without GUI."
+msgstr "bez grafického rozhraní"
+
+#: version.c:764
+msgid "with GTK-GNOME GUI."
+msgstr "s rozhraním GTK-GNOME"
+
+#: version.c:766
+msgid "with GTK GUI."
+msgstr "s rozhraním GTK"
+
+#: version.c:770
+msgid "with X11-Motif GUI."
+msgstr "s rozhraním X11-Motif"
+
+#: version.c:773
+msgid "with X11-Athena GUI."
+msgstr "S rozhraním X11-Athena"
+
+#: version.c:776
+msgid "with BeOS GUI."
+msgstr "s rozhraním BeOS"
+
+#: version.c:779
+msgid "with Photon GUI."
+msgstr "s rozhraním Photon"
+
+#: version.c:782
+msgid "with GUI."
+msgstr "s grafickým rozhraním"
+
+#: version.c:785
+msgid "with Carbon GUI."
+msgstr "s grafickým rozhraním Carbon"
+
+#: version.c:788
+msgid "with Cocoa GUI."
+msgstr "s grafickým rozhraním Cocoa"
+
+#: version.c:791
+msgid "with (classic) GUI."
+msgstr "s (clasickým) grafickým rozhraním"
+
+#: version.c:802
+msgid " Features included (+) or not (-):\n"
+msgstr " Vlastnosti zahrnuté (+) a nezahrnuté (-):\n"
+
+#: version.c:814
+msgid " system vimrc file: \""
+msgstr " systémový vimrc soubor: \""
+
+#: version.c:819
+msgid " user vimrc file: \""
+msgstr " uživatelský vimrc soubor: \""
+
+#: version.c:824
+msgid " 2nd user vimrc file: \""
+msgstr " druhý uživatelský vimrc soubor: \""
+
+#: version.c:829
+msgid " 3rd user vimrc file: \""
+msgstr " tøetí uživatelský vimrc soubor: \""
+
+#: version.c:834
+msgid " user exrc file: \""
+msgstr " uživatelský exrc soubor: \""
+
+#: version.c:839
+msgid " 2nd user exrc file: \""
+msgstr " druhý uživatelský exrc soubor: \""
+
+#: version.c:845
+msgid " system gvimrc file: \""
+msgstr " systémový gvimrc soubor: \""
+
+#: version.c:849
+msgid " user gvimrc file: \""
+msgstr " uživatelský gvimrc soubor: \""
+
+#: version.c:853
+msgid "2nd user gvimrc file: \""
+msgstr "druhý uživatelský gvimrc soubor: \""
+
+#: version.c:858
+msgid "3rd user gvimrc file: \""
+msgstr "tøetí uživatelský gvimrc soubor: \""
+
+#: version.c:865
+msgid " system menu file: \""
+msgstr " systémový soubor s menu: \""
+
+#: version.c:873
+msgid " fall-back for $VIM: \""
+msgstr " implicitní hodnota $VIM:\""
+
+#: version.c:879
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " implicitní hodnota $VIMRUNTIME: \""
+
+#: version.c:883
+msgid "Compilation: "
+msgstr "Pøeklad: "
+
+#: version.c:889
+msgid "Compiler: "
+msgstr "Pøekladaè: "
+
+#: version.c:894
+msgid "Linking: "
+msgstr "Linkuji: "
+
+#: version.c:899
+msgid " DEBUG BUILD"
+msgstr " PODPORA LADÌNÍ"
+
+#: version.c:934
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved"
+
+#: version.c:936
+msgid "version "
+msgstr "verze "
+
+#: version.c:937
+msgid "by Bram Moolenaar et al."
+msgstr "Autor: Bram Moolenaar a další"
+
+#: version.c:938
+msgid "Vim is open source and freely distributable"
+msgstr "Vim je volnì šiøitelný program s otevøeným zdrojovým kódem"
+
+#: version.c:940
+msgid "Help poor children in Uganda!"
+msgstr "Pomozte chudým dìtem v Ugandì!"
+
+#: version.c:941
+msgid "type :help iccf<Enter> for information "
+msgstr "podrobnìjší informace získáte pomocí :help iccf<Enter>"
+
+#: version.c:943
+msgid "type :q<Enter> to exit "
+msgstr "zadejte :q<Enter> pro ukonèení programu"
+
+#: version.c:944
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "zadejte :help<Enter> èi <F1> pro nápovìdu"
+
+#: version.c:945
+msgid "type :help version6<Enter> for version info"
+msgstr "zadejte :help version6<Enter> pro informace o verzi 6"
+
+#: version.c:948
+msgid "Running in Vi compatible mode"
+msgstr "Bìžím v režimu kompatibility s Vi"
+
+#: version.c:949
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "zadejte :set nocp<Enter> pro implicitní nastavení Vim"
+
+#: version.c:950
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "podrobnìjší informace získáte pomocí :help cp-default<Enter>"
+
+#: version.c:990
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "VAROVÁNÍ: detekovány Windows 95/98/ME"
+
+#: version.c:993
+msgid "type :help windows95<Enter> for info on this"
+msgstr "zadejte :help windows95<Enter> pro podrobnìjší informace"
+
+#: window.c:201
+msgid "E441: There is no preview window"
+msgstr "E441: Není žádné preview okno není"
+
+#: window.c:568
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: Okno nelze rozdìlit zároveò topleft a botright"
+
+#: window.c:1327
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Nelze rotovat, pokud je jiné okno rozdìleno"
+
+#: window.c:1810
+msgid "E444: Cannot close last window"
+msgstr "E444: Poslední okno nelze uzavøít"
+
+#: window.c:2474
+msgid "Already only one window"
+msgstr "Již existuje pouze jedno okno"
+
+#: window.c:2521
+msgid "E445: Other window contains changes"
+msgstr "E445: Jiné okno obsahuje zmìny"
+
+#: window.c:4341
+msgid "E446: No file name under cursor"
+msgstr "E446: Pod kurzorem se nenachází název souboru"
+
+#: window.c:4460
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Soubor \"%s\" nelze v path nalézt"
+
+#: ../GvimExt/gvimext.cpp:586
+msgid "Edit with &multiple Vims"
+msgstr "Editace &multiple Vimy"
+
+#: ../GvimExt/gvimext.cpp:592
+msgid "Edit with single &Vim"
+msgstr "Editace jedním $Vim -em"
+
+#: ../GvimExt/gvimext.cpp:604
+msgid "Edit with &Vim"
+msgstr "Editace &Vim -em"
+
+#: ../GvimExt/gvimext.cpp:628
+msgid "Edit with existing Vim - &"
+msgstr "Editace existujícím Vimem - &"
+
+#: ../GvimExt/gvimext.cpp:752
+msgid "Edits the selected file(s) with Vim"
+msgstr "Editace vybraných souborù Vimem"
+
+#: ../GvimExt/gvimext.cpp:891 ../GvimExt/gvimext.cpp:969
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "Chyba pøi spouštìní procesu: Zkontrolujte zdali je gvim v $PATH!"
+
+#: ../GvimExt/gvimext.cpp:892 ../GvimExt/gvimext.cpp:906
+#: ../GvimExt/gvimext.cpp:970
+msgid "gvimext.dll error"
+msgstr "chyba gvimext.dll"
+
+#: ../GvimExt/gvimext.cpp:905
+msgid "Path length too long!"
+msgstr "Název (v path) je pøíliš dlouhý"
+
+#: globals.h:878
+msgid "--No lines in buffer--"
+msgstr "--Buffer neobsahuje žádný øádek--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1019
+msgid "Command aborted"
+msgstr "Pøíkaz pøerušen"
+
+#: globals.h:1020
+msgid "Argument required"
+msgstr "Je vyžadován argument"
+
+#: globals.h:1021
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: po \\ by mìl následovat /. ? nebo &"
+
+#: globals.h:1023
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr ""
+"E11: Chyba v oknì pøíkazové øádky; <CR> pro spuštšní, CTRL-C pro ukonèení"
+
+#: globals.h:1025
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Pøíkaz není z exrc/vimrc v aktuálním adresáøi èi pøi hledání tagu "
+"povolen."
+
+#: globals.h:1026
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Soubor existuje (použijte ! pro vynucení)"
+
+#: globals.h:1027
+msgid "Command failed"
+msgstr "Pøíkaz selhal"
+
+#: globals.h:1028
+msgid "Internal error"
+msgstr "Vnitøní chyba"
+
+#: globals.h:1029
+msgid "Interrupted"
+msgstr "Pøerušeno"
+
+#: globals.h:1030
+msgid "E14: Invalid address"
+msgstr "E14: Chybná adresa"
+
+#: globals.h:1031
+msgid "Invalid argument"
+msgstr "Chybný argument"
+
+#: globals.h:1032
+#, c-format
+msgid "Invalid argument: %s"
+msgstr "Chybný argument: %s"
+
+#: globals.h:1034
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Chybný výraz: %s"
+
+#: globals.h:1036
+msgid "E16: Invalid range"
+msgstr "E16: Chybný rozsah"
+
+#: globals.h:1037
+msgid "Invalid command"
+msgstr "Chybný pøíkaz"
+
+#: globals.h:1039
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" je adresáøem"
+
+#: globals.h:1042
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Neoèekávané znaky pøed '='"
+
+#: globals.h:1044
+msgid "E19: Mark has invalid line number"
+msgstr "E19: Znaèka má chybné èíslo øádku"
+
+#: globals.h:1045
+msgid "E20: Mark not set"
+msgstr "E20: není nastavena"
+
+#: globals.h:1046
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Nelze mìnit, je nastavena volba 'modifiable'"
+
+#: globals.h:1047
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Skript vnoøen pøíliš hluboko"
+
+#: globals.h:1048
+msgid "E23: No alternate file"
+msgstr "E23: Žádný alternativní soubor"
+
+#: globals.h:1049
+msgid "E24: No such abbreviation"
+msgstr "E24: Taková zkratka neexistuje"
+
+#: globals.h:1050
+msgid "No ! allowed"
+msgstr "! není povoleno"
+
+#: globals.h:1052
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: Nelze použít GUI: nebylo zapnuto pøi pøekladu programu"
+
+#: globals.h:1055
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr ""
+"E26: nelze použít hebrejský režim: nebyl zapnut pøi pøekladu programu\n"
+
+#: globals.h:1058
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: Nelze použít farsi režim: nebyl zapnut pøi pøekladu programu\n"
+
+#: globals.h:1061
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Skupina zvýraznìní %s neexistuje"
+
+#: globals.h:1063
+msgid "E29: No inserted text yet"
+msgstr "E29: Zatím není žádný vložený text"
+
+#: globals.h:1064
+msgid "E30: No previous command line"
+msgstr "E30: Žádná pøedchozí pøíkazová øádka"
+
+#: globals.h:1065
+msgid "E31: No such mapping"
+msgstr "E31: Žádné takové mapování"
+
+#: globals.h:1066
+msgid "No match"
+msgstr "Žádná shoda"
+
+#: globals.h:1067
+#, c-format
+msgid "No match: %s"
+msgstr "Žádná shoda: %s"
+
+#: globals.h:1068
+msgid "E32: No file name"
+msgstr "E32: Žádný název souboru"
+
+#: globals.h:1069
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: žádný pøedchozí regulární výraz"
+
+#: globals.h:1070
+msgid "E34: No previous command"
+msgstr "E34: Žádný pøedchozí pøíkaz"
+
+#: globals.h:1071
+msgid "E35: No previous regular expression"
+msgstr "E35: žádný pøedchozí regulární výraz"
+
+#: globals.h:1072
+msgid "No range allowed"
+msgstr "Rozsah není povolen"
+
+#: globals.h:1074
+msgid "E36: Not enough room"
+msgstr "E36: Nedostatek místa"
+
+#: globals.h:1076
+#, c-format
+msgid "Can't create file %s"
+msgstr "Nelze vytvoøit soubor %s"
+
+#: globals.h:1077
+msgid "Can't get temp file name"
+msgstr "Nelze získat název doèasného souboru"
+
+#: globals.h:1078
+#, c-format
+msgid "Can't open file %s"
+msgstr "Nelze otevøít soubor %s"
+
+#: globals.h:1079
+#, c-format
+msgid "Can't read file %s"
+msgstr "Nelze èíst soubor %s"
+
+#: globals.h:1080
+msgid "E37: No write since last change (use ! to override)"
+msgstr "E37: Neuložené zmìny (použijte ! pro vynucení)"
+
+#: globals.h:1081
+msgid "E38: Null argument"
+msgstr "E38: Nulový argument"
+
+#: globals.h:1083
+msgid "E39: Number expected"
+msgstr "E39: Oèekáváno èíslo"
+
+#: globals.h:1086
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Nelze otevøít chybový soubor %s"
+
+#: globals.h:1089
+msgid "E41: Out of memory!"
+msgstr "E41: Nedostatek pamìti!"
+
+#: globals.h:1092
+msgid "Pattern not found"
+msgstr "Vzor nenalezen"
+
+#: globals.h:1094
+#, c-format
+msgid "Pattern not found: %s"
+msgstr "Vzor nenalezen: %s"
+
+#: globals.h:1095
+msgid "Argument must be positive"
+msgstr "Argument musí být kladný"
+
+#: globals.h:1097
+msgid "E42: No Errors"
+msgstr "E42: Žádné chyby"
+
+#: globals.h:1099
+msgid "E43: Damaged match string"
+msgstr "E43: Poškozený øetìzec pro vyhledávání"
+
+#: globals.h:1100
+msgid "E44: Corrupted regexp program"
+msgstr "E44: poškozený regexp program"
+
+#: globals.h:1101
+msgid "E45: 'readonly' option is set (use ! to override)"
+msgstr "E45: 'nastavena volba 'readonly' (použijte ! pro vynucení)"
+
+#: globals.h:1103
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Nelze nastavit pouze_pro_ètení promìnnou \"%s\""
+
+#: globals.h:1106
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Chyba pøi ètení chybového souboru"
+
+#: globals.h:1109
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: Není v bezpeènostní schránce povoleno"
+
+#: globals.h:1111
+msgid "E49: Invalid scroll size"
+msgstr "E49: Chybná hodnota volby 'scroll'"
+
+#: globals.h:1112
+msgid "E91: 'shell' option is empty"
+msgstr "E91: volba 'shell' je prázdná"
+
+#: globals.h:1113
+msgid "E72: Close error on swap file"
+msgstr "E72: Chyba pøi uzavírání odkládacího souboru"
+
+#: globals.h:1114
+msgid "E73: tag stack empty"
+msgstr "E73: seznam tagù je prázdný"
+
+#: globals.h:1115
+msgid "E74: Command too complex"
+msgstr "E74: Pøíkaz je pøíliš složitý"
+
+#: globals.h:1116
+msgid "E75: Name too long"
+msgstr "E75: Název je pøíliš dlouhý"
+
+#: globals.h:1117
+msgid "E76: Too many ["
+msgstr "E76: pøíliš mnoho ["
+
+#: globals.h:1118
+msgid "E77: Too many file names"
+msgstr "E77: Pøíliš mnoho názvù souborù"
+
+#: globals.h:1119
+msgid "Trailing characters"
+msgstr "Nadbyteèné znaky na konci"
+
+#: globals.h:1120
+msgid "E78: Unknown mark"
+msgstr "E78: Neznámá znaèka"
+
+#: globals.h:1121
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Nelze expandovat žolíkové znaky"
+
+#: globals.h:1122
+msgid "E80: Error while writing"
+msgstr "E80: Chyba pøi ukládání"
+
+#: globals.h:1123
+msgid "Zero count"
+msgstr "Nulový poèet"
+
+#: globals.h:1125
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: Použití <SID> mimo kontext skriptu"
diff --git a/src/po/cs.po b/src/po/cs.po
new file mode 100644
index 000000000..e38c66527
--- /dev/null
+++ b/src/po/cs.po
@@ -0,0 +1,5954 @@
+# Czech translation of vim
+# Jiøí Pavlovský <jpavlovsky@mbox.vol.cz>, 2000 - 2002.
+# Some completion for vim6.0 added by Jiøí Bøezina <brz@centrum.cz>
+# Some bugfixes by Tomá¹ Zellerin <zellerin@volny.cz>
+#
+# Original translations.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: vim-6.0\n"
+"POT-Creation-Date: 2001-10-08 08:27-0700\n"
+"PO-Revision-Date: 2002-02-06 22:29+0100\n"
+"Last-Translator: Jiøí Pavlovský <jpavlovsky@mbox.vol.cz>\n"
+"Language-Team: Czech <cs@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-2\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Nelze alokovat ¾ádný buffer, konèím..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: Nelze alokovat buffer, pou¾iji jiný..."
+
+#: buffer.c:698
+msgid "No buffers were unloaded"
+msgstr "®ádný buffer nebyl deaktivován"
+
+#: buffer.c:700
+msgid "No buffers were deleted"
+msgstr "®ádný buffer nebyl smazán"
+
+#: buffer.c:702
+msgid "No buffers were wiped out"
+msgstr "®ádný buffer nebyl zahozen"
+
+#: buffer.c:710
+msgid "1 buffer unloaded"
+msgstr "Poèet deaktivovaných bufferù: 1"
+
+#: buffer.c:712
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "Poèet deaktivovaných bufferù: %d"
+
+#: buffer.c:717
+msgid "1 buffer deleted"
+msgstr "Poèet smazaných bufferù: 1"
+
+#: buffer.c:719
+#, c-format
+msgid "%d buffers deleted"
+msgstr "Poèet smazaných bufferù: %d"
+
+#: buffer.c:724
+msgid "1 buffer wiped out"
+msgstr "Poèet zahozených bufferù: 1"
+
+#: buffer.c:726
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "Poèet zahozených bufferù: %d"
+
+#: buffer.c:783
+msgid "E84: No modified buffer found"
+msgstr "E84: Nebyl nalezen ¾ádný zmìnìný buffer"
+
+#. back where we started, didn't find anything.
+#: buffer.c:822
+msgid "E85: There is no listed buffer"
+msgstr "E85: Seznam bufferù je prázdný"
+
+#: buffer.c:834
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: Nelze pøeskoèit na buffer %ld"
+
+#: buffer.c:837
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Za poslední buffer nelze pøeskoèit"
+
+#: buffer.c:839
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Pøed první buffer nelze pøeskoèit"
+
+#: buffer.c:863
+#, c-format
+msgid "E89: No write since last change for buffer %ld (use ! to override)"
+msgstr "E89: Zmìny v bufferu %ld nebyly ulo¾eny (! pro vynucení)"
+
+#: buffer.c:879
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: Poslední buffer nelze deaktivovat"
+
+#: buffer.c:1314
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Varování: pøeteèení seznamu s názvy souborù"
+
+#: buffer.c:1480
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: Buffer %ld nenalezen"
+
+#: buffer.c:1700
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Vzoru %s vyhovuje více bufferù"
+
+#: buffer.c:1702
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: Vzoru %s nevyhovuje ¾ádný buffer"
+
+#: buffer.c:2105 ex_docmd.c:6065
+#, c-format
+msgid "line %ld"
+msgstr "øádek %ld"
+
+#: buffer.c:2188
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Buffer tohoto jména ji¾ existuje"
+
+#: buffer.c:2481
+msgid " [Modified]"
+msgstr " [Zmìnìný]"
+
+#: buffer.c:2486
+msgid "[Not edited]"
+msgstr "[Needitovaný]"
+
+#: buffer.c:2491
+msgid "[New file]"
+msgstr "[Nový soubor]"
+
+#: buffer.c:2492
+msgid "[Read errors]"
+msgstr "[Chyby pøi ètení]"
+
+#: buffer.c:2494 fileio.c:1754
+msgid "[readonly]"
+msgstr "[Pouze pro ètení]"
+
+#: buffer.c:2510
+msgid "1 line --%d%%--"
+msgstr "øádkù: --%d%%--"
+
+#: buffer.c:2510
+msgid "%ld lines --%d%%--"
+msgstr "øádkù: %ld --%d%%--"
+
+#: buffer.c:2518
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "øádek %ld/%ld --%d%%-- sloupec"
+
+#: buffer.c:2606
+msgid "[No file]"
+msgstr "[®ádný soubor]"
+
+#. must be a help buffer
+#: buffer.c:2646
+msgid "help"
+msgstr "nápovìda"
+
+#: buffer.c:3151 screen.c:4671
+msgid "[help]"
+msgstr "[nápovìda]"
+
+#: buffer.c:3183 screen.c:4677
+msgid "[Preview]"
+msgstr "[náhled]"
+
+#: buffer.c:3389
+msgid "All"
+msgstr "V¹e"
+
+#: buffer.c:3389
+msgid "Bot"
+msgstr "Konec"
+
+#: buffer.c:3391
+msgid "Top"
+msgstr "Zaèátek"
+
+#: buffer.c:4127
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# Seznam bufferù:\n"
+
+#: buffer.c:4160
+msgid "[Error List]"
+msgstr "[seznam chyb]"
+
+#: buffer.c:4173 memline.c:1513
+msgid "[No File]"
+msgstr "[¾ádný soubor]"
+
+#: buffer.c:4393
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Znaky ---"
+
+#: buffer.c:4403
+#, c-format
+msgid "Signs for %s:"
+msgstr "Znaky pro %s:"
+
+#: buffer.c:4409
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " øádek=%ld id=%d jméno=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: Nelze pøekroèit maximální poèet %ld diff bufferù"
+
+#: diff.c:648
+msgid "E97: Cannot create diffs"
+msgstr "E97: Nelze vytvoøit diffy"
+
+#: diff.c:747
+msgid "Patch file"
+msgstr "Soubor se záplatou"
+
+#: diff.c:991
+msgid "E98: Cannot read diff output"
+msgstr "E98: Nelze èíst výstup programu diff"
+
+#: diff.c:1704
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Aktuální buffer není v diff re¾imu"
+
+#: diff.c:1716
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: To byl poslední buffer v diff re¾imu"
+
+#: diff.c:1724
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: V diff re¾imu jsou více ne¾ dva buffery. Nevím, který mám pou¾ít."
+
+#: diff.c:1747
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Nelze nalézt buffer \"%s\""
+
+#: diff.c:1753
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Buffer \"%s\" není v diff re¾imu"
+
+#: digraph.c:2168
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: digraph nesmí obsahovat Escape"
+
+#: digraph.c:2340
+msgid "Keymap file not found"
+msgstr "Soubor s mapou klávesnice nebyl nalezen"
+
+#: digraph.c:2367
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: :loadkeymap mimo interpretovaný soubor"
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " Doplòování klíèových slov (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " ^X re¾im (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " Lokální doplòování klíèových slov (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " Doplòování celých øádkù (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " Doplòování názvù souborù (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " Doplòování tagù (^I/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " Doplòování vzoru cest (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " Doplòování definic (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " Doplòování podle slovníku (^K/^N/^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Doplòování podle tezauru (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " Doplòování pøíkazové øádky (^I/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Konec odstavce"
+
+#: edit.c:894
+msgid "'thesaurus' option is empty"
+msgstr "volba 'thesaurus' je prázdná"
+
+#: edit.c:1070
+msgid "'dictionary' option is empty"
+msgstr "volba 'dictionary' je prázdná"
+
+#: edit.c:1992
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Prohledávám slovník %s"
+
+#: edit.c:2183
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (insert) Rolování (^E/^Y)"
+
+#: edit.c:2185
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (replace) Rolování (^E/^Y)"
+
+#: edit.c:2496
+#, c-format
+msgid "Scanning: %s"
+msgstr "Prohledávám %s"
+
+#: edit.c:2531
+msgid "Scanning tags."
+msgstr "Prohledávám tagy"
+
+#: edit.c:3189
+msgid " Adding"
+msgstr "Pøidávám"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3238
+msgid "-- Searching..."
+msgstr "-- Hledám..."
+
+#: edit.c:3294
+msgid "Back at original"
+msgstr "Výchozí podoba"
+
+#: edit.c:3299
+msgid "Word from other line"
+msgstr "Slovo z jiného øádku"
+
+#: edit.c:3304
+msgid "The only match"
+msgstr "Jediná shoda"
+
+#: edit.c:3363
+#, c-format
+msgid "match %d of %d"
+msgstr "shoda %d/%d"
+
+#: edit.c:3366
+#, c-format
+msgid "match %d"
+msgstr "shoda %d"
+
+#: eval.c:696
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Neznámá promìnná: \"%s\""
+
+#: eval.c:975
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Chybí závorky: %s"
+
+#: eval.c:1043
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Promìnná \"%s\" neexistuje"
+
+#: eval.c:1284
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Po '?' chybí ':'"
+
+#: eval.c:1898
+msgid "E110: Missing ')'"
+msgstr "E110: Chybìjící ')'"
+
+#: eval.c:1948
+msgid "E111: Missing ']'"
+msgstr "E111: Chybìjící ']'"
+
+#: eval.c:2023
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Chybí jméno volby: %s"
+
+#: eval.c:2041
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Neznámá volba: %s"
+
+#: eval.c:2103
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Chybí uvozovky: %s"
+
+#: eval.c:2220
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Chybí uvozovky: %s"
+
+#: eval.c:2537
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Chybné argumenty pro funkci %s"
+
+#: eval.c:2538
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Neznámá funkce: %s"
+
+#: eval.c:2539
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: Pøíli¹ mnoho argumentù pro funkci %s"
+
+#: eval.c:2540
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Pøíli¹ málo argumentù pro funkci %s"
+
+#: eval.c:2541
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: Pou¾ití <SID> mimo kontext skriptu: %s"
+
+#: eval.c:3575
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld øádkù:"
+
+#: eval.c:4690
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&OK\n"
+"&Zru¹it"
+
+#: eval.c:5513
+msgid "E240: No connection to Vim server"
+msgstr "E240: Neexistuje pøipojení k Vim serveru"
+
+#: eval.c:5603
+msgid "E277: Unable to read a server reply"
+msgstr "E277: Nelze èíst odpovìï serveru"
+
+#: eval.c:5628
+msgid "E258: Unable to send to client"
+msgstr "E258: Nelze pøedat klientovi"
+
+#: eval.c:5669
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Nelze pøedat do %s"
+
+#: eval.c:5767
+msgid "(Invalid)"
+msgstr "(Chybný)"
+
+#: eval.c:6770
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Nedefinovaná promìnná: %s"
+
+#: eval.c:7468
+#, c-format
+msgid "E122: Function %s already exists, use ! to replace"
+msgstr "E122: Funkce %s ji¾ existuje. Pou¾ijte ! pro její nahrazení."
+
+#: eval.c:7510
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Nedefinovaná funkce: %s"
+
+#: eval.c:7523
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Chybí '(': %s"
+
+#: eval.c:7555
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Nepøípustný argument: %s"
+
+#: eval.c:7641
+msgid "E126: Missing :endfunction"
+msgstr "E126: Chybí :endfunction"
+
+#: eval.c:7720
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Nelze pøedefinovat funkci %s: je pou¾ívána"
+
+#: eval.c:7777
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: Název funkce musí zaèínat velkým písmenem: %s"
+
+#: eval.c:7783
+msgid "E129: Function name required"
+msgstr "E129: Je vy¾adováno jméno funkce"
+
+#: eval.c:7876
+msgid "function "
+msgstr "funkce "
+
+#: eval.c:7991
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Nedefinovaná funkce: %s"
+
+#: eval.c:7996
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Nelze smazat funkci %s: je ji¾ pou¾ívána"
+
+#: eval.c:8043
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: Zanoøení funkce je hlub¹í ne¾ 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:8094
+#, c-format
+msgid "calling %s"
+msgstr "volám %s"
+
+#. always scroll up, don't overwrite
+#: eval.c:8119 ex_cmds2.c:1973
+#, c-format
+msgid "continuing in %s"
+msgstr "pokraèuji v %s"
+
+#: eval.c:8173
+msgid "E133: :return not inside a function"
+msgstr "E133: :return mimo funkci"
+
+#: eval.c:8251
+#, c-format
+msgid "%s returning #%ld"
+msgstr "dokonèeno provádìní %s. Návratová hodnota #%ld"
+
+#: eval.c:8254
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "dokonèeno provádìní %s. Návratová hodnota \"%s\""
+
+#: eval.c:8395
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# globální promìnné:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, ¹estnáctkovì %02x, osmièkovì %03o"
+
+#: ex_cmds.c:428
+msgid "E134: Move lines into themselves"
+msgstr "E134: Nelze pøesunout øádky na pùvodní místo"
+
+#: ex_cmds.c:497
+msgid "1 line moved"
+msgstr "poèet pøesunutých øádkù: 1"
+
+#: ex_cmds.c:499
+#, c-format
+msgid "%ld lines moved"
+msgstr "Poèet pøesunutých øádkù: %ld"
+
+#: ex_cmds.c:890
+#, c-format
+msgid "%ld lines filtered"
+msgstr "Poèet filtrovaných øádkù: %ld"
+
+#: ex_cmds.c:918
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: Automatické pøíkazy *Filter* nesmí mìnit aktuální buffer"
+
+#: ex_cmds.c:1003
+msgid "[No write since last change]\n"
+msgstr "[Neulo¾ené zmìny]\n"
+
+#: ex_cmds.c:1248
+#, c-format
+msgid "viminfo: %s in line: "
+msgstr "viminfo: %s na øádku: "
+
+#: ex_cmds.c:1253
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: pøíli¹ mnoho chyb, pøeskakuji zbytek souboru"
+
+#: ex_cmds.c:1282
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Ètu viminfo soubor \"%s\"%s%s%s"
+
+#: ex_cmds.c:1283
+msgid " info"
+msgstr " informace"
+
+#: ex_cmds.c:1284
+msgid " marks"
+msgstr " znaèky"
+
+#: ex_cmds.c:1285
+msgid " FAILED"
+msgstr " se nezdaøilo"
+
+#: ex_cmds.c:1376
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: do viminfo souboru %s nelze zapisovat"
+
+#: ex_cmds.c:1501
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Nelze ulo¾it viminfo soubor %s!"
+
+#: ex_cmds.c:1509
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Ukládám viminfo souboru \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1610
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Tento viminfo soubor byl vytvoøen editorem Vim %s.\n"
+
+#: ex_cmds.c:1612
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Pokud budete opatrný, mù¾ete jej upravovat.\n"
+"\n"
+
+#: ex_cmds.c:1614
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Hodnota volby 'encoding' v dobì ulo¾ení tohoto souboru\n"
+
+#: ex_cmds.c:1713
+msgid "Illegal starting char"
+msgstr "Nepøípustný poèáteèní znak"
+
+#: ex_cmds.c:2053 ex_cmds.c:2289 ex_cmds2.c:602
+msgid "Save As"
+msgstr "Ulo¾it jako"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2096
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Soubor je nahrán v jiném bufferu"
+
+#: ex_cmds.c:2130
+msgid "Write partial file?"
+msgstr "Ulo¾it neúplný soubor?"
+
+#: ex_cmds.c:2137
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Pou¾ijte ! pro ulo¾ení neúplného bufferu"
+
+#: ex_cmds.c:2223
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Pøepsat soubor \"%.*s\"?"
+
+#: ex_cmds.c:2294
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: ®ádný název souboru pro buffer %ld"
+
+#: ex_cmds.c:2332
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: Soubor nebyl ulo¾en: Ukládání je zakázáno volbou 'write'"
+
+#: ex_cmds.c:2352
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"Pro \"%.*s\" je nastavena volba 'readonly'.\n"
+"Pøejete si ji potlaèit?"
+
+#: ex_cmds.c:2517
+msgid "Edit File"
+msgstr "Editovat soubor"
+
+#: ex_cmds.c:3024
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Automatické pøíkazy neoèekávanì smazaly nový buffer %s"
+
+#: ex_cmds.c:3156
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: neèíselný argument pro :z"
+
+#: ex_cmds.c:3241
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: rvim nepovoluje pou¾ití pøíkazù shellu"
+
+#: ex_cmds.c:3348
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Regulární výrazy nesmí být oddìleny písmeny"
+
+#: ex_cmds.c:3686
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "nahradit za %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4050
+msgid "(Interrupted) "
+msgstr "(Pøeru¹eno) "
+
+#: ex_cmds.c:4054
+msgid "1 substitution"
+msgstr "1 nahrazení"
+
+#: ex_cmds.c:4056
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld nahrazení"
+
+#: ex_cmds.c:4059
+msgid " on 1 line"
+msgstr " na jednom øádku"
+
+#: ex_cmds.c:4061
+#, c-format
+msgid " on %ld lines"
+msgstr " na %ld øádcích"
+
+#: ex_cmds.c:4112
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :global nelze volat rekurzivnì"
+
+#: ex_cmds.c:4147
+msgid "E148: Regular expression missing from global"
+msgstr "E148: U pøíkazu 'global' chybí regulární výraz"
+
+#: ex_cmds.c:4196
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Vzor nalezen na ka¾dém øádku: %s"
+
+#: ex_cmds.c:4277
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Poslední nahrazující øetìzec:\n"
+"$"
+
+#: ex_cmds.c:4376
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Lituji, pro %s není ¾ádná nápovìda"
+
+#: ex_cmds.c:4410
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Lituji, soubor \"%s\" s nápovìdou nebyl nalezen"
+
+#: ex_cmds.c:4856
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s není adresáøem"
+
+#: ex_cmds.c:4884
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: Nelze otevøít %s pro zápis"
+
+#: ex_cmds.c:4898
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Nelze otevøít %s pro zápis"
+
+#: ex_cmds.c:4977
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: Duplicitní tag \"%s\" v souboru %s"
+
+#: ex_cmds.c:5078
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Neznámá volba pøíkazu: %s"
+
+#: ex_cmds.c:5098
+msgid "E156: Missing sign name"
+msgstr "E156: Chybí jméno volby"
+
+#: ex_cmds.c:5144
+msgid "E255: Too many signs defined"
+msgstr "E255: Nastaveno pøíli¹ mnoho voleb"
+
+#: ex_cmds.c:5186
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Neplatný text volby: %s"
+
+#: ex_cmds.c:5210 ex_cmds.c:5396
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Neznámá volba: %s"
+
+#: ex_cmds.c:5256
+msgid "E159: Missing sign number"
+msgstr "E159: Chybí identifikátor volby"
+
+#: ex_cmds.c:5336
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: chybné jméno bufferu: %s"
+
+#: ex_cmds.c:5375
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Chybné ID volby: %ld"
+
+#: ex_cmds.c:5546
+msgid "[Deleted]"
+msgstr "[Vymazáno]"
+
+#: ex_cmds2.c:70
+msgid "Entering Debug mode. Type \"cont\" to leave."
+msgstr "Spou¹tím ladící re¾im. Pro ukonèení napi¹te \"cont\"."
+
+#: ex_cmds2.c:74 ex_docmd.c:771
+#, c-format
+msgid "line %ld: %s"
+msgstr "øádek %ld: %s"
+
+#: ex_cmds2.c:76
+#, c-format
+msgid "cmd: %s"
+msgstr "pøíkaz: %s"
+
+#: ex_cmds2.c:224
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Bod pøeru¹ení v \"%s%s\" na øádku %ld"
+
+#: ex_cmds2.c:388
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Bod pøeru¹ení nenalezen: %s"
+
+#: ex_cmds2.c:414
+msgid "No breakpoints defined"
+msgstr "Nebyly definovánu ¾ádné body pøeru¹ení"
+
+#: ex_cmds2.c:419
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s øádek %ld"
+
+#: ex_cmds2.c:625
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Ulo¾it zmìny do \"%.*s\"?"
+
+#: ex_cmds2.c:627 ex_docmd.c:8612
+msgid "Untitled"
+msgstr "Nepojmenováno"
+
+#: ex_cmds2.c:763
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Buffer \"%s\" obsahuje neulo¾ené zmìny"
+
+#: ex_cmds2.c:832
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr ""
+"Varování: Neèekaný vstup do jiného bufferu (zkontrolujte automatické pøíkazy)"
+
+#: ex_cmds2.c:1208
+msgid "E163: There is only one file to edit"
+msgstr "E163: Pro editaci byl zadán pouze jeden soubor"
+
+#: ex_cmds2.c:1210
+msgid "E164: Cannot go before first file"
+msgstr "E164: Pøed první soubor nelze pøeskoèit"
+
+#: ex_cmds2.c:1212
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Za poslední soubor nelze pøeskoèit"
+
+#: ex_cmds2.c:1632
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Hledám \"%s\" v \"%s\""
+
+#: ex_cmds2.c:1654
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Hledám \"%s\""
+
+#: ex_cmds2.c:1678
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "soubor \"%s\" nebyl nalezen v 'runtimepath'"
+
+#: ex_cmds2.c:1712
+msgid "Run Macro"
+msgstr "Spustit makro"
+
+#: ex_cmds2.c:1817
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "nelze interpretovat adresáø: \"%s\""
+
+#: ex_cmds2.c:1847
+#, c-format
+msgid "could not source \"%s\""
+msgstr "nelze interpretovat \"%s\""
+
+#: ex_cmds2.c:1849
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "øádek %ld: nelze interpretovat \"%s\""
+
+#: ex_cmds2.c:1863
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "interpretuji \"%s\""
+
+#: ex_cmds2.c:1865
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "øádek %ld: interpretuji %s"
+
+#: ex_cmds2.c:1971
+#, c-format
+msgid "finished sourcing %s"
+msgstr "dokonèena interpretace %s"
+
+#: ex_cmds2.c:2272
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Varování: chybný oddìlovaè øádkù. Mo¾ná chybí ^M."
+
+#: ex_cmds2.c:2321
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :scriptencoding pou¾ito mimo interpretovaný soubor"
+
+#: ex_cmds2.c:2354
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish pou¾ito mimo interpretovaný soubor"
+
+#: ex_cmds2.c:2820
+msgid "No text to be printed"
+msgstr "®ádný text k vyti¹tìní"
+
+#: ex_cmds2.c:2898
+msgid "Printing page %d (%d%%)"
+msgstr "Tisknu stranu %d (%d%%)"
+
+#: ex_cmds2.c:2907
+#, c-format
+msgid " Copy %d of %d"
+msgstr " Kopie %d z %d"
+
+#: ex_cmds2.c:2959
+#, c-format
+msgid "Printed: %s"
+msgstr "Vyti¹tìno: %s"
+
+#: ex_cmds2.c:2966
+msgid "Printing aborted"
+msgstr "Tisk zru¹en"
+
+#: ex_cmds2.c:3344
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Nelze zapisovat do výstupního PostScriptového souboru"
+
+#: ex_cmds2.c:4019
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Nelze otevøít výstupní PostScriptový soubor"
+
+#: ex_cmds2.c:4057
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Nelze otevøít soubor \"%s\""
+
+#: ex_cmds2.c:4068
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Nelze èíst zdrojový PostScriptový soubor \"%s\""
+
+#: ex_cmds2.c:4266
+msgid "Sending to printer..."
+msgstr "Odesílám na tiskárnu..."
+
+#: ex_cmds2.c:4270
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: Selhal tisk PostScriptového souboru"
+
+#: ex_cmds2.c:4272
+msgid "Print job sent."
+msgstr "Tisková úloha odeslána."
+
+#: ex_cmds2.c:4651
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Aktuální %sjazyk: \"%s\""
+
+#: ex_cmds2.c:4658
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Nelze nastavit jazyk na \"%s\""
+
+#: ex_docmd.c:491
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Spou¹tím Ex mód. Napi¹te \"visual\" pro návrat do normálního módu."
+
+#. must be at EOF
+#: ex_docmd.c:527
+msgid "At end-of-file"
+msgstr "Konec souboru"
+
+#: ex_docmd.c:602
+msgid "E169: Command too recursive"
+msgstr "E169: Pøíkaz je pøíli¹ rekurzivní"
+
+#: ex_docmd.c:911
+msgid "E170: Missing :endwhile"
+msgstr "E170: Chybí :endwhile"
+
+#: ex_docmd.c:913
+msgid "E171: Missing :endif"
+msgstr "E171: Chybí :endif"
+
+#: ex_docmd.c:923
+msgid "End of sourced file"
+msgstr "Konec interpretovaného souboru"
+
+#: ex_docmd.c:924
+msgid "End of function"
+msgstr "Konec funkce"
+
+#: ex_docmd.c:1344
+msgid "Ambiguous use of user-defined command"
+msgstr "Nejednoznaèné pou¾ití u¾ivatelsky definovaného pøíkazu"
+
+#: ex_docmd.c:1358
+msgid "Not an editor command"
+msgstr "Není pøíkazem editoru"
+
+#: ex_docmd.c:1441
+msgid "Don't panic!"
+msgstr "Nepanikaøte!"
+
+#: ex_docmd.c:1460
+msgid "Backwards range given"
+msgstr "Zadán zpìtný rozsah"
+
+#: ex_docmd.c:1469
+msgid "Backwards range given, OK to swap"
+msgstr "Zadán zpìtný rozsah. Prohodit hranice"
+
+#: ex_docmd.c:1580
+msgid "Use w or w>>"
+msgstr "Pou¾ijte w èi w>>"
+
+#: ex_docmd.c:3086
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Pøíkaz není této verzi bohu¾el implementován"
+
+#: ex_docmd.c:3256
+msgid "E172: Only one file name allowed"
+msgstr "E172: Pøípustný je pouze jeden název souboru"
+
+#: ex_docmd.c:3810
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "Je¹tì zbývají soubory k editaci (%d). Chcete pøesto ukonèit editor?"
+
+#: ex_docmd.c:3817
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: Je¹tì zbývají soubory k editaci (%ld)."
+
+#: ex_docmd.c:3911
+msgid "E174: Command already exists: use ! to redefine"
+msgstr "E174: Pøíkaz ji¾ existuje: pou¾ijte ! pro pøedefinování"
+
+#: ex_docmd.c:4016
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Jméno Args Rozsah Úplnost Definice"
+
+#: ex_docmd.c:4105
+msgid "No user-defined commands found"
+msgstr "Nebyly nalezeny ¾ádné u¾ivatelsky definované pøíkazy"
+
+#: ex_docmd.c:4136
+msgid "E175: No attribute specified"
+msgstr "E175: Nebyly zadány ¾ádné atributy"
+
+#: ex_docmd.c:4188
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Chybný poèet argumentù"
+
+#: ex_docmd.c:4203
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: Opakování nemù¾e být zadáno dvakrát"
+
+#: ex_docmd.c:4213
+msgid "E178: Invalid default value for count"
+msgstr "E178: Chybná implicitní hodnota pro poèet"
+
+#: ex_docmd.c:4241
+msgid "E179: argument required for complete"
+msgstr "E179: chybná implicitní hodnota pro opakování"
+
+#: ex_docmd.c:4260
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Chybná hodnota doplnìní: %s"
+
+#: ex_docmd.c:4268
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Chybný atribut: %s"
+
+#: ex_docmd.c:4309
+msgid "E182: Invalid command name"
+msgstr "E182: Chybné jméno pøíkazu"
+
+#: ex_docmd.c:4324
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: U¾ivatelsky definované pøíkazy musí zaèínat velikým písmenem."
+
+#: ex_docmd.c:4393
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: U¾ivatelsky definovaný pøíkaz %s neexistuje"
+
+#: ex_docmd.c:4844
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Nelze nalézt barevné schéma %s"
+
+#: ex_docmd.c:4852
+msgid "Greetings, Vim user!"
+msgstr "Blahopøeji, u¾ivateli Vimu!"
+
+#: ex_docmd.c:5549
+msgid "Edit File in new window"
+msgstr "Editovat soubor v novém oknì"
+
+#: ex_docmd.c:5815
+msgid "No swap file"
+msgstr "®ádný odkládací soubor"
+
+#: ex_docmd.c:5919
+msgid "Append File"
+msgstr "Ulo¾it soubor"
+
+#: ex_docmd.c:5978
+msgid "E186: No previous directory"
+msgstr "E186: ®ádný pøedchozí adresáø"
+
+#: ex_docmd.c:6055
+msgid "E187: Unknown"
+msgstr "E187: Neznámý"
+
+#: ex_docmd.c:6173
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Umístìní okna: X %d, Y %d"
+
+#: ex_docmd.c:6178
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: Na této platformì nelze umístìní okna zjistit"
+
+#: ex_docmd.c:6444
+msgid "Save Redirection"
+msgstr "Ulo¾it pøesmìrování"
+
+#: ex_docmd.c:6593
+msgid "Save View"
+msgstr "Ulo¾it pohled"
+
+#: ex_docmd.c:6594
+msgid "Save Session"
+msgstr "Ulo¾it sezení"
+
+#: ex_docmd.c:6596
+msgid "Save Setup"
+msgstr "Ulo¾it nastavení"
+
+#: ex_docmd.c:6745
+#, c-format
+msgid "E189: \"%s\" exists (use ! to override)"
+msgstr "E189: \"%s\" existuje (pou¾ijte ! pro vynucení)"
+
+#: ex_docmd.c:6750
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: Nelze otevøít \"%s\" pro zápis"
+
+#. set mark
+#: ex_docmd.c:6774
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: Argumentem mù¾e být pouze písmeno nebo pravý èi levý apostrof"
+
+#: ex_docmd.c:6803
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Vnoøení :normal je pøíli¹ hluboké"
+
+#: ex_docmd.c:7171
+msgid ":if nesting too deep"
+msgstr "vnoøení :if je pøíli¹ hluboké"
+
+#: ex_docmd.c:7206
+msgid ":endif without :if"
+msgstr ":endif bez odpovídajícího :if"
+
+#: ex_docmd.c:7226
+msgid ":else without :if"
+msgstr ":else bez odpovídajícího :if"
+
+#: ex_docmd.c:7228
+msgid ":elseif without :if"
+msgstr ":elseif bez odpovídajícího :if"
+
+#: ex_docmd.c:7280
+msgid ":while nesting too deep"
+msgstr "vnoøení :while je pøíli¹ hluboké"
+
+#: ex_docmd.c:7326
+msgid ":continue without :while"
+msgstr ":continue bez odpovídajícího :while"
+
+#: ex_docmd.c:7353
+msgid ":break without :while"
+msgstr ":break bez odpovídajícího :while"
+
+#: ex_docmd.c:7376 ex_docmd.c:7381
+msgid ":endwhile without :while"
+msgstr ":endwhile bez odpovídajícího :while"
+
+#: ex_docmd.c:7402
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction mimo funkci"
+
+#: ex_docmd.c:7582
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr ""
+"E194: ®ádný alternativní název souboru, kterým by bylo mo¾né nahradit '#'"
+
+#: ex_docmd.c:7613
+msgid "no autocommand file name to substitute for \"<afile>\""
+msgstr "®ádný název souboru, kterým by bylo mo¾né nahradit \"<afile>\""
+
+#: ex_docmd.c:7621
+msgid "no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "®ádné èíslo bufferu, kterým by bylo mo¾né nahradit \"<abuf>\""
+
+#: ex_docmd.c:7632
+msgid "no autocommand match name to substitute for \"<amatch>\""
+msgstr ""
+"®ádná shoda automatických pøíkazù, kterou by bylo mo¾né nahradit \"<amatch>\""
+
+#: ex_docmd.c:7642
+msgid "no :source file name to substitute for \"<sfile>\""
+msgstr "®ádný interpretovaný soubor, kterým by bylo mo¾né nahradit \"<sfile>\""
+
+#: ex_docmd.c:7683
+#, no-c-format
+msgid "Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "Prázdný název souboru pro '%' èi '#' funguje pouze s \":p:h\""
+
+#: ex_docmd.c:7685
+msgid "Evaluates to an empty string"
+msgstr "Výsledkem vyhodnocení je prázdný øetìzec"
+
+#: ex_docmd.c:8594
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: Nelze otevøít pro ètení viminfo soubor"
+
+#: ex_docmd.c:8767
+msgid "E196: No digraphs in this version"
+msgstr "E196: V této verzi nejsou spøe¾ky podporovány"
+
+#: ex_getln.c:2785
+msgid "tagname"
+msgstr "jméno tagu"
+
+#: ex_getln.c:2788
+msgid " kind file\n"
+msgstr " typ soubor\n"
+
+#: ex_getln.c:3997
+msgid "'history' option is zero"
+msgstr "'volba 'history' je nastavena na nulu"
+
+#: ex_getln.c:4237
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Historie %s (poèínaje nejnovìj¹í polo¾kou):\n"
+
+#: ex_getln.c:4238
+msgid "Command Line"
+msgstr "pøíkazové øádky"
+
+#: ex_getln.c:4239
+msgid "Search String"
+msgstr "vyhledávaných øetìzcù"
+
+#: ex_getln.c:4240
+msgid "Expression"
+msgstr "výrazù"
+
+#: ex_getln.c:4241
+msgid "Input Line"
+msgstr "vstupní øádky"
+
+#: ex_getln.c:4271
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar pøekraèuje délku pøíkazu"
+
+#: ex_getln.c:4435
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Smazáno aktivní okno èi buffer"
+
+#: fileio.c:347
+msgid "Illegal file name"
+msgstr "nepøípustný název souboru"
+
+#: fileio.c:371 fileio.c:495 fileio.c:2491 fileio.c:2529
+msgid "is a directory"
+msgstr "je adresáøem"
+
+#: fileio.c:373
+msgid "is not a file"
+msgstr "není souborem"
+
+#: fileio.c:515 fileio.c:3581
+msgid "[New File]"
+msgstr "[nový soubor]"
+
+#: fileio.c:532
+msgid "[Permission Denied]"
+msgstr "[pøístup odmítnut]"
+
+#: fileio.c:624
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre automatické pøíkazy uèinily soubor neèitelným"
+
+#: fileio.c:626
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *ReadPre automatické pøíkazy nesmí mìnit aktuální buffer"
+
+#: fileio.c:646
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: Ètu ze standardního vstupu...\n"
+
+#: fileio.c:652
+msgid "Reading from stdin..."
+msgstr "Ètu ze standardního vstupu..."
+
+#. Re-opening the original file failed!
+#: fileio.c:876
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: Po konverzi je soubor neèitelný!"
+
+#: fileio.c:1732
+msgid "[fifo/socket]"
+msgstr "[pojmenovaná roura/soket]"
+
+#: fileio.c:1739
+msgid "[fifo]"
+msgstr "[pojmenovaná roura]"
+
+#: fileio.c:1746
+msgid "[socket]"
+msgstr "[soket]"
+
+#: fileio.c:1754
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:1764
+msgid "[CR missing]"
+msgstr "[chybí CR]"
+
+#: fileio.c:1769
+msgid "[NL found]"
+msgstr "[nalezeno NL]"
+
+#: fileio.c:1774
+msgid "[long lines split]"
+msgstr "[dlouhé øádky zalomeny]"
+
+#: fileio.c:1780 fileio.c:3565
+msgid "[NOT converted]"
+msgstr "[nezkonvertován]"
+
+#: fileio.c:1785 fileio.c:3570
+msgid "[converted]"
+msgstr "[zkonvertován]"
+
+#: fileio.c:1792 fileio.c:3595
+msgid "[crypted]"
+msgstr "[za¹ifrován]"
+
+#: fileio.c:1799
+msgid "[CONVERSION ERROR]"
+msgstr "[CHYBA PØEVODU]"
+
+#: fileio.c:1806
+msgid "[READ ERRORS]"
+msgstr "[CHYBY ÈTENÍ]"
+
+#: fileio.c:2013
+msgid "Can't find temp file for conversion"
+msgstr "Nelze nalézt doèasný soubor pro konverzi"
+
+#: fileio.c:2020
+msgid "Conversion with 'charconvert' failed"
+msgstr "Konverze s 'charconvert' se nezdaøila"
+
+#: fileio.c:2023
+msgid "can't read output of 'charconvert'"
+msgstr "nelze èíst výstup 'charconvert'"
+
+#: fileio.c:2407
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr ""
+"E203: Automatické pøíkazy smazaly èi deaktivovaly buffer, který mìl být "
+"ulo¾en"
+
+#: fileio.c:2430
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Automatický pøíkaz neèekaným zpùsobem zmìnil poèet øádkù"
+
+#: fileio.c:2496 fileio.c:2513
+msgid "is not a file or writable device"
+msgstr "není souborem ani zaøízením na nì¾ lze zapisovat"
+
+#: fileio.c:2555
+msgid "is read-only (use ! to override)"
+msgstr "je pouze pro ètení (pou¾ijte ! pro vynucení)"
+
+#: fileio.c:2851
+msgid "Can't write to backup file (use ! to override)"
+msgstr "Nelze zapisovat do zálo¾ního souboru (pou¾ijte ! pro vynucení)"
+
+#: fileio.c:2863
+msgid "Close error for backup file (use ! to override)"
+msgstr "Chyba pøi uzavírání zálo¾ního souboru (pou¾ijte ! pro vynucení)"
+
+#: fileio.c:2865
+msgid "Can't read file for backup (use ! to override)"
+msgstr "Nelze naèíst soubor pro zálohu (pou¾ijte ! pro vynucení)"
+
+#: fileio.c:2881
+msgid "Cannot create backup file (use ! to override)"
+msgstr "Nelze vytvoøit zálo¾ní soubor (pou¾ijte ! pro vynucení)"
+
+#: fileio.c:2970
+msgid "Can't make backup file (use ! to override)"
+msgstr "Nelze vytvoøit zálo¾ní soubor (pou¾ijte ! pro vynucení)"
+
+# resource fork ?!
+#: fileio.c:3032
+msgid "The resource fork will be lost (use ! to override)"
+msgstr "'Resource fork' bude ztracen (pou¾ijte ! pro vynucení)"
+
+#: fileio.c:3121
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: Nelze najít doèasný temp soubor pro zápis"
+
+#: fileio.c:3139
+msgid "E213: Cannot convert (use ! to write without conversion)"
+msgstr "E213: Nelze pøevést (pou¾ijte ! pro zápis bez pøevodu)"
+
+#: fileio.c:3176
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Nelze otevøít pøipojený soubor pro zápis"
+
+#: fileio.c:3180
+msgid "E212: Can't open file for writing"
+msgstr "E212: Nelze otevøít soubor pro zápis"
+
+#: fileio.c:3423
+msgid "Close failed"
+msgstr "Volání close selhalo"
+
+#: fileio.c:3481
+msgid "write error, conversion failed"
+msgstr "chyba pøi zápisu, konverze se nezdaøila"
+
+#: fileio.c:3487
+msgid "write error (file system full?)"
+msgstr "chyba pøi ukládání (je volné místo na disku?)"
+
+#: fileio.c:3560
+msgid " CONVERSION ERROR"
+msgstr " CHYBA PØEVODU"
+
+#: fileio.c:3576
+msgid "[Device]"
+msgstr "[zaøízení]"
+
+#: fileio.c:3581
+msgid "[New]"
+msgstr "[Nový]"
+
+#: fileio.c:3603
+msgid " [a]"
+msgstr " [p]"
+
+#: fileio.c:3603
+msgid " appended"
+msgstr " pøipojen"
+
+#: fileio.c:3605
+msgid " [w]"
+msgstr " [u]"
+
+#: fileio.c:3605
+msgid " written"
+msgstr " ulo¾en"
+
+#: fileio.c:3655
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: patchmode: nelze ulo¾it pùvodní soubor"
+
+#: fileio.c:3677
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: nelze zapisovat do prázdného pùvodního souboru"
+
+#: fileio.c:3692
+msgid "E207: Can't delete backup file"
+msgstr "E207: Nelze smazat zálo¾ní soubor"
+
+#: fileio.c:3744
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"VAROVÁNÍ: Obsah pùvodního souboru mù¾e být ztracen èi po¹kozen\n"
+
+#: fileio.c:3746
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "neukonèujte editor døíve, ne¾ bude soubor úspì¹nì ulo¾en!"
+
+#: fileio.c:3826
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:3826
+msgid "[dos format]"
+msgstr "[dos formát]"
+
+#: fileio.c:3833
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:3833
+msgid "[mac format]"
+msgstr "[mac formát]"
+
+#: fileio.c:3840
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:3840
+msgid "[unix format]"
+msgstr "[unix formát]"
+
+#: fileio.c:3867
+msgid "1 line, "
+msgstr "1 øádek, "
+
+#: fileio.c:3869
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld øádkù, "
+
+#: fileio.c:3872
+msgid "1 character"
+msgstr "1 znak"
+
+#: fileio.c:3874
+#, c-format
+msgid "%ld characters"
+msgstr "%ld znakù, "
+
+#: fileio.c:3884
+msgid "[noeol]"
+msgstr "[¾ádný eol]"
+
+#: fileio.c:3884
+msgid "[Incomplete last line]"
+msgstr "[neúplný poslední øádek]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:3903
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "VAROVÁNÍ: od jeho naètení byl obsah souboru zmìnìn!!!!"
+
+#: fileio.c:3905
+msgid "Do you really want to write to it"
+msgstr "Chcete jej opravdu ulo¾it"
+
+#: fileio.c:4861
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Chyba pøi zápisu do \"%s\""
+
+#: fileio.c:4868
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Chyb pøi uzavírání \"%s\""
+
+#: fileio.c:4871
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Chyba pøi ètení \"%s\""
+
+#: fileio.c:5035
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: FileChangedShell autocommand zru¹il buffer"
+
+#: fileio.c:5043
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: wa1: soubor \"%s\" ji¾ není dostupný"
+
+#: fileio.c:5056
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: Varování: soubor \"%s\" byl po poèátku editace zmìnìn a buffer ve Vim "
+"také"
+
+#: fileio.c:5059
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: wc2: soubor \"%s\" byl po poèátku editace zmìnìn"
+
+#: fileio.c:5061
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: Varování: Mód souboru \"%s\" byl zmìnìn od zapoènutí editace"
+
+#: fileio.c:5071
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: wc4: po poèátku editace vytvoøen soubor \"%s\""
+
+#: fileio.c:5088
+msgid "Warning"
+msgstr "Varování"
+
+#: fileio.c:5089
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Nahrát soubor"
+
+#: fileio.c:5165
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: Nelze znovuotevøít \"%s\""
+
+#: fileio.c:5670
+msgid "--Deleted--"
+msgstr "--Vymazáno--"
+
+#. the group doesn't exist
+#: fileio.c:5830
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Skupina \"%s\" neexistuje"
+
+#: fileio.c:5955
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Nepøípustný znak po *: %s"
+
+#: fileio.c:5966
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Událost %s neexistuje"
+
+#. Highlight title
+#: fileio.c:6115
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Automatické pøíkazy ---"
+
+#: fileio.c:6386
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Automatické pøíkazy nelze spustit pro V©ECHNY události"
+
+#: fileio.c:6409
+msgid "No matching autocommands"
+msgstr "®ádné vyhovující automatické pøíkazy"
+
+#: fileio.c:6681
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: vnoøení automatického pøíkazu pøíli¹ hluboká"
+
+#: fileio.c:6968
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s automatické pøíkazy pro \"%s\""
+
+#: fileio.c:6976
+#, c-format
+msgid "Executing %s"
+msgstr "spou¹tím %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7044
+#, c-format
+msgid "autocommand %s"
+msgstr "Automatický pøíkaz %s"
+
+#: fileio.c:7566
+msgid "E219: Missing {."
+msgstr "E219: Chybí {."
+
+#: fileio.c:7568
+msgid "E220: Missing }."
+msgstr "E220: Chybí }."
+
+#: fold.c:66
+msgid "No fold found"
+msgstr "®ádný záhyb nebyl nalezen"
+
+#: fold.c:554
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: pomocí aktuální 'foldmethod' nelze vytvoøit záhyb"
+
+#: fold.c:556
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: pomocí aktuální 'foldmethod' nelze vytvoøit záhyb"
+
+#: fold.c:1700
+msgid "E221: 'commentstring' is empty"
+msgstr "E221: volba 'commentstring' je prázdná"
+
+#: getchar.c:268
+msgid "E222: Add to read buffer"
+msgstr "E222: Pøidat do bufferu pro ètení"
+
+#: getchar.c:2114
+msgid "E223: recursive mapping"
+msgstr "E223: rekurzivní mapování"
+
+#: getchar.c:2966
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: pro %s ji¾ globální zkratka ji¾ existuje"
+
+#: getchar.c:2969
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: pro %s ji¾ globální mapování ji¾ existuje"
+
+#: getchar.c:3096
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: pro %s ji¾ zkratka ji¾ existuje"
+
+#: getchar.c:3099
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: pro %s ji¾ mapování ji¾ existuje"
+
+#: getchar.c:3163
+msgid "No abbreviation found"
+msgstr "®ádná zkratka nebyl nalezena"
+
+#: getchar.c:3165
+msgid "No mapping found"
+msgstr "®ádné mapování nebylo nalezeno"
+
+#: getchar.c:3990
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: nepøípustný mód"
+
+#: gui.c:181
+msgid "E229: Cannot start the GUI"
+msgstr "E229: Nelze spustit GUI"
+
+#: gui.c:306
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Nelze èíst z \"%s\""
+
+#: gui.c:431
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: volba 'guifontwide' je chybnì nastavena"
+
+#: gui.c:3926
+msgid "Error"
+msgstr "Chyba"
+
+#: gui.c:3927
+msgid "&Ok"
+msgstr "&Ok"
+
+#: gui_at_fs.c:290
+msgid "<cannot open> "
+msgstr "<nelze otevøít> "
+
+#: gui_at_fs.c:1115
+#, c-format
+msgid "vim_SelFile: can't get font %s"
+msgstr "vim_SelFile: písmo %s není dostupné"
+
+#: gui_at_fs.c:2538
+msgid "vim_SelFile: can't return to current directory"
+msgstr "vim_SelFile: nelze se vrátit do aktuálního adresáøe"
+
+#: gui_at_fs.c:2557
+msgid "Pathname:"
+msgstr "Název cesty:"
+
+#: gui_at_fs.c:2563
+msgid "vim_SelFile: can't get current directory"
+msgstr "vim_SelFile: nelze zjistit aktuální adresáø"
+
+#: gui_at_fs.c:2571 gui_motif.c:1607
+msgid "OK"
+msgstr "OK"
+
+#. 'Cancel' button
+#: gui_at_fs.c:2571 gui_gtk.c:1683 gui_motif.c:1602 gui_motif.c:2823
+msgid "Cancel"
+msgstr "Zru¹it"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Pøípravek posunovací li¹ty: nelze zjistit geometrii obrázku"
+
+#: gui_athena.c:1928 gui_motif.c:1855
+msgid "Vim dialog"
+msgstr "Vim dialog"
+
+#: gui_beval.c:68
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: BalloonEval nelze vytvoøit se zprávou a zároveò zpìtným voláním"
+
+#: gui_gtk.c:1144
+msgid "Vim dialog..."
+msgstr "Vim dialog.."
+
+#: gui_gtk.c:1519 gui_motif.c:2742
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Nalézt a nahradit..."
+
+#: gui_gtk.c:1524 gui_motif.c:2744
+msgid "VIM - Search..."
+msgstr "VIM - Nalézt..."
+
+#: gui_gtk.c:1547 gui_motif.c:2862
+msgid "Find what:"
+msgstr "Vyhledat:"
+
+#: gui_gtk.c:1565 gui_motif.c:2894
+msgid "Replace with:"
+msgstr "Nový text:"
+
+#. exact match only button
+#: gui_gtk.c:1597 gui_motif.c:2996
+msgid "Match exact word only"
+msgstr "hledat pouze celá slova"
+
+#: gui_gtk.c:1609 gui_motif.c:2964
+msgid "Direction"
+msgstr "Smìr"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:1621 gui_motif.c:2976
+msgid "Up"
+msgstr "Nahoru"
+
+#: gui_gtk.c:1625 gui_motif.c:2984
+msgid "Down"
+msgstr "Dolù"
+
+#. 'Find Next' button
+#: gui_gtk.c:1647 gui_motif.c:2766
+msgid "Find Next"
+msgstr "Najít dal¹í"
+
+#. 'Replace' button
+#: gui_gtk.c:1664 gui_motif.c:2783
+msgid "Replace"
+msgstr "Nahradit"
+
+#. 'Replace All' button
+#: gui_gtk.c:1673 gui_motif.c:2796
+msgid "Replace All"
+msgstr "Nahradit v¹e"
+
+#: gui_gtk_x11.c:1076 gui_x11.c:1199
+msgid "E233: cannot open display"
+msgstr "E233: nelze otevøít display"
+
+#: gui_gtk_x11.c:2433 gui_x11.c:2002
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Neznámá sada písem: %s"
+
+#: gui_gtk_x11.c:2460
+msgid "Font Selection"
+msgstr "Výbìr písma"
+
+#: gui_gtk_x11.c:2702 gui_mac.c:2780 gui_w48.c:1197 gui_x11.c:1838
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Neznámé písmo: %s"
+
+#: gui_gtk_x11.c:2713 gui_x11.c:1862
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: Písmo \"%s\" nemá pevnou ¹íøku"
+
+#: gui_gtk_x11.c:2843
+#, c-format
+msgid "E242: Color name not recognized: %s"
+msgstr "E242: Neznámé jméno barvy: %s"
+
+#: gui_gtk_x11.c:3519 ui.c:1929
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "Místo prádné schránky pou¾ito CUT_BUFFER0"
+
+#: gui_motif.c:1601 gui_motif.c:1604
+msgid "Filter"
+msgstr "Filtr"
+
+#: gui_motif.c:1603
+msgid "Directories"
+msgstr "Adresáøe"
+
+#: gui_motif.c:1605
+msgid "Help"
+msgstr "Nápovìda"
+
+#: gui_motif.c:1606
+msgid "Files"
+msgstr "Soubory"
+
+#: gui_motif.c:1608
+msgid "Selection"
+msgstr "Výbìr"
+
+#: gui_motif.c:2809
+msgid "Undo"
+msgstr "Zpìt"
+
+#: gui_riscos.c:951
+#, c-format
+msgid "E235: Can't load Zap font '%s'"
+msgstr "E235: Nelze naèíst Zap font '%s'"
+
+#: gui_riscos.c:1047
+#, c-format
+msgid "E235: Can't use font %s"
+msgstr "E235: Nelze pou¾ít font %s"
+
+#: gui_riscos.c:1167
+#, c-format
+msgid "E242: Missing color: %s"
+msgstr "E242: Chybí barva: %s"
+
+#: gui_riscos.c:3269
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Posílám signál k ukonèení synovského procesu.\n"
+
+#: gui_w32.c:823
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Argument nepodporován: \"-%s\"; Pou¾ijte OLE verzi."
+
+#: gui_w48.c:2068
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Najít øetìzec (pou¾ijte '\\\\' k nalezení '\\')"
+
+#: gui_w48.c:2093
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Najít & Nahradit (pou¾ijte '\\\\' k nalezení '\\')"
+
+#: gui_x11.c:1419
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: nelze alokovat polo¾ku barevné mapy. Nìkteré barvy mohou být "
+"nesprávné"
+
+#: gui_x11.c:1992
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: písma pro následující znakové sady chybí v sadì písem %s:"
+
+#: gui_x11.c:2035
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: název sady písem: %s"
+
+#: gui_x11.c:2036
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "Písmo '%s' nemá pevnou ¹íøku"
+
+#: gui_x11.c:2055
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: název sady písem: %s\n"
+
+#: gui_x11.c:2056
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Písmo0: %s\n"
+
+#: gui_x11.c:2057
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Písmo1: %s\n"
+
+#: gui_x11.c:2058
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "©íøka písma%d není dvojnásoblem ¹íøky písma0\n"
+
+#: gui_x11.c:2059
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "©íøka písma0: %ld\n"
+
+#: gui_x11.c:2060
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"©íøka písma1: %ld\n"
+"\n"
+
+#: gui_x11.c:2206
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: nelze alokovat barvu %s"
+
+#: gui_x11.c:3256
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Chyba -- nelze pøeèíst sign data!"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: CYBA Hangul automatu"
+
+#: if_cscope.c:67
+msgid "Add a new database"
+msgstr "Pøidat novou databázi"
+
+#: if_cscope.c:69
+msgid "Query for a pattern"
+msgstr "Hledání vzorku"
+
+#: if_cscope.c:71
+msgid "Show this message"
+msgstr "Zobrazit tuto zprávu"
+
+#: if_cscope.c:73
+msgid "Kill a connection"
+msgstr "Ukonèit spojení"
+
+#: if_cscope.c:75
+msgid "Reinit all connections"
+msgstr "Znovu inicializovat v¹echna spojení"
+
+#: if_cscope.c:77
+msgid "Show connections"
+msgstr "Zobrazit spojení"
+
+#: if_cscope.c:108
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Tento cscope pøíkaz nepodporuje rozdìlení okna.\n"
+
+#: if_cscope.c:143
+msgid "Usage: cstag <ident>"
+msgstr "Pou¾ití: cstag <odsazení>"
+
+#: if_cscope.c:199
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: tag nenalezen"
+
+#: if_cscope.c:407 if_cscope.c:451
+#, c-format
+msgid "stat(%s) error: %d"
+msgstr "stat(%s) chyba: %d"
+
+#: if_cscope.c:460 if_cscope.c:467
+#, c-format
+msgid "Added cscope database %s"
+msgstr "Pøidána cscope databáze %s"
+
+#: if_cscope.c:474
+#, c-format
+msgid "%s is not a directory or a valid cscope database"
+msgstr "%s není ani adresáøem ani správnou cscope databází"
+
+#: if_cscope.c:557
+#, c-format
+msgid "error reading cscope connection %d"
+msgstr "chyba pøi ètení cscope spojení %d"
+
+#: if_cscope.c:633
+msgid "unknown cscope search type"
+msgstr "neznámý typ cscope hledání"
+
+#: if_cscope.c:680
+msgid "Could not create cscope pipes"
+msgstr "nelze vytvoøit cscope roury"
+
+#: if_cscope.c:745
+msgid "cs_create_connection exec failed"
+msgstr "spu¹tìní cs_create_connection selhalo"
+
+#: if_cscope.c:755
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: volání fdopen pro to_fp selhalo"
+
+#: if_cscope.c:757
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: volání fdopen pro fr_fp selhalo"
+
+#: if_cscope.c:785
+msgid "no cscope connections"
+msgstr "¾ádná cscope spojení"
+
+#: if_cscope.c:855
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: cscope hledání %s vzorku %s nena¹lo ¾ádnou shodu"
+
+#: if_cscope.c:899
+msgid "cscope commands:\n"
+msgstr "pøíkazy cscope:\n"
+
+#: if_cscope.c:902
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)\n"
+msgstr "%-5s: %-30s (Pou¾ití: %s)\n"
+
+#: if_cscope.c:970
+msgid "duplicate cscope database not added"
+msgstr "duplicitní cscope databáze nebyla pøidána"
+
+#: if_cscope.c:981
+msgid "maximum number of cscope connections reached"
+msgstr "dosa¾en maximální poèet cscope spojení"
+
+#: if_cscope.c:1102
+msgid "E260: cscope connection not found"
+msgstr "E260: connection spojení nenalezeno"
+
+#: if_cscope.c:1105
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: connection spojení %s nenalezeno"
+
+#: if_cscope.c:1141
+msgid "cscope connection closed"
+msgstr "closed spojení uzavøeno"
+
+#: if_cscope.c:1149
+#, c-format
+msgid "cscope connection %s closed\n"
+msgstr "cscope spojení %s uzavøeno\n"
+
+#. should not reach here
+#: if_cscope.c:1290
+msgid "fatal error in cs_manage_matches"
+msgstr "osudová chyba v cs_manage_matches"
+
+#: if_cscope.c:1341
+#, c-format
+msgid "E262: error reading cscope connection %d"
+msgstr "E262: pøi ètení cscope spojení %d"
+
+#: if_cscope.c:1449
+msgid "couldn't malloc\n"
+msgstr "volání malloc selhalo\n"
+
+#: if_cscope.c:1454
+#, c-format
+msgid "Cscope tag: %s\n"
+msgstr "Cscope tag: %s\n"
+
+#: if_cscope.c:1458
+msgid " # line"
+msgstr " # øádek"
+
+#: if_cscope.c:1460
+msgid "filename / context / line\n"
+msgstr "název souboru/ kontext/ øádek\n"
+
+#: if_cscope.c:1718
+msgid "All cscope databases reset"
+msgstr "V¹echny cscope databáze resetovány"
+
+#: if_cscope.c:1785
+msgid "no cscope connections\n"
+msgstr "¾ádné cscope spojení\n"
+
+#: if_cscope.c:1789
+msgid " # pid database name prepend path\n"
+msgstr " # pid název databáze pøedpona cesty\n"
+
+#: if_cscope.c:1800
+#, c-format
+msgid "%2d %-5ld %-34s <none>\n"
+msgstr "%2d %-5ld %-34s <¾ádný>\n"
+
+#: if_python.c:376
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: Lituji, tento pøíkaz je deaktivován; knihovnu jazyka Python nelze "
+"nahrát."
+
+#: if_python.c:576
+msgid "can't delete OutputObject attributes"
+msgstr "nelze smazat atributy OutputObject"
+
+#: if_python.c:583
+msgid "softspace must be an integer"
+msgstr "softspace musí být kladné celé èíslo"
+
+#: if_python.c:591
+msgid "invalid attribute"
+msgstr "chybný atribut"
+
+#: if_python.c:630 if_python.c:644
+msgid "writelines() requires list of strings"
+msgstr "writelines() vy¾aduje seznam øetìzcù"
+
+#: if_python.c:770
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: chyba pøi inicializaci I/O objektù"
+
+#: if_python.c:955 if_tcl.c:1391
+msgid "invalid expression"
+msgstr "Chybný výraz"
+
+#: if_python.c:969 if_tcl.c:1396
+msgid "expressions disabled at compile time"
+msgstr "podpora výrazù byla vypnuta pøi pøekladu programu"
+
+#: if_python.c:982
+msgid "attempt to refer to deleted buffer"
+msgstr "pokus o odkaz na smazaný buffer"
+
+#: if_python.c:997 if_python.c:1038 if_python.c:1102 if_tcl.c:1203
+msgid "line number out of range"
+msgstr "èíslo øádku mimo rozsah"
+
+#: if_python.c:1235
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<buffer objekt (smazán) na %8lX>"
+
+#: if_python.c:1326 if_tcl.c:825
+msgid "invalid mark name"
+msgstr "chybné jméno znaèky"
+
+#: if_python.c:1601
+msgid "no such buffer"
+msgstr "¾ádný takový buffer"
+
+#: if_python.c:1689
+msgid "attempt to refer to deleted window"
+msgstr "pokus o odkaz na smazané okno"
+
+#: if_python.c:1734
+msgid "readonly attribute"
+msgstr "atribut pouze_pro_ètení"
+
+#: if_python.c:1747
+msgid "cursor position outside buffer"
+msgstr "umístìní kurzoru mimo buffer"
+
+#: if_python.c:1824
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<objekt okna (smazán) na %8lX>"
+
+#: if_python.c:1836
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<objekt okna (neznámý) na %8lX>"
+
+#: if_python.c:1838
+#, c-format
+msgid "<window %d>"
+msgstr "<okno %d>"
+
+#: if_python.c:1914
+msgid "no such window"
+msgstr "¾ádné takové okno"
+
+#: if_python.c:2144 if_python.c:2175 if_python.c:2225 if_python.c:2285
+#: if_python.c:2402 if_python.c:2454 if_tcl.c:673 if_tcl.c:718 if_tcl.c:792
+#: if_tcl.c:862 if_tcl.c:1987
+msgid "cannot save undo information"
+msgstr "nelze ulo¾it informace pro pøíkaz undo"
+
+#: if_python.c:2146 if_python.c:2232 if_python.c:2296
+msgid "cannot delete line"
+msgstr "nelze smazat øádek"
+
+#: if_python.c:2177 if_python.c:2312 if_tcl.c:679 if_tcl.c:2009
+msgid "cannot replace line"
+msgstr "nelze nahradit øádek"
+
+#: if_python.c:2328 if_python.c:2404 if_python.c:2462
+msgid "cannot insert line"
+msgstr "nelze vlo¾it øádek"
+
+#: if_python.c:2566
+msgid "string cannot contain newlines"
+msgstr "øetìzec nesmí obsahovat znaky nového øádku"
+
+#: if_ruby.c:394
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: Lituji, ale tento pøíkaz je deaktivován; knihovnu jazyka Ruby nelze "
+"nahrát."
+
+#: if_ruby.c:457
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: neznámý longjmp stav %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Prohození implementace/definice"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Zobrazení base class z"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Zobrazení overridden member funkce"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Znovuzískáno ze souboru"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Znovuzískáno z projektu"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Znovzískáno ze v¹ech projektù"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Znovuzískáno"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Zobrazení zdroje"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Najít symbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Prohlí¾et class"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Zobrazení class v hierarchii"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Zobrazení class v restricted hierarchii"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref odkazuje na"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref odkazoval na"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref má"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref pou¾it"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Zobrazení documentace"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Generována dokumentace pro"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"Nelze se pøipojit k SNiFF+. Zkontrolujte promìnné (sniffemacs musí "
+"být)uvedena v $PATH.\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Chyba pøi ètení. Odpojeno"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ je právì "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "ne "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "pøipojen"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Neznámý po¾adavek SNiFF+: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Chybné pøipojení k SNiFF+"
+
+#: if_sniff.c:1010
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ nepøipojen"
+
+#: if_sniff.c:1019
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Není SNiFF+ buffer"
+
+#: if_sniff.c:1084
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: Chyba pøi zápisu. Odpojeno."
+
+#: if_tcl.c:407
+msgid "invalid buffer number"
+msgstr "chybný název bufferu"
+
+#: if_tcl.c:453 if_tcl.c:920 if_tcl.c:1099
+msgid "not implemented yet"
+msgstr "není je¹tì podporováno"
+
+#: if_tcl.c:490
+msgid "unknown option"
+msgstr "neznámá volba"
+
+#. ???
+#: if_tcl.c:763
+msgid "cannot set line(s)"
+msgstr "nelze nastavit øádky"
+
+#: if_tcl.c:834
+msgid "mark not set"
+msgstr "znaèka není nastavena"
+
+#: if_tcl.c:840 if_tcl.c:1055
+#, c-format
+msgid "row %d column %d"
+msgstr "øádek %d sloupec %d"
+
+#: if_tcl.c:870
+msgid "cannot insert/append line"
+msgstr "nelze vlo¾it/pøipojit øádek"
+
+#: if_tcl.c:1257
+msgid "unknown flag: "
+msgstr "neznámý pøíznak: "
+
+#: if_tcl.c:1327
+msgid "unknown vimOption"
+msgstr "neznámá vimOption"
+
+#: if_tcl.c:1412
+msgid "keyboard interrupt"
+msgstr "pøeru¹ení z klávesnice"
+
+#: if_tcl.c:1417
+msgid "vim error"
+msgstr "chyba vim"
+
+#: if_tcl.c:1460
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "nelze vytvoøit pøíkaz bufferu/okna: objekt smazán"
+
+#: if_tcl.c:1534
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"nelze zaregistrovat pøíkaz zpìtného volání: buffer/okno ji¾ bylo smazáno"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1551
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to "
+"vim-dev@vim.org"
+msgstr ""
+"E280: TCL FATAL ERROR: reflist po¹kozen!? Oznamte, prosím, tuto chybu na "
+"vim-dev@vim.org"
+
+#: if_tcl.c:1552
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"nelze zaregistrovat pøíkaz zpìtného volání: odkaz na buffer/okno nenalezen"
+
+#: if_tcl.c:1713
+msgid "Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"Lituji, ale tento pøíkaz je deaktivován; knihovnu jazyka Tcl nelze nahrát."
+
+#: if_tcl.c:1875
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: TCL CHYBA: návratový kód není celé èíslo!? Oznamte, prosím, tuto chybu "
+"na vim-dev@vim.org"
+
+#: if_tcl.c:1995
+msgid "cannot get line"
+msgstr "nelze pøeèíst øádek"
+
+#: if_xcmdsrv.c:204
+msgid "Unable to register a command server name"
+msgstr "Není mo¾né zaznamenat jméno command serveru"
+
+#: if_xcmdsrv.c:417
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: Neexistuje registrovaný server jménem \"%s\""
+
+#: if_xcmdsrv.c:446
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Selhalo zaslání pøíkazu urèenému programu"
+
+#: if_xcmdsrv.c:714
+#, c-format
+msgid "Invalid server id used: %s"
+msgstr "Pou¾it chybný id serveru: %s"
+
+#: if_xcmdsrv.c:1061
+msgid "E249: couldn't read VIM instance registry property"
+msgstr "E249: nelze èíst VIM instanci registry property"
+
+#: if_xcmdsrv.c:1072
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr ""
+"E251: VIM instance registry property byla ¹patnì vytvoøenaa byla smazána!"
+
+#: main.c:53 option.c:3162 option.c:3269
+msgid "Unknown option"
+msgstr "Neznámá volba"
+
+#: main.c:55
+msgid "Too many edit arguments"
+msgstr "Pøíli¹ mnoho edit argumentù"
+
+#: main.c:57
+msgid "Argument missing after"
+msgstr "Chybí argument po"
+
+#: main.c:59
+msgid "Garbage after option"
+msgstr "Chyby za volbou"
+
+#: main.c:61
+msgid "Too many \"+command\" or \"-c command\" arguments"
+msgstr "Pøíli¹ mnoho \"+pøíkaz\" èi \"-c pøíkaz\" argumentù"
+
+#: main.c:63
+msgid "Invalid argument for"
+msgstr "Chybný argument pro"
+
+#: main.c:436
+msgid "This Vim was not compiled with the diff feature."
+msgstr "VIM nebyl pøelo¾en s volbou +diff"
+
+#: main.c:858
+msgid "Attempt to open script file again: \""
+msgstr "Pokus o opìtovné otevøení skriptu: \""
+
+#: main.c:862 main.c:869 main.c:913 memline.c:3673 memline.c:3677
+#: version.c:816 version.c:821 version.c:826 version.c:831 version.c:836
+#: version.c:841 version.c:847 version.c:851 version.c:855 version.c:860
+#: version.c:867 version.c:875 version.c:881
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:867
+msgid "Cannot open for reading: \""
+msgstr "Nelze otevøít pro zápis: \""
+
+#: main.c:911
+msgid "Cannot open for script output: \""
+msgstr "Nelze otevøít pro výstup skriptu: \""
+
+#: main.c:1020
+#, c-format
+msgid "%d files to edit\n"
+msgstr "poèet souborù pro editaci: %d\n"
+
+#: main.c:1094
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Varování: výstup nesmìøuje na terminál\n"
+
+#: main.c:1096
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Varování: vstup nepochází z terminálu\n"
+
+#. just in case..
+#: main.c:1171
+msgid "pre-vimrc command line"
+msgstr "pre-vimrc pøíkazový øádek"
+
+#: main.c:1206
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Nelze èíst z \"%s\""
+
+#: main.c:2157
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Podrobnìj¹í informace získáte pomocí \"vim -h\"\n"
+
+#: main.c:2190
+msgid "[file ..] edit specified file(s)"
+msgstr "[SOUBOR] .. editovat SOUBOR(y)"
+
+#: main.c:2191
+msgid "- read text from stdin"
+msgstr "- èíst text ze standardního vstupu"
+
+#: main.c:2192
+msgid "-t tag edit file where tag is defined"
+msgstr "-t TAG editovat soubor na místì definice TAGU"
+
+#: main.c:2194
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [chybový soubor] editovat soubor na místì výskytu první chyby"
+
+#: main.c:2203
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"pou¾ití:"
+
+#: main.c:2206
+msgid " vim [arguments] "
+msgstr "vim [pøepínaèe] "
+
+#: main.c:2210
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" nebo"
+
+#: main.c:2213
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Argumenty:\n"
+
+#: main.c:2214
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tMohou následovat pouze názvy souborù"
+
+#: main.c:2216
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tpøihlásit gvim na OLE"
+
+#: main.c:2217
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-register\t\todhlásit gvim z OLE"
+
+#: main.c:2220
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tspustit v GUI re¾imu (stejné jako \"gvim\")"
+
+#: main.c:2221
+msgid "-f\t\t\tForeground: Don't fork when starting GUI"
+msgstr "-f\t\t\tPopøedí: pøi startu GUI se neoddìlí od shellu"
+
+#: main.c:2223
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi mód (stejné jako \"vi\")"
+
+#: main.c:2224
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-v\t\t\tEx mód (stejné jako \"ex\")"
+
+#: main.c:2225
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tTichý (dávkový) re¾im (pouze pro \"ex\")"
+
+#: main.c:2227
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tDiff re¾im (stejné jako \"vimdiff\")"
+
+#: main.c:2229
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-v\t\t\tSnadný re¾im (stejné jako \"evim\", ¾ádné módy )"
+
+#: main.c:2230
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tRe¾im pouze_pro_ètení (jako \"view\")"
+
+#: main.c:2231
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tOmezený re¾im (stejné jako \"rvim\")"
+
+#: main.c:2232
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tZmìny (ukládání souborù) zakázány"
+
+#: main.c:2233
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tZmìny (ukládání souborù) zakázány"
+
+#: main.c:2234
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tBinární re¾im"
+
+#: main.c:2236
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp re¾im"
+
+#: main.c:2238
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tKompatabilní s Vi: 'compatible'"
+
+#: main.c:2239
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tKompatibilita s Vi vypnuta: 'nocompatible'"
+
+#: main.c:2240
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tÚroveò výpisu hlá¹ek"
+
+#: main.c:2241
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tLadící re¾im"
+
+#: main.c:2242
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tNebude vytváøet odkládací soubor, bude pou¾ívat pouze pamì»"
+
+#: main.c:2243
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tVypí¹e seznam odkládacích souborù a skonèí"
+
+#: main.c:2244
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r název souboru\tObnoví pøeru¹ené sezení"
+
+#: main.c:2245
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tStejné jako -r"
+
+#: main.c:2247
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tNebude pou¾ívat newcli pro otevøení okna"
+
+#: main.c:2248
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <zaøízení>\t\tPou¾ít <zaøízení> pro I/O"
+
+#: main.c:2251
+msgid "-H\t\t\tstart in Hebrew mode"
+msgstr "-H\t\t\tnastartuje v hebrejském re¾imu"
+
+#: main.c:2254
+msgid "-F\t\t\tstart in Farsi mode"
+msgstr "-F\t\t\tnastartuje ve Farsi re¾imu"
+
+#: main.c:2256
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminál>\tNastaví typ terminálu na <terminál>"
+
+#: main.c:2257
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tPou¾ije <vimrc> místo jakéhokoliv .vimrc"
+
+#: main.c:2259
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tPou¾ije <gvimrc> místo jakéhokoliv .gvimrc"
+
+#: main.c:2261
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tNenahraje 'plugin' skripty"
+
+#: main.c:2262
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tOtevøe N oken (implicitnì jedno pro ka¾dý soubor)"
+
+#: main.c:2263
+msgid "-O[N]\t\tlike -o but split vertically"
+msgstr "-O[N]\t\tJako -o but split vertically"
+
+#: main.c:2264
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tNastaví kurzor na konec souboru"
+
+#: main.c:2265
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<øádek>\t\tNastaví kurzor na <øádek>"
+
+#: main.c:2267
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <pøíkaz>\tPo nahrání prvního souboru vykoná <pøíkaz>"
+
+#: main.c:2269
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <pøíkaz>\t\tPo nahrání prvního souboru vykoná <pøíkaz>"
+
+#: main.c:2270
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr ""
+"-S <sezení>\t\tPo nahrání prvního souboru vykoná pøíkazy v souboru <sezení>"
+
+#: main.c:2271
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <skript>\t\tNaète pøíkazy normálního módu ze <skriptu>"
+
+#: main.c:2272
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <skript>\t\tPøipojí v¹echny napsané pøíkazy do souboru <skript>"
+
+#: main.c:2273
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <skript>\t\tUlo¾í v¹echny napsané pøíkazy do souboru <skript>"
+
+#: main.c:2275
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tEditace za¹ifrovaných souborù"
+
+#: main.c:2279
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\tSpustí vim na daný X-server"
+
+#: main.c:2281
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tNepøipojí se k X serveru"
+
+#: main.c:2283
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tOtevøe Vim uvnitø jiného GTK widgetu"
+
+#: main.c:2287
+msgid "--remote <files>\tEdit <files> in a Vim server and exit"
+msgstr "--remote <soubory>\tEdituje <soubory> na Vim serveru a skonèí"
+
+#: main.c:2288
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr ""
+"--remote-wait <soubory> Jako --remote, ale èeká na soubory k editaci"
+
+#: main.c:2289
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <klávesy>\tPøedá <klávesy> Vim serveru a skonèí"
+
+#: main.c:2290
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <výraz>\tProvede <výraz> na serveru a zobrazí výsledek"
+
+#: main.c:2291
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tVypí¹e seznam dostupných Vim serverù a skonèí"
+
+#: main.c:2292
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr ""
+"--servername <jméno>\tZa¹le serveru <jméno>/stane se Vim serverem <jméno>"
+
+#: main.c:2295
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tPou¾ije <viminfo> místo jakéhokoliv .viminfo"
+
+#: main.c:2297
+msgid "-h\t\t\tprint Help (this message) and exit"
+msgstr "-h\t\t\tVypí¹e tuto nápovìdu a skonèí"
+
+#: main.c:2298
+msgid "--version\t\tprint version information and exit"
+msgstr "--version\t\tvypí¹e informace o verzi a skonèí"
+
+#: main.c:2302
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Pøepínaèe pro gvim (Motif verzi):\n"
+
+#: main.c:2305
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Pøepínaèe pro gvim (Athena verzi):\n"
+
+#: main.c:2308
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\tSpustí vim na <display>"
+
+#: main.c:2309
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tSpustí vim minimalizované"
+
+#: main.c:2311
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <název>\t\tPou¾ije resource jako by vim mìl <název>"
+
+#: main.c:2312
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (není implementováno)\n"
+
+#: main.c:2314
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <barva>\tNastaví <barvu> pozadí (také -bg)"
+
+#: main.c:2315
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <barva>\tNastaví <barvu> popøedí (také -fg)"
+
+#: main.c:2316 main.c:2336
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <písmo>\t\tNastaví <písmo> normálního textu (také -fn)"
+
+#: main.c:2317
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <písmo>\tNastaví <písmo> pro zvýraznìný text"
+
+#: main.c:2318
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <písmo>\tNastaví <písmo> pro kurzívu"
+
+#: main.c:2319 main.c:2337
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geometrie>\tNastaví <geometrii> (také -geom)"
+
+#: main.c:2320
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <¹íøka>\tNastaví <¹íøku> okrajù (také -bw)"
+
+#: main.c:2321
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <¹íøku> Nastaví <¹íøku> posunovací li¹ty (také: -sw)"
+
+#: main.c:2323
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <vý¹ka>\tNastaví <vý¹ku> nabídky (také -mh)"
+
+#: main.c:2325 main.c:2338
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tPou¾ije reverzní barvy (také -rv)"
+
+#: main.c:2326
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tNepou¾ije reverzní barvy (také +rv)"
+
+#: main.c:2327
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\tNastaví zadaný <resource>"
+
+#: main.c:2330
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Pøepínaèe pro gvim (RISC OS verzi):\n"
+
+#: main.c:2331
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <poèet>\t<poèet> sloupcù na okno"
+
+#: main.c:2332
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <poèet>\t<poèet> øádkù na okno"
+
+#: main.c:2335
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Pøepínaèe pro gvim (GTK+ verzi):\n"
+
+#: main.c:2339
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\tSpustí vim na <display> (také --display)"
+
+#: main.c:2341
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tVypí¹e Gnome pøepínaèe"
+
+#. Failed to send, abort.
+#: main.c:2566
+msgid ""
+"\n"
+"Send failed.\n"
+msgstr ""
+"\n"
+"Pøedání výrazu selhalo.\n"
+
+#. Let vim start normally.
+#: main.c:2571
+msgid ""
+"\n"
+"Send failed. Trying to execute locally\n"
+msgstr ""
+"\n"
+"Pøedání selhalo. Zkou¹ím provést lokálnì\n"
+
+#: main.c:2604 main.c:2625
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d z %d editováno"
+
+#: main.c:2648
+msgid "Send expression failed.\n"
+msgstr "Pøedání výrazu selhalo.\n"
+
+#: mark.c:660
+msgid "No marks set"
+msgstr "Nejsou nastaveny ¾ádné znaèky"
+
+#: mark.c:662
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: \"%s\" nevyhovují ¾ádné znaèky"
+
+#. Highlight title
+#: mark.c:673
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"znaèka øádek sloupec soubor/text"
+
+#. Highlight title
+#: mark.c:711
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" skok øádek sloupec soubor/text"
+
+#: mark.c:1073
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Souborové znaèky:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1108
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Seznam skokù (poèínaje nejnovìj¹í polo¾kou):\n"
+
+#: mark.c:1203
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Historie znaèek v souborech (poèínaje nejnovìj¹í polo¾kou):\n"
+
+#: mark.c:1286
+msgid "Missing '>'"
+msgstr "Chybí '>'"
+
+#: mbyte.c:395
+msgid "Not a valid codepage"
+msgstr "Chybná kódová stránka"
+
+#: mbyte.c:3014
+msgid "E284: Cannot set IC values"
+msgstr "E284: Nelze nastavit IC hodnoty"
+
+#: mbyte.c:3166
+msgid "E285: Failed to create input context"
+msgstr "E285: Nepodaøilo se vytvoøit vstupní kontext"
+
+#: mbyte.c:3313
+msgid "E286: Failed to open input method"
+msgstr "E286: Nepodaøilo se otevøít vstupní metodu"
+
+#: mbyte.c:3324
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: Varování: likvidaèní zpìtné volání nelze nastavit na IM"
+
+#: mbyte.c:3330
+msgid "E288: input method doesn't support any style"
+msgstr "E288: vstupní metoda nepodporuje ¾ádný styl"
+
+#: mbyte.c:3387
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: vstupní metoda nepodporuje mùj 'preedit' typ"
+
+#: mbyte.c:3461
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: Nadbodový styl vy¾aduje fontset"
+
+#: mbyte.c:3489
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: Máte GTK+ verze star¹í ne¾ 1.2.3. Stavová plocha vypnuta."
+
+#: mbyte.c:3726
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Server vstupních metod nebì¾í"
+
+#: memfile.c:473
+msgid "E293: block was not locked"
+msgstr "E293: blok nebyl zamknut"
+
+#: memfile.c:972
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Chyba posunu ukazovátka pøi ètení odkládacího souboru"
+
+#: memfile.c:977
+msgid "E295: Read error in swap file"
+msgstr "E295: Chyba pøi ètení odkládacího souboru"
+
+#: memfile.c:1029
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Chyba posunu ukazovátka pøi ukládání do odkládacího souboru"
+
+#: memfile.c:1047
+msgid "E297: Write error in swap file"
+msgstr "E297: Chyba pøi ukládání do odkládacího souboru"
+
+#: memfile.c:1244
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr ""
+"E300: Odkládací soubor ji¾ existuje! (Nìkdo hackujepøes nastra¾ený symlink?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Nelze získat blok 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Nelze získat blok 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: nelze získat blok 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Jéje, odkládací soubor byl ztracen!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: Nelze pøejmenovat odkládací soubor"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: Nelze otevøít odkládací soubor pro \"%s\""
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: nelze získat blok 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Odkládací soubor pro %s nebyl nalezen"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr ""
+"Zadejte èíslo odkládacího souboru, který se má pou¾ít (0 pro ukonèení): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: Nelze otevøít %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "Nelze èíst blok 0 z "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Mo¾ná nedo¹lo k ¾ádným zmìnám, nebo Vim neaktualizoval odkládací soubor."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " nelze pou¾ít s touto verzí Vim.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Pou¾ijte Vim verze 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s se nezdá být odkládacím souborem Vim"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " nelze pou¾ít na tomto poèítaèi.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "Soubor byl vytvoøen "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"nebo byl soubor po¹kozen."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "Pou¾ívám odkládací soubor \"%s\""
+
+#: memline.c:915
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Pùvodní soubor \"%s\""
+
+#: memline.c:934
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Varování: Pùvodní soubor mohl být zmìnìn"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Nelze èíst blok 1 z %s"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???CHYBÍ MNOHO ØÁDKÙ"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???CHYBNÝ POÈET ØÁDKÙ"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???PRÁZDNÝ BLOK"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???CHYBÌJÍCÍ ØÁDKY"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ID bloku 1 je chybné (je %s odkládacím souborem?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???CHYBÍ BLOK"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "od ??? po ???END mohou být øádky pomíchané"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "od ??? po ???END mohou být vlo¾ené/smazané øádky"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???KONEC"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Obnova pøeru¹ena"
+
+#: memline.c:1145
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr ""
+"E312: V prùbìhu obnovy do¹lo k chybám; zkontrolujte øádky zaèínající na ???"
+
+#: memline.c:1148
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Obnova dokonèena. Zkontrolujte, zda je v¹e v poøádku."
+
+#: memline.c:1149
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Zva¾te ulo¾ení tohoto souboru pod jiným názvem\n"
+
+#: memline.c:1150
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "a kontrolu zmìn pomocí programu diff.)\n"
+
+#: memline.c:1151
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr "Poté sma¾te odkládací soubor.\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1207
+msgid "Swap files found:"
+msgstr "Nalezené odkládací soubory:"
+
+#: memline.c:1385
+msgid " In current directory:\n"
+msgstr " V aktuálním adresáøi:\n"
+
+#: memline.c:1387
+msgid " Using specified name:\n"
+msgstr " Se zadaným názvem:\n"
+
+#: memline.c:1391
+msgid " In directory "
+msgstr " V adresáøi "
+
+#: memline.c:1409
+msgid " -- none --\n"
+msgstr " -- ¾ádné --\n"
+
+#: memline.c:1481
+msgid " owned by: "
+msgstr " vlastník: "
+
+#: memline.c:1483
+msgid " dated: "
+msgstr " datum vytvoøení: "
+
+#: memline.c:1487 memline.c:3680
+msgid " dated: "
+msgstr " datum vytvoøení: "
+
+#: memline.c:1503
+msgid " [from Vim version 3.0]"
+msgstr " [od Vim verze 3.0]"
+
+#: memline.c:1507
+msgid " [does not look like a Vim swap file]"
+msgstr " [nevypadá jako odkládací soubor Vim]"
+
+#: memline.c:1511
+msgid " file name: "
+msgstr " název souboru: "
+
+#: memline.c:1523
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" datum zmìny: "
+
+#: memline.c:1524
+msgid "YES"
+msgstr "ANO"
+
+#: memline.c:1524
+msgid "no"
+msgstr "ne"
+
+#: memline.c:1528
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" u¾ivatelské jméno: "
+
+#: memline.c:1535
+msgid " host name: "
+msgstr " název poèítaèe: "
+
+#: memline.c:1537
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" název poèítaèe: "
+
+#: memline.c:1543
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ID procesu : "
+
+#: memline.c:1549
+msgid " (still running)"
+msgstr " (stále aktivní)"
+
+#: memline.c:1561
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [nepou¾itelné s touto verzí Vim]"
+
+#: memline.c:1564
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [nepou¾itelné na tomto poèítaèi]"
+
+#: memline.c:1569
+msgid " [cannot be read]"
+msgstr " [nelze pøeèíst]"
+
+#: memline.c:1573
+msgid " [cannot be opened]"
+msgstr " [nelze otevøít]"
+
+#: memline.c:1763
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Nelze zachovat - odkládací soubor neexistuje."
+
+#: memline.c:1816
+msgid "File preserved"
+msgstr "Soubor zachován"
+
+#: memline.c:1818
+msgid "E314: Preserve failed"
+msgstr "E314: Uchování se nezdaøilo"
+
+#: memline.c:1889
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: chybné èíslo øádku: %ld"
+
+#: memline.c:1915
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: nelze nalézt øádek %ld"
+
+#: memline.c:2303
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: chybné id ukazatele na blok 3"
+
+#: memline.c:2383
+msgid "stack_idx should be 0"
+msgstr "stack_idx by mìlo mít hodnotu 3"
+
+#: memline.c:2445
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Aktualizováno pøíli¹ mnoho blokù?"
+
+#: memline.c:2602
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: chybné id ukazatele na blok 4"
+
+#: memline.c:2629
+msgid "deleted block 1?"
+msgstr "smazán blok 1?"
+
+#: memline.c:2829
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Nelze nalézt øádek %ld"
+
+#: memline.c:3072
+msgid "E317: pointer block id wrong"
+msgstr "E317: chybné id ukazatele na blok"
+
+#: memline.c:3088
+msgid "pe_line_count is zero"
+msgstr "pe_line_count má nulovou hodnotu"
+
+#: memline.c:3117
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: poèet øádkù mimo rozsah: %ld > celkový poèet øádkù"
+
+#: memline.c:3121
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: chybný poèet øádkù v bloku %ld"
+
+#: memline.c:3170
+msgid "Stack size increases"
+msgstr "Nárùst velikosti zásobníku"
+
+#: memline.c:3216
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: chybné id ukazatele na blok 2"
+
+#: memline.c:3670
+msgid "E325: ATTENTION"
+msgstr "E325: POZOR"
+
+#: memline.c:3671
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Nalezen odkládací soubor se jménem \""
+
+#: memline.c:3675
+msgid "While opening file \""
+msgstr "Pøi otevírání souboru\""
+
+#: memline.c:3684
+msgid " NEWER than swap file!\n"
+msgstr " NOVÌJ©Í ne¾ odkládací soubor!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3688
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Soubor mù¾e být editován jiným programem.\n"
+" Je-li tomu tak, pak si dejte pozor, aby jste po ulo¾ení zmìn\n"
+" nemìli dvì rùzné verze tého¾ souboru.\n"
+
+#: memline.c:3689
+msgid " Quit, or continue with caution.\n"
+msgstr " Ukonèete program, nebo opatrnì pokraèujte v editaci.\n"
+
+#: memline.c:3690
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) Editace tohoto souboru byla pøeru¹ena neèekaným ukonèením programu.\n"
+
+#: memline.c:3691
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Je-li tomu tak, pak pou¾ijte \":recover\" èi \"vim -r "
+
+#: memline.c:3693
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" pro odstranìní zmìn (viz \":help recovery)\".\n"
+
+#: memline.c:3694
+msgid " If you did this already, delete the swap file \""
+msgstr " Pokud jste tak ji¾ uèinil, tak sma¾te odkládací soubor \""
+
+#: memline.c:3696
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" a tato zpráva se ji¾ nebude objevovat.\n"
+
+#: memline.c:3710 memline.c:3714
+msgid "Swap file \""
+msgstr "Odkládací soubor \""
+
+#: memline.c:3711 memline.c:3717
+msgid "\" already exists!"
+msgstr "\" ji¾ existuje!"
+
+#: memline.c:3720
+msgid "VIM - ATTENTION"
+msgstr "VIM - POZOR"
+
+#: memline.c:3722
+msgid "Swap file already exists!"
+msgstr "Odkládací soubor ji¾ existuje!"
+
+#: memline.c:3726
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"&Otevøít pouze pro ètení\n"
+"&Pokraèovat v editaci\n"
+"O&bnovit soubor\n"
+"&Konec"
+
+#: memline.c:3728
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"&Otevøít pouze pro ètení\n"
+"&Pokraèovat v editaci\n"
+"O&bnovit soubor\n"
+"&Konec\n"
+"&Smazat"
+
+#: memline.c:3781
+msgid "E326: Too many swap files found"
+msgstr "E326: Pøíli¹ mnoho odkládacích souborù"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Èásti cesty k pøedmìtu nabídky není podnabídkou"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Nabídka existuje pouze v jiném módu"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Nabídka tohoto jména neexistuje"
+
+#: menu.c:503
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Cesta nabídkou nesmí vést do podnabídky"
+
+#: menu.c:542
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: Polo¾ky nabídky nelze pøidávat pøímo na li¹tu"
+
+#: menu.c:548
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Oddìlovaè nesmí být èástí cesty nabídkou"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1063
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Nabídky ---"
+
+#: menu.c:1989
+msgid "Tear off this menu"
+msgstr "Odtrhnout tuto nabídku"
+
+#: menu.c:2054
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Cesta nabídkou musí vést k polo¾ce nabídky"
+
+#: menu.c:2074
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Vzor nenalezen: %s"
+
+#: menu.c:2143
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: V %s módu není nabídka definována"
+
+#: menu.c:2181
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Cesta nabídkou musí vést do podnabídky"
+
+#: menu.c:2202
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Nabídka nenalezena - zkontrolujte názvy nabídek"
+
+#: message.c:467
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Chyba pøi zpracování %s:"
+
+#: message.c:483
+#, c-format
+msgid "line %4ld:"
+msgstr "øádek %4ld:"
+
+#: message.c:523
+msgid "[string too long]"
+msgstr "[pøíli¹ dlouhý øetìzec]"
+
+#: message.c:669
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "Správce zpráv: Bram Moolenaar <Bram@vim.org>"
+
+#: message.c:881
+msgid "Interrupt: "
+msgstr "Pøeru¹ení: "
+
+#: message.c:884
+msgid "Hit ENTER to continue"
+msgstr "pokraèování stiskem ENTER"
+
+#: message.c:886
+msgid "Hit ENTER or type command to continue"
+msgstr "Pro pokraèování stisknìte ENTER nebo zadejte pøíkaz"
+
+#: message.c:1940
+msgid "-- More --"
+msgstr "-- Pokraèování --"
+
+#: message.c:1943
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: øádek, MEZERNÍK/b: stránka, d/u: 0.5 stránky, q: konec)"
+
+#: message.c:1944
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: øádek, MEZERNÍK: stránka, d: 0.5 stránky, q: konec)"
+
+#: message.c:2419 message.c:2434
+msgid "Question"
+msgstr "Otázka"
+
+#: message.c:2421
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Ano\n"
+"&Ne"
+
+#: message.c:2436
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Ano\n"
+"&Ne\n"
+"&Zru¹it"
+
+#: message.c:2454
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Ano\n"
+"&Ne\n"
+"&Ulo¾it v¹e\n"
+"Zahodit &v¹e\n"
+"&Zru¹it"
+
+#: message.c:2494
+msgid "Save File dialog"
+msgstr "Dialog pro ukládání souborù"
+
+#: message.c:2496
+msgid "Open File dialog"
+msgstr "Dialog pro otevírání souborù"
+
+#. TODO: non-GUI file selector here
+#: message.c:2547
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: Lituji, ale konzolová verze nepodporuje prohlí¾eè souborù"
+
+#: misc1.c:2449
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: wc1: mìním soubor pouze_pro_ètení"
+
+#: misc1.c:2678
+msgid "1 more line"
+msgstr "poèet nových øádkù: 1"
+
+#: misc1.c:2680
+msgid "1 line less"
+msgstr "poèet smazaných øádkù: 1"
+
+#: misc1.c:2685
+#, c-format
+msgid "%ld more lines"
+msgstr "poèet nových øádkù: %ld"
+
+#: misc1.c:2687
+#, c-format
+msgid "%ld fewer lines"
+msgstr "poèet smazaných øádkù: %ld"
+
+#: misc1.c:2690
+msgid " (Interrupted)"
+msgstr "(Pøeru¹eno)"
+
+#: misc1.c:6245
+msgid "Vim: preserving files...\n"
+msgstr "Vim: zachovávám soubory...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6255
+msgid "Vim: Finished.\n"
+msgstr "Vim: ukonèen\n"
+
+#: misc2.c:647 misc2.c:663
+msgid "ERROR: "
+msgstr "CHYBA: "
+
+#: misc2.c:667
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bajtù] celkem uvolnìno-alokováno %lu-%lu, vyu¾ito %lu, maximální vyu¾ití "
+"%lu\n"
+
+#: misc2.c:669
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[volání] celkem re/malloc(): %lu, celkem free() %lu\n"
+"\n"
+
+#: misc2.c:724
+msgid "E340: Line is becoming too long"
+msgstr "E340: Øádek se stává pøíli¹ dlouhým"
+
+#: misc2.c:768
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Vnitøní chyba: lalloc(%ld, )"
+
+#: misc2.c:876
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Nedostatek pamìti! (potøebuji alokovat bajtù: %lu)"
+
+#: misc2.c:2511
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Spou¹tím pøíkaz \"%s\" pomocí shellu"
+
+#: misc2.c:2706 misc2.c:5148 option.c:4584
+msgid "Missing colon"
+msgstr "Chybí dvojteèka"
+
+#: misc2.c:2708 misc2.c:2735
+msgid "Illegal mode"
+msgstr "nepøípustný mód"
+
+#: misc2.c:2774
+msgid "Illegal mouseshape"
+msgstr "Chybný tvar my¹i"
+
+#: misc2.c:2814 misc2.c:5168
+msgid "digit expected"
+msgstr "oèekávána èíslice"
+
+#: misc2.c:2819
+msgid "Illegal percentage"
+msgstr "nepøípustné procento"
+
+#: misc2.c:3123
+msgid "Enter encryption key: "
+msgstr "Zadejte ¹ifrovací klíè: "
+
+#: misc2.c:3124
+msgid "Enter same key again: "
+msgstr "Zadejte je¹tì jednou tentý¾ klíè:"
+
+#: misc2.c:3134
+msgid "Keys don't match!"
+msgstr "Klíèe se neshodují"
+
+#: misc2.c:3648
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Chybná cesta: '**[èíslo] musí být buï na konci cesty, nebo musí být\n"
+"následováno'%s. Viz :help path."
+
+#: misc2.c:4905
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Adresáø \"%s\" nelze v cdpath nalézt"
+
+#: misc2.c:4908
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Soubor \"%s\" nelze v path nalézt"
+
+#: misc2.c:4914
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: ®ádný dal¹í adresáø \"%s\" nebyl v cdpath nalezen"
+
+#: misc2.c:4917
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: ®ádný dal¹í soubor \"%s\" nebyl v cestì nalezen"
+
+#: misc2.c:5160
+msgid "Illegal component"
+msgstr "nepøípustná souèást"
+
+#: normal.c:2813
+msgid "Warning: terminal cannot highlight"
+msgstr "Varování: terminál nepodporuje zvýrazòování"
+
+#: normal.c:3008
+msgid "E348: No string under cursor"
+msgstr "E348: pod kurzorem není ¾ádný øetìzec"
+
+#: normal.c:3010
+msgid "E349: No identifier under cursor"
+msgstr "E349: pod kurzorem není ¾ádný identifikátor"
+
+#: normal.c:4175
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: pomocí aktuální 'foldmethod' nelze mazat záhyby"
+
+#: ops.c:271
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "poèet øádkù posunutých jednou pomocí %s : 1"
+
+#: ops.c:273
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "Poèet øádkù posunutých pomocí %s %d-krát : 1"
+
+#: ops.c:278
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "Poèet øádkù: %ld (posunutých jednou pomocí %s)"
+
+#: ops.c:281
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "Poèet øádkù: %ld (posunutých pomocí %s %d-krát)"
+
+#: ops.c:638
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "poèet øádkù k odsazení: %ld"
+
+#: ops.c:688
+msgid "1 line indented "
+msgstr "poèet øádkù k odsazení: 1"
+
+#: ops.c:690
+#, c-format
+msgid "%ld lines indented "
+msgstr "poèet odsazených øádkù: %ld"
+
+#. must display the prompt
+#: ops.c:1528
+msgid "cannot yank; delete anyway"
+msgstr "nelze kopírovat; pøesto smazáno"
+
+#: ops.c:2018
+msgid "1 line changed"
+msgstr "poèet øádek se zmìnìnou velikostí písmen: 1"
+
+#: ops.c:2020
+#, c-format
+msgid "%ld lines changed"
+msgstr "poèet øádek se zmìnìnou velikostí písmen: %ld"
+
+#: ops.c:2381
+#, c-format
+msgid "freeing %ld lines"
+msgstr "poèet uvolòovaných øádkù: %ld"
+
+#: ops.c:2658
+msgid "1 line yanked"
+msgstr "poèet zkopírovaných øádkù: 1"
+
+#: ops.c:2660
+#, c-format
+msgid "%ld lines yanked"
+msgstr "poèet zkopírovaných øádkù: %ld"
+
+#: ops.c:2916
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: Registr %s je prázdný"
+
+#. Highlight title
+#: ops.c:3454
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Registry ---"
+
+#: ops.c:4565
+msgid "Illegal register name"
+msgstr "nepøípustný název registru"
+
+#: ops.c:4645
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Registry:\n"
+
+#: ops.c:4671
+#, c-format
+msgid "Unknown register type %d"
+msgstr "%d není známým typem registru"
+
+#: ops.c:5052
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: '%s' není pøípustné jméno registru"
+
+#: ops.c:5393
+#, c-format
+msgid "%ld Cols; "
+msgstr "øádkù: %ld;"
+
+#: ops.c:5400
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Vybráno %s%ld z %ld øádkù; %ld z %ld slov; %ld z %ld Bytù"
+
+#: ops.c:5416
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Sloupec %s z %s; Øádek %ld z %ld; Slovo %ld z %ld; Byte %ld z %ld"
+
+#: ops.c:5427
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld pro BOM)"
+
+#: option.c:1989
+msgid "Thanks for flying Vim"
+msgstr "Dìkuji za pou¾ití Vim"
+
+#: option.c:3175
+msgid "Option not supported"
+msgstr "Volba není podporována"
+
+#: option.c:3200
+msgid "Not allowed in a modeline"
+msgstr "Není v modeline povoleno"
+
+#: option.c:3256
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tNaposledy nastavena z "
+
+#: option.c:3395
+msgid "Number required after ="
+msgstr "Po = je vy¾adováno èíslo"
+
+#: option.c:3702 option.c:4309
+msgid "Not found in termcap"
+msgstr "Nenalezen v termcapu"
+
+#: option.c:3768
+#, c-format
+msgid "Illegal character <%s>"
+msgstr "Nepøípustný znak <%s>"
+
+#: option.c:4294 option.c:5497
+msgid "Not allowed here"
+msgstr "Toto zde není povoleno"
+
+#: option.c:4301
+msgid "Cannot set 'term' to empty string"
+msgstr "volba 'term' nemù¾e být prázdná"
+
+#: option.c:4304
+msgid "Cannot change term in GUI"
+msgstr "V GUI nelze mìnit term"
+
+#: option.c:4306
+msgid "Use \":gui\" to start the GUI"
+msgstr "Pou¾ijte \"gui\" pro spu¹tìní GUI"
+
+#: option.c:4327
+msgid "'backupext' and 'patchmode' are equal"
+msgstr "volby 'backupext' a 'patchmode' mají stejnou hodnotu"
+
+#: option.c:4586
+msgid "Zero length string"
+msgstr "øetìzec o nulové délce"
+
+#: option.c:4654
+#, c-format
+msgid "Missing number after <%s>"
+msgstr "Po <%s> chybí èíslo"
+
+#: option.c:4668
+msgid "Missing comma"
+msgstr "Chybí èárka"
+
+#: option.c:4675
+msgid "Must specify a ' value"
+msgstr "Je nutné zadat hodnotu '"
+
+#: option.c:4715
+msgid "contains unprintable character"
+msgstr "obsahuje netisknutelné znaky"
+
+#: option.c:4728
+msgid "Invalid font(s)"
+msgstr "Chybná písma"
+
+#: option.c:4734
+msgid "can't select fontset"
+msgstr "nelze vybrat sadu písem"
+
+#: option.c:4736
+msgid "Invalid fontset"
+msgstr "chybná sada písem"
+
+#: option.c:4743
+msgid "can't select wide font"
+msgstr "nelze vybrat ¹iroký font"
+
+#: option.c:4745
+msgid "Invalid wide font"
+msgstr "Chybné ¹iroké písmo"
+
+#: option.c:5014
+#, c-format
+msgid "Illegal character after <%c>"
+msgstr "Nepøípustný znak po <%c>"
+
+#: option.c:5097
+msgid "comma required"
+msgstr "je nutná èárka"
+
+#: option.c:5106
+#, c-format
+msgid "'commentstring' must be empty or contain %s"
+msgstr "volba `commentstring` musí být buï prázdná nebo nastavená na %s"
+
+#: option.c:5153
+msgid "No mouse support"
+msgstr "Bez podpory my¹i"
+
+#: option.c:5399
+msgid "Unclosed expression sequence"
+msgstr "neuzavøená sekvence výrazù"
+
+#: option.c:5403
+msgid "too many items"
+msgstr "pøíli¹ mnoho polo¾ek"
+
+#: option.c:5405
+msgid "unbalanced groups"
+msgstr "nevyvá¾ené skupiny"
+
+#: option.c:5620
+msgid "A preview window already exists"
+msgstr "Okno náhledu ji¾ existuje"
+
+#: option.c:5881 option.c:5910
+msgid "'winheight' cannot be smaller than 'winminheight'"
+msgstr ""
+"hodnota volby 'winheight' nesmí být men¹í ne¾ hodnota volby 'winminheight'"
+
+#: option.c:5926 option.c:5945
+msgid "'winwidth' cannot be smaller than 'winminwidth'"
+msgstr ""
+"hodnota volby 'winwidth' nesmí být men¹í ne¾ hodnota volby 'winminwidth'"
+
+#: option.c:6085
+#, c-format
+msgid "Need at least %d lines"
+msgstr "minimální potøebný poèet øádkù: %d"
+
+#: option.c:6094
+#, c-format
+msgid "Need at least %d columns"
+msgstr "minimální potøebný poèet sloupcù: %d"
+
+#: option.c:6391
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Neznámá volba: %s"
+
+#: option.c:6500
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Kódy terminálu ---"
+
+#: option.c:6502
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Nastavení globálních voleb ---"
+
+#: option.c:6504
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Nastavení lokálních voleb ---"
+
+#: option.c:6506
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Volby ---"
+
+#: option.c:7196
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp CHYBA"
+
+#: option.c:8112
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': pro %s chybí vyhovující znak"
+
+#: option.c:8146
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': nadbyteèné znaky po støedníku: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "nelze otevøít "
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Nelze otevøít nové okno!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Vy¾aduje Amigados verze 2.04 nebo vy¹¹í\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Vy¾aduje %s verze %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "Nelze otevøít NIL:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr " Nelze vytvoøit "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim bude ukonèen %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "Nelze zmìnit mód konzole ?!\n"
+
+#: os_amiga.c:938 os_mac.c:1168 os_mswin.c:619 os_riscos.c:728 os_unix.c:2726
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Nastavování re¾imu obrazovky není podporováno"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: neni konzole??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1142
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Nelze spustit shell s parametrem -f"
+
+#: os_amiga.c:1183 os_amiga.c:1273
+msgid "Cannot execute "
+msgstr "Nelze spustit "
+
+#: os_amiga.c:1186 os_amiga.c:1283
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1206 os_amiga.c:1308
+msgid " returned\n"
+msgstr " návratová hodnota shellu\n"
+
+#: os_amiga.c:1448
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE je pøíli¹ malá."
+
+#: os_amiga.c:1452
+msgid "I/O ERROR"
+msgstr "I/O CHYBA"
+
+#: os_mswin.c:503
+msgid "...(truncated)"
+msgstr "...(kráceno)"
+
+#: os_mswin.c:594
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' není 80, nelze spustit externí pøíkaz"
+
+#: os_mswin.c:706 os_unix.c:4945
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Volání knihovní funkce \"%s()\" selhalo"
+
+#: os_mswin.c:1340
+msgid "E237: Printer selection failed"
+msgstr "E237: Nelze zvolit tiskárnu"
+
+#: os_mswin.c:1388
+#, c-format
+msgid "to %s on %s"
+msgstr "do %s v %s"
+
+#: os_mswin.c:1449 os_mswin.c:1459
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Chyba tisku: %s"
+
+#: os_mswin.c:1460
+msgid "Unknown"
+msgstr "Neznámý"
+
+#: os_mswin.c:1487
+#, c-format
+msgid "Printing '%s'"
+msgstr "Vyti¹tìno '%s'"
+
+#: os_mswin.c:2551
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Nepøípustná jméno znakové sady \"%s\" ve fontu \"%s\""
+
+#: os_mswin.c:2559
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Nepøípustný znak '%c' ve fontu \"%s\""
+
+#: os_riscos.c:1227
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Neplatný 'osfiletype' - pou¾it Text"
+
+#: os_unix.c:800
+msgid "Vim: Double signal, exiting\n"
+msgstr "VIm: dvojitý signál, konèím\n"
+
+#: os_unix.c:806
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Zachycen smrtelný signál %s\n"
+
+#: os_unix.c:809
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Zachycen smrtelný signál\n"
+
+#: os_unix.c:1063
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Doba otevírání X displeje (v ms): %ld"
+
+#: os_unix.c:1090
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: chyba X11\n"
+
+#: os_unix.c:1157
+msgid "Testing the X display failed"
+msgstr "Test X displeje se nezdaøil"
+
+#: os_unix.c:1301
+msgid "Opening the X display timed out"
+msgstr "Vypr¹el èas pøi èekání na otevøení X displeje"
+
+#: os_unix.c:2899 os_unix.c:3483
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"nelze spustit shell "
+
+#: os_unix.c:2944
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Nelze spustit sh shell\n"
+
+#: os_unix.c:2948 os_unix.c:3489
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+" návratová hodnota shellu "
+
+#: os_unix.c:3082
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Nelze vytvoøit roury\n"
+
+#: os_unix.c:3097
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"Volání fork selhalo\n"
+
+#: os_unix.c:3496
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Pøíkaz ukonèen\n"
+
+#: os_unix.c:4993
+msgid "Opening the X display failed"
+msgstr "Otevøení X displeje se nezdaøilo"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "Na øádku"
+
+#: os_w32exe.c:169
+msgid "Could not load vim32.dll!"
+msgstr "Nelze naèíst vim32.dll!"
+
+#: os_w32exe.c:169 os_w32exe.c:179
+msgid "VIM Error"
+msgstr "Chyba VIMu"
+
+#: os_w32exe.c:179
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Nelze nastavit ukazatele funkcí na DLL"
+
+#: os_win16.c:578 os_win32.c:3021
+#, c-format
+msgid "shell returned %d"
+msgstr "návratová hodnota shellu %d"
+
+#: os_win32.c:2489
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Zachycen %s signál\n"
+
+#: os_win32.c:2491
+msgid "close"
+msgstr "zavøít"
+
+#: os_win32.c:2493
+msgid "logoff"
+msgstr "logoff"
+
+#: os_win32.c:2494
+msgid "shutdown"
+msgstr "shutdown"
+
+#: os_win32.c:2975
+msgid "E371: Command not found"
+msgstr "E371: Pøíkaz není k dispozici"
+
+#: os_win32.c:2988
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE se nevyskytuje ve Va¹í $PATH.\n"
+"Externí pøíkazy nebudou "
+
+#: os_win32.c:2991
+msgid "Vim Warning"
+msgstr "Varování"
+
+#: quickfix.c:281
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Pøíli¹ mnoho %%%c ve formátovacím øetìzci"
+
+#: quickfix.c:294
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: Neoèekávaný výskyt %%%c ve formátovacím øetìzci"
+
+#: quickfix.c:348
+msgid "E374: Missing ] in format string"
+msgstr "E374: Ve formátovacím øetìzci chybí ]"
+
+#: quickfix.c:362
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: %%%c Nepodporovaná formátová specifikace ve formátovacím øetìzci"
+
+#: quickfix.c:380
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: Nepøípustné %%%c v prefixu formátovacího øetìzce"
+
+#: quickfix.c:388
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: Nepøípustné %%%c ve formátovacím øetìzci"
+
+#: quickfix.c:414
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' neobsahuje ¾ádný vzorek"
+
+#: quickfix.c:520
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Chybìjící nebo prázdný název adresáøe"
+
+#: quickfix.c:931
+msgid "No more items"
+msgstr "®ádné dal¹í polo¾ky"
+
+#: quickfix.c:1152
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d/%d)%s%s: "
+
+#: quickfix.c:1154
+msgid " (line deleted)"
+msgstr " (øádek smazán)"
+
+#: quickfix.c:1360
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Konec quickfix seznamu"
+
+#: quickfix.c:1369
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Zaèátek quickfix seznamu"
+
+#: quickfix.c:1381
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "seznam chyb %d z %d; poèet chyb: %d"
+
+#: quickfix.c:1842
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: Nelze ulo¾it, je nastavena volba 'buftype'"
+
+#: regexp.c:801
+msgid "E339: Pattern too long"
+msgstr "E339: Vzor je pøíli¹ dlouhý"
+
+#: regexp.c:1315
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: %s*"
+
+#: regexp.c:1318
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: %s%c"
+
+#: regexp.c:1467
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c nic není"
+
+#: regexp.c:2469
+#, c-format
+msgid "Syntax error in %s{...}"
+msgstr "Chyba syntaxe v %s{...}"
+
+#: regexp.c:2716
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Zachyceno pøeteèení zásobníku: pøíli¹ slo¾itý regulární výraz?"
+
+#: regexp.c:2851
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: vzorek zpùsobil pøeteèení zásobníku"
+
+#: regexp.c:3087
+msgid "External submatches:\n"
+msgstr "Vnìj¹í podøazené shody:\n"
+
+#: screen.c:2054
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "poèet øádkù v záhybu: %3ld"
+
+#: screen.c:7426
+msgid " VREPLACE"
+msgstr " VREPLACE"
+
+#: screen.c:7430
+msgid " REPLACE"
+msgstr " REPLACE"
+
+#: screen.c:7435
+msgid " REVERSE"
+msgstr " REVERSE"
+
+#: screen.c:7437
+msgid " INSERT"
+msgstr " INSERT"
+
+#: screen.c:7440
+msgid " (insert)"
+msgstr " (insert)"
+
+#: screen.c:7442
+msgid " (replace)"
+msgstr " (replace)"
+
+#: screen.c:7444
+msgid " (vreplace)"
+msgstr " (vreplace)"
+
+#: screen.c:7447
+msgid " Hebrew"
+msgstr " hebrejský"
+
+#: screen.c:7455
+msgid " (lang)"
+msgstr " (lang)"
+
+#: screen.c:7458
+msgid " (paste)"
+msgstr " (paste)"
+
+#: screen.c:7464
+msgid " SELECT"
+msgstr " SHODY"
+
+#: screen.c:7466
+msgid " VISUAL"
+msgstr " VIZUÁLNÍ"
+
+#: screen.c:7468
+msgid " BLOCK"
+msgstr " BLOK"
+
+#: screen.c:7470
+msgid " LINE"
+msgstr " ØÁDEK"
+
+#: screen.c:7483 screen.c:7537
+msgid "recording"
+msgstr "nahrávám"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "hledání dosáhlo zaèátku, pokraèování od konce"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "hledání dosáhlo konce, pokraèování od zaèátku"
+
+#: search.c:440
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Nepøípustný hledaný øetìzec: %s"
+
+#: search.c:747
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: hledaný dosáhlo zaèátku bez nalezení %s"
+
+#: search.c:749
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: hledaný dosáhlo konce bez nalezení %s"
+
+#: search.c:1107
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: Po ';' oèekávám '?' nebo '/'"
+
+#: search.c:3476
+msgid " (includes previously listed match)"
+msgstr " (vèetnì ji¾ vypsaných shod)"
+
+#. cursor at status line
+#: search.c:3496
+msgid "--- Included files "
+msgstr "--- Vlo¾ené soubory"
+
+#: search.c:3498
+msgid "not found "
+msgstr " nenalezeny"
+
+#: search.c:3499
+msgid "in path ---\n"
+msgstr "v cestì ---\n"
+
+#: search.c:3538
+msgid " (Already listed)"
+msgstr " (Ji¾ vypsáno)"
+
+#: search.c:3540
+msgid " NOT FOUND"
+msgstr " NENALEZENY"
+
+#: search.c:3592
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Prohledávám vlo¾ené soubory: %s"
+
+#: search.c:3810
+msgid "E387: Match is on current line"
+msgstr "E387: Shoda je na aktuálním øádku"
+
+#: search.c:3950
+msgid "All included files were found"
+msgstr "V¹echny vlo¾ené soubory byly nalezeny"
+
+#: search.c:3952
+msgid "No included files"
+msgstr "®ádné vlo¾ené soubory"
+
+#: search.c:3968
+msgid "E388: Couldn't find definition"
+msgstr "E388: Nelze nalézt definici"
+
+#: search.c:3970
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Nelze nalézt vzorek"
+
+#: syntax.c:2991
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: nepøípustný argument: %s"
+
+#: syntax.c:3168
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: Syntaktická sestava %s neexistuje"
+
+#: syntax.c:3332
+msgid "No Syntax items defined for this buffer"
+msgstr "Pro tento buffer nejsou definovány ¾ádné pøedmìty syntaxe"
+
+#: syntax.c:3340
+msgid "syncing on C-style comments"
+msgstr "synchronizuji komentáøe v C stylu"
+
+#: syntax.c:3348
+msgid "no syncing"
+msgstr "¾ádná synchronizace"
+
+#: syntax.c:3351
+msgid "syncing starts "
+msgstr "synchronizace zaèíná "
+
+#: syntax.c:3353 syntax.c:3422
+msgid " lines before top line"
+msgstr " øádkù pøed zaèátkem"
+
+#: syntax.c:3357
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Polo¾ky synchronizace syntaxe ---"
+
+#: syntax.c:3360
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"synchronizuji pøedmìty"
+
+#: syntax.c:3365
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Pøedmìty syntaxe ---"
+
+#: syntax.c:3388
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: Syntaktická sestava %s neexistuje"
+
+#: syntax.c:3412
+msgid "minimal "
+msgstr "minimální "
+
+#: syntax.c:3419
+msgid "maximal "
+msgstr "maximální "
+
+#: syntax.c:4047
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: group[t]here nesmí být na tomto místì"
+
+#: syntax.c:4071
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: Pro %s chybí polo¾ka regionu"
+
+#: syntax.c:4099
+msgid "E395: contains argument not accepted here"
+msgstr "E395: obsahuje argumenty, které zde nejsou povoleny"
+
+#: syntax.c:4110
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: obsahuje argumenty, které zde nejsou povoleny"
+
+#: syntax.c:4188
+msgid "E397: Filename required"
+msgstr "E397: Vy¾adován název souboru"
+
+#: syntax.c:4524
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Chybí '=': %s"
+
+#: syntax.c:4680
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Pøíli¹ málo argumentù: oblast syntaxe %s"
+
+#: syntax.c:5011
+msgid "E400: No cluster specified"
+msgstr "E400: Nebyla zadána ¾ádná sestava"
+
+#: syntax.c:5048
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Oddìlovaè vzorku %s nenalezen"
+
+#: syntax.c:5123
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Chyba za vzorkem %s"
+
+#: syntax.c:5205
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: synchronizace syntaxe: vzorek pokraèování øádkù zadán dvakrát"
+
+#: syntax.c:5262
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: nepøípustný argument: %s"
+
+#: syntax.c:5312
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Chybí rovnítko: %s"
+
+#: syntax.c:5318
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Prázdný argument: %s"
+
+#: syntax.c:5345
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s zde není povoleno"
+
+#: syntax.c:5352
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s musí být první v 'contains' seznamu"
+
+#: syntax.c:5422
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Neznámá název skupiny: %s"
+
+#: syntax.c:5645
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: chybný podøazený pøíkaz :syntax : %s "
+
+#: syntax.c:6024
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: skupina zvýraznìní %s nebyla nalezena"
+
+#: syntax.c:6048
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Pøíli¹ málo argumentù: \":highlight link %s\""
+
+#: syntax.c:6055
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: Pøíli¹ mnoho argumentù: \":highlight link %s\""
+
+#: syntax.c:6075
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: skupina je nastavena, odkaz na zvýrazòovací skupinu ignorován"
+
+#: syntax.c:6204
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: neèekané rovnítko : %s"
+
+#: syntax.c:6240
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: chybné rovnítko: %s"
+
+#: syntax.c:6262
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: chybí argument: %s"
+
+#: syntax.c:6299
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: nepøípustná hodnota: %s"
+
+#: syntax.c:6418
+msgid "E419: FG color unknown"
+msgstr "E419: barva popøedí není známá"
+
+#: syntax.c:6429
+msgid "E420: BG color unknown"
+msgstr "E420: barva popøedí není známá"
+
+#: syntax.c:6484
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: název èi èíslo barvy %s nebylo rozpoznáno"
+
+#: syntax.c:6688
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: terminálový kód %s je pøíli¹ dlouhý"
+
+#: syntax.c:6735
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: nepøípustný argument: %s"
+
+#: syntax.c:7264
+msgid "E424: Too many different highlighting attributes in use"
+msgstr ""
+"E424: Je pou¾íváno pøíli¹ velké mno¾ství odli¹ných zvýrazòovacích atributù"
+
+#: tag.c:90
+msgid "at bottom of tag stack"
+msgstr "konec seznamu tagù"
+
+#: tag.c:91
+msgid "at top of tag stack"
+msgstr "zaèátek seznamu tagù"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Pøed první vyhovující tag nelze pøeskoèit"
+
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: tag %s nenalezen"
+
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr " # pri typ tag"
+
+#: tag.c:548
+msgid "file\n"
+msgstr "soubor\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Zadejte èíslo (<CR> pro ukonèení): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: Vyhovuje pouze jeden tag"
+
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Za poslední vyhovující tag nelze pøeskoèit"
+
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Soubor \"%s\" neexistuje"
+
+#. Give an indication of the number of matching tags
+#: tag.c:780
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "tag %d z celkového poètu %d%s"
+
+#: tag.c:783
+msgid " or more"
+msgstr " nebo více"
+
+#: tag.c:785
+msgid " Using tag with different case!"
+msgstr " Pou¾ívám tag s písmeny jiné velikosti!"
+
+#: tag.c:828
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: \"%s\" neexistuje"
+
+#. Highlight title
+#: tag.c:897
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # CÍL tag START øádek v souboru/textu"
+
+#: tag.c:1144
+msgid "Linear tag search"
+msgstr "Lineární hledání tagu"
+
+#: tag.c:1146
+msgid "Binary tag search"
+msgstr "Binární hledání tagu"
+
+#: tag.c:1172
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Prohledávám soubor tagù %s"
+
+#: tag.c:1356
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Soubor tagù %s byl oøezán\n"
+
+#: tag.c:1847
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Chyba formátu v souboru tagù \"%s\""
+
+#: tag.c:1851
+#, c-format
+msgid "Before byte %ld"
+msgstr "Pøed bajtem %ld"
+
+#: tag.c:1872
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Obsah soubor tagù %s není seøazen"
+
+#. never opened any tags file
+#: tag.c:1911
+msgid "E433: No tags file"
+msgstr "E433: ®ádný soubor tagù"
+
+#: tag.c:2583
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Nelze najít vzorek tagù"
+
+#: tag.c:2594
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Tag nelze nalézt, pouze hádám!"
+
+#: term.c:1723
+msgid "' not known. Available builtin terminals are:"
+msgstr "' není znám. Dostupné vestavìné terminály:"
+
+#: term.c:1747
+msgid "defaulting to '"
+msgstr "implicitní terminál '"
+
+#: term.c:2100
+msgid "Cannot open termcap file"
+msgstr "Nelze otevøít termcap"
+
+#: term.c:2103
+msgid "Terminal entry not found in terminfo"
+msgstr "Terminfo neobsahuje polo¾ku pro tento terminál"
+
+#: term.c:2105
+msgid "Terminal entry not found in termcap"
+msgstr "Termcap neobsahuje polo¾ku pro tento terminál"
+
+#: term.c:2264
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Termcap neobsahuje polo¾ku pro \"%s\""
+
+#: term.c:2738
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: Terminál musí mít schopnost \"cm\""
+
+#. Highlight title
+#: term.c:4878
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Klávesy terminálu ---"
+
+#: ui.c:240
+msgid "new shell started\n"
+msgstr "spu¹tìn nový shell\n"
+
+#: ui.c:1705
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: chyba pøi ètení vstupu, konèím...\n"
+
+#. must display the prompt
+#: undo.c:351
+msgid "No undo possible; continue anyway"
+msgstr "odstranìní zmìn není mo¾né; chcete pøesto pokraèovat"
+
+#: undo.c:506
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: èísla øádkù jsou chybná"
+
+#: undo.c:675
+msgid "1 change"
+msgstr "poèet zmìn: 1"
+
+#: undo.c:677
+#, c-format
+msgid "%ld changes"
+msgstr "poèet zmìn: %ld"
+
+#: undo.c:721
+msgid "E439: undo list corrupt"
+msgstr "E439: záznam o zmìnách po¹kozen"
+
+#: undo.c:751
+msgid "E440: undo line missing"
+msgstr "E440: chybí undo øádek"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:655
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"16/32 bitová GUI verze pro MS Windows"
+
+#: version.c:657
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"32 bitová GUI verze pro MS Windows"
+
+#: version.c:660
+msgid " in Win32s mode"
+msgstr " ve Win32s re¾imu"
+
+#: version.c:662
+msgid " with OLE support"
+msgstr " s OLE podporou"
+
+#: version.c:665
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"32 bitová verze pro MS Windows konzolu"
+
+#: version.c:669
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"16 bitová verze pro MS Windows"
+
+#: version.c:673
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 bitová verze pro MS Windows"
+
+#: version.c:675
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 bitová MS-DOS verze"
+
+#: version.c:681
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) verze"
+
+#: version.c:683
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X verze"
+
+#: version.c:686
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS verze"
+
+#: version.c:691
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS verze"
+
+#: version.c:701
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Pou¾ité záplaty: "
+
+#: version.c:728
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"pøelo¾il "
+
+#: version.c:731
+msgid "by "
+msgstr " "
+
+#: version.c:743
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"maximální verze"
+
+#: version.c:746
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"velká verze "
+
+#: version.c:749
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"normální verze"
+
+#: version.c:752
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"malá verze "
+
+#: version.c:754
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"minimální verze"
+
+#: version.c:760
+msgid "without GUI."
+msgstr "bez grafického rozhraní"
+
+#: version.c:764
+msgid "with GTK-GNOME GUI."
+msgstr "s rozhraním GTK-GNOME"
+
+#: version.c:766
+msgid "with GTK GUI."
+msgstr "s rozhraním GTK"
+
+#: version.c:770
+msgid "with X11-Motif GUI."
+msgstr "s rozhraním X11-Motif"
+
+#: version.c:773
+msgid "with X11-Athena GUI."
+msgstr "S rozhraním X11-Athena"
+
+#: version.c:776
+msgid "with BeOS GUI."
+msgstr "s rozhraním BeOS"
+
+#: version.c:779
+msgid "with Photon GUI."
+msgstr "s rozhraním Photon"
+
+#: version.c:782
+msgid "with GUI."
+msgstr "s grafickým rozhraním"
+
+#: version.c:785
+msgid "with Carbon GUI."
+msgstr "s grafickým rozhraním Carbon"
+
+#: version.c:788
+msgid "with Cocoa GUI."
+msgstr "s grafickým rozhraním Cocoa"
+
+#: version.c:791
+msgid "with (classic) GUI."
+msgstr "s (clasickým) grafickým rozhraním"
+
+#: version.c:802
+msgid " Features included (+) or not (-):\n"
+msgstr " Vlastnosti zahrnuté (+) a nezahrnuté (-):\n"
+
+#: version.c:814
+msgid " system vimrc file: \""
+msgstr " systémový vimrc soubor: \""
+
+#: version.c:819
+msgid " user vimrc file: \""
+msgstr " u¾ivatelský vimrc soubor: \""
+
+#: version.c:824
+msgid " 2nd user vimrc file: \""
+msgstr " druhý u¾ivatelský vimrc soubor: \""
+
+#: version.c:829
+msgid " 3rd user vimrc file: \""
+msgstr " tøetí u¾ivatelský vimrc soubor: \""
+
+#: version.c:834
+msgid " user exrc file: \""
+msgstr " u¾ivatelský exrc soubor: \""
+
+#: version.c:839
+msgid " 2nd user exrc file: \""
+msgstr " druhý u¾ivatelský exrc soubor: \""
+
+#: version.c:845
+msgid " system gvimrc file: \""
+msgstr " systémový gvimrc soubor: \""
+
+#: version.c:849
+msgid " user gvimrc file: \""
+msgstr " u¾ivatelský gvimrc soubor: \""
+
+#: version.c:853
+msgid "2nd user gvimrc file: \""
+msgstr "druhý u¾ivatelský gvimrc soubor: \""
+
+#: version.c:858
+msgid "3rd user gvimrc file: \""
+msgstr "tøetí u¾ivatelský gvimrc soubor: \""
+
+#: version.c:865
+msgid " system menu file: \""
+msgstr " systémový soubor s menu: \""
+
+#: version.c:873
+msgid " fall-back for $VIM: \""
+msgstr " implicitní hodnota $VIM:\""
+
+#: version.c:879
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " implicitní hodnota $VIMRUNTIME: \""
+
+#: version.c:883
+msgid "Compilation: "
+msgstr "Pøeklad: "
+
+#: version.c:889
+msgid "Compiler: "
+msgstr "Pøekladaè: "
+
+#: version.c:894
+msgid "Linking: "
+msgstr "Linkuji: "
+
+#: version.c:899
+msgid " DEBUG BUILD"
+msgstr " PODPORA LADÌNÍ"
+
+#: version.c:934
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved"
+
+#: version.c:936
+msgid "version "
+msgstr "verze "
+
+#: version.c:937
+msgid "by Bram Moolenaar et al."
+msgstr "Autor: Bram Moolenaar a dal¹í"
+
+#: version.c:938
+msgid "Vim is open source and freely distributable"
+msgstr "Vim je volnì ¹iøitelný program s otevøeným zdrojovým kódem"
+
+#: version.c:940
+msgid "Help poor children in Uganda!"
+msgstr "Pomozte chudým dìtem v Ugandì!"
+
+#: version.c:941
+msgid "type :help iccf<Enter> for information "
+msgstr "podrobnìj¹í informace získáte pomocí :help iccf<Enter>"
+
+#: version.c:943
+msgid "type :q<Enter> to exit "
+msgstr "zadejte :q<Enter> pro ukonèení programu"
+
+#: version.c:944
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "zadejte :help<Enter> èi <F1> pro nápovìdu"
+
+#: version.c:945
+msgid "type :help version6<Enter> for version info"
+msgstr "zadejte :help version6<Enter> pro informace o verzi 6"
+
+#: version.c:948
+msgid "Running in Vi compatible mode"
+msgstr "Bì¾ím v re¾imu kompatibility s Vi"
+
+#: version.c:949
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "zadejte :set nocp<Enter> pro implicitní nastavení Vim"
+
+#: version.c:950
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "podrobnìj¹í informace získáte pomocí :help cp-default<Enter>"
+
+#: version.c:990
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "VAROVÁNÍ: detekovány Windows 95/98/ME"
+
+#: version.c:993
+msgid "type :help windows95<Enter> for info on this"
+msgstr "zadejte :help windows95<Enter> pro podrobnìj¹í informace"
+
+#: window.c:201
+msgid "E441: There is no preview window"
+msgstr "E441: Není ¾ádné preview okno není"
+
+#: window.c:568
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: Okno nelze rozdìlit zároveò topleft a botright"
+
+#: window.c:1327
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Nelze rotovat, pokud je jiné okno rozdìleno"
+
+#: window.c:1810
+msgid "E444: Cannot close last window"
+msgstr "E444: Poslední okno nelze uzavøít"
+
+#: window.c:2474
+msgid "Already only one window"
+msgstr "Ji¾ existuje pouze jedno okno"
+
+#: window.c:2521
+msgid "E445: Other window contains changes"
+msgstr "E445: Jiné okno obsahuje zmìny"
+
+#: window.c:4341
+msgid "E446: No file name under cursor"
+msgstr "E446: Pod kurzorem se nenachází název souboru"
+
+#: window.c:4460
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Soubor \"%s\" nelze v path nalézt"
+
+#: ../GvimExt/gvimext.cpp:586
+msgid "Edit with &multiple Vims"
+msgstr "Editace &multiple Vimy"
+
+#: ../GvimExt/gvimext.cpp:592
+msgid "Edit with single &Vim"
+msgstr "Editace jedním $Vim -em"
+
+#: ../GvimExt/gvimext.cpp:604
+msgid "Edit with &Vim"
+msgstr "Editace &Vim -em"
+
+#: ../GvimExt/gvimext.cpp:628
+msgid "Edit with existing Vim - &"
+msgstr "Editace existujícím Vimem - &"
+
+#: ../GvimExt/gvimext.cpp:752
+msgid "Edits the selected file(s) with Vim"
+msgstr "Editace vybraných souborù Vimem"
+
+#: ../GvimExt/gvimext.cpp:891 ../GvimExt/gvimext.cpp:969
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "Chyba pøi spou¹tìní procesu: Zkontrolujte zdali je gvim v $PATH!"
+
+#: ../GvimExt/gvimext.cpp:892 ../GvimExt/gvimext.cpp:906
+#: ../GvimExt/gvimext.cpp:970
+msgid "gvimext.dll error"
+msgstr "chyba gvimext.dll"
+
+#: ../GvimExt/gvimext.cpp:905
+msgid "Path length too long!"
+msgstr "Název (v path) je pøíli¹ dlouhý"
+
+#: globals.h:878
+msgid "--No lines in buffer--"
+msgstr "--Buffer neobsahuje ¾ádný øádek--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1019
+msgid "Command aborted"
+msgstr "Pøíkaz pøeru¹en"
+
+#: globals.h:1020
+msgid "Argument required"
+msgstr "Je vy¾adován argument"
+
+#: globals.h:1021
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: po \\ by mìl následovat /. ? nebo &"
+
+#: globals.h:1023
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr ""
+"E11: Chyba v oknì pøíkazové øádky; <CR> pro spu¹t¹ní, CTRL-C pro ukonèení"
+
+#: globals.h:1025
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Pøíkaz není z exrc/vimrc v aktuálním adresáøi èi pøi hledání tagu "
+"povolen."
+
+#: globals.h:1026
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Soubor existuje (pou¾ijte ! pro vynucení)"
+
+#: globals.h:1027
+msgid "Command failed"
+msgstr "Pøíkaz selhal"
+
+#: globals.h:1028
+msgid "Internal error"
+msgstr "Vnitøní chyba"
+
+#: globals.h:1029
+msgid "Interrupted"
+msgstr "Pøeru¹eno"
+
+#: globals.h:1030
+msgid "E14: Invalid address"
+msgstr "E14: Chybná adresa"
+
+#: globals.h:1031
+msgid "Invalid argument"
+msgstr "Chybný argument"
+
+#: globals.h:1032
+#, c-format
+msgid "Invalid argument: %s"
+msgstr "Chybný argument: %s"
+
+#: globals.h:1034
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Chybný výraz: %s"
+
+#: globals.h:1036
+msgid "E16: Invalid range"
+msgstr "E16: Chybný rozsah"
+
+#: globals.h:1037
+msgid "Invalid command"
+msgstr "Chybný pøíkaz"
+
+#: globals.h:1039
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" je adresáøem"
+
+#: globals.h:1042
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Neoèekávané znaky pøed '='"
+
+#: globals.h:1044
+msgid "E19: Mark has invalid line number"
+msgstr "E19: Znaèka má chybné èíslo øádku"
+
+#: globals.h:1045
+msgid "E20: Mark not set"
+msgstr "E20: není nastavena"
+
+#: globals.h:1046
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Nelze mìnit, je nastavena volba 'modifiable'"
+
+#: globals.h:1047
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Skript vnoøen pøíli¹ hluboko"
+
+#: globals.h:1048
+msgid "E23: No alternate file"
+msgstr "E23: ®ádný alternativní soubor"
+
+#: globals.h:1049
+msgid "E24: No such abbreviation"
+msgstr "E24: Taková zkratka neexistuje"
+
+#: globals.h:1050
+msgid "No ! allowed"
+msgstr "! není povoleno"
+
+#: globals.h:1052
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: Nelze pou¾ít GUI: nebylo zapnuto pøi pøekladu programu"
+
+#: globals.h:1055
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr ""
+"E26: nelze pou¾ít hebrejský re¾im: nebyl zapnut pøi pøekladu programu\n"
+
+#: globals.h:1058
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: Nelze pou¾ít farsi re¾im: nebyl zapnut pøi pøekladu programu\n"
+
+#: globals.h:1061
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Skupina zvýraznìní %s neexistuje"
+
+#: globals.h:1063
+msgid "E29: No inserted text yet"
+msgstr "E29: Zatím není ¾ádný vlo¾ený text"
+
+#: globals.h:1064
+msgid "E30: No previous command line"
+msgstr "E30: ®ádná pøedchozí pøíkazová øádka"
+
+#: globals.h:1065
+msgid "E31: No such mapping"
+msgstr "E31: ®ádné takové mapování"
+
+#: globals.h:1066
+msgid "No match"
+msgstr "®ádná shoda"
+
+#: globals.h:1067
+#, c-format
+msgid "No match: %s"
+msgstr "®ádná shoda: %s"
+
+#: globals.h:1068
+msgid "E32: No file name"
+msgstr "E32: ®ádný název souboru"
+
+#: globals.h:1069
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: ¾ádný pøedchozí regulární výraz"
+
+#: globals.h:1070
+msgid "E34: No previous command"
+msgstr "E34: ®ádný pøedchozí pøíkaz"
+
+#: globals.h:1071
+msgid "E35: No previous regular expression"
+msgstr "E35: ¾ádný pøedchozí regulární výraz"
+
+#: globals.h:1072
+msgid "No range allowed"
+msgstr "Rozsah není povolen"
+
+#: globals.h:1074
+msgid "E36: Not enough room"
+msgstr "E36: Nedostatek místa"
+
+#: globals.h:1076
+#, c-format
+msgid "Can't create file %s"
+msgstr "Nelze vytvoøit soubor %s"
+
+#: globals.h:1077
+msgid "Can't get temp file name"
+msgstr "Nelze získat název doèasného souboru"
+
+#: globals.h:1078
+#, c-format
+msgid "Can't open file %s"
+msgstr "Nelze otevøít soubor %s"
+
+#: globals.h:1079
+#, c-format
+msgid "Can't read file %s"
+msgstr "Nelze èíst soubor %s"
+
+#: globals.h:1080
+msgid "E37: No write since last change (use ! to override)"
+msgstr "E37: Neulo¾ené zmìny (pou¾ijte ! pro vynucení)"
+
+#: globals.h:1081
+msgid "E38: Null argument"
+msgstr "E38: Nulový argument"
+
+#: globals.h:1083
+msgid "E39: Number expected"
+msgstr "E39: Oèekáváno èíslo"
+
+#: globals.h:1086
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Nelze otevøít chybový soubor %s"
+
+#: globals.h:1089
+msgid "E41: Out of memory!"
+msgstr "E41: Nedostatek pamìti!"
+
+#: globals.h:1092
+msgid "Pattern not found"
+msgstr "Vzor nenalezen"
+
+#: globals.h:1094
+#, c-format
+msgid "Pattern not found: %s"
+msgstr "Vzor nenalezen: %s"
+
+#: globals.h:1095
+msgid "Argument must be positive"
+msgstr "Argument musí být kladný"
+
+#: globals.h:1097
+msgid "E42: No Errors"
+msgstr "E42: ®ádné chyby"
+
+#: globals.h:1099
+msgid "E43: Damaged match string"
+msgstr "E43: Po¹kozený øetìzec pro vyhledávání"
+
+#: globals.h:1100
+msgid "E44: Corrupted regexp program"
+msgstr "E44: po¹kozený regexp program"
+
+#: globals.h:1101
+msgid "E45: 'readonly' option is set (use ! to override)"
+msgstr "E45: 'nastavena volba 'readonly' (pou¾ijte ! pro vynucení)"
+
+#: globals.h:1103
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Nelze nastavit pouze_pro_ètení promìnnou \"%s\""
+
+#: globals.h:1106
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Chyba pøi ètení chybového souboru"
+
+#: globals.h:1109
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: Není v bezpeènostní schránce povoleno"
+
+#: globals.h:1111
+msgid "E49: Invalid scroll size"
+msgstr "E49: Chybná hodnota volby 'scroll'"
+
+#: globals.h:1112
+msgid "E91: 'shell' option is empty"
+msgstr "E91: volba 'shell' je prázdná"
+
+#: globals.h:1113
+msgid "E72: Close error on swap file"
+msgstr "E72: Chyba pøi uzavírání odkládacího souboru"
+
+#: globals.h:1114
+msgid "E73: tag stack empty"
+msgstr "E73: seznam tagù je prázdný"
+
+#: globals.h:1115
+msgid "E74: Command too complex"
+msgstr "E74: Pøíkaz je pøíli¹ slo¾itý"
+
+#: globals.h:1116
+msgid "E75: Name too long"
+msgstr "E75: Název je pøíli¹ dlouhý"
+
+#: globals.h:1117
+msgid "E76: Too many ["
+msgstr "E76: pøíli¹ mnoho ["
+
+#: globals.h:1118
+msgid "E77: Too many file names"
+msgstr "E77: Pøíli¹ mnoho názvù souborù"
+
+#: globals.h:1119
+msgid "Trailing characters"
+msgstr "Nadbyteèné znaky na konci"
+
+#: globals.h:1120
+msgid "E78: Unknown mark"
+msgstr "E78: Neznámá znaèka"
+
+#: globals.h:1121
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Nelze expandovat ¾olíkové znaky"
+
+#: globals.h:1122
+msgid "E80: Error while writing"
+msgstr "E80: Chyba pøi ukládání"
+
+#: globals.h:1123
+msgid "Zero count"
+msgstr "Nulový poèet"
+
+#: globals.h:1125
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: Pou¾ití <SID> mimo kontext skriptu"
diff --git a/src/po/de.po b/src/po/de.po
new file mode 100644
index 000000000..84d262816
--- /dev/null
+++ b/src/po/de.po
@@ -0,0 +1,6091 @@
+# German Translation for Vim vim:set foldmethod=marker:
+#
+# Do ":help uganda" in Vim to read copying and usage conditions.
+# Do ":help credits" in Vim to see a list of people who contributed.
+#
+# Previous-Translator(s): Johannes Zellner <johannes@zellner.org>
+#
+# thoughts (Gedanken)
+#
+# - mark : Markierung oder Marke?
+# - ambigous: Mehrdeutig, Nicht-eindeutig
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim(deutsch)\n"
+"POT-Creation-Date: 2002-04-20 18:15+0200\n"
+"PO-Revision-Date: 2004-05-12 20:49+0200\n"
+"Last-Translator: Gerfried Fuchs <alfie@ist.org>\n"
+"Language-Team: German <de@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO_8859-1\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Kein Puffer kann alloziert werden; beenden..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: Puffer kann nicht alloziert werden; benutze einen anderen..."
+
+#: buffer.c:706
+msgid "No buffers were unloaded"
+msgstr "Keine Puffer wurden ausgeladen"
+
+#: buffer.c:708
+msgid "No buffers were deleted"
+msgstr "Keine Puffer wurden gelöscht"
+
+#: buffer.c:710
+msgid "No buffers were wiped out"
+msgstr "Keine Puffer wurden gelöscht"
+
+#: buffer.c:718
+msgid "1 buffer unloaded"
+msgstr "1 Puffer ausgeladen"
+
+#: buffer.c:720
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "%d Puffer ausgeladen"
+
+#: buffer.c:725
+msgid "1 buffer deleted"
+msgstr "1 Puffer gelöscht"
+
+#: buffer.c:727
+#, c-format
+msgid "%d buffers deleted"
+msgstr "%d Puffer gelöscht"
+
+#: buffer.c:732
+msgid "1 buffer wiped out"
+msgstr "1 Puffer gelöscht"
+
+#: buffer.c:734
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "%d Puffer gelöscht"
+
+#: buffer.c:791
+msgid "E84: No modified buffer found"
+msgstr "E84: Es wurde keine veränderten Puffer gefunden"
+
+#. back where we started, didn't find anything.
+#: buffer.c:830
+msgid "E85: There is no listed buffer"
+msgstr "E85: Es gibt keine angezeigte Puffer"
+
+#: buffer.c:842
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: Kann nicht zum Puffer %ld wechseln"
+
+#: buffer.c:845
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Kann nicht über den letzten Puffer hinaus gehen"
+
+#: buffer.c:847
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Kann nicht vor den ersten Puffer gehen"
+
+#: buffer.c:871
+#, c-format
+msgid "E89: No write since last change for buffer %ld (use ! to override)"
+msgstr ""
+"E89: Puffer %ld wurde seit der letzten Änderung nicht geschrieben (erzwinge "
+"mit !)"
+
+#: buffer.c:887
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: letzter Puffer kann nicht heraus-geladen werden"
+
+#: buffer.c:1342
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Achtung: Überlauf der Liste der Dateinamen"
+
+#: buffer.c:1508
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: kein Puffer %ld gefunden"
+
+#: buffer.c:1734
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Mehr als eine Möglichkeit für %s"
+
+#: buffer.c:1736
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: Kein Puffer passt zu %s"
+
+#: buffer.c:2141 ex_docmd.c:6089
+#, c-format
+msgid "line %ld"
+msgstr "Zeile %ld"
+
+#: buffer.c:2224
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Ein Puffer mit diesem Namen existiert bereits"
+
+#: buffer.c:2517
+msgid " [Modified]"
+msgstr " [Verändert]"
+
+#: buffer.c:2522
+msgid "[Not edited]"
+msgstr "[Nicht editiert]"
+
+#: buffer.c:2527
+msgid "[New file]"
+msgstr "[Neue Datei]"
+
+#: buffer.c:2528
+msgid "[Read errors]"
+msgstr "[Lese-Fehler]"
+
+#: buffer.c:2530 fileio.c:1777
+msgid "[readonly]"
+msgstr "[nur Lesen]"
+
+#: buffer.c:2545
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 Zeile --%d%%--"
+
+#: buffer.c:2547
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld Zeilen --%d%%--"
+
+#: buffer.c:2554
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "Zeile %ld von %ld --%d%%-- Spalte "
+
+#: buffer.c:2642
+msgid "[No file]"
+msgstr "[Keine Datei]"
+
+#. must be a help buffer
+#: buffer.c:2682
+msgid "help"
+msgstr "[Hilfe]"
+
+#: buffer.c:3193 screen.c:4754
+msgid "[help]"
+msgstr "[Hilfe]"
+
+#: buffer.c:3225 screen.c:4760
+msgid "[Preview]"
+msgstr "[Voransicht]"
+
+#: buffer.c:3431
+msgid "All"
+msgstr "Alles"
+
+# Ende sounds better than "Unten"
+#: buffer.c:3431
+msgid "Bot"
+msgstr "Ende"
+
+# Anfang sounds better than "Oben"
+#: buffer.c:3433
+msgid "Top"
+msgstr "Anfang"
+
+#: buffer.c:4169
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# Liste der Puffer:\n"
+
+#: buffer.c:4202
+msgid "[Error List]"
+msgstr "[Fehlerliste]"
+
+#: buffer.c:4215 memline.c:1513
+msgid "[No File]"
+msgstr "[Keine Datei]"
+
+#: buffer.c:4435
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Optionen ---"
+
+#: buffer.c:4445
+#, c-format
+msgid "Signs for %s:"
+msgstr "Vorzeichen für %s:"
+
+#: buffer.c:4451
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " Zeile=%ld id=%d Name=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: \"diff\" ist für mehr als %ld Puffer nicht möglich"
+
+#: diff.c:648
+msgid "E97: Cannot create diffs"
+msgstr "E97: Kann keine \"diffs\" erstellen"
+
+#: diff.c:747
+msgid "Patch file"
+msgstr "Patch-Datei"
+
+#: diff.c:991
+msgid "E98: Cannot read diff output"
+msgstr "E98: \"diff\"-Ausgabe kann nicht gelesen werden"
+
+#: diff.c:1732
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Aktueller Puffer ist nicht im \"diff\"-Modus"
+
+#: diff.c:1744
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: Kein weiterer Puffer ist im \"diff\"-Modus"
+
+#: diff.c:1752
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: mehrdeutig: Mehr als zwei Puffer im \"diff\"-Modus"
+
+#: diff.c:1775
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Puffer \"%s\" kann nicht gefunden werden"
+
+#: diff.c:1781
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Puffer \"%s\" ist nicht im \"diff\"-Modus"
+
+#: digraph.c:2172
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: 'Escape' ist in einem Digraphen nicht erlaubt"
+
+#: digraph.c:2344
+msgid "Keymap file not found"
+msgstr "\"Keymap\"-Datei nicht gefunden"
+
+#: digraph.c:2371
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: :loadkeymap außerhalb einer eingelesenen Datei"
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " Stichwort-Ergänzung (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " ^X-Modus (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " lokale Stichwort-Ergänzung (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " Zeilen-Ergänzung (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " Datei-Namens-Ergänzung (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " Tag-Ergänzung (^]/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " Pfad-Muster-Ergänzung (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " Definitions-Ergänzung (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " Wörterbuch-Ergänzung (^K/^N/^P) "
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Thesaurus-Ergänzung (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " Kommando-Zeilen-Ergänzung (^V/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Stieß an das Ende eines Absatzes"
+
+#: edit.c:907
+msgid "'thesaurus' option is empty"
+msgstr "Die Option 'thesaurus' ist leer"
+
+#: edit.c:1083
+msgid "'dictionary' option is empty"
+msgstr "Die Option 'dictionary' ist leer"
+
+#: edit.c:2007
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Durchsuchen des Wörterbuchs: %s"
+
+#: edit.c:2198
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (Einfügen) Scrollen (^E/^Y)"
+
+#: edit.c:2200
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (Ersetzen) Scrollen (^E/^Y)"
+
+#: edit.c:2512
+#, c-format
+msgid "Scanning: %s"
+msgstr "Durchsuche: %s"
+
+#: edit.c:2547
+msgid "Scanning tags."
+msgstr "Durchsuchen von Tags."
+
+#: edit.c:3207
+msgid " Adding"
+msgstr " Hinzufügung der"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3256
+msgid "-- Searching..."
+msgstr "-- Suche..."
+
+#: edit.c:3312
+msgid "Back at original"
+msgstr "Zurück am Ursprung"
+
+#: edit.c:3317
+msgid "Word from other line"
+msgstr "Wort aus anderer Zeile"
+
+#: edit.c:3322
+msgid "The only match"
+msgstr "Einziger Treffer"
+
+#: edit.c:3381
+#, c-format
+msgid "match %d of %d"
+msgstr "Treffer %d von %d"
+
+#: edit.c:3384
+#, c-format
+msgid "match %d"
+msgstr "Treffer %d"
+
+#: eval.c:698
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Unbekannte Variable: \"%s\""
+
+#: eval.c:977
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Fehlende Klammern: %s"
+
+#: eval.c:1057 eval.c:1073
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Keine solche Variable: \"%s\""
+
+#: eval.c:1315
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: fehlender ':' nach '?'"
+
+#: eval.c:1929
+msgid "E110: Missing ')'"
+msgstr "E110: fehlende ')'"
+
+#: eval.c:1979
+msgid "E111: Missing ']'"
+msgstr "E111: fehlende ']'"
+
+#: eval.c:2054
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Options-Bezeichnung fehlt: %s"
+
+#: eval.c:2072
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Unbekannte Option: %s"
+
+#: eval.c:2134
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Fehlendes Anführungszeichen: %s"
+
+#: eval.c:2251
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Fehlendes Anführungszeichen: %s"
+
+#: eval.c:2569
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Unzulässige Argumente für Funktion %s"
+
+#: eval.c:2570
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Unbekannte Funktion: %s"
+
+#: eval.c:2571
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: Zu viele Argumente für Funktion: %s"
+
+#: eval.c:2572
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Nicht genug Argumente für Funktion: %s"
+
+#: eval.c:2573
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: <SID> wurde nicht in einer Skript-Umgebung benutzt: %s"
+
+#: eval.c:3172 gui.c:3990
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:3678
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld Zeilen: "
+
+#: eval.c:4794
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&OK\n"
+"&Abbrechen"
+
+#: eval.c:5626
+msgid "E240: No connection to Vim server"
+msgstr "E240: Keine Verbindung zum Vim-Server"
+
+#: eval.c:5716
+msgid "E277: Unable to read a server reply"
+msgstr "E277: Server-Antwort kann nicht gelesen werden"
+
+#: eval.c:5741
+msgid "E258: Unable to send to client"
+msgstr "E258: Kann nicht zum Client senden"
+
+#: eval.c:5786
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Kann nicht zu %s senden"
+
+#: eval.c:5884
+msgid "(Invalid)"
+msgstr "(ungültig)"
+
+#: eval.c:6895
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Variable nicht definiert: %s"
+
+#: eval.c:7593
+#, c-format
+msgid "E122: Function %s already exists, use ! to replace"
+msgstr "E122: Die Funktion %s existiert bereits; ersetze sie mit !"
+
+#: eval.c:7635
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Funktion nicht definiert: %s"
+
+#: eval.c:7648
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: fehlendes '(': %s"
+
+#: eval.c:7680
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Unzulässiges Argument: %s"
+
+#: eval.c:7766
+msgid "E126: Missing :endfunction"
+msgstr "E126: fehlendes :endfunction"
+
+#: eval.c:7845
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Funktion %s kann nicht umdefiniert werden: sie ist in Verwendung"
+
+#: eval.c:7903
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: Funktions-Name muss mit Großbuchstaben beginnen: %s"
+
+#: eval.c:7909
+msgid "E129: Function name required"
+msgstr "E129: Funktions-Name wird verlangt"
+
+#: eval.c:8002
+msgid "function "
+msgstr "Funktion "
+
+#: eval.c:8117
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Funktion nicht definiert: %s"
+
+#: eval.c:8122
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Funktion %s kann nicht gelöscht werden: sie ist in Verwendung"
+
+#: eval.c:8169
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: Funktionsaufruf-Tiefe überschreitet 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:8220
+#, c-format
+msgid "calling %s"
+msgstr "rufe %s auf"
+
+#. always scroll up, don't overwrite
+#: eval.c:8245 ex_cmds2.c:1988
+#, c-format
+msgid "continuing in %s"
+msgstr "weiter in %s"
+
+#: eval.c:8299
+msgid "E133: :return not inside a function"
+msgstr "E133: :return außerhalb einer Funktion"
+
+#: eval.c:8377
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s lieferte #%ld zurück"
+
+#: eval.c:8380
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s lieferte \"%s\" zurück"
+
+#: eval.c:8521
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# globale Variablen:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Hex %02x, Oktal %03o"
+
+#: ex_cmds.c:428
+msgid "E134: Move lines into themselves"
+msgstr "E134: Verschiebe Zeilen in sich selbst"
+
+#: ex_cmds.c:497
+msgid "1 line moved"
+msgstr "1 Zeile verschoben"
+
+#: ex_cmds.c:499
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld Zeilen verschoben"
+
+#: ex_cmds.c:890
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld Zeilen gefiltert"
+
+#: ex_cmds.c:918
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *Filter*-Auto-Kommandos dürfen den aktuellen Puffer nicht ändern"
+
+#: ex_cmds.c:1003
+msgid "[No write since last change]\n"
+msgstr "[Kein Schreiben seit der letzten Änderung]\n"
+
+#: ex_cmds.c:1248
+#, c-format
+msgid "viminfo: %s in line: "
+msgstr "viminfo: %s in Zeile: "
+
+#: ex_cmds.c:1253
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: Zu viele Fehler; überspringe Rest der Datei"
+
+#: ex_cmds.c:1282
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Lesen der viminfo-Datei \"%s\"%s%s%s"
+
+#: ex_cmds.c:1283
+msgid " info"
+msgstr " Information"
+
+#: ex_cmds.c:1284
+msgid " marks"
+msgstr "Markierungen"
+
+#: ex_cmds.c:1285
+msgid " FAILED"
+msgstr " DURCHGEFALLEN"
+
+#: ex_cmds.c:1376
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Viminfo-Datei ist nicht schreibbar: %s"
+
+#: ex_cmds.c:1501
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Schreiben in die viminfo-Datei %s ist nicht möglich!"
+
+#: ex_cmds.c:1509
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Schreiben der viminfo-Datei \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1610
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Diese viminfo-Datei wurde von Vim %s generiert.\n"
+
+#: ex_cmds.c:1612
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Sie können sie verändern, wenn Sie vorsichtig vorgehen!\n"
+"\n"
+
+#: ex_cmds.c:1614
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Wert von 'encoding', als diese Datei geschrieben wurde\n"
+
+#: ex_cmds.c:1713
+msgid "Illegal starting char"
+msgstr "Unzulässiges Zeichen am Anfang"
+
+#: ex_cmds.c:2053 ex_cmds.c:2310 ex_cmds2.c:602
+msgid "Save As"
+msgstr "Schreibe Als"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2096
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Datei ist in einem anderen Puffer geladen"
+
+#: ex_cmds.c:2130
+msgid "Write partial file?"
+msgstr "Partielle Datei schreiben?"
+
+#: ex_cmds.c:2137
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Verwenden Sie ! zum Schreiben von partiellen Puffern"
+
+#: ex_cmds.c:2244
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Überschreibe existierende Datei \"%.*s\"?"
+
+# Cursor: Schreibmarke Positionsmarke
+#: ex_cmds.c:2315
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: Kein Dateiname für Puffer %ld"
+
+#: ex_cmds.c:2353
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr ""
+"E142: Datei wurde nicht geschrieben: Schreiben ist durch die 'write'-Option "
+"ausgeschaltet"
+
+#: ex_cmds.c:2373
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"'readonly'-Option ist für \"%.*s\" gesetzt.\n"
+"Möchten Sie trotzdem schreiben?"
+
+#: ex_cmds.c:2538
+msgid "Edit File"
+msgstr "Editiere Datei"
+
+#: ex_cmds.c:3061
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Auto-Kommandos löschten unerwartet neuen Puffer %s"
+
+#: ex_cmds.c:3193
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: nicht numerisches Argument für :z"
+
+#: ex_cmds.c:3278
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: Shell Befehle sind in rvim nicht erlaubt"
+
+#: ex_cmds.c:3385
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Reguläre Ausdrücke können nicht durch Buchstaben begrenzt werden"
+
+#: ex_cmds.c:3727
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "ersetze durch %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4092
+msgid "(Interrupted) "
+msgstr "(Unterbrochen) "
+
+#: ex_cmds.c:4096
+msgid "1 substitution"
+msgstr "eine Ersetzung"
+
+#: ex_cmds.c:4098
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld Ersetzungen"
+
+#: ex_cmds.c:4101
+msgid " on 1 line"
+msgstr " auf einer Zeile"
+
+#: ex_cmds.c:4103
+#, c-format
+msgid " on %ld lines"
+msgstr " auf %ld Zeilen"
+
+#: ex_cmds.c:4154
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: Kann :global nicht rekursiv ausführen"
+
+#: ex_cmds.c:4189
+msgid "E148: Regular expression missing from global"
+msgstr "E148: Regulärer Ausdruck fehlt in global"
+
+#: ex_cmds.c:4238
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Muster in jeder Zeile gefunden: %s"
+
+#: ex_cmds.c:4319
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Letzte ersetzte Zeichenkette:\n"
+"$"
+
+#: ex_cmds.c:4421
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Schade, keine Hilfe für %s"
+
+#: ex_cmds.c:4455
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Hilfe-Datei \"%s\" nicht gefunden"
+
+#: ex_cmds.c:4917
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: kein Verzeichnis: %s"
+
+#: ex_cmds.c:4945
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: %s kann nicht zum Schreiben geöffnet werden"
+
+#: ex_cmds.c:4959
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: %s kann nicht zum Lesen geöffnet werden"
+
+#: ex_cmds.c:5038
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: Tag \"%s\" ist mehrmals in der Datei %s"
+
+#: ex_cmds.c:5139
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Unbekannter \"sign\"-Befehl: %s"
+
+#: ex_cmds.c:5159
+msgid "E156: Missing sign name"
+msgstr "E156: Name des Zeichens fehlt"
+
+#: ex_cmds.c:5205
+msgid "E255: Too many signs defined"
+msgstr "E255: Zu viele Zeichen definiert"
+
+#: ex_cmds.c:5247
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Ungültiger Text für ein Zeichen: %s"
+
+#: ex_cmds.c:5271 ex_cmds.c:5457
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Unbekanntes Zeichen: %s"
+
+#: ex_cmds.c:5317
+msgid "E159: Missing sign number"
+msgstr "E159: Fehlende Zeichen-Nummer"
+
+#: ex_cmds.c:5397
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: ungültige Puffer-Nummer: %s"
+
+#: ex_cmds.c:5436
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: ungültige Zeichen-ID: %ld"
+
+#: ex_cmds.c:5607
+msgid "[Deleted]"
+msgstr "[gelöscht]"
+
+#: ex_cmds2.c:70
+msgid "Entering Debug mode. Type \"cont\" to leave."
+msgstr "Debug-Modus. Geben Sie \"cont\" zum Verlassen ein."
+
+#: ex_cmds2.c:74 ex_docmd.c:771
+#, c-format
+msgid "line %ld: %s"
+msgstr "Zeile %ld: %s"
+
+#: ex_cmds2.c:76
+#, c-format
+msgid "cmd: %s"
+msgstr "Befehl: %s"
+
+#: ex_cmds2.c:224
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Haltepunkt in \"%s%s\" Zeile %ld"
+
+#: ex_cmds2.c:388
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Haltepunkt nicht gefunden: %s"
+
+#: ex_cmds2.c:414
+msgid "No breakpoints defined"
+msgstr "Keine Haltepunkte definiert"
+
+#: ex_cmds2.c:419
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s Zeile %ld"
+
+#: ex_cmds2.c:625
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Änderungen in \"%.*s\" speichern?"
+
+#: ex_cmds2.c:627 ex_docmd.c:8673
+msgid "Untitled"
+msgstr "Unbenannt"
+
+#: ex_cmds2.c:763
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Puffer \"%s\" wurde seit der letzten Änderung nicht geschrieben"
+
+#: ex_cmds2.c:832
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr ""
+"Achtung: Unerwarteter Eintritt in einen andren Puffer (überprüfen Siedie "
+"Autocommands)"
+
+#: ex_cmds2.c:1208
+msgid "E163: There is only one file to edit"
+msgstr "E163: Es gibt nur eine Datei zum Editieren"
+
+#: ex_cmds2.c:1210
+msgid "E164: Cannot go before first file"
+msgstr "E164: Kann nicht über die erste Datei hinausgehen"
+
+#: ex_cmds2.c:1212
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Kann nicht über die letzte Datei hinausgehen"
+
+#: ex_cmds2.c:1634
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Suche nach \"%s\" in \"%s\""
+
+#: ex_cmds2.c:1656
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Suche nach \"%s\""
+
+#: ex_cmds2.c:1680
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "im 'runtimepath' nicht gefunden: \"%s\""
+
+#: ex_cmds2.c:1714
+msgid "Source Vim script"
+msgstr "Vim Skript"
+
+#: ex_cmds2.c:1832
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "Kann kein Verzeichnis einlesen: \"%s\""
+
+#: ex_cmds2.c:1862
+#, c-format
+msgid "could not source \"%s\""
+msgstr "\"%s\" konnte nicht gelesen werden"
+
+#: ex_cmds2.c:1864
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "Zeile %ld: \"%s\" konnte nicht gelesen werden"
+
+#: ex_cmds2.c:1878
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "lese \"%s\""
+
+#: ex_cmds2.c:1880
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "Zeile %ld: lese \"%s\""
+
+#: ex_cmds2.c:1986
+#, c-format
+msgid "finished sourcing %s"
+msgstr "Lesen von %s beendet"
+
+#: ex_cmds2.c:2287
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Achtung: Falscher Zeilentrenner, vielleicht fehlt ein ^M"
+
+#: ex_cmds2.c:2336
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :scriptencoding außerhalb einer eingelesenen Datei"
+
+#: ex_cmds2.c:2369
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish außerhalb einer eingelesenen Datei"
+
+#: ex_cmds2.c:2838
+msgid "No text to be printed"
+msgstr "Kein Text zum Drucken"
+
+#: ex_cmds2.c:2916
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "Drucke Seite %d (%d%%)"
+
+#: ex_cmds2.c:2925
+#, c-format
+msgid " Copy %d of %d"
+msgstr " Kopie %d von %d"
+
+#: ex_cmds2.c:2977
+#, c-format
+msgid "Printed: %s"
+msgstr "Gedruckt: %s"
+
+#: ex_cmds2.c:2984
+msgid "Printing aborted"
+msgstr "Drucken abgebrochen"
+
+#: ex_cmds2.c:3367
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Fehler beim Schreiben der PostScript Ausgabe-Datei"
+
+#: ex_cmds2.c:4042
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: PostScript Ausgabe-Datei kann nicht geöffnet werden"
+
+#: ex_cmds2.c:4080
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Datei \"%s\" kann nicht geöffnet werden"
+
+#: ex_cmds2.c:4091
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: PostScript 'resource'-Datei \"%s\" kann nicht gelesen werden"
+
+#: ex_cmds2.c:4289
+msgid "Sending to printer..."
+msgstr "Schicke zum Drucker..."
+
+#: ex_cmds2.c:4293
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: Druck der PostScript-Datei schlug fehl"
+
+#: ex_cmds2.c:4295
+msgid "Print job sent."
+msgstr "Druckauftrag abgeschickt"
+
+#: ex_cmds2.c:4691
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Momentane %sSprache: \"%s\""
+
+#: ex_cmds2.c:4702
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Sprache kann nicht auf \"%s\" gesetzt werden"
+
+#: ex_docmd.c:490
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr ""
+"Ex-Modus. Geben Sie \"visual\" ein, um zum Normal-Modus zurückzukehren."
+
+#. must be at EOF
+#: ex_docmd.c:526
+msgid "At end-of-file"
+msgstr "Am Dateiende"
+
+#: ex_docmd.c:601
+msgid "E169: Command too recursive"
+msgstr "E169: Befehl zu rekursiv"
+
+#: ex_docmd.c:911
+msgid "E170: Missing :endwhile"
+msgstr "E170: fehlendes :endwhile"
+
+#: ex_docmd.c:913
+msgid "E171: Missing :endif"
+msgstr "E171: fehlendes :endif"
+
+#: ex_docmd.c:923
+msgid "End of sourced file"
+msgstr "Ende der eingelesenen Datei"
+
+#: ex_docmd.c:924
+msgid "End of function"
+msgstr "Ende der Funktion"
+
+#: ex_docmd.c:1344
+msgid "Ambiguous use of user-defined command"
+msgstr "Nicht-eindeutige Verwendung eines benutzerdefinierten Befehls"
+
+#: ex_docmd.c:1358
+msgid "Not an editor command"
+msgstr "Kein Editor-Befehl"
+
+#: ex_docmd.c:1441
+msgid "Don't panic!"
+msgstr "Nur keine Panik!"
+
+#: ex_docmd.c:1460
+msgid "Backwards range given"
+msgstr "Bereichsgrenzen rückwärts"
+
+#: ex_docmd.c:1469
+msgid "Backwards range given, OK to swap"
+msgstr "Bereichsgrenzen rückwärts; vertauschen"
+
+#: ex_docmd.c:1580
+msgid "Use w or w>>"
+msgstr "Verwenden Sie w oder w>>"
+
+#: ex_docmd.c:3097
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Der Befehl ist in dieser Version nicht implementiert"
+
+#: ex_docmd.c:3267
+msgid "E172: Only one file name allowed"
+msgstr "E172: Nur ein Dateiname erlaubt"
+
+#: ex_docmd.c:3823
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "%d weitere Dateien zum Editieren. Trotzdem beenden?"
+
+#: ex_docmd.c:3830
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: %ld weitere Dateien zum Editieren"
+
+#: ex_docmd.c:3924
+msgid "E174: Command already exists: use ! to redefine"
+msgstr "E174: Befehl existiert bereits: verwenden Sie ! zum Umdefinierten"
+
+#: ex_docmd.c:4029
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Name Args Bereich Fertig Definition"
+
+#: ex_docmd.c:4118
+msgid "No user-defined commands found"
+msgstr "Keine vom Benutzer definierten Befehle gefunden"
+
+#: ex_docmd.c:4149
+msgid "E175: No attribute specified"
+msgstr "E175: Kein Attribut angegeben"
+
+#: ex_docmd.c:4201
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Falsche Anzahl von Argumenten"
+
+#: ex_docmd.c:4216
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: Zähler kann nicht zweimal angegeben werden"
+
+#: ex_docmd.c:4226
+msgid "E178: Invalid default value for count"
+msgstr "E178: Ungültige Voreinstellung für den Zähler"
+
+#: ex_docmd.c:4254
+msgid "E179: argument required for complete"
+msgstr "E179: Argument wird zur Vervollständigung benötigt"
+
+#: ex_docmd.c:4273
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Ungültiger Vervollständigungs-Wert: %s"
+
+#: ex_docmd.c:4281
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Ungültiges Attribut: %s"
+
+#: ex_docmd.c:4322
+msgid "E182: Invalid command name"
+msgstr "E182: Ungültiger Befehls-Name"
+
+#: ex_docmd.c:4337
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: Benutzerdefinierte Befehle müssen mit Großbuchstaben beginnen"
+
+#: ex_docmd.c:4406
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: Unbekannter benutzerdefinierter Befehl: %s"
+
+#: ex_docmd.c:4857
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Zeile %s kann nicht gefunden werden"
+
+#: ex_docmd.c:4865
+msgid "Greetings, Vim user!"
+msgstr "Herzliche Grüße, Vim Benutzer!"
+
+#: ex_docmd.c:5569
+msgid "Edit File in new window"
+msgstr "Editiere Datei in einem neuen Fenster"
+
+#: ex_docmd.c:5839
+msgid "No swap file"
+msgstr "Keine Auslagerungs-Datei"
+
+#: ex_docmd.c:5943
+msgid "Append File"
+msgstr "Füge Datei an"
+
+#: ex_docmd.c:6002
+msgid "E186: No previous directory"
+msgstr "E186: Kein vorheriges Verzeichnis"
+
+#: ex_docmd.c:6079
+msgid "E187: Unknown"
+msgstr "E187: Unbekannt"
+
+#: ex_docmd.c:6197
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Fenster-Position: X %d, Y %d"
+
+#: ex_docmd.c:6202
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr ""
+"E188: die Fenster-Position kann für dieses Terminal nicht bestimmt werden"
+
+#: ex_docmd.c:6474
+msgid "Save Redirection"
+msgstr "Umleitung Speichern"
+
+#: ex_docmd.c:6623
+msgid "Save View"
+msgstr "Ansichten Speichern"
+
+#: ex_docmd.c:6624
+msgid "Save Session"
+msgstr "Sitzung Speichern"
+
+#: ex_docmd.c:6626
+msgid "Save Setup"
+msgstr "Einstellungen Speichern"
+
+#: ex_docmd.c:6775
+#, c-format
+msgid "E189: \"%s\" exists (use ! to override)"
+msgstr "E189: \"%s\" existiert (erzwinge durch !)"
+
+#: ex_docmd.c:6780
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: \"%s\" kann nicht zum Schreiben geöffnet werden"
+
+#. set mark
+#: ex_docmd.c:6804
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr ""
+"E191: Argument muss ein Buchstabe oder vorwärts/rückwärts-Anführungszeichen "
+"sein"
+
+#: ex_docmd.c:6847
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Rekursive Verwendung von :normal zu tief"
+
+#: ex_docmd.c:7208
+msgid ":if nesting too deep"
+msgstr ":if Schachtelung zu tief"
+
+#: ex_docmd.c:7243
+msgid ":endif without :if"
+msgstr ":endif ohne :if"
+
+#: ex_docmd.c:7263
+msgid ":else without :if"
+msgstr ":else ohne :if"
+
+#: ex_docmd.c:7265
+msgid ":elseif without :if"
+msgstr ":elseif ohne :if"
+
+#: ex_docmd.c:7317
+msgid ":while nesting too deep"
+msgstr ":while Schachtelung zu tief"
+
+#: ex_docmd.c:7363
+msgid ":continue without :while"
+msgstr ":continue ohne :while"
+
+#: ex_docmd.c:7390
+msgid ":break without :while"
+msgstr ":break ohne :while"
+
+#: ex_docmd.c:7413 ex_docmd.c:7418
+msgid ":endwhile without :while"
+msgstr ":endwhile ohne :while"
+
+#: ex_docmd.c:7439
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction außerhalb einer Funktion"
+
+#: ex_docmd.c:7619
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: Kein anderer Dateiname zur Ersetzung mit '#'"
+
+#: ex_docmd.c:7650
+msgid "no autocommand file name to substitute for \"<afile>\""
+msgstr "kein Auto-Kommando-Datei-Name zur Ersetzung mit \"<afile>\""
+
+#: ex_docmd.c:7658
+msgid "no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "keine Auto-Kommando-Puffer-Nummer zur Ersetzung mit \"<abuf>\""
+
+#: ex_docmd.c:7669
+msgid "no autocommand match name to substitute for \"<amatch>\""
+msgstr ""
+"kein passender Name eines Auto-Kommandos zur Ersetzung mit \"<amatch>\""
+
+#: ex_docmd.c:7679
+msgid "no :source file name to substitute for \"<sfile>\""
+msgstr "kein :source Dateiname zur Ersetzung mit \"<sfile>\""
+
+#: ex_docmd.c:7720
+#, no-c-format
+msgid "Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "Leerer Dateiname für '%' oder '#', funktioniert nur mit \":p:h\""
+
+#: ex_docmd.c:7722
+msgid "Evaluates to an empty string"
+msgstr "Ergibt eine leere Zeichenkette"
+
+#: ex_docmd.c:8655
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: viminfo kann nicht zum Lesen geöffnet werden"
+
+#: ex_docmd.c:8828
+msgid "E196: No digraphs in this version"
+msgstr "ed9) Keine Digraphen in dieser Version"
+
+#: ex_getln.c:2833
+msgid "tagname"
+msgstr "Tag-Name"
+
+#: ex_getln.c:2836
+msgid " kind file\n"
+msgstr " verwandte Datei\n"
+
+#: ex_getln.c:4049
+msgid "'history' option is zero"
+msgstr "'history'-Option ist Null"
+
+#: ex_getln.c:4289
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s Geschichte (neueste bis älteste):\n"
+
+#: ex_getln.c:4290
+msgid "Command Line"
+msgstr "Befehlszeile"
+
+#: ex_getln.c:4291
+msgid "Search String"
+msgstr "Suchausdruck"
+
+#: ex_getln.c:4292
+msgid "Expression"
+msgstr "Ausdruck"
+
+#: ex_getln.c:4293
+msgid "Input Line"
+msgstr "Eingabe-Zeile"
+
+#: ex_getln.c:4323
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar über die Länge des Befehls hinaus"
+
+#: ex_getln.c:4491
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: aktives Fenster oder Puffer gelöscht"
+
+#: fileio.c:351
+msgid "Illegal file name"
+msgstr "unzulässiger Dateiname"
+
+#: fileio.c:375 fileio.c:500 fileio.c:2516 fileio.c:2554
+msgid "is a directory"
+msgstr "ist ein Verzeichnis"
+
+#: fileio.c:377
+msgid "is not a file"
+msgstr "ist keine Datei"
+
+#: fileio.c:522 fileio.c:3646
+msgid "[New File]"
+msgstr "[Neue Datei]"
+
+#: fileio.c:540
+msgid "[Permission Denied]"
+msgstr "[Keine Erlaubnis]"
+
+#: fileio.c:634
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre Auto-Kommandos haben die Datei unlesbar gemacht"
+
+#: fileio.c:636
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr ""
+"E201: *ReadPre Auto-Kommandos dürfen nicht den aktuellen Puffer wechseln"
+
+#: fileio.c:657
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: Lese von stdin...\n"
+
+#: fileio.c:663
+msgid "Reading from stdin..."
+msgstr "Lese von stdin..."
+
+#. Re-opening the original file failed!
+#: fileio.c:892
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: Datei wurde unlesbar durch Umwandlung"
+
+#: fileio.c:1755
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:1762
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:1769
+msgid "[socket]"
+msgstr "[socket]"
+
+#: fileio.c:1777
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:1787
+msgid "[CR missing]"
+msgstr "[CR fehlt]"
+
+#: fileio.c:1792
+msgid "[NL found]"
+msgstr "[NL gefunden]"
+
+#: fileio.c:1797
+msgid "[long lines split]"
+msgstr "[lange Zeilen geteilt]"
+
+#: fileio.c:1803 fileio.c:3630
+msgid "[NOT converted]"
+msgstr "[NICHT konvertiert]"
+
+#: fileio.c:1808 fileio.c:3635
+msgid "[converted]"
+msgstr "[konvertiert]"
+
+#: fileio.c:1815 fileio.c:3660
+msgid "[crypted]"
+msgstr "[verschlüsselt]"
+
+#: fileio.c:1822
+msgid "[CONVERSION ERROR]"
+msgstr "[UMWANDLUNGS-FEHLER]"
+
+#: fileio.c:1829
+msgid "[READ ERRORS]"
+msgstr "[LESE-FEHLER]"
+
+#: fileio.c:2036
+msgid "Can't find temp file for conversion"
+msgstr "temporäre Datei kann nicht zum Umwandeln geöffnet werden"
+
+#: fileio.c:2043
+msgid "Conversion with 'charconvert' failed"
+msgstr "Fehler bei der Umwandlung mit 'charconvert'"
+
+#: fileio.c:2046
+msgid "can't read output of 'charconvert'"
+msgstr "Ausgabe von 'charconvert' kann nicht gelesen werden"
+
+#: fileio.c:2432
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr ""
+"E203: Auto-Kommandos haben den zu schreibenden Puffer gelöscht oder heraus "
+"geladen"
+
+#: fileio.c:2455
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr ""
+"E204: Auto-Kommandos haben die Anzahl der Zeilen in unerwarteter Weise "
+"verändert"
+
+#: fileio.c:2521 fileio.c:2538
+msgid "is not a file or writable device"
+msgstr "ist keine Datei oder beschreibbares Device"
+
+#: fileio.c:2584
+msgid "is read-only (use ! to override)"
+msgstr "ist Schreibgeschützt (erzwinge durch !)"
+
+#: fileio.c:2886
+msgid "Can't write to backup file (use ! to override)"
+msgstr "Sicherungs-Datei kann nicht geschrieben werden (erzwinge mit !)"
+
+#: fileio.c:2898
+msgid "Close error for backup file (use ! to override)"
+msgstr "Fehler beim Schließen der Sicherungs-Datei (erzwinge mit !)"
+
+#: fileio.c:2900
+msgid "Can't read file for backup (use ! to override)"
+msgstr "Datei zum Backup kann nicht gelesen werden (erzwinge mit !)"
+
+#: fileio.c:2916
+msgid "Cannot create backup file (use ! to override)"
+msgstr "Backup-Datei kann nicht angelegt werden (erzwinge mit !)"
+
+#: fileio.c:3018
+msgid "Can't make backup file (use ! to override)"
+msgstr "Backup-Datei kann nicht erstellt werden (erzwinge mit !)"
+
+#: fileio.c:3080
+msgid "The resource fork will be lost (use ! to override)"
+msgstr "Der Resourcefork geht verloren (erzwinge mit !)"
+
+#: fileio.c:3169
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: temporäre Datei kann nicht zum Schreiben geöffnet werden"
+
+#: fileio.c:3187
+msgid "E213: Cannot convert (use ! to write without conversion)"
+msgstr "E213: Fehler bei der Umwandlung (schreibe ohne Umwandlung mit !)"
+
+#: fileio.c:3222
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Gelinkte Datei kann nicht zum Schreiben geöffnet werden"
+
+#: fileio.c:3226
+msgid "E212: Can't open file for writing"
+msgstr "E212: Datei kann nicht zum Schreiben geöffnet werden"
+
+#: fileio.c:3475
+msgid "Close failed"
+msgstr "Fehler beim Schließen"
+
+#: fileio.c:3546
+msgid "write error, conversion failed"
+msgstr "Schreib-Fehler, Umwandlung schlug fehl"
+
+#: fileio.c:3552
+msgid "write error (file system full?)"
+msgstr "Schreibfehler (Dateisystem voll?)"
+
+#: fileio.c:3625
+msgid " CONVERSION ERROR"
+msgstr "KONVERTIERUNGS-FEHLER"
+
+#: fileio.c:3641
+msgid "[Device]"
+msgstr "[Ausgabegerät]"
+
+#: fileio.c:3646
+msgid "[New]"
+msgstr "[Neu]"
+
+#: fileio.c:3668
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:3668
+msgid " appended"
+msgstr " angefügt"
+
+#: fileio.c:3670
+msgid " [w]"
+msgstr " [w]"
+
+#: fileio.c:3670
+msgid " written"
+msgstr " geschrieben"
+
+#: fileio.c:3720
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: patchmode: Original-Datei kann nicht gespeichert werden"
+
+#: fileio.c:3742
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: leere Original-Datei kann nicht verändert werden"
+
+#: fileio.c:3757
+msgid "E207: Can't delete backup file"
+msgstr "E207: Backup-Datei kann nicht gelöscht werden"
+
+#: fileio.c:3809
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"ACHTUNG: Original-Datei kann verloren oder zerstört sein\n"
+
+#: fileio.c:3811
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "beende nicht den Editor bis die Datei erfolgreich geschrieben wurde!"
+
+#: fileio.c:3891
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:3891
+msgid "[dos format]"
+msgstr "[dos Format]"
+
+#: fileio.c:3898
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:3898
+msgid "[mac format]"
+msgstr "[mac Format]"
+
+#: fileio.c:3905
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:3905
+msgid "[unix format]"
+msgstr "[unix Format]"
+
+#: fileio.c:3932
+msgid "1 line, "
+msgstr "1 Zeile, "
+
+#: fileio.c:3934
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld Zeilen, "
+
+#: fileio.c:3937
+msgid "1 character"
+msgstr "1 Zeichen"
+
+#: fileio.c:3939
+#, c-format
+msgid "%ld characters"
+msgstr "%ld Zeichen"
+
+#: fileio.c:3949
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:3949
+msgid "[Incomplete last line]"
+msgstr "[Unvollständige letzte Zeile]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:3968
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "ACHTUNG: Die Datei wurde seit dem letzten Lesen geändert!!!"
+
+#: fileio.c:3970
+msgid "Do you really want to write to it"
+msgstr "Möchten Sie es wirklich schreiben"
+
+#: fileio.c:4933
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Fehler während des Schreibens nach \"%s\""
+
+#: fileio.c:4940
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Fehler beim Schließen von \"%s\""
+
+#: fileio.c:4943
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Fehler beim Lesen von \"%s\""
+
+#: fileio.c:5115
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: FileChangedShell Autokommando löschte Puffer"
+
+#: fileio.c:5123
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: Achtung: Datei \"%s\" ist nicht länger vorhanden"
+
+#: fileio.c:5136
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: Achtung: Datei \"%s\" wurde verändert und der Puffer wurde ebenfalls in "
+"Vim verändert"
+
+#: fileio.c:5139
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr ""
+"W11: Achtung: Datei \"%s\" wurde verändert, seit mit dem Editieren "
+"angefangen wurde"
+
+#: fileio.c:5141
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr ""
+"W11: Achtung: Mode der Datei \"%s\" wurde verändert seit mit dem Editieren "
+"angefangen wurde"
+
+#: fileio.c:5151
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr ""
+"W13: Achtug: Datei \"%s\" wurde erstellt, nachdem mit dem Editieren begonnen "
+"wurde"
+
+#: fileio.c:5168
+msgid "Warning"
+msgstr "Warnung"
+
+#: fileio.c:5169
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Lese Datei"
+
+#: fileio.c:5248
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: \"%s\" konnte nicht neu geladen werden"
+
+#: fileio.c:5779
+msgid "--Deleted--"
+msgstr "--gelöscht--"
+
+#. the group doesn't exist
+#: fileio.c:5939
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Keine solche Gruppe: \"%s\""
+
+#: fileio.c:6064
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Unzulässiges Zeichen nach *: %s"
+
+#: fileio.c:6075
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Kein derartiges Ereignis: %s"
+
+#. Highlight title
+#: fileio.c:6224
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Auto-Kommandos ---"
+
+#: fileio.c:6495
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Auto-Kommandos können nicht für ALL Ereignisse ausgeführt werden"
+
+#: fileio.c:6518
+msgid "No matching autocommands"
+msgstr "Keine passenden Auto-Kommandos"
+
+#: fileio.c:6790
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: Auto-Kommando Schachtelung zu tief"
+
+#: fileio.c:7077
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Auto-Kommandos für \"%s\""
+
+#: fileio.c:7085
+#, c-format
+msgid "Executing %s"
+msgstr "Ausführung von %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7153
+#, c-format
+msgid "autocommand %s"
+msgstr "Autokommando %s"
+
+#: fileio.c:7675
+msgid "E219: Missing {."
+msgstr "E219: Es fehlt ein {."
+
+#: fileio.c:7677
+msgid "E220: Missing }."
+msgstr "E220: Es fehlt ein }."
+
+#: fold.c:66
+msgid "No fold found"
+msgstr "Keine Faltung gefunden"
+
+#: fold.c:553
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr ""
+"E350: Faltung kann mit der eingestellten Methode 'foldmethod' nicht erzeugt "
+"werden"
+
+#: fold.c:555
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr ""
+"E351: Faltung kann mit der eingestellten Methode 'foldmethod' nicht entfernt "
+"werden"
+
+#: getchar.c:247
+msgid "E222: Add to read buffer"
+msgstr "E222: Zum Lese-Puffer Hinzufügen"
+
+#: getchar.c:2106
+msgid "E223: recursive mapping"
+msgstr "E223: rekursive Zuordnung"
+
+#: getchar.c:2948
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: Globale Abkürzung für %s existiert bereits"
+
+#: getchar.c:2951
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: Globale Zuordnung für %s existiert bereits"
+
+#: getchar.c:3078
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: Abkürzung für %s existiert bereits"
+
+#: getchar.c:3081
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: Zuordnung für %s existiert bereits"
+
+#: getchar.c:3145
+msgid "No abbreviation found"
+msgstr "Keine Abkürzung gefunden"
+
+#: getchar.c:3147
+msgid "No mapping found"
+msgstr "Keine Zuordnung gefunden"
+
+#: getchar.c:3992
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: Unzulässiger Modus"
+
+#: gui.c:203
+msgid "E229: Cannot start the GUI"
+msgstr "E229: GUI kann nicht gestartet werden"
+
+#: gui.c:328
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Kann nicht von \"%s\" lesen"
+
+#: gui.c:453
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: 'guifontwide' ungültig"
+
+#: gui.c:3704
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: Farbe für %s kann nicht alloziert werden"
+
+#: gui.c:3989
+msgid "Error"
+msgstr "Fehler"
+
+#: gui_at_fs.c:290
+msgid "<cannot open> "
+msgstr "<kann nicht öffnen>"
+
+#: gui_at_fs.c:1115
+#, c-format
+msgid "vim_SelFile: can't get font %s"
+msgstr "vim_SelFile: Schriftart %s kann nicht erhalten werden"
+
+#: gui_at_fs.c:2538
+msgid "vim_SelFile: can't return to current directory"
+msgstr "vim_SelFile: kann nicht zum laufenden Verzeichnis zurückkehren"
+
+#: gui_at_fs.c:2557
+msgid "Pathname:"
+msgstr "Pfad:"
+
+#: gui_at_fs.c:2563
+msgid "vim_SelFile: can't get current directory"
+msgstr "vim_SelFile: laufendes Verzeichnis kann nicht ermittelt werden"
+
+#: gui_at_fs.c:2571 gui_motif.c:1619
+msgid "OK"
+msgstr "OK"
+
+#. 'Cancel' button
+#: gui_at_fs.c:2571 gui_gtk.c:1740 gui_motif.c:1614 gui_motif.c:2835
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Scrollbar Widget: Geometrie des Bildchens kann nicht ermittelt werden"
+
+#: gui_athena.c:1956 gui_motif.c:1867
+msgid "Vim dialog"
+msgstr "VIM - Dialog..."
+
+#: gui_beval.c:68
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr ""
+"E232: BalloonEval kann nicht mit sowohl \"message\" und \"callback\" erzeugt "
+"werden"
+
+#: gui_gtk.c:1190
+msgid "Vim dialog..."
+msgstr "VIM - Dialog..."
+
+#: gui_gtk.c:1576 gui_motif.c:2754
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Suchen und Ersetzen..."
+
+#: gui_gtk.c:1581 gui_motif.c:2756
+msgid "VIM - Search..."
+msgstr "VIM - Suchen..."
+
+#: gui_gtk.c:1604 gui_motif.c:2874
+msgid "Find what:"
+msgstr "Wonach suchen:"
+
+#: gui_gtk.c:1622 gui_motif.c:2906
+msgid "Replace with:"
+msgstr "Ersetzen mit:"
+
+#. exact match only button
+#: gui_gtk.c:1654 gui_motif.c:3008
+msgid "Match exact word only"
+msgstr "Passend für einzelne Wörter"
+
+#: gui_gtk.c:1666 gui_motif.c:2976
+msgid "Direction"
+msgstr "Richtung"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:1678 gui_motif.c:2988
+msgid "Up"
+msgstr "Auf"
+
+#: gui_gtk.c:1682 gui_motif.c:2996
+msgid "Down"
+msgstr "Ab"
+
+#. 'Find Next' button
+#: gui_gtk.c:1704 gui_motif.c:2778
+msgid "Find Next"
+msgstr "Suche Nächstes"
+
+#. 'Replace' button
+#: gui_gtk.c:1721 gui_motif.c:2795
+msgid "Replace"
+msgstr "Ersetzen"
+
+#. 'Replace All' button
+#: gui_gtk.c:1730 gui_motif.c:2808
+msgid "Replace All"
+msgstr "Alle Ersetzen"
+
+#: gui_gtk_x11.c:1079 gui_x11.c:1199
+msgid "E233: cannot open display"
+msgstr "E233: Display kann nicht geöffnet werden"
+
+#: gui_gtk_x11.c:2494 gui_x11.c:1999
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Unbekannter Fontset: %s"
+
+#: gui_gtk_x11.c:2518
+msgid "Font Selection"
+msgstr "Auswahl der Schriftart"
+
+#: gui_gtk_x11.c:2764 gui_mac.c:2982 gui_w48.c:1197 gui_x11.c:1835
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Unbekannte Schriftart: %s"
+
+#: gui_gtk_x11.c:2775 gui_x11.c:1859
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: Schriftart \"%s\" hat keine feste Breite"
+
+#: gui_gtk_x11.c:3580 ui.c:1971
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "CUT_BUFFER0 anstatt der leeren Auswahl benutzt"
+
+#: gui_motif.c:1613 gui_motif.c:1616
+msgid "Filter"
+msgstr "Filter"
+
+#: gui_motif.c:1615
+msgid "Directories"
+msgstr "Verzeichnisse"
+
+#: gui_motif.c:1617
+msgid "Help"
+msgstr "Hilfe"
+
+#: gui_motif.c:1618
+msgid "Files"
+msgstr "Dateien"
+
+#: gui_motif.c:1620
+msgid "Selection"
+msgstr "Auswahl"
+
+#: gui_motif.c:2821
+msgid "Undo"
+msgstr "Rückgängig"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E235: Can't load Zap font '%s'"
+msgstr "E235: Zap-Schriftart '%s' kann nicht geladen werden"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E235: Can't use font %s"
+msgstr "E235: Schriftart %s kann nicht verwendet werden"
+
+#: gui_riscos.c:3269
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Sende Nachricht zum Beenden des Kind-Prozesses.\n"
+
+#: gui_w32.c:840
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr ""
+"E243: Argument wird nicht unterstützt: \"-%s\"; verwende die OLE Version."
+
+#. TODO: May be changed this message
+#: gui_w32.c:3448 gui_w32.c:3481 gui_x11.c:3252
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Fehler -- Daten für Debugger-Symbol konnten nicht gelesen werden"
+
+#: gui_w48.c:2081
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Suche Zeichenkette (benütze '\\\\' um ein '\\' zu finden)"
+
+#: gui_w48.c:2106
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Suche & Ersetze (use '\\\\' um ein '\\' zu finden)"
+
+#: gui_x11.c:1419
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: \"Colormap\"-Eintrag kann nicht alloziert werden, einige Farben "
+"können falsch sein"
+
+#: gui_x11.c:1989
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr ""
+"E250: Schriftarten für die folgenden Zeichensätze fehlen im \"fontset\" %s:"
+
+#: gui_x11.c:2032
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Fontset Name: %s"
+
+#: gui_x11.c:2033
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "Schriftart '%s' hat keine feste breite"
+
+#: gui_x11.c:2052
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Fontset Name: %s\n"
+
+#: gui_x11.c:2053
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Schriftart 0: %s\n"
+
+#: gui_x11.c:2054
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Schriftart 1: %s\n"
+
+#: gui_x11.c:2055
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "Schriftart%d ist nicht doppelt so breit wie Schriftart0\n"
+
+#: gui_x11.c:2056
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "Schriftart0 Breite: %ld\n"
+
+#: gui_x11.c:2057
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"Schriftart1 Breite: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: Hangul-Automat Fehler"
+
+#: if_cscope.c:26
+#, c-format
+msgid "Usage: cs[cope] %s"
+msgstr "Verwendung: cs[cope] %s"
+
+#: if_cscope.c:67
+msgid "Add a new database"
+msgstr "Datenbank hinzufügen"
+
+#: if_cscope.c:69
+msgid "Query for a pattern"
+msgstr "Muster suchen"
+
+#: if_cscope.c:71
+msgid "Show this message"
+msgstr "diese Nachricht anzeigen"
+
+#: if_cscope.c:73
+msgid "Kill a connection"
+msgstr "Verbindung abbrechen"
+
+#: if_cscope.c:75
+msgid "Reinit all connections"
+msgstr "Verbindungen reinitialisieren"
+
+#: if_cscope.c:77
+msgid "Show connections"
+msgstr "Verbindungen anzeigen"
+
+#: if_cscope.c:108
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Dieser cscope-Befehl unterstützt nicht Teilen des Fensters.\n"
+
+#: if_cscope.c:143
+msgid "Usage: cstag <ident>"
+msgstr "Verwendung: cstag <ident>"
+
+#: if_cscope.c:199
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: Tag nicht gefunden"
+
+#: if_cscope.c:407 if_cscope.c:451
+#, c-format
+msgid "stat(%s) error: %d"
+msgstr "stat(%s) Fehler: %d"
+
+#: if_cscope.c:460 if_cscope.c:467
+#, c-format
+msgid "Added cscope database %s"
+msgstr "csope Datenbank %s hinzugefügt"
+
+#: if_cscope.c:474
+#, c-format
+msgid "%s is not a directory or a valid cscope database"
+msgstr "%s ist kein Verzeichnis oder zulässige cscope Datenbank"
+
+#: if_cscope.c:557
+#, c-format
+msgid "error reading cscope connection %d"
+msgstr "Fehler beim Lesen aus der cscope Verbindung %d"
+
+#: if_cscope.c:633
+msgid "unknown cscope search type"
+msgstr "unbekannter cscope Suchtyp"
+
+#: if_cscope.c:680
+msgid "Could not create cscope pipes"
+msgstr "cscope Pipes konnten nicht angelegt werden"
+
+#: if_cscope.c:745
+msgid "cs_create_connection exec failed"
+msgstr "cs_create_connection exec misslang"
+
+#: if_cscope.c:755
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen von to_fp misslang"
+
+#: if_cscope.c:757
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen von fr_fp misslang"
+
+#: if_cscope.c:785
+msgid "no cscope connections"
+msgstr "keine Verbindungen zu cscope"
+
+#: if_cscope.c:855
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: keine Treffer gefunden für cscope Anfragen %s aus %s"
+
+#: if_cscope.c:899
+msgid "cscope commands:\n"
+msgstr "cscope Befehle:\n"
+
+#: if_cscope.c:902
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)\n"
+msgstr "%-5s: %-30s (Verwendung: %s)\n"
+
+#: if_cscope.c:970
+msgid "duplicate cscope database not added"
+msgstr "cscope Datenbank nicht doppelt hinzugefügt"
+
+#: if_cscope.c:981
+msgid "maximum number of cscope connections reached"
+msgstr "maximale Anzahl von cscope Verbindungen erreicht"
+
+#: if_cscope.c:1102
+msgid "E260: cscope connection not found"
+msgstr "E260: keine cscope Verbindung gefunden"
+
+#: if_cscope.c:1105
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: cscope Verbindung %s nicht gefunden"
+
+#: if_cscope.c:1141
+msgid "cscope connection closed"
+msgstr "cscope Verbindung geschlossen"
+
+#: if_cscope.c:1149
+#, c-format
+msgid "cscope connection %s closed\n"
+msgstr "cscope Verbindung %s geschlossen\n"
+
+#. should not reach here
+#: if_cscope.c:1290
+msgid "fatal error in cs_manage_matches"
+msgstr "fataler Fehler in cs_manage_matches"
+
+#: if_cscope.c:1341
+#, c-format
+msgid "E262: error reading cscope connection %d"
+msgstr "E262: Fehler beim Lesen aus der cscope Verbindung %d"
+
+#: if_cscope.c:1449
+msgid "couldn't malloc\n"
+msgstr "Fehler beim allozieren\n"
+
+#: if_cscope.c:1454
+#, c-format
+msgid "Cscope tag: %s\n"
+msgstr "Cscope Tag: %s\n"
+
+#: if_cscope.c:1458
+msgid " # line"
+msgstr " # Zeile"
+
+#: if_cscope.c:1460
+msgid "filename / context / line\n"
+msgstr "Dateiname / Kontext / Zeile\n"
+
+#: if_cscope.c:1718
+msgid "All cscope databases reset"
+msgstr "alle cscope Datenbanken zurückgesetzt"
+
+#: if_cscope.c:1785
+msgid "no cscope connections\n"
+msgstr "keine cscope-Verbindungen\n"
+
+#: if_cscope.c:1789
+msgid " # pid database name prepend path\n"
+msgstr " # pid Datenbank Name\t führender Pfad\n"
+
+#: if_cscope.c:1800
+#, c-format
+msgid "%2d %-5ld %-34s <none>\n"
+msgstr "%2d %-5ld %-34s <keine>\n"
+
+#: if_python.c:255 if_ruby.c:260 if_tcl.c:195 mbyte.c:2633 os_win32.c:269
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: Bibliothek %s konnte nicht geladen werden"
+
+#: if_python.c:267 if_ruby.c:272 if_tcl.c:206 mbyte.c:2649 os_win32.c:281
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: Bibliotheks-Funktion %s konnte nicht geladen werden"
+
+#: if_python.c:392
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: Dieser Befehl ist nicht verfügbar, die Python Bibliothek konnte nicht "
+"geladen werden"
+
+#: if_python.c:592
+msgid "can't delete OutputObject attributes"
+msgstr "OutputObject-Attribute können nicht gelöscht werden"
+
+#: if_python.c:599
+msgid "softspace must be an integer"
+msgstr "\"softspace\" muss eine ganze Zahl sein"
+
+#: if_python.c:607
+msgid "invalid attribute"
+msgstr "unzulässiges Attribut"
+
+#: if_python.c:646 if_python.c:660
+msgid "writelines() requires list of strings"
+msgstr "writelines() verlangt eine Liste von Zeichenfolgen"
+
+#: if_python.c:786
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: Fehler bei der Initialisierung von I/O Objekten"
+
+#: if_python.c:971 if_tcl.c:1403
+msgid "invalid expression"
+msgstr "ungültiger Ausdruck"
+
+#: if_python.c:985 if_tcl.c:1408
+msgid "expressions disabled at compile time"
+msgstr "Ausdrücke wurden zur Zeit des Übersetzens nicht zugelassen"
+
+#: if_python.c:998
+msgid "attempt to refer to deleted buffer"
+msgstr "Versuch, Bezug auf einen gelöschten Puffer zu nehmen"
+
+#: if_python.c:1013 if_python.c:1054 if_python.c:1118 if_tcl.c:1215
+msgid "line number out of range"
+msgstr "Zeilennummer außerhalb des zulässigen Bereichs"
+
+#: if_python.c:1251
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<Pufferobjekt (gelöscht) bei %8lX>"
+
+#: if_python.c:1342 if_tcl.c:837
+msgid "invalid mark name"
+msgstr "ungültiger Name einer Markierung"
+
+#: if_python.c:1617
+msgid "no such buffer"
+msgstr "kein solcher Puffer vorhanden"
+
+#: if_python.c:1705
+msgid "attempt to refer to deleted window"
+msgstr "Versuch, Bezug auf eine gelöschtes Fenster zu nehmen"
+
+#: if_python.c:1750
+msgid "readonly attribute"
+msgstr "nur-Lesen Attribut"
+
+#: if_python.c:1763
+msgid "cursor position outside buffer"
+msgstr "Cursor Position außerhalb des Puffers"
+
+#: if_python.c:1840
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<Fensterobjekt (gelöscht) bei %.8lX>"
+
+#: if_python.c:1852
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<Fensterobjekt (unbekannt) bei %.8lX>"
+
+#: if_python.c:1854
+#, c-format
+msgid "<window %d>"
+msgstr "<Fenster %d>"
+
+#: if_python.c:1930
+msgid "no such window"
+msgstr "ungültiges Fenster"
+
+#: if_python.c:2187 if_python.c:2222 if_python.c:2272 if_python.c:2335
+#: if_python.c:2455 if_python.c:2507 if_tcl.c:685 if_tcl.c:730 if_tcl.c:804
+#: if_tcl.c:874 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "Revertierungs-Information kann nicht gespeichert werden"
+
+#: if_python.c:2189 if_python.c:2279 if_python.c:2346
+msgid "cannot delete line"
+msgstr "Zeile kann nicht gelöscht werden"
+
+#: if_python.c:2224 if_python.c:2362 if_tcl.c:691 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "Zeile kann nicht ersetzt werden"
+
+#: if_python.c:2378 if_python.c:2457 if_python.c:2515
+msgid "cannot insert line"
+msgstr "Zeile kann nicht eingefügt werden"
+
+#: if_python.c:2619
+msgid "string cannot contain newlines"
+msgstr "Zeichenfolge kann keine Zeilen-wechsel enthalten"
+
+#: if_ruby.c:401
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: Dieser Befehl ist nicht verfügbar, die Ruby Bibliothek konnte nicht "
+"geladen werden"
+
+#: if_ruby.c:464
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: Unbekannter longjmp Status %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Umschaltung zwischen Implementierung/Definition"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Zeige Basis-Klasse von"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Zeige überschriebene Mitglieds-Funktion"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Beziehe aus Datei"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Beziehe aus Projekt"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Beziehe aus allen Projekten"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Beziehe"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Zeige die Quelle von"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Finde Symbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Durchsehe Klassen"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Zeige Klasse in Hierarchie"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Zeige Klasse in eingeschränkter Hierarchie"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref bezieht sich auf"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref hat Bezüge zu"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref hat ein"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref wird verwendet von"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Zeige Docu aus"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Generiere Docu für"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"Kann keine verbindung zu SNiFF+ aufnehemen. Prüfe die Umgebung (sniffemacs "
+"muss in $PATH) zu finden sein.\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Fehler beim Lesen. Verbindung abgebrochen"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ ist zur Zeit"
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "nicht"
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "verbunden"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Unbekannte SNiFF+ Anfrage: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Fehler beim Herstellen der Verbindung mit SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ ist nicht verbunden"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Ist kein SNiFF+ Puffer"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: Fehler beim Schreiben. Verbindung abgebrochen"
+
+#: if_tcl.c:419
+msgid "invalid buffer number"
+msgstr "ungültige Puffer-Nummer"
+
+#: if_tcl.c:465 if_tcl.c:932 if_tcl.c:1111
+msgid "not implemented yet"
+msgstr "nicht implementiert"
+
+#: if_tcl.c:502
+msgid "unknown option"
+msgstr "unbekannte Option"
+
+#. ???
+#: if_tcl.c:775
+msgid "cannot set line(s)"
+msgstr "kann keine Zeile/Zeilen setzen"
+
+#: if_tcl.c:846
+msgid "mark not set"
+msgstr "Marke nicht gesetzt"
+
+#: if_tcl.c:852 if_tcl.c:1067
+#, c-format
+msgid "row %d column %d"
+msgstr "Zeile %d Spalte %d"
+
+#: if_tcl.c:882
+msgid "cannot insert/append line"
+msgstr "kann Zeile nicht ein-/anfügen"
+
+#: if_tcl.c:1269
+msgid "unknown flag: "
+msgstr "unbekanntes Flag: "
+
+#: if_tcl.c:1339
+msgid "unknown vimOption"
+msgstr "unbekannte vim Option"
+
+#: if_tcl.c:1424
+msgid "keyboard interrupt"
+msgstr "Tastatur-Unterbrechung"
+
+#: if_tcl.c:1429
+msgid "vim error"
+msgstr "vim Fehler"
+
+#: if_tcl.c:1472
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr ""
+"Puffer/Fenster-Befehl kann nicht ausgeführt werden: das Objekt wird gelöscht"
+
+#: if_tcl.c:1546
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"kann keinen Callback-Befehl registrieren: Puffer/Fenster ist bereits gelöscht"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1563
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: TCL FATALER FEHLER: reflist kaputt!? Bitte benachrichtigen Sie vim-"
+"dev@vim.org"
+
+#: if_tcl.c:1564
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"kann keinen Callback-Befehl registrieren: Puffer/Fenster-Referenz nicht "
+"gefunden"
+
+#: if_tcl.c:1725
+msgid "Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"Dieser Befehl ist nicht verfügbar, da die Tcl Bibliothek nicht geladen "
+"werden konnte"
+
+#: if_tcl.c:1887
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: TCL FEHLER: Exit-Code ist nicht int!? Bitte benachrichtigen Sie vim-"
+"dev@vim.org"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "kann Zeile nicht erhalten"
+
+#: if_xcmdsrv.c:213
+msgid "Unable to register a command server name"
+msgstr "Befehls-Server Name kann nicht registriert werden"
+
+#: if_xcmdsrv.c:434 os_mswin.c:2108
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: Kein registrierter Server-Name \"%s\""
+
+#: if_xcmdsrv.c:463
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Schicken des Befehls zum Ziel-Programm schlug fehl"
+
+#: if_xcmdsrv.c:732
+#, c-format
+msgid "Invalid server id used: %s"
+msgstr "Ungültige Server-ID verwendet: %s"
+
+#: if_xcmdsrv.c:1079
+msgid "E249: couldn't read VIM instance registry property"
+msgstr "E249: Registry-Eigenschaft der VIM Instanz konnte nicht gelesen werden"
+
+#: if_xcmdsrv.c:1090
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: Registry-Eigenschaft der VIM Instanz ist fehlerhaft. Gelöscht!"
+
+#: main.c:53 option.c:3162 option.c:3269
+msgid "Unknown option"
+msgstr "Unbekannte Option"
+
+#: main.c:55
+msgid "Too many edit arguments"
+msgstr "Zu viele Editor Argumente"
+
+#: main.c:57
+msgid "Argument missing after"
+msgstr "Argument fehlt nach"
+
+#: main.c:59
+msgid "Garbage after option"
+msgstr "Schrott nach der Option"
+
+#: main.c:61
+msgid "Too many \"+command\" or \"-c command\" arguments"
+msgstr "Zu viele \"+command\" oder \"-c command\" Argumente"
+
+#: main.c:63
+msgid "Invalid argument for"
+msgstr "Ungültiges Argument für"
+
+#: main.c:450
+msgid "This Vim was not compiled with the diff feature."
+msgstr "Vim wurde nicht mit der \"diff\"-Eigenschaft übersetzt"
+
+#: main.c:875
+msgid "Attempt to open script file again: \""
+msgstr "Versuche, die Skript-Datei erneut zu öffnen: \""
+
+#: main.c:879 main.c:886 main.c:930 memline.c:3673 memline.c:3677
+#: version.c:858 version.c:863 version.c:868 version.c:873 version.c:878
+#: version.c:883 version.c:889 version.c:893 version.c:897 version.c:902
+#: version.c:909 version.c:917 version.c:923
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:884
+msgid "Cannot open for reading: \""
+msgstr "kann nicht zum Lesen geöffnet werden: \""
+
+#: main.c:928
+msgid "Cannot open for script output: \""
+msgstr "kann nicht zur Skript-Ausgabe geöffnet werden: \""
+
+#: main.c:1044
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d Dateien zur Bearbeitung\n"
+
+#: main.c:1118
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Warnung: Die Ausgabe erfolgt nicht auf einem Terminal\n"
+
+#: main.c:1120
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Warnung: Die Eingabe kommt nicht von einem Terminal\n"
+
+#. just in case..
+#: main.c:1195
+msgid "pre-vimrc command line"
+msgstr "pre-vimrc Befehls-Zeile"
+
+#: main.c:1230
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Kann nicht von \"%s\" lesen"
+
+#: main.c:2209
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Weitere Informationen mit: \"vim -h\"\n"
+
+#: main.c:2242
+msgid "[file ..] edit specified file(s)"
+msgstr "[Datei ..] editiere die angegebenen Datei(-en)"
+
+#: main.c:2243
+msgid "- read text from stdin"
+msgstr "- lese Text von stdin"
+
+#: main.c:2244
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tag editiere Datei in der der Tag definiert wurde"
+
+#: main.c:2246
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [Fehler-Datei] editiere Datei mit erstem Fehler"
+
+#: main.c:2255
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"Verwendung:"
+
+#: main.c:2258
+msgid " vim [arguments] "
+msgstr " vim [Argumente] "
+
+#: main.c:2262
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" oder:"
+
+#: main.c:2265
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Argumente:\n"
+
+#: main.c:2266
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tHiernach nur Datei-Namen"
+
+#: main.c:2268
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tPlatzhalter werden nicht ausgewertet"
+
+#: main.c:2271
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tRegistriere diesen gvim in OLE"
+
+#: main.c:2272
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tDeregistriere gvim aus OLE"
+
+#: main.c:2275
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tStart als GUI (wie \"gvim\")"
+
+#: main.c:2276
+msgid "-f\t\t\tForeground: Don't fork when starting GUI"
+msgstr "-f\t\t\tFordergrund: Kein \"fork\" beim Start des GUI"
+
+#: main.c:2278
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi Modus (wie \"vi\")"
+
+#: main.c:2279
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx Modus (wie \"ex\")"
+
+#: main.c:2280
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tLeiser (batch) Modus (nur für \"ex\")"
+
+#: main.c:2282
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tDiff Modus (wie \"vimdiff\")"
+
+#: main.c:2284
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tLeichter Modus (wie \"evim\", ohne Modi)"
+
+#: main.c:2285
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tModus ohne Schreibrechte (wie \"view\")"
+
+#: main.c:2286
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tEingeschränkter Modus (wie \"rvim\")"
+
+#: main.c:2287
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tModifikatioen (beim Schreiben von Dateien) sind nicht erlaubt"
+
+#: main.c:2288
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tModifikatioen im Text nicht erlaubt"
+
+#: main.c:2289
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tBinärmodus"
+
+#: main.c:2291
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tList Modus"
+
+#: main.c:2293
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tKompatibel zu Vi: 'compatible'"
+
+#: main.c:2294
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tNicht ganz kompatibel zu Vi: 'nocompatible'"
+
+#: main.c:2295
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tVerbose Stufe"
+
+#: main.c:2296
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tDebug Modus"
+
+#: main.c:2297
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tKeine Auslagerungs-Datei, verwende nur Speicher"
+
+#: main.c:2298
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tListe nur Auslagerungs-Dateien auf"
+
+#: main.c:2299
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (mit Dateiname)\tStelle abgestürzte Session wieder her"
+
+#: main.c:2300
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tGenauso wie z -r"
+
+#: main.c:2302
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tVerwende nicht newcli zum Öffnen eines neuen Fensters"
+
+#: main.c:2303
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <device>\t\tVerwende <device> for I/O"
+
+#: main.c:2306
+msgid "-H\t\t\tstart in Hebrew mode"
+msgstr "-H\t\t\tStart im Hebräischen Modus"
+
+#: main.c:2309
+msgid "-F\t\t\tstart in Farsi mode"
+msgstr "-F\t\t\tStart im Farsi Modus"
+
+#: main.c:2311
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\tSetze Terminal-Typ auf <terminal>"
+
+#: main.c:2312
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tBenutze <vimrc> anstatt jeglicher .vimrc"
+
+#: main.c:2314
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tBenutze <gvimrc> anstatt jeglicher .gvimrc"
+
+#: main.c:2316
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tlade keine \"plugin\"-Skripte"
+
+#: main.c:2317
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tÖffne N Fenster (Vorgabe: einzeln für jede Datei)"
+
+#: main.c:2318
+msgid "-O[N]\t\tlike -o but split vertically"
+msgstr "-O[N]\t\twie -o, aber teile vertikal"
+
+#: main.c:2319
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tStarte am Ende der Datei"
+
+#: main.c:2320
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\tStart in Zeile <lnum>"
+
+#: main.c:2322
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <Befehl>\tFühre <Befehl> vor dem Laden jeglicher vimrc Datei aus"
+
+#: main.c:2324
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <Befehl>\t\tFühre <Befehl> nach dem Laden der ersten Datei aus"
+
+#: main.c:2325
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <session>\t\tLese Datei <session> nach dem Laden der ersten Datei"
+
+#: main.c:2326
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr ""
+"-s <scriptin>\tLese Normal-Modus Befehle aus der Skript-Datei <scriptin>"
+
+#: main.c:2327
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <scriptout>\tBefehle am Ende der Skript-Datei <scriptout> anfügen"
+
+#: main.c:2328
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <scriptout>\tSchreibe Befehle in die Skript-Datei <scriptout>"
+
+#: main.c:2330
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tEditiere kodierte Dateien"
+
+#: main.c:2334
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\tStarte vim <display>"
+
+#: main.c:2336
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tstelle keine Verbindung zum X-server her"
+
+#: main.c:2338
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tÖffne Vim in einem anderen GTK widget"
+
+#: main.c:2342
+msgid "--remote <files>\tEdit <files> in a Vim server and exit"
+msgstr "--remote <Dateien>\tEditiere <Dateien> in einem Vim Server und beende"
+
+#: main.c:2343
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr ""
+"--remote-wait <Dateien> Wie --remote, aber warte, bis die <Dateien> "
+"editiert wurden"
+
+#: main.c:2344
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <keys>\tSchicke <keys> zu einem Vim Server und beende"
+
+#: main.c:2345
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr ""
+"--remote-expr <Ausdruck>\tFühre <Ausdruck> in einem Vim Server aus und "
+"drucke das Ergebnis"
+
+#: main.c:2346
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tDrucke verfügbare Vim Server Namen und beende"
+
+#: main.c:2347
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <Name>\tBenutze den Vim server <Name>"
+
+#: main.c:2350
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tBenutze <viminfo> statt .viminfo"
+
+#: main.c:2352
+msgid "-h\t\t\tprint Help (this message) and exit"
+msgstr "-h\t\t\tdrucke nur Hilfe (diese Nachricht)"
+
+#: main.c:2353
+msgid "--version\t\tprint version information and exit"
+msgstr "--version\t\tDrucke nur Versions-Informationen"
+
+#: main.c:2357
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Argumente für die gvim Motif Version:\n"
+
+#: main.c:2360
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Argumente für die gvim Athena Version:\n"
+
+#: main.c:2363
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\tStarte vim auf <display>"
+
+#: main.c:2364
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tStarte vim als Icon"
+
+#: main.c:2366
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <name>\t\tBenutze so als ob vim <name> hieße"
+
+#: main.c:2367
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (Nicht implementiert)\n"
+
+#: main.c:2369
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr ""
+"-background <Farbe>\tBenutze <Farbe> für den Hintergrund (auch mit: -bg)"
+
+#: main.c:2370
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr ""
+"-foreground <Farbe>\tBenutze <Farbe> für den Text Vordergrund (auch mit: -fg)"
+
+#: main.c:2371 main.c:2391
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr ""
+"-font <Schriftart>\tBenutze <Schriftart> für normalen Text (auch mit: -fn)"
+
+#: main.c:2372
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <Schriftart>\tBenutze <Schriftart> für Fettschrift"
+
+#: main.c:2373
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <Schriftart>\tBenutze <Schriftart> für geneigten Text"
+
+#: main.c:2374 main.c:2392
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr ""
+"-geometry <geom>\tbenutze <geom> für die Anfangs Abmessungen (auch mit: -"
+"geom)"
+
+#: main.c:2375
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr ""
+"-borderwidth <Breite>\tBenutze einen Rahmen der Breite <Breite> (auch mit: -"
+"bw)"
+
+#: main.c:2376
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr ""
+"-scrollbarwidth <Breite> Benutze eine Scrollbar der Breite <Breite> (auch "
+"mit: -sw)"
+
+#: main.c:2378
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr ""
+"-menuheight <Höhe>\tBenutze einen Menü-Balken der Höhe <Höhe> (auch mit: -mh)"
+
+#: main.c:2380 main.c:2393
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tBenutze invertierte Farben (auch mit: -rv)"
+
+#: main.c:2381
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tBenutze keine invertierten Farben (auch mit: +rv)"
+
+#: main.c:2382
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\tSetze die gegebene Resource"
+
+#: main.c:2385
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Argumente für die gvim RISC-OS Version:\n"
+
+#: main.c:2386
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <Nummer>\tAnfangsbreite des Fensters in Spalten"
+
+#: main.c:2387
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <Nummer>\tAnfangshöhe des Fensters in Zeilen"
+
+#: main.c:2390
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Argumente für die gvim GTK+ Version:\n"
+
+#: main.c:2394
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\tStarte vim auf <display> (auch mit: --display)"
+
+#: main.c:2396
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tZeige Gnome-Argumente"
+
+#. Failed to send, abort.
+#: main.c:2638
+msgid ""
+"\n"
+"Send failed.\n"
+msgstr ""
+"\n"
+"Schicken des Ausdrucks schlug fehl.\n"
+
+#. Let vim start normally.
+#: main.c:2643
+msgid ""
+"\n"
+"Send failed. Trying to execute locally\n"
+msgstr ""
+"\n"
+"Schicken schlug fehl. Versuche lokal auszuführen\n"
+
+#: main.c:2676 main.c:2697
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d von %d editiert"
+
+#: main.c:2720
+msgid "Send expression failed.\n"
+msgstr "Schicken des Ausdrucks schlug fehl.\n"
+
+#: mark.c:660
+msgid "No marks set"
+msgstr "Keine Markierungen gesetzt"
+
+#: mark.c:662
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: Keine Markierungen passen zu \"%s\""
+
+#. Highlight title
+#: mark.c:673
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"Mark Zeile Sp Datei/Text"
+
+#. Highlight title
+#: mark.c:711
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" Sprung Zeile Sp Datei/Text"
+
+#: mark.c:1073
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Datei-Marken:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1108
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Geschichte (neueste bis älteste):\n"
+
+#: mark.c:1203
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Geschichte der Markierungen innerhalb von Dateien (neueste bis älteste):\n"
+
+#: mark.c:1286
+msgid "Missing '>'"
+msgstr "'>' fehlt"
+
+#: mbyte.c:395
+msgid "Not a valid codepage"
+msgstr "Ist nicht eine zulässige Code-Seite"
+
+#: mbyte.c:3107
+msgid "E284: Cannot set IC values"
+msgstr "E284: Kann die IC Werte nicht setzen"
+
+#: mbyte.c:3259
+msgid "E285: Failed to create input context"
+msgstr "E285: Eingabe-Kontext konnte nicht erzeugt werden"
+
+#: mbyte.c:3406
+msgid "E286: Failed to open input method"
+msgstr "E286: Eingabe-Methode konnte geöffnet werden"
+
+#: mbyte.c:3417
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: Achtung: Destroy Callabck konnte nicht auf IM gesetzt werden"
+
+#: mbyte.c:3423
+msgid "E288: input method doesn't support any style"
+msgstr "E288: Eingabe-Methode unterstützt keinen einzigen Stil"
+
+#: mbyte.c:3480
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: Eingabe-Methode unterstützt nicht meinen Voreditier-Typen"
+
+#: mbyte.c:3554
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: der Über-dem-Punkt Stil benötigt fontset"
+
+#: mbyte.c:3582
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr ""
+"E291: Ihr GTK+ ist älter als 1.2.3. Der Status-Bereich wird abgeschaltet"
+
+#: mbyte.c:3849
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Server der Eingabe-Methode läuft nicht"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: Block war nicht gesperrt"
+
+#: memfile.c:989
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Positionier-Fehler beim Lesen der Auslagerungs-Datei"
+
+#: memfile.c:994
+msgid "E295: Read error in swap file"
+msgstr "E295: Lese-Fehler in der Auslagerungs-Datei"
+
+#: memfile.c:1046
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Positionier-Fehler beim Schreiben in die Auslagerungs-Datei"
+
+#: memfile.c:1064
+msgid "E297: Write error in swap file"
+msgstr "E297: Fehler beim Schreiben in die Auslagerungs-Datei"
+
+#: memfile.c:1261
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: Auslagerungs-Datei ist bereits vorhanden (symlink Attacke?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Block Nr. 0 nicht erhalten?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Block Nr. 1 nicht erhalten?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: Block Nr. 2 nicht erhalten?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Ups, Verlust der Auslagerungs-Datei!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: Auslagerungs-Datei konnte nicht umbenannt werden"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr ""
+"E303: Auslagerungs-Datei für \"%s\" konnte nicht geöffnet werden, "
+"Wiederherstellung unmöglich"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: Block Nr. 0 nicht erhalten?"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Keine Auslagerungs-Datei für %s gefunden"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr ""
+"Geben Sie die Nummer der Auslagerungs-Datei ein die verwendet werden soll (0 "
+"um abzubrechen): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: %s kann nicht geöffnet werden"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "Block 0 kann nicht gelesen werden aus "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Vielleicht wurden keine Änderungen vorgenommen oder Vim hatte die "
+"Auslagerungs-Datei nicht aktualisiert."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " kann nicht zusammen mit dieser Vim Version verwendet werden.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Benutze Vim Version 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s sieht nicht wie eine Vim Auslagerungs-Datei aus"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " kann auf diesem Rechner nicht verwendet werden.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "Die Datei wurde erstellt um "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"oder die Datei wurde zerstört."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "Verwende Auslagerungs-Datei \"%s\""
+
+#: memline.c:915
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Original-Datei \"%s\""
+
+#: memline.c:934
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Warnung: Die Original-Datei könnte verändert worden sein"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Block 1 kann nicht nicht von %s gelesen werden"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???VIELE ZEILEN FEHLEN"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???ZEILEN ZÄHLER FALSCH"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???LEERER BLOCK"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???ZEILEN FEHLEN"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: Block 1 ID falsch (ist %s keine .swp-Datei?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???BLOCK FEHLT"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? von hier bis ???ENDE könnten die Zeilen falsch sein"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? von hier bis ???ENDE könnten Zeilen eingefügt oder gelöscht sein"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???ENDE"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Wiederherstellung unterbrochen"
+
+#: memline.c:1145
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr ""
+"E312: Fehler wurden festgestellt während der Wiederherstellung: suche nach "
+"Zeilen die mit ??? beginnen"
+
+#: memline.c:1148
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Wiederherstellung beendet. Prüfen Sie, ob alles alles OK ist."
+
+#: memline.c:1149
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Wollen Sie vielleicht diese Datei unter einem neuen Namen speichern\n"
+
+#: memline.c:1150
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "und \"diff\" zur Original-Datei machen, um Änderungen zu prüfen)\n"
+
+#: memline.c:1151
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"Löschen Sie die .swp-Datei danach.\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1207
+msgid "Swap files found:"
+msgstr "Auslagerungs-Dateien gefunden:"
+
+#: memline.c:1385
+msgid " In current directory:\n"
+msgstr " Im laufenden Verzeichnis:\n"
+
+#: memline.c:1387
+msgid " Using specified name:\n"
+msgstr " Benutze gegebenen Namen:\n"
+
+#: memline.c:1391
+msgid " In directory "
+msgstr " Im Verzeichnis "
+
+#: memline.c:1409
+msgid " -- none --\n"
+msgstr " -- Nichts --\n"
+
+#: memline.c:1481
+msgid " owned by: "
+msgstr " Eigentum von: "
+
+#: memline.c:1483
+msgid " dated: "
+msgstr " vom: "
+
+#: memline.c:1487 memline.c:3680
+msgid " dated: "
+msgstr " vom: "
+
+#: memline.c:1503
+msgid " [from Vim version 3.0]"
+msgstr " [von Vim Version 3.0]"
+
+#: memline.c:1507
+msgid " [does not look like a Vim swap file]"
+msgstr " [sieht nicht wie eine Vim Auslagerungs-Datei aus]"
+
+#: memline.c:1511
+msgid " file name: "
+msgstr " Dateiname: "
+
+#: memline.c:1523
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" verändert: "
+
+#: memline.c:1524
+msgid "YES"
+msgstr "JA"
+
+#: memline.c:1524
+msgid "no"
+msgstr "nein"
+
+#: memline.c:1528
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" Benutzer Name: "
+
+#: memline.c:1535
+msgid " host name: "
+msgstr " Host Name: "
+
+#: memline.c:1537
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" Host Name: "
+
+#: memline.c:1543
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" Process ID: "
+
+#: memline.c:1549
+msgid " (still running)"
+msgstr " (läuft noch)"
+
+#: memline.c:1561
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [nicht verwendbar zusammen mit dieser Vim-Version]"
+
+#: memline.c:1564
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [nicht verwendbar auf diesem Rechner]"
+
+#: memline.c:1569
+msgid " [cannot be read]"
+msgstr " [kann nicht gelesen werden]"
+
+#: memline.c:1573
+msgid " [cannot be opened]"
+msgstr " [kann nicht geöffnet werden]"
+
+#: memline.c:1763
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Kann nicht absichern, es gibt keine Auslagerungs-Datei"
+
+#: memline.c:1816
+msgid "File preserved"
+msgstr "Datei gesichert"
+
+#: memline.c:1818
+msgid "E314: Preserve failed"
+msgstr "E314: Absicherung fehlgeschlagen"
+
+#: memline.c:1889
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: unzulässige lnum: %ld"
+
+#: memline.c:1915
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: Zeile %ld kann nicht gefunden werden"
+
+#: memline.c:2303
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: Zeiger-Block id falsch 3"
+
+#: memline.c:2383
+msgid "stack_idx should be 0"
+msgstr "stack_idx sollte 0 sein"
+
+#: memline.c:2445
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Zu viele Blocks aktualisiert?"
+
+#: memline.c:2602
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: Zeiger Block id falsch 4"
+
+#: memline.c:2629
+msgid "deleted block 1?"
+msgstr "Block 1 gelöscht?"
+
+#: memline.c:2829
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Zeile %ld kann nicht gefunden werden"
+
+#: memline.c:3072
+msgid "E317: pointer block id wrong"
+msgstr "E317: Zeiger Block id ist falsch"
+
+#: memline.c:3088
+msgid "pe_line_count is zero"
+msgstr "pe_line_count ist Null"
+
+#: memline.c:3117
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: Zeilennummer nicht im zulässigen Bereich: %ld nach dem Ende"
+
+#: memline.c:3121
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: Zeilen Zähler falsch in Block %ld"
+
+#: memline.c:3170
+msgid "Stack size increases"
+msgstr "Stapel Größe wächst"
+
+#: memline.c:3216
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: Zeiger Block id falsch 2"
+
+#: memline.c:3670
+msgid "E325: ATTENTION"
+msgstr "E325: ACHTUNG"
+
+#: memline.c:3671
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Auslagerungs-Datei mit folgendem Namen gefunden: \""
+
+#: memline.c:3675
+msgid "While opening file \""
+msgstr "Beim Öffnen der Datei \""
+
+#: memline.c:3684
+msgid " NEWER than swap file!\n"
+msgstr " neuer als Auslagerungs-Datei!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3688
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Ein anderes Programm editiert möglicherweise diese Datei.\n"
+" Wenn dies der Fall ist, sollten Sie vorsichtig sein, damit\n"
+" es nicht zu Überschneidungen kommt.\n"
+
+#: memline.c:3689
+msgid " Quit, or continue with caution.\n"
+msgstr " Ende, oder Fortsetzung mit Vorsicht.\n"
+
+#: memline.c:3690
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) Eine Editier-Sitzung für diese Datei ist abgestürzt.\n"
+
+#: memline.c:3691
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr ""
+" Wenn dies der Fall ist, so verwenden Sie \":recover\" oder \"vim -r "
+
+#: memline.c:3693
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" um die Änderungen wiederherzustellen (siehe \":help recovery\").\n"
+
+#: memline.c:3694
+msgid " If you did this already, delete the swap file \""
+msgstr ""
+" Wenn dies bereits geschehen ist, löschen Sie die Auslagerungs-Datei \""
+
+#: memline.c:3696
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" um diese Nachricht zu vermeiden.\n"
+
+#: memline.c:3710 memline.c:3714
+msgid "Swap file \""
+msgstr "Auslagerungs-Datei \""
+
+#: memline.c:3711 memline.c:3717
+msgid "\" already exists!"
+msgstr "\" ist bereits vorhanden!"
+
+#: memline.c:3720
+msgid "VIM - ATTENTION"
+msgstr "VIM - ACHTUNG"
+
+#: memline.c:3722
+msgid "Swap file already exists!"
+msgstr "Auslagerungs-Datei ist bereits vorhanden!"
+
+#: memline.c:3726
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"Öffnen nur zum &Lesen\n"
+"Trotzdem &editieren\n"
+"&Wiederherstellen\n"
+"&Abbrechen"
+
+#: memline.c:3728
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"Öffnen nur zum &Lesen\n"
+"Trotzdem &editieren\n"
+"&Wiederherstellen\n"
+"&Abbrechen\n"
+"Ent&fernen"
+
+#: memline.c:3781
+msgid "E326: Too many swap files found"
+msgstr "E326: Zu viele Auslagerungs-Dateien gefunden"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Teil des Menüpunkt-Pfades muss zum Untermenü führen"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Menü existiert nur in anderen Modus"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Kein Menü mit diesem Namen"
+
+#: menu.c:509
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Menü-Pfad darf nicht zum Untermenü führen"
+
+#: menu.c:548
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr ""
+"E331: Menü-Punkt können nicht direkt zum Menü-Balken hinzugefügt werden"
+
+#: menu.c:554
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Trenner kann nicht Teil des Menü-Pfades sein"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1070
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Menüs ---"
+
+#: menu.c:1987
+msgid "Tear off this menu"
+msgstr "Reiße dieses Menü ab"
+
+#: menu.c:2052
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Menü-Pfad muss zu einem Menü-Punkt führen"
+
+#: menu.c:2072
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Menü nicht gefunden: %s"
+
+#: menu.c:2141
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: Menü ist für %s Modus nicht definiert"
+
+#: menu.c:2179
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Menü-Pfad muss zum Untermenü führen"
+
+#: menu.c:2200
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Menü nicht gefunden - überprüfe Menü-Namen"
+
+#: message.c:470
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Fehler beim Ausführen von \"%s\":"
+
+#: message.c:486
+#, c-format
+msgid "line %4ld:"
+msgstr "Zeile %4ld:"
+
+#: message.c:526
+msgid "[string too long]"
+msgstr "[Zeichenkette zu lang]"
+
+#: message.c:672
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "Übersetzt von Johannes Zellner <johannes@zellner.org>"
+
+#: message.c:885
+msgid "Interrupt: "
+msgstr "Unterbrechung: "
+
+#: message.c:888
+msgid "Hit ENTER to continue"
+msgstr "weiter mit der EINGABETASTE"
+
+#: message.c:890
+msgid "Hit ENTER or type command to continue"
+msgstr "Drücken Sie die EINGABETASTE oder geben Sie einen Befehl ein"
+
+#: message.c:1961
+msgid "-- More --"
+msgstr "-- Mehr --"
+
+#: message.c:1964
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: Zeile, LEERZEICHEN/b: Seite, d/u: Halbe Seite, q: Ende)"
+
+#: message.c:1965
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: Zeile, LEERZEICHEN: Seite, d: Halbe Seite, q: Ende)"
+
+#: message.c:2441 message.c:2456
+msgid "Question"
+msgstr "Frage"
+
+#: message.c:2443
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Ja\n"
+"&Nein"
+
+#: message.c:2458
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Ja\n"
+"&Nein\n"
+"&Abbrechen"
+
+#: message.c:2476
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Ja\n"
+"&Nein\n"
+"Alle &Speichern\n"
+"Alle &Verwerfen\n"
+"&Abbrechen"
+
+#: message.c:2517
+msgid "Save File dialog"
+msgstr "Datei Speichern Dialog"
+
+#: message.c:2519
+msgid "Open File dialog"
+msgstr "Datei Öffnen Dialog"
+
+#. TODO: non-GUI file selector here
+#: message.c:2590
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: kein Datei-Dialog im Konsole-Modus"
+
+#: misc1.c:2462
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: Warnung: Ändern einer schreibgeschützten Datei"
+
+#: misc1.c:2691
+msgid "1 more line"
+msgstr "eine Zeile mehr"
+
+#: misc1.c:2693
+msgid "1 line less"
+msgstr "eine Zeile weniger"
+
+#: misc1.c:2698
+#, c-format
+msgid "%ld more lines"
+msgstr "%ld Zeilen mehr"
+
+#: misc1.c:2700
+#, c-format
+msgid "%ld fewer lines"
+msgstr "%ld Zeilen weniger"
+
+#: misc1.c:2703
+msgid " (Interrupted)"
+msgstr " (Unterbrochen)"
+
+#: misc1.c:6321
+msgid "Vim: preserving files...\n"
+msgstr "Vim: Sichern der Dateien...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6331
+msgid "Vim: Finished.\n"
+msgstr "Vim: Beendet.\n"
+
+#: misc2.c:666 misc2.c:682
+msgid "ERROR: "
+msgstr "FEHLER: "
+
+#: misc2.c:686
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[Bytes] gesamt alloziert-frei %lu-%lu, in Verwendung %lu, maximale "
+"Verwendung %lu\n"
+
+#: misc2.c:688
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[Aufrufe] gesamt re/malloc()s %lu, gesamt free()s %lu\n"
+"\n"
+
+#: misc2.c:743
+msgid "E340: Line is becoming too long"
+msgstr "E340: Zeile wird zu lang"
+
+#: misc2.c:787
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Interner Fehler: lalloc(%ld, )"
+
+#: misc2.c:895
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Kein Speicherplatz mehr vorhanden (%lu bytes alloziert)"
+
+#: misc2.c:2546
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Rufe Shell auf, um \"%s\" auszuführen"
+
+#: misc2.c:2745 misc2.c:5230 option.c:4636
+msgid "Missing colon"
+msgstr "fehlendes Komma"
+
+#: misc2.c:2747 misc2.c:2774
+msgid "Illegal mode"
+msgstr "Unzulässiger Modus"
+
+#: misc2.c:2813
+msgid "Illegal mouseshape"
+msgstr "Unzulässige Maus-Form"
+
+#: misc2.c:2853 misc2.c:5250
+msgid "digit expected"
+msgstr "Ziffer erwartet"
+
+#: misc2.c:2858
+msgid "Illegal percentage"
+msgstr "Unzulässige Prozentangabe"
+
+#: misc2.c:3162
+msgid "Enter encryption key: "
+msgstr "Geben Sie bitte den Schlüssel ein: "
+
+#: misc2.c:3163
+msgid "Enter same key again: "
+msgstr "Geben Sie den gleichen Schlüssel nochmals ein:"
+
+#: misc2.c:3173
+msgid "Keys don't match!"
+msgstr "Die Schlüssel stimmen nicht überein!"
+
+#: misc2.c:3712
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Ungültiger Pfad: '**[Nummer]' muss am Ende des Pfads sein, oder von "
+"'%s' gefolgt werden. Siehe :help path."
+
+#: misc2.c:4984
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Verzeichnis \"%s\" kann im 'cdpath' nicht gefunden werden"
+
+#: misc2.c:4987
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Datei \"%s\" kann im Pfad nicht gefunden werden"
+
+#: misc2.c:4993
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: Kein weiteres Verzeichnis \"%s\" im 'cdpath' gefunden"
+
+#: misc2.c:4996
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: Keine weitere Datei \"%s\" im Pfad gefunden"
+
+#: misc2.c:5242
+msgid "Illegal component"
+msgstr "Unzulässige Komponente"
+
+#: normal.c:2857
+msgid "Warning: terminal cannot highlight"
+msgstr "Achtung: Terminal unterstützt keine Hervorhebung"
+
+#: normal.c:3052
+msgid "E348: No string under cursor"
+msgstr "E348: Keine Zeichenkette unter dem Cursor"
+
+# Identifizierungszeichen/merkmal, Bezeichner
+#: normal.c:3054
+msgid "E349: No identifier under cursor"
+msgstr "E349: Kein Merkmal unter dem Cursor"
+
+#: normal.c:4225
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr ""
+"E352: Faltung kann mit der eingestellten Methode 'foldmethod' nicht gelöscht "
+"werden"
+
+#: ops.c:283
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "eine Zeile ein Mal %s"
+
+#: ops.c:285
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 Zeile %s %d Mal"
+
+#: ops.c:290
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld Zeilen %s ein Mal"
+
+#: ops.c:293
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld Zeilen %s %d Mal"
+
+#: ops.c:651
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld Zeilen zum Einrücken... "
+
+#: ops.c:701
+msgid "1 line indented "
+msgstr "1 Zeile eingerückt... "
+
+#: ops.c:703
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld Zeilen eingerückt... "
+
+#. must display the prompt
+#: ops.c:1546
+msgid "cannot yank; delete anyway"
+msgstr "kann nicht kopieren; lösche trotzdem"
+
+#: ops.c:2079
+msgid "1 line changed"
+msgstr "1 Zeile ~"
+
+#: ops.c:2081
+#, c-format
+msgid "%ld lines changed"
+msgstr "%ld Zeilen geändert"
+
+#: ops.c:2438
+#, c-format
+msgid "freeing %ld lines"
+msgstr "gebe %ld Zeilen frei"
+
+#: ops.c:2719
+msgid "1 line yanked"
+msgstr "Eine Zeile kopiert"
+
+#: ops.c:2721
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld Zeilen kopiert"
+
+#: ops.c:3014
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: Register %s ist leer"
+
+#. Highlight title
+#: ops.c:3572
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Register ---"
+
+#: ops.c:4730
+msgid "Illegal register name"
+msgstr "Unzulässiger Register Name"
+
+#: ops.c:4816
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Register:\n"
+
+#: ops.c:4844
+#, c-format
+msgid "Unknown register type %d"
+msgstr "Unbekannter Register Typ %d"
+
+#: ops.c:5236
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: Unzulässiger Register Name: '%s'"
+
+#: ops.c:5585
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Spalten; "
+
+#: ops.c:5592
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "%s%ld von %ld Zeilen; %ld von %ld Worten; %ld von %ld Bytes"
+
+#: ops.c:5608
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Spal %s von %s; Zeile %ld von %ld; Wort %ld von %ld; Byte %ld von %ld"
+
+#: ops.c:5619
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld für BOM)"
+
+#: option.c:1989
+msgid "Thanks for flying Vim"
+msgstr "Danke für die Benutzung von Vim"
+
+#: option.c:3175
+msgid "Option not supported"
+msgstr "Option nicht unterstützt"
+
+#: option.c:3200
+msgid "Not allowed in a modeline"
+msgstr "Nicht erlaubt in einer 'modeline'"
+
+#: option.c:3256
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tZuletzt gesetzt von "
+
+#: option.c:3395
+msgid "Number required after ="
+msgstr "Brauche Zahl nach ="
+
+#: option.c:3714 option.c:4322
+msgid "Not found in termcap"
+msgstr "Nicht gefunden in termcap"
+
+#: option.c:3780
+#, c-format
+msgid "Illegal character <%s>"
+msgstr "Unzulässiges Zeichen <%s>"
+
+#: option.c:4307 option.c:5573
+msgid "Not allowed here"
+msgstr "hier nicht erlaubt"
+
+#: option.c:4314
+msgid "Cannot set 'term' to empty string"
+msgstr "'term' kann keine leere Zeichenkette sein"
+
+#: option.c:4317
+msgid "Cannot change term in GUI"
+msgstr "'term' kann im GUI nicht verändert werden"
+
+#: option.c:4319
+msgid "Use \":gui\" to start the GUI"
+msgstr "Verwende \":gui\", um die GUI-Version zu starten"
+
+#: option.c:4340
+msgid "'backupext' and 'patchmode' are equal"
+msgstr "'backupext' und 'patchmode' sind gleich"
+
+#: option.c:4638
+msgid "Zero length string"
+msgstr "Zeichenkette der Länge Null"
+
+#: option.c:4706
+#, c-format
+msgid "Missing number after <%s>"
+msgstr "fehlende Zahl nach <%s>"
+
+#: option.c:4720
+msgid "Missing comma"
+msgstr "Komma fehlt"
+
+#: option.c:4727
+msgid "Must specify a ' value"
+msgstr "ein '-Wert muss angegeben werden"
+
+#: option.c:4767
+msgid "contains unprintable character"
+msgstr "enthält nicht-druckbare Zeichen"
+
+#: option.c:4800
+msgid "Invalid font(s)"
+msgstr "Ungültiger Schriftsatz"
+
+# what's the difference ?
+#: option.c:4807
+msgid "can't select fontset"
+msgstr "\"fontset\" kann nicht eingestellt werden"
+
+#: option.c:4809
+msgid "Invalid fontset"
+msgstr "Ungültiger Fontset"
+
+#: option.c:4816
+msgid "can't select wide font"
+msgstr "Weiter Schriftart kann nicht engestellt werden"
+
+#: option.c:4818
+msgid "Invalid wide font"
+msgstr "Ungültiger weiter Schriftsatz"
+
+#: option.c:5088
+#, c-format
+msgid "Illegal character after <%c>"
+msgstr "Unzulässiges Zeichen nach <%c>"
+
+#: option.c:5171
+msgid "comma required"
+msgstr "Komma benötigt"
+
+#: option.c:5179
+#, c-format
+msgid "'commentstring' must be empty or contain %s"
+msgstr "'commentstring' muß leer sein, oder %s enthalten"
+
+#: option.c:5226
+msgid "No mouse support"
+msgstr "Keine Maus-Unterstützung"
+
+# XXX
+#: option.c:5475
+msgid "Unclosed expression sequence"
+msgstr "Nicht geschlossene Ausdrucks Folge"
+
+#: option.c:5479
+msgid "too many items"
+msgstr "zu viele Punkte"
+
+#: option.c:5481
+msgid "unbalanced groups"
+msgstr "nicht ausgewogene Gruppen"
+
+#: option.c:5696
+msgid "A preview window already exists"
+msgstr "Ein Fenster zur Voransicht existiert bereits"
+
+#: option.c:5957 option.c:5986
+msgid "'winheight' cannot be smaller than 'winminheight'"
+msgstr "'winheight' kann nicht kleiner sein als 'winminheight'"
+
+#: option.c:6002 option.c:6021
+msgid "'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "'winwidth' kann nicht kleiner sein als 'winminwidth'"
+
+#: option.c:6162
+#, c-format
+msgid "Need at least %d lines"
+msgstr "mindestens %d Zeilen werden benötigt"
+
+#: option.c:6171
+#, c-format
+msgid "Need at least %d columns"
+msgstr "mindestens %d Spalten werden benötigt"
+
+#: option.c:6468
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Unbekannte Option: %s"
+
+#: option.c:6577
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Terminal Codes ---"
+
+#: option.c:6579
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Werte globaler Optionen ---"
+
+#: option.c:6581
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Werte lokaler Optionen ---"
+
+#: option.c:6583
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Optionen ---"
+
+#: option.c:7272
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp FEHLER"
+
+#: option.c:8230
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': Passendes Zeichen fehlt für %s"
+
+#: option.c:8264
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': Überschüssige Zeichen nach dem Semikolon: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "kann nicht öffnen"
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Fenster kann nicht geöffnet werden!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Brauche Amigados Version 2.04 oder neuere\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Benötige %s Version %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "Kann NIL nicht öffnen:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr "Kann nicht anlegen "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim steigt aus mit %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "kann Konsolen Modus nicht wechseln ?!\n"
+
+#: os_amiga.c:938 os_mac.c:1177 os_mswin.c:629 os_riscos.c:757 os_unix.c:2803
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Bildschirm Modus wird nicht unterstützt"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_winsize: ist keine Konsole??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1142
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Kann Shell nicht mit der -f Option aus führen"
+
+#: os_amiga.c:1183 os_amiga.c:1273
+msgid "Cannot execute "
+msgstr "Kann nicht ausführen "
+
+#: os_amiga.c:1186 os_amiga.c:1283
+msgid "shell "
+msgstr "Shell "
+
+#: os_amiga.c:1206 os_amiga.c:1308
+msgid " returned\n"
+msgstr " zurückgegeben\n"
+
+#: os_amiga.c:1448
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE zu klein."
+
+#: os_amiga.c:1452
+msgid "I/O ERROR"
+msgstr "I/O FEHLER"
+
+#: os_mswin.c:503
+msgid "...(truncated)"
+msgstr "...(abgeschnitten)"
+
+#: os_mswin.c:604
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' beträgt nicht 80, kann externe Befehle nicht ausführen"
+
+#: os_mswin.c:716 os_unix.c:5116
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Bibliotheks-Aufruf für \"%s()\" schlug fehl"
+
+#: os_mswin.c:1365
+msgid "E237: Printer selection failed"
+msgstr "E237: Drucker-Auswahl fehlgeschlagen"
+
+#: os_mswin.c:1405
+#, c-format
+msgid "to %s on %s"
+msgstr "nach %s auf %s"
+
+#: os_mswin.c:1420
+#, c-format
+msgid "E448: Unknown font: %s"
+msgstr "E448: Unbekannte Schriftart: %s"
+
+#: os_mswin.c:1470 os_mswin.c:1480
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Fehler beim Drucken: %s"
+
+#: os_mswin.c:1481
+msgid "Unknown"
+msgstr "Unbekannt"
+
+#: os_mswin.c:1508
+#, c-format
+msgid "Printing '%s'"
+msgstr "Drucke '%s'"
+
+#: os_mswin.c:2596
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Unzulässiger Zeichensatz-Name \"%s\" im Schriftart-Namen \"%s\""
+
+#: os_mswin.c:2604
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Unzulässiges Zeichen '%c' in der Schriftart \"%s\""
+
+#: os_riscos.c:1256
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Unzulässige 'osfiletype'-Option - verwende Text"
+
+#: os_unix.c:862
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: Doppel-Signal, beenden\n"
+
+#: os_unix.c:868
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Erhielt tödliches Signal %s\n"
+
+#: os_unix.c:871
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Erhielt tödliches Signal\n"
+
+#: os_unix.c:1125
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Öffnen des X-Displays dauerte %ld msec"
+
+#: os_unix.c:1152
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: ein X11 Fehler trat auf\n"
+
+#: os_unix.c:1219
+msgid "Testing the X display failed"
+msgstr "Test des X-Displays schlug fehl"
+
+#: os_unix.c:1363
+msgid "Opening the X display timed out"
+msgstr "Zeitüberschreitung während des Öffnens des X-Displays"
+
+#: os_unix.c:2976 os_unix.c:3634
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"Shell kann nicht ausführt werden "
+
+#: os_unix.c:3021
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Shell sh kann nicht ausführt werden\n"
+
+#: os_unix.c:3025 os_unix.c:3640
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"Shell beendet "
+
+#: os_unix.c:3159
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Pipes können nicht angelegt werden\n"
+
+#: os_unix.c:3174
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"'fork' schlug fehl\n"
+
+#: os_unix.c:3647
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Befehl beendet\n"
+
+#: os_unix.c:5164
+msgid "Opening the X display failed"
+msgstr "Öffnen des X-Displays schlug fehl"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "In Zeile"
+
+#: os_w32exe.c:169
+msgid "Could not load vim32.dll!"
+msgstr "Konnte vim32.dll nicht laden!"
+
+#: os_w32exe.c:169 os_w32exe.c:179
+msgid "VIM Error"
+msgstr "VIM Fehler"
+
+#: os_w32exe.c:179
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Konnte Funktions-Zeiger in der DLL nicht korrigieren!"
+
+#: os_win16.c:578 os_win32.c:3037
+#, c-format
+msgid "shell returned %d"
+msgstr "Shell gab %d zurück"
+
+#: os_win32.c:2505
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Fing Ereignis %s ein\n"
+
+#: os_win32.c:2507
+msgid "close"
+msgstr "schließe"
+
+#: os_win32.c:2509
+msgid "logoff"
+msgstr "aus-loggen"
+
+#: os_win32.c:2510
+msgid "shutdown"
+msgstr "beenden"
+
+#: os_win32.c:2991
+msgid "E371: Command not found"
+msgstr "E371: Befehl nicht gefunden"
+
+#: os_win32.c:3004
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE wurde im Pfad $PATH nicht gefunden.\n"
+"Externe Befehle werden nach Ausführung nicht anhalten.\n"
+"Siehe :help win32-vimrun für mehr Information."
+
+#: os_win32.c:3007
+msgid "Vim Warning"
+msgstr "Vim Warnung"
+
+#: quickfix.c:281
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Zu viele %%%c im Format"
+
+#: quickfix.c:294
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: Unerwartetes %%%c im Format"
+
+#: quickfix.c:348
+msgid "E374: Missing ] in format string"
+msgstr "E374: fehlendes ] im Format"
+
+#: quickfix.c:362
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: %%%c wird im Format nicht unterstützt"
+
+#: quickfix.c:380
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: Unzulässiges %%%c im Prefix des Formats"
+
+#: quickfix.c:388
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: Unzulässiges %%%c im Format"
+
+#: quickfix.c:414
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' enthält kein Muster"
+
+#: quickfix.c:520
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Fehlender oder leerer Verzeichnisname"
+
+#: quickfix.c:931
+msgid "No more items"
+msgstr "Keine weiteren Punkte"
+
+#: quickfix.c:1152
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d aus %d)%s%s: "
+
+#: quickfix.c:1154
+msgid " (line deleted)"
+msgstr " (Zeile gelöscht)"
+
+#: quickfix.c:1360
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Am Anfang der quickfix Liste"
+
+#: quickfix.c:1369
+msgid "E381: At top of quickfix stack"
+msgstr "E381: An Ende der quickfix Liste"
+
+#: quickfix.c:1381
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "Fehlerliste %d aus %d; %d Fehler"
+
+#: quickfix.c:1842
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: Kann nicht schreiben, 'buftype'-Option ist gesetzt"
+
+#: regexp.c:822
+msgid "E339: Pattern too long"
+msgstr "E339: Muster zu lang"
+
+#: regexp.c:1339
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: Verschachteltes %s*"
+
+#: regexp.c:1342
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: Verschachteltes %s%c"
+
+#: regexp.c:1493
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c nach Nichts"
+
+#: regexp.c:2510
+#, c-format
+msgid "Syntax error in %s{...}"
+msgstr "Syntax Fehler in %s{...}"
+
+#: regexp.c:2757
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Absturz verhindert; Ist der reguläre Ausdruck zu kompliziert?"
+
+#: regexp.c:2892
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: Muster erzeugte einen Stapel-Überlauf-Fehler"
+
+#: regexp.c:3128
+msgid "External submatches:\n"
+msgstr "externe 'submatches':\n"
+
+#: screen.c:2063
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld Zeilen gefaltet "
+
+#: screen.c:7535
+msgid " VREPLACE"
+msgstr " V-ERSETZEN"
+
+#: screen.c:7539
+msgid " REPLACE"
+msgstr " ERSETZEN"
+
+#: screen.c:7544
+msgid " REVERSE"
+msgstr " INVERTIERT"
+
+#: screen.c:7546
+msgid " INSERT"
+msgstr " EINFÜGEN"
+
+#: screen.c:7549
+msgid " (insert)"
+msgstr " (einfügen)"
+
+#: screen.c:7551
+msgid " (replace)"
+msgstr " (ersetzen)"
+
+#: screen.c:7553
+msgid " (vreplace)"
+msgstr " (v-ersetzen)"
+
+#: screen.c:7556
+msgid " Hebrew"
+msgstr " Hebräisch"
+
+#: screen.c:7564
+msgid " (lang)"
+msgstr " (Sprache)"
+
+# einkleben ist echt Scheiße, aber einfügen
+# gibts schon ...
+#: screen.c:7567
+msgid " (paste)"
+msgstr " (einkleben)"
+
+#: screen.c:7573
+msgid " SELECT"
+msgstr " AUSWAHL"
+
+#: screen.c:7575
+msgid " VISUAL"
+msgstr " VISUELL"
+
+#: screen.c:7577
+msgid " BLOCK"
+msgstr "ER BLOCK"
+
+#: screen.c:7579
+msgid " LINE"
+msgstr "E ZEILE"
+
+#: screen.c:7592 screen.c:7652
+msgid "recording"
+msgstr "aufzeichnen"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "Suche erreichte den ANFANG und wurde am ENDE fortgesetzt"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "Suche erreichte das ENDE und wurde am ANFANG fortgesetzt"
+
+#: search.c:455
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Unzulässiges Suchmuster: %s"
+
+#: search.c:782
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: Suche erreichte den ANFANG ohne Treffer für: %s"
+
+#: search.c:784
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: Suche erreichte das ENDE ohne Treffer für: %s"
+
+#: search.c:1157
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: Erwarte '?' oder '/' nach ';'"
+
+#: search.c:3537
+msgid " (includes previously listed match)"
+msgstr " (enthält bereits vorher aufgezählte Treffer)"
+
+#. cursor at status line
+#: search.c:3557
+msgid "--- Included files "
+msgstr "--- Eingefügte Dateien "
+
+#: search.c:3559
+msgid "not found "
+msgstr "nicht gefunden "
+
+#: search.c:3560
+msgid "in path ---\n"
+msgstr "im Pfad ---\n"
+
+#: search.c:3599
+msgid " (Already listed)"
+msgstr " (Bereits aufgelistet)"
+
+#: search.c:3601
+msgid " NOT FOUND"
+msgstr " NICHT GEFUNDEN"
+
+#: search.c:3653
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Scanne eingefügte Datei: %s"
+
+#: search.c:3871
+msgid "E387: Match is on current line"
+msgstr "E387: Treffer ist auf der momentanen Zeile"
+
+#: search.c:4011
+msgid "All included files were found"
+msgstr "Alle eingefügten Dateien wurden gefunden"
+
+#: search.c:4013
+msgid "No included files"
+msgstr "Keine eingefügten Dateien"
+
+#: search.c:4029
+msgid "E388: Couldn't find definition"
+msgstr "E388: Definition konnte nicht gefunden werden"
+
+#: search.c:4031
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Muster konnte nicht gefunden werden"
+
+#: syntax.c:2999
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: Unzulässiges Argument: %s"
+
+#: syntax.c:3179
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: Kein solches Syntax-Cluster: %s"
+
+#: syntax.c:3343
+msgid "No Syntax items defined for this buffer"
+msgstr "Keine Syntax-Elemente definiert für diesen Puffer"
+
+#: syntax.c:3351
+msgid "syncing on C-style comments"
+msgstr "Synchronisation an C-Stil Kommentaren"
+
+#: syntax.c:3359
+msgid "no syncing"
+msgstr "keine Synchronisation"
+
+#: syntax.c:3362
+msgid "syncing starts "
+msgstr "Synchronisation beginnt "
+
+#: syntax.c:3364 syntax.c:3439
+msgid " lines before top line"
+msgstr " Zeilen vor der obersten Zeile"
+
+#: syntax.c:3369
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Syntax Synchronisations-Elemente ---"
+
+#: syntax.c:3374
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"Synchronisation an Elementen"
+
+#: syntax.c:3380
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Satzbau Elemente ---"
+
+#: syntax.c:3403
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: Kein solches Syntax-Cluster: %s"
+
+#: syntax.c:3429
+msgid "minimal "
+msgstr "minimal "
+
+#: syntax.c:3436
+msgid "maximal "
+msgstr "maximal "
+
+#: syntax.c:3448
+msgid "; match "
+msgstr "; Treffer "
+
+#: syntax.c:3450
+msgid " line breaks"
+msgstr " Zeilen-Umbrüche"
+
+#: syntax.c:4078
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: \"group[t]here\" ist an dieser Stelle ungültig"
+
+#: syntax.c:4102
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: \"region\"-Element für \"%s\" konnte nicht gefunden werden"
+
+#: syntax.c:4130
+msgid "E395: contains argument not accepted here"
+msgstr "E395: \"contains\"-Argument ist an dieser Stelle ungültig"
+
+#: syntax.c:4141
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: \"containedin\"-Argument ist an dieser Stelle ungültig"
+
+#: syntax.c:4219
+msgid "E397: Filename required"
+msgstr "E397: Dateiname wird benötigt"
+
+#: syntax.c:4557
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Fehlendes '=': %s"
+
+#: syntax.c:4715
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Nicht ausreichend viele Argumente: syntax region %s"
+
+#: syntax.c:5046
+msgid "E400: No cluster specified"
+msgstr "E400: Kein Cluster angegeben"
+
+#: syntax.c:5083
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Muster Abgrenzer nicht gefunden: %s"
+
+#: syntax.c:5158
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Schrott nach Muster: %s"
+
+#: syntax.c:5245
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: syntax sync: Zeilen Fortsetzungs Muster zweifach angegeben"
+
+#: syntax.c:5302
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Unzulässige Argumente; %s"
+
+#: syntax.c:5352
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Gleichheitszeichen fehlt: %s"
+
+#: syntax.c:5358
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Leeres Argument: %s"
+
+#: syntax.c:5385
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s ist hier nicht erlaubt"
+
+#: syntax.c:5392
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr ""
+"E408: %s muss als Erstes in der Liste der enthaltenen Elemente auftreten"
+
+#: syntax.c:5462
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Unbekannter Gruppen-Name: %s"
+
+#: syntax.c:5692
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Ungültiger :syntax Befehl: %s"
+
+#: syntax.c:6071
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: Hervorhebungs-Gruppe nicht gefunden: %s"
+
+#: syntax.c:6095
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Nicht ausreichend viele Argumente: \":highlight link %s\""
+
+#: syntax.c:6102
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E412: Zu viele Argumente: \":highlight link %s\""
+
+#: syntax.c:6122
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: Gruppe hat Einstellungen, Unterstreichungs Link ignoriert"
+
+#: syntax.c:6251
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: unerwartetes Gleichheitszeichen: %s"
+
+#: syntax.c:6287
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: fehlendes Gleichheitszeichen: %s"
+
+#: syntax.c:6309
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: fehlendes Argument: %s"
+
+#: syntax.c:6346
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: Unzulässiger Wert: %s"
+
+#: syntax.c:6465
+msgid "E419: FG color unknown"
+msgstr "E419: FG Farbe unbekannt"
+
+#: syntax.c:6476
+msgid "E420: BG color unknown"
+msgstr "E420: BG Farbe unbekannt"
+
+#: syntax.c:6537
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Unbekannte Farb-Bezeichnung oder -Nummer: %s"
+
+#: syntax.c:6745
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: Terminal-Code zu lang: %s"
+
+#: syntax.c:6792
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: Unzulässiges Argument: %s"
+
+#: syntax.c:7321
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: Zu viele verschieden Hervorhebungs-Attribute in Gebrauch"
+
+#: tag.c:90
+msgid "at bottom of tag stack"
+msgstr "am Anfang der Tag-Liste"
+
+#: tag.c:91
+msgid "at top of tag stack"
+msgstr "am Ende der Tag-Liste"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Kann nicht vor den ersten passenden Tag hinausgehen"
+
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: Tag \"%s\" konnte nicht gefunden werden"
+
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr " # pri verw. tag"
+
+#: tag.c:548
+msgid "file\n"
+msgstr "Datei\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Gewünschte Nummer (abbrechen mit <CR>): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: Es gibt nur einen passenden Tag"
+
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Kann nicht über den letzten passenden Tag hinausgehen"
+
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Die Datei \"%s\" existiert nicht"
+
+#. Give an indication of the number of matching tags
+#: tag.c:780
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "Tag %d aus %d%s"
+
+#: tag.c:783
+msgid " or more"
+msgstr " oder mehr"
+
+#: tag.c:785
+msgid " Using tag with different case!"
+msgstr " Verwendung eines Tags mit abgewandelter Groß/Klein-Schreibung"
+
+#: tag.c:828
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Die Datei \"%s\" existiert nicht"
+
+#. Highlight title
+#: tag.c:897
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # NACH TAG VON Zeile in Datei/Text"
+
+#: tag.c:1144
+msgid "Linear tag search"
+msgstr "Lineare Tag-Suche"
+
+#: tag.c:1146
+msgid "Binary tag search"
+msgstr "Binäre Tag-Suche"
+
+#: tag.c:1172
+#, c-format
+msgid "Searching tags file %s"
+msgstr "tags file %s wird durchsucht"
+
+#: tag.c:1356
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Tag-Dateipfad wurde abgeschnitten für %s\n"
+
+#: tag.c:1847
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Format Fehler in Tag-Datei \"%s\""
+
+#: tag.c:1851
+#, c-format
+msgid "Before byte %ld"
+msgstr "vor byte %ld"
+
+#: tag.c:1872
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Tag-Datei ist nicht sortiert: %s"
+
+#. never opened any tags file
+#: tag.c:1911
+msgid "E433: No tags file"
+msgstr "E433: Keine Tag-Datei"
+
+#: tag.c:2583
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Tag-Muster kann nicht gefunden werden"
+
+#: tag.c:2594
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Tag konnte nicht gefunden werden, das ist nur eine Vermutung!"
+
+#: term.c:1737
+msgid "' not known. Available builtin terminals are:"
+msgstr ""
+"' nicht bekannt. Zur Verfügung stehen die folgenden eingebauten Terminals:"
+
+#: term.c:1761
+msgid "defaulting to '"
+msgstr "Voreinstellung '"
+
+#: term.c:2114
+msgid "Cannot open termcap file"
+msgstr "termpcap-Datei kann nicht geöffnet werden"
+
+#: term.c:2117
+msgid "Terminal entry not found in terminfo"
+msgstr "Terminal-Eintrag konnte in der terminfo-Datei nicht gefunden werden"
+
+#: term.c:2119
+msgid "Terminal entry not found in termcap"
+msgstr "Terminal-Eintrag konnte in der termcap-Datei nicht gefunden werden"
+
+#: term.c:2278
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Kein \"%s\" Eintrag in termcap"
+
+#: term.c:2752
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: Terminal-Fähigkeit \"cm\" wird benötigt"
+
+#. Highlight title
+#: term.c:4891
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Terminal Tasten ---"
+
+#: ui.c:251
+msgid "new shell started\n"
+msgstr "neue Shell gestartet\n"
+
+#: ui.c:1747
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: Fehler beim Lesen der Eingabe, Abbruch...\n"
+
+# TODO: need more work!
+#. must display the prompt
+#: undo.c:383
+msgid "No undo possible; continue anyway"
+msgstr "Rückgängigmachung nicht möglich; setze trotz dem fort"
+
+#: undo.c:538
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: Zeilennummer falsch"
+
+#: undo.c:707
+msgid "1 change"
+msgstr "1 Änderung"
+
+#: undo.c:709
+#, c-format
+msgid "%ld changes"
+msgstr "%ld Änderungen"
+
+#: undo.c:753
+msgid "E439: undo list corrupt"
+msgstr "E439: Rückgangbarkeitsliste kaputt"
+
+#: undo.c:785
+msgid "E440: undo line missing"
+msgstr "E440: Rückgangbarkeitsliste fehlt"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:691
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 16/32 Bit GUI Version"
+
+#: version.c:693
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 32 Bit GUI Version"
+
+#: version.c:696
+msgid " in Win32s mode"
+msgstr " in Win32s Modus"
+
+#: version.c:698
+msgid " with OLE support"
+msgstr " mit OLE Unterstützung"
+
+#: version.c:701
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"MS-Windows 32 Bit Konsolen Version"
+
+#: version.c:705
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"MS-Windows 16 Bit Version"
+
+#: version.c:709
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 Bit MS-DOS Version"
+
+#: version.c:711
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 Bit MS-DOS Version"
+
+#: version.c:717
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) Version"
+
+#: version.c:719
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X Version"
+
+#: version.c:722
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS Version"
+
+#: version.c:727
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS Version"
+
+#: version.c:737
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Inclusive der Korrekturen: "
+
+#: version.c:763 version.c:1098
+msgid "Modified by "
+msgstr "Verändert von "
+
+#: version.c:770
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Übersetzt "
+
+#: version.c:773
+msgid "by "
+msgstr "von "
+
+#: version.c:785
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Monster Version "
+
+#: version.c:788
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Große Version "
+
+#: version.c:791
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Normale Version "
+
+#: version.c:794
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Kleine Version "
+
+#: version.c:796
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Winzige Version "
+
+#: version.c:802
+msgid "without GUI."
+msgstr "ohne GUI."
+
+#: version.c:806
+msgid "with GTK-GNOME GUI."
+msgstr "mit GTK-GNOME GUI."
+
+#: version.c:808
+msgid "with GTK GUI."
+msgstr "mit GTK GUI."
+
+#: version.c:812
+msgid "with X11-Motif GUI."
+msgstr "mit X11-Motif GUI."
+
+#: version.c:815
+msgid "with X11-Athena GUI."
+msgstr "mit X11-Athena GUI."
+
+#: version.c:818
+msgid "with BeOS GUI."
+msgstr "mit BeOS GUI."
+
+#: version.c:821
+msgid "with Photon GUI."
+msgstr "mit Photon GUI."
+
+#: version.c:824
+msgid "with GUI."
+msgstr "mit GTK."
+
+#: version.c:827
+msgid "with Carbon GUI."
+msgstr "mit Carbon GUI."
+
+#: version.c:830
+msgid "with Cocoa GUI."
+msgstr "mit Cocoa GUI."
+
+#: version.c:833
+msgid "with (classic) GUI."
+msgstr "mit (klassischem) GUI."
+
+#: version.c:844
+msgid " Features included (+) or not (-):\n"
+msgstr " Ein- (+) oder ausschließlich (-) der Eigenschaften:\n"
+
+#: version.c:856
+msgid " system vimrc file: \""
+msgstr " System-vimrc-Datei: \""
+
+#: version.c:861
+msgid " user vimrc file: \""
+msgstr " Benutzer-vimrc-Datei: \""
+
+#: version.c:866
+msgid " 2nd user vimrc file: \""
+msgstr " zweite Benutzer-vimrc-Datei: \""
+
+#: version.c:871
+msgid " 3rd user vimrc file: \""
+msgstr " dritte Benutzer-vimrc-Datei: \""
+
+#: version.c:876
+msgid " user exrc file: \""
+msgstr " Benutzer-exrc-Datei: \""
+
+#: version.c:881
+msgid " 2nd user exrc file: \""
+msgstr " zweite Benutzer-vimrc-Datei: \""
+
+#: version.c:887
+msgid " system gvimrc file: \""
+msgstr " System-gvimrc-Datei: \""
+
+#: version.c:891
+msgid " user gvimrc file: \""
+msgstr " Benutzer-gvimrc-Datei: \""
+
+#: version.c:895
+msgid "2nd user gvimrc file: \""
+msgstr "zweite Benutzer-gvimrc-Datei: \""
+
+#: version.c:900
+msgid "3rd user gvimrc file: \""
+msgstr "dritte Benutzer-gvimrc-Datei: \""
+
+#: version.c:907
+msgid " system menu file: \""
+msgstr " System-Menü-Datei: \""
+
+#: version.c:915
+msgid " fall-back for $VIM: \""
+msgstr " Voreinstellung für $VIM: \""
+
+#: version.c:921
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " und für $VIMRUNTIME: \""
+
+#: version.c:925
+msgid "Compilation: "
+msgstr "Übersetzt: "
+
+#: version.c:931
+msgid "Compiler: "
+msgstr "Compiler: "
+
+#: version.c:936
+msgid "Linking: "
+msgstr "Linken: "
+
+#: version.c:941
+msgid " DEBUG BUILD"
+msgstr " DEBUG-VERSION"
+
+#: version.c:977
+msgid "VIM - Vi IMproved"
+msgstr "VIM - verbesserter Vi"
+
+#: version.c:979
+msgid "version "
+msgstr "Version "
+
+#: version.c:980
+msgid "by Bram Moolenaar et al."
+msgstr "von Bram Moolenaar und Anderen"
+
+#: version.c:984
+msgid "Vim is open source and freely distributable"
+msgstr "Vim ist Open Source und kann frei weitergegeben werden"
+
+#: version.c:986
+msgid "Help poor children in Uganda!"
+msgstr "Helfen Sie armen Kindern in Uganda!"
+
+#: version.c:987
+msgid "type :help iccf<Enter> for information "
+msgstr "tippe :help iccf<Enter> für Informationen darüber "
+
+#: version.c:989
+msgid "type :q<Enter> to exit "
+msgstr "tippe :q<Enter> zum Beenden "
+
+#: version.c:990
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "tippe :help<Enter> oder <F1> für Online Hilfe "
+
+#: version.c:991
+msgid "type :help version6<Enter> for version info"
+msgstr "tippe :help version6<Enter> für Versions-Informationen"
+
+#: version.c:994
+msgid "Running in Vi compatible mode"
+msgstr "Vi kompatible Einstellung"
+
+#: version.c:995
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "tippe :set nocp<Enter> für Vim-Voreinstellungen "
+
+#: version.c:996
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "tippe :help cp-default<Enter> für Informationen darüber "
+
+#: version.c:1011
+msgid "menu Help->Orphans for information "
+msgstr "Menü Hilfe->Waisen für Informationen darüber "
+
+#: version.c:1013
+msgid "Running modeless, typed text is inserted"
+msgstr "Mode-freier Betrieb, getippter Text wird eingefügt"
+
+#: version.c:1014
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "Menü Editieren->Globale Einstellung->Einfüge-Modus ein- und ausschalten "
+
+#: version.c:1015
+msgid " for two modes "
+msgstr " für zwei Modi "
+
+#: version.c:1019
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "Menü Editieren->Globale Einstellung->Vi-Kompatibilität ein- und ausschalten"
+
+#: version.c:1020
+msgid " for Vim defaults "
+msgstr " für Vim Voreinstellungen "
+
+#: version.c:1066
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "ACHTUNG: Windows 95/98/ME wurde erkannt"
+
+#: version.c:1069
+msgid "type :help windows95<Enter> for info on this"
+msgstr "tippe :help windows95<Enter> für Informationen darüber "
+
+#: window.c:201
+msgid "E441: There is no preview window"
+msgstr "E441: Es gibt kein Fenster zur Voransicht"
+
+# should read: topleft / botright
+#: window.c:580
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: topleft und botright können nicht gleichzeitig verwendet werden"
+
+#: window.c:1339
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Rotieren nicht möglich wenn ein anderes Fenster geteilt ist"
+
+#: window.c:1841
+msgid "E444: Cannot close last window"
+msgstr "E444: Letztes Fenster kann nicht geschlossen werden"
+
+#: window.c:2505
+msgid "Already only one window"
+msgstr "Bereits nur ein Fenster"
+
+#: window.c:2552
+msgid "E445: Other window contains changes"
+msgstr "E445: Anderes Fenster enthält Änderungen"
+
+# Cursor: Schreibmarke Positionsmarke
+#: window.c:4379
+msgid "E446: No file name under cursor"
+msgstr "E446: Kein Dateiname unter dem Cursor"
+
+#: window.c:4498
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Datei \"%s\" kann im Pfad nicht gefunden werden"
+
+#: ../GvimExt/gvimext.cpp:586
+msgid "Edit with &multiple Vims"
+msgstr "Editiere mit &mehreren Vims"
+
+#: ../GvimExt/gvimext.cpp:592
+msgid "Edit with single &Vim"
+msgstr "Editiere mit einem &Vim"
+
+#: ../GvimExt/gvimext.cpp:604
+msgid "Edit with &Vim"
+msgstr "Editiere mit &Vim"
+
+#. Now concatenate
+#: ../GvimExt/gvimext.cpp:628
+msgid "Edit with existing Vim - &"
+msgstr "Editiere mit existierendem Vim - &"
+
+#: ../GvimExt/gvimext.cpp:752
+msgid "Edits the selected file(s) with Vim"
+msgstr "Editiere die ausgewählten Datei(en) mit Vim"
+
+#: ../GvimExt/gvimext.cpp:891 ../GvimExt/gvimext.cpp:969
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "Fehler beim Starten des Prozesses: Ist gvim im Pfad?"
+
+#: ../GvimExt/gvimext.cpp:892 ../GvimExt/gvimext.cpp:906
+#: ../GvimExt/gvimext.cpp:970
+msgid "gvimext.dll error"
+msgstr "gvimext.dll Fehler"
+
+#: ../GvimExt/gvimext.cpp:905
+msgid "Path length too long!"
+msgstr "Pfad-Länge zu lang!"
+
+#: globals.h:900
+msgid "--No lines in buffer--"
+msgstr "--Keine Zeilen im Puffer--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1048
+msgid "Command aborted"
+msgstr "Befehl abgebrochen"
+
+#: globals.h:1049
+msgid "Argument required"
+msgstr "Argument wird benötigt"
+
+#: globals.h:1050
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ sollte von /, ? or & gefolgt werden"
+
+#: globals.h:1052
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr ""
+"E11: Ungültig im Kommando-Zeilen Fenster; <CR> führt aus, CTRL-C beendet"
+
+#: globals.h:1054
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Befehl nicht zulässig vom exrc/vimrc in der momentanen Verzeichnis- "
+"oder Tag-Suche"
+
+#: globals.h:1055
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Datei existiert bereits (erzwinge durch !)"
+
+#: globals.h:1056
+msgid "Command failed"
+msgstr "Befehl schlug fehl"
+
+#: globals.h:1057
+msgid "Internal error"
+msgstr "Interner Fehler"
+
+#: globals.h:1058
+msgid "Interrupted"
+msgstr "Unterbrochen"
+
+#: globals.h:1059
+msgid "E14: Invalid address"
+msgstr "E14: Ungültige Adresse"
+
+#: globals.h:1060
+msgid "Invalid argument"
+msgstr "Ungültiges Argument"
+
+#: globals.h:1061
+#, c-format
+msgid "Invalid argument: %s"
+msgstr "Ungültiges Argument: %s"
+
+#: globals.h:1063
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: ungültiger Ausdruck: %s"
+
+#: globals.h:1065
+msgid "E16: Invalid range"
+msgstr "E16: Ungültiger Bereich"
+
+#: globals.h:1066
+msgid "Invalid command"
+msgstr "Ungültiger Befehls-Name"
+
+#: globals.h:1068
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" ist ein Verzeichnis"
+
+#: globals.h:1071
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Unerwartetes Zeichen vor '='"
+
+#: globals.h:1073
+msgid "E19: Mark has invalid line number"
+msgstr "E19: Marke hat ungültige Zeilennummer"
+
+#: globals.h:1074
+msgid "E20: Mark not set"
+msgstr "E20: Marke nicht gesetzt"
+
+#: globals.h:1075
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Kann keine Änderungen machen, 'modifiable' ist aus"
+
+#: globals.h:1076
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Skript-Schachtelung zu tief"
+
+#: globals.h:1077
+msgid "E23: No alternate file"
+msgstr "E23: Keine alternative Datei"
+
+#: globals.h:1078
+msgid "E24: No such abbreviation"
+msgstr "E24: Keine Abkürzung gefunden"
+
+#: globals.h:1079
+msgid "No ! allowed"
+msgstr "! nicht erlaubt"
+
+#: globals.h:1081
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr ""
+"E25: GUI kann nicht benutzt werden: wurde zum Zeitpunkt des Übersetzens "
+"nicht eingeschaltet."
+
+#: globals.h:1084
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr ""
+"E26: Hebräisch kann nicht benutzt werden: wurde zum Zeitpunkt des "
+"Übersetzens nicht eingeschaltet.\n"
+
+#: globals.h:1087
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr ""
+"E27: Farsi kann nicht benutzt werden: wurde zum Zeitpunkt des Übersetzens "
+"nicht eingeschaltet.\n"
+
+#: globals.h:1090
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Hervorhebungs-Gruppe existiert nicht: %s"
+
+#: globals.h:1092
+msgid "E29: No inserted text yet"
+msgstr "E29: Noch kein eingefügter Text"
+
+#: globals.h:1093
+msgid "E30: No previous command line"
+msgstr "E30: Keine vorherige Befehlszeile"
+
+#: globals.h:1094
+msgid "E31: No such mapping"
+msgstr "E31: Keine Zuordnung gefunden"
+
+#: globals.h:1095
+msgid "No match"
+msgstr "Kein Treffer"
+
+#: globals.h:1096
+#, c-format
+msgid "No match: %s"
+msgstr "Kein Treffer für: %s"
+
+#: globals.h:1097
+msgid "E32: No file name"
+msgstr "E32: Kein Dateiname"
+
+#: globals.h:1098
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: Kein vorheriger regulärer Ersetzungs-Ausdruck"
+
+#: globals.h:1099
+msgid "E34: No previous command"
+msgstr "E34: Kein vorheriger Befehl"
+
+#: globals.h:1100
+msgid "E35: No previous regular expression"
+msgstr "E35: Keine vorheriger regulärer Ausdruck"
+
+#: globals.h:1101
+msgid "No range allowed"
+msgstr "Bereich unzulässig"
+
+#: globals.h:1103
+msgid "E36: Not enough room"
+msgstr "E36: zu wenig Platz"
+
+#: globals.h:1105
+#, c-format
+msgid "Can't create file %s"
+msgstr "Datei kann nicht erzeugt werden: %s"
+
+#: globals.h:1106
+msgid "Can't get temp file name"
+msgstr "temp-Datei kann nicht erzeugt werden"
+
+#: globals.h:1107
+#, c-format
+msgid "Can't open file %s"
+msgstr "Datei %s kann nicht geöffnet werden"
+
+#: globals.h:1108
+#, c-format
+msgid "Can't read file %s"
+msgstr "Datei %s kann nicht gelesen werden"
+
+#: globals.h:1109
+msgid "E37: No write since last change (use ! to override)"
+msgstr ""
+"E37: seit der letzten Änderung wurde nicht geschrieben (erzwinge mit !)"
+
+#: globals.h:1110
+msgid "E38: Null argument"
+msgstr "E38: Null-Argument"
+
+#: globals.h:1112
+msgid "E39: Number expected"
+msgstr "E39: Nummer erwartet"
+
+#: globals.h:1115
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Fehler-Datei %s kann nicht geöffnet werden"
+
+#: globals.h:1118
+msgid "E41: Out of memory!"
+msgstr "E41: Speicher erschöpft!"
+
+#: globals.h:1121
+msgid "Pattern not found"
+msgstr "Muster nicht gefunden"
+
+#: globals.h:1123
+#, c-format
+msgid "Pattern not found: %s"
+msgstr "Muster nicht gefunden: %s"
+
+#: globals.h:1124
+msgid "Argument must be positive"
+msgstr "Argument muss positiv sein"
+
+#: globals.h:1126
+msgid "E42: No Errors"
+msgstr "E42: Kein Fehler"
+
+#: globals.h:1128
+msgid "E43: Damaged match string"
+msgstr "E43: Beschädigter Suchausdruck"
+
+#: globals.h:1129
+msgid "E44: Corrupted regexp program"
+msgstr "E44: schadhaftes regexp Programm"
+
+#: globals.h:1130
+msgid "E45: 'readonly' option is set (use ! to override)"
+msgstr ""
+"E45: Die Schreibschutz-Option 'readonly' ist gesetzt (erzwinge durch !)"
+
+#: globals.h:1132
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Variable \"%s\" kann nur gelesen werden"
+
+#: globals.h:1135
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Fehler während des Lesens der Fehler-Datei"
+
+#: globals.h:1138
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: In einer Sandbox nicht erlaubt"
+
+#: globals.h:1140
+msgid "E49: Invalid scroll size"
+msgstr "E49: Ungültige Scroll-Größe"
+
+#: globals.h:1141
+msgid "E91: 'shell' option is empty"
+msgstr "E91: Die Option 'shell' ist leer"
+
+#: globals.h:1142
+msgid "E72: Close error on swap file"
+msgstr "E72: Fehler beim Schließen der Auslagerungs-Datei"
+
+#: globals.h:1143
+msgid "E73: tag stack empty"
+msgstr "E73: tag Stapel leer."
+
+#: globals.h:1144
+msgid "E74: Command too complex"
+msgstr "E74: Befehl zu kompliziert"
+
+#: globals.h:1145
+msgid "E75: Name too long"
+msgstr "E75: Name zu lang"
+
+#: globals.h:1146
+msgid "E76: Too many ["
+msgstr "E76: zu viele ["
+
+#: globals.h:1147
+msgid "E77: Too many file names"
+msgstr "E77: zu viele Datei-Namen"
+
+#: globals.h:1148
+msgid "Trailing characters"
+msgstr "Überschüssige Zeichen"
+
+#: globals.h:1149
+msgid "E78: Unknown mark"
+msgstr "E78: Unbekannte Mark"
+
+#: globals.h:1150
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Kann \"wildcards\" nicht erweitern"
+
+#: globals.h:1151
+msgid "E80: Error while writing"
+msgstr "E80: Fehler während des Schreibens"
+
+#: globals.h:1152
+msgid "Zero count"
+msgstr "Null-Zähler"
+
+#: globals.h:1154
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: <SID> wurde nicht in einer Skript-Umgebung benutzt"
+
+#: globals.h:1157
+msgid "E449: Invalid expression received"
+msgstr "E449: ungültiger Ausdruck"
diff --git a/src/po/en_GB.po b/src/po/en_GB.po
new file mode 100644
index 000000000..152092a54
--- /dev/null
+++ b/src/po/en_GB.po
@@ -0,0 +1,48 @@
+# UK English Translation for Vim vim:set foldmethod=marker:
+#
+# Do ":help uganda" in Vim to read copying and usage conditions.
+# Do ":help credits" in Vim to see a list of people who contributed.
+#
+# FIRST AUTHOR Mike Williams <mrw@eandem.co.uk>, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim(UK English)\n"
+"POT-Creation-Date: 2003-02-23 10:27+0000\n"
+"PO-Revision-Date: 2003-02-25 11:05+0000\n"
+"Last-Translator: Mike Williams <mrw@eandem.co.uk>\n"
+"Language-Team: Mike Williams <mrw@eandem.co.uk>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO_8859-1\n"
+"Content-Transfer-Encoding: 7bit\n"
+
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Cannot find colour scheme %s"
+
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: Cannot allocate colour %s"
+
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: Cannot allocate colourmap entry, some colours may be incorrect"
+
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <colour>\tUse <colour> for the background (also: -bg)"
+
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <colour>\tUse <colour> for normal text (also: -fg)"
+
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "Messages maintainer: Mike Williams <mrw@eandem.co.uk>"
+
+msgid "E419: FG color unknown"
+msgstr "E419: FG colour unknown"
+
+msgid "E420: BG color unknown"
+msgstr "E420: BG colour unknown"
+
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Colour name or number not recognised: %s"
diff --git a/src/po/es.po b/src/po/es.po
new file mode 100644
index 000000000..24fdec1bf
--- /dev/null
+++ b/src/po/es.po
@@ -0,0 +1,6780 @@
+# Spanish translation for Vim vim:set foldmethod=marker:
+#
+# Do ":help uganda" in Vim to read copying and usage conditions.
+# Do ":help credits" in Vim to see a list of people who contributed.
+#
+# FIRST AUTHOR Eduardo F. Amatria <eferna1@platea.pntic.mec.es>, 2001.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim 6.3a.16 (Español)\n"
+"Report-Msgid-Bugs-To: Alejandro López-Valencia <dradul@yahoo.com>\n"
+"POT-Creation-Date: 2004-05-12 18:38-0500\n"
+"PO-Revision-Date: 2004-05-12 20:34-0500\n"
+"Last-Translator: Alejandro López-Valencia <dradul@yahoo.com>\n"
+"Language-Team: Alejandro López-Valencia <dradul@yahoo.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: buffer.c:102
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: No se puede asignar memoria para ningún «buffer», saliendo..."
+
+#: buffer.c:105
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: No se puede asignar memoria para el «buffer», usando otro..."
+
+#: buffer.c:805
+msgid "E515: No buffers were unloaded"
+msgstr "E515: No se descargó ningún «buffer»."
+
+#: buffer.c:807
+msgid "E516: No buffers were deleted"
+msgstr "E516: No se borró ningún «buffer»."
+
+#: buffer.c:809
+msgid "E517: No buffers were wiped out"
+msgstr "E517: No se eliminó ningún «buffer»."
+
+#: buffer.c:817
+msgid "1 buffer unloaded"
+msgstr "Un «buffer» descargado."
+
+#: buffer.c:819
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "%d «buffers» descargados."
+
+#: buffer.c:824
+msgid "1 buffer deleted"
+msgstr "Un «buffer» suprimido."
+
+#: buffer.c:826
+#, c-format
+msgid "%d buffers deleted"
+msgstr "%d «buffers» suprimidos."
+
+#: buffer.c:831
+msgid "1 buffer wiped out"
+msgstr "1 «buffer» eliminado."
+
+#: buffer.c:833
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "%d «buffers» eliminados."
+
+#: buffer.c:894
+msgid "E84: No modified buffer found"
+msgstr "E84: No he encontrado ningún «buffer» modificado."
+
+#. back where we started, didn't find anything.
+#: buffer.c:933
+msgid "E85: There is no listed buffer"
+msgstr "E85: No hay «buffers» en la lista."
+
+#: buffer.c:945
+#, c-format
+msgid "E86: Buffer %ld does not exist"
+msgstr "E86: El «buffer» %ld no existe."
+
+#: buffer.c:948
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: No puedo ir más allá del último «buffer»."
+
+#: buffer.c:950
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: No puedo ir más atrás del primer buffer."
+
+#: buffer.c:988
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr ""
+"E89: No ha guardado el fichero desde el último cambio del «buffer» %ld "
+"(añada ! para forzar)."
+
+#: buffer.c:1005
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: No se puede descargar el último buffer."
+
+#: buffer.c:1538
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Advertencia: lista de nombres de ficheros demasiado larga."
+
+#: buffer.c:1709
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: No se ha encontrado el buffer %ld"
+
+#: buffer.c:1940
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Más de una coincidencia con %s."
+
+#: buffer.c:1942
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: No hay un buffer que coincida con %s."
+
+#: buffer.c:2337
+#, c-format
+msgid "line %ld"
+msgstr "línea %ld"
+
+#: buffer.c:2420
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Ya existe un buffer con este nombre."
+
+#: buffer.c:2713
+msgid " [Modified]"
+msgstr " [Modificado]"
+
+#: buffer.c:2718
+msgid "[Not edited]"
+msgstr "[Sin editar]"
+
+#: buffer.c:2723
+msgid "[New file]"
+msgstr "[Fichero nuevo]"
+
+#: buffer.c:2724
+msgid "[Read errors]"
+msgstr "[Errores de lectura]"
+
+#: buffer.c:2726 fileio.c:2112
+msgid "[readonly]"
+msgstr "[Sólo lectura]"
+
+#: buffer.c:2747
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 línea --%d%%--"
+
+#: buffer.c:2749
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld líneas --%d%%--"
+
+#: buffer.c:2756
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "línea %ld de %ld --%d%%-- col "
+
+#: buffer.c:2864
+msgid "[No file]"
+msgstr "[Sin fichero]"
+
+# must be a help buffer
+#. must be a help buffer
+#: buffer.c:2904
+msgid "help"
+msgstr "ayuda"
+
+#: buffer.c:3463 screen.c:5075
+msgid "[help]"
+msgstr "[ayuda]"
+
+#: buffer.c:3495 screen.c:5081
+msgid "[Preview]"
+msgstr "[Vista previa]"
+
+#: buffer.c:3775
+msgid "All"
+msgstr "Todo"
+
+#: buffer.c:3775
+msgid "Bot"
+msgstr "Final"
+
+#: buffer.c:3777
+msgid "Top"
+msgstr "Comienzo"
+
+#: buffer.c:4523
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# Lista de «buffers»:\n"
+
+#: buffer.c:4556
+msgid "[Error List]"
+msgstr "[Lista de errores]"
+
+#: buffer.c:4569 memline.c:1520
+msgid "[No File]"
+msgstr "[Sin fichero]"
+
+#: buffer.c:4882
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Signos ---"
+
+#: buffer.c:4901
+#, c-format
+msgid "Signs for %s:"
+msgstr "Signos para %s"
+
+#: buffer.c:4907
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " línea=%ld id=%d nombre=%s"
+
+#: diff.c:139
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: No puedo usar «diff» con más de %ld «buffers»."
+
+#: diff.c:713
+msgid "E97: Cannot create diffs"
+msgstr "E97: No puedo crear «diffs»."
+
+#: diff.c:818
+msgid "Patch file"
+msgstr "Fichero de parches."
+
+#: diff.c:1069
+msgid "E98: Cannot read diff output"
+msgstr "E98: no puedo leer la salida de «diff»."
+
+#: diff.c:1819
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: El «buffer» actual no está en modo «diff»."
+
+#: diff.c:1831
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: Ningún otro «buffer» está en modo «diff»."
+
+#: diff.c:1839
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: Más de dos «buffers» en modo «diff», no se cual usar."
+
+#: diff.c:1862
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: No puedo encontrar el «buffer» «%s»."
+
+#: diff.c:1868
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: El «buffer» «%s» no está en modo «diff»."
+
+#: digraph.c:2199
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: El código de escape no se permite en un dígrafo."
+
+#: digraph.c:2384
+msgid "E544: Keymap file not found"
+msgstr "E544: No encontré el fichero «keymap»."
+
+#: digraph.c:2411
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: «:loadkeymap» en un fichero que no contiene instrucciones ejecutables."
+
+#: edit.c:40
+msgid " Keyword completion (^N^P)"
+msgstr " Completar palabra clave (^N^P)."
+
+# ctrl_x_mode == 0, ^P/^N compl.
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E^Y^L^]^F^I^K^D^V^N^P)"
+msgstr " modo ^X (^E^Y^L^]^F^I^K^D^V^N^P)."
+
+# Scroll has it's own msgs, in it's place there is the msg for local
+# * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N^P)"
+msgstr " Completar palabra clave local (^N^P)."
+
+#: edit.c:45
+msgid " Whole line completion (^L^N^P)"
+msgstr " Completar toda la línea (^L^N^P)."
+
+#: edit.c:46
+msgid " File name completion (^F^N^P)"
+msgstr " Completar nombre de fichero (^F^N^P)."
+
+#: edit.c:47
+msgid " Tag completion (^]^N^P)"
+msgstr " Completar «tag» (^]^N^P)."
+
+#: edit.c:48
+msgid " Path pattern completion (^N^P)"
+msgstr " Completar patrón de ruta (^N^P)."
+
+#: edit.c:49
+msgid " Definition completion (^D^N^P)"
+msgstr " Completar definición (^D^N^P)."
+
+#: edit.c:51
+msgid " Dictionary completion (^K^N^P)"
+msgstr " Completar diccionario (^K^N^P)."
+
+#: edit.c:52
+msgid " Thesaurus completion (^T^N^P)"
+msgstr " Completar diccionario de sinónimos (^T^N^P)."
+
+#: edit.c:53
+msgid " Command-line completion (^V^N^P)"
+msgstr " Completar línea de comandos (^V^N^P)."
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "He llegado al final del párrafo."
+
+#: edit.c:962
+msgid "'thesaurus' option is empty"
+msgstr "La opción «thesaurus» está vacía."
+
+#: edit.c:1166
+msgid "'dictionary' option is empty"
+msgstr "La opción «dictionary» está vacía."
+
+#: edit.c:2162
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Buscando en el diccionario: %s."
+
+#: edit.c:2368
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (insertar) «Scroll» (^E/^Y)."
+
+#: edit.c:2370
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (reemplazar) «Scroll» (^E/^Y)."
+
+#: edit.c:2684
+#, c-format
+msgid "Scanning: %s"
+msgstr "Buscando: %s."
+
+#: edit.c:2719
+msgid "Scanning tags."
+msgstr "Buscando «tags»."
+
+#: edit.c:3381
+msgid " Adding"
+msgstr "Añadiendo."
+
+# showmode might reset the internal line pointers, so it must
+# * be called before line = ml_get(), or when this address is no
+# * longer needed. -- Acevedo.
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3430
+msgid "-- Searching..."
+msgstr "-- Buscando..."
+
+#: edit.c:3486
+msgid "Back at original"
+msgstr "De vuelta al original."
+
+#: edit.c:3491
+msgid "Word from other line"
+msgstr "Palabra de otra línea."
+
+#: edit.c:3496
+msgid "The only match"
+msgstr "La única coincidencia."
+
+#: edit.c:3555
+#, c-format
+msgid "match %d of %d"
+msgstr "coincidencia %d de %d."
+
+#: edit.c:3558
+#, c-format
+msgid "match %d"
+msgstr "coincidencia %d."
+
+# Skip further arguments but do continue to
+# * search for a trailing command.
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:1024
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Variable desconocida: «%s»."
+
+#: eval.c:1320
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Faltan llaves: %s."
+
+#: eval.c:1435 eval.c:1449
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: No existe tal variable: «%s»."
+
+#: eval.c:1705
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Falta «:» después de «?»."
+
+#: eval.c:2327
+msgid "E110: Missing ')'"
+msgstr "E110: Falta un «)»."
+
+#: eval.c:2389
+msgid "E111: Missing ']'"
+msgstr "E111: Falta un «]»."
+
+#: eval.c:2466
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Falta el nombre de la opción: %s."
+
+#: eval.c:2484
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Opción desconocida: %s."
+
+#: eval.c:2555
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Faltan comillas: %s."
+
+#: eval.c:2698
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Faltan comillas: %s."
+
+#: eval.c:3054
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Argumentos no válidos para la función %s."
+
+#: eval.c:3083
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Función desconocida: %s."
+
+#: eval.c:3084
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: Demasiados argumentos para la función: %s."
+
+#: eval.c:3085
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Argumentos insuficientes para la función: %s."
+
+#: eval.c:3086
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: Usando <SID> en un contexto que no es de «script»: %s."
+
+# * Yes this is ugly, I don't particularly like it either. But doing it
+# * this way has the compelling advantage that translations need not to
+# * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3687 gui.c:4382 gui_gtk.c:2059
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:4226
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld líneas: "
+
+#: eval.c:5477
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&Aceptar\n"
+"&Cancelar"
+
+#: eval.c:5517
+msgid "called inputrestore() more often than inputsave()"
+msgstr "He llamado a «inputrestore()» más veces que a «inputsave()»."
+
+#: eval.c:5977
+msgid "E655: Too many symbolic links (cycle?)"
+msgstr "E655: Hay demasiados enlaces symbólicos (¿referencia circular?)"
+
+#: eval.c:6609
+msgid "E240: No connection to Vim server"
+msgstr "E240: Sin conexión al servidor Vim."
+
+#: eval.c:6706
+msgid "E277: Unable to read a server reply"
+msgstr "E277: Incapaz de leer una respuesta del servidor."
+
+#: eval.c:6734
+msgid "E258: Unable to send to client"
+msgstr "E258: Incapaz de enviar al cliente."
+
+#: eval.c:6782
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Incapaz de enviar a %s."
+
+#: eval.c:6882
+msgid "(Invalid)"
+msgstr "(No válido)"
+
+#: eval.c:8060
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Variable sin definir: %s."
+
+#: eval.c:8492
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E244: ¡Nombre ilegal para una variable! %s"
+
+#: eval.c:8784
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E226: La función %s ya existe, añada «!» para reemplazarla."
+
+#: eval.c:8857
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Función sin definir: %s."
+
+#: eval.c:8870
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Falta «(»: %s."
+
+#: eval.c:8903
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Argumento ilegal: %s."
+
+#: eval.c:8982
+msgid "E126: Missing :endfunction"
+msgstr "E126: Falta «:endfunction»."
+
+#: eval.c:9089
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: No se puede redefinir la función %s: está en uso."
+
+#: eval.c:9159
+msgid "E129: Function name required"
+msgstr "E129: Se requiere el nombre de la función."
+
+#: eval.c:9210
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: El nombre de la función debe empezar con mayúscula: %s."
+
+#: eval.c:9402
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Función sin definir: %s."
+
+#: eval.c:9407
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: No se puede eliminar la función %s: está en uso."
+
+#: eval.c:9455
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr ""
+"E132: La profundidad de la llamada a la función es mayor que «maxfuncdepth»."
+
+# always scroll up, don't overwrite
+#. always scroll up, don't overwrite
+#: eval.c:9508
+#, c-format
+msgid "calling %s"
+msgstr "Llamando a %s."
+
+#: eval.c:9570
+#, c-format
+msgid "%s aborted"
+msgstr "He abortado a %s."
+
+#: eval.c:9572
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s devuelve #%ld."
+
+#: eval.c:9579
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s devuelve «%s»."
+
+# always scroll up, don't overwrite
+#. always scroll up, don't overwrite
+#: eval.c:9595 ex_cmds2.c:2365
+#, c-format
+msgid "continuing in %s"
+msgstr "continuando en %s."
+
+#: eval.c:9621
+msgid "E133: :return not inside a function"
+msgstr "E133: «:return» no está dentro de una función."
+
+#: eval.c:9952
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# variables globales:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Hex %02x, Octal %03o"
+
+#: ex_cmds.c:118
+#, c-format
+msgid "> %d, Hex %04x, Octal %o"
+msgstr "> %d, Hex %04x, Octal %o"
+
+#: ex_cmds.c:119
+#, c-format
+msgid "> %d, Hex %08x, Octal %o"
+msgstr "> %d, Hex %08x, Octal %o"
+
+#: ex_cmds.c:430
+msgid "E134: Move lines into themselves"
+msgstr "E134: Moviendo líneas sobre sí mismas."
+
+#: ex_cmds.c:499
+msgid "1 line moved"
+msgstr "1 línea movida."
+
+#: ex_cmds.c:501
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld líneas movidas."
+
+#: ex_cmds.c:924
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld líneas filtradas."
+
+#: ex_cmds.c:952
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *Filtro* Los autocomandos no deben cambiar el «buffer» en curso."
+
+#: ex_cmds.c:1037
+msgid "[No write since last change]\n"
+msgstr "[No se ha escrito al disco nada desde el último cambio]\n"
+
+#: ex_cmds.c:1283
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s en la línea: "
+
+#: ex_cmds.c:1288
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: Hay demasiados errores, omitiendo el resto del fichero."
+
+#: ex_cmds.c:1323
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Leyendo el fichero «viminfo» «%s»%s%s%s"
+
+#: ex_cmds.c:1324
+msgid " info"
+msgstr " info"
+
+#: ex_cmds.c:1325
+msgid " marks"
+msgstr " marcas"
+
+#: ex_cmds.c:1326
+msgid " FAILED"
+msgstr " FALLÓ"
+
+#: ex_cmds.c:1418
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: No hay permiso de escritura para el fichero viminfo: %s"
+
+#: ex_cmds.c:1543
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: ¡No puedo escribir el fichero viminfo %s!"
+
+#: ex_cmds.c:1551
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Escribiendo fichero viminfo «%s»"
+
+# Write the info:
+#. Write the info:
+#: ex_cmds.c:1649
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Este fichero viminfo fue generado por Vim %s.\n"
+
+#: ex_cmds.c:1651
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Usted puede editarlo, ¡solo si tiene cuidado!\n"
+"\n"
+
+#: ex_cmds.c:1653
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Valor de «encoding» cuando se escribió este fichero\n"
+
+#: ex_cmds.c:1752
+msgid "Illegal starting char"
+msgstr "Carácter de comienzo ilegal"
+
+#: ex_cmds.c:2097 ex_cmds.c:2362 ex_cmds2.c:763
+msgid "Save As"
+msgstr "Guardar como"
+
+# Overwriting a file that is loaded in another buffer is not a
+# * good idea.
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2140
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: El fichero está cargado en otro «buffer»."
+
+#: ex_cmds.c:2174
+msgid "Write partial file?"
+msgstr "¿Escribir un fichero parcial?"
+
+#: ex_cmds.c:2181
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Use ! para escribir un «buffer» parcial."
+
+#: ex_cmds.c:2296
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "¿Escribir sobre el fichero existente «%.*s»?"
+
+#: ex_cmds.c:2367
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: No existe un nombre de fichero para el «buffer» %ld"
+
+#: ex_cmds.c:2405
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr ""
+"E142: No se ha escrito el fichero: escritura desactivada por la opción "
+"«write»."
+
+#: ex_cmds.c:2425
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"Se ha activado la opción «readonly» para «%.*s».\n"
+"¿Quiere escribirlo de todas formas?"
+
+#: ex_cmds.c:2597
+msgid "Edit File"
+msgstr "Editar fichero"
+
+#: ex_cmds.c:3205
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr ""
+"E143: Los autocomandos han eliminado inesperadamente el nuevo «buffer» %s"
+
+#: ex_cmds.c:3339
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: Argumento no numérico para «:z»."
+
+#: ex_cmds.c:3424
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: Rvim no permite acceso al procesador de comandos."
+
+#: ex_cmds.c:3531
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Las expresiones regulares no se pueden delimitar con letras."
+
+#: ex_cmds.c:3877
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "¿Reemplazar con %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4270
+msgid "(Interrupted) "
+msgstr "(Interrumpido)"
+
+#: ex_cmds.c:4274
+msgid "1 substitution"
+msgstr "1 sustitución"
+
+#: ex_cmds.c:4276
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld sustituciones"
+
+#: ex_cmds.c:4279
+msgid " on 1 line"
+msgstr " en 1 línea"
+
+#: ex_cmds.c:4281
+#, c-format
+msgid " on %ld lines"
+msgstr " en %ld líneas"
+
+#: ex_cmds.c:4332
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: «:global» no puede ser recursivo."
+
+#: ex_cmds.c:4367
+msgid "E148: Regular expression missing from global"
+msgstr "E148: Falta una expresión regular en el comando global."
+
+#: ex_cmds.c:4416
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Patrón encontrado en cada línea: %s"
+
+#: ex_cmds.c:4497
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Última cadena de sustitución:\n"
+"$"
+
+#: ex_cmds.c:4598
+msgid "E478: Don't panic!"
+msgstr "E478: ¡No entre en pánico!"
+
+#: ex_cmds.c:4650
+#, c-format
+msgid "E661: Sorry, no '%s' help for %s"
+msgstr "E149: Lo siento, no hay ayuda «%s» para %s."
+
+#: ex_cmds.c:4653
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Lo siento, no hay ayuda para %s"
+
+#: ex_cmds.c:4687
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Lo siento, no encuentro el fichero de ayuda «%s»."
+
+#: ex_cmds.c:5170
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: No es un directorio: %s"
+
+#: ex_cmds.c:5309
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: No se puede abrir %s para escritura."
+
+#: ex_cmds.c:5345
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Incapaz de abrir %s para lectura"
+
+#: ex_cmds.c:5367
+#, c-format
+msgid "E670: Mix of help file encodings within a language: %s"
+msgstr ""
+"E670: Mezcla de codificaciones de ficheros de ayuda dentro de un lenguaje: %s"
+
+#: ex_cmds.c:5445
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: Tag «%s» duplicada en el fichero %s"
+
+#: ex_cmds.c:5557
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Comando desconocido de signo: %s"
+
+#: ex_cmds.c:5577
+msgid "E156: Missing sign name"
+msgstr "E156: Falta el nombre del signo."
+
+#: ex_cmds.c:5623
+msgid "E612: Too many signs defined"
+msgstr "E612: Demasiados signos definidos."
+
+#: ex_cmds.c:5691
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Texto de signo no válido: %s"
+
+#: ex_cmds.c:5722 ex_cmds.c:5913
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Signo desconocida: %s"
+
+#: ex_cmds.c:5771
+msgid "E159: Missing sign number"
+msgstr "E159: Falta el número del signo."
+
+#: ex_cmds.c:5853
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E159: El nombre del «buffer» no es válido: %s"
+
+#: ex_cmds.c:5892
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: El id del signo no es válido: %ld"
+
+#: ex_cmds.c:5962
+msgid " (NOT FOUND)"
+msgstr " (NO ENCONTRADO)"
+
+#: ex_cmds.c:5964
+msgid " (not supported)"
+msgstr " (no hay apoyo para la función pedida)"
+
+#: ex_cmds.c:6063
+msgid "[Deleted]"
+msgstr "[Suprimido]"
+
+#: ex_cmds2.c:92
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "Entrando al modo de depuración. Oprima \"cont\" para continuar."
+
+#: ex_cmds2.c:96 ex_docmd.c:966
+#, c-format
+msgid "line %ld: %s"
+msgstr "línea %ld: %s"
+
+#: ex_cmds2.c:98
+#, c-format
+msgid "cmd: %s"
+msgstr "cmd: %s"
+
+#: ex_cmds2.c:290
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "«Breakpoint» en «%s%s» línea %ld"
+
+#: ex_cmds2.c:540
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: No se ha encontrado el «breakpoint»: %s"
+
+#: ex_cmds2.c:566
+msgid "No breakpoints defined"
+msgstr "No hay «breakpoints» definidos."
+
+#: ex_cmds2.c:571
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s línea %ld"
+
+#: ex_cmds2.c:786
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "¿Guardar los cambios en «%.*s»?"
+
+#: ex_cmds2.c:788 ex_docmd.c:9378
+msgid "Untitled"
+msgstr "Sin título"
+
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: No se ha grabado nada desde el último cambio en el buffer «%s»"
+
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr ""
+"Advertencia: se ha entrado en otro «buffer» en forma inesperada (verifique "
+"los autocomandos)."
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: Hay sólo un fichero que editar."
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: No se puede ir antes del primer fichero."
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: No se puede ir más allá del último fichero."
+
+#: ex_cmds2.c:1804
+#, c-format
+msgid "E666: compiler not supported: %s"
+msgstr "E666: El compilador no tiene apoyo en esta versión: %s"
+
+#: ex_cmds2.c:1897
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Buscando «%s» en «%s»."
+
+#: ex_cmds2.c:1919
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Buscando «%s»."
+
+#: ex_cmds2.c:1940
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "No se ha encontrado en «runtimepath»: «%s»"
+
+#: ex_cmds2.c:1974
+msgid "Source Vim script"
+msgstr "Ejecute script de Vim."
+
+#: ex_cmds2.c:2164
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "No se puede ejecutar un directorio: «%s»."
+
+#: ex_cmds2.c:2202
+#, c-format
+msgid "could not source \"%s\""
+msgstr "No se pudo ejecutar «%s»."
+
+#: ex_cmds2.c:2204
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "línea %ld: no se pudo ejecutar «%s»."
+
+#: ex_cmds2.c:2218
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "ejecutando «%s»."
+
+#: ex_cmds2.c:2220
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "línea %ld: ejecutando «%s»."
+
+#: ex_cmds2.c:2363
+#, c-format
+msgid "finished sourcing %s"
+msgstr "La ejecución de «%s» ha terminado."
+
+#: ex_cmds2.c:2707
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Advertencia: separador de línea equivocado, puede que falte ^M"
+
+#: ex_cmds2.c:2756
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: Ha usado «:scriptencoding» fuera de un fichero de instrucciones ejecutables."
+
+#: ex_cmds2.c:2789
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: Ha usado «:finish» fuera de un fichero de instrucciones ejecutables."
+
+#: ex_cmds2.c:3238
+#, c-format
+msgid "Page %d"
+msgstr "Página %d"
+
+#: ex_cmds2.c:3394
+msgid "No text to be printed"
+msgstr "No hay texto que imprimir."
+
+#: ex_cmds2.c:3472
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "Imprimiendo la página %d (%d%%)."
+
+#: ex_cmds2.c:3484
+#, c-format
+msgid " Copy %d of %d"
+msgstr "Copia %d de %d"
+
+#: ex_cmds2.c:3542
+#, c-format
+msgid "Printed: %s"
+msgstr "Impreso: %s."
+
+#: ex_cmds2.c:3549
+msgid "Printing aborted"
+msgstr "Impresión abortada."
+
+#: ex_cmds2.c:3914
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Error escribiendo al fichero PostScript de salida."
+
+#: ex_cmds2.c:4189
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E456: No se puede abrir el fichero «%s»."
+
+#: ex_cmds2.c:4199 ex_cmds2.c:4824
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: No se puede leer el fichero de recursos de PostScript «%s»."
+
+#: ex_cmds2.c:4207
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: El fichero \"%s\" no es un fichero de recursos PostScript."
+
+#: ex_cmds2.c:4222 ex_cmds2.c:4242 ex_cmds2.c:4257 ex_cmds2.c:4279
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: El fichero «%s» no es un recurso PostScript que pueda usar."
+
+#: ex_cmds2.c:4309
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: El fichero de recursos «%s» tiene la versión equivocada."
+
+#: ex_cmds2.c:4776
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: No puedo abrir el fichero PostScript de salida."
+
+#: ex_cmds2.c:4809
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: No puedo abrir el fichero «%s»."
+
+#: ex_cmds2.c:4928
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr ""
+"E456: No encuentro el fichero de recursos PostScript «prolog.ps»."
+
+#: ex_cmds2.c:4959
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: No hallo el fichero de recursos PostScript «%s.ps»."
+
+#: ex_cmds2.c:4977
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr "E620: No puedo convertir de «multi-byte» a la codificación \"%s\"."
+
+#: ex_cmds2.c:5102
+msgid "Sending to printer..."
+msgstr "Envíando a la impresora..."
+
+#: ex_cmds2.c:5106
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: No pude imprimir el fichero PostScript."
+
+#: ex_cmds2.c:5108
+msgid "Print job sent."
+msgstr "Tarea de impresión envíada."
+
+#: ex_cmds2.c:5618
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Idioma actual «%s»: «%s»."
+
+#: ex_cmds2.c:5629
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: No se puede establecer la opción del idioma a «%s»."
+
+#: ex_docmd.c:525
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Entrando al modo Ex. Escriba «visual» para ir al modo Normal."
+
+# must be at EOF
+#. must be at EOF
+#: ex_docmd.c:561
+msgid "E501: At end-of-file"
+msgstr "E501: Estoy al final del fichero."
+
+#: ex_docmd.c:669
+msgid "E169: Command too recursive"
+msgstr "E169: El comando recurre excesivamente."
+
+#: ex_docmd.c:1229
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: La excepción %s no se atrapó."
+
+#: ex_docmd.c:1317
+msgid "End of sourced file"
+msgstr "Fin del fichero de instrcucciones ejecutables."
+
+#: ex_docmd.c:1318
+msgid "End of function"
+msgstr "Fin de la función."
+
+#: ex_docmd.c:1907
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: Uso ambiguo de un comando definido por el usuario."
+
+#: ex_docmd.c:1921
+msgid "E492: Not an editor command"
+msgstr "E371: No es un comando del editor."
+
+#: ex_docmd.c:2028
+msgid "E493: Backwards range given"
+msgstr "E493: Me ha dado un rango invertido."
+
+#: ex_docmd.c:2037
+msgid "Backwards range given, OK to swap"
+msgstr "Me ha dado un rango invertido, ¿está bien intercambiarlo?"
+
+#: ex_docmd.c:2160
+msgid "E494: Use w or w>>"
+msgstr "E494: Use «w» o «w>>»."
+
+#: ex_docmd.c:3786
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Lo siento, el comando no está disponible en esta versión."
+
+#: ex_docmd.c:3989
+msgid "E172: Only one file name allowed"
+msgstr "E172: Sólo se permite un nombre de fichero."
+
+#: ex_docmd.c:4569
+msgid "1 more file to edit. Quit anyway?"
+msgstr "Un fichero más para editar. ¿Termino de todas formas?"
+
+#: ex_docmd.c:4572
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "Hay %d ficheros más en edición. ¿Termino de todas formas?"
+
+#: ex_docmd.c:4579
+msgid "E173: 1 more file to edit"
+msgstr "E173: Un fichero más para editar."
+
+#: ex_docmd.c:4581
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: Hay %ld ficheros en edición."
+
+#: ex_docmd.c:4676
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: El comando ya existe. Añada «!» para reemplazarlo."
+
+#: ex_docmd.c:4787
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Nombre Args Rango Completar Definición"
+
+#: ex_docmd.c:4876
+msgid "No user-defined commands found"
+msgstr "No se han encontrado comandos definidos por el usuario"
+
+#: ex_docmd.c:4908
+msgid "E175: No attribute specified"
+msgstr "E175: No se ha especificado el atributo."
+
+#: ex_docmd.c:4960
+msgid "E176: Invalid number of arguments"
+msgstr "E176: El número de argumentos no es válido."
+
+#: ex_docmd.c:4975
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: El recuento no se puede especificar dos veces."
+
+#: ex_docmd.c:4985
+msgid "E178: Invalid default value for count"
+msgstr "E178: El valor predeterminado para el recuento no es válido."
+
+#: ex_docmd.c:5016
+msgid "E179: argument required for complete"
+msgstr "E179: se necesita un argumento para completar."
+
+#: ex_docmd.c:5048
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: El valor para completar no es válido: %s."
+
+#: ex_docmd.c:5057
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr ""
+"E468: El argumento de finalización solo se permite en finalizaciones "
+"definidas por el usuario."
+
+#: ex_docmd.c:5063
+msgid "E467: Custom completion requires a function argument"
+msgstr ""
+"E467: Las finalizatines definidad por el usuario requieren de un argumento "
+"de función."
+
+#: ex_docmd.c:5074
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: El atributo no es válido: %s"
+
+#: ex_docmd.c:5117
+msgid "E182: Invalid command name"
+msgstr "E182: El nombre de comando no es válido."
+
+#: ex_docmd.c:5132
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr ""
+"E183: Los comandos definidos por el usuario deben comenzar con una letra "
+"mayúscula."
+
+#: ex_docmd.c:5203
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: No existe tal comando definido por el usuario: %s"
+
+#: ex_docmd.c:5664
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: No se puede encontrar el esquema de colores %s"
+
+#: ex_docmd.c:5672
+msgid "Greetings, Vim user!"
+msgstr "¡Saludos, usuario de Vim!"
+
+#: ex_docmd.c:6389
+msgid "Edit File in new window"
+msgstr "Editar fichero en una ventana nueva"
+
+#: ex_docmd.c:6684
+msgid "No swap file"
+msgstr "No hay fichero de intercambio"
+
+#: ex_docmd.c:6788
+msgid "Append File"
+msgstr "Añadir fichero"
+
+#: ex_docmd.c:6852
+msgid "E186: No previous directory"
+msgstr "E186: No hay directorio previo."
+
+#: ex_docmd.c:6934
+msgid "E187: Unknown"
+msgstr "E187: Desconocido."
+
+#: ex_docmd.c:7019
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: «:winsize» requiere de dos argumentos numéricos."
+
+#: ex_docmd.c:7075
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Posición de la ventana: X %d, Y %d"
+
+#: ex_docmd.c:7080
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr ""
+"E188: La obtención de la posición de la ventana no está implementada en esta "
+"plataforma."
+
+#: ex_docmd.c:7090
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: «:winpos» require de dos argumentos numéricos."
+
+#: ex_docmd.c:7368
+msgid "Save Redirection"
+msgstr "Guardar redirección."
+
+#: ex_docmd.c:7558
+msgid "Save View"
+msgstr "Guardar vista"
+
+#: ex_docmd.c:7559
+msgid "Save Session"
+msgstr "Guardar sesión"
+
+#: ex_docmd.c:7561
+msgid "Save Setup"
+msgstr "Guardar configuración"
+
+#: ex_docmd.c:7713
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" ya existe (añada ! para sobreescribir.)"
+
+#: ex_docmd.c:7718
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: No se puede abrir «%s» para escritura"
+
+# set mark
+#. set mark
+#: ex_docmd.c:7742
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr ""
+"E191: El argumento debe ser una letra o un apóstrofo/apóstrofo invertido"
+
+#: ex_docmd.c:7784
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Uso recursivo demasiado profundo de «:normal»."
+
+#: ex_docmd.c:8302
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: No hay un nombre de fichero alternativo que sustituya a «#»."
+
+#: ex_docmd.c:8333
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr ""
+"E495: No ha dado un nombre de fichero de autocomandos para sustituir a "
+"\"<afile>\""
+
+#: ex_docmd.c:8341
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr ""
+"E496: No existe un «buffer» de autocomando para sustituir por \"<abuf>\""
+
+#: ex_docmd.c:8352
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr ""
+"E497: Ningún nombre de autocomando concuerda para sustituir «<amatch>»."
+
+#: ex_docmd.c:8362
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr ""
+"E498: No hay un nombre de fichero «:source» que sustituya a \"<sfile>\"."
+
+#: ex_docmd.c:8403
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: Un nombre de fichero vacio solo funciona con \":p:h\"."
+
+#: ex_docmd.c:8405
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: La expresión evalua a un «string» vacio."
+
+#: ex_docmd.c:9360
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: No se puede abrir el fichero «viminfo» para lectura."
+
+#: ex_docmd.c:9533
+msgid "E196: No digraphs in this version"
+msgstr "E196: No hay dígrafos en esta versión."
+
+#: ex_eval.c:440
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr ""
+"E608: No puedo lanzar (':throw') excepciones si tienen el prefijo 'Vim'."
+
+# always scroll up, don't overwrite
+#. always scroll up, don't overwrite
+#: ex_eval.c:529
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "He encontrado una excepción: %s."
+
+#: ex_eval.c:576
+#, c-format
+msgid "Exception finished: %s"
+msgstr "Exepción finalizada: %s"
+
+#: ex_eval.c:577
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "He descartado una excepción: %s"
+
+#: ex_eval.c:620 ex_eval.c:664
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, en la línea %ld."
+
+# always scroll up, don't overwrite
+#. always scroll up, don't overwrite
+#: ex_eval.c:638
+#, c-format
+msgid "Exception caught: %s"
+msgstr "Exception atrapada: %s"
+
+#: ex_eval.c:713
+#, c-format
+msgid "%s made pending"
+msgstr "He puesto a %s en la lista de pendientes."
+
+#: ex_eval.c:716
+#, c-format
+msgid "%s resumed"
+msgstr "He resumido a %s."
+
+#: ex_eval.c:720
+#, c-format
+msgid "%s discarded"
+msgstr "He descartado a %s."
+
+#: ex_eval.c:746
+msgid "Exception"
+msgstr "Exepción."
+
+#: ex_eval.c:752
+msgid "Error and interrupt"
+msgstr "Error e interrupción"
+
+#: ex_eval.c:754 gui.c:4381
+msgid "Error"
+msgstr "Error"
+
+# if (pending & CSTP_INTERRUPT)
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:756
+msgid "Interrupt"
+msgstr "Interrupción"
+
+#: ex_eval.c:830
+msgid "E579: :if nesting too deep"
+msgstr "E579: Anidamineot de «:if» demasiado profundo."
+
+#: ex_eval.c:867
+msgid "E580: :endif without :if"
+msgstr "E580: ¡:endif sin un :if!"
+
+#: ex_eval.c:911
+msgid "E581: :else without :if"
+msgstr "E581: :else sin un :if"
+
+#: ex_eval.c:914
+msgid "E582: :elseif without :if"
+msgstr "E582: :elseif sin un :if"
+
+#: ex_eval.c:921
+msgid "E583: multiple :else"
+msgstr "E583: «:else» múltiple."
+
+#: ex_eval.c:924
+msgid "E584: :elseif after :else"
+msgstr "E584: :elseif después de :else"
+
+#: ex_eval.c:991
+msgid "E585: :while nesting too deep"
+msgstr "E585: ¡«:while» se anida muy profundamente!"
+
+#: ex_eval.c:1047
+msgid "E586: :continue without :while"
+msgstr "E586: :continue sin un :while"
+
+#: ex_eval.c:1087
+msgid "E587: :break without :while"
+msgstr "E587: :break sin :while"
+
+#: ex_eval.c:1286
+msgid "E601: :try nesting too deep"
+msgstr "E218: ¡«:try» se anida muy profundamente!"
+
+#: ex_eval.c:1366
+msgid "E603: :catch without :try"
+msgstr "E603: :catch sin un :try"
+
+# Give up for a ":catch" after ":finally" and ignore it.
+# * Just parse.
+# Give up for a ":catch" after ":finally" and ignore it.
+# * Just parse.
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1388
+msgid "E604: :catch after :finally"
+msgstr "E604: :catch después de :finally"
+
+#: ex_eval.c:1521
+msgid "E606: :finally without :try"
+msgstr "E606: :finally sin un :try"
+
+# Give up for a multiple ":finally" and ignore it.
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1545
+msgid "E607: multiple :finally"
+msgstr "E607: ¡«:finally» múltiple!"
+
+#: ex_eval.c:1654
+msgid "E602: :endtry without :try"
+msgstr "E602: :endtry sin un :try"
+
+#: ex_eval.c:1986
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: «:endfunction» no está dentro de una función."
+
+#: ex_getln.c:3296
+msgid "tagname"
+msgstr "Nombre del «tag»"
+
+#: ex_getln.c:3299
+msgid " kind file\n"
+msgstr " tipo de fichero\n"
+
+#: ex_getln.c:4752
+msgid "'history' option is zero"
+msgstr "La opción 'history' es cero."
+
+#: ex_getln.c:5023
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Historia de «%s» (de lo más nuevo a lo más antiguo):\n"
+
+#: ex_getln.c:5024
+msgid "Command Line"
+msgstr "Línea de comandos"
+
+#: ex_getln.c:5025
+msgid "Search String"
+msgstr "Cadena de búsqueda"
+
+#: ex_getln.c:5026
+msgid "Expression"
+msgstr "Expresión"
+
+#: ex_getln.c:5027
+msgid "Input Line"
+msgstr "Línea de entrada"
+
+#: ex_getln.c:5065
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: «cmd_pchar» más allá de la longitud del comando."
+
+#: ex_getln.c:5242
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Se ha suprimido la ventana o el buffer activos."
+
+#: fileio.c:377
+msgid "Illegal file name"
+msgstr "Nombre de fichero ilegal"
+
+#: fileio.c:401 fileio.c:535 fileio.c:2913 fileio.c:2954
+msgid "is a directory"
+msgstr "es un directorio"
+
+#: fileio.c:403
+msgid "is not a file"
+msgstr "no es un fichero"
+
+#: fileio.c:557 fileio.c:4131
+msgid "[New File]"
+msgstr "[Fichero nuevo]"
+
+#: fileio.c:590
+msgid "[Permission Denied]"
+msgstr "[Permiso negado]"
+
+#: fileio.c:694
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: Los autocomandos «*ReadPre» hicieron ilegible al fichero."
+
+#: fileio.c:696
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: Los autocomandos «*ReadPre» no deben cambiar el buffer en curso."
+
+#: fileio.c:717
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: leyendo la entrada estándar...\n"
+
+#: fileio.c:723
+msgid "Reading from stdin..."
+msgstr "Leyendo la entrada estándar..."
+
+# Re-opening the original file failed!
+#. Re-opening the original file failed!
+#: fileio.c:1000
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: ¡La conversión ha hecho el fichero ilegible!"
+
+#: fileio.c:2090
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:2097
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:2104
+msgid "[socket]"
+msgstr "[socket]"
+
+#: fileio.c:2112
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:2122
+msgid "[CR missing]"
+msgstr "[Falta un CR]"
+
+#: fileio.c:2127
+msgid "[NL found]"
+msgstr "[Se ha encontrado un NL]"
+
+#: fileio.c:2132
+msgid "[long lines split]"
+msgstr "[he partido las líneas largas]"
+
+#: fileio.c:2138 fileio.c:4115
+msgid "[NOT converted]"
+msgstr "[NO convertido]"
+
+#: fileio.c:2143 fileio.c:4120
+msgid "[converted]"
+msgstr "[convertido]"
+
+#: fileio.c:2150 fileio.c:4145
+msgid "[crypted]"
+msgstr "[encriptado]"
+
+#: fileio.c:2157
+msgid "[CONVERSION ERROR]"
+msgstr "[ERROR DE CONVERSIÓN]"
+
+#: fileio.c:2163
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[BYTE ILEGAL en la línea %ld]"
+
+#: fileio.c:2170
+msgid "[READ ERRORS]"
+msgstr "[ERRORES DE LECTURA]"
+
+#: fileio.c:2386
+msgid "Can't find temp file for conversion"
+msgstr "No se puede encontrar el fichero temporal para la conversión."
+
+#: fileio.c:2393
+msgid "Conversion with 'charconvert' failed"
+msgstr "La conversión con '«charconvert»' ha fallado."
+
+#: fileio.c:2396
+msgid "can't read output of 'charconvert'"
+msgstr "No puedo leer la salida de «charconvert»."
+
+#: fileio.c:2796
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr ""
+"E203: Los autocomandos fueron suprimidos o el «buffer» se descargó para ser "
+"grabado en disco."
+
+#: fileio.c:2819
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr ""
+"E204: El autocomando ha cambiado el número de líneas en forma inesperada."
+
+#: fileio.c:2857
+msgid "NetBeans dissallows writes of unmodified buffers"
+msgstr "NetBeans no permite que se escriba sobre «buffers» sin modificar."
+
+#: fileio.c:2865
+msgid "Partial writes disallowed for NetBeans buffers"
+msgstr "No se permite la escritura parcial de los «buffers» de NetBeans."
+
+#: fileio.c:2919 fileio.c:2937
+msgid "is not a file or writable device"
+msgstr "no es un fichero o dispositivo en el que se pueda escribir."
+
+#: fileio.c:2989
+msgid "is read-only (add ! to override)"
+msgstr "Es de solo lectura (añada ! para obreescribir)."
+
+#: fileio.c:3335
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr ""
+"E506: No puedo escribir al fichero de respaldo (añada ! para forzar el "
+"comando)."
+
+#: fileio.c:3347
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr ""
+"E507: Error al cerrar el fichero de la copia de respaldo (añada ! para "
+"forzar el comando)."
+
+#: fileio.c:3349
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr ""
+"E508: No puedo leer el fichero para crear la copia de respaldo (añada ! para "
+"forzar el comando)."
+
+#: fileio.c:3365
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr ""
+"E509: No puedo crear el fichero para la copia de respaldo (añada ! para "
+"forzar el comando)."
+
+#: fileio.c:3468
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr ""
+"E510: No puedo hacer un fichero de copia de respaldo (añada ! para forzar el "
+"comando)."
+
+#: fileio.c:3530
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr ""
+"E460: Se perdería el segmento («fork») de recursos! (añada ! para forzar el "
+"comando)."
+
+#: fileio.c:3640
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: No puedo encontrar el fichero temporal para escribir en él."
+
+#: fileio.c:3658
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr ""
+"E213: No puedo convertirlo (añada ! para escribir el fichero sin conversión)."
+
+#: fileio.c:3693
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: No puedo abrir el fichero enlazado para escribir en él."
+
+#: fileio.c:3697
+msgid "E212: Can't open file for writing"
+msgstr "E212: No puedo abrir el fichero para escribir en él."
+
+#: fileio.c:3959
+msgid "E667: Fsync failed"
+msgstr "E667: falló «fsync»"
+
+#: fileio.c:3966
+msgid "E512: Close failed"
+msgstr "E314: Falló el cierre del fichero."
+
+#: fileio.c:4037
+msgid "E513: write error, conversion failed"
+msgstr "E513: Error de escritura, la conversión falló."
+
+#: fileio.c:4043
+msgid "E514: write error (file system full?)"
+msgstr "E514: Error de escritura (¿Sistema de ficheros lleno?"
+
+#: fileio.c:4110
+msgid " CONVERSION ERROR"
+msgstr "ERROR DE CONVERSIÓN"
+
+#: fileio.c:4126
+msgid "[Device]"
+msgstr "[Dispositivo]"
+
+#: fileio.c:4131
+msgid "[New]"
+msgstr "[Nuevo]"
+
+#: fileio.c:4153
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:4153
+msgid " appended"
+msgstr " añadido"
+
+#: fileio.c:4155
+msgid " [w]"
+msgstr " [w]"
+
+#: fileio.c:4155
+msgid " written"
+msgstr " escritos"
+
+#: fileio.c:4205
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: Modo «patch»: no se puede guardar el fichero original."
+
+#: fileio.c:4227
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: Modo «patch»: no se puede tocar el fichero original vacío."
+
+#: fileio.c:4242
+msgid "E207: Can't delete backup file"
+msgstr "E207: No se puede borrar el fichero de respaldo."
+
+#: fileio.c:4306
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"AVISO: el fichero original puede haberse perdido o haberse dañado\n"
+
+#: fileio.c:4308
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "¡no salga del editor hasta que el fichero se haya escrito!"
+
+#: fileio.c:4397
+msgid "[dos]"
+msgstr "[DOS]"
+
+#: fileio.c:4397
+msgid "[dos format]"
+msgstr "[formato DOS]"
+
+#: fileio.c:4404
+msgid "[mac]"
+msgstr "[Mac]"
+
+#: fileio.c:4404
+msgid "[mac format]"
+msgstr "[formato Mac]"
+
+#: fileio.c:4411
+msgid "[unix]"
+msgstr "[UNIX]"
+
+#: fileio.c:4411
+msgid "[unix format]"
+msgstr "[formato UNIX]"
+
+#: fileio.c:4438
+msgid "1 line, "
+msgstr "1 línea, "
+
+#: fileio.c:4440
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld líneas, "
+
+#: fileio.c:4443
+msgid "1 character"
+msgstr "1 carácter"
+
+#: fileio.c:4445
+#, c-format
+msgid "%ld characters"
+msgstr "%ld caracteres"
+
+#: fileio.c:4455
+msgid "[noeol]"
+msgstr "[no hay fin de línea]"
+
+#: fileio.c:4455
+msgid "[Incomplete last line]"
+msgstr "[Última línea incompleta]"
+
+# don't overwrite messages here
+# must give this prompt
+# don't use emsg() here, don't want to flush the buffers
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4474
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "ADVERTENCIA: ¡¡¡El fichero ha cambiado desde que se leyó!!!"
+
+#: fileio.c:4476
+msgid "Do you really want to write to it"
+msgstr "¿Quiere realmente escribir a él?"
+
+#: fileio.c:5726
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Error al escribir a «%s»."
+
+#: fileio.c:5733
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Error al cerrar «%s»."
+
+#: fileio.c:5736
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Error al leer «%s»."
+
+#: fileio.c:5970
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: el autocomando «FileChangedShell» ha borrado el buffer."
+
+#: fileio.c:5977
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: Advertencia: el fichero «%s» ya no está disponible"
+
+#: fileio.c:5991
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: Advertencia: el fichero «%s» ha cambiado y el buffer fue cambiado "
+"también en Vim."
+
+#: fileio.c:5994
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr ""
+"W11: Advertencia: el fichero «%s» ha cambiado desde que comenzó la edición."
+
+#: fileio.c:5996
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr ""
+"W16: Advertencia: el modo del fichero «%s» ha cambiado desde que comenzó la "
+"edición."
+
+#: fileio.c:6006
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr ""
+"W13: Advertencia: el fichero «%s» ha sido creado después de comenzar la "
+"edición."
+
+#: fileio.c:6019
+msgid "See \":help W11\" for more info."
+msgstr "Vea «:help w11» para más información."
+
+#: fileio.c:6033
+msgid "Warning"
+msgstr "Advertencia"
+
+#: fileio.c:6034
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Cargar fichero"
+
+#: fileio.c:6140
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: No pude prepararme para recargar a \"%s\"."
+
+#: fileio.c:6159
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: No se pudo recargar «%s»."
+
+#: fileio.c:6740
+msgid "--Deleted--"
+msgstr "--Suprimido--"
+
+# the group doesn't exist
+#. the group doesn't exist
+#: fileio.c:6900
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: No existe el grupo: «%s»."
+
+#: fileio.c:7026
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Carácter ilegal después de *: «%s»."
+
+#: fileio.c:7038
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: No existe tal hecho: «%s»"
+
+#: fileio.c:7040
+#, c-format
+msgid "E216: No such group or event: %s"
+msgstr "E216: No existe tal grupo o evento: %s"
+
+# Highlight title
+#. Highlight title
+#: fileio.c:7198
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Auto-comandos ---"
+
+#: fileio.c:7469
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr ""
+"E217: No se pueden ejecutar los autocomandos para TODOS los eventos de "
+"ejecución."
+
+#: fileio.c:7492
+msgid "No matching autocommands"
+msgstr "Ningún autocomando coincide."
+
+#: fileio.c:7813
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: El autocomando se anida en demasiados bucles."
+
+#: fileio.c:8088
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Auto comandos para «%s»"
+
+#: fileio.c:8096
+#, c-format
+msgid "Executing %s"
+msgstr "Ejecutando %s"
+
+# always scroll up, don't overwrite
+#. always scroll up, don't overwrite
+#: fileio.c:8164
+#, c-format
+msgid "autocommand %s"
+msgstr "autocomando %s"
+
+#: fileio.c:8731
+msgid "E219: Missing {."
+msgstr "E219: Falta un {."
+
+#: fileio.c:8733
+msgid "E220: Missing }."
+msgstr "E220: Falta un }."
+
+#: fold.c:68
+msgid "E490: No fold found"
+msgstr "E490: No encontré ningún pliegue."
+
+#: fold.c:593
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: No puedo crear el pliegue con el 'folmethod' activo."
+
+#: fold.c:595
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: No puedo borrar el pliegue con el 'foldmethod' activo."
+
+#: getchar.c:248
+msgid "E222: Add to read buffer"
+msgstr "E222: Añadir al «buffer» de lectura"
+
+#: getchar.c:2198
+msgid "E223: recursive mapping"
+msgstr "E223: asociación recursiva"
+
+#: getchar.c:3077
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: ya existe una abreviatura global para «%s»."
+
+#: getchar.c:3080
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: ya existe una asociación global para «%s»."
+
+#: getchar.c:3212
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: ya existe una abreviatura para «%s»."
+
+#: getchar.c:3215
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: ya existe una asociación para «%s»."
+
+#: getchar.c:3279
+msgid "No abbreviation found"
+msgstr "No encontré ninguna abreviatura."
+
+#: getchar.c:3281
+msgid "No mapping found"
+msgstr "No encontré ninguna asociación."
+
+#: getchar.c:4173
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: «makemap»: modo ilegal."
+
+#: gui.c:220
+msgid "E229: Cannot start the GUI"
+msgstr "E229: No se puede iniciar la interface gráfica («GUI»)."
+
+#: gui.c:349
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: No puedo leer a «%s»."
+
+#: gui.c:472
+msgid "E665: Cannot start GUI, no valid font found"
+msgstr ""
+"E665: No puedo inicial la interfase gráfica (GUI), no encontré ninguna "
+"fuente de impresión válida."
+
+#: gui.c:477
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: El valor de «guifontwide» no es válido."
+
+#: gui.c:547
+msgid "E599: Value of 'imactivatekey' is invalid"
+msgstr "E599: El valor de «imactivatekey» no es válido."
+
+#: gui.c:4061
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: No se puede asignar el color «%s»."
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<no puedo abrirlo>"
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: «vim_SelFile»: No puedo hallar la fuente de impresión %s."
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: «vim_SelFile»: no puedo regresar al directorio actual."
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "Nombre de la ruta:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr ""
+"E615: v«vim_SelFile»: No puedo obtener la localización del directorio actual."
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "OK"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2731 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Scrollbar Widget: No pude obtener la geometría del «pixmap» miniatura."
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "Diálogo de Vim"
+
+#: gui_beval.c:101 gui_w32.c:3945
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr ""
+"E232: No puedo crear un «BalloonEval» que contenga tanto el mensaje como el "
+"«callback»."
+
+#: gui_gtk.c:1607
+msgid "Vim dialog..."
+msgstr "Diálogo de Vim..."
+
+#: gui_gtk.c:2060 message.c:2999
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Si\n"
+"&No\n"
+"&Cancelar"
+
+#: gui_gtk.c:2268
+msgid "Input _Methods"
+msgstr "Métodos de Entrada («Input_Methods»)"
+
+#: gui_gtk.c:2534 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Buscar y reemplazar..."
+
+#: gui_gtk.c:2542 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "VIM - Buscar..."
+
+#: gui_gtk.c:2574 gui_motif.c:2888
+msgid "Find what:"
+msgstr "¿Encontrar qué?:"
+
+#: gui_gtk.c:2592 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "Reemplazar con:"
+
+# whole word only button
+#. whole word only button
+#: gui_gtk.c:2624 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "Encontrar solo palabras completas."
+
+# match case button
+#. match case button
+#: gui_gtk.c:2635 gui_motif.c:3048
+msgid "Match case"
+msgstr "La única coincidencia"
+
+#: gui_gtk.c:2645 gui_motif.c:2990
+msgid "Direction"
+msgstr "Dirección"
+
+# 'Up' and 'Down' buttons
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2657 gui_motif.c:3002
+msgid "Up"
+msgstr "Hacia arriba"
+
+#: gui_gtk.c:2661 gui_motif.c:3010
+msgid "Down"
+msgstr "Hacia abajo"
+
+#: gui_gtk.c:2683 gui_gtk.c:2685 gui_motif.c:2792
+msgid "Find Next"
+msgstr "Encontrar siguiente"
+
+#: gui_gtk.c:2702 gui_gtk.c:2704 gui_motif.c:2809
+msgid "Replace"
+msgstr "Reemplazar"
+
+#: gui_gtk.c:2715 gui_gtk.c:2717 gui_motif.c:2822
+msgid "Replace All"
+msgstr "Reemplazar todos"
+
+#: gui_gtk_x11.c:2327
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: Recibí una solicitud \"die\" del administrador de sesiones.\n"
+
+#: gui_gtk_x11.c:3519
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: La ventana principal fue destruida inesperadamente.\n"
+
+#: gui_gtk_x11.c:4138
+msgid "Font Selection"
+msgstr "Selección de tipos de letra"
+
+#: gui_gtk_x11.c:6035 ui.c:2120
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "Se ha usado «CUT_BUFFER0» en vez de una selección vacía."
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "Filtro"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "Directorios"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "Ayuda"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "Ficheros"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "Selección"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "Deshacer"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: No puedo cargar la fuente de impresión Zap '%s'."
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: No puedo usar la fuente de impresión %s."
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Enviando mensaje para terminar los procesos dependientes («hijo»).\n"
+
+#: gui_w32.c:834
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Argumento no admitido: «-%s»; use la versión OLE."
+
+#: gui_w48.c:2147
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Buscar cadena (use «\\\\» para encontrar un «\\»)"
+
+#: gui_w48.c:2172
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Buscar y reemplazar (use «\\\\» para encontra una «\\»)"
+
+#: gui_x11.c:1537
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: no se puede asignar una entrada al mapa de colores; algunos "
+"colores tal vez no sean correctos."
+
+#: gui_x11.c:2118
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr ""
+"E250: Faltan las fuentes de impresión para los siguientes conjuntos de "
+"caracteres en el conjunto de fuentes «%s»:"
+
+#: gui_x11.c:2161
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Nombre del conjunto de fuentes de impresión: «%s»"
+
+#: gui_x11.c:2162
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "La fuente de impresión «%s» no es de ancho fijo."
+
+#: gui_x11.c:2181
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Nombre del conjunto de fuentes de impresión: «%s»\n"
+
+#: gui_x11.c:2182
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Fuente de impresión 0: %s\n"
+
+#: gui_x11.c:2183
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Fuente de impresión 1: %s\n"
+
+#: gui_x11.c:2184
+#, c-format
+msgid "Font%ld width is not twice that of font0\n"
+msgstr ""
+"La anchura de la fuente de impresión %ld no es el doble de la de la fuente "
+"de impresión 0\n"
+
+#: gui_x11.c:2185
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "Anchura de la fuente de impresión 0: %ld\n"
+
+#: gui_x11.c:2186
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"Anchura de la fuente de impresión 1: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: ERROR del autómata Hangul."
+
+#: if_cscope.c:77
+msgid "Add a new database"
+msgstr "Añadir una nueva base de datos."
+
+#: if_cscope.c:79
+msgid "Query for a pattern"
+msgstr "Petición de un patrón."
+
+#: if_cscope.c:81
+msgid "Show this message"
+msgstr "Mostrar este mensaje."
+
+#: if_cscope.c:83
+msgid "Kill a connection"
+msgstr "Matar una conexión."
+
+#: if_cscope.c:85
+msgid "Reinit all connections"
+msgstr "Reiniciar todas las conexiones."
+
+#: if_cscope.c:87
+msgid "Show connections"
+msgstr "Mostrar las conexiones."
+
+#: if_cscope.c:95
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: Forma de uso: cs[cope] %s"
+
+#: if_cscope.c:124
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Este comando «cscope» no admite la división de la ventana.\n"
+
+#: if_cscope.c:175
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: Forma de uso: cstag <identificador>"
+
+#: if_cscope.c:231
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: «tag» no encontrado."
+
+#: if_cscope.c:409
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: Error en stat(%s): %d"
+
+#: if_cscope.c:419
+msgid "E563: stat error"
+msgstr "E563: error en la función «stat()»."
+
+#: if_cscope.c:516
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s no es un directorio ni una base de datos válida de cscope."
+
+#: if_cscope.c:534
+#, c-format
+msgid "Added cscope database %s"
+msgstr "Se ha añadido la base de datos «cscope» %s"
+
+#: if_cscope.c:589
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: Error al leer la conexión %ld con cscope."
+
+#: if_cscope.c:694
+msgid "E561: unknown cscope search type"
+msgstr "E561: Tipo de búsqueda desconocido para cscope."
+
+#: if_cscope.c:736
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: No pude crear la conexión «pipe» para comunicarme con cscope."
+
+#: if_cscope.c:753
+msgid "E622: Could not fork for cscope"
+msgstr "E622: No pude crear un nuevo proceso («fork») para usar cscope."
+
+#: if_cscope.c:847 if_cscope.c:897
+msgid "cs_create_connection exec failed"
+msgstr "Falló la ejecución de «cs_create_connection»"
+
+#: if_cscope.c:898
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: No pude crear un nuevo proceso («spawn») de cscope."
+
+#: if_cscope.c:911
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "«cs_create_connection»: Falló «fdopen» para «to_fp»."
+
+#: if_cscope.c:913
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "«cs_create_connection»: Falló «fdopen» para «fr_fp»."
+
+#: if_cscope.c:951
+msgid "E567: no cscope connections"
+msgstr "E567: No hay conexiones con cscope."
+
+#: if_cscope.c:1025
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr ""
+"E259: No se encontraron coincidencias para la búsqueda cscope %s de %s."
+
+#: if_cscope.c:1082
+#, c-format
+msgid "E469: invalid cscopequickfix flag %c for %c"
+msgstr "E469: La marca «cscopequickfix» %c para %c no es válida."
+
+#: if_cscope.c:1152
+msgid "cscope commands:\n"
+msgstr "comandos de «cscope»:\n"
+
+#: if_cscope.c:1155
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (Modo de uso: %s)"
+
+#: if_cscope.c:1253
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: No puedo abrir la base de datos cscope: %s."
+
+#: if_cscope.c:1271
+msgid "E626: cannot get cscope database information"
+msgstr "E626: No puedo obtener información acerca de la base de datos cscope."
+
+#: if_cscope.c:1296
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: No se añadió una base de datos de cscope duplicada."
+
+#: if_cscope.c:1307
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: Se ha alcanzado el número máximo de conexiones con cscope."
+
+#: if_cscope.c:1424
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: no se ha encontrado la conexión «cscope» %s"
+
+#: if_cscope.c:1458
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "Conexión «cscope» %s cerrada."
+
+# should not reach here
+#. should not reach here
+#: if_cscope.c:1598
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: Error fatal en «cs_manage_matches»."
+
+#: if_cscope.c:1848
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "«tag» de cscope: %s"
+
+#: if_cscope.c:1870
+msgid ""
+"\n"
+" # line"
+msgstr ""
+"\n"
+" # línea"
+
+#: if_cscope.c:1872
+msgid "filename / context / line\n"
+msgstr "nombre del fichero / contexto / línea\n"
+
+#: if_cscope.c:1990
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: Error de «cscope»: %s"
+
+#: if_cscope.c:2176
+msgid "All cscope databases reset"
+msgstr "Se han vaciado todas las bases de datos de «cscope»"
+
+#: if_cscope.c:2244
+msgid "no cscope connections\n"
+msgstr "no hay conexiones «cscope»\n"
+
+#: if_cscope.c:2248
+msgid " # pid database name prepend path\n"
+msgstr " nº pid base de datos prefijo ruta\n"
+
+#: if_python.c:436
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: Lo siento, este comando está desactivado pues no se pudo cargar la "
+"biblioteca de Python."
+
+#: if_python.c:500
+msgid "E659: Cannot invoke Python recursively"
+msgstr "E659: No puedo invocar a Python recursivamente."
+
+#: if_python.c:701
+msgid "can't delete OutputObject attributes"
+msgstr "no se pueden borrar los atributos de «OutputObject»."
+
+#: if_python.c:708
+msgid "softspace must be an integer"
+msgstr "«softspace» debe ser un entero."
+
+#: if_python.c:716
+msgid "invalid attribute"
+msgstr "atributo no válido."
+
+#: if_python.c:755 if_python.c:769
+msgid "writelines() requires list of strings"
+msgstr "«writelines()» requiere una lista de cadenas."
+
+#: if_python.c:895
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: error de inicialización de objetos de E/S."
+
+#: if_python.c:1080 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "expresión no válida."
+
+#: if_python.c:1094 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "expresiones desactivadas al compilar."
+
+#: if_python.c:1107
+msgid "attempt to refer to deleted buffer"
+msgstr "intento de referirse a un buffer suprimido."
+
+#: if_python.c:1122 if_python.c:1163 if_python.c:1227 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "número de la línea fuera del rango."
+
+#: if_python.c:1362
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<objeto «buffer» (suprimido) en %8lX>"
+
+#: if_python.c:1453 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "nombre de marca no válido"
+
+#: if_python.c:1733
+msgid "no such buffer"
+msgstr "no existe tal buffer"
+
+#: if_python.c:1821
+msgid "attempt to refer to deleted window"
+msgstr "intento de referirse a una ventana suprimida"
+
+#: if_python.c:1866
+msgid "readonly attribute"
+msgstr "atributo de sólo lectura"
+
+#: if_python.c:1879
+msgid "cursor position outside buffer"
+msgstr "posición del cursor fuera del buffer"
+
+#: if_python.c:1956
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<objeto ventana (suprimido) en %.8lX>"
+
+#: if_python.c:1968
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<objeto ventana (desconocido) en %.8lX>"
+
+#: if_python.c:1970
+#, c-format
+msgid "<window %d>"
+msgstr "<ventana %d>"
+
+#: if_python.c:2046
+msgid "no such window"
+msgstr "no existe tal ventana"
+
+#: if_python.c:2307 if_python.c:2341 if_python.c:2396 if_python.c:2464
+#: if_python.c:2586 if_python.c:2638 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "No puedo guardar la información para deshacer."
+
+#: if_python.c:2309 if_python.c:2403 if_python.c:2475
+msgid "cannot delete line"
+msgstr "no puedo suprimir la línea"
+
+#: if_python.c:2346 if_python.c:2491 if_tcl.c:690 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "no puedo reemplazar la línea"
+
+#: if_python.c:2509 if_python.c:2588 if_python.c:2646
+msgid "cannot insert line"
+msgstr "no puedo insertar la línea"
+
+#: if_python.c:2750
+msgid "string cannot contain newlines"
+msgstr "La cadena no puede contener quiebres de línea"
+
+#: if_ruby.c:422
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: Lo siento, este comando está desactivado pues no se pudo cargar la "
+"biblioteca de Ruby."
+
+#: if_ruby.c:485
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: El estatus %d de «longjmp» no es conocido."
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Intercambiar implementación/definición"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Mostrar la clase base de"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Mostrar la función miembro que se ha sobrepasado con el código nuevo."
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Restaurar del fichero"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Restaurar del proyecto"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Restaurar de todos los proyectos"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Restaurar"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Mostrar el orígen de "
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Buscar símbolo"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Hojear la clase"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Mostrar la clase en su jerarquía"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Mostrar la clase en jerarquía restringida"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref se refiere a"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref referida por"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref tiene un"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref usada por"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Mostrar docu de"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Generar docu de"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"No puedo conectarme a SNiFF+. Verifique el entorno («sniffemacs» debe estar "
+"en $PATH).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Error al leer. Desconectado"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ está actualmente "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "no "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "conectado"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Petición de SNiFF+ desconocida: «%s»"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Error al conectarme a SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ no está conectado"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: No es un «buffer» de SNiFF+"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: error al escribir. Desconectado"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "número de «buffer» no válido"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "no implementado aún"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "opción desconocida"
+
+# ???
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "no se puede(n) poner la(s) línea(s)"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "marca sin poner"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "fila %d columna %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "no se puede insertar/añadir línea"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "indicador desconocido: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "«vimOption» desconocida"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "interrupción desde el teclado"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "error de vim"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "no puedo crear el comando de buffer/ventana: el objeto será suprimido"
+
+#: if_tcl.c:1545
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"No puedo registrar el comando «callback»: El «buffer» o la ventana ya fué "
+"eliminado."
+
+# This should never happen. Famous last word?
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: ERROR FATAL DE TCL: ¿¡«reflist» corrupta!? Por favor, informe de esto "
+"a vim-dev@vim.org"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"No puedo registrar el comando «callback»: No puedo encontrar la referencia "
+"al «buffer» o la ventana."
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"E571: Lo siento, este comando está desactivado pues no se pudo cargar la "
+"biblioteca de Tcl."
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: ERROR DE TCL: ¿¡el código de salida no es «int»!? Por favor informe de "
+"esto a vim-dev@vim.org"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "no puedo obtener la línea"
+
+#: if_xcmdsrv.c:225
+msgid "Unable to register a command server name"
+msgstr "Incapaz de registrar un nombre de servidor de comandos"
+
+#: if_xcmdsrv.c:473
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: No pude enviar el comando al programa de destino"
+
+#: if_xcmdsrv.c:747
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: El ID del usuario del servidor no es válido: «%s»."
+
+#: if_xcmdsrv.c:1110
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: VIM instance registry property is badly formed. Deleted!"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "Opción desconocida"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "Demasiados argumentos de edición."
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "Falta el argumento después de"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "Basura después de la opción"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr ""
+"Demasiados argumentos tales como: «+comando», «-c comando» o «--cmd comando»."
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "Argumento no válido para"
+
+#: main.c:466
+msgid "This Vim was not compiled with the diff feature."
+msgstr "Este Vim no ha sido compilado con la característica «diff»."
+
+#: main.c:932
+msgid "Attempt to open script file again: \""
+msgstr "Intento de abrir de nuevo el fichero «script»: «"
+
+#: main.c:941
+msgid "Cannot open for reading: \""
+msgstr "No puedo abrir para leer: «"
+
+#: main.c:985
+msgid "Cannot open for script output: \""
+msgstr "No puedo abrir para escribir la salida del «script»: «"
+
+#: main.c:1132
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d ficheros que editar\n"
+
+#: main.c:1233
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Advertencia: la salida no es a un terminal\n"
+
+#: main.c:1235
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Advertencia: la entrada no es desde un terminal\n"
+
+# just in case..
+#. just in case..
+#: main.c:1297
+msgid "pre-vimrc command line"
+msgstr "Línea de comandos anter de «vimrc»"
+
+#: main.c:1338
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: No puedo leer desde «%s»"
+
+#: main.c:2411
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Más información con: «vim -h»\n"
+
+#: main.c:2444
+msgid "[file ..] edit specified file(s)"
+msgstr "[fichero ...] edita el/los fichero(s) especificado(s)"
+
+#: main.c:2445
+msgid "- read text from stdin"
+msgstr "- lee texto de la entrada estándar"
+
+#: main.c:2446
+msgid "-t tag edit file where tag is defined"
+msgstr "-t «tag» edita el fichero donde está definido «tag»"
+
+#: main.c:2448
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [fich. err.] edita el fichero con el primer error"
+
+#: main.c:2457
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"Uso:"
+
+#: main.c:2460
+msgid " vim [arguments] "
+msgstr " vim [argumentos]"
+
+#: main.c:2464
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" o:"
+
+#: main.c:2467
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Argumentos:\n"
+
+#: main.c:2468
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tSólo nombres de ficheros después de esto"
+
+#: main.c:2470
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tNo expandir comodines"
+
+#: main.c:2473
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tRegistrar este «gvim» para «OLE»"
+
+#: main.c:2474
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tSuprimir el registro de gvim para OLE"
+
+#: main.c:2477
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tEjecutar usando el GUI (como «gvim»)"
+
+#: main.c:2478
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr ""
+"-f o --nofork\tPrimer plano: No separarse («fork») cuando se inicia la "
+"interface gráfica (GUI)."
+
+#: main.c:2480
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tModo Vi (como «vi»)"
+
+#: main.c:2481
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tModo Ex (como «ex»)"
+
+#: main.c:2482
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tModo silencioso o «batch» (sólo para «ex»)"
+
+#: main.c:2484
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tModo «diff» (como «vimdiff»)"
+
+#: main.c:2486
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tModo fácil (como «evim», sin modo)"
+
+#: main.c:2487
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tModo de sólo lectura (como «view»)"
+
+#: main.c:2488
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tModo restringido (como «rvim»)"
+
+#: main.c:2489
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tModificaciones no permitidas (escritura de ficheros)"
+
+#: main.c:2490
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tModificaciones en el texto no permitidas"
+
+#: main.c:2491
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tModo binario"
+
+#: main.c:2493
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tModo lisp"
+
+#: main.c:2495
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tCompatible con Vi: 'compatible'"
+
+#: main.c:2496
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tNo totalmente compatible con Vi: 'nocompatible'"
+
+#: main.c:2497
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tNivel de detalle de la ejecución"
+
+#: main.c:2498
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tModo de depuración"
+
+#: main.c:2499
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tSin fichero de intercambio, usa sólo la memoria"
+
+#: main.c:2500
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tDar una lista de los fichero de intercambio y salir"
+
+#: main.c:2501
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (con nombre del fichero)\tRecuperar sesión fallida"
+
+#: main.c:2502
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tIgual que -r"
+
+#: main.c:2504
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tNo usar «newcli» para abrir la ventana"
+
+#: main.c:2505
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <dispositivo>\t\tUse <dispositivo> para E/S"
+
+#: main.c:2508
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\t\tIniciar en modo árabe"
+
+#: main.c:2511
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\tIniciar en modo hebreo"
+
+#: main.c:2514
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\tIniciar en modo persa (farsi)"
+
+#: main.c:2516
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\tDetermina el tipo de terminal a <<terminal>>"
+
+#: main.c:2517
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tUsa <vimrc> en lugar de cualquier .vimrc"
+
+#: main.c:2519
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tUsa <gvimrc> en lugar de cualquier .gvimrc"
+
+#: main.c:2521
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tNo carga los «plugin scripts»"
+
+#: main.c:2522
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tAbre N ventanas (valor predeterminado: una por fichero)"
+
+#: main.c:2523
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\tComo «-o» pero divide las ventanas verticalmente."
+
+#: main.c:2524
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tComienza al final del fichero"
+
+#: main.c:2525
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\tComienza en la línea <lnum>"
+
+#: main.c:2527
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <comando>\tEjecuta <comando> antes de cargar algún fichero vimrc"
+
+#: main.c:2529
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <comando>\t\tEjecuta <comando> después de cargar el primer fichero"
+
+#: main.c:2530
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr ""
+"-S <sesión>\t\tEjecuta los comandos del fichero <sesión> después\n"
+" \t\tde cargar el primer fichero"
+
+#: main.c:2531
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <scriptin>\tLee los comandos en modo Normal del fichero <scriptin>"
+
+#: main.c:2532
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr ""
+"-w <scriptout>\tAñade todos los comandos escritos al fichero <scriptout>"
+
+#: main.c:2533
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr ""
+"-W <scriptout>\tGraba todos los comandos escritos al fichero <scriptout>"
+
+#: main.c:2535
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tEdita ficheros cifrados"
+
+#: main.c:2539
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <pantalla>\tConecta vim a este servidor X11 en particular"
+
+#: main.c:2541
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tNo se conecta al servidor X11"
+
+#: main.c:2544
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr ""
+"--remote <ficheros>\tEdita los <ficheros> en un servidor Vim si es posible."
+
+#: main.c:2545
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr ""
+"--remote-silent <ficheros> Lo mismo pero no se queja si no existe un "
+"servidor disponible."
+
+#: main.c:2546
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr ""
+"--remote-wait <ficheros>\tComo --remote pero espera a que los ficheros "
+"terminen de editarse"
+
+#: main.c:2547
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr ""
+"--remote-wait-silent <ficheros> Lo mismo pero no se queja si no hay un "
+"servidor disponible."
+
+#: main.c:2548
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <teclas>\tEnvía <teclas> a un servidor Vim y sale"
+
+#: main.c:2549
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr ""
+"--remote-expr <expr>\tEvalúa <expr> en servidor Vim e imprime el resultado"
+
+#: main.c:2550
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr ""
+"--serverlist\t\tEmite una lista de los servidores Vim disponibles y sale"
+
+#: main.c:2551
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr ""
+"--servername <nombre>\tEnvía a/se convierte en el servidor Vim de nombre "
+"<nombre>"
+
+#: main.c:2554
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tUsa <viminfo> en lugar de .viminfo"
+
+#: main.c:2556
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h or --help\tImprime la ayuda de comandos (este mensaje) y termina."
+
+#: main.c:2557
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\tImprime la información de versión y termina."
+
+#: main.c:2561
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Argumentos reconocidos por gvim (versión Motif):\n"
+
+#: main.c:2565
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr ""
+"\n"
+"Argumentos reconocidos por gvim (versión neXtaw):\n"
+
+#: main.c:2567
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Argumentos reconocidos por gvim (versión Athena):\n"
+
+#: main.c:2571
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <pantalla>\tEjecuta vim en <pantalla>"
+
+#: main.c:2572
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tArranca vim «iconizado»"
+
+#: main.c:2574
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <nombre>\t\tUsa un recurso como si vim fuese <nombre>"
+
+#: main.c:2575
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (Sin implementar)\n"
+
+#: main.c:2577
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <color>\tUsa <color> para el fondo (también: -bg)"
+
+#: main.c:2578
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <color>\tUsa <color> para el texto normal (también: -fg)"
+
+#: main.c:2579 main.c:2599
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr ""
+"-font <tipo>\t\tUsa <fuente de impresión> para el texto normal (también: -fn)"
+
+#: main.c:2580
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <tipo>\tUsa <fuente de impresión> para texto en negrita"
+
+#: main.c:2581
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <tipo>\tUsa <fuente de impresión> para texto en cursiva"
+
+#: main.c:2582 main.c:2600
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr ""
+"-geometry <geom>\tUsa <geom> para la geometría inicial (también: -geom)"
+
+#: main.c:2583
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <ancho>\tUsa un ancho de borde de <ancho> (también: -bw)"
+
+#: main.c:2584
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr ""
+"-scrollbarwidth <ancho> Usa una barra de desplazamiento de ancho <ancho> "
+"(también: -sw)"
+
+#: main.c:2586
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr ""
+"-menuheight <alt>\tUsa una barra de menú de altura <alt> (también: -mh)"
+
+#: main.c:2588 main.c:2601
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tUsar vídeo inverso (también: -rv)"
+
+#: main.c:2589
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tNo usar vídeo inverso (también: +rv)"
+
+#: main.c:2590
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <recurso>\tEstablece el recurso especificado"
+
+#: main.c:2593
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Argumentos reconocidos por gvim (versión para RISC OS):\n"
+
+#: main.c:2594
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <número>\tAnchura inicial de la ventana, en columnas"
+
+#: main.c:2595
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <número>\tAltura inicial de la ventana, en filas"
+
+#: main.c:2598
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Argumentos reconocidos por gvim (versión GTK+):\n"
+
+#: main.c:2602
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <pantalla>\tEjecuta vim en <pantalla> (también: --display)"
+
+#: main.c:2604
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr ""
+"--role <role>\tDefine un rol único para identificar la ventana principal."
+
+#: main.c:2606
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tAbre a Vim dentro de otro «widget» GTK."
+
+#: main.c:2609
+msgid "-P <parent title>\tOpen Vim inside parent application"
+msgstr "-P <título ventana padre>\tAbrir a Vim dentro de la aplicación padre."
+
+#: main.c:2847
+msgid "No display"
+msgstr "No hay una ventana"
+
+# Failed to send, abort.
+#. Failed to send, abort.
+#: main.c:2862
+msgid ": Send failed.\n"
+msgstr ": Falló el envio.\n"
+
+# Let vim start normally.
+#. Let vim start normally.
+#: main.c:2868
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ""
+": Falló el inicio de sesión remota («send»). Intentado una ejecución local.\n"
+
+#: main.c:2906 main.c:2927
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d de %d editados"
+
+#: main.c:2949
+msgid "No display: Send expression failed.\n"
+msgstr "No hay una ventana en el destino: El envio de la expresión falló.\n"
+
+#: main.c:2961
+msgid ": Send expression failed.\n"
+msgstr ": Falló el envio de la expresión.\n"
+
+#: mark.c:709
+msgid "No marks set"
+msgstr "No hay ninguna marca fijada"
+
+#: mark.c:711
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: No hay marcas que coincidan con «%s»"
+
+# Highlight title
+#. Highlight title
+#: mark.c:722
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"marca línea col fichero/texto"
+
+# Highlight title
+#. Highlight title
+#: mark.c:760
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" salto línea col fichero/texto"
+
+# Highlight title
+#. Highlight title
+#: mark.c:805
+msgid ""
+"\n"
+"change line col text"
+msgstr ""
+"\n"
+"marca línea col fichero/texto"
+
+#: mark.c:1281
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Marcas en el fichero:\n"
+
+# Write the jumplist with -'
+#. Write the jumplist with -'
+#: mark.c:1316
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Lista de saltos (el más reciente va primero):\n"
+
+#: mark.c:1412
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Historia de las marcas en los ficheros (de la más reciente a la más "
+"antigua):\n"
+
+#: mark.c:1501
+msgid "Missing '>'"
+msgstr "Falta «>»"
+
+#: mbyte.c:467
+msgid "E543: Not a valid codepage"
+msgstr "E543: No es una página de código válida."
+
+#: mbyte.c:4431
+msgid "E284: Cannot set IC values"
+msgstr "E284: No se pueden fijar los valores IC"
+
+#: mbyte.c:4583
+msgid "E285: Failed to create input context"
+msgstr "E285: Falló la creación del contexto de entrada"
+
+#: mbyte.c:4741
+msgid "E286: Failed to open input method"
+msgstr "E286: Falló la apertura del método de entrada"
+
+#: mbyte.c:4752
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: Advertencia: No pude crear un callbacl de destrucción al IM."
+
+#: mbyte.c:4758
+msgid "E288: input method doesn't support any style"
+msgstr "E288: el método de entrada no admite ningún estilo"
+
+#: mbyte.c:4815
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: El método de entrada no soporta mi tipo de preedición."
+
+#: mbyte.c:4889
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: El estilo «sobre el punto» requiere del uso de un «fontset»."
+
+#: mbyte.c:4925
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: Su GTK+ es anterior a 1.2.3. Área de estado desactivada"
+
+#: mbyte.c:5232
+msgid "E292: Input Method Server is not running"
+msgstr "E292: El servidor de método de entrada (IME) no está funcionando"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: El bloque no estaba asegurado"
+
+#: memfile.c:1005
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Error de búsqueda al leer el fichero de intercambio"
+
+#: memfile.c:1010
+msgid "E295: Read error in swap file"
+msgstr "E295: Error de lectura en el fichero de intercambio"
+
+#: memfile.c:1062
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Error de búsqueda al escribir en el fichero de intercambio"
+
+#: memfile.c:1080
+msgid "E297: Write error in swap file"
+msgstr "E297: Error de escritura en el fichero de intercambio"
+
+#: memfile.c:1277
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: Ya existe un fichero de intercambio (¿ataque de symlink?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: ¿No se obtuvo el bloque nº 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: ¿No se obtuvo el bloque nº 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: ¿No se obtuvo el bloque nº 2?"
+
+# could not (re)open the swap file, what can we do????
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: ¡¡¡Eeeh, se ha perdido el fichero de intercambio!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: No se pudo cambiar el nombre del fichero de intercambio"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr ""
+"E303: Incapaz de abrir el fichero de intercambio para «%s», recuperación "
+"imposible"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: «ml_timestamp»: ¿No se obtuvo el bloque 0?"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: No se encontró el fichero de intercambio para %s"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr ""
+"Introduzca el número del fichero de intercambio a usar (0 para salir): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: No puedo abrir %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "Incapaz de leer el bloque 0 de "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Tal vez no se han hecho cambios o Vim no actualizó el fichero de intercambio"
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " no puede usarse con esta versión de Vim.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Use la versión 3.0 de Vim.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s no parece un fichero de intercambio de Vim"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr "no puede usarse en este ordenador.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "El fichero fue creado el "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"o el fichero ha sido dañado."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "Usando el fichero de intercambio «%s»"
+
+#: memline.c:909
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Fichero original «%s»"
+
+#: memline.c:922
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Advertencia: el fichero original puede haber sido cambiado"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Incapaz de leer el bloque 1 de %s"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???FALTAN MUCHAS LÍNEAS"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???RECUENTO DE LÍNEAS EQUIVOCADO"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???BLOQUE VACÍO"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???FALTAN LÍNEAS"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ID del bloque 1 equivocado (¿no es %s un fichero .swp?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???FALTA UN BLOQUE"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? desde aquí hast ???FIN las líneas pueden estar desordenadas"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr ""
+"??? desde aquí hasta ???FIN las líneas pueden haber sido insertadas/borradas"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???FIN"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Recuperación interrumpida"
+
+#: memline.c:1148
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr ""
+"E312: Se han detectado errores al recuperar; busque líneas que empiecen "
+"con ???"
+
+#: memline.c:1150
+msgid "See \":help E312\" for more information."
+msgstr "Vea «:help E312» para más información."
+
+#: memline.c:1155
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Recuperación completada. Ud. debería comprobar que todo está bien."
+
+#: memline.c:1156
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Podría querer guardar este fichero con otro nombre\n"
+
+#: memline.c:1157
+msgid "and run diff with the original file to check for changes)\n"
+msgstr ""
+"y ejecutar «diff» con el fichero original para comprobar los cambios)\n"
+
+#: memline.c:1158
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"Suprimir el fichero .swp, después de terminar.\n"
+"\n"
+
+# use msg() to start the scrolling properly
+#. use msg() to start the scrolling properly
+#: memline.c:1214
+msgid "Swap files found:"
+msgstr "Se han encontrado ficheros de intercambio:"
+
+#: memline.c:1392
+msgid " In current directory:\n"
+msgstr " En el directorio actual:\n"
+
+#: memline.c:1394
+msgid " Using specified name:\n"
+msgstr " Usando el nombre especificado:\n"
+
+#: memline.c:1398
+msgid " In directory "
+msgstr " En el directorio "
+
+#: memline.c:1416
+msgid " -- none --\n"
+msgstr " -- ninguno --\n"
+
+#: memline.c:1488
+msgid " owned by: "
+msgstr " propiedad de: "
+
+#: memline.c:1490
+msgid " dated: "
+msgstr " de fecha: "
+
+#: memline.c:1494 memline.c:3684
+msgid " dated: "
+msgstr " de fecha: "
+
+#: memline.c:1510
+msgid " [from Vim version 3.0]"
+msgstr " [desde la versión 3.0 de Vim]"
+
+#: memline.c:1514
+msgid " [does not look like a Vim swap file]"
+msgstr " [no parece un fichero de intercambio de Vim]"
+
+#: memline.c:1518
+msgid " file name: "
+msgstr " nombre del fichero: "
+
+#: memline.c:1524
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" modificado: "
+
+#: memline.c:1525
+msgid "YES"
+msgstr "SI"
+
+#: memline.c:1525
+msgid "no"
+msgstr "no"
+
+#: memline.c:1529
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" nombre del usuario: "
+
+#: memline.c:1536
+msgid " host name: "
+msgstr " nombre del «host»: "
+
+#: memline.c:1538
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" nombre del «host»: "
+
+#: memline.c:1544
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ID del proceso: "
+
+#: memline.c:1550
+msgid " (still running)"
+msgstr " (aún en ejecución)"
+
+#: memline.c:1562
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [no se peude usar con esta versión de Vim]"
+
+#: memline.c:1565
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [no se puede usar en este ordenador]"
+
+#: memline.c:1570
+msgid " [cannot be read]"
+msgstr " [no se puede leer]"
+
+#: memline.c:1574
+msgid " [cannot be opened]"
+msgstr " [no se puede abrir]"
+
+#: memline.c:1764
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: No puedo preservarlo, no existe un fichero de intercambio"
+
+#: memline.c:1817
+msgid "File preserved"
+msgstr "fichero preservado"
+
+#: memline.c:1819
+msgid "E314: Preserve failed"
+msgstr "E314: Falló la preservación del fichero"
+
+#: memline.c:1890
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: «ml_get»: número de línea no válido: %ld"
+
+#: memline.c:1916
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: «ml_get»: no puedo encontrar la línea %ld"
+
+#: memline.c:2306
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: El id del bloque de punteros está equivocado. 3"
+
+#: memline.c:2386
+msgid "stack_idx should be 0"
+msgstr "«stack_idx» debería ser 0"
+
+#: memline.c:2448
+msgid "E318: Updated too many blocks?"
+msgstr "E318: ¿Demasiados bloques actualizados?"
+
+#: memline.c:2630
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: El id del bloque de punteros está equivocado. 4"
+
+#: memline.c:2657
+msgid "deleted block 1?"
+msgstr "¿bloque 1 suprimido?"
+
+#: memline.c:2857
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: No puedo encontrar la línea %ld"
+
+#: memline.c:3100
+msgid "E317: pointer block id wrong"
+msgstr "E317: El id del bloque de punteros está equivocado."
+
+#: memline.c:3116
+msgid "pe_line_count is zero"
+msgstr "«pe_line_count» es cero"
+
+#: memline.c:3145
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: número de línea fuera de rango: %ld más allá del final"
+
+#: memline.c:3149
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: recuento de líneas erróneo en el bloque %ld"
+
+#: memline.c:3198
+msgid "Stack size increases"
+msgstr "El tamaño de la pila aumenta"
+
+#: memline.c:3244
+msgid "E317: pointer block id wrong 2"
+msgstr "E310: El id del bloque de punteros está equivocado. 2"
+
+#: memline.c:3674
+msgid "E325: ATTENTION"
+msgstr "E325: ATENCIÓN"
+
+#: memline.c:3675
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Se ha encontrado un fichero de intercambio con el nombre «"
+
+#: memline.c:3679
+msgid "While opening file \""
+msgstr "al abrir el fichero «"
+
+#: memline.c:3688
+msgid " NEWER than swap file!\n"
+msgstr " MÁS NUEVO que el fichero de intercambio!\n"
+
+# Some of these messages are long to allow translation to
+# * other languages.
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3692
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Otro programa puede estar editando el mismo fichero.\n"
+" De ser así, tenga cuidado de no acabar con dos\n"
+" ejemplares diferentes del mismo fichero al hacer cambios.\n"
+
+#: memline.c:3693
+msgid " Quit, or continue with caution.\n"
+msgstr " Salga del programa o continue con precaución.\n"
+
+#: memline.c:3694
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) Falló una sesión de edición de este fichero.\n"
+
+#: memline.c:3695
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Si es así, use «:recover» o «vim -r "
+
+#: memline.c:3697
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"»\n"
+" para recuperar los cambios (véa «:help recovery»).\n"
+
+#: memline.c:3698
+msgid " If you did this already, delete the swap file \""
+msgstr " Si Ud. ya ha hecho esto, borre el fichero de intercambio «"
+
+#: memline.c:3700
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"»\n"
+" para evitar este mensaje.\n"
+
+#: memline.c:3714 memline.c:3718
+msgid "Swap file \""
+msgstr "¡El fichero de intercambio «"
+
+#: memline.c:3715 memline.c:3721
+msgid "\" already exists!"
+msgstr "» ya existe!"
+
+#: memline.c:3724
+msgid "VIM - ATTENTION"
+msgstr "VIM - ATENCIÓN"
+
+#: memline.c:3726
+msgid "Swap file already exists!"
+msgstr "¡Ya existe un fichero de intercambio!"
+
+#: memline.c:3730
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort"
+msgstr ""
+"&Abrir para lectura únicamente\n"
+"&Editar de todas formas\n"
+"&Recuperar\n"
+"&Salir\n"
+"&Abortar"
+
+#: memline.c:3732
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort\n"
+"&Delete it"
+msgstr ""
+"&Abrir para lectura únicamente\n"
+"&Editar de todas formas\n"
+"&Recuperar\n"
+"&Salir\n"
+"&Abortar\n"
+"&Borrarlo"
+
+#: memline.c:3789
+msgid "E326: Too many swap files found"
+msgstr "E326: Se han encontrado demasiados ficheros de intercambio"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Parte de la ruta del item del menú no es un sub-menú"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: El menú sólo existe en otro modo de operación"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: No existe un menú con ese nombre"
+
+#: menu.c:525
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: La ruta del menú no debe conducir a un sub-menú"
+
+#: menu.c:564
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr ""
+"E331: No se deben añadir items del menú directamente a la barra del menú"
+
+#: menu.c:570
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: El separador no puede ser parte de una ruta de menú"
+
+# Now we have found the matching menu, and we list the mappings
+# Highlight title
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1097
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Menús ---"
+
+#: menu.c:2019
+msgid "Tear off this menu"
+msgstr "Desprender y flotar este menú"
+
+#: menu.c:2084
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: La ruta del menu debe conducir a un item del menú"
+
+#: menu.c:2104
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: No se ha encontrado el menú: %s"
+
+#: menu.c:2173
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: El menú no está definido para el modo %s"
+
+#: menu.c:2211
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: La ruta del menú debe conducir a un sub-menú"
+
+#: menu.c:2232
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: No se ha encontrado el menú - verifique los nombres de los menús"
+
+#: message.c:414
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Se ha detectado un error al procesar %s:"
+
+#: message.c:440
+#, c-format
+msgid "line %4ld:"
+msgstr "línea %4ld"
+
+#: message.c:647
+msgid "[string too long]"
+msgstr "[cadena demasiado larga]"
+
+#: message.c:797
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr ""
+"Mantenedor de los mensajes: Alejandro López-Valencia <dradul@yahoo.com>"
+
+#: message.c:1025
+msgid "Interrupt: "
+msgstr "Interrupción: "
+
+#: message.c:1028
+msgid "Hit ENTER to continue"
+msgstr "Pulse INTRO para continuar"
+
+#: message.c:1030
+msgid "Hit ENTER or type command to continue"
+msgstr "Pulse INTRO o escriba un comando para continuar"
+
+#: message.c:2351
+msgid "-- More --"
+msgstr "-- Más --"
+
+#: message.c:2354
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: línea, ESPACIO/b: página, d/u: media página, q: salir)"
+
+#: message.c:2355
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: línea, ESPACIO: página, d: media página, q: salir)"
+
+#: message.c:2982 message.c:2997
+msgid "Question"
+msgstr "Pregunta"
+
+#: message.c:2984
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Si\n"
+"&No"
+
+#: message.c:3017
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Si\n"
+"&No\n"
+"&Guardar todo\n"
+"&Descartar todo\n"
+"&Cancelar"
+
+#: message.c:3058
+msgid "Save File dialog"
+msgstr "Diálogo de Guardar Fichero"
+
+#: message.c:3060
+msgid "Open File dialog"
+msgstr "Diálogo de Abrir Fichero"
+
+#. TODO: non-GUI file selector here
+#: message.c:3131
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: Lo siento, no hay hojeador de ficheros en modo de consola"
+
+#: misc1.c:2773
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: Advertencia: cambiando un fichero de sólo lectura"
+
+#: misc1.c:3021
+msgid "1 more line"
+msgstr "1 línea más"
+
+#: misc1.c:3023
+msgid "1 line less"
+msgstr "1 línea menos"
+
+#: misc1.c:3028
+#, c-format
+msgid "%ld more lines"
+msgstr "%ld líneas más"
+
+#: misc1.c:3030
+#, c-format
+msgid "%ld fewer lines"
+msgstr "%ld líneas menos"
+
+#: misc1.c:3033
+msgid " (Interrupted)"
+msgstr " (Interrumpido)"
+
+#: misc1.c:7588
+msgid "Vim: preserving files...\n"
+msgstr "Vim: preservando ficheros...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:7598
+msgid "Vim: Finished.\n"
+msgstr "Vim: finalizado.\n"
+
+#: misc2.c:695 misc2.c:711
+msgid "ERROR: "
+msgstr "ERROR: "
+
+#: misc2.c:715
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bytes] total liberado por alloc %lu-%lu, en uso %lu, uso máximo %lu\n"
+
+#: misc2.c:717
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[lamadas] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+
+#: misc2.c:772
+msgid "E340: Line is becoming too long"
+msgstr "E340: La línea se está haciendo demasiado larga"
+
+#: misc2.c:816
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Error interno: lalloc(%ld, )"
+
+#: misc2.c:924
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: ¡Memoria agotada! (al asignar %lu bytes)"
+
+#: misc2.c:2594
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Llamando a la «shell» para ejecutar: «%s»"
+
+#: misc2.c:2816
+msgid "E545: Missing colon"
+msgstr "E545: Falta un símbolo de dos puntos."
+
+#: misc2.c:2818 misc2.c:2845
+msgid "E546: Illegal mode"
+msgstr "E546: Modo de operación ilegal."
+
+#: misc2.c:2884
+msgid "E547: Illegal mouseshape"
+msgstr "E547: El «mouseshape» no es válido."
+
+#: misc2.c:2924
+msgid "E548: digit expected"
+msgstr "E548: Se esperaba un dígito."
+
+#: misc2.c:2929
+msgid "E549: Illegal percentage"
+msgstr "E549: Porcentaje ilegal."
+
+#: misc2.c:3239
+msgid "Enter encryption key: "
+msgstr "Introduzca la clave de cifrado: "
+
+#: misc2.c:3240
+msgid "Enter same key again: "
+msgstr "Introduzca la misma clave de cifrado otra vez: "
+
+#: misc2.c:3250
+msgid "Keys don't match!"
+msgstr "¡Las claves de cifrado no coinciden!"
+
+#: misc2.c:3799
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Ruta no válida: '**[número]' debe estar al final de la ruta o seguido "
+"de «%s»."
+
+#: misc2.c:5078
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: No se puede encontrar el directorio «%s» en «cdpath»"
+
+#: misc2.c:5081
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: No se puede encontrar el fichero «%s» en la ruta"
+
+#: misc2.c:5087
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: No se han encontrado mas directorios «%s» en «cdpath»"
+
+#: misc2.c:5090
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: No se han encontrado mas ficheros «%s» en la ruta"
+
+#: misc2.c:5324
+msgid "E550: Missing colon"
+msgstr "E550: Falta un símbolo de dos puntos."
+
+#: misc2.c:5336
+msgid "E551: Illegal component"
+msgstr "E551: Componente ilegal."
+
+#: misc2.c:5344
+msgid "E552: digit expected"
+msgstr "E552: se esperaba un dígito."
+
+# Get here when the server can't be found.
+#. Get here when the server can't be found.
+#: netbeans.c:396
+msgid "Cannot connect to Netbeans #2"
+msgstr "No puedo conectarme a Netbeans #2"
+
+#: netbeans.c:404
+msgid "Cannot connect to Netbeans"
+msgstr "No puedo conectarme a Netbeans"
+
+# c-format
+#: netbeans.c:450
+#, c-format
+msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\""
+msgstr "E668: El dueño(a) del fichero de conexión NetBeans no es válido: «%s»"
+
+#: netbeans.c:749
+msgid "read from Netbeans socket"
+msgstr "leido del socket Netbeans"
+
+#: netbeans.c:1643
+#, c-format
+msgid "E658: NetBeans connection lost for buffer %ld"
+msgstr "E658: Se perdió la conexión NetBeans para el «buffer» %ld."
+
+#: normal.c:2980
+msgid "Warning: terminal cannot highlight"
+msgstr "Advertencia: el terminal no puede realzar el texto"
+
+#: normal.c:3276
+msgid "E348: No string under cursor"
+msgstr "E348: No hay ninguna cadena bajo el cursor"
+
+#: normal.c:3278
+msgid "E349: No identifier under cursor"
+msgstr "E349: No hay ningún identificador bajo el cursor"
+
+#: normal.c:4519
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: No puedo borar pliegues con el «folmethod» actual."
+
+#: normal.c:6740
+msgid "E664: changelist is empty"
+msgstr "E664: La lista de cambios está vacía."
+
+#: normal.c:6742
+msgid "E662: At start of changelist"
+msgstr "E662: Al comienzo de la lista de cambios."
+
+#: normal.c:6744
+msgid "E663: At end of changelist"
+msgstr "E663: Al final de la lista de cambios."
+
+#: normal.c:8005
+msgid "Type :quit<Enter> to exit Vim"
+msgstr "Escriba :quit<enter> para terminar la ejecución de Vim."
+
+#: ops.c:294
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "1 línea %sed 1 vez."
+
+#: ops.c:296
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 línea %sed %d veces."
+
+#: ops.c:301
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld líneas %sed 1 vez."
+
+#: ops.c:304
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld líneas %sed %d veces."
+
+#: ops.c:662
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld líneas por sangrar..."
+
+#: ops.c:712
+msgid "1 line indented "
+msgstr "1 línea sangrada"
+
+#: ops.c:714
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld líneas sangradas"
+
+# Debe mostrar la línea de comandos.
+#. must display the prompt
+#: ops.c:1675
+msgid "cannot yank; delete anyway"
+msgstr "No puedo hacer un «yank»; ¿Lo borro de todas formas?"
+
+#: ops.c:2261
+msgid "1 line changed"
+msgstr "1 línea cambiada"
+
+#: ops.c:2263
+#, c-format
+msgid "%ld lines changed"
+msgstr "%ld líneas cambiadas"
+
+#: ops.c:2647
+#, c-format
+msgid "freeing %ld lines"
+msgstr "liberando %ld líneas"
+
+#: ops.c:2928
+msgid "1 line yanked"
+msgstr "1 línea copiada"
+
+#: ops.c:2930
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld líneas copiadas"
+
+#: ops.c:3215
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: No hay nada en el registro %s"
+
+# Highlight title
+#. Highlight title
+#: ops.c:3766
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Registros ---"
+
+#: ops.c:5075
+msgid "Illegal register name"
+msgstr "Nombre de registro ilegal"
+
+#: ops.c:5163
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Registros:\n"
+
+#: ops.c:5213
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: Registro desconocido de tipo «%d»."
+
+#: ops.c:5698
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: Nombre de registro no válido: '%s'"
+
+#: ops.c:6058
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Cols; "
+
+#: ops.c:6065
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr ""
+"Seleccionadas %s%ld de %ld Líneas; %ld de %ld Palabras; %ld de %ld Caracteres"
+
+#: ops.c:6081
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr ""
+"Col %s de %s; Línea %ld de %ld; Palabra %ld de %ld; Carácter %ld de %ld"
+
+#: ops.c:6092
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld para BOM)"
+
+#: option.c:1643
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=Página %N"
+
+#: option.c:2092
+msgid "Thanks for flying Vim"
+msgstr "Gracias por volar con Vim"
+
+#: option.c:3419 option.c:3535
+msgid "E518: Unknown option"
+msgstr "E518: Opción desconocida."
+
+#: option.c:3432
+msgid "E519: Option not supported"
+msgstr "E519: Opción no admitida"
+
+#: option.c:3457
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: No se permite en una «modeline»"
+
+#: option.c:3522
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tSe definió por última vez en "
+
+#: option.c:3661
+msgid "E521: Number required after ="
+msgstr "E521: Se necesita un número despues de «=»"
+
+#: option.c:3989 option.c:4619
+msgid "E522: Not found in termcap"
+msgstr "E522: No lo encontré en el «termcap»."
+
+#: option.c:4064
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: Carácter ilegal <%s>"
+
+#: option.c:4611
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: No puedo definir «term» como una cadena de caracteres vacía."
+
+#: option.c:4614
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: No puedo cambiar «term» en la GUI."
+
+#: option.c:4616
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: Use «:gui» para iniciar la GUI."
+
+#: option.c:4645
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: «backupext» y «patchmode» son iguales."
+
+#: option.c:4860
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: No puede cambiarse en el GUI de GTK+ 2."
+
+#: option.c:5016
+msgid "E524: Missing colon"
+msgstr "E524: Falta un símbolo de dos puntos."
+
+#: option.c:5018
+msgid "E525: Zero length string"
+msgstr "E525: Cadena de caracteres de largo cero."
+
+#: option.c:5086
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: Falta el número despues de <%s>."
+
+#: option.c:5100
+msgid "E527: Missing comma"
+msgstr "E527: Falta una coma."
+
+#: option.c:5107
+msgid "E528: Must specify a ' value"
+msgstr "E528: Debe especificar un valor '"
+
+#: option.c:5148
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: Contiene un caracter no imprimible o de más de un byte de ancho."
+
+#: option.c:5197
+msgid "E596: Invalid font(s)"
+msgstr "E596: Las fuente(s) de impresión no son válidas."
+
+#: option.c:5205
+msgid "E597: can't select fontset"
+msgstr "E597: No puedo seleccionar ese «fontset»."
+
+#: option.c:5207
+msgid "E598: Invalid fontset"
+msgstr "E598: El conjunto de fuentes de impresión no es válido."
+
+#: option.c:5214
+msgid "E533: can't select wide font"
+msgstr ""
+"E533: No puedo seleccionar la fuente de impresión «ancha» (de byte doble)."
+
+#: option.c:5216
+msgid "E534: Invalid wide font"
+msgstr "E534: Fuente de impresión «ancha» inválida."
+
+#: option.c:5486
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: arácter ilegal después de <%c>."
+
+#: option.c:5597
+msgid "E536: comma required"
+msgstr "E536: Se requiere una coma."
+
+#: option.c:5607
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: «commentstring» debe estar vacio o contener «%s»."
+
+#: option.c:5679
+msgid "E538: No mouse support"
+msgstr "E538: No hay soporte para el ratón."
+
+#: option.c:5947
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: SEcuencia de expresión sin cerrar."
+
+#: option.c:5951
+msgid "E541: too many items"
+msgstr "E541: Demasiados ítems."
+
+#: option.c:5953
+msgid "E542: unbalanced groups"
+msgstr "E542: Grupos desbalanceados."
+
+#: option.c:6193
+msgid "E590: A preview window already exists"
+msgstr "E590: Ya existe una ventana de visualización previa."
+
+#: option.c:6450
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr ""
+"W17: El uso de árabe requiere la codificación UTF-8, use «:set encoding=utf-"
+"8» primero."
+
+#: option.c:6783
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: Necesita al menos %d líneas."
+
+#: option.c:6793
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: Necesita al menos %d columnas."
+
+#: option.c:7100
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Opción desconocida: %s"
+
+#: option.c:7220
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Códigos de terminal ---"
+
+#: option.c:7222
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Valores de las opciones globales ---"
+
+#: option.c:7224
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Valores de las opciones locales ---"
+
+#: option.c:7226
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Opciones ---"
+
+#: option.c:7932
+msgid "E356: get_varp ERROR"
+msgstr "E356: ERROR de «get_varp»"
+
+#: option.c:8903
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: «langmap»: falta carácter coincidente para %s"
+
+#: option.c:8937
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: «langmap»: caracteres extra después del punto y coma: %s"
+
+#: os_amiga.c:280
+msgid "cannot open "
+msgstr "No puedo abrirlo"
+
+#: os_amiga.c:314
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: ¡No puedo abrir la ventana!\n"
+
+#: os_amiga.c:338
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Necesito la versión 2.04 o posterior de Amigados\n"
+
+#: os_amiga.c:344
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Necesito %s versión %ld\n"
+
+#: os_amiga.c:416
+msgid "Cannot open NIL:\n"
+msgstr "No puedo abrir NIL:\n"
+
+#: os_amiga.c:427
+msgid "Cannot create "
+msgstr "No puedo crear "
+
+#: os_amiga.c:905
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Saliendo de Vim con %d\n"
+
+#: os_amiga.c:937
+msgid "cannot change console mode ?!\n"
+msgstr "¡¿No puedo cambiar el modo de la consola?!\n"
+
+#: os_amiga.c:1003
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "«mch_get_shellsize»: ¿No es una consola?\n"
+
+# if Vim opened a window: Executing a shell may cause crashes
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1152
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: No se puede ejecutar la «shell» con la opción -f"
+
+#: os_amiga.c:1193 os_amiga.c:1283
+msgid "Cannot execute "
+msgstr "No puedo ejecutarlo "
+
+#: os_amiga.c:1196 os_amiga.c:1293
+msgid "shell "
+msgstr "«shell» "
+
+#: os_amiga.c:1216 os_amiga.c:1318
+msgid " returned\n"
+msgstr " devuelto\n"
+
+#: os_amiga.c:1459
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "«ANCHOR_BUF_SIZE» demasiado pequeño"
+
+#: os_amiga.c:1463
+msgid "I/O ERROR"
+msgstr "ERROR E/S"
+
+#: os_mswin.c:539
+msgid "...(truncated)"
+msgstr "...(truncado)"
+
+#: os_mswin.c:641
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' no es 80, no se pueden ejecutar comandos externos"
+
+#: os_mswin.c:1973
+msgid "E237: Printer selection failed"
+msgstr "E237: FAlló la selectión de impresora."
+
+#: os_mswin.c:2013
+#, c-format
+msgid "to %s on %s"
+msgstr "para %s en %s"
+
+#: os_mswin.c:2028
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: Fuente de impresión desconocida en la impresora: %s"
+
+#: os_mswin.c:2077 os_mswin.c:2087
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Error de impresión: %s"
+
+#: os_mswin.c:2088
+msgid "Unknown"
+msgstr "Desconocido"
+
+#: os_mswin.c:2115
+#, c-format
+msgid "Printing '%s'"
+msgstr "Imprimiendo «%s»"
+
+#: os_mswin.c:3204
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr ""
+"E244: El nombre del conjunto de caracteres «%s» no es válido en el nombre de "
+"la fuente de impresión «%s»"
+
+#: os_mswin.c:3212
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Carácter «%c» ilegal en el nombre de la fuente de impresión «%s»"
+
+#: os_riscos.c:1259
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Opción «osfiletype» inválida - usando Text"
+
+#: os_unix.c:927
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: doble señal, saliendo\n"
+
+#: os_unix.c:933
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: capté una señal de muerte %s\n"
+
+#: os_unix.c:936
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: capté una señal de muerte\n"
+
+#: os_unix.c:1199
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Abrir la pantalla X tomó %ld ms"
+
+#: os_unix.c:1226
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: Hay un error de X11\n"
+
+#: os_unix.c:1334
+msgid "Testing the X display failed"
+msgstr "Falló la prueba del sistema X11"
+
+#: os_unix.c:1473
+msgid "Opening the X display timed out"
+msgstr "El «display» de X no abrió a tiempo."
+
+#: os_unix.c:3230 os_unix.c:3910
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"No puedo ejecutar la «shell» "
+
+#: os_unix.c:3278
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"No puedo ejecutar la «shell» «sh»\n"
+
+#: os_unix.c:3282 os_unix.c:3916
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"La «shell» ha devuelto "
+
+#: os_unix.c:3417
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"No puedo crear «pipes»\n"
+
+#: os_unix.c:3432
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"No puedo usar «fork»\n"
+
+#: os_unix.c:3923
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Comando finalizado\n"
+
+#: os_unix.c:4187 os_unix.c:4312 os_unix.c:5978
+msgid "XSMP lost ICE connection"
+msgstr "XSMP perdió la conexión ICE."
+
+#: os_unix.c:5561
+msgid "Opening the X display failed"
+msgstr "Falló la apertura de la pantalla X11"
+
+#: os_unix.c:5883
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP está manejando una solicitud de «guardelo usted mismo»."
+
+#: os_unix.c:6002
+msgid "XSMP opening connection"
+msgstr "XSMP está abriendo una conexión."
+
+#: os_unix.c:6021
+msgid "XSMP ICE connection watch failed"
+msgstr "XSMP Falló el monitoreo de la conexión ICE."
+
+#: os_unix.c:6041
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP SmcOpenConnection ha fallado: %s."
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "En la línea"
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "No pude designar memoria para la línea de comandos."
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "Error de Vim"
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "¡No pude cargar vim32.dll!"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "¡No pude fijar los punteros de la función a la DLL!"
+
+#: os_win16.c:342 os_win32.c:3248
+#, c-format
+msgid "shell returned %d"
+msgstr "La «shell» ha devuelto %d"
+
+#: os_win32.c:2706
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Capté el evento %s\n"
+
+#: os_win32.c:2708
+msgid "close"
+msgstr "cerrar"
+
+#: os_win32.c:2710
+msgid "logoff"
+msgstr "salida"
+
+#: os_win32.c:2711
+msgid "shutdown"
+msgstr "apagar"
+
+#: os_win32.c:3201
+msgid "E371: Command not found"
+msgstr "E371: No se encuentra el comando"
+
+#: os_win32.c:3214
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE no se encuentra en su $PATH.\n"
+"Los comandos externos no harán una pausa al finalizar.\n"
+"Véase :help win32-vimrun para más información"
+
+#: os_win32.c:3217
+msgid "Vim Warning"
+msgstr "Advertencia de Vim"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Demasiados %%%c en la cadena de formato"
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: %%%c inesperado en la cadena de formato"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: Falta ] en la cadena de formato"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: %%%c no admitido en cadena de formato"
+
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: %%%c no válido en el prefijo de una cadena de formato"
+
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: %%%c no válido en una cadena de formato"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: «errorformat» no contiene un patrón"
+
+#: quickfix.c:501
+msgid "E379: Missing or empty directory name"
+msgstr "E379: El nombre del directorio falta o está vacío"
+
+#: quickfix.c:990
+msgid "E553: No more items"
+msgstr "E553: No hay más ítems."
+
+#: quickfix.c:1229
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d de %d)%s%s: "
+
+#: quickfix.c:1231
+msgid " (line deleted)"
+msgstr " (línea borrada)"
+
+#: quickfix.c:1444
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Al final de la pila de correción rápida"
+
+#: quickfix.c:1453
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Al principio de la pila de correción rápida"
+
+#: quickfix.c:1465
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "lista de errores %d de %d: %d errores"
+
+#: quickfix.c:1943
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: No se puede grabar, la opción «buftype» está activada"
+
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: El ítem en %s%%[] no es válido."
+
+#: regexp.c:838
+msgid "E339: Pattern too long"
+msgstr "E339: Patrón demasiado largo"
+
+#: regexp.c:1009
+msgid "E50: Too many \\z("
+msgstr "E50: Demasiados \\z("
+
+#: regexp.c:1020
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: Hay demasiados %s("
+
+#: regexp.c:1077
+msgid "E52: Unmatched \\z("
+msgstr "E52: \\z( sin complemento."
+
+#: regexp.c:1081
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: %s%%( sin complemento."
+
+#: regexp.c:1083
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: %s( sin complemento."
+
+#: regexp.c:1088
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: %s) sin complemento."
+
+#: regexp.c:1258
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: El operando %s* podría estar vacío."
+
+#: regexp.c:1261
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: EL operando %s+ podría estar vacío."
+
+#: regexp.c:1316
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: Carácter inválido después de %s@"
+
+#: regexp.c:1344
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: EL operando %s{ podría estar vacío."
+
+#: regexp.c:1354
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: Hay demasiados %s{...}s complejos."
+
+#: regexp.c:1370
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: Anidado %s*"
+
+#: regexp.c:1373
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: Anidado %s%c"
+
+#: regexp.c:1491
+msgid "E63: invalid use of \\_"
+msgstr "E63: Uso inválido de \\_"
+
+#: regexp.c:1536
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c no sigue a nada"
+
+#: regexp.c:1592
+msgid "E65: Illegal back reference"
+msgstr "E65: Refernecia reversa ilegal."
+
+#: regexp.c:1605
+msgid "E66: \\z( not allowed here"
+msgstr "E66: No se permite \\z( aquí."
+
+#: regexp.c:1624
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 et al. no están permitidos aquí."
+
+# Es preferible traducir "invalid" por "no [es] válido" pues "inválido" no es lo suficientemente claro. Además, no es políticamente correcto :-)
+#: regexp.c:1635
+msgid "E68: Invalid character after \\z"
+msgstr "E68: Hay un carácter no válido después de \\z"
+
+#: regexp.c:1684
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: Falta ] despues de %s%%["
+
+#: regexp.c:1700
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: %s%%[] vacío."
+
+#: regexp.c:1760
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: Carácter ilegal después de %s%%"
+
+#: regexp.c:2557
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: Eror de sintáxis en %s{...}."
+
+#: regexp.c:2863 regexp.c:3016
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Intercepté un «crash»; ¿expresión regular muy compleja?"
+
+#: regexp.c:3004 regexp.c:3013
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: el patrón ha provocado un error «out-of-stack»"
+
+#: regexp.c:3258
+msgid "External submatches:\n"
+msgstr "Subcoincidencias externas:\n"
+
+#: screen.c:2184
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld líneas plegadas"
+
+#: screen.c:7996
+msgid " VREPLACE"
+msgstr " REEMPLAZAMIENTO VIRTUAL"
+
+#: screen.c:8000
+msgid " REPLACE"
+msgstr " REEMPLAZAR"
+
+#: screen.c:8005
+msgid " REVERSE"
+msgstr " INVERTIR"
+
+#: screen.c:8007
+msgid " INSERT"
+msgstr " INSERTAR"
+
+#: screen.c:8010
+msgid " (insert)"
+msgstr " (insertar)"
+
+#: screen.c:8012
+msgid " (replace)"
+msgstr " (reemplazar)"
+
+#: screen.c:8014
+msgid " (vreplace)"
+msgstr " (reemplazamiento virtual)"
+
+#: screen.c:8017
+msgid " Hebrew"
+msgstr " Hebreo"
+
+#: screen.c:8028
+msgid " Arabic"
+msgstr " árabe"
+
+#: screen.c:8031
+msgid " (lang)"
+msgstr " (idioma)"
+
+#: screen.c:8035
+msgid " (paste)"
+msgstr " (pegar)"
+
+#: screen.c:8048
+msgid " VISUAL"
+msgstr " VISUAL"
+
+#: screen.c:8049
+msgid " VISUAL LINE"
+msgstr " LÍNEA VISUAL"
+
+#: screen.c:8050
+msgid " VISUAL BLOCK"
+msgstr " BLOQUE VISUAL"
+
+#: screen.c:8051
+msgid " SELECT"
+msgstr " SELECCIONAR"
+
+#: screen.c:8052
+msgid " SELECT LINE"
+msgstr " SELECCIONAR LÍNEA"
+
+#: screen.c:8053
+msgid " SELECT BLOCK"
+msgstr " SELECCIONAR BLOQUE"
+
+#: screen.c:8068 screen.c:8131
+msgid "recording"
+msgstr "grabando"
+
+#: search.c:37
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "La búsqueda ha llegado al PRINCIPIO, continuando desde el FINAL."
+
+#: search.c:38
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "La búsqueda ha llegado al FINAL, continuando desde el PRINCIPIO"
+
+#: search.c:526
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Cadena de búsqueda no válida: %s"
+
+#: search.c:853
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: La búsqueda ha llegado al PRINCIPIO sin coincidencias con: %s"
+
+#: search.c:856
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: La búsqueda ha llegado al FINAL sin coincidencias con: %s"
+
+#: search.c:1249
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: Esperaba «?» o «/» después de «;»"
+
+#: search.c:3759
+msgid " (includes previously listed match)"
+msgstr " (incluye la coincidencia mostrada previamente)."
+
+# cursor at status line
+#. cursor at status line
+#: search.c:3779
+msgid "--- Included files "
+msgstr "--- Ficheros incluidos "
+
+#: search.c:3781
+msgid "not found "
+msgstr "no lo encontré"
+
+#: search.c:3782
+msgid "in path ---\n"
+msgstr "en la ruta ---\n"
+
+#: search.c:3839
+msgid " (Already listed)"
+msgstr " (Ya lo enumeré)"
+
+#: search.c:3841
+msgid " NOT FOUND"
+msgstr " NO SE ENCONTRÓ"
+
+#: search.c:3893
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Explorando el fichero incluido: %s"
+
+#: search.c:4111
+msgid "E387: Match is on current line"
+msgstr "E387: La coincidencia está en la línea en curso."
+
+#: search.c:4254
+msgid "All included files were found"
+msgstr "Se han encontrado todos los ficheros incluidos"
+
+#: search.c:4256
+msgid "No included files"
+msgstr "No hay ficheros incluidos"
+
+#: search.c:4272
+msgid "E388: Couldn't find definition"
+msgstr "E388: No se pudo encontrar la definición"
+
+#: search.c:4274
+msgid "E389: Couldn't find pattern"
+msgstr "E389: No se pudo encontrar el patrón"
+
+#: syntax.c:3050
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: Argumento ilegal: %s"
+
+#: syntax.c:3230
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: No existe tal agrupamiento sintáctico: %s"
+
+#: syntax.c:3394
+msgid "No Syntax items defined for this buffer"
+msgstr "No hay ítems sintácticos definidos para este «buffer»"
+
+#: syntax.c:3402
+msgid "syncing on C-style comments"
+msgstr "Sincronizando en los comentarios de estilo «C»."
+
+#: syntax.c:3410
+msgid "no syncing"
+msgstr "no hay sincronización"
+
+#: syntax.c:3413
+msgid "syncing starts "
+msgstr "Comenzando sincronización."
+
+#: syntax.c:3415 syntax.c:3490
+msgid " lines before top line"
+msgstr " líneas antes de la línea superior"
+
+#: syntax.c:3420
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Ítems de sincronización de sintáxis ---"
+
+#: syntax.c:3425
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"sincronizando en los ítems"
+
+#: syntax.c:3431
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Items sintácticos ---"
+
+#: syntax.c:3454
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: No existe tal agrupamiento sintáctico: %s"
+
+#: syntax.c:3480
+msgid "minimal "
+msgstr "mínimo"
+
+#: syntax.c:3487
+msgid "maximal "
+msgstr "máximo"
+
+#: syntax.c:3499
+msgid "; match "
+msgstr "; coincide"
+
+#: syntax.c:3501
+msgid " line breaks"
+msgstr " líneas de quiebre"
+
+#: syntax.c:4135
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: group[t]here not accepted here"
+
+#: syntax.c:4159
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: No se encuentra el item de región para %s"
+
+#: syntax.c:4187
+msgid "E395: contains argument not accepted here"
+msgstr "E395: el contenido del argumento no se acepta aquí"
+
+#: syntax.c:4198
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: el argumento «containedin» no se acepta aquí"
+
+#: syntax.c:4276
+msgid "E397: Filename required"
+msgstr "E397: Hace falta un nombre de fichero"
+
+#: syntax.c:4614
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Falta el «=»: %s"
+
+#: syntax.c:4772
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Argumentos insuficientes: región de sintaxis %s"
+
+#: syntax.c:5103
+msgid "E400: No cluster specified"
+msgstr "E400: No se ha especificado una agrupación"
+
+#: syntax.c:5140
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: No hay un delimitador de patrón: %s"
+
+#: syntax.c:5215
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Basura después del patrón: %s"
+
+#: syntax.c:5305
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr ""
+"E403: Sincronización de sintáxis: Se especificó dos veces un patrón de "
+"continuaciones de línea."
+
+#: syntax.c:5362
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Argumentos ilegales: %s"
+
+#: syntax.c:5412
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Falta el signo igual: %s"
+
+#: syntax.c:5418
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Argumento vacío: %s"
+
+#: syntax.c:5445
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s no está permitido aquí"
+
+#: syntax.c:5452
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s debe ser el primero en la lista de contenido"
+
+#: syntax.c:5522
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Nombre de grupo desconocido: %s"
+
+#: syntax.c:5755
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Subcomando «:syntax» no válido: %s"
+
+#: syntax.c:6136
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: grupo realzado no encontrado: %s"
+
+#: syntax.c:6160
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Argumentos insuficientes: «:highlight link %s»"
+
+#: syntax.c:6167
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: Demasiados argumentos: «:highlight link %s»"
+
+#: syntax.c:6187
+msgid "E414: group has settings, highlight link ignored"
+msgstr ""
+"E414: El grupo tiene opciones asignadas, se ha ignorado el enlace de "
+"colorización."
+
+#: syntax.c:6316
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: Signo igual inesperado: %s"
+
+#: syntax.c:6352
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: falta el signo igual: %s"
+
+#: syntax.c:6380
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: falta el argumento: %s"
+
+#: syntax.c:6417
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: Valor ilegal: %s"
+
+#: syntax.c:6536
+msgid "E419: FG color unknown"
+msgstr "E419: color de primer plano desconocido"
+
+#: syntax.c:6547
+msgid "E420: BG color unknown"
+msgstr "E420: Color de fondo desconocido"
+
+#: syntax.c:6608
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Nombre o número de color desconocido: %s"
+
+#: syntax.c:6814
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: código de terminal demasiado largo: %s"
+
+#: syntax.c:6861
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: Argumento ilegal: %s"
+
+#: syntax.c:7390
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: Hay demasiados atributos de realzado en uso"
+
+#: syntax.c:7911
+msgid "E669: Unprintable character in group name"
+msgstr "E669: Caracter no imprimible en el nombre del grupo."
+
+# Es preferible traducir "invalid" por "no [es] válido" pues "inválido"
+# no es lo suficientemente claro. Además, no es políticamente correcto :-)
+# ALV
+#. This is an error, but since there previously was no check only
+#. * give a warning.
+#: syntax.c:7918
+msgid "W18: Invalid character in group name"
+msgstr "W18: Hay un carácter no válido en el nobre del grupo."
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: En el final de la pila de correción rápida"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: En el principio de la pila de correción rápida"
+
+#: tag.c:412
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: No se puede ir antes del primer «tag» coincidente"
+
+#: tag.c:550
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: «tag» no encontrado: %s"
+
+#: tag.c:583
+msgid " # pri kind tag"
+msgstr " # marca tipo pri"
+
+#: tag.c:586
+msgid "file\n"
+msgstr "fichero\n"
+
+# * Ask to select a tag from the list.
+# * When using ":silent" assume that <CR> was entered.
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:744
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Introduzca el nº de la elección (<INTRO> para abortar): "
+
+#: tag.c:784
+msgid "E427: There is only one matching tag"
+msgstr "E427: Hay sólo un «tag» que coincide"
+
+#: tag.c:786
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E420: No se puede ir más allá del último «tag» que coincida"
+
+#: tag.c:810
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "No existe el fichero «%s»."
+
+# Give an indication of the number of matching tags
+#. Give an indication of the number of matching tags
+#: tag.c:823
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "«tag» %d de %d%s"
+
+#: tag.c:826
+msgid " or more"
+msgstr " o más"
+
+#: tag.c:828
+msgid " Using tag with different case!"
+msgstr " Uso de un «tag» con caja diferente"
+
+#: tag.c:872
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: El fichero «%s» no existe"
+
+# Highlight title
+#. Highlight title
+#: tag.c:941
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # A «tag» DESDE la línea en el fichero/texto"
+
+#: tag.c:1363
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Buscando el fichero de «tags» %s"
+
+#: tag.c:1550
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Ruta del fichero de «tags» truncada para %s\n"
+
+#: tag.c:2203
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Error de formato en el fichero de «tags» «%s»"
+
+#: tag.c:2207
+#, c-format
+msgid "Before byte %ld"
+msgstr "Adelante del byte %ld"
+
+#: tag.c:2240
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Fichero de «tags» sin ordenar: %s"
+
+# never opened any tags file
+#. never opened any tags file
+#: tag.c:2280
+msgid "E433: No tags file"
+msgstr "E433: No hay fichero de «tags»"
+
+#: tag.c:3016
+msgid "E434: Can't find tag pattern"
+msgstr "E434: No se puede encontrar el patrón de «tags»"
+
+#: tag.c:3027
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: No se pudo encontrar el «tag», ¡adivino solamente!"
+
+#: term.c:1759
+msgid "' not known. Available builtin terminals are:"
+msgstr "' desconocido. Los terminales incorporados disponibles son:"
+
+#: term.c:1783
+msgid "defaulting to '"
+msgstr "Usando ' por defecto."
+
+#: term.c:2141
+msgid "E557: Cannot open termcap file"
+msgstr "E557: No puedo abrir el fichero «termcap»."
+
+#: term.c:2145
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: No se ha encontrado la definición del terminal en «terminfo»."
+
+#: term.c:2147
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: No se ha encontrado la definición del terminal en «termcap»."
+
+#: term.c:2306
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: la entrada «%s» no existe en el fichero «termcap»."
+
+#: term.c:2780
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: Se necesita la capacidad de terminal «cm»"
+
+# Highlight title
+# Highlight title
+#. Highlight title
+#: term.c:4990
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Teclas del terminal ---"
+
+#: ui.c:258
+msgid "new shell started\n"
+msgstr "Inicié una «shell» nueva\n"
+
+#: ui.c:1841
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: error al leer la entrada, saliendo...\n"
+
+# must display the prompt
+#. must display the prompt
+#: undo.c:405
+msgid "No undo possible; continue anyway"
+msgstr "No es posible deshacer; continuando de todos modos"
+
+#: undo.c:561
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: «u_undo»: números de línea erróneos"
+
+#: undo.c:757
+msgid "1 change"
+msgstr "1 cambio"
+
+#: undo.c:759
+#, c-format
+msgid "%ld changes"
+msgstr "%ld cambios"
+
+#: undo.c:812
+msgid "E439: undo list corrupt"
+msgstr "E439: la lista de deshacer se dañó."
+
+#: undo.c:844
+msgid "E440: undo line missing"
+msgstr "E440: falta la línea deshacer."
+
+# Only MS VC 4.1 and earlier can do Win32s
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:739
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"Versión GUI de 16/32 bits para MS-Windows"
+
+#: version.c:741
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"Versión GUI de 32 bits para MS-Windows"
+
+#: version.c:744
+msgid " in Win32s mode"
+msgstr " en modo Win32s"
+
+#: version.c:746
+msgid " with OLE support"
+msgstr " con soporte para OLE"
+
+#: version.c:749
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"Versión de 32 bits para consola de MS-Windows"
+
+#: version.c:753
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"Versión de 16 bits para MS-Windows"
+
+#: version.c:757
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"Versión de 32 bits para MS-DOS"
+
+#: version.c:759
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"Versión de 16 bits para MS-DOS"
+
+#: version.c:765
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"Versión X (unix) para MacOS"
+
+#: version.c:767
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"Versión X para MacOS"
+
+#: version.c:770
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"Versión para MacOS"
+
+#: version.c:775
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"Versión para RISC OS"
+
+#: version.c:785
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Parches incluidos: "
+
+#: version.c:811 version.c:1179
+msgid "Modified by "
+msgstr "Modificado por "
+
+#: version.c:818
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Compilado "
+
+#: version.c:821
+msgid "by "
+msgstr "por "
+
+#: version.c:833
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Versión «enorme» "
+
+#: version.c:836
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Versión «grande» "
+
+#: version.c:839
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Versión «normal» "
+
+#: version.c:842
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Versión «pequeña» "
+
+#: version.c:844
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Versión «diminuta» "
+
+#: version.c:850
+msgid "without GUI."
+msgstr "sin GUI."
+
+#: version.c:855
+msgid "with GTK2-GNOME GUI."
+msgstr "con GUI GTK2-GNOME."
+
+#: version.c:857
+msgid "with GTK-GNOME GUI."
+msgstr "con GUI GTK-GNOME."
+
+#: version.c:861
+msgid "with GTK2 GUI."
+msgstr "con GUI GTK2."
+
+#: version.c:863
+msgid "with GTK GUI."
+msgstr "con GUI GTK."
+
+#: version.c:868
+msgid "with X11-Motif GUI."
+msgstr "con GUI X11-Motif."
+
+#: version.c:872
+msgid "with X11-neXtaw GUI."
+msgstr "con GUI X11-neXtaw."
+
+#: version.c:874
+msgid "with X11-Athena GUI."
+msgstr "con GUI X11-Athena."
+
+#: version.c:878
+msgid "with BeOS GUI."
+msgstr "con GUI para BeOS."
+
+#: version.c:881
+msgid "with Photon GUI."
+msgstr "con GUI para Photon."
+
+#: version.c:884
+msgid "with GUI."
+msgstr "con GUI."
+
+#: version.c:887
+msgid "with Carbon GUI."
+msgstr "con Carbon GUI."
+
+#: version.c:890
+msgid "with Cocoa GUI."
+msgstr "con Cocoa GUI."
+
+#: version.c:893
+msgid "with (classic) GUI."
+msgstr "con GUI (clásico)."
+
+#: version.c:904
+msgid " Features included (+) or not (-):\n"
+msgstr " Aspectos incluidos (+) o no (-):\n"
+
+#: version.c:916
+msgid " system vimrc file: \""
+msgstr " fichero «vimrc» del sistema: \""
+
+#: version.c:921
+msgid " user vimrc file: \""
+msgstr " fichero «vimrc» del usuario: \""
+
+#: version.c:926
+msgid " 2nd user vimrc file: \""
+msgstr " 2º fichero «vimrc» del usuario: \""
+
+#: version.c:931
+msgid " 3rd user vimrc file: \""
+msgstr " 3er fichero «vimrc» del usuario: \""
+
+#: version.c:936
+msgid " user exrc file: \""
+msgstr " fichero «exrc» del usuario: \""
+
+#: version.c:941
+msgid " 2nd user exrc file: \""
+msgstr " 2º fichero «exrc» del usuario: \""
+
+#: version.c:947
+msgid " system gvimrc file: \""
+msgstr " fichero «gvimrc» del sistema: \""
+
+#: version.c:951
+msgid " user gvimrc file: \""
+msgstr " fichero «gvimrc» del usuario: \""
+
+#: version.c:955
+msgid "2nd user gvimrc file: \""
+msgstr " 2º fichero «gvimrc» del usuario: \""
+
+#: version.c:960
+msgid "3rd user gvimrc file: \""
+msgstr "3er fichero «gvimrc» del usuario: \""
+
+#: version.c:967
+msgid " system menu file: \""
+msgstr " fichero de menú del sistema: \""
+
+#: version.c:975
+msgid " fall-back for $VIM: \""
+msgstr " localización de $VIM: \""
+
+#: version.c:981
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " localización de $VIMRUNTIME: \""
+
+#: version.c:985
+msgid "Compilation: "
+msgstr "Compilación: "
+
+#: version.c:991
+msgid "Compiler: "
+msgstr "Compilador: "
+
+#: version.c:996
+msgid "Linking: "
+msgstr "Enlazado: "
+
+#: version.c:1001
+msgid " DEBUG BUILD"
+msgstr " COMPILACIÓN CON SÍMBOLOS DE DEPURACIÓN"
+
+#: version.c:1040
+msgid "VIM - Vi IMproved"
+msgstr "VIM - VI Mejorado"
+
+#: version.c:1042
+msgid "version "
+msgstr "versión "
+
+#: version.c:1043
+msgid "by Bram Moolenaar et al."
+msgstr "por Bram Moolenaar et al."
+
+#: version.c:1047
+msgid "Vim is open source and freely distributable"
+msgstr "Vim es código abierto y se puede distribuir libremente"
+
+#: version.c:1049
+msgid "Help poor children in Uganda!"
+msgstr "¡Ayude a los niños pobres de Uganda!"
+
+#: version.c:1050
+msgid "type :help iccf<Enter> for information "
+msgstr "escriba «:help iccf<Intro>» para más información "
+
+#: version.c:1052
+msgid "type :q<Enter> to exit "
+msgstr "escriba «:q<Intro>» para salir "
+
+#: version.c:1053
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "escriba «:help<Intro> o <F1>» para obtener ayuda "
+
+#: version.c:1054
+msgid "type :help version6<Enter> for version info"
+msgstr "escriba «:help version6<Intro>» para información de la versión"
+
+#: version.c:1057
+msgid "Running in Vi compatible mode"
+msgstr "Ejecutando en modo compatible con Vi"
+
+#: version.c:1058
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "escriba «:set nocp<Intro>» para los valores predefinidos de Vim"
+
+#: version.c:1059
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "escriba «:help cp-default<Intro>» para más información"
+
+#: version.c:1074
+msgid "menu Help->Orphans for information "
+msgstr "menú Ayuda->Ayude a los niños huérfanos para más información "
+
+#: version.c:1076
+msgid "Running modeless, typed text is inserted"
+msgstr "Ejecución no modal, el texto escrito se inserta directamente"
+
+#: version.c:1077
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "menu Editar->Opciones globales->Activar/Desactivar modo de inserción"
+
+#: version.c:1078
+msgid " for two modes "
+msgstr " para dos modos "
+
+#: version.c:1082
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr ""
+"menu Editar->Opciones globales->Activar/Desactivar compatibilidad con Vi"
+
+#: version.c:1083
+msgid " for Vim defaults "
+msgstr ""
+" para los valores predeterminados de Vim"
+
+#: version.c:1130
+msgid "Sponsor Vim development!"
+msgstr "¡Patrocine el desarrollo de Vim!"
+
+#: version.c:1131
+msgid "Become a registered Vim user!"
+msgstr "¡Conviertase en un usuario registrado de Vim!"
+
+#: version.c:1134
+msgid "type :help sponsor<Enter> for information "
+msgstr "escriba :help sponsor<Intro> para más información "
+
+#: version.c:1135
+msgid "type :help register<Enter> for information "
+msgstr "escriba «:help register<Intro>» para más información "
+
+#: version.c:1137
+msgid "menu Help->Sponsor/Register for information "
+msgstr "menu Ayuda->Benefactor/Regístrese para más información."
+
+#: version.c:1147
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "AVISO: se ha detectado Windows 95/98/ME"
+
+#: version.c:1150
+msgid "type :help windows95<Enter> for info on this"
+msgstr "escriba: «:help windows95<Intro>» para más información"
+
+#: window.c:203
+msgid "E441: There is no preview window"
+msgstr "E441: No hay una ventana de vista previa"
+
+#: window.c:581
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: No se puede dividir arriba-izq y abajo-der al mismo tiempo"
+
+#: window.c:1340
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: No se puede rotar cuando otra ventana está dividida."
+
+#: window.c:1836
+msgid "E444: Cannot close last window"
+msgstr "E444: No se puede cerrar la última ventana."
+
+#: window.c:2567
+msgid "Already only one window"
+msgstr "Sólo hay una ventana."
+
+#: window.c:2614
+msgid "E445: Other window contains changes"
+msgstr "E445: Otra ventana contiene cambios."
+
+#: window.c:4480
+msgid "E446: No file name under cursor"
+msgstr "E446: No hay un nombre de fichero bajo el cursor"
+
+#: window.c:4599
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: No se puede encontrar el fichero «%s» en la ruta"
+
+#: if_perl.xs:326 globals.h:1236
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: No se pudo cargar la biblioteca dinámica %s."
+
+#: if_perl.xs:554
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr ""
+"E263: Lo siento, este comando está desactivado, no se pudo cargar la "
+"biblioteca dinámica de Perl."
+
+#: if_perl.xs:607
+msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+msgstr ""
+"E299: No se permite la evaluación de código Perl en la caja de arena sin el "
+"uso del módulo «Safe»."
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "Editar con Vims &múltiples"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "Editar con un solo &Vim"
+
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "&Diff con Vim"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "Editar con &Vim"
+
+# Now concatenate
+#. Now concatenate
+#: GvimExt/gvimext.cpp:633
+msgid "Edit with existing Vim - &"
+msgstr "Editar con un Vim existente - &"
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "Editar el(los) ficheros seleccionado(s) con Vim"
+
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "Error al crear el proceso: Asegúrese de que gvim es en su «path»!"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "error en gvimext.dll"
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "¡La ruta de acceso es demasiado larga!"
+
+#: globals.h:1026
+msgid "--No lines in buffer--"
+msgstr "--No hay líneas en el buffer--"
+
+# * The error messages that can be shared are included here.
+# * Excluded are errors that are only used once and debugging messages.
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1189
+msgid "E470: Command aborted"
+msgstr "E470: El comando abortó."
+
+#: globals.h:1190
+msgid "E471: Argument required"
+msgstr "E471: Se requiere un argumento."
+
+#: globals.h:1191
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ debería ir seguido de /, ? o &."
+
+#: globals.h:1193
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr ""
+"E11: No es válido en la ventana de la línea de comandos: <CR> ejecuta, CTRL-"
+"C sale."
+
+#: globals.h:1195
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Comando no permitido desde exrc/vimrc en el dir en curso o al buscar "
+"«tags»"
+
+#: globals.h:1197
+msgid "E171: Missing :endif"
+msgstr "E171: Falta «:endif»"
+
+#: globals.h:1198
+msgid "E600: Missing :endtry"
+msgstr "E600: Falta «:endtry»"
+
+#: globals.h:1199
+msgid "E170: Missing :endwhile"
+msgstr "E170: Falta «:endwhile»"
+
+#: globals.h:1200
+msgid "E588: :endwhile without :while"
+msgstr "E588: «:endwhile» sin «:while»."
+
+#: globals.h:1202
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: El fichero ya existe (use ! para sobreescribir)"
+
+#: globals.h:1203
+msgid "E472: Command failed"
+msgstr "E472: Falló el comando"
+
+#: globals.h:1205
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Conjunto de fuentes de impresión desconocido: %s"
+
+#: globals.h:1209
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Fuente de impresión desconocida: %s"
+
+#: globals.h:1212
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: La fuente de impresión «%s» no es de ancho fijo"
+
+#: globals.h:1214
+msgid "E473: Internal error"
+msgstr "E473: Error interno."
+
+#: globals.h:1215
+msgid "Interrupted"
+msgstr "Interrumpido"
+
+#: globals.h:1216
+msgid "E14: Invalid address"
+msgstr "E14: Dirección no válida"
+
+#: globals.h:1217
+msgid "E474: Invalid argument"
+msgstr "E474: argumento no válido"
+
+#: globals.h:1218
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: Argumento no válido: %s."
+
+#: globals.h:1220
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Expresión no válida: %s"
+
+#: globals.h:1222
+msgid "E16: Invalid range"
+msgstr "E16: Rango no válido"
+
+#: globals.h:1223
+msgid "E476: Invalid command"
+msgstr "E476: Nombre de comando no válido"
+
+#: globals.h:1225
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: «%s» es un directorio"
+
+#: globals.h:1228
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Caracteres inesperados delante de «=»"
+
+#: globals.h:1231
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Falló la llamada a biblioteca para «%s»()"
+
+#: globals.h:1237
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: Could not load library function %s"
+
+#: globals.h:1239
+msgid "E19: Mark has invalid line number"
+msgstr "E19: La marca tiene un número de línea no válido"
+
+#: globals.h:1240
+msgid "E20: Mark not set"
+msgstr "E20: Marca sin poner"
+
+#: globals.h:1241
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: No se pueden hacer cambios, «modifiable» está desactivado"
+
+#: globals.h:1242
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Demasiados «scripts» anidados"
+
+#: globals.h:1243
+msgid "E23: No alternate file"
+msgstr "E23: No hay un fichero alternativo"
+
+#: globals.h:1244
+msgid "E24: No such abbreviation"
+msgstr "E24: Tal abreviatura no existe"
+
+#: globals.h:1245
+msgid "E477: No ! allowed"
+msgstr "E477: «!» no está permitido."
+
+#: globals.h:1247
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: No se puede usar el GUI: no se ha activado al compilar."
+
+#: globals.h:1250
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: No se puede usar el hebreo: no se ha activado al compilar\n"
+
+#: globals.h:1253
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr ""
+"E27: No se puede usar el persa (farsi): no se ha activado al compilar\n"
+
+#: globals.h:1256
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: No se puede usar el árabe: no se ha activado al compilar\n"
+
+#: globals.h:1259
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: No existe el grupo de realzado con ese nombre: %s"
+
+#: globals.h:1261
+msgid "E29: No inserted text yet"
+msgstr "E29: Aún no ha insertado texto."
+
+#: globals.h:1262
+msgid "E30: No previous command line"
+msgstr "E30: No hay una línea de comandos previa"
+
+#: globals.h:1263
+msgid "E31: No such mapping"
+msgstr "E31: No existe tal asociación."
+
+#: globals.h:1264
+msgid "E479: No match"
+msgstr "E479: No hay coincidencia."
+
+#: globals.h:1265
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: No coincide: %s"
+
+#: globals.h:1266
+msgid "E32: No file name"
+msgstr "E32: No hay un nombre de fichero."
+
+#: globals.h:1267
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: No existe una expresión regular de sustitución previa."
+
+#: globals.h:1268
+msgid "E34: No previous command"
+msgstr "E34: No existe un comando previo."
+
+#: globals.h:1269
+msgid "E35: No previous regular expression"
+msgstr "E35: No existe una expresión regular previa."
+
+#: globals.h:1270
+msgid "E481: No range allowed"
+msgstr "E481: El rango no está permitido."
+
+#: globals.h:1272
+msgid "E36: Not enough room"
+msgstr "E36: No hay espacio suficiente."
+
+#: globals.h:1275
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: El servidor «%s» no está registrado."
+
+#: globals.h:1277
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: No se puede crear el fichero «%s»"
+
+#: globals.h:1278
+msgid "E483: Can't get temp file name"
+msgstr "E483: No puedo obtener el nombre del fichero temporal."
+
+#: globals.h:1279
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: No puedo abrir el fichero «%s»"
+
+#: globals.h:1280
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: No puedo leer el fichero «%s»."
+
+#: globals.h:1281
+msgid "E37: No write since last change (add ! to override)"
+msgstr ""
+"E37: No se ha guardado el fichero desde el último cambio (añada ! para "
+"forzar)."
+
+#: globals.h:1282
+msgid "E38: Null argument"
+msgstr "E38: Argumento nulo."
+
+#: globals.h:1284
+msgid "E39: Number expected"
+msgstr "E39: Esperaba un número."
+
+#: globals.h:1287
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: No puedo abrir el fichero de errores %s."
+
+#: globals.h:1290
+msgid "E233: cannot open display"
+msgstr "E233: No se puede abrir la pantalla."
+
+#: globals.h:1292
+msgid "E41: Out of memory!"
+msgstr "E41: ¡Memoria agotada!"
+
+#: globals.h:1294
+msgid "Pattern not found"
+msgstr "No se encontró el patrón de búsqueda."
+
+#: globals.h:1296
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: No se encontró el patrón de búsqueda: %s"
+
+#: globals.h:1297
+msgid "E487: Argument must be positive"
+msgstr "E487: El argumento debe ser positivo."
+
+#: globals.h:1299
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: No puedo regresar al directorio previo."
+
+#: globals.h:1303
+msgid "E42: No Errors"
+msgstr "E42: No hay errores"
+
+#: globals.h:1305
+msgid "E43: Damaged match string"
+msgstr "E43: Cadena de concidencia dañada."
+
+#: globals.h:1306
+msgid "E44: Corrupted regexp program"
+msgstr "E44: El programa «regexp» está corrupto."
+
+#: globals.h:1307
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: Está activa la opción «readonly» (añada «!» para forzar)."
+
+#: globals.h:1309
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: No se puede definir la variable de sólo lectura «%s»."
+
+#: globals.h:1312
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Error al leer el fichero de errores."
+
+#: globals.h:1315
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: No se permite en el ambiente protegido."
+
+#: globals.h:1317
+msgid "E523: Not allowed here"
+msgstr "E523: No se permite aquí."
+
+#: globals.h:1320
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: La configuración de la pantalla no es válida."
+
+#: globals.h:1322
+msgid "E49: Invalid scroll size"
+msgstr "E49: El tamaño de desplazamiento no válido."
+
+#: globals.h:1323
+msgid "E91: 'shell' option is empty"
+msgstr "E91: La opción «shell» está vacía."
+
+#: globals.h:1325
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: ¡No se pudo leer los datos de los signos!"
+
+#: globals.h:1327
+msgid "E72: Close error on swap file"
+msgstr "E72: Error de cierre en el fichero de intercambio"
+
+#: globals.h:1328
+msgid "E73: tag stack empty"
+msgstr "E73: La pila de «tags» está vacía."
+
+#: globals.h:1329
+msgid "E74: Command too complex"
+msgstr "E74: El comando es demasiado complejo."
+
+#: globals.h:1330
+msgid "E75: Name too long"
+msgstr "E75: El nombre es demasiado largo."
+
+#: globals.h:1331
+msgid "E76: Too many ["
+msgstr "E76: Hay demasiados ["
+
+#: globals.h:1332
+msgid "E77: Too many file names"
+msgstr "E77: Hay demasiados nombres de ficheros."
+
+#: globals.h:1333
+msgid "E488: Trailing characters"
+msgstr "E488: Caracteres en exceso al final de la línea."
+
+#: globals.h:1334
+msgid "E78: Unknown mark"
+msgstr "E78: Marca desconocida."
+
+#: globals.h:1335
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: No puedo expandir los comodines."
+
+#: globals.h:1337
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: «winheight» no puede ser más pequeño que «winminheight»."
+
+#: globals.h:1339
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: «winwidth» no puede ser más pequeño que «winminwidth»."
+
+#: globals.h:1342
+msgid "E80: Error while writing"
+msgstr "E80: Error al escribir el fichero."
+
+#: globals.h:1343
+msgid "Zero count"
+msgstr "El recuento es cero."
+
+#: globals.h:1345
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: Usando <SID> en un contexto que no es de «script»"
+
+#: globals.h:1348
+msgid "E449: Invalid expression received"
+msgstr "E449: Recibí una expresión inválida."
+
+#: globals.h:1351
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: La región está protegida, no puedo modificarla."
+
+#~ msgid "\"\n"
+#~ msgstr "»\n"
+
+#~ msgid " BLOCK"
+#~ msgstr " BLOQUE"
+
+#~ msgid " LINE"
+#~ msgstr " LÍNEA"
diff --git a/src/po/fr.po b/src/po/fr.po
new file mode 100644
index 000000000..22ae4bd3a
--- /dev/null
+++ b/src/po/fr.po
@@ -0,0 +1,6888 @@
+# French Translation for Vim
+#
+# Do ":help uganda" in Vim to read copying and usage conditions.
+# Do ":help credits" in Vim to see a list of people who contributed.
+#
+# FIRST AUTHOR DindinX <David.Odin@bigfoot.com> 2000.
+# SECOND AUTHOR Adrien Beau <version.francaise@free.fr> 2002, 2003.
+#
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+#
+# Ce fichier n'est pas finalisé ! Le gros du travail a été fait, mais la touche
+# finale reste à apporter. Je pense que tout sera bel et bien fini pour Vim 6.3
+# (hum, c'était censé être le cas pour Vim 6.2).
+#
+# Consultez http://version.francaise.free.fr/ pour les mises à jour de ce
+# fichier, ainsi que pour les versions françaises des menus et du tutoriel.
+#
+# Si vous avez des remarques à faire sur ce fichier, écrivez à
+# version.francaise@free.fr. Cette adresse est consultée régulièrement.
+#
+# En cas d'erreur technique au niveau de version.francaise@free.fr, ou si vous
+# ne recevez aucune réponse plusieurs jours après votre envoi, vérifiez si un
+# message n'a pas été posté sur le site web. Si cette option se révèle
+# infructueuse, essayez de me contacter à mes autres adresses, chez free.fr ou
+# chez yahoo.com. Mon nom d'utilisateur est la concaténation de mon prénom et
+# de mon nom.
+#
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+#
+# This file still needs work! The rough work has been done, some polishing
+# needs to be applied. I expect everything to be bright and shiny for Vim 6.3
+# (err, that was supposed to be Vim 6.2).
+#
+# Go to http://version.francaise.free.fr/ for updates to this file, and to the
+# French versions of the menus and the tutor.
+#
+# Send your comments about this file by email, to version.francaise@free.fr.
+# This address is checked regularly.
+#
+# In case of technical error at version.francaise@free.fr, or if you don't get
+# any answer several days after writing, check if there is a message at
+# http://version.francaise.free.fr/. If this option fails to work, try to
+# write to my other addresses at free.fr and yahoo.com. Concatene my first and
+# last name to get my username.
+#
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+#
+# ChangeLog:
+#
+# 2002-03-04 AB Bulk translation (done in 16 hours!)
+# - That's 1.35 msg/min for ya
+# 2002-03-23 AB Initial release (ships with Vim 6.1)
+# - Much cleaner than the first version :)
+# 2002-09-30 AB Patch #200 update (released on web site)
+# - Five new messages
+# - Corrected three typos in printf()-style expressions
+# (thanks Mik)
+# 2003-05-09 AB Patch #474 update (unreleased)
+# - Polishing done on three more files (the three first
+# ones have been reworked, too)
+# - Many comments have been added in the polished
+# section
+# 2003-05-29 AB Vim 6.2 pending release
+# - Finish work on Vim 6.1.474 (quickly!)
+# - Thirty-three new messages (rough translation)
+# - Some of the English messages have been altered
+# (fuzzy entries), deal with it
+# 2003-05-29 AB Vim 6.2 release candidate (sent to Bram Moolenaar)
+# - Update to Vim 6.2f.014 (quickly, too)
+# - Fifty-nine new messages (rough translation)
+# - Hundreds of error messages numbers added (wow)
+#
+# Translated: 1392/1392 (100.00%)
+#
+# Polishing done on:
+# buffer.c
+# diff.c
+# digraph.c
+# edit.c
+# eval.c
+# ex_cmds.c
+#
+# Other files still to do.
+#
+# Notations used in the comments of the unpolished part of this file:
+# TODO There's work to do there, and it's important
+# todo There's work to do there, but it's less important
+# (no comment) Perhaps there's work to do there?
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim(Français)\n"
+"POT-Creation-Date: 2003-05-28 23:09+0200\n"
+"PO-Revision-Date: 2003-05-29 04:01+0200\n"
+"Last-Translator: Adrien Beau <version.francaise@free.fr>\n"
+"Language-Team: Adrien Beau <version.francaise@free.fr>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO_8859-15\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# AB - Il faut respecter l'esprit plus que la lettre.
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Aucun tampon ne peut être alloué, Vim doit s'arrêter"
+
+# AB - La situation est probablement plus grave que la version anglaise ne le
+# laisse entendre (voir l'aide en ligne). La version française est plus
+# explicite.
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: L'allocation du tampon a échoué: arrêtez Vim, libérez de la mémoire"
+
+#: buffer.c:797
+msgid "E515: No buffers were unloaded"
+msgstr "E515: Aucun tampon n'a été déchargé"
+
+#: buffer.c:799
+msgid "E516: No buffers were deleted"
+msgstr "E516: Aucun tampon n'a été effacé"
+
+#: buffer.c:801
+msgid "E517: No buffers were wiped out"
+msgstr "E517: Aucun tampon n'a été détruit"
+
+#: buffer.c:809
+msgid "1 buffer unloaded"
+msgstr "1 tampon a été déchargé"
+
+#: buffer.c:811
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "%d tampons ont été déchargés"
+
+#: buffer.c:816
+msgid "1 buffer deleted"
+msgstr "1 tampon a été effacé"
+
+#: buffer.c:818
+#, c-format
+msgid "%d buffers deleted"
+msgstr "%d tampons ont été effacés"
+
+#: buffer.c:823
+msgid "1 buffer wiped out"
+msgstr "1 tampon a été détruit"
+
+#: buffer.c:825
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "%d tampons ont été détruits"
+
+# AB - La version française est meilleure que la version anglaise.
+#: buffer.c:886
+msgid "E84: No modified buffer found"
+msgstr "E84: Aucun tampon n'est modifié"
+
+#. back where we started, didn't find anything.
+#: buffer.c:925
+msgid "E85: There is no listed buffer"
+msgstr "E85: Aucun tampon n'est listé"
+
+# AB - Vu le code source, la version française est meilleure que la
+# version anglaise.
+#: buffer.c:937
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: Le tampon %ld n'existe pas"
+
+# AB - Je ne suis pas sûr que l'on puisse obtenir ce message.
+#: buffer.c:940
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Impossible d'aller après le dernier tampon"
+
+# AB - Je ne suis pas sûr que l'on puisse obtenir ce message.
+#: buffer.c:942
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Impossible d'aller avant le premier tampon"
+
+#: buffer.c:966
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr "E89: Le tampon %ld n'a pas été enregistré (ajoutez ! pour passer outre)"
+
+#: buffer.c:982
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: Impossible de décharger le dernier tampon"
+
+#: buffer.c:1500
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Alerte: La liste des noms de fichier déborde"
+
+# AB - Vu le code source, la version française est meilleure que la
+# version anglaise. Ce message est similaire au message E86.
+#: buffer.c:1671
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: Le tampon %ld n'existe pas"
+
+# AB - Il faut respecter l'esprit plus que la lettre.
+#: buffer.c:1902
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Plusieurs tampons correspondent à %s"
+
+#: buffer.c:1904
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: Aucun tampon ne correspond à %s"
+
+#: buffer.c:2299 ex_docmd.c:6560
+#, c-format
+msgid "line %ld"
+msgstr "ligne %ld"
+
+#: buffer.c:2382
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Un tampon porte déjà ce nom"
+
+#: buffer.c:2675
+msgid " [Modified]"
+msgstr "[Modifié]"
+
+# AB - "[Inédité]" est plus correct, mais sonne faux.
+#: buffer.c:2680
+msgid "[Not edited]"
+msgstr "[Pas édité]"
+
+#: buffer.c:2685
+msgid "[New file]"
+msgstr "[Nouveau fichier]"
+
+#: buffer.c:2686
+msgid "[Read errors]"
+msgstr "[Erreurs de lecture]"
+
+# AB - La version courte, "[RO]", devrait-elle être traduite par "[LS]" ?
+# Il faudrait faire un sondage auprès des utilisateurs francophones.
+#: buffer.c:2688 fileio.c:1914
+msgid "[readonly]"
+msgstr "[lecture-seule]"
+
+#: buffer.c:2703
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 ligne --%d%%--"
+
+#: buffer.c:2705
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld lignes --%d%%--"
+
+# AB - Faut-il remplacer "sur" par "de" ?
+#: buffer.c:2712
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "ligne %ld sur %ld --%d%%-- col "
+
+#: buffer.c:2813
+msgid "[No file]"
+msgstr "[Pas de fichier]"
+
+#. must be a help buffer
+#: buffer.c:2853
+msgid "help"
+msgstr "aide"
+
+#: buffer.c:3412 screen.c:4996
+msgid "[help]"
+msgstr "[aide]"
+
+# AB - "Prévisualisation" prend beaucoup de place. "Prévision" est une
+# traduction littérale et brève, mais qui risque fort d'être mal comprise.
+# J'ai finalement choisi d'utiliser une abréviation, mais cela ne me
+# satisfait pas.
+#: buffer.c:3444 screen.c:5002
+msgid "[Preview]"
+msgstr "[Prévisu]"
+
+#: buffer.c:3724
+msgid "All"
+msgstr "Tout"
+
+#: buffer.c:3724
+msgid "Bot"
+msgstr "Bas"
+
+# AB - Attention, on passe de trois à quatre lettres.
+#: buffer.c:3726
+msgid "Top"
+msgstr "Haut"
+
+#: buffer.c:4470
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# Liste des tampons:\n"
+
+#: buffer.c:4503
+msgid "[Error List]"
+msgstr "[Liste d'erreurs]"
+
+# AB - Ce message est déjà présent quelques lignes plus haut.
+#: buffer.c:4516 memline.c:1501
+msgid "[No File]"
+msgstr "[Pas de fichier]"
+
+#: buffer.c:4819
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Symboles ---"
+
+#: buffer.c:4838
+#, c-format
+msgid "Signs for %s:"
+msgstr "Symboles dans %s:"
+
+#: buffer.c:4844
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " ligne=%ld id=%d nom=%s"
+
+# AB - Je n'ai pas trouvé de traduction satisfaisante au verbe "diff". Comme
+# Vim fait en pratique appel au programme "diff" pour evaluer les
+# différences entre fichiers, "to diff" a été traduit par "utiliser diff"
+# et d'autres expressions appropriées.
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: Impossible d'utiliser diff sur plus de %ld tampons"
+
+# AB - La version française est meilleure que la version anglaise.
+#: diff.c:651
+msgid "E97: Cannot create diffs"
+msgstr "E97: diff ne fonctionne pas"
+
+# AB - Ceci est un titre de boîte de dialogue.
+#: diff.c:750
+msgid "Patch file"
+msgstr "Sélectionner un patch - Vim"
+
+# AB - La version française est correcte, mais trop technique.
+# AB - "output" est difficile à traduire clairement.
+#: diff.c:1001
+msgid "E98: Cannot read diff output"
+msgstr "E98: Le fichier intermédiaire produit par diff n'a pu être lu"
+
+#: diff.c:1742
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Le tampon courant n'est pas en mode diff"
+
+#: diff.c:1754
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: Aucun autre tampon n'est en mode diff"
+
+# AB - La version française est meilleure que la version anglaise, mais elle
+# peut être améliorée.
+#: diff.c:1762
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: Plus de deux tampons sont en mode diff, soyez plus précis"
+
+#: diff.c:1785
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Le tampon %s est introuvable"
+
+#: diff.c:1791
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Le tampon %s n'est pas en mode diff"
+
+# AB - Je cherche une traduction plus concise pour "escape".
+#: digraph.c:2172
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: Un digraphe ne peut contenir le caractère d'échappement"
+
+# AB - La version française est trop verbeuse.
+#: digraph.c:2344
+msgid "E544: Keymap file not found"
+msgstr "E544: Le fichier descripteur de clavier est introuvable"
+
+# AB - La version française est meilleure que la version anglaise.
+#: digraph.c:2371
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: :loadkeymap ne peut être utilisé que dans un script Vim"
+
+# AB - Remplacer "complétion" par "complètement" ? Voir l'éthymologie
+# d'"accrétion".
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " Complétion de mot-clé (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " mode ^X (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+
+# AB - Remplacer "complétion" par "complètement" ? Voir l'éthymologie
+# d'"accrétion".
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " Complétion locale de mot-clé (^N/^P)"
+
+# AB - Remplacer "complétion" par "complètement" ? Voir l'éthymologie
+# d'"accrétion".
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " Complétion de ligne entière (^L/^N/^P)"
+
+# AB - Remplacer "complétion" par "complètement" ? Voir l'éthymologie
+# d'"accrétion".
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " Complétion de nom de fichier (^F/^N/^P)"
+
+# AB - Remplacer "complétion" par "complètement" ? Voir l'éthymologie
+# d'"accrétion".
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " Complétion d'étiquette (^]/^N/^P)"
+
+# AB - Remplacer "complétion" par "complètement" ? Voir l'éthymologie
+# d'"accrétion".
+# AB - J'ai dû avoir une bonne raison de faire une version française aussi
+# différente de la version anglaise. Il me faut la retrouver.
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " Complétion globale de mot-clé (^N/^P)"
+
+# AB - Remplacer "complétion" par "complètement" ? Voir l'éthymologie
+# d'"accrétion".
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " Complétion de définition (^D/^N/^P)"
+
+# AB - Remplacer "complétion" par "complètement" ? Voir l'éthymologie
+# d'"accrétion".
+# AB - Trouver une meilleure formulation que "selon le".
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " Complétion selon le dictionnaire (^K/^N/^P)"
+
+# AB - Remplacer "complétion" par "complètement" ? Voir l'éthymologie
+# d'"accrétion".
+# AB - Trouver une meilleure formulation que "selon le".
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Complétion selon le thésaurus (^T/^N/^P)"
+
+# AB - Remplacer "complétion" par "complètement" ? Voir l'éthymologie
+# d'"accrétion".
+# AB - La version française est meilleure que la version anglaise.
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " Complétion de commande Vim (^V/^N/^P)"
+
+# AB - Ce texte s'ajoute à la fin d'un des messages de complétion ci-dessus.
+# Il faut éviter de le faire trop long. Je pense que la version française
+# est suffisamment compréhensible dans le contexte dans lequel elle est
+# affichée.
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Fin du paragraphe"
+
+#: edit.c:955
+msgid "'thesaurus' option is empty"
+msgstr "L'option 'thesaurus' est vide"
+
+#: edit.c:1159
+msgid "'dictionary' option is empty"
+msgstr "L'option 'dictionary' est vide"
+
+#: edit.c:2144
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Examen du dictionnaire: %s"
+
+#: edit.c:2350
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (insertion) Défilement (^E/^Y)"
+
+#: edit.c:2352
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (remplacement) Défilement (^E/^Y)"
+
+#: edit.c:2666
+#, c-format
+msgid "Scanning: %s"
+msgstr "Examen: %s"
+
+#: edit.c:2701
+msgid "Scanning tags."
+msgstr "Examen des étiquettes."
+
+# AB - Cette chaîne de caractères est ajoutée en début de ligne lorsqu'une
+# opération de complétion est répétée (typiquement avec CTRL-X CTRL-N).
+# Que ce soit en anglais ou en français, il y a un problème de majuscules.
+# Bien qu'insatisfaisante, cette traduction semble optimale.
+#: edit.c:3363
+msgid " Adding"
+msgstr " Ajout"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3412
+msgid "-- Searching..."
+msgstr "-- Recherche en cours..."
+
+# AB - Ce texte s'ajoute à la fin d'un des messages de complétion ci-dessus.
+# AB - Faut-il utiliser "origine" ou "originel" au lieu d'"original" ?
+#: edit.c:3468
+msgid "Back at original"
+msgstr "De retour à l'original"
+
+# AB - Ce texte s'ajoute à la fin d'un des messages de complétion ci-dessus.
+#: edit.c:3473
+msgid "Word from other line"
+msgstr "Mot d'une autre ligne"
+
+# AB - Ce texte s'ajoute à la fin d'un des messages de complétion ci-dessus.
+#: edit.c:3478
+msgid "The only match"
+msgstr "La seule correspondance"
+
+# AB - Ce texte s'ajoute à la fin d'un des messages de complétion ci-dessus.
+# AB - Faut-il remplacer "sur" par "de" ?
+#: edit.c:3537
+#, c-format
+msgid "match %d of %d"
+msgstr "Correspondance %d sur %d"
+
+# AB - Ce texte s'ajoute à la fin d'un des messages de complétion ci-dessus.
+#: edit.c:3540
+#, c-format
+msgid "match %d"
+msgstr "Correspondance %d"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:979
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Variable inconnue: %s"
+
+# AB - La version française est meilleure que la version anglaise.
+# AB - Je suis partagé entre la concision d'une traduction assez littérale et
+# la lourdeur d'une traduction plus correcte.
+#: eval.c:1275
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Il manque '(' après %s"
+
+#: eval.c:1380 eval.c:1394
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Variable inexistante: %s"
+
+# AB - Je suis partagé entre la concision d'une traduction assez littérale et
+# la lourdeur d'une traduction plus correcte.
+#: eval.c:1650
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Il manque ':' après '?'"
+
+# AB - Je suis partagé entre la concision d'une traduction assez littérale et
+# la lourdeur d'une traduction plus correcte.
+#: eval.c:2266
+msgid "E110: Missing ')'"
+msgstr "E110: Il manque ')'"
+
+# AB - Je suis partagé entre la concision d'une traduction assez littérale et
+# la lourdeur d'une traduction plus correcte.
+#: eval.c:2323
+msgid "E111: Missing ']'"
+msgstr "E111: Il manque ']'"
+
+# AB - La version française est meilleure que la version anglaise.
+# AB - Je suis partagé entre la concision d'une traduction assez littérale et
+# la lourdeur d'une traduction plus correcte.
+#: eval.c:2399
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Il manque un nom d'option après %s"
+
+#: eval.c:2417
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Option inconnue: %s"
+
+# AB - La version française est meilleure que la version anglaise, qui est
+# erronée, d'ailleurs : il s'agit d'une "double quote" et non d'une
+# "quote".
+#: eval.c:2481
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Il manque \" à la fin de %s"
+
+# AB - La version française est meilleure que la version anglaise.
+#: eval.c:2613
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Il manque ' à la fin de %s"
+
+# AB - La version française est meilleure que la version anglaise.
+#: eval.c:2963
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Un argument de la fonction %s est invalide"
+
+#: eval.c:2992
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Fonction inconnue: %s"
+
+#: eval.c:2993
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: La fonction %s a trop d'arguments"
+
+#: eval.c:2994
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: La fonction %s n'a pas assez d'arguments"
+
+#: eval.c:2995
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: <SID> ne peut être utilisé en dehors d'un script: %s"
+
+# AB - Texte par défaut du bouton de la boîte de dialogue affichée par la
+# fonction confirm().
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3585 gui.c:4254 gui_gtk.c:1997
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:4120
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld lignes: "
+
+# AB - Textes des boutons de la boîte de dialogue affichée par inputdialog().
+#: eval.c:5345
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&Ok\n"
+"&Annuler"
+
+# AB - La version française est meilleure que la version anglaise.
+#: eval.c:5385
+msgid "called inputrestore() more often than inputsave()"
+msgstr "inputrestore() a été appelé plus de fois qu'inputsave()"
+
+# AB - À mon avis, la version anglaise est erronée.
+#: eval.c:6300
+msgid "E240: No connection to Vim server"
+msgstr "E240: Pas de connection au serveur X"
+
+#: eval.c:6397
+msgid "E277: Unable to read a server reply"
+msgstr "E277: La réponse du serveur n'a pu être lue"
+
+# AB - La version française est meilleure que la version anglaise.
+#: eval.c:6425
+msgid "E258: Unable to send to client"
+msgstr "E258: La réponse n'a pu être envoyée au client"
+
+# AB - La version française est meilleure que la version anglaise.
+#: eval.c:6473
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: L'envoi au serveur %s à échoué"
+
+#: eval.c:6573
+msgid "(Invalid)"
+msgstr "(Invalide)"
+
+#: eval.c:7688
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Variable indéfinie: %s"
+
+# AB - "illégal" est un terme trop fort à mon goût.
+#: eval.c:8120
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E461: Nom de variable illégal: %s"
+
+#: eval.c:8408
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: La fonction %s existe déjà (ajoutez ! pour la remplacer)"
+
+#: eval.c:8475
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Fonction indéfinie: %s"
+
+# AB - La version française est plus consistante que la version anglaise.
+# AB - Je suis partagé entre la concision d'une traduction assez littérale et
+# la lourdeur d'une traduction plus correcte.
+#: eval.c:8488
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Il manque '(' après %s"
+
+# AB - "illégal" est un terme trop fort à mon goût.
+#: eval.c:8521
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Argument illégal: %s"
+
+#: eval.c:8600
+msgid "E126: Missing :endfunction"
+msgstr "E126: Il manque :endfunction"
+
+# AB - Il est difficile de créer une version française qui fasse moins de 80
+# caractères de long, nom de la fonction compris : "It is in use" est une
+# expression très dense. Traductions possibles : "elle est utilisée",
+# "elle s'exécute" ou "elle est occupée".
+#: eval.c:8683
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Impossible de redéfinir %s: cette fonction est occupée"
+
+#: eval.c:8751
+msgid "E129: Function name required"
+msgstr "E129: Nom de fonction requis"
+
+# AB - Il faut respecter l'esprit plus que la lettre.
+#: eval.c:8802
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: %s ne commence pas par une majuscule"
+
+#: eval.c:8994
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Fonction indéfinie: %s"
+
+# AB - Il est difficile de créer une version française qui fasse moins de 80
+# caractères de long, nom de la fonction compris : "It is in use" est une
+# expression très dense. Traductions possibles : "elle est utilisée",
+# "elle s'exécute" ou "elle est occupée".
+#: eval.c:8999
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Impossible d'effacer %s: cette fonction est occupée"
+
+# AB - Vérifier dans la littérature technique s'il n'existe pas une meilleure
+# traduction pour "function call depth".
+#: eval.c:9047
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: La profondeur d'appel de fonction est supérieure à 'maxfuncdepth'"
+
+# AB - Ce texte fait partie d'un message de débogage.
+#. always scroll up, don't overwrite
+#: eval.c:9100
+#, c-format
+msgid "calling %s"
+msgstr "appel de %s"
+
+# AB - Vérifier.
+#: eval.c:9162
+#, c-format
+msgid "%s aborted"
+msgstr "%s annulée"
+
+# AB - Ce texte fait partie d'un message de débogage.
+#: eval.c:9164
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s a retourné #%ld"
+
+# AB - Ce texte fait partie d'un message de débogage.
+#: eval.c:9171
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s a retourné \"%s\""
+
+# AB - Ce texte fait partie d'un message de débogage.
+#. always scroll up, don't overwrite
+#: eval.c:9187 ex_cmds2.c:2244
+#, c-format
+msgid "continuing in %s"
+msgstr "de retour dans %s"
+
+#: eval.c:9213
+msgid "E133: :return not inside a function"
+msgstr "E133: :return n'est pas à l'intérieur d'une fonction"
+
+# AB - La version française est capitalisée pour être en accord avec les autres
+# commentaires enregistrés dans le fichier viminfo.
+#: eval.c:9544
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# Variables globales:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Hex %02x, Octal %03o"
+
+# AB - La version anglaise est très mauvaise, ce qui m'oblige a inventer une
+# version française.
+#: ex_cmds.c:433
+msgid "E134: Move lines into themselves"
+msgstr "E134: La destination est dans la plage d'origine"
+
+#: ex_cmds.c:502
+msgid "1 line moved"
+msgstr "1 ligne déplacée"
+
+#: ex_cmds.c:504
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld lignes déplacées"
+
+#: ex_cmds.c:909
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld lignes filtrées"
+
+# AB - J'ai volontairement omis l'astérisque initiale car je pense que le
+# motif "Filter*" décrit plus clairement les quatre autocommandes liées
+# au filtrage (FilterReadPre, FilterReadPost, FilterWritePre et
+# FilterWritePost) que "*Filter*" que l'on confond avec une tentative de
+# mise en valeur.
+#: ex_cmds.c:937
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr ""
+"E135: Les autocommandes Filter* ne doivent pas changer le tampon courant"
+
+# AB - Il faut respecter l'esprit plus que la lettre. Dans le cas présent,
+# nettement plus.
+#: ex_cmds.c:1022
+msgid "[No write since last change]\n"
+msgstr "[Attention: tout n'est pas enregistré]\n"
+
+# AB - Le numéro et le message d'erreur (%s ci-dessous) et le "numéro" de ligne
+# sont des chaînes de caractères dont le contenu est à la discrétion de
+# l'appelant de la fonction viminfo_error().
+#: ex_cmds.c:1268
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s à la ligne "
+
+# AB - La version française est meilleure que la version anglaise.
+#: ex_cmds.c:1273
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr ""
+"E136: Il y a trop d'erreurs; interruption de la lecture du fichier viminfo"
+
+# AB - Ce texte fait partie d'un message de débogage.
+#: ex_cmds.c:1308
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Lecture du fichier viminfo \"%s\"%s%s%s"
+
+# AB - Ce texte fait partie d'un message de débogage.
+#: ex_cmds.c:1309
+msgid " info"
+msgstr " info"
+
+# AB - Ce texte fait partie d'un message de débogage.
+#: ex_cmds.c:1310
+msgid " marks"
+msgstr " marques"
+
+# AB - Ce texte fait partie d'un message de débogage.
+#: ex_cmds.c:1311
+msgid " FAILED"
+msgstr " ÉCHEC"
+
+# AB - J'espère que la plupart des utilisateurs aura l'idée d'aller vérifier
+# ses droits d'accès.
+# AB - Le mot "viminfo" a été retiré pour que le message ne dépasse pas 80
+# caractères dans le cas courant où %s = /home/12345678/.viminfo
+#: ex_cmds.c:1403
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: L'écriture dans le fichier %s est interdite"
+
+# AB - Le point d'exclamation est superflu.
+# AB - Le mot "viminfo" a été retiré pour que le message ne dépasse pas 80
+# caractères dans le cas courant où %s = /home/12345678/.viminfo
+#: ex_cmds.c:1528
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Impossible d'écrire le fichier %s"
+
+# AB - Ce texte est un message de débogage.
+#: ex_cmds.c:1536
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Écriture du fichier viminfo \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1634
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Ce fichier viminfo a été généré par Vim %s.\n"
+
+# AB - Les deux versions, bien que différentes, se valent.
+#: ex_cmds.c:1636
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Vous pouvez l'éditer, mais soyez prudent.\n"
+"\n"
+
+# AB - Je préfère "Valeur de 'encoding'" à "Valeur d''encoding'".
+#: ex_cmds.c:1638
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# 'encoding' dans lequel ce fichier a été écrit\n"
+
+# AB - Ce texte est passé en argument à la fonction viminfo_error().
+# AB - "illégal" est un terme trop fort à mon goût.
+#: ex_cmds.c:1737
+msgid "Illegal starting char"
+msgstr "Caractère initial illégal"
+
+# AB - Ceci est un titre de boîte de dialogue. Vérifier que la version
+# française est correcte pour les trois références ; j'ai un doute quant
+# à la troisième.
+#: ex_cmds.c:2082 ex_cmds.c:2347 ex_cmds2.c:754
+msgid "Save As"
+msgstr "Enregistrer sous - Vim"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2125
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Le fichier est chargé dans un autre tampon"
+
+# AB - Ceci est un contenu de boîte de dialogue (éventuellement en mode texte).
+# AB - La version française est meilleure que la version anglaise.
+#: ex_cmds.c:2159
+msgid "Write partial file?"
+msgstr "Perdre une partie du fichier ?"
+
+# AB - La version française est nettement meilleure que la version anglaise.
+#: ex_cmds.c:2166
+msgid "E140: Use ! to write partial buffer"
+msgstr ""
+"E140: Une partie du fichier serait perdue (ajoutez ! pour passer outre)"
+
+# AB - Ceci est un contenu de boîte de dialogue (éventuellement en mode texte).
+#: ex_cmds.c:2281
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Écraser le fichier %.*s existant ?"
+
+#: ex_cmds.c:2352
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: Pas de nom de fichier pour le tampon %ld"
+
+# AB - Il faut respecter l'esprit plus que la lettre.
+#: ex_cmds.c:2390
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: L'option 'nowrite' est activée et empêche toute écriture de fichier"
+
+# AB - Ceci est un contenu de boîte de dialogue (éventuellement en mode texte).
+# AB - "activée pour" n'est pas une formulation très heureuse.
+#: ex_cmds.c:2410
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"L'option 'readonly' est activée pour %.*s.\n"
+"Voulez-vous quand même enregistrer ?"
+
+# AB - Ceci est un titre de boîte de dialogue.
+#: ex_cmds.c:2575
+msgid "Edit File"
+msgstr "Ouvrir un fichier - Vim"
+
+# AB - Il faut respecter l'esprit plus que la lettre.
+# AB - J'hésite à ajouter "à sa création" après le nom du tampon. Ce message
+# devrait n'être affiché qu'après une tentative d'ouverture de fichier,
+# la version actuelle devrait donc suffire.
+#: ex_cmds.c:3147
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Une autocommande a effacé le tampon %s"
+
+#: ex_cmds.c:3279
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: L'argument de :z n'est pas numérique"
+
+# AB - La version française fera peut-être mieux passer l'amère pillule.
+# La consultation de l'aide donnera l'explication complète à ceux qui
+# ne comprendraient pas à quoi ce message est dû.
+#: ex_cmds.c:3364
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: Les commandes externes sont indisponibles"
+
+#: ex_cmds.c:3471
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Les expressions régulières ne peuvent être délimitées par des lettres"
+
+#: ex_cmds.c:3817
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "remplacer par %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4189
+msgid "(Interrupted) "
+msgstr "(Interrompu) "
+
+#: ex_cmds.c:4193
+msgid "1 substitution"
+msgstr "1 substitution"
+
+#: ex_cmds.c:4195
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld substitutions"
+
+#: ex_cmds.c:4198
+msgid " on 1 line"
+msgstr " sur 1 ligne"
+
+#: ex_cmds.c:4200
+#, c-format
+msgid " on %ld lines"
+msgstr " sur %ld lignes"
+
+# AB - Il faut respecter l'esprit plus que la lettre.
+# AB - Ce message devrait contenir une référence à :vglobal.
+#: ex_cmds.c:4251
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :global ne peut exécuter :global"
+
+# AB - Ce message devrait contenir une référence à :vglobal.
+#: ex_cmds.c:4286
+msgid "E148: Regular expression missing from global"
+msgstr "E148: :global doit être suivi par une expression régulière"
+
+# AB - Ce message est utilisé lorsque :vglobal ne trouve rien. Lorsque :global
+# ne trouve rien, c'est "Pattern not found: %s" / "Motif introuvable: %s"
+# qui est utilisé.
+#: ex_cmds.c:4335
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Motif trouvé à chaque ligne: %s"
+
+# AB - Ne pas traduire le dollar.
+# AB - Ce message n'est volontairement pas traduit. En effet, il fait partie
+# d'un groupe de trois messages dans viminfo, dont deux ne sont pas soumis
+# à internationalisation. J'attends que les deux autres messages soient
+# traduisibles pour traduire celui-ci.
+#: ex_cmds.c:4416
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+
+#: ex_cmds.c:4529
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Désolé, pas d'aide pour %s"
+
+#: ex_cmds.c:4563
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Désolé, le fichier d'aide %s est introuvable"
+
+#: ex_cmds.c:5039
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s n'est pas un répertoire"
+
+# AB - La version anglaise est plus précise, mais trop technique.
+#: ex_cmds.c:5067
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: Impossible d'écrire %s"
+
+# AB - La version anglaise est plus précise, mais trop technique.
+#: ex_cmds.c:5102
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Impossible de lire %s"
+
+# AB - L'étiquette la plus longue fait 27 caractères. Le nom de fichier le plus
+# long fait 12 caractères. Il faudrait donc idéalement faire une
+# traduction de 40 caractères ou moins. Ce qui est loin d'être le cas
+# présent.
+#: ex_cmds.c:5181
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: L'étiquette \"%s\" apparaît deux fois dans le fichier %s"
+
+# AB - Il faut respecter l'esprit plus que la lettre.
+#: ex_cmds.c:5288
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Commande inconnue: :sign %s"
+
+# AB - La version française est meilleure que la version anglaise.
+#: ex_cmds.c:5308
+msgid "E156: Missing sign name"
+msgstr "E156: Il manque le nom du symbole"
+
+#: ex_cmds.c:5354
+msgid "E612: Too many signs defined"
+msgstr "E612: Trop de symboles sont définis"
+
+# AB - Cette traduction ne me satisfait pas.
+#: ex_cmds.c:5421
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: La version texte du symbole est invalide: %s"
+
+#: ex_cmds.c:5452 ex_cmds.c:5638
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Symbole inconnu: %s"
+
+# AB - La version française est meilleure que la version anglaise.
+#: ex_cmds.c:5498
+msgid "E159: Missing sign number"
+msgstr "E159: Il manque l'ID du symbole"
+
+# AB - Vu le code source, la version française est meilleure que la
+# version anglaise. Ce message est similaire au message E102.
+#: ex_cmds.c:5578
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: Le tampon %s est introuvable"
+
+# AB - Vu le code source, la version française est meilleure que la
+# version anglaise.
+#: ex_cmds.c:5617
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Le symbole %ld est introuvable"
+
+#: ex_cmds.c:5788
+msgid "[Deleted]"
+msgstr "[Effacé]"
+
+# AB - La version française de la première phrase ne me satisfait pas.
+#: ex_cmds2.c:83
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "Début du déboguage. Tapez \"cont\" pour continuer."
+
+#: ex_cmds2.c:87 ex_docmd.c:854
+#, c-format
+msgid "line %ld: %s"
+msgstr "ligne %ld: %s"
+
+#: ex_cmds2.c:89
+#, c-format
+msgid "cmd: %s"
+msgstr "cmde: %s"
+
+#: ex_cmds2.c:281
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Point d'interruption dans %s%s ligne %ld"
+
+#: ex_cmds2.c:531
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Le point d'interruption %s est introuvable"
+
+#: ex_cmds2.c:557
+msgid "No breakpoints defined"
+msgstr "Aucun point d'interruption n'est défini"
+
+# AB - Le deuxième %s est remplacé par "func" ou "file" sans que l'on puisse
+# traduire ces mots.
+#: ex_cmds2.c:562
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s ligne %ld"
+
+# AB - "changes to" est redondant et a été omis de la version française.
+#: ex_cmds2.c:777
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Enregistrer %.*s ?"
+
+# AB - Si les parenthèses posent problème, il faudra remettre les guillements
+# ci-dessus.
+#: ex_cmds2.c:779 ex_docmd.c:8917
+msgid "Untitled"
+msgstr "(sans titre)"
+
+# AB - Il faut respecter l'esprit plus que la lettre.
+# AB - Ce message est similaire au message E89.
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Le tampon %s n'a pas été enregistré"
+
+# ## HERE ###
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "Alerte: Entrée inattendue dans un autre tampon (vérifier autocmdes)"
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: Il n'y a qu'un seul fichier à éditer"
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: Ne peut aller avant le premier fichier"
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Ne peut aller au delà du dernier fichier"
+
+#: ex_cmds2.c:1841
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Recherche de \"%s\" dans \"%s\""
+
+#: ex_cmds2.c:1863
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Recherche de \"%s\""
+
+#: ex_cmds2.c:1884
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "introuvable dans 'runtimepath': \"%s\""
+
+#: ex_cmds2.c:1918
+msgid "Source Vim script"
+msgstr "Sourcer un script - Vim"
+
+#: ex_cmds2.c:2069
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "Ne peut sourcer un répertoire: \"%s\""
+
+#: ex_cmds2.c:2099
+#, c-format
+msgid "could not source \"%s\""
+msgstr "pas pu sourcer \"%s\""
+
+#: ex_cmds2.c:2101
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "ligne %ld: pas pu sourcer \"%s\""
+
+#: ex_cmds2.c:2115
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "sourçage \"%s\""
+
+# TODO
+#: ex_cmds2.c:2117
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "ligne %ld: sourçage de \"%s\""
+
+# todo
+#: ex_cmds2.c:2242
+#, c-format
+msgid "finished sourcing %s"
+msgstr "fin du sourçage de %s"
+
+#: ex_cmds2.c:2580
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Warning: Mauvais séparateur de ligne, ^M manque peut-être"
+
+#: ex_cmds2.c:2629
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :scriptencoding utilisé en dehors d'un fichier sourcé"
+
+# todo
+#: ex_cmds2.c:2662
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish utilisé en dehors d'un fichier sourcé"
+
+#: ex_cmds2.c:3105
+#, c-format
+msgid "Page %d"
+msgstr "Page %d"
+
+#: ex_cmds2.c:3261
+msgid "No text to be printed"
+msgstr "Pas de texte à imprimer"
+
+#: ex_cmds2.c:3339
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "Impression de la page %d (%d%%)"
+
+#: ex_cmds2.c:3348
+#, c-format
+msgid " Copy %d of %d"
+msgstr " Copie %d de %d"
+
+#: ex_cmds2.c:3406
+#, c-format
+msgid "Printed: %s"
+msgstr "Imprimé: %s"
+
+#: ex_cmds2.c:3413
+msgid "Printing aborted"
+msgstr "Impression interrompue"
+
+#: ex_cmds2.c:3778
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Erreur lors de l'écriture du fichier PostScript de sortie"
+
+#: ex_cmds2.c:4053
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E624: Peut pas ouvrir le fichier \"%s\""
+
+#: ex_cmds2.c:4063 ex_cmds2.c:4688
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Peut pas lire le fichier de ressource PostScript \"%s\""
+
+#: ex_cmds2.c:4071
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: \"%s\" n'est pas un fichier de ressource PostScript"
+
+#: ex_cmds2.c:4086 ex_cmds2.c:4106 ex_cmds2.c:4121 ex_cmds2.c:4143
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: \"%s\" n'est pas un fichier de ressource PostScript supporté"
+
+#: ex_cmds2.c:4173
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: La version du fichier de ressource \"%s\" est mauvaise"
+
+#: ex_cmds2.c:4640
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Peut pas ouvrir le fichier PostScript de sortie"
+
+#: ex_cmds2.c:4673
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Peut pas ouvrir le fichier \"%s\""
+
+#: ex_cmds2.c:4792
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr "E456: Le fichier de ressource PostScript \"prolog.ps\" est introuvable"
+
+#: ex_cmds2.c:4823
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: Le fichier de ressource PostScript \"%s.ps\" est introuvable"
+
+# TODO
+#: ex_cmds2.c:4841
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr "E620: La conversion du multi-octet à l'encodage \"%s\" a échoué"
+
+#: ex_cmds2.c:4966
+msgid "Sending to printer..."
+msgstr "Envoi à l'imprimante..."
+
+#: ex_cmds2.c:4970
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: L'impression du fichier PostScript a échoué"
+
+#: ex_cmds2.c:4972
+msgid "Print job sent."
+msgstr "Job d'impression envoyé."
+
+#: ex_cmds2.c:5381
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Langage %scourant: \"%s\""
+
+#: ex_cmds2.c:5392
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Pas pu régler le langage sur \"%s\""
+
+#: ex_docmd.c:489
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Démarrage du mode Ex. Tapez \"visual\" pour aller en mode Normal."
+
+#. must be at EOF
+#: ex_docmd.c:525
+msgid "E501: At end-of-file"
+msgstr "E501: À la fin du fichier"
+
+#: ex_docmd.c:627
+msgid "E169: Command too recursive"
+msgstr "E169: Commande trop récursive"
+
+# TODO
+#: ex_docmd.c:1094
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: Exception pas attrapée: %s"
+
+# todo
+#: ex_docmd.c:1180
+msgid "End of sourced file"
+msgstr "Fin du fichier sourcé"
+
+#: ex_docmd.c:1181
+msgid "End of function"
+msgstr "Fin de la fonction"
+
+#: ex_docmd.c:1633
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: Utilisation ambigüe d'une commande définie par l'utilisateur"
+
+#: ex_docmd.c:1647
+msgid "E492: Not an editor command"
+msgstr "E492: Pas une commande de l'éditeur"
+
+# TODO This message should *so* be E42!
+#: ex_docmd.c:1737
+msgid "E478: Don't panic!"
+msgstr "E478: Ne paniquez pas !"
+
+#: ex_docmd.c:1756
+msgid "E493: Backwards range given"
+msgstr "E493: Champ d'action inversé reçu"
+
+# todo
+#: ex_docmd.c:1765
+msgid "Backwards range given, OK to swap"
+msgstr "Champ d'action inversé reçu, OK pour inverser"
+
+#: ex_docmd.c:1876
+msgid "E494: Use w or w>>"
+msgstr "E494: Utilisez w ou w>>"
+
+#: ex_docmd.c:3463
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Désolé, cette commande n'est pas disponible dans cette version"
+
+#: ex_docmd.c:3649
+msgid "E172: Only one file name allowed"
+msgstr "E172: Un seul nom de fichier autorisé"
+
+#: ex_docmd.c:4211
+msgid "1 more file to edit. Quit anyway?"
+msgstr "Encore un fichier à éditer. Quitter quand même ?"
+
+#: ex_docmd.c:4214
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "Encore %d fichiers à éditer. Quitter quand même ?"
+
+#: ex_docmd.c:4221
+msgid "E173: 1 more file to edit"
+msgstr "E173: encore un fichier à éditer"
+
+#: ex_docmd.c:4223
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: encore %ld fichiers à éditer"
+
+#: ex_docmd.c:4318
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: La commande existe déjà: ajoutez ! pour la redéfinir"
+
+# TODO
+#: ex_docmd.c:4428
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Nom Args Champ Complét. Définition"
+
+#: ex_docmd.c:4517
+msgid "No user-defined commands found"
+msgstr "Aucune commande définie par l'utilisateur trouvée"
+
+#: ex_docmd.c:4549
+msgid "E175: No attribute specified"
+msgstr "E175: Pas d'attribut spécifié"
+
+#: ex_docmd.c:4601
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Nombre d'arguments invalide"
+
+#: ex_docmd.c:4616
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: La quantité ne peut être indiquée deux fois"
+
+#: ex_docmd.c:4626
+msgid "E178: Invalid default value for count"
+msgstr "E178: La valeur par défaut de la quantité est invalide"
+
+# TODO
+#: ex_docmd.c:4657
+msgid "E179: argument required for complete"
+msgstr "E179: argument requis pour complete"
+
+#: ex_docmd.c:4689
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Valeur complète invalide: %s"
+
+#: ex_docmd.c:4694
+msgid "E467: Custom completion requires a function argument"
+msgstr "E467: La complétion personnalisée requiert une fonction en argument"
+
+#: ex_docmd.c:4699
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr "E468: Seule la complétion personnalisée prend un argument"
+
+#: ex_docmd.c:4709
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Attribut invalide: %s"
+
+#: ex_docmd.c:4752
+msgid "E182: Invalid command name"
+msgstr "E182: Nom de commande invalide"
+
+# TODO
+#: ex_docmd.c:4767
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: Commandes définies par utilisateur doivent commencer par majuscule"
+
+#: ex_docmd.c:4837
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: Pas de telle commande définie par l'utilisateur: %s"
+
+#: ex_docmd.c:5294
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Ne peut trouver le style de couleurs %s"
+
+#: ex_docmd.c:5302
+msgid "Greetings, Vim user!"
+msgstr "Bienvenue, utilisateur de Vim !"
+
+#: ex_docmd.c:6013
+msgid "Edit File in new window"
+msgstr "Ouvrir un fichier dans une nouvelle fenêtre - Vim"
+
+#: ex_docmd.c:6300
+msgid "No swap file"
+msgstr "Pas de fichier d'échange"
+
+#: ex_docmd.c:6404
+msgid "Append File"
+msgstr "Ajouter fichier"
+
+#: ex_docmd.c:6468
+msgid "E186: No previous directory"
+msgstr "E186: Pas de répertoire précédent"
+
+#: ex_docmd.c:6550
+msgid "E187: Unknown"
+msgstr "E187: Inconnu"
+
+#: ex_docmd.c:6635
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: :winsize requiert deux arguments numériques"
+
+#: ex_docmd.c:6686
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Position de la fenêtre: X %d, Y %d"
+
+# TODO
+#: ex_docmd.c:6691
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: La récupération de la position de la fenêtre n'est pas dispo. ici"
+
+#: ex_docmd.c:6701
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: :winpos requiert deux arguments numériques"
+
+# todo
+#: ex_docmd.c:6980
+msgid "Save Redirection"
+msgstr "Enregistrer la redirection"
+
+# todo
+#: ex_docmd.c:7131
+msgid "Save View"
+msgstr "Enregistrer la vue - Vim"
+
+#: ex_docmd.c:7132
+msgid "Save Session"
+msgstr "Enregistrer la session - Vim"
+
+# TODO
+#: ex_docmd.c:7134
+msgid "Save Setup"
+msgstr "Enregistrer les réglages - Vim"
+
+#: ex_docmd.c:7285
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" existe (ajoutez ! pour passer outre)"
+
+#: ex_docmd.c:7290
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: Ne peut ouvrir \"%s\" pour y écrire"
+
+#. set mark
+#: ex_docmd.c:7314
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: L'argument doit être une lettre ou une apostrophe avant/arrière"
+
+#: ex_docmd.c:7356
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Appel récursif de :normal trop important"
+
+#: ex_docmd.c:7869
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: Pas de nom de fichier alternatif à substituer à '#'"
+
+# TODO
+#: ex_docmd.c:7900
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: pas de nom de ficher d'autocommmande à substituer à \"<afile>\""
+
+# TODO
+#: ex_docmd.c:7908
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "E496: pas de numéro de tampon d'autocommande à substituer à \"<abuf>\""
+
+# TODO
+#: ex_docmd.c:7919
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr "E497: pas de nom de corresp. d'autocommande à substituer à \"<amatch>\""
+
+#: ex_docmd.c:7929
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr "E498: pas de nom de fichier :source à substituer à \"<sfile>\""
+
+#: ex_docmd.c:7970
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: Nom de fichier vide pour '%' ou '#', ne marche qu'avec \":p:h\""
+
+#: ex_docmd.c:7972
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: Résulte en une chaîne vide"
+
+#: ex_docmd.c:8899
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: Ne peut ouvrir viminfo pour y lire"
+
+#: ex_docmd.c:9072
+msgid "E196: No digraphs in this version"
+msgstr "E196: Pas de digraphes dans cette version"
+
+#: ex_eval.c:423
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr "E608: Impossible de lancer des exceptions avec 'Vim' comme préfixe"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:509
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "Exception lancée: %s"
+
+#: ex_eval.c:556
+#, c-format
+msgid "Exception finished: %s"
+msgstr "Exception terminée: %s"
+
+#: ex_eval.c:557
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "Exception défaussée: %s"
+
+#: ex_eval.c:600 ex_eval.c:644
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, ligne %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:618
+#, c-format
+msgid "Exception caught: %s"
+msgstr "Exception attrapée: %s"
+
+#: ex_eval.c:693
+#, c-format
+msgid "%s made pending"
+msgstr "%s a été mise en pause"
+
+#: ex_eval.c:696
+#, c-format
+msgid "%s resumed"
+msgstr "%s a été relancée"
+
+#: ex_eval.c:700
+#, c-format
+msgid "%s discarded"
+msgstr "%s a été défaussée"
+
+#: ex_eval.c:726
+msgid "Exception"
+msgstr "Exception"
+
+#: ex_eval.c:732
+msgid "Error and interrupt"
+msgstr "Erreur et interruption"
+
+#: ex_eval.c:734 gui.c:4253
+msgid "Error"
+msgstr "Erreur"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:736
+msgid "Interrupt"
+msgstr "Interruption: "
+
+#: ex_eval.c:810
+msgid "E579: :if nesting too deep"
+msgstr "E579: Imbrication de :if trop importante"
+
+#: ex_eval.c:847
+msgid "E580: :endif without :if"
+msgstr "E580: :endif sans :if"
+
+#: ex_eval.c:891
+msgid "E581: :else without :if"
+msgstr "E581: :else sans :if"
+
+#: ex_eval.c:894
+msgid "E582: :elseif without :if"
+msgstr "E582: :elseif sans :if"
+
+#: ex_eval.c:901
+msgid "E583: multiple :else"
+msgstr "E583: Il ne peut y avoir qu'un seul :else"
+
+#: ex_eval.c:904
+msgid "E584: :elseif after :else"
+msgstr "E584: :elseif après :else"
+
+#: ex_eval.c:971
+msgid "E585: :while nesting too deep"
+msgstr "E585: Imbrication de :while trop importante"
+
+#: ex_eval.c:1027
+msgid "E586: :continue without :while"
+msgstr "E586: :continue sans :while"
+
+#: ex_eval.c:1067
+msgid "E587: :break without :while"
+msgstr "E587: :break sans :while"
+
+#: ex_eval.c:1266
+msgid "E601: :try nesting too deep"
+msgstr "E601: Imbrication de :try trop importante"
+
+#: ex_eval.c:1346
+msgid "E603: :catch without :try"
+msgstr "E603: :catch sans :try"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1368
+msgid "E604: :catch after :finally"
+msgstr "E604: :catch après :finally"
+
+#: ex_eval.c:1501
+msgid "E606: :finally without :try"
+msgstr "E606: :finally sans :try"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1525
+msgid "E607: multiple :finally"
+msgstr "E607: Il ne peut y avoir qu'un seul :finally"
+
+#: ex_eval.c:1634
+msgid "E602: :endtry without :try"
+msgstr "E602: :endtry sans :try"
+
+#: ex_eval.c:1966
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction à l'extérieur d'une fonction"
+
+# TODO
+#: ex_getln.c:3145
+msgid "tagname"
+msgstr "tagname"
+
+# TODO
+#: ex_getln.c:3148
+msgid " kind file\n"
+msgstr " genre de fichier\n"
+
+#: ex_getln.c:4499
+msgid "'history' option is zero"
+msgstr "l'option 'history' vaut zéro"
+
+#: ex_getln.c:4739
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s Historique (chronologie décroissante):\n"
+
+#: ex_getln.c:4740
+msgid "Command Line"
+msgstr "Ligne de commande"
+
+#: ex_getln.c:4741
+msgid "Search String"
+msgstr "Chaîne de recherche"
+
+#: ex_getln.c:4742
+msgid "Expression"
+msgstr "Expression"
+
+#: ex_getln.c:4743
+msgid "Input Line"
+msgstr "Ligne d'entrée"
+
+#: ex_getln.c:4773
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar au delà de la longueur de la commande"
+
+#: ex_getln.c:4950
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Tampon ou fenêtre active effacé(e)"
+
+#: fileio.c:373
+msgid "Illegal file name"
+msgstr "Nom de fichier illégal"
+
+#: fileio.c:397 fileio.c:522 fileio.c:2686 fileio.c:2727
+msgid "is a directory"
+msgstr "est un répertoire"
+
+#: fileio.c:399
+msgid "is not a file"
+msgstr "n'est pas un fichier"
+
+#: fileio.c:544 fileio.c:3836
+msgid "[New File]"
+msgstr "[Nouveau fichier]"
+
+#: fileio.c:566
+msgid "[Permission Denied]"
+msgstr "[Autorisation refusée]"
+
+#: fileio.c:670
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: Les autocommandes *ReadPre ont rendu le fichier illisible"
+
+# TODO
+#: fileio.c:672
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr ""
+"E201: Autocommandes *ReadPre ne doivent pas changer le contenu du tampon "
+"courant"
+
+#: fileio.c:693
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: Lecture de stdin...\n"
+
+#: fileio.c:699
+msgid "Reading from stdin..."
+msgstr "Lecture de stdin..."
+
+#. Re-opening the original file failed!
+#: fileio.c:944
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: La conversion a rendu le fichier illisble !"
+
+#: fileio.c:1892
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:1899
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:1906
+msgid "[socket]"
+msgstr "[socket]"
+
+# TODO
+#: fileio.c:1914
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:1924
+msgid "[CR missing]"
+msgstr "[CR manquant]"
+
+#: fileio.c:1929
+msgid "[NL found]"
+msgstr "[NL trouvé]"
+
+#: fileio.c:1934
+msgid "[long lines split]"
+msgstr "[longues lignes divisées]"
+
+#: fileio.c:1940 fileio.c:3820
+msgid "[NOT converted]"
+msgstr "[PAS converti]"
+
+#: fileio.c:1945 fileio.c:3825
+msgid "[converted]"
+msgstr "[converti]"
+
+#: fileio.c:1952 fileio.c:3850
+msgid "[crypted]"
+msgstr "[chiffré]"
+
+#: fileio.c:1959
+msgid "[CONVERSION ERROR]"
+msgstr "[ERREUR DE CONVERSION]"
+
+#: fileio.c:1965
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[OCTET ILLÉGAL à la ligne %ld]"
+
+#: fileio.c:1972
+msgid "[READ ERRORS]"
+msgstr "[ERREURS DE LECTURE]"
+
+#: fileio.c:2188
+msgid "Can't find temp file for conversion"
+msgstr "Peut pas trouver de fichier temporaire pour la conversion"
+
+#: fileio.c:2195
+msgid "Conversion with 'charconvert' failed"
+msgstr "La conversion avec 'charconvert' a échoué"
+
+#: fileio.c:2198
+msgid "can't read output of 'charconvert'"
+msgstr "peut pas lire la sortie de 'charconvert'"
+
+#: fileio.c:2601
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Des autocommandes ont effacé ou déchargé le tamon à écrire"
+
+#: fileio.c:2624
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: L'autocommande a changé le nombre de lignes de manière inattendue"
+
+#: fileio.c:2692 fileio.c:2710
+msgid "is not a file or writable device"
+msgstr "n'est pas un fichier ou un périphérique inscriptible"
+
+#: fileio.c:2762
+msgid "is read-only (add ! to override)"
+msgstr "est en lecture seule (ajoutez ! pour passer outre)"
+
+#: fileio.c:3068
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: Peut pas écrire dans la copie de secours (ajoutez ! pour passer outre)"
+
+# todo
+#: fileio.c:3080
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr ""
+"E507: Erreur de fermeture de la copie de secours (ajoutez ! pour passer outre)"
+
+# TODO
+#: fileio.c:3082
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr ""
+"E508: Peut pas lire le fichier pour une copie de secours (ajoutez ! pour passer outre)"
+
+#: fileio.c:3098
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: Peut pas créer de copie de secours (ajoutez ! pour passer outre)"
+
+# TODO
+#: fileio.c:3201
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: Peut pas créer de copie de secours (ajoutez ! pour passer outre)"
+
+# TODO
+#: fileio.c:3263
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr ""
+"E460: La section des ressources serait perdue (ajoutez ! pour passer outre)"
+
+#: fileio.c:3364
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: Peut pas trouver le fichier temporaire pour y écrire"
+
+#: fileio.c:3382
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr "E213: Peut pas convertir (ajoutez ! pour écrire sans convertir)"
+
+# todo
+#: fileio.c:3417
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Peut pas ouvrir le fichier lié pour y écrire"
+
+#: fileio.c:3421
+msgid "E212: Can't open file for writing"
+msgstr "E212: Peut pas ouvrir le fichier pour y écrire"
+
+#: fileio.c:3671
+msgid "E512: Close failed"
+msgstr "E512: Erreur de fermeture de fichier"
+
+#: fileio.c:3742
+msgid "E513: write error, conversion failed"
+msgstr "E513: Erreur d'écriture, la conversion a échoué"
+
+#: fileio.c:3748
+msgid "E514: write error (file system full?)"
+msgstr "E514: erreur d'écriture (système de fichiers plein ?)"
+
+#: fileio.c:3815
+msgid " CONVERSION ERROR"
+msgstr " ERREUR DE CONVERSION"
+
+#: fileio.c:3831
+msgid "[Device]"
+msgstr "[Périph.]"
+
+#: fileio.c:3836
+msgid "[New]"
+msgstr "[Nouveau]"
+
+#: fileio.c:3858
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:3858
+msgid " appended"
+msgstr " ajouté(s)"
+
+#: fileio.c:3860
+msgid " [w]"
+msgstr " [e]"
+
+#: fileio.c:3860
+msgid " written"
+msgstr " écrit(s)"
+
+#: fileio.c:3913
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: patchmode: peut pas sauver le fichier original"
+
+#: fileio.c:3935
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: peut pas toucher le fichier original vide"
+
+#: fileio.c:3950
+msgid "E207: Can't delete backup file"
+msgstr "E207: Peut pas effacer la copie de secours"
+
+#: fileio.c:4014
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"ALERTE: Le fichier original est peut-être perdu ou endommagé\n"
+
+#: fileio.c:4016
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "ne quittez pas l'éditeur sans que le fichier soit bien enregistré !"
+
+#: fileio.c:4105
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:4105
+msgid "[dos format]"
+msgstr "[format dos]"
+
+#: fileio.c:4112
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:4112
+msgid "[mac format]"
+msgstr "[format mac]"
+
+#: fileio.c:4119
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:4119
+msgid "[unix format]"
+msgstr "[format unix]"
+
+#: fileio.c:4146
+msgid "1 line, "
+msgstr "1 ligne, "
+
+#: fileio.c:4148
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld lignes, "
+
+#: fileio.c:4151
+msgid "1 character"
+msgstr "1 caractère"
+
+#: fileio.c:4153
+#, c-format
+msgid "%ld characters"
+msgstr "%ld caractères"
+
+# TODO
+#: fileio.c:4163
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:4163
+msgid "[Incomplete last line]"
+msgstr "[Dernière ligne incomplète]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4182
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "ALERTE: Le fichier a été modifié depuis que Vim l'a lu !"
+
+#: fileio.c:4184
+msgid "Do you really want to write to it"
+msgstr "Voulez-vous vraiment écrire dedans"
+
+#: fileio.c:5225
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Erreur lors de l'écriture dans \"%s\""
+
+#: fileio.c:5232
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Erreur lors de la fermeture de \"%s\""
+
+#: fileio.c:5235
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Erreur lors de la lecture de \"%s\""
+
+#: fileio.c:5455
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: L'auto-commande FileChangedShell a effacé le tampon"
+
+#: fileio.c:5463
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: Alerte: Le fichier \"%s\" n'est plus disponible"
+
+# todo
+#: fileio.c:5476
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr "W12: Alerte: Le fichier \"%s\" a changé et le tampon a par ailleurs été modifié dans Vim"
+
+#: fileio.c:5479
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: Alerte: Le fichier \"%s\" a changé depuis le début de l'édition"
+
+#: fileio.c:5481
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: Alerte: Les permissions de \"%s\" ont changé depuis le début de l'édition"
+
+#: fileio.c:5491
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: Alerte: Le fichier \"%s\" a été créé après le début de l'édition"
+
+#: fileio.c:5508
+msgid "Warning"
+msgstr "Alerte"
+
+#: fileio.c:5509
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&Ok\n"
+"&Charge le fichier"
+
+#: fileio.c:5607
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: Pas pu préparer le rechargement de \"%s\""
+
+#: fileio.c:5626
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: Pas pu recharger \"%s\""
+
+#: fileio.c:6208
+msgid "--Deleted--"
+msgstr "--Effacé--"
+
+#. the group doesn't exist
+#: fileio.c:6368
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Pas de tel groupe: \"%s\""
+
+#: fileio.c:6493
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Caractère illégal après *: %s"
+
+#: fileio.c:6504
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Pas de tel évènement: %s"
+
+#. Highlight title
+#: fileio.c:6653
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Auto-commandes ---"
+
+#: fileio.c:6924
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Impossible d'exécuter une autocommande pour TOUS les évènements"
+
+#: fileio.c:6947
+msgid "No matching autocommands"
+msgstr "Pas d'autocommande correspondante"
+
+#: fileio.c:7267
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: autocommandes trop imbriquées"
+
+#: fileio.c:7535
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Auto commandes pour \"%s\""
+
+#: fileio.c:7543
+#, c-format
+msgid "Executing %s"
+msgstr "Exécution de %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7611
+#, c-format
+msgid "autocommand %s"
+msgstr "autocommande %s"
+
+#: fileio.c:8178
+msgid "E219: Missing {."
+msgstr "E219: { manquant."
+
+#: fileio.c:8180
+msgid "E220: Missing }."
+msgstr "E220: } manquant."
+
+#: fold.c:66
+msgid "E490: No fold found"
+msgstr "E490: Pas trouvé de repli"
+
+#: fold.c:553
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: Ne peut créer de repli avec la 'foldmethod' courante"
+
+#: fold.c:555
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: Ne peut effacer le repli avec la 'foldmethod' courante"
+
+#: getchar.c:246
+msgid "E222: Add to read buffer"
+msgstr "E222: Ajout au tampon de lecture"
+
+#: getchar.c:2156
+msgid "E223: recursive mapping"
+msgstr "E223: mapping récursif"
+
+#: getchar.c:3022
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: une abbréviation globale existe déjà pour %s"
+
+#: getchar.c:3025
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: un mapping global existe déjà pour %s"
+
+#: getchar.c:3152
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: une abbréviation existe déjà pour %s"
+
+#: getchar.c:3155
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: un mapping existe déjà pour %s"
+
+#: getchar.c:3219
+msgid "No abbreviation found"
+msgstr "Pas d'abbréviation trouvée"
+
+# TODO
+#: getchar.c:3221
+msgid "No mapping found"
+msgstr "Pas de mapping trouvé"
+
+#: getchar.c:4111
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: Mode illégal"
+
+#: gui.c:219
+msgid "E229: Cannot start the GUI"
+msgstr "E229: Impossible de démarrer l'interface graphique"
+
+#: gui.c:348
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Pas pu lire \"%s\""
+
+#: gui.c:473
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: 'guifontwide' est invalide"
+
+#: gui.c:3939
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: Peut pas allouer la couleur %s"
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<pas pu ouvrir> "
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: pas pu récupérer la fonte %s"
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: pas pu revenir dans le répertoire courant"
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "Chemin:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: pas pu récupérer le répertoire courant"
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "Ok"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2634 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "Annuler"
+
+# TODO
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Widget scrollbar: Pas pu récupérer la géométrie du thumb pixmap. '^_^"
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "Vim"
+
+# todo
+#: gui_beval.c:98
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: Ne peut créer BalloonEval avec message ET callback"
+
+#: gui_gtk.c:1563
+msgid "Vim dialog..."
+msgstr "Vim"
+
+#: gui_gtk.c:1998 message.c:2757
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Oui\n"
+"&Non\n"
+"&Annuler"
+
+# todo '_' is for hotkey, i guess?
+#: gui_gtk.c:2161
+msgid "Input _Methods"
+msgstr "_Méthodes de saisie"
+
+#: gui_gtk.c:2427 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "Remplacer - Vim"
+
+#: gui_gtk.c:2435 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "Rechercher - Vim"
+
+#: gui_gtk.c:2467 gui_motif.c:2888
+msgid "Find what:"
+msgstr "Rechercher :"
+
+#: gui_gtk.c:2487 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "Remplacer par :"
+
+# todo
+#. whole word only button
+#: gui_gtk.c:2519 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "Mots entiers seulement"
+
+#. match case button
+#: gui_gtk.c:2532 gui_motif.c:3048
+msgid "Match case"
+msgstr "Respecter casse"
+
+#: gui_gtk.c:2544 gui_motif.c:2990
+msgid "Direction"
+msgstr "Direction"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2556 gui_motif.c:3002
+msgid "Up"
+msgstr "Haut"
+
+#: gui_gtk.c:2560 gui_motif.c:3010
+msgid "Down"
+msgstr "Bas"
+
+#: gui_gtk.c:2586 gui_gtk.c:2588 gui_motif.c:2792
+msgid "Find Next"
+msgstr "Suivant"
+
+#: gui_gtk.c:2605 gui_gtk.c:2607 gui_motif.c:2809
+msgid "Replace"
+msgstr "Remplacer"
+
+#: gui_gtk.c:2618 gui_gtk.c:2620 gui_motif.c:2822
+msgid "Replace All"
+msgstr "Remplacer tout"
+
+# todo
+#: gui_gtk_x11.c:2285
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: Une requête \"meurs\" a été reçue du gestionnaire de session\n"
+
+#: gui_gtk_x11.c:3474
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: Fenêtre principale détruite inattendûment\n"
+
+#: gui_gtk_x11.c:4088
+msgid "Font Selection"
+msgstr "Choisir une police - Vim"
+
+# todo
+#: gui_gtk_x11.c:5940 ui.c:2009
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "Utilisé CUT_BUFFER0 au lieu d'une sélection vide"
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "Filtre"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "Répertoires"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "Aide"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "Fichiers"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "Sélection"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "Annuler"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: Ne peut charger la fonte Zap '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: Ne peut utiliser la fonte %s"
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Envoi d'un message pour interrompre le processus fils.\n"
+
+#: gui_w32.c:760
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Argument insupporté: \"-%s\"; Utilisez la version OLE."
+
+#: gui_w48.c:2048
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Trouver un texte (utilisez '\\\\' pour trouver un '\\')"
+
+#: gui_w48.c:2073
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Chercher et remplacer (utilisez '\\\\' pour trouver un '\\')"
+
+# todo
+#: gui_x11.c:1479
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: Erreur d'allocation de couleur, couleurs incorrectes possibles"
+
+#: gui_x11.c:2060
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: Pas de fontes pour ces charsets dans le fontset %s:"
+
+#: gui_x11.c:2103
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Nom du fontset: %s"
+
+# todo
+#: gui_x11.c:2104
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "La fonte '%s' n'a pas une largeur fixe"
+
+# TODO
+#: gui_x11.c:2123
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Nom du fontset: %s\n"
+
+#: gui_x11.c:2124
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Font0: %s\n"
+
+#: gui_x11.c:2125
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Font1: %s\n"
+
+#: gui_x11.c:2126
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "La largeur de Font%d n'est pas le double de celle de Font0\n"
+
+#: gui_x11.c:2127
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "Largeur Font0: %ld\n"
+
+#: gui_x11.c:2128
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"Largeur Font1: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: ERREUR de l'automate Hangul"
+
+#: if_cscope.c:76
+msgid "Add a new database"
+msgstr "Ajouter une base de données"
+
+#: if_cscope.c:78
+msgid "Query for a pattern"
+msgstr "Requête selon un motif"
+
+#: if_cscope.c:80
+msgid "Show this message"
+msgstr "Afficher ce message"
+
+#: if_cscope.c:82
+msgid "Kill a connection"
+msgstr "Casser une connection"
+
+#: if_cscope.c:84
+msgid "Reinit all connections"
+msgstr "Réinitialiser les connections"
+
+#: if_cscope.c:86
+msgid "Show connections"
+msgstr "Montrer les connections"
+
+#: if_cscope.c:94
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: Utilisation: cs[cope] %s"
+
+#: if_cscope.c:126
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Cette commande cscope ne supporte pas la séparation de la fenêtre.\n"
+
+#: if_cscope.c:167
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: Utilisation: cstag <ident>"
+
+#: if_cscope.c:223
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: étiquette introuvable"
+
+#: if_cscope.c:401
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: Erreur stat(%s): %d"
+
+#: if_cscope.c:411
+msgid "E563: stat error"
+msgstr "E563: Erreur stat"
+
+#: if_cscope.c:508
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s n'est pas un répertoire ou une base de données cscope valide"
+
+#: if_cscope.c:523
+#, c-format
+msgid "Added cscope database %s"
+msgstr "Ajouté la base de données cscope %s"
+
+#: if_cscope.c:578
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: erreur lors de la lecture de la connection cscope %ld"
+
+#: if_cscope.c:683
+msgid "E561: unknown cscope search type"
+msgstr "E561: type de recherche cscope inconnu"
+
+# todo
+#: if_cscope.c:725
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: Pas pu créer de tuyaux (pipes) cscope"
+
+# TODO
+#: if_cscope.c:742
+msgid "E622: Could not fork for cscope"
+msgstr "E622: Pas pu forker pour cscope"
+
+#: if_cscope.c:836 if_cscope.c:886
+msgid "cs_create_connection exec failed"
+msgstr "exec de cs_create_connection a échoué"
+
+#: if_cscope.c:887
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: Pas pu engendrer le processus cscope"
+
+#: if_cscope.c:900
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen pour to_fp a échoué"
+
+#: if_cscope.c:902
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen pour fr_fp a échoué"
+
+#: if_cscope.c:940
+msgid "E567: no cscope connections"
+msgstr "E567: pas de connection cscope"
+
+#: if_cscope.c:1014
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: pas de corresp. trouvée pour la requête cscope %s de %s"
+
+# todo
+#: if_cscope.c:1071
+#, c-format
+msgid "E469: invalid cscopequickfix flag %c for %c"
+msgstr "E469: Drapeau cscopequickfix %c pour %c invalide"
+
+#: if_cscope.c:1128
+msgid "cscope commands:\n"
+msgstr "commandes cscope:\n"
+
+#: if_cscope.c:1131
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (Utilisation: %s)"
+
+#: if_cscope.c:1224
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: impossible d'ouvrir la base de données cscope: %s"
+
+# todo
+#: if_cscope.c:1241
+msgid "E626: cannot get cscope database information"
+msgstr "E626: impossible d'obtenir des infos sur la base de données cscope"
+
+# todo
+#: if_cscope.c:1261
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: base de données cscope redondante pas ajoutée"
+
+#: if_cscope.c:1272
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: nombre maximum de connections cscope atteint"
+
+#: if_cscope.c:1388
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: la connection cscope %s n'a pas été trouvée"
+
+#: if_cscope.c:1422
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "connection cscope %s est fermée"
+
+#. should not reach here
+#: if_cscope.c:1562
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: erreur fatale dans cs_manage_matches"
+
+#: if_cscope.c:1822
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "Étiquette cscope: %s"
+
+#: if_cscope.c:1826
+msgid ""
+"\n"
+" # line"
+msgstr ""
+"\n"
+" # ligne"
+
+#: if_cscope.c:1828
+msgid "filename / context / line\n"
+msgstr "nom-fichier / context / ligne\n"
+
+#: if_cscope.c:1979
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: Erreur cscope: %s"
+
+#: if_cscope.c:2141
+msgid "All cscope databases reset"
+msgstr "Toutes les bases de données cscope ont été remises à zéro"
+
+#: if_cscope.c:2209
+msgid "no cscope connections\n"
+msgstr "pas de connection cscope\n"
+
+#: if_cscope.c:2213
+msgid " # pid database name prepend path\n"
+msgstr " # pid nom dans base de données insérer chemin\n"
+
+#: if_python.c:394
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr "E263: Désolé, cette commande est désactivée, la bibliothèque Python n'a pu être chargée."
+
+#: if_python.c:596
+msgid "can't delete OutputObject attributes"
+msgstr "impossible d'effacer les attributs d'OutputObject"
+
+#: if_python.c:603
+msgid "softspace must be an integer"
+msgstr "softspace doit être un nombre entier"
+
+#: if_python.c:611
+msgid "invalid attribute"
+msgstr "attribut invalide"
+
+#: if_python.c:650 if_python.c:664
+msgid "writelines() requires list of strings"
+msgstr "writelines() requiert une liste de chaînes"
+
+#: if_python.c:790
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: Erreur d'initialisation des objets d'E/S"
+
+#: if_python.c:975 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "expression invalide"
+
+#: if_python.c:989 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "expressions désactivée lors de la compilation"
+
+#: if_python.c:1002
+msgid "attempt to refer to deleted buffer"
+msgstr "tentative de référence à un tampon effacé"
+
+#: if_python.c:1017 if_python.c:1058 if_python.c:1122 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "numéro de ligne hors limites"
+
+#: if_python.c:1257
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<objet tampon (effacé) à %8lX>"
+
+#: if_python.c:1348 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "nom de marque invalide"
+
+#: if_python.c:1623
+msgid "no such buffer"
+msgstr "pas de tel tampon"
+
+#: if_python.c:1711
+msgid "attempt to refer to deleted window"
+msgstr "tentative de référence à une fenêtre effacée"
+
+#: if_python.c:1756
+msgid "readonly attribute"
+msgstr "attribut en lecture seule"
+
+#: if_python.c:1769
+msgid "cursor position outside buffer"
+msgstr "curseur positionné en dehors du tampon"
+
+#: if_python.c:1846
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<objet fenêtre (effacé) à %.8lX>"
+
+#: if_python.c:1858
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<objet fenêtre (inconnu) à %.8lX>"
+
+#: if_python.c:1860
+#, c-format
+msgid "<window %d>"
+msgstr "<fenêtre %d>"
+
+#: if_python.c:1936
+msgid "no such window"
+msgstr "pas de telle fenêtre"
+
+#: if_python.c:2193 if_python.c:2228 if_python.c:2278 if_python.c:2346
+#: if_python.c:2466 if_python.c:2518 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1998
+msgid "cannot save undo information"
+msgstr "impossible d'enregistrer les informations d'annulation"
+
+#: if_python.c:2195 if_python.c:2285 if_python.c:2357
+msgid "cannot delete line"
+msgstr "impossible d'effacer la ligne"
+
+#: if_python.c:2230 if_python.c:2373 if_tcl.c:690 if_tcl.c:2020
+msgid "cannot replace line"
+msgstr "impossible de remplacer la ligne"
+
+#: if_python.c:2389 if_python.c:2468 if_python.c:2526
+msgid "cannot insert line"
+msgstr "impossible d'insérer la ligne"
+
+#: if_python.c:2630
+msgid "string cannot contain newlines"
+msgstr "la chaîne ne peut contenir de retour à la ligne"
+
+#: if_ruby.c:396
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr "E266: Désolé, commande inactive, la bibliothèque Ruby n'a pu être chargée."
+
+#: if_ruby.c:459
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: statut longjmp inconnu: %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Basculer implémentation/définition"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Montrer la classe de base de"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Montrer les fonctions membres surchargées"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Récupérer du fichier"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Récupérer du projet"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Récupérer de tous les projets"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Récupérer"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Montrer source de"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Trouver symboles"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Parcourir classe"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Montrer classe dans hiérarchie"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Montrer classe dans hiérarchie restreinte"
+
+# todo
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref référence"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref est référencé par"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref a un(e)"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref utilisée par"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Montrer docu de"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Génération de docu pour"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr "Connection à SNiFF+ impossible. Vérifiez l'environnement (sniffemacs doit être dans le $PATH).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Erreur de lecture. Déconnecté"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ est actuellement "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "pas "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "connecté"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Requête SNiFF+ inconnue: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Erreur de connection à SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ n'est pas connecté"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Ceci n'est pas un tampon SNiFF+"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: Erreur d'écriture. Déconnection"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "numéro de tampon invalide"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "pas encore implémenté"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "option inconnue"
+
+# TODO
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "peut pas régler la/les ligne(s) '^_^"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "marque absente"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "ligne %d colonne %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "peut pas insérer/ajouter ligne"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "drapeau inconnu: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "vimOption inconnue"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "interruption clavier"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "erreur vim"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "peut pas créer cmde tampon/fenêtre: objet en train d'être effacé"
+
+# TODO
+#: if_tcl.c:1545
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr "peut pas inscrire commande de rappel: tampon/fenêtre en effacement"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: ERREUR FATALE TCL: reflist corrompue ?! Contactez vim-dev@vim.org, svp."
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr "peut pas inscrire commande de rappel: réf. tampon/fenêtre introuvable"
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"E571: Désolé, commande désactivée: la bibliothèque Tcl n'a pu être chargée."
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr "E281: ERREUR TCL: code de sortie pas int ?! Contacter vim-dev@vim.org"
+
+#: if_tcl.c:2006
+msgid "cannot get line"
+msgstr "pas pu récupérer la ligne"
+
+# todo
+#: if_xcmdsrv.c:215
+msgid "Unable to register a command server name"
+msgstr "Incapable d'inscrire un nom de serveur de commande"
+
+#: if_xcmdsrv.c:465
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Échec de l'envoi de la commande au programme de destination"
+
+#: if_xcmdsrv.c:735
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: Utilisé une Id de serveur invalide: %s"
+
+#: if_xcmdsrv.c:1098
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: Entrée registre de l'instance de Vim mal formattée. Effacée !"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "Option inconnue"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "Trop d'arguments d'édition"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "Argument manquant après"
+
+# todo
+#: main.c:66
+msgid "Garbage after option"
+msgstr "Détritus après l'option"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr "Trop d'arguments \"+command\", \"-c command\" ou \"--cmd command\""
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "Argument invalide pour"
+
+#: main.c:469
+msgid "This Vim was not compiled with the diff feature."
+msgstr "Ce Vim n'a pas été compilé avec la fonctionnalité diff"
+
+#: main.c:926
+msgid "Attempt to open script file again: \""
+msgstr "Nvle tentative pour ouvrir le script: \""
+
+#: main.c:930 main.c:937 main.c:981 memline.c:3682 memline.c:3686
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:935
+msgid "Cannot open for reading: \""
+msgstr "Ne peut ouvrir en lecture: \""
+
+# todo
+#: main.c:979
+msgid "Cannot open for script output: \""
+msgstr "Ne peut ouvrir pour la sortie script: \""
+
+#: main.c:1113
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d fichiers à éditer\n"
+
+#: main.c:1203
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Alerte: La sortie ne s'effectue pas sur un terminal\n"
+
+#: main.c:1205
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Alerte: L'entrée ne se fait pas sur un terminal\n"
+
+#. just in case..
+#: main.c:1267
+msgid "pre-vimrc command line"
+msgstr "ligne de commande pre-vimrc"
+
+#: main.c:1302
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Ne peut lire \"%s\""
+
+#: main.c:2344
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Plus d'info avec: \"vim -h\"\n"
+
+#: main.c:2377
+msgid "[file ..] edit specified file(s)"
+msgstr "[fichier ...] ouvrir le/s fichier/s spécifié/s"
+
+#: main.c:2378
+msgid "- read text from stdin"
+msgstr "- lire le texte à partir de stdin"
+
+#: main.c:2379
+msgid "-t tag edit file where tag is defined"
+msgstr "-t étiquette ouvrir le fichier qui contient l'étiquette"
+
+#: main.c:2381
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [fichErr] ouvrir au niveau de la première erreur"
+
+#: main.c:2390
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"utiliser:"
+
+#: main.c:2393
+msgid " vim [arguments] "
+msgstr " vim [args] "
+
+#: main.c:2397
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" ou:"
+
+#: main.c:2400
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Arguments:\n"
+
+#: main.c:2401
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\tPlus que des noms de fichier après ceci"
+
+#: main.c:2403
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\tNe pas développer les métacaractères"
+
+#: main.c:2406
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\tInscrire ce gvim pour l'OLE"
+
+#: main.c:2407
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\tDésinscrire gvim de l'OLE"
+
+#: main.c:2410
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\tLancer l'interface graphique (comme \"gvim\")"
+
+#: main.c:2411
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f, --nofork\tAvant-plan; ne pas détacher l'interface graphique du terminal"
+
+#: main.c:2413
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\tMode Vi (comme \"vi\")"
+
+#: main.c:2414
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\tMode Ex (comme \"ex\")"
+
+#: main.c:2415
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\tMode silencieux (batch) (seulement pour \"ex\")"
+
+#: main.c:2417
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\tMode Diff (comme \"vimdiff\")"
+
+#: main.c:2419
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\tMode facile (comme \"evim\", vim sans modes)"
+
+#: main.c:2420
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\tMode lecture seule (comme \"view\")"
+
+#: main.c:2421
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\tMode restreint (comme \"rvim\")"
+
+#: main.c:2422
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\tInterdire l'enregistrement de fichiers"
+
+#: main.c:2423
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\tInterdire toute modification de texte"
+
+#: main.c:2424
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\tMode binaire"
+
+#: main.c:2426
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\tMode lisp"
+
+#: main.c:2428
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\tCompatible avec Vi: 'compatible'"
+
+#: main.c:2429
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\tPas tellement compatible avec Vi: 'nocompatible'"
+
+#: main.c:2430
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\tNiveau de verbosité"
+
+#: main.c:2431
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\tMode de débogage"
+
+#: main.c:2432
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\tNe pas utiliser de fichier d'échange, seulement la mémoire"
+
+#: main.c:2433
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\tLister les fichiers d'échange puis quitter"
+
+#: main.c:2434
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r <fichier>\tRécupérer une session plantée"
+
+#: main.c:2435
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\tComme -r"
+
+#: main.c:2437
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\tNe pas utiliser newcli pour l'ouverture des fenêtres"
+
+#: main.c:2438
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <périf>\tUtiliser <périphérique> pour les E/S"
+
+#: main.c:2441
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\tDémarrer en mode arabique"
+
+#: main.c:2444
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\tDémarrer en mode hébreu"
+
+#: main.c:2447
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\tDémarrer en mode farsi"
+
+#: main.c:2449
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <term>\tRégler le type du terminal sur <terminal>"
+
+#: main.c:2450
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\tUtiliser <vimrc> au lieu du vimrc habituel"
+
+#: main.c:2452
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\tUtiliser <gvimrc> au lieu du gvimrc habituel"
+
+# todo
+#: main.c:2454
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\tNe charger aucun plugin scripté"
+
+#: main.c:2455
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\tOuvrir N fenêtres (défaut: une pour chaque fichier)"
+
+#: main.c:2456
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\tComme -o, mais séparer verticalement"
+
+#: main.c:2457
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\tDémarrer en bas du fichier"
+
+#: main.c:2458
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<numL>\tDémarrer à la ligne <numL>"
+
+#: main.c:2460
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <cmde>\tExécuter <commande> avant même de charger les vimrc"
+
+#: main.c:2462
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <cmde>\tExécuter <commande> une fois le 1er fichier chargé"
+
+#: main.c:2463
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <session>\tLire le fichier <session> une fois le 1er fichier chargé"
+
+#: main.c:2464
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <src>\tLire les commandes du mode Normal à partir du fichier <src>"
+
+#: main.c:2465
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <dest>\tAjouter toutes les commandes tapées dans le fichier <dest>"
+
+#: main.c:2466
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <dest>\tÉcrire toutes les commandes tapées dans le fichier <dest>"
+
+#: main.c:2468
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tÉditer des fichiers encodés"
+
+#: main.c:2472
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <écran>\tConnecter Vim au serveur X indiqué dans <écran>"
+
+#: main.c:2474
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tNe se connecter à aucun serveur X"
+
+#: main.c:2477
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <fich>\tÉditer les <fichiers> dans un serveur Vim si possible"
+
+#: main.c:2478
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr ""
+"--remote-silent ...\tPareil, mais pas de plainte s'il n'y a pas de serveur"
+
+#: main.c:2479
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <fich>\tComme --remote mais ne quitter qu'à la fin de l'édition"
+
+#: main.c:2480
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr ""
+"--remote-wait-silent\tPareil, mais pas de plainte s'il n'y a pas de "
+"serveur"
+
+#: main.c:2481
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <tche>\tEnvoyer <touches> à un serveur Vim puis quitter"
+
+#: main.c:2482
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <expr>\tÉvaluer <exp> dans un serveur Vim, afficher le résultat"
+
+#: main.c:2483
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr ""
+"--serverlist\t\tLister les noms des serveurs Vim disponibles et quitter"
+
+#: main.c:2484
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <nom>\tEnvoyer au / Devenir le serveur Vim nommé <nom>"
+
+#: main.c:2487
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tUtiliser <viminfo> au lieu du viminfo habituel"
+
+#: main.c:2489
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h ou --help\t\tAfficher l'aide (ce message) puis quitter"
+
+#: main.c:2490
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\tAfficher les informations de version puis quitter"
+
+#: main.c:2494
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Arguments reconnus par gvim (version Motif):\n"
+
+#: main.c:2498
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr ""
+"\n"
+"Arguments reconnus par gvim (version neXtaw):\n"
+
+#: main.c:2500
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Arguments reconnus par gvim (version Athena):\n"
+
+#: main.c:2504
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <écran>\tLancer Vim sur cet <écran>"
+
+#: main.c:2505
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tIconifier Vim au démarrage"
+
+#: main.c:2507
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <nom>\t\tEmployer les ressources comme si Vim s'appelait <nom>"
+
+#: main.c:2508
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (pas implémenté)\n"
+
+#: main.c:2510
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <coul>\tUtiliser <couleur> pour l'arrière-plan\t (abrv: -bg)"
+
+#: main.c:2511
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr ""
+"-foreground <coul>\tUtiliser <couleur> pour le texte normal\t (abrv: -fg)"
+
+#: main.c:2512 main.c:2532
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <fonte>\tUtiliser <fonte> pour le texte normal\t (abrv: -fn)"
+
+#: main.c:2513
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <fonte>\tUtiliser <fonte> pour le texte gras"
+
+#: main.c:2514
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <fonte>\tUtiliser <fonte> pour le texte italique"
+
+#: main.c:2515 main.c:2533
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <géom>\tUtiliser cette <géométrie> initiale\t (abrv: -geom)"
+
+#: main.c:2516
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <épais>\tUtiliser cette <épaisseur> de bordure\t (abrv: -bw)"
+
+#: main.c:2517
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <lg>\tUtiliser cette <largeur> de barre de défil. (abrv: -sw)"
+
+#: main.c:2519
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <haut>\tUtiliser cette <hauteur> de menu\t (abrv: -mh)"
+
+#: main.c:2521 main.c:2534
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tUtiliser la vidéo inversée\t\t (abrv: -rv)"
+
+#: main.c:2522
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tNe pas utiliser de vidéo inversée\t (abrv: +rv)"
+
+#: main.c:2523
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <ressource>\tConfigurer la <ressource> spécifiée"
+
+#: main.c:2526
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Arguments reconnus par gvim (version RISC OS):\n"
+
+#: main.c:2527
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <nombre>\tNombre de colonnes initial de la fenêtre"
+
+#: main.c:2528
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <nombre>\tNombre de lignes initial de la fenêtre"
+
+#: main.c:2531
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Arguments reconnus par gvim (version GTK+):\n"
+
+#: main.c:2535
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <écran>\tLancer Vim sur cet <écran>\t (également: --display)"
+
+#: main.c:2537
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr ""
+"--role <rôle>\t\tEndosse un rôle unique pour identifier la fenêtre principale"
+
+#: main.c:2539
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tOuvrir Vim dans un autre widget GTK"
+
+#: main.c:2541
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tAfficher les arguments GNOME"
+
+# TODO
+#: main.c:2773
+msgid "No display"
+msgstr "Pas de display"
+
+#. Failed to send, abort.
+#: main.c:2788
+msgid ": Send failed.\n"
+msgstr ": L'envoi a échoué.\n"
+
+#. Let vim start normally.
+#: main.c:2794
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": L'envoi a échoué. Tentative d'exécution locale\n"
+
+#: main.c:2832 main.c:2853
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d de %d édités"
+
+# TODO
+#: main.c:2875
+msgid "No display: Send expression failed.\n"
+msgstr "Pas de display: L'envoi de l'expression a échoué.\n"
+
+#: main.c:2887
+msgid ": Send expression failed.\n"
+msgstr ": L'envoi de l'expression a échoué.\n"
+
+#: mark.c:656
+msgid "No marks set"
+msgstr "Aucune marque activée"
+
+#: mark.c:658
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: Aucune marque ne correspond à \"%s\""
+
+#. Highlight title
+#: mark.c:669
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"marq ligne col fichier/texte"
+
+#. Highlight title
+#: mark.c:707
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" saut ligne col fichier/texte"
+
+#: mark.c:1072
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Marques dans le fichier:\n"
+
+# TODO
+#. Write the jumplist with -'
+#: mark.c:1107
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# List de saut (le plus récent en premier):\n"
+
+#: mark.c:1202
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Historique des marques dans les fichiers (chronologie décroissante):\n"
+
+#: mark.c:1285
+msgid "Missing '>'"
+msgstr "'>' manquant"
+
+#: mbyte.c:409
+msgid "E543: Not a valid codepage"
+msgstr "E543: Pas une page de codes valable"
+
+#: mbyte.c:4014
+msgid "E284: Cannot set IC values"
+msgstr "E284: Impossible de régler les valeurs IC"
+
+#: mbyte.c:4166
+msgid "E285: Failed to create input context"
+msgstr "E285: Erreur de création du contexte de saisie"
+
+#: mbyte.c:4313
+msgid "E286: Failed to open input method"
+msgstr "E286: Erreur d'ouverture de la méthode de saisie"
+
+# TODO
+#: mbyte.c:4324
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: Alerte: Pas pu établir d'appel de destruction dans la MS"
+
+#: mbyte.c:4330
+msgid "E288: input method doesn't support any style"
+msgstr "E288: la méthode de saisie ne supporte aucun style"
+
+#: mbyte.c:4387
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: la méthode de saisie ne supporte pas mon type de préédition"
+
+# TODO
+#: mbyte.c:4461
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: le style over-the-spot nécessite un fontset"
+
+#: mbyte.c:4493
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: Votre GTK+ est plus ancien que 1.2.3. Zone d'état désactivée"
+
+#: mbyte.c:4772
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Le Serveur de Méthodes de Saisie n'est pas lancé"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: le bloc n'était pas verouillé"
+
+#: memfile.c:989
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Erreur de positionnement lors de la lecture du fichier d'échange"
+
+#: memfile.c:994
+msgid "E295: Read error in swap file"
+msgstr "E295: Erreur de lecture dans le fichier d'échange"
+
+#: memfile.c:1046
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Erreur de positionnement lors de l'écriture du fichier d'échange"
+
+#: memfile.c:1064
+msgid "E297: Write error in swap file"
+msgstr "E297: Erreur d'écriture dans le fichier d'échange"
+
+#: memfile.c:1261
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: Le fichier d'échange existe déjà (attaque par symlink ?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Pas récupéré le bloc n°0 ?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Pas récupéré le bloc n°1 ?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: Pas récupéré le bloc n°2 ?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Oups, on a perdu le fichier d'échange !"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: Pas pu renommer le fichier d'échange"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: Pas pu ouvrir fichier .swp pour \"%s\", récup. impossible"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: Pas récupéré le bloc 0 ?!"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Pas de fichier d'échange trouvé pour %s"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "Entre le numéro du fichier d'échange à utiliser (0 pour quitter): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: Ne peut ouvrir %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "Incapable de lire le bloc 0 de "
+
+# TODO
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Peut-être qu'aucune modif. n'a été faite ou Vim n'a pas mis à jour le fichier d'échange."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " ne peut être utilisé avec cette version de Vim.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Utilisez Vim version 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s ne semble pas être un fichier d'échange de Vim"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " ne peut être utilisé sur cet ordinateur.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "Le fichier a été créé le "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"ou le fichier a été endommagé."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "Utilisation du fichier d'échange \"%s\""
+
+#: memline.c:909
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Fichier original \"%s\""
+
+#: memline.c:922
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Alerte: Le fichier original a pu être changé"
+
+#: memline.c:963
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Incapable de lire le bloc 1 de %s"
+
+#: memline.c:967
+msgid "???MANY LINES MISSING"
+msgstr "???BEAUCOUP DE LIGNES MANQUENT"
+
+#: memline.c:983
+msgid "???LINE COUNT WRONG"
+msgstr "???NOMBRE DE LIGNES ERRONÉ"
+
+#: memline.c:990
+msgid "???EMPTY BLOCK"
+msgstr "???BLOC VIDE"
+
+#: memline.c:1016
+msgid "???LINES MISSING"
+msgstr "???LIGNES MANQUANTES"
+
+#: memline.c:1048
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ID du bloc 1 erronée (%s n'est pas un fichier d'échange ?)"
+
+#: memline.c:1053
+msgid "???BLOCK MISSING"
+msgstr "???BLOC MANQUANT"
+
+#: memline.c:1069
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? d'ici jusqu'à ???FIN des lignes peuvent être corrompues"
+
+#: memline.c:1085
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? d'ici jusqu'à ???FIN des lignes ont pu être insérée/effacées"
+
+#: memline.c:1105
+msgid "???END"
+msgstr "???FIN"
+
+#: memline.c:1131
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Récupération interrompue"
+
+#: memline.c:1133
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: Erreurs lors de la récupération; examinez les lignes commençant par ???"
+
+#: memline.c:1136
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Récupération achevée. Vérifiez si tout est OK."
+
+#: memline.c:1137
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Vous voudrez peut-être enregistrer ce fichier sous un autre nom\n"
+
+#: memline.c:1138
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "et lancer diff avec le fichier original pour repérer les changements)\n"
+
+#: memline.c:1139
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"Effacez le fichier .swp ensuite.\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1195
+msgid "Swap files found:"
+msgstr "Fichiers d'échange trouvés:"
+
+#: memline.c:1373
+msgid " In current directory:\n"
+msgstr " Dans le répertoire courant:\n"
+
+#: memline.c:1375
+msgid " Using specified name:\n"
+msgstr "Utilisant le nom indiqué:\n"
+
+#: memline.c:1379
+msgid " In directory "
+msgstr " Dans le répertoire "
+
+#: memline.c:1397
+msgid " -- none --\n"
+msgstr " -- aucun --\n"
+
+#: memline.c:1469
+msgid " owned by: "
+msgstr " propriété de: "
+
+#: memline.c:1471
+msgid " dated: "
+msgstr " daté: "
+
+#: memline.c:1475 memline.c:3689
+msgid " dated: "
+msgstr " daté: "
+
+#: memline.c:1491
+msgid " [from Vim version 3.0]"
+msgstr " [de Vim version 3.0]"
+
+#: memline.c:1495
+msgid " [does not look like a Vim swap file]"
+msgstr " [ne semble pas être un fichier d'échange Vim]"
+
+#: memline.c:1499
+msgid " file name: "
+msgstr " nom de fichier: "
+
+#: memline.c:1505
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" modifié: "
+
+#: memline.c:1506
+msgid "YES"
+msgstr "OUI"
+
+#: memline.c:1506
+msgid "no"
+msgstr "non"
+
+#: memline.c:1510
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" nom d'utilisateur: "
+
+#: memline.c:1517
+msgid " host name: "
+msgstr " nom d'hôte: "
+
+#: memline.c:1519
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" nom d'hôte: "
+
+#: memline.c:1525
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" processus n°: "
+
+#: memline.c:1531
+msgid " (still running)"
+msgstr " (en cours d'exécution)"
+
+#: memline.c:1543
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [inutilisable avec cette version de Vim]"
+
+#: memline.c:1546
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [inutilisable sur cet ordinateur]"
+
+#: memline.c:1551
+msgid " [cannot be read]"
+msgstr " [ne peut être lu]"
+
+#: memline.c:1555
+msgid " [cannot be opened]"
+msgstr " [ne peut être ouvert]"
+
+#: memline.c:1745
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Préservation impossible, il n'y a pas de fichier d'échange"
+
+#: memline.c:1798
+msgid "File preserved"
+msgstr "Fichier préservé"
+
+# todo
+#: memline.c:1800
+msgid "E314: Preserve failed"
+msgstr "E314: Échec de la préservation"
+
+#: memline.c:1871
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: lnum invalide: %ld"
+
+#: memline.c:1897
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: ligne %ld introuvable"
+
+#: memline.c:2287
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: mauvais id de pointeur de bloc 3"
+
+#: memline.c:2367
+msgid "stack_idx should be 0"
+msgstr "stack_idx devrait être 0"
+
+#: memline.c:2429
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Trop de blocs mis à jour ?"
+
+# todo
+#: memline.c:2611
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: mauvais id de pointeur de bloc 4"
+
+#: memline.c:2638
+msgid "deleted block 1?"
+msgstr "bloc 1 effacé ?"
+
+#: memline.c:2838
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Ligne %ld introuvable"
+
+# todo
+#: memline.c:3081
+msgid "E317: pointer block id wrong"
+msgstr "E317: mauvais id de pointeur de bloc"
+
+#: memline.c:3097
+msgid "pe_line_count is zero"
+msgstr "pe_line_count vaut zéro"
+
+# todo dela delà
+#: memline.c:3126
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: numéro de ligne hors limites: %ld au dela de la fin"
+
+#: memline.c:3130
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: nombre de lignes erroné dans le bloc %ld"
+
+#: memline.c:3179
+msgid "Stack size increases"
+msgstr "La taille de la pile s'accroît"
+
+#: memline.c:3225
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: mauvais id de pointeur de block 2"
+
+#: memline.c:3679
+msgid "E325: ATTENTION"
+msgstr "E325: ATTENTION"
+
+#: memline.c:3680
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Trouvé un fichier d'échange nommé \""
+
+#: memline.c:3684
+msgid "While opening file \""
+msgstr "Lors de l'ouverture du fichier \""
+
+#: memline.c:3693
+msgid " NEWER than swap file!\n"
+msgstr " PLUS RÉCENT que le fichier d'échange !\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3697
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Un autre programme est peut-être en train d'éditer ce fichier.\n"
+" Si c'est le cas, faites attention à ne pas vous retrouver avec\n"
+" deux version différentes du même fichier en faisant des modifications.\n"
+
+#: memline.c:3698
+msgid " Quit, or continue with caution.\n"
+msgstr " Quittez, ou continuez prudemment.\n"
+
+#: memline.c:3699
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) Une session d'édition pour ce fichier a planté.\n"
+
+#: memline.c:3700
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Si c'est le cas, utilisez \":recover\" ou \"vim -r "
+
+#: memline.c:3702
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" pour récupérer les changements (voir \":help recovery\").\n"
+
+#: memline.c:3703
+msgid " If you did this already, delete the swap file \""
+msgstr " Si vous l'avez déjà fait, effacez le fichier d'échange \""
+
+#: memline.c:3705
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" pour éviter ce message.\n"
+
+#: memline.c:3719 memline.c:3723
+msgid "Swap file \""
+msgstr "Le fichier d'échange \""
+
+#: memline.c:3720 memline.c:3726
+msgid "\" already exists!"
+msgstr "\" existe déjà !"
+
+#: memline.c:3729
+msgid "VIM - ATTENTION"
+msgstr "VIM - ATTENTION"
+
+#: memline.c:3731
+msgid "Swap file already exists!"
+msgstr "Un fichier d'échange existe déjà !"
+
+#: memline.c:3735
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"&Ouvrir en lecture seule\n"
+"&Editer quand même\n"
+"&Récupérer\n"
+"&Quitter"
+
+#: memline.c:3737
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"&Ouvrir en lecture seule\n"
+"&Editer quand même\n"
+"&Récupérer\n"
+"&Quitter\n"
+"Le &supprimer"
+
+#: memline.c:3790
+msgid "E326: Too many swap files found"
+msgstr "E326: Trop de fichiers d'échange trouvés"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Une partie du chemin d'éléments de menu n'est pas un sous-menu"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Le menu n'existe que dans un autre mode"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Pas de menu de ce nom"
+
+#: menu.c:509
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Le chemin de menu ne doit pas conduire à un sous-menu"
+
+# todo
+#: menu.c:548
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: Ajout d'éléments directement dans barre de menu interdit"
+
+#: menu.c:554
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Un séparateur ne peut faire partie d'un chemin de menu"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1079
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Menus ---"
+
+#: menu.c:1996
+msgid "Tear off this menu"
+msgstr "Arracher ce menu"
+
+#: menu.c:2061
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Le chemin du menu doit conduire à un élément de menu"
+
+#: menu.c:2081
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Menu introuvable: %s"
+
+#: menu.c:2150
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: Le menu n'est pas défini pour le mode %s"
+
+# todo
+#: menu.c:2188
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Le chemin du menu doit conduire à un sous-menu"
+
+#: menu.c:2209
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Menu introuvable - vérifiez les noms des menus"
+
+# todo
+#: message.c:519
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Erreur détectée en traitant %s:"
+
+#: message.c:535
+#, c-format
+msgid "line %4ld:"
+msgstr "ligne %4ld:"
+
+#: message.c:575
+msgid "[string too long]"
+msgstr "[chaîne trop longue]"
+
+# todo
+#: message.c:721
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "Mainteneur des messages: Adrien Beau <version.francaise@free.fr>"
+
+#: message.c:945
+msgid "Interrupt: "
+msgstr "Interruption: "
+
+#: message.c:948
+msgid "Hit ENTER to continue"
+msgstr "Appuyez sur ENTRÉE pour continuer"
+
+#: message.c:950
+msgid "Hit ENTER or type command to continue"
+msgstr "Appuyez sur ENTRÉE ou tapez une commande pour continuer"
+
+#: message.c:2244
+msgid "-- More --"
+msgstr "-- Plus --"
+
+# TODO
+#: message.c:2247
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (ENTR/RA: ligne, ESPCE/b: page, d/u: demi page, q: quitte)"
+
+#: message.c:2248
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (ENTR: ligne, ESPCE: page, d: demi page, q: quitte)"
+
+#: message.c:2740 message.c:2755
+msgid "Question"
+msgstr "Question"
+
+#: message.c:2742
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Oui\n"
+"&Non"
+
+# todo
+#: message.c:2775
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Oui\n"
+"&Non\n"
+"Tout &sauver\n"
+"Tout &rejeter\n"
+"&Annuler"
+
+# todo
+#: message.c:2816
+msgid "Save File dialog"
+msgstr "Boîte de dialogue 'Enregistrer'"
+
+# todo
+#: message.c:2818
+msgid "Open File dialog"
+msgstr "Boîte de dialogue 'Ouvrir'"
+
+# TODO
+#. TODO: non-GUI file selector here
+#: message.c:2889
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: Désolé, pas d'explorateur de fichiers en mode console"
+
+#: misc1.c:2692
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: Alerte: Modification d'un fichier en lecture seule"
+
+#: misc1.c:2927
+msgid "1 more line"
+msgstr "1 ligne en plus"
+
+#: misc1.c:2929
+msgid "1 line less"
+msgstr "1 ligne en moins"
+
+#: misc1.c:2934
+#, c-format
+msgid "%ld more lines"
+msgstr "%ld lignes en plus"
+
+#: misc1.c:2936
+#, c-format
+msgid "%ld fewer lines"
+msgstr "%ld lignes en moins"
+
+#: misc1.c:2939
+msgid " (Interrupted)"
+msgstr " (Interrompu)"
+
+#: misc1.c:6631
+msgid "Vim: preserving files...\n"
+msgstr "Vim: préservation des fichiers...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6641
+msgid "Vim: Finished.\n"
+msgstr "Vim: Fini.\n"
+
+#: misc2.c:670 misc2.c:686
+msgid "ERROR: "
+msgstr "ERREUR: "
+
+#: misc2.c:690
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[octets] total alloué-libéré %lu-%lu, utilisé %lu, pic %lu\n"
+
+#: misc2.c:692
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[appels] total re/malloc() %lu, total free() %lu\n"
+"\n"
+
+#: misc2.c:747
+msgid "E340: Line is becoming too long"
+msgstr "E340: La ligne devient trop lingue"
+
+#: misc2.c:791
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Erreur interne: lalloc(%ld, )"
+
+#: misc2.c:899
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Mémoire épuisée ! (allocation de %lu octets)"
+
+#: misc2.c:2565
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Appel du shell pour exécuter: \"%s\""
+
+#: misc2.c:2786
+msgid "E545: Missing colon"
+msgstr "E545: Deux-points manquant"
+
+#: misc2.c:2788 misc2.c:2815
+msgid "E546: Illegal mode"
+msgstr "E546: Mode illégal"
+
+#: misc2.c:2854
+msgid "E547: Illegal mouseshape"
+msgstr "E547: Forme de curseur illégale"
+
+#: misc2.c:2894
+msgid "E548: digit expected"
+msgstr "E548: chiffre attendu"
+
+#: misc2.c:2899
+msgid "E549: Illegal percentage"
+msgstr "E549: Pourcentage illégal"
+
+#: misc2.c:3209
+msgid "Enter encryption key: "
+msgstr "Tapez la clé d'encodage: "
+
+#: misc2.c:3210
+msgid "Enter same key again: "
+msgstr "Réentrez la même clé: "
+
+#: misc2.c:3220
+msgid "Keys don't match!"
+msgstr "Les clés ne correspondent pas !"
+
+#: misc2.c:3769
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr "E343: Chemin invalide: '**[nombre]' doit être à la fin du chemin ou être suivi de '%s'."
+
+#: misc2.c:5045
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Répertoire \"%s\" introuvable dans le cdpath"
+
+#: misc2.c:5048
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Fichier \"%s\" introuvable dans le chemin"
+
+# todo
+#: misc2.c:5054
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: Plus de répertoire \"%s\" dans le cdpath"
+
+#: misc2.c:5057
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: Plus de fichier \"%s\" dans le chemin"
+
+#: misc2.c:5291
+msgid "E550: Missing colon"
+msgstr "E550: Deux-points manquant"
+
+#: misc2.c:5303
+msgid "E551: Illegal component"
+msgstr "E551: Composant illégal"
+
+#: misc2.c:5311
+msgid "E552: digit expected"
+msgstr "E552: chiffre attendu"
+
+#. Get here when the server can't be found.
+#: netbeans.c:283
+msgid "Cannot connect to Netbeans #2"
+msgstr "Impossible de se connecter à Netbeans n°2"
+
+#: netbeans.c:291
+msgid "Cannot connect to Netbeans"
+msgstr "Impossible de se connecter à Netbeans"
+
+# TODO
+#: netbeans.c:565
+msgid "read from Netbeans socket"
+msgstr "lu en provenance du socket Netbeans"
+
+#: normal.c:2916
+msgid "Warning: terminal cannot highlight"
+msgstr "Alerte: le terminal ne peut surligner"
+
+#: normal.c:3131
+msgid "E348: No string under cursor"
+msgstr "E348: Pas de chaîne sous le curseur"
+
+#: normal.c:3133
+msgid "E349: No identifier under cursor"
+msgstr "E349: Pas d'identifiant sous le curseur"
+
+#: normal.c:4351
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: Les replis ne peuvent être effacés avec la 'foldmethod' actuelle"
+
+# TODO
+#: ops.c:295
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "1 ligne %sée 1 fois"
+
+# TODO
+#: ops.c:297
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 ligne %sée %d fois"
+
+# TODO
+#: ops.c:302
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld lignes %sées 1 fois"
+
+#: ops.c:305
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld lignes %sées %d fois"
+
+#: ops.c:663
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld lignes à indenter... "
+
+#: ops.c:713
+msgid "1 line indented "
+msgstr "1 ligne indentée "
+
+#: ops.c:715
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld lignes indentées "
+
+#. must display the prompt
+#: ops.c:1647
+msgid "cannot yank; delete anyway"
+msgstr "copie impossible; effacement en tout cas"
+
+#: ops.c:2155
+msgid "1 line changed"
+msgstr "1 ligne modifiée"
+
+#: ops.c:2157
+#, c-format
+msgid "%ld lines changed"
+msgstr "%ld lignes modifiées"
+
+#: ops.c:2541
+#, c-format
+msgid "freeing %ld lines"
+msgstr "libération de %ld lignes"
+
+#: ops.c:2822
+msgid "1 line yanked"
+msgstr "1 ligne copiée"
+
+#: ops.c:2824
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld lignes copiées"
+
+#: ops.c:3109
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: Le registre %s est vide"
+
+#. Highlight title
+#: ops.c:3666
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Registres ---"
+
+#: ops.c:4875
+msgid "Illegal register name"
+msgstr "Nom de registre illégal"
+
+#: ops.c:4961
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Resgistres:\n"
+
+#: ops.c:4994
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: Type de registre %d inconnu"
+
+#: ops.c:5480
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: Nom de registre invalide: '%s'"
+
+#: ops.c:5841
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Cols; "
+
+#: ops.c:5848
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Sélectionné %s%ld de %ld Lignes; %ld de %ld Mots; %ld de %ld Octets"
+
+#: ops.c:5864
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Col %s de %s; Ligne %ld de %ld; Mot %ld de %ld; Octet %ld de %ld"
+
+# todo
+#: ops.c:5875
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld pour le BOM)"
+
+#: option.c:1623
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=Page %N"
+
+#: option.c:2072
+msgid "Thanks for flying Vim"
+msgstr "Merci d'avoir choisi Vim"
+
+#: option.c:3344 option.c:3451
+msgid "E518: Unknown option"
+msgstr "E518: Option inconnue"
+
+#: option.c:3357
+msgid "E519: Option not supported"
+msgstr "E519: Option pas supportée"
+
+# todo
+#: option.c:3382
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: Interdit dans une ligne de mode"
+
+# TODO
+#: option.c:3438
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tRéglé récemment dans "
+
+#: option.c:3577
+msgid "E521: Number required after ="
+msgstr "E521: Nombre requis après ="
+
+#: option.c:3903 option.c:4520
+msgid "E522: Not found in termcap"
+msgstr "E522: Pas trouvé dans termcap"
+
+#: option.c:3969
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: Caractère <%s> illégal"
+
+#: option.c:4512
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: 'term' ne peut pas être une chaîne vide"
+
+#: option.c:4515
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: Changement de term impossible dans l'interface graphique"
+
+#: option.c:4517
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: Utilisez \":gui\" pour démarrer l'interface graphique"
+
+#: option.c:4538
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: 'backupext' et 'patchmode' sont égaux"
+
+#: option.c:4723
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: Inchangeable dans l'interface GTK+ 2"
+
+#: option.c:4879
+msgid "E524: Missing colon"
+msgstr "E524: Deux-points manquant"
+
+#: option.c:4881
+msgid "E525: Zero length string"
+msgstr "E525: Chaîne de longueur nulle"
+
+#: option.c:4949
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: Nombre manquant après <%s>"
+
+#: option.c:4963
+msgid "E527: Missing comma"
+msgstr "E527: Virgule manquante"
+
+#: option.c:4970
+msgid "E528: Must specify a ' value"
+msgstr "E528: Une valeur ' doit être spécifiée"
+
+# todo
+#: option.c:5011
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: contient des caractères multi-octets ou inaffichables"
+
+#: option.c:5060
+msgid "E596: Invalid font(s)"
+msgstr "E596: Fonte(s) invalide(s)"
+
+#: option.c:5068
+msgid "E597: can't select fontset"
+msgstr "E597: sélection de fontset impossible"
+
+# todo
+#: option.c:5070
+msgid "E598: Invalid fontset"
+msgstr "E598: Fontset invalide"
+
+# TODO
+#: option.c:5077
+msgid "E533: can't select wide font"
+msgstr "E533: Sélection de fonte large impossible"
+
+#: option.c:5079
+msgid "E534: Invalid wide font"
+msgstr "E534: Fonte large invalide"
+
+#: option.c:5349
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: Caractère illégal après <%c>"
+
+#: option.c:5453
+msgid "E536: comma required"
+msgstr "E536: virgule requise"
+
+#: option.c:5461
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: 'commentstring' doit être vide ou contenir %s"
+
+#: option.c:5534
+msgid "E538: No mouse support"
+msgstr "E538: La souris n'est pas supportée"
+
+# todo
+#: option.c:5802
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: Séquence d'expression mal fermée"
+
+#: option.c:5806
+msgid "E541: too many items"
+msgstr "E541: trop d'éléments"
+
+#: option.c:5808
+msgid "E542: unbalanced groups"
+msgstr "E542: groupes déséquilibrés"
+
+#: option.c:6029
+msgid "E590: A preview window already exists"
+msgstr "E590: Il y a déjà une fenêtre de prévisualisation"
+
+#: option.c:6286
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr "W17: L'arabique requiert l'UTF-8, tapez ':set encoding=utf-8'"
+
+#: option.c:6603
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: Nécessite au moins %d lignes"
+
+#: option.c:6612
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: Nécessite au moins %d colonnes"
+
+#: option.c:6917
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Option inconnue: %s"
+
+#: option.c:7026
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Codes de terminal ---"
+
+#: option.c:7028
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Valeur des options globales ---"
+
+#: option.c:7030
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Valeur des options locales ---"
+
+#: option.c:7032
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Options ---"
+
+#: option.c:7733
+msgid "E356: get_varp ERROR"
+msgstr "E356: ERREUR get_varp"
+
+#: option.c:8704
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': Caractère correspondant manquant pour %s"
+
+#: option.c:8738
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': Caractères surnuméraires après point-virgule: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "ne peut ouvir "
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Ouverture de la fenêtre impossible !\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Nécessite Amigados version 2.04 ou ultérieure\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Nécessité %s version %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "Ne peut ouvrir NIL:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr "Ne peut créer "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim sort avec %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "changement du mode de console impossible ?!\n"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: pas une console ?!\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1143
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Exécution de shell impossible avec l'option -f"
+
+#: os_amiga.c:1184 os_amiga.c:1274
+msgid "Cannot execute "
+msgstr "Ne peut exécuter "
+
+# todo
+#: os_amiga.c:1187 os_amiga.c:1284
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1207 os_amiga.c:1309
+msgid " returned\n"
+msgstr " retourné\n"
+
+#: os_amiga.c:1450
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE trop petit."
+
+#: os_amiga.c:1454
+msgid "I/O ERROR"
+msgstr "ERREUR d'E/S"
+
+#: os_mswin.c:517
+msgid "...(truncated)"
+msgstr "...(tronqué)"
+
+#: os_mswin.c:619
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' ne vaut pas 80, exécution de commandes externes impossible"
+
+#: os_mswin.c:1854
+msgid "E237: Printer selection failed"
+msgstr "E237: La sélection de l'imprimante a échoué"
+
+# TODO
+#: os_mswin.c:1894
+#, c-format
+msgid "to %s on %s"
+msgstr "vers %s sur %s"
+
+#: os_mswin.c:1909
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: Fonte d'imprimante inconnue: %s"
+
+#: os_mswin.c:1959 os_mswin.c:1969
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Erreur d'impression: %s"
+
+#: os_mswin.c:1970
+msgid "Unknown"
+msgstr "Inconnu"
+
+#: os_mswin.c:1997
+#, c-format
+msgid "Printing '%s'"
+msgstr "Impression de '%s'"
+
+# todo
+#: os_mswin.c:3083
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Nom de jeu de carac. \"%s\" illégal dans nom de fonte \"%s\""
+
+#: os_mswin.c:3091
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Caractère '%c' illégal dans le nom de fonte \"%s\""
+
+#: os_riscos.c:1258
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Option 'osfiletype' invalide - Text est utilisé"
+
+#: os_unix.c:887
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: Signal double, sortie\n"
+
+#: os_unix.c:893
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Signal mortel %s intercepté\n"
+
+#: os_unix.c:896
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Signal mortel intercepté\n"
+
+#: os_unix.c:1159
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "L'ouverture de l'affichage X a pris %ld msec"
+
+#: os_unix.c:1186
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: Reçu l'erreur X\n"
+
+# TODO
+#: os_unix.c:1294
+msgid "Testing the X display failed"
+msgstr "Le test de l'affichage X a échoué"
+
+# TODO
+#: os_unix.c:1433
+msgid "Opening the X display timed out"
+msgstr "L'ouverture de l'affichage X a dépassé les délais"
+
+#: os_unix.c:3165 os_unix.c:3845
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"Échec de l'exécution du shell "
+
+# todo
+#: os_unix.c:3213
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Échec de l'exécution du shell sh\n"
+
+#: os_unix.c:3217 os_unix.c:3851
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"le shell a retourné "
+
+# TODO
+#: os_unix.c:3352
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Création de tuyaux (pipes) impossible\n"
+
+# todo
+#: os_unix.c:3367
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"Séparation impossible\n"
+
+#: os_unix.c:3858
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Commande interrompue\n"
+
+#: os_unix.c:4111 os_unix.c:4236 os_unix.c:5894
+msgid "XSMP lost ICE connection"
+msgstr "XSMP a perdu la connection ICE"
+
+# TODO
+#: os_unix.c:5478
+msgid "Opening the X display failed"
+msgstr "L'ouverture da l'affichage X a échoué"
+
+# TODO
+#: os_unix.c:5800
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP gère une requête sauvez-vous"
+
+#: os_unix.c:5917
+msgid "XSMP opening connection"
+msgstr "ouverture de connection XSMP"
+
+#: os_unix.c:5935
+msgid "XSMP ICE connection watch failed"
+msgstr "XSMP: échec de la surveillance de connection ICE"
+
+#: os_unix.c:5955
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP SmcOpenConnection a échoué: %s"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "À la ligne"
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "Pas pu allouer de la mémoire pour la ligne de commande."
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "Erreur VIM"
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "Le chargement de vim32.dll a échoué !"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Les pointeurs de fonction n'ont pu être ajustés à la DLL !"
+
+#: os_win16.c:341 os_win32.c:3049
+#, c-format
+msgid "shell returned %d"
+msgstr "le shell a retourné %d"
+
+#: os_win32.c:2507
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Évènement %s intercepté\n"
+
+#: os_win32.c:2509
+msgid "close"
+msgstr "fermeture"
+
+#: os_win32.c:2511
+msgid "logoff"
+msgstr "déconnection"
+
+#: os_win32.c:2512
+msgid "shutdown"
+msgstr "arrêt"
+
+#: os_win32.c:3002
+msgid "E371: Command not found"
+msgstr "E371: Commande introuvable"
+
+#: os_win32.c:3015
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE n'est pas dans votre $PATH.\n"
+"Les commandes externes ne feront pas de pause une fois terminées.\n"
+"Voir :help win32-vimrun pour plus d'informations."
+
+# todo
+#: os_win32.c:3018
+msgid "Vim Warning"
+msgstr "Alerte Vim"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Trop de %%%c dans le patron de formattage"
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: %%%c inattendu dans le patron de formattage"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: ] manquant dans le patron de formattage"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: %%%c insupporté dans le patron de formattage"
+
+# todo
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: %%%c invalide dans le préfixe du patron de formattage"
+
+# todo
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: %%%c invalide dans le patron de formattage"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' ne contient aucun motif"
+
+#: quickfix.c:497
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Nom de répertoire vide ou absent"
+
+#: quickfix.c:984
+msgid "E553: No more items"
+msgstr "E553: Plus d'éléments"
+
+#: quickfix.c:1221
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d de %d)%s%s: "
+
+#: quickfix.c:1223
+msgid " (line deleted)"
+msgstr " (ligne effacée)"
+
+#: quickfix.c:1433
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: En bas de la pile quickfix"
+
+# todo
+#: quickfix.c:1442
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Au sommet de la pile quickfix"
+
+#: quickfix.c:1454
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "liste d'erreurs %d sur %d; %d erreurs"
+
+#: quickfix.c:1928
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: Écriture impossible, option 'buftype' activée"
+
+# todo
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: élément invalide dans %s%%[]"
+
+#: regexp.c:827
+msgid "E339: Pattern too long"
+msgstr "E339: Motif trop long"
+
+#: regexp.c:996
+msgid "E50: Too many \\z("
+msgstr "E50: Trop de \\z("
+
+#: regexp.c:1007
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: Trop de %s("
+
+#: regexp.c:1064
+msgid "E52: Unmatched \\z("
+msgstr "E52: Pas de correspondance pour \\z("
+
+#: regexp.c:1068
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: Pas de correspondance pour %s%%("
+
+#: regexp.c:1070
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: Pas de correspondance pour %s("
+
+#: regexp.c:1075
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: Pas de correspondance pour %s)"
+
+# TODO
+#: regexp.c:1244
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: L'opérande %s* pourrait être vide"
+
+# TODO
+#: regexp.c:1247
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: L'opérande %s* pourrait être vide"
+
+#: regexp.c:1301
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: caractère invalide après %s@"
+
+# TODO
+#: regexp.c:1326
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: L'opérande %s{ pourrait être vide"
+
+# todo
+#: regexp.c:1336
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: Trop de %s{...}s complexes"
+
+#: regexp.c:1352
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: %s* imbriqué"
+
+#: regexp.c:1355
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: %s%c imbriqué"
+
+#: regexp.c:1473
+msgid "E63: invalid use of \\_"
+msgstr "E63: utilisation invalide de \\_"
+
+#: regexp.c:1518
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c ne suit rien"
+
+# todo
+#: regexp.c:1574
+msgid "E65: Illegal back reference"
+msgstr "E65: Rétroréférence illégale"
+
+#: regexp.c:1587
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z( n'est pas autorisé ici"
+
+#: regexp.c:1606
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 et co. ne sont pas autorisés ici"
+
+#: regexp.c:1617
+msgid "E68: Invalid character after \\z"
+msgstr "E68: Caractère invalide après \\z"
+
+#: regexp.c:1666
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: Il manque ] après %s%%["
+
+#: regexp.c:1682
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: %s%%[] vide"
+
+#: regexp.c:1742
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: Caractère invalide après %s%%"
+
+#: regexp.c:2539
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: Erreur de syntaxe dans %s{...}"
+
+#: regexp.c:2800
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Plantage intercepté; exp.rég. trop complexe ?"
+
+#: regexp.c:2941
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: un motif a fait déborder la pile"
+
+#: regexp.c:3180
+msgid "External submatches:\n"
+msgstr "Sous-correspondances externes:\n"
+
+#: screen.c:2113
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld lignes pliées "
+
+#: screen.c:7884
+msgid " VREPLACE"
+msgstr " REMPLACEMENT-V"
+
+#: screen.c:7888
+msgid " REPLACE"
+msgstr " REMPLACEMENT"
+
+# TODO
+#: screen.c:7893
+msgid " REVERSE"
+msgstr " REVERSE"
+
+#: screen.c:7895
+msgid " INSERT"
+msgstr " INSERTION"
+
+#: screen.c:7898
+msgid " (insert)"
+msgstr " (insertion)"
+
+#: screen.c:7900
+msgid " (replace)"
+msgstr " (remplacement)"
+
+#: screen.c:7902
+msgid " (vreplace)"
+msgstr " (remplacement-v)"
+
+#: screen.c:7905
+msgid " Hebrew"
+msgstr " hébreu"
+
+#: screen.c:7916
+msgid " Arabic"
+msgstr " arabique"
+
+#: screen.c:7919
+msgid " (lang)"
+msgstr " (langue)"
+
+#: screen.c:7923
+msgid " (paste)"
+msgstr " (collage)"
+
+#: screen.c:7929
+msgid " SELECT"
+msgstr " SELECTION"
+
+#: screen.c:7931
+msgid " VISUAL"
+msgstr " VISUEL"
+
+#: screen.c:7933
+msgid " BLOCK"
+msgstr " BLOC"
+
+#: screen.c:7935
+msgid " LINE"
+msgstr " LIGNE"
+
+#: screen.c:7948 screen.c:8008
+msgid "recording"
+msgstr "enregistrement"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "La recherche a atteint le HAUT, et continue en BAS"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "La recherche a atteint le BAS, et continue en HAUT"
+
+#: search.c:525
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Texte de recherche invalide: %s"
+
+#: search.c:852
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: la recherche a atteint le HAUT sans trouver: %s"
+
+#: search.c:855
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: la recherche a atteint le BAS sans trouver: %s"
+
+#: search.c:1247
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: '?' ou '/' attendu après ';'"
+
+#: search.c:3685
+msgid " (includes previously listed match)"
+msgstr " (inclut des correspondances listées précédemment)"
+
+#. cursor at status line
+#: search.c:3705
+msgid "--- Included files "
+msgstr "--- Fichiers inclus "
+
+#: search.c:3707
+msgid "not found "
+msgstr "introuvable "
+
+#: search.c:3708
+msgid "in path ---\n"
+msgstr "dans le chemin ---\n"
+
+#: search.c:3747
+msgid " (Already listed)"
+msgstr " (Déjà listé)"
+
+#: search.c:3749
+msgid " NOT FOUND"
+msgstr " INTROUVABLE"
+
+#: search.c:3801
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Examen des fichiers inclus: %s"
+
+#: search.c:4019
+msgid "E387: Match is on current line"
+msgstr "E387: La correspondance est sur la ligne courante"
+
+#: search.c:4162
+msgid "All included files were found"
+msgstr "Tous les fichiers inclus ont été trouvés"
+
+# todo
+#: search.c:4164
+msgid "No included files"
+msgstr "Pas de fichiers inclus"
+
+#: search.c:4180
+msgid "E388: Couldn't find definition"
+msgstr "E388: Définition introuvable"
+
+#: search.c:4182
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Motif introuvable"
+
+#: syntax.c:3015
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: Argument illégal: %s"
+
+#: syntax.c:3195
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: Pas de tel surgroupe syntactique: %s"
+
+#: syntax.c:3359
+msgid "No Syntax items defined for this buffer"
+msgstr "Pas d'éléments syntactiques définis pour ce tampon"
+
+#: syntax.c:3367
+msgid "syncing on C-style comments"
+msgstr "synchro sur les commentaire style C"
+
+#: syntax.c:3375
+msgid "no syncing"
+msgstr "pas de synchro"
+
+#: syntax.c:3378
+msgid "syncing starts "
+msgstr "la synchro commence "
+
+#: syntax.c:3380 syntax.c:3455
+msgid " lines before top line"
+msgstr " lignes avant la ligne du haut"
+
+# todo
+#: syntax.c:3385
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Éléments de synchro syntactique ---"
+
+# todo
+#: syntax.c:3390
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"synchronisation sur éléments"
+
+#: syntax.c:3396
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Éléments de syntaxe ---"
+
+#: syntax.c:3419
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: Pas de tel surgroupe de syntaxe: %s"
+
+#: syntax.c:3445
+msgid "minimal "
+msgstr "minimal "
+
+#: syntax.c:3452
+msgid "maximal "
+msgstr "maximal "
+
+# todo
+#: syntax.c:3464
+msgid "; match "
+msgstr "; correspondance"
+
+#: syntax.c:3466
+msgid " line breaks"
+msgstr " fins de ligne"
+
+# todo
+#: syntax.c:4100
+msgid "E393: group[t]here not accepted here"
+msgstr "E394: group[t]here pas accepté ici"
+
+# todo
+#: syntax.c:4124
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: Pas trouvé d'objet region pour %s"
+
+#: syntax.c:4152
+msgid "E395: contains argument not accepted here"
+msgstr "E395: L'argument contains n'est pas accepté ici"
+
+#: syntax.c:4163
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: L'argument containedin n'est pas accepté ici"
+
+#: syntax.c:4241
+msgid "E397: Filename required"
+msgstr "E397: Nom de fichier requis"
+
+#: syntax.c:4579
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: '=' manquant: %s"
+
+#: syntax.c:4737
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Pas assez d'arguments: syntax region %s"
+
+# TODO
+#: syntax.c:5068
+msgid "E400: No cluster specified"
+msgstr "E400: Aucun surgroupe spécifié"
+
+#: syntax.c:5105
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Délimiteur de motif introuvable: %s"
+
+# todo
+#: syntax.c:5180
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Détritus après le motif: %s"
+
+# todo
+#: syntax.c:5270
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: synchro syntax: motif de continuation de ligne présent deux fois"
+
+#: syntax.c:5327
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Arguments illégaux: %s"
+
+#: syntax.c:5377
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Signe égal manquant: %s"
+
+#: syntax.c:5383
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Argument vide: %s"
+
+#: syntax.c:5410
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s n'est pas permis ici"
+
+#: syntax.c:5417
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s doit être le premier élément d'une liste contains"
+
+#: syntax.c:5487
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Nom de groupe inconnu: %s"
+
+#: syntax.c:5720
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Sous-commande de :syntax invalide: %s"
+
+#: syntax.c:6099
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: groupe de surlignage introuvable: %s"
+
+#: syntax.c:6123
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Pas assez d'arguments: \":highlight link %s\""
+
+#: syntax.c:6130
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: Trop d'arguments: \":highlight link %s\""
+
+# TODO
+#: syntax.c:6150
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: le groupe a des réglages, lien de surlignage ignoré"
+
+#: syntax.c:6279
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: signe égal inattendu: %s"
+
+#: syntax.c:6315
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: signe égal manquant: %s"
+
+#: syntax.c:6337
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: argument manquant: %s"
+
+#: syntax.c:6374
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: Valeur illégale: %s"
+
+#: syntax.c:6493
+msgid "E419: FG color unknown"
+msgstr "E419: Couleur de premier plan inconnue"
+
+#: syntax.c:6504
+msgid "E420: BG color unknown"
+msgstr "E420: Couleur d'arrière-plan inconnue"
+
+#: syntax.c:6565
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Nom ou numéro de couleur non reconnu: %s"
+
+#: syntax.c:6771
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: le code de terminal est trop long: %s"
+
+#: syntax.c:6818
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: Argument illégal: %s"
+
+#: syntax.c:7347
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: Trop d'attributs de surlignage différents en cours d'utilisation"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: En bas de la pile d'étiquettes"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: Au sommet de la pile d'étiquettes"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Ne peut aller avant la première étiquette correspondante"
+
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: Étiquette introuvable: %s"
+
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr " # pri type étiquette"
+
+#: tag.c:548
+msgid "file\n"
+msgstr "fichier\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Entrez le no choisi (<CR> pour annuler): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: Il n'y a qu'une étiquette correspondante"
+
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Ne peut aller au delà de la dernière étiquette correspondante"
+
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Le fichier \"%s\" n'existe pas"
+
+#. Give an indication of the number of matching tags
+#: tag.c:781
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "étiquette %d de %d%s"
+
+#: tag.c:784
+msgid " or more"
+msgstr " ou plus"
+
+#: tag.c:786
+msgid " Using tag with different case!"
+msgstr " Utilisation d'une étiquette dans une casse différente !"
+
+#: tag.c:830
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Le fichier \"%s\" n'existe pas"
+
+# todo
+#. Highlight title
+#: tag.c:899
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # VERS étiquette DE ligne dans fichier/texte"
+
+#: tag.c:1200
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Examen du fichier d'étiquettes %s"
+
+#: tag.c:1384
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Chemin de fichiers d'étiquettes tronqué pour %s\n"
+
+#: tag.c:1914
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Erreur de format dans le fichier d'étiquettes \"%s\""
+
+#: tag.c:1918
+#, c-format
+msgid "Before byte %ld"
+msgstr "Avant l'octet %ld"
+
+#: tag.c:1939
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Le fichier d'étiquettes n'est pas classé: %s"
+
+#. never opened any tags file
+#: tag.c:1979
+msgid "E433: No tags file"
+msgstr "E433: Par de fichier d'étiquettes"
+
+# todo
+#: tag.c:2666
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Le motif de l'étiquette est introuvable"
+
+#: tag.c:2677
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Étiquette introuvable, on se contente de deviner !"
+
+#: term.c:1745
+msgid "' not known. Available builtin terminals are:"
+msgstr "' inconnu. Les terminaux internes sont:"
+
+# todo
+#: term.c:1769
+msgid "defaulting to '"
+msgstr "utilisation par défaut de '"
+
+#: term.c:2127
+msgid "E557: Cannot open termcap file"
+msgstr "E557: Le fichier termcap ne peut être ouvert"
+
+#: term.c:2131
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: La description du terminal n'a pas été trouvée dans terminfo"
+
+#: term.c:2133
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: La description du terminal n'a pas été trouvée dans termcap"
+
+# todo
+#: term.c:2292
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Pas d'entrée \"%s\" dans termcap"
+
+# todo
+#: term.c:2766
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: capacité de terminal \"cm\" requise"
+
+#. Highlight title
+#: term.c:4970
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Touches du terminal ---"
+
+# todo
+#: ui.c:252
+msgid "new shell started\n"
+msgstr "nouveau shell démarré\n"
+
+# todo
+#: ui.c:1784
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: Erreur en lisant l'entrée, sortie...\n"
+
+# todo
+#. must display the prompt
+#: undo.c:394
+msgid "No undo possible; continue anyway"
+msgstr "Annulation impossible; on continue quand même"
+
+#: undo.c:549
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: numéros de ligne erronés"
+
+#: undo.c:718
+msgid "1 change"
+msgstr "1 changement"
+
+#: undo.c:720
+#, c-format
+msgid "%ld changes"
+msgstr "%ld changements"
+
+#: undo.c:764
+msgid "E439: undo list corrupt"
+msgstr "E439: la liste d'annulation est corrompue"
+
+# todo
+#: undo.c:796
+msgid "E440: undo line missing"
+msgstr "E440: ligne d'annulation manquante"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:724
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"Version graphique MS-Windows 16/32 bits"
+
+#: version.c:726
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"Version graphique MS-Windows 32 bits"
+
+#: version.c:729
+msgid " in Win32s mode"
+msgstr " lancée en mode Win32s"
+
+#: version.c:731
+msgid " with OLE support"
+msgstr " supportant l'OLE"
+
+#: version.c:734
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"Version console MS-Windows 32 bits"
+
+#: version.c:738
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"Version MS-Windows 16 bits"
+
+#: version.c:742
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"Version MS-DOS 32 bits"
+
+#: version.c:744
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"Version MS-DOS 16 bits"
+
+#: version.c:750
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"Version MaxOS X (unix)"
+
+#: version.c:752
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"Version MacOS X"
+
+#: version.c:755
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"Version MacOS"
+
+#: version.c:760
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"Version RISC OS"
+
+# todo
+#: version.c:770
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Patches inclus: "
+
+#: version.c:796 version.c:1145
+msgid "Modified by "
+msgstr "Modifié par "
+
+#: version.c:803
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Compilé "
+
+#: version.c:806
+msgid "by "
+msgstr "par "
+
+#: version.c:818
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Énorme version "
+
+#: version.c:821
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Grosse version "
+
+#: version.c:824
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Version normale "
+
+#: version.c:827
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Petite version "
+
+#: version.c:829
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Version minuscule "
+
+#: version.c:835
+msgid "without GUI."
+msgstr "sans interface graphique."
+
+#: version.c:840
+msgid "with GTK2-GNOME GUI."
+msgstr "avec interface GTK2-GNOME."
+
+#: version.c:842
+msgid "with GTK-GNOME GUI."
+msgstr "avec interface GTK-GNOME."
+
+#: version.c:846
+msgid "with GTK2 GUI."
+msgstr "avec interface GTK2."
+
+#: version.c:848
+msgid "with GTK GUI."
+msgstr "avec interface GTK."
+
+#: version.c:853
+msgid "with X11-Motif GUI."
+msgstr "avec interface X11-Motif."
+
+#: version.c:857
+msgid "with X11-neXtaw GUI."
+msgstr "avec interface X11-neXtaw."
+
+#: version.c:859
+msgid "with X11-Athena GUI."
+msgstr "avec interface X11-Athena."
+
+#: version.c:863
+msgid "with BeOS GUI."
+msgstr "avec interface BeOS."
+
+#: version.c:866
+msgid "with Photon GUI."
+msgstr "avec interface Photon."
+
+#: version.c:869
+msgid "with GUI."
+msgstr "avec une interface graphique."
+
+#: version.c:872
+msgid "with Carbon GUI."
+msgstr "avec interface Carbon."
+
+#: version.c:875
+msgid "with Cocoa GUI."
+msgstr "avec interface Cocoa."
+
+#: version.c:878
+msgid "with (classic) GUI."
+msgstr "avec interface (classique)."
+
+#: version.c:889
+msgid " Features included (+) or not (-):\n"
+msgstr " Fonctionnalités incluses (+) ou non (-):\n"
+
+#: version.c:901
+msgid " system vimrc file: \""
+msgstr " fichier vimrc système: \""
+
+#: version.c:906
+msgid " user vimrc file: \""
+msgstr " fichier vimrc utilisateur: \""
+
+#: version.c:911
+msgid " 2nd user vimrc file: \""
+msgstr " 2me fichier vimrc utilisateur: \""
+
+#: version.c:916
+msgid " 3rd user vimrc file: \""
+msgstr " 3me fichier vimrc utilisateur: \""
+
+#: version.c:921
+msgid " user exrc file: \""
+msgstr " fichier exrc utilisateur: \""
+
+#: version.c:926
+msgid " 2nd user exrc file: \""
+msgstr " 2me fichier exrc utilisateur: \""
+
+#: version.c:932
+msgid " system gvimrc file: \""
+msgstr " fichier gvimrc système: \""
+
+#: version.c:936
+msgid " user gvimrc file: \""
+msgstr " fichier gvimrc utilisateur: \""
+
+#: version.c:940
+msgid "2nd user gvimrc file: \""
+msgstr "2me fichier gvimrc utilisateur: \""
+
+#: version.c:945
+msgid "3rd user gvimrc file: \""
+msgstr "3me fichier gvimrc utilisateur: \""
+
+#: version.c:952
+msgid " system menu file: \""
+msgstr " fichier menu système: \""
+
+#: version.c:960
+msgid " fall-back for $VIM: \""
+msgstr " $VIM par défaut: \""
+
+#: version.c:966
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " $VIMRUNTIME par défaut: \""
+
+#: version.c:970
+msgid "Compilation: "
+msgstr "Compilation: "
+
+#: version.c:976
+msgid "Compiler: "
+msgstr "Compilateur: "
+
+#: version.c:981
+msgid "Linking: "
+msgstr "Édition de liens: "
+
+#: version.c:986
+msgid " DEBUG BUILD"
+msgstr " VERSION DE DÉBOGAGE"
+
+#: version.c:1024
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi Amélioré"
+
+#: version.c:1026
+msgid "version "
+msgstr "version "
+
+#: version.c:1027
+msgid "by Bram Moolenaar et al."
+msgstr "par Bram Moolenaar et al."
+
+# todo
+#: version.c:1031
+msgid "Vim is open source and freely distributable"
+msgstr "Vim est un logiciel libre"
+
+#: version.c:1033
+msgid "Help poor children in Uganda!"
+msgstr "Aidez de pauvres enfants en Ouganda !"
+
+#: version.c:1034
+msgid "type :help iccf<Enter> for information "
+msgstr "tapez :help iccf<Entrée> pour plus d'informations"
+
+#: version.c:1036
+msgid "type :q<Enter> to exit "
+msgstr "tapez :q<Entrée> pour sortir du programme "
+
+#: version.c:1037
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "tapez :help<Entrée> ou <F1> pour accéder à l'aide en ligne "
+
+#: version.c:1038
+msgid "type :help version6<Enter> for version info"
+msgstr "tapez :help version6<Entrée> pour lire les notes de mise à jour"
+
+#: version.c:1041
+msgid "Running in Vi compatible mode"
+msgstr "Compatibilité Vi activée"
+
+#: version.c:1042
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "tapez :set nocp<Entrée> pour déf. de Vim"
+
+#: version.c:1043
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "tapez :help cp-default<Entrée> pour plus d'info"
+
+#: version.c:1058
+msgid "menu Help->Orphans for information "
+msgstr "menu Aide->Orphelins pour plus d'info"
+
+#: version.c:1060
+msgid "Running modeless, typed text is inserted"
+msgstr "Les modes sont désactivés, tout texte est inséré"
+
+# TODO
+#: version.c:1061
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "menu Edition->Réglages Globaux->Insertion Perm. "
+
+#: version.c:1062
+msgid " for two modes "
+msgstr " pour les modes "
+
+# TODO
+#: version.c:1066
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "menu Édition->Réglages Globaux->Compatibilité Vi"
+
+#: version.c:1067
+msgid " for Vim defaults "
+msgstr " pour déf. de Vim "
+
+#: version.c:1113
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "ALERTE: Windows 95/98/ME détecté"
+
+#: version.c:1116
+msgid "type :help windows95<Enter> for info on this"
+msgstr "tapez :help windows95<Entrée> pour plus d'information"
+
+#: window.c:204
+msgid "E441: There is no preview window"
+msgstr "E441: Il n'y a pas de fenêtre de prévisualisation"
+
+#: window.c:582
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: Ne peut séparer hautgauche et basdroite en même temps"
+
+# todo
+#: window.c:1341
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Rotation impossible quand des fenêtres sont séparées"
+
+#: window.c:1832
+msgid "E444: Cannot close last window"
+msgstr "E444: Fermeture de la dernière fenêtre impossible"
+
+#: window.c:2563
+msgid "Already only one window"
+msgstr "Il n'y a déjà plus qu'une fenêtre"
+
+# TODO
+#: window.c:2610
+msgid "E445: Other window contains changes"
+msgstr "E445: L'autre fenêtre n'a pas été enregistrée"
+
+#: window.c:4456
+msgid "E446: No file name under cursor"
+msgstr "E446: Pas de nom de fichier sous le curseur"
+
+# todo
+#: window.c:4575
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Le fichier \"%s\" n'est pas dans le chemin"
+
+#: globals.h:1208 if_perl.xs:363
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: Le chargement de la bibliothèque %s"
+
+#: if_perl.xs:591
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr "Désolé, commande désactivée: la bibliothèque Perl n'a pu être chargée."
+
+#: if_perl.xs:637
+msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+msgstr "E299: Évaluation Perl interdite dans bac à sable sans module Safe"
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "Édite dans &plusieurs Vims"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "Édite dans un seul &Vim"
+
+# todo
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "&Comparer dans Vim"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "Édite dans &Vim"
+
+#. Now concatenate
+#: GvimExt/gvimext.cpp:633
+msgid "Edit with existing Vim - &"
+msgstr "Éditer dans le Vim existant - &"
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "Éditer le(s) fichier(s) sélectionné(s) avec Vim"
+
+# todo
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "Erreur de création du processus: Vérifiez si gvim est bien dans votre chemin!"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "Erreur de gvimext.dll"
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "Le chemin est trop long !"
+
+# msgstr "--Pas de lignes dans le tampon--"
+#: globals.h:998
+msgid "--No lines in buffer--"
+msgstr "--Le tampon est vide--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1161
+msgid "E470: Command aborted"
+msgstr "E470: Commande annulée"
+
+#: globals.h:1162
+msgid "E471: Argument required"
+msgstr "E471: Argument requis"
+
+#: globals.h:1163
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ devrait être suivi de /, ? ou &"
+
+# todo
+#: globals.h:1165
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: Invalide dans la fenêtre ligne-de-commande; <CR> exécute, CTRL-C q"
+
+# TODO
+#: globals.h:1167
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr "E12: Cmde interdite à partir d'un exrc/vimrc dans rép. cour. ou tag search"
+
+#: globals.h:1169
+msgid "E171: Missing :endif"
+msgstr "E171: :endif manquant"
+
+#: globals.h:1170
+msgid "E600: Missing :endtry"
+msgstr "E600: :endtry manquant"
+
+#: globals.h:1171
+msgid "E170: Missing :endwhile"
+msgstr "E170: :endwhile manquant"
+
+#: globals.h:1172
+msgid "E588: :endwhile without :while"
+msgstr "E588: :endwhile sans :while"
+
+#: globals.h:1174
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Le fichier existe déjà (ajoutez ! pour passer outre)"
+
+#: globals.h:1175
+msgid "E472: Command failed"
+msgstr "E472: La commande a échoué"
+
+# todo
+#: globals.h:1177
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Fontset inconnu: %s"
+
+#: globals.h:1181
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Fonte inconnue: %s"
+
+# TODO
+#: globals.h:1184
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: La fonte \"%s\" n'a pas une largeur fixe"
+
+#: globals.h:1186
+msgid "E473: Internal error"
+msgstr "E473: Erreur interne"
+
+#: globals.h:1187
+msgid "Interrupted"
+msgstr "Interrompu"
+
+#: globals.h:1188
+msgid "E14: Invalid address"
+msgstr "E14: Adresse invalide"
+
+#: globals.h:1189
+msgid "E474: Invalid argument"
+msgstr "E474: Argument invalide"
+
+#: globals.h:1190
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: Argument invalide: %s"
+
+#: globals.h:1192
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Expression invalide: %s"
+
+# todo
+#: globals.h:1194
+msgid "E16: Invalid range"
+msgstr "E16: Domaine invalide"
+
+#: globals.h:1195
+msgid "E476: Invalid command"
+msgstr "E476: Commande invalide"
+
+#: globals.h:1197
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" est un répertoire"
+
+#: globals.h:1200
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Caractères inattendus avant '='"
+
+#: globals.h:1203
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: L'appel dans la bibliothèque a échoué pour \"%s()\""
+
+#: globals.h:1209
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: Pas pu charger la fonction %s de la bibliothèque"
+
+#: globals.h:1211
+msgid "E19: Mark has invalid line number"
+msgstr "E19: La marque a un numéro de ligne invalide"
+
+# todo
+#: globals.h:1212
+msgid "E20: Mark not set"
+msgstr "E20: Marque non positionnée"
+
+#: globals.h:1213
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Ne peut rien changer, 'modifiable' est désactivé"
+
+#: globals.h:1214
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Niveau de récursion trop élevé dans les scripts"
+
+# todo
+#: globals.h:1215
+msgid "E23: No alternate file"
+msgstr "E23: Pas de fichier alternatif"
+
+#: globals.h:1216
+msgid "E24: No such abbreviation"
+msgstr "E24: Pas de telle abréviation"
+
+#: globals.h:1217
+msgid "E477: No ! allowed"
+msgstr "E477: Le ! n'est pas autorisé"
+
+#: globals.h:1219
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: L'interface graphique n'a pas été compilée dans cette version"
+
+#: globals.h:1222
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: Le support de l'hébreu n'a pas été compilé dans cette version\n"
+
+#: globals.h:1225
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: Le support du farsi n'a pas été compilé dans cette version\n"
+
+#: globals.h:1228
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: Le support de l'arabique n'a pas été compilé dans cette version\n"
+
+# todo
+#: globals.h:1231
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Pas de tel nom de groupe de surlignage: %s"
+
+#: globals.h:1233
+msgid "E29: No inserted text yet"
+msgstr "E29: Pas encore de texte inséré"
+
+#: globals.h:1234
+msgid "E30: No previous command line"
+msgstr "E30: Pas de ligne de commande précédente"
+
+# todo
+#: globals.h:1235
+msgid "E31: No such mapping"
+msgstr "E31: Pas de tel mapping"
+
+#: globals.h:1236
+msgid "E479: No match"
+msgstr "E479: Pas de correspondance"
+
+#: globals.h:1237
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: Pas de correspondance: %s"
+
+#: globals.h:1238
+msgid "E32: No file name"
+msgstr "E32: Pas de nom de fichier"
+
+# todo
+#: globals.h:1239
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: Pas d'expression régulière de substitution précédente"
+
+#: globals.h:1240
+msgid "E34: No previous command"
+msgstr "E34: Pas de commande précédente"
+
+#: globals.h:1241
+msgid "E35: No previous regular expression"
+msgstr "E35: Pas d'expression régulière précédente"
+
+#: globals.h:1242
+msgid "E481: No range allowed"
+msgstr "E481: Les domaines ne sont pas autorisés"
+
+#: globals.h:1244
+msgid "E36: Not enough room"
+msgstr "E36: Pas assez de place"
+
+#: globals.h:1247
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: pas de serveur nommé \"%s\" inscrit"
+
+#: globals.h:1249
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: Ne peut créer le fichier %s"
+
+#: globals.h:1250
+msgid "E483: Can't get temp file name"
+msgstr "E483: Ne peut obtenir de nom de fichier temporaire"
+
+#: globals.h:1251
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: Impossible d'ouvrir le fichier \"%s\""
+
+#: globals.h:1252
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: Impossible de lire le fichier %s"
+
+#: globals.h:1253
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: Modifications non enregistrées (ajoutez ! pour passer outre)"
+
+#: globals.h:1254
+msgid "E38: Null argument"
+msgstr "E38: Argument nul"
+
+#: globals.h:1256
+msgid "E39: Number expected"
+msgstr "E39: Nombre attendu"
+
+#: globals.h:1259
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Ne peut ouvrir le fichier d'erreurs %s"
+
+# TODO
+#: globals.h:1262
+msgid "E233: cannot open display"
+msgstr "E233: ouverture de l'affichage impossible"
+
+#: globals.h:1264
+msgid "E41: Out of memory!"
+msgstr "E41: Mémoire épuisée"
+
+#: globals.h:1266
+msgid "Pattern not found"
+msgstr "Motif introuvable"
+
+#: globals.h:1268
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: Motif introuvable: %s"
+
+#: globals.h:1269
+msgid "E487: Argument must be positive"
+msgstr "E487: L'argument doit être positif"
+
+#: globals.h:1271
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: Impossible de retourner au répertoire précédent"
+
+#: globals.h:1275
+msgid "E42: No Errors"
+msgstr "E42: Pas d'erreurs"
+
+#: globals.h:1277
+msgid "E43: Damaged match string"
+msgstr "E43: Le texte de la recherche est endommagé"
+
+#: globals.h:1278
+msgid "E44: Corrupted regexp program"
+msgstr "E44: Le programme regexp est corrompu"
+
+#: globals.h:1279
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: L'option 'readonly' est activée (ajoutez ! pour passer outre)"
+
+#: globals.h:1281
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: La variable \"%s\" est en lecture seule"
+
+#: globals.h:1284
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Erreur lors de la lecture du fichier d'erreurs"
+
+#: globals.h:1287
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: Opération interdite dans le bac à sable"
+
+#: globals.h:1289
+msgid "E523: Not allowed here"
+msgstr "E523: Interdit à cet endroit"
+
+# todo
+#: globals.h:1292
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Choix du mode d'écran non supporté"
+
+#: globals.h:1294
+msgid "E49: Invalid scroll size"
+msgstr "E49: L'ampleur du défilement est invalide"
+
+#: globals.h:1295
+msgid "E91: 'shell' option is empty"
+msgstr "E91: L'option 'shell' est vide"
+
+# todo
+#: globals.h:1297
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Pas pu lire les données du symbole!"
+
+#: globals.h:1299
+msgid "E72: Close error on swap file"
+msgstr "E72: Erreur lors de la fermeture du fichier d'échange"
+
+#: globals.h:1300
+msgid "E73: tag stack empty"
+msgstr "E73: La pile des étiquettes est vide"
+
+#: globals.h:1301
+msgid "E74: Command too complex"
+msgstr "E74: Commande trop complexe"
+
+#: globals.h:1302
+msgid "E75: Name too long"
+msgstr "E75: Nom trop long"
+
+#: globals.h:1303
+msgid "E76: Too many ["
+msgstr "E76: Trop de ["
+
+#: globals.h:1304
+msgid "E77: Too many file names"
+msgstr "E77: Trop de noms de fichiers"
+
+#: globals.h:1305
+msgid "E488: Trailing characters"
+msgstr "E488: Caractères surnuméraires"
+
+#: globals.h:1306
+msgid "E78: Unknown mark"
+msgstr "E78: Marque inconnue"
+
+#: globals.h:1307
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Impossible de développer les métacaractères"
+
+#: globals.h:1309
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: 'winheight' ne peut être plus petit que 'winminheight'"
+
+#: globals.h:1311
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: 'winwidth' ne peut être plus petit que 'winminwidth'"
+
+#: globals.h:1314
+msgid "E80: Error while writing"
+msgstr "E80: Erreur lors de l'écriture"
+
+# todo
+#: globals.h:1315
+msgid "Zero count"
+msgstr "Le compte vaut zéro"
+
+#: globals.h:1317
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: <SID> utilisé en dehors d'un script"
+
+# todo
+#: globals.h:1320
+msgid "E449: Invalid expression received"
+msgstr "E449: Expression invalide reçue"
+
+# todo
+#: globals.h:1323
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: Cette zone est verrouillée et ne peut être modifiée"
+
+#~ msgid "error reading cscope connection %d"
+#~ msgstr "erreur lors de la lecture de la connection cscope %d"
+
+#~ msgid "E260: cscope connection not found"
+#~ msgstr "E260: la connection cscope n'a pas été trouvée"
+
+#~ msgid "cscope connection closed"
+#~ msgstr "La connection cscope est fermée"
+
+#~ msgid "couldn't malloc\n"
+#~ msgstr "malloc a échoué\n"
+
+#~ msgid "%2d %-5ld %-34s <none>\n"
+#~ msgstr "%2d %-5ld %-34s <aucun>\n"
+
+#~ msgid "E448: Unknown font: %s"
+#~ msgstr "E448: Fonte inconnue: %s"
+
+#~ msgid "Linear tag search"
+#~ msgstr "Recherche linéaire d'étiquette"
+
+#~ msgid "Binary tag search"
+#~ msgstr "Recherche binaire d'étiquette"
+
+#~ msgid "Can't open file %s"
+#~ msgstr "Ne peut ouvrir le fichier %s"
+
+#~ msgid "E249: couldn't read VIM instance registry property"
+#~ msgstr "E249: Pas pu lire entrée registre de l'instance de Vim"
diff --git a/src/po/it.po b/src/po/it.po
new file mode 100644
index 000000000..cc966fadd
--- /dev/null
+++ b/src/po/it.po
@@ -0,0 +1,6638 @@
+# Italian Translation for Vim
+#
+# FIRST AUTHOR Antonio Colombo <antonio.colombo@jrc.it>, 2000
+#
+# Ogni commento è benvenuto...
+# Every remark is very welcome...
+#
+# Translation done under Linux and using an Italian keyboard.
+# English words left in the text are unmodified at plural.
+# Option names are mostly left untouched.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: vim 6.3\n"
+"POT-Creation-Date: 2004-06-02 20:02+0200\n"
+"PO-Revision-Date: 2004-06-02 20:02+0200\n"
+"Last-Translator: Vlad Sandrini <marco@sandrini.biz>\n"
+"Language-Team: Italian"
+" Antonio Colombo <antonio.colombo@jrc.it>\n"
+" Vlad Sandrini <marco@sandrini.biz>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO_8859-1\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: buffer.c:102
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Non riesco ad allocare alcun buffer, esco..."
+
+#: buffer.c:105
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: Non riesco ad allocare un buffer, uso l'altro..."
+
+#: buffer.c:808
+msgid "E515: No buffers were unloaded"
+msgstr "E515: Nessun buffer scaricato"
+
+#: buffer.c:810
+msgid "E516: No buffers were deleted"
+msgstr "E516: Nessun buffer tolto dalla lista"
+
+#: buffer.c:812
+msgid "E517: No buffers were wiped out"
+msgstr "E517: Nessun buffer cancellato"
+
+#: buffer.c:820
+msgid "1 buffer unloaded"
+msgstr "1 buffer scaricato"
+
+#: buffer.c:822
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "%d buffer scaricati"
+
+#: buffer.c:827
+msgid "1 buffer deleted"
+msgstr "1 buffer tolto dalla lista"
+
+#: buffer.c:829
+#, c-format
+msgid "%d buffers deleted"
+msgstr "%d buffer tolti dalla lista"
+
+#: buffer.c:834
+msgid "1 buffer wiped out"
+msgstr "1 buffer cancellato"
+
+#: buffer.c:836
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "%d buffer cancellati"
+
+#: buffer.c:897
+msgid "E84: No modified buffer found"
+msgstr "E84: Nessun buffer risulta modificato"
+
+#. back where we started, didn't find anything.
+#: buffer.c:936
+msgid "E85: There is no listed buffer"
+msgstr "E85: Non c'è alcun buffer elencato"
+
+#: buffer.c:948
+#, c-format
+msgid "E86: Buffer %ld does not exist"
+msgstr "E86: Non esiste il buffer %ld"
+
+#: buffer.c:951
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Non posso oltrepassare l'ultimo buffer"
+
+#: buffer.c:953
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Non posso andare prima del primo buffer"
+
+#: buffer.c:991
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr ""
+"E89: Buffer %ld non salvato dopo modifica (aggiungi ! per eseguire comunque)"
+
+#: buffer.c:1008
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: Non riesco a scaricare l'ultimo buffer"
+
+#: buffer.c:1544
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Attenzione: Superato limite della lista dei nomi di file"
+
+#: buffer.c:1716
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: Buffer %ld non trovato"
+
+#: buffer.c:1947
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Più di una corrispondenza per %s"
+
+#: buffer.c:1949
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: Nessun buffer corrispondente a %s"
+
+#: buffer.c:2344
+#, c-format
+msgid "line %ld"
+msgstr "linea %ld"
+
+#: buffer.c:2429
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: C'è già un buffer con questo nome"
+
+#: buffer.c:2724
+msgid " [Modified]"
+msgstr " [Modificato]"
+
+#: buffer.c:2729
+msgid "[Not edited]"
+msgstr "[Non elaborato]"
+
+#: buffer.c:2734
+msgid "[New file]"
+msgstr "[File nuovo]"
+
+#: buffer.c:2735
+msgid "[Read errors]"
+msgstr "[Errori in lettura]"
+
+#: buffer.c:2737 fileio.c:2124
+msgid "[readonly]"
+msgstr "[in sola lettura]"
+
+#: buffer.c:2758
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 linea --%d%%--"
+
+#: buffer.c:2760
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld linee --%d%%--"
+
+#: buffer.c:2767
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "linea %ld di %ld --%d%%-- col "
+
+#: buffer.c:2875
+msgid "[No file]"
+msgstr "[Senza nome]"
+
+#. must be a help buffer
+#: buffer.c:2915
+msgid "help"
+msgstr "aiuto"
+
+#: buffer.c:3474 screen.c:5075
+msgid "[help]"
+msgstr "[aiuto]"
+
+#: buffer.c:3506 screen.c:5081
+msgid "[Preview]"
+msgstr "[Anteprima]"
+
+#: buffer.c:3786
+msgid "All"
+msgstr "Tut"
+
+#: buffer.c:3786
+msgid "Bot"
+msgstr "Fon"
+
+#: buffer.c:3788
+msgid "Top"
+msgstr "Cim"
+
+#: buffer.c:4536
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# Lista Buffer:\n"
+
+#: buffer.c:4569
+msgid "[Error List]"
+msgstr "[Lista Errori]"
+
+#: buffer.c:4582 memline.c:1521
+msgid "[No File]"
+msgstr "[Senza nome]"
+
+#: buffer.c:4895
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Segni ---"
+
+#: buffer.c:4914
+#, c-format
+msgid "Signs for %s:"
+msgstr "Segni per %s:"
+
+#: buffer.c:4920
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " linea=%ld id=%d, nome=%s"
+
+#: diff.c:139
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: Non supporto differenze fra più di %ld buffer"
+
+#: diff.c:713
+msgid "E97: Cannot create diffs"
+msgstr "E97: Non riesco a creare differenze "
+
+#: diff.c:818
+msgid "Patch file"
+msgstr "File di differenze"
+
+#: diff.c:1069
+msgid "E98: Cannot read diff output"
+msgstr "E98: Non riesco a leggere output del comando 'diff'"
+
+#: diff.c:1819
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Buffer corrente non in modalità 'diff'"
+
+#: diff.c:1831
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: Non c'è nessun altro buffer in modalità 'diff'"
+
+#: diff.c:1839
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: Più di due buffer in modalità 'diff', non so quale usare"
+
+#: diff.c:1862
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Non riesco a trovare il buffer: \"%s\""
+
+#: diff.c:1868
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Il buffer \"%s\" non è in modalità 'diff'"
+
+#: digraph.c:2199
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: Escape not ammesso nei digrammi"
+
+#: digraph.c:2384
+msgid "E544: Keymap file not found"
+msgstr "E544: File keymap non trovato"
+
+#: digraph.c:2411
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: Uso di :loadkeymap fuori da un file di comandi"
+
+#: edit.c:40
+msgid " Keyword completion (^N^P)"
+msgstr " Completamento Keyword (^N^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E^Y^L^]^F^I^K^D^V^N^P)"
+msgstr " modalità ^X (^E^Y^L^]^F^I^K^D^V^N^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N^P)"
+msgstr " Completamento Keyword Locale (^N^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L^N^P)"
+msgstr " Completamento Linea Intera (^L^N^P)"
+
+#: edit.c:46
+msgid " File name completion (^F^N^P)"
+msgstr " Completamento nomi File (^F^N^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]^N^P)"
+msgstr " Completamento Tag (^]^N^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N^P)"
+msgstr " Completamento modello Path (^N^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D^N^P)"
+msgstr " Completamento Definizione (^D^N^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K^N^P)"
+msgstr " Completamento Dizionario (^K^N^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T^N^P)"
+msgstr " Completamento Thesaurus (^T^N^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V^N^P)"
+msgstr " Completamento linea comandi (^V^N^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Giunto alla fine del paragrafo"
+
+#: edit.c:962
+msgid "'thesaurus' option is empty"
+msgstr "l'opzione 'thesaurus' è vuota"
+
+#: edit.c:1166
+msgid "'dictionary' option is empty"
+msgstr "l'opzione 'dictionary' è vuota"
+
+#: edit.c:2162
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Scansione dizionario: %s"
+
+#: edit.c:2368
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (inserisci) Scroll (^E/^Y)"
+
+#: edit.c:2370
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (sostituisci) Scroll (^E/^Y)"
+
+#: edit.c:2684
+#, c-format
+msgid "Scanning: %s"
+msgstr "Scansione: %s"
+
+#: edit.c:2719
+msgid "Scanning tags."
+msgstr "Scansione tag."
+
+#: edit.c:3381
+msgid " Adding"
+msgstr " Aggiungo"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3430
+msgid "-- Searching..."
+msgstr "-- Ricerca..."
+
+#: edit.c:3486
+msgid "Back at original"
+msgstr "Ritorno all'originale"
+
+#: edit.c:3491
+msgid "Word from other line"
+msgstr "Parola da un'altra linea"
+
+#: edit.c:3496
+msgid "The only match"
+msgstr "L'unica corrispondenza"
+
+#: edit.c:3555
+#, c-format
+msgid "match %d of %d"
+msgstr "corrispondenza %d di %d"
+
+#: edit.c:3558
+#, c-format
+msgid "match %d"
+msgstr "corripondenza %d"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:1024
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Variabile inesistente: \"%s\""
+
+#: eval.c:1320
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Mancano graffe: %s"
+
+#: eval.c:1435 eval.c:1449
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Variabile inesistente: \"%s\""
+
+#: eval.c:1705
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Manca ':' dopo '?'"
+
+#: eval.c:2327
+msgid "E110: Missing ')'"
+msgstr "E110: Manca ')'"
+
+#: eval.c:2389
+msgid "E111: Missing ']'"
+msgstr "E111: Manca ']'"
+
+#: eval.c:2466
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Nome Opzione mancante: %s"
+
+#: eval.c:2484
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Opzione inesistente: %s"
+
+#: eval.c:2555
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Manca '\"': %s"
+
+#: eval.c:2698
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Manca apostrofo: %s"
+
+#: eval.c:3054
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Argomento non valido per la funzione %s"
+
+#: eval.c:3083
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Funzione inesistente: %s"
+
+#: eval.c:3084
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: Troppi argomenti per la funzione: %s"
+
+#: eval.c:3085
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Argomenti insufficienti per la funzione: %s"
+
+#: eval.c:3086
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: Uso di <SID> fuori dal contesto di uno script: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3687 gui.c:4382 gui_gtk.c:2059
+msgid "&Ok"
+msgstr "&OK"
+
+#: eval.c:4226
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld linee: "
+
+#: eval.c:5477
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&OK\n"
+"&Non eseguire"
+
+#: eval.c:5517
+msgid "called inputrestore() more often than inputsave()"
+msgstr "inputrestore() chiamata più volte di inputsave()"
+
+#: eval.c:5977
+msgid "E655: Too many symbolic links (cycle?)"
+msgstr "E655: Troppi link simbolici (circolarità?)"
+
+#: eval.c:6626
+msgid "E240: No connection to Vim server"
+msgstr "E240: Manca connessione con server Vim"
+
+#: eval.c:6724
+msgid "E277: Unable to read a server reply"
+msgstr "E277: Non riesco a leggere una risposta del server"
+
+#: eval.c:6752
+msgid "E258: Unable to send to client"
+msgstr "E258: Impossibile inviare al client"
+
+#: eval.c:6800
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Impossibile inviare a %s"
+
+#: eval.c:6900
+msgid "(Invalid)"
+msgstr "(Non valido)"
+
+#: eval.c:8078
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Variabile non definita: %s"
+
+#: eval.c:8510
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E461: Nome di variabile non ammesso: %s"
+
+#: eval.c:8802
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: La funzione %s esiste già, aggiungi ! per sostituirla"
+
+#: eval.c:8875
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Funzione non definita: %s"
+
+#: eval.c:8888
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Manca '(': %s"
+
+#: eval.c:8921
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Argomento non ammesso: %s"
+
+#: eval.c:9000
+msgid "E126: Missing :endfunction"
+msgstr "E126: Manca :endfunction"
+
+#: eval.c:9107
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Non posso ridefinire la funzione %s: E' in uso"
+
+#: eval.c:9177
+msgid "E129: Function name required"
+msgstr "E129: Nome funzione necessario"
+
+#: eval.c:9228
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: Il nome funzione deve iniziare con una lettera maiuscola: %s"
+
+#: eval.c:9420
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Funzione non definita: %s"
+
+#: eval.c:9425
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Non posso eliminare la funzione %s: E' in uso"
+
+#: eval.c:9473
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr ""
+"E132: Nidificazione della chiamata di funzione maggiore di 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:9526
+#, c-format
+msgid "calling %s"
+msgstr "chiamo %s"
+
+#: eval.c:9588
+#, c-format
+msgid "%s aborted"
+msgstr "%s non completata"
+
+#: eval.c:9590
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s ritorno #%ld"
+
+#: eval.c:9597
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s ritorno \"%s\""
+
+#. always scroll up, don't overwrite
+#: eval.c:9613 ex_cmds2.c:2370
+#, c-format
+msgid "continuing in %s"
+msgstr "continuo in %s"
+
+#: eval.c:9639
+msgid "E133: :return not inside a function"
+msgstr "E133: :return fuori da una funzione"
+
+#: eval.c:9970
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# variabili globali:\n"
+
+#: ex_cmds2.c:92
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "Entro modalità Debug. Batti \"cont\" per continuare."
+
+#: ex_cmds2.c:96 ex_docmd.c:968
+#, c-format
+msgid "line %ld: %s"
+msgstr "linea %ld: %s"
+
+#: ex_cmds2.c:98
+#, c-format
+msgid "cmd: %s"
+msgstr "com: %s"
+
+#: ex_cmds2.c:290
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Pausa in \"%s%s\" linea %ld"
+
+#: ex_cmds2.c:540
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Breakpoint %s non trovato"
+
+#: ex_cmds2.c:566
+msgid "No breakpoints defined"
+msgstr "Nessun 'breakpoint' definito"
+
+#: ex_cmds2.c:571
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s linea %ld"
+
+#: ex_cmds2.c:761 ex_cmds.c:2097
+msgid "Save As"
+msgstr "Salva con Nome"
+
+#: ex_cmds2.c:786
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Salvare modifiche a \"%.*s\"?"
+
+#: ex_cmds2.c:788 ex_docmd.c:9398
+msgid "Untitled"
+msgstr "Senza Nome"
+
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Buffer \"%s\" non salvato dopo modifica"
+
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr ""
+"Attenzione: Entrato in altro buffer inaspettatamente (controllare "
+"autocomandi)"
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: C'è un solo file da elaborare"
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: Non posso andare davanti al primo file"
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Non posso oltrepassare l'ultimo file"
+
+#: ex_cmds2.c:1804
+#, c-format
+msgid "E666: compiler not supported: %s"
+msgstr "E666: compilatore non supportato: %s"
+
+#: ex_cmds2.c:1901
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Cerco \"%s\" in \"%s\""
+
+#: ex_cmds2.c:1923
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Cerco \"%s\""
+
+#: ex_cmds2.c:1945
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "non trovato in 'runtimepath': \"%s\""
+
+#: ex_cmds2.c:1979
+msgid "Source Vim script"
+msgstr "Esegui script Vim"
+
+#: ex_cmds2.c:2169
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "Non riesco ad eseguire una directory: \"%s\""
+
+#: ex_cmds2.c:2207
+#, c-format
+msgid "could not source \"%s\""
+msgstr "non riesco ad eseguire \"%s\""
+
+#: ex_cmds2.c:2209
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "linea %ld: non riesco ad eseguire \"%s\""
+
+#: ex_cmds2.c:2223
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "eseguo \"%s\""
+
+#: ex_cmds2.c:2225
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "linea %ld: eseguo \"%s\""
+
+#: ex_cmds2.c:2368
+#, c-format
+msgid "finished sourcing %s"
+msgstr "esecuzione di %s terminata"
+
+#: ex_cmds2.c:2712
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Attenzione: Separatore di linea errato, forse manca ^M"
+
+#: ex_cmds2.c:2761
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :scriptencoding usato fuori da un file di comandi"
+
+#: ex_cmds2.c:2794
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish usato fuori da file di comandi"
+
+#: ex_cmds2.c:3243
+#, c-format
+msgid "Page %d"
+msgstr "Pagina %d"
+
+#: ex_cmds2.c:3399
+msgid "No text to be printed"
+msgstr "Manca testo da stampare"
+
+#: ex_cmds2.c:3477
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "Sto stampando pagina %d (%d%%)"
+
+#: ex_cmds2.c:3489
+#, c-format
+msgid " Copy %d of %d"
+msgstr " Copia %d di %d"
+
+#: ex_cmds2.c:3547
+#, c-format
+msgid "Printed: %s"
+msgstr "Stampato: %s"
+
+#: ex_cmds2.c:3554
+msgid "Printing aborted"
+msgstr "Stampa non completata'"
+
+#: ex_cmds2.c:3919
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Errore in scrittura a file PostScript di output"
+
+#: ex_cmds2.c:4194
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E624: Non riesco ad aprire il file \"%s\""
+
+#: ex_cmds2.c:4204 ex_cmds2.c:4829
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Non riesco a leggere file risorse PostScript \"%s\""
+
+#: ex_cmds2.c:4212
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: file \"%s\" non è un file di risorse PostScript"
+
+#: ex_cmds2.c:4227 ex_cmds2.c:4247 ex_cmds2.c:4262 ex_cmds2.c:4284
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: file \"%s\" non è un file di risorse PostScript supportato"
+
+#: ex_cmds2.c:4314
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: il file di risorse \"%s\" ha una versione sbagliata"
+
+#: ex_cmds2.c:4781
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Non riesco ad aprire file PostScript di output"
+
+#: ex_cmds2.c:4814
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Non riesco ad aprire il file \"%s\""
+
+#: ex_cmds2.c:4933
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr "E456: Non trovo file risorse PostScript \"prolog.ps\""
+
+#: ex_cmds2.c:4964
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: Non trovo file risorse PostScript \"%s.ps\""
+
+#: ex_cmds2.c:4982
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr "E620: Impossibile convertire da multi-byte a codifica \"%s\""
+
+#: ex_cmds2.c:5107
+msgid "Sending to printer..."
+msgstr "Invio a stampante..."
+
+#: ex_cmds2.c:5111
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: Non riesco ad aprire file PostScript"
+
+#: ex_cmds2.c:5113
+msgid "Print job sent."
+msgstr "Richiesta di stampa inviata."
+
+#: ex_cmds2.c:5623
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Lingua %sin uso: \"%s\""
+
+#: ex_cmds2.c:5634
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Non posso impostare lingua a \"%s\""
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Esa %02x, Ottale %03o"
+
+#: ex_cmds.c:118
+#, c-format
+msgid "> %d, Hex %04x, Octal %o"
+msgstr "> %d, Esa %04x, Ottale %o"
+
+#: ex_cmds.c:119
+#, c-format
+msgid "> %d, Hex %08x, Octal %o"
+msgstr "> %d, Esa %08x, Ottale %o"
+
+#: ex_cmds.c:430
+msgid "E134: Move lines into themselves"
+msgstr "E134: Movimento di linee verso se stesse"
+
+#: ex_cmds.c:499
+msgid "1 line moved"
+msgstr "1 linea mossa"
+
+#: ex_cmds.c:501
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld linee mosse"
+
+#: ex_cmds.c:924
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld linee filtrate"
+
+#: ex_cmds.c:952
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *Filter* Gli autocomandi non devono modificare il buffer in uso"
+
+#: ex_cmds.c:1037
+msgid "[No write since last change]\n"
+msgstr "[Non salvato dopo l'ultima modifica]\n"
+
+#: ex_cmds.c:1283
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s nella linea: "
+
+#: ex_cmds.c:1288
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: Troppi errori, ignoro il resto del file"
+
+#: ex_cmds.c:1323
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Lettura file viminfo \"%s\"%s%s%s"
+
+#: ex_cmds.c:1324
+msgid " info"
+msgstr " informazione"
+
+#: ex_cmds.c:1325
+msgid " marks"
+msgstr " mark"
+
+#: ex_cmds.c:1326
+msgid " FAILED"
+msgstr " FALLITO"
+
+#: ex_cmds.c:1418
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: File viminfo \"%s\" inaccessibile in scrittura"
+
+#: ex_cmds.c:1543
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Non riesco a scrivere il file viminfo %s!"
+
+#: ex_cmds.c:1551
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Scrivo file viminfo \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1649
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Questo file viminfo è stato generato da Vim %s.\n"
+
+#: ex_cmds.c:1651
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# File modificabile, attento a quel che fai!\n"
+"\n"
+
+#: ex_cmds.c:1653
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Valore di 'encoding' al momento della scrittura di questo file\n"
+
+#: ex_cmds.c:1752
+msgid "Illegal starting char"
+msgstr "Carattere iniziale non ammesso"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2140
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: File già caricato in un altro buffer"
+
+#: ex_cmds.c:2174
+msgid "Write partial file?"
+msgstr "Scrivo il file incompleto?"
+
+#: ex_cmds.c:2181
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Usa ! per scrivere il buffer incompleto"
+
+#: ex_cmds.c:2296
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Riscrittura del file esistente \"%.*s\"?"
+
+#: ex_cmds.c:2367
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: Manca nome file per il buffer %ld"
+
+#: ex_cmds.c:2406
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: File non scritto: Scrittura inibita da opzione 'write'"
+
+#: ex_cmds.c:2426
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"opzione 'readonly' attiva per \"%.*s\".\n"
+"Vuoi scrivere comunque?"
+
+#: ex_cmds.c:2599
+msgid "Edit File"
+msgstr "Elabora File"
+
+#: ex_cmds.c:3207
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr ""
+"E143: Gli autocomandi hanno inaspettatamente cancellato il nuovo buffer %s"
+
+#: ex_cmds.c:3341
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: argomento non-numerico a :z"
+
+#: ex_cmds.c:3426
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: Comandi Shell non permessi in rvim"
+
+#: ex_cmds.c:3533
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Le espressioni regolari non possono essere delimitate da lettere"
+
+#: ex_cmds.c:3879
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "sostituire con %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4272
+msgid "(Interrupted) "
+msgstr "(Interrotto) "
+
+#: ex_cmds.c:4276
+msgid "1 substitution"
+msgstr "1 sostituzione"
+
+#: ex_cmds.c:4278
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld sostituzioni"
+
+#: ex_cmds.c:4281
+msgid " on 1 line"
+msgstr " in 1 linea"
+
+#: ex_cmds.c:4283
+#, c-format
+msgid " on %ld lines"
+msgstr " in %ld linee"
+
+#: ex_cmds.c:4334
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :global non può essere usato ricorsivamente"
+
+#: ex_cmds.c:4369
+msgid "E148: Regular expression missing from global"
+msgstr "E148: Manca espressione regolare nel comando 'global'"
+
+#: ex_cmds.c:4418
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Espressione trovata su ogni linea: %s"
+
+#: ex_cmds.c:4499
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Ultima Stringa Sostituzione:\n"
+"$"
+
+#: ex_cmds.c:4600
+msgid "E478: Don't panic!"
+msgstr "E478: Non lasciarti prendere dal panico!"
+
+#: ex_cmds.c:4652
+#, c-format
+msgid "E661: Sorry, no '%s' help for %s"
+msgstr "E661: Spiacente, nessun aiuto '%s' per %s"
+
+#: ex_cmds.c:4655
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Spiacente, nessun aiuto per %s"
+
+#: ex_cmds.c:4689
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Spiacente, non trovo file di aiuto \"%s\""
+
+#: ex_cmds.c:5192
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s non è una directory"
+
+#: ex_cmds.c:5331
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: Non posso aprire %s in scrittura"
+
+#: ex_cmds.c:5367
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Non riesco ad aprire %s in lettura"
+
+#: ex_cmds.c:5389
+#, c-format
+msgid "E670: Mix of help file encodings within a language: %s"
+msgstr "E670: Codifiche diverse fra file di aiuto nella stessa lingua: %s"
+
+#: ex_cmds.c:5467
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: Tag duplicata \"%s\" nel file %s"
+
+#: ex_cmds.c:5579
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Comando 'sign' sconosciuto: %s"
+
+#: ex_cmds.c:5599
+msgid "E156: Missing sign name"
+msgstr "E156: Manca nome 'sign'"
+
+#: ex_cmds.c:5645
+msgid "E612: Too many signs defined"
+msgstr "E612: Troppi 'sign' definiti"
+
+#: ex_cmds.c:5713
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Testo 'sign' non valido: %s"
+
+#: ex_cmds.c:5744 ex_cmds.c:5935
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: 'sign' sconosciuto: %s"
+
+#: ex_cmds.c:5793
+msgid "E159: Missing sign number"
+msgstr "E159: Manca numero 'sign'"
+
+#: ex_cmds.c:5875
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: Nome buffer non valido: %s"
+
+#: ex_cmds.c:5914
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: ID 'sign' non valido: %ld"
+
+#: ex_cmds.c:5984
+msgid " (NOT FOUND)"
+msgstr " (NON TROVATO)"
+
+#: ex_cmds.c:5986
+msgid " (not supported)"
+msgstr " (non supportata)"
+
+#: ex_cmds.c:6085
+msgid "[Deleted]"
+msgstr "[Cancellato]"
+
+#: ex_docmd.c:525
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Entro modalità Ex. Batti \"visual\" per tornare a modalità Normale."
+
+#. must be at EOF
+#: ex_docmd.c:561
+msgid "E501: At end-of-file"
+msgstr "E501: Alla fine-file"
+
+#: ex_docmd.c:670
+msgid "E169: Command too recursive"
+msgstr "E169: Comando troppo ricorsivo"
+
+#: ex_docmd.c:1232
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: Eccezione non intercettata: %s"
+
+#: ex_docmd.c:1320
+msgid "End of sourced file"
+msgstr "Fine del file di comandi"
+
+#: ex_docmd.c:1321
+msgid "End of function"
+msgstr "Fine funzione "
+
+#: ex_docmd.c:1910
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: Uso ambiguo di comando definito dall'utente"
+
+#: ex_docmd.c:1924
+msgid "E492: Not an editor command"
+msgstr "E492: Non è un comando dell'editor"
+
+#: ex_docmd.c:2031
+msgid "E493: Backwards range given"
+msgstr "E493: Intervallo rovesciato"
+
+#: ex_docmd.c:2040
+msgid "Backwards range given, OK to swap"
+msgstr "Intervallo rovesciato, OK invertirlo"
+
+#: ex_docmd.c:2163
+msgid "E494: Use w or w>>"
+msgstr "E494: Usa w oppure w>>"
+
+#: ex_docmd.c:3789
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Spiacente, comando non disponibile in questa versione"
+
+#: ex_docmd.c:3992
+msgid "E172: Only one file name allowed"
+msgstr "E172: Ammesso un solo nome file"
+
+#: ex_docmd.c:4572
+msgid "1 more file to edit. Quit anyway?"
+msgstr "1 ulteriore file da elaborare. Esco lo stesso?"
+
+#: ex_docmd.c:4575
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "%d ulteriori file da elaborare. Esco lo stesso?"
+
+#: ex_docmd.c:4582
+msgid "E173: 1 more file to edit"
+msgstr "E173: ancora 1 file da elaborare"
+
+#: ex_docmd.c:4584
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: ancora %ld file da elaborare"
+
+#: ex_docmd.c:4679
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: Il comando esiste già: aggiungi ! per sostituirlo"
+
+#: ex_docmd.c:4790
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Nome Arg. Inter Completo Definizione"
+
+#: ex_docmd.c:4879
+msgid "No user-defined commands found"
+msgstr "Non trovo comandi definiti dall'utente"
+
+#: ex_docmd.c:4911
+msgid "E175: No attribute specified"
+msgstr "E175: Nessun attributo specificato"
+
+#: ex_docmd.c:4963
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Numero di argomenti non valido"
+
+#: ex_docmd.c:4978
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: Non si può specificare due volte il contatore"
+
+#: ex_docmd.c:4988
+msgid "E178: Invalid default value for count"
+msgstr "E178: Valore predefinito del contatore non valido"
+
+#: ex_docmd.c:5019
+msgid "E179: argument required for complete"
+msgstr "E179: argomento necessario per complete"
+
+#: ex_docmd.c:5051
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Valore %s non valido per 'complete'"
+
+#: ex_docmd.c:5060
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr ""
+"E468: Argomento di completamento permesso solo per completamento "
+"personalizzato"
+
+#: ex_docmd.c:5066
+msgid "E467: Custom completion requires a function argument"
+msgstr ""
+"E467: Il completamento personalizzato richiede un argomento di funzione"
+
+#: ex_docmd.c:5077
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Attributo non valido: %s"
+
+#: ex_docmd.c:5120
+msgid "E182: Invalid command name"
+msgstr "E182: Nome comando non valido"
+
+#: ex_docmd.c:5135
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr ""
+"E183 I comandi definiti dall'utente devono iniziare con lettera maiuscola"
+
+#: ex_docmd.c:5206
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: Comando definito dall'utente %s inesistente"
+
+#: ex_docmd.c:5667
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Non riesco a trovare schema colore %s"
+
+#: ex_docmd.c:5675
+msgid "Greetings, Vim user!"
+msgstr "Salve, utente Vim!"
+
+#: ex_docmd.c:6393
+msgid "Edit File in new window"
+msgstr "Apri il File in una nuova finestra"
+
+#: ex_docmd.c:6688
+msgid "No swap file"
+msgstr "Non posso creare un file di swap"
+
+#: ex_docmd.c:6792
+msgid "Append File"
+msgstr "In aggiunta al File"
+
+#: ex_docmd.c:6856
+msgid "E186: No previous directory"
+msgstr "E186: Non c'è una directory precedente"
+
+#: ex_docmd.c:6938
+msgid "E187: Unknown"
+msgstr "E187: Sconosciuto"
+
+#: ex_docmd.c:7023
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: :winsize richiede due argomenti numerici"
+
+#: ex_docmd.c:7079
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Posizione finestra: X %d, Y %d"
+
+#: ex_docmd.c:7084
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr ""
+"E188: Informazioni posizione finestra non disponibili su questa piattaforma"
+
+#: ex_docmd.c:7094
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: :winpos richiede due argomenti numerici"
+
+#: ex_docmd.c:7372
+msgid "Save Redirection"
+msgstr "Salva Redirezione"
+
+#: ex_docmd.c:7562
+msgid "Save View"
+msgstr "Salva Veduta"
+
+#: ex_docmd.c:7563
+msgid "Save Session"
+msgstr "Salva Sessione"
+
+#: ex_docmd.c:7565
+msgid "Save Setup"
+msgstr "Salva Setup"
+
+#: ex_docmd.c:7717
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" esiste (aggiungi ! per eseguire comunque)"
+
+#: ex_docmd.c:7722
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: Non riesco ad aprire \"%s\" in scrittura"
+
+#. set mark
+#: ex_docmd.c:7746
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr ""
+"E191: L'argomento deve essere una lettera, oppure un apice/apice retroverso"
+
+#: ex_docmd.c:7788
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Uso ricorsivo di :normal troppo esteso"
+
+#: ex_docmd.c:8306
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: Nessun nome file alternativo da sostituire a '#'"
+
+#: ex_docmd.c:8337
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: nessun file di autocomandi da sostituire per \"<afile>\""
+
+#: ex_docmd.c:8345
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr ""
+"E496: nessun numero di buffer di autocomandi da sostituire per \"<abuf>\""
+
+#: ex_docmd.c:8356
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr ""
+"E497: nessun nome di autocomandi trovato da sostituire per \"<amatch>\""
+
+#: ex_docmd.c:8366
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr ""
+"E498: nessun nome di file :source trovato da sostituire per \"<sfile>\""
+
+#: ex_docmd.c:8407
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: Un nome di file nullo per '%' or '#', va bene solo con \":p:h\""
+
+#: ex_docmd.c:8409
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: Il valore è una stringa nulla"
+
+#: ex_docmd.c:9380
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: Non posso aprire il file viminfo in lettura"
+
+#: ex_docmd.c:9553
+msgid "E196: No digraphs in this version"
+msgstr "E196: Digrammi non supportati in questa versione"
+
+#: ex_eval.c:440
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr "E608: Impossibile lanciare eccezioni con prefisso 'Vim'"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:529
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "Eccezione lanciata: %s"
+
+#: ex_eval.c:576
+#, c-format
+msgid "Exception finished: %s"
+msgstr "Eccezione finita: %s"
+
+#: ex_eval.c:577
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "Eccezione scartata: %s"
+
+#: ex_eval.c:620 ex_eval.c:664
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, linea %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:638
+#, c-format
+msgid "Exception caught: %s"
+msgstr "Eccezione intercettata: %s"
+
+#: ex_eval.c:713
+#, c-format
+msgid "%s made pending"
+msgstr "%s reso 'pending'"
+
+#: ex_eval.c:716
+#, c-format
+msgid "%s resumed"
+msgstr "%s ripristinato"
+
+#: ex_eval.c:720
+#, c-format
+msgid "%s discarded"
+msgstr "%s scartato"
+
+#: ex_eval.c:746
+msgid "Exception"
+msgstr "Eccezione"
+
+#: ex_eval.c:752
+msgid "Error and interrupt"
+msgstr "Errore ed interruzione"
+
+#: ex_eval.c:754 gui.c:4381
+msgid "Error"
+msgstr "Errore"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:756
+msgid "Interrupt"
+msgstr "Interruzione"
+
+#: ex_eval.c:830
+msgid "E579: :if nesting too deep"
+msgstr "E579: nidificazione di :if troppo estesa"
+
+#: ex_eval.c:867
+msgid "E580: :endif without :if"
+msgstr "E580: :endif senza :if"
+
+#: ex_eval.c:911
+msgid "E581: :else without :if"
+msgstr "E581: :else senza :if"
+
+#: ex_eval.c:914
+msgid "E582: :elseif without :if"
+msgstr "E582: :elseif senza :if"
+
+#: ex_eval.c:921
+msgid "E583: multiple :else"
+msgstr "E583: :else multipli"
+
+#: ex_eval.c:924
+msgid "E584: :elseif after :else"
+msgstr "E584: :elseif dopo :else"
+
+#: ex_eval.c:991
+msgid "E585: :while nesting too deep"
+msgstr "E585: nidificazione di :while troppo estesa"
+
+#: ex_eval.c:1047
+msgid "E586: :continue without :while"
+msgstr "E586: :continue senza :while"
+
+#: ex_eval.c:1087
+msgid "E587: :break without :while"
+msgstr "E587: :break senza :while"
+
+#: ex_eval.c:1286
+msgid "E601: :try nesting too deep"
+msgstr "E601: nidificazione di :try troppo estesa"
+
+#: ex_eval.c:1366
+msgid "E603: :catch without :try"
+msgstr "E603: :catch senza :try"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1388
+msgid "E604: :catch after :finally"
+msgstr "E604: :catch dopo :finally"
+
+#: ex_eval.c:1521
+msgid "E606: :finally without :try"
+msgstr "E606: :finally senza :try"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1545
+msgid "E607: multiple :finally"
+msgstr "E607: :finally multipli"
+
+#: ex_eval.c:1654
+msgid "E602: :endtry without :try"
+msgstr "E602: :endtry senza :try"
+
+#: ex_eval.c:1986
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction non contenuto in una funzione"
+
+#: ex_getln.c:3299
+msgid "tagname"
+msgstr "nome_tag"
+
+#: ex_getln.c:3302
+msgid " kind file\n"
+msgstr " tipo file\n"
+
+#: ex_getln.c:4768
+msgid "'history' option is zero"
+msgstr "l'opzione 'history' è a zero"
+
+#: ex_getln.c:5039
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s Storia (da più recente a meno recente):\n"
+
+#: ex_getln.c:5040
+msgid "Command Line"
+msgstr "Linea di Comando"
+
+#: ex_getln.c:5041
+msgid "Search String"
+msgstr "Stringa di Ricerca"
+
+#: ex_getln.c:5042
+msgid "Expression"
+msgstr "Espressione"
+
+#: ex_getln.c:5043
+msgid "Input Line"
+msgstr "Linea di Input"
+
+#: ex_getln.c:5081
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar dopo la fine del comando"
+
+#: ex_getln.c:5258
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Finestra attiva o buffer cancellato"
+
+#: fileio.c:378
+msgid "Illegal file name"
+msgstr "Nome di file non ammesso"
+
+#: fileio.c:402 fileio.c:540 fileio.c:2925 fileio.c:2966
+msgid "is a directory"
+msgstr "è una directory"
+
+#: fileio.c:404
+msgid "is not a file"
+msgstr "non è un file"
+
+#: fileio.c:562 fileio.c:4143
+msgid "[New File]"
+msgstr "[File nuovo]"
+
+#: fileio.c:595
+msgid "[Permission Denied]"
+msgstr "[Tipo di accesso non consentito]"
+
+#: fileio.c:706
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: Gli autocomand *ReadPre hanno reso il file illeggibile"
+
+#: fileio.c:708
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: Gli autocomandi *ReadPre non devono modificare il buffer in uso"
+
+#: fileio.c:729
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: Leggo da 'stdin'...\n"
+
+#: fileio.c:735
+msgid "Reading from stdin..."
+msgstr "Leggo da 'stdin'..."
+
+#. Re-opening the original file failed!
+#: fileio.c:1012
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: La conversione ha reso il file illeggibile!"
+
+#: fileio.c:2102
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:2109
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:2116
+msgid "[socket]"
+msgstr "[socket]"
+
+#: fileio.c:2124
+msgid "[RO]"
+msgstr "[Sola Lettura]"
+
+#: fileio.c:2134
+msgid "[CR missing]"
+msgstr "[manca CR]"
+
+#: fileio.c:2139
+msgid "[NL found]"
+msgstr "[trovata NL]"
+
+#: fileio.c:2144
+msgid "[long lines split]"
+msgstr "[linee lunghe divise]"
+
+#: fileio.c:2150 fileio.c:4127
+msgid "[NOT converted]"
+msgstr "[NON convertito]"
+
+#: fileio.c:2155 fileio.c:4132
+msgid "[converted]"
+msgstr "[convertito]"
+
+#: fileio.c:2162 fileio.c:4157
+msgid "[crypted]"
+msgstr "[crittografato]"
+
+#: fileio.c:2169
+msgid "[CONVERSION ERROR]"
+msgstr "[ERRORE DI CONVERSIONE]"
+
+#: fileio.c:2175
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[BYTE NON VALIDO alla linea %ld]"
+
+#: fileio.c:2182
+msgid "[READ ERRORS]"
+msgstr "[ERRORI IN LETTURA]"
+
+#: fileio.c:2398
+msgid "Can't find temp file for conversion"
+msgstr "Non riesco a trovare il file temp per leggerlo"
+
+#: fileio.c:2405
+msgid "Conversion with 'charconvert' failed"
+msgstr "Conversione fallita con 'charconvert'"
+
+#: fileio.c:2408
+msgid "can't read output of 'charconvert'"
+msgstr "non riesco a leggere il risultato di 'charconvert'"
+
+#: fileio.c:2808
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Buffer in scrittuta cancellato o scaricato dagli autocomandi"
+
+#: fileio.c:2831
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: L'autocomando ha modificato numero linee in maniera imprevista"
+
+#: fileio.c:2869
+msgid "NetBeans dissallows writes of unmodified buffers"
+msgstr "NetBeans non permette la scrittura di un buffer non modificato"
+
+#: fileio.c:2877
+msgid "Partial writes disallowed for NetBeans buffers"
+msgstr "Scrittura parziale disabilitata per i buffer di NetBeans"
+
+#: fileio.c:2931 fileio.c:2949
+msgid "is not a file or writable device"
+msgstr "non è un file o un dispositivo su cui si possa scrivere"
+
+#: fileio.c:3001
+msgid "is read-only (add ! to override)"
+msgstr "è in sola letture (aggiungi ! per eseguire comunque)"
+
+#: fileio.c:3347
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr ""
+"E506: Non posso scrivere sul file di backup (aggiungi ! per eseguire "
+"comunque)"
+
+#: fileio.c:3359
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr ""
+"E507: Errore in chiusura sul file di backup (aggiungi ! per eseguire "
+"comunque)"
+
+#: fileio.c:3361
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr ""
+"E508: Non riesco a leggere il file di backup (aggiungi ! per eseguire "
+"comunque)"
+
+#: fileio.c:3377
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr ""
+"E509: Non posso creare il file di backup (aggiungi ! per eseguire comunque)"
+
+#: fileio.c:3480
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr ""
+"E510: Non posso fare il file di backup (aggiungi ! per eseguire comunque)"
+
+#: fileio.c:3542
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr ""
+"E460: La 'fork' sulla risorsa verrebbe persa (aggiungi ! per eseguire "
+"comunque)"
+
+#: fileio.c:3652
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: Non riesco a trovare un file 'temp' su cui scrivere"
+
+#: fileio.c:3670
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr ""
+"E213: Non riesco a convertire (aggiungi ! per scrivere senza conversione)"
+
+#: fileio.c:3705
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Non posso aprire il file collegato ('linked') in scrittura"
+
+#: fileio.c:3709
+msgid "E212: Can't open file for writing"
+msgstr "E212: Non posso aprire il file in scrittura"
+
+#: fileio.c:3971
+msgid "E667: Fsync failed"
+msgstr "E667: Fsync fallito"
+
+#: fileio.c:3978
+msgid "E512: Close failed"
+msgstr "E512: Chiusura fallita"
+
+#: fileio.c:4049
+msgid "E513: write error, conversion failed"
+msgstr "E513: errore in scrittura, conversione fallita"
+
+#: fileio.c:4055
+msgid "E514: write error (file system full?)"
+msgstr "E514: errore in scrittura ('File System' pieno?)"
+
+#: fileio.c:4122
+msgid " CONVERSION ERROR"
+msgstr " ERRORE DI CONVERSIONE"
+
+#: fileio.c:4138
+msgid "[Device]"
+msgstr "[Dispositivo]"
+
+#: fileio.c:4143
+msgid "[New]"
+msgstr "[Nuovo]"
+
+#: fileio.c:4165
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:4165
+msgid " appended"
+msgstr " aggiunto in fondo"
+
+#: fileio.c:4167
+msgid " [w]"
+msgstr " [s]"
+
+#: fileio.c:4167
+msgid " written"
+msgstr " scritti"
+
+#: fileio.c:4217
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: Patchmode: non posso salvare il file originale"
+
+#: fileio.c:4239
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: non posso alterare il file vuoto originale"
+
+#: fileio.c:4254
+msgid "E207: Can't delete backup file"
+msgstr "E193: Non riesco a cancellare il file di backup"
+
+#: fileio.c:4318
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"ATTENZIONE: Il file originale può essere perso o danneggiato\n"
+
+#: fileio.c:4320
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "non uscire dall'editor prima della fine della scrittura del file!"
+
+#: fileio.c:4409
+msgid "[dos]"
+msgstr "[DOS]"
+
+#: fileio.c:4409
+msgid "[dos format]"
+msgstr "[in formato DOS]"
+
+#: fileio.c:4416
+msgid "[mac]"
+msgstr "[MAC]"
+
+#: fileio.c:4416
+msgid "[mac format]"
+msgstr "[in formato MAC]"
+
+#: fileio.c:4423
+msgid "[unix]"
+msgstr "[UNIX]"
+
+#: fileio.c:4423
+msgid "[unix format]"
+msgstr "[in formato UNIX]"
+
+#: fileio.c:4450
+msgid "1 line, "
+msgstr "1 linea, "
+
+#: fileio.c:4452
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld linee,"
+
+#: fileio.c:4455
+msgid "1 character"
+msgstr "1 carattere"
+
+#: fileio.c:4457
+#, c-format
+msgid "%ld characters"
+msgstr "%ld caratteri"
+
+#: fileio.c:4467
+msgid "[noeol]"
+msgstr "[manca carattere di fine linea]"
+
+#: fileio.c:4467
+msgid "[Incomplete last line]"
+msgstr "[Ultima linea incompleta]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4486
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "ATTENZIONE: File modificato dopo essere stato letto dall'Editor!!!"
+
+#: fileio.c:4488
+msgid "Do you really want to write to it"
+msgstr "Vuoi davvero riscriverlo"
+
+#: fileio.c:5738
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Errore in scrittura di \"%s\""
+
+#: fileio.c:5745
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Errore in chiusura di \"%s\""
+
+#: fileio.c:5748
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Errore in lettura di \"%s\""
+
+#: fileio.c:5982
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: L'autocomando 'FileChnagedShell' ha cancellato il buffer"
+
+#: fileio.c:5989
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: Attenzione: Il file \"%s\" non esiste più"
+
+#: fileio.c:6003
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: Attenzione: File \"%s\" modificato su disco ed anche nel buffer di Vim"
+
+#: fileio.c:6006
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: Attenzione: File \"%s\" modificato dopo l'apertura"
+
+#: fileio.c:6008
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: Attenzione: Modo File \"%s\" modificato dopo l'apertura"
+
+#: fileio.c:6018
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: Attenzione: Il file \"%s\" risulta creato dopo l'apertura"
+
+#: fileio.c:6031
+msgid "See \":help W11\" for more info."
+msgstr "Vedere \":help W11\" per ulteriori informazioni."
+
+#: fileio.c:6045
+msgid "Warning"
+msgstr "Attenzione"
+
+#: fileio.c:6046
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Carica File"
+
+#: fileio.c:6152
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: Non riesco a preparare per ri-caricare \"%s\""
+
+#: fileio.c:6171
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: Non riesco a ri-caricare \"%s\""
+
+#: fileio.c:6752
+msgid "--Deleted--"
+msgstr "--Cancellato--"
+
+#. the group doesn't exist
+#: fileio.c:6912
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Gruppo inesistente: \"%s\""
+
+#: fileio.c:7038
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Carattere non ammesso dopo *: %s"
+
+#: fileio.c:7050
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Evento inesistente: %s"
+
+#: fileio.c:7052
+#, c-format
+msgid "E216: No such group or event: %s"
+msgstr "E216: Evento o gruppo inesistente: %s"
+
+#. Highlight title
+#: fileio.c:7210
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Auto-Comandi ---"
+
+#: fileio.c:7481
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Non posso eseguire autocomandi for TUTTI gli eventi"
+
+#: fileio.c:7504
+msgid "No matching autocommands"
+msgstr "Nessun autocomando corrispondente"
+
+#: fileio.c:7825
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: nidificazione dell'autocomando troppo estesa"
+
+#: fileio.c:8100
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Auto comandi per \"%s\""
+
+#: fileio.c:8108
+#, c-format
+msgid "Executing %s"
+msgstr "Eseguo %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:8176
+#, c-format
+msgid "autocommand %s"
+msgstr "autocomando %s"
+
+#: fileio.c:8743
+msgid "E219: Missing {."
+msgstr "E219: Manca {."
+
+#: fileio.c:8745
+msgid "E220: Missing }."
+msgstr "E220: Manca }."
+
+#: fold.c:68
+msgid "E490: No fold found"
+msgstr "E490: Non trovo alcuna piegatura"
+
+#: fold.c:593
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: Non posso create piegatura con il 'foldmethod' in uso"
+
+#: fold.c:595
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: Non posso cancellare piegatura con il 'foldmethod' in uso"
+
+#: getchar.c:248
+msgid "E222: Add to read buffer"
+msgstr "E222: Aggiunto al buffer di lettura"
+
+#: getchar.c:2208
+msgid "E223: recursive mapping"
+msgstr "E223: mapping ricorsivo"
+
+#: getchar.c:3087
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: una abbreviazione globale già esiste per %s"
+
+#: getchar.c:3090
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: un mapping globale già esiste per %s"
+
+#: getchar.c:3222
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: una abbreviazione già esiste per %s"
+
+#: getchar.c:3225
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: un mapping già esiste per %s"
+
+#: getchar.c:3289
+msgid "No abbreviation found"
+msgstr "Non trovo l'abbreviazione"
+
+#: getchar.c:3291
+msgid "No mapping found"
+msgstr "Non trovo il mapping"
+
+#: getchar.c:4183
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: modo non consentito"
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<non posso aprire> "
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: non riesco a trovare il font %s"
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: non posso tornare alla directory in uso"
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "Nome percorso:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: non riesco ad ottenere la directory in uso"
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "OK"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2731 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "Non eseguire"
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "Dialogo Vim"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Scrollbar Widget: Non riesco a ottenere geometria del 'thumb pixmap'."
+
+#: gui_beval.c:101 gui_w32.c:3978
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: Non riesco a creare 'BalloonEval' con sia messaggio che callback"
+
+#: gui.c:220
+msgid "E229: Cannot start the GUI"
+msgstr "E229: Non posso inizializzare la GUI"
+
+#: gui.c:349
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Non posso leggere da \"%s\""
+
+#: gui.c:472
+msgid "E665: Cannot start GUI, no valid font found"
+msgstr "E665: Non posso inizializzare la GUI, nessun font valido trovato"
+
+#: gui.c:477
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: 'guifontwide' non valido"
+
+#: gui.c:547
+msgid "E599: Value of 'imactivatekey' is invalid"
+msgstr "E599: Il valore di 'imactivatekey' non è valido"
+
+#: gui.c:4061
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: Non riesco ad allocare il colore %s"
+
+#: gui_gtk.c:1607
+msgid "Vim dialog..."
+msgstr "Dialogo Vim..."
+
+#: gui_gtk.c:2060 message.c:2999
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Y Sì\n"
+"&No\n"
+"&C Ignora"
+
+#: gui_gtk.c:2268
+msgid "Input _Methods"
+msgstr "_Metodi di inserimento"
+
+#: gui_gtk.c:2534 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Sostituisci..."
+
+#: gui_gtk.c:2542 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "VIM - Cerca..."
+
+#: gui_gtk.c:2574 gui_motif.c:2888
+msgid "Find what:"
+msgstr "Trova cosa:"
+
+#: gui_gtk.c:2592 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "Sostituisci con:"
+
+#. whole word only button
+#: gui_gtk.c:2624 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "Cerca solo la parola intera"
+
+#. match case button
+#: gui_gtk.c:2635 gui_motif.c:3048
+msgid "Match case"
+msgstr "Maiuscole/minuscole"
+
+#: gui_gtk.c:2645 gui_motif.c:2990
+msgid "Direction"
+msgstr "Direzione"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2657 gui_motif.c:3002
+msgid "Up"
+msgstr "Su"
+
+#: gui_gtk.c:2661 gui_motif.c:3010
+msgid "Down"
+msgstr "Giù"
+
+#: gui_gtk.c:2683 gui_gtk.c:2685 gui_motif.c:2792
+msgid "Find Next"
+msgstr "Trova il Prossimo"
+
+#: gui_gtk.c:2702 gui_gtk.c:2704 gui_motif.c:2809
+msgid "Replace"
+msgstr "Sostituisci"
+
+#: gui_gtk.c:2715 gui_gtk.c:2717 gui_motif.c:2822
+msgid "Replace All"
+msgstr "Sostituisci Tutto"
+
+#: gui_gtk_x11.c:2327
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: Ricevuta richiesta \"die\" dal session manager\n"
+
+#: gui_gtk_x11.c:3519
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: Finestra principale distrutta inaspettatamente\n"
+
+#: gui_gtk_x11.c:4138
+msgid "Font Selection"
+msgstr "Selezione Font"
+
+#: gui_gtk_x11.c:6035 ui.c:2120
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "Uso CUT_BUFFER0 invece che una scelta nulla"
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "Filtro"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "Directory"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "Aiuto"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "File"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "Selezione"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "Disfa"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: Non riesco a caricate il fonte Zap '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: Non riesco a usare il font %s"
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Spedisco un messaggio per terminare il processo figlio.\n"
+
+#: gui_w32.c:839
+#, c-format
+msgid "E671: Cannot find window title \"%s\""
+msgstr "E671: Non trovo il titolo della finestra \"%s\""
+
+#: gui_w32.c:847
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Argomento non supportato: \"-%s\"; Usa la versione OLE."
+
+#: gui_w32.c:1100
+msgid "E672: Unable to open window inside MDI application"
+msgstr "E672: Non posso aprire la finestra in un'applicazione MDI"
+
+#: gui_w48.c:2163
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Stringa di ricerca (usa '\\\\' per cercare un '\\')"
+
+#: gui_w48.c:2188
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Sostituisci (usa '\\\\' per cercare un '\\')"
+
+#: gui_x11.c:1537
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: Non riesco ad allocare elemento di colormap, possibili colori "
+"errati"
+
+#: gui_x11.c:2118
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: Mancano descrizioni per i seguenti caratteri nel font: %s"
+
+#: gui_x11.c:2161
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Nome fontset: %s"
+
+#: gui_x11.c:2162
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "Il font '%s' non di larghezza fissa"
+
+#: gui_x11.c:2181
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Nome fontset: %s\n"
+
+#: gui_x11.c:2182
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Font0: %s\n"
+
+#: gui_x11.c:2183
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Font1: %s\n"
+
+#: gui_x11.c:2184
+#, c-format
+msgid "Font%ld width is not twice that of font0\n"
+msgstr "La larghezza di font%ld non è doppia di quella di font0\n"
+
+#: gui_x11.c:2185
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "Larghezza di Font0: %ld\n"
+
+#: gui_x11.c:2186
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"Larghezza di Font1: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: ERRORE processore Hangul"
+
+#: if_cscope.c:77
+msgid "Add a new database"
+msgstr "Aggiungi un nuovo database"
+
+#: if_cscope.c:79
+msgid "Query for a pattern"
+msgstr "Cerca un modello"
+
+#: if_cscope.c:81
+msgid "Show this message"
+msgstr "Visualizza questo messaggio"
+
+#: if_cscope.c:83
+msgid "Kill a connection"
+msgstr "Termina una connessione"
+
+#: if_cscope.c:85
+msgid "Reinit all connections"
+msgstr "Rinizializza tutte le connessioni"
+
+#: if_cscope.c:87
+msgid "Show connections"
+msgstr "Visualizza connessioni"
+
+#: if_cscope.c:95
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: Uso: cs[cope] %s"
+
+#: if_cscope.c:124
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Questo comando cscope non gestisce la divisione delle schermo.\n"
+
+#: if_cscope.c:175
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: Uso: cstag <ident>"
+
+#: if_cscope.c:231
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: tag non trovata"
+
+#: if_cscope.c:409
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: errore stat(%s): %d"
+
+#: if_cscope.c:419
+msgid "E563: stat error"
+msgstr "E563: errore stat"
+
+#: if_cscope.c:516
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s non è una directory o un database cscope valido"
+
+#: if_cscope.c:534
+#, c-format
+msgid "Added cscope database %s"
+msgstr "Aggiunto database cscope %s"
+
+#: if_cscope.c:589
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: errore leggendo connessione cscope %ld"
+
+#: if_cscope.c:694
+msgid "E561: unknown cscope search type"
+msgstr "E561: tipo di ricerca cscope sconosciuta"
+
+#: if_cscope.c:736
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: Non riesco a creare pipes cscope"
+
+#: if_cscope.c:753
+msgid "E622: Could not fork for cscope"
+msgstr "E622: Non riesco a fare fork per cscope"
+
+#: if_cscope.c:847 if_cscope.c:897
+msgid "cs_create_connection exec failed"
+msgstr "cs_create_connection exec fallita"
+
+#: if_cscope.c:898
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: Non riesco a generare processo cscope"
+
+#: if_cscope.c:911
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen di to_fp fallita"
+
+#: if_cscope.c:913
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen di fr_fp fallita"
+
+#: if_cscope.c:951
+msgid "E567: no cscope connections"
+msgstr "E567: nessuna connessione cscope"
+
+#: if_cscope.c:1025
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: nessuna corrispondenza trovata per la richiesta cscope %s di %s"
+
+#: if_cscope.c:1082
+#, c-format
+msgid "E469: invalid cscopequickfix flag %c for %c"
+msgstr "E469: flag cscopequickfix %c non valido per %c"
+
+#: if_cscope.c:1152
+msgid "cscope commands:\n"
+msgstr "comandi cscope:\n"
+
+#: if_cscope.c:1155
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (Uso: %s)"
+
+#: if_cscope.c:1253
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: impossibile aprire database cscope: %s"
+
+#: if_cscope.c:1271
+msgid "E626: cannot get cscope database information"
+msgstr "E626: impossibile leggere informazioni sul database cscope"
+
+#: if_cscope.c:1296
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: database cscope duplicato, non aggiunto"
+
+#: if_cscope.c:1307
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: raggiunto numero massimo di connessioni cscope"
+
+#: if_cscope.c:1424
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: connessione cscope %s non trovata"
+
+#: if_cscope.c:1458
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "connessione cscope %s chiusa"
+
+#. should not reach here
+#: if_cscope.c:1598
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: errore irreparabile in cs_manage_matches"
+
+#: if_cscope.c:1848
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "Tag cscope: %s"
+
+#: if_cscope.c:1870
+msgid ""
+"\n"
+" # line"
+msgstr ""
+"\n"
+" # linea"
+
+#: if_cscope.c:1872
+msgid "filename / context / line\n"
+msgstr "nomefile / contest / linea\n"
+
+#: if_cscope.c:1990
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: Errore cscope: %s"
+
+#: if_cscope.c:2176
+msgid "All cscope databases reset"
+msgstr "Tutti i databese cscope annullati"
+
+#: if_cscope.c:2244
+msgid "no cscope connections\n"
+msgstr "nessuna connessione cscope\n"
+
+#: if_cscope.c:2248
+msgid " # pid database name prepend path\n"
+msgstr " # pid database nome prepend path\n"
+
+#: if_python.c:436
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: Spiacente, comando non disponibile, non riesco a caricare libreria "
+"programmi Python."
+
+#: if_python.c:500
+msgid "E659: Cannot invoke Python recursively"
+msgstr "E659: Python non può essere chiamato ricorsivamente"
+
+#: if_python.c:701
+msgid "can't delete OutputObject attributes"
+msgstr "non riesco a cancellare gli attributi OutputObject"
+
+#: if_python.c:708
+msgid "softspace must be an integer"
+msgstr "softspace deve essere un numero intero"
+
+#: if_python.c:716
+msgid "invalid attribute"
+msgstr "atrributo non valido"
+
+#: if_python.c:755 if_python.c:769
+msgid "writelines() requires list of strings"
+msgstr "writelines() richiede una lista di stringhe"
+
+#: if_python.c:895
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: Errore inizializzazione oggetti I/O"
+
+#: if_python.c:1080 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "espressione non valida"
+
+#: if_python.c:1094 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "espressioni disabilitate in compilazione"
+
+#: if_python.c:1107
+msgid "attempt to refer to deleted buffer"
+msgstr "tentativo di referenza a buffer cancellato"
+
+#: if_python.c:1122 if_python.c:1163 if_python.c:1227 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "numero linea non nell'intervallo"
+
+#: if_python.c:1362
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<buffer oggetto (cancellato) a %8lX>"
+
+#: if_python.c:1453 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "nome di mark non valido"
+
+#: if_python.c:1733
+msgid "no such buffer"
+msgstr "buffer inesistente"
+
+#: if_python.c:1821
+msgid "attempt to refer to deleted window"
+msgstr "tentativo di referenza a una finestra cancellata"
+
+#: if_python.c:1866
+msgid "readonly attribute"
+msgstr "attributo 'readonly'"
+
+#: if_python.c:1879
+msgid "cursor position outside buffer"
+msgstr "posizione cursore fuori dal buffer"
+
+#: if_python.c:1956
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<finestra oggetto (cancellata) a %.8lX>"
+
+#: if_python.c:1968
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<finestra oggetto (sconosciuta) a %.8lX>"
+
+#: if_python.c:1970
+#, c-format
+msgid "<window %d>"
+msgstr "<finestra %d>"
+
+#: if_python.c:2046
+msgid "no such window"
+msgstr "finestra inesistente"
+
+#: if_python.c:2307 if_python.c:2341 if_python.c:2396 if_python.c:2464
+#: if_python.c:2586 if_python.c:2638 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "non riesco a salvare informazioni per 'undo'"
+
+#: if_python.c:2309 if_python.c:2403 if_python.c:2475
+msgid "cannot delete line"
+msgstr "non posso cancellare la linea"
+
+#: if_python.c:2346 if_python.c:2491 if_tcl.c:690 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "non posso sostituire la linea"
+
+#: if_python.c:2509 if_python.c:2588 if_python.c:2646
+msgid "cannot insert line"
+msgstr "non posso inserire la linea"
+
+#: if_python.c:2750
+msgid "string cannot contain newlines"
+msgstr "la stringa non può contenere caratteri 'A CAPO'"
+
+#: if_ruby.c:422
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: Spiacente, comando non disponibile, non riesco a caricare libreria "
+"programmi Ruby."
+
+#: if_ruby.c:485
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: tipo sconosciuto di salto nel programma %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Implementazione/definizione Sì/No"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Visualizza classe base di"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Visualizza funzione modulo sovrascritto"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Carica da file"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Carica da progetto"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Carica da tutti i progetti"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Carica successivo"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Visualizza sorgente di"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Trova simbolo"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Esplora classe"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Visualizza classe in gerarchia"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Visualizza classe nella gerarchia ristretta"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref si riferisce a"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref referenziato da"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref ha un"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref usato da"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Visualizza docu di"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Genera docu per"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"Non riesco a connettermi a SNiFF+. Controllare ambiente (sniffemacs deve "
+"essere presente in $PATH).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Errore in lettura. Disconnessione."
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ è al momento "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "non "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "connesso"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Richiesta SNiFF+ sconosciuta: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Errore connettendosi a SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ non connesso"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Non è un buffer SNiFF+"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: Errore in scrittura. Disconnesso"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "numero buffer non valido"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "non ancora implementato"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "opzione inesistente"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "non posso impostare linea(e)"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "mark non impostato"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "riga %d colonna %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "non riesco a inserire/aggiungere linea"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "opzione inesistente: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "'vimOption' inesistente"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "interruzione dalla tastiera"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "errore vim"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr ""
+"non riesco a creare comando buffer/finestra: oggetto in via di cancellazione"
+
+#: if_tcl.c:1545
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"non posso registrare comando callback: buffer/finestra già in cancellazione"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: ERRORE FATALE TCL: reflist corrotta!? Si prega notificare a vim-"
+"dev@vim.org"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"non posso registrare comando callback: referenza a buffer/finestra "
+"inesistente"
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"E571: Spiacente, comando non disponibile, non riesco a caricare libreria "
+"programmi Tcl."
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: ERRORE TCL: codice di ritorno non int!? Si prega notificare a vim-"
+"dev@vim.org"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "non riesco a ottenere la linea"
+
+#: if_xcmdsrv.c:225
+msgid "Unable to register a command server name"
+msgstr "Non riesco a registrare un nome di server comando"
+
+#: if_xcmdsrv.c:473
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Fallito invio comando a programma destinatario"
+
+#: if_xcmdsrv.c:747
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: Identificativo di server non valido: %s"
+
+#: if_xcmdsrv.c:1110
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: Proprietà registry relative a VIM non adeguate. Cancellate!"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "Opzione inesistente"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "Troppi argomenti di edit"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "Argomento mancante dopo"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "Spazzatura dopo opzione"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr "Troppi argomenti \"+command\", \"-c command\" o \"--cmd command\""
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "Argomento non valido per"
+
+#: main.c:469
+msgid "This Vim was not compiled with the diff feature."
+msgstr "Vim non compilato con opzione 'diff'."
+
+#: main.c:935
+msgid "Attempt to open script file again: \""
+msgstr "Tento di riaprire lo script file: \""
+
+#: main.c:944
+msgid "Cannot open for reading: \""
+msgstr "Non posso aprire in lettura: \""
+
+#: main.c:988
+msgid "Cannot open for script output: \""
+msgstr "Non posso aprire come script output: \""
+
+#: main.c:1135
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d file da elaborare\n"
+
+#: main.c:1236
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Attenzione: Output non diretto a un terminale\n"
+
+#: main.c:1238
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Attenzione: Input non proveniente da un terminale\n"
+
+#. just in case..
+#: main.c:1306
+msgid "pre-vimrc command line"
+msgstr "linea comandi prima di vimrc"
+
+#: main.c:1347
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Non posso leggere da \"%s\""
+
+#: main.c:2420
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Maggiori informazioni con: \"vim -h\"\n"
+
+#: main.c:2453
+msgid "[file ..] edit specified file(s)"
+msgstr "[file ..] apri file(s) specificati"
+
+#: main.c:2454
+msgid "- read text from stdin"
+msgstr "- leggi testo da 'stdin'"
+
+#: main.c:2455
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tag apri file in cui è definita la tag"
+
+#: main.c:2457
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [errorfile] apri file col primo errore"
+
+#: main.c:2466
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+" uso:"
+
+#: main.c:2469
+msgid " vim [arguments] "
+msgstr " vim [argomenti] "
+
+#: main.c:2473
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" o:"
+
+#: main.c:2476
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Argomenti:\n"
+
+#: main.c:2477
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tSolo nomi file da qui in poi"
+
+#: main.c:2479
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tNon espandere wildcard"
+
+#: main.c:2482
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tRegistra questo gvim a OLE"
+
+#: main.c:2483
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tDeregistra gvim a OLE"
+
+#: main.c:2486
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tEsegui usando GUI (come \"gvim\")"
+
+#: main.c:2487
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f opp. --nofork\tForeground: Non usare 'fork' inizializzando GUI"
+
+#: main.c:2489
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tModalità Vi (come \"vi\")"
+
+#: main.c:2490
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tModalità Ex (come \"ex\")"
+
+#: main.c:2491
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tModalità Silenziosa (batch) (solo per \"ex\")"
+
+#: main.c:2493
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tModalità Diff (come \"vimdiff\")"
+
+#: main.c:2495
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tModalità Facile (come \"evim\", senza modalità)"
+
+#: main.c:2496
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tModalità Sola Lettura (come \"view\")"
+
+#: main.c:2497
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tModalità Ristretta (come \"rvim\")"
+
+#: main.c:2498
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tRiscritture del file non permesse"
+
+#: main.c:2499
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tModifiche nel file non permesse"
+
+#: main.c:2500
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tModalità Binaria"
+
+#: main.c:2502
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tModalità Lisp"
+
+#: main.c:2504
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tCompatibile con Vi: 'compatible'"
+
+#: main.c:2505
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tNon interamente compatibile con Vi: 'nocompatible'"
+
+#: main.c:2506
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tLivello Verbosità"
+
+#: main.c:2507
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tModalità Debug"
+
+#: main.c:2508
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tNiente file di swap, usa solo memoria"
+
+#: main.c:2509
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tLista swap file ed esci"
+
+#: main.c:2510
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (e nome file)\tRecupera da sessione finita male"
+
+#: main.c:2511
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tCome -r"
+
+#: main.c:2513
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tNon usare newcli per aprire finestra"
+
+#: main.c:2514
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <dispositivo>\t\tUsa <dispositivo> per I/O"
+
+#: main.c:2517
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\t\tComincia in modalità Araba"
+
+#: main.c:2520
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\tComincia in modalità Ebraica"
+
+#: main.c:2523
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\tComincia in modalità Farsi (Persiano)"
+
+#: main.c:2525
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminale>\tImposta tipo terminale a <terminale>"
+
+#: main.c:2526
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tUsa <vimrc> invece di .vimrc"
+
+#: main.c:2528
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tUsa <gvimrc> invece di .gvimrc"
+
+#: main.c:2530
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tNon caricare script plugin"
+
+#: main.c:2531
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tApri N finestre (predefinito: una per ogni file)"
+
+#: main.c:2532
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\tCome -o ma dividi le finestre in verticale"
+
+#: main.c:2533
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tPosizionati alla fine del file"
+
+#: main.c:2534
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\tPosizionati alla linea <lnum>"
+
+#: main.c:2536
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr ""
+"--cmd <comando>\t\tEsegui <comando> prima di caricare eventuali file vimrc"
+
+#: main.c:2538
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <comando>\t\tEsegui <comando> dopo caricamento primo file"
+
+#: main.c:2539
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr ""
+"-S <sessione>\tEsegui comandi in file <sessione> dopo caricamento primo file"
+
+#: main.c:2540
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <scriptin>\tLeggi comandi in modalità normale da file <scriptin>"
+
+#: main.c:2541
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <scriptout>\tAggiungi tutti i comandi immessi a file <scriptout>"
+
+#: main.c:2542
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <scriptout>\tScrivi tutti i comandi immessi in file <scriptout>"
+
+#: main.c:2544
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tApri un file crittato"
+
+#: main.c:2548
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <schermo>\tEsegui vim a questo particolare server X"
+
+#: main.c:2550
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tNon connetterti a server X"
+
+#: main.c:2553
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <file>\tApri <file> in un server Vim se possibile"
+
+#: main.c:2554
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-silent <files> Stessa cosa, ignora se non esiste un server"
+
+#: main.c:2555
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr ""
+"--remote-wait <file> Come --remote ma aspetta che file siano elaborati"
+
+#: main.c:2556
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr ""
+"--remote-wait-silent <files> Stessa cosa, ignora se non esiste un server"
+
+#: main.c:2557
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <tasti>\tInvia <tasti> a un server Vim ed esci"
+
+#: main.c:2558
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr ""
+"--remote--expr <expr>\tEsegui <expr> in un server Vim e stampa risultato"
+
+#: main.c:2559
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tLista nomi server Vim disponibili ed esci"
+
+#: main.c:2560
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <nome>\tInvia a/diventa server Vim di nome <nome>"
+
+#: main.c:2563
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tUsa <viminfo> invece di .viminfo"
+
+#: main.c:2565
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h opp. --help\tStampa Aiuto (questo messaggio) ed esci"
+
+#: main.c:2566
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\tStampa informazioni sulla versione ed esci"
+
+#: main.c:2570
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Opzioni accettate da gvim (versione Motif):\n"
+
+#: main.c:2574
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr ""
+"\n"
+"Opzioni accettate da gvim (versione neXtaw):\n"
+
+#: main.c:2576
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Opzioni accettate da gvim (versione Athena):\n"
+
+#: main.c:2580
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <schermo>\tEsegui vim su <schermo>"
+
+#: main.c:2581
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tInizia vim riducendolo ad icona"
+
+#: main.c:2583
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <nome>\t\tUsa risorsa come se vim fosse <nome>"
+
+#: main.c:2584
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (Non implementato)\n"
+
+#: main.c:2586
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <colore>\tUsa <colore> come sfondo (anche: -bg)"
+
+#: main.c:2587
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <colore>\tUsa <colore> per il testo normale (anche: -fg)"
+
+#: main.c:2588 main.c:2608
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <font>\t\tUsa <font> for il testo normale (anche: -fn)"
+
+#: main.c:2589
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <font>\tUsa <font> per testo in grassetto"
+
+#: main.c:2590
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <font>\tUsa <font> per testo in corsivo"
+
+#: main.c:2591 main.c:2609
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\tUsa <geom> per la geometria iniziale (anche: -geom)"
+
+#: main.c:2592
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <larg>\tUsa larghezza <larg> per bordo (anche: -bw)"
+
+#: main.c:2593
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr ""
+"-scrollbarwidth <larg> Usa larghezza <larg> per scrollbar (anche: -sw)"
+
+#: main.c:2595
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <alt>\tUsa altezza <alt> per barra menu (anche: -mh)"
+
+#: main.c:2597 main.c:2610
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tUsa colori invertiti (anche: -rv)"
+
+#: main.c:2598
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tNon usare colori invertiti (anche: +rv)"
+
+#: main.c:2599
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <risorsa>\tImposta la risorsa specificata"
+
+#: main.c:2602
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Argomenti accettati da gvim (versione RISC OS):\n"
+
+#: main.c:2603
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <numero>\tLarghezza iniziale finestra in colonne"
+
+#: main.c:2604
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <numero>\tAltezza iniziale finestra in righe"
+
+#: main.c:2607
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Argomenti accettati da gvim (versione GTK+):\n"
+
+#: main.c:2611
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <schermo>\tEsegui vim su <schermo> (anche: --display)"
+
+#: main.c:2613
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr ""
+"--role <ruolo>\tImposta un ruolo univoco per identificare la finestra "
+"principale"
+
+#: main.c:2615
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tApri Vim dentro un altro 'widget' GTK"
+
+#: main.c:2618
+msgid "-P <parent title>\tOpen Vim inside parent application"
+msgstr "-P <titolo padre>\tApri Vim in un'applicazione padre"
+
+#: main.c:2856
+msgid "No display"
+msgstr "Manca display"
+
+#. Failed to send, abort.
+#: main.c:2871
+msgid ": Send failed.\n"
+msgstr ": Invio fallito.\n"
+
+#. Let vim start normally.
+#: main.c:2877
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": Invio fallito. Tento di eseguire localmente\n"
+
+#: main.c:2915 main.c:2936
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d di %d elaborato"
+
+#: main.c:2958
+msgid "No display: Send expression failed.\n"
+msgstr "Nessun display: Invio di espressione fallito.\n"
+
+#: main.c:2970
+msgid ": Send expression failed.\n"
+msgstr ": Invio di espressione fallito.\n"
+
+#: mark.c:709
+msgid "No marks set"
+msgstr "Nessun mark impostato"
+
+#: mark.c:711
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: Nessun mark corrispondente a \"%s\""
+
+#. Highlight title
+#: mark.c:722
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"mark linea col.file/testo"
+
+#. Highlight title
+#: mark.c:760
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" salt.linea col.file/testo"
+
+#. Highlight title
+#: mark.c:805
+msgid ""
+"\n"
+"change line col text"
+msgstr ""
+"\n"
+"modif linea col testo"
+
+#: mark.c:1281
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# File mark:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1316
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Jumplist (dai più recenti):\n"
+
+#: mark.c:1412
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Storia dei mark all'interno dei files (dai più recenti ai meno recenti):\n"
+
+#: mark.c:1501
+msgid "Missing '>'"
+msgstr "Manca '>'"
+
+#: mbyte.c:467
+msgid "E543: Not a valid codepage"
+msgstr "E543: Codepage non valido"
+
+#: mbyte.c:4431
+msgid "E284: Cannot set IC values"
+msgstr "E284: Non posso assegnare valori IC"
+
+#: mbyte.c:4583
+msgid "E285: Failed to create input context"
+msgstr "E285: Creazione di un contesto di input fallita"
+
+#: mbyte.c:4741
+msgid "E286: Failed to open input method"
+msgstr "E286: Apertura 'input method' fallita"
+
+#: mbyte.c:4752
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: Attenzione: Non posso assegnare IM a 'destroy callback'"
+
+#: mbyte.c:4758
+msgid "E288: input method doesn't support any style"
+msgstr "E288: 'input method' non sopporta alcuno stile"
+
+#: mbyte.c:4815
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: 'input method' non supporta il mio tipo di preedit"
+
+#: mbyte.c:4889
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: stile 'over-the-spot' richiede fontset"
+
+#: mbyte.c:4925
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr ""
+"E291: Il tuo GTK+ è anteriore a versione 1.2.3. Area Status disabilitata"
+
+#: mbyte.c:5232
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Server di 'Input Method' non in esecuzione"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: il blocco non era riservato"
+
+#: memfile.c:1010
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Errore di posizionamento durante lettura swap file"
+
+#: memfile.c:1015
+msgid "E295: Read error in swap file"
+msgstr "E295: Errore leggendo swap file"
+
+#: memfile.c:1067
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Errore di posizionamento scrivendo swap file"
+
+#: memfile.c:1085
+msgid "E297: Write error in swap file"
+msgstr "E297: Errore scrivendo swap file"
+
+#: memfile.c:1282
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: Lo swap file esiste già (un link simbolico?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Non riesco a leggere blocco numero 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Non riesco a leggere blocco numero 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: Non riesco a leggere blocco numero 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:444
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Ahimè, lo swap file è perduto!!!"
+
+#: memline.c:449
+msgid "E302: Could not rename swap file"
+msgstr "E302: Non riesco a rinominare lo swap file"
+
+#: memline.c:519
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr ""
+"E303: Non riesco ad aprile lo swap file per \"%s\", recupero impossible"
+
+#: memline.c:618
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: Non riesco a leggere blocco 0??"
+
+#: memline.c:758
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Nessun swap file trovato per %s"
+
+#: memline.c:768
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "Dimmi numero di swap file da usare (0 per lasciar perdere): "
+
+#: memline.c:813
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: Non riesco ad aprire %s"
+
+#: memline.c:835
+msgid "Unable to read block 0 from "
+msgstr "Non riesco a leggere il blocco 0 da "
+
+#: memline.c:838
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Forse non ci sono state modifiche oppure Vim non ha aggiornato lo swap file."
+
+#: memline.c:848 memline.c:865
+msgid " cannot be used with this version of Vim.\n"
+msgstr " non può essere usato con questa versione di Vim.\n"
+
+#: memline.c:850
+msgid "Use Vim version 3.0.\n"
+msgstr "Usa Vim versione 3.0.\n"
+
+#: memline.c:856
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s non sembra uno swap file Vim"
+
+#: memline.c:869
+msgid " cannot be used on this computer.\n"
+msgstr " non può essere usato su questo computer.\n"
+
+#: memline.c:871
+msgid "The file was created on "
+msgstr "Il file è stato creato il "
+
+#: memline.c:875
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"o il file è stato danneggiato."
+
+#: memline.c:904
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "Uso swap file \"%s\""
+
+#: memline.c:910
+#, c-format
+msgid "Original file \"%s\""
+msgstr "File originale \"%s\""
+
+#: memline.c:923
+msgid "E308: Warning: Original file may have been changed"
+msgstr ""
+"E308: Attenzione: il file originale può essere stato modificato nel frattempo"
+
+#: memline.c:976
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Impossibile leggere blocco 1 da %s"
+
+#: memline.c:980
+msgid "???MANY LINES MISSING"
+msgstr "???MOLTE LINEE MANCANTI"
+
+#: memline.c:996
+msgid "???LINE COUNT WRONG"
+msgstr "???CONTATORE LINEE ERRATO"
+
+#: memline.c:1003
+msgid "???EMPTY BLOCK"
+msgstr "???BLOCCO VUOTO"
+
+#: memline.c:1029
+msgid "???LINES MISSING"
+msgstr "???LINEE MANCANTI"
+
+#: memline.c:1061
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ID del Blocco 1 errato (che %s non sia un .swp file?)"
+
+#: memline.c:1066
+msgid "???BLOCK MISSING"
+msgstr "???BLOCCO MANCANTE"
+
+#: memline.c:1082
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? da qui fino a ???END le linee possono essere fuori ordine"
+
+#: memline.c:1098
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr ""
+"??? da qui fino a ???END linee possono essere state inserite/cancellate"
+
+#: memline.c:1118
+msgid "???END"
+msgstr "???END"
+
+#: memline.c:1144
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Recupero Interrotto"
+
+#: memline.c:1149
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: Errori durante recupero; controlla linee che iniziano con ???"
+
+#: memline.c:1151
+msgid "See \":help E312\" for more information."
+msgstr "Vedere \":help E312\" per ulteriori informazioni."
+
+#: memline.c:1156
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Recupero completato. Dovresti controllare se va tutto bene."
+
+#: memline.c:1157
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Potresti salvare questo file con un altro nome ed eseguire\n"
+
+#: memline.c:1158
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "'diff' rispetto al file originale per vedere le differenze)\n"
+
+#: memline.c:1159
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"Cancella il file .swp in seguito.\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1215
+msgid "Swap files found:"
+msgstr "Swap file trovati:"
+
+#: memline.c:1393
+msgid " In current directory:\n"
+msgstr " Nella directory in uso:\n"
+
+#: memline.c:1395
+msgid " Using specified name:\n"
+msgstr " Uso il nome fornito:\n"
+
+#: memline.c:1399
+msgid " In directory "
+msgstr " Nella directory "
+
+#: memline.c:1417
+msgid " -- none --\n"
+msgstr " -- nessuno --\n"
+
+#: memline.c:1489
+msgid " owned by: "
+msgstr " proprietario: "
+
+#: memline.c:1491
+msgid " dated: "
+msgstr " datato: "
+
+#: memline.c:1495 memline.c:3685
+msgid " dated: "
+msgstr " datato: "
+
+#: memline.c:1511
+msgid " [from Vim version 3.0]"
+msgstr " [da Vim versione 3.0]"
+
+#: memline.c:1515
+msgid " [does not look like a Vim swap file]"
+msgstr " [non assomiglia ad uno swap file Vim]"
+
+#: memline.c:1519
+msgid " file name: "
+msgstr " nome file: "
+
+#: memline.c:1525
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" modificato: "
+
+#: memline.c:1526
+msgid "YES"
+msgstr "YES"
+
+#: memline.c:1526
+msgid "no"
+msgstr "no"
+
+#: memline.c:1530
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" nome utente: "
+
+#: memline.c:1537
+msgid " host name: "
+msgstr " nome computer: "
+
+#: memline.c:1539
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" nome computer: "
+
+#: memline.c:1545
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ID del processo: "
+
+#: memline.c:1551
+msgid " (still running)"
+msgstr " (ancora attivo)"
+
+#: memline.c:1563
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [non utilizzabile con questa versione di Vim]"
+
+#: memline.c:1566
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [not utilizzabile su questo computer]"
+
+#: memline.c:1571
+msgid " [cannot be read]"
+msgstr " [non leggibile]"
+
+#: memline.c:1575
+msgid " [cannot be opened]"
+msgstr " [non riesco ad aprire]"
+
+#: memline.c:1765
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Non posso preservare, manca swap file"
+
+#: memline.c:1818
+msgid "File preserved"
+msgstr "File preservato"
+
+#: memline.c:1820
+msgid "E314: Preserve failed"
+msgstr "E314: Preservazione fallita"
+
+#: memline.c:1891
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: numero linea non valido: %ld"
+
+#: memline.c:1917
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: non riesco a trovare la linea %ld"
+
+#: memline.c:2307
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: ID blocco puntatori errato 3"
+
+#: memline.c:2387
+msgid "stack_idx should be 0"
+msgstr "stack_idx dovrebbe essere 0"
+
+#: memline.c:2449
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Aggiornati troppi blocchi?"
+
+#: memline.c:2631
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: ID blocco puntatori errato 4"
+
+#: memline.c:2658
+msgid "deleted block 1?"
+msgstr "cancellato blocco 1?"
+
+#: memline.c:2858
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Non riesco a trovare la linea %ld"
+
+#: memline.c:3101
+msgid "E317: pointer block id wrong"
+msgstr "E317: ID blocco puntatori errato"
+
+#: memline.c:3117
+msgid "pe_line_count is zero"
+msgstr "pe_line_count a zero"
+
+#: memline.c:3146
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: numero linea non ammissibile: %ld dopo la fine"
+
+#: memline.c:3150
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: contatore linee errato nel blocco %ld"
+
+#: memline.c:3199
+msgid "Stack size increases"
+msgstr "Dimensione 'stack' aumentata"
+
+#: memline.c:3245
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: ID blocco puntatori errato 2"
+
+#: memline.c:3675
+msgid "E325: ATTENTION"
+msgstr "E325: ATTENZIONE"
+
+#: memline.c:3676
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Trovato uno swap file di nome \""
+
+#: memline.c:3680
+msgid "While opening file \""
+msgstr "Mentre aprivo file \""
+
+#: memline.c:3689
+msgid " NEWER than swap file!\n"
+msgstr " più RECENTE dello swap file!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3693
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Un altro programma può essere in edit sullo stesso file.\n"
+" Se è così, attenzione a non trovarti con due versioni\n"
+" differenti dello stesso file a cui vengono apportate modifiche.\n"
+
+#: memline.c:3694
+msgid " Quit, or continue with caution.\n"
+msgstr " Esci, o continua con prudenza.\n"
+
+#: memline.c:3695
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) Una sessione di edit per questo file è finita male.\n"
+
+#: memline.c:3696
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Se è così, usa \":recover\" oppure \"vim -r "
+
+#: memline.c:3698
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" per recuperare modifiche fatte (vedi \":help recovery\").\n"
+
+#: memline.c:3699
+msgid " If you did this already, delete the swap file \""
+msgstr " Se hai già fatto ciò, cancella il file di swap \""
+
+#: memline.c:3701
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" per non ricevere ancora questo messaggio.\n"
+
+#: memline.c:3715 memline.c:3719
+msgid "Swap file \""
+msgstr "Swap file \""
+
+#: memline.c:3716 memline.c:3722
+msgid "\" already exists!"
+msgstr "\" già esistente!"
+
+#: memline.c:3725
+msgid "VIM - ATTENTION"
+msgstr "VIM - ATTENZIONE"
+
+#: memline.c:3727
+msgid "Swap file already exists!"
+msgstr "Lo swap file esiste già!"
+
+#: memline.c:3731
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort"
+msgstr ""
+"&O Apri sola-lettura\n"
+"&E Apri comunque\n"
+"&Recupera\n"
+"&Q Esci\n"
+"&Annulla"
+
+#: memline.c:3733
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort\n"
+"&Delete it"
+msgstr ""
+"&O Apri sola-lettura\n"
+"&E Apri comunque\n"
+"&Recupera\n"
+"&Q Esci\n"
+"&Annulla\n"
+"&D Cancellalo"
+
+#: memline.c:3790
+msgid "E326: Too many swap files found"
+msgstr "E326: Trovati troppi swap file"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr ""
+"E327: Parte del percorso di questo elemento di Menu non è un sotto-Menu"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: I Menu esistono solo in un'altra modalità"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Nessun Menu con quel nome"
+
+#: menu.c:525
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Il percorso del Menu non deve condurre a un sotto-Menu"
+
+#: menu.c:564
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr ""
+"E331: Non devi aggiungere elementi di Menu direttamente alla barra Menu"
+
+#: menu.c:570
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Il separatore non può far parte di un percorso di Menu"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1097
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Menu ---"
+
+#: menu.c:2019
+msgid "Tear off this menu"
+msgstr "Togli questo Menu"
+
+#: menu.c:2084
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Il percorso Menu deve condurre ad un elemento Menu"
+
+#: menu.c:2104
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Menu non trovato: %s"
+
+#: menu.c:2173
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: Menu non definito per la modalità %s"
+
+#: menu.c:2211
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Il percorso Menu deve condurre ad un sotto-Menu"
+
+#: menu.c:2232
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Menu non trovato - controlla nomi Menu"
+
+#: message.c:414
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Errore/i eseguendo %s:"
+
+#: message.c:440
+#, c-format
+msgid "line %4ld:"
+msgstr "linea %4ld:"
+
+#: message.c:647
+msgid "[string too long]"
+msgstr "[stringa troppo lunga]"
+
+#: message.c:797
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "Manutentore messaggi: Vlad Sandrini <marco@sandrini.biz>"
+
+#: message.c:1025
+msgid "Interrupt: "
+msgstr "Interruzione: "
+
+#: message.c:1028
+msgid "Hit ENTER to continue"
+msgstr "INVIO per proseguire"
+
+#: message.c:1030
+msgid "Hit ENTER or type command to continue"
+msgstr "Batti INVIO o un comando per proseguire"
+
+#: message.c:2351
+msgid "-- More --"
+msgstr "-- Ancora --"
+
+#: message.c:2354
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: linea, SPAZIO/b: pagina, d/u: mezza pagina, q: esci)"
+
+#: message.c:2355
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: linea, SPAZIO: pagina, d: mezza pagina, q: esci)"
+
+#: message.c:2982 message.c:2997
+msgid "Question"
+msgstr "Domanda"
+
+#: message.c:2984
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Y Sì\n"
+"&No"
+
+#: message.c:3017
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Y Sì\n"
+"&No\n"
+"&A Salva tutto\n"
+"&D Scarta Tutto\n"
+"&Cancella"
+
+#: message.c:3058
+msgid "Save File dialog"
+msgstr "Salva File dialogo"
+
+#: message.c:3060
+msgid "Open File dialog"
+msgstr "Apri File dialogo"
+
+#. TODO: non-GUI file selector here
+#: message.c:3131
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: Spiacente, niente esplorazione file in modalità console"
+
+#: misc1.c:2773
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: Attenzione: Modifica a un file in sola-lettura"
+
+#: misc1.c:3021
+msgid "1 more line"
+msgstr "1 linea in più"
+
+#: misc1.c:3023
+msgid "1 line less"
+msgstr "1 linea in meno"
+
+#: misc1.c:3028
+#, c-format
+msgid "%ld more lines"
+msgstr "%ld linee in più"
+
+#: misc1.c:3030
+#, c-format
+msgid "%ld fewer lines"
+msgstr "%ld linee in meno"
+
+#: misc1.c:3033
+msgid " (Interrupted)"
+msgstr " (Interrotto)"
+
+#: misc1.c:7588
+msgid "Vim: preserving files...\n"
+msgstr "Vim: preservo file...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:7598
+msgid "Vim: Finished.\n"
+msgstr "Vim: Finito.\n"
+
+#: misc2.c:695 misc2.c:711
+msgid "ERROR: "
+msgstr "ERRORE: "
+
+#: misc2.c:715
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bytes] totali alloc-rilasc %lu-%lu, in uso %lu, max uso %lu\n"
+
+#: misc2.c:717
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[chiamate] totale re/malloc() %lu, totale free() %lu\n"
+"\n"
+
+#: misc2.c:772
+msgid "E340: Line is becoming too long"
+msgstr "E340: La linea sta diventando troppo lunga"
+
+#: misc2.c:816
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Errore interno: lalloc(%ld, )"
+
+#: misc2.c:924
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Non c'è più memoria! (stavo allocando %lu bytes)"
+
+#: misc2.c:2594
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Chiamo lo shell per eseguire: \"%s\""
+
+#: misc2.c:2816
+msgid "E545: Missing colon"
+msgstr "E545: Manca ':'"
+
+#: misc2.c:2818 misc2.c:2845
+msgid "E546: Illegal mode"
+msgstr "E546: Modalità non valida"
+
+#: misc2.c:2884
+msgid "E547: Illegal mouseshape"
+msgstr "E547: Forma del mouse non valida"
+
+#: misc2.c:2924
+msgid "E548: digit expected"
+msgstr "E548: aspettavo un numero"
+
+#: misc2.c:2929
+msgid "E549: Illegal percentage"
+msgstr "E549: Percentuale non valida"
+
+#: misc2.c:3239
+msgid "Enter encryption key: "
+msgstr "Immetti chiave di crittazione: "
+
+#: misc2.c:3240
+msgid "Enter same key again: "
+msgstr "Ribatti per conferma la stessa chiave: "
+
+#: misc2.c:3250
+msgid "Keys don't match!"
+msgstr "Le chiavi non corrispondono!"
+
+#: misc2.c:3799
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Percorso non valido: '**[numero]' deve essere a fine percorso o essere "
+"seguito da '%s'."
+
+#: misc2.c:5078
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Non riesco a trovare la directory \"%s\" nel 'cdpath'"
+
+#: misc2.c:5081
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Non riesco a trovare il file \"%s\" nel percorso"
+
+#: misc2.c:5087
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: Nessun altra directory \"%s\" trovata nel 'cdpath'"
+
+#: misc2.c:5090
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: Nessun altro file \"%s\" trovato nel percorso"
+
+#: misc2.c:5324
+msgid "E550: Missing colon"
+msgstr "E550: Manca ':'"
+
+#: misc2.c:5336
+msgid "E551: Illegal component"
+msgstr "E551: Componente non valido"
+
+#: misc2.c:5344
+msgid "E552: digit expected"
+msgstr "E552: aspettavo un numero"
+
+#. Get here when the server can't be found.
+#: netbeans.c:396
+msgid "Cannot connect to Netbeans #2"
+msgstr "Non posso connettermi a Netbeans #2"
+
+#: netbeans.c:404
+msgid "Cannot connect to Netbeans"
+msgstr "Non posso connettermi a Netbeans"
+
+#: netbeans.c:450
+#, c-format
+msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\""
+msgstr ""
+"E668: Modalità errata di accesso a file info connessione NetBeans: \"%s\""
+
+#: netbeans.c:749
+msgid "read from Netbeans socket"
+msgstr "lettura da socket Netbeans"
+
+#: netbeans.c:1643
+#, c-format
+msgid "E658: NetBeans connection lost for buffer %ld"
+msgstr "E658: Connessione NetBeans persa per il buffer %ld"
+
+#: normal.c:2980
+msgid "Warning: terminal cannot highlight"
+msgstr "Attenzione: il terminale non è in grado di evidenziare"
+
+#: normal.c:3276
+msgid "E348: No string under cursor"
+msgstr "E348: Nessuna stringa sotto il cursore"
+
+#: normal.c:3278
+msgid "E349: No identifier under cursor"
+msgstr "E349: Nessun identificativo sotto il cursore"
+
+#: normal.c:4519
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: Non posso togliere piegature con il 'foldmethod' in uso"
+
+#: normal.c:6740
+msgid "E664: changelist is empty"
+msgstr "E664: lista modifiche vuota"
+
+#: normal.c:6742
+msgid "E662: At start of changelist"
+msgstr "E662: All'inizio della lista modifiche"
+
+#: normal.c:6744
+msgid "E663: At end of changelist"
+msgstr "E663: Alla fine della lista modifiche"
+
+#: normal.c:8006
+msgid "Type :quit<Enter> to exit Vim"
+msgstr "Batti :quit<Invio> per uscire da Vim"
+
+#: ops.c:294
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "1 linea %sa 1 volta"
+
+#: ops.c:296
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 linea %sa %d volte"
+
+#: ops.c:301
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld linee %se 1 volta"
+
+#: ops.c:304
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld linee %se %d volte"
+
+#: ops.c:662
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld linee da rientrare... "
+
+#: ops.c:712
+msgid "1 line indented "
+msgstr "1 linea rientrata "
+
+#: ops.c:714
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld linee rientrate "
+
+#. must display the prompt
+#: ops.c:1688
+msgid "cannot yank; delete anyway"
+msgstr "non riesco a salvare in un registro; cancello comunque"
+
+#: ops.c:2274
+msgid "1 line changed"
+msgstr "1 linea cambiata"
+
+#: ops.c:2276
+#, c-format
+msgid "%ld lines changed"
+msgstr "%ld linee cambiate"
+
+#: ops.c:2660
+#, c-format
+msgid "freeing %ld lines"
+msgstr "libero %ld linee"
+
+#: ops.c:2941
+msgid "1 line yanked"
+msgstr "1 linea messa in registro"
+
+#: ops.c:2943
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld linee messe in registro"
+
+#: ops.c:3228
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: Niente nel registro %s"
+
+#. Highlight title
+#: ops.c:3779
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Registri ---"
+
+#: ops.c:5088
+msgid "Illegal register name"
+msgstr "Nome registro non ammesso"
+
+#: ops.c:5176
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Registri:\n"
+
+#: ops.c:5226
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: Tipo di registro sconosciuto: %d"
+
+#: ops.c:5711
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: Nome registro non valido: '%s'"
+
+#: ops.c:6071
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Col.; "
+
+#: ops.c:6078
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Selezionate %s%ld di %ld linee; %ld di %ld parole; %ld di %ld caratt."
+
+#: ops.c:6094
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Col. %s di %s; Linea %ld di %ld; Parola %ld di %ld; Caratt. %ld di %ld"
+
+#: ops.c:6105
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld per BOM)"
+
+#: option.c:1643
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=Pagina %N"
+
+#: option.c:2092
+msgid "Thanks for flying Vim"
+msgstr "Grazie per aver volato con Vim"
+
+#: option.c:3419 option.c:3535
+msgid "E518: Unknown option"
+msgstr "E518: Opzione inesistente"
+
+#: option.c:3432
+msgid "E519: Option not supported"
+msgstr "E519: Opzione non supportata"
+
+#: option.c:3457
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: Non consentito in una 'modeline'"
+
+#: option.c:3522
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tImpostata l'ultima volta da "
+
+#: option.c:3661
+msgid "E521: Number required after ="
+msgstr "E521: Ci vuole un numero dopo ="
+
+#: option.c:3989 option.c:4619
+msgid "E522: Not found in termcap"
+msgstr "E522: Non trovato in 'termcap'"
+
+#: option.c:4064
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: Carattere non ammesso <%s>"
+
+#: option.c:4611
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: Non posso assegnare a 'term' il valore 'stringa nulla'"
+
+#: option.c:4614
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: Non posso modificare 'term' mentre sono nella GUI"
+
+#: option.c:4616
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: Usa \":gui\" per far partire la GUI"
+
+#: option.c:4645
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: 'backupext' e 'patchmode' sono uguali"
+
+#: option.c:4860
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: Non può essere cambiato nella GUI GTK+ 2"
+
+#: option.c:5016
+msgid "E524: Missing colon"
+msgstr "E524: Manca ':'"
+
+#: option.c:5018
+msgid "E525: Zero length string"
+msgstr "E525: Stringa nulla"
+
+#: option.c:5086
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: Manca numero dopo <%s>"
+
+#: option.c:5100
+msgid "E527: Missing comma"
+msgstr "E527: Manca virgola"
+
+#: option.c:5107
+msgid "E528: Must specify a ' value"
+msgstr "E528: Devi specificare un valore '"
+
+#: option.c:5148
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: contiene carattere 'wide' o non-stampabile"
+
+#: option.c:5197
+msgid "E596: Invalid font(s)"
+msgstr "E596: Font non validi"
+
+#: option.c:5205
+msgid "E597: can't select fontset"
+msgstr "E597: non posso selezionare fontset"
+
+#: option.c:5207
+msgid "E598: Invalid fontset"
+msgstr "E598: Fontset non valido"
+
+#: option.c:5214
+msgid "E533: can't select wide font"
+msgstr "E533: non posso selezionare 'wide font'"
+
+#: option.c:5216
+msgid "E534: Invalid wide font"
+msgstr "E534: 'Wide font' non valido"
+
+#: option.c:5486
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: Carattere non ammesso dopo <%c>"
+
+#: option.c:5597
+msgid "E536: comma required"
+msgstr "E536: virgola mancante"
+
+#: option.c:5607
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: 'commentstring' deve essere nulla o contenere %s"
+
+#: option.c:5682
+msgid "E538: No mouse support"
+msgstr "E538: Manca supporto mouse"
+
+#: option.c:5950
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: Espressione non terminata"
+
+#: option.c:5954
+msgid "E541: too many items"
+msgstr "E541: troppi elementi"
+
+#: option.c:5956
+msgid "E542: unbalanced groups"
+msgstr "E542: gruppi sbilanciati"
+
+#: option.c:6196
+msgid "E590: A preview window already exists"
+msgstr "E590: Una finestra di pre-visualizzazione esiste già"
+
+#: option.c:6453
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr "W17: Arabo richiede UTF-8, esegui ':set encoding=utf-8'"
+
+#: option.c:6786
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: Servono almeno %d linee"
+
+#: option.c:6796
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: Servono almeno %d colonne"
+
+#: option.c:7103
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Opzione inesistente: %s"
+
+#: option.c:7223
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Codici terminale ---"
+
+#: option.c:7225
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Valori opzioni globali ---"
+
+#: option.c:7227
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Valore opzioni globali ---"
+
+#: option.c:7229
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Opzioni ---"
+
+#: option.c:7935
+msgid "E356: get_varp ERROR"
+msgstr "E356: ERRORE get_varp"
+
+#: option.c:8906
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': Manca carattere corrispondente per %s"
+
+#: option.c:8940
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': Caratteri in più dopo il ';': %s"
+
+#: os_amiga.c:280
+msgid "cannot open "
+msgstr "non riesco ad aprire "
+
+#: os_amiga.c:314
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Non riesco ad aprire la finestra!\n"
+
+#: os_amiga.c:338
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Serve Amigados versione 2.04 o successiva\n"
+
+#: os_amiga.c:344
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Serve %s versione %ld\n"
+
+#: os_amiga.c:416
+msgid "Cannot open NIL:\n"
+msgstr "Non riesco ad aprire NIL:\n"
+
+#: os_amiga.c:427
+msgid "Cannot create "
+msgstr "Non riesco a creare "
+
+#: os_amiga.c:905
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim esce con %d\n"
+
+#: os_amiga.c:941
+msgid "cannot change console mode ?!\n"
+msgstr "non posso modificare modalità console ?!\n"
+
+#: os_amiga.c:1012
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: non una console??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1161
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Non posso eseguire lo shell con l'opzione -f"
+
+#: os_amiga.c:1202 os_amiga.c:1292
+msgid "Cannot execute "
+msgstr "Non riesco a eseguire "
+
+#: os_amiga.c:1205 os_amiga.c:1302
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1225 os_amiga.c:1327
+msgid " returned\n"
+msgstr " ottenuto\n"
+
+#: os_amiga.c:1468
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE troppo piccolo."
+
+#: os_amiga.c:1472
+msgid "I/O ERROR"
+msgstr "ERRORE I/O"
+
+#: os_mswin.c:548
+msgid "...(truncated)"
+msgstr "...(troncato)"
+
+#: os_mswin.c:650
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' non vale 80, non riesco ad eseguire comandi esterni"
+
+#: os_mswin.c:1982
+msgid "E237: Printer selection failed"
+msgstr "E237: Scelta stampante non riuscita"
+
+#: os_mswin.c:2022
+#, c-format
+msgid "to %s on %s"
+msgstr "a %s su %s"
+
+#: os_mswin.c:2037
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: Font per stampante sconosciuto: %s"
+
+#: os_mswin.c:2086 os_mswin.c:2096
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Errore durante stampa: %s"
+
+#: os_mswin.c:2097
+msgid "Unknown"
+msgstr "Sconosciuto"
+
+#: os_mswin.c:2124
+#, c-format
+msgid "Printing '%s'"
+msgstr "Stampato: '%s'"
+
+#: os_mswin.c:3213
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Nome di charset non ammesso \"%s\" nel fonte di nome \"%s\""
+
+#: os_mswin.c:3221
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Carattere non ammesso '%c' nel font di nome \"%s\""
+
+#: os_riscos.c:1259
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Opzione 'osfiletype' non valida - uso 'Text'"
+
+#: os_unix.c:927
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: Segnale doppio, esco\n"
+
+#: os_unix.c:933
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Intercettato segnale fatale %s\n"
+
+#: os_unix.c:936
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Intercettato segnale fatale\n"
+
+#: os_unix.c:1199
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Attivazione visualizzazione X ha richiesto %ld msec"
+
+#: os_unix.c:1226
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: Preso errore X\n"
+
+#: os_unix.c:1338
+msgid "Testing the X display failed"
+msgstr "Prova visualizzazione X fallita"
+
+#: os_unix.c:1477
+msgid "Opening the X display timed out"
+msgstr "Apertura visualizzazione X: tempo scaduto"
+
+#: os_unix.c:3234 os_unix.c:3914
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"Non riesco a eseguire shell "
+
+#: os_unix.c:3282
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Non riesco a eseguire shell sh\n"
+
+#: os_unix.c:3286 os_unix.c:3920
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"shell terminato con return-code "
+
+#: os_unix.c:3421
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Non posso creare 'pipe'\n"
+
+#: os_unix.c:3436
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"Non riesco ad effettuare 'fork'\n"
+
+#: os_unix.c:3927
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Comando terminato\n"
+
+#: os_unix.c:4191 os_unix.c:4316 os_unix.c:5982
+msgid "XSMP lost ICE connection"
+msgstr "XSMP ha perso la connessione ICE"
+
+#: os_unix.c:5565
+msgid "Opening the X display failed"
+msgstr "Apertura visualizzazione X fallita"
+
+#: os_unix.c:5887
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP gestione richiesta 'save-yourself'"
+
+#: os_unix.c:6006
+msgid "XSMP opening connection"
+msgstr "XSMP apertura connessione"
+
+#: os_unix.c:6025
+msgid "XSMP ICE connection watch failed"
+msgstr "XSMP osservazione connessione ICE fallita"
+
+#: os_unix.c:6045
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP SmcOpenConnection fallita: %s"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "Alla linea"
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "Non riesco ad allocare memoria per linea di comando."
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "Errore VIM"
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "Non riesco a caricare vim32.dll!"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Non sono riuscito a impostare puntatori di funzione verso la DLL!"
+
+#: os_win16.c:342 os_win32.c:3248
+#, c-format
+msgid "shell returned %d"
+msgstr "shell terminato con return-code %d"
+
+#: os_win32.c:2706
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Intercettato evento %s\n"
+
+#: os_win32.c:2708
+msgid "close"
+msgstr "chiusura"
+
+#: os_win32.c:2710
+msgid "logoff"
+msgstr "logoff"
+
+#: os_win32.c:2711
+msgid "shutdown"
+msgstr "shutdown"
+
+#: os_win32.c:3201
+msgid "E371: Command not found"
+msgstr "E371: Comando non trovato"
+
+#: os_win32.c:3214
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE non trovato nel tuo $PATH.\n"
+"I comandi esterni non farano una pausa dopo aver finito l'esecuzione.\n"
+"Vedi :help win32-vimrun per ulteriori informazioni."
+
+#: os_win32.c:3217
+msgid "Vim Warning"
+msgstr "Avviso da Vim"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Troppi %%%c nella stringa di 'format'"
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: %%%c imprevisto nella stringa di 'format'"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: Manca ] nella stringa di 'format'"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: %%%c non supportato nella stringa di 'format'"
+
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: %%%c non valido nel prefisso della stringa di 'format'"
+
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: %%%c non valido nella stringa di 'format'"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' non contiene alcun modello"
+
+#: quickfix.c:501
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Nome directory mancante o nullo"
+
+#: quickfix.c:990
+msgid "E553: No more items"
+msgstr "E553: Non ci sono più elementi"
+
+#: quickfix.c:1229
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d di %d)%s%s: "
+
+#: quickfix.c:1231
+msgid " (line deleted)"
+msgstr " (linea cancellata)"
+
+#: quickfix.c:1444
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Al fondo della 'stack' di quickfix"
+
+#: quickfix.c:1453
+msgid "E381: At top of quickfix stack"
+msgstr "E381: In cima alla 'stack' di quickfix"
+
+#: quickfix.c:1465
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "lista errori %d di %d; %d errori"
+
+#: quickfix.c:1943
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: Non posso scrivere, l'opzione 'buftype' è impostata"
+
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: elemento non valido in %s%%[]"
+
+#: regexp.c:838
+msgid "E339: Pattern too long"
+msgstr "E339: Espressione troppo lunga"
+
+#: regexp.c:1009
+msgid "E50: Too many \\z("
+msgstr "E50: Troppe \\z("
+
+#: regexp.c:1020
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: Troppe %s("
+
+#: regexp.c:1077
+msgid "E52: Unmatched \\z("
+msgstr "E52: Senza riscontro: \\z("
+
+#: regexp.c:1081
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: Senza riscontro: %s%%("
+
+#: regexp.c:1083
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: Senza riscontro: %s("
+
+#: regexp.c:1088
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: Senza riscontro: %s)"
+
+#: regexp.c:1258
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: l'operando %s* non può essere vuoto"
+
+#: regexp.c:1261
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: l'operando %s+ non può essere vuoto"
+
+#: regexp.c:1316
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: Carattere non ammesso dopo %s@"
+
+#: regexp.c:1344
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: l'operando %s{ potrebbe essere vuoto"
+
+#: regexp.c:1354
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: Troppi %s{...}s complessi"
+
+#: regexp.c:1370
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: %s* nidificato"
+
+#: regexp.c:1373
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: %s%c nidificato"
+
+#: regexp.c:1491
+msgid "E63: invalid use of \\_"
+msgstr "E63: uso non valido di \\_"
+
+#: regexp.c:1536
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c senza nulla prima"
+
+#: regexp.c:1592
+msgid "E65: Illegal back reference"
+msgstr "E65: Riferimento all'indietro non ammesso"
+
+#: regexp.c:1605
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z( non consentito qui"
+
+#: regexp.c:1624
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 et al. non consentiti qui"
+
+#: regexp.c:1635
+msgid "E68: Invalid character after \\z"
+msgstr "E68: Carattere non ammesso dopo \\z"
+
+#: regexp.c:1684
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: Manca ] dopo %s%%["
+
+#: regexp.c:1700
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: %s%%[] vuoto"
+
+#: regexp.c:1760
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: Carattere non ammesso dopo %s%%"
+
+#: regexp.c:2557
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: Errore sintattico in %s{...}"
+
+#: regexp.c:2863 regexp.c:3016
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Intercettata fine anormale; 'regexp' troppo complessa?"
+
+#: regexp.c:3004 regexp.c:3013
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: errore di supero-capacità-stack causato da espressione"
+
+#: regexp.c:3258
+msgid "External submatches:\n"
+msgstr "Sotto-corrispondenze esterne:\n"
+
+#: screen.c:2184
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld linee piegate"
+
+#: screen.c:7996
+msgid " VREPLACE"
+msgstr " V-SOSTITUISCI"
+
+#: screen.c:8000
+msgid " REPLACE"
+msgstr " SOSTITUISCI"
+
+#: screen.c:8005
+msgid " REVERSE"
+msgstr " INVERTITO"
+
+#: screen.c:8007
+msgid " INSERT"
+msgstr " INSERISCI"
+
+#: screen.c:8010
+msgid " (insert)"
+msgstr " (inserisci)"
+
+#: screen.c:8012
+msgid " (replace)"
+msgstr " (sostituisci)"
+
+#: screen.c:8014
+msgid " (vreplace)"
+msgstr " (v-sostituisci)"
+
+#: screen.c:8017
+msgid " Hebrew"
+msgstr " Ebraico"
+
+#: screen.c:8028
+msgid " Arabic"
+msgstr " Arabo"
+
+#: screen.c:8031
+msgid " (lang)"
+msgstr " (lingua)"
+
+#: screen.c:8035
+msgid " (paste)"
+msgstr " (incolla)"
+
+#: screen.c:8048
+msgid " VISUAL"
+msgstr " VISUALE"
+
+#: screen.c:8049
+msgid " VISUAL LINE"
+msgstr " VISUALE LINEA"
+
+#: screen.c:8050
+msgid " VISUAL BLOCK"
+msgstr " VISUALE BLOCCO"
+
+#: screen.c:8051
+msgid " SELECT"
+msgstr " SELEZIONA"
+
+#: screen.c:8052
+msgid " SELECT LINE"
+msgstr " SELEZIONA LINEA"
+
+#: screen.c:8053
+msgid " SELECT BLOCK"
+msgstr " SELEZIONA BLOCCO"
+
+#: screen.c:8068 screen.c:8131
+msgid "recording"
+msgstr "registrazione"
+
+#: search.c:37
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "raggiunta la CIMA nella ricerca, continuo dal FONDO"
+
+#: search.c:38
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "raggiunto il FONDO nella ricerca, continuo dalla CIMA"
+
+#: search.c:526
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Stringa di ricerca non valida: %s"
+
+#: search.c:853
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: la ricerca ha raggiunto la CIMA senza successo per: %s"
+
+#: search.c:856
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: la ricerca ha raggiunto il FONDO senza successo per: %s"
+
+#: search.c:1249
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: '?' o '/' atteso dopo ';'"
+
+#: search.c:3768
+msgid " (includes previously listed match)"
+msgstr " (comprese corrispondenze elencate prima)"
+
+#. cursor at status line
+#: search.c:3788
+msgid "--- Included files "
+msgstr "--- File inclusi "
+
+#: search.c:3790
+msgid "not found "
+msgstr "non trovati "
+
+#: search.c:3791
+msgid "in path ---\n"
+msgstr "nel percorso ---\n"
+
+#: search.c:3848
+msgid " (Already listed)"
+msgstr " (Già elencati)"
+
+#: search.c:3850
+msgid " NOT FOUND"
+msgstr " NON TROVATO"
+
+#: search.c:3902
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Scandisco file incluso: %s"
+
+#: search.c:4120
+msgid "E387: Match is on current line"
+msgstr "E387: Corrispondenza nella linea corrente"
+
+#: search.c:4263
+msgid "All included files were found"
+msgstr "Tutti i file inclusi sono stati trovati"
+
+#: search.c:4265
+msgid "No included files"
+msgstr "Nessun file incluso"
+
+#: search.c:4281
+msgid "E388: Couldn't find definition"
+msgstr "E388: Non sono riuscito a trovare la definizione"
+
+#: search.c:4283
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Non son riuscito a trovare il modello"
+
+#: syntax.c:3050
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: Argomento non ammesso: %s"
+
+#: syntax.c:3230
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: 'cluster' sintattico inesistente: %s"
+
+#: syntax.c:3394
+msgid "No Syntax items defined for this buffer"
+msgstr "Nessun elemento sintattico definito per questo buffer"
+
+#: syntax.c:3402
+msgid "syncing on C-style comments"
+msgstr "sincronizzo i commenti nello stile C"
+
+#: syntax.c:3410
+msgid "no syncing"
+msgstr "nessuna ssincronizzazione"
+
+#: syntax.c:3413
+msgid "syncing starts "
+msgstr "la sincronizzazione inizia "
+
+#: syntax.c:3415 syntax.c:3490
+msgid " lines before top line"
+msgstr " linee prima della linea iniziale"
+
+#: syntax.c:3420
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Elementi sincronizzazione sintassi ---"
+
+#: syntax.c:3425
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"sincronizzo elementi"
+
+#: syntax.c:3431
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Elementi sintattici ---"
+
+#: syntax.c:3454
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: 'cluster' sintattico inesistente: %s"
+
+#: syntax.c:3480
+msgid "minimal "
+msgstr "minimale "
+
+#: syntax.c:3487
+msgid "maximal "
+msgstr "massimale "
+
+#: syntax.c:3499
+msgid "; match "
+msgstr "; corrisp. "
+
+#: syntax.c:3501
+msgid " line breaks"
+msgstr " interruzioni di linea"
+
+#: syntax.c:4135
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: group[t]here non ammesso qui"
+
+#: syntax.c:4159
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: Elemento di 'region' non trovato per %s"
+
+#: syntax.c:4187
+msgid "E395: contains argument not accepted here"
+msgstr "E395: contiene argomenti non accettati qui"
+
+#: syntax.c:4198
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: argomento 'containedin' non accettato qui"
+
+#: syntax.c:4276
+msgid "E397: Filename required"
+msgstr "E397: Nome file necessario"
+
+#: syntax.c:4614
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Manca '=': %s"
+
+#: syntax.c:4772
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Argomenti non sufficienti per: 'syntax region' %s"
+
+#: syntax.c:5103
+msgid "E400: No cluster specified"
+msgstr "E400: Nessun 'cluster' specificato"
+
+#: syntax.c:5140
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Delimitatore di espressione non trovato: %s"
+
+#: syntax.c:5215
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Spazzatura dopo espressione: %s"
+
+#: syntax.c:5305
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr ""
+"E403: syntax sync: espressione di continuazione linea specificata due volte"
+
+#: syntax.c:5362
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Argomenti non validi: %s"
+
+#: syntax.c:5412
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Manca '=': %s"
+
+#: syntax.c:5418
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Argomento nullo: %s"
+
+#: syntax.c:5445
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s non consentito qui"
+
+#: syntax.c:5452
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s deve venire per primo nella lista 'contains'"
+
+#: syntax.c:5522
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Nome gruppo sconosciuto: %s"
+
+#: syntax.c:5755
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Sotto-comando :syntax non valido: %s"
+
+#: syntax.c:6136
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: gruppo evidenziazione non trovato: %s"
+
+#: syntax.c:6160
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Argomenti non sufficienti: \":highlight link %s\""
+
+#: syntax.c:6167
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: Troppi argomenti: \":highlight link %s\""
+
+#: syntax.c:6187
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: 'group' ha impostazioni, 'highlight link' ignorato"
+
+#: syntax.c:6316
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: segno '=' inatteso: %s"
+
+#: syntax.c:6352
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: manca segno '=': %s"
+
+#: syntax.c:6380
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: manca argomento: %s"
+
+#: syntax.c:6417
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: Valore non ammesso: %s"
+
+#: syntax.c:6536
+msgid "E419: FG color unknown"
+msgstr "E419: colore di testo sconosciuto"
+
+#: syntax.c:6547
+msgid "E420: BG color unknown"
+msgstr "E420: colore di sfondo sconosciuto"
+
+#: syntax.c:6608
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Numero o nome di colore non riconosciuto: %s"
+
+#: syntax.c:6814
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: codice terminale troppo lungo: %s"
+
+#: syntax.c:6861
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: Argomento non ammesso: %s"
+
+#: syntax.c:7390
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: Troppi gruppi evidenziazione differenti in uso"
+
+#: syntax.c:7911
+msgid "E669: Unprintable character in group name"
+msgstr "E669: Carattere non stampabile in un nome di gruppo"
+
+#. This is an error, but since there previously was no check only
+#. * give a warning.
+#: syntax.c:7918
+msgid "W18: Invalid character in group name"
+msgstr "W18: Carattere non ammesso in un nome di gruppo"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: al fondo della 'stack' delle tag"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: in cima alla 'stack' delle tag"
+
+#: tag.c:412
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Non posso andare prima della prima tag corrispondente"
+
+#: tag.c:550
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: tag non trovata: %s"
+
+#: tag.c:583
+msgid " # pri kind tag"
+msgstr " # pri tipo tag"
+
+#: tag.c:586
+msgid "file\n"
+msgstr "file\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:744
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Batti n. di scelta (<INVIO> per lasciar perdere): "
+
+#: tag.c:784
+msgid "E427: There is only one matching tag"
+msgstr "E427: C'è solo una tag corrispondente"
+
+#: tag.c:786
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Non posso andare oltre l'ultima tag corrispondente"
+
+#: tag.c:810
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Il file \"%s\" non esiste"
+
+#. Give an indication of the number of matching tags
+#: tag.c:823
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "tag %d di %d%s"
+
+#: tag.c:826
+msgid " or more"
+msgstr " o più"
+
+#: tag.c:828
+msgid " Using tag with different case!"
+msgstr " Uso tag ignorando maiuscole/minuscole!"
+
+#: tag.c:872
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Il file \"%s\" non esiste"
+
+#. Highlight title
+#: tag.c:941
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # A tag DA__ linea in file/testo"
+
+#: tag.c:1363
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Ricerca nel tag file %s"
+
+#: tag.c:1550
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Percorso tag file troncato per %s\n"
+
+#: tag.c:2203
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Errore di formato nel tag file \"%s\""
+
+#: tag.c:2207
+#, c-format
+msgid "Before byte %ld"
+msgstr "Prima del byte %ld"
+
+#: tag.c:2240
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Tag file non ordinato alfabeticamente: %s"
+
+#. never opened any tags file
+#: tag.c:2280
+msgid "E433: No tags file"
+msgstr "E433: Nessun tag file"
+
+#: tag.c:3016
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Non riesco a trovare modello tag"
+
+#: tag.c:3027
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Non riesco a trovare tag, sto solo tirando a indovinare!"
+
+#: term.c:1759
+msgid "' not known. Available builtin terminals are:"
+msgstr "' non noto. Terminali disponibili predisposti sono:"
+
+#: term.c:1783
+msgid "defaulting to '"
+msgstr "predefinito a '"
+
+#: term.c:2141
+msgid "E557: Cannot open termcap file"
+msgstr "E557: Non posso aprire file 'termcap'"
+
+#: term.c:2145
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: Descrizione terminale non trovata in 'terminfo'"
+
+#: term.c:2147
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: Descrizione terminale non trovata in 'termcap'"
+
+#: term.c:2306
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Nessuna descrizione per \"%s\" in 'termcap'"
+
+#: term.c:2780
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: capacità \"cm\" del terminale necessaria"
+
+#. Highlight title
+#: term.c:4990
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Tasti Terminale ---"
+
+#: ui.c:258
+msgid "new shell started\n"
+msgstr "fatto eseguire nuovo shell\n"
+
+#: ui.c:1841
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: Errore leggendo l'input, esco...\n"
+
+#. must display the prompt
+#: undo.c:405
+msgid "No undo possible; continue anyway"
+msgstr "'undo' non più possibile; continuo comunque"
+
+#: undo.c:561
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: numeri linee errati"
+
+#: undo.c:757
+msgid "1 change"
+msgstr "1 modifica"
+
+#: undo.c:759
+#, c-format
+msgid "%ld changes"
+msgstr "%ld modifiche"
+
+#: undo.c:812
+msgid "E439: undo list corrupt"
+msgstr "E439: lista 'undo' non valida"
+
+#: undo.c:844
+msgid "E440: undo line missing"
+msgstr "E440: linea di 'undo' mancante"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:759
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"versione MS-Windows 16/32 bit GUI"
+
+#: version.c:761
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"Versione MS-Windows 32 bit GUI"
+
+#: version.c:764
+msgid " in Win32s mode"
+msgstr " in modalità Win32s"
+
+#: version.c:766
+msgid " with OLE support"
+msgstr " con supporto OLE"
+
+#: version.c:769
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"Versione MS-Windows 32 bit console"
+
+#: version.c:773
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"Versione MS-Windows 16 bit"
+
+#: version.c:777
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"Version MS-DOS 32 bit"
+
+#: version.c:779
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"Versione MS-DOS 16 bit"
+
+#: version.c:785
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"Versione MacOS X (unix)"
+
+#: version.c:787
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"Versione X MacOS"
+
+#: version.c:790
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"Versione MacOS"
+
+#: version.c:795
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"Versione RISC OS"
+
+#: version.c:805
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Patch incluse: "
+
+#: version.c:831 version.c:1199
+msgid "Modified by "
+msgstr "Modificato da "
+
+#: version.c:838
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Compilato "
+
+#: version.c:841
+msgid "by "
+msgstr "da "
+
+#: version.c:853
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Versione gigante "
+
+#: version.c:856
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Versione grande "
+
+#: version.c:859
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Versione normale "
+
+#: version.c:862
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Versione piccola "
+
+#: version.c:864
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Versione minuscola "
+
+#: version.c:870
+msgid "without GUI."
+msgstr "senza GUI."
+
+#: version.c:875
+msgid "with GTK2-GNOME GUI."
+msgstr "con GUI GTK2-GNOME."
+
+#: version.c:877
+msgid "with GTK-GNOME GUI."
+msgstr "con GUI GTK-GNOME."
+
+#: version.c:881
+msgid "with GTK2 GUI."
+msgstr "con GUI GTK2."
+
+#: version.c:883
+msgid "with GTK GUI."
+msgstr "con GUI GTK."
+
+#: version.c:888
+msgid "with X11-Motif GUI."
+msgstr "con GUI X11-Motif."
+
+#: version.c:892
+msgid "with X11-neXtaw GUI."
+msgstr "con GUI X11-neXtaw."
+
+#: version.c:894
+msgid "with X11-Athena GUI."
+msgstr "con GUI X11-Athena."
+
+#: version.c:898
+msgid "with BeOS GUI."
+msgstr "con GUI BeOS."
+
+#: version.c:901
+msgid "with Photon GUI."
+msgstr "con GUI Photon."
+
+#: version.c:904
+msgid "with GUI."
+msgstr "con GUI."
+
+#: version.c:907
+msgid "with Carbon GUI."
+msgstr "con GUI Carbon."
+
+#: version.c:910
+msgid "with Cocoa GUI."
+msgstr "con GUI Cocoa."
+
+#: version.c:913
+msgid "with (classic) GUI."
+msgstr "con GUI (classica)."
+
+#: version.c:924
+msgid " Features included (+) or not (-):\n"
+msgstr " Opzioni incluse (+) o escluse (-):\n"
+
+#: version.c:936
+msgid " system vimrc file: \""
+msgstr " file vimrc di sistema: \""
+
+#: version.c:941
+msgid " user vimrc file: \""
+msgstr " file vimrc utente: \""
+
+#: version.c:946
+msgid " 2nd user vimrc file: \""
+msgstr " II file vimrc utente: \""
+
+#: version.c:951
+msgid " 3rd user vimrc file: \""
+msgstr " III file vimrc utente: \""
+
+#: version.c:956
+msgid " user exrc file: \""
+msgstr " file exrc utente: \""
+
+#: version.c:961
+msgid " 2nd user exrc file: \""
+msgstr " II file exrc utente: \""
+
+#: version.c:967
+msgid " system gvimrc file: \""
+msgstr " file gvimrc di sistema: \""
+
+#: version.c:971
+msgid " user gvimrc file: \""
+msgstr " file gvimrc utente: \""
+
+#: version.c:975
+msgid "2nd user gvimrc file: \""
+msgstr " II file gvimrc utente: \""
+
+#: version.c:980
+msgid "3rd user gvimrc file: \""
+msgstr " III file gvimrc utente: \""
+
+#: version.c:987
+msgid " system menu file: \""
+msgstr " file menu di sistema: \""
+
+#: version.c:995
+msgid " fall-back for $VIM: \""
+msgstr " $VIM di riserva: \""
+
+#: version.c:1001
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " $VIMRUNTIME di riserva: \""
+
+#: version.c:1005
+msgid "Compilation: "
+msgstr "Compilazione: "
+
+#: version.c:1011
+msgid "Compiler: "
+msgstr "Compilatore: "
+
+#: version.c:1016
+msgid "Linking: "
+msgstr "Link: "
+
+#: version.c:1021
+msgid " DEBUG BUILD"
+msgstr " VERSIONE DEBUG"
+
+#: version.c:1060
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved (VI Migliorato)"
+
+#: version.c:1062
+msgid "version "
+msgstr "versione "
+
+#: version.c:1063
+msgid "by Bram Moolenaar et al."
+msgstr "di Bram Moolenaar et al."
+
+#: version.c:1067
+msgid "Vim is open source and freely distributable"
+msgstr "Vim è 'open source' e può essere distribuito liberamente"
+
+#: version.c:1069
+msgid "Help poor children in Uganda!"
+msgstr "Aiuta i bambini poveri dell'Uganda!"
+
+#: version.c:1070
+msgid "type :help iccf<Enter> for information "
+msgstr "batti :help iccf<Invio> per informazioni "
+
+#: version.c:1072
+msgid "type :q<Enter> to exit "
+msgstr "batti :q<Invio> per uscire "
+
+#: version.c:1073
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "batti :help<Invio> o <F1> per aiuto online "
+
+#: version.c:1074
+msgid "type :help version6<Enter> for version info"
+msgstr "batti :help version6<Invio> per informazioni su versione"
+
+#: version.c:1077
+msgid "Running in Vi compatible mode"
+msgstr "Eseguo in modalità compatibile Vi"
+
+#: version.c:1078
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "batti :set nocp<Invio> per valori predefiniti Vim"
+
+#: version.c:1079
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "batti :help cp-default<Enter> per info al riguardo"
+
+#: version.c:1094
+msgid "menu Help->Orphans for information "
+msgstr "menu Aiuto->Orfani per informazioni "
+
+#: version.c:1096
+msgid "Running modeless, typed text is inserted"
+msgstr "Esecuzione senza modalità: solo inserimento"
+
+#: version.c:1097
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "menu Modifica->Impost.Globali->Modal.Inser. Sì/No"
+
+#: version.c:1098
+msgid " for two modes "
+msgstr " per modo Inser./Comandi"
+
+#: version.c:1102
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "menu Modifica->Impost.Globali->Compatibile Vi Sì/No"
+
+#: version.c:1103
+msgid " for Vim defaults "
+msgstr " modo Vim predefinito "
+
+#: version.c:1150
+msgid "Sponsor Vim development!"
+msgstr "Sponsorizza lo sviluppo di Vim!"
+
+#: version.c:1151
+msgid "Become a registered Vim user!"
+msgstr "Diventa un utente Vim registrato!"
+
+#: version.c:1154
+msgid "type :help sponsor<Enter> for information "
+msgstr "batti :help sponsor<Invio> per informazioni "
+
+#: version.c:1155
+msgid "type :help register<Enter> for information "
+msgstr "batti :help register<Invio> per informazioni "
+
+#: version.c:1157
+msgid "menu Help->Sponsor/Register for information "
+msgstr "menu Aiuto->Sponsor/Registrazione per informazioni "
+
+#: version.c:1167
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "ATTENZIONE: Trovato Windows 95/98/ME"
+
+#: version.c:1170
+msgid "type :help windows95<Enter> for info on this"
+msgstr "batti :help windows95<Enter> per info al riguardo"
+
+#: window.c:203
+msgid "E441: There is no preview window"
+msgstr "E441: Non c'è una finestra di pre-visualizzazione"
+
+#: window.c:581
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: Non riesco a dividere ALTO-SX e BASSO-DX contemporaneamente"
+
+#: window.c:1340
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Non posso ruotare quando un'altra finestra è divisa in due"
+
+#: window.c:1836
+msgid "E444: Cannot close last window"
+msgstr "E444: Non riesco a chiudere l'ultima finestra"
+
+#: window.c:2567
+msgid "Already only one window"
+msgstr "C'è già una finestra sola"
+
+#: window.c:2614
+msgid "E445: Other window contains changes"
+msgstr "E445: Altre finestre contengono modifiche"
+
+#: window.c:4480
+msgid "E446: No file name under cursor"
+msgstr "E446: Nessun nome file sotto il cursore"
+
+#: window.c:4599
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Non riesco a trovare il file \"%s\" nel percorso"
+
+#: if_perl.xs:326 globals.h:1241
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: Non posso caricare la libreria %s"
+
+#: if_perl.xs:554
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr ""
+"Spiacente, comando non disponibile, non riesco a caricare libreria programmi "
+"Perl."
+
+#: if_perl.xs:607
+msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+msgstr ""
+"E299: Valorizzazione Perl vietata in ambiente protetto senza il modulo Safe"
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "Apri con &molti Vim"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "Apri con un solo &Vim"
+
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "&Differenza con Vim"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "Apri con &Vim"
+
+#. Now concatenate
+#: GvimExt/gvimext.cpp:633
+msgid "Edit with existing Vim - &"
+msgstr "Apri con Vim esistente - &"
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "Apri i(l) file scelto(i) con Vim"
+
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr ""
+"Errore creando il processo: Controllate che gvim sia incluso nel vostro "
+"cammino (PATH)"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "errore gvimext.dll"
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "Percorso file troppo lungo!"
+
+#: globals.h:1031
+msgid "--No lines in buffer--"
+msgstr "--File vuoto--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1194
+msgid "E470: Command aborted"
+msgstr "E470: Comando finito male"
+
+#: globals.h:1195
+msgid "E471: Argument required"
+msgstr "E471: Argomento necessario"
+
+#: globals.h:1196
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ dovrebbe essere seguito da /, ? oppure &"
+
+#: globals.h:1198
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: Non valido nella finestra comandi; <INVIO> esegue, CTRL-C ignora"
+
+#: globals.h:1200
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Comando non ammesso da exrc/vimrc nella dir. in uso o nella ricerca tag"
+
+#: globals.h:1202
+msgid "E171: Missing :endif"
+msgstr "E171: Manca :endif"
+
+#: globals.h:1203
+msgid "E600: Missing :endtry"
+msgstr "E600: Manca :endtry"
+
+#: globals.h:1204
+msgid "E170: Missing :endwhile"
+msgstr "E170: Manca :endwhile"
+
+#: globals.h:1205
+msgid "E588: :endwhile without :while"
+msgstr "E588: :endwhile senza :while"
+
+#: globals.h:1207
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: File esistente (aggiungi ! per riscriverlo)"
+
+#: globals.h:1208
+msgid "E472: Command failed"
+msgstr "E472: Comando fallito"
+
+#: globals.h:1210
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Fontset sconosciuto: %s"
+
+#: globals.h:1214
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Font sconosciuto: %s"
+
+#: globals.h:1217
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: Font \"%s\" non di larghezza fissa"
+
+#: globals.h:1219
+msgid "E473: Internal error"
+msgstr "E473: Errore interno"
+
+#: globals.h:1220
+msgid "Interrupted"
+msgstr "Interrotto"
+
+#: globals.h:1221
+msgid "E14: Invalid address"
+msgstr "E14: Indirizzo non valido"
+
+#: globals.h:1222
+msgid "E474: Invalid argument"
+msgstr "E474: Argomento non valido"
+
+#: globals.h:1223
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: Argomento non valido: %s"
+
+#: globals.h:1225
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Espressione non valida: %s"
+
+#: globals.h:1227
+msgid "E16: Invalid range"
+msgstr "E16: Intervallo non valido"
+
+#: globals.h:1228
+msgid "E476: Invalid command"
+msgstr "E476: Comando non valido"
+
+#: globals.h:1230
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" è una directory"
+
+#: globals.h:1233
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Caratteri non previsti prima di '='"
+
+#: globals.h:1236
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Chiamata a libreria fallita per \"%s()\""
+
+#: globals.h:1242
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: Non posso caricare la funzione di libreria %s"
+
+#: globals.h:1244
+msgid "E19: Mark has invalid line number"
+msgstr "E19: 'Mark' con numero linea non valido"
+
+#: globals.h:1245
+msgid "E20: Mark not set"
+msgstr "E20: 'Mark' non impostato"
+
+#: globals.h:1246
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Non posso fare modifiche, 'modifiable' è inibito"
+
+#: globals.h:1247
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Script troppo nidificati"
+
+#: globals.h:1248
+msgid "E23: No alternate file"
+msgstr "E23: Nessun file alternato"
+
+#: globals.h:1249
+msgid "E24: No such abbreviation"
+msgstr "E24: Abbreviazione inesistente"
+
+#: globals.h:1250
+msgid "E477: No ! allowed"
+msgstr "E477: ! non consentito"
+
+#: globals.h:1252
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: GUI non utilizzabile: Non abilitata in compilazione"
+
+#: globals.h:1255
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: Ebraico non utilizzabile: Non abilitato in compilazione\n"
+
+#: globals.h:1258
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: Farsi non utilizzabile: Non abilitato in compilazione\n"
+
+#: globals.h:1261
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: Arabo non utilizzabile: Non abilitato in compilazione\n"
+
+#: globals.h:1264
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Nome di gruppo di evidenziazione inesistente: %s"
+
+#: globals.h:1266
+msgid "E29: No inserted text yet"
+msgstr "E29: Ancora nessun testo inserito"
+
+#: globals.h:1267
+msgid "E30: No previous command line"
+msgstr "E30: Nessuna linea comandi precedente"
+
+#: globals.h:1268
+msgid "E31: No such mapping"
+msgstr "E31: Mapping inesistente"
+
+#: globals.h:1269
+msgid "E479: No match"
+msgstr "E479: Nessuna corrispondenza"
+
+#: globals.h:1270
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: Nessuna corrispondenza: %s"
+
+#: globals.h:1271
+msgid "E32: No file name"
+msgstr "E32: Manca nome file"
+
+#: globals.h:1272
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: Nessuna espressione regolare precedente di 'substitute'"
+
+#: globals.h:1273
+msgid "E34: No previous command"
+msgstr "E34: Nessun comando precedente"
+
+#: globals.h:1274
+msgid "E35: No previous regular expression"
+msgstr "E35: Nessuna espressione regolare precedente"
+
+#: globals.h:1275
+msgid "E481: No range allowed"
+msgstr "E481: Nessun intervallo consentito"
+
+#: globals.h:1277
+msgid "E36: Not enough room"
+msgstr "E36: Manca spazio"
+
+#: globals.h:1280
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: non esiste server registrato con nome \"%s\""
+
+#: globals.h:1282
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: Non riesco a creare il file %s"
+
+#: globals.h:1283
+msgid "E483: Can't get temp file name"
+msgstr "E483: Non riesco ad ottenere nome file 'temp'"
+
+#: globals.h:1284
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: Non riesco ad aprire il file %s"
+
+#: globals.h:1285
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: Non riesco a leggere il file %s"
+
+#: globals.h:1286
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: Non salvato dopo modifica (aggiungi ! per eseguire comunque)"
+
+#: globals.h:1287
+msgid "E38: Null argument"
+msgstr "E38: Argomento nullo"
+
+#: globals.h:1289
+msgid "E39: Number expected"
+msgstr "E39: Mi aspettavo un numero"
+
+#: globals.h:1292
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Non riesco ad aprire il file errori %s"
+
+#: globals.h:1295
+msgid "E233: cannot open display"
+msgstr "E233: non riesco ad aprire lo schermo"
+
+#: globals.h:1297
+msgid "E41: Out of memory!"
+msgstr "E41: Non c'è più memoria!"
+
+#: globals.h:1299
+msgid "Pattern not found"
+msgstr "Espressione non trovata"
+
+#: globals.h:1301
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: Espressione non trovata: %s"
+
+#: globals.h:1302
+msgid "E487: Argument must be positive"
+msgstr "E487: L'argomento deve essere positivo"
+
+#: globals.h:1304
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: Non posso tornare alla directory precedente"
+
+#: globals.h:1308
+msgid "E42: No Errors"
+msgstr "E42: Nessun Errore"
+
+#: globals.h:1310
+msgid "E43: Damaged match string"
+msgstr "E43: Stringa di confronto danneggiata"
+
+#: globals.h:1311
+msgid "E44: Corrupted regexp program"
+msgstr "E44: Programma 'regexp' corrotto"
+
+#: globals.h:1312
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: file in sola lettura (aggiungi ! per eseguire comunque)"
+
+#: globals.h:1314
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Non posso impostare la variabile read-only \"%s\""
+
+#: globals.h:1317
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Errore leggendo il file errori"
+
+#: globals.h:1320
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: Non ammesso in ambiente protetto"
+
+#: globals.h:1322
+msgid "E523: Not allowed here"
+msgstr "E523: Non consentito qui"
+
+#: globals.h:1325
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Impostazione modalità schermo non supportata"
+
+#: globals.h:1327
+msgid "E49: Invalid scroll size"
+msgstr "E49: Quantità di 'scroll' non valida"
+
+#: globals.h:1328
+msgid "E91: 'shell' option is empty"
+msgstr "E91: opzione 'shell' vuota"
+
+#: globals.h:1330
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Errore -- non sono riuscito a leggere i dati del 'sign'!"
+
+#: globals.h:1332
+msgid "E72: Close error on swap file"
+msgstr "E72: Errore durante chiusura swap file"
+
+#: globals.h:1333
+msgid "E73: tag stack empty"
+msgstr "E73: tag stack vuota"
+
+#: globals.h:1334
+msgid "E74: Command too complex"
+msgstr "E74: Comando troppo complesso"
+
+#: globals.h:1335
+msgid "E75: Name too long"
+msgstr "E75: Nome troppo lungo"
+
+#: globals.h:1336
+msgid "E76: Too many ["
+msgstr "E76: Troppe ["
+
+#: globals.h:1337
+msgid "E77: Too many file names"
+msgstr "E77: Troppi nomi file"
+
+#: globals.h:1338
+msgid "E488: Trailing characters"
+msgstr "E488: Caratteri in più a fine comando"
+
+#: globals.h:1339
+msgid "E78: Unknown mark"
+msgstr "E78: 'Mark' sconosciuto"
+
+#: globals.h:1340
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Non posso espandere 'wildcard'"
+
+#: globals.h:1342
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: 'winheight' non può essere inferiore a 'winminheight'"
+
+#: globals.h:1344
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: 'winwidth' non può essere inferiore a 'winminwidth'"
+
+#: globals.h:1347
+msgid "E80: Error while writing"
+msgstr "E80: Errore in scrittura"
+
+#: globals.h:1348
+msgid "Zero count"
+msgstr "Contatore a zero"
+
+#: globals.h:1350
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: Uso di <SID> fuori dal contesto di uno script"
+
+#: globals.h:1353
+msgid "E449: Invalid expression received"
+msgstr "E449: Ricevuta un'espressione non valida"
+
+#: globals.h:1356
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: Regione protetta, impossibile modificare"
diff --git a/src/po/ja.po b/src/po/ja.po
new file mode 100644
index 000000000..17d94d516
--- /dev/null
+++ b/src/po/ja.po
@@ -0,0 +1,6587 @@
+# Japanese translation for Vim vim:set foldmethod=marker:
+#
+# Do ":help uganda" in Vim to read copying and usage conditions.
+# Do ":help credits" in Vim to see a list of people who contributed.
+#
+# MURAOKA Taro <koron@tka.att.ne.jp>, 2001-4.
+# Last Change: 29-Apr-2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim 6.2\n"
+"POT-Creation-Date: 2004-04-29 13:16+0900\n"
+"PO-Revision-Date: 2004-04-29 13:00+0900\n"
+"Last-Translator: MURAOKA Taro <koron@tka.att.ne.jp>\n"
+"Language-Team: MURAOKA Taro <koron@tka.att.ne.jp>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=euc-jp\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: buffer.c:102
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: ¥Ð¥Ã¥Õ¥¡¤ò1¤Ä¤âºîÀ®¤Ç¤­¤Ê¤¤¤Î¤Ç, ½ªÎ»¤·¤Þ¤¹..."
+
+#: buffer.c:105
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: ¥Ð¥Ã¥Õ¥¡¤òºîÀ®¤Ç¤­¤Ê¤¤¤Î¤Ç, ¾¤Î¤ò»ÈÍѤ·¤Þ¤¹..."
+
+#: buffer.c:805
+msgid "E515: No buffers were unloaded"
+msgstr "E515: ²òÊü¤µ¤ì¤¿¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: buffer.c:807
+msgid "E516: No buffers were deleted"
+msgstr "E516: ºï½ü¤µ¤ì¤¿¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: buffer.c:809
+msgid "E517: No buffers were wiped out"
+msgstr "E517: ÇË´þ¤µ¤ì¤¿¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: buffer.c:817
+msgid "1 buffer unloaded"
+msgstr "1 ¸Ä¤Î¥Ð¥Ã¥Õ¥¡¤¬²òÊü¤µ¤ì¤Þ¤·¤¿"
+
+#: buffer.c:819
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "%d ¸Ä¤Î¥Ð¥Ã¥Õ¥¡¤¬²òÊü¤µ¤ì¤Þ¤·¤¿"
+
+#: buffer.c:824
+msgid "1 buffer deleted"
+msgstr "1 ¸Ä¤Î¥Ð¥Ã¥Õ¥¡¤¬ºï½ü¤µ¤ì¤Þ¤·¤¿"
+
+#: buffer.c:826
+#, c-format
+msgid "%d buffers deleted"
+msgstr "%d ¸Ä¤Î¥Ð¥Ã¥Õ¥¡¤¬ºï½ü¤µ¤ì¤Þ¤·¤¿"
+
+#: buffer.c:831
+msgid "1 buffer wiped out"
+msgstr "1 ¸Ä¤Î¥Ð¥Ã¥Õ¥¡¤¬ÇË´þ¤µ¤ì¤Þ¤·¤¿"
+
+#: buffer.c:833
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "%d ¸Ä¤Î¥Ð¥Ã¥Õ¥¡¤¬ÇË´þ¤µ¤ì¤Þ¤·¤¿"
+
+#: buffer.c:894
+msgid "E84: No modified buffer found"
+msgstr "E84: Êѹ¹¤µ¤ì¤¿¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#. back where we started, didn't find anything.
+#: buffer.c:933
+msgid "E85: There is no listed buffer"
+msgstr "E85: ¥ê¥¹¥Èɽ¼¨¤µ¤ì¤ë¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: buffer.c:945
+#, c-format
+msgid "E86: Buffer %ld does not exist"
+msgstr "E86: ¥Ð¥Ã¥Õ¥¡ %ld ¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: buffer.c:948
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: ºÇ¸å¤Î¥Ð¥Ã¥Õ¥¡¤ò±Û¤¨¤Æ°ÜÆ°¤Ï¤Ç¤­¤Þ¤»¤ó"
+
+#: buffer.c:950
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: ºÇ½é¤Î¥Ð¥Ã¥Õ¥¡¤è¤êÁ°¤Ø¤Ï°ÜÆ°¤Ç¤­¤Þ¤»¤ó"
+
+#: buffer.c:988
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr "E89: ¥Ð¥Ã¥Õ¥¡ %ld ¤ÎÊѹ¹¤ÏÊݸ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó (! ¤ÇÊѹ¹¤òÇË´þ)"
+
+#: buffer.c:1005
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: ºÇ¸å¤Î¥Ð¥Ã¥Õ¥¡¤Ï²òÊü¤Ç¤­¤Þ¤»¤ó"
+
+#: buffer.c:1538
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: ·Ù¹ð: ¥Õ¥¡¥¤¥ë̾¤Î¥ê¥¹¥È¤¬Ä¹¤¹¤®¤Þ¤¹"
+
+#: buffer.c:1709
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: ¥Ð¥Ã¥Õ¥¡ %ld ¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: buffer.c:1940
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: %s ¤ËÊ£¿ô¤Î³ºÅö¤¬¤¢¤ê¤Þ¤·¤¿"
+
+#: buffer.c:1942
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: %s ¤Ë³ºÅö¤¹¤ë¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: buffer.c:2337
+#, c-format
+msgid "line %ld"
+msgstr "¹Ô %ld"
+
+#: buffer.c:2420
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: ¤³¤Î̾Á°¤Î¥Ð¥Ã¥Õ¥¡¤Ï´û¤Ë¤¢¤ê¤Þ¤¹"
+
+#: buffer.c:2713
+msgid " [Modified]"
+msgstr " [Êѹ¹¤¢¤ê]"
+
+#: buffer.c:2718
+msgid "[Not edited]"
+msgstr "[̤ÊÔ½¸]"
+
+#: buffer.c:2723
+msgid "[New file]"
+msgstr "[¿·¥Õ¥¡¥¤¥ë]"
+
+#: buffer.c:2724
+msgid "[Read errors]"
+msgstr "[Æɹþ¥¨¥é¡¼]"
+
+#: buffer.c:2726 fileio.c:2049
+msgid "[readonly]"
+msgstr "[ÆɹþÀìÍÑ]"
+
+#: buffer.c:2747
+msgid "1 line --%d%%--"
+msgstr "1 ¹Ô --%d%%--"
+
+#: buffer.c:2749
+msgid "%ld lines --%d%%--"
+msgstr "%ld ¹Ô --%d%%--"
+
+#: buffer.c:2756
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "¹Ô %ld (Á´ÂÎ %ld) --%d%%-- col "
+
+#: buffer.c:2864
+msgid "[No file]"
+msgstr "[̵Âê]"
+
+#. must be a help buffer
+#: buffer.c:2904
+msgid "help"
+msgstr "¥Ø¥ë¥×"
+
+#: buffer.c:3463 screen.c:5038
+msgid "[help]"
+msgstr "[¥Ø¥ë¥×]"
+
+#: buffer.c:3495 screen.c:5044
+msgid "[Preview]"
+msgstr "[¥×¥ì¥Ó¥å¡¼]"
+
+#: buffer.c:3775
+msgid "All"
+msgstr "Á´¤Æ"
+
+#: buffer.c:3775
+msgid "Bot"
+msgstr "ËöÈø"
+
+#: buffer.c:3777
+msgid "Top"
+msgstr "ÀèƬ"
+
+#: buffer.c:4523
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# ¥Ð¥Ã¥Õ¥¡¥ê¥¹¥È:\n"
+
+#: buffer.c:4556
+msgid "[Error List]"
+msgstr "[¥¨¥é¡¼¥ê¥¹¥È]"
+
+#: buffer.c:4569 memline.c:1520
+msgid "[No File]"
+msgstr "[̵Âê]"
+
+#: buffer.c:4882
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- ¥µ¥¤¥ó ---"
+
+#: buffer.c:4901
+#, c-format
+msgid "Signs for %s:"
+msgstr "%s ¤Î¥µ¥¤¥ó:"
+
+#: buffer.c:4907
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " ¹Ô=%ld ¼±ÊÌ»Ò=%d ̾Á°=%s"
+
+#: diff.c:139
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: %ld °Ê¾å¤Î¥Ð¥Ã¥Õ¥¡¤Ïdiff¤Ç¤­¤Þ¤»¤ó"
+
+#: diff.c:709
+msgid "E97: Cannot create diffs"
+msgstr "E97: º¹Ê¬¤òºîÀ®¤Ç¤­¤Þ¤»¤ó "
+
+#: diff.c:814
+msgid "Patch file"
+msgstr "¥Ñ¥Ã¥Á¥Õ¥¡¥¤¥ë"
+
+#: diff.c:1065
+msgid "E98: Cannot read diff output"
+msgstr "E98: diff¤Î½ÐÎϤòÆɹþ¤á¤Þ¤»¤ó"
+
+#: diff.c:1815
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: ¸½ºß¤Î¥Ð¥Ã¥Õ¥¡¤Ïº¹Ê¬¥â¡¼¥É¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: diff.c:1827
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: º¹Ê¬¥â¡¼¥É¤Ç¤¢¤ë¾¤Î¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: diff.c:1835
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr ""
+"E101: º¹Ê¬¥â¡¼¥É¤Î¥Ð¥Ã¥Õ¥¡¤¬2¸Ä°Ê¾å¤¢¤ë¤Î¤Ç¡¢¤É¤ì¤ò»È¤¦¤«ÆÃÄê¤Ç¤­¤Þ¤»¤ó"
+
+#: diff.c:1858
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: ¥Ð¥Ã¥Õ¥¡ \"%s\" ¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: diff.c:1864
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: ¥Ð¥Ã¥Õ¥¡ \"%s\" ¤Ïº¹Ê¬¥â¡¼¥É¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: digraph.c:2199
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: ¹ç»ú¤ËEscape¤Ï»ÈÍѤǤ­¤Þ¤»¤ó"
+
+#: digraph.c:2384
+msgid "E544: Keymap file not found"
+msgstr "E544: ¥­¡¼¥Þ¥Ã¥×¥Õ¥¡¥¤¥ë¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: digraph.c:2411
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: :source ¤Ç¼è¹þ¤à¥Õ¥¡¥¤¥ë°Ê³°¤Ç¤Ï :loadkeymap ¤ò»È¤¨¤Þ¤»¤ó"
+
+#: edit.c:40
+msgid " Keyword completion (^N^P)"
+msgstr " ¥­¡¼¥ï¡¼¥ÉÊä´° (^N^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E^Y^L^]^F^I^K^D^V^N^P)"
+msgstr " ^X ¥â¡¼¥É (^E^Y^L^]^F^I^K^D^V^N^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N^P)"
+msgstr " ¶É½ê¥­¡¼¥ï¡¼¥ÉÊä´° (^N^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L^N^P)"
+msgstr " ¹Ô(Á´ÂÎ)Êä´° (^L^N^P)"
+
+#: edit.c:46
+msgid " File name completion (^F^N^P)"
+msgstr "¥Õ¥¡¥¤¥ë̾Êä´° (^F^N^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]^N^P)"
+msgstr " ¥¿¥°Êä´° (^]^N^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N^P)"
+msgstr " ¥Ñ¥¹¥Ñ¥¿¡¼¥óÊä´° (^N^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D^N^P)"
+msgstr " ÄêµÁÊä´° (^D^N^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K^N^P)"
+msgstr " ¼­½ñÊä´° (^K^N^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T^N^P)"
+msgstr " ¥·¥½¡¼¥é¥¹Êä´° (^T^N^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V^N^P)"
+msgstr " ¥³¥Þ¥ó¥É¥é¥¤¥óÊä´° (^V^N^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "ÃÊÍî¤ÎºÇ¸å¤Ë¥Ò¥Ã¥È"
+
+#: edit.c:962
+msgid "'thesaurus' option is empty"
+msgstr "'thesaurus' ¥ª¥×¥·¥ç¥ó¤¬¶õ¤Ç¤¹"
+
+#: edit.c:1166
+msgid "'dictionary' option is empty"
+msgstr "'dictionary' ¥ª¥×¥·¥ç¥ó¤¬¶õ¤Ç¤¹"
+
+#: edit.c:2162
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "¼­½ñ¤ò¥¹¥­¥ã¥óÃæ: %s"
+
+#: edit.c:2368
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (ÁÞÆþ) ¥¹¥¯¥í¡¼¥ë(^E/^Y)"
+
+#: edit.c:2370
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (ÃÖ´¹) ¥¹¥¯¥í¡¼¥ë (^E/^Y)"
+
+#: edit.c:2684
+#, c-format
+msgid "Scanning: %s"
+msgstr "¥¹¥­¥ã¥óÃæ: %s"
+
+#: edit.c:2719
+msgid "Scanning tags."
+msgstr "¥¿¥°¤ò¥¹¥­¥ã¥óÃæ."
+
+#: edit.c:3381
+msgid " Adding"
+msgstr " ÄɲÃÃæ"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3430
+msgid "-- Searching..."
+msgstr "-- ¸¡º÷Ãæ..."
+
+#: edit.c:3486
+msgid "Back at original"
+msgstr "»Ï¤á¤ËÌá¤ë"
+
+#: edit.c:3491
+msgid "Word from other line"
+msgstr "¾¤Î¹Ô¤Îñ¸ì"
+
+#: edit.c:3496
+msgid "The only match"
+msgstr "Í£°ì¤Î³ºÅö"
+
+#: edit.c:3555
+#, c-format
+msgid "match %d of %d"
+msgstr "%d ÈÖÌܤγºÅö (Á´³ºÅö %d ¸ÄÃæ)"
+
+#: edit.c:3558
+#, c-format
+msgid "match %d"
+msgstr "%d ÈÖÌܤγºÅö"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:1024
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: ̤ÃΤÎÊÑ¿ô: \"%s\""
+
+#: eval.c:1320
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: ¥«¥Ã¥³ '(' ¤¬¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: eval.c:1435 eval.c:1449
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: ¤½¤ÎÊÑ¿ô¤Ï¤¢¤ê¤Þ¤»¤ó: \"%s\""
+
+#: eval.c:1705
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: '?' ¤Î¸å¤Ë ':' ¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: eval.c:2327
+msgid "E110: Missing ')'"
+msgstr "E110: ')' ¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: eval.c:2389
+msgid "E111: Missing ']'"
+msgstr "E111: ']' ¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: eval.c:2466
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: ¥ª¥×¥·¥ç¥ó̾¤¬¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: eval.c:2484
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: ̤ÃΤΥª¥×¥·¥ç¥ó¤Ç¤¹: %s"
+
+#: eval.c:2555
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: °úÍÑÉä (\") ¤¬¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: eval.c:2698
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: °úÍÑÉä (') ¤¬¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: eval.c:3054
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: ´Ø¿ô %s ¤Ë¤Ï̵¸ú¤Ê°ú¿ô¤Ç¤¹"
+
+#: eval.c:3083
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: ̤ÃΤδؿô¤Ç¤¹: %s"
+
+#: eval.c:3084
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: ´Ø¿ô¤Î°ú¿ô¤¬Â¿¤¹¤®¤Þ¤¹: %s"
+
+#: eval.c:3085
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: ´Ø¿ô¤Î°ú¿ô¤¬Â­¤ê¤Þ¤»¤ó: %s"
+
+#: eval.c:3086
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: ¥¹¥¯¥ê¥×¥È°Ê³°¤Ç<SID>¤¬»È¤ï¤ì¤Þ¤·¤¿: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3687 gui.c:4376 gui_gtk.c:2059
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:4226
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld ¹Ô:"
+
+#: eval.c:5477
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"·èÄê(&O)\n"
+"¥­¥ã¥ó¥»¥ë(&C)"
+
+#: eval.c:5517
+msgid "called inputrestore() more often than inputsave()"
+msgstr "inputrestore() ¤¬ inputsave() ¤è¤ê¤â¿¤¯¸Æ¤Ð¤ì¤Þ¤·¤¿"
+
+# Added at 10-Mar-2004.
+#: eval.c:5977
+msgid "E655: Too many symbolic links (cycle?)"
+msgstr "E655: ¥·¥ó¥Ü¥ê¥Ã¥¯¥ê¥ó¥¯¤¬Â¿²á¤®¤Þ¤¹ (½Û´Ä¤·¤Æ¤¤¤ë²ÄǽÀ­¤¬¤¢¤ê¤Þ¤¹)"
+
+#: eval.c:6609
+msgid "E240: No connection to Vim server"
+msgstr "E240: Vim ¥µ¡¼¥Ð¤Ø¤ÎÀܳ¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: eval.c:6706
+msgid "E277: Unable to read a server reply"
+msgstr "E277: ¥µ¡¼¥Ð¤Î±þÅú¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: eval.c:6734
+msgid "E258: Unable to send to client"
+msgstr "E258: ¥¯¥é¥¤¥¢¥ó¥È¤ØÁ÷¤ë¤³¤È¤¬¤Ç¤­¤Þ¤»¤ó"
+
+#: eval.c:6782
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: %s ¤ØÁ÷¤ë¤³¤È¤¬¤Ç¤­¤Þ¤»¤ó"
+
+#: eval.c:6882
+msgid "(Invalid)"
+msgstr "(̵¸ú)"
+
+#: eval.c:8060
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: ̤ÄêµÁ¤ÎÊÑ¿ô¤Ç¤¹: %s"
+
+#: eval.c:8492
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E461: ÉÔÀµ¤ÊÊÑ¿ô̾¤Ç¤¹: %s"
+
+#: eval.c:8784
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: ´Ø¿ô %s ¤ÏÄêµÁºÑ¤Ç¤¹, ºÆÄêµÁ¤¹¤ë¤Ë¤Ï ! ¤òÄɲ䷤Ƥ¯¤À¤µ¤¤"
+
+#: eval.c:8857
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: ̤ÄêµÁ¤Î´Ø¿ô¤Ç¤¹: %s"
+
+#: eval.c:8870
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: '(' ¤¬¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: eval.c:8903
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: ÉÔÀµ¤Ê°ú¿ô¤Ç¤¹: %s"
+
+#: eval.c:8982
+msgid "E126: Missing :endfunction"
+msgstr "E126: :endfunction ¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: eval.c:9089
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: ´Ø¿ô %s ¤òºÆÄêµÁ¤Ç¤­¤Þ¤»¤ó: »ÈÍÑÃæ¤Ç¤¹"
+
+#: eval.c:9159
+msgid "E129: Function name required"
+msgstr "E129: ´Ø¿ô̾¤¬Í׵ᤵ¤ì¤Þ¤¹"
+
+#: eval.c:9210
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: ´Ø¿ô̾¤ÏÂçʸ»ú¤Ç»Ï¤Þ¤é¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó: %s"
+
+#: eval.c:9402
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: ̤ÄêµÁ¤Î´Ø¿ô¤Ç¤¹: %s"
+
+#: eval.c:9407
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: ´Ø¿ô %s ¤òºï½ü¤Ç¤­¤Þ¤»¤ó: »ÈÍÑÃæ¤Ç¤¹"
+
+#: eval.c:9455
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: ´Ø¿ô¸Æ½Ð¤ÎÆþ¤ì»Ò¿ô¤¬ 'maxfuncdepth' ¤òĶ¤¨¤Þ¤·¤¿"
+
+#. always scroll up, don't overwrite
+#: eval.c:9508
+#, c-format
+msgid "calling %s"
+msgstr "%s ¤ò¼Â¹ÔÃæ¤Ç¤¹"
+
+#: eval.c:9570
+#, c-format
+msgid "%s aborted"
+msgstr "%s ¤¬ÃæÃǤµ¤ì¤Þ¤·¤¿"
+
+#: eval.c:9572
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s ¤¬ #%ld ¤òÊÖ¤·¤Þ¤·¤¿"
+
+#: eval.c:9579
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s ¤¬ \"%s\" ¤òÊÖ¤·¤Þ¤·¤¿"
+
+#. always scroll up, don't overwrite
+#: eval.c:9595 ex_cmds2.c:2365
+#, c-format
+msgid "continuing in %s"
+msgstr "%s ¤Î¼Â¹Ô¤ò·Ñ³Ãæ¤Ç¤¹"
+
+#: eval.c:9621
+msgid "E133: :return not inside a function"
+msgstr "E133: ´Ø¿ô³°¤Ë :return ¤¬¤¢¤ê¤Þ¤·¤¿"
+
+#: eval.c:9952
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# ¥°¥í¡¼¥Ð¥ëÊÑ¿ô:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, 16¿Ê¿ô %02x, 8¿Ê¿ô %03o"
+
+#: ex_cmds.c:118
+#, c-format
+msgid "> %d, Hex %04x, Octal %o"
+msgstr "> %d, 16¿Ê¿ô %04x, 8¿Ê¿ô %o"
+
+#: ex_cmds.c:119
+#, c-format
+msgid "> %d, Hex %08x, Octal %o"
+msgstr "> %d, 16¿Ê¿ô %08x, 8¿Ê¿ô %o"
+
+#: ex_cmds.c:430
+msgid "E134: Move lines into themselves"
+msgstr "E134: ¹Ô¤ò¤½¤ì¼«¿È¤Ë¤Ï°ÜÆ°¤Ç¤­¤Þ¤»¤ó"
+
+#: ex_cmds.c:499
+msgid "1 line moved"
+msgstr "1 ¹Ô¤¬°ÜÆ°¤µ¤ì¤Þ¤·¤¿"
+
+#: ex_cmds.c:501
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld ¹Ô¤¬°ÜÆ°¤µ¤ì¤Þ¤·¤¿"
+
+#: ex_cmds.c:924
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld ¹Ô¤¬¥Õ¥£¥ë¥¿½èÍý¤µ¤ì¤Þ¤·¤¿"
+
+#: ex_cmds.c:952
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *¥Õ¥£¥ë¥¿* autocommand¤Ï¸½ºß¤Î¥Ð¥Ã¥Õ¥¡¤òÊѹ¹¤·¤Æ¤Ï¤¤¤±¤Þ¤»¤ó"
+
+#: ex_cmds.c:1037
+msgid "[No write since last change]\n"
+msgstr "[ºÇ¸å¤ÎÊѹ¹¤¬Êݸ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó]\n"
+
+#: ex_cmds.c:1283
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s ¹ÔÌÜ: "
+
+#: ex_cmds.c:1288
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: ¥¨¥é¡¼¤¬Â¿²á¤®¤ë¤Î¤Ç, °Ê¹ß¤Ï¥¹¥­¥Ã¥×¤·¤Þ¤¹"
+
+#: ex_cmds.c:1323
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "viminfo¥Õ¥¡¥¤¥ë \"%s\"%s%s%s ¤òÆɹþ¤ßÃæ "
+
+#: ex_cmds.c:1324
+msgid " info"
+msgstr " ¾ðÊó"
+
+#: ex_cmds.c:1325
+msgid " marks"
+msgstr " ¥Þ¡¼¥¯"
+
+#: ex_cmds.c:1326
+msgid " FAILED"
+msgstr " ¼ºÇÔ"
+
+#: ex_cmds.c:1418
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: viminfo¥Õ¥¡¥¤¥ë¤¬½ñ¹þ¤ß¤Ç¤­¤Þ¤»¤ó: %s"
+
+#: ex_cmds.c:1543
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: viminfo¥Õ¥¡¥¤¥ë %s ¤òÊݸ¤Ç¤­¤Þ¤»¤ó!"
+
+#: ex_cmds.c:1551
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "viminfo¥Õ¥¡¥¤¥ë \"%s\" ¤ò½ñ¹þ¤ßÃæ"
+
+#. Write the info:
+#: ex_cmds.c:1649
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# ¤³¤Î viminfo ¥Õ¥¡¥¤¥ë¤Ï Vim %s ¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Þ¤·¤¿.\n"
+
+#: ex_cmds.c:1651
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Êѹ¹¤¹¤ëºÝ¤Ë¤Ï½½Ê¬Ãí°Õ¤·¤Æ¤¯¤À¤µ¤¤!\n"
+"\n"
+
+#: ex_cmds.c:1653
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# ¤³¤Î¥Õ¥¡¥¤¥ë¤¬½ñ¤«¤ì¤¿»þ¤Î 'encoding' ¤ÎÃÍ\n"
+
+#: ex_cmds.c:1752
+msgid "Illegal starting char"
+msgstr "ÉÔÀµ¤ÊÀèƬʸ»ú¤Ç¤¹"
+
+#: ex_cmds.c:2097 ex_cmds.c:2362 ex_cmds2.c:763
+msgid "Save As"
+msgstr "ÊÌ̾¤ÇÊݸ"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2140
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Ʊ¤¸Ì¾Á°¤Î¥Õ¥¡¥¤¥ë¤¬Â¾¤Î¥Ð¥Ã¥Õ¥¡¤ÇÆɹþ¤Þ¤ì¤Æ¤¤¤Þ¤¹"
+
+#: ex_cmds.c:2174
+msgid "Write partial file?"
+msgstr "¥Õ¥¡¥¤¥ë¤òÉôʬŪ¤ËÊݸ¤·¤Þ¤¹¤«?"
+
+#: ex_cmds.c:2181
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: ¥Ð¥Ã¥Õ¥¡¤òÉôʬŪ¤ËÊݸ¤¹¤ë¤Ë¤Ï ! ¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤"
+
+#: ex_cmds.c:2296
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "´û¸¤Î¥Õ¥¡¥¤¥ë \"%.*s\" ¤ò¾å½ñ¤­¤·¤Þ¤¹¤«?"
+
+#: ex_cmds.c:2367
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: ¥Ð¥Ã¥Õ¥¡ %ld ¤Ë¤Ï̾Á°¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_cmds.c:2405
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: ¥Õ¥¡¥¤¥ë¤ÏÊݸ¤µ¤ì¤Þ¤»¤ó¤Ç¤·¤¿: 'write' ¥ª¥×¥·¥ç¥ó¤Ë¤è¤ê̵¸ú¤Ç¤¹"
+
+#: ex_cmds.c:2425
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"\"%.*s\" ¤Ë¤Ï 'readonly' ¥ª¥×¥·¥ç¥ó¤¬ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤¹\n"
+"¶¯À©Åª¤Ë¾å½ñ¤­¤·¤Þ¤¹¤«?"
+
+#: ex_cmds.c:2597
+msgid "Edit File"
+msgstr "¥Õ¥¡¥¤¥ë¤òÊÔ½¸"
+
+#: ex_cmds.c:3205
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: autocommand¤¬Í½´ü¤»¤º¿·¤·¤¤¥Ð¥Ã¥Õ¥¡ %s ¤òºï½ü¤·¤Þ¤·¤¿"
+
+#: ex_cmds.c:3339
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: ¿ô¤Ç¤Ï¤Ê¤¤°ú¿ô¤¬ :z ¤ËÅϤµ¤ì¤Þ¤·¤¿"
+
+#: ex_cmds.c:3424
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: rvim¤Ç¤Ï¥·¥§¥ë¥³¥Þ¥ó¥É¤ò»È¤¨¤Þ¤»¤ó"
+
+#: ex_cmds.c:3531
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Àµµ¬É½¸½¤Ïʸ»ú¤Ç¶èÀڤ뤳¤È¤¬¤Ç¤­¤Þ¤»¤ó"
+
+#: ex_cmds.c:3877
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "%s ¤ËÃÖ´¹¤·¤Þ¤¹¤«? (y/n/a/q/l/^E/^Y)"
+
+#: ex_cmds.c:4270
+msgid "(Interrupted) "
+msgstr "(³ä¹þ¤Þ¤ì¤Þ¤·¤¿)"
+
+#: ex_cmds.c:4274
+msgid "1 substitution"
+msgstr "1 ²Õ½êÃÖ´¹¤·¤Þ¤·¤¿"
+
+#: ex_cmds.c:4276
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld ²Õ½êÃÖ´¹¤·¤Þ¤·¤¿"
+
+#: ex_cmds.c:4279
+msgid " on 1 line"
+msgstr " (·× 1 ¹ÔÆâ)"
+
+#: ex_cmds.c:4281
+#, c-format
+msgid " on %ld lines"
+msgstr " (·× %ld ¹ÔÆâ)"
+
+#: ex_cmds.c:4332
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :global ¤òºÆµ¢Åª¤Ë¤Ï»È¤¨¤Þ¤»¤ó"
+
+#: ex_cmds.c:4367
+msgid "E148: Regular expression missing from global"
+msgstr "E148: global¥³¥Þ¥ó¥É¤ËÀµµ¬É½¸½¤¬»ØÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: ex_cmds.c:4416
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "¥Ñ¥¿¡¼¥ó¤¬Á´¤Æ¤Î¹Ô¤Ç¤ß¤Ä¤«¤ê¤Þ¤·¤¿: %s"
+
+#: ex_cmds.c:4497
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# ºÇ¸å¤ËÃÖ´¹¤µ¤ì¤¿Ê¸»úÎó:\n"
+"$"
+
+#: ex_cmds.c:4598 ex_docmd.c:2011
+msgid "E478: Don't panic!"
+msgstr "E478: ¹²¤Æ¤Ê¤¤¤Ç¤¯¤À¤µ¤¤"
+
+#: ex_cmds.c:4650
+#, c-format
+msgid "E661: Sorry, no '%s' help for %s"
+msgstr "E661: »ÄÇ°¤Ç¤¹¤¬ '%s' ¤Î¥Ø¥ë¥×¤¬ %s ¤Ë¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_cmds.c:4653
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: »ÄÇ°¤Ç¤¹¤¬ %s ¤Ë¤Ï¥Ø¥ë¥×¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_cmds.c:4687
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "»ÄÇ°¤Ç¤¹¤¬¥Ø¥ë¥×¥Õ¥¡¥¤¥ë \"%s\" ¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: ex_cmds.c:5170
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: ¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: ex_cmds.c:5309
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: ½ñ¹þ¤ßÍÑ¤Ë %s ¤ò³«¤±¤Þ¤»¤ó"
+
+#: ex_cmds.c:5345
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: ÆɹþÍÑ¤Ë %s ¤ò³«¤±¤Þ¤»¤ó"
+
+# Added at 29-Apr-2004.
+#: ex_cmds.c:5367
+#, c-format
+msgid "E670: Mix of help file encodings within a language: %s"
+msgstr "E670: 1¤Ä¤Î¸À¸ì¤Î¥Ø¥ë¥×¥Õ¥¡¥¤¥ë¤ËÊ£¿ô¤Î¥¨¥ó¥³¡¼¥É¤¬º®ºß¤·¤Æ¤¤¤Þ¤¹: %s"
+
+#: ex_cmds.c:5445
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: ¥¿¥° \"%s\" ¤¬¥Õ¥¡¥¤¥ë %s ¤Ë½ÅÊ£¤·¤Æ¤¤¤Þ¤¹"
+
+#: ex_cmds.c:5557
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: ̤ÃΤÎsign¥³¥Þ¥ó¥É¤Ç¤¹: %s"
+
+#: ex_cmds.c:5577
+msgid "E156: Missing sign name"
+msgstr "E156: sign̾¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_cmds.c:5623
+msgid "E612: Too many signs defined"
+msgstr "E612: sign¤ÎÄêµÁ¤¬Â¿¿ô¸«¤Ä¤«¤ê¤Þ¤·¤¿"
+
+#: ex_cmds.c:5691
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: ̵¸ú¤Êsign¤Î¥Æ¥­¥¹¥È¤Ç¤¹: %s"
+
+#: ex_cmds.c:5722 ex_cmds.c:5913
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: ̤ÃΤÎsign¤Ç¤¹: %s"
+
+#: ex_cmds.c:5771
+msgid "E159: Missing sign number"
+msgstr "E159: sign¤ÎÈֹ椬¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_cmds.c:5853
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: ̵¸ú¤Ê¥Ð¥Ã¥Õ¥¡Ì¾¤Ç¤¹: %s"
+
+#: ex_cmds.c:5892
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: ̵¸ú¤Êsign¼±Ê̻ҤǤ¹: %ld"
+
+# Added at 27-Jan-2004.
+#: ex_cmds.c:5962
+msgid " (NOT FOUND)"
+msgstr " (¤ß¤Ä¤«¤ê¤Þ¤»¤ó)"
+
+#: ex_cmds.c:5964
+msgid " (not supported)"
+msgstr " (È󥵥ݡ¼¥È)"
+
+#: ex_cmds.c:6063
+msgid "[Deleted]"
+msgstr "[ºï½üºÑ]"
+
+#: ex_cmds2.c:92
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "¥Ç¥Ð¥Ã¥°¥â¡¼¥É¤ËÆþ¤ê¤Þ¤¹. ³¤±¤ë¤Ë¤Ï \"cont\" ¤ÈÆþÎϤ·¤Æ¤¯¤À¤µ¤¤."
+
+#: ex_cmds2.c:96 ex_docmd.c:966
+#, c-format
+msgid "line %ld: %s"
+msgstr "¹Ô %ld: %s"
+
+#: ex_cmds2.c:98
+#, c-format
+msgid "cmd: %s"
+msgstr "¥³¥Þ¥ó¥É: %s"
+
+#: ex_cmds2.c:290
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "¥Ö¥ì¡¼¥¯¥Ý¥¤¥ó¥È \"%s%s\" ¹Ô %ld"
+
+#: ex_cmds2.c:540
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: ¥Ö¥ì¡¼¥¯¥Ý¥¤¥ó¥È¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó: %s"
+
+#: ex_cmds2.c:566
+msgid "No breakpoints defined"
+msgstr "¥Ö¥ì¡¼¥¯¥Ý¥¤¥ó¥È¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: ex_cmds2.c:571
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s ¹Ô %ld"
+
+#: ex_cmds2.c:786
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Êѹ¹¤ò \"%.*s\" ¤ËÊݸ¤·¤Þ¤¹¤«?"
+
+#: ex_cmds2.c:788 ex_docmd.c:9356
+msgid "Untitled"
+msgstr "̵Âê"
+
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: ¥Ð¥Ã¥Õ¥¡ \"%s\" ¤ÎÊѹ¹¤ÏÊݸ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "·Ù¹ð: ͽ´ü¤»¤ºÂ¾¥Ð¥Ã¥Õ¥¡¤Ø°ÜÆ°¤·¤Þ¤·¤¿ (autocommands ¤òÄ´¤Ù¤Æ¤¯¤À¤µ¤¤)"
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: ÊÔ½¸¤¹¤ë¥Õ¥¡¥¤¥ë¤Ï1¤Ä¤·¤«¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: ºÇ½é¤Î¥Õ¥¡¥¤¥ë¤è¤êÁ°¤Ë¤Ï¹Ô¤±¤Þ¤»¤ó"
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: ºÇ¸å¤Î¥Õ¥¡¥¤¥ë¤ò±Û¤¨¤Æ¸å¤Ë¤Ï¹Ô¤±¤Þ¤»¤ó"
+
+#: ex_cmds2.c:1804
+#, c-format
+msgid "E666: compiler not supported: %s"
+msgstr "E666: ¤½¤Î¥³¥ó¥Ñ¥¤¥é¤Ë¤ÏÂбþ¤·¤Æ¤¤¤Þ¤»¤ó: %s"
+
+#: ex_cmds2.c:1897
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "\"%s\" ¤ò \"%s\" ¤«¤é¸¡º÷Ãæ"
+
+#: ex_cmds2.c:1919
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "\"%s\" ¤ò¸¡º÷Ãæ"
+
+#: ex_cmds2.c:1940
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "'runtimepath' ¤ÎÃæ¤Ë¤Ï¤ß¤Ä¤«¤ê¤Þ¤»¤ó: \"%s\""
+
+#: ex_cmds2.c:1974
+msgid "Source Vim script"
+msgstr "Vim¥¹¥¯¥ê¥×¥È¤Î¼è¹þ¤ß"
+
+#: ex_cmds2.c:2164
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "¥Ç¥£¥ì¥¯¥È¥ê¤Ï¼è¹þ¤á¤Þ¤»¤ó: \"%s\""
+
+#: ex_cmds2.c:2202
+#, c-format
+msgid "could not source \"%s\""
+msgstr "\"%s\" ¤ò¼è¹þ¤á¤Þ¤»¤ó"
+
+#: ex_cmds2.c:2204
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "¹Ô %ld: \"%s\" ¤ò¼è¹þ¤á¤Þ¤»¤ó"
+
+#: ex_cmds2.c:2218
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "\"%s\" ¤ò¼è¹þÃæ"
+
+#: ex_cmds2.c:2220
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "¹Ô %ld: %s ¤ò¼è¹þÃæ"
+
+#: ex_cmds2.c:2363
+#, c-format
+msgid "finished sourcing %s"
+msgstr "%s ¤Î¼è¹þ¤ò´°Î»"
+
+#: ex_cmds2.c:2707
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: ·Ù¹ð: ¹Ô¶èÀÚ¤¬ÉÔÀµ¤Ç¤¹. ^M ¤¬¤Ê¤¤¤Î¤Ç¤·¤ç¤¦"
+
+#: ex_cmds2.c:2756
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :scriptencoding ¤¬¼è¹þ¥¹¥¯¥ê¥×¥È°Ê³°¤Ç»ÈÍѤµ¤ì¤Þ¤·¤¿"
+
+#: ex_cmds2.c:2789
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish ¤¬¼è¹þ¥¹¥¯¥ê¥×¥È°Ê³°¤Ç»ÈÍѤµ¤ì¤Þ¤·¤¿"
+
+#: ex_cmds2.c:3238
+#, c-format
+msgid "Page %d"
+msgstr "%d ¥Ú¡¼¥¸"
+
+#: ex_cmds2.c:3394
+msgid "No text to be printed"
+msgstr "°õºþ¤¹¤ë¥Æ¥­¥¹¥È¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_cmds2.c:3472
+msgid "Printing page %d (%d%%)"
+msgstr "°õºþÃæ: ¥Ú¡¼¥¸ %d (%d%%)"
+
+#: ex_cmds2.c:3484
+#, c-format
+msgid " Copy %d of %d"
+msgstr " ¥³¥Ô¡¼ %d (Á´ %d Ãæ)"
+
+#: ex_cmds2.c:3542
+#, c-format
+msgid "Printed: %s"
+msgstr "°õºþ¤·¤Þ¤·¤¿: %s"
+
+#: ex_cmds2.c:3549
+msgid "Printing aborted"
+msgstr "°õºþ¤¬Ãæ»ß¤µ¤ì¤Þ¤·¤¿"
+
+#: ex_cmds2.c:3914
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: PostScript½ÐÎÏ¥Õ¥¡¥¤¥ë¤Î½ñ¹þ¤ß¥¨¥é¡¼¤Ç¤¹"
+
+#: ex_cmds2.c:4189
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E624: ¥Õ¥¡¥¤¥ë \"%s\" ¤ò³«¤±¤Þ¤»¤ó"
+
+#: ex_cmds2.c:4199 ex_cmds2.c:4824
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: PostScript¤Î¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë \"%s\" ¤òÆɹþ¤á¤Þ¤»¤ó"
+
+#: ex_cmds2.c:4207
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: ¥Õ¥¡¥¤¥ë \"%s\" ¤Ï PostScript ¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_cmds2.c:4222 ex_cmds2.c:4242 ex_cmds2.c:4257 ex_cmds2.c:4279
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: ¥Õ¥¡¥¤¥ë \"%s\" ¤ÏÂбþ¤·¤Æ¤¤¤Ê¤¤ PostScript ¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë¤Ç¤¹"
+
+#: ex_cmds2.c:4309
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: ¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë \"%s\" ¤Ï¥Ð¡¼¥¸¥ç¥ó¤¬°Û¤Ê¤ê¤Þ¤¹"
+
+#: ex_cmds2.c:4776
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: PostScript½ÐÎÏÍѤΥե¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó"
+
+#: ex_cmds2.c:4809
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: ¥Õ¥¡¥¤¥ë \"%s\" ¤ò³«¤±¤Þ¤»¤ó"
+
+#: ex_cmds2.c:4928
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr "E456: PostScript¤Î¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë \"prolog.ps\" ¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: ex_cmds2.c:4959
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: PostScript¤Î¥ê¥½¡¼¥¹¥Õ¥¡¥¤¥ë \"%s.ps\" ¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: ex_cmds2.c:4977
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr "E620: ¥Þ¥ë¥Á¥Ð¥¤¥Èʸ»ú¤ò¥¨¥ó¥³¡¼¥É \"%s\" ¤ØÊÑ´¹¤Ç¤­¤Þ¤»¤ó"
+
+#: ex_cmds2.c:5102
+msgid "Sending to printer..."
+msgstr "¥×¥ê¥ó¥¿¤ËÁ÷¿®Ãæ..."
+
+#: ex_cmds2.c:5106
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: PostScript¥Õ¥¡¥¤¥ë¤Î°õºþ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: ex_cmds2.c:5108
+msgid "Print job sent."
+msgstr "°õºþ¥¸¥ç¥Ö¤òÁ÷¿®¤·¤Þ¤·¤¿."
+
+#: ex_cmds2.c:5618
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "¸½ºß¤Î %s¸À¸ì: \"%s\""
+
+#: ex_cmds2.c:5629
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: ¸À¸ì¤ò \"%s\" ¤ËÀßÄê¤Ç¤­¤Þ¤»¤ó"
+
+#: ex_docmd.c:525
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Ex¥â¡¼¥É¤ËÆþ¤ê¤Þ¤¹. ¥Î¡¼¥Þ¥ë¤ËÌá¤ë¤Ë¤Ï\"visual\"¤ÈÆþÎϤ·¤Æ¤¯¤À¤µ¤¤."
+
+#. must be at EOF
+#: ex_docmd.c:561
+msgid "E501: At end-of-file"
+msgstr "E501: ¥Õ¥¡¥¤¥ë¤Î½ªÎ»°ÌÃÖ"
+
+#: ex_docmd.c:669
+msgid "E169: Command too recursive"
+msgstr "E169: ¥³¥Þ¥ó¥É¤¬ºÆµ¢Åª²á¤®¤Þ¤¹"
+
+#: ex_docmd.c:1229
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: Îã³°¤¬Ê᪤µ¤ì¤Þ¤»¤ó¤Ç¤·¤¿: %s"
+
+#: ex_docmd.c:1317
+msgid "End of sourced file"
+msgstr "¼è¹þ¥Õ¥¡¥¤¥ë¤ÎºÇ¸å¤Ç¤¹"
+
+#: ex_docmd.c:1318
+msgid "End of function"
+msgstr "´Ø¿ô¤ÎºÇ¸å¤Ç¤¹"
+
+#: ex_docmd.c:1907
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: ¥æ¡¼¥¶ÄêµÁ¥³¥Þ¥ó¥É¤Î¤¢¤¤¤Þ¤¤¤Ê»ÈÍѤǤ¹"
+
+#: ex_docmd.c:1921
+msgid "E492: Not an editor command"
+msgstr "E492: ¥¨¥Ç¥£¥¿¤Î¥³¥Þ¥ó¥É¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_docmd.c:2030
+msgid "E493: Backwards range given"
+msgstr "E493: µÕ¤µ¤Þ¤ÎÈϰϤ¬»ØÄꤵ¤ì¤Þ¤·¤¿"
+
+#: ex_docmd.c:2039
+msgid "Backwards range given, OK to swap"
+msgstr "µÕ¤µ¤Þ¤ÎÈϰϤ¬»ØÄꤵ¤ì¤Þ¤·¤¿, ÆþÂؤ¨¤Þ¤¹¤«?"
+
+#: ex_docmd.c:2162
+msgid "E494: Use w or w>>"
+msgstr "E494: w ¤â¤·¤¯¤Ï w>> ¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤"
+
+#: ex_docmd.c:3788
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: ¤³¤Î¥Ð¡¼¥¸¥ç¥ó¤Ç¤Ï¤³¤Î¥³¥Þ¥ó¥É¤ÏÍøÍѤǤ­¤Þ¤»¤ó, ¤´¤á¤ó¤Ê¤µ¤¤"
+
+#: ex_docmd.c:3991
+msgid "E172: Only one file name allowed"
+msgstr "E172: ¥Õ¥¡¥¤¥ë̾¤Ï 1 ¤Ä¤Ë¤·¤Æ¤¯¤À¤µ¤¤"
+
+#: ex_docmd.c:4571
+msgid "1 more file to edit. Quit anyway?"
+msgstr "ÊÔ½¸¤¹¤Ù¤­¥Õ¥¡¥¤¥ë¤¬ 1 ¸Ä¤¢¤ê¤Þ¤¹¤¬, ½ªÎ»¤·¤Þ¤¹¤«?"
+
+#: ex_docmd.c:4574
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "ÊÔ½¸¤¹¤Ù¤­¥Õ¥¡¥¤¥ë¤¬¤¢¤È %d ¸Ä¤¢¤ê¤Þ¤¹¤¬, ½ªÎ»¤·¤Þ¤¹¤«?"
+
+#: ex_docmd.c:4581
+msgid "E173: 1 more file to edit"
+msgstr "E173: ÊÔ½¸¤¹¤Ù¤­¥Õ¥¡¥¤¥ë¤¬ 1 ¸Ä¤¢¤ê¤Þ¤¹"
+
+#: ex_docmd.c:4583
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: ÊÔ½¸¤¹¤Ù¤­¥Õ¥¡¥¤¥ë¤¬¤¢¤È %ld ¸Ä¤¢¤ê¤Þ¤¹"
+
+#: ex_docmd.c:4678
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: ¥³¥Þ¥ó¥É¤¬´û¤Ë¤¢¤ê¤Þ¤¹: ºÆÄêµÁ¤¹¤ë¤Ë¤Ï ! ¤òÄɲ䷤Ƥ¯¤À¤µ¤¤"
+
+#: ex_docmd.c:4789
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" ̾Á° °ú¿ô ÈÏ°Ï Êä´° ÄêµÁ"
+
+#: ex_docmd.c:4878
+msgid "No user-defined commands found"
+msgstr "¥æ¡¼¥¶ÄêµÁ¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: ex_docmd.c:4910
+msgid "E175: No attribute specified"
+msgstr "E175: °À­¤ÏÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: ex_docmd.c:4962
+msgid "E176: Invalid number of arguments"
+msgstr "E176: °ú¿ô¤Î¿ô¤¬Ìµ¸ú¤Ç¤¹"
+
+#: ex_docmd.c:4977
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: ¥«¥¦¥ó¥È¤ò2½Å»ØÄꤹ¤ë¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó"
+
+#: ex_docmd.c:4987
+msgid "E178: Invalid default value for count"
+msgstr "E178: ¥«¥¦¥ó¥È¤Î¾ÊάÃͤ¬Ìµ¸ú¤Ç¤¹"
+
+#: ex_docmd.c:5018
+msgid "E179: argument required for complete"
+msgstr "E179: Êä´°¤Î¤¿¤á¤Î°ú¿ô¤¬É¬ÍפǤ¹"
+
+#: ex_docmd.c:5050
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: ̵¸ú¤ÊÊä´°»ØÄê¤Ç¤¹: %s"
+
+#: ex_docmd.c:5059
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr "E468: Êä´°°ú¿ô¤Ï¥«¥¹¥¿¥àÊä´°¤Ç¤·¤«»ÈÍѤǤ­¤Þ¤»¤ó"
+
+#: ex_docmd.c:5065
+msgid "E467: Custom completion requires a function argument"
+msgstr "E467: ¥«¥¹¥¿¥àÊä´°¤Ë¤Ï°ú¿ô¤È¤·¤Æ´Ø¿ô¤¬É¬ÍפǤ¹"
+
+#: ex_docmd.c:5076
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: ̵¸ú¤Ê°À­¤Ç¤¹: %s"
+
+#: ex_docmd.c:5119
+msgid "E182: Invalid command name"
+msgstr "E182: ̵¸ú¤Ê¥³¥Þ¥ó¥É̾¤Ç¤¹"
+
+#: ex_docmd.c:5134
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: ¥æ¡¼¥¶ÄêµÁ¥³¥Þ¥ó¥É¤Ï±ÑÂçʸ»ú¤Ç»Ï¤Þ¤é¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó"
+
+#: ex_docmd.c:5205
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: ¤½¤Î¥æ¡¼¥¶ÄêµÁ¥³¥Þ¥ó¥É¤Ï¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: ex_docmd.c:5666
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: ¥«¥é¡¼¥¹¥­¡¼¥à %s ¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: ex_docmd.c:5674
+msgid "Greetings, Vim user!"
+msgstr "Vim »È¤¤¤µ¤ó¡¢¤ä¤¢!"
+
+#: ex_docmd.c:6391
+msgid "Edit File in new window"
+msgstr "¿·¤·¤¤¥¦¥£¥ó¥É¥¦¤Ç¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤·¤Þ¤¹"
+
+#: ex_docmd.c:6686
+msgid "No swap file"
+msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_docmd.c:6790
+msgid "Append File"
+msgstr "Äɲåե¡¥¤¥ë"
+
+#: ex_docmd.c:6854
+msgid "E186: No previous directory"
+msgstr "E186: Á°¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_docmd.c:6936
+msgid "E187: Unknown"
+msgstr "E187: ̤ÃÎ"
+
+#: ex_docmd.c:7021
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: "
+
+#: ex_docmd.c:7077
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "¥¦¥£¥ó¥É¥¦°ÌÃÖ: X %d, Y %d"
+
+#: ex_docmd.c:7082
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr ""
+"E188: ¤³¤Î¥×¥é¥Ã¥È¥Û¡¼¥à¤Ë¤Ï¥¦¥£¥ó¥É¥¦°ÌÃ֤μèÆÀµ¡Ç½¤Ï¼ÂÁõ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: ex_docmd.c:7092
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: :winpos ¤Ë¤Ï2¤Ä¤Î¿ôÃͤΰú¿ô¤¬É¬ÍפǤ¹"
+
+#: ex_docmd.c:7370
+msgid "Save Redirection"
+msgstr "¥ê¥À¥¤¥ì¥¯¥È¤òÊݸ¤·¤Þ¤¹"
+
+#: ex_docmd.c:7560
+msgid "Save View"
+msgstr "¥Ó¥å¡¼¤òÊݸ¤·¤Þ¤¹"
+
+#: ex_docmd.c:7561
+msgid "Save Session"
+msgstr "¥»¥Ã¥·¥ç¥ó¾ðÊó¤òÊݸ¤·¤Þ¤¹"
+
+#: ex_docmd.c:7563
+msgid "Save Setup"
+msgstr "ÀßÄê¤òÊݸ¤·¤Þ¤¹"
+
+#: ex_docmd.c:7715
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" ¤¬Â¸ºß¤·¤Þ¤¹ (¾å½ñ¤¹¤ë¤Ë¤Ï ! ¤òÄɲ䷤Ƥ¯¤À¤µ¤¤)"
+
+#: ex_docmd.c:7720
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: \"%s\" ¤ò½ñ¹þ¤ßÍѤȤ·¤Æ³«¤±¤Þ¤»¤ó"
+
+#. set mark
+#: ex_docmd.c:7744
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: °ú¿ô¤Ïʸ»ú¤«Á°¿Ê/¸åÂ९¥©¡¼¥È¤Ç¤·¤Ê¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó"
+
+#: ex_docmd.c:7786
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: :normal ¤ÎºÆµ¢ÍøÍѤ¬¿¼¤¯¤Ê¤ê¤¹¤®¤Þ¤·¤¿"
+
+#: ex_docmd.c:8304
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: '#'¤òÃÖ¤­´¹¤¨¤ëÉû¥Õ¥¡¥¤¥ë¤Î̾Á°¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_docmd.c:8335
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: \"<afile>\"¤òÃÖ¤­´¹¤¨¤ëautocommand¤Î¥Õ¥¡¥¤¥ë̾¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_docmd.c:8343
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "E496: \"<abuf>\"¤òÃÖ¤­´¹¤¨¤ëautocommand¥Ð¥Ã¥Õ¥¡Èֹ椬¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_docmd.c:8354
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr "E497: \"<amatch>\"¤òÃÖ¤­´¹¤¨¤ëautocommand¤Î³ºÅö̾¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_docmd.c:8364
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr "E498: \"<sfile>\"¤òÃÖ¤­´¹¤¨¤ë :source Âоݥե¡¥¤¥ë̾¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_docmd.c:8405
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr ""
+"E499: '%' ¤ä '#' ¤¬ÌµÌ¾¥Õ¥¡¥¤¥ë¤Ê¤Î¤Ç \":p:h\" ¤òȼ¤ï¤Ê¤¤»È¤¤Êý¤Ï¤Ç¤­¤Þ¤»¤ó"
+
+#: ex_docmd.c:8407
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: ¶õʸ»úÎó¤È¤·¤Æɾ²Á¤µ¤ì¤Þ¤·¤¿"
+
+#: ex_docmd.c:9338
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: viminfo¥Õ¥¡¥¤¥ë¤òÆɹþÍѤȤ·¤Æ³«¤±¤Þ¤»¤ó"
+
+#: ex_docmd.c:9511
+msgid "E196: No digraphs in this version"
+msgstr "E196: ¤³¤Î¥Ð¡¼¥¸¥ç¥ó¤Ë¹ç»ú¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: ex_eval.c:440
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr "E608: 'Vim' ¤Ç»Ï¤Þ¤ëÎã³°¤Ï :throw ¤Ç¤­¤Þ¤»¤ó"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:529
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "Îã³°¤¬È¯À¸¤·¤Þ¤·¤¿: %s"
+
+#: ex_eval.c:576
+#, c-format
+msgid "Exception finished: %s"
+msgstr "Îã³°¤¬¼ý«¤·¤Þ¤·¤¿: %s"
+
+#: ex_eval.c:577
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "Îã³°¤¬ÇË´þ¤µ¤ì¤Þ¤·¤¿: %s"
+
+#: ex_eval.c:620 ex_eval.c:664
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, ¹Ô %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:638
+#, c-format
+msgid "Exception caught: %s"
+msgstr "Îã³°¤¬Ê᪤µ¤ì¤Þ¤·¤¿: %s"
+
+#: ex_eval.c:713
+#, c-format
+msgid "%s made pending"
+msgstr "%s ¤Ë¤è¤ê̤·èÄê¾õÂÖ¤¬À¸¤¸¤Þ¤·¤¿"
+
+#: ex_eval.c:716
+#, c-format
+msgid "%s resumed"
+msgstr "%s ¤¬ºÆ³«¤·¤Þ¤·¤¿"
+
+#: ex_eval.c:720
+#, c-format
+msgid "%s discarded"
+msgstr "%s ¤¬ÇË´þ¤µ¤ì¤Þ¤·¤¿"
+
+#: ex_eval.c:746
+msgid "Exception"
+msgstr "Îã³°"
+
+#: ex_eval.c:752
+msgid "Error and interrupt"
+msgstr "¥¨¥é¡¼¤È³ä¹þ¤ß"
+
+#: ex_eval.c:754 gui.c:4375
+msgid "Error"
+msgstr "¥¨¥é¡¼"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:756
+msgid "Interrupt"
+msgstr "³ä¹þ¤ß"
+
+#: ex_eval.c:830
+msgid "E579: :if nesting too deep"
+msgstr "E579: :if ¤ÎÆþ¤ì»Ò¤¬¿¼²á¤®¤Þ¤¹"
+
+#: ex_eval.c:867
+msgid "E580: :endif without :if"
+msgstr "E580: :if ¤Î¤Ê¤¤ :endif ¤¬¤¢¤ê¤Þ¤¹"
+
+#: ex_eval.c:911
+msgid "E581: :else without :if"
+msgstr "E581: :if ¤Î¤Ê¤¤ :else ¤¬¤¢¤ê¤Þ¤¹"
+
+#: ex_eval.c:914
+msgid "E582: :elseif without :if"
+msgstr "E582: :if ¤Î¤Ê¤¤ :elseif ¤¬¤¢¤ê¤Þ¤¹"
+
+#: ex_eval.c:921
+msgid "E583: multiple :else"
+msgstr "E583: Ê£¿ô¤Î :else ¤¬¤¢¤ê¤Þ¤¹"
+
+#: ex_eval.c:924
+msgid "E584: :elseif after :else"
+msgstr "E584: :else ¤Î¸å¤Ë :elseif ¤¬¤¢¤ê¤Þ¤¹"
+
+#: ex_eval.c:991
+msgid "E585: :while nesting too deep"
+msgstr "E585: :while ¤ÎÆþ¤ì»Ò¤¬¿¼¤¯²á¤®¤Þ¤¹"
+
+#: ex_eval.c:1047
+msgid "E586: :continue without :while"
+msgstr "E586: :while ¤Î¤Ê¤¤ :continue ¤¬¤¢¤ê¤Þ¤¹"
+
+#: ex_eval.c:1087
+msgid "E587: :break without :while"
+msgstr "E587: :while ¤Î¤Ê¤¤ :break ¤¬¤¢¤ê¤Þ¤¹"
+
+#: ex_eval.c:1286
+msgid "E601: :try nesting too deep"
+msgstr "E601: :try ¤ÎÆþ¤ì»Ò¤¬¿¼²á¤®¤Þ¤¹"
+
+#: ex_eval.c:1366
+msgid "E603: :catch without :try"
+msgstr "E603: :try ¤Î¤Ê¤¤ :catch ¤¬¤¢¤ê¤Þ¤¹"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1388
+msgid "E604: :catch after :finally"
+msgstr "E604: :finally ¤Î¸å¤Ë :catch ¤¬¤¢¤ê¤Þ¤¹"
+
+#: ex_eval.c:1521
+msgid "E606: :finally without :try"
+msgstr "E606: :try ¤Î¤Ê¤¤ :finally ¤¬¤¢¤ê¤Þ¤¹"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1545
+msgid "E607: multiple :finally"
+msgstr "E607: Ê£¿ô¤Î :finalyy ¤¬¤¢¤ê¤Þ¤¹"
+
+#: ex_eval.c:1654
+msgid "E602: :endtry without :try"
+msgstr "E602: :try ¤Î¤Ê¤¤ :endtry ¤Ç¤¹"
+
+#: ex_eval.c:1986
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: ´Ø¿ô¤Î³°¤Ë :endfunction ¤¬¤¢¤ê¤Þ¤·¤¿"
+
+#: ex_getln.c:3295
+msgid "tagname"
+msgstr "¥¿¥°Ì¾"
+
+#: ex_getln.c:3298
+msgid " kind file\n"
+msgstr " ¥Õ¥¡¥¤¥ë¼ïÎà\n"
+
+#: ex_getln.c:4751
+msgid "'history' option is zero"
+msgstr "¥ª¥×¥·¥ç¥ó 'history' ¤¬¥¼¥í¤Ç¤¹"
+
+#: ex_getln.c:5017
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s ¹àÌܤÎÍúÎò (¿·¤·¤¤¤â¤Î¤«¤é¸Å¤¤¤â¤Î¤Ø):\n"
+
+#: ex_getln.c:5018
+msgid "Command Line"
+msgstr "¥³¥Þ¥ó¥É¥é¥¤¥ó"
+
+#: ex_getln.c:5019
+msgid "Search String"
+msgstr "¸¡º÷ʸ»úÎó"
+
+#: ex_getln.c:5020
+msgid "Expression"
+msgstr "¼°"
+
+#: ex_getln.c:5021
+msgid "Input Line"
+msgstr "ÆþÎϹÔ"
+
+#: ex_getln.c:5059
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar ¤¬¥³¥Þ¥ó¥ÉŤòĶ¤¨¤Þ¤·¤¿"
+
+#: ex_getln.c:5236
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: ¥¢¥¯¥Æ¥£¥Ö¤Ê¥¦¥£¥ó¥É¥¦¤«¥Ð¥Ã¥Õ¥¡¤¬ºï½ü¤µ¤ì¤Þ¤·¤¿"
+
+#: fileio.c:371
+msgid "Illegal file name"
+msgstr "ÉÔÀµ¤Ê¥Õ¥¡¥¤¥ë̾"
+
+#: fileio.c:395 fileio.c:529 fileio.c:2850 fileio.c:2891
+msgid "is a directory"
+msgstr " ¤Ï¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤¹"
+
+#: fileio.c:397
+msgid "is not a file"
+msgstr " ¤Ï¥Õ¥¡¥¤¥ë¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: fileio.c:551 fileio.c:4057
+msgid "[New File]"
+msgstr "[¿·¥Õ¥¡¥¤¥ë]"
+
+#: fileio.c:584
+msgid "[Permission Denied]"
+msgstr "[ǧ²Ä¤¬¤¢¤ê¤Þ¤»¤ó]"
+
+#: fileio.c:688
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre autocommand ¤¬¥Õ¥¡¥¤¥ë¤òÆɹþÉԲĤˤ·¤Þ¤·¤¿"
+
+#: fileio.c:690
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *ReadPre autocommand ¤Ï¸½ºß¤Î¥Ð¥Ã¥Õ¥¡¤òÊѤ¨¤é¤ì¤Þ¤»¤ó"
+
+#: fileio.c:711
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: ɸ½àÆþÎϤ«¤éÆɹþÃæ...\n"
+
+#: fileio.c:717
+msgid "Reading from stdin..."
+msgstr "ɸ½àÆþÎϤ«¤éÆɹþ¤ßÃæ..."
+
+#. Re-opening the original file failed!
+#: fileio.c:988
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: ÊÑ´¹¤¬¥Õ¥¡¥¤¥ë¤òÆɹþÉԲĤˤ·¤Þ¤·¤¿"
+
+#: fileio.c:2027
+msgid "[fifo/socket]"
+msgstr "[FIFO/¥½¥±¥Ã¥È]"
+
+#: fileio.c:2034
+msgid "[fifo]"
+msgstr "[FIFO]"
+
+#: fileio.c:2041
+msgid "[socket]"
+msgstr "[¥½¥±¥Ã¥È]"
+
+#: fileio.c:2049
+msgid "[RO]"
+msgstr "[ÆÉÀì]"
+
+#: fileio.c:2059
+msgid "[CR missing]"
+msgstr "[CR̵]"
+
+#: fileio.c:2064
+msgid "[NL found]"
+msgstr "[NLÍ­]"
+
+#: fileio.c:2069
+msgid "[long lines split]"
+msgstr "[Ĺ¹Ôʬ³ä]"
+
+#: fileio.c:2075 fileio.c:4041
+msgid "[NOT converted]"
+msgstr "[̤ÊÑ´¹]"
+
+#: fileio.c:2080 fileio.c:4046
+msgid "[converted]"
+msgstr "[ÊÑ´¹ºÑ]"
+
+#: fileio.c:2087 fileio.c:4071
+msgid "[crypted]"
+msgstr "[°Å¹æ²½]"
+
+#: fileio.c:2094
+msgid "[CONVERSION ERROR]"
+msgstr "[ÊÑ´¹¥¨¥é¡¼]"
+
+#: fileio.c:2100
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[%ld ¹ÔÌܤÎÉÔÀµ¤Ê¥Ð¥¤¥È]"
+
+#: fileio.c:2107
+msgid "[READ ERRORS]"
+msgstr "[Æɹþ¥¨¥é¡¼]"
+
+#: fileio.c:2323
+msgid "Can't find temp file for conversion"
+msgstr "ÊÑ´¹¤ËɬÍפʰì»þ¥Õ¥¡¥¤¥ë¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: fileio.c:2330
+msgid "Conversion with 'charconvert' failed"
+msgstr "'charconvert' ¤Ë¤è¤ëÊÑ´¹¤¬¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: fileio.c:2333
+msgid "can't read output of 'charconvert'"
+msgstr "'charconvert' ¤Î½ÐÎϤòÆɹþ¤á¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: fileio.c:2733
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Êݸ¤¹¤ë¥Ð¥Ã¥Õ¥¡¤òautocommand¤¬ºï½ü¤«²òÊü¤·¤Þ¤·¤¿"
+
+#: fileio.c:2756
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: autocommand¤¬Í½´ü¤»¤ÌÊýË¡¤Ç¹Ô¿ô¤òÊѹ¹¤·¤Þ¤·¤¿"
+
+# Added at 19-Jan-2004.
+#: fileio.c:2794
+msgid "NetBeans dissallows writes of unmodified buffers"
+msgstr "NetBeans¤Ï̤Êѹ¹¤Î¥Ð¥Ã¥Õ¥¡¤ò¾å½ñ¤¹¤ë¤³¤È¤Ïµö²Ä¤·¤Æ¤¤¤Þ¤»¤ó"
+
+#: fileio.c:2802
+msgid "Partial writes disallowed for NetBeans buffers"
+msgstr "NetBeans¥Ð¥Ã¥Õ¥¡¤Î°ìÉô¤ò½ñ¤­½Ð¤¹¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó"
+
+#: fileio.c:2856 fileio.c:2874
+msgid "is not a file or writable device"
+msgstr "¤Ï¥Õ¥¡¥¤¥ë¤Ç¤â½ñ¹þ¤ß²Äǽ¥Ç¥Ð¥¤¥¹¤Ç¤â¤¢¤ê¤Þ¤»¤ó"
+
+#: fileio.c:2926
+msgid "is read-only (add ! to override)"
+msgstr "¤ÏÆɹþÀìÍѤǤ¹ (¶¯À©½ñ¹þ¤Ë¤Ï ! ¤òÄɲÃ)"
+
+#: fileio.c:3272
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: ¥Ð¥Ã¥¯¥¢¥Ã¥×¥Õ¥¡¥¤¥ë¤òÊݸ¤Ç¤­¤Þ¤»¤ó (! ¤òÄɲäǶ¯À©Êݸ)"
+
+#: fileio.c:3284
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr ""
+"E507: ¥Ð¥Ã¥¯¥¢¥Ã¥×¥Õ¥¡¥¤¥ë¤òÊĤ¸¤ëºÝ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿ (! ¤òÄɲäǶ¯À©)"
+
+#: fileio.c:3286
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr "E508: ¥Ð¥Ã¥¯¥¢¥Ã¥×ÍÑ¥Õ¥¡¥¤¥ë¤òÆɹþ¤á¤Þ¤»¤ó (! ¤òÄɲäǶ¯À©Æɹþ)"
+
+#: fileio.c:3302
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: ¥Ð¥Ã¥¯¥¢¥Ã¥×¥Õ¥¡¥¤¥ë¤òºî¤ì¤Þ¤»¤ó (! ¤òÄɲäǶ¯À©ºîÀ®)"
+
+#: fileio.c:3405
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: ¥Ð¥Ã¥¯¥¢¥Ã¥×¥Õ¥¡¥¤¥ë¤òºî¤ì¤Þ¤»¤ó (! ¤òÄɲäǶ¯À©ºîÀ®)"
+
+#: fileio.c:3467
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr "E460: ¥ê¥½¡¼¥¹¥Õ¥©¡¼¥¯¤¬¼º¤ï¤ì¤ë¤«¤â¤·¤ì¤Þ¤»¤ó (! ¤òÄɲäǶ¯À©)"
+
+#: fileio.c:3566
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: ÊݸÍÑ°ì»þ¥Õ¥¡¥¤¥ë¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: fileio.c:3584
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr "E213: ÊÑ´¹¤Ç¤­¤Þ¤»¤ó (! ¤òÄɲäÇÊÑ´¹¤»¤º¤ËÊݸ)"
+
+#: fileio.c:3619
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: ¥ê¥ó¥¯¤µ¤ì¤¿¥Õ¥¡¥¤¥ë¤Ë½ñ¹þ¤á¤Þ¤»¤ó"
+
+#: fileio.c:3623
+msgid "E212: Can't open file for writing"
+msgstr "E212: ½ñ¹þ¤ßÍѤ˥ե¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó"
+
+#: fileio.c:3885
+msgid "E667: Fsync failed"
+msgstr "E667: fsync ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: fileio.c:3892
+msgid "E512: Close failed"
+msgstr "E512: ÊĤ¸¤ë¤³¤È¤Ë¼ºÇÔ"
+
+#: fileio.c:3963
+msgid "E513: write error, conversion failed"
+msgstr "E513: ½ñ¹þ¤ß¥¨¥é¡¼, ÊÑ´¹¼ºÇÔ"
+
+#: fileio.c:3969
+msgid "E514: write error (file system full?)"
+msgstr "E514: ½ñ¹þ¤ß¥¨¥é¡¼, (¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤¬ËþÇÕ?)"
+
+#: fileio.c:4036
+msgid " CONVERSION ERROR"
+msgstr " ÊÑ´¹¥¨¥é¡¼"
+
+#: fileio.c:4052
+msgid "[Device]"
+msgstr "[¥Ç¥Ð¥¤¥¹]"
+
+#: fileio.c:4057
+msgid "[New]"
+msgstr "[¿·]"
+
+#: fileio.c:4079
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:4079
+msgid " appended"
+msgstr " ÄɲÃ"
+
+#: fileio.c:4081
+msgid " [w]"
+msgstr " [w]"
+
+#: fileio.c:4081
+msgid " written"
+msgstr " ½ñ¹þ¤ß"
+
+#: fileio.c:4131
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: patchmode: ¸¶ËÜ¥Õ¥¡¥¤¥ë¤òÊݸ¤Ç¤­¤Þ¤»¤ó"
+
+#: fileio.c:4153
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: ¶õ¤Î¸¶ËÜ¥Õ¥¡¥¤¥ë¤òtouch¤Ç¤­¤Þ¤»¤ó"
+
+#: fileio.c:4168
+msgid "E207: Can't delete backup file"
+msgstr "E207: ¥Ð¥Ã¥¯¥¢¥Ã¥×¥Õ¥¡¥¤¥ë¤ò¾Ã¤»¤Þ¤»¤ó"
+
+#: fileio.c:4232
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"·Ù¹ð: ¸¶ËÜ¥Õ¥¡¥¤¥ë¤¬¼º¤ï¤ì¤¿¤«Êѹ¹¤µ¤ì¤Þ¤·¤¿\n"
+
+#: fileio.c:4234
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "¥Õ¥¡¥¤¥ë¤ÎÊݸ¤ËÀ®¸ù¤¹¤ë¤Þ¤Ç¥¨¥Ç¥£¥¿¤ò½ªÎ»¤·¤Ê¤¤¤Ç¤¯¤À¤µ¤¤!"
+
+#: fileio.c:4323
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:4323
+msgid "[dos format]"
+msgstr "[dos¥Õ¥©¡¼¥Þ¥Ã¥È]"
+
+#: fileio.c:4330
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:4330
+msgid "[mac format]"
+msgstr "[mac¥Õ¥©¡¼¥Þ¥Ã¥È]"
+
+#: fileio.c:4337
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:4337
+msgid "[unix format]"
+msgstr "[unix¥Õ¥©¡¼¥Þ¥Ã¥È]"
+
+#: fileio.c:4364
+msgid "1 line, "
+msgstr "1 ¹Ô, "
+
+#: fileio.c:4366
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld ¹Ô, "
+
+#: fileio.c:4369
+msgid "1 character"
+msgstr "1 ʸ»ú"
+
+#: fileio.c:4371
+#, c-format
+msgid "%ld characters"
+msgstr "%ld ʸ»ú"
+
+#: fileio.c:4381
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:4381
+msgid "[Incomplete last line]"
+msgstr "[ºÇ½ª¹Ô¤¬ÉÔ´°Á´]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4400
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "·Ù¹ð: Æɹþ¤ó¤À¸å¤Ë¥Õ¥¡¥¤¥ë¤ËÊѹ¹¤¬¤¢¤ê¤Þ¤·¤¿!!!"
+
+#: fileio.c:4402
+msgid "Do you really want to write to it"
+msgstr "ËÜÅö¤Ë¾å½ñ¤­¤·¤Þ¤¹¤«"
+
+#: fileio.c:5566
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: \"%s\" ¤ò½ñ¹þ¤ßÃæ¤Î¥¨¥é¡¼¤Ç¤¹"
+
+#: fileio.c:5573
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: \"%s\" ¤òÊĤ¸¤ë»þ¤Ë¥¨¥é¡¼¤Ç¤¹"
+
+#: fileio.c:5576
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: \"%s\" ¤òÆɹþÃæ¤Î¥¨¥é¡¼¤Ç¤¹"
+
+#: fileio.c:5810
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: autocommand ¤Î FileChangedShell ¤¬¥Ð¥Ã¥Õ¥¡¤òºï½ü¤·¤Þ¤·¤¿"
+
+#: fileio.c:5817
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: ·Ù¹ð: ¥Õ¥¡¥¤¥ë \"%s\" ¤Ï´û¤Ë¸ºß¤·¤Þ¤»¤ó"
+
+#: fileio.c:5831
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr "W12: ·Ù¹ð: ¥Õ¥¡¥¤¥ë \"%s\" ¤¬Êѹ¹¤µ¤ìVim¤Î¥Ð¥Ã¥Õ¥¡¤âÊѹ¹¤µ¤ì¤Þ¤·¤¿"
+
+#: fileio.c:5834
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: ·Ù¹ð: ¥Õ¥¡¥¤¥ë \"%s\" ¤ÏÊÔ½¸³«»Ï¸å¤ËÊѹ¹¤µ¤ì¤Þ¤·¤¿"
+
+#: fileio.c:5836
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: ·Ù¹ð: ¥Õ¥¡¥¤¥ë \"%s\" ¤Î¥â¡¼¥É¤¬ÊÔ½¸³«»Ï¸å¤ËÊѹ¹¤µ¤ì¤Þ¤·¤¿"
+
+#: fileio.c:5846
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: ·Ù¹ð: ¥Õ¥¡¥¤¥ë \"%s\" ¤ÏÊÔ½¸³«»Ï¸å¤ËºîÀ®¤µ¤ì¤Þ¤·¤¿"
+
+#: fileio.c:5859
+msgid "See \":help W11\" for more info."
+msgstr "¾ÜºÙ¤Ï \":help W11\" ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤"
+
+#: fileio.c:5873
+msgid "Warning"
+msgstr "·Ù¹ð"
+
+#: fileio.c:5874
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"¥Õ¥¡¥¤¥ëÆɹþ(&L)"
+
+#: fileio.c:5980
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: \"%s\" ¤ò¥ê¥í¡¼¥É¤¹¤ë½àÈ÷¤¬¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: fileio.c:5999
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: \"%s\" ¤Ï¥ê¥í¡¼¥É¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: fileio.c:6580
+msgid "--Deleted--"
+msgstr "--ºï½üºÑ--"
+
+#. the group doesn't exist
+#: fileio.c:6740
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: ¤½¤Î¥°¥ë¡¼¥×¤Ï¤¢¤ê¤Þ¤»¤ó: \"%s\""
+
+#: fileio.c:6866
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: * ¤Î¸å¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤·¤¿: %s"
+
+#: fileio.c:6878
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: ¤½¤Î¤è¤¦¤Ê¥¤¥Ù¥ó¥È¤Ï¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: fileio.c:6880
+#, c-format
+msgid "E216: No such group or event: %s"
+msgstr "E216: ¤½¤Î¤è¤¦¤Ê¥°¥ë¡¼¥×¤â¤·¤¯¤Ï¥¤¥Ù¥ó¥È¤Ï¤¢¤ê¤Þ¤»¤ó: %s"
+
+#. Highlight title
+#: fileio.c:7038
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Auto-Commands ---"
+
+#: fileio.c:7309
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Á´¤Æ¤Î¥¤¥Ù¥ó¥È¤ËÂФ·¤Æ¤Îautocommand¤Ï¼Â¹Ô¤Ç¤­¤Þ¤»¤ó"
+
+#: fileio.c:7332
+msgid "No matching autocommands"
+msgstr "³ºÅö¤¹¤ëautocommand¤Ï¸ºß¤·¤Þ¤»¤ó"
+
+#: fileio.c:7653
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: autocommand¤ÎÆþ¤ì»Ò¤¬¿¼¤¹¤®¤Þ¤¹"
+
+#: fileio.c:7928
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Auto commands for \"%s\""
+
+#: fileio.c:7936
+#, c-format
+msgid "Executing %s"
+msgstr "%s ¤ò¼Â¹Ô¤·¤Æ¤¤¤Þ¤¹"
+
+#. always scroll up, don't overwrite
+#: fileio.c:8004
+#, c-format
+msgid "autocommand %s"
+msgstr "autocommand %s"
+
+#: fileio.c:8571
+msgid "E219: Missing {."
+msgstr "E219: { ¤¬¤¢¤ê¤Þ¤»¤ó."
+
+#: fileio.c:8573
+msgid "E220: Missing }."
+msgstr "E220: } ¤¬¤¢¤ê¤Þ¤»¤ó."
+
+#: fold.c:68
+msgid "E490: No fold found"
+msgstr "E490: ÀÞ¾ö¤ß¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: fold.c:593
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: ¸½ºß¤Î 'foldmethod' ¤Ç¤ÏÀÞ¾ö¤ß¤òºîÀ®¤Ç¤­¤Þ¤»¤ó"
+
+#: fold.c:595
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: ¸½ºß¤Î 'foldmethod' ¤Ç¤ÏÀÞ¾ö¤ß¤òºï½ü¤Ç¤­¤Þ¤»¤ó"
+
+#: getchar.c:248
+msgid "E222: Add to read buffer"
+msgstr "E222: Æɹþ¥Ð¥Ã¥Õ¥¡¤ØÄɲÃ"
+
+#: getchar.c:2198
+msgid "E223: recursive mapping"
+msgstr "E223: ºÆµ¢Åª¥Þ¥Ã¥Ô¥ó¥°"
+
+#: getchar.c:3077
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: %s ¤È¤¤¤¦¥°¥í¡¼¥Ð¥ëû½ÌÆþÎϤϴû¤Ë¸ºß¤·¤Þ¤¹"
+
+#: getchar.c:3080
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: %s ¤È¤¤¤¦¥°¥í¡¼¥Ð¥ë¥Þ¥Ã¥Ô¥ó¥°¤Ï´û¤Ë¸ºß¤·¤Þ¤¹"
+
+#: getchar.c:3212
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: %s ¤È¤¤¤¦Ã»½ÌÆþÎϤϴû¤Ë¸ºß¤·¤Þ¤¹"
+
+#: getchar.c:3215
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: %s ¤È¤¤¤¦¥Þ¥Ã¥Ô¥ó¥°¤Ï´û¤Ë¸ºß¤·¤Þ¤¹"
+
+#: getchar.c:3279
+msgid "No abbreviation found"
+msgstr "û½ÌÆþÎϤϤߤĤ«¤ê¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: getchar.c:3281
+msgid "No mapping found"
+msgstr "¥Þ¥Ã¥Ô¥ó¥°¤Ï¤ß¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: getchar.c:4173
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: ÉÔÀµ¤Ê¥â¡¼¥É"
+
+#: gui.c:220
+msgid "E229: Cannot start the GUI"
+msgstr "E229: GUI¤ò³«»Ï¤Ç¤­¤Þ¤»¤ó"
+
+#: gui.c:349
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: \"%s\"¤«¤éÆɹþ¤à¤³¤È¤¬¤Ç¤­¤Þ¤»¤ó"
+
+#: gui.c:472
+msgid "E665: Cannot start GUI, no valid font found"
+msgstr "E665: Í­¸ú¤Ê¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤¤¤Î¤Ç, GUI¤ò³«»Ï¤Ç¤­¤Þ¤»¤ó"
+
+#: gui.c:477
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: 'guifontwide' ¤¬Ìµ¸ú¤Ç¤¹"
+
+#: gui.c:547
+msgid "E599: Value of 'imactivatekey' is invalid"
+msgstr "E599: 'imactivatekey' ¤ËÀßÄꤵ¤ì¤¿Ãͤ¬Ìµ¸ú¤Ç¤¹"
+
+#: gui.c:4061
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: %s ¤Î¿§¤ò³ä¤êÅö¤Æ¤é¤ì¤Þ¤»¤ó"
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<³«¤±¤Þ¤»¤ó>"
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: ¥Õ¥©¥ó¥È %s ¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó"
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: ¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ËÌá¤ì¤Þ¤»¤ó"
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "¥Ñ¥¹Ì¾:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: ¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó"
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "OK"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2731 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "¥­¥ã¥ó¥»¥ë"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "¥¹¥¯¥í¡¼¥ë¥Ð¡¼: ²èÁü¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿."
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "Vim ¥À¥¤¥¢¥í¥°"
+
+#: gui_beval.c:101 gui_w32.c:3830
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: ¥á¥Ã¥»¡¼¥¸¤È¥³¡¼¥ë¥Ð¥Ã¥¯¤Î¤¢¤ë BalloonEval ¤òºîÀ®¤Ç¤­¤Þ¤»¤ó"
+
+#: gui_gtk.c:1607
+msgid "Vim dialog..."
+msgstr "Vim ¥À¥¤¥¢¥í¥°..."
+
+#: gui_gtk.c:2060 message.c:2993
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"¤Ï¤¤(&Y)\n"
+"¤¤¤¤¤¨(&N)\n"
+"¥­¥ã¥ó¥»¥ë(&C)"
+
+#: gui_gtk.c:2268
+msgid "Input _Methods"
+msgstr "¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É"
+
+#: gui_gtk.c:2534 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "VIM - ¸¡º÷¤ÈÃÖ´¹..."
+
+#: gui_gtk.c:2542 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "VIM - ¸¡º÷..."
+
+#: gui_gtk.c:2574 gui_motif.c:2888
+msgid "Find what:"
+msgstr "¸¡º÷ʸ»úÎó:"
+
+#: gui_gtk.c:2592 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "ÃÖ´¹Ê¸»úÎó:"
+
+#. whole word only button
+#: gui_gtk.c:2624 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "Àµ³Î¤Ë³ºÅö¤¹¤ë¤â¤Î¤À¤±"
+
+#. match case button
+#: gui_gtk.c:2635 gui_motif.c:3048
+msgid "Match case"
+msgstr "Âçʸ»ú/¾®Ê¸»ú¤ò¶èÊ̤¹¤ë"
+
+#: gui_gtk.c:2645 gui_motif.c:2990
+msgid "Direction"
+msgstr "Êý¸þ"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2657 gui_motif.c:3002
+msgid "Up"
+msgstr "¾å"
+
+#: gui_gtk.c:2661 gui_motif.c:3010
+msgid "Down"
+msgstr "²¼"
+
+#: gui_gtk.c:2683 gui_gtk.c:2685 gui_motif.c:2792
+msgid "Find Next"
+msgstr "¼¡¤ò¸¡º÷"
+
+#: gui_gtk.c:2702 gui_gtk.c:2704 gui_motif.c:2809
+msgid "Replace"
+msgstr "ÃÖ´¹"
+
+#: gui_gtk.c:2715 gui_gtk.c:2717 gui_motif.c:2822
+msgid "Replace All"
+msgstr "Á´¤ÆÃÖ´¹"
+
+#: gui_gtk_x11.c:2327
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: ¥»¥Ã¥·¥ç¥ó¥Þ¥Í¡¼¥¸¥ã¤«¤é \"die\" Í×µá¤ò¼õ¤±¼è¤ê¤Þ¤·¤¿\n"
+
+#: gui_gtk_x11.c:3519
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: ¥á¥¤¥ó¥¦¥£¥ó¥É¥¦¤¬ÉÔ°Õ¤ËÇ˲õ¤µ¤ì¤Þ¤·¤¿\n"
+
+#: gui_gtk_x11.c:4138
+msgid "Font Selection"
+msgstr "¥Õ¥©¥ó¥ÈÁªÂò"
+
+#: gui_gtk_x11.c:6035 ui.c:2117
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "¶õ¤ÎÁªÂòÎΰè¤Î¤«¤ï¤ê¤ËCUT_BUFFER0¤¬»ÈÍѤµ¤ì¤Þ¤·¤¿"
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "¥Õ¥£¥ë¥¿"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "¥Ç¥£¥ì¥¯¥È¥ê"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "¥Ø¥ë¥×"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "¥Õ¥¡¥¤¥ë"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "ÁªÂò"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "¥¢¥ó¥É¥¥"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: Zap¥Õ¥©¥ó¥È '%s' ¤òÆɹþ¤á¤Þ¤»¤ó"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: ¥Õ¥©¥ó¥È %s ¤ò»ÈÍѤǤ­¤Þ¤»¤ó"
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"»Ò¥×¥í¥»¥¹¤ØÄä»ß¥á¥Ã¥»¡¼¥¸¤òÁ÷¿®Ãæ¤Ç¤¹.\n"
+
+#: gui_w32.c:830
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: °ú¿ô¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó: \"-%s\"; OLEÈǤò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤."
+
+#: gui_w48.c:2090
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "¸¡º÷ʸ»úÎó ('\\' ¤ò¸¡º÷¤¹¤ë¤Ë¤Ï '\\\\')"
+
+#: gui_w48.c:2115
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "¸¡º÷¡¦ÃÖ´¹ ('\\' ¤ò¸¡º÷¤¹¤ë¤Ë¤Ï '\\\\')"
+
+#: gui_x11.c:1537
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr "Vim E458: ¿§»ØÄ꤬Àµ¤·¤¯¤Ê¤¤¤Î¤Ç¥¨¥ó¥È¥ê¤ò³ä¤êÅö¤Æ¤é¤ì¤Þ¤»¤ó"
+
+#: gui_x11.c:2118
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: °Ê²¼¤Îʸ»ú¥»¥Ã¥È¤Î¥Õ¥©¥ó¥È¤¬¤¢¤ê¤Þ¤»¤ó %s:"
+
+#: gui_x11.c:2161
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: ¥Õ¥©¥ó¥È¥»¥Ã¥È̾: %s"
+
+#: gui_x11.c:2162
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "¥Õ¥©¥ó¥È '%s' ¤Ï¸ÇÄêÉý¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: gui_x11.c:2181
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: ¥Õ¥©¥ó¥È¥»¥Ã¥È̾: %s\n"
+
+#: gui_x11.c:2182
+#, c-format
+msgid "Font0: %s\n"
+msgstr "¥Õ¥©¥ó¥È0: %s\n"
+
+#: gui_x11.c:2183
+#, c-format
+msgid "Font1: %s\n"
+msgstr "¥Õ¥©¥ó¥È1: %s\n"
+
+#: gui_x11.c:2184
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "¥Õ¥©¥ó¥È%d ¤ÎÉý¤¬¥Õ¥©¥ó¥È0¤ÎÇܤǤϤ¢¤ê¤Þ¤»¤ó\n"
+
+#: gui_x11.c:2185
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "¥Õ¥©¥ó¥È0¤ÎÉý: %ld\n"
+
+#: gui_x11.c:2186
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"¥Õ¥©¥ó¥È1¤ÎÉý: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: ¥Ï¥ó¥°¥ë¥ª¡¼¥È¥Þ¥È¥ó¥¨¥é¡¼"
+
+#: if_cscope.c:77
+msgid "Add a new database"
+msgstr "¿·¥Ç¡¼¥¿¥Ù¡¼¥¹¤òÄɲÃ"
+
+#: if_cscope.c:79
+msgid "Query for a pattern"
+msgstr "¥Ñ¥¿¡¼¥ó¤Î¥¯¥¨¥ê¡¼¤òÄɲÃ"
+
+#: if_cscope.c:81
+msgid "Show this message"
+msgstr "¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë"
+
+#: if_cscope.c:83
+msgid "Kill a connection"
+msgstr "Àܳ¤ò½ªÎ»¤¹¤ë"
+
+#: if_cscope.c:85
+msgid "Reinit all connections"
+msgstr "Á´¤Æ¤ÎÀܳ¤òºÆ½é´ü²½¤¹¤ë"
+
+#: if_cscope.c:87
+msgid "Show connections"
+msgstr "Àܳ¤òɽ¼¨¤¹¤ë"
+
+#: if_cscope.c:95
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: »ÈÍÑÊýË¡: cs[cope] %s"
+
+#: if_cscope.c:124
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "¤³¤Îcscope¥³¥Þ¥ó¥É¤Ïʬ³ä¥¦¥£¥ó¥É¥¦¤Ç¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó.\n"
+
+#: if_cscope.c:175
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: »ÈÍÑË¡: cstag <ident>"
+
+#: if_cscope.c:231
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: ¥¿¥°¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: if_cscope.c:409
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: stat(%s) ¥¨¥é¡¼: %d"
+
+#: if_cscope.c:419
+msgid "E563: stat error"
+msgstr "E563: stat ¥¨¥é¡¼"
+
+#: if_cscope.c:516
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s ¤Ï¥Ç¥£¥ì¥¯¥È¥êµÚ¤ÓÍ­¸ú¤Êcscope¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: if_cscope.c:534
+#, c-format
+msgid "Added cscope database %s"
+msgstr "cscope¥Ç¡¼¥¿¥Ù¡¼¥¹ %s ¤òÄɲÃ"
+
+#: if_cscope.c:589
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: cscope¤ÎÀܳ %ld ¤òÆɹþ¤ßÃæ¤Î¥¨¥é¡¼¤Ç¤¹"
+
+#: if_cscope.c:694
+msgid "E561: unknown cscope search type"
+msgstr "E561: ̤ÃΤÎcscope¸¡º÷·¿¤Ç¤¹"
+
+#: if_cscope.c:736
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: cscope¥Ñ¥¤¥×¤òºîÀ®¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: if_cscope.c:753
+msgid "E622: Could not fork for cscope"
+msgstr "E622: cscope¤Îµ¯Æ°½àÈ÷(fork)¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: if_cscope.c:847 if_cscope.c:897
+msgid "cs_create_connection exec failed"
+msgstr "cs_create_connection ¤Î¼Â¹Ô¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: if_cscope.c:898
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: cscope¥×¥í¥»¥¹¤òµ¯Æ°¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: if_cscope.c:911
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: to_fp ¤Î fdopen ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: if_cscope.c:913
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fr_fp ¤Î fdopen ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: if_cscope.c:951
+msgid "E567: no cscope connections"
+msgstr "E567: cscopeÀܳ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: if_cscope.c:1025
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: cscope¥¯¥¨¥ê¡¼ %s of %s ¤Ë³ºÅö¤¬¤¢¤ê¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: if_cscope.c:1082
+#, c-format
+msgid "E469: invalid cscopequickfix flag %c for %c"
+msgstr "E469: ̵¸ú¤Ê cscopequickfix ¥Õ¥é¥° %c ¤Î %c ¤Ç¤¹"
+
+#: if_cscope.c:1152
+msgid "cscope commands:\n"
+msgstr "cscope¥³¥Þ¥ó¥É:\n"
+
+#: if_cscope.c:1155
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (»ÈÍÑË¡: %s)"
+
+#: if_cscope.c:1253
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: cscope¥Ç¡¼¥¿¥Ù¡¼¥¹: %s ¤ò³«¤¯¤³¤È¤¬¤Ç¤­¤Þ¤»¤ó"
+
+#: if_cscope.c:1271
+msgid "E626: cannot get cscope database information"
+msgstr "E626: cscope¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¾ðÊó¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó"
+
+#: if_cscope.c:1296
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: ½ÅÊ£¤¹¤ëcscope¥Ç¡¼¥¿¥Ù¡¼¥¹¤ÏÄɲ䵤ì¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: if_cscope.c:1307
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: cscopeÀܳ¤ÎºÇÂç¿ô¤Ë㤷¤Þ¤·¤¿"
+
+#: if_cscope.c:1424
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: cscopeÀܳ %s ¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: if_cscope.c:1458
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "cscopeÀܳ %s ¤¬ÊĤ¸¤é¤ì¤Þ¤·¤¿"
+
+#. should not reach here
+#: if_cscope.c:1598
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: cs_manage_matches ¤ÇÃ×̿Ū¤Ê¥¨¥é¡¼¤Ç¤¹"
+
+#: if_cscope.c:1848
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "Cscope ¥¿¥°: %s"
+
+#: if_cscope.c:1870
+msgid ""
+"\n"
+" # line"
+msgstr ""
+"\n"
+" # ¹ÔÈÖ¹æ"
+
+#: if_cscope.c:1872
+msgid "filename / context / line\n"
+msgstr "¥Õ¥¡¥¤¥ë̾ / ʸ̮ / ¹Ô\n"
+
+#: if_cscope.c:1990
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: cscope¥¨¥é¡¼: %s"
+
+#: if_cscope.c:2176
+msgid "All cscope databases reset"
+msgstr "Á´¤Æ¤Îcscope¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥ê¥»¥Ã¥È¤·¤Þ¤¹"
+
+#: if_cscope.c:2244
+msgid "no cscope connections\n"
+msgstr "cscopeÀܳ¤¬¤¢¤ê¤Þ¤»¤ó\n"
+
+#: if_cscope.c:2248
+msgid " # pid database name prepend path\n"
+msgstr " # pid ¥Ç¡¼¥¿¥Ù¡¼¥¹Ì¾ prepend ¥Ñ¥¹\n"
+
+#: if_python.c:436
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹,¤´¤á¤ó¤Ê¤µ¤¤: "
+"Python¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿."
+
+# Added at 07-Feb-2004.
+#: if_python.c:500
+msgid "E659: Cannot invoke Python recursively"
+msgstr "E659: Python ¤òºÆµ¢Åª¤Ë¼Â¹Ô¤¹¤ë¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó"
+
+#: if_python.c:701
+msgid "can't delete OutputObject attributes"
+msgstr "OutputObject°À­¤ò¾Ã¤»¤Þ¤»¤ó"
+
+#: if_python.c:708
+msgid "softspace must be an integer"
+msgstr "softspace ¤Ï integer ¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó"
+
+#: if_python.c:716
+msgid "invalid attribute"
+msgstr "̵¸ú¤Ê°À­¤Ç¤¹"
+
+#: if_python.c:755 if_python.c:769
+msgid "writelines() requires list of strings"
+msgstr "writelines() ¤Ë¤Ïʸ»úÎó¤Î¥ê¥¹¥È¤¬É¬ÍפǤ¹"
+
+#: if_python.c:895
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: I/O¥ª¥Ö¥¸¥§¥¯¥È¤Î½é´ü²½Ãæ¤Ë¥¨¥é¡¼¤Ç¤¹"
+
+#: if_python.c:1080 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "̵¸ú¤Ê¼°¤Ç¤¹"
+
+#: if_python.c:1094 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "¼°¤Ï¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹"
+
+#: if_python.c:1107
+msgid "attempt to refer to deleted buffer"
+msgstr "¾Ã¤µ¤ì¤¿¥Ð¥Ã¥Õ¥¡¤¬»²¾È¤µ¤ì¤Þ¤·¤¿"
+
+#: if_python.c:1122 if_python.c:1163 if_python.c:1227 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "Èϰϳ°¤Î¹ÔÈÖ¹æ¤Ç¤¹"
+
+#: if_python.c:1362
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<¥Ð¥Ã¥Õ¥¡¥ª¥Ö¥¸¥§¥¯¥È (¾ÃµîºÑ¤ß) %8lX>"
+
+#: if_python.c:1453 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "̵¸ú¤Ê¥Þ¡¼¥¯Ì¾¤Ç¤¹"
+
+#: if_python.c:1733
+msgid "no such buffer"
+msgstr "¤½¤Î¤è¤¦¤Ê¥Ð¥Ã¥Õ¥¡¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: if_python.c:1821
+msgid "attempt to refer to deleted window"
+msgstr "¾Ã¤µ¤ì¤¿¥¦¥£¥ó¥É¥¦¤¬»²¾È¤µ¤ì¤Þ¤·¤¿"
+
+#: if_python.c:1866
+msgid "readonly attribute"
+msgstr "ÆɹþÀìÍÑ°À­"
+
+#: if_python.c:1879
+msgid "cursor position outside buffer"
+msgstr "¥«¡¼¥½¥ë¤¬¥Ð¥Ã¥Õ¥¡¤Î³°¤Ë¤¢¤ê¤Þ¤¹"
+
+#: if_python.c:1956
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<¥¦¥£¥ó¥É¥¦¥ª¥Ö¥¸¥§¥¯¥È (¾ÃµîºÑ) %.8lX>"
+
+#: if_python.c:1968
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<¥¦¥£¥ó¥É¥¦¥ª¥Ö¥¸¥§¥¯¥È (̤ÃÎ) %.8lX>"
+
+#: if_python.c:1970
+#, c-format
+msgid "<window %d>"
+msgstr "<¥¦¥£¥ó¥É¥¦ %d>"
+
+#: if_python.c:2046
+msgid "no such window"
+msgstr "¤½¤Î¤è¤¦¤Ê¥¦¥£¥ó¥É¥¦¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: if_python.c:2307 if_python.c:2341 if_python.c:2396 if_python.c:2464
+#: if_python.c:2586 if_python.c:2638 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "¥¢¥ó¥É¥¥¾ðÊó¤¬Êݸ¤Ç¤­¤Þ¤»¤ó"
+
+#: if_python.c:2309 if_python.c:2403 if_python.c:2475
+msgid "cannot delete line"
+msgstr "¹Ô¤ò¾Ã¤»¤Þ¤»¤ó"
+
+#: if_python.c:2346 if_python.c:2491 if_tcl.c:690 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "¹Ô¤òÃÖ´¹¤Ç¤­¤Þ¤»¤ó"
+
+#: if_python.c:2509 if_python.c:2588 if_python.c:2646
+msgid "cannot insert line"
+msgstr "¹Ô¤òÁÞÆþ¤Ç¤­¤Þ¤»¤ó"
+
+#: if_python.c:2750
+msgid "string cannot contain newlines"
+msgstr "ʸ»úÎó¤Ë¤Ï²þ¹Ôʸ»ú¤ò´Þ¤á¤é¤ì¤Þ¤»¤ó"
+
+#: if_ruby.c:422
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹,¤´¤á¤ó¤Ê¤µ¤¤: "
+"Ruby¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿."
+
+#: if_ruby.c:485
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: ̤ÃΤÎlongjmp¾õÂÖ: %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "¼ÂÁõ¤ÈÄêµÁ¤òÀÚ¤êÂؤ¨¤ë"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "¼¡¤Î¥¯¥é¥¹¤Î´ðÄì¤òɽ¼¨"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "¥ª¡¼¥Ð¡¼¥é¥¤¥É¤µ¤ì¤¿¥á¥ó¥Ð´Ø¿ô¤òɽ¼¨"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "¥Õ¥¡¥¤¥ë¤«¤é²óÉü¤¹¤ë"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "¥×¥í¥¸¥§¥¯¥È¤«¤é²óÉü¤¹¤ë"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Á´¤Æ¤Î¥×¥í¥¸¥§¥¯¥È¤«¤é²óÉü¤¹¤ë"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "²óÉü"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "¼¡¤Î¥½¡¼¥¹¤òɽ¼¨¤¹¤ë"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "¤ß¤Ä¤±¤¿¥·¥ó¥Ü¥ë"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "¥¯¥é¥¹¤ò»²¾È"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "³¬Áؤǥ¯¥é¥¹¤òɽ¼¨"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "¸ÂÄꤵ¤ì¤¿³¬Áؤǥ¯¥é¥¹¤òɽ¼¨"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref ¤Î»²¾ÈÀè"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref ¤¬»²¾È¤µ¤ì¤ë"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref ¤¬¼¡¤Î¤â¤Î¤ò¤â¤Ã¤Æ¤¤¤Þ¤¹"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref ¤¬»ÈÍѤµ¤ì¤ë"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "¼¡¤Îʸ¾Ï¤òɽ¼¨"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "¼¡¤Îʸ¾Ï¤òÀ¸À®"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"SNiFF+¤ËÀܳ¤Ç¤­¤Þ¤»¤ó. ´Ä¶­¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤(sniffemacs ¤¬ $PATH "
+"¤Ë¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: ÆɹþÃæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿. ÀÚÃǤ·¤Þ¤·¤¿"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "¸½ºßSNiFF+ ¤Î¾õÂ֤ϡÖ"
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "̤"
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "Àܳ¡×¤Ç¤¹"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: ̤ÃΤΠSNiFF+ ¥ê¥¯¥¨¥¹¥È¤Ç¤¹: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: SNiFF+ ¤Ø¤ÎÀܳÃæ¤Î¥¨¥é¡¼¤Ç¤¹"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ ¤ËÀܳ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: SNiFF+ ¥Ð¥Ã¥Õ¥¡¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: ½ñ¹þ¤ßÃæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤¿¤Î¤ÇÀÚÃǤ·¤Þ¤·¤¿"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "̵¸ú¤Ê¥Ð¥Ã¥Õ¥¡ÈÖ¹æ¤Ç¤¹"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "¤Þ¤À¼ÂÁõ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "̤ÃΤΥª¥×¥·¥ç¥ó¤Ç¤¹"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "¹Ô¤òÀßÄê¤Ç¤­¤Þ¤»¤ó"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "¥Þ¡¼¥¯¤ÏÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "¹Ô %d Îó %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "¹Ô¤ÎÁÞÆþ/Äɲäò¤Ç¤­¤Þ¤»¤ó"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "̤ÃΤΥե饰:"
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "̤ÃΤΠvimOption ¤Ç¤¹"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "¥­¡¼¥Ü¡¼¥É³ä¹þ¤ß"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "vim ¥¨¥é¡¼"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr ""
+"¥Ð¥Ã¥Õ¥¡/¥¦¥£¥ó¥É¥¦ºîÀ®¥³¥Þ¥ó¥É¤òºîÀ®¤Ç¤­¤Þ¤»¤ó: "
+"¥ª¥Ö¥¸¥§¥¯¥È¤¬¾Ãµî¤µ¤ì¤Æ¤¤¤Þ¤·¤¿"
+
+#: if_tcl.c:1545
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥É¤òÅÐÏ¿¤Ç¤­¤Þ¤»¤ó: ¥Ð¥Ã¥Õ¥¡/¥¦¥£¥ó¥É¥¦¤¬´û¤Ë¾Ãµî¤µ¤ì¤Þ¤·¤¿"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to "
+"vim-dev@vim.org"
+msgstr ""
+"E280: TCL Ã×̿Ū¥¨¥é¡¼: reflist ±øÀ÷!? vim-dev@vim.org ¤ËÊó¹ð¤·¤Æ¤¯¤À¤µ¤¤"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥É¤òÅÐÏ¿¤Ç¤­¤Þ¤»¤ó: "
+"¥Ð¥Ã¥Õ¥¡/¥¦¥£¥ó¥É¥¦¤Î»²¾È¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"E571: ¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹,¤´¤á¤ó¤Ê¤µ¤¤: "
+"Tcl¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿."
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: TCL ¥¨¥é¡¼: ½ªÎ»¥³¡¼¥É¤¬À°¿ôÃͤǤϤ¢¤ê¤Þ¤»¤ó!? vim-dev@vim.org "
+"¤ËÊó¹ð¤·¤Æ¤¯¤À¤µ¤¤"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "¹Ô¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó"
+
+#: if_xcmdsrv.c:225
+msgid "Unable to register a command server name"
+msgstr "Ì¿Î᥵¡¼¥Ð¤Î̾Á°¤òÅÐÏ¿¤Ç¤­¤Þ¤»¤ó"
+
+#: if_xcmdsrv.c:473
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: ÌÜŪ¤Î¥×¥í¥°¥é¥à¤Ø¤Î¥³¥Þ¥ó¥ÉÁ÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: if_xcmdsrv.c:747
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: ̵¸ú¤Ê¥µ¡¼¥ÐID¤¬»È¤ï¤ì¤Þ¤·¤¿: %s"
+
+#: if_xcmdsrv.c:1110
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: VIM ¼ÂÂΤÎÅÐÏ¿¥×¥í¥Ñ¥Æ¥£¤¬ÉÔÀµ¤Ç¤¹. ¾Ãµî¤·¤Þ¤·¤¿!"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "̤ÃΤΥª¥×¥·¥ç¥ó¤Ç¤¹"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "ÊÔ½¸°ú¿ô¤¬Â¿¤¹¤®¤Þ¤¹"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "°ú¿ô¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "¥ª¥×¥·¥ç¥ó¤Î¸å¤Ë¥´¥ß¤¬¤¢¤ê¤Þ¤¹"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr "\"+command\", \"-c command\", \"--cmd command\" ¤Î°ú¿ô¤¬Â¿¤¹¤®¤Þ¤¹"
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "̵¸ú¤Ê°ú¿ô¤Ç¤¹: "
+
+#: main.c:466
+msgid "This Vim was not compiled with the diff feature."
+msgstr "¤³¤ÎVim¤Ë¤Ïdiffµ¡Ç½¤¬¤¢¤ê¤Þ¤»¤ó(¥³¥ó¥Ñ¥¤¥ë»þÀßÄê)."
+
+#: main.c:932
+msgid "Attempt to open script file again: \""
+msgstr "¥¹¥¯¥ê¥×¥È¥Õ¥¡¥¤¥ë¤òºÆ¤Ó³«¤¤¤Æ¤ß¤Þ¤¹: \""
+
+# msgid "\"\n"
+# msgstr "\"\n"
+#: main.c:941
+msgid "Cannot open for reading: \""
+msgstr "ÆɹþÍѤȤ·¤Æ³«¤±¤Þ¤»¤ó"
+
+#: main.c:985
+msgid "Cannot open for script output: \""
+msgstr "¥¹¥¯¥ê¥×¥È½ÐÎÏÍѤò³«¤±¤Þ¤»¤ó"
+
+#: main.c:1132
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d ¸Ä¤Î¥Õ¥¡¥¤¥ë¤¬ÊÔ½¸¤ò¹µ¤¨¤Æ¤¤¤Þ¤¹\n"
+
+#: main.c:1233
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: ·Ù¹ð: üËö¤Ø¤Î½ÐÎϤǤϤ¢¤ê¤Þ¤»¤ó\n"
+
+#: main.c:1235
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: ·Ù¹ð: üËö¤«¤é¤ÎÆþÎϤǤϤ¢¤ê¤Þ¤»¤ó\n"
+
+#. just in case..
+#: main.c:1297
+msgid "pre-vimrc command line"
+msgstr "vimrcÁ°¤Î¥³¥Þ¥ó¥É¥é¥¤¥ó"
+
+#: main.c:1338
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: \"%s\"¤«¤éÆɹþ¤à¤³¤È¤¬¤Ç¤­¤Þ¤»¤ó"
+
+#: main.c:2411
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"¤è¤ê¾ÜºÙ¤Ê¾ðÊó¤Ï: \"vim -h\"\n"
+
+#: main.c:2444
+msgid "[file ..] edit specified file(s)"
+msgstr "[¥Õ¥¡¥¤¥ë..] ¤¢¤ë¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤¹¤ë"
+
+#: main.c:2445
+msgid "- read text from stdin"
+msgstr "- ɸ½àÆþÎϤ«¤é¥Æ¥­¥¹¥È¤òÆɹþ¤à"
+
+#: main.c:2446
+msgid "-t tag edit file where tag is defined"
+msgstr "-t ¥¿¥° ¥¿¥°¤¬ÄêµÁ¤µ¤ì¤¿¤È¤³¤í¤«¤éÊÔ½¸¤¹¤ë"
+
+#: main.c:2448
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [errorfile] ºÇ½é¤Î¥¨¥é¡¼¤ÇÊÔ½¸¤¹¤ë"
+
+#: main.c:2457
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"»ÈÍÑË¡:"
+
+#: main.c:2460
+msgid " vim [arguments] "
+msgstr " vim [°ú¿ô]"
+
+#: main.c:2464
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" ¤â¤·¤¯¤Ï:"
+
+#: main.c:2467
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"°ú¿ô:\n"
+
+#: main.c:2468
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\t¤³¤Î¤¢¤È¤Ë¤Ï¥Õ¥¡¥¤¥ë̾¤À¤±"
+
+#: main.c:2470
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\t¥ï¥¤¥ë¥É¥«¡¼¥É¤òŸ³«¤·¤Ê¤¤"
+
+#: main.c:2473
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\t¤³¤Îgvim¤òOLE¤È¤·¤ÆÅÐÏ¿¤¹¤ë"
+
+#: main.c:2474
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tgvim¤ÎOLEÅÐÏ¿¤ò²ò½ü¤¹¤ë"
+
+#: main.c:2477
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tGUI¤Çµ¯Æ°¤¹¤ë (\"gvim\" ¤ÈƱ¤¸)"
+
+#: main.c:2478
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f or --nofork\t¥Õ¥©¥¢¥°¥é¥¦¥ó¥É: GUI¤ò»Ï¤á¤ë¤È¤­¤Ëfork¤·¤Ê¤¤"
+
+#: main.c:2480
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi¥â¡¼¥É (\"vi\" ¤ÈƱ¤¸)"
+
+#: main.c:2481
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx¥â¡¼¥É (\"ex\" ¤ÈƱ¤¸)"
+
+#: main.c:2482
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\t¥µ¥¤¥ì¥ó¥È(¥Ð¥Ã¥Á)¥â¡¼¥É (\"ex\" ÀìÍÑ)"
+
+#: main.c:2484
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tº¹Ê¬¥â¡¼¥É (\"vidiff\" ¤ÈƱ¤¸)"
+
+#: main.c:2486
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\t¥¤¡¼¥¸¡¼¥â¡¼¥É (\"evim\" ¤ÈƱ¤¸, ¥â¡¼¥É̵)"
+
+#: main.c:2487
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tÆɹþÀìÍѥ⡼¥É (\"view\" ¤ÈƱ¤¸)"
+
+#: main.c:2488
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tÀ©¸Â¥â¡¼¥É (\"rvim\" ¤ÈƱ¤¸)"
+
+#: main.c:2489
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tÊѹ¹ (¥Õ¥¡¥¤¥ëÊݸ»þ) ¤ò¤Ç¤­¤Ê¤¤¤è¤¦¤Ë¤¹¤ë"
+
+#: main.c:2490
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\t¥Æ¥­¥¹¥È¤ÎÊÔ½¸¤ò¹Ô¤Ê¤¨¤Ê¤¤¤è¤¦¤Ë¤¹¤ë"
+
+#: main.c:2491
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\t¥Ð¥¤¥Ê¥ê¥â¡¼¥É"
+
+#: main.c:2493
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp¥â¡¼¥É"
+
+#: main.c:2495
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tVi¸ß´¹¥â¡¼¥É: 'compatible'"
+
+#: main.c:2496
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tViÈó¸ß´¹¥â¡¼¥É: 'nocompatible"
+
+#: main.c:2497
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tVerbose ¥ì¥Ù¥ë"
+
+#: main.c:2498
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\t¥Ç¥Ð¥Ã¥°¥â¡¼¥É"
+
+#: main.c:2499
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\t¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ò»ÈÍѤ»¤º¥á¥â¥ê¤À¤±"
+
+#: main.c:2500
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\t¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤òÎóµó¤·½ªÎ»"
+
+#: main.c:2501
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (¥Õ¥¡¥¤¥ë̾)\t¥¯¥é¥Ã¥·¥å¤·¤¿¥»¥Ã¥·¥ç¥ó¤òÉüµ¢"
+
+#: main.c:2502
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\t-r¤ÈƱ¤¸"
+
+#: main.c:2504
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\t¥¦¥£¥ó¥É¥¦¤ò³«¤¯¤Î¤Ë newcli ¤ò»ÈÍѤ·¤Ê¤¤"
+
+#: main.c:2505
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <device>\t\tI/O¤Ë <device> ¤ò»ÈÍѤ¹¤ë"
+
+#: main.c:2508
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\t\t¥¢¥é¥Ó¥¢¸ì¥â¡¼¥É¤Çµ¯Æ°¤¹¤ë"
+
+#: main.c:2511
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\t¥Ø¥Ö¥é¥¤¸ì¥â¡¼¥É¤Çµ¯Æ°¤¹¤ë"
+
+#: main.c:2514
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\t¥Ú¥ë¥·¥¢¸ì¥â¡¼¥É¤Çµ¯Æ°¤¹¤ë"
+
+#: main.c:2516
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\tüËö¤ò <terminal> ¤ËÀßÄꤹ¤ë"
+
+#: main.c:2517
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\t.vimrc¤ÎÂå¤ï¤ê¤Ë <vimrc> ¤ò»È¤¦"
+
+#: main.c:2519
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\t.gvimrc¤ÎÂå¤ï¤ê¤Ë <gvimrc> ¤ò»È¤¦"
+
+#: main.c:2521
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\t¥×¥é¥°¥¤¥ó¥¹¥¯¥ê¥×¥È¤ò¥í¡¼¥É¤·¤Ê¤¤"
+
+#: main.c:2522
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tN ¸Ä¥¦¥£¥ó¥É¥¦¤ò³«¤¯(¾ÊάÃÍ: ¥Õ¥¡¥¤¥ë¤Ë¤Ä¤­1¸Ä)"
+
+#: main.c:2523
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\t-o¤ÈƱ¤¸¤À¤¬¿âľʬ³ä"
+
+#: main.c:2524
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\t¥Õ¥¡¥¤¥ë¤ÎºÇ¸å¤«¤é¤Ï¤¸¤á¤ë"
+
+#: main.c:2525
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\t<lnum> ¹Ô¤«¤é¤Ï¤¸¤á¤ë"
+
+#: main.c:2527
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <command>\tvimrc¤ò¥í¡¼¥É¤¹¤ëÁ°¤Ë <command> ¤ò¼Â¹Ô¤¹¤ë"
+
+#: main.c:2529
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <command>\t\tºÇ½é¤Î¥Õ¥¡¥¤¥ë¤ò¥í¡¼¥É¸å <command> ¤ò¼Â¹Ô¤¹¤ë"
+
+#: main.c:2530
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <session>\t\tºÇ½é¤Î¥Õ¥¡¥¤¥ë¤ò¥í¡¼¥É¸å¥Õ¥¡¥¤¥ë <session> ¤ò¼è¹þ¤à"
+
+#: main.c:2531
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <scriptin>\t¥Õ¥¡¥¤¥ë <scriptin> ¤«¤é¥Î¡¼¥Þ¥ë¥³¥Þ¥ó¥É¤òÆɹþ¤à"
+
+#: main.c:2532
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <scriptout>\tÆþÎϤ·¤¿Á´¥³¥Þ¥ó¥É¤ò¥Õ¥¡¥¤¥ë <scriptout> ¤ËÄɲ乤ë"
+
+#: main.c:2533
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <scriptout>\tÆþÎϤ·¤¿Á´¥³¥Þ¥ó¥É¤ò¥Õ¥¡¥¤¥ë <scriptout> ¤ËÊݸ¤¹¤ë"
+
+#: main.c:2535
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\t°Å¹æ²½¤µ¤ì¤¿¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤¹¤ë"
+
+#: main.c:2539
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\tvim¤ò»ØÄꤷ¤¿ X ¥µ¡¼¥Ð¤ËÀܳ¤¹¤ë"
+
+#: main.c:2541
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tX¥µ¡¼¥Ð¤ËÀܳ¤·¤Ê¤¤"
+
+#: main.c:2544
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <files>\t²Äǽ¤Ê¤é¤ÐVim¥µ¡¼¥Ð¤Ç <files> ¤òÊÔ½¸¤¹¤ë"
+
+#: main.c:2545
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-silnet <files> Ʊ¾å, ¥µ¡¼¥Ð¤¬Ìµ¤¯¤Æ¤â·Ù¹ðʸ¤ò½ÐÎϤ·¤Ê¤¤"
+
+#: main.c:2546
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <files>\t--remote¸å ¥Õ¥¡¥¤¥ë¤ÎÊÔ½¸¤¬½ª¤ï¤ë¤Î¤òÂÔ¤Ä"
+
+#: main.c:2547
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-wait-silent <files> Ʊ¾å, ¥µ¡¼¥Ð¤¬Ìµ¤¯¤Æ¤â·Ù¹ðʸ¤ò½ÐÎϤ·¤Ê¤¤"
+
+#: main.c:2548
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <keys>\tVim¥µ¡¼¥Ð¤Ë <keys> ¤òÁ÷¿®¤·¤Æ½ªÎ»¤¹¤ë"
+
+#: main.c:2549
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <expr>\t¥µ¡¼¥Ð¤Ç <expr> ¤ò¼Â¹Ô¤·¤Æ·ë²Ì¤òɽ¼¨¤¹¤ë"
+
+#: main.c:2550
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tVim¥µ¡¼¥Ð̾¤Î°ìÍ÷¤òɽ¼¨¤·¤Æ½ªÎ»¤¹¤ë"
+
+#: main.c:2551
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servename <name>\t\tVim¥µ¡¼¥Ð <name> ¤ËÁ÷¿®/̾Á°ÀßÄꤹ¤ë"
+
+#: main.c:2554
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\t.viminfo¤ÎÂå¤ï¤ê¤Ë <viminfo> ¤ò»È¤¦"
+
+#: main.c:2556
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h or --help\t¥Ø¥ë¥×(¤³¤Î¥á¥Ã¥»¡¼¥¸)¤òɽ¼¨¤·½ªÎ»¤¹¤ë"
+
+#: main.c:2557
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\t¥Ð¡¼¥¸¥ç¥ó¾ðÊó¤òɽ¼¨¤·½ªÎ»¤¹¤ë"
+
+#: main.c:2561
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(Motif¥Ð¡¼¥¸¥ç¥ó):\n"
+
+#: main.c:2565
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr ""
+"\n"
+"gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(neXtaw¥Ð¡¼¥¸¥ç¥ó):\n"
+
+#: main.c:2567
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(Athena¥Ð¡¼¥¸¥ç¥ó):\n"
+
+#: main.c:2571
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\t<display> ¤Çvim¤ò¼Â¹Ô¤¹¤ë"
+
+#: main.c:2572
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tºÇ¾®²½¤·¤¿¾õÂÖ¤Çvim¤òµ¯Æ°¤¹¤ë"
+
+#: main.c:2574
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <name>\t\tvim¤Î̾¤¬ <name> ¤Ç¤¢¤ë¤È¤·¤Æ¥ê¥½¡¼¥¹¤ò»È¤¦"
+
+#: main.c:2575
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (¼ÂÁõ¤µ¤ì¤Æ¤¤¤Ê¤¤)\n"
+
+#: main.c:2577
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <color>\tÇØ·Ê¿§¤Ë <color> ¤ò»È¤¦(ƱµÁ: -bg)"
+
+#: main.c:2578
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <color>\tÁ°·Ê¿§¤Ë <color> ¤ò»È¤¦(ƱµÁ: -fg)"
+
+#: main.c:2579 main.c:2599
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <font>\t\t¥Æ¥­¥¹¥Èɽ¼¨¤Ë <font> ¤ò»È¤¦(ƱµÁ: -fn)"
+
+#: main.c:2580
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <font>\tÂÀ»ú¤Ë <font> ¤ò»È¤¦"
+
+#: main.c:2581
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <for>\t¼ÐÂλú¤Ë <font> ¤ò»È¤¦"
+
+#: main.c:2582 main.c:2600
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\t½é´üÇÛÃÖ¤Ë <geom> ¤ò»È¤¦(ƱµÁ: -geom)"
+
+#: main.c:2583
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <width>\t¶­³¦¤ÎÉý¤ò <width> ¤Ë¤¹¤ë(ƱµÁ: -bw)"
+
+#: main.c:2584
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr ""
+"-scrollbarwidth <width> ¥¹¥¯¥í¡¼¥ë¥Ð¡¼¤ÎÉý¤ò <width> ¤Ë¤¹¤ë(ƱµÁ: -sw)"
+
+#: main.c:2586
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <height>\t¥á¥Ë¥å¡¼¥Ð¡¼¤Î¹â¤µ¤ò <height> ¤Ë¤¹¤ë(ƱµÁ: -mh)"
+
+#: main.c:2588 main.c:2601
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tȿž±ÇÁü¤ò»ÈÍѤ¹¤ë(ƱµÁ: -rv)"
+
+#: main.c:2589
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tȿž±ÇÁü¤ò»ÈÍѤ·¤Ê¤¤(ƱµÁ: +rv)"
+
+#: main.c:2590
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\tÆÃÄê¤Î¥ê¥½¡¼¥¹¤ò»ÈÍѤ¹¤ë"
+
+#: main.c:2593
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(RISC OS¥Ð¡¼¥¸¥ç¥ó):\n"
+
+#: main.c:2594
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <number>\t½é´ü¤Î¥¦¥£¥ó¥É¥¦¤Î¥³¥é¥àñ°Ì¤ÎÉý"
+
+#: main.c:2595
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <number>\t½é´ü¤Î¥¦¥£¥ó¥É¥¦¤Î¹Ôñ°Ì¤Î¹â¤µ"
+
+#: main.c:2598
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"gvim¤Ë¤è¤Ã¤Æ²ò¼á¤µ¤ì¤ë°ú¿ô(GTK+¥Ð¡¼¥¸¥ç¥ó):\n"
+
+#: main.c:2602
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\t<display> ¤Çvim¤ò¼Â¹Ô¤¹¤ë(ƱµÁ: --display)"
+
+#: main.c:2604
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr "--role <role>\t¥á¥¤¥ó¥¦¥£¥ó¥É¥¦¤ò¼±Ê̤¹¤ë°ì°Õ¤ÊÌò³ä(role)¤òÀßÄꤹ¤ë"
+
+#: main.c:2606
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\t°Û¤Ê¤ëGTK widget¤ÇVim¤ò³«¤¯"
+
+#: main.c:2609
+msgid "-P <parent title>\tOpen Vim inside parent application"
+msgstr "-P <¿Æ¤Î¥¿¥¤¥È¥ë>\tVim¤ò¿Æ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ÎÃæ¤Çµ¯Æ°¤¹¤ë"
+
+# msgid "--help\t\tShow Gnome arguments"
+# msgstr "--help\t\tGNOME¤Î°ú¿ô¤ò¸«¤»¤ë"
+#: main.c:2847
+msgid "No display"
+msgstr "¥Ç¥£¥¹¥×¥ì¥¤¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#. Failed to send, abort.
+#: main.c:2862
+msgid ": Send failed.\n"
+msgstr ": Á÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿.\n"
+
+#. Let vim start normally.
+#: main.c:2868
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": Á÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿. ¥í¡¼¥«¥ë¤Ç¤Î¼Â¹Ô¤ò»î¤ß¤Æ¤¤¤Þ¤¹\n"
+
+#: main.c:2906 main.c:2927
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d ¸Ä (%d ¸ÄÃæ) ¤Î¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤·¤Þ¤·¤¿"
+
+#: main.c:2949
+msgid "No display: Send expression failed.\n"
+msgstr "¥Ç¥£¥¹¥×¥ì¥¤¤¬¤¢¤ê¤Þ¤»¤ó: ¼°¤ÎÁ÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿.\n"
+
+#: main.c:2961
+msgid ": Send expression failed.\n"
+msgstr ": ¼°¤ÎÁ÷¿®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿.\n"
+
+#: mark.c:709
+msgid "No marks set"
+msgstr "¥Þ¡¼¥¯¤¬ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: mark.c:711
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: \"%s\" ¤Ë³ºÅö¤¹¤ë¥Þ¡¼¥¯¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#. Highlight title
+#: mark.c:722
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"mark ¹Ô Îó ¥Õ¥¡¥¤¥ë/¥Æ¥­¥¹¥È"
+
+#. Highlight title
+#: mark.c:760
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" jump ¹Ô Îó ¥Õ¥¡¥¤¥ë/¥Æ¥­¥¹¥È"
+
+#. Highlight title
+#: mark.c:805
+msgid ""
+"\n"
+"change line col text"
+msgstr ""
+"\n"
+"Êѹ¹ ¹Ô Îó ¥Æ¥­¥¹¥È"
+
+#: mark.c:1281
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# ¥Õ¥¡¥¤¥ë¥Þ¡¼¥¯:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1316
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# ¥¸¥ã¥ó¥×¥ê¥¹¥È (¿·¤·¤¤¤â¤Î¤¬Àè):\n"
+
+#: mark.c:1412
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# ¥Õ¥¡¥¤¥ëÆâ¥Þ¡¼¥¯¤ÎÍúÎò (¿·¤·¤¤¤â¤Î¤«¤é¸Å¤¤¤â¤Î):\n"
+
+#: mark.c:1501
+msgid "Missing '>'"
+msgstr "'>' ¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: mbyte.c:467
+msgid "E543: Not a valid codepage"
+msgstr "E543: ̵¸ú¤Ê¥³¡¼¥É¥Ú¡¼¥¸¤Ç¤¹"
+
+#: mbyte.c:4431
+msgid "E284: Cannot set IC values"
+msgstr "E284: IC¤ÎÃͤòÀßÄê¤Ç¤­¤Þ¤»¤ó"
+
+#: mbyte.c:4583
+msgid "E285: Failed to create input context"
+msgstr "E285: ¥¤¥ó¥×¥Ã¥È¥³¥ó¥Æ¥­¥¹¥È¤ÎºîÀ®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: mbyte.c:4741
+msgid "E286: Failed to open input method"
+msgstr "E286: ¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É¤Î¥ª¡¼¥×¥ó¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: mbyte.c:4752
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: ·Ù¹ð: IM¤ÎÇ˲õ¥³¡¼¥ë¥Ð¥Ã¥¯¤òÀßÄê¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: mbyte.c:4758
+msgid "E288: input method doesn't support any style"
+msgstr "E288: ¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É¤Ï¤É¤ó¤Ê¥¹¥¿¥¤¥ë¤â¥µ¥Ý¡¼¥È¤·¤Þ¤»¤ó"
+
+#: mbyte.c:4815
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: ¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É¤Ï my preedit type ¤ò¥µ¥Ý¡¼¥È¤·¤Þ¤»¤ó"
+
+#: mbyte.c:4889
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: over-the-spot ¥¹¥¿¥¤¥ë¤Ë¤Ïfontset¤¬É¬ÍפǤ¹"
+
+#: mbyte.c:4925
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: GTK+¤¬1.2.3¤è¤ê¤â¸Å¤¤¤Î¤Ç¥¹¥Æ¡¼¥¿¥¹¥¨¥ê¥¢¤¬Ìµ¸ú¤Ç¤¹"
+
+#: mbyte.c:5232
+msgid "E292: Input Method Server is not running"
+msgstr "E292: ¥¤¥ó¥×¥Ã¥È¥á¥½¥Ã¥É¥µ¡¼¥Ð ¤¬Æ°ºî¤·¤Æ¤¤¤Þ¤»¤ó"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: ¥Ö¥í¥Ã¥¯¤¬¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: memfile.c:1005
+msgid "E294: Seek error in swap file read"
+msgstr "E294: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ëÆɹþ»þ¤Ë¥·¡¼¥¯¥¨¥é¡¼¤Ç¤¹"
+
+#: memfile.c:1010
+msgid "E295: Read error in swap file"
+msgstr "E295: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ÎÆɹþ¤ß¥¨¥é¡¼¤Ç¤¹"
+
+#: memfile.c:1062
+msgid "E296: Seek error in swap file write"
+msgstr "E296: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë½ñ¹þ¤ß»þ¤Ë¥·¡¼¥¯¥¨¥é¡¼¤Ç¤¹"
+
+#: memfile.c:1080
+msgid "E297: Write error in swap file"
+msgstr "E297: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Î½ñ¹þ¤ß¥¨¥é¡¼¤Ç¤¹"
+
+#: memfile.c:1277
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬´û¤Ë¸ºß¤·¤Þ¤¹ (symlink¤Ë¤è¤ë¹¶·â?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: ¥Ö¥í¥Ã¥¯ 0 ¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: ¥Ö¥í¥Ã¥¯ 1 ¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: ¥Ö¥í¥Ã¥¯ 2 ¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: ¤ª¤Ã¤È, ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬¼º¤ï¤ì¤Þ¤·¤¿!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Î̾Á°¤òÊѤ¨¤é¤ì¤Þ¤»¤ó"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: \"%s\" ¤Î¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ò³«¤±¤Ê¤¤¤Î¤Ç¥ê¥«¥Ð¥ê¤ÏÉÔ²Äǽ¤Ç¤¹"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: ¥Ö¥í¥Ã¥¯ 0 ¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: %s ¤Ë¤Ï¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "»ÈÍѤ¹¤ë¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ÎÈÖ¹æ¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤(0 ¤Ç½ªÎ»): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: %s ¤ò³«¤±¤Þ¤»¤ó"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "¥Ö¥í¥Ã¥¯ 0 ¤òÆɹþ¤á¤Þ¤»¤ó "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"¶²¤é¤¯Êѹ¹¤¬¤µ¤ì¤Æ¤¤¤Ê¤¤¤«Vim¤¬¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ò¹¹¿·¤·¤Æ¤¤¤Þ¤»¤ó."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " Vim¤Î¤³¤Î¥Ð¡¼¥¸¥ç¥ó¤Ç¤Ï»ÈÍѤǤ­¤Þ¤»¤ó.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Vim¤Î¥Ð¡¼¥¸¥ç¥ó3.0¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s ¤ÏVim¤Î¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Ç¤Ï¤Ê¤¤¤è¤¦¤Ç¤¹"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " ¤³¤Î¥³¥ó¥Ô¥å¡¼¥¿¤Ç¤Ï»ÈÍѤǤ­¤Þ¤»¤ó.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "¤³¤Î¥Õ¥¡¥¤¥ë¤Ï¼¡¤Î¾ì½ê¤Çºî¤é¤ì¤Þ¤·¤¿ "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"¤â¤·¤¯¤Ï¥Õ¥¡¥¤¥ë¤¬Â»½ý¤·¤Æ¤¤¤Þ¤¹."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë \"%s\" ¤ò»ÈÍÑÃæ"
+
+#: memline.c:909
+#, c-format
+msgid "Original file \"%s\""
+msgstr "¸¶ËÜ¥Õ¥¡¥¤¥ë \"%s\""
+
+#: memline.c:922
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: ·Ù¹ð: ¸¶ËÜ¥Õ¥¡¥¤¥ë¤¬Êѹ¹¤µ¤ì¤Æ¤¤¤Þ¤¹"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: %s ¤«¤é¥Ö¥í¥Ã¥¯ 1 ¤òÆɹþ¤á¤Þ¤»¤ó"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???¿¤¯¤Î¹Ô¤¬¼º¤ï¤ì¤Æ¤¤¤Þ¤¹"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???¹Ô¿ô¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???¥Ö¥í¥Ã¥¯¤¬¶õ¤Ç¤¹"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???¹Ô¤¬¼º¤ï¤ì¤Æ¤¤¤Þ¤¹"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ¥Ö¥í¥Ã¥¯ 1 ¤ÎID¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹(%s ¤¬.swp¥Õ¥¡¥¤¥ë¤Ç¤Ê¤¤?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???¥Ö¥í¥Ã¥¯¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? ¤³¤³¤«¤é???END¤Þ¤Ç¤Î¹Ô¤¬Ç˲õ¤µ¤ì¤Æ¤¤¤ë¤è¤¦¤Ç¤¹"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? ¤³¤³¤«¤é??END¤Þ¤Ç¤Î¹Ô¤¬ÁÞÆþ¤«ºï½ü¤µ¤ì¤¿¤è¤¦¤Ç¤¹"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???END"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: ¥ê¥«¥Ð¥ê¤¬³ä¹þ¤Þ¤ì¤Þ¤·¤¿"
+
+#: memline.c:1148
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr ""
+"E312: ¥ê¥«¥Ð¥ê¤ÎºÇÃæ¤Ë¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤Þ¤·¤¿; ???¤Ç»Ï¤Þ¤ë¹Ô¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤"
+
+#: memline.c:1150
+msgid "See \":help E312\" for more information."
+msgstr "¾ÜºÙ¤Ï \":help E312\" ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤"
+
+#: memline.c:1155
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "¥ê¥«¥Ð¥ê¤¬½ªÎ»¤·¤Þ¤·¤¿. Á´¤Æ¤¬Àµ¤·¤¤¤«¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤."
+
+#: memline.c:1156
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Êѹ¹¤ò¥Á¥§¥Ã¥¯¤¹¤ë¤¿¤á¤Ë, ¤³¤Î¥Õ¥¡¥¤¥ë¤òÊ̤Î̾Á°¤ÇÊݸ¤·¤¿¾å¤Ç\n"
+
+#: memline.c:1157
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "¸¶ËÜ¥Õ¥¡¥¤¥ë¤È¤Î diff ¤ò¼Â¹Ô¤¹¤ë¤ÈÎɤ¤¤Ç¤·¤ç¤¦)\n"
+
+#: memline.c:1158
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"¤½¤ì¤«¤é.swp¥Õ¥¡¥¤¥ë¤òºï½ü¤·¤Æ¤¯¤À¤µ¤¤\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1214
+msgid "Swap files found:"
+msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬Ê£¿ô¸«¤Ä¤«¤ê¤Þ¤·¤¿:"
+
+#: memline.c:1392
+msgid " In current directory:\n"
+msgstr " ¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê:\n"
+
+#: memline.c:1394
+msgid " Using specified name:\n"
+msgstr " ¤¢¤ë̾Á°¤ò»ÈÍÑÃæ:\n"
+
+#: memline.c:1398
+msgid " In directory "
+msgstr " ¥Ç¥£¥ì¥¯¥È¥ê "
+
+#: memline.c:1416
+msgid " -- none --\n"
+msgstr " -- ¤Ê¤· --\n"
+
+#: memline.c:1488
+msgid " owned by: "
+msgstr " ½êÍ­¼Ô: "
+
+#: memline.c:1490
+msgid " dated: "
+msgstr " ÆüÉÕ: "
+
+#: memline.c:1494 memline.c:3684
+msgid " dated: "
+msgstr " ÆüÉÕ: "
+
+#: memline.c:1510
+msgid " [from Vim version 3.0]"
+msgstr " [from Vim version 3.0]"
+
+#: memline.c:1514
+msgid " [does not look like a Vim swap file]"
+msgstr " [Vim¤Î¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Ç¤Ï¤Ê¤¤¤è¤¦¤Ç¤¹]"
+
+#: memline.c:1518
+msgid " file name: "
+msgstr " ¥Õ¥¡¥¤¥ë̾: "
+
+#: memline.c:1524
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" Êѹ¹¾õÂÖ: "
+
+#: memline.c:1525
+msgid "YES"
+msgstr "¤¢¤ê"
+
+#: memline.c:1525
+msgid "no"
+msgstr "¤Ê¤·"
+
+#: memline.c:1529
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" ¥æ¡¼¥¶Ì¾: "
+
+#: memline.c:1536
+msgid " host name: "
+msgstr " ¥Û¥¹¥È̾: "
+
+#: memline.c:1538
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" ¥Û¥¹¥È̾: "
+
+#: memline.c:1544
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ¥×¥í¥»¥¹ID: "
+
+#: memline.c:1550
+msgid " (still running)"
+msgstr " (¤Þ¤À¼Â¹ÔÃæ)"
+
+#: memline.c:1562
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [¤³¤ÎVim¥Ð¡¼¥¸¥ç¥ó¤Ç¤Ï»ÈÍѤǤ­¤Þ¤»¤ó]"
+
+#: memline.c:1565
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [¤³¤Î¥³¥ó¥Ô¥å¡¼¥¿¤Ç¤Ï»ÈÍѤǤ­¤Þ¤»¤ó]"
+
+#: memline.c:1570
+msgid " [cannot be read]"
+msgstr " [Æɹþ¤á¤Þ¤»¤ó]"
+
+#: memline.c:1574
+msgid " [cannot be opened]"
+msgstr " [³«¤±¤Þ¤»¤ó]"
+
+#: memline.c:1764
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬Ìµ¤¤¤Î¤Ç°Ý»ý¤Ç¤­¤Þ¤»¤ó"
+
+#: memline.c:1817
+msgid "File preserved"
+msgstr "¥Õ¥¡¥¤¥ë¤¬°Ý»ý¤µ¤ì¤Þ¤¹"
+
+#: memline.c:1819
+msgid "E314: Preserve failed"
+msgstr "E314: °Ý»ý¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: memline.c:1890
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: ̵¸ú¤Êlnum¤Ç¤¹: %ld"
+
+#: memline.c:1916
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: ¹Ô %ld ¤ò¤ß¤Ä¤±¤é¤ì¤Þ¤»¤ó"
+
+#: memline.c:2306
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: ¥Ý¥¤¥ó¥¿¥Ö¥í¥Ã¥¯¤ÎID¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹ 3"
+
+#: memline.c:2386
+msgid "stack_idx should be 0"
+msgstr "stack_idx ¤Ï 0 ¤Ç¤¢¤ë¤Ù¤­¤Ç¤¹"
+
+#: memline.c:2448
+msgid "E318: Updated too many blocks?"
+msgstr "E318: ¹¹¿·¤µ¤ì¤¿¥Ö¥í¥Ã¥¯¤¬Â¿¤¹¤®¤ë¤«¤â?"
+
+#: memline.c:2630
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: ¥Ý¥¤¥ó¥¿¥Ö¥í¥Ã¥¯¤ÎID¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹ 4"
+
+#: memline.c:2657
+msgid "deleted block 1?"
+msgstr "¥Ö¥í¥Ã¥¯ 1 ¤Ï¾Ã¤µ¤ì¤¿?"
+
+#: memline.c:2857
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: ¹Ô %ld ¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: memline.c:3100
+msgid "E317: pointer block id wrong"
+msgstr "E317: ¥Ý¥¤¥ó¥¿¥Ö¥í¥Ã¥¯¤ÎID¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹"
+
+#: memline.c:3116
+msgid "pe_line_count is zero"
+msgstr "pe_line_count ¤¬¥¼¥í¤Ç¤¹"
+
+#: memline.c:3145
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: ¹ÔÈֹ椬Èϰϳ°¤Ç¤¹: %ld Ķ¤¨¤Æ¤¤¤Þ¤¹"
+
+#: memline.c:3149
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: ¥Ö¥í¥Ã¥¯ %ld ¤Î¹Ô¥«¥¦¥ó¥È¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹"
+
+#: memline.c:3198
+msgid "Stack size increases"
+msgstr "¥¹¥¿¥Ã¥¯¥µ¥¤¥º¤¬Áý¤¨¤Þ¤¹"
+
+#: memline.c:3244
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: ¥Ý¥¤¥ó¥¿¥Ö¥í¥Ã¥¯¤ÎID¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹ 2"
+
+#: memline.c:3674
+msgid "E325: ATTENTION"
+msgstr "E325: Ãí°Õ"
+
+#: memline.c:3675
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"¼¡¤Î̾Á°¤Ç¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤ò¸«¤Ä¤±¤Þ¤·¤¿ \""
+
+#: memline.c:3679
+msgid "While opening file \""
+msgstr "¼¡¤Î¥Õ¥¡¥¤¥ë¤ò³«¤¤¤Æ¤¤¤ëºÇÃæ \""
+
+#: memline.c:3688
+msgid " NEWER than swap file!\n"
+msgstr " ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤è¤ê¤â¿·¤·¤¤¤Ç¤¹!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3692
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) ÊÌ¤Î¥×¥í¥°¥é¥à¤¬Æ±¤¸¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤·¤Æ¤¤¤ë¤«¤â¤·¤ì¤Þ¤»¤ó.\n"
+" ¤³¤Î¾ì¹ç¤Ë¤Ï, Êѹ¹¤ò¤·¤¿ºÝ¤ËºÇ½ªÅª¤Ë, Ʊ¤¸¥Õ¥¡¥¤¥ë¤Î°Û¤Ê¤ë\n"
+" 2¤Ä¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤¬¤Ç¤­¤Æ¤·¤Þ¤¦¤³¤È¤ËÃí°Õ¤·¤Æ¤¯¤À¤µ¤¤.\n"
+
+#: memline.c:3693
+msgid " Quit, or continue with caution.\n"
+msgstr " ½ªÎ»¤¹¤ë¤«, Ãí°Õ¤·¤Ê¤¬¤é³¤±¤Þ¤¹.\n"
+
+#: memline.c:3694
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) ¤³¤Î¥Õ¥¡¥¤¥ë¤ÎÊÔ½¸¥»¥Ã¥·¥ç¥ó¤¬¥¯¥é¥Ã¥·¥å¤·¤¿.\n"
+
+#: memline.c:3695
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " ¤³¤Î¾ì¹ç¤Ë¤Ï \":recover\" ¤« \"vim -r "
+
+#: memline.c:3697
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" ¤ò»ÈÍѤ·¤ÆÊѹ¹¤ò¥ê¥«¥Ð¡¼¤·¤Þ¤¹(\":help recover\" ¤ò»²¾È).\n"
+
+#: memline.c:3698
+msgid " If you did this already, delete the swap file \""
+msgstr " ´û¤Ë¤³¤ì¤ò¹Ô¤Ê¤Ã¤¿¤Î¤Ê¤é¤Ð, ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë \""
+
+#: memline.c:3700
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" ¤ò¾Ã¤»¤Ð¤³¤Î¥á¥Ã¥»¡¼¥¸¤ò²óÈò¤Ç¤­¤Þ¤¹.\n"
+
+#: memline.c:3714 memline.c:3718
+msgid "Swap file \""
+msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë \""
+
+#: memline.c:3715 memline.c:3721
+msgid "\" already exists!"
+msgstr "\" ¤¬´û¤Ë¤¢¤ê¤Þ¤¹!"
+
+#: memline.c:3724
+msgid "VIM - ATTENTION"
+msgstr "VIM - Ãí°Õ"
+
+#: memline.c:3726
+msgid "Swap file already exists!"
+msgstr "¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬´û¤Ë¸ºß¤·¤Þ¤¹!"
+
+#: memline.c:3730
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort"
+msgstr ""
+"ÆɹþÀìÍѤdz«¤¯(&O)\n"
+"¤È¤Ë¤«¤¯ÊÔ½¸¤¹¤ë(&E)\n"
+"Éü³è¤µ¤»¤ë(&R)ecover\n"
+"½ªÎ»¤¹¤ë(&Q)\n"
+"Ãæ»ß¤¹¤ë(&A)"
+
+#: memline.c:3732
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort\n"
+"&Delete it"
+msgstr ""
+"ÆɹþÀìÍѤdz«¤¯(&O)\n"
+"¤È¤Ë¤«¤¯ÊÔ½¸¤¹¤ë(&E)\n"
+"Éü³è¤µ¤»¤ë(&R)ecover\n"
+"½ªÎ»¤¹¤ë(&Q)\n"
+"Ãæ»ß¤¹¤ë(&A)\n"
+"¾Ãµî¤¹¤ë(&D)"
+
+#: memline.c:3789
+msgid "E326: Too many swap files found"
+msgstr "E326: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤¬Â¿¿ô¸«¤Ä¤«¤ê¤Þ¤·¤¿"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: ¥á¥Ë¥å¡¼¥¢¥¤¥Æ¥à¤Î¥Ñ¥¹¤ÎÉôʬ¤¬¥µ¥Ö¥á¥Ë¥å¡¼¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: ¥á¥Ë¥å¡¼¤Ï¾¤Î¥â¡¼¥É¤Ë¤À¤±¤¢¤ê¤Þ¤¹"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: ¤½¤Î̾Á°¤Î¥á¥Ë¥å¡¼¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: menu.c:525
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: ¥á¥Ë¥å¡¼¥Ñ¥¹¤Ï¥µ¥Ö¥á¥Ë¥å¡¼¤òÀ¸¤¸¤ë¤Ù¤­¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: menu.c:564
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: ¥á¥Ë¥å¡¼¥Ð¡¼¤Ë¤ÏľÀÜ¥á¥Ë¥å¡¼¥¢¥¤¥Æ¥à¤òÄɲäǤ­¤Þ¤»¤ó"
+
+#: menu.c:570
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: ¶èÀÚ¤ê¤Ï¥á¥Ë¥å¡¼¥Ñ¥¹¤Î°ìÉô¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1097
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- ¥á¥Ë¥å¡¼ ---"
+
+#: menu.c:2019
+msgid "Tear off this menu"
+msgstr "¤³¤Î¥á¥Ë¥å¡¼¤òÀÚ¤ê¼è¤ë"
+
+#: menu.c:2084
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: ¥á¥Ë¥å¡¼¥Ñ¥¹¤Ï¥á¥Ë¥å¡¼¥¢¥¤¥Æ¥à¤òÀ¸¤¸¤Ê¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó"
+
+#: menu.c:2104
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: ¥á¥Ë¥å¡¼¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó: %s"
+
+#: menu.c:2173
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: %s ¤Ë¤Ï¥á¥Ë¥å¡¼¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: menu.c:2211
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: ¥á¥Ë¥å¡¼¥Ñ¥¹¤Ï¥µ¥Ö¥á¥Ë¥å¡¼¤òÀ¸¤¸¤Ê¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó"
+
+#: menu.c:2232
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: ¥á¥Ë¥å¡¼¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó - ¥á¥Ë¥å¡¼Ì¾¤ò³Îǧ¤·¤Æ¤¯¤À¤µ¤¤"
+
+#: message.c:414
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "%s ¤Î½èÍýÃæ¤Ë¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤Þ¤·¤¿:"
+
+#: message.c:440
+#, c-format
+msgid "line %4ld:"
+msgstr "¹Ô %4ld:"
+
+#: message.c:647
+msgid "[string too long]"
+msgstr "[ʸ»úÎó¤¬Ä¹¤¹¤®¤Þ¤¹]"
+
+#: message.c:797
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "ÆüËܸì¥á¥Ã¥»¡¼¥¸ËÝÌõ/´Æ½¤: ¼²¬ ÂÀϺ <koron@tka.att.ne.jp>"
+
+#: message.c:1025
+msgid "Interrupt: "
+msgstr "³ä¹þ¤ß: "
+
+#: message.c:1028
+msgid "Hit ENTER to continue"
+msgstr "³¤±¤ë¤Ë¤ÏENTER¤ò²¡¤·¤Æ¤¯¤À¤µ¤¤"
+
+#: message.c:1030
+msgid "Hit ENTER or type command to continue"
+msgstr "³¤±¤ë¤Ë¤ÏENTER¤ò²¡¤¹¤«¥³¥Þ¥ó¥É¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤"
+
+#: message.c:2351
+msgid "-- More --"
+msgstr "-- ·Ñ³ --"
+
+#: message.c:2354
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: ¹ÔÁ÷¤ê, SPACE/b: ¥Ú¡¼¥¸Á÷¤ê, d/u: Ⱦ¥Ú¡¼¥¸Á÷¤ê, q: ½ªÎ»)"
+
+#: message.c:2355
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: ¹ÔÁ÷¤ê, SPACE: ¥Ú¡¼¥¸Á÷¤ê, d: Ⱦ¥Ú¡¼¥¸Á÷¤ê, q: ½ªÎ»)"
+
+#: message.c:2976 message.c:2991
+msgid "Question"
+msgstr "¼ÁÌä"
+
+#: message.c:2978
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"¤Ï¤¤(&Y)\n"
+"¤¤¤¤¤¨(&N)"
+
+#: message.c:3011
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"¤Ï¤¤(&Y)\n"
+"¤¤¤¤¤¨(&N)\n"
+"Á´¤ÆÊݸ(&A)\n"
+"Á´¤ÆÊü´þ(&D)\n"
+"¥­¥ã¥ó¥»¥ë(&C)"
+
+#: message.c:3052
+msgid "Save File dialog"
+msgstr "¥Õ¥¡¥¤¥ëÊݸ¥À¥¤¥¢¥í¥°"
+
+#: message.c:3054
+msgid "Open File dialog"
+msgstr "¥Õ¥¡¥¤¥ëÆɹþ¥À¥¤¥¢¥í¥°"
+
+#. TODO: non-GUI file selector here
+#: message.c:3125
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: ¥³¥ó¥½¡¼¥ë¥â¡¼¥É¤Ç¤Ï¥Õ¥¡¥¤¥ë¥Ö¥é¥¦¥¶¤ò»È¤¨¤Þ¤»¤ó, ¤´¤á¤ó¤Ê¤µ¤¤"
+
+#: misc1.c:2773
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: ·Ù¹ð: ÆɹþÀìÍÑ¥Õ¥¡¥¤¥ë¤òÊѹ¹¤·¤Þ¤¹"
+
+#: misc1.c:3021
+msgid "1 more line"
+msgstr "1 ¹Ô Äɲä·¤Þ¤·¤¿"
+
+#: misc1.c:3023
+msgid "1 line less"
+msgstr "1 ¹Ô ºï½ü¤·¤Þ¤·¤¿"
+
+#: misc1.c:3028
+#, c-format
+msgid "%ld more lines"
+msgstr "%ld ¹Ô Äɲä·¤Þ¤·¤¿"
+
+#: misc1.c:3030
+#, c-format
+msgid "%ld fewer lines"
+msgstr "%ld ¹Ô ºï½ü¤·¤Þ¤·¤¿"
+
+#: misc1.c:3033
+msgid " (Interrupted)"
+msgstr " (³ä¹þ¤Þ¤ì¤Þ¤·¤¿)"
+
+#: misc1.c:7582
+msgid "Vim: preserving files...\n"
+msgstr "Vim: ¥Õ¥¡¥¤¥ë¤òÊݸÃæ...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:7592
+msgid "Vim: Finished.\n"
+msgstr "Vim: ½ªÎ»¤·¤Þ¤·¤¿.\n"
+
+#: misc2.c:695 misc2.c:711
+msgid "ERROR: "
+msgstr "¥¨¥é¡¼: "
+
+#: misc2.c:715
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[¥á¥â¥ê(¥Ð¥¤¥È)] Áí³äÅö-²òÊüÎÌ %lu-%lu, »ÈÍÑÎÌ %lu, ¥Ô¡¼¥¯»þ %lu\n"
+
+#: misc2.c:717
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[¸Æ½Ð] Áí re/malloc() ²ó¿ô %lu, Áí free() ²ó¿ô %lu\n"
+"\n"
+
+#: misc2.c:772
+msgid "E340: Line is becoming too long"
+msgstr "E340: ¹Ô¤¬Ä¹¤¯¤Ê¤ê¤¹¤®¤Þ¤·¤¿"
+
+#: misc2.c:816
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: ÆâÉô¥¨¥é¡¼: lalloc(%ld,)"
+
+#: misc2.c:924
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: ¥á¥â¥ê¤¬Â­¤ê¤Þ¤»¤ó! (%lu ¥Ð¥¤¥È¤ò³äÅöÍ×µá)"
+
+#: misc2.c:2593
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "¼Â¹Ô¤Î¤¿¤á¤Ë¥·¥§¥ë¤ò¸Æ½Ð¤·Ãæ: \"%s\""
+
+#: misc2.c:2815
+msgid "E545: Missing colon"
+msgstr "E545: ¥³¥í¥ó¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: misc2.c:2817 misc2.c:2844
+msgid "E546: Illegal mode"
+msgstr "E546: ÉÔÀµ¤Ê¥â¡¼¥É¤Ç¤¹"
+
+#: misc2.c:2883
+msgid "E547: Illegal mouseshape"
+msgstr "E547: ÉÔÀµ¤Ê 'mouseshape' ¤Ç¤¹"
+
+#: misc2.c:2923
+msgid "E548: digit expected"
+msgstr "E548: ¿ôÃͤ¬É¬ÍפǤ¹"
+
+#: misc2.c:2928
+msgid "E549: Illegal percentage"
+msgstr "E549: ÉÔÀµ¤Ê¥Ñ¡¼¥»¥ó¥Æ¡¼¥¸¤Ç¤¹"
+
+#: misc2.c:3238
+msgid "Enter encryption key: "
+msgstr "°Å¹æ²½ÍѤΥ­¡¼¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤: "
+
+#: misc2.c:3239
+msgid "Enter same key again: "
+msgstr "¤â¤¦°ìÅÙƱ¤¸¥­¡¼¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤: "
+
+#: misc2.c:3249
+msgid "Keys don't match!"
+msgstr "¥­¡¼¤¬°ìÃפ·¤Þ¤»¤ó"
+
+#: misc2.c:3798
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: ̵¸ú¤Ê¥Ñ¥¹¤Ç¤¹: '**[¿ôÃÍ]' ¤Ïpath¤ÎºÇ¸å¤« '%s' "
+"¤¬Â³¤¤¤Æ¤Ê¤¤¤È¤¤¤±¤Þ¤»¤ó."
+
+#: misc2.c:5077
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: cdpath¤Ë¤Ï \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: misc2.c:5080
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: path¤Ë¤Ï \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: misc2.c:5086
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: cdpath¤Ë¤Ï¤³¤ì°Ê¾å \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: misc2.c:5089
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: ¥Ñ¥¹¤Ë¤Ï¤³¤ì°Ê¾å \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: misc2.c:5323
+msgid "E550: Missing colon"
+msgstr "E550: ¥³¥í¥ó¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: misc2.c:5335
+msgid "E551: Illegal component"
+msgstr "E551: ÉÔÀµ¤Ê¹½Ê¸Í×ÁǤǤ¹"
+
+#: misc2.c:5343
+msgid "E552: digit expected"
+msgstr "E552: ¿ôÃͤ¬É¬ÍפǤ¹"
+
+#. Get here when the server can't be found.
+#: netbeans.c:396
+msgid "Cannot connect to Netbeans #2"
+msgstr "Netbeans #2 ¤ËÀܳ¤Ç¤­¤Þ¤»¤ó"
+
+#: netbeans.c:404
+msgid "Cannot connect to Netbeans"
+msgstr "Netbeans ¤ËÀܳ¤Ç¤­¤Þ¤»¤ó"
+
+#: netbeans.c:450
+#, c-format
+msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\""
+msgstr ""
+"E668: NetBeans¤ÎÀܳ¾ðÊó¥Õ¥¡¥¤¥ë¤Î¥¢¥¯¥»¥¹¥â¡¼¥É¤ËÌäÂ꤬¤¢¤ê¤Þ¤¹: \"%s\""
+
+#: netbeans.c:749
+msgid "read from Netbeans socket"
+msgstr "Netbeans ¤Î¥½¥±¥Ã¥È¤òÆɹþ¤ß"
+
+#: netbeans.c:1638
+#, c-format
+msgid "E658: NetBeans connection lost for buffer %ld"
+msgstr "E658: ¥Ð¥Ã¥Õ¥¡ %ld ¤Î NetBeans Àܳ¤¬¼º¤ï¤ì¤Þ¤·¤¿"
+
+#: normal.c:2980
+msgid "Warning: terminal cannot highlight"
+msgstr "·Ù¹ð: »ÈÍѤ·¤Æ¤¤¤ëüËö¤Ï¥Ï¥¤¥é¥¤¥È¤Ç¤­¤Þ¤»¤ó"
+
+#: normal.c:3276
+msgid "E348: No string under cursor"
+msgstr "E348: ¥«¡¼¥½¥ë¤Î°ÌÃ֤ˤÏʸ»úÎ󤬤¢¤ê¤Þ¤»¤ó"
+
+#: normal.c:3278
+msgid "E349: No identifier under cursor"
+msgstr "E349: ¥«¡¼¥½¥ë¤Î°ÌÃ֤ˤϼ±Ê̻Ҥ¬¤¢¤ê¤Þ¤»¤ó"
+
+#: normal.c:4519
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: ¸½ºß¤Î 'foldmethod' ¤Ç¤ÏÀÞ¾ö¤ß¤ò¾Ãµî¤Ç¤­¤Þ¤»¤ó"
+
+#: normal.c:6708
+msgid "E664: changelist is empty"
+msgstr "E664: Êѹ¹¥ê¥¹¥È¤¬¶õ¤Ç¤¹"
+
+#: normal.c:6710
+msgid "E662: At start of changelist"
+msgstr "E662: Êѹ¹¥ê¥¹¥È¤ÎÀèƬ"
+
+#: normal.c:6712
+msgid "E663: At end of changelist"
+msgstr "E663: Êѹ¹¥ê¥¹¥È¤ÎËöÈø"
+
+#: normal.c:7973
+msgid "Type :quit<Enter> to exit Vim"
+msgstr "Vim¤ò½ªÎ»¤¹¤ë¤Ë¤Ï :quit<Enter> ¤ÈÆþÎϤ·¤Æ¤¯¤À¤µ¤¤"
+
+#: ops.c:294
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "1 ¹Ô¤¬ %s ¤Ç 1 ²ó½èÍý¤µ¤ì¤Þ¤·¤¿"
+
+#: ops.c:296
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 ¹Ô¤¬ %s ¤Ç %d ²ó½èÍý¤µ¤ì¤Þ¤·¤¿"
+
+#: ops.c:301
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld ¹Ô¤¬ %s ¤Ç 1 ²ó½èÍý¤µ¤ì¤Þ¤·¤¿"
+
+#: ops.c:304
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld ¹Ô¤¬ %s ¤Ç %d ²ó½èÍý¤µ¤ì¤Þ¤·¤¿"
+
+#: ops.c:662
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld ¹Ô¤¬¥¤¥ó¥Ç¥ó¥È¤µ¤ì¤Þ¤¹... "
+
+#: ops.c:712
+msgid "1 line indented "
+msgstr "1 ¹Ô¤ò¥¤¥ó¥Ç¥ó¥È¤·¤Þ¤·¤¿"
+
+#: ops.c:714
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld ¹Ô¤ò¥¤¥ó¥Ç¥ó¥È¤·¤Þ¤·¤¿"
+
+#. must display the prompt
+#: ops.c:1675
+msgid "cannot yank; delete anyway"
+msgstr "¥ä¥ó¥¯¤Ç¤­¤Þ¤»¤ó; ¤È¤Ë¤«¤¯¾Ãµî"
+
+#: ops.c:2185
+msgid "1 line changed"
+msgstr "1 ¹Ô¤¬Êѹ¹¤µ¤ì¤Þ¤·¤¿"
+
+#: ops.c:2187
+#, c-format
+msgid "%ld lines changed"
+msgstr "%ld ¹Ô¤¬Êѹ¹¤µ¤ì¤Þ¤·¤¿"
+
+#: ops.c:2571
+#, c-format
+msgid "freeing %ld lines"
+msgstr "%ld ¹Ô¤ò³«ÊüÃæ"
+
+#: ops.c:2852
+msgid "1 line yanked"
+msgstr "1 ¹Ô¤¬¥ä¥ó¥¯¤µ¤ì¤Þ¤·¤¿"
+
+#: ops.c:2854
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld ¹Ô¤¬¥ä¥ó¥¯¤µ¤ì¤Þ¤·¤¿"
+
+#: ops.c:3139
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: ¥ì¥¸¥¹¥¿ %s ¤Ë¤Ï²¿¤â¤¢¤ê¤Þ¤»¤ó"
+
+#. Highlight title
+#: ops.c:3690
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- ¥ì¥¸¥¹¥¿ ---"
+
+#: ops.c:4997
+msgid "Illegal register name"
+msgstr "ÉÔÀµ¤Ê¥ì¥¸¥¹¥¿Ì¾"
+
+#: ops.c:5085
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# ¥ì¥¸¥¹¥¿:\n"
+
+#: ops.c:5135
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: ̤ÃΤΥ쥸¥¹¥¿·¿ %d ¤Ç¤¹"
+
+#: ops.c:5620
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: ̵¸ú¤Ê¥ì¥¸¥¹¥¿Ì¾: '%s'"
+
+#: ops.c:5980
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Îó; "
+
+#: ops.c:5987
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "ÁªÂò %s%ld / %ld ¹Ô; %ld / %ld ñ¸ì; %ld / %ld ʸ»ú"
+
+#: ops.c:6003
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Îó %s / %s; ¹Ô %ld of %ld; ñ¸ì %ld / %ld; ʸ»ú %ld / %ld"
+
+#: ops.c:6014
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld for BOM)"
+
+#: option.c:1643
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=%N ¥Ú¡¼¥¸"
+
+#: option.c:2092
+msgid "Thanks for flying Vim"
+msgstr "Vim ¤ò»È¤Ã¤Æ¤¯¤ì¤Æ¤¢¤ê¤¬¤È¤¦"
+
+#: option.c:3419 option.c:3535
+msgid "E518: Unknown option"
+msgstr "E518: ̤ÃΤΥª¥×¥·¥ç¥ó¤Ç¤¹"
+
+#: option.c:3432
+msgid "E519: Option not supported"
+msgstr "E519: ¥ª¥×¥·¥ç¥ó¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: option.c:3457
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: modeline ¤Ç¤Ïµö²Ä¤µ¤ì¤Þ¤»¤ó"
+
+#: option.c:3522
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tLast set from "
+
+#: option.c:3661
+msgid "E521: Number required after ="
+msgstr "E521: = ¤Î¸å¤Ë¤Ï¿ô»ú¤¬É¬ÍפǤ¹"
+
+#: option.c:3989 option.c:4619
+msgid "E522: Not found in termcap"
+msgstr "E522: termcap Æâ¤Ë¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: option.c:4064
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: ÉÔÀµ¤Êʸ»ú¤Ç¤¹ <%s>"
+
+#: option.c:4611
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: 'term' ¤Ë¤Ï¶õʸ»úÎó¤òÀßÄê¤Ç¤­¤Þ¤»¤ó"
+
+#: option.c:4614
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: GUI¤Ç¤Ï 'term' ¤òÊѹ¹¤Ç¤­¤Þ¤»¤ó"
+
+#: option.c:4616
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: GUI¤ò¥¹¥¿¡¼¥È¤¹¤ë¤Ë¤Ï \":gui\" ¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤"
+
+#: option.c:4645
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: 'backupext' ¤È 'patchmode' ¤¬Æ±¤¸¤Ç¤¹"
+
+#: option.c:4860
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: GTK+2 GUI¤Ç¤ÏÊѹ¹¤Ç¤­¤Þ¤»¤ó"
+
+#: option.c:5016
+msgid "E524: Missing colon"
+msgstr "E524: ¥³¥í¥ó¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: option.c:5018
+msgid "E525: Zero length string"
+msgstr "E525: ʸ»úÎó¤ÎŤµ¤¬¥¼¥í¤Ç¤¹"
+
+#: option.c:5086
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: <%s> ¤Î¸å¤Ë¿ô»ú¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: option.c:5100
+msgid "E527: Missing comma"
+msgstr "E527: ¥«¥ó¥Þ¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: option.c:5107
+msgid "E528: Must specify a ' value"
+msgstr "E528: ' ¤ÎÃͤò»ØÄꤷ¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó"
+
+#: option.c:5148
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: ɽ¼¨¤Ç¤­¤Ê¤¤Ê¸»ú¤«¥ï¥¤¥Éʸ»ú¤ò´Þ¤ó¤Ç¤¤¤Þ¤¹"
+
+#: option.c:5197
+msgid "E596: Invalid font(s)"
+msgstr "E596: ̵¸ú¤Ê¥Õ¥©¥ó¥È¤Ç¤¹"
+
+#: option.c:5205
+msgid "E597: can't select fontset"
+msgstr "E597: ¥Õ¥©¥ó¥È¥»¥Ã¥È¤òÁªÂò¤Ç¤­¤Þ¤»¤ó"
+
+#: option.c:5207
+msgid "E598: Invalid fontset"
+msgstr "E598: ̵¸ú¤Ê¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ç¤¹"
+
+#: option.c:5214
+msgid "E533: can't select wide font"
+msgstr "E533: ¥ï¥¤¥É¥Õ¥©¥ó¥È¤òÁªÂò¤Ç¤­¤Þ¤»¤ó"
+
+#: option.c:5216
+msgid "E534: Invalid wide font"
+msgstr "E534: ̵¸ú¤Ê¥ï¥¤¥É¥Õ¥©¥ó¥È¤Ç¤¹"
+
+#: option.c:5486
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: <%c> ¤Î¸å¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤¹"
+
+#: option.c:5597
+msgid "E536: comma required"
+msgstr "E536: ¥«¥ó¥Þ¤¬É¬ÍפǤ¹"
+
+#: option.c:5607
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: 'commentstring' ¤Ï¶õ¤Ç¤¢¤ë¤« %s ¤ò´Þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹"
+
+#: option.c:5679
+msgid "E538: No mouse support"
+msgstr "E538: ¥Þ¥¦¥¹¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó"
+
+#: option.c:5947
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: ¼°¤¬½ªÎ»¤·¤Æ¤¤¤Þ¤»¤ó"
+
+#: option.c:5951
+msgid "E541: too many items"
+msgstr "E541: Í×ÁǤ¬Â¿¤¹¤®¤Þ¤¹"
+
+#: option.c:5953
+msgid "E542: unbalanced groups"
+msgstr "E542: ¥°¥ë¡¼¥×¤¬Äà¹ç¤¤¤Þ¤»¤ó"
+
+#: option.c:6193
+msgid "E590: A preview window already exists"
+msgstr "E590: ¥×¥ì¥Ó¥å¡¼¥¦¥£¥ó¥É¥¦¤¬´û¤Ë¸ºß¤·¤Þ¤¹"
+
+#: option.c:6450
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr ""
+"W17: ¥¢¥é¥Ó¥¢Ê¸»ú¤Ë¤ÏUTF-8¤¬É¬ÍפʤΤÇ, ':set encoding=utf-8' ¤·¤Æ¤¯¤À¤µ¤¤"
+
+#: option.c:6776
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: ºÇÄã %d ¤Î¹Ô¿ô¤¬É¬ÍפǤ¹"
+
+#: option.c:6786
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: ºÇÄã %d ¤Î¥«¥é¥àÉý¤¬É¬ÍפǤ¹"
+
+#: option.c:7093
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: ̤ÃΤΥª¥×¥·¥ç¥ó¤Ç¤¹: %s"
+
+#: option.c:7213
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- üËö¥³¡¼¥É ---"
+
+#: option.c:7215
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- ¥°¥í¡¼¥Ð¥ë¥ª¥×¥·¥ç¥óÃÍ ---"
+
+#: option.c:7217
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- ¥í¡¼¥«¥ë¥ª¥×¥·¥ç¥óÃÍ ---"
+
+#: option.c:7219
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- ¥ª¥×¥·¥ç¥ó ---"
+
+#: option.c:7925
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp ¥¨¥é¡¼"
+
+#: option.c:8896
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': %s ¤ËÂбþ¤¹¤ëʸ»ú¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: option.c:8930
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': ¥»¥ß¥³¥í¥ó¤Î¸å¤Ë;ʬ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤¹: %s"
+
+#: os_amiga.c:280
+msgid "cannot open "
+msgstr "³«¤±¤Þ¤»¤ó "
+
+#: os_amiga.c:314
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: ¥¦¥£¥ó¥É¥¦¤ò³«¤±¤Þ¤»¤ó!\n"
+
+#: os_amiga.c:338
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Amigados¤Î¥Ð¡¼¥¸¥ç¥ó 2.04¤«¤½¤ì°Ê¹ß¤¬É¬ÍפǤ¹\n"
+
+#: os_amiga.c:344
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "%s ¤Î¥Ð¡¼¥¸¥ç¥ó %ld ¤¬É¬ÍפǤ¹\n"
+
+#: os_amiga.c:416
+msgid "Cannot open NIL:\n"
+msgstr "NIL¤ò³«¤±¤Þ¤»¤ó:\n"
+
+#: os_amiga.c:427
+msgid "Cannot create "
+msgstr "ºîÀ®¤Ç¤­¤Þ¤»¤ó "
+
+#: os_amiga.c:905
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim¤Ï %d ¤Ç½ªÎ»¤·¤Þ¤¹\n"
+
+#: os_amiga.c:937
+msgid "cannot change console mode ?!\n"
+msgstr "¥³¥ó¥½¡¼¥ë¥â¡¼¥É¤òÊѹ¹¤Ç¤­¤Þ¤»¤ó?!\n"
+
+#: os_amiga.c:1003
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: ¥³¥ó¥½¡¼¥ë¤Ç¤Ï¤Ê¤¤??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1152
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: -f ¥ª¥×¥·¥ç¥ó¤Ç¥·¥§¥ë¤ò¼Â¹Ô¤Ç¤­¤Þ¤»¤ó"
+
+#: os_amiga.c:1193 os_amiga.c:1283
+msgid "Cannot execute "
+msgstr "¼Â¹Ô¤Ç¤­¤Þ¤»¤ó "
+
+#: os_amiga.c:1196 os_amiga.c:1293
+msgid "shell "
+msgstr "¥·¥§¥ë "
+
+#: os_amiga.c:1216 os_amiga.c:1318
+msgid " returned\n"
+msgstr " Ìá¤ê¤Þ¤·¤¿\n"
+
+#: os_amiga.c:1459
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE ¤¬¾®¤µ¤¹¤®¤Þ¤¹."
+
+#: os_amiga.c:1463
+msgid "I/O ERROR"
+msgstr "Æþ½ÐÎÏ¥¨¥é¡¼"
+
+#: os_mswin.c:539
+msgid "...(truncated)"
+msgstr "...(¾Êά)"
+
+#: os_mswin.c:641
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' ¤¬80¤Ç¤Ï¤Ê¤¤¤¿¤á, ³°Éô¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤Ç¤­¤Þ¤»¤ó"
+
+#: os_mswin.c:1973
+msgid "E237: Printer selection failed"
+msgstr "E237: ¥×¥ê¥ó¥¿¤ÎÁªÂò¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: os_mswin.c:2013
+#, c-format
+msgid "to %s on %s"
+msgstr "%s ¤Ø (%s ¾å¤Î)"
+
+#: os_mswin.c:2028
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: ̤ÃΤΥץê¥ó¥¿¥ª¥×¥·¥ç¥ó¤Ç¤¹: %s"
+
+#: os_mswin.c:2077 os_mswin.c:2087
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: °õºþ¥¨¥é¡¼: %s"
+
+#: os_mswin.c:2088
+msgid "Unknown"
+msgstr "ÉÔÌÀ"
+
+#: os_mswin.c:2115
+#, c-format
+msgid "Printing '%s'"
+msgstr "°õºþ¤·¤Æ¤¤¤Þ¤¹: '%s'"
+
+#: os_mswin.c:3204
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: ʸ»ú¥»¥Ã¥È̾ \"%s\" ¤ÏÉÔÀµ¤Ç¤¹ (¥Õ¥©¥ó¥È̾ \"%s\")"
+
+#: os_mswin.c:3212
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: '%c' ¤ÏÉÔÀµ¤Êʸ»ú¤Ç¤¹ (¥Õ¥©¥ó¥È̾ \"%s\")"
+
+#: os_riscos.c:1259
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: ̵¸ú¤Ê 'osfiletype' ¥ª¥×¥·¥ç¥ó - \"Text\" ¤ò»È¤¤¤Þ¤¹"
+
+#: os_unix.c:927
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: 2½Å¤Î¥·¥°¥Ê¥ë¤Î¤¿¤á, ½ªÎ»¤·¤Þ¤¹\n"
+
+#: os_unix.c:933
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Ã×̿Ū¥·¥°¥Ê¥ë %s ¤ò¸¡ÃΤ·¤Þ¤·¤¿\n"
+
+#: os_unix.c:936
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Ã×̿Ū¥·¥°¥Ê¥ë¤ò¸¡ÃΤ·¤Þ¤·¤¿\n"
+
+#: os_unix.c:1199
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "X¥µ¡¼¥Ð¤Ø¤ÎÀܳ¤Ë %ld ¥ß¥êÉ䫤«¤ê¤Þ¤·¤¿"
+
+#: os_unix.c:1226
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: X ¤Î¥¨¥é¡¼¤ò¸¡½Ð¤·¤Þ¤·¤¿r\n"
+
+#: os_unix.c:1334
+msgid "Testing the X display failed"
+msgstr "X display ¤Î¥Á¥§¥Ã¥¯¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: os_unix.c:1473
+msgid "Opening the X display timed out"
+msgstr "X display ¤Î open ¤¬¥¿¥¤¥à¥¢¥¦¥È¤·¤Þ¤·¤¿"
+
+#: os_unix.c:3227 os_unix.c:3907
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"¥·¥§¥ë¤ò¼Â¹Ô¤Ç¤­¤Þ¤»¤ó "
+
+#: os_unix.c:3275
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"sh ¥·¥§¥ë¤ò¼Â¹Ô¤Ç¤­¤Þ¤»¤ó\n"
+
+#: os_unix.c:3279 os_unix.c:3913
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"¥·¥§¥ë¤¬ÃͤòÊÖ¤·¤Þ¤·¤¿ "
+
+#: os_unix.c:3414
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"¥Ñ¥¤¥×¤òºîÀ®¤Ç¤­¤Þ¤»¤ó\n"
+
+#: os_unix.c:3429
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"fork ¤Ç¤­¤Þ¤»¤ó\n"
+
+#: os_unix.c:3920
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"¥³¥Þ¥ó¥É¤òÃæÃǤ·¤Þ¤·¤¿\n"
+
+#: os_unix.c:4184 os_unix.c:4309 os_unix.c:5975
+msgid "XSMP lost ICE connection"
+msgstr "XSMP ¤¬ICEÀܳ¤ò¼º¤¤¤Þ¤·¤¿"
+
+#: os_unix.c:5558
+msgid "Opening the X display failed"
+msgstr "X display ¤Î open ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: os_unix.c:5880
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP ¤¬save-yourselfÍ×µá¤ò½èÍý¤·¤Æ¤¤¤Þ¤¹"
+
+#: os_unix.c:5999
+msgid "XSMP opening connection"
+msgstr "XSMP ¤¬Àܳ¤ò³«»Ï¤·¤Æ¤¤¤Þ¤¹"
+
+#: os_unix.c:6018
+msgid "XSMP ICE connection watch failed"
+msgstr "XSMP ICEÀܳ¤¬¼ºÇÔ¤·¤¿¤è¤¦¤Ç¤¹"
+
+#: os_unix.c:6038
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP SmcOpenConnection¤¬¼ºÇÔ¤·¤Þ¤·¤¿: %s"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "¹Ô"
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "¥³¥Þ¥ó¥É¥é¥¤¥ó¤Ë¥á¥â¥ê¤ò³ä¤êÅö¤Æ¤é¤ì¤Þ¤»¤ó"
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "VIM¥¨¥é¡¼"
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "vim32.dll ¤ò¥í¡¼¥É¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "DLL¤«¤é´Ø¿ô¥Ý¥¤¥ó¥¿¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: os_win16.c:342 os_win32.c:3197
+#, c-format
+msgid "shell returned %d"
+msgstr "¥·¥§¥ë¤¬¥³¡¼¥É %d ¤Ç½ªÎ»¤·¤Þ¤·¤¿"
+
+#: os_win32.c:2655
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: ¥¤¥Ù¥ó¥È %s ¤ò¸¡ÃÎ\n"
+
+#: os_win32.c:2657
+msgid "close"
+msgstr "ÊĤ¸¤ë"
+
+#: os_win32.c:2659
+msgid "logoff"
+msgstr "¥í¥°¥ª¥Õ"
+
+#: os_win32.c:2660
+msgid "shutdown"
+msgstr "¥·¥ã¥Ã¥È¥À¥¦¥ó"
+
+#: os_win32.c:3150
+msgid "E371: Command not found"
+msgstr "E371: ¥³¥Þ¥ó¥É¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: os_win32.c:3163
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE¤¬ $PATH ¤ÎÃæ¤Ë¤ß¤Ä¤«¤ê¤Þ¤»¤ó.\n"
+"³°Éô¥³¥Þ¥ó¥É¤Î½ªÎ»¸å¤Ë°ì»þÄä»ß¤ò¤·¤Þ¤»¤ó.\n"
+"¾ÜºÙ¤Ï :help win32-vimrun ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤."
+
+#: os_win32.c:3166
+msgid "Vim Warning"
+msgstr "Vim¤Î·Ù¹ð"
+
+#: quickfix.c:258
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: ¥Õ¥©¡¼¥Þ¥Ã¥Èʸ»úÎó¤Ë %%%c ¤¬Â¿¤¹¤®¤Þ¤¹"
+
+#: quickfix.c:271
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: ¥Õ¥©¡¼¥Þ¥Ã¥Èʸ»úÎó¤Ëͽ´ü¤»¤Ì %%%c ¤¬¤¢¤ê¤Þ¤·¤¿"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: ¥Õ¥©¡¼¥Þ¥Ã¥Èʸ»úÎó¤Ë ] ¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: quickfix.c:339
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: ¥Õ¥©¡¼¥Þ¥Ã¥Èʸ»úÎó¤Ç¤Ï %%%c ¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó"
+
+#: quickfix.c:357
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: ¥Õ¥©¡¼¥Þ¥Ã¥Èʸ»úÎó¤ÎÁ°ÃÖ¤Ë̵¸ú¤Ê %%%c ¤¬¤¢¤ê¤Þ¤¹"
+
+#: quickfix.c:365
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: ¥Õ¥©¡¼¥Þ¥Ã¥Èʸ»úÎó¤Ë̵¸ú¤Ê %%%c ¤¬¤¢¤ê¤Þ¤¹"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' ¤Ë¥Ñ¥¿¡¼¥ó¤¬»ØÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: quickfix.c:501
+msgid "E379: Missing or empty directory name"
+msgstr "E379: ¥Ç¥£¥ì¥¯¥È¥ê̾¤¬Ìµ¤¤¤«¶õ¤Ç¤¹"
+
+#: quickfix.c:990
+msgid "E553: No more items"
+msgstr "E553: Í×ÁǤ¬¤â¤¦¤¢¤ê¤Þ¤»¤ó"
+
+#: quickfix.c:1229
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d of %d)%s%s: "
+
+#: quickfix.c:1231
+msgid " (line deleted)"
+msgstr " (¹Ô¤¬ºï½ü¤µ¤ì¤Þ¤·¤¿)"
+
+#: quickfix.c:1444
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: quickfix ¥¹¥¿¥Ã¥¯¤ÎËöÈø¤Ç¤¹"
+
+#: quickfix.c:1453
+msgid "E381: At top of quickfix stack"
+msgstr "E381: quickfix ¥¹¥¿¥Ã¥¯¤ÎÀèƬ¤Ç¤¹"
+
+#: quickfix.c:1465
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "¥¨¥é¡¼°ìÍ÷ %d of %d; %d ¸Ä¥¨¥é¡¼"
+
+#: quickfix.c:1943
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: 'buftype' ¥ª¥×¥·¥ç¥ó¤¬ÀßÄꤵ¤ì¤Æ¤¤¤ë¤Î¤Ç½ñ¹þ¤ß¤Þ¤»¤ó"
+
+#: regexp.c:838
+msgid "E339: Pattern too long"
+msgstr "E339: ¥Ñ¥¿¡¼¥ó¤¬Ä¹¤¹¤®¤Þ¤¹"
+
+#: regexp.c:1009
+msgid "E50: Too many \\z("
+msgstr "E50: \\z( ¤¬Â¿¤¹¤®¤Þ¤¹"
+
+#: regexp.c:1020
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: %s( ¤¬Â¿¤¹¤®¤Þ¤¹"
+
+#: regexp.c:1077
+msgid "E52: Unmatched \\z("
+msgstr "E52: \\z( ¤¬Äà¤ê¹ç¤Ã¤Æ¤¤¤Þ¤»¤ó"
+
+#: regexp.c:1081
+msgid "E53: Unmatched %s%%("
+msgstr "E53: %s%%( ¤¬Äà¤ê¹ç¤Ã¤Æ¤¤¤Þ¤»¤ó"
+
+#: regexp.c:1083
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: %s( ¤¬Äà¤ê¹ç¤Ã¤Æ¤¤¤Þ¤»¤ó"
+
+#: regexp.c:1088
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: %s) ¤¬Äà¤ê¹ç¤Ã¤Æ¤¤¤Þ¤»¤ó"
+
+#: regexp.c:1258
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: %s* ¤¬¶õʸ»úÎó¤Ë¤Ê¤ë²ÄǽÀ­¤¬¤¢¤ê¤Þ¤¹"
+
+#: regexp.c:1261
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: %s+ ¤¬¶õʸ»úÎó¤Ë¤Ê¤ë²ÄǽÀ­¤¬¤¢¤ê¤Þ¤¹"
+
+#: regexp.c:1316
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: %s@ ¤Î¸å¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤·¤¿"
+
+#: regexp.c:1344
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: %s{ ¤¬¶õʸ»úÎó¤Ë¤Ê¤ë²ÄǽÀ­¤¬¤¢¤ê¤Þ¤¹"
+
+#: regexp.c:1354
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: Ê£»¨¤Ê %s{...} ¤¬Â¿¤¹¤®¤Þ¤¹"
+
+#: regexp.c:1370
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61:%s* ¤¬Æþ¤ì»Ò¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹"
+
+#: regexp.c:1373
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62:%s%c ¤¬Æþ¤ì»Ò¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹"
+
+#
+#: regexp.c:1491
+msgid "E63: invalid use of \\_"
+msgstr "E63: \\_ ¤Î̵¸ú¤Ê»ÈÍÑÊýË¡¤Ç¤¹"
+
+#: regexp.c:1536
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64:%s%c ¤Î¸å¤Ë¤Ê¤Ë¤â¤¢¤ê¤Þ¤»¤ó"
+
+#
+#: regexp.c:1592
+msgid "E65: Illegal back reference"
+msgstr "E65: ÉÔÀµ¤Ê¸åÊý»²¾È¤Ç¤¹"
+
+#
+#: regexp.c:1605
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z( ¤Ï¥³¥³¤Ç¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#
+#: regexp.c:1624
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 ¤½¤Î¾¤Ï¥³¥³¤Ç¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#
+#: regexp.c:1635
+msgid "E68: Invalid character after \\z"
+msgstr "E68: \\z ¤Î¸å¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤·¤¿"
+
+#
+#: regexp.c:1684
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: %s%%[ ¤Î¸å¤Ë ] ¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: regexp.c:1700
+msgid "E70: Empty %s%%[]"
+msgstr "E70: %s%%[] ¤¬¶õ¤Ç¤¹"
+
+#
+#: regexp.c:1760
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: %s%% ¤Î¸å¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤·¤¿"
+
+#: regexp.c:2557
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: %s{...} Æâ¤Ëʸˡ¥¨¥é¡¼¤¬¤¢¤ê¤Þ¤¹"
+
+#: regexp.c:2863 regexp.c:3016
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: ¥¯¥é¥Ã¥·¥å¤Ë¤è¤êÃæÃÇ; Àµµ¬É½¸½¤¬Ê£»¨²á¤®¤ë¤«¤â?"
+
+#: regexp.c:3004 regexp.c:3013
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: ¥Ñ¥¿¡¼¥ó¤Ë¤è¤ë¥¹¥¿¥Ã¥¯ÉÔ­¥¨¥é¡¼¤Ç¤¹"
+
+#: regexp.c:3258
+msgid "External submatches:\n"
+msgstr "³°Éô¤ÎÉôʬ³ºÅö:\n"
+
+#: screen.c:2143
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld ¹Ô¤¬ÀÞ¾ö¤Þ¤ì¤Þ¤·¤¿"
+
+#: screen.c:7959
+msgid " VREPLACE"
+msgstr " ²¾ÁÛÃÖ´¹"
+
+#: screen.c:7963
+msgid " REPLACE"
+msgstr " ÃÖ´¹"
+
+#: screen.c:7968
+msgid " REVERSE"
+msgstr " ȿž"
+
+#: screen.c:7970
+msgid " INSERT"
+msgstr " ÁÞÆþ"
+
+#: screen.c:7973
+msgid " (insert)"
+msgstr " (ÁÞÆþ)"
+
+#: screen.c:7975
+msgid " (replace)"
+msgstr " (ÃÖ´¹)"
+
+#: screen.c:7977
+msgid " (vreplace)"
+msgstr " (²¾ÁÛÃÖ´¹)"
+
+#: screen.c:7980
+msgid " Hebrew"
+msgstr " ¥Ø¥Ö¥é¥¤"
+
+#: screen.c:7991
+msgid " Arabic"
+msgstr " ¥¢¥é¥Ó¥¢"
+
+#: screen.c:7994
+msgid " (lang)"
+msgstr " (¸À¸ì)"
+
+#: screen.c:7998
+msgid " (paste)"
+msgstr " (Ž¤êÉÕ¤±)"
+
+#: screen.c:8011
+msgid " VISUAL"
+msgstr " ¥Ó¥¸¥å¥¢¥ë"
+
+#: screen.c:8012
+msgid " VISUAL LINE"
+msgstr " ¥Ó¥¸¥å¥¢¥ë ¹Ô"
+
+#: screen.c:8013
+msgid " VISUAL BLOCK"
+msgstr " ¥Ó¥¸¥å¥¢¥ë ¶ë·Á"
+
+#: screen.c:8014
+msgid " SELECT"
+msgstr " ¥»¥ì¥¯¥È"
+
+#: screen.c:8015
+msgid " SELECT LINE"
+msgstr " ¹Ô»Ø¸þÁªÂò"
+
+#: screen.c:8016
+msgid " SELECT BLOCK"
+msgstr " ¶ë·ÁÁªÂò"
+
+# msgid " BLOCK"
+# msgstr " ¥Ö¥í¥Ã¥¯"
+# msgid " LINE"
+# msgstr " ¹Ô"
+#: screen.c:8031 screen.c:8094
+msgid "recording"
+msgstr "µ­Ï¿Ãæ"
+
+#: search.c:37
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "¾å¤Þ¤Ç¸¡º÷¤·¤¿¤Î¤Ç²¼¤ËÌá¤ê¤Þ¤¹"
+
+#: search.c:38
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "²¼¤Þ¤Ç¸¡º÷¤·¤¿¤Î¤Ç¾å¤ËÌá¤ê¤Þ¤¹"
+
+#: search.c:526
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: ̵¸ú¤Ê¸¡º÷ʸ»úÎó¤Ç¤¹: %s"
+
+#: search.c:853
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: ¾å¤Þ¤Ç¸¡º÷¤·¤¿¤±¤ì¤É³ºÅö²Õ½ê¤Ï¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: search.c:856
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: ²¼¤Þ¤Ç¸¡º÷¤·¤¿¤±¤ì¤É³ºÅö²Õ½ê¤Ï¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: search.c:1249
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: ';' ¤Î¤¢¤È¤Ë¤Ï '?' ¤« '/' ¤¬´üÂÔ¤µ¤ì¤Æ¤¤¤ë"
+
+#: search.c:3758
+msgid " (includes previously listed match)"
+msgstr " (Á°¤ËÎóµó¤·¤¿³ºÅö²Õ½ê¤ò´Þ¤à)"
+
+#. cursor at status line
+#: search.c:3778
+msgid "--- Included files "
+msgstr "--- ¥¤¥ó¥¯¥ë¡¼¥É¤µ¤ì¤¿¥Õ¥¡¥¤¥ë"
+
+#: search.c:3780
+msgid "not found "
+msgstr "¤ß¤Ä¤«¤ê¤Þ¤»¤ó "
+
+#: search.c:3781
+msgid "in path ---\n"
+msgstr "¥Ñ¥¹¤Ë ----\n"
+
+#: search.c:3820
+msgid " (Already listed)"
+msgstr " (´û¤ËÎóµó)"
+
+#: search.c:3822
+msgid " NOT FOUND"
+msgstr " ¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: search.c:3874
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "¥¤¥ó¥¯¥ë¡¼¥É¤µ¤ì¤¿¥Õ¥¡¥¤¥ë¤ò¥¹¥­¥ã¥óÃæ: %s"
+
+#: search.c:4092
+msgid "E387: Match is on current line"
+msgstr "E387: ¸½ºß¹Ô¤Ë³ºÅö¤¬¤¢¤ê¤Þ¤¹"
+
+#: search.c:4235
+msgid "All included files were found"
+msgstr "Á´¤Æ¤Î¥¤¥ó¥¯¥ë¡¼¥É¤µ¤ì¤¿¥Õ¥¡¥¤¥ë¤¬¤ß¤Ä¤«¤ê¤Þ¤·¤¿"
+
+#: search.c:4237
+msgid "No included files"
+msgstr "¥¤¥ó¥¯¥ë¡¼¥É¥Õ¥¡¥¤¥ë¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: search.c:4253
+msgid "E388: Couldn't find definition"
+msgstr "E388: ÄêµÁ¤ò¤ß¤Ä¤±¤é¤ì¤Þ¤»¤ó"
+
+#: search.c:4255
+msgid "E389: Couldn't find pattern"
+msgstr "E389: ¥Ñ¥¿¡¼¥ó¤ò¤ß¤Ä¤±¤é¤ì¤Þ¤»¤ó"
+
+#: syntax.c:3050
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: ÉÔÀµ¤Ê°ú¿ô¤Ç¤¹: %s"
+
+#: syntax.c:3230
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: ¤½¤Î¤è¤¦¤Ê¹½Ê¸¥¯¥é¥¹¥¿¤Ï¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: syntax.c:3394
+msgid "No Syntax items defined for this buffer"
+msgstr "¤³¤Î¥Ð¥Ã¥Õ¥¡¤ËÄêµÁ¤µ¤ì¤¿¹½Ê¸Í×ÁǤϤ¢¤ê¤Þ¤»¤ó"
+
+#: syntax.c:3402
+msgid "syncing on C-style comments"
+msgstr "C¸À¸ìÉ÷¥³¥á¥ó¥È¤«¤éƱ´üÃæ"
+
+#: syntax.c:3410
+msgid "no syncing"
+msgstr "ÈóƱ´ü"
+
+#: syntax.c:3413
+msgid "syncing starts "
+msgstr "Ʊ´ü³«»Ï "
+
+#: syntax.c:3415 syntax.c:3490
+msgid " lines before top line"
+msgstr " ¹ÔÁ°(¥È¥Ã¥×¹Ô¤è¤ê¤â)"
+
+#: syntax.c:3420
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- ¹½Ê¸Æ±´üÍ×ÁÇ ---"
+
+#: syntax.c:3425
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"Í×ÁǾå¤ÇƱ´üÃæ"
+
+#: syntax.c:3431
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- ¹½Ê¸Í×ÁÇ ---"
+
+#: syntax.c:3454
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: ¤½¤Î¤è¤¦¤Ê¹½Ê¸¥¯¥é¥¹¥¿¤Ï¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: syntax.c:3480
+msgid "minimal "
+msgstr "minimal"
+
+#: syntax.c:3487
+msgid "maximal "
+msgstr "maximal"
+
+#: syntax.c:3499
+msgid "; match "
+msgstr "; ³ºÅö "
+
+#: syntax.c:3501
+msgid " line breaks"
+msgstr " ¸Ä¤Î²þ¹Ô"
+
+#: syntax.c:4135
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: ¤³¤³¤Ç¤Ï¥°¥ë¡¼¥×¤Ïµö²Ä¤µ¤ì¤Þ¤»¤ó"
+
+#: syntax.c:4159
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: %s ¤ÎÈÏ°ÏÍ×ÁǤ¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: syntax.c:4187
+msgid "E395: contains argument not accepted here"
+msgstr "E395: ¤³¤Î¾ì½ê¤Ç¤Ï°ú¿ôcontains¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: syntax.c:4198
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: ¤³¤Î¾ì½ê¤Ç¤Ï°ú¿ôcontainedin¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: syntax.c:4276
+msgid "E397: Filename required"
+msgstr "E397: ¥Õ¥¡¥¤¥ë̾¤¬É¬ÍפǤ¹"
+
+#: syntax.c:4614
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: '=' ¤¬¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: syntax.c:4772
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: °ú¿ô¤¬Â­¤ê¤Þ¤»¤ó: ¹½Ê¸ÈÏ°Ï %s"
+
+#: syntax.c:5103
+msgid "E400: No cluster specified"
+msgstr "E400: ¥¯¥é¥¹¥¿¤¬»ØÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: syntax.c:5140
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: ¥Ñ¥¿¡¼¥ó¶èÀڤ꤬¤ß¤Ä¤«¤ê¤Þ¤»¤ó: %s"
+
+#: syntax.c:5215
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: ¥Ñ¥¿¡¼¥ó¤Î¤¢¤È¤Ë¥´¥ß¤¬¤¢¤ê¤Þ¤¹: %s"
+
+#: syntax.c:5305
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: ¹½Ê¸Æ±´ü: Ϣ³¹Ô¥Ñ¥¿¡¼¥ó¤¬2ÅÙ»ØÄꤵ¤ì¤Þ¤·¤¿"
+
+#: syntax.c:5362
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: ÉÔÀµ¤Ê°ú¿ô¤Ç¤¹: %s"
+
+#: syntax.c:5412
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Åù¤·¤¤ sign ¤¬¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: syntax.c:5418
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: ¶õ¤Î°ú¿ô: %s"
+
+#: syntax.c:5445
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s ¤Ï¥³¥³¤Ç¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: syntax.c:5452
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s ¤ÏÆâÍƥꥹ¥È¤ÎÀèƬ¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤"
+
+#: syntax.c:5522
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: ̤ÃΤΥ°¥ë¡¼¥×̾: %s"
+
+#: syntax.c:5755
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: ̵¸ú¤Ê :syntax ¤Î¥µ¥Ö¥³¥Þ¥ó¥É: %s"
+
+#: syntax.c:6134
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: ¥Ï¥¤¥é¥¤¥È¥°¥ë¡¼¥×¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó: %s"
+
+#: syntax.c:6158
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: °ú¿ô¤¬½¼Ê¬¤Ç¤Ï¤Ê¤¤: \":highlight link %s\""
+
+#: syntax.c:6165
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: °ú¿ô¤¬Â¿¤¹¤®¤Þ¤¹: \":highlight link %s\""
+
+#: syntax.c:6185
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: ¥°¥ë¡¼¥×¤¬ÀßÄꤵ¤ì¤Æ¤¤¤ë¤Î¤Ç¥Ï¥¤¥é¥¤¥È¥ê¥ó¥¯¤Ï̵»ë¤µ¤ì¤Þ¤¹"
+
+#: syntax.c:6314
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: ͽ´ü¤»¤ÌƱ¤¸ sign ¤Ç¤¹: %s"
+
+#: syntax.c:6350
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: Ʊ¤¸ sign ¤¬¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: syntax.c:6378
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: °ú¿ô¤¬¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: syntax.c:6415
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: ÉÔÀµ¤ÊÃͤǤ¹: %s"
+
+#: syntax.c:6534
+msgid "E419: FG color unknown"
+msgstr "E419: ̤ÃΤÎÁ°·Ê¿§¤Ç¤¹"
+
+#: syntax.c:6545
+msgid "E420: BG color unknown"
+msgstr "E420: ̤ÃΤÎÇØ·Ê¿§¤Ç¤¹"
+
+#: syntax.c:6606
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: ¥«¥é¡¼Ì¾¤äÈÖ¹æ¤òǧ¼±¤Ç¤­¤Þ¤»¤ó: %s"
+
+#: syntax.c:6812
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: ½ªÃ¼¥³¡¼¥É¤¬Ä¹¤¹¤®¤Þ¤¹: %s"
+
+#: syntax.c:6859
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: ÉÔÀµ¤Ê°ú¿ô¤Ç¤¹: %s"
+
+#: syntax.c:7388
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: ¿¤¯¤Î°Û¤Ê¤ë¥Ï¥¤¥é¥¤¥È°À­¤¬»È¤ï¤ì¤¹¤®¤Æ¤¤¤Þ¤¹"
+
+#: syntax.c:7909
+msgid "E669: Unprintable character in group name"
+msgstr "E669: ¥°¥ë¡¼¥×̾¤Ë°õºþÉÔ²Äǽ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤¹"
+
+#. This is an error, but since there previously was no check only
+#. * give a warning.
+#: syntax.c:7916
+msgid "W18: Invalid character in group name"
+msgstr "W18: ¥°¥ë¡¼¥×̾¤ËÉÔÀµ¤Êʸ»ú¤¬¤¢¤ê¤Þ¤¹"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: ¥¿¥°¥¹¥¿¥Ã¥¯¤ÎËöÈø¤Ç¤¹"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: ¥¿¥°¥¹¥¿¥Ã¥¯¤ÎÀèƬ¤Ç¤¹"
+
+#: tag.c:412
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: ºÇ½é¤Î³ºÅö¥¿¥°¤òĶ¤¨¤ÆÌá¤ë¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó"
+
+#: tag.c:550
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: ¥¿¥°¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó: %s"
+
+#: tag.c:583
+msgid " # pri kind tag"
+msgstr " # pri kind tag"
+
+#: tag.c:586
+msgid "file\n"
+msgstr "¥Õ¥¡¥¤¥ë\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:744
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "ÁªÂò¤¹¤ëÈÖ¹æ¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤ (<CR>¤ÇÃæ»ß): "
+
+#: tag.c:784
+msgid "E427: There is only one matching tag"
+msgstr "E427: ³ºÅö¥¿¥°¤¬1¤Ä¤À¤±¤·¤«¤¢¤ê¤Þ¤»¤ó"
+
+#: tag.c:786
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: ºÇ¸å¤Ë³ºÅö¤¹¤ë¥¿¥°¤òĶ¤¨¤Æ¿Ê¤à¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó"
+
+#: tag.c:810
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "¥Õ¥¡¥¤¥ë \"%s\" ¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#. Give an indication of the number of matching tags
+#: tag.c:823
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "¥¿¥° %d (Á´%d%s)"
+
+#: tag.c:826
+msgid " or more"
+msgstr " ¤«¤½¤ì°Ê¾å"
+
+#: tag.c:828
+msgid " Using tag with different case!"
+msgstr " ¥¿¥°¤ò°Û¤Ê¤ëcase¤Ç»ÈÍѤ·¤Þ¤¹!"
+
+#: tag.c:872
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: ¥Õ¥¡¥¤¥ë \"%s\" ¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#. Highlight title
+#: tag.c:941
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # TO ¥¿¥° FROM ¹Ô in file/text"
+
+#: tag.c:1363
+#, c-format
+msgid "Searching tags file %s"
+msgstr "¥¿¥°¥Õ¥¡¥¤¥ë %s ¤ò¸¡º÷Ãæ"
+
+#: tag.c:1550
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: ¥¿¥°¥Õ¥¡¥¤¥ë¤Î¥Ñ¥¹¤¬ %s ¤ËÀÚ¤ê¼Î¤Æ¤é¤ì¤Þ¤·¤¿\n"
+
+#: tag.c:2203
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: ¥¿¥°¥Õ¥¡¥¤¥ë \"%s\" ¤Î¥Õ¥©¡¼¥Þ¥Ã¥È¤Ë¥¨¥é¡¼¤¬¤¢¤ê¤Þ¤¹"
+
+#: tag.c:2207
+#, c-format
+msgid "Before byte %ld"
+msgstr "ľÁ°¤Î %ld ¥Ð¥¤¥È"
+
+#: tag.c:2240
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: ¥¿¥°¥Õ¥¡¥¤¥ë¤¬¥½¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó: %s"
+
+#. never opened any tags file
+#: tag.c:2280
+msgid "E433: No tags file"
+msgstr "E433: ¥¿¥°¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: tag.c:3016
+msgid "E434: Can't find tag pattern"
+msgstr "E434: ¥¿¥°¥Ñ¥¿¡¼¥ó¤ò¤ß¤Ä¤±¤é¤ì¤Þ¤»¤ó"
+
+#: tag.c:3027
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: ¥¿¥°¤ò¤ß¤Ä¤±¤é¤ì¤Ê¤¤¤Î¤Çñ¤Ë¿ä¬¤·¤Þ¤¹!"
+
+#: term.c:1759
+msgid "' not known. Available builtin terminals are:"
+msgstr "' ¤Ï̤ÃΤǤ¹. ¸½¹Ô¤ÎÁȤ߹þ¤ßüËö¤Ï¼¡¤Î¤È¤ª¤ê¤Ç¤¹:"
+
+#: term.c:1783
+msgid "defaulting to '"
+msgstr "¾ÊάÃͤò¼¡¤Î¤è¤¦¤ËÀßÄꤷ¤Þ¤¹ '"
+
+#: term.c:2141
+msgid "E557: Cannot open termcap file"
+msgstr "E557: termcap¥Õ¥¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó"
+
+#: term.c:2145
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: terminfo¤ËüËö¥¨¥ó¥È¥ê¤ò¤ß¤Ä¤±¤é¤ì¤Þ¤»¤ó"
+
+#: term.c:2147
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: termcap¤ËüËö¥¨¥ó¥È¥ê¤ò¤ß¤Ä¤±¤é¤ì¤Þ¤»¤ó"
+
+#: term.c:2306
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: termcap¤Ë \"%s\" ¤Î¥¨¥ó¥È¥ê¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: term.c:2780
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: üËö¤Ë \"cm\" µ¡Ç½¤¬É¬ÍפǤ¹"
+
+#. Highlight title
+#: term.c:4990
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- üËö¥­¡¼ ---"
+
+#: ui.c:258
+msgid "new shell started\n"
+msgstr "¿·¤·¤¤¥·¥§¥ë¤òµ¯Æ°¤·¤Þ¤¹\n"
+
+#: ui.c:1841
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: ÆþÎϤòÆɹþ¤ßÃæ¤Î¥¨¥é¡¼¤Ë¤è¤ê½ªÎ»¤·¤Þ¤¹...\n"
+
+#. must display the prompt
+#: undo.c:405
+msgid "No undo possible; continue anyway"
+msgstr "²Äǽ¤Ê¥¢¥ó¥É¥¥¤Ï¤¢¤ê¤Þ¤»¤ó: ¤È¤ê¤¢¤¨¤ºÂ³¤±¤Þ¤¹"
+
+#: undo.c:561
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: ¹ÔÈֹ椬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹"
+
+#: undo.c:757
+msgid "1 change"
+msgstr "1 ²Õ½êÊѹ¹¤·¤Þ¤·¤¿"
+
+#: undo.c:759
+#, c-format
+msgid "%ld changes"
+msgstr "%ld ²Õ½êÊѹ¹¤·¤Þ¤·¤¿"
+
+#: undo.c:812
+msgid "E439: undo list corrupt"
+msgstr "E439: ¥¢¥ó¥É¥¥¥ê¥¹¥È¤¬²õ¤ì¤Æ¤¤¤Þ¤¹"
+
+#: undo.c:844
+msgid "E440: undo line missing"
+msgstr "E440: ¥¢¥ó¥É¥¥¹Ô¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:1731
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 16/32 ¥Ó¥Ã¥È GUI ÈÇ"
+
+#: version.c:1733
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 32 ¥Ó¥Ã¥È GUI ÈÇ"
+
+#: version.c:1736
+msgid " in Win32s mode"
+msgstr " in Win32s ¥â¡¼¥É"
+
+#: version.c:1738
+msgid " with OLE support"
+msgstr " with OLE ¥µ¥Ý¡¼¥È"
+
+#: version.c:1741
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"MS-Windows 32 ¥Ó¥Ã¥È ¥³¥ó¥½¡¼¥ë ÈÇ"
+
+#: version.c:1745
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"MS-Windows 16 ¥Ó¥Ã¥È ÈÇ"
+
+#: version.c:1749
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 ¥Ó¥Ã¥È MS-DOS ÈÇ"
+
+#: version.c:1751
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 ¥Ó¥Ã¥È MS-DOS ÈÇ"
+
+#: version.c:1757
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) ÈÇ"
+
+#: version.c:1759
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X ÈÇ"
+
+#: version.c:1762
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS ÈÇ"
+
+#: version.c:1767
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS ÈÇ"
+
+#: version.c:1777
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"ŬÍѺѥѥåÁ: "
+
+#: version.c:1803 version.c:2171
+msgid "Modified by "
+msgstr "Modified by "
+
+#: version.c:1810
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Compiled "
+
+#: version.c:1813
+msgid "by "
+msgstr "by "
+
+#: version.c:1825
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Huge ÈÇ "
+
+#: version.c:1828
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Big ÈÇ "
+
+#: version.c:1831
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Ä̾ï ÈÇ "
+
+#: version.c:1834
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Small ÈÇ "
+
+#: version.c:1836
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Tiny ÈÇ "
+
+#: version.c:1842
+msgid "without GUI."
+msgstr "without GUI."
+
+#: version.c:1847
+msgid "with GTK2-GNOME GUI."
+msgstr "with GTK2-GNOME GUI."
+
+#: version.c:1849
+msgid "with GTK-GNOME GUI."
+msgstr "with GTK-GNOME GUI."
+
+#: version.c:1853
+msgid "with GTK2 GUI."
+msgstr "with GTK2 GUI."
+
+#: version.c:1855
+msgid "with GTK GUI."
+msgstr "with GTK GUI."
+
+#: version.c:1860
+msgid "with X11-Motif GUI."
+msgstr "with X11-Motif GUI."
+
+#: version.c:1864
+msgid "with X11-neXtaw GUI."
+msgstr "with X11-neXtaw GUI."
+
+#: version.c:1866
+msgid "with X11-Athena GUI."
+msgstr "with X11-Athena GUI."
+
+#: version.c:1870
+msgid "with BeOS GUI."
+msgstr "with BeOS GUI."
+
+#: version.c:1873
+msgid "with Photon GUI."
+msgstr "with Photon GUI."
+
+#: version.c:1876
+msgid "with GUI."
+msgstr "with GUI."
+
+#: version.c:1879
+msgid "with Carbon GUI."
+msgstr "with Carbon GUI."
+
+#: version.c:1882
+msgid "with Cocoa GUI."
+msgstr "with Cocoa GUI."
+
+#: version.c:1885
+msgid "with (classic) GUI."
+msgstr "with (¥¯¥é¥·¥Ã¥¯) GUI."
+
+#: version.c:1896
+msgid " Features included (+) or not (-):\n"
+msgstr " µ¡Ç½¤Î°ìÍ÷ Í­¸ú(+)/̵¸ú(-)\n"
+
+#: version.c:1908
+msgid " system vimrc file: \""
+msgstr " ¥·¥¹¥Æ¥à vimrc: \""
+
+#: version.c:1913
+msgid " user vimrc file: \""
+msgstr " ¥æ¡¼¥¶ vimrc: \""
+
+#: version.c:1918
+msgid " 2nd user vimrc file: \""
+msgstr " Âè2¥æ¡¼¥¶ vimrc: \""
+
+#: version.c:1923
+msgid " 3rd user vimrc file: \""
+msgstr " Âè3¥æ¡¼¥¶ vimrc: \""
+
+#: version.c:1928
+msgid " user exrc file: \""
+msgstr " ¥æ¡¼¥¶ exrc: \""
+
+#: version.c:1933
+msgid " 2nd user exrc file: \""
+msgstr " Âè2¥æ¡¼¥¶ exrc: \""
+
+#: version.c:1939
+msgid " system gvimrc file: \""
+msgstr " ¥·¥¹¥Æ¥à gvimrc: \""
+
+#: version.c:1943
+msgid " user gvimrc file: \""
+msgstr " ¥æ¡¼¥¶ gvimrc: \""
+
+#: version.c:1947
+msgid "2nd user gvimrc file: \""
+msgstr " Âè2¥æ¡¼¥¶ gvimrc: \""
+
+#: version.c:1952
+msgid "3rd user gvimrc file: \""
+msgstr " Âè3¥æ¡¼¥¶ gvimrc: \""
+
+#: version.c:1959
+msgid " system menu file: \""
+msgstr " ¥·¥¹¥Æ¥à¥á¥Ë¥å¡¼: \""
+
+#: version.c:1967
+msgid " fall-back for $VIM: \""
+msgstr " ¾Êά»þ¤Î $VIM: \""
+
+#: version.c:1973
+msgid " f-b for $VIMRUNTIME: \""
+msgstr "¾Êά»þ¤Î $VIMRUNTIME: \""
+
+#: version.c:1977
+msgid "Compilation: "
+msgstr "¥³¥ó¥Ñ¥¤¥ë: "
+
+#: version.c:1983
+msgid "Compiler: "
+msgstr "¥³¥ó¥Ñ¥¤¥é: "
+
+#: version.c:1988
+msgid "Linking: "
+msgstr "¥ê¥ó¥¯: "
+
+#: version.c:1993
+msgid " DEBUG BUILD"
+msgstr "¥Ç¥Ð¥Ã¥°¥Ó¥ë¥É"
+
+#: version.c:2032
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved"
+
+#: version.c:2034
+msgid "version "
+msgstr "version "
+
+#: version.c:2035
+msgid "by Bram Moolenaar et al."
+msgstr "by Bram Moolenaar ¾."
+
+#: version.c:2039
+msgid "Vim is open source and freely distributable"
+msgstr "Vim ¤Ï¥ª¡¼¥×¥ó¥½¡¼¥¹¤Ç¤¢¤ê¼«Í³¤ËÇÛÉÛ²Äǽ¤Ç¤¹"
+
+#: version.c:2041
+msgid "Help poor children in Uganda!"
+msgstr "¥¦¥¬¥ó¥À¤Î·Ã¤Þ¤ì¤Ê¤¤»Ò¶¡¤¿¤Á¤Ë±ç½õ¤ò!"
+
+#: version.c:2042
+msgid "type :help iccf<Enter> for information "
+msgstr "¾ÜºÙ¤Ê¾ðÊó¤Ï :help iccf<Enter> "
+
+#: version.c:2044
+msgid "type :q<Enter> to exit "
+msgstr "½ªÎ»¤¹¤ë¤Ë¤Ï :q<Enter> "
+
+#: version.c:2045
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "¥ª¥ó¥é¥¤¥ó¥Ø¥ë¥×¤Ï :help<Enter> ¤« <F1> "
+
+#: version.c:2046
+msgid "type :help version6<Enter> for version info"
+msgstr "¥Ð¡¼¥¸¥ç¥ó¾ðÊó¤Ï :help version6<Enter> "
+
+#: version.c:2049
+msgid "Running in Vi compatible mode"
+msgstr "Vi¸ß´¹¥â¡¼¥É¤ÇÆ°ºîÃæ"
+
+#: version.c:2050
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "Vim¿ä¾©Ãͤˤ¹¤ë¤Ë¤Ï :set nocp<Enter> "
+
+#: version.c:2051
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "¾ÜºÙ¤Ê¾ðÊó¤Ï :help cp-default<Enter>"
+
+#: version.c:2066
+msgid "menu Help->Orphans for information "
+msgstr "¾ÜºÙ¤Ï¥á¥Ë¥å¡¼¤Î ¥Ø¥ë¥×¢ª¸É»ù ¤ò»²¾È¤·¤Æ²¼¤µ¤¤ "
+
+#: version.c:2068
+msgid "Running modeless, typed text is inserted"
+msgstr "¥â¡¼¥É̵¤Ç¼Â¹ÔÃæ, ¥¿¥¤¥×¤·¤¿Ê¸»ú¤¬ÁÞÆþ¤µ¤ì¤Þ¤¹"
+
+#: version.c:2069
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "¥á¥Ë¥å¡¼¤Î ÊÔ½¸¢ªÁ´ÂÎÀßÄꢪÁÞÆþ(½é¿´¼Ô)¥â¡¼¥ÉÀÚÂØ"
+
+#: version.c:2070
+msgid " for two modes "
+msgstr " ¤Ç¥â¡¼¥ÉÍ­¤Ë "
+
+#: version.c:2074
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "¥á¥Ë¥å¡¼¤Î ÊÔ½¸¢ªÁ´ÂÎÀßÄꢪVi¸ß´¹¥â¡¼¥ÉÀÚÂØ "
+
+#: version.c:2075
+msgid " for Vim defaults "
+msgstr " ¤ÇVim¤È¤·¤ÆÆ°ºî "
+
+#: version.c:2122
+msgid "Sponsor Vim development!"
+msgstr "Vim¤Î³«È¯¤ò±þ±ç¤·¤Æ¤¯¤À¤µ¤¤!"
+
+#: version.c:2123
+msgid "Become a registered Vim user!"
+msgstr "Vim¤ÎÅÐÏ¿¥æ¡¼¥¶¤Ë¤Ê¤Ã¤Æ¤¯¤À¤µ¤¤!"
+
+#: version.c:2126
+msgid "type :help sponsor<Enter> for information "
+msgstr "¾ÜºÙ¤Ê¾ðÊó¤Ï :help sponsor<Enter> "
+
+#: version.c:2127
+msgid "type :help register<Enter> for information "
+msgstr "¾ÜºÙ¤Ê¾ðÊó¤Ï :help register<Enter> "
+
+#: version.c:2129
+msgid "menu Help->Sponsor/Register for information "
+msgstr "¾ÜºÙ¤Ï¥á¥Ë¥å¡¼¤Î ¥Ø¥ë¥×¢ª¥¹¥Ý¥ó¥µ¡¼/ÅÐÏ¿ ¤ò»²¾È¤·¤Æ²¼¤µ¤¤ "
+
+#: version.c:2139
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr " ·Ù¹ð: Windows 95/98/Me ¤ò¸¡½Ð "
+
+#: version.c:2142
+msgid "type :help windows95<Enter> for info on this"
+msgstr " ¾ÜºÙ¤Ê¾ðÊó¤Ï :help windows95<Enter> "
+
+#: window.c:203
+msgid "E441: There is no preview window"
+msgstr "E441: ¥×¥ì¥Ó¥å¡¼¥¦¥£¥ó¥É¥¦¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: window.c:581
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: º¸¾å¤È±¦²¼¤òƱ»þ¤Ëʬ³ä¤¹¤ë¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó"
+
+#: window.c:1340
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: ¾¤Î¥¦¥£¥ó¥É¥¦¤¬Ê¬³ä¤µ¤ì¤Æ¤¤¤ë»þ¤Ë¤Ï½ç²ó¤Ç¤­¤Þ¤»¤ó"
+
+#: window.c:1836
+msgid "E444: Cannot close last window"
+msgstr "E444: ºÇ¸å¤Î¥¦¥£¥ó¥É¥¦¤òÊĤ¸¤ë¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó"
+
+#: window.c:2567
+msgid "Already only one window"
+msgstr "´û¤Ë¥¦¥£¥ó¥É¥¦¤Ï1¤Ä¤·¤«¤¢¤ê¤Þ¤»¤ó"
+
+#: window.c:2614
+msgid "E445: Other window contains changes"
+msgstr "E445: ¾¤Î¥¦¥£¥ó¥É¥¦¤Ë¤ÏÊѹ¹¤¬¤¢¤ê¤Þ¤¹"
+
+#: window.c:4480
+msgid "E446: No file name under cursor"
+msgstr "E446: ¥«¡¼¥½¥ë¤Î²¼¤Ë¥Õ¥¡¥¤¥ë̾¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: window.c:4599
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: path¤Ë¤Ï \"%s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1232 if_perl.xs:326
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: ¥é¥¤¥Ö¥é¥ê %s ¤ò¥í¡¼¥É¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: if_perl.xs:554
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr ""
+"¤³¤Î¥³¥Þ¥ó¥É¤Ï̵¸ú¤Ç¤¹, ¤´¤á¤ó¤Ê¤µ¤¤: Perl¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿."
+
+#: if_perl.xs:607
+msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+msgstr ""
+"E299: ¥µ¥ó¥É¥Ü¥Ã¥¯¥¹¤Ç¤Ï Safe "
+"¥â¥¸¥å¡¼¥ë¤ò»ÈÍѤ·¤Ê¤¤Perl¥¹¥¯¥ê¥×¥È¤Ï¶Ø¤¸¤é¤ì¤Æ¤¤¤Þ¤¹"
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "³Æ¥Õ¥¡¥¤¥ë¤òÊÌ¡¹¤Î Vim ¤ÇÊÔ½¸(&M)"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "Á´¥Õ¥¡¥¤¥ë¤ò1¤Ä¤Î Vim ¤ÇÊÔ½¸(&V)"
+
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "Vim ¤Çº¹Ê¬ÊÔ½¸(&D)"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "Vim ¤ÇÊÔ½¸(&V)"
+
+#: GvimExt/gvimext.cpp:633
+msgid "Edit with existing Vim - &"
+msgstr "´û¸¤Î Vim ¤ÇÊÔ½¸ - &"
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "ÁªÂò¤µ¤ì¤¿¥Õ¥¡¥¤¥ë¤ò Vim ¤ÇÊÔ½¸"
+
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "µ¯Æ°¥¨¥é¡¼: gvim ¤Ë¥Ñ¥¹¤¬Ä̤äƤ¤¤ë¤«³Î¤«¤á¤Æ¤¯¤À¤µ¤¤!"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "gvimext.dll ¥¨¥é¡¼"
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "¥Ñ¥¹¤¬Ä¹¤¹¤®¤Þ¤¹!"
+
+#: globals.h:1022
+msgid "--No lines in buffer--"
+msgstr "--¥Ð¥Ã¥Õ¥¡¤Ë¹Ô¤¬¤¢¤ê¤Þ¤»¤ó--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1185
+msgid "E470: Command aborted"
+msgstr "E470: ¥³¥Þ¥ó¥É¤¬ÃæÃǤµ¤ì¤Þ¤·¤¿"
+
+#: globals.h:1186
+msgid "E471: Argument required"
+msgstr "E471: °ú¿ô¤¬É¬ÍפǤ¹"
+
+#: globals.h:1187
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ ¤Î¸å¤Ï / ¤« ? ¤« & ¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó"
+
+#: globals.h:1189
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: ¥³¥Þ¥ó¥É¥é¥¤¥ó¤Ç¤Ï̵¸ú¤Ç¤¹; <CR>¤Ç¼Â¹Ô, CTRL-C¤Ç¤ä¤á¤ë"
+
+#: globals.h:1191
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: ¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ä¥¿¥°¸¡º÷¤Ç¤Ïexrc/vimrc¤Î¥³¥Þ¥ó¥É¤Ïµö²Ä¤µ¤ì¤Þ¤»¤ó"
+
+#: globals.h:1193
+msgid "E171: Missing :endif"
+msgstr "E171: :endif ¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1194
+msgid "E600: Missing :endtry"
+msgstr "E600: :endtry ¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1195
+msgid "E170: Missing :endwhile"
+msgstr "E170: :endwhile ¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1196
+msgid "E588: :endwhile without :while"
+msgstr "E588: :while ¤Î¤Ê¤¤ :endwhile ¤¬¤¢¤ê¤Þ¤¹"
+
+#: globals.h:1198
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: ¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤·¤Þ¤¹ (! ¤òÄɲäǾå½ñ)"
+
+#: globals.h:1199
+msgid "E472: Command failed"
+msgstr "E472: ¥³¥Þ¥ó¥É¤¬¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: globals.h:1201
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: ̤ÃΤΥե©¥ó¥È¥»¥Ã¥È: %s"
+
+#: globals.h:1205
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: ̤ÃΤΥե©¥ó¥È: %s"
+
+#: globals.h:1208
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: ¥Õ¥©¥ó¥È \"%s\" ¤Ï¸ÇÄêÉý¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1210
+msgid "E473: Internal error"
+msgstr "E473: ÆâÉô¥¨¥é¡¼¤Ç¤¹"
+
+#: globals.h:1211
+msgid "Interrupted"
+msgstr "³ä¹þ¤Þ¤ì¤Þ¤·¤¿"
+
+#: globals.h:1212
+msgid "E14: Invalid address"
+msgstr "E14: ̵¸ú¤Ê¥¢¥É¥ì¥¹¤Ç¤¹"
+
+#: globals.h:1213
+msgid "E474: Invalid argument"
+msgstr "E474: ̵¸ú¤Ê°ú¿ô¤Ç¤¹"
+
+#: globals.h:1214
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: ̵¸ú¤Ê°ú¿ô¤Ç¤¹: %s"
+
+#: globals.h:1216
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: ̵¸ú¤Ê¼°¤Ç¤¹: %s"
+
+#: globals.h:1218
+msgid "E16: Invalid range"
+msgstr "E16: ̵¸ú¤ÊÈϰϤǤ¹"
+
+#: globals.h:1219
+msgid "E476: Invalid command"
+msgstr "E476: ̵¸ú¤Ê¥³¥Þ¥ó¥É¤Ç¤¹"
+
+#: globals.h:1221
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" ¤Ï¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤¹"
+
+#: globals.h:1224
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: ͽ´ü¤»¤Ìʸ»ú¤¬ '=' ¤ÎÁ°¤Ë¤¢¤ê¤Þ¤·¤¿"
+
+#: globals.h:1227
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: \"%s\"() ¤Î¥é¥¤¥Ö¥é¥ê¸Æ½Ð¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: globals.h:1233
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: ¥é¥¤¥Ö¥é¥ê¤Î´Ø¿ô %s ¤ò¥í¡¼¥É¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: globals.h:1235
+msgid "E19: Mark has invalid line number"
+msgstr "E19: ¥Þ¡¼¥¯¤Ë̵¸ú¤Ê¹ÔÈֹ椬»ØÄꤵ¤ì¤Æ¤¤¤Þ¤·¤¿"
+
+#: globals.h:1236
+msgid "E20: Mark not set"
+msgstr "E20: ¥Þ¡¼¥¯¤ÏÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: globals.h:1237
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: 'modifiable' ¤¬¥ª¥Õ¤Ê¤Î¤Ç, Êѹ¹¤Ç¤­¤Þ¤»¤ó"
+
+#: globals.h:1238
+msgid "E22: Scripts nested too deep"
+msgstr "E22: ¥¹¥¯¥ê¥×¥È¤ÎÆþ¤ì»Ò¤¬¿¼¤¹¤®¤Þ¤¹"
+
+#: globals.h:1239
+msgid "E23: No alternate file"
+msgstr "E23: Éû¥Õ¥¡¥¤¥ë¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1240
+msgid "E24: No such abbreviation"
+msgstr "E24: ¤½¤Î¤è¤¦¤Êû½ÌÆþÎϤϤ¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1241
+msgid "E477: No ! allowed"
+msgstr "E477: ! ¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: globals.h:1243
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: GUI¤Ï»ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹"
+
+#: globals.h:1246
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: ¥Ø¥Ö¥é¥¤¸ì¤Ï»ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹\n"
+
+#: globals.h:1249
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: ¥Ú¥ë¥·¥¢¸ì¤Ï»ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹\n"
+
+#: globals.h:1252
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: ¥¢¥é¥Ó¥¢¸ì¤Ï»ÈÍÑÉÔ²Äǽ¤Ç¤¹: ¥³¥ó¥Ñ¥¤¥ë»þ¤Ë̵¸ú¤Ë¤µ¤ì¤Æ¤¤¤Þ¤¹\n"
+
+#: globals.h:1255
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: ¤½¤Î¤è¤¦¤Ê̾¤Î¥Ï¥¤¥é¥¤¥È¥°¥ë¡¼¥×¤Ï¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: globals.h:1257
+msgid "E29: No inserted text yet"
+msgstr "E29: ¤Þ¤À¥Æ¥­¥¹¥È¤¬ÁÞÆþ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: globals.h:1258
+msgid "E30: No previous command line"
+msgstr "E30: °ÊÁ°¤Ë¥³¥Þ¥ó¥É¹Ô¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1259
+msgid "E31: No such mapping"
+msgstr "E31: ¤½¤Î¤è¤¦¤Ê¥Þ¥Ã¥Ô¥ó¥°¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1260
+msgid "E479: No match"
+msgstr "E479: ³ºÅö¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1261
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: ³ºÅö¤Ï¤¢¤ê¤Þ¤»¤ó: %s"
+
+#: globals.h:1262
+msgid "E32: No file name"
+msgstr "E32: ¥Õ¥¡¥¤¥ë̾¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1263
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: Àµµ¬É½¸½ÃÖ´¹¤¬¤Þ¤À¼Â¹Ô¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: globals.h:1264
+msgid "E34: No previous command"
+msgstr "E34: ¥³¥Þ¥ó¥É¤¬¤Þ¤À¼Â¹Ô¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: globals.h:1265
+msgid "E35: No previous regular expression"
+msgstr "E35: Àµµ¬É½¸½¤¬¤Þ¤À¼Â¹Ô¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: globals.h:1266
+msgid "E481: No range allowed"
+msgstr "E481: ÈÏ°Ï»ØÄê¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: globals.h:1268
+msgid "E36: Not enough room"
+msgstr "E36: ½¼Ê¬¤ÊÍÆÎ̤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1271
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: %s ¤È¤¤¤¦Ì¾Á°¤ÎÅÐÏ¿¤µ¤ì¤¿¥µ¡¼¥Ð¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1273
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: ¥Õ¥¡¥¤¥ë %s ¤òºîÀ®¤Ç¤­¤Þ¤»¤ó"
+
+#: globals.h:1274
+msgid "E483: Can't get temp file name"
+msgstr "E483: °ì»þ¥Õ¥¡¥¤¥ë¤Î̾Á°¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó"
+
+#: globals.h:1275
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: ¥Õ¥¡¥¤¥ë \"%s\" ¤ò³«¤±¤Þ¤»¤ó"
+
+#: globals.h:1276
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: ¥Õ¥¡¥¤¥ë %s ¤òÆɹþ¤á¤Þ¤»¤ó"
+
+#: globals.h:1277
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: ºÇ¸å¤ÎÊѹ¹¤¬Êݸ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó (! ¤òÄɲäÇÊѹ¹¤òÇË´þ)"
+
+#: globals.h:1278
+msgid "E38: Null argument"
+msgstr "E38: °ú¿ô¤¬¶õ¤Ç¤¹"
+
+#: globals.h:1280
+msgid "E39: Number expected"
+msgstr "E39: ¿ôÃͤ¬Í׵ᤵ¤ì¤Æ¤¤¤Þ¤¹"
+
+#: globals.h:1283
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: ¥¨¥é¡¼¥Õ¥¡¥¤¥ë %s ¤ò³«¤±¤Þ¤»¤ó"
+
+#: globals.h:1286
+msgid "E233: cannot open display"
+msgstr "E233: ¥Ç¥£¥¹¥×¥ì¥¤¤ò³«¤±¤Þ¤»¤ó"
+
+#: globals.h:1288
+msgid "E41: Out of memory!"
+msgstr "E41: ¥á¥â¥ê¤¬¿Ô¤­²Ì¤Æ¤Þ¤·¤¿!"
+
+#: globals.h:1290
+msgid "Pattern not found"
+msgstr "¥Ñ¥¿¡¼¥ó¤Ï¤ß¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: globals.h:1292
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: ¥Ñ¥¿¡¼¥ó¤Ï¤ß¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿: %s"
+
+#: globals.h:1293
+msgid "E487: Argument must be positive"
+msgstr "E487: °ú¿ô¤ÏÀµ¤ÎÃͤǤʤ±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó"
+
+#: globals.h:1295
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: Á°¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ËÌá¤ì¤Þ¤»¤ó"
+
+#: globals.h:1299
+msgid "E42: No Errors"
+msgstr "E42: ¥¨¥é¡¼¤Ï¤¢¤ê¤Þ¤»¤ó"
+
+#: globals.h:1301
+msgid "E43: Damaged match string"
+msgstr "E43: ³ºÅöʸ»úÎó¤¬ÇË»¤·¤Æ¤¤¤Þ¤¹"
+
+#: globals.h:1302
+msgid "E44: Corrupted regexp program"
+msgstr "E44: ÉÔÀµ¤ÊÀµµ¬É½¸½¥×¥í¥°¥é¥à¤Ç¤¹"
+
+#: globals.h:1303
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: 'readonly' ¥ª¥×¥·¥ç¥ó¤¬ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤¹ (! ¤òÄɲäǾå½ñ¤­)"
+
+#: globals.h:1305
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: ÆɼèÀìÍÑÊÑ¿ô \"%s\" ¤ËÀßÄꤹ¤ë¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó"
+
+#: globals.h:1308
+msgid "E47: Error while reading errorfile"
+msgstr "E47: ¥¨¥é¡¼¥Õ¥¡¥¤¥ë¤ÎÆɹþÃæ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿"
+
+#: globals.h:1311
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: ¥µ¥ó¥É¥Ü¥Ã¥¯¥¹¤Ç¤Ïµö¤µ¤ì¤Þ¤»¤ó"
+
+#: globals.h:1313
+msgid "E523: Not allowed here"
+msgstr "E523: ¤³¤³¤Ç¤Ïµö²Ä¤µ¤ì¤Þ¤»¤ó"
+
+#: globals.h:1316
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: ¥¹¥¯¥ê¡¼¥ó¥â¡¼¥É¤ÎÀßÄê¤Ë¤ÏÂбþ¤·¤Æ¤¤¤Þ¤»¤ó"
+
+#: globals.h:1318
+msgid "E49: Invalid scroll size"
+msgstr "E49: ̵¸ú¤Ê¥¹¥¯¥í¡¼¥ëÎ̤Ǥ¹"
+
+#: globals.h:1319
+msgid "E91: 'shell' option is empty"
+msgstr "E91: 'shell' ¥ª¥×¥·¥ç¥ó¤¬¶õ¤Ç¤¹"
+
+#: globals.h:1321
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: sign ¤Î¥Ç¡¼¥¿¤òÆɹþ¤á¤Þ¤»¤ó¤Ç¤·¤¿"
+
+#: globals.h:1323
+msgid "E72: Close error on swap file"
+msgstr "E72: ¥¹¥ï¥Ã¥×¥Õ¥¡¥¤¥ë¤Î¥¯¥í¡¼¥º»þ¥¨¥é¡¼¤Ç¤¹"
+
+#: globals.h:1324
+msgid "E73: tag stack empty"
+msgstr "E73: ¥¿¥°¥¹¥¿¥Ã¥¯¤¬¶õ¤Ç¤¹"
+
+#: globals.h:1325
+msgid "E74: Command too complex"
+msgstr "E74: ¥³¥Þ¥ó¥É¤¬Ê£»¨¤¹¤®¤Þ¤¹"
+
+#: globals.h:1326
+msgid "E75: Name too long"
+msgstr "E75: ̾Á°¤¬Ä¹¤¹¤®¤Þ¤¹"
+
+#: globals.h:1327
+msgid "E76: Too many ["
+msgstr "E76: [ ¤¬Â¿¤¹¤®¤Þ¤¹"
+
+#: globals.h:1328
+msgid "E77: Too many file names"
+msgstr "E77: ¥Õ¥¡¥¤¥ë̾¤¬Â¿¤¹¤®¤Þ¤¹"
+
+#: globals.h:1329
+msgid "E488: Trailing characters"
+msgstr "E488: ;ʬ¤Êʸ»ú¤¬¸å¤í¤Ë¤¢¤ê¤Þ¤¹"
+
+#: globals.h:1330
+msgid "E78: Unknown mark"
+msgstr "E78: ̤ÃΤΥޡ¼¥¯"
+
+#: globals.h:1331
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: ¥ï¥¤¥ë¥É¥«¡¼¥É¤òŸ³«¤Ç¤­¤Þ¤»¤ó"
+
+#: globals.h:1333
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: 'winheight' ¤Ï 'winminheight' ¤è¤ê¾®¤µ¤¯¤Ç¤­¤Þ¤»¤ó"
+
+#: globals.h:1335
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: 'winwidth' ¤Ï 'winminwidth' ¤è¤ê¾®¤µ¤¯¤Ç¤­¤Þ¤»¤ó"
+
+#: globals.h:1338
+msgid "E80: Error while writing"
+msgstr "E80: ½ñ¹þ¤ßÃæ¤Î¥¨¥é¡¼"
+
+#: globals.h:1339
+msgid "Zero count"
+msgstr "¥¼¥í¥«¥¦¥ó¥È"
+
+#: globals.h:1341
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: ¥¹¥¯¥ê¥×¥È°Ê³°¤Ç<SID>¤¬»È¤ï¤ì¤Þ¤·¤¿"
+
+#: globals.h:1344
+msgid "E449: Invalid expression received"
+msgstr "E449: ̵¸ú¤Ê¼°¤ò¼õ¤±¼è¤ê¤Þ¤·¤¿"
+
+#: globals.h:1347
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: Îΰ褬Êݸ¤ì¤Æ¤¤¤ë¤Î¤Ç, Êѹ¹¤Ç¤­¤Þ¤»¤ó"
diff --git a/src/po/ja.sjis.po b/src/po/ja.sjis.po
new file mode 100644
index 000000000..ae5c110c3
--- /dev/null
+++ b/src/po/ja.sjis.po
@@ -0,0 +1,6587 @@
+# Japanese translation for Vim vim:set foldmethod=marker:
+#
+# Do ":help uganda" in Vim to read copying and usage conditions.
+# Do ":help credits" in Vim to see a list of people who contributed.
+#
+# MURAOKA Taro <koron@tka.att.ne.jp>, 2001-4.
+# Last Change: 29-Apr-2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim 6.2\n"
+"POT-Creation-Date: 2004-04-29 13:16+0900\n"
+"PO-Revision-Date: 2004-04-29 13:00+0900\n"
+"Last-Translator: MURAOKA Taro <koron@tka.att.ne.jp>\n"
+"Language-Team: MURAOKA Taro <koron@tka.att.ne.jp>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=cp932\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: buffer.c:102
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: ƒoƒbƒtƒ@‚ð1‚‚à쬂ł«‚È‚¢‚Ì‚Å, I—¹‚µ‚Ü‚·..."
+
+#: buffer.c:105
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: ƒoƒbƒtƒ@‚ð쬂ł«‚È‚¢‚Ì‚Å, ‘¼‚Ì‚ðŽg—p‚µ‚Ü‚·..."
+
+#: buffer.c:805
+msgid "E515: No buffers were unloaded"
+msgstr "E515: ‰ð•ú‚³‚ꂽƒoƒbƒtƒ@‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: buffer.c:807
+msgid "E516: No buffers were deleted"
+msgstr "E516: 휂³‚ꂽƒoƒbƒtƒ@‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: buffer.c:809
+msgid "E517: No buffers were wiped out"
+msgstr "E517: ”jŠü‚³‚ꂽƒoƒbƒtƒ@‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: buffer.c:817
+msgid "1 buffer unloaded"
+msgstr "1 ŒÂ‚̃oƒbƒtƒ@‚ª‰ð•ú‚³‚ê‚Ü‚µ‚½"
+
+#: buffer.c:819
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "%d ŒÂ‚̃oƒbƒtƒ@‚ª‰ð•ú‚³‚ê‚Ü‚µ‚½"
+
+#: buffer.c:824
+msgid "1 buffer deleted"
+msgstr "1 ŒÂ‚̃oƒbƒtƒ@‚ªíœ‚³‚ê‚Ü‚µ‚½"
+
+#: buffer.c:826
+#, c-format
+msgid "%d buffers deleted"
+msgstr "%d ŒÂ‚̃oƒbƒtƒ@‚ªíœ‚³‚ê‚Ü‚µ‚½"
+
+#: buffer.c:831
+msgid "1 buffer wiped out"
+msgstr "1 ŒÂ‚̃oƒbƒtƒ@‚ª”jŠü‚³‚ê‚Ü‚µ‚½"
+
+#: buffer.c:833
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "%d ŒÂ‚̃oƒbƒtƒ@‚ª”jŠü‚³‚ê‚Ü‚µ‚½"
+
+#: buffer.c:894
+msgid "E84: No modified buffer found"
+msgstr "E84: •ÏX‚³‚ꂽƒoƒbƒtƒ@‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#. back where we started, didn't find anything.
+#: buffer.c:933
+msgid "E85: There is no listed buffer"
+msgstr "E85: ƒŠƒXƒg•\\Ž¦‚³‚ê‚éƒoƒbƒtƒ@‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: buffer.c:945
+#, c-format
+msgid "E86: Buffer %ld does not exist"
+msgstr "E86: ƒoƒbƒtƒ@ %ld ‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: buffer.c:948
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: ÅŒã‚̃oƒbƒtƒ@‚ð‰z‚¦‚Ĉړ®‚Í‚Å‚«‚Ü‚¹‚ñ"
+
+#: buffer.c:950
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: ʼn‚̃oƒbƒtƒ@‚æ‚è‘O‚ւ͈ړ®‚Å‚«‚Ü‚¹‚ñ"
+
+#: buffer.c:988
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr "E89: ƒoƒbƒtƒ@ %ld ‚Ì•ÏX‚Í•Û‘¶‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ (! ‚Å•ÏX‚ð”jŠü)"
+
+#: buffer.c:1005
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: ÅŒã‚̃oƒbƒtƒ@‚͉ð•ú‚Å‚«‚Ü‚¹‚ñ"
+
+#: buffer.c:1538
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Œx: ƒtƒ@ƒCƒ‹–¼‚̃ŠƒXƒg‚ª’·‚·‚¬‚Ü‚·"
+
+#: buffer.c:1709
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: ƒoƒbƒtƒ@ %ld ‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: buffer.c:1940
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: %s ‚É•¡”‚ÌŠY“–‚ª‚ ‚è‚Ü‚µ‚½"
+
+#: buffer.c:1942
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: %s ‚ÉŠY“–‚·‚éƒoƒbƒtƒ@‚Í‚ ‚è‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: buffer.c:2337
+#, c-format
+msgid "line %ld"
+msgstr "s %ld"
+
+#: buffer.c:2420
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: ‚±‚Ì–¼‘O‚̃oƒbƒtƒ@‚ÍŠù‚É‚ ‚è‚Ü‚·"
+
+#: buffer.c:2713
+msgid " [Modified]"
+msgstr " [•ÏX‚ ‚è]"
+
+#: buffer.c:2718
+msgid "[Not edited]"
+msgstr "[–¢•ÒW]"
+
+#: buffer.c:2723
+msgid "[New file]"
+msgstr "[Vƒtƒ@ƒCƒ‹]"
+
+#: buffer.c:2724
+msgid "[Read errors]"
+msgstr "[“ÇžƒGƒ‰[]"
+
+#: buffer.c:2726 fileio.c:2049
+msgid "[readonly]"
+msgstr "[“Çžê—p]"
+
+#: buffer.c:2747
+msgid "1 line --%d%%--"
+msgstr "1 s --%d%%--"
+
+#: buffer.c:2749
+msgid "%ld lines --%d%%--"
+msgstr "%ld s --%d%%--"
+
+#: buffer.c:2756
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "s %ld (‘S‘Ì %ld) --%d%%-- col "
+
+#: buffer.c:2864
+msgid "[No file]"
+msgstr "[–³‘è]"
+
+#. must be a help buffer
+#: buffer.c:2904
+msgid "help"
+msgstr "ƒwƒ‹ƒv"
+
+#: buffer.c:3463 screen.c:5038
+msgid "[help]"
+msgstr "[ƒwƒ‹ƒv]"
+
+#: buffer.c:3495 screen.c:5044
+msgid "[Preview]"
+msgstr "[ƒvƒŒƒrƒ…[]"
+
+#: buffer.c:3775
+msgid "All"
+msgstr "‘S‚Ä"
+
+#: buffer.c:3775
+msgid "Bot"
+msgstr "––”ö"
+
+#: buffer.c:3777
+msgid "Top"
+msgstr "擪"
+
+#: buffer.c:4523
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# ƒoƒbƒtƒ@ƒŠƒXƒg:\n"
+
+#: buffer.c:4556
+msgid "[Error List]"
+msgstr "[ƒGƒ‰[ƒŠƒXƒg]"
+
+#: buffer.c:4569 memline.c:1520
+msgid "[No File]"
+msgstr "[–³‘è]"
+
+#: buffer.c:4882
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- ƒTƒCƒ“ ---"
+
+#: buffer.c:4901
+#, c-format
+msgid "Signs for %s:"
+msgstr "%s ‚̃TƒCƒ“:"
+
+#: buffer.c:4907
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " s=%ld Ž¯•ÊŽq=%d –¼‘O=%s"
+
+#: diff.c:139
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: %ld ˆÈã‚̃oƒbƒtƒ@‚Ídiff‚Å‚«‚Ü‚¹‚ñ"
+
+#: diff.c:709
+msgid "E97: Cannot create diffs"
+msgstr "E97: ·•ª‚ð쬂ł«‚Ü‚¹‚ñ "
+
+#: diff.c:814
+msgid "Patch file"
+msgstr "ƒpƒbƒ`ƒtƒ@ƒCƒ‹"
+
+#: diff.c:1065
+msgid "E98: Cannot read diff output"
+msgstr "E98: diff‚Ìo—Í‚ð“Çž‚ß‚Ü‚¹‚ñ"
+
+#: diff.c:1815
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Œ»Ý‚̃oƒbƒtƒ@‚Í·•ªƒ‚[ƒh‚Å‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: diff.c:1827
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: ·•ªƒ‚[ƒh‚Å‚ ‚鑼‚̃oƒbƒtƒ@‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: diff.c:1835
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr ""
+"E101: ·•ªƒ‚[ƒh‚̃oƒbƒtƒ@‚ª2ŒÂˆÈã‚ ‚é‚Ì‚ÅA‚Ç‚ê‚ðŽg‚¤‚©“Á’è‚Å‚«‚Ü‚¹‚ñ"
+
+#: diff.c:1858
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: ƒoƒbƒtƒ@ \"%s\" ‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: diff.c:1864
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: ƒoƒbƒtƒ@ \"%s\" ‚Í·•ªƒ‚[ƒh‚Å‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: digraph.c:2199
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: ‡Žš‚ÉEscape‚ÍŽg—p‚Å‚«‚Ü‚¹‚ñ"
+
+#: digraph.c:2384
+msgid "E544: Keymap file not found"
+msgstr "E544: ƒL[ƒ}ƒbƒvƒtƒ@ƒCƒ‹‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: digraph.c:2411
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: :source ‚ÅŽæž‚Þƒtƒ@ƒCƒ‹ˆÈŠO‚Å‚Í :loadkeymap ‚ðŽg‚¦‚Ü‚¹‚ñ"
+
+#: edit.c:40
+msgid " Keyword completion (^N^P)"
+msgstr " ƒL[ƒ[ƒh•âŠ® (^N^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E^Y^L^]^F^I^K^D^V^N^P)"
+msgstr " ^X ƒ‚[ƒh (^E^Y^L^]^F^I^K^D^V^N^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N^P)"
+msgstr " ‹ÇŠƒL[ƒ[ƒh•âŠ® (^N^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L^N^P)"
+msgstr " s(‘S‘Ì)•âŠ® (^L^N^P)"
+
+#: edit.c:46
+msgid " File name completion (^F^N^P)"
+msgstr "ƒtƒ@ƒCƒ‹–¼•âŠ® (^F^N^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]^N^P)"
+msgstr " ƒ^ƒO•âŠ® (^]^N^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N^P)"
+msgstr " ƒpƒXƒpƒ^[ƒ“•âŠ® (^N^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D^N^P)"
+msgstr " ’è‹`•âŠ® (^D^N^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K^N^P)"
+msgstr " Ž«‘•âŠ® (^K^N^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T^N^P)"
+msgstr " ƒVƒ\\[ƒ‰ƒX•âŠ® (^T^N^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V^N^P)"
+msgstr " ƒRƒ}ƒ“ƒhƒ‰ƒCƒ“•âŠ® (^V^N^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "’i—Ž‚ÌÅŒã‚Ƀqƒbƒg"
+
+#: edit.c:962
+msgid "'thesaurus' option is empty"
+msgstr "'thesaurus' ƒIƒvƒVƒ‡ƒ“‚ª‹ó‚Å‚·"
+
+#: edit.c:1166
+msgid "'dictionary' option is empty"
+msgstr "'dictionary' ƒIƒvƒVƒ‡ƒ“‚ª‹ó‚Å‚·"
+
+#: edit.c:2162
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Ž«‘‚ðƒXƒLƒƒƒ“’†: %s"
+
+#: edit.c:2368
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (‘}“ü) ƒXƒNƒ[ƒ‹(^E/^Y)"
+
+#: edit.c:2370
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (’uŠ·) ƒXƒNƒ[ƒ‹ (^E/^Y)"
+
+#: edit.c:2684
+#, c-format
+msgid "Scanning: %s"
+msgstr "ƒXƒLƒƒƒ“’†: %s"
+
+#: edit.c:2719
+msgid "Scanning tags."
+msgstr "ƒ^ƒO‚ðƒXƒLƒƒƒ“’†."
+
+#: edit.c:3381
+msgid " Adding"
+msgstr " ’ljÁ’†"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3430
+msgid "-- Searching..."
+msgstr "-- ŒŸõ’†..."
+
+#: edit.c:3486
+msgid "Back at original"
+msgstr "Žn‚ß‚É–ß‚é"
+
+#: edit.c:3491
+msgid "Word from other line"
+msgstr "‘¼‚Ìs‚Ì’PŒê"
+
+#: edit.c:3496
+msgid "The only match"
+msgstr "—Bˆê‚ÌŠY“–"
+
+#: edit.c:3555
+#, c-format
+msgid "match %d of %d"
+msgstr "%d ”Ô–Ú‚ÌŠY“– (‘SŠY“– %d ŒÂ’†)"
+
+#: edit.c:3558
+#, c-format
+msgid "match %d"
+msgstr "%d ”Ô–Ú‚ÌŠY“–"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:1024
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: –¢’m‚Ì•Ï”: \"%s\""
+
+#: eval.c:1320
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: ƒJƒbƒR '(' ‚ª‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: eval.c:1435 eval.c:1449
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: ‚»‚Ì•Ï”‚Í‚ ‚è‚Ü‚¹‚ñ: \"%s\""
+
+#: eval.c:1705
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: '?' ‚ÌŒã‚É ':' ‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: eval.c:2327
+msgid "E110: Missing ')'"
+msgstr "E110: ')' ‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: eval.c:2389
+msgid "E111: Missing ']'"
+msgstr "E111: ']' ‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: eval.c:2466
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: ƒIƒvƒVƒ‡ƒ“–¼‚ª‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: eval.c:2484
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: –¢’m‚̃IƒvƒVƒ‡ƒ“‚Å‚·: %s"
+
+#: eval.c:2555
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: ˆø—p•„ (\") ‚ª‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: eval.c:2698
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: ˆø—p•„ (') ‚ª‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: eval.c:3054
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: ŠÖ” %s ‚É‚Í–³Œø‚Ȉø”‚Å‚·"
+
+#: eval.c:3083
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: –¢’m‚ÌŠÖ”‚Å‚·: %s"
+
+#: eval.c:3084
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: ŠÖ”‚̈ø”‚ª‘½‚·‚¬‚Ü‚·: %s"
+
+#: eval.c:3085
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: ŠÖ”‚̈ø”‚ª‘«‚è‚Ü‚¹‚ñ: %s"
+
+#: eval.c:3086
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: ƒXƒNƒŠƒvƒgˆÈŠO‚Å<SID>‚ªŽg‚í‚ê‚Ü‚µ‚½: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3687 gui.c:4376 gui_gtk.c:2059
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:4226
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld s:"
+
+#: eval.c:5477
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"Œˆ’è(&O)\n"
+"ƒLƒƒƒ“ƒZƒ‹(&C)"
+
+#: eval.c:5517
+msgid "called inputrestore() more often than inputsave()"
+msgstr "inputrestore() ‚ª inputsave() ‚æ‚è‚à‘½‚­ŒÄ‚΂ê‚Ü‚µ‚½"
+
+# Added at 10-Mar-2004.
+#: eval.c:5977
+msgid "E655: Too many symbolic links (cycle?)"
+msgstr "E655: ƒVƒ“ƒ{ƒŠƒbƒNƒŠƒ“ƒN‚ª‘½‰ß‚¬‚Ü‚· (zŠÂ‚µ‚Ä‚¢‚é‰Â”\\«‚ª‚ ‚è‚Ü‚·)"
+
+#: eval.c:6609
+msgid "E240: No connection to Vim server"
+msgstr "E240: Vim ƒT[ƒo‚Ö‚ÌÚ‘±‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: eval.c:6706
+msgid "E277: Unable to read a server reply"
+msgstr "E277: ƒT[ƒo‚̉ž“š‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: eval.c:6734
+msgid "E258: Unable to send to client"
+msgstr "E258: ƒNƒ‰ƒCƒAƒ“ƒg‚Ö‘—‚邱‚Æ‚ª‚Å‚«‚Ü‚¹‚ñ"
+
+#: eval.c:6782
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: %s ‚Ö‘—‚邱‚Æ‚ª‚Å‚«‚Ü‚¹‚ñ"
+
+#: eval.c:6882
+msgid "(Invalid)"
+msgstr "(–³Œø)"
+
+#: eval.c:8060
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: –¢’è‹`‚Ì•Ï”‚Å‚·: %s"
+
+#: eval.c:8492
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E461: •s³‚È•Ï”–¼‚Å‚·: %s"
+
+#: eval.c:8784
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: ŠÖ” %s ‚Í’è‹`Ï‚Å‚·, Ä’è‹`‚·‚é‚É‚Í ! ‚ð’ljÁ‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: eval.c:8857
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: –¢’è‹`‚ÌŠÖ”‚Å‚·: %s"
+
+#: eval.c:8870
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: '(' ‚ª‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: eval.c:8903
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: •s³‚Ȉø”‚Å‚·: %s"
+
+#: eval.c:8982
+msgid "E126: Missing :endfunction"
+msgstr "E126: :endfunction ‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: eval.c:9089
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: ŠÖ” %s ‚ðÄ’è‹`‚Å‚«‚Ü‚¹‚ñ: Žg—p’†‚Å‚·"
+
+#: eval.c:9159
+msgid "E129: Function name required"
+msgstr "E129: ŠÖ”–¼‚ª—v‹‚³‚ê‚Ü‚·"
+
+#: eval.c:9210
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: ŠÖ”–¼‚͑啶Žš‚ÅŽn‚Ü‚ç‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ: %s"
+
+#: eval.c:9402
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: –¢’è‹`‚ÌŠÖ”‚Å‚·: %s"
+
+#: eval.c:9407
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: ŠÖ” %s ‚ð휂ł«‚Ü‚¹‚ñ: Žg—p’†‚Å‚·"
+
+#: eval.c:9455
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: ŠÖ”ŒÄo‚Ì“ü‚êŽq”‚ª 'maxfuncdepth' ‚ð’´‚¦‚Ü‚µ‚½"
+
+#. always scroll up, don't overwrite
+#: eval.c:9508
+#, c-format
+msgid "calling %s"
+msgstr "%s ‚ðŽÀs’†‚Å‚·"
+
+#: eval.c:9570
+#, c-format
+msgid "%s aborted"
+msgstr "%s ‚ª’†’f‚³‚ê‚Ü‚µ‚½"
+
+#: eval.c:9572
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s ‚ª #%ld ‚ð•Ô‚µ‚Ü‚µ‚½"
+
+#: eval.c:9579
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s ‚ª \"%s\" ‚ð•Ô‚µ‚Ü‚µ‚½"
+
+#. always scroll up, don't overwrite
+#: eval.c:9595 ex_cmds2.c:2365
+#, c-format
+msgid "continuing in %s"
+msgstr "%s ‚ÌŽÀs‚ðŒp‘±’†‚Å‚·"
+
+#: eval.c:9621
+msgid "E133: :return not inside a function"
+msgstr "E133: ŠÖ”ŠO‚É :return ‚ª‚ ‚è‚Ü‚µ‚½"
+
+#: eval.c:9952
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# ƒOƒ[ƒoƒ‹•Ï”:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, 16i” %02x, 8i” %03o"
+
+#: ex_cmds.c:118
+#, c-format
+msgid "> %d, Hex %04x, Octal %o"
+msgstr "> %d, 16i” %04x, 8i” %o"
+
+#: ex_cmds.c:119
+#, c-format
+msgid "> %d, Hex %08x, Octal %o"
+msgstr "> %d, 16i” %08x, 8i” %o"
+
+#: ex_cmds.c:430
+msgid "E134: Move lines into themselves"
+msgstr "E134: s‚ð‚»‚êŽ©g‚ɂ͈ړ®‚Å‚«‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:499
+msgid "1 line moved"
+msgstr "1 s‚ªˆÚ“®‚³‚ê‚Ü‚µ‚½"
+
+#: ex_cmds.c:501
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld s‚ªˆÚ“®‚³‚ê‚Ü‚µ‚½"
+
+#: ex_cmds.c:924
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld s‚ªƒtƒBƒ‹ƒ^ˆ—‚³‚ê‚Ü‚µ‚½"
+
+#: ex_cmds.c:952
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *ƒtƒBƒ‹ƒ^* autocommand‚ÍŒ»Ý‚̃oƒbƒtƒ@‚ð•ÏX‚µ‚Ä‚Í‚¢‚¯‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:1037
+msgid "[No write since last change]\n"
+msgstr "[ÅŒã‚Ì•ÏX‚ª•Û‘¶‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ]\n"
+
+#: ex_cmds.c:1283
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s s–Ú: "
+
+#: ex_cmds.c:1288
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: ƒGƒ‰[‚ª‘½‰ß‚¬‚é‚Ì‚Å, ˆÈ~‚̓XƒLƒbƒv‚µ‚Ü‚·"
+
+#: ex_cmds.c:1323
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "viminfoƒtƒ@ƒCƒ‹ \"%s\"%s%s%s ‚ð“Çž‚Ý’† "
+
+#: ex_cmds.c:1324
+msgid " info"
+msgstr " î•ñ"
+
+#: ex_cmds.c:1325
+msgid " marks"
+msgstr " ƒ}[ƒN"
+
+#: ex_cmds.c:1326
+msgid " FAILED"
+msgstr " Ž¸”s"
+
+#: ex_cmds.c:1418
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: viminfoƒtƒ@ƒCƒ‹‚ª‘ž‚Ý‚Å‚«‚Ü‚¹‚ñ: %s"
+
+#: ex_cmds.c:1543
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: viminfoƒtƒ@ƒCƒ‹ %s ‚ð•Û‘¶‚Å‚«‚Ü‚¹‚ñ!"
+
+#: ex_cmds.c:1551
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "viminfoƒtƒ@ƒCƒ‹ \"%s\" ‚ð‘ž‚Ý’†"
+
+#. Write the info:
+#: ex_cmds.c:1649
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# ‚±‚Ì viminfo ƒtƒ@ƒCƒ‹‚Í Vim %s ‚É‚æ‚Á‚Ķ¬‚³‚ê‚Ü‚µ‚½.\n"
+
+#: ex_cmds.c:1651
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# •ÏX‚·‚éÛ‚É‚Í\\•ª’ˆÓ‚µ‚Ä‚­‚¾‚³‚¢!\n"
+"\n"
+
+#: ex_cmds.c:1653
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# ‚±‚̃tƒ@ƒCƒ‹‚ª‘‚©‚ꂽŽž‚Ì 'encoding' ‚Ì’l\n"
+
+#: ex_cmds.c:1752
+msgid "Illegal starting char"
+msgstr "•s³‚È擪•¶Žš‚Å‚·"
+
+#: ex_cmds.c:2097 ex_cmds.c:2362 ex_cmds2.c:763
+msgid "Save As"
+msgstr "•Ê–¼‚Å•Û‘¶"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2140
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: “¯‚¶–¼‘O‚̃tƒ@ƒCƒ‹‚ª‘¼‚̃oƒbƒtƒ@‚Å“Çž‚Ü‚ê‚Ä‚¢‚Ü‚·"
+
+#: ex_cmds.c:2174
+msgid "Write partial file?"
+msgstr "ƒtƒ@ƒCƒ‹‚ð•”•ª“I‚É•Û‘¶‚µ‚Ü‚·‚©?"
+
+#: ex_cmds.c:2181
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: ƒoƒbƒtƒ@‚ð•”•ª“I‚É•Û‘¶‚·‚é‚É‚Í ! ‚ðŽg‚Á‚Ä‚­‚¾‚³‚¢"
+
+#: ex_cmds.c:2296
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Šù‘¶‚̃tƒ@ƒCƒ‹ \"%.*s\" ‚ðã‘‚«‚µ‚Ü‚·‚©?"
+
+#: ex_cmds.c:2367
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: ƒoƒbƒtƒ@ %ld ‚É‚Í–¼‘O‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:2405
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: ƒtƒ@ƒCƒ‹‚Í•Û‘¶‚³‚ê‚Ü‚¹‚ñ‚Å‚µ‚½: 'write' ƒIƒvƒVƒ‡ƒ“‚É‚æ‚è–³Œø‚Å‚·"
+
+#: ex_cmds.c:2425
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"\"%.*s\" ‚É‚Í 'readonly' ƒIƒvƒVƒ‡ƒ“‚ªÝ’肳‚ê‚Ä‚¢‚Ü‚·\n"
+"‹­§“I‚Éã‘‚«‚µ‚Ü‚·‚©?"
+
+#: ex_cmds.c:2597
+msgid "Edit File"
+msgstr "ƒtƒ@ƒCƒ‹‚ð•ÒW"
+
+#: ex_cmds.c:3205
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: autocommand‚ª—\\Šú‚¹‚¸V‚µ‚¢ƒoƒbƒtƒ@ %s ‚ð휂µ‚Ü‚µ‚½"
+
+#: ex_cmds.c:3339
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: ”‚Å‚Í‚È‚¢ˆø”‚ª :z ‚É“n‚³‚ê‚Ü‚µ‚½"
+
+#: ex_cmds.c:3424
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: rvim‚ł̓VƒFƒ‹ƒRƒ}ƒ“ƒh‚ðŽg‚¦‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:3531
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: ³‹K•\\Œ»‚Í•¶Žš‚Å‹æ؂邱‚Æ‚ª‚Å‚«‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:3877
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "%s ‚É’uŠ·‚µ‚Ü‚·‚©? (y/n/a/q/l/^E/^Y)"
+
+#: ex_cmds.c:4270
+msgid "(Interrupted) "
+msgstr "(Š„ž‚Ü‚ê‚Ü‚µ‚½)"
+
+#: ex_cmds.c:4274
+msgid "1 substitution"
+msgstr "1 ‰ÓŠ’uŠ·‚µ‚Ü‚µ‚½"
+
+#: ex_cmds.c:4276
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld ‰ÓŠ’uŠ·‚µ‚Ü‚µ‚½"
+
+#: ex_cmds.c:4279
+msgid " on 1 line"
+msgstr " (Œv 1 s“à)"
+
+#: ex_cmds.c:4281
+#, c-format
+msgid " on %ld lines"
+msgstr " (Œv %ld s“à)"
+
+#: ex_cmds.c:4332
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :global ‚ðÄ‹A“I‚É‚ÍŽg‚¦‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:4367
+msgid "E148: Regular expression missing from global"
+msgstr "E148: globalƒRƒ}ƒ“ƒh‚ɳ‹K•\\Œ»‚ªŽw’肳‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:4416
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "ƒpƒ^[ƒ“‚ª‘S‚Ä‚Ìs‚ł݂‚©‚è‚Ü‚µ‚½: %s"
+
+#: ex_cmds.c:4497
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# ÅŒã‚É’uŠ·‚³‚ꂽ•¶Žš—ñ:\n"
+"$"
+
+#: ex_cmds.c:4598 ex_docmd.c:2011
+msgid "E478: Don't panic!"
+msgstr "E478: Q‚Ä‚È‚¢‚Å‚­‚¾‚³‚¢"
+
+#: ex_cmds.c:4650
+#, c-format
+msgid "E661: Sorry, no '%s' help for %s"
+msgstr "E661: Žc”O‚Å‚·‚ª '%s' ‚̃wƒ‹ƒv‚ª %s ‚É‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:4653
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Žc”O‚Å‚·‚ª %s ‚ɂ̓wƒ‹ƒv‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:4687
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Žc”O‚Å‚·‚ªƒwƒ‹ƒvƒtƒ@ƒCƒ‹ \"%s\" ‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:5170
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: ƒfƒBƒŒƒNƒgƒŠ‚Å‚Í‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: ex_cmds.c:5309
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: ‘ž‚Ý—p‚É %s ‚ðŠJ‚¯‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:5345
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: “Çž—p‚É %s ‚ðŠJ‚¯‚Ü‚¹‚ñ"
+
+# Added at 29-Apr-2004.
+#: ex_cmds.c:5367
+#, c-format
+msgid "E670: Mix of help file encodings within a language: %s"
+msgstr "E670: 1‚‚̌¾Œê‚̃wƒ‹ƒvƒtƒ@ƒCƒ‹‚É•¡”‚̃Gƒ“ƒR[ƒh‚ª¬Ý‚µ‚Ä‚¢‚Ü‚·: %s"
+
+#: ex_cmds.c:5445
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: ƒ^ƒO \"%s\" ‚ªƒtƒ@ƒCƒ‹ %s ‚Éd•¡‚µ‚Ä‚¢‚Ü‚·"
+
+#: ex_cmds.c:5557
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: –¢’m‚ÌsignƒRƒ}ƒ“ƒh‚Å‚·: %s"
+
+#: ex_cmds.c:5577
+msgid "E156: Missing sign name"
+msgstr "E156: sign–¼‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:5623
+msgid "E612: Too many signs defined"
+msgstr "E612: sign‚Ì’è‹`‚ª‘½”Œ©‚‚©‚è‚Ü‚µ‚½"
+
+#: ex_cmds.c:5691
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: –³Œø‚Èsign‚̃eƒLƒXƒg‚Å‚·: %s"
+
+#: ex_cmds.c:5722 ex_cmds.c:5913
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: –¢’m‚Ìsign‚Å‚·: %s"
+
+#: ex_cmds.c:5771
+msgid "E159: Missing sign number"
+msgstr "E159: sign‚̔Ԇ‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_cmds.c:5853
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: –³Œø‚ȃoƒbƒtƒ@–¼‚Å‚·: %s"
+
+#: ex_cmds.c:5892
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: –³Œø‚ÈsignŽ¯•ÊŽq‚Å‚·: %ld"
+
+# Added at 27-Jan-2004.
+#: ex_cmds.c:5962
+msgid " (NOT FOUND)"
+msgstr " (‚݂‚©‚è‚Ü‚¹‚ñ)"
+
+#: ex_cmds.c:5964
+msgid " (not supported)"
+msgstr " (”ñƒTƒ|[ƒg)"
+
+#: ex_cmds.c:6063
+msgid "[Deleted]"
+msgstr "[íœÏ]"
+
+#: ex_cmds2.c:92
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "ƒfƒoƒbƒOƒ‚[ƒh‚É“ü‚è‚Ü‚·. ‘±‚¯‚é‚É‚Í \"cont\" ‚Æ“ü—Í‚µ‚Ä‚­‚¾‚³‚¢."
+
+#: ex_cmds2.c:96 ex_docmd.c:966
+#, c-format
+msgid "line %ld: %s"
+msgstr "s %ld: %s"
+
+#: ex_cmds2.c:98
+#, c-format
+msgid "cmd: %s"
+msgstr "ƒRƒ}ƒ“ƒh: %s"
+
+#: ex_cmds2.c:290
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "ƒuƒŒ[ƒNƒ|ƒCƒ“ƒg \"%s%s\" s %ld"
+
+#: ex_cmds2.c:540
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: ƒuƒŒ[ƒNƒ|ƒCƒ“ƒg‚ª‚݂‚©‚è‚Ü‚¹‚ñ: %s"
+
+#: ex_cmds2.c:566
+msgid "No breakpoints defined"
+msgstr "ƒuƒŒ[ƒNƒ|ƒCƒ“ƒg‚ª’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:571
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s s %ld"
+
+#: ex_cmds2.c:786
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "•ÏX‚ð \"%.*s\" ‚É•Û‘¶‚µ‚Ü‚·‚©?"
+
+#: ex_cmds2.c:788 ex_docmd.c:9356
+msgid "Untitled"
+msgstr "–³‘è"
+
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: ƒoƒbƒtƒ@ \"%s\" ‚Ì•ÏX‚Í•Û‘¶‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "Œx: —\\Šú‚¹‚¸‘¼ƒoƒbƒtƒ@‚ÖˆÚ“®‚µ‚Ü‚µ‚½ (autocommands ‚𒲂ׂĂ­‚¾‚³‚¢)"
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: •ÒW‚·‚éƒtƒ@ƒCƒ‹‚Í1‚‚µ‚©‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: ʼn‚̃tƒ@ƒCƒ‹‚æ‚è‘O‚É‚Ís‚¯‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: ÅŒã‚̃tƒ@ƒCƒ‹‚ð‰z‚¦‚ÄŒã‚É‚Ís‚¯‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:1804
+#, c-format
+msgid "E666: compiler not supported: %s"
+msgstr "E666: ‚»‚̃Rƒ“ƒpƒCƒ‰‚ɂ͑Ήž‚µ‚Ä‚¢‚Ü‚¹‚ñ: %s"
+
+#: ex_cmds2.c:1897
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "\"%s\" ‚ð \"%s\" ‚©‚猟õ’†"
+
+#: ex_cmds2.c:1919
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "\"%s\" ‚ðŒŸõ’†"
+
+#: ex_cmds2.c:1940
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "'runtimepath' ‚Ì’†‚ɂ݂͂‚©‚è‚Ü‚¹‚ñ: \"%s\""
+
+#: ex_cmds2.c:1974
+msgid "Source Vim script"
+msgstr "VimƒXƒNƒŠƒvƒg‚ÌŽæž‚Ý"
+
+#: ex_cmds2.c:2164
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "ƒfƒBƒŒƒNƒgƒŠ‚ÍŽæž‚ß‚Ü‚¹‚ñ: \"%s\""
+
+#: ex_cmds2.c:2202
+#, c-format
+msgid "could not source \"%s\""
+msgstr "\"%s\" ‚ðŽæž‚ß‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:2204
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "s %ld: \"%s\" ‚ðŽæž‚ß‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:2218
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "\"%s\" ‚ðŽæž’†"
+
+#: ex_cmds2.c:2220
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "s %ld: %s ‚ðŽæž’†"
+
+#: ex_cmds2.c:2363
+#, c-format
+msgid "finished sourcing %s"
+msgstr "%s ‚ÌŽæž‚ðŠ®—¹"
+
+#: ex_cmds2.c:2707
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Œx: s‹æØ‚ª•s³‚Å‚·. ^M ‚ª‚È‚¢‚Ì‚Å‚µ‚傤"
+
+#: ex_cmds2.c:2756
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :scriptencoding ‚ªŽæžƒXƒNƒŠƒvƒgˆÈŠO‚ÅŽg—p‚³‚ê‚Ü‚µ‚½"
+
+#: ex_cmds2.c:2789
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish ‚ªŽæžƒXƒNƒŠƒvƒgˆÈŠO‚ÅŽg—p‚³‚ê‚Ü‚µ‚½"
+
+#: ex_cmds2.c:3238
+#, c-format
+msgid "Page %d"
+msgstr "%d ƒy[ƒW"
+
+#: ex_cmds2.c:3394
+msgid "No text to be printed"
+msgstr "ˆóü‚·‚éƒeƒLƒXƒg‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:3472
+msgid "Printing page %d (%d%%)"
+msgstr "ˆóü’†: ƒy[ƒW %d (%d%%)"
+
+#: ex_cmds2.c:3484
+#, c-format
+msgid " Copy %d of %d"
+msgstr " ƒRƒs[ %d (‘S %d ’†)"
+
+#: ex_cmds2.c:3542
+#, c-format
+msgid "Printed: %s"
+msgstr "ˆóü‚µ‚Ü‚µ‚½: %s"
+
+#: ex_cmds2.c:3549
+msgid "Printing aborted"
+msgstr "ˆóü‚ª’†Ž~‚³‚ê‚Ü‚µ‚½"
+
+#: ex_cmds2.c:3914
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: PostScripto—̓tƒ@ƒCƒ‹‚Ì‘ž‚݃Gƒ‰[‚Å‚·"
+
+#: ex_cmds2.c:4189
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E624: ƒtƒ@ƒCƒ‹ \"%s\" ‚ðŠJ‚¯‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:4199 ex_cmds2.c:4824
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: PostScript‚̃Šƒ\\[ƒXƒtƒ@ƒCƒ‹ \"%s\" ‚ð“Çž‚ß‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:4207
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: ƒtƒ@ƒCƒ‹ \"%s\" ‚Í PostScript ƒŠƒ\\[ƒXƒtƒ@ƒCƒ‹‚Å‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:4222 ex_cmds2.c:4242 ex_cmds2.c:4257 ex_cmds2.c:4279
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: ƒtƒ@ƒCƒ‹ \"%s\" ‚͑Ήž‚µ‚Ä‚¢‚È‚¢ PostScript ƒŠƒ\\[ƒXƒtƒ@ƒCƒ‹‚Å‚·"
+
+#: ex_cmds2.c:4309
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: ƒŠƒ\\[ƒXƒtƒ@ƒCƒ‹ \"%s\" ‚̓o[ƒWƒ‡ƒ“‚ªˆÙ‚È‚è‚Ü‚·"
+
+#: ex_cmds2.c:4776
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: PostScripto—Í—p‚̃tƒ@ƒCƒ‹‚ðŠJ‚¯‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:4809
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: ƒtƒ@ƒCƒ‹ \"%s\" ‚ðŠJ‚¯‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:4928
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr "E456: PostScript‚̃Šƒ\\[ƒXƒtƒ@ƒCƒ‹ \"prolog.ps\" ‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:4959
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: PostScript‚̃Šƒ\\[ƒXƒtƒ@ƒCƒ‹ \"%s.ps\" ‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:4977
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr "E620: ƒ}ƒ‹ƒ`ƒoƒCƒg•¶Žš‚ðƒGƒ“ƒR[ƒh \"%s\" ‚Ö•ÏŠ·‚Å‚«‚Ü‚¹‚ñ"
+
+#: ex_cmds2.c:5102
+msgid "Sending to printer..."
+msgstr "ƒvƒŠƒ“ƒ^‚É‘—M’†..."
+
+#: ex_cmds2.c:5106
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: PostScriptƒtƒ@ƒCƒ‹‚̈óü‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: ex_cmds2.c:5108
+msgid "Print job sent."
+msgstr "ˆóüƒWƒ‡ƒu‚ð‘—M‚µ‚Ü‚µ‚½."
+
+#: ex_cmds2.c:5618
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Œ»Ý‚Ì %sŒ¾Œê: \"%s\""
+
+#: ex_cmds2.c:5629
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Œ¾Œê‚ð \"%s\" ‚ÉÝ’è‚Å‚«‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:525
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Exƒ‚[ƒh‚É“ü‚è‚Ü‚·. ƒm[ƒ}ƒ‹‚É–ß‚é‚É‚Í\"visual\"‚Æ“ü—Í‚µ‚Ä‚­‚¾‚³‚¢."
+
+#. must be at EOF
+#: ex_docmd.c:561
+msgid "E501: At end-of-file"
+msgstr "E501: ƒtƒ@ƒCƒ‹‚ÌI—¹ˆÊ’u"
+
+#: ex_docmd.c:669
+msgid "E169: Command too recursive"
+msgstr "E169: ƒRƒ}ƒ“ƒh‚ªÄ‹A“I‰ß‚¬‚Ü‚·"
+
+#: ex_docmd.c:1229
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: —áŠO‚ª•ß‘¨‚³‚ê‚Ü‚¹‚ñ‚Å‚µ‚½: %s"
+
+#: ex_docmd.c:1317
+msgid "End of sourced file"
+msgstr "Žæžƒtƒ@ƒCƒ‹‚ÌÅŒã‚Å‚·"
+
+#: ex_docmd.c:1318
+msgid "End of function"
+msgstr "ŠÖ”‚ÌÅŒã‚Å‚·"
+
+#: ex_docmd.c:1907
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: ƒ†[ƒU’è‹`ƒRƒ}ƒ“ƒh‚Ì‚ ‚¢‚Ü‚¢‚ÈŽg—p‚Å‚·"
+
+#: ex_docmd.c:1921
+msgid "E492: Not an editor command"
+msgstr "E492: ƒGƒfƒBƒ^‚̃Rƒ}ƒ“ƒh‚Å‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:2030
+msgid "E493: Backwards range given"
+msgstr "E493: ‹t‚³‚܂͈̔͂ªŽw’肳‚ê‚Ü‚µ‚½"
+
+#: ex_docmd.c:2039
+msgid "Backwards range given, OK to swap"
+msgstr "‹t‚³‚܂͈̔͂ªŽw’肳‚ê‚Ü‚µ‚½, “ü‘Ö‚¦‚Ü‚·‚©?"
+
+#: ex_docmd.c:2162
+msgid "E494: Use w or w>>"
+msgstr "E494: w ‚à‚µ‚­‚Í w>> ‚ðŽg—p‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: ex_docmd.c:3788
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: ‚±‚̃o[ƒWƒ‡ƒ“‚Å‚Í‚±‚̃Rƒ}ƒ“ƒh‚Í—˜—p‚Å‚«‚Ü‚¹‚ñ, ‚²‚ß‚ñ‚È‚³‚¢"
+
+#: ex_docmd.c:3991
+msgid "E172: Only one file name allowed"
+msgstr "E172: ƒtƒ@ƒCƒ‹–¼‚Í 1 ‚‚ɂµ‚Ä‚­‚¾‚³‚¢"
+
+#: ex_docmd.c:4571
+msgid "1 more file to edit. Quit anyway?"
+msgstr "•ÒW‚·‚ׂ«ƒtƒ@ƒCƒ‹‚ª 1 ŒÂ‚ ‚è‚Ü‚·‚ª, I—¹‚µ‚Ü‚·‚©?"
+
+#: ex_docmd.c:4574
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "•ÒW‚·‚ׂ«ƒtƒ@ƒCƒ‹‚ª‚ ‚Æ %d ŒÂ‚ ‚è‚Ü‚·‚ª, I—¹‚µ‚Ü‚·‚©?"
+
+#: ex_docmd.c:4581
+msgid "E173: 1 more file to edit"
+msgstr "E173: •ÒW‚·‚ׂ«ƒtƒ@ƒCƒ‹‚ª 1 ŒÂ‚ ‚è‚Ü‚·"
+
+#: ex_docmd.c:4583
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: •ÒW‚·‚ׂ«ƒtƒ@ƒCƒ‹‚ª‚ ‚Æ %ld ŒÂ‚ ‚è‚Ü‚·"
+
+#: ex_docmd.c:4678
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: ƒRƒ}ƒ“ƒh‚ªŠù‚É‚ ‚è‚Ü‚·: Ä’è‹`‚·‚é‚É‚Í ! ‚ð’ljÁ‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: ex_docmd.c:4789
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" –¼‘O ˆø” ”ÍˆÍ •âŠ® ’è‹`"
+
+#: ex_docmd.c:4878
+msgid "No user-defined commands found"
+msgstr "ƒ†[ƒU’è‹`ƒRƒ}ƒ“ƒh‚ªŒ©‚‚©‚è‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: ex_docmd.c:4910
+msgid "E175: No attribute specified"
+msgstr "E175: ‘®«‚Í’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:4962
+msgid "E176: Invalid number of arguments"
+msgstr "E176: ˆø”‚Ì”‚ª–³Œø‚Å‚·"
+
+#: ex_docmd.c:4977
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: ƒJƒEƒ“ƒg‚ð2dŽw’è‚·‚邱‚Æ‚Í‚Å‚«‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:4987
+msgid "E178: Invalid default value for count"
+msgstr "E178: ƒJƒEƒ“ƒg‚ÌÈ—ª’l‚ª–³Œø‚Å‚·"
+
+#: ex_docmd.c:5018
+msgid "E179: argument required for complete"
+msgstr "E179: •âŠ®‚Ì‚½‚߂̈ø”‚ª•K—v‚Å‚·"
+
+#: ex_docmd.c:5050
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: –³Œø‚ȕ⊮Žw’è‚Å‚·: %s"
+
+#: ex_docmd.c:5059
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr "E468: •âŠ®ˆø”‚̓JƒXƒ^ƒ€•âŠ®‚Å‚µ‚©Žg—p‚Å‚«‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:5065
+msgid "E467: Custom completion requires a function argument"
+msgstr "E467: ƒJƒXƒ^ƒ€•âŠ®‚ɂ͈ø”‚Æ‚µ‚ÄŠÖ”‚ª•K—v‚Å‚·"
+
+#: ex_docmd.c:5076
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: –³Œø‚È‘®«‚Å‚·: %s"
+
+#: ex_docmd.c:5119
+msgid "E182: Invalid command name"
+msgstr "E182: –³Œø‚ȃRƒ}ƒ“ƒh–¼‚Å‚·"
+
+#: ex_docmd.c:5134
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: ƒ†[ƒU’è‹`ƒRƒ}ƒ“ƒh‚͉p‘啶Žš‚ÅŽn‚Ü‚ç‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:5205
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: ‚»‚̃†[ƒU’è‹`ƒRƒ}ƒ“ƒh‚Í‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: ex_docmd.c:5666
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: ƒJƒ‰[ƒXƒL[ƒ€ %s ‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:5674
+msgid "Greetings, Vim user!"
+msgstr "Vim Žg‚¢‚³‚ñA‚â‚ !"
+
+#: ex_docmd.c:6391
+msgid "Edit File in new window"
+msgstr "V‚µ‚¢ƒEƒBƒ“ƒhƒE‚Ńtƒ@ƒCƒ‹‚ð•ÒW‚µ‚Ü‚·"
+
+#: ex_docmd.c:6686
+msgid "No swap file"
+msgstr "ƒXƒƒbƒvƒtƒ@ƒCƒ‹‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:6790
+msgid "Append File"
+msgstr "’ljÁƒtƒ@ƒCƒ‹"
+
+#: ex_docmd.c:6854
+msgid "E186: No previous directory"
+msgstr "E186: ‘O‚̃fƒBƒŒƒNƒgƒŠ‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:6936
+msgid "E187: Unknown"
+msgstr "E187: –¢’m"
+
+#: ex_docmd.c:7021
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: "
+
+#: ex_docmd.c:7077
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "ƒEƒBƒ“ƒhƒEˆÊ’u: X %d, Y %d"
+
+#: ex_docmd.c:7082
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr ""
+"E188: ‚±‚̃vƒ‰ƒbƒgƒz[ƒ€‚ɂ̓EƒBƒ“ƒhƒEˆÊ’u‚̎擾‹@”\\‚ÍŽÀ‘•‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:7092
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: :winpos ‚É‚Í2‚‚̔’l‚̈ø”‚ª•K—v‚Å‚·"
+
+#: ex_docmd.c:7370
+msgid "Save Redirection"
+msgstr "ƒŠƒ_ƒCƒŒƒNƒg‚ð•Û‘¶‚µ‚Ü‚·"
+
+#: ex_docmd.c:7560
+msgid "Save View"
+msgstr "ƒrƒ…[‚ð•Û‘¶‚µ‚Ü‚·"
+
+#: ex_docmd.c:7561
+msgid "Save Session"
+msgstr "ƒZƒbƒVƒ‡ƒ“î•ñ‚ð•Û‘¶‚µ‚Ü‚·"
+
+#: ex_docmd.c:7563
+msgid "Save Setup"
+msgstr "Ý’è‚ð•Û‘¶‚µ‚Ü‚·"
+
+#: ex_docmd.c:7715
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" ‚ª‘¶Ý‚µ‚Ü‚· (ã‘‚·‚é‚É‚Í ! ‚ð’ljÁ‚µ‚Ä‚­‚¾‚³‚¢)"
+
+#: ex_docmd.c:7720
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: \"%s\" ‚ð‘ž‚Ý—p‚Æ‚µ‚ÄŠJ‚¯‚Ü‚¹‚ñ"
+
+#. set mark
+#: ex_docmd.c:7744
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: ˆø”‚Í•¶Žš‚©‘Oi/Œã‘ÞƒNƒH[ƒg‚Å‚µ‚È‚¯‚ê‚΂¢‚¯‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:7786
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: :normal ‚ÌÄ‹A—˜—p‚ª[‚­‚È‚è‚·‚¬‚Ü‚µ‚½"
+
+#: ex_docmd.c:8304
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: '#'‚ð’u‚«Š·‚¦‚é•›ƒtƒ@ƒCƒ‹‚Ì–¼‘O‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:8335
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: \"<afile>\"‚ð’u‚«Š·‚¦‚éautocommand‚̃tƒ@ƒCƒ‹–¼‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:8343
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "E496: \"<abuf>\"‚ð’u‚«Š·‚¦‚éautocommandƒoƒbƒtƒ@”Ô†‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:8354
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr "E497: \"<amatch>\"‚ð’u‚«Š·‚¦‚éautocommand‚ÌŠY“––¼‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:8364
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr "E498: \"<sfile>\"‚ð’u‚«Š·‚¦‚é :source ‘ÎÛƒtƒ@ƒCƒ‹–¼‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:8405
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr ""
+"E499: '%' ‚â '#' ‚ª–³–¼ƒtƒ@ƒCƒ‹‚È‚Ì‚Å \":p:h\" ‚𔺂í‚È‚¢Žg‚¢•û‚Í‚Å‚«‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:8407
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: ‹ó•¶Žš—ñ‚Æ‚µ‚Ä•]‰¿‚³‚ê‚Ü‚µ‚½"
+
+#: ex_docmd.c:9338
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: viminfoƒtƒ@ƒCƒ‹‚ð“Çž—p‚Æ‚µ‚ÄŠJ‚¯‚Ü‚¹‚ñ"
+
+#: ex_docmd.c:9511
+msgid "E196: No digraphs in this version"
+msgstr "E196: ‚±‚̃o[ƒWƒ‡ƒ“‚ɇŽš‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: ex_eval.c:440
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr "E608: 'Vim' ‚ÅŽn‚Ü‚é—áŠO‚Í :throw ‚Å‚«‚Ü‚¹‚ñ"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:529
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "—áŠO‚ª”­¶‚µ‚Ü‚µ‚½: %s"
+
+#: ex_eval.c:576
+#, c-format
+msgid "Exception finished: %s"
+msgstr "—áŠO‚ªŽû‘©‚µ‚Ü‚µ‚½: %s"
+
+#: ex_eval.c:577
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "—áŠO‚ª”jŠü‚³‚ê‚Ü‚µ‚½: %s"
+
+#: ex_eval.c:620 ex_eval.c:664
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, s %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:638
+#, c-format
+msgid "Exception caught: %s"
+msgstr "—áŠO‚ª•ß‘¨‚³‚ê‚Ü‚µ‚½: %s"
+
+#: ex_eval.c:713
+#, c-format
+msgid "%s made pending"
+msgstr "%s ‚É‚æ‚è–¢Œˆ’èó‘Ô‚ª¶‚¶‚Ü‚µ‚½"
+
+#: ex_eval.c:716
+#, c-format
+msgid "%s resumed"
+msgstr "%s ‚ªÄŠJ‚µ‚Ü‚µ‚½"
+
+#: ex_eval.c:720
+#, c-format
+msgid "%s discarded"
+msgstr "%s ‚ª”jŠü‚³‚ê‚Ü‚µ‚½"
+
+#: ex_eval.c:746
+msgid "Exception"
+msgstr "—áŠO"
+
+#: ex_eval.c:752
+msgid "Error and interrupt"
+msgstr "ƒGƒ‰[‚ÆŠ„ž‚Ý"
+
+#: ex_eval.c:754 gui.c:4375
+msgid "Error"
+msgstr "ƒGƒ‰["
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:756
+msgid "Interrupt"
+msgstr "Š„ž‚Ý"
+
+#: ex_eval.c:830
+msgid "E579: :if nesting too deep"
+msgstr "E579: :if ‚Ì“ü‚êŽq‚ª[‰ß‚¬‚Ü‚·"
+
+#: ex_eval.c:867
+msgid "E580: :endif without :if"
+msgstr "E580: :if ‚Ì‚È‚¢ :endif ‚ª‚ ‚è‚Ü‚·"
+
+#: ex_eval.c:911
+msgid "E581: :else without :if"
+msgstr "E581: :if ‚Ì‚È‚¢ :else ‚ª‚ ‚è‚Ü‚·"
+
+#: ex_eval.c:914
+msgid "E582: :elseif without :if"
+msgstr "E582: :if ‚Ì‚È‚¢ :elseif ‚ª‚ ‚è‚Ü‚·"
+
+#: ex_eval.c:921
+msgid "E583: multiple :else"
+msgstr "E583: •¡”‚Ì :else ‚ª‚ ‚è‚Ü‚·"
+
+#: ex_eval.c:924
+msgid "E584: :elseif after :else"
+msgstr "E584: :else ‚ÌŒã‚É :elseif ‚ª‚ ‚è‚Ü‚·"
+
+#: ex_eval.c:991
+msgid "E585: :while nesting too deep"
+msgstr "E585: :while ‚Ì“ü‚êŽq‚ª[‚­‰ß‚¬‚Ü‚·"
+
+#: ex_eval.c:1047
+msgid "E586: :continue without :while"
+msgstr "E586: :while ‚Ì‚È‚¢ :continue ‚ª‚ ‚è‚Ü‚·"
+
+#: ex_eval.c:1087
+msgid "E587: :break without :while"
+msgstr "E587: :while ‚Ì‚È‚¢ :break ‚ª‚ ‚è‚Ü‚·"
+
+#: ex_eval.c:1286
+msgid "E601: :try nesting too deep"
+msgstr "E601: :try ‚Ì“ü‚êŽq‚ª[‰ß‚¬‚Ü‚·"
+
+#: ex_eval.c:1366
+msgid "E603: :catch without :try"
+msgstr "E603: :try ‚Ì‚È‚¢ :catch ‚ª‚ ‚è‚Ü‚·"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1388
+msgid "E604: :catch after :finally"
+msgstr "E604: :finally ‚ÌŒã‚É :catch ‚ª‚ ‚è‚Ü‚·"
+
+#: ex_eval.c:1521
+msgid "E606: :finally without :try"
+msgstr "E606: :try ‚Ì‚È‚¢ :finally ‚ª‚ ‚è‚Ü‚·"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1545
+msgid "E607: multiple :finally"
+msgstr "E607: •¡”‚Ì :finalyy ‚ª‚ ‚è‚Ü‚·"
+
+#: ex_eval.c:1654
+msgid "E602: :endtry without :try"
+msgstr "E602: :try ‚Ì‚È‚¢ :endtry ‚Å‚·"
+
+#: ex_eval.c:1986
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: ŠÖ”‚ÌŠO‚É :endfunction ‚ª‚ ‚è‚Ü‚µ‚½"
+
+#: ex_getln.c:3295
+msgid "tagname"
+msgstr "ƒ^ƒO–¼"
+
+#: ex_getln.c:3298
+msgid " kind file\n"
+msgstr " ƒtƒ@ƒCƒ‹Ží—Þ\n"
+
+#: ex_getln.c:4751
+msgid "'history' option is zero"
+msgstr "ƒIƒvƒVƒ‡ƒ“ 'history' ‚ªƒ[ƒ‚Å‚·"
+
+#: ex_getln.c:5017
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s €–Ú‚Ì—š—ð (V‚µ‚¢‚à‚Ì‚©‚çŒÃ‚¢‚à‚Ì‚Ö):\n"
+
+#: ex_getln.c:5018
+msgid "Command Line"
+msgstr "ƒRƒ}ƒ“ƒhƒ‰ƒCƒ“"
+
+#: ex_getln.c:5019
+msgid "Search String"
+msgstr "ŒŸõ•¶Žš—ñ"
+
+#: ex_getln.c:5020
+msgid "Expression"
+msgstr "Ž®"
+
+#: ex_getln.c:5021
+msgid "Input Line"
+msgstr "“ü—Ís"
+
+#: ex_getln.c:5059
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar ‚ªƒRƒ}ƒ“ƒh’·‚ð’´‚¦‚Ü‚µ‚½"
+
+#: ex_getln.c:5236
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: ƒAƒNƒeƒBƒu‚ȃEƒBƒ“ƒhƒE‚©ƒoƒbƒtƒ@‚ªíœ‚³‚ê‚Ü‚µ‚½"
+
+#: fileio.c:371
+msgid "Illegal file name"
+msgstr "•s³‚ȃtƒ@ƒCƒ‹–¼"
+
+#: fileio.c:395 fileio.c:529 fileio.c:2850 fileio.c:2891
+msgid "is a directory"
+msgstr " ‚̓fƒBƒŒƒNƒgƒŠ‚Å‚·"
+
+#: fileio.c:397
+msgid "is not a file"
+msgstr " ‚̓tƒ@ƒCƒ‹‚Å‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: fileio.c:551 fileio.c:4057
+msgid "[New File]"
+msgstr "[Vƒtƒ@ƒCƒ‹]"
+
+#: fileio.c:584
+msgid "[Permission Denied]"
+msgstr "[”F‰Â‚ª‚ ‚è‚Ü‚¹‚ñ]"
+
+#: fileio.c:688
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre autocommand ‚ªƒtƒ@ƒCƒ‹‚ð“Çž•s‰Â‚É‚µ‚Ü‚µ‚½"
+
+#: fileio.c:690
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *ReadPre autocommand ‚ÍŒ»Ý‚̃oƒbƒtƒ@‚ð•Ï‚¦‚ç‚ê‚Ü‚¹‚ñ"
+
+#: fileio.c:711
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: •W€“ü—Í‚©‚ç“Çž’†...\n"
+
+#: fileio.c:717
+msgid "Reading from stdin..."
+msgstr "•W€“ü—Í‚©‚ç“Çž‚Ý’†..."
+
+#. Re-opening the original file failed!
+#: fileio.c:988
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: •ÏŠ·‚ªƒtƒ@ƒCƒ‹‚ð“Çž•s‰Â‚É‚µ‚Ü‚µ‚½"
+
+#: fileio.c:2027
+msgid "[fifo/socket]"
+msgstr "[FIFO/ƒ\\ƒPƒbƒg]"
+
+#: fileio.c:2034
+msgid "[fifo]"
+msgstr "[FIFO]"
+
+#: fileio.c:2041
+msgid "[socket]"
+msgstr "[ƒ\\ƒPƒbƒg]"
+
+#: fileio.c:2049
+msgid "[RO]"
+msgstr "[“Çê]"
+
+#: fileio.c:2059
+msgid "[CR missing]"
+msgstr "[CR–³]"
+
+#: fileio.c:2064
+msgid "[NL found]"
+msgstr "[NL—L]"
+
+#: fileio.c:2069
+msgid "[long lines split]"
+msgstr "[’·s•ªŠ„]"
+
+#: fileio.c:2075 fileio.c:4041
+msgid "[NOT converted]"
+msgstr "[–¢•ÏŠ·]"
+
+#: fileio.c:2080 fileio.c:4046
+msgid "[converted]"
+msgstr "[•ÏŠ·Ï]"
+
+#: fileio.c:2087 fileio.c:4071
+msgid "[crypted]"
+msgstr "[ˆÃ†‰»]"
+
+#: fileio.c:2094
+msgid "[CONVERSION ERROR]"
+msgstr "[•ÏŠ·ƒGƒ‰[]"
+
+#: fileio.c:2100
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[%ld s–Ú‚Ì•s³‚ȃoƒCƒg]"
+
+#: fileio.c:2107
+msgid "[READ ERRORS]"
+msgstr "[“ÇžƒGƒ‰[]"
+
+#: fileio.c:2323
+msgid "Can't find temp file for conversion"
+msgstr "•ÏŠ·‚É•K—v‚Ȉꎞƒtƒ@ƒCƒ‹‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: fileio.c:2330
+msgid "Conversion with 'charconvert' failed"
+msgstr "'charconvert' ‚É‚æ‚é•ÏŠ·‚ªŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: fileio.c:2333
+msgid "can't read output of 'charconvert'"
+msgstr "'charconvert' ‚Ìo—Í‚ð“Çž‚ß‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: fileio.c:2733
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: •Û‘¶‚·‚éƒoƒbƒtƒ@‚ðautocommand‚ªíœ‚©‰ð•ú‚µ‚Ü‚µ‚½"
+
+#: fileio.c:2756
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: autocommand‚ª—\\Šú‚¹‚Ê•û–@‚Ås”‚ð•ÏX‚µ‚Ü‚µ‚½"
+
+# Added at 19-Jan-2004.
+#: fileio.c:2794
+msgid "NetBeans dissallows writes of unmodified buffers"
+msgstr "NetBeans‚Í–¢•ÏX‚̃oƒbƒtƒ@‚ðã‘‚·‚邱‚Æ‚Í‹–‰Â‚µ‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: fileio.c:2802
+msgid "Partial writes disallowed for NetBeans buffers"
+msgstr "NetBeansƒoƒbƒtƒ@‚̈ꕔ‚ð‘‚«o‚·‚±‚Æ‚Í‚Å‚«‚Ü‚¹‚ñ"
+
+#: fileio.c:2856 fileio.c:2874
+msgid "is not a file or writable device"
+msgstr "‚̓tƒ@ƒCƒ‹‚Å‚à‘ž‚݉”\\ƒfƒoƒCƒX‚Å‚à‚ ‚è‚Ü‚¹‚ñ"
+
+#: fileio.c:2926
+msgid "is read-only (add ! to override)"
+msgstr "‚Í“Çžê—p‚Å‚· (‹­§‘ž‚É‚Í ! ‚ð’ljÁ)"
+
+#: fileio.c:3272
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: ƒoƒbƒNƒAƒbƒvƒtƒ@ƒCƒ‹‚ð•Û‘¶‚Å‚«‚Ü‚¹‚ñ (! ‚ð’ljÁ‚Å‹­§•Û‘¶)"
+
+#: fileio.c:3284
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr ""
+"E507: ƒoƒbƒNƒAƒbƒvƒtƒ@ƒCƒ‹‚ð•Â‚¶‚éۂɃGƒ‰[‚ª”­¶‚µ‚Ü‚µ‚½ (! ‚ð’ljÁ‚Å‹­§)"
+
+#: fileio.c:3286
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr "E508: ƒoƒbƒNƒAƒbƒv—pƒtƒ@ƒCƒ‹‚ð“Çž‚ß‚Ü‚¹‚ñ (! ‚ð’ljÁ‚Å‹­§“Çž)"
+
+#: fileio.c:3302
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: ƒoƒbƒNƒAƒbƒvƒtƒ@ƒCƒ‹‚ðì‚ê‚Ü‚¹‚ñ (! ‚ð’ljÁ‚Å‹­§ì¬)"
+
+#: fileio.c:3405
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: ƒoƒbƒNƒAƒbƒvƒtƒ@ƒCƒ‹‚ðì‚ê‚Ü‚¹‚ñ (! ‚ð’ljÁ‚Å‹­§ì¬)"
+
+#: fileio.c:3467
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr "E460: ƒŠƒ\\[ƒXƒtƒH[ƒN‚ªŽ¸‚í‚ê‚é‚©‚à‚µ‚ê‚Ü‚¹‚ñ (! ‚ð’ljÁ‚Å‹­§)"
+
+#: fileio.c:3566
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: •Û‘¶—pˆêŽžƒtƒ@ƒCƒ‹‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: fileio.c:3584
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr "E213: •ÏŠ·‚Å‚«‚Ü‚¹‚ñ (! ‚ð’ljÁ‚Å•ÏŠ·‚¹‚¸‚É•Û‘¶)"
+
+#: fileio.c:3619
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: ƒŠƒ“ƒN‚³‚ꂽƒtƒ@ƒCƒ‹‚É‘ž‚ß‚Ü‚¹‚ñ"
+
+#: fileio.c:3623
+msgid "E212: Can't open file for writing"
+msgstr "E212: ‘ž‚Ý—p‚Ƀtƒ@ƒCƒ‹‚ðŠJ‚¯‚Ü‚¹‚ñ"
+
+#: fileio.c:3885
+msgid "E667: Fsync failed"
+msgstr "E667: fsync ‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: fileio.c:3892
+msgid "E512: Close failed"
+msgstr "E512: •Â‚¶‚邱‚Æ‚ÉŽ¸”s"
+
+#: fileio.c:3963
+msgid "E513: write error, conversion failed"
+msgstr "E513: ‘ž‚݃Gƒ‰[, •ÏŠ·Ž¸”s"
+
+#: fileio.c:3969
+msgid "E514: write error (file system full?)"
+msgstr "E514: ‘ž‚݃Gƒ‰[, (ƒtƒ@ƒCƒ‹ƒVƒXƒeƒ€‚ª–ž”t?)"
+
+#: fileio.c:4036
+msgid " CONVERSION ERROR"
+msgstr " •ÏŠ·ƒGƒ‰["
+
+#: fileio.c:4052
+msgid "[Device]"
+msgstr "[ƒfƒoƒCƒX]"
+
+#: fileio.c:4057
+msgid "[New]"
+msgstr "[V]"
+
+#: fileio.c:4079
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:4079
+msgid " appended"
+msgstr " ’ljÁ"
+
+#: fileio.c:4081
+msgid " [w]"
+msgstr " [w]"
+
+#: fileio.c:4081
+msgid " written"
+msgstr " ‘ž‚Ý"
+
+#: fileio.c:4131
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: patchmode: Œ´–{ƒtƒ@ƒCƒ‹‚ð•Û‘¶‚Å‚«‚Ü‚¹‚ñ"
+
+#: fileio.c:4153
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: ‹ó‚ÌŒ´–{ƒtƒ@ƒCƒ‹‚ðtouch‚Å‚«‚Ü‚¹‚ñ"
+
+#: fileio.c:4168
+msgid "E207: Can't delete backup file"
+msgstr "E207: ƒoƒbƒNƒAƒbƒvƒtƒ@ƒCƒ‹‚ðÁ‚¹‚Ü‚¹‚ñ"
+
+#: fileio.c:4232
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"Œx: Œ´–{ƒtƒ@ƒCƒ‹‚ªŽ¸‚í‚ꂽ‚©•ÏX‚³‚ê‚Ü‚µ‚½\n"
+
+#: fileio.c:4234
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "ƒtƒ@ƒCƒ‹‚Ì•Û‘¶‚ɬŒ÷‚·‚é‚܂ŃGƒfƒBƒ^‚ðI—¹‚µ‚È‚¢‚Å‚­‚¾‚³‚¢!"
+
+#: fileio.c:4323
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:4323
+msgid "[dos format]"
+msgstr "[dosƒtƒH[ƒ}ƒbƒg]"
+
+#: fileio.c:4330
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:4330
+msgid "[mac format]"
+msgstr "[macƒtƒH[ƒ}ƒbƒg]"
+
+#: fileio.c:4337
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:4337
+msgid "[unix format]"
+msgstr "[unixƒtƒH[ƒ}ƒbƒg]"
+
+#: fileio.c:4364
+msgid "1 line, "
+msgstr "1 s, "
+
+#: fileio.c:4366
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld s, "
+
+#: fileio.c:4369
+msgid "1 character"
+msgstr "1 •¶Žš"
+
+#: fileio.c:4371
+#, c-format
+msgid "%ld characters"
+msgstr "%ld •¶Žš"
+
+#: fileio.c:4381
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:4381
+msgid "[Incomplete last line]"
+msgstr "[ÅIs‚ª•sŠ®‘S]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4400
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "Œx: “Çž‚ñ‚¾Œã‚Ƀtƒ@ƒCƒ‹‚É•ÏX‚ª‚ ‚è‚Ü‚µ‚½!!!"
+
+#: fileio.c:4402
+msgid "Do you really want to write to it"
+msgstr "–{“–‚Éã‘‚«‚µ‚Ü‚·‚©"
+
+#: fileio.c:5566
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: \"%s\" ‚ð‘ž‚Ý’†‚̃Gƒ‰[‚Å‚·"
+
+#: fileio.c:5573
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: \"%s\" ‚ð•Â‚¶‚鎞‚ɃGƒ‰[‚Å‚·"
+
+#: fileio.c:5576
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: \"%s\" ‚ð“Çž’†‚̃Gƒ‰[‚Å‚·"
+
+#: fileio.c:5810
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: autocommand ‚Ì FileChangedShell ‚ªƒoƒbƒtƒ@‚ð휂µ‚Ü‚µ‚½"
+
+#: fileio.c:5817
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: Œx: ƒtƒ@ƒCƒ‹ \"%s\" ‚ÍŠù‚É‘¶Ý‚µ‚Ü‚¹‚ñ"
+
+#: fileio.c:5831
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr "W12: Œx: ƒtƒ@ƒCƒ‹ \"%s\" ‚ª•ÏX‚³‚êVim‚̃oƒbƒtƒ@‚à•ÏX‚³‚ê‚Ü‚µ‚½"
+
+#: fileio.c:5834
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: Œx: ƒtƒ@ƒCƒ‹ \"%s\" ‚Í•ÒWŠJŽnŒã‚É•ÏX‚³‚ê‚Ü‚µ‚½"
+
+#: fileio.c:5836
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: Œx: ƒtƒ@ƒCƒ‹ \"%s\" ‚̃‚[ƒh‚ª•ÒWŠJŽnŒã‚É•ÏX‚³‚ê‚Ü‚µ‚½"
+
+#: fileio.c:5846
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: Œx: ƒtƒ@ƒCƒ‹ \"%s\" ‚Í•ÒWŠJŽnŒã‚É쬂³‚ê‚Ü‚µ‚½"
+
+#: fileio.c:5859
+msgid "See \":help W11\" for more info."
+msgstr "Ú×‚Í \":help W11\" ‚ðŽQÆ‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: fileio.c:5873
+msgid "Warning"
+msgstr "Œx"
+
+#: fileio.c:5874
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"ƒtƒ@ƒCƒ‹“Çž(&L)"
+
+#: fileio.c:5980
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: \"%s\" ‚ðƒŠƒ[ƒh‚·‚途õ‚ª‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: fileio.c:5999
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: \"%s\" ‚̓Šƒ[ƒh‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: fileio.c:6580
+msgid "--Deleted--"
+msgstr "--íœÏ--"
+
+#. the group doesn't exist
+#: fileio.c:6740
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: ‚»‚̃Oƒ‹[ƒv‚Í‚ ‚è‚Ü‚¹‚ñ: \"%s\""
+
+#: fileio.c:6866
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: * ‚ÌŒã‚É•s³‚È•¶Žš‚ª‚ ‚è‚Ü‚µ‚½: %s"
+
+#: fileio.c:6878
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: ‚»‚̂悤‚ȃCƒxƒ“ƒg‚Í‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: fileio.c:6880
+#, c-format
+msgid "E216: No such group or event: %s"
+msgstr "E216: ‚»‚̂悤‚ȃOƒ‹[ƒv‚à‚µ‚­‚̓Cƒxƒ“ƒg‚Í‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#. Highlight title
+#: fileio.c:7038
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Auto-Commands ---"
+
+#: fileio.c:7309
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: ‘S‚ẴCƒxƒ“ƒg‚ɑ΂µ‚Ä‚Ìautocommand‚ÍŽÀs‚Å‚«‚Ü‚¹‚ñ"
+
+#: fileio.c:7332
+msgid "No matching autocommands"
+msgstr "ŠY“–‚·‚éautocommand‚Í‘¶Ý‚µ‚Ü‚¹‚ñ"
+
+#: fileio.c:7653
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: autocommand‚Ì“ü‚êŽq‚ª[‚·‚¬‚Ü‚·"
+
+#: fileio.c:7928
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Auto commands for \"%s\""
+
+#: fileio.c:7936
+#, c-format
+msgid "Executing %s"
+msgstr "%s ‚ðŽÀs‚µ‚Ä‚¢‚Ü‚·"
+
+#. always scroll up, don't overwrite
+#: fileio.c:8004
+#, c-format
+msgid "autocommand %s"
+msgstr "autocommand %s"
+
+#: fileio.c:8571
+msgid "E219: Missing {."
+msgstr "E219: { ‚ª‚ ‚è‚Ü‚¹‚ñ."
+
+#: fileio.c:8573
+msgid "E220: Missing }."
+msgstr "E220: } ‚ª‚ ‚è‚Ü‚¹‚ñ."
+
+#: fold.c:68
+msgid "E490: No fold found"
+msgstr "E490: Üô‚Ý‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: fold.c:593
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: Œ»Ý‚Ì 'foldmethod' ‚Å‚ÍÜô‚Ý‚ð쬂ł«‚Ü‚¹‚ñ"
+
+#: fold.c:595
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: Œ»Ý‚Ì 'foldmethod' ‚Å‚ÍÜô‚Ý‚ð휂ł«‚Ü‚¹‚ñ"
+
+#: getchar.c:248
+msgid "E222: Add to read buffer"
+msgstr "E222: “Çžƒoƒbƒtƒ@‚֒ljÁ"
+
+#: getchar.c:2198
+msgid "E223: recursive mapping"
+msgstr "E223: Ä‹A“Iƒ}ƒbƒsƒ“ƒO"
+
+#: getchar.c:3077
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: %s ‚Æ‚¢‚¤ƒOƒ[ƒoƒ‹’Zk“ü—Í‚ÍŠù‚É‘¶Ý‚µ‚Ü‚·"
+
+#: getchar.c:3080
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: %s ‚Æ‚¢‚¤ƒOƒ[ƒoƒ‹ƒ}ƒbƒsƒ“ƒO‚ÍŠù‚É‘¶Ý‚µ‚Ü‚·"
+
+#: getchar.c:3212
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: %s ‚Æ‚¢‚¤’Zk“ü—Í‚ÍŠù‚É‘¶Ý‚µ‚Ü‚·"
+
+#: getchar.c:3215
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: %s ‚Æ‚¢‚¤ƒ}ƒbƒsƒ“ƒO‚ÍŠù‚É‘¶Ý‚µ‚Ü‚·"
+
+#: getchar.c:3279
+msgid "No abbreviation found"
+msgstr "’Zk“ü—݂͂͂‚©‚è‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: getchar.c:3281
+msgid "No mapping found"
+msgstr "ƒ}ƒbƒsƒ“ƒO‚݂͂‚©‚è‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: getchar.c:4173
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: •s³‚ȃ‚[ƒh"
+
+#: gui.c:220
+msgid "E229: Cannot start the GUI"
+msgstr "E229: GUI‚ðŠJŽn‚Å‚«‚Ü‚¹‚ñ"
+
+#: gui.c:349
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: \"%s\"‚©‚ç“Çž‚Þ‚±‚Æ‚ª‚Å‚«‚Ü‚¹‚ñ"
+
+#: gui.c:472
+msgid "E665: Cannot start GUI, no valid font found"
+msgstr "E665: —LŒø‚ȃtƒHƒ“ƒg‚ªŒ©‚‚©‚ç‚È‚¢‚Ì‚Å, GUI‚ðŠJŽn‚Å‚«‚Ü‚¹‚ñ"
+
+#: gui.c:477
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: 'guifontwide' ‚ª–³Œø‚Å‚·"
+
+#: gui.c:547
+msgid "E599: Value of 'imactivatekey' is invalid"
+msgstr "E599: 'imactivatekey' ‚Éݒ肳‚ꂽ’l‚ª–³Œø‚Å‚·"
+
+#: gui.c:4061
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: %s ‚ÌF‚ðŠ„‚è“–‚Ä‚ç‚ê‚Ü‚¹‚ñ"
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<ŠJ‚¯‚Ü‚¹‚ñ>"
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: ƒtƒHƒ“ƒg %s ‚ðŽæ“¾‚Å‚«‚Ü‚¹‚ñ"
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: Œ»Ý‚̃fƒBƒŒƒNƒgƒŠ‚É–ß‚ê‚Ü‚¹‚ñ"
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "ƒpƒX–¼:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: Œ»Ý‚̃fƒBƒŒƒNƒgƒŠ‚ðŽæ“¾‚Å‚«‚Ü‚¹‚ñ"
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "OK"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2731 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "ƒLƒƒƒ“ƒZƒ‹"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "ƒXƒNƒ[ƒ‹ƒo[: ‰æ‘œ‚ðŽæ“¾‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½."
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "Vim ƒ_ƒCƒAƒƒO"
+
+#: gui_beval.c:101 gui_w32.c:3830
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: ƒƒbƒZ[ƒW‚ƃR[ƒ‹ƒoƒbƒN‚Ì‚ ‚é BalloonEval ‚ð쬂ł«‚Ü‚¹‚ñ"
+
+#: gui_gtk.c:1607
+msgid "Vim dialog..."
+msgstr "Vim ƒ_ƒCƒAƒƒO..."
+
+#: gui_gtk.c:2060 message.c:2993
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"‚Í‚¢(&Y)\n"
+"‚¢‚¢‚¦(&N)\n"
+"ƒLƒƒƒ“ƒZƒ‹(&C)"
+
+#: gui_gtk.c:2268
+msgid "Input _Methods"
+msgstr "ƒCƒ“ƒvƒbƒgƒƒ\\ƒbƒh"
+
+#: gui_gtk.c:2534 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "VIM - ŒŸõ‚Æ’uŠ·..."
+
+#: gui_gtk.c:2542 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "VIM - ŒŸõ..."
+
+#: gui_gtk.c:2574 gui_motif.c:2888
+msgid "Find what:"
+msgstr "ŒŸõ•¶Žš—ñ:"
+
+#: gui_gtk.c:2592 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "’uŠ·•¶Žš—ñ:"
+
+#. whole word only button
+#: gui_gtk.c:2624 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "³Šm‚ÉŠY“–‚·‚é‚à‚Ì‚¾‚¯"
+
+#. match case button
+#: gui_gtk.c:2635 gui_motif.c:3048
+msgid "Match case"
+msgstr "‘啶Žš/¬•¶Žš‚ð‹æ•Ê‚·‚é"
+
+#: gui_gtk.c:2645 gui_motif.c:2990
+msgid "Direction"
+msgstr "•ûŒü"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2657 gui_motif.c:3002
+msgid "Up"
+msgstr "ã"
+
+#: gui_gtk.c:2661 gui_motif.c:3010
+msgid "Down"
+msgstr "‰º"
+
+#: gui_gtk.c:2683 gui_gtk.c:2685 gui_motif.c:2792
+msgid "Find Next"
+msgstr "ŽŸ‚ðŒŸõ"
+
+#: gui_gtk.c:2702 gui_gtk.c:2704 gui_motif.c:2809
+msgid "Replace"
+msgstr "’uŠ·"
+
+#: gui_gtk.c:2715 gui_gtk.c:2717 gui_motif.c:2822
+msgid "Replace All"
+msgstr "‘S‚Ä’uŠ·"
+
+#: gui_gtk_x11.c:2327
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: ƒZƒbƒVƒ‡ƒ“ƒ}ƒl[ƒWƒƒ‚©‚ç \"die\" —v‹‚ðŽó‚¯Žæ‚è‚Ü‚µ‚½\n"
+
+#: gui_gtk_x11.c:3519
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: ƒƒCƒ“ƒEƒBƒ“ƒhƒE‚ª•sˆÓ‚É”j‰ó‚³‚ê‚Ü‚µ‚½\n"
+
+#: gui_gtk_x11.c:4138
+msgid "Font Selection"
+msgstr "ƒtƒHƒ“ƒg‘I‘ð"
+
+#: gui_gtk_x11.c:6035 ui.c:2117
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "‹ó‚Ì‘I‘ð—̈æ‚Ì‚©‚í‚è‚ÉCUT_BUFFER0‚ªŽg—p‚³‚ê‚Ü‚µ‚½"
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "ƒtƒBƒ‹ƒ^"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "ƒfƒBƒŒƒNƒgƒŠ"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "ƒwƒ‹ƒv"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "ƒtƒ@ƒCƒ‹"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "‘I‘ð"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "ƒAƒ“ƒhƒD"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: ZapƒtƒHƒ“ƒg '%s' ‚ð“Çž‚ß‚Ü‚¹‚ñ"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: ƒtƒHƒ“ƒg %s ‚ðŽg—p‚Å‚«‚Ü‚¹‚ñ"
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"ŽqƒvƒƒZƒX‚Ö’âŽ~ƒƒbƒZ[ƒW‚ð‘—M’†‚Å‚·.\n"
+
+#: gui_w32.c:830
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: ˆø”‚̓Tƒ|[ƒg‚³‚ê‚Ü‚¹‚ñ: \"-%s\"; OLE”Å‚ðŽg—p‚µ‚Ä‚­‚¾‚³‚¢."
+
+#: gui_w48.c:2090
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "ŒŸõ•¶Žš—ñ ('\\' ‚ðŒŸõ‚·‚é‚É‚Í '\\\\')"
+
+#: gui_w48.c:2115
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "ŒŸõE’uŠ· ('\\' ‚ðŒŸõ‚·‚é‚É‚Í '\\\\')"
+
+#: gui_x11.c:1537
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr "Vim E458: FŽw’肪³‚µ‚­‚È‚¢‚̂ŃGƒ“ƒgƒŠ‚ðŠ„‚è“–‚Ä‚ç‚ê‚Ü‚¹‚ñ"
+
+#: gui_x11.c:2118
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: ˆÈ‰º‚Ì•¶ŽšƒZƒbƒg‚̃tƒHƒ“ƒg‚ª‚ ‚è‚Ü‚¹‚ñ %s:"
+
+#: gui_x11.c:2161
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: ƒtƒHƒ“ƒgƒZƒbƒg–¼: %s"
+
+#: gui_x11.c:2162
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "ƒtƒHƒ“ƒg '%s' ‚͌Œ蕂ł͂ ‚è‚Ü‚¹‚ñ"
+
+#: gui_x11.c:2181
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: ƒtƒHƒ“ƒgƒZƒbƒg–¼: %s\n"
+
+#: gui_x11.c:2182
+#, c-format
+msgid "Font0: %s\n"
+msgstr "ƒtƒHƒ“ƒg0: %s\n"
+
+#: gui_x11.c:2183
+#, c-format
+msgid "Font1: %s\n"
+msgstr "ƒtƒHƒ“ƒg1: %s\n"
+
+#: gui_x11.c:2184
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "ƒtƒHƒ“ƒg%d ‚Ì•‚ªƒtƒHƒ“ƒg0‚Ì”{‚Å‚Í‚ ‚è‚Ü‚¹‚ñ\n"
+
+#: gui_x11.c:2185
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "ƒtƒHƒ“ƒg0‚Ì•: %ld\n"
+
+#: gui_x11.c:2186
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"ƒtƒHƒ“ƒg1‚Ì•: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: ƒnƒ“ƒOƒ‹ƒI[ƒgƒ}ƒgƒ“ƒGƒ‰["
+
+#: if_cscope.c:77
+msgid "Add a new database"
+msgstr "Vƒf[ƒ^ƒx[ƒX‚ð’ljÁ"
+
+#: if_cscope.c:79
+msgid "Query for a pattern"
+msgstr "ƒpƒ^[ƒ“‚̃NƒGƒŠ[‚ð’ljÁ"
+
+#: if_cscope.c:81
+msgid "Show this message"
+msgstr "‚±‚̃ƒbƒZ[ƒW‚ð•\\Ž¦‚·‚é"
+
+#: if_cscope.c:83
+msgid "Kill a connection"
+msgstr "Ú‘±‚ðI—¹‚·‚é"
+
+#: if_cscope.c:85
+msgid "Reinit all connections"
+msgstr "‘S‚Ä‚ÌÚ‘±‚ðĉŠú‰»‚·‚é"
+
+#: if_cscope.c:87
+msgid "Show connections"
+msgstr "Ú‘±‚ð•\\Ž¦‚·‚é"
+
+#: if_cscope.c:95
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: Žg—p•û–@: cs[cope] %s"
+
+#: if_cscope.c:124
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "‚±‚ÌcscopeƒRƒ}ƒ“ƒh‚Í•ªŠ„ƒEƒBƒ“ƒhƒE‚ł̓Tƒ|[ƒg‚³‚ê‚Ü‚¹‚ñ.\n"
+
+#: if_cscope.c:175
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: Žg—p–@: cstag <ident>"
+
+#: if_cscope.c:231
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: ƒ^ƒO‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: if_cscope.c:409
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: stat(%s) ƒGƒ‰[: %d"
+
+#: if_cscope.c:419
+msgid "E563: stat error"
+msgstr "E563: stat ƒGƒ‰["
+
+#: if_cscope.c:516
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s ‚̓fƒBƒŒƒNƒgƒŠ‹y‚Ñ—LŒø‚Ècscope‚̃f[ƒ^ƒx[ƒX‚Å‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: if_cscope.c:534
+#, c-format
+msgid "Added cscope database %s"
+msgstr "cscopeƒf[ƒ^ƒx[ƒX %s ‚ð’ljÁ"
+
+#: if_cscope.c:589
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: cscope‚ÌÚ‘± %ld ‚ð“Çž‚Ý’†‚̃Gƒ‰[‚Å‚·"
+
+#: if_cscope.c:694
+msgid "E561: unknown cscope search type"
+msgstr "E561: –¢’m‚ÌcscopeŒŸõŒ^‚Å‚·"
+
+#: if_cscope.c:736
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: cscopeƒpƒCƒv‚ð쬂ł«‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: if_cscope.c:753
+msgid "E622: Could not fork for cscope"
+msgstr "E622: cscope‚Ì‹N“®€”õ(fork)‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: if_cscope.c:847 if_cscope.c:897
+msgid "cs_create_connection exec failed"
+msgstr "cs_create_connection ‚ÌŽÀs‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: if_cscope.c:898
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: cscopeƒvƒƒZƒX‚ð‹N“®‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: if_cscope.c:911
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: to_fp ‚Ì fdopen ‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: if_cscope.c:913
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fr_fp ‚Ì fdopen ‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: if_cscope.c:951
+msgid "E567: no cscope connections"
+msgstr "E567: cscopeÚ‘±‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: if_cscope.c:1025
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: cscopeƒNƒGƒŠ[ %s of %s ‚ÉŠY“–‚ª‚ ‚è‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: if_cscope.c:1082
+#, c-format
+msgid "E469: invalid cscopequickfix flag %c for %c"
+msgstr "E469: –³Œø‚È cscopequickfix ƒtƒ‰ƒO %c ‚Ì %c ‚Å‚·"
+
+#: if_cscope.c:1152
+msgid "cscope commands:\n"
+msgstr "cscopeƒRƒ}ƒ“ƒh:\n"
+
+#: if_cscope.c:1155
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (Žg—p–@: %s)"
+
+#: if_cscope.c:1253
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: cscopeƒf[ƒ^ƒx[ƒX: %s ‚ðŠJ‚­‚±‚Æ‚ª‚Å‚«‚Ü‚¹‚ñ"
+
+#: if_cscope.c:1271
+msgid "E626: cannot get cscope database information"
+msgstr "E626: cscopeƒf[ƒ^ƒx[ƒX‚Ìî•ñ‚ðŽæ“¾‚Å‚«‚Ü‚¹‚ñ"
+
+#: if_cscope.c:1296
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: d•¡‚·‚écscopeƒf[ƒ^ƒx[ƒX‚͒ljÁ‚³‚ê‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: if_cscope.c:1307
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: cscopeÚ‘±‚Ìő唂ɒB‚µ‚Ü‚µ‚½"
+
+#: if_cscope.c:1424
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: cscopeÚ‘± %s ‚ª‚݂‚©‚è‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: if_cscope.c:1458
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "cscopeÚ‘± %s ‚ª•Â‚¶‚ç‚ê‚Ü‚µ‚½"
+
+#. should not reach here
+#: if_cscope.c:1598
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: cs_manage_matches ‚Å’v–½“I‚ȃGƒ‰[‚Å‚·"
+
+#: if_cscope.c:1848
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "Cscope ƒ^ƒO: %s"
+
+#: if_cscope.c:1870
+msgid ""
+"\n"
+" # line"
+msgstr ""
+"\n"
+" # s”Ô†"
+
+#: if_cscope.c:1872
+msgid "filename / context / line\n"
+msgstr "ƒtƒ@ƒCƒ‹–¼ / •¶–¬ / s\n"
+
+#: if_cscope.c:1990
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: cscopeƒGƒ‰[: %s"
+
+#: if_cscope.c:2176
+msgid "All cscope databases reset"
+msgstr "‘S‚Ä‚Ìcscopeƒf[ƒ^ƒx[ƒX‚ðƒŠƒZƒbƒg‚µ‚Ü‚·"
+
+#: if_cscope.c:2244
+msgid "no cscope connections\n"
+msgstr "cscopeÚ‘±‚ª‚ ‚è‚Ü‚¹‚ñ\n"
+
+#: if_cscope.c:2248
+msgid " # pid database name prepend path\n"
+msgstr " # pid ƒf[ƒ^ƒx[ƒX–¼ prepend ƒpƒX\n"
+
+#: if_python.c:436
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: ‚±‚̃Rƒ}ƒ“ƒh‚Í–³Œø‚Å‚·,‚²‚ß‚ñ‚È‚³‚¢: "
+"Pythonƒ‰ƒCƒuƒ‰ƒŠ‚ðƒ[ƒh‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½."
+
+# Added at 07-Feb-2004.
+#: if_python.c:500
+msgid "E659: Cannot invoke Python recursively"
+msgstr "E659: Python ‚ðÄ‹A“I‚ÉŽÀs‚·‚邱‚Æ‚Í‚Å‚«‚Ü‚¹‚ñ"
+
+#: if_python.c:701
+msgid "can't delete OutputObject attributes"
+msgstr "OutputObject‘®«‚ðÁ‚¹‚Ü‚¹‚ñ"
+
+#: if_python.c:708
+msgid "softspace must be an integer"
+msgstr "softspace ‚Í integer ‚Å‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ"
+
+#: if_python.c:716
+msgid "invalid attribute"
+msgstr "–³Œø‚È‘®«‚Å‚·"
+
+#: if_python.c:755 if_python.c:769
+msgid "writelines() requires list of strings"
+msgstr "writelines() ‚É‚Í•¶Žš—ñ‚̃ŠƒXƒg‚ª•K—v‚Å‚·"
+
+#: if_python.c:895
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: I/OƒIƒuƒWƒFƒNƒg‚̉Šú‰»’†‚ɃGƒ‰[‚Å‚·"
+
+#: if_python.c:1080 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "–³Œø‚ÈŽ®‚Å‚·"
+
+#: if_python.c:1094 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "Ž®‚̓Rƒ“ƒpƒCƒ‹Žž‚É–³Œø‚É‚³‚ê‚Ä‚¢‚Ü‚·"
+
+#: if_python.c:1107
+msgid "attempt to refer to deleted buffer"
+msgstr "Á‚³‚ꂽƒoƒbƒtƒ@‚ªŽQÆ‚³‚ê‚Ü‚µ‚½"
+
+#: if_python.c:1122 if_python.c:1163 if_python.c:1227 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "”͈͊O‚Ìs”Ô†‚Å‚·"
+
+#: if_python.c:1362
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<ƒoƒbƒtƒ@ƒIƒuƒWƒFƒNƒg (Á‹ŽÏ‚Ý) %8lX>"
+
+#: if_python.c:1453 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "–³Œø‚ȃ}[ƒN–¼‚Å‚·"
+
+#: if_python.c:1733
+msgid "no such buffer"
+msgstr "‚»‚̂悤‚ȃoƒbƒtƒ@‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: if_python.c:1821
+msgid "attempt to refer to deleted window"
+msgstr "Á‚³‚ꂽƒEƒBƒ“ƒhƒE‚ªŽQÆ‚³‚ê‚Ü‚µ‚½"
+
+#: if_python.c:1866
+msgid "readonly attribute"
+msgstr "“Çžê—p‘®«"
+
+#: if_python.c:1879
+msgid "cursor position outside buffer"
+msgstr "ƒJ[ƒ\\ƒ‹‚ªƒoƒbƒtƒ@‚ÌŠO‚É‚ ‚è‚Ü‚·"
+
+#: if_python.c:1956
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<ƒEƒBƒ“ƒhƒEƒIƒuƒWƒFƒNƒg (Á‹ŽÏ) %.8lX>"
+
+#: if_python.c:1968
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<ƒEƒBƒ“ƒhƒEƒIƒuƒWƒFƒNƒg (–¢’m) %.8lX>"
+
+#: if_python.c:1970
+#, c-format
+msgid "<window %d>"
+msgstr "<ƒEƒBƒ“ƒhƒE %d>"
+
+#: if_python.c:2046
+msgid "no such window"
+msgstr "‚»‚̂悤‚ȃEƒBƒ“ƒhƒE‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: if_python.c:2307 if_python.c:2341 if_python.c:2396 if_python.c:2464
+#: if_python.c:2586 if_python.c:2638 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "ƒAƒ“ƒhƒDî•ñ‚ª•Û‘¶‚Å‚«‚Ü‚¹‚ñ"
+
+#: if_python.c:2309 if_python.c:2403 if_python.c:2475
+msgid "cannot delete line"
+msgstr "s‚ðÁ‚¹‚Ü‚¹‚ñ"
+
+#: if_python.c:2346 if_python.c:2491 if_tcl.c:690 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "s‚ð’uŠ·‚Å‚«‚Ü‚¹‚ñ"
+
+#: if_python.c:2509 if_python.c:2588 if_python.c:2646
+msgid "cannot insert line"
+msgstr "s‚ð‘}“ü‚Å‚«‚Ü‚¹‚ñ"
+
+#: if_python.c:2750
+msgid "string cannot contain newlines"
+msgstr "•¶Žš—ñ‚ɂ͉üs•¶Žš‚ðŠÜ‚ß‚ç‚ê‚Ü‚¹‚ñ"
+
+#: if_ruby.c:422
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: ‚±‚̃Rƒ}ƒ“ƒh‚Í–³Œø‚Å‚·,‚²‚ß‚ñ‚È‚³‚¢: "
+"Rubyƒ‰ƒCƒuƒ‰ƒŠ‚ðƒ[ƒh‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½."
+
+#: if_ruby.c:485
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: –¢’m‚Ìlongjmpó‘Ô: %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "ŽÀ‘•‚Æ’è‹`‚ðØ‚è‘Ö‚¦‚é"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "ŽŸ‚̃Nƒ‰ƒX‚ÌŠî’ê‚ð•\\Ž¦"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "ƒI[ƒo[ƒ‰ƒCƒh‚³‚ꂽƒƒ“ƒoŠÖ”‚ð•\\Ž¦"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "ƒtƒ@ƒCƒ‹‚©‚ç‰ñ•œ‚·‚é"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "ƒvƒƒWƒFƒNƒg‚©‚ç‰ñ•œ‚·‚é"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "‘S‚ẴvƒƒWƒFƒNƒg‚©‚ç‰ñ•œ‚·‚é"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "‰ñ•œ"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "ŽŸ‚̃\\[ƒX‚ð•\\Ž¦‚·‚é"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "‚݂‚¯‚½ƒVƒ“ƒ{ƒ‹"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "ƒNƒ‰ƒX‚ðŽQÆ"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "ŠK‘w‚ŃNƒ‰ƒX‚ð•\\Ž¦"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "ŒÀ’肳‚ꂽŠK‘w‚ŃNƒ‰ƒX‚ð•\\Ž¦"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref ‚ÌŽQÆæ"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref ‚ªŽQÆ‚³‚ê‚é"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref ‚ªŽŸ‚Ì‚à‚Ì‚ð‚à‚Á‚Ä‚¢‚Ü‚·"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref ‚ªŽg—p‚³‚ê‚é"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "ŽŸ‚Ì•¶Í‚ð•\\Ž¦"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "ŽŸ‚Ì•¶Í‚ð¶¬"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"SNiFF+‚ÉÚ‘±‚Å‚«‚Ü‚¹‚ñ. ŠÂ‹«‚ðƒ`ƒFƒbƒN‚µ‚Ä‚­‚¾‚³‚¢(sniffemacs ‚ª $PATH "
+"‚É‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: “Çž’†‚ɃGƒ‰[‚ª”­¶‚µ‚Ü‚µ‚½. Ø’f‚µ‚Ü‚µ‚½"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "Œ»ÝSNiFF+ ‚Ìó‘Ô‚Íu"
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "–¢"
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "Ú‘±v‚Å‚·"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: –¢’m‚Ì SNiFF+ ƒŠƒNƒGƒXƒg‚Å‚·: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: SNiFF+ ‚Ö‚ÌÚ‘±’†‚̃Gƒ‰[‚Å‚·"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ ‚ÉÚ‘±‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: SNiFF+ ƒoƒbƒtƒ@‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: ‘ž‚Ý’†‚ɃGƒ‰[‚ª”­¶‚µ‚½‚Ì‚ÅØ’f‚µ‚Ü‚µ‚½"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "–³Œø‚ȃoƒbƒtƒ@”Ô†‚Å‚·"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "‚Ü‚¾ŽÀ‘•‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "–¢’m‚̃IƒvƒVƒ‡ƒ“‚Å‚·"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "s‚ðÝ’è‚Å‚«‚Ü‚¹‚ñ"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "ƒ}[ƒN‚Íݒ肳‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "s %d —ñ %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "s‚Ì‘}“ü/’ljÁ‚ð‚Å‚«‚Ü‚¹‚ñ"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "–¢’m‚̃tƒ‰ƒO:"
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "–¢’m‚Ì vimOption ‚Å‚·"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "ƒL[ƒ{[ƒhŠ„ž‚Ý"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "vim ƒGƒ‰["
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr ""
+"ƒoƒbƒtƒ@/ƒEƒBƒ“ƒhƒE쬃Rƒ}ƒ“ƒh‚ð쬂ł«‚Ü‚¹‚ñ: "
+"ƒIƒuƒWƒFƒNƒg‚ªÁ‹Ž‚³‚ê‚Ä‚¢‚Ü‚µ‚½"
+
+#: if_tcl.c:1545
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"ƒR[ƒ‹ƒoƒbƒNƒRƒ}ƒ“ƒh‚ð“o˜^‚Å‚«‚Ü‚¹‚ñ: ƒoƒbƒtƒ@/ƒEƒBƒ“ƒhƒE‚ªŠù‚ÉÁ‹Ž‚³‚ê‚Ü‚µ‚½"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to "
+"vim-dev@vim.org"
+msgstr ""
+"E280: TCL ’v–½“IƒGƒ‰[: reflist ‰˜õ!? vim-dev@vim.org ‚É•ñ‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"ƒR[ƒ‹ƒoƒbƒNƒRƒ}ƒ“ƒh‚ð“o˜^‚Å‚«‚Ü‚¹‚ñ: "
+"ƒoƒbƒtƒ@/ƒEƒBƒ“ƒhƒE‚ÌŽQÆ‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"E571: ‚±‚̃Rƒ}ƒ“ƒh‚Í–³Œø‚Å‚·,‚²‚ß‚ñ‚È‚³‚¢: "
+"Tclƒ‰ƒCƒuƒ‰ƒŠ‚ðƒ[ƒh‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½."
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: TCL ƒGƒ‰[: I—¹ƒR[ƒh‚ª®”’l‚Å‚Í‚ ‚è‚Ü‚¹‚ñ!? vim-dev@vim.org "
+"‚É•ñ‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "s‚ðŽæ“¾‚Å‚«‚Ü‚¹‚ñ"
+
+#: if_xcmdsrv.c:225
+msgid "Unable to register a command server name"
+msgstr "–½—߃T[ƒo‚Ì–¼‘O‚ð“o˜^‚Å‚«‚Ü‚¹‚ñ"
+
+#: if_xcmdsrv.c:473
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: –Ú“I‚̃vƒƒOƒ‰ƒ€‚ւ̃Rƒ}ƒ“ƒh‘—M‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: if_xcmdsrv.c:747
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: –³Œø‚ȃT[ƒoID‚ªŽg‚í‚ê‚Ü‚µ‚½: %s"
+
+#: if_xcmdsrv.c:1110
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: VIM ŽÀ‘Ì‚Ì“o˜^ƒvƒƒpƒeƒB‚ª•s³‚Å‚·. Á‹Ž‚µ‚Ü‚µ‚½!"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "–¢’m‚̃IƒvƒVƒ‡ƒ“‚Å‚·"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "•ÒWˆø”‚ª‘½‚·‚¬‚Ü‚·"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "ˆø”‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "ƒIƒvƒVƒ‡ƒ“‚ÌŒã‚ɃSƒ~‚ª‚ ‚è‚Ü‚·"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr "\"+command\", \"-c command\", \"--cmd command\" ‚̈ø”‚ª‘½‚·‚¬‚Ü‚·"
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "–³Œø‚Ȉø”‚Å‚·: "
+
+#: main.c:466
+msgid "This Vim was not compiled with the diff feature."
+msgstr "‚±‚ÌVim‚É‚Ídiff‹@”\\‚ª‚ ‚è‚Ü‚¹‚ñ(ƒRƒ“ƒpƒCƒ‹ŽžÝ’è)."
+
+#: main.c:932
+msgid "Attempt to open script file again: \""
+msgstr "ƒXƒNƒŠƒvƒgƒtƒ@ƒCƒ‹‚ðÄ‚ÑŠJ‚¢‚Ä‚Ý‚Ü‚·: \""
+
+# msgid "\"\n"
+# msgstr "\"\n"
+#: main.c:941
+msgid "Cannot open for reading: \""
+msgstr "“Çž—p‚Æ‚µ‚ÄŠJ‚¯‚Ü‚¹‚ñ"
+
+#: main.c:985
+msgid "Cannot open for script output: \""
+msgstr "ƒXƒNƒŠƒvƒgo—Í—p‚ðŠJ‚¯‚Ü‚¹‚ñ"
+
+#: main.c:1132
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d ŒÂ‚̃tƒ@ƒCƒ‹‚ª•ÒW‚ðT‚¦‚Ä‚¢‚Ü‚·\n"
+
+#: main.c:1233
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Œx: ’[––‚Ö‚Ìo—Í‚Å‚Í‚ ‚è‚Ü‚¹‚ñ\n"
+
+#: main.c:1235
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Œx: ’[––‚©‚ç‚Ì“ü—Í‚Å‚Í‚ ‚è‚Ü‚¹‚ñ\n"
+
+#. just in case..
+#: main.c:1297
+msgid "pre-vimrc command line"
+msgstr "vimrc‘O‚̃Rƒ}ƒ“ƒhƒ‰ƒCƒ“"
+
+#: main.c:1338
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: \"%s\"‚©‚ç“Çž‚Þ‚±‚Æ‚ª‚Å‚«‚Ü‚¹‚ñ"
+
+#: main.c:2411
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"‚æ‚èÚׂÈî•ñ‚Í: \"vim -h\"\n"
+
+#: main.c:2444
+msgid "[file ..] edit specified file(s)"
+msgstr "[ƒtƒ@ƒCƒ‹..] ‚ ‚éƒtƒ@ƒCƒ‹‚ð•ÒW‚·‚é"
+
+#: main.c:2445
+msgid "- read text from stdin"
+msgstr "- •W€“ü—Í‚©‚çƒeƒLƒXƒg‚ð“Çž‚Þ"
+
+#: main.c:2446
+msgid "-t tag edit file where tag is defined"
+msgstr "-t ƒ^ƒO ƒ^ƒO‚ª’è‹`‚³‚ꂽ‚Æ‚±‚ë‚©‚ç•ÒW‚·‚é"
+
+#: main.c:2448
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [errorfile] ʼn‚̃Gƒ‰[‚Å•ÒW‚·‚é"
+
+#: main.c:2457
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"Žg—p–@:"
+
+#: main.c:2460
+msgid " vim [arguments] "
+msgstr " vim [ˆø”]"
+
+#: main.c:2464
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" ‚à‚µ‚­‚Í:"
+
+#: main.c:2467
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"ˆø”:\n"
+
+#: main.c:2468
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\t‚±‚Ì‚ ‚Ƃɂ̓tƒ@ƒCƒ‹–¼‚¾‚¯"
+
+#: main.c:2470
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tƒƒCƒ‹ƒhƒJ[ƒh‚ð“WŠJ‚µ‚È‚¢"
+
+#: main.c:2473
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\t‚±‚Ìgvim‚ðOLE‚Æ‚µ‚Ä“o˜^‚·‚é"
+
+#: main.c:2474
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tgvim‚ÌOLE“o˜^‚ð‰ðœ‚·‚é"
+
+#: main.c:2477
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tGUI‚Å‹N“®‚·‚é (\"gvim\" ‚Æ“¯‚¶)"
+
+#: main.c:2478
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f or --nofork\tƒtƒHƒAƒOƒ‰ƒEƒ“ƒh: GUI‚ðŽn‚ß‚é‚Æ‚«‚Éfork‚µ‚È‚¢"
+
+#: main.c:2480
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tViƒ‚[ƒh (\"vi\" ‚Æ“¯‚¶)"
+
+#: main.c:2481
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tExƒ‚[ƒh (\"ex\" ‚Æ“¯‚¶)"
+
+#: main.c:2482
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tƒTƒCƒŒƒ“ƒg(ƒoƒbƒ`)ƒ‚[ƒh (\"ex\" ê—p)"
+
+#: main.c:2484
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\t·•ªƒ‚[ƒh (\"vidiff\" ‚Æ“¯‚¶)"
+
+#: main.c:2486
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tƒC[ƒW[ƒ‚[ƒh (\"evim\" ‚Æ“¯‚¶, ƒ‚[ƒh–³)"
+
+#: main.c:2487
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\t“Çžê—pƒ‚[ƒh (\"view\" ‚Æ“¯‚¶)"
+
+#: main.c:2488
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\t§ŒÀƒ‚[ƒh (\"rvim\" ‚Æ“¯‚¶)"
+
+#: main.c:2489
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\t•ÏX (ƒtƒ@ƒCƒ‹•Û‘¶Žž) ‚ð‚Å‚«‚È‚¢‚悤‚É‚·‚é"
+
+#: main.c:2490
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tƒeƒLƒXƒg‚Ì•ÒW‚ðs‚È‚¦‚È‚¢‚悤‚É‚·‚é"
+
+#: main.c:2491
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tƒoƒCƒiƒŠƒ‚[ƒh"
+
+#: main.c:2493
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLispƒ‚[ƒh"
+
+#: main.c:2495
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tViŒÝŠ·ƒ‚[ƒh: 'compatible'"
+
+#: main.c:2496
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tVi”ñŒÝŠ·ƒ‚[ƒh: 'nocompatible"
+
+#: main.c:2497
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tVerbose ƒŒƒxƒ‹"
+
+#: main.c:2498
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tƒfƒoƒbƒOƒ‚[ƒh"
+
+#: main.c:2499
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tƒXƒƒbƒvƒtƒ@ƒCƒ‹‚ðŽg—p‚¹‚¸ƒƒ‚ƒŠ‚¾‚¯"
+
+#: main.c:2500
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tƒXƒƒbƒvƒtƒ@ƒCƒ‹‚ð—ñ‹“‚µI—¹"
+
+#: main.c:2501
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (ƒtƒ@ƒCƒ‹–¼)\tƒNƒ‰ƒbƒVƒ…‚µ‚½ƒZƒbƒVƒ‡ƒ“‚𕜋A"
+
+#: main.c:2502
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\t-r‚Æ“¯‚¶"
+
+#: main.c:2504
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tƒEƒBƒ“ƒhƒE‚ðŠJ‚­‚Ì‚É newcli ‚ðŽg—p‚µ‚È‚¢"
+
+#: main.c:2505
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <device>\t\tI/O‚É <device> ‚ðŽg—p‚·‚é"
+
+#: main.c:2508
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\t\tƒAƒ‰ƒrƒAŒêƒ‚[ƒh‚Å‹N“®‚·‚é"
+
+#: main.c:2511
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\tƒwƒuƒ‰ƒCŒêƒ‚[ƒh‚Å‹N“®‚·‚é"
+
+#: main.c:2514
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\tƒyƒ‹ƒVƒAŒêƒ‚[ƒh‚Å‹N“®‚·‚é"
+
+#: main.c:2516
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\t’[––‚ð <terminal> ‚ÉÝ’è‚·‚é"
+
+#: main.c:2517
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\t.vimrc‚Ì‘ã‚í‚è‚É <vimrc> ‚ðŽg‚¤"
+
+#: main.c:2519
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\t.gvimrc‚Ì‘ã‚í‚è‚É <gvimrc> ‚ðŽg‚¤"
+
+#: main.c:2521
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tƒvƒ‰ƒOƒCƒ“ƒXƒNƒŠƒvƒg‚ðƒ[ƒh‚µ‚È‚¢"
+
+#: main.c:2522
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tN ŒÂƒEƒBƒ“ƒhƒE‚ðŠJ‚­(È—ª’l: ƒtƒ@ƒCƒ‹‚ɂ‚«1ŒÂ)"
+
+#: main.c:2523
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\t-o‚Æ“¯‚¶‚¾‚ª‚’¼•ªŠ„"
+
+#: main.c:2524
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tƒtƒ@ƒCƒ‹‚ÌŌォ‚ç‚Í‚¶‚ß‚é"
+
+#: main.c:2525
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\t<lnum> s‚©‚ç‚Í‚¶‚ß‚é"
+
+#: main.c:2527
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <command>\tvimrc‚ðƒ[ƒh‚·‚é‘O‚É <command> ‚ðŽÀs‚·‚é"
+
+#: main.c:2529
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <command>\t\tʼn‚̃tƒ@ƒCƒ‹‚ðƒ[ƒhŒã <command> ‚ðŽÀs‚·‚é"
+
+#: main.c:2530
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <session>\t\tʼn‚̃tƒ@ƒCƒ‹‚ðƒ[ƒhŒãƒtƒ@ƒCƒ‹ <session> ‚ðŽæž‚Þ"
+
+#: main.c:2531
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <scriptin>\tƒtƒ@ƒCƒ‹ <scriptin> ‚©‚çƒm[ƒ}ƒ‹ƒRƒ}ƒ“ƒh‚ð“Çž‚Þ"
+
+#: main.c:2532
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <scriptout>\t“ü—Í‚µ‚½‘SƒRƒ}ƒ“ƒh‚ðƒtƒ@ƒCƒ‹ <scriptout> ‚ɒljÁ‚·‚é"
+
+#: main.c:2533
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <scriptout>\t“ü—Í‚µ‚½‘SƒRƒ}ƒ“ƒh‚ðƒtƒ@ƒCƒ‹ <scriptout> ‚É•Û‘¶‚·‚é"
+
+#: main.c:2535
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tˆÃ†‰»‚³‚ꂽƒtƒ@ƒCƒ‹‚ð•ÒW‚·‚é"
+
+#: main.c:2539
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\tvim‚ðŽw’肵‚½ X ƒT[ƒo‚ÉÚ‘±‚·‚é"
+
+#: main.c:2541
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tXƒT[ƒo‚ÉÚ‘±‚µ‚È‚¢"
+
+#: main.c:2544
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <files>\t‰Â”\\‚È‚ç‚ÎVimƒT[ƒo‚Å <files> ‚ð•ÒW‚·‚é"
+
+#: main.c:2545
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-silnet <files> “¯ã, ƒT[ƒo‚ª–³‚­‚Ä‚àŒx•¶‚ðo—Í‚µ‚È‚¢"
+
+#: main.c:2546
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <files>\t--remoteŒã ƒtƒ@ƒCƒ‹‚Ì•ÒW‚ªI‚í‚é‚Ì‚ð‘Ò‚Â"
+
+#: main.c:2547
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-wait-silent <files> “¯ã, ƒT[ƒo‚ª–³‚­‚Ä‚àŒx•¶‚ðo—Í‚µ‚È‚¢"
+
+#: main.c:2548
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <keys>\tVimƒT[ƒo‚É <keys> ‚ð‘—M‚µ‚ÄI—¹‚·‚é"
+
+#: main.c:2549
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <expr>\tƒT[ƒo‚Å <expr> ‚ðŽÀs‚µ‚ÄŒ‹‰Ê‚ð•\\Ž¦‚·‚é"
+
+#: main.c:2550
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tVimƒT[ƒo–¼‚̈ꗗ‚ð•\\Ž¦‚µ‚ÄI—¹‚·‚é"
+
+#: main.c:2551
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servename <name>\t\tVimƒT[ƒo <name> ‚É‘—M/–¼‘OÝ’è‚·‚é"
+
+#: main.c:2554
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\t.viminfo‚Ì‘ã‚í‚è‚É <viminfo> ‚ðŽg‚¤"
+
+#: main.c:2556
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h or --help\tƒwƒ‹ƒv(‚±‚̃ƒbƒZ[ƒW)‚ð•\\Ž¦‚µI—¹‚·‚é"
+
+#: main.c:2557
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\tƒo[ƒWƒ‡ƒ“î•ñ‚ð•\\Ž¦‚µI—¹‚·‚é"
+
+#: main.c:2561
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"gvim‚É‚æ‚Á‚ĉðŽß‚³‚ê‚éˆø”(Motifƒo[ƒWƒ‡ƒ“):\n"
+
+#: main.c:2565
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr ""
+"\n"
+"gvim‚É‚æ‚Á‚ĉðŽß‚³‚ê‚éˆø”(neXtawƒo[ƒWƒ‡ƒ“):\n"
+
+#: main.c:2567
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"gvim‚É‚æ‚Á‚ĉðŽß‚³‚ê‚éˆø”(Athenaƒo[ƒWƒ‡ƒ“):\n"
+
+#: main.c:2571
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\t<display> ‚Åvim‚ðŽÀs‚·‚é"
+
+#: main.c:2572
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tŬ‰»‚µ‚½ó‘Ô‚Åvim‚ð‹N“®‚·‚é"
+
+#: main.c:2574
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <name>\t\tvim‚Ì–¼‚ª <name> ‚Å‚ ‚é‚Æ‚µ‚ăŠƒ\\[ƒX‚ðŽg‚¤"
+
+#: main.c:2575
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (ŽÀ‘•‚³‚ê‚Ä‚¢‚È‚¢)\n"
+
+#: main.c:2577
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <color>\t”wŒiF‚É <color> ‚ðŽg‚¤(“¯‹`: -bg)"
+
+#: main.c:2578
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <color>\t‘OŒiF‚É <color> ‚ðŽg‚¤(“¯‹`: -fg)"
+
+#: main.c:2579 main.c:2599
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <font>\t\tƒeƒLƒXƒg•\\Ž¦‚É <font> ‚ðŽg‚¤(“¯‹`: -fn)"
+
+#: main.c:2580
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <font>\t‘¾Žš‚É <font> ‚ðŽg‚¤"
+
+#: main.c:2581
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <for>\tŽÎ‘ÌŽš‚É <font> ‚ðŽg‚¤"
+
+#: main.c:2582 main.c:2600
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\t‰Šú”z’u‚É <geom> ‚ðŽg‚¤(“¯‹`: -geom)"
+
+#: main.c:2583
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <width>\t‹«ŠE‚Ì•‚ð <width> ‚É‚·‚é(“¯‹`: -bw)"
+
+#: main.c:2584
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr ""
+"-scrollbarwidth <width> ƒXƒNƒ[ƒ‹ƒo[‚Ì•‚ð <width> ‚É‚·‚é(“¯‹`: -sw)"
+
+#: main.c:2586
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <height>\tƒƒjƒ…[ƒo[‚Ì‚‚³‚ð <height> ‚É‚·‚é(“¯‹`: -mh)"
+
+#: main.c:2588 main.c:2601
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\t”½“]‰f‘œ‚ðŽg—p‚·‚é(“¯‹`: -rv)"
+
+#: main.c:2589
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\t”½“]‰f‘œ‚ðŽg—p‚µ‚È‚¢(“¯‹`: +rv)"
+
+#: main.c:2590
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\t“Á’è‚̃Šƒ\\[ƒX‚ðŽg—p‚·‚é"
+
+#: main.c:2593
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"gvim‚É‚æ‚Á‚ĉðŽß‚³‚ê‚éˆø”(RISC OSƒo[ƒWƒ‡ƒ“):\n"
+
+#: main.c:2594
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <number>\t‰Šú‚̃EƒBƒ“ƒhƒE‚̃Rƒ‰ƒ€’PˆÊ‚Ì•"
+
+#: main.c:2595
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <number>\t‰Šú‚̃EƒBƒ“ƒhƒE‚Ìs’PˆÊ‚Ì‚‚³"
+
+#: main.c:2598
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"gvim‚É‚æ‚Á‚ĉðŽß‚³‚ê‚éˆø”(GTK+ƒo[ƒWƒ‡ƒ“):\n"
+
+#: main.c:2602
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\t<display> ‚Åvim‚ðŽÀs‚·‚é(“¯‹`: --display)"
+
+#: main.c:2604
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr "--role <role>\tƒƒCƒ“ƒEƒBƒ“ƒhƒE‚ðŽ¯•Ê‚·‚éˆêˆÓ‚È–ðŠ„(role)‚ðÝ’è‚·‚é"
+
+#: main.c:2606
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tˆÙ‚È‚éGTK widget‚ÅVim‚ðŠJ‚­"
+
+#: main.c:2609
+msgid "-P <parent title>\tOpen Vim inside parent application"
+msgstr "-P <e‚̃^ƒCƒgƒ‹>\tVim‚ðeƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚Ì’†‚Å‹N“®‚·‚é"
+
+# msgid "--help\t\tShow Gnome arguments"
+# msgstr "--help\t\tGNOME‚̈ø”‚ðŒ©‚¹‚é"
+#: main.c:2847
+msgid "No display"
+msgstr "ƒfƒBƒXƒvƒŒƒC‚ªŒ©‚‚©‚è‚Ü‚¹‚ñ"
+
+#. Failed to send, abort.
+#: main.c:2862
+msgid ": Send failed.\n"
+msgstr ": ‘—M‚ÉŽ¸”s‚µ‚Ü‚µ‚½.\n"
+
+#. Let vim start normally.
+#: main.c:2868
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": ‘—M‚ÉŽ¸”s‚µ‚Ü‚µ‚½. ƒ[ƒJƒ‹‚Å‚ÌŽÀs‚ðŽŽ‚Ý‚Ä‚¢‚Ü‚·\n"
+
+#: main.c:2906 main.c:2927
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d ŒÂ (%d ŒÂ’†) ‚̃tƒ@ƒCƒ‹‚ð•ÒW‚µ‚Ü‚µ‚½"
+
+#: main.c:2949
+msgid "No display: Send expression failed.\n"
+msgstr "ƒfƒBƒXƒvƒŒƒC‚ª‚ ‚è‚Ü‚¹‚ñ: Ž®‚Ì‘—M‚ÉŽ¸”s‚µ‚Ü‚µ‚½.\n"
+
+#: main.c:2961
+msgid ": Send expression failed.\n"
+msgstr ": Ž®‚Ì‘—M‚ÉŽ¸”s‚µ‚Ü‚µ‚½.\n"
+
+#: mark.c:709
+msgid "No marks set"
+msgstr "ƒ}[ƒN‚ªÝ’肳‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: mark.c:711
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: \"%s\" ‚ÉŠY“–‚·‚éƒ}[ƒN‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#. Highlight title
+#: mark.c:722
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"mark s —ñ ƒtƒ@ƒCƒ‹/ƒeƒLƒXƒg"
+
+#. Highlight title
+#: mark.c:760
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" jump s —ñ ƒtƒ@ƒCƒ‹/ƒeƒLƒXƒg"
+
+#. Highlight title
+#: mark.c:805
+msgid ""
+"\n"
+"change line col text"
+msgstr ""
+"\n"
+"•ÏX s —ñ ƒeƒLƒXƒg"
+
+#: mark.c:1281
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# ƒtƒ@ƒCƒ‹ƒ}[ƒN:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1316
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# ƒWƒƒƒ“ƒvƒŠƒXƒg (V‚µ‚¢‚à‚Ì‚ªæ):\n"
+
+#: mark.c:1412
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# ƒtƒ@ƒCƒ‹“àƒ}[ƒN‚Ì—š—ð (V‚µ‚¢‚à‚Ì‚©‚çŒÃ‚¢‚à‚Ì):\n"
+
+#: mark.c:1501
+msgid "Missing '>'"
+msgstr "'>' ‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: mbyte.c:467
+msgid "E543: Not a valid codepage"
+msgstr "E543: –³Œø‚ȃR[ƒhƒy[ƒW‚Å‚·"
+
+#: mbyte.c:4431
+msgid "E284: Cannot set IC values"
+msgstr "E284: IC‚Ì’l‚ðÝ’è‚Å‚«‚Ü‚¹‚ñ"
+
+#: mbyte.c:4583
+msgid "E285: Failed to create input context"
+msgstr "E285: ƒCƒ“ƒvƒbƒgƒRƒ“ƒeƒLƒXƒg‚Ì쬂Ɏ¸”s‚µ‚Ü‚µ‚½"
+
+#: mbyte.c:4741
+msgid "E286: Failed to open input method"
+msgstr "E286: ƒCƒ“ƒvƒbƒgƒƒ\\ƒbƒh‚̃I[ƒvƒ“‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: mbyte.c:4752
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: Œx: IM‚Ì”j‰óƒR[ƒ‹ƒoƒbƒN‚ðÝ’è‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: mbyte.c:4758
+msgid "E288: input method doesn't support any style"
+msgstr "E288: ƒCƒ“ƒvƒbƒgƒƒ\\ƒbƒh‚Í‚Ç‚ñ‚ȃXƒ^ƒCƒ‹‚àƒTƒ|[ƒg‚µ‚Ü‚¹‚ñ"
+
+#: mbyte.c:4815
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: ƒCƒ“ƒvƒbƒgƒƒ\\ƒbƒh‚Í my preedit type ‚ðƒTƒ|[ƒg‚µ‚Ü‚¹‚ñ"
+
+#: mbyte.c:4889
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: over-the-spot ƒXƒ^ƒCƒ‹‚É‚Ífontset‚ª•K—v‚Å‚·"
+
+#: mbyte.c:4925
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: GTK+‚ª1.2.3‚æ‚è‚àŒÃ‚¢‚̂ŃXƒe[ƒ^ƒXƒGƒŠƒA‚ª–³Œø‚Å‚·"
+
+#: mbyte.c:5232
+msgid "E292: Input Method Server is not running"
+msgstr "E292: ƒCƒ“ƒvƒbƒgƒƒ\\ƒbƒhƒT[ƒo ‚ª“®ì‚µ‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: ƒuƒƒbƒN‚ªƒƒbƒN‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: memfile.c:1005
+msgid "E294: Seek error in swap file read"
+msgstr "E294: ƒXƒƒbƒvƒtƒ@ƒCƒ‹“ÇžŽž‚ɃV[ƒNƒGƒ‰[‚Å‚·"
+
+#: memfile.c:1010
+msgid "E295: Read error in swap file"
+msgstr "E295: ƒXƒƒbƒvƒtƒ@ƒCƒ‹‚Ì“Çž‚݃Gƒ‰[‚Å‚·"
+
+#: memfile.c:1062
+msgid "E296: Seek error in swap file write"
+msgstr "E296: ƒXƒƒbƒvƒtƒ@ƒCƒ‹‘ž‚ÝŽž‚ɃV[ƒNƒGƒ‰[‚Å‚·"
+
+#: memfile.c:1080
+msgid "E297: Write error in swap file"
+msgstr "E297: ƒXƒƒbƒvƒtƒ@ƒCƒ‹‚Ì‘ž‚݃Gƒ‰[‚Å‚·"
+
+#: memfile.c:1277
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: ƒXƒƒbƒvƒtƒ@ƒCƒ‹‚ªŠù‚É‘¶Ý‚µ‚Ü‚· (symlink‚É‚æ‚éUŒ‚?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: ƒuƒƒbƒN 0 ‚ðŽæ“¾‚Å‚«‚Ü‚¹‚ñ?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: ƒuƒƒbƒN 1 ‚ðŽæ“¾‚Å‚«‚Ü‚¹‚ñ?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: ƒuƒƒbƒN 2 ‚ðŽæ“¾‚Å‚«‚Ü‚¹‚ñ?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: ‚¨‚Á‚Æ, ƒXƒƒbƒvƒtƒ@ƒCƒ‹‚ªŽ¸‚í‚ê‚Ü‚µ‚½!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: ƒXƒƒbƒvƒtƒ@ƒCƒ‹‚Ì–¼‘O‚ð•Ï‚¦‚ç‚ê‚Ü‚¹‚ñ"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: \"%s\" ‚̃Xƒƒbƒvƒtƒ@ƒCƒ‹‚ðŠJ‚¯‚È‚¢‚̂ŃŠƒJƒoƒŠ‚Í•s‰Â”\\‚Å‚·"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: ƒuƒƒbƒN 0 ‚ðŽæ“¾‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: %s ‚ɂ̓Xƒƒbƒvƒtƒ@ƒCƒ‹‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "Žg—p‚·‚éƒXƒƒbƒvƒtƒ@ƒCƒ‹‚̔Ԇ‚ð“ü—Í‚µ‚Ä‚­‚¾‚³‚¢(0 ‚ÅI—¹): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: %s ‚ðŠJ‚¯‚Ü‚¹‚ñ"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "ƒuƒƒbƒN 0 ‚ð“Çž‚ß‚Ü‚¹‚ñ "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"‹°‚ç‚­•ÏX‚ª‚³‚ê‚Ä‚¢‚È‚¢‚©Vim‚ªƒXƒƒbƒvƒtƒ@ƒCƒ‹‚ðXV‚µ‚Ä‚¢‚Ü‚¹‚ñ."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " Vim‚Ì‚±‚̃o[ƒWƒ‡ƒ“‚Å‚ÍŽg—p‚Å‚«‚Ü‚¹‚ñ.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Vim‚̃o[ƒWƒ‡ƒ“3.0‚ðŽg—p‚µ‚Ä‚­‚¾‚³‚¢.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s ‚ÍVim‚̃Xƒƒbƒvƒtƒ@ƒCƒ‹‚Å‚Í‚È‚¢‚悤‚Å‚·"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " ‚±‚̃Rƒ“ƒsƒ…[ƒ^‚Å‚ÍŽg—p‚Å‚«‚Ü‚¹‚ñ.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "‚±‚̃tƒ@ƒCƒ‹‚ÍŽŸ‚ÌꊂÅì‚ç‚ê‚Ü‚µ‚½ "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"‚à‚µ‚­‚̓tƒ@ƒCƒ‹‚ª‘¹‚µ‚Ä‚¢‚Ü‚·."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "ƒXƒƒbƒvƒtƒ@ƒCƒ‹ \"%s\" ‚ðŽg—p’†"
+
+#: memline.c:909
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Œ´–{ƒtƒ@ƒCƒ‹ \"%s\""
+
+#: memline.c:922
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Œx: Œ´–{ƒtƒ@ƒCƒ‹‚ª•ÏX‚³‚ê‚Ä‚¢‚Ü‚·"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: %s ‚©‚çƒuƒƒbƒN 1 ‚ð“Çž‚ß‚Ü‚¹‚ñ"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???‘½‚­‚Ìs‚ªŽ¸‚í‚ê‚Ä‚¢‚Ü‚·"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???s”‚ªŠÔˆá‚Á‚Ä‚¢‚Ü‚·"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???ƒuƒƒbƒN‚ª‹ó‚Å‚·"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???s‚ªŽ¸‚í‚ê‚Ä‚¢‚Ü‚·"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ƒuƒƒbƒN 1 ‚ÌID‚ªŠÔˆá‚Á‚Ä‚¢‚Ü‚·(%s ‚ª.swpƒtƒ@ƒCƒ‹‚Å‚È‚¢?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???ƒuƒƒbƒN‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? ‚±‚±‚©‚ç???END‚Ü‚Å‚Ìs‚ª”j‰ó‚³‚ê‚Ä‚¢‚é‚悤‚Å‚·"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? ‚±‚±‚©‚ç??END‚Ü‚Å‚Ìs‚ª‘}“ü‚©íœ‚³‚ꂽ‚悤‚Å‚·"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???END"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: ƒŠƒJƒoƒŠ‚ªŠ„ž‚Ü‚ê‚Ü‚µ‚½"
+
+#: memline.c:1148
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr ""
+"E312: ƒŠƒJƒoƒŠ‚ÌÅ’†‚ɃGƒ‰[‚ªŒŸo‚³‚ê‚Ü‚µ‚½; ???‚ÅŽn‚Ü‚és‚ðŽQÆ‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: memline.c:1150
+msgid "See \":help E312\" for more information."
+msgstr "Ú×‚Í \":help E312\" ‚ðŽQÆ‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: memline.c:1155
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "ƒŠƒJƒoƒŠ‚ªI—¹‚µ‚Ü‚µ‚½. ‘S‚Ä‚ª³‚µ‚¢‚©ƒ`ƒFƒbƒN‚µ‚Ä‚­‚¾‚³‚¢."
+
+#: memline.c:1156
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(•ÏX‚ðƒ`ƒFƒbƒN‚·‚邽‚ß‚É, ‚±‚̃tƒ@ƒCƒ‹‚ð•Ê‚Ì–¼‘O‚Å•Û‘¶‚µ‚½ã‚Å\n"
+
+#: memline.c:1157
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "Œ´–{ƒtƒ@ƒCƒ‹‚Æ‚Ì diff ‚ðŽÀs‚·‚é‚Æ—Ç‚¢‚Å‚µ‚傤)\n"
+
+#: memline.c:1158
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"‚»‚ê‚©‚ç.swpƒtƒ@ƒCƒ‹‚ð휂µ‚Ä‚­‚¾‚³‚¢\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1214
+msgid "Swap files found:"
+msgstr "ƒXƒƒbƒvƒtƒ@ƒCƒ‹‚ª•¡”Œ©‚‚©‚è‚Ü‚µ‚½:"
+
+#: memline.c:1392
+msgid " In current directory:\n"
+msgstr " Œ»Ý‚̃fƒBƒŒƒNƒgƒŠ:\n"
+
+#: memline.c:1394
+msgid " Using specified name:\n"
+msgstr " ‚ ‚é–¼‘O‚ðŽg—p’†:\n"
+
+#: memline.c:1398
+msgid " In directory "
+msgstr " ƒfƒBƒŒƒNƒgƒŠ "
+
+#: memline.c:1416
+msgid " -- none --\n"
+msgstr " -- ‚È‚µ --\n"
+
+#: memline.c:1488
+msgid " owned by: "
+msgstr " Š—LŽÒ: "
+
+#: memline.c:1490
+msgid " dated: "
+msgstr " “ú•t: "
+
+#: memline.c:1494 memline.c:3684
+msgid " dated: "
+msgstr " “ú•t: "
+
+#: memline.c:1510
+msgid " [from Vim version 3.0]"
+msgstr " [from Vim version 3.0]"
+
+#: memline.c:1514
+msgid " [does not look like a Vim swap file]"
+msgstr " [Vim‚̃Xƒƒbƒvƒtƒ@ƒCƒ‹‚Å‚Í‚È‚¢‚悤‚Å‚·]"
+
+#: memline.c:1518
+msgid " file name: "
+msgstr " ƒtƒ@ƒCƒ‹–¼: "
+
+#: memline.c:1524
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" •ÏXó‘Ô: "
+
+#: memline.c:1525
+msgid "YES"
+msgstr "‚ ‚è"
+
+#: memline.c:1525
+msgid "no"
+msgstr "‚È‚µ"
+
+#: memline.c:1529
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" ƒ†[ƒU–¼: "
+
+#: memline.c:1536
+msgid " host name: "
+msgstr " ƒzƒXƒg–¼: "
+
+#: memline.c:1538
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" ƒzƒXƒg–¼: "
+
+#: memline.c:1544
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ƒvƒƒZƒXID: "
+
+#: memline.c:1550
+msgid " (still running)"
+msgstr " (‚Ü‚¾ŽÀs’†)"
+
+#: memline.c:1562
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [‚±‚ÌVimƒo[ƒWƒ‡ƒ“‚Å‚ÍŽg—p‚Å‚«‚Ü‚¹‚ñ]"
+
+#: memline.c:1565
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [‚±‚̃Rƒ“ƒsƒ…[ƒ^‚Å‚ÍŽg—p‚Å‚«‚Ü‚¹‚ñ]"
+
+#: memline.c:1570
+msgid " [cannot be read]"
+msgstr " [“Çž‚ß‚Ü‚¹‚ñ]"
+
+#: memline.c:1574
+msgid " [cannot be opened]"
+msgstr " [ŠJ‚¯‚Ü‚¹‚ñ]"
+
+#: memline.c:1764
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: ƒXƒƒbƒvƒtƒ@ƒCƒ‹‚ª–³‚¢‚̂ňێ‚Å‚«‚Ü‚¹‚ñ"
+
+#: memline.c:1817
+msgid "File preserved"
+msgstr "ƒtƒ@ƒCƒ‹‚ªˆÛŽ‚³‚ê‚Ü‚·"
+
+#: memline.c:1819
+msgid "E314: Preserve failed"
+msgstr "E314: ˆÛŽ‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: memline.c:1890
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: –³Œø‚Èlnum‚Å‚·: %ld"
+
+#: memline.c:1916
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: s %ld ‚ð‚݂‚¯‚ç‚ê‚Ü‚¹‚ñ"
+
+#: memline.c:2306
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: ƒ|ƒCƒ“ƒ^ƒuƒƒbƒN‚ÌID‚ªŠÔˆá‚Á‚Ä‚¢‚Ü‚· 3"
+
+#: memline.c:2386
+msgid "stack_idx should be 0"
+msgstr "stack_idx ‚Í 0 ‚Å‚ ‚é‚ׂ«‚Å‚·"
+
+#: memline.c:2448
+msgid "E318: Updated too many blocks?"
+msgstr "E318: XV‚³‚ꂽƒuƒƒbƒN‚ª‘½‚·‚¬‚é‚©‚à?"
+
+#: memline.c:2630
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: ƒ|ƒCƒ“ƒ^ƒuƒƒbƒN‚ÌID‚ªŠÔˆá‚Á‚Ä‚¢‚Ü‚· 4"
+
+#: memline.c:2657
+msgid "deleted block 1?"
+msgstr "ƒuƒƒbƒN 1 ‚ÍÁ‚³‚ꂽ?"
+
+#: memline.c:2857
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: s %ld ‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: memline.c:3100
+msgid "E317: pointer block id wrong"
+msgstr "E317: ƒ|ƒCƒ“ƒ^ƒuƒƒbƒN‚ÌID‚ªŠÔˆá‚Á‚Ä‚¢‚Ü‚·"
+
+#: memline.c:3116
+msgid "pe_line_count is zero"
+msgstr "pe_line_count ‚ªƒ[ƒ‚Å‚·"
+
+#: memline.c:3145
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: s”Ô†‚ª”͈͊O‚Å‚·: %ld ’´‚¦‚Ä‚¢‚Ü‚·"
+
+#: memline.c:3149
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: ƒuƒƒbƒN %ld ‚ÌsƒJƒEƒ“ƒg‚ªŠÔˆá‚Á‚Ä‚¢‚Ü‚·"
+
+#: memline.c:3198
+msgid "Stack size increases"
+msgstr "ƒXƒ^ƒbƒNƒTƒCƒY‚ª‘‚¦‚Ü‚·"
+
+#: memline.c:3244
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: ƒ|ƒCƒ“ƒ^ƒuƒƒbƒN‚ÌID‚ªŠÔˆá‚Á‚Ä‚¢‚Ü‚· 2"
+
+#: memline.c:3674
+msgid "E325: ATTENTION"
+msgstr "E325: ’ˆÓ"
+
+#: memline.c:3675
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"ŽŸ‚Ì–¼‘O‚ŃXƒƒbƒvƒtƒ@ƒCƒ‹‚ðŒ©‚Â‚¯‚Ü‚µ‚½ \""
+
+#: memline.c:3679
+msgid "While opening file \""
+msgstr "ŽŸ‚̃tƒ@ƒCƒ‹‚ðŠJ‚¢‚Ä‚¢‚éÅ’† \""
+
+#: memline.c:3688
+msgid " NEWER than swap file!\n"
+msgstr " ƒXƒƒbƒvƒtƒ@ƒCƒ‹‚æ‚è‚àV‚µ‚¢‚Å‚·!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3692
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) •Ê‚̃vƒƒOƒ‰ƒ€‚ª“¯‚¶ƒtƒ@ƒCƒ‹‚ð•ÒW‚µ‚Ä‚¢‚é‚©‚à‚µ‚ê‚Ü‚¹‚ñ.\n"
+" ‚±‚ÌꇂɂÍ, •ÏX‚ð‚µ‚½Û‚ÉÅI“I‚É, “¯‚¶ƒtƒ@ƒCƒ‹‚̈قȂé\n"
+" 2‚‚̃Cƒ“ƒXƒ^ƒ“ƒX‚ª‚Å‚«‚Ä‚µ‚Ü‚¤‚±‚Æ‚É’ˆÓ‚µ‚Ä‚­‚¾‚³‚¢.\n"
+
+#: memline.c:3693
+msgid " Quit, or continue with caution.\n"
+msgstr " I—¹‚·‚é‚©, ’ˆÓ‚µ‚È‚ª‚瑱‚¯‚Ü‚·.\n"
+
+#: memline.c:3694
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) ‚±‚̃tƒ@ƒCƒ‹‚Ì•ÒWƒZƒbƒVƒ‡ƒ“‚ªƒNƒ‰ƒbƒVƒ…‚µ‚½.\n"
+
+#: memline.c:3695
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " ‚±‚Ìê‡‚É‚Í \":recover\" ‚© \"vim -r "
+
+#: memline.c:3697
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" ‚ðŽg—p‚µ‚Ä•ÏX‚ðƒŠƒJƒo[‚µ‚Ü‚·(\":help recover\" ‚ðŽQÆ).\n"
+
+#: memline.c:3698
+msgid " If you did this already, delete the swap file \""
+msgstr " Šù‚É‚±‚ê‚ðs‚È‚Á‚½‚Ì‚È‚ç‚Î, ƒXƒƒbƒvƒtƒ@ƒCƒ‹ \""
+
+#: memline.c:3700
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" ‚ðÁ‚¹‚΂±‚̃ƒbƒZ[ƒW‚ð‰ñ”ð‚Å‚«‚Ü‚·.\n"
+
+#: memline.c:3714 memline.c:3718
+msgid "Swap file \""
+msgstr "ƒXƒƒbƒvƒtƒ@ƒCƒ‹ \""
+
+#: memline.c:3715 memline.c:3721
+msgid "\" already exists!"
+msgstr "\" ‚ªŠù‚É‚ ‚è‚Ü‚·!"
+
+#: memline.c:3724
+msgid "VIM - ATTENTION"
+msgstr "VIM - ’ˆÓ"
+
+#: memline.c:3726
+msgid "Swap file already exists!"
+msgstr "ƒXƒƒbƒvƒtƒ@ƒCƒ‹‚ªŠù‚É‘¶Ý‚µ‚Ü‚·!"
+
+#: memline.c:3730
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort"
+msgstr ""
+"“Çžê—p‚ÅŠJ‚­(&O)\n"
+"‚Æ‚É‚©‚­•ÒW‚·‚é(&E)\n"
+"•œŠˆ‚³‚¹‚é(&R)ecover\n"
+"I—¹‚·‚é(&Q)\n"
+"’†Ž~‚·‚é(&A)"
+
+#: memline.c:3732
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort\n"
+"&Delete it"
+msgstr ""
+"“Çžê—p‚ÅŠJ‚­(&O)\n"
+"‚Æ‚É‚©‚­•ÒW‚·‚é(&E)\n"
+"•œŠˆ‚³‚¹‚é(&R)ecover\n"
+"I—¹‚·‚é(&Q)\n"
+"’†Ž~‚·‚é(&A)\n"
+"Á‹Ž‚·‚é(&D)"
+
+#: memline.c:3789
+msgid "E326: Too many swap files found"
+msgstr "E326: ƒXƒƒbƒvƒtƒ@ƒCƒ‹‚ª‘½”Œ©‚‚©‚è‚Ü‚µ‚½"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: ƒƒjƒ…[ƒAƒCƒeƒ€‚̃pƒX‚Ì•”•ª‚ªƒTƒuƒƒjƒ…[‚Å‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: ƒƒjƒ…[‚Í‘¼‚̃‚[ƒh‚É‚¾‚¯‚ ‚è‚Ü‚·"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: ‚»‚Ì–¼‘O‚̃ƒjƒ…[‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: menu.c:525
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: ƒƒjƒ…[ƒpƒX‚̓Tƒuƒƒjƒ…[‚𶂶‚é‚ׂ«‚Å‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: menu.c:564
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: ƒƒjƒ…[ƒo[‚É‚Í’¼Úƒƒjƒ…[ƒAƒCƒeƒ€‚ð’ljÁ‚Å‚«‚Ü‚¹‚ñ"
+
+#: menu.c:570
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: ‹æØ‚è‚̓ƒjƒ…[ƒpƒX‚̈ꕔ‚Å‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1097
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- ƒƒjƒ…[ ---"
+
+#: menu.c:2019
+msgid "Tear off this menu"
+msgstr "‚±‚̃ƒjƒ…[‚ðØ‚èŽæ‚é"
+
+#: menu.c:2084
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: ƒƒjƒ…[ƒpƒX‚̓ƒjƒ…[ƒAƒCƒeƒ€‚𶂶‚È‚¯‚ê‚΂¢‚¯‚Ü‚¹‚ñ"
+
+#: menu.c:2104
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: ƒƒjƒ…[‚ª‚݂‚©‚è‚Ü‚¹‚ñ: %s"
+
+#: menu.c:2173
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: %s ‚ɂ̓ƒjƒ…[‚ª’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: menu.c:2211
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: ƒƒjƒ…[ƒpƒX‚̓Tƒuƒƒjƒ…[‚𶂶‚È‚¯‚ê‚΂¢‚¯‚Ü‚¹‚ñ"
+
+#: menu.c:2232
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: ƒƒjƒ…[‚ª‚݂‚©‚è‚Ü‚¹‚ñ - ƒƒjƒ…[–¼‚ðŠm”F‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: message.c:414
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "%s ‚̈—’†‚ɃGƒ‰[‚ªŒŸo‚³‚ê‚Ü‚µ‚½:"
+
+#: message.c:440
+#, c-format
+msgid "line %4ld:"
+msgstr "s %4ld:"
+
+#: message.c:647
+msgid "[string too long]"
+msgstr "[•¶Žš—ñ‚ª’·‚·‚¬‚Ü‚·]"
+
+#: message.c:797
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "“ú–{ŒêƒƒbƒZ[ƒW–|–ó/ŠÄC: ‘º‰ª ‘¾˜Y <koron@tka.att.ne.jp>"
+
+#: message.c:1025
+msgid "Interrupt: "
+msgstr "Š„ž‚Ý: "
+
+#: message.c:1028
+msgid "Hit ENTER to continue"
+msgstr "‘±‚¯‚é‚É‚ÍENTER‚ð‰Ÿ‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: message.c:1030
+msgid "Hit ENTER or type command to continue"
+msgstr "‘±‚¯‚é‚É‚ÍENTER‚ð‰Ÿ‚·‚©ƒRƒ}ƒ“ƒh‚ð“ü—Í‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: message.c:2351
+msgid "-- More --"
+msgstr "-- Œp‘± --"
+
+#: message.c:2354
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: s‘—‚è, SPACE/b: ƒy[ƒW‘—‚è, d/u: ”¼ƒy[ƒW‘—‚è, q: I—¹)"
+
+#: message.c:2355
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: s‘—‚è, SPACE: ƒy[ƒW‘—‚è, d: ”¼ƒy[ƒW‘—‚è, q: I—¹)"
+
+#: message.c:2976 message.c:2991
+msgid "Question"
+msgstr "Ž¿–â"
+
+#: message.c:2978
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"‚Í‚¢(&Y)\n"
+"‚¢‚¢‚¦(&N)"
+
+#: message.c:3011
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"‚Í‚¢(&Y)\n"
+"‚¢‚¢‚¦(&N)\n"
+"‘S‚Ä•Û‘¶(&A)\n"
+"‘S‚Ä•úŠü(&D)\n"
+"ƒLƒƒƒ“ƒZƒ‹(&C)"
+
+#: message.c:3052
+msgid "Save File dialog"
+msgstr "ƒtƒ@ƒCƒ‹•Û‘¶ƒ_ƒCƒAƒƒO"
+
+#: message.c:3054
+msgid "Open File dialog"
+msgstr "ƒtƒ@ƒCƒ‹“Çžƒ_ƒCƒAƒƒO"
+
+#. TODO: non-GUI file selector here
+#: message.c:3125
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: ƒRƒ“ƒ\\[ƒ‹ƒ‚[ƒh‚ł̓tƒ@ƒCƒ‹ƒuƒ‰ƒEƒU‚ðŽg‚¦‚Ü‚¹‚ñ, ‚²‚ß‚ñ‚È‚³‚¢"
+
+#: misc1.c:2773
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: Œx: “Çžê—pƒtƒ@ƒCƒ‹‚ð•ÏX‚µ‚Ü‚·"
+
+#: misc1.c:3021
+msgid "1 more line"
+msgstr "1 s ’ljÁ‚µ‚Ü‚µ‚½"
+
+#: misc1.c:3023
+msgid "1 line less"
+msgstr "1 s 휂µ‚Ü‚µ‚½"
+
+#: misc1.c:3028
+#, c-format
+msgid "%ld more lines"
+msgstr "%ld s ’ljÁ‚µ‚Ü‚µ‚½"
+
+#: misc1.c:3030
+#, c-format
+msgid "%ld fewer lines"
+msgstr "%ld s 휂µ‚Ü‚µ‚½"
+
+#: misc1.c:3033
+msgid " (Interrupted)"
+msgstr " (Š„ž‚Ü‚ê‚Ü‚µ‚½)"
+
+#: misc1.c:7582
+msgid "Vim: preserving files...\n"
+msgstr "Vim: ƒtƒ@ƒCƒ‹‚ð•Û‘¶’†...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:7592
+msgid "Vim: Finished.\n"
+msgstr "Vim: I—¹‚µ‚Ü‚µ‚½.\n"
+
+#: misc2.c:695 misc2.c:711
+msgid "ERROR: "
+msgstr "ƒGƒ‰[: "
+
+#: misc2.c:715
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[ƒƒ‚ƒŠ(ƒoƒCƒg)] ‘Š„“–-‰ð•ú—Ê %lu-%lu, Žg—p—Ê %lu, ƒs[ƒNŽž %lu\n"
+
+#: misc2.c:717
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[ŒÄo] ‘ re/malloc() ‰ñ” %lu, ‘ free() ‰ñ” %lu\n"
+"\n"
+
+#: misc2.c:772
+msgid "E340: Line is becoming too long"
+msgstr "E340: s‚ª’·‚­‚È‚è‚·‚¬‚Ü‚µ‚½"
+
+#: misc2.c:816
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: “à•”ƒGƒ‰[: lalloc(%ld,)"
+
+#: misc2.c:924
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: ƒƒ‚ƒŠ‚ª‘«‚è‚Ü‚¹‚ñ! (%lu ƒoƒCƒg‚ðŠ„“–—v‹)"
+
+#: misc2.c:2593
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "ŽÀs‚Ì‚½‚߂ɃVƒFƒ‹‚ðŒÄo‚µ’†: \"%s\""
+
+#: misc2.c:2815
+msgid "E545: Missing colon"
+msgstr "E545: ƒRƒƒ“‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: misc2.c:2817 misc2.c:2844
+msgid "E546: Illegal mode"
+msgstr "E546: •s³‚ȃ‚[ƒh‚Å‚·"
+
+#: misc2.c:2883
+msgid "E547: Illegal mouseshape"
+msgstr "E547: •s³‚È 'mouseshape' ‚Å‚·"
+
+#: misc2.c:2923
+msgid "E548: digit expected"
+msgstr "E548: ”’l‚ª•K—v‚Å‚·"
+
+#: misc2.c:2928
+msgid "E549: Illegal percentage"
+msgstr "E549: •s³‚ȃp[ƒZƒ“ƒe[ƒW‚Å‚·"
+
+#: misc2.c:3238
+msgid "Enter encryption key: "
+msgstr "ˆÃ†‰»—p‚̃L[‚ð“ü—Í‚µ‚Ä‚­‚¾‚³‚¢: "
+
+#: misc2.c:3239
+msgid "Enter same key again: "
+msgstr "‚à‚¤ˆê“x“¯‚¶ƒL[‚ð“ü—Í‚µ‚Ä‚­‚¾‚³‚¢: "
+
+#: misc2.c:3249
+msgid "Keys don't match!"
+msgstr "ƒL[‚ªˆê’v‚µ‚Ü‚¹‚ñ"
+
+#: misc2.c:3798
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: –³Œø‚ȃpƒX‚Å‚·: '**[”’l]' ‚Ípath‚ÌŌォ '%s' "
+"‚ª‘±‚¢‚Ä‚È‚¢‚Æ‚¢‚¯‚Ü‚¹‚ñ."
+
+#: misc2.c:5077
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: cdpath‚É‚Í \"%s\" ‚Æ‚¢‚¤ƒtƒ@ƒCƒ‹‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: misc2.c:5080
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: path‚É‚Í \"%s\" ‚Æ‚¢‚¤ƒtƒ@ƒCƒ‹‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: misc2.c:5086
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: cdpath‚É‚Í‚±‚êˆÈã \"%s\" ‚Æ‚¢‚¤ƒtƒ@ƒCƒ‹‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: misc2.c:5089
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: ƒpƒX‚É‚Í‚±‚êˆÈã \"%s\" ‚Æ‚¢‚¤ƒtƒ@ƒCƒ‹‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: misc2.c:5323
+msgid "E550: Missing colon"
+msgstr "E550: ƒRƒƒ“‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: misc2.c:5335
+msgid "E551: Illegal component"
+msgstr "E551: •s³‚È\\•¶—v‘f‚Å‚·"
+
+#: misc2.c:5343
+msgid "E552: digit expected"
+msgstr "E552: ”’l‚ª•K—v‚Å‚·"
+
+#. Get here when the server can't be found.
+#: netbeans.c:396
+msgid "Cannot connect to Netbeans #2"
+msgstr "Netbeans #2 ‚ÉÚ‘±‚Å‚«‚Ü‚¹‚ñ"
+
+#: netbeans.c:404
+msgid "Cannot connect to Netbeans"
+msgstr "Netbeans ‚ÉÚ‘±‚Å‚«‚Ü‚¹‚ñ"
+
+#: netbeans.c:450
+#, c-format
+msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\""
+msgstr ""
+"E668: NetBeans‚ÌÚ‘±î•ñƒtƒ@ƒCƒ‹‚̃AƒNƒZƒXƒ‚[ƒh‚É–â‘肪‚ ‚è‚Ü‚·: \"%s\""
+
+#: netbeans.c:749
+msgid "read from Netbeans socket"
+msgstr "Netbeans ‚̃\\ƒPƒbƒg‚ð“Çž‚Ý"
+
+#: netbeans.c:1638
+#, c-format
+msgid "E658: NetBeans connection lost for buffer %ld"
+msgstr "E658: ƒoƒbƒtƒ@ %ld ‚Ì NetBeans Ú‘±‚ªŽ¸‚í‚ê‚Ü‚µ‚½"
+
+#: normal.c:2980
+msgid "Warning: terminal cannot highlight"
+msgstr "Œx: Žg—p‚µ‚Ä‚¢‚é’[––‚̓nƒCƒ‰ƒCƒg‚Å‚«‚Ü‚¹‚ñ"
+
+#: normal.c:3276
+msgid "E348: No string under cursor"
+msgstr "E348: ƒJ[ƒ\\ƒ‹‚̈ʒu‚É‚Í•¶Žš—ñ‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: normal.c:3278
+msgid "E349: No identifier under cursor"
+msgstr "E349: ƒJ[ƒ\\ƒ‹‚̈ʒu‚É‚ÍŽ¯•ÊŽq‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: normal.c:4519
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: Œ»Ý‚Ì 'foldmethod' ‚Å‚ÍÜô‚Ý‚ðÁ‹Ž‚Å‚«‚Ü‚¹‚ñ"
+
+#: normal.c:6708
+msgid "E664: changelist is empty"
+msgstr "E664: •ÏXƒŠƒXƒg‚ª‹ó‚Å‚·"
+
+#: normal.c:6710
+msgid "E662: At start of changelist"
+msgstr "E662: •ÏXƒŠƒXƒg‚Ì擪"
+
+#: normal.c:6712
+msgid "E663: At end of changelist"
+msgstr "E663: •ÏXƒŠƒXƒg‚Ì––”ö"
+
+#: normal.c:7973
+msgid "Type :quit<Enter> to exit Vim"
+msgstr "Vim‚ðI—¹‚·‚é‚É‚Í :quit<Enter> ‚Æ“ü—Í‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: ops.c:294
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "1 s‚ª %s ‚Å 1 ‰ñˆ—‚³‚ê‚Ü‚µ‚½"
+
+#: ops.c:296
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 s‚ª %s ‚Å %d ‰ñˆ—‚³‚ê‚Ü‚µ‚½"
+
+#: ops.c:301
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld s‚ª %s ‚Å 1 ‰ñˆ—‚³‚ê‚Ü‚µ‚½"
+
+#: ops.c:304
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld s‚ª %s ‚Å %d ‰ñˆ—‚³‚ê‚Ü‚µ‚½"
+
+#: ops.c:662
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld s‚ªƒCƒ“ƒfƒ“ƒg‚³‚ê‚Ü‚·... "
+
+#: ops.c:712
+msgid "1 line indented "
+msgstr "1 s‚ðƒCƒ“ƒfƒ“ƒg‚µ‚Ü‚µ‚½"
+
+#: ops.c:714
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld s‚ðƒCƒ“ƒfƒ“ƒg‚µ‚Ü‚µ‚½"
+
+#. must display the prompt
+#: ops.c:1675
+msgid "cannot yank; delete anyway"
+msgstr "ƒ„ƒ“ƒN‚Å‚«‚Ü‚¹‚ñ; ‚Æ‚É‚©‚­Á‹Ž"
+
+#: ops.c:2185
+msgid "1 line changed"
+msgstr "1 s‚ª•ÏX‚³‚ê‚Ü‚µ‚½"
+
+#: ops.c:2187
+#, c-format
+msgid "%ld lines changed"
+msgstr "%ld s‚ª•ÏX‚³‚ê‚Ü‚µ‚½"
+
+#: ops.c:2571
+#, c-format
+msgid "freeing %ld lines"
+msgstr "%ld s‚ðŠJ•ú’†"
+
+#: ops.c:2852
+msgid "1 line yanked"
+msgstr "1 s‚ªƒ„ƒ“ƒN‚³‚ê‚Ü‚µ‚½"
+
+#: ops.c:2854
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld s‚ªƒ„ƒ“ƒN‚³‚ê‚Ü‚µ‚½"
+
+#: ops.c:3139
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: ƒŒƒWƒXƒ^ %s ‚ɂ͉½‚à‚ ‚è‚Ü‚¹‚ñ"
+
+#. Highlight title
+#: ops.c:3690
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- ƒŒƒWƒXƒ^ ---"
+
+#: ops.c:4997
+msgid "Illegal register name"
+msgstr "•s³‚ȃŒƒWƒXƒ^–¼"
+
+#: ops.c:5085
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# ƒŒƒWƒXƒ^:\n"
+
+#: ops.c:5135
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: –¢’m‚̃ŒƒWƒXƒ^Œ^ %d ‚Å‚·"
+
+#: ops.c:5620
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: –³Œø‚ȃŒƒWƒXƒ^–¼: '%s'"
+
+#: ops.c:5980
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld —ñ; "
+
+#: ops.c:5987
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "‘I‘ð %s%ld / %ld s; %ld / %ld ’PŒê; %ld / %ld •¶Žš"
+
+#: ops.c:6003
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "—ñ %s / %s; s %ld of %ld; ’PŒê %ld / %ld; •¶Žš %ld / %ld"
+
+#: ops.c:6014
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld for BOM)"
+
+#: option.c:1643
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=%N ƒy[ƒW"
+
+#: option.c:2092
+msgid "Thanks for flying Vim"
+msgstr "Vim ‚ðŽg‚Á‚Ä‚­‚ê‚Ä‚ ‚肪‚Æ‚¤"
+
+#: option.c:3419 option.c:3535
+msgid "E518: Unknown option"
+msgstr "E518: –¢’m‚̃IƒvƒVƒ‡ƒ“‚Å‚·"
+
+#: option.c:3432
+msgid "E519: Option not supported"
+msgstr "E519: ƒIƒvƒVƒ‡ƒ“‚̓Tƒ|[ƒg‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: option.c:3457
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: modeline ‚Å‚Í‹–‰Â‚³‚ê‚Ü‚¹‚ñ"
+
+#: option.c:3522
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tLast set from "
+
+#: option.c:3661
+msgid "E521: Number required after ="
+msgstr "E521: = ‚ÌŒã‚É‚Í”Žš‚ª•K—v‚Å‚·"
+
+#: option.c:3989 option.c:4619
+msgid "E522: Not found in termcap"
+msgstr "E522: termcap “à‚ɂ݂‚©‚è‚Ü‚¹‚ñ"
+
+#: option.c:4064
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: •s³‚È•¶Žš‚Å‚· <%s>"
+
+#: option.c:4611
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: 'term' ‚ɂ͋󕶎š—ñ‚ðÝ’è‚Å‚«‚Ü‚¹‚ñ"
+
+#: option.c:4614
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: GUI‚Å‚Í 'term' ‚ð•ÏX‚Å‚«‚Ü‚¹‚ñ"
+
+#: option.c:4616
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: GUI‚ðƒXƒ^[ƒg‚·‚é‚É‚Í \":gui\" ‚ðŽg—p‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: option.c:4645
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: 'backupext' ‚Æ 'patchmode' ‚ª“¯‚¶‚Å‚·"
+
+#: option.c:4860
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: GTK+2 GUI‚Å‚Í•ÏX‚Å‚«‚Ü‚¹‚ñ"
+
+#: option.c:5016
+msgid "E524: Missing colon"
+msgstr "E524: ƒRƒƒ“‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: option.c:5018
+msgid "E525: Zero length string"
+msgstr "E525: •¶Žš—ñ‚Ì’·‚³‚ªƒ[ƒ‚Å‚·"
+
+#: option.c:5086
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: <%s> ‚ÌŒã‚É”Žš‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: option.c:5100
+msgid "E527: Missing comma"
+msgstr "E527: ƒJƒ“ƒ}‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: option.c:5107
+msgid "E528: Must specify a ' value"
+msgstr "E528: ' ‚Ì’l‚ðŽw’肵‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ"
+
+#: option.c:5148
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: •\\Ž¦‚Å‚«‚È‚¢•¶Žš‚©ƒƒCƒh•¶Žš‚ðŠÜ‚ñ‚Å‚¢‚Ü‚·"
+
+#: option.c:5197
+msgid "E596: Invalid font(s)"
+msgstr "E596: –³Œø‚ȃtƒHƒ“ƒg‚Å‚·"
+
+#: option.c:5205
+msgid "E597: can't select fontset"
+msgstr "E597: ƒtƒHƒ“ƒgƒZƒbƒg‚ð‘I‘ð‚Å‚«‚Ü‚¹‚ñ"
+
+#: option.c:5207
+msgid "E598: Invalid fontset"
+msgstr "E598: –³Œø‚ȃtƒHƒ“ƒgƒZƒbƒg‚Å‚·"
+
+#: option.c:5214
+msgid "E533: can't select wide font"
+msgstr "E533: ƒƒCƒhƒtƒHƒ“ƒg‚ð‘I‘ð‚Å‚«‚Ü‚¹‚ñ"
+
+#: option.c:5216
+msgid "E534: Invalid wide font"
+msgstr "E534: –³Œø‚ȃƒCƒhƒtƒHƒ“ƒg‚Å‚·"
+
+#: option.c:5486
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: <%c> ‚ÌŒã‚É•s³‚È•¶Žš‚ª‚ ‚è‚Ü‚·"
+
+#: option.c:5597
+msgid "E536: comma required"
+msgstr "E536: ƒJƒ“ƒ}‚ª•K—v‚Å‚·"
+
+#: option.c:5607
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: 'commentstring' ‚Í‹ó‚Å‚ ‚é‚© %s ‚ðŠÜ‚Þ•K—v‚ª‚ ‚è‚Ü‚·"
+
+#: option.c:5679
+msgid "E538: No mouse support"
+msgstr "E538: ƒ}ƒEƒX‚̓Tƒ|[ƒg‚³‚ê‚Ü‚¹‚ñ"
+
+#: option.c:5947
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: Ž®‚ªI—¹‚µ‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: option.c:5951
+msgid "E541: too many items"
+msgstr "E541: —v‘f‚ª‘½‚·‚¬‚Ü‚·"
+
+#: option.c:5953
+msgid "E542: unbalanced groups"
+msgstr "E542: ƒOƒ‹[ƒv‚ª’Þ‡‚¢‚Ü‚¹‚ñ"
+
+#: option.c:6193
+msgid "E590: A preview window already exists"
+msgstr "E590: ƒvƒŒƒrƒ…[ƒEƒBƒ“ƒhƒE‚ªŠù‚É‘¶Ý‚µ‚Ü‚·"
+
+#: option.c:6450
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr ""
+"W17: ƒAƒ‰ƒrƒA•¶Žš‚É‚ÍUTF-8‚ª•K—v‚È‚Ì‚Å, ':set encoding=utf-8' ‚µ‚Ä‚­‚¾‚³‚¢"
+
+#: option.c:6776
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: Å’á %d ‚Ìs”‚ª•K—v‚Å‚·"
+
+#: option.c:6786
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: Å’á %d ‚̃Jƒ‰ƒ€•‚ª•K—v‚Å‚·"
+
+#: option.c:7093
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: –¢’m‚̃IƒvƒVƒ‡ƒ“‚Å‚·: %s"
+
+#: option.c:7213
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- ’[––ƒR[ƒh ---"
+
+#: option.c:7215
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- ƒOƒ[ƒoƒ‹ƒIƒvƒVƒ‡ƒ“’l ---"
+
+#: option.c:7217
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- ƒ[ƒJƒ‹ƒIƒvƒVƒ‡ƒ“’l ---"
+
+#: option.c:7219
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- ƒIƒvƒVƒ‡ƒ“ ---"
+
+#: option.c:7925
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp ƒGƒ‰["
+
+#: option.c:8896
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': %s ‚ɑΉž‚·‚镶Žš‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: option.c:8930
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': ƒZƒ~ƒRƒƒ“‚ÌŒã‚É—]•ª‚È•¶Žš‚ª‚ ‚è‚Ü‚·: %s"
+
+#: os_amiga.c:280
+msgid "cannot open "
+msgstr "ŠJ‚¯‚Ü‚¹‚ñ "
+
+#: os_amiga.c:314
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: ƒEƒBƒ“ƒhƒE‚ðŠJ‚¯‚Ü‚¹‚ñ!\n"
+
+#: os_amiga.c:338
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Amigados‚̃o[ƒWƒ‡ƒ“ 2.04‚©‚»‚êˆÈ~‚ª•K—v‚Å‚·\n"
+
+#: os_amiga.c:344
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "%s ‚̃o[ƒWƒ‡ƒ“ %ld ‚ª•K—v‚Å‚·\n"
+
+#: os_amiga.c:416
+msgid "Cannot open NIL:\n"
+msgstr "NIL‚ðŠJ‚¯‚Ü‚¹‚ñ:\n"
+
+#: os_amiga.c:427
+msgid "Cannot create "
+msgstr "쬂ł«‚Ü‚¹‚ñ "
+
+#: os_amiga.c:905
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim‚Í %d ‚ÅI—¹‚µ‚Ü‚·\n"
+
+#: os_amiga.c:937
+msgid "cannot change console mode ?!\n"
+msgstr "ƒRƒ“ƒ\\[ƒ‹ƒ‚[ƒh‚ð•ÏX‚Å‚«‚Ü‚¹‚ñ?!\n"
+
+#: os_amiga.c:1003
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: ƒRƒ“ƒ\\[ƒ‹‚Å‚Í‚È‚¢??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1152
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: -f ƒIƒvƒVƒ‡ƒ“‚ŃVƒFƒ‹‚ðŽÀs‚Å‚«‚Ü‚¹‚ñ"
+
+#: os_amiga.c:1193 os_amiga.c:1283
+msgid "Cannot execute "
+msgstr "ŽÀs‚Å‚«‚Ü‚¹‚ñ "
+
+#: os_amiga.c:1196 os_amiga.c:1293
+msgid "shell "
+msgstr "ƒVƒFƒ‹ "
+
+#: os_amiga.c:1216 os_amiga.c:1318
+msgid " returned\n"
+msgstr " –ß‚è‚Ü‚µ‚½\n"
+
+#: os_amiga.c:1459
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE ‚ª¬‚³‚·‚¬‚Ü‚·."
+
+#: os_amiga.c:1463
+msgid "I/O ERROR"
+msgstr "“üo—̓Gƒ‰["
+
+#: os_mswin.c:539
+msgid "...(truncated)"
+msgstr "...(È—ª)"
+
+#: os_mswin.c:641
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' ‚ª80‚Å‚Í‚È‚¢‚½‚ß, ŠO•”ƒRƒ}ƒ“ƒh‚ðŽÀs‚Å‚«‚Ü‚¹‚ñ"
+
+#: os_mswin.c:1973
+msgid "E237: Printer selection failed"
+msgstr "E237: ƒvƒŠƒ“ƒ^‚Ì‘I‘ð‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: os_mswin.c:2013
+#, c-format
+msgid "to %s on %s"
+msgstr "%s ‚Ö (%s ã‚Ì)"
+
+#: os_mswin.c:2028
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: –¢’m‚̃vƒŠƒ“ƒ^ƒIƒvƒVƒ‡ƒ“‚Å‚·: %s"
+
+#: os_mswin.c:2077 os_mswin.c:2087
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: ˆóüƒGƒ‰[: %s"
+
+#: os_mswin.c:2088
+msgid "Unknown"
+msgstr "•s–¾"
+
+#: os_mswin.c:2115
+#, c-format
+msgid "Printing '%s'"
+msgstr "ˆóü‚µ‚Ä‚¢‚Ü‚·: '%s'"
+
+#: os_mswin.c:3204
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: •¶ŽšƒZƒbƒg–¼ \"%s\" ‚Í•s³‚Å‚· (ƒtƒHƒ“ƒg–¼ \"%s\")"
+
+#: os_mswin.c:3212
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: '%c' ‚Í•s³‚È•¶Žš‚Å‚· (ƒtƒHƒ“ƒg–¼ \"%s\")"
+
+#: os_riscos.c:1259
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: –³Œø‚È 'osfiletype' ƒIƒvƒVƒ‡ƒ“ - \"Text\" ‚ðŽg‚¢‚Ü‚·"
+
+#: os_unix.c:927
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: 2d‚̃VƒOƒiƒ‹‚Ì‚½‚ß, I—¹‚µ‚Ü‚·\n"
+
+#: os_unix.c:933
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: ’v–½“IƒVƒOƒiƒ‹ %s ‚ðŒŸ’m‚µ‚Ü‚µ‚½\n"
+
+#: os_unix.c:936
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: ’v–½“IƒVƒOƒiƒ‹‚ðŒŸ’m‚µ‚Ü‚µ‚½\n"
+
+#: os_unix.c:1199
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "XƒT[ƒo‚Ö‚ÌÚ‘±‚É %ld ƒ~ƒŠ•b‚©‚©‚è‚Ü‚µ‚½"
+
+#: os_unix.c:1226
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: X ‚̃Gƒ‰[‚ðŒŸo‚µ‚Ü‚µ‚½r\n"
+
+#: os_unix.c:1334
+msgid "Testing the X display failed"
+msgstr "X display ‚̃`ƒFƒbƒN‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: os_unix.c:1473
+msgid "Opening the X display timed out"
+msgstr "X display ‚Ì open ‚ªƒ^ƒCƒ€ƒAƒEƒg‚µ‚Ü‚µ‚½"
+
+#: os_unix.c:3227 os_unix.c:3907
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"ƒVƒFƒ‹‚ðŽÀs‚Å‚«‚Ü‚¹‚ñ "
+
+#: os_unix.c:3275
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"sh ƒVƒFƒ‹‚ðŽÀs‚Å‚«‚Ü‚¹‚ñ\n"
+
+#: os_unix.c:3279 os_unix.c:3913
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"ƒVƒFƒ‹‚ª’l‚ð•Ô‚µ‚Ü‚µ‚½ "
+
+#: os_unix.c:3414
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"ƒpƒCƒv‚ð쬂ł«‚Ü‚¹‚ñ\n"
+
+#: os_unix.c:3429
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"fork ‚Å‚«‚Ü‚¹‚ñ\n"
+
+#: os_unix.c:3920
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"ƒRƒ}ƒ“ƒh‚ð’†’f‚µ‚Ü‚µ‚½\n"
+
+#: os_unix.c:4184 os_unix.c:4309 os_unix.c:5975
+msgid "XSMP lost ICE connection"
+msgstr "XSMP ‚ªICEÚ‘±‚ðŽ¸‚¢‚Ü‚µ‚½"
+
+#: os_unix.c:5558
+msgid "Opening the X display failed"
+msgstr "X display ‚Ì open ‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: os_unix.c:5880
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP ‚ªsave-yourself—v‹‚ðˆ—‚µ‚Ä‚¢‚Ü‚·"
+
+#: os_unix.c:5999
+msgid "XSMP opening connection"
+msgstr "XSMP ‚ªÚ‘±‚ðŠJŽn‚µ‚Ä‚¢‚Ü‚·"
+
+#: os_unix.c:6018
+msgid "XSMP ICE connection watch failed"
+msgstr "XSMP ICEÚ‘±‚ªŽ¸”s‚µ‚½‚悤‚Å‚·"
+
+#: os_unix.c:6038
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP SmcOpenConnection‚ªŽ¸”s‚µ‚Ü‚µ‚½: %s"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "s"
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "ƒRƒ}ƒ“ƒhƒ‰ƒCƒ“‚Ƀƒ‚ƒŠ‚ðŠ„‚è“–‚Ä‚ç‚ê‚Ü‚¹‚ñ"
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "VIMƒGƒ‰["
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "vim32.dll ‚ðƒ[ƒh‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "DLL‚©‚çŠÖ”ƒ|ƒCƒ“ƒ^‚ðŽæ“¾‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: os_win16.c:342 os_win32.c:3197
+#, c-format
+msgid "shell returned %d"
+msgstr "ƒVƒFƒ‹‚ªƒR[ƒh %d ‚ÅI—¹‚µ‚Ü‚µ‚½"
+
+#: os_win32.c:2655
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: ƒCƒxƒ“ƒg %s ‚ðŒŸ’m\n"
+
+#: os_win32.c:2657
+msgid "close"
+msgstr "•Â‚¶‚é"
+
+#: os_win32.c:2659
+msgid "logoff"
+msgstr "ƒƒOƒIƒt"
+
+#: os_win32.c:2660
+msgid "shutdown"
+msgstr "ƒVƒƒƒbƒgƒ_ƒEƒ“"
+
+#: os_win32.c:3150
+msgid "E371: Command not found"
+msgstr "E371: ƒRƒ}ƒ“ƒh‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: os_win32.c:3163
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE‚ª $PATH ‚Ì’†‚ɂ݂‚©‚è‚Ü‚¹‚ñ.\n"
+"ŠO•”ƒRƒ}ƒ“ƒh‚ÌI—¹Œã‚Ɉꎞ’âŽ~‚ð‚µ‚Ü‚¹‚ñ.\n"
+"Ú×‚Í :help win32-vimrun ‚ðŽQÆ‚µ‚Ä‚­‚¾‚³‚¢."
+
+#: os_win32.c:3166
+msgid "Vim Warning"
+msgstr "Vim‚ÌŒx"
+
+#: quickfix.c:258
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: ƒtƒH[ƒ}ƒbƒg•¶Žš—ñ‚É %%%c ‚ª‘½‚·‚¬‚Ü‚·"
+
+#: quickfix.c:271
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: ƒtƒH[ƒ}ƒbƒg•¶Žš—ñ‚É—\\Šú‚¹‚Ê %%%c ‚ª‚ ‚è‚Ü‚µ‚½"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: ƒtƒH[ƒ}ƒbƒg•¶Žš—ñ‚É ] ‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: quickfix.c:339
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: ƒtƒH[ƒ}ƒbƒg•¶Žš—ñ‚Å‚Í %%%c ‚̓Tƒ|[ƒg‚³‚ê‚Ü‚¹‚ñ"
+
+#: quickfix.c:357
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: ƒtƒH[ƒ}ƒbƒg•¶Žš—ñ‚Ì‘O’u‚É–³Œø‚È %%%c ‚ª‚ ‚è‚Ü‚·"
+
+#: quickfix.c:365
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: ƒtƒH[ƒ}ƒbƒg•¶Žš—ñ‚É–³Œø‚È %%%c ‚ª‚ ‚è‚Ü‚·"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' ‚Ƀpƒ^[ƒ“‚ªŽw’肳‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: quickfix.c:501
+msgid "E379: Missing or empty directory name"
+msgstr "E379: ƒfƒBƒŒƒNƒgƒŠ–¼‚ª–³‚¢‚©‹ó‚Å‚·"
+
+#: quickfix.c:990
+msgid "E553: No more items"
+msgstr "E553: —v‘f‚ª‚à‚¤‚ ‚è‚Ü‚¹‚ñ"
+
+#: quickfix.c:1229
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d of %d)%s%s: "
+
+#: quickfix.c:1231
+msgid " (line deleted)"
+msgstr " (s‚ªíœ‚³‚ê‚Ü‚µ‚½)"
+
+#: quickfix.c:1444
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: quickfix ƒXƒ^ƒbƒN‚Ì––”ö‚Å‚·"
+
+#: quickfix.c:1453
+msgid "E381: At top of quickfix stack"
+msgstr "E381: quickfix ƒXƒ^ƒbƒN‚Ì擪‚Å‚·"
+
+#: quickfix.c:1465
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "ƒGƒ‰[ˆê—— %d of %d; %d ŒÂƒGƒ‰["
+
+#: quickfix.c:1943
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: 'buftype' ƒIƒvƒVƒ‡ƒ“‚ªÝ’肳‚ê‚Ä‚¢‚é‚Ì‚Å‘ž‚Ý‚Ü‚¹‚ñ"
+
+#: regexp.c:838
+msgid "E339: Pattern too long"
+msgstr "E339: ƒpƒ^[ƒ“‚ª’·‚·‚¬‚Ü‚·"
+
+#: regexp.c:1009
+msgid "E50: Too many \\z("
+msgstr "E50: \\z( ‚ª‘½‚·‚¬‚Ü‚·"
+
+#: regexp.c:1020
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: %s( ‚ª‘½‚·‚¬‚Ü‚·"
+
+#: regexp.c:1077
+msgid "E52: Unmatched \\z("
+msgstr "E52: \\z( ‚ª’ނ臂Á‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: regexp.c:1081
+msgid "E53: Unmatched %s%%("
+msgstr "E53: %s%%( ‚ª’ނ臂Á‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: regexp.c:1083
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: %s( ‚ª’ނ臂Á‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: regexp.c:1088
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: %s) ‚ª’ނ臂Á‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: regexp.c:1258
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: %s* ‚ª‹ó•¶Žš—ñ‚É‚È‚é‰Â”\\«‚ª‚ ‚è‚Ü‚·"
+
+#: regexp.c:1261
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: %s+ ‚ª‹ó•¶Žš—ñ‚É‚È‚é‰Â”\\«‚ª‚ ‚è‚Ü‚·"
+
+#: regexp.c:1316
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: %s@ ‚ÌŒã‚É•s³‚È•¶Žš‚ª‚ ‚è‚Ü‚µ‚½"
+
+#: regexp.c:1344
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: %s{ ‚ª‹ó•¶Žš—ñ‚É‚È‚é‰Â”\\«‚ª‚ ‚è‚Ü‚·"
+
+#: regexp.c:1354
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: •¡ŽG‚È %s{...} ‚ª‘½‚·‚¬‚Ü‚·"
+
+#: regexp.c:1370
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61:%s* ‚ª“ü‚êŽq‚É‚È‚Á‚Ä‚¢‚Ü‚·"
+
+#: regexp.c:1373
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62:%s%c ‚ª“ü‚êŽq‚É‚È‚Á‚Ä‚¢‚Ü‚·"
+
+#
+#: regexp.c:1491
+msgid "E63: invalid use of \\_"
+msgstr "E63: \\_ ‚Ì–³Œø‚ÈŽg—p•û–@‚Å‚·"
+
+#: regexp.c:1536
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64:%s%c ‚ÌŒã‚É‚È‚É‚à‚ ‚è‚Ü‚¹‚ñ"
+
+#
+#: regexp.c:1592
+msgid "E65: Illegal back reference"
+msgstr "E65: •s³‚ÈŒã•ûŽQÆ‚Å‚·"
+
+#
+#: regexp.c:1605
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z( ‚̓RƒR‚Å‚Í‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#
+#: regexp.c:1624
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 ‚»‚Ì‘¼‚̓RƒR‚Å‚Í‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#
+#: regexp.c:1635
+msgid "E68: Invalid character after \\z"
+msgstr "E68: \\z ‚ÌŒã‚É•s³‚È•¶Žš‚ª‚ ‚è‚Ü‚µ‚½"
+
+#
+#: regexp.c:1684
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: %s%%[ ‚ÌŒã‚É ] ‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: regexp.c:1700
+msgid "E70: Empty %s%%[]"
+msgstr "E70: %s%%[] ‚ª‹ó‚Å‚·"
+
+#
+#: regexp.c:1760
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: %s%% ‚ÌŒã‚É•s³‚È•¶Žš‚ª‚ ‚è‚Ü‚µ‚½"
+
+#: regexp.c:2557
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: %s{...} “à‚É•¶–@ƒGƒ‰[‚ª‚ ‚è‚Ü‚·"
+
+#: regexp.c:2863 regexp.c:3016
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: ƒNƒ‰ƒbƒVƒ…‚É‚æ‚è’†’f; ³‹K•\\Œ»‚ª•¡ŽG‰ß‚¬‚é‚©‚à?"
+
+#: regexp.c:3004 regexp.c:3013
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: ƒpƒ^[ƒ“‚É‚æ‚éƒXƒ^ƒbƒN•s‘«ƒGƒ‰[‚Å‚·"
+
+#: regexp.c:3258
+msgid "External submatches:\n"
+msgstr "ŠO•”‚Ì•”•ªŠY“–:\n"
+
+#: screen.c:2143
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld s‚ªÜô‚Ü‚ê‚Ü‚µ‚½"
+
+#: screen.c:7959
+msgid " VREPLACE"
+msgstr " ‰¼‘z’uŠ·"
+
+#: screen.c:7963
+msgid " REPLACE"
+msgstr " ’uŠ·"
+
+#: screen.c:7968
+msgid " REVERSE"
+msgstr " ”½“]"
+
+#: screen.c:7970
+msgid " INSERT"
+msgstr " ‘}“ü"
+
+#: screen.c:7973
+msgid " (insert)"
+msgstr " (‘}“ü)"
+
+#: screen.c:7975
+msgid " (replace)"
+msgstr " (’uŠ·)"
+
+#: screen.c:7977
+msgid " (vreplace)"
+msgstr " (‰¼‘z’uŠ·)"
+
+#: screen.c:7980
+msgid " Hebrew"
+msgstr " ƒwƒuƒ‰ƒC"
+
+#: screen.c:7991
+msgid " Arabic"
+msgstr " ƒAƒ‰ƒrƒA"
+
+#: screen.c:7994
+msgid " (lang)"
+msgstr " (Œ¾Œê)"
+
+#: screen.c:7998
+msgid " (paste)"
+msgstr " (“\\‚è•t‚¯)"
+
+#: screen.c:8011
+msgid " VISUAL"
+msgstr " ƒrƒWƒ…ƒAƒ‹"
+
+#: screen.c:8012
+msgid " VISUAL LINE"
+msgstr " ƒrƒWƒ…ƒAƒ‹ s"
+
+#: screen.c:8013
+msgid " VISUAL BLOCK"
+msgstr " ƒrƒWƒ…ƒAƒ‹ ‹éŒ`"
+
+#: screen.c:8014
+msgid " SELECT"
+msgstr " ƒZƒŒƒNƒg"
+
+#: screen.c:8015
+msgid " SELECT LINE"
+msgstr " sŽwŒü‘I‘ð"
+
+#: screen.c:8016
+msgid " SELECT BLOCK"
+msgstr " ‹éŒ`‘I‘ð"
+
+# msgid " BLOCK"
+# msgstr " ƒuƒƒbƒN"
+# msgid " LINE"
+# msgstr " s"
+#: screen.c:8031 screen.c:8094
+msgid "recording"
+msgstr "‹L˜^’†"
+
+#: search.c:37
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "ã‚Ü‚ÅŒŸõ‚µ‚½‚̂ʼnº‚É–ß‚è‚Ü‚·"
+
+#: search.c:38
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "‰º‚Ü‚ÅŒŸõ‚µ‚½‚Ì‚Åã‚É–ß‚è‚Ü‚·"
+
+#: search.c:526
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: –³Œø‚ÈŒŸõ•¶Žš—ñ‚Å‚·: %s"
+
+#: search.c:853
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: ã‚Ü‚ÅŒŸõ‚µ‚½‚¯‚ê‚ÇŠY“–‰ÓŠ‚Í‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: search.c:856
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: ‰º‚Ü‚ÅŒŸõ‚µ‚½‚¯‚ê‚ÇŠY“–‰ÓŠ‚Í‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: search.c:1249
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: ';' ‚Ì‚ ‚Æ‚É‚Í '?' ‚© '/' ‚ªŠú‘Ò‚³‚ê‚Ä‚¢‚é"
+
+#: search.c:3758
+msgid " (includes previously listed match)"
+msgstr " (‘O‚É—ñ‹“‚µ‚½ŠY“–‰ÓŠ‚ðŠÜ‚Þ)"
+
+#. cursor at status line
+#: search.c:3778
+msgid "--- Included files "
+msgstr "--- ƒCƒ“ƒNƒ‹[ƒh‚³‚ꂽƒtƒ@ƒCƒ‹"
+
+#: search.c:3780
+msgid "not found "
+msgstr "‚݂‚©‚è‚Ü‚¹‚ñ "
+
+#: search.c:3781
+msgid "in path ---\n"
+msgstr "ƒpƒX‚É ----\n"
+
+#: search.c:3820
+msgid " (Already listed)"
+msgstr " (Šù‚É—ñ‹“)"
+
+#: search.c:3822
+msgid " NOT FOUND"
+msgstr " ‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: search.c:3874
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "ƒCƒ“ƒNƒ‹[ƒh‚³‚ꂽƒtƒ@ƒCƒ‹‚ðƒXƒLƒƒƒ“’†: %s"
+
+#: search.c:4092
+msgid "E387: Match is on current line"
+msgstr "E387: Œ»Ýs‚ÉŠY“–‚ª‚ ‚è‚Ü‚·"
+
+#: search.c:4235
+msgid "All included files were found"
+msgstr "‘S‚ẴCƒ“ƒNƒ‹[ƒh‚³‚ꂽƒtƒ@ƒCƒ‹‚ª‚݂‚©‚è‚Ü‚µ‚½"
+
+#: search.c:4237
+msgid "No included files"
+msgstr "ƒCƒ“ƒNƒ‹[ƒhƒtƒ@ƒCƒ‹‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: search.c:4253
+msgid "E388: Couldn't find definition"
+msgstr "E388: ’è‹`‚ð‚݂‚¯‚ç‚ê‚Ü‚¹‚ñ"
+
+#: search.c:4255
+msgid "E389: Couldn't find pattern"
+msgstr "E389: ƒpƒ^[ƒ“‚ð‚݂‚¯‚ç‚ê‚Ü‚¹‚ñ"
+
+#: syntax.c:3050
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: •s³‚Ȉø”‚Å‚·: %s"
+
+#: syntax.c:3230
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: ‚»‚̂悤‚È\\•¶ƒNƒ‰ƒXƒ^‚Í‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: syntax.c:3394
+msgid "No Syntax items defined for this buffer"
+msgstr "‚±‚̃oƒbƒtƒ@‚É’è‹`‚³‚ꂽ\\•¶—v‘f‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: syntax.c:3402
+msgid "syncing on C-style comments"
+msgstr "CŒ¾Œê•—ƒRƒƒ“ƒg‚©‚瓯Šú’†"
+
+#: syntax.c:3410
+msgid "no syncing"
+msgstr "”ñ“¯Šú"
+
+#: syntax.c:3413
+msgid "syncing starts "
+msgstr "“¯ŠúŠJŽn "
+
+#: syntax.c:3415 syntax.c:3490
+msgid " lines before top line"
+msgstr " s‘O(ƒgƒbƒvs‚æ‚è‚à)"
+
+#: syntax.c:3420
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- \\•¶“¯Šú—v‘f ---"
+
+#: syntax.c:3425
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"—v‘fã‚Å“¯Šú’†"
+
+#: syntax.c:3431
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- \\•¶—v‘f ---"
+
+#: syntax.c:3454
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: ‚»‚̂悤‚È\\•¶ƒNƒ‰ƒXƒ^‚Í‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: syntax.c:3480
+msgid "minimal "
+msgstr "minimal"
+
+#: syntax.c:3487
+msgid "maximal "
+msgstr "maximal"
+
+#: syntax.c:3499
+msgid "; match "
+msgstr "; ŠY“– "
+
+#: syntax.c:3501
+msgid " line breaks"
+msgstr " ŒÂ‚̉üs"
+
+#: syntax.c:4135
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: ‚±‚±‚ł̓Oƒ‹[ƒv‚Í‹–‰Â‚³‚ê‚Ü‚¹‚ñ"
+
+#: syntax.c:4159
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: %s ‚͈̔͗v‘f‚ª‚݂‚©‚è‚Ü‚¹‚ñ"
+
+#: syntax.c:4187
+msgid "E395: contains argument not accepted here"
+msgstr "E395: ‚±‚Ìꊂł͈ø”contains‚Í‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: syntax.c:4198
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: ‚±‚Ìꊂł͈ø”containedin‚Í‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: syntax.c:4276
+msgid "E397: Filename required"
+msgstr "E397: ƒtƒ@ƒCƒ‹–¼‚ª•K—v‚Å‚·"
+
+#: syntax.c:4614
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: '=' ‚ª‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: syntax.c:4772
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: ˆø”‚ª‘«‚è‚Ü‚¹‚ñ: \\•¶”ÍˆÍ %s"
+
+#: syntax.c:5103
+msgid "E400: No cluster specified"
+msgstr "E400: ƒNƒ‰ƒXƒ^‚ªŽw’肳‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: syntax.c:5140
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: ƒpƒ^[ƒ“‹æ؂肪‚݂‚©‚è‚Ü‚¹‚ñ: %s"
+
+#: syntax.c:5215
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: ƒpƒ^[ƒ“‚Ì‚ ‚ƂɃSƒ~‚ª‚ ‚è‚Ü‚·: %s"
+
+#: syntax.c:5305
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: \\•¶“¯Šú: ˜A‘±sƒpƒ^[ƒ“‚ª2“xŽw’肳‚ê‚Ü‚µ‚½"
+
+#: syntax.c:5362
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: •s³‚Ȉø”‚Å‚·: %s"
+
+#: syntax.c:5412
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: “™‚µ‚¢ sign ‚ª‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: syntax.c:5418
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: ‹ó‚̈ø”: %s"
+
+#: syntax.c:5445
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s ‚̓RƒR‚Å‚Í‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: syntax.c:5452
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s ‚Í“à—eƒŠƒXƒg‚Ì擪‚Å‚È‚¯‚ê‚΂Ȃç‚È‚¢"
+
+#: syntax.c:5522
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: –¢’m‚̃Oƒ‹[ƒv–¼: %s"
+
+#: syntax.c:5755
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: –³Œø‚È :syntax ‚̃TƒuƒRƒ}ƒ“ƒh: %s"
+
+#: syntax.c:6134
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: ƒnƒCƒ‰ƒCƒgƒOƒ‹[ƒv‚ª‚݂‚©‚è‚Ü‚¹‚ñ: %s"
+
+#: syntax.c:6158
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: ˆø”‚ª[•ª‚Å‚Í‚È‚¢: \":highlight link %s\""
+
+#: syntax.c:6165
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: ˆø”‚ª‘½‚·‚¬‚Ü‚·: \":highlight link %s\""
+
+#: syntax.c:6185
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: ƒOƒ‹[ƒv‚ªÝ’肳‚ê‚Ä‚¢‚é‚̂ŃnƒCƒ‰ƒCƒgƒŠƒ“ƒN‚Í–³Ž‹‚³‚ê‚Ü‚·"
+
+#: syntax.c:6314
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: —\\Šú‚¹‚Ê“¯‚¶ sign ‚Å‚·: %s"
+
+#: syntax.c:6350
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: “¯‚¶ sign ‚ª‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: syntax.c:6378
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: ˆø”‚ª‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: syntax.c:6415
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: •s³‚È’l‚Å‚·: %s"
+
+#: syntax.c:6534
+msgid "E419: FG color unknown"
+msgstr "E419: –¢’m‚Ì‘OŒiF‚Å‚·"
+
+#: syntax.c:6545
+msgid "E420: BG color unknown"
+msgstr "E420: –¢’m‚Ì”wŒiF‚Å‚·"
+
+#: syntax.c:6606
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: ƒJƒ‰[–¼‚â”Ô†‚ð”FŽ¯‚Å‚«‚Ü‚¹‚ñ: %s"
+
+#: syntax.c:6812
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: I’[ƒR[ƒh‚ª’·‚·‚¬‚Ü‚·: %s"
+
+#: syntax.c:6859
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: •s³‚Ȉø”‚Å‚·: %s"
+
+#: syntax.c:7388
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: ‘½‚­‚̈قȂéƒnƒCƒ‰ƒCƒg‘®«‚ªŽg‚í‚ê‚·‚¬‚Ä‚¢‚Ü‚·"
+
+#: syntax.c:7909
+msgid "E669: Unprintable character in group name"
+msgstr "E669: ƒOƒ‹[ƒv–¼‚Ɉóü•s‰Â”\\‚È•¶Žš‚ª‚ ‚è‚Ü‚·"
+
+#. This is an error, but since there previously was no check only
+#. * give a warning.
+#: syntax.c:7916
+msgid "W18: Invalid character in group name"
+msgstr "W18: ƒOƒ‹[ƒv–¼‚É•s³‚È•¶Žš‚ª‚ ‚è‚Ü‚·"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: ƒ^ƒOƒXƒ^ƒbƒN‚Ì––”ö‚Å‚·"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: ƒ^ƒOƒXƒ^ƒbƒN‚Ì擪‚Å‚·"
+
+#: tag.c:412
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: ʼn‚ÌŠY“–ƒ^ƒO‚ð’´‚¦‚Ė߂邱‚Æ‚Í‚Å‚«‚Ü‚¹‚ñ"
+
+#: tag.c:550
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: ƒ^ƒO‚ª‚݂‚©‚è‚Ü‚¹‚ñ: %s"
+
+#: tag.c:583
+msgid " # pri kind tag"
+msgstr " # pri kind tag"
+
+#: tag.c:586
+msgid "file\n"
+msgstr "ƒtƒ@ƒCƒ‹\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:744
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "‘I‘ð‚·‚é”Ô†‚ð“ü—Í‚µ‚Ä‚­‚¾‚³‚¢ (<CR>‚Å’†Ž~): "
+
+#: tag.c:784
+msgid "E427: There is only one matching tag"
+msgstr "E427: ŠY“–ƒ^ƒO‚ª1‚‚¾‚¯‚µ‚©‚ ‚è‚Ü‚¹‚ñ"
+
+#: tag.c:786
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: ÅŒã‚ÉŠY“–‚·‚éƒ^ƒO‚ð’´‚¦‚Äi‚Þ‚±‚Æ‚Í‚Å‚«‚Ü‚¹‚ñ"
+
+#: tag.c:810
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "ƒtƒ@ƒCƒ‹ \"%s\" ‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#. Give an indication of the number of matching tags
+#: tag.c:823
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "ƒ^ƒO %d (‘S%d%s)"
+
+#: tag.c:826
+msgid " or more"
+msgstr " ‚©‚»‚êˆÈã"
+
+#: tag.c:828
+msgid " Using tag with different case!"
+msgstr " ƒ^ƒO‚ðˆÙ‚È‚écase‚ÅŽg—p‚µ‚Ü‚·!"
+
+#: tag.c:872
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: ƒtƒ@ƒCƒ‹ \"%s\" ‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#. Highlight title
+#: tag.c:941
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # TO ƒ^ƒO FROM s in file/text"
+
+#: tag.c:1363
+#, c-format
+msgid "Searching tags file %s"
+msgstr "ƒ^ƒOƒtƒ@ƒCƒ‹ %s ‚ðŒŸõ’†"
+
+#: tag.c:1550
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: ƒ^ƒOƒtƒ@ƒCƒ‹‚̃pƒX‚ª %s ‚ÉØ‚èŽÌ‚Ä‚ç‚ê‚Ü‚µ‚½\n"
+
+#: tag.c:2203
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: ƒ^ƒOƒtƒ@ƒCƒ‹ \"%s\" ‚̃tƒH[ƒ}ƒbƒg‚ɃGƒ‰[‚ª‚ ‚è‚Ü‚·"
+
+#: tag.c:2207
+#, c-format
+msgid "Before byte %ld"
+msgstr "’¼‘O‚Ì %ld ƒoƒCƒg"
+
+#: tag.c:2240
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: ƒ^ƒOƒtƒ@ƒCƒ‹‚ªƒ\\[ƒg‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ: %s"
+
+#. never opened any tags file
+#: tag.c:2280
+msgid "E433: No tags file"
+msgstr "E433: ƒ^ƒOƒtƒ@ƒCƒ‹‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: tag.c:3016
+msgid "E434: Can't find tag pattern"
+msgstr "E434: ƒ^ƒOƒpƒ^[ƒ“‚ð‚݂‚¯‚ç‚ê‚Ü‚¹‚ñ"
+
+#: tag.c:3027
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: ƒ^ƒO‚ð‚݂‚¯‚ç‚ê‚È‚¢‚Ì‚Å’P‚É„‘ª‚µ‚Ü‚·!"
+
+#: term.c:1759
+msgid "' not known. Available builtin terminals are:"
+msgstr "' ‚Í–¢’m‚Å‚·. Œ»s‚Ì‘g‚Ýž‚Ý’[––‚ÍŽŸ‚Ì‚Æ‚¨‚è‚Å‚·:"
+
+#: term.c:1783
+msgid "defaulting to '"
+msgstr "È—ª’l‚ðŽŸ‚Ì‚æ‚¤‚Éݒ肵‚Ü‚· '"
+
+#: term.c:2141
+msgid "E557: Cannot open termcap file"
+msgstr "E557: termcapƒtƒ@ƒCƒ‹‚ðŠJ‚¯‚Ü‚¹‚ñ"
+
+#: term.c:2145
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: terminfo‚É’[––ƒGƒ“ƒgƒŠ‚ð‚݂‚¯‚ç‚ê‚Ü‚¹‚ñ"
+
+#: term.c:2147
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: termcap‚É’[––ƒGƒ“ƒgƒŠ‚ð‚݂‚¯‚ç‚ê‚Ü‚¹‚ñ"
+
+#: term.c:2306
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: termcap‚É \"%s\" ‚̃Gƒ“ƒgƒŠ‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: term.c:2780
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: ’[––‚É \"cm\" ‹@”\\‚ª•K—v‚Å‚·"
+
+#. Highlight title
+#: term.c:4990
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- ’[––ƒL[ ---"
+
+#: ui.c:258
+msgid "new shell started\n"
+msgstr "V‚µ‚¢ƒVƒFƒ‹‚ð‹N“®‚µ‚Ü‚·\n"
+
+#: ui.c:1841
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: “ü—Í‚ð“Çž‚Ý’†‚̃Gƒ‰[‚É‚æ‚èI—¹‚µ‚Ü‚·...\n"
+
+#. must display the prompt
+#: undo.c:405
+msgid "No undo possible; continue anyway"
+msgstr "‰Â”\\‚ȃAƒ“ƒhƒD‚Í‚ ‚è‚Ü‚¹‚ñ: ‚Æ‚è‚ ‚¦‚¸‘±‚¯‚Ü‚·"
+
+#: undo.c:561
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: s”Ô†‚ªŠÔˆá‚Á‚Ä‚¢‚Ü‚·"
+
+#: undo.c:757
+msgid "1 change"
+msgstr "1 ‰ÓŠ•ÏX‚µ‚Ü‚µ‚½"
+
+#: undo.c:759
+#, c-format
+msgid "%ld changes"
+msgstr "%ld ‰ÓŠ•ÏX‚µ‚Ü‚µ‚½"
+
+#: undo.c:812
+msgid "E439: undo list corrupt"
+msgstr "E439: ƒAƒ“ƒhƒDƒŠƒXƒg‚ª‰ó‚ê‚Ä‚¢‚Ü‚·"
+
+#: undo.c:844
+msgid "E440: undo line missing"
+msgstr "E440: ƒAƒ“ƒhƒDs‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:1731
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 16/32 ƒrƒbƒg GUI ”Å"
+
+#: version.c:1733
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 32 ƒrƒbƒg GUI ”Å"
+
+#: version.c:1736
+msgid " in Win32s mode"
+msgstr " in Win32s ƒ‚[ƒh"
+
+#: version.c:1738
+msgid " with OLE support"
+msgstr " with OLE ƒTƒ|[ƒg"
+
+#: version.c:1741
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"MS-Windows 32 ƒrƒbƒg ƒRƒ“ƒ\\[ƒ‹ ”Å"
+
+#: version.c:1745
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"MS-Windows 16 ƒrƒbƒg ”Å"
+
+#: version.c:1749
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 ƒrƒbƒg MS-DOS ”Å"
+
+#: version.c:1751
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 ƒrƒbƒg MS-DOS ”Å"
+
+#: version.c:1757
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) Ӂ"
+
+#: version.c:1759
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X Ӂ"
+
+#: version.c:1762
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS Ӂ"
+
+#: version.c:1767
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS Ӂ"
+
+#: version.c:1777
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"“K—pσpƒbƒ`: "
+
+#: version.c:1803 version.c:2171
+msgid "Modified by "
+msgstr "Modified by "
+
+#: version.c:1810
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Compiled "
+
+#: version.c:1813
+msgid "by "
+msgstr "by "
+
+#: version.c:1825
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Huge Ӂ "
+
+#: version.c:1828
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Big Ӂ "
+
+#: version.c:1831
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"’Êí ”Å "
+
+#: version.c:1834
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Small Ӂ "
+
+#: version.c:1836
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Tiny Ӂ "
+
+#: version.c:1842
+msgid "without GUI."
+msgstr "without GUI."
+
+#: version.c:1847
+msgid "with GTK2-GNOME GUI."
+msgstr "with GTK2-GNOME GUI."
+
+#: version.c:1849
+msgid "with GTK-GNOME GUI."
+msgstr "with GTK-GNOME GUI."
+
+#: version.c:1853
+msgid "with GTK2 GUI."
+msgstr "with GTK2 GUI."
+
+#: version.c:1855
+msgid "with GTK GUI."
+msgstr "with GTK GUI."
+
+#: version.c:1860
+msgid "with X11-Motif GUI."
+msgstr "with X11-Motif GUI."
+
+#: version.c:1864
+msgid "with X11-neXtaw GUI."
+msgstr "with X11-neXtaw GUI."
+
+#: version.c:1866
+msgid "with X11-Athena GUI."
+msgstr "with X11-Athena GUI."
+
+#: version.c:1870
+msgid "with BeOS GUI."
+msgstr "with BeOS GUI."
+
+#: version.c:1873
+msgid "with Photon GUI."
+msgstr "with Photon GUI."
+
+#: version.c:1876
+msgid "with GUI."
+msgstr "with GUI."
+
+#: version.c:1879
+msgid "with Carbon GUI."
+msgstr "with Carbon GUI."
+
+#: version.c:1882
+msgid "with Cocoa GUI."
+msgstr "with Cocoa GUI."
+
+#: version.c:1885
+msgid "with (classic) GUI."
+msgstr "with (ƒNƒ‰ƒVƒbƒN) GUI."
+
+#: version.c:1896
+msgid " Features included (+) or not (-):\n"
+msgstr " ‹@”\\‚̈ꗗ —LŒø(+)/–³Œø(-)\n"
+
+#: version.c:1908
+msgid " system vimrc file: \""
+msgstr " ƒVƒXƒeƒ€ vimrc: \""
+
+#: version.c:1913
+msgid " user vimrc file: \""
+msgstr " ƒ†[ƒU vimrc: \""
+
+#: version.c:1918
+msgid " 2nd user vimrc file: \""
+msgstr " ‘æ2ƒ†[ƒU vimrc: \""
+
+#: version.c:1923
+msgid " 3rd user vimrc file: \""
+msgstr " ‘æ3ƒ†[ƒU vimrc: \""
+
+#: version.c:1928
+msgid " user exrc file: \""
+msgstr " ƒ†[ƒU exrc: \""
+
+#: version.c:1933
+msgid " 2nd user exrc file: \""
+msgstr " ‘æ2ƒ†[ƒU exrc: \""
+
+#: version.c:1939
+msgid " system gvimrc file: \""
+msgstr " ƒVƒXƒeƒ€ gvimrc: \""
+
+#: version.c:1943
+msgid " user gvimrc file: \""
+msgstr " ƒ†[ƒU gvimrc: \""
+
+#: version.c:1947
+msgid "2nd user gvimrc file: \""
+msgstr " ‘æ2ƒ†[ƒU gvimrc: \""
+
+#: version.c:1952
+msgid "3rd user gvimrc file: \""
+msgstr " ‘æ3ƒ†[ƒU gvimrc: \""
+
+#: version.c:1959
+msgid " system menu file: \""
+msgstr " ƒVƒXƒeƒ€ƒƒjƒ…[: \""
+
+#: version.c:1967
+msgid " fall-back for $VIM: \""
+msgstr " È—ªŽž‚Ì $VIM: \""
+
+#: version.c:1973
+msgid " f-b for $VIMRUNTIME: \""
+msgstr "È—ªŽž‚Ì $VIMRUNTIME: \""
+
+#: version.c:1977
+msgid "Compilation: "
+msgstr "ƒRƒ“ƒpƒCƒ‹: "
+
+#: version.c:1983
+msgid "Compiler: "
+msgstr "ƒRƒ“ƒpƒCƒ‰: "
+
+#: version.c:1988
+msgid "Linking: "
+msgstr "ƒŠƒ“ƒN: "
+
+#: version.c:1993
+msgid " DEBUG BUILD"
+msgstr "ƒfƒoƒbƒOƒrƒ‹ƒh"
+
+#: version.c:2032
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved"
+
+#: version.c:2034
+msgid "version "
+msgstr "version "
+
+#: version.c:2035
+msgid "by Bram Moolenaar et al."
+msgstr "by Bram Moolenaar ‘¼."
+
+#: version.c:2039
+msgid "Vim is open source and freely distributable"
+msgstr "Vim ‚̓I[ƒvƒ“ƒ\\[ƒX‚Å‚ ‚莩—R‚É”z•z‰Â”\\‚Å‚·"
+
+#: version.c:2041
+msgid "Help poor children in Uganda!"
+msgstr "ƒEƒKƒ“ƒ_‚ÌŒb‚Ü‚ê‚È‚¢Žq‹Ÿ‚½‚¿‚ɉ‡•‚ð!"
+
+#: version.c:2042
+msgid "type :help iccf<Enter> for information "
+msgstr "ÚׂÈî•ñ‚Í :help iccf<Enter> "
+
+#: version.c:2044
+msgid "type :q<Enter> to exit "
+msgstr "I—¹‚·‚é‚É‚Í :q<Enter> "
+
+#: version.c:2045
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "ƒIƒ“ƒ‰ƒCƒ“ƒwƒ‹ƒv‚Í :help<Enter> ‚© <F1> "
+
+#: version.c:2046
+msgid "type :help version6<Enter> for version info"
+msgstr "ƒo[ƒWƒ‡ƒ“î•ñ‚Í :help version6<Enter> "
+
+#: version.c:2049
+msgid "Running in Vi compatible mode"
+msgstr "ViŒÝŠ·ƒ‚[ƒh‚Å“®ì’†"
+
+#: version.c:2050
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "Vim„§’l‚É‚·‚é‚É‚Í :set nocp<Enter> "
+
+#: version.c:2051
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "ÚׂÈî•ñ‚Í :help cp-default<Enter>"
+
+#: version.c:2066
+msgid "menu Help->Orphans for information "
+msgstr "Úׂ̓ƒjƒ…[‚Ì ƒwƒ‹ƒv¨ŒÇŽ™ ‚ðŽQÆ‚µ‚ĉº‚³‚¢ "
+
+#: version.c:2068
+msgid "Running modeless, typed text is inserted"
+msgstr "ƒ‚[ƒh–³‚ÅŽÀs’†, ƒ^ƒCƒv‚µ‚½•¶Žš‚ª‘}“ü‚³‚ê‚Ü‚·"
+
+#: version.c:2069
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "ƒƒjƒ…[‚Ì •ÒW¨‘S‘Ìݒ訑}“ü(‰SŽÒ)ƒ‚[ƒhØ‘Ö"
+
+#: version.c:2070
+msgid " for two modes "
+msgstr " ‚Ń‚[ƒh—L‚É "
+
+#: version.c:2074
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "ƒƒjƒ…[‚Ì •ÒW¨‘S‘ÌÝ’è¨ViŒÝŠ·ƒ‚[ƒhØ‘Ö "
+
+#: version.c:2075
+msgid " for Vim defaults "
+msgstr " ‚ÅVim‚Æ‚µ‚Ä“®ì "
+
+#: version.c:2122
+msgid "Sponsor Vim development!"
+msgstr "Vim‚ÌŠJ”­‚ð‰ž‰‡‚µ‚Ä‚­‚¾‚³‚¢!"
+
+#: version.c:2123
+msgid "Become a registered Vim user!"
+msgstr "Vim‚Ì“o˜^ƒ†[ƒU‚É‚È‚Á‚Ä‚­‚¾‚³‚¢!"
+
+#: version.c:2126
+msgid "type :help sponsor<Enter> for information "
+msgstr "ÚׂÈî•ñ‚Í :help sponsor<Enter> "
+
+#: version.c:2127
+msgid "type :help register<Enter> for information "
+msgstr "ÚׂÈî•ñ‚Í :help register<Enter> "
+
+#: version.c:2129
+msgid "menu Help->Sponsor/Register for information "
+msgstr "Úׂ̓ƒjƒ…[‚Ì ƒwƒ‹ƒv¨ƒXƒ|ƒ“ƒT[/“o˜^ ‚ðŽQÆ‚µ‚ĉº‚³‚¢ "
+
+#: version.c:2139
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr " Œx: Windows 95/98/Me ‚ðŒŸo "
+
+#: version.c:2142
+msgid "type :help windows95<Enter> for info on this"
+msgstr " ÚׂÈî•ñ‚Í :help windows95<Enter> "
+
+#: window.c:203
+msgid "E441: There is no preview window"
+msgstr "E441: ƒvƒŒƒrƒ…[ƒEƒBƒ“ƒhƒE‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: window.c:581
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: ¶ã‚ƉE‰º‚𓯎ž‚É•ªŠ„‚·‚邱‚Æ‚Í‚Å‚«‚Ü‚¹‚ñ"
+
+#: window.c:1340
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: ‘¼‚̃EƒBƒ“ƒhƒE‚ª•ªŠ„‚³‚ê‚Ä‚¢‚鎞‚ɂ͇‰ñ‚Å‚«‚Ü‚¹‚ñ"
+
+#: window.c:1836
+msgid "E444: Cannot close last window"
+msgstr "E444: ÅŒã‚̃EƒBƒ“ƒhƒE‚ð•Â‚¶‚邱‚Æ‚Í‚Å‚«‚Ü‚¹‚ñ"
+
+#: window.c:2567
+msgid "Already only one window"
+msgstr "Šù‚ɃEƒBƒ“ƒhƒE‚Í1‚‚µ‚©‚ ‚è‚Ü‚¹‚ñ"
+
+#: window.c:2614
+msgid "E445: Other window contains changes"
+msgstr "E445: ‘¼‚̃EƒBƒ“ƒhƒE‚É‚Í•ÏX‚ª‚ ‚è‚Ü‚·"
+
+#: window.c:4480
+msgid "E446: No file name under cursor"
+msgstr "E446: ƒJ[ƒ\\ƒ‹‚̉º‚Ƀtƒ@ƒCƒ‹–¼‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: window.c:4599
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: path‚É‚Í \"%s\" ‚Æ‚¢‚¤ƒtƒ@ƒCƒ‹‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1232 if_perl.xs:326
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: ƒ‰ƒCƒuƒ‰ƒŠ %s ‚ðƒ[ƒh‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: if_perl.xs:554
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr ""
+"‚±‚̃Rƒ}ƒ“ƒh‚Í–³Œø‚Å‚·, ‚²‚ß‚ñ‚È‚³‚¢: Perlƒ‰ƒCƒuƒ‰ƒŠ‚ðƒ[ƒh‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½."
+
+#: if_perl.xs:607
+msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+msgstr ""
+"E299: ƒTƒ“ƒhƒ{ƒbƒNƒX‚Å‚Í Safe "
+"ƒ‚ƒWƒ…[ƒ‹‚ðŽg—p‚µ‚È‚¢PerlƒXƒNƒŠƒvƒg‚Í‹Ö‚¶‚ç‚ê‚Ä‚¢‚Ü‚·"
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "Šeƒtƒ@ƒCƒ‹‚ð•ÊX‚Ì Vim ‚Å•ÒW(&M)"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "‘Sƒtƒ@ƒCƒ‹‚ð1‚Â‚Ì Vim ‚Å•ÒW(&V)"
+
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "Vim ‚Å·•ª•ÒW(&D)"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "Vim ‚Å•ÒW(&V)"
+
+#: GvimExt/gvimext.cpp:633
+msgid "Edit with existing Vim - &"
+msgstr "Šù‘¶‚Ì Vim ‚Å•ÒW - &"
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "‘I‘ð‚³‚ê‚½ƒtƒ@ƒCƒ‹‚ð Vim ‚Å•ÒW"
+
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "‹N“®ƒGƒ‰[: gvim ‚ɃpƒX‚ª’Ê‚Á‚Ä‚¢‚é‚©Šm‚©‚ß‚Ä‚­‚¾‚³‚¢!"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "gvimext.dll ƒGƒ‰["
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "ƒpƒX‚ª’·‚·‚¬‚Ü‚·!"
+
+#: globals.h:1022
+msgid "--No lines in buffer--"
+msgstr "--ƒoƒbƒtƒ@‚És‚ª‚ ‚è‚Ü‚¹‚ñ--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1185
+msgid "E470: Command aborted"
+msgstr "E470: ƒRƒ}ƒ“ƒh‚ª’†’f‚³‚ê‚Ü‚µ‚½"
+
+#: globals.h:1186
+msgid "E471: Argument required"
+msgstr "E471: ˆø”‚ª•K—v‚Å‚·"
+
+#: globals.h:1187
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ ‚ÌŒã‚Í / ‚© ? ‚© & ‚Å‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ"
+
+#: globals.h:1189
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: ƒRƒ}ƒ“ƒhƒ‰ƒCƒ“‚Å‚Í–³Œø‚Å‚·; <CR>‚ÅŽÀs, CTRL-C‚Å‚â‚ß‚é"
+
+#: globals.h:1191
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Œ»Ý‚̃fƒBƒŒƒNƒgƒŠ‚âƒ^ƒOŒŸõ‚Å‚Íexrc/vimrc‚̃Rƒ}ƒ“ƒh‚Í‹–‰Â‚³‚ê‚Ü‚¹‚ñ"
+
+#: globals.h:1193
+msgid "E171: Missing :endif"
+msgstr "E171: :endif ‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1194
+msgid "E600: Missing :endtry"
+msgstr "E600: :endtry ‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1195
+msgid "E170: Missing :endwhile"
+msgstr "E170: :endwhile ‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1196
+msgid "E588: :endwhile without :while"
+msgstr "E588: :while ‚Ì‚È‚¢ :endwhile ‚ª‚ ‚è‚Ü‚·"
+
+#: globals.h:1198
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: ƒtƒ@ƒCƒ‹‚ª‘¶Ý‚µ‚Ü‚· (! ‚ð’ljÁ‚Åã‘)"
+
+#: globals.h:1199
+msgid "E472: Command failed"
+msgstr "E472: ƒRƒ}ƒ“ƒh‚ªŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: globals.h:1201
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: –¢’m‚̃tƒHƒ“ƒgƒZƒbƒg: %s"
+
+#: globals.h:1205
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: –¢’m‚̃tƒHƒ“ƒg: %s"
+
+#: globals.h:1208
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: ƒtƒHƒ“ƒg \"%s\" ‚͌Œ蕂ł͂ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1210
+msgid "E473: Internal error"
+msgstr "E473: “à•”ƒGƒ‰[‚Å‚·"
+
+#: globals.h:1211
+msgid "Interrupted"
+msgstr "Š„ž‚Ü‚ê‚Ü‚µ‚½"
+
+#: globals.h:1212
+msgid "E14: Invalid address"
+msgstr "E14: –³Œø‚ȃAƒhƒŒƒX‚Å‚·"
+
+#: globals.h:1213
+msgid "E474: Invalid argument"
+msgstr "E474: –³Œø‚Ȉø”‚Å‚·"
+
+#: globals.h:1214
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: –³Œø‚Ȉø”‚Å‚·: %s"
+
+#: globals.h:1216
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: –³Œø‚ÈŽ®‚Å‚·: %s"
+
+#: globals.h:1218
+msgid "E16: Invalid range"
+msgstr "E16: –³Œø‚Ȕ͈͂ł·"
+
+#: globals.h:1219
+msgid "E476: Invalid command"
+msgstr "E476: –³Œø‚ȃRƒ}ƒ“ƒh‚Å‚·"
+
+#: globals.h:1221
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" ‚̓fƒBƒŒƒNƒgƒŠ‚Å‚·"
+
+#: globals.h:1224
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: —\\Šú‚¹‚Ê•¶Žš‚ª '=' ‚Ì‘O‚É‚ ‚è‚Ü‚µ‚½"
+
+#: globals.h:1227
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: \"%s\"() ‚̃‰ƒCƒuƒ‰ƒŠŒÄo‚ÉŽ¸”s‚µ‚Ü‚µ‚½"
+
+#: globals.h:1233
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: ƒ‰ƒCƒuƒ‰ƒŠ‚ÌŠÖ” %s ‚ðƒ[ƒh‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: globals.h:1235
+msgid "E19: Mark has invalid line number"
+msgstr "E19: ƒ}[ƒN‚É–³Œø‚Ès”Ô†‚ªŽw’肳‚ê‚Ä‚¢‚Ü‚µ‚½"
+
+#: globals.h:1236
+msgid "E20: Mark not set"
+msgstr "E20: ƒ}[ƒN‚Íݒ肳‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: globals.h:1237
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: 'modifiable' ‚ªƒIƒt‚È‚Ì‚Å, •ÏX‚Å‚«‚Ü‚¹‚ñ"
+
+#: globals.h:1238
+msgid "E22: Scripts nested too deep"
+msgstr "E22: ƒXƒNƒŠƒvƒg‚Ì“ü‚êŽq‚ª[‚·‚¬‚Ü‚·"
+
+#: globals.h:1239
+msgid "E23: No alternate file"
+msgstr "E23: •›ƒtƒ@ƒCƒ‹‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1240
+msgid "E24: No such abbreviation"
+msgstr "E24: ‚»‚̂悤‚È’Zk“ü—Í‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1241
+msgid "E477: No ! allowed"
+msgstr "E477: ! ‚Í‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: globals.h:1243
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: GUI‚ÍŽg—p•s‰Â”\\‚Å‚·: ƒRƒ“ƒpƒCƒ‹Žž‚É–³Œø‚É‚³‚ê‚Ä‚¢‚Ü‚·"
+
+#: globals.h:1246
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: ƒwƒuƒ‰ƒCŒê‚ÍŽg—p•s‰Â”\\‚Å‚·: ƒRƒ“ƒpƒCƒ‹Žž‚É–³Œø‚É‚³‚ê‚Ä‚¢‚Ü‚·\n"
+
+#: globals.h:1249
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: ƒyƒ‹ƒVƒAŒê‚ÍŽg—p•s‰Â”\\‚Å‚·: ƒRƒ“ƒpƒCƒ‹Žž‚É–³Œø‚É‚³‚ê‚Ä‚¢‚Ü‚·\n"
+
+#: globals.h:1252
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: ƒAƒ‰ƒrƒAŒê‚ÍŽg—p•s‰Â”\\‚Å‚·: ƒRƒ“ƒpƒCƒ‹Žž‚É–³Œø‚É‚³‚ê‚Ä‚¢‚Ü‚·\n"
+
+#: globals.h:1255
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: ‚»‚̂悤‚È–¼‚̃nƒCƒ‰ƒCƒgƒOƒ‹[ƒv‚Í‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: globals.h:1257
+msgid "E29: No inserted text yet"
+msgstr "E29: ‚Ü‚¾ƒeƒLƒXƒg‚ª‘}“ü‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: globals.h:1258
+msgid "E30: No previous command line"
+msgstr "E30: ˆÈ‘O‚ɃRƒ}ƒ“ƒhs‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1259
+msgid "E31: No such mapping"
+msgstr "E31: ‚»‚̂悤‚ȃ}ƒbƒsƒ“ƒO‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1260
+msgid "E479: No match"
+msgstr "E479: ŠY“–‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1261
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: ŠY“–‚Í‚ ‚è‚Ü‚¹‚ñ: %s"
+
+#: globals.h:1262
+msgid "E32: No file name"
+msgstr "E32: ƒtƒ@ƒCƒ‹–¼‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1263
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: ³‹K•\\Œ»’uŠ·‚ª‚Ü‚¾ŽÀs‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: globals.h:1264
+msgid "E34: No previous command"
+msgstr "E34: ƒRƒ}ƒ“ƒh‚ª‚Ü‚¾ŽÀs‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: globals.h:1265
+msgid "E35: No previous regular expression"
+msgstr "E35: ³‹K•\\Œ»‚ª‚Ü‚¾ŽÀs‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: globals.h:1266
+msgid "E481: No range allowed"
+msgstr "E481: ”͈͎w’è‚Í‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: globals.h:1268
+msgid "E36: Not enough room"
+msgstr "E36: [•ª‚È—e—Ê‚ª‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1271
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: %s ‚Æ‚¢‚¤–¼‘O‚Ì“o˜^‚³‚ꂽƒT[ƒo‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1273
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: ƒtƒ@ƒCƒ‹ %s ‚ð쬂ł«‚Ü‚¹‚ñ"
+
+#: globals.h:1274
+msgid "E483: Can't get temp file name"
+msgstr "E483: ˆêŽžƒtƒ@ƒCƒ‹‚Ì–¼‘O‚ðŽæ“¾‚Å‚«‚Ü‚¹‚ñ"
+
+#: globals.h:1275
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: ƒtƒ@ƒCƒ‹ \"%s\" ‚ðŠJ‚¯‚Ü‚¹‚ñ"
+
+#: globals.h:1276
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: ƒtƒ@ƒCƒ‹ %s ‚ð“Çž‚ß‚Ü‚¹‚ñ"
+
+#: globals.h:1277
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: ÅŒã‚Ì•ÏX‚ª•Û‘¶‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ (! ‚ð’ljÁ‚Å•ÏX‚ð”jŠü)"
+
+#: globals.h:1278
+msgid "E38: Null argument"
+msgstr "E38: ˆø”‚ª‹ó‚Å‚·"
+
+#: globals.h:1280
+msgid "E39: Number expected"
+msgstr "E39: ”’l‚ª—v‹‚³‚ê‚Ä‚¢‚Ü‚·"
+
+#: globals.h:1283
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: ƒGƒ‰[ƒtƒ@ƒCƒ‹ %s ‚ðŠJ‚¯‚Ü‚¹‚ñ"
+
+#: globals.h:1286
+msgid "E233: cannot open display"
+msgstr "E233: ƒfƒBƒXƒvƒŒƒC‚ðŠJ‚¯‚Ü‚¹‚ñ"
+
+#: globals.h:1288
+msgid "E41: Out of memory!"
+msgstr "E41: ƒƒ‚ƒŠ‚ªs‚«‰Ê‚Ä‚Ü‚µ‚½!"
+
+#: globals.h:1290
+msgid "Pattern not found"
+msgstr "ƒpƒ^[ƒ“‚݂͂‚©‚è‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: globals.h:1292
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: ƒpƒ^[ƒ“‚݂͂‚©‚è‚Ü‚¹‚ñ‚Å‚µ‚½: %s"
+
+#: globals.h:1293
+msgid "E487: Argument must be positive"
+msgstr "E487: ˆø”‚ͳ‚Ì’l‚Å‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ"
+
+#: globals.h:1295
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: ‘O‚̃fƒBƒŒƒNƒgƒŠ‚É–ß‚ê‚Ü‚¹‚ñ"
+
+#: globals.h:1299
+msgid "E42: No Errors"
+msgstr "E42: ƒGƒ‰[‚Í‚ ‚è‚Ü‚¹‚ñ"
+
+#: globals.h:1301
+msgid "E43: Damaged match string"
+msgstr "E43: ŠY“–•¶Žš—ñ‚ª”j‘¹‚µ‚Ä‚¢‚Ü‚·"
+
+#: globals.h:1302
+msgid "E44: Corrupted regexp program"
+msgstr "E44: •s³‚ȳ‹K•\\Œ»ƒvƒƒOƒ‰ƒ€‚Å‚·"
+
+#: globals.h:1303
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: 'readonly' ƒIƒvƒVƒ‡ƒ“‚ªÝ’肳‚ê‚Ä‚¢‚Ü‚· (! ‚ð’ljÁ‚Åã‘‚«)"
+
+#: globals.h:1305
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: “ÇŽæê—p•Ï” \"%s\" ‚ÉÝ’è‚·‚邱‚Æ‚Í‚Å‚«‚Ü‚¹‚ñ"
+
+#: globals.h:1308
+msgid "E47: Error while reading errorfile"
+msgstr "E47: ƒGƒ‰[ƒtƒ@ƒCƒ‹‚Ì“Çž’†‚ɃGƒ‰[‚ª”­¶‚µ‚Ü‚µ‚½"
+
+#: globals.h:1311
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: ƒTƒ“ƒhƒ{ƒbƒNƒX‚Å‚Í‹–‚³‚ê‚Ü‚¹‚ñ"
+
+#: globals.h:1313
+msgid "E523: Not allowed here"
+msgstr "E523: ‚±‚±‚Å‚Í‹–‰Â‚³‚ê‚Ü‚¹‚ñ"
+
+#: globals.h:1316
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: ƒXƒNƒŠ[ƒ“ƒ‚[ƒh‚ÌÝ’è‚ɂ͑Ήž‚µ‚Ä‚¢‚Ü‚¹‚ñ"
+
+#: globals.h:1318
+msgid "E49: Invalid scroll size"
+msgstr "E49: –³Œø‚ȃXƒNƒ[ƒ‹—Ê‚Å‚·"
+
+#: globals.h:1319
+msgid "E91: 'shell' option is empty"
+msgstr "E91: 'shell' ƒIƒvƒVƒ‡ƒ“‚ª‹ó‚Å‚·"
+
+#: globals.h:1321
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: sign ‚̃f[ƒ^‚ð“Çž‚ß‚Ü‚¹‚ñ‚Å‚µ‚½"
+
+#: globals.h:1323
+msgid "E72: Close error on swap file"
+msgstr "E72: ƒXƒƒbƒvƒtƒ@ƒCƒ‹‚̃Nƒ[ƒYŽžƒGƒ‰[‚Å‚·"
+
+#: globals.h:1324
+msgid "E73: tag stack empty"
+msgstr "E73: ƒ^ƒOƒXƒ^ƒbƒN‚ª‹ó‚Å‚·"
+
+#: globals.h:1325
+msgid "E74: Command too complex"
+msgstr "E74: ƒRƒ}ƒ“ƒh‚ª•¡ŽG‚·‚¬‚Ü‚·"
+
+#: globals.h:1326
+msgid "E75: Name too long"
+msgstr "E75: –¼‘O‚ª’·‚·‚¬‚Ü‚·"
+
+#: globals.h:1327
+msgid "E76: Too many ["
+msgstr "E76: [ ‚ª‘½‚·‚¬‚Ü‚·"
+
+#: globals.h:1328
+msgid "E77: Too many file names"
+msgstr "E77: ƒtƒ@ƒCƒ‹–¼‚ª‘½‚·‚¬‚Ü‚·"
+
+#: globals.h:1329
+msgid "E488: Trailing characters"
+msgstr "E488: —]•ª‚È•¶Žš‚ªŒã‚ë‚É‚ ‚è‚Ü‚·"
+
+#: globals.h:1330
+msgid "E78: Unknown mark"
+msgstr "E78: –¢’m‚̃}[ƒN"
+
+#: globals.h:1331
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: ƒƒCƒ‹ƒhƒJ[ƒh‚ð“WŠJ‚Å‚«‚Ü‚¹‚ñ"
+
+#: globals.h:1333
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: 'winheight' ‚Í 'winminheight' ‚æ‚謂³‚­‚Å‚«‚Ü‚¹‚ñ"
+
+#: globals.h:1335
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: 'winwidth' ‚Í 'winminwidth' ‚æ‚謂³‚­‚Å‚«‚Ü‚¹‚ñ"
+
+#: globals.h:1338
+msgid "E80: Error while writing"
+msgstr "E80: ‘ž‚Ý’†‚̃Gƒ‰["
+
+#: globals.h:1339
+msgid "Zero count"
+msgstr "ƒ[ƒƒJƒEƒ“ƒg"
+
+#: globals.h:1341
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: ƒXƒNƒŠƒvƒgˆÈŠO‚Å<SID>‚ªŽg‚í‚ê‚Ü‚µ‚½"
+
+#: globals.h:1344
+msgid "E449: Invalid expression received"
+msgstr "E449: –³Œø‚ÈŽ®‚ðŽó‚¯Žæ‚è‚Ü‚µ‚½"
+
+#: globals.h:1347
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: —̈悪•ÛŒì‚³‚ê‚Ä‚¢‚é‚Ì‚Å, •ÏX‚Å‚«‚Ü‚¹‚ñ"
diff --git a/src/po/ko.po b/src/po/ko.po
new file mode 100644
index 000000000..2b4ca8575
--- /dev/null
+++ b/src/po/ko.po
@@ -0,0 +1,6580 @@
+# Korean translation for Vim
+#
+# FIRST AUTHOR Nam SungHyun <namsh@kldp.org>, 2000-2004
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: vim 6.3\n"
+"Report-Msgid-Bugs-To: Nam SungHyun <namsh@kldp.org>\n"
+"POT-Creation-Date: 2004-05-17 17:27+0900\n"
+"PO-Revision-Date: 2004-05-17 18:17+0900\n"
+"Last-Translator: Nam SungHyun <namsh@kldp.org>\n"
+"Language-Team: GTP Korean <gnome-kr-translation@gnome.or.kr>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=euc-kr\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: buffer.c:102
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: ¹öÆÛ¸¦ ÇÒ´çÇÒ ¼ö ¾ø¾î¼­ ³¡³À´Ï´Ù..."
+
+#: buffer.c:105
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: ¹öÆÛ¸¦ ÇÒ´çÇÒ ¼ö ¾ø¾î¼­ ´Ù¸¥ °É »ç¿ëÇÕ´Ï´Ù..."
+
+#: buffer.c:805
+#, c-format
+msgid "E515: No buffers were unloaded"
+msgstr "E515: ³»·ÁÁø ¹öÆÛ°¡ ¾ø½À´Ï´Ù"
+
+#: buffer.c:807
+#, c-format
+msgid "E516: No buffers were deleted"
+msgstr "E516: Áö¿öÁø ¹öÆÛ°¡ ¾ø½À´Ï´Ù"
+
+#: buffer.c:809
+#, c-format
+msgid "E517: No buffers were wiped out"
+msgstr "E517: ¿ÏÀüÈ÷ Áö¿öÁø ¹öÆÛ°¡ ¾ø½À´Ï´Ù"
+
+#: buffer.c:817
+msgid "1 buffer unloaded"
+msgstr "¹öÆÛ ÇÑ °³°¡ ³»·ÁÁ³½À´Ï´Ù"
+
+#: buffer.c:819
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "¹öÆÛ %d °³°¡ ³»·ÁÁ³½À´Ï´Ù"
+
+#: buffer.c:824
+msgid "1 buffer deleted"
+msgstr "¹öÆÛ ÇÑ °³°¡ Áö¿öÁ³½À´Ï´Ù"
+
+#: buffer.c:826
+#, c-format
+msgid "%d buffers deleted"
+msgstr "¹öÆÛ %d °³°¡ Áö¿öÁ³½À´Ï´Ù"
+
+#: buffer.c:831
+msgid "1 buffer wiped out"
+msgstr "¹öÆÛ ÇÑ °³°¡ ¿ÏÀüÈ÷ Áö¿öÁ³½À´Ï´Ù"
+
+#: buffer.c:833
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "¹öÆÛ %d°³°¡ ¿ÏÀüÈ÷ Áö¿öÁ³½À´Ï´Ù"
+
+#: buffer.c:894
+msgid "E84: No modified buffer found"
+msgstr "E84: ¹Ù²ï ¹öÆÛ¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#. back where we started, didn't find anything.
+#: buffer.c:933
+msgid "E85: There is no listed buffer"
+msgstr "E85: ³ª¿­µÈ ¹öÆÛ°¡ ¾ø½À´Ï´Ù"
+
+#: buffer.c:945
+#, c-format
+msgid "E86: Buffer %ld does not exist"
+msgstr "E86: ¹öÆÛ %ldÀÌ(°¡) Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù"
+
+#: buffer.c:948
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: ¸¶Áö¸· ¹öÆÛÀÔ´Ï´Ù"
+
+#: buffer.c:950
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: ù ¹ø° ¹öÆÛÀÔ´Ï´Ù"
+
+#: buffer.c:988
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr ""
+"E89: ¹öÆÛ %ldÀ»(¸¦) ¸¶Áö¸·À¸·Î °íÄ£ µÚ ÀúÀåÇÏÁö ¾Ê¾Ò½À´Ï´Ù (µ¤¾î¾²·Á¸é ! ´õÇÏ"
+"±â)"
+
+#: buffer.c:1005
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: ¸¶Áö¸· ¹öÆÛ¸¦ ³»¸± ¼ö ¾ø½À´Ï´Ù"
+
+#: buffer.c:1538
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: °æ°í: ÆÄÀÏ À̸§ ¸ñ·ÏÀÌ ³ÑÃƽÀ´Ï´Ù"
+
+#: buffer.c:1709
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: ¹öÆÛ %ldÀ»(¸¦) ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: buffer.c:1940
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: %sÀ»(¸¦) Çϳª ÀÌ»ó ã¾Ò½À´Ï´Ù"
+
+#: buffer.c:1942
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: %s¿Í ¸Â´Â ¹öÆÛ°¡ ¾ø½À´Ï´Ù"
+
+#: buffer.c:2337
+#, c-format
+msgid "line %ld"
+msgstr "%ld ÁÙ"
+
+#: buffer.c:2422
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: ÀÌ À̸§À» °¡Áø ¹öÆÛ°¡ ÀÌ¹Ì ÀÖ½À´Ï´Ù"
+
+#: buffer.c:2717
+msgid " [Modified]"
+msgstr " [¹Ù²ñ]"
+
+#: buffer.c:2722
+msgid "[Not edited]"
+msgstr "[°íÄ¡Áö ¾Ê¾ÒÀ½]"
+
+#: buffer.c:2727
+msgid "[New file]"
+msgstr "[»õ ÆÄÀÏ]"
+
+#: buffer.c:2728
+msgid "[Read errors]"
+msgstr "[Àб⠿¡·¯]"
+
+#: buffer.c:2730 fileio.c:2112
+msgid "[readonly]"
+msgstr "[Àбâ Àü¿ë]"
+
+#: buffer.c:2751
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 ÁÙ --%d%%--"
+
+#: buffer.c:2753
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld ÁÙ --%d%%--"
+
+#: buffer.c:2760
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "%ld / %ld ÁÙ --%d%%-- Ä­ "
+
+#: buffer.c:2868
+msgid "[No file]"
+msgstr "[ÆÄÀÏ ¾øÀ½]"
+
+#. must be a help buffer
+#: buffer.c:2908
+msgid "help"
+msgstr "µµ¿ò¸»"
+
+#: buffer.c:3467 screen.c:5075
+msgid "[help]"
+msgstr "[µµ¿ò¸»]"
+
+#: buffer.c:3499 screen.c:5081
+msgid "[Preview]"
+msgstr "[¹Ì¸® º¸±â]"
+
+#: buffer.c:3779
+msgid "All"
+msgstr "¸ðµÎ"
+
+#: buffer.c:3779
+msgid "Bot"
+msgstr "¹Ù´Ú"
+
+#: buffer.c:3781
+msgid "Top"
+msgstr "²À´ë±â"
+
+#: buffer.c:4529
+#, c-format
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# ¹öÆÛ ¸ñ·Ï:\n"
+
+#: buffer.c:4562
+msgid "[Error List]"
+msgstr "[¿¡·¯ ¸ñ·Ï]"
+
+#: buffer.c:4575 memline.c:1521
+msgid "[No File]"
+msgstr "[ÆÄÀÏ ¾øÀ½]"
+
+#: buffer.c:4888
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- ±âÈ£ ---"
+
+#: buffer.c:4907
+#, c-format
+msgid "Signs for %s:"
+msgstr "%s¿¡ ´ëÇÑ ±âÈ£:"
+
+#: buffer.c:4913
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " ÁÙ=%ld id=%d À̸§=%s"
+
+#: diff.c:139
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: %ld°³ ÀÌ»óÀÇ ¹öÆÛ¿¡ ´ëÇؼ­´Â diff¸¦ ÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: diff.c:713
+msgid "E97: Cannot create diffs"
+msgstr "E97: diff¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù"
+
+#: diff.c:818
+msgid "Patch file"
+msgstr "ÆÐÅ° ÆÄÀÏ"
+
+#: diff.c:1069
+msgid "E98: Cannot read diff output"
+msgstr "E98: diff Ãâ·ÂÀ» ÀÐÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: diff.c:1819
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: ÇöÀç ¹öÆÛ´Â diff »óÅ°¡ ¾Æ´Õ´Ï´Ù"
+
+#: diff.c:1831
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: ´Ù¸¥ ¹öÆÛÁß¿¡ diff »óÅÂÀÎ °Ô ¾ø½À´Ï´Ù"
+
+#: diff.c:1839
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr ""
+"E101: µÎ°³ ÀÌ»óÀÇ ¹öÆÛ°¡ diff »óÅ¿©¼­ ¾î¶² °ÍÀ» ½á¾ßÇÒ Áö ¾Ë ¼ö ¾ø½À´Ï´Ù"
+
+#: diff.c:1862
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: \"%s\" ¹öÆÛ¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: diff.c:1868
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: \"%s\" ¹öÆÛ´Â diff »óÅ°¡ ¾Æ´Õ´Ï´Ù"
+
+#: digraph.c:2199
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: digraph¿¡´Â EscapeÀ» ¾µ ¼ö ¾ø½À´Ï´Ù"
+
+#: digraph.c:2384
+msgid "E544: Keymap file not found"
+msgstr "E544: Å°¸Ê ÆÄÀÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: digraph.c:2411
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: ºÒ·¯µéÀÎ ÆÄÀÏ¿¡¼­ :loadkeymapÀ» »ç¿ëÇÏÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: edit.c:40
+msgid " Keyword completion (^N^P)"
+msgstr " ³¹¸» ¿Ï¼º (^N^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E^Y^L^]^F^I^K^D^V^N^P)"
+msgstr " ^X ¸ðµå (^E^Y^L^]^F^I^K^D^V^N^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N^P)"
+msgstr " ³¹¸» ·ÎÄà ¿Ï¼º (^N^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L^N^P)"
+msgstr " Àüü ÁÙ ¿Ï¼º (^L^N^P)"
+
+#: edit.c:46
+msgid " File name completion (^F^N^P)"
+msgstr " ÆÄÀÏ À̸§ ¿Ï¼º (^F^N^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]^N^P)"
+msgstr " ÅÂ±× ¿Ï¼º (^]^N^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N^P)"
+msgstr " °æ·Î ÆÐÅÏ ¿Ï¼º (^N^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D^N^P)"
+msgstr " Á¤ÀÇ ¿Ï¼º (^D^N^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K^N^P)"
+msgstr " ÀÚ·á¹æ ¿Ï¼º (^K^N^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T^N^P)"
+msgstr " ¹é°ú»çÀü ¿Ï¼º (^T^N^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V^N^P)"
+msgstr " ¸í·ÉÇà ¿Ï¼º (^V^N^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "´Ü¶ôÀÇ ¸¶Áö¸· ¸¸³²"
+
+#: edit.c:962
+msgid "'thesaurus' option is empty"
+msgstr "'thesaurus' ¿É¼ÇÀÌ ºñ¾ú½À´Ï´Ù"
+
+#: edit.c:1166
+msgid "'dictionary' option is empty"
+msgstr "'dictionary' ¿É¼ÇÀÌ ºñ¾ú½À´Ï´Ù"
+
+#: edit.c:2162
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "»çÀü ã´Â Áß: %s"
+
+#: edit.c:2368
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (³¢¿ö³Ö±â) ½ºÅ©·Ñ (^E/^Y)"
+
+#: edit.c:2370
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (¹Ù²Þ) ½ºÅ©·Ñ (^E/^Y)"
+
+#: edit.c:2684
+#, c-format
+msgid "Scanning: %s"
+msgstr "ã´Â Áß: %s"
+
+#: edit.c:2719
+#, c-format
+msgid "Scanning tags."
+msgstr "ÅÂ±× Ã£´Â Áß."
+
+#: edit.c:3381
+msgid " Adding"
+msgstr " ´õÇϱâ"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3430
+msgid "-- Searching..."
+msgstr "-- ã´Â Áß..."
+
+#: edit.c:3486
+msgid "Back at original"
+msgstr "¿ø·¡´ë·Î º¹±¸"
+
+#: edit.c:3491
+msgid "Word from other line"
+msgstr "´Ù¸¥ ÁÙ¿¡ ³¹¸»"
+
+#: edit.c:3496
+msgid "The only match"
+msgstr "The only match"
+
+#: edit.c:3555
+#, c-format
+msgid "match %d of %d"
+msgstr "match %d of %d"
+
+#: edit.c:3558
+#, c-format
+msgid "match %d"
+msgstr "match %d"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:1024
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: ¸ð¸£´Â º¯¼ö: \"%s\""
+
+#: eval.c:1320
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: °ýÈ£ ¾øÀ½: %s"
+
+#: eval.c:1435 eval.c:1449
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: ÀÌ·± º¯¼ö ¾øÀ½: \"%s\""
+
+#: eval.c:1705
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: '?' µÚ¿¡ ':'ÀÌ ¾ø½À´Ï´Ù"
+
+#: eval.c:2327
+msgid "E110: Missing ')'"
+msgstr "E110: ')'°¡ ¾ø½À´Ï´Ù"
+
+#: eval.c:2389
+msgid "E111: Missing ']'"
+msgstr "E111: ']'ÀÌ ¾ø½À´Ï´Ù"
+
+#: eval.c:2466
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: ¿É¼Ç À̸§ ¾øÀ½: %s"
+
+#: eval.c:2484
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: ¸ð¸£´Â ¿É¼Ç: %s"
+
+#: eval.c:2555
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: µû¿ÈÇ¥ ¾øÀ½: %s"
+
+#: eval.c:2698
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: µû¿ÈÇ¥ ¾øÀ½: %s"
+
+#: eval.c:3054
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: ÇÔ¼ö %s(À¸)·Î À߸øµÈ ÀÎÀÚ°¡ ³Ñ°ÜÁ³½À´Ï´Ù"
+
+#: eval.c:3083
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: ¸ð¸£´Â ÇÔ¼ö: %s"
+
+#: eval.c:3084
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: ÇÔ¼ö¿¡ ³Ê¹« ¸¹Àº ÀÎÀÚ ³Ñ±è: %s"
+
+#: eval.c:3085
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: ÇÔ¼ö¿¡ ÀûÀº ÀÎÀÚ ³Ñ±è: %s"
+
+#: eval.c:3086
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: ½ºÅ©¸³Æ® ÄÜÅؽºÆ® ¹Û¿¡¼­ <SID> »ç¿ë: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3687 gui.c:4382 gui_gtk.c:2059
+msgid "&Ok"
+msgstr "È®ÀÎ(&O)"
+
+#: eval.c:4226
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld ÁÙ: "
+
+#: eval.c:5477
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"È®ÀÎ(&O)\n"
+"Ãë¼Ò(&C)"
+
+#: eval.c:5517
+msgid "called inputrestore() more often than inputsave()"
+msgstr "inputrestore()°¡ inputsave()º¸´Ù ¸¹ÀÌ ºÒ·ÁÁ³½À´Ï´Ù"
+
+#: eval.c:5977
+msgid "E655: Too many symbolic links (cycle?)"
+msgstr "E655: ³Ê¹« ¸¹Àº ½Éº¼¸¯ ¸µÅ© (¹Ýº¹¼øȯ?)"
+
+#: eval.c:6626
+msgid "E240: No connection to Vim server"
+msgstr "E240: Vim ¼­¹ö¿¡ ¿¬°áµÇ¾î ÀÖÁö ¾Ê½À´Ï´Ù"
+
+#: eval.c:6724
+msgid "E277: Unable to read a server reply"
+msgstr "E277: ¼­¹öÀÇ ÀÀ´äÀ» ÀÐÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: eval.c:6752
+msgid "E258: Unable to send to client"
+msgstr "E258: Ŭ¶óÀ̾ðÆ®·Î º¸³¾ ¼ö ¾ø½À´Ï´Ù"
+
+#: eval.c:6800
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: %s(À¸)·Î º¸³¾ ¼ö ¾ø½À´Ï´Ù"
+
+#: eval.c:6900
+msgid "(Invalid)"
+msgstr "(À߸øµÇ¾ú½À´Ï´Ù)"
+
+#: eval.c:8078
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Á¤ÀÇ ¾È µÈ º¯¼ö: %s"
+
+#: eval.c:8510
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E461: ºñÁ¤»óÀûÀÎ º¯¼ö ¸í: %s"
+
+#: eval.c:8802
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: ÇÔ¼ö %sÀÌ(°¡) ÀÌ¹Ì ÀÖ½À´Ï´Ù, ¹Ù²Ù·Á¸é !À» ´õÇϼ¼¿ä"
+
+#: eval.c:8875
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Á¤ÀÇ ¾È µÈ ÇÔ¼ö: %s"
+
+#: eval.c:8888
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: '('°¡ ¾øÀ½: %s"
+
+#: eval.c:8921
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: À߸øµÈ ÀÎÀÚ: %s"
+
+#: eval.c:9000
+msgid "E126: Missing :endfunction"
+msgstr "E126: :endfunctionÀÌ ¾ø½À´Ï´Ù"
+
+#: eval.c:9107
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: ÇÔ¼ö %sÀ»(¸¦) ´Ù½Ã Á¤ÀÇÇÒ ¼ö ¾ø½À´Ï´Ù: »ç¿ëÁßÀÔ´Ï´Ù"
+
+#: eval.c:9177
+msgid "E129: Function name required"
+msgstr "E129: ÇÔ¼ö À̸§ÀÌ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: eval.c:9228
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: ÇÔ¼ö À̸§Àº ´ë¹®ÀÚ·Î ½ÃÀÛÇØ¾ß ÇÔ: %s"
+
+#: eval.c:9420
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Á¤ÀÇ ¾È µÈ ÇÔ¼ö: %s"
+
+#: eval.c:9425
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: ÇÔ¼ö %sÀ»(¸¦) Áö¿ï ¼ö ¾ø½À´Ï´Ù: »ç¿ëÁßÀÔ´Ï´Ù"
+
+#: eval.c:9473
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: ÇÔ¼ö¸¦ ºÎ¸¥ ±íÀÌ°¡ 'maxfuncdepth'º¸´Ù Å®´Ï´Ù"
+
+#. always scroll up, don't overwrite
+#: eval.c:9526
+#, c-format
+msgid "calling %s"
+msgstr "%s ºÎ¸£´Â Áß"
+
+#: eval.c:9588
+#, c-format
+msgid "%s aborted"
+msgstr "%sÀÌ(°¡) ÁßÁöµÇ¾ú½À´Ï´Ù"
+
+#: eval.c:9590
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%sÀÌ(°¡) #%ldÀ»(¸¦) µ¹·ÁÁÖ¾ú½À´Ï´Ù"
+
+#: eval.c:9597
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%sÀÌ(°¡) \"%s\"À»(¸¦) µ¹·ÁÁÖ¾ú½À´Ï´Ù"
+
+#. always scroll up, don't overwrite
+#: eval.c:9613 ex_cmds2.c:2365
+#, c-format
+msgid "continuing in %s"
+msgstr "%s¿¡¼­ °è¼Ó"
+
+#: eval.c:9639
+msgid "E133: :return not inside a function"
+msgstr "E133: :returnÀÌ ÇÔ¼ö ¾È¿¡ ÀÖÁö ¾Ê½À´Ï´Ù"
+
+#: eval.c:9970
+#, c-format
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# Àü¿ª º¯¼ö:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, ½ÊÀ°Áø %02x, ÆÈÁø %03o"
+
+#: ex_cmds.c:118
+#, c-format
+msgid "> %d, Hex %04x, Octal %o"
+msgstr "> %d, ½ÊÀ°Áø %04x, ÆÈÁø %o"
+
+#: ex_cmds.c:119
+#, c-format
+msgid "> %d, Hex %08x, Octal %o"
+msgstr "> %d, ½ÊÀ°Áø %08x, ÆÈÁø %o"
+
+#: ex_cmds.c:430
+msgid "E134: Move lines into themselves"
+msgstr "E134: ÁÙÀ» ±× ÀÚ½ÅÀ¸·Î À̵¿ÇÏ·Á°í Çß½À´Ï´Ù"
+
+#: ex_cmds.c:499
+msgid "1 line moved"
+msgstr "1 ÁÙ ¿Å°ÜÁ³½À´Ï´Ù"
+
+#: ex_cmds.c:501
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld ÁÙ ¿Å°ÜÁ³½À´Ï´Ù"
+
+#: ex_cmds.c:924
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld ÁÙÀ» °É·¶½À´Ï´Ù"
+
+#: ex_cmds.c:952
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *Filter* ÀÚµ¿¸í·ÉÀº ÇöÀç ¹öÆÛ¸¦ ¹Ù²Ù¾î¼­´Â ¾È µË´Ï´Ù"
+
+#: ex_cmds.c:1037
+msgid "[No write since last change]\n"
+msgstr "[¸¶Áö¸·À¸·Î °íÄ£ µÚ ÀúÀå ¾È ÇÔ]\n"
+
+#: ex_cmds.c:1283
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: ÁÙ¿¡ %s: "
+
+#: ex_cmds.c:1288
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: ³Ê¹« ¸¹Àº ¿¡·¯, ³ª¸ÓÁö °Ç³Ê¶Ü"
+
+#: ex_cmds.c:1323
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "viminfo ÆÄÀÏ \"%s\"%s%s%sÀ»(¸¦) Àд Áß"
+
+#: ex_cmds.c:1324
+msgid " info"
+msgstr " ÀÎÆ÷"
+
+#: ex_cmds.c:1325
+msgid " marks"
+msgstr " ¸¶Å©"
+
+#: ex_cmds.c:1326
+msgid " FAILED"
+msgstr " ½ÇÆÐ"
+
+#: ex_cmds.c:1418
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Viminfo ÆÄÀÏÀÇ ¾²±â ±ÇÇÑÀÌ ¾ø½À´Ï´Ù: %s"
+
+#: ex_cmds.c:1543
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Viminfo ÆÄÀÏ %sÀ»(¸¦) ¾µ ¼ö ¾ø½À´Ï´Ù!"
+
+#: ex_cmds.c:1551
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Viminfo ÆÄÀÏ \"%s\"À»(¸¦) ¾²´Â Áß"
+
+#. Write the info:
+#: ex_cmds.c:1649
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# ÀÌ viminfo ÆÄÀÏÀº ºöÀÌ ¸¸µç °ÍÀÔ´Ï´Ù Vim %s.\n"
+
+#: ex_cmds.c:1651
+#, c-format
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Á¶½É¸¸ ÇÑ´Ù¸é °íÄ¥ ¼öµµ ÀÖ½À´Ï´Ù!\n"
+"\n"
+
+#: ex_cmds.c:1653
+#, c-format
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# ÀÌ ÆÄÀÏÀÌ ÀúÀåµÇ¾úÀ» ¶§ÀÇ 'encoding'ÀÇ °ª\n"
+
+#: ex_cmds.c:1752
+msgid "Illegal starting char"
+msgstr "ÀÌ»óÇÑ ½ÃÀÛ ±ÛÀÚ"
+
+#: ex_cmds.c:2097 ex_cmds2.c:761
+msgid "Save As"
+msgstr "´Ù¸¥ À̸§À¸·Î ÀúÀå"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2140
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: ÆÄÀÏÀÌ ´Ù¸¥ ¹öÆÛ¿¡ ·ÎµùµÇ¾î ÀÖ½À´Ï´Ù"
+
+#: ex_cmds.c:2174
+msgid "Write partial file?"
+msgstr "ÆÄÀÏ ÀϺθ¸ ÀúÀåÇÒ±î¿ä?"
+
+#: ex_cmds.c:2181
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: ¹öÆÛ ÀϺθ¸ ¾²·Á¸é !À» »ç¿ëÇϽʽÿÀ"
+
+#: ex_cmds.c:2296
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "ÀÌ¹Ì ÀÖ´Â \"%.*s\" ÆÄÀÏÀ» µ¤¾î¾µ±î¿ä?"
+
+#: ex_cmds.c:2367
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: ¹öÆÛ %ldÀÇ ÆÄÀÏ À̸§ÀÌ ¾ø½À´Ï´Ù"
+
+#: ex_cmds.c:2406
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: ÆÄÀÏÀÌ ½áÁöÁö ¾ÊÀ½: 'write' ¿É¼Ç¿¡ ÀÇÇØ ¾µ ¼ö°¡ ¾ø½À´Ï´Ù"
+
+#: ex_cmds.c:2426
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"'readonly' ¿É¼ÇÀÌ \"%.*s\"¿¡ ´ëÇØ ¼³Á¤µÇ¾î ÀÖ½À´Ï´Ù.\n"
+"±×·¡µµ ¾²±â¸¦ ¿øÇϽʴϱî?"
+
+#: ex_cmds.c:2599
+msgid "Edit File"
+msgstr "ÆÄÀÏ °íÄ¡±â"
+
+#: ex_cmds.c:3207
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Autocommand°¡ ¶æ ¹Û¿¡ »õ ¹öÆÛ %sÀ»(¸¦) Áö¿ü½À´Ï´Ù"
+
+#: ex_cmds.c:3341
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: ¼ýÀÚ°¡ ¾Æ´Ñ ÀÎÀÚ°¡ :z¿¡ ÁÖ¾îÁ³½À´Ï´Ù"
+
+#: ex_cmds.c:3426
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: rvim¿¡¼­´Â ½© ¸í·ÉÀ» »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds.c:3533
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Á¤±ÔÇ¥Çö½ÄÀº ±ÛÀÚ·Î ±¸ºÐµÉ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds.c:3879
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "%s(À¸)·Î ¹Ù²Þ (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4272
+msgid "(Interrupted) "
+msgstr "(ÁߴܵǾú½À´Ï´Ù) "
+
+#: ex_cmds.c:4276
+msgid "1 substitution"
+msgstr "1 °³ ¹Ù²åÀ½"
+
+#: ex_cmds.c:4278
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld °³ ¹Ù²åÀ½"
+
+#: ex_cmds.c:4281
+msgid " on 1 line"
+msgstr " ÇÑ ÁÙ¿¡¼­"
+
+#: ex_cmds.c:4283
+#, c-format
+msgid " on %ld lines"
+msgstr " %ld ÁÙ¿¡¼­"
+
+#: ex_cmds.c:4334
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :globalÀº Àç±Í È£Ãâ µÉ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds.c:4369
+msgid "E148: Regular expression missing from global"
+msgstr "E148: global¿¡¼­ Á¤±ÔÇ¥Çö½ÄÀÌ ºüÁ³½À´Ï´Ù"
+
+#: ex_cmds.c:4418
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "¿©·¯ ÁÙ¿¡¼­ ÆÐÅÏÀ» ã¾Ò½À´Ï´Ù: %s"
+
+#: ex_cmds.c:4499
+#, c-format
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# ¸¶Áö¸·À¸·Î ¹Ù²Û ¹®ÀÚ¿­:\n"
+"$"
+
+#: ex_cmds.c:4600
+msgid "E478: Don't panic!"
+msgstr "E478: ´çȲÇÏÁö ¸¶½Ê½Ã¿À!"
+
+#: ex_cmds.c:4652
+#, c-format
+msgid "E661: Sorry, no '%s' help for %s"
+msgstr "E661: ¹Ì¾ÈÇÕ´Ï´Ù, µµ¿ò¸» '%s'ÀÌ(°¡) %s¿¡ ´ëÇØ ¾ø½À´Ï´Ù"
+
+#: ex_cmds.c:4655
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: ¹Ì¾ÈÇÕ´Ï´Ù, %s¿¡ ´ëÇÑ µµ¿ò¸»ÀÌ ¾ø½À´Ï´Ù"
+
+#: ex_cmds.c:4689
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "¹Ì¾ÈÇÕ´Ï´Ù, µµ¿ò¸» ÆÄÀÏ \"%s\"À»(¸¦) ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds.c:5172
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: ÀÚ·á¹æÀÌ ¾Æ´Ô: %s"
+
+#: ex_cmds.c:5311
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: ¾²±â À§ÇÑ %sÀ»(¸¦) ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds.c:5347
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Àбâ À§ÇÑ %sÀ»(¸¦) ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds.c:5369
+#, c-format
+msgid "E670: Mix of help file encodings within a language: %s"
+msgstr "E670: ÇÑ ¾ð¾î³»¿¡¼­ ¿©·¯ ÀÎÄÚµù »ç¿ë: %s"
+
+#: ex_cmds.c:5447
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: ÅÂ±× \"%s\"ÀÌ(°¡) ÆÄÀÏ %s¿¡ Áߺ¹µÇ¾î ÀÖ½À´Ï´Ù"
+
+#: ex_cmds.c:5559
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: ¸ð¸£´Â sign ¸í·É: %s"
+
+#: ex_cmds.c:5579
+msgid "E156: Missing sign name"
+msgstr "E156: sign À̸§ÀÌ ¾ø½À´Ï´Ù"
+
+#: ex_cmds.c:5625
+msgid "E612: Too many signs defined"
+msgstr "E612: ³Ê¹« ¸¹Àº signÀÌ Á¤ÀǵǾî ÀÖ½À´Ï´Ù"
+
+#: ex_cmds.c:5693
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: À߸øµÈ sign ÅؽºÆ®: %s"
+
+#: ex_cmds.c:5724 ex_cmds.c:5915
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: ¸ð¸£´Â sign: %s"
+
+#: ex_cmds.c:5773
+msgid "E159: Missing sign number"
+msgstr "E159: sign ¹øÈ£°¡ ¾ø½À´Ï´Ù"
+
+#: ex_cmds.c:5855
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: À߸øµÈ ¹öÆÛ À̸§: %s"
+
+#: ex_cmds.c:5894
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: À߸øµÈ sign ID: %ld"
+
+#: ex_cmds.c:5964
+msgid " (NOT FOUND)"
+msgstr " (¸ø ã¾ÒÀ½)"
+
+#: ex_cmds.c:5966
+msgid " (not supported)"
+msgstr " (Áö¿øµÇÁö ¾ÊÀ½)"
+
+#: ex_cmds.c:6065
+msgid "[Deleted]"
+msgstr "[Áö¿öÁ³½À´Ï´Ù]"
+
+#: ex_cmds2.c:92
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "µð¹ö±× »óÅ·Πµé¾î°¨. °è¼ÓÇÏ·Á¸é \"cont\"¸¦ ÀÔ·ÂÇϽʽÿÀ."
+
+#: ex_cmds2.c:96 ex_docmd.c:966
+#, c-format
+msgid "line %ld: %s"
+msgstr "%ld ÁÙ: %s"
+
+#: ex_cmds2.c:98
+#, c-format
+msgid "cmd: %s"
+msgstr "¸í·É: %s"
+
+#: ex_cmds2.c:290
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "ÁßÁöÁ¡: \"%s%s\" %ld ÁÙ"
+
+#: ex_cmds2.c:540
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: ÁßÁöÁ¡À» ãÀ» ¼ö ¾ø½À´Ï´Ù: %s"
+
+#: ex_cmds2.c:566
+msgid "No breakpoints defined"
+msgstr "ÁßÁöÁ¡ÀÌ Á¤ÀǵǾî ÀÖÁö ¾Ê½À´Ï´Ù"
+
+#: ex_cmds2.c:571
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s %ld ÁÙ"
+
+#: ex_cmds2.c:786
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "\"%.*s\"¿¡ ¹Ù²ï ³»¿ëÀ» ÀúÀåÇÒ±î¿ä?"
+
+#: ex_cmds2.c:788 ex_docmd.c:9379
+msgid "Untitled"
+msgstr "Á¦¸ñ ¾øÀ½"
+
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: ¹öÆÛ \"%s\"¿¡ ³ªÁß¿¡ ¹Ù²ï ³»¿ëÀÌ ½áÁöÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "°æ°í: ¶æ ¹Û¿¡ ´Ù¸¥ ¹öÆÛ·Î µé¾î°¬½À´Ï´Ù (autocommand¸¦ È®ÀÎÇϽʽÿÀ)"
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: °íÄ¥ ÆÄÀÏÀÌ Çϳª ¹Û¿¡ ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: ù ¹ø° ÆÄÀÏ ÀÌÀüÀ¸·Î´Â °¥ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: ¸¶Áö¸· ÆÄÀÏ µÚ·Î´Â °¥ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:1804
+#, c-format
+msgid "E666: compiler not supported: %s"
+msgstr "E666: ÄÄÆÄÀÏ·¯°¡ Áö¿øµÇÁö ¾ÊÀ½: %s"
+
+#: ex_cmds2.c:1897
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "\"%s\"À»(¸¦) \"%s\"¿¡¼­ ã´Â Áß"
+
+#: ex_cmds2.c:1919
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "\"%s\"À»(¸¦) ã´Â Áß"
+
+#: ex_cmds2.c:1940
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "'runtimepath'¿¡¼­ ãÀ» ¼ö ¾øÀ½: \"%s\""
+
+#: ex_cmds2.c:1974
+msgid "Source Vim script"
+msgstr "ºö ½ºÅ©¸³Æ® ·Îµå"
+
+#: ex_cmds2.c:2164
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "ÀÚ·á¹æÀº ºÒ·¯ µéÀÏ ¼ö ¾øÀ½: \"%s\""
+
+#: ex_cmds2.c:2202
+#, c-format
+msgid "could not source \"%s\""
+msgstr "\"%s\"À»(¸¦) ºÒ·¯ µéÀÏ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:2204
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "%ld ÁÙ: \"%s\"À»(¸¦) ºÒ·¯ µéÀÏ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:2218
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "\"%s\"À»(¸¦) ºÒ·¯µéÀÌ´Â Áß"
+
+#: ex_cmds2.c:2220
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "%ld ÁÙ: \"%s\" ºÒ·¯µéÀÌ´Â Áß"
+
+#: ex_cmds2.c:2363
+#, c-format
+msgid "finished sourcing %s"
+msgstr "%s ºÒ·¯µéÀ̱⠳¡"
+
+#: ex_cmds2.c:2707
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: °æ°í: À߸øµÈ ÁÙ ±¸ºÐÀÚ. ^MÀÌ ¾ø´Â °Í °°½À´Ï´Ù"
+
+#: ex_cmds2.c:2756
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :scriptencodingÀÌ ºÒ·¯µéÀÎ ÆÄÀÏ ¹Û¿¡¼­ »ç¿ëµÇ¾ú½À´Ï´Ù"
+
+#: ex_cmds2.c:2789
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish°¡ ºÒ·¯µéÀÎ ÆÄÀÏ ¹Û¿¡¼­ »ç¿ëµÇ¾ú½À´Ï´Ù"
+
+#: ex_cmds2.c:3238
+#, c-format
+msgid "Page %d"
+msgstr "ÆäÀÌÁö %d"
+
+#: ex_cmds2.c:3394
+msgid "No text to be printed"
+msgstr "ÀμâµÉ ÅؽºÆ®°¡ ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:3472
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "ÆäÀÌÁö %d ÀμâÁß (%d%%)"
+
+#: ex_cmds2.c:3484
+#, c-format
+msgid " Copy %d of %d"
+msgstr " º¹»ç %d / %d"
+
+#: ex_cmds2.c:3542
+#, c-format
+msgid "Printed: %s"
+msgstr "ÀμâµÊ: %s"
+
+#: ex_cmds2.c:3549
+#, c-format
+msgid "Printing aborted"
+msgstr "ÀμⰡ Ãë¼ÒµÇ¾ú½À´Ï´Ù."
+
+#: ex_cmds2.c:3914
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Æ÷½ºÆ®½ºÅ©¸³Æ® Ãâ·ÂÆÄÀÏ¿¡ ¾µ ¼ö ¾ø½À´Ï´Ù."
+
+#: ex_cmds2.c:4189
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E624: \"%s\" ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:4199 ex_cmds2.c:4824
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Æ÷½ºÆ®½ºÅ©¸³Æ® ¸®¼Ò½º ÆÄÀÏ \"%s\"À»(¸¦) ÀÐÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:4207
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: ÆÄÀÏ \"%s\"Àº(´Â) Æ÷½ºÆ®½ºÅ©¸³Æ® ¸®¼Ò½º ÆÄÀÏÀÌ ¾Æ´Õ´Ï´Ù"
+
+#: ex_cmds2.c:4222 ex_cmds2.c:4242 ex_cmds2.c:4257 ex_cmds2.c:4279
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: ÆÄÀÏ \"%s\"Àº(´Â) Áö¿øµÇ´Â Æ÷½ºÆ®½ºÅ©¸³Æ® ¸®¼Ò½º ÆÄÀÏÀÌ ¾Æ´Õ´Ï´Ù"
+
+#: ex_cmds2.c:4309
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: \"%s\" ¸®¼Ò½º ÆÄÀÏÀº ¹öÀüÀÌ À߸øµÇ¾ú½À´Ï´Ù"
+
+#: ex_cmds2.c:4776
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Æ÷½ºÆ®½ºÅ©¸³Æ® Ãâ·ÂÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:4809
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: \"%s\" ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:4928
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr "E456: Æ÷½ºÆ®½ºÅ©¸³Æ® ¸®¼Ò½º ÆÄÀÏ \"prolog.ps\"¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:4959
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: Æ÷½ºÆ®½ºÅ©¸³Æ® ¸®¼Ò½º ÆÄÀÏ \"%s.ps\"¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:4977
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr "E620: ´ÙÁß¹ÙÀÌÆ®¸¦ \"%s\" ÀÎÄÚµùÀ¸·Î º¯È¯ÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:5102
+msgid "Sending to printer..."
+msgstr "ÇÁ¸°ÅÍ·Î º¸³»´Â Áß..."
+
+#: ex_cmds2.c:5106
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: Æ÷½ºÆ®½ºÅ©¸³Æ® ÆÄÀÏÀ» ÀμâÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_cmds2.c:5108
+msgid "Print job sent."
+msgstr "ÀμâÀÛ¾÷ÀÌ ³¡³µ½À´Ï´Ù."
+
+#: ex_cmds2.c:5618
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "ÇöÀç %s¾ð¾î: \"%s\""
+
+#: ex_cmds2.c:5629
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: ¾ð¾î¸¦ \"%s\"(À¸)·Î ¼³Á¤ÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:525
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Ex »óÅ·ΠÀüȯ. Normal »óÅ·Π°¡·Á¸é \"visual\"À» ÀÔ·ÂÇϽʽÿÀ."
+
+#. must be at EOF
+#: ex_docmd.c:561
+msgid "E501: At end-of-file"
+msgstr "E501: ÆÄÀÏÀÇ ¸¶Áö¸·ÀÔ´Ï´Ù"
+
+#: ex_docmd.c:669
+msgid "E169: Command too recursive"
+msgstr "E169: ¸í·ÉÀÌ ³Ê¹« ¸¹ÀÌ ´Ù½Ã ¹Ýº¹µÇ¾ú½À´Ï´Ù"
+
+#: ex_docmd.c:1229
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: ¿¹¿Ü°¡ ¹ß»ýÇÏÁö ¾Ê¾Ò½À´Ï´Ù: %s"
+
+#: ex_docmd.c:1317
+msgid "End of sourced file"
+msgstr "ºÒ·¯µéÀÎ ÆÄÀÏÀÇ ¸¶Áö¸·"
+
+#: ex_docmd.c:1318
+msgid "End of function"
+msgstr "ÇÔ¼öÀÇ ¸¶Áö¸·"
+
+#: ex_docmd.c:1907
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: »ç¿ëÀÚ Á¤ÀÇ ¸í·ÉÀ» ¸ðÈ£ÇÏ°Ô »ç¿ëÇÏ°í ÀÖ½À´Ï´Ù"
+
+#: ex_docmd.c:1921
+msgid "E492: Not an editor command"
+msgstr "E492: ÆíÁý±â ¸í·ÉÀÌ ¾Æ´Õ´Ï´Ù"
+
+#: ex_docmd.c:2028
+msgid "E493: Backwards range given"
+msgstr "E493: ¹Ý´ë ¿µ¿ªÀÌ ÁÖ¾îÁ³½À´Ï´Ù"
+
+#: ex_docmd.c:2037
+msgid "Backwards range given, OK to swap"
+msgstr "¹Ý´ë ¿µ¿ªÀÌ ÁÖ¾îÁ³½À´Ï´Ù, µÚÁýÀ»±î¿ä"
+
+#: ex_docmd.c:2160
+msgid "E494: Use w or w>>"
+msgstr "E494: w³ª w>>¸¦ »ç¿ëÇϽʽÿÀ"
+
+#: ex_docmd.c:3786
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: ¹Ì¾ÈÇÕ´Ï´Ù, ±× ¸í·ÉÀº ÇöÀç ÆÇ¿¡¼­ »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:3989
+msgid "E172: Only one file name allowed"
+msgstr "E172: ¿À·ÎÁö ÇϳªÀÇ ÆÄÀÏ À̸§¸¸ »ç¿ë °¡´ÉÇÕ´Ï´Ù"
+
+#: ex_docmd.c:4569
+msgid "1 more file to edit. Quit anyway?"
+msgstr "°íÄ¥ ÆÄÀÏÀÌ ÇÑ °³ ´õ ÀÖ½À´Ï´Ù. ±×·¡µµ ³¡³¾±î¿ä?"
+
+#: ex_docmd.c:4572
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "°íÄ¥ ÆÄÀÏÀÌ %d °³ ´õ ÀÖ½À´Ï´Ù. ±×·¡µµ ³¡³¾±î¿ä?"
+
+#: ex_docmd.c:4579
+msgid "E173: 1 more file to edit"
+msgstr "E173: °íÄ¥ ÆÄÀÏÀÌ ÇÑ °³ ´õ ÀÖ½À´Ï´Ù"
+
+#: ex_docmd.c:4581
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: °íÄ¥ ÆÄÀÏÀÌ %ld °³ ´õ ÀÖ½À´Ï´Ù"
+
+#: ex_docmd.c:4676
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: ¸í·ÉÀÌ ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù: ¹Ù²Ù·Á¸é !À» ´õÇϼ¼¿ä"
+
+#: ex_docmd.c:4787
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" À̸§ ÀÎÀÚ ¹üÀ§ ¿Ï¼º Á¤ÀÇ"
+
+#: ex_docmd.c:4876
+msgid "No user-defined commands found"
+msgstr "»ç¿ëÀÚ Á¤ÀÇ ¸í·ÉÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:4908
+msgid "E175: No attribute specified"
+msgstr "E175: ¸í½ÃµÈ ¼Ó¼ºÀÌ ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:4960
+msgid "E176: Invalid number of arguments"
+msgstr "E176: À߸øµÈ ÀÎÀÚ °¹¼ö"
+
+#: ex_docmd.c:4975
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: Ä«¿îÆ®´Â µÎ ¹ø ÀÌ»ó ¸í½ÃµÉ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:4985
+msgid "E178: Invalid default value for count"
+msgstr "E178: À߸øµÈ ±âº» Ä«¿îÆ® °ª"
+
+#: ex_docmd.c:5016
+msgid "E179: argument required for complete"
+msgstr "E179: ³¡³»±â À§ÇØ ÀÎÀÚ°¡ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: ex_docmd.c:5048
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: À߸øµÈ ³¡³»±â °ª: %s"
+
+#: ex_docmd.c:5057
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr "E468: ¿Ï¼º ÀÎÀÚ´Â »ç¿ëÀÚ ¿Ï¼º¿¡¼­¸¸ Çã¿ëµË´Ï´Ù"
+
+#: ex_docmd.c:5063
+msgid "E467: Custom completion requires a function argument"
+msgstr "E467: »ç¿ëÀÚ ¿Ï¼ºÀº ÇÔ¼ö ÀÎÀÚ°¡ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: ex_docmd.c:5074
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: À߸øµÈ ¼Ó¼º: %s"
+
+#: ex_docmd.c:5117
+msgid "E182: Invalid command name"
+msgstr "E182: À߸øµÈ ¸í·É À̸§"
+
+#: ex_docmd.c:5132
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: »ç¿ëÀÚ Á¤ÀÇ ¸í·ÉÀº ´ë¹®ÀÚ·Î ½ÃÀÛÇØ¾ß ÇÕ´Ï´Ù"
+
+#: ex_docmd.c:5203
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: ±×·± »ç¿ëÀÚ Á¤ÀÇ ¸í·É ¾øÀ½: %s"
+
+#: ex_docmd.c:5664
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: »ö ½ºÅ´ %sÀ»(¸¦) ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:5672
+msgid "Greetings, Vim user!"
+msgstr "ºö »ç¿ëÀÚ´Ô, ȯ¿µÇÕ´Ï´Ù!"
+
+#: ex_docmd.c:6390
+msgid "Edit File in new window"
+msgstr "»õ â¿¡¼­ ÆÄÀÏ °íÄ¡±â"
+
+#: ex_docmd.c:6685
+msgid "No swap file"
+msgstr "½º¿Ò ÆÄÀÏÀÌ ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:6789
+msgid "Append File"
+msgstr "ÆÄÀÏ Ãß°¡"
+
+#: ex_docmd.c:6853
+msgid "E186: No previous directory"
+msgstr "E186: ÀÌÀü ÀÚ·á¹æÀÌ ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:6935
+msgid "E187: Unknown"
+msgstr "E187: ¸ð¸§"
+
+#: ex_docmd.c:7020
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: :winsize´Â µÎ°³ÀÇ ÀÎÀÚ°¡ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: ex_docmd.c:7076
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "â À§Ä¡: X %d, Y %d"
+
+#: ex_docmd.c:7081
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: ÀÌ Ç÷§Æû¿¡ ´ëÇÑ Ã¢ À§Ä¡ ¾ò´Â ±â´ÉÀ» ±¸ÇöµÇÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: ex_docmd.c:7091
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: :winpos¿¡´Â µÎ°³ÀÇ ÀÎÀÚ°¡ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: ex_docmd.c:7369
+msgid "Save Redirection"
+msgstr "¸®µð·º¼Ç ÀúÀå"
+
+#: ex_docmd.c:7559
+msgid "Save View"
+msgstr "º¸±â ÀúÀå"
+
+#: ex_docmd.c:7560
+msgid "Save Session"
+msgstr "¼¼¼Ç ÀúÀå"
+
+#: ex_docmd.c:7562
+msgid "Save Setup"
+msgstr "¼³Á¤ ÀúÀå"
+
+#: ex_docmd.c:7714
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\"ÀÌ(°¡) Á¸ÀçÇÕ´Ï´Ù (µ¤¾î¾²·Á¸é ! ´õÇϱâ)"
+
+#: ex_docmd.c:7719
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: ¾²±â À§ÇÑ \"%s\"À»(¸¦) ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#. set mark
+#: ex_docmd.c:7743
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: ÀÎÀÚ´Â ±ÛÀÚ³ª ¾Õ/µÚ ÀÎ¿ë ºÎÈ£¿©¾ß ÇÕ´Ï´Ù"
+
+#: ex_docmd.c:7785
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: :normalÀÇ Àç±Í È£ÃâÀÌ ³Ê¹« ¸¹ÀÌ »ý°å½À´Ï´Ù"
+
+#: ex_docmd.c:8303
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: '#'¿¡ ´ëÇØ Ä¡È¯ÇÒ ±³Ã¼ ÆÄÀÏ À̸§ÀÌ ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:8334
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: \"<afile>\"¿¡ ´ëÇØ Ä¡È¯ÇÒ ÀÚµ¿¸í·É ÆÄÀÏ À̸§ÀÌ ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:8342
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "E496: \"<abuf>\"¿¡ ´ëÇØ Ä¡È¯ÇÒ ÀÚµ¿¸í·É ¹öÆÛ ¹øÈ£°¡ ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:8353
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr "E497: \"<amatch>\"¿¡ ´ëÇØ Ä¡È¯ÇÒ ÀÚµ¿¸í·É ¸ÅÄ¡ À̸§ÀÌ ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:8363
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr "E498: \"<sfile>\"¿¡ ´ëÇØ Ä¡È¯ÇÒ :source ÆÄÀÏ À̸§ÀÌ ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:8404
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: '%'³ª '#'¿¡ ´ëÇÑ ºó ÆÄÀÏ À̸§, ¿À·ÎÁö \":p:h\"¿Í¸¸ µ¿ÀÛÇÕ´Ï´Ù"
+
+#: ex_docmd.c:8406
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: ºó ¹®ÀÚ¿­¿¡¼­ °ªÀ» ±¸ÇÏ·Á°í ÇÕ´Ï´Ù"
+
+#: ex_docmd.c:9361
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: ÀÐÀ» viminfo ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: ex_docmd.c:9534
+msgid "E196: No digraphs in this version"
+msgstr "E196: ÀÌ ÆÇ¿¡´Â digraph°¡ ¾ø½À´Ï´Ù"
+
+#: ex_eval.c:440
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr "E608: 'Vim' Á¢µÎ»ç·Î ¿¹¿Ü¸¦ :throwÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:529
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "¿¹¿Ü thrown: %s"
+
+#: ex_eval.c:576
+#, c-format
+msgid "Exception finished: %s"
+msgstr "¿¹¿Ü Á¾·áµÊ: %s"
+
+#: ex_eval.c:577
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "¿¹¿Ü ¹ö·ÁÁü: %s"
+
+#: ex_eval.c:620 ex_eval.c:664
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, %ld ÁÙ"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:638
+#, c-format
+msgid "Exception caught: %s"
+msgstr "¿¹¿Ü ¹ß»ý: %s"
+
+#: ex_eval.c:713
+#, c-format
+msgid "%s made pending"
+msgstr "%sÀÌ(°¡) pending µÇ¾ú½À´Ï´Ù"
+
+#: ex_eval.c:716
+#, c-format
+msgid "%s resumed"
+msgstr "%sÀÌ(°¡) Àç°³ µÇ¾ú½À´Ï´Ù"
+
+#: ex_eval.c:720
+#, c-format
+msgid "%s discarded"
+msgstr "%sÀÌ(°¡) ¹ö·ÁÁ³½À´Ï´Ù"
+
+#: ex_eval.c:746
+msgid "Exception"
+msgstr "¿¹¿Ü"
+
+#: ex_eval.c:752
+msgid "Error and interrupt"
+msgstr "¿¡·¯¿Í ÀÎÅÍ·´Æ®"
+
+#: ex_eval.c:754 gui.c:4381
+msgid "Error"
+msgstr "¿¡·¯"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:756
+msgid "Interrupt"
+msgstr "ÀÎÅÍ·´Æ®"
+
+#: ex_eval.c:830
+msgid "E579: :if nesting too deep"
+msgstr "E579: :if°¡ ³Ê¹« ±í°Ô ÁßøµÇ¾ú½À´Ï´Ù"
+
+#: ex_eval.c:867
+msgid "E580: :endif without :if"
+msgstr "E580: :if¾øÀÌ :endif°¡ ÀÖ½À´Ï´Ù"
+
+#: ex_eval.c:911
+msgid "E581: :else without :if"
+msgstr "E581: :if¾øÀÌ :else°¡ ÀÖ½À´Ï´Ù"
+
+#: ex_eval.c:914
+msgid "E582: :elseif without :if"
+msgstr "E582: :if¾øÀÌ :elseif°¡ ÀÖ½À´Ï´Ù"
+
+#: ex_eval.c:921
+msgid "E583: multiple :else"
+msgstr "E583: ¿©·¯°³ÀÇ :else°¡ ÀÖ½À´Ï´Ù"
+
+#: ex_eval.c:924
+msgid "E584: :elseif after :else"
+msgstr "E584: :else µÚ¿¡ :elseif°¡ ÀÖ½À´Ï´Ù"
+
+#: ex_eval.c:991
+msgid "E585: :while nesting too deep"
+msgstr "E585: :whileÀÌ ³Ê¹« ±í°Ô ÁßøµÇ¾ú½À´Ï´Ù"
+
+#: ex_eval.c:1047
+msgid "E586: :continue without :while"
+msgstr "E586: :while¾øÀÌ :continue°¡ ÀÖ½À´Ï´Ù"
+
+#: ex_eval.c:1087
+msgid "E587: :break without :while"
+msgstr "E587: :while¾øÀÌ :break°¡ ÀÖ½À´Ï´Ù"
+
+#: ex_eval.c:1286
+msgid "E601: :try nesting too deep"
+msgstr "E601: :try°¡ ³Ê¹« ±í°Ô ÁßøµÇ¾ú½À´Ï´Ù"
+
+#: ex_eval.c:1366
+msgid "E603: :catch without :try"
+msgstr "E603: :try¾øÀÌ :catch°¡ ÀÖ½À´Ï´Ù"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1388
+msgid "E604: :catch after :finally"
+msgstr "E604: :finally µÚ¿¡ :catch°¡ ÀÖ½À´Ï´Ù"
+
+#: ex_eval.c:1521
+msgid "E606: :finally without :try"
+msgstr "E606: :try¾øÀÌ :finally°¡ ÀÖ½À´Ï´Ù"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1545
+msgid "E607: multiple :finally"
+msgstr "E607: ¿©·¯°³ÀÇ :finally°¡ ÀÖ½À´Ï´Ù"
+
+#: ex_eval.c:1654
+msgid "E602: :endtry without :try"
+msgstr "E602: :try¾øÀÌ :endtry°¡ ÀÖ½À´Ï´Ù"
+
+#: ex_eval.c:1986
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunctionÀÌ function ³»¿¡ ¾ø½À´Ï´Ù"
+
+#: ex_getln.c:3296
+msgid "tagname"
+msgstr "ű×À̸§"
+
+#: ex_getln.c:3299
+msgid " kind file\n"
+msgstr " kind file\n"
+
+#: ex_getln.c:4765
+msgid "'history' option is zero"
+msgstr "'history' ¿É¼ÇÀÌ 0ÀÔ´Ï´Ù"
+
+#: ex_getln.c:5036
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s È÷½ºÅ丮 (»õ°ÍºÎÅÍ ¿À·¡µÈ °Í ¼ø):\n"
+
+#: ex_getln.c:5037
+msgid "Command Line"
+msgstr "¸í·É ÁÙ"
+
+#: ex_getln.c:5038
+msgid "Search String"
+msgstr "ãÀ» ¹®ÀÚ¿­"
+
+#: ex_getln.c:5039
+msgid "Expression"
+msgstr "Ç¥Çö"
+
+#: ex_getln.c:5040
+msgid "Input Line"
+msgstr "ÀÔ·Â ÁÙ"
+
+#: ex_getln.c:5078
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar°¡ ¸í·É ±æÀ̸¦ ¹þ¾î³µ½À´Ï´Ù"
+
+#: ex_getln.c:5255
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: È°¼ºµÈ âÀ̳ª ¹öÆÛ°¡ Áö¿öÁ³½À´Ï´Ù"
+
+#: fileio.c:377
+msgid "Illegal file name"
+msgstr "À߸øµÈ ÆÄÀÏ À̸§"
+
+#: fileio.c:401 fileio.c:535 fileio.c:2913 fileio.c:2954
+msgid "is a directory"
+msgstr "´Â ÀÚ·á¹æÀÔ´Ï´Ù"
+
+#: fileio.c:403
+msgid "is not a file"
+msgstr "´Â ÆÄÀÏÀÌ ¾Æ´Õ´Ï´Ù"
+
+#: fileio.c:557 fileio.c:4131
+msgid "[New File]"
+msgstr "[»õ ÆÄÀÏ]"
+
+#: fileio.c:590
+msgid "[Permission Denied]"
+msgstr "[Çã¿ë ¾È µË´Ï´Ù]"
+
+#: fileio.c:694
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre ÀÚµ¿¸í·ÉÀÌ ÆÄÀÏÀ» ÀÐÁö ¸øÇÏ°Ô ¸¸µé¾ú½À´Ï´Ù"
+
+#: fileio.c:696
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *ReadPre ÀÚµ¿¸í·ÉÀº ÇöÀç ¹öÆÛ¸¦ ¹Ù²Ù¸é ¾È µË´Ï´Ù"
+
+#: fileio.c:717
+msgid "Vim: Reading from stdin...\n"
+msgstr "ºö: Ç¥ÁØÀԷ¿¡¼­ Àд Áß...\n"
+
+#: fileio.c:723
+msgid "Reading from stdin..."
+msgstr "Ç¥ÁØÀԷ¿¡¼­ Àд Áß..."
+
+#. Re-opening the original file failed!
+#: fileio.c:1000
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: º¯È¯µÈ ÆÄÀÏÀ» ÀÐÀ» ¼ö°¡ ¾ø½À´Ï´Ù!"
+
+#: fileio.c:2090
+msgid "[fifo/socket]"
+msgstr "[ÇÇÆ÷/¼ÒÄÏ]"
+
+#: fileio.c:2097
+msgid "[fifo]"
+msgstr "[ÇÇÆ÷]"
+
+#: fileio.c:2104
+msgid "[socket]"
+msgstr "[¼ÒÄÏ]"
+
+#: fileio.c:2112
+msgid "[RO]"
+msgstr "[Àбâ Àü¿ë]"
+
+#: fileio.c:2122
+msgid "[CR missing]"
+msgstr "[CR ¾øÀ½]"
+
+#: fileio.c:2127
+msgid "[NL found]"
+msgstr "[NL Æ÷ÇÔ]"
+
+#: fileio.c:2132
+msgid "[long lines split]"
+msgstr "[±ä ÁÙ À߸²]"
+
+#: fileio.c:2138 fileio.c:4115
+msgid "[NOT converted]"
+msgstr "[º¯È¯ ¾È µË´Ï´Ù]"
+
+#: fileio.c:2143 fileio.c:4120
+msgid "[converted]"
+msgstr "[º¯È¯ µÇ¾ú½À´Ï´Ù]"
+
+#: fileio.c:2150 fileio.c:4145
+msgid "[crypted]"
+msgstr "[¾Ïȣȭ µÇ¾ú½À´Ï´Ù]"
+
+#: fileio.c:2157
+msgid "[CONVERSION ERROR]"
+msgstr "[º¯È¯ ¿¡·¯]"
+
+#: fileio.c:2163
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[%ld ÁÙ¿¡ À߸øµÈ ¹ÙÀÌÆ®]"
+
+#: fileio.c:2170
+msgid "[READ ERRORS]"
+msgstr "[Àб⠿¡·¯]"
+
+#: fileio.c:2386
+msgid "Can't find temp file for conversion"
+msgstr "º¯È¯Çϱâ À§ÇÑ Àӽà ÆÄÀÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:2393
+msgid "Conversion with 'charconvert' failed"
+msgstr "'charconvert'¸¦ »ç¿ëÇÑ º¯È¯ÀÌ ½ÇÆÐÇß½À´Ï´Ù"
+
+#: fileio.c:2396
+msgid "can't read output of 'charconvert'"
+msgstr "'charconvert'ÀÇ Ãâ·Â°á°ú¸¦ ÀÐÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:2796
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: ¾µ ¹öÆÛ¸¦ ÀÚµ¿¸í·ÉÀÌ Áö¿ì°Å³ª ´Ý¾Ò½À´Ï´Ù"
+
+#: fileio.c:2819
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Autocommand°¡ À߸øµÈ ¹æ¹ýÀ¸·Î ÁÙÀ» ¹Ù²Ù¾ú½À´Ï´Ù"
+
+#: fileio.c:2857
+msgid "NetBeans dissallows writes of unmodified buffers"
+msgstr "NetBeans¿¡¼­´Â ¹Ù²îÁö ¾ÊÀº ¹öÆÛ¸¦ ¾µ ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:2865
+msgid "Partial writes disallowed for NetBeans buffers"
+msgstr "NetBeans ¹öÆÛ¿¡ ´ëÇؼ­´Â ºÎºÐ ÀúÀåÀ» ÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:2919 fileio.c:2937
+msgid "is not a file or writable device"
+msgstr "ÆÄÀÏ È¤Àº ¾µ ¼ö ÀÖ´Â ÀåÄ¡°¡ ¾Æ´Õ´Ï´Ù"
+
+#: fileio.c:2989
+msgid "is read-only (add ! to override)"
+msgstr "Àбâ Àü¿ëÀÔ´Ï´Ù (µ¤¾î¾²·Á¸é ! ´õÇϱâ)"
+
+#: fileio.c:3335
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: ¹é¾÷ÆÄÀÏÀ» ¾µ ¼ö ¾ø½À´Ï´Ù (µ¤¾î¾²·Á¸é ! ´õÇϱâ)"
+
+#: fileio.c:3347
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr "E507: ¹é¾÷ÆÄÀÏ ´Ý±â ¿¡·¯ (µ¤¾î¾²·Á¸é ! ´õÇϱâ)"
+
+#: fileio.c:3349
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr "E508: ¹é¾÷ÇÒ ÆÄÀÏÀ» ÀÐÀ» ¼ö ¾ø½À´Ï´Ù (µ¤¾î¾²·Á¸é ! ´õÇϱâ)"
+
+#: fileio.c:3365
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: ¹é¾÷ÆÄÀÏÀ» ¸¸µé ¼ö ¾ø½À´Ï´Ù (µ¤¾î¾²·Á¸é ! ´õÇϱâ)"
+
+#: fileio.c:3468
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: ¹é¾÷ÆÄÀÏÀ» ¸¸µé ¼ö ¾ø½À´Ï´Ù (µ¤¾î¾²·Á¸é ! ´õÇϱâ)"
+
+#: fileio.c:3530
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr "E460: The resource fork will be lost (µ¤¾î¾²·Á¸é ! ´õÇϱâ)"
+
+#: fileio.c:3640
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: ¾µ Àӽà ÆÄÀÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:3658
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr "E213: º¯È¯ÇÒ ¼ö ¾ø½À´Ï´Ù (º¯È¯ ¾øÀÌ ÀúÀåÇÏ·Á¸é ! ´õÇϱâ)"
+
+#: fileio.c:3693
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: ¾µ ¿¬°áµÈ ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:3697
+msgid "E212: Can't open file for writing"
+msgstr "E212: ¾µ ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:3959
+msgid "E667: Fsync failed"
+msgstr "E667: Fsync°¡ ½ÇÆÐÇß½À´Ï´Ù"
+
+#: fileio.c:3966
+msgid "E512: Close failed"
+msgstr "E512: ´Ý±â°¡ ½ÇÆÐÇß½À´Ï´Ù"
+
+#: fileio.c:4037
+msgid "E513: write error, conversion failed"
+msgstr "E513: ¾²±â ¿¡·¯, º¯È¯ÀÌ ½ÇÆÐÇß½À´Ï´Ù"
+
+#: fileio.c:4043
+msgid "E514: write error (file system full?)"
+msgstr "E514: ¾²±â ¿¡·¯ (ÆÄÀÏ ½Ã½ºÅÛÀÌ ²Ëᳪ¿ä?)"
+
+#: fileio.c:4110
+msgid " CONVERSION ERROR"
+msgstr " º¯È¯ ¿¡·¯"
+
+#: fileio.c:4126
+msgid "[Device]"
+msgstr "[ÀåÄ¡]"
+
+#: fileio.c:4131
+msgid "[New]"
+msgstr "[»õ·Î¿î]"
+
+#: fileio.c:4153
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:4153
+msgid " appended"
+msgstr " ´õÇß½À´Ï´Ù"
+
+#: fileio.c:4155
+msgid " [w]"
+msgstr " [w]"
+
+#: fileio.c:4155
+msgid " written"
+msgstr " ÀúÀå Çß½À´Ï´Ù"
+
+#: fileio.c:4205
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: ÆÐÄ¡ »óÅÂ: ¿ø·¡ ÆÄÀÏÀ» ÀúÀåÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:4227
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: ÆÐÄ¡ »óÅÂ: ºó ¿ø·¡ ÆÄÀÏÀ» ¸¸µé ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:4242
+msgid "E207: Can't delete backup file"
+msgstr "E207: ¹é¾÷ ÆÄÀÏÀ» Áö¿ï ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:4306
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"°æ°í: ¿ø·¡ ÆÄÀÏÀÌ ¾ø¾îÁ³°Å³ª ±úÁ³À» ¼ö ÀÖ½À´Ï´Ù\n"
+
+#: fileio.c:4308
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "ÆÄÀÏÀÌ ¼º°øÀûÀ¸·Î ÀúÀåµÉ ¶§±îÁö ÆíÁý±â¸¦ ³¡³»Áö ¸¶½Ê½Ã¿À!"
+
+#: fileio.c:4397
+msgid "[dos]"
+msgstr "[µµ½º]"
+
+#: fileio.c:4397
+msgid "[dos format]"
+msgstr "[µµ½º Çü½Ä]"
+
+#: fileio.c:4404
+msgid "[mac]"
+msgstr "[¸Æ]"
+
+#: fileio.c:4404
+msgid "[mac format]"
+msgstr "[¸Æ Çü½Ä]"
+
+#: fileio.c:4411
+msgid "[unix]"
+msgstr "[À¯´Ð½º]"
+
+#: fileio.c:4411
+msgid "[unix format]"
+msgstr "[À¯´Ð½º Çü½Ä]"
+
+#: fileio.c:4438
+msgid "1 line, "
+msgstr "1 ÁÙ, "
+
+#: fileio.c:4440
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld ÁÙ, "
+
+#: fileio.c:4443
+msgid "1 character"
+msgstr "1 ±ÛÀÚ"
+
+#: fileio.c:4445
+#, c-format
+msgid "%ld characters"
+msgstr "%ld ±ÛÀÚ"
+
+#: fileio.c:4455
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:4455
+msgid "[Incomplete last line]"
+msgstr "[ºÒ¿ÏÀüÇÑ ¸¶Áö¸· ÁÙ]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4474
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "°æ°í: ÆÄÀÏÀÌ ÀÐÀº µÚ¿¡ ¹Ù²î¾ú½À´Ï´Ù!!!"
+
+#: fileio.c:4476
+msgid "Do you really want to write to it"
+msgstr "Á¤¸»·Î ¾²±â¸¦ ¿øÇϽʴϱî"
+
+#: fileio.c:5726
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: \"%s\"¿¡ ¾²±â ¿¡·¯"
+
+#: fileio.c:5733
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: \"%s\" ´Ý±â ¿¡·¯"
+
+#: fileio.c:5736
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: \"%s\" Àб⠿¡·¯"
+
+#: fileio.c:5970
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: FileChangedShell ÀÚµ¿¸í·ÉÀÌ ¹öÆÛ¸¦ Áö¿ü½À´Ï´Ù"
+
+#: fileio.c:5977
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: °æ°í: ÆÄÀÏ \"%s\"À»(¸¦) ´õ ÀÌ»ó »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:5991
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: °æ°í: ÆÄÀÏ \"%s\"ÀÌ(°¡) ¹Ù²î¾ú°í ¸¶Âù°¡Áö·Î ºöÀÇ ¹öÆÛµµ ¹Ù²î¾ú½À´Ï´Ù"
+
+#: fileio.c:5994
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: °æ°í: ÆÄÀÏ \"%s\"ÀÌ(°¡) °íÄ¡±â ½ÃÀÛÇÑ µÚ¿¡ ¹Ù²î¾ú½À´Ï´Ù"
+
+#: fileio.c:5996
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: °æ°í: ÆÄÀÏ \"%s\"ÀÇ »óÅ°¡ °íÄ¡±â ½ÃÀÛÇÑ µÚ¿¡ ¹Ù²î¾ú½À´Ï´Ù"
+
+#: fileio.c:6006
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: °æ°í: ÆÄÀÏ \"%s\"ÀÌ(°¡) °íÄ¡±â ½ÃÀÛÇÑ µÚ¿¡ ¸¸µé¾ú½À´Ï´Ù"
+
+#: fileio.c:6019
+msgid "See \":help W11\" for more info."
+msgstr "´õ ¸¹Àº Á¤º¸¸¦ º¸·Á¸é \":help W11\"À» ÀÔ·ÂÇϼ¼¿ä."
+
+#: fileio.c:6033
+msgid "Warning"
+msgstr "°æ°í"
+
+#: fileio.c:6034
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"È®ÀÎ(&O)\n"
+"ÆÄÀÏ ºÒ·¯¿À±â(&L)"
+
+#: fileio.c:6140
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: \"%s\"ÀÇ Àç·Îµå¸¦ ÁغñÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:6159
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: \"%s\"À»(¸¦) ´Ù½Ã ·ÎµåÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:6740
+msgid "--Deleted--"
+msgstr "--Áö¿öÁü--"
+
+#. the group doesn't exist
+#: fileio.c:6900
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: ÀÌ·± ±×·ì ¾øÀ½: \"%s\""
+
+#: fileio.c:7026
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: * µÚ¿¡ ÀÌ»óÇÑ ±ÛÀÚ: %s"
+
+#: fileio.c:7038
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: ±×·± À̺¥Æ® ¾øÀ½: %s"
+
+#: fileio.c:7040
+#, c-format
+msgid "E216: No such group or event: %s"
+msgstr "E216: ±×·± ±×·ìÀ̳ª À̺¥Æ® ¾øÀ½: %s"
+
+#. Highlight title
+#: fileio.c:7198
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- ÀÚµ¿-¸í·É ---"
+
+#: fileio.c:7469
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: ALL À̺¥Æ®¿¡ ´ëÇØ ÀÚµ¿¸í·ÉÀ» ½ÇÇàÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: fileio.c:7492
+msgid "No matching autocommands"
+msgstr "¸Â´Â ÀÚµ¿¸í·ÉÀÌ ¾ø½À´Ï´Ù"
+
+#: fileio.c:7813
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: ÀÚµ¿¸í·ÉÀÌ ³Ê¹« ±í°Ô ÁßøµÇ¾ú½À´Ï´Ù"
+
+#: fileio.c:8088
+#, c-format
+#~ msgid "%s Auto commands for \"%s\""
+#~ msgstr ""
+
+#: fileio.c:8096
+#, c-format
+msgid "Executing %s"
+msgstr "%s ½ÇÇàÁß"
+
+#. always scroll up, don't overwrite
+#: fileio.c:8164
+#, c-format
+msgid "autocommand %s"
+msgstr "ÀÚµ¿¸í·É %s"
+
+#: fileio.c:8731
+msgid "E219: Missing {."
+msgstr "E219: {°¡ ¾ø½À´Ï´Ù."
+
+#: fileio.c:8733
+msgid "E220: Missing }."
+msgstr "E220: }°¡ ¾ø½À´Ï´Ù."
+
+#: fold.c:68
+msgid "E490: No fold found"
+msgstr "E490: fold°¡ ¾ø½À´Ï´Ù"
+
+#: fold.c:593
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: ÇöÀçÀÇ 'foldmethod'À¸·Î Á¢±â¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù"
+
+#: fold.c:595
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: ÇöÀçÀÇ 'foldmethod'À¸·Î Á¢±â¸¦ Áö¿ï ¼ö ¾ø½À´Ï´Ù"
+
+#: getchar.c:248
+msgid "E222: Add to read buffer"
+msgstr "E222: ÀÐÇôÁø ¹öÆÛ¿¡ ´õÇϱâ"
+
+#: getchar.c:2208
+msgid "E223: recursive mapping"
+msgstr "E223: Àç±Í ¸ÊÇÎ"
+
+#: getchar.c:3087
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: %s Àü¿ª ¾à¾î°¡ ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù"
+
+#: getchar.c:3090
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: %s Àü¿ª ¸ÅÇÎÀÌ ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù"
+
+#: getchar.c:3222
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: %s ¾à¾î°¡ ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù"
+
+#: getchar.c:3225
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: %s ¸ÅÇÎÀÌ ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù"
+
+#: getchar.c:3289
+msgid "No abbreviation found"
+msgstr "¾à¾î¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: getchar.c:3291
+msgid "No mapping found"
+msgstr "¸ÊÇÎÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: getchar.c:4183
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: ÀÌ»óÇÑ »óÅÂ"
+
+#: gui.c:220
+msgid "E229: Cannot start the GUI"
+msgstr "E229: GUI¸¦ ½ÃÀÛÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: gui.c:349
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: \"%s\"¿¡¼­ ÀÐÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: gui.c:472
+msgid "E665: Cannot start GUI, no valid font found"
+msgstr "E665: ¾µ¸¸ÇÑ ±Û²ÃÀ» ãÀ» ¼ö ¾ø¾î¼­ GUI¸¦ ½ÇÇàÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: gui.c:477
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: 'guifontwide'°¡ ÀÌ»óÇÕ´Ï´Ù"
+
+#: gui.c:547
+msgid "E599: Value of 'imactivatekey' is invalid"
+msgstr "E599: 'imactivatekey' °ªÀÌ ÀÌ»óÇÕ´Ï´Ù"
+
+#: gui.c:4061
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: »ö %sÀ»(¸¦) ÇÒ´çÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<¿­ ¼ö ¾øÀ½> "
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: ±Û²Ã %sÀ»(¸¦) ¾òÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: ÇöÀç µð·ºÅ丮·Î µ¹¾Æ°¥ ¼ö ¾ø½À´Ï´Ù"
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "°æ·Î À̸§:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: ÇöÀç µð·ºÅ丮¸¦ ¾òÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "È®ÀÎ"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2731 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "Ãë¼Ò"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "½ºÅ©·Ñ¹Ù À§Á¬: ½æ ÇȽº¸ÊÀÇ Áö¿À¹ÌÆ®¸®¸¦ ¾òÀ» ¼ö ¾ø½À´Ï´Ù."
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "ºö ´ëÈ­»óÀÚ"
+
+#: gui_beval.c:101 gui_w32.c:3954
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: ¸Þ½ÃÁö¿Í ÄÝ¹é ¸ðµÎ¸¦ »ç¿ëÇؼ­´Â BalloonEvalÀ» ¸¸µé ¼ö ¾ø½À´Ï´Ù"
+
+#: gui_gtk.c:1607
+msgid "Vim dialog..."
+msgstr "ºö ´ëÈ­»óÀÚ..."
+
+#: gui_gtk.c:2060 message.c:2999
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"¿¹(&Y)\n"
+"¾Æ´Ï¿À(&N)\n"
+"Ãë¼Ò(&C)"
+
+#: gui_gtk.c:2268
+msgid "Input _Methods"
+msgstr "ÀÔ·Â ¹æ¹ý(_M)"
+
+#: gui_gtk.c:2534 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "ºö - ã¾Æ¼­ ¹Ù²Ù±â..."
+
+#: gui_gtk.c:2542 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "ºö - ã±â..."
+
+#: gui_gtk.c:2574 gui_motif.c:2888
+msgid "Find what:"
+msgstr "¹«¾ó ãÀ»±î¿ä:"
+
+#: gui_gtk.c:2592 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "¹Ù²Ü ¹®ÀÚ¿­:"
+
+#. whole word only button
+#: gui_gtk.c:2624 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "¶È°°Àº ³¹¸»¸¸"
+
+#. match case button
+#: gui_gtk.c:2635 gui_motif.c:3048
+#~ msgid "Match case"
+#~ msgstr ""
+
+#: gui_gtk.c:2645 gui_motif.c:2990
+msgid "Direction"
+msgstr "¹æÇâ"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2657 gui_motif.c:3002
+msgid "Up"
+msgstr "À§·Î"
+
+#: gui_gtk.c:2661 gui_motif.c:3010
+msgid "Down"
+msgstr "¾Æ·¡·Î"
+
+#: gui_gtk.c:2683 gui_gtk.c:2685 gui_motif.c:2792
+msgid "Find Next"
+msgstr "´ÙÀ½ ã±â"
+
+#: gui_gtk.c:2702 gui_gtk.c:2704 gui_motif.c:2809
+msgid "Replace"
+msgstr "¹Ù²Ù±â"
+
+#: gui_gtk.c:2715 gui_gtk.c:2717 gui_motif.c:2822
+msgid "Replace All"
+msgstr "¸ðµÎ ¹Ù²Ù±â"
+
+#: gui_gtk_x11.c:2327
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "ºö: ¼¼¼Ç °ü¸®ÀڷκÎÅÍ \"die\" ¿äûÀ» ¹Þ¾Ò½À´Ï´Ù\n"
+
+#: gui_gtk_x11.c:3519
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "ºö: ¸ÞÀΠâÀÌ Á×°Ô µÉ °ÍÀÔ´Ï´Ù\n"
+
+#: gui_gtk_x11.c:4138
+msgid "Font Selection"
+msgstr "±Û²Ã °í¸£±â"
+
+#: gui_gtk_x11.c:6035 ui.c:2120
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "ºó °í¸£±â ´ë½Å CUT_BUFFER0À» »ç¿ëÇß½À´Ï´Ù"
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "°Å¸£°³"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "ÀÚ·á¹æ"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "µµ¿ò¸»"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "ÆÄÀÏ"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "°í¸£±â"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "Ãë¼Ò"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: Zap ±Û²Ã '%s'À»(¸¦) ·ÎµåÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: ±Û²Ã %sÀ»(¸¦) »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"ÀÚ½Ä ÇÁ·Î¼¼½º¸¦ ³¡³»±â À§ÇØ ¸Þ½ÃÁö¸¦ º¸³Â½À´Ï´Ù.\n"
+
+#: gui_w32.c:843
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Áö¿øµÇÁö ¾Ê´Â ÀÎÀÚ: \"-%s\": OLE ÆÇÀ» »ç¿ëÇϽʽÿÀ."
+
+#: gui_w48.c:2163
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "¹®ÀÚ¿­ ã±â ('\\'¸¦ ãÀ¸·Á¸é '\\\\' »ç¿ë)"
+
+#: gui_w48.c:2188
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "¹®ÀÚ¿­ ã¾Æ ¹Ù²Ù±â ('\\'¸¦ ãÀ¸·Á¸é '\\\\' »ç¿ë)"
+
+#: gui_x11.c:1537
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"ºö E458: »ö»ó¸Ê ¿£Æ®¸®¸¦ ÇÒ´çÇÒ ¼ö ¾ø½À´Ï´Ù, ¸î¸î »öÀÌ À߸øµÉ ¼ö ÀÖ½À´Ï´Ù"
+
+#: gui_x11.c:2118
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: ´ÙÀ½ ±ÛÀÚ¼ÂÀÇ ±Û²ÃÀÌ ±Û²Ã¼Â %s¿¡ ¾ø½À´Ï´Ù:"
+
+#: gui_x11.c:2161
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: ±Û²Ã¼Â À̸§: %s"
+
+#: gui_x11.c:2162
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "±Û²Ã '%s'Àº(´Â) °íÁ¤³ÐÀÌ°¡ ¾Æ´Õ´Ï´Ù"
+
+#: gui_x11.c:2181
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: ±Û²Ã¼Â À̸§: %s\n"
+
+#: gui_x11.c:2182
+#, c-format
+msgid "Font0: %s\n"
+msgstr "±Û²Ã0: %s\n"
+
+#: gui_x11.c:2183
+#, c-format
+msgid "Font1: %s\n"
+msgstr "±Û²Ã1: %s\n"
+
+#: gui_x11.c:2184
+#, c-format
+msgid "Font%ld width is not twice that of font0\n"
+msgstr "±Û²Ã%ld ³Êºñ°¡ ±Û²Ã0ÀÇ µÎ¹è°¡ ¾Æ´Õ´Ï´Ù\n"
+
+#: gui_x11.c:2185
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "±Û²Ã0 ³Êºñ: %ld\n"
+
+#: gui_x11.c:2186
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"±Û²Ã1 ³Êºñ: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: ÇÑ±Û ¿ÀÅ丶Ÿ ¿¡·¯"
+
+#: if_cscope.c:77
+msgid "Add a new database"
+msgstr "»õ µ¥ÀÌÅͺ£À̽º ´õÇϱâ"
+
+#: if_cscope.c:79
+#~ msgid "Query for a pattern"
+#~ msgstr ""
+
+#: if_cscope.c:81
+msgid "Show this message"
+msgstr "ÀÌ ¸Þ½ÃÁö º¸À̱â"
+
+#: if_cscope.c:83
+msgid "Kill a connection"
+msgstr "¿¬°á ²÷±â"
+
+#: if_cscope.c:85
+msgid "Reinit all connections"
+msgstr "¸ðµç ¿¬°á ´Ù½Ã ÃʱâÈ­"
+
+#: if_cscope.c:87
+msgid "Show connections"
+msgstr "¿¬°á º¸¿©ÁÖ±â"
+
+#: if_cscope.c:95
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: »ç¿ë¹ý: cs[cope] %s"
+
+#: if_cscope.c:124
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "ÀÌ cscope ¸í·ÉÀº â ³ª´©±â¸¦ Áö¿øÇÏÁö ¾Ê½À´Ï´Ù.\n"
+
+#: if_cscope.c:175
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: »ç¿ë¹ý: cstag <ident>"
+
+#: if_cscope.c:231
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: ű׸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: if_cscope.c:409
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: stat(%s) ¿¡·¯: %d"
+
+#: if_cscope.c:419
+msgid "E563: stat error"
+msgstr "E563: stat ¿¡·¯"
+
+#: if_cscope.c:516
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %sÀº(´Â) µð·ºÅ丮µµ ȤÀº cscope µ¥ÀÌÅͺ£À̽º°¡ ¾Æ´Õ´Ï´Ù"
+
+#: if_cscope.c:534
+#, c-format
+msgid "Added cscope database %s"
+msgstr "cscope µ¥ÀÌÅͺ£À̽º %s¿¡ ´õÇß½À´Ï´Ù."
+
+#: if_cscope.c:589
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: cscope ¿¬°á %ld Àб⠿¡·¯"
+
+#: if_cscope.c:694
+msgid "E561: unknown cscope search type"
+msgstr "E561: ¸ð¸£´Â cscope ã±â Çü½Ä"
+
+#: if_cscope.c:736
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: cscope ÆÄÀÌÇÁ¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù"
+
+#: if_cscope.c:753
+msgid "E622: Could not fork for cscope"
+msgstr "E622: cscope¸¦ forkÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: if_cscope.c:847 if_cscope.c:897
+msgid "cs_create_connection exec failed"
+msgstr "cs_create_connection ½ÇÇàÀÌ ½ÇÆÐÇß½À´Ï´Ù"
+
+#: if_cscope.c:898
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: cscope ÇÁ·Î¼¼½º¸¦ spawnÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: if_cscope.c:911
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: to_fp¿¡ ´ëÇÑ fdopen ½ÇÆÐ"
+
+#: if_cscope.c:913
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fr_fp¿¡ ´ëÇÑ fdopen ½ÇÆÐ"
+
+#: if_cscope.c:951
+msgid "E567: no cscope connections"
+msgstr "E567: cscope ¿¬°áÀÌ ¾ø½À´Ï´Ù"
+
+#: if_cscope.c:1025
+#, c-format
+#~ msgid "E259: no matches found for cscope query %s of %s"
+#~ msgstr ""
+
+#: if_cscope.c:1082
+#, c-format
+#~ msgid "E469: invalid cscopequickfix flag %c for %c"
+#~ msgstr ""
+
+#: if_cscope.c:1152
+msgid "cscope commands:\n"
+msgstr "cscope ¸í·É:\n"
+
+#: if_cscope.c:1155
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (»ç¿ë¹ý: %s)"
+
+#: if_cscope.c:1253
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: cscope µ¥ÀÌÅͺ£À̽º¸¦ ¿­ ¼ö ¾øÀ½: %s"
+
+#: if_cscope.c:1271
+msgid "E626: cannot get cscope database information"
+msgstr "E626: cscope µ¥ÀÌÅͺ£À̽º Á¤º¸¸¦ ¾òÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: if_cscope.c:1296
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: Áߺ¹µÈ cscope µ¥ÀÌÅͺ£À̽º´Â ´õÇØÁöÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: if_cscope.c:1307
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: cscope ¿¬°á Çã¿ëÄ¡ÀÇ ÃÖ´ë °ª¿¡ µµ´ÞÇß½À´Ï´Ù"
+
+#: if_cscope.c:1424
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: cscope ¿¬°á %sÀ»(¸¦) ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: if_cscope.c:1458
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "cscope ¿¬°á %sÀÌ(°¡) ´ÝÇû½À´Ï´Ù"
+
+#. should not reach here
+#: if_cscope.c:1598
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: cs_manage_matches¿¡ ½É°¢ÇÑ ¿¡·¯"
+
+#: if_cscope.c:1848
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "Cscope ű×: %s"
+
+#: if_cscope.c:1870
+msgid ""
+"\n"
+" # line"
+msgstr ""
+"\n"
+" # ÁÙ"
+
+#: if_cscope.c:1872
+msgid "filename / context / line\n"
+msgstr "ÆÄÀÏ À̸§ / ÄÜÅؽºÆ® / ÁÙ\n"
+
+#: if_cscope.c:1990
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: Cscope ¿¡·¯: %s"
+
+#: if_cscope.c:2176
+msgid "All cscope databases reset"
+msgstr "¸ðµç cscope µ¥ÀÌÅͺ£À̽º ¸®¼Â"
+
+#: if_cscope.c:2244
+msgid "no cscope connections\n"
+msgstr "cscope ¿¬°áÀÌ ¾ø½À´Ï´Ù\n"
+
+#: if_cscope.c:2248
+msgid " # pid database name prepend path\n"
+msgstr " # pid µ¥ÀÌÅͺ£À̽º À̸§ prepend path\n"
+
+#: if_python.c:436
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: ¹Ì¾ÈÇÕ´Ï´Ù, ÀÌ ¸í·ÉÀº »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù, ÆÄÀ̽㠶óÀ̺귯¸®¸¦ ·ÎµùÇÒ "
+"¼ö ¾ø½À´Ï´Ù."
+
+#: if_python.c:500
+msgid "E659: Cannot invoke Python recursively"
+msgstr "E659: PythonÀ» Àç±ÍÈ£ÃâÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: if_python.c:701
+msgid "can't delete OutputObject attributes"
+msgstr "OutputObject ¼Ó¼ºÀ» Áö¿ï ¼ö ¾ø½À´Ï´Ù"
+
+#: if_python.c:708
+msgid "softspace must be an integer"
+msgstr "softspace´Â Á¤¼ö¿©¾ß¸¸ ÇÕ´Ï´Ù"
+
+#: if_python.c:716
+msgid "invalid attribute"
+msgstr "À߸øµÈ ¼Ó¼º"
+
+#: if_python.c:755 if_python.c:769
+msgid "writelines() requires list of strings"
+msgstr "writelines()´Â ¹®ÀÚ¿­ ¸ñ·ÏÀÌ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: if_python.c:895
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: ÆÄÀ̽ã: I/O °´Ã¼ ÃʱâÈ­Áß ¿¡·¯°¡ »ý°å½À´Ï´Ù"
+
+#: if_python.c:1080 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "À߸øµÈ Ç¥Çö½Ä"
+
+#: if_python.c:1094 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "Ç¥Çö½ÄÀ» Áö¿øÇÏÁö ¾Êµµ·Ï ÄÄÆÄÀÏ µÇ¾ú½À´Ï´Ù"
+
+#: if_python.c:1107
+msgid "attempt to refer to deleted buffer"
+msgstr "Áö¿öÁø ¹öÆÛ¸¦ ÂüÁ¶ÇÏ·Á°í ÇÏ¿´½À´Ï´Ù"
+
+#: if_python.c:1122 if_python.c:1163 if_python.c:1227 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "ÁÙ ¹øÈ£°¡ ¹üÀ§¸¦ ¹þ¾î³µ½À´Ï´Ù"
+
+#: if_python.c:1362
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<%8lX¿¡ ¹öÆÛ °´Ã¼ (Áö¿öÁ³½À´Ï´Ù)>"
+
+#: if_python.c:1453 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "À߸øµÈ ¸¶Å© À̸§"
+
+#: if_python.c:1733
+msgid "no such buffer"
+msgstr "±×·± ¹öÆÛ´Â ¾ø½À´Ï´Ù"
+
+#: if_python.c:1821
+msgid "attempt to refer to deleted window"
+msgstr "Áö¿öÁø âÀ» ÂüÁ¶ÇÏ·Á°í ÇÏ¿´½À´Ï´Ù"
+
+#: if_python.c:1866
+msgid "readonly attribute"
+msgstr "Àбâ Àü¿ë ¼Ó¼º"
+
+#: if_python.c:1879
+msgid "cursor position outside buffer"
+msgstr "ÆÛ¼­ À§Ä¡°¡ ¹öÆÛ ¹Û¿¡ ÀÖ½À´Ï´Ù"
+
+#: if_python.c:1956
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<%.8lX¿¡ â °´Ã¼ (Áö¿öÁ³½À´Ï´Ù)>"
+
+#: if_python.c:1968
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<%.8lX¿¡ â °´Ã¼ (¸ð¸§)>"
+
+#: if_python.c:1970
+#, c-format
+msgid "<window %d>"
+msgstr "<â %d>"
+
+#: if_python.c:2046
+msgid "no such window"
+msgstr "±×·± âÀº ¾ø½À´Ï´Ù"
+
+#: if_python.c:2307 if_python.c:2341 if_python.c:2396 if_python.c:2464
+#: if_python.c:2586 if_python.c:2638 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "undo Á¤º¸¸¦ ÀúÀåÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: if_python.c:2309 if_python.c:2403 if_python.c:2475
+msgid "cannot delete line"
+msgstr "ÁÙÀ» Áö¿ï ¼ö ¾ø½À´Ï´Ù"
+
+#: if_python.c:2346 if_python.c:2491 if_tcl.c:690 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "ÁÙÀ» ¹Ù²Ü ¼ö ¾ø½À´Ï´Ù"
+
+#: if_python.c:2509 if_python.c:2588 if_python.c:2646
+msgid "cannot insert line"
+msgstr "ÁÙÀ» ³¢¿ö³ÖÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: if_python.c:2750
+msgid "string cannot contain newlines"
+msgstr "¹®ÀÚ¿­Àº newlineÀ» Æ÷ÇÔÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: if_ruby.c:422
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: ¹Ì¾ÈÇÕ´Ï´Ù, ÀÌ ¸í·ÉÀº »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù, ·çºñ ¶óÀ̺귯¸®¸¦ ·ÎµùÇÒ ¼ö "
+"¾ø½À´Ï´Ù."
+
+#: if_ruby.c:485
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: ¸ð¸£´Â longjmp »óÅ %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Åä±Û ±¸Çö/Á¤ÀÇ"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "...ÀÇ ±âº» Ŭ·¡½º º¸¿©ÁÖ±â"
+
+#: if_sniff.c:69
+#~ msgid "Show overridden member function"
+#~ msgstr ""
+
+#: if_sniff.c:70
+#~ msgid "Retrieve from file"
+#~ msgstr ""
+
+#: if_sniff.c:71
+#~ msgid "Retrieve from project"
+#~ msgstr ""
+
+#: if_sniff.c:73
+#~ msgid "Retrieve from all projects"
+#~ msgstr ""
+
+#: if_sniff.c:74
+#~ msgid "Retrieve"
+#~ msgstr ""
+
+#: if_sniff.c:75
+#~ msgid "Show source of"
+#~ msgstr ""
+
+#: if_sniff.c:76
+#~ msgid "Find symbol"
+#~ msgstr ""
+
+#: if_sniff.c:77
+#~ msgid "Browse class"
+#~ msgstr ""
+
+#: if_sniff.c:78
+#~ msgid "Show class in hierarchy"
+#~ msgstr ""
+
+#: if_sniff.c:79
+#~ msgid "Show class in restricted hierarchy"
+#~ msgstr ""
+
+#: if_sniff.c:80
+#~ msgid "Xref refers to"
+#~ msgstr ""
+
+#: if_sniff.c:81
+#~ msgid "Xref referred by"
+#~ msgstr ""
+
+#: if_sniff.c:82
+#~ msgid "Xref has a"
+#~ msgstr ""
+
+#: if_sniff.c:83
+#~ msgid "Xref used by"
+#~ msgstr ""
+
+#: if_sniff.c:84
+#~ msgid "Show docu of"
+#~ msgstr ""
+
+#: if_sniff.c:85
+#~ msgid "Generate docu for"
+#~ msgstr ""
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"SNiFF+·Î ¿¬°áÇÒ ¼ö ¾ø½À´Ï´Ù. ȯ°æÀ» È®ÀÎÇϽʽÿÀ (sniffemacs°¡ $PATH¿¡¼­ ã¾Æ"
+"Á®¾ß ÇÕ´Ï´Ù).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Àд Áß ¿¡·¯. ²÷±è"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ is currently "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "not "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "connected"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: ¸ð¸£´Â SNiFF+ ¿äû: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: SNiFF+¿¡ ¿¬°á ¿¡·¯"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SniFF+°¡ ¿¬°áµÇÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: SniFF+ ¹öÆÛ°¡ ¾Æ´Õ´Ï´Ù"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: ¾²´Â µµÁß ¿¡·¯. ²÷°å½À´Ï´Ù"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "À߸øµÈ ¹öÆÛ ¹øÈ£"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "¾ÆÁ÷ ±¸ÇöµÇÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "¸ð¸£´Â ¿É¼Ç"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "ÁÙÀ» ¼³Á¤ÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "¸¶Å©°¡ ¼³Á¤µÇÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "Çà %d ¿­ %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "ÁÙÀ» ³¢¿ö³Ö°Å³ª ´õÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "¸ð¸£´Â Ç÷¡±×: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "¸ð¸£´Â ºö ¿É¼Ç"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "Å°º¸µå ÀÎÅÍ·´Æ®"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "ºö ¿¡·¯"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "¹öÆÛ/â ¸í·ÉÀ» ¸¸µé ¼ö ¾ø½À´Ï´Ù: °´Ã¼°¡ Áö¿öÁý´Ï´Ù"
+
+#: if_tcl.c:1545
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr "ÄÝ¹é ¸í·ÉÀ» µî·ÏÇÒ ¼ö ¾ø½À´Ï´Ù: ¹öÆÛ/âÀÌ ÀÌ¹Ì Áö¿öÁ³½À´Ï´Ù"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: TCL ½É°¢ÇÑ ¿¡·¯: reflist°¡ ±úÁ³³ª!? ÀÌ ¹®Á¦¸¦ vim-dev@vim.org·Î ¾Ë·ÁÁÖ"
+"½Ê½Ã¿À"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr "ÄÝ¹é ¸í·ÉÀ» µî·ÏÇÒ ¼ö ¾ø½À´Ï´Ù: ¹öÆÛ/â ÂüÁ¶¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"E571: ¹Ì¾ÈÇÕ´Ï´Ù, ÀÌ ¸í·ÉÀº »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù, Tcl ¶óÀ̺귯¸®¸¦ ·ÎµùÇÒ ¼ö ¾ø"
+"½À´Ï´Ù."
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: TCL ¿¡·¯: ³¡³»±â Äڵ尡 Á¤¼ö°¡ ¾Æ´Ñ°¡!? ÀÌ ¹®Á¦¸¦ vim-dev@vim.org·Î ¾Ë"
+"·ÁÁֽʽÿÀ"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "ÁÙÀ» ¾òÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: if_xcmdsrv.c:225
+msgid "Unable to register a command server name"
+msgstr "¸í·É ¼­¹ö À̸§À» µî·ÏÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: if_xcmdsrv.c:473
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: ´ë»óÇÁ·Î±×·¥À¸·Î ¸í·É º¸³»±â°¡ ½ÇÆÐÇß½À´Ï´Ù"
+
+#: if_xcmdsrv.c:747
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: À߸øµÈ ¼­¹ö id »ç¿ëµÊ: %s"
+
+#: if_xcmdsrv.c:1110
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: ºö ÀνºÅϽº ·¹Áö½ºÆ®¸® ¼Ó¼ºÀÌ À߸øµÇ¾î ÀÖ½À´Ï´Ù. Áö¿ü½À´Ï´Ù!"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "¸ð¸£´Â ¿É¼Ç"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "³Ê¹« ¸¹Àº ÆíÁý ÀÎÀÚ"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "µÚ¿¡ ÀÎÀÚ°¡ ¾øÀ½"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "¿É¼Ç µÚ¿¡ ¾²·¹±â °ª"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr "³Ê¹« ¸¹Àº \"+command\" \"-c command\" ȤÀº \"--cmd command\" ÀÎÀÚ"
+
+#: main.c:70
+#~ msgid "Invalid argument for"
+#~ msgstr ""
+
+#: main.c:466
+msgid "This Vim was not compiled with the diff feature."
+msgstr "ÀÌ ºöÀº diff ±â´É ¾øÀÌ ÄÄÆÄÀÏ µÇ¾ú½À´Ï´Ù."
+
+#: main.c:932
+msgid "Attempt to open script file again: \""
+msgstr "½ºÅ©¸³Æ® ÆÄÀÏÀ» ´Ù½Ã ¿­·Á°í ½Ãµµ: \""
+
+#: main.c:941
+msgid "Cannot open for reading: \""
+msgstr "Àбâ À§ÇØ ¿­ ¼ö ¾øÀ½: \""
+
+#: main.c:985
+msgid "Cannot open for script output: \""
+msgstr "½ºÅ©¸³Æ® Ãâ·ÂÀ» ¿­ ¼ö ¾øÀ½: \""
+
+#: main.c:1132
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d ÆÄÀÏÀ» °íÄ¡±â\n"
+
+#: main.c:1233
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "ºö: °æ°í: Å͹̳ηΠÃâ·ÂÇÒ ¼ö ¾ø½À´Ï´Ù\n"
+
+#: main.c:1235
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "ºö: °æ°í: Å͹̳ηΠºÎÅÍ ÀԷ¹ÞÀ» ¼ö ¾ø½À´Ï´Ù\n"
+
+#. just in case..
+#: main.c:1297
+#~ msgid "pre-vimrc command line"
+#~ msgstr ""
+
+#: main.c:1338
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: \"%s\"¿¡¼­ ÀÐÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: main.c:2411
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"´õ ¸¹Àº Á¤º¸¸¦ ¿øÇϽøé: \"vim -h\"\n"
+
+#: main.c:2444
+msgid "[file ..] edit specified file(s)"
+msgstr "[ÆÄÀÏ ..] ÁÖ¾îÁø ÆÄÀÏ °íÄ¡±â"
+
+#: main.c:2445
+msgid "- read text from stdin"
+msgstr "- Ç¥ÁØÀԷ¿¡¼­ ÅؽºÆ® Àбâ"
+
+#: main.c:2446
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tag űװ¡ Á¤ÀÇµÈ À§Ä¡¿¡¼­ ÆÄÀÏ °íÄ¡±â"
+
+#: main.c:2448
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [¿¡·¯ÆÄÀÏ] ù ¹ø° ¿¡·¯°¡ ³­ ÆÄÀÏ °íÄ¡±â"
+
+#: main.c:2457
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"»ç¿ë¹ý:"
+
+#: main.c:2460
+msgid " vim [arguments] "
+msgstr " vim [ÀÎÀÚ] "
+
+#: main.c:2464
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" ȤÀº:"
+
+#: main.c:2467
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"ÀÎÀÚ:\n"
+
+#: main.c:2468
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tÀÌ µÚ¿¡´Â ÆÄÀÏ À̸§¸¸"
+
+#: main.c:2470
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\t¿ÍÀϵåÄ«µå¸¦ È®ÀåÇÏÁö ¾ÊÀ½"
+
+#: main.c:2473
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tÀÌ gvim OLE¿¡ µî·Ï"
+
+#: main.c:2474
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tgvimÀ» OLE¿¡¼­ µî·ÏÃë¼Ò"
+
+#: main.c:2477
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tGUI·Î ½ÇÇà (\"gvim\"°ú °°À½)"
+
+#: main.c:2478
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f ȤÀº --nofork\tÆ÷±×¶ó¿îµå: GUI·Î ½ÃÀÛÇÒ ¶§ forkÇÏÁö ¸» °Í"
+
+#: main.c:2480
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi »óÅ (\"vi\"¿Í °°À½)"
+
+#: main.c:2481
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx »óÅ (\"ex\"¿Í °°À½)"
+
+#: main.c:2482
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tÁ¶¿ëÇÑ (¹èÄ¡) »óÅ (\"ex\"¸¸)"
+
+#: main.c:2484
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tDiff »óÅ (\"vimdiff\"¿Í °°À½)"
+
+#: main.c:2486
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\t½¬¿î »óÅ (\"evim\"°ú °°À½, modeless)"
+
+#: main.c:2487
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tÀбâ Àü¿ë »óÅ (\"view\"¿Í °°À½)"
+
+#: main.c:2488
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tÁ¦ÇÑµÈ »óÅ (\"rvim\"°ú °°À½)"
+
+#: main.c:2489
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\t¼öÁ¤(ÆÄÀÏ ¾²±â)ÀÌ Çã¿ëµÇÁö ¾ÊÀ½"
+
+#: main.c:2490
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tÅؽºÆ® ¼öÁ¤ÀÌ Çã¿ëµÇÁö ¾ÊÀ½"
+
+#: main.c:2491
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tÀÌÁø »óÅÂ"
+
+#: main.c:2493
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\t¸®½ºÇÁ »óÅÂ"
+
+#: main.c:2495
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tVi ȣȯ: 'compatible'"
+
+#: main.c:2496
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tVi¿Í ȣȯµÇÁö ¾ÊÀ½: 'nocompatible'"
+
+#: main.c:2497
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tVerbose ·¹º§"
+
+#: main.c:2498
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tµð¹ö±ë »óÅÂ"
+
+#: main.c:2499
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\t½º¿Ò ÆÄÀÏ ¾øÀÌ ¸Þ¸ð¸®¸¸ »ç¿ë"
+
+#: main.c:2500
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\t½º¿Ò ÆÄÀÏ ¸ñ·ÏÀ» Ç¥½ÃÇÑ µÚ ³¡³»±â"
+
+#: main.c:2501
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (ÆÄÀÏ À̸§°ú ÇÔ²²)\tÆļյǾú´ø ¼¼¼Ç º¹±¸"
+
+#: main.c:2502
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\t-r°ú °°À½"
+
+#: main.c:2504
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tâÀ» ¿­ ¶§ newcli »ç¿ëÇÏÁö ¾ÊÀ½"
+
+#: main.c:2505
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <ÀåÄ¡>\t\tI/O¿¡ <ÀåÄ¡> »ç¿ë"
+
+#: main.c:2508
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\t\tArabic ¸ðµå·Î ½ÃÀÛ"
+
+#: main.c:2511
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\tHebrew ¸ðµå·Î ½ÃÀÛ"
+
+#: main.c:2514
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\tFarsi ¸ðµå·Î ½ÃÀÛ"
+
+#: main.c:2516
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\tÅ͹̳ΠÁ¾·ù¸¦ <terminal>·Î ¼³Á¤"
+
+#: main.c:2517
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\t.vimrc ´ë½Å <vimrc>¸¦ »ç¿ë"
+
+#: main.c:2519
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\t.gvimrc ´ë½Å <gvimrc>¸¦ »ç¿ë"
+
+#: main.c:2521
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tÇ÷¯±×ÀÎ ½ºÅ©¸³Æ®¸¦ ºÒ·¯µéÀÌÁö ¾ÊÀ½"
+
+#: main.c:2522
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tN°³ÀÇ Ã¢ ¿­±â (±âº»: ÆÄÀϺ°·Î Çϳª)"
+
+#: main.c:2523
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\t-o¿Í °°Áö¸¸ âÀ» ¼öÁ÷À¸·Î ³ª´©±â"
+
+#: main.c:2524
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tÆÄÀÏ ¸¶Áö¸·¿¡¼­ ½ÃÀÛ"
+
+#: main.c:2525
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\t<lnum> ÁÙ¿¡¼­ ½ÃÀÛ"
+
+#: main.c:2527
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <¸í·É>\tvimrc ÆÄÀÏÀ» Àбâ Àü¿¡ <¸í·É>À» ½ÇÇà"
+
+#: main.c:2529
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <¸í·É>\t\tù° ÆÄÀÏÀ» ÀÐÀº µÚ <¸í·É>À» ½ÇÇà"
+
+#: main.c:2530
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <¼¼¼Ç>\t\tù° ÆÄÀÏÀ» ÀÐÀº µÚ <¼¼¼Ç> ÆÄÀÏ ºÒ·¯ µéÀ̱â"
+
+#: main.c:2531
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <scriptin>\t<scriptin> ÆÄÀÏ¿¡¼­ Normal »óÅ ¸í·É Àбâ"
+
+#: main.c:2532
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <scriptout>\t¸ðµç ÀÔ·ÂµÈ ¸í·ÉÀ» <scriptout> ÆÄÀÏ¿¡ Ãß°¡"
+
+#: main.c:2533
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <scriptout>\t¸ðµç ÀÔ·ÂµÈ ¸í·ÉÀ» <scriptout> ÆÄÀÏ¿¡ ÀúÀå"
+
+#: main.c:2535
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\t¾ÏȣȭµÈ ÆÄÀÏ °íÄ¡±â"
+
+#: main.c:2539
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\tºöÀ» ƯÁ¤ X-¼­¹ö¿Í ¿¬°á"
+
+#: main.c:2541
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tX ¼­¹ö¿¡ ¿¬°áÇÏÁö ¾ÊÀ½"
+
+#: main.c:2544
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <files>\t°¡´ÉÇÏ¸é ºö ¼­¹ö¿¡¼­ <files> ÆíÁý"
+
+#: main.c:2545
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-silent <files> °°À½, ¼­¹ö°¡ ¾ø´Ù°í ºÒÆòÇÏÁö ¾ÊÀ½"
+
+#: main.c:2546
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <files> --remote¿Í °°Áö¸¸ ´Ù °íÄ¥ ¶§±îÁö ±â´Ù¸³´Ï´Ù"
+
+#: main.c:2547
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-wait-silent <files> °°À½, ¼­¹ö°¡ ¾ø´Ù°í ºÒÆòÇÏÁö ¾ÊÀ½"
+
+#: main.c:2548
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <keys>\tºö ¼­¹ö·Î <keys>¸¦ º¸³»°í ³¡³»±â"
+
+#: main.c:2549
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <expr>\tºö ¼­¹ö¿¡¼­ <expr> ½ÇÇàÇÏ°í °á°ú Ãâ·Â"
+
+#: main.c:2550
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\t»ç¿ë °¡´ÉÇÑ ºö ¼­¹ö À̸§À» Ç¥½ÃÇÏ°í ³¡³»±â"
+
+#: main.c:2551
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <name>\tºö ¼­¹ö <name>ÀÌ µÇ°Å³ª ¼­¹ö·Î º¸³»±â"
+
+#: main.c:2554
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\t.viminfo ´ë½Å <viminfo>¸¦ »ç¿ë"
+
+#: main.c:2556
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h ȤÀº --help\tµµ¿ò¸»(ÀÌ ¸Þ½ÃÁö)À» Ãâ·ÂÇÑ µÚ ³¡³»±â"
+
+#: main.c:2557
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\tÆÇ Á¤º¸¸¦ Ãâ·ÂÇÑ µÚ ³¡³»±â"
+
+#: main.c:2561
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"gvimÀÌ ¾Ë°í ÀÖ´Â ÀÎÀÚ (¸ðƼÇÁ ÆÇ):\n"
+
+#: main.c:2565
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr ""
+"\n"
+"gvimÀÌ ¾Ë°í ÀÖ´Â ÀÎÀÚ (neXtaw ÆÇ):\n"
+
+#: main.c:2567
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"gvimÀÌ ¾Ë°í ÀÖ´Â ÀÎÀÚ (¾ÆÅ׳ª ÆÇ):\n"
+
+#: main.c:2571
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\tºöÀ» <display>¿¡¼­ ½ÇÇà"
+
+#: main.c:2572
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\t¾ÆÀÌÄÜ »óÅ·Πºö ½ÃÀÛ"
+
+#: main.c:2574
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <name>\t\tºöÀÌ <name>ÀÎ °Íó·³ ¸®¼Ò½º »ç¿ë"
+
+#: main.c:2575
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (±¸ÇöµÇÁö ¾ÊÀ½)\n"
+
+#: main.c:2577
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <color>\t¹ÙÅÁ »öÀ¸·Î <color> »ç¿ë (also: -bg)"
+
+#: main.c:2578
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <color>\tÀÏ¹Ý »ö¿¡ <color> »ç¿ë (also: -fg)"
+
+#: main.c:2579 main.c:2599
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <font>\t\tÀÏ¹Ý ÅؽºÆ®¿¡ <font> »ç¿ë (also: -fn)"
+
+#: main.c:2580
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <font>\t±½Àº ÅؽºÆ®¿¡ <font> »ç¿ë"
+
+#: main.c:2581
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <font>\t±â¿ïÀÓ ÅؽºÆ®¿¡ <font> »ç¿ë"
+
+#: main.c:2582 main.c:2600
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\tÃʱâ Áö¿À¹ÌÆ®¸®¿¡ <geom> »ç¿ë (also: -geom)"
+
+#: main.c:2583
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <width>\t°¡ÀåÀÚ¸® ³ÐÀÌ¿¡ <width> »ç¿ë (also: -bw)"
+
+#: main.c:2584
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <width> ½ºÅ©·Ñ¹Ù ³ÐÀÌ¿¡ <width> »ç¿ë (also: -sw)"
+
+#: main.c:2586
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <height>\tÂ÷¸²Ç¥ ¸·´ë ³ôÀÌ¿¡ <height> »ç¿ë (also: -mh)"
+
+#: main.c:2588 main.c:2601
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\t¹ÝÀü ºñµð¿À »ç¿ë (also: -rv)"
+
+#: main.c:2589
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\t¹ÝÀü ºñµð¿À »ç¿ë ¾È ÇÔ (also: +rv)"
+
+#: main.c:2590
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\t¸í½ÃµÈ ¸®¼Ò½º ¼³Á¤"
+
+#: main.c:2593
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"gvimÀÌ ¾Ë°íÀÖ´Â ÀÎÀÚ (RISC OS ÆÇ):\n"
+
+#: main.c:2594
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <¼ýÀÚ>\tÄ­¿¡¼­ â Ãʱ⠳ʺñ"
+
+#: main.c:2595
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <¼ýÀÚ>\tÁÙ¿¡¼­ â Ãʱ⠳ôÀÌ"
+
+#: main.c:2598
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"gvimÀÌ ¾Ë°íÀÖ´Â ÀÎÀÚ (GTK+ ÆÇ):\n"
+
+#: main.c:2602
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\tºöÀ» <display>¿¡¼­ ½ÇÇà (also: --display)"
+
+#: main.c:2604
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr "--role <role>\t¸ÞÀΠâ ±¸ºÐÀ» À§ÇØ À¯ÀÏÇÑ ¿ªÇÒ ¼³Á¤"
+
+#: main.c:2606
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tºöÀ» ´Ù¸¥ GTK À§Á¬ ¾È¿¡¼­ ¿­À½"
+
+#: main.c:2609
+msgid "-P <parent title>\tOpen Vim inside parent application"
+msgstr "-P <parent title>\tVimÀ» ºÎ¸ð ÀÀ¿ë ÇÁ·Î±×·¥ ³»¿¡¼­ ¿­±â"
+
+#: main.c:2847
+msgid "No display"
+msgstr "µð½ºÇ÷¹ÀÌ°¡ ¾ø½À´Ï´Ù"
+
+#. Failed to send, abort.
+#: main.c:2862
+msgid ": Send failed.\n"
+msgstr ": º¸³»±â°¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù.\n"
+
+#. Let vim start normally.
+#: main.c:2868
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": º¸³»±â ½ÇÆÐ. ·ÎÄÿ¡¼­ ½ÇÇàµË´Ï´Ù\n"
+
+#: main.c:2906 main.c:2927
+#, c-format
+#~ msgid "%d of %d edited"
+#~ msgstr ""
+
+#: main.c:2949
+msgid "No display: Send expression failed.\n"
+msgstr "µð½ºÇ÷¹ÀÌ ¾øÀ½: Ç¥Çö½Ä º¸³»±â°¡ ½ÇÆÐÇß½À´Ï´Ù.\n"
+
+#: main.c:2961
+msgid ": Send expression failed.\n"
+msgstr ": Ç¥Çö½Ä º¸³»±â°¡ ½ÇÆÐÇß½À´Ï´Ù.\n"
+
+#: mark.c:709
+msgid "No marks set"
+msgstr "¼³Á¤µÈ ¸¶Å©°¡ ¾ø½À´Ï´Ù"
+
+#: mark.c:711
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: \"%s\"¿¡ ¸Â´Â ¸¶Å©°¡ ¾ø½À´Ï´Ù"
+
+#. Highlight title
+#: mark.c:722
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"¸¶Å© ¶óÀÎ col ÆÄÀÏ/ÅؽºÆ®"
+
+#. Highlight title
+#: mark.c:760
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" Á¡ÇÁ ¶óÀÎ col ÆÄÀÏ/ÅؽºÆ®"
+
+#. Highlight title
+#: mark.c:805
+#~ msgid ""
+#~ "\n"
+#~ "change line col text"
+#~ msgstr ""
+
+#: mark.c:1281
+#, c-format
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# ÆÄÀÏ ¸¶Å©:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1316
+#, c-format
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Á¡ÇÁ¸ñ·Ï (»õ°ÍÀÌ ¸ÕÀú):\n"
+
+#: mark.c:1412
+#, c-format
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# ÆÄÀϳ»ÀÇ ¸¶Å© È÷½ºÅ丮 (»õ°ÍºÎÅÍ ¿À·¡µÈ ¼ø):\n"
+
+#: mark.c:1501
+msgid "Missing '>'"
+msgstr "'>'ÀÌ ¾ø½À´Ï´Ù"
+
+#: mbyte.c:467
+msgid "E543: Not a valid codepage"
+msgstr "E543: Á¤»óÀûÀÎ ÄÚµåÆäÀÌÁö°¡ ¾Æ´Õ´Ï´Ù"
+
+#: mbyte.c:4431
+msgid "E284: Cannot set IC values"
+msgstr "E284: IC °ªÀ» ¼³Á¤ÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: mbyte.c:4583
+msgid "E285: Failed to create input context"
+msgstr "E285: ÀÔ·Â ÄÜÅؽºÆ®¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù"
+
+#: mbyte.c:4741
+msgid "E286: Failed to open input method"
+msgstr "E286: ÀÔ·Â ¹æ½ÄÀ» ¿­´Ù°¡ ½ÇÆÐÇß½À´Ï´Ù"
+
+#: mbyte.c:4752
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: °æ°í: IM¿¡ Æı« ÄݹéÀ» ¼³Á¤ÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: mbyte.c:4758
+msgid "E288: input method doesn't support any style"
+msgstr "E288: ÀÔ·Â ¹æ½ÄÀÌ ¾î¶² Çü½Äµµ Áö¿øÇÏÁö ¾Ê½À´Ï´Ù"
+
+#: mbyte.c:4815
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: ÀÔ·Â ¹æ½ÄÀÌ ³» preedit Çü½ÄÀ» Áö¿øÇÏÁö ¾Ê½À´Ï´Ù"
+
+#: mbyte.c:4889
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: over-the-spot Çü½ÄÀº fontsetÀÌ »ç¿ëµÇ¾î¾ß ÇÕ´Ï´Ù"
+
+#: mbyte.c:4925
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: GTK+°¡ 1.2.3 ÀÌÀü ÆÇÀÔ´Ï´Ù. »óÅ ¿µ¿ªÀ» »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: mbyte.c:5232
+msgid "E292: Input Method Server is not running"
+msgstr "E292: ÀÔ·Â ¼­¹ö°¡ ½ÇÇàµÇÁö ¾Ê°í ÀÖ½À´Ï´Ù"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: ±¸¿ªÀÌ Àá±ÅÁöÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: memfile.c:1010
+msgid "E294: Seek error in swap file read"
+msgstr "E294: ½º¿Ò ÆÄÀÏÀ» Àбâ À§ÇØ Æ¯Á¤ À§Ä¡·Î °¥ ¼ö ¾ø½À´Ï´Ù"
+
+#: memfile.c:1015
+msgid "E295: Read error in swap file"
+msgstr "E295: ½º¿Ò ÆÄÀÏÀ» ÀÐÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: memfile.c:1067
+msgid "E296: Seek error in swap file write"
+msgstr "E296: ½º¿Ò ÆÄÀÏÀ» ¾²±â À§ÇØ Æ¯Á¤ À§Ä¡·Î °¥ ¼ö ¾ø½À´Ï´Ù"
+
+#: memfile.c:1085
+msgid "E297: Write error in swap file"
+msgstr "E297: ½º¿Ò ÆÄÀÏÀ» ¾µ ¼ö ¾ø½À´Ï´Ù"
+
+#: memfile.c:1282
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: ½º¿Ò ÆÄÀÏÀÌ ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù (symlink °ø°Ý?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: ±¸¿ª ¹øÈ£ 0À» ¾òÁö ¸øÇß³ª¿ä?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: ±¸¿ª ¹øÈ£ 1À» ¾òÁö ¸øÇß³ª¿ä?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: ±¸¿ª ¹øÈ£ 2¸¦ ¾òÁö ¸øÇß³ª¿ä?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:444
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: À¸À¹, ½º¿Ò ÆÄÀÏÀ» ÀÒ¾î¹ö·È½À´Ï´Ù!!!"
+
+#: memline.c:449
+msgid "E302: Could not rename swap file"
+msgstr "E302: ½º¿Ò ÆÄÀÏ À̸§À» ¹Ù²Ü ¼ö ¾ø½À´Ï´Ù"
+
+#: memline.c:519
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: \"%s\"ÀÇ ½º¿Ò ÆÄÀÏÀ» ¿­ ¼ö ¾ø¾î¼­ º¹±¸´Â ºÒ°¡´ÉÇÕ´Ï´Ù"
+
+#: memline.c:618
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: ±¸¿ª 0À» ¾òÁö ¸øÇß³ª¿ä??"
+
+#: memline.c:758
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: %sÀÇ ½º¿Ò ÆÄÀÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: memline.c:768
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "»ç¿ëÇÒ ½º¿Ò ÆÄÀÏ ¹øÈ£¸¦ ÀÔ·ÂÇϽʽÿÀ (0Àº ³¡³»±â): "
+
+#: memline.c:813
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: %sÀ»(¸¦) ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: memline.c:835
+msgid "Unable to read block 0 from "
+msgstr "Unable to read block 0 from "
+
+#: memline.c:838
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"¾î¶² ¼öÁ¤µµ ¾ø¾ú°Å³ª ºöÀÌ ½º¿Ò ÆÄÀÏÀ» °»½ÅÇÏÁö ¾ÊÀº °Í °°½À´Ï´Ù."
+
+#: memline.c:848 memline.c:865
+msgid " cannot be used with this version of Vim.\n"
+msgstr " cannot be used with this version of Vim.\n"
+
+#: memline.c:850
+msgid "Use Vim version 3.0.\n"
+msgstr "ºö 3.0 ÆÇÀ» »ç¿ëÇϽʽÿÀ.\n"
+
+#: memline.c:856
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %sÀº(´Â) ºö ½º¿Ò ÆÄÀÏÀÌ ¾Æ´Ñ °Í °°½À´Ï´Ù"
+
+#: memline.c:869
+msgid " cannot be used on this computer.\n"
+msgstr " ÀÌ ÄÄÇ»ÅÍ¿¡¼­´Â »ç¿ëµÉ ¼ö ¾ø½À´Ï´Ù.\n"
+
+#: memline.c:871
+msgid "The file was created on "
+msgstr "The file was created on "
+
+#: memline.c:875
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"or the file has been damaged."
+
+#: memline.c:904
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "½º¿Ò ÆÄÀÏ \"%s\"À»(¸¦) »ç¿ëÇÕ´Ï´Ù"
+
+#: memline.c:910
+#, c-format
+msgid "Original file \"%s\""
+msgstr "¿ø·¡ ÆÄÀÏ \"%s\""
+
+#: memline.c:923
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: °æ°í: ¿ø·¡ ÆÄÀÏÀÌ ¹Ù²î¾ú½À´Ï´Ù"
+
+#: memline.c:976
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: %sÀÇ ±¸¿ª 1À» ÀÐÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: memline.c:980
+msgid "???MANY LINES MISSING"
+msgstr "???¸¹Àº ÁÙÀ» ÀÒ¾î¹ö¸²"
+
+#: memline.c:996
+msgid "???LINE COUNT WRONG"
+msgstr "???ÁÙ ¹øÈ£°¡ À߸øµÇ¾ú½À´Ï´Ù"
+
+#: memline.c:1003
+msgid "???EMPTY BLOCK"
+msgstr "???ºó ±¸¿ª"
+
+#: memline.c:1029
+msgid "???LINES MISSING"
+msgstr "???ÁÙÀ» ÀÒ¾î¹ö¸²"
+
+#: memline.c:1061
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ±¸¿ª 1ÀÇ ID°¡ À߸øµÇ¾ú½À´Ï´Ù (%sÀÌ(°¡) .swp ÆÄÀÏÀÌ ¾Æ´Ñ°¡?)"
+
+#: memline.c:1066
+msgid "???BLOCK MISSING"
+msgstr "???±¸¿ª ÀÒ¾î¹ö¸²"
+
+#: memline.c:1082
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? ¿©±âºÎÅÍ ???³¡±îÁöÀÇ ÁÙÀÌ ¼¯¿´½À´Ï´Ù"
+
+#: memline.c:1098
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? ¿©±âºÎÅÍ ???³¡±îÁöÀÇ ÁÙÀÌ ³¢¿öÁö°Å³ª Áö¿öÁ® ¹ö¸° °Í °°½À´Ï´Ù"
+
+#: memline.c:1118
+msgid "???END"
+msgstr "???³¡"
+
+#: memline.c:1144
+msgid "E311: Recovery Interrupted"
+msgstr "E311: º¹±¸ ÁߴܵǾú½À´Ï´Ù"
+
+#: memline.c:1149
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: º¹±¸ µµÁß ¿¡·¯ »ý°å½À´Ï´Ù; ???·Î ½ÃÀÛÇÏ´Â ÁÙÀ» ã¾Æº¸½Ê½Ã¿À"
+
+#: memline.c:1151
+msgid "See \":help E312\" for more information."
+msgstr "´õ ¸¹Àº Á¤º¸¸¦ º¸·Á¸é \":help E312\"¸¦ ÀÔ·ÂÇϼ¼¿ä."
+
+#: memline.c:1156
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "º¹±¸°¡ ³¡³µ½À´Ï´Ù. ¸ðµç °Ô Á¤»óÀÎ Áö È®ÀÎÇØ º¸¼Å¾ß¸¸ ÇÕ´Ï´Ù."
+
+#: memline.c:1157
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(¾î¼¸é ´Ù¸¥ À̸§À¸·Î ÀúÀåÇÏ°í ½ÍÀ¸½Ç Áöµµ ¸ð¸£°Ú½À´Ï´Ù\n"
+
+#: memline.c:1158
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "±×¸®°í ¹Ù²ï ³»¿ëÀ» È®ÀÎÇÏ·Á¸é diff¸¦ ÀÌ¿ëÇϽʽÿÀ)\n"
+
+#: memline.c:1159
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"³ªÁß¿¡ .swp ÆÄÀÏÀ» Áö¿ì½Ê½Ã¿À.\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1215
+msgid "Swap files found:"
+msgstr "½º¿Ò ÆÄÀÏÀ» ã¾ÒÀ½:"
+
+#: memline.c:1393
+msgid " In current directory:\n"
+msgstr " ÇöÀç ÀÚ·á¹æ¿¡:\n"
+
+#: memline.c:1395
+msgid " Using specified name:\n"
+msgstr " ¸í½ÃµÈ À̸§À» »ç¿ë:\n"
+
+#: memline.c:1399
+msgid " In directory "
+msgstr " In directory "
+
+#: memline.c:1417
+msgid " -- none --\n"
+msgstr " -- ¾øÀ½ --\n"
+
+#: memline.c:1489
+msgid " owned by: "
+msgstr " ¼ÒÀ¯ÀÚ: "
+
+#: memline.c:1491
+msgid " dated: "
+msgstr " ³¯Â¥: "
+
+#: memline.c:1495 memline.c:3685
+msgid " dated: "
+msgstr " ³¯Â¥: "
+
+#: memline.c:1511
+msgid " [from Vim version 3.0]"
+msgstr " [ºö 3.0 ÆÇÀÇ °Í]"
+
+#: memline.c:1515
+msgid " [does not look like a Vim swap file]"
+msgstr " [ºö ½º¿Ò ÆÄÀÏ·Î º¸ÀÌÁö ¾Ê½À´Ï´Ù]"
+
+#: memline.c:1519
+msgid " file name: "
+msgstr " ÆÄÀÏ À̸§: "
+
+#: memline.c:1525
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" ¼öÁ¤: "
+
+#: memline.c:1526
+msgid "YES"
+msgstr "¿¹"
+
+#: memline.c:1526
+msgid "no"
+msgstr "¾Æ´Ï¿À"
+
+#: memline.c:1530
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" »ç¿ëÀÚ À̸§: "
+
+#: memline.c:1537
+msgid " host name: "
+msgstr " È£½ºÆ® À̸§: "
+
+#: memline.c:1539
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" È£½ºÆ® À̸§: "
+
+#: memline.c:1545
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ÇÁ·Î¼¼½º ID: "
+
+#: memline.c:1551
+msgid " (still running)"
+msgstr " (¾ÆÁ÷ ½ÇÇàÁß)"
+
+#: memline.c:1563
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [ºö À̹ø ÆÇ¿¡¼­´Â »ç¿ëÇÒ ¼ö ¾øÀ½]"
+
+#: memline.c:1566
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [ÀÌ ÄÄÇ»ÅÍ¿¡¼­´Â »ç¿ëÇÒ ¼ö ¾øÀ½]"
+
+#: memline.c:1571
+msgid " [cannot be read]"
+msgstr " [ÀÐÀ» ¼ö ¾øÀ½]"
+
+#: memline.c:1575
+msgid " [cannot be opened]"
+msgstr " [¿­ ¼ö ¾øÀ½]"
+
+#: memline.c:1765
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: º¸Á¸ÇÒ ¼ö ¾ø½À´Ï´Ù, ½º¿Ò ÆÄÀÏÀÌ ¾ø½À´Ï´Ù"
+
+#: memline.c:1818
+msgid "File preserved"
+msgstr "ÆÄÀÏÀÌ º¸Á¸µÇ¾ú½À´Ï´Ù"
+
+#: memline.c:1820
+msgid "E314: Preserve failed"
+msgstr "E314: ÆÄÀÏ º¸Á¸À» ½ÇÆÐÇß½À´Ï´Ù"
+
+#: memline.c:1891
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: À߸øµÈ lnum: %ld"
+
+#: memline.c:1917
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: %ld ÁÙÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: memline.c:2307
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: À߸øµÈ Æ÷ÀÎÅÍ ±¸¿ª id 3"
+
+#: memline.c:2387
+msgid "stack_idx should be 0"
+msgstr "stack_idx´Â 0¿©¾ß¸¸ ÇÕ´Ï´Ù"
+
+#: memline.c:2449
+msgid "E318: Updated too many blocks?"
+msgstr "E318: ³Ê¹« ¸¹Àº ±¸¿ªÀÌ °»½ÅµÇ¾ú³ª¿ä?"
+
+#: memline.c:2631
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: À߸øµÈ Æ÷ÀÎÅÍ ±¸¿ª id 4"
+
+#: memline.c:2658
+msgid "deleted block 1?"
+msgstr "±¸¿ª 1ÀÌ Áö¿öÁ³³ª¿ä?"
+
+#: memline.c:2858
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: %ld ÁÙÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: memline.c:3101
+msgid "E317: pointer block id wrong"
+msgstr "E317: À߸øµÈ Æ÷ÀÎÅÍ ±¸¿ª id"
+
+#: memline.c:3117
+msgid "pe_line_count is zero"
+msgstr "pe_line_count°¡ 0ÀÔ´Ï´Ù"
+
+#: memline.c:3146
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: ÁÙ ¹øÈ£°¡ ¹üÀ§¸¦ ¹þ¾î³µ½À´Ï´Ù: ¸¶Áö¸·¿¡¼­ %ld ¸¸Å­"
+
+#: memline.c:3150
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: ±¸¿ª %ldÀÇ ÁÙ °¹¼ö°¡ Ʋ·È½À´Ï´Ù"
+
+#: memline.c:3199
+msgid "Stack size increases"
+msgstr "½ºÅà ũ±â Áõ°¡"
+
+#: memline.c:3245
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: À߸øµÈ Æ÷ÀÎÅÍ ±¸¿ª id 2"
+
+#: memline.c:3675
+msgid "E325: ATTENTION"
+msgstr "E325: ÁÖ¸ñ"
+
+#: memline.c:3676
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Found a swap file by the name \""
+
+#: memline.c:3680
+msgid "While opening file \""
+msgstr "While opening file \""
+
+#: memline.c:3689
+msgid " NEWER than swap file!\n"
+msgstr " NEWER than swap file!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3693
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) ´Ù¸¥ ÇÁ·Î±×·¥ÀÌ °°Àº ÆÄÀÏÀ» °íÄ¡°í ÀÖ´ÂÁßÀÏ ¼ö ÀÖ½À´Ï´Ù.\n"
+" ¸¸¾à ±×·¸´Ù¸é °°Àº ÆÄÀÏÀ» µÎ °³ÀÇ ÇÁ·Î±×·¥¿¡¼­ °íÄ¡Áö\n"
+" ¾Êµµ·Ï Á¶½ÉÇϽñ⠹ٶø´Ï´Ù.\n"
+
+#: memline.c:3694
+msgid " Quit, or continue with caution.\n"
+msgstr " ³¡³»°Å³ª À§ÇèÀ» °¨¼öÇϽ÷Á¸é °è¼ÓÇϽʽÿÀ.\n"
+
+#: memline.c:3695
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) ÆÄÀÏÀ» °íÄ¡´Ù°¡ Á×¾ú¾ú½À´Ï´Ù.\n"
+
+#: memline.c:3696
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " ¸¸¾à ±×·¸´Ù¸é \":recover\" ȤÀº \"vim -r "
+
+#: memline.c:3698
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" À» »ç¿ëÇÏ¿© º¹±¸ÇϽʽÿÀ (\":help recovery\" Âü°í).\n"
+
+#: memline.c:3699
+msgid " If you did this already, delete the swap file \""
+msgstr " ÀÌ¹Ì º¹±¸Çϼ̾ú´Ù¸é ½º¿ÒÆÄÀÏ \""
+
+#: memline.c:3701
+#~ msgid ""
+#~ "\"\n"
+#~ " to avoid this message.\n"
+#~ msgstr ""
+
+#: memline.c:3715 memline.c:3719
+msgid "Swap file \""
+msgstr "½º¿Ò ÆÄÀÏ \""
+
+#: memline.c:3716 memline.c:3722
+msgid "\" already exists!"
+msgstr "\"ÀÌ ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù!"
+
+#: memline.c:3725
+msgid "VIM - ATTENTION"
+msgstr "ºö - ÁÖ¸ñ"
+
+#: memline.c:3727
+msgid "Swap file already exists!"
+msgstr "½º¿Ò ÆÄÀÏÀÌ ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù!"
+
+#: memline.c:3731
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort"
+msgstr ""
+"Àбâ Àü¿ëÀ¸·Î ¿­±â(&O)\n"
+"±×³É °íÄ¡±â(&E)\n"
+"º¹±¸(&R)\n"
+"³¡³»±â(&Q)\n"
+"¹ö¸®±â(&A)"
+
+#: memline.c:3733
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort\n"
+"&Delete it"
+msgstr ""
+"Àбâ Àü¿ëÀ¸·Î ¿­±â(&O)\n"
+"±×³É °íÄ¡±â(&E)\n"
+"º¹±¸(&R)\n"
+"³¡³»±â(&Q)\n"
+"¹ö¸®±â(&A)\n"
+"Áö¿ì±â(&D)"
+
+#: memline.c:3790
+msgid "E326: Too many swap files found"
+msgstr "E326: ³Ê¹« ¸¹Àº ½º¿Ò ÆÄÀÏÀÌ ¹ß°ßµÇ¾ú½À´Ï´Ù"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Â÷¸²Ç¥ Ç׸ñ °æ·ÎÀÇ ºÎºÐÀÌ ÇÏÀ§ Â÷¸²Ç¥°¡ ¾Æ´Õ´Ï´Ù"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Â÷¸²Ç¥´Â ¿À·ÎÁö ´Ù¸¥ »óÅ¿¡¼­¸¸ Á¸ÀçÇÕ´Ï´Ù"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: ±×·± À̸§À» °¡Áø Â÷¸²Ç¥°¡ ¾ø½À´Ï´Ù"
+
+#: menu.c:525
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: ÇÏÀ§ Â÷¸²Ç¥ ¾Õ¿¡´Â Â÷¸²Ç¥ °æ·Î°¡ ºÙÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: menu.c:564
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: Â÷¸²Ç¥ ¸·´ë¿¡ °ð¹Ù·Î Â÷¸²Ç¥ Ç׸ñÀ» ´õÇÒ ¼ö´Â ¾ø½À´Ï´Ù"
+
+#: menu.c:570
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: ±¸ºÐÀÚ´Â Â÷¸²Ç¥ °æ·ÎÀÇ ºÎºÐÀÌ µÉ ¼ö ¾ø½À´Ï´Ù"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1097
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Â÷¸²Ç¥ ---"
+
+#: menu.c:2019
+msgid "Tear off this menu"
+msgstr "ÀÌ Â÷¸²Ç¥¸¦ ¶¼¾î³¿"
+
+#: menu.c:2084
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Â÷¸²Ç¥ Ç׸ñ ¾Õ¿¡´Â Â÷¸²Ç¥ °æ·Î°¡ ÀÖ¾î¾ß ÇÕ´Ï´Ù"
+
+#: menu.c:2104
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Â÷¸²Ç¥¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù: %s"
+
+#: menu.c:2173
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: %s »óÅ¿¡ ´ëÇÑ Â÷¸²Ç¥°¡ Á¤ÀǵǾî ÀÖÁö ¾Ê½À´Ï´Ù"
+
+#: menu.c:2211
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: ÇÏÀ§ Â÷¸²Ç¥ ¾Õ¿¡ Â÷¸²Ç¥ °æ·Î°¡ ÀÖ¾î¾ß ÇÕ´Ï´Ù"
+
+#: menu.c:2232
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Â÷¸²Ç¥¸¦ ãÀ» ¼ö ¾øÀ½ - Â÷¸²Ç¥ À̸§À» È®ÀÎÇϽʽÿÀ"
+
+#: message.c:414
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "%s ¼öÇàÁß ¿¡·¯ ¹ß°ß:"
+
+#: message.c:440
+#, c-format
+msgid "line %4ld:"
+msgstr "%4ld ÁÙ:"
+
+#: message.c:647
+msgid "[string too long]"
+msgstr "[³Ê¹« ±ä ¹®ÀÚ¿­]"
+
+#: message.c:797
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "¸Þ½ÃÁö ¹ø¿ª: Sung-Hyun Nam <namsh@kldp.org>"
+
+#: message.c:1025
+msgid "Interrupt: "
+msgstr "Áß´Ü: "
+
+#: message.c:1028
+msgid "Hit ENTER to continue"
+msgstr "°è¼ÓÇÏ·Á¸é ¿£ÅÍÅ°¸¦ ´©¸£½Ê½Ã¿À"
+
+#: message.c:1030
+msgid "Hit ENTER or type command to continue"
+msgstr "°è¼ÓÇÏ·Á¸é ¿£ÅÍ È¤Àº ¸í·ÉÀ» ÀÔ·ÂÇϽʽÿÀ"
+
+#: message.c:2351
+msgid "-- More --"
+msgstr "-- ´õ --"
+
+#: message.c:2354
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: ÁÙ, SPACE/b: ÂÊ, d/u: ¹ÝÂÊ, q: ³¡³»±â)"
+
+#: message.c:2355
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: ÁÙ, SPACE: ÂÊ, d: ¹ÝÂÊ, q: ³¡³»±â)"
+
+#: message.c:2982 message.c:2997
+msgid "Question"
+msgstr "Áú¹®"
+
+#: message.c:2984
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"¿¹(&Y)\n"
+"¾Æ´Ï¿À(&N)"
+
+#: message.c:3017
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"¿¹(&Y)\n"
+"¾Æ´Ï¿À(&N)\n"
+"¸ðµÎ ÀúÀå(&A)\n"
+"¸ðµÎ ¹ö¸²(&D)\n"
+"Ãë¼Ò(&C)"
+
+#: message.c:3058
+msgid "Save File dialog"
+msgstr "ÆÄÀÏ ÀúÀå ´ëÈ­»óÀÚ"
+
+#: message.c:3060
+msgid "Open File dialog"
+msgstr "ÆÄÀÏ ¿­±â ´ëÈ­»óÀÚ"
+
+#. TODO: non-GUI file selector here
+#: message.c:3131
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: ¹Ì¾ÈÇÕ´Ï´Ù, ÄÜ¼Ö »óÅ¿¡´Â ÆÄÀÏ ºê¶ó¿ìÀú°¡ ¾ø½À´Ï´Ù"
+
+#: misc1.c:2773
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: °æ°í: Àбâ Àü¿ë ÆÄÀÏÀ» °íÄ¡°í ÀÖ½À´Ï´Ù"
+
+#: misc1.c:3021
+msgid "1 more line"
+msgstr "ÇÑ ÁÙ ÀÌ»ó"
+
+#: misc1.c:3023
+msgid "1 line less"
+msgstr "ÇÑ ÁÙ ÀÌÇÏ"
+
+#: misc1.c:3028
+#, c-format
+msgid "%ld more lines"
+msgstr "%ld º¸´Ù ¸¹Àº ÁÙ"
+
+#: misc1.c:3030
+#, c-format
+msgid "%ld fewer lines"
+msgstr "%ld º¸´Ù ÀûÀº ÁÙ"
+
+#: misc1.c:3033
+msgid " (Interrupted)"
+msgstr " (ÁߴܵǾú½À´Ï´Ù)"
+
+#: misc1.c:7588
+msgid "Vim: preserving files...\n"
+msgstr "ºö: ÆÄÀÏ º¸Á¸Áß...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:7598
+msgid "Vim: Finished.\n"
+msgstr "ºö: ²ø³µ½À´Ï´Ù.\n"
+
+#: misc2.c:695 misc2.c:711
+#, c-format
+msgid "ERROR: "
+msgstr "¿¡·¯: "
+
+#: misc2.c:715
+#, c-format
+#~ msgid ""
+#~ "\n"
+#~ "[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+#~ msgstr ""
+
+#: misc2.c:717
+#, c-format
+#~ msgid ""
+#~ "[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+#~ "\n"
+#~ msgstr ""
+
+#: misc2.c:772
+msgid "E340: Line is becoming too long"
+msgstr "E340: ÁÙÀÌ ³Ê¹« ±æ¾îÁ³½À´Ï´Ù"
+
+#: misc2.c:816
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: ³»ºÎ ¿¡·¯: lalloc(%ld, )"
+
+#: misc2.c:924
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: ¸Þ¸ð¸® ºÎÁ·! (%lu ¹ÙÀÌÆ®¸¦ ÇÒ´ç)"
+
+#: misc2.c:2594
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "½ÇÇàÇÏ·Á°í ½© ºÎ¸§: \"%s\""
+
+#: misc2.c:2816
+msgid "E545: Missing colon"
+msgstr "E545: ÄÝ·ÐÀÌ ¾ø½À´Ï´Ù"
+
+#: misc2.c:2818 misc2.c:2845
+msgid "E546: Illegal mode"
+msgstr "E546: ÀÌ»óÇÑ ¸ðµå"
+
+#: misc2.c:2884
+msgid "E547: Illegal mouseshape"
+msgstr "E547: ÀÌ»óÇÑ ¸¶¿ì½º¸ð¾ç"
+
+#: misc2.c:2924
+msgid "E548: digit expected"
+msgstr "E548: ¼ýÀÚ°¡ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: misc2.c:2929
+msgid "E549: Illegal percentage"
+msgstr "E549: ÀÌ»óÇÑ ¹éºÐÀ²"
+
+#: misc2.c:3239
+msgid "Enter encryption key: "
+msgstr "¾ÏÈ£ Å° ÀÔ·Â: "
+
+#: misc2.c:3240
+msgid "Enter same key again: "
+msgstr "°°Àº Å°¸¦ ´Ù½Ã ÀÔ·Â: "
+
+#: misc2.c:3250
+msgid "Keys don't match!"
+msgstr "Å°°¡ ¸ÂÁö ¾Ê½À´Ï´Ù!"
+
+#: misc2.c:3799
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: À߸øµÈ °æ·Î: '**[¹øÈ£]'´Â °æ·ÎÀÇ ¸¶Áö¸·¿¡ À§Ä¡Çϰųª '%s' µÚ¿¡ ÀÖ¾î¾ß "
+"ÇÕ´Ï´Ù."
+
+#: misc2.c:5078
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: cdpath¿¡¼­ \"%s\" ÀÚ·á¹æÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: misc2.c:5081
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: path¿¡¼­ \"%s\" ÆÄÀÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: misc2.c:5087
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: cdpath¿¡¼­ ´õ ÀÌ»óÀÇ \"%s\" ÀÚ·á¹æÀº ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: misc2.c:5090
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: path¿¡¼­ ´õ ÀÌ»óÀÇ \"%s\" ÆÄÀÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: misc2.c:5324
+msgid "E550: Missing colon"
+msgstr "E550: ÄÝ·ÐÀÌ ¾ø½À´Ï´Ù"
+
+#: misc2.c:5336
+msgid "E551: Illegal component"
+msgstr "E551: ÀÌ»óÇÑ ÄÄÆ÷³ÍÆ®"
+
+#: misc2.c:5344
+msgid "E552: digit expected"
+msgstr "E552: ¼ýÀÚ°¡ ÇÊ¿äÇÕ´Ï´Ù"
+
+#. Get here when the server can't be found.
+#: netbeans.c:396
+msgid "Cannot connect to Netbeans #2"
+msgstr "Netbeans #2¿¡ ¿¬°áÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: netbeans.c:404
+msgid "Cannot connect to Netbeans"
+msgstr "Netbeans¿¡ ¿¬°áÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: netbeans.c:450
+#, c-format
+msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\""
+msgstr "E668: NetBeans ¿¬°á Á¤º¸ ÆÄÀÏÀÌ Á¢±Ù ¸ðµå°¡ À߸øµÊ: \"%s\""
+
+#: netbeans.c:749
+msgid "read from Netbeans socket"
+msgstr "Netbeans ¼ÒÄÏ¿¡¼­ Àбâ"
+
+#: netbeans.c:1643
+#, c-format
+msgid "E658: NetBeans connection lost for buffer %ld"
+msgstr "E658: ¹öÆÛ %ld¿¡ ´ëÇÑ NetBeans ¿¬°áÀ» ÀÒ¾î¹ö·È½À´Ï´Ù"
+
+#: normal.c:2980
+msgid "Warning: terminal cannot highlight"
+msgstr "°æ°í: Å͹̳ÎÀÌ ºñÁê¾ó »óŸ¦ Ç¥½ÃÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: normal.c:3276
+msgid "E348: No string under cursor"
+msgstr "E348: Ä¿¼­ ¹Ø¿¡ ¹®ÀÚ¿­ÀÌ ¾ø½À´Ï´Ù"
+
+#: normal.c:3278
+msgid "E349: No identifier under cursor"
+msgstr "E349: Ä¿¼­ ¹Ø¿¡ ½Äº°ÀÚ°¡ ¾ø½À´Ï´Ù"
+
+#: normal.c:4519
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: ÇöÀçÀÇ 'foldmethod'À¸·Î Á¢±â¸¦ Áö¿ï ¼ö ¾ø½À´Ï´Ù"
+
+#: normal.c:6740
+msgid "E664: changelist is empty"
+msgstr "E664: changelist°¡ ºñ¾ú½À´Ï´Ù"
+
+#: normal.c:6742
+#~ msgid "E662: At start of changelist"
+#~ msgstr ""
+
+#: normal.c:6744
+#~ msgid "E663: At end of changelist"
+#~ msgstr ""
+
+#: normal.c:8005
+msgid "Type :quit<Enter> to exit Vim"
+msgstr "VIMÀ» ¸¶Ä¡·Á¸é :quit<Enter> ÀÔ·Â"
+
+#: ops.c:294
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "1 line %sed 1 time"
+
+#: ops.c:296
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 line %sed %d times"
+
+#: ops.c:301
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld lines %sed 1 time"
+
+#: ops.c:304
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld lines %sed %d times"
+
+#: ops.c:662
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld lines to indent... "
+
+#: ops.c:712
+msgid "1 line indented "
+msgstr "1 line indented "
+
+#: ops.c:714
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld lines indented "
+
+#. must display the prompt
+#: ops.c:1675
+msgid "cannot yank; delete anyway"
+msgstr "cannot yank; delete anyway"
+
+#: ops.c:2261
+msgid "1 line changed"
+msgstr "1 line changed"
+
+#: ops.c:2263
+#, c-format
+msgid "%ld lines changed"
+msgstr "%ld lines changed"
+
+#: ops.c:2647
+#, c-format
+msgid "freeing %ld lines"
+msgstr "freeing %ld lines"
+
+#: ops.c:2928
+msgid "1 line yanked"
+msgstr "1 line yanked"
+
+#: ops.c:2930
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld lines yanked"
+
+#: ops.c:3215
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: %s ·¹Áö½ºÅÍ¿¡ ¾Æ¹« °Íµµ ¾ø½À´Ï´Ù"
+
+#. Highlight title
+#: ops.c:3766
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- ·¹Áö½ºÅÍ ---"
+
+#: ops.c:5075
+msgid "Illegal register name"
+msgstr "ÀÌ»óÇÑ ·¹Áö½ºÅÍ À̸§"
+
+#: ops.c:5163
+#, c-format
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# ·¹Áö½ºÅÍ:\n"
+
+#: ops.c:5213
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: ¸ð¸£´Â ·¹Áö½ºÅÍ Çü½Ä %d"
+
+#: ops.c:5698
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: À߸øµÈ ·¹Áö½ºÅÍ À̸§: '%s'"
+
+#: ops.c:6058
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld ¿­; "
+
+#: ops.c:6065
+#, c-format
+#~ msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+#~ msgstr ""
+
+#: ops.c:6081
+#, c-format
+#~ msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+#~ msgstr ""
+
+#: ops.c:6092
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld for BOM)"
+
+#: option.c:1643
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=ÆäÀÌÁö %N"
+
+#: option.c:2092
+msgid "Thanks for flying Vim"
+msgstr "ºöÀ» ³¯°Ô ÇØ Áּż­ °í¸¿½À´Ï´Ù"
+
+#: option.c:3419 option.c:3535
+msgid "E518: Unknown option"
+msgstr "E518: ¸ð¸£´Â ¿É¼Ç"
+
+#: option.c:3432
+msgid "E519: Option not supported"
+msgstr "E519: Áö¿øµÇÁö ¾Ê´Â ¿É¼ÇÀÔ´Ï´Ù"
+
+#: option.c:3457
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: ¸ðµå¶óÀο¡¼­ »ç¿ëµÉ ¼ö ¾ø½À´Ï´Ù"
+
+#: option.c:3522
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tLast set from "
+
+#: option.c:3661
+msgid "E521: Number required after ="
+msgstr "E521: = µÚ¿¡ ¼ýÀÚ°¡ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: option.c:3989 option.c:4619
+msgid "E522: Not found in termcap"
+msgstr "E522: termcap¿¡¼­ ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: option.c:4064
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: ÀÌ»óÇÑ ±ÛÀÚ <%s>"
+
+#: option.c:4611
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: 'term'À» ºó ¹®ÀÚ¿­·Î ¼³Á¤ÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: option.c:4614
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: GUI¿¡¼­´Â termÀ» ¹Ù²Ü ¼ö ¾ø½À´Ï´Ù"
+
+#: option.c:4616
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: GUI¸¦ ½ÃÀÛÇÏ·Á¸é \":gui\"¸¦ »ç¿ëÇϽʽÿÀ"
+
+#: option.c:4645
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: 'backupext'¿Í 'patchmode'°¡ µ¿ÀÏÇÕ´Ï´Ù"
+
+#: option.c:4860
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: GTK+ 2 GUI¿¡¼­´Â ¹Ù²ð ¼ö ¾ø½À´Ï´Ù"
+
+#: option.c:5016
+msgid "E524: Missing colon"
+msgstr "E524: ÄÝ·ÐÀÌ ¾ø½À´Ï´Ù"
+
+#: option.c:5018
+msgid "E525: Zero length string"
+msgstr "E525: ºó ¹®ÀÚ¿­ÀÔ´Ï´Ù"
+
+#: option.c:5086
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: <%s> µÚ¿¡ ¼ýÀÚ°¡ ¾ø½À´Ï´Ù"
+
+#: option.c:5100
+msgid "E527: Missing comma"
+msgstr "E527: ÄÞ¸¶°¡ ¾ø½À´Ï´Ù"
+
+#: option.c:5107
+msgid "E528: Must specify a ' value"
+msgstr "E528: ' °ªÀ» ¸í½ÃÇØ ÁÖ¼Å¾ß ÇÕ´Ï´Ù"
+
+#: option.c:5148
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: Ãâ·ÂÇÒ ¼ö ¾ø´Â, ȤÀº ¿ÍÀÌµå ¹®ÀÚ¸¦ Æ÷ÇÔÇÏ°í ÀÖ½À´Ï´Ù"
+
+#: option.c:5197
+msgid "E596: Invalid font(s)"
+msgstr "E596: À߸øµÈ ±Û²Ã(µé)"
+
+#: option.c:5205
+msgid "E597: can't select fontset"
+msgstr "E597: ±Û²Ã¼ÂÀ» °í¸¦ ¼ö ¾ø½À´Ï´Ù"
+
+#: option.c:5207
+msgid "E598: Invalid fontset"
+msgstr "E598: À߸øµÈ ±Û²Ã¼Â"
+
+#: option.c:5214
+msgid "E533: can't select wide font"
+msgstr "E533: ¿ÍÀÌµå ±Û²ÃÀ» °í¸¦ ¼ö ¾ø½À´Ï´Ù"
+
+#: option.c:5216
+msgid "E534: Invalid wide font"
+msgstr "E534: À߸øµÈ ¿ÍÀÌµå ±Û²Ã"
+
+#: option.c:5486
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: <%c> µÚ¿¡ ÀÌ»óÇÑ ±ÛÀÚ"
+
+#: option.c:5597
+msgid "E536: comma required"
+msgstr "E536: ÄÞ¸¶°¡ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: option.c:5607
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: 'commentstring'Àº ºñ°Å³ª %sÀ»(¸¦) Æ÷ÇÔÇØ¾ß ÇÕ´Ï´Ù"
+
+#: option.c:5682
+msgid "E538: No mouse support"
+msgstr "E538: ¸¶¿ì½º¸¦ Áö¿øÇÏÁö ¾Ê½À´Ï´Ù"
+
+#: option.c:5950
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: ´ÝÈ÷Áö ¾ÊÀº Ç¥Çö½Ä ¹è¿­"
+
+#: option.c:5954
+msgid "E541: too many items"
+msgstr "E541: ³Ê¹« ¸¹Àº Ç׸ñ"
+
+#: option.c:5956
+msgid "E542: unbalanced groups"
+msgstr "E542: ±ÕÇüÀÌ ¾È ÀâÈù ±×·ì"
+
+#: option.c:6196
+msgid "E590: A preview window already exists"
+msgstr "E590: ¹Ì¸® º¸±â âÀÌ ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù"
+
+#: option.c:6453
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr "W17: ArabicÀº UTF-8 ÀÎÄÚµù ÇÊ¿ä, ':set encoding=utf-8' Çϼ¼¿ä"
+
+#: option.c:6786
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: Àû¾îµµ %d ÁÙÀÌ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: option.c:6796
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: Àû¾îµµ %d Ä­ÀÌ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: option.c:7103
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: ¸ð¸£´Â ¿É¼Ç: %s"
+
+#: option.c:7223
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Å͹̳ΠÄÚµå ---"
+
+#: option.c:7225
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Àü¿ª ¿É¼Ç °ª ---"
+
+#: option.c:7227
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Áö¿ª ¿É¼Ç °ª ---"
+
+#: option.c:7229
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- ¿É¼Ç ---"
+
+#: option.c:7935
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp ¿¡·¯"
+
+#: option.c:8906
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': %s¿¡ ´ëÇÑ ¸Â´Â ±ÛÀÚ°¡ ¾ø½À´Ï´Ù"
+
+#: option.c:8940
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': ¼¼¹ÌÄÝ·Ð µÚ¿¡ ±ÛÀÚ°¡ ´õ ÀÖÀ½: %s"
+
+#: os_amiga.c:280
+msgid "cannot open "
+msgstr "cannot open "
+
+#: os_amiga.c:314
+msgid "VIM: Can't open window!\n"
+msgstr "ºö: âÀ» ¿­ ¼ö ¾ø½À´Ï´Ù!\n"
+
+#: os_amiga.c:338
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "¾Æ¹Ì°¡µµ½º 2.04³ª ´õ ³ôÀº ÆÇÀÌ ÇÊ¿äÇÕ´Ï´Ù\n"
+
+#: os_amiga.c:344
+#, c-format
+#~ msgid "Need %s version %ld\n"
+#~ msgstr ""
+
+#: os_amiga.c:416
+msgid "Cannot open NIL:\n"
+msgstr "NILÀ» ¿­ ¼ö ¾øÀ½:\n"
+
+#: os_amiga.c:427
+msgid "Cannot create "
+msgstr "Cannot create "
+
+#: os_amiga.c:905
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "ºöÀÌ %d °ªÀ¸·Î ³¡³À´Ï´Ù\n"
+
+#: os_amiga.c:941
+msgid "cannot change console mode ?!\n"
+msgstr "ÄÜ¼Ö »óŸ¦ ¹Ù²Ü ¼ö ¾ø½À´Ï´Ù ?!\n"
+
+#: os_amiga.c:1012
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: ÄܼÖÀÌ ¾Æ´Ñ°¡??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1161
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: -f ¿É¼ÇÀÌ »ç¿ëµÈ °æ¿ì ½©À» ½ÇÇàÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: os_amiga.c:1202 os_amiga.c:1292
+msgid "Cannot execute "
+msgstr "Cannot execute "
+
+#: os_amiga.c:1205 os_amiga.c:1302
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1225 os_amiga.c:1327
+msgid " returned\n"
+msgstr " returned\n"
+
+#: os_amiga.c:1468
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE°¡ ³Ê¹« ÀÛ½À´Ï´Ù."
+
+#: os_amiga.c:1472
+msgid "I/O ERROR"
+msgstr "I/O ¿¡·¯"
+
+#: os_mswin.c:543
+msgid "...(truncated)"
+msgstr "...(À߸²)"
+
+#: os_mswin.c:645
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns'ÀÌ 80ÀÌ ¾Æ´Ï¾î¼­, ¿ÜºÎ ¸í·ÉÀ» ½ÇÇàÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: os_mswin.c:1977
+msgid "E237: Printer selection failed"
+msgstr "E237: ÇÁ¸°Å͸¦ °í¸£Áö ¸øÇß½À´Ï´Ù"
+
+#: os_mswin.c:2017
+#, c-format
+#~ msgid "to %s on %s"
+#~ msgstr ""
+
+#: os_mswin.c:2032
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: ¸ð¸£´Â ÇÁ¸°ÅÍ ±Û²Ã: %s"
+
+#: os_mswin.c:2081 os_mswin.c:2091
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Àμ⠿¡·¯: %s"
+
+#: os_mswin.c:2092
+msgid "Unknown"
+msgstr "¸ð¸§"
+
+#: os_mswin.c:2119
+#, c-format
+msgid "Printing '%s'"
+msgstr "'%s' ÀμâÁß"
+
+#: os_mswin.c:3208
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: À߸øµÈ ±ÛÀڼ À̸§ \"%s\"ÀÌ(°¡) ±Û²Ã À̸§ \"%s\"¿¡ ÀÖ½À´Ï´Ù"
+
+#: os_mswin.c:3216
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: À߸øµÈ ±ÛÀÚ '%c'ÀÌ(°¡) ±Û²Ã À̸§ \"%s\"¿¡ ÀÖ½À´Ï´Ù"
+
+#: os_riscos.c:1259
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: À߸øµÈ 'osfiletype' ¿É¼Ç - Text¸¦ »ç¿ëÇÕ´Ï´Ù"
+
+#: os_unix.c:927
+msgid "Vim: Double signal, exiting\n"
+msgstr "ºö: °°Àº ½Ã±×³Î µÎ ¹ø, ³¡³À´Ï´Ù\n"
+
+#: os_unix.c:933
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "ºö: %s ½Ã±×³ÎÀ» Àâ¾Ò½À´Ï´Ù\n"
+
+#: os_unix.c:936
+#, c-format
+msgid "Vim: Caught deadly signal\n"
+msgstr "ºö: Á×À» ½Ã±×³ÎÀ» Àâ¾Ò½À´Ï´Ù\n"
+
+#: os_unix.c:1199
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "X µð½ºÇ÷¹À̸¦ ¿©´Â µ¥ %ld msecÀÌ °É·È½À´Ï´Ù"
+
+#: os_unix.c:1226
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"ºö: X ¿¡·¯°¡ »ý°å½À´Ï´Ù\n"
+
+#: os_unix.c:1338
+msgid "Testing the X display failed"
+msgstr "X µð½ºÇ÷¹ÀÌ ½ÃÇèÀÌ ½ÇÆÐÇß½À´Ï´Ù"
+
+#: os_unix.c:1477
+msgid "Opening the X display timed out"
+msgstr "X µð½ºÇ÷¹À̸¦ ¿­´Ù°¡ ½Ã°£ÀÌ ÃÊ°úµÇ¾ú½À´Ï´Ù"
+
+#: os_unix.c:3234 os_unix.c:3914
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"Cannot execute shell "
+
+#: os_unix.c:3282
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"½© sh¸¦ ½ÇÇàÇÒ ¼ö ¾ø½À´Ï´Ù\n"
+
+#: os_unix.c:3286 os_unix.c:3920
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"shell returned "
+
+#: os_unix.c:3421
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"ÆÄÀÌÇÁ¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù\n"
+
+#: os_unix.c:3436
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"ÀÚ½Ä ÇÁ·Î¼¼½º¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù\n"
+
+#: os_unix.c:3927
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"¸í·ÉÀÌ ³¡¸¶ÃÄÁ³½À´Ï´Ù\n"
+
+#: os_unix.c:4191 os_unix.c:4316 os_unix.c:5982
+msgid "XSMP lost ICE connection"
+msgstr "XSMP°¡ ICE ¿¬°áÀ» ÀÒ¾î¹ö·È½À´Ï´Ù"
+
+#: os_unix.c:5565
+msgid "Opening the X display failed"
+msgstr "X µð½ºÇ÷¹ÀÌ ¿­±â°¡ ½ÇÆÐÇß½À´Ï´Ù"
+
+#: os_unix.c:5887
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP°¡ save-yourself ¿äûÀ» ½ÇÇàÇÏ°í ÀÖ½À´Ï´Ù"
+
+#: os_unix.c:6006
+msgid "XSMP opening connection"
+msgstr "XSMP°¡ ¿¬°áÀ» ¿©´Â ÁßÀÔ´Ï´Ù"
+
+#: os_unix.c:6025
+msgid "XSMP ICE connection watch failed"
+msgstr "XSMP°¡ ICE ¿¬°á °¨½Ã¸¦ ½ÇÆÐÇß½À´Ï´Ù"
+
+#: os_unix.c:6045
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP SmcOpenConnection ½ÇÆÐ: %s"
+
+#: os_vms_mms.c:59
+#~ msgid "At line"
+#~ msgstr ""
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "¸í·ÉÇàÀ» À§ÇÑ ¸Þ¸ð¸®¸¦ ÇÒ´çÇÒ ¼ö ¾ø½À´Ï´Ù."
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "ºö ¿¡·¯"
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "vim32.dllÀ» ºÒ·¯ µéÀÏ ¼ö ¾ø½À´Ï´Ù!"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "ÇÔ¼ö Æ÷ÀÎÅ͸¦ DLL·Î ¹Ù²Ü ¼ö ¾ø½À´Ï´Ù!"
+
+#: os_win16.c:342 os_win32.c:3229
+#, c-format
+msgid "shell returned %d"
+msgstr "½©ÀÌ %dÀ»(¸¦) µ¹·ÁÁÖ¾ú½À´Ï´Ù"
+
+#: os_win32.c:2687
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "ºö: %s À̺¥Æ®¸¦ Àâ¾Ò½À´Ï´Ù\n"
+
+#: os_win32.c:2689
+msgid "close"
+msgstr "´Ý±â"
+
+#: os_win32.c:2691
+msgid "logoff"
+msgstr "·Î±×¾Æ¿ô"
+
+#: os_win32.c:2692
+msgid "shutdown"
+msgstr "¼Ë´Ù¿î"
+
+#: os_win32.c:3182
+msgid "E371: Command not found"
+msgstr "E371: ¸í·ÉÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: os_win32.c:3195
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE¸¦ $PATH¿¡¼­ ãÀ» ¼ö ¾ø½À´Ï´Ù.\n"
+"¿ÜºÎ ¸í·ÉÀÌ ³¡³­ µÚ ¸ØÃâ ¼ö ¾ø½À´Ï´Ù.\n"
+"´Ù ¸¹Àº Á¤º¸¸¦ º¸½Ã·Á¸é :help win32-vimrunÀ» º¸½Ê½Ã¿À."
+
+#: os_win32.c:3198
+msgid "Vim Warning"
+msgstr "ºö °æ°í"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Çü½Ä ¹®ÀÚ¿­¿¡ %%%cÀÌ(°¡) ³Ê¹« ¸¹½À´Ï´Ù"
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: Çü½Ä ¹®ÀÚ¿­¿¡ %%%cÀÌ(°¡) À߸øµÇ¾ú½À´Ï´Ù"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: Çü½Ä ¹®ÀÚ¿­¿¡ ]°¡ ¾ø½À´Ï´Ù"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: Çü½Ä ¹®ÀÚ¿­¿¡ Áö¿øµÇÁö ¾Ê´Â %%%cÀÌ(°¡) ÀÖ½À´Ï´Ù"
+
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: Çü½Ä ¹®ÀÚ¿­ ¼­µÎ¿¡ À߸øµÈ %%%cÀÌ(°¡) ÀÖ½À´Ï´Ù"
+
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: Çü½Ä ¹®ÀÚ¿­¿¡ À߸øµÈ %%%cÀÌ(°¡) ÀÖ½À´Ï´Ù"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat'ÀÌ ¾î¶² ÆÐÅϵµ Æ÷ÇÔÇÏ°í ÀÖÁö ¾Ê½À´Ï´Ù"
+
+#: quickfix.c:501
+msgid "E379: Missing or empty directory name"
+msgstr "E379: ºüÁ³°Å³ª ºó ÀÚ·á¹æ À̸§"
+
+#: quickfix.c:990
+msgid "E553: No more items"
+msgstr "E553: ´õ ÀÌ»óÀÇ Ç׸ñÀÌ ¾ø½À´Ï´Ù"
+
+#: quickfix.c:1229
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d of %d)%s%s: "
+
+#: quickfix.c:1231
+msgid " (line deleted)"
+msgstr " (ÁÙÀ» Áö¿üÀ½)"
+
+#: quickfix.c:1444
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: ÄüÇȽº ½ºÅÃÀÇ ¹Ù´ÚÀÔ´Ï´Ù"
+
+#: quickfix.c:1453
+msgid "E381: At top of quickfix stack"
+msgstr "E381: ÄüÇȽº ½ºÅÃÀÇ ²À´ë±âÀÔ´Ï´Ù"
+
+#: quickfix.c:1465
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "error list %d of %d; %d errors"
+
+#: quickfix.c:1943
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: ¾µ ¼ö ¾øÀ½, 'buftype' ¿É¼ÇÀÌ ¼³Á¤µÇ¾î ÀÖ½À´Ï´Ù"
+
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: %s%%[]¿¡ À߸øµÈ Ç׸ñ"
+
+#: regexp.c:838
+msgid "E339: Pattern too long"
+msgstr "E339: ÆÐÅÏÀÌ ³Ê¹« ±é´Ï´Ù"
+
+#: regexp.c:1009
+msgid "E50: Too many \\z("
+msgstr "E50: \\z(°¡ ³Ê¹« ¸¹½À´Ï´Ù"
+
+#: regexp.c:1020
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: %s(°¡ ³Ê¹« ¸¹½À´Ï´Ù"
+
+#: regexp.c:1077
+msgid "E52: Unmatched \\z("
+msgstr "E52: ¸ÂÁö ¾Ê´Â \\z("
+
+#: regexp.c:1081
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: ¸ÂÁö ¾Ê´Â %s%%("
+
+#: regexp.c:1083
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: ¸ÂÁö ¾Ê´Â %s("
+
+#: regexp.c:1088
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: ¸ÂÁö ¾Ê´Â %s)"
+
+#: regexp.c:1258
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: %s* ¿¬»ê¼ö´Â ºô ¼ö ÀÖ½À´Ï´Ù"
+
+#: regexp.c:1261
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: %s+ ¿¬»ê¼ö´Â ºô ¼ö ÀÖ½À´Ï´Ù"
+
+#: regexp.c:1316
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: %s@ µÚ¿¡ À߸øµÈ ¹®ÀÚ"
+
+#: regexp.c:1344
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: %s{ ¿¬»ê¼ö´Â ºô ¼ö ÀÖ½À´Ï´Ù"
+
+#: regexp.c:1354
+#, c-format
+#~ msgid "E60: Too many complex %s{...}s"
+#~ msgstr ""
+
+#: regexp.c:1370
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: Nested %s*"
+
+#: regexp.c:1373
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: Nested %s%c"
+
+#: regexp.c:1491
+msgid "E63: invalid use of \\_"
+msgstr "E63: \\_¸¦ Àß ¸ø »ç¿ë"
+
+#: regexp.c:1536
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c µÚ¿¡ ¾Æ¹«°Íµµ ¾ø½À´Ï´Ù"
+
+#: regexp.c:1592
+msgid "E65: Illegal back reference"
+msgstr "E65: ÀÌ»óÇÑ ÈÄÀ§ ÂüÁ¶"
+
+#: regexp.c:1605
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z(´Â ¿©±â¿¡¼­ Çã¿ëµÇÁö ¾Ê½À´Ï´Ù"
+
+#: regexp.c:1624
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 µîÀº ¿©±â¿¡¼­ Çã¿ëµÇÁö ¾Ê½À´Ï´Ù"
+
+#: regexp.c:1635
+msgid "E68: Invalid character after \\z"
+msgstr "E68: \\z µÚ¿¡ ÀÌ»óÇÑ ¹®ÀÚ"
+
+#: regexp.c:1684
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: %s%%[ µÚ¿¡ ]°¡ ¾ø½À´Ï´Ù"
+
+#: regexp.c:1700
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: ºó %s%%[]"
+
+#: regexp.c:1760
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: %s%% µÚ¿¡ ÀÌ»óÇÑ ¹®ÀÚ"
+
+#: regexp.c:2557
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: %s{...}¿¡ ±¸¹® ¿¡·¯"
+
+#: regexp.c:2863 regexp.c:3016
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Á×À½ °¡·Îè; Á¤±ÔÇ¥Çö½ÄÀÌ ³Ê¹« º¹ÀâÇÑ°¡¿ä?"
+
+#: regexp.c:3004 regexp.c:3013
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: ÆÐÅÏ¿¡ ÀÇÇØ ½ºÅóÑħ ¿¡·¯°¡ »ý°å½À´Ï´Ù"
+
+#: regexp.c:3258
+#~ msgid "External submatches:\n"
+#~ msgstr ""
+
+#: screen.c:2184
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld ÁÙ Á¢Èû "
+
+#: screen.c:7996
+msgid " VREPLACE"
+msgstr " ¼±ÅÃġȯ"
+
+#: screen.c:8000
+msgid " REPLACE"
+msgstr " ¹Ù²Ù±â"
+
+#: screen.c:8005
+msgid " REVERSE"
+msgstr " ¹Ý´ë"
+
+#: screen.c:8007
+msgid " INSERT"
+msgstr " ³¢¿ö³Ö±â"
+
+#: screen.c:8010
+msgid " (insert)"
+msgstr " (³¢¿ö³Ö±â)"
+
+#: screen.c:8012
+msgid " (replace)"
+msgstr " (¹Ù²Ù±â)"
+
+#: screen.c:8014
+msgid " (vreplace)"
+msgstr " (¼±ÅÃġȯ)"
+
+#: screen.c:8017
+msgid " Hebrew"
+msgstr " Çìºê·ç"
+
+#: screen.c:8028
+#~ msgid " Arabic"
+#~ msgstr ""
+
+#: screen.c:8031
+msgid " (lang)"
+msgstr " (¾ð¾î)"
+
+#: screen.c:8035
+msgid " (paste)"
+msgstr " (ºÙÀ̱â)"
+
+#: screen.c:8048
+msgid " VISUAL"
+msgstr " ºñÁÖ¾ó"
+
+#: screen.c:8049
+msgid " VISUAL LINE"
+msgstr " ºñÁÖ¾ó ¶óÀÎ"
+
+#: screen.c:8050
+msgid " VISUAL BLOCK"
+msgstr " ºñÁÖ¾ó ºí·Ï"
+
+#: screen.c:8051
+msgid " SELECT"
+msgstr " °í¸£±â"
+
+#: screen.c:8052
+msgid " SELECT LINE"
+msgstr " ¶óÀÎ °í¸£±â"
+
+#: screen.c:8053
+msgid " SELECT BLOCK"
+msgstr " ºí·Ï °í¸£±â"
+
+#: screen.c:8068 screen.c:8131
+msgid "recording"
+msgstr "±â·ÏÁß"
+
+#: search.c:37
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "óÀ½±îÁö ã¾ÒÀ½, ³¡¿¡¼­ °è¼Ó"
+
+#: search.c:38
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "³¡±îÁö ã¾ÒÀ½, óÀ½ºÎÅÍ °è¼Ó"
+
+#: search.c:526
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: À߸øµÈ ã±â ¹®ÀÚ¿­: %s"
+
+#: search.c:853
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: óÀ½±îÁö ¸Â´Â ¹®ÀÚ¿­ÀÌ ¾ø½À´Ï´Ù: %s"
+
+#: search.c:856
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: ³¡±îÁö ¸Â´Â ¹®ÀÚ¿­ÀÌ ¾ø½À´Ï´Ù: %s"
+
+#: search.c:1249
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: ';' µÚ¿¡´Â '?'³ª '/'°¡ ¿Í¾ß ÇÕ´Ï´Ù"
+
+#: search.c:3759
+msgid " (includes previously listed match)"
+msgstr " (ÀÌÀü¿¡ ¸Â¾Ò´ø ¸ñ·Ï Æ÷ÇÔ)"
+
+#. cursor at status line
+#: search.c:3779
+msgid "--- Included files "
+msgstr "--- Included files "
+
+#: search.c:3781
+msgid "not found "
+msgstr "not found "
+
+#: search.c:3782
+msgid "in path ---\n"
+msgstr "in path ---\n"
+
+#: search.c:3839
+msgid " (Already listed)"
+msgstr " (Already listed)"
+
+#: search.c:3841
+msgid " NOT FOUND"
+msgstr " ¸ø ã¾ÒÀ½"
+
+#: search.c:3893
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Æ÷ÇÔµÈ ÆÄÀÏ Ã£´Â Áß: %s"
+
+#: search.c:4111
+msgid "E387: Match is on current line"
+msgstr "E387: ¸Â´Â °Ô ÇöÀç ÁÙ¿¡ ÀÖ½À´Ï´Ù"
+
+#: search.c:4254
+msgid "All included files were found"
+msgstr "¸ðµç Æ÷ÇÔµÈ ÆÄÀÏÀ» ã¾Ò½À´Ï´Ù"
+
+#: search.c:4256
+msgid "No included files"
+msgstr "Æ÷ÇÔµÈ ÆÄÀÏÀÌ ¾ø½À´Ï´Ù"
+
+#: search.c:4272
+msgid "E388: Couldn't find definition"
+msgstr "E388: Á¤ÀǸ¦ ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: search.c:4274
+msgid "E389: Couldn't find pattern"
+msgstr "E389: ÆÐÅÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: syntax.c:3050
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: À߸øµÈ ÀÎÀÚ: %s"
+
+#: syntax.c:3230
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: ÀÌ·± ±¸¹® Ŭ·¯½ºÅÍ´Â ¾ø½À´Ï´Ù: %s"
+
+#: syntax.c:3394
+msgid "No Syntax items defined for this buffer"
+msgstr "ÀÌ ¹öÆÛ¿¡ ´ëÇØ Á¤ÀÇµÈ ±¸¹® Ç׸ñÀÌ ¾ø½À´Ï´Ù"
+
+#: syntax.c:3402
+msgid "syncing on C-style comments"
+msgstr "C-Çü½Ä ÁÖ¼®¹®¿¡ µ¿±â¸ÂÃã"
+
+#: syntax.c:3410
+#~ msgid "no syncing"
+#~ msgstr ""
+
+#: syntax.c:3413
+#~ msgid "syncing starts "
+#~ msgstr ""
+
+#: syntax.c:3415 syntax.c:3490
+#~ msgid " lines before top line"
+#~ msgstr ""
+
+#: syntax.c:3420
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Syntax µ¿±â Ç׸ñµé ---"
+
+#: syntax.c:3425
+#~ msgid ""
+#~ "\n"
+#~ "syncing on items"
+#~ msgstr ""
+
+#: syntax.c:3431
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Syntax Ç׸ñ ---"
+
+#: syntax.c:3454
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: ÀÌ·± ±¸¹® Ŭ·¯½ºÅÍ´Â ¾ø½À´Ï´Ù: %s"
+
+#: syntax.c:3480
+#~ msgid "minimal "
+#~ msgstr ""
+
+#: syntax.c:3487
+#~ msgid "maximal "
+#~ msgstr ""
+
+#: syntax.c:3499
+#~ msgid "; match "
+#~ msgstr ""
+
+#: syntax.c:3501
+#~ msgid " line breaks"
+#~ msgstr ""
+
+#: syntax.c:4135
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: group[t]here´Â ¿©±â¿¡¼­ »ç¿ëµÉ ¼ö ¾ø½À´Ï´Ù"
+
+#: syntax.c:4159
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: %s¿¡ ´ëÇÑ region Ç׸ñÀ» ãÁö ¸øÇß½À´Ï´Ù"
+
+#: syntax.c:4187
+msgid "E395: contains argument not accepted here"
+msgstr "E395: contains ÀÎÀÚ´Â ¿©±â¿¡ ¾µ ¼ö ¾ø½À´Ï´Ù"
+
+#: syntax.c:4198
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: containedin ÀÎÀÚ´Â ¿©±â¿¡ ¾µ ¼ö ¾ø½À´Ï´Ù"
+
+#: syntax.c:4276
+msgid "E397: Filename required"
+msgstr "E397: ÆÄÀÏÀ̸§ÀÌ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: syntax.c:4614
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: '='ÀÌ ¾ø½À´Ï´Ù: %s"
+
+#: syntax.c:4772
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: ÃæºÐÄ¡ ¾ÊÀº ÀÎÀÚ: ±¸¹® ¿µ¿ª %s"
+
+#: syntax.c:5103
+msgid "E400: No cluster specified"
+msgstr "E400: Ŭ·¯½ºÅÍ°¡ ¸í½ÃµÇÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: syntax.c:5140
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: ÆÐÅÏ ±¸ºÐÀÚ¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù: %s"
+
+#: syntax.c:5215
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: ÆÐÅÏ µÚ¿¡ ¾²·¹±â: %s"
+
+#: syntax.c:5305
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: syntax sync: ÁÙ ¿¬¼Ó ÆÐÅÏÀÌ µÎ ¹ø »ç¿ëµÇ¾ú½À´Ï´Ù"
+
+#: syntax.c:5362
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: ºñÁ¤»óÀûÀÎ ÀÎÀÚ: %s"
+
+#: syntax.c:5412
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: ÀÌÄ÷ ±âÈ£°¡ ºüÁ³À½: %s"
+
+#: syntax.c:5418
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: ºó ÀÎÀÚ: %s"
+
+#: syntax.c:5445
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %sÀº(´Â) ¿©±â¿¡¼­ Çã¿ëµÇÁö ¾Ê½À´Ï´Ù"
+
+#: syntax.c:5452
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %sÀº(´Â) contains ¸ñ·ÏÀÇ Ã¹ ¹ø°¿©¾ß ÇÕ´Ï´Ù"
+
+#: syntax.c:5522
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: ¸ð¸£´Â ±×·ì À̸§: %s"
+
+#: syntax.c:5755
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: À߸øµÈ :syntax ÇÏÀ§ ¸í·É: %s"
+
+#: syntax.c:6136
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: ÇÏÀ̶óÀÌÆ® ±×·ìÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù: %s"
+
+#: syntax.c:6160
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: ÃæºÐÄ¡ ¾ÊÀº ÀÎÀÚ: \":highlight link %s\""
+
+#: syntax.c:6167
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: ³Ê¹« ¸¹Àº ÀÎÀÚ: \":highlight link %s\""
+
+#: syntax.c:6187
+#~ msgid "E414: group has settings, highlight link ignored"
+#~ msgstr ""
+
+#: syntax.c:6316
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: ¶æ¹ÛÀÇ ÀÌÄ÷ ±âÈ£: %s"
+
+#: syntax.c:6352
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: ÀÌÄ÷ ±âÈ£°¡ ºüÁ³À½: %s"
+
+#: syntax.c:6380
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: ÀÎÀÚ°¡ ºüÁ³À½: %s"
+
+#: syntax.c:6417
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: ºñÁ¤»óÀûÀÎ °ª: %s"
+
+#: syntax.c:6536
+msgid "E419: FG color unknown"
+msgstr "E419: ¸ð¸£´Â FG »ö»ó"
+
+#: syntax.c:6547
+msgid "E420: BG color unknown"
+msgstr "E420: ¸ð¸£´Â BG »ö»ó"
+
+#: syntax.c:6608
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: »ö À̸§À̳ª ¼ýÀÚ¸¦ ÀνÄÇÒ ¼ö ¾øÀ½: %s"
+
+#: syntax.c:6814
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: Å͹̳ΠÄڵ尡 ³Ê¹« ±è: %s"
+
+#: syntax.c:6861
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: À߸øµÈ ÀÎÀÚ: %s"
+
+#: syntax.c:7390
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: ³Ê¹« ¸¹Àº ´Ù¸¥ ÇÏÀ̶óÀÌÆ® ¼Ó¼ºÀÌ »ç¿ëµÇ°í ÀÖ½À´Ï´Ù"
+
+#: syntax.c:7911
+msgid "E669: Unprintable character in group name"
+msgstr "E669: ±×·ì À̸§¿¡ Ãâ·ÂÇÒ ¼ö ¾ø´Â ¹®ÀÚ°¡ ÀÖ½À´Ï´Ù"
+
+#. This is an error, but since there previously was no check only
+#. * give a warning.
+#: syntax.c:7918
+msgid "W18: Invalid character in group name"
+msgstr "W18: ±×·ì À̸§¿¡ ÀÌ»óÇÑ ¹®ÀÚ"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: ÅÂ±× ½ºÅÃÀÇ ³¡ÀÔ´Ï´Ù"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: ÅÂ±× ½ºÅÃÀÇ Ã³À½ÀÔ´Ï´Ù"
+
+#: tag.c:412
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: ù ¹ø° ¸Â´Â ÅÂ±× ÀÌÀüÀ¸·Î´Â °¥ ¼ö ¾ø½À´Ï´Ù"
+
+#: tag.c:550
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: ű׸¦ ãÀ» ¼ö ¾øÀ½: %s"
+
+#: tag.c:583
+msgid " # pri kind tag"
+msgstr " # pri kind tag"
+
+#: tag.c:586
+msgid "file\n"
+msgstr "ÆÄÀÏ\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:744
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "°í¸¦ ¼ýÀÚ ÀÔ·Â (<CR>Àº ÁßÁö):"
+
+#: tag.c:784
+msgid "E427: There is only one matching tag"
+msgstr "E427: ¸Â´Â űװ¡ Çϳª ¹Û¿¡ ¾ø½À´Ï´Ù"
+
+#: tag.c:786
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: ¸¶Áö¸· ¸Â´Â ÅÂ±× µÚ·Î´Â °¥ ¼ö ¾ø½À´Ï´Ù"
+
+#: tag.c:810
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "ÆÄÀÏ \"%s\"ÀÌ(°¡) Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù"
+
+#. Give an indication of the number of matching tags
+#: tag.c:823
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "tag %d of %d%s"
+
+#: tag.c:826
+msgid " or more"
+msgstr " or more"
+
+#: tag.c:828
+msgid " Using tag with different case!"
+msgstr " Using tag with different case!"
+
+#: tag.c:872
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: ÆÄÀÏ \"%s\"ÀÌ(°¡) Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù"
+
+#. Highlight title
+#: tag.c:941
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # TO tag FROM line in file/text"
+
+#: tag.c:1363
+#, c-format
+msgid "Searching tags file %s"
+msgstr "ÅÂ±× ÆÄÀÏ %s ã´Â Áß"
+
+#: tag.c:1550
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: %s¿¡ ´ëÇÑ ÅÂ±× ÆÄÀÏ °æ·Î°¡ À߷ȽÀ´Ï´Ù\n"
+
+#: tag.c:2203
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: ÅÂ±× ÆÄÀÏ \"%s\"¿¡ Çü½Ä ¿¡·¯°¡ ÀÖ½À´Ï´Ù"
+
+#: tag.c:2207
+#, c-format
+#~ msgid "Before byte %ld"
+#~ msgstr ""
+
+#: tag.c:2240
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: ÅÂ±× ÆÄÀÏÀÌ Á¤·ÄµÇ¾î ÀÖÁö ¾ÊÀ½: %s"
+
+#. never opened any tags file
+#: tag.c:2280
+msgid "E433: No tags file"
+msgstr "E433: ÅÂ±× ÆÄÀÏÀÌ ¾ø½À´Ï´Ù"
+
+#: tag.c:3016
+msgid "E434: Can't find tag pattern"
+msgstr "E434: ÅÂ±× ÆÐÅÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: tag.c:3027
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: ű׸¦ ãÀ» ¼ö ¾øÁö¸¸ ÀÌ°Å °°½À´Ï´Ù!"
+
+#: term.c:1759
+msgid "' not known. Available builtin terminals are:"
+msgstr "' not known. Available builtin terminals are:"
+
+#: term.c:1783
+msgid "defaulting to '"
+msgstr "defaulting to '"
+
+#: term.c:2141
+msgid "E557: Cannot open termcap file"
+msgstr "E557: termcap ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: term.c:2145
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: Å͹̳ΠÇ׸ñÀ» terminfo¿¡¼­ ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: term.c:2147
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: Å͹̳ΠÇ׸ñÀ» termcap¿¡¼­ ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: term.c:2306
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: termcap¿¡ \"%s\" Ç׸ñÀÌ ¾ø½À´Ï´Ù"
+
+#: term.c:2780
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: Å͹̳ÎÀÌ \"cm\" ±â´ÉÀ» Áö¿øÇØ¾ß ÇÕ´Ï´Ù"
+
+#. Highlight title
+#: term.c:4990
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Å͹̳ΠŰ ---"
+
+#: ui.c:258
+msgid "new shell started\n"
+msgstr "»õ ½©ÀÌ ½ÃÀ۵Ǿú½À´Ï´Ù\n"
+
+#: ui.c:1841
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "ºö: ÀÔ·Â Àд Áß ¿¡·¯, ³¡³»´ÂÁß...\n"
+
+#. must display the prompt
+#: undo.c:405
+msgid "No undo possible; continue anyway"
+msgstr "Ãë¼Ò ºÒ°¡´É; ¾î·µç °è¼ÓÇÕ´Ï´Ù"
+
+#: undo.c:561
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: À߸øµÈ ÁÙ ¹øÈ£"
+
+#: undo.c:757
+msgid "1 change"
+msgstr "Çϳª ¹Ù²Ù¾ú½À´Ï´Ù"
+
+#: undo.c:759
+#, c-format
+msgid "%ld changes"
+msgstr "%ld°³¸¦ ¹Ù²Ù¾ú½À´Ï´Ù"
+
+#: undo.c:812
+msgid "E439: undo list corrupt"
+msgstr "E439: undo ¸ñ·ÏÀÌ ±úÁ³½À´Ï´Ù"
+
+#: undo.c:844
+msgid "E440: undo line missing"
+msgstr "E440: undo ÁÙÀÌ ¾ø½À´Ï´Ù"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:707
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 16/32 ºñÆ® GUI ÆÇ"
+
+#: version.c:709
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 32 ºñÆ® GUI ÆÇ"
+
+#: version.c:712
+msgid " in Win32s mode"
+msgstr " Win32s »óÅÂ"
+
+#: version.c:714
+msgid " with OLE support"
+msgstr " OLE Áö¿ø"
+
+#: version.c:717
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"MS-Windows 32 ºñÆ® ÄÜ¼Ö ÆÇ"
+
+#: version.c:721
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"MS-Windows 16 ºñÆ® ÆÇ"
+
+#: version.c:725
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 ºñÆ® MS-DOS ÆÇ"
+
+#: version.c:727
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 ºñÆ® MS-DOS ÆÇ"
+
+#: version.c:733
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (À¯´Ð½º) ÆÇ"
+
+#: version.c:735
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X ÆÇ"
+
+#: version.c:738
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS ÆÇ"
+
+#: version.c:743
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS ÆÇ"
+
+#: version.c:753
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Æ÷ÇÔµÈ ÆÐÄ¡: "
+
+#: version.c:779 version.c:1147
+#~ msgid "Modified by "
+#~ msgstr ""
+
+#: version.c:786
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Compiled "
+
+#: version.c:789
+msgid "by "
+msgstr "by "
+
+#: version.c:801
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"°Å´ëÇÑ ÆÇ "
+
+#: version.c:804
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Å« ÆÇ "
+
+#: version.c:807
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"º¸Åë ÆÇ "
+
+#: version.c:810
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"ÀÛÀº ÆÇ "
+
+#: version.c:812
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"¾ÆÁÖ ÀÛÀº ÆÇ "
+
+#: version.c:818
+msgid "without GUI."
+msgstr "GUI ¾øÀ½."
+
+#: version.c:823
+msgid "with GTK2-GNOME GUI."
+msgstr "GTK2-GNOME GUI."
+
+#: version.c:825
+msgid "with GTK-GNOME GUI."
+msgstr "GTK-GNOME GUI."
+
+#: version.c:829
+msgid "with GTK2 GUI."
+msgstr "GTK2 GUI."
+
+#: version.c:831
+msgid "with GTK GUI."
+msgstr "GTK GUI."
+
+#: version.c:836
+msgid "with X11-Motif GUI."
+msgstr "X11-Motif GUI."
+
+#: version.c:840
+msgid "with X11-neXtaw GUI."
+msgstr "X11-neXtaw GUI."
+
+#: version.c:842
+msgid "with X11-Athena GUI."
+msgstr "X11-Athena GUI."
+
+#: version.c:846
+msgid "with BeOS GUI."
+msgstr "BeOS GUI."
+
+#: version.c:849
+msgid "with Photon GUI."
+msgstr "Æ÷Åæ GUI."
+
+#: version.c:852
+msgid "with GUI."
+msgstr "GUI."
+
+#: version.c:855
+msgid "with Carbon GUI."
+msgstr "Carbon GUI."
+
+#: version.c:858
+msgid "with Cocoa GUI."
+msgstr "Cocoa GUI."
+
+#: version.c:861
+msgid "with (classic) GUI."
+msgstr "(Ŭ·¡½Ä) GUI."
+
+#: version.c:872
+msgid " Features included (+) or not (-):\n"
+msgstr " ±â´É (+: Æ÷ÇÔµÊ, -: Æ÷ÇÔ ¾È µÊ):\n"
+
+#: version.c:884
+msgid " system vimrc file: \""
+msgstr " ½Ã½ºÅÛ vimrc ÆÄÀÏ: \""
+
+#: version.c:889
+msgid " user vimrc file: \""
+msgstr " »ç¿ëÀÚ vimrc ÆÄÀÏ: \""
+
+#: version.c:894
+msgid " 2nd user vimrc file: \""
+msgstr " »ç¿ëÀÚ µÎ ¹ø° vimrc ÆÄÀÏ: \""
+
+#: version.c:899
+msgid " 3rd user vimrc file: \""
+msgstr " »ç¿ëÀÚ ¼¼ ¹ø° vimrc ÆÄÀÏ: \""
+
+#: version.c:904
+msgid " user exrc file: \""
+msgstr " »ç¿ëÀÚ exrc ÆÄÀÏ: \""
+
+#: version.c:909
+msgid " 2nd user exrc file: \""
+msgstr " »ç¿ëÀÚ µÎ ¹ø° exrc ÆÄÀÏ: \""
+
+#: version.c:915
+msgid " system gvimrc file: \""
+msgstr " ½Ã½ºÅÛ gvimrc ÆÄÀÏ: \""
+
+#: version.c:919
+msgid " user gvimrc file: \""
+msgstr " »ç¿ëÀÚ gvimrc ÆÄÀÏ: \""
+
+#: version.c:923
+msgid "2nd user gvimrc file: \""
+msgstr "»ç¿ëÀÚ µÎ ¹ø° gvimrc ÆÄÀÏ: \""
+
+#: version.c:928
+msgid "3rd user gvimrc file: \""
+msgstr "»ç¿ëÀÚ ¼¼ ¹ø° gvimrc ÆÄÀÏ: \""
+
+#: version.c:935
+msgid " system menu file: \""
+msgstr " ½Ã½ºÅÛ Â÷¸²Ç¥ ÆÄÀÏ: \""
+
+#: version.c:943
+msgid " fall-back for $VIM: \""
+msgstr " fall-back for $VIM: \""
+
+#: version.c:949
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " f-b for $VIMRUNTIME: \""
+
+#: version.c:953
+msgid "Compilation: "
+msgstr "ÄÄÆÄÀÏ: "
+
+#: version.c:959
+msgid "Compiler: "
+msgstr "ÄÄÆÄÀÏ·¯: "
+
+#: version.c:964
+msgid "Linking: "
+msgstr "¸µÅ©: "
+
+#: version.c:969
+msgid " DEBUG BUILD"
+msgstr " µð¹ö±× ºôµå"
+
+#: version.c:1008
+msgid "VIM - Vi IMproved"
+msgstr "ºö - Çâ»óµÈ Vi"
+
+#: version.c:1010
+msgid "version "
+msgstr "ÆÇ "
+
+#: version.c:1011
+msgid "by Bram Moolenaar et al."
+msgstr "by Bram Moolenaar et al."
+
+#: version.c:1015
+msgid "Vim is open source and freely distributable"
+msgstr "ºöÀº ¼Ò½º°¡ ¿­·Á ÀÖ°í °øÂ¥·Î ¹èÆ÷µË´Ï´Ù"
+
+#: version.c:1017
+msgid "Help poor children in Uganda!"
+msgstr "¿ì°£´Ù¿¡ »ç´Â °¡³­ÇÑ ¾ÆÀ̸¦ µµ¿ÍÁÖ¼¼¿ä!"
+
+#: version.c:1018
+msgid "type :help iccf<Enter> for information "
+msgstr "ÀÌ¿¡ ´ëÇÑ Á¤º¸¸¦ º¸·Á¸é :help iccf<¿£ÅÍ> ÀÔ·Â"
+
+#: version.c:1020
+msgid "type :q<Enter> to exit "
+msgstr "³¡³»·Á¸é :q<¿£ÅÍ> ÀÔ·Â"
+
+#: version.c:1021
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "¿Â¶óÀÎ µµ¿ò¸»À» º¸·Á¸é :help<¿£ÅÍ> ¶Ç´Â <F1> ÀÔ·Â"
+
+#: version.c:1022
+msgid "type :help version6<Enter> for version info"
+msgstr "ÆÇ Á¤º¸¸¦ º¸·Á¸é :help version6<¿£ÅÍ> ÀÔ·Â"
+
+#: version.c:1025
+msgid "Running in Vi compatible mode"
+msgstr "Vi ȣȯ »óÅ·Π½ÇÇàÁßÀÔ´Ï´Ù"
+
+#: version.c:1026
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "ºö ±âº»°ªÀ» »ç¿ëÇÏ·Á¸é :set nocp<¿£ÅÍ> ÀÔ·Â"
+
+#: version.c:1027
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "ÀÌ¿¡ ´ëÇÑ Á¤º¸¸¦ º¸·Á¸é :help cp-default<¿£ÅÍ> ÀÔ·Â"
+
+#: version.c:1042
+msgid "menu Help->Orphans for information "
+msgstr "ÀÌ¿¡ ´ëÇÑ Á¤º¸¸¦ º¸·Á¸é ¸Þ´º¿¡¼­ µµ¿ò¸»->°í¾Æ ¼±ÅÃ"
+
+#: version.c:1044
+msgid "Running modeless, typed text is inserted"
+msgstr "¸ðµå¾øÀÌ ¼öÇàÁßÀ̸ç, ÀÔ·ÂµÈ ¹®ÀÚ´Â »ðÀԵ˴ϴÙ"
+
+#: version.c:1045
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "¸Þ´º¿¡¼­ ÆíÁý->Àü¿ª ¼³Á¤->»ðÀÔ ¸ðµå Åä±ÛÀ» ¼±ÅÃÇϽøé "
+
+#: version.c:1046
+msgid " for two modes "
+msgstr " µÎ ¸ðµå¸¦ »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù "
+
+#: version.c:1050
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "¸Þ´º¿¡¼­ ÆíÁý->Àü¿ª ¼³Á¤->Vi ȣȯ Åä±ÛÀ» ¼±ÅÃÇϽøé "
+
+#: version.c:1051
+msgid " for Vim defaults "
+msgstr " VimÀÌ ±âº»°ªÀ¸·Î µ¿ÀÛÇÕ´Ï´Ù "
+
+#: version.c:1098
+msgid "Sponsor Vim development!"
+msgstr "ºö °³¹ßÀ» ÈÄ¿øÇØ ÁÖ¼¼¿ä!"
+
+#: version.c:1099
+msgid "Become a registered Vim user!"
+msgstr "ºö »ç¿ëÀÚ·Î µî·ÏÇϼ¼¿ä!"
+
+#: version.c:1102
+msgid "type :help sponsor<Enter> for information "
+msgstr "ÀÌ¿¡ ´ëÇÑ Á¤º¸¸¦ º¸·Á¸é :help sponsor<¿£ÅÍ> ÀÔ·Â"
+
+#: version.c:1103
+msgid "type :help register<Enter> for information "
+msgstr "ÀÌ¿¡ ´ëÇÑ Á¤º¸¸¦ º¸·Á¸é :help register<¿£ÅÍ> ÀÔ·Â"
+
+#: version.c:1105
+msgid "menu Help->Sponsor/Register for information "
+msgstr "ÀÌ¿¡ ´ëÇÑ Á¤º¸¸¦ º¸·Á¸é ¸Þ´º µµ¿ò¸»->Sponsor/Register"
+
+#: version.c:1115
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "°æ°í: À©µµ¿ìÁî 95/98/ME¸¦ ã¾ÒÀ½"
+
+#: version.c:1118
+msgid "type :help windows95<Enter> for info on this"
+msgstr "ÀÌ¿¡ ´ëÇÑ Á¤º¸¸¦ º¸·Á¸é :help windows95<¿£ÅÍ> ÀÔ·Â"
+
+#: window.c:203
+msgid "E441: There is no preview window"
+msgstr "E441: ¹Ì¸® º¸±â âÀÌ ¾ø½À´Ï´Ù"
+
+#: window.c:581
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: À§ ¿ÞÂÊ°ú ¾Æ·¡ ¿À¸¥ÂÊÀ» µ¿½Ã¿¡ ³ª´­ ¼ö ¾ø½À´Ï´Ù"
+
+#: window.c:1340
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: ´Ù¸¥ âÀÌ ³ª´²Á³À» ¶§¿¡´Â ȸÀüÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: window.c:1836
+msgid "E444: Cannot close last window"
+msgstr "E444: ¸¶Áö¸· âÀ» ´ÝÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: window.c:2567
+msgid "Already only one window"
+msgstr "ÀÌ¹Ì ÇϳªÀÇ Ã¢¸¸ ÀÖ½À´Ï´Ù"
+
+#: window.c:2614
+msgid "E445: Other window contains changes"
+msgstr "E445: ´Ù¸¥ âÀÌ ¹Ù²î¾ú½À´Ï´Ù"
+
+#: window.c:4480
+msgid "E446: No file name under cursor"
+msgstr "E446: Ä¿¼­ ¹Ø¿¡ ÆÄÀÏ À̸§ÀÌ ¾ø½À´Ï´Ù"
+
+#: window.c:4599
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: path¿¡¼­ \"%s\" ÆÄÀÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: if_perl.xs:326 globals.h:1241
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: %s ¶óÀ̺귯¸®¸¦ ·ÎµåÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: if_perl.xs:554
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr "¹Ì¾ÈÇÕ´Ï´Ù, ÀÌ ¸í·ÉÀº »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù, Perl ¶óÀ̺귯¸®¸¦ ·ÎµùÇÒ ¼ö ¾ø"
+"½À´Ï´Ù."
+
+#: if_perl.xs:607
+#~ msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+#~ msgstr ""
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "¿©·¯ ºöÀ¸·Î ÆíÁý(&M)"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "ÇϳªÀÇ ºöÀ¸·Î¸¸ ÆíÁý(&V)"
+
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "ºöÀ¸·Î Diff(&D)"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "ºöÀ¸·Î ÆíÁý(&V)"
+
+#. Now concatenate
+#: GvimExt/gvimext.cpp:633
+#~ msgid "Edit with existing Vim - &"
+#~ msgstr ""
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "¼±ÅÃµÈ ÆÄÀÏ(µé)À» ºöÀ¸·Î ÆíÁý"
+
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "ÇÁ·Î¼¼½º »ý¼º ¿¡·¯: gvimÀÌ path¿¡ ÀÖ´Â Áö È®ÀÎÇϼ¼¿ä!"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "gvimext.dll ¿¡·¯"
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "°æ·Î°¡ ³Ê¹« ±é´Ï´Ù"
+
+#: globals.h:1031
+msgid "--No lines in buffer--"
+msgstr "--¹öÆÛ¿¡ ÁÙ ¾øÀ½--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1194
+msgid "E470: Command aborted"
+msgstr "E470: ¸í·ÉÀÌ ÁßÁöµÇ¾ú½À´Ï´Ù"
+
+#: globals.h:1195
+msgid "E471: Argument required"
+msgstr "E471: ÀÎÀÚ°¡ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: globals.h:1196
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: /, ? ȤÀº &´Â \\ µÚ¿¡ ¿Í¾ß ÇÕ´Ï´Ù"
+
+#: globals.h:1198
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: ¸í·ÉÁ٠â¿¡ À߸øµÊ; <CR> ½ÇÇà, CTRL-C ³¡³»±â"
+
+#: globals.h:1200
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: ÇöÀç ÀÚ·á¹æ ¶ÇÀº ÅÂ±× Ã£±â¿¡¼­ exrc/vimrc¿¡¼­ÀÇ ¸í·ÉÀº Çã¿ë ¾È µË´Ï´Ù"
+
+#: globals.h:1202
+msgid "E171: Missing :endif"
+msgstr "E171: :endif°¡ ¾ø½À´Ï´Ù"
+
+#: globals.h:1203
+msgid "E600: Missing :endtry"
+msgstr "E600: :endtry°¡ ¾ø½À´Ï´Ù"
+
+#: globals.h:1204
+msgid "E170: Missing :endwhile"
+msgstr "E170: :endwhileÀÌ ¾ø½À´Ï´Ù"
+
+#: globals.h:1205
+msgid "E588: :endwhile without :while"
+msgstr "E588: :while¾øÀÌ :endwhileÀÌ ÀÖ½À´Ï´Ù"
+
+#: globals.h:1207
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: ÆÄÀÏÀÌ ÀÖ½À´Ï´Ù (µ¤¾î¾²·Á¸é ! »ç¿ë)"
+
+#: globals.h:1208
+msgid "E472: Command failed"
+msgstr "E472: ¸í·ÉÀÌ ½ÇÆÐÇß½À´Ï´Ù"
+
+#: globals.h:1210
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: ¸ð¸£´Â ±Û²Ã¼Â: %s"
+
+#: globals.h:1214
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: ¸ð¸£´Â ±Û²Ã: %s"
+
+#: globals.h:1217
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: ±Û²Ã \"%s\"Àº(´Â) °íÁ¤³ÐÀÌ°¡ ¾Æ´Õ´Ï´Ù"
+
+#: globals.h:1219
+msgid "E473: Internal error"
+msgstr "E473: ³»ºÎ ¿¡·¯"
+
+#: globals.h:1220
+msgid "Interrupted"
+msgstr "ÁߴܵǾú½À´Ï´Ù"
+
+#: globals.h:1221
+msgid "E14: Invalid address"
+msgstr "E14: À߸øµÈ ÁÖ¼Ò"
+
+#: globals.h:1222
+msgid "E474: Invalid argument"
+msgstr "E474: À߸øµÈ ÀÎÀÚ"
+
+#: globals.h:1223
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: À߸øµÈ ÀÎÀÚ: %s"
+
+#: globals.h:1225
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: À߸øµÈ Ç¥Çö½Ä: %s"
+
+#: globals.h:1227
+msgid "E16: Invalid range"
+msgstr "E16: À߸øµÈ ¹üÀ§"
+
+#: globals.h:1228
+msgid "E476: Invalid command"
+msgstr "E476: À߸øµÈ ¸í·É"
+
+#: globals.h:1230
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\"Àº(´Â) ÀÚ·á¹æÀÔ´Ï´Ù"
+
+#: globals.h:1233
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: '=' Àü¿¡ »ý°¢Áö ¸øÇÑ ±ÛÀÚ"
+
+#: globals.h:1236
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: ¶óÀ̺귯¸® \"%s()\" ºÎ¸£±â ½ÇÆÐ"
+
+#: globals.h:1242
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: %s ¶óÀ̺귯¸® ÇÔ¼ö¸¦ ·ÎµåÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1244
+msgid "E19: Mark has invalid line number"
+msgstr "E19: ¸¶Å©°¡ À߸øµÈ ÁÙ ¹øÈ£¸¦ °¡Áö°í ÀÖ½À´Ï´Ù"
+
+#: globals.h:1245
+msgid "E20: Mark not set"
+msgstr "E20: ¸¶Å©°¡ ¼³Á¤µÇ¾î ÀÖÁö ¾Ê½À´Ï´Ù"
+
+#: globals.h:1246
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: ¹Ù²Ü ¼ö ¾øÀ½, 'modifiable'ÀÌ ²¨Á®ÀÖ½À´Ï´Ù"
+
+#: globals.h:1247
+msgid "E22: Scripts nested too deep"
+msgstr "E22: ½ºÅ©¸³Æ®°¡ ³Ê¹« ±í°Ô ÁßøµÇ¾ú½À´Ï´Ù"
+
+#: globals.h:1248
+msgid "E23: No alternate file"
+msgstr "E23: ´Ù¸¥ ÆÄÀÏÀÌ ¾ø½À´Ï´Ù"
+
+#: globals.h:1249
+msgid "E24: No such abbreviation"
+msgstr "E24: ±×·± ¾à¾î´Â ¾ø½À´Ï´Ù"
+
+#: globals.h:1250
+msgid "E477: No ! allowed"
+msgstr "E477: !Àº Çã¿ëµÇÁö ¾Ê½À´Ï´Ù"
+
+#: globals.h:1252
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: GUI´Â »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù: ÄÄÆÄÀÏ ¶§ Æ÷ÇÔµÇÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: globals.h:1255
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: Hebrew´Â »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù: ÄÄÆÄÀÏ ¶§ Æ÷ÇÔµÇÁö ¾Ê¾Ò½À´Ï´Ù\n"
+
+#: globals.h:1258
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: Farsi´Â »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù: ÄÄÆÄÀÏ ¶§ Æ÷ÇÔµÇÁö ¾Ê¾Ò½À´Ï´Ù\n"
+
+#: globals.h:1261
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: ArabicÀº »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù: ÄÄÆÄÀÏ ¶§ Æ÷ÇÔµÇÁö ¾Ê¾Ò½À´Ï´Ù\n"
+
+#: globals.h:1264
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: ÀÌ·± ÇÏÀ̶óÀÌÆ® ±×·ì À̸§Àº ¾ø½À´Ï´Ù: %s"
+
+#: globals.h:1266
+msgid "E29: No inserted text yet"
+msgstr "E29: ÀÔ·ÂµÈ ÅؽºÆ®°¡ ¾ÆÁ÷ ¾ø½À´Ï´Ù"
+
+#: globals.h:1267
+msgid "E30: No previous command line"
+msgstr "E30: ÀÌÀü ¸í·É ÁÙÀÌ ¾ø½À´Ï´Ù"
+
+#: globals.h:1268
+msgid "E31: No such mapping"
+msgstr "E31: ±×·± ¸ÊÇÎÀÌ ¾ø½À´Ï´Ù"
+
+#: globals.h:1269
+msgid "E479: No match"
+msgstr "E479: ¸ÂÁö ¾Ê½À´Ï´Ù"
+
+#: globals.h:1270
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: ¸ÂÁö ¾ÊÀ½: %s"
+
+#: globals.h:1271
+msgid "E32: No file name"
+msgstr "E32: ÆÄÀÏ À̸§ÀÌ ¾ø½À´Ï´Ù"
+
+#: globals.h:1272
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: ÀÌÀü ¹Ù²Ù±â Á¤±Ô Ç¥Çö½ÄÀÌ ¾ø½À´Ï´Ù"
+
+#: globals.h:1273
+msgid "E34: No previous command"
+msgstr "E34: ÀÌÀü ¸í·ÉÀÌ ¾ø½À´Ï´Ù"
+
+#: globals.h:1274
+msgid "E35: No previous regular expression"
+msgstr "E35: ÀÌÀü Á¤±ÔÇ¥Çö½ÄÀÌ ¾ø½À´Ï´Ù"
+
+#: globals.h:1275
+msgid "E481: No range allowed"
+msgstr "E481: ¹üÀ§´Â Çã¿ëµÇÁö ¾Ê½À´Ï´Ù"
+
+#: globals.h:1277
+msgid "E36: Not enough room"
+msgstr "E36: ºó °ø°£ÀÌ ÃæºÐÇÏÁö ¾Ê½À´Ï´Ù"
+
+#: globals.h:1280
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: \"%s\"Àº(´Â) µî·ÏµÈ ¼­¹ö¸íÀÌ ¾Æ´Õ´Ï´Ù"
+
+#: globals.h:1282
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: %s ÆÄÀÏÀ» ¸¸µé ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1283
+msgid "E483: Can't get temp file name"
+msgstr "E483: Àӽà ÆÄÀÏ À̸§À» ¾òÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1284
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: %s ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1285
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: %s ÆÄÀÏÀ» ÀÐÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1286
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: ¸¶Áö¸·À¸·Î °íÄ£ µÚ ÀúÀåµÇÁö ¾Ê¾Ò½À´Ï´Ù (µ¤¾î¾²·Á¸é ! ´õÇϱâ)"
+
+#: globals.h:1287
+msgid "E38: Null argument"
+msgstr "E38: ³Î ÀÎÀÚ"
+
+#: globals.h:1289
+msgid "E39: Number expected"
+msgstr "E39: ¼ýÀÚ°¡ ÇÊ¿äÇÕ´Ï´Ù"
+
+#: globals.h:1292
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: ¿¡·¯ÆÄÀÏ %sÀ»(¸¦) ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1295
+msgid "E233: cannot open display"
+msgstr "E233: µð½ºÇ÷¹À̸¦ ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1297
+msgid "E41: Out of memory!"
+msgstr "E41: ¸Þ¸ð¸®°¡ ¹Ù´Ú³µ½À´Ï´Ù!"
+
+#: globals.h:1299
+msgid "Pattern not found"
+msgstr "ÆÐÅÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1301
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: ÆÐÅÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù: %s"
+
+#: globals.h:1302
+msgid "E487: Argument must be positive"
+msgstr "E487: ÀÎÀÚ´Â ¾ç¼öÀ̾î¾ß ÇÕ´Ï´Ù"
+
+#: globals.h:1304
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: ÀÌÀü µð·ºÅ丮·Î °¥ ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1308
+msgid "E42: No Errors"
+msgstr "E42: ¿¡·¯ ¾øÀ½"
+
+#: globals.h:1310
+msgid "E43: Damaged match string"
+msgstr "E43: ±úÁø ¸Â´Â ¹®ÀÚ¿­"
+
+#: globals.h:1311
+msgid "E44: Corrupted regexp program"
+msgstr "E44: ±úÁø Á¤±ÔÇ¥Çö½Ä ÇÁ·Î±×·¥"
+
+#: globals.h:1312
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: 'readonly' ¿É¼ÇÀÌ ¼³Á¤µÇ¾î ÀÖ½À´Ï´Ù (µ¤¾î¾²·Á¸é ! ´õÇϱâ)"
+
+#: globals.h:1314
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Àбâ Àü¿ë º¯¼ö \"%s\"À»(¸¦) ¼³Á¤ÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1317
+msgid "E47: Error while reading errorfile"
+msgstr "E47: ¿¡·¯ÆÄÀÏ Àд µµÁß¿¡ ¿¡·¯"
+
+#: globals.h:1320
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: sandbox¿¡¼­´Â Çã¿ëµÇÁö ¾Ê½À´Ï´Ù"
+
+#: globals.h:1322
+msgid "E523: Not allowed here"
+msgstr "E523: ¿©±â¿¡¼­ Çã¿ëµÇÁö ¾Ê½À´Ï´Ù"
+
+#: globals.h:1325
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: ½ºÅ©¸° »óÅ ¼³Á¤Àº Áö¿øµÇÁö ¾Ê½À´Ï´Ù"
+
+#: globals.h:1327
+msgid "E49: Invalid scroll size"
+msgstr "E49: ½ºÅ©·Ñ Å©±â°¡ À߸øµÇ¾ú½À´Ï´Ù"
+
+#: globals.h:1328
+msgid "E91: 'shell' option is empty"
+msgstr "E91: 'shell' ¿É¼ÇÀÌ ºñ¾ú½À´Ï´Ù"
+
+#: globals.h:1330
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: sign ÀڷḦ ÀÐÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1332
+msgid "E72: Close error on swap file"
+msgstr "E72: ½º¿Ò ÆÄÀÏÀ» ´ÝÀ» ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1333
+msgid "E73: tag stack empty"
+msgstr "E73: ÅÂ±× ½ºÅÃÀÌ ºñ¾ú½À´Ï´Ù"
+
+#: globals.h:1334
+msgid "E74: Command too complex"
+msgstr "E74: ¸í·ÉÀÌ ³Ê¹« º¹ÀâÇÕ´Ï´Ù"
+
+#: globals.h:1335
+msgid "E75: Name too long"
+msgstr "E75: À̸§ÀÌ ³Ê¹« ±é´Ï´Ù"
+
+#: globals.h:1336
+msgid "E76: Too many ["
+msgstr "E76: [°¡ ³Ê¹« ¸¹½À´Ï´Ù"
+
+#: globals.h:1337
+msgid "E77: Too many file names"
+msgstr "E77: ÆÄÀÏ À̸§ÀÌ ³Ê¹« ¸¹½À´Ï´Ù"
+
+#: globals.h:1338
+msgid "E488: Trailing characters"
+msgstr "E488: ³¡¿¡ ¹®ÀÚ°¡ ´õ ÀÖ½À´Ï´Ù"
+
+#: globals.h:1339
+msgid "E78: Unknown mark"
+msgstr "E78: ¸ð¸£´Â ¸¶Å©"
+
+#: globals.h:1340
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: ¸¸´É ±ÛÀÚ¸¦ È®ÀåÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: globals.h:1342
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: 'winheight'´Â 'winminheight'º¸´Ù Ä¿¾ß ÇÕ´Ï´Ù"
+
+#: globals.h:1344
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: 'winwidth'´Â 'winminwidth'º¸´Ù Ä¿¾ß ÇÕ´Ï´Ù"
+
+#: globals.h:1347
+msgid "E80: Error while writing"
+msgstr "E80: ¾²´Â Áß¿¡ ¿¡·¯"
+
+#: globals.h:1348
+#~ msgid "Zero count"
+#~ msgstr ""
+
+#: globals.h:1350
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: ½ºÅ©¸³Æ® ÄÜÅؽºÆ® ¹Û¿¡¼­ <SID> »ç¿ë"
+
+#: globals.h:1353
+msgid "E449: Invalid expression received"
+msgstr "E449: À߸øµÈ Ç¥Çö½ÄÀÌ ¹Þ¾ÆÁ³½À´Ï´Ù"
+
+#: globals.h:1356
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: ¿µ¿ªÀÌ º¸È£µÇ°í À־ ¼öÁ¤ÇÒ ¼ö ¾ø½À´Ï´Ù"
diff --git a/src/po/no.po b/src/po/no.po
new file mode 100644
index 000000000..817440e47
--- /dev/null
+++ b/src/po/no.po
@@ -0,0 +1,6630 @@
+# Norwegian (Bokmål) translation of Vim.
+# Copyright (C) 2003-2004 Free Software Foundation, Inc.
+# FIRST AUTHOR Øyvind A. Holm <sunny@sunbase.org>, 2003-2004.
+# no.po 317 2004-06-11 12:54:59Z sunny
+#
+# Comments and error reports appreciated.
+#
+# Information about the "Vim in Norwegian" project:
+#
+# http://www.sunbase.org/src/vim/norwegian/
+#
+# New versions of the translation files can be downloaded in .tar.gz
+# format from
+#
+# http://svn.sunbase.org/repos/norwegian_vim/download/
+#
+# The files are stored in the Subversion version control system and
+# users of this software can check out the latest version with
+#
+# svn checkout http://svn.sunbase.org/repos/norwegian_vim/trunk/msgs norwegian_vim-msgs
+#
+# This will place the message files into the "norwegian_vim-msgs"
+# directory.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim 6.x\n"
+"POT-Creation-Date: 2004-06-11 14:38+0200\n"
+"PO-Revision-Date: 2003-05-13 08:19+0200\n"
+"Last-Translator: Øyvind A. Holm <sunny@sunbase.org>\n"
+"Language-Team: Norwegian <vim.in.norwegian@sunbase.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Report-Msgid-Bugs-To: sunny@sunbase.org\n"
+
+#: buffer.c:102
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Kan ikke reservere plass til noen buffere, avslutter ..."
+
+#: buffer.c:105
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: Kan ikke reservere plass til buffer, bruker en annen ..."
+
+#: buffer.c:808
+msgid "E515: No buffers were unloaded"
+msgstr "E515: Ingen buffere ble lastet ut"
+
+#: buffer.c:810
+msgid "E516: No buffers were deleted"
+msgstr "E516: Ingen buffere ble slettet"
+
+#: buffer.c:812
+msgid "E517: No buffers were wiped out"
+msgstr "E517: Ingen buffere ble visket ut"
+
+#: buffer.c:820
+msgid "1 buffer unloaded"
+msgstr "1 buffer ble lastet ut"
+
+#: buffer.c:822
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "%d buffere ble lastet ut"
+
+#: buffer.c:827
+msgid "1 buffer deleted"
+msgstr "1 buffer ble slettet"
+
+#: buffer.c:829
+#, c-format
+msgid "%d buffers deleted"
+msgstr "%d buffere ble slettet"
+
+#: buffer.c:834
+msgid "1 buffer wiped out"
+msgstr "1 buffer ble visket ut"
+
+#: buffer.c:836
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "%d buffere ble visket ut"
+
+#: buffer.c:897
+msgid "E84: No modified buffer found"
+msgstr "E84: Fant ingen modifisert buffer"
+
+#. back where we started, didn't find anything.
+#: buffer.c:936
+msgid "E85: There is no listed buffer"
+msgstr "E85: Det finnes ingen listede buffere"
+
+#: buffer.c:948
+#, c-format
+msgid "E86: Buffer %ld does not exist"
+msgstr "E86: Bufferen %ld finnes ikke"
+
+#: buffer.c:951
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Kan ikke gå forbi siste buffer"
+
+#: buffer.c:953
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Kan ikke gå forbi første buffer"
+
+#: buffer.c:991
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr ""
+"E89: Ikke lagret siden forrige forandring av bufferen %ld (legg til ! for å "
+"overstyre)"
+
+#: buffer.c:1008
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: Kan ikke laste ut siste buffer"
+
+#: buffer.c:1544
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Advarsel: Listen med filnavn er overfylt"
+
+#: buffer.c:1716
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: Fant ikke bufferen %ld"
+
+#: buffer.c:1947
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Mer enn ett treff for %s"
+
+#: buffer.c:1949
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: Ingen samsvarende buffer for %s"
+
+#: buffer.c:2344
+#, c-format
+msgid "line %ld"
+msgstr "linje %ld"
+
+#: buffer.c:2429
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: En buffer med dette navnet finnes allerede"
+
+#: buffer.c:2724
+msgid " [Modified]"
+msgstr " [Modifisert]"
+
+#: buffer.c:2729
+msgid "[Not edited]"
+msgstr "[Uredigert]"
+
+#: buffer.c:2734
+msgid "[New file]"
+msgstr "[Ny fil]"
+
+#: buffer.c:2735
+msgid "[Read errors]"
+msgstr "[Lesefeil]"
+
+#: buffer.c:2737 fileio.c:2124
+msgid "[readonly]"
+msgstr "[skrivebeskyttet]"
+
+#: buffer.c:2758
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 linje --%d%%--"
+
+#: buffer.c:2760
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld linjer --%d%%--"
+
+#: buffer.c:2767
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "linje %ld av %ld --%d%%-- kol "
+
+#: buffer.c:2875
+msgid "[No file]"
+msgstr "[Uten navn]"
+
+#. must be a help buffer
+#: buffer.c:2915
+msgid "help"
+msgstr "hjelp"
+
+#: buffer.c:3474 screen.c:5079
+msgid "[help]"
+msgstr "[hjelp]"
+
+#: buffer.c:3506 screen.c:5085
+msgid "[Preview]"
+msgstr "[Forhåndsvisning]"
+
+#: buffer.c:3786
+msgid "All"
+msgstr "Alt"
+
+#: buffer.c:3786
+msgid "Bot"
+msgstr "Bunn"
+
+#: buffer.c:3788
+msgid "Top"
+msgstr "Topp"
+
+#: buffer.c:4536
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# Bufferliste:\n"
+
+#: buffer.c:4569
+msgid "[Error List]"
+msgstr "[Feilliste]"
+
+#: buffer.c:4582 memline.c:1521
+msgid "[No File]"
+msgstr "[Uten navn]"
+
+#: buffer.c:4895
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Skilt ---"
+
+#: buffer.c:4914
+#, c-format
+msgid "Signs for %s:"
+msgstr "Skilt for %s:"
+
+#: buffer.c:4920
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " linje=%ld id=%d navn=%s"
+
+#: diff.c:139
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: Kan ikke sammenligne flere enn %ld buffere"
+
+#: diff.c:713
+msgid "E97: Cannot create diffs"
+msgstr "E97: Kan ikke lage differansefiler"
+
+#: diff.c:819
+msgid "Patch file"
+msgstr "Patch fil"
+
+#: diff.c:1072
+msgid "E98: Cannot read diff output"
+msgstr "E98: Kan ikke lese differanse-utdata"
+
+#: diff.c:1822
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Nåværende buffer er ikke i differansemodus"
+
+#: diff.c:1834
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: Ingen annen buffer i differansemodus"
+
+#: diff.c:1842
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr ""
+"E101: Mer enn to buffere i differansemodus, vet ikke hvilken som skal brukes"
+
+#: diff.c:1865
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Kan ikke finne buffer \"%s\""
+
+#: diff.c:1871
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Bufferen \"%s\" er ikke i differansemodus"
+
+#: digraph.c:2199
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: Escape er ikke lovlig i spesialtegn"
+
+#: digraph.c:2384
+msgid "E544: Keymap file not found"
+msgstr "E544: Fant ikke keymap-fil"
+
+#: digraph.c:2411
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: Bruk av :loadkeymap utenfor en kjørt fil"
+
+#: edit.c:40
+msgid " Keyword completion (^N^P)"
+msgstr " Nøkkelordfullføring (^N^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E^Y^L^]^F^I^K^D^V^N^P)"
+msgstr " ^X-modus (^E^Y^L^]^F^I^K^D^V^N^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N^P)"
+msgstr " Lokal nøkkelordfullføring (^N^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L^N^P)"
+msgstr " Fullføring av hel linje (^L^N^P)"
+
+#: edit.c:46
+msgid " File name completion (^F^N^P)"
+msgstr " Fullføring av filnavn (^F^N^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]^N^P)"
+msgstr " Fullføring av tag (^]^N^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N^P)"
+msgstr " Stimønster-fullføring (^N^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D^N^P)"
+msgstr " Fullføring av defineringer (^D^N^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K^N^P)"
+msgstr " Fullføring fra ordliste (^K^N^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T^N^P)"
+msgstr " Thesaurus-fullføring (^T^N^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V^N^P)"
+msgstr " Kommandolinje-fullføring (^V^N^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Kom til slutten av avsnittet"
+
+#: edit.c:962
+msgid "'thesaurus' option is empty"
+msgstr "'thesaurus'-valget er tomt"
+
+#: edit.c:1166
+msgid "'dictionary' option is empty"
+msgstr "'dictionary'-valget er tomt"
+
+#: edit.c:2162
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Leter gjennom ordliste: %s"
+
+#: edit.c:2368
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (sett inn) Rulling (^E/^Y)"
+
+#: edit.c:2370
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (erstatt) Rulling (^E/^Y)"
+
+#: edit.c:2684
+#, c-format
+msgid "Scanning: %s"
+msgstr "Leter: %s"
+
+#: edit.c:2719
+msgid "Scanning tags."
+msgstr "Leter gjennom tagger."
+
+#: edit.c:3381
+msgid " Adding"
+msgstr " Legger til"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3430
+msgid "-- Searching..."
+msgstr "-- Søker ..."
+
+#: edit.c:3486
+msgid "Back at original"
+msgstr "Tilbake i originalen"
+
+#: edit.c:3491
+msgid "Word from other line"
+msgstr "Ord fra annen linje"
+
+#: edit.c:3496
+msgid "The only match"
+msgstr "Det eneste treffet"
+
+#: edit.c:3555
+#, c-format
+msgid "match %d of %d"
+msgstr "treff %d av %d"
+
+#: edit.c:3558
+#, c-format
+msgid "match %d"
+msgstr "treff %d"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:1024
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Ukjent variabel: \"%s\""
+
+#: eval.c:1320
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Mangler parenteser: %s"
+
+#: eval.c:1435 eval.c:1449
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Variabelen finnes ikke: \"%s\""
+
+#: eval.c:1705
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Mangler ':' etter '?'"
+
+#: eval.c:2327
+msgid "E110: Missing ')'"
+msgstr "E110: Mangler ')'"
+
+#: eval.c:2389
+msgid "E111: Missing ']'"
+msgstr "E111: Mangler ']'"
+
+#: eval.c:2466
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Navn på valg mangler: %s"
+
+#: eval.c:2484
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Ukjent valg: %s"
+
+#: eval.c:2555
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Mangler anførselstegn (\"): %s"
+
+#: eval.c:2698
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Mangler apostrof ('): %s"
+
+#: eval.c:3054
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Ugyldige parametere til funksjon %s"
+
+#: eval.c:3083
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Ukjent funksjon: %s"
+
+#: eval.c:3084
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: For mange parametere til funksjonen: %s"
+
+#: eval.c:3085
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Ikke nok parametere til funksjonen: %s"
+
+#: eval.c:3086
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: Bruk av \"<SID>\" utenfor skript-sammenheng: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3687 gui.c:4385 gui_gtk.c:2059
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:4226
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld linjer: "
+
+#: eval.c:5477
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&OK\n"
+"&Avbryt"
+
+#: eval.c:5517
+msgid "called inputrestore() more often than inputsave()"
+msgstr "kalte inputrestore() oftere enn inputsave()"
+
+#: eval.c:5977
+msgid "E655: Too many symbolic links (cycle?)"
+msgstr "E655: For mange symbolske linker (runddans?)"
+
+#: eval.c:6626
+msgid "E240: No connection to Vim server"
+msgstr "E240: Ingen forbindelse med Vim-tjeneren"
+
+#: eval.c:6724
+msgid "E277: Unable to read a server reply"
+msgstr "E277: Klarer ikke lese svar fra tjeneren"
+
+#: eval.c:6752
+msgid "E258: Unable to send to client"
+msgstr "E258: Klarer ikke sende til klienten"
+
+#: eval.c:6800
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Klarer ikke sende til %s"
+
+#: eval.c:6900
+msgid "(Invalid)"
+msgstr "(Ugyldig)"
+
+#: eval.c:8078
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Udefinert variabel: %s"
+
+#: eval.c:8510
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E461: Ugyldig variabelnavn: %s"
+
+#: eval.c:8802
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: Funksjonen %s eksisterer allerede, legg til ! for å erstatte den"
+
+#: eval.c:8875
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Udefinert funksjon: %s"
+
+#: eval.c:8888
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Mangler '(': %s"
+
+#: eval.c:8921
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Ugyldig parameter: %s"
+
+#: eval.c:9000
+msgid "E126: Missing :endfunction"
+msgstr "E126: Mangler :endfunction"
+
+#: eval.c:9107
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Kan ikke omdefinere funksjonen %s: Den er i bruk"
+
+#: eval.c:9177
+msgid "E129: Function name required"
+msgstr "E129: Funksjonsnavn nødvendig"
+
+#: eval.c:9228
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: Funksjonsnavn må ha stor forbokstav: %s"
+
+#: eval.c:9420
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Udefinert funksjon: %s"
+
+#: eval.c:9425
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Kan ikke slette funksjonen %s: Den er i bruk"
+
+#: eval.c:9473
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: Funksjonskalldybden er større enn 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:9526
+#, c-format
+msgid "calling %s"
+msgstr "kaller %s"
+
+#: eval.c:9588
+#, c-format
+msgid "%s aborted"
+msgstr "%s avbrutt"
+
+#: eval.c:9590
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s returnerer #%ld"
+
+#: eval.c:9597
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s returnerer \"%s\""
+
+#. always scroll up, don't overwrite
+#: eval.c:9613 ex_cmds2.c:2370
+#, c-format
+msgid "continuing in %s"
+msgstr "fortsetter i %s"
+
+#: eval.c:9639
+msgid "E133: :return not inside a function"
+msgstr "E133: :return er ikke innenfor en funksjon"
+
+#: eval.c:9970
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# globale variabler:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Hex %02x, Oktal %03o"
+
+#: ex_cmds.c:118
+#, c-format
+msgid "> %d, Hex %04x, Octal %o"
+msgstr "> %d, Hex %04x, Oktal %o"
+
+#: ex_cmds.c:119
+#, c-format
+msgid "> %d, Hex %08x, Octal %o"
+msgstr "> %d, Hex %08x, Oktal %o"
+
+#: ex_cmds.c:430
+msgid "E134: Move lines into themselves"
+msgstr "E134: Flytting av linjer inn i seg selv"
+
+#: ex_cmds.c:499
+msgid "1 line moved"
+msgstr "1 linje flyttet"
+
+#: ex_cmds.c:501
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld linjer flyttet"
+
+#: ex_cmds.c:924
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld linjer filtrert"
+
+#: ex_cmds.c:952
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *Filter* Autokommandoer må ikke forandre nåværende buffer"
+
+#: ex_cmds.c:1037
+msgid "[No write since last change]\n"
+msgstr "[Ikke lagret siden forrige forandring]\n"
+
+#: ex_cmds.c:1283
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s i linje: "
+
+#: ex_cmds.c:1288
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: For mange feil, hopper over resten av filen"
+
+#: ex_cmds.c:1323
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Leser viminfo-fil \"%s\"%s%s%s"
+
+#: ex_cmds.c:1324
+msgid " info"
+msgstr " info"
+
+#: ex_cmds.c:1325
+msgid " marks"
+msgstr " merker"
+
+#: ex_cmds.c:1326
+msgid " FAILED"
+msgstr " FEILET"
+
+#: ex_cmds.c:1418
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Viminfo-fil er ikke skrivbar: %s"
+
+#: ex_cmds.c:1543
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Kan ikke lagre viminfo-fil %s!"
+
+#: ex_cmds.c:1551
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Lagrer viminfo-fil \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1649
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Denne viminfo-filen ble generert av Vim %s.\n"
+
+#: ex_cmds.c:1651
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Du kan redigere den hvis du er forsiktig!\n"
+"\n"
+
+#: ex_cmds.c:1653
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Verdien av 'encoding' når denne filen ble skrevet\n"
+
+#: ex_cmds.c:1752
+msgid "Illegal starting char"
+msgstr "Ulovlig starttegn"
+
+#: ex_cmds.c:2097 ex_cmds2.c:761
+msgid "Save As"
+msgstr "Lagre som"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2140
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Filen er lastet i en annen buffer"
+
+#: ex_cmds.c:2174
+msgid "Write partial file?"
+msgstr "Skrive delvis fil?"
+
+#: ex_cmds.c:2181
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Bruk ! for å skrive delvis buffer"
+
+#: ex_cmds.c:2296
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Overskrive eksisterende fil \"%.*s\"?"
+
+#: ex_cmds.c:2367
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: Mangler filnavn for buffer %ld"
+
+#: ex_cmds.c:2406
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: Filen ble ikke lagret: Lagring er deaktivert med 'write'-valget"
+
+#: ex_cmds.c:2426
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"'readonly'-valget er satt for \"%.*s\".\n"
+"Vil du lagre likevel?"
+
+#: ex_cmds.c:2599
+msgid "Edit File"
+msgstr "Rediger fil"
+
+#: ex_cmds.c:3206
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Autokommandoer slettet uventet den nye bufferen %s"
+
+#: ex_cmds.c:3340
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: Ikke-numerisk parameter til :z"
+
+#: ex_cmds.c:3425
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: Skallkommandoer er ikke tillatt i rvim"
+
+#: ex_cmds.c:3532
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Regulære uttrykk kan ikke bli adskilt av bokstaver"
+
+#: ex_cmds.c:3878
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "Erstatt med %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4271
+msgid "(Interrupted) "
+msgstr "(Avbrutt) "
+
+#: ex_cmds.c:4275
+msgid "1 substitution"
+msgstr "1 erstatning"
+
+#: ex_cmds.c:4277
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld erstatninger"
+
+#: ex_cmds.c:4280
+msgid " on 1 line"
+msgstr " i 1 linje"
+
+#: ex_cmds.c:4282
+#, c-format
+msgid " on %ld lines"
+msgstr " i %ld linjer"
+
+#: ex_cmds.c:4333
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: Kan ikke gjøre :global rekursiv"
+
+#: ex_cmds.c:4368
+msgid "E148: Regular expression missing from global"
+msgstr "E148: Regulært uttrykk mangler i global kommando"
+
+#: ex_cmds.c:4417
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Søkestreng funnet i alle linjene: %s"
+
+#: ex_cmds.c:4498
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Siste erstatningstekst:\n"
+"$"
+
+#: ex_cmds.c:4599
+msgid "E478: Don't panic!"
+msgstr "E478: Ingen panikk!"
+
+#: ex_cmds.c:4651
+#, c-format
+msgid "E661: Sorry, no '%s' help for %s"
+msgstr "E661: Dessverre ingen '%s' hjelp for %s"
+
+#: ex_cmds.c:4654
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Dessverre ingen hjelp for %s"
+
+#: ex_cmds.c:4688
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Fant ikke hjelpefilen \"%s\""
+
+#: ex_cmds.c:5191
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: Er ikke en katalog: %s"
+
+#: ex_cmds.c:5332
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: Kan ikke åpne %s for skriving"
+
+#: ex_cmds.c:5368
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Kan ikke åpne %s for lesing"
+
+#: ex_cmds.c:5404
+#, c-format
+msgid "E670: Mix of help file encodings within a language: %s"
+msgstr "E670: Tegnsettblanding i hjelpefilen innenfor samme språk: %s"
+
+#: ex_cmds.c:5483
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s/%s"
+msgstr "E154: Duplikat-tag \"%s\" i filen %s/%s"
+
+#: ex_cmds.c:5599
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Ukjent skiltkommando: %s"
+
+#: ex_cmds.c:5619
+msgid "E156: Missing sign name"
+msgstr "E156: Mangler skiltnavn"
+
+#: ex_cmds.c:5665
+msgid "E612: Too many signs defined"
+msgstr "E612: For mange skilt definert"
+
+#: ex_cmds.c:5733
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Ugyldig skilttekst: %s"
+
+#: ex_cmds.c:5764 ex_cmds.c:5955
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Ukjent skilt: %s"
+
+#: ex_cmds.c:5813
+msgid "E159: Missing sign number"
+msgstr "E159: Mangler skiltnummer"
+
+#: ex_cmds.c:5895
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: Ugyldig buffernavn: %s"
+
+#: ex_cmds.c:5934
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Ulovlig skilt-ID: %ld"
+
+#: ex_cmds.c:6004
+msgid " (NOT FOUND)"
+msgstr " (IKKE FUNNET)"
+
+#: ex_cmds.c:6006
+msgid " (not supported)"
+msgstr " (ikke støttet)"
+
+#: ex_cmds.c:6105
+msgid "[Deleted]"
+msgstr "[Slettet]"
+
+#: ex_cmds2.c:92
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "Går inn i debuggingsmodus. Skriv \"cont\" for å fortsette."
+
+#: ex_cmds2.c:96 ex_docmd.c:968
+#, c-format
+msgid "line %ld: %s"
+msgstr "linje %ld: %s"
+
+#: ex_cmds2.c:98
+#, c-format
+msgid "cmd: %s"
+msgstr "kommando: %s"
+
+#: ex_cmds2.c:290
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Stoppunkt i \"%s%s\" linje %ld"
+
+#: ex_cmds2.c:540
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Fant ikke stoppunkt: %s"
+
+#: ex_cmds2.c:566
+msgid "No breakpoints defined"
+msgstr "Ingen stoppunkt definert"
+
+#: ex_cmds2.c:571
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s linje %ld"
+
+#: ex_cmds2.c:786
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Lagre forandringer til \"%.*s\"?"
+
+#: ex_cmds2.c:788 ex_docmd.c:9407
+msgid "Untitled"
+msgstr "Uten navn"
+
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Ikke lagret siden siste forandringer i bufferen \"%s\""
+
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "Advarsel: Gikk uventet inn i en annen buffer (sjekk autokommandoer)"
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: Det er bare en fil å redigere"
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: Kan ikke gå forbi første fil"
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Kan ikke gå forbi siste fil"
+
+#: ex_cmds2.c:1804
+#, c-format
+msgid "E666: compiler not supported: %s"
+msgstr "E666: Kompilatoren er ikke støttet: %s"
+
+#: ex_cmds2.c:1901
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Søker etter \"%s\" i \"%s\""
+
+#: ex_cmds2.c:1923
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Søker etter \"%s\""
+
+#: ex_cmds2.c:1945
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "ikke funnet i 'runtimepath': \"%s\""
+
+#: ex_cmds2.c:1979
+msgid "Source Vim script"
+msgstr "Kjør Vim-skript"
+
+#: ex_cmds2.c:2169
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "Kan ikke kjøre en katalog: \"%s\""
+
+#: ex_cmds2.c:2207
+#, c-format
+msgid "could not source \"%s\""
+msgstr "kunne ikke kjøre \"%s\""
+
+#: ex_cmds2.c:2209
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "linje %ld: Kunne ikke kjøre \"%s\""
+
+#: ex_cmds2.c:2223
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "kjører \"%s\""
+
+#: ex_cmds2.c:2225
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "linje %ld: kjører \"%s\""
+
+#: ex_cmds2.c:2368
+#, c-format
+msgid "finished sourcing %s"
+msgstr "ferdig med kjøring av %s"
+
+#: ex_cmds2.c:2712
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Advarsel: Feil linjeseparator, det er mulig ^M mangler"
+
+#: ex_cmds2.c:2761
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :scriptencoding brukt utenfor en kjørt fil"
+
+#: ex_cmds2.c:2794
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish brukt utenfor en kjørt fil"
+
+#: ex_cmds2.c:3243
+#, c-format
+msgid "Page %d"
+msgstr "Side %d"
+
+#: ex_cmds2.c:3399
+msgid "No text to be printed"
+msgstr "Ingen tekst for utskrift"
+
+#: ex_cmds2.c:3477
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "Skriver ut side %d (%d%%)"
+
+#: ex_cmds2.c:3489
+#, c-format
+msgid " Copy %d of %d"
+msgstr " Kopi %d av %d"
+
+#: ex_cmds2.c:3547
+#, c-format
+msgid "Printed: %s"
+msgstr "Skrevet ut: %s"
+
+#: ex_cmds2.c:3554
+msgid "Printing aborted"
+msgstr "Utskrift avbrutt"
+
+#: ex_cmds2.c:3919
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Feil under skriving til Postscript-fil"
+
+#: ex_cmds2.c:4194
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E624: Kan ikke åpne filen \"%s\""
+
+#: ex_cmds2.c:4204 ex_cmds2.c:4829
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Kan ikke lese Postscript-ressursfil \"%s\""
+
+#: ex_cmds2.c:4212
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: Filen \"%s\" er ikke en Postscript-ressursfil"
+
+#: ex_cmds2.c:4227 ex_cmds2.c:4247 ex_cmds2.c:4262 ex_cmds2.c:4284
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: Det er ikke støtte for Postscript-ressursfilen \"%s\""
+
+#: ex_cmds2.c:4314
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: Ressursfilen \"%s\" er feil versjon"
+
+#: ex_cmds2.c:4781
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Kan ikke åpne Postscript-fil for skriving"
+
+#: ex_cmds2.c:4814
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Kan ikke åpne filen \"%s\""
+
+#: ex_cmds2.c:4933
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr "E456: Fant ikke Postscript-ressursfilen \"prolog.ps\""
+
+#: ex_cmds2.c:4964
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: Fant ikke Postscript-ressursfilen \"%s.ps\""
+
+#: ex_cmds2.c:4982
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr "E620: Klarte ikke konvertere fra multibyte til \"%s\"-tegnsett"
+
+#: ex_cmds2.c:5107
+msgid "Sending to printer..."
+msgstr "Sender til skriver ..."
+
+#: ex_cmds2.c:5111
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: Feil under utskrift av Postscript-fil"
+
+#: ex_cmds2.c:5113
+msgid "Print job sent."
+msgstr "Skriverjobb sendt."
+
+#: ex_cmds2.c:5623
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Nåværende %sspråk: \"%s\""
+
+#: ex_cmds2.c:5634
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Kan ikke sette språk til \"%s\""
+
+#: ex_docmd.c:525
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Går inn i Ex-modus. Skriv \"visual\" for å gå til normalmodus."
+
+#. must be at EOF
+#: ex_docmd.c:561
+msgid "E501: At end-of-file"
+msgstr "E501: Ved slutten av filen"
+
+#: ex_docmd.c:670
+msgid "E169: Command too recursive"
+msgstr "E169: Kommando altfor rekursiv"
+
+#: ex_docmd.c:1232
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: Unntak ikke fanget opp: %s"
+
+#: ex_docmd.c:1320
+msgid "End of sourced file"
+msgstr "Slutt på kjørt fil"
+
+#: ex_docmd.c:1321
+msgid "End of function"
+msgstr "Slutt på funksjon"
+
+#: ex_docmd.c:1910
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: Flertydig bruk av brukerdefinert kommando"
+
+#: ex_docmd.c:1924
+msgid "E492: Not an editor command"
+msgstr "E492: Er ikke en editorkommando"
+
+#: ex_docmd.c:2031
+msgid "E493: Backwards range given"
+msgstr "E493: Område bakover er angitt"
+
+#: ex_docmd.c:2040
+msgid "Backwards range given, OK to swap"
+msgstr "Område bakover er angitt, OK å swappe"
+
+#: ex_docmd.c:2163
+msgid "E494: Use w or w>>"
+msgstr "E494: Bruk w eller w>>"
+
+#: ex_docmd.c:3789
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Kommandoen er ikke tilgjengelig i denne versjonen"
+
+#: ex_docmd.c:3992
+msgid "E172: Only one file name allowed"
+msgstr "E172: Bare ett filnavn tillatt"
+
+#: ex_docmd.c:4572
+msgid "1 more file to edit. Quit anyway?"
+msgstr "1 annen fil å redigere. Avslutt likevel?"
+
+#: ex_docmd.c:4575
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "%d andre filer å redigere. Avslutt likevel?"
+
+#: ex_docmd.c:4582
+msgid "E173: 1 more file to edit"
+msgstr "E173: 1 annen fil å redigere"
+
+#: ex_docmd.c:4584
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: %ld andre filer å redigere"
+
+#: ex_docmd.c:4679
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: Kommandoen finnes allerede: Legg til ! for å erstatte den"
+
+#: ex_docmd.c:4790
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Navn Prm. Områd Fullfør Definering"
+
+#: ex_docmd.c:4879
+msgid "No user-defined commands found"
+msgstr "Ingen brukerdefinerte kommandoer funnet"
+
+#: ex_docmd.c:4911
+msgid "E175: No attribute specified"
+msgstr "E175: Ingen attributt spesifisert"
+
+#: ex_docmd.c:4963
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Ugyldig antall parametere"
+
+#: ex_docmd.c:4978
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: Antall repeteringer kan ikke bli spesifisert to ganger"
+
+#: ex_docmd.c:4988
+msgid "E178: Invalid default value for count"
+msgstr "E178: Ugyldig standardverdi for antall repeteringer"
+
+#: ex_docmd.c:5019
+msgid "E179: argument required for complete"
+msgstr "E179: Trenger parameter til \"complete\""
+
+#: ex_docmd.c:5051
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Ugyldig \"complete\"-verdi: %s"
+
+#: ex_docmd.c:5060
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr "E468: Fullføringsparameter er bare tillatt for tilpasset fullføring"
+
+#: ex_docmd.c:5066
+msgid "E467: Custom completion requires a function argument"
+msgstr "E467: Tilpassede fullføringer trenger et funksjonsparameter"
+
+#: ex_docmd.c:5077
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Ugyldig attributt: %s"
+
+#: ex_docmd.c:5120
+msgid "E182: Invalid command name"
+msgstr "E182: Ugyldig kommandonavn"
+
+#: ex_docmd.c:5135
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: Brukerdefinerte kommandoer må ha stor forbokstav"
+
+#: ex_docmd.c:5206
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: Brukerdefinert kommando finnes ikke: %s"
+
+#: ex_docmd.c:5667
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Kan ikke finne fargeoppsettet %s"
+
+#: ex_docmd.c:5675
+msgid "Greetings, Vim user!"
+msgstr "Vær hilset, Vim-bruker!"
+
+#: ex_docmd.c:6396
+msgid "Edit File in new window"
+msgstr "Rediger fil i nytt vindu"
+
+#: ex_docmd.c:6697
+msgid "No swap file"
+msgstr "Ingen swapfil"
+
+#: ex_docmd.c:6801
+msgid "Append File"
+msgstr "Legg til fil"
+
+#: ex_docmd.c:6865
+msgid "E186: No previous directory"
+msgstr "E186: Ingen tidligere katalog"
+
+#: ex_docmd.c:6947
+msgid "E187: Unknown"
+msgstr "E187: Ukjent"
+
+#: ex_docmd.c:7032
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: :winsize trenger to numeriske parametere"
+
+#: ex_docmd.c:7088
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Vindusposisjon: X %d, Y %d"
+
+#: ex_docmd.c:7093
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr ""
+"E188: Lesing av vindusposisjon er ikke implementert på denne plattformen"
+
+#: ex_docmd.c:7103
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: :winpos trenger to numeriske parametere"
+
+#: ex_docmd.c:7381
+msgid "Save Redirection"
+msgstr "Lagre omdirigering"
+
+#: ex_docmd.c:7571
+msgid "Save View"
+msgstr "Lagre utseende"
+
+#: ex_docmd.c:7572
+msgid "Save Session"
+msgstr "Lagre økt"
+
+#: ex_docmd.c:7574
+msgid "Save Setup"
+msgstr "Lagre oppsett"
+
+#: ex_docmd.c:7726
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" finnes (legg til ! for å overstyre)"
+
+#: ex_docmd.c:7731
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: Kan ikke åpne \"%s\" for skriving"
+
+#. set mark
+#: ex_docmd.c:7755
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: Parameter må være en bokstav eller vanlig/baklengs apostrof"
+
+#: ex_docmd.c:7797
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Rekursiv bruk av :normal er for dyp"
+
+#: ex_docmd.c:8315
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: Ingen alternative filnavn tilgjengelig som erstatning for '#'"
+
+#: ex_docmd.c:8346
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr ""
+"E495: Ingen autokommandofilnavn tilgjengelig som erstatning for \"<afile>\""
+
+#: ex_docmd.c:8354
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr ""
+"E496: Ingen buffernummer tilgjengelig som erstatning for \"<abuf>\" i "
+"autokommando"
+
+#: ex_docmd.c:8365
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr ""
+"E497: Ingen autokommandonavn tilgjengelig som erstatning for \"<amatch>\""
+
+#: ex_docmd.c:8375
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr ""
+"E498: Ingen ':source'-filnavn tilgjengelig som erstatning for \"<sfile>\""
+
+#: ex_docmd.c:8416
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: Tomt filnavn for '%' eller '#', virker bare med \":p:h\""
+
+#: ex_docmd.c:8418
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: Resulterer i en tom streng"
+
+#: ex_docmd.c:9389
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: Kan ikke åpne viminfo-fil for lesing"
+
+#: ex_docmd.c:9562
+msgid "E196: No digraphs in this version"
+msgstr "E196: Ingen spesialtegn i denne versjonen"
+
+#: ex_eval.c:440
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr "E608: Kan ikke :throw unntak med 'Vim'-forstavelse"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:529
+#, c-format
+#~ msgid "Exception thrown: %s"
+#~ msgstr ""
+
+#: ex_eval.c:576
+#, c-format
+msgid "Exception finished: %s"
+msgstr "Unntak fullført: %s"
+
+#: ex_eval.c:577
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "Unntak forkastet: %s"
+
+#: ex_eval.c:620 ex_eval.c:664
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, linje %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:638
+#, c-format
+msgid "Exception caught: %s"
+msgstr "Unntak fanget opp: %s"
+
+#: ex_eval.c:713
+#, c-format
+msgid "%s made pending"
+msgstr "%s satt på venting"
+
+#: ex_eval.c:716
+#, c-format
+msgid "%s resumed"
+msgstr "%s gjenopptatt"
+
+#: ex_eval.c:720
+#, c-format
+msgid "%s discarded"
+msgstr "%s forkastet"
+
+#: ex_eval.c:746
+msgid "Exception"
+msgstr "Unntak"
+
+#: ex_eval.c:752
+msgid "Error and interrupt"
+msgstr "Feil og avbrudd"
+
+#: ex_eval.c:754 gui.c:4384
+msgid "Error"
+msgstr "Feil"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:756
+msgid "Interrupt"
+msgstr "Avbrudd"
+
+#: ex_eval.c:830
+msgid "E579: :if nesting too deep"
+msgstr "E579: Nøsting av :if for dyp"
+
+#: ex_eval.c:867
+msgid "E580: :endif without :if"
+msgstr "E580: :endif uten :if"
+
+#: ex_eval.c:911
+msgid "E581: :else without :if"
+msgstr "E581: :else uten :if"
+
+#: ex_eval.c:914
+msgid "E582: :elseif without :if"
+msgstr "E582: :elseif uten :if"
+
+#: ex_eval.c:921
+msgid "E583: multiple :else"
+msgstr "E583: Flere forekomster av :else"
+
+#: ex_eval.c:924
+msgid "E584: :elseif after :else"
+msgstr "E584: :elseif etter :else"
+
+#: ex_eval.c:991
+msgid "E585: :while nesting too deep"
+msgstr "E585: Nøsting av :while for dyp"
+
+#: ex_eval.c:1047
+msgid "E586: :continue without :while"
+msgstr "E586: :continue uten :while"
+
+#: ex_eval.c:1087
+msgid "E587: :break without :while"
+msgstr "E587: :break uten :while"
+
+#: ex_eval.c:1286
+msgid "E601: :try nesting too deep"
+msgstr "E601: Nøsting av :try for dyp"
+
+#: ex_eval.c:1366
+msgid "E603: :catch without :try"
+msgstr "E603: :catch uten :try"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1388
+msgid "E604: :catch after :finally"
+msgstr "E604: :catch etter :finally"
+
+#: ex_eval.c:1521
+msgid "E606: :finally without :try"
+msgstr "E606: :finally uten :try"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1545
+msgid "E607: multiple :finally"
+msgstr "E607: Flere forekomster av :finally"
+
+#: ex_eval.c:1654
+msgid "E602: :endtry without :try"
+msgstr "E602: :endtry uten :try"
+
+#: ex_eval.c:1986
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction er ikke innenfor en funksjon"
+
+#: ex_getln.c:3299
+msgid "tagname"
+msgstr "navn på tag"
+
+#: ex_getln.c:3302
+#~ msgid " kind file\n"
+#~ msgstr ""
+
+#: ex_getln.c:4768
+msgid "'history' option is zero"
+msgstr "'history'-valget er null"
+
+#: ex_getln.c:5039
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s-historie (nyeste til eldste):\n"
+
+#: ex_getln.c:5040
+msgid "Command Line"
+msgstr "Kommandolinje"
+
+#: ex_getln.c:5041
+msgid "Search String"
+msgstr "Søkestreng"
+
+#: ex_getln.c:5042
+msgid "Expression"
+msgstr "Uttrykk"
+
+#: ex_getln.c:5043
+msgid "Input Line"
+msgstr "Inndatalinje"
+
+#: ex_getln.c:5081
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar utenfor kommandolengden"
+
+#: ex_getln.c:5258
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Aktivt vindu eller buffer slettet"
+
+#: fileio.c:378
+msgid "Illegal file name"
+msgstr "Ulovlig filnavn"
+
+#: fileio.c:402 fileio.c:540 fileio.c:2925 fileio.c:2966
+msgid "is a directory"
+msgstr "er en katalog"
+
+#: fileio.c:404
+msgid "is not a file"
+msgstr "er ikke en fil"
+
+#: fileio.c:562 fileio.c:4143
+msgid "[New File]"
+msgstr "[Ny fil]"
+
+#: fileio.c:595
+msgid "[Permission Denied]"
+msgstr "[Tilgang nektet]"
+
+#: fileio.c:706
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: \"*ReadPre\"-autokommandoer gjorde filen uleselig"
+
+#: fileio.c:708
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: \"*ReadPre\"-autokommandoer må ikke forandre nåværende buffer"
+
+#: fileio.c:729
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: Leser fra stdin ...\n"
+
+#: fileio.c:735
+msgid "Reading from stdin..."
+msgstr "Leser fra stdin ..."
+
+#. Re-opening the original file failed!
+#: fileio.c:1012
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: Konverteringen gjorde filen uleselig!"
+
+#: fileio.c:2102
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:2109
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:2116
+msgid "[socket]"
+msgstr "[socket]"
+
+#: fileio.c:2124
+msgid "[RO]"
+msgstr "[SB]"
+
+#: fileio.c:2134
+msgid "[CR missing]"
+msgstr "[CR mangler]"
+
+#: fileio.c:2139
+msgid "[NL found]"
+msgstr "[NL funnet]"
+
+#: fileio.c:2144
+msgid "[long lines split]"
+msgstr "[lange linjer splittes]"
+
+#: fileio.c:2150 fileio.c:4127
+msgid "[NOT converted]"
+msgstr "[IKKE konvertert]"
+
+#: fileio.c:2155 fileio.c:4132
+msgid "[converted]"
+msgstr "[konvertert]"
+
+#: fileio.c:2162 fileio.c:4157
+msgid "[crypted]"
+msgstr "[kryptert]"
+
+#: fileio.c:2169
+msgid "[CONVERSION ERROR]"
+msgstr "[KONVERTERINGSFEIL]"
+
+#: fileio.c:2175
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[ULOVLIG BYTE i linje %ld]"
+
+#: fileio.c:2182
+msgid "[READ ERRORS]"
+msgstr "[LESEFEIL]"
+
+#: fileio.c:2398
+msgid "Can't find temp file for conversion"
+msgstr "Kan ikke finne midlertidig fil for konvertering"
+
+#: fileio.c:2405
+msgid "Conversion with 'charconvert' failed"
+msgstr "Konvertering med 'charconvert' feilet"
+
+#: fileio.c:2408
+msgid "can't read output of 'charconvert'"
+msgstr "Kan ikke lese utdata fra 'charconvert'"
+
+#: fileio.c:2808
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Autokommandoer slettet eller lastet ut buffer som skulle lagres"
+
+#: fileio.c:2831
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Autokommando forandret linjeantall på en uventet måte"
+
+#: fileio.c:2869
+msgid "NetBeans dissallows writes of unmodified buffers"
+msgstr "NetBeans forbyr lagring av buffere som ikke er forandret"
+
+#: fileio.c:2877
+msgid "Partial writes disallowed for NetBeans buffers"
+msgstr "Delvis lagring ikke tillatt for NetBeans-buffere"
+
+#: fileio.c:2931 fileio.c:2949
+msgid "is not a file or writable device"
+msgstr "er ikke en fil eller skrivbar enhet"
+
+#: fileio.c:3001
+msgid "is read-only (add ! to override)"
+msgstr "er skrivebeskyttet (legg til ! for å overstyre)"
+
+#: fileio.c:3347
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: Kan ikke skrive til backupfil (legg til ! for å overstyre)"
+
+#: fileio.c:3359
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr "E507: Feil under lukking av backupfil (legg til ! for å overstyre)"
+
+#: fileio.c:3361
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr "E508: Kan ikke lese fil for backup (legg til ! for å overstyre)"
+
+#: fileio.c:3377
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: Kan ikke lese backupfil (legg til ! for å overstyre)"
+
+#: fileio.c:3480
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: Kan ikke lage backupfil (legg til ! for å overstyre)"
+
+#: fileio.c:3542
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr "E460: Ressursforgreningen ville gått tapt (legg til ! for å overstyre)"
+
+#: fileio.c:3652
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: Kan ikke finne midlertidig fil for skriving"
+
+#: fileio.c:3670
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr "E213: Kan ikke konvertere (legg til ! for å lagre uten konvertering)"
+
+#: fileio.c:3705
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Kan ikke åpne lenket fil for skriving"
+
+#: fileio.c:3709
+msgid "E212: Can't open file for writing"
+msgstr "E212: Kan ikke åpne fil for skriving"
+
+#: fileio.c:3971
+msgid "E667: Fsync failed"
+msgstr "E667: Fsync feilet"
+
+#: fileio.c:3978
+msgid "E512: Close failed"
+msgstr "E512: Lukking feilet"
+
+#: fileio.c:4049
+msgid "E513: write error, conversion failed"
+msgstr "E513: Feil under skriving, konvertering feilet"
+
+#: fileio.c:4055
+msgid "E514: write error (file system full?)"
+msgstr "E514: Feil under lagring (full disk?)"
+
+#: fileio.c:4122
+msgid " CONVERSION ERROR"
+msgstr " KONVERTERINGSFEIL"
+
+#: fileio.c:4138
+msgid "[Device]"
+msgstr "[Enhet]"
+
+#: fileio.c:4143
+msgid "[New]"
+msgstr "[Ny]"
+
+#: fileio.c:4165
+msgid " [a]"
+msgstr " [l]"
+
+#: fileio.c:4165
+msgid " appended"
+msgstr " lagt til"
+
+#: fileio.c:4167
+msgid " [w]"
+msgstr " [s]"
+
+#: fileio.c:4167
+msgid " written"
+msgstr " skrevet"
+
+#: fileio.c:4217
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: Patchmode: Kan ikke lagre originalfil"
+
+#: fileio.c:4239
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: Kan ikke oppdatere tom originalfil"
+
+#: fileio.c:4254
+msgid "E207: Can't delete backup file"
+msgstr "E207: Kan ikke slette backupfil"
+
+#: fileio.c:4318
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"ADVARSEL: Originalfilen kan bli tapt eller ødelagt\n"
+
+#: fileio.c:4320
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "ikke avslutt editoren før filen er skikkelig lagret!"
+
+#: fileio.c:4409
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:4409
+msgid "[dos format]"
+msgstr "[dos-format]"
+
+#: fileio.c:4416
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:4416
+msgid "[mac format]"
+msgstr "[mac-format]"
+
+#: fileio.c:4423
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:4423
+msgid "[unix format]"
+msgstr "[unix-format]"
+
+#: fileio.c:4450
+msgid "1 line, "
+msgstr "1 linje, "
+
+#: fileio.c:4452
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld linjer, "
+
+#: fileio.c:4455
+msgid "1 character"
+msgstr "1 tegn"
+
+#: fileio.c:4457
+#, c-format
+msgid "%ld characters"
+msgstr "%ld tegn"
+
+#: fileio.c:4467
+msgid "[noeol]"
+msgstr "[ingenlinjeslutt]"
+
+#: fileio.c:4467
+msgid "[Incomplete last line]"
+msgstr "[Ufullstendig sistelinje]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4486
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "ADVARSEL: Filen er blitt forandret siden den ble lest!!!"
+
+#: fileio.c:4488
+msgid "Do you really want to write to it"
+msgstr "Vil du virkelig skrive til den"
+
+#: fileio.c:5738
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Feil under skriving til \"%s\""
+
+#: fileio.c:5745
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Feil under lukking av \"%s\""
+
+#: fileio.c:5748
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Feil under lesing av \"%s\""
+
+#: fileio.c:5982
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: Autokommandoen \"FileChangedShell\" slettet buffer"
+
+#: fileio.c:5989
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: Advarsel: Filen \"%s\" er ikke lenger tilgjengelig"
+
+#: fileio.c:6003
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: Advarsel: Filen \"%s\" er forandret og bufferen var også forandret i Vim"
+
+#: fileio.c:6006
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: Advarsel: Filen \"%s\" er forandret siden redigeringen startet"
+
+#: fileio.c:6008
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr ""
+"W16: Advarsel: Rettighetene til filen \"%s\" er forandret siden redigeringen "
+"startet"
+
+#: fileio.c:6018
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr ""
+"W13: Advarsel: Filen \"%s\" er blitt opprettet etter at redigeringen startet"
+
+#: fileio.c:6031
+msgid "See \":help W11\" for more info."
+msgstr "Se \":help W11\" for mer informasjon."
+
+#: fileio.c:6045
+msgid "Warning"
+msgstr "Advarsel"
+
+#: fileio.c:6046
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Åpne fil"
+
+#: fileio.c:6152
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: Kunne ikke forberede for relasting \"%s\""
+
+#: fileio.c:6171
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: Kunne ikke laste \"%s\" på nytt"
+
+#: fileio.c:6752
+msgid "--Deleted--"
+msgstr "--Slettet--"
+
+#. the group doesn't exist
+#: fileio.c:6912
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Gruppen finnes ikke: \"%s\""
+
+#: fileio.c:7038
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Ulovlig tegn etter *: %s"
+
+#: fileio.c:7050
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Handlingen finnes ikke: %s"
+
+#: fileio.c:7052
+#, c-format
+msgid "E216: No such group or event: %s"
+msgstr "E216: Gruppen eller handlingen finnes ikke: %s"
+
+#. Highlight title
+#: fileio.c:7210
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Autokommandoer ---"
+
+#: fileio.c:7481
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Kan ikke utføre autokommandoer for ALLE hendelser"
+
+#: fileio.c:7504
+msgid "No matching autocommands"
+msgstr "Ingen samsvarende autokommandoer"
+
+#: fileio.c:7825
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: Nøsting av autokommandoer for dyp"
+
+#: fileio.c:8100
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Autokommandoer for \"%s\""
+
+#: fileio.c:8108
+#, c-format
+msgid "Executing %s"
+msgstr "Utfører %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:8176
+#, c-format
+msgid "autocommand %s"
+msgstr "autokommando %s"
+
+#: fileio.c:8743
+msgid "E219: Missing {."
+msgstr "E219: Mangler {."
+
+#: fileio.c:8745
+msgid "E220: Missing }."
+msgstr "E220: Mangler }."
+
+#: fold.c:68
+msgid "E490: No fold found"
+msgstr "E490: Ingen fold funnet"
+
+#: fold.c:593
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: Kan ikke lage fold med nåværende 'foldmethod'"
+
+#: fold.c:595
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: Kan ikke slette fold med nåværende 'foldmethod'"
+
+#: getchar.c:248
+#~ msgid "E222: Add to read buffer"
+#~ msgstr ""
+
+#: getchar.c:2208
+msgid "E223: recursive mapping"
+msgstr "E223: Rekursiv mapping"
+
+#: getchar.c:3087
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: Global forkortelse finnes allerede for %s"
+
+#: getchar.c:3090
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: Global mapping finnes allerede for %s"
+
+#: getchar.c:3222
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: Forkortelse finnes allerede for %s"
+
+#: getchar.c:3225
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: Mappingen finnes allerede for %s"
+
+#: getchar.c:3289
+msgid "No abbreviation found"
+msgstr "Ingen forkortelse funnet"
+
+#: getchar.c:3291
+msgid "No mapping found"
+msgstr "Ingen mapping funnet"
+
+#: getchar.c:4183
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: Ulovlig modus"
+
+#: gui.c:220
+msgid "E229: Cannot start the GUI"
+msgstr "E229: Kan ikke starte grafisk brukergrensesnitt (GUI)"
+
+#: gui.c:349
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Kan ikke lese fra \"%s\""
+
+#: gui.c:472
+msgid "E665: Cannot start GUI, no valid font found"
+msgstr ""
+"E665: Kan ikke starte grafisk brukergrensesnitt, fant ingen gyldig font"
+
+#: gui.c:477
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: 'guifontwide' ugyldig"
+
+#: gui.c:547
+msgid "E599: Value of 'imactivatekey' is invalid"
+msgstr "E599: Verdien for 'imactivatekey' er ugyldig"
+
+#: gui.c:4064
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: Kan ikke reservere farge %s"
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<kan ikke åpne> "
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: Kan ikke bruke skrifttypen %s"
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: Kan ikke returnere til nåværende katalog"
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "Sti:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: Kan ikke finne nåværende katalog"
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "OK"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2731 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "Avbryt"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Rullefeltelement: Klarte ikke hente dimensjoner på \"thumb pixmap\"."
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "Dialogvindu for Vim"
+
+#: gui_beval.c:101 gui_w32.c:3978
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: Kan ikke lage BalloonEval med både melding og tilbakekall"
+
+#: gui_gtk.c:1607
+msgid "Vim dialog..."
+msgstr "Vim dialogvindu ..."
+
+#: gui_gtk.c:2060 message.c:2999
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Ja\n"
+"&Nei\n"
+"&Avbryt"
+
+#: gui_gtk.c:2268
+#~ msgid "Input _Methods"
+#~ msgstr ""
+
+#: gui_gtk.c:2534 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Søk og erstatt ..."
+
+#: gui_gtk.c:2542 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "VIM - Søk ..."
+
+#: gui_gtk.c:2574 gui_motif.c:2888
+msgid "Find what:"
+msgstr "Finn hva:"
+
+#: gui_gtk.c:2592 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "Erstatt med:"
+
+#. whole word only button
+#: gui_gtk.c:2624 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "Finn kun hele ord"
+
+#. match case button
+#: gui_gtk.c:2635 gui_motif.c:3048
+msgid "Match case"
+msgstr "Forskjell på store/små bokstaver"
+
+#: gui_gtk.c:2645 gui_motif.c:2990
+msgid "Direction"
+msgstr "Retning"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2657 gui_motif.c:3002
+msgid "Up"
+msgstr "Opp"
+
+#: gui_gtk.c:2661 gui_motif.c:3010
+msgid "Down"
+msgstr "Ned"
+
+#: gui_gtk.c:2683 gui_gtk.c:2685 gui_motif.c:2792
+msgid "Find Next"
+msgstr "Finn neste"
+
+#: gui_gtk.c:2702 gui_gtk.c:2704 gui_motif.c:2809
+msgid "Replace"
+msgstr "Erstatt"
+
+#: gui_gtk.c:2715 gui_gtk.c:2717 gui_motif.c:2822
+msgid "Replace All"
+msgstr "Erstatt alle"
+
+#: gui_gtk_x11.c:2327
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: Mottok \"dø\"-forespørsel fra øktbehandleren\n"
+
+#: gui_gtk_x11.c:3519
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: Uventet ødeleggelse av hovedvinduet\n"
+
+#: gui_gtk_x11.c:4138
+msgid "Font Selection"
+msgstr "Velge skrifttype"
+
+#: gui_gtk_x11.c:6035 ui.c:2120
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "Brukte CUT_BUFFER0 istedenfor tomt valg"
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "Filter"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "Kataloger"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "Hjelp"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "Filer"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "Valg"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "Angre"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: Kan ikke laste Zap-skrifttype '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: Kan ikke bruke skrifttype %s"
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Sender beskjed om å avslutte barneprosess.\n"
+
+#: gui_w32.c:839
+#, c-format
+msgid "E671: Cannot find window title \"%s\""
+msgstr "E671: Fant ikke vindutittel \"%s\""
+
+#: gui_w32.c:847
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Parameter ikke støttet: \"-%s\"; Bruk OLE-versjonen."
+
+#: gui_w32.c:1100
+msgid "E672: Unable to open window inside MDI application"
+msgstr "E672: Klarer ikke åpne vindu inne i MDI-applikasjon"
+
+#: gui_w48.c:2163
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Finn streng (bruk '\\\\' for å finne en '\\')"
+
+#: gui_w48.c:2188
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Søk og erstatt (bruk '\\\\' for å finne en '\\')"
+
+#: gui_x11.c:1537
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr "Vim E458: Kan ikke reservere fargekart, noen farger kan være feil"
+
+#: gui_x11.c:2118
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: Skrifttyper for de følgende tegnsett mangler i fontsett %s:"
+
+#: gui_x11.c:2161
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Navn på skrifttypesett: %s"
+
+#: gui_x11.c:2162
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "Skrifttypen '%s' har ikke konstant bredde"
+
+#: gui_x11.c:2181
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Navn på skrifttypesett: %s\n"
+
+#: gui_x11.c:2182
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Font0: %s\n"
+
+#: gui_x11.c:2183
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Font1: %s\n"
+
+#: gui_x11.c:2184
+#, c-format
+msgid "Font%ld width is not twice that of font0\n"
+msgstr "Font%ld-bredde er ikke to ganger bredden av font0\n"
+
+#: gui_x11.c:2185
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "Font0-bredde: %ld\n"
+
+#: gui_x11.c:2186
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"Font1-bredde: %ld\n"
+"\n"
+
+#: hangulin.c:610
+#~ msgid "E256: Hangul automata ERROR"
+#~ msgstr ""
+
+#: if_cscope.c:77
+msgid "Add a new database"
+msgstr "Legg til en ny database"
+
+#: if_cscope.c:79
+msgid "Query for a pattern"
+msgstr "Forespørsel etter søkestreng"
+
+#: if_cscope.c:81
+msgid "Show this message"
+msgstr "Vis denne meldingen"
+
+#: if_cscope.c:83
+msgid "Kill a connection"
+msgstr "Drep en forbindelse"
+
+#: if_cscope.c:85
+msgid "Reinit all connections"
+msgstr "Reinitialiser alle forbindelser"
+
+#: if_cscope.c:87
+msgid "Show connections"
+msgstr "Vis forbindelser"
+
+#: if_cscope.c:95
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: Bruk: cs[cope] %s"
+
+#: if_cscope.c:124
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Denne cscope-kommandoen støtter ikke splitting av vinduet.\n"
+
+#: if_cscope.c:175
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: Bruk: cstag <identifikator>"
+
+#: if_cscope.c:231
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: Tag ikke funnet"
+
+#: if_cscope.c:409
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: stat(%s) feil: %d"
+
+#: if_cscope.c:419
+msgid "E563: stat error"
+msgstr "E563: \"stat\"-feil"
+
+#: if_cscope.c:516
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s er ikke en katalog eller gyldig cscope-database"
+
+#: if_cscope.c:534
+#, c-format
+msgid "Added cscope database %s"
+msgstr "La til cscope-database %s"
+
+#: if_cscope.c:589
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: Feil under lesing av cscope-forbindelse %ld"
+
+#: if_cscope.c:694
+msgid "E561: unknown cscope search type"
+msgstr "E561: Ukjent cscope-søketype"
+
+#: if_cscope.c:736
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: Kunne ikke lage cscope-rør (\"pipe\")"
+
+#: if_cscope.c:753
+msgid "E622: Could not fork for cscope"
+msgstr "E622: Klarte ikke lage tvillingprosess for cscope"
+
+#: if_cscope.c:847 if_cscope.c:897
+msgid "cs_create_connection exec failed"
+msgstr "Utføring av cs_create_connection feilet"
+
+#: if_cscope.c:898
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: Klarte ikke starte cscope-prosess"
+
+#: if_cscope.c:911
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen for to_fp feilet"
+
+#: if_cscope.c:913
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen for fr_fp feilet"
+
+#: if_cscope.c:951
+msgid "E567: no cscope connections"
+msgstr "E567: Ingen cscope-forbindelse"
+
+#: if_cscope.c:1025
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: Ingen treff funnet for cscope-forespørsel %s av %s"
+
+#: if_cscope.c:1082
+#, c-format
+msgid "E469: invalid cscopequickfix flag %c for %c"
+msgstr "E469: Ugyldig \"cscopequickfix\"-flagg %c for %c"
+
+#: if_cscope.c:1152
+msgid "cscope commands:\n"
+msgstr "cscope-kommandoer:\n"
+
+#: if_cscope.c:1155
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (Bruk: %s)"
+
+#: if_cscope.c:1253
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: Kan ikke åpne cscope-database: %s"
+
+#: if_cscope.c:1271
+msgid "E626: cannot get cscope database information"
+msgstr "E626: Kan ikke hente informasjon om cscope-database"
+
+#: if_cscope.c:1296
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: Duplisert cscope-database ikke lagt til"
+
+#: if_cscope.c:1307
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: Maksimum antall cscope-forbindelser nådd"
+
+#: if_cscope.c:1424
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: cscope-forbindelse %s ikke funnet"
+
+#: if_cscope.c:1458
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "cscope-forbindelsen %s stengt"
+
+#. should not reach here
+#: if_cscope.c:1598
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: Kritisk feil i cs_manage_matches"
+
+#: if_cscope.c:1848
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "Cscope-tag: %s"
+
+#: if_cscope.c:1870
+msgid ""
+"\n"
+" # line"
+msgstr ""
+"\n"
+" # linje"
+
+#: if_cscope.c:1872
+msgid "filename / context / line\n"
+msgstr "filnavn / kontekst / linje\n"
+
+#: if_cscope.c:1990
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: Cscope-feil: %s"
+
+#: if_cscope.c:2176
+msgid "All cscope databases reset"
+msgstr "Alle cscope-databaser resatt"
+
+#: if_cscope.c:2244
+msgid "no cscope connections\n"
+msgstr "ingen cscope-forbindelser\n"
+
+#: if_cscope.c:2248
+msgid " # pid database name prepend path\n"
+msgstr " # pid databasenavn legg til sti\n"
+
+#: if_python.c:436
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: Denne kommandoen er deaktivert, Python-biblioteket kunne ikke lastes."
+
+#: if_python.c:500
+msgid "E659: Cannot invoke Python recursively"
+msgstr "E659: Kan ikke starte Python rekursivt"
+
+#: if_python.c:701
+msgid "can't delete OutputObject attributes"
+msgstr "Kan ikke slette \"OutputObject\"-attributter"
+
+#: if_python.c:708
+msgid "softspace must be an integer"
+msgstr "\"softspace\" må være et heltall"
+
+#: if_python.c:716
+msgid "invalid attribute"
+msgstr "ugyldig attributt"
+
+#: if_python.c:755 if_python.c:769
+msgid "writelines() requires list of strings"
+msgstr "writelines() krever en liste av strenger"
+
+#: if_python.c:895
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: Feil under initialisering av I/U-objekter"
+
+#: if_python.c:1080 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "ugyldig uttrykk"
+
+#: if_python.c:1094 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "uttrykk deaktivert på kompileringsstadiet"
+
+#: if_python.c:1107
+msgid "attempt to refer to deleted buffer"
+msgstr "forsøk på å referere til slettet buffer"
+
+#: if_python.c:1122 if_python.c:1163 if_python.c:1227 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "linjenummer utenfor område"
+
+#: if_python.c:1362
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<bufferobjekt (slettet) ved %8lX>"
+
+#: if_python.c:1453 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "ugyldig merkenavn"
+
+#: if_python.c:1733
+msgid "no such buffer"
+msgstr "bufferen finnes ikke"
+
+#: if_python.c:1821
+msgid "attempt to refer to deleted window"
+msgstr "forsøk på å referere til slettet vindu"
+
+#: if_python.c:1866
+msgid "readonly attribute"
+msgstr "skrivebeskyttet attributt"
+
+#: if_python.c:1879
+msgid "cursor position outside buffer"
+msgstr "markørposisjon utenfor buffer"
+
+#: if_python.c:1956
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<vindusobjekt (slettet) ved %.8lX>"
+
+#: if_python.c:1968
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<vindusobjekt (ukjent) ved %.8lX>"
+
+#: if_python.c:1970
+#, c-format
+msgid "<window %d>"
+msgstr "<vindu %d>"
+
+#: if_python.c:2046
+msgid "no such window"
+msgstr "vinduet finnes ikke"
+
+#: if_python.c:2307 if_python.c:2341 if_python.c:2396 if_python.c:2464
+#: if_python.c:2586 if_python.c:2638 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "kan ikke lagre angre-informasjon"
+
+#: if_python.c:2309 if_python.c:2403 if_python.c:2475
+msgid "cannot delete line"
+msgstr "kan ikke slette linje"
+
+#: if_python.c:2346 if_python.c:2491 if_tcl.c:690 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "kan ikke erstatte linje"
+
+#: if_python.c:2509 if_python.c:2588 if_python.c:2646
+msgid "cannot insert line"
+msgstr "kan ikke sette inn linje"
+
+#: if_python.c:2750
+msgid "string cannot contain newlines"
+msgstr "streng kan ikke inneholde linjeskift"
+
+#: if_ruby.c:422
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: Denne kommandoen er deaktivert, Ruby-biblioteket kunne ikke lastes."
+
+#: if_ruby.c:485
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: Ukjent longjmp-status %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Bytt mellom implementasjon/definisjon"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Vis basisklasse av"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Vis overstyrt medlemsfunksjon"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Hent fra fil"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Hent fra prosjekt"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Hent fra alle prosjekter"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Hent"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Vis kilde til"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Finn symbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Bla gjennom klasse"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Vis klasse i hierarki"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Vis klasse i begrenset hierarki"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref refererer til"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref referert av"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref har en"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref brukt av"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Vis docu av"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Generer docu for"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"Kan ikke koble til SNiFF+. Sjekk miljøet (\"environment\") (sniffemacs må "
+"bli funnet i $PATH).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Feil under lesing. Frakoblet"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ er for øyeblikket "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "ikke "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "oppkoblet"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Ukjent SNiFF+-forespørsel: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Feil ved oppkobling til SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ ikke tilkoblet"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Ikke en SNiFF+-buffer"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: Feil under skriving. Frakoblet"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "ugyldig buffernummer"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "ikke implementert enda"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "ukjent valg"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "kan ikke sette linje(r)"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "merke ikke satt"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "rad %d kolonne %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "kan ikke sette inn/legge til linje"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "ukjent flagg: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "ukjent vimOption"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "tastaturavbrudd"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "vim-feil"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "kan ikke opprette buffer/vindukommando: Objektet slettes"
+
+#: if_tcl.c:1545
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"kan ikke registrere callback-kommando: Buffer/vindu er allerede slettet"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: TCL KRITISK FEIL: reflist skadet!? Vennligst rapporter dette til vim-"
+"dev@vim.org"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"kan ikke registrere callback-kommando: Buffer/vindureferanse ikke funnet"
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"E571: Denne kommandoen er deaktivert, Tcl-biblioteket kunne ikke lastes."
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: TCL-FEIL: Avslutningskode er ikke int!? Vennligst rapporter dette til "
+"vim-dev@vim.org"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "kan ikke hente linje"
+
+#: if_xcmdsrv.c:225
+msgid "Unable to register a command server name"
+msgstr "Klarer ikke registrere kommandotjenernavn"
+
+#: if_xcmdsrv.c:473
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Klarte ikke sende kommando til destinasjonsprogrammet"
+
+#: if_xcmdsrv.c:747
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: Ugyldig tjener-id brukt: %s"
+
+#: if_xcmdsrv.c:1110
+#~ msgid "E251: VIM instance registry property is badly formed. Deleted!"
+#~ msgstr ""
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "Ukjent valg"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "For mange redigeringsparametere"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "Parameter mangler etter"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "Søppel etter valg"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr ""
+"For mange \"+command\"-, \"-c command\"- eller \"--cmd kommando\"-parametere"
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "Ugyldig parameter for"
+
+#: main.c:469
+msgid "This Vim was not compiled with the diff feature."
+msgstr "Denne Vim-versjonen er kompilert uten differansefunksjonen."
+
+#: main.c:935
+msgid "Attempt to open script file again: \""
+msgstr "Forsøk på å åpne skriptfilen igjen: \""
+
+#: main.c:944
+msgid "Cannot open for reading: \""
+msgstr "Kan ikke åpne for lesing: \""
+
+#: main.c:988
+msgid "Cannot open for script output: \""
+msgstr "Kan ikke åpne for skript-utdata: \""
+
+#: main.c:1135
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d filer å redigere\n"
+
+#: main.c:1236
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Advarsel: Utdata går ikke til en terminal\n"
+
+#: main.c:1238
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Advarsel: Inndata kommer ikke fra en terminal\n"
+
+#. just in case..
+#: main.c:1306
+msgid "pre-vimrc command line"
+msgstr "pre-vimrc kommandolinje"
+
+#: main.c:1347
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Kan ikke lese fra \"%s\""
+
+#: main.c:2420
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Mer info med: \"vim -h\"\n"
+
+#: main.c:2453
+msgid "[file ..] edit specified file(s)"
+msgstr "[file ..] rediger spesifisert(e) fil(er)"
+
+#: main.c:2454
+msgid "- read text from stdin"
+msgstr "- les tekst fra stdin"
+
+#: main.c:2455
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tag rediger fil hvor en tag er definert"
+
+#: main.c:2457
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [feilfil] rediger fil med første feil"
+
+#: main.c:2466
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"bruk:"
+
+#: main.c:2469
+msgid " vim [arguments] "
+msgstr " vim [parametere] "
+
+#: main.c:2473
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" eller:"
+
+#: main.c:2476
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Parametere:\n"
+
+#: main.c:2477
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tBare filnavn etter dette"
+
+#: main.c:2479
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tIkke utvid jokertegn"
+
+#: main.c:2482
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tRegistrer gvim for OLE"
+
+#: main.c:2483
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tFjern OLE-registrering for gvim"
+
+#: main.c:2486
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tKjør med GUI (som \"gvim\")"
+
+#: main.c:2487
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f eller --nofork\tForgrunn: Ikke fork når GUI-et startes"
+
+#: main.c:2489
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi-modus (som \"vi\")"
+
+#: main.c:2490
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx-modus (som \"ex\")"
+
+#: main.c:2491
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tStille (batch) modus (bare for \"ex\")"
+
+#: main.c:2493
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tDifferanse-modus (som \"vimdiff\")"
+
+#: main.c:2495
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tLett modus (som \"evim\", uten modus)"
+
+#: main.c:2496
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tSkrivebeskyttet modus (som \"view\")"
+
+#: main.c:2497
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tBegrenset modus (som \"rvim\")"
+
+#: main.c:2498
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tModifisering (lagring av filer) ikke tillatt"
+
+#: main.c:2499
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tModifiseringer i teksten ikke tillatt"
+
+#: main.c:2500
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tBinærmodus"
+
+#: main.c:2502
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp-modus"
+
+#: main.c:2504
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tKompatibel med Vi: 'compatible'"
+
+#: main.c:2505
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tIkke helt Vi-kompatibel: 'nocompatible'"
+
+#: main.c:2506
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tInformasjonsnivå (\"Verbose\")"
+
+#: main.c:2507
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tDebuggingsmodus"
+
+#: main.c:2508
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tIngen swapfil, bruk bare hukommelsen"
+
+#: main.c:2509
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tList swapfiler og avslutt"
+
+#: main.c:2510
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (med filnavn)\tGjenopprett kræsjet økt"
+
+#: main.c:2511
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tSamme som -r"
+
+#: main.c:2513
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tIkke bruk newcli for å åpne vindu"
+
+#: main.c:2514
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <enhet>\t\tBruk <enhet> for I/U"
+
+#: main.c:2517
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\t\tStart i arabisk modus"
+
+#: main.c:2520
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\tStart in hebraisk modus"
+
+#: main.c:2523
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\tStart i persisk (Farsi) modus"
+
+#: main.c:2525
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\tSett terminaltypen til <terminal>"
+
+#: main.c:2526
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tBruk <vimrc> istedenfor eventuell .vimrc"
+
+#: main.c:2528
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tBruk <gvimrc> istedenfor eventuell .gvimrc"
+
+#: main.c:2530
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tIkke last plugin-skripts"
+
+#: main.c:2531
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tÅpne N vinduer (standard: Ett for hver fil)"
+
+#: main.c:2532
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\tSom -o men splitt loddrett"
+
+#: main.c:2533
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tStart på slutten av filen"
+
+#: main.c:2534
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnr>\t\tStart på linje <lnr>"
+
+#: main.c:2536
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <kommando>\tKjør <kommando> før lasting av vimrc-filer"
+
+#: main.c:2538
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <kommando>\t\tKjør <kommando> etter lasting av første fil"
+
+#: main.c:2539
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <økt>\t\tKjør filen <økt> etter lasting av første fil"
+
+#: main.c:2540
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <innskript>\tLes normalmodus-kommandoer fra filen <innskript>"
+
+#: main.c:2541
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <utskript>\tLegg alle skrevne kommandoer til filen <utskript>"
+
+#: main.c:2542
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <utskript>\tSkriv alle skrevne kommandoer til filen <utskript>"
+
+#: main.c:2544
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tRediger krypterte filer"
+
+#: main.c:2548
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\tKoble vim til denne spesielle X-tjeneren"
+
+#: main.c:2550
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tUnngå oppkobling til X-tjener"
+
+#: main.c:2553
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <filer>\tRediger <filer> på en Vim-tjener hvis mulig"
+
+#: main.c:2554
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-silent <filer> Samme, ikke klag hvis tjeneren mangler"
+
+#: main.c:2555
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr ""
+"--remote-wait <filer> Som --remote men vent på filer som blir redigert"
+
+#: main.c:2556
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-wait-silent <files> Samme, ikke klag hvis tjeneren mangler"
+
+#: main.c:2557
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <nøkler>\tSend <nøkler> til en Vim-tjener og avslutt"
+
+#: main.c:2558
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr ""
+"--remote-expr <uttrykk>\tEvaluer <uttrykk> på en Vim-tjener og skriv "
+"resultatet"
+
+#: main.c:2559
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tList navn på tilgjengelige Vim-tjenere og avslutt"
+
+#: main.c:2560
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <navn>\tSend til/bli Vim-tjeneren <navn>"
+
+#: main.c:2563
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tBruk <viminfo> istedenfor .viminfo"
+
+#: main.c:2565
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h eller --help\tSkriv hjelpen (denne teksten) og avslutt"
+
+#: main.c:2566
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\tSkriv versjonsinformasjon og avslutt"
+
+#: main.c:2570
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Parametere gjenkjent av gvim (Motif-versjon):\n"
+
+#: main.c:2574
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr ""
+"\n"
+"Parametere gjenkjent av gvim (neXtaw-versjon):\n"
+
+#: main.c:2576
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Parametere gjenkjent av gvim (Athena-versjon):\n"
+
+#: main.c:2580
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\tKjør vim på <display>"
+
+#: main.c:2581
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tStart vim som ikon"
+
+#: main.c:2583
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <navn>\t\tBruk ressurs som om Vim var <navn>"
+
+#: main.c:2584
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (Ikke implementert)\n"
+
+#: main.c:2586
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <farge>\tBruk <farge> på bakgrunnen (også: -bg)"
+
+#: main.c:2587
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <farge>\tBruk <farge> på normal tekst (også: -fg)"
+
+#: main.c:2588 main.c:2608
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <skrifttype>\t\tBruk <skrifttype> på normal tekst (også: -fn)"
+
+#: main.c:2589
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <skrifttype>\tBruk <skrifttype> på fet skrift"
+
+#: main.c:2590
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <skrifttype>\tBruk <skrifttype> på skrå tekst"
+
+#: main.c:2591 main.c:2609
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr ""
+"-geometry <geom>\tBruk <geom> for innledende vindusplassering (også: -geom)"
+
+#: main.c:2592
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr ""
+"-borderwidth <bredde>\tBruk en rammebredde tilsvarende <bredde> (også: -bw)"
+
+#: main.c:2593
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr ""
+"-scrollbarwidth <bredde> Bruk en rullefeltbredde tilsvarende <bredde> "
+"(også: -sw)"
+
+#: main.c:2595
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr ""
+"-menuheight <høyde>\tBruk en menyblokkhøyde tilsvarende <høyde> (også: -mh)"
+
+#: main.c:2597 main.c:2610
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tBruk invers video (også: -rv)"
+
+#: main.c:2598
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tIkke bruk invers video (også: +rv)"
+
+#: main.c:2599
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <ressurs>\tSett den spesifiserte ressursen"
+
+#: main.c:2602
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Parametere gjenkjent av gvim (RISC OS-versjon):\n"
+
+#: main.c:2603
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <antall>\tInnledende bredde på vindu i kolonner"
+
+#: main.c:2604
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <antall>\tInnledende høyde på vindu i rader"
+
+#: main.c:2607
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Parametere gjenkjent av gvim (GTK+-versjon):\n"
+
+#: main.c:2611
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\tKjør vim på <display> (også: --display)"
+
+#: main.c:2613
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr "--role <role>\tSett en unik \"role\" for å identifisere hovedvinduet"
+
+#: main.c:2615
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tÅpne Vim innenfor et annet GTK-skjermelement"
+
+#: main.c:2618
+msgid "-P <parent title>\tOpen Vim inside parent application"
+msgstr "-P <foreldretittel>\tStart Vim innenfor et foreldreprogram"
+
+#: main.c:2856
+msgid "No display"
+msgstr "Ingen display"
+
+#. Failed to send, abort.
+#: main.c:2871
+msgid ": Send failed.\n"
+msgstr ": Send feilet.\n"
+
+#. Let vim start normally.
+#: main.c:2877
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": Send feilet. Prøver å utføre lokalt\n"
+
+#: main.c:2915 main.c:2936
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d av %d redigert"
+
+#: main.c:2958
+msgid "No display: Send expression failed.\n"
+msgstr "Ingen display: Sending av uttrykk feilet.\n"
+
+#: main.c:2970
+msgid ": Send expression failed.\n"
+msgstr ": Sending av uttrykk feilet.\n"
+
+#: mark.c:709
+msgid "No marks set"
+msgstr "Ingen merker satt"
+
+#: mark.c:711
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: Ingen merker samsvarer med \"%s\""
+
+#. Highlight title
+#: mark.c:722
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"merk linje kol fil/tekst"
+
+#. Highlight title
+#: mark.c:760
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" hopp linje kol fil/tekst"
+
+#. Highlight title
+#: mark.c:805
+msgid ""
+"\n"
+"change line col text"
+msgstr ""
+"\n"
+"forand linje kol tekst"
+
+#: mark.c:1281
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Filmerker:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1316
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Hoppliste (nyeste først):\n"
+
+#: mark.c:1412
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Historie for merker inne i filer (yngst til eldst):\n"
+
+#: mark.c:1501
+msgid "Missing '>'"
+msgstr "Mangler '>'"
+
+#: mbyte.c:467
+msgid "E543: Not a valid codepage"
+msgstr "E543: Er ikke en gyldig codepage"
+
+#: mbyte.c:4431
+msgid "E284: Cannot set IC values"
+msgstr "E284: Kan ikke sette IC-verdier (\"Input Context\")"
+
+#: mbyte.c:4583
+#~ msgid "E285: Failed to create input context"
+#~ msgstr ""
+
+#: mbyte.c:4741
+msgid "E286: Failed to open input method"
+msgstr "E286: Klarte ikke åpne inndatametode"
+
+#: mbyte.c:4752
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr ""
+"E287: Advarsel: Klarte ikke sette \"destroy callback\" til inndatametode"
+
+#: mbyte.c:4758
+#~ msgid "E288: input method doesn't support any style"
+#~ msgstr ""
+
+#: mbyte.c:4815
+#~ msgid "E289: input method doesn't support my preedit type"
+#~ msgstr ""
+
+#: mbyte.c:4889
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: \"over-the-spot\"-stil trenger et skrifttypesett"
+
+#: mbyte.c:4925
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: Din GTK+ er eldre enn 1.2.3. Statusområde deaktivert"
+
+#: mbyte.c:5232
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Inndatametodetjener kjører ikke"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: Blokken var ikke låst"
+
+#: memfile.c:1010
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Søkefeil i lesing av swapfil"
+
+#: memfile.c:1015
+msgid "E295: Read error in swap file"
+msgstr "E295: Lesefeil i swapfil"
+
+#: memfile.c:1067
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Søkefeil i skriving til swapfil"
+
+#: memfile.c:1085
+msgid "E297: Write error in swap file"
+msgstr "E297: Skrivefeil i swapfil"
+
+#: memfile.c:1282
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: Swapfilen finnes allerede (symlenke-angrep?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Hentet ikke blokk nummer 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Hentet ikke blokk nummer 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: Hentet ikke blokk nummer 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:444
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Opps, mistet swapfilen!!!"
+
+#: memline.c:449
+msgid "E302: Could not rename swap file"
+msgstr "E302: Klarte ikke skifte navn på swapfil"
+
+#: memline.c:519
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: Klarte ikke åpne swapfil for \"%s\", gjenoppretting umulig"
+
+#: memline.c:618
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: Hentet ikke blokk 0??"
+
+#: memline.c:758
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Ingen swapfil funnet for %s"
+
+#: memline.c:768
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "Skriv nummeret på swapfil som skal brukes (0 for å avslutte): "
+
+#: memline.c:813
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: Kan ikke åpne %s"
+
+#: memline.c:835
+msgid "Unable to read block 0 from "
+msgstr "Klarte ikke lese blokk 0 fra "
+
+#: memline.c:838
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Det er mulig ingen forandringer ble gjort, eller Vim oppdaterte ikke "
+"swapfilen."
+
+#: memline.c:848 memline.c:865
+msgid " cannot be used with this version of Vim.\n"
+msgstr " kan ikke brukes med denne Vim-versjonen.\n"
+
+#: memline.c:850
+msgid "Use Vim version 3.0.\n"
+msgstr "Bruk Vim versjon 3.0.\n"
+
+#: memline.c:856
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s ser ikke ut som en Vim-swapfil"
+
+#: memline.c:869
+msgid " cannot be used on this computer.\n"
+msgstr " kan ikke brukes på denne maskinen.\n"
+
+#: memline.c:871
+msgid "The file was created on "
+msgstr "Filen ble laget på "
+
+#: memline.c:875
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"eller filen er blitt ødelagt."
+
+#: memline.c:904
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "Bruker swapfilen \"%s\""
+
+#: memline.c:910
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Originalfil \"%s\""
+
+#: memline.c:923
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Advarsel: Originalfilen kan ha blitt forandret"
+
+#: memline.c:976
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Klarte ikke lese blokk 1 fra %s"
+
+#: memline.c:980
+msgid "???MANY LINES MISSING"
+msgstr "???MANGE LINJER MANGLER"
+
+#: memline.c:996
+msgid "???LINE COUNT WRONG"
+msgstr "???FEIL LINJEANTALL"
+
+#: memline.c:1003
+msgid "???EMPTY BLOCK"
+msgstr "???TOM BLOKK"
+
+#: memline.c:1029
+msgid "???LINES MISSING"
+msgstr "???LINJER MANGLER"
+
+#: memline.c:1061
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ID til blokk 1 er feil (%s ikke en \".swp\"-fil?)"
+
+#: memline.c:1066
+msgid "???BLOCK MISSING"
+msgstr "???BLOKK MANGLER"
+
+#: memline.c:1082
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? Herfra til ???SLUTT kan linjer være rotet til"
+
+#: memline.c:1098
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? Herfra til ???SLUTT kan linjer ha blitt lagt til eller slettet"
+
+#: memline.c:1118
+msgid "???END"
+msgstr "???SLUTT"
+
+#: memline.c:1144
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Gjenoppretting avbrutt"
+
+#: memline.c:1149
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr ""
+"E312: Feil oppdaget under gjenoppretting; se etter linjer som starter med ???"
+
+#: memline.c:1151
+msgid "See \":help E312\" for more information."
+msgstr "Se \":help E312\" for mer informasjon."
+
+#: memline.c:1156
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Gjenoppretting komplett. Du bør sjekke at alt er i orden."
+
+#: memline.c:1157
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Du vil kanskje lagre denne filen under et annet navn\n"
+
+#: memline.c:1158
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "og sammenligne den mot den originale filen for å finne forandringer)\n"
+
+#: memline.c:1159
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"Slett \".swp\"-filen etterpå.\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1215
+msgid "Swap files found:"
+msgstr "Swapfiler funnet:"
+
+#: memline.c:1393
+msgid " In current directory:\n"
+msgstr " I nåværende katalog:\n"
+
+#: memline.c:1395
+msgid " Using specified name:\n"
+msgstr " Bruker spesifisert navn:\n"
+
+#: memline.c:1399
+msgid " In directory "
+msgstr " I katalog "
+
+#: memline.c:1417
+msgid " -- none --\n"
+msgstr " -- ingen --\n"
+
+#: memline.c:1489
+msgid " owned by: "
+msgstr " eies av: "
+
+#: memline.c:1491
+msgid " dated: "
+msgstr " datert: "
+
+#: memline.c:1495 memline.c:3685
+msgid " dated: "
+msgstr " datert: "
+
+#: memline.c:1511
+msgid " [from Vim version 3.0]"
+msgstr " [fra Vim versjon 3.0]"
+
+#: memline.c:1515
+msgid " [does not look like a Vim swap file]"
+msgstr " [ser ikke ut som en Vim-swapfil]"
+
+#: memline.c:1519
+msgid " file name: "
+msgstr " filnavn: "
+
+#: memline.c:1525
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" modifisert: "
+
+#: memline.c:1526
+msgid "YES"
+msgstr "JA"
+
+#: memline.c:1526
+msgid "no"
+msgstr "nei"
+
+#: memline.c:1530
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" brukernavn: "
+
+#: memline.c:1537
+msgid " host name: "
+msgstr " vertsnavn: "
+
+#: memline.c:1539
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" vertsnavn: "
+
+#: memline.c:1545
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" prosess-ID: "
+
+#: memline.c:1551
+msgid " (still running)"
+msgstr " (kjører fortsatt)"
+
+#: memline.c:1563
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [ikke brukbar med denne Vim-versjonen]"
+
+#: memline.c:1566
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [ikke brukbar på denne maskinen]"
+
+#: memline.c:1571
+msgid " [cannot be read]"
+msgstr " [kan ikke leses]"
+
+#: memline.c:1575
+msgid " [cannot be opened]"
+msgstr " [kan ikke åpnes]"
+
+#: memline.c:1765
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Kan ikke bevare, swapfil mangler"
+
+#: memline.c:1818
+msgid "File preserved"
+msgstr "Fil bevart"
+
+#: memline.c:1820
+msgid "E314: Preserve failed"
+msgstr "E314: Bevaring feilet"
+
+#: memline.c:1891
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: Ugyldig lnum: %ld"
+
+#: memline.c:1917
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: Kan ikke finne linje %ld"
+
+#: memline.c:2307
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: Pekerblokk-id feil 3"
+
+#: memline.c:2387
+msgid "stack_idx should be 0"
+msgstr "stack_idx skulle være 0"
+
+#: memline.c:2449
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Oppdaterte for mange blokker?"
+
+#: memline.c:2631
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: Pekerblokk-id feil 4"
+
+#: memline.c:2658
+msgid "deleted block 1?"
+msgstr "slettet blokk 1?"
+
+#: memline.c:2858
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Kan ikke finne linje %ld"
+
+#: memline.c:3101
+msgid "E317: pointer block id wrong"
+msgstr "E317: Pekerblokk-id feil"
+
+#: memline.c:3117
+msgid "pe_line_count is zero"
+msgstr "pe_line_count er null"
+
+#: memline.c:3146
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: Linjenummer utenfor område: %ld forbi slutten"
+
+#: memline.c:3150
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: Linjeantall feil i blokk %ld"
+
+#: memline.c:3199
+msgid "Stack size increases"
+msgstr "Stackstørrelse øker"
+
+#: memline.c:3245
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: Pekerblokk-id feil 2"
+
+#: memline.c:3675
+msgid "E325: ATTENTION"
+msgstr "E325: VIKTIG"
+
+#: memline.c:3676
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Fant en swapfil ved navn \""
+
+#: memline.c:3680
+msgid "While opening file \""
+msgstr "Under åpning av filen \""
+
+#: memline.c:3689
+msgid " NEWER than swap file!\n"
+msgstr " NYERE enn swapfil!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3693
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Det er mulig et annet program redigerer den samme filen.\n"
+" Hvis det er tilfelle, vær forsiktig så du ikke ender opp med to\n"
+" forskjellige utgaver av den samme filen når du gjør forandringer.\n"
+
+#: memline.c:3694
+msgid " Quit, or continue with caution.\n"
+msgstr " Avslutt, eller fortsett med varsomhet.\n"
+
+#: memline.c:3695
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) En økt for denne filen kræsjet.\n"
+
+#: memline.c:3696
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Hvis det er tilfelle, bruk \":recover\" eller \"vim -r "
+
+#: memline.c:3698
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" for å gjenopprette forandringene (se \":help recovery\").\n"
+
+#: memline.c:3699
+msgid " If you did this already, delete the swap file \""
+msgstr " Hvis du har gjort dette allerede, slett swapfilen \""
+
+#: memline.c:3701
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" for å unngå denne meldingen.\n"
+
+#: memline.c:3715 memline.c:3719
+msgid "Swap file \""
+msgstr "Swapfilen \""
+
+#: memline.c:3716 memline.c:3722
+msgid "\" already exists!"
+msgstr "\" finnes allerede!"
+
+#: memline.c:3725
+msgid "VIM - ATTENTION"
+msgstr "VIM - VIKTIG"
+
+#: memline.c:3727
+msgid "Swap file already exists!"
+msgstr "Swapfilen eksisterer allerede!"
+
+#: memline.c:3731
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort"
+msgstr ""
+"&Åpne skrivebeskyttet\n"
+"&Rediger likevel\n"
+"&Gjenopprett\n"
+"&Avslutt\n"
+"Av&bryt"
+
+#: memline.c:3733
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort\n"
+"&Delete it"
+msgstr ""
+"&Åpne skrivebeskyttet\n"
+"&Rediger likevel\n"
+"&Gjenopprett\n"
+"&Avslutt\n"
+"Av&bryt\n"
+"&Slette den"
+
+#: memline.c:3790
+msgid "E326: Too many swap files found"
+msgstr "E326: For mange swapfiler funnet"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Del av menyelement er ikke undermeny"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Menyen eksisterer bare i en annen modus"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Ingen meny med dette navnet"
+
+#: menu.c:525
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Menysti kan ikke lede til en undermeny"
+
+#: menu.c:564
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: Kan ikke legge til menyelementer direkte på menylinjen"
+
+#: menu.c:570
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Skilletegn kan ikke være del av en menysti"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1097
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Menyer ---"
+
+#: menu.c:2019
+msgid "Tear off this menu"
+msgstr "Riv av denne menyen"
+
+#: menu.c:2084
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Menystien må lede til et menyvalg"
+
+#: menu.c:2104
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Fant ikke menyen: %s"
+
+#: menu.c:2173
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: Menyen er ikke definert for %s-modus"
+
+#: menu.c:2211
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Menystien må lede til en undermeny"
+
+#: menu.c:2232
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Fant ikke menyen - sjekk menynavnet"
+
+#: message.c:414
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Feil oppdaget under prosessering av %s:"
+
+#: message.c:440
+#, c-format
+msgid "line %4ld:"
+msgstr "linje %4ld:"
+
+#: message.c:647
+msgid "[string too long]"
+msgstr "[strengen er for lang]"
+
+#: message.c:797
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr ""
+"Vedlikeholder for norsk oversettelse: Øyvind A. Holm <sunny@sunbase.org>"
+
+#: message.c:1025
+msgid "Interrupt: "
+msgstr "Avbryt: "
+
+#: message.c:1028
+msgid "Hit ENTER to continue"
+msgstr "Trykk ENTER for å fortsette"
+
+#: message.c:1030
+msgid "Hit ENTER or type command to continue"
+msgstr "Trykk ENTER eller skriv en kommando for å fortsette"
+
+#: message.c:2351
+msgid "-- More --"
+msgstr "-- Mer --"
+
+#: message.c:2354
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr ""
+" (ENTER/BACKSPACE: Linje, MELLOMROM/b: Side, Pil ned/Pil opp: Halv side, q: "
+"Avslutt)"
+
+#: message.c:2355
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (ENTER: Linje, MELLOMROM: Side, d: Halv side, q: Avslutt)"
+
+#: message.c:2982 message.c:2997
+msgid "Question"
+msgstr "Spørsmål"
+
+#: message.c:2984
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Ja\n"
+"&Nei"
+
+#: message.c:3017
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Ja\n"
+"&Nei\n"
+"&Lagre alle\n"
+"&Forkast alle\n"
+"&Avbryt"
+
+#: message.c:3058
+msgid "Save File dialog"
+msgstr "\"Lagre fil\"-dialogvindu"
+
+#: message.c:3060
+msgid "Open File dialog"
+msgstr "\"Åpne fil\"-dialogvindu"
+
+#. TODO: non-GUI file selector here
+#: message.c:3131
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: Dessverre ingen filbehandler i konsollmodus"
+
+#: misc1.c:2773
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: Advarsel: Forandrer en skrivebeskyttet fil"
+
+#: misc1.c:3021
+msgid "1 more line"
+msgstr "1 linje lagt til"
+
+#: misc1.c:3023
+msgid "1 line less"
+msgstr "1 linje fjernet"
+
+#: misc1.c:3028
+#, c-format
+msgid "%ld more lines"
+msgstr "%ld linjer lagt til"
+
+#: misc1.c:3030
+#, c-format
+msgid "%ld fewer lines"
+msgstr "%ld linjer fjernet"
+
+#: misc1.c:3033
+msgid " (Interrupted)"
+msgstr " (Avbrutt)"
+
+#: misc1.c:7588
+msgid "Vim: preserving files...\n"
+msgstr "Vim: Bevarer filer ...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:7598
+msgid "Vim: Finished.\n"
+msgstr "Vim: Ferdig.\n"
+
+#: misc2.c:695 misc2.c:711
+msgid "ERROR: "
+msgstr "FEIL: "
+
+#: misc2.c:715
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bytes] totalt alloc-frigjort %lu-%lu, i bruk %lu, topp-bruk %lu\n"
+
+#: misc2.c:717
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[kall] totale \"re/malloc()\"-er %lu, totale \"free()\"-er %lu\n"
+"\n"
+
+#: misc2.c:772
+msgid "E340: Line is becoming too long"
+msgstr "E340: Linjen blir for lang"
+
+#: misc2.c:816
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Intern feil: lalloc(%ld, )"
+
+#: misc2.c:924
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Ikke mer ledig hukommelse! (Reserverer %lu bytes)"
+
+#: misc2.c:2594
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Kaller skall for å utføre \"%s\""
+
+#: misc2.c:2816
+msgid "E545: Missing colon"
+msgstr "E545: Mangler kolon"
+
+#: misc2.c:2818 misc2.c:2845
+msgid "E546: Illegal mode"
+msgstr "E546: Ulovlig modus"
+
+#: misc2.c:2884
+msgid "E547: Illegal mouseshape"
+msgstr "E547: Ulovlig utseende på musepekeren"
+
+#: misc2.c:2924
+msgid "E548: digit expected"
+msgstr "E548: Siffer forventet"
+
+#: misc2.c:2929
+msgid "E549: Illegal percentage"
+msgstr "E549: Ulovlig prosent"
+
+#: misc2.c:3239
+msgid "Enter encryption key: "
+msgstr "Skriv krypteringsnøkkel: "
+
+#: misc2.c:3240
+msgid "Enter same key again: "
+msgstr "Gjenta krypteringsnøkkelen: "
+
+#: misc2.c:3250
+msgid "Keys don't match!"
+msgstr "Krypteringsnøklene stemmer ikke overens!"
+
+#: misc2.c:3799
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Ugyldig sti: '**[nummer]' må være på slutten av stien eller bli "
+"etterfulgt av '%s'."
+
+#: misc2.c:5078
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Kan ikke finne katalogen \"%s\" i \"cdpath\""
+
+#: misc2.c:5081
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Kan ikke finne filen \"%s\" i stien"
+
+#: misc2.c:5087
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: Ingen flere katalog-\"%s\" funnet i \"cdpath\""
+
+#: misc2.c:5090
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: Ingen flere fil-\"%s\" funnet i stien"
+
+#: misc2.c:5324
+msgid "E550: Missing colon"
+msgstr "E550: Mangler kolon"
+
+#: misc2.c:5336
+msgid "E551: Illegal component"
+msgstr "E551: Ulovlig komponent"
+
+#: misc2.c:5344
+msgid "E552: digit expected"
+msgstr "E552: Siffer forventet"
+
+#. Get here when the server can't be found.
+#: netbeans.c:396
+msgid "Cannot connect to Netbeans #2"
+msgstr "Kan ikke koble til Netbeans #2"
+
+#: netbeans.c:404
+msgid "Cannot connect to Netbeans"
+msgstr "Kan ikke koble til Netbeans"
+
+#: netbeans.c:450
+#, c-format
+msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\""
+msgstr ""
+"E668: Feil tilgangsmodus for infofilen til NetBeans-forbindelse: \"%s\""
+
+#: netbeans.c:749
+msgid "read from Netbeans socket"
+msgstr "les fra Netbeans-socket"
+
+#: netbeans.c:1643
+#, c-format
+msgid "E658: NetBeans connection lost for buffer %ld"
+msgstr "E658: Mistet NetBeans-forbindelse for buffer %ld"
+
+#: normal.c:2983
+msgid "Warning: terminal cannot highlight"
+msgstr "Advarsel: Terminalen kan ikke utheve"
+
+#: normal.c:3279
+msgid "E348: No string under cursor"
+msgstr "E348: Ingen streng under markør"
+
+#: normal.c:3281
+msgid "E349: No identifier under cursor"
+msgstr "E349: Ingen identifikator under markør"
+
+#: normal.c:4522
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: Kan ikke slette folder med nåværende 'foldmethod'"
+
+#: normal.c:6743
+msgid "E664: changelist is empty"
+msgstr "E664: Forandringslisten er tom"
+
+#: normal.c:6745
+msgid "E662: At start of changelist"
+msgstr "E662: Ved starten av forandringsliste"
+
+#: normal.c:6747
+msgid "E663: At end of changelist"
+msgstr "E663: Ved slutten av forandringsliste"
+
+#: normal.c:8009
+msgid "Type :quit<Enter> to exit Vim"
+msgstr "Skriv :quit<Enter> for å avslutte Vim"
+
+#: ops.c:294
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "1 linje \"%s\"-et 1 gang"
+
+#: ops.c:296
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 linje \"%s\"-et %d ganger"
+
+#: ops.c:301
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld linjer \"%s\"-et 1 gang"
+
+#: ops.c:304
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld linjer \"%s\"-et %d ganger"
+
+#: ops.c:662
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld linjer å rykke inn ... "
+
+#: ops.c:712
+msgid "1 line indented "
+msgstr "1 linje rykket inn "
+
+#: ops.c:714
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld linjer rykket inn "
+
+#. must display the prompt
+#: ops.c:1688
+msgid "cannot yank; delete anyway"
+msgstr "kan ikke kopiere til utklippstavle; slett likevel"
+
+#: ops.c:2274
+msgid "1 line changed"
+msgstr "1 linje forandret"
+
+#: ops.c:2276
+#, c-format
+msgid "%ld lines changed"
+msgstr "%ld linjer forandret"
+
+#: ops.c:2660
+#, c-format
+msgid "freeing %ld lines"
+msgstr "frigjør %ld linjer"
+
+#: ops.c:2941
+msgid "1 line yanked"
+msgstr "1 linje kopiert til utklippstavlen"
+
+#: ops.c:2943
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld linjer kopiert til utklippstavlen"
+
+#: ops.c:3228
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: Ingenting i register %s"
+
+#. Highlight title
+#: ops.c:3779
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Registere ---"
+
+#: ops.c:5088
+msgid "Illegal register name"
+msgstr "Ulovlig registernavn"
+
+#: ops.c:5176
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Registere:\n"
+
+#: ops.c:5226
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: Ukjent registertype %d"
+
+#: ops.c:5711
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: Ugyldig registernavn: '%s'"
+
+#: ops.c:6071
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Kol; "
+
+#: ops.c:6078
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Valgte %s%ld av %ld linjer; %ld av %ld ord; %ld av %ld bytes"
+
+#: ops.c:6094
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Kol %s av %s; Linje %ld av %ld; Ord %ld av %ld; Byte %ld av %ld"
+
+#: ops.c:6105
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld for BOM)"
+
+#: option.c:1643
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=Side %N"
+
+#: option.c:2092
+msgid "Thanks for flying Vim"
+msgstr "Takk for at du fløy Vim"
+
+#: option.c:3419 option.c:3535
+msgid "E518: Unknown option"
+msgstr "E518: Ukjent valg"
+
+#: option.c:3432
+msgid "E519: Option not supported"
+msgstr "E519: Valget er ikke støttet"
+
+#: option.c:3457
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: Ikke tillatt i moduslinje"
+
+#: option.c:3522
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tSist satt fra "
+
+#: option.c:3661
+msgid "E521: Number required after ="
+msgstr "E521: Nummer nødvendig etter ="
+
+#: option.c:3989 option.c:4619
+msgid "E522: Not found in termcap"
+msgstr "E522: Ikke funnet i termcap"
+
+#: option.c:4064
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: Ulovlig tegn <%s>"
+
+#: option.c:4611
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: Kan ikke sette 'term' til tom streng"
+
+#: option.c:4614
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: Kan ikke forandre \"term\" i grafisk brukergrensesnitt"
+
+#: option.c:4616
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: Bruk \":gui\" for å starte med grafisk brukergrensesnitt"
+
+#: option.c:4645
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: 'backupext' og 'patchmode' er like"
+
+#: option.c:4860
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: Kan ikke forandres i GTK+ 2 GUI"
+
+#: option.c:5016
+msgid "E524: Missing colon"
+msgstr "E524: Mangler kolon"
+
+#: option.c:5018
+msgid "E525: Zero length string"
+msgstr "E525: Tom streng"
+
+#: option.c:5086
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: Mangler nummer etter <%s>"
+
+#: option.c:5100
+msgid "E527: Missing comma"
+msgstr "E527: Mangler komma"
+
+#: option.c:5107
+msgid "E528: Must specify a ' value"
+msgstr "E528: Må spesifisere en \"'\"-verdi"
+
+#: option.c:5148
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: Inneholder uskrivelige eller brede tegn"
+
+#: option.c:5197
+msgid "E596: Invalid font(s)"
+msgstr "E596: Ugyldig(e) skrifttype(r)"
+
+#: option.c:5205
+msgid "E597: can't select fontset"
+msgstr "E597: Kan ikke velge skrifttypesett"
+
+#: option.c:5207
+msgid "E598: Invalid fontset"
+msgstr "E598: Ugyldig skrifttypesett"
+
+#: option.c:5214
+msgid "E533: can't select wide font"
+msgstr "E533: Kan ikke velge bred skrifttype"
+
+#: option.c:5216
+msgid "E534: Invalid wide font"
+msgstr "E534: Ugyldig bred skrifttype"
+
+#: option.c:5486
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: Ulovlig tegn etter <%c>"
+
+#: option.c:5597
+msgid "E536: comma required"
+msgstr "E536: Komma nødvendig"
+
+#: option.c:5607
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: 'commentstring' må være tom eller inneholde %s"
+
+#: option.c:5682
+msgid "E538: No mouse support"
+msgstr "E538: Ingen støtte for mus"
+
+#: option.c:5950
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: Uttrykkssekvens som ikke er lukket"
+
+#: option.c:5954
+msgid "E541: too many items"
+msgstr "E541: For mange elementer"
+
+#: option.c:5956
+msgid "E542: unbalanced groups"
+msgstr "E542: Ubalanserte grupper"
+
+#: option.c:6196
+msgid "E590: A preview window already exists"
+msgstr "E590: Det finnes allerede et forhåndsvisningsvindu"
+
+#: option.c:6453
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr "W17: Arabisk trenger UTF-8, utfør ':set encoding=utf-8'"
+
+#: option.c:6786
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: Trenger minst %d linjer"
+
+#: option.c:6796
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: Trenger minst %d kolonner"
+
+#: option.c:7103
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Ukjent valg: %s"
+
+#: option.c:7223
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Terminalkoder ---"
+
+#: option.c:7225
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Globale valgverdier ---"
+
+#: option.c:7227
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Lokale valgverdier ---"
+
+#: option.c:7229
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Valg ---"
+
+#: option.c:7935
+msgid "E356: get_varp ERROR"
+msgstr "E356: \"get_varp\"-FEIL"
+
+#: option.c:8906
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': Samsvarende tegn mangler for %s"
+
+#: option.c:8940
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': Ekstra tegn etter semikolon: %s"
+
+#: os_amiga.c:280
+msgid "cannot open "
+msgstr "kan ikke åpne "
+
+#: os_amiga.c:314
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Kan ikke åpne vindu!\n"
+
+#: os_amiga.c:338
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Trenger Amigados versjon 2.04 eller nyere\n"
+
+#: os_amiga.c:344
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Trenger %s versjon %ld\n"
+
+#: os_amiga.c:416
+msgid "Cannot open NIL:\n"
+msgstr "Kan ikke åpne NIL:\n"
+
+#: os_amiga.c:427
+msgid "Cannot create "
+msgstr "Kan ikke opprette "
+
+#: os_amiga.c:905
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim avslutter med %d\n"
+
+#: os_amiga.c:941
+msgid "cannot change console mode ?!\n"
+msgstr "kan ikke forandre konsollmodus ?!\n"
+
+#: os_amiga.c:1012
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: Ikke et konsoll??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1161
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Kan ikke kjøre skall med \"-f\"-valg"
+
+#: os_amiga.c:1202 os_amiga.c:1292
+msgid "Cannot execute "
+msgstr "Kan ikke utføre "
+
+#: os_amiga.c:1205 os_amiga.c:1302
+msgid "shell "
+msgstr "skall "
+
+#: os_amiga.c:1225 os_amiga.c:1327
+msgid " returned\n"
+msgstr " returnerte\n"
+
+#: os_amiga.c:1468
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE for liten."
+
+#: os_amiga.c:1472
+msgid "I/O ERROR"
+msgstr "I/U-FEIL"
+
+#: os_mswin.c:548
+msgid "...(truncated)"
+msgstr " ...(kuttet)"
+
+#: os_mswin.c:650
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' er ikke 80, kan ikke utføre eksterne kommandoer"
+
+#: os_mswin.c:1982
+msgid "E237: Printer selection failed"
+msgstr "E237: Valg av skriver feilet"
+
+#: os_mswin.c:2022
+#, c-format
+msgid "to %s on %s"
+msgstr "til %s på %s"
+
+#: os_mswin.c:2037
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: Ukjent skrifttype for skriver: %s"
+
+#: os_mswin.c:2086 os_mswin.c:2096
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Feil under utskrift: %s"
+
+#: os_mswin.c:2097
+msgid "Unknown"
+msgstr "Ukjent"
+
+#: os_mswin.c:2124
+#, c-format
+msgid "Printing '%s'"
+msgstr "Skriver ut '%s'"
+
+#: os_mswin.c:3213
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Ulovlig navn på tegnsett \"%s\" i skrifttypenavn \"%s\""
+
+#: os_mswin.c:3221
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Ulovlig tegn '%c' i skrifttypenavn \"%s\""
+
+#: os_riscos.c:1259
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Ugyldig 'osfiletype'-valg - bruker Text"
+
+#: os_unix.c:927
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: Dobbelt signal, avslutter\n"
+
+#: os_unix.c:933
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Mottok dødelig signal %s\n"
+
+#: os_unix.c:936
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Mottok dødelig signal\n"
+
+#: os_unix.c:1199
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Åpning av X-display tok %ld millisekunder"
+
+#: os_unix.c:1226
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: Mottok X-feil\n"
+
+#: os_unix.c:1338
+msgid "Testing the X display failed"
+msgstr "Test av X-display feilet"
+
+#: os_unix.c:1477
+msgid "Opening the X display timed out"
+msgstr "Tidsavbrudd for åpning av X-display"
+
+#: os_unix.c:3234 os_unix.c:3914
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"Kan ikke kjøre skall "
+
+#: os_unix.c:3282
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Kan ikke kjøre skallet sh\n"
+
+#: os_unix.c:3286 os_unix.c:3920
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"skallet returnerte "
+
+#: os_unix.c:3421
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Kan ikke opprette rør (\"pipe\")\n"
+
+#: os_unix.c:3436
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"Kan ikke opprette tvillingprosess (\"fork\")\n"
+
+#: os_unix.c:3927
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Kommando avsluttet\n"
+
+#: os_unix.c:4191 os_unix.c:4316 os_unix.c:5982
+msgid "XSMP lost ICE connection"
+msgstr "XSMP mistet ICE-forbindelsen"
+
+#: os_unix.c:5565
+msgid "Opening the X display failed"
+msgstr "Åpning av X-display feilet"
+
+#: os_unix.c:5887
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP håndterer \"redd-deg-selv\"-forespørsel"
+
+#: os_unix.c:6006
+msgid "XSMP opening connection"
+msgstr "XSMP åpner forbindelse"
+
+#: os_unix.c:6025
+msgid "XSMP ICE connection watch failed"
+msgstr "Overvåkning av XSMP ICE-forbindelse feilet"
+
+#: os_unix.c:6045
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP SmcOpenConnection feilet: %s"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "På linje"
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "Klarte ikke reservere hukommelse for kommandolinjen."
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "VIM-feil"
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "Klarte ikke laste vim32.dll!"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Klarte ikke ordne opp i funksjonspekere til DLL-en!"
+
+#: os_win16.c:342 os_win32.c:3248
+#, c-format
+msgid "shell returned %d"
+msgstr "skallet returnerte %d"
+
+#: os_win32.c:2706
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Mottok \"%s\"-hendelse\n"
+
+#: os_win32.c:2708
+msgid "close"
+msgstr "lukk"
+
+#: os_win32.c:2710
+msgid "logoff"
+msgstr "logg av"
+
+#: os_win32.c:2711
+msgid "shutdown"
+msgstr "kjør ned"
+
+#: os_win32.c:3201
+msgid "E371: Command not found"
+msgstr "E371: Kommando ikke funnet"
+
+#: os_win32.c:3214
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE ikke funnet i $PATH.\n"
+"Eksterne kommandoer kommer ikke til å vente etter fullføring.\n"
+"Se \":help win32-vimrun\" for mer informasjon."
+
+#: os_win32.c:3217
+msgid "Vim Warning"
+msgstr "Vim-advarsel"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: For mange %%%c i formatstreng"
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: Uventet %%%c i formatstreng"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: Mangler ] i formatstreng"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: %%%c ikke støttet i formatstreng"
+
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: Ugyldig %%%c i formatstreng-prefiks"
+
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: Ugyldig %%%c i formatstreng"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' inneholder ikke søkestreng"
+
+#: quickfix.c:501
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Manglende eller tomt katalognavn"
+
+#: quickfix.c:990
+msgid "E553: No more items"
+msgstr "E553: Ingen flere elementer"
+
+#: quickfix.c:1229
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d av %d)%s%s: "
+
+#: quickfix.c:1231
+msgid " (line deleted)"
+msgstr " (linjen slettet)"
+
+#: quickfix.c:1444
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: På bunnen av quickfix-stack"
+
+#: quickfix.c:1453
+msgid "E381: At top of quickfix stack"
+msgstr "E381: På toppen av quickfix-stack"
+
+#: quickfix.c:1465
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "feilliste %d av %d; %d feil"
+
+#: quickfix.c:1943
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: Kan ikke lagre, 'buftype'-valget er satt"
+
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: Ugyldig element i %s%%[]"
+
+#: regexp.c:838
+msgid "E339: Pattern too long"
+msgstr "E339: Søkestrengen er for lang"
+
+#: regexp.c:1009
+msgid "E50: Too many \\z("
+msgstr "E50: For mange \\z("
+
+#: regexp.c:1020
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: For mange %s("
+
+#: regexp.c:1077
+msgid "E52: Unmatched \\z("
+msgstr "E52: Usamsvarende \\z("
+
+#: regexp.c:1081
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: Usamsvarende %s%%("
+
+#: regexp.c:1083
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: Usamsvarende %s("
+
+#: regexp.c:1088
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: Usamsvarende %s)"
+
+#: regexp.c:1258
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: \"%s*\"-operatoren kunne være tom"
+
+#: regexp.c:1261
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: \"%s+\"-operatoren kunne være tom"
+
+#: regexp.c:1316
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: Ugyldig tegn etter %s@"
+
+#: regexp.c:1344
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: \"%s{\"-operatoren kunne være tom"
+
+#: regexp.c:1354
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: For mange komplekse %s{...}s"
+
+#: regexp.c:1370
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: Nøstede %s*"
+
+#: regexp.c:1373
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: Nøstede %s%c"
+
+#: regexp.c:1491
+msgid "E63: invalid use of \\_"
+msgstr "E63: Ugyldig bruk av \\_"
+
+#: regexp.c:1536
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c etterfølger ingenting"
+
+#: regexp.c:1592
+msgid "E65: Illegal back reference"
+msgstr "E65: Ulovlig tilbakereferanse"
+
+#: regexp.c:1605
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z( ikke tillatt her"
+
+#: regexp.c:1624
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 med venner er ikke tillatt her"
+
+#: regexp.c:1635
+msgid "E68: Invalid character after \\z"
+msgstr "E68: Ugyldig tegn etter \\z"
+
+#: regexp.c:1684
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: Mangler ] etter %s%%["
+
+#: regexp.c:1700
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: Tom %s%%[]"
+
+#: regexp.c:1760
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: Ugyldig tegn etter %s%%"
+
+#: regexp.c:2557
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: Syntaksfeil i %s{...}"
+
+#: regexp.c:2863 regexp.c:3016
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Kræsj fanget opp; regulært uttrykk for komplekst?"
+
+#: regexp.c:3004 regexp.c:3013
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: Søkestreng forårsaket ut-av-stack-feil"
+
+#: regexp.c:3258
+msgid "External submatches:\n"
+msgstr "Eksterne deltreff:\n"
+
+#: screen.c:2184
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld linjer foldet "
+
+#: screen.c:8000
+msgid " VREPLACE"
+msgstr " V-ERSTATT"
+
+#: screen.c:8004
+msgid " REPLACE"
+msgstr " ERSTATT"
+
+#: screen.c:8009
+msgid " REVERSE"
+msgstr " OMVENDT"
+
+#: screen.c:8011
+msgid " INSERT"
+msgstr " SETT INN"
+
+#: screen.c:8014
+msgid " (insert)"
+msgstr " (sett inn)"
+
+#: screen.c:8016
+msgid " (replace)"
+msgstr " (erstatt)"
+
+#: screen.c:8018
+msgid " (vreplace)"
+msgstr " (v-erstatt)"
+
+#: screen.c:8021
+msgid " Hebrew"
+msgstr " hebraisk"
+
+#: screen.c:8032
+msgid " Arabic"
+msgstr " arabisk"
+
+#: screen.c:8035
+msgid " (lang)"
+msgstr " (lang)"
+
+#: screen.c:8039
+msgid " (paste)"
+msgstr " (lim inn)"
+
+#: screen.c:8052
+msgid " VISUAL"
+msgstr " VISUELL"
+
+#: screen.c:8053
+msgid " VISUAL LINE"
+msgstr " VISUELL LINJE"
+
+#: screen.c:8054
+msgid " VISUAL BLOCK"
+msgstr " VISUELL BLOKK"
+
+#: screen.c:8055
+msgid " SELECT"
+msgstr " VELG"
+
+#: screen.c:8056
+msgid " SELECT LINE"
+msgstr " VELG LINJE"
+
+#: screen.c:8057
+msgid " SELECT BLOCK"
+msgstr " VELG BLOKK"
+
+#: screen.c:8072 screen.c:8135
+msgid "recording"
+msgstr "spiller inn"
+
+#: search.c:37
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "Søket traff TOPPEN, fortsetter fra BUNNEN"
+
+#: search.c:38
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "Søket traff BUNNEN, fortsetter fra TOPPEN"
+
+#: search.c:526
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Ugyldig søkestreng: %s"
+
+#: search.c:853
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: Søket kom til TOPPEN uten treff på: %s"
+
+#: search.c:856
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: Søket kom til BUNNEN uten treff på: %s"
+
+#: search.c:1249
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: Forventet '?' eller '/' etter ';'"
+
+#: search.c:3768
+msgid " (includes previously listed match)"
+msgstr " (inkluderer tidligere utlistede treff)"
+
+#. cursor at status line
+#: search.c:3788
+msgid "--- Included files "
+msgstr "--- Inkluderte filer "
+
+#: search.c:3790
+msgid "not found "
+msgstr "ikke funnet "
+
+#: search.c:3791
+msgid "in path ---\n"
+msgstr "i sti ---\n"
+
+#: search.c:3848
+msgid " (Already listed)"
+msgstr " (Allerede listet)"
+
+#: search.c:3850
+msgid " NOT FOUND"
+msgstr " IKKE FUNNET"
+
+#: search.c:3902
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Leter gjennom inkludert fil: %s"
+
+#: search.c:4120
+msgid "E387: Match is on current line"
+msgstr "E387: Treffet er på nåværende linje"
+
+#: search.c:4263
+msgid "All included files were found"
+msgstr "Alle inkluderte filer ble funnet"
+
+#: search.c:4265
+msgid "No included files"
+msgstr "Ingen inkluderte filer"
+
+#: search.c:4281
+msgid "E388: Couldn't find definition"
+msgstr "E388: Fant ikke definisjonen"
+
+#: search.c:4283
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Fant ikke søketeksten"
+
+#: syntax.c:3050
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: Ulovlig parameter: %s"
+
+#: syntax.c:3230
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: Syntaksklyngen finnes ikke: %s"
+
+#: syntax.c:3394
+msgid "No Syntax items defined for this buffer"
+msgstr "Ingen syntakselementer er definert for denne bufferen"
+
+#: syntax.c:3402
+msgid "syncing on C-style comments"
+msgstr "synkroniserer C-lignende kommentarer"
+
+#: syntax.c:3410
+msgid "no syncing"
+msgstr "ingen synkronisering"
+
+#: syntax.c:3413
+msgid "syncing starts "
+msgstr "synkronisering starter "
+
+#: syntax.c:3415 syntax.c:3490
+msgid " lines before top line"
+msgstr " linjer før topplinje"
+
+#: syntax.c:3420
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- \"Syntax sync\"-elementer ---"
+
+#: syntax.c:3425
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"synkroniserer på elementer"
+
+#: syntax.c:3431
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Syntakselementer ---"
+
+#: syntax.c:3454
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: Syntaksklyngen finnes ikke: %s"
+
+#: syntax.c:3480
+msgid "minimal "
+msgstr "minimal "
+
+#: syntax.c:3487
+msgid "maximal "
+msgstr "maksimal "
+
+#: syntax.c:3499
+msgid "; match "
+msgstr "; samsvarer med "
+
+#: syntax.c:3501
+msgid " line breaks"
+msgstr " linjeskift"
+
+#: syntax.c:4135
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: \"group[t]here\" aksepteres ikke her"
+
+#: syntax.c:4159
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: Fant ikke regionelement for %s"
+
+#: syntax.c:4187
+msgid "E395: contains argument not accepted here"
+msgstr "E395: \"contains\"-parameter aksepteres ikke her"
+
+#: syntax.c:4198
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: \"containedin\"-parameter aksepteres ikke her"
+
+#: syntax.c:4276
+msgid "E397: Filename required"
+msgstr "E397: Trenger filnavn"
+
+#: syntax.c:4614
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Mangler '=': %s"
+
+#: syntax.c:4772
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Ikke nok parametere: syntax region %s"
+
+#: syntax.c:5103
+msgid "E400: No cluster specified"
+msgstr "E400: Ingen klynge er spesifisert"
+
+#: syntax.c:5140
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Skilletegn for søketekst ble ikke funnet: %s"
+
+#: syntax.c:5215
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Søppel etter søketekst: %s"
+
+#: syntax.c:5305
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr ""
+"E403: syntax sync: Søkestreng for linjefortsettelser er spesifisert to ganger"
+
+#: syntax.c:5362
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Ulovlige parametere: %s"
+
+#: syntax.c:5412
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Mangler \"er lik\"-tegn: %s"
+
+#: syntax.c:5418
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Tomt parameter: %s"
+
+#: syntax.c:5445
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s er ikke tillatt her"
+
+#: syntax.c:5452
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s må være først i \"contains\"-liste"
+
+#: syntax.c:5522
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Ukjent gruppenavn: %s"
+
+#: syntax.c:5755
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Ugyldig \":syntax\"-delkommando: %s"
+
+#: syntax.c:6136
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: Fant ikke uthevingsgruppe: %s"
+
+#: syntax.c:6160
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Ikke nok parametere: \":highlight link %s\""
+
+#: syntax.c:6167
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: For mange parametere: \":highlight link %s\""
+
+#: syntax.c:6187
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: Syntaxgruppen har oppsett, uthevingslenke ignoreres"
+
+#: syntax.c:6316
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: Uventet \"er lik\"-tegn: %s"
+
+#: syntax.c:6352
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: Mangler \"er lik\"-tegn: %s"
+
+#: syntax.c:6380
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: Mangler parameter: %s"
+
+#: syntax.c:6417
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: Ulovlig verdi: %s"
+
+#: syntax.c:6536
+msgid "E419: FG color unknown"
+msgstr "E419: Ukjent forgrunnsfarge"
+
+#: syntax.c:6547
+msgid "E420: BG color unknown"
+msgstr "E420: Ukjent bakgrunnsfarge"
+
+#: syntax.c:6608
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Kjenner ikke til fargenavnet eller -nummeret: %s"
+
+#: syntax.c:6814
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: Terminalkoden er for lang: %s"
+
+#: syntax.c:6861
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: Ulovlig parameter: %s"
+
+#: syntax.c:7390
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: For mange forskjellige uthevingsattributter i bruk"
+
+#: syntax.c:7911
+msgid "E669: Unprintable character in group name"
+msgstr "E669: Ikke-skrivbart tegn i gruppenavn"
+
+#. This is an error, but since there previously was no check only
+#. * give a warning.
+#: syntax.c:7918
+msgid "W18: Invalid character in group name"
+msgstr "W18: Ugyldig tegn i gruppenavn"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: På bunnen av tag-stack"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: På toppen av tag-stack"
+
+#: tag.c:412
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Kan ikke gå før første samsvarende tag"
+
+#: tag.c:550
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: Fant ikke tag: %s"
+
+#: tag.c:583
+#~ msgid " # pri kind tag"
+#~ msgstr ""
+
+#: tag.c:586
+msgid "file\n"
+msgstr "fil\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:744
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Velg tag fra listen (<CR> for å avbryte): "
+
+#: tag.c:784
+msgid "E427: There is only one matching tag"
+msgstr "E427: Det finnes bare en samsvarende tag"
+
+#: tag.c:786
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Kan ikke gå bak siste samsvarende tag"
+
+#: tag.c:810
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Filen \"%s\" finnes ikke"
+
+#. Give an indication of the number of matching tags
+#: tag.c:823
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "tag %d av %d%s"
+
+#: tag.c:826
+msgid " or more"
+msgstr " eller mer"
+
+#: tag.c:828
+msgid " Using tag with different case!"
+msgstr " Bruker tag med forskjellig bokstavstørrelse!"
+
+#: tag.c:872
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Filen \"%s\" finnes ikke"
+
+#. Highlight title
+#: tag.c:941
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # TIL tag FRA linje i fil/tekst"
+
+#: tag.c:1363
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Leter i tagfil %s"
+
+#: tag.c:1550
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Sti til tagfil kuttet for %s\n"
+
+#: tag.c:2203
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Formatfeil i tagfil \"%s\""
+
+#: tag.c:2207
+#, c-format
+msgid "Before byte %ld"
+msgstr "Før byte %ld"
+
+#: tag.c:2240
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Tagfil ikke sortert: %s"
+
+#. never opened any tags file
+#: tag.c:2280
+msgid "E433: No tags file"
+msgstr "E433: Ingen tagfil"
+
+#: tag.c:3016
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Kan ikke finne tagsøkestreng"
+
+#: tag.c:3027
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Kunne ikke finne tag, bare gjetter!"
+
+#: term.c:1759
+msgid "' not known. Available builtin terminals are:"
+msgstr "' ikke kjent. Tilgjengelige innebygde terminaler er:"
+
+#: term.c:1783
+msgid "defaulting to '"
+msgstr "faller tilbake på '"
+
+#: term.c:2141
+msgid "E557: Cannot open termcap file"
+msgstr "E557: Kan ikke åpne termcap-fil"
+
+#: term.c:2145
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: Fant ikke terminaloppføring i terminfo"
+
+#: term.c:2147
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: Fant ikke terminaloppføring i termcap"
+
+#: term.c:2306
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Ingen \"%s\"-oppføring i termcap"
+
+#: term.c:2780
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: Terminalfunksjonen \"cm\" nødvendig"
+
+#. Highlight title
+#: term.c:4990
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Terminaltaster ---"
+
+#: ui.c:258
+msgid "new shell started\n"
+msgstr "nytt skall startet\n"
+
+#: ui.c:1841
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: Feil under lesing av inndata, avslutter ...\n"
+
+#. must display the prompt
+#: undo.c:405
+msgid "No undo possible; continue anyway"
+msgstr "Ingen angremuligheter; fortsett likevel"
+
+#: undo.c:561
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: Gale linjenummer"
+
+#: undo.c:757
+msgid "1 change"
+msgstr "1 forandring"
+
+#: undo.c:759
+#, c-format
+msgid "%ld changes"
+msgstr "%ld forandringer"
+
+#: undo.c:812
+msgid "E439: undo list corrupt"
+msgstr "E439: Angrelisten er skadet"
+
+#: undo.c:844
+msgid "E440: undo line missing"
+msgstr "E440: Angrelisten mangler"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:711
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 16/32-bits GUI-versjon"
+
+#: version.c:713
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 32-bits GUI-versjon"
+
+#: version.c:716
+msgid " in Win32s mode"
+msgstr " i Win32s-modus"
+
+#: version.c:718
+msgid " with OLE support"
+msgstr " med OLE-støtte"
+
+#: version.c:721
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"MS-Windows 32-bits konsollversjon"
+
+#: version.c:725
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"MS-Windows 16-bits versjon"
+
+#: version.c:729
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32-bits MS-DOS-versjon"
+
+#: version.c:731
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16-bits MS-DOS-versjon"
+
+#: version.c:737
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix)-versjon"
+
+#: version.c:739
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X-versjon"
+
+#: version.c:742
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS-versjon"
+
+#: version.c:747
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS-versjon"
+
+#: version.c:757
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Inkluderte patcher: "
+
+#: version.c:783 version.c:1151
+msgid "Modified by "
+msgstr "Modifisert av "
+
+#: version.c:790
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Kompilert "
+
+#: version.c:793
+msgid "by "
+msgstr "av "
+
+#: version.c:805
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Diger (\"huge\") versjon "
+
+#: version.c:808
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Stor (\"big\") versjon "
+
+#: version.c:811
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Normal versjon "
+
+#: version.c:814
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Liten (\"small\") versjon "
+
+#: version.c:816
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Spinkel (\"tiny\") versjon "
+
+#: version.c:822
+msgid "without GUI."
+msgstr "uten GUI."
+
+#: version.c:827
+msgid "with GTK2-GNOME GUI."
+msgstr "med GTK2-GNOME GUI."
+
+#: version.c:829
+msgid "with GTK-GNOME GUI."
+msgstr "med GTK-GNOME GUI."
+
+#: version.c:833
+msgid "with GTK2 GUI."
+msgstr "med GTK2 GUI."
+
+#: version.c:835
+msgid "with GTK GUI."
+msgstr "med GTK GUI."
+
+#: version.c:840
+msgid "with X11-Motif GUI."
+msgstr "med X11-Motif GUI."
+
+#: version.c:844
+msgid "with X11-neXtaw GUI."
+msgstr "med X11-neXtaw GUI."
+
+#: version.c:846
+msgid "with X11-Athena GUI."
+msgstr "med X11-Athena GUI."
+
+#: version.c:850
+msgid "with BeOS GUI."
+msgstr "med BeOS GUI."
+
+#: version.c:853
+msgid "with Photon GUI."
+msgstr "med Photon GUI."
+
+#: version.c:856
+msgid "with GUI."
+msgstr "med GUI."
+
+#: version.c:859
+msgid "with Carbon GUI."
+msgstr "med Carbon GUI."
+
+#: version.c:862
+msgid "with Cocoa GUI."
+msgstr "med Cocoa GUI."
+
+#: version.c:865
+msgid "with (classic) GUI."
+msgstr "med (klassisk) GUI."
+
+#: version.c:876
+msgid " Features included (+) or not (-):\n"
+msgstr " Funksjoner inkludert (+) eller ikke (-):\n"
+
+#: version.c:888
+msgid " system vimrc file: \""
+msgstr " vimrc-fil på systemet: \""
+
+#: version.c:893
+msgid " user vimrc file: \""
+msgstr " vimrc-fil for brukere: \""
+
+#: version.c:898
+msgid " 2nd user vimrc file: \""
+msgstr " vimrc-fil nr. 2 for brukere: \""
+
+#: version.c:903
+msgid " 3rd user vimrc file: \""
+msgstr " vimrc-fil nr. 3 for brukere: \""
+
+#: version.c:908
+msgid " user exrc file: \""
+msgstr " exrc-fil for brukere: \""
+
+#: version.c:913
+msgid " 2nd user exrc file: \""
+msgstr " exrc-fil nr. 2 for brukere: \""
+
+#: version.c:919
+msgid " system gvimrc file: \""
+msgstr " gvimrc-fil på systemet: \""
+
+#: version.c:923
+msgid " user gvimrc file: \""
+msgstr " gvimrc-fil for brukere: \""
+
+#: version.c:927
+msgid "2nd user gvimrc file: \""
+msgstr " gvimrc-fil nr. 2 for brukere: \""
+
+#: version.c:932
+msgid "3rd user gvimrc file: \""
+msgstr " gvimrc-fil nr. 3 for brukere: \""
+
+#: version.c:939
+msgid " system menu file: \""
+msgstr " menyfil på systemet: \""
+
+#: version.c:947
+msgid " fall-back for $VIM: \""
+msgstr " $VIM faller tilbake på: \""
+
+#: version.c:953
+msgid " f-b for $VIMRUNTIME: \""
+msgstr "$VIMRUNTIME faller tilbake på: \""
+
+#: version.c:957
+msgid "Compilation: "
+msgstr "Kompilering: "
+
+#: version.c:963
+msgid "Compiler: "
+msgstr "Kompilator: "
+
+#: version.c:968
+msgid "Linking: "
+msgstr "Linking: "
+
+#: version.c:973
+msgid " DEBUG BUILD"
+msgstr " DEBUGGINGSVERSJON"
+
+#: version.c:1012
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved - Forbedret Vi"
+
+#: version.c:1014
+msgid "version "
+msgstr "versjon "
+
+#: version.c:1015
+msgid "by Bram Moolenaar et al."
+msgstr "av Bram Moolenaar med flere"
+
+#: version.c:1019
+msgid "Vim is open source and freely distributable"
+msgstr "Vim er åpen kildekode og kan fritt distribueres"
+
+#: version.c:1021
+msgid "Help poor children in Uganda!"
+msgstr "Hjelp fattige barn i Uganda!"
+
+#: version.c:1022
+msgid "type :help iccf<Enter> for information "
+msgstr "skriv :help iccf<Enter> for informasjon "
+
+#: version.c:1024
+msgid "type :q<Enter> to exit "
+msgstr "skriv :q<Enter> for å avslutte "
+
+#: version.c:1025
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "skriv :help<Enter> eller <F1> for on-line hjelp"
+
+#: version.c:1026
+msgid "type :help version6<Enter> for version info"
+msgstr "skriv :help version6<Enter> for versjonsinfo "
+
+#: version.c:1029
+msgid "Running in Vi compatible mode"
+msgstr "Kjører i Vi-kompatibel modus"
+
+#: version.c:1030
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "skriv :set nocp<Enter> for standard Vim "
+
+#: version.c:1031
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "skriv :help cp-default<Enter> for informasjon "
+
+#: version.c:1046
+msgid "menu Help->Orphans for information "
+msgstr "meny: Hjelp->Foreldreløse for informasjon "
+
+#: version.c:1048
+msgid "Running modeless, typed text is inserted"
+msgstr "Kjører uten modus, tastetrykk blir lagt inn i teksten"
+
+#: version.c:1049
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "meny: Rediger->Globale innstillinger->Innsettingsmodus av/på"
+
+#: version.c:1050
+msgid " for two modes "
+msgstr " for to moduser "
+
+#: version.c:1054
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "meny: Rediger->Globale innstillinger->Vi-kompatibilitet av/på"
+
+#: version.c:1055
+msgid " for Vim defaults "
+msgstr " for standard Vim "
+
+#: version.c:1102
+msgid "Sponsor Vim development!"
+msgstr "Støtt utviklingen av Vim!"
+
+#: version.c:1103
+msgid "Become a registered Vim user!"
+msgstr "Bli registrert bruker av Vim!"
+
+#: version.c:1106
+msgid "type :help sponsor<Enter> for information "
+msgstr "skriv :help sponsor<Enter> for informasjon "
+
+#: version.c:1107
+msgid "type :help register<Enter> for information "
+msgstr "skriv :help register<Enter> for informasjon "
+
+#: version.c:1109
+msgid "menu Help->Sponsor/Register for information "
+msgstr "meny: Hjelp->Støtte/Registrering for informasjon "
+
+#: version.c:1119
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "ADVARSEL: Windows 95/98/ME oppdaget"
+
+#: version.c:1122
+msgid "type :help windows95<Enter> for info on this"
+msgstr "skriv :help windows95<Enter> for informasjon "
+
+#: window.c:203
+msgid "E441: There is no preview window"
+msgstr "E441: Vindu for forhåndsvisning finnes ikke"
+
+#: window.c:581
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: Kan ikke splitte \"topleft\" og \"botright\" på en gang"
+
+#: window.c:1340
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Kan ikke rotere når et annet vindu er splittet"
+
+#: window.c:1836
+msgid "E444: Cannot close last window"
+msgstr "E444: Kan ikke lukke det siste vinduet"
+
+#: window.c:2567
+msgid "Already only one window"
+msgstr "Allerede bare ett vindu"
+
+#: window.c:2614
+msgid "E445: Other window contains changes"
+msgstr "E445: Annet vindu inneholder forandringer"
+
+#: window.c:4480
+msgid "E446: No file name under cursor"
+msgstr "E446: Ingen filnavn under markøren"
+
+#: window.c:4599
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Kan ikke finne filen \"%s\" i stien"
+
+#: globals.h:1241 if_perl.xs:326
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: Klarte ikke laste bibliotek %s"
+
+#: if_perl.xs:554
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr "Denne kommandoen er deaktivert, Perl-biblioteket kunne ikke lastes."
+
+#: if_perl.xs:607
+msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+msgstr ""
+"E299: Evaluering av Perl er ikke tillatt i sandkassen uten \"Safe\"-modulen"
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "Rediger med &flere Vim-er"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "Rediger med enkel &Vim"
+
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "&Differanse med Vim"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "Rediger med &Vim"
+
+#. Now concatenate
+#: GvimExt/gvimext.cpp:633
+msgid "Edit with existing Vim - &"
+msgstr "Rediger med eksisterende Vim - &"
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "Redigerer de(n) valgte filen(e) med Vim"
+
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "Klarte ikke lage prosess: Sjekk at gvim er i stien!"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "Feil i gvimext.dll"
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "Lengden på stien er for lang!"
+
+#: globals.h:1031
+msgid "--No lines in buffer--"
+msgstr "--Ingen linjer i bufferen--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1194
+msgid "E470: Command aborted"
+msgstr "E470: Kommandoen avbrutt"
+
+#: globals.h:1195
+msgid "E471: Argument required"
+msgstr "E471: Parameter nødvendig"
+
+#: globals.h:1196
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ skulle ha vært fulgt av /, ? eller &"
+
+#: globals.h:1198
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: Ugyldig i kommandolinjevindu; <ENTER> utfører, CTRL-C avslutter"
+
+#: globals.h:1200
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Kommandoen er ikke tillatt fra exrc/vimrc i nåværende katalog eller "
+"tagsøk"
+
+#: globals.h:1202
+msgid "E171: Missing :endif"
+msgstr "E171: Mangler :endif"
+
+#: globals.h:1203
+msgid "E600: Missing :endtry"
+msgstr "E600: Mangler :endtry"
+
+#: globals.h:1204
+msgid "E170: Missing :endwhile"
+msgstr "E170: Mangler :endwhile"
+
+#: globals.h:1205
+msgid "E588: :endwhile without :while"
+msgstr "E588: :endwhile uten :while"
+
+#: globals.h:1207
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Filen finnes (legg til ! for å overstyre)"
+
+#: globals.h:1208
+msgid "E472: Command failed"
+msgstr "E472: Kommandoen feilet"
+
+#: globals.h:1210
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Ukjent skrifttypesett: %s"
+
+#: globals.h:1214
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Ukjent skrifttype: %s"
+
+#: globals.h:1217
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: Skrifttypen \"%s\" har ikke fast bredde"
+
+#: globals.h:1219
+msgid "E473: Internal error"
+msgstr "E473: Intern feil"
+
+#: globals.h:1220
+msgid "Interrupted"
+msgstr "Avbrutt"
+
+#: globals.h:1221
+msgid "E14: Invalid address"
+msgstr "E14: Ugyldig adresse"
+
+#: globals.h:1222
+msgid "E474: Invalid argument"
+msgstr "E474: Ugyldig parameter"
+
+#: globals.h:1223
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: Ugyldig paramter: %s"
+
+#: globals.h:1225
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Ugyldig uttrykk: %s"
+
+#: globals.h:1227
+msgid "E16: Invalid range"
+msgstr "E16: Ugyldig område"
+
+#: globals.h:1228
+msgid "E476: Invalid command"
+msgstr "E476: Ugyldig kommando"
+
+#: globals.h:1230
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" er en katalog"
+
+#: globals.h:1233
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Uventede tegn før '='"
+
+#: globals.h:1236
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Bibliotek-kall feilet for \"%s()\""
+
+#: globals.h:1242
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: Klarte ikke laste biblioteksfunksjon %s"
+
+#: globals.h:1244
+msgid "E19: Mark has invalid line number"
+msgstr "E19: Merket har et ugyldig linjenummer"
+
+#: globals.h:1245
+msgid "E20: Mark not set"
+msgstr "E20: Merket ble ikke satt"
+
+#: globals.h:1246
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Kan ikke gjøre forandringer, 'modifiable' er av"
+
+#: globals.h:1247
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Skripts nøstet for dypt"
+
+#: globals.h:1248
+msgid "E23: No alternate file"
+msgstr "E23: Ingen alternativ fil"
+
+#: globals.h:1249
+msgid "E24: No such abbreviation"
+msgstr "E24: Forkortelsen finnes ikke"
+
+#: globals.h:1250
+msgid "E477: No ! allowed"
+msgstr "E477: Ingen ! tillatt"
+
+#: globals.h:1252
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: GUI kan ikke brukes: Ikke slått på under kompilering"
+
+#: globals.h:1255
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: Hebraisk kan ikke brukes: Ikke slått på under kompilering\n"
+
+#: globals.h:1258
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr ""
+"E27: Persisk (Farsi) kan ikke brukes: Ikke slått på under kompilering\n"
+
+#: globals.h:1261
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: Arabisk kan ikke brukes: Ikke slått på under kompilering\n"
+
+#: globals.h:1264
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Uthevingsgruppe finnes ikke: %s"
+
+#: globals.h:1266
+msgid "E29: No inserted text yet"
+msgstr "E29: Ingen innlagt tekst enda"
+
+#: globals.h:1267
+msgid "E30: No previous command line"
+msgstr "E30: Ingen tidligere kommandolinje"
+
+#: globals.h:1268
+msgid "E31: No such mapping"
+msgstr "E31: Mappingen finnes ikke"
+
+#: globals.h:1269
+msgid "E479: No match"
+msgstr "E479: Ingen treff"
+
+#: globals.h:1270
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: Ingen treff: %s"
+
+#: globals.h:1271
+msgid "E32: No file name"
+msgstr "E32: Mangler filnavn"
+
+#: globals.h:1272
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: Ingen tidligere erstatninger med regulære uttrykk"
+
+#: globals.h:1273
+msgid "E34: No previous command"
+msgstr "E34: Ingen tidligere kommando"
+
+#: globals.h:1274
+msgid "E35: No previous regular expression"
+msgstr "E35: Ingen tidligere regulære uttrykk"
+
+#: globals.h:1275
+msgid "E481: No range allowed"
+msgstr "E481: Område er ikke tillatt"
+
+#: globals.h:1277
+msgid "E36: Not enough room"
+msgstr "E36: Ikke nok plass"
+
+#: globals.h:1280
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: Ingen registrert tjener kalt \"%s\""
+
+#: globals.h:1282
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: Kan ikke opprette filen %s"
+
+#: globals.h:1283
+msgid "E483: Can't get temp file name"
+msgstr "E483: Kan ikke hente navn på midlertidig fil"
+
+#: globals.h:1284
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: Kan ikke åpne filen %s"
+
+#: globals.h:1285
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: Kan ikke lese filen %s"
+
+#: globals.h:1286
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: Ikke lagret siden forrige forandring (legg til ! for å overstyre)"
+
+#: globals.h:1287
+msgid "E38: Null argument"
+msgstr "E38: Nullparameter"
+
+#: globals.h:1289
+msgid "E39: Number expected"
+msgstr "E39: Nummer forventet"
+
+#: globals.h:1292
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Kan ikke åpne feilfilen %s"
+
+#: globals.h:1295
+msgid "E233: cannot open display"
+msgstr "E233: Kan ikke åpne display"
+
+#: globals.h:1297
+msgid "E41: Out of memory!"
+msgstr "E41: Ikke mer ledig hukommelse!"
+
+#: globals.h:1299
+msgid "Pattern not found"
+msgstr "Fant ikke søketeksten"
+
+#: globals.h:1301
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: Fant ikke søketeksten: %s"
+
+#: globals.h:1302
+msgid "E487: Argument must be positive"
+msgstr "E487: Parameteret må være positivt"
+
+#: globals.h:1304
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: Kan ikke gå tilbake til tidligere katalog"
+
+#: globals.h:1308
+msgid "E42: No Errors"
+msgstr "E42: Ingen feil"
+
+#: globals.h:1310
+msgid "E43: Damaged match string"
+msgstr "E43: Ødelagt søkestreng"
+
+#: globals.h:1311
+msgid "E44: Corrupted regexp program"
+msgstr "E44: Skadet program med regulært uttrykk"
+
+#: globals.h:1312
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: 'readonly'-valget er satt (legg til ! for å overstyre)"
+
+#: globals.h:1314
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Kan ikke sette skrivebeskyttet variabel \"%s\""
+
+#: globals.h:1317
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Feil under lesing av feilfilen"
+
+#: globals.h:1320
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: Ikke tillatt i sandkassen"
+
+#: globals.h:1322
+msgid "E523: Not allowed here"
+msgstr "E523: Ikke tillatt her"
+
+#: globals.h:1325
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Forandring av skjermmodus er ikke støttet"
+
+#: globals.h:1327
+msgid "E49: Invalid scroll size"
+msgstr "E49: Ugyldig \"scroll\"-verdi"
+
+#: globals.h:1328
+msgid "E91: 'shell' option is empty"
+msgstr "E91: 'shell'-valget er tomt"
+
+#: globals.h:1330
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Kunne ikke lese inn skiltdata!"
+
+#: globals.h:1332
+msgid "E72: Close error on swap file"
+msgstr "E72: Feil under lukking av swapfil"
+
+#: globals.h:1333
+msgid "E73: tag stack empty"
+msgstr "E73: Tag-stack tom"
+
+#: globals.h:1334
+msgid "E74: Command too complex"
+msgstr "E74: Kommandoen er for kompleks"
+
+#: globals.h:1335
+msgid "E75: Name too long"
+msgstr "E75: Navnet er for langt"
+
+#: globals.h:1336
+msgid "E76: Too many ["
+msgstr "E76: For mange ["
+
+#: globals.h:1337
+msgid "E77: Too many file names"
+msgstr "E77: For mange filnavn"
+
+#: globals.h:1338
+msgid "E488: Trailing characters"
+msgstr "E488: Etterfølgende tegn"
+
+#: globals.h:1339
+msgid "E78: Unknown mark"
+msgstr "E78: Ukjent merke"
+
+#: globals.h:1340
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Klarte ikke utvide jokertegn"
+
+#: globals.h:1342
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: 'winheight' kan ikke være mindre enn 'winminheight'"
+
+#: globals.h:1344
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: 'winwidth' kan ikke være mindre enn 'winminwidth'"
+
+#: globals.h:1347
+msgid "E80: Error while writing"
+msgstr "E80: Feil under skriving"
+
+#: globals.h:1348
+msgid "Zero count"
+msgstr "Antall repeteringer er null"
+
+#: globals.h:1350
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: Bruker <SID> utenom skript-kontekst"
+
+#: globals.h:1353
+msgid "E449: Invalid expression received"
+msgstr "E449: Ugyldig uttrykk mottatt"
+
+#: globals.h:1356
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: Regionen er beskyttet og kan ikke modifiseres"
diff --git a/src/po/pl.cp1250.po b/src/po/pl.cp1250.po
new file mode 100644
index 000000000..f569ae6bb
--- /dev/null
+++ b/src/po/pl.cp1250.po
@@ -0,0 +1,6576 @@
+# translation of pl.po to Polish
+# Polish Translation for Vim
+#
+# updated 2001 for vim-6.0
+# FIRST AUTHOR Marcin Dalecki <dalecki@cyber.cs.net.pl>, 2000.
+# Mikolaj Machowski <mikmach@wp.pl>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pl\n"
+"POT-Creation-Date: 2004-05-23 21:41+0200\n"
+"PO-Revision-Date: 2004-05-23 22:00+0200\n"
+"Last-Translator: Mikolaj Machowski <mikmach@wp.pl>\n"
+"Language-Team: Polish <pl@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=cp1250\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.9\n"
+
+#: buffer.c:102
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Nie mogê zarezerwowaæ bufora; zakoñczenie..."
+
+#: buffer.c:105
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: Nie mogê zarezerwowaæ bufora; u¿ywam innego..."
+
+#: buffer.c:805
+msgid "E515: No buffers were unloaded"
+msgstr "E515: Nie wy³adowano ¿adnego bufora"
+
+#: buffer.c:807
+msgid "E516: No buffers were deleted"
+msgstr "E516: Nie skasowano ¿adnego bufora"
+
+#: buffer.c:809
+msgid "E517: No buffers were wiped out"
+msgstr "E517: Nie wyrzucono ¿adnego bufora"
+
+#: buffer.c:817
+msgid "1 buffer unloaded"
+msgstr "1 bufor wy³adowany"
+
+#: buffer.c:819
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "wy³adowano %d buforów"
+
+#: buffer.c:824
+msgid "1 buffer deleted"
+msgstr "1 bufor skasowany"
+
+#: buffer.c:826
+#, c-format
+msgid "%d buffers deleted"
+msgstr "%d buforów skasowano"
+
+#: buffer.c:831
+msgid "1 buffer wiped out"
+msgstr "wyrzucono 1 bufor "
+
+#: buffer.c:833
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "wyrzucono %d buforów"
+
+#: buffer.c:894
+msgid "E84: No modified buffer found"
+msgstr "E84: Nie znaleziono zmienionych buforów"
+
+#. back where we started, didn't find anything.
+#: buffer.c:933
+msgid "E85: There is no listed buffer"
+msgstr "E85: Nie ma wylistowanych buforów"
+
+#: buffer.c:945
+#, c-format
+msgid "E86: Buffer %ld does not exist"
+msgstr "E86: Bufor \"%ld\" nie istnieje"
+
+#: buffer.c:948
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Nie mogê przejœæ poza ostatni bufor"
+
+#: buffer.c:950
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Nie mogê przejœæ przed pierwszy bufor"
+
+#: buffer.c:988
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr "E89 Nie zapisano zmian w buforze %ld (wymuœ przez !)"
+
+#: buffer.c:1005
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: Nie mogê wy³adowaæ ostatniego bufora"
+
+#: buffer.c:1538
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: OSTRZE¯ENIE: Przepe³nienie listy nazw plików"
+
+#: buffer.c:1709
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: Nie znaleziono bufora %ld"
+
+#: buffer.c:1940
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Wielokrotne dopasowania dla %s"
+
+#: buffer.c:1942
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: ¯aden bufor nie pasuje do %s"
+
+#: buffer.c:2337
+#, c-format
+msgid "line %ld"
+msgstr "wiersz %ld"
+
+#: buffer.c:2420
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Bufor o tej nazwie ju¿ istnieje"
+
+#: buffer.c:2713
+msgid " [Modified]"
+msgstr " [Zmieniony]"
+
+#: buffer.c:2718
+msgid "[Not edited]"
+msgstr "[Nie edytowany]"
+
+#: buffer.c:2723
+msgid "[New file]"
+msgstr "[Nowy Plik]"
+
+#: buffer.c:2724
+msgid "[Read errors]"
+msgstr "[B³¹d odczytu]"
+
+#: buffer.c:2726 fileio.c:2112
+msgid "[readonly]"
+msgstr "[tylko odczyt]"
+
+#: buffer.c:2747
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 wiersz --%d%%--"
+
+#: buffer.c:2749
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld wiersze --%d%%--"
+
+#: buffer.c:2756
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "wiersz %ld z %ld --%d%%-- kol "
+
+#: buffer.c:2864
+msgid "[No file]"
+msgstr "[Brak pliku]"
+
+#. must be a help buffer
+#: buffer.c:2904
+msgid "help"
+msgstr "pomoc"
+
+#: buffer.c:3463 screen.c:5075
+msgid "[help]"
+msgstr "[pomoc]"
+
+#: buffer.c:3495 screen.c:5081
+msgid "[Preview]"
+msgstr "[Podgl¹d]"
+
+#: buffer.c:3775
+msgid "All"
+msgstr "Wszystko"
+
+#: buffer.c:3775
+msgid "Bot"
+msgstr "Dó³"
+
+#: buffer.c:3777
+msgid "Top"
+msgstr "Góra"
+
+#: buffer.c:4523
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# Lista buforów:\n"
+
+#: buffer.c:4556
+msgid "[Error List]"
+msgstr "[Lista B³êdów]"
+
+#: buffer.c:4569 memline.c:1520
+msgid "[No File]"
+msgstr "[Brak Pliku]"
+
+#: buffer.c:4882
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Znaki ---"
+
+#: buffer.c:4901
+#, c-format
+msgid "Signs for %s:"
+msgstr "Znaki dla %s:"
+
+#: buffer.c:4907
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " wiersz=%ld id=%d nazwa=%s"
+
+#: diff.c:139
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: Nie mogê zró¿nicowaæ wiêcej ni¿ %ld buforów"
+
+#: diff.c:709
+msgid "E97: Cannot create diffs"
+msgstr "E97: Nie mogê stworzyæ ró¿nic"
+
+#: diff.c:814
+msgid "Patch file"
+msgstr "Plik ³ata"
+
+#: diff.c:1065
+msgid "E98: Cannot read diff output"
+msgstr "E98: Nie mogê wczytaæ wyjœcia ró¿nicy"
+
+#: diff.c:1815
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Bie¿¹cy bufor nie jest w trybie ró¿nic"
+
+#: diff.c:1827
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: Brak innego bufora w trybie ró¿nic"
+
+#: diff.c:1835
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: Wiêcej ni¿ jeden bufor w trybie ró¿nicowania, nie wiem którego u¿yæ"
+
+#: diff.c:1858
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Nie mogê znaleŸæ bufora \"%s\""
+
+#: diff.c:1864
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Bufor \"%s\" nie jest w trybie ró¿nicowania"
+
+#: digraph.c:2199
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: Escape jest niedozwolone w dwugrafie"
+
+#: digraph.c:2384
+msgid "E544: Keymap file not found"
+msgstr "E544: Nie znaleziono pliku rozk³adu klawiszy"
+
+#: digraph.c:2411
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: Zastosowano :loadkeymap w niewczytanym pliku"
+
+#: edit.c:40
+msgid " Keyword completion (^N^P)"
+msgstr " Dope³nianie s³ów kluczowych (^N^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E^Y^L^]^F^I^K^D^V^N^P)"
+msgstr " ^X tryb (^E^Y^L^]^F^I^K^D^V^N^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N^P)"
+msgstr " Lokalne dope³nianie s³ów kluczowych (^N^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L^N^P)"
+msgstr " Dope³nianie pe³nych wierszy (^L^N^P)"
+
+#: edit.c:46
+msgid " File name completion (^F^N^P)"
+msgstr " Dope³nianie nazw plików (^F^N^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]^N^P)"
+msgstr " Dope³nianie znaczników (^]^N^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N^P)"
+msgstr " Dope³nianie wzorców tropów (^N^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D^N^P)"
+msgstr " Dope³nianie definicji (^D^N^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K^N^P)"
+msgstr " Dope³nianie ze s³owników (^K^N^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T^N^P)"
+msgstr " Dope³nianie z tezaurusa (^T^N^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V^N^P)"
+msgstr " Dope³nianie wiersza poleceñ (^V^N^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Dobi³em do koñca akapitu"
+
+#: edit.c:962
+msgid "'thesaurus' option is empty"
+msgstr "opcja 'thesaurus' jest pusta"
+
+#: edit.c:1166
+msgid "'dictionary' option is empty"
+msgstr "opcja 'dictionary' jest pusta"
+
+#: edit.c:2162
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Przegl¹dam s³ownik: %s"
+
+#: edit.c:2368
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (wprowadzanie) Przewijanie (^E/^Y)"
+
+#: edit.c:2370
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (zamiana) Przewijanie (^E/^Y)"
+
+#: edit.c:2684
+#, c-format
+msgid "Scanning: %s"
+msgstr "Przegl¹dam: %s"
+
+#: edit.c:2719
+msgid "Scanning tags."
+msgstr "Przegl¹dam znaczniki."
+
+#: edit.c:3381
+msgid " Adding"
+msgstr " Dodajê"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3430
+msgid "-- Searching..."
+msgstr "-- Szukam..."
+
+#: edit.c:3486
+msgid "Back at original"
+msgstr "Z powrotem na pierwotnym"
+
+#: edit.c:3491
+msgid "Word from other line"
+msgstr "Wyraz z innego wiersza"
+
+#: edit.c:3496
+msgid "The only match"
+msgstr "Jedyne dopasowanie"
+
+#: edit.c:3555
+#, c-format
+msgid "match %d of %d"
+msgstr "pasuje %d z %d"
+
+#: edit.c:3558
+#, c-format
+msgid "match %d"
+msgstr "pasuje %d"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:1024
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Nieznana zmienna: \"%s\""
+
+#: eval.c:1320
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Brak nawiasów: %s"
+
+#: eval.c:1435 eval.c:1449
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Nie istnieje zmienna: \"%s\""
+
+#: eval.c:1705
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Brak ':' po '?'"
+
+#: eval.c:2327
+msgid "E110: Missing ')'"
+msgstr "E110: Brak ')'"
+
+#: eval.c:2389
+msgid "E111: Missing ']'"
+msgstr "E111: Brak ']'"
+
+#: eval.c:2466
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Brak nazwy opcji: %s"
+
+#: eval.c:2484
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Nieznana opcja: %s"
+
+#: eval.c:2555
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Brak cudzys³owu: %s"
+
+#: eval.c:2698
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Brak cudzys³owu: %s"
+
+#: eval.c:3054
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Niew³aœciwe argumenty dla funkcji %s"
+
+#: eval.c:3083
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Nieznana funkcja: %s"
+
+#: eval.c:3084
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: Zbyt wiele argumentów dla funkcji: %s"
+
+#: eval.c:3085
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Za ma³o argumentów dla funkcji: %s"
+
+#: eval.c:3086
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: Zastosowano <SID> poza skryptem: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3687 gui.c:4376 gui_gtk.c:2059
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:4226
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld wierszy: "
+
+#: eval.c:5477
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&OK\n"
+"&Zakoñcz"
+
+#: eval.c:5517
+msgid "called inputrestore() more often than inputsave()"
+msgstr "wywo³ano inputrestore() wiêcej razy ni¿ inputsave()"
+
+#: eval.c:5977
+msgid "E655: Too many symbolic links (cycle?)"
+msgstr "E655: Za du¿o dowi¹zañ symbolicznych (pêtla?)"
+
+#: eval.c:6609
+msgid "E240: No connection to Vim server"
+msgstr "E240: Brak po³¹czenia z serwerem Vim"
+
+#: eval.c:6706
+msgid "E277: Unable to read a server reply"
+msgstr "E277: Nie mogê czytaæ odpowiedzi serwera"
+
+#: eval.c:6734
+msgid "E258: Unable to send to client"
+msgstr "E258: Nie mogê wys³aæ do klienta"
+
+#: eval.c:6782
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Nie mogê wys³aæ do %s"
+
+#: eval.c:6882
+msgid "(Invalid)"
+msgstr "(Niew³aœciwe)"
+
+#: eval.c:8060
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Nieokreœlona zmienna: %s"
+
+#: eval.c:8492
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E418: Niedozwolona nazwa zmiennej: %s"
+
+#: eval.c:8784
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: Funkcja %s ju¿ istnieje; aby j¹ zamieniæ u¿yj !"
+
+#: eval.c:8857
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Nieokreœlona funkcja: %s"
+
+#: eval.c:8870
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Brak '(': %s"
+
+#: eval.c:8903
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Niedozwolony argument: %s"
+
+#: eval.c:8982
+msgid "E126: Missing :endfunction"
+msgstr "E126: Brak :endfunction"
+
+#: eval.c:9089
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Nie mogê przedefiniowaæ funkcji %s: jest w u¿yciu"
+
+#: eval.c:9159
+msgid "E129: Function name required"
+msgstr "E129: Wymagana jest nazwa funkcji"
+
+#: eval.c:9210
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: Nazwa funkcji musi rozpoczynaæ siê du¿¹ liter¹: %s"
+
+#: eval.c:9402
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Nieokreœlona funkcja: %s"
+
+#: eval.c:9407
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Nie mogê skasowaæ funkcji %s: jest w u¿yciu"
+
+#: eval.c:9455
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: Zagnie¿d¿enie wywo³añ funkcji ponad 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:9508
+#, c-format
+msgid "calling %s"
+msgstr "wywo³ujê %s"
+
+#: eval.c:9570
+#, c-format
+msgid "%s aborted"
+msgstr "porzucono %s"
+
+#: eval.c:9572
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s zwraca #%ld"
+
+#: eval.c:9579
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s zwraca \"%s\""
+
+#. always scroll up, don't overwrite
+#: eval.c:9595 ex_cmds2.c:2365
+#, c-format
+msgid "continuing in %s"
+msgstr "kontynuacja w %s"
+
+#: eval.c:9621
+msgid "E133: :return not inside a function"
+msgstr "E133: :return poza funkcj¹"
+
+#: eval.c:9952
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# zmienne globalne:\n"
+
+#: ex_cmds2.c:92
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "Wchodzê w tryb odpluskwiania. WprowadŸ \"cont\" aby kontynuowaæ."
+
+#: ex_cmds2.c:96 ex_docmd.c:966
+#, c-format
+msgid "line %ld: %s"
+msgstr "wiersz %ld: %s"
+
+#: ex_cmds2.c:98
+#, c-format
+msgid "cmd: %s"
+msgstr "cmd: %s"
+
+#: ex_cmds2.c:290
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Punkt kontrolny w \"%s%s\" wiersz %ld"
+
+#: ex_cmds2.c:540
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Nie znaleziono punktu kontrolnego: %s"
+
+#: ex_cmds2.c:566
+msgid "No breakpoints defined"
+msgstr "Nie okreœlono ¿adnych punktów kontrolnych"
+
+#: ex_cmds2.c:571
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s wiersz %ld"
+
+#: ex_cmds2.c:763 ex_cmds.c:2097 ex_cmds.c:2362
+msgid "Save As"
+msgstr "Zapisz jako"
+
+#: ex_cmds2.c:786
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Zachowaj zmiany w \"%.*s\"?"
+
+#: ex_cmds2.c:788 ex_docmd.c:9380
+msgid "Untitled"
+msgstr "Bez Tytu³u"
+
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Nie zapisano zmian w buforze \"%s\""
+
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "OSTRZE¯ENIE: Nieoczekiwane wejœcie w inny bufor (sprawdŸ autokomendy)"
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: Tylko jeden plik w edycji"
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: Nie mo¿na przejœæ przed pierwszy plik"
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Nie mo¿na przejœæ za ostatni plik"
+
+#: ex_cmds2.c:1804
+#, c-format
+msgid "E666: compiler not supported: %s"
+msgstr "E666: nie wspierany kompilator: %s"
+
+#: ex_cmds2.c:1897
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Szukanie \"%s\" w \"%s\""
+
+#: ex_cmds2.c:1919
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Szukanie \"%s\""
+
+#: ex_cmds2.c:1940
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "nie znaleziono w 'runtimepath': \"%s\""
+
+#: ex_cmds2.c:1974
+msgid "Source Vim script"
+msgstr "Wczytaj skrypt Vima"
+
+#: ex_cmds2.c:2164
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "Nie mo¿na wczytaæ katalogu: \"%s\""
+
+#: ex_cmds2.c:2202
+#, c-format
+msgid "could not source \"%s\""
+msgstr "nie mog³em wczytaæ \"%s\""
+
+#: ex_cmds2.c:2204
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "wiersz: %ld nie mog³em wczytaæ \"%s\""
+
+#: ex_cmds2.c:2218
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "wczytywanie \"%s\""
+
+#: ex_cmds2.c:2220
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "wiersz %ld: wczytywanie \"%s\""
+
+#: ex_cmds2.c:2363
+#, c-format
+msgid "finished sourcing %s"
+msgstr "skoñczono wczytywanie %s"
+
+#: ex_cmds2.c:2707
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: OSTRZE¯ENIE: Niew³aœciwy separator wierszy, pewnie brak ^M"
+
+#: ex_cmds2.c:2756
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: u¿yto :scriptencoding poza wczytywanym plikiem"
+
+#: ex_cmds2.c:2789
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: u¿yto :finish poza wczytywanym plikiem"
+
+#: ex_cmds2.c:3238
+#, c-format
+msgid "Page %d"
+msgstr "Strona %d"
+
+#: ex_cmds2.c:3394
+msgid "No text to be printed"
+msgstr "Brak tekstu do drukowania"
+
+#: ex_cmds2.c:3472
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "Drukujê stronê %d (%d%%)"
+
+#: ex_cmds2.c:3484
+#, c-format
+msgid " Copy %d of %d"
+msgstr " Kopia %d z %d"
+
+#: ex_cmds2.c:3542
+#, c-format
+msgid "Printed: %s"
+msgstr "Wydrukowano: %s"
+
+#: ex_cmds2.c:3549
+msgid "Printing aborted"
+msgstr "Drukowanie odwo³ane"
+
+#: ex_cmds2.c:3914
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Nie mo¿na zapisaæ do wyjœciowego pliku PostScriptu"
+
+#: ex_cmds2.c:4189
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E624: Nie mogê otworzyæ pliku \"%s\""
+
+#: ex_cmds2.c:4199 ex_cmds2.c:4824
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Nie mo¿na odczytaæ pliku zasobów PostScriptu \"%s\""
+
+#: ex_cmds2.c:4207
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: plik \"%s\" nie jest plikiem zasobów PostScriptu"
+
+#: ex_cmds2.c:4222 ex_cmds2.c:4242 ex_cmds2.c:4257 ex_cmds2.c:4279
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: plik \"%s\" nie jest wspieranym plikiem zasobów PostScriptu"
+
+#: ex_cmds2.c:4309
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: \"%s\" nieprawid³owa wersja pliku zasobów"
+
+#: ex_cmds2.c:4776
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Nie mo¿na otworzyæ pliku PostScript do wyjœcia"
+
+#: ex_cmds2.c:4809
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Nie mogê otworzyæ pliku \"%s\""
+
+#: ex_cmds2.c:4928
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr "E456: Nie mo¿na znaleŸæ pliku zasobów PostScriptu \"prolog.ps\""
+
+#: ex_cmds2.c:4959
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: Nie mo¿na znaleŸæ pliku zasobów PostScriptu \"%s.ps\""
+
+#: ex_cmds2.c:4977
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr "E620: Nie mo¿na przekonwertowaæ z multi-byte do kodowania \"%s\""
+
+#: ex_cmds2.c:5102
+msgid "Sending to printer..."
+msgstr "Przesy³am do drukarki..."
+
+#: ex_cmds2.c:5106
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: Drukowanie pliku PostScript nie powiod³o siê"
+
+#: ex_cmds2.c:5108
+msgid "Print job sent."
+msgstr "Zadanie drukowanie przes³ane."
+
+#: ex_cmds2.c:5618
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Bie¿¹cy %sjêzyk: \"%s\""
+
+#: ex_cmds2.c:5629
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Nie mogê ustawiæ jêzyka na \"%s\""
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Hex %02x, Oktal %03o"
+
+#: ex_cmds.c:118
+#, c-format
+msgid "> %d, Hex %04x, Octal %o"
+msgstr "> %d, Hex %04x, Oktal %o"
+
+#: ex_cmds.c:119
+#, c-format
+msgid "> %d, Hex %08x, Octal %o"
+msgstr "> %d, Hex %08x, Oktal %o"
+
+#: ex_cmds.c:430
+msgid "E134: Move lines into themselves"
+msgstr "E134: Przeniesienie wierszy na siebie samych"
+
+#: ex_cmds.c:499
+msgid "1 line moved"
+msgstr "1 wiersz przeniesiony"
+
+#: ex_cmds.c:501
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld wiersze przeniesione"
+
+#: ex_cmds.c:924
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld wierszy przefiltrowanych"
+
+#: ex_cmds.c:952
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: Autokomendy *Filter* nie mog¹ zmieniaæ bie¿¹cego bufora"
+
+#: ex_cmds.c:1037
+msgid "[No write since last change]\n"
+msgstr "[Brak zapisu od czasu ostatniej zmiany]\n"
+
+#: ex_cmds.c:1283
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s w wierszu: "
+
+#: ex_cmds.c:1288
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: Zbyt wiele b³êdów; pomijam resztê pliku"
+
+#: ex_cmds.c:1323
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Wczytujê plik viminfo \"%s\"%s%s%s"
+
+#: ex_cmds.c:1324
+msgid " info"
+msgstr " informacja"
+
+#: ex_cmds.c:1325
+msgid " marks"
+msgstr " zak³adki"
+
+#: ex_cmds.c:1326
+msgid " FAILED"
+msgstr " NIE POWIOD£O SIÊ"
+
+#: ex_cmds.c:1418
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Plik viminfo jest niezapisywalny: %s"
+
+#: ex_cmds.c:1543
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Nie mogê zapisaæ pliku viminfo %s!"
+
+#: ex_cmds.c:1551
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Zapisujê plik viminfo \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1649
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Ten plik viminfo zosta³ wygenerowany przez Vima %s.\n"
+
+#: ex_cmds.c:1651
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Mo¿esz go ostro¿nie edytowaæ!\n"
+"\n"
+
+#: ex_cmds.c:1653
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# WartoϾ 'encoding' w czasie zapsu tego pliku\n"
+
+#: ex_cmds.c:1752
+msgid "Illegal starting char"
+msgstr "Niedopuszczalny pocz¹tkowy znak"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2140
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Plik jest za³adowany w innym buforze"
+
+#: ex_cmds.c:2174
+msgid "Write partial file?"
+msgstr "Zapisaæ czêœciowo plik?"
+
+#: ex_cmds.c:2181
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Stosuj ! do zapisania czêœciowo bufora"
+
+#: ex_cmds.c:2296
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Nadpisaæ istniej¹cy plik \"%.*s\"?"
+
+#: ex_cmds.c:2367
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: Brak nazwy pliku dla bufora %ld"
+
+#: ex_cmds.c:2405
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: Plik niezapisany: Zapis jest wy³¹czony opcj¹ 'write'"
+
+#: ex_cmds.c:2425
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"opcja 'readonly' nastawiona dla \"%.*s\".\n"
+"Czy chcesz go pomimo tego zapisaæ?"
+
+#: ex_cmds.c:2597
+msgid "Edit File"
+msgstr "Edytuj Plik"
+
+#: ex_cmds.c:3205
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Autokomendy nieoczekiwanie skasowa³y nowy bufor %s"
+
+#: ex_cmds.c:3339
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: nienumeryczny argument dla :z"
+
+#: ex_cmds.c:3424
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: Komendy pow³oki s¹ niedozwolone w rvim"
+
+#: ex_cmds.c:3531
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Wzorce regularne nie mog¹ byæ rozgraniczane literami"
+
+#: ex_cmds.c:3877
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "zamieñ na %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4266
+msgid "(Interrupted) "
+msgstr "(Przerwane) "
+
+#: ex_cmds.c:4270
+msgid "1 substitution"
+msgstr "1 podstawienie "
+
+#: ex_cmds.c:4272
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld podstawieñ"
+
+#: ex_cmds.c:4275
+msgid " on 1 line"
+msgstr " w 1 wierszu"
+
+#: ex_cmds.c:4277
+#, c-format
+msgid " on %ld lines"
+msgstr " w %ld wierszach"
+
+#: ex_cmds.c:4328
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: Nie mogê wykonaæ :global rekursywnie"
+
+#: ex_cmds.c:4363
+msgid "E148: Regular expression missing from global"
+msgstr "E148: Brak wzorca regularnego w :global"
+
+# c-format
+#: ex_cmds.c:4412
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Wzorzec znaleziono w ka¿dym wierszu: %s"
+
+#: ex_cmds.c:4493
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Ostatni podstawiany ci¹g:\n"
+"$"
+
+#: ex_cmds.c:4594 ex_docmd.c:2011
+msgid "E478: Don't panic!"
+msgstr "E478: Nie panikuj!"
+
+#: ex_cmds.c:4646
+#, c-format
+msgid "E661: Sorry, no '%s' help for %s"
+msgstr "E661: Przykro mi, brak '%s' pomocy dla %s"
+
+#: ex_cmds.c:4649
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Przykro mi, ale brak pomocy o %s"
+
+#: ex_cmds.c:4683
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Przykro mi, nie ma pliku pomocy \"%s\""
+
+#: ex_cmds.c:5166
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: Nie jest katalogiem: %s"
+
+#: ex_cmds.c:5305
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: Nie mogê otworzyæ %s do zapisu"
+
+#: ex_cmds.c:5341
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Nie mogê otworzyæ %s do odczytu"
+
+#: ex_cmds.c:5363
+#, c-format
+msgid "E670: Mix of help file encodings within a language: %s"
+msgstr "E670: Mieszanka kodowañ w pliku pomocy w ramach jêzyka: %s"
+
+#: ex_cmds.c:5441
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: Dwukrotny znacznik \"%s\" w pliku %s"
+
+#: ex_cmds.c:5553
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Nieznana komenda znaku: %s"
+
+#: ex_cmds.c:5573
+msgid "E156: Missing sign name"
+msgstr "E156: Brak nazwy znaku"
+
+#: ex_cmds.c:5619
+msgid "E612: Too many signs defined"
+msgstr "E255: Zbyt wiele nazw znaków"
+
+#: ex_cmds.c:5687
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Niew³aœciwy tekst znaku: %s"
+
+#: ex_cmds.c:5718 ex_cmds.c:5909
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Nieznany znak: %s"
+
+#: ex_cmds.c:5767
+msgid "E159: Missing sign number"
+msgstr "E159: Brak numeru znaku"
+
+#: ex_cmds.c:5849
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: Niew³aœciwa nazwa bufora: %s"
+
+#: ex_cmds.c:5888
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Niew³aœciwe ID znaku: %ld"
+
+#: ex_cmds.c:5958
+msgid " (NOT FOUND)"
+msgstr " (NIE ZNALEZIONO)"
+
+#: ex_cmds.c:5960
+msgid " (not supported)"
+msgstr "(nie wspomagane)"
+
+#: ex_cmds.c:6059
+msgid "[Deleted]"
+msgstr "[Skasowano]"
+
+#: ex_docmd.c:525
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Wchodzê w tryb Ex. WprowadŸ \"visual\" aby przejœæ do trybu Normal."
+
+#. must be at EOF
+#: ex_docmd.c:561
+msgid "E501: At end-of-file"
+msgstr "E501: Na koñcu pliku"
+
+#: ex_docmd.c:669
+msgid "E169: Command too recursive"
+msgstr "E169: Komenda zbyt rekursywna"
+
+#: ex_docmd.c:1229
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: Nie znaleziono wyj¹tku: %s"
+
+#: ex_docmd.c:1317
+msgid "End of sourced file"
+msgstr "Koniec wczytywanego pliku"
+
+#: ex_docmd.c:1318
+msgid "End of function"
+msgstr "Koniec funkcji"
+
+#: ex_docmd.c:1907
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: Niejednoznaczne zastosowanie komendy zdefiniowanej przez u¿ytkownika"
+
+#: ex_docmd.c:1921
+msgid "E492: Not an editor command"
+msgstr "E492: Nie jest komend¹ edytora"
+
+#: ex_docmd.c:2030
+msgid "E493: Backwards range given"
+msgstr "E493: Dano wsteczny zakres"
+
+#: ex_docmd.c:2039
+msgid "Backwards range given, OK to swap"
+msgstr "Dano wsteczny zakres; zamiana jest mo¿liwa"
+
+#: ex_docmd.c:2162
+msgid "E494: Use w or w>>"
+msgstr "E494: Stosuj w lub w>>"
+
+#: ex_docmd.c:3788
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Przykro mi, ale ta komenda nie jest dostêpna w tej wersji"
+
+#: ex_docmd.c:3991
+msgid "E172: Only one file name allowed"
+msgstr "E172: Tylko pojedyncza nazwa pliku dozwolona"
+
+#: ex_docmd.c:4571
+msgid "1 more file to edit. Quit anyway?"
+msgstr "1 wiêcej plik do edycji. Mimo to wyjœæ?"
+
+#: ex_docmd.c:4574
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "jeszcze %d plików do edycji. Mimo to wyjœæ?"
+
+#: ex_docmd.c:4581
+msgid "E173: 1 more file to edit"
+msgstr "E173: 1 wiêcej plik do edycji"
+
+#: ex_docmd.c:4583
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: jeszcze %ld plików do edycji"
+
+#: ex_docmd.c:4678
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: Komenda ju¿ istnieje; aby j¹ przedefiniowaæ stosuj !"
+
+#: ex_docmd.c:4789
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Nazwa Arg. Zak. GotowoϾ Definicja"
+
+#: ex_docmd.c:4878
+msgid "No user-defined commands found"
+msgstr "Nie znaleziono komend zdefiniowanych przez u¿ytkownika"
+
+#: ex_docmd.c:4910
+msgid "E175: No attribute specified"
+msgstr "E175: Nie okreœlono atrybutu"
+
+#: ex_docmd.c:4962
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Niew³aœciwa iloœæ argumentów"
+
+#: ex_docmd.c:4977
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: Mno¿nik nie mo¿e byæ podany dwukrotnie"
+
+#: ex_docmd.c:4987
+msgid "E178: Invalid default value for count"
+msgstr "E178: Niew³aœciwa domyœlna wartoœæ mno¿nika"
+
+#: ex_docmd.c:5018
+msgid "E179: argument required for complete"
+msgstr "E179: argument wymagany do dope³niania"
+
+#: ex_docmd.c:5050
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Niew³aœciwa wartoœæ dope³niania: %s"
+
+#: ex_docmd.c:5059
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr "E468: Argument depe³niania dozwolony wy³¹cznie dla dope³niania u¿ytkownika"
+
+#: ex_docmd.c:5065
+msgid "E467: Custom completion requires a function argument"
+msgstr "E467: Dope³nianie u¿ytkownika wymaga funkcji jako argumentu"
+
+#: ex_docmd.c:5076
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Niew³aœciwy atrybut: %s"
+
+#: ex_docmd.c:5119
+msgid "E182: Invalid command name"
+msgstr "E182: Niew³aœciwa nazwa komendy"
+
+#: ex_docmd.c:5134
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr ""
+"E183: Komendy zdefiniowane przez u¿ytkownika musz¹ rozpoczynaæ siê du¿¹ "
+"liter¹"
+
+#: ex_docmd.c:5205
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: Nie ma takiej komendy u¿ytkownika: %s"
+
+#: ex_docmd.c:5666
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Nie mogê znaleŸæ zestawu kolorów %s"
+
+#: ex_docmd.c:5674
+msgid "Greetings, Vim user!"
+msgstr "Witaj u¿ytkowniku Vima!"
+
+#: ex_docmd.c:6391
+msgid "Edit File in new window"
+msgstr "Edytuj plik w nowym oknie"
+
+#: ex_docmd.c:6686
+msgid "No swap file"
+msgstr "Brak pliku wymiany"
+
+#: ex_docmd.c:6790
+msgid "Append File"
+msgstr "Do³¹cz plik"
+
+#: ex_docmd.c:6854
+msgid "E186: No previous directory"
+msgstr "E186: Nie ma poprzedniego katalogu"
+
+#: ex_docmd.c:6936
+msgid "E187: Unknown"
+msgstr "E187: Nieznany"
+
+#: ex_docmd.c:7021
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: :winsize wymaga dwóch argumentów numerycznych"
+
+#: ex_docmd.c:7077
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Pozycja okna: X %d, Y %d"
+
+#: ex_docmd.c:7082
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: Pozyskiwanie pozycji okna nie jest zaimplementowane dla tego systemu"
+
+#: ex_docmd.c:7092
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: :winpos wymaga dwóch argumentów numerycznych"
+
+#: ex_docmd.c:7370
+msgid "Save Redirection"
+msgstr "Zapisz przekierowanie"
+
+#: ex_docmd.c:7560
+msgid "Save View"
+msgstr "Zapisz widok"
+
+#: ex_docmd.c:7561
+msgid "Save Session"
+msgstr "Zapisz sesjê"
+
+#: ex_docmd.c:7563
+msgid "Save Setup"
+msgstr "Zapisz ustawienia"
+
+#: ex_docmd.c:7715
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" istnieje (wymuœ poprzez !)"
+
+#: ex_docmd.c:7720
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: Nie mogê otworzyæ \"%s\" do zapisu"
+
+#. set mark
+#: ex_docmd.c:7744
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: Argument musi byæ liter¹ albo cudzys³owem w przód/ty³"
+
+#: ex_docmd.c:7786
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Rekursywne zastosowanie :normal za g³êbokie"
+
+#: ex_docmd.c:8304
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: Brak nazwy zamiennego pliku do podstawienia pod '#'"
+
+#: ex_docmd.c:8335
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: brak nazwy pliku autokomend do podstawienia pod \"<afile>\""
+
+#: ex_docmd.c:8343
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "E496: brak numeru bufora autokomend do podstawienia pod \"<abuf>\""
+
+#: ex_docmd.c:8354
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr "E497: brak nazwy dopasowania autokomend pod \"<amatch>\""
+
+#: ex_docmd.c:8364
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr "E498: brak nazwy pliku :source do postawienia pod \"<sfile>\""
+
+#: ex_docmd.c:8405
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: Pusta nazwa pliku dla '%' lub '#', dzia³a tylko z \":p:h\""
+
+#: ex_docmd.c:8407
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: Wynikiem jest pusty ci¹g"
+
+#: ex_docmd.c:9362
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: Nie mogê otworzyæ pliku viminfo do odczytu"
+
+#: ex_docmd.c:9535
+msgid "E196: No digraphs in this version"
+msgstr "E196: Brak dwugrafów w tej wersji"
+
+#: ex_eval.c:440
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr "E608: Nie mo¿na ':throw' wyj¹tków z prefiksem 'Vim'"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:529
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "Wyj¹tek: %s"
+
+#: ex_eval.c:576
+#, c-format
+msgid "Exception finished: %s"
+msgstr "Wyj¹tek zakoñczony: %s"
+
+#: ex_eval.c:577
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "Wyj¹tek odrzucony: %s"
+
+#: ex_eval.c:620 ex_eval.c:664
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, wiersz %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:638
+#, c-format
+msgid "Exception caught: %s"
+msgstr "Wyj¹tek przechwycony: %s"
+
+#: ex_eval.c:713
+#, c-format
+msgid "%s made pending"
+msgstr "%s zosta³ zawieszony"
+
+#: ex_eval.c:716
+#, c-format
+msgid "%s resumed"
+msgstr "%s przywrócony"
+
+#: ex_eval.c:720
+#, c-format
+msgid "%s discarded"
+msgstr "%s odrzucony"
+
+#: ex_eval.c:746
+msgid "Exception"
+msgstr "Wyj¹tek"
+
+#: ex_eval.c:752
+msgid "Error and interrupt"
+msgstr "B³¹d i przerwanie"
+
+#: ex_eval.c:754 gui.c:4375
+msgid "Error"
+msgstr "B³¹d"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:756
+msgid "Interrupt"
+msgstr "Przerwanie"
+
+#: ex_eval.c:830
+msgid "E579: :if nesting too deep"
+msgstr "E579: zbyt g³êbokie zagnie¿d¿enie :if"
+
+#: ex_eval.c:867
+msgid "E580: :endif without :if"
+msgstr "E580: :endif bez :if"
+
+#: ex_eval.c:911
+msgid "E581: :else without :if"
+msgstr "E581: :else bez :if"
+
+#: ex_eval.c:914
+msgid "E582: :elseif without :if"
+msgstr "E582: :elseif bez :if"
+
+#: ex_eval.c:921
+msgid "E583: multiple :else"
+msgstr "E583: wielokrotne :else"
+
+#: ex_eval.c:924
+msgid "E584: :elseif after :else"
+msgstr "E584: :elseif po :else"
+
+#: ex_eval.c:991
+msgid "E585: :while nesting too deep"
+msgstr "E585: zbyt g³êbokie zagnie¿d¿enie :while"
+
+#: ex_eval.c:1047
+msgid "E586: :continue without :while"
+msgstr "E586: :continue bez :while"
+
+#: ex_eval.c:1087
+msgid "E587: :break without :while"
+msgstr "E587: :break bez :while"
+
+#: ex_eval.c:1286
+msgid "E601: :try nesting too deep"
+msgstr "E601: zbyt g³êbokie zagnie¿d¿enie :try"
+
+#: ex_eval.c:1366
+msgid "E603: :catch without :try"
+msgstr "E603: :catch bez :try"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1388
+msgid "E604: :catch after :finally"
+msgstr "E604: :catch za :finally"
+
+#: ex_eval.c:1521
+msgid "E606: :finally without :try"
+msgstr "E606: :finally bez :try"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1545
+msgid "E607: multiple :finally"
+msgstr "E607: wielokrotne :finally"
+
+#: ex_eval.c:1654
+msgid "E602: :endtry without :try"
+msgstr "E602: :endtry bez :try"
+
+#: ex_eval.c:1986
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction poza funkcj¹"
+
+#: ex_getln.c:3296
+msgid "tagname"
+msgstr "nazwa znacznika"
+
+#: ex_getln.c:3299
+msgid " kind file\n"
+msgstr " pokrewny plik\n"
+
+#: ex_getln.c:4752
+msgid "'history' option is zero"
+msgstr "opcja 'history' jest zerowa"
+
+#: ex_getln.c:5023
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s Historia (od najnowszych po najstarsze):\n"
+
+#: ex_getln.c:5024
+msgid "Command Line"
+msgstr "Wiersz poleceñ"
+
+#: ex_getln.c:5025
+msgid "Search String"
+msgstr "Szukany ci¹g"
+
+#: ex_getln.c:5026
+msgid "Expression"
+msgstr "Wyra¿enie"
+
+#: ex_getln.c:5027
+msgid "Input Line"
+msgstr "Wiersz wprowadzeñ"
+
+#: ex_getln.c:5065
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar przekracza d³ugoœæ polecenia"
+
+#: ex_getln.c:5242
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Aktywny widok lub bufor skasowany"
+
+#: fileio.c:377
+msgid "Illegal file name"
+msgstr "Niedopuszczalna nazwa pliku"
+
+#: fileio.c:401 fileio.c:535 fileio.c:2913 fileio.c:2954
+msgid "is a directory"
+msgstr "jest katalogiem"
+
+#: fileio.c:403
+msgid "is not a file"
+msgstr "nie jest plikiem"
+
+#: fileio.c:557 fileio.c:4131
+msgid "[New File]"
+msgstr "[Nowy Plik]"
+
+#: fileio.c:590
+msgid "[Permission Denied]"
+msgstr "[Nie dozwolono]"
+
+#: fileio.c:694
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: Autokomendy *ReadPre zrobi³y plik nieodczytywalnym"
+
+#: fileio.c:696
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: Autokomendy *ReadPre nie mog¹ zmieniaæ bie¿¹cego bufora"
+
+#: fileio.c:717
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: Wczytywanie ze stdin...\n"
+
+#: fileio.c:723
+msgid "Reading from stdin..."
+msgstr "Wczytywanie ze stdin..."
+
+#. Re-opening the original file failed!
+#: fileio.c:1000
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: Plik stworzony poprzez przemianê jest nieodczytywalny!"
+
+#: fileio.c:2090
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:2097
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:2104
+msgid "[socket]"
+msgstr "[socket]"
+
+#: fileio.c:2112
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:2122
+msgid "[CR missing]"
+msgstr "[brak CR]'"
+
+#: fileio.c:2127
+msgid "[NL found]"
+msgstr "[znaleziono NL]"
+
+#: fileio.c:2132
+msgid "[long lines split]"
+msgstr "[d³ugie wiersze rozdzielane]"
+
+#: fileio.c:2138 fileio.c:4115
+msgid "[NOT converted]"
+msgstr "[NIE przemienione]"
+
+#: fileio.c:2143 fileio.c:4120
+msgid "[converted]"
+msgstr "[przemienione]"
+
+#: fileio.c:2150 fileio.c:4145
+msgid "[crypted]"
+msgstr "[zakodowane]"
+
+#: fileio.c:2157
+msgid "[CONVERSION ERROR]"
+msgstr "[B£¥D W PRZEMIANIE]"
+
+#: fileio.c:2163
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[NIEDOZWOLONY BAJT w wierszu %ld]"
+
+#: fileio.c:2170
+msgid "[READ ERRORS]"
+msgstr "[B£ÊDY W ODCZYCIE]"
+
+#: fileio.c:2386
+msgid "Can't find temp file for conversion"
+msgstr "Nie mogê znaleŸæ pliku tymczasowego w celu przemiany"
+
+#: fileio.c:2393
+msgid "Conversion with 'charconvert' failed"
+msgstr "Nieudana przemiana z 'charconvert'"
+
+#: fileio.c:2396
+msgid "can't read output of 'charconvert'"
+msgstr "nie mogê odczytaæ wyjœcia z 'charconvert'"
+
+#: fileio.c:2796
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Autokomendy skasowa³y lub wy³adowa³y bufor przeznaczony do zapisu"
+
+#: fileio.c:2819
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Autokomenda zmieni³a liczbê wierszy w nieoczekiwany sposób"
+
+#: fileio.c:2857
+msgid "NetBeans dissallows writes of unmodified buffers"
+msgstr "NetBeans nie pozwala na zapis niezmodyfikowanych buforów"
+
+#: fileio.c:2865
+msgid "Partial writes disallowed for NetBeans buffers"
+msgstr "Czêœciowy zapis niemo¿liwy dla buforów NetBeans"
+
+#: fileio.c:2919 fileio.c:2937
+msgid "is not a file or writable device"
+msgstr "nie jest plikiem lub zapisywalnym przyrz¹dem"
+
+#: fileio.c:2989
+msgid "is read-only (add ! to override)"
+msgstr "jest tylko do odczytu (wymuœ poprzez !)"
+
+#: fileio.c:3335
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: Nie mogê zapisaæ do pliku zabezpieczenia (wymuœ przez !)"
+
+#: fileio.c:3347
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr "E507: B³¹d podczas zamykania pliku zabezpieczenia (wymuœ przez !)"
+
+#: fileio.c:3349
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr "E508: Nie mogê odczytaæ pliku w celu zabezpieczenia (wymuœ przez !)"
+
+#: fileio.c:3365
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: Nie mogê stworzyæ pliku zabezpieczenia (wymuœ przez !)"
+
+#: fileio.c:3468
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: Nie mogê zrobiæ pliku zabezpieczenia (wymuœ przez !)"
+
+#: fileio.c:3530
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr "E460: Rozdzia³ zasobów zostanie utracony (wymuœ przez !)"
+
+#: fileio.c:3640
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: Nie mogê znaleŸæ pliku tymczasowego do zapisania"
+
+#: fileio.c:3658
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr "E213: Nie mogê przemieniæ (u¿yj ! by zapisaæ bez przemiany)"
+
+#: fileio.c:3693
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Nie mogê otworzyæ pod³¹czonego pliku do zapisu"
+
+#: fileio.c:3697
+msgid "E212: Can't open file for writing"
+msgstr "E212: Nie mogê otworzyæ pliku do zapisu"
+
+#: fileio.c:3959
+msgid "E667: Fsync failed"
+msgstr "E667: Fsync nie powiód³ siê"
+
+#: fileio.c:3966
+msgid "E512: Close failed"
+msgstr "E512: Zamkniêcie siê nie powiod³o"
+
+#: fileio.c:4037
+msgid "E513: write error, conversion failed"
+msgstr "E513: b³¹d w zapisie, przemiana siê nie powiod³a"
+
+#: fileio.c:4043
+msgid "E514: write error (file system full?)"
+msgstr "E514: b³¹d w zapisie (mo¿e system plików jest przepe³niony?)"
+
+#: fileio.c:4110
+msgid " CONVERSION ERROR"
+msgstr " B£¥D W PRZEMIANIE"
+
+#: fileio.c:4126
+msgid "[Device]"
+msgstr "[Urz¹dzenie]"
+
+#: fileio.c:4131
+msgid "[New]"
+msgstr "[Nowy]"
+
+#: fileio.c:4153
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:4153
+msgid " appended"
+msgstr " do³¹czono"
+
+#: fileio.c:4155
+msgid " [w]"
+msgstr " [w]"
+
+#: fileio.c:4155
+msgid " written"
+msgstr " zapisano"
+
+#: fileio.c:4205
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: Patchmode: nie mogê zapisaæ oryginalnego pliku"
+
+#: fileio.c:4227
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: nie mogê stworzyæ pustego oryginalnego pliku"
+
+#: fileio.c:4242
+msgid "E207: Can't delete backup file"
+msgstr "E207: Nie mogê skasowaæ pliku zabezpieczenia"
+
+#: fileio.c:4306
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"OSTRZE¯ENIE: Oryginalny plik mo¿e zostaæ utracony lub uszkodzony\n"
+
+#: fileio.c:4308
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "nie wychodŸ edytora, dopóki plik nie zosta³ poprawnie zapisany!"
+
+#: fileio.c:4397
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:4397
+msgid "[dos format]"
+msgstr "[format dos-a]"
+
+#: fileio.c:4404
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:4404
+msgid "[mac format]"
+msgstr "[format mac-a]"
+
+#: fileio.c:4411
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:4411
+msgid "[unix format]"
+msgstr "[format unix-a]"
+
+#: fileio.c:4438
+msgid "1 line, "
+msgstr "1 wiersz, "
+
+#: fileio.c:4440
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld wierszy, "
+
+#: fileio.c:4443
+msgid "1 character"
+msgstr "1 znak"
+
+#: fileio.c:4445
+#, c-format
+msgid "%ld characters"
+msgstr "%ld znaków"
+
+#: fileio.c:4455
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:4455
+msgid "[Incomplete last line]"
+msgstr "[Niekompletny ostatni wiersz]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4474
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "OSTRZE¯ENIE: Plik zmieni³ siê od czasu ostatniego odczytu!!!"
+
+#: fileio.c:4476
+msgid "Do you really want to write to it"
+msgstr "Czy naprawdê chcesz go zapisaæ"
+
+#: fileio.c:5726
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: B³¹d zapisywania do \"%s\""
+
+#: fileio.c:5733
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: B³¹d w trakcie zamykania \"%s\""
+
+#: fileio.c:5736
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: B³¹d odczytu \"%s\""
+
+#: fileio.c:5970
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: Autokomenda FileChangedShell skasowa³a bufor"
+
+#: fileio.c:5977
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: OSTRZE¯ENIE: Plik \"%s\" nie jest d³u¿ej dostêpny"
+
+#: fileio.c:5991
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: OSTRZE¯ENIE: Plik \"%s\" zmieni³ siê od czasu rozpoczêcia edycji, bufor "
+"w Vimie równie¿ zosta³ zmieniony"
+
+#: fileio.c:5994
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: OSTRZE¯ENIE: Plik \"%s\" zmieni³ siê od czasu rozpoczêcia edycji"
+
+#: fileio.c:5996
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: OSTRZE¯ENIE: Tryb pliku \"%s\" zmieni³ siê od czasu rozpoczêcia edycji"
+
+#: fileio.c:6006
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: OSTRZE¯ENIE: Plik \"%s\" zosta³ stworzony po rozpoczêciu edycji"
+
+#: fileio.c:6019
+msgid "See \":help W11\" for more info."
+msgstr "Patrz \":help W11\" dla dalszych informacji."
+
+#: fileio.c:6033
+msgid "Warning"
+msgstr "OSTRZE¯ENIE"
+
+#: fileio.c:6034
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Za³aduj Plik"
+
+#: fileio.c:6140
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: Nie mo¿na przygotowaæ prze³adowania \"%s\""
+
+#: fileio.c:6159
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: Nie mo¿na prze³adowaæ \"%s\""
+
+#: fileio.c:6740
+msgid "--Deleted--"
+msgstr "--Skasowano--"
+
+#. the group doesn't exist
+#: fileio.c:6900
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Nie ma takiej grupy: \"%s\""
+
+#: fileio.c:7026
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Niedopuszczalny znak po *: %s"
+
+#: fileio.c:7038
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Nie ma takiego wydarzenia: %s"
+
+#: fileio.c:7040
+#, c-format
+msgid "E216: No such group or event: %s"
+msgstr "E216: Nie ma takiej grupy lub wydarzenia: %s"
+
+#. Highlight title
+#: fileio.c:7198
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Autokomendy ---"
+
+#: fileio.c:7469
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Nie mo¿na wykonywaæ autokomend dla wydarzeñ ALL"
+
+#: fileio.c:7492
+msgid "No matching autocommands"
+msgstr "Brak pasuj¹cych autokomend"
+
+#: fileio.c:7813
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: zbyt g³êbokie zagnie¿d¿enie autokomend"
+
+#: fileio.c:8088
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Autokomend dla \"%s\""
+
+#: fileio.c:8096
+#, c-format
+msgid "Executing %s"
+msgstr "Wykonujê %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:8164
+#, c-format
+msgid "autocommand %s"
+msgstr "autokomenda %s"
+
+#: fileio.c:8731
+msgid "E219: Missing {."
+msgstr "E219: Brak {."
+
+#: fileio.c:8733
+msgid "E220: Missing }."
+msgstr "E220: Brak }."
+
+#: fold.c:68
+msgid "E490: No fold found"
+msgstr "E490: Nie znaleziono zwiniêcia"
+
+#: fold.c:593
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: Nie mo¿na utworzyæ zwiniêcia przy bie¿¹cej 'foldmethod'"
+
+#: fold.c:595
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: Nie mo¿na skasowaæ zwiniêcia przy bie¿¹cej 'foldmethod'"
+
+#: getchar.c:248
+msgid "E222: Add to read buffer"
+msgstr "E222: Dodaj do bufora odczytu"
+
+#: getchar.c:2198
+msgid "E223: recursive mapping"
+msgstr "E223: rekursywne przyporz¹dkowanie"
+
+#: getchar.c:3077
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: istnieje ju¿ globalny skrót dla %s"
+
+#: getchar.c:3080
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: istnieje ju¿ globalne przyporz¹dkowanie dla %s"
+
+#: getchar.c:3212
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: istnieje ju¿ skrót dla %s"
+
+#: getchar.c:3215
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: istnieje ju¿ przyporz¹dkowanie dla %s"
+
+#: getchar.c:3279
+msgid "No abbreviation found"
+msgstr "Nie znaleziono skrótu"
+
+#: getchar.c:3281
+msgid "No mapping found"
+msgstr "Nie znaleziono przyporz¹dkowania"
+
+#: getchar.c:4173
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: Niedopuszczalny tryb"
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<nie mogê otworzyæ> "
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: nie mogê otrzymaæ czcionki %s"
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: nie mogê powróciæ do bie¿¹cego katalogu"
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "Trop:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: nie mogê otrzymaæ bie¿¹cego katalogu"
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "OK"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2731 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "Zakoñcz"
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "VIM - Dialog"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Scrollbar Widget: Nie mog³em otrzymaæ rozmiarów rysunku na przycisku."
+
+#: gui_beval.c:101 gui_w32.c:3830
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: Nie mogê stworzyæ BalloonEval z powiadomieniem i wywo³aniem"
+
+#: gui.c:220
+msgid "E229: Cannot start the GUI"
+msgstr "E229: Nie mogê odpaliæ GUI"
+
+#: gui.c:349
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Nie mogê czytaæ z \"%s\""
+
+#: gui.c:472
+msgid "E665: Cannot start GUI, no valid font found"
+msgstr "E665: Nie mo¿na uruchomiæ GUI, brak prawid³owej czcionki"
+
+#: gui.c:477
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: Niew³aœciwe 'guifontwide'"
+
+#: gui.c:547
+msgid "E599: Value of 'imactivatekey' is invalid"
+msgstr "E599: Nieprawid³owa wartoœæ 'imactivatekey'"
+
+#: gui.c:4061
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: Nie mogê zarezerwowaæ koloru %s"
+
+#: gui_gtk.c:1607
+msgid "Vim dialog..."
+msgstr "Dialog Vima..."
+
+#: gui_gtk.c:2060 message.c:2993
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Tak\n"
+"&Nie\n"
+"&Zakoñcz"
+
+#: gui_gtk.c:2268
+msgid "Input _Methods"
+msgstr "Input _Methods"
+
+#: gui_gtk.c:2534 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Szukaj i Zamieniaj..."
+
+#: gui_gtk.c:2542 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "VIM - Szukaj..."
+
+#: gui_gtk.c:2574 gui_motif.c:2888
+msgid "Find what:"
+msgstr "ZnajdŸ:"
+
+#: gui_gtk.c:2592 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "Zamieñ na:"
+
+#. whole word only button
+#: gui_gtk.c:2624 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "Dopasuj tylko ca³e wyrazy"
+
+#. match case button
+#: gui_gtk.c:2635 gui_motif.c:3048
+msgid "Match case"
+msgstr "Dopasuj wielkoϾ liter"
+
+#: gui_gtk.c:2645 gui_motif.c:2990
+msgid "Direction"
+msgstr "Kierunek"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2657 gui_motif.c:3002
+msgid "Up"
+msgstr "W górê"
+
+#: gui_gtk.c:2661 gui_motif.c:3010
+msgid "Down"
+msgstr "W dó³"
+
+#: gui_gtk.c:2683 gui_gtk.c:2685 gui_motif.c:2792
+msgid "Find Next"
+msgstr "ZnajdŸ nastêpne"
+
+#: gui_gtk.c:2702 gui_gtk.c:2704 gui_motif.c:2809
+msgid "Replace"
+msgstr "Zamieñ"
+
+#: gui_gtk.c:2715 gui_gtk.c:2717 gui_motif.c:2822
+msgid "Replace All"
+msgstr "Zamieñ wszystkie"
+
+#: gui_gtk_x11.c:2327
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: otrzymano ¿¹danie \"die\" od manad¿era sesji\n"
+
+#: gui_gtk_x11.c:3519
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: G³ówne okno nieoczekiwanie zniszczone\n"
+
+#: gui_gtk_x11.c:4138
+msgid "Font Selection"
+msgstr "Wybór czcionki"
+
+#: gui_gtk_x11.c:6035 ui.c:2117
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "U¿ywam CUT_BUFFER0 zamiast pustego wyboru"
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "Filtr"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "Katalogi"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "Pomoc"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "Pliki"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "Wybór"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "Cofnij"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: Nie mogê za³adowaæ czcionki Zap '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: Nie mogê u¿yæ czcionki %s"
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Wysy³am zawiadomienie koñcz¹ce proces pochodny.\n"
+
+#: gui_w32.c:830
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Argument nie jest wspomagany: \"-%s\"; U¿ywaj wersji OLE."
+
+#: gui_w48.c:2090
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "ZnajdŸ ci¹g (u¿yj '\\\\' do szukania '\\')"
+
+#: gui_w48.c:2115
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Szukanie i Zamiana (u¿yj '\\\\' do szukania '\\')"
+
+#: gui_x11.c:1537
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: Nie mogê zarezerwowaæ mapy kolorów, pewne kolory mog¹ byæ "
+"nieprawid³owe"
+
+#: gui_x11.c:2118
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: Brak czcionek dla nastêpuj¹cych zestawów znaków w zestawie czcionek %s:"
+
+#: gui_x11.c:2161
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Nazwa zestawu czcionek: %s"
+
+#: gui_x11.c:2162
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "Czcionka '%s' nie posiada znaków jednolitej szerokoœci"
+
+#: gui_x11.c:2181
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Nazwa zestawu czcionek: %s\n"
+
+#: gui_x11.c:2182
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Font0: %s\n"
+
+#: gui_x11.c:2183
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Font1: %s\n"
+
+#: gui_x11.c:2184
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "szerokoœæ font%d nie jest podwójn¹ szerokoœci¹ font0\n"
+
+#: gui_x11.c:2185
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "SzerokoϾ font0: %ld\n"
+
+#: gui_x11.c:2186
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"SzerokoϾ font1: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: B£¥D w automacie Hangul"
+
+#: if_cscope.c:77
+msgid "Add a new database"
+msgstr "Dodaj now¹ bazê danych"
+
+#: if_cscope.c:79
+msgid "Query for a pattern"
+msgstr "Zapytane o wzorzec"
+
+#: if_cscope.c:81
+msgid "Show this message"
+msgstr "Poka¿ ten komunikat"
+
+#: if_cscope.c:83
+msgid "Kill a connection"
+msgstr "Zabij po³¹czenie"
+
+#: if_cscope.c:85
+msgid "Reinit all connections"
+msgstr "Ponów wszelkie po³¹czenia"
+
+#: if_cscope.c:87
+msgid "Show connections"
+msgstr "Poka¿ po³¹czenia"
+
+#: if_cscope.c:95
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: Zastosowanie: cs[cope] %s"
+
+#: if_cscope.c:124
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Ta komenda cscope nie wspomaga podzielenia okna.\n"
+
+#: if_cscope.c:175
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: Zastosowanie: cstag <ident>"
+
+#: if_cscope.c:231
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: nie znaleziono znacznika"
+
+#: if_cscope.c:409
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: stat(%s) b³¹d: %d"
+
+#: if_cscope.c:419
+msgid "E563: stat error"
+msgstr "E563: b³¹d stat"
+
+#: if_cscope.c:516
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s nie jest katalogiem lub poprawn¹ baz¹ danych cscope"
+
+#: if_cscope.c:534
+#, c-format
+msgid "Added cscope database %s"
+msgstr "Dodano bazê danych cscope %s"
+
+#: if_cscope.c:589
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: b³¹d odczytu po³¹czenia z cscope %ld"
+
+#: if_cscope.c:694
+msgid "E561: unknown cscope search type"
+msgstr "E561: nieznany typ szukania cscope"
+
+#: if_cscope.c:736
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: Nie mog³em stworzyæ potoku do cscope"
+
+#: if_cscope.c:753
+msgid "E622: Could not fork for cscope"
+msgstr "E622: Nie mog³em utworzyæ rozwidlenia dla cscope"
+
+#: if_cscope.c:847 if_cscope.c:897
+msgid "cs_create_connection exec failed"
+msgstr "wykonanie cs_create_connection nie powiod³o siê"
+
+#: if_cscope.c:898
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: Nie mog³em stworzyæ procesu cscope"
+
+#: if_cscope.c:911
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen dla to_fp nie powiod³o siê"
+
+#: if_cscope.c:913
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen dla fr_fp nie powiod³o siê"
+
+#: if_cscope.c:951
+msgid "E567: no cscope connections"
+msgstr "E567: brak po³¹czenia z cscope"
+
+#: if_cscope.c:1025
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: brak dopasowañ dla zapytania cscope %s o %s"
+
+#: if_cscope.c:1082
+#, c-format
+msgid "E469: invalid cscopequickfix flag %c for %c"
+msgstr "E469: nieprawid³owa flaga cscopequickfix %c dla %c"
+
+#: if_cscope.c:1152
+msgid "cscope commands:\n"
+msgstr "komendy cscope:\n"
+
+#: if_cscope.c:1155
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (U¿ycie: %s)"
+
+#: if_cscope.c:1253
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: nie mogê otworzyæ bazy danych cscope: %s"
+
+#: if_cscope.c:1271
+msgid "E626: cannot get cscope database information"
+msgstr "E626: nie mogê uzyskaæ informacji z bazy danych cscope"
+
+#: if_cscope.c:1296
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: nie dodano duplikatu bazy danych cscope"
+
+#: if_cscope.c:1307
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: wyczerpano maksymaln¹ liczbê po³¹czeñ cscope"
+
+#: if_cscope.c:1424
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: nie ma po³¹czenia %s z cscope"
+
+#: if_cscope.c:1458
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "po³¹czenie %s z cscope zosta³o zamkniête"
+
+#. should not reach here
+#: if_cscope.c:1598
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: b³¹d krytyczny w cs_manage_matches"
+
+#: if_cscope.c:1848
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "Znacznik cscope: %s"
+
+#: if_cscope.c:1870
+msgid ""
+"\n"
+" # line"
+msgstr ""
+"\n"
+" # wiersz"
+
+#: if_cscope.c:1872
+msgid "filename / context / line\n"
+msgstr "nazwa pliku / kontekst / wiersz\n"
+
+#: if_cscope.c:1990
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: B³¹d cscope: %s"
+
+#: if_cscope.c:2176
+msgid "All cscope databases reset"
+msgstr "Wszystkie bazy danych cscope prze³adowano"
+
+#: if_cscope.c:2244
+msgid "no cscope connections\n"
+msgstr "brak po³¹czeñ z cscope\n"
+
+#: if_cscope.c:2248
+msgid " # pid database name prepend path\n"
+msgstr " # pid nazwa bazy danych przedsionek tropu\n"
+
+#: if_python.c:436
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: Przykro mi, ta komenda jest wy³¹czona, bo nie mo¿na za³adowaæ "
+"biblioteki Pythona"
+
+#: if_python.c:500
+msgid "E659: Cannot invoke Python recursively"
+msgstr "E659: Nie mo¿na wywo³aæ Pythona rekursywnie"
+
+#: if_python.c:701
+msgid "can't delete OutputObject attributes"
+msgstr "nie mogê skasowaæ atrybutów OutputObject"
+
+#: if_python.c:708
+msgid "softspace must be an integer"
+msgstr "softspace musi byæ liczb¹ ca³kowit¹"
+
+#: if_python.c:716
+msgid "invalid attribute"
+msgstr "niepoprawny atrybut"
+
+#: if_python.c:755 if_python.c:769
+msgid "writelines() requires list of strings"
+msgstr "writelines() wymaga listy ci¹gów"
+
+#: if_python.c:895
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: B³¹d w inicjalizacji obiektów I/O"
+
+#: if_python.c:1080 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "niepoprawne wyra¿enie"
+
+#: if_python.c:1094 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "wyra¿enia wy³¹czone podczas kompilacji"
+
+#: if_python.c:1107
+msgid "attempt to refer to deleted buffer"
+msgstr "próba odniesienia do skasowanego bufora"
+
+#: if_python.c:1122 if_python.c:1163 if_python.c:1227 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "numer wiersza poza zakresem"
+
+#: if_python.c:1362
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<obiekt bufora (skasowany) w %8lX>"
+
+#: if_python.c:1453 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "niepoprawna nazwa zak³adki"
+
+#: if_python.c:1733
+msgid "no such buffer"
+msgstr "nie ma takiego bufora"
+
+#: if_python.c:1821
+msgid "attempt to refer to deleted window"
+msgstr "próba odniesienia do skasowanego okna"
+
+#: if_python.c:1866
+msgid "readonly attribute"
+msgstr "atrybut tylko do odczytu"
+
+#: if_python.c:1879
+msgid "cursor position outside buffer"
+msgstr "pozycja kursora poza buforem"
+
+#: if_python.c:1956
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<obiekt okna (skasowany) w %.8lX>"
+
+#: if_python.c:1968
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<obiekt okna (nieznany) w %.8lX>"
+
+#: if_python.c:1970
+#, c-format
+msgid "<window %d>"
+msgstr "<okno %d>"
+
+#: if_python.c:2046
+msgid "no such window"
+msgstr "nie ma takiego okna"
+
+#: if_python.c:2307 if_python.c:2341 if_python.c:2396 if_python.c:2464
+#: if_python.c:2586 if_python.c:2638 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "nie mogê zachowaæ informacji cofania"
+
+#: if_python.c:2309 if_python.c:2403 if_python.c:2475
+msgid "cannot delete line"
+msgstr "nie mogê skasowaæ wiersza"
+
+#: if_python.c:2346 if_python.c:2491 if_tcl.c:690 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "nie mogê zamieniæ wiersza"
+
+#: if_python.c:2509 if_python.c:2588 if_python.c:2646
+msgid "cannot insert line"
+msgstr "nie mogê wprowadziæ wiersza"
+
+#: if_python.c:2750
+msgid "string cannot contain newlines"
+msgstr "ci¹g nie mo¿e zawieraæ znaków nowego wiersza"
+
+#: if_ruby.c:422
+msgid "E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E263: Przykro mi, ta komenda jest wy³¹czona, bo nie mo¿na za³adowaæ "
+"biblioteki Ruby."
+
+#: if_ruby.c:485
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: Nieznany status longjmp %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Prze³¹cz miêdzy implementacj¹/okreœleniem"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Poka¿ bazê klasy"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Poka¿ przepisan¹ funkcjê cz³onkow¹"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Pobieraj z pliku"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Pobieraj z projektu"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Pobieraj z wszystkich projektów"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Pobierz"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Poka¿ Ÿród³o dla"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "ZnajdŸ symbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Przejrzyj klasê"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Poka¿ klasê w hierarchii"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Poka¿ klasê w ograniczonej hierarchii"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref odnosi siê do"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref ma odniesienia od"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref ma"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref u¿yte przez"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Poka¿ dokumentacjê dla"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Wygeneruj dokumentacjê dla"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"Nie mogê pod³¹czyæ do SNiFF+. SprawdŸ œrodowisko (sniffemacs musi byæ "
+"odnaleziony w $PATH).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: B³¹d podczas czytania. Roz³¹czenie"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ jest obecnie "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "nie "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "pod³¹czony"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Nieznane zapytanie SNiFF+: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: B³¹d w trakcie pod³¹czania do SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ niepod³¹czony"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Nie jest buforem SNiFF+"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: B³¹d w trakcie zapisu. Roz³¹czony"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "niew³aœciwy numer bufora"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "obecnie nie zaimplementowano"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "nieznana opcja"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "nie mogê ustawiæ wiersza(y)"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "zak³adka nie ustawiona"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "wiersz %d kolumna %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "nie mogê wprowadziæ/do³¹czyæ wiersza"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "nieznana flaga: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "nieznane vimOption"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "przerwanie klawiatury"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "b³¹d vima"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "nie mogê stworzyæ bufora/okna komendy: obiekt jest kasowany"
+
+#: if_tcl.c:1545
+msgid "cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"nie mogê zarejestrowaæ wstecznego wywo³ania komendy: bufor/okno ju¿ zosta³a "
+"skasowana"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: TCL FATALNY B£¥D: reflist zepsuta!? Proszê z³o¿yæ raport o tym na vim-"
+"dev@vim.org"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"nie mogê zarejestrowaæ wstecznego wywo³ania komendy: brak odniesienia do "
+"bufora/okna"
+
+#: if_tcl.c:1724
+msgid "E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr "Przykro mi, ta komenda jest wy³¹czona, bo nie mo¿na za³adowaæ biblioteki Tcl."
+
+#: if_tcl.c:1886
+msgid "E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: B£¥D TCL: kod zakoñczeniowy nie jest ca³kowity!? Proszê z³o¿yæ raport "
+"o tym na vim-dev@vim.org"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "nie mogê dostaæ wiersza"
+
+#: if_xcmdsrv.c:225
+msgid "Unable to register a command server name"
+msgstr "Nie mogê zarejestrowaæ nazwy serwera komend"
+
+#: if_xcmdsrv.c:473
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Wys³anie komendy do programu docelowego nie powiod³o siê"
+
+#: if_xcmdsrv.c:747
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: U¿yto niew³aœciwego id serwera: %s"
+
+#: if_xcmdsrv.c:1110
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: wcielenia instancji rejestru Vima jest Ÿle sformowane. Skasowano!"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "Nieznana opcja"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "Zbyt wiele argumentów"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "Brak argumentu po"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "Œmiecie po opcji"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr "Zbyt wiele argumentów \"+komenda\", \"-c komenda\" lub \"--cmd komenda\""
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "Niew³aœciwy argument dla"
+
+#: main.c:466
+msgid "This Vim was not compiled with the diff feature."
+msgstr "Ta wersja Vima nie by³a skompilowanego z opcj¹ ró¿nic (diff)."
+
+#: main.c:932
+msgid "Attempt to open script file again: \""
+msgstr "Próba ponownego otworzenia pliku skryptu: \""
+
+#: main.c:941
+msgid "Cannot open for reading: \""
+msgstr "Nie mogê otworzyæ do odczytu: \""
+
+#: main.c:985
+msgid "Cannot open for script output: \""
+msgstr "Nie mogê otworzyæ dla wyjœcia skryptu: \""
+
+#: main.c:1132
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d plików do edycji\n"
+
+#: main.c:1233
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: OSTRZE¯ENIE: Wyjœcie nie jest terminalem\n"
+
+#: main.c:1235
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: OSTRZE¯ENIE: Wejœcie nie pochodzi z terminala\n"
+
+#. just in case..
+#: main.c:1297
+msgid "pre-vimrc command line"
+msgstr "linia poleceñ pre-vimrc"
+
+#: main.c:1338
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Nie mogê czytaæ z \"%s\""
+
+#: main.c:2411
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Dalsze informacje poprzez: \"vim -h\"\n"
+
+#: main.c:2444
+msgid "[file ..] edit specified file(s)"
+msgstr "[plik ..] edytuj zadane pliki"
+
+#: main.c:2445
+msgid "- read text from stdin"
+msgstr "- czytaj tekst ze stdin"
+
+#: main.c:2446
+msgid "-t tag edit file where tag is defined"
+msgstr "-t znacznik edytuj plik, w którym dany znacznik jest zdefiniowany"
+
+#: main.c:2448
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [errorfile] edytuj plik, zawieraj¹cy pierwszy b³¹d"
+
+#: main.c:2457
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"u¿ycie:"
+
+#: main.c:2460
+msgid " vim [arguments] "
+msgstr " vim [argumenty]"
+
+#: main.c:2464
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" lub:"
+
+#: main.c:2467
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Argumenty:\n"
+
+#: main.c:2468
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tTylko nazwy plików po tym"
+
+#: main.c:2470
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tNie rozwijaj znaków specjalnych"
+
+#: main.c:2473
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tZarejestruj tego gvima w OLE"
+
+#: main.c:2474
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tWyrejestruj gvima z OLE"
+
+#: main.c:2477
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tStartuj w GUI (tak jak \"gvim\")"
+
+#: main.c:2478
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f lub --nofork\tPierwszy plan: Nie wydzielaj przy odpalaniu GUI"
+
+#: main.c:2480
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tTryb vi (jak \"vi\")"
+
+#: main.c:2481
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tTryb ex (jak \"ex\")"
+
+#: main.c:2482
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tCichy tryb (t³a) (tylko dla \"ex\")"
+
+#: main.c:2484
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tTryb ró¿nic (jak \"vimdiff\")"
+
+#: main.c:2486
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tTryb ³atwy (jak \"evim\", bez trybów)"
+
+#: main.c:2487
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tTryb wy³¹cznie do odczytu (jak \"view\")"
+
+#: main.c:2488
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tTryb ograniczenia (jak \"rvim\")"
+
+#: main.c:2489
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tModyfikacje (zapisywanie plików) niedozwolone"
+
+#: main.c:2490
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tZakaz modyfikacji tekstu"
+
+#: main.c:2491
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tTryb binarny"
+
+#: main.c:2493
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tTryb lisp"
+
+#: main.c:2495
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tB¹dŸ zgodny z Vi: 'compatible'"
+
+#: main.c:2496
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tB¹dŸ niezupe³nie zgodny z Vi: 'nocompatible'"
+
+#: main.c:2497
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tStopieñ gadatliwoœci"
+
+#: main.c:2498
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tTryb odpluskwiania"
+
+#: main.c:2499
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tZamiast pliku wymiany, u¿ywaj tylko pamiêci"
+
+#: main.c:2500
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tWylicz pliki wymiany i zakoñcz"
+
+#: main.c:2501
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (z nazw¹ pliku)\tOdtwórz za³aman¹ sesjê"
+
+#: main.c:2502
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tTo¿same z -r"
+
+#: main.c:2504
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tNie stosuj newcli do otwierania okien"
+
+#: main.c:2505
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <device>\t\tU¿ywaj <device> do I/O"
+
+#: main.c:2508
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\t\trozpocznij w trybie arabskim"
+
+#: main.c:2511
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\trozpocznij w trybie hebrajskim"
+
+#: main.c:2514
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\trozpocznij w trybie farsi"
+
+#: main.c:2516
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\tUstaw typ terminala na <terminal>"
+
+#: main.c:2517
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tU¿yj <vimrc> zamiast jakiegokolwiek .vimrc"
+
+#: main.c:2519
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tU¿yj <gvimrc> zamiast jakiegokolwiek .gvimrc"
+
+#: main.c:2521
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tNie ³aduj skryptów wtyczek"
+
+#: main.c:2522
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tOtwórz N okien (domyœlnie: po jednym dla ka¿dego pliku)"
+
+#: main.c:2523
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\ttak samo jak -o tylko dziel okno pionowo"
+
+#: main.c:2524
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tZacznij na koñcu pliku"
+
+#: main.c:2525
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\tZacznij w wierszu <lnum>"
+
+#: main.c:2527
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr ""
+"-cmd <command>\t\tWykonaj komendê <command> przed za³adowaniem "
+"jakiegokolwiek pliku vimrc"
+
+#: main.c:2529
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <command>\t\tWykonaj komendê <command> po za³adowaniu pierwszego pliku"
+
+#: main.c:2530
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <sesja>\t\tWczytaj plik <sesja> po za³adowaniu pierwszego pliku"
+
+#: main.c:2531
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <scriptin>\tWczytuj komendy trybu normalnego z pliku <scriptin>"
+
+#: main.c:2532
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <scriptout>\tDo³¹cz wszystkie wprowadzane komendy do pliku <scriptout>"
+
+#: main.c:2533
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <scriptout>\tZapisuj wszystkie wprowadzane komendy do pliku <scriptout>"
+
+#: main.c:2535
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tEdytuj zakodowane pliki"
+
+#: main.c:2539
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\tPod³¹cz vima to danego X-serwera"
+
+#: main.c:2541
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tNie ³¹cz z serwerem X"
+
+#: main.c:2544
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <pliki>\tEdytuj pliki w serwerze Vima jeœli mo¿liwe"
+
+#: main.c:2545
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-silent <pliki> To samo, nie narzekaj jeœli nie ma serwera"
+
+#: main.c:2546
+msgid "--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <pliki>\tTak jak --remote, lecz czekaj na pliki przed edycj¹"
+
+#: main.c:2547
+msgid "--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-wait-silent <pliki> To samo, nie narzekaj jeœli nie ma serwera"
+
+#: main.c:2548
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <klawisze>\tWyœlij <klawisze> do serwera Vima i zakoñcz"
+
+#: main.c:2549
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <wyr>\tWykonaj <wyra¿enie> w serwerze i wypisz wynik"
+
+#: main.c:2550
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tWymieñ nazwy dostêpnych serwerów Vima i zakoñcz"
+
+#: main.c:2551
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <nazwa>\t\tOdsy³aj do/stañ siê serwerem Vim <nazwa>"
+
+#: main.c:2554
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tU¿ywaj <viminfo> zamiast .viminfo"
+
+#: main.c:2556
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h lub --help\twyœwietl Pomoc (czyli tê wiadomoœæ) i zakoñcz"
+
+#: main.c:2557
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\twyœwietl informacjê o wersji i zakoñcz"
+
+#: main.c:2561
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Argumenty rozpoznawane przez gvim (wersja Motif):\n"
+
+#: main.c:2565
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr ""
+"\n"
+"Argumenty rozpoznawane przez gvim (wersja neXtaw):\n"
+
+#: main.c:2567
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Argumenty rozpoznawane przez gvim (wersja Athena):\n"
+
+#: main.c:2571
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\tZa³aduj vim na <display>"
+
+#: main.c:2572
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tZacznij Vim jako ikonê"
+
+#: main.c:2574
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <nazwa>\t\tU¿ywaj zasobów tak jak by Vim by³ <nazwa>"
+
+#: main.c:2575
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (Niezaimplementowane)\n"
+
+#: main.c:2577
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <kolor>\tU¿ywaj <kolor> dla t³a (równie¿: -bg)"
+
+#: main.c:2578
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <kolor>\tU¿ywaj <kolor> dla normalnego tekstu (równie¿: -fg)"
+
+#: main.c:2579 main.c:2599
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <font>\t\tU¿ywaj <font> dla normalnego tekstu (równie¿: -fn)"
+
+#: main.c:2580
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <font>\tU¿ywaj <font> dla wyt³uszczonego tekstu"
+
+#: main.c:2581
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <font>\tU¿ywaj <font> dla pochy³ego"
+
+#: main.c:2582 main.c:2600
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\tU¿ywaj <geom> dla pocz¹tkowych rozmiarów (równie¿: -geom)"
+
+#: main.c:2583
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <szer>\tU¿yj ramki o gruboœci <szer> (równie¿: -bw)"
+
+#: main.c:2584
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <szer> U¿ywaj przewijacza o szerokoœci <szer> (równie¿: -sw)"
+
+#: main.c:2586
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <height>\tStosuj belkê menu o wysokoœci <height> (równie¿: -mh)"
+
+#: main.c:2588 main.c:2601
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tStosuj negatyw kolorów (równie¿: -rv)"
+
+#: main.c:2589
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tNie stosuj negatywu kolorów (równie¿: +rv)"
+
+#: main.c:2590
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\tUstaw okreœlony zasób"
+
+#: main.c:2593
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Argumenty rozpoznawane przez gvim (wersja RISC OS):\n"
+
+#: main.c:2594
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <number>\tPocz¹tkowa szerokoœæ okna w kolumnach"
+
+#: main.c:2595
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <number>\tPocz¹tkowa wysokoœæ okna w wierszach"
+
+#: main.c:2598
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Argumenty rozpoznawane przez gvim (wersja GTK+):\n"
+
+#: main.c:2602
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\tZastartuj vim na <display> (równie¿: --display)"
+
+#: main.c:2604
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr "--role <role>\tUstaw unikatow¹ rolê do identyfikacji g³ównego okna"
+
+#: main.c:2606
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tOtwórz Vim wewn¹trz innego widgetu GTK"
+
+#: main.c:2609
+msgid "-P <parent title>\tOpen Vim inside parent application"
+msgstr "-P <tytu³ rodzica>\tOtwórz Vima wewn¹trz rodzicielskiej aplikacji"
+
+#: main.c:2847
+msgid "No display"
+msgstr "Brak display"
+
+#. Failed to send, abort.
+#: main.c:2862
+msgid ": Send failed.\n"
+msgstr ": Wys³anie nie powiod³o siê.\n"
+
+#. Let vim start normally.
+#: main.c:2868
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": Wys³anie nie powiod³o siê. Próbujê wykonaæ na miejscu\n"
+
+#: main.c:2906 main.c:2927
+#, c-format
+msgid "%d of %d edited"
+msgstr "otworzono %d z %d"
+
+#: main.c:2949
+msgid "No display: Send expression failed.\n"
+msgstr "Brak terminala: Wys³anie wyra¿enia nie powiod³o siê.\n"
+
+#: main.c:2961
+msgid ": Send expression failed.\n"
+msgstr ": Wys³anie wyra¿enia nie powiod³o siê.\n"
+
+#: mark.c:709
+msgid "No marks set"
+msgstr "Brak zak³adek"
+
+#: mark.c:711
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: ¯adna zak³adka nie pasuje do \"%s\""
+
+#. Highlight title
+#: mark.c:722
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"zak³. wiersz kol plik/tekst"
+
+#. Highlight title
+#: mark.c:760
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" skok wiersz kol plik/tekst"
+
+#. Highlight title
+#: mark.c:805
+msgid ""
+"\n"
+"change line col text"
+msgstr ""
+"\n"
+"zmieñ wrsz. kol tekst"
+
+#: mark.c:1281
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Zak³adki w plikach:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1316
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Lista odniesieñ (pocz¹wszy od najnowszych):\n"
+
+#: mark.c:1412
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Historia zak³adek w plikach (od najnowszych po najstarsze):\n"
+
+#: mark.c:1501
+msgid "Missing '>'"
+msgstr "Brak '>'"
+
+#: mbyte.c:467
+msgid "E543: Not a valid codepage"
+msgstr "E543: To nie jest wa¿na strona kodowa"
+
+#: mbyte.c:4431
+msgid "E284: Cannot set IC values"
+msgstr "E284: Nie mogê nastawiæ wartoœci IC"
+
+#: mbyte.c:4583
+msgid "E285: Failed to create input context"
+msgstr "E285: Nie mog³em stworzyæ kontekstu wprowadzeñ"
+
+#: mbyte.c:4741
+msgid "E286: Failed to open input method"
+msgstr "E286: Nie mog³em otworzyæ sposobu wprowadzeñ"
+
+#: mbyte.c:4752
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: OSTRZE¯ENIE: Nie mog³em zlikwidowaæ wywo³ania dla IM"
+
+#: mbyte.c:4758
+msgid "E288: input method doesn't support any style"
+msgstr "E288: metoda wprowadzeñ nie wspomaga ¿adnego stylu"
+
+#: mbyte.c:4815
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: metoda wprowadzeñ nie wspomaga mojego typu preedit"
+
+#: mbyte.c:4889
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: styl nadpunktowy wymaga +fontset"
+
+#: mbyte.c:4925
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: Twój GTK+ jest starszy ni¿ 1.2.3. Pole statusu wy³¹czono"
+
+#: mbyte.c:5232
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Serwer metod wprowadzeñ nie jest uruchomiony"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: blok nie by³ zablokowany"
+
+#: memfile.c:1005
+msgid "E294: Seek error in swap file read"
+msgstr "E294: B³¹d w trakcie czytania pliku wymiany"
+
+#: memfile.c:1010
+msgid "E295: Read error in swap file"
+msgstr "E295: B³¹d odczytu pliku wymiany"
+
+#: memfile.c:1062
+msgid "E296: Seek error in swap file write"
+msgstr "E296: B³¹d szukania w pliku wymiany"
+
+#: memfile.c:1080
+msgid "E297: Write error in swap file"
+msgstr "E297: B³¹d zapisu w pliku wymiany"
+
+#: memfile.c:1277
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: Plik wymiany ju¿ istnieje (atak symlink?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Nie otrzyma³em bloku nr 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Nie otrzyma³em bloku nr 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: Nie otrzyma³em bloku nr 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Ojej, zgubi³em plik wymiany!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: Nie mog³em zmieniæ nazwy pliku wymiany"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: Nie mogê otworzyæ pliku wymiany dla \"%s\"; odtworzenie niemo¿liwe"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: Nie otrzyma³em bloku 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Nie znaleziono pliku wymiany dla %s"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "WprowadŸ numer pliku wymiany, którego u¿yæ (0 by wyjœæ): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: Nie mogê otworzyæ %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "Nie mogê odczytaæ bloku 0 z "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Mo¿e nie wykonano zmian albo Vim nie zaktualizowa³ pliku wymiany."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " nie mo¿e byæ stosowany z t¹ wersj¹ Vima.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "U¿yj Vima w wersji 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s nie wygl¹da na plik wymiany Vima"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " nie mo¿e byæ stosowany na tym komputerze.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "Ten plik zosta³ stworzony na "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"lub plik zosta³ uszkodzony."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "U¿ywam pliku wymiany \"%s\""
+
+#: memline.c:909
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Oryginalny plik \"%s\""
+
+#: memline.c:922
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: OSTRZE¯ENIE: Oryginalny plik móg³ byæ zmieniony"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Nie mogê odczytaæ bloku 1 z %s"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???BRAKUJE WIELU WIERSZY"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???LICZNIK WIERSZY NIEZGODNY"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???PUSTY BLOK"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???BRAKUJE WIERSZY"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: Niew³aœciwe ID bloku 1 (mo¿e %s nie jest plikiem .swp?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???BRAK BLOKU"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? od tego miejsca po ???KONIEC wiersze mog¹ byæ pomieszane"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? od tego miejsca po ???KONIEC wiersze mog¹ byæ w³o¿one/skasowane"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???KONIEC"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Przerwanie odtwarzania"
+
+#: memline.c:1148
+msgid "E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: Wykryto b³êdy podczas odtwarzania; od których wierszy zacz¹æ ???"
+
+#: memline.c:1150
+msgid "See \":help E312\" for more information."
+msgstr "Patrz \":help E312\" dla dalszych informacji."
+
+#: memline.c:1155
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Odtwarzanie zakoñczono. Powinieneœ sprawdziæ czy wszystko jest w porz¹dku."
+
+#: memline.c:1156
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Mo¿esz chcieæ zapisaæ ten plik pod inn¹ nazw¹\n"
+
+#: memline.c:1157
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "i wykonaæ diff z oryginalnym plikiem aby sprawdziæ zmiany)\n"
+
+#: memline.c:1158
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"Skasuj potem plik .swp.\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1214
+msgid "Swap files found:"
+msgstr "Znalezione pliki wymiany:"
+
+#: memline.c:1392
+msgid " In current directory:\n"
+msgstr " W bie¿¹cym katalogu:\n"
+
+#: memline.c:1394
+msgid " Using specified name:\n"
+msgstr " U¿ywam podanej nazwy:\n"
+
+#: memline.c:1398
+msgid " In directory "
+msgstr " W katalogu "
+
+#: memline.c:1416
+msgid " -- none --\n"
+msgstr " -- ¿aden --\n"
+
+#: memline.c:1488
+msgid " owned by: "
+msgstr " posiadany przez: "
+
+#: memline.c:1490
+msgid " dated: "
+msgstr " data: "
+
+#: memline.c:1494 memline.c:3684
+msgid " dated: "
+msgstr " data: "
+
+#: memline.c:1510
+msgid " [from Vim version 3.0]"
+msgstr " [po Vimie wersja 3.0]"
+
+#: memline.c:1514
+msgid " [does not look like a Vim swap file]"
+msgstr " [nie wygl¹da na plik wymiany Vima]"
+
+#: memline.c:1518
+msgid " file name: "
+msgstr " nazwa pliku: "
+
+#: memline.c:1524
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" zmieniono: "
+
+#: memline.c:1525
+msgid "YES"
+msgstr "TAK"
+
+#: memline.c:1525
+msgid "no"
+msgstr "nie"
+
+#: memline.c:1529
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" u¿ytkownik: "
+
+#: memline.c:1536
+msgid " host name: "
+msgstr " nazwa hosta: "
+
+#: memline.c:1538
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" nazwa hosta: "
+
+#: memline.c:1544
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ID procesu: "
+
+#: memline.c:1550
+msgid " (still running)"
+msgstr " (dalej dzia³a)"
+
+#: memline.c:1562
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [nie nadaje siê dla tej wersji Vima]"
+
+#: memline.c:1565
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [nie do u¿ytku na tym komputerze]"
+
+#: memline.c:1570
+msgid " [cannot be read]"
+msgstr " [nieodczytywalny]"
+
+#: memline.c:1574
+msgid " [cannot be opened]"
+msgstr " [nieotwieralny]"
+
+#: memline.c:1764
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Nie mogê zabezpieczyæ, bo brak pliku wymiany"
+
+#: memline.c:1817
+msgid "File preserved"
+msgstr "Plik zabezpieczono"
+
+#: memline.c:1819
+msgid "E314: Preserve failed"
+msgstr "E314: Nieudane zabezpieczenie"
+
+#: memline.c:1890
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: niew³aœciwy lnum: %ld"
+
+#: memline.c:1916
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: nie znaleziono wiersza %ld"
+
+#: memline.c:2306
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: niepoprawne id wskaŸnika bloku 3"
+
+#: memline.c:2386
+msgid "stack_idx should be 0"
+msgstr "stack_idx powinien byæ 0"
+
+#: memline.c:2448
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Zaktualizowano zbyt wiele bloków?"
+
+#: memline.c:2630
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: niepoprawne id wskaŸnika bloku 4"
+
+#: memline.c:2657
+msgid "deleted block 1?"
+msgstr "blok nr 1 skasowany?"
+
+#: memline.c:2857
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Nie mogê znaleŸæ wiersza %ld"
+
+#: memline.c:3100
+msgid "E317: pointer block id wrong"
+msgstr "E317: niepoprawne id bloku odniesienia"
+
+#: memline.c:3116
+msgid "pe_line_count is zero"
+msgstr "pe_line_count wynosi zero"
+
+#: memline.c:3145
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: numer wiersza poza zakresem: %ld jest poza koñcem"
+
+#: memline.c:3149
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: liczba wierszy niepoprawna w bloku %ld"
+
+#: memline.c:3198
+msgid "Stack size increases"
+msgstr "WielkoϾ stosu wzrasta"
+
+#: memline.c:3244
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: niepoprawne id bloku odniesienia 2"
+
+#: memline.c:3674
+msgid "E325: ATTENTION"
+msgstr "E325: UWAGA"
+
+#: memline.c:3675
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Znalaz³em plik wymiany o nazwie \""
+
+#: memline.c:3679
+msgid "While opening file \""
+msgstr "Podczas otwierania pliku \""
+
+#: memline.c:3688
+msgid " NEWER than swap file!\n"
+msgstr " NOWSZE od pliku wymiany!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3692
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Pewnie inny program obrabia ten sam plik.\n"
+" Jeœli tak, b¹dŸ ostro¿ny, aby nie skoñczyæ z dwoma\n"
+" ró¿nymi wersjami jednego tego samego pliku po zmianach.\n"
+
+#: memline.c:3693
+msgid " Quit, or continue with caution.\n"
+msgstr " Zakoñcz lub ostro¿nie kontynuuj.\n"
+
+#: memline.c:3694
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) Sesja edycji dla pliku za³ama³a siê.\n"
+
+#: memline.c:3695
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Jeœli tak, to u¿yj \":recover\" lub \"vim -r "
+
+#: memline.c:3697
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" aby odzyskaæ zmiany (patrz \":help recovery)\").\n"
+
+#: memline.c:3698
+msgid " If you did this already, delete the swap file \""
+msgstr " Jeœli ju¿ to zrobi³eœ, usuñ plik wymiany \""
+
+#: memline.c:3700
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" aby unikn¹æ tej wiadomoœci.\n"
+
+#: memline.c:3714 memline.c:3718
+msgid "Swap file \""
+msgstr "Plik wymiany \""
+
+#: memline.c:3715 memline.c:3721
+msgid "\" already exists!"
+msgstr "\" ju¿ istnieje!"
+
+#: memline.c:3724
+msgid "VIM - ATTENTION"
+msgstr "VIM - UWAGA"
+
+#: memline.c:3726
+msgid "Swap file already exists!"
+msgstr "Plik wymiany ju¿ istnieje!"
+
+#: memline.c:3730
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort"
+msgstr ""
+"&Otwórz Read-Only\n"
+"&Edytuj pomimo\n"
+"O&dtwórz\n"
+"&Zakoñcz\n"
+"&Porzuæ"
+
+#: memline.c:3732
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort\n"
+"&Delete it"
+msgstr ""
+"&Otwórz Read-Only\n"
+"&Edytuj pomimo\n"
+"O&dtwórz\n"
+"&Zakoñcz\n"
+"&Porzuæ\n"
+"&Skasuj go"
+
+#: memline.c:3789
+msgid "E326: Too many swap files found"
+msgstr "E326: Znaleziono zbyt wiele plików wymiany"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Czêœæ tropu punktu menu nie okreœla podmenu"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Menu istnieje tylko w innym trybie"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Nie ma menu o tej nazwie"
+
+#: menu.c:525
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Trop menu nie mo¿e prowadziæ do podmenu"
+
+#: menu.c:564
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: Nie wolno dodawaæ punktów menu wprost do paska menu"
+
+#: menu.c:570
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Separator nie mo¿e byæ czêœci¹ tropu menu"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1097
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Menu ---"
+
+#: menu.c:2019
+msgid "Tear off this menu"
+msgstr "Oderwij to menu"
+
+#: menu.c:2084
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Trop menu musi prowadziæ do punktu menu"
+
+#: menu.c:2104
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Nie znaleziono menu: %s"
+
+#: menu.c:2173
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: Menu nie jest zdefiniowane dla trybu %s"
+
+#: menu.c:2211
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Trop menu musi prowadziæ do podmenu"
+
+#: menu.c:2232
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Nie znaleziono menu - sprawdŸ nazwy menu"
+
+#: message.c:414
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Wykryto b³¹d podczas przetwarzania %s:"
+
+#: message.c:440
+#, c-format
+msgid "line %4ld:"
+msgstr "wiersz %4ld:"
+
+#: message.c:647
+msgid "[string too long]"
+msgstr "[ci¹g zbyt d³ugi]"
+
+#: message.c:797
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr ""
+"Opiekun komunikatów: Marcin Dalecki <dalecki@cs.net.pl>, Miko³aj Machowski "
+"<mikmach@wp.pl>"
+
+#: message.c:1025
+msgid "Interrupt: "
+msgstr "Przerwanie: "
+
+#: message.c:1028
+msgid "Hit ENTER to continue"
+msgstr "Naciœnij ENTER aby kontynuowaæ"
+
+#: message.c:1030
+msgid "Hit ENTER or type command to continue"
+msgstr "Naciœnij ENTER lub wprowadŸ komendê aby kontynuowaæ"
+
+#: message.c:2351
+msgid "-- More --"
+msgstr "-- Wiêcej --"
+
+#: message.c:2354
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: wiersz, SPACE/b: stronê, d/u: pó³ strony, q: zakoñcz)"
+
+#: message.c:2355
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: wiersz, SPACE: stronê, d: pó³ strony, q: zakoñczenie)"
+
+#: message.c:2976 message.c:2991
+msgid "Question"
+msgstr "Pytanie"
+
+#: message.c:2978
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Tak\n"
+"&Nie"
+
+#: message.c:3011
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Tak\n"
+"&Nie\n"
+"Zapisz &wszystkie\n"
+"&Odrzuæ wszystkie\n"
+"&Zakoñcz"
+
+#: message.c:3052
+msgid "Save File dialog"
+msgstr "Dialog zapisywania pliku"
+
+#: message.c:3054
+msgid "Open File dialog"
+msgstr "Dialog otwierania pliku"
+
+#. TODO: non-GUI file selector here
+#: message.c:3125
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: Przykro mi, nie ma przegl¹darki plików w trybie konsoli"
+
+#: misc1.c:2754
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: OSTRZE¯ENIE: Zmiany w pliku tylko do odczytu"
+
+#: misc1.c:3002
+msgid "1 more line"
+msgstr "1 wiersz wiêcej"
+
+#: misc1.c:3004
+msgid "1 line less"
+msgstr "1 wiersz mniej"
+
+#: misc1.c:3009
+#, c-format
+msgid "%ld more lines"
+msgstr "dodano %ld wierszy"
+
+#: misc1.c:3011
+#, c-format
+msgid "%ld fewer lines"
+msgstr "usuniêto %ld wierszy"
+
+#: misc1.c:3014
+msgid " (Interrupted)"
+msgstr " (Przerwane)"
+
+#: misc1.c:7563
+msgid "Vim: preserving files...\n"
+msgstr "Vim: zachowujê plik...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:7573
+msgid "Vim: Finished.\n"
+msgstr "Vim: Zakoñczono.\n"
+
+#: misc2.c:695 misc2.c:711
+msgid "ERROR: "
+msgstr "B£¥D: "
+
+#: misc2.c:715
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bajtów] totalne alokacje-zwolnienia %lu-%lu, w u¿ytku %lu, maksymalne "
+"u¿ycie %lu\n"
+
+#: misc2.c:717
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[wywo³ania] wszystkich re/malloc()-ów %lu, wszystkich free()-ów %lu\n"
+"\n"
+
+#: misc2.c:772
+msgid "E340: Line is becoming too long"
+msgstr "E340: Wiersz staje siê zbyt d³ugi"
+
+#: misc2.c:816
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Wewnêtrzny b³¹d: lalloc(%ld, )"
+
+#: misc2.c:924
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Brak pamiêci! (rezerwacja %lu bajtów)"
+
+#: misc2.c:2593
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Wywo³ujê pow³okê do wykonania: \"%s\""
+
+#: misc2.c:2815
+msgid "E545: Missing colon"
+msgstr "E545: Brak dwukropka"
+
+#: misc2.c:2817 misc2.c:2844
+msgid "E546: Illegal mode"
+msgstr "E546: Niedozwolony tryb"
+
+#: misc2.c:2883
+msgid "E547: Illegal mouseshape"
+msgstr "E547: Niedozwolony obrys myszki"
+
+#: misc2.c:2923
+msgid "E548: digit expected"
+msgstr "E548: oczekiwano cyfry"
+
+#: misc2.c:2928
+msgid "E549: Illegal percentage"
+msgstr "E459: Niedozwolony procent"
+
+#: misc2.c:3238
+msgid "Enter encryption key: "
+msgstr "WprowadŸ klucz do odkodowania: "
+
+#: misc2.c:3239
+msgid "Enter same key again: "
+msgstr "WprowadŸ ponownie ten sam klucz: "
+
+#: misc2.c:3249
+msgid "Keys don't match!"
+msgstr "Klucze nie pasuj¹ do siebie!"
+
+#: misc2.c:3798
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Niew³aœciwy trop: '**[numer]' musi byæ na koñcu tropu lub po nim musi "
+"byæ '%s'."
+
+#: misc2.c:5077
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Nie mogê znaleŸæ katalogu \"%s\" w cdpath"
+
+#: misc2.c:5080
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Nie mogê znaleŸæ pliku \"%s\" w tropie"
+
+#: misc2.c:5086
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: Katalogu \"%s\" nie ma wiêcej w cdpath"
+
+#: misc2.c:5089
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: Pliku \"%s\" nie ma wiêcej w tropie"
+
+#: misc2.c:5323
+msgid "E550: Missing colon"
+msgstr "E550: Brak dwukropka"
+
+#: misc2.c:5335
+msgid "E551: Illegal component"
+msgstr "E551: Niedozwolona czêœæ"
+
+#: misc2.c:5343
+msgid "E552: digit expected"
+msgstr "E552: oczekiwano cyfry"
+
+#. Get here when the server can't be found.
+#: netbeans.c:396
+msgid "Cannot connect to Netbeans #2"
+msgstr "Nie mo¿na po³¹czyæ z Netbeans #2"
+
+#: netbeans.c:404
+msgid "Cannot connect to Netbeans"
+msgstr "Nie mo¿na po³¹czyæ z Netbeans"
+
+#: netbeans.c:450
+#, c-format
+msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\""
+msgstr "E668: B³êdny tryb dostêpu pliku info po³¹czenia NetBeans: \"%s\""
+
+#: netbeans.c:749
+msgid "read from Netbeans socket"
+msgstr "odczyt z gniazda Netbeans"
+
+#: netbeans.c:1638
+#, c-format
+msgid "E658: NetBeans connection lost for buffer %ld"
+msgstr "E658: Bufor %ld utraci³ po³¹czenie z NetBeans"
+
+#: normal.c:2980
+msgid "Warning: terminal cannot highlight"
+msgstr "OSTRZE¯ENIE: terminal nie wykonuje podœwietlania"
+
+#: normal.c:3276
+msgid "E348: No string under cursor"
+msgstr "E348: Brak ci¹gu pod kursorem"
+
+#: normal.c:3278
+msgid "E349: No identifier under cursor"
+msgstr "E349: Brak identyfikatora pod kursorem"
+
+#: normal.c:4519
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: Nie mogê skasowaæ zwiniêcia z bie¿¹c¹ 'foldmethod'"
+
+#: normal.c:6740
+msgid "E662: At start of changelist"
+msgstr "E662: Na pocz¹tku listy zmian"
+
+#: normal.c:6742
+msgid "E663: At end of changelist"
+msgstr "E663: Na koñcu listy zmian"
+
+#: normal.c:8003
+msgid "Type :quit<Enter> to exit Vim"
+msgstr "wprowadŸ :quit<Enter> zakoñczenie programu"
+
+#: ops.c:294
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "1 wiersz %sed 1 raz"
+
+#: ops.c:296
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 wiersz %sed %d razy"
+
+#: ops.c:301
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld wierszy %sed 1 raz"
+
+#: ops.c:304
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld wierszy %sed %d razy"
+
+#: ops.c:662
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld wierszy do wciêcia... "
+
+#: ops.c:712
+msgid "1 line indented "
+msgstr "1 wiersz wciêty "
+
+#: ops.c:714
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld wierszy wciêtych "
+
+#. must display the prompt
+#: ops.c:1675
+msgid "cannot yank; delete anyway"
+msgstr "nie mogê skopiowaæ, mimo to kasujê"
+
+#: ops.c:2261
+msgid "1 line changed"
+msgstr "1 wiersz zmieniono"
+
+#: ops.c:2263
+#, c-format
+msgid "%ld lines changed"
+msgstr "%ld wierszy zmieniono"
+
+#: ops.c:2647
+#, c-format
+msgid "freeing %ld lines"
+msgstr "zwalniam %ld wierszy"
+
+#: ops.c:2928
+msgid "1 line yanked"
+msgstr "1 wiersz przekopiowano"
+
+#: ops.c:2930
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld wierszy przekopiowanych"
+
+#: ops.c:3215
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: Pusty rejestr %s"
+
+#. Highlight title
+#: ops.c:3766
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Rejestry ---"
+
+#: ops.c:5073
+msgid "Illegal register name"
+msgstr "Niedozwolona nazwa rejestru"
+
+#: ops.c:5161
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Rejestry:\n"
+
+#: ops.c:5211
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: Nieznany typ rejestru %d"
+
+#: ops.c:5696
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: Niew³aœciwa nazwa rejestru: '%s'"
+
+#: ops.c:6056
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Kolumn; "
+
+#: ops.c:6063
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Wybrano %s%ld z %ld Wierszy; %ld z %ld S³ów; %ld z %ld Bajtów"
+
+#: ops.c:6079
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Kol %s z %s; Wiersz %ld z %ld; S³owo %ld z %ld; Bajt %ld z %ld"
+
+#: ops.c:6090
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld dla BOM)"
+
+#: option.c:1643
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=Strona %N"
+
+#: option.c:2092
+msgid "Thanks for flying Vim"
+msgstr "Dziêki za lot Vimem"
+
+#: option.c:3419 option.c:3535
+msgid "E518: Unknown option"
+msgstr "E518: Nieznana opcja"
+
+#: option.c:3432
+msgid "E519: Option not supported"
+msgstr "E519: Opcja nie jest wspomagana"
+
+#: option.c:3457
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: Niedozwolone w modeline"
+
+#: option.c:3522
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tOstatnie ustawienie przez "
+
+#: option.c:3661
+msgid "E521: Number required after ="
+msgstr "E521: Po = wymagany jest numer"
+
+#: option.c:3989 option.c:4619
+msgid "E522: Not found in termcap"
+msgstr "E522: Nie znaleziono w termcap"
+
+#: option.c:4064
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: Niedozwolony znak <%s>"
+
+#: option.c:4611
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: Nie mogê ustawiæ 'term' na pusty ci¹g"
+
+#: option.c:4614
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: Nie mogê zmieniæ term w GUI"
+
+#: option.c:4616
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: U¿yj \":gui\" do odpalenia GUI"
+
+#: option.c:4645
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: 'backupext' i 'patchmode' s¹ to¿same"
+
+#: option.c:4860
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: Nie mogê zmieniæ w GTK+2 GUI"
+
+#: option.c:5016
+msgid "E524: Missing colon"
+msgstr "E524: Brak dwukropka"
+
+#: option.c:5018
+msgid "E525: Zero length string"
+msgstr "E525: Ci¹g o zerowej d³ugoœci"
+
+#: option.c:5086
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: Brak numeru po <%s>"
+
+#: option.c:5100
+msgid "E527: Missing comma"
+msgstr "E527: Brak przecinka"
+
+#: option.c:5107
+msgid "E528: Must specify a ' value"
+msgstr "E528: Musi okreœlaæ wartoœæ '"
+
+#: option.c:5148
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: zawiera niewyœwietlalny lub szeroki znak"
+
+#: option.c:5197
+msgid "E596: Invalid font(s)"
+msgstr "E596: Niedozwolona czcionka/ki"
+
+#: option.c:5205
+msgid "E597: can't select fontset"
+msgstr "E597: nie mogê wybraæ zestawu czcionek"
+
+#: option.c:5207
+msgid "E598: Invalid fontset"
+msgstr "E598: Niedozwolony zestaw czcionek"
+
+#: option.c:5214
+msgid "E533: can't select wide font"
+msgstr "E533: nie mogê wybraæ szerokiej czcionki"
+
+#: option.c:5216
+msgid "E534: Invalid wide font"
+msgstr "E534: Niedozwolona szeroka czcionka"
+
+#: option.c:5486
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: Niedozwolony znak po <%c>"
+
+#: option.c:5597
+msgid "E536: comma required"
+msgstr "E536: wymagany przecinek"
+
+#: option.c:5607
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: 'commentstring' musi byæ pusty lub zawieraæ %s"
+
+#: option.c:5679
+msgid "E538: No mouse support"
+msgstr "E538: Brak wspomagania myszki"
+
+#: option.c:5947
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: Niedomkniêty ci¹g wyra¿eñ"
+
+#: option.c:5951
+msgid "E541: too many items"
+msgstr "E541: zbyt wiele elementów"
+
+#: option.c:5953
+msgid "E542: unbalanced groups"
+msgstr "E542: niezbalansowane grupy"
+
+#: option.c:6193
+msgid "E590: A preview window already exists"
+msgstr "E590: okno podgl¹du ju¿ istnieje"
+
+#: option.c:6450
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr "W17: Arabski wymaga UTF-8, zrób ':set encoding=utf-8'"
+
+#: option.c:6783
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: Potrzebujê przynajmniej %d wierszy"
+
+#: option.c:6793
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: Potrzebujê przynajmniej %d kolumn"
+
+#: option.c:7100
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Nieznana opcja: %s"
+
+#: option.c:7220
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Kody terminala ---"
+
+#: option.c:7222
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Globalne wartoœci opcji ---"
+
+#: option.c:7224
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Lokalne wartoœci opcji ---"
+
+#: option.c:7226
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Opcje ---"
+
+#: option.c:7932
+msgid "E356: get_varp ERROR"
+msgstr "E356: B£¥D get_varp"
+
+#: option.c:8903
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': Brak pasuj¹cego znaku dla %s"
+
+#: option.c:8937
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': Dodatkowe znaki po œredniku: %s"
+
+#: os_amiga.c:280
+msgid "cannot open "
+msgstr "nie mogê otworzyæ "
+
+#: os_amiga.c:314
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Nie mogê otworzyæ okna!\n"
+
+#: os_amiga.c:338
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Potrzebujê Amigados w wersji 2.04 lub póŸniejsz¹\n"
+
+#: os_amiga.c:344
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Potrzebujê %s w wersji %ld\n"
+
+#: os_amiga.c:416
+msgid "Cannot open NIL:\n"
+msgstr "Nie mogê otworzyæ NIL:\n"
+
+#: os_amiga.c:427
+msgid "Cannot create "
+msgstr "Nie mogê stworzyæ "
+
+#: os_amiga.c:905
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim koñczy pracê z %d\n"
+
+#: os_amiga.c:937
+msgid "cannot change console mode ?!\n"
+msgstr "nie mogê zmieniæ trybu konsoli ?!\n"
+
+#: os_amiga.c:1003
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: nie jest konsol¹??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1152
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Nie mogê wykonaæ pow³oki z opcj¹ -f"
+
+#: os_amiga.c:1193 os_amiga.c:1283
+msgid "Cannot execute "
+msgstr "Nie mogê wykonaæ "
+
+#: os_amiga.c:1196 os_amiga.c:1293
+msgid "shell "
+msgstr "pow³oka "
+
+#: os_amiga.c:1216 os_amiga.c:1318
+msgid " returned\n"
+msgstr " zwróci³\n"
+
+#: os_amiga.c:1459
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE zbyt niskie."
+
+#: os_amiga.c:1463
+msgid "I/O ERROR"
+msgstr "B£¥D I/O"
+
+#: os_mswin.c:539
+msgid "...(truncated)"
+msgstr "...(obciêty)"
+
+#: os_mswin.c:641
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' nie wynosi 80, nie mogê wykonaæ zewnêtrznych komend"
+
+#: os_mswin.c:1973
+msgid "E237: Printer selection failed"
+msgstr "E237: Wybór drukarki nie powiód³ siê"
+
+#: os_mswin.c:2013
+#, c-format
+msgid "to %s on %s"
+msgstr "do %s z %s"
+
+#: os_mswin.c:2028
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: Nieznana czcionka drukarki: %s"
+
+#: os_mswin.c:2077 os_mswin.c:2087
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: B³¹d drukarki: %s"
+
+#: os_mswin.c:2088
+msgid "Unknown"
+msgstr "Nieznane"
+
+#: os_mswin.c:2115
+#, c-format
+msgid "Printing '%s'"
+msgstr "Wydrukowano '%s'"
+
+#: os_mswin.c:3204
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Niedozwolona nazwa zestawu znaków \"%s\" w nazwie czcionki \"%s\""
+
+#: os_mswin.c:3212
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Niedozwolony znak '%c' w nazwie czcionki \"%s\""
+
+#: os_riscos.c:1259
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Niew³aœciwa opcja 'osfiletype' - u¿ywam Text"
+
+#: os_unix.c:927
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: Podwójny sygna³, wychodzê\n"
+
+#: os_unix.c:933
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Za³apa³ œmiertelny sygna³ %s\n"
+
+#: os_unix.c:936
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Za³apa³ œmiertelny sygna³\n"
+
+#: os_unix.c:1199
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Otwieranie ekranu X trwa³o %ld msec"
+
+#: os_unix.c:1226
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: Dosta³ b³¹d X\n"
+
+#: os_unix.c:1334
+msgid "Testing the X display failed"
+msgstr "Test ekranu X nie powiód³ siê"
+
+#: os_unix.c:1473
+msgid "Opening the X display timed out"
+msgstr "Próba otwarcia ekranu X trwa³a zbyt d³ugo"
+
+#: os_unix.c:3227 os_unix.c:3907
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"Nie mogê wykonaæ pow³oki "
+
+#: os_unix.c:3275
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Nie mogê wykonaæ pow³oki sh\n"
+
+#: os_unix.c:3279 os_unix.c:3913
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"pow³oka zwróci³a "
+
+#: os_unix.c:3414
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Nie mogê stworzyæ potoków\n"
+
+#: os_unix.c:3429
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"Nie mogê rozdzieliæ siê\n"
+
+#: os_unix.c:3920
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Komenda zakoñczona\n"
+
+#: os_unix.c:4184 os_unix.c:4309 os_unix.c:5975
+msgid "XSMP lost ICE connection"
+msgstr "XSMP straci³ po³¹czenie ICE"
+
+#: os_unix.c:5558
+msgid "Opening the X display failed"
+msgstr "Otwarcie ekranu X nie powiod³o siê"
+
+#: os_unix.c:5880
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP obs³uguje ¿¹danie samozapisu"
+
+#: os_unix.c:5999
+msgid "XSMP opening connection"
+msgstr "XSMP otwiera po³¹czenie"
+
+#: os_unix.c:6018
+msgid "XSMP ICE connection watch failed"
+msgstr "Obserwacja po³¹czenia XSMP ICE nie powiod³a siê"
+
+#: os_unix.c:6038
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP SmcOpenConnection nie powiod³o siê: %s"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "W wierszu"
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "Nie mogê zarezerwowaæ pamiêci dla linii poleceñ."
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "B³¹d VIM"
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "Nie mogê za³adowaæ vim32.dll!"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Nie zdo³a³em poprawiæ wskaŸników funkcji w DLL!"
+
+#: os_win16.c:342 os_win32.c:3197
+#, c-format
+msgid "shell returned %d"
+msgstr "pow³oka zwróci³a %d"
+
+#: os_win32.c:2655
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Za³apa³ wydarzenie %s\n"
+
+#: os_win32.c:2657
+msgid "close"
+msgstr "zamknij"
+
+#: os_win32.c:2659
+msgid "logoff"
+msgstr "wyloguj"
+
+#: os_win32.c:2660
+msgid "shutdown"
+msgstr "zakoñcz"
+
+#: os_win32.c:3150
+msgid "E371: Command not found"
+msgstr "E371: Nie znaleziono komendy"
+
+#: os_win32.c:3163
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE nie znaleziono w twoim $PATH.\n"
+"Zewnêtrzne komendy nie bêd¹ wstrzymane po wykonaniu.\n"
+"Patrz :help wim32-vimrun aby otrzymaæ wiêcej informacji."
+
+#: os_win32.c:3166
+msgid "Vim Warning"
+msgstr "Vim Ostrze¿enie"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Zbyt wiele %%%c w ci¹gu formatuj¹cym"
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: Nieoczekiwane %%%c w ci¹gu formatuj¹cym"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: Brak ] w ci¹gu formatuj¹cym"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: Niewspomagane %%%c w ci¹gu formatuj¹cym"
+
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: Niepoprawne %%%c w prefiksie ci¹gu formatuj¹cego"
+
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: Niepoprawne %%%c w ci¹gu formatuj¹cym"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' nie zawiera wzorca"
+
+#: quickfix.c:501
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Pusta nazwa katalogu lub jej brak"
+
+#: quickfix.c:990
+msgid "E553: No more items"
+msgstr "E553: Nie ma wiêcej elementów"
+
+#: quickfix.c:1229
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d z %d)%s%s: "
+
+#: quickfix.c:1231
+msgid " (line deleted)"
+msgstr " (wiersz skasowany)"
+
+#: quickfix.c:1444
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Na dole stosu quickfix"
+
+#: quickfix.c:1453
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Na górze stosu quickfix"
+
+#: quickfix.c:1465
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "lista b³êdów %d z %d; %d b³êdów"
+
+#: quickfix.c:1943
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: Nie mogê zapisaæ, opcja 'buftype' jest ustawiona"
+
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: Niew³aœciwy element w %s%%[]"
+
+#: regexp.c:840
+msgid "E339: Pattern too long"
+msgstr "E339: Zbyt d³ugi wzorzec"
+
+#: regexp.c:1011
+msgid "E50: Too many \\z("
+msgstr "E50: Zbyt wiele \\z("
+
+#: regexp.c:1022
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: Zbyt wiele %s("
+
+#: regexp.c:1079
+msgid "E52: Unmatched \\z("
+msgstr "E52: Niesparowany \\z("
+
+#: regexp.c:1083
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: Niesparowany %s%%("
+
+#: regexp.c:1085
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: Niesparowany %s("
+
+#: regexp.c:1090
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: Niesparowany %s)"
+
+#: regexp.c:1260
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: operand %s* móg³ byæ pusty"
+
+#: regexp.c:1263
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: operand %s+ móg³ byæ pusty"
+
+#: regexp.c:1318
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: niedozwolony znak po %s@"
+
+#: regexp.c:1346
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: operand %s{ móg³ byæ pusty"
+
+#: regexp.c:1356
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: Zbyt wiele z³o¿onych %s{...}"
+
+#: regexp.c:1372
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: Zagnie¿d¿one %s*"
+
+#: regexp.c:1375
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: Zagnie¿d¿one %s%c"
+
+#: regexp.c:1493
+msgid "E63: invalid use of \\_"
+msgstr "E63: Niedozwolone u¿ycie \\_"
+
+#: regexp.c:1538
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c po niczym"
+
+#: regexp.c:1594
+msgid "E65: Illegal back reference"
+msgstr "E65: Niew³aœciwe odwo³anie wsteczne"
+
+#: regexp.c:1607
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z( jest niedozwolone w tym miejscu"
+
+#: regexp.c:1626
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 i podobne s¹ niedozwolone w tym miejscu"
+
+#: regexp.c:1637
+msgid "E68: Invalid character after \\z"
+msgstr "E68: niedopuszczalny znak po \\z"
+
+#: regexp.c:1686
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: Brak ] po %s%%["
+
+#: regexp.c:1702
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: Pusty %s%%[]"
+
+#: regexp.c:1762
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: Niedozwolony znak po %s%%"
+
+#: regexp.c:2559
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: B³¹d sk³adni w %s{...}"
+
+#: regexp.c:2865 regexp.c:3018
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Przechwycono za³amanie; regexp zbyt z³o¿ony?"
+
+#: regexp.c:3006 regexp.c:3015
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: wzorzec spowodowa³ b³¹d out-of-stack"
+
+#: regexp.c:3260
+msgid "External submatches:\n"
+msgstr "Zewnêtrzne poddopasowania:\n"
+
+#: screen.c:2184
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld wierszy zwiniêto "
+
+#: screen.c:7996
+msgid " VREPLACE"
+msgstr " V-ZAMIANA"
+
+#: screen.c:8000
+msgid " REPLACE"
+msgstr " ZAMIANA"
+
+#: screen.c:8005
+msgid " REVERSE"
+msgstr " NEGATYW"
+
+#: screen.c:8007
+msgid " INSERT"
+msgstr " WPROWADZANIE"
+
+#: screen.c:8010
+msgid " (insert)"
+msgstr " (wprowadzanie)"
+
+#: screen.c:8012
+msgid " (replace)"
+msgstr " (zamiana)"
+
+#: screen.c:8014
+msgid " (vreplace)"
+msgstr " (v-zamiana)"
+
+#: screen.c:8017
+msgid " Hebrew"
+msgstr " Hebrajski"
+
+#: screen.c:8028
+msgid " Arabic"
+msgstr " Arabski"
+
+#: screen.c:8031
+msgid " (lang)"
+msgstr " (jêzyk)"
+
+#: screen.c:8035
+msgid " (paste)"
+msgstr " (wklejanie)"
+
+#: screen.c:8048
+msgid " VISUAL"
+msgstr " WIZUALNY"
+
+#: screen.c:8049
+msgid " VISUAL LINE"
+msgstr " WIZUALNY LINIOWY"
+
+#: screen.c:8050
+msgid " VISUAL BLOCK"
+msgstr " WIZUALNY BLOKOWY"
+
+#: screen.c:8051
+msgid " SELECT"
+msgstr " ZAZNACZANIE"
+
+#: screen.c:8052
+msgid " SELECT LINE"
+msgstr " ZAZNACZANIE LINIOWE"
+
+#: screen.c:8053
+msgid " SELECT BLOCK"
+msgstr " ZAZNACZANIE BLOKOWE"
+
+#: screen.c:8068 screen.c:8131
+msgid "recording"
+msgstr "zapis"
+
+#: search.c:37
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "szukanie dobi³o GÓRY; kontynuacja od KOÑCA"
+
+#: search.c:38
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "szukanie dobi³o KOÑCA; kontynuacja od GÓRY"
+
+#: search.c:526
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Niew³aœciwy ci¹g do szukania: %s"
+
+#: search.c:853
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: szukanie dobi³o GÓRY bez znalezienia: %s"
+
+#: search.c:856
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: szukanie dobi³o KOÑCA bez znalezienia : %s"
+
+#: search.c:1249
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: Oczekujê '?' lub '/' po ';'"
+
+#: search.c:3758
+msgid " (includes previously listed match)"
+msgstr " (zawiera poprzednio wymienione dopasowanie)"
+
+#. cursor at status line
+#: search.c:3778
+msgid "--- Included files "
+msgstr "--- Zawarte pliki "
+
+#: search.c:3780
+msgid "not found "
+msgstr "nie znaleziono"
+
+#: search.c:3781
+msgid "in path ---\n"
+msgstr "w tropie ---\n"
+
+#: search.c:3820
+msgid " (Already listed)"
+msgstr " (Ju¿ wymienione)"
+
+#: search.c:3822
+msgid " NOT FOUND"
+msgstr " NIE ZNALEZIONO"
+
+#: search.c:3874
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Przegl¹d w³¹czonego pliku: %s"
+
+#: search.c:4092
+msgid "E387: Match is on current line"
+msgstr "E387: Wzorzec pasuje w bie¿¹cym wierszu"
+
+#: search.c:4235
+msgid "All included files were found"
+msgstr "Wszelkie w³¹czane pliki odnaleziono"
+
+#: search.c:4237
+msgid "No included files"
+msgstr "Brak w³¹czanych plików"
+
+#: search.c:4253
+msgid "E388: Couldn't find definition"
+msgstr "E388: Nie znalaz³em definicji"
+
+#: search.c:4255
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Nie znalaz³em wzorca"
+
+#: syntax.c:3050
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: Niedozwolony argument: %s"
+
+#: syntax.c:3230
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: Nie ma takiego klastra sk³adni: %s"
+
+#: syntax.c:3394
+msgid "No Syntax items defined for this buffer"
+msgstr "Brak elementów sk³adni okreœlonych dla tego bufora"
+
+#: syntax.c:3402
+msgid "syncing on C-style comments"
+msgstr "synchronizacja komentarzy w stylu C"
+
+#: syntax.c:3410
+msgid "no syncing"
+msgstr "brak synchronizacji"
+
+#: syntax.c:3413
+msgid "syncing starts "
+msgstr "pocz¹tek synchronizacji"
+
+#: syntax.c:3415 syntax.c:3490
+msgid " lines before top line"
+msgstr " wierszy przed górn¹ lini¹"
+
+#: syntax.c:3420
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Elementy synchronizacji sk³adni ---"
+
+#: syntax.c:3425
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"synchronizujê na elementach"
+
+#: syntax.c:3431
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Elementy sk³adni ---"
+
+#: syntax.c:3454
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: Nie ma takiego klastra sk³adni: %s"
+
+#: syntax.c:3480
+msgid "minimal "
+msgstr "minimalnie "
+
+#: syntax.c:3487
+msgid "maximal "
+msgstr "maksymalnie "
+
+#: syntax.c:3499
+msgid "; match "
+msgstr "; pasuje "
+
+#: syntax.c:3501
+msgid " line breaks"
+msgstr "znaków nowego wiersza"
+
+#: syntax.c:4135
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: group[t]here niedozwolone w tym miejscu"
+
+#: syntax.c:4159
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: Nie znalaz³em elementów regionu dla %s"
+
+#: syntax.c:4187
+msgid "E395: contains argument not accepted here"
+msgstr "E395: argument contains niedozwolony w tym miejscu"
+
+#: syntax.c:4198
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: argument containedin niedozwolony w tym miejscu"
+
+#: syntax.c:4276
+msgid "E397: Filename required"
+msgstr "E397: Wymagana nazwa pliku"
+
+#: syntax.c:4614
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Brak '=': %s"
+
+#: syntax.c:4772
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Za ma³o argumentów: syntax region %s"
+
+#: syntax.c:5103
+msgid "E400: No cluster specified"
+msgstr "E400: Brak specyfikacji klastra"
+
+#: syntax.c:5140
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Brak ogranicznika wzorca: %s"
+
+#: syntax.c:5215
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Œmieci po wzorcu: %s"
+
+#: syntax.c:5305
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: syntax sync: wielokrotnie podane wzorce kontynuacji wiersza"
+
+#: syntax.c:5362
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Niedozwolone argumenty: %s"
+
+#: syntax.c:5412
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Brak znaku równoœci: %s"
+
+#: syntax.c:5418
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Pusty argument: %s"
+
+#: syntax.c:5445
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s jest niedozwolone w tym miejscu"
+
+#: syntax.c:5452
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s musi byæ pierwsze w liœcie contains"
+
+#: syntax.c:5522
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Nieznana nazwa grupy: %s"
+
+#: syntax.c:5755
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Niew³aœciwa podkomenda :syntax : %s"
+
+#: syntax.c:6136
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: nie znaleziono grupy podœwietlania: %s"
+
+#: syntax.c:6160
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Zbyt ma³o argumentów: \":highlight link %s\""
+
+#: syntax.c:6167
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: Zbyt wiele argumentów: \":highlight link %s\""
+
+#: syntax.c:6187
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: grupa ma ustawienia; zignorowane pod³¹czenie podœwietlania"
+
+#: syntax.c:6316
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: nieoczekiwany znak równoœci: %s"
+
+#: syntax.c:6352
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: brak znaku równoœci: %s"
+
+#: syntax.c:6380
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: brak argumentu: %s"
+
+#: syntax.c:6417
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: Niedozwolona wartoϾ: %s"
+
+#: syntax.c:6536
+msgid "E419: FG color unknown"
+msgstr "E419: Kolor FG nieznany"
+
+#: syntax.c:6547
+msgid "E420: BG color unknown"
+msgstr "E420: Kolor BG nieznany"
+
+#: syntax.c:6608
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Nazwa lub liczba koloru nierozpoznana: %s"
+
+#: syntax.c:6814
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: za d³ugi kod terminala: %s"
+
+#: syntax.c:6861
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: Niedozwolony argument: %s"
+
+#: syntax.c:7390
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: Zbyt wiele ró¿nych atrybutów podkreœlania w u¿yciu"
+
+#: syntax.c:7911
+msgid "E669: Unprintable character in group name"
+msgstr "E669: Niedrukowalny znak w nazwie grupy"
+
+#. This is an error, but since there previously was no check only
+#. * give a warning.
+#: syntax.c:7918
+msgid "W18: Invalid character in group name"
+msgstr "W18: nieprawid³owy znak w nazwie grupy"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: na dole stosu znaczników"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: na górze stosu znaczników"
+
+#: tag.c:412
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Nie mo¿na przejœæ przed pierwszy pasuj¹cy znacznik"
+
+#: tag.c:550
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: nie znaleziono znacznika: %s"
+
+#: tag.c:583
+msgid " # pri kind tag"
+msgstr " # pri rodzaj znacznik"
+
+#: tag.c:586
+msgid "file\n"
+msgstr "plik\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:744
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "WprowadŸ nr wyboru (<CR> przerywa): "
+
+#: tag.c:784
+msgid "E427: There is only one matching tag"
+msgstr "E427: Pasuje tylko jeden znacznik"
+
+#: tag.c:786
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Nie mo¿na przejœæ za ostatni pasuj¹cy znacznik"
+
+#: tag.c:810
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Plik \"%s\" nie istnieje"
+
+#. Give an indication of the number of matching tags
+#: tag.c:823
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "znacznik %d z %d%s"
+
+#: tag.c:826
+msgid " or more"
+msgstr " lub wiêcej"
+
+#: tag.c:828
+msgid " Using tag with different case!"
+msgstr " U¿ywam znacznika o odmiennej wielkoœci liter!"
+
+#: tag.c:872
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Plik \"%s\" nie istnieje"
+
+#. Highlight title
+#: tag.c:941
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # DO znacznik OD wiersza w pliku/tekœcie"
+
+#: tag.c:1363
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Szukam w pliku znaczników %s"
+
+#: tag.c:1550
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Trop szukania pliku znaczników obciêty dla %s\n"
+
+#: tag.c:2203
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: B³¹d formatu w pliku znaczników \"%s\""
+
+#: tag.c:2207
+#, c-format
+msgid "Before byte %ld"
+msgstr "Przed bajtem %ld"
+
+#: tag.c:2240
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Plik znaczników nieuporz¹dkowany: %s"
+
+#. never opened any tags file
+#: tag.c:2280
+msgid "E433: No tags file"
+msgstr "E433: Brak pliku znaczników"
+
+#: tag.c:3016
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Nie mogê znaleŸæ wzorca znacznika"
+
+#: tag.c:3027
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Nie znalaz³em znacznika - tylko zgadujê!"
+
+#: term.c:1759
+msgid "' not known. Available builtin terminals are:"
+msgstr "' nieznany. Mo¿liwe typy wbudowanych terminali:"
+
+#: term.c:1783
+msgid "defaulting to '"
+msgstr "domyœlnie jest '"
+
+#: term.c:2141
+msgid "E557: Cannot open termcap file"
+msgstr "E557: Nie mogê otworzyæ pliku termcap"
+
+#: term.c:2145
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: Nie ma opisu takiego terminala w terminfo"
+
+#: term.c:2147
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: Nie ma opisu takiego terminala w termcap"
+
+#: term.c:2306
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Brak opisu \"%s\" w termcap"
+
+#: term.c:2780
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: wymagana zdolnoϾ \"cm\" terminala"
+
+#. Highlight title
+#: term.c:4990
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Klawisze terminala ---"
+
+#: ui.c:258
+msgid "new shell started\n"
+msgstr "uruchomiono now¹ pow³okê\n"
+
+#: ui.c:1841
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: B³¹d podczas wczytywania wejœcia, koñczê...\n"
+
+#. must display the prompt
+#: undo.c:405
+msgid "No undo possible; continue anyway"
+msgstr "Cofniêcie niemo¿liwe; mimo to kontynuujê"
+
+#: undo.c:561
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: niew³aœciwe numery wierszy"
+
+#: undo.c:757
+msgid "1 change"
+msgstr "1 zmiana"
+
+#: undo.c:759
+#, c-format
+msgid "%ld changes"
+msgstr "%ld zmian"
+
+#: undo.c:812
+msgid "E439: undo list corrupt"
+msgstr "E439: uszkodzona lista cofania"
+
+#: undo.c:844
+msgid "E440: undo line missing"
+msgstr "E440: brak wiersza cofania"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:1769
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"16/32 bitowa wersja GUI dla MS-Windows"
+
+#: version.c:1771
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"32 bitowa wersja GUI dla MS-Windows"
+
+#: version.c:1774
+msgid " in Win32s mode"
+msgstr " w trybie Win32s"
+
+#: version.c:1776
+msgid " with OLE support"
+msgstr " ze wspomaganiem OLE"
+
+#: version.c:1779
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"32 bitowa wersja na konsolê dla MS-Windows"
+
+#: version.c:1783
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"16 bitowa wersja dla MS-Windows"
+
+#: version.c:1787
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 bitowa wersja dla MS-DOS"
+
+#: version.c:1789
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 bitowa wersja dla MS-DOS"
+
+#: version.c:1795
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"wersja dla MacOS X (unix)"
+
+#: version.c:1797
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"wersja dla MacOS X"
+
+#: version.c:1800
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"wersja dla MacOS"
+
+#: version.c:1805
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"wersja dla RISC OS"
+
+#: version.c:1815
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Zadane ³aty: "
+
+#: version.c:1841 version.c:2209
+msgid "Modified by "
+msgstr "Zmieniony przez "
+
+#: version.c:1848
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Skompilowany "
+
+#: version.c:1851
+msgid "by "
+msgstr "przez "
+
+#: version.c:1863
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Olbrzymia wersja "
+
+#: version.c:1866
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Du¿a wersja "
+
+#: version.c:1869
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Normalna wersja "
+
+#: version.c:1872
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Ma³a wersja "
+
+#: version.c:1874
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Malutka wersja "
+
+#: version.c:1880
+msgid "without GUI."
+msgstr "bez GUI."
+
+#: version.c:1885
+msgid "with GTK2-GNOME GUI."
+msgstr "z GTK2-GNOME GUI."
+
+#: version.c:1887
+msgid "with GTK-GNOME GUI."
+msgstr "z GTK-GNOME GUI."
+
+#: version.c:1891
+msgid "with GTK2 GUI."
+msgstr "z GTK2 GUI."
+
+#: version.c:1893
+msgid "with GTK GUI."
+msgstr "z GTK GUI."
+
+#: version.c:1898
+msgid "with X11-Motif GUI."
+msgstr "z X11-Motif GUI."
+
+#: version.c:1902
+msgid "with X11-neXtaw GUI."
+msgstr "z X11-neXtaw GUI."
+
+#: version.c:1904
+msgid "with X11-Athena GUI."
+msgstr "z X11-Athena GUI."
+
+#: version.c:1908
+msgid "with BeOS GUI."
+msgstr "z BeOS GUI."
+
+#: version.c:1911
+msgid "with Photon GUI."
+msgstr "z Photon GUI."
+
+#: version.c:1914
+msgid "with GUI."
+msgstr "z GUI."
+
+#: version.c:1917
+msgid "with Carbon GUI."
+msgstr "z Carbon GUI."
+
+#: version.c:1920
+msgid "with Cocoa GUI."
+msgstr "z Cocoa GUI."
+
+#: version.c:1923
+msgid "with (classic) GUI."
+msgstr "z (klasycznym) GUI."
+
+#: version.c:1934
+msgid " Features included (+) or not (-):\n"
+msgstr " Opcje w³¹czone (+) lub nie (-):\n"
+
+#: version.c:1946
+msgid " system vimrc file: \""
+msgstr " vimrc systemu: \""
+
+#: version.c:1951
+msgid " user vimrc file: \""
+msgstr " vimrc u¿ytkownika: \""
+
+#: version.c:1956
+msgid " 2nd user vimrc file: \""
+msgstr " 2-gi plik vimrc u¿ytkownika: \""
+
+#: version.c:1961
+msgid " 3rd user vimrc file: \""
+msgstr " 3-ci plik vimrc u¿ytkownika: \""
+
+#: version.c:1966
+msgid " user exrc file: \""
+msgstr " exrc u¿ytkownika: \""
+
+#: version.c:1971
+msgid " 2nd user exrc file: \""
+msgstr " 2-gi plik exrc u¿ytkownika: \""
+
+#: version.c:1977
+msgid " system gvimrc file: \""
+msgstr " gvimrc systemu: \""
+
+#: version.c:1981
+msgid " user gvimrc file: \""
+msgstr " gvimrc u¿ytkownika: \""
+
+#: version.c:1985
+msgid "2nd user gvimrc file: \""
+msgstr "2-gi plik gvimrc u¿ytkownika: \""
+
+#: version.c:1990
+msgid "3rd user gvimrc file: \""
+msgstr "3-ci plik gvimrc u¿ytkownika: \""
+
+#: version.c:1997
+msgid " system menu file: \""
+msgstr " systemowy plik menu: \""
+
+#: version.c:2005
+msgid " fall-back for $VIM: \""
+msgstr " odwet dla $VIM-a: \""
+
+#: version.c:2011
+msgid " f-b for $VIMRUNTIME: \""
+msgstr "f-b dla $VIMRUNTIME: \""
+
+#: version.c:2015
+msgid "Compilation: "
+msgstr "Kompilacja: "
+
+#: version.c:2021
+msgid "Compiler: "
+msgstr "Kompilator: "
+
+#: version.c:2026
+msgid "Linking: "
+msgstr "Konsolidacja: "
+
+#: version.c:2031
+msgid " DEBUG BUILD"
+msgstr " KOMPILACJA DEBUG"
+
+#: version.c:2070
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi rozbudowany"
+
+#: version.c:2072
+msgid "version "
+msgstr "wersja "
+
+#: version.c:2073
+msgid "by Bram Moolenaar et al."
+msgstr "Autor: Bram Moolenaar i Inni."
+
+#: version.c:2077
+msgid "Vim is open source and freely distributable"
+msgstr "Vim jest open source i rozprowadzany darmowo"
+
+#: version.c:2079
+msgid "Help poor children in Uganda!"
+msgstr "Pomó¿ biednym dzieciom w Ugandzie!"
+
+#: version.c:2080
+msgid "type :help iccf<Enter> for information "
+msgstr "wprowadŸ :help iccf<Enter> dla informacji o tym "
+
+#: version.c:2082
+msgid "type :q<Enter> to exit "
+msgstr "wprowadŸ :q<Enter> zakoñczenie programu "
+
+#: version.c:2083
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "wprowadŸ :help<Enter> lub <F1> pomoc na bie¿¹co "
+
+#: version.c:2084
+msgid "type :help version6<Enter> for version info"
+msgstr "wprowadŸ :help version6<Enter> dla informacji o wersji"
+
+#: version.c:2087
+msgid "Running in Vi compatible mode"
+msgstr "Dzia³am w trybie zgodnoœci z Vi"
+
+#: version.c:2088
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "wprowadŸ :set nocp<Enter> wartoœci domyœlne Vim-a"
+
+#: version.c:2089
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "wprowadŸ :help cp-default<Enter> dla informacji to tym "
+
+#: version.c:2104
+msgid "menu Help->Orphans for information "
+msgstr "wprowadŸ :help iccf<Enter> dla informacji to tym "
+
+#: version.c:2106
+msgid "Running modeless, typed text is inserted"
+msgstr "Uruchomiony bez trybów, wpisany tekst jest wprowadzany"
+
+#: version.c:2107
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "menu Edytuj->Ustawienia globalne->Tryb wstawiania"
+
+#: version.c:2108
+msgid " for two modes "
+msgstr " dla dwóch trybów "
+
+#: version.c:2112
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "menu Edytuj->Ustawienia globalne->KompatybilnoϾ z Vi"
+
+#: version.c:2113
+msgid " for Vim defaults "
+msgstr " dla domyœlnych ustawieñ Vima "
+
+#: version.c:2160
+msgid "Sponsor Vim development!"
+msgstr "Sponsoruj rozwój Vima!"
+
+#: version.c:2161
+msgid "Become a registered Vim user!"
+msgstr "Zostañ zarejestrowanym u¿ytkownikiem Vima!"
+
+#: version.c:2164
+msgid "type :help sponsor<Enter> for information "
+msgstr "wprowadŸ :help sponsor<Enter> dla informacji"
+
+#: version.c:2165
+msgid "type :help register<Enter> for information "
+msgstr "wprowadŸ :help register<Enter> dla informacji"
+
+#: version.c:2167
+msgid "menu Help->Sponsor/Register for information "
+msgstr "menu Pomoc->Sponsoruj/Zarejestruj siê dla informacji"
+
+#: version.c:2177
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "OSTRZE¯ENIE: wykryto Windows 95/98/ME"
+
+#: version.c:2180
+msgid "type :help windows95<Enter> for info on this"
+msgstr "wprowadŸ :help windows95<Enter> dla informacji to tym "
+
+#: window.c:203
+msgid "E441: There is no preview window"
+msgstr "E441: Nie ma okna podgl¹du"
+
+#: window.c:581
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: Nie mogê rozdzieliæ lewo-górnego i prawo-dolnego jednoczeœnie"
+
+#: window.c:1340
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Nie mogê przekrêciæ, gdy inne okno jest rozdzielone"
+
+#: window.c:1836
+msgid "E444: Cannot close last window"
+msgstr "E444: Nie mogê zamkn¹æ ostatniego okna"
+
+#: window.c:2567
+msgid "Already only one window"
+msgstr "Ju¿ jest tylko jeden widok"
+
+#: window.c:2614
+msgid "E445: Other window contains changes"
+msgstr "E445: Inne okno zawiera zmiany"
+
+#: window.c:4480
+msgid "E446: No file name under cursor"
+msgstr "E446: Brak nazwy pliku pod kursorem"
+
+#: window.c:4599
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Nie mogê znaleŸæ pliku \"%s\" w tropie"
+
+#: if_perl.xs:326 globals.h:1232
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: Nie mog³em za³adowaæ biblioteki %s"
+
+#: if_perl.xs:554
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr "Przykro mi, ta komenda jest wy³¹czona: nie mog³em za³adowaæ biblioteki Perla."
+
+#: if_perl.xs:607
+msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+msgstr "E299: wyliczenie Perla zabronione w piaskownicy bez modu³u Safe"
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "Edytuj w &wielu Vimach"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "Edytuj w pojedynczym &Vimie"
+
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "&Diff z Vimem"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "Edytuj w &Vimie"
+
+#. Now concatenate
+#: GvimExt/gvimext.cpp:633
+msgid "Edit with existing Vim - &"
+msgstr "Edytuj z istniej¹cym Vimem - &"
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "Edytuj wybrane pliki w Vimie"
+
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "B³¹d tworzenia procesu: SprawdŸ czy gvim jest w twojej œcie¿ce!"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "b³¹d gvimext.dll"
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "Za d³uga œcie¿ka!"
+
+#: globals.h:1022
+msgid "--No lines in buffer--"
+msgstr "--Brak wierszy w buforze--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1185
+msgid "E470: Command aborted"
+msgstr "E470: Przerwanie komendy"
+
+#: globals.h:1186
+msgid "E471: Argument required"
+msgstr "E471: wymagany argument"
+
+#: globals.h:1187
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: po \\ powinno byæ /, ? lub &"
+
+#: globals.h:1189
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: Niedozwolone w oknie wiersza poleceñ; <CR> wykonuje, CTRL-C opuszcza"
+
+#: globals.h:1191
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Komenda niedozwolona z exrc/vimrc w bie¿¹cym szukaniu katalogu lub "
+"znacznika"
+
+#: globals.h:1193
+msgid "E171: Missing :endif"
+msgstr "E171: Brak :endif"
+
+#: globals.h:1194
+msgid "E600: Missing :endtry"
+msgstr "E600: Brak :endtry"
+
+#: globals.h:1195
+msgid "E170: Missing :endwhile"
+msgstr "E170: Brak :endwhile"
+
+#: globals.h:1196
+msgid "E588: :endwhile without :while"
+msgstr "E588: :endwhile bez :while"
+
+#: globals.h:1198
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Plik istnieje (wymuœ poprzez !)"
+
+#: globals.h:1199
+msgid "E472: Command failed"
+msgstr "E472: Komenda nie powiod³a siê"
+
+#: globals.h:1201
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Nieznany zestaw czcionek: %s"
+
+#: globals.h:1205
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Nieznana czcionka: %s"
+
+#: globals.h:1208
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: Czcionka \"%s\" nie ma sta³ej szerokoœci znaków"
+
+#: globals.h:1210
+msgid "E473: Internal error"
+msgstr "E473: B³¹d wewnêtrzny"
+
+#: globals.h:1211
+msgid "Interrupted"
+msgstr "Przerwane"
+
+#: globals.h:1212
+msgid "E14: Invalid address"
+msgstr "E14: Niew³aœciwy adres"
+
+#: globals.h:1213
+msgid "E474: Invalid argument"
+msgstr "E474: Niew³aœciwy argument"
+
+#: globals.h:1214
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: Niew³aœciwy argument: %s"
+
+#: globals.h:1216
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Niew³aœciwe wyra¿enie: %s"
+
+#: globals.h:1218
+msgid "E16: Invalid range"
+msgstr "E16: Niew³aœciwy zakres"
+
+#: globals.h:1219
+msgid "E476: Invalid command"
+msgstr "E476: Niew³aœciwa komenda"
+
+#: globals.h:1221
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" jest katalogiem"
+
+#: globals.h:1224
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Nieoczekiwane znaki przed '='"
+
+#: globals.h:1227
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Wywo³anie z biblioteki nie powiod³o siê dla \"%s()\""
+
+#: globals.h:1233
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: Nie mo¿na za³adowaæ funkcji biblioteki %s"
+
+#: globals.h:1235
+msgid "E19: Mark has invalid line number"
+msgstr "E19: Zak³adka ma niew³aœciwy numer wiersza"
+
+#: globals.h:1236
+msgid "E20: Mark not set"
+msgstr "E20: Zak³adka nienastawiona"
+
+#: globals.h:1237
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Nie mogê wykonaæ zmian, 'modifiable' jest wy³¹czone"
+
+#: globals.h:1238
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Zbyt g³êbokie zagnie¿d¿enie skryptów"
+
+#: globals.h:1239
+msgid "E23: No alternate file"
+msgstr "E23: Brak pliku zamiany"
+
+#: globals.h:1240
+msgid "E24: No such abbreviation"
+msgstr "E24: Nie ma takiego skrótu"
+
+#: globals.h:1241
+msgid "E477: No ! allowed"
+msgstr "E477: Niedozwolone !"
+
+#: globals.h:1243
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: GUI nie mo¿e byæ u¿yte: Nie w³¹czono podczas kompilacji"
+
+#: globals.h:1246
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: Hebrajski nie mo¿e byæ u¿yty: Nie w³¹czono podczas kompilacji\n"
+
+#: globals.h:1249
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: Farsi nie mo¿e byæ u¿yty: Nie w³¹czono podczas kompilacji\n"
+
+#: globals.h:1252
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: Arabski nie mo¿e byæ u¿yty: Nie w³¹czono podczas kompilacji\n"
+
+#: globals.h:1255
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Brak takiej nazwy grupy podœwietlania: %s"
+
+#: globals.h:1257
+msgid "E29: No inserted text yet"
+msgstr "E29: Nie wprowadzono jeszcze ¿adnego tekstu"
+
+#: globals.h:1258
+msgid "E30: No previous command line"
+msgstr "E30: Nie ma poprzedniego wiersza poleceñ"
+
+#: globals.h:1259
+msgid "E31: No such mapping"
+msgstr "E31: Nie ma takiego przyporz¹dkowania"
+
+#: globals.h:1260
+msgid "E479: No match"
+msgstr "E479: Brak dopasowañ"
+
+#: globals.h:1261
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: Brak dopasowañ: %s"
+
+#: globals.h:1262
+msgid "E32: No file name"
+msgstr "E32: Brak nazwy pliku"
+
+#: globals.h:1263
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: Brak poprzedniego podstawieniowego wyra¿enia regularnego"
+
+#: globals.h:1264
+msgid "E34: No previous command"
+msgstr "E34: Brak poprzedniej komendy"
+
+#: globals.h:1265
+msgid "E35: No previous regular expression"
+msgstr "E35: Brak poprzedniego wyra¿enia regularnego"
+
+#: globals.h:1266
+msgid "E481: No range allowed"
+msgstr "E481: Zakres niedozwolony"
+
+#: globals.h:1268
+msgid "E36: Not enough room"
+msgstr "E36: Brak miejsca"
+
+#: globals.h:1271
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: brak zarejestrowanego serwera o nazwie \"%s\""
+
+#: globals.h:1273
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: Nie mogê stworzyæ pliku %s"
+
+#: globals.h:1274
+msgid "E483: Can't get temp file name"
+msgstr "E483: Nie mogê pobraæ nazwy pliku tymczasowego"
+
+#: globals.h:1275
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: Nie mogê otworzyæ pliku %s"
+
+#: globals.h:1276
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: Nie mogê odczytaæ pliku %s"
+
+#: globals.h:1277
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: Nie zapisano od ostatniej zmiany (wymuœ przez !)"
+
+#: globals.h:1278
+msgid "E38: Null argument"
+msgstr "E38: Zerowy argument"
+
+#: globals.h:1280
+msgid "E39: Number expected"
+msgstr "E39: Oczekujê liczby"
+
+#: globals.h:1283
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Nie mogê otworzyæ pliku b³êdów %s"
+
+#: globals.h:1286
+msgid "E233: cannot open display"
+msgstr "E233: nie mogê otworzyæ ekranu"
+
+#: globals.h:1288
+msgid "E41: Out of memory!"
+msgstr "E41: Pamiêæ wyczerpana!"
+
+#: globals.h:1290
+msgid "Pattern not found"
+msgstr "Nie znaleziono wzorca"
+
+#: globals.h:1292
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: Nie znaleziono wzorca: %s"
+
+#: globals.h:1293
+msgid "E487: Argument must be positive"
+msgstr "E487: Argument musi byæ dodatni"
+
+#: globals.h:1295
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: Nie mo¿na przejœæ do poprzedniego katalogu"
+
+#: globals.h:1299
+msgid "E42: No Errors"
+msgstr "E42: Brak B³êdów"
+
+#: globals.h:1301
+msgid "E43: Damaged match string"
+msgstr "E43: Popsuty ci¹g wzorca"
+
+#: globals.h:1302
+msgid "E44: Corrupted regexp program"
+msgstr "E44: Zepsuty program wyra¿eñ regularnych"
+
+#: globals.h:1303
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: opcja 'readonly' jest ustawiona (wymuœ poprzez !)"
+
+#: globals.h:1305
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Nie mogê ustawiæ zmiennej tylko do odczytu \"%s\""
+
+#: globals.h:1308
+msgid "E47: Error while reading errorfile"
+msgstr "E47: B³¹d w trakcie czytania pliku b³êdów"
+
+#: globals.h:1311
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: Niedozwolone w piaskownicy"
+
+#: globals.h:1313
+msgid "E523: Not allowed here"
+msgstr "E523: Niedozwolone w tym miejscu"
+
+#: globals.h:1316
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Ustawianie trybu ekranu niewspomagane"
+
+#: globals.h:1318
+msgid "E49: Invalid scroll size"
+msgstr "E49: Niew³aœciwa wielkoœæ przewiniêcia"
+
+#: globals.h:1319
+msgid "E91: 'shell' option is empty"
+msgstr "E91: opcja 'shell' jest pusta"
+
+#: globals.h:1321
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Nie mog³em wczytaæ danych znaku!"
+
+#: globals.h:1323
+msgid "E72: Close error on swap file"
+msgstr "E72: B³¹d podczas zamykania pliku wymiany"
+
+#: globals.h:1324
+msgid "E73: tag stack empty"
+msgstr "E73: stos znaczników jest pusty"
+
+#: globals.h:1325
+msgid "E74: Command too complex"
+msgstr "E74: Komenda jest zbyt skomplikowana"
+
+#: globals.h:1326
+msgid "E75: Name too long"
+msgstr "E75: Zbyt d³uga nazwa"
+
+#: globals.h:1327
+msgid "E76: Too many ["
+msgstr "E76: Zbyt wiele ["
+
+#: globals.h:1328
+msgid "E77: Too many file names"
+msgstr "E77: Zbyt wiele nazw plików"
+
+#: globals.h:1329
+msgid "E488: Trailing characters"
+msgstr "E488: Nadstêpne znaczki"
+
+#: globals.h:1330
+msgid "E78: Unknown mark"
+msgstr "E78: Nieznana zak³adka"
+
+#: globals.h:1331
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Nie mog¹ rozwin¹æ znaków wieloznacznych"
+
+#: globals.h:1333
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: 'winheight' nie mo¿e byæ mniejsze ni¿ 'winminheight'"
+
+#: globals.h:1335
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: 'winwidth' nie mo¿e byæ mniejsze ni¿ 'winminwidth'"
+
+#: globals.h:1338
+msgid "E80: Error while writing"
+msgstr "E80: B³¹d w trakcie zapisu"
+
+#: globals.h:1339
+msgid "Zero count"
+msgstr "Zerowy licznik"
+
+#: globals.h:1341
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: U¿ycie <SID> poza kontekstem skryptu"
+
+#: globals.h:1344
+msgid "E449: Invalid expression received"
+msgstr "E449: Odebra³em niew³aœciwe wyra¿enie"
+
+#: globals.h:1347
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: Region jest chroniony, nie mogê zmieniæ"
+
diff --git a/src/po/pl.po b/src/po/pl.po
new file mode 100644
index 000000000..303d3344a
--- /dev/null
+++ b/src/po/pl.po
@@ -0,0 +1,6576 @@
+# translation of pl.po to Polish
+# Polish Translation for Vim
+#
+# updated 2001 for vim-6.0
+# FIRST AUTHOR Marcin Dalecki <dalecki@cyber.cs.net.pl>, 2000.
+# Mikolaj Machowski <mikmach@wp.pl>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pl\n"
+"POT-Creation-Date: 2004-05-23 21:41+0200\n"
+"PO-Revision-Date: 2004-05-23 22:00+0200\n"
+"Last-Translator: Mikolaj Machowski <mikmach@wp.pl>\n"
+"Language-Team: Polish <pl@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-2\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.9\n"
+
+#: buffer.c:102
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Nie mogê zarezerwowaæ bufora; zakoñczenie..."
+
+#: buffer.c:105
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: Nie mogê zarezerwowaæ bufora; u¿ywam innego..."
+
+#: buffer.c:805
+msgid "E515: No buffers were unloaded"
+msgstr "E515: Nie wy³adowano ¿adnego bufora"
+
+#: buffer.c:807
+msgid "E516: No buffers were deleted"
+msgstr "E516: Nie skasowano ¿adnego bufora"
+
+#: buffer.c:809
+msgid "E517: No buffers were wiped out"
+msgstr "E517: Nie wyrzucono ¿adnego bufora"
+
+#: buffer.c:817
+msgid "1 buffer unloaded"
+msgstr "1 bufor wy³adowany"
+
+#: buffer.c:819
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "wy³adowano %d buforów"
+
+#: buffer.c:824
+msgid "1 buffer deleted"
+msgstr "1 bufor skasowany"
+
+#: buffer.c:826
+#, c-format
+msgid "%d buffers deleted"
+msgstr "%d buforów skasowano"
+
+#: buffer.c:831
+msgid "1 buffer wiped out"
+msgstr "wyrzucono 1 bufor "
+
+#: buffer.c:833
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "wyrzucono %d buforów"
+
+#: buffer.c:894
+msgid "E84: No modified buffer found"
+msgstr "E84: Nie znaleziono zmienionych buforów"
+
+#. back where we started, didn't find anything.
+#: buffer.c:933
+msgid "E85: There is no listed buffer"
+msgstr "E85: Nie ma wylistowanych buforów"
+
+#: buffer.c:945
+#, c-format
+msgid "E86: Buffer %ld does not exist"
+msgstr "E86: Bufor \"%ld\" nie istnieje"
+
+#: buffer.c:948
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Nie mogê przej¶æ poza ostatni bufor"
+
+#: buffer.c:950
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Nie mogê przej¶æ przed pierwszy bufor"
+
+#: buffer.c:988
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr "E89 Nie zapisano zmian w buforze %ld (wymu¶ przez !)"
+
+#: buffer.c:1005
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: Nie mogê wy³adowaæ ostatniego bufora"
+
+#: buffer.c:1538
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: OSTRZE¯ENIE: Przepe³nienie listy nazw plików"
+
+#: buffer.c:1709
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: Nie znaleziono bufora %ld"
+
+#: buffer.c:1940
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Wielokrotne dopasowania dla %s"
+
+#: buffer.c:1942
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: ¯aden bufor nie pasuje do %s"
+
+#: buffer.c:2337
+#, c-format
+msgid "line %ld"
+msgstr "wiersz %ld"
+
+#: buffer.c:2420
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Bufor o tej nazwie ju¿ istnieje"
+
+#: buffer.c:2713
+msgid " [Modified]"
+msgstr " [Zmieniony]"
+
+#: buffer.c:2718
+msgid "[Not edited]"
+msgstr "[Nie edytowany]"
+
+#: buffer.c:2723
+msgid "[New file]"
+msgstr "[Nowy Plik]"
+
+#: buffer.c:2724
+msgid "[Read errors]"
+msgstr "[B³±d odczytu]"
+
+#: buffer.c:2726 fileio.c:2112
+msgid "[readonly]"
+msgstr "[tylko odczyt]"
+
+#: buffer.c:2747
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 wiersz --%d%%--"
+
+#: buffer.c:2749
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld wiersze --%d%%--"
+
+#: buffer.c:2756
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "wiersz %ld z %ld --%d%%-- kol "
+
+#: buffer.c:2864
+msgid "[No file]"
+msgstr "[Brak pliku]"
+
+#. must be a help buffer
+#: buffer.c:2904
+msgid "help"
+msgstr "pomoc"
+
+#: buffer.c:3463 screen.c:5075
+msgid "[help]"
+msgstr "[pomoc]"
+
+#: buffer.c:3495 screen.c:5081
+msgid "[Preview]"
+msgstr "[Podgl±d]"
+
+#: buffer.c:3775
+msgid "All"
+msgstr "Wszystko"
+
+#: buffer.c:3775
+msgid "Bot"
+msgstr "Dó³"
+
+#: buffer.c:3777
+msgid "Top"
+msgstr "Góra"
+
+#: buffer.c:4523
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# Lista buforów:\n"
+
+#: buffer.c:4556
+msgid "[Error List]"
+msgstr "[Lista B³êdów]"
+
+#: buffer.c:4569 memline.c:1520
+msgid "[No File]"
+msgstr "[Brak Pliku]"
+
+#: buffer.c:4882
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Znaki ---"
+
+#: buffer.c:4901
+#, c-format
+msgid "Signs for %s:"
+msgstr "Znaki dla %s:"
+
+#: buffer.c:4907
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " wiersz=%ld id=%d nazwa=%s"
+
+#: diff.c:139
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: Nie mogê zró¿nicowaæ wiêcej ni¿ %ld buforów"
+
+#: diff.c:709
+msgid "E97: Cannot create diffs"
+msgstr "E97: Nie mogê stworzyæ ró¿nic"
+
+#: diff.c:814
+msgid "Patch file"
+msgstr "Plik ³ata"
+
+#: diff.c:1065
+msgid "E98: Cannot read diff output"
+msgstr "E98: Nie mogê wczytaæ wyj¶cia ró¿nicy"
+
+#: diff.c:1815
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Bie¿±cy bufor nie jest w trybie ró¿nic"
+
+#: diff.c:1827
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: Brak innego bufora w trybie ró¿nic"
+
+#: diff.c:1835
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: Wiêcej ni¿ jeden bufor w trybie ró¿nicowania, nie wiem którego u¿yæ"
+
+#: diff.c:1858
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Nie mogê znale¼æ bufora \"%s\""
+
+#: diff.c:1864
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Bufor \"%s\" nie jest w trybie ró¿nicowania"
+
+#: digraph.c:2199
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: Escape jest niedozwolone w dwugrafie"
+
+#: digraph.c:2384
+msgid "E544: Keymap file not found"
+msgstr "E544: Nie znaleziono pliku rozk³adu klawiszy"
+
+#: digraph.c:2411
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: Zastosowano :loadkeymap w niewczytanym pliku"
+
+#: edit.c:40
+msgid " Keyword completion (^N^P)"
+msgstr " Dope³nianie s³ów kluczowych (^N^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E^Y^L^]^F^I^K^D^V^N^P)"
+msgstr " ^X tryb (^E^Y^L^]^F^I^K^D^V^N^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N^P)"
+msgstr " Lokalne dope³nianie s³ów kluczowych (^N^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L^N^P)"
+msgstr " Dope³nianie pe³nych wierszy (^L^N^P)"
+
+#: edit.c:46
+msgid " File name completion (^F^N^P)"
+msgstr " Dope³nianie nazw plików (^F^N^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]^N^P)"
+msgstr " Dope³nianie znaczników (^]^N^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N^P)"
+msgstr " Dope³nianie wzorców tropów (^N^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D^N^P)"
+msgstr " Dope³nianie definicji (^D^N^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K^N^P)"
+msgstr " Dope³nianie ze s³owników (^K^N^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T^N^P)"
+msgstr " Dope³nianie z tezaurusa (^T^N^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V^N^P)"
+msgstr " Dope³nianie wiersza poleceñ (^V^N^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Dobi³em do koñca akapitu"
+
+#: edit.c:962
+msgid "'thesaurus' option is empty"
+msgstr "opcja 'thesaurus' jest pusta"
+
+#: edit.c:1166
+msgid "'dictionary' option is empty"
+msgstr "opcja 'dictionary' jest pusta"
+
+#: edit.c:2162
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Przegl±dam s³ownik: %s"
+
+#: edit.c:2368
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (wprowadzanie) Przewijanie (^E/^Y)"
+
+#: edit.c:2370
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (zamiana) Przewijanie (^E/^Y)"
+
+#: edit.c:2684
+#, c-format
+msgid "Scanning: %s"
+msgstr "Przegl±dam: %s"
+
+#: edit.c:2719
+msgid "Scanning tags."
+msgstr "Przegl±dam znaczniki."
+
+#: edit.c:3381
+msgid " Adding"
+msgstr " Dodajê"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3430
+msgid "-- Searching..."
+msgstr "-- Szukam..."
+
+#: edit.c:3486
+msgid "Back at original"
+msgstr "Z powrotem na pierwotnym"
+
+#: edit.c:3491
+msgid "Word from other line"
+msgstr "Wyraz z innego wiersza"
+
+#: edit.c:3496
+msgid "The only match"
+msgstr "Jedyne dopasowanie"
+
+#: edit.c:3555
+#, c-format
+msgid "match %d of %d"
+msgstr "pasuje %d z %d"
+
+#: edit.c:3558
+#, c-format
+msgid "match %d"
+msgstr "pasuje %d"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:1024
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Nieznana zmienna: \"%s\""
+
+#: eval.c:1320
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Brak nawiasów: %s"
+
+#: eval.c:1435 eval.c:1449
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Nie istnieje zmienna: \"%s\""
+
+#: eval.c:1705
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Brak ':' po '?'"
+
+#: eval.c:2327
+msgid "E110: Missing ')'"
+msgstr "E110: Brak ')'"
+
+#: eval.c:2389
+msgid "E111: Missing ']'"
+msgstr "E111: Brak ']'"
+
+#: eval.c:2466
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Brak nazwy opcji: %s"
+
+#: eval.c:2484
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Nieznana opcja: %s"
+
+#: eval.c:2555
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Brak cudzys³owu: %s"
+
+#: eval.c:2698
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Brak cudzys³owu: %s"
+
+#: eval.c:3054
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Niew³a¶ciwe argumenty dla funkcji %s"
+
+#: eval.c:3083
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Nieznana funkcja: %s"
+
+#: eval.c:3084
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: Zbyt wiele argumentów dla funkcji: %s"
+
+#: eval.c:3085
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Za ma³o argumentów dla funkcji: %s"
+
+#: eval.c:3086
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: Zastosowano <SID> poza skryptem: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3687 gui.c:4376 gui_gtk.c:2059
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:4226
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld wierszy: "
+
+#: eval.c:5477
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&OK\n"
+"&Zakoñcz"
+
+#: eval.c:5517
+msgid "called inputrestore() more often than inputsave()"
+msgstr "wywo³ano inputrestore() wiêcej razy ni¿ inputsave()"
+
+#: eval.c:5977
+msgid "E655: Too many symbolic links (cycle?)"
+msgstr "E655: Za du¿o dowi±zañ symbolicznych (pêtla?)"
+
+#: eval.c:6609
+msgid "E240: No connection to Vim server"
+msgstr "E240: Brak po³±czenia z serwerem Vim"
+
+#: eval.c:6706
+msgid "E277: Unable to read a server reply"
+msgstr "E277: Nie mogê czytaæ odpowiedzi serwera"
+
+#: eval.c:6734
+msgid "E258: Unable to send to client"
+msgstr "E258: Nie mogê wys³aæ do klienta"
+
+#: eval.c:6782
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Nie mogê wys³aæ do %s"
+
+#: eval.c:6882
+msgid "(Invalid)"
+msgstr "(Niew³a¶ciwe)"
+
+#: eval.c:8060
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Nieokre¶lona zmienna: %s"
+
+#: eval.c:8492
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E418: Niedozwolona nazwa zmiennej: %s"
+
+#: eval.c:8784
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: Funkcja %s ju¿ istnieje; aby j± zamieniæ u¿yj !"
+
+#: eval.c:8857
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Nieokre¶lona funkcja: %s"
+
+#: eval.c:8870
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Brak '(': %s"
+
+#: eval.c:8903
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Niedozwolony argument: %s"
+
+#: eval.c:8982
+msgid "E126: Missing :endfunction"
+msgstr "E126: Brak :endfunction"
+
+#: eval.c:9089
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Nie mogê przedefiniowaæ funkcji %s: jest w u¿yciu"
+
+#: eval.c:9159
+msgid "E129: Function name required"
+msgstr "E129: Wymagana jest nazwa funkcji"
+
+#: eval.c:9210
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: Nazwa funkcji musi rozpoczynaæ siê du¿± liter±: %s"
+
+#: eval.c:9402
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Nieokre¶lona funkcja: %s"
+
+#: eval.c:9407
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Nie mogê skasowaæ funkcji %s: jest w u¿yciu"
+
+#: eval.c:9455
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: Zagnie¿d¿enie wywo³añ funkcji ponad 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:9508
+#, c-format
+msgid "calling %s"
+msgstr "wywo³ujê %s"
+
+#: eval.c:9570
+#, c-format
+msgid "%s aborted"
+msgstr "porzucono %s"
+
+#: eval.c:9572
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s zwraca #%ld"
+
+#: eval.c:9579
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s zwraca \"%s\""
+
+#. always scroll up, don't overwrite
+#: eval.c:9595 ex_cmds2.c:2365
+#, c-format
+msgid "continuing in %s"
+msgstr "kontynuacja w %s"
+
+#: eval.c:9621
+msgid "E133: :return not inside a function"
+msgstr "E133: :return poza funkcj±"
+
+#: eval.c:9952
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# zmienne globalne:\n"
+
+#: ex_cmds2.c:92
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "Wchodzê w tryb odpluskwiania. Wprowad¼ \"cont\" aby kontynuowaæ."
+
+#: ex_cmds2.c:96 ex_docmd.c:966
+#, c-format
+msgid "line %ld: %s"
+msgstr "wiersz %ld: %s"
+
+#: ex_cmds2.c:98
+#, c-format
+msgid "cmd: %s"
+msgstr "cmd: %s"
+
+#: ex_cmds2.c:290
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Punkt kontrolny w \"%s%s\" wiersz %ld"
+
+#: ex_cmds2.c:540
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Nie znaleziono punktu kontrolnego: %s"
+
+#: ex_cmds2.c:566
+msgid "No breakpoints defined"
+msgstr "Nie okre¶lono ¿adnych punktów kontrolnych"
+
+#: ex_cmds2.c:571
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s wiersz %ld"
+
+#: ex_cmds2.c:763 ex_cmds.c:2097 ex_cmds.c:2362
+msgid "Save As"
+msgstr "Zapisz jako"
+
+#: ex_cmds2.c:786
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Zachowaj zmiany w \"%.*s\"?"
+
+#: ex_cmds2.c:788 ex_docmd.c:9380
+msgid "Untitled"
+msgstr "Bez Tytu³u"
+
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Nie zapisano zmian w buforze \"%s\""
+
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "OSTRZE¯ENIE: Nieoczekiwane wej¶cie w inny bufor (sprawd¼ autokomendy)"
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: Tylko jeden plik w edycji"
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: Nie mo¿na przej¶æ przed pierwszy plik"
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Nie mo¿na przej¶æ za ostatni plik"
+
+#: ex_cmds2.c:1804
+#, c-format
+msgid "E666: compiler not supported: %s"
+msgstr "E666: nie wspierany kompilator: %s"
+
+#: ex_cmds2.c:1897
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Szukanie \"%s\" w \"%s\""
+
+#: ex_cmds2.c:1919
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Szukanie \"%s\""
+
+#: ex_cmds2.c:1940
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "nie znaleziono w 'runtimepath': \"%s\""
+
+#: ex_cmds2.c:1974
+msgid "Source Vim script"
+msgstr "Wczytaj skrypt Vima"
+
+#: ex_cmds2.c:2164
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "Nie mo¿na wczytaæ katalogu: \"%s\""
+
+#: ex_cmds2.c:2202
+#, c-format
+msgid "could not source \"%s\""
+msgstr "nie mog³em wczytaæ \"%s\""
+
+#: ex_cmds2.c:2204
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "wiersz: %ld nie mog³em wczytaæ \"%s\""
+
+#: ex_cmds2.c:2218
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "wczytywanie \"%s\""
+
+#: ex_cmds2.c:2220
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "wiersz %ld: wczytywanie \"%s\""
+
+#: ex_cmds2.c:2363
+#, c-format
+msgid "finished sourcing %s"
+msgstr "skoñczono wczytywanie %s"
+
+#: ex_cmds2.c:2707
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: OSTRZE¯ENIE: Niew³a¶ciwy separator wierszy, pewnie brak ^M"
+
+#: ex_cmds2.c:2756
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: u¿yto :scriptencoding poza wczytywanym plikiem"
+
+#: ex_cmds2.c:2789
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: u¿yto :finish poza wczytywanym plikiem"
+
+#: ex_cmds2.c:3238
+#, c-format
+msgid "Page %d"
+msgstr "Strona %d"
+
+#: ex_cmds2.c:3394
+msgid "No text to be printed"
+msgstr "Brak tekstu do drukowania"
+
+#: ex_cmds2.c:3472
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "Drukujê stronê %d (%d%%)"
+
+#: ex_cmds2.c:3484
+#, c-format
+msgid " Copy %d of %d"
+msgstr " Kopia %d z %d"
+
+#: ex_cmds2.c:3542
+#, c-format
+msgid "Printed: %s"
+msgstr "Wydrukowano: %s"
+
+#: ex_cmds2.c:3549
+msgid "Printing aborted"
+msgstr "Drukowanie odwo³ane"
+
+#: ex_cmds2.c:3914
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Nie mo¿na zapisaæ do wyj¶ciowego pliku PostScriptu"
+
+#: ex_cmds2.c:4189
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E624: Nie mogê otworzyæ pliku \"%s\""
+
+#: ex_cmds2.c:4199 ex_cmds2.c:4824
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Nie mo¿na odczytaæ pliku zasobów PostScriptu \"%s\""
+
+#: ex_cmds2.c:4207
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: plik \"%s\" nie jest plikiem zasobów PostScriptu"
+
+#: ex_cmds2.c:4222 ex_cmds2.c:4242 ex_cmds2.c:4257 ex_cmds2.c:4279
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: plik \"%s\" nie jest wspieranym plikiem zasobów PostScriptu"
+
+#: ex_cmds2.c:4309
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: \"%s\" nieprawid³owa wersja pliku zasobów"
+
+#: ex_cmds2.c:4776
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Nie mo¿na otworzyæ pliku PostScript do wyj¶cia"
+
+#: ex_cmds2.c:4809
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Nie mogê otworzyæ pliku \"%s\""
+
+#: ex_cmds2.c:4928
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr "E456: Nie mo¿na znale¼æ pliku zasobów PostScriptu \"prolog.ps\""
+
+#: ex_cmds2.c:4959
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: Nie mo¿na znale¼æ pliku zasobów PostScriptu \"%s.ps\""
+
+#: ex_cmds2.c:4977
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr "E620: Nie mo¿na przekonwertowaæ z multi-byte do kodowania \"%s\""
+
+#: ex_cmds2.c:5102
+msgid "Sending to printer..."
+msgstr "Przesy³am do drukarki..."
+
+#: ex_cmds2.c:5106
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: Drukowanie pliku PostScript nie powiod³o siê"
+
+#: ex_cmds2.c:5108
+msgid "Print job sent."
+msgstr "Zadanie drukowanie przes³ane."
+
+#: ex_cmds2.c:5618
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Bie¿±cy %sjêzyk: \"%s\""
+
+#: ex_cmds2.c:5629
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Nie mogê ustawiæ jêzyka na \"%s\""
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Hex %02x, Oktal %03o"
+
+#: ex_cmds.c:118
+#, c-format
+msgid "> %d, Hex %04x, Octal %o"
+msgstr "> %d, Hex %04x, Oktal %o"
+
+#: ex_cmds.c:119
+#, c-format
+msgid "> %d, Hex %08x, Octal %o"
+msgstr "> %d, Hex %08x, Oktal %o"
+
+#: ex_cmds.c:430
+msgid "E134: Move lines into themselves"
+msgstr "E134: Przeniesienie wierszy na siebie samych"
+
+#: ex_cmds.c:499
+msgid "1 line moved"
+msgstr "1 wiersz przeniesiony"
+
+#: ex_cmds.c:501
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld wiersze przeniesione"
+
+#: ex_cmds.c:924
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld wierszy przefiltrowanych"
+
+#: ex_cmds.c:952
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: Autokomendy *Filter* nie mog± zmieniaæ bie¿±cego bufora"
+
+#: ex_cmds.c:1037
+msgid "[No write since last change]\n"
+msgstr "[Brak zapisu od czasu ostatniej zmiany]\n"
+
+#: ex_cmds.c:1283
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s w wierszu: "
+
+#: ex_cmds.c:1288
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: Zbyt wiele b³êdów; pomijam resztê pliku"
+
+#: ex_cmds.c:1323
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Wczytujê plik viminfo \"%s\"%s%s%s"
+
+#: ex_cmds.c:1324
+msgid " info"
+msgstr " informacja"
+
+#: ex_cmds.c:1325
+msgid " marks"
+msgstr " zak³adki"
+
+#: ex_cmds.c:1326
+msgid " FAILED"
+msgstr " NIE POWIOD£O SIÊ"
+
+#: ex_cmds.c:1418
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Plik viminfo jest niezapisywalny: %s"
+
+#: ex_cmds.c:1543
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Nie mogê zapisaæ pliku viminfo %s!"
+
+#: ex_cmds.c:1551
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Zapisujê plik viminfo \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1649
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Ten plik viminfo zosta³ wygenerowany przez Vima %s.\n"
+
+#: ex_cmds.c:1651
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Mo¿esz go ostro¿nie edytowaæ!\n"
+"\n"
+
+#: ex_cmds.c:1653
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Warto¶æ 'encoding' w czasie zapsu tego pliku\n"
+
+#: ex_cmds.c:1752
+msgid "Illegal starting char"
+msgstr "Niedopuszczalny pocz±tkowy znak"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2140
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Plik jest za³adowany w innym buforze"
+
+#: ex_cmds.c:2174
+msgid "Write partial file?"
+msgstr "Zapisaæ czê¶ciowo plik?"
+
+#: ex_cmds.c:2181
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Stosuj ! do zapisania czê¶ciowo bufora"
+
+#: ex_cmds.c:2296
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Nadpisaæ istniej±cy plik \"%.*s\"?"
+
+#: ex_cmds.c:2367
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: Brak nazwy pliku dla bufora %ld"
+
+#: ex_cmds.c:2405
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: Plik niezapisany: Zapis jest wy³±czony opcj± 'write'"
+
+#: ex_cmds.c:2425
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"opcja 'readonly' nastawiona dla \"%.*s\".\n"
+"Czy chcesz go pomimo tego zapisaæ?"
+
+#: ex_cmds.c:2597
+msgid "Edit File"
+msgstr "Edytuj Plik"
+
+#: ex_cmds.c:3205
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Autokomendy nieoczekiwanie skasowa³y nowy bufor %s"
+
+#: ex_cmds.c:3339
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: nienumeryczny argument dla :z"
+
+#: ex_cmds.c:3424
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: Komendy pow³oki s± niedozwolone w rvim"
+
+#: ex_cmds.c:3531
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Wzorce regularne nie mog± byæ rozgraniczane literami"
+
+#: ex_cmds.c:3877
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "zamieñ na %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4266
+msgid "(Interrupted) "
+msgstr "(Przerwane) "
+
+#: ex_cmds.c:4270
+msgid "1 substitution"
+msgstr "1 podstawienie "
+
+#: ex_cmds.c:4272
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld podstawieñ"
+
+#: ex_cmds.c:4275
+msgid " on 1 line"
+msgstr " w 1 wierszu"
+
+#: ex_cmds.c:4277
+#, c-format
+msgid " on %ld lines"
+msgstr " w %ld wierszach"
+
+#: ex_cmds.c:4328
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: Nie mogê wykonaæ :global rekursywnie"
+
+#: ex_cmds.c:4363
+msgid "E148: Regular expression missing from global"
+msgstr "E148: Brak wzorca regularnego w :global"
+
+# c-format
+#: ex_cmds.c:4412
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Wzorzec znaleziono w ka¿dym wierszu: %s"
+
+#: ex_cmds.c:4493
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Ostatni podstawiany ci±g:\n"
+"$"
+
+#: ex_cmds.c:4594 ex_docmd.c:2011
+msgid "E478: Don't panic!"
+msgstr "E478: Nie panikuj!"
+
+#: ex_cmds.c:4646
+#, c-format
+msgid "E661: Sorry, no '%s' help for %s"
+msgstr "E661: Przykro mi, brak '%s' pomocy dla %s"
+
+#: ex_cmds.c:4649
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Przykro mi, ale brak pomocy o %s"
+
+#: ex_cmds.c:4683
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Przykro mi, nie ma pliku pomocy \"%s\""
+
+#: ex_cmds.c:5166
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: Nie jest katalogiem: %s"
+
+#: ex_cmds.c:5305
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: Nie mogê otworzyæ %s do zapisu"
+
+#: ex_cmds.c:5341
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Nie mogê otworzyæ %s do odczytu"
+
+#: ex_cmds.c:5363
+#, c-format
+msgid "E670: Mix of help file encodings within a language: %s"
+msgstr "E670: Mieszanka kodowañ w pliku pomocy w ramach jêzyka: %s"
+
+#: ex_cmds.c:5441
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: Dwukrotny znacznik \"%s\" w pliku %s"
+
+#: ex_cmds.c:5553
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Nieznana komenda znaku: %s"
+
+#: ex_cmds.c:5573
+msgid "E156: Missing sign name"
+msgstr "E156: Brak nazwy znaku"
+
+#: ex_cmds.c:5619
+msgid "E612: Too many signs defined"
+msgstr "E255: Zbyt wiele nazw znaków"
+
+#: ex_cmds.c:5687
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Niew³a¶ciwy tekst znaku: %s"
+
+#: ex_cmds.c:5718 ex_cmds.c:5909
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Nieznany znak: %s"
+
+#: ex_cmds.c:5767
+msgid "E159: Missing sign number"
+msgstr "E159: Brak numeru znaku"
+
+#: ex_cmds.c:5849
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: Niew³a¶ciwa nazwa bufora: %s"
+
+#: ex_cmds.c:5888
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Niew³a¶ciwe ID znaku: %ld"
+
+#: ex_cmds.c:5958
+msgid " (NOT FOUND)"
+msgstr " (NIE ZNALEZIONO)"
+
+#: ex_cmds.c:5960
+msgid " (not supported)"
+msgstr "(nie wspomagane)"
+
+#: ex_cmds.c:6059
+msgid "[Deleted]"
+msgstr "[Skasowano]"
+
+#: ex_docmd.c:525
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Wchodzê w tryb Ex. Wprowad¼ \"visual\" aby przej¶æ do trybu Normal."
+
+#. must be at EOF
+#: ex_docmd.c:561
+msgid "E501: At end-of-file"
+msgstr "E501: Na koñcu pliku"
+
+#: ex_docmd.c:669
+msgid "E169: Command too recursive"
+msgstr "E169: Komenda zbyt rekursywna"
+
+#: ex_docmd.c:1229
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: Nie znaleziono wyj±tku: %s"
+
+#: ex_docmd.c:1317
+msgid "End of sourced file"
+msgstr "Koniec wczytywanego pliku"
+
+#: ex_docmd.c:1318
+msgid "End of function"
+msgstr "Koniec funkcji"
+
+#: ex_docmd.c:1907
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: Niejednoznaczne zastosowanie komendy zdefiniowanej przez u¿ytkownika"
+
+#: ex_docmd.c:1921
+msgid "E492: Not an editor command"
+msgstr "E492: Nie jest komend± edytora"
+
+#: ex_docmd.c:2030
+msgid "E493: Backwards range given"
+msgstr "E493: Dano wsteczny zakres"
+
+#: ex_docmd.c:2039
+msgid "Backwards range given, OK to swap"
+msgstr "Dano wsteczny zakres; zamiana jest mo¿liwa"
+
+#: ex_docmd.c:2162
+msgid "E494: Use w or w>>"
+msgstr "E494: Stosuj w lub w>>"
+
+#: ex_docmd.c:3788
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Przykro mi, ale ta komenda nie jest dostêpna w tej wersji"
+
+#: ex_docmd.c:3991
+msgid "E172: Only one file name allowed"
+msgstr "E172: Tylko pojedyncza nazwa pliku dozwolona"
+
+#: ex_docmd.c:4571
+msgid "1 more file to edit. Quit anyway?"
+msgstr "1 wiêcej plik do edycji. Mimo to wyj¶æ?"
+
+#: ex_docmd.c:4574
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "jeszcze %d plików do edycji. Mimo to wyj¶æ?"
+
+#: ex_docmd.c:4581
+msgid "E173: 1 more file to edit"
+msgstr "E173: 1 wiêcej plik do edycji"
+
+#: ex_docmd.c:4583
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: jeszcze %ld plików do edycji"
+
+#: ex_docmd.c:4678
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: Komenda ju¿ istnieje; aby j± przedefiniowaæ stosuj !"
+
+#: ex_docmd.c:4789
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Nazwa Arg. Zak. Gotowo¶æ Definicja"
+
+#: ex_docmd.c:4878
+msgid "No user-defined commands found"
+msgstr "Nie znaleziono komend zdefiniowanych przez u¿ytkownika"
+
+#: ex_docmd.c:4910
+msgid "E175: No attribute specified"
+msgstr "E175: Nie okre¶lono atrybutu"
+
+#: ex_docmd.c:4962
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Niew³a¶ciwa ilo¶æ argumentów"
+
+#: ex_docmd.c:4977
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: Mno¿nik nie mo¿e byæ podany dwukrotnie"
+
+#: ex_docmd.c:4987
+msgid "E178: Invalid default value for count"
+msgstr "E178: Niew³a¶ciwa domy¶lna warto¶æ mno¿nika"
+
+#: ex_docmd.c:5018
+msgid "E179: argument required for complete"
+msgstr "E179: argument wymagany do dope³niania"
+
+#: ex_docmd.c:5050
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Niew³a¶ciwa warto¶æ dope³niania: %s"
+
+#: ex_docmd.c:5059
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr "E468: Argument depe³niania dozwolony wy³±cznie dla dope³niania u¿ytkownika"
+
+#: ex_docmd.c:5065
+msgid "E467: Custom completion requires a function argument"
+msgstr "E467: Dope³nianie u¿ytkownika wymaga funkcji jako argumentu"
+
+#: ex_docmd.c:5076
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Niew³a¶ciwy atrybut: %s"
+
+#: ex_docmd.c:5119
+msgid "E182: Invalid command name"
+msgstr "E182: Niew³a¶ciwa nazwa komendy"
+
+#: ex_docmd.c:5134
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr ""
+"E183: Komendy zdefiniowane przez u¿ytkownika musz± rozpoczynaæ siê du¿± "
+"liter±"
+
+#: ex_docmd.c:5205
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: Nie ma takiej komendy u¿ytkownika: %s"
+
+#: ex_docmd.c:5666
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Nie mogê znale¼æ zestawu kolorów %s"
+
+#: ex_docmd.c:5674
+msgid "Greetings, Vim user!"
+msgstr "Witaj u¿ytkowniku Vima!"
+
+#: ex_docmd.c:6391
+msgid "Edit File in new window"
+msgstr "Edytuj plik w nowym oknie"
+
+#: ex_docmd.c:6686
+msgid "No swap file"
+msgstr "Brak pliku wymiany"
+
+#: ex_docmd.c:6790
+msgid "Append File"
+msgstr "Do³±cz plik"
+
+#: ex_docmd.c:6854
+msgid "E186: No previous directory"
+msgstr "E186: Nie ma poprzedniego katalogu"
+
+#: ex_docmd.c:6936
+msgid "E187: Unknown"
+msgstr "E187: Nieznany"
+
+#: ex_docmd.c:7021
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: :winsize wymaga dwóch argumentów numerycznych"
+
+#: ex_docmd.c:7077
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Pozycja okna: X %d, Y %d"
+
+#: ex_docmd.c:7082
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: Pozyskiwanie pozycji okna nie jest zaimplementowane dla tego systemu"
+
+#: ex_docmd.c:7092
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: :winpos wymaga dwóch argumentów numerycznych"
+
+#: ex_docmd.c:7370
+msgid "Save Redirection"
+msgstr "Zapisz przekierowanie"
+
+#: ex_docmd.c:7560
+msgid "Save View"
+msgstr "Zapisz widok"
+
+#: ex_docmd.c:7561
+msgid "Save Session"
+msgstr "Zapisz sesjê"
+
+#: ex_docmd.c:7563
+msgid "Save Setup"
+msgstr "Zapisz ustawienia"
+
+#: ex_docmd.c:7715
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" istnieje (wymu¶ poprzez !)"
+
+#: ex_docmd.c:7720
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: Nie mogê otworzyæ \"%s\" do zapisu"
+
+#. set mark
+#: ex_docmd.c:7744
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: Argument musi byæ liter± albo cudzys³owem w przód/ty³"
+
+#: ex_docmd.c:7786
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Rekursywne zastosowanie :normal za g³êbokie"
+
+#: ex_docmd.c:8304
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: Brak nazwy zamiennego pliku do podstawienia pod '#'"
+
+#: ex_docmd.c:8335
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: brak nazwy pliku autokomend do podstawienia pod \"<afile>\""
+
+#: ex_docmd.c:8343
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "E496: brak numeru bufora autokomend do podstawienia pod \"<abuf>\""
+
+#: ex_docmd.c:8354
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr "E497: brak nazwy dopasowania autokomend pod \"<amatch>\""
+
+#: ex_docmd.c:8364
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr "E498: brak nazwy pliku :source do postawienia pod \"<sfile>\""
+
+#: ex_docmd.c:8405
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: Pusta nazwa pliku dla '%' lub '#', dzia³a tylko z \":p:h\""
+
+#: ex_docmd.c:8407
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: Wynikiem jest pusty ci±g"
+
+#: ex_docmd.c:9362
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: Nie mogê otworzyæ pliku viminfo do odczytu"
+
+#: ex_docmd.c:9535
+msgid "E196: No digraphs in this version"
+msgstr "E196: Brak dwugrafów w tej wersji"
+
+#: ex_eval.c:440
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr "E608: Nie mo¿na ':throw' wyj±tków z prefiksem 'Vim'"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:529
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "Wyj±tek: %s"
+
+#: ex_eval.c:576
+#, c-format
+msgid "Exception finished: %s"
+msgstr "Wyj±tek zakoñczony: %s"
+
+#: ex_eval.c:577
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "Wyj±tek odrzucony: %s"
+
+#: ex_eval.c:620 ex_eval.c:664
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, wiersz %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:638
+#, c-format
+msgid "Exception caught: %s"
+msgstr "Wyj±tek przechwycony: %s"
+
+#: ex_eval.c:713
+#, c-format
+msgid "%s made pending"
+msgstr "%s zosta³ zawieszony"
+
+#: ex_eval.c:716
+#, c-format
+msgid "%s resumed"
+msgstr "%s przywrócony"
+
+#: ex_eval.c:720
+#, c-format
+msgid "%s discarded"
+msgstr "%s odrzucony"
+
+#: ex_eval.c:746
+msgid "Exception"
+msgstr "Wyj±tek"
+
+#: ex_eval.c:752
+msgid "Error and interrupt"
+msgstr "B³±d i przerwanie"
+
+#: ex_eval.c:754 gui.c:4375
+msgid "Error"
+msgstr "B³±d"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:756
+msgid "Interrupt"
+msgstr "Przerwanie"
+
+#: ex_eval.c:830
+msgid "E579: :if nesting too deep"
+msgstr "E579: zbyt g³êbokie zagnie¿d¿enie :if"
+
+#: ex_eval.c:867
+msgid "E580: :endif without :if"
+msgstr "E580: :endif bez :if"
+
+#: ex_eval.c:911
+msgid "E581: :else without :if"
+msgstr "E581: :else bez :if"
+
+#: ex_eval.c:914
+msgid "E582: :elseif without :if"
+msgstr "E582: :elseif bez :if"
+
+#: ex_eval.c:921
+msgid "E583: multiple :else"
+msgstr "E583: wielokrotne :else"
+
+#: ex_eval.c:924
+msgid "E584: :elseif after :else"
+msgstr "E584: :elseif po :else"
+
+#: ex_eval.c:991
+msgid "E585: :while nesting too deep"
+msgstr "E585: zbyt g³êbokie zagnie¿d¿enie :while"
+
+#: ex_eval.c:1047
+msgid "E586: :continue without :while"
+msgstr "E586: :continue bez :while"
+
+#: ex_eval.c:1087
+msgid "E587: :break without :while"
+msgstr "E587: :break bez :while"
+
+#: ex_eval.c:1286
+msgid "E601: :try nesting too deep"
+msgstr "E601: zbyt g³êbokie zagnie¿d¿enie :try"
+
+#: ex_eval.c:1366
+msgid "E603: :catch without :try"
+msgstr "E603: :catch bez :try"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1388
+msgid "E604: :catch after :finally"
+msgstr "E604: :catch za :finally"
+
+#: ex_eval.c:1521
+msgid "E606: :finally without :try"
+msgstr "E606: :finally bez :try"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1545
+msgid "E607: multiple :finally"
+msgstr "E607: wielokrotne :finally"
+
+#: ex_eval.c:1654
+msgid "E602: :endtry without :try"
+msgstr "E602: :endtry bez :try"
+
+#: ex_eval.c:1986
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction poza funkcj±"
+
+#: ex_getln.c:3296
+msgid "tagname"
+msgstr "nazwa znacznika"
+
+#: ex_getln.c:3299
+msgid " kind file\n"
+msgstr " pokrewny plik\n"
+
+#: ex_getln.c:4752
+msgid "'history' option is zero"
+msgstr "opcja 'history' jest zerowa"
+
+#: ex_getln.c:5023
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s Historia (od najnowszych po najstarsze):\n"
+
+#: ex_getln.c:5024
+msgid "Command Line"
+msgstr "Wiersz poleceñ"
+
+#: ex_getln.c:5025
+msgid "Search String"
+msgstr "Szukany ci±g"
+
+#: ex_getln.c:5026
+msgid "Expression"
+msgstr "Wyra¿enie"
+
+#: ex_getln.c:5027
+msgid "Input Line"
+msgstr "Wiersz wprowadzeñ"
+
+#: ex_getln.c:5065
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar przekracza d³ugo¶æ polecenia"
+
+#: ex_getln.c:5242
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Aktywny widok lub bufor skasowany"
+
+#: fileio.c:377
+msgid "Illegal file name"
+msgstr "Niedopuszczalna nazwa pliku"
+
+#: fileio.c:401 fileio.c:535 fileio.c:2913 fileio.c:2954
+msgid "is a directory"
+msgstr "jest katalogiem"
+
+#: fileio.c:403
+msgid "is not a file"
+msgstr "nie jest plikiem"
+
+#: fileio.c:557 fileio.c:4131
+msgid "[New File]"
+msgstr "[Nowy Plik]"
+
+#: fileio.c:590
+msgid "[Permission Denied]"
+msgstr "[Nie dozwolono]"
+
+#: fileio.c:694
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: Autokomendy *ReadPre zrobi³y plik nieodczytywalnym"
+
+#: fileio.c:696
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: Autokomendy *ReadPre nie mog± zmieniaæ bie¿±cego bufora"
+
+#: fileio.c:717
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: Wczytywanie ze stdin...\n"
+
+#: fileio.c:723
+msgid "Reading from stdin..."
+msgstr "Wczytywanie ze stdin..."
+
+#. Re-opening the original file failed!
+#: fileio.c:1000
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: Plik stworzony poprzez przemianê jest nieodczytywalny!"
+
+#: fileio.c:2090
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:2097
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:2104
+msgid "[socket]"
+msgstr "[socket]"
+
+#: fileio.c:2112
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:2122
+msgid "[CR missing]"
+msgstr "[brak CR]'"
+
+#: fileio.c:2127
+msgid "[NL found]"
+msgstr "[znaleziono NL]"
+
+#: fileio.c:2132
+msgid "[long lines split]"
+msgstr "[d³ugie wiersze rozdzielane]"
+
+#: fileio.c:2138 fileio.c:4115
+msgid "[NOT converted]"
+msgstr "[NIE przemienione]"
+
+#: fileio.c:2143 fileio.c:4120
+msgid "[converted]"
+msgstr "[przemienione]"
+
+#: fileio.c:2150 fileio.c:4145
+msgid "[crypted]"
+msgstr "[zakodowane]"
+
+#: fileio.c:2157
+msgid "[CONVERSION ERROR]"
+msgstr "[B£¡D W PRZEMIANIE]"
+
+#: fileio.c:2163
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[NIEDOZWOLONY BAJT w wierszu %ld]"
+
+#: fileio.c:2170
+msgid "[READ ERRORS]"
+msgstr "[B£ÊDY W ODCZYCIE]"
+
+#: fileio.c:2386
+msgid "Can't find temp file for conversion"
+msgstr "Nie mogê znale¼æ pliku tymczasowego w celu przemiany"
+
+#: fileio.c:2393
+msgid "Conversion with 'charconvert' failed"
+msgstr "Nieudana przemiana z 'charconvert'"
+
+#: fileio.c:2396
+msgid "can't read output of 'charconvert'"
+msgstr "nie mogê odczytaæ wyj¶cia z 'charconvert'"
+
+#: fileio.c:2796
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Autokomendy skasowa³y lub wy³adowa³y bufor przeznaczony do zapisu"
+
+#: fileio.c:2819
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Autokomenda zmieni³a liczbê wierszy w nieoczekiwany sposób"
+
+#: fileio.c:2857
+msgid "NetBeans dissallows writes of unmodified buffers"
+msgstr "NetBeans nie pozwala na zapis niezmodyfikowanych buforów"
+
+#: fileio.c:2865
+msgid "Partial writes disallowed for NetBeans buffers"
+msgstr "Czê¶ciowy zapis niemo¿liwy dla buforów NetBeans"
+
+#: fileio.c:2919 fileio.c:2937
+msgid "is not a file or writable device"
+msgstr "nie jest plikiem lub zapisywalnym przyrz±dem"
+
+#: fileio.c:2989
+msgid "is read-only (add ! to override)"
+msgstr "jest tylko do odczytu (wymu¶ poprzez !)"
+
+#: fileio.c:3335
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: Nie mogê zapisaæ do pliku zabezpieczenia (wymu¶ przez !)"
+
+#: fileio.c:3347
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr "E507: B³±d podczas zamykania pliku zabezpieczenia (wymu¶ przez !)"
+
+#: fileio.c:3349
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr "E508: Nie mogê odczytaæ pliku w celu zabezpieczenia (wymu¶ przez !)"
+
+#: fileio.c:3365
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: Nie mogê stworzyæ pliku zabezpieczenia (wymu¶ przez !)"
+
+#: fileio.c:3468
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: Nie mogê zrobiæ pliku zabezpieczenia (wymu¶ przez !)"
+
+#: fileio.c:3530
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr "E460: Rozdzia³ zasobów zostanie utracony (wymu¶ przez !)"
+
+#: fileio.c:3640
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: Nie mogê znale¼æ pliku tymczasowego do zapisania"
+
+#: fileio.c:3658
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr "E213: Nie mogê przemieniæ (u¿yj ! by zapisaæ bez przemiany)"
+
+#: fileio.c:3693
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Nie mogê otworzyæ pod³±czonego pliku do zapisu"
+
+#: fileio.c:3697
+msgid "E212: Can't open file for writing"
+msgstr "E212: Nie mogê otworzyæ pliku do zapisu"
+
+#: fileio.c:3959
+msgid "E667: Fsync failed"
+msgstr "E667: Fsync nie powiód³ siê"
+
+#: fileio.c:3966
+msgid "E512: Close failed"
+msgstr "E512: Zamkniêcie siê nie powiod³o"
+
+#: fileio.c:4037
+msgid "E513: write error, conversion failed"
+msgstr "E513: b³±d w zapisie, przemiana siê nie powiod³a"
+
+#: fileio.c:4043
+msgid "E514: write error (file system full?)"
+msgstr "E514: b³±d w zapisie (mo¿e system plików jest przepe³niony?)"
+
+#: fileio.c:4110
+msgid " CONVERSION ERROR"
+msgstr " B£¡D W PRZEMIANIE"
+
+#: fileio.c:4126
+msgid "[Device]"
+msgstr "[Urz±dzenie]"
+
+#: fileio.c:4131
+msgid "[New]"
+msgstr "[Nowy]"
+
+#: fileio.c:4153
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:4153
+msgid " appended"
+msgstr " do³±czono"
+
+#: fileio.c:4155
+msgid " [w]"
+msgstr " [w]"
+
+#: fileio.c:4155
+msgid " written"
+msgstr " zapisano"
+
+#: fileio.c:4205
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: Patchmode: nie mogê zapisaæ oryginalnego pliku"
+
+#: fileio.c:4227
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: nie mogê stworzyæ pustego oryginalnego pliku"
+
+#: fileio.c:4242
+msgid "E207: Can't delete backup file"
+msgstr "E207: Nie mogê skasowaæ pliku zabezpieczenia"
+
+#: fileio.c:4306
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"OSTRZE¯ENIE: Oryginalny plik mo¿e zostaæ utracony lub uszkodzony\n"
+
+#: fileio.c:4308
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "nie wychod¼ edytora, dopóki plik nie zosta³ poprawnie zapisany!"
+
+#: fileio.c:4397
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:4397
+msgid "[dos format]"
+msgstr "[format dos-a]"
+
+#: fileio.c:4404
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:4404
+msgid "[mac format]"
+msgstr "[format mac-a]"
+
+#: fileio.c:4411
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:4411
+msgid "[unix format]"
+msgstr "[format unix-a]"
+
+#: fileio.c:4438
+msgid "1 line, "
+msgstr "1 wiersz, "
+
+#: fileio.c:4440
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld wierszy, "
+
+#: fileio.c:4443
+msgid "1 character"
+msgstr "1 znak"
+
+#: fileio.c:4445
+#, c-format
+msgid "%ld characters"
+msgstr "%ld znaków"
+
+#: fileio.c:4455
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:4455
+msgid "[Incomplete last line]"
+msgstr "[Niekompletny ostatni wiersz]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4474
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "OSTRZE¯ENIE: Plik zmieni³ siê od czasu ostatniego odczytu!!!"
+
+#: fileio.c:4476
+msgid "Do you really want to write to it"
+msgstr "Czy naprawdê chcesz go zapisaæ"
+
+#: fileio.c:5726
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: B³±d zapisywania do \"%s\""
+
+#: fileio.c:5733
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: B³±d w trakcie zamykania \"%s\""
+
+#: fileio.c:5736
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: B³±d odczytu \"%s\""
+
+#: fileio.c:5970
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: Autokomenda FileChangedShell skasowa³a bufor"
+
+#: fileio.c:5977
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: OSTRZE¯ENIE: Plik \"%s\" nie jest d³u¿ej dostêpny"
+
+#: fileio.c:5991
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: OSTRZE¯ENIE: Plik \"%s\" zmieni³ siê od czasu rozpoczêcia edycji, bufor "
+"w Vimie równie¿ zosta³ zmieniony"
+
+#: fileio.c:5994
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: OSTRZE¯ENIE: Plik \"%s\" zmieni³ siê od czasu rozpoczêcia edycji"
+
+#: fileio.c:5996
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: OSTRZE¯ENIE: Tryb pliku \"%s\" zmieni³ siê od czasu rozpoczêcia edycji"
+
+#: fileio.c:6006
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: OSTRZE¯ENIE: Plik \"%s\" zosta³ stworzony po rozpoczêciu edycji"
+
+#: fileio.c:6019
+msgid "See \":help W11\" for more info."
+msgstr "Patrz \":help W11\" dla dalszych informacji."
+
+#: fileio.c:6033
+msgid "Warning"
+msgstr "OSTRZE¯ENIE"
+
+#: fileio.c:6034
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Za³aduj Plik"
+
+#: fileio.c:6140
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: Nie mo¿na przygotowaæ prze³adowania \"%s\""
+
+#: fileio.c:6159
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: Nie mo¿na prze³adowaæ \"%s\""
+
+#: fileio.c:6740
+msgid "--Deleted--"
+msgstr "--Skasowano--"
+
+#. the group doesn't exist
+#: fileio.c:6900
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Nie ma takiej grupy: \"%s\""
+
+#: fileio.c:7026
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Niedopuszczalny znak po *: %s"
+
+#: fileio.c:7038
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Nie ma takiego wydarzenia: %s"
+
+#: fileio.c:7040
+#, c-format
+msgid "E216: No such group or event: %s"
+msgstr "E216: Nie ma takiej grupy lub wydarzenia: %s"
+
+#. Highlight title
+#: fileio.c:7198
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Autokomendy ---"
+
+#: fileio.c:7469
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Nie mo¿na wykonywaæ autokomend dla wydarzeñ ALL"
+
+#: fileio.c:7492
+msgid "No matching autocommands"
+msgstr "Brak pasuj±cych autokomend"
+
+#: fileio.c:7813
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: zbyt g³êbokie zagnie¿d¿enie autokomend"
+
+#: fileio.c:8088
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Autokomend dla \"%s\""
+
+#: fileio.c:8096
+#, c-format
+msgid "Executing %s"
+msgstr "Wykonujê %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:8164
+#, c-format
+msgid "autocommand %s"
+msgstr "autokomenda %s"
+
+#: fileio.c:8731
+msgid "E219: Missing {."
+msgstr "E219: Brak {."
+
+#: fileio.c:8733
+msgid "E220: Missing }."
+msgstr "E220: Brak }."
+
+#: fold.c:68
+msgid "E490: No fold found"
+msgstr "E490: Nie znaleziono zwiniêcia"
+
+#: fold.c:593
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: Nie mo¿na utworzyæ zwiniêcia przy bie¿±cej 'foldmethod'"
+
+#: fold.c:595
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: Nie mo¿na skasowaæ zwiniêcia przy bie¿±cej 'foldmethod'"
+
+#: getchar.c:248
+msgid "E222: Add to read buffer"
+msgstr "E222: Dodaj do bufora odczytu"
+
+#: getchar.c:2198
+msgid "E223: recursive mapping"
+msgstr "E223: rekursywne przyporz±dkowanie"
+
+#: getchar.c:3077
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: istnieje ju¿ globalny skrót dla %s"
+
+#: getchar.c:3080
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: istnieje ju¿ globalne przyporz±dkowanie dla %s"
+
+#: getchar.c:3212
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: istnieje ju¿ skrót dla %s"
+
+#: getchar.c:3215
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: istnieje ju¿ przyporz±dkowanie dla %s"
+
+#: getchar.c:3279
+msgid "No abbreviation found"
+msgstr "Nie znaleziono skrótu"
+
+#: getchar.c:3281
+msgid "No mapping found"
+msgstr "Nie znaleziono przyporz±dkowania"
+
+#: getchar.c:4173
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: Niedopuszczalny tryb"
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<nie mogê otworzyæ> "
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: nie mogê otrzymaæ czcionki %s"
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: nie mogê powróciæ do bie¿±cego katalogu"
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "Trop:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: nie mogê otrzymaæ bie¿±cego katalogu"
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "OK"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2731 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "Zakoñcz"
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "VIM - Dialog"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Scrollbar Widget: Nie mog³em otrzymaæ rozmiarów rysunku na przycisku."
+
+#: gui_beval.c:101 gui_w32.c:3830
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: Nie mogê stworzyæ BalloonEval z powiadomieniem i wywo³aniem"
+
+#: gui.c:220
+msgid "E229: Cannot start the GUI"
+msgstr "E229: Nie mogê odpaliæ GUI"
+
+#: gui.c:349
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Nie mogê czytaæ z \"%s\""
+
+#: gui.c:472
+msgid "E665: Cannot start GUI, no valid font found"
+msgstr "E665: Nie mo¿na uruchomiæ GUI, brak prawid³owej czcionki"
+
+#: gui.c:477
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: Niew³a¶ciwe 'guifontwide'"
+
+#: gui.c:547
+msgid "E599: Value of 'imactivatekey' is invalid"
+msgstr "E599: Nieprawid³owa warto¶æ 'imactivatekey'"
+
+#: gui.c:4061
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: Nie mogê zarezerwowaæ koloru %s"
+
+#: gui_gtk.c:1607
+msgid "Vim dialog..."
+msgstr "Dialog Vima..."
+
+#: gui_gtk.c:2060 message.c:2993
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Tak\n"
+"&Nie\n"
+"&Zakoñcz"
+
+#: gui_gtk.c:2268
+msgid "Input _Methods"
+msgstr "Input _Methods"
+
+#: gui_gtk.c:2534 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Szukaj i Zamieniaj..."
+
+#: gui_gtk.c:2542 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "VIM - Szukaj..."
+
+#: gui_gtk.c:2574 gui_motif.c:2888
+msgid "Find what:"
+msgstr "Znajd¼:"
+
+#: gui_gtk.c:2592 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "Zamieñ na:"
+
+#. whole word only button
+#: gui_gtk.c:2624 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "Dopasuj tylko ca³e wyrazy"
+
+#. match case button
+#: gui_gtk.c:2635 gui_motif.c:3048
+msgid "Match case"
+msgstr "Dopasuj wielko¶æ liter"
+
+#: gui_gtk.c:2645 gui_motif.c:2990
+msgid "Direction"
+msgstr "Kierunek"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2657 gui_motif.c:3002
+msgid "Up"
+msgstr "W górê"
+
+#: gui_gtk.c:2661 gui_motif.c:3010
+msgid "Down"
+msgstr "W dó³"
+
+#: gui_gtk.c:2683 gui_gtk.c:2685 gui_motif.c:2792
+msgid "Find Next"
+msgstr "Znajd¼ nastêpne"
+
+#: gui_gtk.c:2702 gui_gtk.c:2704 gui_motif.c:2809
+msgid "Replace"
+msgstr "Zamieñ"
+
+#: gui_gtk.c:2715 gui_gtk.c:2717 gui_motif.c:2822
+msgid "Replace All"
+msgstr "Zamieñ wszystkie"
+
+#: gui_gtk_x11.c:2327
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: otrzymano ¿±danie \"die\" od manad¿era sesji\n"
+
+#: gui_gtk_x11.c:3519
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: G³ówne okno nieoczekiwanie zniszczone\n"
+
+#: gui_gtk_x11.c:4138
+msgid "Font Selection"
+msgstr "Wybór czcionki"
+
+#: gui_gtk_x11.c:6035 ui.c:2117
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "U¿ywam CUT_BUFFER0 zamiast pustego wyboru"
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "Filtr"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "Katalogi"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "Pomoc"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "Pliki"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "Wybór"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "Cofnij"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: Nie mogê za³adowaæ czcionki Zap '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: Nie mogê u¿yæ czcionki %s"
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Wysy³am zawiadomienie koñcz±ce proces pochodny.\n"
+
+#: gui_w32.c:830
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Argument nie jest wspomagany: \"-%s\"; U¿ywaj wersji OLE."
+
+#: gui_w48.c:2090
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Znajd¼ ci±g (u¿yj '\\\\' do szukania '\\')"
+
+#: gui_w48.c:2115
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Szukanie i Zamiana (u¿yj '\\\\' do szukania '\\')"
+
+#: gui_x11.c:1537
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: Nie mogê zarezerwowaæ mapy kolorów, pewne kolory mog± byæ "
+"nieprawid³owe"
+
+#: gui_x11.c:2118
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: Brak czcionek dla nastêpuj±cych zestawów znaków w zestawie czcionek %s:"
+
+#: gui_x11.c:2161
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Nazwa zestawu czcionek: %s"
+
+#: gui_x11.c:2162
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "Czcionka '%s' nie posiada znaków jednolitej szeroko¶ci"
+
+#: gui_x11.c:2181
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Nazwa zestawu czcionek: %s\n"
+
+#: gui_x11.c:2182
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Font0: %s\n"
+
+#: gui_x11.c:2183
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Font1: %s\n"
+
+#: gui_x11.c:2184
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "szeroko¶æ font%d nie jest podwójn± szeroko¶ci± font0\n"
+
+#: gui_x11.c:2185
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "Szeroko¶æ font0: %ld\n"
+
+#: gui_x11.c:2186
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"Szeroko¶æ font1: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: B£¡D w automacie Hangul"
+
+#: if_cscope.c:77
+msgid "Add a new database"
+msgstr "Dodaj now± bazê danych"
+
+#: if_cscope.c:79
+msgid "Query for a pattern"
+msgstr "Zapytane o wzorzec"
+
+#: if_cscope.c:81
+msgid "Show this message"
+msgstr "Poka¿ ten komunikat"
+
+#: if_cscope.c:83
+msgid "Kill a connection"
+msgstr "Zabij po³±czenie"
+
+#: if_cscope.c:85
+msgid "Reinit all connections"
+msgstr "Ponów wszelkie po³±czenia"
+
+#: if_cscope.c:87
+msgid "Show connections"
+msgstr "Poka¿ po³±czenia"
+
+#: if_cscope.c:95
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: Zastosowanie: cs[cope] %s"
+
+#: if_cscope.c:124
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Ta komenda cscope nie wspomaga podzielenia okna.\n"
+
+#: if_cscope.c:175
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: Zastosowanie: cstag <ident>"
+
+#: if_cscope.c:231
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: nie znaleziono znacznika"
+
+#: if_cscope.c:409
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: stat(%s) b³±d: %d"
+
+#: if_cscope.c:419
+msgid "E563: stat error"
+msgstr "E563: b³±d stat"
+
+#: if_cscope.c:516
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s nie jest katalogiem lub poprawn± baz± danych cscope"
+
+#: if_cscope.c:534
+#, c-format
+msgid "Added cscope database %s"
+msgstr "Dodano bazê danych cscope %s"
+
+#: if_cscope.c:589
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: b³±d odczytu po³±czenia z cscope %ld"
+
+#: if_cscope.c:694
+msgid "E561: unknown cscope search type"
+msgstr "E561: nieznany typ szukania cscope"
+
+#: if_cscope.c:736
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: Nie mog³em stworzyæ potoku do cscope"
+
+#: if_cscope.c:753
+msgid "E622: Could not fork for cscope"
+msgstr "E622: Nie mog³em utworzyæ rozwidlenia dla cscope"
+
+#: if_cscope.c:847 if_cscope.c:897
+msgid "cs_create_connection exec failed"
+msgstr "wykonanie cs_create_connection nie powiod³o siê"
+
+#: if_cscope.c:898
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: Nie mog³em stworzyæ procesu cscope"
+
+#: if_cscope.c:911
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen dla to_fp nie powiod³o siê"
+
+#: if_cscope.c:913
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen dla fr_fp nie powiod³o siê"
+
+#: if_cscope.c:951
+msgid "E567: no cscope connections"
+msgstr "E567: brak po³±czenia z cscope"
+
+#: if_cscope.c:1025
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: brak dopasowañ dla zapytania cscope %s o %s"
+
+#: if_cscope.c:1082
+#, c-format
+msgid "E469: invalid cscopequickfix flag %c for %c"
+msgstr "E469: nieprawid³owa flaga cscopequickfix %c dla %c"
+
+#: if_cscope.c:1152
+msgid "cscope commands:\n"
+msgstr "komendy cscope:\n"
+
+#: if_cscope.c:1155
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (U¿ycie: %s)"
+
+#: if_cscope.c:1253
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: nie mogê otworzyæ bazy danych cscope: %s"
+
+#: if_cscope.c:1271
+msgid "E626: cannot get cscope database information"
+msgstr "E626: nie mogê uzyskaæ informacji z bazy danych cscope"
+
+#: if_cscope.c:1296
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: nie dodano duplikatu bazy danych cscope"
+
+#: if_cscope.c:1307
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: wyczerpano maksymaln± liczbê po³±czeñ cscope"
+
+#: if_cscope.c:1424
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: nie ma po³±czenia %s z cscope"
+
+#: if_cscope.c:1458
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "po³±czenie %s z cscope zosta³o zamkniête"
+
+#. should not reach here
+#: if_cscope.c:1598
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: b³±d krytyczny w cs_manage_matches"
+
+#: if_cscope.c:1848
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "Znacznik cscope: %s"
+
+#: if_cscope.c:1870
+msgid ""
+"\n"
+" # line"
+msgstr ""
+"\n"
+" # wiersz"
+
+#: if_cscope.c:1872
+msgid "filename / context / line\n"
+msgstr "nazwa pliku / kontekst / wiersz\n"
+
+#: if_cscope.c:1990
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: B³±d cscope: %s"
+
+#: if_cscope.c:2176
+msgid "All cscope databases reset"
+msgstr "Wszystkie bazy danych cscope prze³adowano"
+
+#: if_cscope.c:2244
+msgid "no cscope connections\n"
+msgstr "brak po³±czeñ z cscope\n"
+
+#: if_cscope.c:2248
+msgid " # pid database name prepend path\n"
+msgstr " # pid nazwa bazy danych przedsionek tropu\n"
+
+#: if_python.c:436
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: Przykro mi, ta komenda jest wy³±czona, bo nie mo¿na za³adowaæ "
+"biblioteki Pythona"
+
+#: if_python.c:500
+msgid "E659: Cannot invoke Python recursively"
+msgstr "E659: Nie mo¿na wywo³aæ Pythona rekursywnie"
+
+#: if_python.c:701
+msgid "can't delete OutputObject attributes"
+msgstr "nie mogê skasowaæ atrybutów OutputObject"
+
+#: if_python.c:708
+msgid "softspace must be an integer"
+msgstr "softspace musi byæ liczb± ca³kowit±"
+
+#: if_python.c:716
+msgid "invalid attribute"
+msgstr "niepoprawny atrybut"
+
+#: if_python.c:755 if_python.c:769
+msgid "writelines() requires list of strings"
+msgstr "writelines() wymaga listy ci±gów"
+
+#: if_python.c:895
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: B³±d w inicjalizacji obiektów I/O"
+
+#: if_python.c:1080 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "niepoprawne wyra¿enie"
+
+#: if_python.c:1094 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "wyra¿enia wy³±czone podczas kompilacji"
+
+#: if_python.c:1107
+msgid "attempt to refer to deleted buffer"
+msgstr "próba odniesienia do skasowanego bufora"
+
+#: if_python.c:1122 if_python.c:1163 if_python.c:1227 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "numer wiersza poza zakresem"
+
+#: if_python.c:1362
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<obiekt bufora (skasowany) w %8lX>"
+
+#: if_python.c:1453 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "niepoprawna nazwa zak³adki"
+
+#: if_python.c:1733
+msgid "no such buffer"
+msgstr "nie ma takiego bufora"
+
+#: if_python.c:1821
+msgid "attempt to refer to deleted window"
+msgstr "próba odniesienia do skasowanego okna"
+
+#: if_python.c:1866
+msgid "readonly attribute"
+msgstr "atrybut tylko do odczytu"
+
+#: if_python.c:1879
+msgid "cursor position outside buffer"
+msgstr "pozycja kursora poza buforem"
+
+#: if_python.c:1956
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<obiekt okna (skasowany) w %.8lX>"
+
+#: if_python.c:1968
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<obiekt okna (nieznany) w %.8lX>"
+
+#: if_python.c:1970
+#, c-format
+msgid "<window %d>"
+msgstr "<okno %d>"
+
+#: if_python.c:2046
+msgid "no such window"
+msgstr "nie ma takiego okna"
+
+#: if_python.c:2307 if_python.c:2341 if_python.c:2396 if_python.c:2464
+#: if_python.c:2586 if_python.c:2638 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "nie mogê zachowaæ informacji cofania"
+
+#: if_python.c:2309 if_python.c:2403 if_python.c:2475
+msgid "cannot delete line"
+msgstr "nie mogê skasowaæ wiersza"
+
+#: if_python.c:2346 if_python.c:2491 if_tcl.c:690 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "nie mogê zamieniæ wiersza"
+
+#: if_python.c:2509 if_python.c:2588 if_python.c:2646
+msgid "cannot insert line"
+msgstr "nie mogê wprowadziæ wiersza"
+
+#: if_python.c:2750
+msgid "string cannot contain newlines"
+msgstr "ci±g nie mo¿e zawieraæ znaków nowego wiersza"
+
+#: if_ruby.c:422
+msgid "E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E263: Przykro mi, ta komenda jest wy³±czona, bo nie mo¿na za³adowaæ "
+"biblioteki Ruby."
+
+#: if_ruby.c:485
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: Nieznany status longjmp %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Prze³±cz miêdzy implementacj±/okre¶leniem"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Poka¿ bazê klasy"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Poka¿ przepisan± funkcjê cz³onkow±"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Pobieraj z pliku"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Pobieraj z projektu"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Pobieraj z wszystkich projektów"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Pobierz"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Poka¿ ¼ród³o dla"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Znajd¼ symbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Przejrzyj klasê"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Poka¿ klasê w hierarchii"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Poka¿ klasê w ograniczonej hierarchii"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref odnosi siê do"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref ma odniesienia od"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref ma"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref u¿yte przez"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Poka¿ dokumentacjê dla"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Wygeneruj dokumentacjê dla"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"Nie mogê pod³±czyæ do SNiFF+. Sprawd¼ ¶rodowisko (sniffemacs musi byæ "
+"odnaleziony w $PATH).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: B³±d podczas czytania. Roz³±czenie"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ jest obecnie "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "nie "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "pod³±czony"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Nieznane zapytanie SNiFF+: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: B³±d w trakcie pod³±czania do SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ niepod³±czony"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Nie jest buforem SNiFF+"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: B³±d w trakcie zapisu. Roz³±czony"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "niew³a¶ciwy numer bufora"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "obecnie nie zaimplementowano"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "nieznana opcja"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "nie mogê ustawiæ wiersza(y)"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "zak³adka nie ustawiona"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "wiersz %d kolumna %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "nie mogê wprowadziæ/do³±czyæ wiersza"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "nieznana flaga: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "nieznane vimOption"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "przerwanie klawiatury"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "b³±d vima"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "nie mogê stworzyæ bufora/okna komendy: obiekt jest kasowany"
+
+#: if_tcl.c:1545
+msgid "cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"nie mogê zarejestrowaæ wstecznego wywo³ania komendy: bufor/okno ju¿ zosta³a "
+"skasowana"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: TCL FATALNY B£¡D: reflist zepsuta!? Proszê z³o¿yæ raport o tym na vim-"
+"dev@vim.org"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"nie mogê zarejestrowaæ wstecznego wywo³ania komendy: brak odniesienia do "
+"bufora/okna"
+
+#: if_tcl.c:1724
+msgid "E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr "Przykro mi, ta komenda jest wy³±czona, bo nie mo¿na za³adowaæ biblioteki Tcl."
+
+#: if_tcl.c:1886
+msgid "E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: B£¡D TCL: kod zakoñczeniowy nie jest ca³kowity!? Proszê z³o¿yæ raport "
+"o tym na vim-dev@vim.org"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "nie mogê dostaæ wiersza"
+
+#: if_xcmdsrv.c:225
+msgid "Unable to register a command server name"
+msgstr "Nie mogê zarejestrowaæ nazwy serwera komend"
+
+#: if_xcmdsrv.c:473
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Wys³anie komendy do programu docelowego nie powiod³o siê"
+
+#: if_xcmdsrv.c:747
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: U¿yto niew³a¶ciwego id serwera: %s"
+
+#: if_xcmdsrv.c:1110
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: wcielenia instancji rejestru Vima jest ¼le sformowane. Skasowano!"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "Nieznana opcja"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "Zbyt wiele argumentów"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "Brak argumentu po"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "¦miecie po opcji"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr "Zbyt wiele argumentów \"+komenda\", \"-c komenda\" lub \"--cmd komenda\""
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "Niew³a¶ciwy argument dla"
+
+#: main.c:466
+msgid "This Vim was not compiled with the diff feature."
+msgstr "Ta wersja Vima nie by³a skompilowanego z opcj± ró¿nic (diff)."
+
+#: main.c:932
+msgid "Attempt to open script file again: \""
+msgstr "Próba ponownego otworzenia pliku skryptu: \""
+
+#: main.c:941
+msgid "Cannot open for reading: \""
+msgstr "Nie mogê otworzyæ do odczytu: \""
+
+#: main.c:985
+msgid "Cannot open for script output: \""
+msgstr "Nie mogê otworzyæ dla wyj¶cia skryptu: \""
+
+#: main.c:1132
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d plików do edycji\n"
+
+#: main.c:1233
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: OSTRZE¯ENIE: Wyj¶cie nie jest terminalem\n"
+
+#: main.c:1235
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: OSTRZE¯ENIE: Wej¶cie nie pochodzi z terminala\n"
+
+#. just in case..
+#: main.c:1297
+msgid "pre-vimrc command line"
+msgstr "linia poleceñ pre-vimrc"
+
+#: main.c:1338
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Nie mogê czytaæ z \"%s\""
+
+#: main.c:2411
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Dalsze informacje poprzez: \"vim -h\"\n"
+
+#: main.c:2444
+msgid "[file ..] edit specified file(s)"
+msgstr "[plik ..] edytuj zadane pliki"
+
+#: main.c:2445
+msgid "- read text from stdin"
+msgstr "- czytaj tekst ze stdin"
+
+#: main.c:2446
+msgid "-t tag edit file where tag is defined"
+msgstr "-t znacznik edytuj plik, w którym dany znacznik jest zdefiniowany"
+
+#: main.c:2448
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [errorfile] edytuj plik, zawieraj±cy pierwszy b³±d"
+
+#: main.c:2457
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"u¿ycie:"
+
+#: main.c:2460
+msgid " vim [arguments] "
+msgstr " vim [argumenty]"
+
+#: main.c:2464
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" lub:"
+
+#: main.c:2467
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Argumenty:\n"
+
+#: main.c:2468
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tTylko nazwy plików po tym"
+
+#: main.c:2470
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tNie rozwijaj znaków specjalnych"
+
+#: main.c:2473
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tZarejestruj tego gvima w OLE"
+
+#: main.c:2474
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tWyrejestruj gvima z OLE"
+
+#: main.c:2477
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tStartuj w GUI (tak jak \"gvim\")"
+
+#: main.c:2478
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f lub --nofork\tPierwszy plan: Nie wydzielaj przy odpalaniu GUI"
+
+#: main.c:2480
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tTryb vi (jak \"vi\")"
+
+#: main.c:2481
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tTryb ex (jak \"ex\")"
+
+#: main.c:2482
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tCichy tryb (t³a) (tylko dla \"ex\")"
+
+#: main.c:2484
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tTryb ró¿nic (jak \"vimdiff\")"
+
+#: main.c:2486
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tTryb ³atwy (jak \"evim\", bez trybów)"
+
+#: main.c:2487
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tTryb wy³±cznie do odczytu (jak \"view\")"
+
+#: main.c:2488
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tTryb ograniczenia (jak \"rvim\")"
+
+#: main.c:2489
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tModyfikacje (zapisywanie plików) niedozwolone"
+
+#: main.c:2490
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tZakaz modyfikacji tekstu"
+
+#: main.c:2491
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tTryb binarny"
+
+#: main.c:2493
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tTryb lisp"
+
+#: main.c:2495
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tB±d¼ zgodny z Vi: 'compatible'"
+
+#: main.c:2496
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tB±d¼ niezupe³nie zgodny z Vi: 'nocompatible'"
+
+#: main.c:2497
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tStopieñ gadatliwo¶ci"
+
+#: main.c:2498
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tTryb odpluskwiania"
+
+#: main.c:2499
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tZamiast pliku wymiany, u¿ywaj tylko pamiêci"
+
+#: main.c:2500
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tWylicz pliki wymiany i zakoñcz"
+
+#: main.c:2501
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (z nazw± pliku)\tOdtwórz za³aman± sesjê"
+
+#: main.c:2502
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tTo¿same z -r"
+
+#: main.c:2504
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tNie stosuj newcli do otwierania okien"
+
+#: main.c:2505
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <device>\t\tU¿ywaj <device> do I/O"
+
+#: main.c:2508
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\t\trozpocznij w trybie arabskim"
+
+#: main.c:2511
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\trozpocznij w trybie hebrajskim"
+
+#: main.c:2514
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\trozpocznij w trybie farsi"
+
+#: main.c:2516
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\tUstaw typ terminala na <terminal>"
+
+#: main.c:2517
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tU¿yj <vimrc> zamiast jakiegokolwiek .vimrc"
+
+#: main.c:2519
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tU¿yj <gvimrc> zamiast jakiegokolwiek .gvimrc"
+
+#: main.c:2521
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tNie ³aduj skryptów wtyczek"
+
+#: main.c:2522
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tOtwórz N okien (domy¶lnie: po jednym dla ka¿dego pliku)"
+
+#: main.c:2523
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\ttak samo jak -o tylko dziel okno pionowo"
+
+#: main.c:2524
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tZacznij na koñcu pliku"
+
+#: main.c:2525
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\tZacznij w wierszu <lnum>"
+
+#: main.c:2527
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr ""
+"-cmd <command>\t\tWykonaj komendê <command> przed za³adowaniem "
+"jakiegokolwiek pliku vimrc"
+
+#: main.c:2529
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <command>\t\tWykonaj komendê <command> po za³adowaniu pierwszego pliku"
+
+#: main.c:2530
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <sesja>\t\tWczytaj plik <sesja> po za³adowaniu pierwszego pliku"
+
+#: main.c:2531
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <scriptin>\tWczytuj komendy trybu normalnego z pliku <scriptin>"
+
+#: main.c:2532
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <scriptout>\tDo³±cz wszystkie wprowadzane komendy do pliku <scriptout>"
+
+#: main.c:2533
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <scriptout>\tZapisuj wszystkie wprowadzane komendy do pliku <scriptout>"
+
+#: main.c:2535
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tEdytuj zakodowane pliki"
+
+#: main.c:2539
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\tPod³±cz vima to danego X-serwera"
+
+#: main.c:2541
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tNie ³±cz z serwerem X"
+
+#: main.c:2544
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <pliki>\tEdytuj pliki w serwerze Vima je¶li mo¿liwe"
+
+#: main.c:2545
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-silent <pliki> To samo, nie narzekaj je¶li nie ma serwera"
+
+#: main.c:2546
+msgid "--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <pliki>\tTak jak --remote, lecz czekaj na pliki przed edycj±"
+
+#: main.c:2547
+msgid "--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-wait-silent <pliki> To samo, nie narzekaj je¶li nie ma serwera"
+
+#: main.c:2548
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <klawisze>\tWy¶lij <klawisze> do serwera Vima i zakoñcz"
+
+#: main.c:2549
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <wyr>\tWykonaj <wyra¿enie> w serwerze i wypisz wynik"
+
+#: main.c:2550
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tWymieñ nazwy dostêpnych serwerów Vima i zakoñcz"
+
+#: main.c:2551
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <nazwa>\t\tOdsy³aj do/stañ siê serwerem Vim <nazwa>"
+
+#: main.c:2554
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tU¿ywaj <viminfo> zamiast .viminfo"
+
+#: main.c:2556
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h lub --help\twy¶wietl Pomoc (czyli tê wiadomo¶æ) i zakoñcz"
+
+#: main.c:2557
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\twy¶wietl informacjê o wersji i zakoñcz"
+
+#: main.c:2561
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Argumenty rozpoznawane przez gvim (wersja Motif):\n"
+
+#: main.c:2565
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr ""
+"\n"
+"Argumenty rozpoznawane przez gvim (wersja neXtaw):\n"
+
+#: main.c:2567
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Argumenty rozpoznawane przez gvim (wersja Athena):\n"
+
+#: main.c:2571
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\tZa³aduj vim na <display>"
+
+#: main.c:2572
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tZacznij Vim jako ikonê"
+
+#: main.c:2574
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <nazwa>\t\tU¿ywaj zasobów tak jak by Vim by³ <nazwa>"
+
+#: main.c:2575
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (Niezaimplementowane)\n"
+
+#: main.c:2577
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <kolor>\tU¿ywaj <kolor> dla t³a (równie¿: -bg)"
+
+#: main.c:2578
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <kolor>\tU¿ywaj <kolor> dla normalnego tekstu (równie¿: -fg)"
+
+#: main.c:2579 main.c:2599
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <font>\t\tU¿ywaj <font> dla normalnego tekstu (równie¿: -fn)"
+
+#: main.c:2580
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <font>\tU¿ywaj <font> dla wyt³uszczonego tekstu"
+
+#: main.c:2581
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <font>\tU¿ywaj <font> dla pochy³ego"
+
+#: main.c:2582 main.c:2600
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\tU¿ywaj <geom> dla pocz±tkowych rozmiarów (równie¿: -geom)"
+
+#: main.c:2583
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <szer>\tU¿yj ramki o grubo¶ci <szer> (równie¿: -bw)"
+
+#: main.c:2584
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <szer> U¿ywaj przewijacza o szeroko¶ci <szer> (równie¿: -sw)"
+
+#: main.c:2586
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <height>\tStosuj belkê menu o wysoko¶ci <height> (równie¿: -mh)"
+
+#: main.c:2588 main.c:2601
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tStosuj negatyw kolorów (równie¿: -rv)"
+
+#: main.c:2589
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tNie stosuj negatywu kolorów (równie¿: +rv)"
+
+#: main.c:2590
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\tUstaw okre¶lony zasób"
+
+#: main.c:2593
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Argumenty rozpoznawane przez gvim (wersja RISC OS):\n"
+
+#: main.c:2594
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <number>\tPocz±tkowa szeroko¶æ okna w kolumnach"
+
+#: main.c:2595
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <number>\tPocz±tkowa wysoko¶æ okna w wierszach"
+
+#: main.c:2598
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Argumenty rozpoznawane przez gvim (wersja GTK+):\n"
+
+#: main.c:2602
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\tZastartuj vim na <display> (równie¿: --display)"
+
+#: main.c:2604
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr "--role <role>\tUstaw unikatow± rolê do identyfikacji g³ównego okna"
+
+#: main.c:2606
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tOtwórz Vim wewn±trz innego widgetu GTK"
+
+#: main.c:2609
+msgid "-P <parent title>\tOpen Vim inside parent application"
+msgstr "-P <tytu³ rodzica>\tOtwórz Vima wewn±trz rodzicielskiej aplikacji"
+
+#: main.c:2847
+msgid "No display"
+msgstr "Brak display"
+
+#. Failed to send, abort.
+#: main.c:2862
+msgid ": Send failed.\n"
+msgstr ": Wys³anie nie powiod³o siê.\n"
+
+#. Let vim start normally.
+#: main.c:2868
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": Wys³anie nie powiod³o siê. Próbujê wykonaæ na miejscu\n"
+
+#: main.c:2906 main.c:2927
+#, c-format
+msgid "%d of %d edited"
+msgstr "otworzono %d z %d"
+
+#: main.c:2949
+msgid "No display: Send expression failed.\n"
+msgstr "Brak terminala: Wys³anie wyra¿enia nie powiod³o siê.\n"
+
+#: main.c:2961
+msgid ": Send expression failed.\n"
+msgstr ": Wys³anie wyra¿enia nie powiod³o siê.\n"
+
+#: mark.c:709
+msgid "No marks set"
+msgstr "Brak zak³adek"
+
+#: mark.c:711
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: ¯adna zak³adka nie pasuje do \"%s\""
+
+#. Highlight title
+#: mark.c:722
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"zak³. wiersz kol plik/tekst"
+
+#. Highlight title
+#: mark.c:760
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" skok wiersz kol plik/tekst"
+
+#. Highlight title
+#: mark.c:805
+msgid ""
+"\n"
+"change line col text"
+msgstr ""
+"\n"
+"zmieñ wrsz. kol tekst"
+
+#: mark.c:1281
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Zak³adki w plikach:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1316
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Lista odniesieñ (pocz±wszy od najnowszych):\n"
+
+#: mark.c:1412
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Historia zak³adek w plikach (od najnowszych po najstarsze):\n"
+
+#: mark.c:1501
+msgid "Missing '>'"
+msgstr "Brak '>'"
+
+#: mbyte.c:467
+msgid "E543: Not a valid codepage"
+msgstr "E543: To nie jest wa¿na strona kodowa"
+
+#: mbyte.c:4431
+msgid "E284: Cannot set IC values"
+msgstr "E284: Nie mogê nastawiæ warto¶ci IC"
+
+#: mbyte.c:4583
+msgid "E285: Failed to create input context"
+msgstr "E285: Nie mog³em stworzyæ kontekstu wprowadzeñ"
+
+#: mbyte.c:4741
+msgid "E286: Failed to open input method"
+msgstr "E286: Nie mog³em otworzyæ sposobu wprowadzeñ"
+
+#: mbyte.c:4752
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: OSTRZE¯ENIE: Nie mog³em zlikwidowaæ wywo³ania dla IM"
+
+#: mbyte.c:4758
+msgid "E288: input method doesn't support any style"
+msgstr "E288: metoda wprowadzeñ nie wspomaga ¿adnego stylu"
+
+#: mbyte.c:4815
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: metoda wprowadzeñ nie wspomaga mojego typu preedit"
+
+#: mbyte.c:4889
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: styl nadpunktowy wymaga +fontset"
+
+#: mbyte.c:4925
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: Twój GTK+ jest starszy ni¿ 1.2.3. Pole statusu wy³±czono"
+
+#: mbyte.c:5232
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Serwer metod wprowadzeñ nie jest uruchomiony"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: blok nie by³ zablokowany"
+
+#: memfile.c:1005
+msgid "E294: Seek error in swap file read"
+msgstr "E294: B³±d w trakcie czytania pliku wymiany"
+
+#: memfile.c:1010
+msgid "E295: Read error in swap file"
+msgstr "E295: B³±d odczytu pliku wymiany"
+
+#: memfile.c:1062
+msgid "E296: Seek error in swap file write"
+msgstr "E296: B³±d szukania w pliku wymiany"
+
+#: memfile.c:1080
+msgid "E297: Write error in swap file"
+msgstr "E297: B³±d zapisu w pliku wymiany"
+
+#: memfile.c:1277
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: Plik wymiany ju¿ istnieje (atak symlink?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Nie otrzyma³em bloku nr 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Nie otrzyma³em bloku nr 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: Nie otrzyma³em bloku nr 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Ojej, zgubi³em plik wymiany!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: Nie mog³em zmieniæ nazwy pliku wymiany"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: Nie mogê otworzyæ pliku wymiany dla \"%s\"; odtworzenie niemo¿liwe"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: Nie otrzyma³em bloku 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Nie znaleziono pliku wymiany dla %s"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "Wprowad¼ numer pliku wymiany, którego u¿yæ (0 by wyj¶æ): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: Nie mogê otworzyæ %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "Nie mogê odczytaæ bloku 0 z "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Mo¿e nie wykonano zmian albo Vim nie zaktualizowa³ pliku wymiany."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " nie mo¿e byæ stosowany z t± wersj± Vima.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "U¿yj Vima w wersji 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s nie wygl±da na plik wymiany Vima"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " nie mo¿e byæ stosowany na tym komputerze.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "Ten plik zosta³ stworzony na "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"lub plik zosta³ uszkodzony."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "U¿ywam pliku wymiany \"%s\""
+
+#: memline.c:909
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Oryginalny plik \"%s\""
+
+#: memline.c:922
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: OSTRZE¯ENIE: Oryginalny plik móg³ byæ zmieniony"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Nie mogê odczytaæ bloku 1 z %s"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???BRAKUJE WIELU WIERSZY"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???LICZNIK WIERSZY NIEZGODNY"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???PUSTY BLOK"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???BRAKUJE WIERSZY"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: Niew³a¶ciwe ID bloku 1 (mo¿e %s nie jest plikiem .swp?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???BRAK BLOKU"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? od tego miejsca po ???KONIEC wiersze mog± byæ pomieszane"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? od tego miejsca po ???KONIEC wiersze mog± byæ w³o¿one/skasowane"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???KONIEC"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Przerwanie odtwarzania"
+
+#: memline.c:1148
+msgid "E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: Wykryto b³êdy podczas odtwarzania; od których wierszy zacz±æ ???"
+
+#: memline.c:1150
+msgid "See \":help E312\" for more information."
+msgstr "Patrz \":help E312\" dla dalszych informacji."
+
+#: memline.c:1155
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Odtwarzanie zakoñczono. Powiniene¶ sprawdziæ czy wszystko jest w porz±dku."
+
+#: memline.c:1156
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Mo¿esz chcieæ zapisaæ ten plik pod inn± nazw±\n"
+
+#: memline.c:1157
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "i wykonaæ diff z oryginalnym plikiem aby sprawdziæ zmiany)\n"
+
+#: memline.c:1158
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"Skasuj potem plik .swp.\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1214
+msgid "Swap files found:"
+msgstr "Znalezione pliki wymiany:"
+
+#: memline.c:1392
+msgid " In current directory:\n"
+msgstr " W bie¿±cym katalogu:\n"
+
+#: memline.c:1394
+msgid " Using specified name:\n"
+msgstr " U¿ywam podanej nazwy:\n"
+
+#: memline.c:1398
+msgid " In directory "
+msgstr " W katalogu "
+
+#: memline.c:1416
+msgid " -- none --\n"
+msgstr " -- ¿aden --\n"
+
+#: memline.c:1488
+msgid " owned by: "
+msgstr " posiadany przez: "
+
+#: memline.c:1490
+msgid " dated: "
+msgstr " data: "
+
+#: memline.c:1494 memline.c:3684
+msgid " dated: "
+msgstr " data: "
+
+#: memline.c:1510
+msgid " [from Vim version 3.0]"
+msgstr " [po Vimie wersja 3.0]"
+
+#: memline.c:1514
+msgid " [does not look like a Vim swap file]"
+msgstr " [nie wygl±da na plik wymiany Vima]"
+
+#: memline.c:1518
+msgid " file name: "
+msgstr " nazwa pliku: "
+
+#: memline.c:1524
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" zmieniono: "
+
+#: memline.c:1525
+msgid "YES"
+msgstr "TAK"
+
+#: memline.c:1525
+msgid "no"
+msgstr "nie"
+
+#: memline.c:1529
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" u¿ytkownik: "
+
+#: memline.c:1536
+msgid " host name: "
+msgstr " nazwa hosta: "
+
+#: memline.c:1538
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" nazwa hosta: "
+
+#: memline.c:1544
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ID procesu: "
+
+#: memline.c:1550
+msgid " (still running)"
+msgstr " (dalej dzia³a)"
+
+#: memline.c:1562
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [nie nadaje siê dla tej wersji Vima]"
+
+#: memline.c:1565
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [nie do u¿ytku na tym komputerze]"
+
+#: memline.c:1570
+msgid " [cannot be read]"
+msgstr " [nieodczytywalny]"
+
+#: memline.c:1574
+msgid " [cannot be opened]"
+msgstr " [nieotwieralny]"
+
+#: memline.c:1764
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Nie mogê zabezpieczyæ, bo brak pliku wymiany"
+
+#: memline.c:1817
+msgid "File preserved"
+msgstr "Plik zabezpieczono"
+
+#: memline.c:1819
+msgid "E314: Preserve failed"
+msgstr "E314: Nieudane zabezpieczenie"
+
+#: memline.c:1890
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: niew³a¶ciwy lnum: %ld"
+
+#: memline.c:1916
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: nie znaleziono wiersza %ld"
+
+#: memline.c:2306
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: niepoprawne id wska¼nika bloku 3"
+
+#: memline.c:2386
+msgid "stack_idx should be 0"
+msgstr "stack_idx powinien byæ 0"
+
+#: memline.c:2448
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Zaktualizowano zbyt wiele bloków?"
+
+#: memline.c:2630
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: niepoprawne id wska¼nika bloku 4"
+
+#: memline.c:2657
+msgid "deleted block 1?"
+msgstr "blok nr 1 skasowany?"
+
+#: memline.c:2857
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Nie mogê znale¼æ wiersza %ld"
+
+#: memline.c:3100
+msgid "E317: pointer block id wrong"
+msgstr "E317: niepoprawne id bloku odniesienia"
+
+#: memline.c:3116
+msgid "pe_line_count is zero"
+msgstr "pe_line_count wynosi zero"
+
+#: memline.c:3145
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: numer wiersza poza zakresem: %ld jest poza koñcem"
+
+#: memline.c:3149
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: liczba wierszy niepoprawna w bloku %ld"
+
+#: memline.c:3198
+msgid "Stack size increases"
+msgstr "Wielko¶æ stosu wzrasta"
+
+#: memline.c:3244
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: niepoprawne id bloku odniesienia 2"
+
+#: memline.c:3674
+msgid "E325: ATTENTION"
+msgstr "E325: UWAGA"
+
+#: memline.c:3675
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Znalaz³em plik wymiany o nazwie \""
+
+#: memline.c:3679
+msgid "While opening file \""
+msgstr "Podczas otwierania pliku \""
+
+#: memline.c:3688
+msgid " NEWER than swap file!\n"
+msgstr " NOWSZE od pliku wymiany!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3692
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Pewnie inny program obrabia ten sam plik.\n"
+" Je¶li tak, b±d¼ ostro¿ny, aby nie skoñczyæ z dwoma\n"
+" ró¿nymi wersjami jednego tego samego pliku po zmianach.\n"
+
+#: memline.c:3693
+msgid " Quit, or continue with caution.\n"
+msgstr " Zakoñcz lub ostro¿nie kontynuuj.\n"
+
+#: memline.c:3694
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) Sesja edycji dla pliku za³ama³a siê.\n"
+
+#: memline.c:3695
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Je¶li tak, to u¿yj \":recover\" lub \"vim -r "
+
+#: memline.c:3697
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" aby odzyskaæ zmiany (patrz \":help recovery)\").\n"
+
+#: memline.c:3698
+msgid " If you did this already, delete the swap file \""
+msgstr " Je¶li ju¿ to zrobi³e¶, usuñ plik wymiany \""
+
+#: memline.c:3700
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" aby unikn±æ tej wiadomo¶ci.\n"
+
+#: memline.c:3714 memline.c:3718
+msgid "Swap file \""
+msgstr "Plik wymiany \""
+
+#: memline.c:3715 memline.c:3721
+msgid "\" already exists!"
+msgstr "\" ju¿ istnieje!"
+
+#: memline.c:3724
+msgid "VIM - ATTENTION"
+msgstr "VIM - UWAGA"
+
+#: memline.c:3726
+msgid "Swap file already exists!"
+msgstr "Plik wymiany ju¿ istnieje!"
+
+#: memline.c:3730
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort"
+msgstr ""
+"&Otwórz Read-Only\n"
+"&Edytuj pomimo\n"
+"O&dtwórz\n"
+"&Zakoñcz\n"
+"&Porzuæ"
+
+#: memline.c:3732
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort\n"
+"&Delete it"
+msgstr ""
+"&Otwórz Read-Only\n"
+"&Edytuj pomimo\n"
+"O&dtwórz\n"
+"&Zakoñcz\n"
+"&Porzuæ\n"
+"&Skasuj go"
+
+#: memline.c:3789
+msgid "E326: Too many swap files found"
+msgstr "E326: Znaleziono zbyt wiele plików wymiany"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Czê¶æ tropu punktu menu nie okre¶la podmenu"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Menu istnieje tylko w innym trybie"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Nie ma menu o tej nazwie"
+
+#: menu.c:525
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Trop menu nie mo¿e prowadziæ do podmenu"
+
+#: menu.c:564
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: Nie wolno dodawaæ punktów menu wprost do paska menu"
+
+#: menu.c:570
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Separator nie mo¿e byæ czê¶ci± tropu menu"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1097
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Menu ---"
+
+#: menu.c:2019
+msgid "Tear off this menu"
+msgstr "Oderwij to menu"
+
+#: menu.c:2084
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Trop menu musi prowadziæ do punktu menu"
+
+#: menu.c:2104
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Nie znaleziono menu: %s"
+
+#: menu.c:2173
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: Menu nie jest zdefiniowane dla trybu %s"
+
+#: menu.c:2211
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Trop menu musi prowadziæ do podmenu"
+
+#: menu.c:2232
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Nie znaleziono menu - sprawd¼ nazwy menu"
+
+#: message.c:414
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Wykryto b³±d podczas przetwarzania %s:"
+
+#: message.c:440
+#, c-format
+msgid "line %4ld:"
+msgstr "wiersz %4ld:"
+
+#: message.c:647
+msgid "[string too long]"
+msgstr "[ci±g zbyt d³ugi]"
+
+#: message.c:797
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr ""
+"Opiekun komunikatów: Marcin Dalecki <dalecki@cs.net.pl>, Miko³aj Machowski "
+"<mikmach@wp.pl>"
+
+#: message.c:1025
+msgid "Interrupt: "
+msgstr "Przerwanie: "
+
+#: message.c:1028
+msgid "Hit ENTER to continue"
+msgstr "Naci¶nij ENTER aby kontynuowaæ"
+
+#: message.c:1030
+msgid "Hit ENTER or type command to continue"
+msgstr "Naci¶nij ENTER lub wprowad¼ komendê aby kontynuowaæ"
+
+#: message.c:2351
+msgid "-- More --"
+msgstr "-- Wiêcej --"
+
+#: message.c:2354
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: wiersz, SPACE/b: stronê, d/u: pó³ strony, q: zakoñcz)"
+
+#: message.c:2355
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: wiersz, SPACE: stronê, d: pó³ strony, q: zakoñczenie)"
+
+#: message.c:2976 message.c:2991
+msgid "Question"
+msgstr "Pytanie"
+
+#: message.c:2978
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Tak\n"
+"&Nie"
+
+#: message.c:3011
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Tak\n"
+"&Nie\n"
+"Zapisz &wszystkie\n"
+"&Odrzuæ wszystkie\n"
+"&Zakoñcz"
+
+#: message.c:3052
+msgid "Save File dialog"
+msgstr "Dialog zapisywania pliku"
+
+#: message.c:3054
+msgid "Open File dialog"
+msgstr "Dialog otwierania pliku"
+
+#. TODO: non-GUI file selector here
+#: message.c:3125
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: Przykro mi, nie ma przegl±darki plików w trybie konsoli"
+
+#: misc1.c:2754
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: OSTRZE¯ENIE: Zmiany w pliku tylko do odczytu"
+
+#: misc1.c:3002
+msgid "1 more line"
+msgstr "1 wiersz wiêcej"
+
+#: misc1.c:3004
+msgid "1 line less"
+msgstr "1 wiersz mniej"
+
+#: misc1.c:3009
+#, c-format
+msgid "%ld more lines"
+msgstr "dodano %ld wierszy"
+
+#: misc1.c:3011
+#, c-format
+msgid "%ld fewer lines"
+msgstr "usuniêto %ld wierszy"
+
+#: misc1.c:3014
+msgid " (Interrupted)"
+msgstr " (Przerwane)"
+
+#: misc1.c:7563
+msgid "Vim: preserving files...\n"
+msgstr "Vim: zachowujê plik...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:7573
+msgid "Vim: Finished.\n"
+msgstr "Vim: Zakoñczono.\n"
+
+#: misc2.c:695 misc2.c:711
+msgid "ERROR: "
+msgstr "B£¡D: "
+
+#: misc2.c:715
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bajtów] totalne alokacje-zwolnienia %lu-%lu, w u¿ytku %lu, maksymalne "
+"u¿ycie %lu\n"
+
+#: misc2.c:717
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[wywo³ania] wszystkich re/malloc()-ów %lu, wszystkich free()-ów %lu\n"
+"\n"
+
+#: misc2.c:772
+msgid "E340: Line is becoming too long"
+msgstr "E340: Wiersz staje siê zbyt d³ugi"
+
+#: misc2.c:816
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Wewnêtrzny b³±d: lalloc(%ld, )"
+
+#: misc2.c:924
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Brak pamiêci! (rezerwacja %lu bajtów)"
+
+#: misc2.c:2593
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Wywo³ujê pow³okê do wykonania: \"%s\""
+
+#: misc2.c:2815
+msgid "E545: Missing colon"
+msgstr "E545: Brak dwukropka"
+
+#: misc2.c:2817 misc2.c:2844
+msgid "E546: Illegal mode"
+msgstr "E546: Niedozwolony tryb"
+
+#: misc2.c:2883
+msgid "E547: Illegal mouseshape"
+msgstr "E547: Niedozwolony obrys myszki"
+
+#: misc2.c:2923
+msgid "E548: digit expected"
+msgstr "E548: oczekiwano cyfry"
+
+#: misc2.c:2928
+msgid "E549: Illegal percentage"
+msgstr "E459: Niedozwolony procent"
+
+#: misc2.c:3238
+msgid "Enter encryption key: "
+msgstr "Wprowad¼ klucz do odkodowania: "
+
+#: misc2.c:3239
+msgid "Enter same key again: "
+msgstr "Wprowad¼ ponownie ten sam klucz: "
+
+#: misc2.c:3249
+msgid "Keys don't match!"
+msgstr "Klucze nie pasuj± do siebie!"
+
+#: misc2.c:3798
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Niew³a¶ciwy trop: '**[numer]' musi byæ na koñcu tropu lub po nim musi "
+"byæ '%s'."
+
+#: misc2.c:5077
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Nie mogê znale¼æ katalogu \"%s\" w cdpath"
+
+#: misc2.c:5080
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Nie mogê znale¼æ pliku \"%s\" w tropie"
+
+#: misc2.c:5086
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: Katalogu \"%s\" nie ma wiêcej w cdpath"
+
+#: misc2.c:5089
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: Pliku \"%s\" nie ma wiêcej w tropie"
+
+#: misc2.c:5323
+msgid "E550: Missing colon"
+msgstr "E550: Brak dwukropka"
+
+#: misc2.c:5335
+msgid "E551: Illegal component"
+msgstr "E551: Niedozwolona czê¶æ"
+
+#: misc2.c:5343
+msgid "E552: digit expected"
+msgstr "E552: oczekiwano cyfry"
+
+#. Get here when the server can't be found.
+#: netbeans.c:396
+msgid "Cannot connect to Netbeans #2"
+msgstr "Nie mo¿na po³±czyæ z Netbeans #2"
+
+#: netbeans.c:404
+msgid "Cannot connect to Netbeans"
+msgstr "Nie mo¿na po³±czyæ z Netbeans"
+
+#: netbeans.c:450
+#, c-format
+msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\""
+msgstr "E668: B³êdny tryb dostêpu pliku info po³±czenia NetBeans: \"%s\""
+
+#: netbeans.c:749
+msgid "read from Netbeans socket"
+msgstr "odczyt z gniazda Netbeans"
+
+#: netbeans.c:1638
+#, c-format
+msgid "E658: NetBeans connection lost for buffer %ld"
+msgstr "E658: Bufor %ld utraci³ po³±czenie z NetBeans"
+
+#: normal.c:2980
+msgid "Warning: terminal cannot highlight"
+msgstr "OSTRZE¯ENIE: terminal nie wykonuje pod¶wietlania"
+
+#: normal.c:3276
+msgid "E348: No string under cursor"
+msgstr "E348: Brak ci±gu pod kursorem"
+
+#: normal.c:3278
+msgid "E349: No identifier under cursor"
+msgstr "E349: Brak identyfikatora pod kursorem"
+
+#: normal.c:4519
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: Nie mogê skasowaæ zwiniêcia z bie¿±c± 'foldmethod'"
+
+#: normal.c:6740
+msgid "E662: At start of changelist"
+msgstr "E662: Na pocz±tku listy zmian"
+
+#: normal.c:6742
+msgid "E663: At end of changelist"
+msgstr "E663: Na koñcu listy zmian"
+
+#: normal.c:8003
+msgid "Type :quit<Enter> to exit Vim"
+msgstr "wprowad¼ :quit<Enter> zakoñczenie programu"
+
+#: ops.c:294
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "1 wiersz %sed 1 raz"
+
+#: ops.c:296
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 wiersz %sed %d razy"
+
+#: ops.c:301
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld wierszy %sed 1 raz"
+
+#: ops.c:304
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld wierszy %sed %d razy"
+
+#: ops.c:662
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld wierszy do wciêcia... "
+
+#: ops.c:712
+msgid "1 line indented "
+msgstr "1 wiersz wciêty "
+
+#: ops.c:714
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld wierszy wciêtych "
+
+#. must display the prompt
+#: ops.c:1675
+msgid "cannot yank; delete anyway"
+msgstr "nie mogê skopiowaæ, mimo to kasujê"
+
+#: ops.c:2261
+msgid "1 line changed"
+msgstr "1 wiersz zmieniono"
+
+#: ops.c:2263
+#, c-format
+msgid "%ld lines changed"
+msgstr "%ld wierszy zmieniono"
+
+#: ops.c:2647
+#, c-format
+msgid "freeing %ld lines"
+msgstr "zwalniam %ld wierszy"
+
+#: ops.c:2928
+msgid "1 line yanked"
+msgstr "1 wiersz przekopiowano"
+
+#: ops.c:2930
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld wierszy przekopiowanych"
+
+#: ops.c:3215
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: Pusty rejestr %s"
+
+#. Highlight title
+#: ops.c:3766
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Rejestry ---"
+
+#: ops.c:5073
+msgid "Illegal register name"
+msgstr "Niedozwolona nazwa rejestru"
+
+#: ops.c:5161
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Rejestry:\n"
+
+#: ops.c:5211
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: Nieznany typ rejestru %d"
+
+#: ops.c:5696
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: Niew³a¶ciwa nazwa rejestru: '%s'"
+
+#: ops.c:6056
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Kolumn; "
+
+#: ops.c:6063
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Wybrano %s%ld z %ld Wierszy; %ld z %ld S³ów; %ld z %ld Bajtów"
+
+#: ops.c:6079
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Kol %s z %s; Wiersz %ld z %ld; S³owo %ld z %ld; Bajt %ld z %ld"
+
+#: ops.c:6090
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld dla BOM)"
+
+#: option.c:1643
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=Strona %N"
+
+#: option.c:2092
+msgid "Thanks for flying Vim"
+msgstr "Dziêki za lot Vimem"
+
+#: option.c:3419 option.c:3535
+msgid "E518: Unknown option"
+msgstr "E518: Nieznana opcja"
+
+#: option.c:3432
+msgid "E519: Option not supported"
+msgstr "E519: Opcja nie jest wspomagana"
+
+#: option.c:3457
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: Niedozwolone w modeline"
+
+#: option.c:3522
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tOstatnie ustawienie przez "
+
+#: option.c:3661
+msgid "E521: Number required after ="
+msgstr "E521: Po = wymagany jest numer"
+
+#: option.c:3989 option.c:4619
+msgid "E522: Not found in termcap"
+msgstr "E522: Nie znaleziono w termcap"
+
+#: option.c:4064
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: Niedozwolony znak <%s>"
+
+#: option.c:4611
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: Nie mogê ustawiæ 'term' na pusty ci±g"
+
+#: option.c:4614
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: Nie mogê zmieniæ term w GUI"
+
+#: option.c:4616
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: U¿yj \":gui\" do odpalenia GUI"
+
+#: option.c:4645
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: 'backupext' i 'patchmode' s± to¿same"
+
+#: option.c:4860
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: Nie mogê zmieniæ w GTK+2 GUI"
+
+#: option.c:5016
+msgid "E524: Missing colon"
+msgstr "E524: Brak dwukropka"
+
+#: option.c:5018
+msgid "E525: Zero length string"
+msgstr "E525: Ci±g o zerowej d³ugo¶ci"
+
+#: option.c:5086
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: Brak numeru po <%s>"
+
+#: option.c:5100
+msgid "E527: Missing comma"
+msgstr "E527: Brak przecinka"
+
+#: option.c:5107
+msgid "E528: Must specify a ' value"
+msgstr "E528: Musi okre¶laæ warto¶æ '"
+
+#: option.c:5148
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: zawiera niewy¶wietlalny lub szeroki znak"
+
+#: option.c:5197
+msgid "E596: Invalid font(s)"
+msgstr "E596: Niedozwolona czcionka/ki"
+
+#: option.c:5205
+msgid "E597: can't select fontset"
+msgstr "E597: nie mogê wybraæ zestawu czcionek"
+
+#: option.c:5207
+msgid "E598: Invalid fontset"
+msgstr "E598: Niedozwolony zestaw czcionek"
+
+#: option.c:5214
+msgid "E533: can't select wide font"
+msgstr "E533: nie mogê wybraæ szerokiej czcionki"
+
+#: option.c:5216
+msgid "E534: Invalid wide font"
+msgstr "E534: Niedozwolona szeroka czcionka"
+
+#: option.c:5486
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: Niedozwolony znak po <%c>"
+
+#: option.c:5597
+msgid "E536: comma required"
+msgstr "E536: wymagany przecinek"
+
+#: option.c:5607
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: 'commentstring' musi byæ pusty lub zawieraæ %s"
+
+#: option.c:5679
+msgid "E538: No mouse support"
+msgstr "E538: Brak wspomagania myszki"
+
+#: option.c:5947
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: Niedomkniêty ci±g wyra¿eñ"
+
+#: option.c:5951
+msgid "E541: too many items"
+msgstr "E541: zbyt wiele elementów"
+
+#: option.c:5953
+msgid "E542: unbalanced groups"
+msgstr "E542: niezbalansowane grupy"
+
+#: option.c:6193
+msgid "E590: A preview window already exists"
+msgstr "E590: okno podgl±du ju¿ istnieje"
+
+#: option.c:6450
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr "W17: Arabski wymaga UTF-8, zrób ':set encoding=utf-8'"
+
+#: option.c:6783
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: Potrzebujê przynajmniej %d wierszy"
+
+#: option.c:6793
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: Potrzebujê przynajmniej %d kolumn"
+
+#: option.c:7100
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Nieznana opcja: %s"
+
+#: option.c:7220
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Kody terminala ---"
+
+#: option.c:7222
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Globalne warto¶ci opcji ---"
+
+#: option.c:7224
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Lokalne warto¶ci opcji ---"
+
+#: option.c:7226
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Opcje ---"
+
+#: option.c:7932
+msgid "E356: get_varp ERROR"
+msgstr "E356: B£¡D get_varp"
+
+#: option.c:8903
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': Brak pasuj±cego znaku dla %s"
+
+#: option.c:8937
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': Dodatkowe znaki po ¶redniku: %s"
+
+#: os_amiga.c:280
+msgid "cannot open "
+msgstr "nie mogê otworzyæ "
+
+#: os_amiga.c:314
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Nie mogê otworzyæ okna!\n"
+
+#: os_amiga.c:338
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Potrzebujê Amigados w wersji 2.04 lub pó¼niejsz±\n"
+
+#: os_amiga.c:344
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Potrzebujê %s w wersji %ld\n"
+
+#: os_amiga.c:416
+msgid "Cannot open NIL:\n"
+msgstr "Nie mogê otworzyæ NIL:\n"
+
+#: os_amiga.c:427
+msgid "Cannot create "
+msgstr "Nie mogê stworzyæ "
+
+#: os_amiga.c:905
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim koñczy pracê z %d\n"
+
+#: os_amiga.c:937
+msgid "cannot change console mode ?!\n"
+msgstr "nie mogê zmieniæ trybu konsoli ?!\n"
+
+#: os_amiga.c:1003
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: nie jest konsol±??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1152
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Nie mogê wykonaæ pow³oki z opcj± -f"
+
+#: os_amiga.c:1193 os_amiga.c:1283
+msgid "Cannot execute "
+msgstr "Nie mogê wykonaæ "
+
+#: os_amiga.c:1196 os_amiga.c:1293
+msgid "shell "
+msgstr "pow³oka "
+
+#: os_amiga.c:1216 os_amiga.c:1318
+msgid " returned\n"
+msgstr " zwróci³\n"
+
+#: os_amiga.c:1459
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE zbyt niskie."
+
+#: os_amiga.c:1463
+msgid "I/O ERROR"
+msgstr "B£¡D I/O"
+
+#: os_mswin.c:539
+msgid "...(truncated)"
+msgstr "...(obciêty)"
+
+#: os_mswin.c:641
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' nie wynosi 80, nie mogê wykonaæ zewnêtrznych komend"
+
+#: os_mswin.c:1973
+msgid "E237: Printer selection failed"
+msgstr "E237: Wybór drukarki nie powiód³ siê"
+
+#: os_mswin.c:2013
+#, c-format
+msgid "to %s on %s"
+msgstr "do %s z %s"
+
+#: os_mswin.c:2028
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: Nieznana czcionka drukarki: %s"
+
+#: os_mswin.c:2077 os_mswin.c:2087
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: B³±d drukarki: %s"
+
+#: os_mswin.c:2088
+msgid "Unknown"
+msgstr "Nieznane"
+
+#: os_mswin.c:2115
+#, c-format
+msgid "Printing '%s'"
+msgstr "Wydrukowano '%s'"
+
+#: os_mswin.c:3204
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Niedozwolona nazwa zestawu znaków \"%s\" w nazwie czcionki \"%s\""
+
+#: os_mswin.c:3212
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Niedozwolony znak '%c' w nazwie czcionki \"%s\""
+
+#: os_riscos.c:1259
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Niew³a¶ciwa opcja 'osfiletype' - u¿ywam Text"
+
+#: os_unix.c:927
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: Podwójny sygna³, wychodzê\n"
+
+#: os_unix.c:933
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Za³apa³ ¶miertelny sygna³ %s\n"
+
+#: os_unix.c:936
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Za³apa³ ¶miertelny sygna³\n"
+
+#: os_unix.c:1199
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Otwieranie ekranu X trwa³o %ld msec"
+
+#: os_unix.c:1226
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: Dosta³ b³±d X\n"
+
+#: os_unix.c:1334
+msgid "Testing the X display failed"
+msgstr "Test ekranu X nie powiód³ siê"
+
+#: os_unix.c:1473
+msgid "Opening the X display timed out"
+msgstr "Próba otwarcia ekranu X trwa³a zbyt d³ugo"
+
+#: os_unix.c:3227 os_unix.c:3907
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"Nie mogê wykonaæ pow³oki "
+
+#: os_unix.c:3275
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Nie mogê wykonaæ pow³oki sh\n"
+
+#: os_unix.c:3279 os_unix.c:3913
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"pow³oka zwróci³a "
+
+#: os_unix.c:3414
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Nie mogê stworzyæ potoków\n"
+
+#: os_unix.c:3429
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"Nie mogê rozdzieliæ siê\n"
+
+#: os_unix.c:3920
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Komenda zakoñczona\n"
+
+#: os_unix.c:4184 os_unix.c:4309 os_unix.c:5975
+msgid "XSMP lost ICE connection"
+msgstr "XSMP straci³ po³±czenie ICE"
+
+#: os_unix.c:5558
+msgid "Opening the X display failed"
+msgstr "Otwarcie ekranu X nie powiod³o siê"
+
+#: os_unix.c:5880
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP obs³uguje ¿±danie samozapisu"
+
+#: os_unix.c:5999
+msgid "XSMP opening connection"
+msgstr "XSMP otwiera po³±czenie"
+
+#: os_unix.c:6018
+msgid "XSMP ICE connection watch failed"
+msgstr "Obserwacja po³±czenia XSMP ICE nie powiod³a siê"
+
+#: os_unix.c:6038
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP SmcOpenConnection nie powiod³o siê: %s"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "W wierszu"
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "Nie mogê zarezerwowaæ pamiêci dla linii poleceñ."
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "B³±d VIM"
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "Nie mogê za³adowaæ vim32.dll!"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Nie zdo³a³em poprawiæ wska¼ników funkcji w DLL!"
+
+#: os_win16.c:342 os_win32.c:3197
+#, c-format
+msgid "shell returned %d"
+msgstr "pow³oka zwróci³a %d"
+
+#: os_win32.c:2655
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Za³apa³ wydarzenie %s\n"
+
+#: os_win32.c:2657
+msgid "close"
+msgstr "zamknij"
+
+#: os_win32.c:2659
+msgid "logoff"
+msgstr "wyloguj"
+
+#: os_win32.c:2660
+msgid "shutdown"
+msgstr "zakoñcz"
+
+#: os_win32.c:3150
+msgid "E371: Command not found"
+msgstr "E371: Nie znaleziono komendy"
+
+#: os_win32.c:3163
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE nie znaleziono w twoim $PATH.\n"
+"Zewnêtrzne komendy nie bêd± wstrzymane po wykonaniu.\n"
+"Patrz :help wim32-vimrun aby otrzymaæ wiêcej informacji."
+
+#: os_win32.c:3166
+msgid "Vim Warning"
+msgstr "Vim Ostrze¿enie"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Zbyt wiele %%%c w ci±gu formatuj±cym"
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: Nieoczekiwane %%%c w ci±gu formatuj±cym"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: Brak ] w ci±gu formatuj±cym"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: Niewspomagane %%%c w ci±gu formatuj±cym"
+
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: Niepoprawne %%%c w prefiksie ci±gu formatuj±cego"
+
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: Niepoprawne %%%c w ci±gu formatuj±cym"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' nie zawiera wzorca"
+
+#: quickfix.c:501
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Pusta nazwa katalogu lub jej brak"
+
+#: quickfix.c:990
+msgid "E553: No more items"
+msgstr "E553: Nie ma wiêcej elementów"
+
+#: quickfix.c:1229
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d z %d)%s%s: "
+
+#: quickfix.c:1231
+msgid " (line deleted)"
+msgstr " (wiersz skasowany)"
+
+#: quickfix.c:1444
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Na dole stosu quickfix"
+
+#: quickfix.c:1453
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Na górze stosu quickfix"
+
+#: quickfix.c:1465
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "lista b³êdów %d z %d; %d b³êdów"
+
+#: quickfix.c:1943
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: Nie mogê zapisaæ, opcja 'buftype' jest ustawiona"
+
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: Niew³a¶ciwy element w %s%%[]"
+
+#: regexp.c:840
+msgid "E339: Pattern too long"
+msgstr "E339: Zbyt d³ugi wzorzec"
+
+#: regexp.c:1011
+msgid "E50: Too many \\z("
+msgstr "E50: Zbyt wiele \\z("
+
+#: regexp.c:1022
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: Zbyt wiele %s("
+
+#: regexp.c:1079
+msgid "E52: Unmatched \\z("
+msgstr "E52: Niesparowany \\z("
+
+#: regexp.c:1083
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: Niesparowany %s%%("
+
+#: regexp.c:1085
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: Niesparowany %s("
+
+#: regexp.c:1090
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: Niesparowany %s)"
+
+#: regexp.c:1260
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: operand %s* móg³ byæ pusty"
+
+#: regexp.c:1263
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: operand %s+ móg³ byæ pusty"
+
+#: regexp.c:1318
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: niedozwolony znak po %s@"
+
+#: regexp.c:1346
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: operand %s{ móg³ byæ pusty"
+
+#: regexp.c:1356
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: Zbyt wiele z³o¿onych %s{...}"
+
+#: regexp.c:1372
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: Zagnie¿d¿one %s*"
+
+#: regexp.c:1375
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: Zagnie¿d¿one %s%c"
+
+#: regexp.c:1493
+msgid "E63: invalid use of \\_"
+msgstr "E63: Niedozwolone u¿ycie \\_"
+
+#: regexp.c:1538
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c po niczym"
+
+#: regexp.c:1594
+msgid "E65: Illegal back reference"
+msgstr "E65: Niew³a¶ciwe odwo³anie wsteczne"
+
+#: regexp.c:1607
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z( jest niedozwolone w tym miejscu"
+
+#: regexp.c:1626
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 i podobne s± niedozwolone w tym miejscu"
+
+#: regexp.c:1637
+msgid "E68: Invalid character after \\z"
+msgstr "E68: niedopuszczalny znak po \\z"
+
+#: regexp.c:1686
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: Brak ] po %s%%["
+
+#: regexp.c:1702
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: Pusty %s%%[]"
+
+#: regexp.c:1762
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: Niedozwolony znak po %s%%"
+
+#: regexp.c:2559
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: B³±d sk³adni w %s{...}"
+
+#: regexp.c:2865 regexp.c:3018
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Przechwycono za³amanie; regexp zbyt z³o¿ony?"
+
+#: regexp.c:3006 regexp.c:3015
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: wzorzec spowodowa³ b³±d out-of-stack"
+
+#: regexp.c:3260
+msgid "External submatches:\n"
+msgstr "Zewnêtrzne poddopasowania:\n"
+
+#: screen.c:2184
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld wierszy zwiniêto "
+
+#: screen.c:7996
+msgid " VREPLACE"
+msgstr " V-ZAMIANA"
+
+#: screen.c:8000
+msgid " REPLACE"
+msgstr " ZAMIANA"
+
+#: screen.c:8005
+msgid " REVERSE"
+msgstr " NEGATYW"
+
+#: screen.c:8007
+msgid " INSERT"
+msgstr " WPROWADZANIE"
+
+#: screen.c:8010
+msgid " (insert)"
+msgstr " (wprowadzanie)"
+
+#: screen.c:8012
+msgid " (replace)"
+msgstr " (zamiana)"
+
+#: screen.c:8014
+msgid " (vreplace)"
+msgstr " (v-zamiana)"
+
+#: screen.c:8017
+msgid " Hebrew"
+msgstr " Hebrajski"
+
+#: screen.c:8028
+msgid " Arabic"
+msgstr " Arabski"
+
+#: screen.c:8031
+msgid " (lang)"
+msgstr " (jêzyk)"
+
+#: screen.c:8035
+msgid " (paste)"
+msgstr " (wklejanie)"
+
+#: screen.c:8048
+msgid " VISUAL"
+msgstr " WIZUALNY"
+
+#: screen.c:8049
+msgid " VISUAL LINE"
+msgstr " WIZUALNY LINIOWY"
+
+#: screen.c:8050
+msgid " VISUAL BLOCK"
+msgstr " WIZUALNY BLOKOWY"
+
+#: screen.c:8051
+msgid " SELECT"
+msgstr " ZAZNACZANIE"
+
+#: screen.c:8052
+msgid " SELECT LINE"
+msgstr " ZAZNACZANIE LINIOWE"
+
+#: screen.c:8053
+msgid " SELECT BLOCK"
+msgstr " ZAZNACZANIE BLOKOWE"
+
+#: screen.c:8068 screen.c:8131
+msgid "recording"
+msgstr "zapis"
+
+#: search.c:37
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "szukanie dobi³o GÓRY; kontynuacja od KOÑCA"
+
+#: search.c:38
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "szukanie dobi³o KOÑCA; kontynuacja od GÓRY"
+
+#: search.c:526
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Niew³a¶ciwy ci±g do szukania: %s"
+
+#: search.c:853
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: szukanie dobi³o GÓRY bez znalezienia: %s"
+
+#: search.c:856
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: szukanie dobi³o KOÑCA bez znalezienia : %s"
+
+#: search.c:1249
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: Oczekujê '?' lub '/' po ';'"
+
+#: search.c:3758
+msgid " (includes previously listed match)"
+msgstr " (zawiera poprzednio wymienione dopasowanie)"
+
+#. cursor at status line
+#: search.c:3778
+msgid "--- Included files "
+msgstr "--- Zawarte pliki "
+
+#: search.c:3780
+msgid "not found "
+msgstr "nie znaleziono"
+
+#: search.c:3781
+msgid "in path ---\n"
+msgstr "w tropie ---\n"
+
+#: search.c:3820
+msgid " (Already listed)"
+msgstr " (Ju¿ wymienione)"
+
+#: search.c:3822
+msgid " NOT FOUND"
+msgstr " NIE ZNALEZIONO"
+
+#: search.c:3874
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Przegl±d w³±czonego pliku: %s"
+
+#: search.c:4092
+msgid "E387: Match is on current line"
+msgstr "E387: Wzorzec pasuje w bie¿±cym wierszu"
+
+#: search.c:4235
+msgid "All included files were found"
+msgstr "Wszelkie w³±czane pliki odnaleziono"
+
+#: search.c:4237
+msgid "No included files"
+msgstr "Brak w³±czanych plików"
+
+#: search.c:4253
+msgid "E388: Couldn't find definition"
+msgstr "E388: Nie znalaz³em definicji"
+
+#: search.c:4255
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Nie znalaz³em wzorca"
+
+#: syntax.c:3050
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: Niedozwolony argument: %s"
+
+#: syntax.c:3230
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: Nie ma takiego klastra sk³adni: %s"
+
+#: syntax.c:3394
+msgid "No Syntax items defined for this buffer"
+msgstr "Brak elementów sk³adni okre¶lonych dla tego bufora"
+
+#: syntax.c:3402
+msgid "syncing on C-style comments"
+msgstr "synchronizacja komentarzy w stylu C"
+
+#: syntax.c:3410
+msgid "no syncing"
+msgstr "brak synchronizacji"
+
+#: syntax.c:3413
+msgid "syncing starts "
+msgstr "pocz±tek synchronizacji"
+
+#: syntax.c:3415 syntax.c:3490
+msgid " lines before top line"
+msgstr " wierszy przed górn± lini±"
+
+#: syntax.c:3420
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Elementy synchronizacji sk³adni ---"
+
+#: syntax.c:3425
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"synchronizujê na elementach"
+
+#: syntax.c:3431
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Elementy sk³adni ---"
+
+#: syntax.c:3454
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: Nie ma takiego klastra sk³adni: %s"
+
+#: syntax.c:3480
+msgid "minimal "
+msgstr "minimalnie "
+
+#: syntax.c:3487
+msgid "maximal "
+msgstr "maksymalnie "
+
+#: syntax.c:3499
+msgid "; match "
+msgstr "; pasuje "
+
+#: syntax.c:3501
+msgid " line breaks"
+msgstr "znaków nowego wiersza"
+
+#: syntax.c:4135
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: group[t]here niedozwolone w tym miejscu"
+
+#: syntax.c:4159
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: Nie znalaz³em elementów regionu dla %s"
+
+#: syntax.c:4187
+msgid "E395: contains argument not accepted here"
+msgstr "E395: argument contains niedozwolony w tym miejscu"
+
+#: syntax.c:4198
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: argument containedin niedozwolony w tym miejscu"
+
+#: syntax.c:4276
+msgid "E397: Filename required"
+msgstr "E397: Wymagana nazwa pliku"
+
+#: syntax.c:4614
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Brak '=': %s"
+
+#: syntax.c:4772
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Za ma³o argumentów: syntax region %s"
+
+#: syntax.c:5103
+msgid "E400: No cluster specified"
+msgstr "E400: Brak specyfikacji klastra"
+
+#: syntax.c:5140
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Brak ogranicznika wzorca: %s"
+
+#: syntax.c:5215
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: ¦mieci po wzorcu: %s"
+
+#: syntax.c:5305
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: syntax sync: wielokrotnie podane wzorce kontynuacji wiersza"
+
+#: syntax.c:5362
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Niedozwolone argumenty: %s"
+
+#: syntax.c:5412
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Brak znaku równo¶ci: %s"
+
+#: syntax.c:5418
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Pusty argument: %s"
+
+#: syntax.c:5445
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s jest niedozwolone w tym miejscu"
+
+#: syntax.c:5452
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s musi byæ pierwsze w li¶cie contains"
+
+#: syntax.c:5522
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Nieznana nazwa grupy: %s"
+
+#: syntax.c:5755
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Niew³a¶ciwa podkomenda :syntax : %s"
+
+#: syntax.c:6136
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: nie znaleziono grupy pod¶wietlania: %s"
+
+#: syntax.c:6160
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Zbyt ma³o argumentów: \":highlight link %s\""
+
+#: syntax.c:6167
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: Zbyt wiele argumentów: \":highlight link %s\""
+
+#: syntax.c:6187
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: grupa ma ustawienia; zignorowane pod³±czenie pod¶wietlania"
+
+#: syntax.c:6316
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: nieoczekiwany znak równo¶ci: %s"
+
+#: syntax.c:6352
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: brak znaku równo¶ci: %s"
+
+#: syntax.c:6380
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: brak argumentu: %s"
+
+#: syntax.c:6417
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: Niedozwolona warto¶æ: %s"
+
+#: syntax.c:6536
+msgid "E419: FG color unknown"
+msgstr "E419: Kolor FG nieznany"
+
+#: syntax.c:6547
+msgid "E420: BG color unknown"
+msgstr "E420: Kolor BG nieznany"
+
+#: syntax.c:6608
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Nazwa lub liczba koloru nierozpoznana: %s"
+
+#: syntax.c:6814
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: za d³ugi kod terminala: %s"
+
+#: syntax.c:6861
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: Niedozwolony argument: %s"
+
+#: syntax.c:7390
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: Zbyt wiele ró¿nych atrybutów podkre¶lania w u¿yciu"
+
+#: syntax.c:7911
+msgid "E669: Unprintable character in group name"
+msgstr "E669: Niedrukowalny znak w nazwie grupy"
+
+#. This is an error, but since there previously was no check only
+#. * give a warning.
+#: syntax.c:7918
+msgid "W18: Invalid character in group name"
+msgstr "W18: nieprawid³owy znak w nazwie grupy"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: na dole stosu znaczników"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: na górze stosu znaczników"
+
+#: tag.c:412
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Nie mo¿na przej¶æ przed pierwszy pasuj±cy znacznik"
+
+#: tag.c:550
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: nie znaleziono znacznika: %s"
+
+#: tag.c:583
+msgid " # pri kind tag"
+msgstr " # pri rodzaj znacznik"
+
+#: tag.c:586
+msgid "file\n"
+msgstr "plik\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:744
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Wprowad¼ nr wyboru (<CR> przerywa): "
+
+#: tag.c:784
+msgid "E427: There is only one matching tag"
+msgstr "E427: Pasuje tylko jeden znacznik"
+
+#: tag.c:786
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Nie mo¿na przej¶æ za ostatni pasuj±cy znacznik"
+
+#: tag.c:810
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Plik \"%s\" nie istnieje"
+
+#. Give an indication of the number of matching tags
+#: tag.c:823
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "znacznik %d z %d%s"
+
+#: tag.c:826
+msgid " or more"
+msgstr " lub wiêcej"
+
+#: tag.c:828
+msgid " Using tag with different case!"
+msgstr " U¿ywam znacznika o odmiennej wielko¶ci liter!"
+
+#: tag.c:872
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Plik \"%s\" nie istnieje"
+
+#. Highlight title
+#: tag.c:941
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # DO znacznik OD wiersza w pliku/tek¶cie"
+
+#: tag.c:1363
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Szukam w pliku znaczników %s"
+
+#: tag.c:1550
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Trop szukania pliku znaczników obciêty dla %s\n"
+
+#: tag.c:2203
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: B³±d formatu w pliku znaczników \"%s\""
+
+#: tag.c:2207
+#, c-format
+msgid "Before byte %ld"
+msgstr "Przed bajtem %ld"
+
+#: tag.c:2240
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Plik znaczników nieuporz±dkowany: %s"
+
+#. never opened any tags file
+#: tag.c:2280
+msgid "E433: No tags file"
+msgstr "E433: Brak pliku znaczników"
+
+#: tag.c:3016
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Nie mogê znale¼æ wzorca znacznika"
+
+#: tag.c:3027
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Nie znalaz³em znacznika - tylko zgadujê!"
+
+#: term.c:1759
+msgid "' not known. Available builtin terminals are:"
+msgstr "' nieznany. Mo¿liwe typy wbudowanych terminali:"
+
+#: term.c:1783
+msgid "defaulting to '"
+msgstr "domy¶lnie jest '"
+
+#: term.c:2141
+msgid "E557: Cannot open termcap file"
+msgstr "E557: Nie mogê otworzyæ pliku termcap"
+
+#: term.c:2145
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: Nie ma opisu takiego terminala w terminfo"
+
+#: term.c:2147
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: Nie ma opisu takiego terminala w termcap"
+
+#: term.c:2306
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Brak opisu \"%s\" w termcap"
+
+#: term.c:2780
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: wymagana zdolno¶æ \"cm\" terminala"
+
+#. Highlight title
+#: term.c:4990
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Klawisze terminala ---"
+
+#: ui.c:258
+msgid "new shell started\n"
+msgstr "uruchomiono now± pow³okê\n"
+
+#: ui.c:1841
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: B³±d podczas wczytywania wej¶cia, koñczê...\n"
+
+#. must display the prompt
+#: undo.c:405
+msgid "No undo possible; continue anyway"
+msgstr "Cofniêcie niemo¿liwe; mimo to kontynuujê"
+
+#: undo.c:561
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: niew³a¶ciwe numery wierszy"
+
+#: undo.c:757
+msgid "1 change"
+msgstr "1 zmiana"
+
+#: undo.c:759
+#, c-format
+msgid "%ld changes"
+msgstr "%ld zmian"
+
+#: undo.c:812
+msgid "E439: undo list corrupt"
+msgstr "E439: uszkodzona lista cofania"
+
+#: undo.c:844
+msgid "E440: undo line missing"
+msgstr "E440: brak wiersza cofania"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:1769
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"16/32 bitowa wersja GUI dla MS-Windows"
+
+#: version.c:1771
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"32 bitowa wersja GUI dla MS-Windows"
+
+#: version.c:1774
+msgid " in Win32s mode"
+msgstr " w trybie Win32s"
+
+#: version.c:1776
+msgid " with OLE support"
+msgstr " ze wspomaganiem OLE"
+
+#: version.c:1779
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"32 bitowa wersja na konsolê dla MS-Windows"
+
+#: version.c:1783
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"16 bitowa wersja dla MS-Windows"
+
+#: version.c:1787
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 bitowa wersja dla MS-DOS"
+
+#: version.c:1789
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 bitowa wersja dla MS-DOS"
+
+#: version.c:1795
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"wersja dla MacOS X (unix)"
+
+#: version.c:1797
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"wersja dla MacOS X"
+
+#: version.c:1800
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"wersja dla MacOS"
+
+#: version.c:1805
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"wersja dla RISC OS"
+
+#: version.c:1815
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Zadane ³aty: "
+
+#: version.c:1841 version.c:2209
+msgid "Modified by "
+msgstr "Zmieniony przez "
+
+#: version.c:1848
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Skompilowany "
+
+#: version.c:1851
+msgid "by "
+msgstr "przez "
+
+#: version.c:1863
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Olbrzymia wersja "
+
+#: version.c:1866
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Du¿a wersja "
+
+#: version.c:1869
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Normalna wersja "
+
+#: version.c:1872
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Ma³a wersja "
+
+#: version.c:1874
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Malutka wersja "
+
+#: version.c:1880
+msgid "without GUI."
+msgstr "bez GUI."
+
+#: version.c:1885
+msgid "with GTK2-GNOME GUI."
+msgstr "z GTK2-GNOME GUI."
+
+#: version.c:1887
+msgid "with GTK-GNOME GUI."
+msgstr "z GTK-GNOME GUI."
+
+#: version.c:1891
+msgid "with GTK2 GUI."
+msgstr "z GTK2 GUI."
+
+#: version.c:1893
+msgid "with GTK GUI."
+msgstr "z GTK GUI."
+
+#: version.c:1898
+msgid "with X11-Motif GUI."
+msgstr "z X11-Motif GUI."
+
+#: version.c:1902
+msgid "with X11-neXtaw GUI."
+msgstr "z X11-neXtaw GUI."
+
+#: version.c:1904
+msgid "with X11-Athena GUI."
+msgstr "z X11-Athena GUI."
+
+#: version.c:1908
+msgid "with BeOS GUI."
+msgstr "z BeOS GUI."
+
+#: version.c:1911
+msgid "with Photon GUI."
+msgstr "z Photon GUI."
+
+#: version.c:1914
+msgid "with GUI."
+msgstr "z GUI."
+
+#: version.c:1917
+msgid "with Carbon GUI."
+msgstr "z Carbon GUI."
+
+#: version.c:1920
+msgid "with Cocoa GUI."
+msgstr "z Cocoa GUI."
+
+#: version.c:1923
+msgid "with (classic) GUI."
+msgstr "z (klasycznym) GUI."
+
+#: version.c:1934
+msgid " Features included (+) or not (-):\n"
+msgstr " Opcje w³±czone (+) lub nie (-):\n"
+
+#: version.c:1946
+msgid " system vimrc file: \""
+msgstr " vimrc systemu: \""
+
+#: version.c:1951
+msgid " user vimrc file: \""
+msgstr " vimrc u¿ytkownika: \""
+
+#: version.c:1956
+msgid " 2nd user vimrc file: \""
+msgstr " 2-gi plik vimrc u¿ytkownika: \""
+
+#: version.c:1961
+msgid " 3rd user vimrc file: \""
+msgstr " 3-ci plik vimrc u¿ytkownika: \""
+
+#: version.c:1966
+msgid " user exrc file: \""
+msgstr " exrc u¿ytkownika: \""
+
+#: version.c:1971
+msgid " 2nd user exrc file: \""
+msgstr " 2-gi plik exrc u¿ytkownika: \""
+
+#: version.c:1977
+msgid " system gvimrc file: \""
+msgstr " gvimrc systemu: \""
+
+#: version.c:1981
+msgid " user gvimrc file: \""
+msgstr " gvimrc u¿ytkownika: \""
+
+#: version.c:1985
+msgid "2nd user gvimrc file: \""
+msgstr "2-gi plik gvimrc u¿ytkownika: \""
+
+#: version.c:1990
+msgid "3rd user gvimrc file: \""
+msgstr "3-ci plik gvimrc u¿ytkownika: \""
+
+#: version.c:1997
+msgid " system menu file: \""
+msgstr " systemowy plik menu: \""
+
+#: version.c:2005
+msgid " fall-back for $VIM: \""
+msgstr " odwet dla $VIM-a: \""
+
+#: version.c:2011
+msgid " f-b for $VIMRUNTIME: \""
+msgstr "f-b dla $VIMRUNTIME: \""
+
+#: version.c:2015
+msgid "Compilation: "
+msgstr "Kompilacja: "
+
+#: version.c:2021
+msgid "Compiler: "
+msgstr "Kompilator: "
+
+#: version.c:2026
+msgid "Linking: "
+msgstr "Konsolidacja: "
+
+#: version.c:2031
+msgid " DEBUG BUILD"
+msgstr " KOMPILACJA DEBUG"
+
+#: version.c:2070
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi rozbudowany"
+
+#: version.c:2072
+msgid "version "
+msgstr "wersja "
+
+#: version.c:2073
+msgid "by Bram Moolenaar et al."
+msgstr "Autor: Bram Moolenaar i Inni."
+
+#: version.c:2077
+msgid "Vim is open source and freely distributable"
+msgstr "Vim jest open source i rozprowadzany darmowo"
+
+#: version.c:2079
+msgid "Help poor children in Uganda!"
+msgstr "Pomó¿ biednym dzieciom w Ugandzie!"
+
+#: version.c:2080
+msgid "type :help iccf<Enter> for information "
+msgstr "wprowad¼ :help iccf<Enter> dla informacji o tym "
+
+#: version.c:2082
+msgid "type :q<Enter> to exit "
+msgstr "wprowad¼ :q<Enter> zakoñczenie programu "
+
+#: version.c:2083
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "wprowad¼ :help<Enter> lub <F1> pomoc na bie¿±co "
+
+#: version.c:2084
+msgid "type :help version6<Enter> for version info"
+msgstr "wprowad¼ :help version6<Enter> dla informacji o wersji"
+
+#: version.c:2087
+msgid "Running in Vi compatible mode"
+msgstr "Dzia³am w trybie zgodno¶ci z Vi"
+
+#: version.c:2088
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "wprowad¼ :set nocp<Enter> warto¶ci domy¶lne Vim-a"
+
+#: version.c:2089
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "wprowad¼ :help cp-default<Enter> dla informacji to tym "
+
+#: version.c:2104
+msgid "menu Help->Orphans for information "
+msgstr "wprowad¼ :help iccf<Enter> dla informacji to tym "
+
+#: version.c:2106
+msgid "Running modeless, typed text is inserted"
+msgstr "Uruchomiony bez trybów, wpisany tekst jest wprowadzany"
+
+#: version.c:2107
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "menu Edytuj->Ustawienia globalne->Tryb wstawiania"
+
+#: version.c:2108
+msgid " for two modes "
+msgstr " dla dwóch trybów "
+
+#: version.c:2112
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "menu Edytuj->Ustawienia globalne->Kompatybilno¶æ z Vi"
+
+#: version.c:2113
+msgid " for Vim defaults "
+msgstr " dla domy¶lnych ustawieñ Vima "
+
+#: version.c:2160
+msgid "Sponsor Vim development!"
+msgstr "Sponsoruj rozwój Vima!"
+
+#: version.c:2161
+msgid "Become a registered Vim user!"
+msgstr "Zostañ zarejestrowanym u¿ytkownikiem Vima!"
+
+#: version.c:2164
+msgid "type :help sponsor<Enter> for information "
+msgstr "wprowad¼ :help sponsor<Enter> dla informacji"
+
+#: version.c:2165
+msgid "type :help register<Enter> for information "
+msgstr "wprowad¼ :help register<Enter> dla informacji"
+
+#: version.c:2167
+msgid "menu Help->Sponsor/Register for information "
+msgstr "menu Pomoc->Sponsoruj/Zarejestruj siê dla informacji"
+
+#: version.c:2177
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "OSTRZE¯ENIE: wykryto Windows 95/98/ME"
+
+#: version.c:2180
+msgid "type :help windows95<Enter> for info on this"
+msgstr "wprowad¼ :help windows95<Enter> dla informacji to tym "
+
+#: window.c:203
+msgid "E441: There is no preview window"
+msgstr "E441: Nie ma okna podgl±du"
+
+#: window.c:581
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: Nie mogê rozdzieliæ lewo-górnego i prawo-dolnego jednocze¶nie"
+
+#: window.c:1340
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Nie mogê przekrêciæ, gdy inne okno jest rozdzielone"
+
+#: window.c:1836
+msgid "E444: Cannot close last window"
+msgstr "E444: Nie mogê zamkn±æ ostatniego okna"
+
+#: window.c:2567
+msgid "Already only one window"
+msgstr "Ju¿ jest tylko jeden widok"
+
+#: window.c:2614
+msgid "E445: Other window contains changes"
+msgstr "E445: Inne okno zawiera zmiany"
+
+#: window.c:4480
+msgid "E446: No file name under cursor"
+msgstr "E446: Brak nazwy pliku pod kursorem"
+
+#: window.c:4599
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Nie mogê znale¼æ pliku \"%s\" w tropie"
+
+#: if_perl.xs:326 globals.h:1232
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: Nie mog³em za³adowaæ biblioteki %s"
+
+#: if_perl.xs:554
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr "Przykro mi, ta komenda jest wy³±czona: nie mog³em za³adowaæ biblioteki Perla."
+
+#: if_perl.xs:607
+msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+msgstr "E299: wyliczenie Perla zabronione w piaskownicy bez modu³u Safe"
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "Edytuj w &wielu Vimach"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "Edytuj w pojedynczym &Vimie"
+
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "&Diff z Vimem"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "Edytuj w &Vimie"
+
+#. Now concatenate
+#: GvimExt/gvimext.cpp:633
+msgid "Edit with existing Vim - &"
+msgstr "Edytuj z istniej±cym Vimem - &"
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "Edytuj wybrane pliki w Vimie"
+
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "B³±d tworzenia procesu: Sprawd¼ czy gvim jest w twojej ¶cie¿ce!"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "b³±d gvimext.dll"
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "Za d³uga ¶cie¿ka!"
+
+#: globals.h:1022
+msgid "--No lines in buffer--"
+msgstr "--Brak wierszy w buforze--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1185
+msgid "E470: Command aborted"
+msgstr "E470: Przerwanie komendy"
+
+#: globals.h:1186
+msgid "E471: Argument required"
+msgstr "E471: wymagany argument"
+
+#: globals.h:1187
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: po \\ powinno byæ /, ? lub &"
+
+#: globals.h:1189
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: Niedozwolone w oknie wiersza poleceñ; <CR> wykonuje, CTRL-C opuszcza"
+
+#: globals.h:1191
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Komenda niedozwolona z exrc/vimrc w bie¿±cym szukaniu katalogu lub "
+"znacznika"
+
+#: globals.h:1193
+msgid "E171: Missing :endif"
+msgstr "E171: Brak :endif"
+
+#: globals.h:1194
+msgid "E600: Missing :endtry"
+msgstr "E600: Brak :endtry"
+
+#: globals.h:1195
+msgid "E170: Missing :endwhile"
+msgstr "E170: Brak :endwhile"
+
+#: globals.h:1196
+msgid "E588: :endwhile without :while"
+msgstr "E588: :endwhile bez :while"
+
+#: globals.h:1198
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Plik istnieje (wymu¶ poprzez !)"
+
+#: globals.h:1199
+msgid "E472: Command failed"
+msgstr "E472: Komenda nie powiod³a siê"
+
+#: globals.h:1201
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Nieznany zestaw czcionek: %s"
+
+#: globals.h:1205
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Nieznana czcionka: %s"
+
+#: globals.h:1208
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: Czcionka \"%s\" nie ma sta³ej szeroko¶ci znaków"
+
+#: globals.h:1210
+msgid "E473: Internal error"
+msgstr "E473: B³±d wewnêtrzny"
+
+#: globals.h:1211
+msgid "Interrupted"
+msgstr "Przerwane"
+
+#: globals.h:1212
+msgid "E14: Invalid address"
+msgstr "E14: Niew³a¶ciwy adres"
+
+#: globals.h:1213
+msgid "E474: Invalid argument"
+msgstr "E474: Niew³a¶ciwy argument"
+
+#: globals.h:1214
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: Niew³a¶ciwy argument: %s"
+
+#: globals.h:1216
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Niew³a¶ciwe wyra¿enie: %s"
+
+#: globals.h:1218
+msgid "E16: Invalid range"
+msgstr "E16: Niew³a¶ciwy zakres"
+
+#: globals.h:1219
+msgid "E476: Invalid command"
+msgstr "E476: Niew³a¶ciwa komenda"
+
+#: globals.h:1221
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" jest katalogiem"
+
+#: globals.h:1224
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Nieoczekiwane znaki przed '='"
+
+#: globals.h:1227
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Wywo³anie z biblioteki nie powiod³o siê dla \"%s()\""
+
+#: globals.h:1233
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: Nie mo¿na za³adowaæ funkcji biblioteki %s"
+
+#: globals.h:1235
+msgid "E19: Mark has invalid line number"
+msgstr "E19: Zak³adka ma niew³a¶ciwy numer wiersza"
+
+#: globals.h:1236
+msgid "E20: Mark not set"
+msgstr "E20: Zak³adka nienastawiona"
+
+#: globals.h:1237
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Nie mogê wykonaæ zmian, 'modifiable' jest wy³±czone"
+
+#: globals.h:1238
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Zbyt g³êbokie zagnie¿d¿enie skryptów"
+
+#: globals.h:1239
+msgid "E23: No alternate file"
+msgstr "E23: Brak pliku zamiany"
+
+#: globals.h:1240
+msgid "E24: No such abbreviation"
+msgstr "E24: Nie ma takiego skrótu"
+
+#: globals.h:1241
+msgid "E477: No ! allowed"
+msgstr "E477: Niedozwolone !"
+
+#: globals.h:1243
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: GUI nie mo¿e byæ u¿yte: Nie w³±czono podczas kompilacji"
+
+#: globals.h:1246
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: Hebrajski nie mo¿e byæ u¿yty: Nie w³±czono podczas kompilacji\n"
+
+#: globals.h:1249
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: Farsi nie mo¿e byæ u¿yty: Nie w³±czono podczas kompilacji\n"
+
+#: globals.h:1252
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: Arabski nie mo¿e byæ u¿yty: Nie w³±czono podczas kompilacji\n"
+
+#: globals.h:1255
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Brak takiej nazwy grupy pod¶wietlania: %s"
+
+#: globals.h:1257
+msgid "E29: No inserted text yet"
+msgstr "E29: Nie wprowadzono jeszcze ¿adnego tekstu"
+
+#: globals.h:1258
+msgid "E30: No previous command line"
+msgstr "E30: Nie ma poprzedniego wiersza poleceñ"
+
+#: globals.h:1259
+msgid "E31: No such mapping"
+msgstr "E31: Nie ma takiego przyporz±dkowania"
+
+#: globals.h:1260
+msgid "E479: No match"
+msgstr "E479: Brak dopasowañ"
+
+#: globals.h:1261
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: Brak dopasowañ: %s"
+
+#: globals.h:1262
+msgid "E32: No file name"
+msgstr "E32: Brak nazwy pliku"
+
+#: globals.h:1263
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: Brak poprzedniego podstawieniowego wyra¿enia regularnego"
+
+#: globals.h:1264
+msgid "E34: No previous command"
+msgstr "E34: Brak poprzedniej komendy"
+
+#: globals.h:1265
+msgid "E35: No previous regular expression"
+msgstr "E35: Brak poprzedniego wyra¿enia regularnego"
+
+#: globals.h:1266
+msgid "E481: No range allowed"
+msgstr "E481: Zakres niedozwolony"
+
+#: globals.h:1268
+msgid "E36: Not enough room"
+msgstr "E36: Brak miejsca"
+
+#: globals.h:1271
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: brak zarejestrowanego serwera o nazwie \"%s\""
+
+#: globals.h:1273
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: Nie mogê stworzyæ pliku %s"
+
+#: globals.h:1274
+msgid "E483: Can't get temp file name"
+msgstr "E483: Nie mogê pobraæ nazwy pliku tymczasowego"
+
+#: globals.h:1275
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: Nie mogê otworzyæ pliku %s"
+
+#: globals.h:1276
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: Nie mogê odczytaæ pliku %s"
+
+#: globals.h:1277
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: Nie zapisano od ostatniej zmiany (wymu¶ przez !)"
+
+#: globals.h:1278
+msgid "E38: Null argument"
+msgstr "E38: Zerowy argument"
+
+#: globals.h:1280
+msgid "E39: Number expected"
+msgstr "E39: Oczekujê liczby"
+
+#: globals.h:1283
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Nie mogê otworzyæ pliku b³êdów %s"
+
+#: globals.h:1286
+msgid "E233: cannot open display"
+msgstr "E233: nie mogê otworzyæ ekranu"
+
+#: globals.h:1288
+msgid "E41: Out of memory!"
+msgstr "E41: Pamiêæ wyczerpana!"
+
+#: globals.h:1290
+msgid "Pattern not found"
+msgstr "Nie znaleziono wzorca"
+
+#: globals.h:1292
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: Nie znaleziono wzorca: %s"
+
+#: globals.h:1293
+msgid "E487: Argument must be positive"
+msgstr "E487: Argument musi byæ dodatni"
+
+#: globals.h:1295
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: Nie mo¿na przej¶æ do poprzedniego katalogu"
+
+#: globals.h:1299
+msgid "E42: No Errors"
+msgstr "E42: Brak B³êdów"
+
+#: globals.h:1301
+msgid "E43: Damaged match string"
+msgstr "E43: Popsuty ci±g wzorca"
+
+#: globals.h:1302
+msgid "E44: Corrupted regexp program"
+msgstr "E44: Zepsuty program wyra¿eñ regularnych"
+
+#: globals.h:1303
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: opcja 'readonly' jest ustawiona (wymu¶ poprzez !)"
+
+#: globals.h:1305
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Nie mogê ustawiæ zmiennej tylko do odczytu \"%s\""
+
+#: globals.h:1308
+msgid "E47: Error while reading errorfile"
+msgstr "E47: B³±d w trakcie czytania pliku b³êdów"
+
+#: globals.h:1311
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: Niedozwolone w piaskownicy"
+
+#: globals.h:1313
+msgid "E523: Not allowed here"
+msgstr "E523: Niedozwolone w tym miejscu"
+
+#: globals.h:1316
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Ustawianie trybu ekranu niewspomagane"
+
+#: globals.h:1318
+msgid "E49: Invalid scroll size"
+msgstr "E49: Niew³a¶ciwa wielko¶æ przewiniêcia"
+
+#: globals.h:1319
+msgid "E91: 'shell' option is empty"
+msgstr "E91: opcja 'shell' jest pusta"
+
+#: globals.h:1321
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Nie mog³em wczytaæ danych znaku!"
+
+#: globals.h:1323
+msgid "E72: Close error on swap file"
+msgstr "E72: B³±d podczas zamykania pliku wymiany"
+
+#: globals.h:1324
+msgid "E73: tag stack empty"
+msgstr "E73: stos znaczników jest pusty"
+
+#: globals.h:1325
+msgid "E74: Command too complex"
+msgstr "E74: Komenda jest zbyt skomplikowana"
+
+#: globals.h:1326
+msgid "E75: Name too long"
+msgstr "E75: Zbyt d³uga nazwa"
+
+#: globals.h:1327
+msgid "E76: Too many ["
+msgstr "E76: Zbyt wiele ["
+
+#: globals.h:1328
+msgid "E77: Too many file names"
+msgstr "E77: Zbyt wiele nazw plików"
+
+#: globals.h:1329
+msgid "E488: Trailing characters"
+msgstr "E488: Nadstêpne znaczki"
+
+#: globals.h:1330
+msgid "E78: Unknown mark"
+msgstr "E78: Nieznana zak³adka"
+
+#: globals.h:1331
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Nie mog± rozwin±æ znaków wieloznacznych"
+
+#: globals.h:1333
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: 'winheight' nie mo¿e byæ mniejsze ni¿ 'winminheight'"
+
+#: globals.h:1335
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: 'winwidth' nie mo¿e byæ mniejsze ni¿ 'winminwidth'"
+
+#: globals.h:1338
+msgid "E80: Error while writing"
+msgstr "E80: B³±d w trakcie zapisu"
+
+#: globals.h:1339
+msgid "Zero count"
+msgstr "Zerowy licznik"
+
+#: globals.h:1341
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: U¿ycie <SID> poza kontekstem skryptu"
+
+#: globals.h:1344
+msgid "E449: Invalid expression received"
+msgstr "E449: Odebra³em niew³a¶ciwe wyra¿enie"
+
+#: globals.h:1347
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: Region jest chroniony, nie mogê zmieniæ"
+
diff --git a/src/po/ru.cp1251.po b/src/po/ru.cp1251.po
new file mode 100644
index 000000000..f0b0ac2a4
--- /dev/null
+++ b/src/po/ru.cp1251.po
@@ -0,0 +1,6658 @@
+# Russian translation for Vim
+#
+# Îá óñëîâèÿõ èñïîëüçîâàíèÿ ÷èòàéòå â ðåäàêòîðå Vim ":help uganda"
+# Î ëþäÿõ, äåëàþùèõ Vim ÷èòàéòå â ðåäàêòîðå ":help àâòîðû"
+#
+# vassily "vr" ragosin <vrr@users.sourceforge.net>, 2004
+#
+# Generated from ru.po, DO NOT EDIT.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim 6.3a\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2004-05-10 21:37+0400\n"
+"PO-Revision-Date: 2004-05-10 21:37+0400\n"
+"Last-Translator: vassily ragosin <vrr@users.sourceforge.net>\n"
+"Language-Team: vassily ragosin <vrr@users.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=cp1251\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: buffer.c:102
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Íåâîçìîæíî âûäåëèòü ïàìÿòü äàæå äëÿ îäíîãî áóôåðà, âûõîä..."
+
+#: buffer.c:105
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: Íåâîçìîæíî âûäåëèòü ïàìÿòü äëÿ áóôåðà, èñïîëüçóåì äðóãîé áóôåð..."
+
+#: buffer.c:805
+#, c-format
+msgid "E515: No buffers were unloaded"
+msgstr "E515: Íè îäèí áóôåð íå áûë âûãðóæåí èç ïàìÿòè"
+
+#: buffer.c:807
+#, c-format
+msgid "E516: No buffers were deleted"
+msgstr "E516: Íè îäèí áóôåð íå áûë óäàë¸í"
+
+#: buffer.c:809
+#, c-format
+msgid "E517: No buffers were wiped out"
+msgstr "E517: Íè îäèí áóôåð íå áûë î÷èùåí"
+
+#: buffer.c:817
+msgid "1 buffer unloaded"
+msgstr "Îäèí áóôåð âûãðóæåí èç ïàìÿòè"
+
+#: buffer.c:819
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "Âñåãî âûãðóæåíî áóôåðîâ èç ïàìÿòè: %d"
+
+#: buffer.c:824
+msgid "1 buffer deleted"
+msgstr "Îäèí áóôåð óäàë¸í"
+
+#: buffer.c:826
+#, c-format
+msgid "%d buffers deleted"
+msgstr "Âñåãî óäàëåíî áóôåðîâ: %d"
+
+#: buffer.c:831
+msgid "1 buffer wiped out"
+msgstr "Îäèí áóôåð î÷èùåí"
+
+#: buffer.c:833
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "Âñåãî î÷èùåíî áóôåðîâ: %d"
+
+#: buffer.c:894
+msgid "E84: No modified buffer found"
+msgstr "E84: Èçìåí¸ííûõ áóôåðîâ íå îáíàðóæåíî"
+
+#. back where we started, didn't find anything.
+#: buffer.c:933
+msgid "E85: There is no listed buffer"
+msgstr "E85: Áóôåðû â ñïèñêå îòñóòñòâóþò"
+
+#: buffer.c:945
+#, c-format
+msgid "E86: Buffer %ld does not exist"
+msgstr "E86: Áóôåð %ld íå ñóùåñòâóåò"
+
+#: buffer.c:948
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Ýòî ïîñëåäíèé áóôåð"
+
+#: buffer.c:950
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Ýòî ïåðâûé áóôåð"
+
+#: buffer.c:988
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr "E89: Èçìåíåíèÿ â áóôåðå %ld íå ñîõðàíåíû (!, ÷òîáû îáîéòè ïðîâåðêó)"
+
+#: buffer.c:1005
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: Íåâîçìîæíî âûãðóçèòü èç ïàìÿòè ïîñëåäíèé áóôåð"
+
+#: buffer.c:1538
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Ïðåäóïðåæäåíèå: ïåðåïîëíåíèå ñïèñêà èì¸í ôàéëîâ"
+
+#: buffer.c:1709
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: Áóôåð %ld íå íàéäåí"
+
+#: buffer.c:1940
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Íåñêîëüêî ñîîòâåòñòâèé äëÿ %s"
+
+#: buffer.c:1942
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: Íåò ñîîòâåòñòâóþùåãî %s áóôåðà"
+
+#: buffer.c:2337
+#, c-format
+msgid "line %ld"
+msgstr "ñòðîêà %ld"
+
+#: buffer.c:2420
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Áóôåð ñ òàêèì èìåíåì óæå ñóùåñòâóåò"
+
+#: buffer.c:2713
+msgid " [Modified]"
+msgstr " [Èçìåí¸í]"
+
+#: buffer.c:2718
+msgid "[Not edited]"
+msgstr "[Íå ðåäàêòèðîâàëñÿ]"
+
+#: buffer.c:2723
+msgid "[New file]"
+msgstr "[Íîâûé ôàéë]"
+
+#: buffer.c:2724
+msgid "[Read errors]"
+msgstr "[Îøèáêè ÷òåíèÿ]"
+
+#: buffer.c:2726 fileio.c:2112
+msgid "[readonly]"
+msgstr "[òîëüêî äëÿ ÷òåíèÿ]"
+
+#: buffer.c:2747
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "Îäíà ñòðîêà --%d%%--"
+
+#: buffer.c:2749
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld ñòð. --%d%%--"
+
+#: buffer.c:2756
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "ñòð. %ld èç %ld --%d%%-- êîë. "
+
+#: buffer.c:2864
+msgid "[No file]"
+msgstr "[Íåò ôàéëà]"
+
+#. must be a help buffer
+#: buffer.c:2904
+msgid "help"
+msgstr "ñïðàâêà"
+
+#: buffer.c:3463 screen.c:5075
+msgid "[help]"
+msgstr "[ñïðàâêà]"
+
+#: buffer.c:3495 screen.c:5081
+msgid "[Preview]"
+msgstr "[Ïðåäïðîñìîòð]"
+
+#: buffer.c:3775
+msgid "All"
+msgstr "Âåñü"
+
+#: buffer.c:3775
+msgid "Bot"
+msgstr "Âíèçó"
+
+#: buffer.c:3777
+msgid "Top"
+msgstr "Íàâåðõó"
+
+#: buffer.c:4523
+#, c-format
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# Ñïèñîê áóôåðîâ:\n"
+
+#: buffer.c:4556
+msgid "[Error List]"
+msgstr "[Ñïèñîê îøèáîê]"
+
+#: buffer.c:4569 memline.c:1520
+msgid "[No File]"
+msgstr "[Íåò ôàéëà]"
+
+#: buffer.c:4882
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Çíà÷êè ---"
+
+#: buffer.c:4901
+#, c-format
+msgid "Signs for %s:"
+msgstr "Çíà÷êè äëÿ %s:"
+
+#: buffer.c:4907
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " ñòðîêà=%ld id=%d èìÿ=%s"
+
+#: diff.c:139
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: Ñëåäèòü çà îòëè÷èÿìè ìîæíî íå áîëåå ÷åì â %ld áóôåðàõ"
+
+#: diff.c:713
+msgid "E97: Cannot create diffs"
+msgstr "E97: Íåâîçìîæíî ñîçäàòü ôàéëû îòëè÷èé"
+
+#: diff.c:818
+msgid "Patch file"
+msgstr "Ôàéë-çàïëàòêà"
+
+#: diff.c:1069
+msgid "E98: Cannot read diff output"
+msgstr "E98: Íåâîçìîæíî ïðî÷èòàòü âûâîä êîìàíäû diff"
+
+#: diff.c:1819
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Àêòèâíûé áóôåð íå íàõîäèòñÿ â ðåæèìå îòëè÷èé"
+
+#: diff.c:1831
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: Áîëüøå íåò áóôåðîâ â ðåæèìå îòëè÷èé"
+
+#: diff.c:1839
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101:  ðåæèìå îòëè÷èé áîëåå äâóõ áóôåðîâ, íå ìîãó âûáðàòü"
+
+#: diff.c:1862
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Íå ìîãó íàéòè áóôåð \"%s\""
+
+#: diff.c:1868
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Áóôåð \"%s\" íå íàõîäèòñÿ â ðåæèìå îòëè÷èé"
+
+#: digraph.c:2199
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: Ýêðàíèðóþùèé ñèìâîë Escape íåëüçÿ èñïîëüçîâàòü â äèãðàôå"
+
+#: digraph.c:2384
+msgid "E544: Keymap file not found"
+msgstr "E544: Ôàéë ñ ðàñêëàäêîé êëàâèàòóðû íå íàéäåí"
+
+#: digraph.c:2411
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: Êîìàíäà :loadkeymap ïðèìåíåíà âíå ôàéëà ñöåíàðèÿ"
+
+#: edit.c:40
+msgid " Keyword completion (^N^P)"
+msgstr " Àâòîäîïîëíåíèå êëþ÷åâîãî ñëîâà (^N^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E^Y^L^]^F^I^K^D^V^N^P)"
+msgstr " Àâòîäîïîëíåíèå ^X (^E^Y^L^]^F^I^K^D^V^N^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N^P)"
+msgstr " Ìåñòíîå àâòîäîïîëíåíèå êëþ÷åâîãî ñëîâà (^N^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L^N^P)"
+msgstr " Àâòîäîïîëíåíèå öåëîé ñòðîêè (^L^N^P)"
+
+#: edit.c:46
+msgid " File name completion (^F^N^P)"
+msgstr " Àâòîäîïîëíåíèå èìåíè ôàéëà (^F^N^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]^N^P)"
+msgstr " Àâòîäîïîëíåíèå ìåòêè (^]^N^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N^P)"
+msgstr " Àâòîäîïîëíåíèå øàáëîíà ïóòè (^N^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D^N^P)"
+msgstr " Àâòîäîïîëíåíèå îïðåäåëåíèÿ (^D^N^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K^N^P)"
+msgstr " Àâòîäîïîëíåíèå ïî ñëîâàðþ (^K^N^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T^N^P)"
+msgstr " Àâòîäîïîëíåíèå ñèíîíèìîâ (^T^N^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V^N^P)"
+msgstr " Àâòîäîïîëíåíèå êîìàíäíîé ñòðîêè (^V^N^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Êîíåö àáçàöà"
+
+#: edit.c:962
+msgid "'thesaurus' option is empty"
+msgstr "Íå çàäàíî çíà÷åíèå îïöèè 'thesaurus'"
+
+#: edit.c:1166
+msgid "'dictionary' option is empty"
+msgstr "Íå çàäàíî çíà÷åíèå îïöèè 'dictionary'"
+
+#: edit.c:2162
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Ïðîñìîòð ñëîâàðÿ: %s"
+
+#: edit.c:2368
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (âñòàâêà) Ïðîêðóòêà (^E/^Y)"
+
+#: edit.c:2370
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (çàìåíà) Ïðîêðóòêà (^E/^Y)"
+
+#: edit.c:2684
+#, c-format
+msgid "Scanning: %s"
+msgstr "Ïðîñìîòð: %s"
+
+#: edit.c:2719
+#, c-format
+msgid "Scanning tags."
+msgstr "Âûïîëíÿåòñÿ ïîèñê ñðåäè ìåòîê."
+
+#: edit.c:3381
+msgid " Adding"
+msgstr " Äîáàâëåíèå"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3430
+msgid "-- Searching..."
+msgstr "-- Ïîèñê..."
+
+#: edit.c:3486
+msgid "Back at original"
+msgstr "Èñõîäíîå ñëîâî"
+
+#: edit.c:3491
+msgid "Word from other line"
+msgstr "Ñëîâî èç äðóãîé ñòðîêè"
+
+#: edit.c:3496
+msgid "The only match"
+msgstr "Åäèíñòâåííîå ñîîòâåòñòâèå"
+
+#: edit.c:3555
+#, c-format
+msgid "match %d of %d"
+msgstr "ñîîòâåòñòâèå %d èç %d"
+
+#: edit.c:3558
+#, c-format
+msgid "match %d"
+msgstr "ñîîòâåòñòâèå %d"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:1024
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Íåèçâåñòíàÿ ïåðåìåííàÿ: \"%s\""
+
+#: eval.c:1320
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Ïðîïóùåíû ñêîáêè: %s"
+
+#: eval.c:1435 eval.c:1449
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Íåò òàêîé ïåðåìåííîé: \"%s\""
+
+#: eval.c:1705
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Ïðîïóùåíî ':' ïîñëå '?'"
+
+#: eval.c:2327
+msgid "E110: Missing ')'"
+msgstr "E110: Ïðîïóùåíà ')'"
+
+#: eval.c:2389
+msgid "E111: Missing ']'"
+msgstr "E111: Ïðîïóùåíà ']'"
+
+#: eval.c:2466
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Íå óêàçàíî èìÿ îïöèè: %s"
+
+#: eval.c:2484
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Íåèçâåñòíàÿ îïöèÿ: %s"
+
+#: eval.c:2555
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Ïðîïóùåíà êàâû÷êà: %s"
+
+#: eval.c:2698
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Ïðîïóùåíà êàâû÷êà: %s"
+
+#: eval.c:3054
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Ïàðàìåòðû äëÿ ôóíêöèè %s çàäàíû íåâåðíî"
+
+#: eval.c:3083
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Íåèçâåñòíàÿ ôóíêöèÿ: %s"
+
+#: eval.c:3084
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: Ñëèøêîì ìíîãî ïàðàìåòðîâ äëÿ ôóíêöèè %s"
+
+#: eval.c:3085
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Íåäîñòàòî÷íî ïàðàìåòðîâ äëÿ ôóíêöèè %s"
+
+#: eval.c:3086
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: <SID> èñïîëüçóåòñÿ âíå ñöåíàðèÿ: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3687 gui.c:4382 gui_gtk.c:2059
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:4226
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld ñòðîê: "
+
+#: eval.c:5477
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&OK\n"
+"Î&òìåíà"
+
+#: eval.c:5517
+msgid "called inputrestore() more often than inputsave()"
+msgstr "Ôóíêöèÿ inputrestore() âûçûâàåòñÿ ÷àùå, ÷åì ôóíêöèÿ inputsave()"
+
+#: eval.c:5977
+msgid "E655: Too many symbolic links (cycle?)"
+msgstr "E656: Ñëèøêîì ìíîãî ñèìâîëè÷åñêèõ ññûëîê (öèêë?)"
+
+#: eval.c:6609
+msgid "E240: No connection to Vim server"
+msgstr "E240: Íåò ñâÿçè ñ ñåðâåðîì Vim"
+
+#: eval.c:6706
+msgid "E277: Unable to read a server reply"
+msgstr "E227: Ñåðâåð íå îòâå÷àåò"
+
+#: eval.c:6734
+msgid "E258: Unable to send to client"
+msgstr "E258: Íå ìîãó îòâåòèòü êëèåíòó"
+
+#: eval.c:6782
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Íå ìîãó îòïðàâèòü ñîîáùåíèå äëÿ %s"
+
+#: eval.c:6882
+msgid "(Invalid)"
+msgstr "(Íåïðàâèëüíî)"
+
+#: eval.c:8060
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Íåîïðåäåëåííàÿ ïåðåìåííàÿ: %s"
+
+#: eval.c:8492
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E461: Íåäîïóñòèìîå èìÿ ïåðåìåííîé: %s"
+
+#: eval.c:8784
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: Ôóíêöèÿ %s óæå ñóùåñòâóåò. Äîáàâüòå !, ÷òîáû çàìåíèòü å¸."
+
+#: eval.c:8857
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Íåîïðåäåëåííàÿ ôóíêöèÿ: %s"
+
+#: eval.c:8870
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Ïðîïóùåíà '(': %s"
+
+#: eval.c:8903
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Íåäîïóñòèìûé ïàðàìåòð: %s"
+
+#: eval.c:8982
+msgid "E126: Missing :endfunction"
+msgstr "E126: Ïðîïóùåíà êîìàíäà :endfunction"
+
+#: eval.c:9089
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Íåâîçìîæíî ïåðåîïðåäåëèòü ôóíêöèþ %s, îíà èñïîëüçóåòñÿ"
+
+#: eval.c:9159
+msgid "E129: Function name required"
+msgstr "E129: Òðåáóåòñÿ èìÿ ôóíêöèè"
+
+#: eval.c:9210
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: Èìÿ ôóíêöèè äîëæíî íà÷èíàòüñÿ ñ ïðîïèñíîé áóêâû: %s"
+
+#: eval.c:9402
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Ôóíêöèÿ %s íå îïðåäåëåíà"
+
+#: eval.c:9407
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Íåâîçìîæíî óäàëèòü ôóíêöèþ %s, îíà èñïîëüçóåòñÿ"
+
+#: eval.c:9455
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: Ãëóáèíà âûçîâà ôóíêöèè áîëüøå, ÷åì çíà÷åíèå 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:9508
+#, c-format
+msgid "calling %s"
+msgstr "âûçîâ %s"
+
+#: eval.c:9570
+#, c-format
+msgid "%s aborted"
+msgstr "%s ïðåðâàíà"
+
+#: eval.c:9572
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s âîçâðàùàåò #%ld"
+
+#: eval.c:9579
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s âîçâðàùàåò \"%s\""
+
+#. always scroll up, don't overwrite
+#: eval.c:9595 ex_cmds2.c:2365
+#, c-format
+msgid "continuing in %s"
+msgstr "ïðîäîëæåíèå â %s"
+
+#: eval.c:9621
+msgid "E133: :return not inside a function"
+msgstr "E133: êîìàíäà :return âíå ôóíêöèè"
+
+#: eval.c:9952
+#, c-format
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# ãëîáàëüíûå ïåðåìåííûå:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Hex %02x, Octal %03o"
+
+#: ex_cmds.c:118
+#, c-format
+msgid "> %d, Hex %04x, Octal %o"
+msgstr "> %d, Hex %04x, Octal %o"
+
+#: ex_cmds.c:119
+#, c-format
+msgid "> %d, Hex %08x, Octal %o"
+msgstr "> %d, Hex %08x, Octal %o"
+
+#: ex_cmds.c:430
+msgid "E134: Move lines into themselves"
+msgstr "E134: Ñòðîêè ïåðåìåùàþòñÿ ñàìè íà ñåáÿ"
+
+#: ex_cmds.c:499
+msgid "1 line moved"
+msgstr "Ïåðåìåùåíà îäíà ñòðîêà"
+
+#: ex_cmds.c:501
+#, c-format
+msgid "%ld lines moved"
+msgstr "Ïåðåìåùåíî ñòðîê: %ld"
+
+#: ex_cmds.c:924
+#, c-format
+msgid "%ld lines filtered"
+msgstr "Ïðîïóùåíî ÷åðåç ôèëüòð ñòðîê: %ld"
+
+#: ex_cmds.c:952
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: Àâòîêîìàíäû *Filter* íå äîëæíû èçìåíÿòü àêòèâíûé áóôåð"
+
+#: ex_cmds.c:1037
+msgid "[No write since last change]\n"
+msgstr "[Èçìåíåíèÿ íå ñîõðàíåíû]\n"
+
+#: ex_cmds.c:1283
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s â ñòðîêå: "
+
+#: ex_cmds.c:1288
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr ""
+"E136: viminfo: Ñëèøêîì ìíîãî îøèáîê, îñòàëüíàÿ ÷àñòü ôàéëà áóäåò ïðîïóùåíà"
+
+#: ex_cmds.c:1323
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "×òåíèå ôàéëà viminfo \"%s\"%s%s%s"
+
+#: ex_cmds.c:1324
+msgid " info"
+msgstr " èíôî"
+
+#: ex_cmds.c:1325
+msgid " marks"
+msgstr " îòìåòîê"
+
+#: ex_cmds.c:1326
+msgid " FAILED"
+msgstr " ÍÅÓÄÀ×ÍÎ"
+
+#: ex_cmds.c:1418
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Ïðàâà íà çàïèñü ôàéëà viminfo îòñóòñòâóþò: %s"
+
+#: ex_cmds.c:1543
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Íåâîçìîæíî çàïèñàòü ôàéë viminfo %s!"
+
+#: ex_cmds.c:1551
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Çàïèñü ôàéëà viminfo \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1649
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Ýòîò ôàéë viminfo àâòîìàòè÷åñêè ñîçäàí Vim %s.\n"
+
+#: ex_cmds.c:1651
+#, c-format
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Åãî ìîæíî (îñòîðîæíî!) ðåäàêòèðîâàòü.\n"
+"\n"
+
+#: ex_cmds.c:1653
+#, c-format
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Çíà÷åíèå îïöèè 'encoding' â ìîìåíò çàïèñè ôàéëà\n"
+
+#: ex_cmds.c:1752
+msgid "Illegal starting char"
+msgstr "Íåäîïóñòèìûé íà÷àëüíûé ñèìâîë"
+
+#: ex_cmds.c:2097 ex_cmds.c:2362 ex_cmds2.c:763
+msgid "Save As"
+msgstr "Ñîõðàíèòü êàê"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2140
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Ôàéë çàãðóæåí â äðóãîì áóôåðå"
+
+#: ex_cmds.c:2174
+msgid "Write partial file?"
+msgstr "Çàïèñàòü ôàéë ÷àñòè÷íî?"
+
+#: ex_cmds.c:2181
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Äëÿ çàïèñè ÷àñòè áóôåðà èñïîëüçóéòå !"
+
+#: ex_cmds.c:2296
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Ïåðåïèñàòü ñóùåñòâóþùèé ôàéë \"%.*s\"?"
+
+#: ex_cmds.c:2367
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: Áóôåð %ld íå ñâÿçàí ñ èìåíåì ôàéëà"
+
+#: ex_cmds.c:2405
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: Ôàéë íå ñîõðàí¸í: çàïèñü îòêëþ÷åíà îïöèåé 'write'"
+
+#: ex_cmds.c:2425
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"Äëÿ \"%.*s\" âêëþ÷åíà îïöèÿ 'readonly'.\n"
+"Çàïèñàòü?"
+
+#: ex_cmds.c:2597
+msgid "Edit File"
+msgstr "Ðåäàêòèðîâàíèå ôàéëà"
+
+#: ex_cmds.c:3205
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Àâòîêîìàíäû íåîæèäàííî óáèëè íîâûé áóôåð %s"
+
+#: ex_cmds.c:3339
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: Ïàðàìåòð êîìàíäû :z äîëæåí áûòü ÷èñëîì"
+
+#: ex_cmds.c:3424
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: Èñïîëüçîâàíèå êîìàíä îáîëî÷êè íå äîïóñêàåòñÿ â rvim."
+
+#: ex_cmds.c:3531
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Ðåãóëÿðíûå âûðàæåíèÿ íå ìîãóò ðàçäåëÿòüñÿ áóêâàìè"
+
+#: ex_cmds.c:3877
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "çàìåíèòü íà %s? (y/n/a/q/l/^E/^Y)"
+
+#: ex_cmds.c:4270
+msgid "(Interrupted) "
+msgstr "(Ïðåðâàíî)"
+
+#: ex_cmds.c:4274
+msgid "1 substitution"
+msgstr "Îäíà çàìåíà"
+
+#: ex_cmds.c:4276
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld çàìåí"
+
+#: ex_cmds.c:4279
+msgid " on 1 line"
+msgstr " â îäíîé ñòðîêå"
+
+#: ex_cmds.c:4281
+#, c-format
+msgid " on %ld lines"
+msgstr " â %ld ñòð."
+
+#: ex_cmds.c:4332
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: Êîìàíäà :global íå ìîæåò áûòü ðåêóðñèâíîé"
+
+#: ex_cmds.c:4367
+msgid "E148: Regular expression missing from global"
+msgstr "E148: Â êîìàíäå :global ïðîïóùåíî ðåãóëÿðíîå âûðàæåíèå"
+
+#: ex_cmds.c:4416
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Ñîîòâåòñòâèå øàáëîíó íàéäåíî íà êàæäîé ñòðîêå: %s"
+
+#: ex_cmds.c:4497
+#, c-format
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Ïîñëåäíÿÿ ñòðîêà äëÿ çàìåíû:\n"
+"$"
+
+#: ex_cmds.c:4598
+msgid "E478: Don't panic!"
+msgstr "E478: Ñïîêîéñòâèå, òîëüêî ñïîêîéñòâèå!"
+
+#: ex_cmds.c:4650
+#, c-format
+msgid "E661: Sorry, no '%s' help for %s"
+msgstr "E661: ê ñîæàëåíèþ, ñïðàâêà '%s' äëÿ %s îòñóòñòâóåò"
+
+#: ex_cmds.c:4653
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Ê ñîæàëåíèþ ñïðàâêà äëÿ %s îòñóòñòâóåò"
+
+#: ex_cmds.c:4687
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Èçâèíèòå, ôàéë ñïðàâêè \"%s\" íå íàéäåí"
+
+#: ex_cmds.c:5170
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s íå ÿâëÿåòñÿ êàòàëîãîì"
+
+#: ex_cmds.c:5309
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: Íåâîçìîæíî îòêðûòü %s äëÿ çàïèñè"
+
+#: ex_cmds.c:5345
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Íåâîçìîæíî îòêðûòü %s äëÿ ÷òåíèÿ"
+
+#: ex_cmds.c:5367
+#, c-format
+msgid "E670: Mix of help file encodings within a language: %s"
+msgstr "E670: Ôàéëû ñïðàâêè èñïîëüçóþò ðàçíûå êîäèðîâêè äëÿ îäíîãî ÿçûêà: %s"
+
+#: ex_cmds.c:5445
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: Ïîâòîðÿþùàÿñÿ ìåòêà \"%s\" â ôàéëå %s"
+
+#: ex_cmds.c:5557
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Íåèçâåñòíàÿ êîìàíäà çíà÷êà %s"
+
+#: ex_cmds.c:5577
+msgid "E156: Missing sign name"
+msgstr "E156: Ïðîïóùåíî èìÿ çíà÷êà"
+
+#: ex_cmds.c:5623
+msgid "E612: Too many signs defined"
+msgstr "E612: Îïðåäåëåíî ñëèøêîì ìíîãî çíà÷êîâ"
+
+#: ex_cmds.c:5691
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Íåïðàâèëüíûé òåêñò çíà÷êà: %s"
+
+#: ex_cmds.c:5722 ex_cmds.c:5913
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Íåèçâåñòíûé çíà÷îê: %s"
+
+#: ex_cmds.c:5771
+msgid "E159: Missing sign number"
+msgstr "E159: Ïðîïóùåí íîìåð çíà÷êà"
+
+#: ex_cmds.c:5853
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: Íåïðàâèëüíîå èìÿ áóôåðà: %s"
+
+#: ex_cmds.c:5892
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Íåïðàâèëüíûé ID çíà÷êà: %ld"
+
+#: ex_cmds.c:5962
+msgid " (NOT FOUND)"
+msgstr " (ÍÅ ÍÀÉÄÅÍÎ)"
+
+#: ex_cmds.c:5964
+msgid " (not supported)"
+msgstr " (íå ïîääåðæèâàåòñÿ)"
+
+#: ex_cmds.c:6063
+msgid "[Deleted]"
+msgstr "[Óäàëåíî]"
+
+#: ex_cmds2.c:92
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "Âêëþ÷¸í ðåæèì îòëàäêè. Äëÿ ïðîäîëæåíèÿ íàáåðèòå \"cont\""
+
+#: ex_cmds2.c:96 ex_docmd.c:966
+#, c-format
+msgid "line %ld: %s"
+msgstr "ñòðîêà %ld: %s"
+
+#: ex_cmds2.c:98
+#, c-format
+msgid "cmd: %s"
+msgstr "êîìàíäà: %s"
+
+#: ex_cmds2.c:290
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Òî÷êà îñòàíîâêè â \"%s%s\" ñòð. %ld"
+
+#: ex_cmds2.c:540
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Òî÷êà îñòàíîâêè íå íàéäåíà: %s"
+
+#: ex_cmds2.c:566
+msgid "No breakpoints defined"
+msgstr "Òî÷êè îñòàíîâêè íå îïðåäåëåíû"
+
+#: ex_cmds2.c:571
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s ñòð. %ld"
+
+#: ex_cmds2.c:786
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Ñîõðàíèòü èçìåíåíèÿ â \"%.*s\"?"
+
+#: ex_cmds2.c:788 ex_docmd.c:9378
+msgid "Untitled"
+msgstr "Áåç èìåíè"
+
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Íåñîõðàí¸ííûå èçìåíåíèÿ â áóôåðå \"%s\""
+
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr ""
+"Ïðåäóïðåæäåíèå: Íåîæèäàííûé ïåðåõîä â äðóãîé áóôåð (ïðîâåðüòå àâòîêîìàíäû)"
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: Äëÿ ðåäàêòèðîâàíèÿ äîñòóïåí òîëüêî îäèí ôàéë"
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: Ýòî ïåðâûé ôàéë"
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Ýòî ïîñëåäíèé ôàéë"
+
+#: ex_cmds2.c:1804
+#, c-format
+msgid "E666: compiler not supported: %s"
+msgstr "E666: êîìïèëÿòîð íå ïîääåðæèâàåòñÿ: %s"
+
+#: ex_cmds2.c:1897
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Ïîèñê \"%s\" â \"%s\""
+
+#: ex_cmds2.c:1919
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Ïîèñê \"%s\""
+
+#: ex_cmds2.c:1940
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "íå íàéäåíî â 'runtimepath': \"%s\""
+
+#: ex_cmds2.c:1974
+msgid "Source Vim script"
+msgstr "Âûïîëíèòü ñöåíàðèé Vim"
+
+#: ex_cmds2.c:2164
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "Íåëüçÿ ñ÷èòàòü êàòàëîã: \"%s\""
+
+#: ex_cmds2.c:2202
+#, c-format
+msgid "could not source \"%s\""
+msgstr "íåâîçìîæíî ñ÷èòàòü \"%s\""
+
+#: ex_cmds2.c:2204
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "ñòðîêà %ld: íåâîçìîæíî ñ÷èòàòü \"%s\""
+
+#: ex_cmds2.c:2218
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "ñ÷èòûâàíèå ñöåíàðèÿ \"%s\""
+
+#: ex_cmds2.c:2220
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "ñòðîêà %ld: ñ÷èòûâàíèå \"%s\""
+
+#: ex_cmds2.c:2363
+#, c-format
+msgid "finished sourcing %s"
+msgstr "ñ÷èòûâàíèå ñöåíàðèÿ %s çàâåðøåíî"
+
+#: ex_cmds2.c:2707
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr ""
+"W15: Ïðåäóïðåæäåíèå: íåïðàâèëüíûé ðàçäåëèòåëü ñòðîêè. Âîçìîæíî ïðîïóùåíî ^M"
+
+#: ex_cmds2.c:2756
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: Êîìàíäà :scriptencoding èñïîëüçóåòñÿ âíå ôàéëà ñöåíàðèÿ"
+
+#: ex_cmds2.c:2789
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: Êîìàíäà :finish èñïîëüçóåòñÿ âíå ôàéëà ñöåíàðèÿ"
+
+#: ex_cmds2.c:3238
+#, c-format
+msgid "Page %d"
+msgstr "Ñòðàíèöà %d"
+
+#: ex_cmds2.c:3394
+msgid "No text to be printed"
+msgstr "Ïå÷àòàòü íå÷åãî"
+
+#: ex_cmds2.c:3472
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "Ïå÷àòü ñòð. %d (%d%%)"
+
+#: ex_cmds2.c:3484
+#, c-format
+msgid " Copy %d of %d"
+msgstr " Êîïèÿ %d èç %d"
+
+#: ex_cmds2.c:3542
+#, c-format
+msgid "Printed: %s"
+msgstr "Íàïå÷àòàíî: %s"
+
+#: ex_cmds2.c:3549
+#, c-format
+msgid "Printing aborted"
+msgstr "Ïå÷àòü ïðåêðàùåíà"
+
+#: ex_cmds2.c:3914
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Îøèáêà çàïèñè â ôàéë PostScript"
+
+#: ex_cmds2.c:4189
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E624: Íåâîçìîæíî îòêðûòü ôàéë \"%s\""
+
+#: ex_cmds2.c:4199 ex_cmds2.c:4824
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Íåâîçìîæíî ïðî÷èòàòü ôàéë ðåñóðñîâ PostScript \"%s\""
+
+#: ex_cmds2.c:4207
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: ôàéë \"%s\" íå ÿâëÿåòñÿ ôàéëîì ðåñóðñîâ PostScript"
+
+#: ex_cmds2.c:4222 ex_cmds2.c:4242 ex_cmds2.c:4257 ex_cmds2.c:4279
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: ôàéë \"%s\" íå ÿâëÿåòñÿ äîïóñòèìûì ôàéëîì ðåñóðñîâ PostScript"
+
+#: ex_cmds2.c:4309
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: ôàéë ðåñóðñîâ \"%s\" íåèçâåñòíîé âåðñèè"
+
+#: ex_cmds2.c:4776
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Íåâîçìîæíî îòêðûòü ôàéë PostScript"
+
+#: ex_cmds2.c:4809
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Íåâîçìîæíî îòêðûòü ôàéë \"%s\""
+
+#: ex_cmds2.c:4928
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr "E456: Ôàéë ðåñóðñîâ PostScript \"prolog.ps\" íå íàéäåí"
+
+#: ex_cmds2.c:4959
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: Ôàéë ðåñóðñîâ PostScript \"%s.ps\" íå íàéäåí"
+
+#: ex_cmds2.c:4977
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr ""
+"E620: Ïðåîáðàçîâàíèå èç ìóëüòèáàéòíûõ ñèìâîëîâ â êîäèðîâêó \"%s\" íåâîçìîæíî"
+
+#: ex_cmds2.c:5102
+msgid "Sending to printer..."
+msgstr "Îòïðàâêà íà ïå÷àòü..."
+
+#: ex_cmds2.c:5106
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: Íå óäàëîñü âûïîëíèòü ïå÷àòü ôàéëà PostScript"
+
+#: ex_cmds2.c:5108
+msgid "Print job sent."
+msgstr "Çàäàíèå íà ïå÷àòü îòïðàâëåíî."
+
+#: ex_cmds2.c:5618
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Àêòèâíûé %sÿçûê: \"%s\""
+
+#: ex_cmds2.c:5629
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Íåâîçìîæíî ñìåíèòü ÿçûê íà \"%s\""
+
+#: ex_docmd.c:525
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Ïåðåõîä â ðåæèì Ex. Äëÿ ïåðåõîäà â Îáû÷íûé ðåæèì íàáåðèòå \"visual\""
+
+#. must be at EOF
+#: ex_docmd.c:561
+msgid "E501: At end-of-file"
+msgstr "E501: Â êîíöå ôàéëà"
+
+#: ex_docmd.c:669
+msgid "E169: Command too recursive"
+msgstr "E169: Cëèøêîì ðåêóðñèâíàÿ êîìàíäà"
+
+#: ex_docmd.c:1229
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: Èñêëþ÷èòåëüíàÿ ñèòóàöèÿ íå îáðàáîòàíà: %s"
+
+#: ex_docmd.c:1317
+msgid "End of sourced file"
+msgstr "Êîíåö ñ÷èòàííîãî ôàéëà"
+
+#: ex_docmd.c:1318
+msgid "End of function"
+msgstr "Êîíåö ôóíêöèè"
+
+#: ex_docmd.c:1907
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: Íåîäíîçíà÷íîå èñïîëüçîâàíèå êîìàíäû ïîëüçîâàòåëÿ"
+
+#: ex_docmd.c:1921
+msgid "E492: Not an editor command"
+msgstr "E492: Ýòî íå êîìàíäà ðåäàêòîðà"
+
+#: ex_docmd.c:2028
+msgid "E493: Backwards range given"
+msgstr "E493: Çàäàí îáðàòíûé äèàïàçîí"
+
+#: ex_docmd.c:2037
+msgid "Backwards range given, OK to swap"
+msgstr "Çàäàí îáðàòíûé äèàïàçîí, ìåíÿåì ãðàíèöû ìåñòàìè"
+
+#: ex_docmd.c:2160
+msgid "E494: Use w or w>>"
+msgstr "E494: Èñïîëüçóéòå w èëè w>>"
+
+#: ex_docmd.c:3786
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Èçâèíèòå, ýòà êîìàíäà íåäîñòóïíà â äàííîé âåðñèè"
+
+#: ex_docmd.c:3989
+msgid "E172: Only one file name allowed"
+msgstr "E172: Ðàçðåøåíî èñïîëüçîâàòü òîëüêî îäíî èìÿ ôàéëà"
+
+#: ex_docmd.c:4569
+msgid "1 more file to edit. Quit anyway?"
+msgstr "1 ôàéë îæèäàåò ðåäàêòèðîâàíèÿ. Âûéòè?"
+
+#: ex_docmd.c:4572
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "Åñòü íåîòðåäàêòèðîâàííûå ôàéëû (%d). Âûéòè?"
+
+#: ex_docmd.c:4579
+msgid "E173: 1 more file to edit"
+msgstr "E173: 1 ôàéë îæèäàåò ðåäàêòèðîâàíèÿ."
+
+#: ex_docmd.c:4581
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: Åñòü íåîòðåäàêòèðîâàííûå ôàéëû (%d)."
+
+#: ex_docmd.c:4676
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: Êîìàíäà óæå ñóùåñòâóåò. Äîáàâüòå ! äëÿ çàìåíû."
+
+#: ex_docmd.c:4787
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Èìÿ Ïàðàì. Äèàï. Äîïîëí. Îïðåäåëåíèå"
+
+#: ex_docmd.c:4876
+msgid "No user-defined commands found"
+msgstr "Êîìàíäû, îïðåäåë¸ííûå ïîëüçîâàòåëåì, íå îáíàðóæåíû."
+
+#: ex_docmd.c:4908
+msgid "E175: No attribute specified"
+msgstr "E175: ïàðàìåòð íå çàäàí"
+
+#: ex_docmd.c:4960
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Íåïðàâèëüíîå êîëè÷åñòâî ïàðàìåòðîâ"
+
+#: ex_docmd.c:4975
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: ×èñëî-ïðèñòàâêó íåëüçÿ óêàçûâàòü äâàæäû"
+
+#: ex_docmd.c:4985
+msgid "E178: Invalid default value for count"
+msgstr "E178: Íåïðàâèëüíîå çíà÷åíèå ÷èñëà-ïðèñòàâêè ïî óìîë÷àíèþ"
+
+#: ex_docmd.c:5016
+msgid "E179: argument required for complete"
+msgstr "E179: äëÿ çàâåðøåíèÿ òðåáóåòñÿ óêàçàòü ïàðàìåòð"
+
+#: ex_docmd.c:5048
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Íåïðàâèëüíîå çíà÷åíèå äîïîëíåíèÿ: %s"
+
+#: ex_docmd.c:5057
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr ""
+"E468: Ïàðàìåòð àâòîäîïîëíåíèÿ ìîæíî èñïîëüçîâàòü òîëüêî ñ îñîáûì äîïîëíåíèåì"
+
+#: ex_docmd.c:5063
+msgid "E467: Custom completion requires a function argument"
+msgstr "E467: Îñîáîå äîïîëíåíèå òðåáóåò óêàçàíèÿ ïàðàìåòðà ôóíêöèè"
+
+#: ex_docmd.c:5074
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Íåïðàâèëüíûé àòðèáóò: %s"
+
+#: ex_docmd.c:5117
+msgid "E182: Invalid command name"
+msgstr "E182: Íåïðàâèëüíîå èìÿ êîìàíäû"
+
+#: ex_docmd.c:5132
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: Êîìàíäà ïîëüçîâàòåëÿ äîëæíà íà÷èíàòüñÿ ñ çàãëàâíîé áóêâû"
+
+#: ex_docmd.c:5203
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: Íåò òàêîé êîìàíäû ïîëüçîâàòåëÿ: %s"
+
+#: ex_docmd.c:5664
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Öâåòîâàÿ ñõåìà %s íå íàéäåíà"
+
+#: ex_docmd.c:5672
+msgid "Greetings, Vim user!"
+msgstr "Ïðèâåò, ïîëüçîâàòåëü Vim!"
+
+#: ex_docmd.c:6389
+msgid "Edit File in new window"
+msgstr "Ðåäàêòèðîâàòü ôàéë â íîâîì îêíå"
+
+#: ex_docmd.c:6684
+msgid "No swap file"
+msgstr "Áåç ñâîï-ôàéëà"
+
+#: ex_docmd.c:6788
+msgid "Append File"
+msgstr "Äîáàâèòü ôàéë"
+
+#: ex_docmd.c:6852
+msgid "E186: No previous directory"
+msgstr "E186: Íåò ïðåäûäóùåãî êàòàëîãà"
+
+#: ex_docmd.c:6934
+msgid "E187: Unknown"
+msgstr "E187: Íåèçâåñòíî"
+
+#: ex_docmd.c:7019
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: êîìàíäà :winsize òðåáóåò óêàçàíèÿ äâóõ ÷èñëîâûõ ïàðàìåòðîâ"
+
+#: ex_docmd.c:7075
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Ïîëîæåíèå îêíà: X %d, Y %d"
+
+#: ex_docmd.c:7080
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: Â äàííîé ñèñòåìå îïðåäåëåíèå ïîëîæåíèÿ îêíà íå ðàáîòàåò"
+
+#: ex_docmd.c:7090
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: êîìàíäà :winpos òðåáóåò óêàçàíèÿ äâóõ ÷èñëîâûõ ïàðàìåòðîâ"
+
+#: ex_docmd.c:7368
+msgid "Save Redirection"
+msgstr "Ïåðåíàïðàâëåíèå çàïèñè"
+
+#: ex_docmd.c:7558
+msgid "Save View"
+msgstr "Ñîõðàíåíèå âèäà"
+
+#: ex_docmd.c:7559
+msgid "Save Session"
+msgstr "Ñîõðàíåíèå ñåàíñà"
+
+#: ex_docmd.c:7561
+msgid "Save Setup"
+msgstr "Ñîõðàíåíèå íàñòðîåê"
+
+#: ex_docmd.c:7713
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" ñóùåñòâóåò (!, ÷òîáû îáîéòè ïðîâåðêó)"
+
+#: ex_docmd.c:7718
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: Íåâîçìîæíî îòêðûòü äëÿ çàïèñè \"%s\""
+
+#. set mark
+#: ex_docmd.c:7742
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: Ïàðàìåòð äîëæåí áûòü ïðÿìîé/îáðàòíîé êàâû÷êîé èëè áóêâîé"
+
+#: ex_docmd.c:7784
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Ñëèøêîì ãëóáîêàÿ ðåêóðñèÿ ïðè èñïîëüçîâàíèè êîìàíäû :normal"
+
+#: ex_docmd.c:8302
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: Íåò ñîñåäíåãî èìåíè ôàéëà äëÿ çàìåíû '#'"
+
+#: ex_docmd.c:8333
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: Íåò àâòîêîìàíäíîãî èìåíè ôàéëà äëÿ çàìåíû \"<afile>\""
+
+#: ex_docmd.c:8341
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "E496: Íåò àâòîêîìàíäíîãî íîìåðà áóôåðà äëÿ çàìåíû \"<abuf>\""
+
+#: ex_docmd.c:8352
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr "E497: Íåò àâòîêîìàíäíîãî èìåíè ñîîòâåòñòâèÿ äëÿ çàìåíû \"<amatch>\""
+
+#: ex_docmd.c:8362
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr "E498: íåò èìåíè ôàéëà :source äëÿ çàìåíû \"<sfile>\""
+
+#: ex_docmd.c:8403
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: Ïóñòîå èìÿ ôàéëà äëÿ '%' èëè '#', âîçìîæíî òîëüêî c \":p:h\""
+
+#: ex_docmd.c:8405
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: Ðåçóëüòàòîì âûðàæåíèÿ ÿâëÿåòñÿ ïóñòàÿ ñòðîêà"
+
+#: ex_docmd.c:9360
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: Íåâîçìîæíî îòêðûòü ôàéë viminfo äëÿ ÷òåíèÿ"
+
+#: ex_docmd.c:9533
+msgid "E196: No digraphs in this version"
+msgstr "E196: Â ýòîé âåðñèè äèãðàôû íå ðàáîòàþò"
+
+#: ex_eval.c:440
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr ""
+"E608: Íåâîçìîæíî âûïîëíèòü êîìàíäó :throw äëÿ èñêëþ÷åíèé ñ ïðèñòàâêîé 'Vim'"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:529
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "Èñêëþ÷èòåëüíàÿ ñèòóàöèÿ: %s"
+
+#: ex_eval.c:576
+#, c-format
+msgid "Exception finished: %s"
+msgstr "Çàâåðøåíà îáðàáîòêà èñêëþ÷èòåëüíîé ñèòóàöèè: %s"
+
+#: ex_eval.c:577
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "Èñêëþ÷èòåëüíàÿ ñèòóàöèÿ ïðîèãíîðèðîâàíà: %s"
+
+#: ex_eval.c:620 ex_eval.c:664
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, ñòðîêà %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:638
+#, c-format
+msgid "Exception caught: %s"
+msgstr "Îáðàáîòêà èñêëþ÷èòåëüíîé ñèòóàöèè: %s"
+
+#: ex_eval.c:713
+#, c-format
+msgid "%s made pending"
+msgstr "%s âûïîëíÿåò îæèäàíèå"
+
+#: ex_eval.c:716
+#, c-format
+msgid "%s resumed"
+msgstr "%s âîçîáíîâëåíî"
+
+#: ex_eval.c:720
+#, c-format
+msgid "%s discarded"
+msgstr "%s ïðîïóùåíî"
+
+#: ex_eval.c:746
+msgid "Exception"
+msgstr "Èñêëþ÷èòåëüíàÿ ñèòóàöèÿ"
+
+#: ex_eval.c:752
+msgid "Error and interrupt"
+msgstr "Îøèáêà è ïðåðûâàíèå"
+
+#: ex_eval.c:754 gui.c:4381
+msgid "Error"
+msgstr "Îøèáêà"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:756
+msgid "Interrupt"
+msgstr "Ïðåðûâàíèå"
+
+#: ex_eval.c:830
+msgid "E579: :if nesting too deep"
+msgstr "E579: ñëèøêîì ãëóáîêî âëîæåííûé :if"
+
+#: ex_eval.c:867
+msgid "E580: :endif without :if"
+msgstr "E580: :endif áåç :if"
+
+#: ex_eval.c:911
+msgid "E581: :else without :if"
+msgstr "E581: :else áåç :if"
+
+#: ex_eval.c:914
+msgid "E582: :elseif without :if"
+msgstr "E582: :elseif áåç :if"
+
+#: ex_eval.c:921
+msgid "E583: multiple :else"
+msgstr "E583: îáíàðóæåíî íåñêîëüêî :else"
+
+#: ex_eval.c:924
+msgid "E584: :elseif after :else"
+msgstr "E584: :elseif ïîñëå :else"
+
+#: ex_eval.c:991
+msgid "E585: :while nesting too deep"
+msgstr "E585: ñëèøêîì ãëóáîêî âëîæåííûé :while"
+
+#: ex_eval.c:1047
+msgid "E586: :continue without :while"
+msgstr "E586: :continue áåç :while"
+
+#: ex_eval.c:1087
+msgid "E587: :break without :while"
+msgstr "E587: :break áåç :while"
+
+#: ex_eval.c:1286
+msgid "E601: :try nesting too deep"
+msgstr "E601: ñëèøêîì ãëóáîêî âëîæåííûé :try"
+
+#: ex_eval.c:1366
+msgid "E603: :catch without :try"
+msgstr "E603: :catch áåç :try"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1388
+msgid "E604: :catch after :finally"
+msgstr "E604: :catch áåç :finally"
+
+#: ex_eval.c:1521
+msgid "E606: :finally without :try"
+msgstr "E606: :finally áåç :try"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1545
+msgid "E607: multiple :finally"
+msgstr "E607: îáíàðóæåíî íåñêîëüêî :finally"
+
+#: ex_eval.c:1654
+msgid "E602: :endtry without :try"
+msgstr "E602: :endtry áåç :try"
+
+#: ex_eval.c:1986
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: êîìàíäà :endfunction ìîæåò èñïîëüçîâàòüñÿ òîëüêî âíóòðè ôóíêöèè"
+
+#: ex_getln.c:3296
+msgid "tagname"
+msgstr "èìÿ ìåòêè"
+
+#: ex_getln.c:3299
+msgid " kind file\n"
+msgstr " òèï ôàéëà\n"
+
+#: ex_getln.c:4752
+msgid "'history' option is zero"
+msgstr "çíà÷åíèå îïöèè 'history' ðàâíî íóëþ"
+
+#: ex_getln.c:5023
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s, èñòîðèÿ (íà÷èíàÿ îò ñâåæåãî ê ñòàðîìó):\n"
+
+#: ex_getln.c:5024
+msgid "Command Line"
+msgstr "Êîìàíäíàÿ ñòðîêà"
+
+#: ex_getln.c:5025
+msgid "Search String"
+msgstr "Ñòðîêà ïîèñêà"
+
+#: ex_getln.c:5026
+msgid "Expression"
+msgstr "Âûðàæåíèå"
+
+#: ex_getln.c:5027
+msgid "Input Line"
+msgstr "Ñòðîêà ââîäà"
+
+#: ex_getln.c:5065
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar áîëüøå äëèíû êîìàíäû"
+
+#: ex_getln.c:5242
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Óäàëåíî àêòèâíîå îêíî èëè áóôåð"
+
+#: fileio.c:377
+msgid "Illegal file name"
+msgstr "Íåäîïóñòèìîå èìÿ ôàéëà"
+
+#: fileio.c:401 fileio.c:535 fileio.c:2913 fileio.c:2954
+msgid "is a directory"
+msgstr "ÿâëÿåòñÿ êàòàëîãîì"
+
+#: fileio.c:403
+msgid "is not a file"
+msgstr "íå ÿâëÿåòñÿ ôàéëîì"
+
+#: fileio.c:557 fileio.c:4131
+msgid "[New File]"
+msgstr "[Íîâûé ôàéë]"
+
+#: fileio.c:590
+msgid "[Permission Denied]"
+msgstr "[Äîñòóï çàïðåù¸í]"
+
+#: fileio.c:694
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200:  ðåçóëüòàòå âûïîëíåíèÿ àâòîêîìàíä *ReadPre ôàéë ñòàë íå÷èòàåìûì"
+
+#: fileio.c:696
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: àâòîêîìàíäû *ReadPre íå äîëæíû èçìåíÿòü àêòèâíûé áóôåð"
+
+#: fileio.c:717
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: âûïîëíÿåòñÿ ÷òåíèå èç ñòàíäàðòíîãî ïîòîêà ââîäà stdin...\n"
+
+#: fileio.c:723
+msgid "Reading from stdin..."
+msgstr "Âûïîëíÿåòñÿ ÷òåíèå èç ñòàíäàðòíîãî ïîòîêà ââîäà stdin..."
+
+#. Re-opening the original file failed!
+#: fileio.c:1000
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202:  ðåçóëüòàòå ïðåîáðàçîâàíèÿ ôàéë ñòàë íå÷èòàåìûì!"
+
+#: fileio.c:2090
+msgid "[fifo/socket]"
+msgstr "[fifo/ãíåçäî]"
+
+#: fileio.c:2097
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:2104
+msgid "[socket]"
+msgstr "[ãíåçäî]"
+
+#: fileio.c:2112
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:2122
+msgid "[CR missing]"
+msgstr "[ïðîïóùåíû ñèìâîëû CR]"
+
+#: fileio.c:2127
+msgid "[NL found]"
+msgstr "[Îáíàðóæåíû ñèìâîëû NL]"
+
+#: fileio.c:2132
+msgid "[long lines split]"
+msgstr "[äëèííûå ñòðîêè ðàçáèòû]"
+
+#: fileio.c:2138 fileio.c:4115
+msgid "[NOT converted]"
+msgstr "[ÁÅÇ ïðåîáðàçîâàíèé]"
+
+#: fileio.c:2143 fileio.c:4120
+msgid "[converted]"
+msgstr "[ïåðåêîäèðîâàíî]"
+
+#: fileio.c:2150 fileio.c:4145
+msgid "[crypted]"
+msgstr "[çàøèôðîâàíî]"
+
+#: fileio.c:2157
+msgid "[CONVERSION ERROR]"
+msgstr "[ÎØÈÁÊÀ ÏÐÅÎÁÐÀÇÎÂÀÍÈß]"
+
+#: fileio.c:2163
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[ÍÅÄÎÏÓÑÒÈÌÛÉ ÁÀÉÒ â ñòðîêå %ld]"
+
+#: fileio.c:2170
+msgid "[READ ERRORS]"
+msgstr "[ÎØÈÁÊÈ ×ÒÅÍÈß]"
+
+#: fileio.c:2386
+msgid "Can't find temp file for conversion"
+msgstr "Âðåìåííûé ôàéë äëÿ ïåðåêîäèðîâàíèÿ íå íàéäåí"
+
+#: fileio.c:2393
+msgid "Conversion with 'charconvert' failed"
+msgstr "Ïðåîáðàçîâàíèå ñ ïîìîùüþ 'charconvert' íå âûïîëíåíî"
+
+#: fileio.c:2396
+msgid "can't read output of 'charconvert'"
+msgstr "íåâîçìîæíî ïðî÷èòàòü âûâîä 'charconvert'"
+
+#: fileio.c:2796
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr ""
+"E203: Áóôåð, êîòîðûé òðåáîâàëîñü çàïèñàòü, óäàë¸í èëè âûãðóæåí àâòîêîìàíäîé"
+
+#: fileio.c:2819
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Êîëè÷åñòâî ñòðîê èçìåíåíî àâòîêîìàíäîé íåîæèäàííûì îáðàçîì"
+
+#: fileio.c:2857
+msgid "NetBeans dissallows writes of unmodified buffers"
+msgstr "NetBeans íå ïîçâîëÿåò âûïîëíÿòü çàïèñü íåèçìåí¸ííûõ áóôåðîâ"
+
+#: fileio.c:2865
+msgid "Partial writes disallowed for NetBeans buffers"
+msgstr "×àñòè÷íàÿ çàïèñü áóôåðîâ NetBeans íå äîïóñêàåòñÿ"
+
+#: fileio.c:2919 fileio.c:2937
+msgid "is not a file or writable device"
+msgstr "íå ÿâëÿåòñÿ ôàéëîì èëè óñòðîéñòâîì, äîñòóïíûì äëÿ çàïèñè"
+
+#: fileio.c:2989
+msgid "is read-only (add ! to override)"
+msgstr "îòêðûò òîëüêî äëÿ ÷òåíèÿ (!, ÷òîáû îáîéòè ïðîâåðêó)"
+
+#: fileio.c:3335
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: Çàïèñü â ðåçåðâíûé ôàéë íåâîçìîæíà (!, ÷òîáû îáîéòè ïðîâåðêó)"
+
+#: fileio.c:3347
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr "E507: Îøèáêà çàêðûòèÿ ðåçåðâíîãî ôàéëà (!, ÷òîáû îáîéòè ïðîâåðêó)"
+
+#: fileio.c:3349
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr "E508: Íåâîçìîæíî ïðî÷èòàòü ðåçåðâíûé ôàéë (!, ÷òîáû îáîéòè ïðîâåðêó)"
+
+#: fileio.c:3365
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: Íåâîçìîæíî ñîçäàòü ðåçåðâíûé ôàéë (!, ÷òîáû îáîéòè ïðîâåðêó)"
+
+#: fileio.c:3468
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: Íåâîçìîæíî ñîçäàòü ðåçåðâíûé ôàéë (!, ÷òîáû îáîéòè ïðîâåðêó)"
+
+#: fileio.c:3530
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr "E460: Âèëêà ðåñóðñà áóäåò ïîòåðÿíà (!, ÷òîáû îáîéòè ïðîâåðêó)"
+
+#: fileio.c:3640
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: Âðåìåííûé ôàéë äëÿ çàïèñè íå íàéäåí"
+
+#: fileio.c:3658
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr "E213: Ïåðåêîäèðîâêà íåâîçìîæíà (! äëÿ çàïèñè áåç ïåðåêîäèðîâêè)"
+
+#: fileio.c:3693
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Íåâîçìîæíî îòêðûòü ñâÿçàííûé ôàéë äëÿ çàïèñè"
+
+#: fileio.c:3697
+msgid "E212: Can't open file for writing"
+msgstr "E212: Íåâîçìîæíî îòêðûòü ôàéë äëÿ çàïèñè"
+
+#: fileio.c:3959
+msgid "E667: Fsync failed"
+msgstr "E667: Íå óäàëîñü âûïîëíèòü ôóíêöèþ fsync()"
+
+#: fileio.c:3966
+msgid "E512: Close failed"
+msgstr "E512: Îïåðàöèÿ çàêðûòèÿ íå óäàëàñü"
+
+#: fileio.c:4037
+msgid "E513: write error, conversion failed"
+msgstr "E513: Îøèáêà çàïèñè, ïðåîáðàçîâàíèå íå óäàëîñü"
+
+#: fileio.c:4043
+msgid "E514: write error (file system full?)"
+msgstr "E514: îøèáêà çàïèñè (íåò ñâîáîäíîãî ìåñòà?)"
+
+#: fileio.c:4110
+msgid " CONVERSION ERROR"
+msgstr " ÎØÈÁÊÀ ÏÐÅÎÁÐÀÇÎÂÀÍÈß"
+
+#: fileio.c:4126
+msgid "[Device]"
+msgstr "[Óñòðîéñòâî]"
+
+#: fileio.c:4131
+msgid "[New]"
+msgstr "[Íîâûé]"
+
+#: fileio.c:4153
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:4153
+msgid " appended"
+msgstr " äîáàâëåíî"
+
+#: fileio.c:4155
+msgid " [w]"
+msgstr " [w]"
+
+#: fileio.c:4155
+msgid " written"
+msgstr " çàïèñàíî"
+
+#: fileio.c:4205
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: Ðåæèì çàïëàòêè: íåâîçìîæíî ñîõðàíåíèå èñõîäíîãî ôàéëà"
+
+#: fileio.c:4227
+msgid "E206: patchmode: can't touch empty original file"
+msgstr ""
+"E206: Ðåæèì çàïëàòêè: íåâîçìîæíî ñìåíèòü ïàðàìåòðû ïóñòîãî èñõîäíîãî ôàéëà"
+
+#: fileio.c:4242
+msgid "E207: Can't delete backup file"
+msgstr "E207: Íåâîçìîæíî óäàëèòü ðåçåðâíûé ôàéë"
+
+#: fileio.c:4306
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"ÏÐÅÄÓÏÐÅÆÄÅÍÈÅ: Èñõîäíûé ôàéë ìîæåò áûòü óòðà÷åí èëè ïîâðåæä¸í\n"
+
+#: fileio.c:4308
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "íå âûõîäèòå èç ðåäàêòîðà, ïîêà ôàéë íå áóäåò óñïåøíî çàïèñàí!"
+
+#: fileio.c:4397
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:4397
+msgid "[dos format]"
+msgstr "[ôîðìàò dos]"
+
+#: fileio.c:4404
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:4404
+msgid "[mac format]"
+msgstr "[ôîðìàò mac]"
+
+#: fileio.c:4411
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:4411
+msgid "[unix format]"
+msgstr "[ôîðìàò unix]"
+
+#: fileio.c:4438
+msgid "1 line, "
+msgstr "1 ñòðîêà, "
+
+#: fileio.c:4440
+#, c-format
+msgid "%ld lines, "
+msgstr "ñòðîê: %ld, "
+
+#: fileio.c:4443
+msgid "1 character"
+msgstr "1 ñèìâîë"
+
+#: fileio.c:4445
+#, c-format
+msgid "%ld characters"
+msgstr "ñèìâîëîâ: %ld"
+
+#: fileio.c:4455
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:4455
+msgid "[Incomplete last line]"
+msgstr "[Íåçàâåðø¸ííàÿ ïîñëåäíÿÿ ñòðîêà]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4474
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "ÏÐÅÄÓÏÐÅÆÄÅÍÈÅ: Ôàéë èçìåí¸í ñ ìîìåíòà ÷òåíèÿ!!!"
+
+#: fileio.c:4476
+msgid "Do you really want to write to it"
+msgstr "Ñåðü¸çíî õîòèòå çàïèñàòü â ýòîò ôàéë"
+
+#: fileio.c:5726
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Îøèáêà çàïèñè â \"%s\""
+
+#: fileio.c:5733
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Îøèáêà çàêðûòèÿ \"%s\""
+
+#: fileio.c:5736
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Îøèáêà ÷òåíèÿ \"%s\""
+
+#: fileio.c:5970
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: Áóôåð óäàë¸í ïðè âûïîëíåíèè àâòîêîìàíäû FileChangedShell"
+
+#: fileio.c:5977
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: Ïðåäóïðåæäåíèå: ôàéë \"%s\" áîëüøå íå äîñòóïåí"
+
+#: fileio.c:5991
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: Ïðåäóïðåæäåíèå: ôàéë \"%s\" è áóôåð Vim áûëè èçìåíåíû íåçàâèñèìî äðóã "
+"îò äðóãà"
+
+#: fileio.c:5994
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr ""
+"W11: Ïðåäóïðåæäåíèå: ôàéë \"%s\" áûë èçìåí¸í ïîñëå íà÷àëà ðåäàêòèðîâàíèÿ"
+
+#: fileio.c:5996
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr ""
+"W16: Ïðåäóïðåæäåíèå: ðåæèì äîñòóïà ê ôàéëó \"%s\" áûë èçìåí¸í ïîñëå íà÷àëà "
+"ðåäàêòèðîâàíèÿ"
+
+#: fileio.c:6006
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr ""
+"W13: Ïðåäóïðåæäåíèå: ôàéë \"%s\" áûë ñîçäàí ïîñëå íà÷àëà ðåäàêòèðîâàíèÿ"
+
+#: fileio.c:6019
+msgid "See \":help W11\" for more info."
+msgstr "Ñì. äîïîëíèòåëüíóþ èíôîðìàöèþ â \":help W11\"."
+
+#: fileio.c:6033
+msgid "Warning"
+msgstr "Ïðåäóïðåæäåíèå"
+
+#: fileio.c:6034
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Çàãðóçèòü ôàéë"
+
+#: fileio.c:6140
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: Íåâîçìîæíî ïîäãîòîâèòüñÿ ê ïåðåçàãðóçêå \"%s\""
+
+#: fileio.c:6159
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: Íåâîçìîæíî âûïîëíèòü ïåðåçàãðóçêó \"%s\""
+
+#: fileio.c:6740
+msgid "--Deleted--"
+msgstr "--Óäàëåíî--"
+
+#. the group doesn't exist
+#: fileio.c:6900
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Ãðóïïà \"%s\" íå ñóùåñòâóåò"
+
+#: fileio.c:7026
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Íåäîïóñòèìûå ñèìâîëû ïîñëå *: %s"
+
+#: fileio.c:7038
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Íåñóùåñòâóþùåå ñîáûòèå: %s"
+
+#: fileio.c:7040
+#, c-format
+msgid "E216: No such group or event: %s"
+msgstr "E216: Íåñóùåñòâóþùàÿ ãðóïïà èëè ñîáûòèå: %s"
+
+#. Highlight title
+#: fileio.c:7198
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Àâòîêîìàíäû ---"
+
+#: fileio.c:7469
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Íåâîçìîæíî âûïîëíèòü àâòîêîìàíäû äëÿ ÂÑÅÕ ñîáûòèé"
+
+#: fileio.c:7492
+msgid "No matching autocommands"
+msgstr "Íåò ïîäõîäÿùèõ àâòîêîìàíä"
+
+#: fileio.c:7813
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: ñëèøêîì ãëóáîêî âëîæåííûå àâòîêîìàíäû"
+
+#: fileio.c:8088
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Àâòîêîìàíäû äëÿ \"%s\""
+
+#: fileio.c:8096
+#, c-format
+msgid "Executing %s"
+msgstr "Âûïîëíåíèå %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:8164
+#, c-format
+msgid "autocommand %s"
+msgstr "àâòîêîìàíäà %s"
+
+#: fileio.c:8731
+msgid "E219: Missing {."
+msgstr "E219: Ïðîïóùåíà {."
+
+#: fileio.c:8733
+msgid "E220: Missing }."
+msgstr "E220: Ïðîïóùåíà }."
+
+#: fold.c:68
+msgid "E490: No fold found"
+msgstr "E490: Ñêëàäîê íå îáíàðóæåíî"
+
+#: fold.c:593
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr ""
+"E350: Ñêëàäêà íå ìîæåò áûòü ñîçäàíà ñ òåêóùèì çíà÷åíèåì îïöèè 'foldmethod'"
+
+#: fold.c:595
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr ""
+"E351: Ñêëàäêà íå ìîæåò áûòü óäàëåíà ñ òåêóùèì çíà÷åíèåì îïöèè 'foldmethod'"
+
+#: getchar.c:248
+msgid "E222: Add to read buffer"
+msgstr "E222: Äîáàâëåíèå â áóôåð ÷òåíèÿ"
+
+#: getchar.c:2198
+msgid "E223: recursive mapping"
+msgstr "E223: ðåêóðñèâíàÿ ïðèâÿçêà"
+
+#: getchar.c:3077
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: óæå åñòü ãëîáàëüíîå ñîêðàùåíèå äëÿ %s"
+
+#: getchar.c:3080
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: óæå åñòü ãëîáàëüíàÿ ïðèâÿçêà äëÿ %s"
+
+#: getchar.c:3212
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: óæå åñòü ñîêðàùåíèå äëÿ %s"
+
+#: getchar.c:3215
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: óæå åñòü ïðèâÿçêà äëÿ %s"
+
+#: getchar.c:3279
+msgid "No abbreviation found"
+msgstr "Ñîêðàùåíèÿ íå íàéäåíû"
+
+#: getchar.c:3281
+msgid "No mapping found"
+msgstr "Ïðèâÿçêè íå íàéäåíû"
+
+#: getchar.c:4173
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: íåäîïóñòèìûé ðåæèì"
+
+#: gui.c:220
+msgid "E229: Cannot start the GUI"
+msgstr "E229: Íåâîçìîæíî ïåðåéòè â ðåæèì ãðàôè÷åñêîãî èíòåðôåéñà"
+
+#: gui.c:349
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Íåâîçìîæíî âûïîëíèòü ÷òåíèå \"%s\""
+
+#: gui.c:472
+msgid "E665: Cannot start GUI, no valid font found"
+msgstr ""
+"E665: Íåâîçìîæíî ïåðåéòè â ðåæèì ãðàô. èíòåðôåéñà, íåïðàâèëüíî çàäàíû øðèôòû"
+
+#: gui.c:477
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: íåïðàâèëüíîå çíà÷åíèå îïöèè 'guifontwide'"
+
+#: gui.c:547
+msgid "E599: Value of 'imactivatekey' is invalid"
+msgstr "E599: íåïðàâèëüíîå çíà÷åíèå îïöèè 'imactivatekey'"
+
+#: gui.c:4061
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: Íåâîçìîæíî íàçíà÷èòü öâåò %s"
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<íåëüçÿ îòêðûòü> "
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: øðèôò %s íå íàéäåí"
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: âîçâðàò â òåêóùèé êàòàëîã íåâîçìîæåí"
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "Ïóòü ê ôàéëó:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: íå ìîãó íàéòè òåêóùèé êàòàëîã"
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "Äà"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2731 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "Îòìåíà"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Ïîëîñà ïðîêðóòêè: íå ìîãó îïðåäåëèòü ãåîìåòðèþ ïîëçóíêà"
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "Äèàëîãîâîå îêíî Vim"
+
+#: gui_beval.c:101 gui_w32.c:3829
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr ""
+"E232: \"Ïóçûðü\" äëÿ âû÷èñëåíèé, âêëþ÷àþùèé è ñîîáùåíèå, è îáðàòíûé âûçîâ, "
+"íå ìîæåò áûòü ñîçäàí"
+
+#: gui_gtk.c:1607
+msgid "Vim dialog..."
+msgstr "Äèàëîãîâîå îêíî Vim..."
+
+#: gui_gtk.c:2060 message.c:2993
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Äà\n"
+"&Íåò\n"
+"Î&òìåíà"
+
+#: gui_gtk.c:2268
+msgid "Input _Methods"
+msgstr "Ìåòîäû Ââîäà"
+
+#: gui_gtk.c:2534 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Ïîèñê è çàìåíà..."
+
+#: gui_gtk.c:2542 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "VIM - Ïîèñê..."
+
+#: gui_gtk.c:2574 gui_motif.c:2888
+msgid "Find what:"
+msgstr "×òî èùåì:"
+
+#: gui_gtk.c:2592 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "Íà ÷òî çàìåíÿåì:"
+
+#. whole word only button
+#: gui_gtk.c:2624 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "Òîëüêî òî÷íûå ñîîòâåòñòâèÿ"
+
+#. match case button
+#: gui_gtk.c:2635 gui_motif.c:3048
+msgid "Match case"
+msgstr "Ðåãèñòðîçàâèñèìûå ñîîòâåòñòâèÿ"
+
+#: gui_gtk.c:2645 gui_motif.c:2990
+msgid "Direction"
+msgstr "Íàïðàâëåíèå"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2657 gui_motif.c:3002
+msgid "Up"
+msgstr "Ââåðõ"
+
+#: gui_gtk.c:2661 gui_motif.c:3010
+msgid "Down"
+msgstr "Âíèç"
+
+#: gui_gtk.c:2683 gui_gtk.c:2685 gui_motif.c:2792
+msgid "Find Next"
+msgstr "Íàéòè ñëåäóþùåå"
+
+#: gui_gtk.c:2702 gui_gtk.c:2704 gui_motif.c:2809
+msgid "Replace"
+msgstr "Çàìåíà"
+
+#: gui_gtk.c:2715 gui_gtk.c:2717 gui_motif.c:2822
+msgid "Replace All"
+msgstr "Çàìåíèòü âñå"
+
+#: gui_gtk_x11.c:2327
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: Ïîëó÷åí çàïðîñ íà ïðåêðàùåíèå ðàáîòû îò äèñïåò÷åðà ñåàíñîâ\n"
+
+#: gui_gtk_x11.c:3519
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: Îñíîâíîå îêíî áûëî íåîæèäàííî çàêðûòî\n"
+
+#: gui_gtk_x11.c:4138
+msgid "Font Selection"
+msgstr "Âûáîð øðèôòà"
+
+#: gui_gtk_x11.c:6035 ui.c:2120
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "Âìåñòî ïóñòîãî âûäåëåíèÿ èñïîëüçóåòñÿ CUT_BUFFER0"
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "Ôèëüòð"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "Êàòàëîãè"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "Ñïðàâêà"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "Ôàéëû"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "Âûäåëåíèå"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "Îòìåíà"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: Íåâîçìîæíî çàãðóçèòü øðèôò Zap '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: Íåâîçìîæíî èñïîëüçîâàòü øðèôò %s"
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Îòïðàâêà ñîîáùåíèÿ äëÿ óíè÷òîæåíèÿ ïðîöåññà-ïîòîìêà.\n"
+
+#: gui_w32.c:829
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Ïàðàìåòð íå ïîääåðæèâàåòñÿ: \"-%s\"; èñïîëüçóéòå âåðñèþ OLE."
+
+#: gui_w48.c:2090
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Ïîèñê ñòðîêè (èñïîëüçóéòå '\\\\' äëÿ ïîèñêà '\\')"
+
+#: gui_w48.c:2115
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Ïîèñê è çàìåíà (èñïîëüçóéòå '\\\\' äëÿ ïîèñêà '\\')"
+
+#: gui_x11.c:1537
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: íåâîçìîæíî âûäåëèòü çàïèñü â òàáëèöå öâåòà, íåêîòîðûå öâåòàìîãóò "
+"îòîáðàæàòüñÿ íåïðàâèëüíî"
+
+#: gui_x11.c:2118
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: â íàáîðå øðèôòîâ %s îòñóòñòâóþò øðèôòû äëÿ ñëåäóþùèõ êîäèðîâîê:"
+
+#: gui_x11.c:2161
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Íàáîð øðèôòîâ: %s"
+
+#: gui_x11.c:2162
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "Øðèôò '%s' íå ÿâëÿåòñÿ ìîíîøèðèííûì"
+
+#: gui_x11.c:2181
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Íàáîð øðèôòîâ: %s\n"
+
+#: gui_x11.c:2182
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Font0: %s\n"
+
+#: gui_x11.c:2183
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Font1: %s\n"
+
+#: gui_x11.c:2184
+msgid "Font%ld width is not twice that of font0\n"
+msgstr "Øèðèíà øðèôòà font%ld äîëæíà áûòü âäâîå áîëüøå øèðèíû øðèôòà font0\n"
+
+#: gui_x11.c:2185
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "Øèðèíà øðèôòà font0: %ld\n"
+
+#: gui_x11.c:2186
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"Øèðèíà øðèôòà font1: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "Ó256Æ ÎØÈÁÊÀ àâòîìàòèêè Õàíãûë"
+
+#: if_cscope.c:77
+msgid "Add a new database"
+msgstr "Äîáàâèòü íîâóþ áàçó äàííûõ"
+
+#: if_cscope.c:79
+msgid "Query for a pattern"
+msgstr "Çàïðîñ ïî øàáëîíó"
+
+#: if_cscope.c:81
+msgid "Show this message"
+msgstr "Ïîêàçàòü ýòî ñîîáùåíèå"
+
+#: if_cscope.c:83
+msgid "Kill a connection"
+msgstr "Óáèòü ñîåäèíåíèå"
+
+#: if_cscope.c:85
+msgid "Reinit all connections"
+msgstr "Çàíîâî èíèöèàëèçèðîâàòü âñå ñîåäèíåíèÿ"
+
+#: if_cscope.c:87
+msgid "Show connections"
+msgstr "Ïîêàçàòü ñîåäèíåíèÿ"
+
+#: if_cscope.c:95
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: Èñïîëüçîâàíèå: cs[cope] %s"
+
+#: if_cscope.c:124
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Ýòà êîìàíäà cscope íå ïîääåðæèâàåò ðàçäåëåíèå îêíà.\n"
+
+#: if_cscope.c:175
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: Èñïîëüçîâàíèå: cstag <èìÿ>"
+
+#: if_cscope.c:231
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: ìåòêà íå íàéäåíà"
+
+#: if_cscope.c:409
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "îøèáêà stat(%s): %d"
+
+#: if_cscope.c:419
+msgid "E563: stat error"
+msgstr "E563: îøèáêà stat"
+
+#: if_cscope.c:516
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s íå ÿâëÿåòñÿ êàòàëîãîì èëè èìåíåì áàçû cscope"
+
+#: if_cscope.c:534
+#, c-format
+msgid "Added cscope database %s"
+msgstr "Äîáàâëåíà áàçà äàííûõ cscope %s"
+
+#: if_cscope.c:589
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: îøèáêà ïîëó÷åíèÿ èíôîðìàöèè îò ñîåäèíåíèÿ cscope %d"
+
+#: if_cscope.c:694
+msgid "E561: unknown cscope search type"
+msgstr "E561: íåèçâåñòíûé òèï ïîèñêà cscope"
+
+#: if_cscope.c:736
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: Íåâîçìîæíî ñîçäàòü òðóáó äëÿ cscope"
+
+#: if_cscope.c:753
+msgid "E622: Could not fork for cscope"
+msgstr "E622: Íåâîçìîæíî âûïîëíèòü fork() äëÿ cscope"
+
+#: if_cscope.c:847 if_cscope.c:897
+msgid "cs_create_connection exec failed"
+msgstr "íå óäàëîñü âûïîëíèòü cs_create_connection"
+
+#: if_cscope.c:898
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: Íå óäàëîñü çàïóñòèòü ïðîöåññ cscope"
+
+#: if_cscope.c:911
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: íå óäàëîñü âûïîëíèòü fdopen äëÿ to_fp"
+
+#: if_cscope.c:913
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: íå óäàëîñü âûïîëíèòü fdopen äëÿ fr_fp"
+
+#: if_cscope.c:951
+msgid "E567: no cscope connections"
+msgstr "E567: ñîåäèíåíèé ñ cscope íå ñîçäàíî"
+
+#: if_cscope.c:1025
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: íå íàéäåíî ñîîòâåòñòâèé ïî çàïðîñó cscope %s äëÿ %s"
+
+#: if_cscope.c:1082
+#, c-format
+msgid "E469: invalid cscopequickfix flag %c for %c"
+msgstr "E469: íåïðàâèëüíûé ôëàã cscopequickfix %c äëÿ %c"
+
+#: if_cscope.c:1152
+msgid "cscope commands:\n"
+msgstr "êîìàíäû cscope:\n"
+
+#: if_cscope.c:1155
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (Èñïîëüçîâàíèå: %s)"
+
+#: if_cscope.c:1253
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: íåâîçìîæíî îòêðûòü áàçó äàííûõ cscope: %s"
+
+#: if_cscope.c:1271
+msgid "E626: cannot get cscope database information"
+msgstr "E626: èíôîðìàöèÿ î áàçå äàííûõ cscope íå äîñòóïíà"
+
+#: if_cscope.c:1296
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: äàííàÿ áàçà äàííûõ cscope óæå ïîäñîåäèíåíà"
+
+#: if_cscope.c:1307
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: äîñòèãíóòî ìàêñèìàëüíîå çíà÷åíèå îòêðûòûõ ñîåäèíåíèé ñ cscope"
+
+#: if_cscope.c:1424
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: ñîåäèíåíèå ñ cscope %s íå îáíàðóæåíî"
+
+#: if_cscope.c:1458
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "ñîåäèíåíèå ñ cscope çàêðûòî"
+
+#. should not reach here
+#: if_cscope.c:1598
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: êðèòè÷åñêàÿ îøèáêà â cs_manage_matches"
+
+#: if_cscope.c:1848
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "Ìåòêà cscope: %s"
+
+#: if_cscope.c:1870
+msgid ""
+"\n"
+" # line"
+msgstr ""
+"\n"
+" # ñòðîêà"
+
+#: if_cscope.c:1872
+msgid "filename / context / line\n"
+msgstr "èìÿ ôàéëà / êîíòåêñò / ñòðîêà\n"
+
+#: if_cscope.c:1990
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: Îøèáêà cscope: %s"
+
+#: if_cscope.c:2176
+msgid "All cscope databases reset"
+msgstr "Ïåðåçàãðóçêà âñåõ áàç äàííûõ cscope"
+
+#: if_cscope.c:2244
+msgid "no cscope connections\n"
+msgstr "ñîåäèíåíèÿ ñ cscope îòñóòñòâóþò\n"
+
+#: if_cscope.c:2248
+msgid " # pid database name prepend path\n"
+msgstr " # pid áàçà äàííûõ íà÷àëüíûé ïóòü\n"
+
+#: if_python.c:436
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: Ê ñîæàëåíèþ ýòà êîìàíäà íå ðàáîòàåò, ïîñêîëüêó íå çàãðóæåíà áèáëèîòåêà "
+"Python"
+
+#: if_python.c:500
+msgid "E659: Cannot invoke Python recursively"
+msgstr "E659: Íåâîçìîæíî âûïîëíèòü ðåêóðñèâíûé âûçîâ Python"
+
+#: if_python.c:701
+msgid "can't delete OutputObject attributes"
+msgstr "íåâîçìîæíî óäàëèòü àòðèáóòû OutputObject"
+
+#: if_python.c:708
+msgid "softspace must be an integer"
+msgstr "çíà÷åíèå softspace äîëæíî áûòü öåëûì ÷èñëîì"
+
+#: if_python.c:716
+msgid "invalid attribute"
+msgstr "íåïðàâèëüíûé àòðèáóò"
+
+#: if_python.c:755 if_python.c:769
+msgid "writelines() requires list of strings"
+msgstr "writelines() òðåáóåò óêàçàíèÿ ñïèñêà ñòðîê"
+
+#: if_python.c:895
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: Îøèáêà èíèöèàëèçàöèè îáúåêòîâ I/O"
+
+#: if_python.c:1080 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "íåïðàâèëüíîå âûðàæåíèå"
+
+#: if_python.c:1094 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "âûðàæåíèÿ îòêëþ÷åíû ïðè êîìïèëÿöèè"
+
+#: if_python.c:1107
+msgid "attempt to refer to deleted buffer"
+msgstr "ïîïûòêà ñîñëàòüñÿ íà óíè÷òîæåííûé áóôåð"
+
+#: if_python.c:1122 if_python.c:1163 if_python.c:1227 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "çàïðåäåëüíûé íîìåð ñòðîêè"
+
+#: if_python.c:1362
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<îáúåêò áóôåðà (óäàëåí) â %8lX>"
+
+#: if_python.c:1453 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "íåïðàâèëüíîå èìÿ îòìåòêè"
+
+#: if_python.c:1733
+msgid "no such buffer"
+msgstr "íåò òàêîãî áóôåðà"
+
+#: if_python.c:1821
+msgid "attempt to refer to deleted window"
+msgstr "ïîïûòêà ñîñëàòüñÿ íà çàêðûòîå îêíî"
+
+#: if_python.c:1866
+msgid "readonly attribute"
+msgstr "àòðèáóò äîñòóïåí òîëüêî äëÿ ÷òåíèÿ"
+
+#: if_python.c:1879
+msgid "cursor position outside buffer"
+msgstr "ïîçèöèÿ êóðñîðà íàõîäèòñÿ âíå áóôåðà"
+
+#: if_python.c:1956
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<îáúåêò îêíà (óäàëåí) â %.8lX>"
+
+#: if_python.c:1968
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<îáúåêò îêíà (íåèçâåñòåí) â %.8lX>"
+
+#: if_python.c:1970
+#, c-format
+msgid "<window %d>"
+msgstr "<îêíî %d>"
+
+#: if_python.c:2046
+msgid "no such window"
+msgstr "íåò òàêîãî îêíà"
+
+#: if_python.c:2307 if_python.c:2341 if_python.c:2396 if_python.c:2464
+#: if_python.c:2586 if_python.c:2638 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "íåâîçìîæíî ñîõðàíèòü èíôîðìàöèþ îá îòìåíå îïåðàöèè"
+
+#: if_python.c:2309 if_python.c:2403 if_python.c:2475
+msgid "cannot delete line"
+msgstr "íåâîçìîæíî óäàëèòü ñòðîêó"
+
+#: if_python.c:2346 if_python.c:2491 if_tcl.c:690 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "íåâîçìîæíî çàìåíèòü ñòðîêó"
+
+#: if_python.c:2509 if_python.c:2588 if_python.c:2646
+msgid "cannot insert line"
+msgstr "íåâîçìîæíî âñòàâèòü ñòðîêó"
+
+#: if_python.c:2750
+msgid "string cannot contain newlines"
+msgstr "ñòðîêà íå ìîæåò ñîäåðæàòü ñèìâîë íîâîé ñòðîêè"
+
+#: if_ruby.c:422
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: Ê ñîæàëåíèþ ýòà êîìàíäà íå ðàáîòàåò, ïîñêîëüêó íå çàãðóæåíà áèáëèîòåêà "
+"Ruby."
+
+#: if_ruby.c:485
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: íåèçâåñòíîå ñîñòîÿíèå longjmp %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Ïåðåêëþ÷åíèå ìåæäó ðåàëèçàöèåé/îïðåäåëåíèåì"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Ïîêàçàòü áàçîâûé êëàññ "
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Ïîêàçàòü ïåðåãðóæåííûå ôóíêöèè"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Ïîëó÷åíèå èç ôàéëà"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Ïîëó÷åíèå èç ïðîåêòà"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Ïîëó÷åíèå èç âñåõ ïðîåêòîâ"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Ïîëó÷åíèå"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Ïîêàçàòü èñõîäíûé êîä"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Íàéòè ñèìâîë"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Ïðîñìîòð êëàññà"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Ïîêàçàòü êëàññ â èåðàðõèè"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Ïîêàçàòü êëàññ â îãðàíè÷åííîé èåðàðõèè"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref ññûëàåòñÿ íà"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Ññûëêà íà xref èç"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref èìååò"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref èñïîëüçóåòñÿ"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Ïîêàçàòü docu"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Ñîçäàòü docu"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"Íåâîçìîæíî ïîäñîåäèíèòüñÿ ê SNiFF+. Ïðîâåðüòå íàñòðîéêè îêðóæåíèÿ."
+"(sniffemacs äîëæíû áûòü óêàçàíû â ïåðåìåííîé $PATH).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Îøèáêà âî âðåìÿ ÷òåíèÿ. Îòñîåäèíåíèå"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "Â íàñòîÿùèé ìîìåíò SNiFF+ "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "íå "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "ïîäñîåäèí¸í"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Íåèçâåñòíûé çàïðîñ SNiFF+: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Îøèáêà ñîåäèíåíèÿ ñî SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ íå ïîäñîåäèí¸í"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Ýòî íå áóôåð SNiFF+"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: Îøèáêà âî âðåìÿ çàïèñè. Îòñîåäèíåíèå"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "íåïðàâèëüíûé íîìåð áóôåðà"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "ïîêà íå ðåàëèçîâàíî"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "íåèçâåñòíàÿ îïöèÿ"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "íåâîçìîæíî íàçíà÷èòü ñòðîêó èëè ñòðîêè"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "îòìåòêà íå óñòàíîâëåíà"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "ðÿä %d êîëîíêà %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "íåâîçìîæíî âñòàâèòü èëè äîáàâèòü ñòðîêó"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "íåèçâåñòíûé ôëàã: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "íåèçâåñòíàÿ vimOption"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "êëàâèàòóðíîå ïðåðûâàíèå"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "îøèáêà vim"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "íåâîçìîæíî ñîçäàòü êîìàíäó áóôåðà èëè îêíà: îáúåêò â ïðîöåññå óäàëåíèÿ"
+
+#: if_tcl.c:1545
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"íåâîçìîæíî çàðåãèñòðèðîâàòü êîìàíäó ñ îáðàòíûì âûçîâîì: áóôåð èëè îêíî â "
+"ïðîöåññå óäàëåíèÿ"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: ÊÐÈÒÈ×ÅÑÊÀß ÎØÈÁÊÀ TCL: ïîâðåæä¸í ñïèñîê ññûëîê?! Ñîîáùèòå îá ýòîì ïî "
+"àäðåñó vim-dev@vim.org"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"íåâîçìîæíî çàðåãèñòðèðîâàòü êîìàíäó ñ îáðàòíûì âûçîâîì: ññûëêà íà áóôåð èëè "
+"îêíî íå îáíàðóæåíà"
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"E571: Ê ñîæàëåíèþ ýòà êîìàíäà íå ðàáîòàåò, ïîñêîëüêó íå çàãðóæåíà áèáëèîòåêà "
+"Tcl"
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: ÎØÈÁÊÀ TCL: Êîä âûõîäà íå ÿâëÿåòñÿ öåëûì ÷èñëîì?! Ñîîáùèòå îá ýòîì â "
+"vim-dev@vim.org"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "íåâîçìîæíî ïîëó÷èòü ñòðîêó"
+
+#: if_xcmdsrv.c:225
+msgid "Unable to register a command server name"
+msgstr "Íåâîçìîæíî çàðåãèñòðèðîâàòü èìÿ ñåðâåðà êîìàíä"
+
+#: if_xcmdsrv.c:473
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Îòïðàâêà êîìàíäû â äðóãóþ ïðîãðàììó íå óäàëàñü"
+
+#: if_xcmdsrv.c:747
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: Èñïîëüçóåòñÿ íåïðàâèëüíûé id ñåðâåðà: %s"
+
+#: if_xcmdsrv.c:1110
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr ""
+"E251: Íåïðàâèëüíî ñôîðìèðîâàíî çíà÷åíèå äàííîãî ïðîöåññà VIM â ðååñòðå. "
+"Óäàëåíî!"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "Íåèçâåñòíûé àðãóìåíò"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "Ñëèøêîì ìíîãî àðãóìåíòîâ ðåäàêòèðîâàíèÿ"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "Ïðîïóùåí àðãóìåíò ïîñëå"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "Ìóñîð ïîñëå àðãóìåíòà"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr ""
+"Ñëèøêîì ìíîãî àðãóìåíòîâ \"+êîìàíäà\", \"-c êîìàíäà\" èëè \"--cmd êîìàíäà\""
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "Íåäîïóñòèìûå àðãóìåíòû äëÿ"
+
+#: main.c:466
+msgid "This Vim was not compiled with the diff feature."
+msgstr ""
+"Äàííûé Vim áûë ñêîìïèëèðîâàí ñ âûêëþ÷åííîé îñîáåííîñòüþ ïðîñìîòðà îòëè÷èé"
+
+#: main.c:932
+msgid "Attempt to open script file again: \""
+msgstr "Ïîïûòêà ïîâòîðíîãî îòêðûòèÿ ôàéëà ñöåíàðèÿ: \""
+
+#: main.c:941
+msgid "Cannot open for reading: \""
+msgstr "Íåâîçìîæíî îòêðûòü äëÿ ÷òåíèÿ: \""
+
+#: main.c:985
+msgid "Cannot open for script output: \""
+msgstr "Íåâîçìîæíî îòêðûòü äëÿ âûâîäà ñöåíàðèÿ: \""
+
+#: main.c:1132
+#, c-format
+msgid "%d files to edit\n"
+msgstr "Ôàéëîâ äëÿ ðåäàêòèðîâàíèÿ: %d\n"
+
+#: main.c:1233
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Ïðåäóïðåæäåíèå: Âûâîä îñóùåñòâëÿåòñÿ íå íà òåðìèíàë\n"
+
+#: main.c:1235
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Ïðåäóïðåæäåíèå: Ââîä ïðîèñõîäèò íå ñ òåðìèíàëà\n"
+
+#. just in case..
+#: main.c:1297
+msgid "pre-vimrc command line"
+msgstr "êîìàíäíàÿ ñòðîêà ïåðåä âûïîëíåíèåì vimrc"
+
+#: main.c:1338
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Íåâîçìîæíî âûïîëíèòü ÷òåíèå èç \"%s\""
+
+#: main.c:2411
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Äîïîëíèòåëüíàÿ èíôîðìàöèÿ: \"vim -h\"\n"
+
+#: main.c:2444
+msgid "[file ..] edit specified file(s)"
+msgstr "[ôàéë ..] ðåäàêòèðîâàíèå óêàçàííûõ ôàéëîâ"
+
+#: main.c:2445
+msgid "- read text from stdin"
+msgstr "- ÷òåíèå òåêñòà èç ïîòîêà ââîäà stdin"
+
+#: main.c:2446
+msgid "-t tag edit file where tag is defined"
+msgstr "-t ìåòêà ðåäàêòèðîâàíèå ôàéëà ñ óêàçàííîé ìåòêîé"
+
+#: main.c:2448
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [ôàéë îøèáîê] ðåäàêòèðîâàíèå ôàéëà ñ ïåðâîé îøèáêîé"
+
+#: main.c:2457
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"Èñïîëüçîâàíèå:"
+
+#: main.c:2460
+msgid " vim [arguments] "
+msgstr " vim [àðãóìåíòû] "
+
+#: main.c:2464
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" èëè:"
+
+#: main.c:2467
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Àðãóìåíòû:\n"
+
+#: main.c:2468
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tÄàëåå óêàçûâàþòñÿ òîëüêî èìåíà ôàéëîâ"
+
+#: main.c:2470
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tÍå âûïîëíÿòü ïîäñòàíîâêó ïî ìàñêå"
+
+#: main.c:2473
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tÇàðåãèñòðèðîâàòü ýòîò gvim äëÿ OLE"
+
+#: main.c:2474
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tÎòêëþ÷èòü ðåãèñòðàöèþ äàííîãî gvim äëÿ OLE"
+
+#: main.c:2477
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tÇàïóñòèòü ñ ãðàôè÷åñêèì èíòåðôåéñîì (êàê \"gvim\")"
+
+#: main.c:2478
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f èëè --nofork\t àêòèâíîé çàäà÷å: Íå âûïîëíÿòü fork ïðè çàïóñêå GUI"
+
+#: main.c:2480
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tÐåæèì Vi (êàê \"vi\")"
+
+#: main.c:2481
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tÐåæèì Ex (êàê \"ex\")"
+
+#: main.c:2482
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tÒèõèé (ïàêåòíûé) ðåæèì (òîëüêî äëÿ \"ex\")"
+
+#: main.c:2484
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tÐåæèì îòëè÷èé (êàê \"vimdiff\")"
+
+#: main.c:2486
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tÏðîñòîé ðåæèì (êàê \"evim\", áåçðåæèìíûé)"
+
+#: main.c:2487
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tÒîëüêî äëÿ ÷òåíèÿ (êàê \"view\")"
+
+#: main.c:2488
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tÎãðàíè÷åííûé ðåæèì (êàê \"rvim\")"
+
+#: main.c:2489
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tÁåç âîçìîæíîñòè ñîõðàíåíèÿ èçìåíåíèé (çàïèñè ôàéëîâ)"
+
+#: main.c:2490
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tÁåç âîçìîæíîñòè âíåñåíèÿ èçìåíåíèé â òåêñò"
+
+#: main.c:2491
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tÁèíàðíûé ðåæèì"
+
+#: main.c:2493
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tÐåæèì Lisp"
+
+#: main.c:2495
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tÐåæèì ñîâìåñòèìîñòè ñ Vi: 'compatible'"
+
+#: main.c:2496
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tÐåæèì íåïîëíîé ñîâìåñòèìîñòè ñ Vi: 'nocompatible'"
+
+#: main.c:2497
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tÓðîâåíü ïîäðîáíîñòè ñîîáùåíèé"
+
+#: main.c:2498
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tÐåæèì îòëàäêè"
+
+#: main.c:2499
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tÁåç ñâîï-ôàéëà, èñïîëüçóåòñÿ òîëüêî ïàìÿòü"
+
+#: main.c:2500
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tÂûâåñòè ñïèñîê ñâîï-ôàéëîâ è çàâåðøèòü ðàáîòó"
+
+#: main.c:2501
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (ñ èìåíåì ôàéëà)\tÂîññòàíîâèòü àâàðèéíî çàâåðø¸ííûé ñåàíñ"
+
+#: main.c:2502
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tÒî æå, ÷òî è -r"
+
+#: main.c:2504
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tÍå èñïîëüçîâàòü newcli äëÿ îòêðûòèÿ îêíà"
+
+#: main.c:2505
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <óñòðîéñòâî>\t\tÈñïîëüçîâàòü äëÿ I/O óêàçàííîå <óñòðîéñòâî>"
+
+#: main.c:2508
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\t\tÇàïóñê â Àðàáñêîì ðåæèìå"
+
+#: main.c:2511
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\tÇàïóñê â ðåæèìå \"Èâðèò\""
+
+#: main.c:2514
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\tÇàïóñê â ðåæèìå \"Ôàðñè\""
+
+#: main.c:2516
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <òåðìèíàë>\tÍàçíà÷èòü óêàçàííûé òèï <òåðìèíàëà>"
+
+#: main.c:2517
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tÈñïîëüçîâàòü <vimrc> âìåñòî ëþáûõ ôàéëîâ .vimrc"
+
+#: main.c:2519
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tÈñïîëüçîâàòü <gvimrc> âìåñòî ëþáûõ ôàéëîâ .gvimrc"
+
+#: main.c:2521
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tÍå çàãðóæàòü ñöåíàðèè ìîäóëåé"
+
+#: main.c:2522
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tÎòêðûòü N îêîí (ïî óìîë÷àíèþ: ïî îäíîìó íà êàæäûé ôàéë)"
+
+#: main.c:2523
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\tÒî æå, ÷òî è -o, íî ñ âåðòèêàëüíûì ðàçäåëåíèåì îêîí"
+
+#: main.c:2524
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tÍà÷àòü ðåäàêòèðîâàíèå â êîíöå ôàéëà"
+
+#: main.c:2525
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\tÍà÷àòü ðåäàêòèðîâàíèå â ñòðîêå ñ íîìåðîì <lnum>"
+
+#: main.c:2527
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <êîìàíäà>\tÂûïîëíèòü <êîìàíäó> ïåðåä çàãðóçêîé ôàéëà vimrc"
+
+#: main.c:2529
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <êîìàíäà>\t\tÂûïîëíèòü <êîìàíäó> ïîñëå çàãðóçêè ïåðâîãî ôàéëà"
+
+#: main.c:2530
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <ñåàíñ>\t\tÏðî÷èòàòü ñöåíàðèé <ñåàíñà> ïîñëå çàãðóçêè ïåðâîãî ôàéëà"
+
+#: main.c:2531
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <ñöåíàðèé>\tÏðî÷èòàòü êîìàíäû Îáû÷íîãî ðåæèìà èç ôàéëà <ñöåíàðèÿ>"
+
+#: main.c:2532
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <ñöåíàðèé>\tÄîáàâëÿòü âñå ââåä¸ííûå êîìàíäû â ôàéë <ñöåíàðèÿ>"
+
+#: main.c:2533
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <ñöåíàðèé>\tÇàïèñàòü âñå ââåä¸ííûå êîìàíäû â ôàéë <ñöåíàðèÿ>"
+
+#: main.c:2535
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tÐåäàêòèðîâàíèå çàøèôðîâàííûõ ôàéëîâ"
+
+#: main.c:2539
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <ýêðàí>\tÏîäñîåäèíèòü vim ê óêàçàííîìó ñåðâåðó X"
+
+#: main.c:2541
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tÍå âûïîëíÿòü ñîåäèíåíèå ñ ñåðâåðîì X"
+
+#: main.c:2544
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <ôàéëû>\tÏî âîçìîæíîñòè ðåäàêòèðîâàòü <ôàéëû> íà ñåðâåðå Vim"
+
+#: main.c:2545
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-silent <ôàéëû> Òî æå, íî áåç æàëîá íà îòñóòñòâèå ñåðâåðà"
+
+#: main.c:2546
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr ""
+"--remote-wait <ôàéëû> Òî æå, ÷òî è --remote, íî ñ îæèäàíèåì çàâåðøåíèÿ"
+
+#: main.c:2547
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr ""
+"--remote-wait-silent <ôàéëû> Òî æå, íî áåç æàëîá íà îòñóòñòâèå ñåðâåðà"
+
+#: main.c:2548
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <êíîïêè>\tÎòïðàâèòü <êíîïêè> íà ñåðâåð Vim è âûéòè"
+
+#: main.c:2549
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <âûðàæ>\tÂû÷èñëèòü <âûðàæ> íà ñåðâåðå Vim è íàïå÷àòàòü"
+
+#: main.c:2550
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tÏîêàçàòü ñïèñîê èì¸í ñåðâåðîâ Vim è çàâåðøèòü ðàáîòó"
+
+#: main.c:2551
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr ""
+"--servername <èìÿ>\tÎòïðàâèòü íà/ñòàòü ñåðâåðîì Vim ñ óêàçàííûì <èìåíåì>"
+
+#: main.c:2554
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tÈñïîëüçîâàòü âìåñòî .viminfo ôàéë <viminfo>"
+
+#: main.c:2556
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h èëè --help\tÂûâåñòè ñïðàâêó (ýòî ñîîáùåíèå) è çàâåðøèòü ðàáîòó"
+
+#: main.c:2557
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\tÂûâåñòè èíôîðìàöèþ î âåðñèè Vim è çàâåðøèòü ðàáîòó"
+
+#: main.c:2561
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Àðãóìåíòû äëÿ gvim (âåðñèÿ Motif):\n"
+
+#: main.c:2565
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr ""
+"\n"
+"Àðãóìåíòû äëÿ gvim (âåðñèÿ neXtaw):\n"
+
+#: main.c:2567
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Àðãóìåíòû äëÿ gvim (âåðñèÿ Athena):\n"
+
+#: main.c:2571
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <äèñïëåé>\tÇàïóñòèòü vim íà óêàçàííîì <äèñïëåå>"
+
+#: main.c:2572
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tÇàïóñòèòü vim â ñâ¸ðíóòîì âèäå"
+
+#: main.c:2574
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <èìÿ>\t\tÈñïîëüçîâàòü ðåñóðñ, êàê åñëè áû vim áûë <èìåíåì>"
+
+#: main.c:2575
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (Íå ðåàëèçîâàíî)\n"
+
+#: main.c:2577
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr ""
+"-background <öâåò>\tÈñïîëüçîâàòü óêàçàííûé <öâåò> äëÿ ôîíà (òàêæå: -bg)"
+
+#: main.c:2578
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr ""
+"-foreground <öâåò>\tÈñïîëüçîâàòü <öâåò> äëÿ îáû÷íîãî òåêñòà (òàêæå: -fg)"
+
+#: main.c:2579 main.c:2599
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <øðèôò>\t\tÈñïîëüçîâàòü <øðèôò> äëÿ îáû÷íîãî òåêñòà (òàêæå: -fn)"
+
+#: main.c:2580
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <øðèôò>\tÈñïîëüçîâàòü <øðèôò> äëÿ æèðíîãî òåêñòà"
+
+#: main.c:2581
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <øðèôò>\tÈñïîëüçîâàòü <øðèôò> äëÿ íàêëîííîãî òåêñòà"
+
+#: main.c:2582 main.c:2600
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr ""
+"-geometry <ãåîìåòðèÿ>\tÈñïîëüçîâàòü íà÷àëüíóþ <ãåîìåòðèþ> (òàêæå: -geom)"
+
+#: main.c:2583
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <øèðèíà>\tÈñïîëüçîâàòü <øèðèíó> áîðäþðà (òàêæå: -bw)"
+
+#: main.c:2584
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr ""
+"-scrollbarwidth <øèðèíà> Èñïîëüçîâàòü øèðèíó ïîëîñû ïðîêðóòêè (òàêæå: -sw)"
+
+#: main.c:2586
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <âûñîòà>\tÈñïîëüçîâàòü <âûñîòó> ìåíþ (òàêæå: -mh)"
+
+#: main.c:2588 main.c:2601
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tÈñïîëüçîâàòü èíâåðñíûé âèäåîðåæèì (òàêæå: -rv)"
+
+#: main.c:2589
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tÍå èñïîëüçîâàòü èíâåðñíûé âèäåîðåæèì (òàêæå: +rv)"
+
+#: main.c:2590
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <ðåñóðñ>\tÓñòàíîâèòü óêàçàííûé <ðåñóðñ>"
+
+#: main.c:2593
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Àðãóìåíòû äëÿ gvim (âåðñèÿ RISC OS):\n"
+
+#: main.c:2594
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <÷èñëî>\tÏåðâîíà÷àëüíàÿ øèðèíà îêíà â êîëîíêàõ"
+
+#: main.c:2595
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <÷èñëî>\tÏåðâîíà÷àëüíàÿ âûñîòà îêíà â ñòðîêàõ"
+
+#: main.c:2598
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Àðãóìåíòû äëÿ gvim (âåðñèÿ GTK+):\n"
+
+#: main.c:2602
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr ""
+"-display <äèñïëåé>\tÇàïóñòèòü vim íà óêàçàííîì <äèñïëåå> (òàêæå: --display)"
+
+#: main.c:2604
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr ""
+"--role <ðîëü>\tÓñòàíîâèòü óíèêàëüíóþ <ðîëü> äëÿ èäåíòèôèêàöèè ãëàâíîãî îêíà"
+
+#: main.c:2606
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tÎòêðûòü Vim âíóòðè äðóãîãî êîìïîíåíòà GTK"
+
+#: main.c:2609
+msgid "-P <parent title>\tOpen Vim inside parent application"
+msgstr "-P <çàãîëîâîê ðîäèòåëÿ>\tÎòêðûòü Vim â ðîäèòåëüñêîì ïðèëîæåíèè"
+
+#: main.c:2847
+msgid "No display"
+msgstr "Íåò äèñïëåÿ"
+
+#. Failed to send, abort.
+#: main.c:2862
+msgid ": Send failed.\n"
+msgstr ": Îòïðàâêà íå óäàëàñü.\n"
+
+#. Let vim start normally.
+#: main.c:2868
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": Îòïðàâêà íå óäàëàñü. Ïîïûòêà ìåñòíîãî âûïîëíåíèÿ\n"
+
+#: main.c:2906 main.c:2927
+#, c-format
+msgid "%d of %d edited"
+msgstr "îòðåäàêòèðîâàíî %d èç %d"
+
+#: main.c:2949
+msgid "No display: Send expression failed.\n"
+msgstr "Íåò äèñïëåÿ: îòïðàâêà âûðàæåíèÿ íå óäàëàñü.\n"
+
+#: main.c:2961
+msgid ": Send expression failed.\n"
+msgstr ": Îòïðàâêà âûðàæåíèÿ íå óäàëàñü.\n"
+
+#: mark.c:709
+msgid "No marks set"
+msgstr "Íåò óñòàíîâëåííûõ îòìåòîê"
+
+#: mark.c:711
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: Íåò îòìåòîê, ñîâïàäàþùèõ ñ \"%s\""
+
+#. Highlight title
+#: mark.c:722
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"îòìåò ñòð êîë ôàéë/òåêñò"
+
+#. Highlight title
+#: mark.c:760
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+"ïðûæîê ñòð êîë ôàéë/òåêñò"
+
+#. Highlight title
+#: mark.c:805
+msgid ""
+"\n"
+"change line col text"
+msgstr ""
+"\n"
+"èçìåí. ñòð êîë òåêñò"
+
+#: mark.c:1281
+#, c-format
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Ãëîáàëüíûå îòìåòêè:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1316
+#, c-format
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Ñïèñîê ïðûæêîâ (ñíà÷àëà áîëåå ñâåæèå):\n"
+
+#: mark.c:1412
+#, c-format
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Èñòîðèÿ ìåñòíûõ îòìåòîê (îò áîëåå ñâåæèõ ê ñòàðûì):\n"
+
+#: mark.c:1501
+msgid "Missing '>'"
+msgstr "Ïðîïóùåíà '>'"
+
+#: mbyte.c:467
+msgid "E543: Not a valid codepage"
+msgstr "E543: Íåäîïóñòèìîå èìÿ êîäèðîâêè"
+
+#: mbyte.c:4431
+msgid "E284: Cannot set IC values"
+msgstr "E284: Íåâîçìîæíî íàçíà÷èòü çíà÷åíèÿ êîíòåêñòà ââîäà"
+
+#: mbyte.c:4583
+msgid "E285: Failed to create input context"
+msgstr "E285: Íåâîçìîæíî ñîçäàòü êîíòåêñò ââîäà"
+
+#: mbyte.c:4741
+msgid "E286: Failed to open input method"
+msgstr "E286: Íåóäà÷íàÿ ïîïûòêà îòêðûòü ìåòîä ââîäà"
+
+#: mbyte.c:4752
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr ""
+"E287: Ïðåäóïðåæäåíèå: íåâîçìîæíî íàçíà÷èòü îáð. âûçîâ óíè÷òîæåíèÿ ìåòîäà "
+"ââîäà"
+
+#: mbyte.c:4758
+msgid "E288: input method doesn't support any style"
+msgstr "E288: ìåòîä ââîäà íå ïîääåðæèâàåò ñòèëè"
+
+#: mbyte.c:4815
+msgid "E289: input method doesn't support my preedit type"
+msgstr ""
+"E289: ìåòîä ââîäà íå ïîääåðæèâàåò ìîé òèï ïðåäâàðèòåëüíîãî ðåäàêòèðîâàíèÿ"
+
+#: mbyte.c:4889
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: ñòèëü \"íàä ìåñòîì\" òðåáóåò óêàçàíèÿ øðèôòîâîãî íàáîðà"
+
+#: mbyte.c:4925
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr ""
+"E291: GTK+ áîëåå ðàííåé âåðñèè, ÷åì 1.2.3. Îáëàñòü ñîñòîÿíèÿ íå ðàáîòàåò."
+
+#: mbyte.c:5232
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Ñåðâåð ìåòîäà ââîäà íå çàïóùåí"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: áëîê íå çàáëîêèðîâàí"
+
+#: memfile.c:1005
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Îøèáêà ïîèñêà ïðè ÷òåíèè ñâîï-ôàéëà"
+
+#: memfile.c:1010
+msgid "E295: Read error in swap file"
+msgstr "E295: Îøèáêà ÷òåíèÿ ñâîï-ôàéëà"
+
+#: memfile.c:1062
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Îøèáêà ïîèñêà ïðè çàïèñè ñâîï-ôàéëà"
+
+#: memfile.c:1080
+msgid "E297: Write error in swap file"
+msgstr "E297: Îøèáêà ïðè çàïèñè ñâîï-ôàéëà"
+
+#: memfile.c:1277
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr ""
+"E300: Ñâîï-ôàéë óæå ñóùåñòâóåò (àòàêà ñ èñïîëüçîâàíèåì ñèìâîëüíîé ññûëêè?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Íå ïîëó÷åí áëîê íîìåð 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Íå ïîëó÷åí áëîê íîìåð 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: Íå ïîëó÷åí áëîê íîìåð 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Îé, ïîòåðÿëñÿ ñâîï-ôàéë!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: Íåâîçìîæíî ïåðåèìåíîâàòü ñâîï-ôàéë"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr ""
+"E303: Íå óäàëîñü îòêðûòü ñâîï-ôàéë äëÿ \"%s\", âîññòàíîâëåíèå íåâîçìîæíî"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: Íå ïîëó÷åí áëîê 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Ñâîï-ôàéë äëÿ %s íå íàéäåí"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr ""
+"Ââåäèòå íîìåð ñâîï-ôàéëà, êîòîðûé ñëåäóåò èñïîëüçîâàòü (0 äëÿ âûõîäà): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: Íå ìîãó îòêðûòü %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "Íåâîçìîæíî ïðî÷èòàòü áëîê 0 èç "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Íåò èçìåíåíèé, èëè Vim íå ñìîã îáíîâèòü ñâîï-ôàéë"
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " íåëüçÿ èñïîëüçîâàòü â äàííîé âåðñèè Vim.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Èñïîëüçóéòå Vim âåðñèè 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s íå ÿâëÿåòñÿ ñâîï-ôàéëîì Vim"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " íåëüçÿ èñïîëüçîâàòü íà ýòîì êîìïüþòåðå.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "Ôàéë áûë ñîçäàí "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"ëèáî ôàéë áûë ïîâðåæä¸í."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "Èñïîëüçóåòñÿ ñâîï-ôàéë \"%s\""
+
+#: memline.c:909
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Èñõîäíûé ôàéë \"%s\""
+
+#: memline.c:922
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Ïðåäóïðåæäåíèå: èñõîäíûé ôàéë ìîã áûòü èçìåí¸í"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Íåâîçìîæíî ïðî÷èòàòü áëîê 1 èç %s"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???ÎÒÑÓÒÑÒÂÓÅÒ ÌÍÎÃÎ ÑÒÐÎÊ"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???ÍÅÏÐÀÂÈËÜÍÎÅ ÇÍÀ×ÅÍÈÅ Ñ×ÅÒ×ÈÊÀ ÑÒÐÎÊ"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???ÏÓÑÒÎÉ ÁËÎÊ"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???ÎÒÑÓÒÑÒÂÓÞÒ ÑÒÐÎÊÈ"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: íåïðàâèëüíûé áëîê 1 ID (%s íå ÿâëÿåòñÿ ôàéëîì .swp?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???ÏÐÎÏÓÙÅÍ ÁËÎÊ"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "???ñòðîêè ìîãóò áûòü èñïîð÷åíû îòñþäà äî ???ÊÎÍÖÀ"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "???ñòðîêè ìîãëè áûòü âñòàâëåíû èëè óäàëåíû îòñþäà äî ???ÊÎÍÖÀ"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???ÊÎÍÅÖ"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Âîññòàíîâëåíèå ïðåðâàíî"
+
+#: memline.c:1148
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr ""
+"E312: Âî âðåìÿ âîññòàíîâëåíèÿ îáíàðóæåíû îøèáêè; ñì. ñòðîêè, íà÷èíàþùèåñÿ "
+"ñ ???"
+
+#: memline.c:1150
+msgid "See \":help E312\" for more information."
+msgstr "Ñì. äîïîëíèòåëüíóþ èíôîðìàöèþ â ñïðàâî÷íèêå (\":help E312\")"
+
+#: memline.c:1155
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Âîññòàíîâëåíèå çàâåðøåíî. Ïðîâåðüòå, âñ¸ ëè â ïîðÿäêå."
+
+#: memline.c:1156
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Ìîæåòå çàïèñàòü ôàéë ïîä äðóãèì èìåíåì è ñðàâíèòü åãî ñ èñõîäíûì\n"
+
+#: memline.c:1157
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "ôàéëîì ïðè ïîìîùè ïðîãðàììû diff).\n"
+
+#: memline.c:1158
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"Çàòåì óäàëèòå ôàéë .swp.\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1214
+msgid "Swap files found:"
+msgstr "Îáíàðóæåíû ñâîï-ôàéëû:"
+
+#: memline.c:1392
+msgid " In current directory:\n"
+msgstr " Â òåêóùåì êàòàëîãå:\n"
+
+#: memline.c:1394
+msgid " Using specified name:\n"
+msgstr " Ñ óêàçàííûì èìåíåì:\n"
+
+#: memline.c:1398
+msgid " In directory "
+msgstr " Â êàòàëîãå "
+
+#: memline.c:1416
+msgid " -- none --\n"
+msgstr " -- íåò --\n"
+
+#: memline.c:1488
+msgid " owned by: "
+msgstr " âëàäåëåö: "
+
+#: memline.c:1490
+msgid " dated: "
+msgstr " äàòà: "
+
+#: memline.c:1494 memline.c:3684
+msgid " dated: "
+msgstr " äàòà: "
+
+#: memline.c:1510
+msgid " [from Vim version 3.0]"
+msgstr " [îò Vim âåðñèè 3.0]"
+
+#: memline.c:1514
+msgid " [does not look like a Vim swap file]"
+msgstr " [íå ÿâëÿåòñÿ ñâîï-ôàéëîì Vim]"
+
+#: memline.c:1518
+msgid " file name: "
+msgstr " èìÿ ôàéëà: "
+
+#: memline.c:1524
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" èçìåí¸í: "
+
+#: memline.c:1525
+msgid "YES"
+msgstr "ÄÀ"
+
+#: memline.c:1525
+msgid "no"
+msgstr "íåò"
+
+#: memline.c:1529
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" ïîëüçîâàòåëü: "
+
+#: memline.c:1536
+msgid " host name: "
+msgstr " êîìïüþòåð: "
+
+#: memline.c:1538
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" êîìïüþòåð: "
+
+#: memline.c:1544
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ïðîöåññ: "
+
+#: memline.c:1550
+msgid " (still running)"
+msgstr " (åù¸ âûïîëíÿåòñÿ)"
+
+#: memline.c:1562
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [íå ïðèãîäåí äëÿ èñïîëüçîâàíèÿ ñ äàííîé âåðñèåé Vim]"
+
+#: memline.c:1565
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [íå ïðèãîäåí äëÿ èñïîëüçîâàíèÿ íà ýòîì êîìïüþòåðå]"
+
+#: memline.c:1570
+msgid " [cannot be read]"
+msgstr " [íå ÷èòàåòñÿ]"
+
+#: memline.c:1574
+msgid " [cannot be opened]"
+msgstr " [íå îòêðûâàåòñÿ]"
+
+#: memline.c:1764
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Íåâîçìîæíî îáíîâèòü ñâîï-ôàéë, ïîñêîëüêó îí íå îáíàðóæåí"
+
+#: memline.c:1817
+msgid "File preserved"
+msgstr "Ñâîï-ôàéë îáíîâë¸í"
+
+#: memline.c:1819
+msgid "E314: Preserve failed"
+msgstr "E314: Íåóäà÷íàÿ ïîïûòêà îáíîâëåíèÿ ñâîï-ôàéëà"
+
+#: memline.c:1890
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: íåïðàâèëüíîå çíà÷åíèå lnum: %ld"
+
+#: memline.c:1916
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: íåâîçìîæíî íàéòè ñòðîêó %ld"
+
+#: memline.c:2306
+msgid "E317: pointer block id wrong 3"
+msgstr "íåïðàâèëüíîå çíà÷åíèå óêàçàòåëÿ áëîêà 3"
+
+#: memline.c:2386
+msgid "stack_idx should be 0"
+msgstr "çíà÷åíèå stack_idx äîëæíî áûòü ðàâíî 0"
+
+#: memline.c:2448
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Îáíîâëåíî ñëèøêîì ìíîãî áëîêîâ?"
+
+#: memline.c:2630
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: íåïðàâèëüíîå çíà÷åíèå óêàçàòåëÿ áëîêà 4"
+
+#: memline.c:2657
+msgid "deleted block 1?"
+msgstr "óäàë¸í áëîê 1?"
+
+#: memline.c:2857
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Ñòðîêà %ld íå îáíàðóæåíà"
+
+#: memline.c:3100
+msgid "E317: pointer block id wrong"
+msgstr "E317: íåïðàâèëüíîå çíà÷åíèå óêàçàòåëÿ áëîêà"
+
+#: memline.c:3116
+msgid "pe_line_count is zero"
+msgstr "çíà÷åíèå pe_line_count ðàâíî íóëþ"
+
+#: memline.c:3145
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: íîìåð ñòðîêè çà ïðåäåëàìè äèàïàçîíà: %ld"
+
+#: memline.c:3149
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: íåïðàâèëüíîå çíà÷åíèå ñ÷¸ò÷èêà ñòðîê â áëîêå %ld"
+
+#: memline.c:3198
+msgid "Stack size increases"
+msgstr "Ðàçìåð ñòåêà óâåëè÷åí"
+
+#: memline.c:3244
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: íåïðàâèëüíîå çíà÷åíèå óêàçàòåëÿ áëîêà 2"
+
+#: memline.c:3674
+msgid "E325: ATTENTION"
+msgstr "E325: ÂÍÈÌÀÍÈÅ"
+
+#: memline.c:3675
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Îáíàðóæåí ñâîï-ôàéë ñ èìåíåì \""
+
+#: memline.c:3679
+msgid "While opening file \""
+msgstr "Ïðè îòêðûòèè ôàéëà: \""
+
+#: memline.c:3688
+msgid " NEWER than swap file!\n"
+msgstr " Áîëåå ÑÂÅÆÈÉ, ÷åì ñâîï-ôàéë!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3692
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Âîçìîæíî, ðåäàêòèðîâàíèå ôàéëà âûïîëíÿåòñÿ â äðóãîé ïðîãðàììå.\n"
+" Åñëè ýòî òàê, òî áóäüòå âíèìàòåëüíû ïðè âíåñåíèè èçìåíåíèé,\n"
+" ÷òîáû ó âàñ íå ïîÿâèëîñü äâà ðàçíûõ âàðèàíòà îäíîãî è òîãî æå ôàéëà.\n"
+
+#: memline.c:3693
+msgid " Quit, or continue with caution.\n"
+msgstr " Çàâåðøèòå ðàáîòó èëè ïðîäîëæàéòå ñ îñòîðîæíîñòüþ.\n"
+
+#: memline.c:3694
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) Ïðåäûäóùèé ñåàíñ ðåäàêòèðîâàíèÿ ýòîãî ôàéëà çàâåðø¸í àâàðèéíî.\n"
+
+#: memline.c:3695
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr "  ýòîì ñëó÷àå, èñïîëüçóéòå êîìàíäó \":recover\" èëè \"vim -r "
+
+#: memline.c:3697
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" äëÿ âîññòàíîâëåíèÿ èçìåíåíèé (ñì. \":help âîññòàíîâëåíèå\").\n"
+
+#: memline.c:3698
+msgid " If you did this already, delete the swap file \""
+msgstr " Åñëè âû óæå âûïîëíÿëè ýòó îïåðàöèþ, óäàëèòå ñâîï-ôàéë \""
+
+#: memline.c:3700
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" ÷òîáû èçáåæàòü ïîÿâëåíèÿ ýòîãî ñîîáùåíèÿ â áóäóùåì.\n"
+
+#: memline.c:3714 memline.c:3718
+msgid "Swap file \""
+msgstr "Ñâîï-ôàéë \""
+
+#: memline.c:3715 memline.c:3721
+msgid "\" already exists!"
+msgstr "\" óæå ñóùåñòâóåò!"
+
+#: memline.c:3724
+msgid "VIM - ATTENTION"
+msgstr "VIM - ÂÍÈÌÀÍÈÅ"
+
+#: memline.c:3726
+msgid "Swap file already exists!"
+msgstr "Ñâîï-ôàéë óæå ñóùåñòâóåò!"
+
+#: memline.c:3730
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort"
+msgstr ""
+"&O Îòêðûòü äëÿ ÷òåíèÿ\n"
+"&E Ðåäàêòèðîâàòü\n"
+"&R Âîññòàíîâèòü\n"
+"&Q Âûõîä\n"
+"&A Ïðåðâàòü"
+
+#: memline.c:3732
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort\n"
+"&Delete it"
+msgstr ""
+"&O Îòêðûòü äëÿ ÷òåíèÿ\n"
+"&E Ðåäàêòèðîâàòü\n"
+"&R Âîññòàíîâèòü\n"
+"&Q Âûõîä\n"
+"&A Ïðåðâàòü\n"
+"&D Óäàëèòü"
+
+#: memline.c:3789
+msgid "E326: Too many swap files found"
+msgstr "E326: Îáíàðóæåíî ñëèøêîì ìíîãî ñâîï-ôàéëîâ"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Êîìïîíåíò ïóòè ê ýëåìåíòó ìåíþ íå ÿâëÿåòñÿ ïîäìåíþ"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Ìåíþ â ýòîì ðåæèìå íå ñóùåñòâóåò"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Íåò ìåíþ ñ òàêèì èìåíåì"
+
+#: menu.c:525
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Ïóòü ê ìåíþ íå äîëæåí âåñòè ê ïîäìåíþ"
+
+#: menu.c:564
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: Ýëåìåíòû ìåíþ íåëüçÿ äîáàâëÿòü íåïîñðåäñòâåííî â ïîëîñêó ìåíþ"
+
+#: menu.c:570
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Ðàçäåëèòåëè íå ìîãóò áûòü êîìïîíåíòîì ïóòè ê ìåíþ"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1097
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Ìåíþ ---"
+
+#: menu.c:2019
+msgid "Tear off this menu"
+msgstr "Îòîðâàòü ýòî ìåíþ"
+
+#: menu.c:2084
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Ïóòü ê ìåíþ äîëæåí âåñòè ê ýëåìåíòó ìåíþ"
+
+#: menu.c:2104
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Ìåíþ íå íàéäåíî: %s"
+
+#: menu.c:2173
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: Ìåíþ íå îïðåäåëåíî äëÿ ðåæèìà %s"
+
+#: menu.c:2211
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Ïóòü ê ìåíþ äîëæåí âåñòè ê ïîäìåíþ"
+
+#: menu.c:2232
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Ìåíþ íå íàéäåíî -- ïðîâåðüòå èìåíà ìåíþ"
+
+#: message.c:414
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Îáíàðóæåíà îøèáêà ïðè îáðàáîòêå %s:"
+
+#: message.c:440
+#, c-format
+msgid "line %4ld:"
+msgstr "ñòðîêà %4ld:"
+
+#: message.c:647
+msgid "[string too long]"
+msgstr "[ñëèøêîì äëèííàÿ ñòðîêà]"
+
+#: message.c:797
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr ""
+"Ïåðåâîä ñîîáùåíèé íà ðóññêèé ÿçûê: Âàñèëèé Ðàãîçèí <vrr@users.sourceforge."
+"net>"
+
+#: message.c:1025
+msgid "Interrupt: "
+msgstr "Ïðåðûâàíèå: "
+
+#: message.c:1028
+msgid "Hit ENTER to continue"
+msgstr "Äëÿ ïðîäîëæåíèÿ íàæìèòå ENTER"
+
+#: message.c:1030
+msgid "Hit ENTER or type command to continue"
+msgstr "Äëÿ ïðîäîëæåíèÿ íàæìèòå ENTER èëè ââåäèòå êîìàíäó"
+
+#: message.c:2351
+msgid "-- More --"
+msgstr "-- Ïðîäîëæåíèå ñëåäóåò --"
+
+#: message.c:2354
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: ñòðîêà, SPACE/b: ñòðàíèöà, d/u: ïîëñòðàíèöû, q: âûõîä)"
+
+#: message.c:2355
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: ñòðîêà, SPACE: ñòðàíèöà, d: ïîëñòðàíèöû, q: âûõîä)"
+
+#: message.c:2976 message.c:2991
+msgid "Question"
+msgstr "Âîïðîñ"
+
+#: message.c:2978
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Äà\n"
+"&Íåò"
+
+#: message.c:3011
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Äà\n"
+"&Íåò\n"
+"Ñîõðàíèòü &âñå\n"
+"&Ïîòåðÿòü âñå\n"
+"Î&òìåíà"
+
+#: message.c:3052
+msgid "Save File dialog"
+msgstr "Ñîõðàíåíèå ôàéëà"
+
+#: message.c:3054
+msgid "Open File dialog"
+msgstr "Îòêðûòèå ôàéëà"
+
+#. TODO: non-GUI file selector here
+#: message.c:3125
+msgid "E338: Sorry, no file browser in console mode"
+msgstr ""
+"E338: Èçâèíèòå, íî â êîíñîëüíîì ðåæèìå íåò ïðîâîäíèêà ïî ôàéëîâîé ñèñòåìå"
+
+#: misc1.c:2773
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: Ïðåäóïðåæäåíèå: Èçìåíåíèå ôàéëà ñ ïðàâàìè òîëüêî äëÿ ÷òåíèÿ"
+
+#: misc1.c:3021
+msgid "1 more line"
+msgstr "Äîáàâëåíà îäíà ñòðîêà"
+
+#: misc1.c:3023
+msgid "1 line less"
+msgstr "Óäàëåíà îäíà ñòðîêà"
+
+#: misc1.c:3028
+#, c-format
+msgid "%ld more lines"
+msgstr "Äîáàâëåíî ñòðîê: %ld"
+
+#: misc1.c:3030
+#, c-format
+msgid "%ld fewer lines"
+msgstr "Óäàëåíî ñòðîê: %ld"
+
+#: misc1.c:3033
+msgid " (Interrupted)"
+msgstr " (Ïðåðâàíî)"
+
+#: misc1.c:7588
+msgid "Vim: preserving files...\n"
+msgstr "Vim: ñîõðàíÿþòñÿ ôàéëû...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:7598
+msgid "Vim: Finished.\n"
+msgstr "Vim: Ãîòîâî.\n"
+
+#: misc2.c:695 misc2.c:711
+#, c-format
+msgid "ERROR: "
+msgstr "ÎØÈÁÊÀ: "
+
+#: misc2.c:715
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[áàéò] âñåãî âûäåë.-îñâîá. %lu-%lu, èñïîëüç. %lu, ìàêñ. èñïîëüç. %lu\n"
+
+#: misc2.c:717
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[âûçîâû] re/malloc() âñåãî %lu, free() âñåãî %lu\n"
+"\n"
+
+#: misc2.c:772
+msgid "E340: Line is becoming too long"
+msgstr "E340: Ñòðîêà ñòàíîâèòñÿ ñëèøêîì äëèííîé"
+
+#: misc2.c:816
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Âíóòðåííÿÿ îøèáêà: lalloc(%ld, )"
+
+#: misc2.c:924
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Íå õâàòàåò ïàìÿòè! (âûäåëÿåòñÿ %lu áàéò)"
+
+#: misc2.c:2594
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Âûçîâ îáîëî÷êè äëÿ èñïîëíåíèÿ: \"%s\""
+
+#: misc2.c:2816
+msgid "E545: Missing colon"
+msgstr "E545: Ïðîïóùåíî äâîåòî÷èå"
+
+#: misc2.c:2818 misc2.c:2845
+msgid "E546: Illegal mode"
+msgstr "E546: Íåäîïóñòèìûé ðåæèì"
+
+#: misc2.c:2884
+msgid "E547: Illegal mouseshape"
+msgstr "E547: Íåäîïóñòèìàÿ ôîðìà êóðñîðà"
+
+#: misc2.c:2924
+msgid "E548: digit expected"
+msgstr "E548: òðåáóåòñÿ ââåñòè öèôðó"
+
+#: misc2.c:2929
+msgid "E549: Illegal percentage"
+msgstr "E549: Íåäîïóñòèìîå çíà÷åíèå ïðîöåíòîâ"
+
+#: misc2.c:3239
+msgid "Enter encryption key: "
+msgstr "Ââåäèòå ïàðîëü äëÿ øèôðîâàíèÿ: "
+
+#: misc2.c:3240
+msgid "Enter same key again: "
+msgstr " Ïîâòîðèòå ââîä ïàðîëÿ:"
+
+#: misc2.c:3250
+msgid "Keys don't match!"
+msgstr "Ââåä¸ííûå ïàðîëè íå ñîâïàäàþò!"
+
+#: misc2.c:3799
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Íåïðàâèëüíî çàäàí ïóòü: '**[÷èñëî]' äîëæíî áûòü ëèáî â êîíöå ïóòè, "
+"ëèáî çà íèì äîëæíî ñëåäîâàòü '%s'"
+
+#: misc2.c:5078
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Êàòàëîã \"%s\" íå íàéäåí â ïóòè äëÿ ñìåíû êàòàëîãà"
+
+#: misc2.c:5081
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Ôàéë \"%s\" â èçâåñòíûõ êàòàëîãàõ íå íàéäåí"
+
+#: misc2.c:5087
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: Â ïóòè ñìåíû êàòàëîãà áîëüøå íåò êàòàëîãîâ \"%s\""
+
+#: misc2.c:5090
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: Â èçâåñòíûõ êàòàëîãàõ áîëüøå íåò ôàéëîâ \"%s\""
+
+#: misc2.c:5324
+msgid "E550: Missing colon"
+msgstr "E550: Ïðîïóùåíî äâîåòî÷èå"
+
+#: misc2.c:5336
+msgid "E551: Illegal component"
+msgstr "E551: Íåäîïóñòèìûé êîìïîíåíò"
+
+#: misc2.c:5344
+msgid "E552: digit expected"
+msgstr "E552: Òðåáóåòñÿ óêàçàòü öèôðó"
+
+#. Get here when the server can't be found.
+#: netbeans.c:396
+msgid "Cannot connect to Netbeans #2"
+msgstr "Íåâîçìîæíî ñîåäèíèòüñÿ ñ Netbeans #2"
+
+#: netbeans.c:404
+msgid "Cannot connect to Netbeans"
+msgstr "Íåâîçìîæíî ñîåäèíèòüñÿ ñ NetBeans"
+
+#: netbeans.c:450
+#, c-format
+msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\""
+msgstr ""
+"E668: Íåïðàâèëüíûé ðåæèì äîñòóïà ê èíôîðìàöèè î ñîåäèíåíèè ñ NetBeans: \"%s\""
+
+#: netbeans.c:749
+msgid "read from Netbeans socket"
+msgstr "÷òåíèå èç ãíåçäà NetBeans"
+
+#: netbeans.c:1643
+#, c-format
+msgid "E658: NetBeans connection lost for buffer %ld"
+msgstr "E658: Ïîòåðÿíî ñîåäèíåíèå ñ NetBeans äëÿ áóôåðà %ld"
+
+#: normal.c:2980
+msgid "Warning: terminal cannot highlight"
+msgstr "Ïðåäóïðåæäåíèå: òåðìèíàë íå ìîæåò âûïîëíÿòü ïîäñâåòêó"
+
+#: normal.c:3276
+msgid "E348: No string under cursor"
+msgstr "E348: Íåò ñòðîêè â ïîçèöèè êóðñîðà"
+
+#: normal.c:3278
+msgid "E349: No identifier under cursor"
+msgstr "E349: Íåò èìåíè â ïîçèöèè êóðñîðà"
+
+#: normal.c:4519
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr ""
+"E352: Íåâîçìîæíî ñòåðåòü ñêëàäêè ñ òåêóùèì çíà÷åíèåì îïöèè 'foldmethod'"
+
+#: normal.c:6740
+msgid "E664: changelist is empty"
+msgstr "E664: ñïèñîê èçìåíåíèé ïóñòîé"
+
+#: normal.c:6742
+msgid "E662: At start of changelist"
+msgstr "E662:  íà÷àëå ñïèñêà èçìåíåíèé"
+
+#: normal.c:6744
+msgid "E663: At end of changelist"
+msgstr "E662: Â êîíöå ñïèñêà èçìåíåíèé"
+
+#: normal.c:8005
+msgid "Type :quit<Enter> to exit Vim"
+msgstr "Ââåäèòå :quit<Enter> äëÿ âûõîäà èç Vim"
+
+#: ops.c:294
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "Èçìåíåíû îòñòóïû â 1 ñòðîêå (%s 1 ðàç)"
+
+#: ops.c:296
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "Èçìåíåíû îòñòóïû â 1 ñòðîêå (%s %d ðàç)"
+
+#: ops.c:301
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "Èçìåíåíû îòñòóïû, %ld ñòðîê (%s 1 ðàç)"
+
+#: ops.c:304
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "Èçìåíåíû îòñòóïû, %ld ñòðîê (%s %d ðàç)"
+
+#: ops.c:662
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "Èçìåíÿþòñÿ îòñòóïû ñòðîêàõ (%ld)..."
+
+#: ops.c:712
+msgid "1 line indented "
+msgstr "Èçìåí¸í îòñòóï â îäíîé ñòðîêå "
+
+#: ops.c:714
+#, c-format
+msgid "%ld lines indented "
+msgstr "Èçìåíåíû îòñòóïû â ñòðîêàõ (%ld) "
+
+#. must display the prompt
+#: ops.c:1675
+msgid "cannot yank; delete anyway"
+msgstr "ñêîïèðîâàòü íå óäàëîñü, óäàëåíèå âûïîëíåíî"
+
+#: ops.c:2261
+msgid "1 line changed"
+msgstr "èçìåíåíà 1 ñòðîêà"
+
+#: ops.c:2263
+#, c-format
+msgid "%ld lines changed"
+msgstr "èçìåíåíî ñòðîê: %ld"
+
+#: ops.c:2647
+#, c-format
+msgid "freeing %ld lines"
+msgstr "î÷èùåíî ñòðîê: %ld"
+
+#: ops.c:2928
+msgid "1 line yanked"
+msgstr "ñêîïèðîâàíà îäíà ñòðîêà"
+
+#: ops.c:2930
+#, c-format
+msgid "%ld lines yanked"
+msgstr "ñêîïèðîâàíî ñòðîê: %ld"
+
+#: ops.c:3215
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353:  ðåãèñòðå %s íè÷åãî íåò"
+
+#. Highlight title
+#: ops.c:3766
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Ðåãèñòðû ---"
+
+#: ops.c:5075
+msgid "Illegal register name"
+msgstr "Íåäîïóñòèìîå èìÿ ðåãèñòðà"
+
+#: ops.c:5163
+#, c-format
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Ðåãèñòðû:\n"
+
+#: ops.c:5213
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: Íåèçâåñòíûé òèï ðåãèñòðà %d"
+
+#: ops.c:5698
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: Íåäîïóñòèìîå èìÿ ðåãèñòðà: '%s'"
+
+#: ops.c:6058
+#, c-format
+msgid "%ld Cols; "
+msgstr "Êîëîíîê: %ld; "
+
+#: ops.c:6065
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Âûäåëåíî %s%ld èç %ld ñòðîê; %ld èç %ld ñëîâ; %ld èç %ld áàéò"
+
+#: ops.c:6081
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Êîë. %s èç %s; ñòð. %ld èç %ld; ñëîâî %ld èç %ld; áàéò %ld èç %ld"
+
+#: ops.c:6092
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld ñ ó÷¸òîì BOM)"
+
+#: option.c:1643
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=Ñòð. %N"
+
+#: option.c:2092
+msgid "Thanks for flying Vim"
+msgstr "Áëàãîäàðèì çà èñïîëüçîâàíèå Vim"
+
+#: option.c:3419 option.c:3535
+msgid "E518: Unknown option"
+msgstr "E518: Íåèçâåñòíàÿ îïöèÿ"
+
+#: option.c:3432
+msgid "E519: Option not supported"
+msgstr "E519: Îïöèÿ íå ïîääåðæèâàåòñÿ"
+
+#: option.c:3457
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: Íå äîïóñêàåòñÿ â ðåæèìíîé ñòðîêå"
+
+#: option.c:3522
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\t ïîñëåäíèé ðàç îïöèÿ èçìåíåíà â "
+
+#: option.c:3661
+msgid "E521: Number required after ="
+msgstr "E521: Ïîñëå = òðåáóåòñÿ óêàçàòü ÷èñëî"
+
+#: option.c:3989 option.c:4619
+msgid "E522: Not found in termcap"
+msgstr "E522: Íå îáíàðóæåíî â termcap"
+
+#: option.c:4064
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: Íåäîïóñòèìûé ñèìâîë <%s>"
+
+#: option.c:4611
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: Çíà÷åíèå îïöèè 'term' íå ìîæåò áûòü ïóñòîé ñòðîêîé"
+
+#: option.c:4614
+msgid "E530: Cannot change term in GUI"
+msgstr "E530:  ãðàôè÷åñêîì èíòåðôåéñå èçìåíÿòü òåðìèíàë íåâîçìîæíî"
+
+#: option.c:4616
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: Äëÿ çàïóñêà ãðàôè÷åñêîãî èíòåðôåéñà èñïîëüçóéòå \":gui\""
+
+#: option.c:4645
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: çíà÷åíèÿ îïöèé 'backupext' è 'patchmode' ðàâíû"
+
+#: option.c:4860
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: Íå ìîæåò áûòü èçìåíåíî â ãðàôè÷åñêîì èíòåðôåéñå GTK+ 2"
+
+#: option.c:5016
+msgid "E524: Missing colon"
+msgstr "E524: Ïðîïóùåíî äâîåòî÷èå"
+
+#: option.c:5018
+msgid "E525: Zero length string"
+msgstr "E525: Ñòðîêà ñ íóëåâîé äëèíîé"
+
+#: option.c:5086
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: Ïðîïóùåíî ÷èñëî ïîñëå <%s>"
+
+#: option.c:5100
+msgid "E527: Missing comma"
+msgstr "E527: Ïðîïóùåíà çàïÿòàÿ"
+
+#: option.c:5107
+msgid "E528: Must specify a ' value"
+msgstr "E528: Íåîáõîäèìî óêàçàòü çíà÷åíèå äëÿ '"
+
+#: option.c:5148
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: ñîäåðæèò íåïå÷àòíûé ñèìâîë èëè ñèìâîë äâîéíîé øèðèíû"
+
+#: option.c:5197
+msgid "E596: Invalid font(s)"
+msgstr "E596: Íåïðàâèëüíûå øðèôòû"
+
+#: option.c:5205
+msgid "E597: can't select fontset"
+msgstr "E597: íåâîçìîæíî âûáðàòü øðèôòîâîé íàáîð"
+
+#: option.c:5207
+msgid "E598: Invalid fontset"
+msgstr "E598: Íåïðàâèëüíûé øðèôòîâîé íàáîð"
+
+#: option.c:5214
+msgid "E533: can't select wide font"
+msgstr "E533: íåâîçìîæíî âûáðàòü øðèôò ñ ñèìâîëàìè äâîéíîé øèðèíû"
+
+#: option.c:5216
+msgid "E534: Invalid wide font"
+msgstr "E534: Íåïðàâèëüíûé øðèôò ñ ñèìâîëàìè äâîéíîé øèðèíû"
+
+#: option.c:5486
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: Íåïðàâèëüíûé ñèìâîë ïîñëå <%c>"
+
+#: option.c:5597
+msgid "E536: comma required"
+msgstr "E536: òðåáóåòñÿ çàïÿòàÿ"
+
+#: option.c:5607
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr ""
+"E537: Çíà÷åíèå îïöèÿ 'commentstring' äîëæíî áûòü ïóñòîé ñòðîêîé èëè "
+"ñîäåðæàòü %s"
+
+#: option.c:5679
+msgid "E538: No mouse support"
+msgstr "E538: Ìûøü íå ïîääåðæèâàåòñÿ"
+
+#: option.c:5947
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: Íåçàêðûòàÿ ïîñëåäîâàòåëüíîñòü âûðàæåíèÿ"
+
+#: option.c:5951
+msgid "E541: too many items"
+msgstr "E541: ñëèøêîì ìíîãî ýëåìåíòîâ"
+
+#: option.c:5953
+msgid "E542: unbalanced groups"
+msgstr "E542: íåñáàëàíñèðîâàííûå ãðóïïû"
+
+#: option.c:6193
+msgid "E590: A preview window already exists"
+msgstr "E590: Îêíî ïðåäïðîñìîòðà óæå åñòü"
+
+#: option.c:6450
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr ""
+"W17: Àðàáñêèé òðåáóåò èñïîëüçîâàíèÿ UTF-8, ââåäèòå ':set encoding=utf-8'"
+
+#: option.c:6783
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: Íóæíî õîòÿ áû %d ñòðîê"
+
+#: option.c:6793
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: Íóæíî õîòÿ áû %d êîëîíîê"
+
+#: option.c:7100
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Íåèçâåñòíàÿ îïöèÿ: %s"
+
+#: option.c:7220
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Òåðìèíàëüíûå êîäû ---"
+
+#: option.c:7222
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Ãëîáàëüíûå çíà÷åíèÿ îïöèé ---"
+
+#: option.c:7224
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Ìåñòíûå çíà÷åíèÿ îïöèé ---"
+
+#: option.c:7226
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Îïöèè ---"
+
+#: option.c:7932
+msgid "E356: get_varp ERROR"
+msgstr "E356: ÎØÈÁÊÀ get_varp"
+
+#: option.c:8903
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': Íåò ñîîòâåòñòâóþùåãî ñèìâîëà äëÿ %s"
+
+#: option.c:8937
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': Ëèøíèå ñèìâîëû ïîñëå òî÷êè ñ çàïÿòîé: %s"
+
+#: os_amiga.c:280
+msgid "cannot open "
+msgstr "íåâîçìîæíî îòêðûòü "
+
+#: os_amiga.c:314
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Íåâîçìîæíî îòêðûòü îêíî!\n"
+
+#: os_amiga.c:338
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Íåîáõîäèìà Amigados âåðñèè 2.04 èëè áîëåå ïîçäíåé\n"
+
+#: os_amiga.c:344
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Íåîáõîäèìà %s âåðñèè %ld\n"
+
+#: os_amiga.c:416
+msgid "Cannot open NIL:\n"
+msgstr "Íåâîçìîæíî îòêðûòü NIL:\n"
+
+#: os_amiga.c:427
+msgid "Cannot create "
+msgstr "Íåâîçìîæíî ñîçäàòü "
+
+#: os_amiga.c:905
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Ïðåêðàùåíèå ðàáîòû Vim ñ êîäîì %d\n"
+
+#: os_amiga.c:937
+msgid "cannot change console mode ?!\n"
+msgstr "íåâîçìîæíî ñìåíèòü ðåæèì êîíñîëè?!\n"
+
+#: os_amiga.c:1003
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: íå â êîíñîëè??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1152
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Íåâîçìîæíî âûïîëíèòü îáîëî÷êó ñ àðãóìåíòîì -f"
+
+#: os_amiga.c:1193 os_amiga.c:1283
+msgid "Cannot execute "
+msgstr "Íåâîçìîæíî âûïîëíèòü "
+
+#: os_amiga.c:1196 os_amiga.c:1293
+msgid "shell "
+msgstr "îáîëî÷êà "
+
+#: os_amiga.c:1216 os_amiga.c:1318
+msgid " returned\n"
+msgstr " çàâåðøèëà ðàáîòó\n"
+
+#: os_amiga.c:1459
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ñëèøêîì ìàëàÿ âåëè÷èíà ANCHOR_BUF_SIZE."
+
+#: os_amiga.c:1463
+msgid "I/O ERROR"
+msgstr "ÎØÈÁÊÀ ÂÂÎÄÀ/ÂÛÂÎÄÀ"
+
+#: os_mswin.c:539
+msgid "...(truncated)"
+msgstr "...(îáðåçàíî)"
+
+#: os_mswin.c:641
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "Çíà÷åíèå îïöèè 'columns' íå ðàâíî 80, âíåøíèå ïðîãðàììû íå âûïîëíÿþòñÿ"
+
+#: os_mswin.c:1973
+msgid "E237: Printer selection failed"
+msgstr "E327: Íåóäà÷íîå çàâåðøåíèå âûáîðà ïðèíòåðà"
+
+#: os_mswin.c:2013
+#, c-format
+msgid "to %s on %s"
+msgstr "â %s íà %s"
+
+#: os_mswin.c:2028
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: Íåèçâåñòíûé øðèôò ïðèíòåðà: %s"
+
+#: os_mswin.c:2077 os_mswin.c:2087
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Îøèáêà ïå÷àòè: %s"
+
+#: os_mswin.c:2088
+msgid "Unknown"
+msgstr "Íåèçâåñòíî"
+
+#: os_mswin.c:2115
+#, c-format
+msgid "Printing '%s'"
+msgstr "Ïå÷àòü '%s'"
+
+#: os_mswin.c:3204
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Íåäîïóñòèìîå èìÿ êîäèðîâêè \"%s\" â èìåíè øðèôòà \"%s\""
+
+#: os_mswin.c:3212
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Íåäîïóñòèìûé ñèìâîë '%c' â èìåíè øðèôòà \"%s\""
+
+#: os_riscos.c:1259
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Íåäîïóñòèìîå çíà÷åíèå îïöèè 'osfiletype' -- èñïîëüçóåòñÿ Text"
+
+#: os_unix.c:927
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: Äâîéíîé ñèãíàë, çàâåðøåíèå ðàáîòû\n"
+
+#: os_unix.c:933
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Ïîëó÷åí óáèéñòâåííûé ñèãíàë %s\n"
+
+#: os_unix.c:936
+#, c-format
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Ïîëó÷åí óáèéñòâåííûé ñèãíàë\n"
+
+#: os_unix.c:1199
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Îòêðûòèå äèñïëåÿ X çàíÿëî %ld msec"
+
+#: os_unix.c:1226
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: Îøèáêà X\n"
+
+#: os_unix.c:1334
+msgid "Testing the X display failed"
+msgstr "Ïðîâåðêà äèñïëåÿ X çàâåðøåíà íåóäà÷íî"
+
+#: os_unix.c:1473
+msgid "Opening the X display timed out"
+msgstr "Îòêðûòèå äèñïëåÿ X íå âûïîëíåíî â îòâåä¸ííîå âðåìÿ"
+
+#: os_unix.c:3227 os_unix.c:3907
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"Íåâîçìîæíî çàïóñòèòü îáîëî÷êó "
+
+#: os_unix.c:3275
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Íåâîçìîæíî çàïóñòèòü îáîëî÷êó sh\n"
+
+#: os_unix.c:3279 os_unix.c:3913
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"Îáîëî÷êà çàâåðøèëà ðàáîòó "
+
+#: os_unix.c:3414
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Íåâîçìîæíî ñîçäàòü òðóáû\n"
+
+#: os_unix.c:3429
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"Íåâîçìîæíî âûïîëíèòü fork()\n"
+
+#: os_unix.c:3920
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Âûïîëíåíèå êîìàíäû ïðåðâàíî\n"
+
+#: os_unix.c:4184 os_unix.c:4309 os_unix.c:5975
+msgid "XSMP lost ICE connection"
+msgstr "XSMP óòåðÿíî ñîåäèíåíèå ICE"
+
+#: os_unix.c:5558
+msgid "Opening the X display failed"
+msgstr "Íåóäà÷íîå îòêðûòèå äèñïëåÿ X"
+
+#: os_unix.c:5880
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP îáðàáàòûâàåò çàïðîñ ñàìîñîõðàíåíèÿ"
+
+#: os_unix.c:5999
+msgid "XSMP opening connection"
+msgstr "XSMP îòêðûâàåò ñîåäèíåíèå"
+
+#: os_unix.c:6018
+msgid "XSMP ICE connection watch failed"
+msgstr "XSMP ïîòåðÿíî ñëåæåíèå çà ñîåäèíåíèåì ICE"
+
+#: os_unix.c:6038
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP íåóäà÷íî âûïîëíåíî SmcOpenConnection: %s"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "Â ñòðîêå"
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "Íåâîçìîæíî âûäåëèòü ïàìÿòü äëÿ êîìàíäíîé ñòðîêè."
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "Îøèáêà VIM"
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "Íåâîçìîæíî çàãðóçèòü vim32.dll!"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Íåâîçìîæíî èñïðàâèòü óêàçàòåëè ôóíêöèé äëÿ DLL!"
+
+#: os_win16.c:342 os_win32.c:3216
+#, c-format
+msgid "shell returned %d"
+msgstr "çàâåðøåíèå ðàáîòû îáîëî÷êè ñ êîäîì %d"
+
+#: os_win32.c:2674
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Ïåðåõâà÷åíî ñîáûòèå %s\n"
+
+#: os_win32.c:2676
+msgid "close"
+msgstr "çàêðûòèå"
+
+#: os_win32.c:2678
+msgid "logoff"
+msgstr "îòêëþ÷åíèå"
+
+#: os_win32.c:2679
+msgid "shutdown"
+msgstr "çàâåðøåíèå"
+
+#: os_win32.c:3169
+msgid "E371: Command not found"
+msgstr "E371: Êîìàíäà íå íàéäåíà"
+
+#: os_win32.c:3182
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE íå íàéäåí â ïóòè, çàäàííîì â $PATH.\n"
+"Âíåøíèå êîìàíäû íå áóäóò îñòàíàâëèâàòüñÿ ïîñëå âûïîëíåíèÿ.\n"
+"Äîïîëíèòåëüíàÿ èíôîðìàöèÿ â :help win32-vimrun"
+
+#: os_win32.c:3185
+msgid "Vim Warning"
+msgstr "Ïðåäóïðåæäåíèå Vim"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Â ñòðîêå ôîðìàòà ñëèøêîì ìíîãî %%%c"
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: Íåîæèäàííûé ýëåìåíò %%%c â ñòðîêå ôîðìàòà"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: Â ñòðîêå ôîðìàòà ïðîïóùåíà ]"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: %%%c íå ïîääåðæèâàåòñÿ â ñòðîêå ôîðìàòà"
+
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: Íåäîïóñòèìûé %%%c â ïðèñòàâêå â ñòðîêå ôîðìàòà"
+
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: Íåäîïóñòèìûé %%%c â ñòðîêå ôîðìàòà"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378:  çíà÷åíèè îïöèè 'errorformat' îòñóòñòâóåò øàáëîí"
+
+#: quickfix.c:501
+msgid "E379: Missing or empty directory name"
+msgstr "E379: èìÿ êàòàëîãà íå çàäàíî èëè ðàâíî ïóñòîé ñòðîêå"
+
+#: quickfix.c:990
+msgid "E553: No more items"
+msgstr "E553: Áîëüøå íåò ýëåìåíòîâ"
+
+#: quickfix.c:1229
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d èç %d)%s%s: "
+
+#: quickfix.c:1231
+msgid " (line deleted)"
+msgstr " (ñòðîêà óäàëåíà)"
+
+#: quickfix.c:1444
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Âíèçó ñòåêà áûñòðûõ èñïðàâëåíèé"
+
+#: quickfix.c:1453
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Íàâåðõó ñòåêà áûñòðûõ èñïðàâëåíèé"
+
+#: quickfix.c:1465
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "ñïèñîê îøèáîê %d èç %d; %d îøèáîê"
+
+#: quickfix.c:1943
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr ""
+"E382: Çàïèñü íåâîçìîæíà, çíà÷åíèå îïöèè 'buftype' íå ÿâëÿåòñÿ ïóñòîé ñòðîêîé"
+
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: íåäîïóñòèìûé ýëåìåíò â %s%%[]"
+
+#: regexp.c:838
+msgid "E339: Pattern too long"
+msgstr "E339: Ñëèøêîì äëèííûé øàáëîí"
+
+#: regexp.c:1009
+msgid "E50: Too many \\z("
+msgstr "E50: Ñëèøêîì ìíîãî \\z("
+
+#: regexp.c:1020
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: Ñëèøêîì ìíîãî %s("
+
+#: regexp.c:1077
+msgid "E52: Unmatched \\z("
+msgstr "E52: Íåò ïàðû äëÿ \\z("
+
+#: regexp.c:1081
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: Íåò ïàðû äëÿ %s%%("
+
+#: regexp.c:1083
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: Íåò ïàðû äëÿ %s("
+
+#: regexp.c:1088
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: Íåò ïàðû äëÿ %s)"
+
+#: regexp.c:1258
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: âîçìîæíî ïóñòîé îïåðàíä %s*"
+
+#: regexp.c:1261
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: âîçìîæíî ïóñòîé îïåðàíä %s+"
+
+#: regexp.c:1316
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: íåäîïóñòèìûé ñèìâîë ïîñëå %s@"
+
+#: regexp.c:1344
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: âîçìîæíî ïóñòîé îïåðàíä %s{"
+
+#: regexp.c:1354
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: Ñëèøêîì ìíîãî ñëîæíûõ êîíñòðóêöèé %s{...}"
+
+#: regexp.c:1370
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: Âëîæåííûå %s*"
+
+#: regexp.c:1373
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: Âëîæåííûå %s%c"
+
+#: regexp.c:1491
+msgid "E63: invalid use of \\_"
+msgstr "E63: íåäîïóñòèìîå èñïîëüçîâàíèå \\_"
+
+#: regexp.c:1536
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c íè çà ÷åì íå ñëåäóåò"
+
+#: regexp.c:1592
+msgid "E65: Illegal back reference"
+msgstr "E65: Íåäîïóñòèìàÿ îáðàòíàÿ ññûëêà"
+
+#: regexp.c:1605
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z( íå ìîæåò áûòü èñïîëüçîâàíî çäåñü"
+
+#: regexp.c:1624
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 è ò.ï. íå ìîãóò áûòü èñïîëüçîâàíû çäåñü"
+
+#: regexp.c:1635
+msgid "E68: Invalid character after \\z"
+msgstr "E68: Íåäîïóñòèìûé ñèìâîë ïîñëå \\z"
+
+#: regexp.c:1684
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: Ïðîïóùåíà ] ïîñëå %s%%["
+
+#: regexp.c:1700
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: Ïóñòîå %s%%[]"
+
+#: regexp.c:1760
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: Íåäîïóñòèìûé ñèìâîë ïîñëå %s%%"
+
+#: regexp.c:2557
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: Ñèíòàêñè÷åñêàÿ îøèáêà â %s{...}"
+
+#: regexp.c:2863 regexp.c:3016
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr ""
+"E361: Ïðåäîòâðàùåíî àâàðèéíîå çàâåðøåíèå: ñëèøêîì ñëîæíîå ðåãóëÿðíîå "
+"âûðàæåíèå?"
+
+#: regexp.c:3004 regexp.c:3013
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: ïðèìåíåíèå øàáëîíà ïðèâåëî ê îøèáêå âûõîäà çà ïðåäåëû ñòåêà"
+
+#: regexp.c:3258
+msgid "External submatches:\n"
+msgstr "Âíåøíèå ïîäñîîòâåòñòâèÿ:\n"
+
+#: screen.c:2184
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld ñòðîê â ñêëàäêå"
+
+#: screen.c:7996
+msgid " VREPLACE"
+msgstr " ÂÈÐÒÓÀËÜÍÀß ÇÀÌÅÍÀ"
+
+#: screen.c:8000
+msgid " REPLACE"
+msgstr " ÇÀÌÅÍÀ"
+
+#: screen.c:8005
+msgid " REVERSE"
+msgstr " ÎÁÐÀÒÍÀß"
+
+#: screen.c:8007
+msgid " INSERT"
+msgstr " ÂÑÒÀÂÊÀ"
+
+#: screen.c:8010
+msgid " (insert)"
+msgstr " (âñòàâêà)"
+
+#: screen.c:8012
+msgid " (replace)"
+msgstr " (çàìåíà)"
+
+#: screen.c:8014
+msgid " (vreplace)"
+msgstr " (âèðòóàëüíàÿ çàìåíà)"
+
+#: screen.c:8017
+msgid " Hebrew"
+msgstr " Èâðèò"
+
+#: screen.c:8028
+msgid " Arabic"
+msgstr " Àðàáñêèé"
+
+#: screen.c:8031
+msgid " (lang)"
+msgstr " (ÿçûê)"
+
+#: screen.c:8035
+msgid " (paste)"
+msgstr " (âêëåéêà)"
+
+#: screen.c:8048
+msgid " VISUAL"
+msgstr " ÂÈÇÓÀËÜÍÛÉ ÐÅÆÈÌ"
+
+#: screen.c:8049
+msgid " VISUAL LINE"
+msgstr " ÂÈÇÓÀËÜÍÀß ÑÒÐÎÊÀ"
+
+#: screen.c:8050
+msgid " VISUAL BLOCK"
+msgstr " ÂÈÇÓÀËÜÍÛÉ ÁËÎÊ"
+
+#: screen.c:8051
+msgid " SELECT"
+msgstr " ÂÛÄÅËÅÍÈÅ"
+
+#: screen.c:8052
+msgid " SELECT LINE"
+msgstr " ÂÛÄÅËÅÍÈÅ ÑÒÐÎÊÈ"
+
+#: screen.c:8053
+msgid " SELECT BLOCK"
+msgstr " ÂÛÄÅËÅÍÈÅ ÁËÎÊÀ"
+
+#: screen.c:8068 screen.c:8131
+msgid "recording"
+msgstr "çàïèñü"
+
+#: search.c:37
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "ïîèñê áóäåò ïðîäîëæåí ñ ÊÎÍÖÀ äîêóìåíòà"
+
+#: search.c:38
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "ïîèñê áóäåò ïðîäîëæåí ñ ÍÀ×ÀËÀ äîêóìåíòà"
+
+#: search.c:526
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Íåïðàâèëüíàÿ ñòðîêà ïîèñêà: %s"
+
+#: search.c:853
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: ïîèñê çàêîí÷åí â ÍÀ×ÀËÅ äîêóìåíòà; %s íå íàéäåíî"
+
+#: search.c:856
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: ïîèñê çàêîí÷åí â ÊÎÍÖÅ äîêóìåíòà; %s íå íàéäåíî"
+
+#: search.c:1249
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: Ïîñëå ';' îæèäàåòñÿ ââîä '?' èëè '/'"
+
+#: search.c:3759
+msgid " (includes previously listed match)"
+msgstr " (âêëþ÷àåò ðàííåå ïîêàçàííûå ñîîòâåòñòâèÿ)"
+
+#. cursor at status line
+#: search.c:3779
+msgid "--- Included files "
+msgstr "--- Âêëþ÷¸ííûå ôàéëû "
+
+#: search.c:3781
+msgid "not found "
+msgstr "íå íàéäåíî "
+
+#: search.c:3782
+msgid "in path ---\n"
+msgstr "ïî ïóòè ---\n"
+
+#: search.c:3839
+msgid " (Already listed)"
+msgstr " (Óæå ïîêàçàíî)"
+
+#: search.c:3841
+msgid " NOT FOUND"
+msgstr " ÍÅ ÍÀÉÄÅÍÎ"
+
+#: search.c:3893
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Ïðîñìîòð âêëþ÷¸ííûõ ôàéëîâ: %s"
+
+#: search.c:4111
+msgid "E387: Match is on current line"
+msgstr "E387: Ñîîòâåòñòâèå â òåêóùåé ñòðîêå"
+
+#: search.c:4254
+msgid "All included files were found"
+msgstr "Íàéäåíû âñå âêëþ÷¸ííûå ôàéëû"
+
+#: search.c:4256
+msgid "No included files"
+msgstr "Âêëþ÷¸ííûõ ôàéëîâ íåò"
+
+#: search.c:4272
+msgid "E388: Couldn't find definition"
+msgstr "E388: Îïðåäåëåíèå íå íàéäåíî"
+
+#: search.c:4274
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Øàáëîí íå íàéäåí"
+
+#: syntax.c:3050
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: Íåäîïóñòèìûé àðãóìåíò: %s"
+
+#: syntax.c:3230
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: Ñèíòàêñè÷åñêèé êëàñòåð %s íå íàéäåí"
+
+#: syntax.c:3394
+msgid "No Syntax items defined for this buffer"
+msgstr "Ñèíòàêñè÷åñêèå ýëåìåíòû äëÿ äàííîãî áóôåðà íå îïðåäåëåíû"
+
+#: syntax.c:3402
+msgid "syncing on C-style comments"
+msgstr "Ñèíõðîíèçàöèÿ ïî êîììåíòàðèÿì â ñòèëå ÿçûêà C"
+
+#: syntax.c:3410
+msgid "no syncing"
+msgstr "áåç ñèíõðîíèçàöèè"
+
+#: syntax.c:3413
+msgid "syncing starts "
+msgstr "ñèíõðîíèçàöèÿ íà÷àòà "
+
+#: syntax.c:3415 syntax.c:3490
+msgid " lines before top line"
+msgstr " ñòðîê ïåðåä âåðõíåé ñòðîêîé"
+
+#: syntax.c:3420
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Ýëåìåíòû ñèíõðîíèçàöèè ñèíòàêñèñà ---"
+
+#: syntax.c:3425
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"ñèíõðîíèçàöèÿ ïî ýëåìåíòàì"
+
+#: syntax.c:3431
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Ñèíòàêñè÷åñêèå ýëåìåíòû ---"
+
+#: syntax.c:3454
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: Ñèíòàêñè÷åñêèé êëàñòåð %s íå íàéäåí"
+
+#: syntax.c:3480
+msgid "minimal "
+msgstr "ìèíèìóì "
+
+#: syntax.c:3487
+msgid "maximal "
+msgstr "ìàêñèìóì "
+
+#: syntax.c:3499
+msgid "; match "
+msgstr "; ñîîòâåòñòâèå "
+
+#: syntax.c:3501
+msgid " line breaks"
+msgstr " ïåðåíîñîâ ñòðîê"
+
+#: syntax.c:4135
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: çäåñü íåëüçÿ èñïîëüçîâàòü group[t]here"
+
+#: syntax.c:4159
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: Ýëåìåíò îáëàñòè äëÿ %s íå íàéäåí"
+
+#: syntax.c:4187
+msgid "E395: contains argument not accepted here"
+msgstr "E395: çäåñü íåëüçÿ èñïîëüçîâàòü àðãóìåíò contains"
+
+#: syntax.c:4198
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: çäåñü íåëüçÿ èñïîëüçîâàòü àðãóìåíò containedin"
+
+#: syntax.c:4276
+msgid "E397: Filename required"
+msgstr "E397: Òðåáóåòñÿ óêàçàòü èìÿ ôàéëà"
+
+#: syntax.c:4614
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Ïðîïóùåíî '=': %s"
+
+#: syntax.c:4772
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Íå õâàòàåò àðãóìåíòîâ: ñèíòàêñè÷åñêèé ðåãèîí %s"
+
+#: syntax.c:5103
+msgid "E400: No cluster specified"
+msgstr "E400: Êëàñòåð íå óêàçàí"
+
+#: syntax.c:5140
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Íå íàéäåí ðàçäåëèòåëü øàáëîíîâ: %s"
+
+#: syntax.c:5215
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Ìóñîð ïîñëå øàáëîíà: %s"
+
+#: syntax.c:5305
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr ""
+"E403: ñèíõðîíèçàöèÿ ñèíòàêñèñà: øàáëîí ïðîäîëæåíèé ñòðîêè óêàçàí äâàæäû"
+
+#: syntax.c:5362
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Íåäîïóñòèìûå àðãóìåíòû: %s"
+
+#: syntax.c:5412
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Ïðîïóùåí çíàê ðàâåíñòâà: %s"
+
+#: syntax.c:5418
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Ïóñòîé àðãóìåíò: %s"
+
+#: syntax.c:5445
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s íå äîïóñêàåòñÿ â ýòîì ìåñòå"
+
+#: syntax.c:5452
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s äîëæíî áûòü ïåðâûì â ñïèñêå contains"
+
+#: syntax.c:5522
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Íåèçâåñòíàÿ ãðóïïà: %s"
+
+#: syntax.c:5755
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Íåïðàâèëüíàÿ ïîäêîìàíäà :syntax: %s"
+
+#: syntax.c:6136
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: ãðóïïà ïîäñâåòêè ñèíòàêñèñà %s íå íàéäåíà"
+
+#: syntax.c:6160
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Íå õâàòàåò àðãóìåíòîâ: \":highlight link %s\""
+
+#: syntax.c:6167
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: Ñëèøêîì ìíîãî àðãóìåíòîâ: \":highlight link %s\""
+
+#: syntax.c:6187
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: ó ãðóïïû åñòü ñîáñòâåííûå íàñòðîéêè, ññûëêà èãíîðèðóåòñÿ"
+
+#: syntax.c:6316
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: íåîæèäàííûé çíàê ðàâåíñòâà: %s"
+
+#: syntax.c:6352
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: ïðîïóùåí çíàê ðàâåíñòâà: %s"
+
+#: syntax.c:6380
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: ïðîïóùåí àðãóìåíò: %s"
+
+#: syntax.c:6417
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: Íåäîïóñòèìîå çíà÷åíèå: %s"
+
+#: syntax.c:6536
+msgid "E419: FG color unknown"
+msgstr "E419: Íåèçâåñòíûé öâåò òåêñòà"
+
+#: syntax.c:6547
+msgid "E420: BG color unknown"
+msgstr "E420: Íåèçâåñòíûé öâåò ôîíà"
+
+#: syntax.c:6608
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Èìÿ èëè íîìåð öâåòà íå èçâåñòíî: %s"
+
+#: syntax.c:6814
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: ñëèøêîì äëèííûé êîä òåðìèíàëà: %s"
+
+#: syntax.c:6861
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: Íåäîïóñòèìûé àðãóìåíò: %s"
+
+#: syntax.c:7390
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: Èñïîëüçóåòñÿ ñëèøêîì ìíîãî ðàçíûõ àòðèáóòîâ ïîäñâåòêè ñèíòàêñèñà"
+
+#: syntax.c:7911
+msgid "E669: Unprintable character in group name"
+msgstr "E669: Íåïå÷àòíûé ñèìâîë â èìåíè ãðóïïû"
+
+#. This is an error, but since there previously was no check only
+#. * give a warning.
+#: syntax.c:7918
+msgid "W18: Invalid character in group name"
+msgstr "W18: Íåäîïóñòèìûé ñèìâîë â èìåíè ãðóïïû"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: âíèçó ñòåêà ìåòîê"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: íàâåðõó ñòåêà ìåòîê"
+
+#: tag.c:412
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Íåâîçìîæíî ïåðåéòè â ïîçèöèþ äî ïåðâîé ñîâïàäàþùåé ìåòêè"
+
+#: tag.c:550
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: Ìåòêà íå íàéäåíà: %s"
+
+#: tag.c:583
+msgid " # pri kind tag"
+msgstr " # ïðè òèï ìåòêà"
+
+#: tag.c:586
+msgid "file\n"
+msgstr "ôàéë\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:744
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Âûáåðèòå íóæíûé íîìåð (<CR> äëÿ îòêàçà):"
+
+#: tag.c:784
+msgid "E427: There is only one matching tag"
+msgstr "E427: Åñòü òîëüêî îäíà ñîâïàäàþùàÿ ìåòêà"
+
+#: tag.c:786
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Íåâîçìîæíî ïåðåéòè â ïîçèöèþ çà ïîñëåäíåé ñîâïàäàþùåé ìåòêîé"
+
+#: tag.c:810
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Ôàéë \"%s\" íå ñóùåñòâóåò"
+
+#. Give an indication of the number of matching tags
+#: tag.c:823
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "ìåòêà %d èç %d%s"
+
+#: tag.c:826
+msgid " or more"
+msgstr " è áîëåå"
+
+#: tag.c:828
+msgid " Using tag with different case!"
+msgstr " Èñïîëüçóåòñÿ ìåòêà ñ ñèìâîëàìè â äðóãîì ðåãèñòðå!"
+
+#: tag.c:872
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Ôàéë \"%s\" íå ñóùåñòâóåò"
+
+#. Highlight title
+#: tag.c:941
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # Ê ìåòêå ÎÒ ñòð. â ôàéëå/òåêñòå"
+
+#: tag.c:1363
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Ïîèñê â ôàéëå ìåòîê %s"
+
+#: tag.c:1550
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Ïóòü ê ôàéëó ìåòîê %s îáðåçàí\n"
+
+#: tag.c:2203
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Îøèáêà ôîðìàòà â ôàéëå ìåòîê \"%s\""
+
+#: tag.c:2207
+#, c-format
+msgid "Before byte %ld"
+msgstr "Ïåðåä áàéòîì %ld"
+
+#: tag.c:2240
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Ôàéë ìåòîê íå îòñîðòèðîâàí: %s"
+
+#. never opened any tags file
+#: tag.c:2280
+msgid "E433: No tags file"
+msgstr "E433: Ôàéë ìåòîê íå îáíàðóæåí"
+
+#: tag.c:3016
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Íå íàéäåí øàáëîí ìåòêè"
+
+#: tag.c:3027
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Ìåòêà íå íàéäåíà, ïûòàåìñÿ óãàäàòü!"
+
+#: term.c:1759
+msgid "' not known. Available builtin terminals are:"
+msgstr "' íå èçâåñòåí. Äîñòóïíû âñòðîåííûå òåðìèíàëû:"
+
+#: term.c:1783
+msgid "defaulting to '"
+msgstr "ïî óìîë÷àíèþ '"
+
+#: term.c:2141
+msgid "E557: Cannot open termcap file"
+msgstr "E557: Íåâîçìîæíî îòêðûòü ôàéë termcap"
+
+#: term.c:2145
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: Â terminfo íåò çàïèñè îá ýòîì òåðìèíàëå"
+
+#: term.c:2147
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: Â termcap íåò çàïèñè îá ýòîì òåðìèíàëå"
+
+#: term.c:2306
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Â termcap íåò çàïèñè \"%s\""
+
+#: term.c:2780
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: òðåáóåòñÿ ñïîñîáíîñòü òåðìèíàëà \"cm\""
+
+#. Highlight title
+#: term.c:4990
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Êíîïêè òåðìèíàëà ---"
+
+#: ui.c:258
+msgid "new shell started\n"
+msgstr "çàïóñê íîâîé îáîëî÷êè\n"
+
+#: ui.c:1841
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: Îøèáêà ÷òåíèÿ ââîäà, âûõîä...\n"
+
+#. must display the prompt
+#: undo.c:405
+msgid "No undo possible; continue anyway"
+msgstr "Îòìåíà íåâîçìîæíà; ïðîäîëæàòü âûïîëíåíèå"
+
+#: undo.c:561
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: íåïðàâèëüíûå íîìåðà ñòðîê"
+
+#: undo.c:757
+msgid "1 change"
+msgstr "Åäèíñòâåííîå èçìåíåíèå"
+
+#: undo.c:759
+#, c-format
+msgid "%ld changes"
+msgstr "Èçìåíåíèé: %ld"
+
+#: undo.c:812
+msgid "E439: undo list corrupt"
+msgstr "E439: Ïîâðåæä¸í ñïèñîê îòìåíû"
+
+#: undo.c:844
+msgid "E440: undo line missing"
+msgstr "E440: ïîòåðÿíà ñòðîêà îòìåíû"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:721
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"Âåðñèÿ ñ ãðàôè÷åñêèì èíòåðôåéñîì äëÿ MS-Windows 16/32 áèò"
+
+#: version.c:723
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"Âåðñèÿ ñ ãðàôè÷åñêèì èíòåðôåéñîì äëÿ MS-Windows 32 áèò"
+
+#: version.c:726
+msgid " in Win32s mode"
+msgstr " â ðåæèìå Win32s"
+
+#: version.c:728
+msgid " with OLE support"
+msgstr " ñ ïîääåðæêîé OLE"
+
+#: version.c:731
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"Êîíñîëüíàÿ âåðñèÿ äëÿ MS-Windows 32 áèò"
+
+#: version.c:735
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"Âåðñèÿ äëÿ MS-Windows 16 áèò"
+
+#: version.c:739
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"Âåðñèÿ äëÿ MS-DOS 32 áèò"
+
+#: version.c:741
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"Âåðñèÿ äëÿ MS-DOS 16 áèò"
+
+#: version.c:747
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"Âåðñèÿ äëÿ MacOS X (unix)"
+
+#: version.c:749
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"Âåðñèÿ äëÿ MacOS X"
+
+#: version.c:752
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"Âåðñèÿ äëÿ MacOS"
+
+#: version.c:757
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"Âåðñèÿ äëÿ RISC OS"
+
+#: version.c:767
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Çàïëàòêè: "
+
+#: version.c:793 version.c:1161
+msgid "Modified by "
+msgstr "Ñ èçìåíåíèÿìè, âíåñ¸ííûìè "
+
+#: version.c:800
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Ñêîìïèëèðîâàí "
+
+#: version.c:803
+msgid "by "
+msgstr " "
+
+#: version.c:815
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Îãðîìíàÿ âåðñèÿ "
+
+#: version.c:818
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Áîëüøàÿ âåðñèÿ "
+
+#: version.c:821
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Îáû÷íàÿ âåðñèÿ "
+
+#: version.c:824
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Ìàëàÿ âåðñèÿ "
+
+#: version.c:826
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Âåðñèÿ \"Êðîõà\" "
+
+#: version.c:832
+msgid "without GUI."
+msgstr "áåç ãðàôè÷åñêîãî èíòåðôåéñà."
+
+#: version.c:837
+msgid "with GTK2-GNOME GUI."
+msgstr "ñ ãðàôè÷åñêèì èíòåðôåéñîì GTK2-GNOME."
+
+#: version.c:839
+msgid "with GTK-GNOME GUI."
+msgstr "ñ ãðàôè÷åñêèì èíòåðôåéñîì GTK-GNOME."
+
+#: version.c:843
+msgid "with GTK2 GUI."
+msgstr "ñ ãðàôè÷åñêèì èíòåðôåéñîì GTK2."
+
+#: version.c:845
+msgid "with GTK GUI."
+msgstr "ñ ãðàôè÷åñêèì èíòåðôåéñîì GTK."
+
+#: version.c:850
+msgid "with X11-Motif GUI."
+msgstr "ñ ãðàôè÷åñêèì èíòåðôåéñîì X11-Motif."
+
+#: version.c:854
+msgid "with X11-neXtaw GUI."
+msgstr "ñ ãðàôè÷åñêèì èíòåðôåéñîì X11-neXtaw."
+
+#: version.c:856
+msgid "with X11-Athena GUI."
+msgstr "ñ ãðàôè÷åñêèì èíòåðôåéñîì X11-Athena."
+
+#: version.c:860
+msgid "with BeOS GUI."
+msgstr "ñ ãðàôè÷åñêèì èíòåðôåéñîì BeOS."
+
+#: version.c:863
+msgid "with Photon GUI."
+msgstr "ñ ãðàôè÷åñêèì èíòåðôåéñîì Photon."
+
+#: version.c:866
+msgid "with GUI."
+msgstr "ñ ãðàôè÷åñêèì èíòåðôåéñîì."
+
+#: version.c:869
+msgid "with Carbon GUI."
+msgstr "ñ ãðàôè÷åñêèì èíòåðôåéñîì Carbon."
+
+#: version.c:872
+msgid "with Cocoa GUI."
+msgstr "ñ ãðàôè÷åñêèì èíòåðôåéñîì Cocoa."
+
+#: version.c:875
+msgid "with (classic) GUI."
+msgstr "ñ êëàññè÷åñêèì ãðàôè÷åñêèì èíòåðôåéñîì."
+
+#: version.c:886
+msgid " Features included (+) or not (-):\n"
+msgstr " Âêëþ÷¸ííûå (+) è îòêëþ÷¸ííûå (-) îñîáåííîñòè:\n"
+
+#: version.c:898
+msgid " system vimrc file: \""
+msgstr " îáùåñèñòåìíûé ôàéë vimrc: \""
+
+#: version.c:903
+msgid " user vimrc file: \""
+msgstr " ïîëüçîâàòåëüñêèé ôàéë vimrc: \""
+
+#: version.c:908
+msgid " 2nd user vimrc file: \""
+msgstr " âòîðîé ïîëüçîâàòåëüñêèé ôàéë vimrc: \""
+
+#: version.c:913
+msgid " 3rd user vimrc file: \""
+msgstr " òðåòèé ïîëüçîâàòåëüñêèé ôàéë vimrc: \""
+
+#: version.c:918
+msgid " user exrc file: \""
+msgstr " ïîëüçîâàòåëüñêèé ôàéë exrc: \""
+
+#: version.c:923
+msgid " 2nd user exrc file: \""
+msgstr " âòîðîé ïîëüçîâàòåëüñêèé ôàéë exrc: \""
+
+#: version.c:929
+msgid " system gvimrc file: \""
+msgstr " îáùåñèñòåìíûé ôàéë gvimrc: \""
+
+#: version.c:933
+msgid " user gvimrc file: \""
+msgstr " ïîëüçîâàòåëüñêèé ôàéë gvimrc: \""
+
+#: version.c:937
+msgid "2nd user gvimrc file: \""
+msgstr " âòîðîé ïîëüçîâàòåëüñêèé ôàéë gvimrc: \""
+
+#: version.c:942
+msgid "3rd user gvimrc file: \""
+msgstr " òðåòèé ïîëüçîâàòåëüñêèé ôàéë gvimrc: \""
+
+#: version.c:949
+msgid " system menu file: \""
+msgstr " îáùåñèñòåìíûé ôàéë ìåíþ: \""
+
+#: version.c:957
+msgid " fall-back for $VIM: \""
+msgstr " çíà÷åíèå $VIM ïî óìîë÷àíèþ: \""
+
+#: version.c:963
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " çíà÷åíèå $VIMRUNTIME ïî óìîë÷àíèþ: \""
+
+#: version.c:967
+msgid "Compilation: "
+msgstr "Ïàðàìåòðû êîìïèëÿöèè: "
+
+#: version.c:973
+msgid "Compiler: "
+msgstr "Êîìïèëÿòîð: "
+
+#: version.c:978
+msgid "Linking: "
+msgstr "Ñáîðêà: "
+
+#: version.c:983
+msgid " DEBUG BUILD"
+msgstr " ÎÒËÀÄÎ×ÍÀß ÑÁÎÐÊÀ"
+
+#: version.c:1022
+msgid "VIM - Vi IMproved"
+msgstr "VIM ::: Vi IMproved (Óëó÷øåííûé Vi) ::: Ðóññêàÿ âåðñèÿ"
+
+#: version.c:1024
+msgid "version "
+msgstr "âåðñèÿ "
+
+#: version.c:1025
+msgid "by Bram Moolenaar et al."
+msgstr "Áðàì Ìîîëåíààð è äðóãèå"
+
+#: version.c:1029
+msgid "Vim is open source and freely distributable"
+msgstr "Vim ýòî ñâîáîäíî ðàñïðîñòðàíÿåìàÿ ïðîãðàììà ñ îòêðûòûì êîäîì"
+
+#: version.c:1031
+msgid "Help poor children in Uganda!"
+msgstr "Áåäíûì äåòÿì â Óãàíäå íóæíà âàøà ïîìîùü!"
+
+#: version.c:1032
+msgid "type :help iccf<Enter> for information "
+msgstr "íàáåðèòå :help iccf<Enter> äëÿ äîïîëíèòåëüíîé èíôîðìàöèè"
+
+#: version.c:1034
+msgid "type :q<Enter> to exit "
+msgstr "íàáåðèòå :q<Enter> ÷òîáû âûéòè èç ïðîãðàììû "
+
+#: version.c:1035
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "íàáåðèòå :help<Enter> èëè <F1> äëÿ ïîëó÷åíèÿ ñïðàâêè "
+
+#: version.c:1036
+msgid "type :help version6<Enter> for version info"
+msgstr "íàáåðèòå :help version6<Enter> ÷òîáû óçíàòü îá ýòîé âåðñèè "
+
+#: version.c:1039
+msgid "Running in Vi compatible mode"
+msgstr "Ðàáîòà â Vi-ñîâìåñòèìîì ðåæèìå"
+
+#: version.c:1040
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "íàáåðèòå :set nocp<Enter> äëÿ ïåðåõîäà â ðåæèì Vim "
+
+#: version.c:1041
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "íàáåðèòå :help cp-default<Enter> äëÿ äîïîëíèòåëüíîé èíôîðìàöèè"
+
+#: version.c:1056
+msgid "menu Help->Orphans for information "
+msgstr "ìåíþ Ñïðàâêà->Ñèðîòû äëÿ ïîëó÷åíèÿ èíôîðìàöèè "
+
+#: version.c:1058
+msgid "Running modeless, typed text is inserted"
+msgstr "Áåçðåæèìíàÿ ðàáîòû, âñòàâêà ââåä¸ííîãî òåêñòà"
+
+#: version.c:1059
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "ìåíþ Ïðàâêà->Îáùèå Íàñòðîéêè->Ðåæèì Âñòàâêè "
+
+#: version.c:1060
+msgid " for two modes "
+msgstr " äëÿ äâóõ ðåæèìîâ "
+
+#: version.c:1064
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "ìåíþ Ïðàâêà->Îáùèå Íàñòðîéêè->Ñîâìåñòèìîñòü ñ Vi "
+
+#: version.c:1065
+msgid " for Vim defaults "
+msgstr " äëÿ ïåðåõîäà â ðåæèì Vim "
+
+#: version.c:1112
+msgid "Sponsor Vim development!"
+msgstr "Ïîìîãèòå â ðàçðàáîòêå Vim!"
+
+#: version.c:1113
+msgid "Become a registered Vim user!"
+msgstr "Ñòàíüòå çàðåãèñòðèðîâàííûì ïîëüçîâàòåëåì Vim!"
+
+#: version.c:1116
+msgid "type :help sponsor<Enter> for information "
+msgstr "íàáåðèòå :help sponsor<Enter> äëÿ ïîëó÷åíèÿ èíôîðìàöèè "
+
+#: version.c:1117
+msgid "type :help register<Enter> for information "
+msgstr "íàáåðèòå :help register<Enter> äëÿ ïîëó÷åíèÿ èíôîðìàöèè "
+
+#: version.c:1119
+msgid "menu Help->Sponsor/Register for information "
+msgstr "ìåíþ Ñïðàâêà->Ïîìîùü/Ðåãèñòðàöèÿ äëÿ ïîëó÷åíèÿ èíôîðìàöèè "
+
+#: version.c:1129
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "ÏÐÅÄÓÏÐÅÆÄÅÍÈÅ: îáíàðóæåíà Windows 95/98/ME"
+
+#: version.c:1132
+msgid "type :help windows95<Enter> for info on this"
+msgstr "íàáåðèòå :help windows95<Enter> äëÿ ïîëó÷åíèÿ èíôîðìàöèè "
+
+#: window.c:203
+msgid "E441: There is no preview window"
+msgstr "E441: Îêíî ïðåäïðîñìîòðà îòñóòñòâóåò"
+
+#: window.c:581
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: Îêíî íå ìîæåò áûòü îäíîâðåìåííî ñëåâà ââåðõó è ñïðàâà âíèçó"
+
+#: window.c:1340
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Íåâîçìîæíî ïîìåíÿòü ìåñòàìè, ïîêà äðóãîå îêíî ðàçäåëåíî"
+
+#: window.c:1836
+msgid "E444: Cannot close last window"
+msgstr "E444: Íåëüçÿ çàêðûòü ïîñëåäíåå îêíî"
+
+#: window.c:2567
+msgid "Already only one window"
+msgstr "Íà ýêðàíå âñåãî îäíî îêíî"
+
+#: window.c:2614
+msgid "E445: Other window contains changes"
+msgstr "E445:  äðóãîì îêíå åñòü íåñîõðàí¸ííûå èçìåíåíèÿ"
+
+#: window.c:4480
+msgid "E446: No file name under cursor"
+msgstr "E446: Íåò èìåíè ôàéëà â ïîçèöèè êóðñîðà"
+
+#: window.c:4599
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Ôàéë \"%s\" íå íàéäåí ïî èçâåñòíûì ïóòÿì"
+
+#: if_perl.xs:326 globals.h:1232
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: Íåâîçìîæíî çàãðóçèòü áèáëèîòåêó %s"
+
+#: if_perl.xs:554
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr ""
+"Èçâèíèòå, äàííàÿ êîìàíäà îòêëþ÷åíà: íåâîçìîæíî çàãðóçèòü áèáëèîòåêó Perl"
+
+#: if_perl.xs:607
+msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+msgstr ""
+"E299: Íå äîïóñêàåòñÿ âû÷èñëåíèå Perl â ïåñî÷íèöå áåç ìîäóëÿ áåçîïàñíîñòè"
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "Ðåäàêòèðîâàòü â &ðàçíûõ Vim-àõ"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "Ðåäàêòèðîâàòü â &îäíîì Vim"
+
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "&Ñðàâíèòü ñ ïîìîùüþ Vim"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "Ðå&äàêòèðîâàòü ñ ïîìîùüþ Vim"
+
+#. Now concatenate
+#: GvimExt/gvimext.cpp:633
+msgid "Edit with existing Vim - &"
+msgstr "Ðåäàêòèðîâàòü â çàïóùåííîì Vim - &"
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "Ðåäàêòèðîâàòü âûäåëåííûå ôàéëû ñ ïîìîùüþ Vim"
+
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "Îøèáêà ñîçäàíèÿ ïðîöåññà: ïðîâåðüòå äîñòóïíîñòü gvim â ïóòè!"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "îøèáêà gvimext.dll"
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "Ñëèøêîì äëèííûé ïóòü!"
+
+#: globals.h:1022
+msgid "--No lines in buffer--"
+msgstr "-- Íåò ñòðîê â áóôåðå --"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1185
+msgid "E470: Command aborted"
+msgstr "E470: Âûïîëíåíèå êîìàíäû ïðåðâàíî"
+
+#: globals.h:1186
+msgid "E471: Argument required"
+msgstr "E471: Òðåáóåòñÿ óêàçàòü ïàðàìåòð"
+
+#: globals.h:1187
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: Ïîñëå \\ äîëæåí èäòè ñèìâîë /, ? èëè &"
+
+#: globals.h:1189
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr ""
+"E11: Íåäîïóñòèìî â îêíå êîìàíäíîé ñòðîêè; <CR> âûïîëíåíèå, CTRL-C âûõîä"
+
+#: globals.h:1191
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Êîìàíäà íå äîïóñêàåòñÿ â exrc/vimrc â òåêóùåì êàòàëîãå èëè ïîèñêå ìåòîê"
+
+#: globals.h:1193
+msgid "E171: Missing :endif"
+msgstr "E171: Îòñóòñòâóåò êîìàíäà :endif"
+
+#: globals.h:1194
+msgid "E600: Missing :endtry"
+msgstr "E600: Îòñóòñòâóåò êîìàíäà :endtry"
+
+#: globals.h:1195
+msgid "E170: Missing :endwhile"
+msgstr "E170: Îòñóòñòâóåò êîìàíäà :endwhile"
+
+#: globals.h:1196
+msgid "E588: :endwhile without :while"
+msgstr "E588: Êîìàíäà :endwhile áåç ïàðíîé êîìàíäû :while"
+
+#: globals.h:1198
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Ôàéë ñóùåñòâóåò (äëÿ ïåðåçàïèñè äîáàâüòå !)"
+
+#: globals.h:1199
+msgid "E472: Command failed"
+msgstr "E472: Íå óäàëîñü âûïîëíèòü êîìàíäó"
+
+#: globals.h:1201
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Íåèçâåñòíûé øðèôòîâîé íàáîð: %s"
+
+#: globals.h:1205
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Íåèçâåñòíûé øðèôò: %s"
+
+#: globals.h:1208
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: Øðèôò \"%s\" íå ÿâëÿåòñÿ ìîíîøèðèííûì øðèôòîì"
+
+#: globals.h:1210
+msgid "E473: Internal error"
+msgstr "E473: Âíóòðåííÿÿ îøèáêà"
+
+#: globals.h:1211
+msgid "Interrupted"
+msgstr "Ïðåðâàíî"
+
+#: globals.h:1212
+msgid "E14: Invalid address"
+msgstr "E14: Íåäîïóñòèìûé àäðåñ"
+
+#: globals.h:1213
+msgid "E474: Invalid argument"
+msgstr "E474: Íåäîïóñòèìûé àðãóìåíò"
+
+#: globals.h:1214
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: Íåäîïóñòèìûé àðãóìåíò: %s"
+
+#: globals.h:1216
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Íåäîïóñòèìîå âûðàæåíèå: %s"
+
+#: globals.h:1218
+msgid "E16: Invalid range"
+msgstr "E16: Íåäîïóñòèìûé äèàïàçîí"
+
+#: globals.h:1219
+msgid "E476: Invalid command"
+msgstr "E476: Íåäîïóñòèìàÿ êîìàíäà"
+
+#: globals.h:1221
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" ÿâëÿåòñÿ êàòàëîãîì"
+
+#: globals.h:1224
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Ïåðåä '=' îáíàðóæåíû íåîæèäàííûå ñèìâîëû"
+
+#: globals.h:1227
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Íåóäà÷íûé âûçîâ ôóíêöèè \"%s()\" èç áèáëèîòåêè"
+
+#: globals.h:1233
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: Íå óäàëîñü çàãðóçèòü ôóíêöèþ %s èç áèáëèîòåêè"
+
+#: globals.h:1235
+msgid "E19: Mark has invalid line number"
+msgstr "E19: Îòìåòêà óêàçûâàåò íà íåïðàâèëüíûé íîìåð ñòðîêè"
+
+#: globals.h:1236
+msgid "E20: Mark not set"
+msgstr "Îòìåòêà íå îïðåäåëåíà"
+
+#: globals.h:1237
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Èçìåíåíèÿ íåâîçìîæíû, òàê êàê îòêëþ÷åíà îïöèÿ 'modifiable'"
+
+#: globals.h:1238
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Ñëèøêîì ãëóáîêî âëîæåííûå ñöåíàðèè"
+
+#: globals.h:1239
+msgid "E23: No alternate file"
+msgstr "E23: Ñîñåäíèé ôàéë íå ñóùåñòâóåò"
+
+#: globals.h:1240
+msgid "E24: No such abbreviation"
+msgstr "E24: Íåò òàêîãî ñîêðàùåíèÿ"
+
+#: globals.h:1241
+msgid "E477: No ! allowed"
+msgstr "E477: ! íå äîïóñêàåòñÿ"
+
+#: globals.h:1243
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr ""
+"E25: Âîçìîæíîñòü èñïîëüçîâàíèÿ ãðàôè÷åñêîãî èíòåðôåéñà âûêëþ÷åíà ïðè "
+"êîìïèëÿöèè"
+
+#: globals.h:1246
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: Èâðèò âûêëþ÷åí ïðè êîìïèëÿöèè\n"
+
+#: globals.h:1249
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: Ôàðñè âûêëþ÷åíî ïðè êîìïèëÿöèè\n"
+
+#: globals.h:1252
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: Àðàáñêèé âûêëþ÷åí ïðè êîìïèëÿöèè\n"
+
+#: globals.h:1255
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Ãðóïïà ïîäñâåòêè ñèíòàêñèñà %s íå ñóùåñòâóåò"
+
+#: globals.h:1257
+msgid "E29: No inserted text yet"
+msgstr "E29: Ïîêà íåò âñòàâëåííîãî òåêñòà"
+
+#: globals.h:1258
+msgid "E30: No previous command line"
+msgstr "E30: Ïðåäûäóùåé êîìàíäíîé ñòðîêè íåò"
+
+#: globals.h:1259
+msgid "E31: No such mapping"
+msgstr "E31: Òàêîé ïðèâÿçêè íå ñóùåñòâóåò"
+
+#: globals.h:1260
+msgid "E479: No match"
+msgstr "E479: Íåò ñîîòâåòñòâèÿ"
+
+#: globals.h:1261
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: Íåò ñîîòâåòñòâèÿ: %s"
+
+#: globals.h:1262
+msgid "E32: No file name"
+msgstr "E32: Íåò èìåíè ôàéëà"
+
+#: globals.h:1263
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: Íåò ïðåäûäóùåãî ðåãóëÿðíîãî âûðàæåíèÿ äëÿ çàìåíû"
+
+#: globals.h:1264
+msgid "E34: No previous command"
+msgstr "E34: Íåò ïðåäûäóùåé êîìàíäû"
+
+#: globals.h:1265
+msgid "E35: No previous regular expression"
+msgstr "E35: Íåò ïðåäûäóùåãî ðåãóëÿðíîãî âûðàæåíèÿ"
+
+#: globals.h:1266
+msgid "E481: No range allowed"
+msgstr "E481: Èñïîëüçîâàíèå äèàïàçîíà íå äîïóñêàåòñÿ"
+
+#: globals.h:1268
+msgid "E36: Not enough room"
+msgstr "E36: Íåäîñòàòî÷íî ìåñòà"
+
+#: globals.h:1271
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: ñåðâåð \"%s\" íå çàðåãèñòðèðîâàí"
+
+#: globals.h:1273
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: Íåâîçìîæíî ñîçäàòü ôàéë %s"
+
+#: globals.h:1274
+msgid "E483: Can't get temp file name"
+msgstr "E483: Íåâîçìîæíî ïîëó÷èòü èìÿ âðåìåííîãî ôàéëà"
+
+#: globals.h:1275
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: Íåâîçìîæíî îòêðûòü ôàéë %s"
+
+#: globals.h:1276
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: Íåâîçìîæíî ïðî÷èòàòü ôàéë %s"
+
+#: globals.h:1277
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: Èçìåíåíèÿ íå ñîõðàíåíû (äîáàâüòå !, ÷òîáû îáîéòè ïðîâåðêó)"
+
+#: globals.h:1278
+msgid "E38: Null argument"
+msgstr "E38: Íóëåâîé àðãóìåíò"
+
+#: globals.h:1280
+msgid "E39: Number expected"
+msgstr "E39: Òðåáóåòñÿ ÷èñëî"
+
+#: globals.h:1283
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Íå óäàëîñü îòêðûòü ôàéë îøèáîê %s"
+
+#: globals.h:1286
+msgid "E233: cannot open display"
+msgstr "E233: íåâîçìîæíî îòêðûòü äèñïëåé"
+
+#: globals.h:1288
+msgid "E41: Out of memory!"
+msgstr "E41: Íå õâàòàåò ïàìÿòè!"
+
+#: globals.h:1290
+msgid "Pattern not found"
+msgstr "Øàáëîí íå íàéäåí"
+
+#: globals.h:1292
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: Øàáëîí íå íàéäåí: %s"
+
+#: globals.h:1293
+msgid "E487: Argument must be positive"
+msgstr "E487: Ïàðàìåòð äîëæåí áûòü ïîëîæèòåëüíûì ÷èñëîì"
+
+#: globals.h:1295
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: Âîçâðàò â ïðåäûäóùèé êàòàëîã íåâîçìîæåí"
+
+#: globals.h:1299
+msgid "E42: No Errors"
+msgstr "E42: Îøèáîê íåò"
+
+#: globals.h:1301
+msgid "E43: Damaged match string"
+msgstr "E43: Ïîâðåæäåíà ñòðîêà ñîîòâåòñòâèÿ"
+
+#: globals.h:1302
+msgid "E44: Corrupted regexp program"
+msgstr "E44: Ïðîãðàììà îáðàáîòêè ðåãóëÿðíûõ âûðàæåíèé ïîâðåæäåíà"
+
+#: globals.h:1303
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr ""
+"E45: Âêëþ÷åíà îïöèÿ 'readonly' (äîáàâüòå !, ÷òîáû íå îáðàùàòü âíèìàíèÿ)"
+
+#: globals.h:1305
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Íåâîçìîæíî èçìåíèòü äîñòóïíóþ òîëüêî äëÿ ÷òåíèÿ ïåðåìåííóþ \"%s\""
+
+#: globals.h:1308
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Îøèáêà ïðè ÷òåíèè ôàéëà îøèáîê"
+
+#: globals.h:1311
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: Íå äîïóñêàåòñÿ â ïåñî÷íèöå"
+
+#: globals.h:1313
+msgid "E523: Not allowed here"
+msgstr "E523: Çäåñü íå ðàçðåøåíî"
+
+#: globals.h:1316
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Äàííûé ðåæèì ýêðàíà íå ïîääåðæèâàåòñÿ"
+
+#: globals.h:1318
+msgid "E49: Invalid scroll size"
+msgstr "E49: Íåäîïóñòèìûé ðàçìåð ïðîêðóòêè"
+
+#: globals.h:1319
+msgid "E91: 'shell' option is empty"
+msgstr "E91: Çíà÷åíèåì îïöèè 'shell' ÿâëÿåòñÿ ïóñòàÿ ñòðîêà"
+
+#: globals.h:1321
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Íåâîçìîæíî ïðî÷èòàòü äàííûå î çíà÷êàõ!"
+
+#: globals.h:1323
+msgid "E72: Close error on swap file"
+msgstr "E72: Îøèáêà çàêðûòèÿ ñâîï-ôàéëà"
+
+#: globals.h:1324
+msgid "E73: tag stack empty"
+msgstr "E73: Ñòåê ìåòîê ïóñòîé"
+
+#: globals.h:1325
+msgid "E74: Command too complex"
+msgstr "E74: Ñëèøêîì ñëîæíàÿ êîìàíäà"
+
+#: globals.h:1326
+msgid "E75: Name too long"
+msgstr "E75: Ñëèøêîì äëèííîå èìÿ"
+
+#: globals.h:1327
+msgid "E76: Too many ["
+msgstr "E76: Ñëèøêîì ìíîãî ñèìâîëîâ ["
+
+#: globals.h:1328
+msgid "E77: Too many file names"
+msgstr "E77: Ñëèøêîì ìíîãî èì¸í ôàéëîâ"
+
+#: globals.h:1329
+msgid "E488: Trailing characters"
+msgstr "E488: Ëèøíèå ñèìâîëû íà õâîñòå"
+
+#: globals.h:1330
+msgid "E78: Unknown mark"
+msgstr "E78: Íåèçâåñòíàÿ îòìåòêà"
+
+#: globals.h:1331
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Íåâîçìîæíî âûïîëíèòü ïîäñòàíîâêó ïî ìàñêå"
+
+#: globals.h:1333
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr ""
+"E591: Çíà÷åíèå îïöèè 'winheight' íå ìîæåò áûòü ìåíüøå çíà÷åíèÿ 'winminheight'"
+
+#: globals.h:1335
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr ""
+"E592: Çíà÷åíèå îïöèè 'winwidth' íå ìîæåò áûòü ìåíüøå çíà÷åíèÿ 'winminwidth'"
+
+#: globals.h:1338
+msgid "E80: Error while writing"
+msgstr "E80: Îøèáêà ïðè çàïèñè"
+
+#: globals.h:1339
+msgid "Zero count"
+msgstr "Íóëåâîå çíà÷åíèå ñ÷¸ò÷èêà"
+
+#: globals.h:1341
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: Èñïîëüçîâàíèå <SID> âíå êîíòåêñòà ñöåíàðèÿ"
+
+#: globals.h:1344
+msgid "E449: Invalid expression received"
+msgstr "E449: Ïîëó÷åíî íåäîïóñòèìîå âûðàæåíèå"
+
+#: globals.h:1347
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: Íåâîçìîæíî èçìåíèòü îõðàíÿåìóþ îáëàñòü"
+
+#~ msgid "\"\n"
+#~ msgstr "\"\n"
diff --git a/src/po/ru.po b/src/po/ru.po
new file mode 100644
index 000000000..b08bc0230
--- /dev/null
+++ b/src/po/ru.po
@@ -0,0 +1,6658 @@
+# Russian translation for Vim
+#
+# ï ÕÓÌÏ×ÉÑÈ ÉÓÐÏÌØÚÏ×ÁÎÉÑ ÞÉÔÁÊÔÅ × ÒÅÄÁËÔÏÒÅ Vim ":help uganda"
+# ï ÌÀÄÑÈ, ÄÅÌÁÀÝÉÈ Vim ÞÉÔÁÊÔÅ × ÒÅÄÁËÔÏÒÅ ":help Á×ÔÏÒÙ"
+#
+# vassily "vr" ragosin <vrr@users.sourceforge.net>, 2004
+#
+# Original translations.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim 6.3a\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2004-05-10 21:37+0400\n"
+"PO-Revision-Date: 2004-05-10 21:37+0400\n"
+"Last-Translator: vassily ragosin <vrr@users.sourceforge.net>\n"
+"Language-Team: vassily ragosin <vrr@users.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=koi8-r\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: buffer.c:102
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: îÅ×ÏÚÍÏÖÎÏ ×ÙÄÅÌÉÔØ ÐÁÍÑÔØ ÄÁÖÅ ÄÌÑ ÏÄÎÏÇÏ ÂÕÆÅÒÁ, ×ÙÈÏÄ..."
+
+#: buffer.c:105
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: îÅ×ÏÚÍÏÖÎÏ ×ÙÄÅÌÉÔØ ÐÁÍÑÔØ ÄÌÑ ÂÕÆÅÒÁ, ÉÓÐÏÌØÚÕÅÍ ÄÒÕÇÏÊ ÂÕÆÅÒ..."
+
+#: buffer.c:805
+#, c-format
+msgid "E515: No buffers were unloaded"
+msgstr "E515: îÉ ÏÄÉÎ ÂÕÆÅÒ ÎÅ ÂÙÌ ×ÙÇÒÕÖÅÎ ÉÚ ÐÁÍÑÔÉ"
+
+#: buffer.c:807
+#, c-format
+msgid "E516: No buffers were deleted"
+msgstr "E516: îÉ ÏÄÉÎ ÂÕÆÅÒ ÎÅ ÂÙÌ ÕÄÁÌ£Î"
+
+#: buffer.c:809
+#, c-format
+msgid "E517: No buffers were wiped out"
+msgstr "E517: îÉ ÏÄÉÎ ÂÕÆÅÒ ÎÅ ÂÙÌ ÏÞÉÝÅÎ"
+
+#: buffer.c:817
+msgid "1 buffer unloaded"
+msgstr "ïÄÉÎ ÂÕÆÅÒ ×ÙÇÒÕÖÅÎ ÉÚ ÐÁÍÑÔÉ"
+
+#: buffer.c:819
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "÷ÓÅÇÏ ×ÙÇÒÕÖÅÎÏ ÂÕÆÅÒÏ× ÉÚ ÐÁÍÑÔÉ: %d"
+
+#: buffer.c:824
+msgid "1 buffer deleted"
+msgstr "ïÄÉÎ ÂÕÆÅÒ ÕÄÁÌ£Î"
+
+#: buffer.c:826
+#, c-format
+msgid "%d buffers deleted"
+msgstr "÷ÓÅÇÏ ÕÄÁÌÅÎÏ ÂÕÆÅÒÏ×: %d"
+
+#: buffer.c:831
+msgid "1 buffer wiped out"
+msgstr "ïÄÉÎ ÂÕÆÅÒ ÏÞÉÝÅÎ"
+
+#: buffer.c:833
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "÷ÓÅÇÏ ÏÞÉÝÅÎÏ ÂÕÆÅÒÏ×: %d"
+
+#: buffer.c:894
+msgid "E84: No modified buffer found"
+msgstr "E84: éÚÍÅΣÎÎÙÈ ÂÕÆÅÒÏ× ÎÅ ÏÂÎÁÒÕÖÅÎÏ"
+
+#. back where we started, didn't find anything.
+#: buffer.c:933
+msgid "E85: There is no listed buffer"
+msgstr "E85: âÕÆÅÒÙ × ÓÐÉÓËÅ ÏÔÓÕÔÓÔ×ÕÀÔ"
+
+#: buffer.c:945
+#, c-format
+msgid "E86: Buffer %ld does not exist"
+msgstr "E86: âÕÆÅÒ %ld ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+
+#: buffer.c:948
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: üÔÏ ÐÏÓÌÅÄÎÉÊ ÂÕÆÅÒ"
+
+#: buffer.c:950
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: üÔÏ ÐÅÒ×ÙÊ ÂÕÆÅÒ"
+
+#: buffer.c:988
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr "E89: éÚÍÅÎÅÎÉÑ × ÂÕÆÅÒÅ %ld ÎÅ ÓÏÈÒÁÎÅÎÙ (!, ÞÔÏÂÙ ÏÂÏÊÔÉ ÐÒÏ×ÅÒËÕ)"
+
+#: buffer.c:1005
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: îÅ×ÏÚÍÏÖÎÏ ×ÙÇÒÕÚÉÔØ ÉÚ ÐÁÍÑÔÉ ÐÏÓÌÅÄÎÉÊ ÂÕÆÅÒ"
+
+#: buffer.c:1538
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÐÅÒÅÐÏÌÎÅÎÉÅ ÓÐÉÓËÁ ÉͣΠÆÁÊÌÏ×"
+
+#: buffer.c:1709
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: âÕÆÅÒ %ld ÎÅ ÎÁÊÄÅÎ"
+
+#: buffer.c:1940
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: îÅÓËÏÌØËÏ ÓÏÏÔ×ÅÔÓÔ×ÉÊ ÄÌÑ %s"
+
+#: buffer.c:1942
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: îÅÔ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÇÏ %s ÂÕÆÅÒÁ"
+
+#: buffer.c:2337
+#, c-format
+msgid "line %ld"
+msgstr "ÓÔÒÏËÁ %ld"
+
+#: buffer.c:2420
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: âÕÆÅÒ Ó ÔÁËÉÍ ÉÍÅÎÅÍ ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ"
+
+#: buffer.c:2713
+msgid " [Modified]"
+msgstr " [éÚÍÅΣÎ]"
+
+#: buffer.c:2718
+msgid "[Not edited]"
+msgstr "[îÅ ÒÅÄÁËÔÉÒÏ×ÁÌÓÑ]"
+
+#: buffer.c:2723
+msgid "[New file]"
+msgstr "[îÏ×ÙÊ ÆÁÊÌ]"
+
+#: buffer.c:2724
+msgid "[Read errors]"
+msgstr "[ïÛÉÂËÉ ÞÔÅÎÉÑ]"
+
+#: buffer.c:2726 fileio.c:2112
+msgid "[readonly]"
+msgstr "[ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ]"
+
+#: buffer.c:2747
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "ïÄÎÁ ÓÔÒÏËÁ --%d%%--"
+
+#: buffer.c:2749
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld ÓÔÒ. --%d%%--"
+
+#: buffer.c:2756
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "ÓÔÒ. %ld ÉÚ %ld --%d%%-- ËÏÌ. "
+
+#: buffer.c:2864
+msgid "[No file]"
+msgstr "[îÅÔ ÆÁÊÌÁ]"
+
+#. must be a help buffer
+#: buffer.c:2904
+msgid "help"
+msgstr "ÓÐÒÁ×ËÁ"
+
+#: buffer.c:3463 screen.c:5075
+msgid "[help]"
+msgstr "[ÓÐÒÁ×ËÁ]"
+
+#: buffer.c:3495 screen.c:5081
+msgid "[Preview]"
+msgstr "[ðÒÅÄÐÒÏÓÍÏÔÒ]"
+
+#: buffer.c:3775
+msgid "All"
+msgstr "÷ÅÓØ"
+
+#: buffer.c:3775
+msgid "Bot"
+msgstr "÷ÎÉÚÕ"
+
+#: buffer.c:3777
+msgid "Top"
+msgstr "îÁ×ÅÒÈÕ"
+
+#: buffer.c:4523
+#, c-format
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# óÐÉÓÏË ÂÕÆÅÒÏ×:\n"
+
+#: buffer.c:4556
+msgid "[Error List]"
+msgstr "[óÐÉÓÏË ÏÛÉÂÏË]"
+
+#: buffer.c:4569 memline.c:1520
+msgid "[No File]"
+msgstr "[îÅÔ ÆÁÊÌÁ]"
+
+#: buffer.c:4882
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- úÎÁÞËÉ ---"
+
+#: buffer.c:4901
+#, c-format
+msgid "Signs for %s:"
+msgstr "úÎÁÞËÉ ÄÌÑ %s:"
+
+#: buffer.c:4907
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " ÓÔÒÏËÁ=%ld id=%d ÉÍÑ=%s"
+
+#: diff.c:139
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: óÌÅÄÉÔØ ÚÁ ÏÔÌÉÞÉÑÍÉ ÍÏÖÎÏ ÎÅ ÂÏÌÅÅ ÞÅÍ × %ld ÂÕÆÅÒÁÈ"
+
+#: diff.c:713
+msgid "E97: Cannot create diffs"
+msgstr "E97: îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÆÁÊÌÙ ÏÔÌÉÞÉÊ"
+
+#: diff.c:818
+msgid "Patch file"
+msgstr "æÁÊÌ-ÚÁÐÌÁÔËÁ"
+
+#: diff.c:1069
+msgid "E98: Cannot read diff output"
+msgstr "E98: îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ×Ù×ÏÄ ËÏÍÁÎÄÙ diff"
+
+#: diff.c:1819
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: áËÔÉ×ÎÙÊ ÂÕÆÅÒ ÎÅ ÎÁÈÏÄÉÔÓÑ × ÒÅÖÉÍÅ ÏÔÌÉÞÉÊ"
+
+#: diff.c:1831
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: âÏÌØÛÅ ÎÅÔ ÂÕÆÅÒÏ× × ÒÅÖÉÍÅ ÏÔÌÉÞÉÊ"
+
+#: diff.c:1839
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: ÷ ÒÅÖÉÍÅ ÏÔÌÉÞÉÊ ÂÏÌÅÅ Ä×ÕÈ ÂÕÆÅÒÏ×, ÎÅ ÍÏÇÕ ×ÙÂÒÁÔØ"
+
+#: diff.c:1862
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: îÅ ÍÏÇÕ ÎÁÊÔÉ ÂÕÆÅÒ \"%s\""
+
+#: diff.c:1868
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: âÕÆÅÒ \"%s\" ÎÅ ÎÁÈÏÄÉÔÓÑ × ÒÅÖÉÍÅ ÏÔÌÉÞÉÊ"
+
+#: digraph.c:2199
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: üËÒÁÎÉÒÕÀÝÉÊ ÓÉÍ×ÏÌ Escape ÎÅÌØÚÑ ÉÓÐÏÌØÚÏ×ÁÔØ × ÄÉÇÒÁÆÅ"
+
+#: digraph.c:2384
+msgid "E544: Keymap file not found"
+msgstr "E544: æÁÊÌ Ó ÒÁÓËÌÁÄËÏÊ ËÌÁ×ÉÁÔÕÒÙ ÎÅ ÎÁÊÄÅÎ"
+
+#: digraph.c:2411
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: ëÏÍÁÎÄÁ :loadkeymap ÐÒÉÍÅÎÅÎÁ ×ÎÅ ÆÁÊÌÁ ÓÃÅÎÁÒÉÑ"
+
+#: edit.c:40
+msgid " Keyword completion (^N^P)"
+msgstr " á×ÔÏÄÏÐÏÌÎÅÎÉÅ ËÌÀÞÅ×ÏÇÏ ÓÌÏ×Á (^N^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E^Y^L^]^F^I^K^D^V^N^P)"
+msgstr " á×ÔÏÄÏÐÏÌÎÅÎÉÅ ^X (^E^Y^L^]^F^I^K^D^V^N^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N^P)"
+msgstr " íÅÓÔÎÏÅ Á×ÔÏÄÏÐÏÌÎÅÎÉÅ ËÌÀÞÅ×ÏÇÏ ÓÌÏ×Á (^N^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L^N^P)"
+msgstr " á×ÔÏÄÏÐÏÌÎÅÎÉÅ ÃÅÌÏÊ ÓÔÒÏËÉ (^L^N^P)"
+
+#: edit.c:46
+msgid " File name completion (^F^N^P)"
+msgstr " á×ÔÏÄÏÐÏÌÎÅÎÉÅ ÉÍÅÎÉ ÆÁÊÌÁ (^F^N^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]^N^P)"
+msgstr " á×ÔÏÄÏÐÏÌÎÅÎÉÅ ÍÅÔËÉ (^]^N^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N^P)"
+msgstr " á×ÔÏÄÏÐÏÌÎÅÎÉÅ ÛÁÂÌÏÎÁ ÐÕÔÉ (^N^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D^N^P)"
+msgstr " á×ÔÏÄÏÐÏÌÎÅÎÉÅ ÏÐÒÅÄÅÌÅÎÉÑ (^D^N^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K^N^P)"
+msgstr " á×ÔÏÄÏÐÏÌÎÅÎÉÅ ÐÏ ÓÌÏ×ÁÒÀ (^K^N^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T^N^P)"
+msgstr " á×ÔÏÄÏÐÏÌÎÅÎÉÅ ÓÉÎÏÎÉÍÏ× (^T^N^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V^N^P)"
+msgstr " á×ÔÏÄÏÐÏÌÎÅÎÉÅ ËÏÍÁÎÄÎÏÊ ÓÔÒÏËÉ (^V^N^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "ëÏÎÅà ÁÂÚÁÃÁ"
+
+#: edit.c:962
+msgid "'thesaurus' option is empty"
+msgstr "îÅ ÚÁÄÁÎÏ ÚÎÁÞÅÎÉÅ ÏÐÃÉÉ 'thesaurus'"
+
+#: edit.c:1166
+msgid "'dictionary' option is empty"
+msgstr "îÅ ÚÁÄÁÎÏ ÚÎÁÞÅÎÉÅ ÏÐÃÉÉ 'dictionary'"
+
+#: edit.c:2162
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "ðÒÏÓÍÏÔÒ ÓÌÏ×ÁÒÑ: %s"
+
+#: edit.c:2368
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (×ÓÔÁ×ËÁ) ðÒÏËÒÕÔËÁ (^E/^Y)"
+
+#: edit.c:2370
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (ÚÁÍÅÎÁ) ðÒÏËÒÕÔËÁ (^E/^Y)"
+
+#: edit.c:2684
+#, c-format
+msgid "Scanning: %s"
+msgstr "ðÒÏÓÍÏÔÒ: %s"
+
+#: edit.c:2719
+#, c-format
+msgid "Scanning tags."
+msgstr "÷ÙÐÏÌÎÑÅÔÓÑ ÐÏÉÓË ÓÒÅÄÉ ÍÅÔÏË."
+
+#: edit.c:3381
+msgid " Adding"
+msgstr " äÏÂÁ×ÌÅÎÉÅ"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3430
+msgid "-- Searching..."
+msgstr "-- ðÏÉÓË..."
+
+#: edit.c:3486
+msgid "Back at original"
+msgstr "éÓÈÏÄÎÏÅ ÓÌÏ×Ï"
+
+#: edit.c:3491
+msgid "Word from other line"
+msgstr "óÌÏ×Ï ÉÚ ÄÒÕÇÏÊ ÓÔÒÏËÉ"
+
+#: edit.c:3496
+msgid "The only match"
+msgstr "åÄÉÎÓÔ×ÅÎÎÏÅ ÓÏÏÔ×ÅÔÓÔ×ÉÅ"
+
+#: edit.c:3555
+#, c-format
+msgid "match %d of %d"
+msgstr "ÓÏÏÔ×ÅÔÓÔ×ÉÅ %d ÉÚ %d"
+
+#: edit.c:3558
+#, c-format
+msgid "match %d"
+msgstr "ÓÏÏÔ×ÅÔÓÔ×ÉÅ %d"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:1024
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: îÅÉÚ×ÅÓÔÎÁÑ ÐÅÒÅÍÅÎÎÁÑ: \"%s\""
+
+#: eval.c:1320
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: ðÒÏÐÕÝÅÎÙ ÓËÏÂËÉ: %s"
+
+#: eval.c:1435 eval.c:1449
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: îÅÔ ÔÁËÏÊ ÐÅÒÅÍÅÎÎÏÊ: \"%s\""
+
+#: eval.c:1705
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: ðÒÏÐÕÝÅÎÏ ':' ÐÏÓÌÅ '?'"
+
+#: eval.c:2327
+msgid "E110: Missing ')'"
+msgstr "E110: ðÒÏÐÕÝÅÎÁ ')'"
+
+#: eval.c:2389
+msgid "E111: Missing ']'"
+msgstr "E111: ðÒÏÐÕÝÅÎÁ ']'"
+
+#: eval.c:2466
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: îÅ ÕËÁÚÁÎÏ ÉÍÑ ÏÐÃÉÉ: %s"
+
+#: eval.c:2484
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: îÅÉÚ×ÅÓÔÎÁÑ ÏÐÃÉÑ: %s"
+
+#: eval.c:2555
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: ðÒÏÐÕÝÅÎÁ ËÁ×ÙÞËÁ: %s"
+
+#: eval.c:2698
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: ðÒÏÐÕÝÅÎÁ ËÁ×ÙÞËÁ: %s"
+
+#: eval.c:3054
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: ðÁÒÁÍÅÔÒÙ ÄÌÑ ÆÕÎËÃÉÉ %s ÚÁÄÁÎÙ ÎÅ×ÅÒÎÏ"
+
+#: eval.c:3083
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: îÅÉÚ×ÅÓÔÎÁÑ ÆÕÎËÃÉÑ: %s"
+
+#: eval.c:3084
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: óÌÉÛËÏÍ ÍÎÏÇÏ ÐÁÒÁÍÅÔÒÏ× ÄÌÑ ÆÕÎËÃÉÉ %s"
+
+#: eval.c:3085
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: îÅÄÏÓÔÁÔÏÞÎÏ ÐÁÒÁÍÅÔÒÏ× ÄÌÑ ÆÕÎËÃÉÉ %s"
+
+#: eval.c:3086
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: <SID> ÉÓÐÏÌØÚÕÅÔÓÑ ×ÎÅ ÓÃÅÎÁÒÉÑ: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3687 gui.c:4382 gui_gtk.c:2059
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:4226
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld ÓÔÒÏË: "
+
+#: eval.c:5477
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&OK\n"
+"ï&ÔÍÅÎÁ"
+
+#: eval.c:5517
+msgid "called inputrestore() more often than inputsave()"
+msgstr "æÕÎËÃÉÑ inputrestore() ×ÙÚÙ×ÁÅÔÓÑ ÞÁÝÅ, ÞÅÍ ÆÕÎËÃÉÑ inputsave()"
+
+#: eval.c:5977
+msgid "E655: Too many symbolic links (cycle?)"
+msgstr "E656: óÌÉÛËÏÍ ÍÎÏÇÏ ÓÉÍ×ÏÌÉÞÅÓËÉÈ ÓÓÙÌÏË (ÃÉËÌ?)"
+
+#: eval.c:6609
+msgid "E240: No connection to Vim server"
+msgstr "E240: îÅÔ Ó×ÑÚÉ Ó ÓÅÒ×ÅÒÏÍ Vim"
+
+#: eval.c:6706
+msgid "E277: Unable to read a server reply"
+msgstr "E227: óÅÒ×ÅÒ ÎÅ ÏÔ×ÅÞÁÅÔ"
+
+#: eval.c:6734
+msgid "E258: Unable to send to client"
+msgstr "E258: îÅ ÍÏÇÕ ÏÔ×ÅÔÉÔØ ËÌÉÅÎÔÕ"
+
+#: eval.c:6782
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: îÅ ÍÏÇÕ ÏÔÐÒÁ×ÉÔØ ÓÏÏÂÝÅÎÉÅ ÄÌÑ %s"
+
+#: eval.c:6882
+msgid "(Invalid)"
+msgstr "(îÅÐÒÁ×ÉÌØÎÏ)"
+
+#: eval.c:8060
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: îÅÏÐÒÅÄÅÌÅÎÎÁÑ ÐÅÒÅÍÅÎÎÁÑ: %s"
+
+#: eval.c:8492
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E461: îÅÄÏÐÕÓÔÉÍÏÅ ÉÍÑ ÐÅÒÅÍÅÎÎÏÊ: %s"
+
+#: eval.c:8784
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: æÕÎËÃÉÑ %s ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ. äÏÂÁ×ØÔÅ !, ÞÔÏÂÙ ÚÁÍÅÎÉÔØ Å£."
+
+#: eval.c:8857
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: îÅÏÐÒÅÄÅÌÅÎÎÁÑ ÆÕÎËÃÉÑ: %s"
+
+#: eval.c:8870
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: ðÒÏÐÕÝÅÎÁ '(': %s"
+
+#: eval.c:8903
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: îÅÄÏÐÕÓÔÉÍÙÊ ÐÁÒÁÍÅÔÒ: %s"
+
+#: eval.c:8982
+msgid "E126: Missing :endfunction"
+msgstr "E126: ðÒÏÐÕÝÅÎÁ ËÏÍÁÎÄÁ :endfunction"
+
+#: eval.c:9089
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: îÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÏÐÒÅÄÅÌÉÔØ ÆÕÎËÃÉÀ %s, ÏÎÁ ÉÓÐÏÌØÚÕÅÔÓÑ"
+
+#: eval.c:9159
+msgid "E129: Function name required"
+msgstr "E129: ôÒÅÂÕÅÔÓÑ ÉÍÑ ÆÕÎËÃÉÉ"
+
+#: eval.c:9210
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: éÍÑ ÆÕÎËÃÉÉ ÄÏÌÖÎÏ ÎÁÞÉÎÁÔØÓÑ Ó ÐÒÏÐÉÓÎÏÊ ÂÕË×Ù: %s"
+
+#: eval.c:9402
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: æÕÎËÃÉÑ %s ÎÅ ÏÐÒÅÄÅÌÅÎÁ"
+
+#: eval.c:9407
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÆÕÎËÃÉÀ %s, ÏÎÁ ÉÓÐÏÌØÚÕÅÔÓÑ"
+
+#: eval.c:9455
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: çÌÕÂÉÎÁ ×ÙÚÏ×Á ÆÕÎËÃÉÉ ÂÏÌØÛÅ, ÞÅÍ ÚÎÁÞÅÎÉÅ 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:9508
+#, c-format
+msgid "calling %s"
+msgstr "×ÙÚÏ× %s"
+
+#: eval.c:9570
+#, c-format
+msgid "%s aborted"
+msgstr "%s ÐÒÅÒ×ÁÎÁ"
+
+#: eval.c:9572
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s ×ÏÚ×ÒÁÝÁÅÔ #%ld"
+
+#: eval.c:9579
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s ×ÏÚ×ÒÁÝÁÅÔ \"%s\""
+
+#. always scroll up, don't overwrite
+#: eval.c:9595 ex_cmds2.c:2365
+#, c-format
+msgid "continuing in %s"
+msgstr "ÐÒÏÄÏÌÖÅÎÉÅ × %s"
+
+#: eval.c:9621
+msgid "E133: :return not inside a function"
+msgstr "E133: ËÏÍÁÎÄÁ :return ×ÎÅ ÆÕÎËÃÉÉ"
+
+#: eval.c:9952
+#, c-format
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# ÇÌÏÂÁÌØÎÙÅ ÐÅÒÅÍÅÎÎÙÅ:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Hex %02x, Octal %03o"
+
+#: ex_cmds.c:118
+#, c-format
+msgid "> %d, Hex %04x, Octal %o"
+msgstr "> %d, Hex %04x, Octal %o"
+
+#: ex_cmds.c:119
+#, c-format
+msgid "> %d, Hex %08x, Octal %o"
+msgstr "> %d, Hex %08x, Octal %o"
+
+#: ex_cmds.c:430
+msgid "E134: Move lines into themselves"
+msgstr "E134: óÔÒÏËÉ ÐÅÒÅÍÅÝÁÀÔÓÑ ÓÁÍÉ ÎÁ ÓÅÂÑ"
+
+#: ex_cmds.c:499
+msgid "1 line moved"
+msgstr "ðÅÒÅÍÅÝÅÎÁ ÏÄÎÁ ÓÔÒÏËÁ"
+
+#: ex_cmds.c:501
+#, c-format
+msgid "%ld lines moved"
+msgstr "ðÅÒÅÍÅÝÅÎÏ ÓÔÒÏË: %ld"
+
+#: ex_cmds.c:924
+#, c-format
+msgid "%ld lines filtered"
+msgstr "ðÒÏÐÕÝÅÎÏ ÞÅÒÅÚ ÆÉÌØÔÒ ÓÔÒÏË: %ld"
+
+#: ex_cmds.c:952
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: á×ÔÏËÏÍÁÎÄÙ *Filter* ÎÅ ÄÏÌÖÎÙ ÉÚÍÅÎÑÔØ ÁËÔÉ×ÎÙÊ ÂÕÆÅÒ"
+
+#: ex_cmds.c:1037
+msgid "[No write since last change]\n"
+msgstr "[éÚÍÅÎÅÎÉÑ ÎÅ ÓÏÈÒÁÎÅÎÙ]\n"
+
+#: ex_cmds.c:1283
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s × ÓÔÒÏËÅ: "
+
+#: ex_cmds.c:1288
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr ""
+"E136: viminfo: óÌÉÛËÏÍ ÍÎÏÇÏ ÏÛÉÂÏË, ÏÓÔÁÌØÎÁÑ ÞÁÓÔØ ÆÁÊÌÁ ÂÕÄÅÔ ÐÒÏÐÕÝÅÎÁ"
+
+#: ex_cmds.c:1323
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "þÔÅÎÉÅ ÆÁÊÌÁ viminfo \"%s\"%s%s%s"
+
+#: ex_cmds.c:1324
+msgid " info"
+msgstr " ÉÎÆÏ"
+
+#: ex_cmds.c:1325
+msgid " marks"
+msgstr " ÏÔÍÅÔÏË"
+
+#: ex_cmds.c:1326
+msgid " FAILED"
+msgstr " îåõäáþîï"
+
+#: ex_cmds.c:1418
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: ðÒÁ×Á ÎÁ ÚÁÐÉÓØ ÆÁÊÌÁ viminfo ÏÔÓÕÔÓÔ×ÕÀÔ: %s"
+
+#: ex_cmds.c:1543
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: îÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ ÆÁÊÌ viminfo %s!"
+
+#: ex_cmds.c:1551
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "úÁÐÉÓØ ÆÁÊÌÁ viminfo \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1649
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# üÔÏÔ ÆÁÊÌ viminfo Á×ÔÏÍÁÔÉÞÅÓËÉ ÓÏÚÄÁÎ Vim %s.\n"
+
+#: ex_cmds.c:1651
+#, c-format
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# åÇÏ ÍÏÖÎÏ (ÏÓÔÏÒÏÖÎÏ!) ÒÅÄÁËÔÉÒÏ×ÁÔØ.\n"
+"\n"
+
+#: ex_cmds.c:1653
+#, c-format
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# úÎÁÞÅÎÉÅ ÏÐÃÉÉ 'encoding' × ÍÏÍÅÎÔ ÚÁÐÉÓÉ ÆÁÊÌÁ\n"
+
+#: ex_cmds.c:1752
+msgid "Illegal starting char"
+msgstr "îÅÄÏÐÕÓÔÉÍÙÊ ÎÁÞÁÌØÎÙÊ ÓÉÍ×ÏÌ"
+
+#: ex_cmds.c:2097 ex_cmds.c:2362 ex_cmds2.c:763
+msgid "Save As"
+msgstr "óÏÈÒÁÎÉÔØ ËÁË"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2140
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: æÁÊÌ ÚÁÇÒÕÖÅÎ × ÄÒÕÇÏÍ ÂÕÆÅÒÅ"
+
+#: ex_cmds.c:2174
+msgid "Write partial file?"
+msgstr "úÁÐÉÓÁÔØ ÆÁÊÌ ÞÁÓÔÉÞÎÏ?"
+
+#: ex_cmds.c:2181
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: äÌÑ ÚÁÐÉÓÉ ÞÁÓÔÉ ÂÕÆÅÒÁ ÉÓÐÏÌØÚÕÊÔÅ !"
+
+#: ex_cmds.c:2296
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "ðÅÒÅÐÉÓÁÔØ ÓÕÝÅÓÔ×ÕÀÝÉÊ ÆÁÊÌ \"%.*s\"?"
+
+#: ex_cmds.c:2367
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: âÕÆÅÒ %ld ÎÅ Ó×ÑÚÁÎ Ó ÉÍÅÎÅÍ ÆÁÊÌÁ"
+
+#: ex_cmds.c:2405
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: æÁÊÌ ÎÅ ÓÏÈÒÁΣÎ: ÚÁÐÉÓØ ÏÔËÌÀÞÅÎÁ ÏÐÃÉÅÊ 'write'"
+
+#: ex_cmds.c:2425
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"äÌÑ \"%.*s\" ×ËÌÀÞÅÎÁ ÏÐÃÉÑ 'readonly'.\n"
+"úÁÐÉÓÁÔØ?"
+
+#: ex_cmds.c:2597
+msgid "Edit File"
+msgstr "òÅÄÁËÔÉÒÏ×ÁÎÉÅ ÆÁÊÌÁ"
+
+#: ex_cmds.c:3205
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: á×ÔÏËÏÍÁÎÄÙ ÎÅÏÖÉÄÁÎÎÏ ÕÂÉÌÉ ÎÏ×ÙÊ ÂÕÆÅÒ %s"
+
+#: ex_cmds.c:3339
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: ðÁÒÁÍÅÔÒ ËÏÍÁÎÄÙ :z ÄÏÌÖÅÎ ÂÙÔØ ÞÉÓÌÏÍ"
+
+#: ex_cmds.c:3424
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: éÓÐÏÌØÚÏ×ÁÎÉÅ ËÏÍÁÎÄ ÏÂÏÌÏÞËÉ ÎÅ ÄÏÐÕÓËÁÅÔÓÑ × rvim."
+
+#: ex_cmds.c:3531
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: òÅÇÕÌÑÒÎÙÅ ×ÙÒÁÖÅÎÉÑ ÎÅ ÍÏÇÕÔ ÒÁÚÄÅÌÑÔØÓÑ ÂÕË×ÁÍÉ"
+
+#: ex_cmds.c:3877
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "ÚÁÍÅÎÉÔØ ÎÁ %s? (y/n/a/q/l/^E/^Y)"
+
+#: ex_cmds.c:4270
+msgid "(Interrupted) "
+msgstr "(ðÒÅÒ×ÁÎÏ)"
+
+#: ex_cmds.c:4274
+msgid "1 substitution"
+msgstr "ïÄÎÁ ÚÁÍÅÎÁ"
+
+#: ex_cmds.c:4276
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld ÚÁÍÅÎ"
+
+#: ex_cmds.c:4279
+msgid " on 1 line"
+msgstr " × ÏÄÎÏÊ ÓÔÒÏËÅ"
+
+#: ex_cmds.c:4281
+#, c-format
+msgid " on %ld lines"
+msgstr " × %ld ÓÔÒ."
+
+#: ex_cmds.c:4332
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: ëÏÍÁÎÄÁ :global ÎÅ ÍÏÖÅÔ ÂÙÔØ ÒÅËÕÒÓÉ×ÎÏÊ"
+
+#: ex_cmds.c:4367
+msgid "E148: Regular expression missing from global"
+msgstr "E148: ÷ ËÏÍÁÎÄÅ :global ÐÒÏÐÕÝÅÎÏ ÒÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅ"
+
+#: ex_cmds.c:4416
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "óÏÏÔ×ÅÔÓÔ×ÉÅ ÛÁÂÌÏÎÕ ÎÁÊÄÅÎÏ ÎÁ ËÁÖÄÏÊ ÓÔÒÏËÅ: %s"
+
+#: ex_cmds.c:4497
+#, c-format
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# ðÏÓÌÅÄÎÑÑ ÓÔÒÏËÁ ÄÌÑ ÚÁÍÅÎÙ:\n"
+"$"
+
+#: ex_cmds.c:4598
+msgid "E478: Don't panic!"
+msgstr "E478: óÐÏËÏÊÓÔ×ÉÅ, ÔÏÌØËÏ ÓÐÏËÏÊÓÔ×ÉÅ!"
+
+#: ex_cmds.c:4650
+#, c-format
+msgid "E661: Sorry, no '%s' help for %s"
+msgstr "E661: Ë ÓÏÖÁÌÅÎÉÀ, ÓÐÒÁ×ËÁ '%s' ÄÌÑ %s ÏÔÓÕÔÓÔ×ÕÅÔ"
+
+#: ex_cmds.c:4653
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: ë ÓÏÖÁÌÅÎÉÀ ÓÐÒÁ×ËÁ ÄÌÑ %s ÏÔÓÕÔÓÔ×ÕÅÔ"
+
+#: ex_cmds.c:4687
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "éÚ×ÉÎÉÔÅ, ÆÁÊÌ ÓÐÒÁ×ËÉ \"%s\" ÎÅ ÎÁÊÄÅÎ"
+
+#: ex_cmds.c:5170
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s ÎÅ Ñ×ÌÑÅÔÓÑ ËÁÔÁÌÏÇÏÍ"
+
+#: ex_cmds.c:5309
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ %s ÄÌÑ ÚÁÐÉÓÉ"
+
+#: ex_cmds.c:5345
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ %s ÄÌÑ ÞÔÅÎÉÑ"
+
+#: ex_cmds.c:5367
+#, c-format
+msgid "E670: Mix of help file encodings within a language: %s"
+msgstr "E670: æÁÊÌÙ ÓÐÒÁ×ËÉ ÉÓÐÏÌØÚÕÀÔ ÒÁÚÎÙÅ ËÏÄÉÒÏ×ËÉ ÄÌÑ ÏÄÎÏÇÏ ÑÚÙËÁ: %s"
+
+#: ex_cmds.c:5445
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: ðÏ×ÔÏÒÑÀÝÁÑÓÑ ÍÅÔËÁ \"%s\" × ÆÁÊÌÅ %s"
+
+#: ex_cmds.c:5557
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: îÅÉÚ×ÅÓÔÎÁÑ ËÏÍÁÎÄÁ ÚÎÁÞËÁ %s"
+
+#: ex_cmds.c:5577
+msgid "E156: Missing sign name"
+msgstr "E156: ðÒÏÐÕÝÅÎÏ ÉÍÑ ÚÎÁÞËÁ"
+
+#: ex_cmds.c:5623
+msgid "E612: Too many signs defined"
+msgstr "E612: ïÐÒÅÄÅÌÅÎÏ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÚÎÁÞËÏ×"
+
+#: ex_cmds.c:5691
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: îÅÐÒÁ×ÉÌØÎÙÊ ÔÅËÓÔ ÚÎÁÞËÁ: %s"
+
+#: ex_cmds.c:5722 ex_cmds.c:5913
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: îÅÉÚ×ÅÓÔÎÙÊ ÚÎÁÞÏË: %s"
+
+#: ex_cmds.c:5771
+msgid "E159: Missing sign number"
+msgstr "E159: ðÒÏÐÕÝÅÎ ÎÏÍÅÒ ÚÎÁÞËÁ"
+
+#: ex_cmds.c:5853
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: îÅÐÒÁ×ÉÌØÎÏÅ ÉÍÑ ÂÕÆÅÒÁ: %s"
+
+#: ex_cmds.c:5892
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: îÅÐÒÁ×ÉÌØÎÙÊ ID ÚÎÁÞËÁ: %ld"
+
+#: ex_cmds.c:5962
+msgid " (NOT FOUND)"
+msgstr " (îå îáêäåîï)"
+
+#: ex_cmds.c:5964
+msgid " (not supported)"
+msgstr " (ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ)"
+
+#: ex_cmds.c:6063
+msgid "[Deleted]"
+msgstr "[õÄÁÌÅÎÏ]"
+
+#: ex_cmds2.c:92
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "÷ËÌÀޣΠÒÅÖÉÍ ÏÔÌÁÄËÉ. äÌÑ ÐÒÏÄÏÌÖÅÎÉÑ ÎÁÂÅÒÉÔÅ \"cont\""
+
+#: ex_cmds2.c:96 ex_docmd.c:966
+#, c-format
+msgid "line %ld: %s"
+msgstr "ÓÔÒÏËÁ %ld: %s"
+
+#: ex_cmds2.c:98
+#, c-format
+msgid "cmd: %s"
+msgstr "ËÏÍÁÎÄÁ: %s"
+
+#: ex_cmds2.c:290
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "ôÏÞËÁ ÏÓÔÁÎÏ×ËÉ × \"%s%s\" ÓÔÒ. %ld"
+
+#: ex_cmds2.c:540
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: ôÏÞËÁ ÏÓÔÁÎÏ×ËÉ ÎÅ ÎÁÊÄÅÎÁ: %s"
+
+#: ex_cmds2.c:566
+msgid "No breakpoints defined"
+msgstr "ôÏÞËÉ ÏÓÔÁÎÏ×ËÉ ÎÅ ÏÐÒÅÄÅÌÅÎÙ"
+
+#: ex_cmds2.c:571
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s ÓÔÒ. %ld"
+
+#: ex_cmds2.c:786
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "óÏÈÒÁÎÉÔØ ÉÚÍÅÎÅÎÉÑ × \"%.*s\"?"
+
+#: ex_cmds2.c:788 ex_docmd.c:9378
+msgid "Untitled"
+msgstr "âÅÚ ÉÍÅÎÉ"
+
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: îÅÓÏÈÒÁΣÎÎÙÅ ÉÚÍÅÎÅÎÉÑ × ÂÕÆÅÒÅ \"%s\""
+
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr ""
+"ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: îÅÏÖÉÄÁÎÎÙÊ ÐÅÒÅÈÏÄ × ÄÒÕÇÏÊ ÂÕÆÅÒ (ÐÒÏ×ÅÒØÔÅ Á×ÔÏËÏÍÁÎÄÙ)"
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: äÌÑ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ ÄÏÓÔÕÐÅÎ ÔÏÌØËÏ ÏÄÉÎ ÆÁÊÌ"
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: üÔÏ ÐÅÒ×ÙÊ ÆÁÊÌ"
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: üÔÏ ÐÏÓÌÅÄÎÉÊ ÆÁÊÌ"
+
+#: ex_cmds2.c:1804
+#, c-format
+msgid "E666: compiler not supported: %s"
+msgstr "E666: ËÏÍÐÉÌÑÔÏÒ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ: %s"
+
+#: ex_cmds2.c:1897
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "ðÏÉÓË \"%s\" × \"%s\""
+
+#: ex_cmds2.c:1919
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "ðÏÉÓË \"%s\""
+
+#: ex_cmds2.c:1940
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "ÎÅ ÎÁÊÄÅÎÏ × 'runtimepath': \"%s\""
+
+#: ex_cmds2.c:1974
+msgid "Source Vim script"
+msgstr "÷ÙÐÏÌÎÉÔØ ÓÃÅÎÁÒÉÊ Vim"
+
+#: ex_cmds2.c:2164
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "îÅÌØÚÑ ÓÞÉÔÁÔØ ËÁÔÁÌÏÇ: \"%s\""
+
+#: ex_cmds2.c:2202
+#, c-format
+msgid "could not source \"%s\""
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÓÞÉÔÁÔØ \"%s\""
+
+#: ex_cmds2.c:2204
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "ÓÔÒÏËÁ %ld: ÎÅ×ÏÚÍÏÖÎÏ ÓÞÉÔÁÔØ \"%s\""
+
+#: ex_cmds2.c:2218
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "ÓÞÉÔÙ×ÁÎÉÅ ÓÃÅÎÁÒÉÑ \"%s\""
+
+#: ex_cmds2.c:2220
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "ÓÔÒÏËÁ %ld: ÓÞÉÔÙ×ÁÎÉÅ \"%s\""
+
+#: ex_cmds2.c:2363
+#, c-format
+msgid "finished sourcing %s"
+msgstr "ÓÞÉÔÙ×ÁÎÉÅ ÓÃÅÎÁÒÉÑ %s ÚÁ×ÅÒÛÅÎÏ"
+
+#: ex_cmds2.c:2707
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr ""
+"W15: ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÎÅÐÒÁ×ÉÌØÎÙÊ ÒÁÚÄÅÌÉÔÅÌØ ÓÔÒÏËÉ. ÷ÏÚÍÏÖÎÏ ÐÒÏÐÕÝÅÎÏ ^M"
+
+#: ex_cmds2.c:2756
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: ëÏÍÁÎÄÁ :scriptencoding ÉÓÐÏÌØÚÕÅÔÓÑ ×ÎÅ ÆÁÊÌÁ ÓÃÅÎÁÒÉÑ"
+
+#: ex_cmds2.c:2789
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: ëÏÍÁÎÄÁ :finish ÉÓÐÏÌØÚÕÅÔÓÑ ×ÎÅ ÆÁÊÌÁ ÓÃÅÎÁÒÉÑ"
+
+#: ex_cmds2.c:3238
+#, c-format
+msgid "Page %d"
+msgstr "óÔÒÁÎÉÃÁ %d"
+
+#: ex_cmds2.c:3394
+msgid "No text to be printed"
+msgstr "ðÅÞÁÔÁÔØ ÎÅÞÅÇÏ"
+
+#: ex_cmds2.c:3472
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "ðÅÞÁÔØ ÓÔÒ. %d (%d%%)"
+
+#: ex_cmds2.c:3484
+#, c-format
+msgid " Copy %d of %d"
+msgstr " ëÏÐÉÑ %d ÉÚ %d"
+
+#: ex_cmds2.c:3542
+#, c-format
+msgid "Printed: %s"
+msgstr "îÁÐÅÞÁÔÁÎÏ: %s"
+
+#: ex_cmds2.c:3549
+#, c-format
+msgid "Printing aborted"
+msgstr "ðÅÞÁÔØ ÐÒÅËÒÁÝÅÎÁ"
+
+#: ex_cmds2.c:3914
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: ïÛÉÂËÁ ÚÁÐÉÓÉ × ÆÁÊÌ PostScript"
+
+#: ex_cmds2.c:4189
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E624: îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ \"%s\""
+
+#: ex_cmds2.c:4199 ex_cmds2.c:4824
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ÆÁÊÌ ÒÅÓÕÒÓÏ× PostScript \"%s\""
+
+#: ex_cmds2.c:4207
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: ÆÁÊÌ \"%s\" ÎÅ Ñ×ÌÑÅÔÓÑ ÆÁÊÌÏÍ ÒÅÓÕÒÓÏ× PostScript"
+
+#: ex_cmds2.c:4222 ex_cmds2.c:4242 ex_cmds2.c:4257 ex_cmds2.c:4279
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: ÆÁÊÌ \"%s\" ÎÅ Ñ×ÌÑÅÔÓÑ ÄÏÐÕÓÔÉÍÙÍ ÆÁÊÌÏÍ ÒÅÓÕÒÓÏ× PostScript"
+
+#: ex_cmds2.c:4309
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: ÆÁÊÌ ÒÅÓÕÒÓÏ× \"%s\" ÎÅÉÚ×ÅÓÔÎÏÊ ×ÅÒÓÉÉ"
+
+#: ex_cmds2.c:4776
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ PostScript"
+
+#: ex_cmds2.c:4809
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ \"%s\""
+
+#: ex_cmds2.c:4928
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr "E456: æÁÊÌ ÒÅÓÕÒÓÏ× PostScript \"prolog.ps\" ÎÅ ÎÁÊÄÅÎ"
+
+#: ex_cmds2.c:4959
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: æÁÊÌ ÒÅÓÕÒÓÏ× PostScript \"%s.ps\" ÎÅ ÎÁÊÄÅÎ"
+
+#: ex_cmds2.c:4977
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr ""
+"E620: ðÒÅÏÂÒÁÚÏ×ÁÎÉÅ ÉÚ ÍÕÌØÔÉÂÁÊÔÎÙÈ ÓÉÍ×ÏÌÏ× × ËÏÄÉÒÏ×ËÕ \"%s\" ÎÅ×ÏÚÍÏÖÎÏ"
+
+#: ex_cmds2.c:5102
+msgid "Sending to printer..."
+msgstr "ïÔÐÒÁ×ËÁ ÎÁ ÐÅÞÁÔØ..."
+
+#: ex_cmds2.c:5106
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: îÅ ÕÄÁÌÏÓØ ×ÙÐÏÌÎÉÔØ ÐÅÞÁÔØ ÆÁÊÌÁ PostScript"
+
+#: ex_cmds2.c:5108
+msgid "Print job sent."
+msgstr "úÁÄÁÎÉÅ ÎÁ ÐÅÞÁÔØ ÏÔÐÒÁ×ÌÅÎÏ."
+
+#: ex_cmds2.c:5618
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "áËÔÉ×ÎÙÊ %sÑÚÙË: \"%s\""
+
+#: ex_cmds2.c:5629
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: îÅ×ÏÚÍÏÖÎÏ ÓÍÅÎÉÔØ ÑÚÙË ÎÁ \"%s\""
+
+#: ex_docmd.c:525
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "ðÅÒÅÈÏÄ × ÒÅÖÉÍ Ex. äÌÑ ÐÅÒÅÈÏÄÁ × ïÂÙÞÎÙÊ ÒÅÖÉÍ ÎÁÂÅÒÉÔÅ \"visual\""
+
+#. must be at EOF
+#: ex_docmd.c:561
+msgid "E501: At end-of-file"
+msgstr "E501: ÷ ËÏÎÃÅ ÆÁÊÌÁ"
+
+#: ex_docmd.c:669
+msgid "E169: Command too recursive"
+msgstr "E169: CÌÉÛËÏÍ ÒÅËÕÒÓÉ×ÎÁÑ ËÏÍÁÎÄÁ"
+
+#: ex_docmd.c:1229
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: éÓËÌÀÞÉÔÅÌØÎÁÑ ÓÉÔÕÁÃÉÑ ÎÅ ÏÂÒÁÂÏÔÁÎÁ: %s"
+
+#: ex_docmd.c:1317
+msgid "End of sourced file"
+msgstr "ëÏÎÅà ÓÞÉÔÁÎÎÏÇÏ ÆÁÊÌÁ"
+
+#: ex_docmd.c:1318
+msgid "End of function"
+msgstr "ëÏÎÅà ÆÕÎËÃÉÉ"
+
+#: ex_docmd.c:1907
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: îÅÏÄÎÏÚÎÁÞÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ËÏÍÁÎÄÙ ÐÏÌØÚÏ×ÁÔÅÌÑ"
+
+#: ex_docmd.c:1921
+msgid "E492: Not an editor command"
+msgstr "E492: üÔÏ ÎÅ ËÏÍÁÎÄÁ ÒÅÄÁËÔÏÒÁ"
+
+#: ex_docmd.c:2028
+msgid "E493: Backwards range given"
+msgstr "E493: úÁÄÁÎ ÏÂÒÁÔÎÙÊ ÄÉÁÐÁÚÏÎ"
+
+#: ex_docmd.c:2037
+msgid "Backwards range given, OK to swap"
+msgstr "úÁÄÁÎ ÏÂÒÁÔÎÙÊ ÄÉÁÐÁÚÏÎ, ÍÅÎÑÅÍ ÇÒÁÎÉÃÙ ÍÅÓÔÁÍÉ"
+
+#: ex_docmd.c:2160
+msgid "E494: Use w or w>>"
+msgstr "E494: éÓÐÏÌØÚÕÊÔÅ w ÉÌÉ w>>"
+
+#: ex_docmd.c:3786
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: éÚ×ÉÎÉÔÅ, ÜÔÁ ËÏÍÁÎÄÁ ÎÅÄÏÓÔÕÐÎÁ × ÄÁÎÎÏÊ ×ÅÒÓÉÉ"
+
+#: ex_docmd.c:3989
+msgid "E172: Only one file name allowed"
+msgstr "E172: òÁÚÒÅÛÅÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÔÏÌØËÏ ÏÄÎÏ ÉÍÑ ÆÁÊÌÁ"
+
+#: ex_docmd.c:4569
+msgid "1 more file to edit. Quit anyway?"
+msgstr "1 ÆÁÊÌ ÏÖÉÄÁÅÔ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ. ÷ÙÊÔÉ?"
+
+#: ex_docmd.c:4572
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "åÓÔØ ÎÅÏÔÒÅÄÁËÔÉÒÏ×ÁÎÎÙÅ ÆÁÊÌÙ (%d). ÷ÙÊÔÉ?"
+
+#: ex_docmd.c:4579
+msgid "E173: 1 more file to edit"
+msgstr "E173: 1 ÆÁÊÌ ÏÖÉÄÁÅÔ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ."
+
+#: ex_docmd.c:4581
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: åÓÔØ ÎÅÏÔÒÅÄÁËÔÉÒÏ×ÁÎÎÙÅ ÆÁÊÌÙ (%d)."
+
+#: ex_docmd.c:4676
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: ëÏÍÁÎÄÁ ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ. äÏÂÁ×ØÔÅ ! ÄÌÑ ÚÁÍÅÎÙ."
+
+#: ex_docmd.c:4787
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" éÍÑ ðÁÒÁÍ. äÉÁÐ. äÏÐÏÌÎ. ïÐÒÅÄÅÌÅÎÉÅ"
+
+#: ex_docmd.c:4876
+msgid "No user-defined commands found"
+msgstr "ëÏÍÁÎÄÙ, ÏÐÒÅÄÅÌ£ÎÎÙÅ ÐÏÌØÚÏ×ÁÔÅÌÅÍ, ÎÅ ÏÂÎÁÒÕÖÅÎÙ."
+
+#: ex_docmd.c:4908
+msgid "E175: No attribute specified"
+msgstr "E175: ÐÁÒÁÍÅÔÒ ÎÅ ÚÁÄÁÎ"
+
+#: ex_docmd.c:4960
+msgid "E176: Invalid number of arguments"
+msgstr "E176: îÅÐÒÁ×ÉÌØÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÐÁÒÁÍÅÔÒÏ×"
+
+#: ex_docmd.c:4975
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: þÉÓÌÏ-ÐÒÉÓÔÁ×ËÕ ÎÅÌØÚÑ ÕËÁÚÙ×ÁÔØ Ä×ÁÖÄÙ"
+
+#: ex_docmd.c:4985
+msgid "E178: Invalid default value for count"
+msgstr "E178: îÅÐÒÁ×ÉÌØÎÏÅ ÚÎÁÞÅÎÉÅ ÞÉÓÌÁ-ÐÒÉÓÔÁ×ËÉ ÐÏ ÕÍÏÌÞÁÎÉÀ"
+
+#: ex_docmd.c:5016
+msgid "E179: argument required for complete"
+msgstr "E179: ÄÌÑ ÚÁ×ÅÒÛÅÎÉÑ ÔÒÅÂÕÅÔÓÑ ÕËÁÚÁÔØ ÐÁÒÁÍÅÔÒ"
+
+#: ex_docmd.c:5048
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: îÅÐÒÁ×ÉÌØÎÏÅ ÚÎÁÞÅÎÉÅ ÄÏÐÏÌÎÅÎÉÑ: %s"
+
+#: ex_docmd.c:5057
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr ""
+"E468: ðÁÒÁÍÅÔÒ Á×ÔÏÄÏÐÏÌÎÅÎÉÑ ÍÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÔÏÌØËÏ Ó ÏÓÏÂÙÍ ÄÏÐÏÌÎÅÎÉÅÍ"
+
+#: ex_docmd.c:5063
+msgid "E467: Custom completion requires a function argument"
+msgstr "E467: ïÓÏÂÏÅ ÄÏÐÏÌÎÅÎÉÅ ÔÒÅÂÕÅÔ ÕËÁÚÁÎÉÑ ÐÁÒÁÍÅÔÒÁ ÆÕÎËÃÉÉ"
+
+#: ex_docmd.c:5074
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: îÅÐÒÁ×ÉÌØÎÙÊ ÁÔÒÉÂÕÔ: %s"
+
+#: ex_docmd.c:5117
+msgid "E182: Invalid command name"
+msgstr "E182: îÅÐÒÁ×ÉÌØÎÏÅ ÉÍÑ ËÏÍÁÎÄÙ"
+
+#: ex_docmd.c:5132
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: ëÏÍÁÎÄÁ ÐÏÌØÚÏ×ÁÔÅÌÑ ÄÏÌÖÎÁ ÎÁÞÉÎÁÔØÓÑ Ó ÚÁÇÌÁ×ÎÏÊ ÂÕË×Ù"
+
+#: ex_docmd.c:5203
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: îÅÔ ÔÁËÏÊ ËÏÍÁÎÄÙ ÐÏÌØÚÏ×ÁÔÅÌÑ: %s"
+
+#: ex_docmd.c:5664
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: ã×ÅÔÏ×ÁÑ ÓÈÅÍÁ %s ÎÅ ÎÁÊÄÅÎÁ"
+
+#: ex_docmd.c:5672
+msgid "Greetings, Vim user!"
+msgstr "ðÒÉ×ÅÔ, ÐÏÌØÚÏ×ÁÔÅÌØ Vim!"
+
+#: ex_docmd.c:6389
+msgid "Edit File in new window"
+msgstr "òÅÄÁËÔÉÒÏ×ÁÔØ ÆÁÊÌ × ÎÏ×ÏÍ ÏËÎÅ"
+
+#: ex_docmd.c:6684
+msgid "No swap file"
+msgstr "âÅÚ Ó×ÏÐ-ÆÁÊÌÁ"
+
+#: ex_docmd.c:6788
+msgid "Append File"
+msgstr "äÏÂÁ×ÉÔØ ÆÁÊÌ"
+
+#: ex_docmd.c:6852
+msgid "E186: No previous directory"
+msgstr "E186: îÅÔ ÐÒÅÄÙÄÕÝÅÇÏ ËÁÔÁÌÏÇÁ"
+
+#: ex_docmd.c:6934
+msgid "E187: Unknown"
+msgstr "E187: îÅÉÚ×ÅÓÔÎÏ"
+
+#: ex_docmd.c:7019
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: ËÏÍÁÎÄÁ :winsize ÔÒÅÂÕÅÔ ÕËÁÚÁÎÉÑ Ä×ÕÈ ÞÉÓÌÏ×ÙÈ ÐÁÒÁÍÅÔÒÏ×"
+
+#: ex_docmd.c:7075
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "ðÏÌÏÖÅÎÉÅ ÏËÎÁ: X %d, Y %d"
+
+#: ex_docmd.c:7080
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: ÷ ÄÁÎÎÏÊ ÓÉÓÔÅÍÅ ÏÐÒÅÄÅÌÅÎÉÅ ÐÏÌÏÖÅÎÉÑ ÏËÎÁ ÎÅ ÒÁÂÏÔÁÅÔ"
+
+#: ex_docmd.c:7090
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: ËÏÍÁÎÄÁ :winpos ÔÒÅÂÕÅÔ ÕËÁÚÁÎÉÑ Ä×ÕÈ ÞÉÓÌÏ×ÙÈ ÐÁÒÁÍÅÔÒÏ×"
+
+#: ex_docmd.c:7368
+msgid "Save Redirection"
+msgstr "ðÅÒÅÎÁÐÒÁ×ÌÅÎÉÅ ÚÁÐÉÓÉ"
+
+#: ex_docmd.c:7558
+msgid "Save View"
+msgstr "óÏÈÒÁÎÅÎÉÅ ×ÉÄÁ"
+
+#: ex_docmd.c:7559
+msgid "Save Session"
+msgstr "óÏÈÒÁÎÅÎÉÅ ÓÅÁÎÓÁ"
+
+#: ex_docmd.c:7561
+msgid "Save Setup"
+msgstr "óÏÈÒÁÎÅÎÉÅ ÎÁÓÔÒÏÅË"
+
+#: ex_docmd.c:7713
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" ÓÕÝÅÓÔ×ÕÅÔ (!, ÞÔÏÂÙ ÏÂÏÊÔÉ ÐÒÏ×ÅÒËÕ)"
+
+#: ex_docmd.c:7718
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÄÌÑ ÚÁÐÉÓÉ \"%s\""
+
+#. set mark
+#: ex_docmd.c:7742
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: ðÁÒÁÍÅÔÒ ÄÏÌÖÅÎ ÂÙÔØ ÐÒÑÍÏÊ/ÏÂÒÁÔÎÏÊ ËÁ×ÙÞËÏÊ ÉÌÉ ÂÕË×ÏÊ"
+
+#: ex_docmd.c:7784
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: óÌÉÛËÏÍ ÇÌÕÂÏËÁÑ ÒÅËÕÒÓÉÑ ÐÒÉ ÉÓÐÏÌØÚÏ×ÁÎÉÉ ËÏÍÁÎÄÙ :normal"
+
+#: ex_docmd.c:8302
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: îÅÔ ÓÏÓÅÄÎÅÇÏ ÉÍÅÎÉ ÆÁÊÌÁ ÄÌÑ ÚÁÍÅÎÙ '#'"
+
+#: ex_docmd.c:8333
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: îÅÔ Á×ÔÏËÏÍÁÎÄÎÏÇÏ ÉÍÅÎÉ ÆÁÊÌÁ ÄÌÑ ÚÁÍÅÎÙ \"<afile>\""
+
+#: ex_docmd.c:8341
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "E496: îÅÔ Á×ÔÏËÏÍÁÎÄÎÏÇÏ ÎÏÍÅÒÁ ÂÕÆÅÒÁ ÄÌÑ ÚÁÍÅÎÙ \"<abuf>\""
+
+#: ex_docmd.c:8352
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr "E497: îÅÔ Á×ÔÏËÏÍÁÎÄÎÏÇÏ ÉÍÅÎÉ ÓÏÏÔ×ÅÔÓÔ×ÉÑ ÄÌÑ ÚÁÍÅÎÙ \"<amatch>\""
+
+#: ex_docmd.c:8362
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr "E498: ÎÅÔ ÉÍÅÎÉ ÆÁÊÌÁ :source ÄÌÑ ÚÁÍÅÎÙ \"<sfile>\""
+
+#: ex_docmd.c:8403
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: ðÕÓÔÏÅ ÉÍÑ ÆÁÊÌÁ ÄÌÑ '%' ÉÌÉ '#', ×ÏÚÍÏÖÎÏ ÔÏÌØËÏ c \":p:h\""
+
+#: ex_docmd.c:8405
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: òÅÚÕÌØÔÁÔÏÍ ×ÙÒÁÖÅÎÉÑ Ñ×ÌÑÅÔÓÑ ÐÕÓÔÁÑ ÓÔÒÏËÁ"
+
+#: ex_docmd.c:9360
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ viminfo ÄÌÑ ÞÔÅÎÉÑ"
+
+#: ex_docmd.c:9533
+msgid "E196: No digraphs in this version"
+msgstr "E196: ÷ ÜÔÏÊ ×ÅÒÓÉÉ ÄÉÇÒÁÆÙ ÎÅ ÒÁÂÏÔÁÀÔ"
+
+#: ex_eval.c:440
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr ""
+"E608: îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ËÏÍÁÎÄÕ :throw ÄÌÑ ÉÓËÌÀÞÅÎÉÊ Ó ÐÒÉÓÔÁ×ËÏÊ 'Vim'"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:529
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "éÓËÌÀÞÉÔÅÌØÎÁÑ ÓÉÔÕÁÃÉÑ: %s"
+
+#: ex_eval.c:576
+#, c-format
+msgid "Exception finished: %s"
+msgstr "úÁ×ÅÒÛÅÎÁ ÏÂÒÁÂÏÔËÁ ÉÓËÌÀÞÉÔÅÌØÎÏÊ ÓÉÔÕÁÃÉÉ: %s"
+
+#: ex_eval.c:577
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "éÓËÌÀÞÉÔÅÌØÎÁÑ ÓÉÔÕÁÃÉÑ ÐÒÏÉÇÎÏÒÉÒÏ×ÁÎÁ: %s"
+
+#: ex_eval.c:620 ex_eval.c:664
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, ÓÔÒÏËÁ %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:638
+#, c-format
+msgid "Exception caught: %s"
+msgstr "ïÂÒÁÂÏÔËÁ ÉÓËÌÀÞÉÔÅÌØÎÏÊ ÓÉÔÕÁÃÉÉ: %s"
+
+#: ex_eval.c:713
+#, c-format
+msgid "%s made pending"
+msgstr "%s ×ÙÐÏÌÎÑÅÔ ÏÖÉÄÁÎÉÅ"
+
+#: ex_eval.c:716
+#, c-format
+msgid "%s resumed"
+msgstr "%s ×ÏÚÏÂÎÏ×ÌÅÎÏ"
+
+#: ex_eval.c:720
+#, c-format
+msgid "%s discarded"
+msgstr "%s ÐÒÏÐÕÝÅÎÏ"
+
+#: ex_eval.c:746
+msgid "Exception"
+msgstr "éÓËÌÀÞÉÔÅÌØÎÁÑ ÓÉÔÕÁÃÉÑ"
+
+#: ex_eval.c:752
+msgid "Error and interrupt"
+msgstr "ïÛÉÂËÁ É ÐÒÅÒÙ×ÁÎÉÅ"
+
+#: ex_eval.c:754 gui.c:4381
+msgid "Error"
+msgstr "ïÛÉÂËÁ"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:756
+msgid "Interrupt"
+msgstr "ðÒÅÒÙ×ÁÎÉÅ"
+
+#: ex_eval.c:830
+msgid "E579: :if nesting too deep"
+msgstr "E579: ÓÌÉÛËÏÍ ÇÌÕÂÏËÏ ×ÌÏÖÅÎÎÙÊ :if"
+
+#: ex_eval.c:867
+msgid "E580: :endif without :if"
+msgstr "E580: :endif ÂÅÚ :if"
+
+#: ex_eval.c:911
+msgid "E581: :else without :if"
+msgstr "E581: :else ÂÅÚ :if"
+
+#: ex_eval.c:914
+msgid "E582: :elseif without :if"
+msgstr "E582: :elseif ÂÅÚ :if"
+
+#: ex_eval.c:921
+msgid "E583: multiple :else"
+msgstr "E583: ÏÂÎÁÒÕÖÅÎÏ ÎÅÓËÏÌØËÏ :else"
+
+#: ex_eval.c:924
+msgid "E584: :elseif after :else"
+msgstr "E584: :elseif ÐÏÓÌÅ :else"
+
+#: ex_eval.c:991
+msgid "E585: :while nesting too deep"
+msgstr "E585: ÓÌÉÛËÏÍ ÇÌÕÂÏËÏ ×ÌÏÖÅÎÎÙÊ :while"
+
+#: ex_eval.c:1047
+msgid "E586: :continue without :while"
+msgstr "E586: :continue ÂÅÚ :while"
+
+#: ex_eval.c:1087
+msgid "E587: :break without :while"
+msgstr "E587: :break ÂÅÚ :while"
+
+#: ex_eval.c:1286
+msgid "E601: :try nesting too deep"
+msgstr "E601: ÓÌÉÛËÏÍ ÇÌÕÂÏËÏ ×ÌÏÖÅÎÎÙÊ :try"
+
+#: ex_eval.c:1366
+msgid "E603: :catch without :try"
+msgstr "E603: :catch ÂÅÚ :try"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1388
+msgid "E604: :catch after :finally"
+msgstr "E604: :catch ÂÅÚ :finally"
+
+#: ex_eval.c:1521
+msgid "E606: :finally without :try"
+msgstr "E606: :finally ÂÅÚ :try"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1545
+msgid "E607: multiple :finally"
+msgstr "E607: ÏÂÎÁÒÕÖÅÎÏ ÎÅÓËÏÌØËÏ :finally"
+
+#: ex_eval.c:1654
+msgid "E602: :endtry without :try"
+msgstr "E602: :endtry ÂÅÚ :try"
+
+#: ex_eval.c:1986
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: ËÏÍÁÎÄÁ :endfunction ÍÏÖÅÔ ÉÓÐÏÌØÚÏ×ÁÔØÓÑ ÔÏÌØËÏ ×ÎÕÔÒÉ ÆÕÎËÃÉÉ"
+
+#: ex_getln.c:3296
+msgid "tagname"
+msgstr "ÉÍÑ ÍÅÔËÉ"
+
+#: ex_getln.c:3299
+msgid " kind file\n"
+msgstr " ÔÉÐ ÆÁÊÌÁ\n"
+
+#: ex_getln.c:4752
+msgid "'history' option is zero"
+msgstr "ÚÎÁÞÅÎÉÅ ÏÐÃÉÉ 'history' ÒÁ×ÎÏ ÎÕÌÀ"
+
+#: ex_getln.c:5023
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s, ÉÓÔÏÒÉÑ (ÎÁÞÉÎÁÑ ÏÔ Ó×ÅÖÅÇÏ Ë ÓÔÁÒÏÍÕ):\n"
+
+#: ex_getln.c:5024
+msgid "Command Line"
+msgstr "ëÏÍÁÎÄÎÁÑ ÓÔÒÏËÁ"
+
+#: ex_getln.c:5025
+msgid "Search String"
+msgstr "óÔÒÏËÁ ÐÏÉÓËÁ"
+
+#: ex_getln.c:5026
+msgid "Expression"
+msgstr "÷ÙÒÁÖÅÎÉÅ"
+
+#: ex_getln.c:5027
+msgid "Input Line"
+msgstr "óÔÒÏËÁ ××ÏÄÁ"
+
+#: ex_getln.c:5065
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar ÂÏÌØÛÅ ÄÌÉÎÙ ËÏÍÁÎÄÙ"
+
+#: ex_getln.c:5242
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: õÄÁÌÅÎÏ ÁËÔÉ×ÎÏÅ ÏËÎÏ ÉÌÉ ÂÕÆÅÒ"
+
+#: fileio.c:377
+msgid "Illegal file name"
+msgstr "îÅÄÏÐÕÓÔÉÍÏÅ ÉÍÑ ÆÁÊÌÁ"
+
+#: fileio.c:401 fileio.c:535 fileio.c:2913 fileio.c:2954
+msgid "is a directory"
+msgstr "Ñ×ÌÑÅÔÓÑ ËÁÔÁÌÏÇÏÍ"
+
+#: fileio.c:403
+msgid "is not a file"
+msgstr "ÎÅ Ñ×ÌÑÅÔÓÑ ÆÁÊÌÏÍ"
+
+#: fileio.c:557 fileio.c:4131
+msgid "[New File]"
+msgstr "[îÏ×ÙÊ ÆÁÊÌ]"
+
+#: fileio.c:590
+msgid "[Permission Denied]"
+msgstr "[äÏÓÔÕÐ ÚÁÐÒÅÝ£Î]"
+
+#: fileio.c:694
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: ÷ ÒÅÚÕÌØÔÁÔÅ ×ÙÐÏÌÎÅÎÉÑ Á×ÔÏËÏÍÁÎÄ *ReadPre ÆÁÊÌ ÓÔÁÌ ÎÅÞÉÔÁÅÍÙÍ"
+
+#: fileio.c:696
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: Á×ÔÏËÏÍÁÎÄÙ *ReadPre ÎÅ ÄÏÌÖÎÙ ÉÚÍÅÎÑÔØ ÁËÔÉ×ÎÙÊ ÂÕÆÅÒ"
+
+#: fileio.c:717
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: ×ÙÐÏÌÎÑÅÔÓÑ ÞÔÅÎÉÅ ÉÚ ÓÔÁÎÄÁÒÔÎÏÇÏ ÐÏÔÏËÁ ××ÏÄÁ stdin...\n"
+
+#: fileio.c:723
+msgid "Reading from stdin..."
+msgstr "÷ÙÐÏÌÎÑÅÔÓÑ ÞÔÅÎÉÅ ÉÚ ÓÔÁÎÄÁÒÔÎÏÇÏ ÐÏÔÏËÁ ××ÏÄÁ stdin..."
+
+#. Re-opening the original file failed!
+#: fileio.c:1000
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: ÷ ÒÅÚÕÌØÔÁÔÅ ÐÒÅÏÂÒÁÚÏ×ÁÎÉÑ ÆÁÊÌ ÓÔÁÌ ÎÅÞÉÔÁÅÍÙÍ!"
+
+#: fileio.c:2090
+msgid "[fifo/socket]"
+msgstr "[fifo/ÇÎÅÚÄÏ]"
+
+#: fileio.c:2097
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:2104
+msgid "[socket]"
+msgstr "[ÇÎÅÚÄÏ]"
+
+#: fileio.c:2112
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:2122
+msgid "[CR missing]"
+msgstr "[ÐÒÏÐÕÝÅÎÙ ÓÉÍ×ÏÌÙ CR]"
+
+#: fileio.c:2127
+msgid "[NL found]"
+msgstr "[ïÂÎÁÒÕÖÅÎÙ ÓÉÍ×ÏÌÙ NL]"
+
+#: fileio.c:2132
+msgid "[long lines split]"
+msgstr "[ÄÌÉÎÎÙÅ ÓÔÒÏËÉ ÒÁÚÂÉÔÙ]"
+
+#: fileio.c:2138 fileio.c:4115
+msgid "[NOT converted]"
+msgstr "[âåú ÐÒÅÏÂÒÁÚÏ×ÁÎÉÊ]"
+
+#: fileio.c:2143 fileio.c:4120
+msgid "[converted]"
+msgstr "[ÐÅÒÅËÏÄÉÒÏ×ÁÎÏ]"
+
+#: fileio.c:2150 fileio.c:4145
+msgid "[crypted]"
+msgstr "[ÚÁÛÉÆÒÏ×ÁÎÏ]"
+
+#: fileio.c:2157
+msgid "[CONVERSION ERROR]"
+msgstr "[ïûéâëá ðòåïâòáúï÷áîéñ]"
+
+#: fileio.c:2163
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[îåäïðõóôéíùê âáêô × ÓÔÒÏËÅ %ld]"
+
+#: fileio.c:2170
+msgid "[READ ERRORS]"
+msgstr "[ïûéâëé þôåîéñ]"
+
+#: fileio.c:2386
+msgid "Can't find temp file for conversion"
+msgstr "÷ÒÅÍÅÎÎÙÊ ÆÁÊÌ ÄÌÑ ÐÅÒÅËÏÄÉÒÏ×ÁÎÉÑ ÎÅ ÎÁÊÄÅÎ"
+
+#: fileio.c:2393
+msgid "Conversion with 'charconvert' failed"
+msgstr "ðÒÅÏÂÒÁÚÏ×ÁÎÉÅ Ó ÐÏÍÏÝØÀ 'charconvert' ÎÅ ×ÙÐÏÌÎÅÎÏ"
+
+#: fileio.c:2396
+msgid "can't read output of 'charconvert'"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ×Ù×ÏÄ 'charconvert'"
+
+#: fileio.c:2796
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr ""
+"E203: âÕÆÅÒ, ËÏÔÏÒÙÊ ÔÒÅÂÏ×ÁÌÏÓØ ÚÁÐÉÓÁÔØ, ÕÄẠ́ΠÉÌÉ ×ÙÇÒÕÖÅÎ Á×ÔÏËÏÍÁÎÄÏÊ"
+
+#: fileio.c:2819
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: ëÏÌÉÞÅÓÔ×Ï ÓÔÒÏË ÉÚÍÅÎÅÎÏ Á×ÔÏËÏÍÁÎÄÏÊ ÎÅÏÖÉÄÁÎÎÙÍ ÏÂÒÁÚÏÍ"
+
+#: fileio.c:2857
+msgid "NetBeans dissallows writes of unmodified buffers"
+msgstr "NetBeans ÎÅ ÐÏÚ×ÏÌÑÅÔ ×ÙÐÏÌÎÑÔØ ÚÁÐÉÓØ ÎÅÉÚÍÅΣÎÎÙÈ ÂÕÆÅÒÏ×"
+
+#: fileio.c:2865
+msgid "Partial writes disallowed for NetBeans buffers"
+msgstr "þÁÓÔÉÞÎÁÑ ÚÁÐÉÓØ ÂÕÆÅÒÏ× NetBeans ÎÅ ÄÏÐÕÓËÁÅÔÓÑ"
+
+#: fileio.c:2919 fileio.c:2937
+msgid "is not a file or writable device"
+msgstr "ÎÅ Ñ×ÌÑÅÔÓÑ ÆÁÊÌÏÍ ÉÌÉ ÕÓÔÒÏÊÓÔ×ÏÍ, ÄÏÓÔÕÐÎÙÍ ÄÌÑ ÚÁÐÉÓÉ"
+
+#: fileio.c:2989
+msgid "is read-only (add ! to override)"
+msgstr "ÏÔËÒÙÔ ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ (!, ÞÔÏÂÙ ÏÂÏÊÔÉ ÐÒÏ×ÅÒËÕ)"
+
+#: fileio.c:3335
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: úÁÐÉÓØ × ÒÅÚÅÒ×ÎÙÊ ÆÁÊÌ ÎÅ×ÏÚÍÏÖÎÁ (!, ÞÔÏÂÙ ÏÂÏÊÔÉ ÐÒÏ×ÅÒËÕ)"
+
+#: fileio.c:3347
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr "E507: ïÛÉÂËÁ ÚÁËÒÙÔÉÑ ÒÅÚÅÒ×ÎÏÇÏ ÆÁÊÌÁ (!, ÞÔÏÂÙ ÏÂÏÊÔÉ ÐÒÏ×ÅÒËÕ)"
+
+#: fileio.c:3349
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr "E508: îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ÒÅÚÅÒ×ÎÙÊ ÆÁÊÌ (!, ÞÔÏÂÙ ÏÂÏÊÔÉ ÐÒÏ×ÅÒËÕ)"
+
+#: fileio.c:3365
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÒÅÚÅÒ×ÎÙÊ ÆÁÊÌ (!, ÞÔÏÂÙ ÏÂÏÊÔÉ ÐÒÏ×ÅÒËÕ)"
+
+#: fileio.c:3468
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÒÅÚÅÒ×ÎÙÊ ÆÁÊÌ (!, ÞÔÏÂÙ ÏÂÏÊÔÉ ÐÒÏ×ÅÒËÕ)"
+
+#: fileio.c:3530
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr "E460: ÷ÉÌËÁ ÒÅÓÕÒÓÁ ÂÕÄÅÔ ÐÏÔÅÒÑÎÁ (!, ÞÔÏÂÙ ÏÂÏÊÔÉ ÐÒÏ×ÅÒËÕ)"
+
+#: fileio.c:3640
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: ÷ÒÅÍÅÎÎÙÊ ÆÁÊÌ ÄÌÑ ÚÁÐÉÓÉ ÎÅ ÎÁÊÄÅÎ"
+
+#: fileio.c:3658
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr "E213: ðÅÒÅËÏÄÉÒÏ×ËÁ ÎÅ×ÏÚÍÏÖÎÁ (! ÄÌÑ ÚÁÐÉÓÉ ÂÅÚ ÐÅÒÅËÏÄÉÒÏ×ËÉ)"
+
+#: fileio.c:3693
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ Ó×ÑÚÁÎÎÙÊ ÆÁÊÌ ÄÌÑ ÚÁÐÉÓÉ"
+
+#: fileio.c:3697
+msgid "E212: Can't open file for writing"
+msgstr "E212: îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ ÄÌÑ ÚÁÐÉÓÉ"
+
+#: fileio.c:3959
+msgid "E667: Fsync failed"
+msgstr "E667: îÅ ÕÄÁÌÏÓØ ×ÙÐÏÌÎÉÔØ ÆÕÎËÃÉÀ fsync()"
+
+#: fileio.c:3966
+msgid "E512: Close failed"
+msgstr "E512: ïÐÅÒÁÃÉÑ ÚÁËÒÙÔÉÑ ÎÅ ÕÄÁÌÁÓØ"
+
+#: fileio.c:4037
+msgid "E513: write error, conversion failed"
+msgstr "E513: ïÛÉÂËÁ ÚÁÐÉÓÉ, ÐÒÅÏÂÒÁÚÏ×ÁÎÉÅ ÎÅ ÕÄÁÌÏÓØ"
+
+#: fileio.c:4043
+msgid "E514: write error (file system full?)"
+msgstr "E514: ÏÛÉÂËÁ ÚÁÐÉÓÉ (ÎÅÔ Ó×ÏÂÏÄÎÏÇÏ ÍÅÓÔÁ?)"
+
+#: fileio.c:4110
+msgid " CONVERSION ERROR"
+msgstr " ïûéâëá ðòåïâòáúï÷áîéñ"
+
+#: fileio.c:4126
+msgid "[Device]"
+msgstr "[õÓÔÒÏÊÓÔ×Ï]"
+
+#: fileio.c:4131
+msgid "[New]"
+msgstr "[îÏ×ÙÊ]"
+
+#: fileio.c:4153
+msgid " [a]"
+msgstr " [a]"
+
+#: fileio.c:4153
+msgid " appended"
+msgstr " ÄÏÂÁ×ÌÅÎÏ"
+
+#: fileio.c:4155
+msgid " [w]"
+msgstr " [w]"
+
+#: fileio.c:4155
+msgid " written"
+msgstr " ÚÁÐÉÓÁÎÏ"
+
+#: fileio.c:4205
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: òÅÖÉÍ ÚÁÐÌÁÔËÉ: ÎÅ×ÏÚÍÏÖÎÏ ÓÏÈÒÁÎÅÎÉÅ ÉÓÈÏÄÎÏÇÏ ÆÁÊÌÁ"
+
+#: fileio.c:4227
+msgid "E206: patchmode: can't touch empty original file"
+msgstr ""
+"E206: òÅÖÉÍ ÚÁÐÌÁÔËÉ: ÎÅ×ÏÚÍÏÖÎÏ ÓÍÅÎÉÔØ ÐÁÒÁÍÅÔÒÙ ÐÕÓÔÏÇÏ ÉÓÈÏÄÎÏÇÏ ÆÁÊÌÁ"
+
+#: fileio.c:4242
+msgid "E207: Can't delete backup file"
+msgstr "E207: îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÒÅÚÅÒ×ÎÙÊ ÆÁÊÌ"
+
+#: fileio.c:4306
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"ðòåäõðòåöäåîéå: éÓÈÏÄÎÙÊ ÆÁÊÌ ÍÏÖÅÔ ÂÙÔØ ÕÔÒÁÞÅÎ ÉÌÉ ÐÏ×ÒÅÖÄ£Î\n"
+
+#: fileio.c:4308
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "ÎÅ ×ÙÈÏÄÉÔÅ ÉÚ ÒÅÄÁËÔÏÒÁ, ÐÏËÁ ÆÁÊÌ ÎÅ ÂÕÄÅÔ ÕÓÐÅÛÎÏ ÚÁÐÉÓÁÎ!"
+
+#: fileio.c:4397
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:4397
+msgid "[dos format]"
+msgstr "[ÆÏÒÍÁÔ dos]"
+
+#: fileio.c:4404
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:4404
+msgid "[mac format]"
+msgstr "[ÆÏÒÍÁÔ mac]"
+
+#: fileio.c:4411
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:4411
+msgid "[unix format]"
+msgstr "[ÆÏÒÍÁÔ unix]"
+
+#: fileio.c:4438
+msgid "1 line, "
+msgstr "1 ÓÔÒÏËÁ, "
+
+#: fileio.c:4440
+#, c-format
+msgid "%ld lines, "
+msgstr "ÓÔÒÏË: %ld, "
+
+#: fileio.c:4443
+msgid "1 character"
+msgstr "1 ÓÉÍ×ÏÌ"
+
+#: fileio.c:4445
+#, c-format
+msgid "%ld characters"
+msgstr "ÓÉÍ×ÏÌÏ×: %ld"
+
+#: fileio.c:4455
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:4455
+msgid "[Incomplete last line]"
+msgstr "[îÅÚÁ×ÅÒÛ£ÎÎÁÑ ÐÏÓÌÅÄÎÑÑ ÓÔÒÏËÁ]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4474
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "ðòåäõðòåöäåîéå: æÁÊÌ ÉÚÍÅÎ£Î Ó ÍÏÍÅÎÔÁ ÞÔÅÎÉÑ!!!"
+
+#: fileio.c:4476
+msgid "Do you really want to write to it"
+msgstr "óÅÒØ£ÚÎÏ ÈÏÔÉÔÅ ÚÁÐÉÓÁÔØ × ÜÔÏÔ ÆÁÊÌ"
+
+#: fileio.c:5726
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: ïÛÉÂËÁ ÚÁÐÉÓÉ × \"%s\""
+
+#: fileio.c:5733
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: ïÛÉÂËÁ ÚÁËÒÙÔÉÑ \"%s\""
+
+#: fileio.c:5736
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: ïÛÉÂËÁ ÞÔÅÎÉÑ \"%s\""
+
+#: fileio.c:5970
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: âÕÆÅÒ ÕÄẠ́ΠÐÒÉ ×ÙÐÏÌÎÅÎÉÉ Á×ÔÏËÏÍÁÎÄÙ FileChangedShell"
+
+#: fileio.c:5977
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÆÁÊÌ \"%s\" ÂÏÌØÛÅ ÎÅ ÄÏÓÔÕÐÅÎ"
+
+#: fileio.c:5991
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÆÁÊÌ \"%s\" É ÂÕÆÅÒ Vim ÂÙÌÉ ÉÚÍÅÎÅÎÙ ÎÅÚÁ×ÉÓÉÍÏ ÄÒÕÇ "
+"ÏÔ ÄÒÕÇÁ"
+
+#: fileio.c:5994
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr ""
+"W11: ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÆÁÊÌ \"%s\" ÂÙÌ ÉÚÍÅΣΠÐÏÓÌÅ ÎÁÞÁÌÁ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ"
+
+#: fileio.c:5996
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr ""
+"W16: ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÒÅÖÉÍ ÄÏÓÔÕÐÁ Ë ÆÁÊÌÕ \"%s\" ÂÙÌ ÉÚÍÅΣΠÐÏÓÌÅ ÎÁÞÁÌÁ "
+"ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ"
+
+#: fileio.c:6006
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr ""
+"W13: ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÆÁÊÌ \"%s\" ÂÙÌ ÓÏÚÄÁÎ ÐÏÓÌÅ ÎÁÞÁÌÁ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ"
+
+#: fileio.c:6019
+msgid "See \":help W11\" for more info."
+msgstr "óÍ. ÄÏÐÏÌÎÉÔÅÌØÎÕÀ ÉÎÆÏÒÍÁÃÉÀ × \":help W11\"."
+
+#: fileio.c:6033
+msgid "Warning"
+msgstr "ðÒÅÄÕÐÒÅÖÄÅÎÉÅ"
+
+#: fileio.c:6034
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&úÁÇÒÕÚÉÔØ ÆÁÊÌ"
+
+#: fileio.c:6140
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: îÅ×ÏÚÍÏÖÎÏ ÐÏÄÇÏÔÏ×ÉÔØÓÑ Ë ÐÅÒÅÚÁÇÒÕÚËÅ \"%s\""
+
+#: fileio.c:6159
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÐÅÒÅÚÁÇÒÕÚËÕ \"%s\""
+
+#: fileio.c:6740
+msgid "--Deleted--"
+msgstr "--õÄÁÌÅÎÏ--"
+
+#. the group doesn't exist
+#: fileio.c:6900
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: çÒÕÐÐÁ \"%s\" ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+
+#: fileio.c:7026
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: îÅÄÏÐÕÓÔÉÍÙÅ ÓÉÍ×ÏÌÙ ÐÏÓÌÅ *: %s"
+
+#: fileio.c:7038
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: îÅÓÕÝÅÓÔ×ÕÀÝÅÅ ÓÏÂÙÔÉÅ: %s"
+
+#: fileio.c:7040
+#, c-format
+msgid "E216: No such group or event: %s"
+msgstr "E216: îÅÓÕÝÅÓÔ×ÕÀÝÁÑ ÇÒÕÐÐÁ ÉÌÉ ÓÏÂÙÔÉÅ: %s"
+
+#. Highlight title
+#: fileio.c:7198
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- á×ÔÏËÏÍÁÎÄÙ ---"
+
+#: fileio.c:7469
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ Á×ÔÏËÏÍÁÎÄÙ ÄÌÑ ÷óåè ÓÏÂÙÔÉÊ"
+
+#: fileio.c:7492
+msgid "No matching autocommands"
+msgstr "îÅÔ ÐÏÄÈÏÄÑÝÉÈ Á×ÔÏËÏÍÁÎÄ"
+
+#: fileio.c:7813
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: ÓÌÉÛËÏÍ ÇÌÕÂÏËÏ ×ÌÏÖÅÎÎÙÅ Á×ÔÏËÏÍÁÎÄÙ"
+
+#: fileio.c:8088
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s á×ÔÏËÏÍÁÎÄÙ ÄÌÑ \"%s\""
+
+#: fileio.c:8096
+#, c-format
+msgid "Executing %s"
+msgstr "÷ÙÐÏÌÎÅÎÉÅ %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:8164
+#, c-format
+msgid "autocommand %s"
+msgstr "Á×ÔÏËÏÍÁÎÄÁ %s"
+
+#: fileio.c:8731
+msgid "E219: Missing {."
+msgstr "E219: ðÒÏÐÕÝÅÎÁ {."
+
+#: fileio.c:8733
+msgid "E220: Missing }."
+msgstr "E220: ðÒÏÐÕÝÅÎÁ }."
+
+#: fold.c:68
+msgid "E490: No fold found"
+msgstr "E490: óËÌÁÄÏË ÎÅ ÏÂÎÁÒÕÖÅÎÏ"
+
+#: fold.c:593
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr ""
+"E350: óËÌÁÄËÁ ÎÅ ÍÏÖÅÔ ÂÙÔØ ÓÏÚÄÁÎÁ Ó ÔÅËÕÝÉÍ ÚÎÁÞÅÎÉÅÍ ÏÐÃÉÉ 'foldmethod'"
+
+#: fold.c:595
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr ""
+"E351: óËÌÁÄËÁ ÎÅ ÍÏÖÅÔ ÂÙÔØ ÕÄÁÌÅÎÁ Ó ÔÅËÕÝÉÍ ÚÎÁÞÅÎÉÅÍ ÏÐÃÉÉ 'foldmethod'"
+
+#: getchar.c:248
+msgid "E222: Add to read buffer"
+msgstr "E222: äÏÂÁ×ÌÅÎÉÅ × ÂÕÆÅÒ ÞÔÅÎÉÑ"
+
+#: getchar.c:2198
+msgid "E223: recursive mapping"
+msgstr "E223: ÒÅËÕÒÓÉ×ÎÁÑ ÐÒÉ×ÑÚËÁ"
+
+#: getchar.c:3077
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: ÕÖÅ ÅÓÔØ ÇÌÏÂÁÌØÎÏÅ ÓÏËÒÁÝÅÎÉÅ ÄÌÑ %s"
+
+#: getchar.c:3080
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: ÕÖÅ ÅÓÔØ ÇÌÏÂÁÌØÎÁÑ ÐÒÉ×ÑÚËÁ ÄÌÑ %s"
+
+#: getchar.c:3212
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: ÕÖÅ ÅÓÔØ ÓÏËÒÁÝÅÎÉÅ ÄÌÑ %s"
+
+#: getchar.c:3215
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: ÕÖÅ ÅÓÔØ ÐÒÉ×ÑÚËÁ ÄÌÑ %s"
+
+#: getchar.c:3279
+msgid "No abbreviation found"
+msgstr "óÏËÒÁÝÅÎÉÑ ÎÅ ÎÁÊÄÅÎÙ"
+
+#: getchar.c:3281
+msgid "No mapping found"
+msgstr "ðÒÉ×ÑÚËÉ ÎÅ ÎÁÊÄÅÎÙ"
+
+#: getchar.c:4173
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: ÎÅÄÏÐÕÓÔÉÍÙÊ ÒÅÖÉÍ"
+
+#: gui.c:220
+msgid "E229: Cannot start the GUI"
+msgstr "E229: îÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÊÔÉ × ÒÅÖÉÍ ÇÒÁÆÉÞÅÓËÏÇÏ ÉÎÔÅÒÆÅÊÓÁ"
+
+#: gui.c:349
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÞÔÅÎÉÅ \"%s\""
+
+#: gui.c:472
+msgid "E665: Cannot start GUI, no valid font found"
+msgstr ""
+"E665: îÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÊÔÉ × ÒÅÖÉÍ ÇÒÁÆ. ÉÎÔÅÒÆÅÊÓÁ, ÎÅÐÒÁ×ÉÌØÎÏ ÚÁÄÁÎÙ ÛÒÉÆÔÙ"
+
+#: gui.c:477
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: ÎÅÐÒÁ×ÉÌØÎÏÅ ÚÎÁÞÅÎÉÅ ÏÐÃÉÉ 'guifontwide'"
+
+#: gui.c:547
+msgid "E599: Value of 'imactivatekey' is invalid"
+msgstr "E599: ÎÅÐÒÁ×ÉÌØÎÏÅ ÚÎÁÞÅÎÉÅ ÏÐÃÉÉ 'imactivatekey'"
+
+#: gui.c:4061
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: îÅ×ÏÚÍÏÖÎÏ ÎÁÚÎÁÞÉÔØ Ã×ÅÔ %s"
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<ÎÅÌØÚÑ ÏÔËÒÙÔØ> "
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: ÛÒÉÆÔ %s ÎÅ ÎÁÊÄÅÎ"
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: ×ÏÚ×ÒÁÔ × ÔÅËÕÝÉÊ ËÁÔÁÌÏÇ ÎÅ×ÏÚÍÏÖÅÎ"
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "ðÕÔØ Ë ÆÁÊÌÕ:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: ÎÅ ÍÏÇÕ ÎÁÊÔÉ ÔÅËÕÝÉÊ ËÁÔÁÌÏÇ"
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "äÁ"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2731 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "ïÔÍÅÎÁ"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "ðÏÌÏÓÁ ÐÒÏËÒÕÔËÉ: ÎÅ ÍÏÇÕ ÏÐÒÅÄÅÌÉÔØ ÇÅÏÍÅÔÒÉÀ ÐÏÌÚÕÎËÁ"
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "äÉÁÌÏÇÏ×ÏÅ ÏËÎÏ Vim"
+
+#: gui_beval.c:101 gui_w32.c:3829
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr ""
+"E232: \"ðÕÚÙÒØ\" ÄÌÑ ×ÙÞÉÓÌÅÎÉÊ, ×ËÌÀÞÁÀÝÉÊ É ÓÏÏÂÝÅÎÉÅ, É ÏÂÒÁÔÎÙÊ ×ÙÚÏ×, "
+"ÎÅ ÍÏÖÅÔ ÂÙÔØ ÓÏÚÄÁÎ"
+
+#: gui_gtk.c:1607
+msgid "Vim dialog..."
+msgstr "äÉÁÌÏÇÏ×ÏÅ ÏËÎÏ Vim..."
+
+#: gui_gtk.c:2060 message.c:2993
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&äÁ\n"
+"&îÅÔ\n"
+"ï&ÔÍÅÎÁ"
+
+#: gui_gtk.c:2268
+msgid "Input _Methods"
+msgstr "íÅÔÏÄÙ ÷×ÏÄÁ"
+
+#: gui_gtk.c:2534 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "VIM - ðÏÉÓË É ÚÁÍÅÎÁ..."
+
+#: gui_gtk.c:2542 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "VIM - ðÏÉÓË..."
+
+#: gui_gtk.c:2574 gui_motif.c:2888
+msgid "Find what:"
+msgstr "þÔÏ ÉÝÅÍ:"
+
+#: gui_gtk.c:2592 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "îÁ ÞÔÏ ÚÁÍÅÎÑÅÍ:"
+
+#. whole word only button
+#: gui_gtk.c:2624 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "ôÏÌØËÏ ÔÏÞÎÙÅ ÓÏÏÔ×ÅÔÓÔ×ÉÑ"
+
+#. match case button
+#: gui_gtk.c:2635 gui_motif.c:3048
+msgid "Match case"
+msgstr "òÅÇÉÓÔÒÏÚÁ×ÉÓÉÍÙÅ ÓÏÏÔ×ÅÔÓÔ×ÉÑ"
+
+#: gui_gtk.c:2645 gui_motif.c:2990
+msgid "Direction"
+msgstr "îÁÐÒÁ×ÌÅÎÉÅ"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2657 gui_motif.c:3002
+msgid "Up"
+msgstr "÷×ÅÒÈ"
+
+#: gui_gtk.c:2661 gui_motif.c:3010
+msgid "Down"
+msgstr "÷ÎÉÚ"
+
+#: gui_gtk.c:2683 gui_gtk.c:2685 gui_motif.c:2792
+msgid "Find Next"
+msgstr "îÁÊÔÉ ÓÌÅÄÕÀÝÅÅ"
+
+#: gui_gtk.c:2702 gui_gtk.c:2704 gui_motif.c:2809
+msgid "Replace"
+msgstr "úÁÍÅÎÁ"
+
+#: gui_gtk.c:2715 gui_gtk.c:2717 gui_motif.c:2822
+msgid "Replace All"
+msgstr "úÁÍÅÎÉÔØ ×ÓÅ"
+
+#: gui_gtk_x11.c:2327
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: ðÏÌÕÞÅÎ ÚÁÐÒÏÓ ÎÁ ÐÒÅËÒÁÝÅÎÉÅ ÒÁÂÏÔÙ ÏÔ ÄÉÓÐÅÔÞÅÒÁ ÓÅÁÎÓÏ×\n"
+
+#: gui_gtk_x11.c:3519
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: ïÓÎÏ×ÎÏÅ ÏËÎÏ ÂÙÌÏ ÎÅÏÖÉÄÁÎÎÏ ÚÁËÒÙÔÏ\n"
+
+#: gui_gtk_x11.c:4138
+msgid "Font Selection"
+msgstr "÷ÙÂÏÒ ÛÒÉÆÔÁ"
+
+#: gui_gtk_x11.c:6035 ui.c:2120
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "÷ÍÅÓÔÏ ÐÕÓÔÏÇÏ ×ÙÄÅÌÅÎÉÑ ÉÓÐÏÌØÚÕÅÔÓÑ CUT_BUFFER0"
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "æÉÌØÔÒ"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "ëÁÔÁÌÏÇÉ"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "óÐÒÁ×ËÁ"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "æÁÊÌÙ"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "÷ÙÄÅÌÅÎÉÅ"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "ïÔÍÅÎÁ"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: îÅ×ÏÚÍÏÖÎÏ ÚÁÇÒÕÚÉÔØ ÛÒÉÆÔ Zap '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: îÅ×ÏÚÍÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÛÒÉÆÔ %s"
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"ïÔÐÒÁ×ËÁ ÓÏÏÂÝÅÎÉÑ ÄÌÑ ÕÎÉÞÔÏÖÅÎÉÑ ÐÒÏÃÅÓÓÁ-ÐÏÔÏÍËÁ.\n"
+
+#: gui_w32.c:829
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: ðÁÒÁÍÅÔÒ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ: \"-%s\"; ÉÓÐÏÌØÚÕÊÔÅ ×ÅÒÓÉÀ OLE."
+
+#: gui_w48.c:2090
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "ðÏÉÓË ÓÔÒÏËÉ (ÉÓÐÏÌØÚÕÊÔÅ '\\\\' ÄÌÑ ÐÏÉÓËÁ '\\')"
+
+#: gui_w48.c:2115
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "ðÏÉÓË É ÚÁÍÅÎÁ (ÉÓÐÏÌØÚÕÊÔÅ '\\\\' ÄÌÑ ÐÏÉÓËÁ '\\')"
+
+#: gui_x11.c:1537
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: ÎÅ×ÏÚÍÏÖÎÏ ×ÙÄÅÌÉÔØ ÚÁÐÉÓØ × ÔÁÂÌÉÃÅ Ã×ÅÔÁ, ÎÅËÏÔÏÒÙÅ Ã×ÅÔÁÍÏÇÕÔ "
+"ÏÔÏÂÒÁÖÁÔØÓÑ ÎÅÐÒÁ×ÉÌØÎÏ"
+
+#: gui_x11.c:2118
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: × ÎÁÂÏÒÅ ÛÒÉÆÔÏ× %s ÏÔÓÕÔÓÔ×ÕÀÔ ÛÒÉÆÔÙ ÄÌÑ ÓÌÅÄÕÀÝÉÈ ËÏÄÉÒÏ×ÏË:"
+
+#: gui_x11.c:2161
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: îÁÂÏÒ ÛÒÉÆÔÏ×: %s"
+
+#: gui_x11.c:2162
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "ûÒÉÆÔ '%s' ÎÅ Ñ×ÌÑÅÔÓÑ ÍÏÎÏÛÉÒÉÎÎÙÍ"
+
+#: gui_x11.c:2181
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: îÁÂÏÒ ÛÒÉÆÔÏ×: %s\n"
+
+#: gui_x11.c:2182
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Font0: %s\n"
+
+#: gui_x11.c:2183
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Font1: %s\n"
+
+#: gui_x11.c:2184
+msgid "Font%ld width is not twice that of font0\n"
+msgstr "ûÉÒÉÎÁ ÛÒÉÆÔÁ font%ld ÄÏÌÖÎÁ ÂÙÔØ ×Ä×ÏÅ ÂÏÌØÛÅ ÛÉÒÉÎÙ ÛÒÉÆÔÁ font0\n"
+
+#: gui_x11.c:2185
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "ûÉÒÉÎÁ ÛÒÉÆÔÁ font0: %ld\n"
+
+#: gui_x11.c:2186
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"ûÉÒÉÎÁ ÛÒÉÆÔÁ font1: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "õ256ö ïûéâëá Á×ÔÏÍÁÔÉËÉ èÁÎÇÙÌ"
+
+#: if_cscope.c:77
+msgid "Add a new database"
+msgstr "äÏÂÁ×ÉÔØ ÎÏ×ÕÀ ÂÁÚÕ ÄÁÎÎÙÈ"
+
+#: if_cscope.c:79
+msgid "Query for a pattern"
+msgstr "úÁÐÒÏÓ ÐÏ ÛÁÂÌÏÎÕ"
+
+#: if_cscope.c:81
+msgid "Show this message"
+msgstr "ðÏËÁÚÁÔØ ÜÔÏ ÓÏÏÂÝÅÎÉÅ"
+
+#: if_cscope.c:83
+msgid "Kill a connection"
+msgstr "õÂÉÔØ ÓÏÅÄÉÎÅÎÉÅ"
+
+#: if_cscope.c:85
+msgid "Reinit all connections"
+msgstr "úÁÎÏ×Ï ÉÎÉÃÉÁÌÉÚÉÒÏ×ÁÔØ ×ÓÅ ÓÏÅÄÉÎÅÎÉÑ"
+
+#: if_cscope.c:87
+msgid "Show connections"
+msgstr "ðÏËÁÚÁÔØ ÓÏÅÄÉÎÅÎÉÑ"
+
+#: if_cscope.c:95
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: éÓÐÏÌØÚÏ×ÁÎÉÅ: cs[cope] %s"
+
+#: if_cscope.c:124
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "üÔÁ ËÏÍÁÎÄÁ cscope ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÒÁÚÄÅÌÅÎÉÅ ÏËÎÁ.\n"
+
+#: if_cscope.c:175
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: éÓÐÏÌØÚÏ×ÁÎÉÅ: cstag <ÉÍÑ>"
+
+#: if_cscope.c:231
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: ÍÅÔËÁ ÎÅ ÎÁÊÄÅÎÁ"
+
+#: if_cscope.c:409
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "ÏÛÉÂËÁ stat(%s): %d"
+
+#: if_cscope.c:419
+msgid "E563: stat error"
+msgstr "E563: ÏÛÉÂËÁ stat"
+
+#: if_cscope.c:516
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s ÎÅ Ñ×ÌÑÅÔÓÑ ËÁÔÁÌÏÇÏÍ ÉÌÉ ÉÍÅÎÅÍ ÂÁÚÙ cscope"
+
+#: if_cscope.c:534
+#, c-format
+msgid "Added cscope database %s"
+msgstr "äÏÂÁ×ÌÅÎÁ ÂÁÚÁ ÄÁÎÎÙÈ cscope %s"
+
+#: if_cscope.c:589
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: ÏÛÉÂËÁ ÐÏÌÕÞÅÎÉÑ ÉÎÆÏÒÍÁÃÉÉ ÏÔ ÓÏÅÄÉÎÅÎÉÑ cscope %d"
+
+#: if_cscope.c:694
+msgid "E561: unknown cscope search type"
+msgstr "E561: ÎÅÉÚ×ÅÓÔÎÙÊ ÔÉÐ ÐÏÉÓËÁ cscope"
+
+#: if_cscope.c:736
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÔÒÕÂÕ ÄÌÑ cscope"
+
+#: if_cscope.c:753
+msgid "E622: Could not fork for cscope"
+msgstr "E622: îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ fork() ÄÌÑ cscope"
+
+#: if_cscope.c:847 if_cscope.c:897
+msgid "cs_create_connection exec failed"
+msgstr "ÎÅ ÕÄÁÌÏÓØ ×ÙÐÏÌÎÉÔØ cs_create_connection"
+
+#: if_cscope.c:898
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: îÅ ÕÄÁÌÏÓØ ÚÁÐÕÓÔÉÔØ ÐÒÏÃÅÓÓ cscope"
+
+#: if_cscope.c:911
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: ÎÅ ÕÄÁÌÏÓØ ×ÙÐÏÌÎÉÔØ fdopen ÄÌÑ to_fp"
+
+#: if_cscope.c:913
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: ÎÅ ÕÄÁÌÏÓØ ×ÙÐÏÌÎÉÔØ fdopen ÄÌÑ fr_fp"
+
+#: if_cscope.c:951
+msgid "E567: no cscope connections"
+msgstr "E567: ÓÏÅÄÉÎÅÎÉÊ Ó cscope ÎÅ ÓÏÚÄÁÎÏ"
+
+#: if_cscope.c:1025
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: ÎÅ ÎÁÊÄÅÎÏ ÓÏÏÔ×ÅÔÓÔ×ÉÊ ÐÏ ÚÁÐÒÏÓÕ cscope %s ÄÌÑ %s"
+
+#: if_cscope.c:1082
+#, c-format
+msgid "E469: invalid cscopequickfix flag %c for %c"
+msgstr "E469: ÎÅÐÒÁ×ÉÌØÎÙÊ ÆÌÁÇ cscopequickfix %c ÄÌÑ %c"
+
+#: if_cscope.c:1152
+msgid "cscope commands:\n"
+msgstr "ËÏÍÁÎÄÙ cscope:\n"
+
+#: if_cscope.c:1155
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (éÓÐÏÌØÚÏ×ÁÎÉÅ: %s)"
+
+#: if_cscope.c:1253
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÂÁÚÕ ÄÁÎÎÙÈ cscope: %s"
+
+#: if_cscope.c:1271
+msgid "E626: cannot get cscope database information"
+msgstr "E626: ÉÎÆÏÒÍÁÃÉÑ Ï ÂÁÚÅ ÄÁÎÎÙÈ cscope ÎÅ ÄÏÓÔÕÐÎÁ"
+
+#: if_cscope.c:1296
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: ÄÁÎÎÁÑ ÂÁÚÁ ÄÁÎÎÙÈ cscope ÕÖÅ ÐÏÄÓÏÅÄÉÎÅÎÁ"
+
+#: if_cscope.c:1307
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: ÄÏÓÔÉÇÎÕÔÏ ÍÁËÓÉÍÁÌØÎÏÅ ÚÎÁÞÅÎÉÅ ÏÔËÒÙÔÙÈ ÓÏÅÄÉÎÅÎÉÊ Ó cscope"
+
+#: if_cscope.c:1424
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: ÓÏÅÄÉÎÅÎÉÅ Ó cscope %s ÎÅ ÏÂÎÁÒÕÖÅÎÏ"
+
+#: if_cscope.c:1458
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "ÓÏÅÄÉÎÅÎÉÅ Ó cscope ÚÁËÒÙÔÏ"
+
+#. should not reach here
+#: if_cscope.c:1598
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: ËÒÉÔÉÞÅÓËÁÑ ÏÛÉÂËÁ × cs_manage_matches"
+
+#: if_cscope.c:1848
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "íÅÔËÁ cscope: %s"
+
+#: if_cscope.c:1870
+msgid ""
+"\n"
+" # line"
+msgstr ""
+"\n"
+" # ÓÔÒÏËÁ"
+
+#: if_cscope.c:1872
+msgid "filename / context / line\n"
+msgstr "ÉÍÑ ÆÁÊÌÁ / ËÏÎÔÅËÓÔ / ÓÔÒÏËÁ\n"
+
+#: if_cscope.c:1990
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: ïÛÉÂËÁ cscope: %s"
+
+#: if_cscope.c:2176
+msgid "All cscope databases reset"
+msgstr "ðÅÒÅÚÁÇÒÕÚËÁ ×ÓÅÈ ÂÁÚ ÄÁÎÎÙÈ cscope"
+
+#: if_cscope.c:2244
+msgid "no cscope connections\n"
+msgstr "ÓÏÅÄÉÎÅÎÉÑ Ó cscope ÏÔÓÕÔÓÔ×ÕÀÔ\n"
+
+#: if_cscope.c:2248
+msgid " # pid database name prepend path\n"
+msgstr " # pid ÂÁÚÁ ÄÁÎÎÙÈ ÎÁÞÁÌØÎÙÊ ÐÕÔØ\n"
+
+#: if_python.c:436
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: ë ÓÏÖÁÌÅÎÉÀ ÜÔÁ ËÏÍÁÎÄÁ ÎÅ ÒÁÂÏÔÁÅÔ, ÐÏÓËÏÌØËÕ ÎÅ ÚÁÇÒÕÖÅÎÁ ÂÉÂÌÉÏÔÅËÁ "
+"Python"
+
+#: if_python.c:500
+msgid "E659: Cannot invoke Python recursively"
+msgstr "E659: îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÒÅËÕÒÓÉ×ÎÙÊ ×ÙÚÏ× Python"
+
+#: if_python.c:701
+msgid "can't delete OutputObject attributes"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÁÔÒÉÂÕÔÙ OutputObject"
+
+#: if_python.c:708
+msgid "softspace must be an integer"
+msgstr "ÚÎÁÞÅÎÉÅ softspace ÄÏÌÖÎÏ ÂÙÔØ ÃÅÌÙÍ ÞÉÓÌÏÍ"
+
+#: if_python.c:716
+msgid "invalid attribute"
+msgstr "ÎÅÐÒÁ×ÉÌØÎÙÊ ÁÔÒÉÂÕÔ"
+
+#: if_python.c:755 if_python.c:769
+msgid "writelines() requires list of strings"
+msgstr "writelines() ÔÒÅÂÕÅÔ ÕËÁÚÁÎÉÑ ÓÐÉÓËÁ ÓÔÒÏË"
+
+#: if_python.c:895
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: ïÛÉÂËÁ ÉÎÉÃÉÁÌÉÚÁÃÉÉ ÏÂßÅËÔÏ× I/O"
+
+#: if_python.c:1080 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "ÎÅÐÒÁ×ÉÌØÎÏÅ ×ÙÒÁÖÅÎÉÅ"
+
+#: if_python.c:1094 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "×ÙÒÁÖÅÎÉÑ ÏÔËÌÀÞÅÎÙ ÐÒÉ ËÏÍÐÉÌÑÃÉÉ"
+
+#: if_python.c:1107
+msgid "attempt to refer to deleted buffer"
+msgstr "ÐÏÐÙÔËÁ ÓÏÓÌÁÔØÓÑ ÎÁ ÕÎÉÞÔÏÖÅÎÎÙÊ ÂÕÆÅÒ"
+
+#: if_python.c:1122 if_python.c:1163 if_python.c:1227 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "ÚÁÐÒÅÄÅÌØÎÙÊ ÎÏÍÅÒ ÓÔÒÏËÉ"
+
+#: if_python.c:1362
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<ÏÂßÅËÔ ÂÕÆÅÒÁ (ÕÄÁÌÅÎ) × %8lX>"
+
+#: if_python.c:1453 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "ÎÅÐÒÁ×ÉÌØÎÏÅ ÉÍÑ ÏÔÍÅÔËÉ"
+
+#: if_python.c:1733
+msgid "no such buffer"
+msgstr "ÎÅÔ ÔÁËÏÇÏ ÂÕÆÅÒÁ"
+
+#: if_python.c:1821
+msgid "attempt to refer to deleted window"
+msgstr "ÐÏÐÙÔËÁ ÓÏÓÌÁÔØÓÑ ÎÁ ÚÁËÒÙÔÏÅ ÏËÎÏ"
+
+#: if_python.c:1866
+msgid "readonly attribute"
+msgstr "ÁÔÒÉÂÕÔ ÄÏÓÔÕÐÅÎ ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ"
+
+#: if_python.c:1879
+msgid "cursor position outside buffer"
+msgstr "ÐÏÚÉÃÉÑ ËÕÒÓÏÒÁ ÎÁÈÏÄÉÔÓÑ ×ÎÅ ÂÕÆÅÒÁ"
+
+#: if_python.c:1956
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<ÏÂßÅËÔ ÏËÎÁ (ÕÄÁÌÅÎ) × %.8lX>"
+
+#: if_python.c:1968
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<ÏÂßÅËÔ ÏËÎÁ (ÎÅÉÚ×ÅÓÔÅÎ) × %.8lX>"
+
+#: if_python.c:1970
+#, c-format
+msgid "<window %d>"
+msgstr "<ÏËÎÏ %d>"
+
+#: if_python.c:2046
+msgid "no such window"
+msgstr "ÎÅÔ ÔÁËÏÇÏ ÏËÎÁ"
+
+#: if_python.c:2307 if_python.c:2341 if_python.c:2396 if_python.c:2464
+#: if_python.c:2586 if_python.c:2638 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÓÏÈÒÁÎÉÔØ ÉÎÆÏÒÍÁÃÉÀ Ï ÏÔÍÅÎÅ ÏÐÅÒÁÃÉÉ"
+
+#: if_python.c:2309 if_python.c:2403 if_python.c:2475
+msgid "cannot delete line"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÓÔÒÏËÕ"
+
+#: if_python.c:2346 if_python.c:2491 if_tcl.c:690 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÍÅÎÉÔØ ÓÔÒÏËÕ"
+
+#: if_python.c:2509 if_python.c:2588 if_python.c:2646
+msgid "cannot insert line"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ×ÓÔÁ×ÉÔØ ÓÔÒÏËÕ"
+
+#: if_python.c:2750
+msgid "string cannot contain newlines"
+msgstr "ÓÔÒÏËÁ ÎÅ ÍÏÖÅÔ ÓÏÄÅÒÖÁÔØ ÓÉÍ×ÏÌ ÎÏ×ÏÊ ÓÔÒÏËÉ"
+
+#: if_ruby.c:422
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: ë ÓÏÖÁÌÅÎÉÀ ÜÔÁ ËÏÍÁÎÄÁ ÎÅ ÒÁÂÏÔÁÅÔ, ÐÏÓËÏÌØËÕ ÎÅ ÚÁÇÒÕÖÅÎÁ ÂÉÂÌÉÏÔÅËÁ "
+"Ruby."
+
+#: if_ruby.c:485
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: ÎÅÉÚ×ÅÓÔÎÏÅ ÓÏÓÔÏÑÎÉÅ longjmp %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "ðÅÒÅËÌÀÞÅÎÉÅ ÍÅÖÄÕ ÒÅÁÌÉÚÁÃÉÅÊ/ÏÐÒÅÄÅÌÅÎÉÅÍ"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "ðÏËÁÚÁÔØ ÂÁÚÏ×ÙÊ ËÌÁÓÓ "
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "ðÏËÁÚÁÔØ ÐÅÒÅÇÒÕÖÅÎÎÙÅ ÆÕÎËÃÉÉ"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "ðÏÌÕÞÅÎÉÅ ÉÚ ÆÁÊÌÁ"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "ðÏÌÕÞÅÎÉÅ ÉÚ ÐÒÏÅËÔÁ"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "ðÏÌÕÞÅÎÉÅ ÉÚ ×ÓÅÈ ÐÒÏÅËÔÏ×"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "ðÏÌÕÞÅÎÉÅ"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "ðÏËÁÚÁÔØ ÉÓÈÏÄÎÙÊ ËÏÄ"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "îÁÊÔÉ ÓÉÍ×ÏÌ"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "ðÒÏÓÍÏÔÒ ËÌÁÓÓÁ"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "ðÏËÁÚÁÔØ ËÌÁÓÓ × ÉÅÒÁÒÈÉÉ"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "ðÏËÁÚÁÔØ ËÌÁÓÓ × ÏÇÒÁÎÉÞÅÎÎÏÊ ÉÅÒÁÒÈÉÉ"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref ÓÓÙÌÁÅÔÓÑ ÎÁ"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "óÓÙÌËÁ ÎÁ xref ÉÚ"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref ÉÍÅÅÔ"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref ÉÓÐÏÌØÚÕÅÔÓÑ"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "ðÏËÁÚÁÔØ docu"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "óÏÚÄÁÔØ docu"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"îÅ×ÏÚÍÏÖÎÏ ÐÏÄÓÏÅÄÉÎÉÔØÓÑ Ë SNiFF+. ðÒÏ×ÅÒØÔÅ ÎÁÓÔÒÏÊËÉ ÏËÒÕÖÅÎÉÑ."
+"(sniffemacs ÄÏÌÖÎÙ ÂÙÔØ ÕËÁÚÁÎÙ × ÐÅÒÅÍÅÎÎÏÊ $PATH).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: ïÛÉÂËÁ ×Ï ×ÒÅÍÑ ÞÔÅÎÉÑ. ïÔÓÏÅÄÉÎÅÎÉÅ"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "÷ ÎÁÓÔÏÑÝÉÊ ÍÏÍÅÎÔ SNiFF+ "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "ÎÅ "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "ÐÏÄÓÏÅÄÉΣÎ"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: îÅÉÚ×ÅÓÔÎÙÊ ÚÁÐÒÏÓ SNiFF+: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: ïÛÉÂËÁ ÓÏÅÄÉÎÅÎÉÑ ÓÏ SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ ÎÅ ÐÏÄÓÏÅÄÉΣÎ"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: üÔÏ ÎÅ ÂÕÆÅÒ SNiFF+"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: ïÛÉÂËÁ ×Ï ×ÒÅÍÑ ÚÁÐÉÓÉ. ïÔÓÏÅÄÉÎÅÎÉÅ"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "ÎÅÐÒÁ×ÉÌØÎÙÊ ÎÏÍÅÒ ÂÕÆÅÒÁ"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "ÐÏËÁ ÎÅ ÒÅÁÌÉÚÏ×ÁÎÏ"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "ÎÅÉÚ×ÅÓÔÎÁÑ ÏÐÃÉÑ"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÎÁÚÎÁÞÉÔØ ÓÔÒÏËÕ ÉÌÉ ÓÔÒÏËÉ"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "ÏÔÍÅÔËÁ ÎÅ ÕÓÔÁÎÏ×ÌÅÎÁ"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "ÒÑÄ %d ËÏÌÏÎËÁ %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ×ÓÔÁ×ÉÔØ ÉÌÉ ÄÏÂÁ×ÉÔØ ÓÔÒÏËÕ"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "ÎÅÉÚ×ÅÓÔÎÙÊ ÆÌÁÇ: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "ÎÅÉÚ×ÅÓÔÎÁÑ vimOption"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "ËÌÁ×ÉÁÔÕÒÎÏÅ ÐÒÅÒÙ×ÁÎÉÅ"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "ÏÛÉÂËÁ vim"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ËÏÍÁÎÄÕ ÂÕÆÅÒÁ ÉÌÉ ÏËÎÁ: ÏÂßÅËÔ × ÐÒÏÃÅÓÓÅ ÕÄÁÌÅÎÉÑ"
+
+#: if_tcl.c:1545
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"ÎÅ×ÏÚÍÏÖÎÏ ÚÁÒÅÇÉÓÔÒÉÒÏ×ÁÔØ ËÏÍÁÎÄÕ Ó ÏÂÒÁÔÎÙÍ ×ÙÚÏ×ÏÍ: ÂÕÆÅÒ ÉÌÉ ÏËÎÏ × "
+"ÐÒÏÃÅÓÓÅ ÕÄÁÌÅÎÉÑ"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: ëòéôéþåóëáñ ïûéâëá TCL: ÐÏ×ÒÅÖģΠÓÐÉÓÏË ÓÓÙÌÏË?! óÏÏÂÝÉÔÅ Ï ÜÔÏÍ ÐÏ "
+"ÁÄÒÅÓÕ vim-dev@vim.org"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"ÎÅ×ÏÚÍÏÖÎÏ ÚÁÒÅÇÉÓÔÒÉÒÏ×ÁÔØ ËÏÍÁÎÄÕ Ó ÏÂÒÁÔÎÙÍ ×ÙÚÏ×ÏÍ: ÓÓÙÌËÁ ÎÁ ÂÕÆÅÒ ÉÌÉ "
+"ÏËÎÏ ÎÅ ÏÂÎÁÒÕÖÅÎÁ"
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"E571: ë ÓÏÖÁÌÅÎÉÀ ÜÔÁ ËÏÍÁÎÄÁ ÎÅ ÒÁÂÏÔÁÅÔ, ÐÏÓËÏÌØËÕ ÎÅ ÚÁÇÒÕÖÅÎÁ ÂÉÂÌÉÏÔÅËÁ "
+"Tcl"
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: ïûéâëá TCL: ëÏÄ ×ÙÈÏÄÁ ÎÅ Ñ×ÌÑÅÔÓÑ ÃÅÌÙÍ ÞÉÓÌÏÍ?! óÏÏÂÝÉÔÅ Ï ÜÔÏÍ × "
+"vim-dev@vim.org"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÐÏÌÕÞÉÔØ ÓÔÒÏËÕ"
+
+#: if_xcmdsrv.c:225
+msgid "Unable to register a command server name"
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÚÁÒÅÇÉÓÔÒÉÒÏ×ÁÔØ ÉÍÑ ÓÅÒ×ÅÒÁ ËÏÍÁÎÄ"
+
+#: if_xcmdsrv.c:473
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: ïÔÐÒÁ×ËÁ ËÏÍÁÎÄÙ × ÄÒÕÇÕÀ ÐÒÏÇÒÁÍÍÕ ÎÅ ÕÄÁÌÁÓØ"
+
+#: if_xcmdsrv.c:747
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: éÓÐÏÌØÚÕÅÔÓÑ ÎÅÐÒÁ×ÉÌØÎÙÊ id ÓÅÒ×ÅÒÁ: %s"
+
+#: if_xcmdsrv.c:1110
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr ""
+"E251: îÅÐÒÁ×ÉÌØÎÏ ÓÆÏÒÍÉÒÏ×ÁÎÏ ÚÎÁÞÅÎÉÅ ÄÁÎÎÏÇÏ ÐÒÏÃÅÓÓÁ VIM × ÒÅÅÓÔÒÅ. "
+"õÄÁÌÅÎÏ!"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "îÅÉÚ×ÅÓÔÎÙÊ ÁÒÇÕÍÅÎÔ"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "óÌÉÛËÏÍ ÍÎÏÇÏ ÁÒÇÕÍÅÎÔÏ× ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "ðÒÏÐÕÝÅÎ ÁÒÇÕÍÅÎÔ ÐÏÓÌÅ"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "íÕÓÏÒ ÐÏÓÌÅ ÁÒÇÕÍÅÎÔÁ"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr ""
+"óÌÉÛËÏÍ ÍÎÏÇÏ ÁÒÇÕÍÅÎÔÏ× \"+ËÏÍÁÎÄÁ\", \"-c ËÏÍÁÎÄÁ\" ÉÌÉ \"--cmd ËÏÍÁÎÄÁ\""
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "îÅÄÏÐÕÓÔÉÍÙÅ ÁÒÇÕÍÅÎÔÙ ÄÌÑ"
+
+#: main.c:466
+msgid "This Vim was not compiled with the diff feature."
+msgstr ""
+"äÁÎÎÙÊ Vim ÂÙÌ ÓËÏÍÐÉÌÉÒÏ×ÁÎ Ó ×ÙËÌÀÞÅÎÎÏÊ ÏÓÏÂÅÎÎÏÓÔØÀ ÐÒÏÓÍÏÔÒÁ ÏÔÌÉÞÉÊ"
+
+#: main.c:932
+msgid "Attempt to open script file again: \""
+msgstr "ðÏÐÙÔËÁ ÐÏ×ÔÏÒÎÏÇÏ ÏÔËÒÙÔÉÑ ÆÁÊÌÁ ÓÃÅÎÁÒÉÑ: \""
+
+#: main.c:941
+msgid "Cannot open for reading: \""
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÄÌÑ ÞÔÅÎÉÑ: \""
+
+#: main.c:985
+msgid "Cannot open for script output: \""
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÄÌÑ ×Ù×ÏÄÁ ÓÃÅÎÁÒÉÑ: \""
+
+#: main.c:1132
+#, c-format
+msgid "%d files to edit\n"
+msgstr "æÁÊÌÏ× ÄÌÑ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ: %d\n"
+
+#: main.c:1233
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÷Ù×ÏÄ ÏÓÕÝÅÓÔ×ÌÑÅÔÓÑ ÎÅ ÎÁ ÔÅÒÍÉÎÁÌ\n"
+
+#: main.c:1235
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÷×ÏÄ ÐÒÏÉÓÈÏÄÉÔ ÎÅ Ó ÔÅÒÍÉÎÁÌÁ\n"
+
+#. just in case..
+#: main.c:1297
+msgid "pre-vimrc command line"
+msgstr "ËÏÍÁÎÄÎÁÑ ÓÔÒÏËÁ ÐÅÒÅÄ ×ÙÐÏÌÎÅÎÉÅÍ vimrc"
+
+#: main.c:1338
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÞÔÅÎÉÅ ÉÚ \"%s\""
+
+#: main.c:2411
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"äÏÐÏÌÎÉÔÅÌØÎÁÑ ÉÎÆÏÒÍÁÃÉÑ: \"vim -h\"\n"
+
+#: main.c:2444
+msgid "[file ..] edit specified file(s)"
+msgstr "[ÆÁÊÌ ..] ÒÅÄÁËÔÉÒÏ×ÁÎÉÅ ÕËÁÚÁÎÎÙÈ ÆÁÊÌÏ×"
+
+#: main.c:2445
+msgid "- read text from stdin"
+msgstr "- ÞÔÅÎÉÅ ÔÅËÓÔÁ ÉÚ ÐÏÔÏËÁ ××ÏÄÁ stdin"
+
+#: main.c:2446
+msgid "-t tag edit file where tag is defined"
+msgstr "-t ÍÅÔËÁ ÒÅÄÁËÔÉÒÏ×ÁÎÉÅ ÆÁÊÌÁ Ó ÕËÁÚÁÎÎÏÊ ÍÅÔËÏÊ"
+
+#: main.c:2448
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [ÆÁÊÌ ÏÛÉÂÏË] ÒÅÄÁËÔÉÒÏ×ÁÎÉÅ ÆÁÊÌÁ Ó ÐÅÒ×ÏÊ ÏÛÉÂËÏÊ"
+
+#: main.c:2457
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"éÓÐÏÌØÚÏ×ÁÎÉÅ:"
+
+#: main.c:2460
+msgid " vim [arguments] "
+msgstr " vim [ÁÒÇÕÍÅÎÔÙ] "
+
+#: main.c:2464
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" ÉÌÉ:"
+
+#: main.c:2467
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"áÒÇÕÍÅÎÔÙ:\n"
+
+#: main.c:2468
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\täÁÌÅÅ ÕËÁÚÙ×ÁÀÔÓÑ ÔÏÌØËÏ ÉÍÅÎÁ ÆÁÊÌÏ×"
+
+#: main.c:2470
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tîÅ ×ÙÐÏÌÎÑÔØ ÐÏÄÓÔÁÎÏ×ËÕ ÐÏ ÍÁÓËÅ"
+
+#: main.c:2473
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\túÁÒÅÇÉÓÔÒÉÒÏ×ÁÔØ ÜÔÏÔ gvim ÄÌÑ OLE"
+
+#: main.c:2474
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tïÔËÌÀÞÉÔØ ÒÅÇÉÓÔÒÁÃÉÀ ÄÁÎÎÏÇÏ gvim ÄÌÑ OLE"
+
+#: main.c:2477
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\túÁÐÕÓÔÉÔØ Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ (ËÁË \"gvim\")"
+
+#: main.c:2478
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f ÉÌÉ --nofork\t÷ ÁËÔÉ×ÎÏÊ ÚÁÄÁÞÅ: îÅ ×ÙÐÏÌÎÑÔØ fork ÐÒÉ ÚÁÐÕÓËÅ GUI"
+
+#: main.c:2480
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tòÅÖÉÍ Vi (ËÁË \"vi\")"
+
+#: main.c:2481
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tòÅÖÉÍ Ex (ËÁË \"ex\")"
+
+#: main.c:2482
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tôÉÈÉÊ (ÐÁËÅÔÎÙÊ) ÒÅÖÉÍ (ÔÏÌØËÏ ÄÌÑ \"ex\")"
+
+#: main.c:2484
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tòÅÖÉÍ ÏÔÌÉÞÉÊ (ËÁË \"vimdiff\")"
+
+#: main.c:2486
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tðÒÏÓÔÏÊ ÒÅÖÉÍ (ËÁË \"evim\", ÂÅÚÒÅÖÉÍÎÙÊ)"
+
+#: main.c:2487
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tôÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ (ËÁË \"view\")"
+
+#: main.c:2488
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tïÇÒÁÎÉÞÅÎÎÙÊ ÒÅÖÉÍ (ËÁË \"rvim\")"
+
+#: main.c:2489
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tâÅÚ ×ÏÚÍÏÖÎÏÓÔÉ ÓÏÈÒÁÎÅÎÉÑ ÉÚÍÅÎÅÎÉÊ (ÚÁÐÉÓÉ ÆÁÊÌÏ×)"
+
+#: main.c:2490
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tâÅÚ ×ÏÚÍÏÖÎÏÓÔÉ ×ÎÅÓÅÎÉÑ ÉÚÍÅÎÅÎÉÊ × ÔÅËÓÔ"
+
+#: main.c:2491
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tâÉÎÁÒÎÙÊ ÒÅÖÉÍ"
+
+#: main.c:2493
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tòÅÖÉÍ Lisp"
+
+#: main.c:2495
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tòÅÖÉÍ ÓÏ×ÍÅÓÔÉÍÏÓÔÉ Ó Vi: 'compatible'"
+
+#: main.c:2496
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tòÅÖÉÍ ÎÅÐÏÌÎÏÊ ÓÏ×ÍÅÓÔÉÍÏÓÔÉ Ó Vi: 'nocompatible'"
+
+#: main.c:2497
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tõÒÏ×ÅÎØ ÐÏÄÒÏÂÎÏÓÔÉ ÓÏÏÂÝÅÎÉÊ"
+
+#: main.c:2498
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tòÅÖÉÍ ÏÔÌÁÄËÉ"
+
+#: main.c:2499
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tâÅÚ Ó×ÏÐ-ÆÁÊÌÁ, ÉÓÐÏÌØÚÕÅÔÓÑ ÔÏÌØËÏ ÐÁÍÑÔØ"
+
+#: main.c:2500
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\t÷Ù×ÅÓÔÉ ÓÐÉÓÏË Ó×ÏÐ-ÆÁÊÌÏ× É ÚÁ×ÅÒÛÉÔØ ÒÁÂÏÔÕ"
+
+#: main.c:2501
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (Ó ÉÍÅÎÅÍ ÆÁÊÌÁ)\t÷ÏÓÓÔÁÎÏ×ÉÔØ Á×ÁÒÉÊÎÏ ÚÁ×ÅÒÛ£ÎÎÙÊ ÓÅÁÎÓ"
+
+#: main.c:2502
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tôÏ ÖÅ, ÞÔÏ É -r"
+
+#: main.c:2504
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tîÅ ÉÓÐÏÌØÚÏ×ÁÔØ newcli ÄÌÑ ÏÔËÒÙÔÉÑ ÏËÎÁ"
+
+#: main.c:2505
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <ÕÓÔÒÏÊÓÔ×Ï>\t\téÓÐÏÌØÚÏ×ÁÔØ ÄÌÑ I/O ÕËÁÚÁÎÎÏÅ <ÕÓÔÒÏÊÓÔ×Ï>"
+
+#: main.c:2508
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\t\túÁÐÕÓË × áÒÁÂÓËÏÍ ÒÅÖÉÍÅ"
+
+#: main.c:2511
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\túÁÐÕÓË × ÒÅÖÉÍÅ \"é×ÒÉÔ\""
+
+#: main.c:2514
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\túÁÐÕÓË × ÒÅÖÉÍÅ \"æÁÒÓÉ\""
+
+#: main.c:2516
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <ÔÅÒÍÉÎÁÌ>\tîÁÚÎÁÞÉÔØ ÕËÁÚÁÎÎÙÊ ÔÉÐ <ÔÅÒÍÉÎÁÌÁ>"
+
+#: main.c:2517
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\téÓÐÏÌØÚÏ×ÁÔØ <vimrc> ×ÍÅÓÔÏ ÌÀÂÙÈ ÆÁÊÌÏ× .vimrc"
+
+#: main.c:2519
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\téÓÐÏÌØÚÏ×ÁÔØ <gvimrc> ×ÍÅÓÔÏ ÌÀÂÙÈ ÆÁÊÌÏ× .gvimrc"
+
+#: main.c:2521
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tîÅ ÚÁÇÒÕÖÁÔØ ÓÃÅÎÁÒÉÉ ÍÏÄÕÌÅÊ"
+
+#: main.c:2522
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tïÔËÒÙÔØ N ÏËÏÎ (ÐÏ ÕÍÏÌÞÁÎÉÀ: ÐÏ ÏÄÎÏÍÕ ÎÁ ËÁÖÄÙÊ ÆÁÊÌ)"
+
+#: main.c:2523
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\tôÏ ÖÅ, ÞÔÏ É -o, ÎÏ Ó ×ÅÒÔÉËÁÌØÎÙÍ ÒÁÚÄÅÌÅÎÉÅÍ ÏËÏÎ"
+
+#: main.c:2524
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tîÁÞÁÔØ ÒÅÄÁËÔÉÒÏ×ÁÎÉÅ × ËÏÎÃÅ ÆÁÊÌÁ"
+
+#: main.c:2525
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\tîÁÞÁÔØ ÒÅÄÁËÔÉÒÏ×ÁÎÉÅ × ÓÔÒÏËÅ Ó ÎÏÍÅÒÏÍ <lnum>"
+
+#: main.c:2527
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <ËÏÍÁÎÄÁ>\t÷ÙÐÏÌÎÉÔØ <ËÏÍÁÎÄÕ> ÐÅÒÅÄ ÚÁÇÒÕÚËÏÊ ÆÁÊÌÁ vimrc"
+
+#: main.c:2529
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <ËÏÍÁÎÄÁ>\t\t÷ÙÐÏÌÎÉÔØ <ËÏÍÁÎÄÕ> ÐÏÓÌÅ ÚÁÇÒÕÚËÉ ÐÅÒ×ÏÇÏ ÆÁÊÌÁ"
+
+#: main.c:2530
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <ÓÅÁÎÓ>\t\tðÒÏÞÉÔÁÔØ ÓÃÅÎÁÒÉÊ <ÓÅÁÎÓÁ> ÐÏÓÌÅ ÚÁÇÒÕÚËÉ ÐÅÒ×ÏÇÏ ÆÁÊÌÁ"
+
+#: main.c:2531
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <ÓÃÅÎÁÒÉÊ>\tðÒÏÞÉÔÁÔØ ËÏÍÁÎÄÙ ïÂÙÞÎÏÇÏ ÒÅÖÉÍÁ ÉÚ ÆÁÊÌÁ <ÓÃÅÎÁÒÉÑ>"
+
+#: main.c:2532
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <ÓÃÅÎÁÒÉÊ>\täÏÂÁ×ÌÑÔØ ×ÓÅ ××ÅÄ£ÎÎÙÅ ËÏÍÁÎÄÙ × ÆÁÊÌ <ÓÃÅÎÁÒÉÑ>"
+
+#: main.c:2533
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <ÓÃÅÎÁÒÉÊ>\túÁÐÉÓÁÔØ ×ÓÅ ××ÅÄ£ÎÎÙÅ ËÏÍÁÎÄÙ × ÆÁÊÌ <ÓÃÅÎÁÒÉÑ>"
+
+#: main.c:2535
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tòÅÄÁËÔÉÒÏ×ÁÎÉÅ ÚÁÛÉÆÒÏ×ÁÎÎÙÈ ÆÁÊÌÏ×"
+
+#: main.c:2539
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <ÜËÒÁÎ>\tðÏÄÓÏÅÄÉÎÉÔØ vim Ë ÕËÁÚÁÎÎÏÍÕ ÓÅÒ×ÅÒÕ X"
+
+#: main.c:2541
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tîÅ ×ÙÐÏÌÎÑÔØ ÓÏÅÄÉÎÅÎÉÅ Ó ÓÅÒ×ÅÒÏÍ X"
+
+#: main.c:2544
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <ÆÁÊÌÙ>\tðÏ ×ÏÚÍÏÖÎÏÓÔÉ ÒÅÄÁËÔÉÒÏ×ÁÔØ <ÆÁÊÌÙ> ÎÁ ÓÅÒ×ÅÒÅ Vim"
+
+#: main.c:2545
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-silent <ÆÁÊÌÙ> ôÏ ÖÅ, ÎÏ ÂÅÚ ÖÁÌÏ ÎÁ ÏÔÓÕÔÓÔ×ÉÅ ÓÅÒ×ÅÒÁ"
+
+#: main.c:2546
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr ""
+"--remote-wait <ÆÁÊÌÙ> ôÏ ÖÅ, ÞÔÏ É --remote, ÎÏ Ó ÏÖÉÄÁÎÉÅÍ ÚÁ×ÅÒÛÅÎÉÑ"
+
+#: main.c:2547
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr ""
+"--remote-wait-silent <ÆÁÊÌÙ> ôÏ ÖÅ, ÎÏ ÂÅÚ ÖÁÌÏ ÎÁ ÏÔÓÕÔÓÔ×ÉÅ ÓÅÒ×ÅÒÁ"
+
+#: main.c:2548
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <ËÎÏÐËÉ>\tïÔÐÒÁ×ÉÔØ <ËÎÏÐËÉ> ÎÁ ÓÅÒ×ÅÒ Vim É ×ÙÊÔÉ"
+
+#: main.c:2549
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <×ÙÒÁÖ>\t÷ÙÞÉÓÌÉÔØ <×ÙÒÁÖ> ÎÁ ÓÅÒ×ÅÒÅ Vim É ÎÁÐÅÞÁÔÁÔØ"
+
+#: main.c:2550
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tðÏËÁÚÁÔØ ÓÐÉÓÏË ÉͣΠÓÅÒ×ÅÒÏ× Vim É ÚÁ×ÅÒÛÉÔØ ÒÁÂÏÔÕ"
+
+#: main.c:2551
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr ""
+"--servername <ÉÍÑ>\tïÔÐÒÁ×ÉÔØ ÎÁ/ÓÔÁÔØ ÓÅÒ×ÅÒÏÍ Vim Ó ÕËÁÚÁÎÎÙÍ <ÉÍÅÎÅÍ>"
+
+#: main.c:2554
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\téÓÐÏÌØÚÏ×ÁÔØ ×ÍÅÓÔÏ .viminfo ÆÁÊÌ <viminfo>"
+
+#: main.c:2556
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h ÉÌÉ --help\t÷Ù×ÅÓÔÉ ÓÐÒÁ×ËÕ (ÜÔÏ ÓÏÏÂÝÅÎÉÅ) É ÚÁ×ÅÒÛÉÔØ ÒÁÂÏÔÕ"
+
+#: main.c:2557
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\t÷Ù×ÅÓÔÉ ÉÎÆÏÒÍÁÃÉÀ Ï ×ÅÒÓÉÉ Vim É ÚÁ×ÅÒÛÉÔØ ÒÁÂÏÔÕ"
+
+#: main.c:2561
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"áÒÇÕÍÅÎÔÙ ÄÌÑ gvim (×ÅÒÓÉÑ Motif):\n"
+
+#: main.c:2565
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr ""
+"\n"
+"áÒÇÕÍÅÎÔÙ ÄÌÑ gvim (×ÅÒÓÉÑ neXtaw):\n"
+
+#: main.c:2567
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"áÒÇÕÍÅÎÔÙ ÄÌÑ gvim (×ÅÒÓÉÑ Athena):\n"
+
+#: main.c:2571
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <ÄÉÓÐÌÅÊ>\túÁÐÕÓÔÉÔØ vim ÎÁ ÕËÁÚÁÎÎÏÍ <ÄÉÓÐÌÅÅ>"
+
+#: main.c:2572
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\túÁÐÕÓÔÉÔØ vim × Ó×£ÒÎÕÔÏÍ ×ÉÄÅ"
+
+#: main.c:2574
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <ÉÍÑ>\t\téÓÐÏÌØÚÏ×ÁÔØ ÒÅÓÕÒÓ, ËÁË ÅÓÌÉ ÂÙ vim ÂÙÌ <ÉÍÅÎÅÍ>"
+
+#: main.c:2575
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (îÅ ÒÅÁÌÉÚÏ×ÁÎÏ)\n"
+
+#: main.c:2577
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr ""
+"-background <Ã×ÅÔ>\téÓÐÏÌØÚÏ×ÁÔØ ÕËÁÚÁÎÎÙÊ <Ã×ÅÔ> ÄÌÑ ÆÏÎÁ (ÔÁËÖÅ: -bg)"
+
+#: main.c:2578
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr ""
+"-foreground <Ã×ÅÔ>\téÓÐÏÌØÚÏ×ÁÔØ <Ã×ÅÔ> ÄÌÑ ÏÂÙÞÎÏÇÏ ÔÅËÓÔÁ (ÔÁËÖÅ: -fg)"
+
+#: main.c:2579 main.c:2599
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <ÛÒÉÆÔ>\t\téÓÐÏÌØÚÏ×ÁÔØ <ÛÒÉÆÔ> ÄÌÑ ÏÂÙÞÎÏÇÏ ÔÅËÓÔÁ (ÔÁËÖÅ: -fn)"
+
+#: main.c:2580
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <ÛÒÉÆÔ>\téÓÐÏÌØÚÏ×ÁÔØ <ÛÒÉÆÔ> ÄÌÑ ÖÉÒÎÏÇÏ ÔÅËÓÔÁ"
+
+#: main.c:2581
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <ÛÒÉÆÔ>\téÓÐÏÌØÚÏ×ÁÔØ <ÛÒÉÆÔ> ÄÌÑ ÎÁËÌÏÎÎÏÇÏ ÔÅËÓÔÁ"
+
+#: main.c:2582 main.c:2600
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr ""
+"-geometry <ÇÅÏÍÅÔÒÉÑ>\téÓÐÏÌØÚÏ×ÁÔØ ÎÁÞÁÌØÎÕÀ <ÇÅÏÍÅÔÒÉÀ> (ÔÁËÖÅ: -geom)"
+
+#: main.c:2583
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <ÛÉÒÉÎÁ>\téÓÐÏÌØÚÏ×ÁÔØ <ÛÉÒÉÎÕ> ÂÏÒÄÀÒÁ (ÔÁËÖÅ: -bw)"
+
+#: main.c:2584
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr ""
+"-scrollbarwidth <ÛÉÒÉÎÁ> éÓÐÏÌØÚÏ×ÁÔØ ÛÉÒÉÎÕ ÐÏÌÏÓÙ ÐÒÏËÒÕÔËÉ (ÔÁËÖÅ: -sw)"
+
+#: main.c:2586
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <×ÙÓÏÔÁ>\téÓÐÏÌØÚÏ×ÁÔØ <×ÙÓÏÔÕ> ÍÅÎÀ (ÔÁËÖÅ: -mh)"
+
+#: main.c:2588 main.c:2601
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\téÓÐÏÌØÚÏ×ÁÔØ ÉÎ×ÅÒÓÎÙÊ ×ÉÄÅÏÒÅÖÉÍ (ÔÁËÖÅ: -rv)"
+
+#: main.c:2589
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tîÅ ÉÓÐÏÌØÚÏ×ÁÔØ ÉÎ×ÅÒÓÎÙÊ ×ÉÄÅÏÒÅÖÉÍ (ÔÁËÖÅ: +rv)"
+
+#: main.c:2590
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <ÒÅÓÕÒÓ>\tõÓÔÁÎÏ×ÉÔØ ÕËÁÚÁÎÎÙÊ <ÒÅÓÕÒÓ>"
+
+#: main.c:2593
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"áÒÇÕÍÅÎÔÙ ÄÌÑ gvim (×ÅÒÓÉÑ RISC OS):\n"
+
+#: main.c:2594
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <ÞÉÓÌÏ>\tðÅÒ×ÏÎÁÞÁÌØÎÁÑ ÛÉÒÉÎÁ ÏËÎÁ × ËÏÌÏÎËÁÈ"
+
+#: main.c:2595
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <ÞÉÓÌÏ>\tðÅÒ×ÏÎÁÞÁÌØÎÁÑ ×ÙÓÏÔÁ ÏËÎÁ × ÓÔÒÏËÁÈ"
+
+#: main.c:2598
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"áÒÇÕÍÅÎÔÙ ÄÌÑ gvim (×ÅÒÓÉÑ GTK+):\n"
+
+#: main.c:2602
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr ""
+"-display <ÄÉÓÐÌÅÊ>\túÁÐÕÓÔÉÔØ vim ÎÁ ÕËÁÚÁÎÎÏÍ <ÄÉÓÐÌÅÅ> (ÔÁËÖÅ: --display)"
+
+#: main.c:2604
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr ""
+"--role <ÒÏÌØ>\tõÓÔÁÎÏ×ÉÔØ ÕÎÉËÁÌØÎÕÀ <ÒÏÌØ> ÄÌÑ ÉÄÅÎÔÉÆÉËÁÃÉÉ ÇÌÁ×ÎÏÇÏ ÏËÎÁ"
+
+#: main.c:2606
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tïÔËÒÙÔØ Vim ×ÎÕÔÒÉ ÄÒÕÇÏÇÏ ËÏÍÐÏÎÅÎÔÁ GTK"
+
+#: main.c:2609
+msgid "-P <parent title>\tOpen Vim inside parent application"
+msgstr "-P <ÚÁÇÏÌÏ×ÏË ÒÏÄÉÔÅÌÑ>\tïÔËÒÙÔØ Vim × ÒÏÄÉÔÅÌØÓËÏÍ ÐÒÉÌÏÖÅÎÉÉ"
+
+#: main.c:2847
+msgid "No display"
+msgstr "îÅÔ ÄÉÓÐÌÅÑ"
+
+#. Failed to send, abort.
+#: main.c:2862
+msgid ": Send failed.\n"
+msgstr ": ïÔÐÒÁ×ËÁ ÎÅ ÕÄÁÌÁÓØ.\n"
+
+#. Let vim start normally.
+#: main.c:2868
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": ïÔÐÒÁ×ËÁ ÎÅ ÕÄÁÌÁÓØ. ðÏÐÙÔËÁ ÍÅÓÔÎÏÇÏ ×ÙÐÏÌÎÅÎÉÑ\n"
+
+#: main.c:2906 main.c:2927
+#, c-format
+msgid "%d of %d edited"
+msgstr "ÏÔÒÅÄÁËÔÉÒÏ×ÁÎÏ %d ÉÚ %d"
+
+#: main.c:2949
+msgid "No display: Send expression failed.\n"
+msgstr "îÅÔ ÄÉÓÐÌÅÑ: ÏÔÐÒÁ×ËÁ ×ÙÒÁÖÅÎÉÑ ÎÅ ÕÄÁÌÁÓØ.\n"
+
+#: main.c:2961
+msgid ": Send expression failed.\n"
+msgstr ": ïÔÐÒÁ×ËÁ ×ÙÒÁÖÅÎÉÑ ÎÅ ÕÄÁÌÁÓØ.\n"
+
+#: mark.c:709
+msgid "No marks set"
+msgstr "îÅÔ ÕÓÔÁÎÏ×ÌÅÎÎÙÈ ÏÔÍÅÔÏË"
+
+#: mark.c:711
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: îÅÔ ÏÔÍÅÔÏË, ÓÏ×ÐÁÄÁÀÝÉÈ Ó \"%s\""
+
+#. Highlight title
+#: mark.c:722
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"ÏÔÍÅÔ ÓÔÒ ËÏÌ ÆÁÊÌ/ÔÅËÓÔ"
+
+#. Highlight title
+#: mark.c:760
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+"ÐÒÙÖÏË ÓÔÒ ËÏÌ ÆÁÊÌ/ÔÅËÓÔ"
+
+#. Highlight title
+#: mark.c:805
+msgid ""
+"\n"
+"change line col text"
+msgstr ""
+"\n"
+"ÉÚÍÅÎ. ÓÔÒ ËÏÌ ÔÅËÓÔ"
+
+#: mark.c:1281
+#, c-format
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# çÌÏÂÁÌØÎÙÅ ÏÔÍÅÔËÉ:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1316
+#, c-format
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# óÐÉÓÏË ÐÒÙÖËÏ× (ÓÎÁÞÁÌÁ ÂÏÌÅÅ Ó×ÅÖÉÅ):\n"
+
+#: mark.c:1412
+#, c-format
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# éÓÔÏÒÉÑ ÍÅÓÔÎÙÈ ÏÔÍÅÔÏË (ÏÔ ÂÏÌÅÅ Ó×ÅÖÉÈ Ë ÓÔÁÒÙÍ):\n"
+
+#: mark.c:1501
+msgid "Missing '>'"
+msgstr "ðÒÏÐÕÝÅÎÁ '>'"
+
+#: mbyte.c:467
+msgid "E543: Not a valid codepage"
+msgstr "E543: îÅÄÏÐÕÓÔÉÍÏÅ ÉÍÑ ËÏÄÉÒÏ×ËÉ"
+
+#: mbyte.c:4431
+msgid "E284: Cannot set IC values"
+msgstr "E284: îÅ×ÏÚÍÏÖÎÏ ÎÁÚÎÁÞÉÔØ ÚÎÁÞÅÎÉÑ ËÏÎÔÅËÓÔÁ ××ÏÄÁ"
+
+#: mbyte.c:4583
+msgid "E285: Failed to create input context"
+msgstr "E285: îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ËÏÎÔÅËÓÔ ××ÏÄÁ"
+
+#: mbyte.c:4741
+msgid "E286: Failed to open input method"
+msgstr "E286: îÅÕÄÁÞÎÁÑ ÐÏÐÙÔËÁ ÏÔËÒÙÔØ ÍÅÔÏÄ ××ÏÄÁ"
+
+#: mbyte.c:4752
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr ""
+"E287: ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÎÅ×ÏÚÍÏÖÎÏ ÎÁÚÎÁÞÉÔØ ÏÂÒ. ×ÙÚÏ× ÕÎÉÞÔÏÖÅÎÉÑ ÍÅÔÏÄÁ "
+"××ÏÄÁ"
+
+#: mbyte.c:4758
+msgid "E288: input method doesn't support any style"
+msgstr "E288: ÍÅÔÏÄ ××ÏÄÁ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÓÔÉÌÉ"
+
+#: mbyte.c:4815
+msgid "E289: input method doesn't support my preedit type"
+msgstr ""
+"E289: ÍÅÔÏÄ ××ÏÄÁ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÍÏÊ ÔÉÐ ÐÒÅÄ×ÁÒÉÔÅÌØÎÏÇÏ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ"
+
+#: mbyte.c:4889
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: ÓÔÉÌØ \"ÎÁÄ ÍÅÓÔÏÍ\" ÔÒÅÂÕÅÔ ÕËÁÚÁÎÉÑ ÛÒÉÆÔÏ×ÏÇÏ ÎÁÂÏÒÁ"
+
+#: mbyte.c:4925
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr ""
+"E291: GTK+ ÂÏÌÅÅ ÒÁÎÎÅÊ ×ÅÒÓÉÉ, ÞÅÍ 1.2.3. ïÂÌÁÓÔØ ÓÏÓÔÏÑÎÉÑ ÎÅ ÒÁÂÏÔÁÅÔ."
+
+#: mbyte.c:5232
+msgid "E292: Input Method Server is not running"
+msgstr "E292: óÅÒ×ÅÒ ÍÅÔÏÄÁ ××ÏÄÁ ÎÅ ÚÁÐÕÝÅÎ"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: ÂÌÏË ÎÅ ÚÁÂÌÏËÉÒÏ×ÁÎ"
+
+#: memfile.c:1005
+msgid "E294: Seek error in swap file read"
+msgstr "E294: ïÛÉÂËÁ ÐÏÉÓËÁ ÐÒÉ ÞÔÅÎÉÉ Ó×ÏÐ-ÆÁÊÌÁ"
+
+#: memfile.c:1010
+msgid "E295: Read error in swap file"
+msgstr "E295: ïÛÉÂËÁ ÞÔÅÎÉÑ Ó×ÏÐ-ÆÁÊÌÁ"
+
+#: memfile.c:1062
+msgid "E296: Seek error in swap file write"
+msgstr "E296: ïÛÉÂËÁ ÐÏÉÓËÁ ÐÒÉ ÚÁÐÉÓÉ Ó×ÏÐ-ÆÁÊÌÁ"
+
+#: memfile.c:1080
+msgid "E297: Write error in swap file"
+msgstr "E297: ïÛÉÂËÁ ÐÒÉ ÚÁÐÉÓÉ Ó×ÏÐ-ÆÁÊÌÁ"
+
+#: memfile.c:1277
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr ""
+"E300: ó×ÏÐ-ÆÁÊÌ ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ (ÁÔÁËÁ Ó ÉÓÐÏÌØÚÏ×ÁÎÉÅÍ ÓÉÍ×ÏÌØÎÏÊ ÓÓÙÌËÉ?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: îÅ ÐÏÌÕÞÅÎ ÂÌÏË ÎÏÍÅÒ 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: îÅ ÐÏÌÕÞÅÎ ÂÌÏË ÎÏÍÅÒ 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: îÅ ÐÏÌÕÞÅÎ ÂÌÏË ÎÏÍÅÒ 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: ïÊ, ÐÏÔÅÒÑÌÓÑ Ó×ÏÐ-ÆÁÊÌ!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: îÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÉÍÅÎÏ×ÁÔØ Ó×ÏÐ-ÆÁÊÌ"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr ""
+"E303: îÅ ÕÄÁÌÏÓØ ÏÔËÒÙÔØ Ó×ÏÐ-ÆÁÊÌ ÄÌÑ \"%s\", ×ÏÓÓÔÁÎÏ×ÌÅÎÉÅ ÎÅ×ÏÚÍÏÖÎÏ"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: îÅ ÐÏÌÕÞÅÎ ÂÌÏË 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: ó×ÏÐ-ÆÁÊÌ ÄÌÑ %s ÎÅ ÎÁÊÄÅÎ"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr ""
+"÷×ÅÄÉÔÅ ÎÏÍÅÒ Ó×ÏÐ-ÆÁÊÌÁ, ËÏÔÏÒÙÊ ÓÌÅÄÕÅÔ ÉÓÐÏÌØÚÏ×ÁÔØ (0 ÄÌÑ ×ÙÈÏÄÁ): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: îÅ ÍÏÇÕ ÏÔËÒÙÔØ %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ÂÌÏË 0 ÉÚ "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"îÅÔ ÉÚÍÅÎÅÎÉÊ, ÉÌÉ Vim ÎÅ ÓÍÏÇ ÏÂÎÏ×ÉÔØ Ó×ÏÐ-ÆÁÊÌ"
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " ÎÅÌØÚÑ ÉÓÐÏÌØÚÏ×ÁÔØ × ÄÁÎÎÏÊ ×ÅÒÓÉÉ Vim.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "éÓÐÏÌØÚÕÊÔÅ Vim ×ÅÒÓÉÉ 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s ÎÅ Ñ×ÌÑÅÔÓÑ Ó×ÏÐ-ÆÁÊÌÏÍ Vim"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " ÎÅÌØÚÑ ÉÓÐÏÌØÚÏ×ÁÔØ ÎÁ ÜÔÏÍ ËÏÍÐØÀÔÅÒÅ.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "æÁÊÌ ÂÙÌ ÓÏÚÄÁÎ "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"ÌÉÂÏ ÆÁÊÌ ÂÙÌ ÐÏ×ÒÅÖÄ£Î."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "éÓÐÏÌØÚÕÅÔÓÑ Ó×ÏÐ-ÆÁÊÌ \"%s\""
+
+#: memline.c:909
+#, c-format
+msgid "Original file \"%s\""
+msgstr "éÓÈÏÄÎÙÊ ÆÁÊÌ \"%s\""
+
+#: memline.c:922
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÉÓÈÏÄÎÙÊ ÆÁÊÌ ÍÏÇ ÂÙÔØ ÉÚÍÅΣÎ"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ÂÌÏË 1 ÉÚ %s"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???ïôóõôóô÷õåô íîïçï óôòïë"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???îåðòá÷éìøîïå úîáþåîéå óþåôþéëá óôòïë"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???ðõóôïê âìïë"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???ïôóõôóô÷õàô óôòïëé"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ÎÅÐÒÁ×ÉÌØÎÙÊ ÂÌÏË 1 ID (%s ÎÅ Ñ×ÌÑÅÔÓÑ ÆÁÊÌÏÍ .swp?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???ðòïðõýåî âìïë"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "???ÓÔÒÏËÉ ÍÏÇÕÔ ÂÙÔØ ÉÓÐÏÒÞÅÎÙ ÏÔÓÀÄÁ ÄÏ ???ëïîãá"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "???ÓÔÒÏËÉ ÍÏÇÌÉ ÂÙÔØ ×ÓÔÁ×ÌÅÎÙ ÉÌÉ ÕÄÁÌÅÎÙ ÏÔÓÀÄÁ ÄÏ ???ëïîãá"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???ëïîåã"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: ÷ÏÓÓÔÁÎÏ×ÌÅÎÉÅ ÐÒÅÒ×ÁÎÏ"
+
+#: memline.c:1148
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr ""
+"E312: ÷Ï ×ÒÅÍÑ ×ÏÓÓÔÁÎÏ×ÌÅÎÉÑ ÏÂÎÁÒÕÖÅÎÙ ÏÛÉÂËÉ; ÓÍ. ÓÔÒÏËÉ, ÎÁÞÉÎÁÀÝÉÅÓÑ "
+"Ó ???"
+
+#: memline.c:1150
+msgid "See \":help E312\" for more information."
+msgstr "óÍ. ÄÏÐÏÌÎÉÔÅÌØÎÕÀ ÉÎÆÏÒÍÁÃÉÀ × ÓÐÒÁ×ÏÞÎÉËÅ (\":help E312\")"
+
+#: memline.c:1155
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "÷ÏÓÓÔÁÎÏ×ÌÅÎÉÅ ÚÁ×ÅÒÛÅÎÏ. ðÒÏ×ÅÒØÔÅ, ×Ó£ ÌÉ × ÐÏÒÑÄËÅ."
+
+#: memline.c:1156
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(íÏÖÅÔÅ ÚÁÐÉÓÁÔØ ÆÁÊÌ ÐÏÄ ÄÒÕÇÉÍ ÉÍÅÎÅÍ É ÓÒÁ×ÎÉÔØ ÅÇÏ Ó ÉÓÈÏÄÎÙÍ\n"
+
+#: memline.c:1157
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "ÆÁÊÌÏÍ ÐÒÉ ÐÏÍÏÝÉ ÐÒÏÇÒÁÍÍÙ diff).\n"
+
+#: memline.c:1158
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"úÁÔÅÍ ÕÄÁÌÉÔÅ ÆÁÊÌ .swp.\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1214
+msgid "Swap files found:"
+msgstr "ïÂÎÁÒÕÖÅÎÙ Ó×ÏÐ-ÆÁÊÌÙ:"
+
+#: memline.c:1392
+msgid " In current directory:\n"
+msgstr " ÷ ÔÅËÕÝÅÍ ËÁÔÁÌÏÇÅ:\n"
+
+#: memline.c:1394
+msgid " Using specified name:\n"
+msgstr " ó ÕËÁÚÁÎÎÙÍ ÉÍÅÎÅÍ:\n"
+
+#: memline.c:1398
+msgid " In directory "
+msgstr " ÷ ËÁÔÁÌÏÇÅ "
+
+#: memline.c:1416
+msgid " -- none --\n"
+msgstr " -- ÎÅÔ --\n"
+
+#: memline.c:1488
+msgid " owned by: "
+msgstr " ×ÌÁÄÅÌÅÃ: "
+
+#: memline.c:1490
+msgid " dated: "
+msgstr " ÄÁÔÁ: "
+
+#: memline.c:1494 memline.c:3684
+msgid " dated: "
+msgstr " ÄÁÔÁ: "
+
+#: memline.c:1510
+msgid " [from Vim version 3.0]"
+msgstr " [ÏÔ Vim ×ÅÒÓÉÉ 3.0]"
+
+#: memline.c:1514
+msgid " [does not look like a Vim swap file]"
+msgstr " [ÎÅ Ñ×ÌÑÅÔÓÑ Ó×ÏÐ-ÆÁÊÌÏÍ Vim]"
+
+#: memline.c:1518
+msgid " file name: "
+msgstr " ÉÍÑ ÆÁÊÌÁ: "
+
+#: memline.c:1524
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" ÉÚÍÅΣÎ: "
+
+#: memline.c:1525
+msgid "YES"
+msgstr "äá"
+
+#: memline.c:1525
+msgid "no"
+msgstr "ÎÅÔ"
+
+#: memline.c:1529
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" ÐÏÌØÚÏ×ÁÔÅÌØ: "
+
+#: memline.c:1536
+msgid " host name: "
+msgstr " ËÏÍÐØÀÔÅÒ: "
+
+#: memline.c:1538
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" ËÏÍÐØÀÔÅÒ: "
+
+#: memline.c:1544
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ÐÒÏÃÅÓÓ: "
+
+#: memline.c:1550
+msgid " (still running)"
+msgstr " (ÅÝ£ ×ÙÐÏÌÎÑÅÔÓÑ)"
+
+#: memline.c:1562
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [ÎÅ ÐÒÉÇÏÄÅÎ ÄÌÑ ÉÓÐÏÌØÚÏ×ÁÎÉÑ Ó ÄÁÎÎÏÊ ×ÅÒÓÉÅÊ Vim]"
+
+#: memline.c:1565
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [ÎÅ ÐÒÉÇÏÄÅÎ ÄÌÑ ÉÓÐÏÌØÚÏ×ÁÎÉÑ ÎÁ ÜÔÏÍ ËÏÍÐØÀÔÅÒÅ]"
+
+#: memline.c:1570
+msgid " [cannot be read]"
+msgstr " [ÎÅ ÞÉÔÁÅÔÓÑ]"
+
+#: memline.c:1574
+msgid " [cannot be opened]"
+msgstr " [ÎÅ ÏÔËÒÙ×ÁÅÔÓÑ]"
+
+#: memline.c:1764
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: îÅ×ÏÚÍÏÖÎÏ ÏÂÎÏ×ÉÔØ Ó×ÏÐ-ÆÁÊÌ, ÐÏÓËÏÌØËÕ ÏÎ ÎÅ ÏÂÎÁÒÕÖÅÎ"
+
+#: memline.c:1817
+msgid "File preserved"
+msgstr "ó×ÏÐ-ÆÁÊÌ ÏÂÎÏ×Ì£Î"
+
+#: memline.c:1819
+msgid "E314: Preserve failed"
+msgstr "E314: îÅÕÄÁÞÎÁÑ ÐÏÐÙÔËÁ ÏÂÎÏ×ÌÅÎÉÑ Ó×ÏÐ-ÆÁÊÌÁ"
+
+#: memline.c:1890
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: ÎÅÐÒÁ×ÉÌØÎÏÅ ÚÎÁÞÅÎÉÅ lnum: %ld"
+
+#: memline.c:1916
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: ÎÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÓÔÒÏËÕ %ld"
+
+#: memline.c:2306
+msgid "E317: pointer block id wrong 3"
+msgstr "ÎÅÐÒÁ×ÉÌØÎÏÅ ÚÎÁÞÅÎÉÅ ÕËÁÚÁÔÅÌÑ ÂÌÏËÁ 3"
+
+#: memline.c:2386
+msgid "stack_idx should be 0"
+msgstr "ÚÎÁÞÅÎÉÅ stack_idx ÄÏÌÖÎÏ ÂÙÔØ ÒÁ×ÎÏ 0"
+
+#: memline.c:2448
+msgid "E318: Updated too many blocks?"
+msgstr "E318: ïÂÎÏ×ÌÅÎÏ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÂÌÏËÏ×?"
+
+#: memline.c:2630
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: ÎÅÐÒÁ×ÉÌØÎÏÅ ÚÎÁÞÅÎÉÅ ÕËÁÚÁÔÅÌÑ ÂÌÏËÁ 4"
+
+#: memline.c:2657
+msgid "deleted block 1?"
+msgstr "ÕÄẠ́ΠÂÌÏË 1?"
+
+#: memline.c:2857
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: óÔÒÏËÁ %ld ÎÅ ÏÂÎÁÒÕÖÅÎÁ"
+
+#: memline.c:3100
+msgid "E317: pointer block id wrong"
+msgstr "E317: ÎÅÐÒÁ×ÉÌØÎÏÅ ÚÎÁÞÅÎÉÅ ÕËÁÚÁÔÅÌÑ ÂÌÏËÁ"
+
+#: memline.c:3116
+msgid "pe_line_count is zero"
+msgstr "ÚÎÁÞÅÎÉÅ pe_line_count ÒÁ×ÎÏ ÎÕÌÀ"
+
+#: memline.c:3145
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: ÎÏÍÅÒ ÓÔÒÏËÉ ÚÁ ÐÒÅÄÅÌÁÍÉ ÄÉÁÐÁÚÏÎÁ: %ld"
+
+#: memline.c:3149
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: ÎÅÐÒÁ×ÉÌØÎÏÅ ÚÎÁÞÅÎÉÅ ÓÞ£ÔÞÉËÁ ÓÔÒÏË × ÂÌÏËÅ %ld"
+
+#: memline.c:3198
+msgid "Stack size increases"
+msgstr "òÁÚÍÅÒ ÓÔÅËÁ Õ×ÅÌÉÞÅÎ"
+
+#: memline.c:3244
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: ÎÅÐÒÁ×ÉÌØÎÏÅ ÚÎÁÞÅÎÉÅ ÕËÁÚÁÔÅÌÑ ÂÌÏËÁ 2"
+
+#: memline.c:3674
+msgid "E325: ATTENTION"
+msgstr "E325: ÷îéíáîéå"
+
+#: memline.c:3675
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"ïÂÎÁÒÕÖÅÎ Ó×ÏÐ-ÆÁÊÌ Ó ÉÍÅÎÅÍ \""
+
+#: memline.c:3679
+msgid "While opening file \""
+msgstr "ðÒÉ ÏÔËÒÙÔÉÉ ÆÁÊÌÁ: \""
+
+#: memline.c:3688
+msgid " NEWER than swap file!\n"
+msgstr " âÏÌÅÅ ó÷åöéê, ÞÅÍ Ó×ÏÐ-ÆÁÊÌ!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3692
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) ÷ÏÚÍÏÖÎÏ, ÒÅÄÁËÔÉÒÏ×ÁÎÉÅ ÆÁÊÌÁ ×ÙÐÏÌÎÑÅÔÓÑ × ÄÒÕÇÏÊ ÐÒÏÇÒÁÍÍÅ.\n"
+" åÓÌÉ ÜÔÏ ÔÁË, ÔÏ ÂÕÄØÔÅ ×ÎÉÍÁÔÅÌØÎÙ ÐÒÉ ×ÎÅÓÅÎÉÉ ÉÚÍÅÎÅÎÉÊ,\n"
+" ÞÔÏÂÙ Õ ×ÁÓ ÎÅ ÐÏÑ×ÉÌÏÓØ Ä×Á ÒÁÚÎÙÈ ×ÁÒÉÁÎÔÁ ÏÄÎÏÇÏ É ÔÏÇÏ ÖÅ ÆÁÊÌÁ.\n"
+
+#: memline.c:3693
+msgid " Quit, or continue with caution.\n"
+msgstr " úÁ×ÅÒÛÉÔÅ ÒÁÂÏÔÕ ÉÌÉ ÐÒÏÄÏÌÖÁÊÔÅ Ó ÏÓÔÏÒÏÖÎÏÓÔØÀ.\n"
+
+#: memline.c:3694
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) ðÒÅÄÙÄÕÝÉÊ ÓÅÁÎÓ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ ÜÔÏÇÏ ÆÁÊÌÁ ÚÁ×ÅÒۣΠÁ×ÁÒÉÊÎÏ.\n"
+
+#: memline.c:3695
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " ÷ ÜÔÏÍ ÓÌÕÞÁÅ, ÉÓÐÏÌØÚÕÊÔÅ ËÏÍÁÎÄÕ \":recover\" ÉÌÉ \"vim -r "
+
+#: memline.c:3697
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" ÄÌÑ ×ÏÓÓÔÁÎÏ×ÌÅÎÉÑ ÉÚÍÅÎÅÎÉÊ (ÓÍ. \":help ×ÏÓÓÔÁÎÏ×ÌÅÎÉÅ\").\n"
+
+#: memline.c:3698
+msgid " If you did this already, delete the swap file \""
+msgstr " åÓÌÉ ×Ù ÕÖÅ ×ÙÐÏÌÎÑÌÉ ÜÔÕ ÏÐÅÒÁÃÉÀ, ÕÄÁÌÉÔÅ Ó×ÏÐ-ÆÁÊÌ \""
+
+#: memline.c:3700
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" ÞÔÏÂÙ ÉÚÂÅÖÁÔØ ÐÏÑ×ÌÅÎÉÑ ÜÔÏÇÏ ÓÏÏÂÝÅÎÉÑ × ÂÕÄÕÝÅÍ.\n"
+
+#: memline.c:3714 memline.c:3718
+msgid "Swap file \""
+msgstr "ó×ÏÐ-ÆÁÊÌ \""
+
+#: memline.c:3715 memline.c:3721
+msgid "\" already exists!"
+msgstr "\" ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ!"
+
+#: memline.c:3724
+msgid "VIM - ATTENTION"
+msgstr "VIM - ÷îéíáîéå"
+
+#: memline.c:3726
+msgid "Swap file already exists!"
+msgstr "ó×ÏÐ-ÆÁÊÌ ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ!"
+
+#: memline.c:3730
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort"
+msgstr ""
+"&O ïÔËÒÙÔØ ÄÌÑ ÞÔÅÎÉÑ\n"
+"&E òÅÄÁËÔÉÒÏ×ÁÔØ\n"
+"&R ÷ÏÓÓÔÁÎÏ×ÉÔØ\n"
+"&Q ÷ÙÈÏÄ\n"
+"&A ðÒÅÒ×ÁÔØ"
+
+#: memline.c:3732
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Abort\n"
+"&Delete it"
+msgstr ""
+"&O ïÔËÒÙÔØ ÄÌÑ ÞÔÅÎÉÑ\n"
+"&E òÅÄÁËÔÉÒÏ×ÁÔØ\n"
+"&R ÷ÏÓÓÔÁÎÏ×ÉÔØ\n"
+"&Q ÷ÙÈÏÄ\n"
+"&A ðÒÅÒ×ÁÔØ\n"
+"&D õÄÁÌÉÔØ"
+
+#: memline.c:3789
+msgid "E326: Too many swap files found"
+msgstr "E326: ïÂÎÁÒÕÖÅÎÏ ÓÌÉÛËÏÍ ÍÎÏÇÏ Ó×ÏÐ-ÆÁÊÌÏ×"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: ëÏÍÐÏÎÅÎÔ ÐÕÔÉ Ë ÜÌÅÍÅÎÔÕ ÍÅÎÀ ÎÅ Ñ×ÌÑÅÔÓÑ ÐÏÄÍÅÎÀ"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: íÅÎÀ × ÜÔÏÍ ÒÅÖÉÍÅ ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: îÅÔ ÍÅÎÀ Ó ÔÁËÉÍ ÉÍÅÎÅÍ"
+
+#: menu.c:525
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: ðÕÔØ Ë ÍÅÎÀ ÎÅ ÄÏÌÖÅÎ ×ÅÓÔÉ Ë ÐÏÄÍÅÎÀ"
+
+#: menu.c:564
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: üÌÅÍÅÎÔÙ ÍÅÎÀ ÎÅÌØÚÑ ÄÏÂÁ×ÌÑÔØ ÎÅÐÏÓÒÅÄÓÔ×ÅÎÎÏ × ÐÏÌÏÓËÕ ÍÅÎÀ"
+
+#: menu.c:570
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: òÁÚÄÅÌÉÔÅÌÉ ÎÅ ÍÏÇÕÔ ÂÙÔØ ËÏÍÐÏÎÅÎÔÏÍ ÐÕÔÉ Ë ÍÅÎÀ"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1097
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- íÅÎÀ ---"
+
+#: menu.c:2019
+msgid "Tear off this menu"
+msgstr "ïÔÏÒ×ÁÔØ ÜÔÏ ÍÅÎÀ"
+
+#: menu.c:2084
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: ðÕÔØ Ë ÍÅÎÀ ÄÏÌÖÅÎ ×ÅÓÔÉ Ë ÜÌÅÍÅÎÔÕ ÍÅÎÀ"
+
+#: menu.c:2104
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: íÅÎÀ ÎÅ ÎÁÊÄÅÎÏ: %s"
+
+#: menu.c:2173
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: íÅÎÀ ÎÅ ÏÐÒÅÄÅÌÅÎÏ ÄÌÑ ÒÅÖÉÍÁ %s"
+
+#: menu.c:2211
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: ðÕÔØ Ë ÍÅÎÀ ÄÏÌÖÅÎ ×ÅÓÔÉ Ë ÐÏÄÍÅÎÀ"
+
+#: menu.c:2232
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: íÅÎÀ ÎÅ ÎÁÊÄÅÎÏ -- ÐÒÏ×ÅÒØÔÅ ÉÍÅÎÁ ÍÅÎÀ"
+
+#: message.c:414
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "ïÂÎÁÒÕÖÅÎÁ ÏÛÉÂËÁ ÐÒÉ ÏÂÒÁÂÏÔËÅ %s:"
+
+#: message.c:440
+#, c-format
+msgid "line %4ld:"
+msgstr "ÓÔÒÏËÁ %4ld:"
+
+#: message.c:647
+msgid "[string too long]"
+msgstr "[ÓÌÉÛËÏÍ ÄÌÉÎÎÁÑ ÓÔÒÏËÁ]"
+
+#: message.c:797
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr ""
+"ðÅÒÅ×ÏÄ ÓÏÏÂÝÅÎÉÊ ÎÁ ÒÕÓÓËÉÊ ÑÚÙË: ÷ÁÓÉÌÉÊ òÁÇÏÚÉÎ <vrr@users.sourceforge."
+"net>"
+
+#: message.c:1025
+msgid "Interrupt: "
+msgstr "ðÒÅÒÙ×ÁÎÉÅ: "
+
+#: message.c:1028
+msgid "Hit ENTER to continue"
+msgstr "äÌÑ ÐÒÏÄÏÌÖÅÎÉÑ ÎÁÖÍÉÔÅ ENTER"
+
+#: message.c:1030
+msgid "Hit ENTER or type command to continue"
+msgstr "äÌÑ ÐÒÏÄÏÌÖÅÎÉÑ ÎÁÖÍÉÔÅ ENTER ÉÌÉ ××ÅÄÉÔÅ ËÏÍÁÎÄÕ"
+
+#: message.c:2351
+msgid "-- More --"
+msgstr "-- ðÒÏÄÏÌÖÅÎÉÅ ÓÌÅÄÕÅÔ --"
+
+#: message.c:2354
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: ÓÔÒÏËÁ, SPACE/b: ÓÔÒÁÎÉÃÁ, d/u: ÐÏÌÓÔÒÁÎÉÃÙ, q: ×ÙÈÏÄ)"
+
+#: message.c:2355
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: ÓÔÒÏËÁ, SPACE: ÓÔÒÁÎÉÃÁ, d: ÐÏÌÓÔÒÁÎÉÃÙ, q: ×ÙÈÏÄ)"
+
+#: message.c:2976 message.c:2991
+msgid "Question"
+msgstr "÷ÏÐÒÏÓ"
+
+#: message.c:2978
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&äÁ\n"
+"&îÅÔ"
+
+#: message.c:3011
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&äÁ\n"
+"&îÅÔ\n"
+"óÏÈÒÁÎÉÔØ &×ÓÅ\n"
+"&ðÏÔÅÒÑÔØ ×ÓÅ\n"
+"ï&ÔÍÅÎÁ"
+
+#: message.c:3052
+msgid "Save File dialog"
+msgstr "óÏÈÒÁÎÅÎÉÅ ÆÁÊÌÁ"
+
+#: message.c:3054
+msgid "Open File dialog"
+msgstr "ïÔËÒÙÔÉÅ ÆÁÊÌÁ"
+
+#. TODO: non-GUI file selector here
+#: message.c:3125
+msgid "E338: Sorry, no file browser in console mode"
+msgstr ""
+"E338: éÚ×ÉÎÉÔÅ, ÎÏ × ËÏÎÓÏÌØÎÏÍ ÒÅÖÉÍÅ ÎÅÔ ÐÒÏ×ÏÄÎÉËÁ ÐÏ ÆÁÊÌÏ×ÏÊ ÓÉÓÔÅÍÅ"
+
+#: misc1.c:2773
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: éÚÍÅÎÅÎÉÅ ÆÁÊÌÁ Ó ÐÒÁ×ÁÍÉ ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ"
+
+#: misc1.c:3021
+msgid "1 more line"
+msgstr "äÏÂÁ×ÌÅÎÁ ÏÄÎÁ ÓÔÒÏËÁ"
+
+#: misc1.c:3023
+msgid "1 line less"
+msgstr "õÄÁÌÅÎÁ ÏÄÎÁ ÓÔÒÏËÁ"
+
+#: misc1.c:3028
+#, c-format
+msgid "%ld more lines"
+msgstr "äÏÂÁ×ÌÅÎÏ ÓÔÒÏË: %ld"
+
+#: misc1.c:3030
+#, c-format
+msgid "%ld fewer lines"
+msgstr "õÄÁÌÅÎÏ ÓÔÒÏË: %ld"
+
+#: misc1.c:3033
+msgid " (Interrupted)"
+msgstr " (ðÒÅÒ×ÁÎÏ)"
+
+#: misc1.c:7588
+msgid "Vim: preserving files...\n"
+msgstr "Vim: ÓÏÈÒÁÎÑÀÔÓÑ ÆÁÊÌÙ...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:7598
+msgid "Vim: Finished.\n"
+msgstr "Vim: çÏÔÏ×Ï.\n"
+
+#: misc2.c:695 misc2.c:711
+#, c-format
+msgid "ERROR: "
+msgstr "ïûéâëá: "
+
+#: misc2.c:715
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[ÂÁÊÔ] ×ÓÅÇÏ ×ÙÄÅÌ.-ÏÓ×ÏÂ. %lu-%lu, ÉÓÐÏÌØÚ. %lu, ÍÁËÓ. ÉÓÐÏÌØÚ. %lu\n"
+
+#: misc2.c:717
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[×ÙÚÏ×Ù] re/malloc() ×ÓÅÇÏ %lu, free() ×ÓÅÇÏ %lu\n"
+"\n"
+
+#: misc2.c:772
+msgid "E340: Line is becoming too long"
+msgstr "E340: óÔÒÏËÁ ÓÔÁÎÏ×ÉÔÓÑ ÓÌÉÛËÏÍ ÄÌÉÎÎÏÊ"
+
+#: misc2.c:816
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: ÷ÎÕÔÒÅÎÎÑÑ ÏÛÉÂËÁ: lalloc(%ld, )"
+
+#: misc2.c:924
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: îÅ È×ÁÔÁÅÔ ÐÁÍÑÔÉ! (×ÙÄÅÌÑÅÔÓÑ %lu ÂÁÊÔ)"
+
+#: misc2.c:2594
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "÷ÙÚÏ× ÏÂÏÌÏÞËÉ ÄÌÑ ÉÓÐÏÌÎÅÎÉÑ: \"%s\""
+
+#: misc2.c:2816
+msgid "E545: Missing colon"
+msgstr "E545: ðÒÏÐÕÝÅÎÏ Ä×ÏÅÔÏÞÉÅ"
+
+#: misc2.c:2818 misc2.c:2845
+msgid "E546: Illegal mode"
+msgstr "E546: îÅÄÏÐÕÓÔÉÍÙÊ ÒÅÖÉÍ"
+
+#: misc2.c:2884
+msgid "E547: Illegal mouseshape"
+msgstr "E547: îÅÄÏÐÕÓÔÉÍÁÑ ÆÏÒÍÁ ËÕÒÓÏÒÁ"
+
+#: misc2.c:2924
+msgid "E548: digit expected"
+msgstr "E548: ÔÒÅÂÕÅÔÓÑ ××ÅÓÔÉ ÃÉÆÒÕ"
+
+#: misc2.c:2929
+msgid "E549: Illegal percentage"
+msgstr "E549: îÅÄÏÐÕÓÔÉÍÏÅ ÚÎÁÞÅÎÉÅ ÐÒÏÃÅÎÔÏ×"
+
+#: misc2.c:3239
+msgid "Enter encryption key: "
+msgstr "÷×ÅÄÉÔÅ ÐÁÒÏÌØ ÄÌÑ ÛÉÆÒÏ×ÁÎÉÑ: "
+
+#: misc2.c:3240
+msgid "Enter same key again: "
+msgstr " ðÏ×ÔÏÒÉÔÅ ××ÏÄ ÐÁÒÏÌÑ:"
+
+#: misc2.c:3250
+msgid "Keys don't match!"
+msgstr "÷×ÅÄ£ÎÎÙÅ ÐÁÒÏÌÉ ÎÅ ÓÏ×ÐÁÄÁÀÔ!"
+
+#: misc2.c:3799
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: îÅÐÒÁ×ÉÌØÎÏ ÚÁÄÁÎ ÐÕÔØ: '**[ÞÉÓÌÏ]' ÄÏÌÖÎÏ ÂÙÔØ ÌÉÂÏ × ËÏÎÃÅ ÐÕÔÉ, "
+"ÌÉÂÏ ÚÁ ÎÉÍ ÄÏÌÖÎÏ ÓÌÅÄÏ×ÁÔØ '%s'"
+
+#: misc2.c:5078
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: ëÁÔÁÌÏÇ \"%s\" ÎÅ ÎÁÊÄÅÎ × ÐÕÔÉ ÄÌÑ ÓÍÅÎÙ ËÁÔÁÌÏÇÁ"
+
+#: misc2.c:5081
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: æÁÊÌ \"%s\" × ÉÚ×ÅÓÔÎÙÈ ËÁÔÁÌÏÇÁÈ ÎÅ ÎÁÊÄÅÎ"
+
+#: misc2.c:5087
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: ÷ ÐÕÔÉ ÓÍÅÎÙ ËÁÔÁÌÏÇÁ ÂÏÌØÛÅ ÎÅÔ ËÁÔÁÌÏÇÏ× \"%s\""
+
+#: misc2.c:5090
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: ÷ ÉÚ×ÅÓÔÎÙÈ ËÁÔÁÌÏÇÁÈ ÂÏÌØÛÅ ÎÅÔ ÆÁÊÌÏ× \"%s\""
+
+#: misc2.c:5324
+msgid "E550: Missing colon"
+msgstr "E550: ðÒÏÐÕÝÅÎÏ Ä×ÏÅÔÏÞÉÅ"
+
+#: misc2.c:5336
+msgid "E551: Illegal component"
+msgstr "E551: îÅÄÏÐÕÓÔÉÍÙÊ ËÏÍÐÏÎÅÎÔ"
+
+#: misc2.c:5344
+msgid "E552: digit expected"
+msgstr "E552: ôÒÅÂÕÅÔÓÑ ÕËÁÚÁÔØ ÃÉÆÒÕ"
+
+#. Get here when the server can't be found.
+#: netbeans.c:396
+msgid "Cannot connect to Netbeans #2"
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÓÏÅÄÉÎÉÔØÓÑ Ó Netbeans #2"
+
+#: netbeans.c:404
+msgid "Cannot connect to Netbeans"
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÓÏÅÄÉÎÉÔØÓÑ Ó NetBeans"
+
+#: netbeans.c:450
+#, c-format
+msgid "E668: Wrong access mode for NetBeans connection info file: \"%s\""
+msgstr ""
+"E668: îÅÐÒÁ×ÉÌØÎÙÊ ÒÅÖÉÍ ÄÏÓÔÕÐÁ Ë ÉÎÆÏÒÍÁÃÉÉ Ï ÓÏÅÄÉÎÅÎÉÉ Ó NetBeans: \"%s\""
+
+#: netbeans.c:749
+msgid "read from Netbeans socket"
+msgstr "ÞÔÅÎÉÅ ÉÚ ÇÎÅÚÄÁ NetBeans"
+
+#: netbeans.c:1643
+#, c-format
+msgid "E658: NetBeans connection lost for buffer %ld"
+msgstr "E658: ðÏÔÅÒÑÎÏ ÓÏÅÄÉÎÅÎÉÅ Ó NetBeans ÄÌÑ ÂÕÆÅÒÁ %ld"
+
+#: normal.c:2980
+msgid "Warning: terminal cannot highlight"
+msgstr "ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÔÅÒÍÉÎÁÌ ÎÅ ÍÏÖÅÔ ×ÙÐÏÌÎÑÔØ ÐÏÄÓ×ÅÔËÕ"
+
+#: normal.c:3276
+msgid "E348: No string under cursor"
+msgstr "E348: îÅÔ ÓÔÒÏËÉ × ÐÏÚÉÃÉÉ ËÕÒÓÏÒÁ"
+
+#: normal.c:3278
+msgid "E349: No identifier under cursor"
+msgstr "E349: îÅÔ ÉÍÅÎÉ × ÐÏÚÉÃÉÉ ËÕÒÓÏÒÁ"
+
+#: normal.c:4519
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr ""
+"E352: îÅ×ÏÚÍÏÖÎÏ ÓÔÅÒÅÔØ ÓËÌÁÄËÉ Ó ÔÅËÕÝÉÍ ÚÎÁÞÅÎÉÅÍ ÏÐÃÉÉ 'foldmethod'"
+
+#: normal.c:6740
+msgid "E664: changelist is empty"
+msgstr "E664: ÓÐÉÓÏË ÉÚÍÅÎÅÎÉÊ ÐÕÓÔÏÊ"
+
+#: normal.c:6742
+msgid "E662: At start of changelist"
+msgstr "E662: ÷ ÎÁÞÁÌÅ ÓÐÉÓËÁ ÉÚÍÅÎÅÎÉÊ"
+
+#: normal.c:6744
+msgid "E663: At end of changelist"
+msgstr "E662: ÷ ËÏÎÃÅ ÓÐÉÓËÁ ÉÚÍÅÎÅÎÉÊ"
+
+#: normal.c:8005
+msgid "Type :quit<Enter> to exit Vim"
+msgstr "÷×ÅÄÉÔÅ :quit<Enter> ÄÌÑ ×ÙÈÏÄÁ ÉÚ Vim"
+
+#: ops.c:294
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "éÚÍÅÎÅÎÙ ÏÔÓÔÕÐÙ × 1 ÓÔÒÏËÅ (%s 1 ÒÁÚ)"
+
+#: ops.c:296
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "éÚÍÅÎÅÎÙ ÏÔÓÔÕÐÙ × 1 ÓÔÒÏËÅ (%s %d ÒÁÚ)"
+
+#: ops.c:301
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "éÚÍÅÎÅÎÙ ÏÔÓÔÕÐÙ, %ld ÓÔÒÏË (%s 1 ÒÁÚ)"
+
+#: ops.c:304
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "éÚÍÅÎÅÎÙ ÏÔÓÔÕÐÙ, %ld ÓÔÒÏË (%s %d ÒÁÚ)"
+
+#: ops.c:662
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "éÚÍÅÎÑÀÔÓÑ ÏÔÓÔÕÐÙ ÓÔÒÏËÁÈ (%ld)..."
+
+#: ops.c:712
+msgid "1 line indented "
+msgstr "éÚÍÅΣΠÏÔÓÔÕÐ × ÏÄÎÏÊ ÓÔÒÏËÅ "
+
+#: ops.c:714
+#, c-format
+msgid "%ld lines indented "
+msgstr "éÚÍÅÎÅÎÙ ÏÔÓÔÕÐÙ × ÓÔÒÏËÁÈ (%ld) "
+
+#. must display the prompt
+#: ops.c:1675
+msgid "cannot yank; delete anyway"
+msgstr "ÓËÏÐÉÒÏ×ÁÔØ ÎÅ ÕÄÁÌÏÓØ, ÕÄÁÌÅÎÉÅ ×ÙÐÏÌÎÅÎÏ"
+
+#: ops.c:2261
+msgid "1 line changed"
+msgstr "ÉÚÍÅÎÅÎÁ 1 ÓÔÒÏËÁ"
+
+#: ops.c:2263
+#, c-format
+msgid "%ld lines changed"
+msgstr "ÉÚÍÅÎÅÎÏ ÓÔÒÏË: %ld"
+
+#: ops.c:2647
+#, c-format
+msgid "freeing %ld lines"
+msgstr "ÏÞÉÝÅÎÏ ÓÔÒÏË: %ld"
+
+#: ops.c:2928
+msgid "1 line yanked"
+msgstr "ÓËÏÐÉÒÏ×ÁÎÁ ÏÄÎÁ ÓÔÒÏËÁ"
+
+#: ops.c:2930
+#, c-format
+msgid "%ld lines yanked"
+msgstr "ÓËÏÐÉÒÏ×ÁÎÏ ÓÔÒÏË: %ld"
+
+#: ops.c:3215
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: ÷ ÒÅÇÉÓÔÒÅ %s ÎÉÞÅÇÏ ÎÅÔ"
+
+#. Highlight title
+#: ops.c:3766
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- òÅÇÉÓÔÒÙ ---"
+
+#: ops.c:5075
+msgid "Illegal register name"
+msgstr "îÅÄÏÐÕÓÔÉÍÏÅ ÉÍÑ ÒÅÇÉÓÔÒÁ"
+
+#: ops.c:5163
+#, c-format
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# òÅÇÉÓÔÒÙ:\n"
+
+#: ops.c:5213
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: îÅÉÚ×ÅÓÔÎÙÊ ÔÉÐ ÒÅÇÉÓÔÒÁ %d"
+
+#: ops.c:5698
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: îÅÄÏÐÕÓÔÉÍÏÅ ÉÍÑ ÒÅÇÉÓÔÒÁ: '%s'"
+
+#: ops.c:6058
+#, c-format
+msgid "%ld Cols; "
+msgstr "ëÏÌÏÎÏË: %ld; "
+
+#: ops.c:6065
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "÷ÙÄÅÌÅÎÏ %s%ld ÉÚ %ld ÓÔÒÏË; %ld ÉÚ %ld ÓÌÏ×; %ld ÉÚ %ld ÂÁÊÔ"
+
+#: ops.c:6081
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "ëÏÌ. %s ÉÚ %s; ÓÔÒ. %ld ÉÚ %ld; ÓÌÏ×Ï %ld ÉÚ %ld; ÂÁÊÔ %ld ÉÚ %ld"
+
+#: ops.c:6092
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld Ó ÕÞ£ÔÏÍ BOM)"
+
+#: option.c:1643
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=óÔÒ. %N"
+
+#: option.c:2092
+msgid "Thanks for flying Vim"
+msgstr "âÌÁÇÏÄÁÒÉÍ ÚÁ ÉÓÐÏÌØÚÏ×ÁÎÉÅ Vim"
+
+#: option.c:3419 option.c:3535
+msgid "E518: Unknown option"
+msgstr "E518: îÅÉÚ×ÅÓÔÎÁÑ ÏÐÃÉÑ"
+
+#: option.c:3432
+msgid "E519: Option not supported"
+msgstr "E519: ïÐÃÉÑ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ"
+
+#: option.c:3457
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: îÅ ÄÏÐÕÓËÁÅÔÓÑ × ÒÅÖÉÍÎÏÊ ÓÔÒÏËÅ"
+
+#: option.c:3522
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\t÷ ÐÏÓÌÅÄÎÉÊ ÒÁÚ ÏÐÃÉÑ ÉÚÍÅÎÅÎÁ × "
+
+#: option.c:3661
+msgid "E521: Number required after ="
+msgstr "E521: ðÏÓÌÅ = ÔÒÅÂÕÅÔÓÑ ÕËÁÚÁÔØ ÞÉÓÌÏ"
+
+#: option.c:3989 option.c:4619
+msgid "E522: Not found in termcap"
+msgstr "E522: îÅ ÏÂÎÁÒÕÖÅÎÏ × termcap"
+
+#: option.c:4064
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: îÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ <%s>"
+
+#: option.c:4611
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: úÎÁÞÅÎÉÅ ÏÐÃÉÉ 'term' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÐÕÓÔÏÊ ÓÔÒÏËÏÊ"
+
+#: option.c:4614
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: ÷ ÇÒÁÆÉÞÅÓËÏÍ ÉÎÔÅÒÆÅÊÓÅ ÉÚÍÅÎÑÔØ ÔÅÒÍÉÎÁÌ ÎÅ×ÏÚÍÏÖÎÏ"
+
+#: option.c:4616
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: äÌÑ ÚÁÐÕÓËÁ ÇÒÁÆÉÞÅÓËÏÇÏ ÉÎÔÅÒÆÅÊÓÁ ÉÓÐÏÌØÚÕÊÔÅ \":gui\""
+
+#: option.c:4645
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: ÚÎÁÞÅÎÉÑ ÏÐÃÉÊ 'backupext' É 'patchmode' ÒÁ×ÎÙ"
+
+#: option.c:4860
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: îÅ ÍÏÖÅÔ ÂÙÔØ ÉÚÍÅÎÅÎÏ × ÇÒÁÆÉÞÅÓËÏÍ ÉÎÔÅÒÆÅÊÓÅ GTK+ 2"
+
+#: option.c:5016
+msgid "E524: Missing colon"
+msgstr "E524: ðÒÏÐÕÝÅÎÏ Ä×ÏÅÔÏÞÉÅ"
+
+#: option.c:5018
+msgid "E525: Zero length string"
+msgstr "E525: óÔÒÏËÁ Ó ÎÕÌÅ×ÏÊ ÄÌÉÎÏÊ"
+
+#: option.c:5086
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: ðÒÏÐÕÝÅÎÏ ÞÉÓÌÏ ÐÏÓÌÅ <%s>"
+
+#: option.c:5100
+msgid "E527: Missing comma"
+msgstr "E527: ðÒÏÐÕÝÅÎÁ ÚÁÐÑÔÁÑ"
+
+#: option.c:5107
+msgid "E528: Must specify a ' value"
+msgstr "E528: îÅÏÂÈÏÄÉÍÏ ÕËÁÚÁÔØ ÚÎÁÞÅÎÉÅ ÄÌÑ '"
+
+#: option.c:5148
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: ÓÏÄÅÒÖÉÔ ÎÅÐÅÞÁÔÎÙÊ ÓÉÍ×ÏÌ ÉÌÉ ÓÉÍ×ÏÌ Ä×ÏÊÎÏÊ ÛÉÒÉÎÙ"
+
+#: option.c:5197
+msgid "E596: Invalid font(s)"
+msgstr "E596: îÅÐÒÁ×ÉÌØÎÙÅ ÛÒÉÆÔÙ"
+
+#: option.c:5205
+msgid "E597: can't select fontset"
+msgstr "E597: ÎÅ×ÏÚÍÏÖÎÏ ×ÙÂÒÁÔØ ÛÒÉÆÔÏ×ÏÊ ÎÁÂÏÒ"
+
+#: option.c:5207
+msgid "E598: Invalid fontset"
+msgstr "E598: îÅÐÒÁ×ÉÌØÎÙÊ ÛÒÉÆÔÏ×ÏÊ ÎÁÂÏÒ"
+
+#: option.c:5214
+msgid "E533: can't select wide font"
+msgstr "E533: ÎÅ×ÏÚÍÏÖÎÏ ×ÙÂÒÁÔØ ÛÒÉÆÔ Ó ÓÉÍ×ÏÌÁÍÉ Ä×ÏÊÎÏÊ ÛÉÒÉÎÙ"
+
+#: option.c:5216
+msgid "E534: Invalid wide font"
+msgstr "E534: îÅÐÒÁ×ÉÌØÎÙÊ ÛÒÉÆÔ Ó ÓÉÍ×ÏÌÁÍÉ Ä×ÏÊÎÏÊ ÛÉÒÉÎÙ"
+
+#: option.c:5486
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: îÅÐÒÁ×ÉÌØÎÙÊ ÓÉÍ×ÏÌ ÐÏÓÌÅ <%c>"
+
+#: option.c:5597
+msgid "E536: comma required"
+msgstr "E536: ÔÒÅÂÕÅÔÓÑ ÚÁÐÑÔÁÑ"
+
+#: option.c:5607
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr ""
+"E537: úÎÁÞÅÎÉÅ ÏÐÃÉÑ 'commentstring' ÄÏÌÖÎÏ ÂÙÔØ ÐÕÓÔÏÊ ÓÔÒÏËÏÊ ÉÌÉ "
+"ÓÏÄÅÒÖÁÔØ %s"
+
+#: option.c:5679
+msgid "E538: No mouse support"
+msgstr "E538: íÙÛØ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ"
+
+#: option.c:5947
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: îÅÚÁËÒÙÔÁÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÓÔØ ×ÙÒÁÖÅÎÉÑ"
+
+#: option.c:5951
+msgid "E541: too many items"
+msgstr "E541: ÓÌÉÛËÏÍ ÍÎÏÇÏ ÜÌÅÍÅÎÔÏ×"
+
+#: option.c:5953
+msgid "E542: unbalanced groups"
+msgstr "E542: ÎÅÓÂÁÌÁÎÓÉÒÏ×ÁÎÎÙÅ ÇÒÕÐÐÙ"
+
+#: option.c:6193
+msgid "E590: A preview window already exists"
+msgstr "E590: ïËÎÏ ÐÒÅÄÐÒÏÓÍÏÔÒÁ ÕÖÅ ÅÓÔØ"
+
+#: option.c:6450
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr ""
+"W17: áÒÁÂÓËÉÊ ÔÒÅÂÕÅÔ ÉÓÐÏÌØÚÏ×ÁÎÉÑ UTF-8, ××ÅÄÉÔÅ ':set encoding=utf-8'"
+
+#: option.c:6783
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: îÕÖÎÏ ÈÏÔÑ ÂÙ %d ÓÔÒÏË"
+
+#: option.c:6793
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: îÕÖÎÏ ÈÏÔÑ ÂÙ %d ËÏÌÏÎÏË"
+
+#: option.c:7100
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: îÅÉÚ×ÅÓÔÎÁÑ ÏÐÃÉÑ: %s"
+
+#: option.c:7220
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- ôÅÒÍÉÎÁÌØÎÙÅ ËÏÄÙ ---"
+
+#: option.c:7222
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- çÌÏÂÁÌØÎÙÅ ÚÎÁÞÅÎÉÑ ÏÐÃÉÊ ---"
+
+#: option.c:7224
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- íÅÓÔÎÙÅ ÚÎÁÞÅÎÉÑ ÏÐÃÉÊ ---"
+
+#: option.c:7226
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- ïÐÃÉÉ ---"
+
+#: option.c:7932
+msgid "E356: get_varp ERROR"
+msgstr "E356: ïûéâëá get_varp"
+
+#: option.c:8903
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': îÅÔ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÇÏ ÓÉÍ×ÏÌÁ ÄÌÑ %s"
+
+#: option.c:8937
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': ìÉÛÎÉÅ ÓÉÍ×ÏÌÙ ÐÏÓÌÅ ÔÏÞËÉ Ó ÚÁÐÑÔÏÊ: %s"
+
+#: os_amiga.c:280
+msgid "cannot open "
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ "
+
+#: os_amiga.c:314
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÏËÎÏ!\n"
+
+#: os_amiga.c:338
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "îÅÏÂÈÏÄÉÍÁ Amigados ×ÅÒÓÉÉ 2.04 ÉÌÉ ÂÏÌÅÅ ÐÏÚÄÎÅÊ\n"
+
+#: os_amiga.c:344
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "îÅÏÂÈÏÄÉÍÁ %s ×ÅÒÓÉÉ %ld\n"
+
+#: os_amiga.c:416
+msgid "Cannot open NIL:\n"
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ NIL:\n"
+
+#: os_amiga.c:427
+msgid "Cannot create "
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ "
+
+#: os_amiga.c:905
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "ðÒÅËÒÁÝÅÎÉÅ ÒÁÂÏÔÙ Vim Ó ËÏÄÏÍ %d\n"
+
+#: os_amiga.c:937
+msgid "cannot change console mode ?!\n"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÓÍÅÎÉÔØ ÒÅÖÉÍ ËÏÎÓÏÌÉ?!\n"
+
+#: os_amiga.c:1003
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: ÎÅ × ËÏÎÓÏÌÉ??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1152
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÏÂÏÌÏÞËÕ Ó ÁÒÇÕÍÅÎÔÏÍ -f"
+
+#: os_amiga.c:1193 os_amiga.c:1283
+msgid "Cannot execute "
+msgstr "îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ "
+
+#: os_amiga.c:1196 os_amiga.c:1293
+msgid "shell "
+msgstr "ÏÂÏÌÏÞËÁ "
+
+#: os_amiga.c:1216 os_amiga.c:1318
+msgid " returned\n"
+msgstr " ÚÁ×ÅÒÛÉÌÁ ÒÁÂÏÔÕ\n"
+
+#: os_amiga.c:1459
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ÓÌÉÛËÏÍ ÍÁÌÁÑ ×ÅÌÉÞÉÎÁ ANCHOR_BUF_SIZE."
+
+#: os_amiga.c:1463
+msgid "I/O ERROR"
+msgstr "ïûéâëá ÷÷ïäá/÷ù÷ïäá"
+
+#: os_mswin.c:539
+msgid "...(truncated)"
+msgstr "...(ÏÂÒÅÚÁÎÏ)"
+
+#: os_mswin.c:641
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "úÎÁÞÅÎÉÅ ÏÐÃÉÉ 'columns' ÎÅ ÒÁ×ÎÏ 80, ×ÎÅÛÎÉÅ ÐÒÏÇÒÁÍÍÙ ÎÅ ×ÙÐÏÌÎÑÀÔÓÑ"
+
+#: os_mswin.c:1973
+msgid "E237: Printer selection failed"
+msgstr "E327: îÅÕÄÁÞÎÏÅ ÚÁ×ÅÒÛÅÎÉÅ ×ÙÂÏÒÁ ÐÒÉÎÔÅÒÁ"
+
+#: os_mswin.c:2013
+#, c-format
+msgid "to %s on %s"
+msgstr "× %s ÎÁ %s"
+
+#: os_mswin.c:2028
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: îÅÉÚ×ÅÓÔÎÙÊ ÛÒÉÆÔ ÐÒÉÎÔÅÒÁ: %s"
+
+#: os_mswin.c:2077 os_mswin.c:2087
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: ïÛÉÂËÁ ÐÅÞÁÔÉ: %s"
+
+#: os_mswin.c:2088
+msgid "Unknown"
+msgstr "îÅÉÚ×ÅÓÔÎÏ"
+
+#: os_mswin.c:2115
+#, c-format
+msgid "Printing '%s'"
+msgstr "ðÅÞÁÔØ '%s'"
+
+#: os_mswin.c:3204
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: îÅÄÏÐÕÓÔÉÍÏÅ ÉÍÑ ËÏÄÉÒÏ×ËÉ \"%s\" × ÉÍÅÎÉ ÛÒÉÆÔÁ \"%s\""
+
+#: os_mswin.c:3212
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: îÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ '%c' × ÉÍÅÎÉ ÛÒÉÆÔÁ \"%s\""
+
+#: os_riscos.c:1259
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: îÅÄÏÐÕÓÔÉÍÏÅ ÚÎÁÞÅÎÉÅ ÏÐÃÉÉ 'osfiletype' -- ÉÓÐÏÌØÚÕÅÔÓÑ Text"
+
+#: os_unix.c:927
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: ä×ÏÊÎÏÊ ÓÉÇÎÁÌ, ÚÁ×ÅÒÛÅÎÉÅ ÒÁÂÏÔÙ\n"
+
+#: os_unix.c:933
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: ðÏÌÕÞÅÎ ÕÂÉÊÓÔ×ÅÎÎÙÊ ÓÉÇÎÁÌ %s\n"
+
+#: os_unix.c:936
+#, c-format
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: ðÏÌÕÞÅÎ ÕÂÉÊÓÔ×ÅÎÎÙÊ ÓÉÇÎÁÌ\n"
+
+#: os_unix.c:1199
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "ïÔËÒÙÔÉÅ ÄÉÓÐÌÅÑ X ÚÁÎÑÌÏ %ld msec"
+
+#: os_unix.c:1226
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: ïÛÉÂËÁ X\n"
+
+#: os_unix.c:1334
+msgid "Testing the X display failed"
+msgstr "ðÒÏ×ÅÒËÁ ÄÉÓÐÌÅÑ X ÚÁ×ÅÒÛÅÎÁ ÎÅÕÄÁÞÎÏ"
+
+#: os_unix.c:1473
+msgid "Opening the X display timed out"
+msgstr "ïÔËÒÙÔÉÅ ÄÉÓÐÌÅÑ X ÎÅ ×ÙÐÏÌÎÅÎÏ × ÏÔ×ÅÄ£ÎÎÏÅ ×ÒÅÍÑ"
+
+#: os_unix.c:3227 os_unix.c:3907
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"îÅ×ÏÚÍÏÖÎÏ ÚÁÐÕÓÔÉÔØ ÏÂÏÌÏÞËÕ "
+
+#: os_unix.c:3275
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"îÅ×ÏÚÍÏÖÎÏ ÚÁÐÕÓÔÉÔØ ÏÂÏÌÏÞËÕ sh\n"
+
+#: os_unix.c:3279 os_unix.c:3913
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"ïÂÏÌÏÞËÁ ÚÁ×ÅÒÛÉÌÁ ÒÁÂÏÔÕ "
+
+#: os_unix.c:3414
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÔÒÕÂÙ\n"
+
+#: os_unix.c:3429
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ fork()\n"
+
+#: os_unix.c:3920
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"÷ÙÐÏÌÎÅÎÉÅ ËÏÍÁÎÄÙ ÐÒÅÒ×ÁÎÏ\n"
+
+#: os_unix.c:4184 os_unix.c:4309 os_unix.c:5975
+msgid "XSMP lost ICE connection"
+msgstr "XSMP ÕÔÅÒÑÎÏ ÓÏÅÄÉÎÅÎÉÅ ICE"
+
+#: os_unix.c:5558
+msgid "Opening the X display failed"
+msgstr "îÅÕÄÁÞÎÏÅ ÏÔËÒÙÔÉÅ ÄÉÓÐÌÅÑ X"
+
+#: os_unix.c:5880
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP ÏÂÒÁÂÁÔÙ×ÁÅÔ ÚÁÐÒÏÓ ÓÁÍÏÓÏÈÒÁÎÅÎÉÑ"
+
+#: os_unix.c:5999
+msgid "XSMP opening connection"
+msgstr "XSMP ÏÔËÒÙ×ÁÅÔ ÓÏÅÄÉÎÅÎÉÅ"
+
+#: os_unix.c:6018
+msgid "XSMP ICE connection watch failed"
+msgstr "XSMP ÐÏÔÅÒÑÎÏ ÓÌÅÖÅÎÉÅ ÚÁ ÓÏÅÄÉÎÅÎÉÅÍ ICE"
+
+#: os_unix.c:6038
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP ÎÅÕÄÁÞÎÏ ×ÙÐÏÌÎÅÎÏ SmcOpenConnection: %s"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "÷ ÓÔÒÏËÅ"
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "îÅ×ÏÚÍÏÖÎÏ ×ÙÄÅÌÉÔØ ÐÁÍÑÔØ ÄÌÑ ËÏÍÁÎÄÎÏÊ ÓÔÒÏËÉ."
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "ïÛÉÂËÁ VIM"
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÚÁÇÒÕÚÉÔØ vim32.dll!"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÉÓÐÒÁ×ÉÔØ ÕËÁÚÁÔÅÌÉ ÆÕÎËÃÉÊ ÄÌÑ DLL!"
+
+#: os_win16.c:342 os_win32.c:3216
+#, c-format
+msgid "shell returned %d"
+msgstr "ÚÁ×ÅÒÛÅÎÉÅ ÒÁÂÏÔÙ ÏÂÏÌÏÞËÉ Ó ËÏÄÏÍ %d"
+
+#: os_win32.c:2674
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: ðÅÒÅÈ×ÁÞÅÎÏ ÓÏÂÙÔÉÅ %s\n"
+
+#: os_win32.c:2676
+msgid "close"
+msgstr "ÚÁËÒÙÔÉÅ"
+
+#: os_win32.c:2678
+msgid "logoff"
+msgstr "ÏÔËÌÀÞÅÎÉÅ"
+
+#: os_win32.c:2679
+msgid "shutdown"
+msgstr "ÚÁ×ÅÒÛÅÎÉÅ"
+
+#: os_win32.c:3169
+msgid "E371: Command not found"
+msgstr "E371: ëÏÍÁÎÄÁ ÎÅ ÎÁÊÄÅÎÁ"
+
+#: os_win32.c:3182
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE ÎÅ ÎÁÊÄÅÎ × ÐÕÔÉ, ÚÁÄÁÎÎÏÍ × $PATH.\n"
+"÷ÎÅÛÎÉÅ ËÏÍÁÎÄÙ ÎÅ ÂÕÄÕÔ ÏÓÔÁÎÁ×ÌÉ×ÁÔØÓÑ ÐÏÓÌÅ ×ÙÐÏÌÎÅÎÉÑ.\n"
+"äÏÐÏÌÎÉÔÅÌØÎÁÑ ÉÎÆÏÒÍÁÃÉÑ × :help win32-vimrun"
+
+#: os_win32.c:3185
+msgid "Vim Warning"
+msgstr "ðÒÅÄÕÐÒÅÖÄÅÎÉÅ Vim"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: ÷ ÓÔÒÏËÅ ÆÏÒÍÁÔÁ ÓÌÉÛËÏÍ ÍÎÏÇÏ %%%c"
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: îÅÏÖÉÄÁÎÎÙÊ ÜÌÅÍÅÎÔ %%%c × ÓÔÒÏËÅ ÆÏÒÍÁÔÁ"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: ÷ ÓÔÒÏËÅ ÆÏÒÍÁÔÁ ÐÒÏÐÕÝÅÎÁ ]"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: %%%c ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ × ÓÔÒÏËÅ ÆÏÒÍÁÔÁ"
+
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: îÅÄÏÐÕÓÔÉÍÙÊ %%%c × ÐÒÉÓÔÁ×ËÅ × ÓÔÒÏËÅ ÆÏÒÍÁÔÁ"
+
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: îÅÄÏÐÕÓÔÉÍÙÊ %%%c × ÓÔÒÏËÅ ÆÏÒÍÁÔÁ"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: ÷ ÚÎÁÞÅÎÉÉ ÏÐÃÉÉ 'errorformat' ÏÔÓÕÔÓÔ×ÕÅÔ ÛÁÂÌÏÎ"
+
+#: quickfix.c:501
+msgid "E379: Missing or empty directory name"
+msgstr "E379: ÉÍÑ ËÁÔÁÌÏÇÁ ÎÅ ÚÁÄÁÎÏ ÉÌÉ ÒÁ×ÎÏ ÐÕÓÔÏÊ ÓÔÒÏËÅ"
+
+#: quickfix.c:990
+msgid "E553: No more items"
+msgstr "E553: âÏÌØÛÅ ÎÅÔ ÜÌÅÍÅÎÔÏ×"
+
+#: quickfix.c:1229
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d ÉÚ %d)%s%s: "
+
+#: quickfix.c:1231
+msgid " (line deleted)"
+msgstr " (ÓÔÒÏËÁ ÕÄÁÌÅÎÁ)"
+
+#: quickfix.c:1444
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: ÷ÎÉÚÕ ÓÔÅËÁ ÂÙÓÔÒÙÈ ÉÓÐÒÁ×ÌÅÎÉÊ"
+
+#: quickfix.c:1453
+msgid "E381: At top of quickfix stack"
+msgstr "E381: îÁ×ÅÒÈÕ ÓÔÅËÁ ÂÙÓÔÒÙÈ ÉÓÐÒÁ×ÌÅÎÉÊ"
+
+#: quickfix.c:1465
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "ÓÐÉÓÏË ÏÛÉÂÏË %d ÉÚ %d; %d ÏÛÉÂÏË"
+
+#: quickfix.c:1943
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr ""
+"E382: úÁÐÉÓØ ÎÅ×ÏÚÍÏÖÎÁ, ÚÎÁÞÅÎÉÅ ÏÐÃÉÉ 'buftype' ÎÅ Ñ×ÌÑÅÔÓÑ ÐÕÓÔÏÊ ÓÔÒÏËÏÊ"
+
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: ÎÅÄÏÐÕÓÔÉÍÙÊ ÜÌÅÍÅÎÔ × %s%%[]"
+
+#: regexp.c:838
+msgid "E339: Pattern too long"
+msgstr "E339: óÌÉÛËÏÍ ÄÌÉÎÎÙÊ ÛÁÂÌÏÎ"
+
+#: regexp.c:1009
+msgid "E50: Too many \\z("
+msgstr "E50: óÌÉÛËÏÍ ÍÎÏÇÏ \\z("
+
+#: regexp.c:1020
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: óÌÉÛËÏÍ ÍÎÏÇÏ %s("
+
+#: regexp.c:1077
+msgid "E52: Unmatched \\z("
+msgstr "E52: îÅÔ ÐÁÒÙ ÄÌÑ \\z("
+
+#: regexp.c:1081
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: îÅÔ ÐÁÒÙ ÄÌÑ %s%%("
+
+#: regexp.c:1083
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: îÅÔ ÐÁÒÙ ÄÌÑ %s("
+
+#: regexp.c:1088
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: îÅÔ ÐÁÒÙ ÄÌÑ %s)"
+
+#: regexp.c:1258
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: ×ÏÚÍÏÖÎÏ ÐÕÓÔÏÊ ÏÐÅÒÁÎÄ %s*"
+
+#: regexp.c:1261
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: ×ÏÚÍÏÖÎÏ ÐÕÓÔÏÊ ÏÐÅÒÁÎÄ %s+"
+
+#: regexp.c:1316
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: ÎÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ ÐÏÓÌÅ %s@"
+
+#: regexp.c:1344
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: ×ÏÚÍÏÖÎÏ ÐÕÓÔÏÊ ÏÐÅÒÁÎÄ %s{"
+
+#: regexp.c:1354
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: óÌÉÛËÏÍ ÍÎÏÇÏ ÓÌÏÖÎÙÈ ËÏÎÓÔÒÕËÃÉÊ %s{...}"
+
+#: regexp.c:1370
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: ÷ÌÏÖÅÎÎÙÅ %s*"
+
+#: regexp.c:1373
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: ÷ÌÏÖÅÎÎÙÅ %s%c"
+
+#: regexp.c:1491
+msgid "E63: invalid use of \\_"
+msgstr "E63: ÎÅÄÏÐÕÓÔÉÍÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ \\_"
+
+#: regexp.c:1536
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c ÎÉ ÚÁ ÞÅÍ ÎÅ ÓÌÅÄÕÅÔ"
+
+#: regexp.c:1592
+msgid "E65: Illegal back reference"
+msgstr "E65: îÅÄÏÐÕÓÔÉÍÁÑ ÏÂÒÁÔÎÁÑ ÓÓÙÌËÁ"
+
+#: regexp.c:1605
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z( ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÓÐÏÌØÚÏ×ÁÎÏ ÚÄÅÓØ"
+
+#: regexp.c:1624
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 É Ô.Ð. ÎÅ ÍÏÇÕÔ ÂÙÔØ ÉÓÐÏÌØÚÏ×ÁÎÙ ÚÄÅÓØ"
+
+#: regexp.c:1635
+msgid "E68: Invalid character after \\z"
+msgstr "E68: îÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ ÐÏÓÌÅ \\z"
+
+#: regexp.c:1684
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: ðÒÏÐÕÝÅÎÁ ] ÐÏÓÌÅ %s%%["
+
+#: regexp.c:1700
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: ðÕÓÔÏÅ %s%%[]"
+
+#: regexp.c:1760
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: îÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ ÐÏÓÌÅ %s%%"
+
+#: regexp.c:2557
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: óÉÎÔÁËÓÉÞÅÓËÁÑ ÏÛÉÂËÁ × %s{...}"
+
+#: regexp.c:2863 regexp.c:3016
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr ""
+"E361: ðÒÅÄÏÔ×ÒÁÝÅÎÏ Á×ÁÒÉÊÎÏÅ ÚÁ×ÅÒÛÅÎÉÅ: ÓÌÉÛËÏÍ ÓÌÏÖÎÏÅ ÒÅÇÕÌÑÒÎÏÅ "
+"×ÙÒÁÖÅÎÉÅ?"
+
+#: regexp.c:3004 regexp.c:3013
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: ÐÒÉÍÅÎÅÎÉÅ ÛÁÂÌÏÎÁ ÐÒÉ×ÅÌÏ Ë ÏÛÉÂËÅ ×ÙÈÏÄÁ ÚÁ ÐÒÅÄÅÌÙ ÓÔÅËÁ"
+
+#: regexp.c:3258
+msgid "External submatches:\n"
+msgstr "÷ÎÅÛÎÉÅ ÐÏÄÓÏÏÔ×ÅÔÓÔ×ÉÑ:\n"
+
+#: screen.c:2184
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld ÓÔÒÏË × ÓËÌÁÄËÅ"
+
+#: screen.c:7996
+msgid " VREPLACE"
+msgstr " ÷éòôõáìøîáñ úáíåîá"
+
+#: screen.c:8000
+msgid " REPLACE"
+msgstr " úáíåîá"
+
+#: screen.c:8005
+msgid " REVERSE"
+msgstr " ïâòáôîáñ"
+
+#: screen.c:8007
+msgid " INSERT"
+msgstr " ÷óôá÷ëá"
+
+#: screen.c:8010
+msgid " (insert)"
+msgstr " (×ÓÔÁ×ËÁ)"
+
+#: screen.c:8012
+msgid " (replace)"
+msgstr " (ÚÁÍÅÎÁ)"
+
+#: screen.c:8014
+msgid " (vreplace)"
+msgstr " (×ÉÒÔÕÁÌØÎÁÑ ÚÁÍÅÎÁ)"
+
+#: screen.c:8017
+msgid " Hebrew"
+msgstr " é×ÒÉÔ"
+
+#: screen.c:8028
+msgid " Arabic"
+msgstr " áÒÁÂÓËÉÊ"
+
+#: screen.c:8031
+msgid " (lang)"
+msgstr " (ÑÚÙË)"
+
+#: screen.c:8035
+msgid " (paste)"
+msgstr " (×ËÌÅÊËÁ)"
+
+#: screen.c:8048
+msgid " VISUAL"
+msgstr " ÷éúõáìøîùê òåöéí"
+
+#: screen.c:8049
+msgid " VISUAL LINE"
+msgstr " ÷éúõáìøîáñ óôòïëá"
+
+#: screen.c:8050
+msgid " VISUAL BLOCK"
+msgstr " ÷éúõáìøîùê âìïë"
+
+#: screen.c:8051
+msgid " SELECT"
+msgstr " ÷ùäåìåîéå"
+
+#: screen.c:8052
+msgid " SELECT LINE"
+msgstr " ÷ùäåìåîéå óôòïëé"
+
+#: screen.c:8053
+msgid " SELECT BLOCK"
+msgstr " ÷ùäåìåîéå âìïëá"
+
+#: screen.c:8068 screen.c:8131
+msgid "recording"
+msgstr "ÚÁÐÉÓØ"
+
+#: search.c:37
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "ÐÏÉÓË ÂÕÄÅÔ ÐÒÏÄÏÌÖÅÎ Ó ëïîãá ÄÏËÕÍÅÎÔÁ"
+
+#: search.c:38
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "ÐÏÉÓË ÂÕÄÅÔ ÐÒÏÄÏÌÖÅÎ Ó îáþáìá ÄÏËÕÍÅÎÔÁ"
+
+#: search.c:526
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: îÅÐÒÁ×ÉÌØÎÁÑ ÓÔÒÏËÁ ÐÏÉÓËÁ: %s"
+
+#: search.c:853
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: ÐÏÉÓË ÚÁËÏÎÞÅÎ × îáþáìå ÄÏËÕÍÅÎÔÁ; %s ÎÅ ÎÁÊÄÅÎÏ"
+
+#: search.c:856
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: ÐÏÉÓË ÚÁËÏÎÞÅÎ × ëïîãå ÄÏËÕÍÅÎÔÁ; %s ÎÅ ÎÁÊÄÅÎÏ"
+
+#: search.c:1249
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: ðÏÓÌÅ ';' ÏÖÉÄÁÅÔÓÑ ××ÏÄ '?' ÉÌÉ '/'"
+
+#: search.c:3759
+msgid " (includes previously listed match)"
+msgstr " (×ËÌÀÞÁÅÔ ÒÁÎÎÅÅ ÐÏËÁÚÁÎÎÙÅ ÓÏÏÔ×ÅÔÓÔ×ÉÑ)"
+
+#. cursor at status line
+#: search.c:3779
+msgid "--- Included files "
+msgstr "--- ÷ËÌÀÞ£ÎÎÙÅ ÆÁÊÌÙ "
+
+#: search.c:3781
+msgid "not found "
+msgstr "ÎÅ ÎÁÊÄÅÎÏ "
+
+#: search.c:3782
+msgid "in path ---\n"
+msgstr "ÐÏ ÐÕÔÉ ---\n"
+
+#: search.c:3839
+msgid " (Already listed)"
+msgstr " (õÖÅ ÐÏËÁÚÁÎÏ)"
+
+#: search.c:3841
+msgid " NOT FOUND"
+msgstr " îå îáêäåîï"
+
+#: search.c:3893
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "ðÒÏÓÍÏÔÒ ×ËÌÀÞ£ÎÎÙÈ ÆÁÊÌÏ×: %s"
+
+#: search.c:4111
+msgid "E387: Match is on current line"
+msgstr "E387: óÏÏÔ×ÅÔÓÔ×ÉÅ × ÔÅËÕÝÅÊ ÓÔÒÏËÅ"
+
+#: search.c:4254
+msgid "All included files were found"
+msgstr "îÁÊÄÅÎÙ ×ÓÅ ×ËÌÀÞ£ÎÎÙÅ ÆÁÊÌÙ"
+
+#: search.c:4256
+msgid "No included files"
+msgstr "÷ËÌÀÞ£ÎÎÙÈ ÆÁÊÌÏ× ÎÅÔ"
+
+#: search.c:4272
+msgid "E388: Couldn't find definition"
+msgstr "E388: ïÐÒÅÄÅÌÅÎÉÅ ÎÅ ÎÁÊÄÅÎÏ"
+
+#: search.c:4274
+msgid "E389: Couldn't find pattern"
+msgstr "E389: ûÁÂÌÏÎ ÎÅ ÎÁÊÄÅÎ"
+
+#: syntax.c:3050
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: îÅÄÏÐÕÓÔÉÍÙÊ ÁÒÇÕÍÅÎÔ: %s"
+
+#: syntax.c:3230
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: óÉÎÔÁËÓÉÞÅÓËÉÊ ËÌÁÓÔÅÒ %s ÎÅ ÎÁÊÄÅÎ"
+
+#: syntax.c:3394
+msgid "No Syntax items defined for this buffer"
+msgstr "óÉÎÔÁËÓÉÞÅÓËÉÅ ÜÌÅÍÅÎÔÙ ÄÌÑ ÄÁÎÎÏÇÏ ÂÕÆÅÒÁ ÎÅ ÏÐÒÅÄÅÌÅÎÙ"
+
+#: syntax.c:3402
+msgid "syncing on C-style comments"
+msgstr "óÉÎÈÒÏÎÉÚÁÃÉÑ ÐÏ ËÏÍÍÅÎÔÁÒÉÑÍ × ÓÔÉÌÅ ÑÚÙËÁ C"
+
+#: syntax.c:3410
+msgid "no syncing"
+msgstr "ÂÅÚ ÓÉÎÈÒÏÎÉÚÁÃÉÉ"
+
+#: syntax.c:3413
+msgid "syncing starts "
+msgstr "ÓÉÎÈÒÏÎÉÚÁÃÉÑ ÎÁÞÁÔÁ "
+
+#: syntax.c:3415 syntax.c:3490
+msgid " lines before top line"
+msgstr " ÓÔÒÏË ÐÅÒÅÄ ×ÅÒÈÎÅÊ ÓÔÒÏËÏÊ"
+
+#: syntax.c:3420
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- üÌÅÍÅÎÔÙ ÓÉÎÈÒÏÎÉÚÁÃÉÉ ÓÉÎÔÁËÓÉÓÁ ---"
+
+#: syntax.c:3425
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"ÓÉÎÈÒÏÎÉÚÁÃÉÑ ÐÏ ÜÌÅÍÅÎÔÁÍ"
+
+#: syntax.c:3431
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- óÉÎÔÁËÓÉÞÅÓËÉÅ ÜÌÅÍÅÎÔÙ ---"
+
+#: syntax.c:3454
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: óÉÎÔÁËÓÉÞÅÓËÉÊ ËÌÁÓÔÅÒ %s ÎÅ ÎÁÊÄÅÎ"
+
+#: syntax.c:3480
+msgid "minimal "
+msgstr "ÍÉÎÉÍÕÍ "
+
+#: syntax.c:3487
+msgid "maximal "
+msgstr "ÍÁËÓÉÍÕÍ "
+
+#: syntax.c:3499
+msgid "; match "
+msgstr "; ÓÏÏÔ×ÅÔÓÔ×ÉÅ "
+
+#: syntax.c:3501
+msgid " line breaks"
+msgstr " ÐÅÒÅÎÏÓÏ× ÓÔÒÏË"
+
+#: syntax.c:4135
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: ÚÄÅÓØ ÎÅÌØÚÑ ÉÓÐÏÌØÚÏ×ÁÔØ group[t]here"
+
+#: syntax.c:4159
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: üÌÅÍÅÎÔ ÏÂÌÁÓÔÉ ÄÌÑ %s ÎÅ ÎÁÊÄÅÎ"
+
+#: syntax.c:4187
+msgid "E395: contains argument not accepted here"
+msgstr "E395: ÚÄÅÓØ ÎÅÌØÚÑ ÉÓÐÏÌØÚÏ×ÁÔØ ÁÒÇÕÍÅÎÔ contains"
+
+#: syntax.c:4198
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: ÚÄÅÓØ ÎÅÌØÚÑ ÉÓÐÏÌØÚÏ×ÁÔØ ÁÒÇÕÍÅÎÔ containedin"
+
+#: syntax.c:4276
+msgid "E397: Filename required"
+msgstr "E397: ôÒÅÂÕÅÔÓÑ ÕËÁÚÁÔØ ÉÍÑ ÆÁÊÌÁ"
+
+#: syntax.c:4614
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: ðÒÏÐÕÝÅÎÏ '=': %s"
+
+#: syntax.c:4772
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: îÅ È×ÁÔÁÅÔ ÁÒÇÕÍÅÎÔÏ×: ÓÉÎÔÁËÓÉÞÅÓËÉÊ ÒÅÇÉÏÎ %s"
+
+#: syntax.c:5103
+msgid "E400: No cluster specified"
+msgstr "E400: ëÌÁÓÔÅÒ ÎÅ ÕËÁÚÁÎ"
+
+#: syntax.c:5140
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: îÅ ÎÁÊÄÅÎ ÒÁÚÄÅÌÉÔÅÌØ ÛÁÂÌÏÎÏ×: %s"
+
+#: syntax.c:5215
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: íÕÓÏÒ ÐÏÓÌÅ ÛÁÂÌÏÎÁ: %s"
+
+#: syntax.c:5305
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr ""
+"E403: ÓÉÎÈÒÏÎÉÚÁÃÉÑ ÓÉÎÔÁËÓÉÓÁ: ÛÁÂÌÏÎ ÐÒÏÄÏÌÖÅÎÉÊ ÓÔÒÏËÉ ÕËÁÚÁÎ Ä×ÁÖÄÙ"
+
+#: syntax.c:5362
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: îÅÄÏÐÕÓÔÉÍÙÅ ÁÒÇÕÍÅÎÔÙ: %s"
+
+#: syntax.c:5412
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: ðÒÏÐÕÝÅÎ ÚÎÁË ÒÁ×ÅÎÓÔ×Á: %s"
+
+#: syntax.c:5418
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: ðÕÓÔÏÊ ÁÒÇÕÍÅÎÔ: %s"
+
+#: syntax.c:5445
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s ÎÅ ÄÏÐÕÓËÁÅÔÓÑ × ÜÔÏÍ ÍÅÓÔÅ"
+
+#: syntax.c:5452
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s ÄÏÌÖÎÏ ÂÙÔØ ÐÅÒ×ÙÍ × ÓÐÉÓËÅ contains"
+
+#: syntax.c:5522
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: îÅÉÚ×ÅÓÔÎÁÑ ÇÒÕÐÐÁ: %s"
+
+#: syntax.c:5755
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: îÅÐÒÁ×ÉÌØÎÁÑ ÐÏÄËÏÍÁÎÄÁ :syntax: %s"
+
+#: syntax.c:6136
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: ÇÒÕÐÐÁ ÐÏÄÓ×ÅÔËÉ ÓÉÎÔÁËÓÉÓÁ %s ÎÅ ÎÁÊÄÅÎÁ"
+
+#: syntax.c:6160
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: îÅ È×ÁÔÁÅÔ ÁÒÇÕÍÅÎÔÏ×: \":highlight link %s\""
+
+#: syntax.c:6167
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: óÌÉÛËÏÍ ÍÎÏÇÏ ÁÒÇÕÍÅÎÔÏ×: \":highlight link %s\""
+
+#: syntax.c:6187
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: Õ ÇÒÕÐÐÙ ÅÓÔØ ÓÏÂÓÔ×ÅÎÎÙÅ ÎÁÓÔÒÏÊËÉ, ÓÓÙÌËÁ ÉÇÎÏÒÉÒÕÅÔÓÑ"
+
+#: syntax.c:6316
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: ÎÅÏÖÉÄÁÎÎÙÊ ÚÎÁË ÒÁ×ÅÎÓÔ×Á: %s"
+
+#: syntax.c:6352
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: ÐÒÏÐÕÝÅÎ ÚÎÁË ÒÁ×ÅÎÓÔ×Á: %s"
+
+#: syntax.c:6380
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: ÐÒÏÐÕÝÅÎ ÁÒÇÕÍÅÎÔ: %s"
+
+#: syntax.c:6417
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: îÅÄÏÐÕÓÔÉÍÏÅ ÚÎÁÞÅÎÉÅ: %s"
+
+#: syntax.c:6536
+msgid "E419: FG color unknown"
+msgstr "E419: îÅÉÚ×ÅÓÔÎÙÊ Ã×ÅÔ ÔÅËÓÔÁ"
+
+#: syntax.c:6547
+msgid "E420: BG color unknown"
+msgstr "E420: îÅÉÚ×ÅÓÔÎÙÊ Ã×ÅÔ ÆÏÎÁ"
+
+#: syntax.c:6608
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: éÍÑ ÉÌÉ ÎÏÍÅÒ Ã×ÅÔÁ ÎÅ ÉÚ×ÅÓÔÎÏ: %s"
+
+#: syntax.c:6814
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: ÓÌÉÛËÏÍ ÄÌÉÎÎÙÊ ËÏÄ ÔÅÒÍÉÎÁÌÁ: %s"
+
+#: syntax.c:6861
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: îÅÄÏÐÕÓÔÉÍÙÊ ÁÒÇÕÍÅÎÔ: %s"
+
+#: syntax.c:7390
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: éÓÐÏÌØÚÕÅÔÓÑ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÒÁÚÎÙÈ ÁÔÒÉÂÕÔÏ× ÐÏÄÓ×ÅÔËÉ ÓÉÎÔÁËÓÉÓÁ"
+
+#: syntax.c:7911
+msgid "E669: Unprintable character in group name"
+msgstr "E669: îÅÐÅÞÁÔÎÙÊ ÓÉÍ×ÏÌ × ÉÍÅÎÉ ÇÒÕÐÐÙ"
+
+#. This is an error, but since there previously was no check only
+#. * give a warning.
+#: syntax.c:7918
+msgid "W18: Invalid character in group name"
+msgstr "W18: îÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ × ÉÍÅÎÉ ÇÒÕÐÐÙ"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: ×ÎÉÚÕ ÓÔÅËÁ ÍÅÔÏË"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: ÎÁ×ÅÒÈÕ ÓÔÅËÁ ÍÅÔÏË"
+
+#: tag.c:412
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: îÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÊÔÉ × ÐÏÚÉÃÉÀ ÄÏ ÐÅÒ×ÏÊ ÓÏ×ÐÁÄÁÀÝÅÊ ÍÅÔËÉ"
+
+#: tag.c:550
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: íÅÔËÁ ÎÅ ÎÁÊÄÅÎÁ: %s"
+
+#: tag.c:583
+msgid " # pri kind tag"
+msgstr " # ÐÒÉ ÔÉÐ ÍÅÔËÁ"
+
+#: tag.c:586
+msgid "file\n"
+msgstr "ÆÁÊÌ\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:744
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "÷ÙÂÅÒÉÔÅ ÎÕÖÎÙÊ ÎÏÍÅÒ (<CR> ÄÌÑ ÏÔËÁÚÁ):"
+
+#: tag.c:784
+msgid "E427: There is only one matching tag"
+msgstr "E427: åÓÔØ ÔÏÌØËÏ ÏÄÎÁ ÓÏ×ÐÁÄÁÀÝÁÑ ÍÅÔËÁ"
+
+#: tag.c:786
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: îÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÊÔÉ × ÐÏÚÉÃÉÀ ÚÁ ÐÏÓÌÅÄÎÅÊ ÓÏ×ÐÁÄÁÀÝÅÊ ÍÅÔËÏÊ"
+
+#: tag.c:810
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "æÁÊÌ \"%s\" ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+
+#. Give an indication of the number of matching tags
+#: tag.c:823
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "ÍÅÔËÁ %d ÉÚ %d%s"
+
+#: tag.c:826
+msgid " or more"
+msgstr " É ÂÏÌÅÅ"
+
+#: tag.c:828
+msgid " Using tag with different case!"
+msgstr " éÓÐÏÌØÚÕÅÔÓÑ ÍÅÔËÁ Ó ÓÉÍ×ÏÌÁÍÉ × ÄÒÕÇÏÍ ÒÅÇÉÓÔÒÅ!"
+
+#: tag.c:872
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: æÁÊÌ \"%s\" ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+
+#. Highlight title
+#: tag.c:941
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # ë ÍÅÔËÅ ïô ÓÔÒ. × ÆÁÊÌÅ/ÔÅËÓÔÅ"
+
+#: tag.c:1363
+#, c-format
+msgid "Searching tags file %s"
+msgstr "ðÏÉÓË × ÆÁÊÌÅ ÍÅÔÏË %s"
+
+#: tag.c:1550
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: ðÕÔØ Ë ÆÁÊÌÕ ÍÅÔÏË %s ÏÂÒÅÚÁÎ\n"
+
+#: tag.c:2203
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: ïÛÉÂËÁ ÆÏÒÍÁÔÁ × ÆÁÊÌÅ ÍÅÔÏË \"%s\""
+
+#: tag.c:2207
+#, c-format
+msgid "Before byte %ld"
+msgstr "ðÅÒÅÄ ÂÁÊÔÏÍ %ld"
+
+#: tag.c:2240
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: æÁÊÌ ÍÅÔÏË ÎÅ ÏÔÓÏÒÔÉÒÏ×ÁÎ: %s"
+
+#. never opened any tags file
+#: tag.c:2280
+msgid "E433: No tags file"
+msgstr "E433: æÁÊÌ ÍÅÔÏË ÎÅ ÏÂÎÁÒÕÖÅÎ"
+
+#: tag.c:3016
+msgid "E434: Can't find tag pattern"
+msgstr "E434: îÅ ÎÁÊÄÅÎ ÛÁÂÌÏÎ ÍÅÔËÉ"
+
+#: tag.c:3027
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: íÅÔËÁ ÎÅ ÎÁÊÄÅÎÁ, ÐÙÔÁÅÍÓÑ ÕÇÁÄÁÔØ!"
+
+#: term.c:1759
+msgid "' not known. Available builtin terminals are:"
+msgstr "' ÎÅ ÉÚ×ÅÓÔÅÎ. äÏÓÔÕÐÎÙ ×ÓÔÒÏÅÎÎÙÅ ÔÅÒÍÉÎÁÌÙ:"
+
+#: term.c:1783
+msgid "defaulting to '"
+msgstr "ÐÏ ÕÍÏÌÞÁÎÉÀ '"
+
+#: term.c:2141
+msgid "E557: Cannot open termcap file"
+msgstr "E557: îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ termcap"
+
+#: term.c:2145
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: ÷ terminfo ÎÅÔ ÚÁÐÉÓÉ ÏÂ ÜÔÏÍ ÔÅÒÍÉÎÁÌÅ"
+
+#: term.c:2147
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: ÷ termcap ÎÅÔ ÚÁÐÉÓÉ ÏÂ ÜÔÏÍ ÔÅÒÍÉÎÁÌÅ"
+
+#: term.c:2306
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: ÷ termcap ÎÅÔ ÚÁÐÉÓÉ \"%s\""
+
+#: term.c:2780
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: ÔÒÅÂÕÅÔÓÑ ÓÐÏÓÏÂÎÏÓÔØ ÔÅÒÍÉÎÁÌÁ \"cm\""
+
+#. Highlight title
+#: term.c:4990
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- ëÎÏÐËÉ ÔÅÒÍÉÎÁÌÁ ---"
+
+#: ui.c:258
+msgid "new shell started\n"
+msgstr "ÚÁÐÕÓË ÎÏ×ÏÊ ÏÂÏÌÏÞËÉ\n"
+
+#: ui.c:1841
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: ïÛÉÂËÁ ÞÔÅÎÉÑ ××ÏÄÁ, ×ÙÈÏÄ...\n"
+
+#. must display the prompt
+#: undo.c:405
+msgid "No undo possible; continue anyway"
+msgstr "ïÔÍÅÎÁ ÎÅ×ÏÚÍÏÖÎÁ; ÐÒÏÄÏÌÖÁÔØ ×ÙÐÏÌÎÅÎÉÅ"
+
+#: undo.c:561
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: ÎÅÐÒÁ×ÉÌØÎÙÅ ÎÏÍÅÒÁ ÓÔÒÏË"
+
+#: undo.c:757
+msgid "1 change"
+msgstr "åÄÉÎÓÔ×ÅÎÎÏÅ ÉÚÍÅÎÅÎÉÅ"
+
+#: undo.c:759
+#, c-format
+msgid "%ld changes"
+msgstr "éÚÍÅÎÅÎÉÊ: %ld"
+
+#: undo.c:812
+msgid "E439: undo list corrupt"
+msgstr "E439: ðÏ×ÒÅÖģΠÓÐÉÓÏË ÏÔÍÅÎÙ"
+
+#: undo.c:844
+msgid "E440: undo line missing"
+msgstr "E440: ÐÏÔÅÒÑÎÁ ÓÔÒÏËÁ ÏÔÍÅÎÙ"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:721
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"÷ÅÒÓÉÑ Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ ÄÌÑ MS-Windows 16/32 ÂÉÔ"
+
+#: version.c:723
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"÷ÅÒÓÉÑ Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ ÄÌÑ MS-Windows 32 ÂÉÔ"
+
+#: version.c:726
+msgid " in Win32s mode"
+msgstr " × ÒÅÖÉÍÅ Win32s"
+
+#: version.c:728
+msgid " with OLE support"
+msgstr " Ó ÐÏÄÄÅÒÖËÏÊ OLE"
+
+#: version.c:731
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"ëÏÎÓÏÌØÎÁÑ ×ÅÒÓÉÑ ÄÌÑ MS-Windows 32 ÂÉÔ"
+
+#: version.c:735
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"÷ÅÒÓÉÑ ÄÌÑ MS-Windows 16 ÂÉÔ"
+
+#: version.c:739
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"÷ÅÒÓÉÑ ÄÌÑ MS-DOS 32 ÂÉÔ"
+
+#: version.c:741
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"÷ÅÒÓÉÑ ÄÌÑ MS-DOS 16 ÂÉÔ"
+
+#: version.c:747
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"÷ÅÒÓÉÑ ÄÌÑ MacOS X (unix)"
+
+#: version.c:749
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"÷ÅÒÓÉÑ ÄÌÑ MacOS X"
+
+#: version.c:752
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"÷ÅÒÓÉÑ ÄÌÑ MacOS"
+
+#: version.c:757
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"÷ÅÒÓÉÑ ÄÌÑ RISC OS"
+
+#: version.c:767
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"úÁÐÌÁÔËÉ: "
+
+#: version.c:793 version.c:1161
+msgid "Modified by "
+msgstr "ó ÉÚÍÅÎÅÎÉÑÍÉ, ×ÎÅÓ£ÎÎÙÍÉ "
+
+#: version.c:800
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"óËÏÍÐÉÌÉÒÏ×ÁÎ "
+
+#: version.c:803
+msgid "by "
+msgstr " "
+
+#: version.c:815
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"ïÇÒÏÍÎÁÑ ×ÅÒÓÉÑ "
+
+#: version.c:818
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"âÏÌØÛÁÑ ×ÅÒÓÉÑ "
+
+#: version.c:821
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"ïÂÙÞÎÁÑ ×ÅÒÓÉÑ "
+
+#: version.c:824
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"íÁÌÁÑ ×ÅÒÓÉÑ "
+
+#: version.c:826
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"÷ÅÒÓÉÑ \"ëÒÏÈÁ\" "
+
+#: version.c:832
+msgid "without GUI."
+msgstr "ÂÅÚ ÇÒÁÆÉÞÅÓËÏÇÏ ÉÎÔÅÒÆÅÊÓÁ."
+
+#: version.c:837
+msgid "with GTK2-GNOME GUI."
+msgstr "Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ GTK2-GNOME."
+
+#: version.c:839
+msgid "with GTK-GNOME GUI."
+msgstr "Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ GTK-GNOME."
+
+#: version.c:843
+msgid "with GTK2 GUI."
+msgstr "Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ GTK2."
+
+#: version.c:845
+msgid "with GTK GUI."
+msgstr "Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ GTK."
+
+#: version.c:850
+msgid "with X11-Motif GUI."
+msgstr "Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ X11-Motif."
+
+#: version.c:854
+msgid "with X11-neXtaw GUI."
+msgstr "Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ X11-neXtaw."
+
+#: version.c:856
+msgid "with X11-Athena GUI."
+msgstr "Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ X11-Athena."
+
+#: version.c:860
+msgid "with BeOS GUI."
+msgstr "Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ BeOS."
+
+#: version.c:863
+msgid "with Photon GUI."
+msgstr "Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ Photon."
+
+#: version.c:866
+msgid "with GUI."
+msgstr "Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ."
+
+#: version.c:869
+msgid "with Carbon GUI."
+msgstr "Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ Carbon."
+
+#: version.c:872
+msgid "with Cocoa GUI."
+msgstr "Ó ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ Cocoa."
+
+#: version.c:875
+msgid "with (classic) GUI."
+msgstr "Ó ËÌÁÓÓÉÞÅÓËÉÍ ÇÒÁÆÉÞÅÓËÉÍ ÉÎÔÅÒÆÅÊÓÏÍ."
+
+#: version.c:886
+msgid " Features included (+) or not (-):\n"
+msgstr " ÷ËÌÀÞ£ÎÎÙÅ (+) É ÏÔËÌÀÞ£ÎÎÙÅ (-) ÏÓÏÂÅÎÎÏÓÔÉ:\n"
+
+#: version.c:898
+msgid " system vimrc file: \""
+msgstr " ÏÂÝÅÓÉÓÔÅÍÎÙÊ ÆÁÊÌ vimrc: \""
+
+#: version.c:903
+msgid " user vimrc file: \""
+msgstr " ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÊ ÆÁÊÌ vimrc: \""
+
+#: version.c:908
+msgid " 2nd user vimrc file: \""
+msgstr " ×ÔÏÒÏÊ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÊ ÆÁÊÌ vimrc: \""
+
+#: version.c:913
+msgid " 3rd user vimrc file: \""
+msgstr " ÔÒÅÔÉÊ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÊ ÆÁÊÌ vimrc: \""
+
+#: version.c:918
+msgid " user exrc file: \""
+msgstr " ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÊ ÆÁÊÌ exrc: \""
+
+#: version.c:923
+msgid " 2nd user exrc file: \""
+msgstr " ×ÔÏÒÏÊ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÊ ÆÁÊÌ exrc: \""
+
+#: version.c:929
+msgid " system gvimrc file: \""
+msgstr " ÏÂÝÅÓÉÓÔÅÍÎÙÊ ÆÁÊÌ gvimrc: \""
+
+#: version.c:933
+msgid " user gvimrc file: \""
+msgstr " ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÊ ÆÁÊÌ gvimrc: \""
+
+#: version.c:937
+msgid "2nd user gvimrc file: \""
+msgstr " ×ÔÏÒÏÊ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÊ ÆÁÊÌ gvimrc: \""
+
+#: version.c:942
+msgid "3rd user gvimrc file: \""
+msgstr " ÔÒÅÔÉÊ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÊ ÆÁÊÌ gvimrc: \""
+
+#: version.c:949
+msgid " system menu file: \""
+msgstr " ÏÂÝÅÓÉÓÔÅÍÎÙÊ ÆÁÊÌ ÍÅÎÀ: \""
+
+#: version.c:957
+msgid " fall-back for $VIM: \""
+msgstr " ÚÎÁÞÅÎÉÅ $VIM ÐÏ ÕÍÏÌÞÁÎÉÀ: \""
+
+#: version.c:963
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " ÚÎÁÞÅÎÉÅ $VIMRUNTIME ÐÏ ÕÍÏÌÞÁÎÉÀ: \""
+
+#: version.c:967
+msgid "Compilation: "
+msgstr "ðÁÒÁÍÅÔÒÙ ËÏÍÐÉÌÑÃÉÉ: "
+
+#: version.c:973
+msgid "Compiler: "
+msgstr "ëÏÍÐÉÌÑÔÏÒ: "
+
+#: version.c:978
+msgid "Linking: "
+msgstr "óÂÏÒËÁ: "
+
+#: version.c:983
+msgid " DEBUG BUILD"
+msgstr " ïôìáäïþîáñ óâïòëá"
+
+#: version.c:1022
+msgid "VIM - Vi IMproved"
+msgstr "VIM ::: Vi IMproved (õÌÕÞÛÅÎÎÙÊ Vi) ::: òÕÓÓËÁÑ ×ÅÒÓÉÑ"
+
+#: version.c:1024
+msgid "version "
+msgstr "×ÅÒÓÉÑ "
+
+#: version.c:1025
+msgid "by Bram Moolenaar et al."
+msgstr "âÒÁÍ íÏÏÌÅÎÁÁÒ É ÄÒÕÇÉÅ"
+
+#: version.c:1029
+msgid "Vim is open source and freely distributable"
+msgstr "Vim ÜÔÏ Ó×ÏÂÏÄÎÏ ÒÁÓÐÒÏÓÔÒÁÎÑÅÍÁÑ ÐÒÏÇÒÁÍÍÁ Ó ÏÔËÒÙÔÙÍ ËÏÄÏÍ"
+
+#: version.c:1031
+msgid "Help poor children in Uganda!"
+msgstr "âÅÄÎÙÍ ÄÅÔÑÍ × õÇÁÎÄÅ ÎÕÖÎÁ ×ÁÛÁ ÐÏÍÏÝØ!"
+
+#: version.c:1032
+msgid "type :help iccf<Enter> for information "
+msgstr "ÎÁÂÅÒÉÔÅ :help iccf<Enter> ÄÌÑ ÄÏÐÏÌÎÉÔÅÌØÎÏÊ ÉÎÆÏÒÍÁÃÉÉ"
+
+#: version.c:1034
+msgid "type :q<Enter> to exit "
+msgstr "ÎÁÂÅÒÉÔÅ :q<Enter> ÞÔÏÂÙ ×ÙÊÔÉ ÉÚ ÐÒÏÇÒÁÍÍÙ "
+
+#: version.c:1035
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "ÎÁÂÅÒÉÔÅ :help<Enter> ÉÌÉ <F1> ÄÌÑ ÐÏÌÕÞÅÎÉÑ ÓÐÒÁ×ËÉ "
+
+#: version.c:1036
+msgid "type :help version6<Enter> for version info"
+msgstr "ÎÁÂÅÒÉÔÅ :help version6<Enter> ÞÔÏÂÙ ÕÚÎÁÔØ Ï ÜÔÏÊ ×ÅÒÓÉÉ "
+
+#: version.c:1039
+msgid "Running in Vi compatible mode"
+msgstr "òÁÂÏÔÁ × Vi-ÓÏ×ÍÅÓÔÉÍÏÍ ÒÅÖÉÍÅ"
+
+#: version.c:1040
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "ÎÁÂÅÒÉÔÅ :set nocp<Enter> ÄÌÑ ÐÅÒÅÈÏÄÁ × ÒÅÖÉÍ Vim "
+
+#: version.c:1041
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "ÎÁÂÅÒÉÔÅ :help cp-default<Enter> ÄÌÑ ÄÏÐÏÌÎÉÔÅÌØÎÏÊ ÉÎÆÏÒÍÁÃÉÉ"
+
+#: version.c:1056
+msgid "menu Help->Orphans for information "
+msgstr "ÍÅÎÀ óÐÒÁ×ËÁ->óÉÒÏÔÙ ÄÌÑ ÐÏÌÕÞÅÎÉÑ ÉÎÆÏÒÍÁÃÉÉ "
+
+#: version.c:1058
+msgid "Running modeless, typed text is inserted"
+msgstr "âÅÚÒÅÖÉÍÎÁÑ ÒÁÂÏÔÙ, ×ÓÔÁ×ËÁ ××ÅÄ£ÎÎÏÇÏ ÔÅËÓÔÁ"
+
+#: version.c:1059
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "ÍÅÎÀ ðÒÁ×ËÁ->ïÂÝÉÅ îÁÓÔÒÏÊËÉ->òÅÖÉÍ ÷ÓÔÁ×ËÉ "
+
+#: version.c:1060
+msgid " for two modes "
+msgstr " ÄÌÑ Ä×ÕÈ ÒÅÖÉÍÏ× "
+
+#: version.c:1064
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "ÍÅÎÀ ðÒÁ×ËÁ->ïÂÝÉÅ îÁÓÔÒÏÊËÉ->óÏ×ÍÅÓÔÉÍÏÓÔØ Ó Vi "
+
+#: version.c:1065
+msgid " for Vim defaults "
+msgstr " ÄÌÑ ÐÅÒÅÈÏÄÁ × ÒÅÖÉÍ Vim "
+
+#: version.c:1112
+msgid "Sponsor Vim development!"
+msgstr "ðÏÍÏÇÉÔÅ × ÒÁÚÒÁÂÏÔËÅ Vim!"
+
+#: version.c:1113
+msgid "Become a registered Vim user!"
+msgstr "óÔÁÎØÔÅ ÚÁÒÅÇÉÓÔÒÉÒÏ×ÁÎÎÙÍ ÐÏÌØÚÏ×ÁÔÅÌÅÍ Vim!"
+
+#: version.c:1116
+msgid "type :help sponsor<Enter> for information "
+msgstr "ÎÁÂÅÒÉÔÅ :help sponsor<Enter> ÄÌÑ ÐÏÌÕÞÅÎÉÑ ÉÎÆÏÒÍÁÃÉÉ "
+
+#: version.c:1117
+msgid "type :help register<Enter> for information "
+msgstr "ÎÁÂÅÒÉÔÅ :help register<Enter> ÄÌÑ ÐÏÌÕÞÅÎÉÑ ÉÎÆÏÒÍÁÃÉÉ "
+
+#: version.c:1119
+msgid "menu Help->Sponsor/Register for information "
+msgstr "ÍÅÎÀ óÐÒÁ×ËÁ->ðÏÍÏÝØ/òÅÇÉÓÔÒÁÃÉÑ ÄÌÑ ÐÏÌÕÞÅÎÉÑ ÉÎÆÏÒÍÁÃÉÉ "
+
+#: version.c:1129
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "ðòåäõðòåöäåîéå: ÏÂÎÁÒÕÖÅÎÁ Windows 95/98/ME"
+
+#: version.c:1132
+msgid "type :help windows95<Enter> for info on this"
+msgstr "ÎÁÂÅÒÉÔÅ :help windows95<Enter> ÄÌÑ ÐÏÌÕÞÅÎÉÑ ÉÎÆÏÒÍÁÃÉÉ "
+
+#: window.c:203
+msgid "E441: There is no preview window"
+msgstr "E441: ïËÎÏ ÐÒÅÄÐÒÏÓÍÏÔÒÁ ÏÔÓÕÔÓÔ×ÕÅÔ"
+
+#: window.c:581
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: ïËÎÏ ÎÅ ÍÏÖÅÔ ÂÙÔØ ÏÄÎÏ×ÒÅÍÅÎÎÏ ÓÌÅ×Á ××ÅÒÈÕ É ÓÐÒÁ×Á ×ÎÉÚÕ"
+
+#: window.c:1340
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: îÅ×ÏÚÍÏÖÎÏ ÐÏÍÅÎÑÔØ ÍÅÓÔÁÍÉ, ÐÏËÁ ÄÒÕÇÏÅ ÏËÎÏ ÒÁÚÄÅÌÅÎÏ"
+
+#: window.c:1836
+msgid "E444: Cannot close last window"
+msgstr "E444: îÅÌØÚÑ ÚÁËÒÙÔØ ÐÏÓÌÅÄÎÅÅ ÏËÎÏ"
+
+#: window.c:2567
+msgid "Already only one window"
+msgstr "îÁ ÜËÒÁÎÅ ×ÓÅÇÏ ÏÄÎÏ ÏËÎÏ"
+
+#: window.c:2614
+msgid "E445: Other window contains changes"
+msgstr "E445: ÷ ÄÒÕÇÏÍ ÏËÎÅ ÅÓÔØ ÎÅÓÏÈÒÁΣÎÎÙÅ ÉÚÍÅÎÅÎÉÑ"
+
+#: window.c:4480
+msgid "E446: No file name under cursor"
+msgstr "E446: îÅÔ ÉÍÅÎÉ ÆÁÊÌÁ × ÐÏÚÉÃÉÉ ËÕÒÓÏÒÁ"
+
+#: window.c:4599
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: æÁÊÌ \"%s\" ÎÅ ÎÁÊÄÅÎ ÐÏ ÉÚ×ÅÓÔÎÙÍ ÐÕÔÑÍ"
+
+#: if_perl.xs:326 globals.h:1232
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: îÅ×ÏÚÍÏÖÎÏ ÚÁÇÒÕÚÉÔØ ÂÉÂÌÉÏÔÅËÕ %s"
+
+#: if_perl.xs:554
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr ""
+"éÚ×ÉÎÉÔÅ, ÄÁÎÎÁÑ ËÏÍÁÎÄÁ ÏÔËÌÀÞÅÎÁ: ÎÅ×ÏÚÍÏÖÎÏ ÚÁÇÒÕÚÉÔØ ÂÉÂÌÉÏÔÅËÕ Perl"
+
+#: if_perl.xs:607
+msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+msgstr ""
+"E299: îÅ ÄÏÐÕÓËÁÅÔÓÑ ×ÙÞÉÓÌÅÎÉÅ Perl × ÐÅÓÏÞÎÉÃÅ ÂÅÚ ÍÏÄÕÌÑ ÂÅÚÏÐÁÓÎÏÓÔÉ"
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "òÅÄÁËÔÉÒÏ×ÁÔØ × &ÒÁÚÎÙÈ Vim-ÁÈ"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "òÅÄÁËÔÉÒÏ×ÁÔØ × &ÏÄÎÏÍ Vim"
+
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "&óÒÁ×ÎÉÔØ Ó ÐÏÍÏÝØÀ Vim"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "òÅ&ÄÁËÔÉÒÏ×ÁÔØ Ó ÐÏÍÏÝØÀ Vim"
+
+#. Now concatenate
+#: GvimExt/gvimext.cpp:633
+msgid "Edit with existing Vim - &"
+msgstr "òÅÄÁËÔÉÒÏ×ÁÔØ × ÚÁÐÕÝÅÎÎÏÍ Vim - &"
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "òÅÄÁËÔÉÒÏ×ÁÔØ ×ÙÄÅÌÅÎÎÙÅ ÆÁÊÌÙ Ó ÐÏÍÏÝØÀ Vim"
+
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "ïÛÉÂËÁ ÓÏÚÄÁÎÉÑ ÐÒÏÃÅÓÓÁ: ÐÒÏ×ÅÒØÔÅ ÄÏÓÔÕÐÎÏÓÔØ gvim × ÐÕÔÉ!"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "ÏÛÉÂËÁ gvimext.dll"
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "óÌÉÛËÏÍ ÄÌÉÎÎÙÊ ÐÕÔØ!"
+
+#: globals.h:1022
+msgid "--No lines in buffer--"
+msgstr "-- îÅÔ ÓÔÒÏË × ÂÕÆÅÒÅ --"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1185
+msgid "E470: Command aborted"
+msgstr "E470: ÷ÙÐÏÌÎÅÎÉÅ ËÏÍÁÎÄÙ ÐÒÅÒ×ÁÎÏ"
+
+#: globals.h:1186
+msgid "E471: Argument required"
+msgstr "E471: ôÒÅÂÕÅÔÓÑ ÕËÁÚÁÔØ ÐÁÒÁÍÅÔÒ"
+
+#: globals.h:1187
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: ðÏÓÌÅ \\ ÄÏÌÖÅÎ ÉÄÔÉ ÓÉÍ×ÏÌ /, ? ÉÌÉ &"
+
+#: globals.h:1189
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr ""
+"E11: îÅÄÏÐÕÓÔÉÍÏ × ÏËÎÅ ËÏÍÁÎÄÎÏÊ ÓÔÒÏËÉ; <CR> ×ÙÐÏÌÎÅÎÉÅ, CTRL-C ×ÙÈÏÄ"
+
+#: globals.h:1191
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: ëÏÍÁÎÄÁ ÎÅ ÄÏÐÕÓËÁÅÔÓÑ × exrc/vimrc × ÔÅËÕÝÅÍ ËÁÔÁÌÏÇÅ ÉÌÉ ÐÏÉÓËÅ ÍÅÔÏË"
+
+#: globals.h:1193
+msgid "E171: Missing :endif"
+msgstr "E171: ïÔÓÕÔÓÔ×ÕÅÔ ËÏÍÁÎÄÁ :endif"
+
+#: globals.h:1194
+msgid "E600: Missing :endtry"
+msgstr "E600: ïÔÓÕÔÓÔ×ÕÅÔ ËÏÍÁÎÄÁ :endtry"
+
+#: globals.h:1195
+msgid "E170: Missing :endwhile"
+msgstr "E170: ïÔÓÕÔÓÔ×ÕÅÔ ËÏÍÁÎÄÁ :endwhile"
+
+#: globals.h:1196
+msgid "E588: :endwhile without :while"
+msgstr "E588: ëÏÍÁÎÄÁ :endwhile ÂÅÚ ÐÁÒÎÏÊ ËÏÍÁÎÄÙ :while"
+
+#: globals.h:1198
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: æÁÊÌ ÓÕÝÅÓÔ×ÕÅÔ (ÄÌÑ ÐÅÒÅÚÁÐÉÓÉ ÄÏÂÁ×ØÔÅ !)"
+
+#: globals.h:1199
+msgid "E472: Command failed"
+msgstr "E472: îÅ ÕÄÁÌÏÓØ ×ÙÐÏÌÎÉÔØ ËÏÍÁÎÄÕ"
+
+#: globals.h:1201
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: îÅÉÚ×ÅÓÔÎÙÊ ÛÒÉÆÔÏ×ÏÊ ÎÁÂÏÒ: %s"
+
+#: globals.h:1205
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: îÅÉÚ×ÅÓÔÎÙÊ ÛÒÉÆÔ: %s"
+
+#: globals.h:1208
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: ûÒÉÆÔ \"%s\" ÎÅ Ñ×ÌÑÅÔÓÑ ÍÏÎÏÛÉÒÉÎÎÙÍ ÛÒÉÆÔÏÍ"
+
+#: globals.h:1210
+msgid "E473: Internal error"
+msgstr "E473: ÷ÎÕÔÒÅÎÎÑÑ ÏÛÉÂËÁ"
+
+#: globals.h:1211
+msgid "Interrupted"
+msgstr "ðÒÅÒ×ÁÎÏ"
+
+#: globals.h:1212
+msgid "E14: Invalid address"
+msgstr "E14: îÅÄÏÐÕÓÔÉÍÙÊ ÁÄÒÅÓ"
+
+#: globals.h:1213
+msgid "E474: Invalid argument"
+msgstr "E474: îÅÄÏÐÕÓÔÉÍÙÊ ÁÒÇÕÍÅÎÔ"
+
+#: globals.h:1214
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: îÅÄÏÐÕÓÔÉÍÙÊ ÁÒÇÕÍÅÎÔ: %s"
+
+#: globals.h:1216
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: îÅÄÏÐÕÓÔÉÍÏÅ ×ÙÒÁÖÅÎÉÅ: %s"
+
+#: globals.h:1218
+msgid "E16: Invalid range"
+msgstr "E16: îÅÄÏÐÕÓÔÉÍÙÊ ÄÉÁÐÁÚÏÎ"
+
+#: globals.h:1219
+msgid "E476: Invalid command"
+msgstr "E476: îÅÄÏÐÕÓÔÉÍÁÑ ËÏÍÁÎÄÁ"
+
+#: globals.h:1221
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" Ñ×ÌÑÅÔÓÑ ËÁÔÁÌÏÇÏÍ"
+
+#: globals.h:1224
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: ðÅÒÅÄ '=' ÏÂÎÁÒÕÖÅÎÙ ÎÅÏÖÉÄÁÎÎÙÅ ÓÉÍ×ÏÌÙ"
+
+#: globals.h:1227
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: îÅÕÄÁÞÎÙÊ ×ÙÚÏ× ÆÕÎËÃÉÉ \"%s()\" ÉÚ ÂÉÂÌÉÏÔÅËÉ"
+
+#: globals.h:1233
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: îÅ ÕÄÁÌÏÓØ ÚÁÇÒÕÚÉÔØ ÆÕÎËÃÉÀ %s ÉÚ ÂÉÂÌÉÏÔÅËÉ"
+
+#: globals.h:1235
+msgid "E19: Mark has invalid line number"
+msgstr "E19: ïÔÍÅÔËÁ ÕËÁÚÙ×ÁÅÔ ÎÁ ÎÅÐÒÁ×ÉÌØÎÙÊ ÎÏÍÅÒ ÓÔÒÏËÉ"
+
+#: globals.h:1236
+msgid "E20: Mark not set"
+msgstr "ïÔÍÅÔËÁ ÎÅ ÏÐÒÅÄÅÌÅÎÁ"
+
+#: globals.h:1237
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: éÚÍÅÎÅÎÉÑ ÎÅ×ÏÚÍÏÖÎÙ, ÔÁË ËÁË ÏÔËÌÀÞÅÎÁ ÏÐÃÉÑ 'modifiable'"
+
+#: globals.h:1238
+msgid "E22: Scripts nested too deep"
+msgstr "E22: óÌÉÛËÏÍ ÇÌÕÂÏËÏ ×ÌÏÖÅÎÎÙÅ ÓÃÅÎÁÒÉÉ"
+
+#: globals.h:1239
+msgid "E23: No alternate file"
+msgstr "E23: óÏÓÅÄÎÉÊ ÆÁÊÌ ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+
+#: globals.h:1240
+msgid "E24: No such abbreviation"
+msgstr "E24: îÅÔ ÔÁËÏÇÏ ÓÏËÒÁÝÅÎÉÑ"
+
+#: globals.h:1241
+msgid "E477: No ! allowed"
+msgstr "E477: ! ÎÅ ÄÏÐÕÓËÁÅÔÓÑ"
+
+#: globals.h:1243
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr ""
+"E25: ÷ÏÚÍÏÖÎÏÓÔØ ÉÓÐÏÌØÚÏ×ÁÎÉÑ ÇÒÁÆÉÞÅÓËÏÇÏ ÉÎÔÅÒÆÅÊÓÁ ×ÙËÌÀÞÅÎÁ ÐÒÉ "
+"ËÏÍÐÉÌÑÃÉÉ"
+
+#: globals.h:1246
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: é×ÒÉÔ ×ÙËÌÀÞÅÎ ÐÒÉ ËÏÍÐÉÌÑÃÉÉ\n"
+
+#: globals.h:1249
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: æÁÒÓÉ ×ÙËÌÀÞÅÎÏ ÐÒÉ ËÏÍÐÉÌÑÃÉÉ\n"
+
+#: globals.h:1252
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: áÒÁÂÓËÉÊ ×ÙËÌÀÞÅÎ ÐÒÉ ËÏÍÐÉÌÑÃÉÉ\n"
+
+#: globals.h:1255
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: çÒÕÐÐÁ ÐÏÄÓ×ÅÔËÉ ÓÉÎÔÁËÓÉÓÁ %s ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+
+#: globals.h:1257
+msgid "E29: No inserted text yet"
+msgstr "E29: ðÏËÁ ÎÅÔ ×ÓÔÁ×ÌÅÎÎÏÇÏ ÔÅËÓÔÁ"
+
+#: globals.h:1258
+msgid "E30: No previous command line"
+msgstr "E30: ðÒÅÄÙÄÕÝÅÊ ËÏÍÁÎÄÎÏÊ ÓÔÒÏËÉ ÎÅÔ"
+
+#: globals.h:1259
+msgid "E31: No such mapping"
+msgstr "E31: ôÁËÏÊ ÐÒÉ×ÑÚËÉ ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+
+#: globals.h:1260
+msgid "E479: No match"
+msgstr "E479: îÅÔ ÓÏÏÔ×ÅÔÓÔ×ÉÑ"
+
+#: globals.h:1261
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: îÅÔ ÓÏÏÔ×ÅÔÓÔ×ÉÑ: %s"
+
+#: globals.h:1262
+msgid "E32: No file name"
+msgstr "E32: îÅÔ ÉÍÅÎÉ ÆÁÊÌÁ"
+
+#: globals.h:1263
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: îÅÔ ÐÒÅÄÙÄÕÝÅÇÏ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑ ÄÌÑ ÚÁÍÅÎÙ"
+
+#: globals.h:1264
+msgid "E34: No previous command"
+msgstr "E34: îÅÔ ÐÒÅÄÙÄÕÝÅÊ ËÏÍÁÎÄÙ"
+
+#: globals.h:1265
+msgid "E35: No previous regular expression"
+msgstr "E35: îÅÔ ÐÒÅÄÙÄÕÝÅÇÏ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑ"
+
+#: globals.h:1266
+msgid "E481: No range allowed"
+msgstr "E481: éÓÐÏÌØÚÏ×ÁÎÉÅ ÄÉÁÐÁÚÏÎÁ ÎÅ ÄÏÐÕÓËÁÅÔÓÑ"
+
+#: globals.h:1268
+msgid "E36: Not enough room"
+msgstr "E36: îÅÄÏÓÔÁÔÏÞÎÏ ÍÅÓÔÁ"
+
+#: globals.h:1271
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: ÓÅÒ×ÅÒ \"%s\" ÎÅ ÚÁÒÅÇÉÓÔÒÉÒÏ×ÁÎ"
+
+#: globals.h:1273
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÆÁÊÌ %s"
+
+#: globals.h:1274
+msgid "E483: Can't get temp file name"
+msgstr "E483: îÅ×ÏÚÍÏÖÎÏ ÐÏÌÕÞÉÔØ ÉÍÑ ×ÒÅÍÅÎÎÏÇÏ ÆÁÊÌÁ"
+
+#: globals.h:1275
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ %s"
+
+#: globals.h:1276
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ÆÁÊÌ %s"
+
+#: globals.h:1277
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: éÚÍÅÎÅÎÉÑ ÎÅ ÓÏÈÒÁÎÅÎÙ (ÄÏÂÁ×ØÔÅ !, ÞÔÏÂÙ ÏÂÏÊÔÉ ÐÒÏ×ÅÒËÕ)"
+
+#: globals.h:1278
+msgid "E38: Null argument"
+msgstr "E38: îÕÌÅ×ÏÊ ÁÒÇÕÍÅÎÔ"
+
+#: globals.h:1280
+msgid "E39: Number expected"
+msgstr "E39: ôÒÅÂÕÅÔÓÑ ÞÉÓÌÏ"
+
+#: globals.h:1283
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: îÅ ÕÄÁÌÏÓØ ÏÔËÒÙÔØ ÆÁÊÌ ÏÛÉÂÏË %s"
+
+#: globals.h:1286
+msgid "E233: cannot open display"
+msgstr "E233: ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÄÉÓÐÌÅÊ"
+
+#: globals.h:1288
+msgid "E41: Out of memory!"
+msgstr "E41: îÅ È×ÁÔÁÅÔ ÐÁÍÑÔÉ!"
+
+#: globals.h:1290
+msgid "Pattern not found"
+msgstr "ûÁÂÌÏÎ ÎÅ ÎÁÊÄÅÎ"
+
+#: globals.h:1292
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: ûÁÂÌÏÎ ÎÅ ÎÁÊÄÅÎ: %s"
+
+#: globals.h:1293
+msgid "E487: Argument must be positive"
+msgstr "E487: ðÁÒÁÍÅÔÒ ÄÏÌÖÅÎ ÂÙÔØ ÐÏÌÏÖÉÔÅÌØÎÙÍ ÞÉÓÌÏÍ"
+
+#: globals.h:1295
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: ÷ÏÚ×ÒÁÔ × ÐÒÅÄÙÄÕÝÉÊ ËÁÔÁÌÏÇ ÎÅ×ÏÚÍÏÖÅÎ"
+
+#: globals.h:1299
+msgid "E42: No Errors"
+msgstr "E42: ïÛÉÂÏË ÎÅÔ"
+
+#: globals.h:1301
+msgid "E43: Damaged match string"
+msgstr "E43: ðÏ×ÒÅÖÄÅÎÁ ÓÔÒÏËÁ ÓÏÏÔ×ÅÔÓÔ×ÉÑ"
+
+#: globals.h:1302
+msgid "E44: Corrupted regexp program"
+msgstr "E44: ðÒÏÇÒÁÍÍÁ ÏÂÒÁÂÏÔËÉ ÒÅÇÕÌÑÒÎÙÈ ×ÙÒÁÖÅÎÉÊ ÐÏ×ÒÅÖÄÅÎÁ"
+
+#: globals.h:1303
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr ""
+"E45: ÷ËÌÀÞÅÎÁ ÏÐÃÉÑ 'readonly' (ÄÏÂÁ×ØÔÅ !, ÞÔÏÂÙ ÎÅ ÏÂÒÁÝÁÔØ ×ÎÉÍÁÎÉÑ)"
+
+#: globals.h:1305
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: îÅ×ÏÚÍÏÖÎÏ ÉÚÍÅÎÉÔØ ÄÏÓÔÕÐÎÕÀ ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ ÐÅÒÅÍÅÎÎÕÀ \"%s\""
+
+#: globals.h:1308
+msgid "E47: Error while reading errorfile"
+msgstr "E47: ïÛÉÂËÁ ÐÒÉ ÞÔÅÎÉÉ ÆÁÊÌÁ ÏÛÉÂÏË"
+
+#: globals.h:1311
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: îÅ ÄÏÐÕÓËÁÅÔÓÑ × ÐÅÓÏÞÎÉÃÅ"
+
+#: globals.h:1313
+msgid "E523: Not allowed here"
+msgstr "E523: úÄÅÓØ ÎÅ ÒÁÚÒÅÛÅÎÏ"
+
+#: globals.h:1316
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: äÁÎÎÙÊ ÒÅÖÉÍ ÜËÒÁÎÁ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ"
+
+#: globals.h:1318
+msgid "E49: Invalid scroll size"
+msgstr "E49: îÅÄÏÐÕÓÔÉÍÙÊ ÒÁÚÍÅÒ ÐÒÏËÒÕÔËÉ"
+
+#: globals.h:1319
+msgid "E91: 'shell' option is empty"
+msgstr "E91: úÎÁÞÅÎÉÅÍ ÏÐÃÉÉ 'shell' Ñ×ÌÑÅÔÓÑ ÐÕÓÔÁÑ ÓÔÒÏËÁ"
+
+#: globals.h:1321
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ÄÁÎÎÙÅ Ï ÚÎÁÞËÁÈ!"
+
+#: globals.h:1323
+msgid "E72: Close error on swap file"
+msgstr "E72: ïÛÉÂËÁ ÚÁËÒÙÔÉÑ Ó×ÏÐ-ÆÁÊÌÁ"
+
+#: globals.h:1324
+msgid "E73: tag stack empty"
+msgstr "E73: óÔÅË ÍÅÔÏË ÐÕÓÔÏÊ"
+
+#: globals.h:1325
+msgid "E74: Command too complex"
+msgstr "E74: óÌÉÛËÏÍ ÓÌÏÖÎÁÑ ËÏÍÁÎÄÁ"
+
+#: globals.h:1326
+msgid "E75: Name too long"
+msgstr "E75: óÌÉÛËÏÍ ÄÌÉÎÎÏÅ ÉÍÑ"
+
+#: globals.h:1327
+msgid "E76: Too many ["
+msgstr "E76: óÌÉÛËÏÍ ÍÎÏÇÏ ÓÉÍ×ÏÌÏ× ["
+
+#: globals.h:1328
+msgid "E77: Too many file names"
+msgstr "E77: óÌÉÛËÏÍ ÍÎÏÇÏ ÉͣΠÆÁÊÌÏ×"
+
+#: globals.h:1329
+msgid "E488: Trailing characters"
+msgstr "E488: ìÉÛÎÉÅ ÓÉÍ×ÏÌÙ ÎÁ È×ÏÓÔÅ"
+
+#: globals.h:1330
+msgid "E78: Unknown mark"
+msgstr "E78: îÅÉÚ×ÅÓÔÎÁÑ ÏÔÍÅÔËÁ"
+
+#: globals.h:1331
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÐÏÄÓÔÁÎÏ×ËÕ ÐÏ ÍÁÓËÅ"
+
+#: globals.h:1333
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr ""
+"E591: úÎÁÞÅÎÉÅ ÏÐÃÉÉ 'winheight' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÍÅÎØÛÅ ÚÎÁÞÅÎÉÑ 'winminheight'"
+
+#: globals.h:1335
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr ""
+"E592: úÎÁÞÅÎÉÅ ÏÐÃÉÉ 'winwidth' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÍÅÎØÛÅ ÚÎÁÞÅÎÉÑ 'winminwidth'"
+
+#: globals.h:1338
+msgid "E80: Error while writing"
+msgstr "E80: ïÛÉÂËÁ ÐÒÉ ÚÁÐÉÓÉ"
+
+#: globals.h:1339
+msgid "Zero count"
+msgstr "îÕÌÅ×ÏÅ ÚÎÁÞÅÎÉÅ ÓÞ£ÔÞÉËÁ"
+
+#: globals.h:1341
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: éÓÐÏÌØÚÏ×ÁÎÉÅ <SID> ×ÎÅ ËÏÎÔÅËÓÔÁ ÓÃÅÎÁÒÉÑ"
+
+#: globals.h:1344
+msgid "E449: Invalid expression received"
+msgstr "E449: ðÏÌÕÞÅÎÏ ÎÅÄÏÐÕÓÔÉÍÏÅ ×ÙÒÁÖÅÎÉÅ"
+
+#: globals.h:1347
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: îÅ×ÏÚÍÏÖÎÏ ÉÚÍÅÎÉÔØ ÏÈÒÁÎÑÅÍÕÀ ÏÂÌÁÓÔØ"
+
+#~ msgid "\"\n"
+#~ msgstr "\"\n"
diff --git a/src/po/sjiscorr.c b/src/po/sjiscorr.c
new file mode 100644
index 000000000..d7706ba73
--- /dev/null
+++ b/src/po/sjiscorr.c
@@ -0,0 +1,50 @@
+/*
+ * Simplistic program to correct SJIS inside strings. When a trail byte is a
+ * backslash it needs to be doubled.
+ * Public domain.
+ */
+#include <stdio.h>
+#include <string.h>
+
+ int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char buffer[BUFSIZ];
+ char *p;
+
+ while (fgets(buffer, BUFSIZ, stdin) != NULL)
+ {
+ for (p = buffer; *p != 0; p++)
+ {
+ if (strncmp(p, "charset=euc-jp", 14) == 0)
+ {
+ fputs("charset=cp932", stdout);
+ p += 13;
+ }
+ else if (strncmp(p, "ja.po - Japanese message file", 29) == 0)
+ {
+ fputs("ja.sjis.po - Japanese message file for Vim (version 6.x)\n", stdout);
+ fputs("# generated from ja.po, DO NOT EDIT", stdout);
+ while (p[1] != '\n')
+ ++p;
+ }
+ else if (*(unsigned char *)p == 0x81 && p[1] == '_')
+ {
+ putchar('\\');
+ ++p;
+ }
+ else
+ {
+ if (*p & 0x80)
+ {
+ putchar(*p++);
+ if (*p == '\\')
+ putchar(*p);
+ }
+ putchar(*p);
+ }
+ }
+ }
+}
diff --git a/src/po/sk.cp1250.po b/src/po/sk.cp1250.po
new file mode 100644
index 000000000..3e91ad567
--- /dev/null
+++ b/src/po/sk.cp1250.po
@@ -0,0 +1,5998 @@
+# Slovak translation of vim
+# Martin Lacko <lacko@host.sk>, 2001.
+#
+# Generated from sk.po, DO NOT EDIT.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: vim\n"
+"POT-Creation-Date: 2002-03-26 21:54+0100\n"
+"PO-Revision-Date: 2002-03-26 21:58CEST\n"
+"Last-Translator: Martin Lacko <lacko@host.sk>\n"
+"Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=cp1250\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 0.9.5\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Nedá sa alokova buffer, konèím..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: Nedá sa alokova buffer, použijem iný..."
+
+#: buffer.c:706
+msgid "No buffers were unloaded"
+msgstr "Žiadny buffer nebol nájdený"
+
+#: buffer.c:708
+msgid "No buffers were deleted"
+msgstr "Žiadny buffer nebol vymazaný"
+
+#: buffer.c:710
+msgid "No buffers were wiped out"
+msgstr "Žiadny buffer nebol vymazaný"
+
+#: buffer.c:718
+msgid "1 buffer unloaded"
+msgstr "poèet deaktivovaných bufferov: 1"
+
+#: buffer.c:720
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "poèet deaktivovaných bufferov: %d"
+
+#: buffer.c:725
+msgid "1 buffer deleted"
+msgstr "poèet vymazaných bufferov: 1"
+
+#: buffer.c:727
+#, c-format
+msgid "%d buffers deleted"
+msgstr "poèet vymazaných bufferov: %d"
+
+#: buffer.c:732
+msgid "1 buffer wiped out"
+msgstr "poèet vymazaných bufferov: 1"
+
+#: buffer.c:734
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "poèet vymazaných bufferov: %d"
+
+#: buffer.c:791
+msgid "E84: No modified buffer found"
+msgstr "E84: Nebol nájdený žiadny zmenený buffer"
+
+#. back where we started, didn't find anything.
+#: buffer.c:830
+msgid "E85: There is no listed buffer"
+msgstr "E85: Nenašiel som žiadny buffer"
+
+#: buffer.c:842
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: Nedá sa preskoèi na buffer %ld"
+
+#: buffer.c:845
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Za posledný buffer sa nedá preskoèi"
+
+#: buffer.c:847
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Pred prvý buffer sa nedá preskoèi"
+
+#: buffer.c:871
+#, c-format
+msgid "E89: No write since last change for buffer %ld (use ! to override)"
+msgstr "E89: Zmeny v bufferi %ld neboly uložené (! pre vynútenie)"
+
+#: buffer.c:887
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: Posledný buffer sa nedá odstráni"
+
+#: buffer.c:1337
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Varovanie: preteèenie zoznamu s názvami súborov"
+
+#: buffer.c:1503
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: buffer %ld nenájdený"
+
+#: buffer.c:1729
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Vzoru %s vyhovuje viac bufferov"
+
+#: buffer.c:1731
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: Vzoru %s nevyhovuje žiadny buffer"
+
+#: buffer.c:2136 ex_docmd.c:6089
+#, c-format
+msgid "line %ld"
+msgstr "riadok %ld"
+
+#: buffer.c:2219
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Buffer takéhoto mena už existuje"
+
+#: buffer.c:2512
+msgid " [Modified]"
+msgstr " [zmenený]"
+
+#: buffer.c:2517
+msgid "[Not edited]"
+msgstr "[neupravovaný]"
+
+#: buffer.c:2522
+msgid "[New file]"
+msgstr "[nový súbor]"
+
+#: buffer.c:2523
+msgid "[Read errors]"
+msgstr "[chyby pri èítaní]"
+
+#: buffer.c:2525 fileio.c:1777
+msgid "[readonly]"
+msgstr "[iba pre èítanie]"
+
+#: buffer.c:2540
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 riadok --%d%%--"
+
+#: buffer.c:2542
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "riadkov: %ld --%d%%--"
+
+#: buffer.c:2549
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "riadok %ld z %ld --%d%%-- ståpec"
+
+#: buffer.c:2637
+msgid "[No file]"
+msgstr "[žiadny súbor]"
+
+#. must be a help buffer
+#: buffer.c:2677
+msgid "help"
+msgstr "pomocník"
+
+#: buffer.c:3186 screen.c:4743
+msgid "[help]"
+msgstr "[pomocník]"
+
+#: buffer.c:3218 screen.c:4749
+msgid "[Preview]"
+msgstr "[náh¾ad]"
+
+#: buffer.c:3424
+msgid "All"
+msgstr "Všetko"
+
+#: buffer.c:3424
+msgid "Bot"
+msgstr "Koniec"
+
+#: buffer.c:3426
+msgid "Top"
+msgstr "Zaèiatok"
+
+#: buffer.c:4162
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# zoznam bufferov:\n"
+
+#: buffer.c:4195
+msgid "[Error List]"
+msgstr "[zoznam chýb]"
+
+#: buffer.c:4208 memline.c:1513
+msgid "[No File]"
+msgstr "[žiadny súbor]"
+
+#: buffer.c:4428
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Znaky ---"
+
+#: buffer.c:4438
+#, c-format
+msgid "Signs for %s:"
+msgstr "Znaky pre %s:"
+
+#: buffer.c:4444
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " line=%ld id=%d meno=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: Nemôžem porovna viac ako %ld bufferov"
+
+#: diff.c:648
+msgid "E97: Cannot create diffs"
+msgstr "E97: Nedajú sa vytvori porovnania"
+
+#: diff.c:747
+msgid "Patch file"
+msgstr "Opravný súbor"
+
+#: diff.c:991
+msgid "E98: Cannot read diff output"
+msgstr "E98: Nedá sa èíta výstup porovnania"
+
+#: diff.c:1732
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Aktuálny buffer nie je v porovnacom móde"
+
+#: diff.c:1744
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: V porovnávacom móde sa nenachádza iný buffer"
+
+#: diff.c:1752
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: Viac ako dva buffery v porovnávacom móde; neviem, ktorý použi"
+
+#: diff.c:1775
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Nedá sa nájs buffer \"%s\""
+
+#: diff.c:1781
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Buffer \"%s\" nie je v porovnávacom móde"
+
+#: digraph.c:2172
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: diagraph nesmie obsahova Escape"
+
+#: digraph.c:2344
+msgid "Keymap file not found"
+msgstr "Mapa kláves nenájdená"
+
+#: digraph.c:2371
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: Použite :loadkeymap v súbore, ktorý nie je zdrojový"
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " Doplòovanie k¾úèových slov (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " ^X režim (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " Miestne dopåòanie k¾úèových slov (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " Doplòovanie celých riadkov (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " Doplòovanie názvov súborov (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " Doplòovanie tagov (^]/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " Doplòovanie vzoru ciest (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " Doplòovanie definícií (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " Doplòovanie pod¾a slovníka (^K/^N/^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Doplòovanie pod¾a tezauru (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " Doplòovòovanie príkazového riadka (^V/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Koniec odstavca"
+
+#: edit.c:907
+msgid "'thesaurus' option is empty"
+msgstr "vo¾ba 'thesaurus' je prázdna"
+
+#: edit.c:1083
+msgid "'dictionary' option is empty"
+msgstr "vo¾ba 'dictionary' je prázdna"
+
+#: edit.c:2007
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "preh¾adávam slovník %s"
+
+#: edit.c:2198
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (insert) Rolovanie (^E/^Y)"
+
+#: edit.c:2200
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (replace) Rolovanie (^E/^Y)"
+
+#: edit.c:2512
+#, c-format
+msgid "Scanning: %s"
+msgstr "Preh¾adávam: %s"
+
+#: edit.c:2547
+msgid "Scanning tags."
+msgstr "Preh¾adávam tagy."
+
+#: edit.c:3207
+msgid " Adding"
+msgstr " Pridávam"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3256
+msgid "-- Searching..."
+msgstr "-- H¾adám..."
+
+#: edit.c:3312
+msgid "Back at original"
+msgstr "Východzia podoba"
+
+#: edit.c:3317
+msgid "Word from other line"
+msgstr "Slovo z iného riadku"
+
+#: edit.c:3322
+msgid "The only match"
+msgstr "Jediná zhoda"
+
+#: edit.c:3381
+#, c-format
+msgid "match %d of %d"
+msgstr "zhoda %d z %d"
+
+#: edit.c:3384
+#, c-format
+msgid "match %d"
+msgstr "zhoda %d"
+
+#: eval.c:698
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Neznáma premenná: \"%s\""
+
+#: eval.c:977
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Chýbjú závorky: %s"
+
+#: eval.c:1057 eval.c:1073
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Premenná \"%s\" neexistuje"
+
+#: eval.c:1315
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Po '?' chýba ':'"
+
+#: eval.c:1929
+msgid "E110: Missing ')'"
+msgstr "E110: Chýba ')'"
+
+#: eval.c:1979
+msgid "E111: Missing ']'"
+msgstr "E111: Chýba ']'"
+
+#: eval.c:2054
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Chýba meno vo¾by: %s"
+
+#: eval.c:2072
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Neznáma vo¾ba: %s"
+
+#: eval.c:2134
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Chýbjú uvodzovky: %s"
+
+#: eval.c:2251
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Chýbjú uvodzovky: %s"
+
+#: eval.c:2569
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Chybné argumenty pre funkciu %s"
+
+#: eval.c:2570
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Neznáma funkcia: %s"
+
+#: eval.c:2571
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: Príliš mnoho argumentov pre funkciu %s"
+
+#: eval.c:2572
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Príliš málo argumentov pre funkciu %s"
+
+#: eval.c:2573
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: Použitie <SID> mimo kontext skriptu: %s"
+
+#: eval.c:3172 gui.c:3984
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:3678
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld riadky: "
+
+#: eval.c:4794
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&Ok\n"
+"&Zruši"
+
+#: eval.c:5626
+msgid "E240: No connection to Vim server"
+msgstr "E240: Neexistuje pripojenie k Vim serveru"
+
+#: eval.c:5716
+msgid "E277: Unable to read a server reply"
+msgstr "E227: Nemôžem èíta odpoveï servra"
+
+#: eval.c:5741
+msgid "E258: Unable to send to client"
+msgstr "E258: Nemôžem posla klientovi"
+
+#: eval.c:5786
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Nemôžem posla na %s"
+
+#: eval.c:5884
+msgid "(Invalid)"
+msgstr "(Chybný)"
+
+#: eval.c:6895
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Nedefinovaná premenná: %s"
+
+#: eval.c:7593
+#, c-format
+msgid "E122: Function %s already exists, use ! to replace"
+msgstr "E112: Funkcia %s už existuje. Použite ! pre jej nahradenie."
+
+#: eval.c:7635
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Nedefinovaná funkcia: %s"
+
+#: eval.c:7648
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Chýba '(': %s"
+
+#: eval.c:7680
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Neprístupný argument: %s"
+
+#: eval.c:7766
+msgid "E126: Missing :endfunction"
+msgstr "E126: Chýba :endfunction"
+
+#: eval.c:7845
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Nedá sa predefinova funkcia %s: je používaná"
+
+#: eval.c:7903
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: Názov funkcie musí zaèína ve¾kým písmenom: %s"
+
+#: eval.c:7909
+msgid "E129: Function name required"
+msgstr "E129: Je vyžadované meno funkcie"
+
+#: eval.c:8002
+msgid "function "
+msgstr "funkcia "
+
+#: eval.c:8117
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Nedefinovaná funkcia: %s"
+
+#: eval.c:8122
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Nedá sa vymaza funkcia %s: je už používaná"
+
+#: eval.c:8169
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: Zanorenie funkcií je hlbšie než 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:8220
+#, c-format
+msgid "calling %s"
+msgstr "volám %s"
+
+#. always scroll up, don't overwrite
+#: eval.c:8245 ex_cmds2.c:1988
+#, c-format
+msgid "continuing in %s"
+msgstr "pokraèujem v %s"
+
+#: eval.c:8299
+msgid "E133: :return not inside a function"
+msgstr "E133: :return mimo funkciu"
+
+#: eval.c:8377
+#, c-format
+msgid "%s returning #%ld"
+msgstr "dokonèené %s. Návratová hodnota %ld"
+
+#: eval.c:8380
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "dokonèené %s. Návratová hodnota \"%s\""
+
+#: eval.c:8521
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# globálne premenné:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, šestnástkovo %02x, osmièkovo %03o"
+
+#: ex_cmds.c:428
+msgid "E134: Move lines into themselves"
+msgstr "E134: Prekrytie riadkov sebou samými"
+
+#: ex_cmds.c:497
+msgid "1 line moved"
+msgstr "poèet prerušených riadkov: 1"
+
+#: ex_cmds.c:499
+#, c-format
+msgid "%ld lines moved"
+msgstr "poèet prerušených riadkov: %ld"
+
+#: ex_cmds.c:890
+#, c-format
+msgid "%ld lines filtered"
+msgstr "poèet filtrovaných riadkov: %ld"
+
+#: ex_cmds.c:918
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: Automatické príkazy *Filter* nesmie meni aktuálny buffer"
+
+#: ex_cmds.c:1003
+msgid "[No write since last change]\n"
+msgstr "[Neuložené zmeny]\n"
+
+#: ex_cmds.c:1248
+#, c-format
+msgid "viminfo: %s in line: "
+msgstr "viminfo: %s na riadku: "
+
+#: ex_cmds.c:1253
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: príliš mnoho chýb, preskakujem zbytok súboru"
+
+#: ex_cmds.c:1282
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Èítam viminfo súbor \"%s\"%s%s%s"
+
+#: ex_cmds.c:1283
+msgid " info"
+msgstr " informácie"
+
+#: ex_cmds.c:1284
+msgid " marks"
+msgstr " znaèky"
+
+#: ex_cmds.c:1285
+msgid " FAILED"
+msgstr " ZLYHALO"
+
+#: ex_cmds.c:1376
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Do viminfo súboru %s sa nedá zapisova"
+
+#: ex_cmds.c:1501
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Nedá sa uloži viminfo súbor %s!"
+
+#: ex_cmds.c:1509
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Ukládám viminfo súboru \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1610
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Tento viminfo súbor bol vytvorený editorom Vim %s.\n"
+
+#: ex_cmds.c:1612
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Pokia¾ budete opatrnný, môžete ho upravova.\n"
+"\n"
+
+#: ex_cmds.c:1614
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Hodnota 'encoding' poèas zápisu tohoto súboru\n"
+
+#: ex_cmds.c:1713
+msgid "Illegal starting char"
+msgstr "Neprístupný zaèiatoèný znak"
+
+#: ex_cmds.c:2053 ex_cmds.c:2310 ex_cmds2.c:602
+msgid "Save As"
+msgstr "Uloži ako"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2096
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Súbor je naèítaný v inob buffere"
+
+#: ex_cmds.c:2130
+msgid "Write partial file?"
+msgstr "Uloži neúplný súbor?"
+
+#: ex_cmds.c:2137
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Použite ! pre uloženie neúplného bufferu"
+
+#: ex_cmds.c:2244
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Prepísa súbor \"%.*s\"?"
+
+#: ex_cmds.c:2315
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: Žiadny názov súboru pre buffer %ld"
+
+#: ex_cmds.c:2353
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: Súbor nebol uložený: ukladanie je zakázané vo¾bou 'write'"
+
+#: ex_cmds.c:2373
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"Pre \"%.*s\" je nastavená vo¾ba 'readonly' (iba na èítanie).\n"
+"Prajete si ju potlaèi?"
+
+#: ex_cmds.c:2538
+msgid "Edit File"
+msgstr "Upravova súbor"
+
+#: ex_cmds.c:3061
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Automatické príkazy neoèakávane zmazali nový buffer %s"
+
+#: ex_cmds.c:3193
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: neèíselný argument pre :z"
+
+#: ex_cmds.c:3278
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: rvim nepovoluje použitie príkazov shellu"
+
+#: ex_cmds.c:3385
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Regulárne výrazy nesmú by oddelené písmenami"
+
+#: ex_cmds.c:3727
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "nahradi %s (y/n/a/q/I/^E/^Y)?"
+
+#: ex_cmds.c:4092
+msgid "(Interrupted) "
+msgstr "(prerušený) "
+
+#: ex_cmds.c:4096
+msgid "1 substitution"
+msgstr "poèet nahradení na riadok: 1"
+
+#: ex_cmds.c:4098
+#, c-format
+msgid "%ld substitutions"
+msgstr "poèet nahradení na riadok: %ld"
+
+#: ex_cmds.c:4101
+msgid " on 1 line"
+msgstr " na 1 riadku"
+
+#: ex_cmds.c:4103
+#, c-format
+msgid " on %ld lines"
+msgstr " na %ld riadkov"
+
+#: ex_cmds.c:4154
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: global nedá sa vola rekurzívne"
+
+#: ex_cmds.c:4189
+msgid "E148: Regular expression missing from global"
+msgstr "E148: Pri príkaze global chýba regulárny výraz"
+
+#: ex_cmds.c:4238
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Vzor nájdený na každom riadku: %s"
+
+#: ex_cmds.c:4319
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Posledný Reazec Podnadpisu:\n"
+"$"
+
+#: ex_cmds.c:4421
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: ¼utujem, pre %s nie je žiadny pomocník"
+
+#: ex_cmds.c:4455
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "¼utujem, súbor \"%s\" s pomocníkom nebol nájdený"
+
+#: ex_cmds.c:4917
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s nie je adresárom"
+
+#: ex_cmds.c:4945
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: Nedá sa otvori %s pre zápis"
+
+#: ex_cmds.c:4959
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Nedá sa otvori %s pre zápis"
+
+#: ex_cmds.c:5038
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: Duplicitný tag \"%s\" v súbore %s"
+
+#: ex_cmds.c:5139
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Neznáma funkcia: %s"
+
+#: ex_cmds.c:5159
+msgid "E156: Missing sign name"
+msgstr "E156: Chýba identifikátor pre sign"
+
+#: ex_cmds.c:5205
+msgid "E255: Too many signs defined"
+msgstr "E255: Príliš mnoho definovaných oznaèení"
+
+#: ex_cmds.c:5247
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Chybne oznaèený text: %s"
+
+#: ex_cmds.c:5271 ex_cmds.c:5457
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Neznáme oznaèenie: %s"
+
+#: ex_cmds.c:5317
+msgid "E159: Missing sign number"
+msgstr "E159: Chýba èislo oznaèenia"
+
+#: ex_cmds.c:5397
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: Chybné meno bufferu: %s"
+
+#: ex_cmds.c:5436
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Chybné ID oznaèenia: %ld"
+
+#: ex_cmds.c:5607
+msgid "[Deleted]"
+msgstr "[vymazaný]"
+
+#: ex_cmds2.c:70
+msgid "Entering Debug mode. Type \"cont\" to leave."
+msgstr "Spúšam režim ladenia. Pre ukonèenie napíšte \"cont\"."
+
+#: ex_cmds2.c:74 ex_docmd.c:771
+#, c-format
+msgid "line %ld: %s"
+msgstr "riadok %ld: %s"
+
+#: ex_cmds2.c:76
+#, c-format
+msgid "cmd: %s"
+msgstr "príkaz: %s"
+
+#: ex_cmds2.c:224
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Bod prerušenia v \"%s%s\" na riadku %ld"
+
+#: ex_cmds2.c:388
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Bod prerušenia nenájdený: %s"
+
+#: ex_cmds2.c:414
+msgid "No breakpoints defined"
+msgstr "Neboli definovné žiadne body prerušenia"
+
+#: ex_cmds2.c:419
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s riadok %ld"
+
+#: ex_cmds2.c:625
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Uloži zmeny do \"%.*s\"?"
+
+#: ex_cmds2.c:627 ex_docmd.c:8667
+msgid "Untitled"
+msgstr "Bez mena"
+
+#: ex_cmds2.c:763
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Buffer \"%s\" obsahuje neuložené zmeny"
+
+#: ex_cmds2.c:832
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "Varovanie: Neèakaný vstup do iného bufferu (skontrolujte automatické príkazy)"
+
+#: ex_cmds2.c:1208
+msgid "E163: There is only one file to edit"
+msgstr "E163: Pre úpravu bol zadaný iba jeden súbor"
+
+#: ex_cmds2.c:1210
+msgid "E164: Cannot go before first file"
+msgstr "E164: Pred prvý súbor sa nedá preskoèi"
+
+#: ex_cmds2.c:1212
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Za posledný súbor sa nedá preskoèi"
+
+#: ex_cmds2.c:1634
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "H¾adám \"%s\" v \"%s\""
+
+#: ex_cmds2.c:1656
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "H¾adám \"%s\""
+
+#: ex_cmds2.c:1680
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "súbor \"%s\" nebol nájdený v 'runtimepath'"
+
+#: ex_cmds2.c:1714
+msgid "Source Vim script"
+msgstr "Zdrojový skript Vim"
+
+#: ex_cmds2.c:1832
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "\"%s\" nie je adresárom"
+
+#: ex_cmds2.c:1862
+#, c-format
+msgid "could not source \"%s\""
+msgstr "nedá sa interpretova \"%s\""
+
+#: ex_cmds2.c:1864
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "riadok %ld: nemôže by zdroj \"%s\""
+
+#: ex_cmds2.c:1878
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "interpretujem \"%s\""
+
+#: ex_cmds2.c:1880
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "riadok %ld je zdrojom \"%s\""
+
+#: ex_cmds2.c:1986
+#, c-format
+msgid "finished sourcing %s"
+msgstr "dokonèená interpretácia %s"
+
+#: ex_cmds2.c:2287
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Varovanie: chybný odde¾ovaè riadkov. Možná chýba ^M."
+
+#: ex_cmds2.c:2336
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :finish použité mimo interpretovaný súbor"
+
+#: ex_cmds2.c:2369
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish použité mimo interpretovaný súbor"
+
+#: ex_cmds2.c:2838
+msgid "No text to be printed"
+msgstr "Ïalší na tlaè"
+
+#: ex_cmds2.c:2916
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "Tlaèím stranu %d (%d%%)"
+
+#: ex_cmds2.c:2925
+#, c-format
+msgid " Copy %d of %d"
+msgstr "Kópia %d z %d"
+
+#: ex_cmds2.c:2977
+#, c-format
+msgid "Printed: %s"
+msgstr "Vytlaèené: %s"
+
+#: ex_cmds2.c:2984
+msgid "Printing aborted"
+msgstr "Tlaè bola zrušená"
+
+#: ex_cmds2.c:3367
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Nedá sa zapisova do výstupného PostScriptového súboru"
+
+#: ex_cmds2.c:4042
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Nedá sa otvori výstupný PostScriptový súbor"
+
+#: ex_cmds2.c:4080
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Nedá sa otvori súbor \"%s\""
+
+#: ex_cmds2.c:4091
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Nedá sa èíta PostScriptový súbor \"%s\""
+
+#: ex_cmds2.c:4289
+msgid "Sending to printer..."
+msgstr "Posielam na tlaèiareò..."
+
+#: ex_cmds2.c:4293
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: PostScriptový súbor sa nepodarilo vytlaèi"
+
+#: ex_cmds2.c:4295
+msgid "Print job sent."
+msgstr "Tlaèová úloha bola odoslaná."
+
+#: ex_cmds2.c:4691
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Aktuálny %s jazyk: \"%s\""
+
+#: ex_cmds2.c:4702
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Nedá sa nastavi jazyk na \"%s\""
+
+#: ex_docmd.c:490
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Spúšam Ex režim. Napište \"visual\" pre návrat do Normálního režimu."
+
+#. must be at EOF
+#: ex_docmd.c:526
+msgid "At end-of-file"
+msgstr "Koniec súboru"
+
+#: ex_docmd.c:601
+msgid "E169: Command too recursive"
+msgstr "E169: Príkaz je príliš zložitý"
+
+#: ex_docmd.c:911
+msgid "E170: Missing :endwhile"
+msgstr "E170: Chýba :endwhile"
+
+#: ex_docmd.c:913
+msgid "E171: Missing :endif"
+msgstr "E171: Chýba :endif"
+
+#: ex_docmd.c:923
+msgid "End of sourced file"
+msgstr "Koniec zdrojového súboru"
+
+#: ex_docmd.c:924
+msgid "End of function"
+msgstr "Koniec funkcie"
+
+#: ex_docmd.c:1344
+msgid "Ambiguous use of user-defined command"
+msgstr "Nejednoznaèné použitie používate¾om definovaného príkazu"
+
+#: ex_docmd.c:1358
+msgid "Not an editor command"
+msgstr "Nie je príkazom editoru"
+
+#: ex_docmd.c:1441
+msgid "Don't panic!"
+msgstr "Žiadnu paniku!"
+
+#: ex_docmd.c:1460
+msgid "Backwards range given"
+msgstr "Zadaný spätný rozsah"
+
+#: ex_docmd.c:1469
+msgid "Backwards range given, OK to swap"
+msgstr "Zadaný spätný rozsah. OK odloži"
+
+#: ex_docmd.c:1580
+msgid "Use w or w>>"
+msgstr "Použite w èi w>>"
+
+#: ex_docmd.c:3097
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: ¼utujem, ale tento príkaz nie je implementovaný"
+
+#: ex_docmd.c:3267
+msgid "E172: Only one file name allowed"
+msgstr "E172: Prípustný je iba jeden názov súboru"
+
+#: ex_docmd.c:3823
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "Ešte zostávajú %d súborov k úprave. Chcete napriek tomu ukonèi editor?"
+
+#: ex_docmd.c:3830
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: Ešte zostávajajú %ld súbory k úprave."
+
+#: ex_docmd.c:3924
+msgid "E174: Command already exists: use ! to redefine"
+msgstr "E174: Príkaz už existuje: použite ! pre predefinovanie"
+
+#: ex_docmd.c:4029
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Meno Args Rozsah Úplnos Definícia"
+
+#: ex_docmd.c:4118
+msgid "No user-defined commands found"
+msgstr "Neboli nájdené žiadne použivate¾om definované príkazy"
+
+#: ex_docmd.c:4149
+msgid "E175: No attribute specified"
+msgstr "E175: Neboli zadané žiadne vlastnosti"
+
+#: ex_docmd.c:4201
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Chybný poèet argumentov"
+
+#: ex_docmd.c:4216
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: Poèet nemôže by zadaný dvakrát"
+
+#: ex_docmd.c:4226
+msgid "E178: Invalid default value for count"
+msgstr "E178: Chybná implicitná hodnota pre poèet"
+
+#: ex_docmd.c:4254
+msgid "E179: argument required for complete"
+msgstr "E179: pre doplnenie je potrebný argument"
+
+#: ex_docmd.c:4273
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Chybná hodnota doplnenia: %s"
+
+#: ex_docmd.c:4281
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Chybná vlastnos: %s"
+
+#: ex_docmd.c:4322
+msgid "E182: Invalid command name"
+msgstr "E182: Chybné meno príkazu"
+
+#: ex_docmd.c:4337
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: Používate¾om definované príkazy musia zaèína ve¾kým písmenom"
+
+#: ex_docmd.c:4406
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: Používate¾om definovaný príkaz %s neexistuje"
+
+#: ex_docmd.c:4857
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Schéma farieb %s nenájdená"
+
+#: ex_docmd.c:4865
+msgid "Greetings, Vim user!"
+msgstr "Pozdraujem, Vim používate¾!"
+
+#: ex_docmd.c:5569
+msgid "Edit File in new window"
+msgstr "Upravi súbor v novom okne"
+
+#: ex_docmd.c:5839
+msgid "No swap file"
+msgstr "Žiadny odkladací súbor"
+
+#: ex_docmd.c:5943
+msgid "Append File"
+msgstr "Pripoji súbor"
+
+#: ex_docmd.c:6002
+msgid "E186: No previous directory"
+msgstr "E186: Žiadny predchádzajúci adresár"
+
+#: ex_docmd.c:6079
+msgid "E187: Unknown"
+msgstr "E187: Neznámy"
+
+#: ex_docmd.c:6197
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Umiestenie okna: X %d, Y %d"
+
+#: ex_docmd.c:6202
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: Na tejto platforme sa nedá umiestnenie okna zisti"
+
+#: ex_docmd.c:6468
+msgid "Save Redirection"
+msgstr "Uloži presmerovanie"
+
+#: ex_docmd.c:6617
+msgid "Save View"
+msgstr "Uloži poh¾ad"
+
+#: ex_docmd.c:6618
+msgid "Save Session"
+msgstr "Uloži sedenie"
+
+#: ex_docmd.c:6620
+msgid "Save Setup"
+msgstr "Uloži nastavenie"
+
+#: ex_docmd.c:6769
+#, c-format
+msgid "E189: \"%s\" exists (use ! to override)"
+msgstr "E189: \"%s\" existuje (použite ! pre vynútenie)"
+
+#: ex_docmd.c:6774
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: Nedá sa otvori \"%s\" pre zápis"
+
+#. set mark
+#: ex_docmd.c:6798
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: Argumentem môže by iba písiemo alebo pravý èi ¾avý apostrof"
+
+#: ex_docmd.c:6841
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Vnorenie :normal je príliš hlboké"
+
+#: ex_docmd.c:7202
+msgid ":if nesting too deep"
+msgstr "vnorenie :if je príliš hlboké"
+
+#: ex_docmd.c:7237
+msgid ":endif without :if"
+msgstr ":endif bez zodpovedajúceho :if"
+
+#: ex_docmd.c:7257
+msgid ":else without :if"
+msgstr ":else bez zodpovedajúceho :if"
+
+#: ex_docmd.c:7259
+msgid ":elseif without :if"
+msgstr ":elseif bez zodpovedajúceho :if"
+
+#: ex_docmd.c:7311
+msgid ":while nesting too deep"
+msgstr "vnorenie :while je príliš hlboké"
+
+#: ex_docmd.c:7357
+msgid ":continue without :while"
+msgstr ":continue bez zodpovedajúceho :while"
+
+#: ex_docmd.c:7384
+msgid ":break without :while"
+msgstr ":break bez zodpovedajúceho :while"
+
+#: ex_docmd.c:7407 ex_docmd.c:7412
+msgid ":endwhile without :while"
+msgstr ":endwhile bez zodpovedajúceho :while"
+
+#: ex_docmd.c:7433
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction mimo funkciu"
+
+#: ex_docmd.c:7613
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: Žiadny alternatívny názov súboru, ktorým by bolo možné nahradi '#'"
+
+#: ex_docmd.c:7644
+msgid "no autocommand file name to substitute for \"<afile>\""
+msgstr "žiadny názov súboru, ktorým by bolo možné nahradi \"<afile>\""
+
+#: ex_docmd.c:7652
+msgid "no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "žiadne èíslo bufferu, ktorým by bolo možné nahradi \"<abuf>\""
+
+#: ex_docmd.c:7663
+msgid "no autocommand match name to substitute for \"<amatch>\""
+msgstr ""
+"žiadna zhoda automatických príkazov, ktorou by bolo možné nahradi \"<amatch>"
+"\""
+
+#: ex_docmd.c:7673
+msgid "no :source file name to substitute for \"<sfile>\""
+msgstr "žiadny :source súbor, ktorým by bolo možné nahradi \"<sfile>\""
+
+#: ex_docmd.c:7714
+#, no-c-format
+msgid "Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "Prázdný názov súboru pre '%' èi '#' funguje iba s \":p:h\""
+
+#: ex_docmd.c:7716
+msgid "Evaluates to an empty string"
+msgstr "Výsledkom vyhodnotenia je prázdny reazec"
+
+#: ex_docmd.c:8649
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: Nedá sa otvori pre èítaní viminfo súbor"
+
+#: ex_docmd.c:8822
+msgid "E196: No digraphs in this version"
+msgstr "E196: V tejto verzi nie sú diagraphy podporované"
+
+#: ex_getln.c:2833
+msgid "tagname"
+msgstr "meno tagu"
+
+#: ex_getln.c:2836
+msgid " kind file\n"
+msgstr " typ súboru\n"
+
+#: ex_getln.c:4049
+msgid "'history' option is zero"
+msgstr "'vo¾ba 'history' je nastavená na nulu"
+
+#: ex_getln.c:4289
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# História %s (zaèínajúci najnovšou položkou):\n"
+
+#: ex_getln.c:4290
+msgid "Command Line"
+msgstr "Príkazové Riadky"
+
+#: ex_getln.c:4291
+msgid "Search String"
+msgstr "Vyh¾adávaný Reazec"
+
+#: ex_getln.c:4292
+msgid "Expression"
+msgstr "Výraz"
+
+#: ex_getln.c:4293
+msgid "Input Line"
+msgstr "Vstupný Riadok"
+
+#: ex_getln.c:4323
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar prevyšuje dåžku príkazu"
+
+#: ex_getln.c:4491
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Aktívne okno alebo buffer bol vymazaný"
+
+#: fileio.c:351
+msgid "Illegal file name"
+msgstr "Neprístupný názov súboru"
+
+#: fileio.c:375 fileio.c:500 fileio.c:2516 fileio.c:2554
+msgid "is a directory"
+msgstr "je adresárom"
+
+#: fileio.c:377
+msgid "is not a file"
+msgstr "nie je súborom"
+
+#: fileio.c:522 fileio.c:3646
+msgid "[New File]"
+msgstr "[nový súbor]"
+
+#: fileio.c:540
+msgid "[Permission Denied]"
+msgstr "[prístup odmietnutý]"
+
+#: fileio.c:634
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre automatické príkazy urobili súbor neèitate¾ným"
+
+#: fileio.c:636
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *ReadPre automatické príkazy nesmú meni aktuálny buffer"
+
+#: fileio.c:657
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: èítam z štandardného vstupu...\n"
+
+#: fileio.c:663
+msgid "Reading from stdin..."
+msgstr "Èítam z štandardného vstupu..."
+
+#. Re-opening the original file failed!
+#: fileio.c:892
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: Po konverzii je súbor neèittate¾ný!"
+
+#: fileio.c:1755
+msgid "[fifo/socket]"
+msgstr "[fpomenovaná rúra/soket]"
+
+#: fileio.c:1762
+msgid "[fifo]"
+msgstr "[pomenovaná rúra]"
+
+#: fileio.c:1769
+msgid "[socket]"
+msgstr "[soket]"
+
+#: fileio.c:1777
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:1787
+msgid "[CR missing]"
+msgstr "[chýba CR]"
+
+#: fileio.c:1792
+msgid "[NL found]"
+msgstr "[nájdené NL]"
+
+#: fileio.c:1797
+msgid "[long lines split]"
+msgstr "[dlhé riadky zalomené]"
+
+#: fileio.c:1803 fileio.c:3630
+msgid "[NOT converted]"
+msgstr "[neskonvertovaný]"
+
+#: fileio.c:1808 fileio.c:3635
+msgid "[converted]"
+msgstr "[skonvertovaný]"
+
+#: fileio.c:1815 fileio.c:3660
+msgid "[crypted]"
+msgstr "[zašifrovaný]"
+
+#: fileio.c:1822
+msgid "[CONVERSION ERROR]"
+msgstr "[CHYBA PREVODU]"
+
+#: fileio.c:1829
+msgid "[READ ERRORS]"
+msgstr "[CHYBY ÈÍTANIA]"
+
+#: fileio.c:2036
+msgid "Can't find temp file for conversion"
+msgstr "Nedá sa nájs doèasný súbor pre konverziu"
+
+#: fileio.c:2043
+msgid "Conversion with 'charconvert' failed"
+msgstr "Konverzia s 'charconvert' sa nepodarila"
+
+#: fileio.c:2046
+msgid "can't read output of 'charconvert'"
+msgstr "nedá sa èíta výstup 'charconvert'"
+
+#: fileio.c:2432
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr ""
+"E203: Automatické príkazy zmazali èi deaktivovali buffer, ktorý mal by "
+"uložený"
+
+#: fileio.c:2455
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Automatický príkaz neoèakávaným spôsobom zmenil poèet riadkov"
+
+#: fileio.c:2521 fileio.c:2538
+msgid "is not a file or writable device"
+msgstr "nie je súborom ani zariadením na ktoré sa dá zapisova"
+
+#: fileio.c:2584
+msgid "is read-only (use ! to override)"
+msgstr "je iba pre èítaníie(použite ! pre vynútenie)"
+
+#: fileio.c:2886
+msgid "Can't write to backup file (use ! to override)"
+msgstr "Nedá sa zapisova do záložného súboru (použite ! pre vynútenie)"
+
+#: fileio.c:2898
+msgid "Close error for backup file (use ! to override)"
+msgstr "Chyba pri uzatváraní záložného súboru (použite ! pre vynútenie)"
+
+#: fileio.c:2900
+msgid "Can't read file for backup (use ! to override)"
+msgstr "Nedá sa naèíta súbor pre zálohu (použite ! pre vynútenie)"
+
+#: fileio.c:2916
+msgid "Cannot create backup file (use ! to override)"
+msgstr "Nedá sa vytvori záložný súbor (použite ! pre vynútenie)"
+
+#: fileio.c:3018
+msgid "Can't make backup file (use ! to override)"
+msgstr "Nedá sa vytvori záložný súbor (použite ! pre vynútenie)"
+
+# resource fork ?!
+#: fileio.c:3080
+msgid "The resource fork will be lost (use ! to override)"
+msgstr "'Resource fork' bude stratený (použite ! pre vynútenie)"
+
+#: fileio.c:3169
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: Nedá sa nájs doèasný súbor pre ukladanie"
+
+#: fileio.c:3187
+msgid "E213: Cannot convert (use ! to write without conversion)"
+msgstr "E213: Nedá sa previes (použite ! pre vynútenie prevodu)"
+
+#: fileio.c:3222
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Súbor sa nedá otvori pre ukladanie"
+
+#: fileio.c:3226
+msgid "E212: Can't open file for writing"
+msgstr "E212: Súbor sa nedá otvori pre ukladanie"
+
+#: fileio.c:3475
+msgid "Close failed"
+msgstr "Zatvorenie zlyhalo"
+
+#: fileio.c:3546
+msgid "write error, conversion failed"
+msgstr "chyba pri zápise, prevod sa nepodaril"
+
+#: fileio.c:3552
+msgid "write error (file system full?)"
+msgstr "chyba pri ukladaní (je vo¾né miesto na disku?)"
+
+#: fileio.c:3625
+msgid " CONVERSION ERROR"
+msgstr " CHYBA PREVODU"
+
+#: fileio.c:3641
+msgid "[Device]"
+msgstr "[zariadenie]"
+
+#: fileio.c:3646
+msgid "[New]"
+msgstr "[nový]"
+
+#: fileio.c:3668
+msgid " [a]"
+msgstr " [p]"
+
+#: fileio.c:3668
+msgid " appended"
+msgstr " pripojený"
+
+#: fileio.c:3670
+msgid " [w]"
+msgstr " [u]"
+
+#: fileio.c:3670
+msgid " written"
+msgstr " uložený"
+
+#: fileio.c:3720
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: patchmode: nedá sa uloži pôvodný súbor"
+
+#: fileio.c:3742
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: nedá sa zapisova do prázdneho pôvodného súboru"
+
+#: fileio.c:3757
+msgid "E207: Can't delete backup file"
+msgstr "E207: Nedá sa vymaza záložný súbor"
+
+#: fileio.c:3809
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"VAROVANIE: Obsah pôvodného súboru môže by stratený alebo poškodený\n"
+
+#: fileio.c:3811
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "neukonèujte editor skôr, než bude súbor úspešne uložený!"
+
+#: fileio.c:3891
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:3891
+msgid "[dos format]"
+msgstr "[dos formát]"
+
+#: fileio.c:3898
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:3898
+msgid "[mac format]"
+msgstr "[mac formát]"
+
+#: fileio.c:3905
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:3905
+msgid "[unix format]"
+msgstr "[unix formát]"
+
+#: fileio.c:3932
+msgid "1 line, "
+msgstr "1 riadok, "
+
+#: fileio.c:3934
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld riadkov, "
+
+#: fileio.c:3937
+msgid "1 character"
+msgstr "1 znak"
+
+#: fileio.c:3939
+#, c-format
+msgid "%ld characters"
+msgstr "%ld znakov"
+
+#: fileio.c:3949
+msgid "[noeol]"
+msgstr "[žiadny koniec riadku]"
+
+#: fileio.c:3949
+msgid "[Incomplete last line]"
+msgstr "[neúplný posledný riadok]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:3968
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "VAROVANIE: od jeho naèítania bol obsah súboru zmenený!!!!"
+
+#: fileio.c:3970
+msgid "Do you really want to write to it"
+msgstr "Chcete ho naozaj uloži"
+
+#: fileio.c:4933
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Chyba pri zápise do \"%s\""
+
+#: fileio.c:4940
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Chyb pri uzatváraní \"%s\""
+
+#: fileio.c:4943
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Chyba pri èítaní \"%s\""
+
+#: fileio.c:5115
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: FileChangedShell automatický príkaz vymazal buffer"
+
+#: fileio.c:5123
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: Varovanie: súbor \"%s\" už nie je dostupný"
+
+#: fileio.c:5136
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: Varovanie: súbor \"%s\" bol po zaèatí úpravy zmenený a Vim tiež zmenil "
+"buffer"
+
+#: fileio.c:5139
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: Varovanie: súbor \"%s\" bol po zaèatí úpravy zmenený"
+
+#: fileio.c:5141
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: Varovanie: Režim súboru \"%s\" bol po zaèatí úprav zmenený"
+
+#: fileio.c:5151
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: Varovanie: po zaèatí úpravy vytvorený súbor \"%s\""
+
+#: fileio.c:5168
+msgid "Warning"
+msgstr "Varovanie"
+
+#: fileio.c:5169
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Naèíta súbor"
+
+#: fileio.c:5248
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: nedá sa obnovi \"%s\""
+
+#: fileio.c:5779
+msgid "--Deleted--"
+msgstr "--Vymazaný--"
+
+#. the group doesn't exist
+#: fileio.c:5939
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Skupina \"%s\" neexistuje"
+
+#: fileio.c:6064
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Neprístupný znak po *: %s"
+
+#: fileio.c:6075
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Udalos %s neexistuje"
+
+#. Highlight title
+#: fileio.c:6224
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Automatické príkazy ---"
+
+#: fileio.c:6495
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Automatické príkazy sa nedajú spusti pre VŠETKY udalosi"
+
+#: fileio.c:6518
+msgid "No matching autocommands"
+msgstr "Žiadne vyhovujúce automatické príkazy"
+
+#: fileio.c:6790
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: vnorenia automatického príkazu sú príliš hlboké"
+
+#: fileio.c:7077
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s automatické príkazy pre \"%s\""
+
+#: fileio.c:7085
+#, c-format
+msgid "Executing %s"
+msgstr "Spúšam %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7153
+#, c-format
+msgid "autocommand %s"
+msgstr "Automatický príkaz %s"
+
+#: fileio.c:7675
+msgid "E219: Missing {."
+msgstr "E219: Chýba {."
+
+#: fileio.c:7677
+msgid "E220: Missing }."
+msgstr "E220: Chýba }."
+
+#: fold.c:66
+msgid "No fold found"
+msgstr "Žiadny záhyb nebol nájdený"
+
+#: fold.c:553
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: Pomocou 'foldmethod' sa nedá vytvori záhyb"
+
+#: fold.c:555
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: Pomocou 'foldmethod' sa nedá odstráni záhyb"
+
+#: getchar.c:247
+msgid "E222: Add to read buffer"
+msgstr "E222: Prida do bufferu pre èítanie"
+
+#: getchar.c:2106
+msgid "E223: recursive mapping"
+msgstr "E223: rekurzívne mapovanie"
+
+#: getchar.c:2948
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: pre %s už globálna skratka existuje"
+
+#: getchar.c:2951
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: pre %s už globálne mapovanie existuje"
+
+#: getchar.c:3078
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: pre %s už skratka existuje"
+
+#: getchar.c:3081
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: pre %s už mapovanie existuje"
+
+#: getchar.c:3145
+msgid "No abbreviation found"
+msgstr "Žiadna skratka nebola nájdená"
+
+#: getchar.c:3147
+msgid "No mapping found"
+msgstr "Žiadne mapovanie nebolo nájdené"
+
+#: getchar.c:3992
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: neprístupný mód"
+
+#: gui_at_fs.c:290
+msgid "<cannot open> "
+msgstr "<nedá sa otvori> "
+
+#: gui_at_fs.c:1115
+#, c-format
+msgid "vim_SelFile: can't get font %s"
+msgstr "vim_SelFile: písmo %s nie je dostupné"
+
+#: gui_at_fs.c:2538
+msgid "vim_SelFile: can't return to current directory"
+msgstr "vim_SelFile: nedá sa vráti do aktuálneho adresára"
+
+#: gui_at_fs.c:2557
+msgid "Pathname:"
+msgstr "Názov cesty:"
+
+#: gui_at_fs.c:2563
+msgid "vim_SelFile: can't get current directory"
+msgstr "vim_SelFile: nedá sa zisti aktuálny adresár"
+
+#: gui_at_fs.c:2571 gui_motif.c:1619
+msgid "OK"
+msgstr "OK"
+
+#. 'Cancel' button
+#: gui_at_fs.c:2571 gui_gtk.c:1740 gui_motif.c:1614 gui_motif.c:2835
+msgid "Cancel"
+msgstr "Zruši"
+
+#: gui_athena.c:1956 gui_motif.c:1867
+msgid "Vim dialog"
+msgstr "Vim dialóg"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Prípravok posuvnej lišty: nedá sa zisti geometria obrázku"
+
+#: gui_beval.c:68
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: BalloonEval nedá sa vytvori správou a zároveò spätným volaním"
+
+#: gui.c:203
+msgid "E229: Cannot start the GUI"
+msgstr "E229: Nedá sa spusti GUI"
+
+#: gui.c:328
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Nedá sa èíta z \"%s\""
+
+#: gui.c:453
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: vo¾ba 'guifontwide' je chybne nastavená"
+
+#: gui.c:3698
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: Nedá sa alokova farba %s"
+
+#: gui.c:3983
+msgid "Error"
+msgstr "Chyba"
+
+#: gui_gtk.c:1190
+msgid "Vim dialog..."
+msgstr "Vim dialóg.."
+
+#: gui_gtk.c:1576 gui_motif.c:2754
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Nájs a nahradi..."
+
+#: gui_gtk.c:1581 gui_motif.c:2756
+msgid "VIM - Search..."
+msgstr "VIM - Nájs..."
+
+#: gui_gtk.c:1604 gui_motif.c:2874
+msgid "Find what:"
+msgstr "Vyh¾ada:"
+
+#: gui_gtk.c:1622 gui_motif.c:2906
+msgid "Replace with:"
+msgstr "Nový text:"
+
+#. exact match only button
+#: gui_gtk.c:1654 gui_motif.c:3008
+msgid "Match exact word only"
+msgstr "H¾ada len celé slová"
+
+#: gui_gtk.c:1666 gui_motif.c:2976
+msgid "Direction"
+msgstr "Smer"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:1678 gui_motif.c:2988
+msgid "Up"
+msgstr "Hore"
+
+#: gui_gtk.c:1682 gui_motif.c:2996
+msgid "Down"
+msgstr "Dolu"
+
+#. 'Find Next' button
+#: gui_gtk.c:1704 gui_motif.c:2778
+msgid "Find Next"
+msgstr "Nájs ïalšie"
+
+#. 'Replace' button
+#: gui_gtk.c:1721 gui_motif.c:2795
+msgid "Replace"
+msgstr "Nahradi"
+
+#. 'Replace All' button
+#: gui_gtk.c:1730 gui_motif.c:2808
+msgid "Replace All"
+msgstr "Nahradi Všetko"
+
+#: gui_gtk_x11.c:1079 gui_x11.c:1199
+msgid "E233: cannot open display"
+msgstr "E233: nedá sa otvori displej"
+
+#: gui_gtk_x11.c:2494 gui_x11.c:1999
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Neznáma sada písiem: %s"
+
+#: gui_gtk_x11.c:2518
+msgid "Font Selection"
+msgstr "Výber Písma"
+
+#: gui_gtk_x11.c:2764 gui_mac.c:2982 gui_w48.c:1197 gui_x11.c:1835
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Neznáme písmo: %s"
+
+#: gui_gtk_x11.c:2775 gui_x11.c:1859
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: Písmo \"%s\" nemá pevnú šírku"
+
+#: gui_gtk_x11.c:3580 ui.c:1971
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "Použitý CUT_BUFFER0 namiesto prázdneho výberu"
+
+#: gui_motif.c:1613 gui_motif.c:1616
+msgid "Filter"
+msgstr "Filter"
+
+#: gui_motif.c:1615
+msgid "Directories"
+msgstr "Adresáre"
+
+#: gui_motif.c:1617
+msgid "Help"
+msgstr "Pomocník"
+
+#: gui_motif.c:1618
+msgid "Files"
+msgstr "Súbory"
+
+#: gui_motif.c:1620
+msgid "Selection"
+msgstr "Výber"
+
+#: gui_motif.c:2821
+msgid "Undo"
+msgstr "Spä"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E235: Can't load Zap font '%s'"
+msgstr "E235: Nemôžem naèíta chybný font '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E235: Can't use font %s"
+msgstr "E235: Nedá sa použí písmo %s"
+
+#: gui_riscos.c:3269
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Posielam správu na ukonèenie synovského procesu.\n"
+
+#: gui_w32.c:836
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr ""
+"E243: Argument nie je podporovaný: \n"
+"-%s\"; Použite OLE verziu."
+
+#. TODO: May be changed this message
+#: gui_w32.c:3499 gui_w32.c:3532 gui_x11.c:3252
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Chyba -- nedájú sa preèíta oznaèovacie dáta!"
+
+#: gui_w48.c:2081
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Nájs reazec (použite '\\\\' ak chete nájs '\\')"
+
+#: gui_w48.c:2106
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Nájs a Nahradi (použite '\\\\' ak chcete nájs '\\')"
+
+#: gui_x11.c:1419
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: Nedá sa alokova položka mapy farieb. Niektoré farby môžu by "
+"nesprávne"
+
+#: gui_x11.c:1989
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: Chýba písmo pre nasledujúce znakové sady %s:"
+
+#: gui_x11.c:2032
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Názov sady písiem: %s"
+
+#: gui_x11.c:2033
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "Písmo '%s' nemá pevnou šírku"
+
+#: gui_x11.c:2052
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Názov sady písiem: %s\n"
+
+#: gui_x11.c:2053
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Písmo0: %s\n"
+
+#: gui_x11.c:2054
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Písmo1: %s\n"
+
+#: gui_x11.c:2055
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "Písmo%d nie je dvakrát širšie ako písmo0\n"
+
+#: gui_x11.c:2056
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "Šírka písma0: %ld\n"
+
+#: gui_x11.c:2057
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"Šírka písma1: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: Hangul automata ERROR"
+
+#: if_cscope.c:26
+#, c-format
+msgid "Usage: cs[cope] %s"
+msgstr "Použitie: cs[cope] %s"
+
+#: if_cscope.c:67
+msgid "Add a new database"
+msgstr "Prida novú databázu"
+
+#: if_cscope.c:69
+msgid "Query for a pattern"
+msgstr "H¾adanie vzoru"
+
+#: if_cscope.c:71
+msgid "Show this message"
+msgstr "Zobrazi túto správu"
+
+#: if_cscope.c:73
+msgid "Kill a connection"
+msgstr "Ukonèi spojenie"
+
+#: if_cscope.c:75
+msgid "Reinit all connections"
+msgstr "Znovu inicializova všetky spojenia"
+
+#: if_cscope.c:77
+msgid "Show connections"
+msgstr "Zobrazi spojenia"
+
+#: if_cscope.c:108
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Táto cscope príkaz nepodporuje rozde¾ovanie okna.\n"
+
+#: if_cscope.c:143
+msgid "Usage: cstag <ident>"
+msgstr "Použitie: cstag <odsadenie>"
+
+#: if_cscope.c:199
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: tag nenájdený"
+
+#: if_cscope.c:407 if_cscope.c:451
+#, c-format
+msgid "stat(%s) error: %d"
+msgstr "stat(%s) chyba: %d"
+
+#: if_cscope.c:460 if_cscope.c:467
+#, c-format
+msgid "Added cscope database %s"
+msgstr "Pridaná cscope databáza %s"
+
+#: if_cscope.c:474
+#, c-format
+msgid "%s is not a directory or a valid cscope database"
+msgstr "%s nie je ani adresárom ani správnou cscope databázou"
+
+#: if_cscope.c:557
+#, c-format
+msgid "error reading cscope connection %d"
+msgstr "chyba pri èítaní cscope spojenia %d"
+
+#: if_cscope.c:633
+msgid "unknown cscope search type"
+msgstr "neznámy typ cscope h¾adania"
+
+#: if_cscope.c:680
+msgid "Could not create cscope pipes"
+msgstr "Nedajú sa vytvori cscope rúry"
+
+#: if_cscope.c:745
+msgid "cs_create_connection exec failed"
+msgstr "spustenie cs_create_connection zlyhalo"
+
+#: if_cscope.c:755
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: volanie fdopen pre to_fp zlyhalo"
+
+#: if_cscope.c:757
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: volanie fdopen pre fr_fp zlyhalo"
+
+#: if_cscope.c:785
+msgid "no cscope connections"
+msgstr "žiadne cscope spojenia"
+
+#: if_cscope.c:855
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: cscope h¾adanie %s vo vzore %s nenašlo žiadnu zhodu"
+
+#: if_cscope.c:899
+msgid "cscope commands:\n"
+msgstr "príkazy cscope:\n"
+
+#: if_cscope.c:902
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)\n"
+msgstr "%-5s: %-30s (Použitie: %s)\n"
+
+#: if_cscope.c:970
+msgid "duplicate cscope database not added"
+msgstr "duplicitná cscope databáza nebola pridaná"
+
+#: if_cscope.c:981
+msgid "maximum number of cscope connections reached"
+msgstr "dosiahnutý maximálny poèet cscope spojení"
+
+#: if_cscope.c:1102
+msgid "E260: cscope connection not found"
+msgstr "E260: cscope spojenie nenájdené"
+
+#: if_cscope.c:1105
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: cscope spojenie %s nenájdené"
+
+#: if_cscope.c:1141
+msgid "cscope connection closed"
+msgstr "cscope spojenie ukonèené"
+
+#: if_cscope.c:1149
+#, c-format
+msgid "cscope connection %s closed\n"
+msgstr "cscope spojenie %s ukonèené\n"
+
+#. should not reach here
+#: if_cscope.c:1290
+msgid "fatal error in cs_manage_matches"
+msgstr "osudová chyba v cs_manage_matches"
+
+#: if_cscope.c:1341
+#, c-format
+msgid "E262: error reading cscope connection %d"
+msgstr "E262: chyba pri èítaní cscope spojenia %d"
+
+#: if_cscope.c:1449
+msgid "couldn't malloc\n"
+msgstr "volanie malloc zlyhalo\n"
+
+#: if_cscope.c:1454
+#, c-format
+msgid "Cscope tag: %s\n"
+msgstr "Cscope tag: %s\n"
+
+#: if_cscope.c:1458
+msgid " # line"
+msgstr " # riadok"
+
+#: if_cscope.c:1460
+msgid "filename / context / line\n"
+msgstr "názov súboru/ kontext/ riadok\n"
+
+#: if_cscope.c:1718
+msgid "All cscope databases reset"
+msgstr "Všetky cscope databáze resetované"
+
+#: if_cscope.c:1785
+msgid "no cscope connections\n"
+msgstr "žiadne cscope spojenia\n"
+
+#: if_cscope.c:1789
+msgid " # pid database name prepend path\n"
+msgstr " # pid názov databáze predpona cesty\n"
+
+#: if_cscope.c:1800
+#, c-format
+msgid "%2d %-5ld %-34s <none>\n"
+msgstr "%2d %-5ld %-34s <žiadny>\n"
+
+#: if_python.c:255 if_ruby.c:260 if_tcl.c:195 mbyte.c:2629 os_win32.c:269
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: Nepodarilo sa nahra knižnicu %s"
+
+#: if_python.c:267 if_ruby.c:272 if_tcl.c:206 mbyte.c:2645 os_win32.c:281
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: Nepodarilo sa nahra funkciu knižnice %s"
+
+#: if_python.c:392
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr "E262: Prepáète, tento príkaz je vypnutý, Python knižnica nemôže bynaèítaná."
+
+#: if_python.c:592
+msgid "can't delete OutputObject attributes"
+msgstr "nedá sa vymaza vlastnos OutputObject"
+
+#: if_python.c:599
+msgid "softspace must be an integer"
+msgstr "softspace musí by kladné celé èíslo"
+
+#: if_python.c:607
+msgid "invalid attribute"
+msgstr "chybná vlastnos"
+
+#: if_python.c:646 if_python.c:660
+msgid "writelines() requires list of strings"
+msgstr "writelines() vyžaduje zoznam reazcov"
+
+#: if_python.c:786
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: Chyba pri inicializácii I/O objektov"
+
+#: if_python.c:971 if_tcl.c:1403
+msgid "invalid expression"
+msgstr "chybný výraz"
+
+#: if_python.c:985 if_tcl.c:1408
+msgid "expressions disabled at compile time"
+msgstr "podpora výrazov bola vypnutá pri preklade programu"
+
+#: if_python.c:998
+msgid "attempt to refer to deleted buffer"
+msgstr "pokus o odkaz na vymazaný buffer"
+
+#: if_python.c:1013 if_python.c:1054 if_python.c:1118 if_tcl.c:1215
+msgid "line number out of range"
+msgstr "èíslo riadka mimo rozsah"
+
+#: if_python.c:1251
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<objekt bufferu (vymazaný) na %8lX>"
+
+#: if_python.c:1342 if_tcl.c:837
+msgid "invalid mark name"
+msgstr "chybné meno znaèky"
+
+#: if_python.c:1617
+msgid "no such buffer"
+msgstr "žiadny taký buffer"
+
+#: if_python.c:1705
+msgid "attempt to refer to deleted window"
+msgstr "pokus o odkaz na vymazané okno"
+
+#: if_python.c:1750
+msgid "readonly attribute"
+msgstr "vlastnos iba pre èítanie"
+
+#: if_python.c:1763
+msgid "cursor position outside buffer"
+msgstr "umiestnenie kurzoru mimo buffer"
+
+#: if_python.c:1840
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<objekt okna (vymazaný) na %.8lX>"
+
+#: if_python.c:1852
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<objekt okna (neznámy) na %.8lX>"
+
+#: if_python.c:1854
+#, c-format
+msgid "<window %d>"
+msgstr "<okno %d>"
+
+#: if_python.c:1930
+msgid "no such window"
+msgstr "žiadne také okno"
+
+#: if_python.c:2187 if_python.c:2222 if_python.c:2272 if_python.c:2335
+#: if_python.c:2455 if_python.c:2507 if_tcl.c:685 if_tcl.c:730 if_tcl.c:804
+#: if_tcl.c:874 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "nedajú sa uloži spätné informácie"
+
+#: if_python.c:2189 if_python.c:2279 if_python.c:2346
+msgid "cannot delete line"
+msgstr "nedá sa vymaza riadok"
+
+#: if_python.c:2224 if_python.c:2362 if_tcl.c:691 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "nedá sa nahradi riadok"
+
+#: if_python.c:2378 if_python.c:2457 if_python.c:2515
+msgid "cannot insert line"
+msgstr "nedá sa vloži riadok"
+
+#: if_python.c:2619
+msgid "string cannot contain newlines"
+msgstr "reazec nesmie obsahova znaky nového riadku"
+
+#: if_ruby.c:401
+msgid "E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr "E266: Prepáète, tento príkaz je vypnutý, Ruby knižnica nemôže by naèítaná."
+
+#: if_ruby.c:464
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: Neznámy 'longjmp' stav %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Prepnú implementáciu/definíciu"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Ukáza základnú triedu"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Ukáza preaženú èlenskú funkciu"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Obnovi zo súboru"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Obnovi z projektu"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Obnovi zo všetkých projektov"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Obnovi"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Ukáza zdroj"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Nájs znak"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Prezrie triedu"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Ukáza triedu v hierarchii"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Ukáza triedu v obmedzenej hierarchii"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref odkazuje na"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref odkázaný z"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref má"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref použitý"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Ukáza dokumentáciu"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Vytvori dokumentáciu pre"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"Zlihalo pripojenie na SNiFF+, Preverte prostredie (sniffemacs sa musí "
+"nachádza v $PATH).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Chyba poèas èítania. Odpojené"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ je aktuálne "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "ne"
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "pripojený"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Neznáma SNiFF+ požiadavka: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Chyba pripojenia na SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ nie je pripojený"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Nie je SNiFF+ bufferom"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: Chyba zápisu. Odpojené"
+
+#: if_tcl.c:419
+msgid "invalid buffer number"
+msgstr "chybné èíslo bufferu"
+
+#: if_tcl.c:465 if_tcl.c:932 if_tcl.c:1111
+msgid "not implemented yet"
+msgstr "nie je ešte podporované"
+
+#: if_tcl.c:502
+msgid "unknown option"
+msgstr "neznáma vo¾ba"
+
+#. ???
+#: if_tcl.c:775
+msgid "cannot set line(s)"
+msgstr "nedajú sa nastavi riadky"
+
+#: if_tcl.c:846
+msgid "mark not set"
+msgstr "znaèka nie je nastavená"
+
+#: if_tcl.c:852 if_tcl.c:1067
+#, c-format
+msgid "row %d column %d"
+msgstr "riadok %d ståpec %d"
+
+#: if_tcl.c:882
+msgid "cannot insert/append line"
+msgstr "nedá sa vloži/pripoji riadok"
+
+#: if_tcl.c:1269
+msgid "unknown flag: "
+msgstr "neznámy príznak: "
+
+#: if_tcl.c:1339
+msgid "unknown vimOption"
+msgstr "neznáma vimMožnos"
+
+#: if_tcl.c:1424
+msgid "keyboard interrupt"
+msgstr "prerušenie z klávesnice"
+
+#: if_tcl.c:1429
+msgid "vim error"
+msgstr "chyba vim"
+
+#: if_tcl.c:1472
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "nedá sa vytvori príkaz bufferu/okna: objekt vymazaný"
+
+#: if_tcl.c:1546
+msgid "cannot register callback command: buffer/window is already being deleted"
+msgstr "nedá sa zaregistrova príkaz spätného volania: buffer/okno už bol vymazaný"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1563
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: TCL FATAL ERROR: reflist poškodený!? Oznámte, prosím, túto chybu na "
+"vim-dev@vim.org"
+
+#: if_tcl.c:1564
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr "nedá sa zaregistrova príkaz spätného volania: odkaz na buffer/okno nenájdený"
+
+#: if_tcl.c:1725
+msgid "Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr "Prepáète, tento príkaz je vypnutý, Tcl knižnica nemôže by naèítaná."
+
+#: if_tcl.c:1887
+msgid "E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: TCL CHYBA: návratový kód nie je celé èíslo!? Oznamte, presím, tuto "
+"chybu na vim-dev@vim.org"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "nedá sa preèíta riadok"
+
+#: if_xcmdsrv.c:213
+msgid "Unable to register a command server name"
+msgstr "Nemôžem zaregistrova meno príkazového servra"
+
+#: if_xcmdsrv.c:434 os_mswin.c:2108
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: meno registrovaného servra \"%s\" neexistuje"
+
+#: if_xcmdsrv.c:463
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Chyba poèas prenosu príkazu do cie¾ového programu"
+
+#: if_xcmdsrv.c:732
+#, c-format
+msgid "Invalid server id used: %s"
+msgstr "Použíté chybné id servra: %s"
+
+#: if_xcmdsrv.c:1079
+msgid "E249: couldn't read VIM instance registry property"
+msgstr "E249: nemôžem èíta VIM registrovú vlastnos"
+
+#: if_xcmdsrv.c:1090
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: VIM registrová žiados je zle formulovaná. Vymazané!"
+
+#: main.c:53 option.c:3162 option.c:3269
+msgid "Unknown option"
+msgstr "Neznáma vo¾ba"
+
+#: main.c:55
+msgid "Too many edit arguments"
+msgstr "Príliš mnoho upravovacích argumentov"
+
+#: main.c:57
+msgid "Argument missing after"
+msgstr "Chýba argument po"
+
+#: main.c:59
+msgid "Garbage after option"
+msgstr "Chyby za vo¾bou"
+
+#: main.c:61
+msgid "Too many \"+command\" or \"-c command\" arguments"
+msgstr "Príliš mnoho \"+príkaz\" èi \"-c príkaz\" argumentov"
+
+#: main.c:63
+msgid "Invalid argument for"
+msgstr "Chybný argument pre"
+
+#: main.c:450
+msgid "This Vim was not compiled with the diff feature."
+msgstr "Tento Vim nebol kompilovaný s porovnávacími funkciami."
+
+#: main.c:875
+msgid "Attempt to open script file again: \""
+msgstr "Pokus o opätovné otvorenie skriptu: \""
+
+#: main.c:879 main.c:886 main.c:930 memline.c:3673 memline.c:3677
+#: version.c:892 version.c:897 version.c:902 version.c:907 version.c:912
+#: version.c:917 version.c:923 version.c:927 version.c:931 version.c:936
+#: version.c:943 version.c:951 version.c:957
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:884
+msgid "Cannot open for reading: \""
+msgstr "Nedá sa otvori pre zápis: \""
+
+#: main.c:928
+msgid "Cannot open for script output: \""
+msgstr "Nedá sa otvori pre výstup skriptu: \""
+
+#: main.c:1044
+#, c-format
+msgid "%d files to edit\n"
+msgstr "poèet súborov pre úpravu: %d\n"
+
+#: main.c:1118
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Varovanie: Výstup nesmeruje na terminál\n"
+
+#: main.c:1120
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Varovanie: Vstup nepochádza z terminálu\n"
+
+#. just in case..
+#: main.c:1195
+msgid "pre-vimrc command line"
+msgstr "pre-vimrc príkazový riadok"
+
+#: main.c:1230
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Nedá sa èíta z \"%s\""
+
+#: main.c:2205
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Podrobnejšie informácie získáte pomocou \"vim -h\"\n"
+
+#: main.c:2238
+msgid "[file ..] edit specified file(s)"
+msgstr "[súbor ..] .. upravi súbor(y)"
+
+#: main.c:2239
+msgid "- read text from stdin"
+msgstr "- èíta text z štandardného vstupu"
+
+#: main.c:2240
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tag upravi súbor na mieste definície tagu"
+
+#: main.c:2242
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [chybový súbor] upravi súbor na mieste výskytu prvej chyby"
+
+#: main.c:2251
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"použitie:"
+
+#: main.c:2254
+msgid " vim [arguments] "
+msgstr "vim [argumenty] "
+
+#: main.c:2258
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" alebo"
+
+#: main.c:2261
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Argumenty:\n"
+
+#: main.c:2262
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tMôžu nasledova iba názvy súborov"
+
+#: main.c:2264
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tnepodarilo sa expandova žolíkové znaky (wildcards)"
+
+#: main.c:2267
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tprihlási gvim na OLE"
+
+#: main.c:2268
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-register\t\todhlási gvim z OLE"
+
+#: main.c:2271
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tspusti v GUI móde (rovnaké ako \"gvim\")"
+
+#: main.c:2272
+msgid "-f\t\t\tForeground: Don't fork when starting GUI"
+msgstr "-f\t\t\tPopredie: pri spustení GUI sa neoddelí od shellu"
+
+#: main.c:2274
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi mód (rovnaké ako \"vi\")"
+
+#: main.c:2275
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx mód (rovnaké ako \"ex\")"
+
+#: main.c:2276
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tTichý (dávkový) mód (iba pre \"ex\")"
+
+#: main.c:2278
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tPorovnávací mód (rovnaké ako \"vimdiff\")"
+
+#: main.c:2280
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tJednoduchý mód (rovnaké ako \"evim\", modeless)"
+
+#: main.c:2281
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tMód iba_pre_èítanie (ako \"view\")"
+
+#: main.c:2282
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tObmedzený mód (rovnaké ako \"rvim\")"
+
+#: main.c:2283
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tZmeny (ukladanie súborov) zakázané"
+
+#: main.c:2284
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tZmeny v texte nie sú povolené"
+
+#: main.c:2285
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tBinárny mód"
+
+#: main.c:2287
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp mód"
+
+#: main.c:2289
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tKompatabilný s Vi: 'compatible'"
+
+#: main.c:2290
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tKompatibilita s Vi vypnutá: 'nocompatible'"
+
+#: main.c:2291
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tÚroveò výpisu hlášok"
+
+#: main.c:2292
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tLadiaci mód"
+
+#: main.c:2293
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tNebude vytvára odkladací súbor, bude používa iba pamä"
+
+#: main.c:2294
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tVypíše zoznam odkladacích súborov a skonèí"
+
+#: main.c:2295
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r názov súboru\tObnoví prerušené sedenie"
+
+#: main.c:2296
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tRovnaké ako -r"
+
+#: main.c:2298
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tNebude používa newcli pre otvorenie okna"
+
+#: main.c:2299
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <zariadenie>\t\tPouži <zariadenie> pre I/O"
+
+#: main.c:2302
+msgid "-H\t\t\tstart in Hebrew mode"
+msgstr "-H\t\t\tna spusteníe v hebrejskom móde"
+
+#: main.c:2305
+msgid "-F\t\t\tstart in Farsi mode"
+msgstr "-F\t\t\tna spusteníe vo Farsi móde"
+
+#: main.c:2307
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminál>\tNastaví typ terminálu na <terminál>"
+
+#: main.c:2308
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tPoužije <vimrc> namiesto akéhoko¾vek .vimrc"
+
+#: main.c:2310
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tPoužije <gvimrc> namiesto akéhoko¾vek .gvimrc"
+
+#: main.c:2312
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tNenahrá 'plugin' skripty"
+
+#: main.c:2313
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tOtvorí N okien (implicitne jedno pre každý súbor)"
+
+#: main.c:2314
+msgid "-O[N]\t\tlike -o but split vertically"
+msgstr "-O[N]\t\tako -o ale rozdelí vertikálne"
+
+#: main.c:2315
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tNastaví kurzor na koniec súboru"
+
+#: main.c:2316
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<riadok>\t\tNastaví kurzor na <riadok>"
+
+#: main.c:2318
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <príkaz>\t\tVykoná <príkaz> pred nahraním vimrc súboru"
+
+#: main.c:2320
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <príkaz>\t\tPo nahraní prvého súboru vykoná <príkaz>"
+
+#: main.c:2321
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <sedenie>\t\tPo nahrání prvého súboru vykoná príkazy v súbore <sedenie>"
+
+#: main.c:2322
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <skript>\t\tNaèíta príkazy normálneho módu zo <skriptu>"
+
+#: main.c:2323
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <skript>\t\tPripojí všetky napísané príkazy do súboru <skript>"
+
+#: main.c:2324
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <skript>\t\tUloží všetky napísané príkazy do súboru <skript>"
+
+#: main.c:2326
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tÚprava zašifrovaných súborov"
+
+#: main.c:2330
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <displej>\tSpustí vim na <displej>"
+
+#: main.c:2332
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tNepripojí sa k X serveru"
+
+#: main.c:2334
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tOtvorí Vim vnútri iného GTK programu."
+
+#: main.c:2338
+msgid "--remote <files>\tEdit <files> in a Vim server and exit"
+msgstr "--remote <súbory>\tUpravi <súbory> na Vim servri a skonèi"
+
+#: main.c:2339
+msgid "--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <súbory>\tAko --remote ale èaká na súbory pre ukonèenie úprav"
+
+#: main.c:2340
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <vo¾by>\tOdošle <vo¾by> na Vim server a skonèí"
+
+#: main.c:2341
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <výraz>\tSpusti <výraz> na servri a vytlaèí výsledok"
+
+#: main.c:2342
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tVypíše zoznam mien dostupných Vim servrov a skonèí"
+
+#: main.c:2343
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <názov>\tOdošle na Vim server <názov>"
+
+#: main.c:2346
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tPoužije <viminfo> namiesto akéhoko¾vek .viminfo"
+
+#: main.c:2348
+msgid "-h\t\t\tprint Help (this message) and exit"
+msgstr "-h\t\t\tVypíše túto nápovedu a skonèí"
+
+#: main.c:2349
+msgid "--version\t\tprint version information and exit"
+msgstr "--version\t\tvypíše informácie o verzii a skonèí"
+
+#: main.c:2353
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Argumenty pre gvim (Motif verzia):\n"
+
+#: main.c:2356
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Argumenty pre gvim (Athena verzia):\n"
+
+#: main.c:2359
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <displej>\tSpustí vim na <displej>"
+
+#: main.c:2360
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tSpustí vim minimalizované"
+
+#: main.c:2362
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <názov>\t\tPoužije resource ako by vim mal <názov>"
+
+#: main.c:2363
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (nie je implementované)\n"
+
+#: main.c:2365
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <farba>\tNastaví sa <farba> pozadia (tiež -bg)"
+
+#: main.c:2366
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <farba>\tNastaví sa <farba> popredia (tiež -fg)"
+
+#: main.c:2367 main.c:2387
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <písmo>\t\tNastaví <písmo> normálneho textu (tiež -fn)"
+
+#: main.c:2368
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <písmo>\tNastaví <písmo> pre zvýraznený text"
+
+#: main.c:2369
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <písmo>\tNastaví <písmo> pre kurzívu"
+
+#: main.c:2370 main.c:2388
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geometrie>\tNastaví sa <geometria> (tiež -geom)"
+
+#: main.c:2371
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <šírka>\tNastaví <šírku> okrajov (tiež -bw)"
+
+#: main.c:2372
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <šírka> Nastaví <šírku> posuvnej lišty (tiež -sw)"
+
+#: main.c:2374
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <výška>\tNastaví <výšku> ponuky (tiež -mh)"
+
+#: main.c:2376 main.c:2389
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tPoužije reverzné farby (tiež -rv)"
+
+#: main.c:2377
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tNepoužije reverzné farby (tiež +rv)"
+
+#: main.c:2378
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\tNastaví zadaný <resource>"
+
+#: main.c:2381
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Argumenty pre gvim (RISC OS verzia):\n"
+
+#: main.c:2382
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <poèet>\t<poèet> ståpcov na okno"
+
+#: main.c:2383
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <poèet>\t<poèet> riadkov na okno"
+
+#: main.c:2386
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Argumenty pre gvim (GTK+ verzia):\n"
+
+#: main.c:2390
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <displej>\tspustí vim na <displej> (tiež --display)"
+
+#: main.c:2392
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tVypíše Gnome argumenty"
+
+#. Failed to send, abort.
+#: main.c:2634
+msgid ""
+"\n"
+"Send failed.\n"
+msgstr ""
+"\n"
+"Odoslanie zlyhalo.\n"
+
+#. Let vim start normally.
+#: main.c:2639
+msgid ""
+"\n"
+"Send failed. Trying to execute locally\n"
+msgstr ""
+"\n"
+"Odoslanie zlyhalo. Pokúšam sa spusti lokálne\n"
+
+#: main.c:2672 main.c:2693
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d upravených súborov z %d"
+
+#: main.c:2716
+msgid "Send expression failed.\n"
+msgstr "Odoslanie výrazu zlyhalo.\n"
+
+#: mark.c:660
+msgid "No marks set"
+msgstr "Nie sú nastavené žiadne znaèky"
+
+#: mark.c:662
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283:\"%s\" nevyhovujú žiadne znaèky"
+
+#. Highlight title
+#: mark.c:673
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"znaèka riadok ståpec súbor/text"
+
+#. Highlight title
+#: mark.c:711
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" skok riadok ståpec súbor/text"
+
+#: mark.c:1073
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Súborové znaèky:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1108
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Zoznam skokov (zaèínajúci najnovšou položkou):\n"
+
+#: mark.c:1203
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# História znaèiek v súboroch (zaèínajúci najnovšou položkou):\n"
+
+#: mark.c:1286
+msgid "Missing '>'"
+msgstr "Chýba '>'"
+
+#: mbyte.c:395
+msgid "Not a valid codepage"
+msgstr "Chybná kódová stránka"
+
+#: mbyte.c:3103
+msgid "E284: Cannot set IC values"
+msgstr "E284: Nedjú sa nastavi IC hodnoty"
+
+#: mbyte.c:3255
+msgid "E285: Failed to create input context"
+msgstr "E285: Nepodarilo sa vytvori vstupný kontext"
+
+#: mbyte.c:3402
+msgid "E286: Failed to open input method"
+msgstr "E286: Nepodarilo sa otvori vstupnú metódu"
+
+#: mbyte.c:3413
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: Varovanie: likvidaèné spätné volanie sa nedá nastavi na IM"
+
+#: mbyte.c:3419
+msgid "E288: input method doesn't support any style"
+msgstr "E288: vstupná metóda nepodporuje žiadny štýl"
+
+#: mbyte.c:3476
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: vstupná metóda nepodporuje môj 'preedit' typ"
+
+#: mbyte.c:3550
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: Nadbodový štýl vyžaduje fontset"
+
+#: mbyte.c:3578
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: Máte GTK+ verziu staršiu než 1.2.3. Stavová plocha vypnutá."
+
+#: mbyte.c:3843
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Server vstupných metód nebeží"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: blok nebol zamknutý"
+
+#: memfile.c:989
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Chyba posunu pri èítaní odkladacieho súboru"
+
+#: memfile.c:994
+msgid "E295: Read error in swap file"
+msgstr "E295: Chyba pri èítaní odkladacieho súboru"
+
+#: memfile.c:1046
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Chyba posunu pri ukladaní do odkladacieho súboru"
+
+#: memfile.c:1064
+msgid "E297: Write error in swap file"
+msgstr "E297: Chyba pri ukladaní do odkladacieho súboru"
+
+#: memfile.c:1261
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: Odkladací súbor už existuje!"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Nedá sa získa blok 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Nedá sa získa blok 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: Nedá sa získa blok 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Ups, odkladací súbor bol stratený!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: Nedá sa premenova odkladací súbor"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: Nedá sa otvori odkladací súbor pre \"%s\", oprava nie je nemožná"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: nedá sa získa blok 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Odkladací súbor pre %s nebol nájdený"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "Zadajte èíslo odkladacieho súboru, ktorý sa má použit (0 pre ukonèenie): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: Nedá sa otvori %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "Nedá sa èíta blok 0 z "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Možno nedošlo k žiadnym zmenám, alebo Vim neaktualizoval odkladací súbor."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " nedá sa použi s touto verziou Vim.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Použite Vim verziu 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s sa nezdá by odkladacím súborom Vim"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " nedá sa použí na tomto poèítaèi.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "Súbor bol vytvorený "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"alebo bol súbor poškodený."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "Používám odkladací súbor \"%s\""
+
+#: memline.c:915
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Pôvodný súbor \"%s\""
+
+#: memline.c:934
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Varovanie: Pôvodný súbor mohl by zmenený"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Nedá sa èíta blok 1 z %s"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???CHÝBA MNOHO RIADKOV"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???CHYBNÝ POÈET RIADKOV"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???PRÁZDNY BLOK"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???CHÝBAJÚCE RIADKY"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ID bloku 1 je chybné (je %s odkladacím súborom?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???CHÝBA BLOK"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "od ??? po ???END môžu by riadky pomiešané"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "od ??? po ???END môžu by vložené/vymazané riadky"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???KONIEC"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Obnova prerušená"
+
+#: memline.c:1145
+msgid "E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: V priebehu obnovy došlo k chybám; skontrolujte riadky zaèínajúce na ???"
+
+#: memline.c:1148
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Obnova dokonèená. Skontrolujte, èi je všetko v poriadku."
+
+#: memline.c:1149
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Zvážte uloženie tohoto súboru pod iným menom\n"
+
+#: memline.c:1150
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "a pomocou programu diff zistite zmeny oproti pôvodnému súboru.)\n"
+
+#: memline.c:1151
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr "Potom vymažte odkladací súbor.\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1207
+msgid "Swap files found:"
+msgstr "Nájdené odkladacie súbory:"
+
+#: memline.c:1385
+msgid " In current directory:\n"
+msgstr " V aktuálnom adresári:\n"
+
+#: memline.c:1387
+msgid " Using specified name:\n"
+msgstr " So zadaným menom:\n"
+
+#: memline.c:1391
+msgid " In directory "
+msgstr " V adresári "
+
+#: memline.c:1409
+msgid " -- none --\n"
+msgstr " -- žiadne --\n"
+
+#: memline.c:1481
+msgid " owned by: "
+msgstr " vlastník: "
+
+#: memline.c:1483
+msgid " dated: "
+msgstr " dátum vytvorenia: "
+
+#: memline.c:1487 memline.c:3680
+msgid " dated: "
+msgstr " dátum vytvorenia: "
+
+#: memline.c:1503
+msgid " [from Vim version 3.0]"
+msgstr " [od Vim verzie 3.0]"
+
+#: memline.c:1507
+msgid " [does not look like a Vim swap file]"
+msgstr " [nevypadá ako odkladací súbor Vim]"
+
+#: memline.c:1511
+msgid " file name: "
+msgstr " názov súboru: "
+
+#: memline.c:1523
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" dátum zmeny: "
+
+#: memline.c:1524
+msgid "YES"
+msgstr "ÁNO"
+
+#: memline.c:1524
+msgid "no"
+msgstr "nie"
+
+#: memline.c:1528
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" užívate¾ské meno: "
+
+#: memline.c:1535
+msgid " host name: "
+msgstr " názov poèítaèa: "
+
+#: memline.c:1537
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" názov poèítaèa: "
+
+#: memline.c:1543
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ID procesu : "
+
+#: memline.c:1549
+msgid " (still running)"
+msgstr " (stále aktívny)"
+
+#: memline.c:1561
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [nepoužite¾né s touto verziou Vim]"
+
+#: memline.c:1564
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [nepoužitelné na tomto poèítaèi]"
+
+#: memline.c:1569
+msgid " [cannot be read]"
+msgstr " [nedá sa preèíta]"
+
+#: memline.c:1573
+msgid " [cannot be opened]"
+msgstr " [nedá sa otvori]"
+
+#: memline.c:1763
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Nedá sa zachova - odkladací súbor neexistuje."
+
+#: memline.c:1816
+msgid "File preserved"
+msgstr "Súbor zachovaný"
+
+#: memline.c:1818
+msgid "E314: Preserve failed"
+msgstr "E314: Uchovanie sa nepodarilo"
+
+#: memline.c:1889
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: chybné èíslo riadku: %ld"
+
+#: memline.c:1915
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: nedá sa nájs riadok %ld"
+
+#: memline.c:2303
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: chybné id ukazovate¾a na blok 3"
+
+#: memline.c:2383
+msgid "stack_idx should be 0"
+msgstr "stack_idx by malo ma hodnotu 3"
+
+#: memline.c:2445
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Aktualizovaných príliš ve¾a blokov?"
+
+#: memline.c:2602
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: chybné id ukazovate¾a na blok 4"
+
+#: memline.c:2629
+msgid "deleted block 1?"
+msgstr "vymazaný blok 1?"
+
+#: memline.c:2829
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Nedá sa nájs riadok %ld"
+
+#: memline.c:3072
+msgid "E317: pointer block id wrong"
+msgstr "E317: chybné id ukazovate¾a na blok"
+
+#: memline.c:3088
+msgid "pe_line_count is zero"
+msgstr "pe_line_count má nulovú hodnotu"
+
+#: memline.c:3117
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: èíslo riadku je mimo rozsah: %ld (za koncom)"
+
+#: memline.c:3121
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: chybný poèet riadkov v bloku %ld"
+
+#: memline.c:3170
+msgid "Stack size increases"
+msgstr "Nárast ve¾kosti zásobníku"
+
+#: memline.c:3216
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: chybný id ukazovate¾a na blok 2"
+
+#: memline.c:3670
+msgid "E325: ATTENTION"
+msgstr "E325: POZOR"
+
+#: memline.c:3671
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Nájdený odkladací súbor s menom \""
+
+#: memline.c:3675
+msgid "While opening file \""
+msgstr "Pri otváraní súboru\""
+
+#: memline.c:3684
+msgid " NEWER than swap file!\n"
+msgstr " NOVŠÍ ako odkladací súbor!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3688
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Súbor môže by upravovaný iným programom.\n"
+" Ak je tomu tak, potom si dajte pozor, aby ste po uložení zmien\n"
+" nemali dve rôzne verzie toho istého súboru.\n"
+
+#: memline.c:3689
+msgid " Quit, or continue with caution.\n"
+msgstr " Ukonèite program, alebo opatrnne pokraèujte v úpravách.\n"
+
+#: memline.c:3690
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) Úprava tohoto súboru bola prerušená neoèakávaným ukonèením programu.\n"
+
+#: memline.c:3691
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Ak je tomu tak, potom použite \":recover\" alebo \"vim -r "
+
+#: memline.c:3693
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" pre obnovenie zmien (viz \":help recovery)\".\n"
+
+#: memline.c:3694
+msgid " If you did this already, delete the swap file \""
+msgstr " Pokia¾ ste tak už urobili, tak vymažte odkladací súbor \""
+
+#: memline.c:3696
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" a táto správa sa už nebude objavova.\n"
+
+#: memline.c:3710 memline.c:3714
+msgid "Swap file \""
+msgstr "Odkladací súbor \""
+
+#: memline.c:3711 memline.c:3717
+msgid "\" already exists!"
+msgstr "\" už existuje!"
+
+#: memline.c:3720
+msgid "VIM - ATTENTION"
+msgstr "VIM - POZOR"
+
+#: memline.c:3722
+msgid "Swap file already exists!"
+msgstr "Odkladací súbor už existuje!"
+
+#: memline.c:3726
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"&Otvori iba pre èítanie\n"
+"&Pokraèova v úpravách\n"
+"O&bnovi súbor\n"
+"&Koniec"
+
+#: memline.c:3728
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"&Otvori iba pre èítanie\n"
+"&Pokraèovat v úpravách\n"
+"O&bnovi súbor\n"
+"&Koniec\n"
+"&Zmaza"
+
+#: memline.c:3781
+msgid "E326: Too many swap files found"
+msgstr "E326: Príliš mnoho odkladacích súborov"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Èas cesty k predmetu ponuky nie je podponukou"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Ponuka existuje iba v inom móde"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Ponuka tohoto mena neexistuje"
+
+#: menu.c:509
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Cesta ponuky nesmie vies do podponuky"
+
+#: menu.c:548
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: Položky ponuky sa nedjú pridáva priamo na lištu"
+
+#: menu.c:554
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Odde¾ovaè nesmie by èasou cesty ponuky"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1070
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Ponuky ---"
+
+#: menu.c:1987
+msgid "Tear off this menu"
+msgstr "Odtrhnú tuto ponuku"
+
+#: menu.c:2052
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Cesta ponuky musí vies k položke ponuky"
+
+#: menu.c:2072
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Vzor nenájdený: %s"
+
+#: menu.c:2141
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: V %s móde nie je ponuka definovaná"
+
+#: menu.c:2179
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Cesta ponuky musí vies do podponuky"
+
+#: menu.c:2200
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Ponuka nenájdená - skontrolujte názvy ponúk"
+
+#: message.c:470
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Chyba pri spracovaní %s:"
+
+#: message.c:486
+#, c-format
+msgid "line %4ld:"
+msgstr "riadok %4ld:"
+
+#: message.c:526
+msgid "[string too long]"
+msgstr "[príliš dlhý reazec]"
+
+#: message.c:672
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "Správca správ: Martin Lacko <lacko@host.sk>"
+
+#: message.c:885
+msgid "Interrupt: "
+msgstr "Prerušenie: "
+
+#: message.c:888
+msgid "Hit ENTER to continue"
+msgstr "Pokraèovanie stlaèením ENTER"
+
+#: message.c:890
+msgid "Hit ENTER or type command to continue"
+msgstr "Pre pokraèovanie stlaète ENTER alebo zadajte príkaz"
+
+#: message.c:1961
+msgid "-- More --"
+msgstr "-- Pokraèovanie --"
+
+#: message.c:1964
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: riadok, MEDZERNÍK/b: stránka, d/u: 0.5 stránky, q: koniec)"
+
+#: message.c:1965
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: riadok, MEDZERNÍK: stránka, d: 0.5 stránky, q: koniec)"
+
+#: message.c:2441 message.c:2456
+msgid "Question"
+msgstr "Otázka"
+
+#: message.c:2443
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"Án&o\n"
+"&Nie"
+
+#: message.c:2458
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"Án&o\n"
+"&Nie\n"
+"&Zruši"
+
+#: message.c:2476
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"Án&o\n"
+"&Nie\n"
+"&Uloži všetko\n"
+"Zahodi &všetko\n"
+"&Zruši"
+
+#: message.c:2517
+msgid "Save File dialog"
+msgstr "Dialóg pre ukladanie súborov"
+
+#: message.c:2519
+msgid "Open File dialog"
+msgstr "Dialóg pre otváranie súborov"
+
+#. TODO: non-GUI file selector here
+#: message.c:2590
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: ¼utujem, ale konzolová verzia nepodporuje prehliadaè súborov"
+
+#: misc1.c:2457
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: Varovanie: mením súbor iba pre èítanie"
+
+#: misc1.c:2686
+msgid "1 more line"
+msgstr "poèet nových riadkov: 1"
+
+#: misc1.c:2688
+msgid "1 line less"
+msgstr "poèet vymazaných riadkov: 1"
+
+#: misc1.c:2693
+#, c-format
+msgid "%ld more lines"
+msgstr "poèet nových riadkov: %ld"
+
+#: misc1.c:2695
+#, c-format
+msgid "%ld fewer lines"
+msgstr "poèet vymazaných riadkov: %ld"
+
+#: misc1.c:2698
+msgid " (Interrupted)"
+msgstr " (Prerušené)"
+
+#: misc1.c:6316
+msgid "Vim: preserving files...\n"
+msgstr "Vim: zachovávam súbory...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6326
+msgid "Vim: Finished.\n"
+msgstr "Vim: ukonèený\n"
+
+#: misc2.c:661 misc2.c:677
+msgid "ERROR: "
+msgstr "CHYBA: "
+
+#: misc2.c:681
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bajtov] celkom uvolnené-alokované %lu-%lu, využité %lu, maximálne využitie %"
+"lu\n"
+
+#: misc2.c:683
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[volanie] celkom re/malloc(): %lu, celkom free() %lu\n"
+"\n"
+
+#: misc2.c:738
+msgid "E340: Line is becoming too long"
+msgstr "E340: Riadok sa stáva príliš dlhým"
+
+#: misc2.c:782
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Vnútorná chyba: lalloc(%ld, )"
+
+#: misc2.c:890
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Nedostatok pamäte! (alokujem %lu bytov)"
+
+#: misc2.c:2541
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Volám shell na spustenie: \"%s\""
+
+#: misc2.c:2740 misc2.c:5225 option.c:4636
+msgid "Missing colon"
+msgstr "Chýba dvojbodka"
+
+#: misc2.c:2742 misc2.c:2769
+msgid "Illegal mode"
+msgstr "Neprístupný mód"
+
+#: misc2.c:2808
+msgid "Illegal mouseshape"
+msgstr "Chybný tvar myši"
+
+#: misc2.c:2848 misc2.c:5245
+msgid "digit expected"
+msgstr "oèakávaná èíslica"
+
+#: misc2.c:2853
+msgid "Illegal percentage"
+msgstr "Neprístupné precento"
+
+#: misc2.c:3157
+msgid "Enter encryption key: "
+msgstr "Zadajte šifrovací k¾úè: "
+
+#: misc2.c:3158
+msgid "Enter same key again: "
+msgstr "Vložte k¾úè znova: "
+
+#: misc2.c:3168
+msgid "Keys don't match!"
+msgstr "K¾úè nie je správny!"
+
+#: misc2.c:3707
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Chybná cesta: '**[èíslo] musí by buï na konci cesty, alebo musí by\n"
+"nasledované '%s. Viz :help path."
+
+#: misc2.c:4979
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Adresár \"%s\" sa nedá v cdpath nájs"
+
+#: misc2.c:4982
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Súbor \"%s\" sa nepodarilo nájs"
+
+#: misc2.c:4988
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: Žiadny ïalší adresár \"%s\" nebol v cdpath nájdený"
+
+#: misc2.c:4991
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: Žiadny ïalší súbor \"%s\" nebol v ceste nájdený"
+
+#: misc2.c:5237
+msgid "Illegal component"
+msgstr "Neprístupný komponent"
+
+#: normal.c:2843
+msgid "Warning: terminal cannot highlight"
+msgstr "Varovanie: terminál nepodporuje zvýrazòovanie"
+
+#: normal.c:3038
+msgid "E348: No string under cursor"
+msgstr "E348: Pod kurzorom nie je žiadny reazec"
+
+#: normal.c:3040
+msgid "E349: No identifier under cursor"
+msgstr "E349: Pod kurzorom nie je žiadny identifikátor"
+
+#: normal.c:4211
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: Pomocou 'foldmethod' sa nedá vymaza záhyb"
+
+#: ops.c:283
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "poèet riadkov posunutých naraz pomocou %s : 1"
+
+#: ops.c:285
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "poèet riadkov posunutých %s krát pomocou %d s : 1"
+
+#: ops.c:290
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld riadkov posunutých naraz pomocou %s"
+
+#: ops.c:293
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld riadkov posunutých pomocou %s %d krát"
+
+#: ops.c:651
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "poèet riadkov pre odsadenie: %ld"
+
+#: ops.c:701
+msgid "1 line indented "
+msgstr "poèet riadkov pre odsadenie: 1 "
+
+#: ops.c:703
+#, c-format
+msgid "%ld lines indented "
+msgstr "poèet odsadených riadkov: %ld"
+
+#. must display the prompt
+#: ops.c:1546
+msgid "cannot yank; delete anyway"
+msgstr "nedá sa kopírova; napriek tomu vymazané"
+
+#: ops.c:2080
+msgid "1 line changed"
+msgstr "poèet zmenených riadkov: 1"
+
+#: ops.c:2082
+#, c-format
+msgid "%ld lines changed"
+msgstr "poèet zmenených riadkov: %ld"
+
+#: ops.c:2439
+#, c-format
+msgid "freeing %ld lines"
+msgstr "poèet uvolòovaných riadkov: %ld"
+
+#: ops.c:2720
+msgid "1 line yanked"
+msgstr "poèet skopírovaných riadkov: 1"
+
+#: ops.c:2722
+#, c-format
+msgid "%ld lines yanked"
+msgstr "poèet skopírovaných riadkov: %ld"
+
+#: ops.c:2995
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: Register %s je prázdny"
+
+#. Highlight title
+#: ops.c:3553
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Registre ---"
+
+#: ops.c:4711
+msgid "Illegal register name"
+msgstr "Neprístupný názov registru"
+
+#: ops.c:4797
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Registre:\n"
+
+#: ops.c:4825
+#, c-format
+msgid "Unknown register type %d"
+msgstr "%d nie je známým typom registru"
+
+#: ops.c:5217
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: '%s' nie je prístupné meno registru"
+
+#: ops.c:5560
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Buniek; "
+
+#: ops.c:5567
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Vybraných %s%ld z %ld riadkov; %ld zo %ld slov; %ld z %ld Bytov"
+
+#: ops.c:5583
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Bunka %s z %s; Riadok %ld z %ld; Slovo %ld z %ld; Byte %ld z %ld"
+
+#: ops.c:5594
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld pre BOM)"
+
+#: option.c:1989
+msgid "Thanks for flying Vim"
+msgstr "Ïakujem za použitie Vim"
+
+#: option.c:3175
+msgid "Option not supported"
+msgstr "Vo¾ba nie je podporovaná"
+
+#: option.c:3200
+msgid "Not allowed in a modeline"
+msgstr "Nie je v modeline povolené"
+
+#: option.c:3256
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tOstatné nastavenie z "
+
+#: option.c:3395
+msgid "Number required after ="
+msgstr "Po = je vyžadované èíslo"
+
+#: option.c:3714 option.c:4322
+msgid "Not found in termcap"
+msgstr "Nenájdený v termcapu"
+
+#: option.c:3780
+#, c-format
+msgid "Illegal character <%s>"
+msgstr "Neprístupný znak <%s>"
+
+#: option.c:4307 option.c:5570
+msgid "Not allowed here"
+msgstr "Toto nie je na tomto mieste povolené"
+
+#: option.c:4314
+msgid "Cannot set 'term' to empty string"
+msgstr "Vo¾ba 'term' nemôže by prázdna"
+
+#: option.c:4317
+msgid "Cannot change term in GUI"
+msgstr "V GUI sa nedá meni term"
+
+#: option.c:4319
+msgid "Use \":gui\" to start the GUI"
+msgstr "Použite \"gui\" pre spustenie GUI"
+
+#: option.c:4340
+msgid "'backupext' and 'patchmode' are equal"
+msgstr "vo¾by 'backupext' a 'patchmode' majú rovnakú hodnotu"
+
+#: option.c:4638
+msgid "Zero length string"
+msgstr "Reazec s nulovou dåžkou"
+
+#: option.c:4706
+#, c-format
+msgid "Missing number after <%s>"
+msgstr "Po <%s> chýba èíslo"
+
+#: option.c:4720
+msgid "Missing comma"
+msgstr "Chýba èiarka"
+
+#: option.c:4727
+msgid "Must specify a ' value"
+msgstr "Je nutné zada hodnotu '"
+
+#: option.c:4767
+msgid "contains unprintable character"
+msgstr "obsahuje netlaèite¾né znaky"
+
+#: option.c:4800
+msgid "Invalid font(s)"
+msgstr "Chybné písma"
+
+#: option.c:4807
+msgid "can't select fontset"
+msgstr "nedá sa vybra sada písiem"
+
+#: option.c:4809
+msgid "Invalid fontset"
+msgstr "Chybná sada písiem"
+
+#: option.c:4816
+msgid "can't select wide font"
+msgstr "nedá sa vybra široký font"
+
+#: option.c:4818
+msgid "Invalid wide font"
+msgstr "Chybné široké písmo"
+
+#: option.c:5088
+#, c-format
+msgid "Illegal character after <%c>"
+msgstr "Neprístupný znak po <%c>"
+
+#: option.c:5171
+msgid "comma required"
+msgstr "je nutná èiarka"
+
+#: option.c:5179
+#, c-format
+msgid "'commentstring' must be empty or contain %s"
+msgstr "'komentár' musí by prázdny alebo musí obsahova %s"
+
+#: option.c:5226
+msgid "No mouse support"
+msgstr "Bez podpory myši"
+
+#: option.c:5472
+msgid "Unclosed expression sequence"
+msgstr "Neuzatvorené zoskupenie výrazov"
+
+#: option.c:5476
+msgid "too many items"
+msgstr "príliš mnoho položiek"
+
+#: option.c:5478
+msgid "unbalanced groups"
+msgstr "nevyvážené skupiny"
+
+#: option.c:5693
+msgid "A preview window already exists"
+msgstr "Okno náh¾adu už existuje"
+
+#: option.c:5954 option.c:5983
+msgid "'winheight' cannot be smaller than 'winminheight'"
+msgstr "hodnota vo¾by 'winheight' nesmie by menšia než hodnota vo¾by 'winminheight'"
+
+#: option.c:5999 option.c:6018
+msgid "'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "hodnota vo¾by 'winwidth' nesmie by menšia než hodnota vol¾y 'winminwidth'"
+
+#: option.c:6159
+#, c-format
+msgid "Need at least %d lines"
+msgstr "Minimálne potrebný poèet riadkov: %d"
+
+#: option.c:6168
+#, c-format
+msgid "Need at least %d columns"
+msgstr "Minimálne potrebný poèet ståpcov: %d"
+
+#: option.c:6465
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Neznáma vo¾ba: %s"
+
+#: option.c:6574
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Kódy terminálu ---"
+
+#: option.c:6576
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Nastavenie globálnych volieb ---"
+
+#: option.c:6578
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Nastavenie globálnych volieb ---"
+
+#: option.c:6580
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Možnosti ---"
+
+#: option.c:7269
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp CHYBA"
+
+#: option.c:8227
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': pre %s chýba vyhovujúci znak"
+
+#: option.c:8261
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': nadbytoèné znaky po bodkoèiarke: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "nedá sa otvori "
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Nedá sa otvori okno!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Je potrebná Amigados verzia 2.04 alebo novšia\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Potrebný %s verzia %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "Nedá sa otvori NIL:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr "Nedá sa vytvori "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim ukonèený s %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "nemôžem zmeni konzolový mód ?!\n"
+
+#: os_amiga.c:938 os_mac.c:1177 os_mswin.c:629 os_riscos.c:757 os_unix.c:2803
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Nastavovanie režimu obrazovky nie je podporované"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: nie je konzolou??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1142
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Nedá sa spusti shell s -f vo¾bou"
+
+#: os_amiga.c:1183 os_amiga.c:1273
+msgid "Cannot execute "
+msgstr "Nedá sa spusti "
+
+#: os_amiga.c:1186 os_amiga.c:1283
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1206 os_amiga.c:1308
+msgid " returned\n"
+msgstr " vrátené\n"
+
+#: os_amiga.c:1448
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE príliš malá."
+
+#: os_amiga.c:1452
+msgid "I/O ERROR"
+msgstr "I/O CHYBA"
+
+#: os_mswin.c:503
+msgid "...(truncated)"
+msgstr "...(skrátené)"
+
+#: os_mswin.c:604
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'ståpce' nie je 80, nemôžem spusti externý príkaz"
+
+#: os_mswin.c:716 os_unix.c:5116
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Vyvolanie knižniènej funkcia zlyhalo pre \"%s()\""
+
+#: os_mswin.c:1365
+msgid "E237: Printer selection failed"
+msgstr "E237: Zlyhal výber tlaèiarne"
+
+#: os_mswin.c:1405
+#, c-format
+msgid "to %s on %s"
+msgstr "%s na %s"
+
+#: os_mswin.c:1420
+#, c-format
+msgid "E448: Unknown font: %s"
+msgstr "E448: Neznáme písmo: %s"
+
+#: os_mswin.c:1470 os_mswin.c:1480
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Chyba tlaèe: %s"
+
+#: os_mswin.c:1481
+msgid "Unknown"
+msgstr "Neznámy"
+
+#: os_mswin.c:1508
+#, c-format
+msgid "Printing '%s'"
+msgstr "Tlaèím '%s'"
+
+#: os_mswin.c:2596
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Chybný názov znakovej sady \"%s\" v názve písma \"%s\""
+
+#: os_mswin.c:2604
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Chybný znak '%c' v názve písma \"%s\""
+
+#: os_riscos.c:1256
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Chybná 'osfiletype' vo¾ba - použitie Textu"
+
+#: os_unix.c:862
+msgid "Vim: Double signal, exiting\n"
+msgstr "VIm: dvojitý signál, konèím\n"
+
+#: os_unix.c:868
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Zachytený smrtiaci signál %s\n"
+
+#: os_unix.c:871
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Zachytený smrtiaci signál\n"
+
+#: os_unix.c:1125
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Otváram X displej - zaberie %ld msec"
+
+#: os_unix.c:1152
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: chyba X\n"
+
+#: os_unix.c:1219
+msgid "Testing the X display failed"
+msgstr "Testovanie X displeja zlyhalo"
+
+#: os_unix.c:1363
+msgid "Opening the X display timed out"
+msgstr "Uplynul èas otvorenia X displeja"
+
+#: os_unix.c:2976 os_unix.c:3634
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"Nedá sa spusti shell "
+
+#: os_unix.c:3021
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Nedá sa spusti sh shell\n"
+
+#: os_unix.c:3025 os_unix.c:3640
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+" návratová hodnota shellu "
+
+#: os_unix.c:3159
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Nedjú sa vytvori rúry\n"
+
+#: os_unix.c:3174
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"Vyvolanie fork zlyhalo\n"
+
+#: os_unix.c:3647
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Príkaz ukonèený\n"
+
+#: os_unix.c:5164
+msgid "Opening the X display failed"
+msgstr "Otvorenie X displeja zlyhalo"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "Na riadku"
+
+#: os_win16.c:578 os_win32.c:3037
+#, c-format
+msgid "shell returned %d"
+msgstr "návratová hodnota shellu %d"
+
+#: os_win32.c:2505
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Zachytená udalos %s\n"
+
+#: os_win32.c:2507
+msgid "close"
+msgstr "zavrie"
+
+#: os_win32.c:2509
+msgid "logoff"
+msgstr "odhlási"
+
+#: os_win32.c:2510
+msgid "shutdown"
+msgstr "vypnú"
+
+#: os_win32.c:2991
+msgid "E371: Command not found"
+msgstr "E371: Príkaz nenájdený"
+
+#: os_win32.c:3004
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE nenájdený v $PATH.\n"
+"Po dokonèení externých príkazov nebude výstup pozastavený.\n"
+"Pozrite :help win32-vimrun pre viac informácií."
+
+#: os_win32.c:3007
+msgid "Vim Warning"
+msgstr "Vim Varovanie"
+
+#: os_w32exe.c:169
+msgid "Could not load vim32.dll!"
+msgstr "Nemôžem nahra vim32.dll!"
+
+#: os_w32exe.c:169 os_w32exe.c:179
+msgid "VIM Error"
+msgstr "VIM Chyba"
+
+#: os_w32exe.c:179
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Nemôžem opravi odkazy funkcie na DLL!"
+
+#: quickfix.c:281
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Príliš mnoho %%%c vo formátovacom reazci"
+
+#: quickfix.c:294
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: Neoèakávaný výskyt %%%c vo formátovacom reazci"
+
+#: quickfix.c:348
+msgid "E374: Missing ] in format string"
+msgstr "E374: Vo formátovacom reazci chýba ]"
+
+#: quickfix.c:362
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: Nepodporovaná formátová špecifikácia %%%c vo formátovacom reazci"
+
+#: quickfix.c:380
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: Neprístupné %%%c v prefixe formátovacieho reazca"
+
+#: quickfix.c:388
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: Neprístupné %%%c vo formátovacom reazci"
+
+#: quickfix.c:414
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' neobsahuje žiadny vzor"
+
+#: quickfix.c:520
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Chýbajúci alebo prázdny názov adresára"
+
+#: quickfix.c:931
+msgid "No more items"
+msgstr "Žiadne ïalšie položky"
+
+#: quickfix.c:1152
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d/%d)%s%s: "
+
+#: quickfix.c:1154
+msgid " (line deleted)"
+msgstr " (riadok vymazaný)"
+
+#: quickfix.c:1360
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Koniec quickfix zoznamu"
+
+#: quickfix.c:1369
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Zaèiatok quickfix zoznamu"
+
+#: quickfix.c:1381
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "zoznam chýb %d z %d; poèet chýb: %d"
+
+#: quickfix.c:1842
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: Nedá sa uloži, je nastavená vo¾ba 'buftype'"
+
+#: regexp.c:802
+msgid "E339: Pattern too long"
+msgstr "E339: Vzor je príliš dlhý"
+
+#: regexp.c:1319
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: Vhniezdený %s*"
+
+#: regexp.c:1322
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: Vhniezdené %s%c"
+
+#: regexp.c:1473
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c niè nenasleduje"
+
+#: regexp.c:2490
+#, c-format
+msgid "Syntax error in %s{...}"
+msgstr "Chyba syntaxe v %s{...}"
+
+#: regexp.c:2737
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Zachytené preteèenie zásobníku: príliš zložitý regulárny výraz?"
+
+#: regexp.c:2872
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: vzor spôsobil preteèenie zásobníku"
+
+#: regexp.c:3108
+msgid "External submatches:\n"
+msgstr "Vnútorné podradené zhody:\n"
+
+#: screen.c:2063
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld riadkov zahnutých "
+
+#: screen.c:7517
+msgid " VREPLACE"
+msgstr " NAHRADI VERTIKÁLNE"
+
+#: screen.c:7521
+msgid " REPLACE"
+msgstr " NAHRADI"
+
+#: screen.c:7526
+msgid " REVERSE"
+msgstr " OBRÁTI"
+
+#: screen.c:7528
+msgid " INSERT"
+msgstr " VLOŽI"
+
+#: screen.c:7531
+msgid " (insert)"
+msgstr " (vloži)"
+
+#: screen.c:7533
+msgid " (replace)"
+msgstr " (nahradi)"
+
+#: screen.c:7535
+msgid " (vreplace)"
+msgstr " (nahradi vertikálne)"
+
+#: screen.c:7538
+msgid " Hebrew"
+msgstr " hebrejský"
+
+#: screen.c:7546
+msgid " (lang)"
+msgstr " (jazyk)"
+
+#: screen.c:7549
+msgid " (paste)"
+msgstr " (vloži)"
+
+#: screen.c:7555
+msgid " SELECT"
+msgstr " ZHODY"
+
+#: screen.c:7557
+msgid " VISUAL"
+msgstr " VIZUÁLNE"
+
+#: screen.c:7559
+msgid " BLOCK"
+msgstr " BLOK"
+
+#: screen.c:7561
+msgid " LINE"
+msgstr " RIADOK"
+
+#: screen.c:7574 screen.c:7634
+msgid "recording"
+msgstr "nahrávam"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "h¾adanie dosiahlo zaèiatok, pokraèovanie od konca"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "h¾adanie dosiahlo koniec, pokraèovanie od zaèiatku"
+
+#: search.c:455
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Neprístupný h¾adaný reazec: %s"
+
+#: search.c:782
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: h¾adanie dosiahlo zaèiatok bez nájdenia %s"
+
+#: search.c:784
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: h¾adanie dosiahlo koniec bez nájdenia %s"
+
+#: search.c:1144
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: Po ';' oèakávam '?' alebo '/'"
+
+#: search.c:3523
+msgid " (includes previously listed match)"
+msgstr " (vrátane už vypísaných zhôd)"
+
+#. cursor at status line
+#: search.c:3543
+msgid "--- Included files "
+msgstr "--- Vložené súbory"
+
+#: search.c:3545
+msgid "not found "
+msgstr "nenájdené "
+
+#: search.c:3546
+msgid "in path ---\n"
+msgstr "v ceste ---\n"
+
+#: search.c:3585
+msgid " (Already listed)"
+msgstr " (Už vypísané)"
+
+#: search.c:3587
+msgid " NOT FOUND"
+msgstr " NENÁJDENÉ"
+
+#: search.c:3639
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Preh¾adávam vložené súbory: %s"
+
+#: search.c:3857
+msgid "E387: Match is on current line"
+msgstr "E387: Zhoda je na aktuálnom riadku"
+
+#: search.c:3997
+msgid "All included files were found"
+msgstr "Všetky vložené súbory boli nájdené"
+
+#: search.c:3999
+msgid "No included files"
+msgstr "Žiadne vložené súbory"
+
+#: search.c:4015
+msgid "E388: Couldn't find definition"
+msgstr "E388: Nedá sa nájs definícia"
+
+#: search.c:4017
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Nedá sa nájs vzor"
+
+#: syntax.c:2999
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: Neprístupný argument: %s"
+
+#: syntax.c:3179
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: Syntaktická zostava %s neexistuje"
+
+#: syntax.c:3343
+msgid "No Syntax items defined for this buffer"
+msgstr "Pre tento buffer nie sú definované žiadne položky syntaxe"
+
+#: syntax.c:3351
+msgid "syncing on C-style comments"
+msgstr "synchronizujem komentáre v C štýle"
+
+#: syntax.c:3359
+msgid "no syncing"
+msgstr "žiadne synchronizácie"
+
+#: syntax.c:3362
+msgid "syncing starts "
+msgstr "synchronizácia zaèína "
+
+#: syntax.c:3364 syntax.c:3439
+msgid " lines before top line"
+msgstr " riadkov pred zaèiatkom"
+
+#: syntax.c:3369
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Položky synchronizácie syntaxe ---"
+
+#: syntax.c:3374
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"synchronizujem položky"
+
+#: syntax.c:3380
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Položky syntaxe ---"
+
+#: syntax.c:3403
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: Syntaktická zostava %s neexistuje"
+
+#: syntax.c:3429
+msgid "minimal "
+msgstr "minimálne "
+
+#: syntax.c:3436
+msgid "maximal "
+msgstr "maximálne "
+
+#: syntax.c:3448
+msgid "; match "
+msgstr "; zhoda "
+
+#: syntax.c:3450
+msgid " line breaks"
+msgstr " riadkov"
+
+#: syntax.c:4078
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: group[t]here nesmie by na tomto mieste"
+
+#: syntax.c:4102
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: Pre %s chýba položka regiónu"
+
+#: syntax.c:4130
+msgid "E395: contains argument not accepted here"
+msgstr "E395: obsahuje argumenty, ktoré tu nie sú povolené"
+
+#: syntax.c:4141
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: obsahuje argumenty, ktoré tu nie sú povolené"
+
+#: syntax.c:4219
+msgid "E397: Filename required"
+msgstr "E397: Vyžadovaný názov súboru"
+
+#: syntax.c:4557
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Chýba '=': %s"
+
+#: syntax.c:4715
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Príliš málo argumentov: oblas syntaxe %s"
+
+#: syntax.c:5046
+msgid "E400: No cluster specified"
+msgstr "E400: Nebola zadaná žiadna zostava"
+
+#: syntax.c:5083
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Odde¾ovaè vzoru %s nenájdený"
+
+#: syntax.c:5158
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Chyba za vzorom %s"
+
+#: syntax.c:5245
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: synchronizácia syntaxe: vzor pokraèovania riadkov zadaný dvakrát"
+
+#: syntax.c:5302
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Chybné argumenty: %s"
+
+#: syntax.c:5352
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Chýba znamienko rovnása: %s"
+
+#: syntax.c:5358
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Prázdny argument: %s"
+
+#: syntax.c:5385
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s tu nie je povolené"
+
+#: syntax.c:5392
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s musí by prvý v 'contains' zozname"
+
+#: syntax.c:5462
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Neznámy názov skupiny: %s"
+
+#: syntax.c:5692
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Chybný podradený príkaz :syntax : %s "
+
+#: syntax.c:6071
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: skupina zvíraznenia %s nebola nájdená"
+
+#: syntax.c:6095
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Príliš málo argumentov: \":highlight link %s\""
+
+#: syntax.c:6102
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: Príliš mnoho argumentov: \":highlight link %s\""
+
+#: syntax.c:6122
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: skupina je nastavená, odkaz na zvýrazòovaciu skupinu ignorovaný"
+
+#: syntax.c:6251
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: neoèakávané znamienko rovnása : %s"
+
+#: syntax.c:6287
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: chýba znamienko rovnása: %s"
+
+#: syntax.c:6309
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: chýba argument: %s"
+
+#: syntax.c:6346
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: Neprípustná hodnota: %s"
+
+#: syntax.c:6465
+msgid "E419: FG color unknown"
+msgstr "E419: farba popredia nie je známa"
+
+#: syntax.c:6476
+msgid "E420: BG color unknown"
+msgstr "E420: farba pozadia nie je známa"
+
+#: syntax.c:6537
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Názov alebo èíslo farby %s nebolo rozpoznané"
+
+#: syntax.c:6745
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: terminálový kód %s je príliš dlhý"
+
+#: syntax.c:6792
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: Neprístupný argument: %s"
+
+#: syntax.c:7321
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: Je používané príliš velké množstvo odlišných zvýrazòovacích vlastností"
+
+#: tag.c:90
+msgid "at bottom of tag stack"
+msgstr "koniec zoznamu tagov"
+
+#: tag.c:91
+msgid "at top of tag stack"
+msgstr "zaèiatok zoznamu tagov"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Nedá sa skoèi pred prvý vyhovujúci tag"
+
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: tag %s nenájdený"
+
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr " # pri tag"
+
+#: tag.c:548
+msgid "file\n"
+msgstr "súbor\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Zadajte èíslo (<CR> pre ukonèenie): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: Vyhovuje iba jeden tag"
+
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Za posledný vyhovujúci tag sa nedá preskoèi"
+
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Súbor \"%s\" neexistuje"
+
+#. Give an indication of the number of matching tags
+#: tag.c:780
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "tag %d z celkového poètu %d%s"
+
+#: tag.c:783
+msgid " or more"
+msgstr " alebo viac"
+
+#: tag.c:785
+msgid " Using tag with different case!"
+msgstr " Používam tag s písmom inej ve¾kosti!"
+
+#: tag.c:828
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Súbor \"%s\" neexistuje"
+
+#. Highlight title
+#: tag.c:897
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # CIE¼ tag ŠTART riadok v súbore/texte"
+
+#: tag.c:1144
+msgid "Linear tag search"
+msgstr "Lineárne h¾adanie tagu"
+
+#: tag.c:1146
+msgid "Binary tag search"
+msgstr "Binárne h¾adanie tagu"
+
+#: tag.c:1172
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Preh¾adávam súbor tagov %s"
+
+#: tag.c:1356
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Súbor tagov %s bol orezaný\n"
+
+#: tag.c:1847
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Chyba formátu v súbore tagov \"%s\""
+
+#: tag.c:1851
+#, c-format
+msgid "Before byte %ld"
+msgstr "Pred bajtom %ld"
+
+#: tag.c:1872
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Obsah súboru tagov %s nie je zoradený"
+
+#. never opened any tags file
+#: tag.c:1911
+msgid "E433: No tags file"
+msgstr "E433: Žiadny súbor tagov"
+
+#: tag.c:2583
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Nedá sa nájs vzor tagov"
+
+#: tag.c:2594
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Tag sa nedá nájs, iba hádam!"
+
+#: term.c:1737
+msgid "' not known. Available builtin terminals are:"
+msgstr "' nie je známy. Dostupné vstavané terminály:"
+
+#: term.c:1761
+msgid "defaulting to '"
+msgstr "nastavujem na '"
+
+#: term.c:2114
+msgid "Cannot open termcap file"
+msgstr "Nedá sa otvori termcap súbor"
+
+#: term.c:2117
+msgid "Terminal entry not found in terminfo"
+msgstr "Terminfo neobsahuje položku pre tento terminál"
+
+#: term.c:2119
+msgid "Terminal entry not found in termcap"
+msgstr "Termcap neobsahuje položku pre tento terminál"
+
+#: term.c:2278
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Termcap neobsahuje položku pre \"%s\""
+
+#: term.c:2752
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: Terminál musí ma \"cm\" schopnos"
+
+#. Highlight title
+#: term.c:4891
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Klávesy terminálu ---"
+
+#: ui.c:251
+msgid "new shell started\n"
+msgstr "spustený nový shell\n"
+
+#: ui.c:1747
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: Chyba pri èítaní vstupu, konèím...\n"
+
+#. must display the prompt
+#: undo.c:383
+msgid "No undo possible; continue anyway"
+msgstr "Odstránenie zmien nie je možné; chcete napriek tomu pokraèova"
+
+#: undo.c:538
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: èísla riadkov sú chybné"
+
+#: undo.c:707
+msgid "1 change"
+msgstr "poèet zmien: 1"
+
+#: undo.c:709
+#, c-format
+msgid "%ld changes"
+msgstr "poèet zmien: %ld"
+
+#: undo.c:753
+msgid "E439: undo list corrupt"
+msgstr "E439: záznam o zmenách poškodený"
+
+#: undo.c:785
+msgid "E440: undo line missing"
+msgstr "E440: chýba riadok spä"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:725
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"16/32 bitová GUI verzia pre MS Windows"
+
+#: version.c:727
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"32 bitová GUI verzia pre MS Windows"
+
+#: version.c:730
+msgid " in Win32s mode"
+msgstr " v Win32 režime"
+
+#: version.c:732
+msgid " with OLE support"
+msgstr " s OLE podporou"
+
+#: version.c:735
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"32 bitová verzia pre MS Windows konzolu"
+
+#: version.c:739
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"16 bitová verzia pre MS Windows"
+
+#: version.c:743
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 bitová verzia pre MS-DOS"
+
+#: version.c:745
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 bitová MS-DOS verzia"
+
+#: version.c:751
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) verzia"
+
+#: version.c:753
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X verzia"
+
+#: version.c:756
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS verzia"
+
+#: version.c:761
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS verzia"
+
+#: version.c:771
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Použité záplaty: "
+
+#: version.c:797 version.c:1132
+msgid "Modified by "
+msgstr "Zmenil "
+
+#: version.c:804
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Preložená "
+
+#: version.c:807
+msgid "by "
+msgstr " "
+
+#: version.c:819
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Maximálna verzia"
+
+#: version.c:822
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Ve¾ká verzia "
+
+#: version.c:825
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Normálna verzia"
+
+#: version.c:828
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Malá verzia "
+
+#: version.c:830
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Minimálna verzia "
+
+#: version.c:836
+msgid "without GUI."
+msgstr "bez grafického rozhrania."
+
+#: version.c:840
+msgid "with GTK-GNOME GUI."
+msgstr "s rozhraním GTK-GNOME."
+
+#: version.c:842
+msgid "with GTK GUI."
+msgstr "s rozhraním GTK."
+
+#: version.c:846
+msgid "with X11-Motif GUI."
+msgstr "s rozhraním X11-Motif."
+
+#: version.c:849
+msgid "with X11-Athena GUI."
+msgstr "s rozhraním X11-Athena."
+
+#: version.c:852
+msgid "with BeOS GUI."
+msgstr "s rozhraním BeOS."
+
+#: version.c:855
+msgid "with Photon GUI."
+msgstr "s rozhraním Photon."
+
+#: version.c:858
+msgid "with GUI."
+msgstr "s grafickým rozhraním."
+
+#: version.c:861
+msgid "with Carbon GUI."
+msgstr "s Carbon grafickým rozhraním."
+
+#: version.c:864
+msgid "with Cocoa GUI."
+msgstr "s Cocoa grafickým rozhraním."
+
+#: version.c:867
+msgid "with (classic) GUI."
+msgstr "s (klasickým) grafickým rozhraním."
+
+#: version.c:878
+msgid " Features included (+) or not (-):\n"
+msgstr " Vlastnosti zahrnuté (+) a nezahrnuté (-):\n"
+
+#: version.c:890
+msgid " system vimrc file: \""
+msgstr " systémový vimrc súbor: \""
+
+#: version.c:895
+msgid " user vimrc file: \""
+msgstr " užívate¾ský vimrc súbor: \""
+
+#: version.c:900
+msgid " 2nd user vimrc file: \""
+msgstr " druhý užívate¾ský vimrc súbor: \""
+
+#: version.c:905
+msgid " 3rd user vimrc file: \""
+msgstr " tretí užívate¾ský vimrc súbor: \""
+
+#: version.c:910
+msgid " user exrc file: \""
+msgstr " užívate¾ský exrc súbor: \""
+
+#: version.c:915
+msgid " 2nd user exrc file: \""
+msgstr " druhý užívate¾ský exrc súbor: \""
+
+#: version.c:921
+msgid " system gvimrc file: \""
+msgstr " systémový gvimrc súbor: \""
+
+#: version.c:925
+msgid " user gvimrc file: \""
+msgstr " užívate¾ský gvimrc súbor: \""
+
+#: version.c:929
+msgid "2nd user gvimrc file: \""
+msgstr "druhý užívate¾ský gvimrc súbor: \""
+
+#: version.c:934
+msgid "3rd user gvimrc file: \""
+msgstr "tretí užívate¾ský gvimrc súbor: \""
+
+#: version.c:941
+msgid " system menu file: \""
+msgstr " systémový súbor s ponukou: \""
+
+#: version.c:949
+msgid " fall-back for $VIM: \""
+msgstr " implicitná hodnota $VIM:\""
+
+#: version.c:955
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " f-b pre $VIMRUNTIME: \""
+
+#: version.c:959
+msgid "Compilation: "
+msgstr "Preklad: "
+
+#: version.c:965
+msgid "Compiler: "
+msgstr "Prekladaè: "
+
+#: version.c:970
+msgid "Linking: "
+msgstr "Linkujem: "
+
+#: version.c:975
+msgid " DEBUG BUILD"
+msgstr " PODPORA LADENIA"
+
+#: version.c:1011
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMpreved"
+
+#: version.c:1013
+msgid "version "
+msgstr "verzia "
+
+#: version.c:1014
+msgid "by Bram Moolenaar et al."
+msgstr "Autor: Bram Moolenaar a ïalší"
+
+#: version.c:1018
+msgid "Vim is open source and freely distributable"
+msgstr "Vim je vo¾ne šírite¾ný program"
+
+#: version.c:1020
+msgid "Help poor children in Uganda!"
+msgstr "Pomôžte chudobným deom v Ugande!"
+
+#: version.c:1021
+msgid "type :help iccf<Enter> for information "
+msgstr "podrobnejšie informácie získate pomocou :help iccf<Enter>"
+
+#: version.c:1023
+msgid "type :q<Enter> to exit "
+msgstr "zadajte :q<Enter> pre ukonèenie programu"
+
+#: version.c:1024
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "zadajte :help<Enter> alebo <F1> pre pomocníka"
+
+#: version.c:1025
+msgid "type :help version6<Enter> for version info"
+msgstr "zadajte :help version6<Enter> pre informácie o verzii"
+
+#: version.c:1028
+msgid "Running in Vi compatible mode"
+msgstr "Bežím v režime kompatibility s Vi"
+
+#: version.c:1029
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "zadajte :set nocp<Enter> pre implicitné nastavenie Vim"
+
+#: version.c:1030
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "podrobnejšie informácie získate pomocou :help cp-default<Enter>"
+
+#: version.c:1045
+msgid "menu Help->Orphans for information "
+msgstr "bližšie informácie v menu Pomocník->Samostatné"
+
+#: version.c:1047
+msgid "Running modeless, typed text is inserted"
+msgstr "Spúšam modeless, písaný text je vložený"
+
+#: version.c:1048
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "menu Úpravy->Globálne možnosti->Prepnú režim vloženia "
+
+#: version.c:1049
+msgid " for two modes "
+msgstr " pre dva režimy "
+
+#: version.c:1053
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "menu Úpravy->Globálne možnostt->Prepnú Vi kompatibilný režím"
+
+#: version.c:1054
+msgid " for Vim defaults "
+msgstr " pre predvolené vlastnosti Vim "
+
+#: version.c:1100
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "VAROVANIE: detekované Windows 95/98/ME"
+
+#: version.c:1103
+msgid "type :help windows95<Enter> for info on this"
+msgstr "zadajte :help windows95<Enter> pre podrobnejšie informácie"
+
+#: window.c:201
+msgid "E441: There is no preview window"
+msgstr "E441: Nenájdené žiadne okno náh¾adu"
+
+#: window.c:580
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: Okno sa nedá rozdeli zároveò topleft a botright"
+
+#: window.c:1339
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Nedá sa rotova, ak je iné okno rozdelené"
+
+#: window.c:1841
+msgid "E444: Cannot close last window"
+msgstr "E444: Posledné okno sa nedá zatvori"
+
+#: window.c:2505
+msgid "Already only one window"
+msgstr "Už existuje iba jedno okno"
+
+#: window.c:2552
+msgid "E445: Other window contains changes"
+msgstr "E445: Iné okno obsahuje zmeny"
+
+#: window.c:4379
+msgid "E446: No file name under cursor"
+msgstr "E446: Pod kurzorom sa nenachádza názov súboru"
+
+#: window.c:4498
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Súbor \"%s\" sa nedá v cdpath nájs"
+
+#: ../GvimExt/gvimext.cpp:586
+msgid "Edit with &multiple Vims"
+msgstr "Upravi s viacnásobný&m Vimom"
+
+#: ../GvimExt/gvimext.cpp:592
+msgid "Edit with single &Vim"
+msgstr "Upravi s jedným &Vimom"
+
+#: ../GvimExt/gvimext.cpp:604
+msgid "Edit with &Vim"
+msgstr "Upravi s &Vimom"
+
+#. Now concatenate
+#: ../GvimExt/gvimext.cpp:628
+msgid "Edit with existing Vim - &"
+msgstr "Upravi s existujúcim Vimom - &"
+
+#: ../GvimExt/gvimext.cpp:752
+msgid "Edits the selected file(s) with Vim"
+msgstr "Upravi vybrané súbory s Vimom"
+
+#: ../GvimExt/gvimext.cpp:891 ../GvimExt/gvimext.cpp:969
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "Chyba vytváracieho procesu: Skontrolujte, èi je gvim vo vašej ceste!"
+
+#: ../GvimExt/gvimext.cpp:892 ../GvimExt/gvimext.cpp:906
+#: ../GvimExt/gvimext.cpp:970
+msgid "gvimext.dll error"
+msgstr "chyba gvimext.dll"
+
+#: ../GvimExt/gvimext.cpp:905
+msgid "Path length too long!"
+msgstr "Príliš dlhá cesta!"
+
+#: globals.h:900
+msgid "--No lines in buffer--"
+msgstr "--Buffer neobsahuje žiadny riadok--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1042
+msgid "Command aborted"
+msgstr "Príkaz prerušený"
+
+#: globals.h:1043
+msgid "Argument required"
+msgstr "Je vyžadovaný argument"
+
+#: globals.h:1044
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: po \\ by malo nasledova /. ? alebo &"
+
+#: globals.h:1046
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr ""
+"E11: Chybný príkaz v okne príkazového riadku; <Enter> spustíte, CTRL-C "
+"vypnete"
+
+#: globals.h:1048
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Príkaz nie je z exrc/vimrc v aktuálnom adresári alebo pri h¾adaní tagu "
+"povolený."
+
+#: globals.h:1049
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Súbor existuje (použite ! pre vynútenie)"
+
+#: globals.h:1050
+msgid "Command failed"
+msgstr "Príkaz zlyhal"
+
+#: globals.h:1051
+msgid "Internal error"
+msgstr "Vnútorná chyba"
+
+#: globals.h:1052
+msgid "Interrupted"
+msgstr "Prerušené"
+
+#: globals.h:1053
+msgid "E14: Invalid address"
+msgstr "E14: Chybná adresa"
+
+#: globals.h:1054
+msgid "Invalid argument"
+msgstr "Chybný argument"
+
+#: globals.h:1055
+#, c-format
+msgid "Invalid argument: %s"
+msgstr "Chybný argument: %s"
+
+#: globals.h:1057
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Chybný výraz: %s"
+
+#: globals.h:1059
+msgid "E16: Invalid range"
+msgstr "E16: Chybný rozsah"
+
+#: globals.h:1060
+msgid "Invalid command"
+msgstr "Chybný príkaz"
+
+#: globals.h:1062
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" je adresárom"
+
+#: globals.h:1065
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Neoèekávané znaky pred '='"
+
+#: globals.h:1067
+msgid "E19: Mark has invalid line number"
+msgstr "E19: Znaèka má chybné èíslo riadku"
+
+#: globals.h:1068
+msgid "E20: Mark not set"
+msgstr "E20: Znaèka nie je nastavená"
+
+#: globals.h:1069
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Nedá sa meni, je nastavená vo¾ba 'modifiable'"
+
+#: globals.h:1070
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Skript vnorený príliš hlboko"
+
+#: globals.h:1071
+msgid "E23: No alternate file"
+msgstr "E23: Žiadny alternatívny súbor"
+
+#: globals.h:1072
+msgid "E24: No such abbreviation"
+msgstr "E24: Taká skratka neexistuje"
+
+#: globals.h:1073
+msgid "No ! allowed"
+msgstr "! nie je povolené"
+
+#: globals.h:1075
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: Nedá sa použí GUI: nebolo zapnuté pri preklade programu"
+
+#: globals.h:1078
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: Nedá sa použí hebrejský režim: nebol zapnutý pri preklade programu\n"
+
+#: globals.h:1081
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: Nedá sa použí farsi režim: nebol zapnutý pri preklade programu\n"
+
+#: globals.h:1084
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Skupina zvíraznenia %s neexistuje"
+
+#: globals.h:1086
+msgid "E29: No inserted text yet"
+msgstr "E29: Zatia¾ nie je žiadny vložený text"
+
+#: globals.h:1087
+msgid "E30: No previous command line"
+msgstr "E30: Žiadny predchádzajúci príkazový riadok"
+
+#: globals.h:1088
+msgid "E31: No such mapping"
+msgstr "E31: Žiadne také mapovanie"
+
+#: globals.h:1089
+msgid "No match"
+msgstr "Žiadna zhoda"
+
+#: globals.h:1090
+#, c-format
+msgid "No match: %s"
+msgstr "Žiadna zhoda: %s"
+
+#: globals.h:1091
+msgid "E32: No file name"
+msgstr "E32: Žiadny názov súboru"
+
+#: globals.h:1092
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: Žiadny predchádzajúci prislúchajúci správny výraz"
+
+#: globals.h:1093
+msgid "E34: No previous command"
+msgstr "E34: Žiadny predchádzajúci príkaz"
+
+#: globals.h:1094
+msgid "E35: No previous regular expression"
+msgstr "E35: Žiadny predchádzajúci regulárny výraz"
+
+#: globals.h:1095
+msgid "No range allowed"
+msgstr "Rozsah nie je povolený"
+
+#: globals.h:1097
+msgid "E36: Not enough room"
+msgstr "E36: Nedostatok miesta"
+
+#: globals.h:1099
+#, c-format
+msgid "Can't create file %s"
+msgstr "Nedá sa vytvori súbor %s"
+
+#: globals.h:1100
+msgid "Can't get temp file name"
+msgstr "Nedá sa získa názov doèasného súboru"
+
+#: globals.h:1101
+#, c-format
+msgid "Can't open file %s"
+msgstr "Nedá sa otvori súbor %s"
+
+#: globals.h:1102
+#, c-format
+msgid "Can't read file %s"
+msgstr "Nedá sa èíta súbor %s"
+
+#: globals.h:1103
+msgid "E37: No write since last change (use ! to override)"
+msgstr "E37: Neuložené zmeny (použite ! pre vynútenie)"
+
+#: globals.h:1104
+msgid "E38: Null argument"
+msgstr "E38: Nulový argument"
+
+#: globals.h:1106
+msgid "E39: Number expected"
+msgstr "E39: Oèakávané èíslo"
+
+#: globals.h:1109
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Nedá sa otvori chybový súbor %s"
+
+#: globals.h:1112
+msgid "E41: Out of memory!"
+msgstr "E41: Nedostatok pamäti!"
+
+#: globals.h:1115
+msgid "Pattern not found"
+msgstr "Vzor nenájdený"
+
+#: globals.h:1117
+#, c-format
+msgid "Pattern not found: %s"
+msgstr "Vzor nenájdený: %s"
+
+#: globals.h:1118
+msgid "Argument must be positive"
+msgstr "Argument musí by kladný"
+
+#: globals.h:1120
+msgid "E42: No Errors"
+msgstr "E42: Žiadne chyby"
+
+#: globals.h:1122
+msgid "E43: Damaged match string"
+msgstr "E43: Poškodený reazac pre vyh¾adávanie"
+
+#: globals.h:1123
+msgid "E44: Corrupted regexp program"
+msgstr "E44: Poškodený regexp program"
+
+#: globals.h:1124
+msgid "E45: 'readonly' option is set (use ! to override)"
+msgstr "E45: nastavená vo¾ba 'iba_pre_èítanie' (použite ! pre vynútenie)"
+
+#: globals.h:1126
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Nedá sa nastavi premenná iba_pre_èítanie \"%s\""
+
+#: globals.h:1129
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Chyba pri èítaní chybového súboru"
+
+#: globals.h:1132
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: Nie je v bezpeènostnej schránke povolené"
+
+#: globals.h:1134
+msgid "E49: Invalid scroll size"
+msgstr "E49: Chybná hodnota premennej 'scroll'"
+
+#: globals.h:1135
+msgid "E91: 'shell' option is empty"
+msgstr "E91: vo¾ba 'shell' je prázdna"
+
+#: globals.h:1136
+msgid "E72: Close error on swap file"
+msgstr "E72: Chyba pri uzatváraní odkladacieho súboru"
+
+#: globals.h:1137
+msgid "E73: tag stack empty"
+msgstr "E73: zoznam tagov je prázdny"
+
+#: globals.h:1138
+msgid "E74: Command too complex"
+msgstr "E74: Príkaz je príliš zložitý"
+
+#: globals.h:1139
+msgid "E75: Name too long"
+msgstr "E75: Názov je príliš dlhý"
+
+#: globals.h:1140
+msgid "E76: Too many ["
+msgstr "E76: Príliš mnoho ["
+
+#: globals.h:1141
+msgid "E77: Too many file names"
+msgstr "E77: Príliš mnoho názvov súborov"
+
+#: globals.h:1142
+msgid "Trailing characters"
+msgstr "Nadbytoèné znaky na konci"
+
+#: globals.h:1143
+msgid "E78: Unknown mark"
+msgstr "E78: Neznáma znaèka"
+
+#: globals.h:1144
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Nedá sa expandova žolíkové znaky (wildcards)"
+
+#: globals.h:1145
+msgid "E80: Error while writing"
+msgstr "E80: Chyba pri ukladaní"
+
+#: globals.h:1146
+msgid "Zero count"
+msgstr "Nulový poèet"
+
+#: globals.h:1148
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: Použitie <SID> mimo kontext skriptu"
+
+#: globals.h:1151
+msgid "E449: Invalid expression received"
+msgstr "E449: Bol prijatý chybný výraz"
+
diff --git a/src/po/sk.po b/src/po/sk.po
new file mode 100644
index 000000000..00fe87c5f
--- /dev/null
+++ b/src/po/sk.po
@@ -0,0 +1,5998 @@
+# Slovak translation of vim
+# Martin Lacko <lacko@host.sk>, 2001.
+#
+# Original translations.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: vim\n"
+"POT-Creation-Date: 2002-03-26 21:54+0100\n"
+"PO-Revision-Date: 2002-03-26 21:58CEST\n"
+"Last-Translator: Martin Lacko <lacko@host.sk>\n"
+"Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-2\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 0.9.5\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Nedá sa alokova» buffer, konèím..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: Nedá sa alokova» buffer, pou¾ijem iný..."
+
+#: buffer.c:706
+msgid "No buffers were unloaded"
+msgstr "®iadny buffer nebol nájdený"
+
+#: buffer.c:708
+msgid "No buffers were deleted"
+msgstr "®iadny buffer nebol vymazaný"
+
+#: buffer.c:710
+msgid "No buffers were wiped out"
+msgstr "®iadny buffer nebol vymazaný"
+
+#: buffer.c:718
+msgid "1 buffer unloaded"
+msgstr "poèet deaktivovaných bufferov: 1"
+
+#: buffer.c:720
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "poèet deaktivovaných bufferov: %d"
+
+#: buffer.c:725
+msgid "1 buffer deleted"
+msgstr "poèet vymazaných bufferov: 1"
+
+#: buffer.c:727
+#, c-format
+msgid "%d buffers deleted"
+msgstr "poèet vymazaných bufferov: %d"
+
+#: buffer.c:732
+msgid "1 buffer wiped out"
+msgstr "poèet vymazaných bufferov: 1"
+
+#: buffer.c:734
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "poèet vymazaných bufferov: %d"
+
+#: buffer.c:791
+msgid "E84: No modified buffer found"
+msgstr "E84: Nebol nájdený ¾iadny zmenený buffer"
+
+#. back where we started, didn't find anything.
+#: buffer.c:830
+msgid "E85: There is no listed buffer"
+msgstr "E85: Nena¹iel som ¾iadny buffer"
+
+#: buffer.c:842
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: Nedá sa preskoèi» na buffer %ld"
+
+#: buffer.c:845
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Za posledný buffer sa nedá preskoèi»"
+
+#: buffer.c:847
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Pred prvý buffer sa nedá preskoèi»"
+
+#: buffer.c:871
+#, c-format
+msgid "E89: No write since last change for buffer %ld (use ! to override)"
+msgstr "E89: Zmeny v bufferi %ld neboly ulo¾ené (! pre vynútenie)"
+
+#: buffer.c:887
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: Posledný buffer sa nedá odstráni»"
+
+#: buffer.c:1337
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Varovanie: preteèenie zoznamu s názvami súborov"
+
+#: buffer.c:1503
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: buffer %ld nenájdený"
+
+#: buffer.c:1729
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Vzoru %s vyhovuje viac bufferov"
+
+#: buffer.c:1731
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: Vzoru %s nevyhovuje ¾iadny buffer"
+
+#: buffer.c:2136 ex_docmd.c:6089
+#, c-format
+msgid "line %ld"
+msgstr "riadok %ld"
+
+#: buffer.c:2219
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Buffer takéhoto mena u¾ existuje"
+
+#: buffer.c:2512
+msgid " [Modified]"
+msgstr " [zmenený]"
+
+#: buffer.c:2517
+msgid "[Not edited]"
+msgstr "[neupravovaný]"
+
+#: buffer.c:2522
+msgid "[New file]"
+msgstr "[nový súbor]"
+
+#: buffer.c:2523
+msgid "[Read errors]"
+msgstr "[chyby pri èítaní]"
+
+#: buffer.c:2525 fileio.c:1777
+msgid "[readonly]"
+msgstr "[iba pre èítanie]"
+
+#: buffer.c:2540
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 riadok --%d%%--"
+
+#: buffer.c:2542
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "riadkov: %ld --%d%%--"
+
+#: buffer.c:2549
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "riadok %ld z %ld --%d%%-- ståpec"
+
+#: buffer.c:2637
+msgid "[No file]"
+msgstr "[¾iadny súbor]"
+
+#. must be a help buffer
+#: buffer.c:2677
+msgid "help"
+msgstr "pomocník"
+
+#: buffer.c:3186 screen.c:4743
+msgid "[help]"
+msgstr "[pomocník]"
+
+#: buffer.c:3218 screen.c:4749
+msgid "[Preview]"
+msgstr "[náhµad]"
+
+#: buffer.c:3424
+msgid "All"
+msgstr "V¹etko"
+
+#: buffer.c:3424
+msgid "Bot"
+msgstr "Koniec"
+
+#: buffer.c:3426
+msgid "Top"
+msgstr "Zaèiatok"
+
+#: buffer.c:4162
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# zoznam bufferov:\n"
+
+#: buffer.c:4195
+msgid "[Error List]"
+msgstr "[zoznam chýb]"
+
+#: buffer.c:4208 memline.c:1513
+msgid "[No File]"
+msgstr "[¾iadny súbor]"
+
+#: buffer.c:4428
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Znaky ---"
+
+#: buffer.c:4438
+#, c-format
+msgid "Signs for %s:"
+msgstr "Znaky pre %s:"
+
+#: buffer.c:4444
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " line=%ld id=%d meno=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: Nemô¾em porovna» viac ako %ld bufferov"
+
+#: diff.c:648
+msgid "E97: Cannot create diffs"
+msgstr "E97: Nedajú sa vytvori» porovnania"
+
+#: diff.c:747
+msgid "Patch file"
+msgstr "Opravný súbor"
+
+#: diff.c:991
+msgid "E98: Cannot read diff output"
+msgstr "E98: Nedá sa èíta» výstup porovnania"
+
+#: diff.c:1732
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Aktuálny buffer nie je v porovnacom móde"
+
+#: diff.c:1744
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: V porovnávacom móde sa nenachádza iný buffer"
+
+#: diff.c:1752
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: Viac ako dva buffery v porovnávacom móde; neviem, ktorý pou¾i»"
+
+#: diff.c:1775
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Nedá sa nájs» buffer \"%s\""
+
+#: diff.c:1781
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Buffer \"%s\" nie je v porovnávacom móde"
+
+#: digraph.c:2172
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: diagraph nesmie obsahova» Escape"
+
+#: digraph.c:2344
+msgid "Keymap file not found"
+msgstr "Mapa kláves nenájdená"
+
+#: digraph.c:2371
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: Pou¾ite :loadkeymap v súbore, ktorý nie je zdrojový"
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " Doplòovanie kµúèových slov (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " ^X re¾im (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " Miestne dopåòanie kµúèových slov (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " Doplòovanie celých riadkov (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " Doplòovanie názvov súborov (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " Doplòovanie tagov (^]/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " Doplòovanie vzoru ciest (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " Doplòovanie definícií (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " Doplòovanie podµa slovníka (^K/^N/^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Doplòovanie podµa tezauru (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " Doplòovòovanie príkazového riadka (^V/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Koniec odstavca"
+
+#: edit.c:907
+msgid "'thesaurus' option is empty"
+msgstr "voµba 'thesaurus' je prázdna"
+
+#: edit.c:1083
+msgid "'dictionary' option is empty"
+msgstr "voµba 'dictionary' je prázdna"
+
+#: edit.c:2007
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "prehµadávam slovník %s"
+
+#: edit.c:2198
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (insert) Rolovanie (^E/^Y)"
+
+#: edit.c:2200
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (replace) Rolovanie (^E/^Y)"
+
+#: edit.c:2512
+#, c-format
+msgid "Scanning: %s"
+msgstr "Prehµadávam: %s"
+
+#: edit.c:2547
+msgid "Scanning tags."
+msgstr "Prehµadávam tagy."
+
+#: edit.c:3207
+msgid " Adding"
+msgstr " Pridávam"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3256
+msgid "-- Searching..."
+msgstr "-- Hµadám..."
+
+#: edit.c:3312
+msgid "Back at original"
+msgstr "Východzia podoba"
+
+#: edit.c:3317
+msgid "Word from other line"
+msgstr "Slovo z iného riadku"
+
+#: edit.c:3322
+msgid "The only match"
+msgstr "Jediná zhoda"
+
+#: edit.c:3381
+#, c-format
+msgid "match %d of %d"
+msgstr "zhoda %d z %d"
+
+#: edit.c:3384
+#, c-format
+msgid "match %d"
+msgstr "zhoda %d"
+
+#: eval.c:698
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Neznáma premenná: \"%s\""
+
+#: eval.c:977
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Chýbjú závorky: %s"
+
+#: eval.c:1057 eval.c:1073
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Premenná \"%s\" neexistuje"
+
+#: eval.c:1315
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Po '?' chýba ':'"
+
+#: eval.c:1929
+msgid "E110: Missing ')'"
+msgstr "E110: Chýba ')'"
+
+#: eval.c:1979
+msgid "E111: Missing ']'"
+msgstr "E111: Chýba ']'"
+
+#: eval.c:2054
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Chýba meno voµby: %s"
+
+#: eval.c:2072
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Neznáma voµba: %s"
+
+#: eval.c:2134
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Chýbjú uvodzovky: %s"
+
+#: eval.c:2251
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Chýbjú uvodzovky: %s"
+
+#: eval.c:2569
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Chybné argumenty pre funkciu %s"
+
+#: eval.c:2570
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Neznáma funkcia: %s"
+
+#: eval.c:2571
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: Príli¹ mnoho argumentov pre funkciu %s"
+
+#: eval.c:2572
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Príli¹ málo argumentov pre funkciu %s"
+
+#: eval.c:2573
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: Pou¾itie <SID> mimo kontext skriptu: %s"
+
+#: eval.c:3172 gui.c:3984
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:3678
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld riadky: "
+
+#: eval.c:4794
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&Ok\n"
+"&Zru¹i»"
+
+#: eval.c:5626
+msgid "E240: No connection to Vim server"
+msgstr "E240: Neexistuje pripojenie k Vim serveru"
+
+#: eval.c:5716
+msgid "E277: Unable to read a server reply"
+msgstr "E227: Nemô¾em èíta» odpoveï servra"
+
+#: eval.c:5741
+msgid "E258: Unable to send to client"
+msgstr "E258: Nemô¾em posla» klientovi"
+
+#: eval.c:5786
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Nemô¾em posla» na %s"
+
+#: eval.c:5884
+msgid "(Invalid)"
+msgstr "(Chybný)"
+
+#: eval.c:6895
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Nedefinovaná premenná: %s"
+
+#: eval.c:7593
+#, c-format
+msgid "E122: Function %s already exists, use ! to replace"
+msgstr "E112: Funkcia %s u¾ existuje. Pou¾ite ! pre jej nahradenie."
+
+#: eval.c:7635
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Nedefinovaná funkcia: %s"
+
+#: eval.c:7648
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Chýba '(': %s"
+
+#: eval.c:7680
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Neprístupný argument: %s"
+
+#: eval.c:7766
+msgid "E126: Missing :endfunction"
+msgstr "E126: Chýba :endfunction"
+
+#: eval.c:7845
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Nedá sa predefinova» funkcia %s: je pou¾ívaná"
+
+#: eval.c:7903
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: Názov funkcie musí zaèína» veµkým písmenom: %s"
+
+#: eval.c:7909
+msgid "E129: Function name required"
+msgstr "E129: Je vy¾adované meno funkcie"
+
+#: eval.c:8002
+msgid "function "
+msgstr "funkcia "
+
+#: eval.c:8117
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Nedefinovaná funkcia: %s"
+
+#: eval.c:8122
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Nedá sa vymaza» funkcia %s: je u¾ pou¾ívaná"
+
+#: eval.c:8169
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: Zanorenie funkcií je hlb¹ie ne¾ 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:8220
+#, c-format
+msgid "calling %s"
+msgstr "volám %s"
+
+#. always scroll up, don't overwrite
+#: eval.c:8245 ex_cmds2.c:1988
+#, c-format
+msgid "continuing in %s"
+msgstr "pokraèujem v %s"
+
+#: eval.c:8299
+msgid "E133: :return not inside a function"
+msgstr "E133: :return mimo funkciu"
+
+#: eval.c:8377
+#, c-format
+msgid "%s returning #%ld"
+msgstr "dokonèené %s. Návratová hodnota %ld"
+
+#: eval.c:8380
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "dokonèené %s. Návratová hodnota \"%s\""
+
+#: eval.c:8521
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# globálne premenné:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, ¹estnástkovo %02x, osmièkovo %03o"
+
+#: ex_cmds.c:428
+msgid "E134: Move lines into themselves"
+msgstr "E134: Prekrytie riadkov sebou samými"
+
+#: ex_cmds.c:497
+msgid "1 line moved"
+msgstr "poèet preru¹ených riadkov: 1"
+
+#: ex_cmds.c:499
+#, c-format
+msgid "%ld lines moved"
+msgstr "poèet preru¹ených riadkov: %ld"
+
+#: ex_cmds.c:890
+#, c-format
+msgid "%ld lines filtered"
+msgstr "poèet filtrovaných riadkov: %ld"
+
+#: ex_cmds.c:918
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: Automatické príkazy *Filter* nesmie meni» aktuálny buffer"
+
+#: ex_cmds.c:1003
+msgid "[No write since last change]\n"
+msgstr "[Neulo¾ené zmeny]\n"
+
+#: ex_cmds.c:1248
+#, c-format
+msgid "viminfo: %s in line: "
+msgstr "viminfo: %s na riadku: "
+
+#: ex_cmds.c:1253
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: príli¹ mnoho chýb, preskakujem zbytok súboru"
+
+#: ex_cmds.c:1282
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Èítam viminfo súbor \"%s\"%s%s%s"
+
+#: ex_cmds.c:1283
+msgid " info"
+msgstr " informácie"
+
+#: ex_cmds.c:1284
+msgid " marks"
+msgstr " znaèky"
+
+#: ex_cmds.c:1285
+msgid " FAILED"
+msgstr " ZLYHALO"
+
+#: ex_cmds.c:1376
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Do viminfo súboru %s sa nedá zapisova»"
+
+#: ex_cmds.c:1501
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Nedá sa ulo¾i» viminfo súbor %s!"
+
+#: ex_cmds.c:1509
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Ukládám viminfo súboru \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1610
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Tento viminfo súbor bol vytvorený editorom Vim %s.\n"
+
+#: ex_cmds.c:1612
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Pokiaµ budete opatrnný, mô¾ete ho upravova».\n"
+"\n"
+
+#: ex_cmds.c:1614
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Hodnota 'encoding' poèas zápisu tohoto súboru\n"
+
+#: ex_cmds.c:1713
+msgid "Illegal starting char"
+msgstr "Neprístupný zaèiatoèný znak"
+
+#: ex_cmds.c:2053 ex_cmds.c:2310 ex_cmds2.c:602
+msgid "Save As"
+msgstr "Ulo¾i» ako"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2096
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Súbor je naèítaný v inob buffere"
+
+#: ex_cmds.c:2130
+msgid "Write partial file?"
+msgstr "Ulo¾i» neúplný súbor?"
+
+#: ex_cmds.c:2137
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Pou¾ite ! pre ulo¾enie neúplného bufferu"
+
+#: ex_cmds.c:2244
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Prepísa» súbor \"%.*s\"?"
+
+#: ex_cmds.c:2315
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: ®iadny názov súboru pre buffer %ld"
+
+#: ex_cmds.c:2353
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: Súbor nebol ulo¾ený: ukladanie je zakázané voµbou 'write'"
+
+#: ex_cmds.c:2373
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"Pre \"%.*s\" je nastavená voµba 'readonly' (iba na èítanie).\n"
+"Prajete si ju potlaèi»?"
+
+#: ex_cmds.c:2538
+msgid "Edit File"
+msgstr "Upravova» súbor"
+
+#: ex_cmds.c:3061
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Automatické príkazy neoèakávane zmazali nový buffer %s"
+
+#: ex_cmds.c:3193
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: neèíselný argument pre :z"
+
+#: ex_cmds.c:3278
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: rvim nepovoluje pou¾itie príkazov shellu"
+
+#: ex_cmds.c:3385
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Regulárne výrazy nesmú by» oddelené písmenami"
+
+#: ex_cmds.c:3727
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "nahradi» %s (y/n/a/q/I/^E/^Y)?"
+
+#: ex_cmds.c:4092
+msgid "(Interrupted) "
+msgstr "(preru¹ený) "
+
+#: ex_cmds.c:4096
+msgid "1 substitution"
+msgstr "poèet nahradení na riadok: 1"
+
+#: ex_cmds.c:4098
+#, c-format
+msgid "%ld substitutions"
+msgstr "poèet nahradení na riadok: %ld"
+
+#: ex_cmds.c:4101
+msgid " on 1 line"
+msgstr " na 1 riadku"
+
+#: ex_cmds.c:4103
+#, c-format
+msgid " on %ld lines"
+msgstr " na %ld riadkov"
+
+#: ex_cmds.c:4154
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: global nedá sa vola» rekurzívne"
+
+#: ex_cmds.c:4189
+msgid "E148: Regular expression missing from global"
+msgstr "E148: Pri príkaze global chýba regulárny výraz"
+
+#: ex_cmds.c:4238
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Vzor nájdený na ka¾dom riadku: %s"
+
+#: ex_cmds.c:4319
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Posledný Re»azec Podnadpisu:\n"
+"$"
+
+#: ex_cmds.c:4421
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: ¥utujem, pre %s nie je ¾iadny pomocník"
+
+#: ex_cmds.c:4455
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "¥utujem, súbor \"%s\" s pomocníkom nebol nájdený"
+
+#: ex_cmds.c:4917
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s nie je adresárom"
+
+#: ex_cmds.c:4945
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: Nedá sa otvori» %s pre zápis"
+
+#: ex_cmds.c:4959
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Nedá sa otvori» %s pre zápis"
+
+#: ex_cmds.c:5038
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: Duplicitný tag \"%s\" v súbore %s"
+
+#: ex_cmds.c:5139
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Neznáma funkcia: %s"
+
+#: ex_cmds.c:5159
+msgid "E156: Missing sign name"
+msgstr "E156: Chýba identifikátor pre sign"
+
+#: ex_cmds.c:5205
+msgid "E255: Too many signs defined"
+msgstr "E255: Príli¹ mnoho definovaných oznaèení"
+
+#: ex_cmds.c:5247
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Chybne oznaèený text: %s"
+
+#: ex_cmds.c:5271 ex_cmds.c:5457
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Neznáme oznaèenie: %s"
+
+#: ex_cmds.c:5317
+msgid "E159: Missing sign number"
+msgstr "E159: Chýba èislo oznaèenia"
+
+#: ex_cmds.c:5397
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: Chybné meno bufferu: %s"
+
+#: ex_cmds.c:5436
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Chybné ID oznaèenia: %ld"
+
+#: ex_cmds.c:5607
+msgid "[Deleted]"
+msgstr "[vymazaný]"
+
+#: ex_cmds2.c:70
+msgid "Entering Debug mode. Type \"cont\" to leave."
+msgstr "Spú¹»am re¾im ladenia. Pre ukonèenie napí¹te \"cont\"."
+
+#: ex_cmds2.c:74 ex_docmd.c:771
+#, c-format
+msgid "line %ld: %s"
+msgstr "riadok %ld: %s"
+
+#: ex_cmds2.c:76
+#, c-format
+msgid "cmd: %s"
+msgstr "príkaz: %s"
+
+#: ex_cmds2.c:224
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Bod preru¹enia v \"%s%s\" na riadku %ld"
+
+#: ex_cmds2.c:388
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Bod preru¹enia nenájdený: %s"
+
+#: ex_cmds2.c:414
+msgid "No breakpoints defined"
+msgstr "Neboli definovné ¾iadne body preru¹enia"
+
+#: ex_cmds2.c:419
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s riadok %ld"
+
+#: ex_cmds2.c:625
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Ulo¾i» zmeny do \"%.*s\"?"
+
+#: ex_cmds2.c:627 ex_docmd.c:8667
+msgid "Untitled"
+msgstr "Bez mena"
+
+#: ex_cmds2.c:763
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Buffer \"%s\" obsahuje neulo¾ené zmeny"
+
+#: ex_cmds2.c:832
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "Varovanie: Neèakaný vstup do iného bufferu (skontrolujte automatické príkazy)"
+
+#: ex_cmds2.c:1208
+msgid "E163: There is only one file to edit"
+msgstr "E163: Pre úpravu bol zadaný iba jeden súbor"
+
+#: ex_cmds2.c:1210
+msgid "E164: Cannot go before first file"
+msgstr "E164: Pred prvý súbor sa nedá preskoèi»"
+
+#: ex_cmds2.c:1212
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Za posledný súbor sa nedá preskoèi»"
+
+#: ex_cmds2.c:1634
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Hµadám \"%s\" v \"%s\""
+
+#: ex_cmds2.c:1656
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Hµadám \"%s\""
+
+#: ex_cmds2.c:1680
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "súbor \"%s\" nebol nájdený v 'runtimepath'"
+
+#: ex_cmds2.c:1714
+msgid "Source Vim script"
+msgstr "Zdrojový skript Vim"
+
+#: ex_cmds2.c:1832
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "\"%s\" nie je adresárom"
+
+#: ex_cmds2.c:1862
+#, c-format
+msgid "could not source \"%s\""
+msgstr "nedá sa interpretova» \"%s\""
+
+#: ex_cmds2.c:1864
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "riadok %ld: nemô¾e by» zdroj \"%s\""
+
+#: ex_cmds2.c:1878
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "interpretujem \"%s\""
+
+#: ex_cmds2.c:1880
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "riadok %ld je zdrojom \"%s\""
+
+#: ex_cmds2.c:1986
+#, c-format
+msgid "finished sourcing %s"
+msgstr "dokonèená interpretácia %s"
+
+#: ex_cmds2.c:2287
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Varovanie: chybný oddeµovaè riadkov. Mo¾ná chýba ^M."
+
+#: ex_cmds2.c:2336
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :finish pou¾ité mimo interpretovaný súbor"
+
+#: ex_cmds2.c:2369
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish pou¾ité mimo interpretovaný súbor"
+
+#: ex_cmds2.c:2838
+msgid "No text to be printed"
+msgstr "Ïal¹í na tlaè"
+
+#: ex_cmds2.c:2916
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "Tlaèím stranu %d (%d%%)"
+
+#: ex_cmds2.c:2925
+#, c-format
+msgid " Copy %d of %d"
+msgstr "Kópia %d z %d"
+
+#: ex_cmds2.c:2977
+#, c-format
+msgid "Printed: %s"
+msgstr "Vytlaèené: %s"
+
+#: ex_cmds2.c:2984
+msgid "Printing aborted"
+msgstr "Tlaè bola zru¹ená"
+
+#: ex_cmds2.c:3367
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Nedá sa zapisova» do výstupného PostScriptového súboru"
+
+#: ex_cmds2.c:4042
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Nedá sa otvori» výstupný PostScriptový súbor"
+
+#: ex_cmds2.c:4080
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Nedá sa otvori» súbor \"%s\""
+
+#: ex_cmds2.c:4091
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Nedá sa èíta» PostScriptový súbor \"%s\""
+
+#: ex_cmds2.c:4289
+msgid "Sending to printer..."
+msgstr "Posielam na tlaèiareò..."
+
+#: ex_cmds2.c:4293
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: PostScriptový súbor sa nepodarilo vytlaèi»"
+
+#: ex_cmds2.c:4295
+msgid "Print job sent."
+msgstr "Tlaèová úloha bola odoslaná."
+
+#: ex_cmds2.c:4691
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Aktuálny %s jazyk: \"%s\""
+
+#: ex_cmds2.c:4702
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Nedá sa nastavi» jazyk na \"%s\""
+
+#: ex_docmd.c:490
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Spú¹»am Ex re¾im. Napi¹te \"visual\" pre návrat do Normálního re¾imu."
+
+#. must be at EOF
+#: ex_docmd.c:526
+msgid "At end-of-file"
+msgstr "Koniec súboru"
+
+#: ex_docmd.c:601
+msgid "E169: Command too recursive"
+msgstr "E169: Príkaz je príli¹ zlo¾itý"
+
+#: ex_docmd.c:911
+msgid "E170: Missing :endwhile"
+msgstr "E170: Chýba :endwhile"
+
+#: ex_docmd.c:913
+msgid "E171: Missing :endif"
+msgstr "E171: Chýba :endif"
+
+#: ex_docmd.c:923
+msgid "End of sourced file"
+msgstr "Koniec zdrojového súboru"
+
+#: ex_docmd.c:924
+msgid "End of function"
+msgstr "Koniec funkcie"
+
+#: ex_docmd.c:1344
+msgid "Ambiguous use of user-defined command"
+msgstr "Nejednoznaèné pou¾itie pou¾ívateµom definovaného príkazu"
+
+#: ex_docmd.c:1358
+msgid "Not an editor command"
+msgstr "Nie je príkazom editoru"
+
+#: ex_docmd.c:1441
+msgid "Don't panic!"
+msgstr "®iadnu paniku!"
+
+#: ex_docmd.c:1460
+msgid "Backwards range given"
+msgstr "Zadaný spätný rozsah"
+
+#: ex_docmd.c:1469
+msgid "Backwards range given, OK to swap"
+msgstr "Zadaný spätný rozsah. OK odlo¾i»"
+
+#: ex_docmd.c:1580
+msgid "Use w or w>>"
+msgstr "Pou¾ite w èi w>>"
+
+#: ex_docmd.c:3097
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: ¥utujem, ale tento príkaz nie je implementovaný"
+
+#: ex_docmd.c:3267
+msgid "E172: Only one file name allowed"
+msgstr "E172: Prípustný je iba jeden názov súboru"
+
+#: ex_docmd.c:3823
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "E¹te zostávajú %d súborov k úprave. Chcete napriek tomu ukonèi» editor?"
+
+#: ex_docmd.c:3830
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: E¹te zostávajajú %ld súbory k úprave."
+
+#: ex_docmd.c:3924
+msgid "E174: Command already exists: use ! to redefine"
+msgstr "E174: Príkaz u¾ existuje: pou¾ite ! pre predefinovanie"
+
+#: ex_docmd.c:4029
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Meno Args Rozsah Úplnos» Definícia"
+
+#: ex_docmd.c:4118
+msgid "No user-defined commands found"
+msgstr "Neboli nájdené ¾iadne pou¾ivateµom definované príkazy"
+
+#: ex_docmd.c:4149
+msgid "E175: No attribute specified"
+msgstr "E175: Neboli zadané ¾iadne vlastnosti"
+
+#: ex_docmd.c:4201
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Chybný poèet argumentov"
+
+#: ex_docmd.c:4216
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: Poèet nemô¾e by» zadaný dvakrát"
+
+#: ex_docmd.c:4226
+msgid "E178: Invalid default value for count"
+msgstr "E178: Chybná implicitná hodnota pre poèet"
+
+#: ex_docmd.c:4254
+msgid "E179: argument required for complete"
+msgstr "E179: pre doplnenie je potrebný argument"
+
+#: ex_docmd.c:4273
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Chybná hodnota doplnenia: %s"
+
+#: ex_docmd.c:4281
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Chybná vlastnos»: %s"
+
+#: ex_docmd.c:4322
+msgid "E182: Invalid command name"
+msgstr "E182: Chybné meno príkazu"
+
+#: ex_docmd.c:4337
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: Pou¾ívateµom definované príkazy musia zaèína» veµkým písmenom"
+
+#: ex_docmd.c:4406
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: Pou¾ívateµom definovaný príkaz %s neexistuje"
+
+#: ex_docmd.c:4857
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Schéma farieb %s nenájdená"
+
+#: ex_docmd.c:4865
+msgid "Greetings, Vim user!"
+msgstr "Pozdraujem, Vim pou¾ívateµ!"
+
+#: ex_docmd.c:5569
+msgid "Edit File in new window"
+msgstr "Upravi» súbor v novom okne"
+
+#: ex_docmd.c:5839
+msgid "No swap file"
+msgstr "®iadny odkladací súbor"
+
+#: ex_docmd.c:5943
+msgid "Append File"
+msgstr "Pripoji» súbor"
+
+#: ex_docmd.c:6002
+msgid "E186: No previous directory"
+msgstr "E186: ®iadny predchádzajúci adresár"
+
+#: ex_docmd.c:6079
+msgid "E187: Unknown"
+msgstr "E187: Neznámy"
+
+#: ex_docmd.c:6197
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Umiestenie okna: X %d, Y %d"
+
+#: ex_docmd.c:6202
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: Na tejto platforme sa nedá umiestnenie okna zisti»"
+
+#: ex_docmd.c:6468
+msgid "Save Redirection"
+msgstr "Ulo¾i» presmerovanie"
+
+#: ex_docmd.c:6617
+msgid "Save View"
+msgstr "Ulo¾i» pohµad"
+
+#: ex_docmd.c:6618
+msgid "Save Session"
+msgstr "Ulo¾i» sedenie"
+
+#: ex_docmd.c:6620
+msgid "Save Setup"
+msgstr "Ulo¾i» nastavenie"
+
+#: ex_docmd.c:6769
+#, c-format
+msgid "E189: \"%s\" exists (use ! to override)"
+msgstr "E189: \"%s\" existuje (pou¾ite ! pre vynútenie)"
+
+#: ex_docmd.c:6774
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: Nedá sa otvori» \"%s\" pre zápis"
+
+#. set mark
+#: ex_docmd.c:6798
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: Argumentem mô¾e by» iba písiemo alebo pravý èi µavý apostrof"
+
+#: ex_docmd.c:6841
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Vnorenie :normal je príli¹ hlboké"
+
+#: ex_docmd.c:7202
+msgid ":if nesting too deep"
+msgstr "vnorenie :if je príli¹ hlboké"
+
+#: ex_docmd.c:7237
+msgid ":endif without :if"
+msgstr ":endif bez zodpovedajúceho :if"
+
+#: ex_docmd.c:7257
+msgid ":else without :if"
+msgstr ":else bez zodpovedajúceho :if"
+
+#: ex_docmd.c:7259
+msgid ":elseif without :if"
+msgstr ":elseif bez zodpovedajúceho :if"
+
+#: ex_docmd.c:7311
+msgid ":while nesting too deep"
+msgstr "vnorenie :while je príli¹ hlboké"
+
+#: ex_docmd.c:7357
+msgid ":continue without :while"
+msgstr ":continue bez zodpovedajúceho :while"
+
+#: ex_docmd.c:7384
+msgid ":break without :while"
+msgstr ":break bez zodpovedajúceho :while"
+
+#: ex_docmd.c:7407 ex_docmd.c:7412
+msgid ":endwhile without :while"
+msgstr ":endwhile bez zodpovedajúceho :while"
+
+#: ex_docmd.c:7433
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction mimo funkciu"
+
+#: ex_docmd.c:7613
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: ®iadny alternatívny názov súboru, ktorým by bolo mo¾né nahradi» '#'"
+
+#: ex_docmd.c:7644
+msgid "no autocommand file name to substitute for \"<afile>\""
+msgstr "¾iadny názov súboru, ktorým by bolo mo¾né nahradi» \"<afile>\""
+
+#: ex_docmd.c:7652
+msgid "no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "¾iadne èíslo bufferu, ktorým by bolo mo¾né nahradi» \"<abuf>\""
+
+#: ex_docmd.c:7663
+msgid "no autocommand match name to substitute for \"<amatch>\""
+msgstr ""
+"¾iadna zhoda automatických príkazov, ktorou by bolo mo¾né nahradi» \"<amatch>"
+"\""
+
+#: ex_docmd.c:7673
+msgid "no :source file name to substitute for \"<sfile>\""
+msgstr "¾iadny :source súbor, ktorým by bolo mo¾né nahradi» \"<sfile>\""
+
+#: ex_docmd.c:7714
+#, no-c-format
+msgid "Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "Prázdný názov súboru pre '%' èi '#' funguje iba s \":p:h\""
+
+#: ex_docmd.c:7716
+msgid "Evaluates to an empty string"
+msgstr "Výsledkom vyhodnotenia je prázdny re»azec"
+
+#: ex_docmd.c:8649
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: Nedá sa otvori» pre èítaní viminfo súbor"
+
+#: ex_docmd.c:8822
+msgid "E196: No digraphs in this version"
+msgstr "E196: V tejto verzi nie sú diagraphy podporované"
+
+#: ex_getln.c:2833
+msgid "tagname"
+msgstr "meno tagu"
+
+#: ex_getln.c:2836
+msgid " kind file\n"
+msgstr " typ súboru\n"
+
+#: ex_getln.c:4049
+msgid "'history' option is zero"
+msgstr "'voµba 'history' je nastavená na nulu"
+
+#: ex_getln.c:4289
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# História %s (zaèínajúci najnov¹ou polo¾kou):\n"
+
+#: ex_getln.c:4290
+msgid "Command Line"
+msgstr "Príkazové Riadky"
+
+#: ex_getln.c:4291
+msgid "Search String"
+msgstr "Vyhµadávaný Re»azec"
+
+#: ex_getln.c:4292
+msgid "Expression"
+msgstr "Výraz"
+
+#: ex_getln.c:4293
+msgid "Input Line"
+msgstr "Vstupný Riadok"
+
+#: ex_getln.c:4323
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar prevy¹uje då¾ku príkazu"
+
+#: ex_getln.c:4491
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Aktívne okno alebo buffer bol vymazaný"
+
+#: fileio.c:351
+msgid "Illegal file name"
+msgstr "Neprístupný názov súboru"
+
+#: fileio.c:375 fileio.c:500 fileio.c:2516 fileio.c:2554
+msgid "is a directory"
+msgstr "je adresárom"
+
+#: fileio.c:377
+msgid "is not a file"
+msgstr "nie je súborom"
+
+#: fileio.c:522 fileio.c:3646
+msgid "[New File]"
+msgstr "[nový súbor]"
+
+#: fileio.c:540
+msgid "[Permission Denied]"
+msgstr "[prístup odmietnutý]"
+
+#: fileio.c:634
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre automatické príkazy urobili súbor neèitateµným"
+
+#: fileio.c:636
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *ReadPre automatické príkazy nesmú meni» aktuálny buffer"
+
+#: fileio.c:657
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: èítam z ¹tandardného vstupu...\n"
+
+#: fileio.c:663
+msgid "Reading from stdin..."
+msgstr "Èítam z ¹tandardného vstupu..."
+
+#. Re-opening the original file failed!
+#: fileio.c:892
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: Po konverzii je súbor neèittateµný!"
+
+#: fileio.c:1755
+msgid "[fifo/socket]"
+msgstr "[fpomenovaná rúra/soket]"
+
+#: fileio.c:1762
+msgid "[fifo]"
+msgstr "[pomenovaná rúra]"
+
+#: fileio.c:1769
+msgid "[socket]"
+msgstr "[soket]"
+
+#: fileio.c:1777
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:1787
+msgid "[CR missing]"
+msgstr "[chýba CR]"
+
+#: fileio.c:1792
+msgid "[NL found]"
+msgstr "[nájdené NL]"
+
+#: fileio.c:1797
+msgid "[long lines split]"
+msgstr "[dlhé riadky zalomené]"
+
+#: fileio.c:1803 fileio.c:3630
+msgid "[NOT converted]"
+msgstr "[neskonvertovaný]"
+
+#: fileio.c:1808 fileio.c:3635
+msgid "[converted]"
+msgstr "[skonvertovaný]"
+
+#: fileio.c:1815 fileio.c:3660
+msgid "[crypted]"
+msgstr "[za¹ifrovaný]"
+
+#: fileio.c:1822
+msgid "[CONVERSION ERROR]"
+msgstr "[CHYBA PREVODU]"
+
+#: fileio.c:1829
+msgid "[READ ERRORS]"
+msgstr "[CHYBY ÈÍTANIA]"
+
+#: fileio.c:2036
+msgid "Can't find temp file for conversion"
+msgstr "Nedá sa nájs» doèasný súbor pre konverziu"
+
+#: fileio.c:2043
+msgid "Conversion with 'charconvert' failed"
+msgstr "Konverzia s 'charconvert' sa nepodarila"
+
+#: fileio.c:2046
+msgid "can't read output of 'charconvert'"
+msgstr "nedá sa èíta» výstup 'charconvert'"
+
+#: fileio.c:2432
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr ""
+"E203: Automatické príkazy zmazali èi deaktivovali buffer, ktorý mal by» "
+"ulo¾ený"
+
+#: fileio.c:2455
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Automatický príkaz neoèakávaným spôsobom zmenil poèet riadkov"
+
+#: fileio.c:2521 fileio.c:2538
+msgid "is not a file or writable device"
+msgstr "nie je súborom ani zariadením na ktoré sa dá zapisova»"
+
+#: fileio.c:2584
+msgid "is read-only (use ! to override)"
+msgstr "je iba pre èítaníie(pou¾ite ! pre vynútenie)"
+
+#: fileio.c:2886
+msgid "Can't write to backup file (use ! to override)"
+msgstr "Nedá sa zapisova» do zálo¾ného súboru (pou¾ite ! pre vynútenie)"
+
+#: fileio.c:2898
+msgid "Close error for backup file (use ! to override)"
+msgstr "Chyba pri uzatváraní zálo¾ného súboru (pou¾ite ! pre vynútenie)"
+
+#: fileio.c:2900
+msgid "Can't read file for backup (use ! to override)"
+msgstr "Nedá sa naèíta» súbor pre zálohu (pou¾ite ! pre vynútenie)"
+
+#: fileio.c:2916
+msgid "Cannot create backup file (use ! to override)"
+msgstr "Nedá sa vytvori» zálo¾ný súbor (pou¾ite ! pre vynútenie)"
+
+#: fileio.c:3018
+msgid "Can't make backup file (use ! to override)"
+msgstr "Nedá sa vytvori» zálo¾ný súbor (pou¾ite ! pre vynútenie)"
+
+# resource fork ?!
+#: fileio.c:3080
+msgid "The resource fork will be lost (use ! to override)"
+msgstr "'Resource fork' bude stratený (pou¾ite ! pre vynútenie)"
+
+#: fileio.c:3169
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: Nedá sa nájs» doèasný súbor pre ukladanie"
+
+#: fileio.c:3187
+msgid "E213: Cannot convert (use ! to write without conversion)"
+msgstr "E213: Nedá sa previes» (pou¾ite ! pre vynútenie prevodu)"
+
+#: fileio.c:3222
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Súbor sa nedá otvori» pre ukladanie"
+
+#: fileio.c:3226
+msgid "E212: Can't open file for writing"
+msgstr "E212: Súbor sa nedá otvori» pre ukladanie"
+
+#: fileio.c:3475
+msgid "Close failed"
+msgstr "Zatvorenie zlyhalo"
+
+#: fileio.c:3546
+msgid "write error, conversion failed"
+msgstr "chyba pri zápise, prevod sa nepodaril"
+
+#: fileio.c:3552
+msgid "write error (file system full?)"
+msgstr "chyba pri ukladaní (je voµné miesto na disku?)"
+
+#: fileio.c:3625
+msgid " CONVERSION ERROR"
+msgstr " CHYBA PREVODU"
+
+#: fileio.c:3641
+msgid "[Device]"
+msgstr "[zariadenie]"
+
+#: fileio.c:3646
+msgid "[New]"
+msgstr "[nový]"
+
+#: fileio.c:3668
+msgid " [a]"
+msgstr " [p]"
+
+#: fileio.c:3668
+msgid " appended"
+msgstr " pripojený"
+
+#: fileio.c:3670
+msgid " [w]"
+msgstr " [u]"
+
+#: fileio.c:3670
+msgid " written"
+msgstr " ulo¾ený"
+
+#: fileio.c:3720
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: patchmode: nedá sa ulo¾i» pôvodný súbor"
+
+#: fileio.c:3742
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchmode: nedá sa zapisova» do prázdneho pôvodného súboru"
+
+#: fileio.c:3757
+msgid "E207: Can't delete backup file"
+msgstr "E207: Nedá sa vymaza» zálo¾ný súbor"
+
+#: fileio.c:3809
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"VAROVANIE: Obsah pôvodného súboru mô¾e by» stratený alebo po¹kodený\n"
+
+#: fileio.c:3811
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "neukonèujte editor skôr, ne¾ bude súbor úspe¹ne ulo¾ený!"
+
+#: fileio.c:3891
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:3891
+msgid "[dos format]"
+msgstr "[dos formát]"
+
+#: fileio.c:3898
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:3898
+msgid "[mac format]"
+msgstr "[mac formát]"
+
+#: fileio.c:3905
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:3905
+msgid "[unix format]"
+msgstr "[unix formát]"
+
+#: fileio.c:3932
+msgid "1 line, "
+msgstr "1 riadok, "
+
+#: fileio.c:3934
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld riadkov, "
+
+#: fileio.c:3937
+msgid "1 character"
+msgstr "1 znak"
+
+#: fileio.c:3939
+#, c-format
+msgid "%ld characters"
+msgstr "%ld znakov"
+
+#: fileio.c:3949
+msgid "[noeol]"
+msgstr "[¾iadny koniec riadku]"
+
+#: fileio.c:3949
+msgid "[Incomplete last line]"
+msgstr "[neúplný posledný riadok]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:3968
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "VAROVANIE: od jeho naèítania bol obsah súboru zmenený!!!!"
+
+#: fileio.c:3970
+msgid "Do you really want to write to it"
+msgstr "Chcete ho naozaj ulo¾i»"
+
+#: fileio.c:4933
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Chyba pri zápise do \"%s\""
+
+#: fileio.c:4940
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Chyb pri uzatváraní \"%s\""
+
+#: fileio.c:4943
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Chyba pri èítaní \"%s\""
+
+#: fileio.c:5115
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: FileChangedShell automatický príkaz vymazal buffer"
+
+#: fileio.c:5123
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: Varovanie: súbor \"%s\" u¾ nie je dostupný"
+
+#: fileio.c:5136
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: Varovanie: súbor \"%s\" bol po zaèatí úpravy zmenený a Vim tie¾ zmenil "
+"buffer"
+
+#: fileio.c:5139
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: Varovanie: súbor \"%s\" bol po zaèatí úpravy zmenený"
+
+#: fileio.c:5141
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: Varovanie: Re¾im súboru \"%s\" bol po zaèatí úprav zmenený"
+
+#: fileio.c:5151
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: Varovanie: po zaèatí úpravy vytvorený súbor \"%s\""
+
+#: fileio.c:5168
+msgid "Warning"
+msgstr "Varovanie"
+
+#: fileio.c:5169
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Naèíta» súbor"
+
+#: fileio.c:5248
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: nedá sa obnovi» \"%s\""
+
+#: fileio.c:5779
+msgid "--Deleted--"
+msgstr "--Vymazaný--"
+
+#. the group doesn't exist
+#: fileio.c:5939
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Skupina \"%s\" neexistuje"
+
+#: fileio.c:6064
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Neprístupný znak po *: %s"
+
+#: fileio.c:6075
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Udalos» %s neexistuje"
+
+#. Highlight title
+#: fileio.c:6224
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Automatické príkazy ---"
+
+#: fileio.c:6495
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Automatické príkazy sa nedajú spusti» pre V©ETKY udalos»i"
+
+#: fileio.c:6518
+msgid "No matching autocommands"
+msgstr "®iadne vyhovujúce automatické príkazy"
+
+#: fileio.c:6790
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: vnorenia automatického príkazu sú príli¹ hlboké"
+
+#: fileio.c:7077
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s automatické príkazy pre \"%s\""
+
+#: fileio.c:7085
+#, c-format
+msgid "Executing %s"
+msgstr "Spú¹»am %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7153
+#, c-format
+msgid "autocommand %s"
+msgstr "Automatický príkaz %s"
+
+#: fileio.c:7675
+msgid "E219: Missing {."
+msgstr "E219: Chýba {."
+
+#: fileio.c:7677
+msgid "E220: Missing }."
+msgstr "E220: Chýba }."
+
+#: fold.c:66
+msgid "No fold found"
+msgstr "®iadny záhyb nebol nájdený"
+
+#: fold.c:553
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: Pomocou 'foldmethod' sa nedá vytvori» záhyb"
+
+#: fold.c:555
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: Pomocou 'foldmethod' sa nedá odstráni» záhyb"
+
+#: getchar.c:247
+msgid "E222: Add to read buffer"
+msgstr "E222: Prida» do bufferu pre èítanie"
+
+#: getchar.c:2106
+msgid "E223: recursive mapping"
+msgstr "E223: rekurzívne mapovanie"
+
+#: getchar.c:2948
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: pre %s u¾ globálna skratka existuje"
+
+#: getchar.c:2951
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: pre %s u¾ globálne mapovanie existuje"
+
+#: getchar.c:3078
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: pre %s u¾ skratka existuje"
+
+#: getchar.c:3081
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: pre %s u¾ mapovanie existuje"
+
+#: getchar.c:3145
+msgid "No abbreviation found"
+msgstr "®iadna skratka nebola nájdená"
+
+#: getchar.c:3147
+msgid "No mapping found"
+msgstr "®iadne mapovanie nebolo nájdené"
+
+#: getchar.c:3992
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: neprístupný mód"
+
+#: gui_at_fs.c:290
+msgid "<cannot open> "
+msgstr "<nedá sa otvori»> "
+
+#: gui_at_fs.c:1115
+#, c-format
+msgid "vim_SelFile: can't get font %s"
+msgstr "vim_SelFile: písmo %s nie je dostupné"
+
+#: gui_at_fs.c:2538
+msgid "vim_SelFile: can't return to current directory"
+msgstr "vim_SelFile: nedá sa vráti» do aktuálneho adresára"
+
+#: gui_at_fs.c:2557
+msgid "Pathname:"
+msgstr "Názov cesty:"
+
+#: gui_at_fs.c:2563
+msgid "vim_SelFile: can't get current directory"
+msgstr "vim_SelFile: nedá sa zisti» aktuálny adresár"
+
+#: gui_at_fs.c:2571 gui_motif.c:1619
+msgid "OK"
+msgstr "OK"
+
+#. 'Cancel' button
+#: gui_at_fs.c:2571 gui_gtk.c:1740 gui_motif.c:1614 gui_motif.c:2835
+msgid "Cancel"
+msgstr "Zru¹i»"
+
+#: gui_athena.c:1956 gui_motif.c:1867
+msgid "Vim dialog"
+msgstr "Vim dialóg"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Prípravok posuvnej li¹ty: nedá sa zisti» geometria obrázku"
+
+#: gui_beval.c:68
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: BalloonEval nedá sa vytvori» správou a zároveò spätným volaním"
+
+#: gui.c:203
+msgid "E229: Cannot start the GUI"
+msgstr "E229: Nedá sa spusti» GUI"
+
+#: gui.c:328
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Nedá sa èíta» z \"%s\""
+
+#: gui.c:453
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: voµba 'guifontwide' je chybne nastavená"
+
+#: gui.c:3698
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: Nedá sa alokova» farba %s"
+
+#: gui.c:3983
+msgid "Error"
+msgstr "Chyba"
+
+#: gui_gtk.c:1190
+msgid "Vim dialog..."
+msgstr "Vim dialóg.."
+
+#: gui_gtk.c:1576 gui_motif.c:2754
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Nájs» a nahradi»..."
+
+#: gui_gtk.c:1581 gui_motif.c:2756
+msgid "VIM - Search..."
+msgstr "VIM - Nájs»..."
+
+#: gui_gtk.c:1604 gui_motif.c:2874
+msgid "Find what:"
+msgstr "Vyhµada»:"
+
+#: gui_gtk.c:1622 gui_motif.c:2906
+msgid "Replace with:"
+msgstr "Nový text:"
+
+#. exact match only button
+#: gui_gtk.c:1654 gui_motif.c:3008
+msgid "Match exact word only"
+msgstr "Hµada» len celé slová"
+
+#: gui_gtk.c:1666 gui_motif.c:2976
+msgid "Direction"
+msgstr "Smer"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:1678 gui_motif.c:2988
+msgid "Up"
+msgstr "Hore"
+
+#: gui_gtk.c:1682 gui_motif.c:2996
+msgid "Down"
+msgstr "Dolu"
+
+#. 'Find Next' button
+#: gui_gtk.c:1704 gui_motif.c:2778
+msgid "Find Next"
+msgstr "Nájs» ïal¹ie"
+
+#. 'Replace' button
+#: gui_gtk.c:1721 gui_motif.c:2795
+msgid "Replace"
+msgstr "Nahradi»"
+
+#. 'Replace All' button
+#: gui_gtk.c:1730 gui_motif.c:2808
+msgid "Replace All"
+msgstr "Nahradi» V¹etko"
+
+#: gui_gtk_x11.c:1079 gui_x11.c:1199
+msgid "E233: cannot open display"
+msgstr "E233: nedá sa otvori» displej"
+
+#: gui_gtk_x11.c:2494 gui_x11.c:1999
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Neznáma sada písiem: %s"
+
+#: gui_gtk_x11.c:2518
+msgid "Font Selection"
+msgstr "Výber Písma"
+
+#: gui_gtk_x11.c:2764 gui_mac.c:2982 gui_w48.c:1197 gui_x11.c:1835
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Neznáme písmo: %s"
+
+#: gui_gtk_x11.c:2775 gui_x11.c:1859
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: Písmo \"%s\" nemá pevnú ¹írku"
+
+#: gui_gtk_x11.c:3580 ui.c:1971
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "Pou¾itý CUT_BUFFER0 namiesto prázdneho výberu"
+
+#: gui_motif.c:1613 gui_motif.c:1616
+msgid "Filter"
+msgstr "Filter"
+
+#: gui_motif.c:1615
+msgid "Directories"
+msgstr "Adresáre"
+
+#: gui_motif.c:1617
+msgid "Help"
+msgstr "Pomocník"
+
+#: gui_motif.c:1618
+msgid "Files"
+msgstr "Súbory"
+
+#: gui_motif.c:1620
+msgid "Selection"
+msgstr "Výber"
+
+#: gui_motif.c:2821
+msgid "Undo"
+msgstr "Spä»"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E235: Can't load Zap font '%s'"
+msgstr "E235: Nemô¾em naèíta» chybný font '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E235: Can't use font %s"
+msgstr "E235: Nedá sa pou¾í» písmo %s"
+
+#: gui_riscos.c:3269
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Posielam správu na ukonèenie synovského procesu.\n"
+
+#: gui_w32.c:836
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr ""
+"E243: Argument nie je podporovaný: \n"
+"-%s\"; Pou¾ite OLE verziu."
+
+#. TODO: May be changed this message
+#: gui_w32.c:3499 gui_w32.c:3532 gui_x11.c:3252
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Chyba -- nedájú sa preèíta» oznaèovacie dáta!"
+
+#: gui_w48.c:2081
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Nájs» re»azec (pou¾ite '\\\\' ak chete nájs» '\\')"
+
+#: gui_w48.c:2106
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Nájs» a Nahradi» (pou¾ite '\\\\' ak chcete nájs» '\\')"
+
+#: gui_x11.c:1419
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: Nedá sa alokova» polo¾ka mapy farieb. Niektoré farby mô¾u by» "
+"nesprávne"
+
+#: gui_x11.c:1989
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: Chýba písmo pre nasledujúce znakové sady %s:"
+
+#: gui_x11.c:2032
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Názov sady písiem: %s"
+
+#: gui_x11.c:2033
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "Písmo '%s' nemá pevnou ¹írku"
+
+#: gui_x11.c:2052
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Názov sady písiem: %s\n"
+
+#: gui_x11.c:2053
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Písmo0: %s\n"
+
+#: gui_x11.c:2054
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Písmo1: %s\n"
+
+#: gui_x11.c:2055
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "Písmo%d nie je dvakrát ¹ir¹ie ako písmo0\n"
+
+#: gui_x11.c:2056
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "©írka písma0: %ld\n"
+
+#: gui_x11.c:2057
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"©írka písma1: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: Hangul automata ERROR"
+
+#: if_cscope.c:26
+#, c-format
+msgid "Usage: cs[cope] %s"
+msgstr "Pou¾itie: cs[cope] %s"
+
+#: if_cscope.c:67
+msgid "Add a new database"
+msgstr "Prida» novú databázu"
+
+#: if_cscope.c:69
+msgid "Query for a pattern"
+msgstr "Hµadanie vzoru"
+
+#: if_cscope.c:71
+msgid "Show this message"
+msgstr "Zobrazi» túto správu"
+
+#: if_cscope.c:73
+msgid "Kill a connection"
+msgstr "Ukonèi» spojenie"
+
+#: if_cscope.c:75
+msgid "Reinit all connections"
+msgstr "Znovu inicializova» v¹etky spojenia"
+
+#: if_cscope.c:77
+msgid "Show connections"
+msgstr "Zobrazi» spojenia"
+
+#: if_cscope.c:108
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Táto cscope príkaz nepodporuje rozdeµovanie okna.\n"
+
+#: if_cscope.c:143
+msgid "Usage: cstag <ident>"
+msgstr "Pou¾itie: cstag <odsadenie>"
+
+#: if_cscope.c:199
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: tag nenájdený"
+
+#: if_cscope.c:407 if_cscope.c:451
+#, c-format
+msgid "stat(%s) error: %d"
+msgstr "stat(%s) chyba: %d"
+
+#: if_cscope.c:460 if_cscope.c:467
+#, c-format
+msgid "Added cscope database %s"
+msgstr "Pridaná cscope databáza %s"
+
+#: if_cscope.c:474
+#, c-format
+msgid "%s is not a directory or a valid cscope database"
+msgstr "%s nie je ani adresárom ani správnou cscope databázou"
+
+#: if_cscope.c:557
+#, c-format
+msgid "error reading cscope connection %d"
+msgstr "chyba pri èítaní cscope spojenia %d"
+
+#: if_cscope.c:633
+msgid "unknown cscope search type"
+msgstr "neznámy typ cscope hµadania"
+
+#: if_cscope.c:680
+msgid "Could not create cscope pipes"
+msgstr "Nedajú sa vytvori» cscope rúry"
+
+#: if_cscope.c:745
+msgid "cs_create_connection exec failed"
+msgstr "spustenie cs_create_connection zlyhalo"
+
+#: if_cscope.c:755
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: volanie fdopen pre to_fp zlyhalo"
+
+#: if_cscope.c:757
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: volanie fdopen pre fr_fp zlyhalo"
+
+#: if_cscope.c:785
+msgid "no cscope connections"
+msgstr "¾iadne cscope spojenia"
+
+#: if_cscope.c:855
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: cscope hµadanie %s vo vzore %s nena¹lo ¾iadnu zhodu"
+
+#: if_cscope.c:899
+msgid "cscope commands:\n"
+msgstr "príkazy cscope:\n"
+
+#: if_cscope.c:902
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)\n"
+msgstr "%-5s: %-30s (Pou¾itie: %s)\n"
+
+#: if_cscope.c:970
+msgid "duplicate cscope database not added"
+msgstr "duplicitná cscope databáza nebola pridaná"
+
+#: if_cscope.c:981
+msgid "maximum number of cscope connections reached"
+msgstr "dosiahnutý maximálny poèet cscope spojení"
+
+#: if_cscope.c:1102
+msgid "E260: cscope connection not found"
+msgstr "E260: cscope spojenie nenájdené"
+
+#: if_cscope.c:1105
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: cscope spojenie %s nenájdené"
+
+#: if_cscope.c:1141
+msgid "cscope connection closed"
+msgstr "cscope spojenie ukonèené"
+
+#: if_cscope.c:1149
+#, c-format
+msgid "cscope connection %s closed\n"
+msgstr "cscope spojenie %s ukonèené\n"
+
+#. should not reach here
+#: if_cscope.c:1290
+msgid "fatal error in cs_manage_matches"
+msgstr "osudová chyba v cs_manage_matches"
+
+#: if_cscope.c:1341
+#, c-format
+msgid "E262: error reading cscope connection %d"
+msgstr "E262: chyba pri èítaní cscope spojenia %d"
+
+#: if_cscope.c:1449
+msgid "couldn't malloc\n"
+msgstr "volanie malloc zlyhalo\n"
+
+#: if_cscope.c:1454
+#, c-format
+msgid "Cscope tag: %s\n"
+msgstr "Cscope tag: %s\n"
+
+#: if_cscope.c:1458
+msgid " # line"
+msgstr " # riadok"
+
+#: if_cscope.c:1460
+msgid "filename / context / line\n"
+msgstr "názov súboru/ kontext/ riadok\n"
+
+#: if_cscope.c:1718
+msgid "All cscope databases reset"
+msgstr "V¹etky cscope databáze resetované"
+
+#: if_cscope.c:1785
+msgid "no cscope connections\n"
+msgstr "¾iadne cscope spojenia\n"
+
+#: if_cscope.c:1789
+msgid " # pid database name prepend path\n"
+msgstr " # pid názov databáze predpona cesty\n"
+
+#: if_cscope.c:1800
+#, c-format
+msgid "%2d %-5ld %-34s <none>\n"
+msgstr "%2d %-5ld %-34s <¾iadny>\n"
+
+#: if_python.c:255 if_ruby.c:260 if_tcl.c:195 mbyte.c:2629 os_win32.c:269
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: Nepodarilo sa nahra» kni¾nicu %s"
+
+#: if_python.c:267 if_ruby.c:272 if_tcl.c:206 mbyte.c:2645 os_win32.c:281
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: Nepodarilo sa nahra» funkciu kni¾nice %s"
+
+#: if_python.c:392
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr "E262: Prepáète, tento príkaz je vypnutý, Python kni¾nica nemô¾e by»naèítaná."
+
+#: if_python.c:592
+msgid "can't delete OutputObject attributes"
+msgstr "nedá sa vymaza» vlastnos» OutputObject"
+
+#: if_python.c:599
+msgid "softspace must be an integer"
+msgstr "softspace musí by» kladné celé èíslo"
+
+#: if_python.c:607
+msgid "invalid attribute"
+msgstr "chybná vlastnos»"
+
+#: if_python.c:646 if_python.c:660
+msgid "writelines() requires list of strings"
+msgstr "writelines() vy¾aduje zoznam re»azcov"
+
+#: if_python.c:786
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: Chyba pri inicializácii I/O objektov"
+
+#: if_python.c:971 if_tcl.c:1403
+msgid "invalid expression"
+msgstr "chybný výraz"
+
+#: if_python.c:985 if_tcl.c:1408
+msgid "expressions disabled at compile time"
+msgstr "podpora výrazov bola vypnutá pri preklade programu"
+
+#: if_python.c:998
+msgid "attempt to refer to deleted buffer"
+msgstr "pokus o odkaz na vymazaný buffer"
+
+#: if_python.c:1013 if_python.c:1054 if_python.c:1118 if_tcl.c:1215
+msgid "line number out of range"
+msgstr "èíslo riadka mimo rozsah"
+
+#: if_python.c:1251
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<objekt bufferu (vymazaný) na %8lX>"
+
+#: if_python.c:1342 if_tcl.c:837
+msgid "invalid mark name"
+msgstr "chybné meno znaèky"
+
+#: if_python.c:1617
+msgid "no such buffer"
+msgstr "¾iadny taký buffer"
+
+#: if_python.c:1705
+msgid "attempt to refer to deleted window"
+msgstr "pokus o odkaz na vymazané okno"
+
+#: if_python.c:1750
+msgid "readonly attribute"
+msgstr "vlastnos» iba pre èítanie"
+
+#: if_python.c:1763
+msgid "cursor position outside buffer"
+msgstr "umiestnenie kurzoru mimo buffer"
+
+#: if_python.c:1840
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<objekt okna (vymazaný) na %.8lX>"
+
+#: if_python.c:1852
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<objekt okna (neznámy) na %.8lX>"
+
+#: if_python.c:1854
+#, c-format
+msgid "<window %d>"
+msgstr "<okno %d>"
+
+#: if_python.c:1930
+msgid "no such window"
+msgstr "¾iadne také okno"
+
+#: if_python.c:2187 if_python.c:2222 if_python.c:2272 if_python.c:2335
+#: if_python.c:2455 if_python.c:2507 if_tcl.c:685 if_tcl.c:730 if_tcl.c:804
+#: if_tcl.c:874 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "nedajú sa ulo¾i» spätné informácie"
+
+#: if_python.c:2189 if_python.c:2279 if_python.c:2346
+msgid "cannot delete line"
+msgstr "nedá sa vymaza» riadok"
+
+#: if_python.c:2224 if_python.c:2362 if_tcl.c:691 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "nedá sa nahradi» riadok"
+
+#: if_python.c:2378 if_python.c:2457 if_python.c:2515
+msgid "cannot insert line"
+msgstr "nedá sa vlo¾i» riadok"
+
+#: if_python.c:2619
+msgid "string cannot contain newlines"
+msgstr "re»azec nesmie obsahova» znaky nového riadku"
+
+#: if_ruby.c:401
+msgid "E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr "E266: Prepáète, tento príkaz je vypnutý, Ruby kni¾nica nemô¾e by» naèítaná."
+
+#: if_ruby.c:464
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: Neznámy 'longjmp' stav %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Prepnú» implementáciu/definíciu"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Ukáza» základnú triedu"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Ukáza» pre»a¾enú èlenskú funkciu"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Obnovi» zo súboru"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Obnovi» z projektu"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Obnovi» zo v¹etkých projektov"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Obnovi»"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Ukáza» zdroj"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Nájs» znak"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Prezrie» triedu"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Ukáza» triedu v hierarchii"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Ukáza» triedu v obmedzenej hierarchii"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref odkazuje na"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref odkázaný z"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref má"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref pou¾itý"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Ukáza» dokumentáciu"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Vytvori» dokumentáciu pre"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"Zlihalo pripojenie na SNiFF+, Preverte prostredie (sniffemacs sa musí "
+"nachádza» v $PATH).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Chyba poèas èítania. Odpojené"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ je aktuálne "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "ne"
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "pripojený"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Neznáma SNiFF+ po¾iadavka: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Chyba pripojenia na SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ nie je pripojený"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Nie je SNiFF+ bufferom"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: Chyba zápisu. Odpojené"
+
+#: if_tcl.c:419
+msgid "invalid buffer number"
+msgstr "chybné èíslo bufferu"
+
+#: if_tcl.c:465 if_tcl.c:932 if_tcl.c:1111
+msgid "not implemented yet"
+msgstr "nie je e¹te podporované"
+
+#: if_tcl.c:502
+msgid "unknown option"
+msgstr "neznáma voµba"
+
+#. ???
+#: if_tcl.c:775
+msgid "cannot set line(s)"
+msgstr "nedajú sa nastavi» riadky"
+
+#: if_tcl.c:846
+msgid "mark not set"
+msgstr "znaèka nie je nastavená"
+
+#: if_tcl.c:852 if_tcl.c:1067
+#, c-format
+msgid "row %d column %d"
+msgstr "riadok %d ståpec %d"
+
+#: if_tcl.c:882
+msgid "cannot insert/append line"
+msgstr "nedá sa vlo¾i»/pripoji» riadok"
+
+#: if_tcl.c:1269
+msgid "unknown flag: "
+msgstr "neznámy príznak: "
+
+#: if_tcl.c:1339
+msgid "unknown vimOption"
+msgstr "neznáma vimMo¾nos»"
+
+#: if_tcl.c:1424
+msgid "keyboard interrupt"
+msgstr "preru¹enie z klávesnice"
+
+#: if_tcl.c:1429
+msgid "vim error"
+msgstr "chyba vim"
+
+#: if_tcl.c:1472
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "nedá sa vytvori» príkaz bufferu/okna: objekt vymazaný"
+
+#: if_tcl.c:1546
+msgid "cannot register callback command: buffer/window is already being deleted"
+msgstr "nedá sa zaregistrova» príkaz spätného volania: buffer/okno u¾ bol vymazaný"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1563
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: TCL FATAL ERROR: reflist po¹kodený!? Oznámte, prosím, túto chybu na "
+"vim-dev@vim.org"
+
+#: if_tcl.c:1564
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr "nedá sa zaregistrova» príkaz spätného volania: odkaz na buffer/okno nenájdený"
+
+#: if_tcl.c:1725
+msgid "Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr "Prepáète, tento príkaz je vypnutý, Tcl kni¾nica nemô¾e by» naèítaná."
+
+#: if_tcl.c:1887
+msgid "E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: TCL CHYBA: návratový kód nie je celé èíslo!? Oznamte, presím, tuto "
+"chybu na vim-dev@vim.org"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "nedá sa preèíta» riadok"
+
+#: if_xcmdsrv.c:213
+msgid "Unable to register a command server name"
+msgstr "Nemô¾em zaregistrova» meno príkazového servra"
+
+#: if_xcmdsrv.c:434 os_mswin.c:2108
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: meno registrovaného servra \"%s\" neexistuje"
+
+#: if_xcmdsrv.c:463
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Chyba poèas prenosu príkazu do cieµového programu"
+
+#: if_xcmdsrv.c:732
+#, c-format
+msgid "Invalid server id used: %s"
+msgstr "Pou¾íté chybné id servra: %s"
+
+#: if_xcmdsrv.c:1079
+msgid "E249: couldn't read VIM instance registry property"
+msgstr "E249: nemô¾em èíta» VIM registrovú vlastnos»"
+
+#: if_xcmdsrv.c:1090
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: VIM registrová ¾iados» je zle formulovaná. Vymazané!"
+
+#: main.c:53 option.c:3162 option.c:3269
+msgid "Unknown option"
+msgstr "Neznáma voµba"
+
+#: main.c:55
+msgid "Too many edit arguments"
+msgstr "Príli¹ mnoho upravovacích argumentov"
+
+#: main.c:57
+msgid "Argument missing after"
+msgstr "Chýba argument po"
+
+#: main.c:59
+msgid "Garbage after option"
+msgstr "Chyby za voµbou"
+
+#: main.c:61
+msgid "Too many \"+command\" or \"-c command\" arguments"
+msgstr "Príli¹ mnoho \"+príkaz\" èi \"-c príkaz\" argumentov"
+
+#: main.c:63
+msgid "Invalid argument for"
+msgstr "Chybný argument pre"
+
+#: main.c:450
+msgid "This Vim was not compiled with the diff feature."
+msgstr "Tento Vim nebol kompilovaný s porovnávacími funkciami."
+
+#: main.c:875
+msgid "Attempt to open script file again: \""
+msgstr "Pokus o opätovné otvorenie skriptu: \""
+
+#: main.c:879 main.c:886 main.c:930 memline.c:3673 memline.c:3677
+#: version.c:892 version.c:897 version.c:902 version.c:907 version.c:912
+#: version.c:917 version.c:923 version.c:927 version.c:931 version.c:936
+#: version.c:943 version.c:951 version.c:957
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:884
+msgid "Cannot open for reading: \""
+msgstr "Nedá sa otvori» pre zápis: \""
+
+#: main.c:928
+msgid "Cannot open for script output: \""
+msgstr "Nedá sa otvori» pre výstup skriptu: \""
+
+#: main.c:1044
+#, c-format
+msgid "%d files to edit\n"
+msgstr "poèet súborov pre úpravu: %d\n"
+
+#: main.c:1118
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Varovanie: Výstup nesmeruje na terminál\n"
+
+#: main.c:1120
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Varovanie: Vstup nepochádza z terminálu\n"
+
+#. just in case..
+#: main.c:1195
+msgid "pre-vimrc command line"
+msgstr "pre-vimrc príkazový riadok"
+
+#: main.c:1230
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Nedá sa èíta» z \"%s\""
+
+#: main.c:2205
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Podrobnej¹ie informácie získáte pomocou \"vim -h\"\n"
+
+#: main.c:2238
+msgid "[file ..] edit specified file(s)"
+msgstr "[súbor ..] .. upravi» súbor(y)"
+
+#: main.c:2239
+msgid "- read text from stdin"
+msgstr "- èíta» text z ¹tandardného vstupu"
+
+#: main.c:2240
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tag upravi» súbor na mieste definície tagu"
+
+#: main.c:2242
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [chybový súbor] upravi» súbor na mieste výskytu prvej chyby"
+
+#: main.c:2251
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"pou¾itie:"
+
+#: main.c:2254
+msgid " vim [arguments] "
+msgstr "vim [argumenty] "
+
+#: main.c:2258
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" alebo"
+
+#: main.c:2261
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Argumenty:\n"
+
+#: main.c:2262
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tMô¾u nasledova» iba názvy súborov"
+
+#: main.c:2264
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tnepodarilo sa expandova» ¾olíkové znaky (wildcards)"
+
+#: main.c:2267
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tprihlási» gvim na OLE"
+
+#: main.c:2268
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-register\t\todhlási» gvim z OLE"
+
+#: main.c:2271
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tspusti» v GUI móde (rovnaké ako \"gvim\")"
+
+#: main.c:2272
+msgid "-f\t\t\tForeground: Don't fork when starting GUI"
+msgstr "-f\t\t\tPopredie: pri spustení GUI sa neoddelí od shellu"
+
+#: main.c:2274
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi mód (rovnaké ako \"vi\")"
+
+#: main.c:2275
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx mód (rovnaké ako \"ex\")"
+
+#: main.c:2276
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tTichý (dávkový) mód (iba pre \"ex\")"
+
+#: main.c:2278
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tPorovnávací mód (rovnaké ako \"vimdiff\")"
+
+#: main.c:2280
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tJednoduchý mód (rovnaké ako \"evim\", modeless)"
+
+#: main.c:2281
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tMód iba_pre_èítanie (ako \"view\")"
+
+#: main.c:2282
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tObmedzený mód (rovnaké ako \"rvim\")"
+
+#: main.c:2283
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tZmeny (ukladanie súborov) zakázané"
+
+#: main.c:2284
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tZmeny v texte nie sú povolené"
+
+#: main.c:2285
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tBinárny mód"
+
+#: main.c:2287
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp mód"
+
+#: main.c:2289
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tKompatabilný s Vi: 'compatible'"
+
+#: main.c:2290
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tKompatibilita s Vi vypnutá: 'nocompatible'"
+
+#: main.c:2291
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tÚroveò výpisu hlá¹ok"
+
+#: main.c:2292
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tLadiaci mód"
+
+#: main.c:2293
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tNebude vytvára» odkladací súbor, bude pou¾íva» iba pamä»"
+
+#: main.c:2294
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tVypí¹e zoznam odkladacích súborov a skonèí"
+
+#: main.c:2295
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r názov súboru\tObnoví preru¹ené sedenie"
+
+#: main.c:2296
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tRovnaké ako -r"
+
+#: main.c:2298
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tNebude pou¾íva» newcli pre otvorenie okna"
+
+#: main.c:2299
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <zariadenie>\t\tPou¾i» <zariadenie> pre I/O"
+
+#: main.c:2302
+msgid "-H\t\t\tstart in Hebrew mode"
+msgstr "-H\t\t\tna spusteníe v hebrejskom móde"
+
+#: main.c:2305
+msgid "-F\t\t\tstart in Farsi mode"
+msgstr "-F\t\t\tna spusteníe vo Farsi móde"
+
+#: main.c:2307
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminál>\tNastaví typ terminálu na <terminál>"
+
+#: main.c:2308
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tPou¾ije <vimrc> namiesto akéhokoµvek .vimrc"
+
+#: main.c:2310
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tPou¾ije <gvimrc> namiesto akéhokoµvek .gvimrc"
+
+#: main.c:2312
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tNenahrá 'plugin' skripty"
+
+#: main.c:2313
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tOtvorí N okien (implicitne jedno pre ka¾dý súbor)"
+
+#: main.c:2314
+msgid "-O[N]\t\tlike -o but split vertically"
+msgstr "-O[N]\t\tako -o ale rozdelí vertikálne"
+
+#: main.c:2315
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tNastaví kurzor na koniec súboru"
+
+#: main.c:2316
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<riadok>\t\tNastaví kurzor na <riadok>"
+
+#: main.c:2318
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <príkaz>\t\tVykoná <príkaz> pred nahraním vimrc súboru"
+
+#: main.c:2320
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <príkaz>\t\tPo nahraní prvého súboru vykoná <príkaz>"
+
+#: main.c:2321
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <sedenie>\t\tPo nahrání prvého súboru vykoná príkazy v súbore <sedenie>"
+
+#: main.c:2322
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <skript>\t\tNaèíta príkazy normálneho módu zo <skriptu>"
+
+#: main.c:2323
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <skript>\t\tPripojí v¹etky napísané príkazy do súboru <skript>"
+
+#: main.c:2324
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <skript>\t\tUlo¾í v¹etky napísané príkazy do súboru <skript>"
+
+#: main.c:2326
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tÚprava za¹ifrovaných súborov"
+
+#: main.c:2330
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <displej>\tSpustí vim na <displej>"
+
+#: main.c:2332
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tNepripojí sa k X serveru"
+
+#: main.c:2334
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tOtvorí Vim vnútri iného GTK programu."
+
+#: main.c:2338
+msgid "--remote <files>\tEdit <files> in a Vim server and exit"
+msgstr "--remote <súbory>\tUpravi» <súbory> na Vim servri a skonèi»"
+
+#: main.c:2339
+msgid "--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <súbory>\tAko --remote ale èaká na súbory pre ukonèenie úprav"
+
+#: main.c:2340
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <voµby>\tOdo¹le <voµby> na Vim server a skonèí"
+
+#: main.c:2341
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <výraz>\tSpusti <výraz> na servri a vytlaèí výsledok"
+
+#: main.c:2342
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tVypí¹e zoznam mien dostupných Vim servrov a skonèí"
+
+#: main.c:2343
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <názov>\tOdo¹le na Vim server <názov>"
+
+#: main.c:2346
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tPou¾ije <viminfo> namiesto akéhokoµvek .viminfo"
+
+#: main.c:2348
+msgid "-h\t\t\tprint Help (this message) and exit"
+msgstr "-h\t\t\tVypí¹e túto nápovedu a skonèí"
+
+#: main.c:2349
+msgid "--version\t\tprint version information and exit"
+msgstr "--version\t\tvypí¹e informácie o verzii a skonèí"
+
+#: main.c:2353
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Argumenty pre gvim (Motif verzia):\n"
+
+#: main.c:2356
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Argumenty pre gvim (Athena verzia):\n"
+
+#: main.c:2359
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <displej>\tSpustí vim na <displej>"
+
+#: main.c:2360
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tSpustí vim minimalizované"
+
+#: main.c:2362
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <názov>\t\tPou¾ije resource ako by vim mal <názov>"
+
+#: main.c:2363
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (nie je implementované)\n"
+
+#: main.c:2365
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <farba>\tNastaví sa <farba> pozadia (tie¾ -bg)"
+
+#: main.c:2366
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <farba>\tNastaví sa <farba> popredia (tie¾ -fg)"
+
+#: main.c:2367 main.c:2387
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <písmo>\t\tNastaví <písmo> normálneho textu (tie¾ -fn)"
+
+#: main.c:2368
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <písmo>\tNastaví <písmo> pre zvýraznený text"
+
+#: main.c:2369
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <písmo>\tNastaví <písmo> pre kurzívu"
+
+#: main.c:2370 main.c:2388
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geometrie>\tNastaví sa <geometria> (tie¾ -geom)"
+
+#: main.c:2371
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <¹írka>\tNastaví <¹írku> okrajov (tie¾ -bw)"
+
+#: main.c:2372
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <¹írka> Nastaví <¹írku> posuvnej li¹ty (tie¾ -sw)"
+
+#: main.c:2374
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <vý¹ka>\tNastaví <vý¹ku> ponuky (tie¾ -mh)"
+
+#: main.c:2376 main.c:2389
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tPou¾ije reverzné farby (tie¾ -rv)"
+
+#: main.c:2377
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tNepou¾ije reverzné farby (tie¾ +rv)"
+
+#: main.c:2378
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\tNastaví zadaný <resource>"
+
+#: main.c:2381
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Argumenty pre gvim (RISC OS verzia):\n"
+
+#: main.c:2382
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <poèet>\t<poèet> ståpcov na okno"
+
+#: main.c:2383
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <poèet>\t<poèet> riadkov na okno"
+
+#: main.c:2386
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Argumenty pre gvim (GTK+ verzia):\n"
+
+#: main.c:2390
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <displej>\tspustí vim na <displej> (tie¾ --display)"
+
+#: main.c:2392
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tVypí¹e Gnome argumenty"
+
+#. Failed to send, abort.
+#: main.c:2634
+msgid ""
+"\n"
+"Send failed.\n"
+msgstr ""
+"\n"
+"Odoslanie zlyhalo.\n"
+
+#. Let vim start normally.
+#: main.c:2639
+msgid ""
+"\n"
+"Send failed. Trying to execute locally\n"
+msgstr ""
+"\n"
+"Odoslanie zlyhalo. Pokú¹am sa spusti» lokálne\n"
+
+#: main.c:2672 main.c:2693
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d upravených súborov z %d"
+
+#: main.c:2716
+msgid "Send expression failed.\n"
+msgstr "Odoslanie výrazu zlyhalo.\n"
+
+#: mark.c:660
+msgid "No marks set"
+msgstr "Nie sú nastavené ¾iadne znaèky"
+
+#: mark.c:662
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283:\"%s\" nevyhovujú ¾iadne znaèky"
+
+#. Highlight title
+#: mark.c:673
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"znaèka riadok ståpec súbor/text"
+
+#. Highlight title
+#: mark.c:711
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" skok riadok ståpec súbor/text"
+
+#: mark.c:1073
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Súborové znaèky:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1108
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Zoznam skokov (zaèínajúci najnov¹ou polo¾kou):\n"
+
+#: mark.c:1203
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# História znaèiek v súboroch (zaèínajúci najnov¹ou polo¾kou):\n"
+
+#: mark.c:1286
+msgid "Missing '>'"
+msgstr "Chýba '>'"
+
+#: mbyte.c:395
+msgid "Not a valid codepage"
+msgstr "Chybná kódová stránka"
+
+#: mbyte.c:3103
+msgid "E284: Cannot set IC values"
+msgstr "E284: Nedjú sa nastavi» IC hodnoty"
+
+#: mbyte.c:3255
+msgid "E285: Failed to create input context"
+msgstr "E285: Nepodarilo sa vytvori» vstupný kontext"
+
+#: mbyte.c:3402
+msgid "E286: Failed to open input method"
+msgstr "E286: Nepodarilo sa otvori» vstupnú metódu"
+
+#: mbyte.c:3413
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: Varovanie: likvidaèné spätné volanie sa nedá nastavi» na IM"
+
+#: mbyte.c:3419
+msgid "E288: input method doesn't support any style"
+msgstr "E288: vstupná metóda nepodporuje ¾iadny ¹týl"
+
+#: mbyte.c:3476
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: vstupná metóda nepodporuje môj 'preedit' typ"
+
+#: mbyte.c:3550
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: Nadbodový ¹týl vy¾aduje fontset"
+
+#: mbyte.c:3578
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: Máte GTK+ verziu star¹iu ne¾ 1.2.3. Stavová plocha vypnutá."
+
+#: mbyte.c:3843
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Server vstupných metód nebe¾í"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: blok nebol zamknutý"
+
+#: memfile.c:989
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Chyba posunu pri èítaní odkladacieho súboru"
+
+#: memfile.c:994
+msgid "E295: Read error in swap file"
+msgstr "E295: Chyba pri èítaní odkladacieho súboru"
+
+#: memfile.c:1046
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Chyba posunu pri ukladaní do odkladacieho súboru"
+
+#: memfile.c:1064
+msgid "E297: Write error in swap file"
+msgstr "E297: Chyba pri ukladaní do odkladacieho súboru"
+
+#: memfile.c:1261
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: Odkladací súbor u¾ existuje!"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Nedá sa získa» blok 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Nedá sa získa» blok 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: Nedá sa získa» blok 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Ups, odkladací súbor bol stratený!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: Nedá sa premenova» odkladací súbor"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: Nedá sa otvori» odkladací súbor pre \"%s\", oprava nie je nemo¾ná"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: nedá sa získa» blok 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Odkladací súbor pre %s nebol nájdený"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "Zadajte èíslo odkladacieho súboru, ktorý sa má pou¾it (0 pre ukonèenie): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: Nedá sa otvori» %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "Nedá sa èíta» blok 0 z "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Mo¾no nedo¹lo k ¾iadnym zmenám, alebo Vim neaktualizoval odkladací súbor."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " nedá sa pou¾i» s touto verziou Vim.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Pou¾ite Vim verziu 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s sa nezdá by» odkladacím súborom Vim"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " nedá sa pou¾í» na tomto poèítaèi.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "Súbor bol vytvorený "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"alebo bol súbor po¹kodený."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "Pou¾ívám odkladací súbor \"%s\""
+
+#: memline.c:915
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Pôvodný súbor \"%s\""
+
+#: memline.c:934
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Varovanie: Pôvodný súbor mohl by» zmenený"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Nedá sa èíta» blok 1 z %s"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???CHÝBA MNOHO RIADKOV"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???CHYBNÝ POÈET RIADKOV"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???PRÁZDNY BLOK"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???CHÝBAJÚCE RIADKY"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ID bloku 1 je chybné (je %s odkladacím súborom?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???CHÝBA BLOK"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "od ??? po ???END mô¾u by» riadky pomie¹ané"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "od ??? po ???END mô¾u by» vlo¾ené/vymazané riadky"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???KONIEC"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Obnova preru¹ená"
+
+#: memline.c:1145
+msgid "E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: V priebehu obnovy do¹lo k chybám; skontrolujte riadky zaèínajúce na ???"
+
+#: memline.c:1148
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Obnova dokonèená. Skontrolujte, èi je v¹etko v poriadku."
+
+#: memline.c:1149
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Zvá¾te ulo¾enie tohoto súboru pod iným menom\n"
+
+#: memline.c:1150
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "a pomocou programu diff zistite zmeny oproti pôvodnému súboru.)\n"
+
+#: memline.c:1151
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr "Potom vyma¾te odkladací súbor.\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1207
+msgid "Swap files found:"
+msgstr "Nájdené odkladacie súbory:"
+
+#: memline.c:1385
+msgid " In current directory:\n"
+msgstr " V aktuálnom adresári:\n"
+
+#: memline.c:1387
+msgid " Using specified name:\n"
+msgstr " So zadaným menom:\n"
+
+#: memline.c:1391
+msgid " In directory "
+msgstr " V adresári "
+
+#: memline.c:1409
+msgid " -- none --\n"
+msgstr " -- ¾iadne --\n"
+
+#: memline.c:1481
+msgid " owned by: "
+msgstr " vlastník: "
+
+#: memline.c:1483
+msgid " dated: "
+msgstr " dátum vytvorenia: "
+
+#: memline.c:1487 memline.c:3680
+msgid " dated: "
+msgstr " dátum vytvorenia: "
+
+#: memline.c:1503
+msgid " [from Vim version 3.0]"
+msgstr " [od Vim verzie 3.0]"
+
+#: memline.c:1507
+msgid " [does not look like a Vim swap file]"
+msgstr " [nevypadá ako odkladací súbor Vim]"
+
+#: memline.c:1511
+msgid " file name: "
+msgstr " názov súboru: "
+
+#: memline.c:1523
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" dátum zmeny: "
+
+#: memline.c:1524
+msgid "YES"
+msgstr "ÁNO"
+
+#: memline.c:1524
+msgid "no"
+msgstr "nie"
+
+#: memline.c:1528
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" u¾ívateµské meno: "
+
+#: memline.c:1535
+msgid " host name: "
+msgstr " názov poèítaèa: "
+
+#: memline.c:1537
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" názov poèítaèa: "
+
+#: memline.c:1543
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ID procesu : "
+
+#: memline.c:1549
+msgid " (still running)"
+msgstr " (stále aktívny)"
+
+#: memline.c:1561
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [nepou¾iteµné s touto verziou Vim]"
+
+#: memline.c:1564
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [nepou¾itelné na tomto poèítaèi]"
+
+#: memline.c:1569
+msgid " [cannot be read]"
+msgstr " [nedá sa preèíta»]"
+
+#: memline.c:1573
+msgid " [cannot be opened]"
+msgstr " [nedá sa otvori»]"
+
+#: memline.c:1763
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Nedá sa zachova» - odkladací súbor neexistuje."
+
+#: memline.c:1816
+msgid "File preserved"
+msgstr "Súbor zachovaný"
+
+#: memline.c:1818
+msgid "E314: Preserve failed"
+msgstr "E314: Uchovanie sa nepodarilo"
+
+#: memline.c:1889
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: chybné èíslo riadku: %ld"
+
+#: memline.c:1915
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: nedá sa nájs» riadok %ld"
+
+#: memline.c:2303
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: chybné id ukazovateµa na blok 3"
+
+#: memline.c:2383
+msgid "stack_idx should be 0"
+msgstr "stack_idx by malo ma» hodnotu 3"
+
+#: memline.c:2445
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Aktualizovaných príli¹ veµa blokov?"
+
+#: memline.c:2602
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: chybné id ukazovateµa na blok 4"
+
+#: memline.c:2629
+msgid "deleted block 1?"
+msgstr "vymazaný blok 1?"
+
+#: memline.c:2829
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Nedá sa nájs» riadok %ld"
+
+#: memline.c:3072
+msgid "E317: pointer block id wrong"
+msgstr "E317: chybné id ukazovateµa na blok"
+
+#: memline.c:3088
+msgid "pe_line_count is zero"
+msgstr "pe_line_count má nulovú hodnotu"
+
+#: memline.c:3117
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: èíslo riadku je mimo rozsah: %ld (za koncom)"
+
+#: memline.c:3121
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: chybný poèet riadkov v bloku %ld"
+
+#: memline.c:3170
+msgid "Stack size increases"
+msgstr "Nárast veµkosti zásobníku"
+
+#: memline.c:3216
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: chybný id ukazovateµa na blok 2"
+
+#: memline.c:3670
+msgid "E325: ATTENTION"
+msgstr "E325: POZOR"
+
+#: memline.c:3671
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Nájdený odkladací súbor s menom \""
+
+#: memline.c:3675
+msgid "While opening file \""
+msgstr "Pri otváraní súboru\""
+
+#: memline.c:3684
+msgid " NEWER than swap file!\n"
+msgstr " NOV©Í ako odkladací súbor!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3688
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Súbor mô¾e by» upravovaný iným programom.\n"
+" Ak je tomu tak, potom si dajte pozor, aby ste po ulo¾ení zmien\n"
+" nemali dve rôzne verzie toho istého súboru.\n"
+
+#: memline.c:3689
+msgid " Quit, or continue with caution.\n"
+msgstr " Ukonèite program, alebo opatrnne pokraèujte v úpravách.\n"
+
+#: memline.c:3690
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) Úprava tohoto súboru bola preru¹ená neoèakávaným ukonèením programu.\n"
+
+#: memline.c:3691
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Ak je tomu tak, potom pou¾ite \":recover\" alebo \"vim -r "
+
+#: memline.c:3693
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" pre obnovenie zmien (viz \":help recovery)\".\n"
+
+#: memline.c:3694
+msgid " If you did this already, delete the swap file \""
+msgstr " Pokiaµ ste tak u¾ urobili, tak vyma¾te odkladací súbor \""
+
+#: memline.c:3696
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" a táto správa sa u¾ nebude objavova».\n"
+
+#: memline.c:3710 memline.c:3714
+msgid "Swap file \""
+msgstr "Odkladací súbor \""
+
+#: memline.c:3711 memline.c:3717
+msgid "\" already exists!"
+msgstr "\" u¾ existuje!"
+
+#: memline.c:3720
+msgid "VIM - ATTENTION"
+msgstr "VIM - POZOR"
+
+#: memline.c:3722
+msgid "Swap file already exists!"
+msgstr "Odkladací súbor u¾ existuje!"
+
+#: memline.c:3726
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"&Otvori» iba pre èítanie\n"
+"&Pokraèova» v úpravách\n"
+"O&bnovi» súbor\n"
+"&Koniec"
+
+#: memline.c:3728
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"&Otvori» iba pre èítanie\n"
+"&Pokraèovat v úpravách\n"
+"O&bnovi» súbor\n"
+"&Koniec\n"
+"&Zmaza»"
+
+#: memline.c:3781
+msgid "E326: Too many swap files found"
+msgstr "E326: Príli¹ mnoho odkladacích súborov"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Èas» cesty k predmetu ponuky nie je podponukou"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Ponuka existuje iba v inom móde"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Ponuka tohoto mena neexistuje"
+
+#: menu.c:509
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Cesta ponuky nesmie vies» do podponuky"
+
+#: menu.c:548
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: Polo¾ky ponuky sa nedjú pridáva» priamo na li¹tu"
+
+#: menu.c:554
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Oddeµovaè nesmie by» èas»ou cesty ponuky"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1070
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Ponuky ---"
+
+#: menu.c:1987
+msgid "Tear off this menu"
+msgstr "Odtrhnú» tuto ponuku"
+
+#: menu.c:2052
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Cesta ponuky musí vies» k polo¾ke ponuky"
+
+#: menu.c:2072
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Vzor nenájdený: %s"
+
+#: menu.c:2141
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: V %s móde nie je ponuka definovaná"
+
+#: menu.c:2179
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Cesta ponuky musí vies» do podponuky"
+
+#: menu.c:2200
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Ponuka nenájdená - skontrolujte názvy ponúk"
+
+#: message.c:470
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Chyba pri spracovaní %s:"
+
+#: message.c:486
+#, c-format
+msgid "line %4ld:"
+msgstr "riadok %4ld:"
+
+#: message.c:526
+msgid "[string too long]"
+msgstr "[príli¹ dlhý re»azec]"
+
+#: message.c:672
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "Správca správ: Martin Lacko <lacko@host.sk>"
+
+#: message.c:885
+msgid "Interrupt: "
+msgstr "Preru¹enie: "
+
+#: message.c:888
+msgid "Hit ENTER to continue"
+msgstr "Pokraèovanie stlaèením ENTER"
+
+#: message.c:890
+msgid "Hit ENTER or type command to continue"
+msgstr "Pre pokraèovanie stlaète ENTER alebo zadajte príkaz"
+
+#: message.c:1961
+msgid "-- More --"
+msgstr "-- Pokraèovanie --"
+
+#: message.c:1964
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: riadok, MEDZERNÍK/b: stránka, d/u: 0.5 stránky, q: koniec)"
+
+#: message.c:1965
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: riadok, MEDZERNÍK: stránka, d: 0.5 stránky, q: koniec)"
+
+#: message.c:2441 message.c:2456
+msgid "Question"
+msgstr "Otázka"
+
+#: message.c:2443
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"Án&o\n"
+"&Nie"
+
+#: message.c:2458
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"Án&o\n"
+"&Nie\n"
+"&Zru¹i»"
+
+#: message.c:2476
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"Án&o\n"
+"&Nie\n"
+"&Ulo¾i» v¹etko\n"
+"Zahodi» &v¹etko\n"
+"&Zru¹i»"
+
+#: message.c:2517
+msgid "Save File dialog"
+msgstr "Dialóg pre ukladanie súborov"
+
+#: message.c:2519
+msgid "Open File dialog"
+msgstr "Dialóg pre otváranie súborov"
+
+#. TODO: non-GUI file selector here
+#: message.c:2590
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: ¥utujem, ale konzolová verzia nepodporuje prehliadaè súborov"
+
+#: misc1.c:2457
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: Varovanie: mením súbor iba pre èítanie"
+
+#: misc1.c:2686
+msgid "1 more line"
+msgstr "poèet nových riadkov: 1"
+
+#: misc1.c:2688
+msgid "1 line less"
+msgstr "poèet vymazaných riadkov: 1"
+
+#: misc1.c:2693
+#, c-format
+msgid "%ld more lines"
+msgstr "poèet nových riadkov: %ld"
+
+#: misc1.c:2695
+#, c-format
+msgid "%ld fewer lines"
+msgstr "poèet vymazaných riadkov: %ld"
+
+#: misc1.c:2698
+msgid " (Interrupted)"
+msgstr " (Preru¹ené)"
+
+#: misc1.c:6316
+msgid "Vim: preserving files...\n"
+msgstr "Vim: zachovávam súbory...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6326
+msgid "Vim: Finished.\n"
+msgstr "Vim: ukonèený\n"
+
+#: misc2.c:661 misc2.c:677
+msgid "ERROR: "
+msgstr "CHYBA: "
+
+#: misc2.c:681
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bajtov] celkom uvolnené-alokované %lu-%lu, vyu¾ité %lu, maximálne vyu¾itie %"
+"lu\n"
+
+#: misc2.c:683
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[volanie] celkom re/malloc(): %lu, celkom free() %lu\n"
+"\n"
+
+#: misc2.c:738
+msgid "E340: Line is becoming too long"
+msgstr "E340: Riadok sa stáva príli¹ dlhým"
+
+#: misc2.c:782
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Vnútorná chyba: lalloc(%ld, )"
+
+#: misc2.c:890
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Nedostatok pamäte! (alokujem %lu bytov)"
+
+#: misc2.c:2541
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Volám shell na spustenie: \"%s\""
+
+#: misc2.c:2740 misc2.c:5225 option.c:4636
+msgid "Missing colon"
+msgstr "Chýba dvojbodka"
+
+#: misc2.c:2742 misc2.c:2769
+msgid "Illegal mode"
+msgstr "Neprístupný mód"
+
+#: misc2.c:2808
+msgid "Illegal mouseshape"
+msgstr "Chybný tvar my¹i"
+
+#: misc2.c:2848 misc2.c:5245
+msgid "digit expected"
+msgstr "oèakávaná èíslica"
+
+#: misc2.c:2853
+msgid "Illegal percentage"
+msgstr "Neprístupné precento"
+
+#: misc2.c:3157
+msgid "Enter encryption key: "
+msgstr "Zadajte ¹ifrovací kµúè: "
+
+#: misc2.c:3158
+msgid "Enter same key again: "
+msgstr "Vlo¾te kµúè znova: "
+
+#: misc2.c:3168
+msgid "Keys don't match!"
+msgstr "Kµúè nie je správny!"
+
+#: misc2.c:3707
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Chybná cesta: '**[èíslo] musí by» buï na konci cesty, alebo musí by»\n"
+"nasledované '%s. Viz :help path."
+
+#: misc2.c:4979
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Adresár \"%s\" sa nedá v cdpath nájs»"
+
+#: misc2.c:4982
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Súbor \"%s\" sa nepodarilo nájs»"
+
+#: misc2.c:4988
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: ®iadny ïal¹í adresár \"%s\" nebol v cdpath nájdený"
+
+#: misc2.c:4991
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: ®iadny ïal¹í súbor \"%s\" nebol v ceste nájdený"
+
+#: misc2.c:5237
+msgid "Illegal component"
+msgstr "Neprístupný komponent"
+
+#: normal.c:2843
+msgid "Warning: terminal cannot highlight"
+msgstr "Varovanie: terminál nepodporuje zvýrazòovanie"
+
+#: normal.c:3038
+msgid "E348: No string under cursor"
+msgstr "E348: Pod kurzorom nie je ¾iadny re»azec"
+
+#: normal.c:3040
+msgid "E349: No identifier under cursor"
+msgstr "E349: Pod kurzorom nie je ¾iadny identifikátor"
+
+#: normal.c:4211
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: Pomocou 'foldmethod' sa nedá vymaza» záhyb"
+
+#: ops.c:283
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "poèet riadkov posunutých naraz pomocou %s : 1"
+
+#: ops.c:285
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "poèet riadkov posunutých %s krát pomocou %d s : 1"
+
+#: ops.c:290
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld riadkov posunutých naraz pomocou %s"
+
+#: ops.c:293
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld riadkov posunutých pomocou %s %d krát"
+
+#: ops.c:651
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "poèet riadkov pre odsadenie: %ld"
+
+#: ops.c:701
+msgid "1 line indented "
+msgstr "poèet riadkov pre odsadenie: 1 "
+
+#: ops.c:703
+#, c-format
+msgid "%ld lines indented "
+msgstr "poèet odsadených riadkov: %ld"
+
+#. must display the prompt
+#: ops.c:1546
+msgid "cannot yank; delete anyway"
+msgstr "nedá sa kopírova»; napriek tomu vymazané"
+
+#: ops.c:2080
+msgid "1 line changed"
+msgstr "poèet zmenených riadkov: 1"
+
+#: ops.c:2082
+#, c-format
+msgid "%ld lines changed"
+msgstr "poèet zmenených riadkov: %ld"
+
+#: ops.c:2439
+#, c-format
+msgid "freeing %ld lines"
+msgstr "poèet uvolòovaných riadkov: %ld"
+
+#: ops.c:2720
+msgid "1 line yanked"
+msgstr "poèet skopírovaných riadkov: 1"
+
+#: ops.c:2722
+#, c-format
+msgid "%ld lines yanked"
+msgstr "poèet skopírovaných riadkov: %ld"
+
+#: ops.c:2995
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: Register %s je prázdny"
+
+#. Highlight title
+#: ops.c:3553
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Registre ---"
+
+#: ops.c:4711
+msgid "Illegal register name"
+msgstr "Neprístupný názov registru"
+
+#: ops.c:4797
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Registre:\n"
+
+#: ops.c:4825
+#, c-format
+msgid "Unknown register type %d"
+msgstr "%d nie je známým typom registru"
+
+#: ops.c:5217
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: '%s' nie je prístupné meno registru"
+
+#: ops.c:5560
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Buniek; "
+
+#: ops.c:5567
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Vybraných %s%ld z %ld riadkov; %ld zo %ld slov; %ld z %ld Bytov"
+
+#: ops.c:5583
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Bunka %s z %s; Riadok %ld z %ld; Slovo %ld z %ld; Byte %ld z %ld"
+
+#: ops.c:5594
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld pre BOM)"
+
+#: option.c:1989
+msgid "Thanks for flying Vim"
+msgstr "Ïakujem za pou¾itie Vim"
+
+#: option.c:3175
+msgid "Option not supported"
+msgstr "Voµba nie je podporovaná"
+
+#: option.c:3200
+msgid "Not allowed in a modeline"
+msgstr "Nie je v modeline povolené"
+
+#: option.c:3256
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tOstatné nastavenie z "
+
+#: option.c:3395
+msgid "Number required after ="
+msgstr "Po = je vy¾adované èíslo"
+
+#: option.c:3714 option.c:4322
+msgid "Not found in termcap"
+msgstr "Nenájdený v termcapu"
+
+#: option.c:3780
+#, c-format
+msgid "Illegal character <%s>"
+msgstr "Neprístupný znak <%s>"
+
+#: option.c:4307 option.c:5570
+msgid "Not allowed here"
+msgstr "Toto nie je na tomto mieste povolené"
+
+#: option.c:4314
+msgid "Cannot set 'term' to empty string"
+msgstr "Voµba 'term' nemô¾e by» prázdna"
+
+#: option.c:4317
+msgid "Cannot change term in GUI"
+msgstr "V GUI sa nedá meni» term"
+
+#: option.c:4319
+msgid "Use \":gui\" to start the GUI"
+msgstr "Pou¾ite \"gui\" pre spustenie GUI"
+
+#: option.c:4340
+msgid "'backupext' and 'patchmode' are equal"
+msgstr "voµby 'backupext' a 'patchmode' majú rovnakú hodnotu"
+
+#: option.c:4638
+msgid "Zero length string"
+msgstr "Re»azec s nulovou då¾kou"
+
+#: option.c:4706
+#, c-format
+msgid "Missing number after <%s>"
+msgstr "Po <%s> chýba èíslo"
+
+#: option.c:4720
+msgid "Missing comma"
+msgstr "Chýba èiarka"
+
+#: option.c:4727
+msgid "Must specify a ' value"
+msgstr "Je nutné zada» hodnotu '"
+
+#: option.c:4767
+msgid "contains unprintable character"
+msgstr "obsahuje netlaèiteµné znaky"
+
+#: option.c:4800
+msgid "Invalid font(s)"
+msgstr "Chybné písma"
+
+#: option.c:4807
+msgid "can't select fontset"
+msgstr "nedá sa vybra» sada písiem"
+
+#: option.c:4809
+msgid "Invalid fontset"
+msgstr "Chybná sada písiem"
+
+#: option.c:4816
+msgid "can't select wide font"
+msgstr "nedá sa vybra» ¹iroký font"
+
+#: option.c:4818
+msgid "Invalid wide font"
+msgstr "Chybné ¹iroké písmo"
+
+#: option.c:5088
+#, c-format
+msgid "Illegal character after <%c>"
+msgstr "Neprístupný znak po <%c>"
+
+#: option.c:5171
+msgid "comma required"
+msgstr "je nutná èiarka"
+
+#: option.c:5179
+#, c-format
+msgid "'commentstring' must be empty or contain %s"
+msgstr "'komentár' musí by» prázdny alebo musí obsahova» %s"
+
+#: option.c:5226
+msgid "No mouse support"
+msgstr "Bez podpory my¹i"
+
+#: option.c:5472
+msgid "Unclosed expression sequence"
+msgstr "Neuzatvorené zoskupenie výrazov"
+
+#: option.c:5476
+msgid "too many items"
+msgstr "príli¹ mnoho polo¾iek"
+
+#: option.c:5478
+msgid "unbalanced groups"
+msgstr "nevyvá¾ené skupiny"
+
+#: option.c:5693
+msgid "A preview window already exists"
+msgstr "Okno náhµadu u¾ existuje"
+
+#: option.c:5954 option.c:5983
+msgid "'winheight' cannot be smaller than 'winminheight'"
+msgstr "hodnota voµby 'winheight' nesmie by» men¹ia ne¾ hodnota voµby 'winminheight'"
+
+#: option.c:5999 option.c:6018
+msgid "'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "hodnota voµby 'winwidth' nesmie by» men¹ia ne¾ hodnota volµy 'winminwidth'"
+
+#: option.c:6159
+#, c-format
+msgid "Need at least %d lines"
+msgstr "Minimálne potrebný poèet riadkov: %d"
+
+#: option.c:6168
+#, c-format
+msgid "Need at least %d columns"
+msgstr "Minimálne potrebný poèet ståpcov: %d"
+
+#: option.c:6465
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Neznáma voµba: %s"
+
+#: option.c:6574
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Kódy terminálu ---"
+
+#: option.c:6576
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Nastavenie globálnych volieb ---"
+
+#: option.c:6578
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Nastavenie globálnych volieb ---"
+
+#: option.c:6580
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Mo¾nosti ---"
+
+#: option.c:7269
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp CHYBA"
+
+#: option.c:8227
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': pre %s chýba vyhovujúci znak"
+
+#: option.c:8261
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': nadbytoèné znaky po bodkoèiarke: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "nedá sa otvori» "
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Nedá sa otvori» okno!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Je potrebná Amigados verzia 2.04 alebo nov¹ia\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Potrebný %s verzia %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "Nedá sa otvori» NIL:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr "Nedá sa vytvori» "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim ukonèený s %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "nemô¾em zmeni» konzolový mód ?!\n"
+
+#: os_amiga.c:938 os_mac.c:1177 os_mswin.c:629 os_riscos.c:757 os_unix.c:2803
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Nastavovanie re¾imu obrazovky nie je podporované"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: nie je konzolou??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1142
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Nedá sa spusti» shell s -f voµbou"
+
+#: os_amiga.c:1183 os_amiga.c:1273
+msgid "Cannot execute "
+msgstr "Nedá sa spusti» "
+
+#: os_amiga.c:1186 os_amiga.c:1283
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1206 os_amiga.c:1308
+msgid " returned\n"
+msgstr " vrátené\n"
+
+#: os_amiga.c:1448
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE príli¹ malá."
+
+#: os_amiga.c:1452
+msgid "I/O ERROR"
+msgstr "I/O CHYBA"
+
+#: os_mswin.c:503
+msgid "...(truncated)"
+msgstr "...(skrátené)"
+
+#: os_mswin.c:604
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'ståpce' nie je 80, nemô¾em spusti» externý príkaz"
+
+#: os_mswin.c:716 os_unix.c:5116
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Vyvolanie kni¾niènej funkcia zlyhalo pre \"%s()\""
+
+#: os_mswin.c:1365
+msgid "E237: Printer selection failed"
+msgstr "E237: Zlyhal výber tlaèiarne"
+
+#: os_mswin.c:1405
+#, c-format
+msgid "to %s on %s"
+msgstr "%s na %s"
+
+#: os_mswin.c:1420
+#, c-format
+msgid "E448: Unknown font: %s"
+msgstr "E448: Neznáme písmo: %s"
+
+#: os_mswin.c:1470 os_mswin.c:1480
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Chyba tlaèe: %s"
+
+#: os_mswin.c:1481
+msgid "Unknown"
+msgstr "Neznámy"
+
+#: os_mswin.c:1508
+#, c-format
+msgid "Printing '%s'"
+msgstr "Tlaèím '%s'"
+
+#: os_mswin.c:2596
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Chybný názov znakovej sady \"%s\" v názve písma \"%s\""
+
+#: os_mswin.c:2604
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Chybný znak '%c' v názve písma \"%s\""
+
+#: os_riscos.c:1256
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Chybná 'osfiletype' voµba - pou¾itie Textu"
+
+#: os_unix.c:862
+msgid "Vim: Double signal, exiting\n"
+msgstr "VIm: dvojitý signál, konèím\n"
+
+#: os_unix.c:868
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Zachytený smrtiaci signál %s\n"
+
+#: os_unix.c:871
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Zachytený smrtiaci signál\n"
+
+#: os_unix.c:1125
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Otváram X displej - zaberie %ld msec"
+
+#: os_unix.c:1152
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: chyba X\n"
+
+#: os_unix.c:1219
+msgid "Testing the X display failed"
+msgstr "Testovanie X displeja zlyhalo"
+
+#: os_unix.c:1363
+msgid "Opening the X display timed out"
+msgstr "Uplynul èas otvorenia X displeja"
+
+#: os_unix.c:2976 os_unix.c:3634
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"Nedá sa spusti» shell "
+
+#: os_unix.c:3021
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Nedá sa spusti» sh shell\n"
+
+#: os_unix.c:3025 os_unix.c:3640
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+" návratová hodnota shellu "
+
+#: os_unix.c:3159
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Nedjú sa vytvori» rúry\n"
+
+#: os_unix.c:3174
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"Vyvolanie fork zlyhalo\n"
+
+#: os_unix.c:3647
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Príkaz ukonèený\n"
+
+#: os_unix.c:5164
+msgid "Opening the X display failed"
+msgstr "Otvorenie X displeja zlyhalo"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "Na riadku"
+
+#: os_win16.c:578 os_win32.c:3037
+#, c-format
+msgid "shell returned %d"
+msgstr "návratová hodnota shellu %d"
+
+#: os_win32.c:2505
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Zachytená udalos» %s\n"
+
+#: os_win32.c:2507
+msgid "close"
+msgstr "zavrie»"
+
+#: os_win32.c:2509
+msgid "logoff"
+msgstr "odhlási»"
+
+#: os_win32.c:2510
+msgid "shutdown"
+msgstr "vypnú»"
+
+#: os_win32.c:2991
+msgid "E371: Command not found"
+msgstr "E371: Príkaz nenájdený"
+
+#: os_win32.c:3004
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE nenájdený v $PATH.\n"
+"Po dokonèení externých príkazov nebude výstup pozastavený.\n"
+"Pozrite :help win32-vimrun pre viac informácií."
+
+#: os_win32.c:3007
+msgid "Vim Warning"
+msgstr "Vim Varovanie"
+
+#: os_w32exe.c:169
+msgid "Could not load vim32.dll!"
+msgstr "Nemô¾em nahra» vim32.dll!"
+
+#: os_w32exe.c:169 os_w32exe.c:179
+msgid "VIM Error"
+msgstr "VIM Chyba"
+
+#: os_w32exe.c:179
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Nemô¾em opravi» odkazy funkcie na DLL!"
+
+#: quickfix.c:281
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: Príli¹ mnoho %%%c vo formátovacom re»azci"
+
+#: quickfix.c:294
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: Neoèakávaný výskyt %%%c vo formátovacom re»azci"
+
+#: quickfix.c:348
+msgid "E374: Missing ] in format string"
+msgstr "E374: Vo formátovacom re»azci chýba ]"
+
+#: quickfix.c:362
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: Nepodporovaná formátová ¹pecifikácia %%%c vo formátovacom re»azci"
+
+#: quickfix.c:380
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: Neprístupné %%%c v prefixe formátovacieho re»azca"
+
+#: quickfix.c:388
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: Neprístupné %%%c vo formátovacom re»azci"
+
+#: quickfix.c:414
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' neobsahuje ¾iadny vzor"
+
+#: quickfix.c:520
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Chýbajúci alebo prázdny názov adresára"
+
+#: quickfix.c:931
+msgid "No more items"
+msgstr "®iadne ïal¹ie polo¾ky"
+
+#: quickfix.c:1152
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d/%d)%s%s: "
+
+#: quickfix.c:1154
+msgid " (line deleted)"
+msgstr " (riadok vymazaný)"
+
+#: quickfix.c:1360
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Koniec quickfix zoznamu"
+
+#: quickfix.c:1369
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Zaèiatok quickfix zoznamu"
+
+#: quickfix.c:1381
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "zoznam chýb %d z %d; poèet chýb: %d"
+
+#: quickfix.c:1842
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: Nedá sa ulo¾i», je nastavená voµba 'buftype'"
+
+#: regexp.c:802
+msgid "E339: Pattern too long"
+msgstr "E339: Vzor je príli¹ dlhý"
+
+#: regexp.c:1319
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: Vhniezdený %s*"
+
+#: regexp.c:1322
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: Vhniezdené %s%c"
+
+#: regexp.c:1473
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c niè nenasleduje"
+
+#: regexp.c:2490
+#, c-format
+msgid "Syntax error in %s{...}"
+msgstr "Chyba syntaxe v %s{...}"
+
+#: regexp.c:2737
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Zachytené preteèenie zásobníku: príli¹ zlo¾itý regulárny výraz?"
+
+#: regexp.c:2872
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: vzor spôsobil preteèenie zásobníku"
+
+#: regexp.c:3108
+msgid "External submatches:\n"
+msgstr "Vnútorné podradené zhody:\n"
+
+#: screen.c:2063
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld riadkov zahnutých "
+
+#: screen.c:7517
+msgid " VREPLACE"
+msgstr " NAHRADI« VERTIKÁLNE"
+
+#: screen.c:7521
+msgid " REPLACE"
+msgstr " NAHRADI«"
+
+#: screen.c:7526
+msgid " REVERSE"
+msgstr " OBRÁTI«"
+
+#: screen.c:7528
+msgid " INSERT"
+msgstr " VLO®I«"
+
+#: screen.c:7531
+msgid " (insert)"
+msgstr " (vlo¾i»)"
+
+#: screen.c:7533
+msgid " (replace)"
+msgstr " (nahradi»)"
+
+#: screen.c:7535
+msgid " (vreplace)"
+msgstr " (nahradi» vertikálne)"
+
+#: screen.c:7538
+msgid " Hebrew"
+msgstr " hebrejský"
+
+#: screen.c:7546
+msgid " (lang)"
+msgstr " (jazyk)"
+
+#: screen.c:7549
+msgid " (paste)"
+msgstr " (vlo¾i»)"
+
+#: screen.c:7555
+msgid " SELECT"
+msgstr " ZHODY"
+
+#: screen.c:7557
+msgid " VISUAL"
+msgstr " VIZUÁLNE"
+
+#: screen.c:7559
+msgid " BLOCK"
+msgstr " BLOK"
+
+#: screen.c:7561
+msgid " LINE"
+msgstr " RIADOK"
+
+#: screen.c:7574 screen.c:7634
+msgid "recording"
+msgstr "nahrávam"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "hµadanie dosiahlo zaèiatok, pokraèovanie od konca"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "hµadanie dosiahlo koniec, pokraèovanie od zaèiatku"
+
+#: search.c:455
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Neprístupný hµadaný re»azec: %s"
+
+#: search.c:782
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: hµadanie dosiahlo zaèiatok bez nájdenia %s"
+
+#: search.c:784
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: hµadanie dosiahlo koniec bez nájdenia %s"
+
+#: search.c:1144
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: Po ';' oèakávam '?' alebo '/'"
+
+#: search.c:3523
+msgid " (includes previously listed match)"
+msgstr " (vrátane u¾ vypísaných zhôd)"
+
+#. cursor at status line
+#: search.c:3543
+msgid "--- Included files "
+msgstr "--- Vlo¾ené súbory"
+
+#: search.c:3545
+msgid "not found "
+msgstr "nenájdené "
+
+#: search.c:3546
+msgid "in path ---\n"
+msgstr "v ceste ---\n"
+
+#: search.c:3585
+msgid " (Already listed)"
+msgstr " (U¾ vypísané)"
+
+#: search.c:3587
+msgid " NOT FOUND"
+msgstr " NENÁJDENÉ"
+
+#: search.c:3639
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Prehµadávam vlo¾ené súbory: %s"
+
+#: search.c:3857
+msgid "E387: Match is on current line"
+msgstr "E387: Zhoda je na aktuálnom riadku"
+
+#: search.c:3997
+msgid "All included files were found"
+msgstr "V¹etky vlo¾ené súbory boli nájdené"
+
+#: search.c:3999
+msgid "No included files"
+msgstr "®iadne vlo¾ené súbory"
+
+#: search.c:4015
+msgid "E388: Couldn't find definition"
+msgstr "E388: Nedá sa nájs» definícia"
+
+#: search.c:4017
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Nedá sa nájs» vzor"
+
+#: syntax.c:2999
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: Neprístupný argument: %s"
+
+#: syntax.c:3179
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: Syntaktická zostava %s neexistuje"
+
+#: syntax.c:3343
+msgid "No Syntax items defined for this buffer"
+msgstr "Pre tento buffer nie sú definované ¾iadne polo¾ky syntaxe"
+
+#: syntax.c:3351
+msgid "syncing on C-style comments"
+msgstr "synchronizujem komentáre v C ¹týle"
+
+#: syntax.c:3359
+msgid "no syncing"
+msgstr "¾iadne synchronizácie"
+
+#: syntax.c:3362
+msgid "syncing starts "
+msgstr "synchronizácia zaèína "
+
+#: syntax.c:3364 syntax.c:3439
+msgid " lines before top line"
+msgstr " riadkov pred zaèiatkom"
+
+#: syntax.c:3369
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Polo¾ky synchronizácie syntaxe ---"
+
+#: syntax.c:3374
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"synchronizujem polo¾ky"
+
+#: syntax.c:3380
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Polo¾ky syntaxe ---"
+
+#: syntax.c:3403
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: Syntaktická zostava %s neexistuje"
+
+#: syntax.c:3429
+msgid "minimal "
+msgstr "minimálne "
+
+#: syntax.c:3436
+msgid "maximal "
+msgstr "maximálne "
+
+#: syntax.c:3448
+msgid "; match "
+msgstr "; zhoda "
+
+#: syntax.c:3450
+msgid " line breaks"
+msgstr " riadkov"
+
+#: syntax.c:4078
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: group[t]here nesmie by» na tomto mieste"
+
+#: syntax.c:4102
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: Pre %s chýba polo¾ka regiónu"
+
+#: syntax.c:4130
+msgid "E395: contains argument not accepted here"
+msgstr "E395: obsahuje argumenty, ktoré tu nie sú povolené"
+
+#: syntax.c:4141
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: obsahuje argumenty, ktoré tu nie sú povolené"
+
+#: syntax.c:4219
+msgid "E397: Filename required"
+msgstr "E397: Vy¾adovaný názov súboru"
+
+#: syntax.c:4557
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Chýba '=': %s"
+
+#: syntax.c:4715
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Príli¹ málo argumentov: oblas» syntaxe %s"
+
+#: syntax.c:5046
+msgid "E400: No cluster specified"
+msgstr "E400: Nebola zadaná ¾iadna zostava"
+
+#: syntax.c:5083
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Oddeµovaè vzoru %s nenájdený"
+
+#: syntax.c:5158
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Chyba za vzorom %s"
+
+#: syntax.c:5245
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: synchronizácia syntaxe: vzor pokraèovania riadkov zadaný dvakrát"
+
+#: syntax.c:5302
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Chybné argumenty: %s"
+
+#: syntax.c:5352
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Chýba znamienko rovnása: %s"
+
+#: syntax.c:5358
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Prázdny argument: %s"
+
+#: syntax.c:5385
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s tu nie je povolené"
+
+#: syntax.c:5392
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s musí by» prvý v 'contains' zozname"
+
+#: syntax.c:5462
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Neznámy názov skupiny: %s"
+
+#: syntax.c:5692
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Chybný podradený príkaz :syntax : %s "
+
+#: syntax.c:6071
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: skupina zvíraznenia %s nebola nájdená"
+
+#: syntax.c:6095
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Príli¹ málo argumentov: \":highlight link %s\""
+
+#: syntax.c:6102
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: Príli¹ mnoho argumentov: \":highlight link %s\""
+
+#: syntax.c:6122
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: skupina je nastavená, odkaz na zvýrazòovaciu skupinu ignorovaný"
+
+#: syntax.c:6251
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: neoèakávané znamienko rovnása : %s"
+
+#: syntax.c:6287
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: chýba znamienko rovnása: %s"
+
+#: syntax.c:6309
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: chýba argument: %s"
+
+#: syntax.c:6346
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: Neprípustná hodnota: %s"
+
+#: syntax.c:6465
+msgid "E419: FG color unknown"
+msgstr "E419: farba popredia nie je známa"
+
+#: syntax.c:6476
+msgid "E420: BG color unknown"
+msgstr "E420: farba pozadia nie je známa"
+
+#: syntax.c:6537
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Názov alebo èíslo farby %s nebolo rozpoznané"
+
+#: syntax.c:6745
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: terminálový kód %s je príli¹ dlhý"
+
+#: syntax.c:6792
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: Neprístupný argument: %s"
+
+#: syntax.c:7321
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: Je pou¾ívané príli¹ velké mno¾stvo odli¹ných zvýrazòovacích vlastností"
+
+#: tag.c:90
+msgid "at bottom of tag stack"
+msgstr "koniec zoznamu tagov"
+
+#: tag.c:91
+msgid "at top of tag stack"
+msgstr "zaèiatok zoznamu tagov"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Nedá sa skoèi» pred prvý vyhovujúci tag"
+
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: tag %s nenájdený"
+
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr " # pri tag"
+
+#: tag.c:548
+msgid "file\n"
+msgstr "súbor\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Zadajte èíslo (<CR> pre ukonèenie): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: Vyhovuje iba jeden tag"
+
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Za posledný vyhovujúci tag sa nedá preskoèi»"
+
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Súbor \"%s\" neexistuje"
+
+#. Give an indication of the number of matching tags
+#: tag.c:780
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "tag %d z celkového poètu %d%s"
+
+#: tag.c:783
+msgid " or more"
+msgstr " alebo viac"
+
+#: tag.c:785
+msgid " Using tag with different case!"
+msgstr " Pou¾ívam tag s písmom inej veµkosti!"
+
+#: tag.c:828
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Súbor \"%s\" neexistuje"
+
+#. Highlight title
+#: tag.c:897
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # CIE¥ tag ©TART riadok v súbore/texte"
+
+#: tag.c:1144
+msgid "Linear tag search"
+msgstr "Lineárne hµadanie tagu"
+
+#: tag.c:1146
+msgid "Binary tag search"
+msgstr "Binárne hµadanie tagu"
+
+#: tag.c:1172
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Prehµadávam súbor tagov %s"
+
+#: tag.c:1356
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Súbor tagov %s bol orezaný\n"
+
+#: tag.c:1847
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Chyba formátu v súbore tagov \"%s\""
+
+#: tag.c:1851
+#, c-format
+msgid "Before byte %ld"
+msgstr "Pred bajtom %ld"
+
+#: tag.c:1872
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Obsah súboru tagov %s nie je zoradený"
+
+#. never opened any tags file
+#: tag.c:1911
+msgid "E433: No tags file"
+msgstr "E433: ®iadny súbor tagov"
+
+#: tag.c:2583
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Nedá sa nájs» vzor tagov"
+
+#: tag.c:2594
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Tag sa nedá nájs», iba hádam!"
+
+#: term.c:1737
+msgid "' not known. Available builtin terminals are:"
+msgstr "' nie je známy. Dostupné vstavané terminály:"
+
+#: term.c:1761
+msgid "defaulting to '"
+msgstr "nastavujem na '"
+
+#: term.c:2114
+msgid "Cannot open termcap file"
+msgstr "Nedá sa otvori» termcap súbor"
+
+#: term.c:2117
+msgid "Terminal entry not found in terminfo"
+msgstr "Terminfo neobsahuje polo¾ku pre tento terminál"
+
+#: term.c:2119
+msgid "Terminal entry not found in termcap"
+msgstr "Termcap neobsahuje polo¾ku pre tento terminál"
+
+#: term.c:2278
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Termcap neobsahuje polo¾ku pre \"%s\""
+
+#: term.c:2752
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: Terminál musí ma» \"cm\" schopnos»"
+
+#. Highlight title
+#: term.c:4891
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Klávesy terminálu ---"
+
+#: ui.c:251
+msgid "new shell started\n"
+msgstr "spustený nový shell\n"
+
+#: ui.c:1747
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: Chyba pri èítaní vstupu, konèím...\n"
+
+#. must display the prompt
+#: undo.c:383
+msgid "No undo possible; continue anyway"
+msgstr "Odstránenie zmien nie je mo¾né; chcete napriek tomu pokraèova»"
+
+#: undo.c:538
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: èísla riadkov sú chybné"
+
+#: undo.c:707
+msgid "1 change"
+msgstr "poèet zmien: 1"
+
+#: undo.c:709
+#, c-format
+msgid "%ld changes"
+msgstr "poèet zmien: %ld"
+
+#: undo.c:753
+msgid "E439: undo list corrupt"
+msgstr "E439: záznam o zmenách po¹kodený"
+
+#: undo.c:785
+msgid "E440: undo line missing"
+msgstr "E440: chýba riadok spä»"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:725
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"16/32 bitová GUI verzia pre MS Windows"
+
+#: version.c:727
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"32 bitová GUI verzia pre MS Windows"
+
+#: version.c:730
+msgid " in Win32s mode"
+msgstr " v Win32 re¾ime"
+
+#: version.c:732
+msgid " with OLE support"
+msgstr " s OLE podporou"
+
+#: version.c:735
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"32 bitová verzia pre MS Windows konzolu"
+
+#: version.c:739
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"16 bitová verzia pre MS Windows"
+
+#: version.c:743
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 bitová verzia pre MS-DOS"
+
+#: version.c:745
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 bitová MS-DOS verzia"
+
+#: version.c:751
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) verzia"
+
+#: version.c:753
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X verzia"
+
+#: version.c:756
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS verzia"
+
+#: version.c:761
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS verzia"
+
+#: version.c:771
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Pou¾ité záplaty: "
+
+#: version.c:797 version.c:1132
+msgid "Modified by "
+msgstr "Zmenil "
+
+#: version.c:804
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Prelo¾ená "
+
+#: version.c:807
+msgid "by "
+msgstr " "
+
+#: version.c:819
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Maximálna verzia"
+
+#: version.c:822
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Veµká verzia "
+
+#: version.c:825
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Normálna verzia"
+
+#: version.c:828
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Malá verzia "
+
+#: version.c:830
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Minimálna verzia "
+
+#: version.c:836
+msgid "without GUI."
+msgstr "bez grafického rozhrania."
+
+#: version.c:840
+msgid "with GTK-GNOME GUI."
+msgstr "s rozhraním GTK-GNOME."
+
+#: version.c:842
+msgid "with GTK GUI."
+msgstr "s rozhraním GTK."
+
+#: version.c:846
+msgid "with X11-Motif GUI."
+msgstr "s rozhraním X11-Motif."
+
+#: version.c:849
+msgid "with X11-Athena GUI."
+msgstr "s rozhraním X11-Athena."
+
+#: version.c:852
+msgid "with BeOS GUI."
+msgstr "s rozhraním BeOS."
+
+#: version.c:855
+msgid "with Photon GUI."
+msgstr "s rozhraním Photon."
+
+#: version.c:858
+msgid "with GUI."
+msgstr "s grafickým rozhraním."
+
+#: version.c:861
+msgid "with Carbon GUI."
+msgstr "s Carbon grafickým rozhraním."
+
+#: version.c:864
+msgid "with Cocoa GUI."
+msgstr "s Cocoa grafickým rozhraním."
+
+#: version.c:867
+msgid "with (classic) GUI."
+msgstr "s (klasickým) grafickým rozhraním."
+
+#: version.c:878
+msgid " Features included (+) or not (-):\n"
+msgstr " Vlastnosti zahrnuté (+) a nezahrnuté (-):\n"
+
+#: version.c:890
+msgid " system vimrc file: \""
+msgstr " systémový vimrc súbor: \""
+
+#: version.c:895
+msgid " user vimrc file: \""
+msgstr " u¾ívateµský vimrc súbor: \""
+
+#: version.c:900
+msgid " 2nd user vimrc file: \""
+msgstr " druhý u¾ívateµský vimrc súbor: \""
+
+#: version.c:905
+msgid " 3rd user vimrc file: \""
+msgstr " tretí u¾ívateµský vimrc súbor: \""
+
+#: version.c:910
+msgid " user exrc file: \""
+msgstr " u¾ívateµský exrc súbor: \""
+
+#: version.c:915
+msgid " 2nd user exrc file: \""
+msgstr " druhý u¾ívateµský exrc súbor: \""
+
+#: version.c:921
+msgid " system gvimrc file: \""
+msgstr " systémový gvimrc súbor: \""
+
+#: version.c:925
+msgid " user gvimrc file: \""
+msgstr " u¾ívateµský gvimrc súbor: \""
+
+#: version.c:929
+msgid "2nd user gvimrc file: \""
+msgstr "druhý u¾ívateµský gvimrc súbor: \""
+
+#: version.c:934
+msgid "3rd user gvimrc file: \""
+msgstr "tretí u¾ívateµský gvimrc súbor: \""
+
+#: version.c:941
+msgid " system menu file: \""
+msgstr " systémový súbor s ponukou: \""
+
+#: version.c:949
+msgid " fall-back for $VIM: \""
+msgstr " implicitná hodnota $VIM:\""
+
+#: version.c:955
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " f-b pre $VIMRUNTIME: \""
+
+#: version.c:959
+msgid "Compilation: "
+msgstr "Preklad: "
+
+#: version.c:965
+msgid "Compiler: "
+msgstr "Prekladaè: "
+
+#: version.c:970
+msgid "Linking: "
+msgstr "Linkujem: "
+
+#: version.c:975
+msgid " DEBUG BUILD"
+msgstr " PODPORA LADENIA"
+
+#: version.c:1011
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMpreved"
+
+#: version.c:1013
+msgid "version "
+msgstr "verzia "
+
+#: version.c:1014
+msgid "by Bram Moolenaar et al."
+msgstr "Autor: Bram Moolenaar a ïal¹í"
+
+#: version.c:1018
+msgid "Vim is open source and freely distributable"
+msgstr "Vim je voµne ¹íriteµný program"
+
+#: version.c:1020
+msgid "Help poor children in Uganda!"
+msgstr "Pomô¾te chudobným de»om v Ugande!"
+
+#: version.c:1021
+msgid "type :help iccf<Enter> for information "
+msgstr "podrobnej¹ie informácie získate pomocou :help iccf<Enter>"
+
+#: version.c:1023
+msgid "type :q<Enter> to exit "
+msgstr "zadajte :q<Enter> pre ukonèenie programu"
+
+#: version.c:1024
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "zadajte :help<Enter> alebo <F1> pre pomocníka"
+
+#: version.c:1025
+msgid "type :help version6<Enter> for version info"
+msgstr "zadajte :help version6<Enter> pre informácie o verzii"
+
+#: version.c:1028
+msgid "Running in Vi compatible mode"
+msgstr "Be¾ím v re¾ime kompatibility s Vi"
+
+#: version.c:1029
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "zadajte :set nocp<Enter> pre implicitné nastavenie Vim"
+
+#: version.c:1030
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "podrobnej¹ie informácie získate pomocou :help cp-default<Enter>"
+
+#: version.c:1045
+msgid "menu Help->Orphans for information "
+msgstr "bli¾¹ie informácie v menu Pomocník->Samostatné"
+
+#: version.c:1047
+msgid "Running modeless, typed text is inserted"
+msgstr "Spú¹»am modeless, písaný text je vlo¾ený"
+
+#: version.c:1048
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "menu Úpravy->Globálne mo¾nosti->Prepnú» re¾im vlo¾enia "
+
+#: version.c:1049
+msgid " for two modes "
+msgstr " pre dva re¾imy "
+
+#: version.c:1053
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "menu Úpravy->Globálne mo¾nostt->Prepnú» Vi kompatibilný re¾ím"
+
+#: version.c:1054
+msgid " for Vim defaults "
+msgstr " pre predvolené vlastnosti Vim "
+
+#: version.c:1100
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "VAROVANIE: detekované Windows 95/98/ME"
+
+#: version.c:1103
+msgid "type :help windows95<Enter> for info on this"
+msgstr "zadajte :help windows95<Enter> pre podrobnej¹ie informácie"
+
+#: window.c:201
+msgid "E441: There is no preview window"
+msgstr "E441: Nenájdené ¾iadne okno náhµadu"
+
+#: window.c:580
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: Okno sa nedá rozdeli» zároveò topleft a botright"
+
+#: window.c:1339
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Nedá sa rotova», ak je iné okno rozdelené"
+
+#: window.c:1841
+msgid "E444: Cannot close last window"
+msgstr "E444: Posledné okno sa nedá zatvori»"
+
+#: window.c:2505
+msgid "Already only one window"
+msgstr "U¾ existuje iba jedno okno"
+
+#: window.c:2552
+msgid "E445: Other window contains changes"
+msgstr "E445: Iné okno obsahuje zmeny"
+
+#: window.c:4379
+msgid "E446: No file name under cursor"
+msgstr "E446: Pod kurzorom sa nenachádza názov súboru"
+
+#: window.c:4498
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Súbor \"%s\" sa nedá v cdpath nájs»"
+
+#: ../GvimExt/gvimext.cpp:586
+msgid "Edit with &multiple Vims"
+msgstr "Upravi» s viacnásobný&m Vimom"
+
+#: ../GvimExt/gvimext.cpp:592
+msgid "Edit with single &Vim"
+msgstr "Upravi» s jedným &Vimom"
+
+#: ../GvimExt/gvimext.cpp:604
+msgid "Edit with &Vim"
+msgstr "Upravi» s &Vimom"
+
+#. Now concatenate
+#: ../GvimExt/gvimext.cpp:628
+msgid "Edit with existing Vim - &"
+msgstr "Upravi» s existujúcim Vimom - &"
+
+#: ../GvimExt/gvimext.cpp:752
+msgid "Edits the selected file(s) with Vim"
+msgstr "Upravi» vybrané súbory s Vimom"
+
+#: ../GvimExt/gvimext.cpp:891 ../GvimExt/gvimext.cpp:969
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "Chyba vytváracieho procesu: Skontrolujte, èi je gvim vo va¹ej ceste!"
+
+#: ../GvimExt/gvimext.cpp:892 ../GvimExt/gvimext.cpp:906
+#: ../GvimExt/gvimext.cpp:970
+msgid "gvimext.dll error"
+msgstr "chyba gvimext.dll"
+
+#: ../GvimExt/gvimext.cpp:905
+msgid "Path length too long!"
+msgstr "Príli¹ dlhá cesta!"
+
+#: globals.h:900
+msgid "--No lines in buffer--"
+msgstr "--Buffer neobsahuje ¾iadny riadok--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1042
+msgid "Command aborted"
+msgstr "Príkaz preru¹ený"
+
+#: globals.h:1043
+msgid "Argument required"
+msgstr "Je vy¾adovaný argument"
+
+#: globals.h:1044
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: po \\ by malo nasledova» /. ? alebo &"
+
+#: globals.h:1046
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr ""
+"E11: Chybný príkaz v okne príkazového riadku; <Enter> spustíte, CTRL-C "
+"vypnete"
+
+#: globals.h:1048
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Príkaz nie je z exrc/vimrc v aktuálnom adresári alebo pri hµadaní tagu "
+"povolený."
+
+#: globals.h:1049
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Súbor existuje (pou¾ite ! pre vynútenie)"
+
+#: globals.h:1050
+msgid "Command failed"
+msgstr "Príkaz zlyhal"
+
+#: globals.h:1051
+msgid "Internal error"
+msgstr "Vnútorná chyba"
+
+#: globals.h:1052
+msgid "Interrupted"
+msgstr "Preru¹ené"
+
+#: globals.h:1053
+msgid "E14: Invalid address"
+msgstr "E14: Chybná adresa"
+
+#: globals.h:1054
+msgid "Invalid argument"
+msgstr "Chybný argument"
+
+#: globals.h:1055
+#, c-format
+msgid "Invalid argument: %s"
+msgstr "Chybný argument: %s"
+
+#: globals.h:1057
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Chybný výraz: %s"
+
+#: globals.h:1059
+msgid "E16: Invalid range"
+msgstr "E16: Chybný rozsah"
+
+#: globals.h:1060
+msgid "Invalid command"
+msgstr "Chybný príkaz"
+
+#: globals.h:1062
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" je adresárom"
+
+#: globals.h:1065
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Neoèekávané znaky pred '='"
+
+#: globals.h:1067
+msgid "E19: Mark has invalid line number"
+msgstr "E19: Znaèka má chybné èíslo riadku"
+
+#: globals.h:1068
+msgid "E20: Mark not set"
+msgstr "E20: Znaèka nie je nastavená"
+
+#: globals.h:1069
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Nedá sa meni», je nastavená voµba 'modifiable'"
+
+#: globals.h:1070
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Skript vnorený príli¹ hlboko"
+
+#: globals.h:1071
+msgid "E23: No alternate file"
+msgstr "E23: ®iadny alternatívny súbor"
+
+#: globals.h:1072
+msgid "E24: No such abbreviation"
+msgstr "E24: Taká skratka neexistuje"
+
+#: globals.h:1073
+msgid "No ! allowed"
+msgstr "! nie je povolené"
+
+#: globals.h:1075
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: Nedá sa pou¾í» GUI: nebolo zapnuté pri preklade programu"
+
+#: globals.h:1078
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: Nedá sa pou¾í» hebrejský re¾im: nebol zapnutý pri preklade programu\n"
+
+#: globals.h:1081
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: Nedá sa pou¾í» farsi re¾im: nebol zapnutý pri preklade programu\n"
+
+#: globals.h:1084
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Skupina zvíraznenia %s neexistuje"
+
+#: globals.h:1086
+msgid "E29: No inserted text yet"
+msgstr "E29: Zatiaµ nie je ¾iadny vlo¾ený text"
+
+#: globals.h:1087
+msgid "E30: No previous command line"
+msgstr "E30: ®iadny predchádzajúci príkazový riadok"
+
+#: globals.h:1088
+msgid "E31: No such mapping"
+msgstr "E31: ®iadne také mapovanie"
+
+#: globals.h:1089
+msgid "No match"
+msgstr "®iadna zhoda"
+
+#: globals.h:1090
+#, c-format
+msgid "No match: %s"
+msgstr "®iadna zhoda: %s"
+
+#: globals.h:1091
+msgid "E32: No file name"
+msgstr "E32: ®iadny názov súboru"
+
+#: globals.h:1092
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: ®iadny predchádzajúci prislúchajúci správny výraz"
+
+#: globals.h:1093
+msgid "E34: No previous command"
+msgstr "E34: ®iadny predchádzajúci príkaz"
+
+#: globals.h:1094
+msgid "E35: No previous regular expression"
+msgstr "E35: ®iadny predchádzajúci regulárny výraz"
+
+#: globals.h:1095
+msgid "No range allowed"
+msgstr "Rozsah nie je povolený"
+
+#: globals.h:1097
+msgid "E36: Not enough room"
+msgstr "E36: Nedostatok miesta"
+
+#: globals.h:1099
+#, c-format
+msgid "Can't create file %s"
+msgstr "Nedá sa vytvori» súbor %s"
+
+#: globals.h:1100
+msgid "Can't get temp file name"
+msgstr "Nedá sa získa» názov doèasného súboru"
+
+#: globals.h:1101
+#, c-format
+msgid "Can't open file %s"
+msgstr "Nedá sa otvori» súbor %s"
+
+#: globals.h:1102
+#, c-format
+msgid "Can't read file %s"
+msgstr "Nedá sa èíta» súbor %s"
+
+#: globals.h:1103
+msgid "E37: No write since last change (use ! to override)"
+msgstr "E37: Neulo¾ené zmeny (pou¾ite ! pre vynútenie)"
+
+#: globals.h:1104
+msgid "E38: Null argument"
+msgstr "E38: Nulový argument"
+
+#: globals.h:1106
+msgid "E39: Number expected"
+msgstr "E39: Oèakávané èíslo"
+
+#: globals.h:1109
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Nedá sa otvori» chybový súbor %s"
+
+#: globals.h:1112
+msgid "E41: Out of memory!"
+msgstr "E41: Nedostatok pamäti!"
+
+#: globals.h:1115
+msgid "Pattern not found"
+msgstr "Vzor nenájdený"
+
+#: globals.h:1117
+#, c-format
+msgid "Pattern not found: %s"
+msgstr "Vzor nenájdený: %s"
+
+#: globals.h:1118
+msgid "Argument must be positive"
+msgstr "Argument musí by» kladný"
+
+#: globals.h:1120
+msgid "E42: No Errors"
+msgstr "E42: ®iadne chyby"
+
+#: globals.h:1122
+msgid "E43: Damaged match string"
+msgstr "E43: Po¹kodený re»azac pre vyhµadávanie"
+
+#: globals.h:1123
+msgid "E44: Corrupted regexp program"
+msgstr "E44: Po¹kodený regexp program"
+
+#: globals.h:1124
+msgid "E45: 'readonly' option is set (use ! to override)"
+msgstr "E45: nastavená voµba 'iba_pre_èítanie' (pou¾ite ! pre vynútenie)"
+
+#: globals.h:1126
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Nedá sa nastavi» premenná iba_pre_èítanie \"%s\""
+
+#: globals.h:1129
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Chyba pri èítaní chybového súboru"
+
+#: globals.h:1132
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: Nie je v bezpeènostnej schránke povolené"
+
+#: globals.h:1134
+msgid "E49: Invalid scroll size"
+msgstr "E49: Chybná hodnota premennej 'scroll'"
+
+#: globals.h:1135
+msgid "E91: 'shell' option is empty"
+msgstr "E91: voµba 'shell' je prázdna"
+
+#: globals.h:1136
+msgid "E72: Close error on swap file"
+msgstr "E72: Chyba pri uzatváraní odkladacieho súboru"
+
+#: globals.h:1137
+msgid "E73: tag stack empty"
+msgstr "E73: zoznam tagov je prázdny"
+
+#: globals.h:1138
+msgid "E74: Command too complex"
+msgstr "E74: Príkaz je príli¹ zlo¾itý"
+
+#: globals.h:1139
+msgid "E75: Name too long"
+msgstr "E75: Názov je príli¹ dlhý"
+
+#: globals.h:1140
+msgid "E76: Too many ["
+msgstr "E76: Príli¹ mnoho ["
+
+#: globals.h:1141
+msgid "E77: Too many file names"
+msgstr "E77: Príli¹ mnoho názvov súborov"
+
+#: globals.h:1142
+msgid "Trailing characters"
+msgstr "Nadbytoèné znaky na konci"
+
+#: globals.h:1143
+msgid "E78: Unknown mark"
+msgstr "E78: Neznáma znaèka"
+
+#: globals.h:1144
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Nedá sa expandova» ¾olíkové znaky (wildcards)"
+
+#: globals.h:1145
+msgid "E80: Error while writing"
+msgstr "E80: Chyba pri ukladaní"
+
+#: globals.h:1146
+msgid "Zero count"
+msgstr "Nulový poèet"
+
+#: globals.h:1148
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: Pou¾itie <SID> mimo kontext skriptu"
+
+#: globals.h:1151
+msgid "E449: Invalid expression received"
+msgstr "E449: Bol prijatý chybný výraz"
+
diff --git a/src/po/sv.po b/src/po/sv.po
new file mode 100644
index 000000000..4f84b2173
--- /dev/null
+++ b/src/po/sv.po
@@ -0,0 +1,6516 @@
+# Swedish translation for Vim.
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# Johan Svedberg <johan@svedberg.pp.se>, 2003.
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim 6.2\n"
+"POT-Creation-Date: 2004-01-30 11:57+0100\n"
+"PO-Revision-Date: 2004-04-24 21:54+0200\n"
+"Last-Translator: Johan Svedberg <johan@svedberg.pp.se>\n"
+"Language-Team: Swedish <sv@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: Kan inte allokera någon buffert, avslutar..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: Kan inte allokera buffert, använder en annan..."
+
+#: buffer.c:797
+msgid "E515: No buffers were unloaded"
+msgstr "E515: Inga buffertar blev urladdade"
+
+#: buffer.c:799
+msgid "E516: No buffers were deleted"
+msgstr "E516: Inga buffertar blev borttagna"
+
+#: buffer.c:801
+msgid "E517: No buffers were wiped out"
+msgstr "E517: Inga buffertar blev utraderade"
+
+#: buffer.c:809
+msgid "1 buffer unloaded"
+msgstr "1 buffert laddades ur"
+
+#: buffer.c:811
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "%d buffertar laddades ur"
+
+#: buffer.c:816
+msgid "1 buffer deleted"
+msgstr "1 buffert borttagen"
+
+#: buffer.c:818
+#, c-format
+msgid "%d buffers deleted"
+msgstr "%d buffertar borttagna"
+
+#: buffer.c:823
+msgid "1 buffer wiped out"
+msgstr "1 buffert utraderad"
+
+#: buffer.c:825
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "%d buffertar utraderade"
+
+#: buffer.c:886
+msgid "E84: No modified buffer found"
+msgstr "E84: Ingen modifierad buffert hittad"
+
+#. back where we started, didn't find anything.
+#: buffer.c:925
+msgid "E85: There is no listed buffer"
+msgstr "E85: Det finns inga listade buffertar"
+
+#: buffer.c:937
+msgid "E86: Buffer %ld does not exist"
+msgstr "E86: Buffert %ld existerar inte"
+
+#: buffer.c:940
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: Kan inte gå bortom sista buffert"
+
+#: buffer.c:942
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: Kan inte gå före första buffert"
+
+#: buffer.c:980
+#, c-format
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr ""
+"E89: Ingen skrivning sedan senaste ändring för buffert %ld (lägg till ! för "
+"att tvinga)"
+
+#: buffer.c:997
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: Kan inte ladda ur senaste buffert"
+
+#: buffer.c:1530
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: Varning: Lista över filnamn flödar över"
+
+#: buffer.c:1701
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: Buffer %ld hittades inte"
+
+#: buffer.c:1932
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: Fler än en träff för %s"
+
+#: buffer.c:1934
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: Ingen matchande buffert för %s"
+
+#: buffer.c:2329 ex_docmd.c:6691
+#, c-format
+msgid "line %ld"
+msgstr "rad %ld"
+
+#: buffer.c:2412
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: Buffer med det här namnet existerar redan"
+
+#: buffer.c:2705
+msgid " [Modified]"
+msgstr " [Modifierad]"
+
+#: buffer.c:2710
+msgid "[Not edited]"
+msgstr "[Inte redigerad]"
+
+#: buffer.c:2715
+msgid "[New file]"
+msgstr "[Ny fil]"
+
+#: buffer.c:2716
+msgid "[Read errors]"
+msgstr "[Läsfel]"
+
+#: buffer.c:2718 fileio.c:1939
+msgid "[readonly]"
+msgstr "[skrivskyddad]"
+
+#: buffer.c:2739
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "1 rad --%d%%--"
+
+#: buffer.c:2741
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "%ld rader --%d%%--"
+
+#: buffer.c:2748
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "rad %ld av %ld --%d%%-- kol "
+
+#: buffer.c:2849
+msgid "[No file]"
+msgstr "[Ingen fil]"
+
+#. must be a help buffer
+#: buffer.c:2889
+msgid "help"
+msgstr "hjälp"
+
+#: buffer.c:3448 screen.c:4996
+msgid "[help]"
+msgstr "[hjälp]"
+
+#: buffer.c:3480 screen.c:5002
+msgid "[Preview]"
+msgstr "[Förhandsvisning]"
+
+#: buffer.c:3760
+msgid "All"
+msgstr "Alla"
+
+#: buffer.c:3760
+msgid "Bot"
+msgstr "Bott"
+
+#: buffer.c:3762
+msgid "Top"
+msgstr "Topp"
+
+#: buffer.c:4508
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# Buffertlista:\n"
+
+#: buffer.c:4541
+msgid "[Error List]"
+msgstr "[Fellista]"
+
+#: buffer.c:4554 memline.c:1513
+msgid "[No File]"
+msgstr "[Ingen fil]"
+
+#: buffer.c:4857
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- Tecken ---"
+
+#: buffer.c:4876
+#, c-format
+msgid "Signs for %s:"
+msgstr "Tecken för %s:"
+
+#: buffer.c:4882
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " line=%ld id=%d namn%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: Kan inte skilja fler än %ld buffertar"
+
+#: diff.c:651
+msgid "E97: Cannot create diffs"
+msgstr "E97: Kan inte skapa skiljare"
+
+#: diff.c:750
+msgid "Patch file"
+msgstr "Patchfil"
+
+#: diff.c:1001
+msgid "E98: Cannot read diff output"
+msgstr "E98: Kan inte läsa skiljeutdata"
+
+#: diff.c:1742
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Aktuell buffert är inte i skiljeläge"
+
+#: diff.c:1754
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: Ingen annan buffert i skiljeläge"
+
+#: diff.c:1762
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr ""
+"E101: Fler än två buffertar i skiljeläge, vet inte vilken som ska användas"
+
+#: diff.c:1785
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: Kan inte hitta buffert \"%s\""
+
+#: diff.c:1791
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: Buffert \"%s\" är inte i skiljeläge"
+
+#: digraph.c:2172
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: Escape inte tillåtet i digraf"
+
+#: digraph.c:2344
+msgid "E544: Keymap file not found"
+msgstr "E544: Keymap-fil hittades inte"
+
+#: digraph.c:2371
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: Användning av :loadkeymap utanför en körd fil"
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " Nyckelordskomplettering (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " ^X-läge (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " Lokal nyckelordskomplettering (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " Helradskomplettering (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " Filnamnskomplettering (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " Taggkomplettering (^]/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " Sökvägsmönsterkomplettering (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " Definitionskomplettering (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " Ordbokskomplettering (^K/^N/^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Tesaurkomplettering (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " Kommandoradskomplettering (^V/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Stötte på slutet på stycket"
+
+#: edit.c:953
+msgid "'thesaurus' option is empty"
+msgstr "'thesaurus'-flagga är tom"
+
+#: edit.c:1157
+msgid "'dictionary' option is empty"
+msgstr "'dictionary'-flagga är tom"
+
+#: edit.c:2154
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "Söker igenom ordbok: %s"
+
+#: edit.c:2360
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (infoga) Rulla (^E/^Y)"
+
+#: edit.c:2362
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (ersätt) Rulla (^E/^Y)"
+
+#: edit.c:2676
+#, c-format
+msgid "Scanning: %s"
+msgstr "Söker igenom: %s"
+
+#: edit.c:2711
+msgid "Scanning tags."
+msgstr "Söker igenom taggar."
+
+#: edit.c:3373
+msgid " Adding"
+msgstr " Lägger till"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3422
+msgid "-- Searching..."
+msgstr "-- Söker..."
+
+#: edit.c:3478
+msgid "Back at original"
+msgstr "Tillbaka på orginalet"
+
+#: edit.c:3483
+msgid "Word from other line"
+msgstr "Ord från annan rad"
+
+#: edit.c:3488
+msgid "The only match"
+msgstr "Den enda träffen"
+
+#: edit.c:3547
+#, c-format
+msgid "match %d of %d"
+msgstr "träff %d av %d"
+
+#: edit.c:3550
+#, c-format
+msgid "match %d"
+msgstr "träff %d"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:1011
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: Okänd variabel: \"%s\""
+
+#: eval.c:1307
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: Saknar hakparantes: %s"
+
+#: eval.c:1412 eval.c:1426
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Ingen sådan variabel: \"%s\""
+
+#: eval.c:1682
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: Saknar ':' efter '?'"
+
+#: eval.c:2298
+msgid "E110: Missing ')'"
+msgstr "E110: Saknar ')'"
+
+#: eval.c:2355
+msgid "E111: Missing ']'"
+msgstr "E111: Saknar ']'"
+
+#: eval.c:2431
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: Flaggnamn saknas: %s"
+
+#: eval.c:2449
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: Okänd flagga: %s"
+
+#: eval.c:2520
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: Saknar citattecken: %s"
+
+#: eval.c:2663
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: Saknar citattecken: %s"
+
+#: eval.c:3018
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: Ogiltiga argument för funktion %s"
+
+#: eval.c:3048
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: Okänd funktion: %s"
+
+#: eval.c:3049
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: För många argument till funktion: %s"
+
+#: eval.c:3050
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: Inte tillräckligt med argument till funktion: %s"
+
+#: eval.c:3051
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: Använder <SID> inte i skriptsammanhang: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3641 gui.c:4260 gui_gtk.c:2001
+msgid "&Ok"
+msgstr "&Ok"
+
+#: eval.c:4180
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld rader: "
+
+#: eval.c:5406
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&OK\n"
+"&Avbryt"
+
+#: eval.c:5446
+msgid "called inputrestore() more often than inputsave()"
+msgstr "anropade inputrestore() oftare än inputsave()"
+
+#: eval.c:5904
+msgid "E655: Too much symbolic links (cycle?)"
+msgstr "E655: För många symboliska länkar (slinga?)"
+
+#: eval.c:6523
+msgid "E240: No connection to Vim server"
+msgstr "E240: Ingen anslutning till Vim-server"
+
+#: eval.c:6620
+msgid "E277: Unable to read a server reply"
+msgstr "E277: Kunde inte läsa ett serversvar"
+
+#: eval.c:6648
+msgid "E258: Unable to send to client"
+msgstr "E258: Kunde inte sända till klient"
+
+#: eval.c:6696
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: Kunde inte sända till %s"
+
+#: eval.c:6796
+msgid "(Invalid)"
+msgstr "(Ogiltig)"
+
+#: eval.c:7945
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: Odefinierad variabel: %s"
+
+#: eval.c:8377
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E461: Otillåtet variabelnamn: %s"
+
+#: eval.c:8665
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: Funktionen %s existerar redan, lägg till ! för att ersätta den"
+
+#: eval.c:8732
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: Odefinierad funktion: %s"
+
+#: eval.c:8745
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: Saknar '(': %s"
+
+#: eval.c:8778
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: Otillåtet argument: %s"
+
+#: eval.c:8857
+msgid "E126: Missing :endfunction"
+msgstr "E126: Saknar :endfunction"
+
+#: eval.c:8940
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: Kan inte omdefiniera funktion %s: Den används"
+
+#: eval.c:9008
+msgid "E129: Function name required"
+msgstr "E129: Funktionsnamn krävs"
+
+#: eval.c:9059
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: Funktionsnamn måste börja med en versal: %s"
+
+#: eval.c:9251
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: Odefinierad funktion: %s"
+
+#: eval.c:9256
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: Kan inte ta bort funktion %s: Den används"
+
+#: eval.c:9304
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: Djupet på funktionsanropet är högre än 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:9357
+#, c-format
+msgid "calling %s"
+msgstr "anropar %s"
+
+#: eval.c:9419
+#, c-format
+msgid "%s aborted"
+msgstr "%s avbröts"
+
+#: eval.c:9421
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s returnerar #%ld"
+
+#: eval.c:9428
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s returnerar \"%s\""
+
+#. always scroll up, don't overwrite
+#: eval.c:9444 ex_cmds2.c:2292
+#, c-format
+msgid "continuing in %s"
+msgstr "fortsätter i %s"
+
+#: eval.c:9470
+msgid "E133: :return not inside a function"
+msgstr "E133: :return inte inom en funktion"
+
+#: eval.c:9801
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# globala variabler:\n"
+
+#: ex_cmds2.c:92
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "Går in i felsökningsläge. Skriv \"cont\" för att fortsätta."
+
+#: ex_cmds2.c:96 ex_docmd.c:906
+#, c-format
+msgid "line %ld: %s"
+msgstr "rad %ld: %s"
+
+#: ex_cmds2.c:98
+#, c-format
+msgid "cmd: %s"
+msgstr "kommando: %s"
+
+#: ex_cmds2.c:290
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "Brytpunkt i \"%s%s\" rad %ld"
+
+#: ex_cmds2.c:540
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: Brytpunkt hittades inte: %s"
+
+#: ex_cmds2.c:566
+msgid "No breakpoints defined"
+msgstr "Inga brytpunkter definierade"
+
+#: ex_cmds2.c:571
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s rad %ld"
+
+#: ex_cmds.c:2097 ex_cmds.c:2362 ex_cmds2.c:763
+msgid "Save As"
+msgstr "Spara som"
+
+#: ex_cmds2.c:786
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "Spara ändringar till \"%.*s\"?"
+
+#: ex_cmds2.c:788 ex_docmd.c:9085
+msgid "Untitled"
+msgstr "Namnlös"
+
+#: ex_cmds2.c:915
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: Ingen skrivning sedan senaste ändring för buffert \"%s\""
+
+#: ex_cmds2.c:984
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "Varning: Gick in i andra buffertar oväntat (kontrollera autokommandon)"
+
+#: ex_cmds2.c:1387
+msgid "E163: There is only one file to edit"
+msgstr "E163: Det finns bara en fil att redigera"
+
+#: ex_cmds2.c:1389
+msgid "E164: Cannot go before first file"
+msgstr "E164: Kan inte gå före första filen"
+
+#: ex_cmds2.c:1391
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: Kan inte gå bortom sista filen"
+
+#: ex_cmds2.c:1842
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Söker efter \"%s\" i \"%s\""
+
+#: ex_cmds2.c:1864
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Söker efter \"%s\""
+
+#: ex_cmds2.c:1885
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "hittades inte i 'runtimepath': \"%s\""
+
+#: ex_cmds2.c:1919
+msgid "Source Vim script"
+msgstr "Läs Vim-skript"
+
+#: ex_cmds2.c:2109
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "Kan inte läsa en katalog: \"%s\""
+
+#: ex_cmds2.c:2147
+#, c-format
+msgid "could not source \"%s\""
+msgstr "kunde inte läsa \"%s\""
+
+#: ex_cmds2.c:2149
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "rad %ld: kunde inte läsa \"%s\""
+
+#: ex_cmds2.c:2163
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "läser \"%s\""
+
+#: ex_cmds2.c:2165
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "rad %ld: läser \"%s\""
+
+#: ex_cmds2.c:2290
+#, c-format
+msgid "finished sourcing %s"
+msgstr "läste klart %s"
+
+#: ex_cmds2.c:2634
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: Varning: Fel radavskiljare, ^M kan saknas"
+
+#: ex_cmds2.c:2683
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :scriptencoding används utanför en körd fil"
+
+#: ex_cmds2.c:2716
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish används utanför en körd fil"
+
+#: ex_cmds2.c:3159
+#, c-format
+msgid "Page %d"
+msgstr "Sida %d"
+
+#: ex_cmds2.c:3315
+msgid "No text to be printed"
+msgstr "Ingen text att skriva ut"
+
+#: ex_cmds2.c:3393
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "Skriver ut sida %d (%d%%)"
+
+#: ex_cmds2.c:3405
+#, c-format
+msgid " Copy %d of %d"
+msgstr " Kopia %d av %d"
+
+#: ex_cmds2.c:3463
+#, c-format
+msgid "Printed: %s"
+msgstr "Skrev ut: %s"
+
+#: ex_cmds2.c:3470
+msgid "Printing aborted"
+msgstr "Utskrift avbruten"
+
+#: ex_cmds2.c:3835
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: Fel vid skrivning av utdata till PostScript-fil"
+
+#: ex_cmds2.c:4110
+#, c-format
+msgid "E624: Can't open file \"%s\""
+msgstr "E624: Kan inte öppna fil \"%s\""
+
+#: ex_cmds2.c:4120 ex_cmds2.c:4745
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: Kan inte läsa PostScript-resursfil \"%s\""
+
+#: ex_cmds2.c:4128
+#, c-format
+msgid "E618: file \"%s\" is not a PostScript resource file"
+msgstr "E618: fil \"%s\" är inte en PostScript-resursfil"
+
+#: ex_cmds2.c:4143 ex_cmds2.c:4163 ex_cmds2.c:4178 ex_cmds2.c:4200
+#, c-format
+msgid "E619: file \"%s\" is not a supported PostScript resource file"
+msgstr "E619: fil \"%s\" är inte en PostScript-resursfil som stöds"
+
+#: ex_cmds2.c:4230
+#, c-format
+msgid "E621: \"%s\" resource file has wrong version"
+msgstr "E621: \"%s\"-källfilen har fel version"
+
+#: ex_cmds2.c:4697
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: Kan inte öppna PostScript-utfil"
+
+#: ex_cmds2.c:4730
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: Kan inte öppna fil \"%s\""
+
+#: ex_cmds2.c:4849
+msgid "E456: Can't find PostScript resource file \"prolog.ps\""
+msgstr "E456: Kan inte hitta PostScript-källfilen \"prolog.ps\""
+
+#: ex_cmds2.c:4880
+#, c-format
+msgid "E456: Can't find PostScript resource file \"%s.ps\""
+msgstr "E456: Kan inte hitta PostScript-källfilen \"%s.ps\""
+
+#: ex_cmds2.c:4898
+#, c-format
+msgid "E620: Unable to convert from multi-byte to \"%s\" encoding"
+msgstr "E620: Kunde inte konvertera från multi-byte till \"%s\" encoding"
+
+#: ex_cmds2.c:5023
+msgid "Sending to printer..."
+msgstr "Skickar till skrivare..."
+
+#: ex_cmds2.c:5027
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: Misslyckades med att skriva ut PostScript-fil"
+
+#: ex_cmds2.c:5029
+msgid "Print job sent."
+msgstr "Skrivarjobb skickat."
+
+#: ex_cmds2.c:5438
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Aktuellt %sspråk: \"%s\""
+
+#: ex_cmds2.c:5449
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: Kan inte sätta språk till \"%s\""
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Hex %02x, Oktalt %03o"
+
+#: ex_cmds.c:118
+msgid "> %d, Hex %04x, Octal %o"
+msgstr "> %d, Hex %04x, Oktalt %o"
+
+#: ex_cmds.c:119
+msgid "> %d, Hex %08x, Octal %o"
+msgstr "> %d, Hex %08x, Oktalt %o"
+
+#: ex_cmds.c:430
+msgid "E134: Move lines into themselves"
+msgstr "E134: Flytta rader in i dem själva"
+
+#: ex_cmds.c:499
+msgid "1 line moved"
+msgstr "1 rad flyttad"
+
+#: ex_cmds.c:501
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld rader flyttade"
+
+#: ex_cmds.c:924
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld rader filtrerade"
+
+#: ex_cmds.c:952
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *Filter*-Autokommandon får inte ändra aktuell buffert"
+
+#: ex_cmds.c:1037
+msgid "[No write since last change]\n"
+msgstr "[Ingen skrivning sedan senaste ändring]\n"
+
+#: ex_cmds.c:1283
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s på rad: "
+
+#: ex_cmds.c:1288
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: För många fel, hoppar över resten av filen"
+
+#: ex_cmds.c:1323
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Läser viminfo-fil \"%s\"%s%s%s"
+
+#: ex_cmds.c:1324
+msgid " info"
+msgstr " info"
+
+#: ex_cmds.c:1325
+msgid " marks"
+msgstr " märken"
+
+#: ex_cmds.c:1326
+msgid " FAILED"
+msgstr " MISSLYCKADES"
+
+#: ex_cmds.c:1418
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Viminfo-fil är inte skrivbar: %s"
+
+#: ex_cmds.c:1543
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: Kan inte skriva viminfo-fil %s!"
+
+#: ex_cmds.c:1551
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "Skriver viminfo-fil \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1649
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# Den här viminfo-filen genererades av Vim %s.\n"
+
+#: ex_cmds.c:1651
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Du får redigera den om du är försiktig!\n"
+"\n"
+
+#: ex_cmds.c:1653
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# Värde av 'encoding' när den här filen blev skriven\n"
+
+#: ex_cmds.c:1752
+msgid "Illegal starting char"
+msgstr "Otillåtet starttecken"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2140
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: Filen är inläst i en annan buffert"
+
+#: ex_cmds.c:2174
+msgid "Write partial file?"
+msgstr "Skriv ofullständig fil?"
+
+#: ex_cmds.c:2181
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: Använd ! för att skriva ofullständig buffert"
+
+#: ex_cmds.c:2296
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Skriv över befintlig fil \"%.*s\"?"
+
+#: ex_cmds.c:2367
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: Inget filnamn för buffert %ld"
+
+#: ex_cmds.c:2405
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: Filen skrevs inte: Skrivning är inaktiverat med 'write'-flaggan"
+
+#: ex_cmds.c:2425
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"'readonly' flaggan är satt för \"%.*s\".\n"
+"Önskar du att skriva ändå?"
+
+#: ex_cmds.c:2597
+msgid "Edit File"
+msgstr "Redigera fil"
+
+#: ex_cmds.c:3170
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Autokommandon tog oväntat bort ny buffert %s"
+
+#: ex_cmds.c:3302
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: ickenumeriskt argument till :z"
+
+#: ex_cmds.c:3387
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: Skalkommandon inte tillåtna i rvim"
+
+#: ex_cmds.c:3494
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Reguljära uttryck kan inte vara åtskilda av bokstäver"
+
+#: ex_cmds.c:3840
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "ersätt med %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4216
+msgid "(Interrupted) "
+msgstr "(Avbruten) "
+
+#: ex_cmds.c:4220
+msgid "1 substitution"
+msgstr "1 ersättning"
+
+#: ex_cmds.c:4222
+#, c-format
+msgid "%ld substitutions"
+msgstr "%ld ersättningar"
+
+#: ex_cmds.c:4225
+msgid " on 1 line"
+msgstr " på 1 rad"
+
+#: ex_cmds.c:4227
+#, c-format
+msgid " on %ld lines"
+msgstr " på %ld rader"
+
+#: ex_cmds.c:4278
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: Kan inte göra :global rekursivt"
+
+#: ex_cmds.c:4313
+msgid "E148: Regular expression missing from global"
+msgstr "E148: Reguljärt uttryck saknas från global"
+
+#: ex_cmds.c:4362
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "Mönster funnet i varje rad: %s"
+
+#: ex_cmds.c:4443
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Senaste ersättningssträng:\n"
+"$"
+
+#: ex_cmds.c:4556
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: Tyvärr, ingen hjälp för %s"
+
+#: ex_cmds.c:4590
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "Tyvärr, hjälpfil \"%s\" hittades inte"
+
+#: ex_cmds.c:5067
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: Inte en katalog: %s"
+
+#: ex_cmds.c:5095
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: Kan inte öppna %s för skrivning"
+
+#: ex_cmds.c:5130
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: Kunde inte öppna %s för läsning"
+
+#: ex_cmds.c:5209
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: Duplicerad tagg \"%s\" i fil %s"
+
+#: ex_cmds.c:5316
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: Okänt signaturkommando: %s"
+
+#: ex_cmds.c:5336
+msgid "E156: Missing sign name"
+msgstr "E156: Saknar signaturnamn"
+
+#: ex_cmds.c:5382
+msgid "E612: Too many signs defined"
+msgstr "E612: För många signaturer definierade"
+
+#: ex_cmds.c:5449
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: Ogiltig signaturtext: %s"
+
+#: ex_cmds.c:5480 ex_cmds.c:5666
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: Okänd signatur: %s"
+
+#: ex_cmds.c:5526
+msgid "E159: Missing sign number"
+msgstr "E159: Saknar signaturnummer"
+
+#: ex_cmds.c:5606
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: Ogiltigt buffertnamn: %s"
+
+#: ex_cmds.c:5645
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Ogiltigt signatur-ID: %ld"
+
+#: ex_cmds.c:5715
+msgid " (NOT FOUND)"
+msgstr " (INTE HITTADE)"
+
+#: ex_cmds.c:5717
+msgid " (not supported)"
+msgstr " (stöds inte)"
+
+#: ex_cmds.c:5816
+msgid "[Deleted]"
+msgstr "[Borttagen]"
+
+#: ex_docmd.c:490
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "Går in i Ex-läge. Skriv \"visual\" för att gå till Normal-läge."
+
+#. must be at EOF
+#: ex_docmd.c:526
+msgid "E501: At end-of-file"
+msgstr "E501: Vid filslut"
+
+#: ex_docmd.c:632
+msgid "E169: Command too recursive"
+msgstr "E169: Kommando för rekursivt"
+
+#: ex_docmd.c:1155
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: Undantag inte fångat: %s"
+
+#: ex_docmd.c:1241
+msgid "End of sourced file"
+msgstr "Slut på läst fil"
+
+#: ex_docmd.c:1242
+msgid "End of function"
+msgstr "Slut på funktion"
+
+#: ex_docmd.c:1706
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: Otydlig användning av användardefinierat kommando"
+
+#: ex_docmd.c:1720
+msgid "E492: Not an editor command"
+msgstr "E492: Inte ett redigerarkommando"
+
+#: ex_docmd.c:1810
+msgid "E478: Don't panic!"
+msgstr "E478: Få inte panik!"
+
+#: ex_docmd.c:1829
+msgid "E493: Backwards range given"
+msgstr "E493: Bakåtområde givet"
+
+#: ex_docmd.c:1838
+msgid "Backwards range given, OK to swap"
+msgstr "Bakåtområde givet, OK att växla"
+
+#: ex_docmd.c:1961
+msgid "E494: Use w or w>>"
+msgstr "E494: Använd w eller w>>"
+
+#: ex_docmd.c:3570
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: Tyvärr, kommandot är inte tillgängligt i den här versionen"
+
+#: ex_docmd.c:3756
+msgid "E172: Only one file name allowed"
+msgstr "E172: Bara ett filnamn tillåtet"
+
+#: ex_docmd.c:4320
+msgid "1 more file to edit. Quit anyway?"
+msgstr "1 fil till att redigera. Avsluta ändå?"
+
+#: ex_docmd.c:4323
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "%d filer till att redigera. Avsluta ändå?"
+
+#: ex_docmd.c:4330
+msgid "E173: 1 more file to edit"
+msgstr "E173: 1 fil till att redigera"
+
+#: ex_docmd.c:4332
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: %ld filer till att redigera"
+
+#: ex_docmd.c:4427
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: Kommando existerar redan: lägg till ! för att ersätta det"
+
+#: ex_docmd.c:4537
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Namn Arg Område Färdigt Definition"
+
+#: ex_docmd.c:4626
+msgid "No user-defined commands found"
+msgstr "Inga användardefinierade kommandon hittade"
+
+#: ex_docmd.c:4658
+msgid "E175: No attribute specified"
+msgstr "E175: Inga attribut angivna"
+
+#: ex_docmd.c:4710
+msgid "E176: Invalid number of arguments"
+msgstr "E176: Ogiltigt antal argument"
+
+#: ex_docmd.c:4725
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: Antal kan inte anges två gånger"
+
+#: ex_docmd.c:4735
+msgid "E178: Invalid default value for count"
+msgstr "E178: Ogiltigt standardvärde för antal"
+
+#: ex_docmd.c:4766
+msgid "E179: argument required for complete"
+msgstr "E179: argument krävs för komplettering"
+
+#: ex_docmd.c:4798
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: Ogiltigt kompletteringsvärde: %s"
+
+#: ex_docmd.c:4803
+msgid "E467: Custom completion requires a function argument"
+msgstr "E467: Specialkomplettering kräver ett funktionsargument"
+
+#: ex_docmd.c:4808
+msgid "E468: Completion argument only allowed for custom completion"
+msgstr "E468: Kompletteringsargument bara tillåtet för specialkomplettering"
+
+#: ex_docmd.c:4818
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: Ogiltigt attribut: %s"
+
+#: ex_docmd.c:4861
+msgid "E182: Invalid command name"
+msgstr "E182: Ogiltigt kommandonamn"
+
+#: ex_docmd.c:4876
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: Användardefinierade kommandon måste börja med en stor bokstav"
+
+#: ex_docmd.c:4946
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: Inget sådant användardefinierat kommando: %s"
+
+#: ex_docmd.c:5405
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: Kan inte hitta färgschema %s"
+
+#: ex_docmd.c:5413
+msgid "Greetings, Vim user!"
+msgstr "Välkommen, Vim-användare!"
+
+#: ex_docmd.c:6136
+msgid "Edit File in new window"
+msgstr "Redigera fil i nytt fönster"
+
+#: ex_docmd.c:6431
+msgid "No swap file"
+msgstr "Ingen växlingsfil"
+
+#: ex_docmd.c:6535
+msgid "Append File"
+msgstr "Lägg till fil"
+
+#: ex_docmd.c:6599
+msgid "E186: No previous directory"
+msgstr "E186: Ingen tidigare katalog"
+
+#: ex_docmd.c:6681
+msgid "E187: Unknown"
+msgstr "E187: Okänt"
+
+#: ex_docmd.c:6766
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: :winsize kräver två sifferargument"
+
+#: ex_docmd.c:6817
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "Fönsterposition: X %d, Y %d"
+
+#: ex_docmd.c:6822
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr ""
+"E188: Förskaffa fönsterposition inte implementerat för den här plattformen"
+
+#: ex_docmd.c:6832
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: :winpos kräver två sifferargument"
+
+#: ex_docmd.c:7111
+msgid "Save Redirection"
+msgstr "Spara omdirigering"
+
+#: ex_docmd.c:7292
+msgid "Save View"
+msgstr "Spara vy"
+
+#: ex_docmd.c:7293
+msgid "Save Session"
+msgstr "Spara session"
+
+#: ex_docmd.c:7295
+msgid "Save Setup"
+msgstr "Spara konfiguration"
+
+#: ex_docmd.c:7446
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" existerar (lägg till ! för att tvinga)"
+
+#: ex_docmd.c:7451
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: Kan inte öppna \"%s\" för skrivning"
+
+#. set mark
+#: ex_docmd.c:7475
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr ""
+"E191: Argument måste vara en bokstav eller framåt-/bakåtvänt citattecken"
+
+#: ex_docmd.c:7517
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: Rekursiv användning av :normal för djup"
+
+#: ex_docmd.c:8033
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: Inget alternativt filnamn att byta ut '#' med"
+
+#: ex_docmd.c:8064
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: inget autokommando-filnamn att ersätta \"<afile>\" med"
+
+#: ex_docmd.c:8072
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "E496: inget autokommando-buffernummer att ersätta \"<abuf>\" med"
+
+#: ex_docmd.c:8083
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr "E497: inget autokommando-träffnamn att byta ut \"<amatch>\" med"
+
+#: ex_docmd.c:8093
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr "E498: inget :source-filnamn att byta ut \"<sfile>\" med"
+
+#: ex_docmd.c:8134
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: Tomt filnamn för '%' or '#', fungerar bara med \":p:h\""
+
+#: ex_docmd.c:8136
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: Evaluerar till en tom sträng"
+
+#: ex_docmd.c:9067
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: Kan inte öppna viminfo-fil för läsning"
+
+#: ex_docmd.c:9240
+msgid "E196: No digraphs in this version"
+msgstr "E196: Inga digrafer i den här versionen"
+
+#: ex_eval.c:423
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr "E608: Kan inte :throw undantag med 'Vim'-prefix"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:509
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "Undantag kastade: %s"
+
+#: ex_eval.c:556
+#, c-format
+msgid "Exception finished: %s"
+msgstr "Undantag färdiga: %s"
+
+#: ex_eval.c:557
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "Undantag förkastade: %s"
+
+#: ex_eval.c:600 ex_eval.c:644
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, rad %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:618
+#, c-format
+msgid "Exception caught: %s"
+msgstr "Undantag fångade: %s"
+
+#: ex_eval.c:693
+#, c-format
+msgid "%s made pending"
+msgstr "%s gjordes avvaktande"
+
+#: ex_eval.c:696
+#, c-format
+msgid "%s resumed"
+msgstr "%s återupptagen"
+
+#: ex_eval.c:700
+#, c-format
+msgid "%s discarded"
+msgstr "%s förkastad"
+
+#: ex_eval.c:726
+msgid "Exception"
+msgstr "Undantag"
+
+#: ex_eval.c:732
+msgid "Error and interrupt"
+msgstr "Fel och avbrytet"
+
+#: ex_eval.c:734 gui.c:4259
+msgid "Error"
+msgstr "Fel"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:736
+msgid "Interrupt"
+msgstr "Avbryt"
+
+#: ex_eval.c:810
+msgid "E579: :if nesting too deep"
+msgstr "E579: :if nästlad för djupt"
+
+#: ex_eval.c:847
+msgid "E580: :endif without :if"
+msgstr "E580: :endif utan :if"
+
+#: ex_eval.c:891
+msgid "E581: :else without :if"
+msgstr "E581: :else utan :if"
+
+#: ex_eval.c:894
+msgid "E582: :elseif without :if"
+msgstr "E582: :elseif utan :if"
+
+#: ex_eval.c:901
+msgid "E583: multiple :else"
+msgstr "E583: flera :else"
+
+#: ex_eval.c:904
+msgid "E584: :elseif after :else"
+msgstr "E584: :elseif efter :else"
+
+#: ex_eval.c:971
+msgid "E585: :while nesting too deep"
+msgstr "E585: :while nästlad för djupt"
+
+#: ex_eval.c:1027
+msgid "E586: :continue without :while"
+msgstr "E586: :continue utan :while"
+
+#: ex_eval.c:1067
+msgid "E587: :break without :while"
+msgstr "E587: :break utan :while"
+
+#: ex_eval.c:1266
+msgid "E601: :try nesting too deep"
+msgstr "E601: :try nästlad för djupt"
+
+#: ex_eval.c:1346
+msgid "E603: :catch without :try"
+msgstr "E603: :catch utan :try"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1368
+msgid "E604: :catch after :finally"
+msgstr "E604: :catch efter :finally"
+
+#: ex_eval.c:1501
+msgid "E606: :finally without :try"
+msgstr "E606: :finally utan :try"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1525
+msgid "E607: multiple :finally"
+msgstr "E607: flera :finally"
+
+#: ex_eval.c:1634
+msgid "E602: :endtry without :try"
+msgstr "E602: :endtry utan :try"
+
+#: ex_eval.c:1966
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction inte inom en funktion"
+
+#: ex_getln.c:3229
+msgid "tagname"
+msgstr "taggnamn"
+
+#: ex_getln.c:3232
+msgid " kind file\n"
+msgstr " snäll fil\n"
+
+#: ex_getln.c:4591
+msgid "'history' option is zero"
+msgstr "'history'-flagga är noll"
+
+#: ex_getln.c:4856
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s Historia (nyaste till äldsta):\n"
+
+#: ex_getln.c:4857
+msgid "Command Line"
+msgstr "Kommandorad"
+
+#: ex_getln.c:4858
+msgid "Search String"
+msgstr "Söksträng"
+
+#: ex_getln.c:4859
+msgid "Expression"
+msgstr "Uttryck"
+
+#: ex_getln.c:4860
+msgid "Input Line"
+msgstr "Inmatningsrad"
+
+#: ex_getln.c:4898
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar bortom kommandolängden"
+
+#: ex_getln.c:5075
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: Aktivt fönster eller buffert borttagen"
+
+#: fileio.c:369
+msgid "Illegal file name"
+msgstr "Otillåtet filnamn"
+
+#: fileio.c:393 fileio.c:518 fileio.c:2730 fileio.c:2771
+msgid "is a directory"
+msgstr "är en katalog"
+
+#: fileio.c:395
+msgid "is not a file"
+msgstr "är inte en fil"
+
+#: fileio.c:540 fileio.c:3892
+msgid "[New File]"
+msgstr "[Ny fil]"
+
+#: fileio.c:573
+msgid "[Permission Denied]"
+msgstr "[Tillåtelse nekas]"
+
+#: fileio.c:677
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre autokommandon gjorde filen oläsbar"
+
+#: fileio.c:679
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *ReadPre autokommandon får inte ändra nuvarande buffert"
+
+#: fileio.c:700
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: Läser från standard in...\n"
+
+#: fileio.c:706
+msgid "Reading from stdin..."
+msgstr "Läser från standard in..."
+
+#. Re-opening the original file failed!
+#: fileio.c:951
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: Konvertering gjorde filen oläsbar!"
+
+#: fileio.c:1917
+msgid "[fifo/socket]"
+msgstr "[fifo/uttag]"
+
+#: fileio.c:1924
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:1931
+msgid "[socket]"
+msgstr "[uttag]"
+
+#: fileio.c:1939
+msgid "[RO]"
+msgstr "[EL]"
+
+#: fileio.c:1949
+msgid "[CR missing]"
+msgstr "[CR saknas]"
+
+#: fileio.c:1954
+msgid "[NL found]"
+msgstr "[NL hittat]"
+
+#: fileio.c:1959
+msgid "[long lines split]"
+msgstr "[långa rader delade]"
+
+#: fileio.c:1965 fileio.c:3876
+msgid "[NOT converted]"
+msgstr "[INTE konverterad]"
+
+#: fileio.c:1970 fileio.c:3881
+msgid "[converted]"
+msgstr "[konverterad]"
+
+#: fileio.c:1977 fileio.c:3906
+msgid "[crypted]"
+msgstr "[krypterad]"
+
+#: fileio.c:1984
+msgid "[CONVERSION ERROR]"
+msgstr "[KONVERTERINGSFEL]"
+
+#: fileio.c:1990
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[OTILLÅTEN BIT på rad %ld]"
+
+#: fileio.c:1997
+msgid "[READ ERRORS]"
+msgstr "[LÄSFEL]"
+
+#: fileio.c:2213
+msgid "Can't find temp file for conversion"
+msgstr "Kan inte hitta temporär fil för konvertering"
+
+#: fileio.c:2220
+msgid "Conversion with 'charconvert' failed"
+msgstr "Konvertering med 'charconvert' misslyckades"
+
+#: fileio.c:2223
+msgid "can't read output of 'charconvert'"
+msgstr "kan inte läsa utdata av 'charconvert'"
+
+#: fileio.c:2617
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr ""
+"E203: Autokommandon tog bort eller laddade ur buffert som skulle skrivas"
+
+#: fileio.c:2640
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Autokommado ändrade antal rader på ett oväntat sätt"
+
+#: fileio.c:2674
+msgid "NetBeans dissallows writes of unmodified buffers"
+msgstr "NetBeans tillåter inte skrivning av omodifierade buffertar"
+
+#: fileio.c:2682
+msgid "Partial writes disallowed for NetBeans buffers"
+msgstr "Delvisa skrivningar tillåts inte i NetBeans-buffertar"
+
+#: fileio.c:2736 fileio.c:2754
+msgid "is not a file or writable device"
+msgstr "är inte en fil eller skrivbar enhet"
+
+#: fileio.c:2806
+msgid "is read-only (add ! to override)"
+msgstr "är skrivskyddad (lägg till ! för att tvinga)"
+
+#: fileio.c:3124
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: Kan inte skriva till säkerhetskopia (lägg till ! för att tvinga)"
+
+#: fileio.c:3136
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr "E507: Stängningsfel för säkerhetskopia (lägg till ! för att tvinga)"
+
+#: fileio.c:3138
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr ""
+"E508: Kan inte läsa fil för säkerhetskopia (lägg till ! för att tvinga)"
+
+#: fileio.c:3154
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: Kan inte skapa säkerhetskopia (lägg till ! för att tvinga)"
+
+#: fileio.c:3257
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: Kan inte göra säkerhetskopia (lägg till ! för att tvinga)"
+
+#: fileio.c:3319
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr "E460: Resursgrenen skulle tappas bort (lägg till ! för att tvinga)"
+
+#: fileio.c:3420
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: Kan inte hitta temporär fil för skrivning"
+
+#: fileio.c:3438
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr ""
+"E213: Kan inte konvertera (lägg till ! för att skriva utan konvertering)"
+
+#: fileio.c:3473
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: Kan inte öppna länkad fil för skrivning"
+
+#: fileio.c:3477
+msgid "E212: Can't open file for writing"
+msgstr "E212: Kan inte öppna fil för skrivning"
+
+#: fileio.c:3727
+msgid "E512: Close failed"
+msgstr "E512: Stängning misslyckades"
+
+#: fileio.c:3798
+msgid "E513: write error, conversion failed"
+msgstr "E513: skrivfel, konvertering misslyckades"
+
+#: fileio.c:3804
+msgid "E514: write error (file system full?)"
+msgstr "E514: skrivfel (filsystem fullt?)"
+
+#: fileio.c:3871
+msgid " CONVERSION ERROR"
+msgstr " KONVERTERINGSFEL"
+
+#: fileio.c:3887
+msgid "[Device]"
+msgstr "[Enhet]"
+
+#: fileio.c:3892
+msgid "[New]"
+msgstr "[Ny]"
+
+#: fileio.c:3914
+msgid " [a]"
+msgstr " [l]"
+
+#: fileio.c:3914
+msgid " appended"
+msgstr " lade till"
+
+#: fileio.c:3916
+msgid " [w]"
+msgstr " [s]"
+
+#: fileio.c:3916
+msgid " written"
+msgstr " skriven"
+
+#: fileio.c:3966
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: Patchläge: kan inte spara orginalfil"
+
+#: fileio.c:3988
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: patchläge: kan inte skapa tom orginalfil"
+
+#: fileio.c:4003
+msgid "E207: Can't delete backup file"
+msgstr "E207: Kan inte ta bort säkerhetskopia"
+
+#: fileio.c:4067
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"VARNING: Orginalfilen kan vara förlorad eller skadad\n"
+
+#: fileio.c:4069
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "avsluta inte redigeraren innan filen är framgångsrikt skriven"
+
+#: fileio.c:4158
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:4158
+msgid "[dos format]"
+msgstr "[dos-format]"
+
+#: fileio.c:4165
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:4165
+msgid "[mac format]"
+msgstr "[mac-format]"
+
+#: fileio.c:4172
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:4172
+msgid "[unix format]"
+msgstr "[unix-format]"
+
+#: fileio.c:4199
+msgid "1 line, "
+msgstr "1 rad, "
+
+#: fileio.c:4201
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld rader, "
+
+#: fileio.c:4204
+msgid "1 character"
+msgstr "1 tecken"
+
+#: fileio.c:4206
+#, c-format
+msgid "%ld characters"
+msgstr "%ld tecken"
+
+#: fileio.c:4216
+msgid "[noeol]"
+msgstr "[inget radslut]"
+
+#: fileio.c:4216
+msgid "[Incomplete last line]"
+msgstr "[Ofullständig sistarad]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4235
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "VARNING: Filen har ändrats sedan den lästes in!!!"
+
+#: fileio.c:4237
+msgid "Do you really want to write to it"
+msgstr "Vill du verkligen skriva till den"
+
+#: fileio.c:5313
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: Fel vid skrivning till \"%s\""
+
+#: fileio.c:5320
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Fel vid stängning av \"%s\""
+
+#: fileio.c:5323
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Fel vid läsning av \"%s\""
+
+#: fileio.c:5543
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: FileChangedShell-autokommandot tog bort buffert"
+
+#: fileio.c:5551
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: Varning: Filen \"%s\" är inte längre tillgänglig"
+
+#: fileio.c:5564
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: Varning: Filen \"%s\" har ändrats och bufferten ändrades i Vim också"
+
+#: fileio.c:5567
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: Varning: Filen \"%s\" har ändrats sedan redigeringen började"
+
+#: fileio.c:5569
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr ""
+"W16: Varning: Rättigheterna på filen \"%s\" har ändrats sedan redigeringen "
+"började"
+
+#: fileio.c:5579
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: Varning: Filen \"%s\" har skapats efter redigeringen började"
+
+#: fileio.c:5596
+msgid "Warning"
+msgstr "Varning"
+
+#: fileio.c:5597
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&OK\n"
+"&Läs in filen"
+
+#: fileio.c:5695
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: Kunde inte förbereda för att läsa om \"%s\""
+
+#: fileio.c:5714
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: Kunde inte läsa om \"%s\""
+
+#: fileio.c:6296
+msgid "--Deleted--"
+msgstr "--Borttagen--"
+
+#. the group doesn't exist
+#: fileio.c:6456
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Ingen sådan grupp: \"%s\""
+
+#: fileio.c:6582
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Otillåtet tecken efter *: %s"
+
+#: fileio.c:6594
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Ingen sådan händelse: %s"
+
+#: fileio.c:6596
+msgid "E216: No such group or event: %s"
+msgstr "E216: Ingen sådan grupp eller händelse: %s"
+
+#. Highlight title
+#: fileio.c:6745
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Autokommandon ---"
+
+#: fileio.c:7016
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Kan inte köra autokommandon för ALLA händelser"
+
+#: fileio.c:7039
+msgid "No matching autocommands"
+msgstr "Inga matchande autokommandon"
+
+#: fileio.c:7359
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: autokommando nästlad för djupt"
+
+#: fileio.c:7627
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Autokommandon för \"%s\""
+
+#: fileio.c:7635
+#, c-format
+msgid "Executing %s"
+msgstr "Kör %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7703
+#, c-format
+msgid "autocommand %s"
+msgstr "autokommando %s"
+
+#: fileio.c:8270
+msgid "E219: Missing {."
+msgstr "E219: Saknar {."
+
+#: fileio.c:8272
+msgid "E220: Missing }."
+msgstr "E220: Saknar }."
+
+#: fold.c:66
+msgid "E490: No fold found"
+msgstr "E490: Inget veck funnet"
+
+#: fold.c:565
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: Kan inte skapa veck med nuvarande 'foldmethod'"
+
+#: fold.c:567
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: Kan inte ta bort veck med nuvarande 'foldmethod'"
+
+#: getchar.c:246
+msgid "E222: Add to read buffer"
+msgstr "E222: Lägg till i läsbuffert"
+
+#: getchar.c:2157
+msgid "E223: recursive mapping"
+msgstr "E223: rekursiv mappning"
+
+#: getchar.c:3023
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: global förkortning existerar redan för %s"
+
+#: getchar.c:3026
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: global mappning existerar redan för %s"
+
+#: getchar.c:3153
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: förkortning existerar redan för %s"
+
+#: getchar.c:3156
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: mappning existerar redan för %s"
+
+#: getchar.c:3220
+msgid "No abbreviation found"
+msgstr "Ingen förkortning hittades"
+
+#: getchar.c:3222
+msgid "No mapping found"
+msgstr "Ingen mappning hittades"
+
+#: getchar.c:4112
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: Otillåtet läge"
+
+#: gui_at_fs.c:300
+msgid "<cannot open> "
+msgstr "<kan inte öppna> "
+
+#: gui_at_fs.c:1136
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: kan inte hämta typsnitt %s"
+
+#: gui_at_fs.c:2781
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: Kan inte återvända till aktuell katalog"
+
+#: gui_at_fs.c:2801
+msgid "Pathname:"
+msgstr "Sökväg:"
+
+#: gui_at_fs.c:2807
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: kan inte hämta aktuell katalog"
+
+#: gui_at_fs.c:2815 gui_motif.c:1623
+msgid "OK"
+msgstr "OK"
+
+#: gui_at_fs.c:2815 gui_gtk.c:2638 gui_motif.c:1618 gui_motif.c:2849
+msgid "Cancel"
+msgstr "Avbryt"
+
+#: gui_athena.c:2047 gui_motif.c:1871
+msgid "Vim dialog"
+msgstr "Vim-dialog"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Rullningslist: Kunde inte hämta geometrin på miniatyrbild."
+
+#: gui_beval.c:101 gui_w32.c:3772
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: Kan inte skapa BalloonEval med både meddelande och återkallning"
+
+#: gui.c:219
+msgid "E229: Cannot start the GUI"
+msgstr "E229: Kan inte starta GUI"
+
+#: gui.c:348
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: Kan inte läsa från \"%s\""
+
+#: gui.c:473
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: 'guifontwide' ogiltig"
+
+#: gui.c:543
+msgid "E599: Value of 'imactivatekey' is invalid"
+msgstr "E599: Värdet av 'imactivatekey' är ogiltigt"
+
+#: gui.c:3945
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: Kan inte allokera färg %s"
+
+#: gui_gtk.c:1567
+msgid "Vim dialog..."
+msgstr "Vim-dialog..."
+
+#: gui_gtk.c:2002 message.c:2886
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Ja\n"
+"&Nej\n"
+"&Avbryt"
+
+#: gui_gtk.c:2165
+msgid "Input _Methods"
+msgstr "Inmatnings_metoder"
+
+#: gui_gtk.c:2431 gui_motif.c:2768
+msgid "VIM - Search and Replace..."
+msgstr "VIM - Sök och ersätt..."
+
+#: gui_gtk.c:2439 gui_motif.c:2770
+msgid "VIM - Search..."
+msgstr "VIM - Sök..."
+
+#: gui_gtk.c:2471 gui_motif.c:2888
+msgid "Find what:"
+msgstr "Hitta vad:"
+
+#: gui_gtk.c:2491 gui_motif.c:2920
+msgid "Replace with:"
+msgstr "Ersätt med:"
+
+#. whole word only button
+#: gui_gtk.c:2523 gui_motif.c:3036
+msgid "Match whole word only"
+msgstr "Matcha endast hela ord"
+
+#. match case button
+#: gui_gtk.c:2536 gui_motif.c:3048
+msgid "Match case"
+msgstr "Skilj på stora/små bokstäver"
+
+#: gui_gtk.c:2548 gui_motif.c:2990
+msgid "Direction"
+msgstr "Riktning"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2560 gui_motif.c:3002
+msgid "Up"
+msgstr "Upp"
+
+#: gui_gtk.c:2564 gui_motif.c:3010
+msgid "Down"
+msgstr "Ned"
+
+#: gui_gtk.c:2590 gui_gtk.c:2592 gui_motif.c:2792
+msgid "Find Next"
+msgstr "Hitta nästa"
+
+#: gui_gtk.c:2609 gui_gtk.c:2611 gui_motif.c:2809
+msgid "Replace"
+msgstr "Ersätt"
+
+#: gui_gtk.c:2622 gui_gtk.c:2624 gui_motif.c:2822
+msgid "Replace All"
+msgstr "Ersätt alla"
+
+#: gui_gtk_x11.c:2248
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: Tog emot \"die\"-begäran från sessionshanteraren\n"
+
+#: gui_gtk_x11.c:3437
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: Huvudfönster oväntat förstört\n"
+
+#: gui_gtk_x11.c:4051
+msgid "Font Selection"
+msgstr "Typsnittsval"
+
+#: gui_gtk_x11.c:5907 ui.c:2016
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "Använd CUT_BUFFER0 istället för tomt val"
+
+#: gui_motif.c:1617 gui_motif.c:1620
+msgid "Filter"
+msgstr "Filter"
+
+#: gui_motif.c:1619
+msgid "Directories"
+msgstr "Kataloger"
+
+#: gui_motif.c:1621
+msgid "Help"
+msgstr "Hjälp"
+
+#: gui_motif.c:1622
+msgid "Files"
+msgstr "Filer"
+
+#: gui_motif.c:1624
+msgid "Selection"
+msgstr "Val"
+
+#: gui_motif.c:2835
+msgid "Undo"
+msgstr "Ångra"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: Kan inte läsa in Zap-typsnitt '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: Kan inte använda typsnitt %s"
+
+#: gui_riscos.c:3270
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"Skickar meddelande för att avsluta barnprocess.\n"
+
+#: gui_w32.c:803
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: Argument stöds inte: \"-%s\"; Används OLE-versionen."
+
+#: gui_w48.c:2079
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "Sök sträng (använd '\\\\' för att hitta '\\')"
+
+#: gui_w48.c:2104
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "Sök & ersätt (använd '\\\\' för att hitta '\\')"
+
+#: gui_x11.c:1523
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: Kan inte allokera post i färgkarta, några färger kan bli felaktiga"
+
+#: gui_x11.c:2104
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr ""
+"E250: Typsnitt för följande teckenkoder saknas i typsnittsuppsättningen %s:"
+
+#: gui_x11.c:2147
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: Typsnittsuppsättningsnamn: %s"
+
+#: gui_x11.c:2148
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "Font '%s' är inte fast bredd"
+
+#: gui_x11.c:2167
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: Typsnittsuppsättningsnamn: %s\n"
+
+#: gui_x11.c:2168
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Typsnitt0: %s\n"
+
+#: gui_x11.c:2169
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Typsnitt1: %s\n"
+
+#: gui_x11.c:2170
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "Typsnitt%d är inte dubbelt så bred som font0\n"
+
+#: gui_x11.c:2171
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "Typsnitt0 bredd: %ld\n"
+
+#: gui_x11.c:2172
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"Typsnitt1 bredd: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: Hangul automata FEL"
+
+#: if_cscope.c:77
+msgid "Add a new database"
+msgstr "Lägg till en ny databas"
+
+#: if_cscope.c:79
+msgid "Query for a pattern"
+msgstr "Fråga efter ett mönster"
+
+#: if_cscope.c:81
+msgid "Show this message"
+msgstr "Visa detta meddelande"
+
+#: if_cscope.c:83
+msgid "Kill a connection"
+msgstr "Döda en anslutning"
+
+#: if_cscope.c:85
+msgid "Reinit all connections"
+msgstr "Ominitiera alla anslutningar"
+
+#: if_cscope.c:87
+msgid "Show connections"
+msgstr "Visa anslutningar"
+
+#: if_cscope.c:95
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: Användning: cs[cope] %s"
+
+#: if_cscope.c:124
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Det här scope-kommandot stöder inte delning av fönstret.\n"
+
+#: if_cscope.c:170
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: Användning: cstag <identifierare>"
+
+#: if_cscope.c:226
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: tagg hittades inte"
+
+#: if_cscope.c:404
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: stat(%s)-fel: %d"
+
+#: if_cscope.c:414
+msgid "E563: stat error"
+msgstr "E563: stat-fel"
+
+#: if_cscope.c:511
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s är inte en katalog eller en godkänd cscope-databas"
+
+#: if_cscope.c:529
+#, c-format
+msgid "Added cscope database %s"
+msgstr "Lade till cscope-databas %s"
+
+#: if_cscope.c:584
+#, c-format
+msgid "E262: error reading cscope connection %ld"
+msgstr "E262: fel vid läsning av cscope-anslutning %ld"
+
+#: if_cscope.c:689
+msgid "E561: unknown cscope search type"
+msgstr "E561: okänd cscope-söktyp"
+
+#: if_cscope.c:731
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: Kunde inte skapa cscope-rör"
+
+#: if_cscope.c:748
+msgid "E622: Could not fork for cscope"
+msgstr "E622: Kunde inte grena för cscope"
+
+#: if_cscope.c:842 if_cscope.c:892
+msgid "cs_create_connection exec failed"
+msgstr "cs_create_connection-exekvering misslyckades"
+
+#: if_cscope.c:893
+msgid "E623: Could not spawn cscope process"
+msgstr "E623: Kunde inte starta cscope-process"
+
+#: if_cscope.c:906
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen för to_fp misslyckades"
+
+#: if_cscope.c:908
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen för fr_fp misslyckades"
+
+#: if_cscope.c:946
+msgid "E567: no cscope connections"
+msgstr "E567: inga cscope-anslutningar"
+
+#: if_cscope.c:1020
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: inga träffar funna för cscope-förfrågan %s av %s"
+
+#: if_cscope.c:1077
+#, c-format
+msgid "E469: invalid cscopequickfix flag %c for %c"
+msgstr "E469: ogiltig cscopequickfix flagga %c för %c"
+
+#: if_cscope.c:1146
+msgid "cscope commands:\n"
+msgstr "cscope-kommandon:\n"
+
+#: if_cscope.c:1149
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)"
+msgstr "%-5s: %-30s (Användning: %s)"
+
+#: if_cscope.c:1247
+#, c-format
+msgid "E625: cannot open cscope database: %s"
+msgstr "E625: kan inte öppna cscope-databas: %s"
+
+#: if_cscope.c:1265
+msgid "E626: cannot get cscope database information"
+msgstr "E626: kan inte hämta cscope-databasinformation"
+
+#: if_cscope.c:1290
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: dubblerad cscope-databas inte lagd till"
+
+#: if_cscope.c:1301
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: maximalt antal av cscope-anslutningar nått"
+
+#: if_cscope.c:1417
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: cscope-anslutning %s hittades inte"
+
+#: if_cscope.c:1451
+#, c-format
+msgid "cscope connection %s closed"
+msgstr "cscope-anslutning %s stängd"
+
+#. should not reach here
+#: if_cscope.c:1591
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: ödesdigert fel i cs_manage_matches"
+
+#: if_cscope.c:1841
+#, c-format
+msgid "Cscope tag: %s"
+msgstr "Cscope-tagg: %s"
+
+#: if_cscope.c:1863
+msgid ""
+"\n"
+" # line"
+msgstr ""
+"\n"
+" # rad"
+
+#: if_cscope.c:1865
+msgid "filename / context / line\n"
+msgstr "filnamn / sammanhang / rad\n"
+
+#: if_cscope.c:1977
+#, c-format
+msgid "E609: Cscope error: %s"
+msgstr "E609: Cscope-fel: %s"
+
+#: if_cscope.c:2143
+msgid "All cscope databases reset"
+msgstr "Alla cscope-databaser återställda"
+
+#: if_cscope.c:2211
+msgid "no cscope connections\n"
+msgstr "inga cscope-anslutningar\n"
+
+#: if_cscope.c:2215
+msgid " # pid database name prepend path\n"
+msgstr " # pid databasnamn först i sökväg\n"
+
+#: if_python.c:413
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: Tyvärr, detta kommandot är inaktiverat, Python-biblioteket kunde inte "
+"läsas in."
+
+#: if_python.c:615
+msgid "can't delete OutputObject attributes"
+msgstr "kan inte ta bort OutputObject-attribut"
+
+#: if_python.c:622
+msgid "softspace must be an integer"
+msgstr "softspace måste vara ett heltal"
+
+#: if_python.c:630
+msgid "invalid attribute"
+msgstr "ogiltigt attribut"
+
+#: if_python.c:669 if_python.c:683
+msgid "writelines() requires list of strings"
+msgstr "writelines() kräver lista av strängar"
+
+#: if_python.c:809
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: Fel vid initiering av I/O-objekt"
+
+#: if_python.c:994 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "ogiltigt uttryck"
+
+#: if_python.c:1008 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "uttryck inaktiverat vid kompilering"
+
+#: if_python.c:1021
+msgid "attempt to refer to deleted buffer"
+msgstr "försök att referera till borttagen buffert"
+
+#: if_python.c:1036 if_python.c:1077 if_python.c:1141 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "radnummer utanför område"
+
+#: if_python.c:1276
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<buffertobjekt (borttaget) vid %8lX>"
+
+#: if_python.c:1367 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "ogiltigt märknamn"
+
+#: if_python.c:1647
+msgid "no such buffer"
+msgstr "ingen sådan buffert"
+
+#: if_python.c:1735
+msgid "attempt to refer to deleted window"
+msgstr "försök att referera till borttaget fönster"
+
+#: if_python.c:1780
+msgid "readonly attribute"
+msgstr "skrivskyddad attribut"
+
+#: if_python.c:1793
+msgid "cursor position outside buffer"
+msgstr "markörposition utanför buffert"
+
+#: if_python.c:1870
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<fönsterobjekt (borttaget) vid %.8lX>"
+
+#: if_python.c:1882
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<fönsterobjekt (okänt) vid %.8lX>"
+
+#: if_python.c:1884
+#, c-format
+msgid "<window %d>"
+msgstr "<fönster %d>"
+
+#: if_python.c:1960
+msgid "no such window"
+msgstr "inget sådant fönster"
+
+#: if_python.c:2221 if_python.c:2255 if_python.c:2310 if_python.c:2378
+#: if_python.c:2500 if_python.c:2552 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1998
+msgid "cannot save undo information"
+msgstr "kan inte spara ångra-information"
+
+#: if_python.c:2223 if_python.c:2317 if_python.c:2389
+msgid "cannot delete line"
+msgstr "kan inte ta bort rad"
+
+#: if_python.c:2260 if_python.c:2405 if_tcl.c:690 if_tcl.c:2020
+msgid "cannot replace line"
+msgstr "kan inte ersätta rad"
+
+#: if_python.c:2423 if_python.c:2502 if_python.c:2560
+msgid "cannot insert line"
+msgstr "kan inte infoga rad"
+
+#: if_python.c:2664
+msgid "string cannot contain newlines"
+msgstr "sträng kan inte innehålla nyrader"
+
+#: if_ruby.c:412
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: Tyvärr, detta kommandot är inaktiverat, Ruby-biblioteket kunde inte "
+"läsas in."
+
+#: if_ruby.c:475
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: okänt longjmp-status %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Växla mellan implementation/definition"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Visa basklass av"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Visa åsidosatt medlemsfunktion"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Hämta från fil"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Hämta från projekt"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Hämta från alla projekt"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Hämta"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Visa källa för"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "Hitta symbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "Bläddra i klass"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Visa klass i hierarki"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Visa klass i begränsad hierarki"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref refererar till"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref refereras av"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref har en"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref används av"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Visa docu av"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "Generera docu för"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"Kan inte ansluta till SNiFF+. Kontrollera miljö (sniffemacs måste kunna "
+"hittas i $PATH).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Fel vid läsning. Frånkopplad"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ är för närvarande "
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "inte "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "ansluten"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: Okänd SNiFF+-begäran: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Fel vid anslutning till SNiFF+"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ inte ansluten"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: Inte en SNiFF+-buffert"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: Fel vid skrivning. Frånkopplad"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "ogiltigt buffertnummer"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "inte implementerat än"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "okänd flagga"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "kan inte ställa in rad(er)"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "märke inte satt"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "rad %d kolumn %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "kan inte infoga/lägga till rad"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "okänd flagga: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "okänd vimOption"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "tangentbordsavbrott"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "vim-fel"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "kan inte skapa buffert/fönster-kommando: objekt håller på att tas bort"
+
+#: if_tcl.c:1545
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr ""
+"kan inte registera återkallningskommando: buffert/fönster håller redan på "
+"att tas bort"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr ""
+"E280: TCL ÖDESDIGERT FEL: reflist trasig!? Var snäll och rapportera detta "
+"till vim-dev@vim.org"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr ""
+"kan inte registrera återkallningskommando: buffert-/fönsterreferens hittades "
+"inte"
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"E571: Tyvärr, detta kommando är inaktiverat: Tcl-biblioteket kunde inte "
+"läsas in."
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E281: TCL-FEL: Avslutningskoden är inte int!? Var snäll och rapportera detta "
+"till vim-dev@vim.org"
+
+#: if_tcl.c:2006
+msgid "cannot get line"
+msgstr "kan inte hämta rad"
+
+#: if_xcmdsrv.c:215
+msgid "Unable to register a command server name"
+msgstr "Kunde inte registrera ett kommandoservernamn"
+
+#: if_xcmdsrv.c:465
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: Misslyckades att skicka kommando till målprogrammet"
+
+#: if_xcmdsrv.c:739
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: Ogiltigt server-id använt: %s"
+
+#: if_xcmdsrv.c:1102
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: VIM instansregisteregenskap är dåligt format. Borttaget!"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "Okänd flagga"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "För många redigeringsargument"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "Argument saknas efter"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "Skräp efter flagga"
+
+#: main.c:68
+msgid "Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"
+msgstr ""
+"För många \"+kommando\"-, \"-c kommando\"- eller \"--cmd kommando\"-argument"
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "Ogiltigt argument för"
+
+#: main.c:466
+msgid "This Vim was not compiled with the diff feature."
+msgstr "Denna Vim blev inte kompilerad med diff-funktionen."
+
+#: main.c:925
+msgid "Attempt to open script file again: \""
+msgstr "Försök att öppna skriptfil igen: \""
+
+#: main.c:929 main.c:936 main.c:980 memline.c:3694 memline.c:3698
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:934
+msgid "Cannot open for reading: \""
+msgstr "Kan inte öppna för läsning: \""
+
+#: main.c:978
+msgid "Cannot open for script output: \""
+msgstr "Kan inte öppna för skriptutmatning: \""
+
+#: main.c:1112
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d filer att redigera\n"
+
+#: main.c:1202
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: Varning: Utmatning är inte till en terminal\n"
+
+#: main.c:1204
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: Varning: Inmatning är inte från en terminal\n"
+
+#. just in case..
+#: main.c:1266
+msgid "pre-vimrc command line"
+msgstr "pre-vimrc kommandorad"
+
+#: main.c:1307
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: Kan inte läsa från \"%s\""
+
+#: main.c:2365
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"Mer info med: \"vim -h\"\n"
+
+#: main.c:2398
+msgid "[file ..] edit specified file(s)"
+msgstr "[fil ..] redigera angivna fil(er)"
+
+#: main.c:2399
+msgid "- read text from stdin"
+msgstr "- läs text från standard in"
+
+#: main.c:2400
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tagg redigera fil där tagg är definierad"
+
+#: main.c:2402
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [felfil] redigera fil med första fel"
+
+#: main.c:2411
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"användning:"
+
+#: main.c:2414
+msgid " vim [arguments] "
+msgstr " vim [argument] "
+
+#: main.c:2418
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" eller:"
+
+#: main.c:2421
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"Argument:\n"
+
+#: main.c:2422
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tBara filnamn efter det här"
+
+#: main.c:2424
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tExpandera inte jokertecken"
+
+#: main.c:2427
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tRegistrera gvim för OLE"
+
+#: main.c:2428
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tAvregistrera gvim för OLE"
+
+#: main.c:2431
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tKör som GUI (som \"gvim\")"
+
+#: main.c:2432
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f eller --nofork\tFörgrund: Grena inte vid start av GUI"
+
+#: main.c:2434
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi-läge (som \"vi\")"
+
+#: main.c:2435
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx-läge (som \"ex\")"
+
+#: main.c:2436
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tTyst (batch) läge (bara för \"ex\")"
+
+#: main.c:2438
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tDiff-läge (som \"vimdiff\")"
+
+#: main.c:2440
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tLätt läge (som \"evim\", lägeslös)"
+
+#: main.c:2441
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tSkrivskyddat läge (som \"view\")"
+
+#: main.c:2442
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tBegränsat läge (som \"rvim\")"
+
+#: main.c:2443
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tModifieringar (skriva filer) inte tillåtet"
+
+#: main.c:2444
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tModifieringar i text inte tillåtet"
+
+#: main.c:2445
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\tBinärläge"
+
+#: main.c:2447
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp-läge"
+
+#: main.c:2449
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tKompatibelt med Vi: 'compatible'"
+
+#: main.c:2450
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tInte fullt Vi-kompatibel: 'nocompatible'"
+
+#: main.c:2451
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tMångordigt läge"
+
+#: main.c:2452
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tFelsökningsläge"
+
+#: main.c:2453
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tIngen växlingsfil, använd endast minnet"
+
+#: main.c:2454
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tLista växlingsfiler och avsluta"
+
+#: main.c:2455
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (med filnamn)\tÅterskapa kraschad session"
+
+#: main.c:2456
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tSamma som -r"
+
+#: main.c:2458
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tAnvända inte newcli för att öppna fönster"
+
+#: main.c:2459
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <enhet>\t\tAnvänd <enhet> för I/O"
+
+#: main.c:2462
+msgid "-A\t\t\tstart in Arabic mode"
+msgstr "-A\t\t\tstarta i arabiskt läge"
+
+#: main.c:2465
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\tStarta i hebreiskt läge"
+
+#: main.c:2468
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\tStarta i persiskt läge (Farsi)"
+
+#: main.c:2470
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\tStäll in terminaltyp till <terminal>"
+
+#: main.c:2471
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tAnvänd <vimrc> istället för någon .vimrc"
+
+#: main.c:2473
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tAnvänd <gvimrc> istället för någon .gvimrc"
+
+#: main.c:2475
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tLäs inte in insticksskript"
+
+#: main.c:2476
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\tÖppna N fönster (standard: ett för varje fil)"
+
+#: main.c:2477
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\tSom -o men dela vertikalt"
+
+#: main.c:2478
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tStarta vid slut av fil"
+
+#: main.c:2479
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnr>\t\tStarta på rad <rnr>"
+
+#: main.c:2481
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <kommando>\tKör <kommando> före inläsning av någon vimrc fil"
+
+#: main.c:2483
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <kommando>\tKör <kommando> efter inläsning av den första filen"
+
+#: main.c:2484
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <session>\t\tKör fil <session> efter inläsning av den första filen"
+
+#: main.c:2485
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <inskript>\tLäs Normallägeskommandon från fil <inskript>"
+
+#: main.c:2486
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <utskript>\tLägg till alla skrivna kommandon till fil <utskript>"
+
+#: main.c:2487
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <utskript>\tSkriv alla skrivna kommandon till fil <utskript>"
+
+#: main.c:2489
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tRedigera krypterade filer"
+
+#: main.c:2493
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\tAnslut vim till just denna X-server"
+
+#: main.c:2495
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tAnslut inte till X server"
+
+#: main.c:2498
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <filer>\tRedigera <filer> i en Vim-server om möjligt"
+
+#: main.c:2499
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr ""
+"--remote-silent <filer>\tSamma, klaga inte om det inte finns någon server"
+
+#: main.c:2500
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr ""
+"--remote-wait <filer>\tSom --remote men vänta på att filer har blivit "
+"redigerade"
+
+#: main.c:2501
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr ""
+"--remote-wait-silent <filer>\tSamma, klaga inte om det inte finns någon "
+"server"
+
+#: main.c:2502
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr ""
+"--remote-send <nycklar>\tSkicka <nycklar> till en Vim-server och avsluta"
+
+#: main.c:2503
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr ""
+"--remote-expr <uttryck>\tEvaluera <uttryck> i en Vim-server och skriv ut "
+"resultatet"
+
+#: main.c:2504
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tLista tillgängliga Vim-servernamn och avsluta"
+
+#: main.c:2505
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <namn>\tSkicka till/för att bli Vim-servern <namn>"
+
+#: main.c:2508
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tAnvänd <viminfo> istället för .viminfo"
+
+#: main.c:2510
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h eller --help\tSkriv ut Hjälp (det här meddelandet) och avsluta"
+
+#: main.c:2511
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\tSkriv ut versionsinformation och avsluta"
+
+#: main.c:2515
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"Argument som stöds av gvim (Motif-version):\n"
+
+#: main.c:2519
+msgid ""
+"\n"
+"Arguments recognised by gvim (neXtaw version):\n"
+msgstr ""
+"\n"
+"Argument som stöds av gvim (neXtaw-version):\n"
+
+#: main.c:2521
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"Argument som stöds av gvim (Athena-version):\n"
+
+#: main.c:2525
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\tKör vim på <display>"
+
+#: main.c:2526
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tStarta vim som ikon"
+
+#: main.c:2528
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <namn>\t\tAnvänd resurs som om vim var <namn>"
+
+#: main.c:2529
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (Oimplementerat)\n"
+
+#: main.c:2531
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <färg>\tAnvänd <färg> för bakgrunden (även: -bg)"
+
+#: main.c:2532
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <färg>\tAnvänd <färg> för vanlig text (även: -fg)"
+
+#: main.c:2533 main.c:2553
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <typsnitt>\t\tAnvänd <typsnitt> för vanlig text (även: -fn)"
+
+#: main.c:2534
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "­boldfont <typsnitt>\tAnvänd <typsnitt> för fet text"
+
+#: main.c:2535
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <typsnitt>\tAnvänd <typsnitt> för kursiv text"
+
+#: main.c:2536 main.c:2554
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr ""
+"-geometry <geom>\tAnvänd <geom> för inledande fönsterplacering (även: -geom)"
+
+#: main.c:2537
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <bredd>\tAnvänd en rambredd med <bredd> (även: -bw)"
+
+#: main.c:2538
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr ""
+"-scrollbarwidth <bredd> Använd en rullningslistbredd på <bredd> (även: -sw)"
+
+#: main.c:2540
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <höjd>\tAnvänd en menyradshöjd med <höjd> (även: -mh)"
+
+#: main.c:2542 main.c:2555
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tAnvänd omvänd video (även: -rv)"
+
+#: main.c:2543
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tAnvänd inte omvänd video (även: +rv)"
+
+#: main.c:2544
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <tillgång>\tStäll in den angivna tillgången"
+
+#: main.c:2547
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"Argument igenkända av gvim (RISC OS-version):\n"
+
+#: main.c:2548
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <antal>\tInledande bredd på fönster i kolumner"
+
+#: main.c:2549
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <antal>\tInledande höjd på fönster i rader"
+
+#: main.c:2552
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"Argument igenkända av gvim (GTK+-version):\n"
+
+#: main.c:2556
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\tKör vim på <display> (även: --display)"
+
+#: main.c:2558
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr "--role <roll>\tStäll in en unik roll för att identifiera huvudfönstret"
+
+#: main.c:2560
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tÖppna Vim innanför en annan GTK-widget"
+
+#: main.c:2562
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tVisa Gnome-argument"
+
+#: main.c:2794
+msgid "No display"
+msgstr "Ingen display"
+
+#. Failed to send, abort.
+#: main.c:2809
+msgid ": Send failed.\n"
+msgstr ": Överföring misslyckades.\n"
+
+#. Let vim start normally.
+#: main.c:2815
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": Överföring misslyckades. Försöker att köra lokalt\n"
+
+#: main.c:2853 main.c:2874
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d av %d redigerade"
+
+#: main.c:2896
+msgid "No display: Send expression failed.\n"
+msgstr "Ingen display: Överföringsuttryck misslyckades.\n"
+
+#: main.c:2908
+msgid ": Send expression failed.\n"
+msgstr ": Överföringsuttryck misslyckades.\n"
+
+#: mark.c:662
+msgid "No marks set"
+msgstr "Inga märken satta"
+
+#: mark.c:664
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: Inga märken matchade \"%s\""
+
+#. Highlight title
+#: mark.c:675
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"märke rad kol fil/text"
+
+#. Highlight title
+#: mark.c:713
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" hopp rad kol fil/text"
+
+#: mark.c:1083
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Filmärken:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1118
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Hopplista (nyaste först):\n"
+
+#: mark.c:1214
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Historia för märken inne i filer (nyaste till äldsta):\n"
+
+#: mark.c:1297
+msgid "Missing '>'"
+msgstr "Saknar '>'"
+
+#: mbyte.c:415
+msgid "E543: Not a valid codepage"
+msgstr "E543: Inte en godkänd teckentabell"
+
+#: mbyte.c:4099
+msgid "E284: Cannot set IC values"
+msgstr "E284: Kan inte ställa in IC-värden"
+
+#: mbyte.c:4251
+msgid "E285: Failed to create input context"
+msgstr "E285: Misslyckades att skapa inmatningsmiljö"
+
+#: mbyte.c:4398
+msgid "E286: Failed to open input method"
+msgstr "E286: Misslyckades att öppna inmatningsmetod"
+
+#: mbyte.c:4409
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: Varning: Kunde inte ställa in förstörningsåterkallning till IM"
+
+#: mbyte.c:4415
+msgid "E288: input method doesn't support any style"
+msgstr "E288: inmatningsmetod stöder inte någon stil"
+
+#: mbyte.c:4472
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: inmatningsmetod stöder inte min förredigeringstyp"
+
+#: mbyte.c:4546
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: över-pricken-stil kräver typsnittsuppsättning"
+
+#: mbyte.c:4578
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: Din GTK+ är äldre än 1.2.3. Statusområde inaktiverat"
+
+#: mbyte.c:4857
+msgid "E292: Input Method Server is not running"
+msgstr "E292: Inmatningsmetodserver körs inte"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: block låstes inte"
+
+#: memfile.c:995
+msgid "E294: Seek error in swap file read"
+msgstr "E294: Sökfel i växelfilsläsning"
+
+#: memfile.c:1000
+msgid "E295: Read error in swap file"
+msgstr "E295: Läsfel i växelfil"
+
+#: memfile.c:1052
+msgid "E296: Seek error in swap file write"
+msgstr "E296: Sökfel i växelfilskrivning"
+
+#: memfile.c:1070
+msgid "E297: Write error in swap file"
+msgstr "E297: Skrivfel i växelfil"
+
+#: memfile.c:1267
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: Växelfil existerar redan (symlänksattack?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: Tog inte emot block nr 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: Tog inte emot block nr 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: Tog inte emot block nr 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: Hoppsan, tappat bort växelfilen!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: Kunde inte döpa om växelfil"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: Kunde inte öppna växelfil för \"%s\", återskapning omöjlig"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: Tog inte emot block 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: Ingen växelfil hittad för %s"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "Ange nummer på växelfil att använda (0 för att avsluta): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: Kan inte öppna %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "Kunde inte läsa block 0 från "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"Kanske gjordes inte några förändringar eller så uppdaterade inte Vim "
+"växlingsfilen."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " kan inte användas med den här versionen av Vim.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "Använd Vim version 3.0.\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s ser inte ut som en Vim-växlingsfil"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " kan inte användas på den här datorn.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "Filen skapades på "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"eller så har filen blivit skadad."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "Använder växlingsfil \"%s\""
+
+#: memline.c:909
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Orginalfil \"%s\""
+
+#: memline.c:922
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: Varning: Orginalfilen kan ha blivit skadad"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: Kunde inte läsa block 1 från %s"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???MÅNGA RADER SAKNAS"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???RADANTAL FEL"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???TOMT BLOCK"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???RADER SAKNAS"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: Block 1 ID fel (%s inte en .swp-fil?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???BLOCK SAKNAS"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? från här till ???SLUT kan rader vara tillstökade"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? från här till ???SLUT kan rader ha blivit infogade/borttagna"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "??SLUT"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: Återskapning avbruten"
+
+#: memline.c:1145
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr ""
+"E312: Fel upptäckt vid återskapning; titta efter rader som börjar med ???"
+
+#: memline.c:1148
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "Återskapning klar. Du borde kontrollera om allting är OK."
+
+#: memline.c:1149
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Du kanske vill spara den här filen under ett annat namn\n"
+
+#: memline.c:1150
+msgid "and run diff with the original file to check for changes)\n"
+msgstr ""
+"och kör diff med orginalfilen för att kontrollera efter förändringar)\n"
+
+#: memline.c:1151
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"Ta bort .swp-filen efteråt.\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1207
+msgid "Swap files found:"
+msgstr "Växlingsfiler hittade:"
+
+#: memline.c:1385
+msgid " In current directory:\n"
+msgstr " I aktuell katalog:\n"
+
+#: memline.c:1387
+msgid " Using specified name:\n"
+msgstr " Använder angivet namn:\n"
+
+#: memline.c:1391
+msgid " In directory "
+msgstr " I katalog "
+
+#: memline.c:1409
+msgid " -- none --\n"
+msgstr " -- inget --\n"
+
+#: memline.c:1481
+msgid " owned by: "
+msgstr " ägd av: "
+
+#: memline.c:1483
+msgid " dated: "
+msgstr " daterad: "
+
+#: memline.c:1487 memline.c:3701
+msgid " dated: "
+msgstr " daterad: "
+
+#: memline.c:1503
+msgid " [from Vim version 3.0]"
+msgstr " [från Vim version 3.0]"
+
+#: memline.c:1507
+msgid " [does not look like a Vim swap file]"
+msgstr " [ser inte ut som en Vim-växlingsfil]"
+
+#: memline.c:1511
+msgid " file name: "
+msgstr " filnamn: "
+
+#: memline.c:1517
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" modifierad: "
+
+#: memline.c:1518
+msgid "YES"
+msgstr "JA"
+
+#: memline.c:1518
+msgid "no"
+msgstr "nej"
+
+#: memline.c:1522
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" användarnamn: "
+
+#: memline.c:1529
+msgid " host name: "
+msgstr " värdnamn: "
+
+#: memline.c:1531
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" värdnamn: "
+
+#: memline.c:1537
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" process-ID: "
+
+#: memline.c:1543
+msgid " (still running)"
+msgstr " (körs fortfarande)"
+
+#: memline.c:1555
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [inte användbar med den här versionen av Vim]"
+
+#: memline.c:1558
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [inte användbar på den här datorn]"
+
+#: memline.c:1563
+msgid " [cannot be read]"
+msgstr " [kan inte läsas]"
+
+#: memline.c:1567
+msgid " [cannot be opened]"
+msgstr " [kan inte öppnas]"
+
+#: memline.c:1757
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: Kan inte bevara, det finns ingen växlingsfil"
+
+#: memline.c:1810
+msgid "File preserved"
+msgstr "Fil bevarad"
+
+#: memline.c:1812
+msgid "E314: Preserve failed"
+msgstr "E314: Bevaring misslyckades"
+
+#: memline.c:1883
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: ogiltigt lnum: %ld"
+
+#: memline.c:1909
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: kan inte hitta rad %ld"
+
+#: memline.c:2299
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: pekarblock-id fel 3"
+
+#: memline.c:2379
+msgid "stack_idx should be 0"
+msgstr "stack_idx ska vara 0"
+
+#: memline.c:2441
+msgid "E318: Updated too many blocks?"
+msgstr "E318: Uppdaterade för många block?"
+
+#: memline.c:2623
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: pekarblock-id fel 4"
+
+#: memline.c:2650
+msgid "deleted block 1?"
+msgstr "tagit bort block 1?"
+
+#: memline.c:2850
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: Kan inte hitta rad %ld"
+
+#: memline.c:3093
+msgid "E317: pointer block id wrong"
+msgstr "E317: pekarblock-id fel"
+
+#: memline.c:3109
+msgid "pe_line_count is zero"
+msgstr "pe_line_count är noll"
+
+#: memline.c:3138
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: radnummer utanför område: %ld bakom slutet"
+
+#: memline.c:3142
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: radantal fel i block %ld"
+
+#: memline.c:3191
+msgid "Stack size increases"
+msgstr "Stackstorlek ökar"
+
+#: memline.c:3237
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: pekarblock-id fel 2"
+
+#: memline.c:3691
+msgid "E325: ATTENTION"
+msgstr "E325: LYSTRING"
+
+#: memline.c:3692
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"Hittade en växlingsfil med namnet \""
+
+#: memline.c:3696
+msgid "While opening file \""
+msgstr "Vid öppning av fil \""
+
+#: memline.c:3705
+msgid " NEWER than swap file!\n"
+msgstr " NYARE än växelfil!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3709
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) Ett annat program kan redigera samma fil.\n"
+" Om så är fallet, var försiktig så att det inte slutar med två\n"
+" versioner av samma fil vid förändringar.\n"
+
+#: memline.c:3710
+msgid " Quit, or continue with caution.\n"
+msgstr " Avsluta, eller fortsätt på egen risk.\n"
+
+#: memline.c:3711
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) En redigeringssession för den här filen kraschade.\n"
+
+#: memline.c:3712
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Om så är fallet, använd \":recover\" eller \"vim -r "
+
+#: memline.c:3714
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" för att återskapa förändringarna (se \":help recovery\").\n"
+
+#: memline.c:3715
+msgid " If you did this already, delete the swap file \""
+msgstr " Om du redan har gjort det, ta bort växlingsfilen \""
+
+#: memline.c:3717
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" för att undvika det här meddelandet.\n"
+
+#: memline.c:3731 memline.c:3735
+msgid "Swap file \""
+msgstr "Växlingsfil \""
+
+#: memline.c:3732 memline.c:3738
+msgid "\" already exists!"
+msgstr "\" existerar redan!"
+
+#: memline.c:3741
+msgid "VIM - ATTENTION"
+msgstr "VIM - LYSTRING"
+
+#: memline.c:3743
+msgid "Swap file already exists!"
+msgstr "Växlingsfil existerar redan!"
+
+#: memline.c:3747
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"&Öppna skrivskyddad\n"
+"&Redigera ändå\n"
+"&Återskapa\n"
+"&Avsluta"
+
+#: memline.c:3749
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"&Öppna skrivskyddad\n"
+"&Redigera ändå\n"
+"&Återskapa\n"
+"&Avsluta\n"
+"&Ta bort den"
+
+#: memline.c:3802
+msgid "E326: Too many swap files found"
+msgstr "E326: För många växlingsfiler hittade"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: Del av menyföremål sökväg är inte undermeny"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: Meny existerar bara i ett annat läge"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: Ingen meny med det namnet"
+
+#: menu.c:509
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: Menysökväg får inte leda till en undermeny"
+
+#: menu.c:548
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: Får inte lägga till menyföremål direkt till menyrad"
+
+#: menu.c:554
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: Avskiljare kam inte vara en del av en menysökväg"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1081
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- Menyer ---"
+
+#: menu.c:1998
+msgid "Tear off this menu"
+msgstr "Ta loss den här menyn"
+
+#: menu.c:2063
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: Menysökväg måste leda till ett menyföremål"
+
+#: menu.c:2083
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: Meny hittades inte: %s"
+
+#: menu.c:2152
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: Meny inte definierad för %s läge"
+
+#: menu.c:2190
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: Menysökväg måste leda till en undermeny"
+
+#: menu.c:2211
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: Meny hittades inte - kontrollera menynamn"
+
+#: message.c:519
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "Fel upptäcktes vid bearbetning av %s:"
+
+#: message.c:535
+#, c-format
+msgid "line %4ld:"
+msgstr "rad %4ld:"
+
+#: message.c:575
+msgid "[string too long]"
+msgstr "[sträng för lång]"
+
+#: message.c:721
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "Meddelandeansvarig: Johan Svedberg <johan@svedberg.pp.se>"
+
+#: message.c:945
+msgid "Interrupt: "
+msgstr "Avbrott: "
+
+#: message.c:948
+msgid "Hit ENTER to continue"
+msgstr "Tryck RETUR för att fortsätta"
+
+#: message.c:950
+msgid "Hit ENTER or type command to continue"
+msgstr "Tryck RETUR eller skriv kommando för att fortsätta"
+
+#: message.c:2258
+msgid "-- More --"
+msgstr "-- Mer --"
+
+#: message.c:2261
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (ENT/BS: rad, BLANKSTEG/b: sida, d/u: halv sida q: avsluta"
+
+#: message.c:2262
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (ENT: rad, BLANKSTEG: sida d: halv sida q: avsluta)"
+
+#: message.c:2869 message.c:2884
+msgid "Question"
+msgstr "Fråga"
+
+#: message.c:2871
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Ja\n"
+"&Nej"
+
+#: message.c:2904
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Ja\n"
+"&Nej\n"
+"&Spara &alla\n"
+"&Kasta bort alla\n"
+"&Avbryt"
+
+#: message.c:2945
+msgid "Save File dialog"
+msgstr "Filsparandedialog"
+
+#: message.c:2947
+msgid "Open File dialog"
+msgstr "Filöppnandedialog"
+
+#. TODO: non-GUI file selector here
+#: message.c:3018
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: Tyvärr, ingen filbläddrare i konsoll-läge"
+
+#: misc1.c:2679
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: Varning: Ändrar en skrivskyddad fil"
+
+#: misc1.c:2918
+msgid "1 more line"
+msgstr "1 rad till"
+
+#: misc1.c:2920
+msgid "1 line less"
+msgstr "1 rad mindre"
+
+#: misc1.c:2925
+#, c-format
+msgid "%ld more lines"
+msgstr "%ld rad till"
+
+#: misc1.c:2927
+#, c-format
+msgid "%ld fewer lines"
+msgstr "%ld färre rader"
+
+#: misc1.c:2930
+msgid " (Interrupted)"
+msgstr " (Avbruten)"
+
+#: misc1.c:6602
+msgid "Vim: preserving files...\n"
+msgstr "Vim: bevarar filer...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6612
+msgid "Vim: Finished.\n"
+msgstr "Vim: Färdig.\n"
+
+#: misc2.c:670 misc2.c:686
+msgid "ERROR: "
+msgstr "FEL: "
+
+#: misc2.c:690
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bitar] sammanlagd allok-frigjord %lu-%lu, i användning %lu, toppanvändning %"
+"lu\n"
+
+#: misc2.c:692
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[anrop] sammanlagda om/malloc()'s %lu, sammanlagda free()'s %lu\n"
+"\n"
+
+#: misc2.c:747
+msgid "E340: Line is becoming too long"
+msgstr "E340: Rad börjar bli för lång"
+
+#: misc2.c:791
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: Internt fel: lalloc(%ld, )"
+
+#: misc2.c:899
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: Slut på minne! (allokerar %lu bitar)"
+
+#: misc2.c:2565
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "Anropar skal att köra: \"%s\""
+
+#: misc2.c:2787
+msgid "E545: Missing colon"
+msgstr "E545: Saknar kolon"
+
+#: misc2.c:2789 misc2.c:2816
+msgid "E546: Illegal mode"
+msgstr "E546: Otillåtet läge"
+
+#: misc2.c:2855
+msgid "E547: Illegal mouseshape"
+msgstr "E547: Otillåten musform"
+
+#: misc2.c:2895
+msgid "E548: digit expected"
+msgstr "E548: siffra förväntades"
+
+#: misc2.c:2900
+msgid "E549: Illegal percentage"
+msgstr "E549: Otillåten procentsats"
+
+#: misc2.c:3210
+msgid "Enter encryption key: "
+msgstr "Ange krypteringsnyckel: "
+
+#: misc2.c:3211
+msgid "Enter same key again: "
+msgstr "Ange samma nyckel igen: "
+
+#: misc2.c:3221
+msgid "Keys don't match!"
+msgstr "Nycklar matchar inte!"
+
+#: misc2.c:3770
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: Ogiltig sökväg: '**[nummer]' måste vara i slutet på sökvägen eller "
+"följas av '%s'."
+
+#: misc2.c:5049
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: Kan inte hitta katalog \"%s\" i cdpath"
+
+#: misc2.c:5052
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: Kan inte hitta fil \"%s\" i sökväg"
+
+#: misc2.c:5058
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: Ingen katalog \"%s\" hittades i cdpath"
+
+#: misc2.c:5061
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: Ingen fil \"%s\" hittades i sökvägen"
+
+#: misc2.c:5295
+msgid "E550: Missing colon"
+msgstr "E550: Saknar kolon"
+
+#: misc2.c:5307
+msgid "E551: Illegal component"
+msgstr "E551: Otillåten komponent"
+
+#: misc2.c:5315
+msgid "E552: digit expected"
+msgstr "E552: siffra förväntades"
+
+#. Get here when the server can't be found.
+#: netbeans.c:346
+msgid "Cannot connect to Netbeans #2"
+msgstr "Kan inte ansluta till Netbeans #2"
+
+#: netbeans.c:354
+msgid "Cannot connect to Netbeans"
+msgstr "Kan inte ansluta till Netbeans"
+
+#: netbeans.c:633
+msgid "read from Netbeans socket"
+msgstr "läs från Netbeans-uttag"
+
+#: normal.c:2944
+msgid "Warning: terminal cannot highlight"
+msgstr "Varning: terminal kan inte framhäva"
+
+#: normal.c:3159
+msgid "E348: No string under cursor"
+msgstr "E348: Ingen sträng under markör"
+
+#: normal.c:3161
+msgid "E349: No identifier under cursor"
+msgstr "E349: Ingen identifierare under markör"
+
+#: normal.c:4379
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: Kan inte ta bort veck med aktuell 'foldmethod'"
+
+#: normal.c:7802
+msgid "Type :quit<Enter> to exit Vim"
+msgstr "skriv :q<Enter> för att avsluta Vim "
+
+#: ops.c:295
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "1 rad %sad 1 gång"
+
+#: ops.c:297
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "1 rad %sade %d gånger"
+
+#: ops.c:302
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld rader %sad 1 gång"
+
+#: ops.c:305
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld rader %sade %d gånger"
+
+#: ops.c:663
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "%ld rader att indentera... "
+
+#: ops.c:713
+msgid "1 line indented "
+msgstr "1 rad indenterad "
+
+#: ops.c:715
+#, c-format
+msgid "%ld lines indented "
+msgstr "%ld rader indenterade "
+
+#. must display the prompt
+#: ops.c:1647
+msgid "cannot yank; delete anyway"
+msgstr "kan inte kopiera; ta bort ändå"
+
+#: ops.c:2155
+msgid "1 line changed"
+msgstr "1 rad ändrad"
+
+#: ops.c:2157
+#, c-format
+msgid "%ld lines changed"
+msgstr "%ld rader ändrade"
+
+#: ops.c:2541
+#, c-format
+msgid "freeing %ld lines"
+msgstr "frigör %ld rader"
+
+#: ops.c:2822
+msgid "1 line yanked"
+msgstr "1 rad kopierad"
+
+#: ops.c:2824
+#, c-format
+msgid "%ld lines yanked"
+msgstr "%ld rader kopierade"
+
+#: ops.c:3109
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: Ingenting i register %s"
+
+#. Highlight title
+#: ops.c:3660
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- Register ---"
+
+#: ops.c:4875
+msgid "Illegal register name"
+msgstr "Otillåtet registernamn"
+
+#: ops.c:4961
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# Register:\n"
+
+#: ops.c:4994
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: Okänd registertyp %d"
+
+#: ops.c:5480
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: Otillåtet registernamn: '%s'"
+
+#: ops.c:5840
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld kolumner; "
+
+#: ops.c:5847
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Markerade %s%ld av %ld rader; %ld av %ld ord; %ld av %ld bitar"
+
+#: ops.c:5863
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Kol %s av %s; rad %ld av %ld; ord %ld av %ld; bit %ld av %ld"
+
+#: ops.c:5874
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld för BOM)"
+
+#: option.c:1633
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=Sida %N"
+
+#: option.c:2082
+msgid "Thanks for flying Vim"
+msgstr "Tack för att du flyger med Vim"
+
+#: option.c:3354 option.c:3461
+msgid "E518: Unknown option"
+msgstr "E518: Okänd flagga"
+
+#: option.c:3367
+msgid "E519: Option not supported"
+msgstr "E519: Flagga inte stödd"
+
+#: option.c:3392
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: Inte tillåtet i en lägesrad"
+
+#: option.c:3448
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tSenast satt från "
+
+#: option.c:3587
+msgid "E521: Number required after ="
+msgstr "E521: Nummer krävs efter ="
+
+#: option.c:3914 option.c:4531
+msgid "E522: Not found in termcap"
+msgstr "E522: Inte hittat i termcap"
+
+#: option.c:3980
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: Otillåtet tecken <%s>"
+
+#: option.c:4523
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: Kan inte sätta 'term' till tom sträng"
+
+#: option.c:4526
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: Kan inte ändra term i GUI"
+
+#: option.c:4528
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: Använd \":gui\" för att starta GUI"
+
+#: option.c:4549
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: 'backuptext' och 'patchmode' är lika"
+
+#: option.c:4734
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: Kan inte bli ändrat i GTK+ 2-GUI"
+
+#: option.c:4890
+msgid "E524: Missing colon"
+msgstr "E524: Saknar kolon"
+
+#: option.c:4892
+msgid "E525: Zero length string"
+msgstr "E525: Nollängdssträng"
+
+#: option.c:4960
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: Saknar nummer efter <%s>"
+
+#: option.c:4974
+msgid "E527: Missing comma"
+msgstr "E527: Saknar komma"
+
+#: option.c:4981
+msgid "E528: Must specify a ' value"
+msgstr "E528: Måste ange ett '-värde"
+
+#: option.c:5022
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: innehåller outskrivbara eller breda tecken"
+
+#: option.c:5071
+msgid "E596: Invalid font(s)"
+msgstr "E596: Ogiltig(a) typsnitt"
+
+#: option.c:5079
+msgid "E597: can't select fontset"
+msgstr "E597: kan inte välja typsnittsuppsättning"
+
+#: option.c:5081
+msgid "E598: Invalid fontset"
+msgstr "E598: Ogiltig typsnittsuppsättning"
+
+#: option.c:5088
+msgid "E533: can't select wide font"
+msgstr "E533: kan inte välja brett typsnitt"
+
+#: option.c:5090
+msgid "E534: Invalid wide font"
+msgstr "E534: Ogiltigt brett typsnitt"
+
+#: option.c:5360
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: Otillåtet tecken efter <%c>"
+
+#: option.c:5465
+msgid "E536: comma required"
+msgstr "E536: komma krävs"
+
+#: option.c:5475
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: 'commentstring' måste vara tom eller innehålla %s"
+
+#: option.c:5548
+msgid "E538: No mouse support"
+msgstr "E538: Inget musstöd"
+
+#: option.c:5816
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: Ostängd uttryckssekvens"
+
+#: option.c:5820
+msgid "E541: too many items"
+msgstr "E541: för många föremål"
+
+#: option.c:5822
+msgid "E542: unbalanced groups"
+msgstr "E542: obalanserade grupper"
+
+#: option.c:6062
+msgid "E590: A preview window already exists"
+msgstr "E590: Ett förhandsvisningsfönster existerar redan"
+
+#: option.c:6319
+msgid "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"
+msgstr "W17: Arabiska kräver UTF-8, gör ':set encoding=utf-8'"
+
+#: option.c:6636
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: Behöver åtminstone %d rader"
+
+#: option.c:6645
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: Behöver åtminstone %d kolumner"
+
+#: option.c:6950
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: Okänd flagga: %s"
+
+#: option.c:7060
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Terminalkoder ---"
+
+#: option.c:7062
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Globala flaggvärden ---"
+
+#: option.c:7064
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Lokala flaggvärden ---"
+
+#: option.c:7066
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Flaggor ---"
+
+#: option.c:7767
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp-FEL"
+
+#: option.c:8738
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': Matchande tecken saknas för %s"
+
+#: option.c:8772
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': Extra tecken efter semikolon: %s"
+
+#: os_amiga.c:275
+msgid "cannot open "
+msgstr "kan inte öppna "
+
+#: os_amiga.c:309
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: Kan inte öppna fönster!\n"
+
+#: os_amiga.c:333
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "Behöver Amigados version 2.04 eller senare\n"
+
+#: os_amiga.c:339
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "Behöver %s version %ld\n"
+
+#: os_amiga.c:411
+msgid "Cannot open NIL:\n"
+msgstr "Kan inte öppna NIL:\n"
+
+#: os_amiga.c:422
+msgid "Cannot create "
+msgstr "Kan inte skapa "
+
+#: os_amiga.c:900
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim avslutar med %d\n"
+
+#: os_amiga.c:932
+msgid "cannot change console mode ?!\n"
+msgstr "kan inte ändra konsoll-läge ?!\n"
+
+#: os_amiga.c:998
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: inte en konsoll??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1147
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: Kan inte köra skal med -f-flagga"
+
+#: os_amiga.c:1188 os_amiga.c:1278
+msgid "Cannot execute "
+msgstr "Kan inte köra "
+
+#: os_amiga.c:1191 os_amiga.c:1288
+msgid "shell "
+msgstr "skal "
+
+#: os_amiga.c:1211 os_amiga.c:1313
+msgid " returned\n"
+msgstr " returnerade\n"
+
+#: os_amiga.c:1454
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE för liten."
+
+#: os_amiga.c:1458
+msgid "I/O ERROR"
+msgstr "I/O-FEL"
+
+#: os_mswin.c:525
+msgid "...(truncated)"
+msgstr "...(trunkerade)"
+
+#: os_mswin.c:627
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' är inte 80, kan inte köra externa kommandon"
+
+#: os_mswin.c:1866
+msgid "E237: Printer selection failed"
+msgstr "E237: Skrivarval misslyckades"
+
+#: os_mswin.c:1906
+#, c-format
+msgid "to %s on %s"
+msgstr "till %s på %s"
+
+#: os_mswin.c:1921
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: Okänt skrivartypsnitt: %s"
+
+#: os_mswin.c:1971 os_mswin.c:1981
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: Skrivarfel: %s"
+
+#: os_mswin.c:1982
+msgid "Unknown"
+msgstr "Okänd"
+
+#: os_mswin.c:2009
+#, c-format
+msgid "Printing '%s'"
+msgstr "Skriver ut '%s'"
+
+#: os_mswin.c:3095
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: Otillåtet teckenkodsnamn \"%s\" i typsnittsnamn \"%s\""
+
+#: os_mswin.c:3103
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: Otillåtet tecken '%c' i typsnittsnamn \"%s\""
+
+#: os_riscos.c:1258
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: Ogiltig 'osfiletype'-flagga - använder Text"
+
+#: os_unix.c:897
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: Dubbelsignal, avslutar\n"
+
+#: os_unix.c:903
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: Fångade dödlig signal %s\n"
+
+#: os_unix.c:906
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: Fångade dödlig signal\n"
+
+#: os_unix.c:1169
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "Öppning av X-display tog %ld ms"
+
+#: os_unix.c:1196
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: Fick X-error\n"
+
+#: os_unix.c:1304
+msgid "Testing the X display failed"
+msgstr "Testning av X-displayen misslyckades"
+
+#: os_unix.c:1443
+msgid "Opening the X display timed out"
+msgstr "Öppning av X-displayen tog för lång tid"
+
+#: os_unix.c:3190 os_unix.c:3870
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"Kan inte köra skal "
+
+#: os_unix.c:3238
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"Kan inte köra skal sh\n"
+
+#: os_unix.c:3242 os_unix.c:3876
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"skal returnerade "
+
+#: os_unix.c:3377
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"Kan inte skapa rör\n"
+
+#: os_unix.c:3392
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"Kan inte grena\n"
+
+#: os_unix.c:3883
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"Kommando avslutades\n"
+
+#: os_unix.c:4147 os_unix.c:4272 os_unix.c:5933
+msgid "XSMP lost ICE connection"
+msgstr "XSMP tappade ICE-anslutning"
+
+#: os_unix.c:5516
+msgid "Opening the X display failed"
+msgstr "Öppning av X-displayen misslyckades"
+
+#: os_unix.c:5838
+msgid "XSMP handling save-yourself request"
+msgstr "XSMP hanterar spara-själv-förfrågan"
+
+#: os_unix.c:5957
+msgid "XSMP opening connection"
+msgstr "XSMP öppnar anslutning"
+
+#: os_unix.c:5976
+msgid "XSMP ICE connection watch failed"
+msgstr "XSMP ICE-anslutning övervakning misslyckades"
+
+#: os_unix.c:5996
+#, c-format
+msgid "XSMP SmcOpenConnection failed: %s"
+msgstr "XSMP SmcOpenConnection misslyckades: %s"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "På rad"
+
+#: os_w32exe.c:65
+msgid "Could not allocate memory for command line."
+msgstr "Kunde inte allokera minne för kommandorad."
+
+#: os_w32exe.c:66 os_w32exe.c:89 os_w32exe.c:100
+msgid "VIM Error"
+msgstr "VIM-fel"
+
+#: os_w32exe.c:89
+msgid "Could not load vim32.dll!"
+msgstr "Kunde inte läsa in vim32.dll!"
+
+#: os_w32exe.c:99
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "Kunde inte ordna upp funktionspekare till DLL:en!"
+
+#: os_win16.c:341 os_win32.c:3064
+#, c-format
+msgid "shell returned %d"
+msgstr "skal returnerade %d"
+
+#: os_win32.c:2522
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: Fångade %s-händelse\n"
+
+#: os_win32.c:2524
+msgid "close"
+msgstr "stäng"
+
+#: os_win32.c:2526
+msgid "logoff"
+msgstr "logga ut"
+
+#: os_win32.c:2527
+msgid "shutdown"
+msgstr "stäng av"
+
+#: os_win32.c:3017
+msgid "E371: Command not found"
+msgstr "E371: Kommando hittades inte"
+
+#: os_win32.c:3030
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"VIMRUN.EXE hittades inte i din $PATH.\n"
+"Externa kommandon vill inte stå stilla efter färdigställning.\n"
+"Se :help win32-vimrun för mer information."
+
+#: os_win32.c:3033
+msgid "Vim Warning"
+msgstr "Vim-varning"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: För många %%%c i formatsträng"
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: Oväntad %%%c i formatsträng"
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: Saknar ] i formatsträng"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: Ostödd %%%c i formatsträng"
+
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: Ogiltig %%%c i formatsträngprefix"
+
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: Ogiltig %%%c i formatsträng"
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' innehåller inga mönster"
+
+#: quickfix.c:501
+msgid "E379: Missing or empty directory name"
+msgstr "E379: Saknar eller tomt katalognamn"
+
+#: quickfix.c:988
+msgid "E553: No more items"
+msgstr "E553: Inga fler föremål"
+
+#: quickfix.c:1225
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d av %d)%s%s: "
+
+#: quickfix.c:1227
+msgid " (line deleted)"
+msgstr " (rad borttagen)"
+
+#: quickfix.c:1440
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: På botten av quickfix-stack"
+
+#: quickfix.c:1449
+msgid "E381: At top of quickfix stack"
+msgstr "E381: På toppen av quickfix-stack"
+
+#: quickfix.c:1461
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "fellista %d av %d; %d fel"
+
+#: quickfix.c:1939
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: Kan inte skriva, 'buftype'-flagga är satt"
+
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: ogiltigt föremål i %s%%[]"
+
+#: regexp.c:827
+msgid "E339: Pattern too long"
+msgstr "E339: Mönster för långt"
+
+#: regexp.c:996
+msgid "E50: Too many \\z("
+msgstr "E50: För många \\z("
+
+#: regexp.c:1007
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: För många %s("
+
+#: regexp.c:1064
+msgid "E52: Unmatched \\z("
+msgstr "E52: Omatchade \\z("
+
+#: regexp.c:1068
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: Omatchade %s%%("
+
+#: regexp.c:1070
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: Omatchade %s("
+
+#: regexp.c:1075
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: Omatchade %s)"
+
+#: regexp.c:1244
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: %s*-operand kan vara tom"
+
+#: regexp.c:1247
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E57: %s+-operand kan vara tom"
+
+#: regexp.c:1301
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: ogiltigt tecken efter %s@"
+
+#: regexp.c:1326
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: %s{-operand kan vara tom"
+
+#: regexp.c:1336
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: För många komplexa %s{...}s"
+
+#: regexp.c:1352
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: Nästlade %s*"
+
+#: regexp.c:1355
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: Nästlade %s%c"
+
+#: regexp.c:1473
+msgid "E63: invalid use of \\_"
+msgstr "E63: ogiltig användning av \\_"
+
+#: regexp.c:1518
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c följer ingenting"
+
+#: regexp.c:1574
+msgid "E65: Illegal back reference"
+msgstr "E65: Otillåten bakåtreferens"
+
+#: regexp.c:1587
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z{ inte tillåtet här"
+
+#: regexp.c:1606
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 m.fl. inte tillåtet här"
+
+#: regexp.c:1617
+msgid "E68: Invalid character after \\z"
+msgstr "E68: Ogiltigt tecken efter \\z"
+
+#: regexp.c:1666
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: Saknar ] efter %s%%["
+
+#: regexp.c:1682
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: Tom %s%%[]"
+
+#: regexp.c:1742
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: Ogiltigt tecken efter %s%%"
+
+#: regexp.c:2539
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: Syntaxfel i %s{...}"
+
+#: regexp.c:2800
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: Krasch hejdad; reguljärt uttryck för komplext?"
+
+#: regexp.c:2941
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: mönster orsakade slut-på-stack-fel"
+
+#: regexp.c:3180
+msgid "External submatches:\n"
+msgstr "Externa underträffar:\n"
+
+#: screen.c:2115
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--%3ld rader vikta "
+
+#: screen.c:7892
+msgid " VREPLACE"
+msgstr " VERSÄTT"
+
+#: screen.c:7896
+msgid " REPLACE"
+msgstr " ERSÄTT"
+
+#: screen.c:7901
+msgid " REVERSE"
+msgstr " OMVÄND"
+
+#: screen.c:7903
+msgid " INSERT"
+msgstr " INFOGA"
+
+#: screen.c:7906
+msgid " (insert)"
+msgstr " (infoga)"
+
+#: screen.c:7908
+msgid " (replace)"
+msgstr " (ersätt)"
+
+#: screen.c:7910
+msgid " (vreplace)"
+msgstr " (versätt)"
+
+#: screen.c:7913
+msgid " Hebrew"
+msgstr " Hebreiska"
+
+#: screen.c:7924
+msgid " Arabic"
+msgstr " Arabiska"
+
+#: screen.c:7927
+msgid " (lang)"
+msgstr " (språk)"
+
+#: screen.c:7931
+msgid " (paste)"
+msgstr " (klistra in)"
+
+#: screen.c:7937
+msgid " SELECT"
+msgstr " MARKERA"
+
+#: screen.c:7939
+msgid " VISUAL"
+msgstr " VISUELL"
+
+#: screen.c:7941
+msgid " BLOCK"
+msgstr " BLOCK"
+
+#: screen.c:7943
+msgid " LINE"
+msgstr " RAD"
+
+#: screen.c:7956 screen.c:8016
+msgid "recording"
+msgstr "spelar in"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "sökning nådde TOPPEN, fortsätter vid BOTTEN"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "sökning nådde BOTTEN, forsätter vid TOPPEN"
+
+#: search.c:525
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: Ogiltig söksträng: %s"
+
+#: search.c:852
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: sökning nådde TOPPEN utan träff av: %s"
+
+#: search.c:855
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: sökning nådde BOTTEN utan träff av: %s"
+
+#: search.c:1247
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: Förväntade '?' eller '/' efter ';'"
+
+#: search.c:3709
+msgid " (includes previously listed match)"
+msgstr " (inkluderar tidigare listad träff)"
+
+#. cursor at status line
+#: search.c:3729
+msgid "--- Included files "
+msgstr "--- Inkluderade filer "
+
+#: search.c:3731
+msgid "not found "
+msgstr "hittades inte "
+
+#: search.c:3732
+msgid "in path ---\n"
+msgstr "i sökväg ---\n"
+
+#: search.c:3771
+msgid " (Already listed)"
+msgstr " (Redan listade)"
+
+#: search.c:3773
+msgid " NOT FOUND"
+msgstr " INTE HITTADE"
+
+#: search.c:3825
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "Söker igenom inkluderad fil: %s"
+
+#: search.c:4043
+msgid "E387: Match is on current line"
+msgstr "E387: Matchning är på aktuell rad"
+
+#: search.c:4186
+msgid "All included files were found"
+msgstr "Alla inkluderade filer hittades"
+
+#: search.c:4188
+msgid "No included files"
+msgstr "Inga inkluderade filer"
+
+#: search.c:4204
+msgid "E388: Couldn't find definition"
+msgstr "E388: Kunde inte hitta definition"
+
+#: search.c:4206
+msgid "E389: Couldn't find pattern"
+msgstr "E389: Kunde inte hitta mönster"
+
+#: syntax.c:3023
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: Otillåtet argument: %s"
+
+#: syntax.c:3203
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: Inget sådant syntax-kluster: %s"
+
+#: syntax.c:3367
+msgid "No Syntax items defined for this buffer"
+msgstr "Inga syntax-föremål definierade för den här bufferten"
+
+#: syntax.c:3375
+msgid "syncing on C-style comments"
+msgstr "synkning av C-stil-kommentarer"
+
+#: syntax.c:3383
+msgid "no syncing"
+msgstr "ingen synkning"
+
+#: syntax.c:3386
+msgid "syncing starts "
+msgstr "synkning startar"
+
+#: syntax.c:3388 syntax.c:3463
+msgid " lines before top line"
+msgstr " rader före topprad"
+
+#: syntax.c:3393
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Syntax-synkföremål ---"
+
+#: syntax.c:3398
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"synkning av föremål"
+
+#: syntax.c:3404
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Syntax föremål ---"
+
+#: syntax.c:3427
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: Inga sådana syntaxkluster: %s"
+
+#: syntax.c:3453
+msgid "minimal "
+msgstr "minimal "
+
+#: syntax.c:3460
+msgid "maximal "
+msgstr "maximal "
+
+#: syntax.c:3472
+msgid "; match "
+msgstr "; träff "
+
+#: syntax.c:3474
+msgid " line breaks"
+msgstr " radbrytningar"
+
+#: syntax.c:4108
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: grupper inte tillåtna här"
+
+#: syntax.c:4132
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: Hittade inte regionföremål för %s"
+
+#: syntax.c:4160
+msgid "E395: contains argument not accepted here"
+msgstr "E395: innehåller argument som inte är tillåtna här"
+
+#: syntax.c:4171
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: innehöll argument som inte är tillåtna här"
+
+#: syntax.c:4249
+msgid "E397: Filename required"
+msgstr "E397: Filnamn krävs"
+
+#: syntax.c:4587
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: Saknar '=': %s"
+
+#: syntax.c:4745
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: Inte tillräckliga argument: syntaxregion %s"
+
+#: syntax.c:5076
+msgid "E400: No cluster specified"
+msgstr "E400: Inget kluster angivet"
+
+#: syntax.c:5113
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: Mönsteravgränsare hittades inte: %s"
+
+#: syntax.c:5188
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: Skräp efter mönster: %s"
+
+#: syntax.c:5278
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: syntax-synk: radfortsättningsmönster angivet två gånger"
+
+#: syntax.c:5335
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: Otillåtna argument: %s"
+
+#: syntax.c:5385
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: Saknar likamed-tecken: %s"
+
+#: syntax.c:5391
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: Tomt argument: %s"
+
+#: syntax.c:5418
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s inte tillåtet här"
+
+#: syntax.c:5425
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s måste vara först i innehållslista"
+
+#: syntax.c:5495
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: Okänt gruppnamn: %s"
+
+#: syntax.c:5728
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: Ogiltigt :syntax-underkommando: %s"
+
+#: syntax.c:6107
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: framhävningsgrupp hittades inte: %s"
+
+#: syntax.c:6131
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: Inte tillräckliga argument: \":highlight länk %s\""
+
+#: syntax.c:6138
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: För många argument: \":highlight länk %s\""
+
+#: syntax.c:6158
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: grupp har inställningar, framhävningslänk ignorerad"
+
+#: syntax.c:6287
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: oväntat likamed-tecken: %s"
+
+#: syntax.c:6323
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: saknar likamed-tecken: %s"
+
+#: syntax.c:6345
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: saknar argument: %s"
+
+#: syntax.c:6382
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: Otillåtet värde: %s"
+
+#: syntax.c:6501
+msgid "E419: FG color unknown"
+msgstr "E419: FG-färg okänd"
+
+#: syntax.c:6512
+msgid "E420: BG color unknown"
+msgstr "E420: BG-färg okänd"
+
+#: syntax.c:6573
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: Färgnamn eller nummer inte igenkänt: %s"
+
+#: syntax.c:6779
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: terminalkod för lång: %s"
+
+#: syntax.c:6826
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: Otillåtet argument: %s"
+
+#: syntax.c:7355
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: För många olika framhävningsattribut i användning"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: på botten av taggstack"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: på toppen av taggstack"
+
+#: tag.c:396
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: Kan inte gå före första matchande tagg"
+
+#: tag.c:516
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: tagg hittades inte: %s"
+
+#: tag.c:549
+msgid " # pri kind tag"
+msgstr " # pri-typ-tagg"
+
+#: tag.c:552
+msgid "file\n"
+msgstr "fil\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:710
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "Ange nr av val (<CR> för att avbryta): "
+
+#: tag.c:750
+msgid "E427: There is only one matching tag"
+msgstr "E427: Det finns bara en matchande tagg"
+
+#: tag.c:752
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: Kan inte gå bortom sista matchande tagg"
+
+#: tag.c:772
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Fil \"%s\" existerar inte"
+
+#. Give an indication of the number of matching tags
+#: tag.c:785
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "tagg %d av %d%s"
+
+#: tag.c:788
+msgid " or more"
+msgstr " eller fler"
+
+#: tag.c:790
+msgid " Using tag with different case!"
+msgstr " Använder tagg med annan storlek!"
+
+#: tag.c:834
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Fil \"%s\" existerar inte"
+
+#. Highlight title
+#: tag.c:903
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # TILL tagg FRÅN LINJE i fil/text"
+
+#: tag.c:1210
+#, c-format
+msgid "Searching tags file %s"
+msgstr "Söker tagg-fil %s"
+
+#: tag.c:1396
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Taggfilsökväg trunkerades för %s\n"
+
+#: tag.c:1969
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Formateringsfel i tagg-fil \"%s\""
+
+#: tag.c:1973
+#, c-format
+msgid "Before byte %ld"
+msgstr "Före byte %ld"
+
+#: tag.c:1994
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Tagg-fil inte sorterad: %s"
+
+#. never opened any tags file
+#: tag.c:2034
+msgid "E433: No tags file"
+msgstr "E433: Ingen tagg-fil"
+
+#: tag.c:2742
+msgid "E434: Can't find tag pattern"
+msgstr "E434: Kan inte hitta taggmönster"
+
+#: tag.c:2753
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: Kunde inte hitta tagg, gissar bara!"
+
+#: term.c:1745
+msgid "' not known. Available builtin terminals are:"
+msgstr "' inte känd. Tillgängliga inbyggda terminaler är:"
+
+#: term.c:1769
+msgid "defaulting to '"
+msgstr "använder standard '"
+
+#: term.c:2127
+msgid "E557: Cannot open termcap file"
+msgstr "E557: Kan inte öppna termcap-fil"
+
+#: term.c:2131
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: Terminalnotering hittades inte i terminfo"
+
+#: term.c:2133
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: Terminalnotering hittades inte i termcap"
+
+#: term.c:2292
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: Ingen \"%s\"-notering i termcap"
+
+#: term.c:2766
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: terminalkapacitet \"cm\" krävs"
+
+#. Highlight title
+#: term.c:4973
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Terminalnycklar ---"
+
+#: ui.c:252
+msgid "new shell started\n"
+msgstr "nytt skal startat\n"
+
+#: ui.c:1791
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: Fel vid läsning av inmatning, avslutar...\n"
+
+#. must display the prompt
+#: undo.c:394
+msgid "No undo possible; continue anyway"
+msgstr "Ingen ångring möjlig; fortsätter ändå"
+
+#: undo.c:549
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: radnummer fel"
+
+#: undo.c:718
+msgid "1 change"
+msgstr "1 ändring"
+
+#: undo.c:720
+#, c-format
+msgid "%ld changes"
+msgstr "%ld ändringar"
+
+#: undo.c:764
+msgid "E439: undo list corrupt"
+msgstr "E439: ångra-lista trasig"
+
+#: undo.c:796
+msgid "E440: undo line missing"
+msgstr "E440: ångra-rad saknas"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:1131
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 16/32-bitars GUI-version"
+
+#: version.c:1133
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 32-bitars GUI-version"
+
+#: version.c:1136
+msgid " in Win32s mode"
+msgstr " i Win32s-läge"
+
+#: version.c:1138
+msgid " with OLE support"
+msgstr " med OLE-stöd"
+
+#: version.c:1141
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"MS-Windows 32-bitars konsollversion"
+
+#: version.c:1145
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"MS-Windows 16-bitars version"
+
+#: version.c:1149
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32-bitars MS-DOS-version"
+
+#: version.c:1151
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16-bitars MS-DOS-version"
+
+#: version.c:1157
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X-version (unix)"
+
+#: version.c:1159
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X-version"
+
+#: version.c:1162
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS-version"
+
+#: version.c:1167
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS-version"
+
+#: version.c:1177
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"Inkluderade patchar: "
+
+#: version.c:1203 version.c:1571
+msgid "Modified by "
+msgstr "Modifierad av "
+
+#: version.c:1210
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"Kompilerad "
+
+#: version.c:1213
+msgid "by "
+msgstr "av "
+
+#: version.c:1225
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"Enorm version "
+
+#: version.c:1228
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"Stor version "
+
+#: version.c:1231
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Normal version "
+
+#: version.c:1234
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"Liten version "
+
+#: version.c:1236
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"Jätteliten version "
+
+#: version.c:1242
+msgid "without GUI."
+msgstr "utan GUI."
+
+#: version.c:1247
+msgid "with GTK2-GNOME GUI."
+msgstr "med GTK2-GNOME-GUI."
+
+#: version.c:1249
+msgid "with GTK-GNOME GUI."
+msgstr "med GTK-GNOME-GUI."
+
+#: version.c:1253
+msgid "with GTK2 GUI."
+msgstr "med GTK2-GUI."
+
+#: version.c:1255
+msgid "with GTK GUI."
+msgstr "med GTK-GUI."
+
+#: version.c:1260
+msgid "with X11-Motif GUI."
+msgstr "med X11-Motif-GUI."
+
+#: version.c:1264
+msgid "with X11-neXtaw GUI."
+msgstr "med X11-neXtaw-GUI."
+
+#: version.c:1266
+msgid "with X11-Athena GUI."
+msgstr "med X11-Athena-GUI."
+
+#: version.c:1270
+msgid "with BeOS GUI."
+msgstr "med BeOS-GUI."
+
+#: version.c:1273
+msgid "with Photon GUI."
+msgstr "med Photon-GUI."
+
+#: version.c:1276
+msgid "with GUI."
+msgstr "med GUI."
+
+#: version.c:1279
+msgid "with Carbon GUI."
+msgstr "med Carbon-GUI."
+
+#: version.c:1282
+msgid "with Cocoa GUI."
+msgstr "med Cocoa-GUI."
+
+#: version.c:1285
+msgid "with (classic) GUI."
+msgstr "med (klassiskt) GUI."
+
+#: version.c:1296
+msgid " Features included (+) or not (-):\n"
+msgstr " Funktioner inkluderade (+) eller inte (-):\n"
+
+#: version.c:1308
+msgid " system vimrc file: \""
+msgstr " system-vimrc-fil: \""
+
+#: version.c:1313
+msgid " user vimrc file: \""
+msgstr " användar-vimrc-fil: \""
+
+#: version.c:1318
+msgid " 2nd user vimrc file: \""
+msgstr " Andra användar-vimrc-fil: \""
+
+#: version.c:1323
+msgid " 3rd user vimrc file: \""
+msgstr " Tredje användar-vimrc-fil: \""
+
+#: version.c:1328
+msgid " user exrc file: \""
+msgstr " användar-exrc-fil: \""
+
+#: version.c:1333
+msgid " 2nd user exrc file: \""
+msgstr " Andra användar-exrc-fil: \""
+
+#: version.c:1339
+msgid " system gvimrc file: \""
+msgstr " system-gvimrc-fil: \""
+
+#: version.c:1343
+msgid " user gvimrc file: \""
+msgstr " användar-gvimrc-fil: \""
+
+#: version.c:1347
+msgid "2nd user gvimrc file: \""
+msgstr "Andra användar-gvimrc-fil: \""
+
+#: version.c:1352
+msgid "3rd user gvimrc file: \""
+msgstr "Tredje användar-gvimrc-fil: \""
+
+#: version.c:1359
+msgid " system menu file: \""
+msgstr " systemmenyfil: \""
+
+#: version.c:1367
+msgid " fall-back for $VIM: \""
+msgstr " reserv för $VIM: \""
+
+#: version.c:1373
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " reserv för $VIMRUNTIME: \""
+
+#: version.c:1377
+msgid "Compilation: "
+msgstr "Kompilering: "
+
+#: version.c:1383
+msgid "Compiler: "
+msgstr "Kompilator: "
+
+#: version.c:1388
+msgid "Linking: "
+msgstr "Länkning: "
+
+#: version.c:1393
+msgid " DEBUG BUILD"
+msgstr " FELSÖKNINGSBYGGD"
+
+#: version.c:1432
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved"
+
+#: version.c:1434
+msgid "version "
+msgstr "version "
+
+#: version.c:1435
+msgid "by Bram Moolenaar et al."
+msgstr "av Bram Moolenaar m.fl."
+
+#: version.c:1439
+msgid "Vim is open source and freely distributable"
+msgstr "Vim är öppen källkod och fri att distribuera"
+
+#: version.c:1441
+msgid "Help poor children in Uganda!"
+msgstr "Hjälp fattiga barn i Uganda!"
+
+#: version.c:1442
+msgid "type :help iccf<Enter> for information "
+msgstr "skriv :help iccf<Enter> för information "
+
+#: version.c:1444
+msgid "type :q<Enter> to exit "
+msgstr "skriv :q<Enter> för att avsluta "
+
+#: version.c:1445
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "skriv :help<Enter> eller <F1> för online-hjälp "
+
+#: version.c:1446
+msgid "type :help version6<Enter> for version info"
+msgstr "skriv :help version6<Enter> för versioninformation "
+
+#: version.c:1449
+msgid "Running in Vi compatible mode"
+msgstr "Kör i Vi-kompatibelt läge"
+
+#: version.c:1450
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "skriv :set nocp<Enter> för Vim- standarder "
+
+#: version.c:1451
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "skriv :help cp-default<Enter> för information om det här"
+
+#: version.c:1466
+msgid "menu Help->Orphans for information "
+msgstr "meny Hjälp->Föräldralösa för information "
+
+#: version.c:1468
+msgid "Running modeless, typed text is inserted"
+msgstr "Kör lägeslöst, skriven text blir infogad"
+
+#: version.c:1469
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "meny Redigera->Globala inställningar->Växla infogningsläge "
+
+#: version.c:1470
+msgid " for two modes "
+msgstr " för två lägen "
+
+#: version.c:1474
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "meny Redigera->Globala Inställningar->Växla Vi Komptaibel"
+
+#: version.c:1475
+msgid " for Vim defaults "
+msgstr " för vim-standardalternativ "
+
+#: version.c:1522
+msgid "Sponsor Vim development!"
+msgstr "Stöd utvecklingen av Vim!"
+
+#: version.c:1523
+msgid "Become a registered Vim user!"
+msgstr "Bli en registrerad Vim-användare!"
+
+#: version.c:1526
+msgid "type :help sponsor<Enter> for information "
+msgstr "skriv :help sponsor<Enter> för information "
+
+#: version.c:1527
+msgid "type :help register<Enter> for information "
+msgstr "skriv :help register<Enter> för information "
+
+#: version.c:1529
+msgid "menu Help->Sponsor/Register for information "
+msgstr "meny Hjälp->Stöd/Registrera för information "
+
+#: version.c:1539
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "VARNING: Windows 95/98/ME upptäckt"
+
+#: version.c:1542
+msgid "type :help windows95<Enter> for info on this"
+msgstr "skriv :help windows95<Enter> för info om det här"
+
+#: window.c:203
+msgid "E441: There is no preview window"
+msgstr "E441: Det finns inget förhandsvisningsfönster"
+
+#: window.c:581
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: Kan inte dela toppvänster och bottenhöger samtidigt"
+
+#: window.c:1340
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: Kan inte rotera när ett annat fönster är delat"
+
+#: window.c:1835
+msgid "E444: Cannot close last window"
+msgstr "E444: Kan inte stänga senaste fönstret"
+
+#: window.c:2566
+msgid "Already only one window"
+msgstr "Redan bara ett fönster"
+
+#: window.c:2613
+msgid "E445: Other window contains changes"
+msgstr "E445: Andra fönster innehåller ändringar"
+
+#: window.c:4474
+msgid "E446: No file name under cursor"
+msgstr "E446: Inget filnamn under markör"
+
+#: window.c:4593
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: Kan inte hitta fil \"%s\" i sökväg"
+
+#: globals.h:1209 if_perl.xs:326
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: Kunde inte läsa in bibliotek %s"
+
+#: if_perl.xs:554
+msgid "Sorry, this command is disabled: the Perl library could not be loaded."
+msgstr ""
+"Tyvärr, det här kommandot är inaktiverat: Perl-biblioteket kunde inte läsas "
+"in."
+
+#: if_perl.xs:600
+msgid "E299: Perl evaluation forbidden in sandbox without the Safe module"
+msgstr "E299: Perl-evaluering förbjuden i sandlåda utan Safe-modulen"
+
+#: GvimExt/gvimext.cpp:583
+msgid "Edit with &multiple Vims"
+msgstr "Redigera med &flera Vims"
+
+#: GvimExt/gvimext.cpp:589
+msgid "Edit with single &Vim"
+msgstr "Redigera med en &Vim"
+
+#: GvimExt/gvimext.cpp:598
+msgid "&Diff with Vim"
+msgstr "&Diff med Vim"
+
+#: GvimExt/gvimext.cpp:611
+msgid "Edit with &Vim"
+msgstr "Redigera med &Vim"
+
+#. Now concatenate
+#: GvimExt/gvimext.cpp:633
+msgid "Edit with existing Vim - &"
+msgstr "Redigera med befintlig Vim - &"
+
+#: GvimExt/gvimext.cpp:746
+msgid "Edits the selected file(s) with Vim"
+msgstr "Redigerar markerade fil(erna) med Vim"
+
+#: GvimExt/gvimext.cpp:885 GvimExt/gvimext.cpp:966
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "Felskapande process: Kontrollera om gvim är i din sökväg!"
+
+#: GvimExt/gvimext.cpp:886 GvimExt/gvimext.cpp:900 GvimExt/gvimext.cpp:967
+msgid "gvimext.dll error"
+msgstr "gvimext.dll-fel"
+
+#: GvimExt/gvimext.cpp:899
+msgid "Path length too long!"
+msgstr "Sökvägslängd för lång!"
+
+#: globals.h:999
+msgid "--No lines in buffer--"
+msgstr "--Inga rader i buffert--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1162
+msgid "E470: Command aborted"
+msgstr "E470: Kommando avbrutet"
+
+#: globals.h:1163
+msgid "E471: Argument required"
+msgstr "E471: Argument krävs"
+
+#: globals.h:1164
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ borde följas av /, ? eller &"
+
+#: globals.h:1166
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: Felaktighet i kommandoradsfönster; <CR> kör, CTRL-C avslutar"
+
+#: globals.h:1168
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr ""
+"E12: Kommando inte tillåtet från exrc/vimrc i aktuell katalog eller "
+"taggsökning"
+
+#: globals.h:1170
+msgid "E171: Missing :endif"
+msgstr "E171: Saknar :endif"
+
+#: globals.h:1171
+msgid "E600: Missing :endtry"
+msgstr "E600: Saknar :endtry"
+
+#: globals.h:1172
+msgid "E170: Missing :endwhile"
+msgstr "E170: Saknar :endwhile"
+
+#: globals.h:1173
+msgid "E588: :endwhile without :while"
+msgstr "E588: :endwhile utan :while"
+
+#: globals.h:1175
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Fil existerar (lägg till ! för att tvinga)"
+
+#: globals.h:1176
+msgid "E472: Command failed"
+msgstr "E472: Kommando misslyckades"
+
+#: globals.h:1178
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: Okänd typsnittsuppsättning: %s"
+
+#: globals.h:1182
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "E235: Okänt typsnitt: %s"
+
+#: globals.h:1185
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: Typsnitt \"%s\" är inte bredd-fixerad"
+
+#: globals.h:1187
+msgid "E473: Internal error"
+msgstr "E473: Internt fel"
+
+#: globals.h:1188
+msgid "Interrupted"
+msgstr "Avbruten"
+
+#: globals.h:1189
+msgid "E14: Invalid address"
+msgstr "E14: Ogiltig address"
+
+#: globals.h:1190
+msgid "E474: Invalid argument"
+msgstr "E474: Ogiltigt argument"
+
+#: globals.h:1191
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: Ogiltigt argument: %s"
+
+#: globals.h:1193
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: Ogiltigt uttryck: %s"
+
+#: globals.h:1195
+msgid "E16: Invalid range"
+msgstr "E16: Ogiltigt område"
+
+#: globals.h:1196
+msgid "E476: Invalid command"
+msgstr "E476: Ogiltigt kommando"
+
+#: globals.h:1198
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" är en katalog"
+
+#: globals.h:1201
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: Oväntade tecken före '='"
+
+#: globals.h:1204
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: Biblioteksanrop misslyckades för \"%s()\""
+
+#: globals.h:1210
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: Kunde inte läsa in biblioteksfunktion %s"
+
+#: globals.h:1212
+msgid "E19: Mark has invalid line number"
+msgstr "E19: Markering har ogiltigt radnummer"
+
+#: globals.h:1213
+msgid "E20: Mark not set"
+msgstr "E20: Markering inte satt"
+
+#: globals.h:1214
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: Kan inte göra ändringar, 'modifiable' är av"
+
+#: globals.h:1215
+msgid "E22: Scripts nested too deep"
+msgstr "E22: Skript nästlade för djupt"
+
+#: globals.h:1216
+msgid "E23: No alternate file"
+msgstr "E23: Ingen alternativ fil"
+
+#: globals.h:1217
+msgid "E24: No such abbreviation"
+msgstr "E24: Ingen sådan förkortning"
+
+#: globals.h:1218
+msgid "E477: No ! allowed"
+msgstr "E477: Inget ! tillåtet"
+
+#: globals.h:1220
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: GUI kan inte användas: Inte aktiverat vid kompilering"
+
+#: globals.h:1223
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: Hebreiska kan inte användas: Inte aktiverat vid kompilering\n"
+
+#: globals.h:1226
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: Persiska kan inte användas: Inte aktiverat vid kompilering\n"
+
+#: globals.h:1229
+msgid "E800: Arabic cannot be used: Not enabled at compile time\n"
+msgstr "E800: Arabiska kan inte användas: Inte aktiverat vid kompilering\n"
+
+#: globals.h:1232
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: Inget sådant framhävningsgruppnamn: %s"
+
+#: globals.h:1234
+msgid "E29: No inserted text yet"
+msgstr "E29: Ingen infogad text än"
+
+#: globals.h:1235
+msgid "E30: No previous command line"
+msgstr "E30: Ingen tidigare kommandorad"
+
+#: globals.h:1236
+msgid "E31: No such mapping"
+msgstr "E31: Ingen sådan mappning"
+
+#: globals.h:1237
+msgid "E479: No match"
+msgstr "E479: Ingen träff"
+
+#: globals.h:1238
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: Ingen träff: %s"
+
+#: globals.h:1239
+msgid "E32: No file name"
+msgstr "E32: Inget filnamn"
+
+#: globals.h:1240
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: Inget tidigare utbytningsreguljäruttryck"
+
+#: globals.h:1241
+msgid "E34: No previous command"
+msgstr "E34: Inget tidigare kommando"
+
+#: globals.h:1242
+msgid "E35: No previous regular expression"
+msgstr "E35: Inget tidigare reguljärt uttryck"
+
+#: globals.h:1243
+msgid "E481: No range allowed"
+msgstr "E481: Inget område tillåtet"
+
+#: globals.h:1245
+msgid "E36: Not enough room"
+msgstr "E36: Inte tillräckligt med utrymme"
+
+#: globals.h:1248
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: ingen registrerad server med namnet \"%s\""
+
+#: globals.h:1250
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: Kan inte skapa fil %s"
+
+#: globals.h:1251
+msgid "E483: Can't get temp file name"
+msgstr "E483: Kan inte hämta temporärt filnamn"
+
+#: globals.h:1252
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: Kan inte öppna fil %s"
+
+#: globals.h:1253
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: Kan inte läsa fil %s"
+
+#: globals.h:1254
+msgid "E37: No write since last change (add ! to override)"
+msgstr ""
+"E37: Ingen skrivning sedan senaste ändring (lägg till ! för att tvinga)"
+
+#: globals.h:1255
+msgid "E38: Null argument"
+msgstr "E38: Null-argument"
+
+#: globals.h:1257
+msgid "E39: Number expected"
+msgstr "E39: Nummer väntat"
+
+#: globals.h:1260
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: Kan inte öppna felfil %s"
+
+#: globals.h:1263
+msgid "E233: cannot open display"
+msgstr "E233: kan inte öppna display"
+
+#: globals.h:1265
+msgid "E41: Out of memory!"
+msgstr "E41: Slut på minne!"
+
+#: globals.h:1267
+msgid "Pattern not found"
+msgstr "Mönster hittades inte"
+
+#: globals.h:1269
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: Mönster hittades inte: %s"
+
+#: globals.h:1270
+msgid "E487: Argument must be positive"
+msgstr "E487: Argument måste vara positivt"
+
+#: globals.h:1272
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: Kan inte gå tillbaka till tidigare katalog"
+
+#: globals.h:1276
+msgid "E42: No Errors"
+msgstr "E42: Inga fel"
+
+#: globals.h:1278
+msgid "E43: Damaged match string"
+msgstr "E43: Skadad träffsträng"
+
+#: globals.h:1279
+msgid "E44: Corrupted regexp program"
+msgstr "E44: Trasigt program för reguljära uttryck"
+
+#: globals.h:1280
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: 'readonly' flagga är satt (lägg till ! för att tvinga)"
+
+#: globals.h:1282
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: Kan inte sätta skrivskyddad variabel \"%s\""
+
+#: globals.h:1285
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Fel vid läsning av felfil"
+
+#: globals.h:1288
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: Inte tillåtet i sandlåda"
+
+#: globals.h:1290
+msgid "E523: Not allowed here"
+msgstr "E523: Inte tillåtet här"
+
+#: globals.h:1293
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: Skärmläge inställning inte stödd"
+
+#: globals.h:1295
+msgid "E49: Invalid scroll size"
+msgstr "E49: Ogiltig rullningsstorlek"
+
+#: globals.h:1296
+msgid "E91: 'shell' option is empty"
+msgstr "E91: 'shell' flagga är tom"
+
+#: globals.h:1298
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: Kunde inte läsa in teckendata!"
+
+#: globals.h:1300
+msgid "E72: Close error on swap file"
+msgstr "E72: Stängningsfel på växlingsfil"
+
+#: globals.h:1301
+msgid "E73: tag stack empty"
+msgstr "E73: taggstack tom"
+
+#: globals.h:1302
+msgid "E74: Command too complex"
+msgstr "E74: Kommando för komplext"
+
+#: globals.h:1303
+msgid "E75: Name too long"
+msgstr "E75: Namn för långt"
+
+#: globals.h:1304
+msgid "E76: Too many ["
+msgstr "E76: För många ["
+
+#: globals.h:1305
+msgid "E77: Too many file names"
+msgstr "E77: För många filnamn"
+
+#: globals.h:1306
+msgid "E488: Trailing characters"
+msgstr "E488: Eftersläpande tecken"
+
+#: globals.h:1307
+msgid "E78: Unknown mark"
+msgstr "E78: Okänt märke"
+
+#: globals.h:1308
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: Kan inte expandera jokertecken"
+
+#: globals.h:1310
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: 'winheight' kan inte vara mindre än 'winminheight'"
+
+#: globals.h:1312
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: 'winwidth' kan inte vara mindre än 'winminwidth'"
+
+#: globals.h:1315
+msgid "E80: Error while writing"
+msgstr "E80: Fel vid skrivning"
+
+#: globals.h:1316
+msgid "Zero count"
+msgstr "Noll-längd"
+
+#: globals.h:1318
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: Använder inte <SID> i ett skriptsammanhang"
+
+#: globals.h:1321
+msgid "E449: Invalid expression received"
+msgstr "E449: Ogiltigt uttryck mottaget"
+
+#: globals.h:1324
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: Region är vaktad, kan inte modifiera"
+
+#~ msgid "E86: Cannot go to buffer %ld"
+#~ msgstr "E85: Kan inte gå till buffert %ld"
diff --git a/src/po/uk.po b/src/po/uk.po
new file mode 100644
index 000000000..f8223d3f2
--- /dev/null
+++ b/src/po/uk.po
@@ -0,0 +1,6225 @@
+#
+# Ukrainian Vim translation [uk]
+#
+# Copyright (C) 2001 Bohdan Vlasyuk <bohdan@vstu.edu.ua>
+#
+# Thanks to:
+# Dmytro Kovalov <dmytro.kovalov@nssmb.com> for useful suggestions
+# Dmytro O. Redchuk <dor@kiev-online.net> for viminfo bug
+#
+# Please, see readme at htpp://www.vstu.edu.ua/~bohdan/vim before any
+# complains, and even if you won't complain, read it anyway.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: vim 6.0\n"
+"POT-Creation-Date: 2002-01-10 09:03+0200\n"
+"PO-Revision-Date: 2001-10-16 13:34+0300\n"
+"Last-Translator: Bohdan Vlasyuk <bohdan@vstu.edu.ua>\n"
+"Language-Team: Bohdan Vlasyuk <bohdan@vstu.edu.ua>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=koi8-u\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: îÅÍÁ¤ ÍÏÖÌÉ×ÏÓÔ¦ ÒÏÚͦÓÔÉÔÉ ÈÏÞ ÏÄÉÎ ÂÕÆÅÒ, ÚÁ×ÅÒÛÅÎÎÑ ÒÏÂÏÔÉ..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: îÅÍÁ¤ ÍÏÖÌÉ×ÏÓÔ¦ ÒÏÚͦÓÔÉÔÉ ÂÕÆÅÒ, ÂÕÄÅ ×ÉËÏÒÉÓÔÁÎÏ ¦ÎÛÉÊ..."
+
+#: buffer.c:698
+msgid "No buffers were unloaded"
+msgstr "öÏÄÅÎ Ú ÂÕÆÅÒ¦× ÎÅ ÂÕ× ×É×ÁÎÔÁÖÅÎÉÊ"
+
+#: buffer.c:700
+msgid "No buffers were deleted"
+msgstr "öÏÄÅÎ Ú ÂÕÆÅÒ¦× ÎÅ ÂÕ× ×ÉÄÁÌÅÎÉÊ"
+
+#: buffer.c:702
+msgid "No buffers were wiped out"
+msgstr "öÏÄÅÎ Ú ÂÕÆÅÒ¦× ÎÅ ÂÕ× ×ÉÔÅÒÔÉÊ"
+
+#: buffer.c:710
+msgid "1 buffer unloaded"
+msgstr "÷É×ÁÎÔÁÖÅÎÏ ÏÄÉÎ ÂÕÆÅÒ"
+
+#: buffer.c:712
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "÷É×ÁÎÔÁÖÅÎÏ ÂÕÆÅÒ¦× -- %d"
+
+#: buffer.c:717
+msgid "1 buffer deleted"
+msgstr "÷ÉÄÁÌÅÎÏ ÏÄÉÎ ÂÕÆÅÒ"
+
+#: buffer.c:719
+#, c-format
+msgid "%d buffers deleted"
+msgstr "÷ÉÄÁÌÅÎÏ ÂÕÆÅÒ¦× -- %d"
+
+#: buffer.c:724
+msgid "1 buffer wiped out"
+msgstr "÷ÉÔÅÒÔÏ ÏÄÉÎ ÂÕÆÅÒ"
+
+#: buffer.c:726
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "÷ÉÔÅÒÔÏ ÂÕÆÅÒ¦× -- %d"
+
+#: buffer.c:783
+msgid "E84: No modified buffer found"
+msgstr "E84: öÏÄÅÎ ÂÕÆÅÒ ÎÅ ÚͦÎÅÎÏ"
+
+#. back where we started, didn't find anything.
+#: buffer.c:822
+msgid "E85: There is no listed buffer"
+msgstr "E85: õ ÓÐÉÓËÕ ÎÅÍÁ¤ ÂÕÆÅÒ¦×"
+
+#: buffer.c:834
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: îÅ ÍÏÖÕ ÐÅÒÅÊÔÉ × ÂÕÆÅÒ %ld"
+
+#: buffer.c:837
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: îÅ ÍÏÖÕ ÐÅÒÅÊÔÉ Õ ÎÁÓÔÕÐÎÉÊ ÂÕÆÅÒ Ú ÏÓÔÁÎÎØÏÇÏ"
+
+#: buffer.c:839
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: îÅ ÍÏÖÕ ÐÅÒÅÊÔÉ Õ ÐÏÐÅÒÅÄÎ¦Ê ÂÕÆÅÒ Ú ÐÅÒÛÏÇÏ"
+
+#: buffer.c:863
+#, c-format
+msgid "E89: No write since last change for buffer %ld (use ! to override)"
+msgstr ""
+"E89: âÕÆÅÒ %ld ÎÅ ÚÁÐÉÓÁÎÉÊ Ð¦ÓÌÑ ÏÓÔÁÎÎØϧ ÚͦÎÉ (×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÎÅ "
+"Ú×ÁÖÁÔÉ)"
+
+#: buffer.c:879
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: îÅ ÍÏÖÕ ×É×ÁÎÔÁÖÉÔÉ ÏÓÔÁÎÎ¦Ê ÂÕÆÅÒ"
+
+#: buffer.c:1314
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: ïÂÅÒÅÖÎÏ: óÐÉÓÏË ¦ÍÅÎ ÆÁÊÌ¦× ÐÅÒÅÐÏ×ÎÅÎÏ"
+
+#: buffer.c:1480
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: âÕÆÅÒ %ld ÎÅ ÚÎÁÊÄÅÎÏ"
+
+#: buffer.c:1700
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: úÎÁÊÄÅÎÏ Â¦ÌØÛÅ Î¦Ö ÏÄÉÎ ×ÁÒ¦ÁÎÔ ÄÌÑ %s"
+
+#: buffer.c:1702
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: îÅ ÚÎÁÊÄÅÎÏ ×ÁÒ¦ÁÎÔ¦× ÄÌÑ %s"
+
+#: buffer.c:2105 ex_docmd.c:6066
+#, c-format
+msgid "line %ld"
+msgstr "ÒÑÄÏË %ld"
+
+#: buffer.c:2188
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: âÕÆÅÒ Ú ÔÁËÏÀ ÎÁÚ×ÏÀ ÕÖÅ ¦ÓÎÕ¤"
+
+#: buffer.c:2481
+msgid " [Modified]"
+msgstr "[úͦÎÅÎÏ]"
+
+#: buffer.c:2486
+msgid "[Not edited]"
+msgstr "[îÅ ÂÕÌÏ ÒÅÄÁÇÏ×ÁÎÏ]"
+
+#: buffer.c:2491
+msgid "[New file]"
+msgstr "[îÏ×ÉÊ ÆÁÊÌ]"
+
+#: buffer.c:2492
+msgid "[Read errors]"
+msgstr "[ðÏÍÉÌËÁ ÚÞÉÔÕ×ÁÎÎÑ]"
+
+#: buffer.c:2494 fileio.c:1754
+msgid "[readonly]"
+msgstr "[ÌÉÛÅ ÞÉÔÁÔÉ]"
+
+#: buffer.c:2510
+msgid "1 line --%d%%--"
+msgstr "ÏÄÉÎ ÒÑÄÏË --%d%%--"
+
+#: buffer.c:2510
+msgid "%ld lines --%d%%--"
+msgstr "(ÒÑÄ˦×: %ld) --%d%%--"
+
+#: buffer.c:2518
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "ÒÑÄÏË %ld Ú %ld --%d%%-- ËÏÌÏÎËÁ"
+
+#: buffer.c:2606
+msgid "[No file]"
+msgstr "[îÏ×ÉÊ ÆÁÊÌ]"
+
+#. must be a help buffer
+#: buffer.c:2646
+msgid "help"
+msgstr "ÄÏÐÏÍÏÇÁ"
+
+#: buffer.c:3151 screen.c:4691
+msgid "[help]"
+msgstr "[ÄÏÐÏÍÏÇÁ]"
+
+#: buffer.c:3183 screen.c:4697
+msgid "[Preview]"
+msgstr "[ÐÅÒÅÇÌÑÄ]"
+
+#: buffer.c:3389
+msgid "All"
+msgstr "õÓÅ"
+
+#: buffer.c:3389
+msgid "Bot"
+msgstr "õÎÉÚÕ"
+
+#: buffer.c:3391
+msgid "Top"
+msgstr "÷ÇÏÒ¦"
+
+#: buffer.c:4127
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# óÐÉÓÏË ÂÕÆÅÒ¦×:\n"
+
+#: buffer.c:4160
+msgid "[Error List]"
+msgstr "[óÐÉÓÏË ÐÏÍÉÌÏË]"
+
+#: buffer.c:4173 memline.c:1513
+msgid "[No File]"
+msgstr "[îÏ×ÉÊ ÆÁÊÌ]"
+
+#: buffer.c:4393
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- úÎÁËÉ ---"
+
+#: buffer.c:4403
+#, c-format
+msgid "Signs for %s:"
+msgstr "úÎÁËÉ ÄÌÑ %s:"
+
+#: buffer.c:4409
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " ÒÑÄÏË=%ld id=%d ¦Í'Ñ=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: îÅ ÍÏÖÕ ÐÏÒ¦×ÎÀ×ÁÔÉ ÐÏÎÁÄ %ld ÂÕÆÅÒ¦× "
+
+#: diff.c:648
+msgid "E97: Cannot create diffs"
+msgstr "E97: îÅÍÏÖÎÁ ÓÔ×ÏÒÉÔÉ diff'É"
+
+#: diff.c:747
+msgid "Patch file"
+msgstr "patch-ÆÁÊÌ"
+
+#: diff.c:991
+msgid "E98: Cannot read diff output"
+msgstr "E98: îÅ ÍÏÖÕ ÚÞÉÔÁÔÉ ÒÅÚÕÌØÔÁÔ diff'Õ"
+
+#: diff.c:1704
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: ãÅÊ ÂÕÆÅÒ ÎÅ × ÒÅÖÉͦ diff"
+
+#: diff.c:1716
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: îÅÍÁÅ ¦ÎÛÉÈ ÂÕÆÅÒ¦× × ÒÅÖÉͦ diff"
+
+#: diff.c:1724
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr ""
+"E101: ðÏÎÁÄ Ä×Á ÂÕÆÅÒÁ ÚÎÁÈÏÄÑÔØÓÑ × ÒÅÖÉͦ diff, ÎÅ ÚÒÏÚÕͦÌÏ ÑËÉÊ Ú ÎÉÈ "
+"×ÉËÏÒÉÓÔÁÔÉ"
+
+#: diff.c:1747
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: âÕÆÅÒ \"%s\" ÎÅ ÚÎÁÊÄÅÎÏ"
+
+#: diff.c:1753
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: âÕÆÅÒ \"%s\" ÎÅ × ÒÅÖÉͦ diff"
+
+#: digraph.c:2168
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: õ ÄÉÇÒÁÆÁÈ ÎÅ ÍÏÖŠͦÓÔÉÔÉÓÑ Escape"
+
+#: digraph.c:2340
+msgid "Keymap file not found"
+msgstr "æÁÊÌ ÒÏÚËÌÁÄËÉ ËÌÁצÁÔÕÒÉ ÎÅ ÚÎÁÊÄÅÎÏ"
+
+#: digraph.c:2367
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: ÷ÉËÏÒÉÓÔÁÎÎÑ :loadkeymap ÎÅ × ÆÁÊ̦ ËÏÍÁÎÄ"
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " äÏÐÏ×ÎÅÎÎÑ ËÌÀÞÏ×ÉÈ ÓÌ¦× (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " òÅÖÉÍ ^X (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " äÏ×ÅÒÛÅÎÎÑ Í¦ÓÃÅ×ÉÈ ËÌÀÞÏ×ÉÈ ÓÌ¦× (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " äÏ×ÅÒÛÅÎÎÑ ÕÓØÏÇÏ ÒÑÄËÁ (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " äÏ×ÅÒÛÅÎÎÑ ¦ÍÅΦ ÆÁÊÌÁ (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " äÏ×ÅÒÛÅÎÎÑ ÐÏͦÔÏË (^]/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " äÏ×ÅÒÛÅÎÎÑ ÛÌÑÈÕ ÚÁ ÚÒÁÚËÏÍ (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " äÏ×ÅÒÛÅÎÎÑ ×ÉÚÎÁÞÅÎÎÑ (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " äÏ×ÅÒÛÅÎÎÑ Ú ÓÌÏ×ÎÉËÁ (^K/^N/^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " äÏ×ÅÒÛÅÎÎÑ Ú ¦ÄÅÏÇÒÁÍÁÔÉÞÎÏÇÏ ÓÌÏ×ÎÉËÁ (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " äÏ×ÅÒÛÅÎÎÑ ËÏÍÁÎÄ (^V/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "äÏÓÑÇÎÕÔÏ Ë¦ÎÅÃØ ÐÁÒÁÇÒÁÆÁ"
+
+#: edit.c:899
+msgid "'thesaurus' option is empty"
+msgstr "ÏÐÃ¦Ñ 'thesaurus' ÐÕÓÔÁ"
+
+#: edit.c:1075
+msgid "'dictionary' option is empty"
+msgstr "ÏÐÃ¦Ñ 'dictionary' ÐÕÓÔÁ"
+
+#: edit.c:1997
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "ÚÞÉÔÕÅÍÏ ÄÉÒÅËÔÏÒ¦À: %s"
+
+#: edit.c:2188
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (×ÓÔÁ×ËÁ) úÓÕ× (^E/^Y)"
+
+#: edit.c:2190
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (ÚÁͦÎÁ) úÓÕ× (^E/^Y)"
+
+#: edit.c:2501
+#, c-format
+msgid "Scanning: %s"
+msgstr "ðÏÛÕË Õ: %s"
+
+#: edit.c:2536
+msgid "Scanning tags."
+msgstr "ðÏÛÕË ÓÅÒÅÄ ÐÏͦÔÏË."
+
+#: edit.c:3194
+msgid " Adding"
+msgstr " äÏÄÁ¤ÍÏ"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3243
+msgid "-- Searching..."
+msgstr "-- ðÏÛÕË..."
+
+#: edit.c:3299
+msgid "Back at original"
+msgstr "îÁÚÁÄ ÄÏ ÐÏÞÁÔËÏ×ÏÇÏ ×ÁÒ¦ÁÎÔÕ"
+
+#: edit.c:3304
+msgid "Word from other line"
+msgstr "óÌÏ×Ï Ú ¦ÎÛÏÇÏ ÒÑÄËÁ"
+
+#: edit.c:3309
+msgid "The only match"
+msgstr "åÄÉÎÉÊ ×ÁÒ¦ÁÎÔ"
+
+#: edit.c:3368
+#, c-format
+msgid "match %d of %d"
+msgstr " ×ÁÒ¦ÁÎÔ %d Ú %d"
+
+#: edit.c:3371
+#, c-format
+msgid "match %d"
+msgstr "×ÁÒ¦ÁÎÔ %d"
+
+#: eval.c:696
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: îÅצÄÏÍÁ ÚͦÎÎÁ: \"%s\""
+
+#: eval.c:975
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: îÅÍÁÅ ÄÕÖÏË: %s"
+
+#: eval.c:1043
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: úͦÎÎÁ ÎÅ ¦ÓÎÕ¤: \"%s\""
+
+#: eval.c:1284
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: îÅÍÁÅ ':' ЦÓÌÑ '?'"
+
+#: eval.c:1898
+msgid "E110: Missing ')'"
+msgstr "E110: îÅÍÁ¤ ')'"
+
+#: eval.c:1948
+msgid "E111: Missing ']'"
+msgstr "E111: îÅÍÁ¤ ']'"
+
+#: eval.c:2023
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: îÅÍÁ¤ ÎÁÚ×É ÏÐæ§: %s"
+
+#: eval.c:2041
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: îÅצÄÏÍÁ ÏÐæÑ: %s"
+
+#: eval.c:2103
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: îÅ ×ÉÓÔÁÞÁ¤ ÌÁÐËÉ: %s"
+
+#: eval.c:2220
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: ÷ÔÒÁÞÅÎÉÊ ÓÉÍ×ÏÌ '\"': %s"
+
+#: eval.c:2537
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: îÅצÒΦ ÁÒÇÕÍÅÎÔÉ ÄÌÑ ÆÕÎËæ§ %s"
+
+#: eval.c:2538
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: îÅצÄÏÍÁ ÆÕÎËæÑ: %s"
+
+#: eval.c:2539
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: úÁÂÁÇÁÔÏ ÁÒÇÕÍÅÎÔ¦× ÄÌÑ ÆÕÎËæ§ %s"
+
+#: eval.c:2540
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: úÁÍÁÌÏ ÁÒÇÕÍÅÎÔ¦× ÄÌÑ ÆÕÎËæ§ %s"
+
+#: eval.c:2541
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: <SID> ×ÉËÏÒÉÓÔÏ×Õ¤ÔØÓÑ ÎÅ Õ ÆÁÊ̦ ËÏÍÁÎÄ: %s"
+
+#: eval.c:3575
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld: "
+
+#: eval.c:4690
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"&O:çÁÒÁÚÄ\n"
+"&C:÷¦ÄͦÎÁ"
+
+#: eval.c:5514
+msgid "E240: No connection to Vim server"
+msgstr "E240: îÅÍÁ¤ Ú'¤ÄÎÁÎÎÑ Ú Vim-ÓÅÒ×ÅÒÏÍ"
+
+#: eval.c:5604
+msgid "E277: Unable to read a server reply"
+msgstr "E277: îÅ ÍÏÖÕ ÚÞÉÔÁÔÉ ×¦ÄÐÏצÄØ ÓÅÒ×ÅÒÁ"
+
+#: eval.c:5629
+msgid "E258: Unable to send to client"
+msgstr "E258: îÅ ÍÏÖÕ ÓЦÌËÕ×ÁÔÉÓÑ Ë̦¤ÎÔÏÍ"
+
+#: eval.c:5670
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: îÅ ÍÏÖÕ ÓЦÌËÕ×ÁÔÉÓÑ Ú %s"
+
+#: eval.c:5768
+msgid "(Invalid)"
+msgstr "(îÅÍÏÖÌÉ×Ï)"
+
+#: eval.c:6771
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: îÅ×ÉÚÎÁÞÅÎÁ ÚͦÎÎÁ: %s"
+
+#: eval.c:7469
+#, c-format
+msgid "E122: Function %s already exists, use ! to replace"
+msgstr "E122: æÕÎËÃ¦Ñ %s ÕÖÅ ¦ÓÎÕ¤ (×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÚÁͦÎÉÔÉ)"
+
+#: eval.c:7511
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: îÅ×ÉÚÎÁÞÅÎÁ ÆÕÎËæÑ: %s"
+
+#: eval.c:7524
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: âÒÁËÕ¤ '(': %s"
+
+#: eval.c:7556
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: îÅÄÏÚ×ÏÌÅÎÉÊ ÁÒÇÕÍÅÎÔ: %s"
+
+#: eval.c:7642
+msgid "E126: Missing :endfunction"
+msgstr "E126: âÒÁËÕ¤ :endfunction"
+
+#: eval.c:7721
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: îÅ ÍÏÖÕ ÚÁͦÎÉÔÉ ÆÕÎËæÀ %s: ÷ÏÎÁ ×ÉËÏÒÉÓÔÏ×Õ¤ÔØÓÑ"
+
+#: eval.c:7778
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: îÁÚ×Á ÆÕÎËæ§ ÍÁ¤ ÐÏÞÉÎÁÔÉÑ Ú ×ÅÌÉËϧ ̦ÔÅÒÉ: %s"
+
+#: eval.c:7784
+msgid "E129: Function name required"
+msgstr "E129: îÅ ×ËÁÚÁÎÁ ÎÁÚ×Á ÆÕÎËæ§"
+
+#: eval.c:7877
+msgid "function "
+msgstr "ÆÕÎËÃ¦Ñ "
+
+#: eval.c:7992
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: îÅ×ÉÚÎÁÞÅÎÁ ÆÕÎËæÑ: %s"
+
+#: eval.c:7997
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÆÕÎËæÀ %s: ÷ÏÎÁ ×ÉËÏÒÉÓÔÏ×Õ¤ÔØÓÑ"
+
+#: eval.c:8044
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: çÌÉÂÉÎÁ ×ÉËÌÉË¦× ÆÕÎËæ§ ÐÅÒÅ×ÉÝÕ¤ 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:8095
+#, c-format
+msgid "calling %s"
+msgstr "×ÉËÌÉËÁ¤ÔØÓÑ %s"
+
+#. always scroll up, don't overwrite
+#: eval.c:8120 ex_cmds2.c:1988
+#, c-format
+msgid "continuing in %s"
+msgstr "ÐÒÏÄÏ×ÖÅÎÎÑ × %s"
+
+#: eval.c:8174
+msgid "E133: :return not inside a function"
+msgstr "E133: :return ÐÏÚÁ ÍÅÖÁÍÉ ÆÕÎËæ§"
+
+#: eval.c:8252
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s ÐÏ×ÅÒÔÁ¤ #%ld"
+
+#: eval.c:8255
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s ÐÏ×ÅÒÔÁ¤ \"%s\""
+
+#: eval.c:8396
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# ÚÁÇÁÌØΦ ÚͦÎΦ:\n"
+
+#: ex_cmds2.c:70
+msgid "Entering Debug mode. Type \"cont\" to leave."
+msgstr "ðÏÞÁÔÏË ÒÅÖÉÍÕ ÎÁÌÁÇÏÄÖÕ×ÁÎÎÑ. ÷ÉËÏÒÉÓÔÏ×ÕÊÔÅ \"cont\" ÄÌÑ ×ÉÈÏÄÕ."
+
+#: ex_cmds2.c:74 ex_docmd.c:770
+#, c-format
+msgid "line %ld: %s"
+msgstr "ÒÑÄÏË %ld: %s"
+
+#: ex_cmds2.c:76
+#, c-format
+msgid "cmd: %s"
+msgstr "ËÏÍÁÎÄÁ: %s"
+
+#: ex_cmds2.c:224
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "úÕÐÉÎËÁ × \"%s%s\" ÒÑÄÏË %ld"
+
+#: ex_cmds2.c:388
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: ôÏÞËÕ ÚÕÐÉÎËÉ ÎÅ ÚÎÁÊÄÅÎÏ: %s"
+
+#: ex_cmds2.c:414
+msgid "No breakpoints defined"
+msgstr "öÏÄÎϧ ÔÏÞËÉ ÚÕÐÉÎËÉ ÎÅ ÂÕÌÏ ×ÉÚÎÁÞÅÎÏ"
+
+#: ex_cmds2.c:419
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s ÒÑÄÏË %ld"
+
+#: ex_cmds.c:2053 ex_cmds.c:2310 ex_cmds2.c:602
+msgid "Save As"
+msgstr "úÁÐÁÍ'ÑÔÁÔÉ ÑË"
+
+#: ex_cmds2.c:625
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "úÁÐÁÍ'ÑÔÁÔÉ ÚͦÎÉ × \"%.*s\"?"
+
+#: ex_cmds2.c:627 ex_docmd.c:8646
+msgid "Untitled"
+msgstr "îÅÎÁÚ×ÁÎÉÊ"
+
+#: ex_cmds2.c:763
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: öÏÄÎÏÇÏ ÚÁÐÉÓÕ Ð¦ÓÌÑ ÏÓÔÁÎÎØϧ ÚͦÎÉ ÄÌÑ ÂÕÆÅÒÁ \"%s\""
+
+#: ex_cmds2.c:832
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr ""
+"ïÂÅÒÅÖÎÏ: îÅÓÐÏĦ×ÁÎÏ ÐÏÔÒÁÐÔÌÅÎÏ × ¦ÎÛÉÊ ÂÕÆÅÒ (ÐÅÒÅצÒÔÅ Á×ÔÏËÏÍÁÎÄÉ)"
+
+#: ex_cmds2.c:1208
+msgid "E163: There is only one file to edit"
+msgstr "E163: ìÉÛÅ ÏÄÉÎ ÆÁÊÌ ÒÅÄÁÇÕ¤ÔØÓÑ"
+
+#: ex_cmds2.c:1210
+msgid "E164: Cannot go before first file"
+msgstr "E164: îÅ ÍÏÖÕ ÐÅÒÅÊÔÉ Õ ÐÏÐÅÒÅÄÎ¦Ê ÆÁÊÌ Ú ÐÅÒÛÏÇÏ"
+
+#: ex_cmds2.c:1212
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: îÅ ÍÏÖÕ ÐÅÒÅÊÔÉ Õ ÎÁÓÔÕÐÎÉÊ ÆÁÊÌ Ú ÏÓÔÁÎÎØÏÇÏ"
+
+# msgstr "E195: "
+#: ex_cmds2.c:1634
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "ðÏÛÕË \"%s\" × \"%s\""
+
+#: ex_cmds2.c:1656
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "ðÏÛÕË \"%s\""
+
+#: ex_cmds2.c:1680
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "\"%s\" ÎÅ ÚÎÁÊÄÅÎÏ × 'runtimepath'"
+
+#: ex_cmds2.c:1714
+msgid "Run Macro"
+msgstr "÷ÉËÏÎÁÔÉ ÆÁÊÌ ËÏÍÁÎÄ"
+
+#: ex_cmds2.c:1832
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "îÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ ÄÉÒÅËÔÏÒ¦À: \"%s\""
+
+#: ex_cmds2.c:1862
+#, c-format
+msgid "could not source \"%s\""
+msgstr "ÎÅÍÏÖÌÉ×Ï ×ÉËÏÎÁÔÉ \"%s\""
+
+#: ex_cmds2.c:1864
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "ÒÑÄÏË %ld: ÎÅÍÏÖÌÉ×Ï ×ÉËÏÎÁÔÉ \"%s\""
+
+#: ex_cmds2.c:1878
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "×ÉËÏÎÕÅÔØÓÑ \"%s\""
+
+#: ex_cmds2.c:1880
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "ÒÑÄÏË %ld: ×ÉËÏÎÕ¤ÔØÓÑ \"%s\""
+
+#: ex_cmds2.c:1986
+#, c-format
+msgid "finished sourcing %s"
+msgstr "×ÉËÏÎÁÎÎÑ %s ÚÁ˦ÎÞÅÎÏ"
+
+#: ex_cmds2.c:2287
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: îÅצÒÎÉÊ ÒÏÚĦÌØÎÉË ÒÑÄ˦×, ÍÏÖÌÉ×Ï ÂÒÁËÕ¤ ^M"
+
+#: ex_cmds2.c:2336
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: :scriptencoding ×ÉËÏÒÉÓÔÁÎÏ ÐÏÚÁ ×ÉËÏÎÕ×ÁÎÉÍ ÆÁÊÌÏÍ"
+
+#: ex_cmds2.c:2369
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: :finish ×ÉËÏÒÉÓÔÁÎÏ ÐÏÚÁ ×ÉËÏÎÕ×ÁÎÉÍ ÆÁÊÌÏÍ"
+
+#: ex_cmds2.c:2835
+msgid "No text to be printed"
+msgstr "î¦ÞÏÇÏ ÄÒÕËÕ×ÁÔÉ"
+
+#: ex_cmds2.c:2913
+msgid "Printing page %d (%d%%)"
+msgstr "äÒÕËÕ¤ÔØÓÑ ÓÔÏÒ¦ÎËÁ %d (%d)"
+
+#: ex_cmds2.c:2922
+#, c-format
+msgid " Copy %d of %d"
+msgstr " ëÏÐ¦Ñ %d, ÕÓØÏÇÏ %d"
+
+#: ex_cmds2.c:2974
+#, c-format
+msgid "Printed: %s"
+msgstr "îÁÄÒÕËÏ×ÁÎÏ: %s"
+
+#: ex_cmds2.c:2981
+msgid "Printing aborted"
+msgstr "äÒÕË ÐÅÒÅÒ×ÁÎÏ"
+
+#: ex_cmds2.c:3359
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: îÅ ÍÏÖÕ ÐÉÓÁÔÉ × ×ÉȦÄÎÉÊ ÆÁÊÌ PostScrip"
+
+#: ex_cmds2.c:4034
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÑË ×ȦÄÎÉÊ ÆÁÊÌ PostScrip"
+
+#: ex_cmds2.c:4072
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÆÁÊÌ \"%s\""
+
+#: ex_cmds2.c:4083
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: îÅ ÍÏÖÕ ÚÞÉÔÁÔÉ ÆÁÊÌ ÒÅÓÕÒÓ¦× PostScrip \"%s\""
+
+#: ex_cmds2.c:4281
+msgid "Sending to printer..."
+msgstr "÷¦ÄÓÉÌÁ¤ÍÏ ÎÁ ÄÒÕ˦×ÎÉË..."
+
+#: ex_cmds2.c:4285
+msgid "E365: Failed to print PostScript file"
+msgstr "E324: îÅ ÍÏÖÕ ÎÁÄÒÕËÕ×ÁÔÉ ÆÁÊÌ PostScrip"
+
+#: ex_cmds2.c:4287
+msgid "Print job sent."
+msgstr "úÁ×ÄÁÎÎÑ ÄÒÕËÕ ×¦Ä¦ÓÌÁÎÏ."
+
+#: ex_cmds2.c:4683
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "íÏ×Á (%s): \"%s\""
+
+#: ex_cmds2.c:4694
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: îÅ ÍÏÖÕ ×ÓÔÁÎÏ×ÉÔÉ ÍÏ×Õ \"%s\""
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Û¦Ó %02x, ×¦Ó %03o"
+
+#: ex_cmds.c:428
+msgid "E134: Move lines into themselves"
+msgstr "E134: îÅÍÏÖÌÉ×Ï ÚͦÓÔÉÔÉ ÒÑÄËÉ ÓÁͦ Õ ÓÅÂÅ"
+
+#: ex_cmds.c:497
+msgid "1 line moved"
+msgstr "1 ÒÑÄÏË ÚͦÝÅÎÏ"
+
+#: ex_cmds.c:499
+#, c-format
+msgid "%ld lines moved"
+msgstr "%ld ÒÑÄË¦× ÚͦÝÅÎÏ"
+
+#: ex_cmds.c:890
+#, c-format
+msgid "%ld lines filtered"
+msgstr "%ld ÒÑÄË¦× ×¦ÄƦÌØÔÒÏ×ÁÎÏ"
+
+#: ex_cmds.c:918
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: á×ÔÏËÏÍÁÎÄÉ *Filter* ÎÅ ÐÏ×ÉÎÎØ ÚͦÎÀ×ÁÔÉ ÂÕÆÅÒ"
+
+#: ex_cmds.c:1003
+msgid "[No write since last change]\n"
+msgstr "[îÅ ÚÁÐÉÓÁÎÏ Ð¦ÓÌÑ ÏÓÔÁÎÎØϧ ÚͦÎÉ]\n"
+
+#: ex_cmds.c:1248
+#, c-format
+msgid "viminfo: %s in line: "
+msgstr "viminfo: %s × ÒÑÄËÕ"
+
+#: ex_cmds.c:1253
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: ÚÁÂÁÇÁÔÏ ÐÏÍÉÌÏË, ÒÅÛÔÁ ÆÁÊÌÁ ÏÐÕÝÅÎÏ"
+
+#: ex_cmds.c:1282
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "úÞÉÔÕ¤ÔØÓÑ ÆÁÊÌ viminfo: \"%s\"%s%s%s"
+
+#: ex_cmds.c:1283
+msgid " info"
+msgstr " ¦ÎÆÏÒÍÁæÑ"
+
+#: ex_cmds.c:1284
+msgid " marks"
+msgstr " ÐÏÚÎÁÞËÉ"
+
+#: ex_cmds.c:1285
+msgid " FAILED"
+msgstr " îå ÷äáìïóñ"
+
+#: ex_cmds.c:1376
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: õ ÆÁÊÌ viminfo (\"%s\") ÚÁÐÉÓ ÎÅ ÄÏÚ×ÏÌÅÎÏ"
+
+#: ex_cmds.c:1501
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ viminfo ÆÁÊÌ %s!"
+
+#: ex_cmds.c:1509
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "úÁÐÉÓÕ¤ÔØÓÑ viminfo ÆÁÊÌ \"%s\""
+
+#. Write the info:
+#: ex_cmds.c:1610
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# ãÅÊ ÆÁÊÌ Á×ÔÏÍÁÔÉÞÎÏ ÓÔ×ÏÒÉ× Vim %s.\n"
+
+#: ex_cmds.c:1612
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr "# íÏÖÅÔÅ ÒÅÄÁÇÕ×ÁÔÉ, ÁÌÅ ïâåòåöîï!\n"
+
+#: ex_cmds.c:1614
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# úÎÁÞÅÎÎÑ 'encoding' ËÏÌÉ ÃÅÊ ÆÁÊÌ ÂÕÌÏ ÚÁÐÉÓÁÎÏ\n"
+
+#: ex_cmds.c:1713
+msgid "Illegal starting char"
+msgstr "îÅÄÏÚ×ÏÌÅÎÉÊ ÓÉÍ×ÏÌ ÎÁ ÐÏÞÁÔËÕ ÒÑÄËÁ"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2096
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: æÁÊÌ ÕÖÅ ÚÁ×ÁÎÔÁÖÅÎÏ Õ ¦ÎÛÏÍÕ ÂÕÆÅÒ¦"
+
+#: ex_cmds.c:2130
+msgid "Write partial file?"
+msgstr "úÁÐÉÓÁÔÉ ÞÁÓÔÉÎÕ ÆÁÊÌÁ?"
+
+#: ex_cmds.c:2137
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: ÷ÉËÏÒÉÓÔÏ×ÕÊÔÅ ! ÄÌÑ ÚÁÐÉÓÕ ÞÁÓÔÉÎÉ ÂÕÆÅÒÁ"
+
+#: ex_cmds.c:2244
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "ðÅÒÅÚÁÐÉÓÁÔÉ ¦ÓÎÕÀÞÉÊ ÆÁÊÌ \"%*.s\"?"
+
+#: ex_cmds.c:2315
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: îÅÍÁ¤ ×ȦÄÎÏÇÏ ÆÁÊÌÁ ÄÌÑ ÂÕÆÅÒÁ %ld"
+
+#: ex_cmds.c:2353
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: æÁÊÌ ÎÅ ÚÁÐÉÓÁÎÏ: ÚÁÐÉÓ ÚÁÂÏÒÏÎÅÎÏ ÏÐæ¤À 'write'"
+
+#: ex_cmds.c:2373
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"äÌÑ \"%.*s\" ×ËÁÚÁÎÏ ÏÐæÀ 'readonly'.\n"
+"÷É ×ÓÅ ÝÅ ÂÁÖÁ¤ÔÅ ÐÒÏÄÏ×ÖÉÔÉ ÚÁÐÉÓ?"
+
+#: ex_cmds.c:2538
+msgid "Edit File"
+msgstr "òÅÄÁÇÕ×ÁÔÉ æÁÊÌ"
+
+#: ex_cmds.c:3061
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: á×ÔÏËÏÍÁÎÄÁ ÎÅÓÐÏĦ×ÁÎÏ ×ÉÄÁÌÉÌÁ ÎÏ×ÉÊ ÂÕÆÅÒ %s"
+
+#: ex_cmds.c:3193
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: ÎÅÞÉÓÌÏ×ÉÊ ÁÒÇÕÍÅÎÔ ÄÌÑ :z"
+
+#: ex_cmds.c:3278
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: õ rvim ÎÅ ÄÏÚ×ÏÌÅΦ ËÏÍÁÎÄÉ shell"
+
+#: ex_cmds.c:3385
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: ÚÒÁÚËÉ ÎÅ ÍÏÖÕÔØ ÂÕÔÉ ÒÏÚĦÌÅΦ ̦ÔÅÒÁÍÉ"
+
+#: ex_cmds.c:3723
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "úÁͦÎÉÔÉ ÎÁ %s (y/n/a/q/l/^E/^Y)?"
+
+#: ex_cmds.c:4087
+msgid "(Interrupted) "
+msgstr "(ðÅÒÅÒ×ÁÎÏ) "
+
+#: ex_cmds.c:4091
+msgid "1 substitution"
+msgstr "ïÄÎÁ ÚÁͦÎÁ"
+
+#: ex_cmds.c:4093
+#, c-format
+msgid "%ld substitutions"
+msgstr "úÁͦÎÅÎÏ -- %ld"
+
+#: ex_cmds.c:4096
+msgid " on 1 line"
+msgstr " × ÏÄÎÏÍÕ ÒÑÄËÕ"
+
+#: ex_cmds.c:4098
+#, c-format
+msgid " on %ld lines"
+msgstr " × %ld ÒÑÄËÁÈ"
+
+#: ex_cmds.c:4149
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :global ÎÅ ÍÏÖÅ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉÓØ ÒÅËÕÒÓÉ×ÎÏ"
+
+#: ex_cmds.c:4184
+msgid "E148: Regular expression missing from global"
+msgstr "E148: âÒÁËÕ¤ ÚÒÁÚËÁ ÄÌÑ global"
+
+#: ex_cmds.c:4233
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "úÒÁÚÏË ÎÅ ÚÎÁÊÄÅÎÏ: %s"
+
+#: ex_cmds.c:4314
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# ïÓÔÁÎÎ¦Ê ÚÒÁÚÏË ÄÌÑ ÚÁͦÎÉ:\n"
+"$"
+
+#: ex_cmds.c:4413
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: ÷ÉÂÁÞÔÅ, ÄÌÑ %s ÎÅÍÁ¤ ÄÏÐÏÍÏÇÉ"
+
+#: ex_cmds.c:4447
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "÷ÉÂÁÞÔÅ, ÆÁÊÌ ÄÏÐÏÍÏÇÉ \"%s\" ÎÅ ÚÎÁÊÄÅÎÏ"
+
+#: ex_cmds.c:4893
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s: îÅ ¤ ÄÉÒÅËÔÏÒ¦¤À"
+
+#: ex_cmds.c:4921
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ %s ÄÌÑ ÚÁÐÉÓÕ"
+
+#: ex_cmds.c:4935
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ %s ÄÌÑ ÞÉÔÁÎÎÑ"
+
+#: ex_cmds.c:5014
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: ðÏÄצÊÎÁ ÐÏÚÎÁÞËÁ \"%s\" × ÆÁÊ̦ %s"
+
+#: ex_cmds.c:5115
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: îÅצÄÏÍÁ ËÏÍÁÎÄÁ sign: %s"
+
+#: ex_cmds.c:5135
+msgid "E156: Missing sign name"
+msgstr "E156: âÒÁËÕ¤ ÎÁÚ×É ÎÁÐÉÓÕ"
+
+#: ex_cmds.c:5181
+msgid "E255: Too many signs defined"
+msgstr "E255: ÷ÉÚÎÁÞÅÎÏ ÚÁÂÁÇÁÔÏ ÎÁÐÉÓ¦×"
+
+#: ex_cmds.c:5223
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: îÅצÒÎÉÊ ÎÁÐÉÓ: %s"
+
+#: ex_cmds.c:5247 ex_cmds.c:5433
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: îÅצÄÏÍÉÊ ÎÁÐÉÓ: %s"
+
+#: ex_cmds.c:5293
+msgid "E159: Missing sign number"
+msgstr "E159: âÒÁËÕ¤ ÁÒÇÕÍÅÎÔÕ ÎÁÐÉÓÕ"
+
+#: ex_cmds.c:5373
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: îÅצÒÎÁ ÎÁÚ×Á ÂÕÆÅÒÁ: %s"
+
+#: ex_cmds.c:5412
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: îÅצÒÎÉÊ ID ÎÁÐÉÓÕ: %ld"
+
+#: ex_cmds.c:5583
+msgid "[Deleted]"
+msgstr "[÷ÉÄÁÌÅÎÏ]"
+
+#: ex_docmd.c:490
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr ""
+"ðÏÞÁÔÏË ÒÅÖÉÍÕ Ex. ÷ÉËÏÒÉÓÔÏ×ÕÊÔÅ \"visual\" ÄÌÑ ÐÏ×ÅÒÎÅÎÎÑ × ÎÏÒÍÁÌØÎÉÊ "
+"ÒÅÈÉÍ"
+
+#. must be at EOF
+#: ex_docmd.c:526
+msgid "At end-of-file"
+msgstr "â¦ÌÑ Ë¦ÎÃÑ ÆÁÊÌÁ"
+
+#: ex_docmd.c:601
+msgid "E169: Command too recursive"
+msgstr "E169: ëÏÍÁÎÄÁ ÚÁÎÁÄÔÏ ÒÅËÕÒÓÉ×ÎÁ"
+
+#: ex_docmd.c:910
+msgid "E170: Missing :endwhile"
+msgstr "E170: âÒÁËÕ¤ :endwhile"
+
+#: ex_docmd.c:912
+msgid "E171: Missing :endif"
+msgstr "E171: âÒÁËÕ¤ :endif"
+
+#: ex_docmd.c:922
+msgid "End of sourced file"
+msgstr "ë¦ÎÅÃØ ×ÉËÏÎÕ×ÁÎÏÇÏ ÆÁÊÌÁ"
+
+#: ex_docmd.c:923
+msgid "End of function"
+msgstr "ë¦ÎÅÃØ ÆÕÎËæ§"
+
+#: ex_docmd.c:1343
+msgid "Ambiguous use of user-defined command"
+msgstr "ä×ÏÚÎÁÞÎÉÊ ×ÖÉÔÏË ËÏÍÁÎÄÉ ËÏÒÉÓÔÕ×ÁÞÁ"
+
+#: ex_docmd.c:1357
+msgid "Not an editor command"
+msgstr "îÅ ¤ ËÏÍÁÎÄÏÀ ÒÅÄÁËÔÏÒÁ"
+
+#: ex_docmd.c:1440
+msgid "Don't panic!"
+msgstr "îÅ ÎÅÒ×ÕÊÔÅ!"
+
+#: ex_docmd.c:1459
+msgid "Backwards range given"
+msgstr "îÅ ÂÕÄÕ ÚÁÄËÕ×ÁÔÉ!"
+
+#: ex_docmd.c:1468
+msgid "Backwards range given, OK to swap"
+msgstr "îÅ ÂÕÄÕ ÚÁÄËÕ×ÁÔÉ, ÁÌÅ ÍÏÖÕ ÏÂÅÒÎÕÔÉÓÑ..."
+
+#: ex_docmd.c:1579
+msgid "Use w or w>>"
+msgstr "÷ÉËÏÒÉÓÔÏ×ÕÊÔÅ :w ÁÂÏ :w>>"
+
+#: ex_docmd.c:3086
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: ÷ÉÂÁÊÔÅ, ÃÑ ËÏÍÁÎÄÁ ΊĦ¤"
+
+#: ex_docmd.c:3256
+msgid "E172: Only one file name allowed"
+msgstr "E172: ô¦ÌØËÉ ÏÄÎÅ ¦Í'Ñ ÆÁÊÌÁ ÄÏÚ×ÏÌÅÎÏ"
+
+#: ex_docmd.c:3811
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "ýÅ ¤ %d ÎÅÒÅÄÁÇÏ×ÁÎÉÈ ÆÁÊ̦×. ÷ÉÊÔÉ?"
+
+#: ex_docmd.c:3818
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: úÁÌÉÛÉÌÏÓÑ %ld ÎÅÒÅÄÁÇÏ×ÁÎÉÈ ÆÁÊ̦×"
+
+#: ex_docmd.c:3912
+msgid "E174: Command already exists: use ! to redefine"
+msgstr "E174: ëÏÍÁÎÄÁ ×ÖÅ ¦ÓÎÕ¤, ×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÎÅ Ú×ÁÖÁÔÉ"
+
+#: ex_docmd.c:4017
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" îÁÚ×Á áÒÇ. íÅÖÁ äÏÐÏ×ÎÅÎÑ ÷ÉÚÎÁÞÅÎÎÑ"
+
+#: ex_docmd.c:4106
+msgid "No user-defined commands found"
+msgstr "îÅ ÚÎÁÊÄÅÎÏ ËÏÍÁÎÄ ËÏÒÉÓÔÕ×ÁÞÁ"
+
+#: ex_docmd.c:4137
+msgid "E175: No attribute specified"
+msgstr "E175: îÅ ×ËÁÚÁÎÏ ÁÔÒÉÂÕÔ"
+
+#: ex_docmd.c:4189
+msgid "E176: Invalid number of arguments"
+msgstr "E176: îÅצÒÎÁ ˦ÌØ˦ÓÔØ ÁÒÇÕÍÅÎÔ¦×"
+
+#: ex_docmd.c:4204
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: ì¦ÞÉÌØÎÉË ÎÅ ÍÏÖÅ ÂÕÔÉ ×ËÁÚÁÎÏ Äצަ"
+
+# msgstr "E177: "
+#: ex_docmd.c:4214
+msgid "E178: Invalid default value for count"
+msgstr "E178: îÅצÒÎÅ ÐÏÞÁÔËÏ×Å ÚÎÁÞÅÎÎÑ ÄÌÑ count"
+
+# msgstr "E178: "
+#: ex_docmd.c:4242
+msgid "E179: argument required for complete"
+msgstr "E179: äÌÑ ÄÏÐÏ×ÎÅÎÎÑ ÎÅÏÂȦÄÅÎ ÁÒÇÕÍÅÎÔ"
+
+# msgstr "E179: "
+#: ex_docmd.c:4261
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: îÅצÒÎÁ ×ËÁÚ¦×ËÁ ÄÌÑ ÄÏÐÏ×ÎÅÎÎÑ: %s"
+
+# msgstr "E180: "
+#: ex_docmd.c:4269
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: îÅצÒÎÉÊ ÁÔÒÉÂÕÔ: %s"
+
+# msgstr "E181: "
+#: ex_docmd.c:4310
+msgid "E182: Invalid command name"
+msgstr "E182: îÅצÒÎÁ ÎÁÚ×Á ËÏÍÁÎÄÉ"
+
+# msgstr "E182: "
+#: ex_docmd.c:4325
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: ëÏÍÁÎÄÉ ËÏÒÉÓÔÕ×ÁÞÁ ÐÏצÎÎÉ ÐÏÞÉÎÁÔÉÓÑ Ú ×ÅÌÉËϧ ̦ÔÅÒÉ"
+
+# msgstr "E183: "
+#: ex_docmd.c:4394
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: ëÏÍÁÎÄÕ ËÏÒÉÓÔÕ×ÁÞÁ ÎÅ ÚÎÁÊÄÅÎÏ: %s"
+
+# msgstr "E184: "
+#: ex_docmd.c:4845
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: îÅ ÍÏÖÎÁ ÚÎÁÊÔÉ ÓÈÅÍÕ ËÏÌØÏÒ¦× %s"
+
+#: ex_docmd.c:4853
+msgid "Greetings, Vim user!"
+msgstr "ñË ÖÉ×ÅÔØÓÑ, ËÏÒÉÓÔÕ×ÁÞ Vim ?"
+
+# msgstr "E185: "
+#: ex_docmd.c:5550
+msgid "Edit File in new window"
+msgstr "òÅÄÁÇÕ×ÁÔÉ ÆÁÊÌ Õ ÎÏ×ÏÍÕ ×¦ËΦ"
+
+#: ex_docmd.c:5816
+msgid "No swap file"
+msgstr "îÅÍÁ¤ ÆÁÊÌÁ ÏÂͦÎÕ"
+
+#: ex_docmd.c:5920
+msgid "Append File"
+msgstr "äÏÐÉÓÁÔÉ ÆÁÊÌ"
+
+#: ex_docmd.c:5979
+msgid "E186: No previous directory"
+msgstr "E186: öÏÄÎϧ ÐÏÐÅÒÅÄÎØϧ ÄÉÒÅËÔÏÒ¦§"
+
+# msgstr "E186: "
+#: ex_docmd.c:6056
+msgid "E187: Unknown"
+msgstr "E187: îÅצÄÏÍÁ ÄÉÒÅËÔÏÒ¦Ñ"
+
+# msgstr "E187: "
+#: ex_docmd.c:6174
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "ðÏÚÉÃ¦Ñ ×¦ËÎÁ: X %d, Y %d"
+
+#: ex_docmd.c:6179
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: æÕÎËÃ¦Ñ ÏÂÒÁÈÕ×ÁÎÎÑ ÐÏÚÉæ§ צËÎÁ ΊĦ¤ ÄÌÑ ×ÁÛϧ ÐÌÁÔÆÏÒÍÉ"
+
+# msgstr "E188: "
+#: ex_docmd.c:6445
+msgid "Save Redirection"
+msgstr "úÁÐÁÍ'ÑÔÁÔÉ ÐÅÒÅÁÄÒÅÓÏ×ÁÎÉÊ ×ÉצÄ"
+
+#: ex_docmd.c:6594
+msgid "Save View"
+msgstr "úÁÐÁÍ'ÑÔÁÔÉ ×ÉÇÌÑÄ"
+
+#: ex_docmd.c:6595
+msgid "Save Session"
+msgstr "úÁÐÁÍ'ÑÔÁÔÉ ÓÅÁÎÓ"
+
+#: ex_docmd.c:6597
+msgid "Save Setup"
+msgstr "úÁÐÁÍ'ÑÔÁÔÉ ÎÁÌÁÛÔÕ×ÁÎÎÑ"
+
+#: ex_docmd.c:6746
+#, c-format
+msgid "E189: \"%s\" exists (use ! to override)"
+msgstr "E189: æÁÊÌ \"%s\" ¦ÓÎÕ¤, (×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÎÅ Ú×ÁÖÁÔÉ)"
+
+# msgstr "E189: "
+#: ex_docmd.c:6751
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ \"%s\" ÄÌÑ ÞÉÔÁÎÎÑ"
+
+# msgstr "E190: "
+#. set mark
+#: ex_docmd.c:6775
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: áÒÇÕÍÅÎÔ ÍÁ¤ ÂÕÔÉ Ì¦ÔÅÒÏÀ, ` ÁÂÏ '"
+
+# msgstr "E191: "
+#: ex_docmd.c:6818
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: òÅËÕÒÓÉ×ÎÁ ÇÌÉÂÉÎÁ ×ÅËÏÒÉÓÔÁÎÎÑ :normal ÚÁÎÁÄÒÏ ×ÅÌÉËÁ"
+
+#: ex_docmd.c:7179
+msgid ":if nesting too deep"
+msgstr "úÁÎÁÄÔÏ ×ÅÌÉËÁ ˦ÌØ˦ÓÔØ ×ËÌÁÄÅÎÉÈ :if"
+
+#: ex_docmd.c:7214
+msgid ":endif without :if"
+msgstr "âÒÁËÕ¤ צÄÐÏצÄÎÏÇÏ :if ÄÌÑ :endif"
+
+#: ex_docmd.c:7234
+msgid ":else without :if"
+msgstr "âÒÁËÕ¤ צÄÐÏצÄÎÏÇÏ :if ÄÌÑ :else"
+
+#: ex_docmd.c:7236
+msgid ":elseif without :if"
+msgstr "âÒÁËÕ¤ צÄÐÏצÄÎÏÇÏ :if ÄÌÑ :elseif"
+
+#: ex_docmd.c:7288
+msgid ":while nesting too deep"
+msgstr "úÁÎÁÄÔÏ ×ÅÌÉËÁ ˦ÌØ˦ÓÔØ ×ËÌÁÄÅÎÉÈ :while"
+
+#: ex_docmd.c:7334
+msgid ":continue without :while"
+msgstr "âÒÁËÕ¤ צÄÐÏצÄÎÏÇÏ :while ÄÌÑ :continue"
+
+#: ex_docmd.c:7361
+msgid ":break without :while"
+msgstr "âÒÁËÕ¤ צÄÐÏצÄÎÏÇÏ :while ÄÌÑ :break"
+
+#: ex_docmd.c:7384 ex_docmd.c:7389
+msgid ":endwhile without :while"
+msgstr "âÒÁËÕ¤ צÄÐÏצÄÎÏÇÏ :while ÄÌÑ :endwhile"
+
+#: ex_docmd.c:7410
+msgid "E193: :endfunction not inside a function"
+msgstr "E133: :endfunction ÐÏÚÁ ÍÅÖÁÍÉ ÆÕÎËæ§"
+
+# msgstr "E193: "
+#: ex_docmd.c:7590
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: îÅÍÁ¤ ×ÔÏÒÉÎÎÏÇÏ ÆÁÊÌÁ ÄÌÑ ÚÁͦÎÉ '#'"
+
+#: ex_docmd.c:7621
+msgid "no autocommand file name to substitute for \"<afile>\""
+msgstr "îÅ ÍÏÖÎÁ ÚÁͦÎÉÔÉ \"<afile>\" × Á×ÔÏËÏÍÁÎĦ, ¦Í'Ñ ÆÁÊÌÁ צÄÓÕÔΦ¤"
+
+#: ex_docmd.c:7629
+msgid "no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "îÅ ÍÏÖÎÁ ÚÁͦÎÉÔÉ \"<abuf>\" × Á×ÔÏËÏÍÁÎĦ, ÎÁÚ×Á ÂÕÆÅÒÁ צÄÓÕÔÎÑ"
+
+#: ex_docmd.c:7640
+msgid "no autocommand match name to substitute for \"<amatch>\""
+msgstr ""
+"îÅ ÍÏÖÎÁ ÚÁͦÎÉÔÉ \"<amatch>\" × Á×ÔÏËÏÍÁÎĦ, ÄÌÑ Ú¦ÇÕ ÎÅ ×ÉËÏÒÉÓÔÏ×ÁÌÏÓØ "
+"¦Í'Ñ"
+
+#: ex_docmd.c:7650
+msgid "no :source file name to substitute for \"<sfile>\""
+msgstr "îÅ ÍÏÖÎÁ ÚÁͦÎÉÔÉ \"<sfile>\" × Á×ÔÏËÏÍÁÎĦ, ¦Í'Ñ ÆÁÊÌÁ צÄÓÕÔΦ¤"
+
+#: ex_docmd.c:7691
+#, no-c-format
+msgid "Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "ðÏÒÏÖÎÅ ¦Í'Ñ ÆÁÊÌÁ ÄÌÑ '%' ÔÁ '#' ÐÒÁÃÀ¤ ÌÉÛÅ Ú \":p:h\""
+
+#: ex_docmd.c:7693
+msgid "Evaluates to an empty string"
+msgstr "òÅÚÕÌØÔÁÔ -- ÐÏÒÏÖÎ¦Ê ÒÑÄÏË"
+
+#: ex_docmd.c:8628
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÆÁÊÌ viminfo"
+
+#: ex_docmd.c:8801
+msgid "E196: No digraphs in this version"
+msgstr "E196: õ Ã¦Ê ×ÅÒÓ¦§ ÎÅÍÁ¤ ÄÉÇÒÁƦ×"
+
+# msgstr "E197: "
+#: ex_getln.c:2785
+msgid "tagname"
+msgstr "ÎÁÚ×Á ÐÏͦÔËÉ"
+
+#: ex_getln.c:2788
+msgid " kind file\n"
+msgstr " ÔÉÐ ÆÁÊÌÁ\n"
+
+#: ex_getln.c:3997
+msgid "'history' option is zero"
+msgstr "ïÐÃ¦Ñ 'history' ÐÏÒÏÖÎÑ"
+
+#: ex_getln.c:4237
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# ðÏÐÅÒÅÄΦ %s:\n"
+
+#: ex_getln.c:4238
+msgid "Command Line"
+msgstr "ËÏÍÁÎÄÉ"
+
+#: ex_getln.c:4239
+msgid "Search String"
+msgstr "ÚÒÁÚËÉ ÄÌÑ ÐÏÛÕËÕ"
+
+#: ex_getln.c:4240
+msgid "Expression"
+msgstr "×ÉÒÁÚÉ"
+
+#: ex_getln.c:4241
+msgid "Input Line"
+msgstr "××ÅÄÅΦ ÒÑÄËÉ"
+
+#: ex_getln.c:4271
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: "
+
+#: ex_getln.c:4435
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: áËÔÉ×ΊצËÎÏ ÁÂÏ ÂÕÆÅÒ ÂÕÌÏ ×ÉÄÁÌÅÎÏ"
+
+# msgstr "E199: "
+#: fileio.c:347
+msgid "Illegal file name"
+msgstr "îÅÄÏÚ×ÏÌÅÎÅ ¦Í'Ñ ÆÁÊÌÁ"
+
+#: fileio.c:371 fileio.c:495 fileio.c:2493 fileio.c:2531
+msgid "is a directory"
+msgstr "ÃÅ ÄÉÒÅËÔÏÒ¦Ñ"
+
+#: fileio.c:373
+msgid "is not a file"
+msgstr "ÎÅ ÆÁÊÌ"
+
+#: fileio.c:515 fileio.c:3604
+msgid "[New File]"
+msgstr "[îÏ×ÉÊ ÆÁÊÌ]"
+
+#: fileio.c:532
+msgid "[Permission Denied]"
+msgstr "[÷¦ÄÍÏ×ÌÅÎÏ]"
+
+#: fileio.c:624
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: á×ÔÏËÏÍÁÎÄÉ *ReadPre ÚÒÏÂÉÌÉ ÞÉÔÁÎÎÑ ÆÁÊÌÁ ÎÅÍÏÖÌÉ×ÉÍ"
+
+# msgstr "E200: "
+#: fileio.c:626
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: á×ÔÏËÏÍÁÎÄÉ *ReadPre ÎÅ ÍÁ¤ÔØ ÐÒÁ×Á ÚͦÎÀ×ÁÔÉ ÂÕÆÅÒ"
+
+# msgstr "E201: "
+#: fileio.c:646
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: þÉÔÁÅÍÏ Ú stdin...\n"
+
+#: fileio.c:652
+msgid "Reading from stdin..."
+msgstr "þÉÔÁÅÍÏ Ú stdin..."
+
+#. Re-opening the original file failed!
+#: fileio.c:876
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: ëÏÎ×ÅÒÔÕ×ÁÎÎÑ ÚÒÏÂÉÌÏ ÞÉÔÁÎÎÑ ÆÁÊÌÁ ÎÅÍÏÖÌÉ×ÉÍ!"
+
+# msgstr "E202: "
+#: fileio.c:1732
+msgid "[fifo/socket]"
+msgstr "[fifo/ÓÏËÅÔ]"
+
+#: fileio.c:1739
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:1746
+msgid "[socket]"
+msgstr "[ÓÏËÅÔ]"
+
+#: fileio.c:1754
+msgid "[RO]"
+msgstr "[RO]"
+
+#: fileio.c:1764
+msgid "[CR missing]"
+msgstr "[÷ÔÒÁÞÅÎÏ CR]"
+
+#: fileio.c:1769
+msgid "[NL found]"
+msgstr "[úÎÁÊÄÅÎÏ NL]"
+
+#: fileio.c:1774
+msgid "[long lines split]"
+msgstr "[äÏ×Ǧ ÒÑÄËÉ ÐÏÄÒ¦ÂÎÅÎÏ]"
+
+#: fileio.c:1780 fileio.c:3588
+msgid "[NOT converted]"
+msgstr "[îå ËÏÎ×ÅÒÔÏ×ÁÎÏ]"
+
+#: fileio.c:1785 fileio.c:3593
+msgid "[converted]"
+msgstr "[ËÏÎ×ÅÒÔÏ×ÁÎÏ]"
+
+#: fileio.c:1792 fileio.c:3618
+msgid "[crypted]"
+msgstr "[ÚÁÛÉÆÒÏ×ÁÎÏ]"
+
+#: fileio.c:1799
+msgid "[CONVERSION ERROR]"
+msgstr "[ðïíéìëá ëïî÷åòôõ÷áîîñ]"
+
+#: fileio.c:1806
+msgid "[READ ERRORS]"
+msgstr "[ðïíéìëá úþéôõ÷áîîñ]"
+
+#: fileio.c:2013
+msgid "Can't find temp file for conversion"
+msgstr "îÅ ÍÏÖÕ Ð¦ÄÛÕËÁÔÉ ÔÉÍÞÁÓÏ×ÉÊ ÆÁÊÌ ÄÌÑ ËÏÎ×ÅÒÔÕ×ÁÎÎÑ"
+
+#: fileio.c:2020
+msgid "Conversion with 'charconvert' failed"
+msgstr "ëÏ×ÎÅÒÔÕ×ÁÎÎÑ Ú 'charconvert' ÎÅ ×ÄÁÌÏÓÑ"
+
+#: fileio.c:2023
+msgid "can't read output of 'charconvert'"
+msgstr "ÎÅ ÍÏÖÕ ÚÞÉÔÁÔÉ ×É×¦Ä 'charconvert'"
+
+#: fileio.c:2409
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: á×ÔÏËÏÍÁÎÄÁ ×ÉÄÁÌÉÌÁ ÁÂÏ ×É×ÁÎÔÁÖÉÌÁ ÂÕÆÅÒ ÝÏ ÍÁ¤ ÂÕÔÉ ÚÁÐÉÓÁÎÉÊ"
+
+#: fileio.c:2432
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: á×ÔÏËÏÍÁÎÄÁ ÚͦÎÉÌÁ ˦ÌØËØÓÔØ ÒÑÄË¦× ÎÅÓÐÏĦ×ÁÎÉÍ ÞÉÎÏÍ"
+
+#: fileio.c:2498 fileio.c:2515
+msgid "is not a file or writable device"
+msgstr "ÎÅ ¤ ÆÁÊÌÏÍ ÞÉ ÐÒÉÓÔÒÏ¤Í Ú ÍÏÖÌÉצÓÔÀ ÚÁÐÉÓÕ"
+
+#: fileio.c:2561
+msgid "is read-only (use ! to override)"
+msgstr "ÍÏÖÎÁ ÌÉÛÅ ÞÉÔÁÔÉ (×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÎÅ Ú×ÁÖÁÔÉ)"
+
+#: fileio.c:2857
+msgid "Can't write to backup file (use ! to override)"
+msgstr "îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ ÒÅÚÅÒ×ÎÉÊ ÆÁÊÌ (×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÎÅ Ú×ÁÖÁÔÉ)"
+
+#: fileio.c:2869
+msgid "Close error for backup file (use ! to override)"
+msgstr "ðÏÍÉÌËÁ Ð¦Ä ÞÁÓ ÓÐÒÏÂÉ ÚÁËÒÉÔÉ ÒÅÚÅÒ×ÎÉÊ ÆÁÊÌ"
+
+#: fileio.c:2871
+msgid "Can't read file for backup (use ! to override)"
+msgstr ""
+"îÅÍÁ¤ ÚÍÏÇÉ ÓÔ×ÏÒÉÔÉ ÆÁÊÌ ÄÌÑ ÒÅÚÅÒ×Îϧ ËÏЦ§ (×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÎÅ Ú×ÁÖÁÔÉ)"
+
+#: fileio.c:2887
+msgid "Cannot create backup file (use ! to override)"
+msgstr "îÅÍÁ¤ ÚÍÏÇÉ ÓÔ×ÏÒÉÔÉ ÒÅÚÅÒ×ÎÕ ËÏЦÀ (×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÎÅ Ú×ÁÖÁÔÉ)"
+
+#: fileio.c:2989
+msgid "Can't make backup file (use ! to override)"
+msgstr "îÅÍÁ¤ ÚÍÏÇÉ ÓÔ×ÏÒÉÔÉ ÒÅÚÅÒ×ÎÕ ËÏЦÀ (×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÎÅ Ú×ÁÖÁÔÉ)"
+
+#: fileio.c:3051
+msgid "The resource fork will be lost (use ! to override)"
+msgstr "òÅÓÕÒÓÎÕ Ç¦ÌËÕ ÆÁÊÌÁ ÂÕÄÅ ×ÔÒÁÞÅÎÏ (! ÝÏ ÎÅ Ú×ÁÖÁÔÉ)"
+
+#: fileio.c:3140
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: îÅ ÍÏÖÕ Ð¦ÄÛÕËÁÔÉ ÔÉÍÞÁÓÏ×ÉÊ ÆÁÊÌ ÄÌÑ ÚÁÐÉÓÕ"
+
+#: fileio.c:3158
+msgid "E213: Cannot convert (use ! to write without conversion)"
+msgstr ""
+"E213: îÅ ÍÏÖÕ ËÏÎ×ÅÒÔÕ×ÁÔÉ (×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÚÁÐÉÓÁÔÉ ÂÅÚ ËÏÎ×ÅÒÔÕ×ÁÎÎÑ)"
+
+#: fileio.c:3193
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÄÌÑ ÚÁÐÉÓÕ ÆÁÊÌ ÎÁ ÑËÉÊ ×ËÁÚÕ¤ ÐÏÓÉÌÁÎÎÑ"
+
+#: fileio.c:3197
+msgid "E212: Can't open file for writing"
+msgstr "E212: îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÆÁÊÌ ÄÌÑ ÚÁÐÉÓÕ"
+
+#: fileio.c:3446
+msgid "Close failed"
+msgstr "îÅ ×ÄÁÌÏÓÑ ÚÁËÒÉÔÉ ÆÁÊÌ"
+
+#: fileio.c:3504
+msgid "write error, conversion failed"
+msgstr "ÐÏÍÉÌËÁ ÚÁÐÉÓÕ, ËÏÎ×ÅÒÔÕ×ÁÎÎÑ ÎÅ ×ÄÁÌÏÓÑ"
+
+#: fileio.c:3510
+msgid "write error (file system full?)"
+msgstr "ÐÏÍÉÌËÁ ÚÁÐÉÓÕ (Ó˦ÎÞÉÌÏÓØ ×¦ÌØΊͦÓÃÅ??)"
+
+#: fileio.c:3583
+msgid " CONVERSION ERROR"
+msgstr " ðïíéìëá ëïî÷åòôõ÷áîîñ"
+
+#: fileio.c:3599
+msgid "[Device]"
+msgstr "[ðÒÉÓÔÒ¦Ê]"
+
+#: fileio.c:3604
+msgid "[New]"
+msgstr "[îÏ×ÉÊ]"
+
+#: fileio.c:3626
+msgid " [a]"
+msgstr "[Ä]"
+
+#: fileio.c:3626
+msgid " appended"
+msgstr " ÄÏÐÉÓÁÎÉÊ"
+
+#: fileio.c:3628
+msgid " [w]"
+msgstr "[Ú]"
+
+#: fileio.c:3628
+msgid " written"
+msgstr " ÚÁÐÉÓÁÎÉÊ"
+
+#: fileio.c:3678
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: òÅÖÉÍ patch: ÎÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ ÐÅÒ×ÉÎÎÉÊ ÆÁÊÌ"
+
+#: fileio.c:3700
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: òÅÖÉÍ patch: ÎÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÐÕÓÔÉÊ ÐÅÒ×ÉÎÎÉÊ ÆÁÊÌ"
+
+#: fileio.c:3715
+msgid "E207: Can't delete backup file"
+msgstr "E207: îÅ ÍÏÖÕ ×ÉÄÁÌÉÌÁ ÒÅÚÅÒ×ÎÉÊ ÆÁÊÌ"
+
+#: fileio.c:3767
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"õ÷áçá: ðÏÞÁÔËÏ×ÉÊ ÆÁÊÌ ÍÏÖÅ ÂÕÔÉ ×ÔÒÁÞÅÎÉÊ ÁÂÏ ×ÉÄÁÌÅÎÉÊ\n"
+
+#: fileio.c:3769
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "îÅ ×ÉÈÏÄØÔÅ Ú ÒÅÄÁËÔÏÒÁ ÄÏÐÏËÉ ÆÁÊÌ ÎÅ ÂÕÄÅ ÚÁÐÉÓÁÎÏ"
+
+#: fileio.c:3849
+msgid "[dos]"
+msgstr "[ÄÏÓ]"
+
+#: fileio.c:3849
+msgid "[dos format]"
+msgstr "[ÆÏÒÍÁÔ dos]"
+
+#: fileio.c:3856
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:3856
+msgid "[mac format]"
+msgstr "[ÆÏÒÍÁÔ mac]"
+
+#: fileio.c:3863
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:3863
+msgid "[unix format]"
+msgstr "[unix ÆÏÒÍÁÔ]"
+
+#: fileio.c:3890
+msgid "1 line, "
+msgstr "ÏÄÉÎ ÒÑÄÏË, "
+
+#: fileio.c:3892
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld ÒÑÄ˦×, "
+
+#: fileio.c:3895
+msgid "1 character"
+msgstr "ÏÄÉÎ ÓÉÍ×ÏÌ"
+
+#: fileio.c:3897
+#, c-format
+msgid "%ld characters"
+msgstr "%ld ÓÉÍ×Ï̦×"
+
+#: fileio.c:3907
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:3907
+msgid "[Incomplete last line]"
+msgstr "[ÎÅÐÏ×ÎÉÊ ÏÓÔÁÎ¦Ê ÒÑÄÏË]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:3926
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "õ÷áçá: æÁÊÌ ÂÕÌÏ ÚͦÎÅÎÏ Ð¦ÓÌÑ ÚÞÉÔÁÎÎÑ!!!"
+
+#: fileio.c:3928
+msgid "Do you really want to write to it"
+msgstr "÷É Ä¦ÊÓÎÏ ÈÏÞÅÔÅ ÊÏÇÏ ÐÅÒÅÚÁÐÉÓÁÔÉ ??"
+
+#: fileio.c:4884
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: ðÏÍÉÌËÁ ÚÁÐÉÓÕ × \"%s\""
+
+#: fileio.c:4891
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: ðÏÍÉÌËÁ Ð¦Ä ÞÁÓ ÚÁËÒÉÔÔÑ \"%s\""
+
+#: fileio.c:4894
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: ðÏÍÉÌËÁ Ð¦Ä ÞÁÓ ÚÞÉÔÕ×ÁÎÎÑ \"%s\""
+
+#: fileio.c:5058
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: á×ÔÏËÏÍÁÎÄÁ FileChangedShell ×ÉÄÁÌÉÌÁ ÂÕÆÅÒ"
+
+#: fileio.c:5066
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: õ×ÁÇÁ: æÁÊÌ \"%s\" ÎÅÄÏÓÑÖÎÉÊ"
+
+#: fileio.c:5079
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr ""
+"W12: õ×ÁÇÁ: æÁÊÌ \"%s\" ÂÕÌÏ ÚͦÎÅÎÏ, ÁÌÅ Ê ÂÕÆÅÒ Õ Vim ÔÅÖ ÂÕÌÏ ÚͦÎÅÎÏ"
+
+#: fileio.c:5082
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: õ×ÁÇÁ: æÁÊÌ \"%s\" ÂÕÌÏ ÚͦÎÅÎÏ Ð¦ÓÌÑ ÐÏÞÁÔËÕ ÒÅÄÁÇÕ×ÁÎÎÑ"
+
+#: fileio.c:5084
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: õ×ÁÇÁ: òÅÖÉÍ ÆÁÊÌÁ \"%s\" ÂÕÌÏ ÚͦÎÅÎÏ Ð¦ÓÌÑ ÐÏÞÁÔËÕ ÒÅÄÁÇÕ×ÁÎÎÑ"
+
+#: fileio.c:5094
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: õ×ÁÇÁ: æÁÊÌ \"%s\" ÂÕÌÏ ÓÔ×ÏÒÅÎÏ Ð¦ÓÌÑ ÐÏÞÅÔËÕ ÒÅÄÁÇÕ×ÁÎÎÑ"
+
+#: fileio.c:5111
+msgid "Warning"
+msgstr "õ×ÁÇÁ"
+
+#: fileio.c:5112
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"&O:çÁÒÁÚÄ\n"
+"&L:úÁ×ÁÎÔÁÖÉÔÉ ÆÁÊÌ"
+
+#: fileio.c:5188
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: îÅ ÍÏÖÕ ÐÅÒÅ×ÁÎÔÁÖÉÔÉ \"%s\""
+
+#: fileio.c:5703
+msgid "--Deleted--"
+msgstr "--÷ÉÄÁÌÅÎÏ--"
+
+#. the group doesn't exist
+#: fileio.c:5863
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: çÒÕÐÁ ÎÅ ¦ÓÎÕ¤: \"%s\""
+
+#: fileio.c:5988
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: îÅÄÏÚ×ÏÌÅÎÉÊ ÓÉÍ×ÏÌ Ð¦ÓÌÑ *: %s"
+
+# msgstr "E215: "
+#: fileio.c:5999
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: ðÏÄ¦Ñ ÎÅ ¦ÓÎÕ¤: %s"
+
+# msgstr "E216: "
+#. Highlight title
+#: fileio.c:6148
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- á×ÔÏËÏÍÁÎÄÉ ---"
+
+#: fileio.c:6419
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: îÅ ÍÏÖÕ ×ÉËÏÎÕ×ÁÔÉ Á×ÔÏËÏÍÁÎÄÉ ÄÌÑ õó¶è ÐÏĦÊ"
+
+# msgstr "E217: "
+#: fileio.c:6442
+msgid "No matching autocommands"
+msgstr "îÅ ¦ÓÎÕ¤ צÄÐÏצÄÎÉÈ Á×ÔÏËÏÍÁÎÄ"
+
+#: fileio.c:6714
+msgid "E218: autocommand nesting too deep"
+msgstr "úÁÎÁÄÔÏ ×ÅÌÉËÁ ˦ÌØ˦ÓÔØ ×ËÌÁÄÅÎÉÈ Á×ÔÏËÏÍÁÎÄ"
+
+# msgstr "E218: "
+#: fileio.c:7001
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s á×ÔÏËÏÍÁÎÄÉ ÄÌÑ \"%s\""
+
+#: fileio.c:7009
+#, c-format
+msgid "Executing %s"
+msgstr "÷ÉËÏÎÕÅÔØÓÑ %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7077
+#, c-format
+msgid "autocommand %s"
+msgstr "Á×ÔÏËÏÍÁÎÄÁ %s"
+
+#: fileio.c:7599
+msgid "E219: Missing {."
+msgstr "÷ÔÒÁÞÅÎÏ {."
+
+# msgstr "E219: "
+#: fileio.c:7601
+msgid "E220: Missing }."
+msgstr "÷ÔÒÁÞÅÎÏ }."
+
+# msgstr "E220: "
+#: fold.c:66
+msgid "No fold found"
+msgstr "úÇÏÒÔÏË ÎÅ ÚÎÁÊÄÅÎÏ"
+
+# msgstr "E349: "
+#: fold.c:554
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÚÇÏÒÔÏË (Ú×ÁÖÁÀÞÉ ÎÁ 'foldmethod')"
+
+#: fold.c:556
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÚÇÏÒÔÏË (Ú×ÁÖÁÀÞÉ ÎÁ 'foldmethod')"
+
+#: fold.c:1701
+msgid "E221: 'commentstring' is empty"
+msgstr "E221: ÏÐÃ¦Ñ 'commentstring' ÐÏÒÏÖÎÑ"
+
+#: getchar.c:247
+msgid "E222: Add to read buffer"
+msgstr "E222: âÕÆÅÒ ÕÖÅ ÂÕÌÏ ÚÞÉÔÁÎÏ [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#: getchar.c:2106
+msgid "E223: recursive mapping"
+msgstr "E332: úÁͦÎÁ ÚÁÃÉËÌÅÎÁ"
+
+# msgstr "E223: "
+#: getchar.c:2958
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "úÁÇÁÌØÎÅ ÓËÏÒÏÞÅÎÎÑ ÄÌÑ %s ×ÖÅ ¦ÓÎÕ¤"
+
+# msgstr "E224: "
+#: getchar.c:2961
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "úÁÇÁÌØÎÁ ÚÁͦÎÁ ÄÌÑ %s ×ÖÅ ¦ÓÎÕ¤"
+
+# msgstr "E225: "
+#: getchar.c:3088
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "óËÏÒÏÞÅÎÎÑ ÄÌÑ %s ×ÓÅ ¦ÓÎÕ¤"
+
+# msgstr "E226: "
+#: getchar.c:3091
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "úÁͦÎÁ ÄÌÑ %s ×ÖÅ ¦ÓÎÕ¤"
+
+# msgstr "E227: "
+#: getchar.c:3155
+msgid "No abbreviation found"
+msgstr "óËÏÒÏÞÅÎÎÑ ÎÅ ÚÎÁÊÄÅÎÏ"
+
+#: getchar.c:3157
+msgid "No mapping found"
+msgstr "úÁͦÎÉ ÎÅ ÚÎÁÊÄÅÎÏ"
+
+#: getchar.c:3982
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: ÷ÎÕÔÒ¦ÛÎÑ ÐÏÍÉÌËÁ"
+
+#: gui_at_fs.c:290
+msgid "<cannot open> "
+msgstr "<ÎÅÍÏÖÌÉ×Ï ×¦ÄËÒÉÔÉ> "
+
+#: gui_at_fs.c:1115
+#, c-format
+msgid "vim_SelFile: can't get font %s"
+msgstr "vim_SelFile: ÎÅ ÍÏÖÕ ÏÔÒÉÍÁÔÉ ÛÒÉÆÔ %s"
+
+#: gui_at_fs.c:2538
+msgid "vim_SelFile: can't return to current directory"
+msgstr "vim_SelFile: ÎÅ ÍÏÖÕ ÐÏ×ÅÒÎÉÔÕÓÑ × ÐÏÔÏÞÎÕ ÄÉÒÅËÔÏÒ¦À"
+
+#: gui_at_fs.c:2557
+msgid "Pathname:"
+msgstr "ûÌÑÈ:"
+
+#: gui_at_fs.c:2563
+msgid "vim_SelFile: can't get current directory"
+msgstr "vim_SelFile: ÎÅ ÍÏÖÕ Ä¦ÓÔÁÔÉ ÐÏÔÏÞÎÕ ÄÉÒÅËÔÏÒ¦À"
+
+#: gui_at_fs.c:2571 gui_motif.c:1607
+msgid "OK"
+msgstr "OK"
+
+#. 'Cancel' button
+#: gui_at_fs.c:2571 gui_gtk.c:1689 gui_motif.c:1602 gui_motif.c:2823
+msgid "Cancel"
+msgstr "Cancel"
+
+#: gui_athena.c:1938 gui_motif.c:1855
+msgid "Vim dialog"
+msgstr "ä¦ÁÌÏÇ Vim"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "Scrollbar Widget: ÎÅ ÍÏÖÕ ×ÚÎÁÔÉ ÒÏÚÍ¦Ò ÓËÏÒÏÞÅÎϧ ËÁÒÔÉÎËÉ."
+
+#: gui_beval.c:68
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr ""
+"E232: îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ BalloonEval Ú ÐÏצÄÏÍÌÅÎÎÑÍ ¦ ÆÕÎËæ¤À ÏÄÎÏÞÁÓÎÏ"
+
+# msgstr "E228: "
+#: gui.c:181
+msgid "E229: Cannot start the GUI"
+msgstr "E229: îÅ ÍÏÖÕ ÒÏÚÐÏÞÁÔÉ GUI"
+
+# msgstr "E229: "
+#: gui.c:306
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: îÅ ÍÏÖÕ ÞÉÔÁÔÉ Ú \"%s\""
+
+# msgstr "E230: "
+#: gui.c:431
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: 'guifontwide' ×ÉÚÎÁÞÅÎÏ ÎÅצÒÎÏ"
+
+# msgstr "E231: "
+#: gui.c:3928
+msgid "Error"
+msgstr "ðÏÍÉÌËÁ"
+
+#: gui.c:3929
+msgid "&Ok"
+msgstr "&Ok"
+
+# msgstr "E232: "
+#: gui_gtk.c:1148
+msgid "Vim dialog..."
+msgstr "ä¦ÁÌÏÇ Vim..."
+
+#: gui_gtk.c:1525 gui_motif.c:2742
+msgid "VIM - Search and Replace..."
+msgstr "VIM - úÎÁÊÔÉ ¦ ÚÁͦÎÉÔÉ..."
+
+#: gui_gtk.c:1530 gui_motif.c:2744
+msgid "VIM - Search..."
+msgstr "VIM - ðÏÛÕË"
+
+#: gui_gtk.c:1553 gui_motif.c:2862
+msgid "Find what:"
+msgstr "úÎÁÊÔÉ:"
+
+#: gui_gtk.c:1571 gui_motif.c:2894
+msgid "Replace with:"
+msgstr "úÁͦÎÁ:"
+
+#. exact match only button
+#: gui_gtk.c:1603 gui_motif.c:2996
+msgid "Match exact word only"
+msgstr "÷×ÁÖÁÔÉ ÚÁ ÚÂ¦Ç ÌÉÛÅ ÐÏ×ÎÅ ÓÌÏ×Ï"
+
+#: gui_gtk.c:1615 gui_motif.c:2964
+msgid "Direction"
+msgstr "îÁÐÒÑÍ"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:1627 gui_motif.c:2976
+msgid "Up"
+msgstr "äÏÇÏÒÉ"
+
+#: gui_gtk.c:1631 gui_motif.c:2984
+msgid "Down"
+msgstr "õÎÉÚ"
+
+#. 'Find Next' button
+#: gui_gtk.c:1653 gui_motif.c:2766
+msgid "Find Next"
+msgstr "úÎÁÊÔÉ ÎÁÓÔÕÐÎÉÊ ×ÁÒ¦ÁÎÔ"
+
+#. 'Replace' button
+#: gui_gtk.c:1670 gui_motif.c:2783
+msgid "Replace"
+msgstr "úÁͦÎÉÔÉ"
+
+#. 'Replace All' button
+#: gui_gtk.c:1679 gui_motif.c:2796
+msgid "Replace All"
+msgstr "úÁͦÎÉÔÉ ÕÓ¦"
+
+#: gui_gtk_x11.c:1078 gui_x11.c:1199
+msgid "E233: cannot open display"
+msgstr "E233: îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÄÉÓÐÌÅÊ"
+
+# msgstr "E233: "
+#: gui_gtk_x11.c:2435 gui_x11.c:2002
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: îÅצÄÏÍÉÊ fontset: %s"
+
+# msgstr "E234: "
+#: gui_gtk_x11.c:2462
+msgid "Font Selection"
+msgstr "÷ÉĦÌÅÎÎÑ"
+
+#: gui_gtk_x11.c:2704 gui_mac.c:2780 gui_w48.c:1197 gui_x11.c:1838
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "îÅצÄÏÍÉÊ ÛÒÉÆÔ: %s"
+
+# msgstr "E235: "
+#: gui_gtk_x11.c:2715 gui_x11.c:1862
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: ûÒÉÆÔ \"%s\" ÎÅ ÍÏÎÏÛÉÒÉÎÎÉÊ"
+
+# msgstr "E236: "
+#: gui_gtk_x11.c:2845
+#, c-format
+msgid "E242: Color name not recognized: %s"
+msgstr "E242: îÅÚÒÏÚÕͦÌÁ ÎÁÚ×Á ËÏÌØÏÒÕ: %s"
+
+# msgstr "E242: "
+#: gui_gtk_x11.c:3521 ui.c:1929
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "÷ÉËÏÒÉÓÔÁÎÏ CUT_BUFFER0 ÚÁͦÓÔØ ÐÏÒÏÖÎØÏÇÏ ×ÉĦÌÅÎÎÑ"
+
+#: gui_motif.c:1601 gui_motif.c:1604
+msgid "Filter"
+msgstr "æ¦ÌØÔÒ"
+
+#: gui_motif.c:1603
+msgid "Directories"
+msgstr "ÄÉÒÅËÔÏÒ¦§"
+
+#: gui_motif.c:1605
+msgid "Help"
+msgstr "äÏÐÏÍÏÇÁ"
+
+#: gui_motif.c:1606
+msgid "Files"
+msgstr "æÁÊÌÉ"
+
+#: gui_motif.c:1608
+msgid "Selection"
+msgstr "÷ÉÂ¦Ò ÛÒÉÆÔÁ"
+
+#: gui_motif.c:2809
+msgid "Undo"
+msgstr "÷¦ÄͦÎÁ"
+
+#: gui_riscos.c:951
+#, c-format
+msgid "E235: Can't load Zap font '%s'"
+msgstr ""
+"E235: ñ ÎÅ ÚÎÁÀ ÝÏ ÔÁËÅ riscos, × õËÒÁ§Î¦ ÔÁËÏÇÏ ÎÅÍÁ¤.. (Á ÔÕÔ ÝÅ Ê ÑËÉÊÓØ "
+"ÛÒÉÆÔ ÎÅ ÈÏÞÅ ×ÁÎÔÁÖÉÔÉÓÑ: %s)"
+
+# msgstr "E235: "
+#: gui_riscos.c:1047
+#, c-format
+msgid "E235: Can't use font %s"
+msgstr "E235: îÅ ÍÏÖÕ ×ÉËÏÒÉÓÔÁÔÉ ÛÒÉÆÔ %s"
+
+# msgstr "E235: "
+#: gui_riscos.c:1167
+#, c-format
+msgid "E242: Missing color: %s"
+msgstr "E242: ÷ÔÒÁÞÅÎÏ ËÏ̦Ò: %s"
+
+# msgstr "E242: "
+#: gui_riscos.c:3269
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"ìÑËÁ¤ÍÏ Ä¦ÔÅÊ Í¦Ì¦Ã¦ÏÎÅÒÏÍ. :-)\n"
+
+#: gui_w32.c:825
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr ""
+"E243: áÒÇÕÍÅÎÔ ÎŠЦÄÔÒÉÍÕ¤ØÔØÓÑ: \"-%s\", ×ÉËÕÒÉÓÔÏ×ÕÊÔÅ ×ÅÒÓ¦À Ú OLE."
+
+# msgstr "E245: "
+#: gui_w48.c:2068
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "VIM - ðÏÛÕË"
+
+#: gui_w48.c:2093
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "VIM - úÎÁÊÔÉ ¦ ÚÁͦÎÉÔÉ..."
+
+#: gui_x11.c:1419
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr ""
+"Vim E458: îÅÍÁ¤ צÌØÎÉÈ ÓÅËÃ¦Ê Õ ÔÁÂÌÉæ ËÏÌØÏÒ¦×. äÅÑ˦ ËÏÌØÏÒÉ ÍÏÖÕÔØ "
+"ÂÕÔÉ ×ÔÒÁÞÅΦ"
+
+#: gui_x11.c:1992
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: ûÒÉÆÔÉ ÄÌÑ ÃØÏÇÏ ÎÁÂÏÒÕ ÓÉÍ×ÏÌ¦× ×¦ÄÓÕÔΦ Õ fontset %s:"
+
+# msgstr "E250: "
+#: gui_x11.c:2035
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: îÁÚ×Á fontset: %s"
+
+# msgstr "E252: "
+#: gui_x11.c:2036
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "ûÒÉÆÔ '%s' ÎÅ ¤ ÍÏÎÏÛÉÒÉÎÎÉÍ"
+
+#: gui_x11.c:2055
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E252: îÁÚ×Á fontset: %s\n"
+
+#: gui_x11.c:2056
+#, c-format
+msgid "Font0: %s\n"
+msgstr "ûÒÉÆÔ0: %s\n"
+
+#: gui_x11.c:2057
+#, c-format
+msgid "Font1: %s\n"
+msgstr "ûÒÉÆÔ1: %s\n"
+
+#: gui_x11.c:2058
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "öÉÒΦÓÔØ ÛÒÉÆÔÁ %d ÍÁ¤ ÂÕÔÉ × Äצަ ¦ÌØÛÏÀ ÚÁ ÔÏ×ÝÉÎÕ font0\n"
+
+#: gui_x11.c:2059
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "öÉÒΦÓÔØ font0: %ld\n"
+
+#: gui_x11.c:2060
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"öÉÒΦÓÔØ font1: %ld\n"
+"\n"
+
+#: gui_x11.c:2206
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: îÅ ÍÏÖÕ ÒÏÚͦÓÔÉÔÉ ËÏÌ¦Ò %s"
+
+# msgstr "E254: "
+#: gui_x11.c:3256
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: îÅ ÍÏÖÎÁ ÚÞÉÔÁÔÉ ÄÁΦ ÎÁÐÉÓÕ!"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: ðÏÍÉÌËÁ `Hangul automata' [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+# msgstr "E255: "
+#: if_cscope.c:67
+msgid "Add a new database"
+msgstr "äÏÄÁÔÉ ÎÏ×Õ ÂÁÚÕ ÄÁÎÉÈ"
+
+#: if_cscope.c:69
+msgid "Query for a pattern"
+msgstr "úÁÐÉÔ ÚÁ ÚÒÁÚËÏÍ"
+
+#: if_cscope.c:71
+msgid "Show this message"
+msgstr "ðÏËÁÚÁÔÉ ÃÅ ÐÏצÄÏÍÌÅÎÎÑ"
+
+#: if_cscope.c:73
+msgid "Kill a connection"
+msgstr "úÎÉÝÉÔÉ Ú'¤ÄÎÁÎÎÑ"
+
+#: if_cscope.c:75
+msgid "Reinit all connections"
+msgstr "òÏÚÐÏÞÁÔÉ Ú ÐÏÞÁÔËÕ ÕÓ¦ Ú'¤ÄÎÁÎÎÑ"
+
+#: if_cscope.c:77
+msgid "Show connections"
+msgstr "ðÏËÁÚÁÔÉ Ú'¤ÄÎÁÎÎÑ"
+
+#: if_cscope.c:108
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "ãÑ ËÏÍÁÎÄÁ cscope ÎÅ Õͦ¤ ĦÌÉÔÉ ×¦ËÎÏ.\n"
+
+#: if_cscope.c:143
+msgid "Usage: cstag <ident>"
+msgstr "÷ÉËÏÒÉÓÔÏ×ÕÊÔÅ: cstag <ÐÏͦÔËÁ>"
+
+#: if_cscope.c:199
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: ÐÏͦÔËÕ ÎÅ ÚÎÁÊÄÅÎÏ"
+
+# msgstr "E257: "
+#: if_cscope.c:407 if_cscope.c:451
+#, c-format
+msgid "stat(%s) error: %d"
+msgstr "stat(%s) ÐÏÍÉÌËÁ: %d"
+
+#: if_cscope.c:460 if_cscope.c:467
+#, c-format
+msgid "Added cscope database %s"
+msgstr "äÏÄÁÎÏ ÂÁÚÕ ÄÁÎÉÈ cscope %s"
+
+#: if_cscope.c:474
+#, c-format
+msgid "%s is not a directory or a valid cscope database"
+msgstr "%s ÎÅ ¤ Φ ÄÉÒÅËÔÏÒ¦¤À Φ ÂÁÚÏÀ ÄÁÎÉÈ cscope"
+
+#: if_cscope.c:557
+#, c-format
+msgid "error reading cscope connection %d"
+msgstr "ðÏÍÉÌËÁ ÞÉÔÁÎÎÑ Ú'¤ÄÎÁÎÎÑ cscope #%d"
+
+#: if_cscope.c:633
+msgid "unknown cscope search type"
+msgstr "îÅצÄÏÍ¦Ê ÔÉÐ ÐÏÛÕËÕ cscope"
+
+#: if_cscope.c:680
+msgid "Could not create cscope pipes"
+msgstr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ËÁÎÁÌ ÄÏ cscope"
+
+#: if_cscope.c:745
+msgid "cs_create_connection exec failed"
+msgstr "cs_create_connection: ÐÏÍÉÌËÁ Ð¦Ä ÞÁÓ ×ÉËÏÎÁÎÎÑ"
+
+#: if_cscope.c:755
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen ÄÌÑ to_fp ÎÅ ×ÄÁ×ÓÑ"
+
+#: if_cscope.c:757
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen ÄÌÑ fr_fp ÎÅ ×ÄÁ×ÓÑ"
+
+#: if_cscope.c:785
+msgid "no cscope connections"
+msgstr "ÖÏÄÎÏÇÏ Ú'¤ÄÎÁÎÑ Ú cscope"
+
+# msgstr "E258: "
+#: if_cscope.c:855
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: äÌÑ %s-ÚÁÐÉÔÕ cscope ÓÔÏÓÏ×ÎÏ %s ÎÅ ÚÎÁÊÄÅÎÏ Ó¦ÒÎÉ˦×"
+
+# msgstr "E259: "
+#: if_cscope.c:899
+msgid "cscope commands:\n"
+msgstr "ËÏÍÁÎÄÉ cscope:\n"
+
+#: if_cscope.c:902
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)\n"
+msgstr "%-5s: %-30s (÷ÖÉ×ÁÊÔÅ: %s)\n"
+
+#: if_cscope.c:970
+msgid "duplicate cscope database not added"
+msgstr "ÐÏ×ÔÏÒÎÁ ÂÁÚÁ ÄÁÎÉÈ cscope ÎÅ ÄÏÄÁÎÁ"
+
+#: if_cscope.c:981
+msgid "maximum number of cscope connections reached"
+msgstr "˦ÌØ˦ÓÔØ Ú'¤ÄÎÁÎØ Ú cscope ÄÏÓÑÇÌÁ ÍÁËÓÉÍÕÍÕ"
+
+#: if_cscope.c:1102
+msgid "E260: cscope connection not found"
+msgstr "E260: Ú'¤ÄÎÁÎÎÑ Ú cscope ÎÅ ÚÎÁÊÄÅÎÏ"
+
+# msgstr "E260: "
+#: if_cscope.c:1105
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: Ú'¤ÄÎÁÎÎÑ Ú cscope %s ÎÅ ÚÎÁÊÄÅÎÏ"
+
+# msgstr "E261: "
+#: if_cscope.c:1141
+msgid "cscope connection closed"
+msgstr "Ú'¤ÄÎÁÎÎÑ Ú cscope ÚÁ˦ÎÞÅÎÏ"
+
+#: if_cscope.c:1149
+#, c-format
+msgid "cscope connection %s closed\n"
+msgstr "Ú'¤ÄÎÁÎÎÑ Ú cscope %s ÚÁ˦ÎÞÅÎÏ\n"
+
+#. should not reach here
+#: if_cscope.c:1290
+msgid "fatal error in cs_manage_matches"
+msgstr "cs_manage_matches: Ó¦ÒÎÉË¦× Â¦ÌØÛÅ ÎÅÍÁ¤ [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#: if_cscope.c:1341
+#, c-format
+msgid "E262: error reading cscope connection %d"
+msgstr "E262: ÐÏÍÉÌËÁ ÞÉÔÁÎÎÑ Ú Ú'¤ÄÎÁÎÎÑ cscope %d"
+
+# msgstr "E262: "
+#: if_cscope.c:1449
+msgid "couldn't malloc\n"
+msgstr "ÎÅ ÍÏÖÕ ×ÉĦÌÉÔÉ ÐÁÍ'ÑÔØ\n"
+
+#: if_cscope.c:1454
+#, c-format
+msgid "Cscope tag: %s\n"
+msgstr "ðÏͦÔËÁ cscope: %s\n"
+
+#: if_cscope.c:1458
+msgid " # line"
+msgstr " # ÒÑÄÏË"
+
+#: if_cscope.c:1460
+msgid "filename / context / line\n"
+msgstr "ÆÁÊÌ / ËÏÎÔÅËÓÔ / ÒÑÄÏË\n"
+
+#: if_cscope.c:1718
+msgid "All cscope databases reset"
+msgstr "õÓ¦ Ú'¤ÄÎÁÎÎÑ Ú cscope ÐÅÒÅÚÁ×ÁÎÔÁÖÅÎÏ"
+
+#: if_cscope.c:1785
+msgid "no cscope connections\n"
+msgstr "öÏÄÎÏÇÏ Ú'¤ÄÎÁÎÎÑ Ú cscope\n"
+
+#: if_cscope.c:1789
+msgid " # pid database name prepend path\n"
+msgstr " # pid ÎÁÚ×Á ÂÁÚÉ ÄÁÎÉÈ ÛÌÑÈ\n"
+
+#: if_cscope.c:1800
+#, c-format
+msgid "%2d %-5ld %-34s <none>\n"
+msgstr "%2d %-5ld %-34s <ÖÏÖÎÏÇÏ>\n"
+
+#: if_python.c:246 if_ruby.c:260 if_tcl.c:195 mbyte.c:2568 os_win32.c:269
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: îÅ ÍÏÖÕ ÚÁ×ÁÎÔÁÖÉÔÉ Â¦Â̦ÏÔÅËÕ %s"
+
+#: if_python.c:258 if_ruby.c:272 if_tcl.c:206 mbyte.c:2584 os_win32.c:281
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: îÅ ÍÏÖÕ ÚÁ×ÁÎÔÁÖÉÔÉ Â¦Â̦ÏÔÅÞÎÕ ÆÕÎËæÀ %s"
+
+#: if_python.c:383
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr ""
+"E263: ÷ÉÂÁÞÔÅ, ÃÑ ËÏÍÁÎÄÁ ×ÉÍËÎÕÔÁ, ¦Â̦ÏÔÅËÁ Python ÎÅ ÍÏÖÅ ÂÕÔÉ "
+"ÚÁ×ÁÎÔÁÖÅÎÁ."
+
+#: if_python.c:583
+msgid "can't delete OutputObject attributes"
+msgstr "ÎÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÁÔÒÉÂÕÔÉ OutputObject"
+
+#: if_python.c:590
+msgid "softspace must be an integer"
+msgstr "softspace ÍÁ¤ ÂÕÔÉ ÎÁÔÕÒÁÌØÎÉÍ"
+
+# msgstr "E180: "
+#: if_python.c:598
+msgid "invalid attribute"
+msgstr "ÎÅצÒÎÉÊ ÁÔÒÉÂÕÔ"
+
+#: if_python.c:637 if_python.c:651
+msgid "writelines() requires list of strings"
+msgstr "writelines() ÐÏÔÒ¦ÂÅÎ ÓÐÉÓÏË ÒÑÄ˦×"
+
+#: if_python.c:777
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: ðÏÍÉÌËÁ ¦Î¦Ã¦Ñ̦ÚÁæ§ ÏÂ'¤ËÔ¦× ××ÏÄÕ/×É×ÏÄÕ"
+
+#: if_python.c:962 if_tcl.c:1403
+msgid "invalid expression"
+msgstr "ÎÅצÒÎÉÊ ×ÉÒÁÚ"
+
+#: if_python.c:976 if_tcl.c:1408
+msgid "expressions disabled at compile time"
+msgstr "ÏÂÒÏÂËÕ ×ÉÒÁÚ¦× ÚÁÂÏÒÏÎÅÎÏ ÐÏÄ ÞÁÓ ËÏÍЦÌÑæ§"
+
+#: if_python.c:989
+msgid "attempt to refer to deleted buffer"
+msgstr "ÓÐÒÏÂÁ ÞÉÔÁÔÉ ×ÉÄÁÌÅÎÉÊ ÂÕÆÅÒ"
+
+#: if_python.c:1004 if_python.c:1045 if_python.c:1109 if_tcl.c:1215
+msgid "line number out of range"
+msgstr "ÎÏÍÅÒ ÒÑÄËÁ ÚÁ ÍÅÖÁÍÉ ÆÁÊÌÁ"
+
+#: if_python.c:1242
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<ÏÂ'¤ËÔ ÂÕÆÅÒÁ (×ÉÄÁÌÅÎÏ) × %8lX>"
+
+#: if_python.c:1333 if_tcl.c:837
+msgid "invalid mark name"
+msgstr "ÎÅצÒÎÁ ÎÁÚ×Á ÐÏͦÔËÉ"
+
+#: if_python.c:1608
+msgid "no such buffer"
+msgstr "ÔÁËÏÇÏ ÂÕÆÅÒÁ ÎÅÍÁ¤"
+
+#: if_python.c:1696
+msgid "attempt to refer to deleted window"
+msgstr "ÓÔÒÏÂÁ Ú×ÅÒÎÕÔÉÓÑ ÄÏ ×ÉÄÁÌÅÎÏÇÏ ×¦ËÎÁ"
+
+#: if_python.c:1741
+msgid "readonly attribute"
+msgstr "ÌÉÛÅ ÄÌÑ ÞÉÔÁÎÎÑ"
+
+#: if_python.c:1754
+msgid "cursor position outside buffer"
+msgstr "ËÕÒÓÏÒ ÚÁ ÍÅÖÁÍÉ ÂÕÆÅÒÁ"
+
+#: if_python.c:1831
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<ÏÂ'¤ËÔ ×¦ËÎÁ (×ÉÄÁÌÅÎÏ) × %.8lX>"
+
+#: if_python.c:1843
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<ÏÂ'¤ËÔ ×¦ËÎÁ (ÎÅצÄÏÍÉÊ) × %.8lX>"
+
+#: if_python.c:1845
+#, c-format
+msgid "<window %d>"
+msgstr "<צËÎÏ %d>"
+
+#: if_python.c:1921
+msgid "no such window"
+msgstr "ÔÁËÏÇÏ ×¦ËÎÁ ÎÅÍÁ¤"
+
+#: if_python.c:2178 if_python.c:2213 if_python.c:2263 if_python.c:2326
+#: if_python.c:2446 if_python.c:2498 if_tcl.c:685 if_tcl.c:730 if_tcl.c:804
+#: if_tcl.c:874 if_tcl.c:1999
+msgid "cannot save undo information"
+msgstr "ÎÅ ÍÏÖÕ ÚÂÅÒÅÇÔÉ ¦ÎÆÏÒÍÁæÀ ÄÌÑ ×¦ÄͦÎÉ"
+
+#: if_python.c:2180 if_python.c:2270 if_python.c:2337
+msgid "cannot delete line"
+msgstr "ÎÅÍÏÖÌÉ×Ï ×ÉÄÁÌÉÔÉ ÒÑÄÏË"
+
+#: if_python.c:2215 if_python.c:2353 if_tcl.c:691 if_tcl.c:2021
+msgid "cannot replace line"
+msgstr "ÎÅÍÏÖÌÉ×Ï ÚÁͦÎÉÔÉ ÒÑÄÏË"
+
+#: if_python.c:2369 if_python.c:2448 if_python.c:2506
+msgid "cannot insert line"
+msgstr "ÎÅ ÍÏÖÕ ×ÓÔÁ×ÉÔÉ ÒÑÄÏË"
+
+#: if_python.c:2610
+msgid "string cannot contain newlines"
+msgstr "¦ÌØÛ Î¦Ö ÏÄÉÎ ÒÑÄÏË"
+
+#: if_ruby.c:401
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr ""
+"E266: ÷ÉÂÁÞÔÅ, ÃÑ ËÏÍÁÎÄÁ ×ÉÍËÎÕÔÁ, ¦Â̦ÏÔÅËÁ Ruby ÎÅ ÍÏÖÅ ÂÕÔÉ ÚÁ×ÁÎÔÁÖÅÎÁ."
+
+# msgstr "E233: "
+#: if_ruby.c:464
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E234: îÅצÄÏÍÉÊ ÓÔÁÔÕÓ longjmp: %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "ðÅÒÅÍËÎÕÔÉ implementation/definition"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "úÎÁÊÔÉ ÂÁÚÏ×ÉÊ ËÌÁÓ"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "ðÏËÁÚÁÔÉ ÚÁͦÎÅΦ(overridden) ÆÕÎËæ§-ÞÌÅÎÉ"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "úÞÉÔÁÔÉ Ú ÆÁÊÌÁ"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "úÞÉÔÁÔÉ Ú ÐÒÏÅËÔÕ"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "úÞÉÔÁÔÉ Ú ÕÓ¦È ÐÒÏÅËÔ¦×"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "úÞÉÔÁÔÉ"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "äÖÅÒÅÌÏ"
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "úÎÁÊÔÉ ÓÉÍ×ÏÌ"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "ðÒÏÄÉ×ÉÔÉÓÑ ËÌÁÓ"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "úÎÁÊÔÉ ËÌÁÓ × ¦¤ÒÁÒȦ§"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "úÎÁÊÔÉ ËÌÁÓ × ÚÁÂÏÒÏÎÅÎ¦Ê §¤ÒÁÒȦ§"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref ×ËÁÚÕ¤ ÎÁ"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "ÎÁ Xref ×ËÁÚÁÎÏ Ú"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref ÍÁ¤"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref ×ÉËÏÒÉÓÔÁÎÏ"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "ðÏËÁÚÁÔÉ docu"
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "óÔ×ÏÒÉÔÉ docu ÄÌÑ"
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr ""
+"îÅ ÍÏÖÕ Ú¤ÄÎÁÔÉÓÑ Ú SNiFF+. ðÅÒÅצÒÔÅ ÏÔÏÞÅÎÎÑ\n"
+"(sniffemacs ÎÅ ÂÕÌÏ ÚÎÁÊÄÅÎÏ Õ ÛÌÑÈÕ ÐÏÛÕËÕ).\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: ðÏÍÉÌËÁ ÐÁÄ ÞÁÓ ÚÞÉÔÕ×ÁÎÎÑ. ÷¦Ä¤ÄÎÁÎÏ"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "ÚÁÒÁÚ SNiFF"
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "ÎÅ "
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "ЦĤÄÎÁÎÉÊ"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: îÅצÄÏÍÅ ÚÁÐÉÔÁÎÎÑ ÄÏ SNiFF+: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: ðÏÍÉÌËÁ Ð¦Ä ÞÁÓ Ú¤ÄÎÁÎÎÑ Ú SNiFF+"
+
+#: if_sniff.c:1010
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: SNiFF+ ΊЦĤÄÎÁÎÏ"
+
+#: if_sniff.c:1019
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: îÅ ¤ ÂÕÆÅÒÏÍ SNiFF+"
+
+#: if_sniff.c:1084
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff. ÐÏÍÉÌËÁ ÚÁÐÉÓÕ. ÷¦Ä¤ÄÎÁÎÏ"
+
+#: if_tcl.c:419
+msgid "invalid buffer number"
+msgstr "ÎÅצÒÎÁ ÎÁÚ×Á ÂÕÆÅÒÁ"
+
+#: if_tcl.c:465 if_tcl.c:932 if_tcl.c:1111
+msgid "not implemented yet"
+msgstr "ΊĦ¤ (ÐÏËÉ ÝÏ)"
+
+#: if_tcl.c:502
+msgid "unknown option"
+msgstr "ÎÅצÄÏÍÁ ÏÐæÑ"
+
+#. ???
+#: if_tcl.c:775
+msgid "cannot set line(s)"
+msgstr "ÎÅ ÍÏÖÕ ÚÁÄÁÔÉ ÒÑÄËÉ"
+
+# msgstr "E19: "
+#: if_tcl.c:846
+msgid "mark not set"
+msgstr "ÐÏͦÔËÕ ÎÅ ×ËÁÚÁÎÏ"
+
+#: if_tcl.c:852 if_tcl.c:1067
+#, c-format
+msgid "row %d column %d"
+msgstr "ÒÑÄÏË %d ËÏÌÏÎËÁ %d"
+
+#: if_tcl.c:882
+msgid "cannot insert/append line"
+msgstr "îÅ ÍÏÖÕ ×ÓÔÁ×ÉÔÉ/ÄÏÄÁÔÉ ÒÑÄÏË"
+
+#: if_tcl.c:1269
+msgid "unknown flag: "
+msgstr "ÎÅצÄÏÍÉÊ ÐÒÁÐÏÒÅÃØ: "
+
+#: if_tcl.c:1339
+msgid "unknown vimOption"
+msgstr "îÅצÄÏÍÁ ÏÐæÑ"
+
+#: if_tcl.c:1424
+msgid "keyboard interrupt"
+msgstr "ÐÅÒÅÒ×ÁÎÏ ËÏÒÉÓÔÕ×ÁÞÅÍ"
+
+#: if_tcl.c:1429
+msgid "vim error"
+msgstr "ÐÏÍÉÌËÁ Vim"
+
+#: if_tcl.c:1472
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "ÎÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ËÏÍÁÎÄÕ ÄÌÑ ×¦ËÎÁ/ÂÕÆÅÒÁ: ÏÂ'ÅËÔ ×ÉÄÑÌѤÔØÓÑ"
+
+#: if_tcl.c:1546
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr "îÅ ÍÏÖÕ ÚÁÒŤÓÔÒÕ×ÁÔÉ ÐÏĦÀ: ÂÕÆÅÒ/צËÎÏ ÕÖÅ ÚÎÉÝÕ¤ÔØÓÑ"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1563
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to "
+"vim-dev@vim.org"
+msgstr ""
+"E280: ðïíéìëá × ¦ÎÔÅÒÆÅÊÓ¦ Ú TCL: ÍÏÖÌÉ×Ï ÐÏÛËÏÄÖÅÎÏ ÓÐÉÓÏË ÐÏÓÉÌÁÎÎØ.. "
+"ðÏצÄÏÍÔÅ, ÂÕÄØÌÁÓËÁ, ÎÁ vim-dev@vim.org"
+
+#: if_tcl.c:1564
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr "îÅ ÍÏÖÕ ÚÁÒŤÓÔÒÕ×ÁÔÉ ÐÏĦÀ: ÐÏÓÉÌÁÎÎÑ ÎÁ ÂÕÆÅÒ/צËÎÏ ÎÅ ÚÎÁÊÄÅÎÏ"
+
+#: if_tcl.c:1725
+msgid "Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr "÷ÉÂÁÞÔÅ, ÃÑ ËÏÍÁÎÄÁ ×ÉÍËÎÕÔÁ, ¦Â̦ÏÔÅËÁ Tcl ÎÅ ÍÏÖÅ ÂÕÔÉ ÚÁ×ÁÎÔÁÖÅÎÁ."
+
+#: if_tcl.c:1887
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr ""
+"E280: ðïíéìëá × ¦ÎÔÅÒÆÅÊÓ¦ Ú TCL: ÍÏÖÌÉ×Ï ÒÅÚÕÌØÔÁÔ ÎÅ int.. ðÏצÄÏÍÔÅ, "
+"ÂÕÄØÌÁÓËÁ, ÎÁ vim-dev@vim.org"
+
+#: if_tcl.c:2007
+msgid "cannot get line"
+msgstr "ÎÅ ÍÏÖÕ Ä¦ÓÔÁÔÉ ÒÑÄÏË"
+
+#: if_xcmdsrv.c:209
+msgid "Unable to register a command server name"
+msgstr "îÅ ÍÏÖÕ ÚÁÒŤÓÔÒÕ×ÁÔÉ ¦Í'Ñ ÓÅÒ×ÅÒÁ"
+
+#: if_xcmdsrv.c:422
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E354: îÅÍÁ¤ ÚÁÒÅÅÓÔÒÏ×ÁÎÉÈ ÓÅÒ×ÅÒ¦× ÎÁ ¦Í'Ñ \"%s\""
+
+#: if_xcmdsrv.c:451
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: îÅ ×ÄÁÌÏÓÑ ×¦Ä¦ÓÌÁÔÉ ËÏÍÁÎÄÕ ÄÏ Ë¦ÎÃÅ×ϧ ÐÒÏÇÒÁÍÉ"
+
+#: if_xcmdsrv.c:719
+#, c-format
+msgid "Invalid server id used: %s"
+msgstr "÷ÉËÏÒÉÓÔÁÎÏ ÎÅצÒÎÕ ÎÁÚ×Õ ÓÅÒ×ÅÒÁ :%s"
+
+#: if_xcmdsrv.c:1066
+msgid "E249: couldn't read VIM instance registry property"
+msgstr "E249: ÎÅ ÍÏÖÕ ÚÞÉÔÁÔÉ ÞÁÓÔÉÎÕ ÒŤÓÔÒÕ ÚÒÁÚËÁ Vim"
+
+#: if_xcmdsrv.c:1077
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: ÞÁÓÔÉÎÁ ÒŤÓÔÒÕ ÚÒÁÚËÁ Vim ÎÅצÒÎÏ ÚÆÏÒÍÏ×ÁÎÁ. ÷ÉÄÁÌÅÎÏ!"
+
+#: main.c:53 option.c:3162 option.c:3269
+msgid "Unknown option"
+msgstr "îÅצÄÏÍÁ ÏÐæÑ"
+
+#: main.c:55
+msgid "Too many edit arguments"
+msgstr "úÁÂÁÇÁÔÏ ÁÒÇÕÍÅÎÔ¦×"
+
+#: main.c:57
+msgid "Argument missing after"
+msgstr "÷ÔÒÁÞÅÎÏ ÁÒÇÕÍÅÎÔÉ Ð¦ÓÌÑ"
+
+#: main.c:59
+msgid "Garbage after option"
+msgstr "óͦÔÔÑ ÐÏÓÌÑ ÏÐæ§"
+
+#: main.c:61
+msgid "Too many \"+command\" or \"-c command\" arguments"
+msgstr "úÁÂÁÇÁÔÏ '+' ÁÂÏ '-c' ÁÒÇÕÍÅÎÔ¦×"
+
+# msgstr "E14: "
+#: main.c:63
+msgid "Invalid argument for"
+msgstr "îÅצÒÎÉÊ ÁÒÇÕÍÅÎÔ ÄÌÑ"
+
+#: main.c:436
+msgid "This Vim was not compiled with the diff feature."
+msgstr "ãÑ ×ÅÒÓ¦Ñ Vim ÎÅ ÂÕÌÁ ÚËÏÍЦÌØÏ×ÁÎÁ Ú Ð¦ÄÔÒÉÍËÏÀ diff."
+
+#: main.c:858
+msgid "Attempt to open script file again: \""
+msgstr "óÐÒÏÂÁ צÄËÒÉÔÉ ÝÅ ÒÁÚ ÆÁÊÌ ËÏÍÁÎÄ \""
+
+#: main.c:862 main.c:869 main.c:913 memline.c:3673 memline.c:3677
+#: version.c:1058 version.c:1063 version.c:1068 version.c:1073 version.c:1078
+#: version.c:1083 version.c:1089 version.c:1093 version.c:1097 version.c:1102
+#: version.c:1109 version.c:1117 version.c:1123
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:867
+msgid "Cannot open for reading: \""
+msgstr "îÅ ÍÏÖÕ ÐÒÏÞÉÔÁÔÉ: \""
+
+#: main.c:911
+msgid "Cannot open for script output: \""
+msgstr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÑË ×¦È¦ÄÎÉÊ ÆÁÊÌ: \""
+
+#: main.c:1020
+#, c-format
+msgid "%d files to edit\n"
+msgstr "%d ÆÁÊÌ¦× ÚÁÌÉÛÉÌÏÓØ\n"
+
+#: main.c:1094
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: õ×ÁÇÁ: ÷ÉÈ¦Ä ÊÄÅ ÎÅ ÎÁ ÔÅÒͦÎÁÌ\n"
+
+#: main.c:1096
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: õ×ÁÇÁ: ÷ȦÄÎ ÊÄÅ ÎÅ Ú ÔÅÒͦÎÁÌÕ\n"
+
+#. just in case..
+#: main.c:1171
+msgid "pre-vimrc command line"
+msgstr "ËÏÍÁÎÄÉ Ñ˦ ×ÉËÏÎÕ×ÁÌÉÓÑ ÄÏ vimrc"
+
+#: main.c:1206
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: îÅ ÍÏÖÕ ÐÒÏÞÉÔÁÔÉ \"%s\""
+
+# msgstr "E282: "
+#: main.c:2175
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"÷ÚÎÁÊÔŠ¦ÌØÛÅ: vim -h\n"
+
+#: main.c:2208
+msgid "[file ..] edit specified file(s)"
+msgstr "[ÆÁÊÌ ..] ÒÅÄÁÇÕ×ÁÔÉ ×ËÁÚÁÎÉÊ ÆÁÊÌ"
+
+#: main.c:2209
+msgid "- read text from stdin"
+msgstr "- ÞÉÔÁÔÉ ÔÅËÓÔ Ú stdin"
+
+#: main.c:2210
+msgid "-t tag edit file where tag is defined"
+msgstr "-t ÐÏͦÔËÁ ÐÅÒÅÔÉ ÄÏ ÐÏͦÔËÉ"
+
+#: main.c:2212
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [ÆÁÊÌ] ÐÅÒÅÊÔÉ ÄÏ ÐÅÒÛϧ ÐÏÍÉÌËÉ"
+
+#: main.c:2221
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+"÷ÖÉ×ÁÊÔÅ:"
+
+#: main.c:2224
+msgid " vim [arguments] "
+msgstr " vim [ÁÒÇÕÍÅÎÔÉ] "
+
+#: main.c:2228
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" ÁÂÏ:"
+
+#: main.c:2231
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"áÒÇÕÍÅÎÔÉ:\n"
+
+#: main.c:2232
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tìÉÛÅ ¦ÍÅÎÁ ÆÁÊÌ¦× Ð¦ÓÌÑ ÃØÏÇÏ"
+
+#: main.c:2234
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\túÁÒŤÓÔÒÕ×ÁÔÉ ÃÅÊ gvim ÞÅÒÅÚ OLE"
+
+#: main.c:2235
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\t÷¦ÄͦÎÉÔÉ ÒŤÓÔÒÁæÀ ÃØÏÇÏ gvim ÞÅÒÅÚ OLE"
+
+#: main.c:2238
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\t÷ÉËÏÎÁÔÉ ×ÉËÏÒÉÓÔÏ×ÕÀÞÉ GUI (ΦÂÉ \"gvim\")"
+
+#: main.c:2239
+msgid "-f\t\t\tForeground: Don't fork when starting GUI"
+msgstr "-f\t\t\tîÅ ÚÁÌÉÛÁÔÉ ÔÅÒͦÎÁÌ Ð¦ÓÌÑ ÚÁÐÕÓËÕ GUI"
+
+#: main.c:2241
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tòÅÖÉÍ Vi (ΦÂÉ \"vi\")"
+
+#: main.c:2242
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tòÅÖÉÍ Ex (ΦÂÉ \"ex\")"
+
+#: main.c:2243
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tðÒÁÃÀ×ÁÔÉ ÍÏ×ÞËÉ (ÌÉÛÅ ÄÌÑ \"ex\")"
+
+#: main.c:2245
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tòÅÖÉÍ diff (ΦÂÉ \"vimdiff\")"
+
+#: main.c:2247
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tðÒÏÓÔÉÊ ÒÅÖÉÍ (ΦÂÉ \"evim\")"
+
+#: main.c:2248
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tòÅÖÉÍ ÐÅÒÅÇÌÑÄÕ (ΦÂÉ \"view\")"
+
+#: main.c:2249
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\túÁÂÏÒÏÎÅÎÉÊ ÒÅÖÉÍ (ΦÂÉ \"rvim\")"
+
+#: main.c:2250
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\túͦÎÉ (ÚÁÐÉÓ ÆÁÊ̦×) ÎÅ ÄÏÚ×ÏÌÅÎÏ"
+
+#: main.c:2251
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\túͦÎÉ × ÔÅËÓÔ¦ ÆÁÊÌ¦× ÎÅ ÄÏÚ×ÏÌÅÎÏ"
+
+#: main.c:2252
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\täצÊËÏ×ÉÊ ÒÅÖÉÍ"
+
+#: main.c:2254
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tòÅÖÍÉ lisp"
+
+#: main.c:2256
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\tòÅÖÉÍ, ÓÕͦÓÎÉÊ Ú Vi: 'compatible'"
+
+#: main.c:2257
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\tîÅ ÚÏ×Ó¦Í ÓÕͦÓÎÉÊ Ú Vi ÒÅÖÉÍ: 'nocompatible'"
+
+#: main.c:2258
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tò¦×ÅÎØ ÇÁÌÁÓÌÉ×ÏÓÔ¦"
+
+#: main.c:2259
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tòÅÖÉÍ ÎÁÌÁÇÏÄÖÕ×ÁÎÎÑ"
+
+#: main.c:2260
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tîÅ ËÏÒÉÓÔÕ×ÁÔÉÓÑ ÆÁÊÌÏÍ ÏÂͦÎÕ, ÔÒÉÍÁÔÉ ÕÓÅ × ÐÁÍ'ÑÔ¦"
+
+#: main.c:2261
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tðÏËÁÚÁÔÉ ÆÁÊÌÉ ÏÂͦÎÕ ¦ ×ÉÊÔÉ"
+
+#: main.c:2262
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (¦ÍÑ ÆÁÊÌÁ)\t÷¦ÄÎÏ×ÉÔÉ Á×ÁÒ¦ÊÎÏ ÚÁ˦ÎÞÅÎÉÊ ÓÅÁÎÓ"
+
+#: main.c:2263
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tôÅ ÓÁÍÅ ÝÏ Ê -r"
+
+#: main.c:2265
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tñ ÔÁË ÒÏÚÕͦÀ ÃÅ ÌÉÛÅ ÄÌÑ Amiga. ÷ÉÂÁÞ, Bram."
+
+#: main.c:2266
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <ÐÒÉÓÔÒ¦Ê>\t\t\t÷ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÐÒÉÓÔÒ¦Ê ÄÌÑ ××ÏÄÕ/×É×ÏÄÕ"
+
+#: main.c:2269
+msgid "-H\t\t\tstart in Hebrew mode"
+msgstr "-H\t\t\tòÏÚÐÏÞÁÔÉ ÒÅÖÉͦ Hebrew"
+
+#: main.c:2272
+msgid "-F\t\t\tstart in Farsi mode"
+msgstr "-F\t\t\tòÏÚÐÏÞÁÔÉ × ÐÅÒÓØËÏÍÕ ÒÅÖÉͦ"
+
+#: main.c:2274
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <ÔÅÒͦÎÁÌ>\t÷ÉÚÎÉÞÉÔÉ ÔÉÐ ÔÅÒͦÎÁÌÕ"
+
+#: main.c:2275
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\t÷ÉËÏÒÉÓÔÁÔÉ ÐÏÄÁÎÉÊ ÆÁÊÌ ÑË .vimrc"
+
+#: main.c:2277
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-u <gvimrc>\t\t÷ÉËÏÒÉÓÔÁÔÉ ÐÏÄÁÎÉÊ ÆÁÊÌ ÑË .gvimrc"
+
+#: main.c:2279
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tîÅ ×ÁÎÔÁÖÉÔÉ ÆÁÊÌÉ-ÄÏÐÏ×ÎÅÎÎÑ"
+
+#: main.c:2280
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr ""
+"-o[N]\t\tòÏÚËÒÉÔÉ N צËÏÎ (ÑËÝÏ ÎÅ ×ËÁÚÁÎÏ -- ÐÏ\n"
+"\t\t\tÏÄÎÏÍÕ ÄÌÑ ËÏÖÎÏÇÏ ÆÁÊÌÁ)"
+
+#: main.c:2281
+msgid "-O[N]\t\tlike -o but split vertically"
+msgstr "-O[N]\t\tΦÂÉ -o, ÁÌÅ ÐÏĦÌÉÔÉ ×¦ËÎÁ ×ÅÒÔÉËÁÌØÎÏ"
+
+#: main.c:2282
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tòÏÚÐÏÞÁÔÉ × Ë¦Îæ ÆÁÊÌÁ"
+
+#: main.c:2283
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<ÒÑÄÏË>\t\tòÏÚÐÏÞÁÔÉ ÎÁ ×ËÁÚÁÎÏÍÕ ÒÑÄËÕ"
+
+#: main.c:2285
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr ""
+"--cmd <ËÏÍÁÎÄÁ>\t÷ÉËÏÎÁÔÉ ËÏÍÁÎÄÕ ÐÅÒÅÄ ×ÉËÏÎÁÎÎÑÍ ÂÕÄØ-ÑËÉÈ .*rc ÆÁÊ̦×"
+
+#: main.c:2287
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <ËÏÍÁÎÄÁ>\t\t÷ÉËÏÎÁÔÉ ËÏÍÁÎÄÕ Ð¦ÓÌÑ ÚÁ×ÁÎÔÁÖÅÎÎÑ ÐÅÒÛÏÇÏ ÆÁÊÌÁ"
+
+#: main.c:2288
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <ÓÅÁÎÓ>\t\t÷ÉËÏÎÁÔÉ ÐÏÄÁÎÉÊ ÆÁÊÌ Ð¦ÓÌÑ ÐÅÒÛÏÇÏ ÚÁ×ÁÎÔÁÖÅÎÏÇÏ ÆÁÊÌÁ"
+
+#: main.c:2289
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <ÆÁÊÌ>\t\túÞÉÔÁÔÉ ËÏÍÁÎÄÉ Ú ÆÁÊÌÁ <scriptin>"
+
+#: main.c:2290
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <ÆÁÊÌ>\t\täÏÐÉÓÁÔÉ ÕÓ¦ ÎÁÂÒÁΦ ËÏÍÁÎÄÉ ÄÏ ÐÏÄÁÎÏÇÏ ÆÁÊÌÁ"
+
+#: main.c:2291
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-w <ÆÁÊÌ>\t\túÁÐÉÓÁÔÉ ÕÓ¦ ÎÁÂÒÁΦ ËÏÍÁÎÄÉ Õ ÐÏÄÁÎÉÊ ÆÁÊÌ"
+
+#: main.c:2293
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\tòÅÄÁÇÕ×ÁÔÉ ÚÁÛÉÆÒÏ×ÁÎÉÊ ÆÁÊÌ"
+
+#: main.c:2297
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <ÄÉÓÐÌÅÊ>\t÷ÉËÏÎÁÔÉ vim ×ÉËÏÒÉÓÔÏ×ÕÀÞÉ ÐÏÄÁÎÉÊ ÄÉÓÐÌÅÊ"
+
+#: main.c:2299
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tîÅ Ú'¤ÄÎÕ×ÁÔÉÓÑ Ú X ÓÅÒ×ÅÒÏÍ"
+
+#: main.c:2301
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\t÷¦ÄËÔÉÒÉ Vim × ¦ÎÛÏÍÕ ÅÌÅÍÅÎÔ¦ ¦ÎÔÅÒÆÅÊÓÕ GTK"
+
+#: main.c:2305
+msgid "--remote <files>\tEdit <files> in a Vim server and exit"
+msgstr "--remote <ÆÁÊÌÉ>\tòÅÄÁÇÕ×ÁÔÉ ÆÁÊÌÉ ÎÁ Vim ÓÅÒ×ÅÒ¦ ¦ ÚÁ×ÅÒÛÉÔÉ ÒÏÂÏÔÕ"
+
+#: main.c:2306
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr ""
+"--remote-wait <ÆÁÊÌÉ> ..., ÁÌÅ ÚÁÞÅËÁÔÉ ÐÏËÉ ÕÓ¦ ÆÁÊÌÉ ÂÕÄŠצÄÒÅÄÁÇÏ×ÁÎÏ"
+
+#: main.c:2307
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <ÓÉÍ×ÏÌÉ> ÷¦Ä¦ÓÌÁÔÉ <ÓÉÍ×ÏÌÉ> ÓÅÒ×ÅÒÕ ¦ ÚÁ×ÅÒÛÉÔÉ ÒÏÂÏÔÕ"
+
+#: main.c:2308
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr ""
+"--remote-expr <×ÉÒÁÚ> ÷ÉËÏÎÁÔÉ ×ÉÒÁÚ ÎÁ ÓÅÒ×ÅÒ¦, ¦ ÎÁÄÒÕËÕ×ÁÔÉ ÒÅÚÕÌØÔÁÔ"
+
+#: main.c:2309
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr ""
+"--serverlist\t\tðÏËÁÚÁÔÉ ÓÐÉÓÏË ÎÁÑ×ÎÉÈ ÓÅÒ×ÅÒ¦× Vim ¦ ÚÁ×ÅÒÛÉÔÉ ÒÏÂÏÔÕ"
+
+#: main.c:2310
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <¦Í'Ñ>\tóЦÌËÕ×ÁÔÉÓÑ Ú/ÓÔÁÔÉ Vim ÓÅÒ×ÅÒÏÍ Ú ÐÏÄÁÎÉÍ ¦Í'ÑÍ"
+
+#: main.c:2313
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\t÷ÉËÏÒÉÓÔÁÔÉ ÐÏÄÁÎÉÊ ÆÁÊÌ ÑË .viminfo"
+
+#: main.c:2315
+msgid "-h\t\t\tprint Help (this message) and exit"
+msgstr "-h\t\t\tîÁÄÒÕËÕ×ÁÔÉ ÃÅ ÐÏצÄÏÍÌÅÎÎÑ, ¦ ×ÉÊÔÉ"
+
+#: main.c:2316
+msgid "--version\t\tprint version information and exit"
+msgstr "--version\t\tÎÁÄÒÕËÕ×ÁÔÉ ¦ÎÆÏÒÍÁæÀ ÐÒÏ ×ÅÒÓ¦À ÐÒÏÇÒÁÍÉ"
+
+#: main.c:2320
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"áÒÇÕÍÅÎÔÉ ÄÌÑ gvim (×ÅÒÓ¦Ñ Motif)\n"
+
+#: main.c:2323
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"áÒÇÕÍÅÎÔÉ ÄÌÑ gvim (×ÅÒÓ¦Ñ Athena)\n"
+
+#: main.c:2326
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <ÄÉÓÐÌÅÊ>\t÷ÉËÏÎÁÔÉ vim ×ÉËÏÒÉÓÔÏ×ÕÀÞÉ ÐÏÄÁÎÉÊ ÄÉÓÐÌÅÊ"
+
+#: main.c:2327
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\túÁÐÉÓÔÉÔÉ Vim"
+
+#: main.c:2329
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <¦Í'Ñ>\t\t÷ÉËÏÒÉÓÔÁÔÉ ÒÅÓÕÒÓÉ ÄÌÑ <¦Í`Ñ>"
+
+#: main.c:2330
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (îŠĦ¤)\n"
+
+#: main.c:2332
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <ËÏ̦Ò>\t÷ÉËÏÒÉÓÔÁÔÉ <ËÏ̦Ò> ÄÌÑ ÆÏÎÕ (ÔÁËÏÖ: -bg)"
+
+#: main.c:2333
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr ""
+"-foreground <ËÏ̦Ò>\t÷ÉËÏÒÉÓÔÁÔÉ <ËÏ̦Ò> ÄÌÑ Ú×ÉÞÁÊÎÏÇÏ ÔÅËÓÔÕ (ÔÁËÏÖ: -fg)"
+
+#: main.c:2334 main.c:2354
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <ÛÒÉÆÔ>\t÷ÉËÏÒÉÓÔÁÔÉ <ÛÒÉÆÔ> ÄÌÑ Ú×ÉÞÁÊÎÏÇÏ ÔÅËÓÔÕ (ÔÁËÏÖ: -fn)"
+
+#: main.c:2335
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <ÛÒÉÆÔ>\t÷ÉËÏÒÉÓÔÁÔÉ <ÛÒÉÆÔ> ÄÌÑ ÖÉÒÎÏÇÏ ÔÅËÓÔÕ"
+
+#: main.c:2336
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <ÛÒÉÆÔ>\t÷ÉËÏÒÉÓÔÁÔÉ <ÛÒÉÆÔ> ÄÌÑ ÐÏÈÉÌÏÇÏ ÔÅËÓÔÕ"
+
+#: main.c:2337 main.c:2355
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <ÇÅÏÍ>\túÁÄÁÔÉ ÒÏÚͦÔÉ ÔÁ ÐÏÌÏÖÅÎÎÑ (ÔÁËÏÖ: -geom)"
+
+#: main.c:2338
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <ÔÏ×Ý>\t÷ÓÔÁÎÏ×ÉÔÉ ÔÏ×ÝÉÎÕ ÍÅÖ <ÔÏ×Ý> (ÔÁËÏÖ: -bw)"
+
+#: main.c:2339
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <ÔÏ×Ý> ÷ÓÔÁÎÏ×ÉÔÉ ÔÏ×ÝÉÎÕ Ì¦Î¦ÊËÉ ÚÓÕ×Õ (ÔÁËÏÖ: -sw)"
+
+#: main.c:2341
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <×ÉÓÏÔÁ>\t÷ÓÔÁÎÏ×ÉÔÉ ×ÉÓÏÔÕ ÍÅÎÀ <×ÉÓÏÔÁ> (ÔÁËÏÖ: -mh)"
+
+#: main.c:2343 main.c:2356
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tïÂÅÒÎÕÔÉ ËÏÌØÏÒÉ (ÔÁËÏÖ: -rv)"
+
+#: main.c:2344
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tîÅ ÏÂÅÒÔÁÔÉ ËÏÌØÏÒÉ (ÔÁËÏÖ: +rv)"
+
+#: main.c:2345
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <ÒÅÓÕÒÓ>\t÷ÓÔÁÎÏ×ÉÔÉ ×¦ÄÐÏצÄÎÉÊ ÒÅÓÕÒÓ"
+
+#: main.c:2348
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"áÒÛÕÍÅÎÔÉ ÄÏ gvim (×ÅÒÓ¦Ñ RISC OS):\n"
+
+#: main.c:2349
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <˦ÌØ˦ÓÔØ>\tðÏÞÁÔËÏ×Á ÛÉÒÉÎÁ צËÎÁ × ÓÉÍ×ÏÌÁÈ"
+
+#: main.c:2350
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <˦ÌØ˦ÓÔØ>\tðÏÞÁËÏ×Á ×ÉÓÏÔÁ צËÎÁ × ÒÑÄËÁÈ"
+
+#: main.c:2353
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"áÒÇÕÍÅÎÔÉ ÄÌÑ gvim (×ÅÒÓ¦Ñ GTK+)\n"
+
+#: main.c:2357
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr ""
+"-display <ÄÉÓÐÌÅÊ>\t÷ÉËÏÎÁÔÉ vim ÎÁ ÐÏÄÁÎÏÍÕ ÄÉÓÐÌŧ (ÔÁËÏÖ: --display)"
+
+#: main.c:2359
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tðÏËÁÚÁÔÉ ÁÒÇÕÍÅÎÔÉ Gnome"
+
+#. Failed to send, abort.
+#: main.c:2584
+msgid ""
+"\n"
+"Send failed.\n"
+msgstr ""
+"\n"
+"óÐÒÏÂÁ צĦÓÌÁÔÉ ×ÉÒÁÚ ÎÅ ×ÄÁÌÁÓÑ.\n"
+
+#. Let vim start normally.
+#: main.c:2589
+msgid ""
+"\n"
+"Send failed. Trying to execute locally\n"
+msgstr ""
+"\n"
+"îÅ ×ÄÁÌÏÓÑ ×¦Ä¦ÓÌÁÔÉ ÄÁΦ. óÐÒÏÂÕ¤ÍÏ ×ÉËÏÎÁÔÉ ÎÁ ͦÓæ\n"
+
+#: main.c:2622 main.c:2643
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d Ú %d ÆÁÊÌ¦× ×¦ÄÒÅÄÁÇÏ×ÁÎÏ"
+
+#: main.c:2666
+msgid "Send expression failed.\n"
+msgstr "óÐÒÏÂÁ צĦÓÌÁÔÉ ×ÉÒÁÚ ÎÅ ×ÄÁÌÁÓÑ.\n"
+
+#: mark.c:660
+msgid "No marks set"
+msgstr "öÏÄÎÉÈ ÐÏͦÔÏË ÎÅ ÂÕÌÏ ×ËÁÚÁÎÏ"
+
+#: mark.c:662
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: ðÏͦÔËÕ \"%s\" ÎÅ ÚÎÁÊÄÅÎÏ"
+
+# msgstr "E283: "
+#. Highlight title
+#: mark.c:673
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"ÐÏÍ. ÒÑÄ. ËÏÌ. ÆÁÊÌ/ÔÅËÓÔ"
+
+#. Highlight title
+#: mark.c:711
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+
+# TODO
+#: mark.c:1073
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# ðÏͦÔËÉ:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1108
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# óÐÉÓÏË ÐÅÒÅÈÏĦ×\n"
+
+# TODO
+#: mark.c:1203
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# ðÏÐÅÒÅÄΦ ÐÏͦÔËÉ × ÆÁÊÌÁÈ (ÓÐÏÞÁÔËÕ ÎÏצ):\n"
+
+#: mark.c:1286
+msgid "Missing '>'"
+msgstr "÷ÔÒÁÞÅÎÏ '>'"
+
+#: mbyte.c:395
+msgid "Not a valid codepage"
+msgstr "ëÏÄÏ×Á ÓÔÏÒ¦ÎËÁ ÎÅ ¦ÓÎÕ¤"
+
+#: mbyte.c:3029
+msgid "E284: Cannot set IC values"
+msgstr "E284: îÅ ÍÏÖÕ ×ÓÔÁÎÏ×ÉÔÉ ÚÎÁÞÅÎÎÑ IC"
+
+#: mbyte.c:3181
+msgid "E285: Failed to create input context"
+msgstr "E285: ðÏÍÉÌËÁ Ð¦Ä ÞÁÓ ÓÔ×ÏÒÅÎÎÑ `input context'"
+
+#: mbyte.c:3328
+msgid "E286: Failed to open input method"
+msgstr "E286: ðÏÍÉÌËÁ Ð¦Ä ÞÁÓ ÓÔ×ÏÒÅÎÎÑ `input method'"
+
+# msgstr "E286: "
+#: mbyte.c:3339
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: õ×ÁÇÁ: ÎÅ ÍÏÖÕ ×ÓÔÁÎÏ×ÉÔÉ ÐÏĦÀ ÄÌÑ ÚÎÉÝÅÎÎÑ IM"
+
+# msgstr "E287: "
+#: mbyte.c:3345
+msgid "E288: input method doesn't support any style"
+msgstr "E288: `input method' ΊЦÄÔÒÉÍÕ¤ ÓÔÉ̦"
+
+# msgstr "E288: "
+#: mbyte.c:3402
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: `input method' ΊЦÄÔÒÉÍÕ¤ ÒÅÄÁÇÏ×ÁΦ ÔÉÐÉ"
+
+# msgstr "E289: "
+#: mbyte.c:3476
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: ÓÔÉÌØ ×ÉÍÁÇÁ¤ fontset"
+
+# msgstr "E290: "
+#: mbyte.c:3504
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: ÷ÅÒÓ¦Ñ Â¦Â̦ÏÔÅËÉ GTK+ ÍÅÎÛÁ ÚÁ 1.2.3. `Status area' ×ÉÍËÎÕÔÏ"
+
+# msgstr "E291: "
+#: mbyte.c:3741
+msgid "E292: Input Method Server is not running"
+msgstr "E292: IM ÓÅÒ×ÅÒ ÎÅ ÆÕÎËæÏÎÕ¤"
+
+# msgstr "E292: "
+#: memfile.c:473
+msgid "E293: block was not locked"
+msgstr "E293: ÂÌÏË ÎÅ ÂÕÌÏ ÚÁƦËÓÏ×ÁÎÏ"
+
+# msgstr "E293: "
+#: memfile.c:972
+msgid "E294: Seek error in swap file read"
+msgstr "E294: ðÏÍÉÌËÁ ÚͦÎÉ ÐÏÚ¦ÃÉÉ Õ ÆÁÊ̦ ÏÂͦÎÕ"
+
+#: memfile.c:977
+msgid "E295: Read error in swap file"
+msgstr "E295: ðÏÍÉÌËÁ ÚÞÉÔÕ×ÁÎÎÑ ÆÁÊÌÁ ÏÂͦÎÕ"
+
+#: memfile.c:1029
+msgid "E296: Seek error in swap file write"
+msgstr "E296: ðÏÍÉÌËÁ ÚͦÎÉ ÐÏÚ¦ÃÉÉ Ð¦Ä ÞÁÓ ÚÁÐÉÓÕ ÆÁÊÌÁ ÏÂͦÎÕ"
+
+#: memfile.c:1047
+msgid "E297: Write error in swap file"
+msgstr "E297: ðÏÍÉÌËÁ ÚÁÐÉÓÕ ÆÁÊÌÁ ÏÂͦÎÕ"
+
+#: memfile.c:1244
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: æÁÊÌ ÏÂͦÎÕ ÕÖÅ ¦ÓÎÕ¤! (ÚÌÏ×ÍÉÓÎÉË??)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: îÅÍÁ¤ ÂÌÏËÕ 0? [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: îÅÍÁ¤ ÂÌÏËÕ 1? [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+# msgstr "E298: "
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: îÅÍÁ¤ ÂÌÏËÕ 2? [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: æÁÊÌ ÏÂͦÎÕ ×ÔÒÁÞÅÎÏ!!!"
+
+# msgstr "E301: "
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: îÅ ÍÏÖÕ ÐÅÒÅÊÍÅÎÕ×ÁÔÉ ÆÁÊÌÁ ÏÂͦÎÕ"
+
+# msgstr "E302: "
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: ÎÅ ÍÏÖÕ ÐÒÏÞÉÔÁÔÉ ÆÁÊÌ ÏÂͦÎÕ ÄÌÑ \"%s\", צÄÎÏ×ÌÅÎÎÑ ÎÅÍÏÖÌÉ×Å"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: îÅÍÁ¤ ÂÌÏËÕ 0?? [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: îÅ ÚÎÁÊÄÅÎÏ ÆÁÊÌÕ ÏÂͦÎÕ ÄÌÑ %s"
+
+# msgstr "E305: "
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "ñËÉÊ ÓÁÍÅ ÆÁÊÌ ÏÂͦÎÕ ×ÉËÏÒÉÓÔÁÔÉ (0 ÄÌÑ ×ÉÈÏÄÕ):"
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "îÅ ÍÏÖÕ ÚÞÉÔÁÔÉ ÂÌÏË 0 Ú "
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"îÁÐÅ×ÎÏ ÚͦΠÎÅ ÂÕÌÏ, ÁÂÏ Vim ÎÅ ÐÏÎÏ×É× ÆÁÊÌ ÏÂͦÎÕ."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " ÎÅÐÒÉÄÁÔÎÉÊ ÄÌÑ ×ÉËÏÒÉÓÔÁÎÎÑ Ú Ã¦¤À ×ÅÒÓ¦¤À Vim.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "úÎÁÊĦÔØ Vim 3.0\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s ÎÅ ÓÈÏÖÅ ÎÁ ÆÁÊÌ ÏÂͦÎÕ Vim"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " ÎÅÐÒÉÄÁÔÎÉÊ ÄÏ ×ÉËÏÒÉÓÔÁÎÎÑ ÎÁ ×ÁÛ¦Ê ÁÒȦÔÅËÔÕÒ¦.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "æÁÊÌ ÂÕÌÏ ÓÔ×ÏÒÅÎÏ ÎÁ "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"ÁÂÏ ÆÁÊÌ ÂÕÌÏ ÐÏÛËÏÄÖÅÎÏ."
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "÷ÉËÕÒÏÓÔÏ×À ÆÁÊÌ ÏÂͦÎÕ \"%s\""
+
+#: memline.c:915
+#, c-format
+msgid "Original file \"%s\""
+msgstr "ðÏÞÁÔËÏ×ÉÊ ÆÁÊÌ \"%s\""
+
+#: memline.c:934
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: õ×ÁÇÁ: íÏÖÌÉ×Ï, ÐÏÞÁÔËÏ×ÉÊ ÆÁÊÌ ÂÕÌÏ ÚͦÎÅÎÏ"
+
+# msgstr "E308: "
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: îÅ ÍÏÄÕ ÚÞÉÔÁÔÉ ÂÌÏË 1 Ú %s"
+
+# msgstr "E309: "
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "??? âÁÇÁÔÏ ÒÑÄË¦× ×ÔÒÁÞÅÎÏ"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "??? îÅצÒÎÁ ˦ÌØ˦ÓÔØ ÒÑÄ˦×"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "??? ðÏÒÏÖÎ¦Ê ÂÌÏË"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "??? òÑÄËÉ ×ÔÒÁÞÅÎÏ"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: éÄÅÎÔÉƦËÁÔÏÒ ÂÌÏËÕ 1 ÎÅצÒÎÉÊ (ÍÏÖÌÉ×Ï %s ÎÅ ÆÁÊÌ ÏÂͦÎÕ?)"
+
+# msgstr "E310: "
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "??? âÌÏË ×ÔÒÁÞÅÎÏ"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? ÷¦Ä ÃØÏÇÏ ÒÑÄËÁ ¦ ÄÏ `??? ë¦ÎÅÃØ' ÒÑÄËÉ ÍÏÖÕÔØ ÂÕÔÉ ÓÐÌÕÔÁΦ"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr ""
+"??? ÷¦Ä ÃØÏÇÏ ÒÑÄËÁ ¦ ÄÏ `??? ë¦ÎÅÃØ' ÒÑÄËÉ ÍÏÖÕÔØ ÂÕÔÉ ÄÏÄÁΦ/×ÔÒÁÞÅΦ"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "??? ë¦ÎÅÃØ"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: ÷¦ÄÎÏ×ÌÅÎÎÑ ÐÅÒÅÒ×ÁÎÏ"
+
+#: memline.c:1145
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr ""
+"E312: ð¦Ä ÞÁÓ ×¦ÄÎÏ×ÌÅÎÎÑ ÚÎÁÊÄÅÎ ÐÏÍÉÌËÉ.. ðÉÌØÎÕÊÔÅ ÒÑÄËÉ ÝÏ ÐÏÞÉÎÁÀÉÔØÓÑ "
+"Ú `???'"
+
+#: memline.c:1148
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "÷¦ÄÎÏ×ÌÅÎÎÑ ÚÁ˦ÎÞÅÎÏ, ÐÅÒÅצÒÔÅ ÞÉ ×ÓÅ ÐÒÁ×ÉÌØÎÏ."
+
+#: memline.c:1149
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(ñËÝÏ ÂÁÖÁ¤ÔÅ, ÍÏÖÅÔÅ ÚÁÐÁÍ'ÑÔÁÔÉ ÃÅÊ ÆÁÊÌ Ú ¦ÎÛÉÍ ¦ÍÅÎÅÍ\n"
+
+#: memline.c:1150
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "¦, ÐÏÒ¦×Ñ×ÛÉ Ú ÏÒÉǦÎÉÌÏÍ, ÐÅÒÅצÒÔÅ ÚͦÎÉ)\n"
+
+#: memline.c:1151
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"ð¦ÓÌÑ ÃØÏÇÏ, ×ÉÄÁ̦ÔØ ÆÁÊÌ ÏÂͦÎÕ.\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1207
+msgid "Swap files found:"
+msgstr "úÎÁÊÄÅÎÏ ÆÁÊÌÉ ÏÂͦÎÕ:"
+
+#: memline.c:1385
+msgid " In current directory:\n"
+msgstr " ÷ ÐÏÔÏÞÎ¦Ê ÄÉÒÅËÔÏÒ¦§:\n"
+
+#: memline.c:1387
+msgid " Using specified name:\n"
+msgstr " ÷ÉËÏÒÉÓÔÏ×ÕÀÖÉ ×ËÁÚÁÎÕ ÎÁÚ×Õ:\n"
+
+#: memline.c:1391
+msgid " In directory "
+msgstr " õ ÄÉÒÅËÔÏÒ¦§ "
+
+#: memline.c:1409
+msgid " -- none --\n"
+msgstr " -- ÖÏÄÎÏÇÏ --\n"
+
+#: memline.c:1481
+msgid " owned by: "
+msgstr " ×ÌÁÓÎÉË: "
+
+#: memline.c:1483
+msgid " dated: "
+msgstr " ÄÁÔÏ×ÁÎÏ: "
+
+#: memline.c:1487 memline.c:3680
+msgid " dated: "
+msgstr " ÄÁÔÏ×ÁÎÏ: "
+
+#: memline.c:1503
+msgid " [from Vim version 3.0]"
+msgstr " [×¦Ä Vim 3.0]"
+
+#: memline.c:1507
+msgid " [does not look like a Vim swap file]"
+msgstr " [ÎÅ ÓÈÏÖÅ ÎÁ ÆÁÊÌ ÏÂͦÎÕ]"
+
+#: memline.c:1511
+msgid " file name: "
+msgstr " ÎÁÚ×Á ÆÁÊÌÁ: "
+
+#: memline.c:1523
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" ÚͦÎÅÎÏ: "
+
+#: memline.c:1524
+msgid "YES"
+msgstr "ôáë"
+
+#: memline.c:1524
+msgid "no"
+msgstr "Φ"
+
+#: memline.c:1528
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" ¦Í'Ñ ËÏÒÉÓÔÕ×ÁÞÁ: "
+
+#: memline.c:1535
+msgid " host name: "
+msgstr " ÎÁÚ×Á ÓÉÓÔÅÍÉ: "
+
+#: memline.c:1537
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" ÎÁÚ×Á ÓÉÓÔÅÍÉ: "
+
+#: memline.c:1543
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ÎÏÍÅÒ ÐÒÏÃÅÓÕ: "
+
+#: memline.c:1549
+msgid " (still running)"
+msgstr " (ÕÓÅ ÝÅ ×ÉËÏÎÕ¤ÔØÓÑ)"
+
+#: memline.c:1561
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [îÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÏ Ú Ã¦¤À ×ÅÒÓ¦¤À Vim]"
+
+#: memline.c:1564
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [ÎÅÐÒÉÄÁÔÎÉÊ ÄÏ ×ÉËÏÒÉÓÔÁÎÎÑ ÎÁ ×ÁÛ¦Ê ÁÒȦÔÅËÔÕÒ¦]"
+
+#: memline.c:1569
+msgid " [cannot be read]"
+msgstr " [ÎÅ ÍÏÖŠ¦ÔØ ÐÒÏÞÉÔÁÎÉÊ]"
+
+#: memline.c:1573
+msgid " [cannot be opened]"
+msgstr " [ÎÅ ÍÏÖÅ ÂÕÔÉ ×¦ÄËÒÉÔÉÊ]"
+
+#: memline.c:1763
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: îÅ ÍÏÖÕ ÚÂÅÒ¦ÇÔÉ, ÎÅÍÁ¤ ÆÁÊÌÁ ÏÂͦÎÕ"
+
+# msgstr "E313: "
+#: memline.c:1816
+msgid "File preserved"
+msgstr "æÁÊÌ ÚÂÅÒÅÖÅÎÏ"
+
+#: memline.c:1818
+msgid "E314: Preserve failed"
+msgstr "E314: úÂÅÒÅÖÅÎÎÑ ÎÅ ×ÄÁÌÏÓÑ"
+
+# msgstr "E314: "
+#: memline.c:1889
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: ÎÅצÒÎÉÊ lnum: %ld [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+# msgstr "E315: "
+#: memline.c:1915
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: ÒÑÄÏË %ld ÎÅ ÚÎÁÊÄÅÎÏ [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+# msgstr "E316: "
+#: memline.c:2303
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: ×ËÁÚ¦×ÎÉË ÂÌÏËÕ ÐÏÍÉÌËÏ×ÉÊ (3) [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+# msgstr "E317: "
+#: memline.c:2383
+msgid "stack_idx should be 0"
+msgstr "stack_idx ÍÁ¤ ÂÕÔÉ Ò¦×ÎÉÍ 0 [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#: memline.c:2445
+msgid "E318: Updated too many blocks?"
+msgstr "E318: úÁÂÁÇÁÔÏ ÂÌÏË¦× ÐÏÎÏ×ÌÅÎÏ? [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#: memline.c:2602
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: ×ËÁÚ¦×ÎÉË ÂÌÏËÕ ÐÏÍÉÌËÏ×ÉÊ (4) [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#: memline.c:2629
+msgid "deleted block 1?"
+msgstr "ÂÌÏË 1 ×ÉÄÁÌÅÎÏ? [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#: memline.c:2829
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÒÑÄÏË %ld [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#: memline.c:3072
+msgid "E317: pointer block id wrong"
+msgstr "E317: ×ËÁÚ¦×ÎÉË ÂÌÏËÕ ÐÏÍÉÌËÏ×ÉÊ [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+# msgstr "E317: "
+#: memline.c:3088
+msgid "pe_line_count is zero"
+msgstr "pe_line_count Ò¦×ÅÎ 0 [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#: memline.c:3117
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: ÎÏÍÅÒ ÒÑÄËÁ ×ÉÊÛÏ× ÚÁ ÍÅÖ¦: %ld [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+# msgstr "E322: "
+#: memline.c:3121
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: ë¦ÌØ˦ÓÔØ ÒÑÄË¦× Õ ÂÌÏæ %ld ÐÏÍÉÌËÏ×Á"
+
+# msgstr "E323: "
+#: memline.c:3170
+msgid "Stack size increases"
+msgstr "òÏÚÍ¦Ò ÓÔÅËÕ Ú¦ÌØÛÕ¤ÔØÓÑ"
+
+#: memline.c:3216
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: ×ËÁÚ¦×ÎÉË ÂÌÏËÕ ÐÏÍÉÌËÏ×ÉÊ (2) [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+# msgstr "E317: "
+#: memline.c:3670
+msgid "E325: ATTENTION"
+msgstr "E325: õ÷áçá"
+
+#: memline.c:3671
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"úÎÁÊÄÅÎÏ ÆÁÊÌ ÏÂͦÎÕ ÎÁ ¦Í'Ñ \""
+
+#: memline.c:3675
+msgid "While opening file \""
+msgstr "îÁÍÁÇÁÀÞÉÓØ ×¦ÄËÒÉÔÉ ÆÁÊÌ \""
+
+#: memline.c:3684
+msgid " NEWER than swap file!\n"
+msgstr " ðÏÞÁÔËÏÉÊ ÆÁÊÌ ÎÏצÝÉÊ ÚÁ ÆÁÊÌ ÏÂͦÎÕ\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3688
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) íÏÖÌÉ×Ï, ¦ÎÛÉÊ Vim ÕÖÅ ÒÅÄÁÇÕ¤ ÃÅÊ ÆÁÊÌ. âÕÄØÔÅ ÏÂÅÒÅÖΦ,\n"
+" ×É ÍÏÖÅÔÅ ÚÁÌÉÛ¦ÔØÓÑ Ú Ä×ÏÍÁ Ò¦ÚÎÉÍÉ ×ÅÒÓ¦ÑÍÉ ÆÁÊÌÕ.\n"
+
+#: memline.c:3689
+msgid " Quit, or continue with caution.\n"
+msgstr " ÷ÉÊĦÔØ, ÁÂÏ ÐÒÏÄÏ×ÖÕÊÔÅ Ú ÏÂÅÒÅÖΦÓÔÀ.\n"
+
+#: memline.c:3690
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) ðÏÐÅÒÅÄÎ¦Ê ÓÅÁÎÓ ÒÅÄÁÇÕ×ÁÎÎÑ Á×ÁÒ¦ÊÎÏ ÚÁ×ÅÒÛÉ×ÓÑ.\n"
+
+#: memline.c:3691
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " ÷ÉËÏÒÉÓÔÁÊÔÅ \":recover\" ÁÂÏ \"vim -r\" "
+
+#: memline.c:3693
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"ÄÌÑ\n"
+" צÄÎÏ×ÌÅÎÎÑ ÚͦÎ. (ÄÉ×. \":help recovery\").\n"
+
+#: memline.c:3694
+msgid " If you did this already, delete the swap file \""
+msgstr " ñËÝÏ ×É ÃÅ ×ÖÅ ÒÏÂÉÌÉ, ×ÉÄÁ̦ÔØ ÆÁÊÌ ÏÂͦÎÕ \""
+
+#: memline.c:3696
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" ÝÏ ÐÏÚÂÁ×ÉÔÉÓÑ ÃØÏÇÏ ÐÏצÄÏÍÌÅÎÎÑ.\n"
+"\n"
+
+#: memline.c:3710 memline.c:3714
+msgid "Swap file \""
+msgstr "æÁÊÌ ÏÂͦÎÕ \""
+
+#: memline.c:3711 memline.c:3717
+msgid "\" already exists!"
+msgstr "\" ÕÖÅ ¦ÓÎÕ¤!"
+
+#: memline.c:3720
+msgid "VIM - ATTENTION"
+msgstr "Vim -- õ×ÁÇÁ"
+
+#: memline.c:3722
+msgid "Swap file already exists!"
+msgstr "æÁÊÌ ÏÂͦÎÕ ÕÖÅ ¦ÓÎÕ¤!"
+
+#: memline.c:3726
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"&O:÷¦ÄËÒÉÔÉ ÌÉÛÅ ÄÌÑ ÞÉÔÁÎÎÑ\n"
+"&E:õÓÅ ÏÄÎÏ ÒÅÄÁÇÕ×ÁÔÉ\n"
+"&R:÷¦ÄÎÏ×ÉÔÉ\n"
+"&Q:÷ÉÊÔÉ"
+
+#: memline.c:3728
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"&O:÷¦ÄËÒÉÔÉ ÌÉÛÅ ÄÌÑ ÞÉÔÁÎÎÑ\n"
+"&E:õÓÅ ÏÄÎÏ ÒÅÄÁÇÕ×ÁÔÉ\n"
+"&R:÷¦ÄÎÏ×ÉÔÉ\n"
+"&Q:÷ÉÊÔÉ\n"
+"&D:÷ÉÄÁÌÉÔÉ ÃÅÊ ÆÁÊÌ"
+
+#: memline.c:3781
+msgid "E326: Too many swap files found"
+msgstr "E326: úÁÂÁÇÁÔÏ ÆÁÊÌ¦× ÏÂͦÎÕ ÚÎÁÊÄÅÎÏ"
+
+# msgstr "E326: "
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: ûÌÑÈÕ ÄÏ ÅÌÅÍÅÎÔÁ ÍÅÎÑ ÍÁ¤ ͦÓÔÉÔÉ ÌÉÛŠЦÄÍÅÎÀ"
+
+# msgstr "E327: "
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: íÅÎÀ ÎÅ ¦ÓÎÕ¤ Õ ×ËÁÚÁÎÉÈ ÒÅÖÉÍÁÈ"
+
+# msgstr "E328: "
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: îÅÍÁ¤ ÍÅÎÀ Ú ÔÁËÏÀ ÎÁÚ×ÏÀ"
+
+# msgstr "E329: "
+#: menu.c:503
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: ûÌÑÈ ÄÏ ÍÅÎÑ ÎÅ ÐÏ×ÉÎÅÎ ×ÅÓÔÉ ÄÏ Ð¦ÄÍÅÎÀ"
+
+# msgstr "E330: "
+#: menu.c:542
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: ÷¦ÄÍÏ×ÌÑÀÓØ ÄÏÄÁ×ÁÔÉ *ÅÌÅÍÅÎÔÉ* ÍÅÎÀ ÐÒÑÍÏ ÄÏ menubar"
+
+# msgstr "E331: "
+#: menu.c:548
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: òÏÚĦÌØÎÉË ÎÅ ÍÏÖÎÁ ÄÏÄÁ×ÁÔÉ × ÛÌÑÈ ÄÏ ÍÅÎÀ"
+
+# msgstr "E332: "
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1063
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- íÅÎÀ ---"
+
+#: menu.c:1989
+msgid "Tear off this menu"
+msgstr "÷¦Ä¦Ò×ÁÔÉ ÃÅ ÍÅÎÀ"
+
+#: menu.c:2054
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: ûÌÑÈ ÐÏ×ÉÎÅÎ ×ÅÓÔÉ ÄÏ ÅÌÅÍÅÎÔÁ ÍÅÎÀ"
+
+# msgstr "E333: "
+#: menu.c:2074
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: íÅÎÀ %s ÎÅ ÚÎÁÊÄÅÎÏ"
+
+# msgstr "E334: "
+#: menu.c:2143
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: ÷ ÒÅÖÉͦ `%s' ÍÅÎÀ ÎÅ ¦ÓÎÕ¤"
+
+# msgstr "E335: "
+#: menu.c:2181
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: ûÌÑÈ ÐÏ×ÉÎÅÎ ×ÅÓÔÉ ÄÏ Ð¦ÄÍÅÎÀ"
+
+# msgstr "E336: "
+#: menu.c:2202
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: íÅÎÀ ÎÅ ÚÎÁÊÄÅÎÏ -- ÐÅÒÅצÒÔÅ ÎÁÚ×Õ"
+
+# msgstr "E337: "
+#: message.c:467
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "ðÏÍÉÌËÁ Ð¦Ä ÞÁÓ ×ÉËÏÎÁÎÎÑ %s:"
+
+#: message.c:483
+#, c-format
+msgid "line %4ld:"
+msgstr "ÒÑÄÏË %4ld:"
+
+#: message.c:523
+msgid "[string too long]"
+msgstr "[ÒÑÄÏË ÚÁÎÁÄÎÏ ÄÏ×ÇÉÊ]"
+
+#: message.c:669
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "÷¦ÄÐÏצÄÁÌØÎÉÊ ÚÁ ÐÏצÄÏÍÌÅÎÎÑ: âÏÇÄÁÎ ÷ÌÁÓÀË <bodq@yahoo.com>"
+
+#: message.c:882
+msgid "Interrupt: "
+msgstr "ðÅÒÅÒ×ÁÎÏ: "
+
+#: message.c:885
+msgid "Hit ENTER to continue"
+msgstr "îÁÔÉÓΦÔØ ENTER ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ"
+
+#: message.c:887
+msgid "Hit ENTER or type command to continue"
+msgstr "îÁÔÉÓΦÔØ ENTER ÁÂÏ ×ËÁÖ¦ÔØ ËÏÍÁÎÄÕ ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ"
+
+#: message.c:1942
+msgid "-- More --"
+msgstr "-- ýÅ --"
+
+#: message.c:1945
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: ÒÑÄÏË, ðòïâ¶ì/b: ÌÉÓÔ, d/u: Ð¦× ÌÉÓÔÁ, q: ×ÉȦÄ)"
+
+#: message.c:1946
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: ÒÑÄÏË, ðòïâ¶ì: ÌÉÓÔ, d: Ð¦× ÌÉÓÔÁ, q: ×ÉȦÄ)"
+
+#: message.c:2421 message.c:2436
+msgid "Question"
+msgstr "úÁÐÉÔÁÎÎÑ"
+
+#: message.c:2423
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Y:ôÁË\n"
+"&N:î¦"
+
+#: message.c:2438
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Y:ôÁË\n"
+"&N:î¦\n"
+"&C:÷¦ÄͦÎÉÔÉ"
+
+#: message.c:2456
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Y:ôÁË\n"
+"&N:î¦\n"
+"&A:õÓ¦\n"
+"&D:öÏÄÎÏÇÏ\n"
+"&C:÷¦ÄͦÎÉÔÉ"
+
+#: message.c:2496
+msgid "Save File dialog"
+msgstr "úÁÐÁÍ'ÑÔÁÔÉ ÆÁÊÌ"
+
+#: message.c:2498
+msgid "Open File dialog"
+msgstr "÷¦ÄËÒÉÔÉ ÆÁÊÌ"
+
+#. TODO: non-GUI file selector here
+#: message.c:2549
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: ÷ÉÂÁÞÔÅ, ÁÌÅ × ËÏÎÓÏ̦ ÎÅÍÁ¤ ĦÁÌÏÇÕ ×ÉÂÏÒÕ ÆÁÊÌÁ"
+
+# msgstr "E338: "
+#: misc1.c:2455
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: õ×ÁÇÁ: úͦÎÀ¤ÔØÓÑ ÆÁÊÌ ÐÒÉÚÎÁÞÅÎÉÊ ÌÉÛÅ ÄÌÑ ÞÉÔÁÎÎÑ"
+
+#: misc1.c:2684
+msgid "1 more line"
+msgstr "ÚÎÉÝÅÎÏ ÏÄÉÎ ÒÑÄÏË"
+
+#: misc1.c:2686
+msgid "1 line less"
+msgstr "ÄÏÄÁÎÏ ÏÄÉÎ ÒÑÄÏË"
+
+#: misc1.c:2691
+#, c-format
+msgid "%ld more lines"
+msgstr "ÄÏÄÁÎÏ ÒÑÄ˦×: %ld"
+
+#: misc1.c:2693
+#, c-format
+msgid "%ld fewer lines"
+msgstr "ÚÎÉÝÅÎÏ ÒÑÄ˦×: %ld"
+
+#: misc1.c:2696
+msgid " (Interrupted)"
+msgstr " (ðÅÒÅÒ×ÁÎÏ)"
+
+#: misc1.c:6296
+msgid "Vim: preserving files...\n"
+msgstr "Vim: úÁÂÅÒ¦ÇÁÀ ÆÁÊÌÉ...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6306
+msgid "Vim: Finished.\n"
+msgstr "Vim: úÁ×ÅÒÛÅÎÏ.\n"
+
+#: misc2.c:647 misc2.c:663
+msgid "ERROR: "
+msgstr "ðÏÍÉÌËÁ: "
+
+#: misc2.c:667
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[ÂÁÊÔ] ×ÓØÏÇÏ ÒÏÚÍ/ÚÎÉÝ. %lu/%lu, ×ÉËÏÒ. %lu, ÍÁËÓ. %lu\n"
+
+#: misc2.c:669
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[×ÉËÌÉËÉ] ÕÓØÏÇÏ re/malloc() - %lu, ÕÓØÏÇÏ free() - %lu\n"
+"\n"
+
+#: misc2.c:724
+msgid "E340: Line is becoming too long"
+msgstr "E340: òÑÄËÉ ÚÁÎÁÄÔÏ ÄÏ×Ǧ"
+
+# msgstr "E340: "
+#: misc2.c:768
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: ÷ÎÕÔÒ¦ÛÎÑ ÐÏÍÉÌËÁ: lalloc(%ld, )"
+
+# msgstr "E341: "
+#: misc2.c:876
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: úÁÂÒÁËÌÏ ÐÁÍ'ÑÔ¦ (×ÉĦÌÑÌÏÓÑ %lu ÂÁÊÔ¦×)"
+
+# msgstr "E342: "
+#: misc2.c:2513
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "÷ÉËÏÎÕ¤ÍÏ ÚÏ×ΦÛÎÕ ËÏÍÁÎÄÕ: \"%s\""
+
+#: misc2.c:2712 misc2.c:5182 option.c:4584
+msgid "Missing colon"
+msgstr "÷ÔÒÁÞÅÎÏ Ä×ÏËÒÁÐËÕ"
+
+#: misc2.c:2714 misc2.c:2741
+msgid "Illegal mode"
+msgstr "îÅÐÒÉÊÎÑÔÎÉÊ ÒÅÖÉÍ"
+
+#: misc2.c:2780
+msgid "Illegal mouseshape"
+msgstr "îÅÐÒÉÊÎÑÔÎÉÊ ×ÉÇÌÑÄ ÍÉÛ¦"
+
+#: misc2.c:2820 misc2.c:5202
+msgid "digit expected"
+msgstr "ÐÏÔÒ¦ÂÎÁ ÃÉÆÒÁ"
+
+#: misc2.c:2825
+msgid "Illegal percentage"
+msgstr "îÅÐÒÁ×ÉÌØÎÉÊ ×¦ÄÓÏÔÏË"
+
+#: misc2.c:3129
+msgid "Enter encryption key: "
+msgstr "÷ËÁÖ¦ÔØ ËÌÀÞ ÛÉÆÒÕ: "
+
+#: misc2.c:3130
+msgid "Enter same key again: "
+msgstr "÷ËÁÖ¦ÔØ ÔÏÊ ÔÁÍÊ ËÌÀÞ: "
+
+#: misc2.c:3140
+msgid "Keys don't match!"
+msgstr "ëÌÀÞ¦ ÎÅ ÓЦ×ÐÁÄÁÀÔØ!"
+
+#: misc2.c:3679
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr ""
+"E343: îÅÐÒÉÊÎÑÔÎÅ ×ÉÚÎÁÞÅÎÎÑ 'path'. `**[ÃÉÆÒÁ]' ÐÏ×ÉÎÎÏ ÚÎÁÈÏÄÉÔÉÓÑ × Ë¦Îæ "
+"ÛÌÑÈÕ, ÁÂÏ ÐÅÒÅÄ '%s'."
+
+# msgstr "E343: "
+#: misc2.c:4939
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÄÉÒÅËÔÏÒ¦À \"%s\" Õ 'cdpath'"
+
+# msgstr "E344: "
+#: misc2.c:4942
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÆÁÊÌ \"%s\" Õ 'path'"
+
+# msgstr "E345: "
+#: misc2.c:4948
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: õ 'cdpath' ÎÅ ÚÎÁÊÄÅÎÏ ¦ÎÛÉÈ ÄÉÒÅËÔÏÒ¦Ê \"%s\""
+
+# msgstr "E346: "
+#: misc2.c:4951
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: õ ÛÌÑÈÕ ÐÏÛÕËÕ Â¦ÌØÛÅ ÎÅÍÁ¤ ÆÁÊÌ¦× \"%s\""
+
+# msgstr "E347: "
+#: misc2.c:5194
+msgid "Illegal component"
+msgstr "îÅÍÏÖÌÉ×ÉÊ ËÏÍÐÏÎÅÎÔ"
+
+#: normal.c:2825
+msgid "Warning: terminal cannot highlight"
+msgstr "õ×ÁÇÁ: ÔÅÒͦÎÁÌ ÎŠЦÄÔÒÉÍÕ¤ ËÏÌØÏÒÉ"
+
+#: normal.c:3020
+msgid "E348: No string under cursor"
+msgstr "E348: ÷É ÓÔϧÔÅ ÎÁ ÐÏÒÏÖÎØÏÍÕ ÒÑÄËÕ"
+
+# msgstr "E348: "
+#: normal.c:3022
+msgid "E349: No identifier under cursor"
+msgstr "E349: ÷É ÎÅ ÓÔϦÔÅ ÎÁ ÓÌÏצ"
+
+#: normal.c:4187
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: îÅ ÍÏÖÕ ÚÎÉÝÉÔÉ ÚÇÏÒÔËÉ (Ú×ÁÖÁÀÞÉ ÎÁ 'foldmethod')"
+
+#: ops.c:271
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "ÏÄÉÎ ÒÑÄÏË %s-ÎÏ"
+
+#: ops.c:273
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "ÏÄÉÎ ÒÑÄÏË %s-ÎÏ %d ÒÁÚ¦×"
+
+#: ops.c:278
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld ÒÑÄË¦× %s-ÎÏ"
+
+#: ops.c:281
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld ÒÑÄË¦× %s-ÎÏ %d ÒÁÚ¦×"
+
+#: ops.c:638
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "úÁÌÉÛÉÌÏÓÑ ×ÉÒ¦×ÎÑÔÉ: %ld ÒÑÄ˦×"
+
+#: ops.c:688
+msgid "1 line indented "
+msgstr "ÏÄÉÎ ÒÑÄÏË ×ÉÒ¦×ÎÑÎÏ"
+
+#: ops.c:690
+#, c-format
+msgid "%ld lines indented "
+msgstr "×ÉÒ¦×ÎÑÎÏ ÒÑÄ˦×: %ld"
+
+#. must display the prompt
+#: ops.c:1531
+msgid "cannot yank; delete anyway"
+msgstr "ÐÒÏÂÌÅÍÉ Ú ÚÂÅÒÅÖÅÎÎÑÍ, ×ÓÅ ÏÄÎÏ ×ÉÄÁÌÉÔÉ?"
+
+#: ops.c:2021
+msgid "1 line changed"
+msgstr "ïÄÉÎ ÒÑÄÏË ÚͦÎÅÎÏ"
+
+#: ops.c:2023
+#, c-format
+msgid "%ld lines changed"
+msgstr "úͦÎÅÎÏ ÒÑÄ˦×: %ld"
+
+#: ops.c:2383
+#, c-format
+msgid "freeing %ld lines"
+msgstr "ÚצÌØÎÅÎÏ ÒÑÄ˦×: %ld"
+
+#: ops.c:2660
+msgid "1 line yanked"
+msgstr "òÑÄÏË ÚÂÅÒÅÖÅÎÏ"
+
+#: ops.c:2662
+#, c-format
+msgid "%ld lines yanked"
+msgstr "úÂÅÒÅÖÅÎÏ ÒÑÄ˦×: %ld"
+
+#: ops.c:2918
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: õ ÒÅǦÓÔÒ¦ %s ÐÏÒÏÖÎØÏ"
+
+# msgstr "E353: "
+#. Highlight title
+#: ops.c:3465
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- òÅǦÓÔÒÉ ---"
+
+#: ops.c:4597
+msgid "Illegal register name"
+msgstr "îÅÐÒÁ×ÉÌØÎÁ ÎÁÚ×Á ÒÅǦÓÔÒÁ"
+
+#: ops.c:4677
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# òÅǦÓÔÒÉ:\n"
+
+#: ops.c:4703
+#, c-format
+msgid "Unknown register type %d"
+msgstr "îÅצÄÏÍÉÊ ÔÅÐ ÒÅǦÓÔÒÁ: %d"
+
+#: ops.c:5084
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: îÅÐÒÁ×ÉÌØÎÁ ÎÁÚ×Á ÒÅǦÓÔÒÁ: '%s'"
+
+#: ops.c:5425
+#, c-format
+msgid "%ld Cols; "
+msgstr "ÄÏ×Ö.: %ld; "
+
+#: ops.c:5432
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "÷ÉÂÒÁÎÏ - %s%ld Ú %ld òÑÄ˦×; %ld Ú %ld ó̦×; %ld Ú %ld âÁÊÔ¦×"
+
+#: ops.c:5448
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "ëÏÌÏÎËÁ %s Ú %s; òÑÄÏË %ld Ú %ld; óÌÏ×Ï %ld Ú %ld; âÁÊÔ %ld Ú %ld"
+
+#: ops.c:5459
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld ÄÌÑ BOM)"
+
+#: option.c:1989
+msgid "Thanks for flying Vim"
+msgstr "äÑËÕ¤ÍÏ ÚÁ צÄצÄÁÎÎÑ Vim"
+
+#: option.c:3175
+msgid "Option not supported"
+msgstr "ïÐÃ¦Ñ ÎŠЦÄÔÒÉÍÕ¤ÔØÓÑ"
+
+#: option.c:3200
+msgid "Not allowed in a modeline"
+msgstr "îÅ ÄÏÚ×ÏÌÅÎÏ Õ modeline"
+
+#: option.c:3256
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\t÷ÏÓÔÁÎÎÅ ÚͦÎÅÎÕ Õ "
+
+#: option.c:3395
+msgid "Number required after ="
+msgstr "ð¦ÓÌÑ = ÐÏÔÒ¦ÂÎÏ ×ËÁÚÁÔÉ ÞÉÓÌÏ"
+
+#: option.c:3702 option.c:4309
+msgid "Not found in termcap"
+msgstr "îÅ ÚÎÁÊÌÅÎÏ ÓÅÒÅÄ ÍÏÖÌÉ×ÏÓÔÅÊ ÔÅÒͦÎÁ̦×"
+
+#: option.c:3768
+#, c-format
+msgid "Illegal character <%s>"
+msgstr "îÅÄÏÚ×ÁÌÅÎÉÊ ÓÉÍ×ÏÌ <%s>"
+
+#: option.c:4294 option.c:5498
+msgid "Not allowed here"
+msgstr "ôÕÔ ÔÁËÏÇÏ ÎÅ ÌÀÂÌÑÔØ"
+
+#: option.c:4301
+msgid "Cannot set 'term' to empty string"
+msgstr "îÅ ÍÏÖÕ ÓÐÏÒÏÖÎÉÔÉ 'term'"
+
+#: option.c:4304
+msgid "Cannot change term in GUI"
+msgstr "îÅ ÍÏÖÕ ÚͦÎÉÔÉ 'term' × GUI"
+
+#: option.c:4306
+msgid "Use \":gui\" to start the GUI"
+msgstr "÷ÉËÏÒÉÓÔÏ×ÕÊÔÅ \":gui\" ÄÌÑ ÔÏÇÏ ÝÏ ÒÏÚÐÏÞÁÔÉ GUI"
+
+#: option.c:4327
+msgid "'backupext' and 'patchmode' are equal"
+msgstr "ïÐæ§ 'backupext' ÔÁ 'patchmode' ÏÄÎÁËÏצ"
+
+#: option.c:4586
+msgid "Zero length string"
+msgstr "òÑÄÏË ÐÏÒÏÖΦÊ"
+
+#: option.c:4654
+#, c-format
+msgid "Missing number after <%s>"
+msgstr "ð¦ÓÌÑ <%s> ×ÔÒÁÞÅÎÏ ÎÏÍÅÒ"
+
+#: option.c:4668
+msgid "Missing comma"
+msgstr "÷ÔÒÁÞÅÎÏ ËÏÍÕ"
+
+#: option.c:4675
+msgid "Must specify a ' value"
+msgstr "úÎÁÞÅÎÎÑ ' ÎÅ ×ËÁÚÁÎÏ"
+
+#: option.c:4715
+msgid "contains unprintable character"
+msgstr "ͦÓÔÉÔØ ÎÅÄÒÕËÏ×Φ ÓÉÍ×ÏÌÉ"
+
+#: option.c:4728
+msgid "Invalid font(s)"
+msgstr "îÅצÒÎÏ ×ËÁÚÁÎÏ ÛÒÉÆÔ(É)"
+
+#: option.c:4734
+msgid "can't select fontset"
+msgstr "ÎÅ ÍÏÖÕ ×ÉÂÒÁÔÉ fontset"
+
+#: option.c:4736
+msgid "Invalid fontset"
+msgstr "îÅצÒÎÉÊ fontset"
+
+#: option.c:4743
+msgid "can't select wide font"
+msgstr "îÅ ÍÏÖÕ ×ÉËÏÒÉÓÔÁÔÉ ÛÉÒÏËÉÊ ÛÒÉÆÔ"
+
+#: option.c:4745
+msgid "Invalid wide font"
+msgstr "îÅצÒÎÉÊ ÛÉÒÏËÉÊ ÛÒÉÆÔ"
+
+#: option.c:5015
+#, c-format
+msgid "Illegal character after <%c>"
+msgstr "îÅÄÏÚ×ÏÌÅÎÉÊ ÓÉÍ×ÏÌ Ð¦ÓÌÑ <%c>"
+
+#: option.c:5098
+msgid "comma required"
+msgstr "ÐÏÔÒ¦ÂÎÁ ËÏÍÁ"
+
+#: option.c:5107
+#, c-format
+msgid "'commentstring' must be empty or contain %s"
+msgstr "'commentstring' ÍÁ¤ ͦÓÔÉÔÉ %s"
+
+#: option.c:5154
+msgid "No mouse support"
+msgstr "íÉÛÁ ΊЦÄÔÒÉÍÕÀ¤ÔØÓÑ"
+
+#: option.c:5400
+msgid "Unclosed expression sequence"
+msgstr "ðÏÓ̦ÄÏ×ΦÓÔØ ×ÉÒÁÚ¦× ÎÅ ÚÁ×ÅÒÛÅÎÏ"
+
+#: option.c:5404
+msgid "too many items"
+msgstr "ÚÁÂÁÇÁÔÏ ÞÁÓÔÉÎ"
+
+#: option.c:5406
+msgid "unbalanced groups"
+msgstr "ÇÒÕÐÉ ÎÅ ÚÂÁÌÁÎÓÏ×ÁÎÏ"
+
+#: option.c:5621
+msgid "A preview window already exists"
+msgstr "ðÏÐÅÒÅÄΊצËÎÏ ÕÖÅ ¦ÓÎÕ¤"
+
+#: option.c:5882 option.c:5911
+msgid "'winheight' cannot be smaller than 'winminheight'"
+msgstr "'winheight' ÎÅ ÍÏÖÅ ÂÕÔÉ ÍÅÎÛÅ ÚÁ 'winminheight'"
+
+#: option.c:5927 option.c:5946
+msgid "'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "'winwidth' ÎÅ ÍÏÖÅ ÂÕÔÉ ÍÅÎÛÅ ÚÁ 'winminwidth'"
+
+#: option.c:6086
+#, c-format
+msgid "Need at least %d lines"
+msgstr "ðÏÔÒ¦ÂÎÏ ÒÑÄ˦×: ÎÅ ÍÅÎÛÅ %d"
+
+#: option.c:6095
+#, c-format
+msgid "Need at least %d columns"
+msgstr "ðÏÔÒ¦ÂÎÏ ËÏÌÏÎÏË: ÎÅ ÍÅÎÛÅ %d"
+
+#: option.c:6392
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: îÅצÄÏÍÁ ÏÐæÑ: %s"
+
+# msgstr "E355: "
+#: option.c:6501
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- ëÏÄÉ ÔÅÒͦÎÁÌÁ ---"
+
+#: option.c:6503
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- úÁÇÁÌØΦ ÚÎÁÞÅÎÎÑ ÚͦÎÎÉÈ ---"
+
+#: option.c:6505
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- í¦ÓÃÅצ ÚÎÁÞÅÎÎÑ ÚͦÎÎÉÈ ---"
+
+#: option.c:6507
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- úͦÎΦ ---"
+
+#: option.c:7197
+msgid "E356: get_varp ERROR"
+msgstr "E356: ðÏÍÉÌËÁ get_varp [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+# msgstr "E356: "
+#: option.c:8113
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': äÌÑ ÓÉÍ×ÏÌÕ %s ÎÅÍÁ¤ ÐÁÒÉ"
+
+# msgstr "E357: "
+#: option.c:8147
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': îÁÄÌÉÛËÏצ ÓÉÍ×ÏÌÉ Ð¦ÓÌÑ `;': %s"
+
+# msgstr "E358: "
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "ÎÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ "
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ×¦ËÎÏ!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "ðÏÔÒ¦ÂÎÏ Amigados 2.04 ÁÂÏ Ð¦ÚΦۦ ×ÅÒÓ¦§\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "ðÏÔÒ¦ÂÎÏ %s ×ÅÒÓ¦§ %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ NIL:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim ÚÁ×ÅÒÛÕ¤ ÒÏÂÏÔÕ Ú %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "ÎÅ ÍÏÖÕ ÈͦÎÉÔÉ ÒÅÖÉÍ ËÏÎÓÏ̦ ?!\n"
+
+#: os_amiga.c:938 os_mac.c:1168 os_mswin.c:619 os_riscos.c:728 os_unix.c:2733
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: òÅÖÉÍ ÅËÒÁÎÕ ÎŠЦÄÔÒÉÍÕ¤ÔØÓÑ"
+
+# msgstr "E359: "
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: ÎÅ ËÏÎÓÏÌØ??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1142
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: îÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ `shell' Ú ÏÐæ¤À -f"
+
+# msgstr "E360: "
+#: os_amiga.c:1183 os_amiga.c:1273
+msgid "Cannot execute "
+msgstr "îÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ "
+
+#: os_amiga.c:1186 os_amiga.c:1283
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1206 os_amiga.c:1308
+msgid " returned\n"
+msgstr " ÐÏ×ÅÒÎÕÔÏ\n"
+
+#: os_amiga.c:1448
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE ÚÁÍÁÌÉÊ"
+
+#: os_amiga.c:1452
+msgid "I/O ERROR"
+msgstr "ðÏÍÉÌËÁ ××ÏÄÕ/×É×ÏÄÕ"
+
+#: os_mswin.c:503
+msgid "...(truncated)"
+msgstr "...(צÄÒ¦ÚÁÎÏ)"
+
+#: os_mswin.c:594
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'commands' ÎÅ 80, ÎÅ ÍÏÖÕ ×ÉËÏÎÕ×ÁÔÉ ÚÏ×ΦÛΦ ËÏÍÁÎÄÉ"
+
+#: os_mswin.c:706 os_unix.c:4962
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: ÷ÉËÌÉË Ú Â¦Â̦ÏÔÅËÉ ÄÌÑ \"%s()\"ÎÅ ×ÄÁ×ÓÑ"
+
+# msgstr "E364: "
+#: os_mswin.c:1340
+msgid "E237: Printer selection failed"
+msgstr "E237: îÅ ×ÄÁÌÏÓÑ ×ÉÂÒÁÔÉ ÄÒÕ˦×ÎÉË"
+
+#: os_mswin.c:1388
+#, c-format
+msgid "to %s on %s"
+msgstr "ÎÁ %s Ú %s"
+
+#: os_mswin.c:1403
+#, c-format
+msgid "E448: Unknown font: %s"
+msgstr "E488: îÅצÄÏÍÉÊ ÛÒÉÆÔ: %s"
+
+#: os_mswin.c:1453 os_mswin.c:1463
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: ðÏÍÉÌËÁ ÄÒÕËÕ: %s"
+
+#: os_mswin.c:1464
+msgid "Unknown"
+msgstr "îÅצÄÏÍÏ"
+
+#: os_mswin.c:1491
+#, c-format
+msgid "Printing '%s'"
+msgstr "äÒÕËÕ¤ÍÏ '%s'"
+
+#: os_mswin.c:2555
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: ðÏÍÉÌËÏ×Á ÎÁÚ×Á ÎÁÂÏÒÕ ÓÉÍ×ÏÌ¦× \"%s\" Õ ÎÁÚצ ÛÒÉÆÔÁ \"%s\""
+
+#: os_mswin.c:2563
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: ðÏÍÉÌËÏ×ÉÊ ÓÉÍ×ÏÌ %c × ÎÁÚצ ÛÒÉÆÔÁ \"%s\""
+
+#: os_riscos.c:1227
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: îÅצÒÎÁ ÏÐÃ¦Ñ 'osfiletype' -- ×ÉËÏÒÉÓÔÏ×ÕÀ `Text'"
+
+# msgstr "E366: "
+#: os_unix.c:803
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: ïÔÒÉÍÁÎÏ ÓÉÇÎÁÌ Äצަ, ÚÁ×ÅÒÛÕÀ\n"
+
+#: os_unix.c:809
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: ïÔÒÉÍÁÎÏ ÓÉÇÎÁÌ ÚÁ˦ÎÞÉÔÉ ÒÏÂÏÔÕ (%s)\n"
+
+#: os_unix.c:812
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: ïÔÒÉÍÁÎÏ ÓÉÇÎÁÌ ÚÁ˦ÎÞÉÔÉ ÒÏÂÏÔÕ\n"
+
+#: os_unix.c:1066
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "îÁ צÄËÒÉÔÔÑ X-ÄÁÓÐÌÅÀ ЦÛÌÏ %ld ̦ͦÓÅËÕÎÄ"
+
+#: os_unix.c:1093
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ X\n"
+
+#: os_unix.c:1160
+msgid "Testing the X display failed"
+msgstr "îÅ ×ÄÁÌÏÓÑ ÐÅÒÅצÒÉÔÉ ÄÉÓÐÌÅÊ X"
+
+#: os_unix.c:1304
+msgid "Opening the X display timed out"
+msgstr "äÕÖÅ ÄÏ×ÇÏ ×¦ÄËÒÉפÔØÓÑ ÄÉÓÐÌÅÊ X, ÐÅÒÅÒ×ÁÎÏ"
+
+#: os_unix.c:2906 os_unix.c:3490
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"îÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ `shell'"
+
+#: os_unix.c:2951
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"îÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ `sh'\n"
+
+# msgstr "E362: "
+#: os_unix.c:2955 os_unix.c:3496
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"shell ÐÏ×ÅÒÔÁ¤: "
+
+#: os_unix.c:3089
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ËÁÎÁÌÉ\n"
+
+#: os_unix.c:3104
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"îÅ ÍÏÖÕ ÒÏÚÄ×ϧÔÉ ×ÉËÏÎÁÎÎÑ [fork()]\n"
+
+#: os_unix.c:3503
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"ëÏÍÁÎÄÁ ÚÁ˦ÎÞÉÌÁ ×ÉËÏÎÁÎÎÑ\n"
+
+#: os_unix.c:5010
+msgid "Opening the X display failed"
+msgstr "îÅ ×ÄÁÌÏÓÑ ×¦ÄËÒÉÔÉ ÄÉÓÐÌÅÊ X"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "òÑÄÏË:"
+
+#: os_w32exe.c:169
+msgid "Could not load vim32.dll!"
+msgstr "îÅ ×ÄÁÌÏÓÑ ÚÁ×ÁÎÔÁÖÉÔÉ vim32.dll"
+
+#: os_w32exe.c:169 os_w32exe.c:179
+msgid "VIM Error"
+msgstr "ðÏÍÉÌËÁ Vim"
+
+#: os_w32exe.c:179
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "îÅ ÍÏÖÕ ×ÉÐÒÁ×ÉÔÉ ×ËÁÚ¦×ÎÉËÉ ÎÁ ÆÕÎËæ§ DLL!"
+
+#: os_win16.c:578 os_win32.c:3067
+#, c-format
+msgid "shell returned %d"
+msgstr "shell ÐÏ×ÅÒÔÁ¤ %d"
+
+#: os_win32.c:2535
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: ïÔÒÉÍÁÎÏ %s-ÐÏĦÀ\n"
+
+#: os_win32.c:2537
+msgid "close"
+msgstr "close"
+
+#: os_win32.c:2539
+msgid "logoff"
+msgstr "logoff"
+
+#: os_win32.c:2540
+msgid "shutdown"
+msgstr "shutdown"
+
+#: os_win32.c:3021
+msgid "E371: Command not found"
+msgstr "E371: ëÏÍÁÎÄÕ ÎÅ ÚÎÁÊÄÅÎÏ"
+
+#: os_win32.c:3034
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"æÁÊÌ VIMRUN.EXE ÎÅ ÚÎÁÊÄÅÎÏ Õ ×ÁÛÏÍÕ ÛÌÑÈÕ ÐÏÛÕËÕ.\n"
+"úÏ×ΦÛΦ ËÏÍÁÎÄÉ ÎÅ ÂÕÄÕÔØ ÐÒÉÚÕÐÉÎÅΦ ЦÓÌÑ ×ÉËÏÎÁÎÎÑ.\n"
+"äÉצÔØÓÑ :help win32-vimrun ÄÌÑ ÐÏÄÁÌØÛϧ ¦ÎÆÏÒÍÁæ§."
+
+#: os_win32.c:3037
+msgid "Vim Warning"
+msgstr "ðÏÐÅÒÅÄÖÅÎÎÑ Vim"
+
+# msgstr "E371: "
+#: quickfix.c:281
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: úÁÂÁÇÁÔÏ %%%c Õ ÒÑÄËÕ ÆÏÒÍÁÔÁ"
+
+# msgstr "E372: "
+#: quickfix.c:294
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: îÅÏÞ¦ËÕ×ÁÎÉÊ `%%%c' Õ ÒÑÄËÕ ÆÏÒÍÁÔÁ"
+
+# msgstr "E373: "
+#: quickfix.c:348
+msgid "E374: Missing ] in format string"
+msgstr "E374: ÷ÔÒÁÞÅÎÏ ] Õ ÒÑÄËÕ ÆÏÒÍÁÔÁ"
+
+# msgstr "E374: "
+#: quickfix.c:362
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: %%%c Õ ÒÑÄËÕ ÆÏÒÍÁÔÁ ΊЦÄÔÒÉÍÕ¤ÔØÓÑ"
+
+# msgstr "E375: "
+#: quickfix.c:380
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: ðÏÍÉÌËÏ×ÉÊ `%%%c' Õ ÐÒÅƦËÓ¦ ÒÑÄËÕ ÆÏÒÍÁÔÁ"
+
+# msgstr "E376: "
+#: quickfix.c:388
+msgid "E377: Invalid %%%c in format string"
+msgstr "E376: ðÏÍÉÌËÏ×ÉÊ `%%%c' Õ ÒÑÄËÕ ÆÏÒÍÁÔÁ"
+
+# msgstr "E377: "
+#: quickfix.c:414
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' ͦÓÔÉÔØ ÌÉÛÅ Ú×ÉÞÁÊΦ ÓÉÍ×ÏÌÉ"
+
+# msgstr "E378: "
+#: quickfix.c:520
+msgid "E379: Missing or empty directory name"
+msgstr "E379: ÷ÔÒÁÞÅÎÏ ÎÁÚ×Õ ÄÉÒÅËÔÏÒ¦§"
+
+#: quickfix.c:931
+msgid "No more items"
+msgstr "ïÓÔÁÎÎ¦Ê ÅÌÅÍÅÎÔ"
+
+#: quickfix.c:1152
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d Ú %d)%s%s: "
+
+#: quickfix.c:1154
+msgid " (line deleted)"
+msgstr " (ÒÑÄÏË ×ÉÄÁÌÅÎÏ)"
+
+#: quickfix.c:1360
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: óÔÅË quickfix ÐÏÒÏÖΦÊ"
+
+#: quickfix.c:1369
+msgid "E381: At top of quickfix stack"
+msgstr "E381: ÷ÅÒÛÉÎÁ ÓÔÅËÕ quickfix"
+
+#: quickfix.c:1381
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "ÓÐÉÓÏË ÐÏÍÉÌÏË %d Ú %d; %d ÐÏÍÉÌÏË"
+
+#: quickfix.c:1842
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ, ×ËÁÚÁÎÁ ÏÐÃ¦Ñ 'buftype'"
+
+# msgstr "E382: "
+#: regexp.c:802
+msgid "E339: Pattern too long"
+msgstr "E339: úÒÁÚÏË ÚÁÎÁÄÔÏ ÄÏ×ÇÉÊ"
+
+# msgstr "E339: "
+#: regexp.c:1316
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: ÷ËÌÁÄÅΦ %s*"
+
+# msgstr "E61: "
+#: regexp.c:1319
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: ÷ËÌÁÄÅΦ %s%c"
+
+# msgstr "E62: "
+#: regexp.c:1470
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: ð¦ÓÌÑ %s%c ΦÞÏÇÏ ÎÅÍÁ¤"
+
+# msgstr "E64: "
+#: regexp.c:2480
+#, c-format
+msgid "Syntax error in %s{...}"
+msgstr "óÉÎÔÁËÓÉÞÎÁ ÐÏÍÉÌËÁ × %s{...}"
+
+#: regexp.c:2727
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: ÷¦ÄÂÕÌÁÓØ Á×ÁÒ¦Ñ; ÚÁÎÁÄÔÏ ÓËÌÁÄÎÉÊ ÚÒÁÚÏË?"
+
+#: regexp.c:2862
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: úÒÁÚÏË ÚÞÉÎÉ× ÐÏÍÉÌËÕ ÓÔÅËÕ"
+
+#: regexp.c:3098
+msgid "External submatches:\n"
+msgstr "úÏ×ΦÛΦ ЦÄÚ¦ÇÉ:\n"
+
+#: screen.c:2058
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--[ÚÇÏÒÔÏË](%3ld ÒÑÄ˦×)"
+
+#: screen.c:7451
+msgid " VREPLACE"
+msgstr " V-ÚÁͦÎÁ"
+
+#: screen.c:7455
+msgid " REPLACE"
+msgstr " úÁͦÎÁ"
+
+#: screen.c:7460
+msgid " REVERSE"
+msgstr " ïÂÅÒÎÕÔÏ"
+
+#: screen.c:7462
+msgid " INSERT"
+msgstr " ÷ÓÔÁ×ËÁ"
+
+#: screen.c:7465
+msgid " (insert)"
+msgstr " (×ÓÔÁ×ËÁ)"
+
+#: screen.c:7467
+msgid " (replace)"
+msgstr " (ÚÁͦÎÁ)"
+
+#: screen.c:7469
+msgid " (vreplace)"
+msgstr " (V-ÚÁͦÎÁ)"
+
+#: screen.c:7472
+msgid " Hebrew"
+msgstr " Hebrew"
+
+#: screen.c:7480
+msgid " (lang)"
+msgstr " (lang)"
+
+#: screen.c:7483
+msgid " (paste)"
+msgstr " (ÂÅÚ ÏÂÒÏÂËÉ)"
+
+#: screen.c:7489
+msgid " SELECT"
+msgstr " ÷ÉĦÌÅÎÎÑ"
+
+#: screen.c:7491
+msgid " VISUAL"
+msgstr " ÷ɦÒ"
+
+#: screen.c:7493
+msgid " BLOCK"
+msgstr " [âÌÏË]"
+
+#: screen.c:7495
+msgid " LINE"
+msgstr " [òÑÄËÉ]"
+
+#: screen.c:7508 screen.c:7562
+msgid "recording"
+msgstr "ÊÄÅ ÚÁÐÉÓ"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "ðÏÛÕË Ä¦ÊÛÏ× ÄÏ ÇÏÒÉ, ÐÒÏÄÏ×ÖÕ¤ÍÏ ÕÎÉÚÕ"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "ðÏÛÕË Ä¦ÊÛÏ× ÄÏ ÎÉÚÕ, ÐÒÏÄÏ×ÖÕ¤ÍÏ Ú ÇÏÒÉ"
+
+#: search.c:440
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: îÅצÒÎÉÊ ÚÒÁÚÏË ÄÌÑ ÐÏÛÕËÕ: %s"
+
+#: search.c:747
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: ðÏÛÕË Ä¦ÊÛÏ× ÄÏ ÇÏÒÉ ÂÅÚ ÚÂ¦Ç¦× Ú %s"
+
+#: search.c:749
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: ðÏÛÕË Ä¦ÊÛÏ× ÄÏ ÎÉÚÕ ÂÅÚ ÚÂ¦Ç¦× Ú %s"
+
+#: search.c:1107
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: ð¦ÓÌÑ `;' ÍÁ¤ ÊÔÉ `?' ÁÂÏ `/'"
+
+# msgstr "E386: "
+#: search.c:3479
+msgid " (includes previously listed match)"
+msgstr " (ÒÁÚÏÍ Ú ÐÏÐÅÒÅÄΦÍÉ Ú¦ÇÁÍÉ)"
+
+#. cursor at status line
+#: search.c:3499
+msgid "--- Included files "
+msgstr "--- ÷ËÌÀÞÅΦ ÆÁÊÌÉ "
+
+#: search.c:3501
+msgid "not found "
+msgstr "ÎÅ ÚÎÁÊÄÅÎÏ "
+
+#: search.c:3502
+msgid "in path ---\n"
+msgstr "Õ ÛÌÑÈÕ ÐÏÛÕËÕ ---\n"
+
+#: search.c:3541
+msgid " (Already listed)"
+msgstr " (õÖÅ Õ ÓÐÉÓËÕ)"
+
+#: search.c:3543
+msgid " NOT FOUND"
+msgstr " îÅ ÚÎÁÊÄÅÎÏ"
+
+#: search.c:3595
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "ðÏÛÕË Õ ×ËÌÀÞÅÎÏÍÕ ÆÁÊ̦: %s"
+
+#: search.c:3813
+msgid "E387: Match is on current line"
+msgstr "E387: úÂ¦Ç Õ ÐÏÔÏÞÎÏÍÕ ÒÑÄËÕ"
+
+#: search.c:3953
+msgid "All included files were found"
+msgstr "õÓ¦ ×ËÌÀÞÅΦ ÆÁÊÌÉ ÂÕÌÏ ÚÎÁÊÄÅÎÏ"
+
+#: search.c:3955
+msgid "No included files"
+msgstr "öÏÄÎÏÇÏ ×ËÌÀÞÅÎÏÇÏ ÆÁÊÌÁ"
+
+#: search.c:3971
+msgid "E388: Couldn't find definition"
+msgstr "E388: ÷ÉÚÎÁÞÅÎÎÑ ÎÅ ÚÎÁÊÄÅÎÏ"
+
+#: search.c:3973
+msgid "E389: Couldn't find pattern"
+msgstr "E389: úÒÁÚÏË ÎÅ ÚÎÁÊÄÅÎÏ"
+
+#: syntax.c:2998
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: îÅצÒÎÉÊ ÁÒÇÕÍÅÎÔ: %s"
+
+#: syntax.c:3176
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: îÅ ¦ÓÎÕÀÞÉÊ ËÌÁÓÅÔÒ ÓÉÎÔÁËÓÉÓÕ: %s"
+
+# msgstr "E391: "
+#: syntax.c:3340
+msgid "No Syntax items defined for this buffer"
+msgstr "äÌÑ ÂÕÆÅÒÕ ÎÅ ×ÉÚÎÁÞÅÎÏ ÅÌÅÍÅÎÔ¦× ÓÉÎÔÁËÓÉÓÕ"
+
+#: syntax.c:3348
+msgid "syncing on C-style comments"
+msgstr "ÓÉÎÈÒÏΦÚÁÃ¦Ñ ÂÁÚÕ¤ÔØÓÑ ÎÁ ó-ËÏÍÅÎÔÁÒ¦ÑÈ"
+
+#: syntax.c:3356
+msgid "no syncing"
+msgstr "ÓÉÎÈÒÏΦÚÁÃ¦Ñ ÎÅ ×ÉËÏÒÉÓÔÏ×Õ¤ÔØÓÑ"
+
+#: syntax.c:3359
+msgid "syncing starts "
+msgstr "ÓÉÎÈÒÏΦÚÁÃ¦Ñ ÐÏÞÉÎÁ¤ÔØÓÑ ÚÁ "
+
+#: syntax.c:3361 syntax.c:3430
+msgid " lines before top line"
+msgstr " ÒÑÄË¦× ÐÅÒÅÄ ÐÅÒÛÉÍ ÒÑÄËÏÍ"
+
+#: syntax.c:3365
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- åÌÅÍÅÎÔÉ ÓÉÎÈÒÏΦÚÁæ§ ÓÉÎÔÁËÓÉÓÕ ---"
+
+#: syntax.c:3368
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"ÓÉÎÈÒÏΦÚÁæ§ ÂÁÚÕ¤ÔØÓÑ ÎÁ ÅÌÅÍÅÎÔÁÈ"
+
+#: syntax.c:3373
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- åÌÅÍÅÎÔÉ ÓÉÎÔÁËÓÉÓÕ ---"
+
+#: syntax.c:3396
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: îÅ ¦ÓÎÕÀÞÉÊ ËÌÁÓÅÔÒ ÓÉÎÔÁËÓÉÓÕ: %s"
+
+#: syntax.c:3420
+msgid "minimal "
+msgstr "ͦΦÍÁÌØÎÉÊ "
+
+#: syntax.c:3427
+msgid "maximal "
+msgstr "ÍÁËÓÉÍÁÌØÎÉÊ "
+
+#: syntax.c:4057
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: group[t]hete ÔÕÔ ÎÅ ÐÒÁÃÀ¤"
+
+#: syntax.c:4081
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: îÅ ÚÎÁÊÄÅÎÏ ÏÂÌÁÓÔ¦ ÄÌÑ %s"
+
+#: syntax.c:4109
+msgid "E395: contains argument not accepted here"
+msgstr "E395: í¦ÓÔÉÔØ ÁÒÇÕÍÅÎÔÉ ÝÏ ÎÅÐÒÉÊÎÑÔΦ ÔÕÔ"
+
+#: syntax.c:4120
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: áÒÇÕÍÅÎÔ ÎÅÐÒÉÊÎÑÔÎÉÊ ÔÕÔ"
+
+# msgstr "E396: "
+#: syntax.c:4198
+msgid "E397: Filename required"
+msgstr "E397: ðÏÔÒ¦ÂÎÁ ÎÁÚ×Á ÆÁÊÌÁ"
+
+#: syntax.c:4536
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: `=' ×ÔÒÁÞÅÎÏ: %s"
+
+# ---------------------------------------
+#: syntax.c:4694
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: îÅ ÄÏÓÉÔØ ÁÒÇÕÍÅÎÔ¦×: syntax region %s"
+
+#: syntax.c:5025
+msgid "E400: No cluster specified"
+msgstr "E400: ëÌÁÓÔÅÒ ÎÅ ×ËÁÚÁÎÏ"
+
+#: syntax.c:5062
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: ë¦ÎÅÃØ ÚÒÁÚËÁ ÎÅ ÚÎÁÊÄÎÏ: %s"
+
+#: syntax.c:5137
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: óͦÔÔÑ Ð¦ÓÌÑ ÚÒÁÚËÁ: %s"
+
+# msgstr "E402: "
+#: syntax.c:5219
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: syntax syntax: ÚÒÁÚÏË ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ ÒÑÄËÁ ×ËÁÚÁÎÏ Äצަ"
+
+#: syntax.c:5276
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: îÅצÒΦ ÁÒÇÕÍÅÎÔÉ: %s"
+
+# msgstr "E404: "
+#: syntax.c:5326
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: îÅÍÁ¤ `=': %s"
+
+# msgstr "E405: "
+#: syntax.c:5332
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: ðÏÒÏÖÎ¦Ê ÁÒÇÕÍÅÎÔ: %s"
+
+# msgstr "E406: "
+#: syntax.c:5359
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s ÔÕÔ ÎÅ ÄÏÚ×ÏÌÅÎÏ"
+
+#: syntax.c:5366
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s ÍÁ¤ ÂÕÔÉ ÐÅÒÛÉÍ ÒÑÄËÏÍ Õ ÆÁÊ̦"
+
+#: syntax.c:5436
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: îÅצÒÎÁ ÎÁÚ×Á ÇÒÕÐÉ: %s"
+
+# msgstr "E409: "
+#: syntax.c:5666
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: îÅצÒÎÁ ЦÄËÏÍÁÎÄÁ :syntax : %s"
+
+# msgstr "E410: "
+#: syntax.c:6045
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: ëÏÌØÏÒ ÎÅ ÚÎÁÊÄÅÎÏ: %s"
+
+# msgstr "E411: "
+#: syntax.c:6069
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: îÅÄÏÓÔÁÔÎØÏ ÁÒÇÕÍÅÎÔ¦×: \"highlight link %s\""
+
+# msgstr "E412: "
+#: syntax.c:6076
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: úÁÂÁÇÁÔÏ ÁÒÇÕÍÅÎÔ¦×: \":highlight link %s\""
+
+# msgstr "E413: "
+#: syntax.c:6096
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: ëÏÌ¦Ò ÕÖÅ ×ÓÔÁÎÏ×ÌÅÎÏ, \":highlight link\" ÐÒϦÇÎÏÒÏ×ÁÎÏ"
+
+# msgstr "E414: "
+#: syntax.c:6225
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: úÎÁË Ò¦×ÎÏÓÔ¦ ÎÅ ÐÏÔÒ¦ÂÅÎ: %s"
+
+# msgstr "E415: "
+#: syntax.c:6261
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: ÷ÔÒÁÞÅÎÏ ÚÎÁË Ò¦×ÎÏÓÔ¦: %s"
+
+#: syntax.c:6283
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: ÷ÔÒÁÞÅÎÏ ÁÒÇÕÍÅÎÔ: %s"
+
+#: syntax.c:6320
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: îÅצÒÎÅ ÚÎÁÞÅÎÎÑ: %s"
+
+# msgstr "E418: "
+#: syntax.c:6439
+msgid "E419: FG color unknown"
+msgstr "E419: îÅצÄÏÍÉÊ ËÏÌ¦Ò ÔÅËÓÔÕ"
+
+# msgstr "E419: "
+#: syntax.c:6450
+msgid "E420: BG color unknown"
+msgstr "E420: îÅצÄÏÍÉÊ ËÏÌ¦Ò ÆÏÎÕ"
+
+# msgstr "E420: "
+#: syntax.c:6511
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: îÅÚÒÏÚÕͦÌÁ ÎÁÚ×Á ÁÂÏ ÎÏÍÅÒ ËÏÌØÏÒÕ: %s"
+
+# msgstr "E421: "
+#: syntax.c:6719
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: úÁÎÁÄÔÏ ÄÏ×ÇÉÊ ËÏÄ ÔÅÒͦÎÁÌÕ: %s"
+
+# msgstr "E422: "
+#: syntax.c:6766
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: îÅצÒÎÉÊ ÁÒÇÕÍÅÎÔ: %s"
+
+# msgstr "E423: "
+#: syntax.c:7295
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: úÁÂÁÇÁÔÏ Ò¦ÚÎÉÈ ÁÔÒÉÂÕÔ ËÏÌØÏÒÕ"
+
+# msgstr "E424: "
+#: tag.c:90
+msgid "at bottom of tag stack"
+msgstr "ÓÔÅË ÐÏͦÔÏË ÐÏÒÏÖΦÊ"
+
+#: tag.c:91
+msgid "at top of tag stack"
+msgstr "×ÅÒÛÉÎÁ ÓÔÅËÕ ÐÏͦÔÏË"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: îÅ ÍÏÖÕ ÐÅÒÅÊÔÉ ÄÏ ÐÏÐÅÒÅÄÎÏا ÐÏͦÔËÉ Ú ÐÅÒÛϧ"
+
+# msgstr "E425: "
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: ÐÏͦÔËÕ %s ÎÅ ÚÎÁÊÄÅÎÏ"
+
+# msgstr "E426: "
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr ""
+
+#: tag.c:548
+msgid "file\n"
+msgstr "ÆÁÊÌ\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "ñËÕ ÓÁÍÅ ÐÏͦÔËÕ ×ÉËÏÒÉÓÔÁÔÉ (<CR> ÄÌÑ ×¦ÄͦÎÉ): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: ìÉÛÅ ÏÄÎÁ צÄÐÏצÄÎÁ ÐÏͦÔËÁ"
+
+# msgstr "E427: "
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: ãÅ ÏÓÔÁÎÎÑ ×¦ÄÐÏצÄÎÏ ÐÏͦÔËÁ"
+
+# msgstr "E428: "
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "æÁÊÌ \"%s\" ÎÅ ¦ÓÎÕ¤"
+
+#. Give an indication of the number of matching tags
+#: tag.c:780
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "ÐÏͦÔËÁ %d Ú %d%s"
+
+#: tag.c:783
+msgid " or more"
+msgstr " ÁÂÏ Â¦ÌØÛÅ"
+
+#: tag.c:785
+msgid " Using tag with different case!"
+msgstr " ÷ÉËÏÒÉÓÔÏ×ÕÀ ÐÏͦÔËÕ ÎÅ ÒÏÚÒ¦ÚÎÑÀÞÉ ×ÅÌÉ˦ ÔÁ ÍÁ̦ ̦ÔÅÒÉ"
+
+#: tag.c:828
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: æÁÊÌ \"%s\" ÎÅ ¦ÓÎÕ¤"
+
+# msgstr "E429: "
+#. Highlight title
+#: tag.c:897
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+
+#: tag.c:1144
+msgid "Linear tag search"
+msgstr "ì¦Î¦ÊÎÉÊ ÐÏÛÕË ÐÏͦÔËÉ"
+
+#: tag.c:1146
+msgid "Binary tag search"
+msgstr "äצÊËÏ×ÉÊ ÐÏÛÕË ÐÏͦÔËÉ"
+
+#: tag.c:1172
+#, c-format
+msgid "Searching tags file %s"
+msgstr "ûÕËÁÀ Á ÆÁÊ̦ ÐÏͦÔÏË %s"
+
+#: tag.c:1356
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: ûÌÑÈ ÄÌÑ %s × ÆÁÊ̦ ÐÏͦÔË ÚËÏÒÏÞÅÎÏ\n"
+
+# msgstr "E430: "
+#: tag.c:1847
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: ðÏÍÉÌËÁ ÆÏÒÍÁÔÕ Õ ÆÁÊ̦ ÐÏͦÔÏË \"%s\""
+
+# msgstr "E431: "
+#: tag.c:1851
+#, c-format
+msgid "Before byte %ld"
+msgstr "ðÅÒÅÄ ÂÁÊÔÏÍ %ld"
+
+#: tag.c:1872
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: æÁÊÌ ÐÏͦÔÏË %s ÎÅ ×ÐÏÒÑÄËÏ×ÁÎÉÊ"
+
+# msgstr "E432: "
+#. never opened any tags file
+#: tag.c:1911
+msgid "E433: No tags file"
+msgstr "E433: îÅÍÁ¤ ÆÁÌÁ ÐÏͦÔÏË"
+
+# msgstr "E433: "
+#: tag.c:2583
+msgid "E434: Can't find tag pattern"
+msgstr "E434: îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÐÏͦÔËÕ ÚÁ §§ ÚÒÁÚËÏÍ"
+
+# msgstr "E434: "
+#: tag.c:2594
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÐÏͦÔËÕ, ÚÄÏÇÁÄÕÀÓØ!"
+
+# msgstr "E435: "
+#: term.c:1733
+msgid "' not known. Available builtin terminals are:"
+msgstr "' ΊצÄÏÍÉÊ. ÷ÂÕÄÏ×ÁΦ ÔÅÒͦÎÁÌÉ:"
+
+#: term.c:1757
+msgid "defaulting to '"
+msgstr "ÂÕÄÅÍÏ ××ÁÖÁÔÉ ÝÏ ÃÅ '"
+
+#: term.c:2110
+msgid "Cannot open termcap file"
+msgstr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ¦ÁÊÌ ÍÏÖÌÉ×ÏÓÔÅÊ ÔÅÒͦÎÁÌ¦× [termcap]"
+
+#: term.c:2113
+msgid "Terminal entry not found in terminfo"
+msgstr "îÅÍÁ¤ ¦ÎÆÏÒÍÁæ§ ÐÒÏ ÔÅÒͦÎÁÌ [terminfo]"
+
+#: term.c:2115
+msgid "Terminal entry not found in termcap"
+msgstr "îÅÍÁ¤ ¦ÎÆÏÒÍÁæ§ ÐÒÏ ÍÏÖÌÉ×ÏÓÔ¦ ÔÅÒͦÎÁÌÁ [termcap]"
+
+#: term.c:2274
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: îÅÍÁ¤ ¦ÎÆÏÒÍÁæ§ ÐÒÏ ÍÏÖÌÉ×ÏÓÔ¦ ÔÅÒͦÎÁÌÁ \"%s\" [termcap]"
+
+#: term.c:2748
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: ÍÏÖÌÉצÓÔØ ÔÅÒͦÎÁÌÁ \"cm\" ÏÂÏ×'ÑÚËÏ×Á"
+
+#. Highlight title
+#: term.c:4888
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- ëÌÁצۦ ÔÅÒͦÎÁÌÁ ---"
+
+#: ui.c:240
+msgid "new shell started\n"
+msgstr "ÒÏÚÐÏÞÁÔÏ ÎÏ×ÉÊ shell\n"
+
+#: ui.c:1705
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: ðÏÍÉÌËÁ ÞÉÔÁÎÎÑ ××ÏÄÕ, ÚÁ×ÅÒÛÕÀ ÒÏÂÏÔÕ...\n"
+
+#. must display the prompt
+#: undo.c:383
+msgid "No undo possible; continue anyway"
+msgstr "÷¦ÄͦÎÁ ÎÅ ÂÕÄÅ ÍÏÖÌÉ×Á, ÐÒÏÄÏ×ÖÉÔÉ"
+
+#: undo.c:538
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: ÎÅצÒΦ ÎÏÍÅÒÉ ÒÑÄË¦× [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+# msgstr "E438: "
+#: undo.c:707
+msgid "1 change"
+msgstr "ÏÄÎÁ ÚͦÎÁ"
+
+#: undo.c:709
+#, c-format
+msgid "%ld changes"
+msgstr "ÚͦÎ: %ld"
+
+#: undo.c:753
+msgid "E439: undo list corrupt"
+msgstr "E439: óÐÉÓÏË ×¦ÄͦÎÉ ÐÏÛËÏÄÖÅÎÏ [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+# msgstr "E439: "
+#: undo.c:785
+msgid "E440: undo line missing"
+msgstr "E440: ×ÔÒÁÞÅÎÏ ÒÑÄÏË ×¦ÄͦÎÉ [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+# msgstr "E440: "
+# ---------------------------------------
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:897
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ ÄÌÑ 16/32 bit Windows Ú Ð¦ÄÔÒÉÍËÏÀ GUI"
+
+#: version.c:899
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ ÄÌÑ 32 bit Windows Ú Ð¦ÄÔÒÉÍËÏÀ GUI"
+
+#: version.c:902
+msgid " in Win32s mode"
+msgstr " × ÒÅÖÉͦ Win32s"
+
+#: version.c:904
+msgid " with OLE support"
+msgstr " Ú Ð¦ÄÔÒÉÍËÏÀ OLE"
+
+#: version.c:907
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ ÄÌÑ 32 bit Windows"
+
+#: version.c:911
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ ÄÌÑ 16 bit Windows"
+
+#: version.c:915
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ ÄÌÑ 32 bit MS-DOS"
+
+#: version.c:917
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ ÄÌÑ 16 bit MS-DOS"
+
+#: version.c:923
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ ÄÌÑ MacOS X (unix)"
+
+#: version.c:925
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ ÄÌÑ MacOS X"
+
+#: version.c:928
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ ÄÌÑ MacOS"
+
+#: version.c:933
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"×ÅÒÓ¦Ñ RISC OS"
+
+#: version.c:943
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"÷ËÌÀÞÅÎÏ ÌÁÔËÉ: "
+
+#: version.c:970
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"úËÏÍЦÌØÏ×ÁÎÏ "
+
+#: version.c:973
+msgid "by "
+msgstr "-- "
+
+#: version.c:985
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ `huge' "
+
+#: version.c:988
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ `big' "
+
+#: version.c:991
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ `normal' "
+
+#: version.c:994
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ `small' "
+
+#: version.c:996
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"÷ÅÒÓ¦Ñ `tiny' "
+
+#: version.c:1002
+msgid "without GUI."
+msgstr "ÂÅÚ Ð¦ÄÔÒÉÍËÉ GUI."
+
+#: version.c:1006
+msgid "with GTK-GNOME GUI."
+msgstr "Ú Ð¦ÄÔÒÉÍËÏÀ GTK-GNOME GUI."
+
+#: version.c:1008
+msgid "with GTK GUI."
+msgstr "Ú Ð¦ÄÔÒÉÍËÏÀ GTK GUI."
+
+#: version.c:1012
+msgid "with X11-Motif GUI."
+msgstr "Ú Ð¦ÄÔÒÉÍËÏÀ X11-Motif GUI."
+
+#: version.c:1015
+msgid "with X11-Athena GUI."
+msgstr "Ú Ð¦ÄÔÒÉÍËÏÀ X11-Athena GUI."
+
+#: version.c:1018
+msgid "with BeOS GUI."
+msgstr "Ú Ð¦ÄÔÒÉÍËÏÀ BeOS GUI."
+
+#: version.c:1021
+msgid "with Photon GUI."
+msgstr "Ú Ð¦ÄÔÒÉÍËÏÀ Photon GUI."
+
+#: version.c:1024
+msgid "with GUI."
+msgstr "Ú Ð¦ÄÔÒÉÍËÏÀ GUI."
+
+#: version.c:1027
+msgid "with Carbon GUI."
+msgstr "Ú Ð¦ÄÔÒÉÍËÏÀ Carbon GUI."
+
+#: version.c:1030
+msgid "with Cocoa GUI."
+msgstr "Ú Ð¦ÄÔÒÉÍËÏÀ Cocoa GUI."
+
+#: version.c:1033
+msgid "with (classic) GUI."
+msgstr "Ú (ËÌÁÓÉÞÎÉÍ) GUI."
+
+#: version.c:1044
+msgid " Features included (+) or not (-):\n"
+msgstr ""
+" \n"
+"í¦ÓÔÉÔØ (+) [ÁÂÏ ÎŠͦÓÔÉÔØ (-)] ÔÁ˦ ËÏÍÐÏÎÅÎÔÉ:\n"
+
+#: version.c:1056
+msgid " system vimrc file: \""
+msgstr " ÓÉÓÔÅÍÎÉÊ vimrc: \""
+
+#: version.c:1061
+msgid " user vimrc file: \""
+msgstr " vimrc ËÏÒÉÓÔÕ×ÁÞÁ: \""
+
+#: version.c:1066
+msgid " 2nd user vimrc file: \""
+msgstr " ÄÒÕÇÉÊ vimrc ËÏÒÉÓÔÕ×ÁÞÁ: \""
+
+#: version.c:1071
+msgid " 3rd user vimrc file: \""
+msgstr " ÔÒÅÔ¦Ê vimrc ËÏÒÉÓÔÕ×ÁÞÁ: \""
+
+#: version.c:1076
+msgid " user exrc file: \""
+msgstr " exrc ËÏÒÉÓÔÕ×ÁÞÁ: \""
+
+#: version.c:1081
+msgid " 2nd user exrc file: \""
+msgstr " ÄÒÕÇÉÊ exrc ËÏÒÉÓÔÕ×ÁÞÁ: \""
+
+#: version.c:1087
+msgid " system gvimrc file: \""
+msgstr " ÓÉÓÔÅÍÎÉÊ gvimrc: \""
+
+#: version.c:1091
+msgid " user gvimrc file: \""
+msgstr " gvimrc ËÏÒÉÓÔÕ×ÁÞÁ: \""
+
+#: version.c:1095
+msgid "2nd user gvimrc file: \""
+msgstr "ÄÒÕÇÉÊ gvimrc ËÏÒÉÓÔÕ×ÁÞÁ: \""
+
+#: version.c:1100
+msgid "3rd user gvimrc file: \""
+msgstr "ÔÒÅÔ¦Ê gvimrc ËÏÒÉÓÔÕ×ÁÞÁ: \""
+
+#: version.c:1107
+msgid " system menu file: \""
+msgstr " ÓÉÓÔÅÍÎÅ ÍÅÎÀ: \""
+
+#: version.c:1115
+msgid " fall-back for $VIM: \""
+msgstr " ÚÁͦÎÁ ÄÌÑ $VIM: \""
+
+#: version.c:1121
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " ÚÁͦÎÁ ÄÌÑ $VIMRUNTIME: \""
+
+#: version.c:1125
+msgid "Compilation: "
+msgstr "úËÏÍЦÌØÏ×ÁÎÏ: "
+
+#: version.c:1131
+msgid "Compiler: "
+msgstr "ëÏÍЦÌÑÔÏÒ: "
+
+#: version.c:1136
+msgid "Linking: "
+msgstr "úËÏÍÐÏÎÏ×ÁÎÏ: "
+
+#: version.c:1141
+msgid " DEBUG BUILD"
+msgstr " ÷åòó¶ñ äìñ îáìáçïäöåîîñ"
+
+#: version.c:1177
+msgid "VIM - Vi IMproved"
+msgstr "Vim - ðÏËÒÁÝÅÎÉÊ Vi"
+
+#: version.c:1179
+msgid "version "
+msgstr "×ÅÒÓ¦Ñ: "
+
+#: version.c:1180
+msgid "by Bram Moolenaar et al."
+msgstr " Á×ÔÏÒ: Bram Moolenaar ÔÁ ¦Î."
+
+#: version.c:1181
+msgid "Vim is open source and freely distributable"
+msgstr "Vim ÊצÄËÒÉÔÁ ÐÒÏÇÒÁÍÁ, ×É ÍÏÖÅÔŠצÌØÎÏ ÒÏÚÐÏ×ÓÀÄÖÕ×ÁÔÉ §§"
+
+#: version.c:1183
+msgid "Help poor children in Uganda!"
+msgstr "äÏÐÏÍÏÖ¦ÔØ ÓÉÒÏÔÁÍ Ú õÇÁÎÄÉ!"
+
+#: version.c:1184
+msgid "type :help iccf<Enter> for information "
+msgstr ":help iccf<Enter> ÐÏÄÁÌØÛÁ ¦ÎÆÏÒÍÁÃ¦Ñ "
+
+#: version.c:1186
+msgid "type :q<Enter> to exit "
+msgstr ":q<Enter> ×ÉÈ¦Ä Ú Vim "
+
+#: version.c:1187
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr ":help<Enter> ÁÂÏ <F1> ÐÅÒÅÇÌÑÄ ÄÏÐÏÍÏÇÉ "
+
+#: version.c:1188
+msgid "type :help version6<Enter> for version info"
+msgstr ":help version6<Enter> ¦ÎÆÏÒÍÁÃ¦Ñ ÐÒÏ Vim 6 "
+
+#: version.c:1191
+msgid "Running in Vi compatible mode"
+msgstr "÷É ÐÒÁÃÀ¤ÔÅ × ÒÅÖÉͦ ÓÕͦÓÎÏÍÕ Ú Vi"
+
+#: version.c:1192
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr ":set nocp<Enter> ÒÅÖÉÍ ÎÅÓÕͦÓÎÉÊ Ú Vi "
+
+#: version.c:1193
+msgid "type :help cp-default<Enter> for info on this"
+msgstr ":help cp-default<Enter> ¦ÎÆÏÒÍÁÃ¦Ñ ÐÒÏ ÓÕͦÓΦÓÔØ"
+
+#: version.c:1205
+msgid "menu Help->Orphans for information "
+msgstr "ÍÅÎÀ Help->Orphans ÐÏÄÁÌØÛÁ ¦ÎÆÏÒÍÁæÑ"
+
+#: version.c:1207
+msgid "Running modeless, typed text is inserted"
+msgstr "ðÒÁÃÀ¤ÍÏ ÂÅÚ ÒÅÖÉͦ×, ÔÅËÓÔ ÝÏ ÎÁÂÒÁÎÏ ×ÓÔÁ×ÌѤÔØÓÑ"
+
+#: version.c:1208
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "ÍÅÎÀ Edit->Global Settings->Toggle Insert Mode "
+
+#: version.c:1209
+msgid " for two modes "
+msgstr " ÄÌÑ Ä×ÏÈ ÒÅÖÉÍ¦× "
+
+#: version.c:1213
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "ÍÅÎÀ Edit->Global Settings->Toggle Vi Compatible"
+
+#: version.c:1214
+#, fuzzy
+msgid " for Vim defaults "
+msgstr " ÄÌÑ Vim defaults "
+
+#: version.c:1260
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "õ÷áçá: ÷É ËÏÒÉÓÔÕ¤ÔÅÓÑ Windows 95/98/ME"
+
+#: version.c:1263
+msgid "type :help windows95<Enter> for info on this"
+msgstr ":help windows95<Enter> ¦ÎÆÏÒÍÁÃ¦Ñ ÐÒÏ ÃÅ "
+
+#: window.c:201
+msgid "E441: There is no preview window"
+msgstr "E441: ÷¦ËÎÏ ÐÅÒÅÇÌÑÄÕ ×¦ÄÓÕÔΤ"
+
+# msgstr "E441: "
+#: window.c:580
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: îÅ ÍÏÖÕ ÒÏÚͦÓÔÉÔÉ ×¦ËÎÏ ÏÄÎÏÞÁÓÎÏ × ÏÂÏÈ ËÕÔÁÈ"
+
+# msgstr "E442: "
+#: window.c:1339
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: îÅ ÍÏÖÕ ÚͦÓÔÉÔÉ ×¦ËÎÏ -- ¦ÎÛ¦ צËÎÁ ÚÁ×ÁÖÁÀÔØ"
+
+# msgstr "E443: "
+#: window.c:1837
+msgid "E444: Cannot close last window"
+msgstr "E444: îÅ ÍÏÖÕ ÚÁËÒÉÔÉ ÏÓÔÁÎΤ צËÎÏ"
+
+# msgstr "E444: "
+#: window.c:2501
+msgid "Already only one window"
+msgstr "ìÉÛÅ ÏÄΊצËÎÏ"
+
+#: window.c:2548
+msgid "E445: Other window contains changes"
+msgstr "E445: ¶ÎÛ¦ צËÎÁ ͦÓÔÑÔØ ÚͦÎÉ"
+
+# msgstr "E445: "
+#: window.c:4375
+msgid "E446: No file name under cursor"
+msgstr "E446: ÷É ÎÅ ÓÔϧÔÅ ÎÁ ¦ÍÅΦ ÆÁÊÌÁ"
+
+# msgstr "E446: "
+#: window.c:4494
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: æÁÊÌ \"%s\" ÎÅ ÚÎÁÊÄÅÎÏ Õ 'path'"
+
+#: ../GvimExt/gvimext.cpp:586
+msgid "Edit with &multiple Vims"
+msgstr "òÅÄÁÇÕ×ÁÔÉ (&m)Ò¦ÚÎÉÍÉ Vim"
+
+#: ../GvimExt/gvimext.cpp:592
+msgid "Edit with single &Vim"
+msgstr "òÅÄÁÇÕ×ÁÔÉ ÏÄÎÉÍ (&V)im"
+
+#: ../GvimExt/gvimext.cpp:604
+msgid "Edit with &Vim"
+msgstr "òÅÄÁÇÕ×ÁÔÉ ÚÁ ÄÏÔÏÍÏÇÏÀ &Vim"
+
+#: ../GvimExt/gvimext.cpp:628
+msgid "Edit with existing Vim - &"
+msgstr "òÅÄÁÇÕ×ÁÔÉ (&e)¦ÓÎÕÀÞÉÍ Vim"
+
+#: ../GvimExt/gvimext.cpp:752
+msgid "Edits the selected file(s) with Vim"
+msgstr "òÅÄÁÇÕ×ÁÔÉ ×ÉÂÒÁΦ ÆÁÊÌÉ ÚÁ ÄÏÐÏÍÏÇÏÀ Vim"
+
+#: ../GvimExt/gvimext.cpp:891 ../GvimExt/gvimext.cpp:969
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "ðÏÍÉÌËÁ ÓÔ×ÏÒÅÎÎÑ ÐÒÏÃÅÓÕ, ÐÅÒÅצÒÔÅ ÞÉ gvim ¤ ÎÁ ÛÌÑÈÕ ÐÏÛÕËÕ!"
+
+#: ../GvimExt/gvimext.cpp:892 ../GvimExt/gvimext.cpp:906
+#: ../GvimExt/gvimext.cpp:970
+msgid "gvimext.dll error"
+msgstr "ÐÏÍÉÌËÁ gvimext.dll"
+
+#: ../GvimExt/gvimext.cpp:905
+msgid "Path length too long!"
+msgstr "ûÌÑÈ ÚÁÎÁÄÎÏ ÄÏ×ÇÉÊ!"
+
+# msgstr "E447: "
+#: globals.h:887
+msgid "--No lines in buffer--"
+msgstr "--öÏÄÎÏÇÏ ÒÑÄËÁ--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1028
+msgid "Command aborted"
+msgstr "ëÏÍÁÎÄÕ ÚÁ×ÅÒÛÅÎÏ"
+
+#: globals.h:1029
+msgid "Argument required"
+msgstr "îÅÏÂȦÄÎÏ ×ËÁÚÁÔÉ ÁÒÇÕÍÅÎÔ"
+
+#: globals.h:1030
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: úÁ \\ ÍÁ¤ ÊÔÉ /, ? ÁÂÏ &"
+
+# msgstr "E10: "
+#: globals.h:1032
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: îÅÐÒÉÐÕÓÔÉÍÏ × ×¦ËΦ ËÏÍÁÎÄ, <CR> ×ÉËÏÎÕ¤, CTRL-C ×ÉÈÏÄÉÔØ"
+
+#: globals.h:1034
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr "E12: ëÏÍÁÎÄÁ ÎÅ ÄÏÚ×ÏÌÅÎÁ Ú Í¦ÒËÕ×ÁÎØ ÂÅÚÐÅËÉ"
+
+#: globals.h:1035
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: æÁÊÌ ¦ÓÎÕ¤ (×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÎÅ Ú×ÁÖÁÔÉ)"
+
+#: globals.h:1036
+msgid "Command failed"
+msgstr "ëÏÍÁÎÄÁ ÎÁ ×ÄÁÌÁÓØ"
+
+#: globals.h:1037
+msgid "Internal error"
+msgstr "÷ÎÕÔÒ¦ÛÎÑ ÐÏÍÉÌËÁ"
+
+#: globals.h:1038
+msgid "Interrupted"
+msgstr "ðÅÒÅÒ×ÁÎÏ"
+
+#: globals.h:1039
+msgid "E14: Invalid address"
+msgstr "E14: îÅצÒÎÁ ÁÄÒÅÓÁ"
+
+# msgstr "E14: "
+#: globals.h:1040
+msgid "Invalid argument"
+msgstr "îÅצÒÎÉÊ ÁÒÇÕÍÅÎÔ"
+
+#: globals.h:1041
+#, c-format
+msgid "Invalid argument: %s"
+msgstr "îÅצÒÎÉÊ ÁÒÇÕÍÅÎÔ %s"
+
+#: globals.h:1043
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: îÅצÒÎÉÊ ×ÉÒÁÚ: %s"
+
+# msgstr "E15: "
+#: globals.h:1045
+msgid "E16: Invalid range"
+msgstr "E16: îÅצÒΦ ÍÅÖ¦"
+
+# msgstr "E16: "
+#: globals.h:1046
+msgid "Invalid command"
+msgstr "îÅצÒÎÁ ËÏÍÁÎÄÁ"
+
+#: globals.h:1048
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" ÃÅ ÄÉÒÅËÔÏÒ¦Ñ"
+
+# msgstr "E17: "
+#: globals.h:1051
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: îÅcÐÏĦ×ÁÎÉÊ ÓÉÍ×ÏÌ ÐÅÒÅÄ '='"
+
+# msgstr "E18: "
+#: globals.h:1053
+msgid "E19: Mark has invalid line number"
+msgstr "E19: ðÏͦÔËÕ ×ËÁÚÁÎÏ Ú ÎÅÍÏÖÌÉ×ÉÍ ÎÏÍÅÒÏÍ ÒÑÄËÁ"
+
+# msgstr "E19: "
+#: globals.h:1054
+msgid "E20: Mark not set"
+msgstr "E20: ðÏͦÔËÕ ÎÅ ×ËÁÚÁÎÏ"
+
+# msgstr "E20: "
+#: globals.h:1055
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: úͦÎÉ ÎÅ ÄÏÚ×ÏÌÅΦ: 'modifiable' ×ÉÍËÎÕÔÏ"
+
+# msgstr "E21: "
+#: globals.h:1056
+msgid "E22: Scripts nested too deep"
+msgstr "E22: úÁÎÁÄÔÏ ×ÅÌÉËÁ ˦ÌØ˦ÓÔØ ×ËÌÁÄÅÎÉÈ ËÏÍÁÎÄÎÉÈ ÆÁÊ̦×"
+
+# msgstr "E22: "
+#: globals.h:1057
+msgid "E23: No alternate file"
+msgstr "E23: îÅÍÁ¤ ×ÔÏÒÉÎÎÏÇÏ ÆÁÊÌÁ"
+
+# msgstr "E23: "
+#: globals.h:1058
+msgid "E24: No such abbreviation"
+msgstr "E24: ôÁËÏÇÏ ÓËÏÒÏÞÅÎÎÑ ÎÅÍÁ¤"
+
+# msgstr "E24: "
+#: globals.h:1059
+msgid "No ! allowed"
+msgstr "ëÏÒÉÓÔÕ×ÁÔÁÔÉÓÑ ! ÎÅ ÄÏÚ×ÏÌÅÎÏ"
+
+#: globals.h:1061
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: GUI ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÏ -- ÎÅ ×צÍËÎÅÎÏ Ð¦Ä ÞÁÓ ËÏÍЦÌÑæ§"
+
+#: globals.h:1064
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr ""
+"E25: Hebrew ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÏ -- ÎÅ ×צÍËÎÅÎÏ Ð¦Ä ÞÁÓ ËÏÍЦÌÑæ§\n"
+
+#: globals.h:1067
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr ""
+"E25: Farsi ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÏ -- ÎÅ ×צÍËÎÅÎÏ Ð¦Ä ÞÁÓ ËÏÍЦÌÑæ§\n"
+
+# msgstr "E25: "
+#: globals.h:1070
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: ëÏÌØÏÒ %s ÎÅ ¦ÓÎÕ¤"
+
+# msgstr "E28: "
+#: globals.h:1072
+msgid "E29: No inserted text yet"
+msgstr "E29: ôÅËÓÔ ÃÅ ÎÅ ÒÅÄÁÇÕ×Á×ÓÑ"
+
+# msgstr "E29: "
+#: globals.h:1073
+msgid "E30: No previous command line"
+msgstr "E30: ëÏÍÁÎÄÉ ÝÅ ÎÅ ×ÉËÏÒÉÓÔÏ×Õ×ÁÌÉÓÑ"
+
+# msgstr "E30: "
+#: globals.h:1074
+msgid "E31: No such mapping"
+msgstr "÷ËÁÚÁΦ ÚÁͦÎÁ ÎÅ ¦ÓÎÕ¤"
+
+# msgstr "E31: "
+#: globals.h:1075
+msgid "No match"
+msgstr "öÏÄÎÏÇÏ ×ÁÒ¦ÁÎÔÕ"
+
+#: globals.h:1076
+#, c-format
+msgid "No match: %s"
+msgstr "öÏÄÎÏÇÏ ×ÁÒ¦ÁÎÔÕ: %s"
+
+#: globals.h:1077
+msgid "E32: No file name"
+msgstr "âÒÁËÕ¤ ¦ÍÅΦ ÆÁÊÌÁ"
+
+# msgstr "E32: "
+#: globals.h:1078
+msgid "E33: No previous substitute regular expression"
+msgstr "úÁͦÎÁ ÚÒÁÚË¦× ÛÅ ÎÅ ×ÉËÏÒÉÓÔÏ×Õ×ÁÌÁÓØ"
+
+# msgstr "E33: "
+#: globals.h:1079
+msgid "E34: No previous command"
+msgstr "ëÏÍÁÎÄÉ ÝÅ ÎÅ ×ÉËÏÒÉÓÔÏ×Õ×ÁÌÉÓÑ"
+
+# msgstr "E34: "
+#: globals.h:1080
+msgid "E35: No previous regular expression"
+msgstr "úÒÁÚËÉ ÝÅ ÎÅ ×ÉËÏÒÉÓÔÏ×Õ×ÁÌÉÓÑ"
+
+# msgstr "E35: "
+#: globals.h:1081
+msgid "No range allowed"
+msgstr "îÅ ÄÏÚ×ÏÌÅÎÏ ×ËÁÚÕ×ÁÔÉ ÍÅÖ¦"
+
+#: globals.h:1083
+msgid "E36: Not enough room"
+msgstr "îÅ ÄÏÓÉÔØ Í¦ÓÃÑ"
+
+# msgstr "E36: "
+#: globals.h:1085
+#, c-format
+msgid "Can't create file %s"
+msgstr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÆÁÊÌ %s"
+
+#: globals.h:1086
+msgid "Can't get temp file name"
+msgstr "îÅ ÍÏÖÕ ÚÆÏÒÍÕ×ÁÔÉ ¦Í'Ñ ÄÌÑ ÔÉÍÞÁÓÏ×ÏÇÏ ÆÁÊÌÁ"
+
+#: globals.h:1087
+#, c-format
+msgid "Can't open file %s"
+msgstr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÆÁÊÌ %s"
+
+#: globals.h:1088
+#, c-format
+msgid "Can't read file %s"
+msgstr "îÅ ÍÏÖÕ ÚÞÉÔÁÔÉ ÆÁÊÌ %s"
+
+#: globals.h:1089
+msgid "E37: No write since last change (use ! to override)"
+msgstr ""
+"E37: öÏÄÎÏÇÏ ÚÁÐÉÓÕ Ð¦ÓÌÑ ÏÓÔÁÎÎØϧ ÚͦÎÉ (×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÎÅ Ú×ÁÖÁÔÉ)"
+
+#: globals.h:1090
+msgid "E38: Null argument"
+msgstr "E38: ÷¦ÄÓÕÔÎ¦Ê ÁÒÇÕÍÅÎÔ"
+
+#: globals.h:1092
+msgid "E39: Number expected"
+msgstr "E39: ïÞ¦ËÕ×ÁÎÏ ÞÉÓÌÏ"
+
+#: globals.h:1095
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÆÁÊÌ ÐÏÍÉÌÏË %s"
+
+#: globals.h:1098
+msgid "E41: Out of memory!"
+msgstr "E41: úÁÂÒÁËÌÏ ÐÁÍ'ÑÔ¦!"
+
+#: globals.h:1101
+msgid "Pattern not found"
+msgstr "úÒÁÚÏË ÎÅ ÚÎÁÊÄÅÎÏ"
+
+#: globals.h:1103
+#, c-format
+msgid "Pattern not found: %s"
+msgstr "úÒÁÚÏË ÎÅ ÚÎÁÊÄÅÎÏ: %s"
+
+#: globals.h:1104
+msgid "Argument must be positive"
+msgstr "áÒÇÕÍÅÎÔ ÍÁ¤ ÂÕÔÉ ÄÏÄÁÔΦÊ"
+
+#: globals.h:1106
+msgid "E42: No Errors"
+msgstr "E42: öÏÄÎϧ ÐÏÍÉÌËÉ"
+
+#: globals.h:1108
+msgid "E43: Damaged match string"
+msgstr "E43: 'match string' ÐÏÛËÏÖÅÎÁ [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#: globals.h:1109
+msgid "E44: Corrupted regexp program"
+msgstr "E44: óÐÏÔ×ÏÒÅÎÁ ÐÒÏÇÒÁÍÁ regexp [ÐÏÍÉÌËÁ ÐÒÏÇÒÁÍÉ]"
+
+#: globals.h:1110
+msgid "E45: 'readonly' option is set (use ! to override)"
+msgstr "E45: ÷ÉÓÔÁ×ÌÅÎÁ ÏÐÃ¦Ñ 'readonly' (×ÉËÏÒÉÓÔÁÊÔÅ ! ÝÏ ÎÅ Ú×ÁÖÁÔÉ)"
+
+#: globals.h:1112
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: úͦÎÎÁ \"%s\" ÍÏÖÅ ÂÕÔÉ ÌÉÛÅ ÐÒÏÞÉÔÁÎÁ"
+
+#: globals.h:1115
+msgid "E47: Error while reading errorfile"
+msgstr "E47: ðÏÍÉÌËÁ ÚÞÉÔÕ×ÁÎÎÑ ÆÁÊÌÁ ÐÏÍÉÌÏË"
+
+#: globals.h:1118
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: îÁ ÄÏÚ×ÏÌÅÎÏ Õ *******"
+
+#: globals.h:1120
+msgid "E49: Invalid scroll size"
+msgstr "E49: îÅÍÏÖÌÉ×ÉÊ ÒÏÚÍ¦Ò ÚÓÕ×Õ"
+
+#: globals.h:1121
+msgid "E91: 'shell' option is empty"
+msgstr "E91: ÏÐÃ¦Ñ 'shell' ÐÏÒÏÖÎÑ"
+
+#: globals.h:1122
+msgid "E72: Close error on swap file"
+msgstr "E72: ðÏÍÉÌËÁ Ð¦Ä ÞÁÓ ÚÁËÒÉÔÔÑ ÆÁÊÌÁ ÏÂͦÎÕ"
+
+#: globals.h:1123
+msgid "E73: tag stack empty"
+msgstr "E73: óÔÅË ÔÏͦÔÏË ÓÐÕÓÔÏÛÅÎÏ"
+
+#: globals.h:1124
+msgid "E74: Command too complex"
+msgstr "E74: úÁÎÁÄÔÏ ÓËÌÁÄÎÁ ËÏÍÁÎÄÁ"
+
+#: globals.h:1125
+msgid "E75: Name too long"
+msgstr "E75: úÁÄÏ×ÇÅ ¦Í'Ñ"
+
+#: globals.h:1126
+msgid "E76: Too many ["
+msgstr "E76: úÁÂÁÇÁÔÏ '['"
+
+#: globals.h:1127
+msgid "E77: Too many file names"
+msgstr "E77: úÁÂÁÇÁÔÏ ¦ÍÅÎ ÆÁÊ̦×"
+
+#: globals.h:1128
+msgid "Trailing characters"
+msgstr "îÁÄÌÉÛËÏצ ÓÉÍ×ÏÌÉ"
+
+#: globals.h:1129
+msgid "E78: Unknown mark"
+msgstr "E78: îÅצÄÏÍÁ ÐÏͦÔËÁ"
+
+#: globals.h:1130
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: îÅ ÍÏÖÕ ÚÒÏÚÕͦÔÉ ÚÒÁÚÏË"
+
+# msgstr "E79: "
+#: globals.h:1131
+msgid "E80: Error while writing"
+msgstr "E80: ðÏÍÉÌËÁ Ð¦Ä ÞÁÓ ÚÁÐÉÓÕ"
+
+#: globals.h:1132
+msgid "Zero count"
+msgstr "îÕÌØÏ×ÉÊ Ì¦ÞÉÌØÎÉË"
+
+#: globals.h:1134
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: <SID> ×ÉËÏÒÉÓÔÏ×Õ¤ÔØÓÑ ÎÅ Õ ÆÁÊ̦ ËÏÍÁÎÄ"
+
+#~ msgid "1 line ~ed"
+#~ msgstr "òÑÄÏË ¦Î×ÅÒÔÏ×ÁÎÏ"
+
+#~ msgid "%ld lines ~ed"
+#~ msgstr "¶Î×ÅÒÔÏ×ÁÎÏ ÒÑÄ˦×: %ld"
+
+#~ msgid "Unable to send reply"
+#~ msgstr "îÅ ÍÏÖÕ ×¦Ä¦ÓÌÁÔÉ ×¦ÄÐÏצÄØ"
+
+#~ msgid ""
+#~ "\n"
+#~ "Send failed. No command server present ?\n"
+#~ msgstr ""
+#~ "\n"
+#~ "îÅ ×ÄÁÌÏÓÑ ×¦Ä¦ÓÌÁÔÉ ÄÁΦ. íÏÖÌÉ×Ï, ÓÅÒ×ÅÒ ËÏÍÁÎÄ ×¦ÄÓÕÔÎ¦Ê ?\n"
+
+#~ msgid "E258: no matches found in cscope connections"
+#~ msgstr "E258: ÎÅ ÚÎÁÊÄÅÎÏ ×¦ÄÐÏצÄÎÏÇÏ Ú'¤ÄÎÁÎÎÑ Ú cscope"
diff --git a/src/po/zh_CN.UTF-8.po b/src/po/zh_CN.UTF-8.po
new file mode 100644
index 000000000..956a82a5c
--- /dev/null
+++ b/src/po/zh_CN.UTF-8.po
@@ -0,0 +1,5937 @@
+# Chinese (simplified) Translation for Vim
+#
+# Do ":help uganda" in Vim to read copying and usage conditions.
+# Do ":help credits" in Vim to see a list of people who contributed.
+#
+# FIRST AUTHOR Wang Jun <junw@turbolinux.com.cn>
+#
+# Original translations.
+#
+#, no-wrap
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim(Simplified Chinese)\n"
+"POT-Creation-Date: 2001-09-24 10:10+0800\n"
+"PO-Revision-Date: 2001-09-24 11:13+0800\n"
+"Last-Translator: Wang Jun <junw@turbolinux.com.cn>\n"
+"Language-Team: Wang Jun <junw@turbolinux.com.cn>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: ä¸èƒ½åˆ†é…任何缓冲区,退出程åº..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: ä¸èƒ½åˆ†é…缓冲区,使用å¦ä¸€ä¸ªç¼“冲区...."
+
+#: buffer.c:698
+msgid "No buffers were unloaded"
+msgstr "没有释放任何缓冲区"
+
+#: buffer.c:700
+msgid "No buffers were deleted"
+msgstr "没有删除任何缓冲区"
+
+#: buffer.c:702
+msgid "No buffers were wiped out"
+msgstr "没有删除任何缓冲区"
+
+#: buffer.c:710
+msgid "1 buffer unloaded"
+msgstr "已释放一个缓冲区"
+
+#: buffer.c:712
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "已释放 %d 个缓冲区"
+
+#: buffer.c:717
+msgid "1 buffer deleted"
+msgstr "已删除一个缓冲区"
+
+#: buffer.c:719
+#, c-format
+msgid "%d buffers deleted"
+msgstr "已删除 %d 个缓冲区"
+
+#: buffer.c:724
+msgid "1 buffer wiped out"
+msgstr "已删除一个缓冲区"
+
+#: buffer.c:726
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "已删除 %d 个缓冲区"
+
+#: buffer.c:783
+msgid "E84: No modified buffer found"
+msgstr "E84: 没有修改过的缓冲区"
+
+#. back where we started, didn't find anything.
+#: buffer.c:822
+msgid "E85: There is no listed buffer"
+msgstr "E85: 没有å¯åˆ—出的缓冲区"
+
+#: buffer.c:834
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: ä¸èƒ½åˆ‡æ¢åˆ°ç¬¬ %ld 个缓冲区"
+
+#: buffer.c:837
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: ä¸èƒ½åˆ‡æ¢åˆ°æ›´åŽé¢çš„缓冲区"
+
+#: buffer.c:839
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: ä¸èƒ½åˆ‡æ¢åˆ°æ›´å‰é¢çš„缓冲区"
+
+#: buffer.c:863
+#, c-format
+msgid "E89: No write since last change for buffer %ld (use ! to override)"
+msgstr "E89: 已更改过缓冲区 %ld 但尚未ä¿å­˜ (å¯ç”¨ ! 强制执行)"
+
+#: buffer.c:879
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: ä¸èƒ½é‡Šæ”¾æœ€åŽä¸€ä¸ªç¼“冲区"
+
+#: buffer.c:1314
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: 警告: 文件å过多"
+
+#: buffer.c:1480
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: 找ä¸åˆ°ç¬¬ %ld 个缓冲区"
+
+#: buffer.c:1700
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: 找到一个以上的 %s"
+
+#: buffer.c:1702
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: 找ä¸åˆ° %s"
+
+#: buffer.c:2105 ex_docmd.c:6065
+#, c-format
+msgid "line %ld"
+msgstr "行 %ld"
+
+#: buffer.c:2188
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: 已有缓冲区使用这个åå­—"
+
+#: buffer.c:2481
+msgid " [Modified]"
+msgstr " [已修改]"
+
+#: buffer.c:2486
+msgid "[Not edited]"
+msgstr "[未编辑]"
+
+#: buffer.c:2491
+msgid "[New file]"
+msgstr "[新文件]"
+
+#: buffer.c:2492
+msgid "[Read errors]"
+msgstr "[读错误]"
+
+#: buffer.c:2494 fileio.c:1754
+msgid "[readonly]"
+msgstr "[åªè¯»]"
+
+#: buffer.c:2510
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "行数 1 --%d%%--"
+
+#: buffer.c:2510
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "行数 %ld --%d%%--"
+
+#: buffer.c:2518
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "行 %ld/%ld --%d%%-- 列 "
+
+#: buffer.c:2606
+msgid "[No file]"
+msgstr "[未命å]"
+
+#. must be a help buffer
+#: buffer.c:2646
+msgid "help"
+msgstr "[帮助]"
+
+#: buffer.c:3151 screen.c:4657
+msgid "[help]"
+msgstr "[帮助]"
+
+#: buffer.c:3183 screen.c:4663
+msgid "[Preview]"
+msgstr "[预览]"
+
+#: buffer.c:3389
+msgid "All"
+msgstr "全部"
+
+#: buffer.c:3389
+msgid "Bot"
+msgstr "底端"
+
+#: buffer.c:3391
+msgid "Top"
+msgstr "顶端"
+
+#: buffer.c:4127
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# 缓冲区列表:\n"
+
+#: buffer.c:4160
+msgid "[Error List]"
+msgstr "[错误列表]"
+
+#: buffer.c:4173 memline.c:1513
+msgid "[No File]"
+msgstr "[未命å]"
+
+#: buffer.c:4393
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- ç¬¦å· ---"
+
+#: buffer.c:4403
+#, c-format
+msgid "Signs for %s:"
+msgstr "%s 的符å·:"
+
+#: buffer.c:4409
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " è¡Œ=%ld id=%d å称=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: ä¸èƒ½æ¯”较(diff) %ld个以上的缓冲区"
+
+#: diff.c:648
+msgid "E97: Cannot create diffs"
+msgstr "E97: ä¸èƒ½åˆ›å»º diff "
+
+#: diff.c:747
+msgid "Patch file"
+msgstr "Patch 文件"
+
+#: diff.c:991
+msgid "E98: Cannot read diff output"
+msgstr "E98: ä¸èƒ½è¯»å– diff 的输出"
+
+#: diff.c:1704
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: ç›®å‰çš„缓冲区ä¸æ˜¯åœ¨ diff 模å¼"
+
+#: diff.c:1716
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: 没有缓冲区在 diff 模å¼"
+
+#: diff.c:1724
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: 有两个以上的缓冲区在 diff 模å¼ï¼Œä¸èƒ½å†³å®šè¦ç”¨å“ªä¸€ä¸ª"
+
+#: diff.c:1747
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: 找ä¸åˆ°ç¼“冲区: \"%s\""
+
+#: diff.c:1753
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: 缓冲区 \"%s\" ä¸æ˜¯åœ¨ diff 模å¼"
+
+#: digraph.c:2168
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: å¤åˆå­—符(digraph)中ä¸èƒ½ä½¿ç”¨ Escape"
+
+#: digraph.c:2340
+msgid "Keymap file not found"
+msgstr "找ä¸åˆ° keymap 文件"
+
+#: digraph.c:2367
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: 使用 :loadkeymap "
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " å…³é”®å­—è‡ªåŠ¨å®Œæˆ (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " ^X æ¨¡å¼ (^E/^Y/^L/^]/^F/^I/^K/^D/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " åŒºåŸŸå…³é”®å­—è‡ªåŠ¨å®Œæˆ (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " æ•´è¡Œè‡ªåŠ¨å®Œæˆ (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " 文件åè‡ªåŠ¨å®Œæˆ (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " æ ‡ç­¾è‡ªåŠ¨å®Œæˆ (^]/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " è·¯å¾„è‡ªåŠ¨å®Œæˆ (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " å®šä¹‰è‡ªåŠ¨å®Œæˆ (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " å­—å…¸è‡ªåŠ¨å®Œæˆ (^K/^N/^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Thesaurus è‡ªåŠ¨å®Œæˆ (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " å‘½ä»¤è‡ªåŠ¨å®Œæˆ (^V/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "已到段è½ç»“å°¾"
+
+#: edit.c:894
+msgid "'thesaurus' option is empty"
+msgstr "选项 'thesaurus' 未设定"
+
+#: edit.c:1070
+msgid "'dictionary' option is empty"
+msgstr "选项 'dictionary' 为空"
+
+#: edit.c:1992
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "扫æå­—å…¸: %s"
+
+#: edit.c:2183
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (æ’å…¥) Scroll (^E/^Y)"
+
+#: edit.c:2185
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (替æ¢) Scroll (^E/^Y)"
+
+#: edit.c:2496
+#, c-format
+msgid "Scanning: %s"
+msgstr "扫æ中: %s"
+
+#: edit.c:2531
+msgid "Scanning tags."
+msgstr "扫æ标签."
+
+#: edit.c:3189
+msgid " Adding"
+msgstr " 增加"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3238
+msgid "-- Searching..."
+msgstr "-- æœå¯»ä¸­..."
+
+#: edit.c:3294
+msgid "Back at original"
+msgstr "回到起点"
+
+#: edit.c:3299
+msgid "Word from other line"
+msgstr "ä»Žå…¶å®ƒè¡Œå¼€å§‹çš„è¯ (?)"
+
+#: edit.c:3304
+msgid "The only match"
+msgstr "åªæœ‰æ­¤é¡¹åŒ¹é…"
+
+#: edit.c:3363
+#, c-format
+msgid "match %d of %d"
+msgstr "找到 %d / %d"
+
+#: edit.c:3366
+#, c-format
+msgid "match %d"
+msgstr "åŒ¹é… %d"
+
+#: eval.c:696
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: 未定义的å˜é‡: \"%s\""
+
+#: eval.c:975
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: 缺少对应的括å·: %s"
+
+#: eval.c:1043
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: æ— æ­¤å˜é‡: \"%s\""
+
+#: eval.c:1284
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: '?' åŽç¼ºå°‘ ':'"
+
+#: eval.c:1898
+msgid "E110: Missing ')'"
+msgstr "E110: 缺少对应的 \")\""
+
+#: eval.c:1948
+msgid "E111: Missing ']'"
+msgstr "E111: 缺少对应的 \"]\""
+
+#: eval.c:2023
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: 缺少选项å称: %s"
+
+#: eval.c:2041
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: ä¸æ­£ç¡®çš„选项: %s"
+
+#: eval.c:2103
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: 缺少引å·: %s"
+
+#: eval.c:2220
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: 缺少引å·: %s"
+
+#: eval.c:2537
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: 函数 %s çš„å‚æ•°ä¸æ­£ç¡®"
+
+#: eval.c:2538
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: 未定义的函数: %s"
+
+#: eval.c:2539
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: 函数 %s çš„å‚数过多"
+
+#: eval.c:2540
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: 函数 %s çš„å‚数太少"
+
+#: eval.c:2541
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: <SID> ä¸èƒ½åœ¨ script 上下文外使用: %s"
+
+#: eval.c:3574
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld 行: "
+
+#: eval.c:4689
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"确定(&O)\n"
+"å–消(&C)"
+
+#: eval.c:5511
+msgid "E240: No connection to Vim server"
+msgstr "E240: 没有与 Vim Server 创建连接"
+
+#: eval.c:5601
+msgid "E277: Unable to read a server reply"
+msgstr "E277: ä¸èƒ½è¯»å–æœåŠ¡å™¨çš„å“应"
+
+#: eval.c:5626
+msgid "E258: Unable to send to client"
+msgstr "E258: ä¸èƒ½ä¼ é€åˆ°å®¢æˆ·ç«¯"
+
+#: eval.c:5667
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: ä¸èƒ½ä¼ é€åˆ° %s"
+
+#: eval.c:5763
+msgid "(Invalid)"
+msgstr "(无效)"
+
+#: eval.c:6766
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: å˜é‡ %s 尚未定义"
+
+#: eval.c:7464
+#, c-format
+msgid "E122: Function %s already exists, use ! to replace"
+msgstr "E122: 函数 %s å·²ç»å­˜åœ¨, 请使用 ! 强制替æ¢"
+
+#: eval.c:7506
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: 函数 %s 尚未定义"
+
+#: eval.c:7519
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: 缺少 \"(\": %s"
+
+#: eval.c:7551
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: å‚æ•°ä¸æ­£ç¡®: %s"
+
+#: eval.c:7637
+msgid "E126: Missing :endfunction"
+msgstr "E126: 缺少 :endfunction"
+
+#: eval.c:7716
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: 函数 %s 正在使用中,ä¸èƒ½é‡æ–°å®šä¹‰"
+
+#: eval.c:7773
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: 函数å称第一个字æ¯å¿…须大写: %s"
+
+#: eval.c:7779
+msgid "E129: Function name required"
+msgstr "E129: 需è¦å‡½æ•°å称"
+
+#: eval.c:7872
+msgid "function "
+msgstr "函数 "
+
+#: eval.c:7987
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: 函数 %s 尚未定义"
+
+#: eval.c:7992
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: 函数 %s 正在使用中,ä¸èƒ½åˆ é™¤"
+
+#: eval.c:8039
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: 函数递归调用层数超过 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:8090
+#, c-format
+msgid "calling %s"
+msgstr "调用 %s"
+
+#. always scroll up, don't overwrite
+#: eval.c:8115 ex_cmds2.c:1973
+#, c-format
+msgid "continuing in %s"
+msgstr "继续: %s"
+
+#: eval.c:8169
+msgid "E133: :return not inside a function"
+msgstr "E133: :return 必须在函数里使用"
+
+#: eval.c:8247
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s 返回值 #%ld "
+
+#: eval.c:8250
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s 返回值 \"%s\""
+
+#: eval.c:8391
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# 全局å˜é‡:\n"
+
+#: ex_cmds2.c:70
+msgid "Entering Debug mode. Type \"cont\" to leave."
+msgstr "进入调试模å¼. 输入 \"cont\" 以回到正常模å¼."
+
+#: ex_cmds2.c:74 ex_docmd.c:771
+#, c-format
+msgid "line %ld: %s"
+msgstr "行 %ld: %s"
+
+#: ex_cmds2.c:76
+#, c-format
+msgid "cmd: %s"
+msgstr "cmd: %s"
+
+#: ex_cmds2.c:224
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "\"%s%s\" 中断点: 第 %ld 行"
+
+#: ex_cmds2.c:388
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: 找ä¸åˆ°ä¸­æ–­ç‚¹: %s"
+
+#: ex_cmds2.c:414
+msgid "No breakpoints defined"
+msgstr "没有定义中断点"
+
+#: ex_cmds2.c:419
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s 第 %ld 行"
+
+#: ex_cmds.c:2053 ex_cmds.c:2289 ex_cmds2.c:602
+msgid "Save As"
+msgstr "å¦å­˜ä¸º"
+
+#: ex_cmds2.c:625
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "将改å˜ä¿å­˜åˆ° \"%.*s\"?"
+
+#: ex_cmds2.c:627 ex_docmd.c:8612
+msgid "Untitled"
+msgstr "未命å"
+
+#: ex_cmds2.c:763
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: 已更改过缓冲区 \"%s\" 但尚未ä¿å­˜ (å¯ç”¨ ! 强制执行)"
+
+#: ex_cmds2.c:832
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "注æ„: 已切æ¢åˆ°å…¶å®ƒç¼“冲区 (请检查 Autocommands 有无错误)"
+
+#: ex_cmds2.c:1208
+msgid "E163: There is only one file to edit"
+msgstr "E163: åªæœ‰ä¸€ä¸ªæ–‡ä»¶å¯ç¼–辑"
+
+#: ex_cmds2.c:1210
+msgid "E164: Cannot go before first file"
+msgstr "E164: å·²ç»åœ¨ç¬¬ä¸€ä¸ªæ–‡ä»¶äº†"
+
+#: ex_cmds2.c:1212
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: å·²ç»åœ¨æœ€åŽä¸€ä¸ªæ–‡ä»¶äº†"
+
+#: ex_cmds2.c:1632
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "查找中: \"%s\" -- \"%s\""
+
+#: ex_cmds2.c:1654
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "查找中: \"%s\""
+
+#: ex_cmds2.c:1678
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "在 'runtimepath' 里找ä¸åˆ° \"%s\""
+
+#: ex_cmds2.c:1712
+msgid "Run Macro"
+msgstr "执行å®"
+
+#: ex_cmds2.c:1817
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "ä¸èƒ½æ‰§è¡Œç›®å½•ï¼š \"%s\""
+
+#: ex_cmds2.c:1847
+#, c-format
+msgid "could not source \"%s\""
+msgstr "ä¸èƒ½æ‰§è¡Œ \"%s\""
+
+#: ex_cmds2.c:1849
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "第 %ld è¡Œ: ä¸èƒ½æ‰§è¡Œ \"%s\""
+
+#: ex_cmds2.c:1863
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "执行 \"%s\" 中"
+
+#: ex_cmds2.c:1865
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "第 %ld è¡Œ: 结æŸæ‰§è¡Œ %s"
+
+#: ex_cmds2.c:1971
+#, c-format
+msgid "finished sourcing %s"
+msgstr "结æŸæ‰§è¡Œ %s"
+
+#: ex_cmds2.c:2272
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: 注æ„: 错误的行分隔字符,å¯èƒ½æ˜¯å°‘了 ^M"
+
+#: ex_cmds2.c:2321
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: 在执行 script 文件外ä¸å¯ä½¿ç”¨ :scriptencoding"
+
+#: ex_cmds2.c:2354
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: 在执行 script 文件外ä¸å¯ä½¿ç”¨ :finish"
+
+#: ex_cmds2.c:2820
+msgid "No text to be printed"
+msgstr "没有è¦æ‰“å°çš„文字"
+
+#: ex_cmds2.c:2898
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "打å°ä¸­: 第 %d 页 (%d%%)"
+
+#: ex_cmds2.c:2907
+#, c-format
+msgid " Copy %d of %d"
+msgstr "å¤åˆ¶ %d / %d"
+
+#: ex_cmds2.c:2959
+#, c-format
+msgid "Printed: %s"
+msgstr "已打å°: %s"
+
+#: ex_cmds2.c:2966
+msgid "Printing aborted"
+msgstr "打å°ä¸­æ–­"
+
+#: ex_cmds2.c:3344
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: 写入 PostScript 文件出错"
+
+#: ex_cmds2.c:4019
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: ä¸èƒ½æ‰“å¼€ PostScript 输出文件"
+
+#: ex_cmds2.c:4057
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: ä¸èƒ½æ‰“开文件 \"%s\""
+
+#: ex_cmds2.c:4068
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: ä¸èƒ½è¯» PostScript 资æºæ–‡ä»¶ \"%s\""
+
+#: ex_cmds2.c:4266
+msgid "Sending to printer..."
+msgstr "å‘é€åˆ°æ‰“å°æœº..."
+
+#: ex_cmds2.c:4270
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: æ‰“å° PostScript 文件失败"
+
+#: ex_cmds2.c:4272
+msgid "Print job sent."
+msgstr ""
+
+#: ex_cmds2.c:4646
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "ç›®å‰çš„ %s语言: \"%s\""
+
+#: ex_cmds2.c:4653
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: ä¸èƒ½è®¾å®šè¯­è¨€ä¸º \"%s\""
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, å六进制 %02x, 八进制 %03o"
+
+#: ex_cmds.c:428
+msgid "E134: Move lines into themselves"
+msgstr "E134: ä¸èƒ½æŠŠè¡Œç§»åˆ°å®ƒè‡ªå·²å†…"
+
+#: ex_cmds.c:497
+msgid "1 line moved"
+msgstr "已移动 1 行"
+
+#: ex_cmds.c:499
+#, c-format
+msgid "%ld lines moved"
+msgstr "å·²æ¬ç§» %ld è¡Œ"
+
+#: ex_cmds.c:890
+#, c-format
+msgid "%ld lines filtered"
+msgstr "å·²å¤„ç† %ld è¡Œ"
+
+#: ex_cmds.c:918
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *Filter* Autocommand ä¸å¯ä»¥æ›´æ”¹ç¼“冲区的内容"
+
+#: ex_cmds.c:1003
+msgid "[No write since last change]\n"
+msgstr "[æ›´æ–°åŽå°šæœªä¿å­˜]\n"
+
+#: ex_cmds.c:1248
+#, c-format
+msgid "viminfo: %s in line: "
+msgstr "viminfo: %s 在行中: "
+
+#: ex_cmds.c:1253
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: 过多错误, 忽略文件其余部分"
+
+#: ex_cmds.c:1282
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "è¯»å– viminfo 文件 \"%s\"%s%s%s"
+
+#: ex_cmds.c:1283
+msgid " info"
+msgstr " ä¿¡æ¯"
+
+#: ex_cmds.c:1284
+msgid " marks"
+msgstr " 标记"
+
+#: ex_cmds.c:1285
+msgid " FAILED"
+msgstr " 失败"
+
+#: ex_cmds.c:1376
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Viminfo 文件ä¸èƒ½å†™å…¥: %s"
+
+#: ex_cmds.c:1501
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: ä¸èƒ½å†™å…¥ viminfo 文件 %s !"
+
+#: ex_cmds.c:1509
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "写入 viminfo 文件 \"%s\" 中"
+
+#. Write the info:
+#: ex_cmds.c:1610
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# viminfo 文件是由 vim %s 所产生.\n"
+
+#: ex_cmds.c:1612
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# 如果想è¦è‡ªè¡Œä¿®æ”¹è¯·ç‰¹åˆ«å°å¿ƒï¼\n"
+"\n"
+
+#: ex_cmds.c:1614
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# 'encoding' 在此文件建立时的值\n"
+
+#: ex_cmds.c:1713
+msgid "Illegal starting char"
+msgstr "无效的å¯åŠ¨å­—符"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2096
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: 您在å¦ä¸€ä¸ªç¼“冲区也加载了这个文件"
+
+#: ex_cmds.c:2130
+msgid "Write partial file?"
+msgstr "è¦å†™å…¥éƒ¨åˆ†æ–‡ä»¶å—?"
+
+#: ex_cmds.c:2137
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: 请使用 ! æ¥å†™å…¥éƒ¨åˆ†ç¼“冲区"
+
+#: ex_cmds.c:2223
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "è¦è¦†ç›–已存在的文件 \"%.*s\"?"
+
+#: ex_cmds.c:2294
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: 缓冲区 %ld 没有文件å"
+
+#: ex_cmds.c:2332
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: 文件未写入,因为 'write' 选项关闭"
+
+#: ex_cmds.c:2352
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"\"%.*s\" 已设定 'readonly' 选项.\n"
+"确定è¦è¦†ç›–å—?"
+
+#: ex_cmds.c:2517
+msgid "Edit File"
+msgstr "编辑文件"
+
+#: ex_cmds.c:3024
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Autocommands æ„外地删除新缓冲区 %s"
+
+#: ex_cmds.c:3156
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: :z ä¸æŽ¥å—éžæ•°å­—çš„å‚æ•°"
+
+#: ex_cmds.c:3241
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: rvim 中ç¦æ­¢ä½¿ç”¨ shell 命令"
+
+#: ex_cmds.c:3348
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: 正则表达å¼ä¸èƒ½ç”¨å­—æ¯åˆ†éš” (?)"
+
+#: ex_cmds.c:3686
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "替æ¢ä¸º %s (y/n/a/q/^E/^Y)?"
+
+#: ex_cmds.c:4050
+msgid "(Interrupted) "
+msgstr "(已中断) "
+
+#: ex_cmds.c:4054
+msgid "1 substitution"
+msgstr "替æ¢ä¸€ç»„"
+
+#: ex_cmds.c:4056
+#, c-format
+msgid "%ld substitutions"
+msgstr "æ›¿æ¢ %ld 组"
+
+#: ex_cmds.c:4059
+msgid " on 1 line"
+msgstr " 一行中"
+
+#: ex_cmds.c:4061
+#, c-format
+msgid " on %ld lines"
+msgstr " %ld 行中"
+
+#: ex_cmds.c:4112
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :global ä¸èƒ½é€’归执行"
+
+#: ex_cmds.c:4147
+msgid "E148: Regular expression missing from global"
+msgstr "E148: æ²¡æœ‰ä½¿ç”¨è¿‡æ­£åˆ™è¡¨è¾¾å¼ (?)"
+
+#: ex_cmds.c:4196
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "æ¯ä¸€è¡Œéƒ½æ‰¾ä¸åˆ°æ¨¡å¼: %s"
+
+#: ex_cmds.c:4277
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# å‰ä¸€ç»„替代字符串:\n"
+"$"
+
+#: ex_cmds.c:4376
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: 抱歉, 没有 %s 的说明"
+
+#: ex_cmds.c:4410
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "抱歉, 找ä¸åˆ°å¸®åŠ©æ–‡ä»¶ \"%s\""
+
+#: ex_cmds.c:4856
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s ä¸æ˜¯ç›®å½•"
+
+#: ex_cmds.c:4884
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: ä¸èƒ½ä»¥å†™å…¥æ¨¡å¼æ‰“å¼€ \"%s\""
+
+#: ex_cmds.c:4898
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: ä¸èƒ½è¯»å–文件: %s"
+
+#: ex_cmds.c:4977
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: 标签(tag) \"%s\" 在文件 %s 里é‡å¤å‡ºçŽ°å¤šæ¬¡"
+
+#: ex_cmds.c:5078
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: 未定义的 sign command: %s"
+
+#: ex_cmds.c:5098
+msgid "E156: Missing sign name"
+msgstr "E156: 缺少 sign å称"
+
+#: ex_cmds.c:5144
+msgid "E255: Too many signs defined"
+msgstr "E326: 找到太多 signs"
+
+#: ex_cmds.c:5186
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: ä¸æ­£ç¡®çš„ sign 文字: %s"
+
+#: ex_cmds.c:5210 ex_cmds.c:5396
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: ä¸æ­£ç¡®çš„ sign: %s"
+
+#: ex_cmds.c:5256
+msgid "E159: Missing sign number"
+msgstr "E159: 缺少 sign number"
+
+#: ex_cmds.c:5336
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: 缓冲区å称错误: %s"
+
+#: ex_cmds.c:5375
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Sign ID 错误: %ld"
+
+#: ex_cmds.c:5546
+msgid "[Deleted]"
+msgstr "[已删除]"
+
+#: ex_docmd.c:491
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "进入 Ex 模å¼. 输入 \"visua\" 以回到正常模å¼."
+
+#. must be at EOF
+#: ex_docmd.c:527
+msgid "At end-of-file"
+msgstr "已到文件结尾"
+
+#: ex_docmd.c:602
+msgid "E169: Command too recursive"
+msgstr "E169: 命令递归层数过多"
+
+#: ex_docmd.c:911
+msgid "E170: Missing :endwhile"
+msgstr "E170: 缺少 :endwhile"
+
+#: ex_docmd.c:913
+msgid "E171: Missing :endif"
+msgstr "E171: 缺少 :endif"
+
+#: ex_docmd.c:923
+msgid "End of sourced file"
+msgstr "命令文件结æŸ"
+
+#: ex_docmd.c:924
+msgid "End of function"
+msgstr "函数结尾"
+
+#: ex_docmd.c:1344
+msgid "Ambiguous use of user-defined command"
+msgstr "用户定义的命令会混淆"
+
+#: ex_docmd.c:1358
+msgid "Not an editor command"
+msgstr "ä¸æ˜¯ç¼–辑器的命令"
+
+#: ex_docmd.c:1441
+msgid "Don't panic!"
+msgstr "ä¸è¦æƒŠæ…Œ!"
+
+#: ex_docmd.c:1460
+msgid "Backwards range given"
+msgstr "指定了å‘å‰å‚考的范围"
+
+#: ex_docmd.c:1469
+msgid "Backwards range given, OK to swap"
+msgstr "指定了å‘å‰å‚考的范围,OK to swap"
+
+#: ex_docmd.c:1580
+msgid "Use w or w>>"
+msgstr "请使用 w 或 w>>"
+
+#: ex_docmd.c:3086
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: 抱歉, 本命令在此版本中未实现"
+
+#: ex_docmd.c:3256
+msgid "E172: Only one file name allowed"
+msgstr "E172: åªèƒ½æœ‰ä¸€ä¸ªæ–‡ä»¶å"
+
+#: ex_docmd.c:3810
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "还有 %d 个文件未编辑. 确定è¦é€€å‡ºï¼Ÿ"
+
+#: ex_docmd.c:3817
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: 还有 %ld 个文件未编辑"
+
+#: ex_docmd.c:3911
+msgid "E174: Command already exists: use ! to redefine"
+msgstr "E174: 命令已ç»å­˜åœ¨, 请使用 ! 强制é‡æ–°å®šä¹‰"
+
+#: ex_docmd.c:4016
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" å称 å‚æ•° 范围 完整 定义 "
+
+#: ex_docmd.c:4105
+msgid "No user-defined commands found"
+msgstr "找ä¸åˆ°ç”¨æˆ·è‡ªå®šä¹‰çš„命令"
+
+#: ex_docmd.c:4136
+msgid "E175: No attribute specified"
+msgstr "E175: 没有指定的属性"
+
+#: ex_docmd.c:4188
+msgid "E176: Invalid number of arguments"
+msgstr "E176: ä¸æ­£ç¡®çš„å‚数个数"
+
+#: ex_docmd.c:4203
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: ä¸èƒ½æŒ‡å®šä¸¤æ¬¡"
+
+#: ex_docmd.c:4213
+msgid "E178: Invalid default value for count"
+msgstr "E178: 计数的缺çœå€¼ä¸æ­£ç¡®"
+
+#: ex_docmd.c:4241
+msgid "E179: argument required for complete"
+msgstr "E179: 指令需è¦å‚æ•°æ‰èƒ½å®Œæˆ"
+
+#: ex_docmd.c:4260
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: ä¸å®Œæ•´çš„值: '%s'"
+
+#: ex_docmd.c:4268
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: ä¸æ­£ç¡®çš„属性: %s"
+
+#: ex_docmd.c:4309
+msgid "E182: Invalid command name"
+msgstr "E182: 命令å称ä¸æ­£ç¡®"
+
+#: ex_docmd.c:4324
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: 用户自定义命令必须以大写字æ¯å¼€å§‹"
+
+#: ex_docmd.c:4393
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: 没有用户自定义的命令: %s"
+
+#: ex_docmd.c:4844
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: 找ä¸åˆ°é¢œè‰²æ ·å¼ %s"
+
+#: ex_docmd.c:4852
+msgid "Greetings, Vim user!"
+msgstr "你好, Vim 用户ï¼"
+
+#: ex_docmd.c:5549
+msgid "Edit File in new window"
+msgstr "在新窗å£ç¼–辑文件"
+
+#: ex_docmd.c:5815
+msgid "No swap file"
+msgstr "无交æ¢æ–‡ä»¶"
+
+#: ex_docmd.c:5919
+msgid "Append File"
+msgstr "附加文件"
+
+#: ex_docmd.c:5978
+msgid "E186: No previous directory"
+msgstr "E186: å‰ä¸€ä¸ªç›®å½•ä¸å­˜åœ¨"
+
+#: ex_docmd.c:6055
+msgid "E187: Unknown"
+msgstr "E187: ä¸èƒ½è¯†åˆ«çš„标记"
+
+#: ex_docmd.c:6173
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "窗å£ä½ç½®: X %d, Y %d"
+
+#: ex_docmd.c:6178
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: 在您的平å°ä¸Šä¸èƒ½èŽ·å¾—窗å£ä½ç½®"
+
+#: ex_docmd.c:6444
+msgid "Save Redirection"
+msgstr "ä¿å­˜é‡å®šå‘"
+
+#: ex_docmd.c:6593
+msgid "Save View"
+msgstr "ä¿å­˜è§†å›¾"
+
+#: ex_docmd.c:6594
+msgid "Save Session"
+msgstr "ä¿å­˜ä¼šè¯"
+
+#: ex_docmd.c:6596
+msgid "Save Setup"
+msgstr "ä¿å­˜è®¾å®š"
+
+#: ex_docmd.c:6745
+#, c-format
+msgid "E189: \"%s\" exists (use ! to override)"
+msgstr "E189: \"%s\" 已存在 (请用 ! 强制执行)"
+
+#: ex_docmd.c:6750
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: ä¸èƒ½ä»¥å†™å…¥æ¨¡å¼æ‰“å¼€ \"%s\""
+
+#. set mark
+#: ex_docmd.c:6774
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: å‚数必须是英文字æ¯æˆ–å‘å‰/åŽçš„引å·"
+
+#: ex_docmd.c:6803
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: :normal 递归层数过深"
+
+#: ex_docmd.c:7171
+msgid ":if nesting too deep"
+msgstr ":if 层数过深"
+
+#: ex_docmd.c:7206
+msgid ":endif without :if"
+msgstr ":endif 缺少对应的 :if"
+
+#: ex_docmd.c:7226
+msgid ":else without :if"
+msgstr ":else 缺少对应的 :if"
+
+#: ex_docmd.c:7228
+msgid ":elseif without :if"
+msgstr ":elseif 缺少对应的 :if"
+
+#: ex_docmd.c:7280
+msgid ":while nesting too deep"
+msgstr ":while 层数过深"
+
+#: ex_docmd.c:7326
+msgid ":continue without :while"
+msgstr ":continue 缺少对应的 :while"
+
+#: ex_docmd.c:7353
+msgid ":break without :while"
+msgstr ":break 缺少对应的 :while"
+
+#: ex_docmd.c:7376 ex_docmd.c:7381
+msgid ":endwhile without :while"
+msgstr ":endwhile 缺少对应的 :while"
+
+#: ex_docmd.c:7402
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction 必须在函数内部使用"
+
+#: ex_docmd.c:7582
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: 没有 '#' å¯æ›¿ä»£çš„文件å"
+
+#: ex_docmd.c:7613
+msgid "no autocommand file name to substitute for \"<afile>\""
+msgstr "没有 Autocommand 文件åä»¥æ›¿æ¢ \"<afile>\""
+
+#: ex_docmd.c:7621
+msgid "no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "没有 Autocommand 缓冲区åç§°ä»¥æ›¿æ¢ \"<abuf>\""
+
+#: ex_docmd.c:7632
+msgid "no autocommand match name to substitute for \"<amatch>\""
+msgstr "没有 Autocommand Match name ä»¥æ›¿æ¢ \"<amatch>\""
+
+#: ex_docmd.c:7642
+msgid "no :source file name to substitute for \"<sfile>\""
+msgstr "没有 :source 文件åä»¥æ›¿æ¢ \"<sfile>\""
+
+#: ex_docmd.c:7683
+#, no-c-format
+msgid "Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "'%' 或 '#' 指å‘空文件å,åªèƒ½ç”¨æ–¼ \":p:h\""
+
+#: ex_docmd.c:7685
+msgid "Evaluates to an empty string"
+msgstr "输入为空字符串"
+
+#: ex_docmd.c:8594
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: ä¸èƒ½è¯»å– viminfo"
+
+#: ex_docmd.c:8767
+msgid "E196: No digraphs in this version"
+msgstr "E196: 本版本无å¤åˆå­—符(digraph)"
+
+#: ex_getln.c:2785
+msgid "tagname"
+msgstr "标签å称"
+
+#: ex_getln.c:2788
+msgid " kind file\n"
+msgstr "类文件\n"
+
+#: ex_getln.c:3997
+msgid "'history' option is zero"
+msgstr "选项 'history' 是零"
+
+#: ex_getln.c:4237
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s 历å²è®°å½• (从新到旧):\n"
+
+#: ex_getln.c:4238
+msgid "Command Line"
+msgstr "命令行"
+
+#: ex_getln.c:4239
+msgid "Search String"
+msgstr "查找字符串"
+
+#: ex_getln.c:4240
+msgid "Expression"
+msgstr "表达å¼"
+
+#: ex_getln.c:4241
+msgid "Input Line"
+msgstr "输入行"
+
+#: ex_getln.c:4271
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar 超过命令长度"
+
+#: ex_getln.c:4435
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: 已删除活动窗å£æˆ–缓存"
+
+#: fileio.c:347
+msgid "Illegal file name"
+msgstr "ä¸æ­£ç¡®çš„文件å"
+
+#: fileio.c:371 fileio.c:495 fileio.c:2491 fileio.c:2529
+msgid "is a directory"
+msgstr "是目录"
+
+#: fileio.c:373
+msgid "is not a file"
+msgstr "ä¸æ˜¯æ–‡ä»¶"
+
+#: fileio.c:515 fileio.c:3581
+msgid "[New File]"
+msgstr "[未命å]"
+
+#: fileio.c:532
+msgid "[Permission Denied]"
+msgstr "[æƒé™ä¸è¶³]"
+
+#: fileio.c:624
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre Autocommand 使程åºä¸èƒ½è¯»å–此文件"
+
+#: fileio.c:626
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *Filter* Autocommand ä¸å¯ä»¥æ›´æ”¹ç¼“冲区的内容"
+
+#: fileio.c:646
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: 从标准输入读å–...\n"
+
+#: fileio.c:652
+msgid "Reading from stdin..."
+msgstr "从标准输入读..."
+
+#. Re-opening the original file failed!
+#: fileio.c:876
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: 转æ¢é”™è¯¯"
+
+#: fileio.c:1732
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:1739
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:1746
+msgid "[socket]"
+msgstr "[socket]"
+
+#: fileio.c:1754
+msgid "[RO]"
+msgstr "[åªè¯»]"
+
+#: fileio.c:1764
+msgid "[CR missing]"
+msgstr "[缺少CR]'"
+
+#: fileio.c:1769
+msgid "[NL found]"
+msgstr "[找到NL]"
+
+#: fileio.c:1774
+msgid "[long lines split]"
+msgstr "[分割过长行]"
+
+#: fileio.c:1780 fileio.c:3565
+msgid "[NOT converted]"
+msgstr "[未转æ¢]"
+
+#: fileio.c:1785 fileio.c:3570
+msgid "[converted]"
+msgstr "[已转æ¢]"
+
+#: fileio.c:1792 fileio.c:3595
+msgid "[crypted]"
+msgstr "[已加密]"
+
+#: fileio.c:1799
+msgid "[CONVERSION ERROR]"
+msgstr "转æ¢é”™è¯¯"
+
+#: fileio.c:1806
+msgid "[READ ERRORS]"
+msgstr "[读错误]"
+
+#: fileio.c:2013
+msgid "Can't find temp file for conversion"
+msgstr "找ä¸åˆ°è½¬æ¢ç”¨çš„临时文件"
+
+#: fileio.c:2020
+msgid "Conversion with 'charconvert' failed"
+msgstr "字符集转æ¢é”™è¯¯"
+
+#: fileio.c:2023
+msgid "can't read output of 'charconvert'"
+msgstr "ä¸èƒ½è¯»å– 'charconvert' 的输出"
+
+#: fileio.c:2407
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Autocommand 删除或释放了è¦å†™å…¥çš„缓冲区"
+
+#: fileio.c:2430
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Autocommand æ„外地改å˜äº†è¡Œå·"
+
+#: fileio.c:2496 fileio.c:2513
+msgid "is not a file or writable device"
+msgstr "ä¸æ˜¯æ–‡ä»¶æˆ–å¯å†™çš„设备"
+
+#: fileio.c:2555
+msgid "is read-only (use ! to override)"
+msgstr "是åªè¯»æ–‡ä»¶ (请使用 ! 强制执行)"
+
+#: fileio.c:2851
+msgid "Can't write to backup file (use ! to override)"
+msgstr "ä¸èƒ½å†™å¤‡ä»½æ–‡ä»¶ (请使用 ! 强制执行)"
+
+#: fileio.c:2863
+msgid "Close error for backup file (use ! to override)"
+msgstr "关闭备份文件出错 (请使用 ! 强制执行)"
+
+#: fileio.c:2865
+msgid "Can't read file for backup (use ! to override)"
+msgstr "ä¸èƒ½è¯»å–文件以供备份 (请使用 ! 强制执行)"
+
+#: fileio.c:2881
+msgid "Cannot create backup file (use ! to override)"
+msgstr "ä¸èƒ½åˆ›å»ºå¤‡ä»½æ–‡ä»¶ (请使用 ! 强制执行)"
+
+#: fileio.c:2970
+msgid "Can't make backup file (use ! to override)"
+msgstr "ä¸èƒ½ä½œå¤‡ä»½æ–‡ä»¶ (请使用 ! 强制执行)"
+
+#: fileio.c:3032
+msgid "The resource fork will be lost (use ! to override)"
+msgstr "Resource fork 会消失 (请使用 ! 强制执行)"
+
+#: fileio.c:3121
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: 找ä¸åˆ°å†™å…¥ç”¨çš„交æ¢æ–‡ä»¶"
+
+#: fileio.c:3139
+msgid "E213: Cannot convert (use ! to write without conversion)"
+msgstr "E213: ä¸èƒ½è½¬æ¢ (请使用 ! 强制ä¸è½¬æ¢å†™å…¥)"
+
+#: fileio.c:3176
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: ä¸èƒ½ä»¥å†™å…¥æ¨¡å¼æ‰“开链接文件"
+
+#: fileio.c:3180
+msgid "E212: Can't open file for writing"
+msgstr "E212: ä¸èƒ½ä»¥å†™å…¥æ¨¡å¼æ‰“å¼€"
+
+#: fileio.c:3423
+msgid "Close failed"
+msgstr "关闭失败"
+
+#: fileio.c:3481
+msgid "write error, conversion failed"
+msgstr "ä¸èƒ½å†™å…¥ -- 转æ¢å¤±è´¥"
+
+#: fileio.c:3487
+msgid "write error (file system full?)"
+msgstr "写入错误 (文件系统已满?)"
+
+#: fileio.c:3560
+msgid " CONVERSION ERROR"
+msgstr "转æ¢é”™è¯¯"
+
+#: fileio.c:3576
+msgid "[Device]"
+msgstr "[设备]"
+
+#: fileio.c:3581
+msgid "[New]"
+msgstr "[æ–°]"
+
+#: fileio.c:3603
+msgid " [a]"
+msgstr "[a]"
+
+#: fileio.c:3603
+msgid " appended"
+msgstr " 已附加"
+
+#: fileio.c:3605
+msgid " [w]"
+msgstr "[w]"
+
+#: fileio.c:3605
+msgid " written"
+msgstr " 已写入"
+
+#: fileio.c:3655
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: Patch 模å¼: ä¸èƒ½å‚¨å­˜åŽŸå§‹æ–‡ä»¶"
+
+#: fileio.c:3677
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: Patch 模å¼: ä¸èƒ½æ”¹å˜ç©ºçš„原始文件"
+
+#: fileio.c:3692
+msgid "E207: Can't delete backup file"
+msgstr "E207: ä¸èƒ½åˆ é™¤å¤‡ä»½æ–‡ä»¶"
+
+#: fileio.c:3744
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"警告: 原始文件丢失或æŸå\n"
+
+#: fileio.c:3746
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "在文件正确写入å‰è¯·å‹¿é€€å‡ºç¼–辑器!"
+
+#: fileio.c:3826
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:3826
+msgid "[dos format]"
+msgstr "[dos æ ¼å¼]"
+
+#: fileio.c:3833
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:3833
+msgid "[mac format]"
+msgstr "[mac æ ¼å¼]"
+
+#: fileio.c:3840
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:3840
+msgid "[unix format]"
+msgstr "[unix æ ¼å¼]"
+
+#: fileio.c:3867
+msgid "1 line, "
+msgstr "1 行, "
+
+#: fileio.c:3869
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld 行, "
+
+#: fileio.c:3872
+msgid "1 character"
+msgstr "一个字符"
+
+#: fileio.c:3874
+#, c-format
+msgid "%ld characters"
+msgstr "%ld个字符"
+
+#: fileio.c:3884
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:3884
+msgid "[Incomplete last line]"
+msgstr "[最åŽä¸€è¡Œä¸å®Œæ•´]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:3903
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "警告: 本文件自上次读入åŽå·²å˜åŠ¨!!!"
+
+#: fileio.c:3905
+msgid "Do you really want to write to it"
+msgstr "确定è¦å†™å…¥å—"
+
+#: fileio.c:4861
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: 写入文件 \"%s\" 错误"
+
+#: fileio.c:4868
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: 关闭文件 \"%s\" 错误"
+
+#: fileio.c:4871
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: 读å–文件 \"%s\" 错误"
+
+#: fileio.c:5035
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: FileChangedShell autocommand 删除缓冲区"
+
+#: fileio.c:5043
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: 警告: 文件 \"%s\" å·²ç»ä¸å­˜åœ¨"
+
+#: fileio.c:5056
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr "W12: 警告: 文件 \"%s\" 自上次读入åŽå·²å˜åŠ¨, 而且编辑中的缓冲区也更动了"
+
+#: fileio.c:5059
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: 警告: 文件 \"%s\" 自上次读入åŽå·²æ”¹å˜"
+
+#: fileio.c:5061
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: 警告: 文件 \"%s\" 自上次读入åŽå·²æ”¹å˜"
+
+#: fileio.c:5071
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: 警告: 文件 \"%s\" 在开始编辑åŽåˆè¢«åˆ›å»ºäº†"
+
+#: fileio.c:5088
+msgid "Warning"
+msgstr "警告"
+
+#: fileio.c:5089
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"确定(&O)\n"
+"加载文件(&L)"
+
+#: fileio.c:5165
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: ä¸èƒ½é‡æ–°åŠ è½½ \"%s\""
+
+#: fileio.c:5670
+msgid "--Deleted--"
+msgstr "--已删除--"
+
+#. the group doesn't exist
+#: fileio.c:5830
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: 组ä¸å­˜åœ¨: \"%s\""
+
+#: fileio.c:5955
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: * åŽé¢æœ‰ä¸æ­£ç¡®çš„字符: %s"
+
+#: fileio.c:5966
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: 无此事件: %s"
+
+#. Highlight title
+#: fileio.c:6115
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Auto-Commands ---"
+
+#: fileio.c:6386
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: ä¸èƒ½å¯¹æ‰€æœ‰äº‹ä»¶æ‰§è¡Œ autocommand"
+
+#: fileio.c:6409
+msgid "No matching autocommands"
+msgstr "找ä¸åˆ°å¯¹åº”çš„ autocommand"
+
+#: fileio.c:6681
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: autocommand 层数过深"
+
+#: fileio.c:6968
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Auto commands: \"%s\""
+
+#: fileio.c:6976
+#, c-format
+msgid "Executing %s"
+msgstr "执行 %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7044
+#, c-format
+msgid "autocommand %s"
+msgstr "autocommand %s"
+
+#: fileio.c:7566
+msgid "E219: Missing {."
+msgstr "E219: 缺少 {."
+
+#: fileio.c:7568
+msgid "E220: Missing }."
+msgstr "E220: 缺少 }."
+
+#: fold.c:66
+msgid "No fold found"
+msgstr "找ä¸åˆ°ä»»ä½• fold"
+
+#: fold.c:554
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: ä¸èƒ½åœ¨ç›®å‰çš„ 'foldmethod' 下创建 fold"
+
+#: fold.c:556
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: ä¸èƒ½åœ¨ç›®å‰çš„ 'foldmethod' 下删除 fold"
+
+#: fold.c:1700
+msgid "E221: 'commentstring' is empty"
+msgstr "E221: 选项 'commentstring' 未设定"
+
+#: getchar.c:268
+msgid "E222: Add to read buffer"
+msgstr "E222: 加入读缓冲中"
+
+#: getchar.c:2114
+msgid "E223: recursive mapping"
+msgstr "E223: 递归 mapping"
+
+#: getchar.c:2966
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: %s å·²ç»æœ‰å…¨å±€ abbreviation 了"
+
+#: getchar.c:2969
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: %s å·²ç»æœ‰å…¨å±€ mapping 了"
+
+#: getchar.c:3096
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: %s å·²ç»æœ‰ abbreviation 了"
+
+#: getchar.c:3099
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: %s çš„ mapping å·²ç»å­˜åœ¨"
+
+#: getchar.c:3163
+msgid "No abbreviation found"
+msgstr "找ä¸åˆ°ç¼©å†™"
+
+#: getchar.c:3165
+msgid "No mapping found"
+msgstr "没有这个对应"
+
+#: getchar.c:3990
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: ä¸æ­£ç¡®çš„模å¼"
+
+#: gui_at_fs.c:290
+msgid "<cannot open> "
+msgstr "<ä¸èƒ½æ‰“å¼€>"
+
+#: gui_at_fs.c:1115
+#, c-format
+msgid "vim_SelFile: can't get font %s"
+msgstr "vim_SelFile: ä¸èƒ½ä½¿ç”¨ %s 字体"
+
+#: gui_at_fs.c:2535
+msgid "vim_SelFile: can't return to current directory"
+msgstr "vim_SelFile: ä¸èƒ½å›žåˆ°ç›®å‰ç›®å½•"
+
+#: gui_at_fs.c:2554
+msgid "Pathname:"
+msgstr "路径:"
+
+#: gui_at_fs.c:2560
+msgid "vim_SelFile: can't get current directory"
+msgstr "vim_SelFile: ä¸èƒ½å–å¾—ç›®å‰ç›®å½•"
+
+#: gui_at_fs.c:2568 gui_motif.c:1607
+msgid "OK"
+msgstr "确定"
+
+#. 'Cancel' button
+#: gui_at_fs.c:2568 gui_gtk.c:1683 gui_motif.c:1602 gui_motif.c:2823
+msgid "Cancel"
+msgstr "å–消"
+
+#: gui_athena.c:1928 gui_motif.c:1855
+msgid "Vim dialog"
+msgstr "Vim 对è¯æ¡†"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "滚动æ¡: ä¸èƒ½è®¾å®š thumb pixmap çš„ä½ç½®"
+
+#: gui_beval.c:68
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: ä¸èƒ½å¯¹ä¿¡æ¯ä¸Ž callback 创建 BallonEval"
+
+#: gui.c:181
+msgid "E229: Cannot start the GUI"
+msgstr "E229: ä¸èƒ½å¯åŠ¨å›¾åž‹ç•Œé¢"
+
+#: gui.c:306
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: ä¸èƒ½è¯»å–文件 \"%s\""
+
+#: gui.c:431
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: ä¸æ­£ç¡®çš„ 'guifontwide'"
+
+#: gui.c:3919
+msgid "Error"
+msgstr "错误"
+
+#: gui.c:3920
+msgid "&Ok"
+msgstr "确定(&O)"
+
+#: gui_gtk.c:1144
+msgid "Vim dialog..."
+msgstr "Vim 对è¯æ¡†..."
+
+#: gui_gtk.c:1519 gui_motif.c:2742
+msgid "VIM - Search and Replace..."
+msgstr "VIM - 查找与替æ¢..."
+
+#: gui_gtk.c:1524 gui_motif.c:2744
+msgid "VIM - Search..."
+msgstr "VIM - 查找..."
+
+#: gui_gtk.c:1547 gui_motif.c:2862
+msgid "Find what:"
+msgstr "查找:"
+
+#: gui_gtk.c:1565 gui_motif.c:2894
+msgid "Replace with:"
+msgstr "替æ¢ä¸º:"
+
+#. exact match only button
+#: gui_gtk.c:1597 gui_motif.c:2996
+msgid "Match exact word only"
+msgstr "åªåŒ¹é…完全相åŒçš„å­—"
+
+#: gui_gtk.c:1609 gui_motif.c:2964
+msgid "Direction"
+msgstr "æ–¹å‘"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:1621 gui_motif.c:2976
+msgid "Up"
+msgstr "å‘上"
+
+#: gui_gtk.c:1625 gui_motif.c:2984
+msgid "Down"
+msgstr "å‘下"
+
+#. 'Find Next' button
+#: gui_gtk.c:1647 gui_motif.c:2766
+msgid "Find Next"
+msgstr "找下一个"
+
+#. 'Replace' button
+#: gui_gtk.c:1664 gui_motif.c:2783
+msgid "Replace"
+msgstr "替æ¢"
+
+#. 'Replace All' button
+#: gui_gtk.c:1673 gui_motif.c:2796
+msgid "Replace All"
+msgstr "替æ¢å…¨éƒ¨"
+
+#: gui_gtk_x11.c:1076 gui_x11.c:1194
+msgid "E233: cannot open display"
+msgstr "E233: <ä¸èƒ½æ‰“å¼€ X Server DISPLAY>"
+
+#: gui_gtk_x11.c:2433 gui_x11.c:1997
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: ä¸æ­£ç¡®çš„字符集 (Fontset): %s"
+
+#: gui_gtk_x11.c:2460
+msgid "Font Selection"
+msgstr "字体选择"
+
+#: gui_gtk_x11.c:2702 gui_mac.c:2780 gui_w48.c:1197 gui_x11.c:1833
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "ä¸æ­£ç¡®çš„字体å称: %s"
+
+#: gui_gtk_x11.c:2713 gui_x11.c:1857
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: \"%s\" ä¸æ˜¯å›ºå®šå®½åº¦å­—体"
+
+#: gui_gtk_x11.c:2843
+#, c-format
+msgid "E242: Color name not recognized: %s"
+msgstr "E242: %s 为ä¸èƒ½è¯†åˆ«çš„颜色å称"
+
+#: gui_gtk_x11.c:3519 ui.c:1929
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "使用 CUT_BUFFER0 æ¥æ›¿æ¢ç©ºé€‰æ‹©"
+
+#: gui_motif.c:1601 gui_motif.c:1604
+msgid "Filter"
+msgstr "过滤器"
+
+#: gui_motif.c:1603
+msgid "Directories"
+msgstr "目录"
+
+#: gui_motif.c:1605
+msgid "Help"
+msgstr "帮助"
+
+#: gui_motif.c:1606
+msgid "Files"
+msgstr "文件"
+
+#: gui_motif.c:1608
+msgid "Selection"
+msgstr "选择"
+
+#: gui_motif.c:2809
+msgid "Undo"
+msgstr "撤消"
+
+#: gui_riscos.c:951
+#, c-format
+msgid "E235: Can't load Zap font '%s'"
+msgstr "E235: ä¸èƒ½æ‰“å¼€ Zap 字体 '%s'"
+
+#: gui_riscos.c:1047
+#, c-format
+msgid "E235: Can't use font %s"
+msgstr "E235: ä¸èƒ½ä½¿ç”¨å­—体 %s"
+
+#: gui_riscos.c:1167
+#, c-format
+msgid "E242: Missing color: %s"
+msgstr "E242: 找ä¸åˆ°é¢œè‰²: %s"
+
+#: gui_riscos.c:3269
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"正在å‘é€ä¸­æ–­å­ç¨‹åºçš„ä¿¡æ¯.\n"
+
+#: gui_w32.c:823
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: ä¸æ”¯æŒå‚æ•° \"-%s\"。请用 OLE 版本。"
+
+#: gui_w48.c:2068
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "查找字符串 (使用 '\\\\' æ¥è¡¨ç¤º '\\')"
+
+#: gui_w48.c:2093
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "查找åŠæ›¿æ¢å­—符串 (使用 '\\\\' æ¥è¡¨ç¤º '\\')"
+
+#: gui_x11.c:1414
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr "Vim E458: ä¸èƒ½é…ç½® color map 对象,有些颜色看起æ¥ä¼šæ€ªæ€ªçš„"
+
+#: gui_x11.c:1987
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: Fontset %s 没有设定正确的字体以供显示这些字符集:"
+
+#: gui_x11.c:2030
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: 字体集(Fontset)å称: %s"
+
+#: gui_x11.c:2031
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "'%s' ä¸æ˜¯å›ºå®šå®½åº¦å­—体"
+
+#: gui_x11.c:2050
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: 字体集(Fontset)å称: %s\n"
+
+#: gui_x11.c:2051
+#, c-format
+msgid "Font0: %s\n"
+msgstr "字体0: %s\n"
+
+#: gui_x11.c:2052
+#, c-format
+msgid "Font1: %s\n"
+msgstr "字体1: %s\n"
+
+#: gui_x11.c:2053
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "字体%d宽度ä¸æ˜¯å­—体0的两å€\n"
+
+#: gui_x11.c:2054
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "字体0的宽度:%ld\n"
+
+#: gui_x11.c:2055
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"字体1宽度: %ld\n"
+"\n"
+
+#: gui_x11.c:2201
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: ä¸èƒ½é…置颜色 %s"
+
+#: gui_x11.c:3250
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: ä¸èƒ½è¯»å– sign data!"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: Hangul automata 错误"
+
+#: if_cscope.c:26
+#, c-format
+msgid "Usage: cs[cope] %s"
+msgstr ""
+
+#: if_cscope.c:67
+msgid "Add a new database"
+msgstr "新增数æ®åº“"
+
+#: if_cscope.c:69
+msgid "Query for a pattern"
+msgstr "查询模å¼"
+
+#: if_cscope.c:71
+msgid "Show this message"
+msgstr "显示此信æ¯"
+
+#: if_cscope.c:73
+msgid "Kill a connection"
+msgstr "结æŸè¿žæŽ¥"
+
+#: if_cscope.c:75
+msgid "Reinit all connections"
+msgstr "é‡è®¾æ‰€æœ‰è¿žæŽ¥"
+
+#: if_cscope.c:77
+msgid "Show connections"
+msgstr "显示连接"
+
+#: if_cscope.c:108
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "这个 cscope 命令ä¸æ”¯æŒåˆ†å‰²å±å¹•\n"
+
+#: if_cscope.c:143
+msgid "Usage: cstag <ident>"
+msgstr "用法: cstag <识别字>"
+
+#: if_cscope.c:199
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: 找ä¸åˆ° tag"
+
+#: if_cscope.c:407 if_cscope.c:451
+#, c-format
+msgid "stat(%s) error: %d"
+msgstr "stat(%s) 错误: %d"
+
+#: if_cscope.c:460 if_cscope.c:467
+#, c-format
+msgid "Added cscope database %s"
+msgstr "新增 cscope æ•°æ®åº“ %s"
+
+#: if_cscope.c:474
+#, c-format
+msgid "%s is not a directory or a valid cscope database"
+msgstr "%s ä¸æ˜¯ç›®å½•æˆ– cscope æ•°æ®åº“"
+
+#: if_cscope.c:557
+#, c-format
+msgid "error reading cscope connection %d"
+msgstr "è¯»å– cscope 连接 %d 时错误"
+
+#: if_cscope.c:633
+msgid "unknown cscope search type"
+msgstr "未知的 cscope 查找形æ€"
+
+#: if_cscope.c:680
+msgid "Could not create cscope pipes"
+msgstr "ä¸èƒ½åˆ›å»ºä¸Ž cscope 连接的管é“"
+
+#: if_cscope.c:745
+msgid "cs_create_connection exec failed"
+msgstr "cs_create_connection 执行失败"
+
+#: if_cscope.c:755
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen 失败 (to_fp)"
+
+#: if_cscope.c:757
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen 失败 (fr_fp)"
+
+#: if_cscope.c:785
+msgid "no cscope connections"
+msgstr "没有 cscope 连接"
+
+#: if_cscope.c:855
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: 找ä¸åˆ°ç¬¦åˆ cscope çš„æœå¯» %s / %s"
+
+#: if_cscope.c:899
+msgid "cscope commands:\n"
+msgstr "cscope 命令:\n"
+
+#: if_cscope.c:902
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)\n"
+msgstr "%-5s: %-30s (用法: %s)\n"
+
+#: if_cscope.c:970
+msgid "duplicate cscope database not added"
+msgstr "é‡å¤çš„ cscope æ•°æ®åº“未被加入"
+
+#: if_cscope.c:981
+msgid "maximum number of cscope connections reached"
+msgstr "已达到 cscope 最大连接数目"
+
+#: if_cscope.c:1102
+msgid "E260: cscope connection not found"
+msgstr "E260: 找ä¸åˆ° cscope 连接"
+
+#: if_cscope.c:1105
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: 找ä¸åˆ° cscope 连接 %s"
+
+#: if_cscope.c:1141
+msgid "cscope connection closed"
+msgstr "cscope 连接已关闭"
+
+#: if_cscope.c:1149
+#, c-format
+msgid "cscope connection %s closed\n"
+msgstr "cscope 连接 %s 已关闭\n"
+
+#. should not reach here
+#: if_cscope.c:1290
+msgid "fatal error in cs_manage_matches"
+msgstr "cs_manage_matches 严é‡é”™è¯¯"
+
+#: if_cscope.c:1341
+#, c-format
+msgid "E262: error reading cscope connection %d"
+msgstr "E262: è¯»å– cscope 连接 %d 错误"
+
+#: if_cscope.c:1449
+msgid "couldn't malloc\n"
+msgstr "ä¸èƒ½ä½¿ç”¨ malloc\n"
+
+#: if_cscope.c:1454
+#, c-format
+msgid "Cscope tag: %s\n"
+msgstr "Cscope 标签(tag): %s\n"
+
+#: if_cscope.c:1458
+msgid " # line"
+msgstr " # 行 "
+
+#: if_cscope.c:1460
+msgid "filename / context / line\n"
+msgstr "文件å / 上下文 / è¡Œå·\n"
+
+#: if_cscope.c:1718
+msgid "All cscope databases reset"
+msgstr "é‡è®¾æ‰€æœ‰ cscope æ•°æ®åº“"
+
+#: if_cscope.c:1785
+msgid "no cscope connections\n"
+msgstr "没有 cscope 连接\n"
+
+#: if_cscope.c:1789
+msgid " # pid database name prepend path\n"
+msgstr " # pid æ•°æ®åº“å称 prepend path\n"
+
+#: if_cscope.c:1800
+#, c-format
+msgid "%2d %-5ld %-34s <none>\n"
+msgstr "%2d %-5ld %-34s <æ— >\n"
+
+#: if_python.c:376
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr "E263: 抱歉,这个命令ä¸èƒ½ä½¿ç”¨ï¼ŒPython 程åºåº“没有加载。"
+
+#: if_python.c:576
+msgid "can't delete OutputObject attributes"
+msgstr "ä¸èƒ½åˆ é™¤ OutputObject 属性"
+
+#: if_python.c:583
+msgid "softspace must be an integer"
+msgstr "softspace 必需是整数"
+
+#: if_python.c:591
+msgid "invalid attribute"
+msgstr "ä¸æ­£ç¡®çš„属性"
+
+#: if_python.c:630 if_python.c:644
+msgid "writelines() requires list of strings"
+msgstr "writelines() éœ€è¦ string list 当å‚æ•°"
+
+#: if_python.c:770
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: ä¸èƒ½åˆå§‹åŒ– I/O 对象"
+
+#: if_python.c:955 if_tcl.c:1391
+msgid "invalid expression"
+msgstr "ä¸æ­£ç¡®çš„表达å¼"
+
+#: if_python.c:969 if_tcl.c:1396
+msgid "expressions disabled at compile time"
+msgstr "因为编译时没有加入表达å¼(expression)的程åºä»£ç ï¼Œæ‰€ä»¥ä¸èƒ½ä½¿ç”¨è¡¨è¾¾å¼"
+
+#: if_python.c:982
+msgid "attempt to refer to deleted buffer"
+msgstr "试图使用已被删除的缓冲区"
+
+#: if_python.c:997 if_python.c:1038 if_python.c:1102 if_tcl.c:1203
+msgid "line number out of range"
+msgstr "è¡Œå·è¶…出范围"
+
+#: if_python.c:1235
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<buffer 对象 (已删除): %8lX>"
+
+#: if_python.c:1326 if_tcl.c:825
+msgid "invalid mark name"
+msgstr "标记å称ä¸æ­£ç¡®"
+
+#: if_python.c:1601
+msgid "no such buffer"
+msgstr "无此缓冲区"
+
+#: if_python.c:1689
+msgid "attempt to refer to deleted window"
+msgstr "试图使用已被删除的窗å£"
+
+#: if_python.c:1734
+msgid "readonly attribute"
+msgstr "åªè¯»å±žæ€§"
+
+#: if_python.c:1747
+msgid "cursor position outside buffer"
+msgstr "光标定ä½åœ¨ç¼“冲区之外"
+
+#: if_python.c:1824
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<窗å£å¯¹è±¡(已删除): %.8lX>"
+
+#: if_python.c:1836
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<窗å£å¯¹è±¡(未知): %.8lX>"
+
+#: if_python.c:1838
+#, c-format
+msgid "<window %d>"
+msgstr "<çª—å£ %d>"
+
+#: if_python.c:1914
+msgid "no such window"
+msgstr "无此窗å£"
+
+#: if_python.c:2144 if_python.c:2175 if_python.c:2225 if_python.c:2285
+#: if_python.c:2402 if_python.c:2454 if_tcl.c:673 if_tcl.c:718 if_tcl.c:792
+#: if_tcl.c:862 if_tcl.c:1987
+msgid "cannot save undo information"
+msgstr "ä¸èƒ½ä¿å­˜å¤åŽŸä¿¡æ¯"
+
+#: if_python.c:2146 if_python.c:2232 if_python.c:2296
+msgid "cannot delete line"
+msgstr "ä¸èƒ½åˆ é™¤æ­¤è¡Œ"
+
+#: if_python.c:2177 if_python.c:2312 if_tcl.c:679 if_tcl.c:2009
+msgid "cannot replace line"
+msgstr "ä¸èƒ½æ›¿æ¢æ­¤è¡Œ"
+
+#: if_python.c:2328 if_python.c:2404 if_python.c:2462
+msgid "cannot insert line"
+msgstr "ä¸èƒ½æ’入此行"
+
+#: if_python.c:2566
+msgid "string cannot contain newlines"
+msgstr "字符串ä¸èƒ½åŒ…å«æ–°è¡Œ"
+
+#: if_ruby.c:394
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr "E266: 此命令ä¸èƒ½ä½¿ç”¨ï¼Œæ— æ³•åŠ è½½ Ruby 程åºåº“(Library)"
+
+#: if_ruby.c:457
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: 未知的 longjmp çŠ¶æ€ %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "切æ¢å®žçŽ°/定义"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "显示 base class of:"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "显示被覆盖的æˆå‘˜å‡½æ•°"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "æ¢å¤: 从文件"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "æ¢å¤: 从对象"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "æ¢å¤: 从所有项目"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "æ¢å¤"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "显示æºä»£ç : "
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "查找 symbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "æµè§ˆ class"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "显示层次关系的类"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "显示 restricted 层次关系的 class"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref å‚考到"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref 被è°å‚考:"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref 有"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref 被è°ä½¿ç”¨:"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "显示文件: "
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "产生文件: "
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr "ä¸èƒ½è¿žæŽ¥åˆ° SNiFF+。请检查环境å˜é‡ ($PATH 里必需å¯ä»¥æ‰¾åˆ° sniffemacs)\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: 读å–错误. å–消连接"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ ç›®å‰"
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "未"
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "连接中"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: ä¸æ­£ç¡®çš„ SNiff+ 调用: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: 连接到 SNiFF+ 失败"
+
+#: if_sniff.c:1010
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: 未连接到 SNiFF+"
+
+#: if_sniff.c:1019
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: ä¸æ˜¯ SNiFF+ 的缓冲区"
+
+#: if_sniff.c:1084
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: 写入错误。结æŸè¿žæŽ¥"
+
+#: if_tcl.c:407
+msgid "invalid buffer number"
+msgstr "ä¸æ­£ç¡®çš„缓冲区å·"
+
+#: if_tcl.c:453 if_tcl.c:920 if_tcl.c:1099
+msgid "not implemented yet"
+msgstr "尚未实现"
+
+#: if_tcl.c:490
+msgid "unknown option"
+msgstr "ä¸æ­£ç¡®çš„选项"
+
+#. ???
+#: if_tcl.c:763
+msgid "cannot set line(s)"
+msgstr "ä¸èƒ½è®¾å®šè¡Œ"
+
+#: if_tcl.c:834
+msgid "mark not set"
+msgstr "没有设定标记"
+
+#: if_tcl.c:840 if_tcl.c:1055
+#, c-format
+msgid "row %d column %d"
+msgstr "列 %d 行 %d"
+
+#: if_tcl.c:870
+msgid "cannot insert/append line"
+msgstr "ä¸èƒ½æ’入或添加此行"
+
+#: if_tcl.c:1257
+msgid "unknown flag: "
+msgstr "错误的标志: "
+
+#: if_tcl.c:1327
+msgid "unknown vimOption"
+msgstr "ä¸æ­£ç¡®çš„ VIM 选项"
+
+#: if_tcl.c:1412
+msgid "keyboard interrupt"
+msgstr "键盘中断"
+
+#: if_tcl.c:1417
+msgid "vim error"
+msgstr "vim 错误"
+
+#: if_tcl.c:1460
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "ä¸èƒ½åˆ›å»ºç¼“冲区/窗å£å‘½ä»¤: 对象将被删除"
+
+#: if_tcl.c:1534
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr "ä¸èƒ½æ³¨å†Œ callback 命令: 缓冲区/窗å£å·²ç»è¢«åˆ é™¤äº†"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1551
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr "E280: TCL 严é‡é”™è¯¯: reflist ä¸å¯é !? 请报告给 to vim-dev@vim.org"
+
+#: if_tcl.c:1552
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr "ä¸èƒ½æ³¨å†Œ callback 命令: 找ä¸åˆ°ç¼“冲区/窗å£"
+
+#: if_tcl.c:1713
+msgid "Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr "此命令ä¸èƒ½ä½¿ç”¨, 因为无法加载 Tcl 程åºåº“(Library)"
+
+#: if_tcl.c:1875
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr "E281: TCL 错误: 退出返回值ä¸æ˜¯æ•´æ•°!? 请报告给 to vim-dev@vim.org"
+
+#: if_tcl.c:1995
+msgid "cannot get line"
+msgstr "ä¸èƒ½å–得此行"
+
+#: if_xcmdsrv.c:204
+msgid "Unable to register a command server name"
+msgstr "ä¸èƒ½æ³¨å†Œå‘½ä»¤æœåŠ¡å™¨å称"
+
+#: if_xcmdsrv.c:417
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: 没有注册为 \"%s\" çš„æœåŠ¡å™¨"
+
+#: if_xcmdsrv.c:446
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: ä¸èƒ½é€å‡ºå‘½ä»¤åˆ°ç›®çš„地程åº"
+
+#: if_xcmdsrv.c:709
+#, c-format
+msgid "Invalid server id used: %s"
+msgstr "ä¸æ­£ç¡®çš„æœåŠ¡å™¨ id : %s"
+
+#: if_xcmdsrv.c:1056
+msgid "E249: couldn't read VIM instance registry property"
+msgstr "E249: ä¸èƒ½è¯»å– VIM çš„ 注册表属性"
+
+#: if_xcmdsrv.c:1067
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: VIM 的注册表属性有误。已删除。"
+
+#: main.c:53 option.c:3162 option.c:3269
+msgid "Unknown option"
+msgstr "ä¸æ­£ç¡®çš„选项"
+
+#: main.c:55
+msgid "Too many edit arguments"
+msgstr "太多编辑å‚æ•°"
+
+#: main.c:57
+msgid "Argument missing after"
+msgstr "缺少必è¦çš„å‚æ•°:"
+
+#: main.c:59
+msgid "Garbage after option"
+msgstr "ä¸èƒ½è¾¨è®¤æ­¤é€‰é¡¹åŽçš„命令: "
+
+#: main.c:61
+msgid "Too many \"+command\" or \"-c command\" arguments"
+msgstr "太多 \"+command\" 或 \"-c command\" å‚æ•°"
+
+#: main.c:63
+msgid "Invalid argument for"
+msgstr "ä¸æ­£ç¡®çš„å‚æ•°: "
+
+#: main.c:436
+msgid "This Vim was not compiled with the diff feature."
+msgstr "您的 Vim 编译时没有加入 diff 的能力"
+
+#: main.c:858
+msgid "Attempt to open script file again: \""
+msgstr "试图å†æ¬¡æ‰“å¼€ script 文件: \""
+
+#: main.c:862 main.c:869 main.c:913 memline.c:3673 memline.c:3677
+#: version.c:816 version.c:821 version.c:826 version.c:831 version.c:836
+#: version.c:841 version.c:847 version.c:851 version.c:855 version.c:860
+#: version.c:867 version.c:875 version.c:881
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:867
+msgid "Cannot open for reading: \""
+msgstr "ä¸èƒ½ä¸ºè¯»è€Œæ‰“å¼€: \""
+
+#: main.c:911
+msgid "Cannot open for script output: \""
+msgstr "ä¸èƒ½ä¸º script 输出而打开: \""
+
+#: main.c:1020
+#, c-format
+msgid "%d files to edit\n"
+msgstr "还有 %d 个文件等待编辑\n"
+
+#: main.c:1094
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: 注æ„: 输出ä¸æ˜¯ç»ˆç«¯(å±å¹•)\n"
+
+#: main.c:1096
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: 注æ„: 输入ä¸æ˜¯ç»ˆç«¯(键盘)\n"
+
+#. just in case..
+#: main.c:1171
+msgid "pre-vimrc command line"
+msgstr "pre-vimrc 命令行"
+
+#: main.c:1206
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: ä¸èƒ½è¯»å–文件 \"%s\""
+
+#: main.c:2157
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"查询更多信æ¯è¯·æ‰§è¡Œ: \"vim -h\"\n"
+
+#: main.c:2190
+msgid "[file ..] edit specified file(s)"
+msgstr "[文件 ..] 编辑指定的文件"
+
+#: main.c:2191
+msgid "- read text from stdin"
+msgstr "- 从标准输入(stdin)读å–文本"
+
+#: main.c:2192
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tag 编辑时使用指定的 tag"
+
+#: main.c:2194
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [errorfile] 编辑时加载第一个错误"
+
+#: main.c:2203
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+" 用法:"
+
+#: main.c:2206
+msgid " vim [arguments] "
+msgstr "vim [å‚æ•°] "
+
+#: main.c:2210
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" 或:"
+
+#: main.c:2213
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"å‚æ•°:\n"
+
+#: main.c:2214
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tåªæœ‰åœ¨è¿™ä¹‹åŽçš„文件"
+
+#: main.c:2216
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\t注册 gvim 到 OLE"
+
+#: main.c:2217
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tå–消 OLE 中的 gvim 注册"
+
+#: main.c:2220
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tä½¿ç”¨å›¾å½¢ç•Œé¢ (åŒ \"gvim\")"
+
+#: main.c:2221
+msgid "-f\t\t\tForeground: Don't fork when starting GUI"
+msgstr "-f\t\t\tå‰æ™¯: å¯åŠ¨å›¾å½¢ç•Œé¢æ—¶ä¸ fork"
+
+#: main.c:2223
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi æ¨¡å¼ (åŒ \"vi\")"
+
+#: main.c:2224
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx æ¨¡å¼ (åŒ \"ex\")"
+
+#: main.c:2225
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tå®‰é™ (batch) æ¨¡å¼ (åªèƒ½ä¸Ž \"ex\" 一起使用)"
+
+#: main.c:2227
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tDiff æ¨¡å¼ (åŒ \"vimdiff\", å¯è¿…速比较两文件ä¸åŒå¤„)"
+
+#: main.c:2229
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tç®€æ˜“æ¨¡å¼ (åŒ \"evim\", modeless)"
+
+#: main.c:2230
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tåªè¯»æ¨¡å¼ (åŒ \"view\")"
+
+#: main.c:2231
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\té™åˆ¶æ¨¡å¼ (åŒ \"rvim\")"
+
+#: main.c:2232
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tä¸å¯ä¿®æ”¹ (写入文件)"
+
+#: main.c:2233
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\t文本ä¸å¯ä¿®æ”¹"
+
+#: main.c:2234
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\t二进制模å¼"
+
+#: main.c:2236
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp 模å¼"
+
+#: main.c:2238
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\t'compatible' 传统 Vi 兼容模å¼"
+
+#: main.c:2239
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\t'nocompatible' ä¸å®Œå…¨ä¸Žä¼ ç»Ÿ Vi 兼容,å¯ä½¿ç”¨ Vim 加强能力"
+
+#: main.c:2240
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tVerbose 等级"
+
+#: main.c:2241
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\t调试模å¼"
+
+#: main.c:2242
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tä¸ä½¿ç”¨äº¤æ¢æ–‡ä»¶, åªä½¿ç”¨å†…å­˜"
+
+#: main.c:2243
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\t列出交æ¢æ–‡ä»¶åŽé€€å‡º"
+
+#: main.c:2244
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (加文件å) \tæ¢å¤ä¸Šæ¬¡å´©æºƒçš„资料(Recover crashed session)"
+
+#: main.c:2245
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\t与 -r 一样"
+
+#: main.c:2247
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tä¸ä½¿ç”¨ newcli æ¥æ‰“开窗å£"
+
+#: main.c:2248
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <device>\t\t使用 <device> åšè¾“入输出设备"
+
+#: main.c:2251
+msgid "-H\t\t\tstart in Hebrew mode"
+msgstr "-H\t\t\tå¯åŠ¨ä¸º 希伯莱模å¼"
+
+#: main.c:2254
+msgid "-F\t\t\tstart in Farsi mode"
+msgstr "-F\t\t\tå¯åŠ¨ä¸º Farsi 模å¼"
+
+#: main.c:2256
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\t设定终端为 <terminal>"
+
+#: main.c:2257
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\t使用 <vimrc> 替æ¢ä»»ä½• .vimrc"
+
+#: main.c:2259
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\t使用 <gvimrc> 替æ¢ä»»ä½• .gvimrc"
+
+#: main.c:2261
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tä¸åŠ è½½ä»»ä½• plugin"
+
+#: main.c:2262
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\t打开 N ä¸ªçª—å£ (预设是æ¯ä¸ªæ–‡ä»¶ä¸€ä¸ª)"
+
+#: main.c:2263
+msgid "-O[N]\t\tlike -o but split vertically"
+msgstr "-O[N]\t\tåŒ -o 但使用垂直分割"
+
+#: main.c:2264
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tå¯åŠ¨åŽè·³åˆ°æ–‡ä»¶ç»“å°¾"
+
+#: main.c:2265
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\tå¯åŠ¨åŽè·³åˆ°ç¬¬ <lnum> è¡Œ"
+
+#: main.c:2267
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <command>\t加载任何 vimrc å‰æ‰§è¡Œ <command>"
+
+#: main.c:2269
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <command>\t\t加载第一个文件åŽæ‰§è¡Œ <command>"
+
+#: main.c:2270
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <session>\t\t加载第一个文件åŽè½½å…¥ Session 文件<session>"
+
+#: main.c:2271
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <scriptin>\t从 <scriptin> 读入一般模å¼å‘½ä»¤"
+
+#: main.c:2272
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <scriptout>\t对文件 <scriptout> 附加(append)所有输入的命令"
+
+#: main.c:2273
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <scriptout>\t对文件 <scriptout> 写入所有输入的命令"
+
+#: main.c:2275
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\t编辑编ç è¿‡çš„文件"
+
+#: main.c:2279
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\t将 vim 与指定的 X-server 连接"
+
+#: main.c:2281
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tä¸è¦è¿žæŽ¥åˆ° X Server"
+
+#: main.c:2283
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\t在å¦ä¸€ä¸ª GTK 组件内打开 Vim"
+
+#: main.c:2287
+msgid "--remote <files>\tEdit <files> in a Vim server and exit"
+msgstr "--remote <files>\t编辑 Vim æœåŠ¡å™¨ä¸Šçš„文件并退出"
+
+#: main.c:2288
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <files> 等效于 --remote, 但会等候文件完æˆç¼–辑"
+
+#: main.c:2289
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <keys>\té€å‡º <keys> 到 Vim æœåŠ¡å™¨å¹¶é€€å‡º"
+
+#: main.c:2290
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <expr>\t在æœåŠ¡å™¨ä¸Šæ±‚表达å¼çš„值并打å°ç»“æžœ"
+
+#: main.c:2291
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\t列出å¯ç”¨çš„ Vim æœåŠ¡å™¨å称并退出"
+
+#: main.c:2292
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <name>\té€è‡³/æˆä¸º Vim æœåŠ¡å™¨ <name>"
+
+#: main.c:2295
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\t使用 <viminfo> è€Œéž .viminfo"
+
+#: main.c:2297
+msgid "-h\t\t\tprint Help (this message) and exit"
+msgstr "-h\t\t\t打å°è¯´æ˜Ž(也就是本信æ¯)åŽé€€å‡º"
+
+#: main.c:2298
+msgid "--version\t\tprint version information and exit"
+msgstr "--version\t\t打å°ç‰ˆæœ¬ä¿¡æ¯åŽé€€å‡º"
+
+#: main.c:2302
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"gvim å¯è¯†åˆ«çš„å‚æ•° (Motif 版):\n"
+
+#: main.c:2305
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"gvim å¯è¯†åˆ«çš„å‚æ•° (Athena 版):\n"
+
+#: main.c:2308
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\tåœ¨çª—å£ <display> 执行 vim"
+
+#: main.c:2309
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tå¯åŠ¨åŽæœ€å°åŒ–(iconified)"
+
+#: main.c:2311
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <name>\t\tè¯»å– Resource 时把 vim çš„å称视为 <name>"
+
+#: main.c:2312
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (尚未实现)\n"
+
+#: main.c:2314
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <color>\t设定 <color> 为背景色 (也å¯ç”¨ -bg)"
+
+#: main.c:2315
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <color>\t设定 <color> 为一般文字颜色 (也å¯ç”¨ -fg)"
+
+#: main.c:2316 main.c:2336
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <font>\t使用 <font> 为一般字体 (也å¯ç”¨ -fn)"
+
+#: main.c:2317
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <font>\t使用 <font> 为粗体字体"
+
+#: main.c:2318
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <font>\t使用 <font> 为斜体字体"
+
+#: main.c:2319 main.c:2337
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\t使用<geom>为åˆå§‹ä½ç½® (也å¯ç”¨ -geom)"
+
+#: main.c:2320
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <width>\t使用宽度为 <width> 的边框 (也å¯ç”¨ -bw)"
+
+#: main.c:2321
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <width> 设定滚动æ¡å®½åº¦ä¸º <width> (也å¯ç”¨ -sw)"
+
+#: main.c:2323
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <height>\t设定èœå•åˆ—的高度为 <height> (也å¯ç”¨ -mh)"
+
+#: main.c:2325 main.c:2338
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\t使用å显 (也å¯ç”¨ -rv)"
+
+#: main.c:2326
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tä¸ä½¿ç”¨å显 (也å¯ç”¨ +rv)"
+
+#: main.c:2327
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\t设定指定的资æº"
+
+#: main.c:2330
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"gvim å¯è¯†åˆ«çš„å‚æ•° (RISC OS 版):\n"
+
+#: main.c:2331
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <number>\t窗å£åˆå§‹å®½åº¦"
+
+#: main.c:2332
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <number>\t窗å£åˆå§‹é«˜åº¦"
+
+#: main.c:2335
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"gvim å¯è¯†åˆ«çš„å‚æ•° (GTK+ 版):\n"
+
+#: main.c:2339
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\t在 <display> 执行 vim (也å¯ç”¨ --display)"
+
+#: main.c:2341
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\t显示 Gnome 相关å‚æ•°"
+
+#. Failed to send, abort.
+#: main.c:2566
+msgid ""
+"\n"
+"Send failed.\n"
+msgstr ""
+"\n"
+"å‘é€è¡¨è¾¾å¼å¤±è´¥ã€‚\n"
+
+#. Let vim start normally.
+#: main.c:2571
+msgid ""
+"\n"
+"Send failed. Trying to execute locally\n"
+msgstr ""
+"\n"
+"é€å‡ºå¤±è´¥ã€‚试图在本地执行\n"
+
+#: main.c:2604 main.c:2625
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d 中 %d 已编辑"
+
+#: main.c:2648
+msgid "Send expression failed.\n"
+msgstr "å‘é€è¡¨è¾¾å¼å¤±è´¥ã€‚\n"
+
+#: mark.c:655
+msgid "No marks set"
+msgstr "没有设定标记 (mark)"
+
+#: mark.c:657
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: 找ä¸åˆ°ç¬¦åˆ \"%s\" 的标记(mark)"
+
+#. Highlight title
+#: mark.c:668
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"标记 è¡Œå· åˆ— 文件/文本"
+
+#. Highlight title
+#: mark.c:706
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" 跳到 è¡Œå· åˆ— 文件/文本"
+
+#: mark.c:1068
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# 文件标记:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1103
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Jumplist (从新到旧):\n"
+
+#: mark.c:1198
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# 文件内历å²è®°å½• (从新到旧):\n"
+
+#: mark.c:1281
+msgid "Missing '>'"
+msgstr "缺少对应的 '>'"
+
+#: mbyte.c:395
+msgid "Not a valid codepage"
+msgstr "ä¸æ­£ç¡®çš„代ç é¡µ"
+
+#: mbyte.c:3005
+msgid "E284: Cannot set IC values"
+msgstr "E284: ä¸èƒ½è®¾å®š IC 数值"
+
+#: mbyte.c:3157
+msgid "E285: Failed to create input context"
+msgstr "E285: ä¸èƒ½åˆ›å»ºè¾“入上下文"
+
+#: mbyte.c:3304
+msgid "E286: Failed to open input method"
+msgstr "E286: ä¸èƒ½æ‰“开输入法"
+
+#: mbyte.c:3315
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: 警告: ä¸èƒ½ç§»é™¤ IM çš„ callback"
+
+#: mbyte.c:3321
+msgid "E288: input method doesn't support any style"
+msgstr "E288: 输入法ä¸æ”¯æŒä»»ä½• style"
+
+#: mbyte.c:3378
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: 输入法ä¸æ”¯æŒä»»ä½• style"
+
+#: mbyte.c:3452
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: over-the-spot 需è¦å­—体集(Fontset)"
+
+#: mbyte.c:3480
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: ä½ çš„ GTK+ 比 1.2.3 è€ã€‚ä¸èƒ½ä½¿ç”¨çŠ¶æ€åŒºã€‚"
+
+#: mbyte.c:3717
+msgid "E292: Input Method Server is not running"
+msgstr "E292: 输入法管ç†ç¨‹åº(Input Method Server)未è¿è¡Œ"
+
+#: memfile.c:473
+msgid "E293: block was not locked"
+msgstr "E293: å—未被é”定"
+
+#: memfile.c:972
+msgid "E294: Seek error in swap file read"
+msgstr "E294: 交æ¢æ–‡ä»¶è¯»å–错误"
+
+#: memfile.c:977
+msgid "E295: Read error in swap file"
+msgstr "E295: 交æ¢æ–‡ä»¶è¯»å–错误"
+
+#: memfile.c:1029
+msgid "E296: Seek error in swap file write"
+msgstr "E296: 交æ¢æ–‡ä»¶å†™å…¥é”™è¯¯"
+
+#: memfile.c:1047
+msgid "E297: Write error in swap file"
+msgstr "E297: 交æ¢æ–‡ä»¶å†™å…¥é”™è¯¯"
+
+#: memfile.c:1244
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: 交æ¢æ–‡ä»¶å·²ç»å­˜åœ¨! (å°å¿ƒç¬¦å·è¿žç»“的安全æ¼æ´ž!?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: 找ä¸åˆ°å— 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: 找ä¸åˆ°å— 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: 找ä¸åˆ°å— 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: 噢噢, 交æ¢æ–‡ä»¶ä¸è§äº†!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: ä¸èƒ½æ”¹å˜äº¤æ¢æ–‡ä»¶çš„å称"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: ä¸èƒ½æ‰“开交æ¢æ–‡ä»¶ \"%s\", ä¸å¯èƒ½æ¢å¤äº†"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: 找ä¸åˆ°å— 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: 找ä¸åˆ° %s 的交æ¢æ–‡ä»¶"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "请选择你è¦ä½¿ç”¨çš„交æ¢æ–‡ä»¶ (按0 退出): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: ä¸èƒ½æ‰“å¼€ %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "ä¸èƒ½è¯»å–å— 0:"
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"å¯èƒ½ä½ æ²¡åšè¿‡ä»»ä½•ä¿®æ”¹æˆ–是 Vim 还æ¥ä¸åŠæ›´æ–°äº¤æ¢æ–‡ä»¶."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " ä¸èƒ½åœ¨æœ¬ç‰ˆæœ¬çš„ Vim 中使用.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "使用 Vim 3.0。\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s 看起æ¥ä¸åƒæ˜¯ Vim 交æ¢æ–‡ä»¶"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " ä¸èƒ½åœ¨è¿™å°ç”µè„‘上使用.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "本文件创建于 "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"或是这文件已被破å。"
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "使用交æ¢æ–‡ä»¶ \"%s\""
+
+#: memline.c:915
+#, c-format
+msgid "Original file \"%s\""
+msgstr "原文件 \"%s\""
+
+#: memline.c:934
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: 警告: 原始文件å¯èƒ½å·²ç»ä¿®æ”¹è¿‡äº†"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: ä¸èƒ½ä»Ž %s 读å–å— 1"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???缺少太多行"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???è¡Œå·é”™è¯¯"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???空的 å—"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???找ä¸åˆ°ä¸€äº›è¡Œ"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: å— 1 ID 错误 (%s ä¸æ˜¯äº¤æ¢æ–‡ä»¶?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???找ä¸åˆ°å—"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? 从这里到 ???END 的内容å¯èƒ½æœ‰é—®é¢˜"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? 从这里到 ???END 的内容å¯èƒ½è¢«åˆ é™¤/æ’入过"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???END"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: æ¢å¤å·²ä¸­æ–­"
+
+#: memline.c:1145
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: æ¢å¤æ—¶å‘生错误; 请注æ„开头为 ??? çš„è¡Œ"
+
+#: memline.c:1148
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "æ¢å¤å®Œæˆ. 请确定一切正常."
+
+#: memline.c:1149
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(ä½ å¯èƒ½æƒ³è¦æŠŠè¿™ä¸ªæ–‡ä»¶å¦å­˜ä¸ºåˆ«çš„文件å,\n"
+
+#: memline.c:1150
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "å†æ‰§è¡Œ diff 与原文件比较以检查是å¦æœ‰æ”¹å˜)\n"
+
+#: memline.c:1151
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"(D)直接删除 .swp 交æ¢æ–‡ä»¶\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1207
+msgid "Swap files found:"
+msgstr "找到以下的交æ¢æ–‡ä»¶:"
+
+#: memline.c:1385
+msgid " In current directory:\n"
+msgstr " 在目å‰ç›®å½•:\n"
+
+#: memline.c:1387
+msgid " Using specified name:\n"
+msgstr " Using specified name:\n"
+
+#: memline.c:1391
+msgid " In directory "
+msgstr " 在目录 "
+
+#: memline.c:1409
+msgid " -- none --\n"
+msgstr " -- æ—  --\n"
+
+#: memline.c:1481
+msgid " owned by: "
+msgstr " 所有者: "
+
+#: memline.c:1483
+msgid " dated: "
+msgstr " 日期: "
+
+#: memline.c:1487 memline.c:3680
+msgid " dated: "
+msgstr " 日期: "
+
+#: memline.c:1503
+msgid " [from Vim version 3.0]"
+msgstr " [从 Vim 版本 3.0]"
+
+#: memline.c:1507
+msgid " [does not look like a Vim swap file]"
+msgstr " [ä¸åƒ Vim 的交æ¢æ–‡ä»¶]"
+
+#: memline.c:1511
+msgid " file name: "
+msgstr " 文件å: "
+
+#: memline.c:1523
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" 修改过: "
+
+#: memline.c:1524
+msgid "YES"
+msgstr "是"
+
+#: memline.c:1524
+msgid "no"
+msgstr "å¦"
+
+#: memline.c:1528
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" 用户å: "
+
+#: memline.c:1535
+msgid " host name: "
+msgstr " 主机å: "
+
+#: memline.c:1537
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" 主机å: "
+
+#: memline.c:1543
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" 进程 ID: "
+
+#: memline.c:1549
+msgid " (still running)"
+msgstr " (正在执行)"
+
+#: memline.c:1561
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [ä¸èƒ½åœ¨æœ¬ç‰ˆæœ¬çš„ Vim 上使用]"
+
+#: memline.c:1564
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [ä¸èƒ½åœ¨æœ¬æœºä¸Šä½¿ç”¨]"
+
+#: memline.c:1569
+msgid " [cannot be read]"
+msgstr " [ä¸èƒ½è¯»å–]"
+
+#: memline.c:1573
+msgid " [cannot be opened]"
+msgstr " [ä¸èƒ½æ‰“å¼€]"
+
+#: memline.c:1763
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: ä¸èƒ½ä¿ç•™, ä¸ä½¿ç”¨äº¤æ¢æ–‡ä»¶"
+
+#: memline.c:1816
+msgid "File preserved"
+msgstr "文件已ä¿ç•™"
+
+#: memline.c:1818
+msgid "E314: Preserve failed"
+msgstr "E314: ä¿ç•™å¤±è´¥"
+
+#: memline.c:1889
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: 错误的 lnum: %ld"
+
+#: memline.c:1915
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: 找ä¸åˆ°ç¬¬ %ld è¡Œ"
+
+#: memline.c:2303
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: æŒ‡é’ˆå— id 错误 3"
+
+#: memline.c:2383
+msgid "stack_idx should be 0"
+msgstr "stack_idx 应该是 0"
+
+#: memline.c:2445
+msgid "E318: Updated too many blocks?"
+msgstr "E318: 更新太多�"
+
+#: memline.c:2602
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: æŒ‡é’ˆå— id 错误 4"
+
+#: memline.c:2629
+msgid "deleted block 1?"
+msgstr "åˆ é™¤å— 1?"
+
+#: memline.c:2829
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: 找ä¸åˆ°ç¬¬ %ld è¡Œ"
+
+#: memline.c:3072
+msgid "E317: pointer block id wrong"
+msgstr "E317: æŒ‡é’ˆå— id 错误"
+
+#: memline.c:3088
+msgid "pe_line_count is zero"
+msgstr "pe_line_count 为零"
+
+#: memline.c:3117
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: è¡Œå·è¶…出范围: %ld 超过结尾"
+
+#: memline.c:3121
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: å— %ld 行数错误"
+
+#: memline.c:3170
+msgid "Stack size increases"
+msgstr "堆栈大å°å¢žåŠ "
+
+#: memline.c:3216
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: æŒ‡é’ˆå— id é”™ 2"
+
+#: memline.c:3670
+msgid "E325: ATTENTION"
+msgstr "E325: 注æ„"
+
+#: memline.c:3671
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"å‘现交æ¢æ–‡ä»¶ \""
+
+#: memline.c:3675
+msgid "While opening file \""
+msgstr "当打开文件时 \""
+
+#: memline.c:3684
+msgid " NEWER than swap file!\n"
+msgstr " 比交æ¢æ–‡ä»¶æ–°!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3688
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) å¯èƒ½æœ‰å¦ä¸€ä¸ªç¨‹åºä¹Ÿåœ¨ç¼–辑åŒä¸€ä¸ªæ–‡ä»¶.\n"
+" 如果是这样,请注æ„ä¸è¦ä¸€èµ·å†™å…¥ï¼Œä¸ç„¶ä½ çš„努力都会付诸东æµã€‚\n"
+
+#: memline.c:3689
+msgid " Quit, or continue with caution.\n"
+msgstr " 退出,或是继续编辑。\n"
+
+#: memline.c:3690
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) 上一次编辑此文件时崩溃\n"
+
+#: memline.c:3691
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " 如果是这样, 请用 \":recover\" 或 \"vim -r"
+
+#: memline.c:3693
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" æ¢å¤ä¿®æ”¹å†…容 (进一步说明请看 \":help recovery\").\n"
+
+#: memline.c:3694
+msgid " If you did this already, delete the swap file \""
+msgstr " 如果该æ¢å¤çš„都已ç»æ¢å¤äº†, 请直接删除此交æ¢æ–‡ä»¶ \""
+
+#: memline.c:3696
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" 以é¿å…å†çœ‹åˆ°æ­¤ä¿¡æ¯.\n"
+
+#: memline.c:3710 memline.c:3714
+msgid "Swap file \""
+msgstr "交æ¢æ–‡ä»¶ \""
+
+#: memline.c:3711 memline.c:3717
+msgid "\" already exists!"
+msgstr "\" å·²ç»å­˜åœ¨äº†!"
+
+#: memline.c:3720
+msgid "VIM - ATTENTION"
+msgstr "VIM - 注æ„"
+
+#: memline.c:3722
+msgid "Swap file already exists!"
+msgstr "交æ¢æ–‡ä»¶å·²ç»å­˜åœ¨!"
+
+#: memline.c:3726
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"以åªè¯»æ–¹å¼æ‰“å¼€(&O)\n"
+"直接编辑(&E)\n"
+"æ¢å¤(&R)\n"
+"退出(&Q)"
+
+#: memline.c:3728
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"以åªè¯»æ–¹å¼æ‰“å¼€(&O)\n"
+"直接编辑(&E)\n"
+"æ¢å¤(&R)\n"
+"退出(&Q)\n"
+"删除交æ¢æ–‡ä»¶(&D)"
+
+#: memline.c:3781
+msgid "E326: Too many swap files found"
+msgstr "E326: 找到太多交æ¢æ–‡ä»¶"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: 部份èœå•é¡¹ä¸æ˜¯å­èœå•"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: èœå•åªèƒ½åœ¨å…¶å®ƒæ¨¡å¼ä¸­ä½¿ç”¨"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: 没有那样的èœå•"
+
+#: menu.c:503
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: èœå•ä¸èƒ½æŒ‡å‘å­é€‰å•"
+
+#: menu.c:542
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: ä¸èƒ½ç›´æŽ¥æŠŠèœå•é¡¹åŠ åˆ°èœå•æ¡ä¸­"
+
+#: menu.c:548
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: 分隔线ä¸èƒ½æ˜¯èœå•çš„一部分"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1063
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- èœå• ---"
+
+#: menu.c:1989
+msgid "Tear off this menu"
+msgstr "切下此èœå•"
+
+#: menu.c:2054
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: èœå•å¿…需指å‘一个èœå•é¡¹"
+
+#: menu.c:2074
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: [èœå•] 找ä¸åˆ° %s"
+
+#: menu.c:2143
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: %s 模å¼æœªå®šä¹‰èœå•"
+
+#: menu.c:2181
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: èœå•å¿…需指å‘å­èœå•"
+
+#: menu.c:2202
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: 找ä¸åˆ°èœå• - 请检查èœå•å称"
+
+#: message.c:467
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "å¤„ç† %s æ—¶å‘生错误:"
+
+#: message.c:483
+#, c-format
+msgid "line %4ld:"
+msgstr "行 %4ld:"
+
+#: message.c:523
+msgid "[string too long]"
+msgstr "[字符串太长]"
+
+#: message.c:669
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "简体中文信æ¯ç»´æŠ¤è€…: Wang Jun <junw@turbolinux.com.cn>"
+
+#: message.c:881
+msgid "Interrupt: "
+msgstr "已中断: "
+
+#: message.c:884
+msgid "Hit ENTER to continue"
+msgstr "请按 ENTER 继续"
+
+#: message.c:886
+msgid "Hit ENTER or type command to continue"
+msgstr "请按 ENTER 或其它命令继续"
+
+#: message.c:1940
+msgid "-- More --"
+msgstr "-- 更多 --"
+
+#: message.c:1943
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: å‘下/å‘上一行, 空格/b: 一页, d/u: åŠé¡µ, q: 退出)"
+
+#: message.c:1944
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: å‘下一行, 空白键: 一页, d: åŠé¡µ, q: 退出)"
+
+#: message.c:2419 message.c:2434
+msgid "Question"
+msgstr "问题"
+
+#: message.c:2421
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Y是\n"
+"&Nå¦"
+
+#: message.c:2436
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Y是\n"
+"&Nå¦\n"
+"&Cå–消"
+
+#: message.c:2454
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Y是\n"
+"&Nå¦\n"
+"&A全部ä¿å­˜\n"
+"&D全部ä¸å­˜\n"
+"&Cå–消"
+
+#: message.c:2494
+msgid "Save File dialog"
+msgstr "ä¿å­˜æ–‡ä»¶å¯¹è¯æ¡†"
+
+#: message.c:2496
+msgid "Open File dialog"
+msgstr "打开文件对è¯æ¡†"
+
+#. TODO: non-GUI file selector here
+#: message.c:2547
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: 主控å°(Console)模å¼æ—¶æ²¡æœ‰æ–‡ä»¶æµè§ˆå™¨(file browser)"
+
+#: misc1.c:2449
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: 注æ„: 你正在修改一个åªè¯»æ–‡ä»¶"
+
+#: misc1.c:2678
+msgid "1 more line"
+msgstr "还有一行"
+
+#: misc1.c:2680
+msgid "1 line less"
+msgstr "少于一行"
+
+#: misc1.c:2685
+#, c-format
+msgid "%ld more lines"
+msgstr " 还有 %ld 行"
+
+#: misc1.c:2687
+#, c-format
+msgid "%ld fewer lines"
+msgstr "åªå‰© %ld è¡Œ"
+
+#: misc1.c:2690
+msgid " (Interrupted)"
+msgstr " (已中断)"
+
+#: misc1.c:6244
+msgid "Vim: preserving files...\n"
+msgstr "Vim: ä¿ç•™æ–‡ä»¶ä¸­...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6254
+msgid "Vim: Finished.\n"
+msgstr "Vim: 结æŸ.\n"
+
+#: misc2.c:644 misc2.c:660
+msgid "ERROR: "
+msgstr "错误: "
+
+#: misc2.c:664
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bytes] 全部 alloc-freed %lu-%lu, 使用中 %lu, peak 使用 %lu\n"
+
+#: misc2.c:666
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[调用] 全部 re/malloc(): %lu, 全部 free()': %lu\n"
+"\n"
+
+#: misc2.c:721
+msgid "E340: Line is becoming too long"
+msgstr "E340: 此行过长"
+
+#: misc2.c:765
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: 内部错误: lalloc(%ld, )"
+
+#: misc2.c:873
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: 内存ä¸è¶³! (å°è¯•é…ç½® %lu 字节组)"
+
+#: misc2.c:2508
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "调用 shell 执行: \"%s\""
+
+#: misc2.c:2703 misc2.c:5142 option.c:4584
+msgid "Missing colon"
+msgstr "缺少冒å·"
+
+#: misc2.c:2705 misc2.c:2732
+msgid "Illegal mode"
+msgstr "ä¸æ­£ç¡®çš„模å¼"
+
+#: misc2.c:2771
+msgid "Illegal mouseshape"
+msgstr "ä¸æ­£ç¡®çš„鼠标形状"
+
+#: misc2.c:2811 misc2.c:5162
+msgid "digit expected"
+msgstr "应该为数字"
+
+#: misc2.c:2816
+msgid "Illegal percentage"
+msgstr "ä¸æ­£ç¡®çš„百分比"
+
+#: misc2.c:3120
+msgid "Enter encryption key: "
+msgstr "输入密ç : "
+
+#: misc2.c:3121
+msgid "Enter same key again: "
+msgstr "请å†è¾“入一次: "
+
+#: misc2.c:3131
+msgid "Keys don't match!"
+msgstr "两次输入密ç ä¸åŒ!"
+
+#: misc2.c:3645
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr "E343: ä¸æ­£ç¡®çš„路径: '**[number]' 必需è¦åœ¨è·¯å¾„结尾或è¦æŽ¥è‘— '%s'"
+
+#: misc2.c:4899
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: cdpath 中没有目录 \"%s\""
+
+#: misc2.c:4902
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: 在路径中找ä¸åˆ°æ–‡ä»¶ \"%s\""
+
+#: misc2.c:4908
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: 在路径中找ä¸åˆ°æ›´å¤šçš„文件 \"%s\""
+
+#: misc2.c:4911
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: 在路径中找ä¸åˆ°æ›´å¤šçš„文件 \"%s\""
+
+#: misc2.c:5154
+msgid "Illegal component"
+msgstr "ä¸æ­£ç¡®çš„组件"
+
+#: normal.c:2798
+msgid "Warning: terminal cannot highlight"
+msgstr "注æ„: 你的终端ä¸èƒ½æ˜¾ç¤ºé«˜äº®åº¦"
+
+#: normal.c:2993
+msgid "E348: No string under cursor"
+msgstr "E348: 光标处没有字符串"
+
+#: normal.c:2995
+msgid "E349: No identifier under cursor"
+msgstr "E349: 光标处没有识别字"
+
+#: normal.c:4160
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: ä¸èƒ½åœ¨ç›®å‰çš„ 'foldmethod' 下删除 fold"
+
+#: ops.c:271
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "一行 %s 过 一次"
+
+#: ops.c:273
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "一行 %s 过 %d 次"
+
+#: ops.c:278
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld 行 %s 过 一次"
+
+#: ops.c:281
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld 行 %s 过 %d 次"
+
+#: ops.c:638
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "识别 %ld 行..."
+
+#: ops.c:688
+msgid "1 line indented "
+msgstr "一行已识别"
+
+#: ops.c:690
+#, c-format
+msgid "%ld lines indented "
+msgstr "已识别 %ld 行"
+
+#. must display the prompt
+#: ops.c:1528
+msgid "cannot yank; delete anyway"
+msgstr "ä¸èƒ½å¤åˆ¶; 直接删除"
+
+#: ops.c:2018
+msgid "1 line changed"
+msgstr " 1 行 ~ed"
+
+#: ops.c:2020
+#, c-format
+msgid "%ld lines changed"
+msgstr " %ld 行 ~ed"
+
+#: ops.c:2381
+#, c-format
+msgid "freeing %ld lines"
+msgstr "释放 %ld 行中"
+
+#: ops.c:2658
+msgid "1 line yanked"
+msgstr "å·²å¤åˆ¶ 1 è¡Œ"
+
+#: ops.c:2660
+#, c-format
+msgid "%ld lines yanked"
+msgstr "å·²å¤åˆ¶ %ld è¡Œ"
+
+#: ops.c:2916
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: 寄存器 %s 里没有东西"
+
+#. Highlight title
+#: ops.c:3454
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- 寄存器 ---"
+
+#: ops.c:4565
+msgid "Illegal register name"
+msgstr "ä¸æ­£ç¡®çš„寄存器å称"
+
+#: ops.c:4645
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# 寄存器:\n"
+
+#: ops.c:4671
+#, c-format
+msgid "Unknown register type %d"
+msgstr "未知的注册类型: %d"
+
+#: ops.c:5052
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: 寄存器å称错误: '%s'"
+
+#: ops.c:5393
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld 列; "
+
+#: ops.c:5400
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "选择了 %s%ld/%ld 行; %ld/%ld 字(Word); %ld/%ld 字符(Bytes)"
+
+#: ops.c:5416
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "列 %s/%s; 行 %ld/%ld; 字(Word) %ld/%ld; 字符(Byte) %ld/%ld"
+
+#: ops.c:5427
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld for BOM)"
+
+#: option.c:1989
+msgid "Thanks for flying Vim"
+msgstr "感谢您选择 Vim"
+
+#: option.c:3175
+msgid "Option not supported"
+msgstr "ä¸æ”¯æŒè¯¥é€‰é¡¹"
+
+#: option.c:3200
+msgid "Not allowed in a modeline"
+msgstr "ä¸èƒ½åœ¨æ¨¡å¼è¡Œé‡Œå‡ºçŽ°"
+
+#: option.c:3256
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\t当å‰è®¾ç½®: "
+
+#: option.c:3395
+msgid "Number required after ="
+msgstr "= åŽéœ€è¦æœ‰æ•°å­—"
+
+#: option.c:3702 option.c:4309
+msgid "Not found in termcap"
+msgstr "Termcap 里é¢æ‰¾ä¸åˆ°"
+
+#: option.c:3768
+#, c-format
+msgid "Illegal character <%s>"
+msgstr "ä¸æ­£ç¡®çš„字符 <%s>"
+
+#: option.c:4294 option.c:5497
+msgid "Not allowed here"
+msgstr "这里ä¸å¯ä½¿ç”¨"
+
+#: option.c:4301
+msgid "Cannot set 'term' to empty string"
+msgstr "ä¸èƒ½è®¾å®š 'term' 为空字符串"
+
+#: option.c:4304
+msgid "Cannot change term in GUI"
+msgstr "在图型界é¢ä¸­ä¸èƒ½åˆ‡æ¢ç»ˆç«¯"
+
+#: option.c:4306
+msgid "Use \":gui\" to start the GUI"
+msgstr "输入 \":gui\" æ¥å¯åŠ¨å›¾å½¢ç•Œé¢"
+
+#: option.c:4327
+msgid "'backupext' and 'patchmode' are equal"
+msgstr "'backupext' 跟 'patchmode' 是一样的"
+
+#: option.c:4586
+msgid "Zero length string"
+msgstr "零长度字符串"
+
+#: option.c:4654
+#, c-format
+msgid "Missing number after <%s>"
+msgstr "<%s> åŽç¼ºå°‘æ•°å­—"
+
+#: option.c:4668
+msgid "Missing comma"
+msgstr "缺少逗å·"
+
+#: option.c:4675
+msgid "Must specify a ' value"
+msgstr "必需指定一个 ' 值"
+
+#: option.c:4715
+msgid "contains unprintable character"
+msgstr "包å«ä¸èƒ½æ˜¾ç¤ºçš„字符"
+
+#: option.c:4728
+msgid "Invalid font(s)"
+msgstr "ä¸æ­£ç¡®çš„字体"
+
+#: option.c:4734
+msgid "can't select fontset"
+msgstr "ä¸èƒ½ä½¿ç”¨å­—体集(Fontset)"
+
+#: option.c:4736
+msgid "Invalid fontset"
+msgstr "ä¸æ­£ç¡®çš„字体集(Fontset)"
+
+#: option.c:4743
+msgid "can't select wide font"
+msgstr "ä¸èƒ½ä½¿ç”¨è®¾å®šçš„宽字体(Widefont)"
+
+#: option.c:4745
+msgid "Invalid wide font"
+msgstr "ä¸æ­£ç¡®çš„宽字体(Widefont)"
+
+#: option.c:5014
+#, c-format
+msgid "Illegal character after <%c>"
+msgstr "<%c> åŽæœ‰ä¸æ­£ç¡®çš„字符"
+
+#: option.c:5097
+msgid "comma required"
+msgstr "需è¦é€—å·"
+
+#: option.c:5106
+#, c-format
+msgid "'commentstring' must be empty or contain %s"
+msgstr "'commentstring' å¿…éœ€æ˜¯ç©ºç™½æˆ–åŒ…å« %s"
+
+#: option.c:5153
+msgid "No mouse support"
+msgstr "ä¸æ”¯æŒé¼ æ ‡"
+
+#: option.c:5399
+msgid "Unclosed expression sequence"
+msgstr "没有结æŸçš„表达å¼: "
+
+#: option.c:5403
+msgid "too many items"
+msgstr "太多对象"
+
+#: option.c:5405
+msgid "unbalanced groups"
+msgstr "ä¸å¯¹ç§°çš„组"
+
+#: option.c:5620
+msgid "A preview window already exists"
+msgstr "预览窗å£å·²ç»å­˜åœ¨äº†"
+
+#: option.c:5881 option.c:5910
+msgid "'winheight' cannot be smaller than 'winminheight'"
+msgstr "'winheight' ä¸èƒ½æ¯” 'winminheight' æ›´å°‘"
+
+#: option.c:5926 option.c:5945
+msgid "'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "'winwidth' ä¸èƒ½æ¯” 'winminwidth' æ›´å°‘"
+
+#: option.c:6085
+#, c-format
+msgid "Need at least %d lines"
+msgstr "è‡³å°‘éœ€è¦ %d è¡Œ"
+
+#: option.c:6094
+#, c-format
+msgid "Need at least %d columns"
+msgstr "è‡³å°‘éœ€è¦ %d 列"
+
+#: option.c:6391
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: ä¸æ­£ç¡®çš„选项: %s"
+
+#: option.c:6500
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- ç»ˆç«¯ç¼–ç  ---"
+
+#: option.c:6502
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- 全局 选项值 ---"
+
+#: option.c:6504
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- 本地 选项值 ---"
+
+#: option.c:6506
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- 选项 ---"
+
+#: option.c:7196
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp 错误"
+
+#: option.c:8112
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': 找ä¸åˆ° %s 对应的字符"
+
+#: option.c:8146
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': 分å·åŽæœ‰å¤šä½™çš„字符: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "ä¸èƒ½æ‰“å¼€"
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: ä¸èƒ½æ‰“开窗å£!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "éœ€è¦ Amigados 版本 2.04 以上\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "éœ€è¦ %s 版本 %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "ä¸èƒ½æ‰“å¼€ NIL:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr "ä¸èƒ½åˆ›å»º "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim 返回值: %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "ä¸èƒ½åˆ‡æ¢ä¸»æŽ§å°(console)æ¨¡å¼ !?\n"
+
+#: os_amiga.c:938 os_mac.c:1168 os_mswin.c:619 os_riscos.c:728 os_unix.c:2726
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: ä¸æ”¯æŒè®¾å®šå±å¹•æ¨¡å¼"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: ä¸æ˜¯ä¸»æŽ§å°(console)??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1142
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: ä¸èƒ½ç”¨ -f 选项执行 shell"
+
+#: os_amiga.c:1183 os_amiga.c:1273
+msgid "Cannot execute "
+msgstr "ä¸èƒ½æ‰§è¡Œ "
+
+#: os_amiga.c:1186 os_amiga.c:1283
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1206 os_amiga.c:1308
+msgid " returned\n"
+msgstr " 已返回\n"
+
+#: os_amiga.c:1448
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE 太å°"
+
+#: os_amiga.c:1452
+msgid "I/O ERROR"
+msgstr "I/O 错误"
+
+#: os_mswin.c:503
+msgid "...(truncated)"
+msgstr ""
+
+#: os_mswin.c:594
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' ä¸æ˜¯ 80, ä¸èƒ½æ‰§è¡Œå¤–部命令"
+
+#: os_mswin.c:706 os_unix.c:4945
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: 调用函数库 \"%s\"() 失败"
+
+#: os_mswin.c:1340
+msgid "E237: Printer selection failed"
+msgstr "E237: ä¸èƒ½é€‰æ‹©æ­¤æ‰“å°æœº"
+
+#: os_mswin.c:1388
+#, c-format
+msgid "to %s on %s"
+msgstr "从 %s 到 %s"
+
+#: os_mswin.c:1449 os_mswin.c:1459
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: 打å°é”™è¯¯: %s"
+
+#: os_mswin.c:1459
+msgid "Unknown"
+msgstr "未知"
+
+#: os_mswin.c:1486
+#, c-format
+msgid "Printing '%s'"
+msgstr "已打å°: '%s'"
+
+#: os_mswin.c:2550
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: 字符集 \"%s\" ä¸èƒ½å¯¹åº”字体\"%s\""
+
+#: os_mswin.c:2558
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: ä¸æ­£ç¡®çš„字符 '%c' 出现在字体å称 \"%s\" 内"
+
+#: os_riscos.c:1227
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: ä¸æ­£ç¡®çš„ 'filetype' 选项 - 使用纯文字模å¼"
+
+#: os_unix.c:800
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: åŒé‡ä¿¡å·, 退出中\n"
+
+#: os_unix.c:806
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: CVim: 拦截到信å·(signal) %s\n"
+
+#: os_unix.c:809
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: 拦截到致命的信å·(deadly signale)\n"
+
+#: os_unix.c:1063
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "打开 X Window 用时 %ld 秒"
+
+#: os_unix.c:1090
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: X 错误\n"
+
+#: os_unix.c:1157
+msgid "Testing the X display failed"
+msgstr "测试 X Window 失败"
+
+#: os_unix.c:1301
+msgid "Opening the X display timed out"
+msgstr "打开 X Window 超时"
+
+#: os_unix.c:2899 os_unix.c:3483
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"ä¸èƒ½æ‰§è¡Œ shell"
+
+#: os_unix.c:2944
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"ä¸èƒ½æ‰§è¡Œ shell sh\n"
+
+#: os_unix.c:2948 os_unix.c:3489
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"Shell 已返回"
+
+#: os_unix.c:3082
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"ä¸èƒ½å»ºç«‹ç®¡é“\n"
+
+#: os_unix.c:3097
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"ä¸èƒ½ fork\n"
+
+#: os_unix.c:3496
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"命令已结æŸ\n"
+
+#: os_unix.c:4993
+msgid "Opening the X display failed"
+msgstr "打开 X Window 失败"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "åœ¨è¡Œå· "
+
+#: os_w32exe.c:169
+msgid "Could not load vim32.dll!"
+msgstr "ä¸èƒ½åŠ è½½ vim32.dllï¼"
+
+#: os_w32exe.c:169 os_w32exe.c:179
+msgid "VIM Error"
+msgstr "VIM 错误"
+
+#: os_w32exe.c:179
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "ä¸èƒ½ä¿®æ­£å‡½æ•°æŒ‡é’ˆåˆ° DLL!"
+
+#: os_win16.c:578 os_win32.c:3019
+#, c-format
+msgid "shell returned %d"
+msgstr "Shell 返回值 %d"
+
+#: os_win32.c:2489
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: 拦截到 %s 事件\n"
+
+#: os_win32.c:2491
+msgid "close"
+msgstr "关闭"
+
+#: os_win32.c:2493
+msgid "logoff"
+msgstr "注消"
+
+#: os_win32.c:2494
+msgid "shutdown"
+msgstr "关机"
+
+#: os_win32.c:2975
+msgid "E371: Command not found"
+msgstr "E371: 找ä¸åˆ°å‘½ä»¤"
+
+#: os_win32.c:2988
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"在你的 $PATH 中找ä¸åˆ° VIMRUN.EXE.\n"
+"外部命令执行完毕åŽå°†ä¸ä¼šæš‚åœ.\n"
+"进一步说明请执行 :help win32-vimrun "
+
+#: os_win32.c:2991
+msgid "Vim Warning"
+msgstr "Vim 警告"
+
+#: quickfix.c:281
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: æ ¼å¼åŒ–字符串里有太多 %%%c "
+
+#: quickfix.c:294
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: æ ¼å¼åŒ–字符串ä¸åº”该出现 %%%c "
+
+#: quickfix.c:348
+msgid "E374: Missing ] in format string"
+msgstr "E374: æ ¼å¼åŒ–字符串里少了 ]"
+
+#: quickfix.c:362
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: æ ¼å¼åŒ–字符串里有ä¸æ”¯æŒçš„ %%%c "
+
+#: quickfix.c:380
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: æ ¼å¼åŒ–字符串开头里有ä¸æ­£ç¡®çš„ %%%c "
+
+#: quickfix.c:388
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: æ ¼å¼åŒ–字符串里有ä¸æ­£ç¡®çš„ %%%c "
+
+#: quickfix.c:414
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' 未设定"
+
+#: quickfix.c:520
+msgid "E379: Missing or empty directory name"
+msgstr "E379: 找ä¸åˆ°ç›®å½•å称或是空的目录å称"
+
+#: quickfix.c:931
+msgid "No more items"
+msgstr "没有其它对象"
+
+#: quickfix.c:1152
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d / %d)%s%s: "
+
+#: quickfix.c:1154
+msgid " (line deleted)"
+msgstr " (行已删除)"
+
+#: quickfix.c:1360
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Quickfix 堆栈结尾"
+
+#: quickfix.c:1369
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Quickfix 堆栈顶端"
+
+#: quickfix.c:1381
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "错误列表 %d/%d; 共有 %d 项错误"
+
+#: quickfix.c:1842
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: ä¸èƒ½å†™å…¥ï¼Œ'buftype' 选项已设定"
+
+#: regexp.c:801
+msgid "E339: Pattern too long"
+msgstr "E339: å字太长"
+
+#: regexp.c:1315
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: 巢状 %s*"
+
+#: regexp.c:1318
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: 巢状 %s%c"
+
+#: regexp.c:1467
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c 没有接东西"
+
+#: regexp.c:2469
+#, c-format
+msgid "Syntax error in %s{...}"
+msgstr "语法错误: %s{...}"
+
+#: regexp.c:2716
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: ä¸èƒ½æ‰§è¡Œ; regular expression 太å¤æ‚?"
+
+#: regexp.c:2851
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: regular expression 造æˆå †æ ˆç”¨å…‰çš„错误"
+
+#: regexp.c:3087
+msgid "External submatches:\n"
+msgstr "外部符åˆ:\n"
+
+#: screen.c:2051
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--已 fold %3ld 行"
+
+#: screen.c:7411
+msgid " VREPLACE"
+msgstr " V-替æ¢"
+
+#: screen.c:7415
+msgid " REPLACE"
+msgstr " 替æ¢"
+
+#: screen.c:7420
+msgid " REVERSE"
+msgstr " å转"
+
+#: screen.c:7422
+msgid " INSERT"
+msgstr " æ’å…¥"
+
+#: screen.c:7425
+msgid " (insert)"
+msgstr " (æ’å…¥)"
+
+#: screen.c:7427
+msgid " (replace)"
+msgstr " (替æ¢)"
+
+#: screen.c:7429
+msgid " (vreplace)"
+msgstr " (v-替æ¢)"
+
+#: screen.c:7432
+msgid " Hebrew"
+msgstr " 希伯莱"
+
+#: screen.c:7440
+msgid " (lang)"
+msgstr " (语言)"
+
+#: screen.c:7443
+msgid " (paste)"
+msgstr " (粘帖)"
+
+#: screen.c:7449
+msgid " SELECT"
+msgstr " 选å–"
+
+#: screen.c:7451
+msgid " VISUAL"
+msgstr " å¯è§†"
+
+#: screen.c:7453
+msgid " BLOCK"
+msgstr " å—"
+
+#: screen.c:7455
+msgid " LINE"
+msgstr " 行"
+
+#: screen.c:7468 screen.c:7522
+msgid "recording"
+msgstr "记录中"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "已查找到文件开头;å†ä»Žç»“尾继续查找"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "已查找到文件结尾;å†ä»Žå¼€å¤´ç»§ç»­æŸ¥æ‰¾"
+
+#: search.c:440
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: 错误的查找字符串: %s"
+
+#: search.c:747
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: 已查找到文件开头ä»æ‰¾ä¸åˆ° %s"
+
+#: search.c:749
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: 已查找到文件结尾ä»æ‰¾ä¸åˆ° %s"
+
+#: search.c:1107
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: 在 ';' åŽé¢åº”该有 '?' 或 '/'"
+
+#: search.c:3476
+msgid " (includes previously listed match)"
+msgstr " (包括上次列出符åˆé¡¹)"
+
+#. cursor at status line
+#: search.c:3496
+msgid "--- Included files "
+msgstr "--- 包å«æ–‡ä»¶ "
+
+#: search.c:3498
+msgid "not found "
+msgstr "找ä¸åˆ° "
+
+#: search.c:3499
+msgid "in path ---\n"
+msgstr "在路径 ---\n"
+
+#: search.c:3538
+msgid " (Already listed)"
+msgstr " (已列出)"
+
+#: search.c:3540
+msgid " NOT FOUND"
+msgstr " 找ä¸åˆ°"
+
+#: search.c:3592
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "查找包å«æ–‡ä»¶: %s"
+
+#: search.c:3810
+msgid "E387: Match is on current line"
+msgstr "E387: 当å‰è¡ŒåŒ¹é…"
+
+#: search.c:3950
+msgid "All included files were found"
+msgstr "所有包å«æ–‡ä»¶éƒ½å·²æ‰¾åˆ°"
+
+#: search.c:3952
+msgid "No included files"
+msgstr "没有包å«æ–‡ä»¶"
+
+#: search.c:3968
+msgid "E388: Couldn't find definition"
+msgstr "E388: 找ä¸åˆ°å®šä¹‰"
+
+#: search.c:3970
+msgid "E389: Couldn't find pattern"
+msgstr "E389: 找ä¸åˆ° pattern"
+
+#: syntax.c:2990
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: å‚æ•°ä¸æ­£ç¡®: %s"
+
+#: syntax.c:3167
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: 无此语法 cluster: \"%s\""
+
+#: syntax.c:3331
+msgid "No Syntax items defined for this buffer"
+msgstr "这个缓冲区没有定义任何语法项"
+
+#: syntax.c:3339
+msgid "syncing on C-style comments"
+msgstr "C风格注释åŒæ­¥ä¸­"
+
+#: syntax.c:3347
+msgid "no syncing"
+msgstr "没有åŒæ­¥"
+
+#: syntax.c:3350
+msgid "syncing starts "
+msgstr "åŒæ­¥å¼€å§‹"
+
+#: syntax.c:3352 syntax.c:3421
+msgid " lines before top line"
+msgstr "è¡Œå·è¶…出范围"
+
+#: syntax.c:3356
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- 语法åŒæ­¥é¡¹ç›® (Syntax sync items) ---"
+
+#: syntax.c:3359
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"åŒæ­¥ä¸­:"
+
+#: syntax.c:3364
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- 语法项目 ---"
+
+#: syntax.c:3387
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: 无此语法 cluster: \"%s\""
+
+#: syntax.c:3411
+msgid "minimal "
+msgstr "最å°"
+
+#: syntax.c:3418
+msgid "maximal "
+msgstr "最大"
+
+#: syntax.c:4046
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: 使用了ä¸æ­£ç¡®çš„å‚æ•°"
+
+#: syntax.c:4070
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: 找ä¸åˆ° %s çš„ region item"
+
+#: syntax.c:4098
+msgid "E395: contains argument not accepted here"
+msgstr "E395: 使用了ä¸æ­£ç¡®çš„å‚æ•°"
+
+#: syntax.c:4109
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: 使用了ä¸æ­£ç¡®çš„å‚æ•°"
+
+#: syntax.c:4187
+msgid "E397: Filename required"
+msgstr "E397: 需è¦æ–‡ä»¶å称"
+
+#: syntax.c:4523
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: 缺少 \"=\": %s"
+
+#: syntax.c:4679
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: syntax region %s çš„å‚数太少"
+
+#: syntax.c:5010
+msgid "E400: No cluster specified"
+msgstr "E400: 没有指定的属性"
+
+#: syntax.c:5047
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: 找ä¸åˆ°åˆ†éš”符å·: %s"
+
+#: syntax.c:5122
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: '%s' åŽé¢çš„东西ä¸èƒ½è¯†åˆ«"
+
+#: syntax.c:5204
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: 语法åŒæ­¥: 连接行符å·æŒ‡å®šäº†ä¸¤æ¬¡"
+
+#: syntax.c:5261
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: å‚æ•°ä¸æ­£ç¡®: %s"
+
+#: syntax.c:5311
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: 缺少等å·: %s"
+
+#: syntax.c:5317
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: 空å‚æ•°: %s"
+
+#: syntax.c:5344
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s ä¸èƒ½åœ¨æ­¤å‡ºçŽ°"
+
+#: syntax.c:5351
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s 必须是列表里的第一个"
+
+#: syntax.c:5421
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: ä¸æ­£ç¡®çš„组å: %s"
+
+#: syntax.c:5644
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: ä¸æ­£ç¡®çš„ :syntax å­å‘½ä»¤: %s"
+
+#: syntax.c:6023
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: 找ä¸åˆ° highlight group: %s"
+
+#: syntax.c:6047
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: å‚数太少: \":highlight link %s\""
+
+#: syntax.c:6054
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: å‚数过多: \":highlight link %s\""
+
+#: syntax.c:6074
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: 已设定组, 忽略 highlight link"
+
+#: syntax.c:6203
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: ä¸è¯¥æœ‰çš„ç­‰å·: %s"
+
+#: syntax.c:6239
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: 缺少等å·: %s"
+
+#: syntax.c:6261
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: 缺少å‚æ•°: %s"
+
+#: syntax.c:6298
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: ä¸åˆæ³•çš„值: %s"
+
+#: syntax.c:6417
+msgid "E419: FG color unknown"
+msgstr "E419: 错误的å‰æ™¯é¢œè‰²"
+
+#: syntax.c:6428
+msgid "E420: BG color unknown"
+msgstr "E420: 错误的背景颜色"
+
+#: syntax.c:6483
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: 错误的颜色å称或数值: %s"
+
+#: syntax.c:6687
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: 终端编ç å¤ªé•¿: %s"
+
+#: syntax.c:6734
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: å‚æ•°ä¸æ­£ç¡®: %s"
+
+#: syntax.c:7263
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: 使用了太多ä¸åŒçš„高亮度属性"
+
+#: tag.c:90
+msgid "at bottom of tag stack"
+msgstr "标签(tag)堆栈结尾"
+
+#: tag.c:91
+msgid "at top of tag stack"
+msgstr "标签(tag)堆栈开头"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: å·²ç»åœ¨æœ€å‰é¢çš„标签(tag)了"
+
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: 找ä¸åˆ°æ ‡ç­¾(tag): %s"
+
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr " # pri kind tag"
+
+#: tag.c:548
+msgid "file\n"
+msgstr "文件\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "输入 nr 或选择 (<CR> 退出): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: åªæœ‰æ­¤é¡¹ç¬¦åˆ"
+
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: å·±ç»åœ¨æœ€åŽä¸€ä¸ªç¬¦åˆçš„标签(tag)了"
+
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "文件 \"%s\" ä¸å­˜åœ¨"
+
+#. Give an indication of the number of matching tags
+#: tag.c:780
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "找到 tag: %d/%d%s"
+
+#: tag.c:783
+msgid " or more"
+msgstr " 或更多"
+
+#: tag.c:785
+msgid " Using tag with different case!"
+msgstr " 以ä¸åŒå¤§å°å†™æ¥ä½¿ç”¨ tag!"
+
+#: tag.c:828
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: 文件 \"%s\" ä¸å­˜åœ¨"
+
+#. Highlight title
+#: tag.c:897
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # 到 tag 从 行 在 文件/文本"
+
+#: tag.c:1144
+msgid "Linear tag search"
+msgstr "线性查找标签 (Tags)"
+
+#: tag.c:1146
+msgid "Binary tag search"
+msgstr "二进制查找(Binary search) 标签(Tags)"
+
+#: tag.c:1172
+#, c-format
+msgid "Searching tags file %s"
+msgstr "查找 tag 文件 \"%s\""
+
+#: tag.c:1356
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Tag 文件路径被截断为 %s\n"
+
+#: tag.c:1847
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Tag 文件 \"%s\" æ ¼å¼é”™è¯¯"
+
+#: tag.c:1851
+#, c-format
+msgid "Before byte %ld"
+msgstr "在 %ld 字节之å‰"
+
+#: tag.c:1872
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Tag 文件未排åº: %s"
+
+#. never opened any tags file
+#: tag.c:1911
+msgid "E433: No tags file"
+msgstr "E433: 没有 tag 文件"
+
+#: tag.c:2583
+msgid "E434: Can't find tag pattern"
+msgstr "E434: 找ä¸åˆ° tag"
+
+#: tag.c:2594
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: 找ä¸åˆ° tag, 试ç€çŒœ!"
+
+#: term.c:1723
+msgid "' not known. Available builtin terminals are:"
+msgstr "' ä¸èƒ½åŠ è½½ã€‚å¯ç”¨çš„内建终端形å¼æœ‰:"
+
+#: term.c:1747
+msgid "defaulting to '"
+msgstr "预设: '"
+
+#: term.c:2100
+msgid "Cannot open termcap file"
+msgstr "ä¸èƒ½æ‰“å¼€ termcap 文件"
+
+#: term.c:2103
+msgid "Terminal entry not found in terminfo"
+msgstr "在terminfo中未找到终端项"
+
+#: term.c:2105
+msgid "Terminal entry not found in termcap"
+msgstr "在termcap中未找到终端项"
+
+#: term.c:2264
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: termcap 没有 \"%s\" 项"
+
+#: term.c:2738
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: ç»ˆç«¯éœ€è¦ \"cm\" 的能力"
+
+#. Highlight title
+#: term.c:4872
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- 终端按键 ---"
+
+#: ui.c:240
+msgid "new shell started\n"
+msgstr "å¯åŠ¨æ–° shell\n"
+
+#: ui.c:1705
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: 读错误,退出中...\n"
+
+#. must display the prompt
+#: undo.c:351
+msgid "No undo possible; continue anyway"
+msgstr "ä¸èƒ½è¿˜åŽŸï¼›è¯·ç»§ç»­"
+
+#: undo.c:506
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: è¡Œå·é”™è¯¯"
+
+#: undo.c:675
+msgid "1 change"
+msgstr "一项改å˜"
+
+#: undo.c:677
+#, c-format
+msgid "%ld changes"
+msgstr "%ld 项改å˜"
+
+#: undo.c:721
+msgid "E439: undo list corrupt"
+msgstr "E439: 撤销列表æŸå"
+
+#: undo.c:751
+msgid "E440: undo line missing"
+msgstr "E440: 找ä¸åˆ°è¦æ’¤é”€æ“作的行"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:655
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 16/32ä½ å›¾åž‹ç•Œé¢ç‰ˆæœ¬"
+
+#: version.c:657
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 32 Bit 图型界é¢ç‰ˆæœ¬"
+
+#: version.c:660
+msgid " in Win32s mode"
+msgstr "Win32s 模å¼"
+
+#: version.c:662
+msgid " with OLE support"
+msgstr "æ”¯æŒ OLE"
+
+#: version.c:665
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"MS-Windows 32ä½ å­—ç¬¦ç•Œé¢ç‰ˆæœ¬"
+
+#: version.c:669
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"MS-Windows 32ä½ å­—ç¬¦ç•Œé¢ç‰ˆæœ¬"
+
+#: version.c:673
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 ä½ MS-DOS 版本"
+
+#: version.c:675
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 ä½ MS-DOS 版本"
+
+#: version.c:681
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) 版本"
+
+#: version.c:683
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X 版本"
+
+#: version.c:686
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS 版本"
+
+#: version.c:691
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS 版本"
+
+#: version.c:701
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"加入补ä¸: "
+
+#: version.c:728
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"编译"
+
+#: version.c:731
+msgid "by "
+msgstr "者:"
+
+#: version.c:743
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"超强版本 "
+
+#: version.c:746
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"大型版本 "
+
+#: version.c:749
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"一般版本 "
+
+#: version.c:752
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"简易版本 "
+
+#: version.c:754
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"精简版本 "
+
+#: version.c:760
+msgid "without GUI."
+msgstr "ä¸ä½¿ç”¨å›¾åž‹ç•Œé¢ã€‚"
+
+#: version.c:764
+msgid "with GTK-GNOME GUI."
+msgstr "使用 GTK-GNOME 图型界é¢ã€‚"
+
+#: version.c:766
+msgid "with GTK GUI."
+msgstr "使用 GTK 图型界é¢ã€‚"
+
+#: version.c:770
+msgid "with X11-Motif GUI."
+msgstr "使用 X11-Motif 图型界é¢ã€‚"
+
+#: version.c:773
+msgid "with X11-Athena GUI."
+msgstr "使用 X11-Athena 图型界é¢ã€‚"
+
+#: version.c:776
+msgid "with BeOS GUI."
+msgstr "使用 BeOS 图型界é¢ã€‚"
+
+#: version.c:779
+msgid "with Photon GUI."
+msgstr "使用Photon图型界é¢ã€‚"
+
+#: version.c:782
+msgid "with GUI."
+msgstr "使用图型界é¢ã€‚"
+
+#: version.c:785
+msgid "with Carbon GUI."
+msgstr "使用 Carbon 图型界é¢ã€‚"
+
+#: version.c:788
+msgid "with Cocoa GUI."
+msgstr "使用 Cocoa 图型界é¢ã€‚"
+
+#: version.c:791
+msgid "with (classic) GUI."
+msgstr "使用 (传统) 图型界é¢ã€‚"
+
+#: version.c:802
+msgid " Features included (+) or not (-):\n"
+msgstr " ç›®å‰å¯ä½¿ç”¨(+)与ä¸å¯ä½¿ç”¨(-)的模å—列表:\n"
+
+#: version.c:814
+msgid " system vimrc file: \""
+msgstr " 系统 vimrc é…置文件: \""
+
+#: version.c:819
+msgid " user vimrc file: \""
+msgstr " 用户的 vimrc é…置文件: \""
+
+#: version.c:824
+msgid " 2nd user vimrc file: \""
+msgstr " 第二组用户 vimrc 文件: \""
+
+#: version.c:829
+msgid " 3rd user vimrc file: \""
+msgstr " 第三组用户 vimrc 文件: \""
+
+#: version.c:834
+msgid " user exrc file: \""
+msgstr " 用户的 exrc é…置文件: \""
+
+#: version.c:839
+msgid " 2nd user exrc file: \""
+msgstr " 第二组用户 exrc 文件: \""
+
+#: version.c:845
+msgid " system gvimrc file: \""
+msgstr " 系统 gvimrc 文件: \""
+
+#: version.c:849
+msgid " user gvimrc file: \""
+msgstr " 用户的 gvimrc é…置文件: \""
+
+#: version.c:853
+msgid "2nd user gvimrc file: \""
+msgstr " 第二组用户 gvimrc 文件: \""
+
+#: version.c:858
+msgid "3rd user gvimrc file: \""
+msgstr " 第三组用户 gvimrc 文件: \""
+
+#: version.c:865
+msgid " system menu file: \""
+msgstr " 系统èœå•é…置文件: \""
+
+#: version.c:873
+msgid " fall-back for $VIM: \""
+msgstr " $VIM 预设值: \""
+
+#: version.c:879
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " $VIMRUNTIME 预设值: \""
+
+#: version.c:883
+msgid "Compilation: "
+msgstr "编译方å¼: "
+
+#: version.c:889
+msgid "Compiler: "
+msgstr "编译器: "
+
+#: version.c:894
+msgid "Linking: "
+msgstr "链结方å¼: "
+
+#: version.c:899
+msgid " DEBUG BUILD"
+msgstr " 调试版本"
+
+#: version.c:934
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved"
+
+#: version.c:936
+msgid "version "
+msgstr "版本 "
+
+#: version.c:937
+msgid "by Bram Moolenaar et al."
+msgstr "维护人: Bram Moolenaar et al."
+
+#: version.c:938
+msgid "Vim is open source and freely distributable"
+msgstr "Vim 为å¯è‡ªç”±å‘行的开放æºä»£ç è½¯ä»¶"
+
+#: version.c:940
+msgid "Help poor children in Uganda!"
+msgstr "帮助乌干达的å¯æ€œå„¿ç«¥!"
+
+#: version.c:941
+msgid "type :help iccf<Enter> for information "
+msgstr "进一步说明请输入 :help iccf<Enter>"
+
+#: version.c:943
+msgid "type :q<Enter> to exit "
+msgstr "è¦é€€å‡ºè¯·è¾“å…¥ :q<Enter> "
+
+#: version.c:944
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "在线帮助请输入 :help<Enter> "
+
+#: version.c:945
+msgid "type :help version6<Enter> for version info"
+msgstr "新版本信æ¯è¯·è¾“å…¥ :help version6<Enter>"
+
+#: version.c:948
+msgid "Running in Vi compatible mode"
+msgstr "Vi 兼容模å¼"
+
+#: version.c:949
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "如果è¦å®Œå…¨æ¨¡æ‹Ÿä¼ ç»Ÿ Vi 请输入 :set nocp<Enter>"
+
+#: version.c:950
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "如果需è¦å¯¹ Vi 兼容模å¼è¿›ä¸€æ­¥è¯´æ˜Žè¯·è¾“å…¥ :help cp-default<Enter>"
+
+#: version.c:990
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "注æ„: 检测到 Windows 95/98/ME"
+
+#: version.c:993
+msgid "type :help windows95<Enter> for info on this"
+msgstr "如果需è¦å¯¹ Windows 95 支æŒçš„更多信æ¯è¯·è¾“å…¥ :help windows95<Enter>"
+
+#: window.c:201
+msgid "E441: There is no preview window"
+msgstr "E441: 没有预览窗å£"
+
+#: window.c:568
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: ä¸èƒ½åŒæ—¶åˆ†å‰²çª—å£ä¸ºå·¦ä¸Šå’Œå³ä¸‹è§’"
+
+#: window.c:1327
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: 有其它分割窗å£æ—¶ä¸èƒ½æ—‹è½¬"
+
+#: window.c:1810
+msgid "E444: Cannot close last window"
+msgstr "E444: ä¸èƒ½å…³é—­æœ€åŽä¸€ä¸ªçª—å£"
+
+#: window.c:2474
+msgid "Already only one window"
+msgstr "å·²ç»åªå‰©ä¸€ä¸ªçª—å£äº†"
+
+#: window.c:2521
+msgid "E445: Other window contains changes"
+msgstr "E445: 其它窗å£æœ‰æ”¹å˜çš„内容"
+
+#: window.c:4341
+msgid "E446: No file name under cursor"
+msgstr "E446: 光标处没有文件å"
+
+#: window.c:4460
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: 在路径中找ä¸åˆ°æ–‡ä»¶ \"%s\""
+
+#: ../GvimExt/gvimext.cpp:586
+msgid "Edit with &multiple Vims"
+msgstr "用 &multiple Vims 编辑"
+
+#: ../GvimExt/gvimext.cpp:592
+msgid "Edit with single &Vim"
+msgstr "用 single &Vim 编辑"
+
+#: ../GvimExt/gvimext.cpp:604
+msgid "Edit with &Vim"
+msgstr "用 &Vim 编辑"
+
+#. Now concatenate
+#: ../GvimExt/gvimext.cpp:628
+msgid "Edit with existing Vim - &"
+msgstr "用当å‰çš„ Vim 编辑 - &"
+
+#: ../GvimExt/gvimext.cpp:752
+msgid "Edits the selected file(s) with Vim"
+msgstr "用 Vim 编辑选择的文件"
+
+#: ../GvimExt/gvimext.cpp:891 ../GvimExt/gvimext.cpp:969
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "创建进程失败: 请检查gvim是å¦åœ¨å¯æ‰§è¡Œè·¯å¾„中!"
+
+#: ../GvimExt/gvimext.cpp:892 ../GvimExt/gvimext.cpp:906
+#: ../GvimExt/gvimext.cpp:970
+msgid "gvimext.dll error"
+msgstr "gvimext.dll 出错"
+
+#: ../GvimExt/gvimext.cpp:905
+msgid "Path length too long!"
+msgstr "路径å太长"
+
+#: globals.h:878
+msgid "--No lines in buffer--"
+msgstr "--缓冲区无资料--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1019
+msgid "Command aborted"
+msgstr "命令被强制中断"
+
+#: globals.h:1020
+msgid "Argument required"
+msgstr "需è¦æŒ‡ä»¤å‚æ•°"
+
+#: globals.h:1021
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ åŽé¢åº”该有 / ? 或 &"
+
+#: globals.h:1023
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: ä¸èƒ½åœ¨å‘½ä»¤è¡Œçª—å£ä¸­ä½¿ç”¨ã€‚<CR>执行,CTRL-C 退出"
+
+#: globals.h:1025
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr "E12: exrc/vimrc 里的指令ä¸èƒ½æ‰§è¡Œ"
+
+#: globals.h:1026
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: 文件已ç»å­˜åœ¨ (å¯ç”¨ ! 强制替æ¢)"
+
+#: globals.h:1027
+msgid "Command failed"
+msgstr "命令执行失败"
+
+#: globals.h:1028
+msgid "Internal error"
+msgstr "内部错误"
+
+#: globals.h:1029
+msgid "Interrupted"
+msgstr "已中断"
+
+#: globals.h:1030
+msgid "E14: Invalid address"
+msgstr "E14: ä¸æ­£ç¡®çš„地å€"
+
+#: globals.h:1031
+msgid "Invalid argument"
+msgstr "ä¸æ­£ç¡®çš„å‚æ•°"
+
+#: globals.h:1032
+#, c-format
+msgid "Invalid argument: %s"
+msgstr "ä¸æ­£ç¡®çš„å‚æ•°: %s"
+
+#: globals.h:1034
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: ä¸æ­£ç¡®çš„表达å¼: %s"
+
+#: globals.h:1036
+msgid "E16: Invalid range"
+msgstr "E16: ä¸æ­£ç¡®çš„范围"
+
+#: globals.h:1037
+msgid "Invalid command"
+msgstr "ä¸æ­£ç¡®çš„命令"
+
+#: globals.h:1039
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" 是目录"
+
+#: globals.h:1042
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: '=' å‰é¢å‡ºçŽ°äº†é”™è¯¯çš„字符"
+
+#: globals.h:1044
+msgid "E19: Mark has invalid line number"
+msgstr "E19: 标记的行å·é”™è¯¯"
+
+#: globals.h:1045
+msgid "E20: Mark not set"
+msgstr "E20: 没有设定标记"
+
+#: globals.h:1046
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: 因为 'modifiable' 选项是关闭的,所以ä¸èƒ½ä¿®æ”¹"
+
+#: globals.h:1047
+msgid "E22: Scripts nested too deep"
+msgstr "E22: 递归调用太多层"
+
+#: globals.h:1048
+msgid "E23: No alternate file"
+msgstr "E23: 没有替代的文件"
+
+#: globals.h:1049
+msgid "E24: No such abbreviation"
+msgstr "E24: 没有这个 abbreviation 对应"
+
+#: globals.h:1050
+msgid "No ! allowed"
+msgstr "ä¸å¯ä½¿ç”¨ '!'"
+
+#: globals.h:1052
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: 因为编译时没有加入图型界é¢çš„程åºä»£ç ï¼Œæ‰€ä»¥ä¸èƒ½ä½¿ç”¨å›¾åž‹ç•Œé¢"
+
+#: globals.h:1055
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: 因为编译时没有加入希伯莱的程åºä»£ç ï¼Œæ‰€ä»¥ä¸èƒ½ä½¿ç”¨ Hebrew\n"
+
+#: globals.h:1058
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: 因为编译时没有加入 Farsi 的程åºä»£ç ï¼Œæ‰€ä»¥ä¸èƒ½ä½¿ç”¨ Farsi\n"
+
+#: globals.h:1061
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: 没有å为 '%s' çš„ highlight group"
+
+#: globals.h:1063
+msgid "E29: No inserted text yet"
+msgstr "E29: 没有æ’入过文字"
+
+#: globals.h:1064
+msgid "E30: No previous command line"
+msgstr "E30: 没有å‰ä¸€é¡¹å‘½ä»¤"
+
+#: globals.h:1065
+msgid "E31: No such mapping"
+msgstr "E31: 没有这个 mapping 对应"
+
+#: globals.h:1066
+msgid "No match"
+msgstr "找ä¸åˆ°"
+
+#: globals.h:1067
+#, c-format
+msgid "No match: %s"
+msgstr "找ä¸åˆ°: %s"
+
+#: globals.h:1068
+msgid "E32: No file name"
+msgstr "E32: 没有文件å"
+
+#: globals.h:1069
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: 没有å‰ä¸€ä¸ªæŸ¥æ‰¾/替æ¢çš„命令"
+
+#: globals.h:1070
+msgid "E34: No previous command"
+msgstr "E34: 没有å‰ä¸€ä¸ªå‘½ä»¤"
+
+#: globals.h:1071
+msgid "E35: No previous regular expression"
+msgstr "E35: 没有å‰ä¸€ä¸ªæŸ¥æ‰¾å‘½ä»¤"
+
+#: globals.h:1072
+msgid "No range allowed"
+msgstr "ä¸å¯ä½¿ç”¨èŒƒå›´å‘½ä»¤"
+
+#: globals.h:1074
+msgid "E36: Not enough room"
+msgstr "E36: 没有足够的空间"
+
+#: globals.h:1076
+#, c-format
+msgid "Can't create file %s"
+msgstr "ä¸èƒ½åˆ›å»ºæ–‡ä»¶ %s"
+
+#: globals.h:1077
+msgid "Can't get temp file name"
+msgstr "ä¸èƒ½å¾—到临时文件å"
+
+#: globals.h:1078
+#, c-format
+msgid "Can't open file %s"
+msgstr "ä¸èƒ½æ‰“开文件 %s"
+
+#: globals.h:1079
+#, c-format
+msgid "Can't read file %s"
+msgstr "ä¸èƒ½è¯»å–文件 %s"
+
+#: globals.h:1080
+msgid "E37: No write since last change (use ! to override)"
+msgstr "E37: 文件内容已改å˜ä½†å°šæœªä¿å­˜ (å¯ç”¨ ! 强制执行)"
+
+#: globals.h:1081
+msgid "E38: Null argument"
+msgstr "E38: 空的 (Null) å‚æ•°"
+
+#: globals.h:1083
+msgid "E39: Number expected"
+msgstr "E39: 应该è¦æœ‰æ•°å­—"
+
+#: globals.h:1086
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: ä¸èƒ½æ‰“开错误文件 %s"
+
+#: globals.h:1089
+msgid "E41: Out of memory!"
+msgstr "E41: 内存ä¸è¶³!"
+
+#: globals.h:1092
+msgid "Pattern not found"
+msgstr "找ä¸åˆ°æ¨¡å¼"
+
+#: globals.h:1094
+#, c-format
+msgid "Pattern not found: %s"
+msgstr "找ä¸åˆ°æ¨¡å¼ %s"
+
+#: globals.h:1095
+msgid "Argument must be positive"
+msgstr "å‚数应该是正数"
+
+#: globals.h:1097
+msgid "E42: No Errors"
+msgstr "E42: 没有错误"
+
+#: globals.h:1099
+msgid "E43: Damaged match string"
+msgstr "E43: 匹é…字符串有问题"
+
+#: globals.h:1100
+msgid "E44: Corrupted regexp program"
+msgstr "E44: 正则表达å¼æœ‰é—®é¢˜"
+
+#: globals.h:1101
+msgid "E45: 'readonly' option is set (use ! to override)"
+msgstr "E45: 设定 'readonly' 选项(åªè¯») (å¯ç”¨ ! 强制执行)"
+
+#: globals.h:1103
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: ä¸èƒ½è®¾å®šåªè¯»å˜é‡ \"%s\""
+
+#: globals.h:1106
+msgid "E47: Error while reading errorfile"
+msgstr "E47: 读å–错误文件失败"
+
+#: globals.h:1109
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: ä¸èƒ½åœ¨ sandbox 里出现"
+
+#: globals.h:1111
+msgid "E49: Invalid scroll size"
+msgstr "E49: 错误的滚动大å°"
+
+#: globals.h:1112
+msgid "E91: 'shell' option is empty"
+msgstr "E91: 'E71: 选项 'shell' 未设定"
+
+#: globals.h:1113
+msgid "E72: Close error on swap file"
+msgstr "E72: 交æ¢æ–‡ä»¶å…³é—­é”™è¯¯"
+
+#: globals.h:1114
+msgid "E73: tag stack empty"
+msgstr "E73: 标签堆栈已空"
+
+#: globals.h:1115
+msgid "E74: Command too complex"
+msgstr "E74: 命令太å¤æ‚"
+
+#: globals.h:1116
+msgid "E75: Name too long"
+msgstr "E75: å字太长"
+
+#: globals.h:1117
+msgid "E76: Too many ["
+msgstr "E76: 太多 ["
+
+#: globals.h:1118
+msgid "E77: Too many file names"
+msgstr "E77: 太多文件å"
+
+#: globals.h:1119
+msgid "Trailing characters"
+msgstr "你输入了多余的字符"
+
+#: globals.h:1120
+msgid "E78: Unknown mark"
+msgstr "E78: ä¸èƒ½åŠžè¯†çš„标记"
+
+#: globals.h:1121
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: ä¸èƒ½æ‰©å±•é€šé…符"
+
+#: globals.h:1122
+msgid "E80: Error while writing"
+msgstr "E80: 写入错误"
+
+#: globals.h:1123
+msgid "Zero count"
+msgstr "数到零 (?)"
+
+#: globals.h:1125
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: <SID> ä¸èƒ½åœ¨ script 本文外使用."
diff --git a/src/po/zh_CN.cp936.po b/src/po/zh_CN.cp936.po
new file mode 100644
index 000000000..53e6cbcb3
--- /dev/null
+++ b/src/po/zh_CN.cp936.po
@@ -0,0 +1,5937 @@
+# Chinese (simplified) Translation for Vim
+#
+# Do ":help uganda" in Vim to read copying and usage conditions.
+# Do ":help credits" in Vim to see a list of people who contributed.
+#
+# FIRST AUTHOR Wang Jun <junw@turbolinux.com.cn>
+#
+# Generated from zh_CN.po, DO NOT EDIT.
+#
+#, no-wrap
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim(Simplified Chinese)\n"
+"POT-Creation-Date: 2001-09-24 10:10+0800\n"
+"PO-Revision-Date: 2001-09-24 11:13+0800\n"
+"Last-Translator: Wang Jun <junw@turbolinux.com.cn>\n"
+"Language-Team: Wang Jun <junw@turbolinux.com.cn>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=gbk\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: ²»ÄÜ·ÖÅäÈκλº³åÇø£¬Í˳ö³ÌÐò..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: ²»ÄÜ·ÖÅ仺³åÇø£¬Ê¹ÓÃÁíÒ»¸ö»º³åÇø...."
+
+#: buffer.c:698
+msgid "No buffers were unloaded"
+msgstr "ûÓÐÊÍ·ÅÈκλº³åÇø"
+
+#: buffer.c:700
+msgid "No buffers were deleted"
+msgstr "ûÓÐɾ³ýÈκλº³åÇø"
+
+#: buffer.c:702
+msgid "No buffers were wiped out"
+msgstr "ûÓÐɾ³ýÈκλº³åÇø"
+
+#: buffer.c:710
+msgid "1 buffer unloaded"
+msgstr "ÒÑÊÍ·ÅÒ»¸ö»º³åÇø"
+
+#: buffer.c:712
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "ÒÑÊÍ·Å %d ¸ö»º³åÇø"
+
+#: buffer.c:717
+msgid "1 buffer deleted"
+msgstr "ÒÑɾ³ýÒ»¸ö»º³åÇø"
+
+#: buffer.c:719
+#, c-format
+msgid "%d buffers deleted"
+msgstr "ÒÑɾ³ý %d ¸ö»º³åÇø"
+
+#: buffer.c:724
+msgid "1 buffer wiped out"
+msgstr "ÒÑɾ³ýÒ»¸ö»º³åÇø"
+
+#: buffer.c:726
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "ÒÑɾ³ý %d ¸ö»º³åÇø"
+
+#: buffer.c:783
+msgid "E84: No modified buffer found"
+msgstr "E84: ûÓÐÐ޸ĹýµÄ»º³åÇø"
+
+#. back where we started, didn't find anything.
+#: buffer.c:822
+msgid "E85: There is no listed buffer"
+msgstr "E85: ûÓпÉÁгöµÄ»º³åÇø"
+
+#: buffer.c:834
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: ²»ÄÜÇл»µ½µÚ %ld ¸ö»º³åÇø"
+
+#: buffer.c:837
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: ²»ÄÜÇл»µ½¸üºóÃæµÄ»º³åÇø"
+
+#: buffer.c:839
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: ²»ÄÜÇл»µ½¸üÇ°ÃæµÄ»º³åÇø"
+
+#: buffer.c:863
+#, c-format
+msgid "E89: No write since last change for buffer %ld (use ! to override)"
+msgstr "E89: ÒѸü¸Ä¹ý»º³åÇø %ld µ«ÉÐδ±£´æ (¿ÉÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: buffer.c:879
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: ²»ÄÜÊÍ·Å×îºóÒ»¸ö»º³åÇø"
+
+#: buffer.c:1314
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: ¾¯¸æ: ÎļþÃû¹ý¶à"
+
+#: buffer.c:1480
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: ÕÒ²»µ½µÚ %ld ¸ö»º³åÇø"
+
+#: buffer.c:1700
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: ÕÒµ½Ò»¸öÒÔÉ쵀 %s"
+
+#: buffer.c:1702
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: ÕÒ²»µ½ %s"
+
+#: buffer.c:2105 ex_docmd.c:6065
+#, c-format
+msgid "line %ld"
+msgstr "ÐÐ %ld"
+
+#: buffer.c:2188
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: ÒÑÓлº³åÇøʹÓÃÕâ¸öÃû×Ö"
+
+#: buffer.c:2481
+msgid " [Modified]"
+msgstr " [ÒÑÐÞ¸Ä]"
+
+#: buffer.c:2486
+msgid "[Not edited]"
+msgstr "[δ±à¼­]"
+
+#: buffer.c:2491
+msgid "[New file]"
+msgstr "[ÐÂÎļþ]"
+
+#: buffer.c:2492
+msgid "[Read errors]"
+msgstr "[¶Á´íÎó]"
+
+#: buffer.c:2494 fileio.c:1754
+msgid "[readonly]"
+msgstr "[Ö»¶Á]"
+
+#: buffer.c:2510
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "ÐÐÊý 1 --%d%%--"
+
+#: buffer.c:2510
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "ÐÐÊý %ld --%d%%--"
+
+#: buffer.c:2518
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "ÐÐ %ld/%ld --%d%%-- ÁÐ "
+
+#: buffer.c:2606
+msgid "[No file]"
+msgstr "[δÃüÃû]"
+
+#. must be a help buffer
+#: buffer.c:2646
+msgid "help"
+msgstr "[°ïÖú]"
+
+#: buffer.c:3151 screen.c:4657
+msgid "[help]"
+msgstr "[°ïÖú]"
+
+#: buffer.c:3183 screen.c:4663
+msgid "[Preview]"
+msgstr "[Ô¤ÀÀ]"
+
+#: buffer.c:3389
+msgid "All"
+msgstr "È«²¿"
+
+#: buffer.c:3389
+msgid "Bot"
+msgstr "µ×¶Ë"
+
+#: buffer.c:3391
+msgid "Top"
+msgstr "¶¥¶Ë"
+
+#: buffer.c:4127
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# »º³åÇøÁбí:\n"
+
+#: buffer.c:4160
+msgid "[Error List]"
+msgstr "[´íÎóÁбí]"
+
+#: buffer.c:4173 memline.c:1513
+msgid "[No File]"
+msgstr "[δÃüÃû]"
+
+#: buffer.c:4393
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- ·ûºÅ ---"
+
+#: buffer.c:4403
+#, c-format
+msgid "Signs for %s:"
+msgstr "%s µÄ·ûºÅ:"
+
+#: buffer.c:4409
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " ÐÐ=%ld id=%d Ãû³Æ=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: ²»ÄܱȽÏ(diff) %ld¸öÒÔÉϵĻº³åÇø"
+
+#: diff.c:648
+msgid "E97: Cannot create diffs"
+msgstr "E97: ²»ÄÜ´´½¨ diff "
+
+#: diff.c:747
+msgid "Patch file"
+msgstr "Patch Îļþ"
+
+#: diff.c:991
+msgid "E98: Cannot read diff output"
+msgstr "E98: ²»ÄܶÁÈ¡ diff µÄÊä³ö"
+
+#: diff.c:1704
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Ä¿Ç°µÄ»º³åÇø²»ÊÇÔÚ diff ģʽ"
+
+#: diff.c:1716
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: ûÓлº³åÇøÔÚ diff ģʽ"
+
+#: diff.c:1724
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: ÓÐÁ½¸öÒÔÉϵĻº³åÇøÔÚ diff ģʽ£¬²»Äܾö¶¨ÒªÓÃÄÄÒ»¸ö"
+
+#: diff.c:1747
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: ÕÒ²»µ½»º³åÇø: \"%s\""
+
+#: diff.c:1753
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: »º³åÇø \"%s\" ²»ÊÇÔÚ diff ģʽ"
+
+#: digraph.c:2168
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: ¸´ºÏ×Ö·û(digraph)Öв»ÄÜʹÓà Escape"
+
+#: digraph.c:2340
+msgid "Keymap file not found"
+msgstr "ÕÒ²»µ½ keymap Îļþ"
+
+#: digraph.c:2367
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: ʹÓà :loadkeymap "
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " ¹Ø¼ü×Ö×Ô¶¯Íê³É (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " ^X ģʽ (^E/^Y/^L/^]/^F/^I/^K/^D/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " ÇøÓò¹Ø¼ü×Ö×Ô¶¯Íê³É (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " ÕûÐÐ×Ô¶¯Íê³É (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " ÎļþÃû×Ô¶¯Íê³É (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " ±êÇ©×Ô¶¯Íê³É (^]/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " ·¾¶×Ô¶¯Íê³É (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " ¶¨Òå×Ô¶¯Íê³É (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " ×Öµä×Ô¶¯Íê³É (^K/^N/^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Thesaurus ×Ô¶¯Íê³É (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " ÃüÁî×Ô¶¯Íê³É (^V/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Òѵ½¶ÎÂä½áβ"
+
+#: edit.c:894
+msgid "'thesaurus' option is empty"
+msgstr "Ñ¡Ïî 'thesaurus' δÉ趨"
+
+#: edit.c:1070
+msgid "'dictionary' option is empty"
+msgstr "Ñ¡Ïî 'dictionary' Ϊ¿Õ"
+
+#: edit.c:1992
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "ɨÃè×Öµä: %s"
+
+#: edit.c:2183
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (²åÈë) Scroll (^E/^Y)"
+
+#: edit.c:2185
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (Ìæ»») Scroll (^E/^Y)"
+
+#: edit.c:2496
+#, c-format
+msgid "Scanning: %s"
+msgstr "ɨÃèÖÐ: %s"
+
+#: edit.c:2531
+msgid "Scanning tags."
+msgstr "ɨÃè±êÇ©."
+
+#: edit.c:3189
+msgid " Adding"
+msgstr " Ôö¼Ó"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3238
+msgid "-- Searching..."
+msgstr "-- ËÑÑ°ÖÐ..."
+
+#: edit.c:3294
+msgid "Back at original"
+msgstr "»Øµ½Æðµã"
+
+#: edit.c:3299
+msgid "Word from other line"
+msgstr "´ÓÆäËüÐпªÊ¼µÄ´Ê (?)"
+
+#: edit.c:3304
+msgid "The only match"
+msgstr "Ö»ÓдËÏîÆ¥Åä"
+
+#: edit.c:3363
+#, c-format
+msgid "match %d of %d"
+msgstr "ÕÒµ½ %d / %d"
+
+#: edit.c:3366
+#, c-format
+msgid "match %d"
+msgstr "Æ¥Åä %d"
+
+#: eval.c:696
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: 䶨ÒåµÄ±äÁ¿: \"%s\""
+
+#: eval.c:975
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: ȱÉÙ¶ÔÓ¦µÄÀ¨ºÅ: %s"
+
+#: eval.c:1043
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Î޴˱äÁ¿: \"%s\""
+
+#: eval.c:1284
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: '?' ºóȱÉÙ ':'"
+
+#: eval.c:1898
+msgid "E110: Missing ')'"
+msgstr "E110: ȱÉÙ¶ÔÓ¦µÄ \")\""
+
+#: eval.c:1948
+msgid "E111: Missing ']'"
+msgstr "E111: ȱÉÙ¶ÔÓ¦µÄ \"]\""
+
+#: eval.c:2023
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: ȱÉÙÑ¡ÏîÃû³Æ: %s"
+
+#: eval.c:2041
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: ²»ÕýÈ·µÄÑ¡Ïî: %s"
+
+#: eval.c:2103
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: ȱÉÙÒýºÅ: %s"
+
+#: eval.c:2220
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: ȱÉÙÒýºÅ: %s"
+
+#: eval.c:2537
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: º¯Êý %s µÄ²ÎÊý²»ÕýÈ·"
+
+#: eval.c:2538
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: 䶨ÒåµÄº¯Êý: %s"
+
+#: eval.c:2539
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: º¯Êý %s µÄ²ÎÊý¹ý¶à"
+
+#: eval.c:2540
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: º¯Êý %s µÄ²ÎÊýÌ«ÉÙ"
+
+#: eval.c:2541
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: <SID> ²»ÄÜÔÚ script ÉÏÏÂÎÄÍâʹÓÃ: %s"
+
+#: eval.c:3574
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld ÐÐ: "
+
+#: eval.c:4689
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"È·¶¨(&O)\n"
+"È¡Ïû(&C)"
+
+#: eval.c:5511
+msgid "E240: No connection to Vim server"
+msgstr "E240: ûÓÐÓë Vim Server ´´½¨Á¬½Ó"
+
+#: eval.c:5601
+msgid "E277: Unable to read a server reply"
+msgstr "E277: ²»ÄܶÁÈ¡·þÎñÆ÷µÄÏìÓ¦"
+
+#: eval.c:5626
+msgid "E258: Unable to send to client"
+msgstr "E258: ²»ÄÜ´«Ë͵½¿Í»§¶Ë"
+
+#: eval.c:5667
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: ²»ÄÜ´«Ë͵½ %s"
+
+#: eval.c:5763
+msgid "(Invalid)"
+msgstr "(ÎÞЧ)"
+
+#: eval.c:6766
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: ±äÁ¿ %s ÉÐ䶨Òå"
+
+#: eval.c:7464
+#, c-format
+msgid "E122: Function %s already exists, use ! to replace"
+msgstr "E122: º¯Êý %s ÒѾ­´æÔÚ, ÇëʹÓà ! Ç¿ÖÆÌæ»»"
+
+#: eval.c:7506
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: º¯Êý %s ÉÐ䶨Òå"
+
+#: eval.c:7519
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: ȱÉÙ \"(\": %s"
+
+#: eval.c:7551
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: ²ÎÊý²»ÕýÈ·: %s"
+
+#: eval.c:7637
+msgid "E126: Missing :endfunction"
+msgstr "E126: ȱÉÙ :endfunction"
+
+#: eval.c:7716
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: º¯Êý %s ÕýÔÚʹÓÃÖУ¬²»ÄÜÖØж¨Òå"
+
+#: eval.c:7773
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: º¯ÊýÃû³ÆµÚÒ»¸ö×Öĸ±ØÐë´óд: %s"
+
+#: eval.c:7779
+msgid "E129: Function name required"
+msgstr "E129: ÐèÒªº¯ÊýÃû³Æ"
+
+#: eval.c:7872
+msgid "function "
+msgstr "º¯Êý "
+
+#: eval.c:7987
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: º¯Êý %s ÉÐ䶨Òå"
+
+#: eval.c:7992
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: º¯Êý %s ÕýÔÚʹÓÃÖУ¬²»ÄÜɾ³ý"
+
+#: eval.c:8039
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: º¯ÊýµÝ¹éµ÷ÓòãÊý³¬¹ý 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:8090
+#, c-format
+msgid "calling %s"
+msgstr "µ÷ÓÃ %s"
+
+#. always scroll up, don't overwrite
+#: eval.c:8115 ex_cmds2.c:1973
+#, c-format
+msgid "continuing in %s"
+msgstr "¼ÌÐø: %s"
+
+#: eval.c:8169
+msgid "E133: :return not inside a function"
+msgstr "E133: :return ±ØÐëÔÚº¯ÊýÀïʹÓÃ"
+
+#: eval.c:8247
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s ·µ»ØÖµ #%ld "
+
+#: eval.c:8250
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s ·µ»ØÖµ \"%s\""
+
+#: eval.c:8391
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# È«¾Ö±äÁ¿:\n"
+
+#: ex_cmds2.c:70
+msgid "Entering Debug mode. Type \"cont\" to leave."
+msgstr "½øÈëµ÷ÊÔģʽ. ÊäÈë \"cont\" ÒԻص½Õý³£Ä£Ê½."
+
+#: ex_cmds2.c:74 ex_docmd.c:771
+#, c-format
+msgid "line %ld: %s"
+msgstr "ÐÐ %ld: %s"
+
+#: ex_cmds2.c:76
+#, c-format
+msgid "cmd: %s"
+msgstr "cmd: %s"
+
+#: ex_cmds2.c:224
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "\"%s%s\" Öжϵã: µÚ %ld ÐÐ"
+
+#: ex_cmds2.c:388
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: ÕÒ²»µ½Öжϵã: %s"
+
+#: ex_cmds2.c:414
+msgid "No breakpoints defined"
+msgstr "ûÓж¨ÒåÖжϵã"
+
+#: ex_cmds2.c:419
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s µÚ %ld ÐÐ"
+
+#: ex_cmds.c:2053 ex_cmds.c:2289 ex_cmds2.c:602
+msgid "Save As"
+msgstr "Áí´æΪ"
+
+#: ex_cmds2.c:625
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "½«¸Ä±ä±£´æµ½ \"%.*s\"?"
+
+#: ex_cmds2.c:627 ex_docmd.c:8612
+msgid "Untitled"
+msgstr "δÃüÃû"
+
+#: ex_cmds2.c:763
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: ÒѸü¸Ä¹ý»º³åÇø \"%s\" µ«ÉÐδ±£´æ (¿ÉÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: ex_cmds2.c:832
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "×¢Òâ: ÒÑÇл»µ½ÆäËü»º³åÇø (Çë¼ì²é Autocommands ÓÐÎÞ´íÎó)"
+
+#: ex_cmds2.c:1208
+msgid "E163: There is only one file to edit"
+msgstr "E163: Ö»ÓÐÒ»¸öÎļþ¿É±à¼­"
+
+#: ex_cmds2.c:1210
+msgid "E164: Cannot go before first file"
+msgstr "E164: ÒѾ­ÔÚµÚÒ»¸öÎļþÁË"
+
+#: ex_cmds2.c:1212
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: ÒѾ­ÔÚ×îºóÒ»¸öÎļþÁË"
+
+#: ex_cmds2.c:1632
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "²éÕÒÖÐ: \"%s\" -- \"%s\""
+
+#: ex_cmds2.c:1654
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "²éÕÒÖÐ: \"%s\""
+
+#: ex_cmds2.c:1678
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "ÔÚ 'runtimepath' ÀïÕÒ²»µ½ \"%s\""
+
+#: ex_cmds2.c:1712
+msgid "Run Macro"
+msgstr "Ö´Ðкê"
+
+#: ex_cmds2.c:1817
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "²»ÄÜÖ´ÐÐĿ¼£º \"%s\""
+
+#: ex_cmds2.c:1847
+#, c-format
+msgid "could not source \"%s\""
+msgstr "²»ÄÜÖ´ÐÐ \"%s\""
+
+#: ex_cmds2.c:1849
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "µÚ %ld ÐÐ: ²»ÄÜÖ´ÐÐ \"%s\""
+
+#: ex_cmds2.c:1863
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "Ö´ÐÐ \"%s\" ÖÐ"
+
+#: ex_cmds2.c:1865
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "µÚ %ld ÐÐ: ½áÊøÖ´ÐÐ %s"
+
+#: ex_cmds2.c:1971
+#, c-format
+msgid "finished sourcing %s"
+msgstr "½áÊøÖ´ÐÐ %s"
+
+#: ex_cmds2.c:2272
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: ×¢Òâ: ´íÎóµÄÐзָô×Ö·û£¬¿ÉÄÜÊÇÉÙÁË ^M"
+
+#: ex_cmds2.c:2321
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: ÔÚÖ´ÐÐ script ÎļþÍâ²»¿ÉʹÓà :scriptencoding"
+
+#: ex_cmds2.c:2354
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: ÔÚÖ´ÐÐ script ÎļþÍâ²»¿ÉʹÓà :finish"
+
+#: ex_cmds2.c:2820
+msgid "No text to be printed"
+msgstr "ûÓÐÒª´òÓ¡µÄÎÄ×Ö"
+
+#: ex_cmds2.c:2898
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "´òÓ¡ÖÐ: µÚ %d Ò³ (%d%%)"
+
+#: ex_cmds2.c:2907
+#, c-format
+msgid " Copy %d of %d"
+msgstr "¸´ÖÆ %d / %d"
+
+#: ex_cmds2.c:2959
+#, c-format
+msgid "Printed: %s"
+msgstr "ÒÑ´òÓ¡: %s"
+
+#: ex_cmds2.c:2966
+msgid "Printing aborted"
+msgstr "´òÓ¡ÖжÏ"
+
+#: ex_cmds2.c:3344
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: дÈë PostScript Îļþ³ö´í"
+
+#: ex_cmds2.c:4019
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: ²»ÄÜ´ò¿ª PostScript Êä³öÎļþ"
+
+#: ex_cmds2.c:4057
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: ²»ÄÜ´ò¿ªÎļþ \"%s\""
+
+#: ex_cmds2.c:4068
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: ²»ÄܶÁ PostScript ×ÊÔ´Îļþ \"%s\""
+
+#: ex_cmds2.c:4266
+msgid "Sending to printer..."
+msgstr "·¢Ë͵½´òÓ¡»ú..."
+
+#: ex_cmds2.c:4270
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: ´òÓ¡ PostScript Îļþʧ°Ü"
+
+#: ex_cmds2.c:4272
+msgid "Print job sent."
+msgstr ""
+
+#: ex_cmds2.c:4646
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Ä¿Ç°µÄ %sÓïÑÔ: \"%s\""
+
+#: ex_cmds2.c:4653
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: ²»ÄÜÉ趨ÓïÑÔΪ \"%s\""
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Ê®Áù½øÖÆ %02x, °Ë½øÖÆ %03o"
+
+#: ex_cmds.c:428
+msgid "E134: Move lines into themselves"
+msgstr "E134: ²»ÄÜ°ÑÐÐÒƵ½Ëü×ÔÒÑÄÚ"
+
+#: ex_cmds.c:497
+msgid "1 line moved"
+msgstr "ÒÑÒƶ¯ 1 ÐÐ"
+
+#: ex_cmds.c:499
+#, c-format
+msgid "%ld lines moved"
+msgstr "ÒÑ°áÒÆ %ld ÐÐ"
+
+#: ex_cmds.c:890
+#, c-format
+msgid "%ld lines filtered"
+msgstr "ÒÑ´¦Àí %ld ÐÐ"
+
+#: ex_cmds.c:918
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *Filter* Autocommand ²»¿ÉÒÔ¸ü¸Ä»º³åÇøµÄÄÚÈÝ"
+
+#: ex_cmds.c:1003
+msgid "[No write since last change]\n"
+msgstr "[¸üкóÉÐδ±£´æ]\n"
+
+#: ex_cmds.c:1248
+#, c-format
+msgid "viminfo: %s in line: "
+msgstr "viminfo: %s ÔÚÐÐÖÐ: "
+
+#: ex_cmds.c:1253
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: ¹ý¶à´íÎó, ºöÂÔÎļþÆäÓಿ·Ö"
+
+#: ex_cmds.c:1282
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "¶ÁÈ¡ viminfo Îļþ \"%s\"%s%s%s"
+
+#: ex_cmds.c:1283
+msgid " info"
+msgstr " ÐÅÏ¢"
+
+#: ex_cmds.c:1284
+msgid " marks"
+msgstr " 񈬀"
+
+#: ex_cmds.c:1285
+msgid " FAILED"
+msgstr " ʧ°Ü"
+
+#: ex_cmds.c:1376
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Viminfo Îļþ²»ÄÜдÈë: %s"
+
+#: ex_cmds.c:1501
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: ²»ÄÜдÈë viminfo Îļþ %s !"
+
+#: ex_cmds.c:1509
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "дÈë viminfo Îļþ \"%s\" ÖÐ"
+
+#. Write the info:
+#: ex_cmds.c:1610
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# viminfo ÎļþÊÇÓÉ vim %s Ëù²úÉú.\n"
+
+#: ex_cmds.c:1612
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Èç¹ûÏëÒª×ÔÐÐÐÞ¸ÄÇëÌرðСÐÄ£¡\n"
+"\n"
+
+#: ex_cmds.c:1614
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# 'encoding' ÔÚ´ËÎļþ½¨Á¢Ê±µÄÖµ\n"
+
+#: ex_cmds.c:1713
+msgid "Illegal starting char"
+msgstr "ÎÞЧµÄÆô¶¯×Ö·û"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2096
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: ÄúÔÚÁíÒ»¸ö»º³åÇøÒ²¼ÓÔØÁËÕâ¸öÎļþ"
+
+#: ex_cmds.c:2130
+msgid "Write partial file?"
+msgstr "ҪдÈ벿·ÖÎļþÂð£¿"
+
+#: ex_cmds.c:2137
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: ÇëʹÓà ! À´Ð´È벿·Ö»º³åÇø"
+
+#: ex_cmds.c:2223
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Òª¸²¸ÇÒÑ´æÔÚµÄÎļþ \"%.*s\"£¿"
+
+#: ex_cmds.c:2294
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: »º³åÇø %ld ûÓÐÎļþÃû"
+
+#: ex_cmds.c:2332
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: ÎļþδдÈ룬ÒòΪ 'write' Ñ¡Ïî¹Ø±Õ"
+
+#: ex_cmds.c:2352
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"\"%.*s\" ÒÑÉ趨 'readonly' Ñ¡Ïî.\n"
+"È·¶¨Òª¸²¸ÇÂð£¿"
+
+#: ex_cmds.c:2517
+msgid "Edit File"
+msgstr "±à¼­Îļþ"
+
+#: ex_cmds.c:3024
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Autocommands ÒâÍâµØɾ³ýлº³åÇø %s"
+
+#: ex_cmds.c:3156
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: :z ²»½ÓÊÜ·ÇÊý×ֵIJÎÊý"
+
+#: ex_cmds.c:3241
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: rvim ÖнûֹʹÓà shell ÃüÁî"
+
+#: ex_cmds.c:3348
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: ÕýÔò±í´ïʽ²»ÄÜÓÃ×Öĸ·Ö¸ô (?)"
+
+#: ex_cmds.c:3686
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "Ì滻Ϊ %s (y/n/a/q/^E/^Y)?"
+
+#: ex_cmds.c:4050
+msgid "(Interrupted) "
+msgstr "(ÒÑÖжÏ) "
+
+#: ex_cmds.c:4054
+msgid "1 substitution"
+msgstr "Ìæ»»Ò»×é"
+
+#: ex_cmds.c:4056
+#, c-format
+msgid "%ld substitutions"
+msgstr "Ìæ»» %ld ×é"
+
+#: ex_cmds.c:4059
+msgid " on 1 line"
+msgstr " Ò»ÐÐÖÐ"
+
+#: ex_cmds.c:4061
+#, c-format
+msgid " on %ld lines"
+msgstr " %ld ÐÐÖÐ"
+
+#: ex_cmds.c:4112
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :global ²»ÄܵݹéÖ´ÐÐ"
+
+#: ex_cmds.c:4147
+msgid "E148: Regular expression missing from global"
+msgstr "E148: ûÓÐʹÓùýÕýÔò±í´ïʽ (?)"
+
+#: ex_cmds.c:4196
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "ÿһÐж¼ÕÒ²»µ½Ä£Ê½: %s"
+
+#: ex_cmds.c:4277
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Ç°Ò»×éÌæ´ú×Ö·û´®:\n"
+"$"
+
+#: ex_cmds.c:4376
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: ±§Ç¸, ûÓÐ %s µÄ˵Ã÷"
+
+#: ex_cmds.c:4410
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "±§Ç¸, ÕÒ²»µ½°ïÖúÎļþ \"%s\""
+
+#: ex_cmds.c:4856
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s ²»ÊÇĿ¼"
+
+#: ex_cmds.c:4884
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: ²»ÄÜÒÔдÈëģʽ´ò¿ª \"%s\""
+
+#: ex_cmds.c:4898
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: ²»ÄܶÁÈ¡Îļþ: %s"
+
+#: ex_cmds.c:4977
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: ±êÇ©(tag) \"%s\" ÔÚÎļþ %s ÀïÖظ´³öÏÖ¶à´Î"
+
+#: ex_cmds.c:5078
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: 䶨ÒåµÄ sign command: %s"
+
+#: ex_cmds.c:5098
+msgid "E156: Missing sign name"
+msgstr "E156: ȱÉÙ sign Ãû³Æ"
+
+#: ex_cmds.c:5144
+msgid "E255: Too many signs defined"
+msgstr "E326: ÕÒµ½Ì«¶à signs"
+
+#: ex_cmds.c:5186
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: ²»ÕýÈ·µÄ sign ÎÄ×Ö: %s"
+
+#: ex_cmds.c:5210 ex_cmds.c:5396
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: ²»ÕýÈ·µÄ sign: %s"
+
+#: ex_cmds.c:5256
+msgid "E159: Missing sign number"
+msgstr "E159: ȱÉÙ sign number"
+
+#: ex_cmds.c:5336
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: »º³åÇøÃû³Æ´íÎó: %s"
+
+#: ex_cmds.c:5375
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Sign ID ´íÎó: %ld"
+
+#: ex_cmds.c:5546
+msgid "[Deleted]"
+msgstr "[ÒÑɾ³ý]"
+
+#: ex_docmd.c:491
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "½øÈë Ex ģʽ. ÊäÈë \"visua\" ÒԻص½Õý³£Ä£Ê½."
+
+#. must be at EOF
+#: ex_docmd.c:527
+msgid "At end-of-file"
+msgstr "Òѵ½Îļþ½áβ"
+
+#: ex_docmd.c:602
+msgid "E169: Command too recursive"
+msgstr "E169: ÃüÁîµÝ¹é²ãÊý¹ý¶à"
+
+#: ex_docmd.c:911
+msgid "E170: Missing :endwhile"
+msgstr "E170: ȱÉÙ :endwhile"
+
+#: ex_docmd.c:913
+msgid "E171: Missing :endif"
+msgstr "E171: ȱÉÙ :endif"
+
+#: ex_docmd.c:923
+msgid "End of sourced file"
+msgstr "ÃüÁîÎļþ½áÊø"
+
+#: ex_docmd.c:924
+msgid "End of function"
+msgstr "º¯Êý½áβ"
+
+#: ex_docmd.c:1344
+msgid "Ambiguous use of user-defined command"
+msgstr "Óû§¶¨ÒåµÄÃüÁî»á»ìÏý"
+
+#: ex_docmd.c:1358
+msgid "Not an editor command"
+msgstr "²»ÊDZ༭Æ÷µÄÃüÁî"
+
+#: ex_docmd.c:1441
+msgid "Don't panic!"
+msgstr "²»Òª¾ª»Å!"
+
+#: ex_docmd.c:1460
+msgid "Backwards range given"
+msgstr "Ö¸¶¨ÁËÏòÇ°²Î¿¼µÄ·¶Î§"
+
+#: ex_docmd.c:1469
+msgid "Backwards range given, OK to swap"
+msgstr "Ö¸¶¨ÁËÏòÇ°²Î¿¼µÄ·¶Î§£¬OK to swap"
+
+#: ex_docmd.c:1580
+msgid "Use w or w>>"
+msgstr "ÇëʹÓà w »ò w>>"
+
+#: ex_docmd.c:3086
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: ±§Ç¸, ±¾ÃüÁîÔÚ´Ë°æ±¾ÖÐδʵÏÖ"
+
+#: ex_docmd.c:3256
+msgid "E172: Only one file name allowed"
+msgstr "E172: Ö»ÄÜÓÐÒ»¸öÎļþÃû"
+
+#: ex_docmd.c:3810
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "»¹ÓÐ %d ¸öÎļþδ±à¼­. È·¶¨ÒªÍ˳ö£¿"
+
+#: ex_docmd.c:3817
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: »¹ÓÐ %ld ¸öÎļþδ±à¼­"
+
+#: ex_docmd.c:3911
+msgid "E174: Command already exists: use ! to redefine"
+msgstr "E174: ÃüÁîÒѾ­´æÔÚ, ÇëʹÓà ! Ç¿ÖÆÖØж¨Òå"
+
+#: ex_docmd.c:4016
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Ãû³Æ ²ÎÊý ·¶Î§ ÍêÕû ¶¨Òå "
+
+#: ex_docmd.c:4105
+msgid "No user-defined commands found"
+msgstr "ÕÒ²»µ½Óû§×Ô¶¨ÒåµÄÃüÁî"
+
+#: ex_docmd.c:4136
+msgid "E175: No attribute specified"
+msgstr "E175: ûÓÐÖ¸¶¨µÄÊôÐÔ"
+
+#: ex_docmd.c:4188
+msgid "E176: Invalid number of arguments"
+msgstr "E176: ²»ÕýÈ·µÄ²ÎÊý¸öÊý"
+
+#: ex_docmd.c:4203
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: ²»ÄÜÖ¸¶¨Á½´Î"
+
+#: ex_docmd.c:4213
+msgid "E178: Invalid default value for count"
+msgstr "E178: ¼ÆÊýµÄȱʡֵ²»ÕýÈ·"
+
+#: ex_docmd.c:4241
+msgid "E179: argument required for complete"
+msgstr "E179: Ö¸ÁîÐèÒª²ÎÊý²ÅÄÜÍê³É"
+
+#: ex_docmd.c:4260
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: ²»ÍêÕûµÄÖµ: '%s'"
+
+#: ex_docmd.c:4268
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: ²»ÕýÈ·µÄÊôÐÔ: %s"
+
+#: ex_docmd.c:4309
+msgid "E182: Invalid command name"
+msgstr "E182: ÃüÁîÃû³Æ²»ÕýÈ·"
+
+#: ex_docmd.c:4324
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: Óû§×Ô¶¨ÒåÃüÁî±ØÐëÒÔ´óд×Öĸ¿ªÊ¼"
+
+#: ex_docmd.c:4393
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: ûÓÐÓû§×Ô¶¨ÒåµÄÃüÁ %s"
+
+#: ex_docmd.c:4844
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: ÕÒ²»µ½ÑÕÉ«Ñùʽ %s"
+
+#: ex_docmd.c:4852
+msgid "Greetings, Vim user!"
+msgstr "ÄãºÃ, Vim Óû§£¡"
+
+#: ex_docmd.c:5549
+msgid "Edit File in new window"
+msgstr "ÔÚд°¿Ú±à¼­Îļþ"
+
+#: ex_docmd.c:5815
+msgid "No swap file"
+msgstr "ÎÞ½»»»Îļþ"
+
+#: ex_docmd.c:5919
+msgid "Append File"
+msgstr "¸½¼ÓÎļþ"
+
+#: ex_docmd.c:5978
+msgid "E186: No previous directory"
+msgstr "E186: Ç°Ò»¸öĿ¼²»´æÔÚ"
+
+#: ex_docmd.c:6055
+msgid "E187: Unknown"
+msgstr "E187: ²»ÄÜʶ±ðµÄ±ê¼Ç"
+
+#: ex_docmd.c:6173
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "´°¿ÚλÖÃ: X %d, Y %d"
+
+#: ex_docmd.c:6178
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: ÔÚÄúµÄƽ̨Éϲ»ÄÜ»ñµÃ´°¿ÚλÖÃ"
+
+#: ex_docmd.c:6444
+msgid "Save Redirection"
+msgstr "±£´æÖض¨Ïò"
+
+#: ex_docmd.c:6593
+msgid "Save View"
+msgstr "±£´æÊÓͼ"
+
+#: ex_docmd.c:6594
+msgid "Save Session"
+msgstr "±£´æ»á»°"
+
+#: ex_docmd.c:6596
+msgid "Save Setup"
+msgstr "±£´æÉ趨"
+
+#: ex_docmd.c:6745
+#, c-format
+msgid "E189: \"%s\" exists (use ! to override)"
+msgstr "E189: \"%s\" ÒÑ´æÔÚ (ÇëÓÃ ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: ex_docmd.c:6750
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: ²»ÄÜÒÔдÈëģʽ´ò¿ª \"%s\""
+
+#. set mark
+#: ex_docmd.c:6774
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: ²ÎÊý±ØÐëÊÇÓ¢ÎÄ×Öĸ»òÏòÇ°/ºóµÄÒýºÅ"
+
+#: ex_docmd.c:6803
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: :normal µÝ¹é²ãÊý¹ýÉî"
+
+#: ex_docmd.c:7171
+msgid ":if nesting too deep"
+msgstr ":if ²ãÊý¹ýÉî"
+
+#: ex_docmd.c:7206
+msgid ":endif without :if"
+msgstr ":endif ȱÉÙ¶ÔÓ¦µÄ :if"
+
+#: ex_docmd.c:7226
+msgid ":else without :if"
+msgstr ":else ȱÉÙ¶ÔÓ¦µÄ :if"
+
+#: ex_docmd.c:7228
+msgid ":elseif without :if"
+msgstr ":elseif ȱÉÙ¶ÔÓ¦µÄ :if"
+
+#: ex_docmd.c:7280
+msgid ":while nesting too deep"
+msgstr ":while ²ãÊý¹ýÉî"
+
+#: ex_docmd.c:7326
+msgid ":continue without :while"
+msgstr ":continue ȱÉÙ¶ÔÓ¦µÄ :while"
+
+#: ex_docmd.c:7353
+msgid ":break without :while"
+msgstr ":break ȱÉÙ¶ÔÓ¦µÄ :while"
+
+#: ex_docmd.c:7376 ex_docmd.c:7381
+msgid ":endwhile without :while"
+msgstr ":endwhile ȱÉÙ¶ÔÓ¦µÄ :while"
+
+#: ex_docmd.c:7402
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction ±ØÐëÔÚº¯ÊýÄÚ²¿Ê¹ÓÃ"
+
+#: ex_docmd.c:7582
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: ûÓÐ '#' ¿ÉÌæ´úµÄÎļþÃû"
+
+#: ex_docmd.c:7613
+msgid "no autocommand file name to substitute for \"<afile>\""
+msgstr "ûÓÐ Autocommand ÎļþÃûÒÔÌæ»» \"<afile>\""
+
+#: ex_docmd.c:7621
+msgid "no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "ûÓÐ Autocommand »º³åÇøÃû³ÆÒÔÌæ»» \"<abuf>\""
+
+#: ex_docmd.c:7632
+msgid "no autocommand match name to substitute for \"<amatch>\""
+msgstr "ûÓÐ Autocommand Match name ÒÔÌæ»» \"<amatch>\""
+
+#: ex_docmd.c:7642
+msgid "no :source file name to substitute for \"<sfile>\""
+msgstr "ûÓÐ :source ÎļþÃûÒÔÌæ»» \"<sfile>\""
+
+#: ex_docmd.c:7683
+#, no-c-format
+msgid "Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "'%' »ò '#' Ö¸Ïò¿ÕÎļþÃû£¬Ö»ÄÜÓÃì¶ \":p:h\""
+
+#: ex_docmd.c:7685
+msgid "Evaluates to an empty string"
+msgstr "ÊäÈëΪ¿Õ×Ö·û´®"
+
+#: ex_docmd.c:8594
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: ²»ÄܶÁÈ¡ viminfo"
+
+#: ex_docmd.c:8767
+msgid "E196: No digraphs in this version"
+msgstr "E196: ±¾°æ±¾ÎÞ¸´ºÏ×Ö·û(digraph)"
+
+#: ex_getln.c:2785
+msgid "tagname"
+msgstr "±êÇ©Ãû³Æ"
+
+#: ex_getln.c:2788
+msgid " kind file\n"
+msgstr "ÀàÎļþ\n"
+
+#: ex_getln.c:3997
+msgid "'history' option is zero"
+msgstr "Ñ¡Ïî 'history' ÊÇÁã"
+
+#: ex_getln.c:4237
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s ÀúÊ·¼Ç¼ (´Óе½¾É):\n"
+
+#: ex_getln.c:4238
+msgid "Command Line"
+msgstr "ÃüÁîÐÐ"
+
+#: ex_getln.c:4239
+msgid "Search String"
+msgstr "²éÕÒ×Ö·û´®"
+
+#: ex_getln.c:4240
+msgid "Expression"
+msgstr "±í´ïʽ"
+
+#: ex_getln.c:4241
+msgid "Input Line"
+msgstr "ÊäÈëÐÐ"
+
+#: ex_getln.c:4271
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar ³¬¹ýÃüÁ¶È"
+
+#: ex_getln.c:4435
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: ÒÑɾ³ý»î¶¯´°¿Ú»ò»º´æ"
+
+#: fileio.c:347
+msgid "Illegal file name"
+msgstr "²»ÕýÈ·µÄÎļþÃû"
+
+#: fileio.c:371 fileio.c:495 fileio.c:2491 fileio.c:2529
+msgid "is a directory"
+msgstr "ÊÇĿ¼"
+
+#: fileio.c:373
+msgid "is not a file"
+msgstr "²»ÊÇÎļþ"
+
+#: fileio.c:515 fileio.c:3581
+msgid "[New File]"
+msgstr "[δÃüÃû]"
+
+#: fileio.c:532
+msgid "[Permission Denied]"
+msgstr "[ȨÏÞ²»×ã]"
+
+#: fileio.c:624
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre Autocommand ʹ³ÌÐò²»ÄܶÁÈ¡´ËÎļþ"
+
+#: fileio.c:626
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *Filter* Autocommand ²»¿ÉÒÔ¸ü¸Ä»º³åÇøµÄÄÚÈÝ"
+
+#: fileio.c:646
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: ´Ó±ê×¼ÊäÈë¶ÁÈ¡...\n"
+
+#: fileio.c:652
+msgid "Reading from stdin..."
+msgstr "´Ó±ê×¼ÊäÈë¶Á..."
+
+#. Re-opening the original file failed!
+#: fileio.c:876
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: ת»»´íÎó"
+
+#: fileio.c:1732
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:1739
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:1746
+msgid "[socket]"
+msgstr "[socket]"
+
+#: fileio.c:1754
+msgid "[RO]"
+msgstr "[Ö»¶Á]"
+
+#: fileio.c:1764
+msgid "[CR missing]"
+msgstr "[ȱÉÙCR]'"
+
+#: fileio.c:1769
+msgid "[NL found]"
+msgstr "[ÕÒµ½NL]"
+
+#: fileio.c:1774
+msgid "[long lines split]"
+msgstr "[·Ö¸î¹ý³¤ÐÐ]"
+
+#: fileio.c:1780 fileio.c:3565
+msgid "[NOT converted]"
+msgstr "[δת»»]"
+
+#: fileio.c:1785 fileio.c:3570
+msgid "[converted]"
+msgstr "[ÒÑת»»]"
+
+#: fileio.c:1792 fileio.c:3595
+msgid "[crypted]"
+msgstr "[ÒѼÓÃÜ]"
+
+#: fileio.c:1799
+msgid "[CONVERSION ERROR]"
+msgstr "ת»»´íÎó"
+
+#: fileio.c:1806
+msgid "[READ ERRORS]"
+msgstr "[¶Á´íÎó]"
+
+#: fileio.c:2013
+msgid "Can't find temp file for conversion"
+msgstr "ÕÒ²»µ½×ª»»ÓõÄÁÙʱÎļþ"
+
+#: fileio.c:2020
+msgid "Conversion with 'charconvert' failed"
+msgstr "×Ö·û¼¯×ª»»´íÎó"
+
+#: fileio.c:2023
+msgid "can't read output of 'charconvert'"
+msgstr "²»ÄܶÁÈ¡ 'charconvert' µÄÊä³ö"
+
+#: fileio.c:2407
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Autocommand ɾ³ý»òÊÍ·ÅÁËҪдÈëµÄ»º³åÇø"
+
+#: fileio.c:2430
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Autocommand ÒâÍâµØ¸Ä±äÁËÐкÅ"
+
+#: fileio.c:2496 fileio.c:2513
+msgid "is not a file or writable device"
+msgstr "²»ÊÇÎļþ»ò¿ÉдµÄÉ豸"
+
+#: fileio.c:2555
+msgid "is read-only (use ! to override)"
+msgstr "ÊÇÖ»¶ÁÎļþ (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:2851
+msgid "Can't write to backup file (use ! to override)"
+msgstr "²»ÄÜд±¸·ÝÎļþ (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:2863
+msgid "Close error for backup file (use ! to override)"
+msgstr "¹Ø±Õ±¸·ÝÎļþ³ö´í (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:2865
+msgid "Can't read file for backup (use ! to override)"
+msgstr "²»ÄܶÁÈ¡ÎļþÒÔ¹©±¸·Ý (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:2881
+msgid "Cannot create backup file (use ! to override)"
+msgstr "²»ÄÜ´´½¨±¸·ÝÎļþ (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:2970
+msgid "Can't make backup file (use ! to override)"
+msgstr "²»ÄÜ×÷±¸·ÝÎļþ (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:3032
+msgid "The resource fork will be lost (use ! to override)"
+msgstr "Resource fork »áÏûʧ (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:3121
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: ÕÒ²»µ½Ð´ÈëÓõĽ»»»Îļþ"
+
+#: fileio.c:3139
+msgid "E213: Cannot convert (use ! to write without conversion)"
+msgstr "E213: ²»ÄÜת»» (ÇëʹÓà ! Ç¿ÖƲ»×ª»»Ð´Èë)"
+
+#: fileio.c:3176
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: ²»ÄÜÒÔдÈëģʽ´ò¿ªÁ´½ÓÎļþ"
+
+#: fileio.c:3180
+msgid "E212: Can't open file for writing"
+msgstr "E212: ²»ÄÜÒÔдÈëģʽ´ò¿ª"
+
+#: fileio.c:3423
+msgid "Close failed"
+msgstr "¹Ø±Õʧ°Ü"
+
+#: fileio.c:3481
+msgid "write error, conversion failed"
+msgstr "²»ÄÜдÈë -- ת»»Ê§°Ü"
+
+#: fileio.c:3487
+msgid "write error (file system full?)"
+msgstr "дÈë´íÎó (ÎļþϵͳÒÑÂú£¿)"
+
+#: fileio.c:3560
+msgid " CONVERSION ERROR"
+msgstr "ת»»´íÎó"
+
+#: fileio.c:3576
+msgid "[Device]"
+msgstr "[É豸]"
+
+#: fileio.c:3581
+msgid "[New]"
+msgstr "[ÐÂ]"
+
+#: fileio.c:3603
+msgid " [a]"
+msgstr "[a]"
+
+#: fileio.c:3603
+msgid " appended"
+msgstr " ÒѸ½¼Ó"
+
+#: fileio.c:3605
+msgid " [w]"
+msgstr "[w]"
+
+#: fileio.c:3605
+msgid " written"
+msgstr " ÒÑдÈë"
+
+#: fileio.c:3655
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: Patch ģʽ: ²»ÄÜ´¢´æԭʼÎļþ"
+
+#: fileio.c:3677
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: Patch ģʽ: ²»Äܸıä¿ÕµÄԭʼÎļþ"
+
+#: fileio.c:3692
+msgid "E207: Can't delete backup file"
+msgstr "E207: ²»ÄÜɾ³ý±¸·ÝÎļþ"
+
+#: fileio.c:3744
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"¾¯¸æ: ԭʼÎļþ¶ªÊ§»òËð»µ\n"
+
+#: fileio.c:3746
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "ÔÚÎļþÕýȷдÈëÇ°ÇëÎðÍ˳ö±à¼­Æ÷!"
+
+#: fileio.c:3826
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:3826
+msgid "[dos format]"
+msgstr "[dos ¸ñʽ]"
+
+#: fileio.c:3833
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:3833
+msgid "[mac format]"
+msgstr "[mac ¸ñʽ]"
+
+#: fileio.c:3840
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:3840
+msgid "[unix format]"
+msgstr "[unix ¸ñʽ]"
+
+#: fileio.c:3867
+msgid "1 line, "
+msgstr "1 ÐÐ, "
+
+#: fileio.c:3869
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld ÐÐ, "
+
+#: fileio.c:3872
+msgid "1 character"
+msgstr "Ò»¸ö×Ö·û"
+
+#: fileio.c:3874
+#, c-format
+msgid "%ld characters"
+msgstr "%ld¸ö×Ö·û"
+
+#: fileio.c:3884
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:3884
+msgid "[Incomplete last line]"
+msgstr "[×îºóÒ»Ðв»ÍêÕû]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:3903
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "¾¯¸æ: ±¾Îļþ×ÔÉϴζÁÈëºóÒѱ䶯!!!"
+
+#: fileio.c:3905
+msgid "Do you really want to write to it"
+msgstr "È·¶¨ÒªÐ´ÈëÂð"
+
+#: fileio.c:4861
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: дÈëÎļþ \"%s\" ´íÎó"
+
+#: fileio.c:4868
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: ¹Ø±ÕÎļþ \"%s\" ´íÎó"
+
+#: fileio.c:4871
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: ¶ÁÈ¡Îļþ \"%s\" ´íÎó"
+
+#: fileio.c:5035
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: FileChangedShell autocommand ɾ³ý»º³åÇø"
+
+#: fileio.c:5043
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: ¾¯¸æ: Îļþ \"%s\" ÒѾ­²»´æÔÚ"
+
+#: fileio.c:5056
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr "W12: ¾¯¸æ: Îļþ \"%s\" ×ÔÉϴζÁÈëºóÒѱ䶯, ¶øÇұ༭ÖеĻº³åÇøÒ²¸ü¶¯ÁË"
+
+#: fileio.c:5059
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: ¾¯¸æ: Îļþ \"%s\" ×ÔÉϴζÁÈëºóÒѸıä"
+
+#: fileio.c:5061
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: ¾¯¸æ: Îļþ \"%s\" ×ÔÉϴζÁÈëºóÒѸıä"
+
+#: fileio.c:5071
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: ¾¯¸æ: Îļþ \"%s\" ÔÚ¿ªÊ¼±à¼­ºóÓÖ±»´´½¨ÁË"
+
+#: fileio.c:5088
+msgid "Warning"
+msgstr "¾¯¸æ"
+
+#: fileio.c:5089
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"È·¶¨(&O)\n"
+"¼ÓÔØÎļþ(&L)"
+
+#: fileio.c:5165
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: ²»ÄÜÖØмÓÔØ \"%s\""
+
+#: fileio.c:5670
+msgid "--Deleted--"
+msgstr "--ÒÑɾ³ý--"
+
+#. the group doesn't exist
+#: fileio.c:5830
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: ×é²»´æÔÚ: \"%s\""
+
+#: fileio.c:5955
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: * ºóÃæÓв»ÕýÈ·µÄ×Ö·û: %s"
+
+#: fileio.c:5966
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: ÎÞ´Ëʼþ: %s"
+
+#. Highlight title
+#: fileio.c:6115
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Auto-Commands ---"
+
+#: fileio.c:6386
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: ²»ÄܶÔËùÓÐʼþÖ´ÐÐ autocommand"
+
+#: fileio.c:6409
+msgid "No matching autocommands"
+msgstr "ÕÒ²»µ½¶ÔÓ¦µÄ autocommand"
+
+#: fileio.c:6681
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: autocommand ²ãÊý¹ýÉî"
+
+#: fileio.c:6968
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Auto commands: \"%s\""
+
+#: fileio.c:6976
+#, c-format
+msgid "Executing %s"
+msgstr "Ö´ÐÐ %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7044
+#, c-format
+msgid "autocommand %s"
+msgstr "autocommand %s"
+
+#: fileio.c:7566
+msgid "E219: Missing {."
+msgstr "E219: ȱÉÙ {."
+
+#: fileio.c:7568
+msgid "E220: Missing }."
+msgstr "E220: ȱÉÙ }."
+
+#: fold.c:66
+msgid "No fold found"
+msgstr "ÕÒ²»µ½ÈκΠfold"
+
+#: fold.c:554
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: ²»ÄÜÔÚÄ¿Ç°µÄ 'foldmethod' Ï´´½¨ fold"
+
+#: fold.c:556
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: ²»ÄÜÔÚÄ¿Ç°µÄ 'foldmethod' ÏÂɾ³ý fold"
+
+#: fold.c:1700
+msgid "E221: 'commentstring' is empty"
+msgstr "E221: Ñ¡Ïî 'commentstring' δÉ趨"
+
+#: getchar.c:268
+msgid "E222: Add to read buffer"
+msgstr "E222: ¼ÓÈë¶Á»º³åÖÐ"
+
+#: getchar.c:2114
+msgid "E223: recursive mapping"
+msgstr "E223: µÝ¹é mapping"
+
+#: getchar.c:2966
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: %s ÒѾ­ÓÐÈ«¾Ö abbreviation ÁË"
+
+#: getchar.c:2969
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: %s ÒѾ­ÓÐÈ«¾Ö mapping ÁË"
+
+#: getchar.c:3096
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: %s ÒѾ­ÓÐ abbreviation ÁË"
+
+#: getchar.c:3099
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: %s µÄ mapping ÒѾ­´æÔÚ"
+
+#: getchar.c:3163
+msgid "No abbreviation found"
+msgstr "ÕÒ²»µ½Ëõд"
+
+#: getchar.c:3165
+msgid "No mapping found"
+msgstr "ûÓÐÕâ¸ö¶ÔÓ¦"
+
+#: getchar.c:3990
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: ²»ÕýÈ·µÄģʽ"
+
+#: gui_at_fs.c:290
+msgid "<cannot open> "
+msgstr "<²»ÄÜ´ò¿ª>"
+
+#: gui_at_fs.c:1115
+#, c-format
+msgid "vim_SelFile: can't get font %s"
+msgstr "vim_SelFile: ²»ÄÜʹÓà %s ×ÖÌå"
+
+#: gui_at_fs.c:2535
+msgid "vim_SelFile: can't return to current directory"
+msgstr "vim_SelFile: ²»Äܻص½Ä¿Ç°Ä¿Â¼"
+
+#: gui_at_fs.c:2554
+msgid "Pathname:"
+msgstr "·¾¶:"
+
+#: gui_at_fs.c:2560
+msgid "vim_SelFile: can't get current directory"
+msgstr "vim_SelFile: ²»ÄÜÈ¡µÃĿǰĿ¼"
+
+#: gui_at_fs.c:2568 gui_motif.c:1607
+msgid "OK"
+msgstr "È·¶¨"
+
+#. 'Cancel' button
+#: gui_at_fs.c:2568 gui_gtk.c:1683 gui_motif.c:1602 gui_motif.c:2823
+msgid "Cancel"
+msgstr "È¡Ïû"
+
+#: gui_athena.c:1928 gui_motif.c:1855
+msgid "Vim dialog"
+msgstr "Vim ¶Ô»°¿ò"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "¹ö¶¯Ìõ: ²»ÄÜÉ趨 thumb pixmap µÄλÖÃ"
+
+#: gui_beval.c:68
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: ²»ÄܶÔÐÅÏ¢Óë callback ´´½¨ BallonEval"
+
+#: gui.c:181
+msgid "E229: Cannot start the GUI"
+msgstr "E229: ²»ÄÜÆô¶¯Í¼ÐͽçÃæ"
+
+#: gui.c:306
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: ²»ÄܶÁÈ¡Îļþ \"%s\""
+
+#: gui.c:431
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: ²»ÕýÈ·µÄ 'guifontwide'"
+
+#: gui.c:3919
+msgid "Error"
+msgstr "´íÎó"
+
+#: gui.c:3920
+msgid "&Ok"
+msgstr "È·¶¨(&O)"
+
+#: gui_gtk.c:1144
+msgid "Vim dialog..."
+msgstr "Vim ¶Ô»°¿ò..."
+
+#: gui_gtk.c:1519 gui_motif.c:2742
+msgid "VIM - Search and Replace..."
+msgstr "VIM - ²éÕÒÓëÌæ»»..."
+
+#: gui_gtk.c:1524 gui_motif.c:2744
+msgid "VIM - Search..."
+msgstr "VIM - ²éÕÒ..."
+
+#: gui_gtk.c:1547 gui_motif.c:2862
+msgid "Find what:"
+msgstr "²éÕÒ:"
+
+#: gui_gtk.c:1565 gui_motif.c:2894
+msgid "Replace with:"
+msgstr "Ì滻Ϊ:"
+
+#. exact match only button
+#: gui_gtk.c:1597 gui_motif.c:2996
+msgid "Match exact word only"
+msgstr "ֻƥÅäÍêÈ«ÏàͬµÄ×Ö"
+
+#: gui_gtk.c:1609 gui_motif.c:2964
+msgid "Direction"
+msgstr "·½Ïò"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:1621 gui_motif.c:2976
+msgid "Up"
+msgstr "ÏòÉÏ"
+
+#: gui_gtk.c:1625 gui_motif.c:2984
+msgid "Down"
+msgstr "ÏòÏÂ"
+
+#. 'Find Next' button
+#: gui_gtk.c:1647 gui_motif.c:2766
+msgid "Find Next"
+msgstr "ÕÒÏÂÒ»¸ö"
+
+#. 'Replace' button
+#: gui_gtk.c:1664 gui_motif.c:2783
+msgid "Replace"
+msgstr "Ìæ»»"
+
+#. 'Replace All' button
+#: gui_gtk.c:1673 gui_motif.c:2796
+msgid "Replace All"
+msgstr "Ì滻ȫ²¿"
+
+#: gui_gtk_x11.c:1076 gui_x11.c:1194
+msgid "E233: cannot open display"
+msgstr "E233: <²»ÄÜ´ò¿ª X Server DISPLAY>"
+
+#: gui_gtk_x11.c:2433 gui_x11.c:1997
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: ²»ÕýÈ·µÄ×Ö·û¼¯ (Fontset): %s"
+
+#: gui_gtk_x11.c:2460
+msgid "Font Selection"
+msgstr "×ÖÌåÑ¡Ôñ"
+
+#: gui_gtk_x11.c:2702 gui_mac.c:2780 gui_w48.c:1197 gui_x11.c:1833
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "²»ÕýÈ·µÄ×ÖÌåÃû³Æ: %s"
+
+#: gui_gtk_x11.c:2713 gui_x11.c:1857
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: \"%s\" ²»Êǹ̶¨¿í¶È×ÖÌå"
+
+#: gui_gtk_x11.c:2843
+#, c-format
+msgid "E242: Color name not recognized: %s"
+msgstr "E242: %s Ϊ²»ÄÜʶ±ðµÄÑÕÉ«Ãû³Æ"
+
+#: gui_gtk_x11.c:3519 ui.c:1929
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "ʹÓà CUT_BUFFER0 À´Ìæ»»¿ÕÑ¡Ôñ"
+
+#: gui_motif.c:1601 gui_motif.c:1604
+msgid "Filter"
+msgstr "¹ýÂËÆ÷"
+
+#: gui_motif.c:1603
+msgid "Directories"
+msgstr "Ŀ¼"
+
+#: gui_motif.c:1605
+msgid "Help"
+msgstr "°ïÖú"
+
+#: gui_motif.c:1606
+msgid "Files"
+msgstr "Îļþ"
+
+#: gui_motif.c:1608
+msgid "Selection"
+msgstr "Ñ¡Ôñ"
+
+#: gui_motif.c:2809
+msgid "Undo"
+msgstr "³·Ïû"
+
+#: gui_riscos.c:951
+#, c-format
+msgid "E235: Can't load Zap font '%s'"
+msgstr "E235: ²»ÄÜ´ò¿ª Zap ×ÖÌå '%s'"
+
+#: gui_riscos.c:1047
+#, c-format
+msgid "E235: Can't use font %s"
+msgstr "E235: ²»ÄÜʹÓÃ×ÖÌå %s"
+
+#: gui_riscos.c:1167
+#, c-format
+msgid "E242: Missing color: %s"
+msgstr "E242: ÕÒ²»µ½ÑÕÉ«: %s"
+
+#: gui_riscos.c:3269
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"ÕýÔÚ·¢ËÍÖжÏ×Ó³ÌÐòµÄÐÅÏ¢.\n"
+
+#: gui_w32.c:823
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: ²»Ö§³Ö²ÎÊý \"-%s\"¡£ÇëÓà OLE °æ±¾¡£"
+
+#: gui_w48.c:2068
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "²éÕÒ×Ö·û´® (ʹÓà '\\\\' À´±íʾ '\\')"
+
+#: gui_w48.c:2093
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "²éÕÒ¼°Ìæ»»×Ö·û´® (ʹÓà '\\\\' À´±íʾ '\\')"
+
+#: gui_x11.c:1414
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr "Vim E458: ²»ÄÜÅäÖà color map ¶ÔÏó£¬ÓÐЩÑÕÉ«¿´ÆðÀ´»á¹Ö¹ÖµÄ"
+
+#: gui_x11.c:1987
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: Fontset %s ûÓÐÉ趨ÕýÈ·µÄ×ÖÌåÒÔ¹©ÏÔʾÕâЩ×Ö·û¼¯:"
+
+#: gui_x11.c:2030
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: ×ÖÌ弯(Fontset)Ãû³Æ: %s"
+
+#: gui_x11.c:2031
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "'%s' ²»Êǹ̶¨¿í¶È×ÖÌå"
+
+#: gui_x11.c:2050
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: ×ÖÌ弯(Fontset)Ãû³Æ: %s\n"
+
+#: gui_x11.c:2051
+#, c-format
+msgid "Font0: %s\n"
+msgstr "×ÖÌå0: %s\n"
+
+#: gui_x11.c:2052
+#, c-format
+msgid "Font1: %s\n"
+msgstr "×ÖÌå1: %s\n"
+
+#: gui_x11.c:2053
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "×ÖÌå%d¿í¶È²»ÊÇ×ÖÌå0µÄÁ½±¶\n"
+
+#: gui_x11.c:2054
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "×ÖÌå0µÄ¿í¶È£º%ld\n"
+
+#: gui_x11.c:2055
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"×ÖÌå1¿í¶È: %ld\n"
+"\n"
+
+#: gui_x11.c:2201
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: ²»ÄÜÅäÖÃÑÕÉ« %s"
+
+#: gui_x11.c:3250
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: ²»ÄܶÁÈ¡ sign data!"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: Hangul automata ´íÎó"
+
+#: if_cscope.c:26
+#, c-format
+msgid "Usage: cs[cope] %s"
+msgstr ""
+
+#: if_cscope.c:67
+msgid "Add a new database"
+msgstr "ÐÂÔöÊý¾Ý¿â"
+
+#: if_cscope.c:69
+msgid "Query for a pattern"
+msgstr "²éѯģʽ"
+
+#: if_cscope.c:71
+msgid "Show this message"
+msgstr "ÏÔʾ´ËÐÅÏ¢"
+
+#: if_cscope.c:73
+msgid "Kill a connection"
+msgstr "½áÊøÁ¬½Ó"
+
+#: if_cscope.c:75
+msgid "Reinit all connections"
+msgstr "ÖØÉèËùÓÐÁ¬½Ó"
+
+#: if_cscope.c:77
+msgid "Show connections"
+msgstr "ÏÔʾÁ¬½Ó"
+
+#: if_cscope.c:108
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Õâ¸ö cscope ÃüÁî²»Ö§³Ö·Ö¸îÆÁÄ»\n"
+
+#: if_cscope.c:143
+msgid "Usage: cstag <ident>"
+msgstr "Ó÷¨: cstag <ʶ±ð×Ö>"
+
+#: if_cscope.c:199
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: ÕÒ²»µ½ tag"
+
+#: if_cscope.c:407 if_cscope.c:451
+#, c-format
+msgid "stat(%s) error: %d"
+msgstr "stat(%s) ´íÎó: %d"
+
+#: if_cscope.c:460 if_cscope.c:467
+#, c-format
+msgid "Added cscope database %s"
+msgstr "ÐÂÔö cscope Êý¾Ý¿â %s"
+
+#: if_cscope.c:474
+#, c-format
+msgid "%s is not a directory or a valid cscope database"
+msgstr "%s ²»ÊÇĿ¼»ò cscope Êý¾Ý¿â"
+
+#: if_cscope.c:557
+#, c-format
+msgid "error reading cscope connection %d"
+msgstr "¶ÁÈ¡ cscope Á¬½Ó %d ʱ´íÎó"
+
+#: if_cscope.c:633
+msgid "unknown cscope search type"
+msgstr "δ֪µÄ cscope ²éÕÒÐÎ̬"
+
+#: if_cscope.c:680
+msgid "Could not create cscope pipes"
+msgstr "²»ÄÜ´´½¨Óë cscope Á¬½ÓµÄ¹ÜµÀ"
+
+#: if_cscope.c:745
+msgid "cs_create_connection exec failed"
+msgstr "cs_create_connection Ö´ÐÐʧ°Ü"
+
+#: if_cscope.c:755
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen ʧ°Ü (to_fp)"
+
+#: if_cscope.c:757
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen ʧ°Ü (fr_fp)"
+
+#: if_cscope.c:785
+msgid "no cscope connections"
+msgstr "ûÓÐ cscope Á¬½Ó"
+
+#: if_cscope.c:855
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: ÕÒ²»µ½·ûºÏ cscope µÄËÑÑ° %s / %s"
+
+#: if_cscope.c:899
+msgid "cscope commands:\n"
+msgstr "cscope ÃüÁî:\n"
+
+#: if_cscope.c:902
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)\n"
+msgstr "%-5s: %-30s (Ó÷¨: %s)\n"
+
+#: if_cscope.c:970
+msgid "duplicate cscope database not added"
+msgstr "Öظ´µÄ cscope Êý¾Ý¿âδ±»¼ÓÈë"
+
+#: if_cscope.c:981
+msgid "maximum number of cscope connections reached"
+msgstr "ÒÑ´ïµ½ cscope ×î´óÁ¬½ÓÊýÄ¿"
+
+#: if_cscope.c:1102
+msgid "E260: cscope connection not found"
+msgstr "E260: ÕÒ²»µ½ cscope Á¬½Ó"
+
+#: if_cscope.c:1105
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: ÕÒ²»µ½ cscope Á¬½Ó %s"
+
+#: if_cscope.c:1141
+msgid "cscope connection closed"
+msgstr "cscope Á¬½ÓÒѹرÕ"
+
+#: if_cscope.c:1149
+#, c-format
+msgid "cscope connection %s closed\n"
+msgstr "cscope Á¬½Ó %s ÒѹرÕ\n"
+
+#. should not reach here
+#: if_cscope.c:1290
+msgid "fatal error in cs_manage_matches"
+msgstr "cs_manage_matches ÑÏÖØ´íÎó"
+
+#: if_cscope.c:1341
+#, c-format
+msgid "E262: error reading cscope connection %d"
+msgstr "E262: ¶ÁÈ¡ cscope Á¬½Ó %d ´íÎó"
+
+#: if_cscope.c:1449
+msgid "couldn't malloc\n"
+msgstr "²»ÄÜʹÓà malloc\n"
+
+#: if_cscope.c:1454
+#, c-format
+msgid "Cscope tag: %s\n"
+msgstr "Cscope ±êÇ©(tag): %s\n"
+
+#: if_cscope.c:1458
+msgid " # line"
+msgstr " # ÐÐ "
+
+#: if_cscope.c:1460
+msgid "filename / context / line\n"
+msgstr "ÎļþÃû / ÉÏÏÂÎÄ / ÐкÅ\n"
+
+#: if_cscope.c:1718
+msgid "All cscope databases reset"
+msgstr "ÖØÉèËùÓÐ cscope Êý¾Ý¿â"
+
+#: if_cscope.c:1785
+msgid "no cscope connections\n"
+msgstr "ûÓÐ cscope Á¬½Ó\n"
+
+#: if_cscope.c:1789
+msgid " # pid database name prepend path\n"
+msgstr " # pid Êý¾Ý¿âÃû³Æ prepend path\n"
+
+#: if_cscope.c:1800
+#, c-format
+msgid "%2d %-5ld %-34s <none>\n"
+msgstr "%2d %-5ld %-34s <ÎÞ>\n"
+
+#: if_python.c:376
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr "E263: ±§Ç¸£¬Õâ¸öÃüÁî²»ÄÜʹÓã¬Python ³ÌÐò¿âûÓмÓÔØ¡£"
+
+#: if_python.c:576
+msgid "can't delete OutputObject attributes"
+msgstr "²»ÄÜɾ³ý OutputObject ÊôÐÔ"
+
+#: if_python.c:583
+msgid "softspace must be an integer"
+msgstr "softspace ±ØÐèÊÇÕûÊý"
+
+#: if_python.c:591
+msgid "invalid attribute"
+msgstr "²»ÕýÈ·µÄÊôÐÔ"
+
+#: if_python.c:630 if_python.c:644
+msgid "writelines() requires list of strings"
+msgstr "writelines() ÐèÒª string list µ±²ÎÊý"
+
+#: if_python.c:770
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: ²»Äܳõʼ»¯ I/O ¶ÔÏó"
+
+#: if_python.c:955 if_tcl.c:1391
+msgid "invalid expression"
+msgstr "²»ÕýÈ·µÄ±í´ïʽ"
+
+#: if_python.c:969 if_tcl.c:1396
+msgid "expressions disabled at compile time"
+msgstr "ÒòΪ±àÒëʱûÓмÓÈë±í´ïʽ(expression)µÄ³ÌÐò´úÂ룬ËùÒÔ²»ÄÜʹÓñí´ïʽ"
+
+#: if_python.c:982
+msgid "attempt to refer to deleted buffer"
+msgstr "ÊÔͼʹÓÃÒѱ»É¾³ýµÄ»º³åÇø"
+
+#: if_python.c:997 if_python.c:1038 if_python.c:1102 if_tcl.c:1203
+msgid "line number out of range"
+msgstr "Ðкų¬³ö·¶Î§"
+
+#: if_python.c:1235
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<buffer ¶ÔÏó (ÒÑɾ³ý): %8lX>"
+
+#: if_python.c:1326 if_tcl.c:825
+msgid "invalid mark name"
+msgstr "±ê¼ÇÃû³Æ²»ÕýÈ·"
+
+#: if_python.c:1601
+msgid "no such buffer"
+msgstr "ÎÞ´Ë»º³åÇø"
+
+#: if_python.c:1689
+msgid "attempt to refer to deleted window"
+msgstr "ÊÔͼʹÓÃÒѱ»É¾³ýµÄ´°¿Ú"
+
+#: if_python.c:1734
+msgid "readonly attribute"
+msgstr "Ö»¶ÁÊôÐÔ"
+
+#: if_python.c:1747
+msgid "cursor position outside buffer"
+msgstr "¹â±ê¶¨Î»ÔÚ»º³åÇøÖ®Íâ"
+
+#: if_python.c:1824
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<´°¿Ú¶ÔÏó(ÒÑɾ³ý): %.8lX>"
+
+#: if_python.c:1836
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<´°¿Ú¶ÔÏó(δ֪): %.8lX>"
+
+#: if_python.c:1838
+#, c-format
+msgid "<window %d>"
+msgstr "<´°¿Ú %d>"
+
+#: if_python.c:1914
+msgid "no such window"
+msgstr "ÎÞ´Ë´°¿Ú"
+
+#: if_python.c:2144 if_python.c:2175 if_python.c:2225 if_python.c:2285
+#: if_python.c:2402 if_python.c:2454 if_tcl.c:673 if_tcl.c:718 if_tcl.c:792
+#: if_tcl.c:862 if_tcl.c:1987
+msgid "cannot save undo information"
+msgstr "²»Äܱ£´æ¸´Ô­ÐÅÏ¢"
+
+#: if_python.c:2146 if_python.c:2232 if_python.c:2296
+msgid "cannot delete line"
+msgstr "²»ÄÜɾ³ý´ËÐÐ"
+
+#: if_python.c:2177 if_python.c:2312 if_tcl.c:679 if_tcl.c:2009
+msgid "cannot replace line"
+msgstr "²»ÄÜÌæ»»´ËÐÐ"
+
+#: if_python.c:2328 if_python.c:2404 if_python.c:2462
+msgid "cannot insert line"
+msgstr "²»ÄܲåÈë´ËÐÐ"
+
+#: if_python.c:2566
+msgid "string cannot contain newlines"
+msgstr "×Ö·û´®²»ÄÜ°üº¬ÐÂÐÐ"
+
+#: if_ruby.c:394
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr "E266: ´ËÃüÁî²»ÄÜʹÓã¬ÎÞ·¨¼ÓÔØ Ruby ³ÌÐò¿â(Library)"
+
+#: if_ruby.c:457
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: δ֪µÄ longjmp ״̬ %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Çл»ÊµÏÖ/¶¨Òå"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "ÏÔʾ base class of:"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "ÏÔʾ±»¸²¸ÇµÄ³ÉÔ±º¯Êý"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "»Ö¸´: ´ÓÎļþ"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "»Ö¸´: ´Ó¶ÔÏó"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "»Ö¸´: ´ÓËùÓÐÏîÄ¿"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "»Ö¸´"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "ÏÔʾԴ´úÂë: "
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "²éÕÒ symbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "ä¯ÀÀ class"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "ÏÔʾ²ã´Î¹ØϵµÄÀà"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "ÏÔʾ restricted ²ã´Î¹ØϵµÄ class"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref ²Î¿¼µ½"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref ±»Ë­²Î¿¼:"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref ÓÐ"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref ±»Ë­Ê¹ÓÃ:"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "ÏÔʾÎļþ: "
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "²úÉúÎļþ: "
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr "²»ÄÜÁ¬½Óµ½ SNiFF+¡£Çë¼ì²é»·¾³±äÁ¿ ($PATH Àï±ØÐè¿ÉÒÔÕÒµ½ sniffemacs)\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: ¶ÁÈ¡´íÎó. È¡ÏûÁ¬½Ó"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ Ä¿Ç°"
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "δ"
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "Á¬½ÓÖÐ"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: ²»ÕýÈ·µÄ SNiff+ µ÷ÓÃ: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Á¬½Óµ½ SNiFF+ ʧ°Ü"
+
+#: if_sniff.c:1010
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: δÁ¬½Óµ½ SNiFF+"
+
+#: if_sniff.c:1019
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: ²»ÊÇ SNiFF+ µÄ»º³åÇø"
+
+#: if_sniff.c:1084
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: дÈë´íÎó¡£½áÊøÁ¬½Ó"
+
+#: if_tcl.c:407
+msgid "invalid buffer number"
+msgstr "²»ÕýÈ·µÄ»º³åÇøºÅ"
+
+#: if_tcl.c:453 if_tcl.c:920 if_tcl.c:1099
+msgid "not implemented yet"
+msgstr "ÉÐδʵÏÖ"
+
+#: if_tcl.c:490
+msgid "unknown option"
+msgstr "²»ÕýÈ·µÄÑ¡Ïî"
+
+#. ???
+#: if_tcl.c:763
+msgid "cannot set line(s)"
+msgstr "²»ÄÜÉ趨ÐÐ"
+
+#: if_tcl.c:834
+msgid "mark not set"
+msgstr "ûÓÐÉ趨±ê¼Ç"
+
+#: if_tcl.c:840 if_tcl.c:1055
+#, c-format
+msgid "row %d column %d"
+msgstr "ÁÐ %d ÐÐ %d"
+
+#: if_tcl.c:870
+msgid "cannot insert/append line"
+msgstr "²»ÄܲåÈë»òÌí¼Ó´ËÐÐ"
+
+#: if_tcl.c:1257
+msgid "unknown flag: "
+msgstr "´íÎóµÄ±êÖ¾: "
+
+#: if_tcl.c:1327
+msgid "unknown vimOption"
+msgstr "²»ÕýÈ·µÄ VIM Ñ¡Ïî"
+
+#: if_tcl.c:1412
+msgid "keyboard interrupt"
+msgstr "¼üÅÌÖжÏ"
+
+#: if_tcl.c:1417
+msgid "vim error"
+msgstr "vim ´íÎó"
+
+#: if_tcl.c:1460
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "²»ÄÜ´´½¨»º³åÇø/´°¿ÚÃüÁî: ¶ÔÏ󽫱»É¾³ý"
+
+#: if_tcl.c:1534
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr "²»ÄÜ×¢²á callback ÃüÁî: »º³åÇø/´°¿ÚÒѾ­±»É¾³ýÁË"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1551
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr "E280: TCL ÑÏÖØ´íÎó: reflist ²»¿É¿¿!? Ç뱨¸æ¸ø to vim-dev@vim.org"
+
+#: if_tcl.c:1552
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr "²»ÄÜ×¢²á callback ÃüÁî: ÕÒ²»µ½»º³åÇø/´°¿Ú"
+
+#: if_tcl.c:1713
+msgid "Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr "´ËÃüÁî²»ÄÜʹÓÃ, ÒòΪÎÞ·¨¼ÓÔØ Tcl ³ÌÐò¿â(Library)"
+
+#: if_tcl.c:1875
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr "E281: TCL ´íÎó: Í˳ö·µ»ØÖµ²»ÊÇÕûÊý!? Ç뱨¸æ¸ø to vim-dev@vim.org"
+
+#: if_tcl.c:1995
+msgid "cannot get line"
+msgstr "²»ÄÜÈ¡µÃ´ËÐÐ"
+
+#: if_xcmdsrv.c:204
+msgid "Unable to register a command server name"
+msgstr "²»ÄÜ×¢²áÃüÁî·þÎñÆ÷Ãû³Æ"
+
+#: if_xcmdsrv.c:417
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: ûÓÐ×¢²áΪ \"%s\" µÄ·þÎñÆ÷"
+
+#: if_xcmdsrv.c:446
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: ²»ÄÜËͳöÃüÁĿµÄµØ³ÌÐò"
+
+#: if_xcmdsrv.c:709
+#, c-format
+msgid "Invalid server id used: %s"
+msgstr "²»ÕýÈ·µÄ·þÎñÆ÷ id : %s"
+
+#: if_xcmdsrv.c:1056
+msgid "E249: couldn't read VIM instance registry property"
+msgstr "E249: ²»ÄܶÁÈ¡ VIM µÄ ×¢²á±íÊôÐÔ"
+
+#: if_xcmdsrv.c:1067
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: VIM µÄ×¢²á±íÊôÐÔÓÐÎó¡£ÒÑɾ³ý¡£"
+
+#: main.c:53 option.c:3162 option.c:3269
+msgid "Unknown option"
+msgstr "²»ÕýÈ·µÄÑ¡Ïî"
+
+#: main.c:55
+msgid "Too many edit arguments"
+msgstr "Ì«¶à±à¼­²ÎÊý"
+
+#: main.c:57
+msgid "Argument missing after"
+msgstr "ȱÉÙ±ØÒªµÄ²ÎÊý:"
+
+#: main.c:59
+msgid "Garbage after option"
+msgstr "²»ÄܱæÈÏ´ËÑ¡ÏîºóµÄÃüÁî: "
+
+#: main.c:61
+msgid "Too many \"+command\" or \"-c command\" arguments"
+msgstr "Ì«¶à \"+command\" »ò \"-c command\" ²ÎÊý"
+
+#: main.c:63
+msgid "Invalid argument for"
+msgstr "²»ÕýÈ·µÄ²ÎÊý: "
+
+#: main.c:436
+msgid "This Vim was not compiled with the diff feature."
+msgstr "ÄúµÄ Vim ±àÒëʱûÓмÓÈë diff µÄÄÜÁ¦"
+
+#: main.c:858
+msgid "Attempt to open script file again: \""
+msgstr "ÊÔͼÔٴδò¿ª script Îļþ: \""
+
+#: main.c:862 main.c:869 main.c:913 memline.c:3673 memline.c:3677
+#: version.c:816 version.c:821 version.c:826 version.c:831 version.c:836
+#: version.c:841 version.c:847 version.c:851 version.c:855 version.c:860
+#: version.c:867 version.c:875 version.c:881
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:867
+msgid "Cannot open for reading: \""
+msgstr "²»ÄÜΪ¶Á¶ø´ò¿ª: \""
+
+#: main.c:911
+msgid "Cannot open for script output: \""
+msgstr "²»ÄÜΪ script Êä³ö¶ø´ò¿ª: \""
+
+#: main.c:1020
+#, c-format
+msgid "%d files to edit\n"
+msgstr "»¹ÓÐ %d ¸öÎļþµÈ´ý±à¼­\n"
+
+#: main.c:1094
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: ×¢Òâ: Êä³ö²»ÊÇÖÕ¶Ë(ÆÁÄ»)\n"
+
+#: main.c:1096
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: ×¢Òâ: ÊäÈë²»ÊÇÖÕ¶Ë(¼üÅÌ)\n"
+
+#. just in case..
+#: main.c:1171
+msgid "pre-vimrc command line"
+msgstr "pre-vimrc ÃüÁîÐÐ"
+
+#: main.c:1206
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: ²»ÄܶÁÈ¡Îļþ \"%s\""
+
+#: main.c:2157
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"²éѯ¸ü¶àÐÅÏ¢ÇëÖ´ÐÐ: \"vim -h\"\n"
+
+#: main.c:2190
+msgid "[file ..] edit specified file(s)"
+msgstr "[Îļþ ..] ±à¼­Ö¸¶¨µÄÎļþ"
+
+#: main.c:2191
+msgid "- read text from stdin"
+msgstr "- ´Ó±ê×¼ÊäÈë(stdin)¶ÁÈ¡Îı¾"
+
+#: main.c:2192
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tag ±à¼­Ê±Ê¹ÓÃÖ¸¶¨µÄ tag"
+
+#: main.c:2194
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [errorfile] ±à¼­Ê±¼ÓÔصÚÒ»¸ö´íÎó"
+
+#: main.c:2203
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+" Ó÷¨:"
+
+#: main.c:2206
+msgid " vim [arguments] "
+msgstr "vim [²ÎÊý] "
+
+#: main.c:2210
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" »ò:"
+
+#: main.c:2213
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"²ÎÊý:\n"
+
+#: main.c:2214
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tÖ»ÓÐÔÚÕâÖ®ºóµÄÎļþ"
+
+#: main.c:2216
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\t×¢²á gvim µ½ OLE"
+
+#: main.c:2217
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tÈ¡Ïû OLE ÖÐµÄ gvim ×¢²á"
+
+#: main.c:2220
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tʹÓÃͼÐνçÃæ (ͬ \"gvim\")"
+
+#: main.c:2221
+msgid "-f\t\t\tForeground: Don't fork when starting GUI"
+msgstr "-f\t\t\tÇ°¾°: Æô¶¯Í¼ÐνçÃæʱ²» fork"
+
+#: main.c:2223
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi ģʽ (ͬ \"vi\")"
+
+#: main.c:2224
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx ģʽ (ͬ \"ex\")"
+
+#: main.c:2225
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\t°²¾² (batch) ģʽ (Ö»ÄÜÓë \"ex\" Ò»ÆðʹÓÃ)"
+
+#: main.c:2227
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tDiff ģʽ (ͬ \"vimdiff\", ¿ÉѸËٱȽÏÁ½Îļþ²»Í¬´¦)"
+
+#: main.c:2229
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\t¼òÒ×ģʽ (ͬ \"evim\", modeless)"
+
+#: main.c:2230
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tÖ»¶Áģʽ (ͬ \"view\")"
+
+#: main.c:2231
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tÏÞÖÆģʽ (ͬ \"rvim\")"
+
+#: main.c:2232
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\t²»¿ÉÐÞ¸Ä (дÈëÎļþ)"
+
+#: main.c:2233
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tÎı¾²»¿ÉÐÞ¸Ä"
+
+#: main.c:2234
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\t¶þ½øÖÆģʽ"
+
+#: main.c:2236
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp ģʽ"
+
+#: main.c:2238
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\t'compatible' ´«Í³ Vi ¼æÈÝģʽ"
+
+#: main.c:2239
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\t'nocompatible' ²»ÍêÈ«Ó봫ͳ Vi ¼æÈÝ£¬¿ÉʹÓà Vim ¼ÓÇ¿ÄÜÁ¦"
+
+#: main.c:2240
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tVerbose µÈ¼¶"
+
+#: main.c:2241
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tµ÷ÊÔģʽ"
+
+#: main.c:2242
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\t²»Ê¹Óý»»»Îļþ, ֻʹÓÃÄÚ´æ"
+
+#: main.c:2243
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tÁгö½»»»ÎļþºóÍ˳ö"
+
+#: main.c:2244
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (¼ÓÎļþÃû) \t»Ö¸´ÉϴαÀÀ£µÄ×ÊÁÏ(Recover crashed session)"
+
+#: main.c:2245
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tÓë -r Ò»Ñù"
+
+#: main.c:2247
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\t²»Ê¹Óà newcli À´´ò¿ª´°¿Ú"
+
+#: main.c:2248
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <device>\t\tʹÓà <device> ×öÊäÈëÊä³öÉ豸"
+
+#: main.c:2251
+msgid "-H\t\t\tstart in Hebrew mode"
+msgstr "-H\t\t\tÆô¶¯Îª Ï£²®À³Ä£Ê½"
+
+#: main.c:2254
+msgid "-F\t\t\tstart in Farsi mode"
+msgstr "-F\t\t\tÆô¶¯Îª Farsi ģʽ"
+
+#: main.c:2256
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\tÉ趨ÖÕ¶ËΪ <terminal>"
+
+#: main.c:2257
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tʹÓà <vimrc> Ìæ»»ÈκΠ.vimrc"
+
+#: main.c:2259
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tʹÓà <gvimrc> Ìæ»»ÈκΠ.gvimrc"
+
+#: main.c:2261
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\t²»¼ÓÔØÈκΠplugin"
+
+#: main.c:2262
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\t´ò¿ª N ¸ö´°¿Ú (Ô¤ÉèÊÇÿ¸öÎļþÒ»¸ö)"
+
+#: main.c:2263
+msgid "-O[N]\t\tlike -o but split vertically"
+msgstr "-O[N]\t\tͬ -o µ«Ê¹Óô¹Ö±·Ö¸î"
+
+#: main.c:2264
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tÆô¶¯ºóÌøµ½Îļþ½áβ"
+
+#: main.c:2265
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\tÆô¶¯ºóÌøµ½µÚ <lnum> ÐÐ"
+
+#: main.c:2267
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <command>\t¼ÓÔØÈκΠvimrc Ç°Ö´ÐÐ <command>"
+
+#: main.c:2269
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <command>\t\t¼ÓÔصÚÒ»¸öÎļþºóÖ´ÐÐ <command>"
+
+#: main.c:2270
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <session>\t\t¼ÓÔصÚÒ»¸öÎļþºóÔØÈë Session Îļþ<session>"
+
+#: main.c:2271
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <scriptin>\t´Ó <scriptin> ¶ÁÈëÒ»°ãģʽÃüÁî"
+
+#: main.c:2272
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <scriptout>\t¶ÔÎļþ <scriptout> ¸½¼Ó(append)ËùÓÐÊäÈëµÄÃüÁî"
+
+#: main.c:2273
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <scriptout>\t¶ÔÎļþ <scriptout> дÈëËùÓÐÊäÈëµÄÃüÁî"
+
+#: main.c:2275
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\t±à¼­±àÂë¹ýµÄÎļþ"
+
+#: main.c:2279
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\t½« vim ÓëÖ¸¶¨µÄ X-server Á¬½Ó"
+
+#: main.c:2281
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\t²»ÒªÁ¬½Óµ½ X Server"
+
+#: main.c:2283
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tÔÚÁíÒ»¸ö GTK ×é¼þÄÚ´ò¿ª Vim"
+
+#: main.c:2287
+msgid "--remote <files>\tEdit <files> in a Vim server and exit"
+msgstr "--remote <files>\t±à¼­ Vim ·þÎñÆ÷ÉϵÄÎļþ²¢Í˳ö"
+
+#: main.c:2288
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <files> µÈЧÓÚ --remote, µ«»áµÈºòÎļþÍê³É±à¼­"
+
+#: main.c:2289
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <keys>\tËͳö <keys> µ½ Vim ·þÎñÆ÷²¢Í˳ö"
+
+#: main.c:2290
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <expr>\tÔÚ·þÎñÆ÷ÉÏÇó±í´ïʽµÄÖµ²¢´òÓ¡½á¹û"
+
+#: main.c:2291
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tÁгö¿ÉÓÃµÄ Vim ·þÎñÆ÷Ãû³Æ²¢Í˳ö"
+
+#: main.c:2292
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <name>\tËÍÖÁ/³ÉΪ Vim ·þÎñÆ÷ <name>"
+
+#: main.c:2295
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tʹÓà <viminfo> ¶ø·Ç .viminfo"
+
+#: main.c:2297
+msgid "-h\t\t\tprint Help (this message) and exit"
+msgstr "-h\t\t\t´òӡ˵Ã÷(Ò²¾ÍÊDZ¾ÐÅÏ¢)ºóÍ˳ö"
+
+#: main.c:2298
+msgid "--version\t\tprint version information and exit"
+msgstr "--version\t\t´òÓ¡°æ±¾ÐÅÏ¢ºóÍ˳ö"
+
+#: main.c:2302
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"gvim ¿Éʶ±ðµÄ²ÎÊý (Motif °æ):\n"
+
+#: main.c:2305
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"gvim ¿Éʶ±ðµÄ²ÎÊý (Athena °æ):\n"
+
+#: main.c:2308
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\tÔÚ´°¿Ú <display> Ö´ÐÐ vim"
+
+#: main.c:2309
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tÆô¶¯ºó×îС»¯(iconified)"
+
+#: main.c:2311
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <name>\t\t¶ÁÈ¡ Resource ʱ°Ñ vim µÄÃû³ÆÊÓΪ <name>"
+
+#: main.c:2312
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (ÉÐδʵÏÖ)\n"
+
+#: main.c:2314
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <color>\tÉ趨 <color> Ϊ±³¾°É« (Ò²¿ÉÓà -bg)"
+
+#: main.c:2315
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <color>\tÉ趨 <color> Ϊһ°ãÎÄ×ÖÑÕÉ« (Ò²¿ÉÓà -fg)"
+
+#: main.c:2316 main.c:2336
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <font>\tʹÓà <font> Ϊһ°ã×ÖÌå (Ò²¿ÉÓà -fn)"
+
+#: main.c:2317
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <font>\tʹÓà <font> Ϊ´ÖÌå×ÖÌå"
+
+#: main.c:2318
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <font>\tʹÓà <font> ΪбÌå×ÖÌå"
+
+#: main.c:2319 main.c:2337
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\tʹÓÃ<geom>Ϊ³õʼλÖà (Ò²¿ÉÓà -geom)"
+
+#: main.c:2320
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <width>\tʹÓÿí¶ÈΪ <width> µÄ±ß¿ò (Ò²¿ÉÓà -bw)"
+
+#: main.c:2321
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <width> É趨¹ö¶¯Ìõ¿í¶ÈΪ <width> (Ò²¿ÉÓà -sw)"
+
+#: main.c:2323
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <height>\tÉ趨²Ëµ¥Áеĸ߶ÈΪ <height> (Ò²¿ÉÓà -mh)"
+
+#: main.c:2325 main.c:2338
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tʹÓ÷´ÏÔ (Ò²¿ÉÓà -rv)"
+
+#: main.c:2326
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\t²»Ê¹Ó÷´ÏÔ (Ò²¿ÉÓà +rv)"
+
+#: main.c:2327
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\tÉ趨ָ¶¨µÄ×ÊÔ´"
+
+#: main.c:2330
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"gvim ¿Éʶ±ðµÄ²ÎÊý (RISC OS °æ):\n"
+
+#: main.c:2331
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <number>\t´°¿Ú³õʼ¿í¶È"
+
+#: main.c:2332
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <number>\t´°¿Ú³õʼ¸ß¶È"
+
+#: main.c:2335
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"gvim ¿Éʶ±ðµÄ²ÎÊý (GTK+ °æ):\n"
+
+#: main.c:2339
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\tÔÚ <display> Ö´ÐÐ vim (Ò²¿ÉÓà --display)"
+
+#: main.c:2341
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tÏÔʾ Gnome Ïà¹Ø²ÎÊý"
+
+#. Failed to send, abort.
+#: main.c:2566
+msgid ""
+"\n"
+"Send failed.\n"
+msgstr ""
+"\n"
+"·¢Ëͱí´ïʽʧ°Ü¡£\n"
+
+#. Let vim start normally.
+#: main.c:2571
+msgid ""
+"\n"
+"Send failed. Trying to execute locally\n"
+msgstr ""
+"\n"
+"Ëͳöʧ°Ü¡£ÊÔͼÔÚ±¾µØÖ´ÐÐ\n"
+
+#: main.c:2604 main.c:2625
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d ÖÐ %d Òѱ༭"
+
+#: main.c:2648
+msgid "Send expression failed.\n"
+msgstr "·¢Ëͱí´ïʽʧ°Ü¡£\n"
+
+#: mark.c:655
+msgid "No marks set"
+msgstr "ûÓÐÉ趨±ê¼Ç (mark)"
+
+#: mark.c:657
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: ÕÒ²»µ½·ûºÏ \"%s\" µÄ±ê¼Ç(mark)"
+
+#. Highlight title
+#: mark.c:668
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"±ê¼Ç ÐкŠÁÐ Îļþ/Îı¾"
+
+#. Highlight title
+#: mark.c:706
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" Ìøµ½ ÐкŠÁÐ Îļþ/Îı¾"
+
+#: mark.c:1068
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Îļþ±ê¼Ç:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1103
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Jumplist (´Óе½¾É):\n"
+
+#: mark.c:1198
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# ÎļþÄÚÀúÊ·¼Ç¼ (´Óе½¾É):\n"
+
+#: mark.c:1281
+msgid "Missing '>'"
+msgstr "ȱÉÙ¶ÔÓ¦µÄ '>'"
+
+#: mbyte.c:395
+msgid "Not a valid codepage"
+msgstr "²»ÕýÈ·µÄ´úÂëÒ³"
+
+#: mbyte.c:3005
+msgid "E284: Cannot set IC values"
+msgstr "E284: ²»ÄÜÉ趨 IC ÊýÖµ"
+
+#: mbyte.c:3157
+msgid "E285: Failed to create input context"
+msgstr "E285: ²»ÄÜ´´½¨ÊäÈëÉÏÏÂÎÄ"
+
+#: mbyte.c:3304
+msgid "E286: Failed to open input method"
+msgstr "E286: ²»ÄÜ´ò¿ªÊäÈë·¨"
+
+#: mbyte.c:3315
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: ¾¯¸æ: ²»ÄÜÒƳý IM µÄ callback"
+
+#: mbyte.c:3321
+msgid "E288: input method doesn't support any style"
+msgstr "E288: ÊäÈë·¨²»Ö§³ÖÈκΠstyle"
+
+#: mbyte.c:3378
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: ÊäÈë·¨²»Ö§³ÖÈκΠstyle"
+
+#: mbyte.c:3452
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: over-the-spot ÐèÒª×ÖÌ弯(Fontset)"
+
+#: mbyte.c:3480
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: ÄãµÄ GTK+ ±È 1.2.3 ÀÏ¡£²»ÄÜʹÓÃ״̬Çø¡£"
+
+#: mbyte.c:3717
+msgid "E292: Input Method Server is not running"
+msgstr "E292: ÊäÈë·¨¹ÜÀí³ÌÐò(Input Method Server)δÔËÐÐ"
+
+#: memfile.c:473
+msgid "E293: block was not locked"
+msgstr "E293: ¿éδ±»Ëø¶¨"
+
+#: memfile.c:972
+msgid "E294: Seek error in swap file read"
+msgstr "E294: ½»»»Îļþ¶ÁÈ¡´íÎó"
+
+#: memfile.c:977
+msgid "E295: Read error in swap file"
+msgstr "E295: ½»»»Îļþ¶ÁÈ¡´íÎó"
+
+#: memfile.c:1029
+msgid "E296: Seek error in swap file write"
+msgstr "E296: ½»»»ÎļþдÈë´íÎó"
+
+#: memfile.c:1047
+msgid "E297: Write error in swap file"
+msgstr "E297: ½»»»ÎļþдÈë´íÎó"
+
+#: memfile.c:1244
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: ½»»»ÎļþÒѾ­´æÔÚ! (СÐÄ·ûºÅÁ¬½áµÄ°²È«Â©¶´!?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: ÕÒ²»µ½¿é 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: ÕÒ²»µ½¿é 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: ÕÒ²»µ½¿é 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: àÞàÞ, ½»»»Îļþ²»¼ûÁË!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: ²»Äܸı佻»»ÎļþµÄÃû³Æ"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: ²»ÄÜ´ò¿ª½»»»Îļþ \"%s\", ²»¿ÉÄָܻ´ÁË"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: ÕÒ²»µ½¿é 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: ÕÒ²»µ½ %s µÄ½»»»Îļþ"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "ÇëÑ¡ÔñÄãҪʹÓõĽ»»»Îļþ (°´0 Í˳ö): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: ²»ÄÜ´ò¿ª %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "²»ÄܶÁÈ¡¿é 0:"
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"¿ÉÄÜÄãû×ö¹ýÈκÎÐ޸ĻòÊÇ Vim »¹À´²»¼°¸üн»»»Îļþ."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " ²»ÄÜÔÚ±¾°æ±¾µÄ Vim ÖÐʹÓÃ.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "ʹÓà Vim 3.0¡£\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s ¿´ÆðÀ´²»ÏñÊÇ Vim ½»»»Îļþ"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " ²»ÄÜÔÚÕą̂µçÄÔÉÏʹÓÃ.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "±¾Îļþ´´½¨ÓÚ "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"»òÊÇÕâÎļþÒѱ»ÆÆ»µ¡£"
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "ʹÓý»»»Îļþ \"%s\""
+
+#: memline.c:915
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Ô­Îļþ \"%s\""
+
+#: memline.c:934
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: ¾¯¸æ: ԭʼÎļþ¿ÉÄÜÒѾ­Ð޸ĹýÁË"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: ²»ÄÜ´Ó %s ¶ÁÈ¡¿é 1"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???ȱÉÙÌ«¶àÐÐ"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???ÐкŴíÎó"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???¿ÕµÄ ¿é"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???ÕÒ²»µ½Ò»Ð©ÐÐ"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ¿é 1 ID ´íÎó (%s ²»Êǽ»»»Îļþ?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???ÕÒ²»µ½¿é"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? ´ÓÕâÀïµ½ ???END µÄÄÚÈÝ¿ÉÄÜÓÐÎÊÌâ"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? ´ÓÕâÀïµ½ ???END µÄÄÚÈÝ¿ÉÄܱ»É¾³ý/²åÈë¹ý"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???END"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: »Ö¸´ÒÑÖжÏ"
+
+#: memline.c:1145
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: »Ö¸´Ê±·¢Éú´íÎó; Çë×¢Ò⿪ͷΪ ??? µÄÐÐ"
+
+#: memline.c:1148
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "»Ö¸´Íê³É. ÇëÈ·¶¨Ò»ÇÐÕý³£."
+
+#: memline.c:1149
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Äã¿ÉÄÜÏëÒª°ÑÕâ¸öÎļþÁí´æΪ±ðµÄÎļþÃû£¬\n"
+
+#: memline.c:1150
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "ÔÙÖ´ÐÐ diff ÓëÔ­Îļþ±È½ÏÒÔ¼ì²éÊÇ·ñÓиıä)\n"
+
+#: memline.c:1151
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"(D)Ö±½Óɾ³ý .swp ½»»»Îļþ\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1207
+msgid "Swap files found:"
+msgstr "ÕÒµ½ÒÔϵĽ»»»Îļþ:"
+
+#: memline.c:1385
+msgid " In current directory:\n"
+msgstr " ÔÚĿǰĿ¼:\n"
+
+#: memline.c:1387
+msgid " Using specified name:\n"
+msgstr " Using specified name:\n"
+
+#: memline.c:1391
+msgid " In directory "
+msgstr " ÔÚĿ¼ "
+
+#: memline.c:1409
+msgid " -- none --\n"
+msgstr " -- ÎÞ --\n"
+
+#: memline.c:1481
+msgid " owned by: "
+msgstr " ËùÓÐÕß: "
+
+#: memline.c:1483
+msgid " dated: "
+msgstr " ÈÕÆÚ: "
+
+#: memline.c:1487 memline.c:3680
+msgid " dated: "
+msgstr " ÈÕÆÚ: "
+
+#: memline.c:1503
+msgid " [from Vim version 3.0]"
+msgstr " [´Ó Vim °æ±¾ 3.0]"
+
+#: memline.c:1507
+msgid " [does not look like a Vim swap file]"
+msgstr " [²»Ïñ Vim µÄ½»»»Îļþ]"
+
+#: memline.c:1511
+msgid " file name: "
+msgstr " ÎļþÃû: "
+
+#: memline.c:1523
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" Ð޸Ĺý: "
+
+#: memline.c:1524
+msgid "YES"
+msgstr "ÊÇ"
+
+#: memline.c:1524
+msgid "no"
+msgstr "·ñ"
+
+#: memline.c:1528
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" ̞: "
+
+#: memline.c:1535
+msgid " host name: "
+msgstr " Ö÷»úÃû: "
+
+#: memline.c:1537
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" Ö÷»úÃû: "
+
+#: memline.c:1543
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ½ø³Ì ID: "
+
+#: memline.c:1549
+msgid " (still running)"
+msgstr " (ÕýÔÚÖ´ÐÐ)"
+
+#: memline.c:1561
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [²»ÄÜÔÚ±¾°æ±¾µÄ Vim ÉÏʹÓÃ]"
+
+#: memline.c:1564
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [²»ÄÜÔÚ±¾»úÉÏʹÓÃ]"
+
+#: memline.c:1569
+msgid " [cannot be read]"
+msgstr " [²»ÄܶÁÈ¡]"
+
+#: memline.c:1573
+msgid " [cannot be opened]"
+msgstr " [²»ÄÜ´ò¿ª]"
+
+#: memline.c:1763
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: ²»Äܱ£Áô, ²»Ê¹Óý»»»Îļþ"
+
+#: memline.c:1816
+msgid "File preserved"
+msgstr "ÎļþÒѱ£Áô"
+
+#: memline.c:1818
+msgid "E314: Preserve failed"
+msgstr "E314: ±£Áôʧ°Ü"
+
+#: memline.c:1889
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: ´íÎóµÄ lnum: %ld"
+
+#: memline.c:1915
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: ÕÒ²»µ½µÚ %ld ÐÐ"
+
+#: memline.c:2303
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: Ö¸Õë¿é id ´íÎó 3"
+
+#: memline.c:2383
+msgid "stack_idx should be 0"
+msgstr "stack_idx Ó¦¸ÃÊÇ 0"
+
+#: memline.c:2445
+msgid "E318: Updated too many blocks?"
+msgstr "E318: ¸üÐÂÌ«¶à¿é?"
+
+#: memline.c:2602
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: Ö¸Õë¿é id ´íÎó 4"
+
+#: memline.c:2629
+msgid "deleted block 1?"
+msgstr "ɾ³ý¿é 1?"
+
+#: memline.c:2829
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: ÕÒ²»µ½µÚ %ld ÐÐ"
+
+#: memline.c:3072
+msgid "E317: pointer block id wrong"
+msgstr "E317: Ö¸Õë¿é id ´íÎó"
+
+#: memline.c:3088
+msgid "pe_line_count is zero"
+msgstr "pe_line_count ΪÁã"
+
+#: memline.c:3117
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: Ðкų¬³ö·¶Î§: %ld ³¬¹ý½áβ"
+
+#: memline.c:3121
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: ¿é %ld ÐÐÊý´íÎó"
+
+#: memline.c:3170
+msgid "Stack size increases"
+msgstr "¶ÑÕ»´óСÔö¼Ó"
+
+#: memline.c:3216
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: Ö¸Õë¿é id ´í 2"
+
+#: memline.c:3670
+msgid "E325: ATTENTION"
+msgstr "E325: ×¢Òâ"
+
+#: memline.c:3671
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"·¢ÏÖ½»»»Îļþ \""
+
+#: memline.c:3675
+msgid "While opening file \""
+msgstr "µ±´ò¿ªÎļþʱ \""
+
+#: memline.c:3684
+msgid " NEWER than swap file!\n"
+msgstr " ±È½»»»ÎļþÐÂ!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3688
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) ¿ÉÄÜÓÐÁíÒ»¸ö³ÌÐòÒ²Ôڱ༭ͬһ¸öÎļþ.\n"
+" Èç¹ûÊÇÕâÑù£¬Çë×¢Òâ²»ÒªÒ»ÆðдÈ룬²»È»ÄãµÄŬÁ¦¶¼»á¸¶ÖÁ÷¡£\n"
+
+#: memline.c:3689
+msgid " Quit, or continue with caution.\n"
+msgstr " Í˳ö£¬»òÊǼÌÐø±à¼­¡£\n"
+
+#: memline.c:3690
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) ÉÏÒ»´Î±à¼­´ËÎļþʱ±ÀÀ£\n"
+
+#: memline.c:3691
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Èç¹ûÊÇÕâÑù, ÇëÓà \":recover\" »ò \"vim -r"
+
+#: memline.c:3693
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" »Ö¸´ÐÞ¸ÄÄÚÈÝ (½øÒ»²½ËµÃ÷Çë¿´ \":help recovery\").\n"
+
+#: memline.c:3694
+msgid " If you did this already, delete the swap file \""
+msgstr " Èç¹û¸Ã»Ö¸´µÄ¶¼ÒѾ­»Ö¸´ÁË, ÇëÖ±½Óɾ³ý´Ë½»»»Îļþ \""
+
+#: memline.c:3696
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" ÒÔ±ÜÃâÔÙ¿´µ½´ËÐÅÏ¢.\n"
+
+#: memline.c:3710 memline.c:3714
+msgid "Swap file \""
+msgstr "½»»»Îļþ \""
+
+#: memline.c:3711 memline.c:3717
+msgid "\" already exists!"
+msgstr "\" ÒѾ­´æÔÚÁË!"
+
+#: memline.c:3720
+msgid "VIM - ATTENTION"
+msgstr "VIM - ×¢Òâ"
+
+#: memline.c:3722
+msgid "Swap file already exists!"
+msgstr "½»»»ÎļþÒѾ­´æÔÚ!"
+
+#: memline.c:3726
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"ÒÔÖ»¶Á·½Ê½´ò¿ª(&O)\n"
+"Ö±½Ó±à¼­(&E)\n"
+"»Ö¸´(&R)\n"
+"Í˳ö(&Q)"
+
+#: memline.c:3728
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"ÒÔÖ»¶Á·½Ê½´ò¿ª(&O)\n"
+"Ö±½Ó±à¼­(&E)\n"
+"»Ö¸´(&R)\n"
+"Í˳ö(&Q)\n"
+"ɾ³ý½»»»Îļþ(&D)"
+
+#: memline.c:3781
+msgid "E326: Too many swap files found"
+msgstr "E326: ÕÒµ½Ì«¶à½»»»Îļþ"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: ²¿·Ý²Ëµ¥Ïî²»ÊÇ×Ӳ˵¥"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: ²Ëµ¥Ö»ÄÜÔÚÆäËüģʽÖÐʹÓÃ"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: ûÓÐÄÇÑùµÄ²Ëµ¥"
+
+#: menu.c:503
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: ²Ëµ¥²»ÄÜÖ¸Ïò×ÓÑ¡µ¥"
+
+#: menu.c:542
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: ²»ÄÜÖ±½Ó°Ñ²Ëµ¥Ïî¼Óµ½²Ëµ¥ÌõÖÐ"
+
+#: menu.c:548
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: ·Ö¸ôÏß²»ÄÜÊDz˵¥µÄÒ»²¿·Ö"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1063
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- ²Ëµ¥ ---"
+
+#: menu.c:1989
+msgid "Tear off this menu"
+msgstr "ÇÐÏ´˲˵¥"
+
+#: menu.c:2054
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: ²Ëµ¥±ØÐèÖ¸ÏòÒ»¸ö²Ëµ¥Ïî"
+
+#: menu.c:2074
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: [²Ëµ¥] ÕÒ²»µ½ %s"
+
+#: menu.c:2143
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: %s ģʽ䶨Òå²Ëµ¥"
+
+#: menu.c:2181
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: ²Ëµ¥±ØÐèÖ¸Ïò×Ӳ˵¥"
+
+#: menu.c:2202
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: ÕÒ²»µ½²Ëµ¥ - Çë¼ì²é²Ëµ¥Ãû³Æ"
+
+#: message.c:467
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "´¦Àí %s ʱ·¢Éú´íÎó:"
+
+#: message.c:483
+#, c-format
+msgid "line %4ld:"
+msgstr "ÐÐ %4ld:"
+
+#: message.c:523
+msgid "[string too long]"
+msgstr "[×Ö·û´®Ì«³¤]"
+
+#: message.c:669
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "¼òÌåÖÐÎÄÐÅϢά»¤Õß: Wang Jun <junw@turbolinux.com.cn>"
+
+#: message.c:881
+msgid "Interrupt: "
+msgstr "ÒÑÖжÏ: "
+
+#: message.c:884
+msgid "Hit ENTER to continue"
+msgstr "Çë°´ ENTER ¼ÌÐø"
+
+#: message.c:886
+msgid "Hit ENTER or type command to continue"
+msgstr "Çë°´ ENTER »òÆäËüÃüÁî¼ÌÐø"
+
+#: message.c:1940
+msgid "-- More --"
+msgstr "-- ¸ü¶à --"
+
+#: message.c:1943
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: ÏòÏÂ/ÏòÉÏÒ»ÐÐ, ¿Õ¸ñ/b: Ò»Ò³, d/u: °ëÒ³, q: Í˳ö)"
+
+#: message.c:1944
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: ÏòÏÂÒ»ÐÐ, ¿Õ°×¼ü: Ò»Ò³, d: °ëÒ³, q: Í˳ö)"
+
+#: message.c:2419 message.c:2434
+msgid "Question"
+msgstr "ÎÊÌâ"
+
+#: message.c:2421
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&YÊÇ\n"
+"&N·ñ"
+
+#: message.c:2436
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&YÊÇ\n"
+"&N·ñ\n"
+"&CÈ¡Ïû"
+
+#: message.c:2454
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&YÊÇ\n"
+"&N·ñ\n"
+"&AÈ«²¿±£´æ\n"
+"&DÈ«²¿²»´æ\n"
+"&CÈ¡Ïû"
+
+#: message.c:2494
+msgid "Save File dialog"
+msgstr "±£´æÎļþ¶Ô»°¿ò"
+
+#: message.c:2496
+msgid "Open File dialog"
+msgstr "´ò¿ªÎļþ¶Ô»°¿ò"
+
+#. TODO: non-GUI file selector here
+#: message.c:2547
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: Ö÷¿Ø̨(Console)ģʽʱûÓÐÎļþä¯ÀÀÆ÷(file browser)"
+
+#: misc1.c:2449
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: ×¢Òâ: ÄãÕýÔÚÐÞ¸ÄÒ»¸öÖ»¶ÁÎļþ"
+
+#: misc1.c:2678
+msgid "1 more line"
+msgstr "»¹ÓÐÒ»ÐÐ"
+
+#: misc1.c:2680
+msgid "1 line less"
+msgstr "ÉÙÓÚÒ»ÐÐ"
+
+#: misc1.c:2685
+#, c-format
+msgid "%ld more lines"
+msgstr " »¹ÓÐ %ld ÐÐ"
+
+#: misc1.c:2687
+#, c-format
+msgid "%ld fewer lines"
+msgstr "ֻʣ %ld ÐÐ"
+
+#: misc1.c:2690
+msgid " (Interrupted)"
+msgstr " (ÒÑÖжÏ)"
+
+#: misc1.c:6244
+msgid "Vim: preserving files...\n"
+msgstr "Vim: ±£ÁôÎļþÖÐ...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6254
+msgid "Vim: Finished.\n"
+msgstr "Vim: ½áÊø.\n"
+
+#: misc2.c:644 misc2.c:660
+msgid "ERROR: "
+msgstr "´íÎó: "
+
+#: misc2.c:664
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bytes] È«²¿ alloc-freed %lu-%lu, ʹÓÃÖÐ %lu, peak ʹÓà %lu\n"
+
+#: misc2.c:666
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[µ÷ÓÃ] È«²¿ re/malloc(): %lu, È«²¿ free()': %lu\n"
+"\n"
+
+#: misc2.c:721
+msgid "E340: Line is becoming too long"
+msgstr "E340: ´ËÐйý³¤"
+
+#: misc2.c:765
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: ÄÚ²¿´íÎó: lalloc(%ld, )"
+
+#: misc2.c:873
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: ÄÚ´æ²»×ã! (³¢ÊÔÅäÖà %lu ×Ö½Ú×é)"
+
+#: misc2.c:2508
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "µ÷ÓÃ shell Ö´ÐÐ: \"%s\""
+
+#: misc2.c:2703 misc2.c:5142 option.c:4584
+msgid "Missing colon"
+msgstr "ȱÉÙðºÅ"
+
+#: misc2.c:2705 misc2.c:2732
+msgid "Illegal mode"
+msgstr "²»ÕýÈ·µÄģʽ"
+
+#: misc2.c:2771
+msgid "Illegal mouseshape"
+msgstr "²»ÕýÈ·µÄÊó±êÐÎ×´"
+
+#: misc2.c:2811 misc2.c:5162
+msgid "digit expected"
+msgstr "Ó¦¸ÃΪÊý×Ö"
+
+#: misc2.c:2816
+msgid "Illegal percentage"
+msgstr "²»ÕýÈ·µÄ°Ù·Ö±È"
+
+#: misc2.c:3120
+msgid "Enter encryption key: "
+msgstr "ÊäÈëÃÜÂë: "
+
+#: misc2.c:3121
+msgid "Enter same key again: "
+msgstr "ÇëÔÙÊäÈëÒ»´Î: "
+
+#: misc2.c:3131
+msgid "Keys don't match!"
+msgstr "Á½´ÎÊäÈëÃÜÂ벻ͬ!"
+
+#: misc2.c:3645
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr "E343: ²»ÕýÈ·µÄ·¾¶: '**[number]' ±ØÐèÒªÔÚ·¾¶½áβ»òÒª½ÓÖø '%s'"
+
+#: misc2.c:4899
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: cdpath ÖÐûÓÐĿ¼ \"%s\""
+
+#: misc2.c:4902
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: ÔÚ·¾¶ÖÐÕÒ²»µ½Îļþ \"%s\""
+
+#: misc2.c:4908
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: ÔÚ·¾¶ÖÐÕÒ²»µ½¸ü¶àµÄÎļþ \"%s\""
+
+#: misc2.c:4911
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: ÔÚ·¾¶ÖÐÕÒ²»µ½¸ü¶àµÄÎļþ \"%s\""
+
+#: misc2.c:5154
+msgid "Illegal component"
+msgstr "²»ÕýÈ·µÄ×é¼þ"
+
+#: normal.c:2798
+msgid "Warning: terminal cannot highlight"
+msgstr "×¢Òâ: ÄãµÄÖն˲»ÄÜÏÔʾ¸ßÁÁ¶È"
+
+#: normal.c:2993
+msgid "E348: No string under cursor"
+msgstr "E348: ¹â±ê´¦Ã»ÓÐ×Ö·û´®"
+
+#: normal.c:2995
+msgid "E349: No identifier under cursor"
+msgstr "E349: ¹â±ê´¦Ã»ÓÐʶ±ð×Ö"
+
+#: normal.c:4160
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: ²»ÄÜÔÚÄ¿Ç°µÄ 'foldmethod' ÏÂɾ³ý fold"
+
+#: ops.c:271
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "Ò»ÐÐ %s ¹ý Ò»´Î"
+
+#: ops.c:273
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "Ò»ÐÐ %s ¹ý %d ´Î"
+
+#: ops.c:278
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld ÐÐ %s ¹ý Ò»´Î"
+
+#: ops.c:281
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld ÐÐ %s ¹ý %d ´Î"
+
+#: ops.c:638
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "ʶ±ð %ld ÐÐ..."
+
+#: ops.c:688
+msgid "1 line indented "
+msgstr "Ò»ÐÐÒÑʶ±ð"
+
+#: ops.c:690
+#, c-format
+msgid "%ld lines indented "
+msgstr "ÒÑʶ±ð %ld ÐÐ"
+
+#. must display the prompt
+#: ops.c:1528
+msgid "cannot yank; delete anyway"
+msgstr "²»Äܸ´ÖÆ; Ö±½Óɾ³ý"
+
+#: ops.c:2018
+msgid "1 line changed"
+msgstr " 1 ÐÐ ~ed"
+
+#: ops.c:2020
+#, c-format
+msgid "%ld lines changed"
+msgstr " %ld ÐÐ ~ed"
+
+#: ops.c:2381
+#, c-format
+msgid "freeing %ld lines"
+msgstr "ÊÍ·Å %ld ÐÐÖÐ"
+
+#: ops.c:2658
+msgid "1 line yanked"
+msgstr "ÒѸ´ÖÆ 1 ÐÐ"
+
+#: ops.c:2660
+#, c-format
+msgid "%ld lines yanked"
+msgstr "ÒѸ´ÖÆ %ld ÐÐ"
+
+#: ops.c:2916
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: ¼Ä´æÆ÷ %s ÀïûÓж«Î÷"
+
+#. Highlight title
+#: ops.c:3454
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- ¼Ä´æÆ÷ ---"
+
+#: ops.c:4565
+msgid "Illegal register name"
+msgstr "²»ÕýÈ·µÄ¼Ä´æÆ÷Ãû³Æ"
+
+#: ops.c:4645
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# ¼Ä´æÆ÷:\n"
+
+#: ops.c:4671
+#, c-format
+msgid "Unknown register type %d"
+msgstr "δ֪µÄ×¢²áÀàÐÍ: %d"
+
+#: ops.c:5052
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: ¼Ä´æÆ÷Ãû³Æ´íÎó: '%s'"
+
+#: ops.c:5393
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld ÁÐ; "
+
+#: ops.c:5400
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Ñ¡ÔñÁË %s%ld/%ld ÐÐ; %ld/%ld ×Ö(Word); %ld/%ld ×Ö·û(Bytes)"
+
+#: ops.c:5416
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "ÁÐ %s/%s; ÐÐ %ld/%ld; ×Ö(Word) %ld/%ld; ×Ö·û(Byte) %ld/%ld"
+
+#: ops.c:5427
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld for BOM)"
+
+#: option.c:1989
+msgid "Thanks for flying Vim"
+msgstr "¸ÐлÄúÑ¡Ôñ Vim"
+
+#: option.c:3175
+msgid "Option not supported"
+msgstr "²»Ö§³Ö¸ÃÑ¡Ïî"
+
+#: option.c:3200
+msgid "Not allowed in a modeline"
+msgstr "²»ÄÜÔÚģʽÐÐÀï³öÏÖ"
+
+#: option.c:3256
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tµ±Ç°ÉèÖÃ: "
+
+#: option.c:3395
+msgid "Number required after ="
+msgstr "= ºóÐèÒªÓÐÊý×Ö"
+
+#: option.c:3702 option.c:4309
+msgid "Not found in termcap"
+msgstr "Termcap ÀïÃæÕÒ²»µ½"
+
+#: option.c:3768
+#, c-format
+msgid "Illegal character <%s>"
+msgstr "²»ÕýÈ·µÄ×Ö·û <%s>"
+
+#: option.c:4294 option.c:5497
+msgid "Not allowed here"
+msgstr "ÕâÀï²»¿ÉʹÓÃ"
+
+#: option.c:4301
+msgid "Cannot set 'term' to empty string"
+msgstr "²»ÄÜÉ趨 'term' Ϊ¿Õ×Ö·û´®"
+
+#: option.c:4304
+msgid "Cannot change term in GUI"
+msgstr "ÔÚͼÐͽçÃæÖв»ÄÜÇл»ÖÕ¶Ë"
+
+#: option.c:4306
+msgid "Use \":gui\" to start the GUI"
+msgstr "ÊäÈë \":gui\" À´Æô¶¯Í¼ÐνçÃæ"
+
+#: option.c:4327
+msgid "'backupext' and 'patchmode' are equal"
+msgstr "'backupext' ¸ú 'patchmode' ÊÇÒ»ÑùµÄ"
+
+#: option.c:4586
+msgid "Zero length string"
+msgstr "Á㳤¶È×Ö·û´®"
+
+#: option.c:4654
+#, c-format
+msgid "Missing number after <%s>"
+msgstr "<%s> ºóȱÉÙÊý×Ö"
+
+#: option.c:4668
+msgid "Missing comma"
+msgstr "ȱÉÙ¶ººÅ"
+
+#: option.c:4675
+msgid "Must specify a ' value"
+msgstr "±ØÐèÖ¸¶¨Ò»¸ö ' Öµ"
+
+#: option.c:4715
+msgid "contains unprintable character"
+msgstr "°üº¬²»ÄÜÏÔʾµÄ×Ö·û"
+
+#: option.c:4728
+msgid "Invalid font(s)"
+msgstr "²»ÕýÈ·µÄ×ÖÌå"
+
+#: option.c:4734
+msgid "can't select fontset"
+msgstr "²»ÄÜʹÓÃ×ÖÌ弯(Fontset)"
+
+#: option.c:4736
+msgid "Invalid fontset"
+msgstr "²»ÕýÈ·µÄ×ÖÌ弯(Fontset)"
+
+#: option.c:4743
+msgid "can't select wide font"
+msgstr "²»ÄÜʹÓÃÉ趨µÄ¿í×ÖÌå(Widefont)"
+
+#: option.c:4745
+msgid "Invalid wide font"
+msgstr "²»ÕýÈ·µÄ¿í×ÖÌå(Widefont)"
+
+#: option.c:5014
+#, c-format
+msgid "Illegal character after <%c>"
+msgstr "<%c> ºóÓв»ÕýÈ·µÄ×Ö·û"
+
+#: option.c:5097
+msgid "comma required"
+msgstr "ÐèÒª¶ººÅ"
+
+#: option.c:5106
+#, c-format
+msgid "'commentstring' must be empty or contain %s"
+msgstr "'commentstring' ±ØÐèÊÇ¿Õ°×»ò°üº¬ %s"
+
+#: option.c:5153
+msgid "No mouse support"
+msgstr "²»Ö§³ÖÊó±ê"
+
+#: option.c:5399
+msgid "Unclosed expression sequence"
+msgstr "ûÓнáÊøµÄ±í´ïʽ: "
+
+#: option.c:5403
+msgid "too many items"
+msgstr "Ì«¶à¶ÔÏó"
+
+#: option.c:5405
+msgid "unbalanced groups"
+msgstr "²»¶Ô³ÆµÄ×é"
+
+#: option.c:5620
+msgid "A preview window already exists"
+msgstr "Ô¤ÀÀ´°¿ÚÒѾ­´æÔÚÁË"
+
+#: option.c:5881 option.c:5910
+msgid "'winheight' cannot be smaller than 'winminheight'"
+msgstr "'winheight' ²»ÄÜ±È 'winminheight' ¸üÉÙ"
+
+#: option.c:5926 option.c:5945
+msgid "'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "'winwidth' ²»ÄÜ±È 'winminwidth' ¸üÉÙ"
+
+#: option.c:6085
+#, c-format
+msgid "Need at least %d lines"
+msgstr "ÖÁÉÙÐèÒª %d ÐÐ"
+
+#: option.c:6094
+#, c-format
+msgid "Need at least %d columns"
+msgstr "ÖÁÉÙÐèÒª %d ÁÐ"
+
+#: option.c:6391
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: ²»ÕýÈ·µÄÑ¡Ïî: %s"
+
+#: option.c:6500
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Öն˱àÂë ---"
+
+#: option.c:6502
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- È«¾Ö Ñ¡ÏîÖµ ---"
+
+#: option.c:6504
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- ±¾µØ Ñ¡ÏîÖµ ---"
+
+#: option.c:6506
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Ñ¡Ïî ---"
+
+#: option.c:7196
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp ´íÎó"
+
+#: option.c:8112
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': ÕÒ²»µ½ %s ¶ÔÓ¦µÄ×Ö·û"
+
+#: option.c:8146
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': ·ÖºÅºóÓжàÓàµÄ×Ö·û: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "²»ÄÜ´ò¿ª"
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: ²»ÄÜ´ò¿ª´°¿Ú!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "ÐèÒª Amigados °æ±¾ 2.04 ÒÔÉÏ\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "ÐèÒª %s °æ±¾ %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "²»ÄÜ´ò¿ª NIL:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr "²»ÄÜ´´½¨ "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim ·µ»ØÖµ: %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "²»ÄÜÇл»Ö÷¿Ø̨(console)ģʽ !?\n"
+
+#: os_amiga.c:938 os_mac.c:1168 os_mswin.c:619 os_riscos.c:728 os_unix.c:2726
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: ²»Ö§³ÖÉ趨ÆÁĻģʽ"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: ²»ÊÇÖ÷¿Ø̨(console)??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1142
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: ²»ÄÜÓà -f Ñ¡ÏîÖ´ÐÐ shell"
+
+#: os_amiga.c:1183 os_amiga.c:1273
+msgid "Cannot execute "
+msgstr "²»ÄÜÖ´ÐÐ "
+
+#: os_amiga.c:1186 os_amiga.c:1283
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1206 os_amiga.c:1308
+msgid " returned\n"
+msgstr " ÒÑ·µ»Ø\n"
+
+#: os_amiga.c:1448
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE ̫С"
+
+#: os_amiga.c:1452
+msgid "I/O ERROR"
+msgstr "I/O ´íÎó"
+
+#: os_mswin.c:503
+msgid "...(truncated)"
+msgstr ""
+
+#: os_mswin.c:594
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' ²»ÊÇ 80, ²»ÄÜÖ´ÐÐÍⲿÃüÁî"
+
+#: os_mswin.c:706 os_unix.c:4945
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: µ÷Óú¯Êý¿â \"%s\"() ʧ°Ü"
+
+#: os_mswin.c:1340
+msgid "E237: Printer selection failed"
+msgstr "E237: ²»ÄÜÑ¡Ôñ´Ë´òÓ¡»ú"
+
+#: os_mswin.c:1388
+#, c-format
+msgid "to %s on %s"
+msgstr "´Ó %s µ½ %s"
+
+#: os_mswin.c:1449 os_mswin.c:1459
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: ´òÓ¡´íÎó: %s"
+
+#: os_mswin.c:1459
+msgid "Unknown"
+msgstr "δ֪"
+
+#: os_mswin.c:1486
+#, c-format
+msgid "Printing '%s'"
+msgstr "ÒÑ´òÓ¡: '%s'"
+
+#: os_mswin.c:2550
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: ×Ö·û¼¯ \"%s\" ²»ÄܶÔÓ¦×ÖÌå\"%s\""
+
+#: os_mswin.c:2558
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: ²»ÕýÈ·µÄ×Ö·û '%c' ³öÏÖÔÚ×ÖÌåÃû³Æ \"%s\" ÄÚ"
+
+#: os_riscos.c:1227
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: ²»ÕýÈ·µÄ 'filetype' Ñ¡Ïî - ʹÓô¿ÎÄ×Öģʽ"
+
+#: os_unix.c:800
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: Ë«ÖØÐźÅ, Í˳öÖÐ\n"
+
+#: os_unix.c:806
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: CVim: À¹½Øµ½ÐźÅ(signal) %s\n"
+
+#: os_unix.c:809
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: À¹½Øµ½ÖÂÃüµÄÐźÅ(deadly signale)\n"
+
+#: os_unix.c:1063
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "´ò¿ª X Window ÓÃʱ %ld Ãë"
+
+#: os_unix.c:1090
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: X ´íÎó\n"
+
+#: os_unix.c:1157
+msgid "Testing the X display failed"
+msgstr "²âÊÔ X Window ʧ°Ü"
+
+#: os_unix.c:1301
+msgid "Opening the X display timed out"
+msgstr "´ò¿ª X Window ³¬Ê±"
+
+#: os_unix.c:2899 os_unix.c:3483
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"²»ÄÜÖ´ÐÐ shell"
+
+#: os_unix.c:2944
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"²»ÄÜÖ´ÐÐ shell sh\n"
+
+#: os_unix.c:2948 os_unix.c:3489
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"Shell ÒÑ·µ»Ø"
+
+#: os_unix.c:3082
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"²»Äܽ¨Á¢¹ÜµÀ\n"
+
+#: os_unix.c:3097
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"²»ÄÜ fork\n"
+
+#: os_unix.c:3496
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"ÃüÁîÒѽáÊø\n"
+
+#: os_unix.c:4993
+msgid "Opening the X display failed"
+msgstr "´ò¿ª X Window ʧ°Ü"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "ÔÚÐкŠ"
+
+#: os_w32exe.c:169
+msgid "Could not load vim32.dll!"
+msgstr "²»ÄܼÓÔØ vim32.dll£¡"
+
+#: os_w32exe.c:169 os_w32exe.c:179
+msgid "VIM Error"
+msgstr "VIM ´íÎó"
+
+#: os_w32exe.c:179
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "²»ÄÜÐÞÕýº¯ÊýÖ¸Õëµ½ DLL!"
+
+#: os_win16.c:578 os_win32.c:3019
+#, c-format
+msgid "shell returned %d"
+msgstr "Shell ·µ»ØÖµ %d"
+
+#: os_win32.c:2489
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: À¹½Øµ½ %s ʼþ\n"
+
+#: os_win32.c:2491
+msgid "close"
+msgstr "¹Ø±Õ"
+
+#: os_win32.c:2493
+msgid "logoff"
+msgstr "×¢Ïû"
+
+#: os_win32.c:2494
+msgid "shutdown"
+msgstr "¹Ø»ú"
+
+#: os_win32.c:2975
+msgid "E371: Command not found"
+msgstr "E371: ÕÒ²»µ½ÃüÁî"
+
+#: os_win32.c:2988
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"ÔÚÄãµÄ $PATH ÖÐÕÒ²»µ½ VIMRUN.EXE.\n"
+"ÍⲿÃüÁîÖ´ÐÐÍê±Ïºó½«²»»áÔÝÍ£.\n"
+"½øÒ»²½ËµÃ÷ÇëÖ´ÐÐ :help win32-vimrun "
+
+#: os_win32.c:2991
+msgid "Vim Warning"
+msgstr "Vim ¾¯¸æ"
+
+#: quickfix.c:281
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: ¸ñʽ»¯×Ö·û´®ÀïÓÐÌ«¶à %%%c "
+
+#: quickfix.c:294
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: ¸ñʽ»¯×Ö·û´®²»Ó¦¸Ã³öÏÖ %%%c "
+
+#: quickfix.c:348
+msgid "E374: Missing ] in format string"
+msgstr "E374: ¸ñʽ»¯×Ö·û´®ÀïÉÙÁË ]"
+
+#: quickfix.c:362
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: ¸ñʽ»¯×Ö·û´®ÀïÓв»Ö§³ÖµÄ %%%c "
+
+#: quickfix.c:380
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: ¸ñʽ»¯×Ö·û´®¿ªÍ·ÀïÓв»ÕýÈ·µÄ %%%c "
+
+#: quickfix.c:388
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: ¸ñʽ»¯×Ö·û´®ÀïÓв»ÕýÈ·µÄ %%%c "
+
+#: quickfix.c:414
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' δÉ趨"
+
+#: quickfix.c:520
+msgid "E379: Missing or empty directory name"
+msgstr "E379: ÕÒ²»µ½Ä¿Â¼Ãû³Æ»òÊÇ¿ÕµÄĿ¼Ãû³Æ"
+
+#: quickfix.c:931
+msgid "No more items"
+msgstr "ûÓÐÆäËü¶ÔÏó"
+
+#: quickfix.c:1152
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d / %d)%s%s: "
+
+#: quickfix.c:1154
+msgid " (line deleted)"
+msgstr " (ÐÐÒÑɾ³ý)"
+
+#: quickfix.c:1360
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Quickfix ¶ÑÕ»½áβ"
+
+#: quickfix.c:1369
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Quickfix ¶ÑÕ»¶¥¶Ë"
+
+#: quickfix.c:1381
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "´íÎóÁбí %d/%d; ¹²ÓÐ %d Ïî´íÎó"
+
+#: quickfix.c:1842
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: ²»ÄÜдÈ룬'buftype' Ñ¡ÏîÒÑÉ趨"
+
+#: regexp.c:801
+msgid "E339: Pattern too long"
+msgstr "E339: Ãû×ÖÌ«³¤"
+
+#: regexp.c:1315
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: ³²×´ %s*"
+
+#: regexp.c:1318
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: ³²×´ %s%c"
+
+#: regexp.c:1467
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c ûÓнӶ«Î÷"
+
+#: regexp.c:2469
+#, c-format
+msgid "Syntax error in %s{...}"
+msgstr "Óï·¨´íÎó: %s{...}"
+
+#: regexp.c:2716
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: ²»ÄÜÖ´ÐÐ; regular expression Ì«¸´ÔÓ?"
+
+#: regexp.c:2851
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: regular expression Ôì³É¶ÑÕ»ÓùâµÄ´íÎó"
+
+#: regexp.c:3087
+msgid "External submatches:\n"
+msgstr "Íⲿ·ûºÏ:\n"
+
+#: screen.c:2051
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--ÒÑ fold %3ld ÐÐ"
+
+#: screen.c:7411
+msgid " VREPLACE"
+msgstr " V-Ìæ»»"
+
+#: screen.c:7415
+msgid " REPLACE"
+msgstr " Ìæ»»"
+
+#: screen.c:7420
+msgid " REVERSE"
+msgstr " ·´×ª"
+
+#: screen.c:7422
+msgid " INSERT"
+msgstr " ²åÈë"
+
+#: screen.c:7425
+msgid " (insert)"
+msgstr " (²åÈë)"
+
+#: screen.c:7427
+msgid " (replace)"
+msgstr " (Ìæ»»)"
+
+#: screen.c:7429
+msgid " (vreplace)"
+msgstr " (v-Ìæ»»)"
+
+#: screen.c:7432
+msgid " Hebrew"
+msgstr " Ï£²®À³"
+
+#: screen.c:7440
+msgid " (lang)"
+msgstr " (ÓïÑÔ)"
+
+#: screen.c:7443
+msgid " (paste)"
+msgstr " (Õ³Ìû)"
+
+#: screen.c:7449
+msgid " SELECT"
+msgstr " Ñ¡È¡"
+
+#: screen.c:7451
+msgid " VISUAL"
+msgstr " ¿ÉÊÓ"
+
+#: screen.c:7453
+msgid " BLOCK"
+msgstr " ¿é"
+
+#: screen.c:7455
+msgid " LINE"
+msgstr " ÐÐ"
+
+#: screen.c:7468 screen.c:7522
+msgid "recording"
+msgstr "¼Ç¼ÖÐ"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "ÒѲéÕÒµ½Îļþ¿ªÍ·£»ÔÙ´Ó½áβ¼ÌÐø²éÕÒ"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "ÒѲéÕÒµ½Îļþ½áβ£»ÔÙ´Ó¿ªÍ·¼ÌÐø²éÕÒ"
+
+#: search.c:440
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: ´íÎóµÄ²éÕÒ×Ö·û´®: %s"
+
+#: search.c:747
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: ÒѲéÕÒµ½Îļþ¿ªÍ·ÈÔÕÒ²»µ½ %s"
+
+#: search.c:749
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: ÒѲéÕÒµ½Îļþ½áβÈÔÕÒ²»µ½ %s"
+
+#: search.c:1107
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: ÔÚ ';' ºóÃæÓ¦¸ÃÓÐ '?' »ò '/'"
+
+#: search.c:3476
+msgid " (includes previously listed match)"
+msgstr " (°üÀ¨ÉÏ´ÎÁгö·ûºÏÏî)"
+
+#. cursor at status line
+#: search.c:3496
+msgid "--- Included files "
+msgstr "--- °üº¬Îļþ "
+
+#: search.c:3498
+msgid "not found "
+msgstr "ÕÒ²»µ½ "
+
+#: search.c:3499
+msgid "in path ---\n"
+msgstr "ÔÚ·¾¶ ---\n"
+
+#: search.c:3538
+msgid " (Already listed)"
+msgstr " (ÒÑÁгö)"
+
+#: search.c:3540
+msgid " NOT FOUND"
+msgstr " ÕÒ²»µ½"
+
+#: search.c:3592
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "²éÕÒ°üº¬Îļþ: %s"
+
+#: search.c:3810
+msgid "E387: Match is on current line"
+msgstr "E387: µ±Ç°ÐÐÆ¥Åä"
+
+#: search.c:3950
+msgid "All included files were found"
+msgstr "ËùÓаüº¬Îļþ¶¼ÒÑÕÒµ½"
+
+#: search.c:3952
+msgid "No included files"
+msgstr "ûÓаüº¬Îļþ"
+
+#: search.c:3968
+msgid "E388: Couldn't find definition"
+msgstr "E388: ÕÒ²»µ½¶¨Òå"
+
+#: search.c:3970
+msgid "E389: Couldn't find pattern"
+msgstr "E389: ÕÒ²»µ½ pattern"
+
+#: syntax.c:2990
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: ²ÎÊý²»ÕýÈ·: %s"
+
+#: syntax.c:3167
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: ÎÞ´ËÓï·¨ cluster: \"%s\""
+
+#: syntax.c:3331
+msgid "No Syntax items defined for this buffer"
+msgstr "Õâ¸ö»º³åÇøûÓж¨ÒåÈκÎÓï·¨Ïî"
+
+#: syntax.c:3339
+msgid "syncing on C-style comments"
+msgstr "C·ç¸ñ×¢ÊÍͬ²½ÖÐ"
+
+#: syntax.c:3347
+msgid "no syncing"
+msgstr "ûÓÐͬ²½"
+
+#: syntax.c:3350
+msgid "syncing starts "
+msgstr "ͬ²½¿ªÊ¼"
+
+#: syntax.c:3352 syntax.c:3421
+msgid " lines before top line"
+msgstr "Ðкų¬³ö·¶Î§"
+
+#: syntax.c:3356
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Ó﷨ͬ²½ÏîÄ¿ (Syntax sync items) ---"
+
+#: syntax.c:3359
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"ͬ²½ÖÐ:"
+
+#: syntax.c:3364
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Óï·¨ÏîÄ¿ ---"
+
+#: syntax.c:3387
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: ÎÞ´ËÓï·¨ cluster: \"%s\""
+
+#: syntax.c:3411
+msgid "minimal "
+msgstr "×îС"
+
+#: syntax.c:3418
+msgid "maximal "
+msgstr "×î´ó"
+
+#: syntax.c:4046
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: ʹÓÃÁ˲»ÕýÈ·µÄ²ÎÊý"
+
+#: syntax.c:4070
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: ÕÒ²»µ½ %s µÄ region item"
+
+#: syntax.c:4098
+msgid "E395: contains argument not accepted here"
+msgstr "E395: ʹÓÃÁ˲»ÕýÈ·µÄ²ÎÊý"
+
+#: syntax.c:4109
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: ʹÓÃÁ˲»ÕýÈ·µÄ²ÎÊý"
+
+#: syntax.c:4187
+msgid "E397: Filename required"
+msgstr "E397: ÐèÒªÎļþÃû³Æ"
+
+#: syntax.c:4523
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: ȱÉÙ \"=\": %s"
+
+#: syntax.c:4679
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: syntax region %s µÄ²ÎÊýÌ«ÉÙ"
+
+#: syntax.c:5010
+msgid "E400: No cluster specified"
+msgstr "E400: ûÓÐÖ¸¶¨µÄÊôÐÔ"
+
+#: syntax.c:5047
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: ÕÒ²»µ½·Ö¸ô·ûºÅ: %s"
+
+#: syntax.c:5122
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: '%s' ºóÃæµÄ¶«Î÷²»ÄÜʶ±ð"
+
+#: syntax.c:5204
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: Ó﷨ͬ²½: Á¬½ÓÐзûºÅÖ¸¶¨ÁËÁ½´Î"
+
+#: syntax.c:5261
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: ²ÎÊý²»ÕýÈ·: %s"
+
+#: syntax.c:5311
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: ȱÉٵȺÅ: %s"
+
+#: syntax.c:5317
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: ¿Õ²ÎÊý: %s"
+
+#: syntax.c:5344
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s ²»ÄÜÔڴ˳öÏÖ"
+
+#: syntax.c:5351
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s ±ØÐëÊÇÁбíÀïµÄµÚÒ»¸ö"
+
+#: syntax.c:5421
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: ²»ÕýÈ·µÄ×éÃû: %s"
+
+#: syntax.c:5644
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: ²»ÕýÈ·µÄ :syntax ×ÓÃüÁî: %s"
+
+#: syntax.c:6023
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: ÕÒ²»µ½ highlight group: %s"
+
+#: syntax.c:6047
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: ²ÎÊýÌ«ÉÙ: \":highlight link %s\""
+
+#: syntax.c:6054
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: ²ÎÊý¹ý¶à: \":highlight link %s\""
+
+#: syntax.c:6074
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: ÒÑÉ趨×é, ºöÂÔ highlight link"
+
+#: syntax.c:6203
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: ²»¸ÃÓеĵȺÅ: %s"
+
+#: syntax.c:6239
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: ȱÉٵȺÅ: %s"
+
+#: syntax.c:6261
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: ȱÉÙ²ÎÊý: %s"
+
+#: syntax.c:6298
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: ²»ºÏ·¨µÄÖµ: %s"
+
+#: syntax.c:6417
+msgid "E419: FG color unknown"
+msgstr "E419: ´íÎóµÄÇ°¾°ÑÕÉ«"
+
+#: syntax.c:6428
+msgid "E420: BG color unknown"
+msgstr "E420: ´íÎóµÄ±³¾°ÑÕÉ«"
+
+#: syntax.c:6483
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: ´íÎóµÄÑÕÉ«Ãû³Æ»òÊýÖµ: %s"
+
+#: syntax.c:6687
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: Öն˱àÂëÌ«³¤: %s"
+
+#: syntax.c:6734
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: ²ÎÊý²»ÕýÈ·: %s"
+
+#: syntax.c:7263
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: ʹÓÃÁËÌ«¶à²»Í¬µÄ¸ßÁÁ¶ÈÊôÐÔ"
+
+#: tag.c:90
+msgid "at bottom of tag stack"
+msgstr "±êÇ©(tag)¶ÑÕ»½áβ"
+
+#: tag.c:91
+msgid "at top of tag stack"
+msgstr "±êÇ©(tag)¶ÑÕ»¿ªÍ·"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: ÒѾ­ÔÚ×îÇ°ÃæµÄ±êÇ©(tag)ÁË"
+
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: ÕÒ²»µ½±êÇ©(tag): %s"
+
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr " # pri kind tag"
+
+#: tag.c:548
+msgid "file\n"
+msgstr "Îļþ\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "ÊäÈë nr »òÑ¡Ôñ (<CR> Í˳ö): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: Ö»ÓдËÏî·ûºÏ"
+
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: ¼º¾­ÔÚ×îºóÒ»¸ö·ûºÏµÄ±êÇ©(tag)ÁË"
+
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Îļþ \"%s\" ²»´æÔÚ"
+
+#. Give an indication of the number of matching tags
+#: tag.c:780
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "ÕÒµ½ tag: %d/%d%s"
+
+#: tag.c:783
+msgid " or more"
+msgstr " »ò¸ü¶à"
+
+#: tag.c:785
+msgid " Using tag with different case!"
+msgstr " ÒÔ²»Í¬´óСдÀ´Ê¹Óà tag!"
+
+#: tag.c:828
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Îļþ \"%s\" ²»´æÔÚ"
+
+#. Highlight title
+#: tag.c:897
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # µ½ tag ´Ó ÐÐ ÔÚ Îļþ/Îı¾"
+
+#: tag.c:1144
+msgid "Linear tag search"
+msgstr "ÏßÐÔ²éÕÒ±êÇ© (Tags)"
+
+#: tag.c:1146
+msgid "Binary tag search"
+msgstr "¶þ½øÖƲéÕÒ(Binary search) ±êÇ©(Tags)"
+
+#: tag.c:1172
+#, c-format
+msgid "Searching tags file %s"
+msgstr "²éÕÒ tag Îļþ \"%s\""
+
+#: tag.c:1356
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Tag Îļþ·¾¶±»½Ø¶ÏΪ %s\n"
+
+#: tag.c:1847
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Tag Îļþ \"%s\" ¸ñʽ´íÎó"
+
+#: tag.c:1851
+#, c-format
+msgid "Before byte %ld"
+msgstr "ÔÚ %ld ×Ö½Ú֮ǰ"
+
+#: tag.c:1872
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Tag ÎļþδÅÅÐò: %s"
+
+#. never opened any tags file
+#: tag.c:1911
+msgid "E433: No tags file"
+msgstr "E433: ûÓÐ tag Îļþ"
+
+#: tag.c:2583
+msgid "E434: Can't find tag pattern"
+msgstr "E434: ÕÒ²»µ½ tag"
+
+#: tag.c:2594
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: ÕÒ²»µ½ tag, ÊÔ×ŲÂ!"
+
+#: term.c:1723
+msgid "' not known. Available builtin terminals are:"
+msgstr "' ²»ÄܼÓÔØ¡£¿ÉÓõÄÄÚ½¨ÖÕ¶ËÐÎʽÓÐ:"
+
+#: term.c:1747
+msgid "defaulting to '"
+msgstr "Ô¤Éè: '"
+
+#: term.c:2100
+msgid "Cannot open termcap file"
+msgstr "²»ÄÜ´ò¿ª termcap Îļþ"
+
+#: term.c:2103
+msgid "Terminal entry not found in terminfo"
+msgstr "ÔÚterminfoÖÐδÕÒµ½ÖÕ¶ËÏî"
+
+#: term.c:2105
+msgid "Terminal entry not found in termcap"
+msgstr "ÔÚtermcapÖÐδÕÒµ½ÖÕ¶ËÏî"
+
+#: term.c:2264
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: termcap ûÓÐ \"%s\" Ïî"
+
+#: term.c:2738
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: ÖÕ¶ËÐèÒª \"cm\" µÄÄÜÁ¦"
+
+#. Highlight title
+#: term.c:4872
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Öն˰´¼ü ---"
+
+#: ui.c:240
+msgid "new shell started\n"
+msgstr "Æô¶¯Ð shell\n"
+
+#: ui.c:1705
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: ¶Á´íÎó£¬Í˳öÖÐ...\n"
+
+#. must display the prompt
+#: undo.c:351
+msgid "No undo possible; continue anyway"
+msgstr "²»ÄÜ»¹Ô­£»Çë¼ÌÐø"
+
+#: undo.c:506
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: ÐкŴíÎó"
+
+#: undo.c:675
+msgid "1 change"
+msgstr "Ò»Ïî¸Ä±ä"
+
+#: undo.c:677
+#, c-format
+msgid "%ld changes"
+msgstr "%ld Ïî¸Ä±ä"
+
+#: undo.c:721
+msgid "E439: undo list corrupt"
+msgstr "E439: ³·ÏúÁбíËð»µ"
+
+#: undo.c:751
+msgid "E440: undo line missing"
+msgstr "E440: ÕÒ²»µ½Òª³·Ïú²Ù×÷µÄÐÐ"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:655
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 16/32λ ͼÐͽçÃæ°æ±¾"
+
+#: version.c:657
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 32 Bit ͼÐͽçÃæ°æ±¾"
+
+#: version.c:660
+msgid " in Win32s mode"
+msgstr "Win32s ģʽ"
+
+#: version.c:662
+msgid " with OLE support"
+msgstr "Ö§³Ö OLE"
+
+#: version.c:665
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"MS-Windows 32λ ×Ö·û½çÃæ°æ±¾"
+
+#: version.c:669
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"MS-Windows 32λ ×Ö·û½çÃæ°æ±¾"
+
+#: version.c:673
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 λ MS-DOS °æ±¾"
+
+#: version.c:675
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 λ MS-DOS °æ±¾"
+
+#: version.c:681
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) °æ±¾"
+
+#: version.c:683
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X °æ±¾"
+
+#: version.c:686
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS °æ±¾"
+
+#: version.c:691
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS °æ±¾"
+
+#: version.c:701
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"¼ÓÈë²¹¶¡: "
+
+#: version.c:728
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"±àÒë"
+
+#: version.c:731
+msgid "by "
+msgstr "Õß:"
+
+#: version.c:743
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"³¬Ç¿°æ±¾ "
+
+#: version.c:746
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"´óÐÍ°æ±¾ "
+
+#: version.c:749
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Ò»°ã°æ±¾ "
+
+#: version.c:752
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"¼òÒ×°æ±¾ "
+
+#: version.c:754
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"¾«¼ò°æ±¾ "
+
+#: version.c:760
+msgid "without GUI."
+msgstr "²»Ê¹ÓÃͼÐͽçÃæ¡£"
+
+#: version.c:764
+msgid "with GTK-GNOME GUI."
+msgstr "ʹÓà GTK-GNOME ͼÐͽçÃæ¡£"
+
+#: version.c:766
+msgid "with GTK GUI."
+msgstr "ʹÓà GTK ͼÐͽçÃæ¡£"
+
+#: version.c:770
+msgid "with X11-Motif GUI."
+msgstr "ʹÓà X11-Motif ͼÐͽçÃæ¡£"
+
+#: version.c:773
+msgid "with X11-Athena GUI."
+msgstr "ʹÓà X11-Athena ͼÐͽçÃæ¡£"
+
+#: version.c:776
+msgid "with BeOS GUI."
+msgstr "ʹÓà BeOS ͼÐͽçÃæ¡£"
+
+#: version.c:779
+msgid "with Photon GUI."
+msgstr "ʹÓÃPhotonͼÐͽçÃæ¡£"
+
+#: version.c:782
+msgid "with GUI."
+msgstr "ʹÓÃͼÐͽçÃæ¡£"
+
+#: version.c:785
+msgid "with Carbon GUI."
+msgstr "ʹÓà Carbon ͼÐͽçÃæ¡£"
+
+#: version.c:788
+msgid "with Cocoa GUI."
+msgstr "ʹÓà Cocoa ͼÐͽçÃæ¡£"
+
+#: version.c:791
+msgid "with (classic) GUI."
+msgstr "ʹÓà (´«Í³) ͼÐͽçÃæ¡£"
+
+#: version.c:802
+msgid " Features included (+) or not (-):\n"
+msgstr " Ä¿Ç°¿ÉʹÓÃ(+)Óë²»¿ÉʹÓÃ(-)µÄÄ£¿éÁбí:\n"
+
+#: version.c:814
+msgid " system vimrc file: \""
+msgstr " ϵͳ vimrc ÅäÖÃÎļþ: \""
+
+#: version.c:819
+msgid " user vimrc file: \""
+msgstr " Óû§µÄ vimrc ÅäÖÃÎļþ: \""
+
+#: version.c:824
+msgid " 2nd user vimrc file: \""
+msgstr " µÚ¶þ×éÓû§ vimrc Îļþ: \""
+
+#: version.c:829
+msgid " 3rd user vimrc file: \""
+msgstr " µÚÈý×éÓû§ vimrc Îļþ: \""
+
+#: version.c:834
+msgid " user exrc file: \""
+msgstr " Óû§µÄ exrc ÅäÖÃÎļþ: \""
+
+#: version.c:839
+msgid " 2nd user exrc file: \""
+msgstr " µÚ¶þ×éÓû§ exrc Îļþ: \""
+
+#: version.c:845
+msgid " system gvimrc file: \""
+msgstr " ϵͳ gvimrc Îļþ: \""
+
+#: version.c:849
+msgid " user gvimrc file: \""
+msgstr " Óû§µÄ gvimrc ÅäÖÃÎļþ: \""
+
+#: version.c:853
+msgid "2nd user gvimrc file: \""
+msgstr " µÚ¶þ×éÓû§ gvimrc Îļþ: \""
+
+#: version.c:858
+msgid "3rd user gvimrc file: \""
+msgstr " µÚÈý×éÓû§ gvimrc Îļþ: \""
+
+#: version.c:865
+msgid " system menu file: \""
+msgstr " ϵͳ²Ëµ¥ÅäÖÃÎļþ: \""
+
+#: version.c:873
+msgid " fall-back for $VIM: \""
+msgstr " $VIM Ô¤ÉèÖµ: \""
+
+#: version.c:879
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " $VIMRUNTIME Ô¤ÉèÖµ: \""
+
+#: version.c:883
+msgid "Compilation: "
+msgstr "±àÒ뷽ʽ: "
+
+#: version.c:889
+msgid "Compiler: "
+msgstr "±àÒëÆ÷: "
+
+#: version.c:894
+msgid "Linking: "
+msgstr "Á´½á·½Ê½: "
+
+#: version.c:899
+msgid " DEBUG BUILD"
+msgstr " µ÷ÊÔ°æ±¾"
+
+#: version.c:934
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved"
+
+#: version.c:936
+msgid "version "
+msgstr "°æ±¾ "
+
+#: version.c:937
+msgid "by Bram Moolenaar et al."
+msgstr "ά»¤ÈË: Bram Moolenaar et al."
+
+#: version.c:938
+msgid "Vim is open source and freely distributable"
+msgstr "Vim Ϊ¿É×ÔÓÉ·¢ÐеĿª·ÅÔ´´úÂëÈí¼þ"
+
+#: version.c:940
+msgid "Help poor children in Uganda!"
+msgstr "°ïÖúÎڸɴïµÄ¿ÉÁ¯¶ùͯ!"
+
+#: version.c:941
+msgid "type :help iccf<Enter> for information "
+msgstr "½øÒ»²½ËµÃ÷ÇëÊäÈë :help iccf<Enter>"
+
+#: version.c:943
+msgid "type :q<Enter> to exit "
+msgstr "ÒªÍ˳öÇëÊäÈë :q<Enter> "
+
+#: version.c:944
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "ÔÚÏß°ïÖúÇëÊäÈë :help<Enter> "
+
+#: version.c:945
+msgid "type :help version6<Enter> for version info"
+msgstr "а汾ÐÅÏ¢ÇëÊäÈë :help version6<Enter>"
+
+#: version.c:948
+msgid "Running in Vi compatible mode"
+msgstr "Vi ¼æÈÝģʽ"
+
+#: version.c:949
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "Èç¹ûÒªÍêÈ«Ä£Ä⴫ͳ Vi ÇëÊäÈë :set nocp<Enter>"
+
+#: version.c:950
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "Èç¹ûÐèÒª¶Ô Vi ¼æÈÝģʽ½øÒ»²½ËµÃ÷ÇëÊäÈë :help cp-default<Enter>"
+
+#: version.c:990
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "×¢Òâ: ¼ì²âµ½ Windows 95/98/ME"
+
+#: version.c:993
+msgid "type :help windows95<Enter> for info on this"
+msgstr "Èç¹ûÐèÒª¶Ô Windows 95 Ö§³ÖµÄ¸ü¶àÐÅÏ¢ÇëÊäÈë :help windows95<Enter>"
+
+#: window.c:201
+msgid "E441: There is no preview window"
+msgstr "E441: ûÓÐÔ¤ÀÀ´°¿Ú"
+
+#: window.c:568
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: ²»ÄÜͬʱ·Ö¸î´°¿ÚΪ×óÉϺÍÓÒϽÇ"
+
+#: window.c:1327
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: ÓÐÆäËü·Ö¸î´°¿Úʱ²»ÄÜÐýת"
+
+#: window.c:1810
+msgid "E444: Cannot close last window"
+msgstr "E444: ²»ÄܹرÕ×îºóÒ»¸ö´°¿Ú"
+
+#: window.c:2474
+msgid "Already only one window"
+msgstr "ÒѾ­Ö»Ê£Ò»¸ö´°¿ÚÁË"
+
+#: window.c:2521
+msgid "E445: Other window contains changes"
+msgstr "E445: ÆäËü´°¿ÚÓиıäµÄÄÚÈÝ"
+
+#: window.c:4341
+msgid "E446: No file name under cursor"
+msgstr "E446: ¹â±ê´¦Ã»ÓÐÎļþÃû"
+
+#: window.c:4460
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: ÔÚ·¾¶ÖÐÕÒ²»µ½Îļþ \"%s\""
+
+#: ../GvimExt/gvimext.cpp:586
+msgid "Edit with &multiple Vims"
+msgstr "Óà &multiple Vims ±à¼­"
+
+#: ../GvimExt/gvimext.cpp:592
+msgid "Edit with single &Vim"
+msgstr "Óà single &Vim ±à¼­"
+
+#: ../GvimExt/gvimext.cpp:604
+msgid "Edit with &Vim"
+msgstr "Óà &Vim ±à¼­"
+
+#. Now concatenate
+#: ../GvimExt/gvimext.cpp:628
+msgid "Edit with existing Vim - &"
+msgstr "Óõ±Ç°µÄ Vim ±à¼­ - &"
+
+#: ../GvimExt/gvimext.cpp:752
+msgid "Edits the selected file(s) with Vim"
+msgstr "Óà Vim ±à¼­Ñ¡ÔñµÄÎļþ"
+
+#: ../GvimExt/gvimext.cpp:891 ../GvimExt/gvimext.cpp:969
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "´´½¨½ø³Ìʧ°Ü: Çë¼ì²égvimÊÇ·ñÔÚ¿ÉÖ´Ðз¾¶ÖÐ!"
+
+#: ../GvimExt/gvimext.cpp:892 ../GvimExt/gvimext.cpp:906
+#: ../GvimExt/gvimext.cpp:970
+msgid "gvimext.dll error"
+msgstr "gvimext.dll ³ö´í"
+
+#: ../GvimExt/gvimext.cpp:905
+msgid "Path length too long!"
+msgstr "·¾¶ÃûÌ«³¤"
+
+#: globals.h:878
+msgid "--No lines in buffer--"
+msgstr "--»º³åÇøÎÞ×ÊÁÏ--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1019
+msgid "Command aborted"
+msgstr "ÃüÁǿÖÆÖжÏ"
+
+#: globals.h:1020
+msgid "Argument required"
+msgstr "ÐèÒªÖ¸Áî²ÎÊý"
+
+#: globals.h:1021
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ ºóÃæÓ¦¸ÃÓÐ / ? »ò &"
+
+#: globals.h:1023
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: ²»ÄÜÔÚÃüÁîÐд°¿ÚÖÐʹÓá£<CR>Ö´ÐУ¬CTRL-C Í˳ö"
+
+#: globals.h:1025
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr "E12: exrc/vimrc ÀïµÄÖ¸Áî²»ÄÜÖ´ÐÐ"
+
+#: globals.h:1026
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: ÎļþÒѾ­´æÔÚ (¿ÉÓà ! Ç¿ÖÆÌæ»»)"
+
+#: globals.h:1027
+msgid "Command failed"
+msgstr "ÃüÁîÖ´ÐÐʧ°Ü"
+
+#: globals.h:1028
+msgid "Internal error"
+msgstr "ÄÚ²¿´íÎó"
+
+#: globals.h:1029
+msgid "Interrupted"
+msgstr "ÒÑÖжÏ"
+
+#: globals.h:1030
+msgid "E14: Invalid address"
+msgstr "E14: ²»ÕýÈ·µÄµØÖ·"
+
+#: globals.h:1031
+msgid "Invalid argument"
+msgstr "²»ÕýÈ·µÄ²ÎÊý"
+
+#: globals.h:1032
+#, c-format
+msgid "Invalid argument: %s"
+msgstr "²»ÕýÈ·µÄ²ÎÊý: %s"
+
+#: globals.h:1034
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: ²»ÕýÈ·µÄ±í´ïʽ: %s"
+
+#: globals.h:1036
+msgid "E16: Invalid range"
+msgstr "E16: ²»ÕýÈ·µÄ·¶Î§"
+
+#: globals.h:1037
+msgid "Invalid command"
+msgstr "²»ÕýÈ·µÄÃüÁî"
+
+#: globals.h:1039
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" ÊÇĿ¼"
+
+#: globals.h:1042
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: '=' Ç°Ãæ³öÏÖÁË´íÎóµÄ×Ö·û"
+
+#: globals.h:1044
+msgid "E19: Mark has invalid line number"
+msgstr "E19: ±ê¼ÇµÄÐкŴíÎó"
+
+#: globals.h:1045
+msgid "E20: Mark not set"
+msgstr "E20: ûÓÐÉ趨±ê¼Ç"
+
+#: globals.h:1046
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: ÒòΪ 'modifiable' Ñ¡ÏîÊǹرյģ¬ËùÒÔ²»ÄÜÐÞ¸Ä"
+
+#: globals.h:1047
+msgid "E22: Scripts nested too deep"
+msgstr "E22: µÝ¹éµ÷ÓÃÌ«¶à²ã"
+
+#: globals.h:1048
+msgid "E23: No alternate file"
+msgstr "E23: ûÓÐÌæ´úµÄÎļþ"
+
+#: globals.h:1049
+msgid "E24: No such abbreviation"
+msgstr "E24: ûÓÐÕâ¸ö abbreviation ¶ÔÓ¦"
+
+#: globals.h:1050
+msgid "No ! allowed"
+msgstr "²»¿ÉʹÓà '!'"
+
+#: globals.h:1052
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: ÒòΪ±àÒëʱûÓмÓÈëͼÐͽçÃæµÄ³ÌÐò´úÂ룬ËùÒÔ²»ÄÜʹÓÃͼÐͽçÃæ"
+
+#: globals.h:1055
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: ÒòΪ±àÒëʱûÓмÓÈëÏ£²®À³µÄ³ÌÐò´úÂ룬ËùÒÔ²»ÄÜʹÓà Hebrew\n"
+
+#: globals.h:1058
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: ÒòΪ±àÒëʱûÓмÓÈë Farsi µÄ³ÌÐò´úÂ룬ËùÒÔ²»ÄÜʹÓà Farsi\n"
+
+#: globals.h:1061
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: ûÓÐÃûΪ '%s' µÄ highlight group"
+
+#: globals.h:1063
+msgid "E29: No inserted text yet"
+msgstr "E29: ûÓвåÈë¹ýÎÄ×Ö"
+
+#: globals.h:1064
+msgid "E30: No previous command line"
+msgstr "E30: ûÓÐÇ°Ò»ÏîÃüÁî"
+
+#: globals.h:1065
+msgid "E31: No such mapping"
+msgstr "E31: ûÓÐÕâ¸ö mapping ¶ÔÓ¦"
+
+#: globals.h:1066
+msgid "No match"
+msgstr "ÕÒ²»µ½"
+
+#: globals.h:1067
+#, c-format
+msgid "No match: %s"
+msgstr "ÕÒ²»µ½: %s"
+
+#: globals.h:1068
+msgid "E32: No file name"
+msgstr "E32: ûÓÐÎļþÃû"
+
+#: globals.h:1069
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: ûÓÐÇ°Ò»¸ö²éÕÒ/Ìæ»»µÄÃüÁî"
+
+#: globals.h:1070
+msgid "E34: No previous command"
+msgstr "E34: ûÓÐÇ°Ò»¸öÃüÁî"
+
+#: globals.h:1071
+msgid "E35: No previous regular expression"
+msgstr "E35: ûÓÐÇ°Ò»¸ö²éÕÒÃüÁî"
+
+#: globals.h:1072
+msgid "No range allowed"
+msgstr "²»¿ÉʹÓ÷¶Î§ÃüÁî"
+
+#: globals.h:1074
+msgid "E36: Not enough room"
+msgstr "E36: ûÓÐ×ã¹»µÄ¿Õ¼ä"
+
+#: globals.h:1076
+#, c-format
+msgid "Can't create file %s"
+msgstr "²»ÄÜ´´½¨Îļþ %s"
+
+#: globals.h:1077
+msgid "Can't get temp file name"
+msgstr "²»Äܵõ½ÁÙʱÎļþÃû"
+
+#: globals.h:1078
+#, c-format
+msgid "Can't open file %s"
+msgstr "²»ÄÜ´ò¿ªÎļþ %s"
+
+#: globals.h:1079
+#, c-format
+msgid "Can't read file %s"
+msgstr "²»ÄܶÁÈ¡Îļþ %s"
+
+#: globals.h:1080
+msgid "E37: No write since last change (use ! to override)"
+msgstr "E37: ÎļþÄÚÈÝÒѸı䵫ÉÐδ±£´æ (¿ÉÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: globals.h:1081
+msgid "E38: Null argument"
+msgstr "E38: ¿ÕµÄ (Null) ²ÎÊý"
+
+#: globals.h:1083
+msgid "E39: Number expected"
+msgstr "E39: Ó¦¸ÃÒªÓÐÊý×Ö"
+
+#: globals.h:1086
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: ²»ÄÜ´ò¿ª´íÎóÎļþ %s"
+
+#: globals.h:1089
+msgid "E41: Out of memory!"
+msgstr "E41: ÄÚ´æ²»×ã!"
+
+#: globals.h:1092
+msgid "Pattern not found"
+msgstr "ÕÒ²»µ½Ä£Ê½"
+
+#: globals.h:1094
+#, c-format
+msgid "Pattern not found: %s"
+msgstr "ÕÒ²»µ½Ä£Ê½ %s"
+
+#: globals.h:1095
+msgid "Argument must be positive"
+msgstr "²ÎÊýÓ¦¸ÃÊÇÕýÊý"
+
+#: globals.h:1097
+msgid "E42: No Errors"
+msgstr "E42: ûÓдíÎó"
+
+#: globals.h:1099
+msgid "E43: Damaged match string"
+msgstr "E43: Æ¥Åä×Ö·û´®ÓÐÎÊÌâ"
+
+#: globals.h:1100
+msgid "E44: Corrupted regexp program"
+msgstr "E44: ÕýÔò±í´ïʽÓÐÎÊÌâ"
+
+#: globals.h:1101
+msgid "E45: 'readonly' option is set (use ! to override)"
+msgstr "E45: É趨 'readonly' Ñ¡Ïî(Ö»¶Á) (¿ÉÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: globals.h:1103
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: ²»ÄÜÉ趨ֻ¶Á±äÁ¿ \"%s\""
+
+#: globals.h:1106
+msgid "E47: Error while reading errorfile"
+msgstr "E47: ¶ÁÈ¡´íÎóÎļþʧ°Ü"
+
+#: globals.h:1109
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: ²»ÄÜÔÚ sandbox Àï³öÏÖ"
+
+#: globals.h:1111
+msgid "E49: Invalid scroll size"
+msgstr "E49: ´íÎóµÄ¹ö¶¯´óС"
+
+#: globals.h:1112
+msgid "E91: 'shell' option is empty"
+msgstr "E91: 'E71: Ñ¡Ïî 'shell' δÉ趨"
+
+#: globals.h:1113
+msgid "E72: Close error on swap file"
+msgstr "E72: ½»»»Îļþ¹Ø±Õ´íÎó"
+
+#: globals.h:1114
+msgid "E73: tag stack empty"
+msgstr "E73: ±êÇ©¶ÑÕ»ÒÑ¿Õ"
+
+#: globals.h:1115
+msgid "E74: Command too complex"
+msgstr "E74: ÃüÁîÌ«¸´ÔÓ"
+
+#: globals.h:1116
+msgid "E75: Name too long"
+msgstr "E75: Ãû×ÖÌ«³¤"
+
+#: globals.h:1117
+msgid "E76: Too many ["
+msgstr "E76: Ì«¶à ["
+
+#: globals.h:1118
+msgid "E77: Too many file names"
+msgstr "E77: Ì«¶àÎļþÃû"
+
+#: globals.h:1119
+msgid "Trailing characters"
+msgstr "ÄãÊäÈëÁ˶àÓàµÄ×Ö·û"
+
+#: globals.h:1120
+msgid "E78: Unknown mark"
+msgstr "E78: ²»ÄÜ°ìʶµÄ±ê¼Ç"
+
+#: globals.h:1121
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: ²»ÄÜÀ©Õ¹Í¨Åä·û"
+
+#: globals.h:1122
+msgid "E80: Error while writing"
+msgstr "E80: дÈë´íÎó"
+
+#: globals.h:1123
+msgid "Zero count"
+msgstr "Êýµ½Áã (?)"
+
+#: globals.h:1125
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: <SID> ²»ÄÜÔÚ script ±¾ÎÄÍâʹÓÃ."
diff --git a/src/po/zh_CN.po b/src/po/zh_CN.po
new file mode 100644
index 000000000..28fb5ad05
--- /dev/null
+++ b/src/po/zh_CN.po
@@ -0,0 +1,5937 @@
+# Chinese (simplified) Translation for Vim
+#
+# Do ":help uganda" in Vim to read copying and usage conditions.
+# Do ":help credits" in Vim to see a list of people who contributed.
+#
+# FIRST AUTHOR Wang Jun <junw@turbolinux.com.cn>
+#
+# Original translations.
+#
+#, no-wrap
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim(Simplified Chinese)\n"
+"POT-Creation-Date: 2001-09-24 10:10+0800\n"
+"PO-Revision-Date: 2001-09-24 11:13+0800\n"
+"Last-Translator: Wang Jun <junw@turbolinux.com.cn>\n"
+"Language-Team: Wang Jun <junw@turbolinux.com.cn>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=gb2312\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: ²»ÄÜ·ÖÅäÈκλº³åÇø£¬Í˳ö³ÌÐò..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: ²»ÄÜ·ÖÅ仺³åÇø£¬Ê¹ÓÃÁíÒ»¸ö»º³åÇø...."
+
+#: buffer.c:698
+msgid "No buffers were unloaded"
+msgstr "ûÓÐÊÍ·ÅÈκλº³åÇø"
+
+#: buffer.c:700
+msgid "No buffers were deleted"
+msgstr "ûÓÐɾ³ýÈκλº³åÇø"
+
+#: buffer.c:702
+msgid "No buffers were wiped out"
+msgstr "ûÓÐɾ³ýÈκλº³åÇø"
+
+#: buffer.c:710
+msgid "1 buffer unloaded"
+msgstr "ÒÑÊÍ·ÅÒ»¸ö»º³åÇø"
+
+#: buffer.c:712
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "ÒÑÊÍ·Å %d ¸ö»º³åÇø"
+
+#: buffer.c:717
+msgid "1 buffer deleted"
+msgstr "ÒÑɾ³ýÒ»¸ö»º³åÇø"
+
+#: buffer.c:719
+#, c-format
+msgid "%d buffers deleted"
+msgstr "ÒÑɾ³ý %d ¸ö»º³åÇø"
+
+#: buffer.c:724
+msgid "1 buffer wiped out"
+msgstr "ÒÑɾ³ýÒ»¸ö»º³åÇø"
+
+#: buffer.c:726
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "ÒÑɾ³ý %d ¸ö»º³åÇø"
+
+#: buffer.c:783
+msgid "E84: No modified buffer found"
+msgstr "E84: ûÓÐÐ޸ĹýµÄ»º³åÇø"
+
+#. back where we started, didn't find anything.
+#: buffer.c:822
+msgid "E85: There is no listed buffer"
+msgstr "E85: ûÓпÉÁгöµÄ»º³åÇø"
+
+#: buffer.c:834
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: ²»ÄÜÇл»µ½µÚ %ld ¸ö»º³åÇø"
+
+#: buffer.c:837
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: ²»ÄÜÇл»µ½¸üºóÃæµÄ»º³åÇø"
+
+#: buffer.c:839
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: ²»ÄÜÇл»µ½¸üÇ°ÃæµÄ»º³åÇø"
+
+#: buffer.c:863
+#, c-format
+msgid "E89: No write since last change for buffer %ld (use ! to override)"
+msgstr "E89: ÒѸü¸Ä¹ý»º³åÇø %ld µ«ÉÐδ±£´æ (¿ÉÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: buffer.c:879
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: ²»ÄÜÊÍ·Å×îºóÒ»¸ö»º³åÇø"
+
+#: buffer.c:1314
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: ¾¯¸æ: ÎļþÃû¹ý¶à"
+
+#: buffer.c:1480
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: ÕÒ²»µ½µÚ %ld ¸ö»º³åÇø"
+
+#: buffer.c:1700
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: ÕÒµ½Ò»¸öÒÔÉ쵀 %s"
+
+#: buffer.c:1702
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: ÕÒ²»µ½ %s"
+
+#: buffer.c:2105 ex_docmd.c:6065
+#, c-format
+msgid "line %ld"
+msgstr "ÐÐ %ld"
+
+#: buffer.c:2188
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: ÒÑÓлº³åÇøʹÓÃÕâ¸öÃû×Ö"
+
+#: buffer.c:2481
+msgid " [Modified]"
+msgstr " [ÒÑÐÞ¸Ä]"
+
+#: buffer.c:2486
+msgid "[Not edited]"
+msgstr "[δ±à¼­]"
+
+#: buffer.c:2491
+msgid "[New file]"
+msgstr "[ÐÂÎļþ]"
+
+#: buffer.c:2492
+msgid "[Read errors]"
+msgstr "[¶Á´íÎó]"
+
+#: buffer.c:2494 fileio.c:1754
+msgid "[readonly]"
+msgstr "[Ö»¶Á]"
+
+#: buffer.c:2510
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "ÐÐÊý 1 --%d%%--"
+
+#: buffer.c:2510
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "ÐÐÊý %ld --%d%%--"
+
+#: buffer.c:2518
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "ÐÐ %ld/%ld --%d%%-- ÁÐ "
+
+#: buffer.c:2606
+msgid "[No file]"
+msgstr "[δÃüÃû]"
+
+#. must be a help buffer
+#: buffer.c:2646
+msgid "help"
+msgstr "[°ïÖú]"
+
+#: buffer.c:3151 screen.c:4657
+msgid "[help]"
+msgstr "[°ïÖú]"
+
+#: buffer.c:3183 screen.c:4663
+msgid "[Preview]"
+msgstr "[Ô¤ÀÀ]"
+
+#: buffer.c:3389
+msgid "All"
+msgstr "È«²¿"
+
+#: buffer.c:3389
+msgid "Bot"
+msgstr "µ×¶Ë"
+
+#: buffer.c:3391
+msgid "Top"
+msgstr "¶¥¶Ë"
+
+#: buffer.c:4127
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# »º³åÇøÁбí:\n"
+
+#: buffer.c:4160
+msgid "[Error List]"
+msgstr "[´íÎóÁбí]"
+
+#: buffer.c:4173 memline.c:1513
+msgid "[No File]"
+msgstr "[δÃüÃû]"
+
+#: buffer.c:4393
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- ·ûºÅ ---"
+
+#: buffer.c:4403
+#, c-format
+msgid "Signs for %s:"
+msgstr "%s µÄ·ûºÅ:"
+
+#: buffer.c:4409
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " ÐÐ=%ld id=%d Ãû³Æ=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: ²»ÄܱȽÏ(diff) %ld¸öÒÔÉϵĻº³åÇø"
+
+#: diff.c:648
+msgid "E97: Cannot create diffs"
+msgstr "E97: ²»ÄÜ´´½¨ diff "
+
+#: diff.c:747
+msgid "Patch file"
+msgstr "Patch Îļþ"
+
+#: diff.c:991
+msgid "E98: Cannot read diff output"
+msgstr "E98: ²»ÄܶÁÈ¡ diff µÄÊä³ö"
+
+#: diff.c:1704
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: Ä¿Ç°µÄ»º³åÇø²»ÊÇÔÚ diff ģʽ"
+
+#: diff.c:1716
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: ûÓлº³åÇøÔÚ diff ģʽ"
+
+#: diff.c:1724
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: ÓÐÁ½¸öÒÔÉϵĻº³åÇøÔÚ diff ģʽ£¬²»Äܾö¶¨ÒªÓÃÄÄÒ»¸ö"
+
+#: diff.c:1747
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: ÕÒ²»µ½»º³åÇø: \"%s\""
+
+#: diff.c:1753
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: »º³åÇø \"%s\" ²»ÊÇÔÚ diff ģʽ"
+
+#: digraph.c:2168
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: ¸´ºÏ×Ö·û(digraph)Öв»ÄÜʹÓà Escape"
+
+#: digraph.c:2340
+msgid "Keymap file not found"
+msgstr "ÕÒ²»µ½ keymap Îļþ"
+
+#: digraph.c:2367
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: ʹÓà :loadkeymap "
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " ¹Ø¼ü×Ö×Ô¶¯Íê³É (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " ^X ģʽ (^E/^Y/^L/^]/^F/^I/^K/^D/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " ÇøÓò¹Ø¼ü×Ö×Ô¶¯Íê³É (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " ÕûÐÐ×Ô¶¯Íê³É (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " ÎļþÃû×Ô¶¯Íê³É (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " ±êÇ©×Ô¶¯Íê³É (^]/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " ·¾¶×Ô¶¯Íê³É (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " ¶¨Òå×Ô¶¯Íê³É (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " ×Öµä×Ô¶¯Íê³É (^K/^N/^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Thesaurus ×Ô¶¯Íê³É (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " ÃüÁî×Ô¶¯Íê³É (^V/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "Òѵ½¶ÎÂä½áβ"
+
+#: edit.c:894
+msgid "'thesaurus' option is empty"
+msgstr "Ñ¡Ïî 'thesaurus' δÉ趨"
+
+#: edit.c:1070
+msgid "'dictionary' option is empty"
+msgstr "Ñ¡Ïî 'dictionary' Ϊ¿Õ"
+
+#: edit.c:1992
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "ɨÃè×Öµä: %s"
+
+#: edit.c:2183
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (²åÈë) Scroll (^E/^Y)"
+
+#: edit.c:2185
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (Ìæ»») Scroll (^E/^Y)"
+
+#: edit.c:2496
+#, c-format
+msgid "Scanning: %s"
+msgstr "ɨÃèÖÐ: %s"
+
+#: edit.c:2531
+msgid "Scanning tags."
+msgstr "ɨÃè±êÇ©."
+
+#: edit.c:3189
+msgid " Adding"
+msgstr " Ôö¼Ó"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3238
+msgid "-- Searching..."
+msgstr "-- ËÑÑ°ÖÐ..."
+
+#: edit.c:3294
+msgid "Back at original"
+msgstr "»Øµ½Æðµã"
+
+#: edit.c:3299
+msgid "Word from other line"
+msgstr "´ÓÆäËüÐпªÊ¼µÄ´Ê (?)"
+
+#: edit.c:3304
+msgid "The only match"
+msgstr "Ö»ÓдËÏîÆ¥Åä"
+
+#: edit.c:3363
+#, c-format
+msgid "match %d of %d"
+msgstr "ÕÒµ½ %d / %d"
+
+#: edit.c:3366
+#, c-format
+msgid "match %d"
+msgstr "Æ¥Åä %d"
+
+#: eval.c:696
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: 䶨ÒåµÄ±äÁ¿: \"%s\""
+
+#: eval.c:975
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: ȱÉÙ¶ÔÓ¦µÄÀ¨ºÅ: %s"
+
+#: eval.c:1043
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: Î޴˱äÁ¿: \"%s\""
+
+#: eval.c:1284
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: '?' ºóȱÉÙ ':'"
+
+#: eval.c:1898
+msgid "E110: Missing ')'"
+msgstr "E110: ȱÉÙ¶ÔÓ¦µÄ \")\""
+
+#: eval.c:1948
+msgid "E111: Missing ']'"
+msgstr "E111: ȱÉÙ¶ÔÓ¦µÄ \"]\""
+
+#: eval.c:2023
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: ȱÉÙÑ¡ÏîÃû³Æ: %s"
+
+#: eval.c:2041
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: ²»ÕýÈ·µÄÑ¡Ïî: %s"
+
+#: eval.c:2103
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: ȱÉÙÒýºÅ: %s"
+
+#: eval.c:2220
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: ȱÉÙÒýºÅ: %s"
+
+#: eval.c:2537
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: º¯Êý %s µÄ²ÎÊý²»ÕýÈ·"
+
+#: eval.c:2538
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: 䶨ÒåµÄº¯Êý: %s"
+
+#: eval.c:2539
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: º¯Êý %s µÄ²ÎÊý¹ý¶à"
+
+#: eval.c:2540
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: º¯Êý %s µÄ²ÎÊýÌ«ÉÙ"
+
+#: eval.c:2541
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: <SID> ²»ÄÜÔÚ script ÉÏÏÂÎÄÍâʹÓÃ: %s"
+
+#: eval.c:3574
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld ÐÐ: "
+
+#: eval.c:4689
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"È·¶¨(&O)\n"
+"È¡Ïû(&C)"
+
+#: eval.c:5511
+msgid "E240: No connection to Vim server"
+msgstr "E240: ûÓÐÓë Vim Server ´´½¨Á¬½Ó"
+
+#: eval.c:5601
+msgid "E277: Unable to read a server reply"
+msgstr "E277: ²»ÄܶÁÈ¡·þÎñÆ÷µÄÏìÓ¦"
+
+#: eval.c:5626
+msgid "E258: Unable to send to client"
+msgstr "E258: ²»ÄÜ´«Ë͵½¿Í»§¶Ë"
+
+#: eval.c:5667
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: ²»ÄÜ´«Ë͵½ %s"
+
+#: eval.c:5763
+msgid "(Invalid)"
+msgstr "(ÎÞЧ)"
+
+#: eval.c:6766
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: ±äÁ¿ %s ÉÐ䶨Òå"
+
+#: eval.c:7464
+#, c-format
+msgid "E122: Function %s already exists, use ! to replace"
+msgstr "E122: º¯Êý %s ÒѾ­´æÔÚ, ÇëʹÓà ! Ç¿ÖÆÌæ»»"
+
+#: eval.c:7506
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: º¯Êý %s ÉÐ䶨Òå"
+
+#: eval.c:7519
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: ȱÉÙ \"(\": %s"
+
+#: eval.c:7551
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: ²ÎÊý²»ÕýÈ·: %s"
+
+#: eval.c:7637
+msgid "E126: Missing :endfunction"
+msgstr "E126: ȱÉÙ :endfunction"
+
+#: eval.c:7716
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: º¯Êý %s ÕýÔÚʹÓÃÖУ¬²»ÄÜÖØж¨Òå"
+
+#: eval.c:7773
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: º¯ÊýÃû³ÆµÚÒ»¸ö×Öĸ±ØÐë´óд: %s"
+
+#: eval.c:7779
+msgid "E129: Function name required"
+msgstr "E129: ÐèÒªº¯ÊýÃû³Æ"
+
+#: eval.c:7872
+msgid "function "
+msgstr "º¯Êý "
+
+#: eval.c:7987
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: º¯Êý %s ÉÐ䶨Òå"
+
+#: eval.c:7992
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: º¯Êý %s ÕýÔÚʹÓÃÖУ¬²»ÄÜɾ³ý"
+
+#: eval.c:8039
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: º¯ÊýµÝ¹éµ÷ÓòãÊý³¬¹ý 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:8090
+#, c-format
+msgid "calling %s"
+msgstr "µ÷ÓÃ %s"
+
+#. always scroll up, don't overwrite
+#: eval.c:8115 ex_cmds2.c:1973
+#, c-format
+msgid "continuing in %s"
+msgstr "¼ÌÐø: %s"
+
+#: eval.c:8169
+msgid "E133: :return not inside a function"
+msgstr "E133: :return ±ØÐëÔÚº¯ÊýÀïʹÓÃ"
+
+#: eval.c:8247
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s ·µ»ØÖµ #%ld "
+
+#: eval.c:8250
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s ·µ»ØÖµ \"%s\""
+
+#: eval.c:8391
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# È«¾Ö±äÁ¿:\n"
+
+#: ex_cmds2.c:70
+msgid "Entering Debug mode. Type \"cont\" to leave."
+msgstr "½øÈëµ÷ÊÔģʽ. ÊäÈë \"cont\" ÒԻص½Õý³£Ä£Ê½."
+
+#: ex_cmds2.c:74 ex_docmd.c:771
+#, c-format
+msgid "line %ld: %s"
+msgstr "ÐÐ %ld: %s"
+
+#: ex_cmds2.c:76
+#, c-format
+msgid "cmd: %s"
+msgstr "cmd: %s"
+
+#: ex_cmds2.c:224
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "\"%s%s\" Öжϵã: µÚ %ld ÐÐ"
+
+#: ex_cmds2.c:388
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: ÕÒ²»µ½Öжϵã: %s"
+
+#: ex_cmds2.c:414
+msgid "No breakpoints defined"
+msgstr "ûÓж¨ÒåÖжϵã"
+
+#: ex_cmds2.c:419
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s µÚ %ld ÐÐ"
+
+#: ex_cmds.c:2053 ex_cmds.c:2289 ex_cmds2.c:602
+msgid "Save As"
+msgstr "Áí´æΪ"
+
+#: ex_cmds2.c:625
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "½«¸Ä±ä±£´æµ½ \"%.*s\"?"
+
+#: ex_cmds2.c:627 ex_docmd.c:8612
+msgid "Untitled"
+msgstr "δÃüÃû"
+
+#: ex_cmds2.c:763
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: ÒѸü¸Ä¹ý»º³åÇø \"%s\" µ«ÉÐδ±£´æ (¿ÉÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: ex_cmds2.c:832
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "×¢Òâ: ÒÑÇл»µ½ÆäËü»º³åÇø (Çë¼ì²é Autocommands ÓÐÎÞ´íÎó)"
+
+#: ex_cmds2.c:1208
+msgid "E163: There is only one file to edit"
+msgstr "E163: Ö»ÓÐÒ»¸öÎļþ¿É±à¼­"
+
+#: ex_cmds2.c:1210
+msgid "E164: Cannot go before first file"
+msgstr "E164: ÒѾ­ÔÚµÚÒ»¸öÎļþÁË"
+
+#: ex_cmds2.c:1212
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: ÒѾ­ÔÚ×îºóÒ»¸öÎļþÁË"
+
+#: ex_cmds2.c:1632
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "²éÕÒÖÐ: \"%s\" -- \"%s\""
+
+#: ex_cmds2.c:1654
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "²éÕÒÖÐ: \"%s\""
+
+#: ex_cmds2.c:1678
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "ÔÚ 'runtimepath' ÀïÕÒ²»µ½ \"%s\""
+
+#: ex_cmds2.c:1712
+msgid "Run Macro"
+msgstr "Ö´Ðкê"
+
+#: ex_cmds2.c:1817
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "²»ÄÜÖ´ÐÐĿ¼£º \"%s\""
+
+#: ex_cmds2.c:1847
+#, c-format
+msgid "could not source \"%s\""
+msgstr "²»ÄÜÖ´ÐÐ \"%s\""
+
+#: ex_cmds2.c:1849
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "µÚ %ld ÐÐ: ²»ÄÜÖ´ÐÐ \"%s\""
+
+#: ex_cmds2.c:1863
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "Ö´ÐÐ \"%s\" ÖÐ"
+
+#: ex_cmds2.c:1865
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "µÚ %ld ÐÐ: ½áÊøÖ´ÐÐ %s"
+
+#: ex_cmds2.c:1971
+#, c-format
+msgid "finished sourcing %s"
+msgstr "½áÊøÖ´ÐÐ %s"
+
+#: ex_cmds2.c:2272
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: ×¢Òâ: ´íÎóµÄÐзָô×Ö·û£¬¿ÉÄÜÊÇÉÙÁË ^M"
+
+#: ex_cmds2.c:2321
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: ÔÚÖ´ÐÐ script ÎļþÍâ²»¿ÉʹÓà :scriptencoding"
+
+#: ex_cmds2.c:2354
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: ÔÚÖ´ÐÐ script ÎļþÍâ²»¿ÉʹÓà :finish"
+
+#: ex_cmds2.c:2820
+msgid "No text to be printed"
+msgstr "ûÓÐÒª´òÓ¡µÄÎÄ×Ö"
+
+#: ex_cmds2.c:2898
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "´òÓ¡ÖÐ: µÚ %d Ò³ (%d%%)"
+
+#: ex_cmds2.c:2907
+#, c-format
+msgid " Copy %d of %d"
+msgstr "¸´ÖÆ %d / %d"
+
+#: ex_cmds2.c:2959
+#, c-format
+msgid "Printed: %s"
+msgstr "ÒÑ´òÓ¡: %s"
+
+#: ex_cmds2.c:2966
+msgid "Printing aborted"
+msgstr "´òÓ¡ÖжÏ"
+
+#: ex_cmds2.c:3344
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: дÈë PostScript Îļþ³ö´í"
+
+#: ex_cmds2.c:4019
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: ²»ÄÜ´ò¿ª PostScript Êä³öÎļþ"
+
+#: ex_cmds2.c:4057
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: ²»ÄÜ´ò¿ªÎļþ \"%s\""
+
+#: ex_cmds2.c:4068
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: ²»ÄܶÁ PostScript ×ÊÔ´Îļþ \"%s\""
+
+#: ex_cmds2.c:4266
+msgid "Sending to printer..."
+msgstr "·¢Ë͵½´òÓ¡»ú..."
+
+#: ex_cmds2.c:4270
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: ´òÓ¡ PostScript Îļþʧ°Ü"
+
+#: ex_cmds2.c:4272
+msgid "Print job sent."
+msgstr ""
+
+#: ex_cmds2.c:4646
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "Ä¿Ç°µÄ %sÓïÑÔ: \"%s\""
+
+#: ex_cmds2.c:4653
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: ²»ÄÜÉ趨ÓïÑÔΪ \"%s\""
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, Ê®Áù½øÖÆ %02x, °Ë½øÖÆ %03o"
+
+#: ex_cmds.c:428
+msgid "E134: Move lines into themselves"
+msgstr "E134: ²»ÄÜ°ÑÐÐÒƵ½Ëü×ÔÒÑÄÚ"
+
+#: ex_cmds.c:497
+msgid "1 line moved"
+msgstr "ÒÑÒƶ¯ 1 ÐÐ"
+
+#: ex_cmds.c:499
+#, c-format
+msgid "%ld lines moved"
+msgstr "ÒÑ°áÒÆ %ld ÐÐ"
+
+#: ex_cmds.c:890
+#, c-format
+msgid "%ld lines filtered"
+msgstr "ÒÑ´¦Àí %ld ÐÐ"
+
+#: ex_cmds.c:918
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *Filter* Autocommand ²»¿ÉÒÔ¸ü¸Ä»º³åÇøµÄÄÚÈÝ"
+
+#: ex_cmds.c:1003
+msgid "[No write since last change]\n"
+msgstr "[¸üкóÉÐδ±£´æ]\n"
+
+#: ex_cmds.c:1248
+#, c-format
+msgid "viminfo: %s in line: "
+msgstr "viminfo: %s ÔÚÐÐÖÐ: "
+
+#: ex_cmds.c:1253
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: ¹ý¶à´íÎó, ºöÂÔÎļþÆäÓಿ·Ö"
+
+#: ex_cmds.c:1282
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "¶ÁÈ¡ viminfo Îļþ \"%s\"%s%s%s"
+
+#: ex_cmds.c:1283
+msgid " info"
+msgstr " ÐÅÏ¢"
+
+#: ex_cmds.c:1284
+msgid " marks"
+msgstr " 񈬀"
+
+#: ex_cmds.c:1285
+msgid " FAILED"
+msgstr " ʧ°Ü"
+
+#: ex_cmds.c:1376
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Viminfo Îļþ²»ÄÜдÈë: %s"
+
+#: ex_cmds.c:1501
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: ²»ÄÜдÈë viminfo Îļþ %s !"
+
+#: ex_cmds.c:1509
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "дÈë viminfo Îļþ \"%s\" ÖÐ"
+
+#. Write the info:
+#: ex_cmds.c:1610
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# viminfo ÎļþÊÇÓÉ vim %s Ëù²úÉú.\n"
+
+#: ex_cmds.c:1612
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# Èç¹ûÏëÒª×ÔÐÐÐÞ¸ÄÇëÌرðСÐÄ£¡\n"
+"\n"
+
+#: ex_cmds.c:1614
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# 'encoding' ÔÚ´ËÎļþ½¨Á¢Ê±µÄÖµ\n"
+
+#: ex_cmds.c:1713
+msgid "Illegal starting char"
+msgstr "ÎÞЧµÄÆô¶¯×Ö·û"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2096
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: ÄúÔÚÁíÒ»¸ö»º³åÇøÒ²¼ÓÔØÁËÕâ¸öÎļþ"
+
+#: ex_cmds.c:2130
+msgid "Write partial file?"
+msgstr "ҪдÈ벿·ÖÎļþÂð£¿"
+
+#: ex_cmds.c:2137
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: ÇëʹÓà ! À´Ð´È벿·Ö»º³åÇø"
+
+#: ex_cmds.c:2223
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "Òª¸²¸ÇÒÑ´æÔÚµÄÎļþ \"%.*s\"£¿"
+
+#: ex_cmds.c:2294
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: »º³åÇø %ld ûÓÐÎļþÃû"
+
+#: ex_cmds.c:2332
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: ÎļþδдÈ룬ÒòΪ 'write' Ñ¡Ïî¹Ø±Õ"
+
+#: ex_cmds.c:2352
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"\"%.*s\" ÒÑÉ趨 'readonly' Ñ¡Ïî.\n"
+"È·¶¨Òª¸²¸ÇÂð£¿"
+
+#: ex_cmds.c:2517
+msgid "Edit File"
+msgstr "±à¼­Îļþ"
+
+#: ex_cmds.c:3024
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Autocommands ÒâÍâµØɾ³ýлº³åÇø %s"
+
+#: ex_cmds.c:3156
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: :z ²»½ÓÊÜ·ÇÊý×ֵIJÎÊý"
+
+#: ex_cmds.c:3241
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: rvim ÖнûֹʹÓà shell ÃüÁî"
+
+#: ex_cmds.c:3348
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: ÕýÔò±í´ïʽ²»ÄÜÓÃ×Öĸ·Ö¸ô (?)"
+
+#: ex_cmds.c:3686
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "Ì滻Ϊ %s (y/n/a/q/^E/^Y)?"
+
+#: ex_cmds.c:4050
+msgid "(Interrupted) "
+msgstr "(ÒÑÖжÏ) "
+
+#: ex_cmds.c:4054
+msgid "1 substitution"
+msgstr "Ìæ»»Ò»×é"
+
+#: ex_cmds.c:4056
+#, c-format
+msgid "%ld substitutions"
+msgstr "Ìæ»» %ld ×é"
+
+#: ex_cmds.c:4059
+msgid " on 1 line"
+msgstr " Ò»ÐÐÖÐ"
+
+#: ex_cmds.c:4061
+#, c-format
+msgid " on %ld lines"
+msgstr " %ld ÐÐÖÐ"
+
+#: ex_cmds.c:4112
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :global ²»ÄܵݹéÖ´ÐÐ"
+
+#: ex_cmds.c:4147
+msgid "E148: Regular expression missing from global"
+msgstr "E148: ûÓÐʹÓùýÕýÔò±í´ïʽ (?)"
+
+#: ex_cmds.c:4196
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "ÿһÐж¼ÕÒ²»µ½Ä£Ê½: %s"
+
+#: ex_cmds.c:4277
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# Ç°Ò»×éÌæ´ú×Ö·û´®:\n"
+"$"
+
+#: ex_cmds.c:4376
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: ±§Ç¸, ûÓÐ %s µÄ˵Ã÷"
+
+#: ex_cmds.c:4410
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "±§Ç¸, ÕÒ²»µ½°ïÖúÎļþ \"%s\""
+
+#: ex_cmds.c:4856
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s ²»ÊÇĿ¼"
+
+#: ex_cmds.c:4884
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: ²»ÄÜÒÔдÈëģʽ´ò¿ª \"%s\""
+
+#: ex_cmds.c:4898
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: ²»ÄܶÁÈ¡Îļþ: %s"
+
+#: ex_cmds.c:4977
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: ±êÇ©(tag) \"%s\" ÔÚÎļþ %s ÀïÖظ´³öÏÖ¶à´Î"
+
+#: ex_cmds.c:5078
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: 䶨ÒåµÄ sign command: %s"
+
+#: ex_cmds.c:5098
+msgid "E156: Missing sign name"
+msgstr "E156: ȱÉÙ sign Ãû³Æ"
+
+#: ex_cmds.c:5144
+msgid "E255: Too many signs defined"
+msgstr "E326: ÕÒµ½Ì«¶à signs"
+
+#: ex_cmds.c:5186
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: ²»ÕýÈ·µÄ sign ÎÄ×Ö: %s"
+
+#: ex_cmds.c:5210 ex_cmds.c:5396
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: ²»ÕýÈ·µÄ sign: %s"
+
+#: ex_cmds.c:5256
+msgid "E159: Missing sign number"
+msgstr "E159: ȱÉÙ sign number"
+
+#: ex_cmds.c:5336
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: »º³åÇøÃû³Æ´íÎó: %s"
+
+#: ex_cmds.c:5375
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Sign ID ´íÎó: %ld"
+
+#: ex_cmds.c:5546
+msgid "[Deleted]"
+msgstr "[ÒÑɾ³ý]"
+
+#: ex_docmd.c:491
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "½øÈë Ex ģʽ. ÊäÈë \"visua\" ÒԻص½Õý³£Ä£Ê½."
+
+#. must be at EOF
+#: ex_docmd.c:527
+msgid "At end-of-file"
+msgstr "Òѵ½Îļþ½áβ"
+
+#: ex_docmd.c:602
+msgid "E169: Command too recursive"
+msgstr "E169: ÃüÁîµÝ¹é²ãÊý¹ý¶à"
+
+#: ex_docmd.c:911
+msgid "E170: Missing :endwhile"
+msgstr "E170: ȱÉÙ :endwhile"
+
+#: ex_docmd.c:913
+msgid "E171: Missing :endif"
+msgstr "E171: ȱÉÙ :endif"
+
+#: ex_docmd.c:923
+msgid "End of sourced file"
+msgstr "ÃüÁîÎļþ½áÊø"
+
+#: ex_docmd.c:924
+msgid "End of function"
+msgstr "º¯Êý½áβ"
+
+#: ex_docmd.c:1344
+msgid "Ambiguous use of user-defined command"
+msgstr "Óû§¶¨ÒåµÄÃüÁî»á»ìÏý"
+
+#: ex_docmd.c:1358
+msgid "Not an editor command"
+msgstr "²»ÊDZ༭Æ÷µÄÃüÁî"
+
+#: ex_docmd.c:1441
+msgid "Don't panic!"
+msgstr "²»Òª¾ª»Å!"
+
+#: ex_docmd.c:1460
+msgid "Backwards range given"
+msgstr "Ö¸¶¨ÁËÏòÇ°²Î¿¼µÄ·¶Î§"
+
+#: ex_docmd.c:1469
+msgid "Backwards range given, OK to swap"
+msgstr "Ö¸¶¨ÁËÏòÇ°²Î¿¼µÄ·¶Î§£¬OK to swap"
+
+#: ex_docmd.c:1580
+msgid "Use w or w>>"
+msgstr "ÇëʹÓà w »ò w>>"
+
+#: ex_docmd.c:3086
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: ±§Ç¸, ±¾ÃüÁîÔÚ´Ë°æ±¾ÖÐδʵÏÖ"
+
+#: ex_docmd.c:3256
+msgid "E172: Only one file name allowed"
+msgstr "E172: Ö»ÄÜÓÐÒ»¸öÎļþÃû"
+
+#: ex_docmd.c:3810
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "»¹ÓÐ %d ¸öÎļþδ±à¼­. È·¶¨ÒªÍ˳ö£¿"
+
+#: ex_docmd.c:3817
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: »¹ÓÐ %ld ¸öÎļþδ±à¼­"
+
+#: ex_docmd.c:3911
+msgid "E174: Command already exists: use ! to redefine"
+msgstr "E174: ÃüÁîÒѾ­´æÔÚ, ÇëʹÓà ! Ç¿ÖÆÖØж¨Òå"
+
+#: ex_docmd.c:4016
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" Ãû³Æ ²ÎÊý ·¶Î§ ÍêÕû ¶¨Òå "
+
+#: ex_docmd.c:4105
+msgid "No user-defined commands found"
+msgstr "ÕÒ²»µ½Óû§×Ô¶¨ÒåµÄÃüÁî"
+
+#: ex_docmd.c:4136
+msgid "E175: No attribute specified"
+msgstr "E175: ûÓÐÖ¸¶¨µÄÊôÐÔ"
+
+#: ex_docmd.c:4188
+msgid "E176: Invalid number of arguments"
+msgstr "E176: ²»ÕýÈ·µÄ²ÎÊý¸öÊý"
+
+#: ex_docmd.c:4203
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: ²»ÄÜÖ¸¶¨Á½´Î"
+
+#: ex_docmd.c:4213
+msgid "E178: Invalid default value for count"
+msgstr "E178: ¼ÆÊýµÄȱʡֵ²»ÕýÈ·"
+
+#: ex_docmd.c:4241
+msgid "E179: argument required for complete"
+msgstr "E179: Ö¸ÁîÐèÒª²ÎÊý²ÅÄÜÍê³É"
+
+#: ex_docmd.c:4260
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: ²»ÍêÕûµÄÖµ: '%s'"
+
+#: ex_docmd.c:4268
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: ²»ÕýÈ·µÄÊôÐÔ: %s"
+
+#: ex_docmd.c:4309
+msgid "E182: Invalid command name"
+msgstr "E182: ÃüÁîÃû³Æ²»ÕýÈ·"
+
+#: ex_docmd.c:4324
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: Óû§×Ô¶¨ÒåÃüÁî±ØÐëÒÔ´óд×Öĸ¿ªÊ¼"
+
+#: ex_docmd.c:4393
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: ûÓÐÓû§×Ô¶¨ÒåµÄÃüÁ %s"
+
+#: ex_docmd.c:4844
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: ÕÒ²»µ½ÑÕÉ«Ñùʽ %s"
+
+#: ex_docmd.c:4852
+msgid "Greetings, Vim user!"
+msgstr "ÄãºÃ, Vim Óû§£¡"
+
+#: ex_docmd.c:5549
+msgid "Edit File in new window"
+msgstr "ÔÚд°¿Ú±à¼­Îļþ"
+
+#: ex_docmd.c:5815
+msgid "No swap file"
+msgstr "ÎÞ½»»»Îļþ"
+
+#: ex_docmd.c:5919
+msgid "Append File"
+msgstr "¸½¼ÓÎļþ"
+
+#: ex_docmd.c:5978
+msgid "E186: No previous directory"
+msgstr "E186: Ç°Ò»¸öĿ¼²»´æÔÚ"
+
+#: ex_docmd.c:6055
+msgid "E187: Unknown"
+msgstr "E187: ²»ÄÜʶ±ðµÄ±ê¼Ç"
+
+#: ex_docmd.c:6173
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "´°¿ÚλÖÃ: X %d, Y %d"
+
+#: ex_docmd.c:6178
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: ÔÚÄúµÄƽ̨Éϲ»ÄÜ»ñµÃ´°¿ÚλÖÃ"
+
+#: ex_docmd.c:6444
+msgid "Save Redirection"
+msgstr "±£´æÖض¨Ïò"
+
+#: ex_docmd.c:6593
+msgid "Save View"
+msgstr "±£´æÊÓͼ"
+
+#: ex_docmd.c:6594
+msgid "Save Session"
+msgstr "±£´æ»á»°"
+
+#: ex_docmd.c:6596
+msgid "Save Setup"
+msgstr "±£´æÉ趨"
+
+#: ex_docmd.c:6745
+#, c-format
+msgid "E189: \"%s\" exists (use ! to override)"
+msgstr "E189: \"%s\" ÒÑ´æÔÚ (ÇëÓÃ ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: ex_docmd.c:6750
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: ²»ÄÜÒÔдÈëģʽ´ò¿ª \"%s\""
+
+#. set mark
+#: ex_docmd.c:6774
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: ²ÎÊý±ØÐëÊÇÓ¢ÎÄ×Öĸ»òÏòÇ°/ºóµÄÒýºÅ"
+
+#: ex_docmd.c:6803
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: :normal µÝ¹é²ãÊý¹ýÉî"
+
+#: ex_docmd.c:7171
+msgid ":if nesting too deep"
+msgstr ":if ²ãÊý¹ýÉî"
+
+#: ex_docmd.c:7206
+msgid ":endif without :if"
+msgstr ":endif ȱÉÙ¶ÔÓ¦µÄ :if"
+
+#: ex_docmd.c:7226
+msgid ":else without :if"
+msgstr ":else ȱÉÙ¶ÔÓ¦µÄ :if"
+
+#: ex_docmd.c:7228
+msgid ":elseif without :if"
+msgstr ":elseif ȱÉÙ¶ÔÓ¦µÄ :if"
+
+#: ex_docmd.c:7280
+msgid ":while nesting too deep"
+msgstr ":while ²ãÊý¹ýÉî"
+
+#: ex_docmd.c:7326
+msgid ":continue without :while"
+msgstr ":continue ȱÉÙ¶ÔÓ¦µÄ :while"
+
+#: ex_docmd.c:7353
+msgid ":break without :while"
+msgstr ":break ȱÉÙ¶ÔÓ¦µÄ :while"
+
+#: ex_docmd.c:7376 ex_docmd.c:7381
+msgid ":endwhile without :while"
+msgstr ":endwhile ȱÉÙ¶ÔÓ¦µÄ :while"
+
+#: ex_docmd.c:7402
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction ±ØÐëÔÚº¯ÊýÄÚ²¿Ê¹ÓÃ"
+
+#: ex_docmd.c:7582
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: ûÓÐ '#' ¿ÉÌæ´úµÄÎļþÃû"
+
+#: ex_docmd.c:7613
+msgid "no autocommand file name to substitute for \"<afile>\""
+msgstr "ûÓÐ Autocommand ÎļþÃûÒÔÌæ»» \"<afile>\""
+
+#: ex_docmd.c:7621
+msgid "no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "ûÓÐ Autocommand »º³åÇøÃû³ÆÒÔÌæ»» \"<abuf>\""
+
+#: ex_docmd.c:7632
+msgid "no autocommand match name to substitute for \"<amatch>\""
+msgstr "ûÓÐ Autocommand Match name ÒÔÌæ»» \"<amatch>\""
+
+#: ex_docmd.c:7642
+msgid "no :source file name to substitute for \"<sfile>\""
+msgstr "ûÓÐ :source ÎļþÃûÒÔÌæ»» \"<sfile>\""
+
+#: ex_docmd.c:7683
+#, no-c-format
+msgid "Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "'%' »ò '#' Ö¸Ïò¿ÕÎļþÃû£¬Ö»ÄÜÓÃì¶ \":p:h\""
+
+#: ex_docmd.c:7685
+msgid "Evaluates to an empty string"
+msgstr "ÊäÈëΪ¿Õ×Ö·û´®"
+
+#: ex_docmd.c:8594
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: ²»ÄܶÁÈ¡ viminfo"
+
+#: ex_docmd.c:8767
+msgid "E196: No digraphs in this version"
+msgstr "E196: ±¾°æ±¾ÎÞ¸´ºÏ×Ö·û(digraph)"
+
+#: ex_getln.c:2785
+msgid "tagname"
+msgstr "±êÇ©Ãû³Æ"
+
+#: ex_getln.c:2788
+msgid " kind file\n"
+msgstr "ÀàÎļþ\n"
+
+#: ex_getln.c:3997
+msgid "'history' option is zero"
+msgstr "Ñ¡Ïî 'history' ÊÇÁã"
+
+#: ex_getln.c:4237
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s ÀúÊ·¼Ç¼ (´Óе½¾É):\n"
+
+#: ex_getln.c:4238
+msgid "Command Line"
+msgstr "ÃüÁîÐÐ"
+
+#: ex_getln.c:4239
+msgid "Search String"
+msgstr "²éÕÒ×Ö·û´®"
+
+#: ex_getln.c:4240
+msgid "Expression"
+msgstr "±í´ïʽ"
+
+#: ex_getln.c:4241
+msgid "Input Line"
+msgstr "ÊäÈëÐÐ"
+
+#: ex_getln.c:4271
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar ³¬¹ýÃüÁ¶È"
+
+#: ex_getln.c:4435
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: ÒÑɾ³ý»î¶¯´°¿Ú»ò»º´æ"
+
+#: fileio.c:347
+msgid "Illegal file name"
+msgstr "²»ÕýÈ·µÄÎļþÃû"
+
+#: fileio.c:371 fileio.c:495 fileio.c:2491 fileio.c:2529
+msgid "is a directory"
+msgstr "ÊÇĿ¼"
+
+#: fileio.c:373
+msgid "is not a file"
+msgstr "²»ÊÇÎļþ"
+
+#: fileio.c:515 fileio.c:3581
+msgid "[New File]"
+msgstr "[δÃüÃû]"
+
+#: fileio.c:532
+msgid "[Permission Denied]"
+msgstr "[ȨÏÞ²»×ã]"
+
+#: fileio.c:624
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre Autocommand ʹ³ÌÐò²»ÄܶÁÈ¡´ËÎļþ"
+
+#: fileio.c:626
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *Filter* Autocommand ²»¿ÉÒÔ¸ü¸Ä»º³åÇøµÄÄÚÈÝ"
+
+#: fileio.c:646
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: ´Ó±ê×¼ÊäÈë¶ÁÈ¡...\n"
+
+#: fileio.c:652
+msgid "Reading from stdin..."
+msgstr "´Ó±ê×¼ÊäÈë¶Á..."
+
+#. Re-opening the original file failed!
+#: fileio.c:876
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: ת»»´íÎó"
+
+#: fileio.c:1732
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:1739
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:1746
+msgid "[socket]"
+msgstr "[socket]"
+
+#: fileio.c:1754
+msgid "[RO]"
+msgstr "[Ö»¶Á]"
+
+#: fileio.c:1764
+msgid "[CR missing]"
+msgstr "[ȱÉÙCR]'"
+
+#: fileio.c:1769
+msgid "[NL found]"
+msgstr "[ÕÒµ½NL]"
+
+#: fileio.c:1774
+msgid "[long lines split]"
+msgstr "[·Ö¸î¹ý³¤ÐÐ]"
+
+#: fileio.c:1780 fileio.c:3565
+msgid "[NOT converted]"
+msgstr "[δת»»]"
+
+#: fileio.c:1785 fileio.c:3570
+msgid "[converted]"
+msgstr "[ÒÑת»»]"
+
+#: fileio.c:1792 fileio.c:3595
+msgid "[crypted]"
+msgstr "[ÒѼÓÃÜ]"
+
+#: fileio.c:1799
+msgid "[CONVERSION ERROR]"
+msgstr "ת»»´íÎó"
+
+#: fileio.c:1806
+msgid "[READ ERRORS]"
+msgstr "[¶Á´íÎó]"
+
+#: fileio.c:2013
+msgid "Can't find temp file for conversion"
+msgstr "ÕÒ²»µ½×ª»»ÓõÄÁÙʱÎļþ"
+
+#: fileio.c:2020
+msgid "Conversion with 'charconvert' failed"
+msgstr "×Ö·û¼¯×ª»»´íÎó"
+
+#: fileio.c:2023
+msgid "can't read output of 'charconvert'"
+msgstr "²»ÄܶÁÈ¡ 'charconvert' µÄÊä³ö"
+
+#: fileio.c:2407
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Autocommand ɾ³ý»òÊÍ·ÅÁËҪдÈëµÄ»º³åÇø"
+
+#: fileio.c:2430
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Autocommand ÒâÍâµØ¸Ä±äÁËÐкÅ"
+
+#: fileio.c:2496 fileio.c:2513
+msgid "is not a file or writable device"
+msgstr "²»ÊÇÎļþ»ò¿ÉдµÄÉ豸"
+
+#: fileio.c:2555
+msgid "is read-only (use ! to override)"
+msgstr "ÊÇÖ»¶ÁÎļþ (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:2851
+msgid "Can't write to backup file (use ! to override)"
+msgstr "²»ÄÜд±¸·ÝÎļþ (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:2863
+msgid "Close error for backup file (use ! to override)"
+msgstr "¹Ø±Õ±¸·ÝÎļþ³ö´í (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:2865
+msgid "Can't read file for backup (use ! to override)"
+msgstr "²»ÄܶÁÈ¡ÎļþÒÔ¹©±¸·Ý (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:2881
+msgid "Cannot create backup file (use ! to override)"
+msgstr "²»ÄÜ´´½¨±¸·ÝÎļþ (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:2970
+msgid "Can't make backup file (use ! to override)"
+msgstr "²»ÄÜ×÷±¸·ÝÎļþ (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:3032
+msgid "The resource fork will be lost (use ! to override)"
+msgstr "Resource fork »áÏûʧ (ÇëʹÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: fileio.c:3121
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: ÕÒ²»µ½Ð´ÈëÓõĽ»»»Îļþ"
+
+#: fileio.c:3139
+msgid "E213: Cannot convert (use ! to write without conversion)"
+msgstr "E213: ²»ÄÜת»» (ÇëʹÓà ! Ç¿ÖƲ»×ª»»Ð´Èë)"
+
+#: fileio.c:3176
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: ²»ÄÜÒÔдÈëģʽ´ò¿ªÁ´½ÓÎļþ"
+
+#: fileio.c:3180
+msgid "E212: Can't open file for writing"
+msgstr "E212: ²»ÄÜÒÔдÈëģʽ´ò¿ª"
+
+#: fileio.c:3423
+msgid "Close failed"
+msgstr "¹Ø±Õʧ°Ü"
+
+#: fileio.c:3481
+msgid "write error, conversion failed"
+msgstr "²»ÄÜдÈë -- ת»»Ê§°Ü"
+
+#: fileio.c:3487
+msgid "write error (file system full?)"
+msgstr "дÈë´íÎó (ÎļþϵͳÒÑÂú£¿)"
+
+#: fileio.c:3560
+msgid " CONVERSION ERROR"
+msgstr "ת»»´íÎó"
+
+#: fileio.c:3576
+msgid "[Device]"
+msgstr "[É豸]"
+
+#: fileio.c:3581
+msgid "[New]"
+msgstr "[ÐÂ]"
+
+#: fileio.c:3603
+msgid " [a]"
+msgstr "[a]"
+
+#: fileio.c:3603
+msgid " appended"
+msgstr " ÒѸ½¼Ó"
+
+#: fileio.c:3605
+msgid " [w]"
+msgstr "[w]"
+
+#: fileio.c:3605
+msgid " written"
+msgstr " ÒÑдÈë"
+
+#: fileio.c:3655
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: Patch ģʽ: ²»ÄÜ´¢´æԭʼÎļþ"
+
+#: fileio.c:3677
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: Patch ģʽ: ²»Äܸıä¿ÕµÄԭʼÎļþ"
+
+#: fileio.c:3692
+msgid "E207: Can't delete backup file"
+msgstr "E207: ²»ÄÜɾ³ý±¸·ÝÎļþ"
+
+#: fileio.c:3744
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"¾¯¸æ: ԭʼÎļþ¶ªÊ§»òËð»µ\n"
+
+#: fileio.c:3746
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "ÔÚÎļþÕýȷдÈëÇ°ÇëÎðÍ˳ö±à¼­Æ÷!"
+
+#: fileio.c:3826
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:3826
+msgid "[dos format]"
+msgstr "[dos ¸ñʽ]"
+
+#: fileio.c:3833
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:3833
+msgid "[mac format]"
+msgstr "[mac ¸ñʽ]"
+
+#: fileio.c:3840
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:3840
+msgid "[unix format]"
+msgstr "[unix ¸ñʽ]"
+
+#: fileio.c:3867
+msgid "1 line, "
+msgstr "1 ÐÐ, "
+
+#: fileio.c:3869
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld ÐÐ, "
+
+#: fileio.c:3872
+msgid "1 character"
+msgstr "Ò»¸ö×Ö·û"
+
+#: fileio.c:3874
+#, c-format
+msgid "%ld characters"
+msgstr "%ld¸ö×Ö·û"
+
+#: fileio.c:3884
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:3884
+msgid "[Incomplete last line]"
+msgstr "[×îºóÒ»Ðв»ÍêÕû]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:3903
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "¾¯¸æ: ±¾Îļþ×ÔÉϴζÁÈëºóÒѱ䶯!!!"
+
+#: fileio.c:3905
+msgid "Do you really want to write to it"
+msgstr "È·¶¨ÒªÐ´ÈëÂð"
+
+#: fileio.c:4861
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: дÈëÎļþ \"%s\" ´íÎó"
+
+#: fileio.c:4868
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: ¹Ø±ÕÎļþ \"%s\" ´íÎó"
+
+#: fileio.c:4871
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: ¶ÁÈ¡Îļþ \"%s\" ´íÎó"
+
+#: fileio.c:5035
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: FileChangedShell autocommand ɾ³ý»º³åÇø"
+
+#: fileio.c:5043
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: ¾¯¸æ: Îļþ \"%s\" ÒѾ­²»´æÔÚ"
+
+#: fileio.c:5056
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr "W12: ¾¯¸æ: Îļþ \"%s\" ×ÔÉϴζÁÈëºóÒѱ䶯, ¶øÇұ༭ÖеĻº³åÇøÒ²¸ü¶¯ÁË"
+
+#: fileio.c:5059
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: ¾¯¸æ: Îļþ \"%s\" ×ÔÉϴζÁÈëºóÒѸıä"
+
+#: fileio.c:5061
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: ¾¯¸æ: Îļþ \"%s\" ×ÔÉϴζÁÈëºóÒѸıä"
+
+#: fileio.c:5071
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: ¾¯¸æ: Îļþ \"%s\" ÔÚ¿ªÊ¼±à¼­ºóÓÖ±»´´½¨ÁË"
+
+#: fileio.c:5088
+msgid "Warning"
+msgstr "¾¯¸æ"
+
+#: fileio.c:5089
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"È·¶¨(&O)\n"
+"¼ÓÔØÎļþ(&L)"
+
+#: fileio.c:5165
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: ²»ÄÜÖØмÓÔØ \"%s\""
+
+#: fileio.c:5670
+msgid "--Deleted--"
+msgstr "--ÒÑɾ³ý--"
+
+#. the group doesn't exist
+#: fileio.c:5830
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: ×é²»´æÔÚ: \"%s\""
+
+#: fileio.c:5955
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: * ºóÃæÓв»ÕýÈ·µÄ×Ö·û: %s"
+
+#: fileio.c:5966
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: ÎÞ´Ëʼþ: %s"
+
+#. Highlight title
+#: fileio.c:6115
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Auto-Commands ---"
+
+#: fileio.c:6386
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: ²»ÄܶÔËùÓÐʼþÖ´ÐÐ autocommand"
+
+#: fileio.c:6409
+msgid "No matching autocommands"
+msgstr "ÕÒ²»µ½¶ÔÓ¦µÄ autocommand"
+
+#: fileio.c:6681
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: autocommand ²ãÊý¹ýÉî"
+
+#: fileio.c:6968
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Auto commands: \"%s\""
+
+#: fileio.c:6976
+#, c-format
+msgid "Executing %s"
+msgstr "Ö´ÐÐ %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7044
+#, c-format
+msgid "autocommand %s"
+msgstr "autocommand %s"
+
+#: fileio.c:7566
+msgid "E219: Missing {."
+msgstr "E219: ȱÉÙ {."
+
+#: fileio.c:7568
+msgid "E220: Missing }."
+msgstr "E220: ȱÉÙ }."
+
+#: fold.c:66
+msgid "No fold found"
+msgstr "ÕÒ²»µ½ÈκΠfold"
+
+#: fold.c:554
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: ²»ÄÜÔÚÄ¿Ç°µÄ 'foldmethod' Ï´´½¨ fold"
+
+#: fold.c:556
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: ²»ÄÜÔÚÄ¿Ç°µÄ 'foldmethod' ÏÂɾ³ý fold"
+
+#: fold.c:1700
+msgid "E221: 'commentstring' is empty"
+msgstr "E221: Ñ¡Ïî 'commentstring' δÉ趨"
+
+#: getchar.c:268
+msgid "E222: Add to read buffer"
+msgstr "E222: ¼ÓÈë¶Á»º³åÖÐ"
+
+#: getchar.c:2114
+msgid "E223: recursive mapping"
+msgstr "E223: µÝ¹é mapping"
+
+#: getchar.c:2966
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: %s ÒѾ­ÓÐÈ«¾Ö abbreviation ÁË"
+
+#: getchar.c:2969
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: %s ÒѾ­ÓÐÈ«¾Ö mapping ÁË"
+
+#: getchar.c:3096
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: %s ÒѾ­ÓÐ abbreviation ÁË"
+
+#: getchar.c:3099
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: %s µÄ mapping ÒѾ­´æÔÚ"
+
+#: getchar.c:3163
+msgid "No abbreviation found"
+msgstr "ÕÒ²»µ½Ëõд"
+
+#: getchar.c:3165
+msgid "No mapping found"
+msgstr "ûÓÐÕâ¸ö¶ÔÓ¦"
+
+#: getchar.c:3990
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: ²»ÕýÈ·µÄģʽ"
+
+#: gui_at_fs.c:290
+msgid "<cannot open> "
+msgstr "<²»ÄÜ´ò¿ª>"
+
+#: gui_at_fs.c:1115
+#, c-format
+msgid "vim_SelFile: can't get font %s"
+msgstr "vim_SelFile: ²»ÄÜʹÓà %s ×ÖÌå"
+
+#: gui_at_fs.c:2535
+msgid "vim_SelFile: can't return to current directory"
+msgstr "vim_SelFile: ²»Äܻص½Ä¿Ç°Ä¿Â¼"
+
+#: gui_at_fs.c:2554
+msgid "Pathname:"
+msgstr "·¾¶:"
+
+#: gui_at_fs.c:2560
+msgid "vim_SelFile: can't get current directory"
+msgstr "vim_SelFile: ²»ÄÜÈ¡µÃĿǰĿ¼"
+
+#: gui_at_fs.c:2568 gui_motif.c:1607
+msgid "OK"
+msgstr "È·¶¨"
+
+#. 'Cancel' button
+#: gui_at_fs.c:2568 gui_gtk.c:1683 gui_motif.c:1602 gui_motif.c:2823
+msgid "Cancel"
+msgstr "È¡Ïû"
+
+#: gui_athena.c:1928 gui_motif.c:1855
+msgid "Vim dialog"
+msgstr "Vim ¶Ô»°¿ò"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "¹ö¶¯Ìõ: ²»ÄÜÉ趨 thumb pixmap µÄλÖÃ"
+
+#: gui_beval.c:68
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: ²»ÄܶÔÐÅÏ¢Óë callback ´´½¨ BallonEval"
+
+#: gui.c:181
+msgid "E229: Cannot start the GUI"
+msgstr "E229: ²»ÄÜÆô¶¯Í¼ÐͽçÃæ"
+
+#: gui.c:306
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: ²»ÄܶÁÈ¡Îļþ \"%s\""
+
+#: gui.c:431
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: ²»ÕýÈ·µÄ 'guifontwide'"
+
+#: gui.c:3919
+msgid "Error"
+msgstr "´íÎó"
+
+#: gui.c:3920
+msgid "&Ok"
+msgstr "È·¶¨(&O)"
+
+#: gui_gtk.c:1144
+msgid "Vim dialog..."
+msgstr "Vim ¶Ô»°¿ò..."
+
+#: gui_gtk.c:1519 gui_motif.c:2742
+msgid "VIM - Search and Replace..."
+msgstr "VIM - ²éÕÒÓëÌæ»»..."
+
+#: gui_gtk.c:1524 gui_motif.c:2744
+msgid "VIM - Search..."
+msgstr "VIM - ²éÕÒ..."
+
+#: gui_gtk.c:1547 gui_motif.c:2862
+msgid "Find what:"
+msgstr "²éÕÒ:"
+
+#: gui_gtk.c:1565 gui_motif.c:2894
+msgid "Replace with:"
+msgstr "Ì滻Ϊ:"
+
+#. exact match only button
+#: gui_gtk.c:1597 gui_motif.c:2996
+msgid "Match exact word only"
+msgstr "ֻƥÅäÍêÈ«ÏàͬµÄ×Ö"
+
+#: gui_gtk.c:1609 gui_motif.c:2964
+msgid "Direction"
+msgstr "·½Ïò"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:1621 gui_motif.c:2976
+msgid "Up"
+msgstr "ÏòÉÏ"
+
+#: gui_gtk.c:1625 gui_motif.c:2984
+msgid "Down"
+msgstr "ÏòÏÂ"
+
+#. 'Find Next' button
+#: gui_gtk.c:1647 gui_motif.c:2766
+msgid "Find Next"
+msgstr "ÕÒÏÂÒ»¸ö"
+
+#. 'Replace' button
+#: gui_gtk.c:1664 gui_motif.c:2783
+msgid "Replace"
+msgstr "Ìæ»»"
+
+#. 'Replace All' button
+#: gui_gtk.c:1673 gui_motif.c:2796
+msgid "Replace All"
+msgstr "Ì滻ȫ²¿"
+
+#: gui_gtk_x11.c:1076 gui_x11.c:1194
+msgid "E233: cannot open display"
+msgstr "E233: <²»ÄÜ´ò¿ª X Server DISPLAY>"
+
+#: gui_gtk_x11.c:2433 gui_x11.c:1997
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: ²»ÕýÈ·µÄ×Ö·û¼¯ (Fontset): %s"
+
+#: gui_gtk_x11.c:2460
+msgid "Font Selection"
+msgstr "×ÖÌåÑ¡Ôñ"
+
+#: gui_gtk_x11.c:2702 gui_mac.c:2780 gui_w48.c:1197 gui_x11.c:1833
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "²»ÕýÈ·µÄ×ÖÌåÃû³Æ: %s"
+
+#: gui_gtk_x11.c:2713 gui_x11.c:1857
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: \"%s\" ²»Êǹ̶¨¿í¶È×ÖÌå"
+
+#: gui_gtk_x11.c:2843
+#, c-format
+msgid "E242: Color name not recognized: %s"
+msgstr "E242: %s Ϊ²»ÄÜʶ±ðµÄÑÕÉ«Ãû³Æ"
+
+#: gui_gtk_x11.c:3519 ui.c:1929
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "ʹÓà CUT_BUFFER0 À´Ìæ»»¿ÕÑ¡Ôñ"
+
+#: gui_motif.c:1601 gui_motif.c:1604
+msgid "Filter"
+msgstr "¹ýÂËÆ÷"
+
+#: gui_motif.c:1603
+msgid "Directories"
+msgstr "Ŀ¼"
+
+#: gui_motif.c:1605
+msgid "Help"
+msgstr "°ïÖú"
+
+#: gui_motif.c:1606
+msgid "Files"
+msgstr "Îļþ"
+
+#: gui_motif.c:1608
+msgid "Selection"
+msgstr "Ñ¡Ôñ"
+
+#: gui_motif.c:2809
+msgid "Undo"
+msgstr "³·Ïû"
+
+#: gui_riscos.c:951
+#, c-format
+msgid "E235: Can't load Zap font '%s'"
+msgstr "E235: ²»ÄÜ´ò¿ª Zap ×ÖÌå '%s'"
+
+#: gui_riscos.c:1047
+#, c-format
+msgid "E235: Can't use font %s"
+msgstr "E235: ²»ÄÜʹÓÃ×ÖÌå %s"
+
+#: gui_riscos.c:1167
+#, c-format
+msgid "E242: Missing color: %s"
+msgstr "E242: ÕÒ²»µ½ÑÕÉ«: %s"
+
+#: gui_riscos.c:3269
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"ÕýÔÚ·¢ËÍÖжÏ×Ó³ÌÐòµÄÐÅÏ¢.\n"
+
+#: gui_w32.c:823
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: ²»Ö§³Ö²ÎÊý \"-%s\"¡£ÇëÓà OLE °æ±¾¡£"
+
+#: gui_w48.c:2068
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "²éÕÒ×Ö·û´® (ʹÓà '\\\\' À´±íʾ '\\')"
+
+#: gui_w48.c:2093
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "²éÕÒ¼°Ìæ»»×Ö·û´® (ʹÓà '\\\\' À´±íʾ '\\')"
+
+#: gui_x11.c:1414
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr "Vim E458: ²»ÄÜÅäÖà color map ¶ÔÏó£¬ÓÐЩÑÕÉ«¿´ÆðÀ´»á¹Ö¹ÖµÄ"
+
+#: gui_x11.c:1987
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: Fontset %s ûÓÐÉ趨ÕýÈ·µÄ×ÖÌåÒÔ¹©ÏÔʾÕâЩ×Ö·û¼¯:"
+
+#: gui_x11.c:2030
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: ×ÖÌ弯(Fontset)Ãû³Æ: %s"
+
+#: gui_x11.c:2031
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "'%s' ²»Êǹ̶¨¿í¶È×ÖÌå"
+
+#: gui_x11.c:2050
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: ×ÖÌ弯(Fontset)Ãû³Æ: %s\n"
+
+#: gui_x11.c:2051
+#, c-format
+msgid "Font0: %s\n"
+msgstr "×ÖÌå0: %s\n"
+
+#: gui_x11.c:2052
+#, c-format
+msgid "Font1: %s\n"
+msgstr "×ÖÌå1: %s\n"
+
+#: gui_x11.c:2053
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "×ÖÌå%d¿í¶È²»ÊÇ×ÖÌå0µÄÁ½±¶\n"
+
+#: gui_x11.c:2054
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "×ÖÌå0µÄ¿í¶È£º%ld\n"
+
+#: gui_x11.c:2055
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"×ÖÌå1¿í¶È: %ld\n"
+"\n"
+
+#: gui_x11.c:2201
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: ²»ÄÜÅäÖÃÑÕÉ« %s"
+
+#: gui_x11.c:3250
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: ²»ÄܶÁÈ¡ sign data!"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: Hangul automata ´íÎó"
+
+#: if_cscope.c:26
+#, c-format
+msgid "Usage: cs[cope] %s"
+msgstr ""
+
+#: if_cscope.c:67
+msgid "Add a new database"
+msgstr "ÐÂÔöÊý¾Ý¿â"
+
+#: if_cscope.c:69
+msgid "Query for a pattern"
+msgstr "²éѯģʽ"
+
+#: if_cscope.c:71
+msgid "Show this message"
+msgstr "ÏÔʾ´ËÐÅÏ¢"
+
+#: if_cscope.c:73
+msgid "Kill a connection"
+msgstr "½áÊøÁ¬½Ó"
+
+#: if_cscope.c:75
+msgid "Reinit all connections"
+msgstr "ÖØÉèËùÓÐÁ¬½Ó"
+
+#: if_cscope.c:77
+msgid "Show connections"
+msgstr "ÏÔʾÁ¬½Ó"
+
+#: if_cscope.c:108
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "Õâ¸ö cscope ÃüÁî²»Ö§³Ö·Ö¸îÆÁÄ»\n"
+
+#: if_cscope.c:143
+msgid "Usage: cstag <ident>"
+msgstr "Ó÷¨: cstag <ʶ±ð×Ö>"
+
+#: if_cscope.c:199
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: ÕÒ²»µ½ tag"
+
+#: if_cscope.c:407 if_cscope.c:451
+#, c-format
+msgid "stat(%s) error: %d"
+msgstr "stat(%s) ´íÎó: %d"
+
+#: if_cscope.c:460 if_cscope.c:467
+#, c-format
+msgid "Added cscope database %s"
+msgstr "ÐÂÔö cscope Êý¾Ý¿â %s"
+
+#: if_cscope.c:474
+#, c-format
+msgid "%s is not a directory or a valid cscope database"
+msgstr "%s ²»ÊÇĿ¼»ò cscope Êý¾Ý¿â"
+
+#: if_cscope.c:557
+#, c-format
+msgid "error reading cscope connection %d"
+msgstr "¶ÁÈ¡ cscope Á¬½Ó %d ʱ´íÎó"
+
+#: if_cscope.c:633
+msgid "unknown cscope search type"
+msgstr "δ֪µÄ cscope ²éÕÒÐÎ̬"
+
+#: if_cscope.c:680
+msgid "Could not create cscope pipes"
+msgstr "²»ÄÜ´´½¨Óë cscope Á¬½ÓµÄ¹ÜµÀ"
+
+#: if_cscope.c:745
+msgid "cs_create_connection exec failed"
+msgstr "cs_create_connection Ö´ÐÐʧ°Ü"
+
+#: if_cscope.c:755
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen ʧ°Ü (to_fp)"
+
+#: if_cscope.c:757
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen ʧ°Ü (fr_fp)"
+
+#: if_cscope.c:785
+msgid "no cscope connections"
+msgstr "ûÓÐ cscope Á¬½Ó"
+
+#: if_cscope.c:855
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: ÕÒ²»µ½·ûºÏ cscope µÄËÑÑ° %s / %s"
+
+#: if_cscope.c:899
+msgid "cscope commands:\n"
+msgstr "cscope ÃüÁî:\n"
+
+#: if_cscope.c:902
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)\n"
+msgstr "%-5s: %-30s (Ó÷¨: %s)\n"
+
+#: if_cscope.c:970
+msgid "duplicate cscope database not added"
+msgstr "Öظ´µÄ cscope Êý¾Ý¿âδ±»¼ÓÈë"
+
+#: if_cscope.c:981
+msgid "maximum number of cscope connections reached"
+msgstr "ÒÑ´ïµ½ cscope ×î´óÁ¬½ÓÊýÄ¿"
+
+#: if_cscope.c:1102
+msgid "E260: cscope connection not found"
+msgstr "E260: ÕÒ²»µ½ cscope Á¬½Ó"
+
+#: if_cscope.c:1105
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: ÕÒ²»µ½ cscope Á¬½Ó %s"
+
+#: if_cscope.c:1141
+msgid "cscope connection closed"
+msgstr "cscope Á¬½ÓÒѹرÕ"
+
+#: if_cscope.c:1149
+#, c-format
+msgid "cscope connection %s closed\n"
+msgstr "cscope Á¬½Ó %s ÒѹرÕ\n"
+
+#. should not reach here
+#: if_cscope.c:1290
+msgid "fatal error in cs_manage_matches"
+msgstr "cs_manage_matches ÑÏÖØ´íÎó"
+
+#: if_cscope.c:1341
+#, c-format
+msgid "E262: error reading cscope connection %d"
+msgstr "E262: ¶ÁÈ¡ cscope Á¬½Ó %d ´íÎó"
+
+#: if_cscope.c:1449
+msgid "couldn't malloc\n"
+msgstr "²»ÄÜʹÓà malloc\n"
+
+#: if_cscope.c:1454
+#, c-format
+msgid "Cscope tag: %s\n"
+msgstr "Cscope ±êÇ©(tag): %s\n"
+
+#: if_cscope.c:1458
+msgid " # line"
+msgstr " # ÐÐ "
+
+#: if_cscope.c:1460
+msgid "filename / context / line\n"
+msgstr "ÎļþÃû / ÉÏÏÂÎÄ / ÐкÅ\n"
+
+#: if_cscope.c:1718
+msgid "All cscope databases reset"
+msgstr "ÖØÉèËùÓÐ cscope Êý¾Ý¿â"
+
+#: if_cscope.c:1785
+msgid "no cscope connections\n"
+msgstr "ûÓÐ cscope Á¬½Ó\n"
+
+#: if_cscope.c:1789
+msgid " # pid database name prepend path\n"
+msgstr " # pid Êý¾Ý¿âÃû³Æ prepend path\n"
+
+#: if_cscope.c:1800
+#, c-format
+msgid "%2d %-5ld %-34s <none>\n"
+msgstr "%2d %-5ld %-34s <ÎÞ>\n"
+
+#: if_python.c:376
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr "E263: ±§Ç¸£¬Õâ¸öÃüÁî²»ÄÜʹÓã¬Python ³ÌÐò¿âûÓмÓÔØ¡£"
+
+#: if_python.c:576
+msgid "can't delete OutputObject attributes"
+msgstr "²»ÄÜɾ³ý OutputObject ÊôÐÔ"
+
+#: if_python.c:583
+msgid "softspace must be an integer"
+msgstr "softspace ±ØÐèÊÇÕûÊý"
+
+#: if_python.c:591
+msgid "invalid attribute"
+msgstr "²»ÕýÈ·µÄÊôÐÔ"
+
+#: if_python.c:630 if_python.c:644
+msgid "writelines() requires list of strings"
+msgstr "writelines() ÐèÒª string list µ±²ÎÊý"
+
+#: if_python.c:770
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: ²»Äܳõʼ»¯ I/O ¶ÔÏó"
+
+#: if_python.c:955 if_tcl.c:1391
+msgid "invalid expression"
+msgstr "²»ÕýÈ·µÄ±í´ïʽ"
+
+#: if_python.c:969 if_tcl.c:1396
+msgid "expressions disabled at compile time"
+msgstr "ÒòΪ±àÒëʱûÓмÓÈë±í´ïʽ(expression)µÄ³ÌÐò´úÂ룬ËùÒÔ²»ÄÜʹÓñí´ïʽ"
+
+#: if_python.c:982
+msgid "attempt to refer to deleted buffer"
+msgstr "ÊÔͼʹÓÃÒѱ»É¾³ýµÄ»º³åÇø"
+
+#: if_python.c:997 if_python.c:1038 if_python.c:1102 if_tcl.c:1203
+msgid "line number out of range"
+msgstr "Ðкų¬³ö·¶Î§"
+
+#: if_python.c:1235
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<buffer ¶ÔÏó (ÒÑɾ³ý): %8lX>"
+
+#: if_python.c:1326 if_tcl.c:825
+msgid "invalid mark name"
+msgstr "±ê¼ÇÃû³Æ²»ÕýÈ·"
+
+#: if_python.c:1601
+msgid "no such buffer"
+msgstr "ÎÞ´Ë»º³åÇø"
+
+#: if_python.c:1689
+msgid "attempt to refer to deleted window"
+msgstr "ÊÔͼʹÓÃÒѱ»É¾³ýµÄ´°¿Ú"
+
+#: if_python.c:1734
+msgid "readonly attribute"
+msgstr "Ö»¶ÁÊôÐÔ"
+
+#: if_python.c:1747
+msgid "cursor position outside buffer"
+msgstr "¹â±ê¶¨Î»ÔÚ»º³åÇøÖ®Íâ"
+
+#: if_python.c:1824
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<´°¿Ú¶ÔÏó(ÒÑɾ³ý): %.8lX>"
+
+#: if_python.c:1836
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<´°¿Ú¶ÔÏó(δ֪): %.8lX>"
+
+#: if_python.c:1838
+#, c-format
+msgid "<window %d>"
+msgstr "<´°¿Ú %d>"
+
+#: if_python.c:1914
+msgid "no such window"
+msgstr "ÎÞ´Ë´°¿Ú"
+
+#: if_python.c:2144 if_python.c:2175 if_python.c:2225 if_python.c:2285
+#: if_python.c:2402 if_python.c:2454 if_tcl.c:673 if_tcl.c:718 if_tcl.c:792
+#: if_tcl.c:862 if_tcl.c:1987
+msgid "cannot save undo information"
+msgstr "²»Äܱ£´æ¸´Ô­ÐÅÏ¢"
+
+#: if_python.c:2146 if_python.c:2232 if_python.c:2296
+msgid "cannot delete line"
+msgstr "²»ÄÜɾ³ý´ËÐÐ"
+
+#: if_python.c:2177 if_python.c:2312 if_tcl.c:679 if_tcl.c:2009
+msgid "cannot replace line"
+msgstr "²»ÄÜÌæ»»´ËÐÐ"
+
+#: if_python.c:2328 if_python.c:2404 if_python.c:2462
+msgid "cannot insert line"
+msgstr "²»ÄܲåÈë´ËÐÐ"
+
+#: if_python.c:2566
+msgid "string cannot contain newlines"
+msgstr "×Ö·û´®²»ÄÜ°üº¬ÐÂÐÐ"
+
+#: if_ruby.c:394
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr "E266: ´ËÃüÁî²»ÄÜʹÓã¬ÎÞ·¨¼ÓÔØ Ruby ³ÌÐò¿â(Library)"
+
+#: if_ruby.c:457
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: δ֪µÄ longjmp ״̬ %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "Çл»ÊµÏÖ/¶¨Òå"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "ÏÔʾ base class of:"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "ÏÔʾ±»¸²¸ÇµÄ³ÉÔ±º¯Êý"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "»Ö¸´: ´ÓÎļþ"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "»Ö¸´: ´Ó¶ÔÏó"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "»Ö¸´: ´ÓËùÓÐÏîÄ¿"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "»Ö¸´"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "ÏÔʾԴ´úÂë: "
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "²éÕÒ symbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "ä¯ÀÀ class"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "ÏÔʾ²ã´Î¹ØϵµÄÀà"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "ÏÔʾ restricted ²ã´Î¹ØϵµÄ class"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref ²Î¿¼µ½"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref ±»Ë­²Î¿¼:"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref ÓÐ"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref ±»Ë­Ê¹ÓÃ:"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "ÏÔʾÎļþ: "
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "²úÉúÎļþ: "
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr "²»ÄÜÁ¬½Óµ½ SNiFF+¡£Çë¼ì²é»·¾³±äÁ¿ ($PATH Àï±ØÐè¿ÉÒÔÕÒµ½ sniffemacs)\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: ¶ÁÈ¡´íÎó. È¡ÏûÁ¬½Ó"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ Ä¿Ç°"
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "δ"
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "Á¬½ÓÖÐ"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: ²»ÕýÈ·µÄ SNiff+ µ÷ÓÃ: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: Á¬½Óµ½ SNiFF+ ʧ°Ü"
+
+#: if_sniff.c:1010
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: δÁ¬½Óµ½ SNiFF+"
+
+#: if_sniff.c:1019
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: ²»ÊÇ SNiFF+ µÄ»º³åÇø"
+
+#: if_sniff.c:1084
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: дÈë´íÎó¡£½áÊøÁ¬½Ó"
+
+#: if_tcl.c:407
+msgid "invalid buffer number"
+msgstr "²»ÕýÈ·µÄ»º³åÇøºÅ"
+
+#: if_tcl.c:453 if_tcl.c:920 if_tcl.c:1099
+msgid "not implemented yet"
+msgstr "ÉÐδʵÏÖ"
+
+#: if_tcl.c:490
+msgid "unknown option"
+msgstr "²»ÕýÈ·µÄÑ¡Ïî"
+
+#. ???
+#: if_tcl.c:763
+msgid "cannot set line(s)"
+msgstr "²»ÄÜÉ趨ÐÐ"
+
+#: if_tcl.c:834
+msgid "mark not set"
+msgstr "ûÓÐÉ趨±ê¼Ç"
+
+#: if_tcl.c:840 if_tcl.c:1055
+#, c-format
+msgid "row %d column %d"
+msgstr "ÁÐ %d ÐÐ %d"
+
+#: if_tcl.c:870
+msgid "cannot insert/append line"
+msgstr "²»ÄܲåÈë»òÌí¼Ó´ËÐÐ"
+
+#: if_tcl.c:1257
+msgid "unknown flag: "
+msgstr "´íÎóµÄ±êÖ¾: "
+
+#: if_tcl.c:1327
+msgid "unknown vimOption"
+msgstr "²»ÕýÈ·µÄ VIM Ñ¡Ïî"
+
+#: if_tcl.c:1412
+msgid "keyboard interrupt"
+msgstr "¼üÅÌÖжÏ"
+
+#: if_tcl.c:1417
+msgid "vim error"
+msgstr "vim ´íÎó"
+
+#: if_tcl.c:1460
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "²»ÄÜ´´½¨»º³åÇø/´°¿ÚÃüÁî: ¶ÔÏ󽫱»É¾³ý"
+
+#: if_tcl.c:1534
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr "²»ÄÜ×¢²á callback ÃüÁî: »º³åÇø/´°¿ÚÒѾ­±»É¾³ýÁË"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1551
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr "E280: TCL ÑÏÖØ´íÎó: reflist ²»¿É¿¿!? Ç뱨¸æ¸ø to vim-dev@vim.org"
+
+#: if_tcl.c:1552
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr "²»ÄÜ×¢²á callback ÃüÁî: ÕÒ²»µ½»º³åÇø/´°¿Ú"
+
+#: if_tcl.c:1713
+msgid "Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr "´ËÃüÁî²»ÄÜʹÓÃ, ÒòΪÎÞ·¨¼ÓÔØ Tcl ³ÌÐò¿â(Library)"
+
+#: if_tcl.c:1875
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr "E281: TCL ´íÎó: Í˳ö·µ»ØÖµ²»ÊÇÕûÊý!? Ç뱨¸æ¸ø to vim-dev@vim.org"
+
+#: if_tcl.c:1995
+msgid "cannot get line"
+msgstr "²»ÄÜÈ¡µÃ´ËÐÐ"
+
+#: if_xcmdsrv.c:204
+msgid "Unable to register a command server name"
+msgstr "²»ÄÜ×¢²áÃüÁî·þÎñÆ÷Ãû³Æ"
+
+#: if_xcmdsrv.c:417
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: ûÓÐ×¢²áΪ \"%s\" µÄ·þÎñÆ÷"
+
+#: if_xcmdsrv.c:446
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: ²»ÄÜËͳöÃüÁĿµÄµØ³ÌÐò"
+
+#: if_xcmdsrv.c:709
+#, c-format
+msgid "Invalid server id used: %s"
+msgstr "²»ÕýÈ·µÄ·þÎñÆ÷ id : %s"
+
+#: if_xcmdsrv.c:1056
+msgid "E249: couldn't read VIM instance registry property"
+msgstr "E249: ²»ÄܶÁÈ¡ VIM µÄ ×¢²á±íÊôÐÔ"
+
+#: if_xcmdsrv.c:1067
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: VIM µÄ×¢²á±íÊôÐÔÓÐÎó¡£ÒÑɾ³ý¡£"
+
+#: main.c:53 option.c:3162 option.c:3269
+msgid "Unknown option"
+msgstr "²»ÕýÈ·µÄÑ¡Ïî"
+
+#: main.c:55
+msgid "Too many edit arguments"
+msgstr "Ì«¶à±à¼­²ÎÊý"
+
+#: main.c:57
+msgid "Argument missing after"
+msgstr "ȱÉÙ±ØÒªµÄ²ÎÊý:"
+
+#: main.c:59
+msgid "Garbage after option"
+msgstr "²»ÄܱæÈÏ´ËÑ¡ÏîºóµÄÃüÁî: "
+
+#: main.c:61
+msgid "Too many \"+command\" or \"-c command\" arguments"
+msgstr "Ì«¶à \"+command\" »ò \"-c command\" ²ÎÊý"
+
+#: main.c:63
+msgid "Invalid argument for"
+msgstr "²»ÕýÈ·µÄ²ÎÊý: "
+
+#: main.c:436
+msgid "This Vim was not compiled with the diff feature."
+msgstr "ÄúµÄ Vim ±àÒëʱûÓмÓÈë diff µÄÄÜÁ¦"
+
+#: main.c:858
+msgid "Attempt to open script file again: \""
+msgstr "ÊÔͼÔٴδò¿ª script Îļþ: \""
+
+#: main.c:862 main.c:869 main.c:913 memline.c:3673 memline.c:3677
+#: version.c:816 version.c:821 version.c:826 version.c:831 version.c:836
+#: version.c:841 version.c:847 version.c:851 version.c:855 version.c:860
+#: version.c:867 version.c:875 version.c:881
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:867
+msgid "Cannot open for reading: \""
+msgstr "²»ÄÜΪ¶Á¶ø´ò¿ª: \""
+
+#: main.c:911
+msgid "Cannot open for script output: \""
+msgstr "²»ÄÜΪ script Êä³ö¶ø´ò¿ª: \""
+
+#: main.c:1020
+#, c-format
+msgid "%d files to edit\n"
+msgstr "»¹ÓÐ %d ¸öÎļþµÈ´ý±à¼­\n"
+
+#: main.c:1094
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: ×¢Òâ: Êä³ö²»ÊÇÖÕ¶Ë(ÆÁÄ»)\n"
+
+#: main.c:1096
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: ×¢Òâ: ÊäÈë²»ÊÇÖÕ¶Ë(¼üÅÌ)\n"
+
+#. just in case..
+#: main.c:1171
+msgid "pre-vimrc command line"
+msgstr "pre-vimrc ÃüÁîÐÐ"
+
+#: main.c:1206
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: ²»ÄܶÁÈ¡Îļþ \"%s\""
+
+#: main.c:2157
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"²éѯ¸ü¶àÐÅÏ¢ÇëÖ´ÐÐ: \"vim -h\"\n"
+
+#: main.c:2190
+msgid "[file ..] edit specified file(s)"
+msgstr "[Îļþ ..] ±à¼­Ö¸¶¨µÄÎļþ"
+
+#: main.c:2191
+msgid "- read text from stdin"
+msgstr "- ´Ó±ê×¼ÊäÈë(stdin)¶ÁÈ¡Îı¾"
+
+#: main.c:2192
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tag ±à¼­Ê±Ê¹ÓÃÖ¸¶¨µÄ tag"
+
+#: main.c:2194
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [errorfile] ±à¼­Ê±¼ÓÔصÚÒ»¸ö´íÎó"
+
+#: main.c:2203
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+" Ó÷¨:"
+
+#: main.c:2206
+msgid " vim [arguments] "
+msgstr "vim [²ÎÊý] "
+
+#: main.c:2210
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" »ò:"
+
+#: main.c:2213
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"²ÎÊý:\n"
+
+#: main.c:2214
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tÖ»ÓÐÔÚÕâÖ®ºóµÄÎļþ"
+
+#: main.c:2216
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\t×¢²á gvim µ½ OLE"
+
+#: main.c:2217
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tÈ¡Ïû OLE ÖÐµÄ gvim ×¢²á"
+
+#: main.c:2220
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tʹÓÃͼÐνçÃæ (ͬ \"gvim\")"
+
+#: main.c:2221
+msgid "-f\t\t\tForeground: Don't fork when starting GUI"
+msgstr "-f\t\t\tÇ°¾°: Æô¶¯Í¼ÐνçÃæʱ²» fork"
+
+#: main.c:2223
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi ģʽ (ͬ \"vi\")"
+
+#: main.c:2224
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx ģʽ (ͬ \"ex\")"
+
+#: main.c:2225
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\t°²¾² (batch) ģʽ (Ö»ÄÜÓë \"ex\" Ò»ÆðʹÓÃ)"
+
+#: main.c:2227
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tDiff ģʽ (ͬ \"vimdiff\", ¿ÉѸËٱȽÏÁ½Îļþ²»Í¬´¦)"
+
+#: main.c:2229
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\t¼òÒ×ģʽ (ͬ \"evim\", modeless)"
+
+#: main.c:2230
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tÖ»¶Áģʽ (ͬ \"view\")"
+
+#: main.c:2231
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\tÏÞÖÆģʽ (ͬ \"rvim\")"
+
+#: main.c:2232
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\t²»¿ÉÐÞ¸Ä (дÈëÎļþ)"
+
+#: main.c:2233
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tÎı¾²»¿ÉÐÞ¸Ä"
+
+#: main.c:2234
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\t¶þ½øÖÆģʽ"
+
+#: main.c:2236
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp ģʽ"
+
+#: main.c:2238
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\t'compatible' ´«Í³ Vi ¼æÈÝģʽ"
+
+#: main.c:2239
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\t'nocompatible' ²»ÍêÈ«Ó봫ͳ Vi ¼æÈÝ£¬¿ÉʹÓà Vim ¼ÓÇ¿ÄÜÁ¦"
+
+#: main.c:2240
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tVerbose µÈ¼¶"
+
+#: main.c:2241
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\tµ÷ÊÔģʽ"
+
+#: main.c:2242
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\t²»Ê¹Óý»»»Îļþ, ֻʹÓÃÄÚ´æ"
+
+#: main.c:2243
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\tÁгö½»»»ÎļþºóÍ˳ö"
+
+#: main.c:2244
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (¼ÓÎļþÃû) \t»Ö¸´ÉϴαÀÀ£µÄ×ÊÁÏ(Recover crashed session)"
+
+#: main.c:2245
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tÓë -r Ò»Ñù"
+
+#: main.c:2247
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\t²»Ê¹Óà newcli À´´ò¿ª´°¿Ú"
+
+#: main.c:2248
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <device>\t\tʹÓà <device> ×öÊäÈëÊä³öÉ豸"
+
+#: main.c:2251
+msgid "-H\t\t\tstart in Hebrew mode"
+msgstr "-H\t\t\tÆô¶¯Îª Ï£²®À³Ä£Ê½"
+
+#: main.c:2254
+msgid "-F\t\t\tstart in Farsi mode"
+msgstr "-F\t\t\tÆô¶¯Îª Farsi ģʽ"
+
+#: main.c:2256
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\tÉ趨ÖÕ¶ËΪ <terminal>"
+
+#: main.c:2257
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\tʹÓà <vimrc> Ìæ»»ÈκΠ.vimrc"
+
+#: main.c:2259
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\tʹÓà <gvimrc> Ìæ»»ÈκΠ.gvimrc"
+
+#: main.c:2261
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\t²»¼ÓÔØÈκΠplugin"
+
+#: main.c:2262
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\t´ò¿ª N ¸ö´°¿Ú (Ô¤ÉèÊÇÿ¸öÎļþÒ»¸ö)"
+
+#: main.c:2263
+msgid "-O[N]\t\tlike -o but split vertically"
+msgstr "-O[N]\t\tͬ -o µ«Ê¹Óô¹Ö±·Ö¸î"
+
+#: main.c:2264
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\tÆô¶¯ºóÌøµ½Îļþ½áβ"
+
+#: main.c:2265
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\tÆô¶¯ºóÌøµ½µÚ <lnum> ÐÐ"
+
+#: main.c:2267
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <command>\t¼ÓÔØÈκΠvimrc Ç°Ö´ÐÐ <command>"
+
+#: main.c:2269
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <command>\t\t¼ÓÔصÚÒ»¸öÎļþºóÖ´ÐÐ <command>"
+
+#: main.c:2270
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <session>\t\t¼ÓÔصÚÒ»¸öÎļþºóÔØÈë Session Îļþ<session>"
+
+#: main.c:2271
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <scriptin>\t´Ó <scriptin> ¶ÁÈëÒ»°ãģʽÃüÁî"
+
+#: main.c:2272
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <scriptout>\t¶ÔÎļþ <scriptout> ¸½¼Ó(append)ËùÓÐÊäÈëµÄÃüÁî"
+
+#: main.c:2273
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <scriptout>\t¶ÔÎļþ <scriptout> дÈëËùÓÐÊäÈëµÄÃüÁî"
+
+#: main.c:2275
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\t±à¼­±àÂë¹ýµÄÎļþ"
+
+#: main.c:2279
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\t½« vim ÓëÖ¸¶¨µÄ X-server Á¬½Ó"
+
+#: main.c:2281
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\t²»ÒªÁ¬½Óµ½ X Server"
+
+#: main.c:2283
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\tÔÚÁíÒ»¸ö GTK ×é¼þÄÚ´ò¿ª Vim"
+
+#: main.c:2287
+msgid "--remote <files>\tEdit <files> in a Vim server and exit"
+msgstr "--remote <files>\t±à¼­ Vim ·þÎñÆ÷ÉϵÄÎļþ²¢Í˳ö"
+
+#: main.c:2288
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <files> µÈЧÓÚ --remote, µ«»áµÈºòÎļþÍê³É±à¼­"
+
+#: main.c:2289
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <keys>\tËͳö <keys> µ½ Vim ·þÎñÆ÷²¢Í˳ö"
+
+#: main.c:2290
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <expr>\tÔÚ·þÎñÆ÷ÉÏÇó±í´ïʽµÄÖµ²¢´òÓ¡½á¹û"
+
+#: main.c:2291
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\tÁгö¿ÉÓÃµÄ Vim ·þÎñÆ÷Ãû³Æ²¢Í˳ö"
+
+#: main.c:2292
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <name>\tËÍÖÁ/³ÉΪ Vim ·þÎñÆ÷ <name>"
+
+#: main.c:2295
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\tʹÓà <viminfo> ¶ø·Ç .viminfo"
+
+#: main.c:2297
+msgid "-h\t\t\tprint Help (this message) and exit"
+msgstr "-h\t\t\t´òӡ˵Ã÷(Ò²¾ÍÊDZ¾ÐÅÏ¢)ºóÍ˳ö"
+
+#: main.c:2298
+msgid "--version\t\tprint version information and exit"
+msgstr "--version\t\t´òÓ¡°æ±¾ÐÅÏ¢ºóÍ˳ö"
+
+#: main.c:2302
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"gvim ¿Éʶ±ðµÄ²ÎÊý (Motif °æ):\n"
+
+#: main.c:2305
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"gvim ¿Éʶ±ðµÄ²ÎÊý (Athena °æ):\n"
+
+#: main.c:2308
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\tÔÚ´°¿Ú <display> Ö´ÐÐ vim"
+
+#: main.c:2309
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\tÆô¶¯ºó×îС»¯(iconified)"
+
+#: main.c:2311
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <name>\t\t¶ÁÈ¡ Resource ʱ°Ñ vim µÄÃû³ÆÊÓΪ <name>"
+
+#: main.c:2312
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (ÉÐδʵÏÖ)\n"
+
+#: main.c:2314
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <color>\tÉ趨 <color> Ϊ±³¾°É« (Ò²¿ÉÓà -bg)"
+
+#: main.c:2315
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <color>\tÉ趨 <color> Ϊһ°ãÎÄ×ÖÑÕÉ« (Ò²¿ÉÓà -fg)"
+
+#: main.c:2316 main.c:2336
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <font>\tʹÓà <font> Ϊһ°ã×ÖÌå (Ò²¿ÉÓà -fn)"
+
+#: main.c:2317
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <font>\tʹÓà <font> Ϊ´ÖÌå×ÖÌå"
+
+#: main.c:2318
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <font>\tʹÓà <font> ΪбÌå×ÖÌå"
+
+#: main.c:2319 main.c:2337
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\tʹÓÃ<geom>Ϊ³õʼλÖà (Ò²¿ÉÓà -geom)"
+
+#: main.c:2320
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <width>\tʹÓÿí¶ÈΪ <width> µÄ±ß¿ò (Ò²¿ÉÓà -bw)"
+
+#: main.c:2321
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <width> É趨¹ö¶¯Ìõ¿í¶ÈΪ <width> (Ò²¿ÉÓà -sw)"
+
+#: main.c:2323
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <height>\tÉ趨²Ëµ¥Áеĸ߶ÈΪ <height> (Ò²¿ÉÓà -mh)"
+
+#: main.c:2325 main.c:2338
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\tʹÓ÷´ÏÔ (Ò²¿ÉÓà -rv)"
+
+#: main.c:2326
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\t²»Ê¹Ó÷´ÏÔ (Ò²¿ÉÓà +rv)"
+
+#: main.c:2327
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\tÉ趨ָ¶¨µÄ×ÊÔ´"
+
+#: main.c:2330
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"gvim ¿Éʶ±ðµÄ²ÎÊý (RISC OS °æ):\n"
+
+#: main.c:2331
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <number>\t´°¿Ú³õʼ¿í¶È"
+
+#: main.c:2332
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <number>\t´°¿Ú³õʼ¸ß¶È"
+
+#: main.c:2335
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"gvim ¿Éʶ±ðµÄ²ÎÊý (GTK+ °æ):\n"
+
+#: main.c:2339
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\tÔÚ <display> Ö´ÐÐ vim (Ò²¿ÉÓà --display)"
+
+#: main.c:2341
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tÏÔʾ Gnome Ïà¹Ø²ÎÊý"
+
+#. Failed to send, abort.
+#: main.c:2566
+msgid ""
+"\n"
+"Send failed.\n"
+msgstr ""
+"\n"
+"·¢Ëͱí´ïʽʧ°Ü¡£\n"
+
+#. Let vim start normally.
+#: main.c:2571
+msgid ""
+"\n"
+"Send failed. Trying to execute locally\n"
+msgstr ""
+"\n"
+"Ëͳöʧ°Ü¡£ÊÔͼÔÚ±¾µØÖ´ÐÐ\n"
+
+#: main.c:2604 main.c:2625
+#, c-format
+msgid "%d of %d edited"
+msgstr "%d ÖÐ %d Òѱ༭"
+
+#: main.c:2648
+msgid "Send expression failed.\n"
+msgstr "·¢Ëͱí´ïʽʧ°Ü¡£\n"
+
+#: mark.c:655
+msgid "No marks set"
+msgstr "ûÓÐÉ趨±ê¼Ç (mark)"
+
+#: mark.c:657
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: ÕÒ²»µ½·ûºÏ \"%s\" µÄ±ê¼Ç(mark)"
+
+#. Highlight title
+#: mark.c:668
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"±ê¼Ç ÐкŠÁÐ Îļþ/Îı¾"
+
+#. Highlight title
+#: mark.c:706
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" Ìøµ½ ÐкŠÁÐ Îļþ/Îı¾"
+
+#: mark.c:1068
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Îļþ±ê¼Ç:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1103
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Jumplist (´Óе½¾É):\n"
+
+#: mark.c:1198
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# ÎļþÄÚÀúÊ·¼Ç¼ (´Óе½¾É):\n"
+
+#: mark.c:1281
+msgid "Missing '>'"
+msgstr "ȱÉÙ¶ÔÓ¦µÄ '>'"
+
+#: mbyte.c:395
+msgid "Not a valid codepage"
+msgstr "²»ÕýÈ·µÄ´úÂëÒ³"
+
+#: mbyte.c:3005
+msgid "E284: Cannot set IC values"
+msgstr "E284: ²»ÄÜÉ趨 IC ÊýÖµ"
+
+#: mbyte.c:3157
+msgid "E285: Failed to create input context"
+msgstr "E285: ²»ÄÜ´´½¨ÊäÈëÉÏÏÂÎÄ"
+
+#: mbyte.c:3304
+msgid "E286: Failed to open input method"
+msgstr "E286: ²»ÄÜ´ò¿ªÊäÈë·¨"
+
+#: mbyte.c:3315
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: ¾¯¸æ: ²»ÄÜÒƳý IM µÄ callback"
+
+#: mbyte.c:3321
+msgid "E288: input method doesn't support any style"
+msgstr "E288: ÊäÈë·¨²»Ö§³ÖÈκΠstyle"
+
+#: mbyte.c:3378
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: ÊäÈë·¨²»Ö§³ÖÈκΠstyle"
+
+#: mbyte.c:3452
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: over-the-spot ÐèÒª×ÖÌ弯(Fontset)"
+
+#: mbyte.c:3480
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: ÄãµÄ GTK+ ±È 1.2.3 ÀÏ¡£²»ÄÜʹÓÃ״̬Çø¡£"
+
+#: mbyte.c:3717
+msgid "E292: Input Method Server is not running"
+msgstr "E292: ÊäÈë·¨¹ÜÀí³ÌÐò(Input Method Server)δÔËÐÐ"
+
+#: memfile.c:473
+msgid "E293: block was not locked"
+msgstr "E293: ¿éδ±»Ëø¶¨"
+
+#: memfile.c:972
+msgid "E294: Seek error in swap file read"
+msgstr "E294: ½»»»Îļþ¶ÁÈ¡´íÎó"
+
+#: memfile.c:977
+msgid "E295: Read error in swap file"
+msgstr "E295: ½»»»Îļþ¶ÁÈ¡´íÎó"
+
+#: memfile.c:1029
+msgid "E296: Seek error in swap file write"
+msgstr "E296: ½»»»ÎļþдÈë´íÎó"
+
+#: memfile.c:1047
+msgid "E297: Write error in swap file"
+msgstr "E297: ½»»»ÎļþдÈë´íÎó"
+
+#: memfile.c:1244
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: ½»»»ÎļþÒѾ­´æÔÚ! (СÐÄ·ûºÅÁ¬½áµÄ°²È«Â©¶´!?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: ÕÒ²»µ½¿é 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: ÕÒ²»µ½¿é 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: ÕÒ²»µ½¿é 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: àÞàÞ, ½»»»Îļþ²»¼ûÁË!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: ²»Äܸı佻»»ÎļþµÄÃû³Æ"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: ²»ÄÜ´ò¿ª½»»»Îļþ \"%s\", ²»¿ÉÄָܻ´ÁË"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: ÕÒ²»µ½¿é 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: ÕÒ²»µ½ %s µÄ½»»»Îļþ"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "ÇëÑ¡ÔñÄãҪʹÓõĽ»»»Îļþ (°´0 Í˳ö): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: ²»ÄÜ´ò¿ª %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "²»ÄܶÁÈ¡¿é 0:"
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"¿ÉÄÜÄãû×ö¹ýÈκÎÐ޸ĻòÊÇ Vim »¹À´²»¼°¸üн»»»Îļþ."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " ²»ÄÜÔÚ±¾°æ±¾µÄ Vim ÖÐʹÓÃ.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "ʹÓà Vim 3.0¡£\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s ¿´ÆðÀ´²»ÏñÊÇ Vim ½»»»Îļþ"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " ²»ÄÜÔÚÕą̂µçÄÔÉÏʹÓÃ.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "±¾Îļþ´´½¨ÓÚ "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"»òÊÇÕâÎļþÒѱ»ÆÆ»µ¡£"
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "ʹÓý»»»Îļþ \"%s\""
+
+#: memline.c:915
+#, c-format
+msgid "Original file \"%s\""
+msgstr "Ô­Îļþ \"%s\""
+
+#: memline.c:934
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: ¾¯¸æ: ԭʼÎļþ¿ÉÄÜÒѾ­Ð޸ĹýÁË"
+
+#: memline.c:975
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: ²»ÄÜ´Ó %s ¶ÁÈ¡¿é 1"
+
+#: memline.c:979
+msgid "???MANY LINES MISSING"
+msgstr "???ȱÉÙÌ«¶àÐÐ"
+
+#: memline.c:995
+msgid "???LINE COUNT WRONG"
+msgstr "???ÐкŴíÎó"
+
+#: memline.c:1002
+msgid "???EMPTY BLOCK"
+msgstr "???¿ÕµÄ ¿é"
+
+#: memline.c:1028
+msgid "???LINES MISSING"
+msgstr "???ÕÒ²»µ½Ò»Ð©ÐÐ"
+
+#: memline.c:1060
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: ¿é 1 ID ´íÎó (%s ²»Êǽ»»»Îļþ?)"
+
+#: memline.c:1065
+msgid "???BLOCK MISSING"
+msgstr "???ÕÒ²»µ½¿é"
+
+#: memline.c:1081
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? ´ÓÕâÀïµ½ ???END µÄÄÚÈÝ¿ÉÄÜÓÐÎÊÌâ"
+
+#: memline.c:1097
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? ´ÓÕâÀïµ½ ???END µÄÄÚÈÝ¿ÉÄܱ»É¾³ý/²åÈë¹ý"
+
+#: memline.c:1117
+msgid "???END"
+msgstr "???END"
+
+#: memline.c:1143
+msgid "E311: Recovery Interrupted"
+msgstr "E311: »Ö¸´ÒÑÖжÏ"
+
+#: memline.c:1145
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: »Ö¸´Ê±·¢Éú´íÎó; Çë×¢Ò⿪ͷΪ ??? µÄÐÐ"
+
+#: memline.c:1148
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "»Ö¸´Íê³É. ÇëÈ·¶¨Ò»ÇÐÕý³£."
+
+#: memline.c:1149
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(Äã¿ÉÄÜÏëÒª°ÑÕâ¸öÎļþÁí´æΪ±ðµÄÎļþÃû£¬\n"
+
+#: memline.c:1150
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "ÔÙÖ´ÐÐ diff ÓëÔ­Îļþ±È½ÏÒÔ¼ì²éÊÇ·ñÓиıä)\n"
+
+#: memline.c:1151
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"(D)Ö±½Óɾ³ý .swp ½»»»Îļþ\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1207
+msgid "Swap files found:"
+msgstr "ÕÒµ½ÒÔϵĽ»»»Îļþ:"
+
+#: memline.c:1385
+msgid " In current directory:\n"
+msgstr " ÔÚĿǰĿ¼:\n"
+
+#: memline.c:1387
+msgid " Using specified name:\n"
+msgstr " Using specified name:\n"
+
+#: memline.c:1391
+msgid " In directory "
+msgstr " ÔÚĿ¼ "
+
+#: memline.c:1409
+msgid " -- none --\n"
+msgstr " -- ÎÞ --\n"
+
+#: memline.c:1481
+msgid " owned by: "
+msgstr " ËùÓÐÕß: "
+
+#: memline.c:1483
+msgid " dated: "
+msgstr " ÈÕÆÚ: "
+
+#: memline.c:1487 memline.c:3680
+msgid " dated: "
+msgstr " ÈÕÆÚ: "
+
+#: memline.c:1503
+msgid " [from Vim version 3.0]"
+msgstr " [´Ó Vim °æ±¾ 3.0]"
+
+#: memline.c:1507
+msgid " [does not look like a Vim swap file]"
+msgstr " [²»Ïñ Vim µÄ½»»»Îļþ]"
+
+#: memline.c:1511
+msgid " file name: "
+msgstr " ÎļþÃû: "
+
+#: memline.c:1523
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" Ð޸Ĺý: "
+
+#: memline.c:1524
+msgid "YES"
+msgstr "ÊÇ"
+
+#: memline.c:1524
+msgid "no"
+msgstr "·ñ"
+
+#: memline.c:1528
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" ̞: "
+
+#: memline.c:1535
+msgid " host name: "
+msgstr " Ö÷»úÃû: "
+
+#: memline.c:1537
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" Ö÷»úÃû: "
+
+#: memline.c:1543
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" ½ø³Ì ID: "
+
+#: memline.c:1549
+msgid " (still running)"
+msgstr " (ÕýÔÚÖ´ÐÐ)"
+
+#: memline.c:1561
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [²»ÄÜÔÚ±¾°æ±¾µÄ Vim ÉÏʹÓÃ]"
+
+#: memline.c:1564
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [²»ÄÜÔÚ±¾»úÉÏʹÓÃ]"
+
+#: memline.c:1569
+msgid " [cannot be read]"
+msgstr " [²»ÄܶÁÈ¡]"
+
+#: memline.c:1573
+msgid " [cannot be opened]"
+msgstr " [²»ÄÜ´ò¿ª]"
+
+#: memline.c:1763
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: ²»Äܱ£Áô, ²»Ê¹Óý»»»Îļþ"
+
+#: memline.c:1816
+msgid "File preserved"
+msgstr "ÎļþÒѱ£Áô"
+
+#: memline.c:1818
+msgid "E314: Preserve failed"
+msgstr "E314: ±£Áôʧ°Ü"
+
+#: memline.c:1889
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: ´íÎóµÄ lnum: %ld"
+
+#: memline.c:1915
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: ÕÒ²»µ½µÚ %ld ÐÐ"
+
+#: memline.c:2303
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: Ö¸Õë¿é id ´íÎó 3"
+
+#: memline.c:2383
+msgid "stack_idx should be 0"
+msgstr "stack_idx Ó¦¸ÃÊÇ 0"
+
+#: memline.c:2445
+msgid "E318: Updated too many blocks?"
+msgstr "E318: ¸üÐÂÌ«¶à¿é?"
+
+#: memline.c:2602
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: Ö¸Õë¿é id ´íÎó 4"
+
+#: memline.c:2629
+msgid "deleted block 1?"
+msgstr "ɾ³ý¿é 1?"
+
+#: memline.c:2829
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: ÕÒ²»µ½µÚ %ld ÐÐ"
+
+#: memline.c:3072
+msgid "E317: pointer block id wrong"
+msgstr "E317: Ö¸Õë¿é id ´íÎó"
+
+#: memline.c:3088
+msgid "pe_line_count is zero"
+msgstr "pe_line_count ΪÁã"
+
+#: memline.c:3117
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: Ðкų¬³ö·¶Î§: %ld ³¬¹ý½áβ"
+
+#: memline.c:3121
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: ¿é %ld ÐÐÊý´íÎó"
+
+#: memline.c:3170
+msgid "Stack size increases"
+msgstr "¶ÑÕ»´óСÔö¼Ó"
+
+#: memline.c:3216
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: Ö¸Õë¿é id ´í 2"
+
+#: memline.c:3670
+msgid "E325: ATTENTION"
+msgstr "E325: ×¢Òâ"
+
+#: memline.c:3671
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"·¢ÏÖ½»»»Îļþ \""
+
+#: memline.c:3675
+msgid "While opening file \""
+msgstr "µ±´ò¿ªÎļþʱ \""
+
+#: memline.c:3684
+msgid " NEWER than swap file!\n"
+msgstr " ±È½»»»ÎļþÐÂ!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3688
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) ¿ÉÄÜÓÐÁíÒ»¸ö³ÌÐòÒ²Ôڱ༭ͬһ¸öÎļþ.\n"
+" Èç¹ûÊÇÕâÑù£¬Çë×¢Òâ²»ÒªÒ»ÆðдÈ룬²»È»ÄãµÄŬÁ¦¶¼»á¸¶ÖÁ÷¡£\n"
+
+#: memline.c:3689
+msgid " Quit, or continue with caution.\n"
+msgstr " Í˳ö£¬»òÊǼÌÐø±à¼­¡£\n"
+
+#: memline.c:3690
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) ÉÏÒ»´Î±à¼­´ËÎļþʱ±ÀÀ£\n"
+
+#: memline.c:3691
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " Èç¹ûÊÇÕâÑù, ÇëÓà \":recover\" »ò \"vim -r"
+
+#: memline.c:3693
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" »Ö¸´ÐÞ¸ÄÄÚÈÝ (½øÒ»²½ËµÃ÷Çë¿´ \":help recovery\").\n"
+
+#: memline.c:3694
+msgid " If you did this already, delete the swap file \""
+msgstr " Èç¹û¸Ã»Ö¸´µÄ¶¼ÒѾ­»Ö¸´ÁË, ÇëÖ±½Óɾ³ý´Ë½»»»Îļþ \""
+
+#: memline.c:3696
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" ÒÔ±ÜÃâÔÙ¿´µ½´ËÐÅÏ¢.\n"
+
+#: memline.c:3710 memline.c:3714
+msgid "Swap file \""
+msgstr "½»»»Îļþ \""
+
+#: memline.c:3711 memline.c:3717
+msgid "\" already exists!"
+msgstr "\" ÒѾ­´æÔÚÁË!"
+
+#: memline.c:3720
+msgid "VIM - ATTENTION"
+msgstr "VIM - ×¢Òâ"
+
+#: memline.c:3722
+msgid "Swap file already exists!"
+msgstr "½»»»ÎļþÒѾ­´æÔÚ!"
+
+#: memline.c:3726
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"ÒÔÖ»¶Á·½Ê½´ò¿ª(&O)\n"
+"Ö±½Ó±à¼­(&E)\n"
+"»Ö¸´(&R)\n"
+"Í˳ö(&Q)"
+
+#: memline.c:3728
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"ÒÔÖ»¶Á·½Ê½´ò¿ª(&O)\n"
+"Ö±½Ó±à¼­(&E)\n"
+"»Ö¸´(&R)\n"
+"Í˳ö(&Q)\n"
+"ɾ³ý½»»»Îļþ(&D)"
+
+#: memline.c:3781
+msgid "E326: Too many swap files found"
+msgstr "E326: ÕÒµ½Ì«¶à½»»»Îļþ"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: ²¿·Ý²Ëµ¥Ïî²»ÊÇ×Ӳ˵¥"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: ²Ëµ¥Ö»ÄÜÔÚÆäËüģʽÖÐʹÓÃ"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: ûÓÐÄÇÑùµÄ²Ëµ¥"
+
+#: menu.c:503
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: ²Ëµ¥²»ÄÜÖ¸Ïò×ÓÑ¡µ¥"
+
+#: menu.c:542
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: ²»ÄÜÖ±½Ó°Ñ²Ëµ¥Ïî¼Óµ½²Ëµ¥ÌõÖÐ"
+
+#: menu.c:548
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: ·Ö¸ôÏß²»ÄÜÊDz˵¥µÄÒ»²¿·Ö"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1063
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- ²Ëµ¥ ---"
+
+#: menu.c:1989
+msgid "Tear off this menu"
+msgstr "ÇÐÏ´˲˵¥"
+
+#: menu.c:2054
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: ²Ëµ¥±ØÐèÖ¸ÏòÒ»¸ö²Ëµ¥Ïî"
+
+#: menu.c:2074
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: [²Ëµ¥] ÕÒ²»µ½ %s"
+
+#: menu.c:2143
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: %s ģʽ䶨Òå²Ëµ¥"
+
+#: menu.c:2181
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: ²Ëµ¥±ØÐèÖ¸Ïò×Ӳ˵¥"
+
+#: menu.c:2202
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: ÕÒ²»µ½²Ëµ¥ - Çë¼ì²é²Ëµ¥Ãû³Æ"
+
+#: message.c:467
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "´¦Àí %s ʱ·¢Éú´íÎó:"
+
+#: message.c:483
+#, c-format
+msgid "line %4ld:"
+msgstr "ÐÐ %4ld:"
+
+#: message.c:523
+msgid "[string too long]"
+msgstr "[×Ö·û´®Ì«³¤]"
+
+#: message.c:669
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr "¼òÌåÖÐÎÄÐÅϢά»¤Õß: Wang Jun <junw@turbolinux.com.cn>"
+
+#: message.c:881
+msgid "Interrupt: "
+msgstr "ÒÑÖжÏ: "
+
+#: message.c:884
+msgid "Hit ENTER to continue"
+msgstr "Çë°´ ENTER ¼ÌÐø"
+
+#: message.c:886
+msgid "Hit ENTER or type command to continue"
+msgstr "Çë°´ ENTER »òÆäËüÃüÁî¼ÌÐø"
+
+#: message.c:1940
+msgid "-- More --"
+msgstr "-- ¸ü¶à --"
+
+#: message.c:1943
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: ÏòÏÂ/ÏòÉÏÒ»ÐÐ, ¿Õ¸ñ/b: Ò»Ò³, d/u: °ëÒ³, q: Í˳ö)"
+
+#: message.c:1944
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: ÏòÏÂÒ»ÐÐ, ¿Õ°×¼ü: Ò»Ò³, d: °ëÒ³, q: Í˳ö)"
+
+#: message.c:2419 message.c:2434
+msgid "Question"
+msgstr "ÎÊÌâ"
+
+#: message.c:2421
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&YÊÇ\n"
+"&N·ñ"
+
+#: message.c:2436
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&YÊÇ\n"
+"&N·ñ\n"
+"&CÈ¡Ïû"
+
+#: message.c:2454
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&YÊÇ\n"
+"&N·ñ\n"
+"&AÈ«²¿±£´æ\n"
+"&DÈ«²¿²»´æ\n"
+"&CÈ¡Ïû"
+
+#: message.c:2494
+msgid "Save File dialog"
+msgstr "±£´æÎļþ¶Ô»°¿ò"
+
+#: message.c:2496
+msgid "Open File dialog"
+msgstr "´ò¿ªÎļþ¶Ô»°¿ò"
+
+#. TODO: non-GUI file selector here
+#: message.c:2547
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: Ö÷¿Ø̨(Console)ģʽʱûÓÐÎļþä¯ÀÀÆ÷(file browser)"
+
+#: misc1.c:2449
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: ×¢Òâ: ÄãÕýÔÚÐÞ¸ÄÒ»¸öÖ»¶ÁÎļþ"
+
+#: misc1.c:2678
+msgid "1 more line"
+msgstr "»¹ÓÐÒ»ÐÐ"
+
+#: misc1.c:2680
+msgid "1 line less"
+msgstr "ÉÙÓÚÒ»ÐÐ"
+
+#: misc1.c:2685
+#, c-format
+msgid "%ld more lines"
+msgstr " »¹ÓÐ %ld ÐÐ"
+
+#: misc1.c:2687
+#, c-format
+msgid "%ld fewer lines"
+msgstr "ֻʣ %ld ÐÐ"
+
+#: misc1.c:2690
+msgid " (Interrupted)"
+msgstr " (ÒÑÖжÏ)"
+
+#: misc1.c:6244
+msgid "Vim: preserving files...\n"
+msgstr "Vim: ±£ÁôÎļþÖÐ...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6254
+msgid "Vim: Finished.\n"
+msgstr "Vim: ½áÊø.\n"
+
+#: misc2.c:644 misc2.c:660
+msgid "ERROR: "
+msgstr "´íÎó: "
+
+#: misc2.c:664
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bytes] È«²¿ alloc-freed %lu-%lu, ʹÓÃÖÐ %lu, peak ʹÓà %lu\n"
+
+#: misc2.c:666
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[µ÷ÓÃ] È«²¿ re/malloc(): %lu, È«²¿ free()': %lu\n"
+"\n"
+
+#: misc2.c:721
+msgid "E340: Line is becoming too long"
+msgstr "E340: ´ËÐйý³¤"
+
+#: misc2.c:765
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: ÄÚ²¿´íÎó: lalloc(%ld, )"
+
+#: misc2.c:873
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: ÄÚ´æ²»×ã! (³¢ÊÔÅäÖà %lu ×Ö½Ú×é)"
+
+#: misc2.c:2508
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "µ÷ÓÃ shell Ö´ÐÐ: \"%s\""
+
+#: misc2.c:2703 misc2.c:5142 option.c:4584
+msgid "Missing colon"
+msgstr "ȱÉÙðºÅ"
+
+#: misc2.c:2705 misc2.c:2732
+msgid "Illegal mode"
+msgstr "²»ÕýÈ·µÄģʽ"
+
+#: misc2.c:2771
+msgid "Illegal mouseshape"
+msgstr "²»ÕýÈ·µÄÊó±êÐÎ×´"
+
+#: misc2.c:2811 misc2.c:5162
+msgid "digit expected"
+msgstr "Ó¦¸ÃΪÊý×Ö"
+
+#: misc2.c:2816
+msgid "Illegal percentage"
+msgstr "²»ÕýÈ·µÄ°Ù·Ö±È"
+
+#: misc2.c:3120
+msgid "Enter encryption key: "
+msgstr "ÊäÈëÃÜÂë: "
+
+#: misc2.c:3121
+msgid "Enter same key again: "
+msgstr "ÇëÔÙÊäÈëÒ»´Î: "
+
+#: misc2.c:3131
+msgid "Keys don't match!"
+msgstr "Á½´ÎÊäÈëÃÜÂ벻ͬ!"
+
+#: misc2.c:3645
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr "E343: ²»ÕýÈ·µÄ·¾¶: '**[number]' ±ØÐèÒªÔÚ·¾¶½áβ»òÒª½ÓÖø '%s'"
+
+#: misc2.c:4899
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: cdpath ÖÐûÓÐĿ¼ \"%s\""
+
+#: misc2.c:4902
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: ÔÚ·¾¶ÖÐÕÒ²»µ½Îļþ \"%s\""
+
+#: misc2.c:4908
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: ÔÚ·¾¶ÖÐÕÒ²»µ½¸ü¶àµÄÎļþ \"%s\""
+
+#: misc2.c:4911
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: ÔÚ·¾¶ÖÐÕÒ²»µ½¸ü¶àµÄÎļþ \"%s\""
+
+#: misc2.c:5154
+msgid "Illegal component"
+msgstr "²»ÕýÈ·µÄ×é¼þ"
+
+#: normal.c:2798
+msgid "Warning: terminal cannot highlight"
+msgstr "×¢Òâ: ÄãµÄÖն˲»ÄÜÏÔʾ¸ßÁÁ¶È"
+
+#: normal.c:2993
+msgid "E348: No string under cursor"
+msgstr "E348: ¹â±ê´¦Ã»ÓÐ×Ö·û´®"
+
+#: normal.c:2995
+msgid "E349: No identifier under cursor"
+msgstr "E349: ¹â±ê´¦Ã»ÓÐʶ±ð×Ö"
+
+#: normal.c:4160
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: ²»ÄÜÔÚÄ¿Ç°µÄ 'foldmethod' ÏÂɾ³ý fold"
+
+#: ops.c:271
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "Ò»ÐÐ %s ¹ý Ò»´Î"
+
+#: ops.c:273
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "Ò»ÐÐ %s ¹ý %d ´Î"
+
+#: ops.c:278
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld ÐÐ %s ¹ý Ò»´Î"
+
+#: ops.c:281
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld ÐÐ %s ¹ý %d ´Î"
+
+#: ops.c:638
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "ʶ±ð %ld ÐÐ..."
+
+#: ops.c:688
+msgid "1 line indented "
+msgstr "Ò»ÐÐÒÑʶ±ð"
+
+#: ops.c:690
+#, c-format
+msgid "%ld lines indented "
+msgstr "ÒÑʶ±ð %ld ÐÐ"
+
+#. must display the prompt
+#: ops.c:1528
+msgid "cannot yank; delete anyway"
+msgstr "²»Äܸ´ÖÆ; Ö±½Óɾ³ý"
+
+#: ops.c:2018
+msgid "1 line changed"
+msgstr " 1 ÐÐ ~ed"
+
+#: ops.c:2020
+#, c-format
+msgid "%ld lines changed"
+msgstr " %ld ÐÐ ~ed"
+
+#: ops.c:2381
+#, c-format
+msgid "freeing %ld lines"
+msgstr "ÊÍ·Å %ld ÐÐÖÐ"
+
+#: ops.c:2658
+msgid "1 line yanked"
+msgstr "ÒѸ´ÖÆ 1 ÐÐ"
+
+#: ops.c:2660
+#, c-format
+msgid "%ld lines yanked"
+msgstr "ÒѸ´ÖÆ %ld ÐÐ"
+
+#: ops.c:2916
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: ¼Ä´æÆ÷ %s ÀïûÓж«Î÷"
+
+#. Highlight title
+#: ops.c:3454
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- ¼Ä´æÆ÷ ---"
+
+#: ops.c:4565
+msgid "Illegal register name"
+msgstr "²»ÕýÈ·µÄ¼Ä´æÆ÷Ãû³Æ"
+
+#: ops.c:4645
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# ¼Ä´æÆ÷:\n"
+
+#: ops.c:4671
+#, c-format
+msgid "Unknown register type %d"
+msgstr "δ֪µÄ×¢²áÀàÐÍ: %d"
+
+#: ops.c:5052
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: ¼Ä´æÆ÷Ãû³Æ´íÎó: '%s'"
+
+#: ops.c:5393
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld ÁÐ; "
+
+#: ops.c:5400
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "Ñ¡ÔñÁË %s%ld/%ld ÐÐ; %ld/%ld ×Ö(Word); %ld/%ld ×Ö·û(Bytes)"
+
+#: ops.c:5416
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "ÁÐ %s/%s; ÐÐ %ld/%ld; ×Ö(Word) %ld/%ld; ×Ö·û(Byte) %ld/%ld"
+
+#: ops.c:5427
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld for BOM)"
+
+#: option.c:1989
+msgid "Thanks for flying Vim"
+msgstr "¸ÐлÄúÑ¡Ôñ Vim"
+
+#: option.c:3175
+msgid "Option not supported"
+msgstr "²»Ö§³Ö¸ÃÑ¡Ïî"
+
+#: option.c:3200
+msgid "Not allowed in a modeline"
+msgstr "²»ÄÜÔÚģʽÐÐÀï³öÏÖ"
+
+#: option.c:3256
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\tµ±Ç°ÉèÖÃ: "
+
+#: option.c:3395
+msgid "Number required after ="
+msgstr "= ºóÐèÒªÓÐÊý×Ö"
+
+#: option.c:3702 option.c:4309
+msgid "Not found in termcap"
+msgstr "Termcap ÀïÃæÕÒ²»µ½"
+
+#: option.c:3768
+#, c-format
+msgid "Illegal character <%s>"
+msgstr "²»ÕýÈ·µÄ×Ö·û <%s>"
+
+#: option.c:4294 option.c:5497
+msgid "Not allowed here"
+msgstr "ÕâÀï²»¿ÉʹÓÃ"
+
+#: option.c:4301
+msgid "Cannot set 'term' to empty string"
+msgstr "²»ÄÜÉ趨 'term' Ϊ¿Õ×Ö·û´®"
+
+#: option.c:4304
+msgid "Cannot change term in GUI"
+msgstr "ÔÚͼÐͽçÃæÖв»ÄÜÇл»ÖÕ¶Ë"
+
+#: option.c:4306
+msgid "Use \":gui\" to start the GUI"
+msgstr "ÊäÈë \":gui\" À´Æô¶¯Í¼ÐνçÃæ"
+
+#: option.c:4327
+msgid "'backupext' and 'patchmode' are equal"
+msgstr "'backupext' ¸ú 'patchmode' ÊÇÒ»ÑùµÄ"
+
+#: option.c:4586
+msgid "Zero length string"
+msgstr "Á㳤¶È×Ö·û´®"
+
+#: option.c:4654
+#, c-format
+msgid "Missing number after <%s>"
+msgstr "<%s> ºóȱÉÙÊý×Ö"
+
+#: option.c:4668
+msgid "Missing comma"
+msgstr "ȱÉÙ¶ººÅ"
+
+#: option.c:4675
+msgid "Must specify a ' value"
+msgstr "±ØÐèÖ¸¶¨Ò»¸ö ' Öµ"
+
+#: option.c:4715
+msgid "contains unprintable character"
+msgstr "°üº¬²»ÄÜÏÔʾµÄ×Ö·û"
+
+#: option.c:4728
+msgid "Invalid font(s)"
+msgstr "²»ÕýÈ·µÄ×ÖÌå"
+
+#: option.c:4734
+msgid "can't select fontset"
+msgstr "²»ÄÜʹÓÃ×ÖÌ弯(Fontset)"
+
+#: option.c:4736
+msgid "Invalid fontset"
+msgstr "²»ÕýÈ·µÄ×ÖÌ弯(Fontset)"
+
+#: option.c:4743
+msgid "can't select wide font"
+msgstr "²»ÄÜʹÓÃÉ趨µÄ¿í×ÖÌå(Widefont)"
+
+#: option.c:4745
+msgid "Invalid wide font"
+msgstr "²»ÕýÈ·µÄ¿í×ÖÌå(Widefont)"
+
+#: option.c:5014
+#, c-format
+msgid "Illegal character after <%c>"
+msgstr "<%c> ºóÓв»ÕýÈ·µÄ×Ö·û"
+
+#: option.c:5097
+msgid "comma required"
+msgstr "ÐèÒª¶ººÅ"
+
+#: option.c:5106
+#, c-format
+msgid "'commentstring' must be empty or contain %s"
+msgstr "'commentstring' ±ØÐèÊÇ¿Õ°×»ò°üº¬ %s"
+
+#: option.c:5153
+msgid "No mouse support"
+msgstr "²»Ö§³ÖÊó±ê"
+
+#: option.c:5399
+msgid "Unclosed expression sequence"
+msgstr "ûÓнáÊøµÄ±í´ïʽ: "
+
+#: option.c:5403
+msgid "too many items"
+msgstr "Ì«¶à¶ÔÏó"
+
+#: option.c:5405
+msgid "unbalanced groups"
+msgstr "²»¶Ô³ÆµÄ×é"
+
+#: option.c:5620
+msgid "A preview window already exists"
+msgstr "Ô¤ÀÀ´°¿ÚÒѾ­´æÔÚÁË"
+
+#: option.c:5881 option.c:5910
+msgid "'winheight' cannot be smaller than 'winminheight'"
+msgstr "'winheight' ²»ÄÜ±È 'winminheight' ¸üÉÙ"
+
+#: option.c:5926 option.c:5945
+msgid "'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "'winwidth' ²»ÄÜ±È 'winminwidth' ¸üÉÙ"
+
+#: option.c:6085
+#, c-format
+msgid "Need at least %d lines"
+msgstr "ÖÁÉÙÐèÒª %d ÐÐ"
+
+#: option.c:6094
+#, c-format
+msgid "Need at least %d columns"
+msgstr "ÖÁÉÙÐèÒª %d ÁÐ"
+
+#: option.c:6391
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: ²»ÕýÈ·µÄÑ¡Ïî: %s"
+
+#: option.c:6500
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- Öն˱àÂë ---"
+
+#: option.c:6502
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- È«¾Ö Ñ¡ÏîÖµ ---"
+
+#: option.c:6504
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- ±¾µØ Ñ¡ÏîÖµ ---"
+
+#: option.c:6506
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- Ñ¡Ïî ---"
+
+#: option.c:7196
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp ´íÎó"
+
+#: option.c:8112
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': ÕÒ²»µ½ %s ¶ÔÓ¦µÄ×Ö·û"
+
+#: option.c:8146
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': ·ÖºÅºóÓжàÓàµÄ×Ö·û: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "²»ÄÜ´ò¿ª"
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: ²»ÄÜ´ò¿ª´°¿Ú!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "ÐèÒª Amigados °æ±¾ 2.04 ÒÔÉÏ\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "ÐèÒª %s °æ±¾ %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "²»ÄÜ´ò¿ª NIL:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr "²»ÄÜ´´½¨ "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim ·µ»ØÖµ: %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "²»ÄÜÇл»Ö÷¿Ø̨(console)ģʽ !?\n"
+
+#: os_amiga.c:938 os_mac.c:1168 os_mswin.c:619 os_riscos.c:728 os_unix.c:2726
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: ²»Ö§³ÖÉ趨ÆÁĻģʽ"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: ²»ÊÇÖ÷¿Ø̨(console)??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1142
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: ²»ÄÜÓà -f Ñ¡ÏîÖ´ÐÐ shell"
+
+#: os_amiga.c:1183 os_amiga.c:1273
+msgid "Cannot execute "
+msgstr "²»ÄÜÖ´ÐÐ "
+
+#: os_amiga.c:1186 os_amiga.c:1283
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1206 os_amiga.c:1308
+msgid " returned\n"
+msgstr " ÒÑ·µ»Ø\n"
+
+#: os_amiga.c:1448
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE ̫С"
+
+#: os_amiga.c:1452
+msgid "I/O ERROR"
+msgstr "I/O ´íÎó"
+
+#: os_mswin.c:503
+msgid "...(truncated)"
+msgstr ""
+
+#: os_mswin.c:594
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' ²»ÊÇ 80, ²»ÄÜÖ´ÐÐÍⲿÃüÁî"
+
+#: os_mswin.c:706 os_unix.c:4945
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: µ÷Óú¯Êý¿â \"%s\"() ʧ°Ü"
+
+#: os_mswin.c:1340
+msgid "E237: Printer selection failed"
+msgstr "E237: ²»ÄÜÑ¡Ôñ´Ë´òÓ¡»ú"
+
+#: os_mswin.c:1388
+#, c-format
+msgid "to %s on %s"
+msgstr "´Ó %s µ½ %s"
+
+#: os_mswin.c:1449 os_mswin.c:1459
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: ´òÓ¡´íÎó: %s"
+
+#: os_mswin.c:1459
+msgid "Unknown"
+msgstr "δ֪"
+
+#: os_mswin.c:1486
+#, c-format
+msgid "Printing '%s'"
+msgstr "ÒÑ´òÓ¡: '%s'"
+
+#: os_mswin.c:2550
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: ×Ö·û¼¯ \"%s\" ²»ÄܶÔÓ¦×ÖÌå\"%s\""
+
+#: os_mswin.c:2558
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: ²»ÕýÈ·µÄ×Ö·û '%c' ³öÏÖÔÚ×ÖÌåÃû³Æ \"%s\" ÄÚ"
+
+#: os_riscos.c:1227
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: ²»ÕýÈ·µÄ 'filetype' Ñ¡Ïî - ʹÓô¿ÎÄ×Öģʽ"
+
+#: os_unix.c:800
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: Ë«ÖØÐźÅ, Í˳öÖÐ\n"
+
+#: os_unix.c:806
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: CVim: À¹½Øµ½ÐźÅ(signal) %s\n"
+
+#: os_unix.c:809
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: À¹½Øµ½ÖÂÃüµÄÐźÅ(deadly signale)\n"
+
+#: os_unix.c:1063
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "´ò¿ª X Window ÓÃʱ %ld Ãë"
+
+#: os_unix.c:1090
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: X ´íÎó\n"
+
+#: os_unix.c:1157
+msgid "Testing the X display failed"
+msgstr "²âÊÔ X Window ʧ°Ü"
+
+#: os_unix.c:1301
+msgid "Opening the X display timed out"
+msgstr "´ò¿ª X Window ³¬Ê±"
+
+#: os_unix.c:2899 os_unix.c:3483
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"²»ÄÜÖ´ÐÐ shell"
+
+#: os_unix.c:2944
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"²»ÄÜÖ´ÐÐ shell sh\n"
+
+#: os_unix.c:2948 os_unix.c:3489
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"Shell ÒÑ·µ»Ø"
+
+#: os_unix.c:3082
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"²»Äܽ¨Á¢¹ÜµÀ\n"
+
+#: os_unix.c:3097
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"²»ÄÜ fork\n"
+
+#: os_unix.c:3496
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"ÃüÁîÒѽáÊø\n"
+
+#: os_unix.c:4993
+msgid "Opening the X display failed"
+msgstr "´ò¿ª X Window ʧ°Ü"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "ÔÚÐкŠ"
+
+#: os_w32exe.c:169
+msgid "Could not load vim32.dll!"
+msgstr "²»ÄܼÓÔØ vim32.dll£¡"
+
+#: os_w32exe.c:169 os_w32exe.c:179
+msgid "VIM Error"
+msgstr "VIM ´íÎó"
+
+#: os_w32exe.c:179
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "²»ÄÜÐÞÕýº¯ÊýÖ¸Õëµ½ DLL!"
+
+#: os_win16.c:578 os_win32.c:3019
+#, c-format
+msgid "shell returned %d"
+msgstr "Shell ·µ»ØÖµ %d"
+
+#: os_win32.c:2489
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: À¹½Øµ½ %s ʼþ\n"
+
+#: os_win32.c:2491
+msgid "close"
+msgstr "¹Ø±Õ"
+
+#: os_win32.c:2493
+msgid "logoff"
+msgstr "×¢Ïû"
+
+#: os_win32.c:2494
+msgid "shutdown"
+msgstr "¹Ø»ú"
+
+#: os_win32.c:2975
+msgid "E371: Command not found"
+msgstr "E371: ÕÒ²»µ½ÃüÁî"
+
+#: os_win32.c:2988
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"ÔÚÄãµÄ $PATH ÖÐÕÒ²»µ½ VIMRUN.EXE.\n"
+"ÍⲿÃüÁîÖ´ÐÐÍê±Ïºó½«²»»áÔÝÍ£.\n"
+"½øÒ»²½ËµÃ÷ÇëÖ´ÐÐ :help win32-vimrun "
+
+#: os_win32.c:2991
+msgid "Vim Warning"
+msgstr "Vim ¾¯¸æ"
+
+#: quickfix.c:281
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: ¸ñʽ»¯×Ö·û´®ÀïÓÐÌ«¶à %%%c "
+
+#: quickfix.c:294
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: ¸ñʽ»¯×Ö·û´®²»Ó¦¸Ã³öÏÖ %%%c "
+
+#: quickfix.c:348
+msgid "E374: Missing ] in format string"
+msgstr "E374: ¸ñʽ»¯×Ö·û´®ÀïÉÙÁË ]"
+
+#: quickfix.c:362
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: ¸ñʽ»¯×Ö·û´®ÀïÓв»Ö§³ÖµÄ %%%c "
+
+#: quickfix.c:380
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: ¸ñʽ»¯×Ö·û´®¿ªÍ·ÀïÓв»ÕýÈ·µÄ %%%c "
+
+#: quickfix.c:388
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: ¸ñʽ»¯×Ö·û´®ÀïÓв»ÕýÈ·µÄ %%%c "
+
+#: quickfix.c:414
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' δÉ趨"
+
+#: quickfix.c:520
+msgid "E379: Missing or empty directory name"
+msgstr "E379: ÕÒ²»µ½Ä¿Â¼Ãû³Æ»òÊÇ¿ÕµÄĿ¼Ãû³Æ"
+
+#: quickfix.c:931
+msgid "No more items"
+msgstr "ûÓÐÆäËü¶ÔÏó"
+
+#: quickfix.c:1152
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d / %d)%s%s: "
+
+#: quickfix.c:1154
+msgid " (line deleted)"
+msgstr " (ÐÐÒÑɾ³ý)"
+
+#: quickfix.c:1360
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Quickfix ¶ÑÕ»½áβ"
+
+#: quickfix.c:1369
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Quickfix ¶ÑÕ»¶¥¶Ë"
+
+#: quickfix.c:1381
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "´íÎóÁбí %d/%d; ¹²ÓÐ %d Ïî´íÎó"
+
+#: quickfix.c:1842
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: ²»ÄÜдÈ룬'buftype' Ñ¡ÏîÒÑÉ趨"
+
+#: regexp.c:801
+msgid "E339: Pattern too long"
+msgstr "E339: Ãû×ÖÌ«³¤"
+
+#: regexp.c:1315
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: ³²×´ %s*"
+
+#: regexp.c:1318
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: ³²×´ %s%c"
+
+#: regexp.c:1467
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c ûÓнӶ«Î÷"
+
+#: regexp.c:2469
+#, c-format
+msgid "Syntax error in %s{...}"
+msgstr "Óï·¨´íÎó: %s{...}"
+
+#: regexp.c:2716
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: ²»ÄÜÖ´ÐÐ; regular expression Ì«¸´ÔÓ?"
+
+#: regexp.c:2851
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: regular expression Ôì³É¶ÑÕ»ÓùâµÄ´íÎó"
+
+#: regexp.c:3087
+msgid "External submatches:\n"
+msgstr "Íⲿ·ûºÏ:\n"
+
+#: screen.c:2051
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--ÒÑ fold %3ld ÐÐ"
+
+#: screen.c:7411
+msgid " VREPLACE"
+msgstr " V-Ìæ»»"
+
+#: screen.c:7415
+msgid " REPLACE"
+msgstr " Ìæ»»"
+
+#: screen.c:7420
+msgid " REVERSE"
+msgstr " ·´×ª"
+
+#: screen.c:7422
+msgid " INSERT"
+msgstr " ²åÈë"
+
+#: screen.c:7425
+msgid " (insert)"
+msgstr " (²åÈë)"
+
+#: screen.c:7427
+msgid " (replace)"
+msgstr " (Ìæ»»)"
+
+#: screen.c:7429
+msgid " (vreplace)"
+msgstr " (v-Ìæ»»)"
+
+#: screen.c:7432
+msgid " Hebrew"
+msgstr " Ï£²®À³"
+
+#: screen.c:7440
+msgid " (lang)"
+msgstr " (ÓïÑÔ)"
+
+#: screen.c:7443
+msgid " (paste)"
+msgstr " (Õ³Ìû)"
+
+#: screen.c:7449
+msgid " SELECT"
+msgstr " Ñ¡È¡"
+
+#: screen.c:7451
+msgid " VISUAL"
+msgstr " ¿ÉÊÓ"
+
+#: screen.c:7453
+msgid " BLOCK"
+msgstr " ¿é"
+
+#: screen.c:7455
+msgid " LINE"
+msgstr " ÐÐ"
+
+#: screen.c:7468 screen.c:7522
+msgid "recording"
+msgstr "¼Ç¼ÖÐ"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "ÒѲéÕÒµ½Îļþ¿ªÍ·£»ÔÙ´Ó½áβ¼ÌÐø²éÕÒ"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "ÒѲéÕÒµ½Îļþ½áβ£»ÔÙ´Ó¿ªÍ·¼ÌÐø²éÕÒ"
+
+#: search.c:440
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: ´íÎóµÄ²éÕÒ×Ö·û´®: %s"
+
+#: search.c:747
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: ÒѲéÕÒµ½Îļþ¿ªÍ·ÈÔÕÒ²»µ½ %s"
+
+#: search.c:749
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: ÒѲéÕÒµ½Îļþ½áβÈÔÕÒ²»µ½ %s"
+
+#: search.c:1107
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: ÔÚ ';' ºóÃæÓ¦¸ÃÓÐ '?' »ò '/'"
+
+#: search.c:3476
+msgid " (includes previously listed match)"
+msgstr " (°üÀ¨ÉÏ´ÎÁгö·ûºÏÏî)"
+
+#. cursor at status line
+#: search.c:3496
+msgid "--- Included files "
+msgstr "--- °üº¬Îļþ "
+
+#: search.c:3498
+msgid "not found "
+msgstr "ÕÒ²»µ½ "
+
+#: search.c:3499
+msgid "in path ---\n"
+msgstr "ÔÚ·¾¶ ---\n"
+
+#: search.c:3538
+msgid " (Already listed)"
+msgstr " (ÒÑÁгö)"
+
+#: search.c:3540
+msgid " NOT FOUND"
+msgstr " ÕÒ²»µ½"
+
+#: search.c:3592
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "²éÕÒ°üº¬Îļþ: %s"
+
+#: search.c:3810
+msgid "E387: Match is on current line"
+msgstr "E387: µ±Ç°ÐÐÆ¥Åä"
+
+#: search.c:3950
+msgid "All included files were found"
+msgstr "ËùÓаüº¬Îļþ¶¼ÒÑÕÒµ½"
+
+#: search.c:3952
+msgid "No included files"
+msgstr "ûÓаüº¬Îļþ"
+
+#: search.c:3968
+msgid "E388: Couldn't find definition"
+msgstr "E388: ÕÒ²»µ½¶¨Òå"
+
+#: search.c:3970
+msgid "E389: Couldn't find pattern"
+msgstr "E389: ÕÒ²»µ½ pattern"
+
+#: syntax.c:2990
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: ²ÎÊý²»ÕýÈ·: %s"
+
+#: syntax.c:3167
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: ÎÞ´ËÓï·¨ cluster: \"%s\""
+
+#: syntax.c:3331
+msgid "No Syntax items defined for this buffer"
+msgstr "Õâ¸ö»º³åÇøûÓж¨ÒåÈκÎÓï·¨Ïî"
+
+#: syntax.c:3339
+msgid "syncing on C-style comments"
+msgstr "C·ç¸ñ×¢ÊÍͬ²½ÖÐ"
+
+#: syntax.c:3347
+msgid "no syncing"
+msgstr "ûÓÐͬ²½"
+
+#: syntax.c:3350
+msgid "syncing starts "
+msgstr "ͬ²½¿ªÊ¼"
+
+#: syntax.c:3352 syntax.c:3421
+msgid " lines before top line"
+msgstr "Ðкų¬³ö·¶Î§"
+
+#: syntax.c:3356
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- Ó﷨ͬ²½ÏîÄ¿ (Syntax sync items) ---"
+
+#: syntax.c:3359
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"ͬ²½ÖÐ:"
+
+#: syntax.c:3364
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- Óï·¨ÏîÄ¿ ---"
+
+#: syntax.c:3387
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: ÎÞ´ËÓï·¨ cluster: \"%s\""
+
+#: syntax.c:3411
+msgid "minimal "
+msgstr "×îС"
+
+#: syntax.c:3418
+msgid "maximal "
+msgstr "×î´ó"
+
+#: syntax.c:4046
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: ʹÓÃÁ˲»ÕýÈ·µÄ²ÎÊý"
+
+#: syntax.c:4070
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: ÕÒ²»µ½ %s µÄ region item"
+
+#: syntax.c:4098
+msgid "E395: contains argument not accepted here"
+msgstr "E395: ʹÓÃÁ˲»ÕýÈ·µÄ²ÎÊý"
+
+#: syntax.c:4109
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: ʹÓÃÁ˲»ÕýÈ·µÄ²ÎÊý"
+
+#: syntax.c:4187
+msgid "E397: Filename required"
+msgstr "E397: ÐèÒªÎļþÃû³Æ"
+
+#: syntax.c:4523
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: ȱÉÙ \"=\": %s"
+
+#: syntax.c:4679
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: syntax region %s µÄ²ÎÊýÌ«ÉÙ"
+
+#: syntax.c:5010
+msgid "E400: No cluster specified"
+msgstr "E400: ûÓÐÖ¸¶¨µÄÊôÐÔ"
+
+#: syntax.c:5047
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: ÕÒ²»µ½·Ö¸ô·ûºÅ: %s"
+
+#: syntax.c:5122
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: '%s' ºóÃæµÄ¶«Î÷²»ÄÜʶ±ð"
+
+#: syntax.c:5204
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: Ó﷨ͬ²½: Á¬½ÓÐзûºÅÖ¸¶¨ÁËÁ½´Î"
+
+#: syntax.c:5261
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: ²ÎÊý²»ÕýÈ·: %s"
+
+#: syntax.c:5311
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: ȱÉٵȺÅ: %s"
+
+#: syntax.c:5317
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: ¿Õ²ÎÊý: %s"
+
+#: syntax.c:5344
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s ²»ÄÜÔڴ˳öÏÖ"
+
+#: syntax.c:5351
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s ±ØÐëÊÇÁбíÀïµÄµÚÒ»¸ö"
+
+#: syntax.c:5421
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: ²»ÕýÈ·µÄ×éÃû: %s"
+
+#: syntax.c:5644
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: ²»ÕýÈ·µÄ :syntax ×ÓÃüÁî: %s"
+
+#: syntax.c:6023
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: ÕÒ²»µ½ highlight group: %s"
+
+#: syntax.c:6047
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: ²ÎÊýÌ«ÉÙ: \":highlight link %s\""
+
+#: syntax.c:6054
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: ²ÎÊý¹ý¶à: \":highlight link %s\""
+
+#: syntax.c:6074
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: ÒÑÉ趨×é, ºöÂÔ highlight link"
+
+#: syntax.c:6203
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: ²»¸ÃÓеĵȺÅ: %s"
+
+#: syntax.c:6239
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: ȱÉٵȺÅ: %s"
+
+#: syntax.c:6261
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: ȱÉÙ²ÎÊý: %s"
+
+#: syntax.c:6298
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: ²»ºÏ·¨µÄÖµ: %s"
+
+#: syntax.c:6417
+msgid "E419: FG color unknown"
+msgstr "E419: ´íÎóµÄÇ°¾°ÑÕÉ«"
+
+#: syntax.c:6428
+msgid "E420: BG color unknown"
+msgstr "E420: ´íÎóµÄ±³¾°ÑÕÉ«"
+
+#: syntax.c:6483
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: ´íÎóµÄÑÕÉ«Ãû³Æ»òÊýÖµ: %s"
+
+#: syntax.c:6687
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: Öն˱àÂëÌ«³¤: %s"
+
+#: syntax.c:6734
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: ²ÎÊý²»ÕýÈ·: %s"
+
+#: syntax.c:7263
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: ʹÓÃÁËÌ«¶à²»Í¬µÄ¸ßÁÁ¶ÈÊôÐÔ"
+
+#: tag.c:90
+msgid "at bottom of tag stack"
+msgstr "±êÇ©(tag)¶ÑÕ»½áβ"
+
+#: tag.c:91
+msgid "at top of tag stack"
+msgstr "±êÇ©(tag)¶ÑÕ»¿ªÍ·"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: ÒѾ­ÔÚ×îÇ°ÃæµÄ±êÇ©(tag)ÁË"
+
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: ÕÒ²»µ½±êÇ©(tag): %s"
+
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr " # pri kind tag"
+
+#: tag.c:548
+msgid "file\n"
+msgstr "Îļþ\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "ÊäÈë nr »òÑ¡Ôñ (<CR> Í˳ö): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: Ö»ÓдËÏî·ûºÏ"
+
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: ¼º¾­ÔÚ×îºóÒ»¸ö·ûºÏµÄ±êÇ©(tag)ÁË"
+
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "Îļþ \"%s\" ²»´æÔÚ"
+
+#. Give an indication of the number of matching tags
+#: tag.c:780
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "ÕÒµ½ tag: %d/%d%s"
+
+#: tag.c:783
+msgid " or more"
+msgstr " »ò¸ü¶à"
+
+#: tag.c:785
+msgid " Using tag with different case!"
+msgstr " ÒÔ²»Í¬´óСдÀ´Ê¹Óà tag!"
+
+#: tag.c:828
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: Îļþ \"%s\" ²»´æÔÚ"
+
+#. Highlight title
+#: tag.c:897
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # µ½ tag ´Ó ÐÐ ÔÚ Îļþ/Îı¾"
+
+#: tag.c:1144
+msgid "Linear tag search"
+msgstr "ÏßÐÔ²éÕÒ±êÇ© (Tags)"
+
+#: tag.c:1146
+msgid "Binary tag search"
+msgstr "¶þ½øÖƲéÕÒ(Binary search) ±êÇ©(Tags)"
+
+#: tag.c:1172
+#, c-format
+msgid "Searching tags file %s"
+msgstr "²éÕÒ tag Îļþ \"%s\""
+
+#: tag.c:1356
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Tag Îļþ·¾¶±»½Ø¶ÏΪ %s\n"
+
+#: tag.c:1847
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Tag Îļþ \"%s\" ¸ñʽ´íÎó"
+
+#: tag.c:1851
+#, c-format
+msgid "Before byte %ld"
+msgstr "ÔÚ %ld ×Ö½Ú֮ǰ"
+
+#: tag.c:1872
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Tag ÎļþδÅÅÐò: %s"
+
+#. never opened any tags file
+#: tag.c:1911
+msgid "E433: No tags file"
+msgstr "E433: ûÓÐ tag Îļþ"
+
+#: tag.c:2583
+msgid "E434: Can't find tag pattern"
+msgstr "E434: ÕÒ²»µ½ tag"
+
+#: tag.c:2594
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: ÕÒ²»µ½ tag, ÊÔ×ŲÂ!"
+
+#: term.c:1723
+msgid "' not known. Available builtin terminals are:"
+msgstr "' ²»ÄܼÓÔØ¡£¿ÉÓõÄÄÚ½¨ÖÕ¶ËÐÎʽÓÐ:"
+
+#: term.c:1747
+msgid "defaulting to '"
+msgstr "Ô¤Éè: '"
+
+#: term.c:2100
+msgid "Cannot open termcap file"
+msgstr "²»ÄÜ´ò¿ª termcap Îļþ"
+
+#: term.c:2103
+msgid "Terminal entry not found in terminfo"
+msgstr "ÔÚterminfoÖÐδÕÒµ½ÖÕ¶ËÏî"
+
+#: term.c:2105
+msgid "Terminal entry not found in termcap"
+msgstr "ÔÚtermcapÖÐδÕÒµ½ÖÕ¶ËÏî"
+
+#: term.c:2264
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: termcap ûÓÐ \"%s\" Ïî"
+
+#: term.c:2738
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: ÖÕ¶ËÐèÒª \"cm\" µÄÄÜÁ¦"
+
+#. Highlight title
+#: term.c:4872
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- Öն˰´¼ü ---"
+
+#: ui.c:240
+msgid "new shell started\n"
+msgstr "Æô¶¯Ð shell\n"
+
+#: ui.c:1705
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: ¶Á´íÎó£¬Í˳öÖÐ...\n"
+
+#. must display the prompt
+#: undo.c:351
+msgid "No undo possible; continue anyway"
+msgstr "²»ÄÜ»¹Ô­£»Çë¼ÌÐø"
+
+#: undo.c:506
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: ÐкŴíÎó"
+
+#: undo.c:675
+msgid "1 change"
+msgstr "Ò»Ïî¸Ä±ä"
+
+#: undo.c:677
+#, c-format
+msgid "%ld changes"
+msgstr "%ld Ïî¸Ä±ä"
+
+#: undo.c:721
+msgid "E439: undo list corrupt"
+msgstr "E439: ³·ÏúÁбíËð»µ"
+
+#: undo.c:751
+msgid "E440: undo line missing"
+msgstr "E440: ÕÒ²»µ½Òª³·Ïú²Ù×÷µÄÐÐ"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:655
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 16/32λ ͼÐͽçÃæ°æ±¾"
+
+#: version.c:657
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 32 Bit ͼÐͽçÃæ°æ±¾"
+
+#: version.c:660
+msgid " in Win32s mode"
+msgstr "Win32s ģʽ"
+
+#: version.c:662
+msgid " with OLE support"
+msgstr "Ö§³Ö OLE"
+
+#: version.c:665
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"MS-Windows 32λ ×Ö·û½çÃæ°æ±¾"
+
+#: version.c:669
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"MS-Windows 32λ ×Ö·û½çÃæ°æ±¾"
+
+#: version.c:673
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 λ MS-DOS °æ±¾"
+
+#: version.c:675
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 λ MS-DOS °æ±¾"
+
+#: version.c:681
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) °æ±¾"
+
+#: version.c:683
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X °æ±¾"
+
+#: version.c:686
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS °æ±¾"
+
+#: version.c:691
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS °æ±¾"
+
+#: version.c:701
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"¼ÓÈë²¹¶¡: "
+
+#: version.c:728
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"±àÒë"
+
+#: version.c:731
+msgid "by "
+msgstr "Õß:"
+
+#: version.c:743
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"³¬Ç¿°æ±¾ "
+
+#: version.c:746
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"´óÐÍ°æ±¾ "
+
+#: version.c:749
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"Ò»°ã°æ±¾ "
+
+#: version.c:752
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"¼òÒ×°æ±¾ "
+
+#: version.c:754
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"¾«¼ò°æ±¾ "
+
+#: version.c:760
+msgid "without GUI."
+msgstr "²»Ê¹ÓÃͼÐͽçÃæ¡£"
+
+#: version.c:764
+msgid "with GTK-GNOME GUI."
+msgstr "ʹÓà GTK-GNOME ͼÐͽçÃæ¡£"
+
+#: version.c:766
+msgid "with GTK GUI."
+msgstr "ʹÓà GTK ͼÐͽçÃæ¡£"
+
+#: version.c:770
+msgid "with X11-Motif GUI."
+msgstr "ʹÓà X11-Motif ͼÐͽçÃæ¡£"
+
+#: version.c:773
+msgid "with X11-Athena GUI."
+msgstr "ʹÓà X11-Athena ͼÐͽçÃæ¡£"
+
+#: version.c:776
+msgid "with BeOS GUI."
+msgstr "ʹÓà BeOS ͼÐͽçÃæ¡£"
+
+#: version.c:779
+msgid "with Photon GUI."
+msgstr "ʹÓÃPhotonͼÐͽçÃæ¡£"
+
+#: version.c:782
+msgid "with GUI."
+msgstr "ʹÓÃͼÐͽçÃæ¡£"
+
+#: version.c:785
+msgid "with Carbon GUI."
+msgstr "ʹÓà Carbon ͼÐͽçÃæ¡£"
+
+#: version.c:788
+msgid "with Cocoa GUI."
+msgstr "ʹÓà Cocoa ͼÐͽçÃæ¡£"
+
+#: version.c:791
+msgid "with (classic) GUI."
+msgstr "ʹÓà (´«Í³) ͼÐͽçÃæ¡£"
+
+#: version.c:802
+msgid " Features included (+) or not (-):\n"
+msgstr " Ä¿Ç°¿ÉʹÓÃ(+)Óë²»¿ÉʹÓÃ(-)µÄÄ£¿éÁбí:\n"
+
+#: version.c:814
+msgid " system vimrc file: \""
+msgstr " ϵͳ vimrc ÅäÖÃÎļþ: \""
+
+#: version.c:819
+msgid " user vimrc file: \""
+msgstr " Óû§µÄ vimrc ÅäÖÃÎļþ: \""
+
+#: version.c:824
+msgid " 2nd user vimrc file: \""
+msgstr " µÚ¶þ×éÓû§ vimrc Îļþ: \""
+
+#: version.c:829
+msgid " 3rd user vimrc file: \""
+msgstr " µÚÈý×éÓû§ vimrc Îļþ: \""
+
+#: version.c:834
+msgid " user exrc file: \""
+msgstr " Óû§µÄ exrc ÅäÖÃÎļþ: \""
+
+#: version.c:839
+msgid " 2nd user exrc file: \""
+msgstr " µÚ¶þ×éÓû§ exrc Îļþ: \""
+
+#: version.c:845
+msgid " system gvimrc file: \""
+msgstr " ϵͳ gvimrc Îļþ: \""
+
+#: version.c:849
+msgid " user gvimrc file: \""
+msgstr " Óû§µÄ gvimrc ÅäÖÃÎļþ: \""
+
+#: version.c:853
+msgid "2nd user gvimrc file: \""
+msgstr " µÚ¶þ×éÓû§ gvimrc Îļþ: \""
+
+#: version.c:858
+msgid "3rd user gvimrc file: \""
+msgstr " µÚÈý×éÓû§ gvimrc Îļþ: \""
+
+#: version.c:865
+msgid " system menu file: \""
+msgstr " ϵͳ²Ëµ¥ÅäÖÃÎļþ: \""
+
+#: version.c:873
+msgid " fall-back for $VIM: \""
+msgstr " $VIM Ô¤ÉèÖµ: \""
+
+#: version.c:879
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " $VIMRUNTIME Ô¤ÉèÖµ: \""
+
+#: version.c:883
+msgid "Compilation: "
+msgstr "±àÒ뷽ʽ: "
+
+#: version.c:889
+msgid "Compiler: "
+msgstr "±àÒëÆ÷: "
+
+#: version.c:894
+msgid "Linking: "
+msgstr "Á´½á·½Ê½: "
+
+#: version.c:899
+msgid " DEBUG BUILD"
+msgstr " µ÷ÊÔ°æ±¾"
+
+#: version.c:934
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved"
+
+#: version.c:936
+msgid "version "
+msgstr "°æ±¾ "
+
+#: version.c:937
+msgid "by Bram Moolenaar et al."
+msgstr "ά»¤ÈË: Bram Moolenaar et al."
+
+#: version.c:938
+msgid "Vim is open source and freely distributable"
+msgstr "Vim Ϊ¿É×ÔÓÉ·¢ÐеĿª·ÅÔ´´úÂëÈí¼þ"
+
+#: version.c:940
+msgid "Help poor children in Uganda!"
+msgstr "°ïÖúÎڸɴïµÄ¿ÉÁ¯¶ùͯ!"
+
+#: version.c:941
+msgid "type :help iccf<Enter> for information "
+msgstr "½øÒ»²½ËµÃ÷ÇëÊäÈë :help iccf<Enter>"
+
+#: version.c:943
+msgid "type :q<Enter> to exit "
+msgstr "ÒªÍ˳öÇëÊäÈë :q<Enter> "
+
+#: version.c:944
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "ÔÚÏß°ïÖúÇëÊäÈë :help<Enter> "
+
+#: version.c:945
+msgid "type :help version6<Enter> for version info"
+msgstr "а汾ÐÅÏ¢ÇëÊäÈë :help version6<Enter>"
+
+#: version.c:948
+msgid "Running in Vi compatible mode"
+msgstr "Vi ¼æÈÝģʽ"
+
+#: version.c:949
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "Èç¹ûÒªÍêÈ«Ä£Ä⴫ͳ Vi ÇëÊäÈë :set nocp<Enter>"
+
+#: version.c:950
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "Èç¹ûÐèÒª¶Ô Vi ¼æÈÝģʽ½øÒ»²½ËµÃ÷ÇëÊäÈë :help cp-default<Enter>"
+
+#: version.c:990
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "×¢Òâ: ¼ì²âµ½ Windows 95/98/ME"
+
+#: version.c:993
+msgid "type :help windows95<Enter> for info on this"
+msgstr "Èç¹ûÐèÒª¶Ô Windows 95 Ö§³ÖµÄ¸ü¶àÐÅÏ¢ÇëÊäÈë :help windows95<Enter>"
+
+#: window.c:201
+msgid "E441: There is no preview window"
+msgstr "E441: ûÓÐÔ¤ÀÀ´°¿Ú"
+
+#: window.c:568
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: ²»ÄÜͬʱ·Ö¸î´°¿ÚΪ×óÉϺÍÓÒϽÇ"
+
+#: window.c:1327
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: ÓÐÆäËü·Ö¸î´°¿Úʱ²»ÄÜÐýת"
+
+#: window.c:1810
+msgid "E444: Cannot close last window"
+msgstr "E444: ²»ÄܹرÕ×îºóÒ»¸ö´°¿Ú"
+
+#: window.c:2474
+msgid "Already only one window"
+msgstr "ÒѾ­Ö»Ê£Ò»¸ö´°¿ÚÁË"
+
+#: window.c:2521
+msgid "E445: Other window contains changes"
+msgstr "E445: ÆäËü´°¿ÚÓиıäµÄÄÚÈÝ"
+
+#: window.c:4341
+msgid "E446: No file name under cursor"
+msgstr "E446: ¹â±ê´¦Ã»ÓÐÎļþÃû"
+
+#: window.c:4460
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: ÔÚ·¾¶ÖÐÕÒ²»µ½Îļþ \"%s\""
+
+#: ../GvimExt/gvimext.cpp:586
+msgid "Edit with &multiple Vims"
+msgstr "Óà &multiple Vims ±à¼­"
+
+#: ../GvimExt/gvimext.cpp:592
+msgid "Edit with single &Vim"
+msgstr "Óà single &Vim ±à¼­"
+
+#: ../GvimExt/gvimext.cpp:604
+msgid "Edit with &Vim"
+msgstr "Óà &Vim ±à¼­"
+
+#. Now concatenate
+#: ../GvimExt/gvimext.cpp:628
+msgid "Edit with existing Vim - &"
+msgstr "Óõ±Ç°µÄ Vim ±à¼­ - &"
+
+#: ../GvimExt/gvimext.cpp:752
+msgid "Edits the selected file(s) with Vim"
+msgstr "Óà Vim ±à¼­Ñ¡ÔñµÄÎļþ"
+
+#: ../GvimExt/gvimext.cpp:891 ../GvimExt/gvimext.cpp:969
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "´´½¨½ø³Ìʧ°Ü: Çë¼ì²égvimÊÇ·ñÔÚ¿ÉÖ´Ðз¾¶ÖÐ!"
+
+#: ../GvimExt/gvimext.cpp:892 ../GvimExt/gvimext.cpp:906
+#: ../GvimExt/gvimext.cpp:970
+msgid "gvimext.dll error"
+msgstr "gvimext.dll ³ö´í"
+
+#: ../GvimExt/gvimext.cpp:905
+msgid "Path length too long!"
+msgstr "·¾¶ÃûÌ«³¤"
+
+#: globals.h:878
+msgid "--No lines in buffer--"
+msgstr "--»º³åÇøÎÞ×ÊÁÏ--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1019
+msgid "Command aborted"
+msgstr "ÃüÁǿÖÆÖжÏ"
+
+#: globals.h:1020
+msgid "Argument required"
+msgstr "ÐèÒªÖ¸Áî²ÎÊý"
+
+#: globals.h:1021
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ ºóÃæÓ¦¸ÃÓÐ / ? »ò &"
+
+#: globals.h:1023
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: ²»ÄÜÔÚÃüÁîÐд°¿ÚÖÐʹÓá£<CR>Ö´ÐУ¬CTRL-C Í˳ö"
+
+#: globals.h:1025
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr "E12: exrc/vimrc ÀïµÄÖ¸Áî²»ÄÜÖ´ÐÐ"
+
+#: globals.h:1026
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: ÎļþÒѾ­´æÔÚ (¿ÉÓà ! Ç¿ÖÆÌæ»»)"
+
+#: globals.h:1027
+msgid "Command failed"
+msgstr "ÃüÁîÖ´ÐÐʧ°Ü"
+
+#: globals.h:1028
+msgid "Internal error"
+msgstr "ÄÚ²¿´íÎó"
+
+#: globals.h:1029
+msgid "Interrupted"
+msgstr "ÒÑÖжÏ"
+
+#: globals.h:1030
+msgid "E14: Invalid address"
+msgstr "E14: ²»ÕýÈ·µÄµØÖ·"
+
+#: globals.h:1031
+msgid "Invalid argument"
+msgstr "²»ÕýÈ·µÄ²ÎÊý"
+
+#: globals.h:1032
+#, c-format
+msgid "Invalid argument: %s"
+msgstr "²»ÕýÈ·µÄ²ÎÊý: %s"
+
+#: globals.h:1034
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: ²»ÕýÈ·µÄ±í´ïʽ: %s"
+
+#: globals.h:1036
+msgid "E16: Invalid range"
+msgstr "E16: ²»ÕýÈ·µÄ·¶Î§"
+
+#: globals.h:1037
+msgid "Invalid command"
+msgstr "²»ÕýÈ·µÄÃüÁî"
+
+#: globals.h:1039
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" ÊÇĿ¼"
+
+#: globals.h:1042
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: '=' Ç°Ãæ³öÏÖÁË´íÎóµÄ×Ö·û"
+
+#: globals.h:1044
+msgid "E19: Mark has invalid line number"
+msgstr "E19: ±ê¼ÇµÄÐкŴíÎó"
+
+#: globals.h:1045
+msgid "E20: Mark not set"
+msgstr "E20: ûÓÐÉ趨±ê¼Ç"
+
+#: globals.h:1046
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: ÒòΪ 'modifiable' Ñ¡ÏîÊǹرյģ¬ËùÒÔ²»ÄÜÐÞ¸Ä"
+
+#: globals.h:1047
+msgid "E22: Scripts nested too deep"
+msgstr "E22: µÝ¹éµ÷ÓÃÌ«¶à²ã"
+
+#: globals.h:1048
+msgid "E23: No alternate file"
+msgstr "E23: ûÓÐÌæ´úµÄÎļþ"
+
+#: globals.h:1049
+msgid "E24: No such abbreviation"
+msgstr "E24: ûÓÐÕâ¸ö abbreviation ¶ÔÓ¦"
+
+#: globals.h:1050
+msgid "No ! allowed"
+msgstr "²»¿ÉʹÓà '!'"
+
+#: globals.h:1052
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: ÒòΪ±àÒëʱûÓмÓÈëͼÐͽçÃæµÄ³ÌÐò´úÂ룬ËùÒÔ²»ÄÜʹÓÃͼÐͽçÃæ"
+
+#: globals.h:1055
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: ÒòΪ±àÒëʱûÓмÓÈëÏ£²®À³µÄ³ÌÐò´úÂ룬ËùÒÔ²»ÄÜʹÓà Hebrew\n"
+
+#: globals.h:1058
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: ÒòΪ±àÒëʱûÓмÓÈë Farsi µÄ³ÌÐò´úÂ룬ËùÒÔ²»ÄÜʹÓà Farsi\n"
+
+#: globals.h:1061
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: ûÓÐÃûΪ '%s' µÄ highlight group"
+
+#: globals.h:1063
+msgid "E29: No inserted text yet"
+msgstr "E29: ûÓвåÈë¹ýÎÄ×Ö"
+
+#: globals.h:1064
+msgid "E30: No previous command line"
+msgstr "E30: ûÓÐÇ°Ò»ÏîÃüÁî"
+
+#: globals.h:1065
+msgid "E31: No such mapping"
+msgstr "E31: ûÓÐÕâ¸ö mapping ¶ÔÓ¦"
+
+#: globals.h:1066
+msgid "No match"
+msgstr "ÕÒ²»µ½"
+
+#: globals.h:1067
+#, c-format
+msgid "No match: %s"
+msgstr "ÕÒ²»µ½: %s"
+
+#: globals.h:1068
+msgid "E32: No file name"
+msgstr "E32: ûÓÐÎļþÃû"
+
+#: globals.h:1069
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: ûÓÐÇ°Ò»¸ö²éÕÒ/Ìæ»»µÄÃüÁî"
+
+#: globals.h:1070
+msgid "E34: No previous command"
+msgstr "E34: ûÓÐÇ°Ò»¸öÃüÁî"
+
+#: globals.h:1071
+msgid "E35: No previous regular expression"
+msgstr "E35: ûÓÐÇ°Ò»¸ö²éÕÒÃüÁî"
+
+#: globals.h:1072
+msgid "No range allowed"
+msgstr "²»¿ÉʹÓ÷¶Î§ÃüÁî"
+
+#: globals.h:1074
+msgid "E36: Not enough room"
+msgstr "E36: ûÓÐ×ã¹»µÄ¿Õ¼ä"
+
+#: globals.h:1076
+#, c-format
+msgid "Can't create file %s"
+msgstr "²»ÄÜ´´½¨Îļþ %s"
+
+#: globals.h:1077
+msgid "Can't get temp file name"
+msgstr "²»Äܵõ½ÁÙʱÎļþÃû"
+
+#: globals.h:1078
+#, c-format
+msgid "Can't open file %s"
+msgstr "²»ÄÜ´ò¿ªÎļþ %s"
+
+#: globals.h:1079
+#, c-format
+msgid "Can't read file %s"
+msgstr "²»ÄܶÁÈ¡Îļþ %s"
+
+#: globals.h:1080
+msgid "E37: No write since last change (use ! to override)"
+msgstr "E37: ÎļþÄÚÈÝÒѸı䵫ÉÐδ±£´æ (¿ÉÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: globals.h:1081
+msgid "E38: Null argument"
+msgstr "E38: ¿ÕµÄ (Null) ²ÎÊý"
+
+#: globals.h:1083
+msgid "E39: Number expected"
+msgstr "E39: Ó¦¸ÃÒªÓÐÊý×Ö"
+
+#: globals.h:1086
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: ²»ÄÜ´ò¿ª´íÎóÎļþ %s"
+
+#: globals.h:1089
+msgid "E41: Out of memory!"
+msgstr "E41: ÄÚ´æ²»×ã!"
+
+#: globals.h:1092
+msgid "Pattern not found"
+msgstr "ÕÒ²»µ½Ä£Ê½"
+
+#: globals.h:1094
+#, c-format
+msgid "Pattern not found: %s"
+msgstr "ÕÒ²»µ½Ä£Ê½ %s"
+
+#: globals.h:1095
+msgid "Argument must be positive"
+msgstr "²ÎÊýÓ¦¸ÃÊÇÕýÊý"
+
+#: globals.h:1097
+msgid "E42: No Errors"
+msgstr "E42: ûÓдíÎó"
+
+#: globals.h:1099
+msgid "E43: Damaged match string"
+msgstr "E43: Æ¥Åä×Ö·û´®ÓÐÎÊÌâ"
+
+#: globals.h:1100
+msgid "E44: Corrupted regexp program"
+msgstr "E44: ÕýÔò±í´ïʽÓÐÎÊÌâ"
+
+#: globals.h:1101
+msgid "E45: 'readonly' option is set (use ! to override)"
+msgstr "E45: É趨 'readonly' Ñ¡Ïî(Ö»¶Á) (¿ÉÓà ! Ç¿ÖÆÖ´ÐÐ)"
+
+#: globals.h:1103
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: ²»ÄÜÉ趨ֻ¶Á±äÁ¿ \"%s\""
+
+#: globals.h:1106
+msgid "E47: Error while reading errorfile"
+msgstr "E47: ¶ÁÈ¡´íÎóÎļþʧ°Ü"
+
+#: globals.h:1109
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: ²»ÄÜÔÚ sandbox Àï³öÏÖ"
+
+#: globals.h:1111
+msgid "E49: Invalid scroll size"
+msgstr "E49: ´íÎóµÄ¹ö¶¯´óС"
+
+#: globals.h:1112
+msgid "E91: 'shell' option is empty"
+msgstr "E91: 'E71: Ñ¡Ïî 'shell' δÉ趨"
+
+#: globals.h:1113
+msgid "E72: Close error on swap file"
+msgstr "E72: ½»»»Îļþ¹Ø±Õ´íÎó"
+
+#: globals.h:1114
+msgid "E73: tag stack empty"
+msgstr "E73: ±êÇ©¶ÑÕ»ÒÑ¿Õ"
+
+#: globals.h:1115
+msgid "E74: Command too complex"
+msgstr "E74: ÃüÁîÌ«¸´ÔÓ"
+
+#: globals.h:1116
+msgid "E75: Name too long"
+msgstr "E75: Ãû×ÖÌ«³¤"
+
+#: globals.h:1117
+msgid "E76: Too many ["
+msgstr "E76: Ì«¶à ["
+
+#: globals.h:1118
+msgid "E77: Too many file names"
+msgstr "E77: Ì«¶àÎļþÃû"
+
+#: globals.h:1119
+msgid "Trailing characters"
+msgstr "ÄãÊäÈëÁ˶àÓàµÄ×Ö·û"
+
+#: globals.h:1120
+msgid "E78: Unknown mark"
+msgstr "E78: ²»ÄÜ°ìʶµÄ±ê¼Ç"
+
+#: globals.h:1121
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: ²»ÄÜÀ©Õ¹Í¨Åä·û"
+
+#: globals.h:1122
+msgid "E80: Error while writing"
+msgstr "E80: дÈë´íÎó"
+
+#: globals.h:1123
+msgid "Zero count"
+msgstr "Êýµ½Áã (?)"
+
+#: globals.h:1125
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: <SID> ²»ÄÜÔÚ script ±¾ÎÄÍâʹÓÃ."
diff --git a/src/po/zh_TW.UTF-8.po b/src/po/zh_TW.UTF-8.po
new file mode 100644
index 000000000..0af90e6b8
--- /dev/null
+++ b/src/po/zh_TW.UTF-8.po
@@ -0,0 +1,6389 @@
+# Traditional Chinese Translation for Vim vim:set foldmethod=marker:
+#
+# Do ":help uganda" in Vim to read copying and usage conditions.
+# Do ":help credits" in Vim to see a list of people who contributed.
+#
+# FIRST AUTHOR Francis S.Lin <piaip@csie.ntu.edu.tw>, 2000
+# FIRST RELEASE Thu Jun 14 14:24:17 CST 2001
+#
+# Last update: Thu Apr 24 13:09:07 CST 2003 (6.2a)
+#
+# To update, search pattern: /fuzzy\|^msgstr ""\(\n"\)\@!
+#
+# DO NOT USE WORDS WITH BACKSLASH ('\') AS SECOND BYTE OF BIG5 CHARS
+# EG: '功', # 許功蓋
+# é¤æž¯é–±ç®ç©€è·šæ·šèº¡è±¹æ“ºç’žç¸·é«å­æ­¿ä¿ž
+# 墦娉崤黠孀廄çµæ„§ç¨žéˆ¾æšå…么å’æ²”å¼è‹’塿踊
+# you can replace these characters with alternative words.
+# THIS WILL CAUSE INCOMPATIBLE ON gettext 0.10.36+
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim(Traditional Chinese)\n"
+"POT-Creation-Date: 2003-04-24 13:06+0800\n"
+"PO-Revision-Date: Mon Feb 19 22:49:21 CST 2001\n"
+"Last-Translator: Francis S.Lin <piaip@csie.ntu.edu.tw>\n"
+"Language-Team: Francis S.Lin <piaip@csie.ntu.edu.tw>, Cecil Sheng "
+"<b7506022@csie.ntu.edu.tw>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: 無法é…置任何緩è¡å€ï¼Œé›¢é–‹ç¨‹å¼..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: 無法é…置緩è¡å€ï¼Œä½¿ç”¨å¦ä¸€å€‹ç·©è¡å€...."
+
+#: buffer.c:797
+msgid "E515: No buffers were unloaded"
+msgstr "E515: 沒有釋放任何緩è¡å€"
+
+#: buffer.c:799
+msgid "E516: No buffers were deleted"
+msgstr "E516: 沒有刪除任何緩è¡å€"
+
+#: buffer.c:801
+msgid "E517: No buffers were wiped out"
+msgstr "E517: 沒有清除任何緩è¡å€"
+
+#: buffer.c:809
+msgid "1 buffer unloaded"
+msgstr "已釋放一個緩è¡å€"
+
+#: buffer.c:811
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "已釋放 %d 個緩è¡å€"
+
+#: buffer.c:816
+msgid "1 buffer deleted"
+msgstr "已刪除一個緩è¡å€"
+
+#: buffer.c:818
+#, c-format
+msgid "%d buffers deleted"
+msgstr "已刪除 %d 個緩è¡å€"
+
+#: buffer.c:823
+msgid "1 buffer wiped out"
+msgstr "已刪除一個緩è¡å€"
+
+#: buffer.c:825
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "已刪除 %d 個緩è¡å€"
+
+#: buffer.c:886
+msgid "E84: No modified buffer found"
+msgstr "E84: 沒有修改éŽçš„ç·©è¡å€"
+
+#. back where we started, didn't find anything.
+#: buffer.c:925
+msgid "E85: There is no listed buffer"
+msgstr "E85: 沒有列出的緩è¡å€"
+
+#: buffer.c:937
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: 無法切æ›åˆ°ç¬¬ %ld 個緩è¡å€"
+
+#: buffer.c:940
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: 無法切æ›åˆ°æ›´å¾Œé¢çš„ç·©è¡å€"
+
+#: buffer.c:942
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: 無法切æ›åˆ°æ›´å‰é¢çš„ç·©è¡å€"
+
+#: buffer.c:966
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr "E89: 已更改éŽç·©è¡å€ %ld 但尚未存檔 (å¯ç”¨ ! 強制執行)"
+
+#: buffer.c:982
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: 無法釋放最後一個緩è¡å€"
+
+#: buffer.c:1494
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: 警告: 檔åéŽå¤š"
+
+#: buffer.c:1664
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: 找ä¸åˆ°ç¬¬ %ld 個緩è¡å€"
+
+#: buffer.c:1890
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: 找到一個以上的 %s"
+
+#: buffer.c:1892
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: 找ä¸åˆ° %s"
+
+#: buffer.c:2297 ex_docmd.c:6479
+#, c-format
+msgid "line %ld"
+msgstr "行 %ld"
+
+#: buffer.c:2380
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: 已有緩è¡å€ä½¿ç”¨é€™å€‹åå­—"
+
+#: buffer.c:2673
+msgid " [Modified]"
+msgstr " [已修改]"
+
+#: buffer.c:2678
+msgid "[Not edited]"
+msgstr "[未編輯]"
+
+#: buffer.c:2683
+msgid "[New file]"
+msgstr "[新檔案]"
+
+#: buffer.c:2684
+msgid "[Read errors]"
+msgstr "[讀å–錯誤]"
+
+#: buffer.c:2686 fileio.c:1914
+msgid "[readonly]"
+msgstr "[唯讀]"
+
+#: buffer.c:2701
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "行數 1 --%d%%--"
+
+#: buffer.c:2703
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "行數 %ld --%d%%--"
+
+#: buffer.c:2710
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "行 %ld/%ld --%d%%-- 欄 "
+
+#: buffer.c:2811
+msgid "[No file]"
+msgstr "[未命å]"
+
+#. must be a help buffer
+#: buffer.c:2851
+msgid "help"
+msgstr "[輔助說明]"
+
+#: buffer.c:3405 screen.c:4943
+msgid "[help]"
+msgstr "[輔助說明]"
+
+#: buffer.c:3437 screen.c:4949
+msgid "[Preview]"
+msgstr "[é è¦½]"
+
+#: buffer.c:3708
+msgid "All"
+msgstr "全部"
+
+#: buffer.c:3708
+msgid "Bot"
+msgstr "底端"
+
+#: buffer.c:3710
+msgid "Top"
+msgstr "頂端"
+
+#: buffer.c:4454
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# ç·©è¡å€åˆ—表:\n"
+
+#: buffer.c:4487
+msgid "[Error List]"
+msgstr "[錯誤列表]"
+
+#: buffer.c:4500 memline.c:1501
+msgid "[No File]"
+msgstr "[未命å]"
+
+#: buffer.c:4803
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- 符號 ---"
+
+#: buffer.c:4813
+#, c-format
+msgid "Signs for %s:"
+msgstr "%s 的符號:"
+
+#: buffer.c:4819
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " è¡Œ=%ld id=%d å稱=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: 無法比較(diff) %ld個以上的緩è¡å€"
+
+#: diff.c:651
+msgid "E97: Cannot create diffs"
+msgstr "E97: ä¸èƒ½å»ºç«‹ "
+
+#: diff.c:750
+msgid "Patch file"
+msgstr "Patch 檔案"
+
+#: diff.c:1001
+msgid "E98: Cannot read diff output"
+msgstr "E98: ç„¡æ³•è®€å– diff 的輸出"
+
+#: diff.c:1742
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: ç›®å‰çš„ç·©è¡å€ä¸æ˜¯åœ¨ diff 模å¼"
+
+#: diff.c:1754
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: 沒有緩è¡å€åœ¨ diff 模å¼"
+
+#: diff.c:1762
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: 有兩個以上的緩è¡å€åœ¨ diff 模å¼ï¼Œç„¡æ³•æ±ºå®šè¦ç”¨å“ªä¸€å€‹"
+
+#: diff.c:1785
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: 找ä¸åˆ°ç·©è¡å€: \"%s\""
+
+#: diff.c:1791
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: ç·©è¡å€ \"%s\" ä¸æ˜¯åœ¨ diff 模å¼"
+
+#: digraph.c:2172
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: 複åˆå­—å…ƒ(digraph)中ä¸èƒ½ä½¿ç”¨ Escape"
+
+#: digraph.c:2344
+msgid "E544: Keymap file not found"
+msgstr "E544: 找ä¸åˆ° keymap 檔"
+
+#: digraph.c:2371
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: 使用 :loadkeymap "
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " é—œéµå­—è‡ªå‹•å®Œæˆ (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " ^X æ¨¡å¼ (^E/^Y/^L/^]/^F/^I/^K/^D/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " å€åŸŸé—œéµå­—è‡ªå‹•å®Œæˆ (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " æ•´è¡Œè‡ªå‹•å®Œæˆ (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " 檔åè‡ªå‹•å®Œæˆ (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " æ¨™ç±¤è‡ªå‹•å®Œæˆ (^]/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " è·¯å¾‘è‡ªå‹•å®Œæˆ (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " å®šç¾©è‡ªå‹•å®Œæˆ (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " å­—å…¸è‡ªå‹•å®Œæˆ (^K/^N/^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Thesaurus è‡ªå‹•å®Œæˆ (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " å‘½ä»¤åˆ—è‡ªå‹•å®Œæˆ (^V/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "已到段è½çµå°¾"
+
+#: edit.c:941
+msgid "'thesaurus' option is empty"
+msgstr "é¸é … 'thesaurus' 未設定"
+
+#: edit.c:1145
+msgid "'dictionary' option is empty"
+msgstr "é¸é … 'dictionary' 未設定"
+
+#: edit.c:2130
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "掃瞄字典: %s"
+
+#: edit.c:2336
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (æ’å…¥) Scroll (^E/^Y)"
+
+#: edit.c:2338
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (å–代) Scroll (^E/^Y)"
+
+#: edit.c:2652
+#, c-format
+msgid "Scanning: %s"
+msgstr "掃瞄中: %s"
+
+#: edit.c:2687
+msgid "Scanning tags."
+msgstr "掃瞄標籤."
+
+#: edit.c:3349
+msgid " Adding"
+msgstr " 增加"
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3398
+msgid "-- Searching..."
+msgstr "-- æœå°‹ä¸­..."
+
+#: edit.c:3454
+msgid "Back at original"
+msgstr "回到起點"
+
+#: edit.c:3459
+msgid "Word from other line"
+msgstr "從別行開始的字 (?)"
+
+#: edit.c:3464
+msgid "The only match"
+msgstr "åªæœ‰æ­¤é …符åˆ"
+
+#: edit.c:3523
+#, c-format
+msgid "match %d of %d"
+msgstr "找到 %d / %d"
+
+#: edit.c:3526
+#, c-format
+msgid "match %d"
+msgstr "ç¬¦åˆ %d"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:889
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: 未定義的變數: \"%s\""
+
+#: eval.c:1185
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: 缺少å°æ‡‰çš„括號: %s"
+
+#: eval.c:1290 eval.c:1304
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: 無此變數: \"%s\""
+
+#: eval.c:1560
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: '?' 後缺少 ':'"
+
+#: eval.c:2176
+msgid "E110: Missing ')'"
+msgstr "E110: 缺少å°æ‡‰çš„ \")\""
+
+#: eval.c:2233
+msgid "E111: Missing ']'"
+msgstr "E111: 缺少å°æ‡‰çš„ \"]\""
+
+#: eval.c:2309
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: 缺少é¸é …å稱: %s"
+
+#: eval.c:2327
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: ä¸æ­£ç¢ºçš„é¸é …: %s"
+
+#: eval.c:2391
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: 缺少引號: %s"
+
+#: eval.c:2523
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: 缺少引號: %s"
+
+#: eval.c:2843
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: å‡½å¼ %s 的引數ä¸æ­£ç¢º"
+
+#: eval.c:2844
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: 未定義的函å¼: %s"
+
+#: eval.c:2845
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: å‡½å¼ %s 的引數éŽå¤š"
+
+#: eval.c:2846
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: å‡½å¼ %s 的引數太少"
+
+#: eval.c:2847
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: <SID> ä¸èƒ½åœ¨ script 本文外使用: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3465 gui.c:4238 gui_gtk.c:1991
+msgid "&Ok"
+msgstr "確定(&O)"
+
+#: eval.c:4000
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld 行: "
+
+#: eval.c:5149
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"確定(&O)\n"
+"å–消(&C)"
+
+#: eval.c:5182
+msgid "called inputrestore() more often than inputsave()"
+msgstr "å‘¼å« inputrestore() 的次數比 inputsave() 還多"
+
+#: eval.c:6036
+msgid "E240: No connection to Vim server"
+msgstr "E240: 沒有與 Vim Server 建立連線"
+
+#: eval.c:6133
+msgid "E277: Unable to read a server reply"
+msgstr "E277: 無法讀å–伺æœå™¨çš„回應"
+
+#: eval.c:6161
+msgid "E258: Unable to send to client"
+msgstr "E258: 無法傳é€åˆ° client"
+
+#: eval.c:6209
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: 無法傳é€åˆ° %s"
+
+#: eval.c:6309
+msgid "(Invalid)"
+msgstr "(ä¸æ­£ç¢º)"
+
+#: eval.c:7402
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: 變數 %s 尚未定義"
+
+#: eval.c:7834
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E461: ä¸åˆæ³•çš„變數å稱: %s"
+
+#: eval.c:8121
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: å‡½å¼ %s 已經存在, 請使用 ! 強制å–代"
+
+#: eval.c:8188
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: å‡½å¼ %s 尚未定義"
+
+#: eval.c:8201
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: 缺少 \"(\": %s"
+
+#: eval.c:8234
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: åƒæ•¸ä¸æ­£ç¢º: %s"
+
+#: eval.c:8313
+msgid "E126: Missing :endfunction"
+msgstr "E126: 缺少 :endfunction"
+
+#: eval.c:8396
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: å‡½å¼ %s 正在使用中,無法é‡æ–°å®šç¾©"
+
+#: eval.c:8464
+msgid "E129: Function name required"
+msgstr "E129: 需è¦å‡½å¼å稱"
+
+#: eval.c:8515
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: 函å¼å稱第一個字æ¯å¿…須大寫: %s"
+
+#: eval.c:8707
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: å‡½å¼ %s 尚未定義"
+
+#: eval.c:8712
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: å‡½å¼ %s 正在使用中,無法刪除"
+
+#: eval.c:8760
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: 函å¼éžè¿´å‘¼å«å±¤æ•¸è¶…éŽ 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:8813
+#, c-format
+msgid "calling %s"
+msgstr "å‘¼å« %s"
+
+#: eval.c:8867
+#, c-format
+msgid "%s aborted"
+msgstr "%s 被強制中斷執行"
+
+#: eval.c:8869
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s 傳回值 #%ld "
+
+#: eval.c:8872
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s 傳回值 \"%s\""
+
+#. always scroll up, don't overwrite
+#: eval.c:8888 ex_cmds2.c:2231
+#, c-format
+msgid "continuing in %s"
+msgstr "繼續: %s"
+
+#: eval.c:8935
+msgid "E133: :return not inside a function"
+msgstr "E133: :return 必須在函å¼è£¡ä½¿ç”¨"
+
+#: eval.c:9266
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# 全域變數:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, åå…­é€²ä½ %02x, å…«é€²ä½ %03o"
+
+#: ex_cmds.c:433
+msgid "E134: Move lines into themselves"
+msgstr "E134: 無法把行移到它自已內"
+
+#: ex_cmds.c:502
+msgid "1 line moved"
+msgstr "å·²æ¬ç§» 1 è¡Œ"
+
+#: ex_cmds.c:504
+#, c-format
+msgid "%ld lines moved"
+msgstr "å·²æ¬ç§» %ld è¡Œ"
+
+#: ex_cmds.c:909
+#, c-format
+msgid "%ld lines filtered"
+msgstr "å·²è™•ç† %ld è¡Œ"
+
+#: ex_cmds.c:937
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *Filter* Autocommand ä¸å¯ä»¥æ›´æ”¹ç·©è¡å€çš„內容"
+
+#: ex_cmds.c:1022
+msgid "[No write since last change]\n"
+msgstr "[更新後尚未儲存]\n"
+
+#: ex_cmds.c:1268
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s 在行中: "
+
+#: ex_cmds.c:1273
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: éŽå¤šéŒ¯èª¤, 忽略檔案其餘部分"
+
+#: ex_cmds.c:1302
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "è®€å– viminfo 檔案 \"%s\"%s%s%s"
+
+#: ex_cmds.c:1303
+msgid " info"
+msgstr " 訊æ¯"
+
+#: ex_cmds.c:1304
+msgid " marks"
+msgstr " 標記"
+
+#: ex_cmds.c:1305
+msgid " FAILED"
+msgstr " 失敗"
+
+#: ex_cmds.c:1396
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Viminfo 檔案無法寫入: %s"
+
+#: ex_cmds.c:1521
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: 無法寫入 viminfo 檔案 %s !"
+
+#: ex_cmds.c:1529
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "寫入 viminfo 檔案 \"%s\" 中"
+
+#. Write the info:
+#: ex_cmds.c:1627
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# 本 viminfo 檔案是由 Vim %s 所產生.\n"
+
+#: ex_cmds.c:1629
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# 如果想è¦è‡ªè¡Œä¿®æ”¹è«‹ç‰¹åˆ¥å°å¿ƒï¼\n"
+"\n"
+
+#: ex_cmds.c:1631
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# 'encoding' 在此檔建立時的值\n"
+
+#: ex_cmds.c:1730
+msgid "Illegal starting char"
+msgstr "無效的起始字元"
+
+#: ex_cmds.c:2075 ex_cmds.c:2340 ex_cmds2.c:744
+msgid "Save As"
+msgstr "å¦å­˜æ–°æª”"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2118
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: 您在å¦ä¸€å€‹ç·©è¡å€ä¹Ÿè¼‰å…¥äº†é€™å€‹æª”案"
+
+#: ex_cmds.c:2152
+msgid "Write partial file?"
+msgstr "è¦å¯«å…¥éƒ¨åˆ†æª”案嗎?"
+
+#: ex_cmds.c:2159
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: 請使用 ! 以寫入部分緩è¡å€"
+
+#: ex_cmds.c:2274
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "è¦è¦†å¯«å·²å­˜åœ¨çš„檔案 \"%.*s\"?"
+
+#: ex_cmds.c:2345
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: ç·©è¡å€ %ld 沒有檔案å稱"
+
+#: ex_cmds.c:2383
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: 檔案未寫入,因為 'write' é¸é …被關閉"
+
+#: ex_cmds.c:2403
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"\"%.*s\" 已設定 'readonly' é¸é ….\n"
+"確定è¦è¦†å¯«å—Žï¼Ÿ"
+
+#: ex_cmds.c:2568
+msgid "Edit File"
+msgstr "編輯檔案"
+
+#: ex_cmds.c:3137
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Autocommands æ„外地刪除新緩è¡å€ %s"
+
+#: ex_cmds.c:3269
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: :z ä¸æŽ¥å—éžæ•¸å­—çš„åƒæ•¸"
+
+#: ex_cmds.c:3354
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: rvim 中ç¦æ­¢ä½¿ç”¨ shell 命令"
+
+#: ex_cmds.c:3461
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Regular expression 無法用字æ¯åˆ†éš” (?)"
+
+#: ex_cmds.c:3807
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "å–代為 %s (y/n/a/q/^E/^Y)?"
+
+#: ex_cmds.c:4172
+msgid "(Interrupted) "
+msgstr "(已中斷) "
+
+#: ex_cmds.c:4176
+msgid "1 substitution"
+msgstr "å–代一組"
+
+#: ex_cmds.c:4178
+#, c-format
+msgid "%ld substitutions"
+msgstr "å–代 %ld 組"
+
+#: ex_cmds.c:4181
+msgid " on 1 line"
+msgstr " 一行中"
+
+#: ex_cmds.c:4183
+#, c-format
+msgid " on %ld lines"
+msgstr " %ld 行中"
+
+#: ex_cmds.c:4234
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :global 無法éžè¿´åŸ·è¡Œ"
+
+#: ex_cmds.c:4269
+msgid "E148: Regular expression missing from global"
+msgstr "E148: æ²’æœ‰ä½¿ç”¨éŽ Regular expression (?)"
+
+#: ex_cmds.c:4318
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "æ¯ä¸€è¡Œéƒ½æ‰¾ä¸åˆ°: %s"
+
+#: ex_cmds.c:4399
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# å‰ä¸€çµ„替代字串:\n"
+"$"
+
+#: ex_cmds.c:4503
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: 抱歉, 沒有 %s 的說明"
+
+#: ex_cmds.c:4537
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "抱歉, 找ä¸åˆ°èªªæ˜Žæª” \"%s\""
+
+#: ex_cmds.c:5012
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s ä¸æ˜¯ç›®éŒ„"
+
+#: ex_cmds.c:5040
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: 無法以寫入模å¼é–‹å•Ÿ \"%s\""
+
+#: ex_cmds.c:5075
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: 無法讀å–檔案: %s"
+
+#: ex_cmds.c:5154
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: 標籤(tag) \"%s\" 在檔案 %s 裡é‡è¤‡å‡ºç¾å¤šæ¬¡"
+
+#: ex_cmds.c:5261
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: 未定義的 sign command: %s"
+
+#: ex_cmds.c:5281
+msgid "E156: Missing sign name"
+msgstr "E156: 缺少 sign å稱"
+
+#: ex_cmds.c:5327
+msgid "E612: Too many signs defined"
+msgstr "E612: 已定義太多 signs"
+
+#: ex_cmds.c:5394
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: ä¸æ­£ç¢ºçš„ sign 文字: %s"
+
+#: ex_cmds.c:5425 ex_cmds.c:5611
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: ä¸æ­£ç¢ºçš„ sign: %s"
+
+#: ex_cmds.c:5471
+msgid "E159: Missing sign number"
+msgstr "E159: 缺少 sign number"
+
+#: ex_cmds.c:5551
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: ç·©è¡å€å稱錯誤: %s"
+
+#: ex_cmds.c:5590
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Sign ID 錯誤: %ld"
+
+#: ex_cmds.c:5761
+msgid "[Deleted]"
+msgstr "[已刪除]"
+
+#: ex_cmds2.c:82
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "進入除錯模å¼. 輸入 \"cont\" 以回到正常模å¼."
+
+#: ex_cmds2.c:86 ex_docmd.c:850
+#, c-format
+msgid "line %ld: %s"
+msgstr "行 %ld: %s"
+
+#: ex_cmds2.c:88
+#, c-format
+msgid "cmd: %s"
+msgstr "cmd: %s"
+
+#: ex_cmds2.c:271
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "\"%s%s\" 中斷點: 第 %ld 行"
+
+#: ex_cmds2.c:521
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: 找ä¸åˆ°ä¸­æ–·é»ž: %s"
+
+#: ex_cmds2.c:547
+msgid "No breakpoints defined"
+msgstr "沒有定義中斷點"
+
+#: ex_cmds2.c:552
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s 第 %ld 行"
+
+#: ex_cmds2.c:767
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "將變動存儲至 \"%.*s\"?"
+
+#: ex_cmds2.c:769 ex_docmd.c:8820
+msgid "Untitled"
+msgstr "未命å"
+
+#: ex_cmds2.c:905
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: 已更改éŽç·©è¡å€ \"%s\" 但尚未存檔 (å¯ç”¨ ! 強制執行)"
+
+#: ex_cmds2.c:974
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "注æ„: 已切æ›åˆ°å…¶å®ƒç·©è¡å€ (請檢查 Autocommands 有無錯誤)"
+
+#: ex_cmds2.c:1377
+msgid "E163: There is only one file to edit"
+msgstr "E163: åªæœ‰ä¸€å€‹æª”案å¯ç·¨è¼¯"
+
+#: ex_cmds2.c:1379
+msgid "E164: Cannot go before first file"
+msgstr "E164: 已經在第一個檔案了"
+
+#: ex_cmds2.c:1381
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: 已經在最後一個檔案了"
+
+#: ex_cmds2.c:1828
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "æœå°‹ä¸­: \"%s\" -- \"%s\""
+
+#: ex_cmds2.c:1850
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "æœå°‹ä¸­: \"%s\""
+
+#: ex_cmds2.c:1871
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "在 'runtimepath' 裡找ä¸åˆ° \"%s\""
+
+#: ex_cmds2.c:1905
+msgid "Source Vim script"
+msgstr "執行 Vim script"
+
+#: ex_cmds2.c:2056
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "無法執行目錄: \"%s\""
+
+#: ex_cmds2.c:2086
+#, c-format
+msgid "could not source \"%s\""
+msgstr "無法執行 \"%s\""
+
+#: ex_cmds2.c:2088
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "第 %ld 行: 無法執行 \"%s\""
+
+#: ex_cmds2.c:2102
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "執行 \"%s\" 中"
+
+#: ex_cmds2.c:2104
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "第 %ld è¡Œ: çµæŸåŸ·è¡Œ %s"
+
+#: ex_cmds2.c:2229
+#, c-format
+msgid "finished sourcing %s"
+msgstr "çµæŸåŸ·è¡Œ %s"
+
+#: ex_cmds2.c:2528
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: 注æ„: 錯誤的行分隔字元,å¯èƒ½æ˜¯å°‘了 ^M"
+
+#: ex_cmds2.c:2577
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: 在執行 script 檔案外ä¸å¯ä½¿ç”¨ :scriptencoding"
+
+#: ex_cmds2.c:2610
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: 在執行 script 檔案外ä¸å¯ä½¿ç”¨ :finish"
+
+#: ex_cmds2.c:3004
+#, c-format
+msgid "Page %d"
+msgstr "第 %d é "
+
+#: ex_cmds2.c:3116
+msgid "No text to be printed"
+msgstr "沒有è¦åˆ—å°çš„文字"
+
+#: ex_cmds2.c:3194
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "列å°ä¸­: 第 %d é  (%d%%)"
+
+#: ex_cmds2.c:3203
+#, c-format
+msgid " Copy %d of %d"
+msgstr "複製 %d / %d"
+
+#: ex_cmds2.c:3255
+#, c-format
+msgid "Printed: %s"
+msgstr "已列å°: %s"
+
+#: ex_cmds2.c:3262
+msgid "Printing aborted"
+msgstr "å·²å–消列å°"
+
+#: ex_cmds2.c:3645
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: 無法寫入 PostScript 輸出檔"
+
+#: ex_cmds2.c:4320
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: 無法開啟 PostScript 輸出檔"
+
+#: ex_cmds2.c:4362
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: 無法開啟檔案 \"%s\""
+
+#: ex_cmds2.c:4373
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: ç„¡æ³•è®€å– PostScript resource 檔 \"%s\""
+
+#: ex_cmds2.c:4576
+msgid "Sending to printer..."
+msgstr "傳é€è³‡æ–™åˆ°å°è¡¨æ©Ÿ..."
+
+#: ex_cmds2.c:4580
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: ç„¡æ³•åˆ—å° PostScript 檔案"
+
+#: ex_cmds2.c:4582
+msgid "Print job sent."
+msgstr "å·²é€å‡ºåˆ—å°å·¥ä½œã€‚"
+
+#: ex_cmds2.c:4978
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "ç›®å‰çš„ %s語言: \"%s\""
+
+#: ex_cmds2.c:4989
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: ä¸èƒ½è¨­å®šèªžè¨€æˆ \"%s\""
+
+#: ex_docmd.c:486
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "進入 Ex 模å¼. 輸入 \"visua\" 以回到正常模å¼."
+
+#. must be at EOF
+#: ex_docmd.c:522
+msgid "E501: At end-of-file"
+msgstr "E501: 已到檔案çµå°¾"
+
+#: ex_docmd.c:624
+msgid "E169: Command too recursive"
+msgstr "E169: 命令éžè¿´å±¤æ•¸éŽå¤š"
+
+#: ex_docmd.c:1090
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: 未攔截的例外: %s"
+
+#: ex_docmd.c:1176
+msgid "End of sourced file"
+msgstr "命令檔çµæŸ"
+
+#: ex_docmd.c:1177
+msgid "End of function"
+msgstr "函å¼çµå°¾"
+
+#: ex_docmd.c:1628
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: 使用者定義的命令會混淆"
+
+#: ex_docmd.c:1642
+msgid "E492: Not an editor command"
+msgstr "E492: ä¸æ˜¯ç·¨è¼¯å™¨çš„命令"
+
+#: ex_docmd.c:1725
+msgid "E478: Don't panic!"
+msgstr "E478: ä¸è¦é©šæ…Œ!"
+
+#: ex_docmd.c:1744
+msgid "E493: Backwards range given"
+msgstr "E493: 指定了å‘å‰åƒè€ƒçš„範åœ"
+
+#: ex_docmd.c:1753
+msgid "Backwards range given, OK to swap"
+msgstr "指定了å‘å‰åƒè€ƒçš„範åœï¼ŒOK to swap"
+
+#: ex_docmd.c:1864
+msgid "E494: Use w or w>>"
+msgstr "E494: 請使用 w 或 w>>"
+
+#: ex_docmd.c:3446
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: 抱歉, 本命令在此版本中沒有實作"
+
+#: ex_docmd.c:3624
+msgid "E172: Only one file name allowed"
+msgstr "E172: åªèƒ½æœ‰ä¸€å€‹æª”"
+
+#: ex_docmd.c:4191
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "還有 %d 個檔案未編輯. 確定è¦é›¢é–‹ï¼Ÿ"
+
+#: ex_docmd.c:4198
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: 還有 %ld 個檔案未編輯"
+
+#: ex_docmd.c:4292
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: 命令已經存在, 請使用 ! 強制é‡æ–°å®šç¾©"
+
+#: ex_docmd.c:4397
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" å稱 åƒæ•¸ ç¯„åœ å®Œæ•´ 定義 "
+
+#: ex_docmd.c:4486
+msgid "No user-defined commands found"
+msgstr "找ä¸åˆ°ä½¿ç”¨è€…定義的命令"
+
+#: ex_docmd.c:4517
+msgid "E175: No attribute specified"
+msgstr "E175: 沒有指定的屬性"
+
+#: ex_docmd.c:4569
+msgid "E176: Invalid number of arguments"
+msgstr "E176: ä¸æ­£ç¢ºçš„åƒæ•¸æ•¸ç›®"
+
+#: ex_docmd.c:4584
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: ä¸èƒ½æŒ‡å®šå…©æ¬¡æ•¸ç›®"
+
+#: ex_docmd.c:4594
+msgid "E178: Invalid default value for count"
+msgstr "E178: 數目的é è¨­åƒæ•¸ä¸æ­£ç¢º"
+
+#: ex_docmd.c:4622
+msgid "E179: argument required for complete"
+msgstr "E179: 指令需è¦åƒæ•¸æ‰èƒ½å®Œæˆ"
+
+#: ex_docmd.c:4641
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: ä¸å®Œæ•´çš„值: '%s'"
+
+#: ex_docmd.c:4649
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: ä¸æ­£ç¢ºçš„屬性: %s"
+
+#: ex_docmd.c:4690
+msgid "E182: Invalid command name"
+msgstr "E182: 指令å稱ä¸æ­£ç¢º"
+
+#: ex_docmd.c:4705
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: 使用者自定指令必須以大寫字æ¯é–‹å§‹"
+
+#: ex_docmd.c:4774
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: 沒有使用者自定的命令: %s"
+
+#: ex_docmd.c:5230
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: 找ä¸åˆ°é¡è‰²æ¨£å¼ %s"
+
+#: ex_docmd.c:5238
+msgid "Greetings, Vim user!"
+msgstr "å—¨, Vim 使用者ï¼"
+
+#: ex_docmd.c:5946
+msgid "Edit File in new window"
+msgstr "在新視窗編輯檔案"
+
+#: ex_docmd.c:6219
+msgid "No swap file"
+msgstr "無暫存檔"
+
+#: ex_docmd.c:6323
+msgid "Append File"
+msgstr "附加檔案"
+
+#: ex_docmd.c:6387
+msgid "E186: No previous directory"
+msgstr "E186: 沒有å‰ä¸€å€‹ç›®éŒ„"
+
+#: ex_docmd.c:6469
+msgid "E187: Unknown"
+msgstr "E187: 無法辦識的標記"
+
+#: ex_docmd.c:6554
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: :winsize 需è¦å…©å€‹åƒæ•¸"
+
+#: ex_docmd.c:6605
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "視窗ä½ç½®: X %d, Y %d"
+
+#: ex_docmd.c:6610
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: 在您的平å°ä¸Šç„¡æ³•ç²å¾—視窗ä½ç½®"
+
+#: ex_docmd.c:6620
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: :winpos 需è¦å…©å€‹åƒæ•¸"
+
+#: ex_docmd.c:6899
+msgid "Save Redirection"
+msgstr "儲存 Redirection"
+
+#: ex_docmd.c:7046
+msgid "Save View"
+msgstr "儲存 View"
+
+#: ex_docmd.c:7047
+msgid "Save Session"
+msgstr "儲存 Session"
+
+#: ex_docmd.c:7049
+msgid "Save Setup"
+msgstr "儲存設定"
+
+#: ex_docmd.c:7200
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" 已存在 (請用 ! 強制執行)"
+
+#: ex_docmd.c:7205
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: 無法以寫入模å¼é–‹å•Ÿ \"%s\""
+
+#. set mark
+#: ex_docmd.c:7229
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: åƒæ•¸å¿…須是英文字æ¯æˆ–å‘å‰/後的引號"
+
+#: ex_docmd.c:7271
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: :normal éžè¿´å±¤æ•¸éŽæ·±"
+
+#: ex_docmd.c:7772
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: 沒有 '#' å¯æ›¿ä»£çš„檔å"
+
+#: ex_docmd.c:7803
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: 沒有 Autocommand 檔å以å–代 \"<afile>\""
+
+#: ex_docmd.c:7811
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "E496: 沒有 Autocommand ç·©è¡å€å稱以å–代 \"<abuf>\""
+
+#: ex_docmd.c:7822
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr "E497: 沒有 Autocommand 符åˆå稱以å–代 \"<amatch>\""
+
+#: ex_docmd.c:7832
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr "E498: 沒有 :source 檔å以å–代 \"<sfile>\""
+
+#: ex_docmd.c:7873
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: '%' 或 '#' 指å‘空檔å,åªèƒ½ç”¨æ–¼ \":p:h\""
+
+#: ex_docmd.c:7875
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: 輸入為空字串"
+
+#: ex_docmd.c:8802
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: ç„¡æ³•è®€å– viminfo"
+
+#: ex_docmd.c:8975
+msgid "E196: No digraphs in this version"
+msgstr "E196: 本版本無複åˆå­—å…ƒ(digraph)"
+
+#: ex_eval.c:407
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr "E608: ä¸èƒ½ :throw 用 'Vim' 開頭的例外"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:488
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "丟出例外: %s"
+
+#: ex_eval.c:530
+#, c-format
+msgid "Exception finished: %s"
+msgstr "例外çµæŸï¼š %s"
+
+#: ex_eval.c:531
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "已丟棄例外: %s"
+
+#: ex_eval.c:582 ex_eval.c:620
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, 行 %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:596
+#, c-format
+msgid "Exception caught: %s"
+msgstr "發生例外:%s"
+
+#: ex_eval.c:667
+#, c-format
+msgid "%s made pending"
+msgstr "%s é€ æˆ pending"
+
+#: ex_eval.c:670
+#, c-format
+msgid "%s resumed"
+msgstr "%s 已回復"
+
+#: ex_eval.c:674
+#, c-format
+msgid "%s discarded"
+msgstr "%s 已丟棄"
+
+#: ex_eval.c:700
+msgid "Exception"
+msgstr "例外"
+
+#: ex_eval.c:706
+msgid "Error and interrupt"
+msgstr "錯誤與中斷"
+
+#: ex_eval.c:708 gui.c:4237
+msgid "Error"
+msgstr "錯誤"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:710
+msgid "Interrupt"
+msgstr "中斷"
+
+#: ex_eval.c:779
+msgid "E579: :if nesting too deep"
+msgstr "E579: :if 層數éŽæ·±"
+
+#: ex_eval.c:816
+msgid "E580: :endif without :if"
+msgstr "E580: :endif 缺少å°æ‡‰çš„ :if"
+
+#: ex_eval.c:860
+msgid "E581: :else without :if"
+msgstr "E581: :else 缺少å°æ‡‰çš„ :if"
+
+#: ex_eval.c:863
+msgid "E582: :elseif without :if"
+msgstr "E582: :elseif 缺少å°æ‡‰çš„ :if"
+
+#: ex_eval.c:870
+msgid "E583: multiple :else"
+msgstr "E583: å¤šé‡ :else"
+
+#: ex_eval.c:873
+msgid "E584: :elseif after :else"
+msgstr "E584: :elseif 在 :else 之後"
+
+#: ex_eval.c:940
+msgid "E585: :while nesting too deep"
+msgstr "E585: :while 層數éŽæ·±"
+
+#: ex_eval.c:996
+msgid "E586: :continue without :while"
+msgstr "E586: :continue 缺少å°æ‡‰çš„ :while"
+
+#: ex_eval.c:1036
+msgid "E587: :break without :while"
+msgstr "E587: :break 缺少å°æ‡‰çš„ :while"
+
+#: ex_eval.c:1235
+msgid "E601: :try nesting too deep"
+msgstr "E601: :if 層數éŽæ·±"
+
+#: ex_eval.c:1278
+msgid "E603: :catch without :try"
+msgstr "E603: :catch 沒有 :try"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1300
+msgid "E604: :catch after :finally"
+msgstr "E604: :catch 在 :finally 之後"
+
+#: ex_eval.c:1418
+msgid "E606: :finally without :try"
+msgstr "E606: :finally 沒有 :try"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1442
+msgid "E607: multiple :finally"
+msgstr "E607: å¤šé‡ :finally"
+
+#: ex_eval.c:1551
+msgid "E602: :endtry without :try"
+msgstr "E602: :endif 缺少å°æ‡‰çš„ :if"
+
+#: ex_eval.c:1857
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction 必須在函å¼å…§éƒ¨ä½¿ç”¨"
+
+#: ex_getln.c:2967
+msgid "tagname"
+msgstr "標籤å稱"
+
+#: ex_getln.c:2970
+msgid " kind file\n"
+msgstr "類檔案\n"
+
+#: ex_getln.c:4176
+msgid "'history' option is zero"
+msgstr "é¸é … 'history' 是零"
+
+#: ex_getln.c:4416
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s æ­·å²è¨˜éŒ„ (新到舊):\n"
+
+#: ex_getln.c:4417
+msgid "Command Line"
+msgstr "命令列"
+
+#: ex_getln.c:4418
+msgid "Search String"
+msgstr "æœå°‹å­—串"
+
+#: ex_getln.c:4419
+msgid "Expression"
+msgstr "é‹ç®—å¼"
+
+#: ex_getln.c:4420
+msgid "Input Line"
+msgstr "輸入行"
+
+#: ex_getln.c:4450
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar 超éŽå‘½ä»¤é•·åº¦"
+
+#: ex_getln.c:4624
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: 已刪除掉作用中的視窗或暫存å€"
+
+#: fileio.c:373
+msgid "Illegal file name"
+msgstr "ä¸æ­£ç¢ºçš„檔å"
+
+#: fileio.c:397 fileio.c:522 fileio.c:2686 fileio.c:2727
+msgid "is a directory"
+msgstr "是目錄"
+
+#: fileio.c:399
+msgid "is not a file"
+msgstr "ä¸æ˜¯æª”案"
+
+#: fileio.c:544 fileio.c:3833
+msgid "[New File]"
+msgstr "[未命å]"
+
+#: fileio.c:566
+msgid "[Permission Denied]"
+msgstr "[權é™ä¸è¶³]"
+
+#: fileio.c:670
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre Autocommand 使程å¼ç„¡æ³•è®€å–此檔"
+
+#: fileio.c:672
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *Filter* Autocommand ä¸å¯ä»¥æ›´æ”¹ç·©è¡å€çš„內容"
+
+#: fileio.c:693
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: 從標準輸入讀å–...\n"
+
+#: fileio.c:699
+msgid "Reading from stdin..."
+msgstr "從標準輸入讀å–..."
+
+#. Re-opening the original file failed!
+#: fileio.c:944
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: 轉æ›éŒ¯èª¤"
+
+#: fileio.c:1892
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:1899
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:1906
+msgid "[socket]"
+msgstr "[socket]"
+
+#: fileio.c:1914
+msgid "[RO]"
+msgstr "[唯讀]"
+
+#: fileio.c:1924
+msgid "[CR missing]"
+msgstr "[缺少CR]'"
+
+#: fileio.c:1929
+msgid "[NL found]"
+msgstr "[找到NL]"
+
+#: fileio.c:1934
+msgid "[long lines split]"
+msgstr "[分割éŽé•·è¡Œ]"
+
+#: fileio.c:1940 fileio.c:3817
+msgid "[NOT converted]"
+msgstr "[未轉æ›]"
+
+#: fileio.c:1945 fileio.c:3822
+msgid "[converted]"
+msgstr "[已轉æ›]"
+
+#: fileio.c:1952 fileio.c:3847
+msgid "[crypted]"
+msgstr "[已加密]"
+
+#: fileio.c:1959
+msgid "[CONVERSION ERROR]"
+msgstr "轉æ›éŒ¯èª¤"
+
+#: fileio.c:1965
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[è¡Œ %ld 有ä¸æ­£ç¢ºçš„ä½å…ƒ]"
+
+#: fileio.c:1972
+msgid "[READ ERRORS]"
+msgstr "[讀å–錯誤]"
+
+#: fileio.c:2188
+msgid "Can't find temp file for conversion"
+msgstr "找ä¸åˆ°è½‰æ›ç”¨çš„暫存檔"
+
+#: fileio.c:2195
+msgid "Conversion with 'charconvert' failed"
+msgstr "字元集轉æ›éŒ¯èª¤"
+
+#: fileio.c:2198
+msgid "can't read output of 'charconvert'"
+msgstr "ç„¡æ³•è®€å– 'charconvert' 的輸出"
+
+#: fileio.c:2601
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Autocommand 刪除或釋放了è¦å¯«å…¥çš„ç·©è¡å€"
+
+#: fileio.c:2624
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Autocommand æ„外地改變了行號"
+
+#: fileio.c:2692 fileio.c:2710
+msgid "is not a file or writable device"
+msgstr "ä¸æ˜¯æª”案或å¯å¯«å…¥çš„è£ç½®"
+
+#: fileio.c:2762
+msgid "is read-only (add ! to override)"
+msgstr "是唯讀檔 (請使用 ! 強制執行)"
+
+#: fileio.c:3065
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: 無法寫入備份檔 (請使用 ! 強制執行)"
+
+#: fileio.c:3077
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr "E507: 無法關閉備份檔 (請使用 ! 強制執行)"
+
+#: fileio.c:3079
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr "E508: 無法讀å–檔案以供備份 (請使用 ! 強制執行)"
+
+#: fileio.c:3095
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: 無法建立備份檔 (請使用 ! 強制執行)"
+
+#: fileio.c:3198
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: 無法製作備份檔 (請使用 ! 強制執行)"
+
+#: fileio.c:3260
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr "E460: Resource fork 會消失 (請使用 ! 強制執行)"
+
+#: fileio.c:3361
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: 找ä¸åˆ°å¯«å…¥ç”¨çš„暫存檔"
+
+#: fileio.c:3379
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr "E213: ç„¡æ³•è½‰æ› (請使用 ! 強制ä¸è½‰æ›å¯«å…¥)"
+
+#: fileio.c:3414
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: 無法以寫入模å¼é–‹å•Ÿé€£çµæª”案"
+
+#: fileio.c:3418
+msgid "E212: Can't open file for writing"
+msgstr "E212: 無法以寫入模å¼é–‹å•Ÿ"
+
+#: fileio.c:3668
+msgid "E512: Close failed"
+msgstr "E512: 關閉失敗"
+
+#: fileio.c:3739
+msgid "E513: write error, conversion failed"
+msgstr "E513: 無法寫入 -- 轉æ›å¤±æ•—"
+
+#: fileio.c:3745
+msgid "E514: write error (file system full?)"
+msgstr "E514: 寫入錯誤 (檔案系統已滿?)"
+
+#: fileio.c:3812
+msgid " CONVERSION ERROR"
+msgstr "轉æ›éŒ¯èª¤"
+
+#: fileio.c:3828
+msgid "[Device]"
+msgstr "[è£ç½®]"
+
+#: fileio.c:3833
+msgid "[New]"
+msgstr "[æ–°]"
+
+#: fileio.c:3855
+msgid " [a]"
+msgstr "[a]"
+
+#: fileio.c:3855
+msgid " appended"
+msgstr " 已附加"
+
+#: fileio.c:3857
+msgid " [w]"
+msgstr "[w]"
+
+#: fileio.c:3857
+msgid " written"
+msgstr " 已寫入"
+
+#: fileio.c:3910
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: Patch 模å¼: 無法儲存原始檔案"
+
+#: fileio.c:3932
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: Patch 模å¼: 無法變更空的原始檔案"
+
+#: fileio.c:3947
+msgid "E207: Can't delete backup file"
+msgstr "E207: 無法刪除備份檔"
+
+#: fileio.c:4008
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"警告: 原始檔案æµå¤±æˆ–æ壞\n"
+
+#: fileio.c:4010
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "在檔案正確寫入å‰è«‹å‹¿é›¢é–‹ç·¨è¼¯å™¨!"
+
+#: fileio.c:4099
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:4099
+msgid "[dos format]"
+msgstr "[dos æ ¼å¼]"
+
+#: fileio.c:4106
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:4106
+msgid "[mac format]"
+msgstr "[mac æ ¼å¼]"
+
+#: fileio.c:4113
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:4113
+msgid "[unix format]"
+msgstr "[unix æ ¼å¼]"
+
+#: fileio.c:4140
+msgid "1 line, "
+msgstr "1 行, "
+
+#: fileio.c:4142
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld 行, "
+
+#: fileio.c:4145
+msgid "1 character"
+msgstr "一個字元"
+
+#: fileio.c:4147
+#, c-format
+msgid "%ld characters"
+msgstr "%ld個字元"
+
+#: fileio.c:4157
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:4157
+msgid "[Incomplete last line]"
+msgstr "[çµå°¾è¡Œä¸å®Œæ•´]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4176
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "警告: 本檔案自上次讀入後已變動!!!"
+
+#: fileio.c:4178
+msgid "Do you really want to write to it"
+msgstr "確定è¦å¯«å…¥å—Ž"
+
+#: fileio.c:5219
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: 寫入檔案 \"%s\" 錯誤"
+
+#: fileio.c:5226
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: 關閉檔案 \"%s\" 錯誤"
+
+#: fileio.c:5229
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: 讀å–檔案 \"%s\" 錯誤"
+
+#: fileio.c:5448
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: FileChangedShell autocommand 刪除緩è¡å€"
+
+#: fileio.c:5456
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: 警告: 檔案 \"%s\" 已經ä¸å­˜åœ¨"
+
+#: fileio.c:5469
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr "W12: 警告: 檔案 \"%s\" 自上次讀入後已變動, 而且編輯中的緩è¡å€ä¹Ÿæ›´å‹•äº†"
+
+#: fileio.c:5472
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: 警告: 檔案 \"%s\" 自上次讀入後已變動"
+
+#: fileio.c:5474
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: 警告: 檔案 \"%s\" 的權é™èˆ‡ä¸Šæ¬¡è®€å…¥æ™‚ä¸ä¸€æ¨£ (有變動éŽ)"
+
+# 'mode' seems better as translated to 'permission'?
+#: fileio.c:5484
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: 警告: 檔案 \"%s\" 在開始編輯後åˆè¢«å»ºç«‹äº†"
+
+#: fileio.c:5501
+msgid "Warning"
+msgstr "警告"
+
+#: fileio.c:5502
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"確定(&O)\n"
+"載入檔案(&L)"
+
+#: fileio.c:5600
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: 無法準備é‡æ–°è¼‰å…¥ \"%s\""
+
+#: fileio.c:5619
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: 無法é‡æ–°è¼‰å…¥ \"%s\""
+
+#: fileio.c:6201
+msgid "--Deleted--"
+msgstr "--已刪除--"
+
+#. the group doesn't exist
+#: fileio.c:6361
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: 無此群組: \"%s\""
+
+#: fileio.c:6486
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: * 後é¢æœ‰ä¸æ­£ç¢ºçš„å­—å…ƒ: %s"
+
+#: fileio.c:6497
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: 無此事件: %s"
+
+#. Highlight title
+#: fileio.c:6646
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Auto-Commands ---"
+
+#: fileio.c:6917
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: 無法å°æ‰€æœ‰äº‹ä»¶åŸ·è¡Œ autocommand"
+
+#: fileio.c:6940
+msgid "No matching autocommands"
+msgstr "找ä¸åˆ°å°æ‡‰çš„ autocommand"
+
+#: fileio.c:7260
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: autocommand 層數éŽæ·±"
+
+#: fileio.c:7528
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Auto commands: \"%s\""
+
+#: fileio.c:7536
+#, c-format
+msgid "Executing %s"
+msgstr "執行 %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7604
+#, c-format
+msgid "autocommand %s"
+msgstr "autocommand %s"
+
+#: fileio.c:8171
+msgid "E219: Missing {."
+msgstr "E219: 缺少 {."
+
+#: fileio.c:8173
+msgid "E220: Missing }."
+msgstr "E220: 缺少 }."
+
+#: fold.c:66
+msgid "E490: No fold found"
+msgstr "E490: 找ä¸åˆ°ä»»ä½• fold"
+
+#: fold.c:553
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: 無法在目å‰çš„ 'foldmethod' 下建立 fold"
+
+#: fold.c:555
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: 無法在目å‰çš„ 'foldmethod' 下刪除 fold"
+
+#: getchar.c:246
+msgid "E222: Add to read buffer"
+msgstr "E222: 加入讀å–ç·©è¡å€ä¸­"
+
+#: getchar.c:2146
+msgid "E223: recursive mapping"
+msgstr "E223: éžè¿´ mapping"
+
+#: getchar.c:2994
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: %s 已經有全域 abbreviation 了"
+
+#: getchar.c:2997
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: %s 已經有全域 mapping 了"
+
+#: getchar.c:3124
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: %s 已經有 abbreviation 了"
+
+#: getchar.c:3127
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: %s 的 mapping 已經存在"
+
+#: getchar.c:3191
+msgid "No abbreviation found"
+msgstr "找ä¸åˆ° abbreviation"
+
+#: getchar.c:3193
+msgid "No mapping found"
+msgstr "沒有這個 mapping å°æ‡‰"
+
+#: getchar.c:4083
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: ä¸æ­£ç¢ºçš„模å¼"
+
+#: gui.c:218
+msgid "E229: Cannot start the GUI"
+msgstr "E229: 無法啟動圖型界é¢"
+
+#: gui.c:347
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: 無法讀å–檔案 \"%s\""
+
+#: gui.c:472
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: ä¸æ­£ç¢ºçš„ 'guifontwide'"
+
+#: gui.c:3925
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: ä¸èƒ½é…ç½®é¡è‰² %s"
+
+#: gui_at_fs.c:290
+msgid "<cannot open> "
+msgstr "<ä¸èƒ½é–‹å•Ÿ>"
+
+#: gui_at_fs.c:1115
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: ä¸èƒ½ä½¿ç”¨ %s å­—åž‹"
+
+#: gui_at_fs.c:2538
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: 無法回到目å‰ç›®éŒ„"
+
+#: gui_at_fs.c:2557
+msgid "Pathname:"
+msgstr "路徑:"
+
+#: gui_at_fs.c:2563
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: 無法å–å¾—ç›®å‰ç›®éŒ„"
+
+#: gui_at_fs.c:2571 gui_motif.c:1619
+msgid "OK"
+msgstr "確定"
+
+#: gui_at_fs.c:2571 gui_gtk.c:2625 gui_motif.c:1614 gui_motif.c:2844
+msgid "Cancel"
+msgstr "å–消"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "æ²å‹•è»¸: ä¸èƒ½è¨­å®š thumb pixmap çš„ä½ç½®"
+
+#: gui_athena.c:1956 gui_motif.c:1867
+msgid "Vim dialog"
+msgstr "Vim å°è©±ç›’"
+
+#: gui_beval.c:91
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: ä¸èƒ½å°è¨Šæ¯èˆ‡ callback 建立 BallonEval"
+
+#: gui_gtk.c:1561
+msgid "Vim dialog..."
+msgstr "Vim å°è©±ç›’..."
+
+#: gui_gtk.c:1992 message.c:2525
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Y是\n"
+"&Nå¦\n"
+"&Cå–消"
+
+#: gui_gtk.c:2152
+msgid "Input _Methods"
+msgstr "輸入法"
+
+#: gui_gtk.c:2418 gui_motif.c:2763
+msgid "VIM - Search and Replace..."
+msgstr "VIM - 尋找與å–代..."
+
+#: gui_gtk.c:2426 gui_motif.c:2765
+msgid "VIM - Search..."
+msgstr "VIM - 尋找..."
+
+#: gui_gtk.c:2458 gui_motif.c:2883
+msgid "Find what:"
+msgstr "æœå°‹:"
+
+#: gui_gtk.c:2478 gui_motif.c:2915
+msgid "Replace with:"
+msgstr "å–代為:"
+
+#. whole word only button
+#: gui_gtk.c:2510 gui_motif.c:3031
+msgid "Match whole word only"
+msgstr "åªæœå°‹å®Œå…¨ç›¸åŒçš„å­—"
+
+#. match case button
+#: gui_gtk.c:2523 gui_motif.c:3043
+msgid "Match case"
+msgstr "符åˆå¤§å°å¯«"
+
+#: gui_gtk.c:2535 gui_motif.c:2985
+msgid "Direction"
+msgstr "æ–¹å‘"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2547 gui_motif.c:2997
+msgid "Up"
+msgstr "å‘上"
+
+#: gui_gtk.c:2551 gui_motif.c:3005
+msgid "Down"
+msgstr "å‘下"
+
+#: gui_gtk.c:2577 gui_gtk.c:2579 gui_motif.c:2787
+msgid "Find Next"
+msgstr "找下一個"
+
+#: gui_gtk.c:2596 gui_gtk.c:2598 gui_motif.c:2804
+msgid "Replace"
+msgstr "å–代"
+
+#: gui_gtk.c:2609 gui_gtk.c:2611 gui_motif.c:2817
+msgid "Replace All"
+msgstr "å–代全部"
+
+#: gui_gtk_x11.c:2285
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: ç”± Session 管ç†å“¡æ”¶åˆ° \"die\" è¦æ±‚\n"
+
+#: gui_gtk_x11.c:3424
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: 主視窗爛掉\n"
+
+#: gui_gtk_x11.c:4038
+msgid "Font Selection"
+msgstr "å­—åž‹é¸æ“‡"
+
+#: gui_gtk_x11.c:5890 ui.c:2009
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "使用 CUT_BUFFER0 來å–代空é¸æ“‡"
+
+#: gui_motif.c:1613 gui_motif.c:1616
+msgid "Filter"
+msgstr "éŽæ¿¾å™¨"
+
+#: gui_motif.c:1615
+msgid "Directories"
+msgstr "目錄"
+
+#: gui_motif.c:1617
+msgid "Help"
+msgstr "輔助說明"
+
+#: gui_motif.c:1618
+msgid "Files"
+msgstr "檔案"
+
+#: gui_motif.c:1620
+msgid "Selection"
+msgstr "é¸æ“‡"
+
+#: gui_motif.c:2830
+msgid "Undo"
+msgstr "復原"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: 無法開啟 Zap 字型 '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: 無法使用字型 %s"
+
+#: gui_riscos.c:3269
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"é€å‡ºä¸­æ–·å­ç¨‹å¼çš„訊æ¯ä¸­.\n"
+
+#: gui_w32.c:759
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: ä¸æ”¯æ´åƒæ•¸ \"-%s\"。請用 OLE 版本。"
+
+#: gui_w48.c:2029
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "æœå°‹å­—串 (使用 '\\\\' 來表示 '\\')"
+
+#: gui_w48.c:2054
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "æœå°‹åŠå–代字串 (使用 '\\\\' 來表示 '\\')"
+
+#: gui_x11.c:1445
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr "Vim E458: 無法é…ç½® color map 項目,有些é¡è‰²çœ‹èµ·ä¾†æœƒæ€ªæ€ªçš„"
+
+#: gui_x11.c:2019
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: Fontset %s 沒有設定正確的字型以供顯示這些字元集:"
+
+#: gui_x11.c:2062
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: 字型集(Fontset)å稱: %s"
+
+#: gui_x11.c:2063
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "'%s' ä¸æ˜¯å›ºå®šå¯¬åº¦å­—åž‹"
+
+#: gui_x11.c:2082
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: 字型集(Fontset)å稱: %s\n"
+
+#: gui_x11.c:2083
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Font0: %s\n"
+
+#: gui_x11.c:2084
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Font1: %s\n"
+
+#: gui_x11.c:2085
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "å­—åž‹%d寬度ä¸æ˜¯å­—åž‹0çš„å…©å€\n"
+
+#: gui_x11.c:2086
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "字型0的寬度:%ld\n"
+
+#: gui_x11.c:2087
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"字型1寬度: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: Hangul automata 錯誤"
+
+#: if_cscope.c:26
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: 用法: cs[cope] %s"
+
+#: if_cscope.c:67
+msgid "Add a new database"
+msgstr "新增資料庫"
+
+#: if_cscope.c:69
+msgid "Query for a pattern"
+msgstr "輸入 pattern"
+
+#: if_cscope.c:71
+msgid "Show this message"
+msgstr "顯示此訊æ¯"
+
+#: if_cscope.c:73
+msgid "Kill a connection"
+msgstr "çµæŸé€£ç·š"
+
+#: if_cscope.c:75
+msgid "Reinit all connections"
+msgstr "é‡è¨­æ‰€æœ‰é€£ç·š"
+
+#: if_cscope.c:77
+msgid "Show connections"
+msgstr "顯示連線"
+
+#: if_cscope.c:108
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "這個 cscope 命令ä¸æ”¯æ´åˆ†å‰²èž¢å¹•\n"
+
+#: if_cscope.c:143
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: 用法: cstag <識別字ident>"
+
+#: if_cscope.c:199
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: 找ä¸åˆ° tag"
+
+#: if_cscope.c:407 if_cscope.c:451
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: stat(%s) 錯誤: %d"
+
+#: if_cscope.c:461 if_cscope.c:468
+#, c-format
+msgid "Added cscope database %s"
+msgstr "新增 cscope 資料庫 %s"
+
+#: if_cscope.c:475
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s ä¸æ˜¯ç›®éŒ„或 cscope 資料庫"
+
+#: if_cscope.c:559
+#, c-format
+msgid "E565: error reading cscope connection %d"
+msgstr "E565: è®€å– cscope 連線 %d 錯誤"
+
+#: if_cscope.c:636
+msgid "E561: unknown cscope search type"
+msgstr "E561: 未知的 cscope æœå°‹å½¢æ…‹"
+
+#: if_cscope.c:683
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: 無法建立與 cscope 的 pipe 連線"
+
+#: if_cscope.c:748
+msgid "cs_create_connection exec failed"
+msgstr "cs_create_connection 執行失敗"
+
+#: if_cscope.c:758
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen 失敗 (to_fp)"
+
+#: if_cscope.c:760
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen 失敗 (fr_fp)"
+
+#: if_cscope.c:788
+msgid "E567: no cscope connections"
+msgstr "E567: 沒有 cscope 連線"
+
+#: if_cscope.c:858
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: 找ä¸åˆ°ç¬¦åˆ cscope çš„æœå°‹ %s / %s"
+
+#: if_cscope.c:902
+msgid "cscope commands:\n"
+msgstr "cscope 命令:\n"
+
+#: if_cscope.c:905
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)\n"
+msgstr "%-5s: %-30s (用法: %s)\n"
+
+#: if_cscope.c:973
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: é‡è¤‡çš„ cscope 資料庫未被加入"
+
+#: if_cscope.c:984
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: å·²é”到 cscope 最大連線數目"
+
+#: if_cscope.c:1105
+msgid "E260: cscope connection not found"
+msgstr "E260: 找ä¸åˆ° cscope 連線"
+
+#: if_cscope.c:1108
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: 找ä¸åˆ° cscope 連線 %s"
+
+#: if_cscope.c:1144
+msgid "cscope connection closed"
+msgstr "cscope 連線已關閉"
+
+#: if_cscope.c:1152
+#, c-format
+msgid "cscope connection %s closed\n"
+msgstr "cscope 連線 %s 已關閉\n"
+
+#. should not reach here
+#: if_cscope.c:1293
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: cs_manage_matches åš´é‡éŒ¯èª¤"
+
+#: if_cscope.c:1344
+#, c-format
+msgid "E262: error reading cscope connection %d"
+msgstr "E262: è®€å– cscope 連線 %d 錯誤"
+
+#: if_cscope.c:1452
+msgid "couldn't malloc\n"
+msgstr "無法使用 malloc\n"
+
+#: if_cscope.c:1457
+#, c-format
+msgid "Cscope tag: %s\n"
+msgstr "Cscope 標籤(tag): %s\n"
+
+#: if_cscope.c:1461
+msgid " # line"
+msgstr " # 行 "
+
+#: if_cscope.c:1463
+msgid "filename / context / line\n"
+msgstr "檔å / 內文 / 行號\n"
+
+#: if_cscope.c:1721
+msgid "All cscope databases reset"
+msgstr "é‡è¨­æ‰€æœ‰ cscope 資料庫"
+
+#: if_cscope.c:1788
+msgid "no cscope connections\n"
+msgstr "沒有 cscope 連線\n"
+
+#: if_cscope.c:1792
+msgid " # pid database name prepend path\n"
+msgstr " # pid 資料庫å稱 prepend path\n"
+
+#: if_cscope.c:1803
+#, c-format
+msgid "%2d %-5ld %-34s <none>\n"
+msgstr "%2d %-5ld %-34s <ç„¡>\n"
+
+#: if_python.c:394
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr "E263: 抱歉,這個命令無法使用,Python 程å¼åº«æ²’有載入。"
+
+#: if_python.c:596
+msgid "can't delete OutputObject attributes"
+msgstr "無法刪除 OutputObject 屬性"
+
+#: if_python.c:603
+msgid "softspace must be an integer"
+msgstr "softspace 必需是整數"
+
+#: if_python.c:611
+msgid "invalid attribute"
+msgstr "ä¸æ­£ç¢ºçš„屬性"
+
+#: if_python.c:650 if_python.c:664
+msgid "writelines() requires list of strings"
+msgstr "writelines() éœ€è¦ string list 當åƒæ•¸"
+
+#: if_python.c:790
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: 無法åˆå§‹ I/O 物件"
+
+#: if_python.c:975 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "ä¸æ­£ç¢ºçš„é‹ç®—å¼"
+
+#: if_python.c:989 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "因為編譯時沒有加入é‹ç®—å¼(expression)的程å¼ç¢¼ï¼Œæ‰€ä»¥ç„¡æ³•ä½¿ç”¨é‹ç®—å¼"
+
+#: if_python.c:1002
+msgid "attempt to refer to deleted buffer"
+msgstr "試圖使用已被刪除的 buffer"
+
+#: if_python.c:1017 if_python.c:1058 if_python.c:1122 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "行號超出範åœ"
+
+#: if_python.c:1257
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<buffer 物件 (已刪除): %8lX>"
+
+#: if_python.c:1348 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "標記å稱ä¸æ­£ç¢º"
+
+#: if_python.c:1623
+msgid "no such buffer"
+msgstr "ç„¡æ­¤ buffer"
+
+#: if_python.c:1711
+msgid "attempt to refer to deleted window"
+msgstr "試圖使用已被刪除的視窗"
+
+#: if_python.c:1756
+msgid "readonly attribute"
+msgstr "唯讀屬性"
+
+#: if_python.c:1769
+msgid "cursor position outside buffer"
+msgstr "游標定ä½åœ¨ç·©è¡å€ä¹‹å¤–"
+
+#: if_python.c:1846
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<視窗物件(已刪除): %.8lX>"
+
+#: if_python.c:1858
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<視窗物件(未知): %.8lX>"
+
+#: if_python.c:1860
+#, c-format
+msgid "<window %d>"
+msgstr "<視窗 %d>"
+
+#: if_python.c:1936
+msgid "no such window"
+msgstr "無此視窗"
+
+#: if_python.c:2193 if_python.c:2228 if_python.c:2278 if_python.c:2346
+#: if_python.c:2466 if_python.c:2518 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1998
+msgid "cannot save undo information"
+msgstr "無法儲存復原資訊"
+
+#: if_python.c:2195 if_python.c:2285 if_python.c:2357
+msgid "cannot delete line"
+msgstr "ä¸èƒ½åˆªé™¤æ­¤è¡Œ"
+
+#: if_python.c:2230 if_python.c:2373 if_tcl.c:690 if_tcl.c:2020
+msgid "cannot replace line"
+msgstr "ä¸èƒ½æ›¿ä»£æ­¤è¡Œ"
+
+#: if_python.c:2389 if_python.c:2468 if_python.c:2526
+msgid "cannot insert line"
+msgstr "ä¸èƒ½æ›¿ä»£æ’入此行"
+
+#: if_python.c:2630
+msgid "string cannot contain newlines"
+msgstr "字串無法包å«æ–°è¡Œ"
+
+#: if_ruby.c:396
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr "E266: 此命令無法使用,無法載入 Ruby 程å¼åº«(Library)"
+
+#: if_ruby.c:459
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: 未知的 longjmp status %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "切æ›å¯¦ä½œ/定義"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "顯示 base class of:"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "顯示被 override 的 member function"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "讀å–: 從檔案"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "讀å–: 從物件"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "讀å–: 從所有 project"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "讀å–"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "顯示原始碼: "
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "æœå°‹ symbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "ç€è¦½ class"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "顯示階層å¼çš„ class"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "顯示 restricted 階層å¼çš„ class"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref åƒè€ƒåˆ°"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref 被誰åƒè€ƒ:"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref 有"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref 被誰使用:"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "顯示文件: "
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "產生文件: "
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr "無法連線到 SNiFF+。請檢查環境變數 ($PATH 裡必需å¯ä»¥æ‰¾åˆ° sniffemacs)\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: 讀å–錯誤. å–消連線"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ ç›®å‰"
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "未"
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "連線中"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: ä¸æ­£ç¢ºçš„ SNiff+ 呼å«: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: 連線到 SNiFF+ 失敗"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: 未連線到 SNiFF+"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: ä¸æ˜¯ SNiFF+ çš„ç·©è¡å€"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: 寫入錯誤。çµæŸé€£ç·š"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "ç·©è¡å€è™Ÿç¢¼éŒ¯èª¤"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "尚未實作"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "ä¸æ­£ç¢ºçš„é¸é …"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "ä¸èƒ½è¨­å®šè¡Œ"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "沒有設定標記"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "列 %d 行 %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "ä¸èƒ½æ’入或附加此行"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "錯誤的旗標: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "ä¸æ­£ç¢ºçš„ VIM é¸é …"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "éµç›¤ä¸­æ–·"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "vim 錯誤"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "無法建立緩è¡å€/視窗命令: 物件將會被刪除"
+
+#: if_tcl.c:1545
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr "無法註冊 callback 命令: ç·©è¡å€/視窗已經被刪除了"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr "E280: TCL åš´é‡éŒ¯èª¤: reflist 爛掉了!? 請報告給 to vim-dev@vim.org"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr "無法註冊 callback 命令: 找ä¸åˆ°ç·©è¡å€/視窗"
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"E571: 此命令無法使用, 因為無法載入 Tcl 程å¼åº«(Library)"
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr "E281: TCL 錯誤: çµæŸç¢¼ä¸æ˜¯æ•´æ•¸!? 請報告給 to vim-dev@vim.org"
+
+#: if_tcl.c:2006
+msgid "cannot get line"
+msgstr "ä¸èƒ½å–得此行"
+
+#: if_xcmdsrv.c:215
+msgid "Unable to register a command server name"
+msgstr "無法註冊命令伺æœå™¨å稱"
+
+#: if_xcmdsrv.c:465
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: 無法é€å‡ºå‘½ä»¤åˆ°ç›®çš„地程å¼"
+
+#: if_xcmdsrv.c:735
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: ä¸æ­£ç¢ºçš„伺æœå™¨ id : %s"
+
+#: if_xcmdsrv.c:1098
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: VIM 的 registry 設定項有誤。已刪除。"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "ä¸æ­£ç¢ºçš„é¸é …"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "太多編輯åƒæ•¸"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "缺少必è¦çš„åƒæ•¸:"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "無法辨èªæ­¤é¸é …後的命令: "
+
+#: main.c:68
+msgid "Too many \"+command\" or \"-c command\" arguments"
+msgstr "太多 \"+command\" 或 \"-c command\" åƒæ•¸"
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "ä¸æ­£ç¢ºçš„åƒæ•¸: "
+
+#: main.c:469
+msgid "This Vim was not compiled with the diff feature."
+msgstr "您的 Vim 編譯時沒有加入 diff 的能力"
+
+#: main.c:917
+msgid "Attempt to open script file again: \""
+msgstr "試圖å†æ¬¡é–‹å•Ÿ script 檔: \""
+
+#: main.c:921 main.c:928 main.c:972 memline.c:3682 memline.c:3686
+#: version.c:857 version.c:862 version.c:867 version.c:872 version.c:877
+#: version.c:882 version.c:888 version.c:892 version.c:896 version.c:901
+#: version.c:908 version.c:916 version.c:922
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:926
+msgid "Cannot open for reading: \""
+msgstr "無法開啟以讀å–: \""
+
+#: main.c:970
+msgid "Cannot open for script output: \""
+msgstr "無法開啟為 script 輸出: \""
+
+#: main.c:1104
+#, c-format
+msgid "%d files to edit\n"
+msgstr "還有 %d 個檔案等待編輯\n"
+
+#: main.c:1178
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: 注æ„: 輸出ä¸æ˜¯çµ‚端機(螢幕)\n"
+
+#: main.c:1180
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: 注æ„: 輸入ä¸æ˜¯çµ‚端機(éµç›¤)\n"
+
+#. just in case..
+#: main.c:1257
+msgid "pre-vimrc command line"
+msgstr "vimrc å‰å‘½ä»¤åˆ—"
+
+#: main.c:1292
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: 無法讀å–檔案 \"%s\""
+
+#: main.c:2313
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"查詢更多資訊請執行: \"vim -h\"\n"
+
+#: main.c:2346
+msgid "[file ..] edit specified file(s)"
+msgstr "[檔案 ..] 編輯指定的檔案"
+
+#: main.c:2347
+msgid "- read text from stdin"
+msgstr "- 從標準輸入(stdin)讀å–檔案"
+
+#: main.c:2348
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tag 編輯時使用指定的 tag"
+
+#: main.c:2350
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [errorfile] 編輯時載入第一個錯誤"
+
+#: main.c:2359
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+" 用法:"
+
+#: main.c:2362
+msgid " vim [arguments] "
+msgstr "vim [åƒæ•¸] "
+
+#: main.c:2366
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" 或:"
+
+#: main.c:2369
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"åƒæ•¸:\n"
+
+#: main.c:2370
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\tåªæœ‰åœ¨é€™ä¹‹å¾Œçš„檔案"
+
+#: main.c:2372
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\tä¸å±•é–‹è¬ç”¨å­—å…ƒ"
+
+#: main.c:2375
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\t註冊 gvim 到 OLE"
+
+#: main.c:2376
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\tå–消 OLE 中的 gvim 註冊"
+
+#: main.c:2379
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\tä½¿ç”¨åœ–å½¢ç•Œé¢ (åŒ \"gvim\")"
+
+#: main.c:2380
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f 或 --nofork\tå‰æ™¯: 起始圖形界é¢æ™‚ä¸ fork"
+
+#: main.c:2382
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi æ¨¡å¼ (åŒ \"vi\")"
+
+#: main.c:2383
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx æ¨¡å¼ (åŒ \"ex\")"
+
+#: main.c:2384
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\tå®‰éœ (batch) æ¨¡å¼ (åªèƒ½èˆ‡ \"ex\" 一起使用)"
+
+#: main.c:2386
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tDiff æ¨¡å¼ (åŒ \"vimdiff\", å¯è¿…速比較兩檔案ä¸åŒè™•)"
+
+#: main.c:2388
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\tç°¡æ˜“æ¨¡å¼ (åŒ \"evim\", modeless)"
+
+#: main.c:2389
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\tå”¯è®€æ¨¡å¼ (åŒ \"view\")"
+
+#: main.c:2390
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\té™åˆ¶æ¨¡å¼ (åŒ \"rvim\")"
+
+#: main.c:2391
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\tä¸å¯ä¿®æ”¹ (寫入檔案)"
+
+#: main.c:2392
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\tä¸å¯ä¿®æ”¹æ–‡å­—"
+
+#: main.c:2393
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\t二進ä½æ¨¡å¼"
+
+#: main.c:2395
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp 模å¼"
+
+#: main.c:2397
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\t'compatible' 傳統 Vi 相容模å¼"
+
+#: main.c:2398
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\t'nocompatible' ä¸å®Œå…¨èˆ‡å‚³çµ± Vi 相容,å¯ä½¿ç”¨ Vim 加強能力"
+
+#: main.c:2399
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tVerbose 等級"
+
+#: main.c:2400
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\t除錯模å¼"
+
+#: main.c:2401
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\tä¸ä½¿ç”¨æš«å­˜æª”, åªä½¿ç”¨è¨˜æ†¶é«”"
+
+#: main.c:2402
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\t列出暫存檔後離開"
+
+#: main.c:2403
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (加檔å) \t修復上次æ毀的資料(Recover crashed session)"
+
+#: main.c:2404
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\tåŒ -r"
+
+#: main.c:2406
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\tä¸ä½¿ç”¨ newcli 來開啟視窗"
+
+#: main.c:2407
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <device>\t\t使用 <device> åšè¼¸å‡ºå…¥"
+
+#: main.c:2410
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\t啟動為 Hebrew 模å¼"
+
+#: main.c:2413
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\t啟動為 Farsi 模å¼"
+
+#: main.c:2415
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\t設定終端機為 <terminal>"
+
+#: main.c:2416
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\t使用 <vimrc> å–代任何 .vimrc"
+
+#: main.c:2418
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\t使用 <gvimrc> å–代任何 .gvimrc"
+
+#: main.c:2420
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\tä¸è¼‰å…¥ä»»ä½• plugin"
+
+#: main.c:2421
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\té–‹å•Ÿ N 個視窗 (é è¨­æ˜¯æ¯å€‹æª”案一個)"
+
+#: main.c:2422
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\tåŒ -o 但使用垂直分割"
+
+#: main.c:2423
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\t啟動後跳到檔案çµå°¾"
+
+#: main.c:2424
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\t啟動後跳到第 <lnum> 行"
+
+#: main.c:2426
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <command>\t載入任何 vimrc å‰åŸ·è¡Œ <command>"
+
+#: main.c:2428
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <command>\t\t載入第一個檔案後執行 <command>"
+
+#: main.c:2429
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <session>\t\t載入第一個檔案後載入 Session 檔 <session>"
+
+#: main.c:2430
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <scriptin>\t從 <scriptin> 讀入一般模å¼å‘½ä»¤"
+
+#: main.c:2431
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <scriptout>\tå°æª”案 <scriptout> 附加(append)所有輸入的命令"
+
+#: main.c:2432
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <scriptout>\tå°æª”案 <scriptout> 寫入所有輸入的命令"
+
+#: main.c:2434
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\t編輯編碼éŽçš„檔案"
+
+#: main.c:2438
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\t將 vim 與指定的 X-server 連線"
+
+#: main.c:2440
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\tä¸è¦é€£ç·šåˆ° X Server"
+
+#: main.c:2443
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <files>\t編輯 Vim 伺æœå™¨ä¸Šçš„ <files> 後離開"
+
+#: main.c:2444
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-silent <files> 相åŒï¼Œä½†æ²’有伺æœå™¨æ™‚ä¸è­¦å‘Š"
+
+#: main.c:2445
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <files> åŒ --remote, 但會等候檔案完æˆç·¨è¼¯"
+
+#: main.c:2446
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr ""
+"--remote-wait-silent <files> 相åŒï¼Œä½†æ²’伺æœå™¨æ™‚ä¸è­¦å‘Š"
+
+#: main.c:2447
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <keys>\té€å‡º <keys> 到 Vim 伺æœå™¨ä¸¦é›¢é–‹"
+
+#: main.c:2448
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <expr>\t在伺æœå™¨ä¸ŠåŸ·è¡Œ <expr> 並å°å‡ºçµæžœ"
+
+#: main.c:2449
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\t列出å¯ç”¨çš„ Vim 伺æœå™¨å稱並離開"
+
+#: main.c:2450
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <name>\té€è‡³/æˆç‚º Vim 伺æœå™¨ <name>"
+
+#: main.c:2453
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\t使用 <viminfo> è€Œéž .viminfo"
+
+#: main.c:2455
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h 或 --help\tå°å‡ºèªªæ˜Ž(也就是本訊æ¯)後離開"
+
+#: main.c:2456
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\tå°å‡ºç‰ˆæœ¬è³‡è¨Šå¾Œé›¢é–‹"
+
+#: main.c:2460
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"gvim èªå¾—çš„åƒæ•¸ (Motif 版):\n"
+
+#: main.c:2463
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"gvim èªå¾—çš„åƒæ•¸ (Athena 版):\n"
+
+#: main.c:2466
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\t在視窗 <display> 執行 vim"
+
+#: main.c:2467
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\t啟動後圖示化(iconified)"
+
+#: main.c:2469
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <name>\t\tè®€å– Resource 時把 vim çš„å稱視為 <name>"
+
+#: main.c:2470
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (尚未實作)\n"
+
+#: main.c:2472
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <color>\t設定 <color> 為背景色 (也å¯ç”¨ -bg)"
+
+#: main.c:2473
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <color>\t設定 <color> 為一般文字é¡è‰² (也å¯ç”¨ -fg)"
+
+#: main.c:2474 main.c:2494
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <font>\t使用 <font> 為一般字型 (也å¯ç”¨ -fn)"
+
+#: main.c:2475
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <font>\t使用 <font> 為粗體字型"
+
+#: main.c:2476
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <font>\t使用 <font> 為斜體字型"
+
+#: main.c:2477 main.c:2495
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\t使用<geom>為起始ä½ç½® (也å¯ç”¨ -geom)"
+
+#: main.c:2478
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <width>\t使用寬度為 <width> 的邊框 (也å¯ç”¨ -bw)"
+
+#: main.c:2479
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <width> 設定æ²å‹•è»¸å¯¬åº¦ç‚º <width> (也å¯ç”¨ -sw)"
+
+#: main.c:2481
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <height>\t設定é¸å–®åˆ—的高度為 <height> (也å¯ç”¨ -mh)"
+
+#: main.c:2483 main.c:2496
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\t使用å相顯示 (也å¯ç”¨ -rv)"
+
+#: main.c:2484
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\tä¸ä½¿ç”¨å相顯示 (也å¯ç”¨ +rv)"
+
+#: main.c:2485
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\t設定指定的 resource"
+
+#: main.c:2488
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"gvim èªå¾—çš„åƒæ•¸ (RISC OS 版):\n"
+
+#: main.c:2489
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <number>\t視窗åˆå§‹åŒ–寬度"
+
+#: main.c:2490
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <number>\t視窗åˆå§‹åŒ–高度"
+
+#: main.c:2493
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"gvim èªå¾—çš„åƒæ•¸ (GTK+ 版):\n"
+
+#: main.c:2497
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\t在 <display> 執行 vim (也å¯ç”¨ --display)"
+
+#: main.c:2499
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr "--role <role>\t設定ç¨ç‰¹çš„角色(role)以å€åˆ†ä¸»è¦–窗"
+
+#: main.c:2501
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\t在å¦ä¸€å€‹ GTK widget 內開啟 Vim"
+
+#: main.c:2503
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\t顯示 Gnome 相關åƒæ•¸"
+
+#: main.c:2735
+msgid "No display"
+msgstr "無顯示"
+
+#. Failed to send, abort.
+#: main.c:2750
+msgid ": Send failed.\n"
+msgstr ": 傳é€å¤±æ•—。\n"
+
+#. Let vim start normally.
+#: main.c:2756
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": é€å‡ºå¤±æ•—。試圖在本地執行\n"
+
+#: main.c:2794 main.c:2815
+#, c-format
+msgid "%d of %d edited"
+msgstr "已編輯 %d/%d 個檔案"
+
+#: main.c:2837
+msgid "No display: Send expression failed.\n"
+msgstr "ç„¡ Display: 無法傳é€é‹ç®—å¼ã€‚\n"
+
+#: main.c:2849
+msgid ": Send expression failed.\n"
+msgstr ": 無法傳é€é‹ç®—å¼ã€‚\n"
+
+#: mark.c:656
+msgid "No marks set"
+msgstr "沒有設定標記 (mark)"
+
+#: mark.c:658
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: 找ä¸åˆ°ç¬¦åˆ \"%s\" 的標記(mark)"
+
+#. Highlight title
+#: mark.c:669
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"標記 行號 欄 檔案/文字"
+
+#. Highlight title
+#: mark.c:707
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" jump 行號 欄 檔案/文字"
+
+#: mark.c:1072
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# 檔案標記:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1107
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Jumplist (由新到舊):\n"
+
+#: mark.c:1202
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# 檔案內 Mark 記錄 (由新到舊):\n"
+
+#: mark.c:1285
+msgid "Missing '>'"
+msgstr "缺少å°æ‡‰çš„ '>'"
+
+#: mbyte.c:403
+msgid "E543: Not a valid codepage"
+msgstr "E543: ä¸æ­£ç¢ºçš„ codepage"
+
+#: mbyte.c:3879
+msgid "E284: Cannot set IC values"
+msgstr "E284: ä¸èƒ½è¨­å®š IC 數值"
+
+#: mbyte.c:4031
+msgid "E285: Failed to create input context"
+msgstr "E285: 無法建立 input context"
+
+#: mbyte.c:4178
+msgid "E286: Failed to open input method"
+msgstr "E286: 無法開啟輸入法"
+
+#: mbyte.c:4189
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: 警告: 無法移除 IM 的 callback"
+
+#: mbyte.c:4195
+msgid "E288: input method doesn't support any style"
+msgstr "E288: 輸入法ä¸æ”¯æ´ä»»ä½• style"
+
+#: mbyte.c:4252
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: 輸入法ä¸æ”¯æ´ä»»ä½• style"
+
+#: mbyte.c:4326
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: over-the-spot 需è¦å­—型集(Fontset)"
+
+#: mbyte.c:4358
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: ä½ çš„ GTK+ 比 1.2.3 還舊。無法使用狀態å€ã€‚"
+
+#: mbyte.c:4637
+msgid "E292: Input Method Server is not running"
+msgstr "E292: 沒有執行中的輸入法管ç†ç¨‹å¼(Input Method Server)"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: å€å¡Šæœªè¢«éŽ–定"
+
+#: memfile.c:989
+msgid "E294: Seek error in swap file read"
+msgstr "E294: 暫存檔讀å–錯誤"
+
+#: memfile.c:994
+msgid "E295: Read error in swap file"
+msgstr "E295: 暫存檔讀å–錯誤"
+
+#: memfile.c:1046
+msgid "E296: Seek error in swap file write"
+msgstr "E296: 暫存檔寫入錯誤"
+
+#: memfile.c:1064
+msgid "E297: Write error in swap file"
+msgstr "E297: 暫存檔寫入錯誤"
+
+#: memfile.c:1261
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: 暫存檔已經存在! (å°å¿ƒç¬¦è™Ÿé€£çµçš„安全æ¼æ´ž!?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: 找ä¸åˆ°å€å¡Š 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: 找ä¸åˆ°å€å¡Š 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: 找ä¸åˆ°å€å¡Š 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: 噢噢, 暫存檔ä¸è¦‹äº†!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: 無法改變暫存檔的å稱"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: 無法開啟暫存檔 \"%s\", ä¸å¯èƒ½ä¿®å¾©äº†"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: 找ä¸åˆ°å€å¡Š 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: 找ä¸åˆ° %s 的暫存檔"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "è«‹é¸æ“‡ä½ è¦ä½¿ç”¨çš„暫存檔 (按0 離開): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: 無法開啟 %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "無法讀å–å€å¡Š 0:"
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"å¯èƒ½æ˜¯ä½ æ²’åšéŽä»»ä½•ä¿®æ”¹æˆ–是 Vim 還來ä¸åŠæ›´æ–°æš«å­˜æª”."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " 無法在本版本的 Vim 中使用.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "使用 Vim 3.0。\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s 看起來ä¸åƒæ˜¯ Vim 暫存檔"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " 無法在這臺電腦上使用.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "本檔案建立於 "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"或是這檔案已經æ毀。"
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "使用暫存檔 \"%s\""
+
+#: memline.c:909
+#, c-format
+msgid "Original file \"%s\""
+msgstr "原始檔 \"%s\""
+
+#: memline.c:922
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: 警告: 原始檔案å¯èƒ½å·²ç¶“修改éŽäº†"
+
+#: memline.c:963
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: 無法從 %s 讀å–å€å¡Š 1"
+
+#: memline.c:967
+msgid "???MANY LINES MISSING"
+msgstr "???缺少太多行"
+
+#: memline.c:983
+msgid "???LINE COUNT WRONG"
+msgstr "???行號錯誤"
+
+#: memline.c:990
+msgid "???EMPTY BLOCK"
+msgstr "???空的 BLOCK"
+
+#: memline.c:1016
+msgid "???LINES MISSING"
+msgstr "???找ä¸åˆ°ä¸€äº›è¡Œ"
+
+#: memline.c:1048
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: å€å¡Š 1 ID 錯誤 (%s ä¸æ˜¯æš«å­˜æª”?)"
+
+#: memline.c:1053
+msgid "???BLOCK MISSING"
+msgstr "???找ä¸åˆ°BLOCK"
+
+#: memline.c:1069
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? 從這裡到 ???END 的內容å¯èƒ½æœ‰å•é¡Œ"
+
+#: memline.c:1085
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? 從這裡到 ???END 的內容å¯èƒ½è¢«åˆªé™¤/æ’å…¥éŽ"
+
+# do not translate
+#: memline.c:1105
+msgid "???END"
+msgstr "???END"
+
+#: memline.c:1131
+msgid "E311: Recovery Interrupted"
+msgstr "E311: 修復已中斷"
+
+#: memline.c:1133
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: 修復時發生錯誤; 請注æ„開頭為 ??? çš„è¡Œ"
+
+#: memline.c:1136
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "復原完æˆ. 請確定一切正常."
+
+#: memline.c:1137
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(ä½ å¯èƒ½æœƒæƒ³è¦æŠŠé€™å€‹æª”案å¦å­˜åˆ¥çš„檔å,\n"
+
+#: memline.c:1138
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "å†åŸ·è¡Œ diff 與原檔案比較以檢查是å¦æœ‰æ”¹è®Š)\n"
+
+#: memline.c:1139
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"(D)直接刪除 .swp 暫存檔\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1195
+msgid "Swap files found:"
+msgstr "找到以下的暫存檔:"
+
+#: memline.c:1373
+msgid " In current directory:\n"
+msgstr " 在目å‰çš„目錄:\n"
+
+#: memline.c:1375
+msgid " Using specified name:\n"
+msgstr " Using specified name:\n"
+
+#: memline.c:1379
+msgid " In directory "
+msgstr " 在目錄 "
+
+#: memline.c:1397
+msgid " -- none --\n"
+msgstr " -- ç„¡ --\n"
+
+#: memline.c:1469
+msgid " owned by: "
+msgstr " æ“有者: "
+
+#: memline.c:1471
+msgid " dated: "
+msgstr " 日期: "
+
+#: memline.c:1475 memline.c:3689
+msgid " dated: "
+msgstr " 日期: "
+
+#: memline.c:1491
+msgid " [from Vim version 3.0]"
+msgstr " [從 Vim 版本 3.0]"
+
+#: memline.c:1495
+msgid " [does not look like a Vim swap file]"
+msgstr " [ä¸åƒ Vim 的暫存檔]"
+
+#: memline.c:1499
+msgid " file name: "
+msgstr " 檔å: "
+
+#: memline.c:1505
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" 修改éŽ: "
+
+#: memline.c:1506
+msgid "YES"
+msgstr "是"
+
+#: memline.c:1506
+msgid "no"
+msgstr "å¦"
+
+#: memline.c:1510
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" 使用者: "
+
+#: memline.c:1517
+msgid " host name: "
+msgstr " 主機å稱: "
+
+#: memline.c:1519
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" 主機å稱: "
+
+#: memline.c:1525
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" process ID: "
+
+#: memline.c:1531
+msgid " (still running)"
+msgstr " (執行中)"
+
+#: memline.c:1543
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [無法在本版本的 Vim 上使用]"
+
+#: memline.c:1546
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [無法在本電腦上使用]"
+
+#: memline.c:1551
+msgid " [cannot be read]"
+msgstr " [無法讀å–]"
+
+#: memline.c:1555
+msgid " [cannot be opened]"
+msgstr " [無法開啟]"
+
+#: memline.c:1745
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: 無法ä¿ç•™, ä¸ä½¿ç”¨æš«å­˜æª”"
+
+#: memline.c:1798
+msgid "File preserved"
+msgstr "檔案已ä¿ç•™"
+
+#: memline.c:1800
+msgid "E314: Preserve failed"
+msgstr "E314: ä¿ç•™å¤±æ•—"
+
+#: memline.c:1871
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: 錯誤的 lnum: %ld"
+
+#: memline.c:1897
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: 找ä¸åˆ°ç¬¬ %ld è¡Œ"
+
+#: memline.c:2287
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: 指標å€å¡Š id 錯誤 3"
+
+#: memline.c:2367
+msgid "stack_idx should be 0"
+msgstr "stack_idx 應該是 0"
+
+#: memline.c:2429
+msgid "E318: Updated too many blocks?"
+msgstr "E318: 更新太多å€å¡Š?"
+
+#: memline.c:2611
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: 指標å€å¡Š id 錯誤 4"
+
+#: memline.c:2638
+msgid "deleted block 1?"
+msgstr "刪除å€å¡Š 1?"
+
+#: memline.c:2838
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: 找ä¸åˆ°ç¬¬ %ld è¡Œ"
+
+#: memline.c:3081
+msgid "E317: pointer block id wrong"
+msgstr "E317: 指標å€å¡Š id 錯誤"
+
+#: memline.c:3097
+msgid "pe_line_count is zero"
+msgstr "pe_line_count 為零"
+
+#: memline.c:3126
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: 行號超出範åœ: %ld 超éŽçµå°¾"
+
+#: memline.c:3130
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: å€å¡Š %ld 行數錯誤"
+
+#: memline.c:3179
+msgid "Stack size increases"
+msgstr "堆疊大å°å¢žåŠ "
+
+#: memline.c:3225
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: 指標å€å¡Š id 錯 2"
+
+#: memline.c:3679
+msgid "E325: ATTENTION"
+msgstr "E325: 注æ„"
+
+#: memline.c:3680
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"找到暫存檔 \""
+
+#: memline.c:3684
+msgid "While opening file \""
+msgstr "在開啟檔案 \""
+
+#: memline.c:3693
+msgid " NEWER than swap file!\n"
+msgstr " 比暫存檔更新!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3697
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) å¯èƒ½æœ‰å¦ä¸€å€‹ç¨‹å¼ä¹Ÿåœ¨ç·¨è¼¯åŒä¸€å€‹æª”案.\n"
+" 如果是這樣,請å°å¿ƒä¸è¦å…©é‚Šä¸€èµ·å¯«å…¥ï¼Œä¸ç„¶ä½ çš„努力都會負諸æµæ°´ã€‚\n"
+
+#: memline.c:3698
+msgid " Quit, or continue with caution.\n"
+msgstr " 離開,或是繼續編輯。\n"
+
+#: memline.c:3699
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) å‰æ¬¡ç·¨è¼¯æ­¤æª”時當機\n"
+
+#: memline.c:3700
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " 如果是這樣, 請用 \":recover\" 或 \"vim -r"
+
+#: memline.c:3702
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" 來救回修改資料 (進一步說明請看 \":help recovery\").\n"
+
+#: memline.c:3703
+msgid " If you did this already, delete the swap file \""
+msgstr " 如果該救的都已經救了, 請直接刪除此暫存檔 \""
+
+#: memline.c:3705
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" 以é¿å…å†çœ‹åˆ°æ­¤è¨Šæ¯.\n"
+
+#: memline.c:3719 memline.c:3723
+msgid "Swap file \""
+msgstr "暫存檔 \""
+
+#: memline.c:3720 memline.c:3726
+msgid "\" already exists!"
+msgstr "\" 已經存在了!"
+
+#: memline.c:3729
+msgid "VIM - ATTENTION"
+msgstr "VIM - 注æ„"
+
+#: memline.c:3731
+msgid "Swap file already exists!"
+msgstr "暫存檔已經存在!"
+
+#: memline.c:3735
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"以唯讀方å¼é–‹å•Ÿ(&O)\n"
+"直接編輯(&E)\n"
+"修復(&R)\n"
+"離開(&Q)"
+
+#: memline.c:3737
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"以唯讀方å¼é–‹å•Ÿ(&O)\n"
+"直接編輯(&E)\n"
+"修復(&R)\n"
+"離開(&Q)\n"
+"刪除暫存檔(&D)"
+
+#: memline.c:3790
+msgid "E326: Too many swap files found"
+msgstr "E326: 找到太多暫存檔"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: 部份é¸é …路徑ä¸æ˜¯å­é¸å–®"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: é¸å–®åªèƒ½åœ¨å…¶å®ƒæ¨¡å¼ä¸­ä½¿ç”¨"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: 沒有那樣的é¸å–®"
+
+#: menu.c:509
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: é¸å–®è·¯å¾‘ä¸èƒ½æŒ‡å‘å­é¸å–®"
+
+#: menu.c:548
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: ä¸èƒ½ç›´æŽ¥æŠŠé¸é …加到é¸å–®åˆ—中"
+
+#: menu.c:554
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: 分隔線ä¸èƒ½æ˜¯é¸å–®è·¯å¾‘的一部份"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1079
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- é¸å–® ---"
+
+#: menu.c:1996
+msgid "Tear off this menu"
+msgstr "切下此é¸å–®"
+
+#: menu.c:2061
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: é¸å–®è·¯å¾‘必需指å‘一個é¸é …"
+
+#: menu.c:2081
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: [é¸å–®] 找ä¸åˆ° %s"
+
+#: menu.c:2150
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: %s 模å¼æœªå®šç¾©é¸å–®"
+
+#: menu.c:2188
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: é¸å–®è·¯å¾‘必需指å‘å­é¸å–®"
+
+#: menu.c:2209
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: 找ä¸åˆ°é¸å–® - 請檢查é¸å–®å稱"
+
+#: message.c:509
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "è™•ç† %s 時發生錯誤:"
+
+#: message.c:525
+#, c-format
+msgid "line %4ld:"
+msgstr "行 %4ld:"
+
+#: message.c:565
+msgid "[string too long]"
+msgstr "[此行éŽé•·]"
+
+#: message.c:711
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr ""
+"正體中文訊æ¯ç¶­è­·è€…: Francis S.Lin <piaip@csie.ntu.edu."
+"tw>, Cecil Sheng <b7506022@csie.ntu.edu.tw>"
+
+#: message.c:935
+msgid "Interrupt: "
+msgstr "已中斷: "
+
+#: message.c:938
+msgid "Hit ENTER to continue"
+msgstr "請按 ENTER 繼續"
+
+#: message.c:940
+msgid "Hit ENTER or type command to continue"
+msgstr "請按 ENTER 或其它命令以繼續"
+
+#: message.c:2028
+msgid "-- More --"
+msgstr "-- 尚有 --"
+
+#: message.c:2031
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: å‘下/å‘上一行, 空白éµ/b: 一é , d/u: åŠé , q: 離開)"
+
+#: message.c:2032
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: å‘下一行, 空白éµ: 一é , d: åŠé , q: 離開)"
+
+#: message.c:2508 message.c:2523
+msgid "Question"
+msgstr "å•é¡Œ"
+
+#: message.c:2510
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Y是\n"
+"&Nå¦"
+
+#: message.c:2543
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Y是\n"
+"&Nå¦\n"
+"&A全部存檔\n"
+"&D全部ä¸å­˜\n"
+"&Cå–消"
+
+#: message.c:2584
+msgid "Save File dialog"
+msgstr "存檔"
+
+#: message.c:2586
+msgid "Open File dialog"
+msgstr "開檔"
+
+#. TODO: non-GUI file selector here
+#: message.c:2657
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: 主控å°(Console)模å¼æ™‚沒有檔案ç€è¦½å™¨(file browser)"
+
+#: misc1.c:2477
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: 注æ„: 你正在修改一個唯讀檔"
+
+#: misc1.c:2712
+msgid "1 more line"
+msgstr "還有一行"
+
+#: misc1.c:2714
+msgid "1 line less"
+msgstr "少於一行"
+
+#: misc1.c:2719
+#, c-format
+msgid "%ld more lines"
+msgstr " 還有 %ld 行"
+
+#: misc1.c:2721
+#, c-format
+msgid "%ld fewer lines"
+msgstr "åªå‰© %ld è¡Œ"
+
+#: misc1.c:2724
+msgid " (Interrupted)"
+msgstr " (已中斷)"
+
+#: misc1.c:6348
+msgid "Vim: preserving files...\n"
+msgstr "Vim: ä¿ç•™æª”案中...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6358
+msgid "Vim: Finished.\n"
+msgstr "Vim: çµæŸ.\n"
+
+#: misc2.c:670 misc2.c:686
+msgid "ERROR: "
+msgstr "錯誤: "
+
+#: misc2.c:690
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bytes] 全部 alloc-freed %lu-%lu, 使用中 %lu, peak 使用 %lu\n"
+
+#: misc2.c:692
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[呼å«] 全部 re/malloc(): %lu, 全部 free()': %lu\n"
+"\n"
+
+#: misc2.c:747
+msgid "E340: Line is becoming too long"
+msgstr "E340: 此行éŽé•·"
+
+#: misc2.c:791
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: 內部錯誤: lalloc(%ld, )"
+
+#: misc2.c:899
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: 記憶體ä¸è¶³! (嘗試é…ç½® %lu ä½å…ƒçµ„)"
+
+#: misc2.c:2564
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "å‘¼å« shell 執行: \"%s\""
+
+#: misc2.c:2785
+msgid "E545: Missing colon"
+msgstr "E545: 缺少 colon"
+
+#: misc2.c:2787 misc2.c:2814
+msgid "E546: Illegal mode"
+msgstr "E546: ä¸æ­£ç¢ºçš„模å¼"
+
+#: misc2.c:2853
+msgid "E547: Illegal mouseshape"
+msgstr "E547: ä¸æ­£ç¢ºçš„滑鼠形狀"
+
+#: misc2.c:2893
+msgid "E548: digit expected"
+msgstr "E548: 應該è¦æœ‰æ•¸å­—"
+
+#: misc2.c:2898
+msgid "E549: Illegal percentage"
+msgstr "E549: ä¸æ­£ç¢ºçš„百分比"
+
+#: misc2.c:3208
+msgid "Enter encryption key: "
+msgstr "輸入密碼: "
+
+#: misc2.c:3209
+msgid "Enter same key again: "
+msgstr "è«‹å†è¼¸å…¥ä¸€æ¬¡: "
+
+#: misc2.c:3219
+msgid "Keys don't match!"
+msgstr "兩次輸入密碼ä¸ç›¸åŒ!"
+
+#: misc2.c:3768
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr "E343: ä¸æ­£ç¢ºçš„路徑: '**[number]' 必需è¦åœ¨è·¯å¾‘çµå°¾æˆ–è¦æŽ¥è‘— '%s'"
+
+#: misc2.c:5044
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: cdpath 中沒有目錄 \"%s\""
+
+#: misc2.c:5047
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: 在路徑中找ä¸åˆ°æª”案 \"%s\""
+
+#: misc2.c:5053
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: 在路徑中找ä¸åˆ°æ›´å¤šçš„檔案 \"%s\""
+
+#: misc2.c:5056
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: 在路徑中找ä¸åˆ°æ›´å¤šçš„檔案 \"%s\""
+
+#: misc2.c:5290
+msgid "E550: Missing colon"
+msgstr "E550: 缺少 colon"
+
+#: misc2.c:5302
+msgid "E551: Illegal component"
+msgstr "E551: ä¸æ­£ç¢ºçš„模å¼"
+
+#: misc2.c:5310
+msgid "E552: digit expected"
+msgstr "E552: 應該è¦æœ‰æ•¸å­—"
+
+#. Get here when the server can't be found.
+#: netbeans.c:283
+msgid "Cannot connect to Netbeans #2"
+msgstr "無法連接到 Netbeans #2"
+
+#: netbeans.c:291
+msgid "Cannot connect to Netbeans"
+msgstr "無法連接到 Netbeans"
+
+#: netbeans.c:565
+msgid "read from Netbeans socket"
+msgstr "ç”± Netbeans socket 讀å–"
+
+#: normal.c:2913
+msgid "Warning: terminal cannot highlight"
+msgstr "注æ„: 你的終端機無法顯示高亮度"
+
+#: normal.c:3128
+msgid "E348: No string under cursor"
+msgstr "E348: 游標處沒有字串"
+
+#: normal.c:3130
+msgid "E349: No identifier under cursor"
+msgstr "E349: 游標處沒有識別字"
+
+#: normal.c:4348
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: 無法在目å‰çš„ 'foldmethod' 下刪除 fold"
+
+#: ops.c:295
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "一行 %s éŽ ä¸€æ¬¡"
+
+#: ops.c:297
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "一行 %s éŽ %d 次"
+
+#: ops.c:302
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld è¡Œ %s éŽ ä¸€æ¬¡"
+
+#: ops.c:305
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld è¡Œ %s éŽ %d 次"
+
+#: ops.c:663
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "縮排 %ld 行..."
+
+#: ops.c:713
+msgid "1 line indented "
+msgstr "一行已縮排"
+
+#: ops.c:715
+#, c-format
+msgid "%ld lines indented "
+msgstr "已縮排 %ld 行"
+
+#. must display the prompt
+#: ops.c:1645
+msgid "cannot yank; delete anyway"
+msgstr "無法剪下; 直接刪除"
+
+#: ops.c:2152
+msgid "1 line changed"
+msgstr " 1 行 ~ed"
+
+#: ops.c:2154
+#, c-format
+msgid "%ld lines changed"
+msgstr " %ld 行 ~ed"
+
+#: ops.c:2538
+#, c-format
+msgid "freeing %ld lines"
+msgstr "釋放 %ld 行中"
+
+#: ops.c:2819
+msgid "1 line yanked"
+msgstr "已複製 1 行"
+
+#: ops.c:2821
+#, c-format
+msgid "%ld lines yanked"
+msgstr "已複製 %ld 行"
+
+#: ops.c:3106
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: 暫存器 %s 裡沒有æ±è¥¿"
+
+#. Highlight title
+#: ops.c:3664
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- 暫存器 ---"
+
+#: ops.c:4873
+msgid "Illegal register name"
+msgstr "ä¸æ­£ç¢ºçš„暫存器å稱"
+
+#: ops.c:4959
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# 暫存器:\n"
+
+#: ops.c:4992
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: 未知的註冊型態: %d"
+
+#: ops.c:5412
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: 暫存器å稱錯誤: '%s'"
+
+#: ops.c:5750
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld 欄; "
+
+#: ops.c:5757
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "é¸æ“‡äº† %s%ld/%ld è¡Œ; %ld/%ld å­—(Word); %ld/%ld å­—å…ƒ(Bytes)"
+
+#: ops.c:5773
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "欄 %s/%s; 行 %ld/%ld; 字(Word) %ld/%ld; 字元(Byte) %ld/%ld"
+
+#: ops.c:5784
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld for BOM)"
+
+#: option.c:1579
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=第 %N é "
+
+# ? what's this for?
+#: option.c:2012
+msgid "Thanks for flying Vim"
+msgstr "æ„Ÿè¬æ‚¨æ„›ç”¨ Vim"
+
+#: option.c:3250 option.c:3357
+msgid "E518: Unknown option"
+msgstr "E518: ä¸æ­£ç¢ºçš„é¸é …"
+
+#: option.c:3263
+msgid "E519: Option not supported"
+msgstr "E519: ä¸æ”¯æ´è©²é¸é …"
+
+#: option.c:3288
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: ä¸èƒ½åœ¨ Modeline 裡出ç¾"
+
+#: option.c:3344
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\t上次設定: "
+
+#: option.c:3483
+msgid "E521: Number required after ="
+msgstr "E521: = 後需è¦æœ‰æ•¸å­—"
+
+#: option.c:3797 option.c:4413
+msgid "E522: Not found in termcap"
+msgstr "E522: Termcap 裡é¢æ‰¾ä¸åˆ°"
+
+#: option.c:3863
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: ä¸æ­£ç¢ºçš„å­—å…ƒ <%s>"
+
+#: option.c:4405
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: 無法設定 'term' 為空字串"
+
+#: option.c:4408
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: 在圖型界é¢ä¸­ç„¡æ³•åˆ‡æ› term"
+
+#: option.c:4410
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: 輸入 \":gui\" 來啟動圖形界é¢"
+
+#: option.c:4431
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: 'backupext' 跟 'patchmode' 是一樣的"
+
+#: option.c:4616
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: 在圖型界é¢ä¸­ç„¡æ³•åˆ‡æ› term"
+
+#: option.c:4748
+msgid "E524: Missing colon"
+msgstr "E524: 缺少 colon"
+
+#: option.c:4750
+msgid "E525: Zero length string"
+msgstr "E525: 零長度字串"
+
+#: option.c:4818
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: <%s> 後缺少數字"
+
+#: option.c:4832
+msgid "E527: Missing comma"
+msgstr "E527: 缺少逗號"
+
+#: option.c:4839
+msgid "E528: Must specify a ' value"
+msgstr "E528: 必需指定一個 ' 值"
+
+#: option.c:4880
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: å…§å«ç„¡æ³•é¡¯ç¤ºçš„å­—å…ƒ"
+
+#: option.c:4929
+msgid "E596: Invalid font(s)"
+msgstr "E596: ä¸æ­£ç¢ºçš„å­—åž‹"
+
+#: option.c:4937
+msgid "E597: can't select fontset"
+msgstr "E597: 無法使用字型集(Fontset)"
+
+#: option.c:4939
+msgid "E598: Invalid fontset"
+msgstr "E598: ä¸æ­£ç¢ºçš„字型集(Fontset)"
+
+#: option.c:4946
+msgid "E533: can't select wide font"
+msgstr "E533: 無法使用設定的中文字型(Widefont)"
+
+#: option.c:4948
+msgid "E534: Invalid wide font"
+msgstr "E534: ä¸æ­£ç¢ºçš„å­—åž‹(Widefont)"
+
+#: option.c:5218
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: <%c> 後有ä¸æ­£ç¢ºçš„å­—å…ƒ"
+
+#: option.c:5322
+msgid "E536: comma required"
+msgstr "E536: 需è¦é€—號"
+
+#: option.c:5330
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: 'commentstring' å¿…éœ€æ˜¯ç©ºç™½æˆ–åŒ…å« %s"
+
+#: option.c:5377
+msgid "E538: No mouse support"
+msgstr "E538: ä¸æ”¯æ´æ»‘é¼ "
+
+#: option.c:5645
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: 沒有çµæŸçš„é‹ç®—å¼: "
+
+#: option.c:5649
+msgid "E541: too many items"
+msgstr "E541: 太多項目"
+
+#: option.c:5651
+msgid "E542: unbalanced groups"
+msgstr "E542: ä¸å°ç¨±çš„ group"
+
+#: option.c:5872
+msgid "E590: A preview window already exists"
+msgstr "E590: é è¦–的視窗已經存在了"
+
+#: option.c:6346
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: è‡³å°‘éœ€è¦ %d è¡Œ"
+
+#: option.c:6355
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: è‡³å°‘éœ€è¦ %d 欄"
+
+#: option.c:6660
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: ä¸æ­£ç¢ºçš„é¸é …: %s"
+
+#: option.c:6769
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- 終端機碼 ---"
+
+#: option.c:6771
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Global é¸é …值 ---"
+
+#: option.c:6773
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Local é¸é …值 ---"
+
+#: option.c:6775
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- é¸é … ---"
+
+#: option.c:7467
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp 錯誤"
+
+#: option.c:8425
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': 找ä¸åˆ° %s å°æ‡‰çš„å­—å…ƒ"
+
+#: option.c:8459
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': 分號後有多餘的字元: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "ä¸èƒ½é–‹å•Ÿ"
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: 無法開啟視窗!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "éœ€è¦ Amigados 版本 2.04 以上\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "éœ€è¦ %s 版本 %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "無法開啟 NIL:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr "ä¸èƒ½å»ºç«‹ "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim çµæŸå‚³å›žå€¼: %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "無法切æ›ä¸»æŽ§å°(console)æ¨¡å¼ !?\n"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: ä¸æ˜¯ä¸»æŽ§å°(console)??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1143
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: ä¸èƒ½ç”¨ -f é¸é …執行 shell"
+
+#: os_amiga.c:1184 os_amiga.c:1274
+msgid "Cannot execute "
+msgstr "ä¸èƒ½åŸ·è¡Œ "
+
+#: os_amiga.c:1187 os_amiga.c:1284
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1207 os_amiga.c:1309
+msgid " returned\n"
+msgstr " 已返回\n"
+
+#: os_amiga.c:1450
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE 太å°"
+
+#: os_amiga.c:1454
+msgid "I/O ERROR"
+msgstr "I/O 錯誤"
+
+#: os_mswin.c:515
+msgid "...(truncated)"
+msgstr "...(已切掉)"
+
+#: os_mswin.c:617
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' ä¸æ˜¯ 80, 無法執行外部命令"
+
+#: os_mswin.c:1802
+msgid "E237: Printer selection failed"
+msgstr "E237: 無法é¸æ“‡æ­¤å°è¡¨æ©Ÿ"
+
+#: os_mswin.c:1842
+#, c-format
+msgid "to %s on %s"
+msgstr "到 %s on %s"
+
+#: os_mswin.c:1857
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: ä¸æ­£ç¢ºçš„å°è¡¨æ©Ÿå­—åž‹: %s"
+
+#: os_mswin.c:1907 os_mswin.c:1917
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: 列å°éŒ¯èª¤: %s"
+
+#: os_mswin.c:1918
+msgid "Unknown"
+msgstr "未知"
+
+#: os_mswin.c:1945
+#, c-format
+msgid "Printing '%s'"
+msgstr "列å°ä¸­: '%s'"
+
+#: os_mswin.c:3033
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: 字元集 \"%s\" 無法å°æ‡‰å­—åž‹\"%s\""
+
+#: os_mswin.c:3041
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: ä¸æ­£ç¢ºçš„å­—å…ƒ '%c' 出ç¾åœ¨å­—åž‹å稱 \"%s\" å…§"
+
+#: os_riscos.c:1258
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: ä¸æ­£ç¢ºçš„ 'filetype' é¸é … - 使用純文字模å¼"
+
+#: os_unix.c:871
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: é›™é‡signal, 離開中\n"
+
+#: os_unix.c:877
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: CVim: 攔截到信號(signal) %s\n"
+
+#: os_unix.c:880
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: 攔截到致命的信號(deadly signale)\n"
+
+#: os_unix.c:1143
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "開啟 X Window 耗時 %ld msec"
+
+#: os_unix.c:1170
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: X 錯誤\n"
+
+#: os_unix.c:1276
+msgid "Testing the X display failed"
+msgstr "測試 X Window 失敗"
+
+#: os_unix.c:1415
+msgid "Opening the X display timed out"
+msgstr "開啟 X Window 逾時"
+
+#: os_unix.c:3145 os_unix.c:3825
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"ä¸èƒ½åŸ·è¡Œ shell"
+
+#: os_unix.c:3193
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"ä¸èƒ½åŸ·è¡Œ shell sh\n"
+
+#: os_unix.c:3197 os_unix.c:3831
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"Shell 已返回"
+
+#: os_unix.c:3332
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"ä¸èƒ½å»ºç«‹ pipe 管線\n"
+
+#: os_unix.c:3347
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"ä¸èƒ½ fork\n"
+
+#: os_unix.c:3838
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"命令已終çµ\n"
+
+#: os_unix.c:5398
+msgid "Opening the X display failed"
+msgstr "開啟 X Window 失敗"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "在行號 "
+
+#: os_w32exe.c:169
+msgid "Could not load vim32.dll!"
+msgstr "無法載入 vim32.dllï¼"
+
+#: os_w32exe.c:169 os_w32exe.c:179
+msgid "VIM Error"
+msgstr "VIM 錯誤"
+
+#: os_w32exe.c:179
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "ä¸èƒ½ä¿®æ­£å‡½å¼æŒ‡æ¨™åˆ° DLL!"
+
+#: os_win16.c:583 os_win32.c:3047
+#, c-format
+msgid "shell returned %d"
+msgstr "Shell 傳回值 %d"
+
+#: os_win32.c:2505
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: 攔截到 %s \n"
+
+#: os_win32.c:2507
+msgid "close"
+msgstr "關閉"
+
+#: os_win32.c:2509
+msgid "logoff"
+msgstr "登出"
+
+#: os_win32.c:2510
+msgid "shutdown"
+msgstr "關機"
+
+#: os_win32.c:3000
+msgid "E371: Command not found"
+msgstr "E371: 找ä¸åˆ°å‘½ä»¤"
+
+#: os_win32.c:3013
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"在你的 $PATH 中找ä¸åˆ° VIMRUN.EXE.\n"
+"外部命令執行完畢後將ä¸æœƒæš«åœ.\n"
+"進一步說明請執行 :help win32-vimrun "
+
+#: os_win32.c:3016
+msgid "Vim Warning"
+msgstr "Vim 警告"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: æ ¼å¼åŒ–字串裡有太多 %%%c "
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: æ ¼å¼åŒ–字串ä¸æ‡‰è©²å‡ºç¾ %%%c "
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: æ ¼å¼åŒ–字串裡少了 ]"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: æ ¼å¼åŒ–字串裡有ä¸æ”¯æ´çš„ %%%c "
+
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: æ ¼å¼åŒ–字串開頭裡有ä¸æ­£ç¢ºçš„ %%%c "
+
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: æ ¼å¼åŒ–字串裡有ä¸æ­£ç¢ºçš„ %%%c "
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' 未設定"
+
+#: quickfix.c:497
+msgid "E379: Missing or empty directory name"
+msgstr "E379: 找ä¸åˆ°ç›®éŒ„å稱或是空的目錄å稱"
+
+#: quickfix.c:979
+msgid "E553: No more items"
+msgstr "E553: 沒有其它項目"
+
+#: quickfix.c:1200
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d / %d)%s%s: "
+
+#: quickfix.c:1202
+msgid " (line deleted)"
+msgstr " (行已刪除)"
+
+#: quickfix.c:1412
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Quickfix 堆疊çµå°¾"
+
+#: quickfix.c:1421
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Quickfix 堆疊頂端"
+
+#: quickfix.c:1433
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "錯誤列表 %d/%d; 共有 %d 項錯誤"
+
+#: quickfix.c:1904
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: 無法寫入,'buftype' é¸é …已設定"
+
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: ä¸æ­£ç¢ºçš„項目: %s%%[]"
+
+#: regexp.c:826
+msgid "E339: Pattern too long"
+msgstr "E339: å字太長"
+
+#: regexp.c:995
+msgid "E50: Too many \\z("
+msgstr "E50: 太多 \\z("
+
+#: regexp.c:1006
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: 太多 %s("
+
+#: regexp.c:1063
+msgid "E52: Unmatched \\z("
+msgstr "E52: ç„¡å°æ‡‰çš„ \\z("
+
+#: regexp.c:1067
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: ç„¡å°æ‡‰çš„ %s%%("
+
+#: regexp.c:1069
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: ç„¡å°æ‡‰çš„ %s("
+
+#: regexp.c:1074
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: ç„¡å°æ‡‰çš„ %s)"
+
+#: regexp.c:1237
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: %s* é‹ç®—å…ƒå¯ä»¥æ˜¯ç©ºçš„"
+
+#: regexp.c:1240
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E56: %s+ é‹ç®—å…ƒå¯ä»¥æ˜¯ç©ºçš„"
+
+#: regexp.c:1294
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: 後é¢æœ‰ä¸æ­£ç¢ºçš„å­—å…ƒ: %s@"
+
+#: regexp.c:1319
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: %s{ é‹ç®—å…ƒå¯ä»¥æ˜¯ç©ºçš„"
+
+#: regexp.c:1329
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: 太多複雜的 %s{...}s"
+
+#: regexp.c:1345
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: 巢狀 %s*"
+
+#: regexp.c:1348
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: 巢狀 %s%c"
+
+#: regexp.c:1466
+msgid "E63: invalid use of \\_"
+msgstr "E63: ä¸æ­£ç¢ºçš„使用 \\_"
+
+#: regexp.c:1511
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c 沒有接æ±è¥¿"
+
+#: regexp.c:1567
+msgid "E65: Illegal back reference"
+msgstr "E65: ä¸æ­£ç¢ºçš„åå‘åƒè€ƒ"
+
+#: regexp.c:1580
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z( ä¸èƒ½åœ¨æ­¤å‡ºç¾"
+
+#: regexp.c:1599
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 et al. ä¸èƒ½åœ¨æ­¤å‡ºç¾"
+
+#: regexp.c:1610
+msgid "E68: Invalid character after \\z"
+msgstr "E68: 後é¢æœ‰ä¸æ­£ç¢ºçš„å­—å…ƒ: \\z"
+
+#: regexp.c:1659
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: %s%%[ 後缺少 ]"
+
+#: regexp.c:1675
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: 空的 %s%%[]"
+
+#: regexp.c:1735
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: 後é¢æœ‰ä¸æ­£ç¢ºçš„å­—å…ƒ: %s%%"
+
+#: regexp.c:2530
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: 語法錯誤: %s{...}"
+
+#: regexp.c:2777
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: 無法執行; regular expression 太複雜?"
+
+#: regexp.c:2912
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: regular expression 造æˆå †ç–Šç”¨å…‰çš„錯誤"
+
+#: regexp.c:3148
+msgid "External submatches:\n"
+msgstr "外部符åˆ:\n"
+
+#: screen.c:2103
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--已 fold %3ld 行"
+
+#: screen.c:7785
+msgid " VREPLACE"
+msgstr " V-å–代"
+
+#: screen.c:7789
+msgid " REPLACE"
+msgstr " å–代"
+
+#: screen.c:7794
+msgid " REVERSE"
+msgstr " å轉"
+
+#: screen.c:7796
+msgid " INSERT"
+msgstr " æ’å…¥"
+
+#: screen.c:7799
+msgid " (insert)"
+msgstr " (æ’å…¥)"
+
+#: screen.c:7801
+msgid " (replace)"
+msgstr " (å–代)"
+
+#: screen.c:7803
+msgid " (vreplace)"
+msgstr " (v-å–代)"
+
+#: screen.c:7806
+msgid " Hebrew"
+msgstr " Hebrew"
+
+#: screen.c:7814
+msgid " (lang)"
+msgstr " (語言)"
+
+#: screen.c:7817
+msgid " (paste)"
+msgstr " (貼上)"
+
+#: screen.c:7823
+msgid " SELECT"
+msgstr " é¸å–"
+
+#: screen.c:7825
+msgid " VISUAL"
+msgstr " é¸å–"
+
+#: screen.c:7827
+msgid " BLOCK"
+msgstr " å€å¡Š"
+
+#: screen.c:7829
+msgid " LINE"
+msgstr " è¡Œé¸å–"
+
+#: screen.c:7842 screen.c:7902
+msgid "recording"
+msgstr "記錄中"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "å·²æœå°‹åˆ°æª”案開頭;å†å¾žçµå°¾ç¹¼çºŒæœå°‹"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "å·²æœå°‹åˆ°æª”案çµå°¾ï¼›å†å¾žé–‹é ­ç¹¼çºŒæœå°‹"
+
+#: search.c:455
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: 錯誤的æœå°‹å­—串: %s"
+
+#: search.c:782
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: å·²æœå°‹åˆ°æª”案開頭ä»æ‰¾ä¸åˆ° %s"
+
+#: search.c:784
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: å·²æœå°‹åˆ°æª”案çµå°¾ä»æ‰¾ä¸åˆ° %s"
+
+#: search.c:1157
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: 在 ';' 後é¢æ‡‰è©²æœ‰ '?' 或 '/'"
+
+#: search.c:3567
+msgid " (includes previously listed match)"
+msgstr " (包括å‰æ¬¡åˆ—出符åˆé …)"
+
+#. cursor at status line
+#: search.c:3587
+msgid "--- Included files "
+msgstr "--- 引入檔案 "
+
+#: search.c:3589
+msgid "not found "
+msgstr "找ä¸åˆ° "
+
+#: search.c:3590
+msgid "in path ---\n"
+msgstr "---\n"
+
+#: search.c:3629
+msgid " (Already listed)"
+msgstr " (已列出)"
+
+#: search.c:3631
+msgid " NOT FOUND"
+msgstr " 找ä¸åˆ°"
+
+#: search.c:3683
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "æœå°‹å¼•å…¥æª”案: %s"
+
+#: search.c:3901
+msgid "E387: Match is on current line"
+msgstr "E387: ç›®å‰æ‰€åœ¨è¡Œä¸­æœ‰ä¸€åŒ¹é…"
+
+#: search.c:4041
+msgid "All included files were found"
+msgstr "所有引入檔案都已找到"
+
+#: search.c:4043
+msgid "No included files"
+msgstr "沒有引入檔案"
+
+#: search.c:4059
+msgid "E388: Couldn't find definition"
+msgstr "E388: 找ä¸åˆ°å®šç¾©"
+
+#: search.c:4061
+msgid "E389: Couldn't find pattern"
+msgstr "E389: 找ä¸åˆ° pattern"
+
+#: syntax.c:3015
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: åƒæ•¸ä¸æ­£ç¢º: %s"
+
+#: syntax.c:3195
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: ç„¡æ­¤ syntax cluster: \"%s\""
+
+#: syntax.c:3359
+msgid "No Syntax items defined for this buffer"
+msgstr "這個緩è¡å€æ²’有定義任何語法"
+
+#: syntax.c:3367
+msgid "syncing on C-style comments"
+msgstr "C語言å¼è¨»è§£åŒæ­¥åŒ–中"
+
+#: syntax.c:3375
+msgid "no syncing"
+msgstr "沒有åŒæ­¥åŒ–"
+
+#: syntax.c:3378
+msgid "syncing starts "
+msgstr "åŒæ­¥åŒ–開始"
+
+#: syntax.c:3380 syntax.c:3455
+msgid " lines before top line"
+msgstr "行號超出範åœ"
+
+#: syntax.c:3385
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- 語法åŒæ­¥ç‰©ä»¶ (Syntax sync items) ---"
+
+#: syntax.c:3390
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"åŒæ­¥åŒ–中:"
+
+#: syntax.c:3396
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- 語法項目 ---"
+
+#: syntax.c:3419
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: ç„¡æ­¤ syntax cluster: \"%s\""
+
+#: syntax.c:3445
+msgid "minimal "
+msgstr "最å°"
+
+#: syntax.c:3452
+msgid "maximal "
+msgstr "最大"
+
+#: syntax.c:3464
+msgid "; match "
+msgstr "; ç¬¦åˆ "
+
+#: syntax.c:3466
+msgid " line breaks"
+msgstr "斷行"
+
+#: syntax.c:4100
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: 使用了ä¸æ­£ç¢ºçš„åƒæ•¸"
+
+#: syntax.c:4124
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: 找ä¸åˆ° %s çš„ region item"
+
+#: syntax.c:4152
+msgid "E395: contains argument not accepted here"
+msgstr "E395: 使用了ä¸æ­£ç¢ºçš„åƒæ•¸"
+
+#: syntax.c:4163
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: 使用了ä¸æ­£ç¢ºçš„åƒæ•¸"
+
+#: syntax.c:4241
+msgid "E397: Filename required"
+msgstr "E397: 需è¦æª”案å稱"
+
+#: syntax.c:4579
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: 缺少 \"=\": %s"
+
+#: syntax.c:4737
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: syntax region %s 的引數太少"
+
+#: syntax.c:5068
+msgid "E400: No cluster specified"
+msgstr "E400: 沒有指定的屬性"
+
+#: syntax.c:5105
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: 找ä¸åˆ°åˆ†éš”符號: %s"
+
+#: syntax.c:5180
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: '%s' 後é¢çš„æ±è¥¿ç„¡æ³•è¾¨è­˜"
+
+#: syntax.c:5270
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: 語法åŒæ­¥: 連接行符號被指定了兩次"
+
+#: syntax.c:5327
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: åƒæ•¸ä¸æ­£ç¢º: %s"
+
+#: syntax.c:5377
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: 缺少相等符號: %s"
+
+#: syntax.c:5383
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: 空白åƒæ•¸: %s"
+
+#: syntax.c:5410
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s ä¸èƒ½åœ¨æ­¤å‡ºç¾"
+
+#: syntax.c:5417
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s 必須是列表裡的第一個"
+
+#: syntax.c:5487
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: ä¸æ­£ç¢ºçš„群組å稱: %s"
+
+#: syntax.c:5720
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: ä¸æ­£ç¢ºçš„ :syntax å­å‘½ä»¤: %s"
+
+#: syntax.c:6099
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: 找ä¸åˆ° highlight group: %s"
+
+#: syntax.c:6123
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: åƒæ•¸å¤ªå°‘: \":highlight link %s\""
+
+#: syntax.c:6130
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: åƒæ•¸éŽå¤š: \":highlight link %s\""
+
+#: syntax.c:6150
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: 已設定群組, 忽略 highlight link"
+
+#: syntax.c:6279
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: ä¸è©²æœ‰çš„等號: %s"
+
+#: syntax.c:6315
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: 缺少相等符號: %s"
+
+#: syntax.c:6337
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: 缺少åƒæ•¸: %s"
+
+#: syntax.c:6374
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: ä¸åˆæ³•çš„值: %s"
+
+#: syntax.c:6493
+msgid "E419: FG color unknown"
+msgstr "E419: 錯誤的å‰æ™¯é¡è‰²"
+
+#: syntax.c:6504
+msgid "E420: BG color unknown"
+msgstr "E420: 錯誤的背景é¡è‰²"
+
+#: syntax.c:6565
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: 錯誤的é¡è‰²å稱或數值: %s"
+
+#: syntax.c:6771
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: 終端機碼太長: %s"
+
+#: syntax.c:6818
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: åƒæ•¸ä¸æ­£ç¢º: %s"
+
+#: syntax.c:7347
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: 使用了éŽå¤šç›¸ç•°çš„高亮度屬性"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: 標籤(tag)堆疊çµå°¾"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: 標籤(tag)堆疊開頭"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: 已經在最å‰é¢çš„標籤(tag)了"
+
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: 找ä¸åˆ°æ¨™ç±¤(tag): %s"
+
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr " # pri kind tag"
+
+#: tag.c:548
+msgid "file\n"
+msgstr "檔案\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "輸入 nr 或é¸æ“‡ (<CR> 離開): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: åªæœ‰æ­¤é …符åˆ"
+
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: 己經在最後一個符åˆçš„ tag 了"
+
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "檔案 \"%s\" ä¸å­˜åœ¨"
+
+#. Give an indication of the number of matching tags
+#: tag.c:780
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "找到 tag: %d/%d%s"
+
+#: tag.c:783
+msgid " or more"
+msgstr " 或更多"
+
+#: tag.c:785
+msgid " Using tag with different case!"
+msgstr " 以ä¸åŒå¤§å°å¯«ä¾†ä½¿ç”¨ tag!"
+
+#: tag.c:828
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: 檔案 \"%s\" ä¸å­˜åœ¨"
+
+#. Highlight title
+#: tag.c:897
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # 到 tag 從 行 在 檔案/文字"
+
+#: tag.c:1144
+msgid "Linear tag search"
+msgstr "線性æœå°‹æ¨™ç±¤ (Tags)"
+
+#: tag.c:1146
+msgid "Binary tag search"
+msgstr "二分æœå°‹(Binary search) 標籤(Tags)"
+
+#: tag.c:1172
+#, c-format
+msgid "Searching tags file %s"
+msgstr "æœå°‹ tag 檔案 \"%s\""
+
+#: tag.c:1356
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Tag 檔案路徑被截斷為 %s\n"
+
+#: tag.c:1858
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Tag 檔 \"%s\" æ ¼å¼éŒ¯èª¤"
+
+#: tag.c:1862
+#, c-format
+msgid "Before byte %ld"
+msgstr "在 %ld ä½å…ƒä¹‹å‰"
+
+#: tag.c:1883
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Tag 檔案未排åº: %s"
+
+#. never opened any tags file
+#: tag.c:1922
+msgid "E433: No tags file"
+msgstr "E433: 沒有 tag 檔"
+
+#: tag.c:2600
+msgid "E434: Can't find tag pattern"
+msgstr "E434: 找ä¸åˆ° tag"
+
+#: tag.c:2611
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: 找ä¸åˆ° tag, 用猜的!"
+
+#: term.c:1745
+msgid "' not known. Available builtin terminals are:"
+msgstr "' 無法載入。å¯ç”¨çš„內建終端機形å¼æœ‰:"
+
+#: term.c:1769
+msgid "defaulting to '"
+msgstr "é è¨­: '"
+
+#: term.c:2127
+msgid "E557: Cannot open termcap file"
+msgstr "E557: 無法開啟 termcap 檔案"
+
+#: term.c:2131
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: terminfo 中沒有終端機資料項"
+
+#: term.c:2133
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: termcap 中沒有終端機資料項"
+
+#: term.c:2292
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: termcap 沒有 \"%s\" entry"
+
+#: term.c:2766
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: çµ‚ç«¯æ©Ÿéœ€è¦ \"cm\" 的能力"
+
+#. Highlight title
+#: term.c:4927
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- çµ‚ç«¯æ©ŸæŒ‰éµ ---"
+
+#: ui.c:252
+msgid "new shell started\n"
+msgstr "èµ·å‹•æ–° shell\n"
+
+#: ui.c:1784
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: 讀å–輸入錯誤,離開中...\n"
+
+#. must display the prompt
+#: undo.c:394
+msgid "No undo possible; continue anyway"
+msgstr "無法還原;請繼續努力"
+
+#: undo.c:549
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: 行號錯誤"
+
+#: undo.c:718
+msgid "1 change"
+msgstr "一項改變"
+
+#: undo.c:720
+#, c-format
+msgid "%ld changes"
+msgstr "%ld 項改變"
+
+#: undo.c:764
+msgid "E439: undo list corrupt"
+msgstr "E439: 復原列表æ壞"
+
+#: undo.c:796
+msgid "E440: undo line missing"
+msgstr "E440: 找ä¸åˆ°è¦ undo çš„è¡Œ"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:682
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 16/32 Bit 圖型界é¢ç‰ˆæœ¬"
+
+#: version.c:684
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 32 Bit 圖型界é¢ç‰ˆæœ¬"
+
+#: version.c:687
+msgid " in Win32s mode"
+msgstr "Win32s 模å¼"
+
+#: version.c:689
+msgid " with OLE support"
+msgstr "æ”¯æ´ OLE"
+
+#: version.c:692
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"MS-Windows 32 Bit console 版本"
+
+#: version.c:696
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"MS-Windows 32 Bit console 版本"
+
+#: version.c:700
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 Bit MS-DOS 版本"
+
+#: version.c:702
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 Bit MS-DOS 版本"
+
+#: version.c:708
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) 版本"
+
+#: version.c:710
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X 版本"
+
+#: version.c:713
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS 版本"
+
+#: version.c:718
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS 版本"
+
+#: version.c:728
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"引入修正: "
+
+#: version.c:754 version.c:1097
+msgid "Modified by "
+msgstr "修改者為"
+
+#: version.c:761
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"編譯"
+
+#: version.c:764
+msgid "by "
+msgstr "者:"
+
+#: version.c:776
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"超強版本 "
+
+#: version.c:779
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"大型版本 "
+
+#: version.c:782
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"一般版本 "
+
+#: version.c:785
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"簡易版本 "
+
+#: version.c:787
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"精簡版本 "
+
+#: version.c:793
+msgid "without GUI."
+msgstr "ä¸ä½¿ç”¨åœ–åž‹ç•Œé¢ã€‚"
+
+#: version.c:798
+msgid "with GTK2-GNOME GUI."
+msgstr "使用 GTK2-GNOME 圖型界é¢ã€‚"
+
+#: version.c:800
+msgid "with GTK-GNOME GUI."
+msgstr "使用 GTK-GNOME 圖型界é¢ã€‚"
+
+#: version.c:804
+msgid "with GTK2 GUI."
+msgstr "使用 GTK2 圖型界é¢ã€‚"
+
+#: version.c:806
+msgid "with GTK GUI."
+msgstr "使用 GTK 圖型界é¢ã€‚"
+
+#: version.c:811
+msgid "with X11-Motif GUI."
+msgstr "使用 X11-Motif 圖型界é¢ã€‚"
+
+#: version.c:814
+msgid "with X11-Athena GUI."
+msgstr "使用 X11-Athena 圖型界é¢ã€‚"
+
+#: version.c:817
+msgid "with BeOS GUI."
+msgstr "使用 BeOS 圖型界é¢ã€‚"
+
+#: version.c:820
+msgid "with Photon GUI."
+msgstr "使用Photon圖型界é¢ã€‚"
+
+#: version.c:823
+msgid "with GUI."
+msgstr "使用圖型界é¢ã€‚"
+
+#: version.c:826
+msgid "with Carbon GUI."
+msgstr "使用 Carbon 圖型界é¢ã€‚"
+
+#: version.c:829
+msgid "with Cocoa GUI."
+msgstr "使用 Cocoa 圖型界é¢ã€‚"
+
+#: version.c:832
+msgid "with (classic) GUI."
+msgstr "使用 (傳統) 圖型界é¢ã€‚"
+
+#: version.c:843
+msgid " Features included (+) or not (-):\n"
+msgstr " ç›®å‰å¯ä½¿ç”¨(+)與ä¸å¯ä½¿ç”¨(-)的模組列表:\n"
+
+#: version.c:855
+msgid " system vimrc file: \""
+msgstr " 系統 vimrc 設定檔: \""
+
+#: version.c:860
+msgid " user vimrc file: \""
+msgstr " 使用者個人 vimrc 設定檔: \""
+
+#: version.c:865
+msgid " 2nd user vimrc file: \""
+msgstr " 第二組個人 vimrc 檔案: \""
+
+#: version.c:870
+msgid " 3rd user vimrc file: \""
+msgstr " 第三組個人 vimrc 檔案: \""
+
+#: version.c:875
+msgid " user exrc file: \""
+msgstr " 使用者個人 exrc 設定檔: \""
+
+#: version.c:880
+msgid " 2nd user exrc file: \""
+msgstr " 第二組使用者 exrc 檔案: \""
+
+#: version.c:886
+msgid " system gvimrc file: \""
+msgstr " 系統 gvimrc 檔案: \""
+
+#: version.c:890
+msgid " user gvimrc file: \""
+msgstr " 使用者個人 gvimrc 檔: \""
+
+#: version.c:894
+msgid "2nd user gvimrc file: \""
+msgstr " 第二組個人 gvimrc 檔案: \""
+
+#: version.c:899
+msgid "3rd user gvimrc file: \""
+msgstr " 第三組個人 gvimrc 檔案: \""
+
+#: version.c:906
+msgid " system menu file: \""
+msgstr " 系統é¸å–®è¨­å®šæª”: \""
+
+#: version.c:914
+msgid " fall-back for $VIM: \""
+msgstr " $VIM é è¨­å€¼: \""
+
+#: version.c:920
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " $VIMRUNTIME é è¨­å€¼: \""
+
+#: version.c:924
+msgid "Compilation: "
+msgstr "編譯方å¼: "
+
+#: version.c:930
+msgid "Compiler: "
+msgstr "編譯器: "
+
+#: version.c:935
+msgid "Linking: "
+msgstr "éˆçµæ–¹å¼: "
+
+#: version.c:940
+msgid " DEBUG BUILD"
+msgstr " 除錯版本"
+
+#: version.c:976
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved"
+
+#: version.c:978
+msgid "version "
+msgstr "版本 "
+
+#: version.c:979
+msgid "by Bram Moolenaar et al."
+msgstr "維護者: Bram Moolenaar et al."
+
+#: version.c:983
+msgid "Vim is open source and freely distributable"
+msgstr "Vim 為å¯è‡ªç”±æ•£ä½ˆçš„開放原始碼軟體"
+
+#: version.c:985
+msgid "Help poor children in Uganda!"
+msgstr "請幫助çƒå¹²é”çš„å¯æ†å­©ç«¥!"
+
+#: version.c:986
+msgid "type :help iccf<Enter> for information "
+msgstr "進一步說明請輸入 :help iccf<Enter>"
+
+#: version.c:988
+msgid "type :q<Enter> to exit "
+msgstr "è¦é›¢é–‹è«‹è¼¸å…¥ :q<Enter> "
+
+#: version.c:989
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "線上說明請輸入 :help<Enter> "
+
+#: version.c:990
+msgid "type :help version6<Enter> for version info"
+msgstr "新版本資訊請輸入 :help version6<Enter>"
+
+#: version.c:993
+msgid "Running in Vi compatible mode"
+msgstr "Vi 相容模å¼"
+
+#: version.c:994
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "如果è¦å®Œå…¨æ¨¡æ“¬å‚³çµ± Vi 請輸入 :set nocp<Enter>"
+
+#: version.c:995
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "如果需è¦å° Vi 相容模å¼çš„進一步說明請輸入 :help cp-default<Enter>"
+
+#: version.c:1010
+msgid "menu Help->Orphans for information "
+msgstr "進一步說明請é¸å–é¸å–®çš„ 輔助說明->拯救孤兒"
+
+#: version.c:1012
+msgid "Running modeless, typed text is inserted"
+msgstr "執行 Modeless 模å¼ï¼Œè¼¸å…¥çš„文字會自動æ’å…¥"
+
+#: version.c:1013
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "é¸å–é¸å–®çš„「編輯ã€ã€Œå…¨åŸŸè¨­å®šã€ã€Œåˆ‡æ›æ’入模å¼ã€"
+
+#: version.c:1014
+msgid " for two modes "
+msgstr " å…©ç¨®æ¨¡å¼ "
+
+#: version.c:1018
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "é¸å–é¸å–®çš„「編輯ã€ã€Œå…¨åŸŸè¨­å®šã€ã€Œåˆ‡æ›å‚³çµ±Vi相容模å¼ã€"
+
+#: version.c:1019
+msgid " for Vim defaults "
+msgstr " 以得 Vim é è¨­å€¼ "
+
+#: version.c:1065
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "注æ„: åµæ¸¬åˆ° Windows 95/98/ME"
+
+#: version.c:1068
+msgid "type :help windows95<Enter> for info on this"
+msgstr "如果需è¦å° Windows 95 支æ´çš„更多資訊請輸入 :help windows95<Enter>"
+
+#: window.c:204
+msgid "E441: There is no preview window"
+msgstr "E441: 沒有é è¦½è¦–窗"
+
+#: window.c:577
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: ä¸èƒ½åŒæ™‚分割視窗為左上和å³ä¸‹è§’"
+
+#: window.c:1336
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: 有其它分割視窗時無法旋轉"
+
+#: window.c:1827
+msgid "E444: Cannot close last window"
+msgstr "E444: ä¸èƒ½é—œé–‰æœ€å¾Œä¸€å€‹è¦–窗"
+
+#: window.c:2557
+msgid "Already only one window"
+msgstr "已經åªå‰©ä¸€å€‹è¦–窗了"
+
+#: window.c:2604
+msgid "E445: Other window contains changes"
+msgstr "E445: 其它視窗有更動資料"
+
+#: window.c:4449
+msgid "E446: No file name under cursor"
+msgstr "E446: 游標處沒有檔å"
+
+#: window.c:4568
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: 在路徑中找ä¸åˆ°æª”案 \"%s\""
+
+#: ../GvimExt/gvimext.cpp:586
+msgid "Edit with &multiple Vims"
+msgstr "使用多個 Vim session 編輯(&M)"
+
+#: ../GvimExt/gvimext.cpp:592
+msgid "Edit with single &Vim"
+msgstr "åªä½¿ç”¨åŒä¸€å€‹ Vim session 編輯(&V)"
+
+#: ../GvimExt/gvimext.cpp:601
+msgid "&Diff with Vim"
+msgstr "使用 Vim 來比較(&Diff)"
+
+#: ../GvimExt/gvimext.cpp:614
+msgid "Edit with &Vim"
+msgstr "使用 Vim 編輯此檔(&V)"
+
+#. Now concatenate
+#: ../GvimExt/gvimext.cpp:636
+msgid "Edit with existing Vim - &"
+msgstr "使用執行中的 Vim session 編輯 - &"
+
+#: ../GvimExt/gvimext.cpp:749
+msgid "Edits the selected file(s) with Vim"
+msgstr "使用 Vim 編輯已é¸å–的檔案"
+
+#: ../GvimExt/gvimext.cpp:888 ../GvimExt/gvimext.cpp:969
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "無法執行程å¼: 請檢查 gvim 有沒有在你的 PATH 變數裡!"
+
+#: ../GvimExt/gvimext.cpp:889 ../GvimExt/gvimext.cpp:903
+#: ../GvimExt/gvimext.cpp:970
+msgid "gvimext.dll error"
+msgstr "gvimext.dll 錯誤"
+
+#: ../GvimExt/gvimext.cpp:902
+msgid "Path length too long!"
+msgstr "路徑長度太長!"
+
+#: globals.h:990
+msgid "--No lines in buffer--"
+msgstr "--ç·©è¡å€ç„¡è³‡æ–™--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1149
+msgid "E470: Command aborted"
+msgstr "E470: 命令被強制中斷執行"
+
+#: globals.h:1150
+msgid "E471: Argument required"
+msgstr "E471: 需è¦æŒ‡ä»¤åƒæ•¸"
+
+#: globals.h:1151
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ 後é¢æ‡‰è©²æœ‰ / ? 或 &"
+
+#: globals.h:1153
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: ä¸èƒ½åœ¨å‘½ä»¤åˆ—視窗中使用。<CR>執行,CTRL-C 離開"
+
+#: globals.h:1155
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr "E12: exrc/vimrc 裡的指令無法執行"
+
+#: globals.h:1157
+msgid "E171: Missing :endif"
+msgstr "E171: 缺少 :endif"
+
+#: globals.h:1158
+msgid "E600: Missing :endtry"
+msgstr "E600: 缺少 :endtry"
+
+#: globals.h:1159
+msgid "E170: Missing :endwhile"
+msgstr "E170: 缺少 :endwhile"
+
+#: globals.h:1160
+msgid "E588: :endwhile without :while"
+msgstr "E588: :endwhile 缺少å°æ‡‰çš„ :while"
+
+#: globals.h:1162
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: 檔案已經存在 (å¯ç”¨ ! 強制å–代)"
+
+#: globals.h:1163
+msgid "E472: Command failed"
+msgstr "E472: 命令執行失敗"
+
+#: globals.h:1165
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: ä¸æ­£ç¢ºçš„字元集 (Fontset): %s"
+
+#: globals.h:1169
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "ä¸æ­£ç¢ºçš„å­—åž‹å稱: %s"
+
+#: globals.h:1172
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: \"%s\" ä¸æ˜¯å›ºå®šå¯¬åº¦å­—åž‹"
+
+#: globals.h:1174
+msgid "E473: Internal error"
+msgstr "E473: 內部錯誤"
+
+#: globals.h:1175
+msgid "Interrupted"
+msgstr "已中斷"
+
+#: globals.h:1176
+msgid "E14: Invalid address"
+msgstr "E14: ä¸æ­£ç¢ºçš„ä½å€"
+
+#: globals.h:1177
+msgid "E474: Invalid argument"
+msgstr "E474: ä¸æ­£ç¢ºçš„åƒæ•¸"
+
+#: globals.h:1178
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: ä¸æ­£ç¢ºçš„åƒæ•¸: %s"
+
+#: globals.h:1180
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: ä¸æ­£ç¢ºçš„é‹ç®—å¼: %s"
+
+#: globals.h:1182
+msgid "E16: Invalid range"
+msgstr "E16: ä¸æ­£ç¢ºçš„範åœ"
+
+#: globals.h:1183
+msgid "E476: Invalid command"
+msgstr "E476: ä¸æ­£ç¢ºçš„命令"
+
+#: globals.h:1185
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" 是目錄"
+
+#: globals.h:1188
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: '=' å‰é¢å‡ºç¾äº†éŒ¯èª¤çš„å­—å…ƒ"
+
+#: globals.h:1191
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: 呼å«å‡½å¼åº« \"%s\"() 失敗"
+
+#: globals.h:1196
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: 無法é‡æ–°è¼‰å…¥ç¨‹å¼åº« %s"
+
+#: globals.h:1197
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: 無法載入程å¼åº«çš„å‡½å¼ %s"
+
+#: globals.h:1199
+msgid "E19: Mark has invalid line number"
+msgstr "E19: 標記的行號錯誤"
+
+#: globals.h:1200
+msgid "E20: Mark not set"
+msgstr "E20: 沒有設定標記"
+
+#: globals.h:1201
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: 因為 'modifiable' é¸é …是關閉的,所以ä¸èƒ½ä¿®æ”¹"
+
+#: globals.h:1202
+msgid "E22: Scripts nested too deep"
+msgstr "E22: 巢狀éžè¿´å‘¼å«å¤ªå¤šå±¤"
+
+#: globals.h:1203
+msgid "E23: No alternate file"
+msgstr "E23: 沒有替代的檔案"
+
+#: globals.h:1204
+msgid "E24: No such abbreviation"
+msgstr "E24: 沒有這個 abbreviation å°æ‡‰"
+
+#: globals.h:1205
+msgid "E477: No ! allowed"
+msgstr "E477: ä¸å¯ä½¿ç”¨ '!'"
+
+#: globals.h:1207
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: 因為編譯時沒有加入圖型界é¢çš„程å¼ç¢¼ï¼Œæ‰€ä»¥ç„¡æ³•ä½¿ç”¨åœ–åž‹ç•Œé¢"
+
+#: globals.h:1210
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: 因為編譯時沒有加入 Hebrew 的程å¼ç¢¼ï¼Œæ‰€ä»¥ç„¡æ³•ä½¿ç”¨ Hebrew\n"
+
+#: globals.h:1213
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: 因為編譯時沒有加入 Farsi 的程å¼ç¢¼ï¼Œæ‰€ä»¥ç„¡æ³•ä½¿ç”¨ Farsi\n"
+
+#: globals.h:1216
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: 沒有å為 '%s' çš„ highlight group"
+
+#: globals.h:1218
+msgid "E29: No inserted text yet"
+msgstr "E29: 還沒有æ’入文字éŽ"
+
+#: globals.h:1219
+msgid "E30: No previous command line"
+msgstr "E30: 沒有å‰ä¸€é …命令"
+
+#: globals.h:1220
+msgid "E31: No such mapping"
+msgstr "E31: 沒有這個 mapping å°æ‡‰"
+
+#: globals.h:1221
+msgid "E479: No match"
+msgstr "E479: 找ä¸åˆ°"
+
+#: globals.h:1222
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: 找ä¸åˆ°: %s"
+
+#: globals.h:1223
+msgid "E32: No file name"
+msgstr "E32: 沒有檔å"
+
+#: globals.h:1224
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: 沒有å‰ä¸€å€‹æœå°‹/å–代的命令"
+
+#: globals.h:1225
+msgid "E34: No previous command"
+msgstr "E34: 沒有å‰ä¸€å€‹å‘½ä»¤"
+
+#: globals.h:1226
+msgid "E35: No previous regular expression"
+msgstr "E35: 沒有å‰ä¸€å€‹æœå°‹æŒ‡ä»¤"
+
+#: globals.h:1227
+msgid "E481: No range allowed"
+msgstr "E481: ä¸å¯ä½¿ç”¨ç¯„åœæŒ‡ä»¤"
+
+#: globals.h:1229
+msgid "E36: Not enough room"
+msgstr "E36: 沒有足夠的空間"
+
+#: globals.h:1232
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: 沒有註冊為 \"%s\" 的伺æœå™¨"
+
+#: globals.h:1234
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: ä¸èƒ½å»ºç«‹æª”案 %s"
+
+#: globals.h:1235
+msgid "E483: Can't get temp file name"
+msgstr "E483: 無法得知暫存檔å"
+
+#: globals.h:1236
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: 無法開啟檔案 %s"
+
+#: globals.h:1237
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: 無法讀å–檔案 %s"
+
+#: globals.h:1238
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: 已更改éŽæª”案但尚未存檔 (å¯ç”¨ ! 強制執行)"
+
+#: globals.h:1239
+msgid "E38: Null argument"
+msgstr "E38: 空的 (Null) åƒæ•¸"
+
+#: globals.h:1241
+msgid "E39: Number expected"
+msgstr "E39: 應該è¦æœ‰æ•¸å­—"
+
+#: globals.h:1244
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: 無法開啟錯誤檔案 %s"
+
+#: globals.h:1247
+msgid "E233: cannot open display"
+msgstr "E233: <ä¸èƒ½é–‹å•Ÿ X Server DISPLAY>"
+
+#: globals.h:1249
+msgid "E41: Out of memory!"
+msgstr "E41: 記憶體ä¸è¶³!"
+
+#: globals.h:1251
+msgid "Pattern not found"
+msgstr "找ä¸åˆ°"
+
+#: globals.h:1253
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: 找ä¸åˆ° %s"
+
+#: globals.h:1254
+msgid "E487: Argument must be positive"
+msgstr "E487: åƒæ•¸æ‡‰è©²æ˜¯æ­£æ•¸"
+
+#: globals.h:1256
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: 無法回到å‰ä¸€å€‹ç›®éŒ„"
+
+#: globals.h:1260
+msgid "E42: No Errors"
+msgstr "E42: 沒有錯誤"
+
+#: globals.h:1262
+msgid "E43: Damaged match string"
+msgstr "E43: 符åˆå­—串有å•é¡Œ"
+
+#: globals.h:1263
+msgid "E44: Corrupted regexp program"
+msgstr "E44: regexp 有å•é¡Œ"
+
+#: globals.h:1264
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: 有設定 'readonly' é¸é …(唯讀) (å¯ç”¨ ! 強制執行)"
+
+#: globals.h:1266
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: 無法設定唯讀變數 \"%s\""
+
+#: globals.h:1269
+msgid "E47: Error while reading errorfile"
+msgstr "E47: 讀å–錯誤檔案失敗"
+
+#: globals.h:1272
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: ä¸èƒ½åœ¨ sandbox 裡出ç¾"
+
+#: globals.h:1274
+msgid "E523: Not allowed here"
+msgstr "E523: 這裡ä¸å¯ä½¿ç”¨"
+
+#: globals.h:1277
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: ä¸æ”¯æ´è¨­å®šèž¢å¹•æ¨¡å¼"
+
+#: globals.h:1279
+msgid "E49: Invalid scroll size"
+msgstr "E49: 錯誤的æ²å‹•å¤§å°"
+
+#: globals.h:1280
+msgid "E91: 'shell' option is empty"
+msgstr "E91: 'E71: é¸é … 'shell' 未設定"
+
+#: globals.h:1282
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: ç„¡æ³•è®€å– sign data!"
+
+#: globals.h:1284
+msgid "E72: Close error on swap file"
+msgstr "E72: 暫存檔關閉錯誤"
+
+#: globals.h:1285
+msgid "E73: tag stack empty"
+msgstr "E73: 標籤堆疊已空"
+
+#: globals.h:1286
+msgid "E74: Command too complex"
+msgstr "E74: 命令太複雜"
+
+#: globals.h:1287
+msgid "E75: Name too long"
+msgstr "E75: å字太長"
+
+#: globals.h:1288
+msgid "E76: Too many ["
+msgstr "E76: 太多 ["
+
+#: globals.h:1289
+msgid "E77: Too many file names"
+msgstr "E77: 太多檔å"
+
+#: globals.h:1290
+msgid "E488: Trailing characters"
+msgstr "E488: 你輸入了多餘的字元"
+
+#: globals.h:1291
+msgid "E78: Unknown mark"
+msgstr "E78: 無法辦識的標記"
+
+#: globals.h:1292
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: 無法展開è¬ç”¨å­—å…ƒ"
+
+#: globals.h:1294
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: 'winheight' ä¸èƒ½æ¯” 'winminheight' æ›´å°‘"
+
+#: globals.h:1296
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: 'winwidth' ä¸èƒ½æ¯” 'winminwidth' æ›´å°‘"
+
+#: globals.h:1299
+msgid "E80: Error while writing"
+msgstr "E80: 寫入錯誤"
+
+#: globals.h:1300
+msgid "Zero count"
+msgstr "數到零 (?)"
+
+#: globals.h:1302
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: <SID> ä¸èƒ½åœ¨ script 本文外使用."
+
+#: globals.h:1305
+msgid "E449: Invalid expression received"
+msgstr "E449: 收到ä¸æ­£ç¢ºçš„é‹ç®—å¼"
+
+#: globals.h:1308
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: å€åŸŸè¢«ä¿è­·ï¼Œç„¡æ³•ä¿®æ”¹"
+
+#~ msgid "function "
+#~ msgstr "å‡½å¼ "
+
+#~ msgid "Run Macro"
+#~ msgstr "執行巨集"
+
+#~ msgid "E221: 'commentstring' is empty"
+#~ msgstr "E221: é¸é … 'commentstring' 未設定"
+
+#~ msgid "E242: Color name not recognized: %s"
+#~ msgstr "E242: %s 為無法識別的é¡è‰²å稱"
+
+#~ msgid "E242: Missing color: %s"
+#~ msgstr "E242: 找ä¸åˆ°é¡è‰²: %s"
+
+#~ msgid "error reading cscope connection %d"
+#~ msgstr "è®€å– cscope 連線 %d 時錯誤"
+
+#~ msgid "E249: couldn't read VIM instance registry property"
+#~ msgstr "E249: ç„¡æ³•è®€å– VIM çš„ registry 設定項"
+
+#~ msgid "Can't open file %s"
+#~ msgstr "無法開啟檔案 %s"
+
+#~ msgid "Unable to send reply"
+#~ msgstr "無法傳é€å›žæ‡‰è¨Šæ¯"
+
+#~ msgid "E241: Unable to send to Vim server"
+#~ msgstr "E241: 無法傳é€åˆ° Vim 伺æœå™¨"
+
+#~ msgid ""
+#~ "\n"
+#~ "Send failed. No command server present ?\n"
+#~ msgstr ""
+#~ "\n"
+#~ "傳é€å¤±æ•—。沒有命令伺æœå™¨å­˜åœ¨ ?\n"
+
+#~ msgid "PC (32 bits Vim)"
+#~ msgstr "PC (32 ä½å…ƒ Vim)"
+
+#~ msgid "PC (16 bits Vim)"
+#~ msgstr "PC (16 ä½å…ƒ Vim)"
+
+#~ msgid "E362: Unsupported screen mode"
+#~ msgstr "E362: 螢幕模å¼ä¸æ”¯æ´"
+
+#~ msgid "No servers found for this display"
+#~ msgstr "æ­¤Display沒有伺æœå™¨(Servers)"
+
+#~ msgid "E258: no matches found in cscope connections"
+#~ msgstr "E258: cscope 連線找ä¸åˆ°ç¬¦åˆçš„"
+
+#~ msgid ""
+#~ "\n"
+#~ "MacOS Carbon"
+#~ msgstr ""
+#~ "\n"
+#~ "MacOS Carbon"
+
+#~ msgid ""
+#~ "\n"
+#~ "MacOS 8"
+#~ msgstr ""
+#~ "\n"
+#~ "MacOS 8"
+
+#~ msgid "Retrieve next symbol"
+#~ msgstr "讀å–: 從下個 symbol"
+
+#~ msgid "-- SNiFF+ commands --"
+#~ msgstr "-- SNiFF+ 命令 --"
+
+#~ msgid "E277: Unrecognized sniff request [%s]"
+#~ msgstr "E277: 無法辨識 sniff 命令 [%s]"
diff --git a/src/po/zh_TW.po b/src/po/zh_TW.po
new file mode 100644
index 000000000..c318e6341
--- /dev/null
+++ b/src/po/zh_TW.po
@@ -0,0 +1,6389 @@
+# Traditional Chinese Translation for Vim vim:set foldmethod=marker:
+#
+# Do ":help uganda" in Vim to read copying and usage conditions.
+# Do ":help credits" in Vim to see a list of people who contributed.
+#
+# FIRST AUTHOR Francis S.Lin <piaip@csie.ntu.edu.tw>, 2000
+# FIRST RELEASE Thu Jun 14 14:24:17 CST 2001
+#
+# Last update: Thu Apr 24 13:09:07 CST 2003 (6.2a)
+#
+# To update, search pattern: /fuzzy\|^msgstr ""\(\n"\)\@!
+#
+# DO NOT USE WORDS WITH BACKSLASH ('\') AS SECOND BYTE OF BIG5 CHARS
+# EG: '¥\', # ³\¥\»\
+# À\¬\¾\¯\½\¶\²\Æ\°\Â\¿\Á\Å\§\ª\«\
+# ¼\®\±\Ã\Ä\´\µ\·\¸\¹\º\¢\¤\¦\¨\©\­\á\ä\
+# you can replace these characters with alternative words.
+# THIS WILL CAUSE INCOMPATIBLE ON gettext 0.10.36+
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Vim(Traditional Chinese)\n"
+"POT-Creation-Date: 2003-04-24 13:06+0800\n"
+"PO-Revision-Date: Mon Feb 19 22:49:21 CST 2001\n"
+"Last-Translator: Francis S.Lin <piaip@csie.ntu.edu.tw>\n"
+"Language-Team: Francis S.Lin <piaip@csie.ntu.edu.tw>, Cecil Sheng "
+"<b7506022@csie.ntu.edu.tw>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=big5\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: buffer.c:97
+msgid "E82: Cannot allocate any buffer, exiting..."
+msgstr "E82: µLªk°t¸m¥ô¦ó½w½Ä°Ï¡AÂ÷¶}µ{¦¡..."
+
+#: buffer.c:100
+msgid "E83: Cannot allocate buffer, using other one..."
+msgstr "E83: µLªk°t¸m½w½Ä°Ï¡A¨Ï¥Î¥t¤@­Ó½w½Ä°Ï...."
+
+#: buffer.c:797
+msgid "E515: No buffers were unloaded"
+msgstr "E515: ¨S¦³ÄÀ©ñ¥ô¦ó½w½Ä°Ï"
+
+#: buffer.c:799
+msgid "E516: No buffers were deleted"
+msgstr "E516: ¨S¦³§R°£¥ô¦ó½w½Ä°Ï"
+
+#: buffer.c:801
+msgid "E517: No buffers were wiped out"
+msgstr "E517: ¨S¦³²M°£¥ô¦ó½w½Ä°Ï"
+
+#: buffer.c:809
+msgid "1 buffer unloaded"
+msgstr "¤wÄÀ©ñ¤@­Ó½w½Ä°Ï"
+
+#: buffer.c:811
+#, c-format
+msgid "%d buffers unloaded"
+msgstr "¤wÄÀ©ñ %d ­Ó½w½Ä°Ï"
+
+#: buffer.c:816
+msgid "1 buffer deleted"
+msgstr "¤w§R°£¤@­Ó½w½Ä°Ï"
+
+#: buffer.c:818
+#, c-format
+msgid "%d buffers deleted"
+msgstr "¤w§R°£ %d ­Ó½w½Ä°Ï"
+
+#: buffer.c:823
+msgid "1 buffer wiped out"
+msgstr "¤w§R°£¤@­Ó½w½Ä°Ï"
+
+#: buffer.c:825
+#, c-format
+msgid "%d buffers wiped out"
+msgstr "¤w§R°£ %d ­Ó½w½Ä°Ï"
+
+#: buffer.c:886
+msgid "E84: No modified buffer found"
+msgstr "E84: ¨S¦³­×§ï¹Lªº½w½Ä°Ï"
+
+#. back where we started, didn't find anything.
+#: buffer.c:925
+msgid "E85: There is no listed buffer"
+msgstr "E85: ¨S¦³¦C¥Xªº½w½Ä°Ï"
+
+#: buffer.c:937
+#, c-format
+msgid "E86: Cannot go to buffer %ld"
+msgstr "E86: µLªk¤Á´«¨ì²Ä %ld ­Ó½w½Ä°Ï"
+
+#: buffer.c:940
+msgid "E87: Cannot go beyond last buffer"
+msgstr "E87: µLªk¤Á´«¨ì§ó«á­±ªº½w½Ä°Ï"
+
+#: buffer.c:942
+msgid "E88: Cannot go before first buffer"
+msgstr "E88: µLªk¤Á´«¨ì§ó«e­±ªº½w½Ä°Ï"
+
+#: buffer.c:966
+msgid "E89: No write since last change for buffer %ld (add ! to override)"
+msgstr "E89: ¤w§ó§ï¹L½w½Ä°Ï %ld ¦ý©|¥¼¦sÀÉ (¥i¥Î ! ±j¨î°õ¦æ)"
+
+#: buffer.c:982
+msgid "E90: Cannot unload last buffer"
+msgstr "E90: µLªkÄÀ©ñ³Ì«á¤@­Ó½w½Ä°Ï"
+
+#: buffer.c:1494
+msgid "W14: Warning: List of file names overflow"
+msgstr "W14: ĵ§i: ÀɦW¹L¦h"
+
+#: buffer.c:1664
+#, c-format
+msgid "E92: Buffer %ld not found"
+msgstr "E92: §ä¤£¨ì²Ä %ld ­Ó½w½Ä°Ï"
+
+#: buffer.c:1890
+#, c-format
+msgid "E93: More than one match for %s"
+msgstr "E93: §ä¨ì¤@­Ó¥H¤Wªº %s"
+
+#: buffer.c:1892
+#, c-format
+msgid "E94: No matching buffer for %s"
+msgstr "E94: §ä¤£¨ì %s"
+
+#: buffer.c:2297 ex_docmd.c:6479
+#, c-format
+msgid "line %ld"
+msgstr "¦æ %ld"
+
+#: buffer.c:2380
+msgid "E95: Buffer with this name already exists"
+msgstr "E95: ¤w¦³½w½Ä°Ï¨Ï¥Î³o­Ó¦W¦r"
+
+#: buffer.c:2673
+msgid " [Modified]"
+msgstr " [¤w­×§ï]"
+
+#: buffer.c:2678
+msgid "[Not edited]"
+msgstr "[¥¼½s¿è]"
+
+#: buffer.c:2683
+msgid "[New file]"
+msgstr "[·sÀÉ®×]"
+
+#: buffer.c:2684
+msgid "[Read errors]"
+msgstr "[Ū¨ú¿ù»~]"
+
+#: buffer.c:2686 fileio.c:1914
+msgid "[readonly]"
+msgstr "[°ßŪ]"
+
+#: buffer.c:2701
+#, c-format
+msgid "1 line --%d%%--"
+msgstr "¦æ¼Æ 1 --%d%%--"
+
+#: buffer.c:2703
+#, c-format
+msgid "%ld lines --%d%%--"
+msgstr "¦æ¼Æ %ld --%d%%--"
+
+#: buffer.c:2710
+#, c-format
+msgid "line %ld of %ld --%d%%-- col "
+msgstr "¦æ %ld/%ld --%d%%-- Äæ "
+
+#: buffer.c:2811
+msgid "[No file]"
+msgstr "[¥¼©R¦W]"
+
+#. must be a help buffer
+#: buffer.c:2851
+msgid "help"
+msgstr "[»²§U»¡©ú]"
+
+#: buffer.c:3405 screen.c:4943
+msgid "[help]"
+msgstr "[»²§U»¡©ú]"
+
+#: buffer.c:3437 screen.c:4949
+msgid "[Preview]"
+msgstr "[¹wÄý]"
+
+#: buffer.c:3708
+msgid "All"
+msgstr "¥þ³¡"
+
+#: buffer.c:3708
+msgid "Bot"
+msgstr "©³ºÝ"
+
+#: buffer.c:3710
+msgid "Top"
+msgstr "³»ºÝ"
+
+#: buffer.c:4454
+msgid ""
+"\n"
+"# Buffer list:\n"
+msgstr ""
+"\n"
+"# ½w½Ä°Ï¦Cªí:\n"
+
+#: buffer.c:4487
+msgid "[Error List]"
+msgstr "[¿ù»~¦Cªí]"
+
+#: buffer.c:4500 memline.c:1501
+msgid "[No File]"
+msgstr "[¥¼©R¦W]"
+
+#: buffer.c:4803
+msgid ""
+"\n"
+"--- Signs ---"
+msgstr ""
+"\n"
+"--- ²Å¸¹ ---"
+
+#: buffer.c:4813
+#, c-format
+msgid "Signs for %s:"
+msgstr "%s ªº²Å¸¹:"
+
+#: buffer.c:4819
+#, c-format
+msgid " line=%ld id=%d name=%s"
+msgstr " ¦æ=%ld id=%d ¦WºÙ=%s"
+
+#: diff.c:133
+#, c-format
+msgid "E96: Can not diff more than %ld buffers"
+msgstr "E96: µLªk¤ñ¸û(diff) %ld­Ó¥H¤Wªº½w½Ä°Ï"
+
+#: diff.c:651
+msgid "E97: Cannot create diffs"
+msgstr "E97: ¤£¯à«Ø¥ß "
+
+#: diff.c:750
+msgid "Patch file"
+msgstr "Patch ÀÉ®×"
+
+#: diff.c:1001
+msgid "E98: Cannot read diff output"
+msgstr "E98: µLªkŪ¨ú diff ªº¿é¥X"
+
+#: diff.c:1742
+msgid "E99: Current buffer is not in diff mode"
+msgstr "E99: ¥Ø«eªº½w½Ä°Ï¤£¬O¦b diff ¼Ò¦¡"
+
+#: diff.c:1754
+msgid "E100: No other buffer in diff mode"
+msgstr "E100: ¨S¦³½w½Ä°Ï¦b diff ¼Ò¦¡"
+
+#: diff.c:1762
+msgid "E101: More than two buffers in diff mode, don't know which one to use"
+msgstr "E101: ¦³¨â­Ó¥H¤Wªº½w½Ä°Ï¦b diff ¼Ò¦¡¡AµLªk¨M©w­n¥Î­þ¤@­Ó"
+
+#: diff.c:1785
+#, c-format
+msgid "E102: Can't find buffer \"%s\""
+msgstr "E102: §ä¤£¨ì½w½Ä°Ï: \"%s\""
+
+#: diff.c:1791
+#, c-format
+msgid "E103: Buffer \"%s\" is not in diff mode"
+msgstr "E103: ½w½Ä°Ï \"%s\" ¤£¬O¦b diff ¼Ò¦¡"
+
+#: digraph.c:2172
+msgid "E104: Escape not allowed in digraph"
+msgstr "E104: ½Æ¦X¦r¤¸(digraph)¤¤¤£¯à¨Ï¥Î Escape"
+
+#: digraph.c:2344
+msgid "E544: Keymap file not found"
+msgstr "E544: §ä¤£¨ì keymap ÀÉ"
+
+#: digraph.c:2371
+msgid "E105: Using :loadkeymap not in a sourced file"
+msgstr "E105: ¨Ï¥Î :loadkeymap "
+
+#: edit.c:40
+msgid " Keyword completion (^N/^P)"
+msgstr " ÃöÁä¦r¦Û°Ê§¹¦¨ (^N/^P)"
+
+#. ctrl_x_mode == 0, ^P/^N compl.
+#: edit.c:41
+msgid " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"
+msgstr " ^X ¼Ò¦¡ (^E/^Y/^L/^]/^F/^I/^K/^D/^N/^P)"
+
+#. Scroll has it's own msgs, in it's place there is the msg for local
+#. * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo
+#: edit.c:44
+msgid " Keyword Local completion (^N/^P)"
+msgstr " °Ï°ìÃöÁä¦r¦Û°Ê§¹¦¨ (^N/^P)"
+
+#: edit.c:45
+msgid " Whole line completion (^L/^N/^P)"
+msgstr " ¾ã¦æ¦Û°Ê§¹¦¨ (^L/^N/^P)"
+
+#: edit.c:46
+msgid " File name completion (^F/^N/^P)"
+msgstr " ÀɦW¦Û°Ê§¹¦¨ (^F/^N/^P)"
+
+#: edit.c:47
+msgid " Tag completion (^]/^N/^P)"
+msgstr " ¼ÐÅҦ۰ʧ¹¦¨ (^]/^N/^P)"
+
+#: edit.c:48
+msgid " Path pattern completion (^N/^P)"
+msgstr " ¸ô®|¦Û°Ê§¹¦¨ (^N/^P)"
+
+#: edit.c:49
+msgid " Definition completion (^D/^N/^P)"
+msgstr " ©w¸q¦Û°Ê§¹¦¨ (^D/^N/^P)"
+
+#: edit.c:51
+msgid " Dictionary completion (^K/^N/^P)"
+msgstr " ¦r¨å¦Û°Ê§¹¦¨ (^K/^N/^P)"
+
+#: edit.c:52
+msgid " Thesaurus completion (^T/^N/^P)"
+msgstr " Thesaurus ¦Û°Ê§¹¦¨ (^T/^N/^P)"
+
+#: edit.c:53
+msgid " Command-line completion (^V/^N/^P)"
+msgstr " ©R¥O¦C¦Û°Ê§¹¦¨ (^V/^N/^P)"
+
+#: edit.c:56
+msgid "Hit end of paragraph"
+msgstr "¤w¨ì¬q¸¨µ²§À"
+
+#: edit.c:941
+msgid "'thesaurus' option is empty"
+msgstr "¿ï¶µ 'thesaurus' ¥¼³]©w"
+
+#: edit.c:1145
+msgid "'dictionary' option is empty"
+msgstr "¿ï¶µ 'dictionary' ¥¼³]©w"
+
+#: edit.c:2130
+#, c-format
+msgid "Scanning dictionary: %s"
+msgstr "±½ºË¦r¨å: %s"
+
+#: edit.c:2336
+msgid " (insert) Scroll (^E/^Y)"
+msgstr " (´¡¤J) Scroll (^E/^Y)"
+
+#: edit.c:2338
+msgid " (replace) Scroll (^E/^Y)"
+msgstr " (¨ú¥N) Scroll (^E/^Y)"
+
+#: edit.c:2652
+#, c-format
+msgid "Scanning: %s"
+msgstr "±½ºË¤¤: %s"
+
+#: edit.c:2687
+msgid "Scanning tags."
+msgstr "±½ºË¼ÐÅÒ."
+
+#: edit.c:3349
+msgid " Adding"
+msgstr " ¼W¥["
+
+#. showmode might reset the internal line pointers, so it must
+#. * be called before line = ml_get(), or when this address is no
+#. * longer needed. -- Acevedo.
+#.
+#: edit.c:3398
+msgid "-- Searching..."
+msgstr "-- ·j´M¤¤..."
+
+#: edit.c:3454
+msgid "Back at original"
+msgstr "¦^¨ì°_ÂI"
+
+#: edit.c:3459
+msgid "Word from other line"
+msgstr "±q§O¦æ¶}©lªº¦r (?)"
+
+#: edit.c:3464
+msgid "The only match"
+msgstr "¥u¦³¦¹¶µ²Å¦X"
+
+#: edit.c:3523
+#, c-format
+msgid "match %d of %d"
+msgstr "§ä¨ì %d / %d"
+
+#: edit.c:3526
+#, c-format
+msgid "match %d"
+msgstr "²Å¦X %d"
+
+#. Skip further arguments but do continue to
+#. * search for a trailing command.
+#: eval.c:889
+#, c-format
+msgid "E106: Unknown variable: \"%s\""
+msgstr "E106: ¥¼©w¸qªºÅܼÆ: \"%s\""
+
+#: eval.c:1185
+#, c-format
+msgid "E107: Missing braces: %s"
+msgstr "E107: ¯Ê¤Ö¹ïÀ³ªº¬A¸¹: %s"
+
+#: eval.c:1290 eval.c:1304
+#, c-format
+msgid "E108: No such variable: \"%s\""
+msgstr "E108: µL¦¹ÅܼÆ: \"%s\""
+
+#: eval.c:1560
+msgid "E109: Missing ':' after '?'"
+msgstr "E109: '?' «á¯Ê¤Ö ':'"
+
+#: eval.c:2176
+msgid "E110: Missing ')'"
+msgstr "E110: ¯Ê¤Ö¹ïÀ³ªº \")\""
+
+#: eval.c:2233
+msgid "E111: Missing ']'"
+msgstr "E111: ¯Ê¤Ö¹ïÀ³ªº \"]\""
+
+#: eval.c:2309
+#, c-format
+msgid "E112: Option name missing: %s"
+msgstr "E112: ¯Ê¤Ö¿ï¶µ¦WºÙ: %s"
+
+#: eval.c:2327
+#, c-format
+msgid "E113: Unknown option: %s"
+msgstr "E113: ¤£¥¿½Tªº¿ï¶µ: %s"
+
+#: eval.c:2391
+#, c-format
+msgid "E114: Missing quote: %s"
+msgstr "E114: ¯Ê¤Ö¤Þ¸¹: %s"
+
+#: eval.c:2523
+#, c-format
+msgid "E115: Missing quote: %s"
+msgstr "E115: ¯Ê¤Ö¤Þ¸¹: %s"
+
+#: eval.c:2843
+#, c-format
+msgid "E116: Invalid arguments for function %s"
+msgstr "E116: ¨ç¦¡ %s ªº¤Þ¼Æ¤£¥¿½T"
+
+#: eval.c:2844
+#, c-format
+msgid "E117: Unknown function: %s"
+msgstr "E117: ¥¼©w¸qªº¨ç¦¡: %s"
+
+#: eval.c:2845
+#, c-format
+msgid "E118: Too many arguments for function: %s"
+msgstr "E118: ¨ç¦¡ %s ªº¤Þ¼Æ¹L¦h"
+
+#: eval.c:2846
+#, c-format
+msgid "E119: Not enough arguments for function: %s"
+msgstr "E119: ¨ç¦¡ %s ªº¤Þ¼Æ¤Ó¤Ö"
+
+#: eval.c:2847
+#, c-format
+msgid "E120: Using <SID> not in a script context: %s"
+msgstr "E120: <SID> ¤£¯à¦b script ¥»¤å¥~¨Ï¥Î: %s"
+
+#.
+#. * Yes this is ugly, I don't particularly like it either. But doing it
+#. * this way has the compelling advantage that translations need not to
+#. * be touched at all. See below what 'ok' and 'ync' are used for.
+#.
+#: eval.c:3465 gui.c:4238 gui_gtk.c:1991
+msgid "&Ok"
+msgstr "½T©w(&O)"
+
+#: eval.c:4000
+#, c-format
+msgid "+-%s%3ld lines: "
+msgstr "+-%s%3ld ¦æ: "
+
+#: eval.c:5149
+msgid ""
+"&OK\n"
+"&Cancel"
+msgstr ""
+"½T©w(&O)\n"
+"¨ú®ø(&C)"
+
+#: eval.c:5182
+msgid "called inputrestore() more often than inputsave()"
+msgstr "©I¥s inputrestore() ªº¦¸¼Æ¤ñ inputsave() ÁÙ¦h"
+
+#: eval.c:6036
+msgid "E240: No connection to Vim server"
+msgstr "E240: ¨S¦³»P Vim Server «Ø¥ß³s½u"
+
+#: eval.c:6133
+msgid "E277: Unable to read a server reply"
+msgstr "E277: µLªkŪ¨ú¦øªA¾¹ªº¦^À³"
+
+#: eval.c:6161
+msgid "E258: Unable to send to client"
+msgstr "E258: µLªk¶Ç°e¨ì client"
+
+#: eval.c:6209
+#, c-format
+msgid "E241: Unable to send to %s"
+msgstr "E241: µLªk¶Ç°e¨ì %s"
+
+#: eval.c:6309
+msgid "(Invalid)"
+msgstr "(¤£¥¿½T)"
+
+#: eval.c:7402
+#, c-format
+msgid "E121: Undefined variable: %s"
+msgstr "E121: ÅÜ¼Æ %s ©|¥¼©w¸q"
+
+#: eval.c:7834
+#, c-format
+msgid "E461: Illegal variable name: %s"
+msgstr "E461: ¤£¦XªkªºÅܼƦWºÙ: %s"
+
+#: eval.c:8121
+#, c-format
+msgid "E122: Function %s already exists, add ! to replace it"
+msgstr "E122: ¨ç¦¡ %s ¤w¸g¦s¦b, ½Ð¨Ï¥Î ! ±j¨î¨ú¥N"
+
+#: eval.c:8188
+#, c-format
+msgid "E123: Undefined function: %s"
+msgstr "E123: ¨ç¦¡ %s ©|¥¼©w¸q"
+
+#: eval.c:8201
+#, c-format
+msgid "E124: Missing '(': %s"
+msgstr "E124: ¯Ê¤Ö \"(\": %s"
+
+#: eval.c:8234
+#, c-format
+msgid "E125: Illegal argument: %s"
+msgstr "E125: °Ñ¼Æ¤£¥¿½T: %s"
+
+#: eval.c:8313
+msgid "E126: Missing :endfunction"
+msgstr "E126: ¯Ê¤Ö :endfunction"
+
+#: eval.c:8396
+#, c-format
+msgid "E127: Cannot redefine function %s: It is in use"
+msgstr "E127: ¨ç¦¡ %s ¥¿¦b¨Ï¥Î¤¤¡AµLªk­«·s©w¸q"
+
+#: eval.c:8464
+msgid "E129: Function name required"
+msgstr "E129: »Ý­n¨ç¦¡¦WºÙ"
+
+#: eval.c:8515
+#, c-format
+msgid "E128: Function name must start with a capital: %s"
+msgstr "E128: ¨ç¦¡¦WºÙ²Ä¤@­Ó¦r¥À¥²¶·¤j¼g: %s"
+
+#: eval.c:8707
+#, c-format
+msgid "E130: Undefined function: %s"
+msgstr "E130: ¨ç¦¡ %s ©|¥¼©w¸q"
+
+#: eval.c:8712
+#, c-format
+msgid "E131: Cannot delete function %s: It is in use"
+msgstr "E131: ¨ç¦¡ %s ¥¿¦b¨Ï¥Î¤¤¡AµLªk§R°£"
+
+#: eval.c:8760
+msgid "E132: Function call depth is higher than 'maxfuncdepth'"
+msgstr "E132: ¨ç¦¡»¼°j©I¥s¼h¼Æ¶W¹L 'maxfuncdepth'"
+
+#. always scroll up, don't overwrite
+#: eval.c:8813
+#, c-format
+msgid "calling %s"
+msgstr "©I¥s %s"
+
+#: eval.c:8867
+#, c-format
+msgid "%s aborted"
+msgstr "%s ³Q±j¨î¤¤Â_°õ¦æ"
+
+#: eval.c:8869
+#, c-format
+msgid "%s returning #%ld"
+msgstr "%s ¶Ç¦^­È #%ld "
+
+#: eval.c:8872
+#, c-format
+msgid "%s returning \"%s\""
+msgstr "%s ¶Ç¦^­È \"%s\""
+
+#. always scroll up, don't overwrite
+#: eval.c:8888 ex_cmds2.c:2231
+#, c-format
+msgid "continuing in %s"
+msgstr "Ä~Äò: %s"
+
+#: eval.c:8935
+msgid "E133: :return not inside a function"
+msgstr "E133: :return ¥²¶·¦b¨ç¦¡¸Ì¨Ï¥Î"
+
+#: eval.c:9266
+msgid ""
+"\n"
+"# global variables:\n"
+msgstr ""
+"\n"
+"# ¥þ°ìÅܼÆ:\n"
+
+#: ex_cmds.c:92
+#, c-format
+msgid "<%s>%s%s %d, Hex %02x, Octal %03o"
+msgstr "<%s>%s%s %d, ¤Q¤»¶i¦ì %02x, ¤K¶i¦ì %03o"
+
+#: ex_cmds.c:433
+msgid "E134: Move lines into themselves"
+msgstr "E134: µLªk§â¦æ²¾¨ì¥¦¦Û¤w¤º"
+
+#: ex_cmds.c:502
+msgid "1 line moved"
+msgstr "¤w·h²¾ 1 ¦æ"
+
+#: ex_cmds.c:504
+#, c-format
+msgid "%ld lines moved"
+msgstr "¤w·h²¾ %ld ¦æ"
+
+#: ex_cmds.c:909
+#, c-format
+msgid "%ld lines filtered"
+msgstr "¤w³B²z %ld ¦æ"
+
+#: ex_cmds.c:937
+msgid "E135: *Filter* Autocommands must not change current buffer"
+msgstr "E135: *Filter* Autocommand ¤£¥i¥H§ó§ï½w½Ä°Ïªº¤º®e"
+
+#: ex_cmds.c:1022
+msgid "[No write since last change]\n"
+msgstr "[§ó·s«á©|¥¼Àx¦s]\n"
+
+#: ex_cmds.c:1268
+#, c-format
+msgid "%sviminfo: %s in line: "
+msgstr "%sviminfo: %s ¦b¦æ¤¤: "
+
+#: ex_cmds.c:1273
+msgid "E136: viminfo: Too many errors, skipping rest of file"
+msgstr "E136: viminfo: ¹L¦h¿ù»~, ©¿²¤Àɮרä¾l³¡¤À"
+
+#: ex_cmds.c:1302
+#, c-format
+msgid "Reading viminfo file \"%s\"%s%s%s"
+msgstr "Ū¨ú viminfo ÀÉ®× \"%s\"%s%s%s"
+
+#: ex_cmds.c:1303
+msgid " info"
+msgstr " °T®§"
+
+#: ex_cmds.c:1304
+msgid " marks"
+msgstr " ¼Ð°O"
+
+#: ex_cmds.c:1305
+msgid " FAILED"
+msgstr " ¥¢±Ñ"
+
+#: ex_cmds.c:1396
+#, c-format
+msgid "E137: Viminfo file is not writable: %s"
+msgstr "E137: Viminfo ÀÉ®×µLªk¼g¤J: %s"
+
+#: ex_cmds.c:1521
+#, c-format
+msgid "E138: Can't write viminfo file %s!"
+msgstr "E138: µLªk¼g¤J viminfo ÀÉ®× %s !"
+
+#: ex_cmds.c:1529
+#, c-format
+msgid "Writing viminfo file \"%s\""
+msgstr "¼g¤J viminfo ÀÉ®× \"%s\" ¤¤"
+
+#. Write the info:
+#: ex_cmds.c:1627
+#, c-format
+msgid "# This viminfo file was generated by Vim %s.\n"
+msgstr "# ¥» viminfo Àɮ׬O¥Ñ Vim %s ©Ò²£¥Í.\n"
+
+#: ex_cmds.c:1629
+msgid ""
+"# You may edit it if you're careful!\n"
+"\n"
+msgstr ""
+"# ¦pªG·Q­n¦Û¦æ­×§ï½Ð¯S§O¤p¤ß¡I\n"
+"\n"
+
+#: ex_cmds.c:1631
+msgid "# Value of 'encoding' when this file was written\n"
+msgstr "# 'encoding' ¦b¦¹Àɫإ߮ɪº­È\n"
+
+#: ex_cmds.c:1730
+msgid "Illegal starting char"
+msgstr "µL®Äªº°_©l¦r¤¸"
+
+#: ex_cmds.c:2075 ex_cmds.c:2340 ex_cmds2.c:744
+msgid "Save As"
+msgstr "¥t¦s·sÀÉ"
+
+#. Overwriting a file that is loaded in another buffer is not a
+#. * good idea.
+#: ex_cmds.c:2118
+msgid "E139: File is loaded in another buffer"
+msgstr "E139: ±z¦b¥t¤@­Ó½w½Ä°Ï¤]¸ü¤J¤F³o­ÓÀÉ®×"
+
+#: ex_cmds.c:2152
+msgid "Write partial file?"
+msgstr "­n¼g¤J³¡¤ÀÀɮ׶ܡH"
+
+#: ex_cmds.c:2159
+msgid "E140: Use ! to write partial buffer"
+msgstr "E140: ½Ð¨Ï¥Î ! ¥H¼g¤J³¡¤À½w½Ä°Ï"
+
+#: ex_cmds.c:2274
+#, c-format
+msgid "Overwrite existing file \"%.*s\"?"
+msgstr "­nÂмg¤w¦s¦bªºÀÉ®× \"%.*s\"¡H"
+
+#: ex_cmds.c:2345
+#, c-format
+msgid "E141: No file name for buffer %ld"
+msgstr "E141: ½w½Ä°Ï %ld ¨S¦³ÀɮצWºÙ"
+
+#: ex_cmds.c:2383
+msgid "E142: File not written: Writing is disabled by 'write' option"
+msgstr "E142: ÀÉ®×¥¼¼g¤J¡A¦]¬° 'write' ¿ï¶µ³QÃö³¬"
+
+#: ex_cmds.c:2403
+#, c-format
+msgid ""
+"'readonly' option is set for \"%.*s\".\n"
+"Do you wish to write anyway?"
+msgstr ""
+"\"%.*s\" ¤w³]©w 'readonly' ¿ï¶µ.\n"
+"½T©w­nÂмg¶Ü¡H"
+
+#: ex_cmds.c:2568
+msgid "Edit File"
+msgstr "½s¿èÀÉ®×"
+
+#: ex_cmds.c:3137
+#, c-format
+msgid "E143: Autocommands unexpectedly deleted new buffer %s"
+msgstr "E143: Autocommands ·N¥~¦a§R°£·s½w½Ä°Ï %s"
+
+#: ex_cmds.c:3269
+msgid "E144: non-numeric argument to :z"
+msgstr "E144: :z ¤£±µ¨ü«D¼Æ¦rªº°Ñ¼Æ"
+
+#: ex_cmds.c:3354
+msgid "E145: Shell commands not allowed in rvim"
+msgstr "E145: rvim ¤¤¸T¤î¨Ï¥Î shell ©R¥O"
+
+#: ex_cmds.c:3461
+msgid "E146: Regular expressions can't be delimited by letters"
+msgstr "E146: Regular expression µLªk¥Î¦r¥À¤À¹j (?)"
+
+#: ex_cmds.c:3807
+#, c-format
+msgid "replace with %s (y/n/a/q/l/^E/^Y)?"
+msgstr "¨ú¥N¬° %s (y/n/a/q/^E/^Y)?"
+
+#: ex_cmds.c:4172
+msgid "(Interrupted) "
+msgstr "(¤w¤¤Â_) "
+
+#: ex_cmds.c:4176
+msgid "1 substitution"
+msgstr "¨ú¥N¤@²Õ"
+
+#: ex_cmds.c:4178
+#, c-format
+msgid "%ld substitutions"
+msgstr "¨ú¥N %ld ²Õ"
+
+#: ex_cmds.c:4181
+msgid " on 1 line"
+msgstr " ¤@¦æ¤¤"
+
+#: ex_cmds.c:4183
+#, c-format
+msgid " on %ld lines"
+msgstr " %ld ¦æ¤¤"
+
+#: ex_cmds.c:4234
+msgid "E147: Cannot do :global recursive"
+msgstr "E147: :global µLªk»¼°j°õ¦æ"
+
+#: ex_cmds.c:4269
+msgid "E148: Regular expression missing from global"
+msgstr "E148: ¨S¦³¨Ï¥Î¹L Regular expression (?)"
+
+#: ex_cmds.c:4318
+#, c-format
+msgid "Pattern found in every line: %s"
+msgstr "¨C¤@¦æ³£§ä¤£¨ì: %s"
+
+#: ex_cmds.c:4399
+msgid ""
+"\n"
+"# Last Substitute String:\n"
+"$"
+msgstr ""
+"\n"
+"# «e¤@²Õ´À¥N¦r¦ê:\n"
+"$"
+
+#: ex_cmds.c:4503
+#, c-format
+msgid "E149: Sorry, no help for %s"
+msgstr "E149: ©êºp, ¨S¦³ %s ªº»¡©ú"
+
+#: ex_cmds.c:4537
+#, c-format
+msgid "Sorry, help file \"%s\" not found"
+msgstr "©êºp, §ä¤£¨ì»¡©úÀÉ \"%s\""
+
+#: ex_cmds.c:5012
+#, c-format
+msgid "E150: Not a directory: %s"
+msgstr "E150: %s ¤£¬O¥Ø¿ý"
+
+#: ex_cmds.c:5040
+#, c-format
+msgid "E152: Cannot open %s for writing"
+msgstr "E152: µLªk¥H¼g¤J¼Ò¦¡¶}±Ò \"%s\""
+
+#: ex_cmds.c:5075
+#, c-format
+msgid "E153: Unable to open %s for reading"
+msgstr "E153: µLªkŪ¨úÀÉ®×: %s"
+
+#: ex_cmds.c:5154
+#, c-format
+msgid "E154: Duplicate tag \"%s\" in file %s"
+msgstr "E154: ¼ÐÅÒ(tag) \"%s\" ¦bÀÉ®× %s ¸Ì­«½Æ¥X²{¦h¦¸"
+
+#: ex_cmds.c:5261
+#, c-format
+msgid "E160: Unknown sign command: %s"
+msgstr "E160: ¥¼©w¸qªº sign command: %s"
+
+#: ex_cmds.c:5281
+msgid "E156: Missing sign name"
+msgstr "E156: ¯Ê¤Ö sign ¦WºÙ"
+
+#: ex_cmds.c:5327
+msgid "E612: Too many signs defined"
+msgstr "E612: ¤w©w¸q¤Ó¦h signs"
+
+#: ex_cmds.c:5394
+#, c-format
+msgid "E239: Invalid sign text: %s"
+msgstr "E239: ¤£¥¿½Tªº sign ¤å¦r: %s"
+
+#: ex_cmds.c:5425 ex_cmds.c:5611
+#, c-format
+msgid "E155: Unknown sign: %s"
+msgstr "E155: ¤£¥¿½Tªº sign: %s"
+
+#: ex_cmds.c:5471
+msgid "E159: Missing sign number"
+msgstr "E159: ¯Ê¤Ö sign number"
+
+#: ex_cmds.c:5551
+#, c-format
+msgid "E158: Invalid buffer name: %s"
+msgstr "E158: ½w½Ä°Ï¦WºÙ¿ù»~: %s"
+
+#: ex_cmds.c:5590
+#, c-format
+msgid "E157: Invalid sign ID: %ld"
+msgstr "E157: Sign ID ¿ù»~: %ld"
+
+#: ex_cmds.c:5761
+msgid "[Deleted]"
+msgstr "[¤w§R°£]"
+
+#: ex_cmds2.c:82
+msgid "Entering Debug mode. Type \"cont\" to continue."
+msgstr "¶i¤J°£¿ù¼Ò¦¡. ¿é¤J \"cont\" ¥H¦^¨ì¥¿±`¼Ò¦¡."
+
+#: ex_cmds2.c:86 ex_docmd.c:850
+#, c-format
+msgid "line %ld: %s"
+msgstr "¦æ %ld: %s"
+
+#: ex_cmds2.c:88
+#, c-format
+msgid "cmd: %s"
+msgstr "cmd: %s"
+
+#: ex_cmds2.c:271
+#, c-format
+msgid "Breakpoint in \"%s%s\" line %ld"
+msgstr "\"%s%s\" ¤¤Â_ÂI: ²Ä %ld ¦æ"
+
+#: ex_cmds2.c:521
+#, c-format
+msgid "E161: Breakpoint not found: %s"
+msgstr "E161: §ä¤£¨ì¤¤Â_ÂI: %s"
+
+#: ex_cmds2.c:547
+msgid "No breakpoints defined"
+msgstr "¨S¦³©w¸q¤¤Â_ÂI"
+
+#: ex_cmds2.c:552
+#, c-format
+msgid "%3d %s %s line %ld"
+msgstr "%3d %s %s ²Ä %ld ¦æ"
+
+#: ex_cmds2.c:767
+#, c-format
+msgid "Save changes to \"%.*s\"?"
+msgstr "±NÅܰʦsÀx¦Ü \"%.*s\"?"
+
+#: ex_cmds2.c:769 ex_docmd.c:8820
+msgid "Untitled"
+msgstr "¥¼©R¦W"
+
+#: ex_cmds2.c:905
+#, c-format
+msgid "E162: No write since last change for buffer \"%s\""
+msgstr "E162: ¤w§ó§ï¹L½w½Ä°Ï \"%s\" ¦ý©|¥¼¦sÀÉ (¥i¥Î ! ±j¨î°õ¦æ)"
+
+#: ex_cmds2.c:974
+msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
+msgstr "ª`·N: ¤w¤Á´«¨ì¨ä¥¦½w½Ä°Ï (½ÐÀˬd Autocommands ¦³µL¿ù»~)"
+
+#: ex_cmds2.c:1377
+msgid "E163: There is only one file to edit"
+msgstr "E163: ¥u¦³¤@­ÓÀÉ®×¥i½s¿è"
+
+#: ex_cmds2.c:1379
+msgid "E164: Cannot go before first file"
+msgstr "E164: ¤w¸g¦b²Ä¤@­ÓÀɮפF"
+
+#: ex_cmds2.c:1381
+msgid "E165: Cannot go beyond last file"
+msgstr "E165: ¤w¸g¦b³Ì«á¤@­ÓÀɮפF"
+
+#: ex_cmds2.c:1828
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "·j´M¤¤: \"%s\" -- \"%s\""
+
+#: ex_cmds2.c:1850
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "·j´M¤¤: \"%s\""
+
+#: ex_cmds2.c:1871
+#, c-format
+msgid "not found in 'runtimepath': \"%s\""
+msgstr "¦b 'runtimepath' ¸Ì§ä¤£¨ì \"%s\""
+
+#: ex_cmds2.c:1905
+msgid "Source Vim script"
+msgstr "°õ¦æ Vim script"
+
+#: ex_cmds2.c:2056
+#, c-format
+msgid "Cannot source a directory: \"%s\""
+msgstr "µLªk°õ¦æ¥Ø¿ý¡G \"%s\""
+
+#: ex_cmds2.c:2086
+#, c-format
+msgid "could not source \"%s\""
+msgstr "µLªk°õ¦æ \"%s\""
+
+#: ex_cmds2.c:2088
+#, c-format
+msgid "line %ld: could not source \"%s\""
+msgstr "²Ä %ld ¦æ: µLªk°õ¦æ \"%s\""
+
+#: ex_cmds2.c:2102
+#, c-format
+msgid "sourcing \"%s\""
+msgstr "°õ¦æ \"%s\" ¤¤"
+
+#: ex_cmds2.c:2104
+#, c-format
+msgid "line %ld: sourcing \"%s\""
+msgstr "²Ä %ld ¦æ: µ²§ô°õ¦æ %s"
+
+#: ex_cmds2.c:2229
+#, c-format
+msgid "finished sourcing %s"
+msgstr "µ²§ô°õ¦æ %s"
+
+#: ex_cmds2.c:2528
+msgid "W15: Warning: Wrong line separator, ^M may be missing"
+msgstr "W15: ª`·N: ¿ù»~ªº¦æ¤À¹j¦r¤¸¡A¥i¯à¬O¤Ö¤F ^M"
+
+#: ex_cmds2.c:2577
+msgid "E167: :scriptencoding used outside of a sourced file"
+msgstr "E167: ¦b°õ¦æ script ÀÉ®×¥~¤£¥i¨Ï¥Î :scriptencoding"
+
+#: ex_cmds2.c:2610
+msgid "E168: :finish used outside of a sourced file"
+msgstr "E168: ¦b°õ¦æ script ÀÉ®×¥~¤£¥i¨Ï¥Î :finish"
+
+#: ex_cmds2.c:3004
+#, c-format
+msgid "Page %d"
+msgstr "²Ä %d ­¶"
+
+#: ex_cmds2.c:3116
+msgid "No text to be printed"
+msgstr "¨S¦³­n¦C¦Lªº¤å¦r"
+
+#: ex_cmds2.c:3194
+#, c-format
+msgid "Printing page %d (%d%%)"
+msgstr "¦C¦L¤¤: ²Ä %d ­¶ (%d%%)"
+
+#: ex_cmds2.c:3203
+#, c-format
+msgid " Copy %d of %d"
+msgstr "½Æ»s %d / %d"
+
+#: ex_cmds2.c:3255
+#, c-format
+msgid "Printed: %s"
+msgstr "¤w¦C¦L: %s"
+
+#: ex_cmds2.c:3262
+msgid "Printing aborted"
+msgstr "¤w¨ú®ø¦C¦L"
+
+#: ex_cmds2.c:3645
+msgid "E455: Error writing to PostScript output file"
+msgstr "E455: µLªk¼g¤J PostScript ¿é¥XÀÉ"
+
+#: ex_cmds2.c:4320
+msgid "E324: Can't open PostScript output file"
+msgstr "E324: µLªk¶}±Ò PostScript ¿é¥XÀÉ"
+
+#: ex_cmds2.c:4362
+#, c-format
+msgid "E456: Can't open file \"%s\""
+msgstr "E456: µLªk¶}±ÒÀÉ®× \"%s\""
+
+#: ex_cmds2.c:4373
+#, c-format
+msgid "E457: Can't read PostScript resource file \"%s\""
+msgstr "E457: µLªkŪ¨ú PostScript resource ÀÉ \"%s\""
+
+#: ex_cmds2.c:4576
+msgid "Sending to printer..."
+msgstr "¶Ç°e¸ê®Æ¨ì¦Lªí¾÷..."
+
+#: ex_cmds2.c:4580
+msgid "E365: Failed to print PostScript file"
+msgstr "E365: µLªk¦C¦L PostScript ÀÉ®×"
+
+#: ex_cmds2.c:4582
+msgid "Print job sent."
+msgstr "¤w°e¥X¦C¦L¤u§@¡C"
+
+#: ex_cmds2.c:4978
+#, c-format
+msgid "Current %slanguage: \"%s\""
+msgstr "¥Ø«eªº %s»y¨¥: \"%s\""
+
+#: ex_cmds2.c:4989
+#, c-format
+msgid "E197: Cannot set language to \"%s\""
+msgstr "E197: ¤£¯à³]©w»y¨¥¦¨ \"%s\""
+
+#: ex_docmd.c:486
+msgid "Entering Ex mode. Type \"visual\" to go to Normal mode."
+msgstr "¶i¤J Ex ¼Ò¦¡. ¿é¤J \"visua\" ¥H¦^¨ì¥¿±`¼Ò¦¡."
+
+#. must be at EOF
+#: ex_docmd.c:522
+msgid "E501: At end-of-file"
+msgstr "E501: ¤w¨ìÀÉ®×µ²§À"
+
+#: ex_docmd.c:624
+msgid "E169: Command too recursive"
+msgstr "E169: ©R¥O»¼°j¼h¼Æ¹L¦h"
+
+#: ex_docmd.c:1090
+#, c-format
+msgid "E605: Exception not caught: %s"
+msgstr "E605: ¥¼ÄdºIªº¨Ò¥~¡G %s"
+
+#: ex_docmd.c:1176
+msgid "End of sourced file"
+msgstr "©R¥OÀɵ²§ô"
+
+#: ex_docmd.c:1177
+msgid "End of function"
+msgstr "¨ç¦¡µ²§À"
+
+#: ex_docmd.c:1628
+msgid "E464: Ambiguous use of user-defined command"
+msgstr "E464: ¨Ï¥ÎªÌ©w¸qªº©R¥O·|²V²c"
+
+#: ex_docmd.c:1642
+msgid "E492: Not an editor command"
+msgstr "E492: ¤£¬O½s¿è¾¹ªº©R¥O"
+
+#: ex_docmd.c:1725
+msgid "E478: Don't panic!"
+msgstr "E478: ¤£­nÅå·W!"
+
+#: ex_docmd.c:1744
+msgid "E493: Backwards range given"
+msgstr "E493: «ü©w¤F¦V«e°Ñ¦Òªº½d³ò"
+
+#: ex_docmd.c:1753
+msgid "Backwards range given, OK to swap"
+msgstr "«ü©w¤F¦V«e°Ñ¦Òªº½d³ò¡AOK to swap"
+
+#: ex_docmd.c:1864
+msgid "E494: Use w or w>>"
+msgstr "E494: ½Ð¨Ï¥Î w ©Î w>>"
+
+#: ex_docmd.c:3446
+msgid "E319: Sorry, the command is not available in this version"
+msgstr "E319: ©êºp, ¥»©R¥O¦b¦¹ª©¥»¤¤¨S¦³¹ê§@"
+
+#: ex_docmd.c:3624
+msgid "E172: Only one file name allowed"
+msgstr "E172: ¥u¯à¦³¤@­ÓÀÉ"
+
+#: ex_docmd.c:4191
+#, c-format
+msgid "%d more files to edit. Quit anyway?"
+msgstr "ÁÙ¦³ %d ­ÓÀÉ®×¥¼½s¿è. ½T©w­nÂ÷¶}¡H"
+
+#: ex_docmd.c:4198
+#, c-format
+msgid "E173: %ld more files to edit"
+msgstr "E173: ÁÙ¦³ %ld ­ÓÀÉ®×¥¼½s¿è"
+
+#: ex_docmd.c:4292
+msgid "E174: Command already exists: add ! to replace it"
+msgstr "E174: ©R¥O¤w¸g¦s¦b, ½Ð¨Ï¥Î ! ±j¨î­«·s©w¸q"
+
+#: ex_docmd.c:4397
+msgid ""
+"\n"
+" Name Args Range Complete Definition"
+msgstr ""
+"\n"
+" ¦WºÙ °Ñ¼Æ ½d³ò §¹¾ã ©w¸q "
+
+#: ex_docmd.c:4486
+msgid "No user-defined commands found"
+msgstr "§ä¤£¨ì¨Ï¥ÎªÌ©w¸qªº©R¥O"
+
+#: ex_docmd.c:4517
+msgid "E175: No attribute specified"
+msgstr "E175: ¨S¦³«ü©wªºÄÝ©Ê"
+
+#: ex_docmd.c:4569
+msgid "E176: Invalid number of arguments"
+msgstr "E176: ¤£¥¿½Tªº°Ñ¼Æ¼Æ¥Ø"
+
+#: ex_docmd.c:4584
+msgid "E177: Count cannot be specified twice"
+msgstr "E177: ¤£¯à«ü©w¨â¦¸¼Æ¥Ø"
+
+#: ex_docmd.c:4594
+msgid "E178: Invalid default value for count"
+msgstr "E178: ¼Æ¥Øªº¹w³]°Ñ¼Æ¤£¥¿½T"
+
+#: ex_docmd.c:4622
+msgid "E179: argument required for complete"
+msgstr "E179: «ü¥O»Ý­n°Ñ¼Æ¤~¯à§¹¦¨"
+
+#: ex_docmd.c:4641
+#, c-format
+msgid "E180: Invalid complete value: %s"
+msgstr "E180: ¤£§¹¾ãªº­È: '%s'"
+
+#: ex_docmd.c:4649
+#, c-format
+msgid "E181: Invalid attribute: %s"
+msgstr "E181: ¤£¥¿½TªºÄÝ©Ê: %s"
+
+#: ex_docmd.c:4690
+msgid "E182: Invalid command name"
+msgstr "E182: «ü¥O¦WºÙ¤£¥¿½T"
+
+#: ex_docmd.c:4705
+msgid "E183: User defined commands must start with an uppercase letter"
+msgstr "E183: ¨Ï¥ÎªÌ¦Û©w«ü¥O¥²¶·¥H¤j¼g¦r¥À¶}©l"
+
+#: ex_docmd.c:4774
+#, c-format
+msgid "E184: No such user-defined command: %s"
+msgstr "E184: ¨S¦³¨Ï¥ÎªÌ¦Û©wªº©R¥O¡G %s"
+
+#: ex_docmd.c:5230
+#, c-format
+msgid "E185: Cannot find color scheme %s"
+msgstr "E185: §ä¤£¨ìÃC¦â¼Ë¦¡ %s"
+
+#: ex_docmd.c:5238
+msgid "Greetings, Vim user!"
+msgstr "¶Ù, Vim ¨Ï¥ÎªÌ¡I"
+
+#: ex_docmd.c:5946
+msgid "Edit File in new window"
+msgstr "¦b·sµøµ¡½s¿èÀÉ®×"
+
+#: ex_docmd.c:6219
+msgid "No swap file"
+msgstr "µL¼È¦sÀÉ"
+
+#: ex_docmd.c:6323
+msgid "Append File"
+msgstr "ªþ¥[ÀÉ®×"
+
+#: ex_docmd.c:6387
+msgid "E186: No previous directory"
+msgstr "E186: ¨S¦³«e¤@­Ó¥Ø¿ý"
+
+#: ex_docmd.c:6469
+msgid "E187: Unknown"
+msgstr "E187: µLªk¿ìÃѪº¼Ð°O"
+
+#: ex_docmd.c:6554
+msgid "E465: :winsize requires two number arguments"
+msgstr "E465: :winsize »Ý­n¨â­Ó°Ñ¼Æ"
+
+#: ex_docmd.c:6605
+#, c-format
+msgid "Window position: X %d, Y %d"
+msgstr "µøµ¡¦ì¸m: X %d, Y %d"
+
+#: ex_docmd.c:6610
+msgid "E188: Obtaining window position not implemented for this platform"
+msgstr "E188: ¦b±zªº¥­¥x¤WµLªkÀò±oµøµ¡¦ì¸m"
+
+#: ex_docmd.c:6620
+msgid "E466: :winpos requires two number arguments"
+msgstr "E466: :winpos »Ý­n¨â­Ó°Ñ¼Æ"
+
+#: ex_docmd.c:6899
+msgid "Save Redirection"
+msgstr "Àx¦s Redirection"
+
+#: ex_docmd.c:7046
+msgid "Save View"
+msgstr "Àx¦s View"
+
+#: ex_docmd.c:7047
+msgid "Save Session"
+msgstr "Àx¦s Session"
+
+#: ex_docmd.c:7049
+msgid "Save Setup"
+msgstr "Àx¦s³]©w"
+
+#: ex_docmd.c:7200
+#, c-format
+msgid "E189: \"%s\" exists (add ! to override)"
+msgstr "E189: \"%s\" ¤w¦s¦b (½Ð¥Î ! ±j¨î°õ¦æ)"
+
+#: ex_docmd.c:7205
+#, c-format
+msgid "E190: Cannot open \"%s\" for writing"
+msgstr "E190: µLªk¥H¼g¤J¼Ò¦¡¶}±Ò \"%s\""
+
+#. set mark
+#: ex_docmd.c:7229
+msgid "E191: Argument must be a letter or forward/backward quote"
+msgstr "E191: °Ñ¼Æ¥²¶·¬O­^¤å¦r¥À©Î¦V«e/«áªº¤Þ¸¹"
+
+#: ex_docmd.c:7271
+msgid "E192: Recursive use of :normal too deep"
+msgstr "E192: :normal »¼°j¼h¼Æ¹L²`"
+
+#: ex_docmd.c:7772
+msgid "E194: No alternate file name to substitute for '#'"
+msgstr "E194: ¨S¦³ '#' ¥i´À¥NªºÀɦW"
+
+#: ex_docmd.c:7803
+msgid "E495: no autocommand file name to substitute for \"<afile>\""
+msgstr "E495: ¨S¦³ Autocommand ÀɦW¥H¨ú¥N \"<afile>\""
+
+#: ex_docmd.c:7811
+msgid "E496: no autocommand buffer number to substitute for \"<abuf>\""
+msgstr "E496: ¨S¦³ Autocommand ½w½Ä°Ï¦WºÙ¥H¨ú¥N \"<abuf>\""
+
+#: ex_docmd.c:7822
+msgid "E497: no autocommand match name to substitute for \"<amatch>\""
+msgstr "E497: ¨S¦³ Autocommand ²Å¦X¦WºÙ¥H¨ú¥N \"<amatch>\""
+
+#: ex_docmd.c:7832
+msgid "E498: no :source file name to substitute for \"<sfile>\""
+msgstr "E498: ¨S¦³ :source ÀɦW¥H¨ú¥N \"<sfile>\""
+
+#: ex_docmd.c:7873
+#, no-c-format
+msgid "E499: Empty file name for '%' or '#', only works with \":p:h\""
+msgstr "E499: '%' ©Î '#' «ü¦VªÅÀɦW¡A¥u¯à¥Î©ó \":p:h\""
+
+#: ex_docmd.c:7875
+msgid "E500: Evaluates to an empty string"
+msgstr "E500: ¿é¤J¬°ªÅ¦r¦ê"
+
+#: ex_docmd.c:8802
+msgid "E195: Cannot open viminfo file for reading"
+msgstr "E195: µLªkŪ¨ú viminfo"
+
+#: ex_docmd.c:8975
+msgid "E196: No digraphs in this version"
+msgstr "E196: ¥»ª©¥»µL½Æ¦X¦r¤¸(digraph)"
+
+#: ex_eval.c:407
+msgid "E608: Cannot :throw exceptions with 'Vim' prefix"
+msgstr "E608: ¤£¯à :throw ¥Î 'Vim' ¶}ÀYªº¨Ò¥~"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:488
+#, c-format
+msgid "Exception thrown: %s"
+msgstr "¥á¥X¨Ò¥~¡G %s"
+
+#: ex_eval.c:530
+#, c-format
+msgid "Exception finished: %s"
+msgstr "¨Ò¥~µ²§ô¡G %s"
+
+#: ex_eval.c:531
+#, c-format
+msgid "Exception discarded: %s"
+msgstr "¤w¥á±ó¨Ò¥~¡G %s"
+
+#: ex_eval.c:582 ex_eval.c:620
+#, c-format
+msgid "%s, line %ld"
+msgstr "%s, ¦æ %ld"
+
+#. always scroll up, don't overwrite
+#: ex_eval.c:596
+#, c-format
+msgid "Exception caught: %s"
+msgstr "µo¥Í¨Ò¥~¡G%s"
+
+#: ex_eval.c:667
+#, c-format
+msgid "%s made pending"
+msgstr "%s ³y¦¨ pending"
+
+#: ex_eval.c:670
+#, c-format
+msgid "%s resumed"
+msgstr "%s ¤w¦^´_"
+
+#: ex_eval.c:674
+#, c-format
+msgid "%s discarded"
+msgstr "%s ¤w¥á±ó"
+
+#: ex_eval.c:700
+msgid "Exception"
+msgstr "¨Ò¥~"
+
+#: ex_eval.c:706
+msgid "Error and interrupt"
+msgstr "¿ù»~»P¤¤Â_"
+
+#: ex_eval.c:708 gui.c:4237
+msgid "Error"
+msgstr "¿ù»~"
+
+#. if (pending & CSTP_INTERRUPT)
+#: ex_eval.c:710
+msgid "Interrupt"
+msgstr "¤¤Â_"
+
+#: ex_eval.c:779
+msgid "E579: :if nesting too deep"
+msgstr "E579: :if ¼h¼Æ¹L²`"
+
+#: ex_eval.c:816
+msgid "E580: :endif without :if"
+msgstr "E580: :endif ¯Ê¤Ö¹ïÀ³ªº :if"
+
+#: ex_eval.c:860
+msgid "E581: :else without :if"
+msgstr "E581: :else ¯Ê¤Ö¹ïÀ³ªº :if"
+
+#: ex_eval.c:863
+msgid "E582: :elseif without :if"
+msgstr "E582: :elseif ¯Ê¤Ö¹ïÀ³ªº :if"
+
+#: ex_eval.c:870
+msgid "E583: multiple :else"
+msgstr "E583: ¦h­« :else"
+
+#: ex_eval.c:873
+msgid "E584: :elseif after :else"
+msgstr "E584: :elseif ¦b :else ¤§«á"
+
+#: ex_eval.c:940
+msgid "E585: :while nesting too deep"
+msgstr "E585: :while ¼h¼Æ¹L²`"
+
+#: ex_eval.c:996
+msgid "E586: :continue without :while"
+msgstr "E586: :continue ¯Ê¤Ö¹ïÀ³ªº :while"
+
+#: ex_eval.c:1036
+msgid "E587: :break without :while"
+msgstr "E587: :break ¯Ê¤Ö¹ïÀ³ªº :while"
+
+#: ex_eval.c:1235
+msgid "E601: :try nesting too deep"
+msgstr "E601: :if ¼h¼Æ¹L²`"
+
+#: ex_eval.c:1278
+msgid "E603: :catch without :try"
+msgstr "E603: :catch ¨S¦³ :try"
+
+#. Give up for a ":catch" after ":finally" and ignore it.
+#. * Just parse.
+#: ex_eval.c:1300
+msgid "E604: :catch after :finally"
+msgstr "E604: :catch ¦b :finally ¤§«á"
+
+#: ex_eval.c:1418
+msgid "E606: :finally without :try"
+msgstr "E606: :finally ¨S¦³ :try"
+
+#. Give up for a multiple ":finally" and ignore it.
+#: ex_eval.c:1442
+msgid "E607: multiple :finally"
+msgstr "E607: ¦h­« :finally"
+
+#: ex_eval.c:1551
+msgid "E602: :endtry without :try"
+msgstr "E602: :endif ¯Ê¤Ö¹ïÀ³ªº :if"
+
+#: ex_eval.c:1857
+msgid "E193: :endfunction not inside a function"
+msgstr "E193: :endfunction ¥²¶·¦b¨ç¦¡¤º³¡¨Ï¥Î"
+
+#: ex_getln.c:2967
+msgid "tagname"
+msgstr "¼ÐÅÒ¦WºÙ"
+
+#: ex_getln.c:2970
+msgid " kind file\n"
+msgstr "ÃþÀÉ®×\n"
+
+#: ex_getln.c:4176
+msgid "'history' option is zero"
+msgstr "¿ï¶µ 'history' ¬O¹s"
+
+#: ex_getln.c:4416
+#, c-format
+msgid ""
+"\n"
+"# %s History (newest to oldest):\n"
+msgstr ""
+"\n"
+"# %s ¾ú¥v°O¿ý (·s¨ìÂÂ):\n"
+
+#: ex_getln.c:4417
+msgid "Command Line"
+msgstr "©R¥O¦C"
+
+#: ex_getln.c:4418
+msgid "Search String"
+msgstr "·j´M¦r¦ê"
+
+#: ex_getln.c:4419
+msgid "Expression"
+msgstr "¹Bºâ¦¡"
+
+#: ex_getln.c:4420
+msgid "Input Line"
+msgstr "¿é¤J¦æ"
+
+#: ex_getln.c:4450
+msgid "E198: cmd_pchar beyond the command length"
+msgstr "E198: cmd_pchar ¶W¹L©R¥Oªø«×"
+
+#: ex_getln.c:4624
+msgid "E199: Active window or buffer deleted"
+msgstr "E199: ¤w§R°£±¼§@¥Î¤¤ªºµøµ¡©Î¼È¦s°Ï"
+
+#: fileio.c:373
+msgid "Illegal file name"
+msgstr "¤£¥¿½TªºÀɦW"
+
+#: fileio.c:397 fileio.c:522 fileio.c:2686 fileio.c:2727
+msgid "is a directory"
+msgstr "¬O¥Ø¿ý"
+
+#: fileio.c:399
+msgid "is not a file"
+msgstr "¤£¬OÀÉ®×"
+
+#: fileio.c:544 fileio.c:3833
+msgid "[New File]"
+msgstr "[¥¼©R¦W]"
+
+#: fileio.c:566
+msgid "[Permission Denied]"
+msgstr "[Åv­­¤£¨¬]"
+
+#: fileio.c:670
+msgid "E200: *ReadPre autocommands made the file unreadable"
+msgstr "E200: *ReadPre Autocommand ¨Ïµ{¦¡µLªkŪ¨ú¦¹ÀÉ"
+
+#: fileio.c:672
+msgid "E201: *ReadPre autocommands must not change current buffer"
+msgstr "E201: *Filter* Autocommand ¤£¥i¥H§ó§ï½w½Ä°Ïªº¤º®e"
+
+#: fileio.c:693
+msgid "Vim: Reading from stdin...\n"
+msgstr "Vim: ±q¼Ð·Ç¿é¤JŪ¨ú...\n"
+
+#: fileio.c:699
+msgid "Reading from stdin..."
+msgstr "±q¼Ð·Ç¿é¤JŪ¨ú..."
+
+#. Re-opening the original file failed!
+#: fileio.c:944
+msgid "E202: Conversion made file unreadable!"
+msgstr "E202: Âà´«¿ù»~"
+
+#: fileio.c:1892
+msgid "[fifo/socket]"
+msgstr "[fifo/socket]"
+
+#: fileio.c:1899
+msgid "[fifo]"
+msgstr "[fifo]"
+
+#: fileio.c:1906
+msgid "[socket]"
+msgstr "[socket]"
+
+#: fileio.c:1914
+msgid "[RO]"
+msgstr "[°ßŪ]"
+
+#: fileio.c:1924
+msgid "[CR missing]"
+msgstr "[¯Ê¤ÖCR]'"
+
+#: fileio.c:1929
+msgid "[NL found]"
+msgstr "[§ä¨ìNL]"
+
+#: fileio.c:1934
+msgid "[long lines split]"
+msgstr "[¤À³Î¹Lªø¦æ]"
+
+#: fileio.c:1940 fileio.c:3817
+msgid "[NOT converted]"
+msgstr "[¥¼Âà´«]"
+
+#: fileio.c:1945 fileio.c:3822
+msgid "[converted]"
+msgstr "[¤wÂà´«]"
+
+#: fileio.c:1952 fileio.c:3847
+msgid "[crypted]"
+msgstr "[¤w¥[±K]"
+
+#: fileio.c:1959
+msgid "[CONVERSION ERROR]"
+msgstr "Âà´«¿ù»~"
+
+#: fileio.c:1965
+#, c-format
+msgid "[ILLEGAL BYTE in line %ld]"
+msgstr "[¦æ %ld ¦³¤£¥¿½Tªº¦ì¤¸]"
+
+#: fileio.c:1972
+msgid "[READ ERRORS]"
+msgstr "[Ū¨ú¿ù»~]"
+
+#: fileio.c:2188
+msgid "Can't find temp file for conversion"
+msgstr "§ä¤£¨ìÂà´«¥Îªº¼È¦sÀÉ"
+
+#: fileio.c:2195
+msgid "Conversion with 'charconvert' failed"
+msgstr "¦r¤¸¶°Âà´«¿ù»~"
+
+#: fileio.c:2198
+msgid "can't read output of 'charconvert'"
+msgstr "µLªkŪ¨ú 'charconvert' ªº¿é¥X"
+
+#: fileio.c:2601
+msgid "E203: Autocommands deleted or unloaded buffer to be written"
+msgstr "E203: Autocommand §R°£©ÎÄÀ©ñ¤F­n¼g¤Jªº½w½Ä°Ï"
+
+#: fileio.c:2624
+msgid "E204: Autocommand changed number of lines in unexpected way"
+msgstr "E204: Autocommand ·N¥~¦a§ïÅܤF¦æ¸¹"
+
+#: fileio.c:2692 fileio.c:2710
+msgid "is not a file or writable device"
+msgstr "¤£¬OÀɮשΥi¼g¤Jªº¸Ë¸m"
+
+#: fileio.c:2762
+msgid "is read-only (add ! to override)"
+msgstr "¬O°ßŪÀÉ (½Ð¨Ï¥Î ! ±j¨î°õ¦æ)"
+
+#: fileio.c:3065
+msgid "E506: Can't write to backup file (add ! to override)"
+msgstr "E506: µLªk¼g¤J³Æ¥÷ÀÉ (½Ð¨Ï¥Î ! ±j¨î°õ¦æ)"
+
+#: fileio.c:3077
+msgid "E507: Close error for backup file (add ! to override)"
+msgstr "E507: µLªkÃö³¬³Æ¥÷ÀÉ (½Ð¨Ï¥Î ! ±j¨î°õ¦æ)"
+
+#: fileio.c:3079
+msgid "E508: Can't read file for backup (add ! to override)"
+msgstr "E508: µLªkŪ¨úÀÉ®×¥H¨Ñ³Æ¥÷ (½Ð¨Ï¥Î ! ±j¨î°õ¦æ)"
+
+#: fileio.c:3095
+msgid "E509: Cannot create backup file (add ! to override)"
+msgstr "E509: µLªk«Ø¥ß³Æ¥÷ÀÉ (½Ð¨Ï¥Î ! ±j¨î°õ¦æ)"
+
+#: fileio.c:3198
+msgid "E510: Can't make backup file (add ! to override)"
+msgstr "E510: µLªk»s§@³Æ¥÷ÀÉ (½Ð¨Ï¥Î ! ±j¨î°õ¦æ)"
+
+#: fileio.c:3260
+msgid "E460: The resource fork would be lost (add ! to override)"
+msgstr "E460: Resource fork ·|®ø¥¢ (½Ð¨Ï¥Î ! ±j¨î°õ¦æ)"
+
+#: fileio.c:3361
+msgid "E214: Can't find temp file for writing"
+msgstr "E214: §ä¤£¨ì¼g¤J¥Îªº¼È¦sÀÉ"
+
+#: fileio.c:3379
+msgid "E213: Cannot convert (add ! to write without conversion)"
+msgstr "E213: µLªkÂà´« (½Ð¨Ï¥Î ! ±j¨î¤£Âà´«¼g¤J)"
+
+#: fileio.c:3414
+msgid "E166: Can't open linked file for writing"
+msgstr "E166: µLªk¥H¼g¤J¼Ò¦¡¶}±Ò³sµ²ÀÉ®×"
+
+#: fileio.c:3418
+msgid "E212: Can't open file for writing"
+msgstr "E212: µLªk¥H¼g¤J¼Ò¦¡¶}±Ò"
+
+#: fileio.c:3668
+msgid "E512: Close failed"
+msgstr "E512: Ãö³¬¥¢±Ñ"
+
+#: fileio.c:3739
+msgid "E513: write error, conversion failed"
+msgstr "E513: µLªk¼g¤J -- Âà´«¥¢±Ñ"
+
+#: fileio.c:3745
+msgid "E514: write error (file system full?)"
+msgstr "E514: ¼g¤J¿ù»~ (Àɮרt²Î¤wº¡¡H)"
+
+#: fileio.c:3812
+msgid " CONVERSION ERROR"
+msgstr "Âà´«¿ù»~"
+
+#: fileio.c:3828
+msgid "[Device]"
+msgstr "[¸Ë¸m]"
+
+#: fileio.c:3833
+msgid "[New]"
+msgstr "[·s]"
+
+#: fileio.c:3855
+msgid " [a]"
+msgstr "[a]"
+
+#: fileio.c:3855
+msgid " appended"
+msgstr " ¤wªþ¥["
+
+#: fileio.c:3857
+msgid " [w]"
+msgstr "[w]"
+
+#: fileio.c:3857
+msgid " written"
+msgstr " ¤w¼g¤J"
+
+#: fileio.c:3910
+msgid "E205: Patchmode: can't save original file"
+msgstr "E205: Patch ¼Ò¦¡: µLªkÀx¦s­ì©lÀÉ®×"
+
+#: fileio.c:3932
+msgid "E206: patchmode: can't touch empty original file"
+msgstr "E206: Patch ¼Ò¦¡: µLªkÅܧóªÅªº­ì©lÀÉ®×"
+
+#: fileio.c:3947
+msgid "E207: Can't delete backup file"
+msgstr "E207: µLªk§R°£³Æ¥÷ÀÉ"
+
+#: fileio.c:4008
+msgid ""
+"\n"
+"WARNING: Original file may be lost or damaged\n"
+msgstr ""
+"\n"
+"ĵ§i: ­ì©lÀɮ׬y¥¢©Î·lÃa\n"
+
+#: fileio.c:4010
+msgid "don't quit the editor until the file is successfully written!"
+msgstr "¦bÀÉ®×¥¿½T¼g¤J«e½Ð¤ÅÂ÷¶}½s¿è¾¹!"
+
+#: fileio.c:4099
+msgid "[dos]"
+msgstr "[dos]"
+
+#: fileio.c:4099
+msgid "[dos format]"
+msgstr "[dos ®æ¦¡]"
+
+#: fileio.c:4106
+msgid "[mac]"
+msgstr "[mac]"
+
+#: fileio.c:4106
+msgid "[mac format]"
+msgstr "[mac ®æ¦¡]"
+
+#: fileio.c:4113
+msgid "[unix]"
+msgstr "[unix]"
+
+#: fileio.c:4113
+msgid "[unix format]"
+msgstr "[unix ®æ¦¡]"
+
+#: fileio.c:4140
+msgid "1 line, "
+msgstr "1 ¦æ, "
+
+#: fileio.c:4142
+#, c-format
+msgid "%ld lines, "
+msgstr "%ld ¦æ, "
+
+#: fileio.c:4145
+msgid "1 character"
+msgstr "¤@­Ó¦r¤¸"
+
+#: fileio.c:4147
+#, c-format
+msgid "%ld characters"
+msgstr "%ld­Ó¦r¤¸"
+
+#: fileio.c:4157
+msgid "[noeol]"
+msgstr "[noeol]"
+
+#: fileio.c:4157
+msgid "[Incomplete last line]"
+msgstr "[µ²§À¦æ¤£§¹¾ã]"
+
+#. don't overwrite messages here
+#. must give this prompt
+#. don't use emsg() here, don't want to flush the buffers
+#: fileio.c:4176
+msgid "WARNING: The file has been changed since reading it!!!"
+msgstr "ĵ§i: ¥»ÀɮצۤW¦¸Åª¤J«á¤wÅÜ°Ê!!!"
+
+#: fileio.c:4178
+msgid "Do you really want to write to it"
+msgstr "½T©w­n¼g¤J¶Ü"
+
+#: fileio.c:5219
+#, c-format
+msgid "E208: Error writing to \"%s\""
+msgstr "E208: ¼g¤JÀÉ®× \"%s\" ¿ù»~"
+
+#: fileio.c:5226
+#, c-format
+msgid "E209: Error closing \"%s\""
+msgstr "E209: Ãö³¬ÀÉ®× \"%s\" ¿ù»~"
+
+#: fileio.c:5229
+#, c-format
+msgid "E210: Error reading \"%s\""
+msgstr "E210: Ū¨úÀÉ®× \"%s\" ¿ù»~"
+
+#: fileio.c:5448
+msgid "E246: FileChangedShell autocommand deleted buffer"
+msgstr "E246: FileChangedShell autocommand §R°£½w½Ä°Ï"
+
+#: fileio.c:5456
+#, c-format
+msgid "E211: Warning: File \"%s\" no longer available"
+msgstr "E211: ĵ§i: ÀÉ®× \"%s\" ¤w¸g¤£¦s¦b"
+
+#: fileio.c:5469
+#, c-format
+msgid ""
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
+msgstr "W12: ĵ§i: ÀÉ®× \"%s\" ¦Û¤W¦¸Åª¤J«á¤wÅÜ°Ê, ¦Ó¥B½s¿è¤¤ªº½w½Ä°Ï¤]§ó°Ê¤F"
+
+#: fileio.c:5472
+#, c-format
+msgid "W11: Warning: File \"%s\" has changed since editing started"
+msgstr "W11: ĵ§i: ÀÉ®× \"%s\" ¦Û¤W¦¸Åª¤J«á¤wÅÜ°Ê"
+
+#: fileio.c:5474
+#, c-format
+msgid "W16: Warning: Mode of file \"%s\" has changed since editing started"
+msgstr "W16: ĵ§i: ÀÉ®× \"%s\" ªºÅv­­»P¤W¦¸Åª¤J®É¤£¤@¼Ë (¦³ÅܰʹL)"
+
+# 'mode' seems better as translated to 'permission'?
+#: fileio.c:5484
+#, c-format
+msgid "W13: Warning: File \"%s\" has been created after editing started"
+msgstr "W13: ĵ§i: ÀÉ®× \"%s\" ¦b¶}©l½s¿è«á¤S³Q«Ø¥ß¤F"
+
+#: fileio.c:5501
+msgid "Warning"
+msgstr "ĵ§i"
+
+#: fileio.c:5502
+msgid ""
+"&OK\n"
+"&Load File"
+msgstr ""
+"½T©w(&O)\n"
+"¸ü¤JÀÉ®×(&L)"
+
+#: fileio.c:5600
+#, c-format
+msgid "E462: Could not prepare for reloading \"%s\""
+msgstr "E462: µLªk·Ç³Æ­«·s¸ü¤J \"%s\""
+
+#: fileio.c:5619
+#, c-format
+msgid "E321: Could not reload \"%s\""
+msgstr "E321: µLªk­«·s¸ü¤J \"%s\""
+
+#: fileio.c:6201
+msgid "--Deleted--"
+msgstr "--¤w§R°£--"
+
+#. the group doesn't exist
+#: fileio.c:6361
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: µL¦¹¸s²Õ: \"%s\""
+
+#: fileio.c:6486
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: * «á­±¦³¤£¥¿½Tªº¦r¤¸: %s"
+
+#: fileio.c:6497
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: µL¦¹¨Æ¥ó: %s"
+
+#. Highlight title
+#: fileio.c:6646
+msgid ""
+"\n"
+"--- Auto-Commands ---"
+msgstr ""
+"\n"
+"--- Auto-Commands ---"
+
+#: fileio.c:6917
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: µLªk¹ï©Ò¦³¨Æ¥ó°õ¦æ autocommand"
+
+#: fileio.c:6940
+msgid "No matching autocommands"
+msgstr "§ä¤£¨ì¹ïÀ³ªº autocommand"
+
+#: fileio.c:7260
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: autocommand ¼h¼Æ¹L²`"
+
+#: fileio.c:7528
+#, c-format
+msgid "%s Auto commands for \"%s\""
+msgstr "%s Auto commands: \"%s\""
+
+#: fileio.c:7536
+#, c-format
+msgid "Executing %s"
+msgstr "°õ¦æ %s"
+
+#. always scroll up, don't overwrite
+#: fileio.c:7604
+#, c-format
+msgid "autocommand %s"
+msgstr "autocommand %s"
+
+#: fileio.c:8171
+msgid "E219: Missing {."
+msgstr "E219: ¯Ê¤Ö {."
+
+#: fileio.c:8173
+msgid "E220: Missing }."
+msgstr "E220: ¯Ê¤Ö }."
+
+#: fold.c:66
+msgid "E490: No fold found"
+msgstr "E490: §ä¤£¨ì¥ô¦ó fold"
+
+#: fold.c:553
+msgid "E350: Cannot create fold with current 'foldmethod'"
+msgstr "E350: µLªk¦b¥Ø«eªº 'foldmethod' ¤U«Ø¥ß fold"
+
+#: fold.c:555
+msgid "E351: Cannot delete fold with current 'foldmethod'"
+msgstr "E351: µLªk¦b¥Ø«eªº 'foldmethod' ¤U§R°£ fold"
+
+#: getchar.c:246
+msgid "E222: Add to read buffer"
+msgstr "E222: ¥[¤JŪ¨ú½w½Ä°Ï¤¤"
+
+#: getchar.c:2146
+msgid "E223: recursive mapping"
+msgstr "E223: »¼°j mapping"
+
+#: getchar.c:2994
+#, c-format
+msgid "E224: global abbreviation already exists for %s"
+msgstr "E224: %s ¤w¸g¦³¥þ°ì abbreviation ¤F"
+
+#: getchar.c:2997
+#, c-format
+msgid "E225: global mapping already exists for %s"
+msgstr "E225: %s ¤w¸g¦³¥þ°ì mapping ¤F"
+
+#: getchar.c:3124
+#, c-format
+msgid "E226: abbreviation already exists for %s"
+msgstr "E226: %s ¤w¸g¦³ abbreviation ¤F"
+
+#: getchar.c:3127
+#, c-format
+msgid "E227: mapping already exists for %s"
+msgstr "E227: %s ªº mapping ¤w¸g¦s¦b"
+
+#: getchar.c:3191
+msgid "No abbreviation found"
+msgstr "§ä¤£¨ì abbreviation"
+
+#: getchar.c:3193
+msgid "No mapping found"
+msgstr "¨S¦³³o­Ó mapping ¹ïÀ³"
+
+#: getchar.c:4083
+msgid "E228: makemap: Illegal mode"
+msgstr "E228: makemap: ¤£¥¿½Tªº¼Ò¦¡"
+
+#: gui.c:218
+msgid "E229: Cannot start the GUI"
+msgstr "E229: µLªk±Ò°Ê¹Ï«¬¬É­±"
+
+#: gui.c:347
+#, c-format
+msgid "E230: Cannot read from \"%s\""
+msgstr "E230: µLªkŪ¨úÀÉ®× \"%s\""
+
+#: gui.c:472
+msgid "E231: 'guifontwide' invalid"
+msgstr "E231: ¤£¥¿½Tªº 'guifontwide'"
+
+#: gui.c:3925
+#, c-format
+msgid "E254: Cannot allocate color %s"
+msgstr "E254: ¤£¯à°t¸mÃC¦â %s"
+
+#: gui_at_fs.c:290
+msgid "<cannot open> "
+msgstr "<¤£¯à¶}±Ò>"
+
+#: gui_at_fs.c:1115
+#, c-format
+msgid "E616: vim_SelFile: can't get font %s"
+msgstr "E616: vim_SelFile: ¤£¯à¨Ï¥Î %s ¦r«¬"
+
+#: gui_at_fs.c:2538
+msgid "E614: vim_SelFile: can't return to current directory"
+msgstr "E614: vim_SelFile: µLªk¦^¨ì¥Ø«e¥Ø¿ý"
+
+#: gui_at_fs.c:2557
+msgid "Pathname:"
+msgstr "¸ô®|:"
+
+#: gui_at_fs.c:2563
+msgid "E615: vim_SelFile: can't get current directory"
+msgstr "E615: vim_SelFile: µLªk¨ú±o¥Ø«e¥Ø¿ý"
+
+#: gui_at_fs.c:2571 gui_motif.c:1619
+msgid "OK"
+msgstr "½T©w"
+
+#: gui_at_fs.c:2571 gui_gtk.c:2625 gui_motif.c:1614 gui_motif.c:2844
+msgid "Cancel"
+msgstr "¨ú®ø"
+
+#: gui_at_sb.c:486
+msgid "Scrollbar Widget: Could not get geometry of thumb pixmap."
+msgstr "±²°Ê¶b: ¤£¯à³]©w thumb pixmap ªº¦ì¸m"
+
+#: gui_athena.c:1956 gui_motif.c:1867
+msgid "Vim dialog"
+msgstr "Vim ¹ï¸Ü²°"
+
+#: gui_beval.c:91
+msgid "E232: Cannot create BalloonEval with both message and callback"
+msgstr "E232: ¤£¯à¹ï°T®§»P callback «Ø¥ß BallonEval"
+
+#: gui_gtk.c:1561
+msgid "Vim dialog..."
+msgstr "Vim ¹ï¸Ü²°..."
+
+#: gui_gtk.c:1992 message.c:2525
+msgid ""
+"&Yes\n"
+"&No\n"
+"&Cancel"
+msgstr ""
+"&Y¬O\n"
+"&N§_\n"
+"&C¨ú®ø"
+
+#: gui_gtk.c:2152
+msgid "Input _Methods"
+msgstr "¿é¤Jªk"
+
+#: gui_gtk.c:2418 gui_motif.c:2763
+msgid "VIM - Search and Replace..."
+msgstr "VIM - ´M§ä»P¨ú¥N..."
+
+#: gui_gtk.c:2426 gui_motif.c:2765
+msgid "VIM - Search..."
+msgstr "VIM - ´M§ä..."
+
+#: gui_gtk.c:2458 gui_motif.c:2883
+msgid "Find what:"
+msgstr "·j´M:"
+
+#: gui_gtk.c:2478 gui_motif.c:2915
+msgid "Replace with:"
+msgstr "¨ú¥N¬°:"
+
+#. whole word only button
+#: gui_gtk.c:2510 gui_motif.c:3031
+msgid "Match whole word only"
+msgstr "¥u·j´M§¹¥þ¬Û¦Pªº¦r"
+
+#. match case button
+#: gui_gtk.c:2523 gui_motif.c:3043
+msgid "Match case"
+msgstr "²Å¦X¤j¤p¼g"
+
+#: gui_gtk.c:2535 gui_motif.c:2985
+msgid "Direction"
+msgstr "¤è¦V"
+
+#. 'Up' and 'Down' buttons
+#: gui_gtk.c:2547 gui_motif.c:2997
+msgid "Up"
+msgstr "¦V¤W"
+
+#: gui_gtk.c:2551 gui_motif.c:3005
+msgid "Down"
+msgstr "¦V¤U"
+
+#: gui_gtk.c:2577 gui_gtk.c:2579 gui_motif.c:2787
+msgid "Find Next"
+msgstr "§ä¤U¤@­Ó"
+
+#: gui_gtk.c:2596 gui_gtk.c:2598 gui_motif.c:2804
+msgid "Replace"
+msgstr "¨ú¥N"
+
+#: gui_gtk.c:2609 gui_gtk.c:2611 gui_motif.c:2817
+msgid "Replace All"
+msgstr "¨ú¥N¥þ³¡"
+
+#: gui_gtk_x11.c:2285
+msgid "Vim: Received \"die\" request from session manager\n"
+msgstr "Vim: ¥Ñ Session ºÞ²z­û¦¬¨ì \"die\" ­n¨D\n"
+
+#: gui_gtk_x11.c:3424
+msgid "Vim: Main window unexpectedly destroyed\n"
+msgstr "Vim: ¥Dµøµ¡Äê±¼\n"
+
+#: gui_gtk_x11.c:4038
+msgid "Font Selection"
+msgstr "¦r«¬¿ï¾Ü"
+
+#: gui_gtk_x11.c:5890 ui.c:2009
+msgid "Used CUT_BUFFER0 instead of empty selection"
+msgstr "¨Ï¥Î CUT_BUFFER0 ¨Ó¨ú¥NªÅ¿ï¾Ü"
+
+#: gui_motif.c:1613 gui_motif.c:1616
+msgid "Filter"
+msgstr "¹LÂo¾¹"
+
+#: gui_motif.c:1615
+msgid "Directories"
+msgstr "¥Ø¿ý"
+
+#: gui_motif.c:1617
+msgid "Help"
+msgstr "»²§U»¡©ú"
+
+#: gui_motif.c:1618
+msgid "Files"
+msgstr "ÀÉ®×"
+
+#: gui_motif.c:1620
+msgid "Selection"
+msgstr "¿ï¾Ü"
+
+#: gui_motif.c:2830
+msgid "Undo"
+msgstr "´_­ì"
+
+#: gui_riscos.c:952
+#, c-format
+msgid "E610: Can't load Zap font '%s'"
+msgstr "E610: µLªk¶}±Ò Zap ¦r«¬ '%s'"
+
+#: gui_riscos.c:1048
+#, c-format
+msgid "E611: Can't use font %s"
+msgstr "E611: µLªk¨Ï¥Î¦r«¬ %s"
+
+#: gui_riscos.c:3269
+msgid ""
+"\n"
+"Sending message to terminate child process.\n"
+msgstr ""
+"\n"
+"°e¥X¤¤Â_¤lµ{¦¡ªº°T®§¤¤.\n"
+
+#: gui_w32.c:759
+#, c-format
+msgid "E243: Argument not supported: \"-%s\"; Use the OLE version."
+msgstr "E243: ¤£¤ä´©°Ñ¼Æ \"-%s\"¡C½Ð¥Î OLE ª©¥»¡C"
+
+#: gui_w48.c:2029
+msgid "Find string (use '\\\\' to find a '\\')"
+msgstr "·j´M¦r¦ê (¨Ï¥Î '\\\\' ¨Óªí¥Ü '\\')"
+
+#: gui_w48.c:2054
+msgid "Find & Replace (use '\\\\' to find a '\\')"
+msgstr "·j´M¤Î¨ú¥N¦r¦ê (¨Ï¥Î '\\\\' ¨Óªí¥Ü '\\')"
+
+#: gui_x11.c:1445
+msgid "Vim E458: Cannot allocate colormap entry, some colors may be incorrect"
+msgstr "Vim E458: µLªk°t¸m color map ¶µ¥Ø¡A¦³¨ÇÃC¦â¬Ý°_¨Ó·|©Ç©Çªº"
+
+#: gui_x11.c:2019
+#, c-format
+msgid "E250: Fonts for the following charsets are missing in fontset %s:"
+msgstr "E250: Fontset %s ¨S¦³³]©w¥¿½Tªº¦r«¬¥H¨ÑÅã¥Ü³o¨Ç¦r¤¸¶°:"
+
+#: gui_x11.c:2062
+#, c-format
+msgid "E252: Fontset name: %s"
+msgstr "E252: ¦r«¬¶°(Fontset)¦WºÙ: %s"
+
+#: gui_x11.c:2063
+#, c-format
+msgid "Font '%s' is not fixed-width"
+msgstr "'%s' ¤£¬O©T©w¼e«×¦r«¬"
+
+#: gui_x11.c:2082
+#, c-format
+msgid "E253: Fontset name: %s\n"
+msgstr "E253: ¦r«¬¶°(Fontset)¦WºÙ: %s\n"
+
+#: gui_x11.c:2083
+#, c-format
+msgid "Font0: %s\n"
+msgstr "Font0: %s\n"
+
+#: gui_x11.c:2084
+#, c-format
+msgid "Font1: %s\n"
+msgstr "Font1: %s\n"
+
+#: gui_x11.c:2085
+#, c-format
+msgid "Font%d width is not twice that of font0\n"
+msgstr "¦r«¬%d¼e«×¤£¬O¦r«¬0ªº¨â­¿\n"
+
+#: gui_x11.c:2086
+#, c-format
+msgid "Font0 width: %ld\n"
+msgstr "¦r«¬0ªº¼e«×¡G%ld\n"
+
+#: gui_x11.c:2087
+#, c-format
+msgid ""
+"Font1 width: %ld\n"
+"\n"
+msgstr ""
+"¦r«¬1¼e«×: %ld\n"
+"\n"
+
+#: hangulin.c:610
+msgid "E256: Hangul automata ERROR"
+msgstr "E256: Hangul automata ¿ù»~"
+
+#: if_cscope.c:26
+#, c-format
+msgid "E560: Usage: cs[cope] %s"
+msgstr "E560: ¥Îªk: cs[cope] %s"
+
+#: if_cscope.c:67
+msgid "Add a new database"
+msgstr "·s¼W¸ê®Æ®w"
+
+#: if_cscope.c:69
+msgid "Query for a pattern"
+msgstr "¿é¤J pattern"
+
+#: if_cscope.c:71
+msgid "Show this message"
+msgstr "Åã¥Ü¦¹°T®§"
+
+#: if_cscope.c:73
+msgid "Kill a connection"
+msgstr "µ²§ô³s½u"
+
+#: if_cscope.c:75
+msgid "Reinit all connections"
+msgstr "­«³]©Ò¦³³s½u"
+
+#: if_cscope.c:77
+msgid "Show connections"
+msgstr "Åã¥Ü³s½u"
+
+#: if_cscope.c:108
+msgid "This cscope command does not support splitting the window.\n"
+msgstr "³o­Ó cscope ©R¥O¤£¤ä´©¤À³Î¿Ã¹õ\n"
+
+#: if_cscope.c:143
+msgid "E562: Usage: cstag <ident>"
+msgstr "E562: ¥Îªk: cstag <ÃѧO¦rident>"
+
+#: if_cscope.c:199
+msgid "E257: cstag: tag not found"
+msgstr "E257: cstag: §ä¤£¨ì tag"
+
+#: if_cscope.c:407 if_cscope.c:451
+#, c-format
+msgid "E563: stat(%s) error: %d"
+msgstr "E563: stat(%s) ¿ù»~: %d"
+
+#: if_cscope.c:461 if_cscope.c:468
+#, c-format
+msgid "Added cscope database %s"
+msgstr "·s¼W cscope ¸ê®Æ®w %s"
+
+#: if_cscope.c:475
+#, c-format
+msgid "E564: %s is not a directory or a valid cscope database"
+msgstr "E564: %s ¤£¬O¥Ø¿ý©Î cscope ¸ê®Æ®w"
+
+#: if_cscope.c:559
+#, c-format
+msgid "E565: error reading cscope connection %d"
+msgstr "E565: Ū¨ú cscope ³s½u %d ¿ù»~"
+
+#: if_cscope.c:636
+msgid "E561: unknown cscope search type"
+msgstr "E561: ¥¼ª¾ªº cscope ·j´M§ÎºA"
+
+#: if_cscope.c:683
+msgid "E566: Could not create cscope pipes"
+msgstr "E566: µLªk«Ø¥ß»P cscope ªº pipe ³s½u"
+
+#: if_cscope.c:748
+msgid "cs_create_connection exec failed"
+msgstr "cs_create_connection °õ¦æ¥¢±Ñ"
+
+#: if_cscope.c:758
+msgid "cs_create_connection: fdopen for to_fp failed"
+msgstr "cs_create_connection: fdopen ¥¢±Ñ (to_fp)"
+
+#: if_cscope.c:760
+msgid "cs_create_connection: fdopen for fr_fp failed"
+msgstr "cs_create_connection: fdopen ¥¢±Ñ (fr_fp)"
+
+#: if_cscope.c:788
+msgid "E567: no cscope connections"
+msgstr "E567: ¨S¦³ cscope ³s½u"
+
+#: if_cscope.c:858
+#, c-format
+msgid "E259: no matches found for cscope query %s of %s"
+msgstr "E259: §ä¤£¨ì²Å¦X cscope ªº·j´M %s / %s"
+
+#: if_cscope.c:902
+msgid "cscope commands:\n"
+msgstr "cscope ©R¥O:\n"
+
+#: if_cscope.c:905
+#, c-format
+msgid "%-5s: %-30s (Usage: %s)\n"
+msgstr "%-5s: %-30s (¥Îªk: %s)\n"
+
+#: if_cscope.c:973
+msgid "E568: duplicate cscope database not added"
+msgstr "E568: ­«½Æªº cscope ¸ê®Æ®w¥¼³Q¥[¤J"
+
+#: if_cscope.c:984
+msgid "E569: maximum number of cscope connections reached"
+msgstr "E569: ¤w¹F¨ì cscope ³Ì¤j³s½u¼Æ¥Ø"
+
+#: if_cscope.c:1105
+msgid "E260: cscope connection not found"
+msgstr "E260: §ä¤£¨ì cscope ³s½u"
+
+#: if_cscope.c:1108
+#, c-format
+msgid "E261: cscope connection %s not found"
+msgstr "E261: §ä¤£¨ì cscope ³s½u %s"
+
+#: if_cscope.c:1144
+msgid "cscope connection closed"
+msgstr "cscope ³s½u¤wÃö³¬"
+
+#: if_cscope.c:1152
+#, c-format
+msgid "cscope connection %s closed\n"
+msgstr "cscope ³s½u %s ¤wÃö³¬\n"
+
+#. should not reach here
+#: if_cscope.c:1293
+msgid "E570: fatal error in cs_manage_matches"
+msgstr "E570: cs_manage_matches ÄY­«¿ù»~"
+
+#: if_cscope.c:1344
+#, c-format
+msgid "E262: error reading cscope connection %d"
+msgstr "E262: Ū¨ú cscope ³s½u %d ¿ù»~"
+
+#: if_cscope.c:1452
+msgid "couldn't malloc\n"
+msgstr "µLªk¨Ï¥Î malloc\n"
+
+#: if_cscope.c:1457
+#, c-format
+msgid "Cscope tag: %s\n"
+msgstr "Cscope ¼ÐÅÒ(tag): %s\n"
+
+#: if_cscope.c:1461
+msgid " # line"
+msgstr " # ¦æ "
+
+#: if_cscope.c:1463
+msgid "filename / context / line\n"
+msgstr "ÀɦW / ¤º¤å / ¦æ¸¹\n"
+
+#: if_cscope.c:1721
+msgid "All cscope databases reset"
+msgstr "­«³]©Ò¦³ cscope ¸ê®Æ®w"
+
+#: if_cscope.c:1788
+msgid "no cscope connections\n"
+msgstr "¨S¦³ cscope ³s½u\n"
+
+#: if_cscope.c:1792
+msgid " # pid database name prepend path\n"
+msgstr " # pid ¸ê®Æ®w¦WºÙ prepend path\n"
+
+#: if_cscope.c:1803
+#, c-format
+msgid "%2d %-5ld %-34s <none>\n"
+msgstr "%2d %-5ld %-34s <µL>\n"
+
+#: if_python.c:394
+msgid ""
+"E263: Sorry, this command is disabled, the Python library could not be "
+"loaded."
+msgstr "E263: ©êºp¡A³o­Ó©R¥OµLªk¨Ï¥Î¡APython µ{¦¡®w¨S¦³¸ü¤J¡C"
+
+#: if_python.c:596
+msgid "can't delete OutputObject attributes"
+msgstr "µLªk§R°£ OutputObject ÄÝ©Ê"
+
+#: if_python.c:603
+msgid "softspace must be an integer"
+msgstr "softspace ¥²»Ý¬O¾ã¼Æ"
+
+#: if_python.c:611
+msgid "invalid attribute"
+msgstr "¤£¥¿½TªºÄÝ©Ê"
+
+#: if_python.c:650 if_python.c:664
+msgid "writelines() requires list of strings"
+msgstr "writelines() »Ý­n string list ·í°Ñ¼Æ"
+
+#: if_python.c:790
+msgid "E264: Python: Error initialising I/O objects"
+msgstr "E264: Python: µLªkªì©l I/O ª«¥ó"
+
+#: if_python.c:975 if_tcl.c:1402
+msgid "invalid expression"
+msgstr "¤£¥¿½Tªº¹Bºâ¦¡"
+
+#: if_python.c:989 if_tcl.c:1407
+msgid "expressions disabled at compile time"
+msgstr "¦]¬°½sĶ®É¨S¦³¥[¤J¹Bºâ¦¡(expression)ªºµ{¦¡½X¡A©Ò¥HµLªk¨Ï¥Î¹Bºâ¦¡"
+
+#: if_python.c:1002
+msgid "attempt to refer to deleted buffer"
+msgstr "¸Õ¹Ï¨Ï¥Î¤w³Q§R°£ªº buffer"
+
+#: if_python.c:1017 if_python.c:1058 if_python.c:1122 if_tcl.c:1214
+msgid "line number out of range"
+msgstr "¦æ¸¹¶W¥X½d³ò"
+
+#: if_python.c:1257
+#, c-format
+msgid "<buffer object (deleted) at %8lX>"
+msgstr "<buffer ª«¥ó (¤w§R°£): %8lX>"
+
+#: if_python.c:1348 if_tcl.c:836
+msgid "invalid mark name"
+msgstr "¼Ð°O¦WºÙ¤£¥¿½T"
+
+#: if_python.c:1623
+msgid "no such buffer"
+msgstr "µL¦¹ buffer"
+
+#: if_python.c:1711
+msgid "attempt to refer to deleted window"
+msgstr "¸Õ¹Ï¨Ï¥Î¤w³Q§R°£ªºµøµ¡"
+
+#: if_python.c:1756
+msgid "readonly attribute"
+msgstr "°ßŪÄÝ©Ê"
+
+#: if_python.c:1769
+msgid "cursor position outside buffer"
+msgstr "´å¼Ð©w¦ì¦b½w½Ä°Ï¤§¥~"
+
+#: if_python.c:1846
+#, c-format
+msgid "<window object (deleted) at %.8lX>"
+msgstr "<µøµ¡ª«¥ó(¤w§R°£): %.8lX>"
+
+#: if_python.c:1858
+#, c-format
+msgid "<window object (unknown) at %.8lX>"
+msgstr "<µøµ¡ª«¥ó(¥¼ª¾): %.8lX>"
+
+#: if_python.c:1860
+#, c-format
+msgid "<window %d>"
+msgstr "<µøµ¡ %d>"
+
+#: if_python.c:1936
+msgid "no such window"
+msgstr "µL¦¹µøµ¡"
+
+#: if_python.c:2193 if_python.c:2228 if_python.c:2278 if_python.c:2346
+#: if_python.c:2466 if_python.c:2518 if_tcl.c:684 if_tcl.c:729 if_tcl.c:803
+#: if_tcl.c:873 if_tcl.c:1998
+msgid "cannot save undo information"
+msgstr "µLªkÀx¦s´_­ì¸ê°T"
+
+#: if_python.c:2195 if_python.c:2285 if_python.c:2357
+msgid "cannot delete line"
+msgstr "¤£¯à§R°£¦¹¦æ"
+
+#: if_python.c:2230 if_python.c:2373 if_tcl.c:690 if_tcl.c:2020
+msgid "cannot replace line"
+msgstr "¤£¯à´À¥N¦¹¦æ"
+
+#: if_python.c:2389 if_python.c:2468 if_python.c:2526
+msgid "cannot insert line"
+msgstr "¤£¯à´À¥N´¡¤J¦¹¦æ"
+
+#: if_python.c:2630
+msgid "string cannot contain newlines"
+msgstr "¦r¦êµLªk¥]§t·s¦æ"
+
+#: if_ruby.c:396
+msgid ""
+"E266: Sorry, this command is disabled, the Ruby library could not be loaded."
+msgstr "E266: ¦¹©R¥OµLªk¨Ï¥Î¡AµLªk¸ü¤J Ruby µ{¦¡®w(Library)"
+
+#: if_ruby.c:459
+#, c-format
+msgid "E273: unknown longjmp status %d"
+msgstr "E273: ¥¼ª¾ªº longjmp status %d"
+
+#: if_sniff.c:67
+msgid "Toggle implementation/definition"
+msgstr "¤Á´«¹ê§@/©w¸q"
+
+#: if_sniff.c:68
+msgid "Show base class of"
+msgstr "Åã¥Ü base class of:"
+
+#: if_sniff.c:69
+msgid "Show overridden member function"
+msgstr "Åã¥Ü³Q override ªº member function"
+
+#: if_sniff.c:70
+msgid "Retrieve from file"
+msgstr "Ū¨ú: ±qÀÉ®×"
+
+#: if_sniff.c:71
+msgid "Retrieve from project"
+msgstr "Ū¨ú: ±qª«¥ó"
+
+#: if_sniff.c:73
+msgid "Retrieve from all projects"
+msgstr "Ū¨ú: ±q©Ò¦³ project"
+
+#: if_sniff.c:74
+msgid "Retrieve"
+msgstr "Ū¨ú"
+
+#: if_sniff.c:75
+msgid "Show source of"
+msgstr "Åã¥Ü­ì©l½X: "
+
+#: if_sniff.c:76
+msgid "Find symbol"
+msgstr "·j´M symbol"
+
+#: if_sniff.c:77
+msgid "Browse class"
+msgstr "ÂsÄý class"
+
+#: if_sniff.c:78
+msgid "Show class in hierarchy"
+msgstr "Åã¥Ü¶¥¼h¦¡ªº class"
+
+#: if_sniff.c:79
+msgid "Show class in restricted hierarchy"
+msgstr "Åã¥Ü restricted ¶¥¼h¦¡ªº class"
+
+#: if_sniff.c:80
+msgid "Xref refers to"
+msgstr "Xref °Ñ¦Ò¨ì"
+
+#: if_sniff.c:81
+msgid "Xref referred by"
+msgstr "Xref ³Q½Ö°Ñ¦Ò:"
+
+#: if_sniff.c:82
+msgid "Xref has a"
+msgstr "Xref ¦³"
+
+#: if_sniff.c:83
+msgid "Xref used by"
+msgstr "Xref ³Q½Ö¨Ï¥Î:"
+
+#: if_sniff.c:84
+msgid "Show docu of"
+msgstr "Åã¥Ü¤å¥ó: "
+
+#: if_sniff.c:85
+msgid "Generate docu for"
+msgstr "²£¥Í¤å¥ó: "
+
+#: if_sniff.c:97
+msgid ""
+"Cannot connect to SNiFF+. Check environment (sniffemacs must be found in "
+"$PATH).\n"
+msgstr "µLªk³s½u¨ì SNiFF+¡C½ÐÀˬdÀô¹ÒÅÜ¼Æ ($PATH ¸Ì¥²»Ý¥i¥H§ä¨ì sniffemacs)\n"
+
+#: if_sniff.c:425
+msgid "E274: Sniff: Error during read. Disconnected"
+msgstr "E274: Sniff: Ū¨ú¿ù»~. ¨ú®ø³s½u"
+
+#: if_sniff.c:553
+msgid "SNiFF+ is currently "
+msgstr "SNiFF+ ¥Ø«e"
+
+#: if_sniff.c:555
+msgid "not "
+msgstr "¥¼"
+
+#: if_sniff.c:556
+msgid "connected"
+msgstr "³s½u¤¤"
+
+#: if_sniff.c:592
+#, c-format
+msgid "E275: Unknown SNiFF+ request: %s"
+msgstr "E275: ¤£¥¿½Tªº SNiff+ ©I¥s: %s"
+
+#: if_sniff.c:605
+msgid "E276: Error connecting to SNiFF+"
+msgstr "E276: ³s½u¨ì SNiFF+ ¥¢±Ñ"
+
+#: if_sniff.c:1009
+msgid "E278: SNiFF+ not connected"
+msgstr "E278: ¥¼³s½u¨ì SNiFF+"
+
+#: if_sniff.c:1018
+msgid "E279: Not a SNiFF+ buffer"
+msgstr "E279: ¤£¬O SNiFF+ ªº½w½Ä°Ï"
+
+#: if_sniff.c:1083
+msgid "Sniff: Error during write. Disconnected"
+msgstr "Sniff: ¼g¤J¿ù»~¡Cµ²§ô³s½u"
+
+#: if_tcl.c:418
+msgid "invalid buffer number"
+msgstr "½w½Ä°Ï¸¹½X¿ù»~"
+
+#: if_tcl.c:464 if_tcl.c:931 if_tcl.c:1110
+msgid "not implemented yet"
+msgstr "©|¥¼¹ê§@"
+
+#: if_tcl.c:501
+msgid "unknown option"
+msgstr "¤£¥¿½Tªº¿ï¶µ"
+
+#. ???
+#: if_tcl.c:774
+msgid "cannot set line(s)"
+msgstr "¤£¯à³]©w¦æ"
+
+#: if_tcl.c:845
+msgid "mark not set"
+msgstr "¨S¦³³]©w¼Ð°O"
+
+#: if_tcl.c:851 if_tcl.c:1066
+#, c-format
+msgid "row %d column %d"
+msgstr "¦C %d ¦æ %d"
+
+#: if_tcl.c:881
+msgid "cannot insert/append line"
+msgstr "¤£¯à´¡¤J©Îªþ¥[¦¹¦æ"
+
+#: if_tcl.c:1268
+msgid "unknown flag: "
+msgstr "¿ù»~ªººX¼Ð: "
+
+#: if_tcl.c:1338
+msgid "unknown vimOption"
+msgstr "¤£¥¿½Tªº VIM ¿ï¶µ"
+
+#: if_tcl.c:1423
+msgid "keyboard interrupt"
+msgstr "Áä½L¤¤Â_"
+
+#: if_tcl.c:1428
+msgid "vim error"
+msgstr "vim ¿ù»~"
+
+#: if_tcl.c:1471
+msgid "cannot create buffer/window command: object is being deleted"
+msgstr "µLªk«Ø¥ß½w½Ä°Ï/µøµ¡©R¥O: ª«¥ó±N·|³Q§R°£"
+
+#: if_tcl.c:1545
+msgid ""
+"cannot register callback command: buffer/window is already being deleted"
+msgstr "µLªkµù¥U callback ©R¥O: ½w½Ä°Ï/µøµ¡¤w¸g³Q§R°£¤F"
+
+#. This should never happen. Famous last word?
+#: if_tcl.c:1562
+msgid ""
+"E280: TCL FATAL ERROR: reflist corrupt!? Please report this to vim-dev@vim."
+"org"
+msgstr "E280: TCL ÄY­«¿ù»~: reflist Äê±¼¤F!? ½Ð³ø§iµ¹ to vim-dev@vim.org"
+
+#: if_tcl.c:1563
+msgid "cannot register callback command: buffer/window reference not found"
+msgstr "µLªkµù¥U callback ©R¥O: §ä¤£¨ì½w½Ä°Ï/µøµ¡"
+
+#: if_tcl.c:1724
+msgid ""
+"E571: Sorry, this command is disabled: the Tcl library could not be loaded."
+msgstr ""
+"E571: ¦¹©R¥OµLªk¨Ï¥Î, ¦]¬°µLªk¸ü¤J Tcl µ{¦¡®w(Library)"
+
+#: if_tcl.c:1886
+msgid ""
+"E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"
+msgstr "E281: TCL ¿ù»~: µ²§ô½X¤£¬O¾ã¼Æ!? ½Ð³ø§iµ¹ to vim-dev@vim.org"
+
+#: if_tcl.c:2006
+msgid "cannot get line"
+msgstr "¤£¯à¨ú±o¦¹¦æ"
+
+#: if_xcmdsrv.c:215
+msgid "Unable to register a command server name"
+msgstr "µLªkµù¥U©R¥O¦øªA¾¹¦WºÙ"
+
+#: if_xcmdsrv.c:465
+msgid "E248: Failed to send command to the destination program"
+msgstr "E248: µLªk°e¥X©R¥O¨ì¥Øªº¦aµ{¦¡"
+
+#: if_xcmdsrv.c:735
+#, c-format
+msgid "E573: Invalid server id used: %s"
+msgstr "E573: ¤£¥¿½Tªº¦øªA¾¹ id : %s"
+
+#: if_xcmdsrv.c:1098
+msgid "E251: VIM instance registry property is badly formed. Deleted!"
+msgstr "E251: VIM ªº registry ³]©w¶µ¦³»~¡C¤w§R°£¡C"
+
+#: main.c:60
+msgid "Unknown option"
+msgstr "¤£¥¿½Tªº¿ï¶µ"
+
+#: main.c:62
+msgid "Too many edit arguments"
+msgstr "¤Ó¦h½s¿è°Ñ¼Æ"
+
+#: main.c:64
+msgid "Argument missing after"
+msgstr "¯Ê¤Ö¥²­nªº°Ñ¼Æ:"
+
+#: main.c:66
+msgid "Garbage after option"
+msgstr "µLªk¿ë»{¦¹¿ï¶µ«áªº©R¥O: "
+
+#: main.c:68
+msgid "Too many \"+command\" or \"-c command\" arguments"
+msgstr "¤Ó¦h \"+command\" ©Î \"-c command\" °Ñ¼Æ"
+
+#: main.c:70
+msgid "Invalid argument for"
+msgstr "¤£¥¿½Tªº°Ñ¼Æ: "
+
+#: main.c:469
+msgid "This Vim was not compiled with the diff feature."
+msgstr "±zªº Vim ½sĶ®É¨S¦³¥[¤J diff ªº¯à¤O"
+
+#: main.c:917
+msgid "Attempt to open script file again: \""
+msgstr "¸Õ¹Ï¦A¦¸¶}±Ò script ÀÉ: \""
+
+#: main.c:921 main.c:928 main.c:972 memline.c:3682 memline.c:3686
+#: version.c:857 version.c:862 version.c:867 version.c:872 version.c:877
+#: version.c:882 version.c:888 version.c:892 version.c:896 version.c:901
+#: version.c:908 version.c:916 version.c:922
+msgid "\"\n"
+msgstr "\"\n"
+
+#: main.c:926
+msgid "Cannot open for reading: \""
+msgstr "µLªk¶}±Ò¥HŪ¨ú: \""
+
+#: main.c:970
+msgid "Cannot open for script output: \""
+msgstr "µLªk¶}±Ò¬° script ¿é¥X: \""
+
+#: main.c:1104
+#, c-format
+msgid "%d files to edit\n"
+msgstr "ÁÙ¦³ %d ­ÓÀÉ®×µ¥«Ý½s¿è\n"
+
+#: main.c:1178
+msgid "Vim: Warning: Output is not to a terminal\n"
+msgstr "Vim: ª`·N: ¿é¥X¤£¬O²×ºÝ¾÷(¿Ã¹õ)\n"
+
+#: main.c:1180
+msgid "Vim: Warning: Input is not from a terminal\n"
+msgstr "Vim: ª`·N: ¿é¤J¤£¬O²×ºÝ¾÷(Áä½L)\n"
+
+#. just in case..
+#: main.c:1257
+msgid "pre-vimrc command line"
+msgstr "vimrc «e©R¥O¦C"
+
+#: main.c:1292
+#, c-format
+msgid "E282: Cannot read from \"%s\""
+msgstr "E282: µLªkŪ¨úÀÉ®× \"%s\""
+
+#: main.c:2313
+msgid ""
+"\n"
+"More info with: \"vim -h\"\n"
+msgstr ""
+"\n"
+"¬d¸ß§ó¦h¸ê°T½Ð°õ¦æ: \"vim -h\"\n"
+
+#: main.c:2346
+msgid "[file ..] edit specified file(s)"
+msgstr "[ÀÉ®× ..] ½s¿è«ü©wªºÀÉ®×"
+
+#: main.c:2347
+msgid "- read text from stdin"
+msgstr "- ±q¼Ð·Ç¿é¤J(stdin)Ū¨úÀÉ®×"
+
+#: main.c:2348
+msgid "-t tag edit file where tag is defined"
+msgstr "-t tag ½s¿è®É¨Ï¥Î«ü©wªº tag"
+
+#: main.c:2350
+msgid "-q [errorfile] edit file with first error"
+msgstr "-q [errorfile] ½s¿è®É¸ü¤J²Ä¤@­Ó¿ù»~"
+
+#: main.c:2359
+msgid ""
+"\n"
+"\n"
+"usage:"
+msgstr ""
+"\n"
+"\n"
+" ¥Îªk:"
+
+#: main.c:2362
+msgid " vim [arguments] "
+msgstr "vim [°Ñ¼Æ] "
+
+#: main.c:2366
+msgid ""
+"\n"
+" or:"
+msgstr ""
+"\n"
+" ©Î:"
+
+#: main.c:2369
+msgid ""
+"\n"
+"\n"
+"Arguments:\n"
+msgstr ""
+"\n"
+"\n"
+"°Ñ¼Æ:\n"
+
+#: main.c:2370
+msgid "--\t\t\tOnly file names after this"
+msgstr "--\t\t\t¥u¦³¦b³o¤§«áªºÀÉ®×"
+
+#: main.c:2372
+msgid "--literal\t\tDon't expand wildcards"
+msgstr "--literal\t\t¤£®i¶}¸U¥Î¦r¤¸"
+
+#: main.c:2375
+msgid "-register\t\tRegister this gvim for OLE"
+msgstr "-register\t\tµù¥U gvim ¨ì OLE"
+
+#: main.c:2376
+msgid "-unregister\t\tUnregister gvim for OLE"
+msgstr "-unregister\t\t¨ú®ø OLE ¤¤ªº gvim µù¥U"
+
+#: main.c:2379
+msgid "-g\t\t\tRun using GUI (like \"gvim\")"
+msgstr "-g\t\t\t¨Ï¥Î¹Ï§Î¬É­± (¦P \"gvim\")"
+
+#: main.c:2380
+msgid "-f or --nofork\tForeground: Don't fork when starting GUI"
+msgstr "-f ©Î --nofork\t«e´º: °_©l¹Ï§Î¬É­±®É¤£ fork"
+
+#: main.c:2382
+msgid "-v\t\t\tVi mode (like \"vi\")"
+msgstr "-v\t\t\tVi ¼Ò¦¡ (¦P \"vi\")"
+
+#: main.c:2383
+msgid "-e\t\t\tEx mode (like \"ex\")"
+msgstr "-e\t\t\tEx ¼Ò¦¡ (¦P \"ex\")"
+
+#: main.c:2384
+msgid "-s\t\t\tSilent (batch) mode (only for \"ex\")"
+msgstr "-s\t\t\t¦wÀR (batch) ¼Ò¦¡ (¥u¯à»P \"ex\" ¤@°_¨Ï¥Î)"
+
+#: main.c:2386
+msgid "-d\t\t\tDiff mode (like \"vimdiff\")"
+msgstr "-d\t\t\tDiff ¼Ò¦¡ (¦P \"vimdiff\", ¥i¨³³t¤ñ¸û¨âÀɮפ£¦P³B)"
+
+#: main.c:2388
+msgid "-y\t\t\tEasy mode (like \"evim\", modeless)"
+msgstr "-y\t\t\t²©ö¼Ò¦¡ (¦P \"evim\", modeless)"
+
+#: main.c:2389
+msgid "-R\t\t\tReadonly mode (like \"view\")"
+msgstr "-R\t\t\t°ßŪ¼Ò¦¡ (¦P \"view\")"
+
+#: main.c:2390
+msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
+msgstr "-Z\t\t\t­­¨î¼Ò¦¡ (¦P \"rvim\")"
+
+#: main.c:2391
+msgid "-m\t\t\tModifications (writing files) not allowed"
+msgstr "-m\t\t\t¤£¥i­×§ï (¼g¤JÀÉ®×)"
+
+#: main.c:2392
+msgid "-M\t\t\tModifications in text not allowed"
+msgstr "-M\t\t\t¤£¥i­×§ï¤å¦r"
+
+#: main.c:2393
+msgid "-b\t\t\tBinary mode"
+msgstr "-b\t\t\t¤G¶i¦ì¼Ò¦¡"
+
+#: main.c:2395
+msgid "-l\t\t\tLisp mode"
+msgstr "-l\t\t\tLisp ¼Ò¦¡"
+
+#: main.c:2397
+msgid "-C\t\t\tCompatible with Vi: 'compatible'"
+msgstr "-C\t\t\t'compatible' ¶Ç²Î Vi ¬Û®e¼Ò¦¡"
+
+#: main.c:2398
+msgid "-N\t\t\tNot fully Vi compatible: 'nocompatible'"
+msgstr "-N\t\t\t'nocompatible' ¤£§¹¥þ»P¶Ç²Î Vi ¬Û®e¡A¥i¨Ï¥Î Vim ¥[±j¯à¤O"
+
+#: main.c:2399
+msgid "-V[N]\t\tVerbose level"
+msgstr "-V[N]\t\tVerbose µ¥¯Å"
+
+#: main.c:2400
+msgid "-D\t\t\tDebugging mode"
+msgstr "-D\t\t\t°£¿ù¼Ò¦¡"
+
+#: main.c:2401
+msgid "-n\t\t\tNo swap file, use memory only"
+msgstr "-n\t\t\t¤£¨Ï¥Î¼È¦sÀÉ, ¥u¨Ï¥Î°O¾ÐÅé"
+
+#: main.c:2402
+msgid "-r\t\t\tList swap files and exit"
+msgstr "-r\t\t\t¦C¥X¼È¦sÀÉ«áÂ÷¶}"
+
+#: main.c:2403
+msgid "-r (with file name)\tRecover crashed session"
+msgstr "-r (¥[ÀɦW) \t­×´_¤W¦¸·l·´ªº¸ê®Æ(Recover crashed session)"
+
+#: main.c:2404
+msgid "-L\t\t\tSame as -r"
+msgstr "-L\t\t\t¦P -r"
+
+#: main.c:2406
+msgid "-f\t\t\tDon't use newcli to open window"
+msgstr "-f\t\t\t¤£¨Ï¥Î newcli ¨Ó¶}±Òµøµ¡"
+
+#: main.c:2407
+msgid "-dev <device>\t\tUse <device> for I/O"
+msgstr "-dev <device>\t\t¨Ï¥Î <device> °µ¿é¥X¤J"
+
+#: main.c:2410
+msgid "-H\t\t\tStart in Hebrew mode"
+msgstr "-H\t\t\t±Ò°Ê¬° Hebrew ¼Ò¦¡"
+
+#: main.c:2413
+msgid "-F\t\t\tStart in Farsi mode"
+msgstr "-F\t\t\t±Ò°Ê¬° Farsi ¼Ò¦¡"
+
+#: main.c:2415
+msgid "-T <terminal>\tSet terminal type to <terminal>"
+msgstr "-T <terminal>\t³]©w²×ºÝ¾÷¬° <terminal>"
+
+#: main.c:2416
+msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"
+msgstr "-u <vimrc>\t\t¨Ï¥Î <vimrc> ¨ú¥N¥ô¦ó .vimrc"
+
+#: main.c:2418
+msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"
+msgstr "-U <gvimrc>\t\t¨Ï¥Î <gvimrc> ¨ú¥N¥ô¦ó .gvimrc"
+
+#: main.c:2420
+msgid "--noplugin\t\tDon't load plugin scripts"
+msgstr "--noplugin\t\t¤£¸ü¤J¥ô¦ó plugin"
+
+#: main.c:2421
+msgid "-o[N]\t\tOpen N windows (default: one for each file)"
+msgstr "-o[N]\t\t¶}±Ò N ­Óµøµ¡ (¹w³]¬O¨C­ÓÀɮפ@­Ó)"
+
+#: main.c:2422
+msgid "-O[N]\t\tLike -o but split vertically"
+msgstr "-O[N]\t\t¦P -o ¦ý¨Ï¥Î««ª½¤À³Î"
+
+#: main.c:2423
+msgid "+\t\t\tStart at end of file"
+msgstr "+\t\t\t±Ò°Ê«á¸õ¨ìÀÉ®×µ²§À"
+
+#: main.c:2424
+msgid "+<lnum>\t\tStart at line <lnum>"
+msgstr "+<lnum>\t\t±Ò°Ê«á¸õ¨ì²Ä <lnum> ¦æ"
+
+#: main.c:2426
+msgid "--cmd <command>\tExecute <command> before loading any vimrc file"
+msgstr "--cmd <command>\t¸ü¤J¥ô¦ó vimrc «e°õ¦æ <command>"
+
+#: main.c:2428
+msgid "-c <command>\t\tExecute <command> after loading the first file"
+msgstr "-c <command>\t\t¸ü¤J²Ä¤@­ÓÀɮ׫á°õ¦æ <command>"
+
+#: main.c:2429
+msgid "-S <session>\t\tSource file <session> after loading the first file"
+msgstr "-S <session>\t\t¸ü¤J²Ä¤@­ÓÀɮ׫á¸ü¤J Session ÀÉ <session>"
+
+#: main.c:2430
+msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>"
+msgstr "-s <scriptin>\t±q <scriptin> Ū¤J¤@¯ë¼Ò¦¡©R¥O"
+
+#: main.c:2431
+msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>"
+msgstr "-w <scriptout>\t¹ïÀÉ®× <scriptout> ªþ¥[(append)©Ò¦³¿é¤Jªº©R¥O"
+
+#: main.c:2432
+msgid "-W <scriptout>\tWrite all typed commands to file <scriptout>"
+msgstr "-W <scriptout>\t¹ïÀÉ®× <scriptout> ¼g¤J©Ò¦³¿é¤Jªº©R¥O"
+
+#: main.c:2434
+msgid "-x\t\t\tEdit encrypted files"
+msgstr "-x\t\t\t½s¿è½s½X¹LªºÀÉ®×"
+
+#: main.c:2438
+msgid "-display <display>\tConnect vim to this particular X-server"
+msgstr "-display <display>\t±N vim »P«ü©wªº X-server ³s½u"
+
+#: main.c:2440
+msgid "-X\t\t\tDo not connect to X server"
+msgstr "-X\t\t\t¤£­n³s½u¨ì X Server"
+
+#: main.c:2443
+msgid "--remote <files>\tEdit <files> in a Vim server if possible"
+msgstr "--remote <files>\t½s¿è Vim ¦øªA¾¹¤Wªº <files> «áÂ÷¶}"
+
+#: main.c:2444
+msgid "--remote-silent <files> Same, don't complain if there is no server"
+msgstr "--remote-silent <files> ¬Û¦P¡A¦ý¨S¦³¦øªA¾¹®É¤£Äµ§i"
+
+#: main.c:2445
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
+msgstr "--remote-wait <files> ¦P --remote, ¦ý·|µ¥­ÔÀɮק¹¦¨½s¿è"
+
+#: main.c:2446
+msgid ""
+"--remote-wait-silent <files> Same, don't complain if there is no server"
+msgstr ""
+"--remote-wait-silent <files> ¬Û¦P¡A¦ý¨S¦øªA¾¹®É¤£Äµ§i"
+
+#: main.c:2447
+msgid "--remote-send <keys>\tSend <keys> to a Vim server and exit"
+msgstr "--remote-send <keys>\t°e¥X <keys> ¨ì Vim ¦øªA¾¹¨ÃÂ÷¶}"
+
+#: main.c:2448
+msgid "--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"
+msgstr "--remote-expr <expr>\t¦b¦øªA¾¹¤W°õ¦æ <expr> ¨Ã¦L¥Xµ²ªG"
+
+#: main.c:2449
+msgid "--serverlist\t\tList available Vim server names and exit"
+msgstr "--serverlist\t\t¦C¥X¥i¥Îªº Vim ¦øªA¾¹¦WºÙ¨ÃÂ÷¶}"
+
+#: main.c:2450
+msgid "--servername <name>\tSend to/become the Vim server <name>"
+msgstr "--servername <name>\t°e¦Ü/¦¨¬° Vim ¦øªA¾¹ <name>"
+
+#: main.c:2453
+msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
+msgstr "-i <viminfo>\t\t¨Ï¥Î <viminfo> ¦Ó«D .viminfo"
+
+#: main.c:2455
+msgid "-h or --help\tPrint Help (this message) and exit"
+msgstr "-h ©Î --help\t¦L¥X»¡©ú(¤]´N¬O¥»°T®§)«áÂ÷¶}"
+
+#: main.c:2456
+msgid "--version\t\tPrint version information and exit"
+msgstr "--version\t\t¦L¥Xª©¥»¸ê°T«áÂ÷¶}"
+
+#: main.c:2460
+msgid ""
+"\n"
+"Arguments recognised by gvim (Motif version):\n"
+msgstr ""
+"\n"
+"gvim »{±oªº°Ñ¼Æ (Motif ª©):\n"
+
+#: main.c:2463
+msgid ""
+"\n"
+"Arguments recognised by gvim (Athena version):\n"
+msgstr ""
+"\n"
+"gvim »{±oªº°Ñ¼Æ (Athena ª©):\n"
+
+#: main.c:2466
+msgid "-display <display>\tRun vim on <display>"
+msgstr "-display <display>\t¦bµøµ¡ <display> °õ¦æ vim"
+
+#: main.c:2467
+msgid "-iconic\t\tStart vim iconified"
+msgstr "-iconic\t\t±Ò°Ê«á¹Ï¥Ü¤Æ(iconified)"
+
+#: main.c:2469
+msgid "-name <name>\t\tUse resource as if vim was <name>"
+msgstr "-name <name>\t\tŪ¨ú Resource ®É§â vim ªº¦WºÙµø¬° <name>"
+
+#: main.c:2470
+msgid "\t\t\t (Unimplemented)\n"
+msgstr "\t\t\t (©|¥¼¹ê§@)\n"
+
+#: main.c:2472
+msgid "-background <color>\tUse <color> for the background (also: -bg)"
+msgstr "-background <color>\t³]©w <color> ¬°­I´º¦â (¤]¥i¥Î -bg)"
+
+#: main.c:2473
+msgid "-foreground <color>\tUse <color> for normal text (also: -fg)"
+msgstr "-foreground <color>\t³]©w <color> ¬°¤@¯ë¤å¦rÃC¦â (¤]¥i¥Î -fg)"
+
+#: main.c:2474 main.c:2494
+msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
+msgstr "-font <font>\t¨Ï¥Î <font> ¬°¤@¯ë¦r«¬ (¤]¥i¥Î -fn)"
+
+#: main.c:2475
+msgid "-boldfont <font>\tUse <font> for bold text"
+msgstr "-boldfont <font>\t¨Ï¥Î <font> ¬°²ÊÅé¦r«¬"
+
+#: main.c:2476
+msgid "-italicfont <font>\tUse <font> for italic text"
+msgstr "-italicfont <font>\t¨Ï¥Î <font> ¬°±×Åé¦r«¬"
+
+#: main.c:2477 main.c:2495
+msgid "-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"
+msgstr "-geometry <geom>\t¨Ï¥Î<geom>¬°°_©l¦ì¸m (¤]¥i¥Î -geom)"
+
+#: main.c:2478
+msgid "-borderwidth <width>\tUse a border width of <width> (also: -bw)"
+msgstr "-borderwidth <width>\t¨Ï¥Î¼e«×¬° <width> ªºÃä®Ø (¤]¥i¥Î -bw)"
+
+#: main.c:2479
+msgid "-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"
+msgstr "-scrollbarwidth <width> ³]©w±²°Ê¶b¼e«×¬° <width> (¤]¥i¥Î -sw)"
+
+#: main.c:2481
+msgid "-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"
+msgstr "-menuheight <height>\t³]©w¿ï³æ¦Cªº°ª«×¬° <height> (¤]¥i¥Î -mh)"
+
+#: main.c:2483 main.c:2496
+msgid "-reverse\t\tUse reverse video (also: -rv)"
+msgstr "-reverse\t\t¨Ï¥Î¤Ï¬ÛÅã¥Ü (¤]¥i¥Î -rv)"
+
+#: main.c:2484
+msgid "+reverse\t\tDon't use reverse video (also: +rv)"
+msgstr "+reverse\t\t¤£¨Ï¥Î¤Ï¬ÛÅã¥Ü (¤]¥i¥Î +rv)"
+
+#: main.c:2485
+msgid "-xrm <resource>\tSet the specified resource"
+msgstr "-xrm <resource>\t³]©w«ü©wªº resource"
+
+#: main.c:2488
+msgid ""
+"\n"
+"Arguments recognised by gvim (RISC OS version):\n"
+msgstr ""
+"\n"
+"gvim »{±oªº°Ñ¼Æ (RISC OS ª©):\n"
+
+#: main.c:2489
+msgid "--columns <number>\tInitial width of window in columns"
+msgstr "--columns <number>\tµøµ¡ªì©l¤Æ¼e«×"
+
+#: main.c:2490
+msgid "--rows <number>\tInitial height of window in rows"
+msgstr "--rows <number>\tµøµ¡ªì©l¤Æ°ª«×"
+
+#: main.c:2493
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK+ version):\n"
+msgstr ""
+"\n"
+"gvim »{±oªº°Ñ¼Æ (GTK+ ª©):\n"
+
+#: main.c:2497
+msgid "-display <display>\tRun vim on <display> (also: --display)"
+msgstr "-display <display>\t¦b <display> °õ¦æ vim (¤]¥i¥Î --display)"
+
+#: main.c:2499
+msgid "--role <role>\tSet a unique role to identify the main window"
+msgstr "--role <role>\t³]©w¿W¯Sªº¨¤¦â(role)¥H°Ï¤À¥Dµøµ¡"
+
+#: main.c:2501
+msgid "--socketid <xid>\tOpen Vim inside another GTK widget"
+msgstr "--socketid <xid>\t¦b¥t¤@­Ó GTK widget ¤º¶}±Ò Vim"
+
+#: main.c:2503
+msgid "--help\t\tShow Gnome arguments"
+msgstr "--help\t\tÅã¥Ü Gnome ¬ÛÃö°Ñ¼Æ"
+
+#: main.c:2735
+msgid "No display"
+msgstr "µLÅã¥Ü"
+
+#. Failed to send, abort.
+#: main.c:2750
+msgid ": Send failed.\n"
+msgstr ": ¶Ç°e¥¢±Ñ¡C\n"
+
+#. Let vim start normally.
+#: main.c:2756
+msgid ": Send failed. Trying to execute locally\n"
+msgstr ": °e¥X¥¢±Ñ¡C¸Õ¹Ï¦b¥»¦a°õ¦æ\n"
+
+#: main.c:2794 main.c:2815
+#, c-format
+msgid "%d of %d edited"
+msgstr "¤w½s¿è %d/%d ­ÓÀÉ®×"
+
+#: main.c:2837
+msgid "No display: Send expression failed.\n"
+msgstr "µL Display: µLªk¶Ç°e¹Bºâ¦¡¡C\n"
+
+#: main.c:2849
+msgid ": Send expression failed.\n"
+msgstr ": µLªk¶Ç°e¹Bºâ¦¡¡C\n"
+
+#: mark.c:656
+msgid "No marks set"
+msgstr "¨S¦³³]©w¼Ð°O (mark)"
+
+#: mark.c:658
+#, c-format
+msgid "E283: No marks matching \"%s\""
+msgstr "E283: §ä¤£¨ì²Å¦X \"%s\" ªº¼Ð°O(mark)"
+
+#. Highlight title
+#: mark.c:669
+msgid ""
+"\n"
+"mark line col file/text"
+msgstr ""
+"\n"
+"¼Ð°O ¦æ¸¹ Äæ ÀÉ®×/¤å¦r"
+
+#. Highlight title
+#: mark.c:707
+msgid ""
+"\n"
+" jump line col file/text"
+msgstr ""
+"\n"
+" jump ¦æ¸¹ Äæ ÀÉ®×/¤å¦r"
+
+#: mark.c:1072
+msgid ""
+"\n"
+"# File marks:\n"
+msgstr ""
+"\n"
+"# Àɮ׼аO:\n"
+
+#. Write the jumplist with -'
+#: mark.c:1107
+msgid ""
+"\n"
+"# Jumplist (newest first):\n"
+msgstr ""
+"\n"
+"# Jumplist (¥Ñ·s¨ìÂÂ):\n"
+
+#: mark.c:1202
+msgid ""
+"\n"
+"# History of marks within files (newest to oldest):\n"
+msgstr ""
+"\n"
+"# Àɮפº Mark °O¿ý (¥Ñ·s¨ìÂÂ):\n"
+
+#: mark.c:1285
+msgid "Missing '>'"
+msgstr "¯Ê¤Ö¹ïÀ³ªº '>'"
+
+#: mbyte.c:403
+msgid "E543: Not a valid codepage"
+msgstr "E543: ¤£¥¿½Tªº codepage"
+
+#: mbyte.c:3879
+msgid "E284: Cannot set IC values"
+msgstr "E284: ¤£¯à³]©w IC ¼Æ­È"
+
+#: mbyte.c:4031
+msgid "E285: Failed to create input context"
+msgstr "E285: µLªk«Ø¥ß input context"
+
+#: mbyte.c:4178
+msgid "E286: Failed to open input method"
+msgstr "E286: µLªk¶}±Ò¿é¤Jªk"
+
+#: mbyte.c:4189
+msgid "E287: Warning: Could not set destroy callback to IM"
+msgstr "E287: ĵ§i: µLªk²¾°£ IM ªº callback"
+
+#: mbyte.c:4195
+msgid "E288: input method doesn't support any style"
+msgstr "E288: ¿é¤Jªk¤£¤ä´©¥ô¦ó style"
+
+#: mbyte.c:4252
+msgid "E289: input method doesn't support my preedit type"
+msgstr "E289: ¿é¤Jªk¤£¤ä´©¥ô¦ó style"
+
+#: mbyte.c:4326
+msgid "E290: over-the-spot style requires fontset"
+msgstr "E290: over-the-spot »Ý­n¦r«¬¶°(Fontset)"
+
+#: mbyte.c:4358
+msgid "E291: Your GTK+ is older than 1.2.3. Status area disabled"
+msgstr "E291: §Aªº GTK+ ¤ñ 1.2.3 ÁÙ¡CµLªk¨Ï¥Îª¬ºA°Ï¡C"
+
+#: mbyte.c:4637
+msgid "E292: Input Method Server is not running"
+msgstr "E292: ¨S¦³°õ¦æ¤¤ªº¿é¤JªkºÞ²zµ{¦¡(Input Method Server)"
+
+#: memfile.c:488
+msgid "E293: block was not locked"
+msgstr "E293: °Ï¶ô¥¼³QÂê©w"
+
+#: memfile.c:989
+msgid "E294: Seek error in swap file read"
+msgstr "E294: ¼È¦sÀÉŪ¨ú¿ù»~"
+
+#: memfile.c:994
+msgid "E295: Read error in swap file"
+msgstr "E295: ¼È¦sÀÉŪ¨ú¿ù»~"
+
+#: memfile.c:1046
+msgid "E296: Seek error in swap file write"
+msgstr "E296: ¼È¦sÀɼg¤J¿ù»~"
+
+#: memfile.c:1064
+msgid "E297: Write error in swap file"
+msgstr "E297: ¼È¦sÀɼg¤J¿ù»~"
+
+#: memfile.c:1261
+msgid "E300: Swap file already exists (symlink attack?)"
+msgstr "E300: ¼È¦sÀɤw¸g¦s¦b! (¤p¤ß²Å¸¹³sµ²ªº¦w¥þº|¬}!?)"
+
+#: memline.c:275
+msgid "E298: Didn't get block nr 0?"
+msgstr "E298: §ä¤£¨ì°Ï¶ô 0?"
+
+#: memline.c:315
+msgid "E298: Didn't get block nr 1?"
+msgstr "E298: §ä¤£¨ì°Ï¶ô 1?"
+
+#: memline.c:333
+msgid "E298: Didn't get block nr 2?"
+msgstr "E298: §ä¤£¨ì°Ï¶ô 2?"
+
+#. could not (re)open the swap file, what can we do????
+#: memline.c:443
+msgid "E301: Oops, lost the swap file!!!"
+msgstr "E301: ¾¾¾¾, ¼È¦sÀɤ£¨£¤F!!!"
+
+#: memline.c:448
+msgid "E302: Could not rename swap file"
+msgstr "E302: µLªk§ïÅܼȦsÀɪº¦WºÙ"
+
+#: memline.c:518
+#, c-format
+msgid "E303: Unable to open swap file for \"%s\", recovery impossible"
+msgstr "E303: µLªk¶}±Ò¼È¦sÀÉ \"%s\", ¤£¥i¯à­×´_¤F"
+
+#: memline.c:617
+msgid "E304: ml_timestamp: Didn't get block 0??"
+msgstr "E304: ml_timestamp: §ä¤£¨ì°Ï¶ô 0??"
+
+#: memline.c:757
+#, c-format
+msgid "E305: No swap file found for %s"
+msgstr "E305: §ä¤£¨ì %s ªº¼È¦sÀÉ"
+
+#: memline.c:767
+msgid "Enter number of swap file to use (0 to quit): "
+msgstr "½Ð¿ï¾Ü§A­n¨Ï¥Îªº¼È¦sÀÉ («ö0 Â÷¶}): "
+
+#: memline.c:812
+#, c-format
+msgid "E306: Cannot open %s"
+msgstr "E306: µLªk¶}±Ò %s"
+
+#: memline.c:834
+msgid "Unable to read block 0 from "
+msgstr "µLªkŪ¨ú°Ï¶ô 0:"
+
+#: memline.c:837
+msgid ""
+"\n"
+"Maybe no changes were made or Vim did not update the swap file."
+msgstr ""
+"\n"
+"¥i¯à¬O§A¨S°µ¹L¥ô¦ó­×§ï©Î¬O Vim ÁÙ¨Ó¤£¤Î§ó·s¼È¦sÀÉ."
+
+#: memline.c:847 memline.c:864
+msgid " cannot be used with this version of Vim.\n"
+msgstr " µLªk¦b¥»ª©¥»ªº Vim ¤¤¨Ï¥Î.\n"
+
+#: memline.c:849
+msgid "Use Vim version 3.0.\n"
+msgstr "¨Ï¥Î Vim 3.0¡C\n"
+
+#: memline.c:855
+#, c-format
+msgid "E307: %s does not look like a Vim swap file"
+msgstr "E307: %s ¬Ý°_¨Ó¤£¹³¬O Vim ¼È¦sÀÉ"
+
+#: memline.c:868
+msgid " cannot be used on this computer.\n"
+msgstr " µLªk¦b³o»O¹q¸£¤W¨Ï¥Î.\n"
+
+#: memline.c:870
+msgid "The file was created on "
+msgstr "¥»Àɮ׫إߩó "
+
+#: memline.c:874
+msgid ""
+",\n"
+"or the file has been damaged."
+msgstr ""
+",\n"
+"©Î¬O³oÀɮפw¸g·l·´¡C"
+
+#: memline.c:903
+#, c-format
+msgid "Using swap file \"%s\""
+msgstr "¨Ï¥Î¼È¦sÀÉ \"%s\""
+
+#: memline.c:909
+#, c-format
+msgid "Original file \"%s\""
+msgstr "­ì©lÀÉ \"%s\""
+
+#: memline.c:922
+msgid "E308: Warning: Original file may have been changed"
+msgstr "E308: ĵ§i: ­ì©lÀÉ®×¥i¯à¤w¸g­×§ï¹L¤F"
+
+#: memline.c:963
+#, c-format
+msgid "E309: Unable to read block 1 from %s"
+msgstr "E309: µLªk±q %s Ū¨ú°Ï¶ô 1"
+
+#: memline.c:967
+msgid "???MANY LINES MISSING"
+msgstr "???¯Ê¤Ö¤Ó¦h¦æ"
+
+#: memline.c:983
+msgid "???LINE COUNT WRONG"
+msgstr "???¦æ¸¹¿ù»~"
+
+#: memline.c:990
+msgid "???EMPTY BLOCK"
+msgstr "???ªÅªº BLOCK"
+
+#: memline.c:1016
+msgid "???LINES MISSING"
+msgstr "???§ä¤£¨ì¤@¨Ç¦æ"
+
+#: memline.c:1048
+#, c-format
+msgid "E310: Block 1 ID wrong (%s not a .swp file?)"
+msgstr "E310: °Ï¶ô 1 ID ¿ù»~ (%s ¤£¬O¼È¦sÀÉ?)"
+
+#: memline.c:1053
+msgid "???BLOCK MISSING"
+msgstr "???§ä¤£¨ìBLOCK"
+
+#: memline.c:1069
+msgid "??? from here until ???END lines may be messed up"
+msgstr "??? ±q³o¸Ì¨ì ???END ªº¤º®e¥i¯à¦³°ÝÃD"
+
+#: memline.c:1085
+msgid "??? from here until ???END lines may have been inserted/deleted"
+msgstr "??? ±q³o¸Ì¨ì ???END ªº¤º®e¥i¯à³Q§R°£/´¡¤J¹L"
+
+# do not translate
+#: memline.c:1105
+msgid "???END"
+msgstr "???END"
+
+#: memline.c:1131
+msgid "E311: Recovery Interrupted"
+msgstr "E311: ­×´_¤w¤¤Â_"
+
+#: memline.c:1133
+msgid ""
+"E312: Errors detected while recovering; look for lines starting with ???"
+msgstr "E312: ­×´_®Éµo¥Í¿ù»~; ½Ðª`·N¶}ÀY¬° ??? ªº¦æ"
+
+#: memline.c:1136
+msgid "Recovery completed. You should check if everything is OK."
+msgstr "´_­ì§¹¦¨. ½Ð½T©w¤@¤Á¥¿±`."
+
+#: memline.c:1137
+msgid ""
+"\n"
+"(You might want to write out this file under another name\n"
+msgstr ""
+"\n"
+"(§A¥i¯à·|·Q­n§â³o­ÓÀÉ®×¥t¦s§OªºÀɦW¡A\n"
+
+#: memline.c:1138
+msgid "and run diff with the original file to check for changes)\n"
+msgstr "¦A°õ¦æ diff »P­ìÀɮפñ¸û¥HÀˬd¬O§_¦³§ïÅÜ)\n"
+
+#: memline.c:1139
+msgid ""
+"Delete the .swp file afterwards.\n"
+"\n"
+msgstr ""
+"(D)ª½±µ§R°£ .swp ¼È¦sÀÉ\n"
+"\n"
+
+#. use msg() to start the scrolling properly
+#: memline.c:1195
+msgid "Swap files found:"
+msgstr "§ä¨ì¥H¤Uªº¼È¦sÀÉ:"
+
+#: memline.c:1373
+msgid " In current directory:\n"
+msgstr " ¦b¥Ø«eªº¥Ø¿ý:\n"
+
+#: memline.c:1375
+msgid " Using specified name:\n"
+msgstr " Using specified name:\n"
+
+#: memline.c:1379
+msgid " In directory "
+msgstr " ¦b¥Ø¿ý "
+
+#: memline.c:1397
+msgid " -- none --\n"
+msgstr " -- µL --\n"
+
+#: memline.c:1469
+msgid " owned by: "
+msgstr " ¾Ö¦³ªÌ: "
+
+#: memline.c:1471
+msgid " dated: "
+msgstr " ¤é´Á: "
+
+#: memline.c:1475 memline.c:3689
+msgid " dated: "
+msgstr " ¤é´Á: "
+
+#: memline.c:1491
+msgid " [from Vim version 3.0]"
+msgstr " [±q Vim ª©¥» 3.0]"
+
+#: memline.c:1495
+msgid " [does not look like a Vim swap file]"
+msgstr " [¤£¹³ Vim ªº¼È¦sÀÉ]"
+
+#: memline.c:1499
+msgid " file name: "
+msgstr " ÀɦW: "
+
+#: memline.c:1505
+msgid ""
+"\n"
+" modified: "
+msgstr ""
+"\n"
+" ­×§ï¹L: "
+
+#: memline.c:1506
+msgid "YES"
+msgstr "¬O"
+
+#: memline.c:1506
+msgid "no"
+msgstr "§_"
+
+#: memline.c:1510
+msgid ""
+"\n"
+" user name: "
+msgstr ""
+"\n"
+" ¨Ï¥ÎªÌ: "
+
+#: memline.c:1517
+msgid " host name: "
+msgstr " ¥D¾÷¦WºÙ: "
+
+#: memline.c:1519
+msgid ""
+"\n"
+" host name: "
+msgstr ""
+"\n"
+" ¥D¾÷¦WºÙ: "
+
+#: memline.c:1525
+msgid ""
+"\n"
+" process ID: "
+msgstr ""
+"\n"
+" process ID: "
+
+#: memline.c:1531
+msgid " (still running)"
+msgstr " (°õ¦æ¤¤)"
+
+#: memline.c:1543
+msgid ""
+"\n"
+" [not usable with this version of Vim]"
+msgstr ""
+"\n"
+" [µLªk¦b¥»ª©¥»ªº Vim ¤W¨Ï¥Î]"
+
+#: memline.c:1546
+msgid ""
+"\n"
+" [not usable on this computer]"
+msgstr ""
+"\n"
+" [µLªk¦b¥»¹q¸£¤W¨Ï¥Î]"
+
+#: memline.c:1551
+msgid " [cannot be read]"
+msgstr " [µLªkŪ¨ú]"
+
+#: memline.c:1555
+msgid " [cannot be opened]"
+msgstr " [µLªk¶}±Ò]"
+
+#: memline.c:1745
+msgid "E313: Cannot preserve, there is no swap file"
+msgstr "E313: µLªk«O¯d, ¤£¨Ï¥Î¼È¦sÀÉ"
+
+#: memline.c:1798
+msgid "File preserved"
+msgstr "Àɮפw«O¯d"
+
+#: memline.c:1800
+msgid "E314: Preserve failed"
+msgstr "E314: «O¯d¥¢±Ñ"
+
+#: memline.c:1871
+#, c-format
+msgid "E315: ml_get: invalid lnum: %ld"
+msgstr "E315: ml_get: ¿ù»~ªº lnum: %ld"
+
+#: memline.c:1897
+#, c-format
+msgid "E316: ml_get: cannot find line %ld"
+msgstr "E316: ml_get: §ä¤£¨ì²Ä %ld ¦æ"
+
+#: memline.c:2287
+msgid "E317: pointer block id wrong 3"
+msgstr "E317: «ü¼Ð°Ï¶ô id ¿ù»~ 3"
+
+#: memline.c:2367
+msgid "stack_idx should be 0"
+msgstr "stack_idx À³¸Ó¬O 0"
+
+#: memline.c:2429
+msgid "E318: Updated too many blocks?"
+msgstr "E318: §ó·s¤Ó¦h°Ï¶ô?"
+
+#: memline.c:2611
+msgid "E317: pointer block id wrong 4"
+msgstr "E317: «ü¼Ð°Ï¶ô id ¿ù»~ 4"
+
+#: memline.c:2638
+msgid "deleted block 1?"
+msgstr "§R°£°Ï¶ô 1?"
+
+#: memline.c:2838
+#, c-format
+msgid "E320: Cannot find line %ld"
+msgstr "E320: §ä¤£¨ì²Ä %ld ¦æ"
+
+#: memline.c:3081
+msgid "E317: pointer block id wrong"
+msgstr "E317: «ü¼Ð°Ï¶ô id ¿ù»~"
+
+#: memline.c:3097
+msgid "pe_line_count is zero"
+msgstr "pe_line_count ¬°¹s"
+
+#: memline.c:3126
+#, c-format
+msgid "E322: line number out of range: %ld past the end"
+msgstr "E322: ¦æ¸¹¶W¥X½d³ò: %ld ¶W¹Lµ²§À"
+
+#: memline.c:3130
+#, c-format
+msgid "E323: line count wrong in block %ld"
+msgstr "E323: °Ï¶ô %ld ¦æ¼Æ¿ù»~"
+
+#: memline.c:3179
+msgid "Stack size increases"
+msgstr "°ïÅ|¤j¤p¼W¥["
+
+#: memline.c:3225
+msgid "E317: pointer block id wrong 2"
+msgstr "E317: «ü¼Ð°Ï¶ô id ¿ù 2"
+
+#: memline.c:3679
+msgid "E325: ATTENTION"
+msgstr "E325: ª`·N"
+
+#: memline.c:3680
+msgid ""
+"\n"
+"Found a swap file by the name \""
+msgstr ""
+"\n"
+"§ä¨ì¼È¦sÀÉ \""
+
+#: memline.c:3684
+msgid "While opening file \""
+msgstr "¦b¶}±ÒÀÉ®× \""
+
+#: memline.c:3693
+msgid " NEWER than swap file!\n"
+msgstr " ¤ñ¼È¦sÀɧó·s!\n"
+
+#. Some of these messages are long to allow translation to
+#. * other languages.
+#: memline.c:3697
+msgid ""
+"\n"
+"(1) Another program may be editing the same file.\n"
+" If this is the case, be careful not to end up with two\n"
+" different instances of the same file when making changes.\n"
+msgstr ""
+"\n"
+"(1) ¥i¯à¦³¥t¤@­Óµ{¦¡¤]¦b½s¿è¦P¤@­ÓÀÉ®×.\n"
+" ¦pªG¬O³o¼Ë¡A½Ð¤p¤ß¤£­n¨âÃä¤@°_¼g¤J¡A¤£µM§Aªº§V¤O³£·|­t½Ñ¬y¤ô¡C\n"
+
+#: memline.c:3698
+msgid " Quit, or continue with caution.\n"
+msgstr " Â÷¶}¡A©Î¬OÄ~Äò½s¿è¡C\n"
+
+#: memline.c:3699
+msgid ""
+"\n"
+"(2) An edit session for this file crashed.\n"
+msgstr ""
+"\n"
+"(2) «e¦¸½s¿è¦¹Àɮɷí¾÷\n"
+
+#: memline.c:3700
+msgid " If this is the case, use \":recover\" or \"vim -r "
+msgstr " ¦pªG¬O³o¼Ë, ½Ð¥Î \":recover\" ©Î \"vim -r"
+
+#: memline.c:3702
+msgid ""
+"\"\n"
+" to recover the changes (see \":help recovery\").\n"
+msgstr ""
+"\"\n"
+" ¨Ó±Ï¦^­×§ï¸ê®Æ (¶i¤@¨B»¡©ú½Ð¬Ý \":help recovery\").\n"
+
+#: memline.c:3703
+msgid " If you did this already, delete the swap file \""
+msgstr " ¦pªG¸Ó±Ïªº³£¤w¸g±Ï¤F, ½Ðª½±µ§R°£¦¹¼È¦sÀÉ \""
+
+#: memline.c:3705
+msgid ""
+"\"\n"
+" to avoid this message.\n"
+msgstr ""
+"\"\n"
+" ¥HÁקK¦A¬Ý¨ì¦¹°T®§.\n"
+
+#: memline.c:3719 memline.c:3723
+msgid "Swap file \""
+msgstr "¼È¦sÀÉ \""
+
+#: memline.c:3720 memline.c:3726
+msgid "\" already exists!"
+msgstr "\" ¤w¸g¦s¦b¤F!"
+
+#: memline.c:3729
+msgid "VIM - ATTENTION"
+msgstr "VIM - ª`·N"
+
+#: memline.c:3731
+msgid "Swap file already exists!"
+msgstr "¼È¦sÀɤw¸g¦s¦b!"
+
+#: memline.c:3735
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit"
+msgstr ""
+"¥H°ßŪ¤è¦¡¶}±Ò(&O)\n"
+"ª½±µ½s¿è(&E)\n"
+"­×´_(&R)\n"
+"Â÷¶}(&Q)"
+
+#: memline.c:3737
+msgid ""
+"&Open Read-Only\n"
+"&Edit anyway\n"
+"&Recover\n"
+"&Quit\n"
+"&Delete it"
+msgstr ""
+"¥H°ßŪ¤è¦¡¶}±Ò(&O)\n"
+"ª½±µ½s¿è(&E)\n"
+"­×´_(&R)\n"
+"Â÷¶}(&Q)\n"
+"§R°£¼È¦sÀÉ(&D)"
+
+#: memline.c:3790
+msgid "E326: Too many swap files found"
+msgstr "E326: §ä¨ì¤Ó¦h¼È¦sÀÉ"
+
+#: menu.c:64
+msgid "E327: Part of menu-item path is not sub-menu"
+msgstr "E327: ³¡¥÷¿ï¶µ¸ô®|¤£¬O¤l¿ï³æ"
+
+#: menu.c:65
+msgid "E328: Menu only exists in another mode"
+msgstr "E328: ¿ï³æ¥u¯à¦b¨ä¥¦¼Ò¦¡¤¤¨Ï¥Î"
+
+#: menu.c:66
+msgid "E329: No menu of that name"
+msgstr "E329: ¨S¦³¨º¼Ëªº¿ï³æ"
+
+#: menu.c:509
+msgid "E330: Menu path must not lead to a sub-menu"
+msgstr "E330: ¿ï³æ¸ô®|¤£¯à«ü¦V¤l¿ï³æ"
+
+#: menu.c:548
+msgid "E331: Must not add menu items directly to menu bar"
+msgstr "E331: ¤£¯àª½±µ§â¿ï¶µ¥[¨ì¿ï³æ¦C¤¤"
+
+#: menu.c:554
+msgid "E332: Separator cannot be part of a menu path"
+msgstr "E332: ¤À¹j½u¤£¯à¬O¿ï³æ¸ô®|ªº¤@³¡¥÷"
+
+#. Now we have found the matching menu, and we list the mappings
+#. Highlight title
+#: menu.c:1079
+msgid ""
+"\n"
+"--- Menus ---"
+msgstr ""
+"\n"
+"--- ¿ï³æ ---"
+
+#: menu.c:1996
+msgid "Tear off this menu"
+msgstr "¤Á¤U¦¹¿ï³æ"
+
+#: menu.c:2061
+msgid "E333: Menu path must lead to a menu item"
+msgstr "E333: ¿ï³æ¸ô®|¥²»Ý«ü¦V¤@­Ó¿ï¶µ"
+
+#: menu.c:2081
+#, c-format
+msgid "E334: Menu not found: %s"
+msgstr "E334: [¿ï³æ] §ä¤£¨ì %s"
+
+#: menu.c:2150
+#, c-format
+msgid "E335: Menu not defined for %s mode"
+msgstr "E335: %s ¼Ò¦¡¥¼©w¸q¿ï³æ"
+
+#: menu.c:2188
+msgid "E336: Menu path must lead to a sub-menu"
+msgstr "E336: ¿ï³æ¸ô®|¥²»Ý«ü¦V¤l¿ï³æ"
+
+#: menu.c:2209
+msgid "E337: Menu not found - check menu names"
+msgstr "E337: §ä¤£¨ì¿ï³æ - ½ÐÀˬd¿ï³æ¦WºÙ"
+
+#: message.c:509
+#, c-format
+msgid "Error detected while processing %s:"
+msgstr "³B²z %s ®Éµo¥Í¿ù»~:"
+
+#: message.c:525
+#, c-format
+msgid "line %4ld:"
+msgstr "¦æ %4ld:"
+
+#: message.c:565
+msgid "[string too long]"
+msgstr "[¦¹¦æ¹Lªø]"
+
+#: message.c:711
+msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
+msgstr ""
+"¥¿Å餤¤å°T®§ºûÅ@ªÌ: Francis S.Lin <piaip@csie.ntu.edu."
+"tw>, Cecil Sheng <b7506022@csie.ntu.edu.tw>"
+
+#: message.c:935
+msgid "Interrupt: "
+msgstr "¤w¤¤Â_: "
+
+#: message.c:938
+msgid "Hit ENTER to continue"
+msgstr "½Ð«ö ENTER Ä~Äò"
+
+#: message.c:940
+msgid "Hit ENTER or type command to continue"
+msgstr "½Ð«ö ENTER ©Î¨ä¥¦©R¥O¥HÄ~Äò"
+
+#: message.c:2028
+msgid "-- More --"
+msgstr "-- ©|¦³ --"
+
+#: message.c:2031
+msgid " (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)"
+msgstr " (RET/BS: ¦V¤U/¦V¤W¤@¦æ, ªÅ¥ÕÁä/b: ¤@­¶, d/u: ¥b­¶, q: Â÷¶})"
+
+#: message.c:2032
+msgid " (RET: line, SPACE: page, d: half page, q: quit)"
+msgstr " (RET: ¦V¤U¤@¦æ, ªÅ¥ÕÁä: ¤@­¶, d: ¥b­¶, q: Â÷¶})"
+
+#: message.c:2508 message.c:2523
+msgid "Question"
+msgstr "°ÝÃD"
+
+#: message.c:2510
+msgid ""
+"&Yes\n"
+"&No"
+msgstr ""
+"&Y¬O\n"
+"&N§_"
+
+#: message.c:2543
+msgid ""
+"&Yes\n"
+"&No\n"
+"Save &All\n"
+"&Discard All\n"
+"&Cancel"
+msgstr ""
+"&Y¬O\n"
+"&N§_\n"
+"&A¥þ³¡¦sÀÉ\n"
+"&D¥þ³¡¤£¦s\n"
+"&C¨ú®ø"
+
+#: message.c:2584
+msgid "Save File dialog"
+msgstr "¦sÀÉ"
+
+#: message.c:2586
+msgid "Open File dialog"
+msgstr "¶}ÀÉ"
+
+#. TODO: non-GUI file selector here
+#: message.c:2657
+msgid "E338: Sorry, no file browser in console mode"
+msgstr "E338: ¥D±±¥x(Console)¼Ò¦¡®É¨S¦³ÀÉ®×ÂsÄý¾¹(file browser)"
+
+#: misc1.c:2477
+msgid "W10: Warning: Changing a readonly file"
+msgstr "W10: ª`·N: §A¥¿¦b­×§ï¤@­Ó°ßŪÀÉ"
+
+#: misc1.c:2712
+msgid "1 more line"
+msgstr "ÁÙ¦³¤@¦æ"
+
+#: misc1.c:2714
+msgid "1 line less"
+msgstr "¤Ö©ó¤@¦æ"
+
+#: misc1.c:2719
+#, c-format
+msgid "%ld more lines"
+msgstr " ÁÙ¦³ %ld ¦æ"
+
+#: misc1.c:2721
+#, c-format
+msgid "%ld fewer lines"
+msgstr "¥u³Ñ %ld ¦æ"
+
+#: misc1.c:2724
+msgid " (Interrupted)"
+msgstr " (¤w¤¤Â_)"
+
+#: misc1.c:6348
+msgid "Vim: preserving files...\n"
+msgstr "Vim: «O¯dÀɮפ¤...\n"
+
+#. close all memfiles, without deleting
+#: misc1.c:6358
+msgid "Vim: Finished.\n"
+msgstr "Vim: µ²§ô.\n"
+
+#: misc2.c:670 misc2.c:686
+msgid "ERROR: "
+msgstr "¿ù»~: "
+
+#: misc2.c:690
+#, c-format
+msgid ""
+"\n"
+"[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"
+msgstr ""
+"\n"
+"[bytes] ¥þ³¡ alloc-freed %lu-%lu, ¨Ï¥Î¤¤ %lu, peak ¨Ï¥Î %lu\n"
+
+#: misc2.c:692
+#, c-format
+msgid ""
+"[calls] total re/malloc()'s %lu, total free()'s %lu\n"
+"\n"
+msgstr ""
+"[©I¥s] ¥þ³¡ re/malloc(): %lu, ¥þ³¡ free()': %lu\n"
+"\n"
+
+#: misc2.c:747
+msgid "E340: Line is becoming too long"
+msgstr "E340: ¦¹¦æ¹Lªø"
+
+#: misc2.c:791
+#, c-format
+msgid "E341: Internal error: lalloc(%ld, )"
+msgstr "E341: ¤º³¡¿ù»~: lalloc(%ld, )"
+
+#: misc2.c:899
+#, c-format
+msgid "E342: Out of memory! (allocating %lu bytes)"
+msgstr "E342: °O¾ÐÅ餣¨¬! (¹Á¸Õ°t¸m %lu ¦ì¤¸²Õ)"
+
+#: misc2.c:2564
+#, c-format
+msgid "Calling shell to execute: \"%s\""
+msgstr "©I¥s shell °õ¦æ: \"%s\""
+
+#: misc2.c:2785
+msgid "E545: Missing colon"
+msgstr "E545: ¯Ê¤Ö colon"
+
+#: misc2.c:2787 misc2.c:2814
+msgid "E546: Illegal mode"
+msgstr "E546: ¤£¥¿½Tªº¼Ò¦¡"
+
+#: misc2.c:2853
+msgid "E547: Illegal mouseshape"
+msgstr "E547: ¤£¥¿½Tªº·Æ¹«§Îª¬"
+
+#: misc2.c:2893
+msgid "E548: digit expected"
+msgstr "E548: À³¸Ó­n¦³¼Æ¦r"
+
+#: misc2.c:2898
+msgid "E549: Illegal percentage"
+msgstr "E549: ¤£¥¿½Tªº¦Ê¤À¤ñ"
+
+#: misc2.c:3208
+msgid "Enter encryption key: "
+msgstr "¿é¤J±K½X: "
+
+#: misc2.c:3209
+msgid "Enter same key again: "
+msgstr "½Ð¦A¿é¤J¤@¦¸: "
+
+#: misc2.c:3219
+msgid "Keys don't match!"
+msgstr "¨â¦¸¿é¤J±K½X¤£¬Û¦P!"
+
+#: misc2.c:3768
+#, c-format
+msgid ""
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
+msgstr "E343: ¤£¥¿½Tªº¸ô®|: '**[number]' ¥²»Ý­n¦b¸ô®|µ²§À©Î­n±µµÛ '%s'"
+
+#: misc2.c:5044
+#, c-format
+msgid "E344: Can't find directory \"%s\" in cdpath"
+msgstr "E344: cdpath ¤¤¨S¦³¥Ø¿ý \"%s\""
+
+#: misc2.c:5047
+#, c-format
+msgid "E345: Can't find file \"%s\" in path"
+msgstr "E345: ¦b¸ô®|¤¤§ä¤£¨ìÀÉ®× \"%s\""
+
+#: misc2.c:5053
+#, c-format
+msgid "E346: No more directory \"%s\" found in cdpath"
+msgstr "E346: ¦b¸ô®|¤¤§ä¤£¨ì§ó¦hªºÀÉ®× \"%s\""
+
+#: misc2.c:5056
+#, c-format
+msgid "E347: No more file \"%s\" found in path"
+msgstr "E347: ¦b¸ô®|¤¤§ä¤£¨ì§ó¦hªºÀÉ®× \"%s\""
+
+#: misc2.c:5290
+msgid "E550: Missing colon"
+msgstr "E550: ¯Ê¤Ö colon"
+
+#: misc2.c:5302
+msgid "E551: Illegal component"
+msgstr "E551: ¤£¥¿½Tªº¼Ò¦¡"
+
+#: misc2.c:5310
+msgid "E552: digit expected"
+msgstr "E552: À³¸Ó­n¦³¼Æ¦r"
+
+#. Get here when the server can't be found.
+#: netbeans.c:283
+msgid "Cannot connect to Netbeans #2"
+msgstr "µLªk³s±µ¨ì Netbeans #2"
+
+#: netbeans.c:291
+msgid "Cannot connect to Netbeans"
+msgstr "µLªk³s±µ¨ì Netbeans"
+
+#: netbeans.c:565
+msgid "read from Netbeans socket"
+msgstr "¥Ñ Netbeans socket Ū¨ú"
+
+#: normal.c:2913
+msgid "Warning: terminal cannot highlight"
+msgstr "ª`·N: §Aªº²×ºÝ¾÷µLªkÅã¥Ü°ª«G«×"
+
+#: normal.c:3128
+msgid "E348: No string under cursor"
+msgstr "E348: ´å¼Ð³B¨S¦³¦r¦ê"
+
+#: normal.c:3130
+msgid "E349: No identifier under cursor"
+msgstr "E349: ´å¼Ð³B¨S¦³ÃѧO¦r"
+
+#: normal.c:4348
+msgid "E352: Cannot erase folds with current 'foldmethod'"
+msgstr "E352: µLªk¦b¥Ø«eªº 'foldmethod' ¤U§R°£ fold"
+
+#: ops.c:295
+#, c-format
+msgid "1 line %sed 1 time"
+msgstr "¤@¦æ %s ¹L ¤@¦¸"
+
+#: ops.c:297
+#, c-format
+msgid "1 line %sed %d times"
+msgstr "¤@¦æ %s ¹L %d ¦¸"
+
+#: ops.c:302
+#, c-format
+msgid "%ld lines %sed 1 time"
+msgstr "%ld ¦æ %s ¹L ¤@¦¸"
+
+#: ops.c:305
+#, c-format
+msgid "%ld lines %sed %d times"
+msgstr "%ld ¦æ %s ¹L %d ¦¸"
+
+#: ops.c:663
+#, c-format
+msgid "%ld lines to indent... "
+msgstr "ÁY±Æ %ld ¦æ..."
+
+#: ops.c:713
+msgid "1 line indented "
+msgstr "¤@¦æ¤wÁY±Æ"
+
+#: ops.c:715
+#, c-format
+msgid "%ld lines indented "
+msgstr "¤wÁY±Æ %ld ¦æ"
+
+#. must display the prompt
+#: ops.c:1645
+msgid "cannot yank; delete anyway"
+msgstr "µLªk°Å¤U; ª½±µ§R°£"
+
+#: ops.c:2152
+msgid "1 line changed"
+msgstr " 1 ¦æ ~ed"
+
+#: ops.c:2154
+#, c-format
+msgid "%ld lines changed"
+msgstr " %ld ¦æ ~ed"
+
+#: ops.c:2538
+#, c-format
+msgid "freeing %ld lines"
+msgstr "ÄÀ©ñ %ld ¦æ¤¤"
+
+#: ops.c:2819
+msgid "1 line yanked"
+msgstr "¤w½Æ»s 1 ¦æ"
+
+#: ops.c:2821
+#, c-format
+msgid "%ld lines yanked"
+msgstr "¤w½Æ»s %ld ¦æ"
+
+#: ops.c:3106
+#, c-format
+msgid "E353: Nothing in register %s"
+msgstr "E353: ¼È¦s¾¹ %s ¸Ì¨S¦³ªF¦è"
+
+#. Highlight title
+#: ops.c:3664
+msgid ""
+"\n"
+"--- Registers ---"
+msgstr ""
+"\n"
+"--- ¼È¦s¾¹ ---"
+
+#: ops.c:4873
+msgid "Illegal register name"
+msgstr "¤£¥¿½Tªº¼È¦s¾¹¦WºÙ"
+
+#: ops.c:4959
+msgid ""
+"\n"
+"# Registers:\n"
+msgstr ""
+"\n"
+"# ¼È¦s¾¹:\n"
+
+#: ops.c:4992
+#, c-format
+msgid "E574: Unknown register type %d"
+msgstr "E574: ¥¼ª¾ªºµù¥U«¬ºA: %d"
+
+#: ops.c:5412
+#, c-format
+msgid "E354: Invalid register name: '%s'"
+msgstr "E354: ¼È¦s¾¹¦WºÙ¿ù»~: '%s'"
+
+#: ops.c:5750
+#, c-format
+msgid "%ld Cols; "
+msgstr "%ld Äæ; "
+
+#: ops.c:5757
+#, c-format
+msgid "Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"
+msgstr "¿ï¾Ü¤F %s%ld/%ld ¦æ; %ld/%ld ¦r(Word); %ld/%ld ¦r¤¸(Bytes)"
+
+#: ops.c:5773
+#, c-format
+msgid "Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"
+msgstr "Äæ %s/%s; ¦æ %ld/%ld; ¦r(Word) %ld/%ld; ¦r¤¸(Byte) %ld/%ld"
+
+#: ops.c:5784
+#, c-format
+msgid "(+%ld for BOM)"
+msgstr "(+%ld for BOM)"
+
+#: option.c:1579
+msgid "%<%f%h%m%=Page %N"
+msgstr "%<%f%h%m%=²Ä %N ­¶"
+
+# ? what's this for?
+#: option.c:2012
+msgid "Thanks for flying Vim"
+msgstr "·PÁ±z·R¥Î Vim"
+
+#: option.c:3250 option.c:3357
+msgid "E518: Unknown option"
+msgstr "E518: ¤£¥¿½Tªº¿ï¶µ"
+
+#: option.c:3263
+msgid "E519: Option not supported"
+msgstr "E519: ¤£¤ä´©¸Ó¿ï¶µ"
+
+#: option.c:3288
+msgid "E520: Not allowed in a modeline"
+msgstr "E520: ¤£¯à¦b Modeline ¸Ì¥X²{"
+
+#: option.c:3344
+msgid ""
+"\n"
+"\tLast set from "
+msgstr ""
+"\n"
+"\t¤W¦¸³]©w: "
+
+#: option.c:3483
+msgid "E521: Number required after ="
+msgstr "E521: = «á»Ý­n¦³¼Æ¦r"
+
+#: option.c:3797 option.c:4413
+msgid "E522: Not found in termcap"
+msgstr "E522: Termcap ¸Ì­±§ä¤£¨ì"
+
+#: option.c:3863
+#, c-format
+msgid "E539: Illegal character <%s>"
+msgstr "E539: ¤£¥¿½Tªº¦r¤¸ <%s>"
+
+#: option.c:4405
+msgid "E529: Cannot set 'term' to empty string"
+msgstr "E529: µLªk³]©w 'term' ¬°ªÅ¦r¦ê"
+
+#: option.c:4408
+msgid "E530: Cannot change term in GUI"
+msgstr "E530: ¦b¹Ï«¬¬É­±¤¤µLªk¤Á´« term"
+
+#: option.c:4410
+msgid "E531: Use \":gui\" to start the GUI"
+msgstr "E531: ¿é¤J \":gui\" ¨Ó±Ò°Ê¹Ï§Î¬É­±"
+
+#: option.c:4431
+msgid "E589: 'backupext' and 'patchmode' are equal"
+msgstr "E589: 'backupext' ¸ò 'patchmode' ¬O¤@¼Ëªº"
+
+#: option.c:4616
+msgid "E617: Cannot be changed in the GTK+ 2 GUI"
+msgstr "E617: ¦b¹Ï«¬¬É­±¤¤µLªk¤Á´« term"
+
+#: option.c:4748
+msgid "E524: Missing colon"
+msgstr "E524: ¯Ê¤Ö colon"
+
+#: option.c:4750
+msgid "E525: Zero length string"
+msgstr "E525: ¹sªø«×¦r¦ê"
+
+#: option.c:4818
+#, c-format
+msgid "E526: Missing number after <%s>"
+msgstr "E526: <%s> «á¯Ê¤Ö¼Æ¦r"
+
+#: option.c:4832
+msgid "E527: Missing comma"
+msgstr "E527: ¯Ê¤Ö³r¸¹"
+
+#: option.c:4839
+msgid "E528: Must specify a ' value"
+msgstr "E528: ¥²»Ý«ü©w¤@­Ó ' ­È"
+
+#: option.c:4880
+msgid "E595: contains unprintable or wide character"
+msgstr "E595: ¤º§tµLªkÅã¥Üªº¦r¤¸"
+
+#: option.c:4929
+msgid "E596: Invalid font(s)"
+msgstr "E596: ¤£¥¿½Tªº¦r«¬"
+
+#: option.c:4937
+msgid "E597: can't select fontset"
+msgstr "E597: µLªk¨Ï¥Î¦r«¬¶°(Fontset)"
+
+#: option.c:4939
+msgid "E598: Invalid fontset"
+msgstr "E598: ¤£¥¿½Tªº¦r«¬¶°(Fontset)"
+
+#: option.c:4946
+msgid "E533: can't select wide font"
+msgstr "E533: µLªk¨Ï¥Î³]©wªº¤¤¤å¦r«¬(Widefont)"
+
+#: option.c:4948
+msgid "E534: Invalid wide font"
+msgstr "E534: ¤£¥¿½Tªº¦r«¬(Widefont)"
+
+#: option.c:5218
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: <%c> «á¦³¤£¥¿½Tªº¦r¤¸"
+
+#: option.c:5322
+msgid "E536: comma required"
+msgstr "E536: »Ý­n³r¸¹"
+
+#: option.c:5330
+#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: 'commentstring' ¥²»Ý¬OªÅ¥Õ©Î¥]§t %s"
+
+#: option.c:5377
+msgid "E538: No mouse support"
+msgstr "E538: ¤£¤ä´©·Æ¹«"
+
+#: option.c:5645
+msgid "E540: Unclosed expression sequence"
+msgstr "E540: ¨S¦³µ²§ôªº¹Bºâ¦¡: "
+
+#: option.c:5649
+msgid "E541: too many items"
+msgstr "E541: ¤Ó¦h¶µ¥Ø"
+
+#: option.c:5651
+msgid "E542: unbalanced groups"
+msgstr "E542: ¤£¹ïºÙªº group"
+
+#: option.c:5872
+msgid "E590: A preview window already exists"
+msgstr "E590: ¹wµøªºµøµ¡¤w¸g¦s¦b¤F"
+
+#: option.c:6346
+#, c-format
+msgid "E593: Need at least %d lines"
+msgstr "E593: ¦Ü¤Ö»Ý­n %d ¦æ"
+
+#: option.c:6355
+#, c-format
+msgid "E594: Need at least %d columns"
+msgstr "E594: ¦Ü¤Ö»Ý­n %d Äæ"
+
+#: option.c:6660
+#, c-format
+msgid "E355: Unknown option: %s"
+msgstr "E355: ¤£¥¿½Tªº¿ï¶µ: %s"
+
+#: option.c:6769
+msgid ""
+"\n"
+"--- Terminal codes ---"
+msgstr ""
+"\n"
+"--- ²×ºÝ¾÷½X ---"
+
+#: option.c:6771
+msgid ""
+"\n"
+"--- Global option values ---"
+msgstr ""
+"\n"
+"--- Global ¿ï¶µ­È ---"
+
+#: option.c:6773
+msgid ""
+"\n"
+"--- Local option values ---"
+msgstr ""
+"\n"
+"--- Local ¿ï¶µ­È ---"
+
+#: option.c:6775
+msgid ""
+"\n"
+"--- Options ---"
+msgstr ""
+"\n"
+"--- ¿ï¶µ ---"
+
+#: option.c:7467
+msgid "E356: get_varp ERROR"
+msgstr "E356: get_varp ¿ù»~"
+
+#: option.c:8425
+#, c-format
+msgid "E357: 'langmap': Matching character missing for %s"
+msgstr "E357: 'langmap': §ä¤£¨ì %s ¹ïÀ³ªº¦r¤¸"
+
+#: option.c:8459
+#, c-format
+msgid "E358: 'langmap': Extra characters after semicolon: %s"
+msgstr "E358: 'langmap': ¤À¸¹«á¦³¦h¾lªº¦r¤¸: %s"
+
+#: os_amiga.c:273
+msgid "cannot open "
+msgstr "¤£¯à¶}±Ò"
+
+#: os_amiga.c:307
+msgid "VIM: Can't open window!\n"
+msgstr "VIM: µLªk¶}±Òµøµ¡!\n"
+
+#: os_amiga.c:329
+msgid "Need Amigados version 2.04 or later\n"
+msgstr "»Ý­n Amigados ª©¥» 2.04 ¥H¤W\n"
+
+#: os_amiga.c:335
+#, c-format
+msgid "Need %s version %ld\n"
+msgstr "»Ý­n %s ª©¥» %ld\n"
+
+#: os_amiga.c:407
+msgid "Cannot open NIL:\n"
+msgstr "µLªk¶}±Ò NIL:\n"
+
+#: os_amiga.c:418
+msgid "Cannot create "
+msgstr "¤£¯à«Ø¥ß "
+
+#: os_amiga.c:896
+#, c-format
+msgid "Vim exiting with %d\n"
+msgstr "Vim µ²§ô¶Ç¦^­È: %d\n"
+
+#: os_amiga.c:928
+msgid "cannot change console mode ?!\n"
+msgstr "µLªk¤Á´«¥D±±¥x(console)¼Ò¦¡ !?\n"
+
+#: os_amiga.c:994
+msgid "mch_get_shellsize: not a console??\n"
+msgstr "mch_get_shellsize: ¤£¬O¥D±±¥x(console)??\n"
+
+#. if Vim opened a window: Executing a shell may cause crashes
+#: os_amiga.c:1143
+msgid "E360: Cannot execute shell with -f option"
+msgstr "E360: ¤£¯à¥Î -f ¿ï¶µ°õ¦æ shell"
+
+#: os_amiga.c:1184 os_amiga.c:1274
+msgid "Cannot execute "
+msgstr "¤£¯à°õ¦æ "
+
+#: os_amiga.c:1187 os_amiga.c:1284
+msgid "shell "
+msgstr "shell "
+
+#: os_amiga.c:1207 os_amiga.c:1309
+msgid " returned\n"
+msgstr " ¤wªð¦^\n"
+
+#: os_amiga.c:1450
+msgid "ANCHOR_BUF_SIZE too small."
+msgstr "ANCHOR_BUF_SIZE ¤Ó¤p"
+
+#: os_amiga.c:1454
+msgid "I/O ERROR"
+msgstr "I/O ¿ù»~"
+
+#: os_mswin.c:515
+msgid "...(truncated)"
+msgstr "...(¤w¤Á±¼)"
+
+#: os_mswin.c:617
+msgid "'columns' is not 80, cannot execute external commands"
+msgstr "'columns' ¤£¬O 80, µLªk°õ¦æ¥~³¡©R¥O"
+
+#: os_mswin.c:1802
+msgid "E237: Printer selection failed"
+msgstr "E237: µLªk¿ï¾Ü¦¹¦Lªí¾÷"
+
+#: os_mswin.c:1842
+#, c-format
+msgid "to %s on %s"
+msgstr "¨ì %s on %s"
+
+#: os_mswin.c:1857
+#, c-format
+msgid "E613: Unknown printer font: %s"
+msgstr "E613: ¤£¥¿½Tªº¦Lªí¾÷¦r«¬: %s"
+
+#: os_mswin.c:1907 os_mswin.c:1917
+#, c-format
+msgid "E238: Print error: %s"
+msgstr "E238: ¦C¦L¿ù»~: %s"
+
+#: os_mswin.c:1918
+msgid "Unknown"
+msgstr "¥¼ª¾"
+
+#: os_mswin.c:1945
+#, c-format
+msgid "Printing '%s'"
+msgstr "¦C¦L¤¤: '%s'"
+
+#: os_mswin.c:3033
+#, c-format
+msgid "E244: Illegal charset name \"%s\" in font name \"%s\""
+msgstr "E244: ¦r¤¸¶° \"%s\" µLªk¹ïÀ³¦r«¬\"%s\""
+
+#: os_mswin.c:3041
+#, c-format
+msgid "E245: Illegal char '%c' in font name \"%s\""
+msgstr "E245: ¤£¥¿½Tªº¦r¤¸ '%c' ¥X²{¦b¦r«¬¦WºÙ \"%s\" ¤º"
+
+#: os_riscos.c:1258
+msgid "E366: Invalid 'osfiletype' option - using Text"
+msgstr "E366: ¤£¥¿½Tªº 'filetype' ¿ï¶µ - ¨Ï¥Î¯Â¤å¦r¼Ò¦¡"
+
+#: os_unix.c:871
+msgid "Vim: Double signal, exiting\n"
+msgstr "Vim: Âù­«signal, Â÷¶}¤¤\n"
+
+#: os_unix.c:877
+#, c-format
+msgid "Vim: Caught deadly signal %s\n"
+msgstr "Vim: CVim: ÄdºI¨ì«H¸¹(signal) %s\n"
+
+#: os_unix.c:880
+msgid "Vim: Caught deadly signal\n"
+msgstr "Vim: ÄdºI¨ì­P©Rªº«H¸¹(deadly signale)\n"
+
+#: os_unix.c:1143
+#, c-format
+msgid "Opening the X display took %ld msec"
+msgstr "¶}±Ò X Window ¯Ó®É %ld msec"
+
+#: os_unix.c:1170
+msgid ""
+"\n"
+"Vim: Got X error\n"
+msgstr ""
+"\n"
+"Vim: X ¿ù»~\n"
+
+#: os_unix.c:1276
+msgid "Testing the X display failed"
+msgstr "´ú¸Õ X Window ¥¢±Ñ"
+
+#: os_unix.c:1415
+msgid "Opening the X display timed out"
+msgstr "¶}±Ò X Window ¹O®É"
+
+#: os_unix.c:3145 os_unix.c:3825
+msgid ""
+"\n"
+"Cannot execute shell "
+msgstr ""
+"\n"
+"¤£¯à°õ¦æ shell"
+
+#: os_unix.c:3193
+msgid ""
+"\n"
+"Cannot execute shell sh\n"
+msgstr ""
+"\n"
+"¤£¯à°õ¦æ shell sh\n"
+
+#: os_unix.c:3197 os_unix.c:3831
+msgid ""
+"\n"
+"shell returned "
+msgstr ""
+"\n"
+"Shell ¤wªð¦^"
+
+#: os_unix.c:3332
+msgid ""
+"\n"
+"Cannot create pipes\n"
+msgstr ""
+"\n"
+"¤£¯à«Ø¥ß pipe ºÞ½u\n"
+
+#: os_unix.c:3347
+msgid ""
+"\n"
+"Cannot fork\n"
+msgstr ""
+"\n"
+"¤£¯à fork\n"
+
+#: os_unix.c:3838
+msgid ""
+"\n"
+"Command terminated\n"
+msgstr ""
+"\n"
+"©R¥O¤w²×µ²\n"
+
+#: os_unix.c:5398
+msgid "Opening the X display failed"
+msgstr "¶}±Ò X Window ¥¢±Ñ"
+
+#: os_vms_mms.c:59
+msgid "At line"
+msgstr "¦b¦æ¸¹ "
+
+#: os_w32exe.c:169
+msgid "Could not load vim32.dll!"
+msgstr "µLªk¸ü¤J vim32.dll¡I"
+
+#: os_w32exe.c:169 os_w32exe.c:179
+msgid "VIM Error"
+msgstr "VIM ¿ù»~"
+
+#: os_w32exe.c:179
+msgid "Could not fix up function pointers to the DLL!"
+msgstr "¤£¯à­×¥¿¨ç¦¡«ü¼Ð¨ì DLL!"
+
+#: os_win16.c:583 os_win32.c:3047
+#, c-format
+msgid "shell returned %d"
+msgstr "Shell ¶Ç¦^­È %d"
+
+#: os_win32.c:2505
+#, c-format
+msgid "Vim: Caught %s event\n"
+msgstr "Vim: ÄdºI¨ì %s \n"
+
+#: os_win32.c:2507
+msgid "close"
+msgstr "Ãö³¬"
+
+#: os_win32.c:2509
+msgid "logoff"
+msgstr "µn¥X"
+
+#: os_win32.c:2510
+msgid "shutdown"
+msgstr "Ãö¾÷"
+
+#: os_win32.c:3000
+msgid "E371: Command not found"
+msgstr "E371: §ä¤£¨ì©R¥O"
+
+#: os_win32.c:3013
+msgid ""
+"VIMRUN.EXE not found in your $PATH.\n"
+"External commands will not pause after completion.\n"
+"See :help win32-vimrun for more information."
+msgstr ""
+"¦b§Aªº $PATH ¤¤§ä¤£¨ì VIMRUN.EXE.\n"
+"¥~³¡©R¥O°õ¦æ§¹²¦«á±N¤£·|¼È°±.\n"
+"¶i¤@¨B»¡©ú½Ð°õ¦æ :help win32-vimrun "
+
+#: os_win32.c:3016
+msgid "Vim Warning"
+msgstr "Vim ĵ§i"
+
+#: quickfix.c:258
+#, c-format
+msgid "E372: Too many %%%c in format string"
+msgstr "E372: ®æ¦¡¤Æ¦r¦ê¸Ì¦³¤Ó¦h %%%c "
+
+#: quickfix.c:271
+#, c-format
+msgid "E373: Unexpected %%%c in format string"
+msgstr "E373: ®æ¦¡¤Æ¦r¦ê¤£À³¸Ó¥X²{ %%%c "
+
+#: quickfix.c:325
+msgid "E374: Missing ] in format string"
+msgstr "E374: ®æ¦¡¤Æ¦r¦ê¸Ì¤Ö¤F ]"
+
+#: quickfix.c:339
+#, c-format
+msgid "E375: Unsupported %%%c in format string"
+msgstr "E375: ®æ¦¡¤Æ¦r¦ê¸Ì¦³¤£¤ä´©ªº %%%c "
+
+#: quickfix.c:357
+#, c-format
+msgid "E376: Invalid %%%c in format string prefix"
+msgstr "E376: ®æ¦¡¤Æ¦r¦ê¶}ÀY¸Ì¦³¤£¥¿½Tªº %%%c "
+
+#: quickfix.c:365
+#, c-format
+msgid "E377: Invalid %%%c in format string"
+msgstr "E377: ®æ¦¡¤Æ¦r¦ê¸Ì¦³¤£¥¿½Tªº %%%c "
+
+#: quickfix.c:391
+msgid "E378: 'errorformat' contains no pattern"
+msgstr "E378: 'errorformat' ¥¼³]©w"
+
+#: quickfix.c:497
+msgid "E379: Missing or empty directory name"
+msgstr "E379: §ä¤£¨ì¥Ø¿ý¦WºÙ©Î¬OªÅªº¥Ø¿ý¦WºÙ"
+
+#: quickfix.c:979
+msgid "E553: No more items"
+msgstr "E553: ¨S¦³¨ä¥¦¶µ¥Ø"
+
+#: quickfix.c:1200
+#, c-format
+msgid "(%d of %d)%s%s: "
+msgstr "(%d / %d)%s%s: "
+
+#: quickfix.c:1202
+msgid " (line deleted)"
+msgstr " (¦æ¤w§R°£)"
+
+#: quickfix.c:1412
+msgid "E380: At bottom of quickfix stack"
+msgstr "E380: Quickfix °ïÅ|µ²§À"
+
+#: quickfix.c:1421
+msgid "E381: At top of quickfix stack"
+msgstr "E381: Quickfix °ïÅ|³»ºÝ"
+
+#: quickfix.c:1433
+#, c-format
+msgid "error list %d of %d; %d errors"
+msgstr "¿ù»~¦Cªí %d/%d; ¦@¦³ %d ¶µ¿ù»~"
+
+#: quickfix.c:1904
+msgid "E382: Cannot write, 'buftype' option is set"
+msgstr "E382: µLªk¼g¤J¡A'buftype' ¿ï¶µ¤w³]©w"
+
+#: regexp.c:319
+#, c-format
+msgid "E369: invalid item in %s%%[]"
+msgstr "E369: ¤£¥¿½Tªº¶µ¥Ø¡G %s%%[]"
+
+#: regexp.c:826
+msgid "E339: Pattern too long"
+msgstr "E339: ¦W¦r¤Óªø"
+
+#: regexp.c:995
+msgid "E50: Too many \\z("
+msgstr "E50: ¤Ó¦h \\z("
+
+#: regexp.c:1006
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: ¤Ó¦h %s("
+
+#: regexp.c:1063
+msgid "E52: Unmatched \\z("
+msgstr "E52: µL¹ïÀ³ªº \\z("
+
+#: regexp.c:1067
+#, c-format
+msgid "E53: Unmatched %s%%("
+msgstr "E53: µL¹ïÀ³ªº %s%%("
+
+#: regexp.c:1069
+#, c-format
+msgid "E54: Unmatched %s("
+msgstr "E54: µL¹ïÀ³ªº %s("
+
+#: regexp.c:1074
+#, c-format
+msgid "E55: Unmatched %s)"
+msgstr "E55: µL¹ïÀ³ªº %s)"
+
+#: regexp.c:1237
+#, c-format
+msgid "E56: %s* operand could be empty"
+msgstr "E56: %s* ¹Bºâ¤¸¥i¥H¬OªÅªº"
+
+#: regexp.c:1240
+#, c-format
+msgid "E57: %s+ operand could be empty"
+msgstr "E56: %s+ ¹Bºâ¤¸¥i¥H¬OªÅªº"
+
+#: regexp.c:1294
+#, c-format
+msgid "E59: invalid character after %s@"
+msgstr "E59: «á­±¦³¤£¥¿½Tªº¦r¤¸: %s@"
+
+#: regexp.c:1319
+#, c-format
+msgid "E58: %s{ operand could be empty"
+msgstr "E58: %s{ ¹Bºâ¤¸¥i¥H¬OªÅªº"
+
+#: regexp.c:1329
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: ¤Ó¦h½ÆÂøªº %s{...}s"
+
+#: regexp.c:1345
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: ±_ª¬ %s*"
+
+#: regexp.c:1348
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: ±_ª¬ %s%c"
+
+#: regexp.c:1466
+msgid "E63: invalid use of \\_"
+msgstr "E63: ¤£¥¿½Tªº¨Ï¥Î \\_"
+
+#: regexp.c:1511
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c ¨S¦³±µªF¦è"
+
+#: regexp.c:1567
+msgid "E65: Illegal back reference"
+msgstr "E65: ¤£¥¿½Tªº¤Ï¦V°Ñ¦Ò"
+
+#: regexp.c:1580
+msgid "E66: \\z( not allowed here"
+msgstr "E66: \\z( ¤£¯à¦b¦¹¥X²{"
+
+#: regexp.c:1599
+msgid "E67: \\z1 et al. not allowed here"
+msgstr "E67: \\z1 et al. ¤£¯à¦b¦¹¥X²{"
+
+#: regexp.c:1610
+msgid "E68: Invalid character after \\z"
+msgstr "E68: «á­±¦³¤£¥¿½Tªº¦r¤¸: \\z"
+
+#: regexp.c:1659
+#, c-format
+msgid "E69: Missing ] after %s%%["
+msgstr "E69: %s%%[ «á¯Ê¤Ö ]"
+
+#: regexp.c:1675
+#, c-format
+msgid "E70: Empty %s%%[]"
+msgstr "E70: ªÅªº %s%%[]"
+
+#: regexp.c:1735
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: «á­±¦³¤£¥¿½Tªº¦r¤¸: %s%%"
+
+#: regexp.c:2530
+#, c-format
+msgid "E554: Syntax error in %s{...}"
+msgstr "E554: »yªk¿ù»~: %s{...}"
+
+#: regexp.c:2777
+msgid "E361: Crash intercepted; regexp too complex?"
+msgstr "E361: µLªk°õ¦æ; regular expression ¤Ó½ÆÂø?"
+
+#: regexp.c:2912
+msgid "E363: pattern caused out-of-stack error"
+msgstr "E363: regular expression ³y¦¨°ïÅ|¥Î¥úªº¿ù»~"
+
+#: regexp.c:3148
+msgid "External submatches:\n"
+msgstr "¥~³¡²Å¦X:\n"
+
+#: screen.c:2103
+#, c-format
+msgid "+--%3ld lines folded "
+msgstr "+--¤w fold %3ld ¦æ"
+
+#: screen.c:7785
+msgid " VREPLACE"
+msgstr " V-¨ú¥N"
+
+#: screen.c:7789
+msgid " REPLACE"
+msgstr " ¨ú¥N"
+
+#: screen.c:7794
+msgid " REVERSE"
+msgstr " ¤ÏÂà"
+
+#: screen.c:7796
+msgid " INSERT"
+msgstr " ´¡¤J"
+
+#: screen.c:7799
+msgid " (insert)"
+msgstr " (´¡¤J)"
+
+#: screen.c:7801
+msgid " (replace)"
+msgstr " (¨ú¥N)"
+
+#: screen.c:7803
+msgid " (vreplace)"
+msgstr " (v-¨ú¥N)"
+
+#: screen.c:7806
+msgid " Hebrew"
+msgstr " Hebrew"
+
+#: screen.c:7814
+msgid " (lang)"
+msgstr " (»y¨¥)"
+
+#: screen.c:7817
+msgid " (paste)"
+msgstr " (¶K¤W)"
+
+#: screen.c:7823
+msgid " SELECT"
+msgstr " ¿ï¨ú"
+
+#: screen.c:7825
+msgid " VISUAL"
+msgstr " ¿ï¨ú"
+
+#: screen.c:7827
+msgid " BLOCK"
+msgstr " °Ï¶ô"
+
+#: screen.c:7829
+msgid " LINE"
+msgstr " ¦æ¿ï¨ú"
+
+#: screen.c:7842 screen.c:7902
+msgid "recording"
+msgstr "°O¿ý¤¤"
+
+#: search.c:36
+msgid "search hit TOP, continuing at BOTTOM"
+msgstr "¤w·j´M¨ìÀɮ׶}ÀY¡F¦A±qµ²§ÀÄ~Äò·j´M"
+
+#: search.c:37
+msgid "search hit BOTTOM, continuing at TOP"
+msgstr "¤w·j´M¨ìÀÉ®×µ²§À¡F¦A±q¶}ÀYÄ~Äò·j´M"
+
+#: search.c:455
+#, c-format
+msgid "E383: Invalid search string: %s"
+msgstr "E383: ¿ù»~ªº·j´M¦r¦ê: %s"
+
+#: search.c:782
+#, c-format
+msgid "E384: search hit TOP without match for: %s"
+msgstr "E384: ¤w·j´M¨ìÀɮ׶}ÀY¤´§ä¤£¨ì %s"
+
+#: search.c:784
+#, c-format
+msgid "E385: search hit BOTTOM without match for: %s"
+msgstr "E385: ¤w·j´M¨ìÀÉ®×µ²§À¤´§ä¤£¨ì %s"
+
+#: search.c:1157
+msgid "E386: Expected '?' or '/' after ';'"
+msgstr "E386: ¦b ';' «á­±À³¸Ó¦³ '?' ©Î '/'"
+
+#: search.c:3567
+msgid " (includes previously listed match)"
+msgstr " (¥]¬A«e¦¸¦C¥X²Å¦X¶µ)"
+
+#. cursor at status line
+#: search.c:3587
+msgid "--- Included files "
+msgstr "--- ¤Þ¤JÀÉ®× "
+
+#: search.c:3589
+msgid "not found "
+msgstr "§ä¤£¨ì "
+
+#: search.c:3590
+msgid "in path ---\n"
+msgstr "---\n"
+
+#: search.c:3629
+msgid " (Already listed)"
+msgstr " (¤w¦C¥X)"
+
+#: search.c:3631
+msgid " NOT FOUND"
+msgstr " §ä¤£¨ì"
+
+#: search.c:3683
+#, c-format
+msgid "Scanning included file: %s"
+msgstr "·j´M¤Þ¤JÀÉ®×: %s"
+
+#: search.c:3901
+msgid "E387: Match is on current line"
+msgstr "E387: ¥Ø«e©Ò¦b¦æ¤¤¦³¤@¤Ç°t"
+
+#: search.c:4041
+msgid "All included files were found"
+msgstr "©Ò¦³¤Þ¤JÀɮ׳£¤w§ä¨ì"
+
+#: search.c:4043
+msgid "No included files"
+msgstr "¨S¦³¤Þ¤JÀÉ®×"
+
+#: search.c:4059
+msgid "E388: Couldn't find definition"
+msgstr "E388: §ä¤£¨ì©w¸q"
+
+#: search.c:4061
+msgid "E389: Couldn't find pattern"
+msgstr "E389: §ä¤£¨ì pattern"
+
+#: syntax.c:3015
+#, c-format
+msgid "E390: Illegal argument: %s"
+msgstr "E390: °Ñ¼Æ¤£¥¿½T: %s"
+
+#: syntax.c:3195
+#, c-format
+msgid "E391: No such syntax cluster: %s"
+msgstr "E391: µL¦¹ syntax cluster: \"%s\""
+
+#: syntax.c:3359
+msgid "No Syntax items defined for this buffer"
+msgstr "³o­Ó½w½Ä°Ï¨S¦³©w¸q¥ô¦ó»yªk"
+
+#: syntax.c:3367
+msgid "syncing on C-style comments"
+msgstr "C»y¨¥¦¡µù¸Ñ¦P¨B¤Æ¤¤"
+
+#: syntax.c:3375
+msgid "no syncing"
+msgstr "¨S¦³¦P¨B¤Æ"
+
+#: syntax.c:3378
+msgid "syncing starts "
+msgstr "¦P¨B¤Æ¶}©l"
+
+#: syntax.c:3380 syntax.c:3455
+msgid " lines before top line"
+msgstr "¦æ¸¹¶W¥X½d³ò"
+
+#: syntax.c:3385
+msgid ""
+"\n"
+"--- Syntax sync items ---"
+msgstr ""
+"\n"
+"--- »yªk¦P¨Bª«¥ó (Syntax sync items) ---"
+
+#: syntax.c:3390
+msgid ""
+"\n"
+"syncing on items"
+msgstr ""
+"\n"
+"¦P¨B¤Æ¤¤:"
+
+#: syntax.c:3396
+msgid ""
+"\n"
+"--- Syntax items ---"
+msgstr ""
+"\n"
+"--- »yªk¶µ¥Ø ---"
+
+#: syntax.c:3419
+#, c-format
+msgid "E392: No such syntax cluster: %s"
+msgstr "E392: µL¦¹ syntax cluster: \"%s\""
+
+#: syntax.c:3445
+msgid "minimal "
+msgstr "³Ì¤p"
+
+#: syntax.c:3452
+msgid "maximal "
+msgstr "³Ì¤j"
+
+#: syntax.c:3464
+msgid "; match "
+msgstr "; ²Å¦X "
+
+#: syntax.c:3466
+msgid " line breaks"
+msgstr "Â_¦æ"
+
+#: syntax.c:4100
+msgid "E393: group[t]here not accepted here"
+msgstr "E393: ¨Ï¥Î¤F¤£¥¿½Tªº°Ñ¼Æ"
+
+#: syntax.c:4124
+#, c-format
+msgid "E394: Didn't find region item for %s"
+msgstr "E394: §ä¤£¨ì %s ªº region item"
+
+#: syntax.c:4152
+msgid "E395: contains argument not accepted here"
+msgstr "E395: ¨Ï¥Î¤F¤£¥¿½Tªº°Ñ¼Æ"
+
+#: syntax.c:4163
+msgid "E396: containedin argument not accepted here"
+msgstr "E396: ¨Ï¥Î¤F¤£¥¿½Tªº°Ñ¼Æ"
+
+#: syntax.c:4241
+msgid "E397: Filename required"
+msgstr "E397: »Ý­nÀɮצWºÙ"
+
+#: syntax.c:4579
+#, c-format
+msgid "E398: Missing '=': %s"
+msgstr "E398: ¯Ê¤Ö \"=\": %s"
+
+#: syntax.c:4737
+#, c-format
+msgid "E399: Not enough arguments: syntax region %s"
+msgstr "E399: syntax region %s ªº¤Þ¼Æ¤Ó¤Ö"
+
+#: syntax.c:5068
+msgid "E400: No cluster specified"
+msgstr "E400: ¨S¦³«ü©wªºÄÝ©Ê"
+
+#: syntax.c:5105
+#, c-format
+msgid "E401: Pattern delimiter not found: %s"
+msgstr "E401: §ä¤£¨ì¤À¹j²Å¸¹: %s"
+
+#: syntax.c:5180
+#, c-format
+msgid "E402: Garbage after pattern: %s"
+msgstr "E402: '%s' «á­±ªºªF¦èµLªk¿ëÃÑ"
+
+#: syntax.c:5270
+msgid "E403: syntax sync: line continuations pattern specified twice"
+msgstr "E403: »yªk¦P¨B: ³s±µ¦æ²Å¸¹³Q«ü©w¤F¨â¦¸"
+
+#: syntax.c:5327
+#, c-format
+msgid "E404: Illegal arguments: %s"
+msgstr "E404: °Ñ¼Æ¤£¥¿½T: %s"
+
+#: syntax.c:5377
+#, c-format
+msgid "E405: Missing equal sign: %s"
+msgstr "E405: ¯Ê¤Ö¬Ûµ¥²Å¸¹: %s"
+
+#: syntax.c:5383
+#, c-format
+msgid "E406: Empty argument: %s"
+msgstr "E406: ªÅ¥Õ°Ñ¼Æ: %s"
+
+#: syntax.c:5410
+#, c-format
+msgid "E407: %s not allowed here"
+msgstr "E407: %s ¤£¯à¦b¦¹¥X²{"
+
+#: syntax.c:5417
+#, c-format
+msgid "E408: %s must be first in contains list"
+msgstr "E408: %s ¥²¶·¬O¦Cªí¸Ìªº²Ä¤@­Ó"
+
+#: syntax.c:5487
+#, c-format
+msgid "E409: Unknown group name: %s"
+msgstr "E409: ¤£¥¿½Tªº¸s²Õ¦WºÙ: %s"
+
+#: syntax.c:5720
+#, c-format
+msgid "E410: Invalid :syntax subcommand: %s"
+msgstr "E410: ¤£¥¿½Tªº :syntax ¤l©R¥O: %s"
+
+#: syntax.c:6099
+#, c-format
+msgid "E411: highlight group not found: %s"
+msgstr "E411: §ä¤£¨ì highlight group: %s"
+
+#: syntax.c:6123
+#, c-format
+msgid "E412: Not enough arguments: \":highlight link %s\""
+msgstr "E412: °Ñ¼Æ¤Ó¤Ö: \":highlight link %s\""
+
+#: syntax.c:6130
+#, c-format
+msgid "E413: Too many arguments: \":highlight link %s\""
+msgstr "E413: °Ñ¼Æ¹L¦h: \":highlight link %s\""
+
+#: syntax.c:6150
+msgid "E414: group has settings, highlight link ignored"
+msgstr "E414: ¤w³]©w¸s²Õ, ©¿²¤ highlight link"
+
+#: syntax.c:6279
+#, c-format
+msgid "E415: unexpected equal sign: %s"
+msgstr "E415: ¤£¸Ó¦³ªºµ¥¸¹: %s"
+
+#: syntax.c:6315
+#, c-format
+msgid "E416: missing equal sign: %s"
+msgstr "E416: ¯Ê¤Ö¬Ûµ¥²Å¸¹: %s"
+
+#: syntax.c:6337
+#, c-format
+msgid "E417: missing argument: %s"
+msgstr "E417: ¯Ê¤Ö°Ñ¼Æ: %s"
+
+#: syntax.c:6374
+#, c-format
+msgid "E418: Illegal value: %s"
+msgstr "E418: ¤£¦Xªkªº­È: %s"
+
+#: syntax.c:6493
+msgid "E419: FG color unknown"
+msgstr "E419: ¿ù»~ªº«e´ºÃC¦â"
+
+#: syntax.c:6504
+msgid "E420: BG color unknown"
+msgstr "E420: ¿ù»~ªº­I´ºÃC¦â"
+
+#: syntax.c:6565
+#, c-format
+msgid "E421: Color name or number not recognized: %s"
+msgstr "E421: ¿ù»~ªºÃC¦â¦WºÙ©Î¼Æ­È: %s"
+
+#: syntax.c:6771
+#, c-format
+msgid "E422: terminal code too long: %s"
+msgstr "E422: ²×ºÝ¾÷½X¤Óªø: %s"
+
+#: syntax.c:6818
+#, c-format
+msgid "E423: Illegal argument: %s"
+msgstr "E423: °Ñ¼Æ¤£¥¿½T: %s"
+
+#: syntax.c:7347
+msgid "E424: Too many different highlighting attributes in use"
+msgstr "E424: ¨Ï¥Î¤F¹L¦h¬Û²§ªº°ª«G«×ÄÝ©Ê"
+
+#: tag.c:90
+msgid "E555: at bottom of tag stack"
+msgstr "E555: ¼ÐÅÒ(tag)°ïÅ|µ²§À"
+
+#: tag.c:91
+msgid "E556: at top of tag stack"
+msgstr "E556: ¼ÐÅÒ(tag)°ïÅ|¶}ÀY"
+
+#: tag.c:392
+msgid "E425: Cannot go before first matching tag"
+msgstr "E425: ¤w¸g¦b³Ì«e­±ªº¼ÐÅÒ(tag)¤F"
+
+#: tag.c:512
+#, c-format
+msgid "E426: tag not found: %s"
+msgstr "E426: §ä¤£¨ì¼ÐÅÒ(tag): %s"
+
+#: tag.c:545
+msgid " # pri kind tag"
+msgstr " # pri kind tag"
+
+#: tag.c:548
+msgid "file\n"
+msgstr "ÀÉ®×\n"
+
+#.
+#. * Ask to select a tag from the list.
+#. * When using ":silent" assume that <CR> was entered.
+#.
+#: tag.c:706
+msgid "Enter nr of choice (<CR> to abort): "
+msgstr "¿é¤J nr ©Î¿ï¾Ü (<CR> Â÷¶}): "
+
+#: tag.c:746
+msgid "E427: There is only one matching tag"
+msgstr "E427: ¥u¦³¦¹¶µ²Å¦X"
+
+#: tag.c:748
+msgid "E428: Cannot go beyond last matching tag"
+msgstr "E428: ¤v¸g¦b³Ì«á¤@­Ó²Å¦Xªº tag ¤F"
+
+#: tag.c:768
+#, c-format
+msgid "File \"%s\" does not exist"
+msgstr "ÀÉ®× \"%s\" ¤£¦s¦b"
+
+#. Give an indication of the number of matching tags
+#: tag.c:780
+#, c-format
+msgid "tag %d of %d%s"
+msgstr "§ä¨ì tag: %d/%d%s"
+
+#: tag.c:783
+msgid " or more"
+msgstr " ©Î§ó¦h"
+
+#: tag.c:785
+msgid " Using tag with different case!"
+msgstr " ¥H¤£¦P¤j¤p¼g¨Ó¨Ï¥Î tag!"
+
+#: tag.c:828
+#, c-format
+msgid "E429: File \"%s\" does not exist"
+msgstr "E429: ÀÉ®× \"%s\" ¤£¦s¦b"
+
+#. Highlight title
+#: tag.c:897
+msgid ""
+"\n"
+" # TO tag FROM line in file/text"
+msgstr ""
+"\n"
+" # ¨ì tag ±q ¦æ ¦b ÀÉ®×/¤å¦r"
+
+#: tag.c:1144
+msgid "Linear tag search"
+msgstr "½u©Ê·j´M¼ÐÅÒ (Tags)"
+
+#: tag.c:1146
+msgid "Binary tag search"
+msgstr "¤G¤À·j´M(Binary search) ¼ÐÅÒ(Tags)"
+
+#: tag.c:1172
+#, c-format
+msgid "Searching tags file %s"
+msgstr "·j´M tag ÀÉ®× \"%s\""
+
+#: tag.c:1356
+#, c-format
+msgid "E430: Tag file path truncated for %s\n"
+msgstr "E430: Tag Àɮ׸ô®|³QºIÂ_¬° %s\n"
+
+#: tag.c:1858
+#, c-format
+msgid "E431: Format error in tags file \"%s\""
+msgstr "E431: Tag ÀÉ \"%s\" ®æ¦¡¿ù»~"
+
+#: tag.c:1862
+#, c-format
+msgid "Before byte %ld"
+msgstr "¦b %ld ¦ì¤¸¤§«e"
+
+#: tag.c:1883
+#, c-format
+msgid "E432: Tags file not sorted: %s"
+msgstr "E432: Tag ÀÉ®×¥¼±Æ§Ç: %s"
+
+#. never opened any tags file
+#: tag.c:1922
+msgid "E433: No tags file"
+msgstr "E433: ¨S¦³ tag ÀÉ"
+
+#: tag.c:2600
+msgid "E434: Can't find tag pattern"
+msgstr "E434: §ä¤£¨ì tag"
+
+#: tag.c:2611
+msgid "E435: Couldn't find tag, just guessing!"
+msgstr "E435: §ä¤£¨ì tag, ¥Î²qªº!"
+
+#: term.c:1745
+msgid "' not known. Available builtin terminals are:"
+msgstr "' µLªk¸ü¤J¡C¥i¥Îªº¤º«Ø²×ºÝ¾÷§Î¦¡¦³:"
+
+#: term.c:1769
+msgid "defaulting to '"
+msgstr "¹w³]: '"
+
+#: term.c:2127
+msgid "E557: Cannot open termcap file"
+msgstr "E557: µLªk¶}±Ò termcap ÀÉ®×"
+
+#: term.c:2131
+msgid "E558: Terminal entry not found in terminfo"
+msgstr "E558: terminfo ¤¤¨S¦³²×ºÝ¾÷¸ê®Æ¶µ"
+
+#: term.c:2133
+msgid "E559: Terminal entry not found in termcap"
+msgstr "E559: termcap ¤¤¨S¦³²×ºÝ¾÷¸ê®Æ¶µ"
+
+#: term.c:2292
+#, c-format
+msgid "E436: No \"%s\" entry in termcap"
+msgstr "E436: termcap ¨S¦³ \"%s\" entry"
+
+#: term.c:2766
+msgid "E437: terminal capability \"cm\" required"
+msgstr "E437: ²×ºÝ¾÷»Ý­n \"cm\" ªº¯à¤O"
+
+#. Highlight title
+#: term.c:4927
+msgid ""
+"\n"
+"--- Terminal keys ---"
+msgstr ""
+"\n"
+"--- ²×ºÝ¾÷«öÁä ---"
+
+#: ui.c:252
+msgid "new shell started\n"
+msgstr "°_°Ê·s shell\n"
+
+#: ui.c:1784
+msgid "Vim: Error reading input, exiting...\n"
+msgstr "Vim: Ū¨ú¿é¤J¿ù»~¡AÂ÷¶}¤¤...\n"
+
+#. must display the prompt
+#: undo.c:394
+msgid "No undo possible; continue anyway"
+msgstr "µLªkÁÙ­ì¡F½ÐÄ~Äò§V¤O"
+
+#: undo.c:549
+msgid "E438: u_undo: line numbers wrong"
+msgstr "E438: u_undo: ¦æ¸¹¿ù»~"
+
+#: undo.c:718
+msgid "1 change"
+msgstr "¤@¶µ§ïÅÜ"
+
+#: undo.c:720
+#, c-format
+msgid "%ld changes"
+msgstr "%ld ¶µ§ïÅÜ"
+
+#: undo.c:764
+msgid "E439: undo list corrupt"
+msgstr "E439: ´_­ì¦Cªí·lÃa"
+
+#: undo.c:796
+msgid "E440: undo line missing"
+msgstr "E440: §ä¤£¨ì­n undo ªº¦æ"
+
+#. Only MS VC 4.1 and earlier can do Win32s
+#: version.c:682
+msgid ""
+"\n"
+"MS-Windows 16/32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 16/32 Bit ¹Ï«¬¬É­±ª©¥»"
+
+#: version.c:684
+msgid ""
+"\n"
+"MS-Windows 32 bit GUI version"
+msgstr ""
+"\n"
+"MS-Windows 32 Bit ¹Ï«¬¬É­±ª©¥»"
+
+#: version.c:687
+msgid " in Win32s mode"
+msgstr "Win32s ¼Ò¦¡"
+
+#: version.c:689
+msgid " with OLE support"
+msgstr "¤ä´© OLE"
+
+#: version.c:692
+msgid ""
+"\n"
+"MS-Windows 32 bit console version"
+msgstr ""
+"\n"
+"MS-Windows 32 Bit console ª©¥»"
+
+#: version.c:696
+msgid ""
+"\n"
+"MS-Windows 16 bit version"
+msgstr ""
+"\n"
+"MS-Windows 32 Bit console ª©¥»"
+
+#: version.c:700
+msgid ""
+"\n"
+"32 bit MS-DOS version"
+msgstr ""
+"\n"
+"32 Bit MS-DOS ª©¥»"
+
+#: version.c:702
+msgid ""
+"\n"
+"16 bit MS-DOS version"
+msgstr ""
+"\n"
+"16 Bit MS-DOS ª©¥»"
+
+#: version.c:708
+msgid ""
+"\n"
+"MacOS X (unix) version"
+msgstr ""
+"\n"
+"MacOS X (unix) ª©¥»"
+
+#: version.c:710
+msgid ""
+"\n"
+"MacOS X version"
+msgstr ""
+"\n"
+"MacOS X ª©¥»"
+
+#: version.c:713
+msgid ""
+"\n"
+"MacOS version"
+msgstr ""
+"\n"
+"MacOS ª©¥»"
+
+#: version.c:718
+msgid ""
+"\n"
+"RISC OS version"
+msgstr ""
+"\n"
+"RISC OS ª©¥»"
+
+#: version.c:728
+msgid ""
+"\n"
+"Included patches: "
+msgstr ""
+"\n"
+"¤Þ¤J­×¥¿: "
+
+#: version.c:754 version.c:1097
+msgid "Modified by "
+msgstr "­×§ïªÌ¬°"
+
+#: version.c:761
+msgid ""
+"\n"
+"Compiled "
+msgstr ""
+"\n"
+"½sĶ"
+
+#: version.c:764
+msgid "by "
+msgstr "ªÌ:"
+
+#: version.c:776
+msgid ""
+"\n"
+"Huge version "
+msgstr ""
+"\n"
+"¶W±jª©¥» "
+
+#: version.c:779
+msgid ""
+"\n"
+"Big version "
+msgstr ""
+"\n"
+"¤j«¬ª©¥» "
+
+#: version.c:782
+msgid ""
+"\n"
+"Normal version "
+msgstr ""
+"\n"
+"¤@¯ëª©¥» "
+
+#: version.c:785
+msgid ""
+"\n"
+"Small version "
+msgstr ""
+"\n"
+"²©öª©¥» "
+
+#: version.c:787
+msgid ""
+"\n"
+"Tiny version "
+msgstr ""
+"\n"
+"ºë²ª©¥» "
+
+#: version.c:793
+msgid "without GUI."
+msgstr "¤£¨Ï¥Î¹Ï«¬¬É­±¡C"
+
+#: version.c:798
+msgid "with GTK2-GNOME GUI."
+msgstr "¨Ï¥Î GTK2-GNOME ¹Ï«¬¬É­±¡C"
+
+#: version.c:800
+msgid "with GTK-GNOME GUI."
+msgstr "¨Ï¥Î GTK-GNOME ¹Ï«¬¬É­±¡C"
+
+#: version.c:804
+msgid "with GTK2 GUI."
+msgstr "¨Ï¥Î GTK2 ¹Ï«¬¬É­±¡C"
+
+#: version.c:806
+msgid "with GTK GUI."
+msgstr "¨Ï¥Î GTK ¹Ï«¬¬É­±¡C"
+
+#: version.c:811
+msgid "with X11-Motif GUI."
+msgstr "¨Ï¥Î X11-Motif ¹Ï«¬¬É­±¡C"
+
+#: version.c:814
+msgid "with X11-Athena GUI."
+msgstr "¨Ï¥Î X11-Athena ¹Ï«¬¬É­±¡C"
+
+#: version.c:817
+msgid "with BeOS GUI."
+msgstr "¨Ï¥Î BeOS ¹Ï«¬¬É­±¡C"
+
+#: version.c:820
+msgid "with Photon GUI."
+msgstr "¨Ï¥ÎPhoton¹Ï«¬¬É­±¡C"
+
+#: version.c:823
+msgid "with GUI."
+msgstr "¨Ï¥Î¹Ï«¬¬É­±¡C"
+
+#: version.c:826
+msgid "with Carbon GUI."
+msgstr "¨Ï¥Î Carbon ¹Ï«¬¬É­±¡C"
+
+#: version.c:829
+msgid "with Cocoa GUI."
+msgstr "¨Ï¥Î Cocoa ¹Ï«¬¬É­±¡C"
+
+#: version.c:832
+msgid "with (classic) GUI."
+msgstr "¨Ï¥Î (¶Ç²Î) ¹Ï«¬¬É­±¡C"
+
+#: version.c:843
+msgid " Features included (+) or not (-):\n"
+msgstr " ¥Ø«e¥i¨Ï¥Î(+)»P¤£¥i¨Ï¥Î(-)ªº¼Ò²Õ¦Cªí:\n"
+
+#: version.c:855
+msgid " system vimrc file: \""
+msgstr " ¨t²Î vimrc ³]©wÀÉ: \""
+
+#: version.c:860
+msgid " user vimrc file: \""
+msgstr " ¨Ï¥ÎªÌ­Ó¤H vimrc ³]©wÀÉ: \""
+
+#: version.c:865
+msgid " 2nd user vimrc file: \""
+msgstr " ²Ä¤G²Õ­Ó¤H vimrc ÀÉ®×: \""
+
+#: version.c:870
+msgid " 3rd user vimrc file: \""
+msgstr " ²Ä¤T²Õ­Ó¤H vimrc ÀÉ®×: \""
+
+#: version.c:875
+msgid " user exrc file: \""
+msgstr " ¨Ï¥ÎªÌ­Ó¤H exrc ³]©wÀÉ: \""
+
+#: version.c:880
+msgid " 2nd user exrc file: \""
+msgstr " ²Ä¤G²Õ¨Ï¥ÎªÌ exrc ÀÉ®×: \""
+
+#: version.c:886
+msgid " system gvimrc file: \""
+msgstr " ¨t²Î gvimrc ÀÉ®×: \""
+
+#: version.c:890
+msgid " user gvimrc file: \""
+msgstr " ¨Ï¥ÎªÌ­Ó¤H gvimrc ÀÉ: \""
+
+#: version.c:894
+msgid "2nd user gvimrc file: \""
+msgstr " ²Ä¤G²Õ­Ó¤H gvimrc ÀÉ®×: \""
+
+#: version.c:899
+msgid "3rd user gvimrc file: \""
+msgstr " ²Ä¤T²Õ­Ó¤H gvimrc ÀÉ®×: \""
+
+#: version.c:906
+msgid " system menu file: \""
+msgstr " ¨t²Î¿ï³æ³]©wÀÉ: \""
+
+#: version.c:914
+msgid " fall-back for $VIM: \""
+msgstr " $VIM ¹w³]­È: \""
+
+#: version.c:920
+msgid " f-b for $VIMRUNTIME: \""
+msgstr " $VIMRUNTIME ¹w³]­È: \""
+
+#: version.c:924
+msgid "Compilation: "
+msgstr "½sĶ¤è¦¡: "
+
+#: version.c:930
+msgid "Compiler: "
+msgstr "½sĶ¾¹: "
+
+#: version.c:935
+msgid "Linking: "
+msgstr "Ãìµ²¤è¦¡: "
+
+#: version.c:940
+msgid " DEBUG BUILD"
+msgstr " °£¿ùª©¥»"
+
+#: version.c:976
+msgid "VIM - Vi IMproved"
+msgstr "VIM - Vi IMproved"
+
+#: version.c:978
+msgid "version "
+msgstr "ª©¥» "
+
+#: version.c:979
+msgid "by Bram Moolenaar et al."
+msgstr "ºûÅ@ªÌ: Bram Moolenaar et al."
+
+#: version.c:983
+msgid "Vim is open source and freely distributable"
+msgstr "Vim ¬°¥i¦Û¥Ñ´²§Gªº¶}©ñ­ì©l½X³nÅé"
+
+#: version.c:985
+msgid "Help poor children in Uganda!"
+msgstr "½ÐÀ°§U¯Q¤z¹Fªº¥i¼¦«Äµ£!"
+
+#: version.c:986
+msgid "type :help iccf<Enter> for information "
+msgstr "¶i¤@¨B»¡©ú½Ð¿é¤J :help iccf<Enter>"
+
+#: version.c:988
+msgid "type :q<Enter> to exit "
+msgstr "­nÂ÷¶}½Ð¿é¤J :q<Enter> "
+
+#: version.c:989
+msgid "type :help<Enter> or <F1> for on-line help"
+msgstr "½u¤W»¡©ú½Ð¿é¤J :help<Enter> "
+
+#: version.c:990
+msgid "type :help version6<Enter> for version info"
+msgstr "·sª©¥»¸ê°T½Ð¿é¤J :help version6<Enter>"
+
+#: version.c:993
+msgid "Running in Vi compatible mode"
+msgstr "Vi ¬Û®e¼Ò¦¡"
+
+#: version.c:994
+msgid "type :set nocp<Enter> for Vim defaults"
+msgstr "¦pªG­n§¹¥þ¼ÒÀÀ¶Ç²Î Vi ½Ð¿é¤J :set nocp<Enter>"
+
+#: version.c:995
+msgid "type :help cp-default<Enter> for info on this"
+msgstr "¦pªG»Ý­n¹ï Vi ¬Û®e¼Ò¦¡ªº¶i¤@¨B»¡©ú½Ð¿é¤J :help cp-default<Enter>"
+
+#: version.c:1010
+msgid "menu Help->Orphans for information "
+msgstr "¶i¤@¨B»¡©ú½Ð¿ï¨ú¿ï³æªº »²§U»¡©ú->¬@±Ï©t¨à"
+
+#: version.c:1012
+msgid "Running modeless, typed text is inserted"
+msgstr "°õ¦æ Modeless ¼Ò¦¡¡A¿é¤Jªº¤å¦r·|¦Û°Ê´¡¤J"
+
+#: version.c:1013
+msgid "menu Edit->Global Settings->Toggle Insert Mode "
+msgstr "¿ï¨ú¿ï³æªº¡u½s¿è¡v¡u¥þ°ì³]©w¡v¡u¤Á´«´¡¤J¼Ò¦¡¡v"
+
+#: version.c:1014
+msgid " for two modes "
+msgstr " ¨âºØ¼Ò¦¡ "
+
+#: version.c:1018
+msgid "menu Edit->Global Settings->Toggle Vi Compatible"
+msgstr "¿ï¨ú¿ï³æªº¡u½s¿è¡v¡u¥þ°ì³]©w¡v¡u¤Á´«¶Ç²ÎVi¬Û®e¼Ò¦¡¡v"
+
+#: version.c:1019
+msgid " for Vim defaults "
+msgstr " ¥H±o Vim ¹w³]­È "
+
+#: version.c:1065
+msgid "WARNING: Windows 95/98/ME detected"
+msgstr "ª`·N: °»´ú¨ì Windows 95/98/ME"
+
+#: version.c:1068
+msgid "type :help windows95<Enter> for info on this"
+msgstr "¦pªG»Ý­n¹ï Windows 95 ¤ä´©ªº§ó¦h¸ê°T½Ð¿é¤J :help windows95<Enter>"
+
+#: window.c:204
+msgid "E441: There is no preview window"
+msgstr "E441: ¨S¦³¹wÄýµøµ¡"
+
+#: window.c:577
+msgid "E442: Can't split topleft and botright at the same time"
+msgstr "E442: ¤£¯à¦P®É¤À³Îµøµ¡¬°¥ª¤W©M¥k¤U¨¤"
+
+#: window.c:1336
+msgid "E443: Cannot rotate when another window is split"
+msgstr "E443: ¦³¨ä¥¦¤À³Îµøµ¡®ÉµLªk±ÛÂà"
+
+#: window.c:1827
+msgid "E444: Cannot close last window"
+msgstr "E444: ¤£¯àÃö³¬³Ì«á¤@­Óµøµ¡"
+
+#: window.c:2557
+msgid "Already only one window"
+msgstr "¤w¸g¥u³Ñ¤@­Óµøµ¡¤F"
+
+#: window.c:2604
+msgid "E445: Other window contains changes"
+msgstr "E445: ¨ä¥¦µøµ¡¦³§ó°Ê¸ê®Æ"
+
+#: window.c:4449
+msgid "E446: No file name under cursor"
+msgstr "E446: ´å¼Ð³B¨S¦³ÀɦW"
+
+#: window.c:4568
+#, c-format
+msgid "E447: Can't find file \"%s\" in path"
+msgstr "E447: ¦b¸ô®|¤¤§ä¤£¨ìÀÉ®× \"%s\""
+
+#: ../GvimExt/gvimext.cpp:586
+msgid "Edit with &multiple Vims"
+msgstr "¨Ï¥Î¦h­Ó Vim session ½s¿è(&M)"
+
+#: ../GvimExt/gvimext.cpp:592
+msgid "Edit with single &Vim"
+msgstr "¥u¨Ï¥Î¦P¤@­Ó Vim session ½s¿è(&V)"
+
+#: ../GvimExt/gvimext.cpp:601
+msgid "&Diff with Vim"
+msgstr "¨Ï¥Î Vim ¨Ó¤ñ¸û(&Diff)"
+
+#: ../GvimExt/gvimext.cpp:614
+msgid "Edit with &Vim"
+msgstr "¨Ï¥Î Vim ½s¿è¦¹ÀÉ(&V)"
+
+#. Now concatenate
+#: ../GvimExt/gvimext.cpp:636
+msgid "Edit with existing Vim - &"
+msgstr "¨Ï¥Î°õ¦æ¤¤ªº Vim session ½s¿è - &"
+
+#: ../GvimExt/gvimext.cpp:749
+msgid "Edits the selected file(s) with Vim"
+msgstr "¨Ï¥Î Vim ½s¿è¤w¿ï¨úªºÀÉ®×"
+
+#: ../GvimExt/gvimext.cpp:888 ../GvimExt/gvimext.cpp:969
+msgid "Error creating process: Check if gvim is in your path!"
+msgstr "µLªk°õ¦æµ{¦¡: ½ÐÀˬd gvim ¦³¨S¦³¦b§Aªº PATH ÅܼƸÌ!"
+
+#: ../GvimExt/gvimext.cpp:889 ../GvimExt/gvimext.cpp:903
+#: ../GvimExt/gvimext.cpp:970
+msgid "gvimext.dll error"
+msgstr "gvimext.dll ¿ù»~"
+
+#: ../GvimExt/gvimext.cpp:902
+msgid "Path length too long!"
+msgstr "¸ô®|ªø«×¤Óªø!"
+
+#: globals.h:990
+msgid "--No lines in buffer--"
+msgstr "--½w½Ä°ÏµL¸ê®Æ--"
+
+#.
+#. * The error messages that can be shared are included here.
+#. * Excluded are errors that are only used once and debugging messages.
+#.
+#: globals.h:1149
+msgid "E470: Command aborted"
+msgstr "E470: ©R¥O³Q±j¨î¤¤Â_°õ¦æ"
+
+#: globals.h:1150
+msgid "E471: Argument required"
+msgstr "E471: »Ý­n«ü¥O°Ñ¼Æ"
+
+#: globals.h:1151
+msgid "E10: \\ should be followed by /, ? or &"
+msgstr "E10: \\ «á­±À³¸Ó¦³ / ? ©Î &"
+
+#: globals.h:1153
+msgid "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"
+msgstr "E11: ¤£¯à¦b©R¥O¦Cµøµ¡¤¤¨Ï¥Î¡C<CR>°õ¦æ¡ACTRL-C Â÷¶}"
+
+#: globals.h:1155
+msgid "E12: Command not allowed from exrc/vimrc in current dir or tag search"
+msgstr "E12: exrc/vimrc ¸Ìªº«ü¥OµLªk°õ¦æ"
+
+#: globals.h:1157
+msgid "E171: Missing :endif"
+msgstr "E171: ¯Ê¤Ö :endif"
+
+#: globals.h:1158
+msgid "E600: Missing :endtry"
+msgstr "E600: ¯Ê¤Ö :endtry"
+
+#: globals.h:1159
+msgid "E170: Missing :endwhile"
+msgstr "E170: ¯Ê¤Ö :endwhile"
+
+#: globals.h:1160
+msgid "E588: :endwhile without :while"
+msgstr "E588: :endwhile ¯Ê¤Ö¹ïÀ³ªº :while"
+
+#: globals.h:1162
+msgid "E13: File exists (add ! to override)"
+msgstr "E13: Àɮפw¸g¦s¦b (¥i¥Î ! ±j¨î¨ú¥N)"
+
+#: globals.h:1163
+msgid "E472: Command failed"
+msgstr "E472: ©R¥O°õ¦æ¥¢±Ñ"
+
+#: globals.h:1165
+#, c-format
+msgid "E234: Unknown fontset: %s"
+msgstr "E234: ¤£¥¿½Tªº¦r¤¸¶° (Fontset): %s"
+
+#: globals.h:1169
+#, c-format
+msgid "E235: Unknown font: %s"
+msgstr "¤£¥¿½Tªº¦r«¬¦WºÙ: %s"
+
+#: globals.h:1172
+#, c-format
+msgid "E236: Font \"%s\" is not fixed-width"
+msgstr "E236: \"%s\" ¤£¬O©T©w¼e«×¦r«¬"
+
+#: globals.h:1174
+msgid "E473: Internal error"
+msgstr "E473: ¤º³¡¿ù»~"
+
+#: globals.h:1175
+msgid "Interrupted"
+msgstr "¤w¤¤Â_"
+
+#: globals.h:1176
+msgid "E14: Invalid address"
+msgstr "E14: ¤£¥¿½Tªº¦ì§}"
+
+#: globals.h:1177
+msgid "E474: Invalid argument"
+msgstr "E474: ¤£¥¿½Tªº°Ñ¼Æ"
+
+#: globals.h:1178
+#, c-format
+msgid "E475: Invalid argument: %s"
+msgstr "E475: ¤£¥¿½Tªº°Ñ¼Æ: %s"
+
+#: globals.h:1180
+#, c-format
+msgid "E15: Invalid expression: %s"
+msgstr "E15: ¤£¥¿½Tªº¹Bºâ¦¡: %s"
+
+#: globals.h:1182
+msgid "E16: Invalid range"
+msgstr "E16: ¤£¥¿½Tªº½d³ò"
+
+#: globals.h:1183
+msgid "E476: Invalid command"
+msgstr "E476: ¤£¥¿½Tªº©R¥O"
+
+#: globals.h:1185
+#, c-format
+msgid "E17: \"%s\" is a directory"
+msgstr "E17: \"%s\" ¬O¥Ø¿ý"
+
+#: globals.h:1188
+msgid "E18: Unexpected characters before '='"
+msgstr "E18: '=' «e­±¥X²{¤F¿ù»~ªº¦r¤¸"
+
+#: globals.h:1191
+#, c-format
+msgid "E364: Library call failed for \"%s()\""
+msgstr "E364: ©I¥s¨ç¦¡®w \"%s\"() ¥¢±Ñ"
+
+#: globals.h:1196
+#, c-format
+msgid "E370: Could not load library %s"
+msgstr "E370: µLªk­«·s¸ü¤Jµ{¦¡®w %s"
+
+#: globals.h:1197
+#, c-format
+msgid "E448: Could not load library function %s"
+msgstr "E448: µLªk¸ü¤Jµ{¦¡®wªº¨ç¦¡ %s"
+
+#: globals.h:1199
+msgid "E19: Mark has invalid line number"
+msgstr "E19: ¼Ð°Oªº¦æ¸¹¿ù»~"
+
+#: globals.h:1200
+msgid "E20: Mark not set"
+msgstr "E20: ¨S¦³³]©w¼Ð°O"
+
+#: globals.h:1201
+msgid "E21: Cannot make changes, 'modifiable' is off"
+msgstr "E21: ¦]¬° 'modifiable' ¿ï¶µ¬OÃö³¬ªº¡A©Ò¥H¤£¯à­×§ï"
+
+#: globals.h:1202
+msgid "E22: Scripts nested too deep"
+msgstr "E22: ±_ª¬»¼°j©I¥s¤Ó¦h¼h"
+
+#: globals.h:1203
+msgid "E23: No alternate file"
+msgstr "E23: ¨S¦³´À¥NªºÀÉ®×"
+
+#: globals.h:1204
+msgid "E24: No such abbreviation"
+msgstr "E24: ¨S¦³³o­Ó abbreviation ¹ïÀ³"
+
+#: globals.h:1205
+msgid "E477: No ! allowed"
+msgstr "E477: ¤£¥i¨Ï¥Î '!'"
+
+#: globals.h:1207
+msgid "E25: GUI cannot be used: Not enabled at compile time"
+msgstr "E25: ¦]¬°½sĶ®É¨S¦³¥[¤J¹Ï«¬¬É­±ªºµ{¦¡½X¡A©Ò¥HµLªk¨Ï¥Î¹Ï«¬¬É­±"
+
+#: globals.h:1210
+msgid "E26: Hebrew cannot be used: Not enabled at compile time\n"
+msgstr "E26: ¦]¬°½sĶ®É¨S¦³¥[¤J Hebrew ªºµ{¦¡½X¡A©Ò¥HµLªk¨Ï¥Î Hebrew\n"
+
+#: globals.h:1213
+msgid "E27: Farsi cannot be used: Not enabled at compile time\n"
+msgstr "E27: ¦]¬°½sĶ®É¨S¦³¥[¤J Farsi ªºµ{¦¡½X¡A©Ò¥HµLªk¨Ï¥Î Farsi\n"
+
+#: globals.h:1216
+#, c-format
+msgid "E28: No such highlight group name: %s"
+msgstr "E28: ¨S¦³¦W¬° '%s' ªº highlight group"
+
+#: globals.h:1218
+msgid "E29: No inserted text yet"
+msgstr "E29: ÁÙ¨S¦³´¡¤J¤å¦r¹L"
+
+#: globals.h:1219
+msgid "E30: No previous command line"
+msgstr "E30: ¨S¦³«e¤@¶µ©R¥O"
+
+#: globals.h:1220
+msgid "E31: No such mapping"
+msgstr "E31: ¨S¦³³o­Ó mapping ¹ïÀ³"
+
+#: globals.h:1221
+msgid "E479: No match"
+msgstr "E479: §ä¤£¨ì"
+
+#: globals.h:1222
+#, c-format
+msgid "E480: No match: %s"
+msgstr "E480: §ä¤£¨ì: %s"
+
+#: globals.h:1223
+msgid "E32: No file name"
+msgstr "E32: ¨S¦³ÀɦW"
+
+#: globals.h:1224
+msgid "E33: No previous substitute regular expression"
+msgstr "E33: ¨S¦³«e¤@­Ó·j´M/¨ú¥Nªº©R¥O"
+
+#: globals.h:1225
+msgid "E34: No previous command"
+msgstr "E34: ¨S¦³«e¤@­Ó©R¥O"
+
+#: globals.h:1226
+msgid "E35: No previous regular expression"
+msgstr "E35: ¨S¦³«e¤@­Ó·j´M«ü¥O"
+
+#: globals.h:1227
+msgid "E481: No range allowed"
+msgstr "E481: ¤£¥i¨Ï¥Î½d³ò«ü¥O"
+
+#: globals.h:1229
+msgid "E36: Not enough room"
+msgstr "E36: ¨S¦³¨¬°÷ªºªÅ¶¡"
+
+#: globals.h:1232
+#, c-format
+msgid "E247: no registered server named \"%s\""
+msgstr "E247: ¨S¦³µù¥U¬° \"%s\" ªº¦øªA¾¹"
+
+#: globals.h:1234
+#, c-format
+msgid "E482: Can't create file %s"
+msgstr "E482: ¤£¯à«Ø¥ßÀÉ®× %s"
+
+#: globals.h:1235
+msgid "E483: Can't get temp file name"
+msgstr "E483: µLªk±oª¾¼È¦sÀɦW"
+
+#: globals.h:1236
+#, c-format
+msgid "E484: Can't open file %s"
+msgstr "E484: µLªk¶}±ÒÀÉ®× %s"
+
+#: globals.h:1237
+#, c-format
+msgid "E485: Can't read file %s"
+msgstr "E485: µLªkŪ¨úÀÉ®× %s"
+
+#: globals.h:1238
+msgid "E37: No write since last change (add ! to override)"
+msgstr "E37: ¤w§ó§ï¹LÀɮצý©|¥¼¦sÀÉ (¥i¥Î ! ±j¨î°õ¦æ)"
+
+#: globals.h:1239
+msgid "E38: Null argument"
+msgstr "E38: ªÅªº (Null) °Ñ¼Æ"
+
+#: globals.h:1241
+msgid "E39: Number expected"
+msgstr "E39: À³¸Ó­n¦³¼Æ¦r"
+
+#: globals.h:1244
+#, c-format
+msgid "E40: Can't open errorfile %s"
+msgstr "E40: µLªk¶}±Ò¿ù»~ÀÉ®× %s"
+
+#: globals.h:1247
+msgid "E233: cannot open display"
+msgstr "E233: <¤£¯à¶}±Ò X Server DISPLAY>"
+
+#: globals.h:1249
+msgid "E41: Out of memory!"
+msgstr "E41: °O¾ÐÅ餣¨¬!"
+
+#: globals.h:1251
+msgid "Pattern not found"
+msgstr "§ä¤£¨ì"
+
+#: globals.h:1253
+#, c-format
+msgid "E486: Pattern not found: %s"
+msgstr "E486: §ä¤£¨ì %s"
+
+#: globals.h:1254
+msgid "E487: Argument must be positive"
+msgstr "E487: °Ñ¼ÆÀ³¸Ó¬O¥¿¼Æ"
+
+#: globals.h:1256
+msgid "E459: Cannot go back to previous directory"
+msgstr "E459: µLªk¦^¨ì«e¤@­Ó¥Ø¿ý"
+
+#: globals.h:1260
+msgid "E42: No Errors"
+msgstr "E42: ¨S¦³¿ù»~"
+
+#: globals.h:1262
+msgid "E43: Damaged match string"
+msgstr "E43: ²Å¦X¦r¦ê¦³°ÝÃD"
+
+#: globals.h:1263
+msgid "E44: Corrupted regexp program"
+msgstr "E44: regexp ¦³°ÝÃD"
+
+#: globals.h:1264
+msgid "E45: 'readonly' option is set (add ! to override)"
+msgstr "E45: ¦³³]©w 'readonly' ¿ï¶µ(°ßŪ) (¥i¥Î ! ±j¨î°õ¦æ)"
+
+#: globals.h:1266
+#, c-format
+msgid "E46: Cannot set read-only variable \"%s\""
+msgstr "E46: µLªk³]©w°ßŪÅÜ¼Æ \"%s\""
+
+#: globals.h:1269
+msgid "E47: Error while reading errorfile"
+msgstr "E47: Ū¨ú¿ù»~ÀÉ®×¥¢±Ñ"
+
+#: globals.h:1272
+msgid "E48: Not allowed in sandbox"
+msgstr "E48: ¤£¯à¦b sandbox ¸Ì¥X²{"
+
+#: globals.h:1274
+msgid "E523: Not allowed here"
+msgstr "E523: ³o¸Ì¤£¥i¨Ï¥Î"
+
+#: globals.h:1277
+msgid "E359: Screen mode setting not supported"
+msgstr "E359: ¤£¤ä´©³]©w¿Ã¹õ¼Ò¦¡"
+
+#: globals.h:1279
+msgid "E49: Invalid scroll size"
+msgstr "E49: ¿ù»~ªº±²°Ê¤j¤p"
+
+#: globals.h:1280
+msgid "E91: 'shell' option is empty"
+msgstr "E91: 'E71: ¿ï¶µ 'shell' ¥¼³]©w"
+
+#: globals.h:1282
+msgid "E255: Couldn't read in sign data!"
+msgstr "E255: µLªkŪ¨ú sign data!"
+
+#: globals.h:1284
+msgid "E72: Close error on swap file"
+msgstr "E72: ¼È¦sÀÉÃö³¬¿ù»~"
+
+#: globals.h:1285
+msgid "E73: tag stack empty"
+msgstr "E73: ¼ÐÅÒ°ïÅ|¤wªÅ"
+
+#: globals.h:1286
+msgid "E74: Command too complex"
+msgstr "E74: ©R¥O¤Ó½ÆÂø"
+
+#: globals.h:1287
+msgid "E75: Name too long"
+msgstr "E75: ¦W¦r¤Óªø"
+
+#: globals.h:1288
+msgid "E76: Too many ["
+msgstr "E76: ¤Ó¦h ["
+
+#: globals.h:1289
+msgid "E77: Too many file names"
+msgstr "E77: ¤Ó¦hÀɦW"
+
+#: globals.h:1290
+msgid "E488: Trailing characters"
+msgstr "E488: §A¿é¤J¤F¦h¾lªº¦r¤¸"
+
+#: globals.h:1291
+msgid "E78: Unknown mark"
+msgstr "E78: µLªk¿ìÃѪº¼Ð°O"
+
+#: globals.h:1292
+msgid "E79: Cannot expand wildcards"
+msgstr "E79: µLªk®i¶}¸U¥Î¦r¤¸"
+
+#: globals.h:1294
+msgid "E591: 'winheight' cannot be smaller than 'winminheight'"
+msgstr "E591: 'winheight' ¤£¯à¤ñ 'winminheight' §ó¤Ö"
+
+#: globals.h:1296
+msgid "E592: 'winwidth' cannot be smaller than 'winminwidth'"
+msgstr "E592: 'winwidth' ¤£¯à¤ñ 'winminwidth' §ó¤Ö"
+
+#: globals.h:1299
+msgid "E80: Error while writing"
+msgstr "E80: ¼g¤J¿ù»~"
+
+#: globals.h:1300
+msgid "Zero count"
+msgstr "¼Æ¨ì¹s (?)"
+
+#: globals.h:1302
+msgid "E81: Using <SID> not in a script context"
+msgstr "E81: <SID> ¤£¯à¦b script ¥»¤å¥~¨Ï¥Î."
+
+#: globals.h:1305
+msgid "E449: Invalid expression received"
+msgstr "E449: ¦¬¨ì¤£¥¿½Tªº¹Bºâ¦¡"
+
+#: globals.h:1308
+msgid "E463: Region is guarded, cannot modify"
+msgstr "E463: °Ï°ì³Q«OÅ@¡AµLªk­×§ï"
+
+#~ msgid "function "
+#~ msgstr "¨ç¦¡ "
+
+#~ msgid "Run Macro"
+#~ msgstr "°õ¦æ¥¨¶°"
+
+#~ msgid "E221: 'commentstring' is empty"
+#~ msgstr "E221: ¿ï¶µ 'commentstring' ¥¼³]©w"
+
+#~ msgid "E242: Color name not recognized: %s"
+#~ msgstr "E242: %s ¬°µLªkÃѧOªºÃC¦â¦WºÙ"
+
+#~ msgid "E242: Missing color: %s"
+#~ msgstr "E242: §ä¤£¨ìÃC¦â: %s"
+
+#~ msgid "error reading cscope connection %d"
+#~ msgstr "Ū¨ú cscope ³s½u %d ®É¿ù»~"
+
+#~ msgid "E249: couldn't read VIM instance registry property"
+#~ msgstr "E249: µLªkŪ¨ú VIM ªº registry ³]©w¶µ"
+
+#~ msgid "Can't open file %s"
+#~ msgstr "µLªk¶}±ÒÀÉ®× %s"
+
+#~ msgid "Unable to send reply"
+#~ msgstr "µLªk¶Ç°e¦^À³°T®§"
+
+#~ msgid "E241: Unable to send to Vim server"
+#~ msgstr "E241: µLªk¶Ç°e¨ì Vim ¦øªA¾¹"
+
+#~ msgid ""
+#~ "\n"
+#~ "Send failed. No command server present ?\n"
+#~ msgstr ""
+#~ "\n"
+#~ "¶Ç°e¥¢±Ñ¡C¨S¦³©R¥O¦øªA¾¹¦s¦b ?\n"
+
+#~ msgid "PC (32 bits Vim)"
+#~ msgstr "PC (32 ¦ì¤¸ Vim)"
+
+#~ msgid "PC (16 bits Vim)"
+#~ msgstr "PC (16 ¦ì¤¸ Vim)"
+
+#~ msgid "E362: Unsupported screen mode"
+#~ msgstr "E362: ¿Ã¹õ¼Ò¦¡¤£¤ä´©"
+
+#~ msgid "No servers found for this display"
+#~ msgstr "¦¹Display¨S¦³¦øªA¾¹(Servers)"
+
+#~ msgid "E258: no matches found in cscope connections"
+#~ msgstr "E258: cscope ³s½u§ä¤£¨ì²Å¦Xªº"
+
+#~ msgid ""
+#~ "\n"
+#~ "MacOS Carbon"
+#~ msgstr ""
+#~ "\n"
+#~ "MacOS Carbon"
+
+#~ msgid ""
+#~ "\n"
+#~ "MacOS 8"
+#~ msgstr ""
+#~ "\n"
+#~ "MacOS 8"
+
+#~ msgid "Retrieve next symbol"
+#~ msgstr "Ū¨ú: ±q¤U­Ó symbol"
+
+#~ msgid "-- SNiFF+ commands --"
+#~ msgstr "-- SNiFF+ ©R¥O --"
+
+#~ msgid "E277: Unrecognized sniff request [%s]"
+#~ msgstr "E277: µLªk¿ëÃÑ sniff ©R¥O [%s]"
diff --git a/src/proto.h b/src/proto.h
new file mode 100644
index 000000000..d89c84731
--- /dev/null
+++ b/src/proto.h
@@ -0,0 +1,251 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * proto.h: include the (automatically generated) function prototypes
+ */
+
+/*
+ * Don't include these while generating prototypes. Prevents problems when
+ * files are missing.
+ */
+#if !defined(PROTO) && !defined(NOPROTO)
+
+/*
+ * Machine-dependent routines.
+ */
+/* avoid errors in function prototypes */
+# if !defined(FEAT_X11) && !defined(FEAT_GUI_GTK)
+# define Display int
+# define Widget int
+# endif
+# ifndef FEAT_GUI_GTK
+# define GdkEvent int
+# define GdkEventKey int
+# endif
+# ifndef FEAT_X11
+# define XImage int
+# endif
+
+# ifdef AMIGA
+# include "os_amiga.pro"
+# endif
+# if defined(UNIX) || defined(__EMX__) || defined(VMS)
+# include "os_unix.pro"
+# endif
+# if defined(MSDOS) || defined(WIN16)
+# include "os_msdos.pro"
+# endif
+# ifdef WIN16
+ typedef LPSTR LPWSTR;
+ typedef LPCSTR LPCWSTR;
+ typedef int LPBOOL;
+# include "os_win16.pro"
+# include "os_mswin.pro"
+# endif
+# ifdef WIN3264
+# include "os_win32.pro"
+# include "os_mswin.pro"
+# if (defined(__GNUC__) && !defined(__MINGW32__)) \
+ || (defined(__BORLANDC__) && __BORLANDC__ < 0x502)
+extern int _stricoll __ARGS((char *a, char *b));
+# endif
+# endif
+# ifdef VMS
+# include "os_vms.pro"
+# endif
+# ifdef __BEOS__
+# include "os_beos.pro"
+# endif
+# ifdef MACOS
+# include "os_mac.pro"
+# endif
+# ifdef RISCOS
+# include "os_riscos.pro"
+# endif
+# ifdef __QNX__
+# include "os_qnx.pro"
+# endif
+
+# include "buffer.pro"
+# include "charset.pro"
+# ifdef FEAT_CSCOPE
+# include "if_cscope.pro"
+# endif
+# include "diff.pro"
+# include "digraph.pro"
+# include "edit.pro"
+# include "eval.pro"
+# include "ex_cmds.pro"
+# include "ex_cmds2.pro"
+# include "ex_docmd.pro"
+# include "ex_eval.pro"
+# include "ex_getln.pro"
+# include "fileio.pro"
+# include "fold.pro"
+# include "getchar.pro"
+# ifdef FEAT_HANGULIN
+# include "hangulin.pro"
+# endif
+# include "main.pro"
+# include "mark.pro"
+# if !defined MESSAGE_FILE || defined(HAVE_STDARG_H)
+ /* These prototypes cannot be produced automatically and conflict with
+ * the old-style prototypes in message.c. */
+int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+smsg __ARGS((char_u *, ...));
+int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+smsg_attr __ARGS((int, char_u *, ...));
+# endif
+# include "memfile.pro"
+# include "memline.pro"
+# ifdef FEAT_MENU
+# include "menu.pro"
+# endif
+# include "message.pro"
+# include "misc1.pro"
+# include "misc2.pro"
+#ifndef HAVE_STRPBRK /* not generated automatically from misc2.c */
+char_u *vim_strpbrk __ARGS((char_u *s, char_u *charset));
+#endif
+#ifndef HAVE_QSORT
+/* Use our own qsort(), don't define the prototype when not used. */
+void qsort __ARGS((void *base, size_t elm_count, size_t elm_size, int (*cmp)(const void *, const void *)));
+#endif
+# include "move.pro"
+# if defined(FEAT_MBYTE) || defined(FEAT_XIM) || defined(FEAT_KEYMAP) \
+ || defined(FEAT_POSTSCRIPT)
+# include "mbyte.pro"
+# endif
+# include "normal.pro"
+# include "ops.pro"
+# include "option.pro"
+# include "quickfix.pro"
+# include "regexp.pro"
+# include "screen.pro"
+# include "search.pro"
+# include "syntax.pro"
+# include "tag.pro"
+# include "term.pro"
+# if defined(HAVE_TGETENT) && (defined(AMIGA) || defined(VMS))
+# include "termlib.pro"
+# endif
+# include "ui.pro"
+# include "undo.pro"
+# include "version.pro"
+# include "window.pro"
+
+# ifdef FEAT_PYTHON
+# include "if_python.pro"
+# endif
+
+# ifdef FEAT_TCL
+# include "if_tcl.pro"
+# endif
+
+# ifdef FEAT_RUBY
+# include "if_ruby.pro"
+# endif
+
+# ifdef FEAT_GUI
+# include "gui.pro"
+# if defined(UNIX) || defined(MACOS)
+# include "pty.pro"
+# endif
+# if !defined(HAVE_SETENV) && !defined(HAVE_PUTENV) && !defined(VMS)
+extern int putenv __ARGS((const char *string)); /* from pty.c */
+# ifdef USE_VIMPTY_GETENV
+extern char_u *vimpty_getenv __ARGS((const char_u *string)); /* from pty.c */
+# endif
+# endif
+# ifdef FEAT_GUI_W16
+# include "gui_w16.pro"
+# endif
+ /* Ugly solution for "BalloonEval" not being defined while it's used in
+ * the prototypes. */
+# ifndef FEAT_BEVAL
+# define BalloonEval int
+# endif
+# ifdef FEAT_GUI_W32
+# include "gui_w32.pro"
+# endif
+# ifdef FEAT_GUI_GTK
+# include "gui_gtk.pro"
+# include "gui_gtk_x11.pro"
+# endif
+# ifdef FEAT_GUI_MOTIF
+# include "gui_motif.pro"
+# endif
+# ifdef FEAT_GUI_ATHENA
+# include "gui_athena.pro"
+# ifdef FEAT_BROWSE
+extern char *vim_SelFile __ARGS((Widget toplevel, char *prompt, char *init_path, int (*show_entry)(), int x, int y, guicolor_T fg, guicolor_T bg, guicolor_T scroll_fg, guicolor_T scroll_bg));
+# endif
+# endif
+# ifdef FEAT_GUI_BEOS
+# include "gui_beos.pro"
+# endif
+# ifdef FEAT_GUI_MAC
+# include "gui_mac.pro"
+# endif
+# ifdef FEAT_GUI_X11
+# include "gui_x11.pro"
+# endif
+# if defined(FEAT_GUI_AMIGA)
+# include "gui_amiga.pro"
+# endif
+# ifdef RISCOS
+# include "gui_riscos.pro"
+# endif
+# ifdef FEAT_GUI_PHOTON
+# include "gui_photon.pro"
+# endif
+# ifdef FEAT_SUN_WORKSHOP
+# include "workshop.pro"
+# endif
+# ifdef FEAT_NETBEANS_INTG
+# include "netbeans.pro"
+# endif
+# endif /* FEAT_GUI */
+
+# ifdef FEAT_OLE
+# include "if_ole.pro"
+# endif
+# if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
+# include "if_xcmdsrv.pro"
+# endif
+
+/*
+ * The perl include files pollute the namespace, therfore proto.h must be
+ * included before the perl include files. But then CV is not defined, which
+ * is used in if_perl.pro. To get around this, the perl prototype files are
+ * not included here for the perl files. Use a dummy define for CV for the
+ * other files.
+ */
+#if defined(FEAT_PERL) && !defined(IN_PERL_FILE)
+# define CV void
+# ifdef __BORLANDC__
+# pragma option -pc
+# endif
+# include "if_perl.pro"
+# ifdef __BORLANDC__
+# pragma option -p.
+# endif
+# include "if_perlsfio.pro"
+#endif
+
+#ifdef __BORLANDC__
+# define _PROTO_H
+#endif
+#endif /* !PROTO && !NOPROTO */
diff --git a/src/proto/buffer.pro b/src/proto/buffer.pro
new file mode 100644
index 000000000..b2ade2b85
--- /dev/null
+++ b/src/proto/buffer.pro
@@ -0,0 +1,66 @@
+/* buffer.c */
+int open_buffer __ARGS((int read_stdin, exarg_T *eap));
+int buf_valid __ARGS((buf_T *buf));
+void close_buffer __ARGS((win_T *win, buf_T *buf, int action));
+void buf_clear_file __ARGS((buf_T *buf));
+void buf_freeall __ARGS((buf_T *buf, int del_buf, int wipe_buf));
+void goto_buffer __ARGS((exarg_T *eap, int start, int dir, int count));
+void handle_swap_exists __ARGS((buf_T *old_curbuf));
+char_u *do_bufdel __ARGS((int command, char_u *arg, int addr_count, int start_bnr, int end_bnr, int forceit));
+int do_buffer __ARGS((int action, int start, int dir, int count, int forceit));
+void set_curbuf __ARGS((buf_T *buf, int action));
+void enter_buffer __ARGS((buf_T *buf));
+buf_T *buflist_new __ARGS((char_u *ffname, char_u *sfname, linenr_T lnum, int flags));
+void free_buf_options __ARGS((buf_T *buf, int free_p_ff));
+int buflist_getfile __ARGS((int n, linenr_T lnum, int options, int forceit));
+void buflist_getfpos __ARGS((void));
+buf_T *buflist_findname __ARGS((char_u *ffname));
+int buflist_findpat __ARGS((char_u *pattern, char_u *pattern_end, int unlisted, int diffmode));
+int ExpandBufnames __ARGS((char_u *pat, int *num_file, char_u ***file, int options));
+buf_T *buflist_findnr __ARGS((int nr));
+char_u *buflist_nr2name __ARGS((int n, int fullname, int helptail));
+void get_winopts __ARGS((buf_T *buf));
+pos_T *buflist_findfpos __ARGS((buf_T *buf));
+linenr_T buflist_findlnum __ARGS((buf_T *buf));
+void buflist_list __ARGS((exarg_T *eap));
+int buflist_name_nr __ARGS((int fnum, char_u **fname, linenr_T *lnum));
+int setfname __ARGS((buf_T *buf, char_u *ffname, char_u *sfname, int message));
+void buf_name_changed __ARGS((buf_T *buf));
+buf_T *setaltfname __ARGS((char_u *ffname, char_u *sfname, linenr_T lnum));
+char_u *getaltfname __ARGS((int errmsg));
+int buflist_add __ARGS((char_u *fname, int flags));
+void buflist_slash_adjust __ARGS((void));
+void buflist_altfpos __ARGS((void));
+int otherfile __ARGS((char_u *ffname));
+void buf_setino __ARGS((buf_T *buf));
+void fileinfo __ARGS((int fullname, int shorthelp, int dont_truncate));
+void col_print __ARGS((char_u *buf, int col, int vcol));
+void maketitle __ARGS((void));
+void resettitle __ARGS((void));
+int build_stl_str_hl __ARGS((win_T *wp, char_u *out, size_t outlen, char_u *fmt, int fillchar, int maxwidth, struct stl_hlrec *hl));
+void get_rel_pos __ARGS((win_T *wp, char_u *str));
+int append_arg_number __ARGS((win_T *wp, char_u *buf, int add_file, int maxlen));
+char_u *fix_fname __ARGS((char_u *fname));
+void fname_expand __ARGS((buf_T *buf, char_u **ffname, char_u **sfname));
+char_u *alist_name __ARGS((aentry_T *aep));
+void do_arg_all __ARGS((int count, int forceit));
+void ex_buffer_all __ARGS((exarg_T *eap));
+void do_modelines __ARGS((void));
+int read_viminfo_bufferlist __ARGS((vir_T *virp, int writing));
+void write_viminfo_bufferlist __ARGS((FILE *fp));
+char *buf_spname __ARGS((buf_T *buf));
+void buf_addsign __ARGS((buf_T *buf, int id, linenr_T lnum, int typenr));
+int buf_change_sign_type __ARGS((buf_T *buf, int markId, int typenr));
+int_u buf_getsigntype __ARGS((buf_T *buf, linenr_T lnum, int type));
+linenr_T buf_delsign __ARGS((buf_T *buf, int id));
+int buf_findsign __ARGS((buf_T *buf, int id));
+int buf_findsign_id __ARGS((buf_T *buf, linenr_T lnum));
+int buf_findsigntype_id __ARGS((buf_T *buf, linenr_T lnum, int typenr));
+int buf_signcount __ARGS((buf_T *buf, linenr_T lnum));
+void buf_delete_all_signs __ARGS((void));
+void sign_list_placed __ARGS((buf_T *rbuf));
+void sign_mark_adjust __ARGS((linenr_T line1, linenr_T line2, long amount, long amount_after));
+void set_buflisted __ARGS((int on));
+int buf_contents_changed __ARGS((buf_T *buf));
+void wipe_buffer __ARGS((buf_T *buf, int aucmd));
+/* vim: set ft=c : */
diff --git a/src/proto/charset.pro b/src/proto/charset.pro
new file mode 100644
index 000000000..88e9754b3
--- /dev/null
+++ b/src/proto/charset.pro
@@ -0,0 +1,49 @@
+/* charset.c */
+int init_chartab __ARGS((void));
+int buf_init_chartab __ARGS((buf_T *buf, int global));
+void trans_characters __ARGS((char_u *buf, int bufsize));
+char_u *transstr __ARGS((char_u *s));
+char_u *str_foldcase __ARGS((char_u *str, int len));
+char_u *transchar __ARGS((int c));
+char_u *transchar_byte __ARGS((int c));
+void transchar_nonprint __ARGS((char_u *buf, int c));
+void transchar_hex __ARGS((char_u *buf, int c));
+int byte2cells __ARGS((int b));
+int char2cells __ARGS((int c));
+int ptr2cells __ARGS((char_u *p));
+int vim_strsize __ARGS((char_u *s));
+int vim_strnsize __ARGS((char_u *s, int len));
+int chartabsize __ARGS((char_u *p, colnr_T col));
+int linetabsize __ARGS((char_u *s));
+int win_linetabsize __ARGS((win_T *wp, char_u *p, colnr_T len));
+int vim_isIDc __ARGS((int c));
+int vim_iswordc __ARGS((int c));
+int vim_iswordp __ARGS((char_u *p));
+int vim_iswordc_buf __ARGS((char_u *p, buf_T *buf));
+int vim_isfilec __ARGS((int c));
+int vim_isprintc __ARGS((int c));
+int vim_isprintc_strict __ARGS((int c));
+int lbr_chartabsize __ARGS((unsigned char *s, colnr_T col));
+int lbr_chartabsize_adv __ARGS((char_u **s, colnr_T col));
+int win_lbr_chartabsize __ARGS((win_T *wp, char_u *s, colnr_T col, int *headp));
+int in_win_border __ARGS((win_T *wp, colnr_T vcol));
+void getvcol __ARGS((win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end));
+colnr_T getvcol_nolist __ARGS((pos_T *posp));
+void getvvcol __ARGS((win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end));
+void getvcols __ARGS((win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T *right));
+char_u *skipwhite __ARGS((char_u *p));
+char_u *skipdigits __ARGS((char_u *p));
+int vim_isdigit __ARGS((int c));
+int vim_isxdigit __ARGS((int c));
+char_u *skiptowhite __ARGS((char_u *p));
+char_u *skiptowhite_esc __ARGS((char_u *p));
+long getdigits __ARGS((char_u **pp));
+int vim_isblankline __ARGS((char_u *lbuf));
+void vim_str2nr __ARGS((char_u *start, int *hexp, int *len, int dooct, int dohex, long *nptr, unsigned long *unptr));
+int hex2nr __ARGS((int c));
+int hexhex2nr __ARGS((char_u *p));
+int rem_backslash __ARGS((char_u *str));
+void backslash_halve __ARGS((char_u *p));
+char_u *backslash_halve_save __ARGS((char_u *p));
+void ebcdic2ascii __ARGS((char_u *buffer, int len));
+/* vim: set ft=c : */
diff --git a/src/proto/diff.pro b/src/proto/diff.pro
new file mode 100644
index 000000000..a9fe99e56
--- /dev/null
+++ b/src/proto/diff.pro
@@ -0,0 +1,23 @@
+/* diff.c */
+void diff_new_buffer __ARGS((void));
+void diff_buf_delete __ARGS((buf_T *buf));
+void diff_buf_add __ARGS((buf_T *buf));
+void diff_invalidate __ARGS((void));
+void diff_mark_adjust __ARGS((linenr_T line1, linenr_T line2, long amount, long amount_after));
+void ex_diffupdate __ARGS((exarg_T *eap));
+void ex_diffpatch __ARGS((exarg_T *eap));
+void ex_diffsplit __ARGS((exarg_T *eap));
+void ex_diffthis __ARGS((exarg_T *eap));
+void diff_win_options __ARGS((win_T *wp, int addbuf));
+int diff_check __ARGS((win_T *wp, linenr_T lnum));
+int diff_check_fill __ARGS((win_T *wp, linenr_T lnum));
+void diff_set_topline __ARGS((win_T *fromwin, win_T *towin));
+int diffopt_changed __ARGS((void));
+int diff_find_change __ARGS((win_T *wp, linenr_T lnum, int *startp, int *endp));
+int diff_infold __ARGS((win_T *wp, linenr_T lnum));
+void nv_diffgetput __ARGS((int put));
+void ex_diffgetput __ARGS((exarg_T *eap));
+int diff_mode_buf __ARGS((buf_T *buf));
+int diff_move_to __ARGS((int dir, long count));
+linenr_T diff_lnum_win __ARGS((linenr_T lnum, win_T *wp));
+/* vim: set ft=c : */
diff --git a/src/proto/digraph.pro b/src/proto/digraph.pro
new file mode 100644
index 000000000..be5be71ed
--- /dev/null
+++ b/src/proto/digraph.pro
@@ -0,0 +1,9 @@
+/* digraph.c */
+int do_digraph __ARGS((int c));
+int get_digraph __ARGS((int cmdline));
+int getdigraph __ARGS((int char1, int char2, int meta));
+void putdigraph __ARGS((char_u *str));
+void listdigraphs __ARGS((void));
+char_u *keymap_init __ARGS((void));
+void ex_loadkeymap __ARGS((exarg_T *eap));
+/* vim: set ft=c : */
diff --git a/src/proto/edit.pro b/src/proto/edit.pro
new file mode 100644
index 000000000..59939593e
--- /dev/null
+++ b/src/proto/edit.pro
@@ -0,0 +1,36 @@
+/* edit.c */
+int edit __ARGS((int cmdchar, int startln, long count));
+void edit_putchar __ARGS((int c, int highlight));
+void edit_unputchar __ARGS((void));
+void display_dollar __ARGS((colnr_T col));
+void change_indent __ARGS((int type, int amount, int round, int replaced));
+void truncate_spaces __ARGS((char_u *line));
+void backspace_until_column __ARGS((int col));
+int vim_is_ctrl_x_key __ARGS((int c));
+int ins_compl_add_infercase __ARGS((char_u *str, int len, char_u *fname, int dir, int reuse));
+char_u *find_word_start __ARGS((char_u *ptr));
+char_u *find_word_end __ARGS((char_u *ptr));
+void ins_compl_check_keys __ARGS((void));
+int get_literal __ARGS((void));
+void insertchar __ARGS((int c, int flags, int second_indent));
+void auto_format __ARGS((int trailblank, int prev_line));
+int comp_textwidth __ARGS((int ff));
+int stop_arrow __ARGS((void));
+void set_last_insert __ARGS((int c));
+char_u *add_char2buf __ARGS((int c, char_u *s));
+void beginline __ARGS((int flags));
+int oneright __ARGS((void));
+int oneleft __ARGS((void));
+int cursor_up __ARGS((long n, int upd_topline));
+int cursor_down __ARGS((long n, int upd_topline));
+int stuff_inserted __ARGS((int c, long count, int no_esc));
+char_u *get_last_insert __ARGS((void));
+char_u *get_last_insert_save __ARGS((void));
+void replace_push __ARGS((int c));
+void fixthisline __ARGS((int (*get_the_indent)(void)));
+void fix_indent __ARGS((void));
+int in_cinkeys __ARGS((int keytyped, int when, int line_is_empty));
+int hkmap __ARGS((int c));
+void ins_scroll __ARGS((void));
+void ins_horscroll __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/eval.pro b/src/proto/eval.pro
new file mode 100644
index 000000000..c1dfbb8e9
--- /dev/null
+++ b/src/proto/eval.pro
@@ -0,0 +1,60 @@
+/* eval.c */
+char_u *func_name __ARGS((void *cookie));
+linenr_T *func_breakpoint __ARGS((void *cookie));
+int *func_dbg_tick __ARGS((void *cookie));
+int func_level __ARGS((void *cookie));
+int current_func_returned __ARGS((void));
+void set_internal_string_var __ARGS((char_u *name, char_u *value));
+int eval_charconvert __ARGS((char_u *enc_from, char_u *enc_to, char_u *fname_from, char_u *fname_to));
+int eval_printexpr __ARGS((char_u *fname, char_u *args));
+void eval_diff __ARGS((char_u *origfile, char_u *newfile, char_u *outfile));
+void eval_patch __ARGS((char_u *origfile, char_u *difffile, char_u *outfile));
+int eval_to_bool __ARGS((char_u *arg, int *error, char_u **nextcmd, int skip));
+char_u *eval_to_string_skip __ARGS((char_u *arg, char_u **nextcmd, int skip));
+char_u *eval_to_string __ARGS((char_u *arg, char_u **nextcmd));
+char_u *eval_to_string_safe __ARGS((char_u *arg, char_u **nextcmd));
+int eval_to_number __ARGS((char_u *expr));
+char_u *call_vim_function __ARGS((char_u *func, int argc, char_u **argv, int safe));
+void *save_funccal __ARGS((void));
+void restore_funccal __ARGS((void *fc));
+int eval_foldexpr __ARGS((char_u *arg, int *cp));
+void ex_let __ARGS((exarg_T *eap));
+void set_context_for_expression __ARGS((expand_T *xp, char_u *arg, cmdidx_T cmdidx));
+void ex_call __ARGS((exarg_T *eap));
+void ex_unlet __ARGS((exarg_T *eap));
+int do_unlet __ARGS((char_u *name));
+void del_menutrans_vars __ARGS((void));
+char_u *get_user_var_name __ARGS((expand_T *xp, int idx));
+char_u *get_function_name __ARGS((expand_T *xp, int idx));
+char_u *get_expr_name __ARGS((expand_T *xp, int idx));
+void set_vim_var_nr __ARGS((int idx, long val));
+long get_vim_var_nr __ARGS((int idx));
+void set_vcount __ARGS((long count, long count1));
+void set_vim_var_string __ARGS((int idx, char_u *val, int len));
+void set_reg_var __ARGS((int c));
+char_u *v_exception __ARGS((char_u *oldval));
+char_u *v_throwpoint __ARGS((char_u *oldval));
+char_u *set_cmdarg __ARGS((exarg_T *eap, char_u *oldarg));
+char_u *get_var_value __ARGS((char_u *name));
+void new_script_vars __ARGS((scid_T id));
+void var_init __ARGS((garray_T *gap));
+void var_clear __ARGS((garray_T *gap));
+void ex_echo __ARGS((exarg_T *eap));
+void ex_echohl __ARGS((exarg_T *eap));
+void ex_execute __ARGS((exarg_T *eap));
+void ex_function __ARGS((exarg_T *eap));
+char_u *get_user_func_name __ARGS((expand_T *xp, int idx));
+void ex_delfunction __ARGS((exarg_T *eap));
+void ex_return __ARGS((exarg_T *eap));
+int do_return __ARGS((exarg_T *eap, int reanimate, int is_cmd, void *value));
+void discard_pending_return __ARGS((void *retvar));
+char_u *get_return_cmd __ARGS((void *retvar));
+char_u *get_func_line __ARGS((int c, void *cookie, int indent));
+int func_has_ended __ARGS((void *cookie));
+int func_has_abort __ARGS((void *cookie));
+int read_viminfo_varlist __ARGS((vir_T *virp, int writing));
+void write_viminfo_varlist __ARGS((FILE *fp));
+int store_session_globals __ARGS((FILE *fd));
+int modify_fname __ARGS((char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen));
+char_u *do_string_sub __ARGS((char_u *str, char_u *pat, char_u *sub, char_u *flags));
+/* vim: set ft=c : */
diff --git a/src/proto/ex_cmds.pro b/src/proto/ex_cmds.pro
new file mode 100644
index 000000000..33f105a09
--- /dev/null
+++ b/src/proto/ex_cmds.pro
@@ -0,0 +1,52 @@
+/* ex_cmds.c */
+void do_ascii __ARGS((exarg_T *eap));
+void ex_align __ARGS((exarg_T *eap));
+void ex_retab __ARGS((exarg_T *eap));
+int do_move __ARGS((linenr_T line1, linenr_T line2, linenr_T dest));
+void ex_copy __ARGS((linenr_T line1, linenr_T line2, linenr_T n));
+void do_bang __ARGS((int addr_count, exarg_T *eap, int forceit, int do_in, int do_out));
+void do_shell __ARGS((char_u *cmd, int flags));
+char_u *make_filter_cmd __ARGS((char_u *cmd, char_u *itmp, char_u *otmp));
+void append_redir __ARGS((char_u *buf, char_u *opt, char_u *fname));
+int viminfo_error __ARGS((char *errnum, char *message, char_u *line));
+int read_viminfo __ARGS((char_u *file, int want_info, int want_marks, int forceit));
+void write_viminfo __ARGS((char_u *file, int forceit));
+int viminfo_readline __ARGS((vir_T *virp));
+char_u *viminfo_readstring __ARGS((vir_T *virp, int off, int convert));
+void viminfo_writestring __ARGS((FILE *fd, char_u *p));
+void do_fixdel __ARGS((exarg_T *eap));
+void print_line_no_prefix __ARGS((linenr_T lnum, int use_number));
+void print_line __ARGS((linenr_T lnum, int use_number));
+void ex_file __ARGS((exarg_T *eap));
+void ex_update __ARGS((exarg_T *eap));
+void ex_write __ARGS((exarg_T *eap));
+int do_write __ARGS((exarg_T *eap));
+void ex_wnext __ARGS((exarg_T *eap));
+void do_wqall __ARGS((exarg_T *eap));
+int not_writing __ARGS((void));
+int getfile __ARGS((int fnum, char_u *ffname, char_u *sfname, int setpm, linenr_T lnum, int forceit));
+int do_ecmd __ARGS((int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T newlnum, int flags));
+void ex_append __ARGS((exarg_T *eap));
+void ex_change __ARGS((exarg_T *eap));
+void ex_z __ARGS((exarg_T *eap));
+int check_restricted __ARGS((void));
+int check_secure __ARGS((void));
+void do_sub __ARGS((exarg_T *eap));
+void ex_global __ARGS((exarg_T *eap));
+void global_exe __ARGS((char_u *cmd));
+int read_viminfo_sub_string __ARGS((vir_T *virp, int force));
+void write_viminfo_sub_string __ARGS((FILE *fp));
+void prepare_tagpreview __ARGS((void));
+void ex_help __ARGS((exarg_T *eap));
+int help_heuristic __ARGS((char_u *matched_string, int offset, int wrong_case));
+int find_help_tags __ARGS((char_u *arg, int *num_matches, char_u ***matches, int keep_lang));
+void fix_help_buffer __ARGS((void));
+void ex_helptags __ARGS((exarg_T *eap));
+void ex_sign __ARGS((exarg_T *eap));
+void sign_gui_started __ARGS((void));
+int sign_get_attr __ARGS((int typenr, int line));
+char_u *sign_get_text __ARGS((int typenr));
+void *sign_get_image __ARGS((int typenr));
+char_u *sign_typenr2name __ARGS((int typenr));
+void ex_drop __ARGS((exarg_T *eap));
+/* vim: set ft=c : */
diff --git a/src/proto/ex_cmds2.pro b/src/proto/ex_cmds2.pro
new file mode 100644
index 000000000..adf2d8f36
--- /dev/null
+++ b/src/proto/ex_cmds2.pro
@@ -0,0 +1,76 @@
+/* ex_cmds2.c */
+void do_debug __ARGS((char_u *cmd));
+void ex_debug __ARGS((exarg_T *eap));
+void dbg_check_breakpoint __ARGS((exarg_T *eap));
+int dbg_check_skipped __ARGS((exarg_T *eap));
+void ex_breakadd __ARGS((exarg_T *eap));
+void ex_debuggreedy __ARGS((exarg_T *eap));
+void ex_breakdel __ARGS((exarg_T *eap));
+void ex_breaklist __ARGS((exarg_T *eap));
+linenr_T dbg_find_breakpoint __ARGS((int file, char_u *fname, linenr_T after));
+void dbg_breakpoint __ARGS((char_u *name, linenr_T lnum));
+int autowrite __ARGS((buf_T *buf, int forceit));
+void autowrite_all __ARGS((void));
+int check_changed __ARGS((buf_T *buf, int checkaw, int mult_win, int forceit, int allbuf));
+void browse_save_fname __ARGS((buf_T *buf));
+void dialog_changed __ARGS((buf_T *buf, int checkall));
+int can_abandon __ARGS((buf_T *buf, int forceit));
+int check_changed_any __ARGS((int hidden));
+int check_fname __ARGS((void));
+int buf_write_all __ARGS((buf_T *buf, int forceit));
+char_u *do_one_arg __ARGS((char_u *str));
+void set_arglist __ARGS((char_u *str));
+void check_arg_idx __ARGS((win_T *win));
+void ex_args __ARGS((exarg_T *eap));
+void ex_previous __ARGS((exarg_T *eap));
+void ex_rewind __ARGS((exarg_T *eap));
+void ex_last __ARGS((exarg_T *eap));
+void ex_argument __ARGS((exarg_T *eap));
+void do_argfile __ARGS((exarg_T *eap, int argn));
+void ex_next __ARGS((exarg_T *eap));
+void ex_argedit __ARGS((exarg_T *eap));
+void ex_argadd __ARGS((exarg_T *eap));
+void ex_argdelete __ARGS((exarg_T *eap));
+void ex_listdo __ARGS((exarg_T *eap));
+void ex_compiler __ARGS((exarg_T *eap));
+void ex_runtime __ARGS((exarg_T *eap));
+int cmd_runtime __ARGS((char_u *name, int all));
+int do_in_runtimepath __ARGS((char_u *name, int all, void (*callback)(char_u *fname)));
+void ex_options __ARGS((exarg_T *eap));
+void ex_source __ARGS((exarg_T *eap));
+linenr_T *source_breakpoint __ARGS((void *cookie));
+int *source_dbg_tick __ARGS((void *cookie));
+int source_level __ARGS((void *cookie));
+int do_source __ARGS((char_u *fname, int check_other, int is_vimrc));
+void ex_scriptnames __ARGS((exarg_T *eap));
+void scriptnames_slash_adjust __ARGS((void));
+char_u *get_scriptname __ARGS((scid_T id));
+char *fgets_cr __ARGS((char *s, int n, FILE *stream));
+char_u *getsourceline __ARGS((int c, void *cookie, int indent));
+void ex_scriptencoding __ARGS((exarg_T *eap));
+void ex_finish __ARGS((exarg_T *eap));
+void do_finish __ARGS((exarg_T *eap, int reanimate));
+int source_finished __ARGS((char_u *(*getline)(int, void *, int), void *cookie));
+void ex_checktime __ARGS((exarg_T *eap));
+int get_printer_page_num __ARGS((void));
+int prt_header_height __ARGS((void));
+int prt_use_number __ARGS((void));
+int prt_get_unit __ARGS((int idx));
+void ex_hardcopy __ARGS((exarg_T *eap));
+void mch_print_cleanup __ARGS((void));
+int mch_print_init __ARGS((prt_settings_T *psettings, char_u *jobname, int forceit));
+int mch_print_begin __ARGS((prt_settings_T *psettings));
+void mch_print_end __ARGS((prt_settings_T *psettings));
+int mch_print_end_page __ARGS((void));
+int mch_print_begin_page __ARGS((char_u *str));
+int mch_print_blank_page __ARGS((void));
+void mch_print_start_line __ARGS((int margin, int page_line));
+int mch_print_text_out __ARGS((char_u *p, int len));
+void mch_print_set_font __ARGS((int iBold, int iItalic, int iUnderline));
+void mch_print_set_bg __ARGS((long_u bgcol));
+void mch_print_set_fg __ARGS((long_u fgcol));
+char_u *get_mess_lang __ARGS((void));
+void set_lang_var __ARGS((void));
+void ex_language __ARGS((exarg_T *eap));
+char_u *get_lang_arg __ARGS((expand_T *xp, int idx));
+/* vim: set ft=c : */
diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro
new file mode 100644
index 000000000..6efec49f5
--- /dev/null
+++ b/src/proto/ex_docmd.pro
@@ -0,0 +1,41 @@
+/* ex_docmd.c */
+void do_exmode __ARGS((int improved));
+int do_cmdline_cmd __ARGS((char_u *cmd));
+int do_cmdline __ARGS((char_u *cmdline, char_u *(*getline)(int, void *, int), void *cookie, int flags));
+int getline_equal __ARGS((char_u *(*getline)(int, void *, int), void *cookie, char_u *(*func)(int, void *, int)));
+void *getline_cookie __ARGS((char_u *(*getline)(int, void *, int), void *cookie));
+int cmd_exists __ARGS((char_u *name));
+char_u *set_one_cmd_context __ARGS((expand_T *xp, char_u *buff));
+char_u *skip_range __ARGS((char_u *cmd, int *ctx));
+void ex_ni __ARGS((exarg_T *eap));
+int expand_filename __ARGS((exarg_T *eap, char_u **cmdlinep, char_u **errormsgp));
+void separate_nextcmd __ARGS((exarg_T *eap));
+int ends_excmd __ARGS((int c));
+char_u *find_nextcmd __ARGS((char_u *p));
+char_u *check_nextcmd __ARGS((char_u *p));
+char_u *get_command_name __ARGS((expand_T *xp, int idx));
+void uc_clear __ARGS((garray_T *gap));
+char_u *get_user_commands __ARGS((expand_T *xp, int idx));
+char_u *get_user_cmd_flags __ARGS((expand_T *xp, int idx));
+char_u *get_user_cmd_nargs __ARGS((expand_T *xp, int idx));
+char_u *get_user_cmd_complete __ARGS((expand_T *xp, int idx));
+void not_exiting __ARGS((void));
+void handle_drop __ARGS((int filec, char_u **filev, int split));
+void alist_init __ARGS((alist_T *al));
+void alist_unlink __ARGS((alist_T *al));
+void alist_new __ARGS((void));
+void alist_expand __ARGS((void));
+void alist_set __ARGS((alist_T *al, int count, char_u **files, int use_curbuf));
+void alist_add __ARGS((alist_T *al, char_u *fname, int set_fnum));
+void alist_slash_adjust __ARGS((void));
+void ex_splitview __ARGS((exarg_T *eap));
+void do_exedit __ARGS((exarg_T *eap, win_T *old_curwin));
+void do_sleep __ARGS((long msec));
+FILE *open_exfile __ARGS((char_u *fname, int forceit, char *mode));
+void update_topline_cursor __ARGS((void));
+char_u *eval_vars __ARGS((char_u *src, int *usedlen, linenr_T *lnump, char_u **errormsg, char_u *srcstart));
+char_u *expand_sfile __ARGS((char_u *arg));
+int put_eol __ARGS((FILE *fd));
+int put_line __ARGS((FILE *fd, char *s));
+void dialog_msg __ARGS((char_u *buff, char *format, char_u *fname));
+/* vim: set ft=c : */
diff --git a/src/proto/ex_eval.pro b/src/proto/ex_eval.pro
new file mode 100644
index 000000000..80ecfcabd
--- /dev/null
+++ b/src/proto/ex_eval.pro
@@ -0,0 +1,29 @@
+/* ex_eval.c */
+int aborting __ARGS((void));
+void update_force_abort __ARGS((void));
+int should_abort __ARGS((int retcode));
+int aborted_in_try __ARGS((void));
+int cause_errthrow __ARGS((char_u *mesg, int severe, int *ignore));
+void do_errthrow __ARGS((struct condstack *cstack, char_u *cmdname));
+int do_intthrow __ARGS((struct condstack *cstack));
+void discard_current_exception __ARGS((void));
+void report_make_pending __ARGS((int pending, void *value));
+void report_resume_pending __ARGS((int pending, void *value));
+void report_discard_pending __ARGS((int pending, void *value));
+void ex_if __ARGS((exarg_T *eap));
+void ex_endif __ARGS((exarg_T *eap));
+void ex_else __ARGS((exarg_T *eap));
+void ex_while __ARGS((exarg_T *eap));
+void ex_continue __ARGS((exarg_T *eap));
+void ex_break __ARGS((exarg_T *eap));
+void ex_endwhile __ARGS((exarg_T *eap));
+void ex_throw __ARGS((exarg_T *eap));
+void do_throw __ARGS((struct condstack *cstack));
+void ex_try __ARGS((exarg_T *eap));
+void ex_catch __ARGS((exarg_T *eap));
+void ex_finally __ARGS((exarg_T *eap));
+void ex_endtry __ARGS((exarg_T *eap));
+int cleanup_conditionals __ARGS((struct condstack *cstack, int searched_cond, int inclusive));
+void ex_endfunction __ARGS((exarg_T *eap));
+int has_while_cmd __ARGS((char_u *p));
+/* vim: set ft=c : */
diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro
new file mode 100644
index 000000000..aa791ac9c
--- /dev/null
+++ b/src/proto/ex_getln.pro
@@ -0,0 +1,47 @@
+/* ex_getln.c */
+char_u *getcmdline __ARGS((int firstc, long count, int indent));
+char_u *getcmdline_prompt __ARGS((int firstc, char_u *prompt, int attr));
+char_u *getexline __ARGS((int c, void *dummy, int indent));
+char_u *getexmodeline __ARGS((int c, void *dummy, int indent));
+int cmdline_overstrike __ARGS((void));
+int cmdline_at_end __ARGS((void));
+colnr_T cmdline_getvcol_cursor __ARGS((void));
+void putcmdline __ARGS((int c, int shift));
+void unputcmdline __ARGS((void));
+int put_on_cmdline __ARGS((char_u *str, int len, int redraw));
+void redrawcmdline __ARGS((void));
+void redrawcmd __ARGS((void));
+void compute_cmdrow __ARGS((void));
+void gotocmdline __ARGS((int clr));
+char_u *ExpandOne __ARGS((expand_T *xp, char_u *str, char_u *orig, int options, int mode));
+void ExpandInit __ARGS((expand_T *xp));
+void ExpandCleanup __ARGS((expand_T *xp));
+void ExpandEscape __ARGS((expand_T *xp, char_u *str, int numfiles, char_u **files, int options));
+void tilde_replace __ARGS((char_u *orig_pat, int num_files, char_u **files));
+char_u *sm_gettail __ARGS((char_u *s));
+char_u *addstar __ARGS((char_u *fname, int len, int context));
+void set_cmd_context __ARGS((expand_T *xp, char_u *str, int len, int col));
+int expand_cmdline __ARGS((expand_T *xp, char_u *str, int col, int *matchcount, char_u ***matches));
+int ExpandGeneric __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file, char_u *((*func)(expand_T *, int))));
+char_u *globpath __ARGS((char_u *path, char_u *file));
+int get_histtype __ARGS((char_u *name));
+void add_to_history __ARGS((int histype, char_u *new_entry, int in_map, int sep));
+int get_history_idx __ARGS((int histype));
+char_u *get_cmdline_str __ARGS((void));
+int get_cmdline_pos __ARGS((void));
+int set_cmdline_pos __ARGS((int pos));
+char_u *get_history_entry __ARGS((int histype, int idx));
+int clr_history __ARGS((int histype));
+int del_history_entry __ARGS((int histype, char_u *str));
+int del_history_idx __ARGS((int histype, int idx));
+void remove_key_from_history __ARGS((void));
+int get_list_range __ARGS((char_u **str, int *num1, int *num2));
+void ex_history __ARGS((exarg_T *eap));
+void prepare_viminfo_history __ARGS((int asklen));
+int read_viminfo_history __ARGS((vir_T *virp));
+void finish_viminfo_history __ARGS((void));
+void write_viminfo_history __ARGS((FILE *fp));
+void cmd_pchar __ARGS((int c, int offset));
+int cmd_gchar __ARGS((int offset));
+char_u *script_get __ARGS((exarg_T *eap, char_u *cmd));
+/* vim: set ft=c : */
diff --git a/src/proto/fileio.pro b/src/proto/fileio.pro
new file mode 100644
index 000000000..fa275f463
--- /dev/null
+++ b/src/proto/fileio.pro
@@ -0,0 +1,39 @@
+/* fileio.c */
+void filemess __ARGS((buf_T *buf, char_u *name, char_u *s, int attr));
+int readfile __ARGS((char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_skip, linenr_T lines_to_read, exarg_T *eap, int flags));
+int prep_exarg __ARGS((exarg_T *eap, buf_T *buf));
+int buf_write __ARGS((buf_T *buf, char_u *fname, char_u *sfname, linenr_T start, linenr_T end, exarg_T *eap, int append, int forceit, int reset_changed, int filtering));
+char_u *shorten_fname __ARGS((char_u *full_path, char_u *dir_name));
+void shorten_fnames __ARGS((int force));
+void shorten_filenames __ARGS((char_u **fnames, int count));
+char_u *modname __ARGS((char_u *fname, char_u *ext, int prepend_dot));
+char_u *buf_modname __ARGS((int shortname, char_u *fname, char_u *ext, int prepend_dot));
+int vim_fgets __ARGS((char_u *buf, int size, FILE *fp));
+int tag_fgets __ARGS((char_u *buf, int size, FILE *fp));
+int vim_rename __ARGS((char_u *from, char_u *to));
+int check_timestamps __ARGS((int focus));
+int buf_check_timestamp __ARGS((buf_T *buf, int focus));
+void buf_store_time __ARGS((buf_T *buf, struct stat *st, char_u *fname));
+void write_lnum_adjust __ARGS((linenr_T offset));
+void vim_deltempdir __ARGS((void));
+char_u *vim_tempname __ARGS((int extra_char));
+void forward_slash __ARGS((char_u *fname));
+void do_augroup __ARGS((char_u *arg, int del_group));
+int check_ei __ARGS((void));
+void do_autocmd __ARGS((char_u *arg, int forceit));
+int do_doautocmd __ARGS((char_u *arg, int do_msg));
+void ex_doautoall __ARGS((exarg_T *eap));
+void aucmd_prepbuf __ARGS((aco_save_T *aco, buf_T *buf));
+void aucmd_restbuf __ARGS((aco_save_T *aco));
+int apply_autocmds __ARGS((EVENT_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf));
+int apply_autocmds_retval __ARGS((EVENT_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, int *retval));
+int has_cursorhold __ARGS((void));
+int has_autocmd __ARGS((EVENT_T event, char_u *sfname));
+char_u *get_augroup_name __ARGS((expand_T *xp, int idx));
+char_u *set_context_in_autocmd __ARGS((expand_T *xp, char_u *arg, int doautocmd));
+char_u *get_event_name __ARGS((expand_T *xp, int idx));
+int au_exists __ARGS((char_u *name, char_u *name_end, char_u *pattern));
+int match_file_pat __ARGS((char_u *pattern, char_u *fname, char_u *sfname, char_u *tail, int allow_dirs));
+int match_file_list __ARGS((char_u *list, char_u *sfname, char_u *ffname));
+char_u *file_pat_to_reg_pat __ARGS((char_u *pat, char_u *pat_end, char *allow_dirs, int no_bslash));
+/* vim: set ft=c : */
diff --git a/src/proto/fold.pro b/src/proto/fold.pro
new file mode 100644
index 000000000..75af30563
--- /dev/null
+++ b/src/proto/fold.pro
@@ -0,0 +1,40 @@
+/* fold.c */
+void copyFoldingState __ARGS((win_T *wp_from, win_T *wp_to));
+int hasAnyFolding __ARGS((win_T *win));
+int hasFolding __ARGS((linenr_T lnum, linenr_T *firstp, linenr_T *lastp));
+int hasFoldingWin __ARGS((win_T *win, linenr_T lnum, linenr_T *firstp, linenr_T *lastp, int cache, foldinfo_T *infop));
+int foldLevel __ARGS((linenr_T lnum));
+int lineFolded __ARGS((win_T *win, linenr_T lnum));
+long foldedCount __ARGS((win_T *win, linenr_T lnum, foldinfo_T *infop));
+int foldmethodIsManual __ARGS((win_T *wp));
+int foldmethodIsIndent __ARGS((win_T *wp));
+int foldmethodIsExpr __ARGS((win_T *wp));
+int foldmethodIsMarker __ARGS((win_T *wp));
+int foldmethodIsSyntax __ARGS((win_T *wp));
+int foldmethodIsDiff __ARGS((win_T *wp));
+void closeFold __ARGS((linenr_T lnum, long count));
+void closeFoldRecurse __ARGS((linenr_T lnum));
+void opFoldRange __ARGS((linenr_T first, linenr_T last, int opening, int recurse, int had_visual));
+void openFold __ARGS((linenr_T lnum, long count));
+void openFoldRecurse __ARGS((linenr_T lnum));
+void foldOpenCursor __ARGS((void));
+void newFoldLevel __ARGS((void));
+void foldCheckClose __ARGS((void));
+int foldManualAllowed __ARGS((int create));
+void foldCreate __ARGS((linenr_T start, linenr_T end));
+void deleteFold __ARGS((linenr_T start, linenr_T end, int recursive, int had_visual));
+void clearFolding __ARGS((win_T *win));
+void foldUpdate __ARGS((win_T *wp, linenr_T top, linenr_T bot));
+void foldUpdateAll __ARGS((win_T *win));
+int foldMoveTo __ARGS((int updown, int dir, long count));
+void foldInitWin __ARGS((win_T *newwin));
+int find_wl_entry __ARGS((win_T *win, linenr_T lnum));
+void foldAdjustVisual __ARGS((void));
+void foldAdjustCursor __ARGS((void));
+void cloneFoldGrowArray __ARGS((garray_T *from, garray_T *to));
+void deleteFoldRecurse __ARGS((garray_T *gap));
+void foldMarkAdjust __ARGS((win_T *wp, linenr_T line1, linenr_T line2, long amount, long amount_after));
+int getDeepestNesting __ARGS((void));
+void foldtext_cleanup __ARGS((char_u *str));
+int put_folds __ARGS((FILE *fd, win_T *wp));
+/* vim: set ft=c : */
diff --git a/src/proto/getchar.pro b/src/proto/getchar.pro
new file mode 100644
index 000000000..fc49b7972
--- /dev/null
+++ b/src/proto/getchar.pro
@@ -0,0 +1,61 @@
+/* getchar.c */
+void free_buff __ARGS((struct buffheader *buf));
+char_u *get_recorded __ARGS((void));
+char_u *get_inserted __ARGS((void));
+int stuff_empty __ARGS((void));
+void typeahead_noflush __ARGS((int c));
+void flush_buffers __ARGS((int typeahead));
+void ResetRedobuff __ARGS((void));
+void saveRedobuff __ARGS((void));
+void restoreRedobuff __ARGS((void));
+void AppendToRedobuff __ARGS((char_u *s));
+void AppendToRedobuffLit __ARGS((char_u *s));
+void AppendCharToRedobuff __ARGS((int c));
+void AppendNumberToRedobuff __ARGS((long n));
+void stuffReadbuff __ARGS((char_u *s));
+void stuffReadbuffLen __ARGS((char_u *s, long len));
+void stuffReadbuffSpec __ARGS((char_u *s));
+void stuffcharReadbuff __ARGS((int c));
+void stuffnumReadbuff __ARGS((long n));
+int start_redo __ARGS((long count, int old_redo));
+int start_redo_ins __ARGS((void));
+void stop_redo_ins __ARGS((void));
+int ins_typebuf __ARGS((char_u *str, int noremap, int offset, int nottyped, int silent));
+int typebuf_changed __ARGS((int tb_change_cnt));
+int typebuf_typed __ARGS((void));
+int typebuf_maplen __ARGS((void));
+void del_typebuf __ARGS((int len, int offset));
+int alloc_typebuf __ARGS((void));
+void free_typebuf __ARGS((void));
+int save_typebuf __ARGS((void));
+void save_typeahead __ARGS((tasave_T *tp));
+void restore_typeahead __ARGS((tasave_T *tp));
+void openscript __ARGS((char_u *name, int directly));
+int using_script __ARGS((void));
+void updatescript __ARGS((int c));
+int vgetc __ARGS((void));
+int safe_vgetc __ARGS((void));
+int vpeekc __ARGS((void));
+int vpeekc_nomap __ARGS((void));
+int vpeekc_any __ARGS((void));
+int char_avail __ARGS((void));
+void vungetc __ARGS((int c));
+int inchar __ARGS((char_u *buf, int maxlen, long wait_time, int tb_change_cnt));
+int fix_input_buffer __ARGS((char_u *buf, int len, int script));
+int input_available __ARGS((void));
+int do_map __ARGS((int maptype, char_u *arg, int mode, int abbrev));
+int get_map_mode __ARGS((char_u **cmdp, int forceit));
+void map_clear __ARGS((char_u *cmdp, char_u *arg, int forceit, int abbr));
+void map_clear_int __ARGS((buf_T *buf, int mode, int local, int abbr));
+int map_to_exists __ARGS((char_u *str, char_u *modechars));
+int map_to_exists_mode __ARGS((char_u *rhs, int mode));
+char_u *set_context_in_map_cmd __ARGS((expand_T *xp, char_u *cmd, char_u *arg, int forceit, int isabbrev, int isunmap, cmdidx_T cmdidx));
+int ExpandMappings __ARGS((regmatch_T *regmatch, int *num_file, char_u ***file));
+int check_abbr __ARGS((int c, char_u *ptr, int col, int mincol));
+int makemap __ARGS((FILE *fd, buf_T *buf));
+int put_escstr __ARGS((FILE *fd, char_u *strstart, int what));
+void check_map_keycodes __ARGS((void));
+char_u *check_map __ARGS((char_u *keys, int mode, int exact));
+void init_mappings __ARGS((void));
+void add_map __ARGS((char_u *map, int mode));
+/* vim: set ft=c : */
diff --git a/src/proto/gui.pro b/src/proto/gui.pro
new file mode 100644
index 000000000..cb254d7d9
--- /dev/null
+++ b/src/proto/gui.pro
@@ -0,0 +1,61 @@
+/* gui.c */
+void gui_start __ARGS((void));
+void gui_prepare __ARGS((int *argc, char **argv));
+int gui_init_check __ARGS((void));
+void gui_init __ARGS((void));
+void gui_exit __ARGS((int rc));
+void gui_shell_closed __ARGS((void));
+int gui_init_font __ARGS((char_u *font_list, int fontset));
+int gui_get_wide_font __ARGS((void));
+void gui_set_cursor __ARGS((int row, int col));
+void gui_update_cursor __ARGS((int force, int clear_selection));
+void gui_position_menu __ARGS((void));
+int gui_get_base_width __ARGS((void));
+int gui_get_base_height __ARGS((void));
+void gui_resize_shell __ARGS((int pixel_width, int pixel_height));
+void gui_may_resize_shell __ARGS((void));
+int gui_get_shellsize __ARGS((void));
+void gui_set_shellsize __ARGS((int mustset, int fit_to_display));
+void gui_new_shellsize __ARGS((void));
+void gui_reset_scroll_region __ARGS((void));
+void gui_start_highlight __ARGS((int mask));
+void gui_stop_highlight __ARGS((int mask));
+void gui_clear_block __ARGS((int row1, int col1, int row2, int col2));
+void gui_update_cursor_later __ARGS((void));
+void gui_write __ARGS((char_u *s, int len));
+void gui_dont_update_cursor __ARGS((void));
+void gui_can_update_cursor __ARGS((void));
+int gui_outstr_nowrap __ARGS((char_u *s, int len, int flags, guicolor_T fg, guicolor_T bg, int back));
+void gui_undraw_cursor __ARGS((void));
+void gui_redraw __ARGS((int x, int y, int w, int h));
+int gui_redraw_block __ARGS((int row1, int col1, int row2, int col2, int flags));
+int gui_wait_for_chars __ARGS((long wtime));
+void gui_send_mouse_event __ARGS((int button, int x, int y, int repeated_click, int_u modifiers));
+int gui_xy2colrow __ARGS((int x, int y, int *colp));
+void gui_menu_cb __ARGS((vimmenu_T *menu));
+void gui_init_which_components __ARGS((char_u *oldval));
+void gui_create_scrollbar __ARGS((scrollbar_T *sb, int type, win_T *wp));
+scrollbar_T *gui_find_scrollbar __ARGS((long ident));
+void gui_drag_scrollbar __ARGS((scrollbar_T *sb, long value, int still_dragging));
+void gui_update_scrollbars __ARGS((int force));
+int gui_do_scroll __ARGS((void));
+int gui_do_horiz_scroll __ARGS((void));
+void gui_check_colors __ARGS((void));
+void gui_set_fg_color __ARGS((char_u *name));
+void gui_set_bg_color __ARGS((char_u *name));
+guicolor_T gui_get_color __ARGS((char_u *name));
+int gui_get_lightness __ARGS((guicolor_T pixel));
+void gui_new_scrollbar_colors __ARGS((void));
+void gui_focus_change __ARGS((int in_focus));
+void gui_mouse_moved __ARGS((int x, int y));
+void gui_mouse_correct __ARGS((void));
+void ex_gui __ARGS((exarg_T *eap));
+int gui_find_bitmap __ARGS((char_u *name, char_u *buffer, char *ext));
+void gui_find_iconfile __ARGS((char_u *name, char_u *buffer, char *ext));
+void display_errors __ARGS((void));
+int no_console_input __ARGS((void));
+void gui_update_screen __ARGS((void));
+char_u *get_find_dialog_text __ARGS((char_u *arg, int *wwordp, int *mcasep));
+int gui_do_findrepl __ARGS((int flags, char_u *find_text, char_u *repl_text, int down));
+void gui_handle_drop __ARGS((int x, int y, int_u modifiers, char_u **fnames, int count));
+/* vim: set ft=c : */
diff --git a/src/proto/gui_amiga.pro b/src/proto/gui_amiga.pro
new file mode 100644
index 000000000..ec70bc102
--- /dev/null
+++ b/src/proto/gui_amiga.pro
@@ -0,0 +1,67 @@
+/* gui_amiga.c */
+void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int idx));
+void gui_mch_add_menu __ARGS((vimmenu_T *menu, int idx));
+void gui_mch_toggle_tearoffs __ARGS((int enable));
+int gui_mch_set_blinking __ARGS((long wait, long on, long off));
+void gui_mch_prepare __ARGS((int *argc, char **argv));
+void atexitDoThis __ARGS((void));
+int gui_mch_init_check __ARGS((void));
+int gui_mch_init __ARGS((void));
+void gui_mch_new_colors __ARGS((void));
+int gui_mch_open __ARGS((void));
+void gui_mch_exit __ARGS((int returnCode));
+int gui_mch_get_winpos __ARGS((int *x, int *y));
+void gui_mch_set_winpos __ARGS((int x, int y));
+void gui_mch_set_shellsize __ARGS((int width, int height, int min_width, int min_height, int base_width, int base_height));
+void gui_mch_get_screen_dimensions __ARGS((int *screen_w, int *screen_h));
+void gui_mch_set_text_area_pos __ARGS((int x, int y, int w, int h));
+void gui_mch_enable_scrollbar __ARGS((scrollbar_T *sb, int flag));
+void gui_mch_set_scrollbar_thumb __ARGS((scrollbar_T *sb, long val, long size, long max));
+void gui_mch_set_scrollbar_pos __ARGS((scrollbar_T *sb, int x, int y, int w, int h));
+void gui_mch_create_scrollbar __ARGS((scrollbar_T *sb, int orient));
+void gui_mch_destroy_scrollbar __ARGS((scrollbar_T *sb));
+int gui_mch_init_font __ARGS((char_u *font_name, int fontset));
+int gui_mch_adjust_charsize __ARGS((void));
+GuiFont gui_mch_get_font __ARGS((char_u *name, int giveErrorIfMissing));
+void gui_mch_set_font __ARGS((GuiFont font));
+void gui_mch_free_font __ARGS((GuiFont font));
+guicolor_T gui_mch_get_color __ARGS((char_u *name));
+void gui_mch_set_colors __ARGS((guicolor_T fg, guicolor_T bg));
+void gui_mch_set_fg_color __ARGS((guicolor_T color));
+void gui_mch_set_bg_color __ARGS((guicolor_T color));
+void gui_mch_draw_string __ARGS((int row, int col, char_u *s, int len, int flags));
+int gui_mch_haskey __ARGS((char_u *name));
+void gui_mch_beep __ARGS((void));
+void gui_mch_flash __ARGS((int msec));
+void gui_mch_invert_rectangle __ARGS((int r, int c, int nr, int nc));
+void gui_mch_iconify __ARGS((void));
+void gui_mch_set_foreground __ARGS((void));
+void gui_mch_settitle __ARGS((char_u *title, char_u *icon));
+void gui_mch_stop_blink __ARGS((void));
+void gui_mch_start_blink __ARGS((void));
+void gui_mch_draw_hollow_cursor __ARGS((guicolor_T color));
+void gui_mch_draw_part_cursor __ARGS((int w, int h, guicolor_T color));
+void gui_mch_update __ARGS((void));
+int gui_mch_wait_for_chars __ARGS((int wtime));
+void gui_mch_flush __ARGS((void));
+void gui_mch_clear_block __ARGS((int row1, int col1, int row2, int col2));
+void gui_mch_clear_all __ARGS((void));
+void gui_mch_delete_lines __ARGS((int row, int num_lines));
+void gui_mch_insert_lines __ARGS((int row, int num_lines));
+void gui_mch_enable_menu __ARGS((int flag));
+void gui_mch_set_menu_pos __ARGS((int x, int y, int w, int h));
+void gui_mch_destroy_menu __ARGS((vimmenu_T *menu));
+void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey));
+void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden));
+void gui_mch_draw_menubar __ARGS((void));
+int clip_mch_own_selection __ARGS((VimClipboard *cbd));
+void mch_setmouse __ARGS((int on));
+int gui_mch_get_mouse_x __ARGS((void));
+int gui_mch_get_mouse_y __ARGS((void));
+void gui_mch_setmouse __ARGS((int x, int y));
+void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu));
+void clip_mch_lose_selection __ARGS((VimClipboard *cbd));
+void clip_mch_request_selection __ARGS((VimClipboard *cbd));
+void clip_mch_set_selection __ARGS((VimClipboard *cbd));
+long_u gui_mch_get_rgb __ARGS((guicolor_T pixel));
+/* vim: set ft=c : */
diff --git a/src/proto/gui_athena.pro b/src/proto/gui_athena.pro
new file mode 100644
index 000000000..353c33b07
--- /dev/null
+++ b/src/proto/gui_athena.pro
@@ -0,0 +1,31 @@
+/* gui_athena.c */
+void gui_x11_create_widgets __ARGS((void));
+void gui_x11_destroy_widgets __ARGS((void));
+void gui_mch_set_toolbar_pos __ARGS((int x, int y, int w, int h));
+void gui_mch_set_text_area_pos __ARGS((int x, int y, int w, int h));
+void gui_x11_set_back_color __ARGS((void));
+void gui_mch_enable_menu __ARGS((int flag));
+void gui_mch_set_menu_pos __ARGS((int x, int y, int w, int h));
+void gui_mch_add_menu __ARGS((vimmenu_T *menu, int idx));
+void gui_mch_new_menu_font __ARGS((void));
+void gui_mch_new_tooltip_font __ARGS((void));
+void gui_mch_new_tooltip_colors __ARGS((void));
+void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int idx));
+void gui_mch_show_toolbar __ARGS((int showit));
+int gui_mch_compute_toolbar_height __ARGS((void));
+void gui_mch_get_toolbar_colors __ARGS((Pixel *bgp, Pixel *fgp, Pixel *bsp, Pixel *tsp, Pixel *hsp));
+void gui_mch_toggle_tearoffs __ARGS((int enable));
+void gui_mch_new_menu_colors __ARGS((void));
+void gui_mch_destroy_menu __ARGS((vimmenu_T *menu));
+void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu));
+void gui_mch_def_colors __ARGS((void));
+void gui_mch_set_scrollbar_thumb __ARGS((scrollbar_T *sb, long val, long size, long max));
+void gui_mch_set_scrollbar_pos __ARGS((scrollbar_T *sb, int x, int y, int w, int h));
+void gui_mch_enable_scrollbar __ARGS((scrollbar_T *sb, int flag));
+void gui_mch_create_scrollbar __ARGS((scrollbar_T *sb, int orient));
+void gui_mch_destroy_scrollbar __ARGS((scrollbar_T *sb));
+void gui_mch_set_scrollbar_colors __ARGS((scrollbar_T *sb));
+Window gui_x11_get_wid __ARGS((void));
+char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter));
+int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield));
+/* vim: set ft=c : */
diff --git a/src/proto/gui_beos.pro b/src/proto/gui_beos.pro
new file mode 100644
index 000000000..af52885f8
--- /dev/null
+++ b/src/proto/gui_beos.pro
@@ -0,0 +1,14 @@
+/* gui_beos.cc - hand crafted */
+int vim_lock_screen __ARGS((void));
+void vim_unlock_screen __ARGS((void));
+void gui_mch_prepare __ARGS((int *argc, char **argv));
+int gui_mch_init __ARGS((void));
+void gui_mch_new_colors __ARGS((void));
+int gui_mch_open __ARGS((void));
+void gui_mch_exit __ARGS((int vim_exitcode));
+GuiFont gui_mch_get_font __ARGS((char_u *name, int giveErrorIfMissing));
+void gui_mch_set_bg_color __ARGS((guicolor_T color));
+void gui_mch_set_font __ARGS((GuiFont font));
+void gui_mch_flush __ARGS((void));
+long_u gui_mch_get_rgb __ARGS((guicolor_T pixel));
+void gui_mch_set_winpos __ARGS((int x, int y));
diff --git a/src/proto/gui_beval.pro b/src/proto/gui_beval.pro
new file mode 100644
index 000000000..160b0e1bd
--- /dev/null
+++ b/src/proto/gui_beval.pro
@@ -0,0 +1,10 @@
+/* gui_beval.c */
+BalloonEval *gui_mch_create_beval_area __ARGS((void *target, char_u *mesg, void (*mesgCB)(BalloonEval *, int), void *clientData));
+void gui_mch_destroy_beval_area __ARGS((BalloonEval *beval));
+void gui_mch_enable_beval_area __ARGS((BalloonEval *beval));
+void gui_mch_disable_beval_area __ARGS((BalloonEval *beval));
+BalloonEval *gui_mch_currently_showing_beval __ARGS((void));
+int gui_mch_get_beval_info __ARGS((BalloonEval *beval, char_u **filename, int *line, char_u **text, int *idx));
+void gui_mch_post_balloon __ARGS((BalloonEval *beval, char_u *mesg));
+void gui_mch_unpost_balloon __ARGS((BalloonEval *beval));
+/* vim: set ft=c : */
diff --git a/src/proto/gui_gtk.pro b/src/proto/gui_gtk.pro
new file mode 100644
index 000000000..2ff220553
--- /dev/null
+++ b/src/proto/gui_gtk.pro
@@ -0,0 +1,24 @@
+/* gui_gtk.c */
+void gui_gtk_register_stock_icons __ARGS((void));
+void gui_mch_add_menu __ARGS((vimmenu_T *menu, int idx));
+void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int idx));
+void gui_mch_set_text_area_pos __ARGS((int x, int y, int w, int h));
+void gui_gtk_set_mnemonics __ARGS((int enable));
+void gui_mch_toggle_tearoffs __ARGS((int enable));
+void gui_mch_menu_set_tip __ARGS((vimmenu_T *menu));
+void gui_mch_destroy_menu __ARGS((vimmenu_T *menu));
+void gui_mch_set_scrollbar_thumb __ARGS((scrollbar_T *sb, long val, long size, long max));
+void gui_mch_set_scrollbar_pos __ARGS((scrollbar_T *sb, int x, int y, int w, int h));
+void gui_mch_create_scrollbar __ARGS((scrollbar_T *sb, int orient));
+void gui_mch_destroy_scrollbar __ARGS((scrollbar_T *sb));
+char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter));
+int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int def_but, char_u *textfield));
+int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int def_but, char_u *textfield));
+void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu));
+void gui_make_popup __ARGS((char_u *path_name));
+void gui_mch_find_dialog __ARGS((exarg_T *eap));
+void gui_mch_replace_dialog __ARGS((exarg_T *eap));
+void gui_gtk_synch_fonts __ARGS((void));
+void ex_helpfind __ARGS((exarg_T *eap));
+void gui_gtk_position_in_parent __ARGS((GtkWidget *parent, GtkWidget *child, gui_win_pos_T where));
+/* vim: set ft=c : */
diff --git a/src/proto/gui_gtk_x11.pro b/src/proto/gui_gtk_x11.pro
new file mode 100644
index 000000000..a3bfaa464
--- /dev/null
+++ b/src/proto/gui_gtk_x11.pro
@@ -0,0 +1,67 @@
+/* gui_gtk_x11.c */
+void gui_mch_prepare __ARGS((int *argc, char **argv));
+void gui_mch_set_blinking __ARGS((long waittime, long on, long off));
+void gui_mch_stop_blink __ARGS((void));
+void gui_mch_start_blink __ARGS((void));
+int gui_mch_init_check __ARGS((void));
+int gui_mch_init __ARGS((void));
+void gui_mch_forked __ARGS((void));
+void gui_mch_new_colors __ARGS((void));
+int gui_mch_open __ARGS((void));
+void gui_mch_exit __ARGS((int rc));
+int gui_mch_get_winpos __ARGS((int *x, int *y));
+void gui_mch_set_winpos __ARGS((int x, int y));
+void gui_mch_set_shellsize __ARGS((int width, int height, int min_width, int min_height, int base_width, int base_height));
+void gui_mch_get_screen_dimensions __ARGS((int *screen_w, int *screen_h));
+void gui_mch_settitle __ARGS((char_u *title, char_u *icon));
+void gui_mch_enable_menu __ARGS((int showit));
+void gui_mch_show_toolbar __ARGS((int showit));
+int gui_mch_adjust_charsize __ARGS((void));
+GuiFontset gui_mch_get_fontset __ARGS((char_u *name, int report_error, int fixed_width));
+char_u *gui_mch_font_dialog __ARGS((char_u *oldval));
+int gui_mch_init_font __ARGS((char_u *font_name, int fontset));
+GuiFont gui_mch_get_font __ARGS((char_u *name, int report_error));
+void gui_mch_set_font __ARGS((GuiFont font));
+void gui_mch_set_fontset __ARGS((GuiFontset fontset));
+void gui_mch_free_font __ARGS((GuiFont font));
+void gui_mch_free_fontset __ARGS((GuiFontset fontset));
+guicolor_T gui_mch_get_color __ARGS((char_u *name));
+void gui_mch_set_fg_color __ARGS((guicolor_T color));
+void gui_mch_set_bg_color __ARGS((guicolor_T color));
+int gui_gtk2_draw_string __ARGS((int row, int col, char_u *s, int len, int flags));
+void gui_mch_draw_string __ARGS((int row, int col, char_u *s, int len, int flags));
+int gui_mch_haskey __ARGS((char_u *name));
+int gui_get_x11_windis __ARGS((Window *win, Display **dis));
+Display *gui_mch_get_display __ARGS((void));
+void gui_mch_beep __ARGS((void));
+void gui_mch_flash __ARGS((int msec));
+void gui_mch_invert_rectangle __ARGS((int r, int c, int nr, int nc));
+void gui_mch_iconify __ARGS((void));
+void gui_mch_set_foreground __ARGS((void));
+void gui_mch_draw_hollow_cursor __ARGS((guicolor_T color));
+void gui_mch_draw_part_cursor __ARGS((int w, int h, guicolor_T color));
+void gui_mch_update __ARGS((void));
+int gui_mch_wait_for_chars __ARGS((long wtime));
+void gui_mch_flush __ARGS((void));
+void gui_mch_clear_block __ARGS((int row1, int col1, int row2, int col2));
+void gui_mch_clear_all __ARGS((void));
+void gui_mch_delete_lines __ARGS((int row, int num_lines));
+void gui_mch_insert_lines __ARGS((int row, int num_lines));
+void clip_mch_request_selection __ARGS((VimClipboard *cbd));
+void clip_mch_lose_selection __ARGS((VimClipboard *cbd));
+int clip_mch_own_selection __ARGS((VimClipboard *cbd));
+void clip_mch_set_selection __ARGS((VimClipboard *cbd));
+void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey));
+void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden));
+void gui_mch_draw_menubar __ARGS((void));
+void gui_mch_enable_scrollbar __ARGS((scrollbar_T *sb, int flag));
+long_u gui_mch_get_rgb __ARGS((guicolor_T pixel));
+int gui_mch_get_mouse_x __ARGS((void));
+int gui_mch_get_mouse_y __ARGS((void));
+void gui_mch_setmouse __ARGS((int x, int y));
+void gui_mch_mousehide __ARGS((int hide));
+void mch_set_mouse_shape __ARGS((int shape));
+void gui_mch_drawsign __ARGS((int row, int col, int typenr));
+void *gui_mch_register_sign __ARGS((char_u *signfile));
+void gui_mch_destroy_sign __ARGS((void *sign));
+/* vim: set ft=c : */
diff --git a/src/proto/gui_mac.pro b/src/proto/gui_mac.pro
new file mode 100644
index 000000000..6f595e2bd
--- /dev/null
+++ b/src/proto/gui_mac.pro
@@ -0,0 +1,142 @@
+/* gui_mac.c */
+
+/*
+ * Mac specific prototypes
+ */
+
+pascal Boolean WaitNextEventWrp __ARGS((EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn));
+pascal void gui_mac_scroll_action __ARGS((ControlHandle theControl, short partCode));
+pascal void gui_mac_drag_thumb (ControlHandle theControl, short partCode);
+void gui_mac_handle_event __ARGS((EventRecord *event));
+void gui_mac_doMouseDown __ARGS((EventRecord *theEvent));
+void gui_mac_do_key __ARGS((EventRecord *theEvent));
+void gui_mac_handle_menu __ARGS((long menuChoice));
+void gui_mac_focus_change __ARGS((EventRecord *event));
+void gui_mac_update __ARGS((EventRecord *event));
+short gui_mch_get_mac_menu_item_index __ARGS((vimmenu_T *menu, vimmenu_T *parent));
+void gui_mch_set_blinking __ARGS((long wait, long on, long off));
+void gui_mch_stop_blink __ARGS((void));
+void gui_mch_start_blink __ARGS((void));
+int gui_mch_get_mouse_x __ARGS((void));
+int gui_mch_get_mouse_y __ARGS((void));
+void gui_mch_setmouse __ARGS((int x, int y));
+void gui_mch_prepare __ARGS((int *argc, char **argv));
+int gui_mch_init_check __ARGS((void));
+int gui_mch_init __ARGS((void));
+void gui_mch_new_colors __ARGS((void));
+int gui_mch_open __ARGS((void));
+void gui_mch_exit __ARGS((int));
+void gui_mch_set_winsize __ARGS((int width, int height, int min_width, int min_height, int base_width, int base_height));
+int gui_mch_get_winpos __ARGS((int *x, int *y));
+void gui_mch_set_winpos __ARGS((int x, int y));
+void gui_mch_set_shellsize __ARGS((int width, int height, int min_width, int min_height, int base_width, int base_height));
+void gui_mch_get_screen_dimensions __ARGS((int *screen_w, int *screen_h));
+void gui_mch_set_text_area_pos __ARGS((int x, int y, int w, int h));
+void gui_mch_enable_scrollbar __ARGS((scrollbar_T *sb, int flag));
+void gui_mch_set_scrollbar_thumb __ARGS((scrollbar_T *sb, long val, long size, long max));
+void gui_mch_set_scrollbar_pos __ARGS((scrollbar_T *sb, int x, int y, int w, int h));
+void gui_mch_create_scrollbar __ARGS((scrollbar_T *sb, int orient));
+void gui_mch_destroy_scrollbar __ARGS((scrollbar_T *sb));
+int gui_mch_adjust_charsize __ARGS((void));
+int gui_mch_init_font __ARGS((char_u *font_name, int fontset));
+GuiFont gui_mch_get_font __ARGS((char_u *name, int giveErrorIfMissing));
+GuiFont gui_mac_find_font __ARGS((char_u *font_name));
+void gui_mch_set_font __ARGS((GuiFont font));
+int gui_mch_same_font __ARGS((GuiFont f1, GuiFont f2));
+void gui_mch_free_font __ARGS((GuiFont font));
+guicolor_T gui_mch_get_color __ARGS((char_u *name));
+void gui_mch_set_fg_color __ARGS((guicolor_T color));
+void gui_mch_set_bg_color __ARGS((guicolor_T color));
+void gui_mch_draw_string __ARGS((int row, int col, char_u *s, int len, int flags));
+int gui_mch_haskey __ARGS((char_u *name));
+void gui_mch_beep __ARGS((void));
+void gui_mch_flash __ARGS((int msec));
+void gui_mch_invert_rectangle __ARGS((int r, int c, int nr, int nc));
+void gui_mch_iconify __ARGS((void));
+void gui_mch_settitle __ARGS((char_u *title, char_u *icon));
+void gui_mch_draw_hollow_cursor __ARGS((guicolor_T color));
+void gui_mch_draw_part_cursor __ARGS((int w, int h, guicolor_T color));
+void gui_mch_update __ARGS((void));
+int gui_mch_wait_for_chars __ARGS((int wtime));
+void gui_mch_flush __ARGS((void));
+void gui_mch_clear_block __ARGS((int row1, int col1, int row2, int col2));
+void gui_mch_clear_all __ARGS((void));
+void gui_mch_delete_lines __ARGS((int row, int num_lines));
+void gui_mch_insert_lines __ARGS((int row, int num_lines));
+void gui_mch_enable_menu __ARGS((int flag));
+void gui_mch_set_menu_pos __ARGS((int x, int y, int w, int h));
+/*void gui_mch_add_menu __ARGS((vimmenu_T *menu, vimmenu_T *parent, int idx));*/
+void gui_mch_add_menu __ARGS((vimmenu_T *menu, int pos));
+/*void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, vimmenu_T *parent, int idx));*/
+void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int idx));
+void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu));
+void gui_mch_destroy_menu __ARGS((vimmenu_T *menu));
+void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey));
+void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden));
+void gui_mch_draw_menubar __ARGS((void));
+int gui_mch_get_lightness __ARGS((guicolor_T pixel));
+long_u gui_mch_get_rgb __ARGS((guicolor_T pixel));
+int gui_mch_get_mouse_x __ARGS((void));
+int gui_mch_get_mouse_y __ARGS((void));
+void gui_mch_setmouse __ARGS((int x, int y));
+void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu));
+int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield));
+char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter));
+void gui_mch_set_foreground __ARGS((void));
+
+char_u *C2Pascal_save __ARGS((char_u *Cstring));
+char_u *C2Pascal_save_and_remove_backslash __ARGS((char_u *Cstring));
+int_u EventModifiers2VimMouseModifiers __ARGS((EventModifiers macModifiers));
+char_u **new_fnames_from_AEDesc __ARGS((AEDesc *theList, long *numFiles, OSErr *error));
+
+
+void gui_request_selection __ARGS((void));
+void gui_mch_lose_selection __ARGS((void));
+int gui_mch_own_selection __ARGS((void));
+void gui_mch_clear_selection __ARGS((void));
+
+void gui_win_new_height __ARGS((win_T *wp));
+void gui_win_comp_pos __ARGS((void));
+void gui_win_free __ARGS((win_T *wp));
+void gui_win_alloc __ARGS((win_T *wp));
+void mch_post_buffer_write (buf_T *buf);
+
+void mch_errmsg __ARGS((char *str));
+void mch_display_error __ARGS((void));
+void clip_mch_lose_selection __ARGS((VimClipboard *cbd));
+void clip_mch_request_selection __ARGS((VimClipboard *cbd));
+void clip_mch_set_selection __ARGS((VimClipboard *cbd));
+int clip_mch_own_selection __ARGS((VimClipboard *cbd));
+
+pascal OSErr FindProcessBySignature( const OSType targetType,
+ const OSType targetCreator, ProcessSerialNumberPtr psnPtr );
+OSErr InstallAEHandlers (void);
+pascal OSErr HandleODocAE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon);
+pascal OSErr Handle_aevt_oapp_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon);
+pascal OSErr Handle_aevt_quit_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon);
+pascal OSErr Handle_aevt_pdoc_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon);
+pascal OSErr Handle_unknown_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon);
+/* Shoulde we return MenuItemIndex? IMO yes, I did that for 5.7 ak*/
+short gui_mac_get_menu_item_index (vimmenu_T *pMenu);
+
+pascal OSErr Handle_KAHL_SRCH_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon);
+pascal OSErr Handle_KAHL_MOD_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon);
+pascal OSErr Handle_KAHL_GTTX_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon);
+void Send_KAHL_MOD_AE (buf_T *buf);
+
+void gui_mac_doInContentClick __ARGS((EventRecord *theEvent, WindowPtr whichWindow));
+void gui_mac_doInDragClick __ARGS((Point where, WindowPtr whichWindow));
+void gui_mac_doInGrowClick __ARGS((Point where, WindowPtr whichWindow));
+void gui_mac_doUpdateEvent __ARGS((EventRecord *event));
+void gui_mac_doActivateEvent __ARGS((EventRecord *event));
+void gui_mac_doSuspendEvent __ARGS((EventRecord *event));
+void gui_mac_doKeyEvent __ARGS((EventRecord *theEvent));
+void gui_mac_doMouseDownEvent __ARGS((EventRecord *theEvent));
+void gui_mac_doMouseMovedEvent __ARGS((EventRecord *event));
+void gui_mac_doMouseUpEvent __ARGS((EventRecord *theEvent));
+
+int C2PascalString (char_u *CString, Str255 *PascalString);
+int GetFSSpecFromPath ( char_u *file, FSSpec *fileFSSpec);
+char_u *FullPathFromFSSpec_save (FSSpec file);
+
+/* vim: set ft=c : */
diff --git a/src/proto/gui_motif.pro b/src/proto/gui_motif.pro
new file mode 100644
index 000000000..cd5d8ab7a
--- /dev/null
+++ b/src/proto/gui_motif.pro
@@ -0,0 +1,39 @@
+/* gui_motif.c */
+void gui_x11_create_widgets __ARGS((void));
+void gui_x11_destroy_widgets __ARGS((void));
+void gui_mch_set_text_area_pos __ARGS((int x, int y, int w, int h));
+void gui_x11_set_back_color __ARGS((void));
+XmFontList gui_motif_create_fontlist __ARGS((XFontStruct *font));
+XmFontList gui_motif_fontset2fontlist __ARGS((XFontSet *fontset));
+void gui_mch_enable_menu __ARGS((int flag));
+void gui_motif_set_mnemonics __ARGS((int enable));
+void gui_mch_add_menu __ARGS((vimmenu_T *menu, int idx));
+void gui_mch_toggle_tearoffs __ARGS((int enable));
+int gui_mch_text_area_extra_height __ARGS((void));
+void gui_mch_compute_menu_height __ARGS((Widget id));
+void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int idx));
+void gui_motif_update_mousemodel __ARGS((vimmenu_T *menu));
+void gui_mch_new_menu_colors __ARGS((void));
+void gui_mch_new_menu_font __ARGS((void));
+void gui_mch_new_tooltip_font __ARGS((void));
+void gui_mch_new_tooltip_colors __ARGS((void));
+void gui_mch_destroy_menu __ARGS((vimmenu_T *menu));
+void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu));
+void gui_mch_def_colors __ARGS((void));
+void gui_mch_set_scrollbar_thumb __ARGS((scrollbar_T *sb, long val, long size, long max));
+void gui_mch_set_scrollbar_pos __ARGS((scrollbar_T *sb, int x, int y, int w, int h));
+void gui_mch_enable_scrollbar __ARGS((scrollbar_T *sb, int flag));
+void gui_mch_create_scrollbar __ARGS((scrollbar_T *sb, int orient));
+void gui_mch_destroy_scrollbar __ARGS((scrollbar_T *sb));
+void gui_mch_set_scrollbar_colors __ARGS((scrollbar_T *sb));
+Window gui_x11_get_wid __ARGS((void));
+char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter));
+int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *button_names, int dfltbutton, char_u *textfield));
+void gui_mch_enable_footer __ARGS((int showit));
+void gui_mch_set_footer __ARGS((char_u *s));
+void gui_mch_show_toolbar __ARGS((int showit));
+int gui_mch_compute_toolbar_height __ARGS((void));
+void gui_mch_get_toolbar_colors __ARGS((Pixel *bgp, Pixel *fgp, Pixel *bsp, Pixel *tsp, Pixel *hsp));
+void gui_mch_find_dialog __ARGS((exarg_T *eap));
+void gui_mch_replace_dialog __ARGS((exarg_T *eap));
+/* vim: set ft=c : */
diff --git a/src/proto/gui_photon.pro b/src/proto/gui_photon.pro
new file mode 100644
index 000000000..c7354a190
--- /dev/null
+++ b/src/proto/gui_photon.pro
@@ -0,0 +1,66 @@
+/* gui_photon.c */
+void gui_ph_encoding_changed __ARGS((int new_encoding));
+void gui_mch_prepare __ARGS((int *argc, char **argv));
+int gui_mch_init __ARGS((void));
+int gui_mch_init_check __ARGS((void));
+int gui_mch_open __ARGS((void));
+void gui_mch_exit __ARGS((int rc));
+void gui_mch_update __ARGS((void));
+int gui_mch_wait_for_chars __ARGS((int wtime));
+char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *default_name, char_u *ext, char_u *initdir, char_u *filter));
+int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int default_button, char_u *textfield));
+int gui_mch_get_winpos __ARGS((int *x, int *y));
+void gui_mch_set_winpos __ARGS((int x, int y));
+void gui_mch_set_shellsize __ARGS((int width, int height, int min_width, int min_height, int base_width, int base_height));
+void gui_mch_get_screen_dimensions __ARGS((int *screen_w, int *screen_h));
+void gui_mch_iconify __ARGS((void));
+void gui_mch_set_foreground __ARGS((void));
+void gui_mch_settitle __ARGS((char_u *title, char_u *icon));
+void gui_mch_set_scrollbar_thumb __ARGS((scrollbar_T *sb, int val, int size, int max));
+void gui_mch_set_scrollbar_pos __ARGS((scrollbar_T *sb, int x, int y, int w, int h));
+void gui_mch_create_scrollbar __ARGS((scrollbar_T *sb, int orient));
+void gui_mch_enable_scrollbar __ARGS((scrollbar_T *sb, int flag));
+void gui_mch_destroy_scrollbar __ARGS((scrollbar_T *sb));
+void mch_set_mouse_shape __ARGS((int shape));
+void gui_mch_mousehide __ARGS((int hide));
+int gui_mch_get_mouse_x __ARGS((void));
+int gui_mch_get_mouse_y __ARGS((void));
+void gui_mch_setmouse __ARGS((int x, int y));
+long_u gui_mch_get_rgb __ARGS((guicolor_T pixel));
+void gui_mch_new_colors __ARGS((void));
+guicolor_T gui_mch_get_color __ARGS((char_u *name));
+void gui_mch_set_fg_color __ARGS((guicolor_T color));
+void gui_mch_set_bg_color __ARGS((guicolor_T color));
+void gui_mch_invert_rectangle __ARGS((int row, int col, int nr, int nc));
+void gui_mch_clear_block __ARGS((int row1, int col1, int row2, int col2));
+void gui_mch_clear_all __ARGS((void));
+void gui_mch_delete_lines __ARGS((int row, int num_lines));
+void gui_mch_insert_lines __ARGS((int row, int num_lines));
+void gui_mch_draw_string __ARGS((int row, int col, char_u *s, int len, int flags));
+void gui_mch_draw_hollow_cursor __ARGS((guicolor_T color));
+void gui_mch_draw_part_cursor __ARGS((int w, int h, guicolor_T color));
+void gui_mch_set_blinking __ARGS((long wait, long on, long off));
+void gui_mch_start_blink __ARGS((void));
+void gui_mch_stop_blink __ARGS((void));
+void gui_mch_beep __ARGS((void));
+void gui_mch_flash __ARGS((int msec));
+void gui_mch_flush __ARGS((void));
+void gui_mch_set_text_area_pos __ARGS((int x, int y, int w, int h));
+int gui_mch_haskey __ARGS((char_u *name));
+void gui_mch_enable_menu __ARGS((int flag));
+void gui_mch_set_menu_pos __ARGS((int x, int y, int w, int h));
+void gui_mch_add_menu __ARGS((vimmenu_T *menu, int index));
+void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int index));
+void gui_mch_destroy_menu __ARGS((vimmenu_T *menu));
+void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey));
+void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden));
+void gui_mch_draw_menubar __ARGS((void));
+void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu));
+void gui_mch_toggle_tearoffs __ARGS((int enable));
+void gui_mch_show_toolbar __ARGS((int showit));
+int gui_mch_init_font __ARGS((char_u *vim_font_name, int fontset));
+int gui_mch_adjust_charsize __ARGS((void));
+GuiFont gui_mch_get_font __ARGS((char_u *vim_font_name, int report_error));
+void gui_mch_set_font __ARGS((GuiFont font));
+void gui_mch_free_font __ARGS((GuiFont font));
+/* vim: set ft=c : */
diff --git a/src/proto/gui_riscos.pro b/src/proto/gui_riscos.pro
new file mode 100644
index 000000000..3c23fe004
--- /dev/null
+++ b/src/proto/gui_riscos.pro
@@ -0,0 +1,67 @@
+/* Prototypes for gui_riscos.c
+ * Based on gui_x11_pro.h (10 March 2002 version)
+ */
+void gui_mch_prepare __ARGS((int *argc, char **argv));
+int gui_mch_init_check __ARGS((void));
+int gui_mch_init __ARGS((void));
+void gui_mch_uninit __ARGS((void));
+void gui_mch_new_colors __ARGS((void));
+int gui_mch_open __ARGS((void));
+void gui_init_tooltip_font __ARGS((void));
+void gui_init_menu_font __ARGS((void));void gui_mch_exit __ARGS((int rc));
+int gui_mch_get_winpos __ARGS((int *x, int *y));
+void gui_mch_set_winpos __ARGS((int x, int y));
+void gui_mch_set_shellsize __ARGS((int width, int height, int min_width, int min_height, int base_width, int base_height));
+void gui_mch_get_screen_dimensions __ARGS((int *screen_w, int *screen_h));
+int gui_mch_init_font __ARGS((char_u *font_name, int do_fontset));
+GuiFont gui_mch_get_font __ARGS((char_u *name, int giveErrorIfMissing));
+int gui_mch_adjust_charsize __ARGS((void));
+void gui_mch_set_font __ARGS((GuiFont font));
+void gui_mch_set_fontset __ARGS((GuiFontset fontset));
+void gui_mch_free_font __ARGS((GuiFont font));
+void gui_mch_free_fontset __ARGS((GuiFontset fontset));
+GuiFontset gui_mch_get_fontset __ARGS((char_u *name, int giveErrorIfMissing, int fixed_width));
+guicolor_T gui_mch_get_color __ARGS((char_u *reqname));
+void gui_mch_set_fg_color __ARGS((guicolor_T color));
+void gui_mch_set_bg_color __ARGS((guicolor_T color));
+void gui_mch_draw_string __ARGS((int row, int col, char_u *s, int len, int flags));
+int gui_mch_haskey __ARGS((char_u *name));
+void gui_mch_beep __ARGS((void));
+void gui_mch_flash __ARGS((int msec));
+void gui_mch_invert_rectangle __ARGS((int r, int c, int nr, int nc));
+void gui_mch_iconify __ARGS((void));
+void gui_mch_set_foreground __ARGS((void));
+void gui_mch_draw_hollow_cursor __ARGS((guicolor_T color));
+void gui_mch_draw_part_cursor __ARGS((int w, int h, guicolor_T color));
+void gui_mch_update __ARGS((void));
+int gui_mch_wait_for_chars __ARGS((long wtime));
+void gui_mch_flush __ARGS((void));
+void gui_mch_clear_block __ARGS((int row1, int col1, int row2, int col2));
+void gui_mch_clear_all __ARGS((void));
+void gui_mch_delete_lines __ARGS((int row, int num_lines));
+void gui_mch_insert_lines __ARGS((int row, int num_lines));
+void clip_mch_lose_selection __ARGS((VimClipboard *cbd));
+int clip_mch_own_selection __ARGS((VimClipboard *cbd));
+void clip_mch_request_selection __ARGS((VimClipboard *cbd));
+void clip_mch_set_selection __ARGS((VimClipboard *cbd));
+void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey));
+void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden));
+void gui_mch_draw_menubar __ARGS((void));
+void gui_mch_set_blinking __ARGS((long waittime, long on, long off));
+void gui_mch_stop_blink __ARGS((void));
+void gui_mch_start_blink __ARGS((void));
+void process_event __ARGS((int event, int *block));
+void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu));
+long_u gui_mch_get_rgb __ARGS((guicolor_T pixel));
+int gui_mch_get_mouse_x __ARGS((void));
+int gui_mch_get_mouse_y __ARGS((void));
+void gui_mch_setmouse __ARGS((int x, int y));
+void gui_mch_drawsign __ARGS((int row, int col, int typenr));
+void gui_mch_destroy_sign __ARGS((XImage *sign));
+void gui_mch_mousehide __ARGS((int hide));
+void mch_set_mouse_shape __ARGS((int shape));
+void gui_mch_menu_set_tip __ARGS((vimmenu_T *menu));
+
+void ro_redraw_title __ARGS((int window));
+int ro_ok_to_quit __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/gui_w16.pro b/src/proto/gui_w16.pro
new file mode 100644
index 000000000..b43c606ae
--- /dev/null
+++ b/src/proto/gui_w16.pro
@@ -0,0 +1,73 @@
+/* gui_w16.c */
+void gui_mch_set_blinking __ARGS((long wait, long on, long off));
+void gui_mch_stop_blink __ARGS((void));
+void gui_mch_start_blink __ARGS((void));
+LRESULT WINAPI vim_WindowProc __ARGS((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam));
+void gui_mch_new_colors __ARGS((void));
+void gui_mch_def_colors __ARGS((void));
+int gui_mch_open __ARGS((void));
+int gui_mch_get_winpos __ARGS((int *x, int *y));
+void gui_mch_set_winpos __ARGS((int x, int y));
+void gui_mch_set_text_area_pos __ARGS((int x, int y, int w, int h));
+void gui_mch_enable_scrollbar __ARGS((scrollbar_T *sb, int flag));
+void gui_mch_set_scrollbar_pos __ARGS((scrollbar_T *sb, int x, int y, int w, int h));
+void gui_mch_create_scrollbar __ARGS((scrollbar_T *sb, int orient));
+int gui_mch_adjust_charsize __ARGS((void));
+GuiFont gui_mch_get_font __ARGS((char_u *name, int giveErrorIfMissing));
+void gui_mch_free_font __ARGS((GuiFont font));
+guicolor_T gui_mch_get_color __ARGS((char_u *name));
+int gui_mch_haskey __ARGS((char_u *name));
+void gui_mch_beep __ARGS((void));
+void gui_mch_invert_rectangle __ARGS((int r, int c, int nr, int nc));
+void gui_mch_iconify __ARGS((void));
+void gui_mch_draw_hollow_cursor __ARGS((guicolor_T color));
+void gui_mch_draw_part_cursor __ARGS((int w, int h, guicolor_T color));
+void gui_mch_update __ARGS((void));
+int gui_mch_wait_for_chars __ARGS((int wtime));
+void gui_mch_clear_block __ARGS((int row1, int col1, int row2, int col2));
+void gui_mch_clear_all __ARGS((void));
+void gui_mch_enable_menu __ARGS((int flag));
+void gui_mch_set_menu_pos __ARGS((int x, int y, int w, int h));
+void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden));
+void gui_mch_draw_menubar __ARGS((void));
+long_u gui_mch_get_rgb __ARGS((guicolor_T pixel));
+void gui_mch_activate_window __ARGS((void));
+void gui_mch_show_toolbar __ARGS((int showit));
+void ex_simalt __ARGS((exarg_T *eap));
+void gui_mch_find_dialog __ARGS((exarg_T *eap));
+void gui_mch_replace_dialog __ARGS((exarg_T *eap));
+void gui_mch_mousehide __ARGS((int hide));
+void gui_mch_destroy_scrollbar __ARGS((scrollbar_T *sb));
+int gui_mch_get_mouse_x __ARGS((void));
+int gui_mch_get_mouse_y __ARGS((void));
+void gui_mch_setmouse __ARGS((int x, int y));
+void gui_mch_get_screen_dimensions __ARGS((int *screen_w, int *screen_h));
+void gui_mch_flash __ARGS((int msec));
+void gui_mch_delete_lines __ARGS((int row, int num_lines));
+void gui_mch_insert_lines __ARGS((int row, int num_lines));
+void gui_mch_exit __ARGS((int rc));
+int gui_mch_init_font __ARGS((char_u *font_name, int fontset));
+int gui_mch_maximized __ARGS((void));
+void gui_mch_newfont __ARGS((void));
+void gui_mch_settitle __ARGS((char_u *title, char_u *icon));
+void mch_set_mouse_shape __ARGS((int shape));
+char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter));
+int get_cmd_args __ARGS((char *prog, char *cmdline, char ***argvp, char **tofree));
+void gui_mch_prepare __ARGS((int *argc, char **argv));
+int gui_mch_init __ARGS((void));
+void gui_mch_set_shellsize __ARGS((int width, int height, int min_width, int min_height, int base_width, int base_height));
+void gui_mch_set_scrollbar_thumb __ARGS((scrollbar_T *sb, long val, long size, long max));
+void gui_mch_set_font __ARGS((GuiFont font));
+void gui_mch_set_fg_color __ARGS((guicolor_T color));
+void gui_mch_set_bg_color __ARGS((guicolor_T color));
+void gui_mch_draw_string __ARGS((int row, int col, char_u *text, int len, int flags));
+void gui_mch_flush __ARGS((void));
+void gui_mch_add_menu __ARGS((vimmenu_T *menu, int pos));
+void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu));
+void gui_make_popup __ARGS((char_u *path_name));
+void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int idx));
+void gui_mch_destroy_menu __ARGS((vimmenu_T *menu));
+void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey));
+int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield));
+void gui_mch_set_foreground __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/gui_w32.pro b/src/proto/gui_w32.pro
new file mode 100644
index 000000000..58ad4f4ee
--- /dev/null
+++ b/src/proto/gui_w32.pro
@@ -0,0 +1,89 @@
+/* gui_w32.c */
+void gui_mch_set_blinking __ARGS((long wait, long on, long off));
+void gui_mch_stop_blink __ARGS((void));
+void gui_mch_start_blink __ARGS((void));
+LRESULT WINAPI vim_WindowProc __ARGS((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam));
+void gui_mch_new_colors __ARGS((void));
+void gui_mch_def_colors __ARGS((void));
+int gui_mch_open __ARGS((void));
+int gui_mch_get_winpos __ARGS((int *x, int *y));
+void gui_mch_set_winpos __ARGS((int x, int y));
+void gui_mch_set_text_area_pos __ARGS((int x, int y, int w, int h));
+void gui_mch_enable_scrollbar __ARGS((scrollbar_T *sb, int flag));
+void gui_mch_set_scrollbar_pos __ARGS((scrollbar_T *sb, int x, int y, int w, int h));
+void gui_mch_create_scrollbar __ARGS((scrollbar_T *sb, int orient));
+int gui_mch_adjust_charsize __ARGS((void));
+GuiFont gui_mch_get_font __ARGS((char_u *name, int giveErrorIfMissing));
+void gui_mch_free_font __ARGS((GuiFont font));
+guicolor_T gui_mch_get_color __ARGS((char_u *name));
+int gui_mch_haskey __ARGS((char_u *name));
+void gui_mch_beep __ARGS((void));
+void gui_mch_invert_rectangle __ARGS((int r, int c, int nr, int nc));
+void gui_mch_iconify __ARGS((void));
+void gui_mch_draw_hollow_cursor __ARGS((guicolor_T color));
+void gui_mch_draw_part_cursor __ARGS((int w, int h, guicolor_T color));
+void gui_mch_update __ARGS((void));
+int gui_mch_wait_for_chars __ARGS((int wtime));
+void gui_mch_clear_block __ARGS((int row1, int col1, int row2, int col2));
+void gui_mch_clear_all __ARGS((void));
+void gui_mch_enable_menu __ARGS((int flag));
+void gui_mch_set_menu_pos __ARGS((int x, int y, int w, int h));
+void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden));
+void gui_mch_draw_menubar __ARGS((void));
+long_u gui_mch_get_rgb __ARGS((guicolor_T pixel));
+void gui_mch_activate_window __ARGS((void));
+void gui_mch_show_toolbar __ARGS((int showit));
+void ex_simalt __ARGS((exarg_T *eap));
+void gui_mch_find_dialog __ARGS((exarg_T *eap));
+void gui_mch_replace_dialog __ARGS((exarg_T *eap));
+void gui_mch_mousehide __ARGS((int hide));
+void gui_mch_destroy_scrollbar __ARGS((scrollbar_T *sb));
+int gui_mch_get_mouse_x __ARGS((void));
+int gui_mch_get_mouse_y __ARGS((void));
+void gui_mch_setmouse __ARGS((int x, int y));
+void gui_mch_get_screen_dimensions __ARGS((int *screen_w, int *screen_h));
+void gui_mch_flash __ARGS((int msec));
+void gui_mch_delete_lines __ARGS((int row, int num_lines));
+void gui_mch_insert_lines __ARGS((int row, int num_lines));
+void gui_mch_exit __ARGS((int rc));
+int gui_mch_init_font __ARGS((char_u *font_name, int fontset));
+int gui_mch_maximized __ARGS((void));
+void gui_mch_newfont __ARGS((void));
+void gui_mch_settitle __ARGS((char_u *title, char_u *icon));
+void mch_set_mouse_shape __ARGS((int shape));
+char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter));
+int get_cmd_args __ARGS((char *prog, char *cmdline, char ***argvp, char **tofree));
+int gui_is_win32s __ARGS((void));
+void gui_mch_set_parent __ARGS((char *title));
+void gui_mch_prepare __ARGS((int *argc, char **argv));
+int gui_mch_init __ARGS((void));
+void gui_mch_set_shellsize __ARGS((int width, int height, int min_width, int min_height, int base_width, int base_height));
+void gui_mch_set_scrollbar_thumb __ARGS((scrollbar_T *sb, long val, long size, long max));
+void gui_mch_set_font __ARGS((GuiFont font));
+void gui_mch_set_fg_color __ARGS((guicolor_T color));
+void gui_mch_set_bg_color __ARGS((guicolor_T color));
+void im_set_font __ARGS((LOGFONT *lf));
+void im_set_position __ARGS((int row, int col));
+void im_set_active __ARGS((int active));
+int im_get_status __ARGS((void));
+void gui_mch_draw_string __ARGS((int row, int col, char_u *text, int len, int flags));
+void gui_mch_flush __ARGS((void));
+void gui_mch_add_menu __ARGS((vimmenu_T *menu, int pos));
+void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu));
+void gui_make_popup __ARGS((char_u *path_name));
+void gui_make_tearoff __ARGS((char_u *path_name));
+void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int idx));
+void gui_mch_destroy_menu __ARGS((vimmenu_T *menu));
+void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey));
+int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield));
+void gui_mch_set_foreground __ARGS((void));
+void gui_mch_drawsign __ARGS((int row, int col, int typenr));
+void *gui_mch_register_sign __ARGS((char_u *signfile));
+void gui_mch_destroy_sign __ARGS((void *sign));
+void gui_mch_disable_beval_area __ARGS((BalloonEval *beval));
+void gui_mch_enable_beval_area __ARGS((BalloonEval *beval));
+void gui_mch_post_balloon __ARGS((BalloonEval *beval, char_u *mesg));
+BalloonEval *gui_mch_create_beval_area __ARGS((void *target, char_u *mesg, void (*mesgCB)(BalloonEval *, int), void *clientData));
+void gui_mch_destroy_beval_area __ARGS((BalloonEval *beval));
+void netbeans_draw_multisign_indicator __ARGS((int row));
+/* vim: set ft=c : */
diff --git a/src/proto/gui_x11.pro b/src/proto/gui_x11.pro
new file mode 100644
index 000000000..6524c265d
--- /dev/null
+++ b/src/proto/gui_x11.pro
@@ -0,0 +1,70 @@
+/* gui_x11.c */
+void gui_x11_key_hit_cb __ARGS((Widget w, XtPointer dud, XEvent *event, Boolean *dum));
+void gui_mch_prepare __ARGS((int *argc, char **argv));
+int gui_mch_init_check __ARGS((void));
+int gui_mch_init __ARGS((void));
+void gui_mch_uninit __ARGS((void));
+void gui_mch_new_colors __ARGS((void));
+int gui_mch_open __ARGS((void));
+void gui_init_tooltip_font __ARGS((void));
+void gui_init_menu_font __ARGS((void));
+void gui_mch_exit __ARGS((int rc));
+int gui_mch_get_winpos __ARGS((int *x, int *y));
+void gui_mch_set_winpos __ARGS((int x, int y));
+void gui_mch_set_shellsize __ARGS((int width, int height, int min_width, int min_height, int base_width, int base_height));
+void gui_mch_get_screen_dimensions __ARGS((int *screen_w, int *screen_h));
+int gui_mch_init_font __ARGS((char_u *font_name, int do_fontset));
+GuiFont gui_mch_get_font __ARGS((char_u *name, int giveErrorIfMissing));
+int gui_mch_adjust_charsize __ARGS((void));
+void gui_mch_set_font __ARGS((GuiFont font));
+void gui_mch_set_fontset __ARGS((GuiFontset fontset));
+void gui_mch_free_font __ARGS((GuiFont font));
+void gui_mch_free_fontset __ARGS((GuiFontset fontset));
+GuiFontset gui_mch_get_fontset __ARGS((char_u *name, int giveErrorIfMissing, int fixed_width));
+int fontset_height __ARGS((XFontSet fs));
+int fontset_height2 __ARGS((XFontSet fs));
+guicolor_T gui_mch_get_color __ARGS((char_u *reqname));
+void gui_mch_set_fg_color __ARGS((guicolor_T color));
+void gui_mch_set_bg_color __ARGS((guicolor_T color));
+void gui_mch_draw_string __ARGS((int row, int col, char_u *s, int len, int flags));
+int gui_mch_haskey __ARGS((char_u *name));
+int gui_get_x11_windis __ARGS((Window *win, Display **dis));
+void gui_mch_beep __ARGS((void));
+void gui_mch_flash __ARGS((int msec));
+void gui_mch_invert_rectangle __ARGS((int r, int c, int nr, int nc));
+void gui_mch_iconify __ARGS((void));
+void gui_mch_set_foreground __ARGS((void));
+void gui_mch_draw_hollow_cursor __ARGS((guicolor_T color));
+void gui_mch_draw_part_cursor __ARGS((int w, int h, guicolor_T color));
+void gui_mch_update __ARGS((void));
+int gui_mch_wait_for_chars __ARGS((long wtime));
+void gui_mch_flush __ARGS((void));
+void gui_mch_clear_block __ARGS((int row1, int col1, int row2, int col2));
+void gui_mch_clear_all __ARGS((void));
+void gui_mch_delete_lines __ARGS((int row, int num_lines));
+void gui_mch_insert_lines __ARGS((int row, int num_lines));
+void clip_mch_lose_selection __ARGS((VimClipboard *cbd));
+int clip_mch_own_selection __ARGS((VimClipboard *cbd));
+void clip_mch_request_selection __ARGS((VimClipboard *cbd));
+void clip_mch_set_selection __ARGS((VimClipboard *cbd));
+void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey));
+void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden));
+void gui_mch_draw_menubar __ARGS((void));
+void gui_x11_menu_cb __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
+void gui_mch_set_blinking __ARGS((long waittime, long on, long off));
+void gui_mch_stop_blink __ARGS((void));
+void gui_mch_start_blink __ARGS((void));
+long_u gui_mch_get_rgb __ARGS((guicolor_T pixel));
+void gui_x11_callbacks __ARGS((Widget textArea, Widget vimForm));
+int gui_mch_get_mouse_x __ARGS((void));
+int gui_mch_get_mouse_y __ARGS((void));
+void gui_mch_setmouse __ARGS((int x, int y));
+XButtonPressedEvent *gui_x11_get_last_mouse_event __ARGS((void));
+void gui_mch_drawsign __ARGS((int row, int col, int typenr));
+void *gui_mch_register_sign __ARGS((char_u *signfile));
+void gui_mch_destroy_sign __ARGS((void *sign));
+void gui_mch_mousehide __ARGS((int hide));
+void mch_set_mouse_shape __ARGS((int shape));
+void get_toolbar_pixmap __ARGS((vimmenu_T *menu, Pixmap *sen, Pixmap *insen));
+void gui_mch_menu_set_tip __ARGS((vimmenu_T *menu));
+/* vim: set ft=c : */
diff --git a/src/proto/hangulin.pro b/src/proto/hangulin.pro
new file mode 100644
index 000000000..adfde142f
--- /dev/null
+++ b/src/proto/hangulin.pro
@@ -0,0 +1,9 @@
+/* hangulin.c */
+int hangul_input_state_get __ARGS((void));
+void hangul_input_state_set __ARGS((int state));
+int im_get_status __ARGS((void));
+void hangul_input_state_toggle __ARGS((void));
+void hangul_keyboard_set __ARGS((void));
+int hangul_input_process __ARGS((char_u *s, int len));
+void hangul_input_clear __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/if_cscope.pro b/src/proto/if_cscope.pro
new file mode 100644
index 000000000..0617d13a9
--- /dev/null
+++ b/src/proto/if_cscope.pro
@@ -0,0 +1,9 @@
+/* if_cscope.c */
+void do_cscope __ARGS((exarg_T *eap));
+void do_scscope __ARGS((exarg_T *eap));
+void do_cstag __ARGS((exarg_T *eap));
+int cs_fgets __ARGS((char_u *buf, int size));
+void cs_free_tags __ARGS((void));
+void cs_print_tags __ARGS((void));
+int cs_connection __ARGS((int num, char_u *dbpath, char_u *ppath));
+/* vim: set ft=c : */
diff --git a/src/proto/if_ole.pro b/src/proto/if_ole.pro
new file mode 100644
index 000000000..36edcb0d2
--- /dev/null
+++ b/src/proto/if_ole.pro
@@ -0,0 +1,5 @@
+/* if_ole.cpp */
+void InitOLE __ARGS((int* pbDoRestart));
+void UninitOLE __ARGS((void));
+void RegisterMe __ARGS((int silent));
+void UnregisterMe __ARGS((int bNotifyUser));
diff --git a/src/proto/if_perl.pro b/src/proto/if_perl.pro
new file mode 100644
index 000000000..fe0301b0b
--- /dev/null
+++ b/src/proto/if_perl.pro
@@ -0,0 +1,8 @@
+/* auto/if_perl.c */
+int perl_enabled __ARGS((int verbose));
+void perl_end __ARGS((void));
+void msg_split __ARGS((char_u *s, int attr));
+void perl_win_free __ARGS((win_T *wp));
+void perl_buf_free __ARGS((buf_T *bp));
+void ex_perl __ARGS((exarg_T *eap));
+void ex_perldo __ARGS((exarg_T *eap));
diff --git a/src/proto/if_perlsfio.pro b/src/proto/if_perlsfio.pro
new file mode 100644
index 000000000..bb9046809
--- /dev/null
+++ b/src/proto/if_perlsfio.pro
@@ -0,0 +1,3 @@
+/* if_perlsfio.c */
+int *sfdcnewvim __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/if_python.pro b/src/proto/if_python.pro
new file mode 100644
index 000000000..793b6eeb5
--- /dev/null
+++ b/src/proto/if_python.pro
@@ -0,0 +1,8 @@
+/* if_python.c */
+int python_enabled __ARGS((int verbose));
+void python_end __ARGS((void));
+void ex_python __ARGS((exarg_T *eap));
+void ex_pyfile __ARGS((exarg_T *eap));
+void python_buffer_free __ARGS((buf_T *buf));
+void python_window_free __ARGS((win_T *win));
+/* vim: set ft=c : */
diff --git a/src/proto/if_ruby.pro b/src/proto/if_ruby.pro
new file mode 100644
index 000000000..7dedb225c
--- /dev/null
+++ b/src/proto/if_ruby.pro
@@ -0,0 +1,9 @@
+/* if_ruby.c */
+int ruby_enabled __ARGS((int verbose));
+void ruby_end __ARGS((void));
+void ex_ruby __ARGS((exarg_T *eap));
+void ex_rubydo __ARGS((exarg_T *eap));
+void ex_rubyfile __ARGS((exarg_T *eap));
+void ruby_buffer_free __ARGS((buf_T *buf));
+void ruby_window_free __ARGS((win_T *win));
+/* vim: set ft=c : */
diff --git a/src/proto/if_tcl.pro b/src/proto/if_tcl.pro
new file mode 100644
index 000000000..0679ed41a
--- /dev/null
+++ b/src/proto/if_tcl.pro
@@ -0,0 +1,10 @@
+/* if_tcl.c */
+void vim_tcl_init __ARGS((char *arg));
+int tcl_enabled __ARGS((int verbose));
+void tcl_end __ARGS((void));
+void ex_tcl __ARGS((exarg_T *eap));
+void ex_tclfile __ARGS((exarg_T *eap));
+void ex_tcldo __ARGS((exarg_T *eap));
+void tcl_buffer_free __ARGS((buf_T *buf));
+void tcl_window_free __ARGS((win_T *win));
+/* vim: set ft=c : */
diff --git a/src/proto/if_xcmdsrv.pro b/src/proto/if_xcmdsrv.pro
new file mode 100644
index 000000000..dd6a12084
--- /dev/null
+++ b/src/proto/if_xcmdsrv.pro
@@ -0,0 +1,11 @@
+/* if_xcmdsrv.c */
+int serverRegisterName __ARGS((Display *dpy, char_u *name));
+void serverChangeRegisteredWindow __ARGS((Display *dpy, Window newwin));
+int serverSendToVim __ARGS((Display *dpy, char_u *name, char_u *cmd, char_u **result, Window *server, int asExpr, int localLoop, int silent));
+char_u *serverGetVimNames __ARGS((Display *dpy));
+Window serverStrToWin __ARGS((char_u *str));
+int serverSendReply __ARGS((char_u *name, char_u *str));
+int serverReadReply __ARGS((Display *dpy, Window win, char_u **str, int localLoop));
+int serverPeekReply __ARGS((Display *dpy, Window win, char_u **str));
+void serverEventProc __ARGS((Display *dpy, XEvent *eventPtr));
+/* vim: set ft=c : */
diff --git a/src/proto/main.pro b/src/proto/main.pro
new file mode 100644
index 000000000..7e965fb94
--- /dev/null
+++ b/src/proto/main.pro
@@ -0,0 +1,25 @@
+/* main.c */
+void main_loop __ARGS((int cmdwin));
+void getout_preserve_modified __ARGS((int exitval));
+void getout __ARGS((int exitval));
+int process_env __ARGS((char_u *env, int is_viminit));
+void mainerr_arg_missing __ARGS((char_u *str));
+void time_push __ARGS((void *tv_rel, void *tv_start));
+void time_pop __ARGS((void *tp));
+void time_msg __ARGS((char *msg, void *tv_start));
+void server_to_input_buf __ARGS((char_u *str));
+char_u *eval_client_expr_to_string __ARGS((char_u *expr));
+int toF_TyA __ARGS((int c));
+int fkmap __ARGS((int c));
+void conv_to_pvim __ARGS((void));
+void conv_to_pstd __ARGS((void));
+char_u *lrswap __ARGS((char_u *ibuf));
+char_u *lrFswap __ARGS((char_u *cmdbuf, int len));
+char_u *lrF_sub __ARGS((char_u *ibuf));
+int cmdl_fkmap __ARGS((int c));
+int F_isalpha __ARGS((int c));
+int F_isdigit __ARGS((int c));
+int F_ischar __ARGS((int c));
+void farsi_fkey __ARGS((cmdarg_T *cap));
+int arabic_shape __ARGS((int c, int *ccp, int *c1p, int prev_c, int prev_c1, int next_c));
+/* vim: set ft=c : */
diff --git a/src/proto/mark.pro b/src/proto/mark.pro
new file mode 100644
index 000000000..b90a1b07a
--- /dev/null
+++ b/src/proto/mark.pro
@@ -0,0 +1,26 @@
+/* mark.c */
+int setmark __ARGS((int c));
+void setpcmark __ARGS((void));
+void checkpcmark __ARGS((void));
+pos_T *movemark __ARGS((int count));
+pos_T *movechangelist __ARGS((int count));
+pos_T *getmark __ARGS((int c, int changefile));
+pos_T *getnextmark __ARGS((pos_T *startpos, int dir, int begin_line));
+void fmarks_check_names __ARGS((buf_T *buf));
+int check_mark __ARGS((pos_T *pos));
+void clrallmarks __ARGS((buf_T *buf));
+char_u *fm_getname __ARGS((fmark_T *fmark, int lead_len));
+void do_marks __ARGS((exarg_T *eap));
+void ex_jumps __ARGS((exarg_T *eap));
+void ex_changes __ARGS((exarg_T *eap));
+void mark_adjust __ARGS((linenr_T line1, linenr_T line2, long amount, long amount_after));
+void mark_col_adjust __ARGS((linenr_T lnum, colnr_T mincol, long lnum_amount, long col_amount));
+void copy_jumplist __ARGS((win_T *from, win_T *to));
+void free_jumplist __ARGS((win_T *wp));
+void set_last_cursor __ARGS((win_T *win));
+int read_viminfo_filemark __ARGS((vir_T *virp, int force));
+void write_viminfo_filemarks __ARGS((FILE *fp));
+int removable __ARGS((char_u *name));
+int write_viminfo_marks __ARGS((FILE *fp_out));
+void copy_viminfo_marks __ARGS((vir_T *virp, FILE *fp_out, int count, int eof));
+/* vim: set ft=c : */
diff --git a/src/proto/mbyte.pro b/src/proto/mbyte.pro
new file mode 100644
index 000000000..9567a0acb
--- /dev/null
+++ b/src/proto/mbyte.pro
@@ -0,0 +1,86 @@
+/* mbyte.c */
+int enc_canon_props __ARGS((char_u *name));
+char_u *mb_init __ARGS((void));
+int bomb_size __ARGS((void));
+int mb_get_class __ARGS((char_u *p));
+int dbcs_class __ARGS((unsigned lead, unsigned trail));
+int latin_char2len __ARGS((int c));
+int latin_char2bytes __ARGS((int c, char_u *buf));
+int latin_ptr2len_check __ARGS((char_u *p));
+int utf_char2cells __ARGS((int c));
+int latin_ptr2cells __ARGS((char_u *p));
+int utf_ptr2cells __ARGS((char_u *p));
+int dbcs_ptr2cells __ARGS((char_u *p));
+int latin_char2cells __ARGS((int c));
+int latin_off2cells __ARGS((unsigned off));
+int dbcs_off2cells __ARGS((unsigned off));
+int utf_off2cells __ARGS((unsigned off));
+int latin_ptr2char __ARGS((char_u *p));
+int utf_ptr2char __ARGS((char_u *p));
+int mb_ptr2char_adv __ARGS((char_u **pp));
+int arabic_combine __ARGS((int one, int two));
+int arabic_maycombine __ARGS((int two));
+int utf_composinglike __ARGS((char_u *p1, char_u *p2));
+int utfc_ptr2char __ARGS((char_u *p, int *p1, int *p2));
+int utfc_ptr2char_len __ARGS((char_u *p, int *p1, int *p2, int maxlen));
+int utfc_char2bytes __ARGS((int off, char_u *buf));
+int utf_ptr2len_check __ARGS((char_u *p));
+int utf_byte2len __ARGS((int b));
+int utf_ptr2len_check_len __ARGS((char_u *p, int size));
+int utfc_ptr2len_check __ARGS((char_u *p));
+int utfc_ptr2len_check_len __ARGS((char_u *p, int size));
+int utf_char2len __ARGS((int c));
+int utf_char2bytes __ARGS((int c, char_u *buf));
+int utf_iscomposing __ARGS((int c));
+int utf_printable __ARGS((int c));
+int utf_class __ARGS((int c));
+int utf_fold __ARGS((int a));
+int utf_toupper __ARGS((int a));
+int utf_islower __ARGS((int a));
+int utf_tolower __ARGS((int a));
+int utf_isupper __ARGS((int a));
+int mb_strnicmp __ARGS((char_u *s1, char_u *s2, int n));
+void show_utf8 __ARGS((void));
+int latin_head_off __ARGS((char_u *base, char_u *p));
+int dbcs_head_off __ARGS((char_u *base, char_u *p));
+int dbcs_screen_head_off __ARGS((char_u *base, char_u *p));
+int utf_head_off __ARGS((char_u *base, char_u *p));
+int mb_off_next __ARGS((char_u *base, char_u *p));
+int mb_tail_off __ARGS((char_u *base, char_u *p));
+int dbcs_screen_tail_off __ARGS((char_u *base, char_u *p));
+void mb_adjust_cursor __ARGS((void));
+void mb_adjustpos __ARGS((pos_T *lp));
+char_u *mb_prevptr __ARGS((char_u *line, char_u *p));
+int mb_charlen __ARGS((char_u *str));
+char_u *mb_unescape __ARGS((char_u **pp));
+int mb_lefthalve __ARGS((int row, int col));
+int mb_fix_col __ARGS((int col, int row));
+char_u *enc_skip __ARGS((char_u *p));
+char_u *enc_canonize __ARGS((char_u *enc));
+char_u *enc_locale __ARGS((void));
+int encname2codepage __ARGS((char_u *name));
+void *my_iconv_open __ARGS((char_u *to, char_u *from));
+int iconv_enabled __ARGS((int verbose));
+void iconv_end __ARGS((void));
+int im_xim_isvalid_imactivate __ARGS((void));
+void im_set_active __ARGS((int active));
+void xim_set_focus __ARGS((int focus));
+void im_set_position __ARGS((int row, int col));
+void xim_set_preedit __ARGS((void));
+void xim_set_status_area __ARGS((void));
+void xim_init __ARGS((void));
+void xim_decide_input_style __ARGS((void));
+int im_get_feedback_attr __ARGS((int col));
+void xim_reset __ARGS((void));
+int xim_queue_key_press_event __ARGS((GdkEventKey *event, int down));
+void xim_init __ARGS((void));
+void im_shutdown __ARGS((void));
+int xim_get_status_area_height __ARGS((void));
+int im_get_status __ARGS((void));
+int im_is_preediting __ARGS((void));
+int convert_setup __ARGS((vimconv_T *vcp, char_u *from, char_u *to));
+int convert_input __ARGS((char_u *ptr, int len, int maxlen));
+int convert_input_safe __ARGS((char_u *ptr, int len, int maxlen, char_u **restp, int *restlenp));
+char_u *string_convert __ARGS((vimconv_T *vcp, char_u *ptr, int *lenp));
+char_u *string_convert_ext __ARGS((vimconv_T *vcp, char_u *ptr, int *lenp, int *unconvlenp));
+/* vim: set ft=c : */
diff --git a/src/proto/memfile.pro b/src/proto/memfile.pro
new file mode 100644
index 000000000..3feb67744
--- /dev/null
+++ b/src/proto/memfile.pro
@@ -0,0 +1,17 @@
+/* memfile.c */
+memfile_T *mf_open __ARGS((char_u *fname, int flags));
+int mf_open_file __ARGS((memfile_T *mfp, char_u *fname));
+void mf_close __ARGS((memfile_T *mfp, int del_file));
+void mf_close_file __ARGS((buf_T *buf, int getlines));
+void mf_new_page_size __ARGS((memfile_T *mfp, unsigned new_size));
+bhdr_T *mf_new __ARGS((memfile_T *mfp, int negative, int page_count));
+bhdr_T *mf_get __ARGS((memfile_T *mfp, blocknr_T nr, int page_count));
+void mf_put __ARGS((memfile_T *mfp, bhdr_T *hp, int dirty, int infile));
+void mf_free __ARGS((memfile_T *mfp, bhdr_T *hp));
+int mf_sync __ARGS((memfile_T *mfp, int flags));
+int mf_release_all __ARGS((void));
+blocknr_T mf_trans_del __ARGS((memfile_T *mfp, blocknr_T old_nr));
+void mf_set_ffname __ARGS((memfile_T *mfp));
+void mf_fullname __ARGS((memfile_T *mfp));
+int mf_need_trans __ARGS((memfile_T *mfp));
+/* vim: set ft=c : */
diff --git a/src/proto/memline.pro b/src/proto/memline.pro
new file mode 100644
index 000000000..36d1086c9
--- /dev/null
+++ b/src/proto/memline.pro
@@ -0,0 +1,31 @@
+/* memline.c */
+int ml_open __ARGS((void));
+void ml_setname __ARGS((buf_T *buf));
+void ml_open_files __ARGS((void));
+void ml_open_file __ARGS((buf_T *buf));
+void check_need_swap __ARGS((int newfile));
+void ml_close __ARGS((buf_T *buf, int del_file));
+void ml_close_all __ARGS((int del_file));
+void ml_close_notmod __ARGS((void));
+void ml_timestamp __ARGS((buf_T *buf));
+void ml_recover __ARGS((void));
+int recover_names __ARGS((char_u **fname, int list, int nr));
+void ml_sync_all __ARGS((int check_file, int check_char));
+void ml_preserve __ARGS((buf_T *buf, int message));
+char_u *ml_get __ARGS((linenr_T lnum));
+char_u *ml_get_pos __ARGS((pos_T *pos));
+char_u *ml_get_curline __ARGS((void));
+char_u *ml_get_cursor __ARGS((void));
+char_u *ml_get_buf __ARGS((buf_T *buf, linenr_T lnum, int will_change));
+int ml_line_alloced __ARGS((void));
+int ml_append __ARGS((linenr_T lnum, char_u *line, colnr_T len, int newfile));
+int ml_replace __ARGS((linenr_T lnum, char_u *line, int copy));
+int ml_delete __ARGS((linenr_T lnum, int message));
+void ml_setmarked __ARGS((linenr_T lnum));
+linenr_T ml_firstmarked __ARGS((void));
+void ml_clearmarked __ARGS((void));
+char_u *get_file_in_dir __ARGS((char_u *fname, char_u *dname));
+void ml_setdirty __ARGS((buf_T *buf, int flag));
+long ml_find_line_or_offset __ARGS((buf_T *buf, linenr_T line, long *offp));
+void goto_byte __ARGS((long cnt));
+/* vim: set ft=c : */
diff --git a/src/proto/menu.pro b/src/proto/menu.pro
new file mode 100644
index 000000000..506a963b2
--- /dev/null
+++ b/src/proto/menu.pro
@@ -0,0 +1,21 @@
+/* menu.c */
+void ex_menu __ARGS((exarg_T *eap));
+char_u *set_context_in_menu_cmd __ARGS((expand_T *xp, char_u *cmd, char_u *arg, int forceit));
+char_u *get_menu_name __ARGS((expand_T *xp, int idx));
+char_u *get_menu_names __ARGS((expand_T *xp, int idx));
+char_u *menu_name_skip __ARGS((char_u *name));
+int get_menu_index __ARGS((vimmenu_T *menu, int state));
+int menu_is_menubar __ARGS((char_u *name));
+int menu_is_popup __ARGS((char_u *name));
+int menu_is_child_of_popup __ARGS((vimmenu_T *menu));
+int menu_is_toolbar __ARGS((char_u *name));
+int menu_is_separator __ARGS((char_u *name));
+void gui_create_initial_menus __ARGS((vimmenu_T *menu));
+void gui_update_menus __ARGS((int modes));
+int gui_is_menu_shortcut __ARGS((int key));
+void gui_show_popupmenu __ARGS((void));
+void gui_mch_toggle_tearoffs __ARGS((int enable));
+void ex_emenu __ARGS((exarg_T *eap));
+vimmenu_T *gui_find_menu __ARGS((char_u *path_name));
+void ex_menutranslate __ARGS((exarg_T *eap));
+/* vim: set ft=c : */
diff --git a/src/proto/message.pro b/src/proto/message.pro
new file mode 100644
index 000000000..937765424
--- /dev/null
+++ b/src/proto/message.pro
@@ -0,0 +1,57 @@
+/* message.c */
+int msg __ARGS((char_u *s));
+int msg_attr __ARGS((char_u *s, int attr));
+int msg_attr_keep __ARGS((char_u *s, int attr, int keep));
+char_u *msg_strtrunc __ARGS((char_u *s));
+void trunc_string __ARGS((char_u *s, char_u *buf, int room));
+int emsg __ARGS((char_u *s));
+int emsg2 __ARGS((char_u *s, char_u *a1));
+int emsg3 __ARGS((char_u *s, char_u *a1, char_u *a2));
+int emsgn __ARGS((char_u *s, long n));
+char_u *msg_trunc_attr __ARGS((char_u *s, int force, int attr));
+char_u *msg_may_trunc __ARGS((int force, char_u *s));
+void ex_messages __ARGS((exarg_T *eap));
+void wait_return __ARGS((int redraw));
+void set_keep_msg __ARGS((char_u *s));
+void msg_start __ARGS((void));
+void msg_starthere __ARGS((void));
+void msg_putchar __ARGS((int c));
+void msg_putchar_attr __ARGS((int c, int attr));
+void msg_outnum __ARGS((long n));
+void msg_home_replace __ARGS((char_u *fname));
+void msg_home_replace_hl __ARGS((char_u *fname));
+int msg_outtrans __ARGS((char_u *str));
+int msg_outtrans_attr __ARGS((char_u *str, int attr));
+int msg_outtrans_len __ARGS((char_u *str, int len));
+char_u *msg_outtrans_one __ARGS((char_u *p, int attr));
+int msg_outtrans_len_attr __ARGS((char_u *msgstr, int len, int attr));
+void msg_make __ARGS((char_u *arg));
+int msg_outtrans_special __ARGS((char_u *strstart, int from));
+char_u *str2special __ARGS((char_u **sp, int from));
+void str2specialbuf __ARGS((char_u *sp, char_u *buf, int len));
+void msg_prt_line __ARGS((char_u *s));
+void msg_puts __ARGS((char_u *s));
+void msg_puts_title __ARGS((char_u *s));
+void msg_puts_long __ARGS((char_u *longstr));
+void msg_puts_long_attr __ARGS((char_u *longstr, int attr));
+void msg_puts_long_len_attr __ARGS((char_u *longstr, int len, int attr));
+void msg_puts_attr __ARGS((char_u *s, int attr));
+int msg_use_printf __ARGS((void));
+void mch_errmsg __ARGS((char *str));
+void mch_msg __ARGS((char *str));
+void msg_moremsg __ARGS((int full));
+void repeat_message __ARGS((void));
+void msg_clr_eos __ARGS((void));
+void msg_clr_eos_force __ARGS((void));
+void msg_clr_cmdline __ARGS((void));
+int msg_end __ARGS((void));
+void msg_check __ARGS((void));
+void give_warning __ARGS((char_u *message, int hl));
+void msg_advance __ARGS((int col));
+int do_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield));
+void display_confirm_msg __ARGS((void));
+int vim_dialog_yesno __ARGS((int type, char_u *title, char_u *message, int dflt));
+int vim_dialog_yesnocancel __ARGS((int type, char_u *title, char_u *message, int dflt));
+int vim_dialog_yesnoallcancel __ARGS((int type, char_u *title, char_u *message, int dflt));
+char_u *do_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter, buf_T *buf));
+/* vim: set ft=c : */
diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro
new file mode 100644
index 000000000..3fac334ab
--- /dev/null
+++ b/src/proto/misc1.pro
@@ -0,0 +1,87 @@
+/* misc1.c */
+int get_indent __ARGS((void));
+int get_indent_lnum __ARGS((linenr_T lnum));
+int get_indent_buf __ARGS((buf_T *buf, linenr_T lnum));
+int set_indent __ARGS((int size, int flags));
+int get_number_indent __ARGS((linenr_T lnum));
+int open_line __ARGS((int dir, int flags, int old_indent));
+int get_leader_len __ARGS((char_u *line, char_u **flags, int backward));
+int plines __ARGS((linenr_T lnum));
+int plines_win __ARGS((win_T *wp, linenr_T lnum, int winheight));
+int plines_nofill __ARGS((linenr_T lnum));
+int plines_win_nofill __ARGS((win_T *wp, linenr_T lnum, int winheight));
+int plines_win_nofold __ARGS((win_T *wp, linenr_T lnum));
+int plines_win_col __ARGS((win_T *wp, linenr_T lnum, long column));
+int plines_m_win __ARGS((win_T *wp, linenr_T first, linenr_T last));
+void ins_bytes __ARGS((char_u *p));
+void ins_bytes_len __ARGS((char_u *p, int len));
+void ins_char __ARGS((int c));
+void ins_char_bytes __ARGS((char_u *buf, int charlen));
+void ins_str __ARGS((char_u *s));
+int del_char __ARGS((int fixpos));
+int del_chars __ARGS((long count, int fixpos));
+int del_bytes __ARGS((long count, int fixpos));
+int truncate_line __ARGS((int fixpos));
+void del_lines __ARGS((long nlines, int undo));
+int gchar_pos __ARGS((pos_T *pos));
+int gchar_cursor __ARGS((void));
+void pchar_cursor __ARGS((int c));
+int inindent __ARGS((int extra));
+char_u *skip_to_option_part __ARGS((char_u *p));
+void changed __ARGS((void));
+void changed_bytes __ARGS((linenr_T lnum, colnr_T col));
+void appended_lines __ARGS((linenr_T lnum, long count));
+void appended_lines_mark __ARGS((linenr_T lnum, long count));
+void deleted_lines __ARGS((linenr_T lnum, long count));
+void deleted_lines_mark __ARGS((linenr_T lnum, long count));
+void changed_lines __ARGS((linenr_T lnum, colnr_T col, linenr_T lnume, long xtra));
+void unchanged __ARGS((buf_T *buf, int ff));
+void check_status __ARGS((buf_T *buf));
+void change_warning __ARGS((int col));
+int ask_yesno __ARGS((char_u *str, int direct));
+int get_keystroke __ARGS((void));
+int get_number __ARGS((int colon));
+void msgmore __ARGS((long n));
+void beep_flush __ARGS((void));
+void vim_beep __ARGS((void));
+void init_homedir __ARGS((void));
+void expand_env __ARGS((char_u *src, char_u *dst, int dstlen));
+void expand_env_esc __ARGS((char_u *src, char_u *dst, int dstlen, int esc));
+char_u *vim_getenv __ARGS((char_u *name, int *mustfree));
+char_u *expand_env_save __ARGS((char_u *src));
+void vim_setenv __ARGS((char_u *name, char_u *val));
+char_u *get_env_name __ARGS((expand_T *xp, int idx));
+void home_replace __ARGS((buf_T *buf, char_u *src, char_u *dst, int dstlen, int one));
+char_u *home_replace_save __ARGS((buf_T *buf, char_u *src));
+int fullpathcmp __ARGS((char_u *s1, char_u *s2, int checkname));
+char_u *gettail __ARGS((char_u *fname));
+char_u *getnextcomp __ARGS((char_u *fname));
+char_u *get_past_head __ARGS((char_u *path));
+int vim_ispathsep __ARGS((int c));
+int vim_ispathlistsep __ARGS((int c));
+int vim_fnamecmp __ARGS((char_u *x, char_u *y));
+int vim_fnamencmp __ARGS((char_u *x, char_u *y, size_t len));
+char_u *concat_fnames __ARGS((char_u *fname1, char_u *fname2, int sep));
+void add_pathsep __ARGS((char_u *p));
+char_u *FullName_save __ARGS((char_u *fname, int force));
+pos_T *find_start_comment __ARGS((int ind_maxcomment));
+void do_c_expr_indent __ARGS((void));
+int cin_islabel __ARGS((int ind_maxcomment));
+int cin_iscase __ARGS((char_u *s));
+int cin_isscopedecl __ARGS((char_u *s));
+int get_c_indent __ARGS((void));
+int get_expr_indent __ARGS((void));
+int get_lisp_indent __ARGS((void));
+void prepare_to_exit __ARGS((void));
+void preserve_exit __ARGS((void));
+int vim_fexists __ARGS((char_u *fname));
+void line_breakcheck __ARGS((void));
+void fast_breakcheck __ARGS((void));
+int expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags));
+int match_suffix __ARGS((char_u *fname));
+int gen_expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags));
+void addfile __ARGS((garray_T *gap, char_u *f, int flags));
+char_u *get_cmd_output __ARGS((char_u *cmd, int flags));
+void FreeWild __ARGS((int count, char_u **files));
+int goto_im __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro
new file mode 100644
index 000000000..cbe2af759
--- /dev/null
+++ b/src/proto/misc2.pro
@@ -0,0 +1,91 @@
+/* misc2.c */
+int virtual_active __ARGS((void));
+int getviscol __ARGS((void));
+int getviscol2 __ARGS((colnr_T col, colnr_T coladd));
+int coladvance_force __ARGS((colnr_T wcol));
+int coladvance __ARGS((colnr_T wcol));
+int getvpos __ARGS((pos_T *pos, colnr_T wcol));
+int inc_cursor __ARGS((void));
+int inc __ARGS((pos_T *lp));
+int incl __ARGS((pos_T *lp));
+int dec_cursor __ARGS((void));
+int dec __ARGS((pos_T *lp));
+int decl __ARGS((pos_T *lp));
+void check_cursor_lnum __ARGS((void));
+void check_cursor_col __ARGS((void));
+void check_cursor __ARGS((void));
+void adjust_cursor_col __ARGS((void));
+int leftcol_changed __ARGS((void));
+void vim_mem_profile_dump __ARGS((void));
+char_u *alloc __ARGS((unsigned size));
+char_u *alloc_clear __ARGS((unsigned size));
+char_u *alloc_check __ARGS((unsigned size));
+char_u *lalloc_clear __ARGS((long_u size, int message));
+char_u *lalloc __ARGS((long_u size, int message));
+void *mem_realloc __ARGS((void *ptr, size_t size));
+void do_outofmem_msg __ARGS((long_u size));
+char_u *vim_strsave __ARGS((char_u *string));
+char_u *vim_strnsave __ARGS((char_u *string, int len));
+char_u *vim_strsave_escaped __ARGS((char_u *string, char_u *esc_chars));
+char_u *vim_strsave_escaped_ext __ARGS((char_u *string, char_u *esc_chars, int bsl));
+char_u *vim_strsave_up __ARGS((char_u *string));
+char_u *vim_strnsave_up __ARGS((char_u *string, int len));
+void vim_strup __ARGS((char_u *p));
+void copy_spaces __ARGS((char_u *ptr, size_t count));
+void copy_chars __ARGS((char_u *ptr, size_t count, int c));
+void del_trailing_spaces __ARGS((char_u *ptr));
+void vim_strncpy __ARGS((char_u *to, char_u *from, int len));
+int copy_option_part __ARGS((char_u **option, char_u *buf, int maxlen, char *sep_chars));
+void vim_free __ARGS((void *x));
+int vim_stricmp __ARGS((char *s1, char *s2));
+int vim_strnicmp __ARGS((char *s1, char *s2, size_t len));
+char_u *vim_strchr __ARGS((char_u *string, int c));
+char_u *vim_strrchr __ARGS((char_u *string, int c));
+int vim_isspace __ARGS((int x));
+void ga_clear __ARGS((garray_T *gap));
+void ga_clear_strings __ARGS((garray_T *gap));
+void ga_init __ARGS((garray_T *gap));
+void ga_init2 __ARGS((garray_T *gap, int itemsize, int growsize));
+int ga_grow __ARGS((garray_T *gap, int n));
+void ga_concat __ARGS((garray_T *gap, char_u *s));
+void ga_append __ARGS((garray_T *gap, int c));
+int name_to_mod_mask __ARGS((int c));
+int simplify_key __ARGS((int key, int *modifiers));
+char_u *get_special_key_name __ARGS((int c, int modifiers));
+int trans_special __ARGS((char_u **srcp, char_u *dst, int keycode));
+int find_special_key __ARGS((char_u **srcp, int *modp, int keycode));
+int extract_modifiers __ARGS((int key, int *modp));
+int find_special_key_in_table __ARGS((int c));
+int get_special_key_code __ARGS((char_u *name));
+char_u *get_key_name __ARGS((int i));
+int get_mouse_button __ARGS((int code, int *is_click, int *is_drag));
+int get_pseudo_mouse_code __ARGS((int button, int is_click, int is_drag));
+int get_fileformat __ARGS((buf_T *buf));
+int get_fileformat_force __ARGS((buf_T *buf, exarg_T *eap));
+void set_fileformat __ARGS((int t, int opt_flags));
+int default_fileformat __ARGS((void));
+int call_shell __ARGS((char_u *cmd, int opt));
+int get_real_state __ARGS((void));
+int vim_chdirfile __ARGS((char_u *fname));
+int illegal_slash __ARGS((char *name));
+char_u *parse_shape_opt __ARGS((int what));
+int get_shape_idx __ARGS((int mouse));
+void update_mouseshape __ARGS((int shape_idx));
+int decrypt_byte __ARGS((void));
+int update_keys __ARGS((int c));
+void crypt_init_keys __ARGS((char_u *passwd));
+char_u *get_crypt_key __ARGS((int store, int twice));
+void *vim_findfile_init __ARGS((char_u *path, char_u *filename, char_u *stopdirs, int level, int free_visited, int need_dir, void *search_ctx, int tagfile, char_u *rel_fname));
+char_u *vim_findfile_stopdir __ARGS((char_u *buf));
+void vim_findfile_cleanup __ARGS((void *ctx));
+char_u *vim_findfile __ARGS((void *search_ctx));
+void vim_findfile_free_visited __ARGS((void *search_ctx));
+char_u *find_file_in_path __ARGS((char_u *ptr, int len, int options, int first, char_u *rel_fname));
+char_u *find_directory_in_path __ARGS((char_u *ptr, int len, int options, char_u *rel_fname));
+int vim_chdir __ARGS((char_u *new_dir));
+int get_user_name __ARGS((char_u *buf, int len));
+void sort_strings __ARGS((char_u **files, int count));
+int pathcmp __ARGS((const char *p, const char *q));
+char_u *parse_list_options __ARGS((char_u *option_str, option_table_T *table, int table_size));
+void msg_str __ARGS((char_u *s, char_u *arg));
+/* vim: set ft=c : */
diff --git a/src/proto/move.pro b/src/proto/move.pro
new file mode 100644
index 000000000..de51aa240
--- /dev/null
+++ b/src/proto/move.pro
@@ -0,0 +1,40 @@
+/* move.c */
+void update_topline_redraw __ARGS((void));
+void update_topline __ARGS((void));
+void update_curswant __ARGS((void));
+void check_cursor_moved __ARGS((win_T *wp));
+void changed_window_setting __ARGS((void));
+void changed_window_setting_win __ARGS((win_T *wp));
+void set_topline __ARGS((win_T *wp, linenr_T lnum));
+void changed_cline_bef_curs __ARGS((void));
+void changed_cline_bef_curs_win __ARGS((win_T *wp));
+void changed_line_abv_curs __ARGS((void));
+void changed_line_abv_curs_win __ARGS((win_T *wp));
+void validate_botline __ARGS((void));
+void invalidate_botline __ARGS((void));
+void invalidate_botline_win __ARGS((win_T *wp));
+void approximate_botline_win __ARGS((win_T *wp));
+int cursor_valid __ARGS((void));
+void validate_cursor __ARGS((void));
+void validate_cline_row __ARGS((void));
+void validate_virtcol __ARGS((void));
+void validate_virtcol_win __ARGS((win_T *wp));
+void validate_cursor_col __ARGS((void));
+int win_col_off __ARGS((win_T *wp));
+int curwin_col_off __ARGS((void));
+int win_col_off2 __ARGS((win_T *wp));
+int curwin_col_off2 __ARGS((void));
+void curs_columns __ARGS((int scroll));
+void scrolldown __ARGS((long line_count, int byfold));
+void scrollup __ARGS((long line_count, int byfold));
+void check_topfill __ARGS((win_T *wp, int down));
+void scrolldown_clamp __ARGS((void));
+void scrollup_clamp __ARGS((void));
+void scroll_cursor_top __ARGS((int min_scroll, int always));
+void set_empty_rows __ARGS((win_T *wp, int used));
+void scroll_cursor_bot __ARGS((int min_scroll, int set_topbot));
+void scroll_cursor_halfway __ARGS((int atend));
+void cursor_correct __ARGS((void));
+int onepage __ARGS((int dir, long count));
+void halfpage __ARGS((int flag, linenr_T Prenum));
+/* vim: set ft=c : */
diff --git a/src/proto/netbeans.pro b/src/proto/netbeans.pro
new file mode 100644
index 000000000..e43ae733c
--- /dev/null
+++ b/src/proto/netbeans.pro
@@ -0,0 +1,24 @@
+/* netbeans.c */
+void netbeans_Xt_connect __ARGS((void *context));
+void netbeans_gtk_connect __ARGS((void));
+void netbeans_w32_connect __ARGS((void));
+void messageFromNetbeansW32 __ARGS((void));
+int isNetbeansBuffer __ARGS((buf_T *bufp));
+int isNetbeansModified __ARGS((buf_T *bufp));
+void netbeans_end __ARGS((void));
+void netbeans_startup_done __ARGS((void));
+void netbeans_frame_moved __ARGS((int new_x, int new_y));
+void netbeans_file_opened __ARGS((char *filename));
+void netbeans_file_closed __ARGS((buf_T *bufp));
+void netbeans_inserted __ARGS((buf_T *bufp, linenr_T linenr, colnr_T col, int oldlen, char_u *txt, int newlen));
+void netbeans_removed __ARGS((buf_T *bufp, linenr_T linenr, colnr_T col, long len));
+void netbeans_unmodified __ARGS((buf_T *bufp));
+void netbeans_button_release __ARGS((int button));
+void netbeans_keycommand __ARGS((int key));
+void netbeans_save_buffer __ARGS((buf_T *bufp));
+void netbeans_deleted_all_lines __ARGS((buf_T *bufp));
+int netbeans_is_guarded __ARGS((linenr_T top, linenr_T bot));
+void netbeans_draw_multisign_indicator __ARGS((int row));
+void netbeans_draw_multisign_indicator __ARGS((int row));
+void netbeans_gutter_click __ARGS((linenr_T lnum));
+/* vim: set ft=c : */
diff --git a/src/proto/normal.pro b/src/proto/normal.pro
new file mode 100644
index 000000000..f5e332b65
--- /dev/null
+++ b/src/proto/normal.pro
@@ -0,0 +1,23 @@
+/* normal.c */
+void init_normal_cmds __ARGS((void));
+void normal_cmd __ARGS((oparg_T *oap, int toplevel));
+void do_pending_operator __ARGS((cmdarg_T *cap, int old_col, int gui_yank));
+int do_mouse __ARGS((oparg_T *oap, int c, int dir, long count, int fixindent));
+void check_visual_highlight __ARGS((void));
+void end_visual_mode __ARGS((void));
+void reset_VIsual_and_resel __ARGS((void));
+void reset_VIsual __ARGS((void));
+int find_ident_under_cursor __ARGS((char_u **string, int find_type));
+int find_ident_at_pos __ARGS((win_T *wp, linenr_T lnum, colnr_T startcol, char_u **string, int find_type));
+void clear_showcmd __ARGS((void));
+int add_to_showcmd __ARGS((int c));
+void add_to_showcmd_c __ARGS((int c));
+void push_showcmd __ARGS((void));
+void pop_showcmd __ARGS((void));
+void do_check_scrollbind __ARGS((int check));
+void check_scrollbind __ARGS((linenr_T topline_diff, long leftcol_diff));
+void scroll_redraw __ARGS((int up, long count));
+void do_nv_ident __ARGS((int c1, int c2));
+void start_selection __ARGS((void));
+void may_start_select __ARGS((int c));
+/* vim: set ft=c : */
diff --git a/src/proto/ops.pro b/src/proto/ops.pro
new file mode 100644
index 000000000..c64267309
--- /dev/null
+++ b/src/proto/ops.pro
@@ -0,0 +1,53 @@
+/* ops.c */
+int get_op_type __ARGS((int char1, int char2));
+int op_on_lines __ARGS((int op));
+int get_op_char __ARGS((int optype));
+int get_extra_op_char __ARGS((int optype));
+void op_shift __ARGS((oparg_T *oap, int curs_top, int amount));
+void shift_line __ARGS((int left, int round, int amount));
+void op_reindent __ARGS((oparg_T *oap, int (*how)(void)));
+int get_expr_register __ARGS((void));
+void set_expr_line __ARGS((char_u *new_line));
+char_u *get_expr_line __ARGS((void));
+int valid_yank_reg __ARGS((int regname, int writing));
+void *get_register __ARGS((int name, int copy));
+void put_register __ARGS((int name, void *reg));
+int yank_register_mline __ARGS((int regname));
+int do_record __ARGS((int c));
+int do_execreg __ARGS((int regname, int colon, int addcr));
+int insert_reg __ARGS((int regname, int literally));
+int cmdline_paste __ARGS((int regname, int literally));
+void adjust_clip_reg __ARGS((int *rp));
+int op_delete __ARGS((oparg_T *oap));
+int op_replace __ARGS((oparg_T *oap, int c));
+void op_tilde __ARGS((oparg_T *oap));
+int swapchar __ARGS((int op_type, pos_T *pos));
+void op_insert __ARGS((oparg_T *oap, long count1));
+int op_change __ARGS((oparg_T *oap));
+void init_yank __ARGS((void));
+int op_yank __ARGS((oparg_T *oap, int deleting, int mess));
+void do_put __ARGS((int regname, int dir, long count, int flags));
+int preprocs_left __ARGS((void));
+int get_register_name __ARGS((int num));
+void ex_display __ARGS((exarg_T *eap));
+void do_do_join __ARGS((long count, int insert_space));
+int do_join __ARGS((int insert_space));
+void op_format __ARGS((oparg_T *oap, int keep_cursor));
+void format_lines __ARGS((linenr_T line_count));
+int paragraph_start __ARGS((linenr_T lnum));
+int do_addsub __ARGS((int command, linenr_T Prenum1));
+int read_viminfo_register __ARGS((vir_T *virp, int force));
+void write_viminfo_registers __ARGS((FILE *fp));
+void x11_export_final_selection __ARGS((void));
+void clip_free_selection __ARGS((VimClipboard *cbd));
+void clip_get_selection __ARGS((VimClipboard *cbd));
+void clip_yank_selection __ARGS((int type, char_u *str, long len, VimClipboard *cbd));
+int clip_convert_selection __ARGS((char_u **str, long_u *len, VimClipboard *cbd));
+void dnd_yank_drag_data __ARGS((char_u *str, long len));
+char_u get_reg_type __ARGS((int regname, long *reglen));
+char_u *get_reg_contents __ARGS((int regname, int allowexpr));
+void write_reg_contents __ARGS((int name, char_u *str, int maxlen, int must_append));
+void write_reg_contents_ex __ARGS((int name, char_u *str, int maxlen, int must_append, int yank_type, long block_len));
+void clear_oparg __ARGS((oparg_T *oap));
+void cursor_pos_info __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/option.pro b/src/proto/option.pro
new file mode 100644
index 000000000..c0a567ba6
--- /dev/null
+++ b/src/proto/option.pro
@@ -0,0 +1,52 @@
+/* option.c */
+void set_init_1 __ARGS((void));
+void set_string_default __ARGS((char *name, char_u *val));
+void set_number_default __ARGS((char *name, long val));
+void set_init_2 __ARGS((void));
+void set_init_3 __ARGS((void));
+void set_helplang_default __ARGS((char_u *lang));
+void init_gui_options __ARGS((void));
+void set_title_defaults __ARGS((void));
+int do_set __ARGS((char_u *arg, int opt_flags));
+void set_options_bin __ARGS((int oldval, int newval, int opt_flags));
+int get_viminfo_parameter __ARGS((int type));
+char_u *find_viminfo_parameter __ARGS((int type));
+void check_options __ARGS((void));
+void check_buf_options __ARGS((buf_T *buf));
+void free_string_option __ARGS((char_u *p));
+void clear_string_option __ARGS((char_u **pp));
+void set_term_option_alloced __ARGS((char_u **p));
+void set_string_option_direct __ARGS((char_u *name, int opt_idx, char_u *val, int opt_flags));
+char_u *check_stl_option __ARGS((char_u *s));
+int get_option_value __ARGS((char_u *name, long *numval, char_u **stringval, int opt_flags));
+void set_option_value __ARGS((char_u *name, long number, char_u *string, int opt_flags));
+char_u *get_term_code __ARGS((char_u *tname));
+char_u *get_highlight_default __ARGS((void));
+int makeset __ARGS((FILE *fd, int opt_flags, int local_only));
+int makefoldset __ARGS((FILE *fd));
+void clear_termoptions __ARGS((void));
+void set_term_defaults __ARGS((void));
+void comp_col __ARGS((void));
+char_u *get_equalprg __ARGS((void));
+void win_copy_options __ARGS((win_T *wp_from, win_T *wp_to));
+void copy_winopt __ARGS((winopt_T *from, winopt_T *to));
+void check_win_options __ARGS((win_T *win));
+void check_winopt __ARGS((winopt_T *wop));
+void clear_winopt __ARGS((winopt_T *wop));
+void buf_copy_options __ARGS((buf_T *buf, int flags));
+void reset_modifiable __ARGS((void));
+void set_iminsert_global __ARGS((void));
+void set_imsearch_global __ARGS((void));
+void set_context_in_set_cmd __ARGS((expand_T *xp, char_u *arg, int opt_flags));
+int ExpandSettings __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file));
+int ExpandOldSetting __ARGS((int *num_file, char_u ***file));
+int has_format_option __ARGS((int x));
+int shortmess __ARGS((int x));
+void vimrc_found __ARGS((void));
+void change_compatible __ARGS((int on));
+int option_was_set __ARGS((char_u *name));
+int can_bs __ARGS((int what));
+void save_file_ff __ARGS((buf_T *buf));
+int file_ff_differs __ARGS((buf_T *buf));
+int check_ff_value __ARGS((char_u *p));
+/* vim: set ft=c : */
diff --git a/src/proto/os_amiga.pro b/src/proto/os_amiga.pro
new file mode 100644
index 000000000..317e21100
--- /dev/null
+++ b/src/proto/os_amiga.pro
@@ -0,0 +1,46 @@
+/* os_amiga.c */
+void win_resize_on __ARGS((void));
+void win_resize_off __ARGS((void));
+void mch_write __ARGS((char_u *p, int len));
+int mch_inchar __ARGS((char_u *buf, int maxlen, long time, int tb_change_cnt));
+int mch_char_avail __ARGS((void));
+long_u mch_avail_mem __ARGS((int special));
+void mch_delay __ARGS((long msec, int ignoreinput));
+void mch_suspend __ARGS((void));
+void mch_init __ARGS((void));
+int mch_check_win __ARGS((int argc, char **argv));
+int mch_input_isatty __ARGS((void));
+void fname_case __ARGS((char_u *name, int len));
+void mch_settitle __ARGS((char_u *title, char_u *icon));
+void mch_restore_title __ARGS((int which));
+int mch_can_restore_title __ARGS((void));
+int mch_can_restore_icon __ARGS((void));
+int mch_get_user_name __ARGS((char_u *s, int len));
+void mch_get_host_name __ARGS((char_u *s, int len));
+long mch_get_pid __ARGS((void));
+int mch_dirname __ARGS((char_u *buf, int len));
+int mch_FullName __ARGS((char_u *fname, char_u *buf, int len, int force));
+int mch_isFullName __ARGS((char_u *fname));
+long mch_getperm __ARGS((char_u *name));
+int mch_setperm __ARGS((char_u *name, long perm));
+void mch_hide __ARGS((char_u *name));
+int mch_isdir __ARGS((char_u *name));
+void mch_mkdir __ARGS((char_u *name));
+int mch_can_exe __ARGS((char_u *name));
+int mch_nodetype __ARGS((char_u *name));
+void mch_early_init __ARGS((void));
+void mch_exit __ARGS((int r));
+void mch_settmode __ARGS((int tmode));
+int mch_screenmode __ARGS((char_u *arg));
+int mch_get_shellsize __ARGS((void));
+void mch_set_shellsize __ARGS((void));
+void mch_new_shellsize __ARGS((void));
+int mch_call_shell __ARGS((char_u *cmd, int options));
+void mch_breakcheck __ARGS((void));
+long Chk_Abort __ARGS((void));
+int mch_expandpath __ARGS((garray_T *gap, char_u *pat, int flags));
+int mch_has_exp_wildcard __ARGS((char_u *p));
+int mch_has_wildcard __ARGS((char_u *p));
+char_u *mch_getenv __ARGS((char_u *var));
+int mch_setenv __ARGS((char *var, char *value, int x));
+/* vim: set ft=c : */
diff --git a/src/proto/os_beos.pro b/src/proto/os_beos.pro
new file mode 100644
index 000000000..c53710126
--- /dev/null
+++ b/src/proto/os_beos.pro
@@ -0,0 +1,4 @@
+/* os_beos.c */
+void beos_cleanup_read_thread __ARGS((void));
+int beos_select __ARGS((int nbits, struct fd_set *rbits, struct fd_set *wbits, struct fd_set *ebits, struct timeval *timeout));
+/* vim: set ft=c : */
diff --git a/src/proto/os_mac.pro b/src/proto/os_mac.pro
new file mode 100644
index 000000000..ced47faf2
--- /dev/null
+++ b/src/proto/os_mac.pro
@@ -0,0 +1,64 @@
+/* os_mac.c */
+void mch_setmouse __ARGS((int on));
+
+void mch_windexit __ARGS((int r));
+int mch_check_win __ARGS((int argc, char **argv));
+int mch_input_isatty __ARGS((void));
+
+void fname_case __ARGS((char_u *name, int len));
+void mch_early_init __ARGS((void));
+void mch_exit __ARGS((int r));
+void mch_settitle __ARGS((char_u *title, char_u *icon));
+void mch_restore_title __ARGS((int which));
+
+int mch_get_user_name __ARGS((char_u *s, int len));
+void mch_get_host_name __ARGS((char_u *s, int len));
+long mch_get_pid __ARGS((void));
+
+int mch_dirname __ARGS((char_u *buf, int len));
+int mch_FullName __ARGS((char_u *fname, char_u *buf, int len, int force));
+int mch_isFullName __ARGS((char_u *fname));
+void slash_adjust __ARGS((char_u *p));
+long mch_getperm __ARGS((char_u *name));
+int mch_setperm __ARGS((char_u *name, long perm));
+void mch_hide __ARGS((char_u *name));
+int mch_isdir __ARGS((char_u *name));
+int mch_can_exe __ARGS((char_u *name));
+int mch_nodetype __ARGS((char_u *name));
+void mch_init __ARGS((void));
+void mch_settmode __ARGS((int raw));
+
+int mch_chdir __ARGS((char *p_name));
+#if defined(__MRC__) || defined(__SC__)
+int stat __ARGS((char *p, struct stat *p_st));
+#endif
+
+int mch_call_shell __ARGS((char_u *cmd, int options));
+int mch_has_wildcard __ARGS((char_u *s));
+int mch_expandpath __ARGS((struct growarray *gap, char_u *path, int flags));
+int mac_expandpath __ARGS((struct growarray *gap, char_u *path, int flags, short start_at, short as_full));
+/*int vim_chdir __ARGS((char *path));*/
+void mch_delay __ARGS((long msec, int ignoreinput));
+void mch_breakcheck __ARGS((void));
+long_u mch_avail_mem __ARGS((int special));
+int mch_screenmode __ARGS((char_u *arg));
+int mch_has_exp_wildcard __ARGS((char_u *p));
+
+void slash_n_colon_adjust __ARGS((char_u *buf));
+int mch_copy_file(char_u *from, char_u *to);
+
+int mch_has_resource_fork (char_u *file);
+int mch_copy_file_attribute(char_u *from, char_u *to);
+
+void mch_shellinit __ARGS((void));
+int mch_get_shellsize __ARGS((void));
+void mch_set_shellsize __ARGS((void));
+void mch_new_shellsize __ARGS((void));
+void mch_suspend __ARGS((void));
+int mch_can_restore_title __ARGS((void));
+int mch_can_restore_icon __ARGS((void));
+
+void slash_to_colon __ARGS((char_u *p));
+char_u *slash_to_colon_save __ARGS((char_u *p));
+
+/* vim: set ft=c : */
diff --git a/src/proto/os_msdos.pro b/src/proto/os_msdos.pro
new file mode 100644
index 000000000..a867f3d1c
--- /dev/null
+++ b/src/proto/os_msdos.pro
@@ -0,0 +1,48 @@
+/* os_msdos.c */
+void mch_set_normal_colors __ARGS((void));
+void mch_update_cursor __ARGS((void));
+long_u mch_avail_mem __ARGS((int special));
+void mch_delay __ARGS((long msec, int ignoreinput));
+void mch_write __ARGS((char_u *s, int len));
+int mch_inchar __ARGS((char_u *buf, int maxlen, long time, int tb_change_cnt));
+int mch_char_avail __ARGS((void));
+void mch_suspend __ARGS((void));
+void mch_init __ARGS((void));
+int mch_check_win __ARGS((int argc, char **argv));
+int mch_input_isatty __ARGS((void));
+void fname_case __ARGS((char_u *name, int len));
+long mch_get_pid __ARGS((void));
+int mch_FullName __ARGS((char_u *fname, char_u *buf, int len, int force));
+void slash_adjust __ARGS((char_u *p));
+int mch_isFullName __ARGS((char_u *fname));
+void mch_early_init __ARGS((void));
+void mch_exit __ARGS((int r));
+void mch_settmode __ARGS((int tmode));
+void mch_setmouse __ARGS((int on));
+int mch_screenmode __ARGS((char_u *arg));
+int mch_get_shellsize __ARGS((void));
+void mch_set_shellsize __ARGS((void));
+void mch_new_shellsize __ARGS((void));
+void mch_check_columns __ARGS((void));
+int mch_call_shell __ARGS((char_u *cmd, int options));
+void mch_breakcheck __ARGS((void));
+int mch_has_exp_wildcard __ARGS((char_u *p));
+int mch_has_wildcard __ARGS((char_u *p));
+int mch_chdir __ARGS((char *path));
+char *djgpp_setlocale __ARGS((void));
+int clip_mch_own_selection __ARGS((VimClipboard *cbd));
+void clip_mch_lose_selection __ARGS((VimClipboard *cbd));
+void clip_mch_request_selection __ARGS((VimClipboard *cbd));
+void clip_mch_set_selection __ARGS((VimClipboard *cbd));
+long mch_getperm __ARGS((char_u *name));
+int mch_setperm __ARGS((char_u *name, long perm));
+void mch_hide __ARGS((char_u *name));
+int mch_isdir __ARGS((char_u *name));
+int mch_can_exe __ARGS((char_u *name));
+int mch_nodetype __ARGS((char_u *name));
+int mch_dirname __ARGS((char_u *buf, int len));
+int mch_remove __ARGS((char_u *name));
+char_u *mch_getenv __ARGS((char_u *name));
+int mch_get_user_name __ARGS((char_u *s, int len));
+void mch_get_host_name __ARGS((char_u *s, int len));
+/* vim: set ft=c : */
diff --git a/src/proto/os_mswin.pro b/src/proto/os_mswin.pro
new file mode 100644
index 000000000..b4612f0d0
--- /dev/null
+++ b/src/proto/os_mswin.pro
@@ -0,0 +1,60 @@
+/* os_mswin.c */
+void mch_exit __ARGS((int r));
+void mch_early_init __ARGS((void));
+int mch_input_isatty __ARGS((void));
+void mch_settitle __ARGS((char_u *title, char_u *icon));
+void mch_restore_title __ARGS((int which));
+int mch_can_restore_title __ARGS((void));
+int mch_can_restore_icon __ARGS((void));
+int mch_FullName __ARGS((char_u *fname, char_u *buf, int len, int force));
+int mch_isFullName __ARGS((char_u *fname));
+void slash_adjust __ARGS((char_u *p));
+int vim_stat __ARGS((const char *name, struct stat *stp));
+void mch_settmode __ARGS((int tmode));
+int mch_get_shellsize __ARGS((void));
+void mch_set_shellsize __ARGS((void));
+void mch_new_shellsize __ARGS((void));
+void mch_suspend __ARGS((void));
+void display_errors __ARGS((void));
+int mch_has_exp_wildcard __ARGS((char_u *p));
+int mch_has_wildcard __ARGS((char_u *p));
+int mch_chdir __ARGS((char *path));
+int can_end_termcap_mode __ARGS((int give_msg));
+int mch_screenmode __ARGS((char_u *arg));
+int mch_libcall __ARGS((char_u *libname, char_u *funcname, char_u *argstring, int argint, char_u **string_result, int *number_result));
+int utf8_to_ucs2 __ARGS((char_u *instr, int inlen, short_u *outstr, int *unconvlenp));
+int ucs2_to_utf8 __ARGS((short_u *instr, int inlen, char_u *outstr));
+void MultiByteToWideChar_alloc __ARGS((UINT cp, DWORD flags, LPCSTR in, int inlen, LPWSTR *out, int *outlen));
+void WideCharToMultiByte_alloc __ARGS((UINT cp, DWORD flags, LPCWSTR in, int inlen, LPSTR *out, int *outlen, LPCSTR def, LPBOOL useddef));
+int clip_mch_own_selection __ARGS((VimClipboard *cbd));
+void clip_mch_lose_selection __ARGS((VimClipboard *cbd));
+short_u *enc_to_ucs2 __ARGS((char_u *str, int *lenp));
+char_u *ucs2_to_enc __ARGS((short_u *str, int *lenp));
+void clip_mch_request_selection __ARGS((VimClipboard *cbd));
+void clip_mch_set_selection __ARGS((VimClipboard *cbd));
+void DumpPutS __ARGS((const char *psz));
+void mch_print_cleanup __ARGS((void));
+int mch_print_init __ARGS((prt_settings_T *psettings, char_u *jobname, int forceit));
+int mch_print_begin __ARGS((prt_settings_T *psettings));
+void mch_print_end __ARGS((prt_settings_T *psettings));
+int mch_print_end_page __ARGS((void));
+int mch_print_begin_page __ARGS((char_u *msg));
+int mch_print_blank_page __ARGS((void));
+void mch_print_start_line __ARGS((int margin, int page_line));
+int mch_print_text_out __ARGS((char_u *p, int len));
+void mch_print_set_font __ARGS((int iBold, int iItalic, int iUnderline));
+void mch_print_set_bg __ARGS((unsigned long bgcol));
+void mch_print_set_fg __ARGS((unsigned long fgcol));
+char_u *mch_resolve_shortcut __ARGS((char_u *fname));
+void win32_set_foreground __ARGS((void));
+void serverInitMessaging __ARGS((void));
+void serverSetName __ARGS((char_u *name));
+char_u *serverGetVimNames __ARGS((void));
+int serverSendReply __ARGS((char_u *name, char_u *reply));
+int serverSendToVim __ARGS((char_u *name, char_u *cmd, char_u **result, void *ptarget, int asExpr, int silent));
+void serverForeground __ARGS((char_u *name));
+char_u *serverGetReply __ARGS((HWND server, int *expr_res, int remove, int wait));
+void serverProcessPendingMessages __ARGS((void));
+char *charset_id2name __ARGS((int id));
+int get_logfont __ARGS((LOGFONT *lf, char_u *name, HDC printer_dc));
+/* vim: set ft=c : */
diff --git a/src/proto/os_qnx.pro b/src/proto/os_qnx.pro
new file mode 100644
index 000000000..54a63149a
--- /dev/null
+++ b/src/proto/os_qnx.pro
@@ -0,0 +1,8 @@
+/* os_qnx.c */
+void qnx_init __ARGS((void));
+void qnx_clip_init __ARGS((void));
+int clip_mch_own_selection __ARGS((VimClipboard *cbd));
+void clip_mch_lose_selection __ARGS((VimClipboard *cbd));
+void clip_mch_request_selection __ARGS((VimClipboard *cbd));
+void clip_mch_set_selection __ARGS((VimClipboard *cbd));
+/* vim: set ft=c : */
diff --git a/src/proto/os_riscos.pro b/src/proto/os_riscos.pro
new file mode 100644
index 000000000..9ea4cd55f
--- /dev/null
+++ b/src/proto/os_riscos.pro
@@ -0,0 +1,49 @@
+/* os_riscos.c */
+void mch_write __ARGS((char_u *s, int len));
+int mch_inchar __ARGS((char_u *buf, int maxlen, long wtime, int tb_change_cnt));
+int mch_char_avail __ARGS((void));
+long_u mch_avail_mem __ARGS((int special));
+void mch_delay __ARGS((long msec, int ignoreinput));
+void mch_suspend __ARGS((void));
+void mch_init __ARGS((void));
+int mch_check_win __ARGS((int argc, char **argv));
+int mch_input_isatty __ARGS((void));
+int mch_can_restore_title __ARGS((void));
+int mch_can_restore_icon __ARGS((void));
+void mch_settitle __ARGS((char_u *title, char_u *icon));
+void mch_restore_title __ARGS((int which));
+int mch_get_user_name __ARGS((char_u *s, int len));
+void mch_get_host_name __ARGS((char_u *s, int len));
+long mch_get_pid __ARGS((void));
+int mch_dirname __ARGS((char_u *buf, int len));
+int mch_FullName __ARGS((char_u *fname, char_u *buf, int len, int force));
+int mch_isFullName __ARGS((char_u *fname));
+long mch_getperm __ARGS((char_u *name));
+int mch_setperm __ARGS((char_u *name, long perm));
+void mch_hide __ARGS((char_u *name));
+int mch_isdir __ARGS((char_u *name));
+int mch_can_exe __ARGS((char_u *name));
+int mch_nodetype __ARGS((char_u *name));
+void mch_early_init __ARGS((void));
+void mch_exit __ARGS((int r));
+void mch_settmode __ARGS((int tmode));
+void mch_setmouse __ARGS((int on));
+int mch_screenmode __ARGS((char_u *arg));
+int mch_get_shellsize __ARGS((void));
+void mch_set_shellsize __ARGS((void));
+void mch_new_shellsize __ARGS((void));
+int mch_call_shell __ARGS((char_u *cmd, int options));
+void mch_breakcheck __ARGS((void));
+int mch_expandpath __ARGS((garray_T *gap, char_u *path, int flags));
+int expand_section __ARGS((garray_T *gap, char_u *root, char_u *rest, int flags));
+int mch_expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags));
+int mch_has_exp_wildcard __ARGS((char_u *p));
+int mch_has_wildcard __ARGS((char_u *p));
+int mch_remove __ARGS((char_u *file));
+char_u *mch_munge_fname __ARGS((char_u *fname));
+int ro_buflist_add __ARGS((char_u *old_name));
+int mch_chdir __ARGS((char_u *dir));
+void mch_read_filetype __ARGS((char_u *file));
+void mch_set_filetype __ARGS((char_u *file, char_u *type));
+int mch_check_filetype __ARGS((char_u *fname, char_u *type));
+/* vim: set ft=c : */
diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro
new file mode 100644
index 000000000..9a3908b49
--- /dev/null
+++ b/src/proto/os_unix.pro
@@ -0,0 +1,70 @@
+/* os_unix.c */
+void mch_write __ARGS((char_u *s, int len));
+int mch_inchar __ARGS((char_u *buf, int maxlen, long wtime, int tb_change_cnt));
+int mch_char_avail __ARGS((void));
+long_u mch_total_mem __ARGS((int special));
+void mch_delay __ARGS((long msec, int ignoreinput));
+int mch_stackcheck __ARGS((char *p));
+void mch_startjmp __ARGS((void));
+void mch_endjmp __ARGS((void));
+void mch_didjmp __ARGS((void));
+void mch_suspend __ARGS((void));
+void mch_init __ARGS((void));
+void reset_signals __ARGS((void));
+int mch_check_win __ARGS((int argc, char **argv));
+int mch_input_isatty __ARGS((void));
+int mch_can_restore_title __ARGS((void));
+int mch_can_restore_icon __ARGS((void));
+void mch_settitle __ARGS((char_u *title, char_u *icon));
+void mch_restore_title __ARGS((int which));
+int vim_is_xterm __ARGS((char_u *name));
+int use_xterm_mouse __ARGS((void));
+int vim_is_iris __ARGS((char_u *name));
+int vim_is_vt300 __ARGS((char_u *name));
+int vim_is_fastterm __ARGS((char_u *name));
+int mch_get_user_name __ARGS((char_u *s, int len));
+int mch_get_uname __ARGS((uid_t uid, char_u *s, int len));
+void mch_get_host_name __ARGS((char_u *s, int len));
+long mch_get_pid __ARGS((void));
+int mch_dirname __ARGS((char_u *buf, int len));
+void slash_adjust __ARGS((char_u *p));
+int mch_FullName __ARGS((char_u *fname, char_u *buf, int len, int force));
+int mch_isFullName __ARGS((char_u *fname));
+long mch_getperm __ARGS((char_u *name));
+int mch_setperm __ARGS((char_u *name, long perm));
+vim_acl_T mch_get_acl __ARGS((char_u *fname));
+void mch_set_acl __ARGS((char_u *fname, vim_acl_T aclent));
+void mch_free_acl __ARGS((vim_acl_T aclent));
+void mch_hide __ARGS((char_u *name));
+int mch_isdir __ARGS((char_u *name));
+int mch_can_exe __ARGS((char_u *name));
+int mch_nodetype __ARGS((char_u *name));
+void mch_early_init __ARGS((void));
+void mch_exit __ARGS((int r));
+void mch_settmode __ARGS((int tmode));
+void get_stty __ARGS((void));
+void mch_setmouse __ARGS((int on));
+void check_mouse_termcode __ARGS((void));
+int mch_screenmode __ARGS((char_u *arg));
+int mch_get_shellsize __ARGS((void));
+void mch_set_shellsize __ARGS((void));
+void mch_new_shellsize __ARGS((void));
+int mch_call_shell __ARGS((char_u *cmd, int options));
+void mch_breakcheck __ARGS((void));
+int mch_expandpath __ARGS((garray_T *gap, char_u *path, int flags));
+int mch_expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags));
+int mch_has_exp_wildcard __ARGS((char_u *p));
+int mch_has_wildcard __ARGS((char_u *p));
+int mch_libcall __ARGS((char_u *libname, char_u *funcname, char_u *argstring, int argint, char_u **string_result, int *number_result));
+void setup_term_clip __ARGS((void));
+void start_xterm_trace __ARGS((int button));
+void stop_xterm_trace __ARGS((void));
+void clear_xterm_clip __ARGS((void));
+int clip_xterm_own_selection __ARGS((VimClipboard *cbd));
+void clip_xterm_lose_selection __ARGS((VimClipboard *cbd));
+void clip_xterm_request_selection __ARGS((VimClipboard *cbd));
+void clip_xterm_set_selection __ARGS((VimClipboard *cbd));
+int xsmp_handle_requests __ARGS((void));
+void xsmp_init __ARGS((void));
+void xsmp_close __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/os_vms.pro b/src/proto/os_vms.pro
new file mode 100644
index 000000000..2ed6394eb
--- /dev/null
+++ b/src/proto/os_vms.pro
@@ -0,0 +1,14 @@
+/* os_vms.c */
+void mch_settmode __ARGS((int tmode));
+int mch_get_shellsize __ARGS((void));
+void mch_set_shellsize __ARGS((void));
+char_u *mch_getenv __ARGS((char_u *lognam));
+int mch_setenv __ARGS((char *var, char *value, int x));
+int vms_sys __ARGS((char *cmd, char *out, char *inp));
+int vms_sys_status __ARGS((int status));
+int vms_read __ARGS((char *inbuf, size_t nbytes));
+int mch_expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags));
+int mch_expandpath __ARGS((garray_T *gap, char_u *path, int flags));
+void *vms_fixfilename __ARGS((void *instring));
+void vms_remove_version __ARGS((void *fname));
+/* vim: set ft=c : */
diff --git a/src/proto/os_win16.pro b/src/proto/os_win16.pro
new file mode 100644
index 000000000..31fa72c05
--- /dev/null
+++ b/src/proto/os_win16.pro
@@ -0,0 +1,12 @@
+/* os_win16.c */
+void mch_setmouse __ARGS((int on));
+void mch_init __ARGS((void));
+int mch_check_win __ARGS((int argc, char **argv));
+long mch_get_pid __ARGS((void));
+int mch_call_shell __ARGS((char_u *cmd, int options));
+void mch_delay __ARGS((long msec, int ignoreinput));
+void mch_breakcheck __ARGS((void));
+long_u mch_avail_mem __ARGS((int special));
+int mch_rename __ARGS((const char *pszOldFile, const char *pszNewFile));
+char *default_shell __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/os_win32.pro b/src/proto/os_win32.pro
new file mode 100644
index 000000000..2daa1467b
--- /dev/null
+++ b/src/proto/os_win32.pro
@@ -0,0 +1,48 @@
+/* os_win32.c */
+int dyn_libintl_init __ARGS((char *libname));
+void dyn_libintl_end __ARGS((void));
+void PlatformId __ARGS((void));
+int mch_windows95 __ARGS((void));
+void mch_setmouse __ARGS((int on));
+void mch_update_cursor __ARGS((void));
+int mch_char_avail __ARGS((void));
+int mch_inchar __ARGS((char_u *buf, int maxlen, long time, int tb_change_cnt));
+void mch_init __ARGS((void));
+void mch_exit __ARGS((int r));
+int mch_check_win __ARGS((int argc, char **argv));
+void fname_case __ARGS((char_u *name, int len));
+int mch_get_user_name __ARGS((char_u *s, int len));
+void mch_get_host_name __ARGS((char_u *s, int len));
+long mch_get_pid __ARGS((void));
+int mch_dirname __ARGS((char_u *buf, int len));
+long mch_getperm __ARGS((char_u *name));
+int mch_setperm __ARGS((char_u *name, long perm));
+void mch_hide __ARGS((char_u *name));
+int mch_isdir __ARGS((char_u *name));
+int mch_writable __ARGS((char_u *name));
+int mch_can_exe __ARGS((char_u *name));
+int mch_nodetype __ARGS((char_u *name));
+vim_acl_T mch_get_acl __ARGS((char_u *fname));
+void mch_set_acl __ARGS((char_u *fname, vim_acl_T acl));
+void mch_free_acl __ARGS((vim_acl_T acl));
+void mch_settmode __ARGS((int tmode));
+int mch_get_shellsize __ARGS((void));
+void mch_set_shellsize __ARGS((void));
+void mch_new_shellsize __ARGS((void));
+void mch_set_winsize_now __ARGS((void));
+int mch_call_shell __ARGS((char_u *cmd, int options));
+void mch_set_normal_colors __ARGS((void));
+void mch_write __ARGS((char_u *s, int len));
+void mch_delay __ARGS((long msec, int ignoreinput));
+int mch_remove __ARGS((char_u *name));
+void mch_breakcheck __ARGS((void));
+long_u mch_avail_mem __ARGS((int special));
+int mch_wrename __ARGS((WCHAR *wold, WCHAR *wnew));
+int mch_rename __ARGS((const char *pszOldFile, const char *pszNewFile));
+char *default_shell __ARGS((void));
+int mch_access __ARGS((char *n, int p));
+int mch_open __ARGS((char *name, int flags, int mode));
+FILE *mch_fopen __ARGS((char *name, char *mode));
+int mch_copy_file_attribute __ARGS((char_u *from, char_u *to));
+int myresetstkoflw __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/pty.pro b/src/proto/pty.pro
new file mode 100644
index 000000000..f2424a509
--- /dev/null
+++ b/src/proto/pty.pro
@@ -0,0 +1,3 @@
+/* pty.c */
+int OpenPTY __ARGS((char **ttyn));
+int SetupSlavePTY __ARGS((int fd));
diff --git a/src/proto/quickfix.pro b/src/proto/quickfix.pro
new file mode 100644
index 000000000..c1d619dc0
--- /dev/null
+++ b/src/proto/quickfix.pro
@@ -0,0 +1,21 @@
+/* quickfix.c */
+int qf_init __ARGS((char_u *efile, char_u *errorformat, int newlist));
+void qf_jump __ARGS((int dir, int errornr, int forceit));
+void qf_list __ARGS((exarg_T *eap));
+void qf_age __ARGS((exarg_T *eap));
+void qf_mark_adjust __ARGS((linenr_T line1, linenr_T line2, long amount, long amount_after));
+void ex_cwindow __ARGS((exarg_T *eap));
+void ex_cclose __ARGS((exarg_T *eap));
+void ex_copen __ARGS((exarg_T *eap));
+linenr_T qf_current_entry __ARGS((void));
+int bt_quickfix __ARGS((buf_T *buf));
+int bt_nofile __ARGS((buf_T *buf));
+int bt_dontwrite __ARGS((buf_T *buf));
+int bt_dontwrite_msg __ARGS((buf_T *buf));
+int buf_hide __ARGS((buf_T *buf));
+void ex_make __ARGS((exarg_T *eap));
+void ex_cc __ARGS((exarg_T *eap));
+void ex_cnext __ARGS((exarg_T *eap));
+void ex_cfile __ARGS((exarg_T *eap));
+void ex_helpgrep __ARGS((exarg_T *eap));
+/* vim: set ft=c : */
diff --git a/src/proto/regexp.pro b/src/proto/regexp.pro
new file mode 100644
index 000000000..0ff1c24ea
--- /dev/null
+++ b/src/proto/regexp.pro
@@ -0,0 +1,16 @@
+/* regexp.c */
+int re_multiline __ARGS((regprog_T *prog));
+int re_lookbehind __ARGS((regprog_T *prog));
+char_u *skip_regexp __ARGS((char_u *startp, int dirc, int magic, char_u **newp));
+regprog_T *vim_regcomp __ARGS((char_u *expr, int re_flags));
+int vim_regcomp_had_eol __ARGS((void));
+int vim_regexec __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
+int vim_regexec_nl __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
+long vim_regexec_multi __ARGS((regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col));
+reg_extmatch_T *ref_extmatch __ARGS((reg_extmatch_T *em));
+void unref_extmatch __ARGS((reg_extmatch_T *em));
+char_u *regtilde __ARGS((char_u *source, int magic));
+int vim_regsub __ARGS((regmatch_T *rmp, char_u *source, char_u *dest, int copy, int magic, int backslash));
+int vim_regsub_multi __ARGS((regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *dest, int copy, int magic, int backslash));
+char_u *reg_submatch __ARGS((int no));
+/* vim: set ft=c : */
diff --git a/src/proto/screen.pro b/src/proto/screen.pro
new file mode 100644
index 000000000..7a41fd431
--- /dev/null
+++ b/src/proto/screen.pro
@@ -0,0 +1,46 @@
+/* screen.c */
+void redraw_later __ARGS((int type));
+void redraw_win_later __ARGS((win_T *wp, int type));
+void redraw_later_clear __ARGS((void));
+void redraw_all_later __ARGS((int type));
+void redraw_curbuf_later __ARGS((int type));
+void redraw_buf_later __ARGS((buf_T *buf, int type));
+void redrawWinline __ARGS((linenr_T lnum, int invalid));
+void update_curbuf __ARGS((int type));
+void update_screen __ARGS((int type));
+void update_debug_sign __ARGS((buf_T *buf, linenr_T lnum));
+void updateWindow __ARGS((win_T *wp));
+void status_redraw_all __ARGS((void));
+void status_redraw_curbuf __ARGS((void));
+void redraw_statuslines __ARGS((void));
+void win_redraw_last_status __ARGS((frame_T *frp));
+void win_redr_status_matches __ARGS((expand_T *xp, int num_matches, char_u **matches, int match, int showtail));
+void win_redr_status __ARGS((win_T *wp));
+int stl_connected __ARGS((win_T *wp));
+int get_keymap_str __ARGS((win_T *wp, char_u *buf, int len));
+void screen_putchar __ARGS((int c, int row, int col, int attr));
+void screen_getbytes __ARGS((int row, int col, char_u *bytes, int *attrp));
+void screen_puts __ARGS((char_u *text, int row, int col, int attr));
+void screen_puts_len __ARGS((char_u *text, int len, int row, int col, int attr));
+void screen_stop_highlight __ARGS((void));
+void reset_cterm_colors __ARGS((void));
+void screen_draw_rectangle __ARGS((int row, int col, int height, int width, int invert));
+void screen_fill __ARGS((int start_row, int end_row, int start_col, int end_col, int c1, int c2, int attr));
+void check_for_delay __ARGS((int check_msg_scroll));
+int screen_valid __ARGS((int clear));
+void screenalloc __ARGS((int clear));
+void screenclear __ARGS((void));
+int can_clear __ARGS((char_u *p));
+void screen_start __ARGS((void));
+void screen_down __ARGS((void));
+void windgoto __ARGS((int row, int col));
+void setcursor __ARGS((void));
+int win_ins_lines __ARGS((win_T *wp, int row, int line_count, int invalid, int mayclear));
+int win_del_lines __ARGS((win_T *wp, int row, int line_count, int invalid, int mayclear));
+int screen_del_lines __ARGS((int off, int row, int line_count, int end, int force, win_T *wp));
+int showmode __ARGS((void));
+void unshowmode __ARGS((int force));
+int redrawing __ARGS((void));
+int messaging __ARGS((void));
+void showruler __ARGS((int always));
+/* vim: set ft=c : */
diff --git a/src/proto/search.pro b/src/proto/search.pro
new file mode 100644
index 000000000..194c39087
--- /dev/null
+++ b/src/proto/search.pro
@@ -0,0 +1,33 @@
+/* search.c */
+int search_regcomp __ARGS((char_u *pat, int pat_save, int pat_use, int options, regmmatch_T *regmatch));
+char_u *get_search_pat __ARGS((void));
+void save_search_patterns __ARGS((void));
+void restore_search_patterns __ARGS((void));
+int ignorecase __ARGS((char_u *pat));
+char_u *last_search_pat __ARGS((void));
+void reset_search_dir __ARGS((void));
+void set_last_search_pat __ARGS((char_u *s, int idx, int magic, int setlast));
+void last_pat_prog __ARGS((regmmatch_T *regmatch));
+int searchit __ARGS((win_T *win, buf_T *buf, pos_T *pos, int dir, char_u *pat, long count, int options, int pat_use));
+int do_search __ARGS((oparg_T *oap, int dirc, char_u *pat, long count, int options));
+int search_for_exact_line __ARGS((buf_T *buf, pos_T *pos, int dir, char_u *pat));
+int searchc __ARGS((cmdarg_T *cap, int t_cmd));
+pos_T *findmatch __ARGS((oparg_T *oap, int initc));
+pos_T *findmatchlimit __ARGS((oparg_T *oap, int initc, int flags, int maxtravel));
+void showmatch __ARGS((int c));
+int findsent __ARGS((int dir, long count));
+int findpar __ARGS((oparg_T *oap, int dir, long count, int what, int both));
+int startPS __ARGS((linenr_T lnum, int para, int both));
+int fwd_word __ARGS((long count, int bigword, int eol));
+int bck_word __ARGS((long count, int bigword, int stop));
+int end_word __ARGS((long count, int bigword, int stop, int empty));
+int bckend_word __ARGS((long count, int bigword, int eol));
+int current_word __ARGS((oparg_T *oap, long count, int include, int bigword));
+int current_sent __ARGS((oparg_T *oap, long count, int include));
+int current_block __ARGS((oparg_T *oap, long count, int include, int what, int other));
+int current_par __ARGS((oparg_T *oap, long count, int include, int type));
+int linewhite __ARGS((linenr_T lnum));
+void find_pattern_in_path __ARGS((char_u *ptr, int dir, int len, int whole, int skip_comments, int type, long count, int action, linenr_T start_lnum, linenr_T end_lnum));
+int read_viminfo_search_pattern __ARGS((vir_T *virp, int force));
+void write_viminfo_search_pattern __ARGS((FILE *fp));
+/* vim: set ft=c : */
diff --git a/src/proto/syntax.pro b/src/proto/syntax.pro
new file mode 100644
index 000000000..b4dd3eae6
--- /dev/null
+++ b/src/proto/syntax.pro
@@ -0,0 +1,42 @@
+/* syntax.c */
+void syntax_start __ARGS((win_T *wp, linenr_T lnum));
+void syn_stack_free_all __ARGS((buf_T *buf));
+void syn_stack_apply_changes __ARGS((buf_T *buf));
+void syntax_end_parsing __ARGS((linenr_T lnum));
+int syntax_check_changed __ARGS((linenr_T lnum));
+int get_syntax_attr __ARGS((colnr_T col));
+void syntax_clear __ARGS((buf_T *buf));
+void ex_syntax __ARGS((exarg_T *eap));
+int syntax_present __ARGS((buf_T *buf));
+void set_context_in_syntax_cmd __ARGS((expand_T *xp, char_u *arg));
+char_u *get_syntax_name __ARGS((expand_T *xp, int idx));
+int syn_get_id __ARGS((long lnum, long col, int trans));
+int syn_get_foldlevel __ARGS((win_T *wp, long lnum));
+void init_highlight __ARGS((int both, int reset));
+int load_colors __ARGS((char_u *p));
+void do_highlight __ARGS((char_u *line, int forceit, int init));
+void restore_cterm_colors __ARGS((void));
+void set_normal_colors __ARGS((void));
+char_u *hl_get_font_name __ARGS((void));
+void hl_set_font_name __ARGS((char_u *font_name));
+void hl_set_bg_color_name __ARGS((char_u *name));
+void hl_set_fg_color_name __ARGS((char_u *name));
+attrentry_T *syn_gui_attr2entry __ARGS((int attr));
+attrentry_T *syn_term_attr2entry __ARGS((int attr));
+attrentry_T *syn_cterm_attr2entry __ARGS((int attr));
+char_u *highlight_has_attr __ARGS((int id, int flag, int modec));
+char_u *highlight_color __ARGS((int id, char_u *what, int modec));
+long_u highlight_gui_color_rgb __ARGS((int id, int fg));
+int syn_name2id __ARGS((char_u *name));
+int highlight_exists __ARGS((char_u *name));
+int syn_namen2id __ARGS((char_u *linep, int len));
+int syn_check_group __ARGS((char_u *pp, int len));
+int syn_id2attr __ARGS((int hl_id));
+int syn_id2colors __ARGS((int hl_id, guicolor_T *fgp, guicolor_T *bgp));
+int syn_get_final_id __ARGS((int hl_id));
+void highlight_gui_started __ARGS((void));
+int highlight_changed __ARGS((void));
+void set_context_in_highlight_cmd __ARGS((expand_T *xp, char_u *arg));
+char_u *get_highlight_name __ARGS((expand_T *xp, int idx));
+void free_highlight_fonts __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/tag.pro b/src/proto/tag.pro
new file mode 100644
index 000000000..f8c236f56
--- /dev/null
+++ b/src/proto/tag.pro
@@ -0,0 +1,8 @@
+/* tag.c */
+int do_tag __ARGS((char_u *tag, int type, int count, int forceit, int verbose));
+void tag_freematch __ARGS((void));
+void do_tags __ARGS((exarg_T *eap));
+int find_tags __ARGS((char_u *pat, int *num_matches, char_u ***matchesp, int flags, int mincount, char_u *buf_ffname));
+void simplify_filename __ARGS((char_u *filename));
+int expand_tags __ARGS((int tagnames, char_u *pat, int *num_file, char_u ***file));
+/* vim: set ft=c : */
diff --git a/src/proto/term.pro b/src/proto/term.pro
new file mode 100644
index 000000000..16924badc
--- /dev/null
+++ b/src/proto/term.pro
@@ -0,0 +1,58 @@
+/* term.c */
+int set_termname __ARGS((char_u *term));
+void set_mouse_termcode __ARGS((int n, char_u *s));
+void del_mouse_termcode __ARGS((int n));
+void getlinecol __ARGS((long *cp, long *rp));
+int add_termcap_entry __ARGS((char_u *name, int force));
+int term_is_8bit __ARGS((char_u *name));
+int term_is_gui __ARGS((char_u *name));
+char_u *tltoa __ARGS((unsigned long i));
+void termcapinit __ARGS((char_u *name));
+void out_flush __ARGS((void));
+void out_flush_check __ARGS((void));
+void out_trash __ARGS((void));
+void out_char __ARGS((unsigned c));
+void out_str_nf __ARGS((char_u *s));
+void out_str __ARGS((char_u *s));
+void term_windgoto __ARGS((int row, int col));
+void term_cursor_right __ARGS((int i));
+void term_append_lines __ARGS((int line_count));
+void term_delete_lines __ARGS((int line_count));
+void term_set_winpos __ARGS((int x, int y));
+void term_set_winsize __ARGS((int width, int height));
+void term_fg_color __ARGS((int n));
+void term_bg_color __ARGS((int n));
+void term_settitle __ARGS((char_u *title));
+void ttest __ARGS((int pairs));
+void add_long_to_buf __ARGS((long_u val, char_u *dst));
+void check_shellsize __ARGS((void));
+void win_new_shellsize __ARGS((void));
+void shell_resized __ARGS((void));
+void shell_resized_check __ARGS((void));
+void set_shellsize __ARGS((int width, int height, int mustset));
+void settmode __ARGS((int tmode));
+void starttermcap __ARGS((void));
+void stoptermcap __ARGS((void));
+int swapping_screen __ARGS((void));
+void setmouse __ARGS((void));
+int mouse_has __ARGS((int c));
+int mouse_model_popup __ARGS((void));
+void scroll_start __ARGS((void));
+void cursor_on __ARGS((void));
+void cursor_off __ARGS((void));
+void scroll_region_set __ARGS((win_T *wp, int off));
+void scroll_region_reset __ARGS((void));
+void clear_termcodes __ARGS((void));
+void add_termcode __ARGS((char_u *name, char_u *string, int use_8bit));
+char_u *find_termcode __ARGS((char_u *name));
+char_u *get_termcode __ARGS((int i));
+void del_termcode __ARGS((char_u *name));
+void set_mouse_topline __ARGS((win_T *wp));
+int check_termcode __ARGS((int max_offset, char_u *buf, int buflen));
+char_u *replace_termcodes __ARGS((char_u *from, char_u **bufp, int from_part, int do_lt));
+int find_term_bykeys __ARGS((char_u *src));
+void show_termcodes __ARGS((void));
+int show_one_termcode __ARGS((char_u *name, char_u *code, int printit));
+char_u *translate_mapping __ARGS((char_u *str, int expmap));
+void update_tcap __ARGS((int attr));
+/* vim: set ft=c : */
diff --git a/src/proto/termlib.pro b/src/proto/termlib.pro
new file mode 100644
index 000000000..4369ecfc6
--- /dev/null
+++ b/src/proto/termlib.pro
@@ -0,0 +1,8 @@
+/* termlib.c */
+int tgetent __ARGS((char *tbuf, char *term));
+int tgetflag __ARGS((char *id));
+int tgetnum __ARGS((char *id));
+char *tgetstr __ARGS((char *id, char **buf));
+char *tgoto __ARGS((char *cm, int col, int line));
+int tputs __ARGS((char *cp, int affcnt, void (*outc)(unsigned int)));
+/* vim: set ft=c : */
diff --git a/src/proto/ui.pro b/src/proto/ui.pro
new file mode 100644
index 000000000..8825b6a16
--- /dev/null
+++ b/src/proto/ui.pro
@@ -0,0 +1,61 @@
+/* ui.c */
+void ui_write __ARGS((char_u *s, int len));
+void ui_inchar_undo __ARGS((char_u *s, int len));
+int ui_inchar __ARGS((char_u *buf, int maxlen, long wtime, int tb_change_cnt));
+int ui_char_avail __ARGS((void));
+void ui_delay __ARGS((long msec, int ignoreinput));
+void ui_suspend __ARGS((void));
+void suspend_shell __ARGS((void));
+int ui_get_shellsize __ARGS((void));
+void ui_set_shellsize __ARGS((int mustset));
+void ui_new_shellsize __ARGS((void));
+void ui_breakcheck __ARGS((void));
+void clip_init __ARGS((int can_use));
+void clip_update_selection __ARGS((void));
+void clip_own_selection __ARGS((VimClipboard *cbd));
+void clip_lose_selection __ARGS((VimClipboard *cbd));
+void clip_copy_selection __ARGS((void));
+void clip_auto_select __ARGS((void));
+int clip_isautosel __ARGS((void));
+void clip_modeless __ARGS((int button, int is_click, int is_drag));
+void clip_start_selection __ARGS((int col, int row, int repeated_click));
+void clip_process_selection __ARGS((int button, int col, int row, int_u repeated_click));
+void clip_may_redraw_selection __ARGS((int row, int col, int len));
+void clip_clear_selection __ARGS((void));
+void clip_may_clear_selection __ARGS((int row1, int row2));
+void clip_scroll_selection __ARGS((int rows));
+void clip_copy_modeless_selection __ARGS((int both));
+int clip_gen_own_selection __ARGS((VimClipboard *cbd));
+void clip_gen_lose_selection __ARGS((VimClipboard *cbd));
+void clip_gen_set_selection __ARGS((VimClipboard *cbd));
+void clip_gen_request_selection __ARGS((VimClipboard *cbd));
+int vim_is_input_buf_full __ARGS((void));
+int vim_is_input_buf_empty __ARGS((void));
+int vim_free_in_input_buf __ARGS((void));
+int vim_used_in_input_buf __ARGS((void));
+char_u *get_input_buf __ARGS((void));
+void set_input_buf __ARGS((char_u *p));
+void add_to_input_buf __ARGS((char_u *s, int len));
+void add_to_input_buf_csi __ARGS((char_u *str, int len));
+void push_raw_key __ARGS((char_u *s, int len));
+void trash_input_buf __ARGS((void));
+int read_from_input_buf __ARGS((char_u *buf, long maxlen));
+void fill_input_buf __ARGS((int exit_on_error));
+void read_error_exit __ARGS((void));
+void ui_cursor_shape __ARGS((void));
+int check_col __ARGS((int col));
+int check_row __ARGS((int row));
+void open_app_context __ARGS((void));
+void x11_setup_atoms __ARGS((Display *dpy));
+void clip_x11_request_selection __ARGS((Widget myShell, Display *dpy, VimClipboard *cbd));
+void clip_x11_lose_selection __ARGS((Widget myShell, VimClipboard *cbd));
+int clip_x11_own_selection __ARGS((Widget myShell, VimClipboard *cbd));
+void clip_x11_set_selection __ARGS((VimClipboard *cbd));
+int jump_to_mouse __ARGS((int flags, int *inclusive, int which_button));
+int mouse_comp_pos __ARGS((win_T *win, int *rowp, int *colp, linenr_T *lnump));
+win_T *mouse_find_win __ARGS((int *rowp, int *colp));
+int get_fpos_of_mouse __ARGS((pos_T *mpos));
+int vcol2col __ARGS((win_T *wp, linenr_T lnum, int vcol));
+void ui_focus_change __ARGS((int in_focus));
+void im_save_status __ARGS((long *psave));
+/* vim: set ft=c : */
diff --git a/src/proto/undo.pro b/src/proto/undo.pro
new file mode 100644
index 000000000..8ac23239e
--- /dev/null
+++ b/src/proto/undo.pro
@@ -0,0 +1,18 @@
+/* undo.c */
+int u_save_cursor __ARGS((void));
+int u_save __ARGS((linenr_T top, linenr_T bot));
+int u_savesub __ARGS((linenr_T lnum));
+int u_inssub __ARGS((linenr_T lnum));
+int u_savedel __ARGS((linenr_T lnum, long nlines));
+void u_undo __ARGS((int count));
+void u_redo __ARGS((int count));
+void u_sync __ARGS((void));
+void u_unchanged __ARGS((buf_T *buf));
+void u_clearall __ARGS((buf_T *buf));
+void u_saveline __ARGS((linenr_T lnum));
+void u_clearline __ARGS((void));
+void u_undoline __ARGS((void));
+void u_blockfree __ARGS((buf_T *buf));
+int bufIsChanged __ARGS((buf_T *buf));
+int curbufIsChanged __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/version.pro b/src/proto/version.pro
new file mode 100644
index 000000000..3f371f9b8
--- /dev/null
+++ b/src/proto/version.pro
@@ -0,0 +1,9 @@
+/* version.c */
+void make_version __ARGS((void));
+int highest_patch __ARGS((void));
+int has_patch __ARGS((int n));
+void ex_version __ARGS((exarg_T *eap));
+void list_version __ARGS((void));
+void intro_message __ARGS((int colon));
+void ex_intro __ARGS((exarg_T *eap));
+/* vim: set ft=c : */
diff --git a/src/proto/window.pro b/src/proto/window.pro
new file mode 100644
index 000000000..243bd7bf6
--- /dev/null
+++ b/src/proto/window.pro
@@ -0,0 +1,44 @@
+/* window.c */
+void do_window __ARGS((int nchar, long Prenum, int xchar));
+int win_split __ARGS((int size, int flags));
+int win_valid __ARGS((win_T *win));
+int win_count __ARGS((void));
+int make_windows __ARGS((int count, int vertical));
+void win_move_after __ARGS((win_T *win1, win_T *win2));
+void win_equal __ARGS((win_T *next_curwin, int current, int dir));
+void close_windows __ARGS((buf_T *buf));
+void win_close __ARGS((win_T *win, int free_buf));
+void close_others __ARGS((int message, int forceit));
+void win_init __ARGS((win_T *wp));
+void win_alloc_first __ARGS((void));
+void win_goto __ARGS((win_T *wp));
+win_T *win_find_nr __ARGS((int winnr));
+void win_enter __ARGS((win_T *wp, int undo_sync));
+win_T *buf_jump_open_win __ARGS((buf_T *buf));
+int win_alloc_lines __ARGS((win_T *wp));
+void win_free_lsize __ARGS((win_T *wp));
+void shell_new_rows __ARGS((void));
+void shell_new_columns __ARGS((void));
+void win_size_save __ARGS((garray_T *gap));
+void win_size_restore __ARGS((garray_T *gap));
+void win_setheight __ARGS((int height));
+void win_setheight_win __ARGS((int height, win_T *win));
+void win_setwidth __ARGS((int width));
+void win_setwidth_win __ARGS((int width, win_T *wp));
+void win_setminheight __ARGS((void));
+void win_drag_status_line __ARGS((win_T *dragwin, int offset));
+void win_drag_vsep_line __ARGS((win_T *dragwin, int offset));
+void win_comp_scroll __ARGS((win_T *wp));
+void command_height __ARGS((long old_p_ch));
+void last_status __ARGS((int morewin));
+char_u *file_name_at_cursor __ARGS((int options, long count));
+char_u *file_name_in_line __ARGS((char_u *line, int col, int options, long count, char_u *rel_fname));
+char_u *find_file_name_in_path __ARGS((char_u *ptr, int len, int options, long count, char_u *rel_fname));
+int path_with_url __ARGS((char_u *fname));
+int vim_isAbsName __ARGS((char_u *name));
+int vim_FullName __ARGS((char_u *fname, char_u *buf, int len, int force));
+int min_rows __ARGS((void));
+int only_one_window __ARGS((void));
+void check_lnums __ARGS((int do_curwin));
+int win_hasvertsplit __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/workshop.pro b/src/proto/workshop.pro
new file mode 100644
index 000000000..13a105065
--- /dev/null
+++ b/src/proto/workshop.pro
@@ -0,0 +1,48 @@
+/* workshop.c */
+void workshop_init __ARGS((void));
+void workshop_postinit __ARGS((void));
+void ex_wsverb __ARGS((exarg_T *eap));
+char *workshop_get_editor_name __ARGS((void));
+char *workshop_get_editor_version __ARGS((void));
+void workshop_load_file __ARGS((char *filename, int line, char *frameid));
+void workshop_reload_file __ARGS((char *filename, int line));
+void workshop_show_file __ARGS((char *filename));
+void workshop_goto_line __ARGS((char *filename, int lineno));
+void workshop_front_file __ARGS((char *filename));
+void workshop_save_file __ARGS((char *filename));
+void workshop_save_files __ARGS((void));
+void workshop_quit __ARGS((void));
+void workshop_minimize __ARGS((void));
+void workshop_maximize __ARGS((void));
+void workshop_add_mark_type __ARGS((int idx, char *colorspec, char *sign));
+void workshop_set_mark __ARGS((char *filename, int lineno, int markId, int idx));
+void workshop_change_mark_type __ARGS((char *filename, int markId, int idx));
+void workshop_goto_mark __ARGS((char *filename, int markId, char *message));
+void workshop_delete_mark __ARGS((char *filename, int markId));
+int workshop_get_mark_lineno __ARGS((char *filename, int markId));
+void workshop_moved_marks __ARGS((char *filename));
+int workshop_get_font_height __ARGS((void));
+void workshop_footer_message __ARGS((char *message, int severity));
+void workshop_menu_begin __ARGS((char *label));
+void workshop_submenu_begin __ARGS((char *label));
+void workshop_submenu_end __ARGS((void));
+void workshop_menu_item __ARGS((char *label, char *verb, char *accelerator, char *acceleratorText, char *name, char *filepos, char *sensitive));
+void workshop_menu_end __ARGS((void));
+void workshop_toolbar_begin __ARGS((void));
+void workshop_toolbar_end __ARGS((void));
+void workshop_toolbar_button __ARGS((char *label, char *verb, char *senseVerb, char *filepos, char *help, char *sense, char *file, char *left));
+void workshop_frame_sensitivities __ARGS((VerbSense *vs));
+void workshop_set_option __ARGS((char *option, char *value));
+void workshop_balloon_mode __ARGS((Boolean on));
+void workshop_balloon_delay __ARGS((int delay));
+void workshop_show_balloon_tip __ARGS((char *tip));
+void workshop_hotkeys __ARGS((Boolean on));
+int workshop_get_positions __ARGS((void *clientData, char **filename, int *curLine, int *curCol, int *selStartLine, int *selStartCol, int *selEndLine, int *selEndCol, int *selLength, char **selection));
+char *workshop_test_getcurrentfile __ARGS((void));
+int workshop_test_getcursorrow __ARGS((void));
+int workshop_test_getcursorcol __ARGS((void));
+char *workshop_test_getcursorrowtext __ARGS((void));
+char *workshop_test_getselectedtext __ARGS((void));
+void workshop_save_sensitivity __ARGS((char *filename));
+void findYourself __ARGS((char *argv0));
+/* vim: set ft=c : */
diff --git a/src/pty.c b/src/pty.c
new file mode 100644
index 000000000..c28d78e43
--- /dev/null
+++ b/src/pty.c
@@ -0,0 +1,425 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * The stuff in this file mostly comes from the "screen" program.
+ * Included with permission from Juergen Weigert.
+ * Copied from "pty.c". "putenv.c" was used for putenv() in misc2.c.
+ *
+ * It has been modified to work better with Vim.
+ * The parts that are not used in Vim have been deleted.
+ * See the "screen" sources for the complete stuff.
+ */
+
+/* Copyright (c) 1993
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Copyright (c) 1987 Oliver Laumann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING); if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* RCS_ID("$Id$ FAU") */
+
+#include "vim.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#include <signal.h>
+
+#ifdef __CYGWIN32__
+# include <sys/termios.h>
+#endif
+
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+
+#if HAVE_STROPTS_H
+#include <sys/types.h>
+#ifdef sinix
+#define buf_T __system_buf_t__
+#endif
+#include <stropts.h>
+#ifdef sinix
+#undef buf_T
+#endif
+# ifdef sun
+# include <sys/conf.h>
+# endif
+#endif
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if HAVE_TERMIO_H
+# include <termio.h>
+#else
+# if HAVE_TERMIOS_H
+# include <termios.h>
+# endif
+#endif
+
+#if HAVE_SYS_STREAM_H
+# include <sys/stream.h>
+#endif
+
+#if HAVE_SYS_PTEM_H
+# include <sys/ptem.h>
+#endif
+
+#if !defined(sun) && !defined(VMS) && !defined(MACOS)
+# include <sys/ioctl.h>
+#endif
+
+#if defined(sun) && defined(LOCKPTY) && !defined(TIOCEXCL)
+# include <sys/ttold.h>
+#endif
+
+#ifdef ISC
+# include <sys/tty.h>
+# include <sys/sioctl.h>
+# include <sys/pty.h>
+#endif
+
+#ifdef sgi
+# include <sys/sysmacros.h>
+#endif
+
+#if defined(_INCLUDE_HPUX_SOURCE) && !defined(hpux)
+# define hpux
+#endif
+
+/*
+ * if no PTYRANGE[01] is in the config file, we pick a default
+ */
+#ifndef PTYRANGE0
+# define PTYRANGE0 "qprs"
+#endif
+#ifndef PTYRANGE1
+# define PTYRANGE1 "0123456789abcdef"
+#endif
+
+/* SVR4 pseudo ttys don't seem to work with SCO-5 */
+#ifdef M_UNIX
+# undef HAVE_SVR4_PTYS
+#endif
+
+static void initmaster __ARGS((int));
+
+/*
+ * Open all ptys with O_NOCTTY, just to be on the safe side
+ * (RISCos mips breaks otherwise)
+ */
+#ifndef O_NOCTTY
+# define O_NOCTTY 0
+#endif
+
+ static void
+initmaster(f)
+ int f;
+{
+#ifndef VMS
+# ifdef POSIX
+ tcflush(f, TCIOFLUSH);
+# else
+# ifdef TIOCFLUSH
+ (void)ioctl(f, TIOCFLUSH, (char *) 0);
+# endif
+# endif
+# ifdef LOCKPTY
+ (void)ioctl(f, TIOCEXCL, (char *) 0);
+# endif
+#endif
+}
+
+/*
+ * This causes a hang on some systems, but is required for a properly working
+ * pty on others. Needs to be tuned...
+ */
+ int
+SetupSlavePTY(fd)
+ int fd;
+{
+ if (fd < 0)
+ return 0;
+#if defined(I_PUSH) && defined(HAVE_SVR4_PTYS) && !defined(sgi) && !defined(linux) && !defined(__osf__) && !defined(M_UNIX)
+# if defined(HAVE_SYS_PTEM_H) || defined(hpux)
+ if (ioctl(fd, I_PUSH, "ptem") != 0)
+ return -1;
+# endif
+ if (ioctl(fd, I_PUSH, "ldterm") != 0)
+ return -1;
+# ifdef sun
+ if (ioctl(fd, I_PUSH, "ttcompat") != 0)
+ return -1;
+# endif
+#endif
+ return 0;
+}
+
+
+#if defined(OSX) && !defined(PTY_DONE)
+#define PTY_DONE
+ int
+OpenPTY(ttyn)
+ char **ttyn;
+{
+ int f;
+ static char TtyName[32];
+
+ if ((f = open_controlling_pty(TtyName)) < 0)
+ return -1;
+ initmaster(f);
+ *ttyn = TtyName;
+ return f;
+}
+#endif
+
+#if (defined(sequent) || defined(_SEQUENT_)) && defined(HAVE_GETPSEUDOTTY) \
+ && !defined(PTY_DONE)
+#define PTY_DONE
+ int
+OpenPTY(ttyn)
+ char **ttyn;
+{
+ char *m, *s;
+ int f;
+ /* used for opening a new pty-pair: */
+ static char PtyName[32];
+ static char TtyName[32];
+
+ if ((f = getpseudotty(&s, &m)) < 0)
+ return -1;
+#ifdef _SEQUENT_
+ fvhangup(s);
+#endif
+ strncpy(PtyName, m, sizeof(PtyName));
+ strncpy(TtyName, s, sizeof(TtyName));
+ initmaster(f);
+ *ttyn = TtyName;
+ return f;
+}
+#endif
+
+#if defined(__sgi) && !defined(PTY_DONE)
+#define PTY_DONE
+ int
+OpenPTY(ttyn)
+ char **ttyn;
+{
+ int f;
+ char *name;
+ RETSIGTYPE (*sigcld)__ARGS(SIGPROTOARG);
+
+ /*
+ * SIGCHLD set to SIG_DFL for _getpty() because it may fork() and
+ * exec() /usr/adm/mkpts
+ */
+ sigcld = signal(SIGCHLD, SIG_DFL);
+ name = _getpty(&f, O_RDWR | O_NONBLOCK | O_EXTRA, 0600, 0);
+ signal(SIGCHLD, sigcld);
+
+ if (name == 0)
+ return -1;
+ initmaster(f);
+ *ttyn = name;
+ return f;
+}
+#endif
+
+#if defined(MIPS) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE)
+#define PTY_DONE
+ int
+OpenPTY(ttyn)
+ char **ttyn;
+{
+ int f;
+ struct stat buf;
+ /* used for opening a new pty-pair: */
+ static char TtyName[32];
+
+ if ((f = open("/dev/ptc", O_RDWR | O_NOCTTY | O_NONBLOCK | O_EXTRA, 0)) < 0)
+ return -1;
+ if (mch_fstat(f, &buf) < 0)
+ {
+ close(f);
+ return -1;
+ }
+ sprintf(TtyName, "/dev/ttyq%d", minor(buf.st_rdev));
+ initmaster(f);
+ *ttyn = TtyName;
+ return f;
+}
+#endif
+
+#if defined(HAVE_SVR4_PTYS) && !defined(PTY_DONE) && !defined(hpux)
+
+/* NOTE: Even though HPUX can have /dev/ptmx, the code below doesn't work! */
+#define PTY_DONE
+ int
+OpenPTY(ttyn)
+ char **ttyn;
+{
+ int f;
+ char *m, *ptsname();
+ int unlockpt __ARGS((int)), grantpt __ARGS((int));
+ RETSIGTYPE (*sigcld)__ARGS(SIGPROTOARG);
+ /* used for opening a new pty-pair: */
+ static char TtyName[32];
+
+ if ((f = open("/dev/ptmx", O_RDWR | O_NOCTTY | O_EXTRA, 0)) == -1)
+ return -1;
+
+ /*
+ * SIGCHLD set to SIG_DFL for grantpt() because it fork()s and
+ * exec()s pt_chmod
+ */
+ sigcld = signal(SIGCHLD, SIG_DFL);
+ if ((m = ptsname(f)) == NULL || grantpt(f) || unlockpt(f))
+ {
+ signal(SIGCHLD, sigcld);
+ close(f);
+ return -1;
+ }
+ signal(SIGCHLD, sigcld);
+ strncpy(TtyName, m, sizeof(TtyName));
+ initmaster(f);
+ *ttyn = TtyName;
+ return f;
+}
+#endif
+
+#if defined(_AIX) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE)
+#define PTY_DONE
+
+#ifdef _IBMR2
+int aixhack = -1;
+#endif
+
+ int
+OpenPTY(ttyn)
+ char **ttyn;
+{
+ int f;
+ /* used for opening a new pty-pair: */
+ static char TtyName[32];
+
+ /* a dumb looking loop replaced by mycrofts code: */
+ if ((f = open("/dev/ptc", O_RDWR | O_NOCTTY | O_EXTRA)) < 0)
+ return -1;
+ strncpy(TtyName, ttyname(f), sizeof(TtyName));
+ if (geteuid() && mch_access(TtyName, R_OK | W_OK))
+ {
+ close(f);
+ return -1;
+ }
+ initmaster(f);
+# ifdef _IBMR2
+ if (aixhack >= 0)
+ close(aixhack);
+ if ((aixhack = open(TtyName, O_RDWR | O_NOCTTY | O_EXTRA, 0)) < 0)
+ {
+ close(f);
+ return -1;
+ }
+# endif
+ *ttyn = TtyName;
+ return f;
+}
+#endif
+
+#ifndef PTY_DONE
+
+# ifdef hpux
+static char PtyProto[] = "/dev/ptym/ptyXY";
+static char TtyProto[] = "/dev/pty/ttyXY";
+# else
+# ifdef __BEOS__
+static char PtyProto[] = "/dev/pt/XY";
+static char TtyProto[] = "/dev/tt/XY";
+# else
+static char PtyProto[] = "/dev/ptyXY";
+static char TtyProto[] = "/dev/ttyXY";
+# endif
+# endif
+
+ int
+OpenPTY(ttyn)
+ char **ttyn;
+{
+ char *p, *q, *l, *d;
+ int f;
+ /* used for opening a new pty-pair: */
+ static char PtyName[32];
+ static char TtyName[32];
+
+ strcpy(PtyName, PtyProto);
+ strcpy(TtyName, TtyProto);
+ for (p = PtyName; *p != 'X'; p++)
+ ;
+ for (q = TtyName; *q != 'X'; q++)
+ ;
+ for (l = PTYRANGE0; (*p = *l) != '\0'; l++)
+ {
+ for (d = PTYRANGE1; (p[1] = *d) != '\0'; d++)
+ {
+#if !defined(MACOS) || defined(USE_CARBONIZED)
+ if ((f = open(PtyName, O_RDWR | O_NOCTTY | O_EXTRA, 0)) == -1)
+#else
+ if ((f = open(PtyName, O_RDWR | O_NOCTTY | O_EXTRA)) == -1)
+#endif
+ continue;
+ q[0] = *l;
+ q[1] = *d;
+#ifndef MACOS
+ if (geteuid() && mch_access(TtyName, R_OK | W_OK))
+ {
+ close(f);
+ continue;
+ }
+#endif
+#if defined(sun) && defined(TIOCGPGRP) && !defined(SUNOS3)
+ /* Hack to ensure that the slave side of the pty is
+ * unused. May not work in anything other than SunOS4.1
+ */
+ {
+ int pgrp;
+
+ /* tcgetpgrp does not work (uses TIOCGETPGRP)! */
+ if (ioctl(f, TIOCGPGRP, (char *)&pgrp) != -1 || errno != EIO)
+ {
+ close(f);
+ continue;
+ }
+ }
+#endif
+ initmaster(f);
+ *ttyn = TtyName;
+ return f;
+ }
+ }
+ return -1;
+}
+#endif
diff --git a/src/quickfix.c b/src/quickfix.c
new file mode 100644
index 000000000..5dbbc1b53
--- /dev/null
+++ b/src/quickfix.c
@@ -0,0 +1,2232 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * quickfix.c: functions for quickfix mode, using a file with error messages
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_QUICKFIX) || defined(PROTO)
+
+struct dir_stack_T
+{
+ struct dir_stack_T *next;
+ char_u *dirname;
+};
+
+static struct dir_stack_T *dir_stack = NULL;
+
+/*
+ * for each error the next struct is allocated and linked in a list
+ */
+struct qf_line
+{
+ struct qf_line *qf_next; /* pointer to next error in the list */
+ struct qf_line *qf_prev; /* pointer to previous error in the list */
+ linenr_T qf_lnum; /* line number where the error occurred */
+ int qf_fnum; /* file number for the line */
+ int qf_col; /* column where the error occurred */
+ int qf_nr; /* error number */
+ char_u *qf_text; /* description of the error */
+ char_u qf_virt_col; /* set to TRUE if qf_col is screen column */
+ char_u qf_cleared;/* set to TRUE if line has been deleted */
+ char_u qf_type; /* type of the error (mostly 'E'); 1 for
+ :helpgrep */
+ char_u qf_valid; /* valid error message detected */
+};
+
+/*
+ * There is a stack of error lists.
+ */
+#define LISTCOUNT 10
+
+struct qf_list
+{
+ struct qf_line *qf_start; /* pointer to the first error */
+ struct qf_line *qf_ptr; /* pointer to the current error */
+ int qf_count; /* number of errors (0 means no error list) */
+ int qf_index; /* current index in the error list */
+ int qf_nonevalid; /* TRUE if not a single valid entry found */
+} qf_lists[LISTCOUNT];
+
+static int qf_curlist = 0; /* current error list */
+static int qf_listcount = 0; /* current number of lists */
+
+#define FMT_PATTERNS 9 /* maximum number of % recognized */
+
+/*
+ * Structure used to hold the info of one part of 'errorformat'
+ */
+struct eformat
+{
+ regprog_T *prog; /* pre-formatted part of 'errorformat' */
+ struct eformat *next; /* pointer to next (NULL if last) */
+ char_u addr[FMT_PATTERNS]; /* indices of used % patterns */
+ char_u prefix; /* prefix of this format line: */
+ /* 'D' enter directory */
+ /* 'X' leave directory */
+ /* 'A' start of multi-line message */
+ /* 'E' error message */
+ /* 'W' warning message */
+ /* 'I' informational message */
+ /* 'C' continuation line */
+ /* 'Z' end of multi-line message */
+ /* 'G' general, unspecific message */
+ /* 'P' push file (partial) message */
+ /* 'Q' pop/quit file (partial) message */
+ /* 'O' overread (partial) message */
+ char_u flags; /* additional flags given in prefix */
+ /* '-' do not include this line */
+};
+
+static void qf_new_list __ARGS((void));
+static int qf_add_entry __ARGS((struct qf_line **prevp, char_u *dir, char_u *fname, char_u *mesg, long lnum, int col, int virt_col, int nr, int type, int valid));
+static void qf_msg __ARGS((void));
+static void qf_free __ARGS((int idx));
+static char_u *qf_types __ARGS((int, int));
+static int qf_get_fnum __ARGS((char_u *, char_u *));
+static char_u *qf_push_dir __ARGS((char_u *, struct dir_stack_T **));
+static char_u *qf_pop_dir __ARGS((struct dir_stack_T **));
+static char_u *qf_guess_filepath __ARGS((char_u *));
+static void qf_fmt_text __ARGS((char_u *text, char_u *buf, int bufsize));
+static void qf_clean_dir_stack __ARGS((struct dir_stack_T **));
+#ifdef FEAT_WINDOWS
+static int qf_win_pos_update __ARGS((int old_qf_index));
+static buf_T *qf_find_buf __ARGS((void));
+static void qf_update_buffer __ARGS((void));
+static void qf_fill_buffer __ARGS((void));
+#endif
+static char_u *get_mef_name __ARGS((void));
+
+/*
+ * Read the errorfile into memory, line by line, building the error list.
+ * Return -1 for error, number of errors for success.
+ */
+ int
+qf_init(efile, errorformat, newlist)
+ char_u *efile;
+ char_u *errorformat;
+ int newlist; /* TRUE: start a new error list */
+{
+ char_u *namebuf;
+ char_u *errmsg;
+ char_u *fmtstr = NULL;
+ int col = 0;
+ char_u use_virt_col = FALSE;
+ int type = 0;
+ int valid;
+ long lnum = 0L;
+ int enr = 0;
+ FILE *fd;
+ struct qf_line *qfprev = NULL; /* init to make SASC shut up */
+ char_u *efmp;
+ struct eformat *fmt_first = NULL;
+ struct eformat *fmt_last = NULL;
+ struct eformat *fmt_ptr;
+ char_u *efm;
+ char_u *ptr;
+ char_u *srcptr;
+ int len;
+ int i;
+ int round;
+ int idx = 0;
+ int multiline = FALSE;
+ int multiignore = FALSE;
+ int multiscan = FALSE;
+ int retval = -1; /* default: return error flag */
+ char_u *directory = NULL;
+ char_u *currfile = NULL;
+ char_u *tail = NULL;
+ struct dir_stack_T *file_stack = NULL;
+ regmatch_T regmatch;
+ static struct fmtpattern
+ {
+ char_u convchar;
+ char *pattern;
+ } fmt_pat[FMT_PATTERNS] =
+ {
+ {'f', "\\f\\+"},
+ {'n', "\\d\\+"},
+ {'l', "\\d\\+"},
+ {'c', "\\d\\+"},
+ {'t', "."},
+ {'m', ".\\+"},
+ {'r', ".*"},
+ {'p', "[- .]*"},
+ {'v', "\\d\\+"}
+ };
+
+ if (efile == NULL)
+ return FAIL;
+
+ namebuf = alloc(CMDBUFFSIZE + 1);
+ errmsg = alloc(CMDBUFFSIZE + 1);
+ if (namebuf == NULL || errmsg == NULL)
+ goto qf_init_end;
+
+ if ((fd = mch_fopen((char *)efile, "r")) == NULL)
+ {
+ EMSG2(_(e_openerrf), efile);
+ goto qf_init_end;
+ }
+
+ if (newlist || qf_curlist == qf_listcount)
+ /* make place for a new list */
+ qf_new_list();
+ else if (qf_lists[qf_curlist].qf_count > 0)
+ /* Adding to existing list, find last entry. */
+ for (qfprev = qf_lists[qf_curlist].qf_start;
+ qfprev->qf_next != qfprev; qfprev = qfprev->qf_next)
+ ;
+
+/*
+ * Each part of the format string is copied and modified from errorformat to
+ * regex prog. Only a few % characters are allowed.
+ */
+ /* Use the local value of 'errorformat' if it's set. */
+ if (errorformat == p_efm && *curbuf->b_p_efm != NUL)
+ efm = curbuf->b_p_efm;
+ else
+ efm = errorformat;
+ /*
+ * Get some space to modify the format string into.
+ */
+ i = (FMT_PATTERNS * 3) + ((int)STRLEN(efm) << 2);
+ for (round = FMT_PATTERNS; round > 0; )
+ i += (int)STRLEN(fmt_pat[--round].pattern);
+#ifdef COLON_IN_FILENAME
+ i += 12; /* "%f" can become twelve chars longer */
+#else
+ i += 2; /* "%f" can become two chars longer */
+#endif
+ if ((fmtstr = alloc(i)) == NULL)
+ goto error2;
+
+ while (efm[0])
+ {
+ /*
+ * Allocate a new eformat structure and put it at the end of the list
+ */
+ fmt_ptr = (struct eformat *)alloc((unsigned)sizeof(struct eformat));
+ if (fmt_ptr == NULL)
+ goto error2;
+ if (fmt_first == NULL) /* first one */
+ fmt_first = fmt_ptr;
+ else
+ fmt_last->next = fmt_ptr;
+ fmt_last = fmt_ptr;
+ fmt_ptr->prefix = NUL;
+ fmt_ptr->flags = NUL;
+ fmt_ptr->next = NULL;
+ fmt_ptr->prog = NULL;
+ for (round = FMT_PATTERNS; round > 0; )
+ fmt_ptr->addr[--round] = NUL;
+ /* round is 0 now */
+
+ /*
+ * Isolate one part in the 'errorformat' option
+ */
+ for (len = 0; efm[len] != NUL && efm[len] != ','; ++len)
+ if (efm[len] == '\\' && efm[len + 1] != NUL)
+ ++len;
+
+ /*
+ * Build regexp pattern from current 'errorformat' option
+ */
+ ptr = fmtstr;
+ *ptr++ = '^';
+ for (efmp = efm; efmp < efm + len; ++efmp)
+ {
+ if (*efmp == '%')
+ {
+ ++efmp;
+ for (idx = 0; idx < FMT_PATTERNS; ++idx)
+ if (fmt_pat[idx].convchar == *efmp)
+ break;
+ if (idx < FMT_PATTERNS)
+ {
+ if (fmt_ptr->addr[idx])
+ {
+ sprintf((char *)errmsg,
+ _("E372: Too many %%%c in format string"), *efmp);
+ EMSG(errmsg);
+ goto error2;
+ }
+ if ((idx
+ && idx < 6
+ && vim_strchr((char_u *)"DXOPQ",
+ fmt_ptr->prefix) != NULL)
+ || (idx == 6
+ && vim_strchr((char_u *)"OPQ",
+ fmt_ptr->prefix) == NULL))
+ {
+ sprintf((char *)errmsg,
+ _("E373: Unexpected %%%c in format string"), *efmp);
+ EMSG(errmsg);
+ goto error2;
+ }
+ fmt_ptr->addr[idx] = (char_u)++round;
+ *ptr++ = '\\';
+ *ptr++ = '(';
+#ifdef BACKSLASH_IN_FILENAME
+ if (*efmp == 'f')
+ {
+ /* Also match "c:" in the file name, even when
+ * checking for a colon next: "%f:".
+ * "\%(\a:\)\=" */
+ STRCPY(ptr, "\\%(\\a:\\)\\=");
+ ptr += 10;
+ }
+#endif
+ if (*efmp == 'f' && efmp[1] != NUL
+ && efmp[1] != '\\' && efmp[1] != '%')
+ {
+ /* A file name may contain spaces, but this isn't in
+ * "\f". use "[^x]\+" instead (x is next character) */
+ *ptr++ = '[';
+ *ptr++ = '^';
+ *ptr++ = efmp[1];
+ *ptr++ = ']';
+ *ptr++ = '\\';
+ *ptr++ = '+';
+ }
+ else
+ {
+ srcptr = (char_u *)fmt_pat[idx].pattern;
+ while ((*ptr = *srcptr++) != NUL)
+ ++ptr;
+ }
+ *ptr++ = '\\';
+ *ptr++ = ')';
+ }
+ else if (*efmp == '*')
+ {
+ if (*++efmp == '[' || *efmp == '\\')
+ {
+ if ((*ptr++ = *efmp) == '[') /* %*[^a-z0-9] etc. */
+ {
+ if (efmp[1] == '^')
+ *ptr++ = *++efmp;
+ if (efmp < efm + len)
+ {
+ *ptr++ = *++efmp; /* could be ']' */
+ while (efmp < efm + len
+ && (*ptr++ = *++efmp) != ']')
+ /* skip */;
+ if (efmp == efm + len)
+ {
+ EMSG(_("E374: Missing ] in format string"));
+ goto error2;
+ }
+ }
+ }
+ else if (efmp < efm + len) /* %*\D, %*\s etc. */
+ *ptr++ = *++efmp;
+ *ptr++ = '\\';
+ *ptr++ = '+';
+ }
+ else
+ {
+ /* TODO: scanf()-like: %*ud, %*3c, %*f, ... ? */
+ sprintf((char *)errmsg,
+ _("E375: Unsupported %%%c in format string"), *efmp);
+ EMSG(errmsg);
+ goto error2;
+ }
+ }
+ else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL)
+ *ptr++ = *efmp; /* regexp magic characters */
+ else if (*efmp == '#')
+ *ptr++ = '*';
+ else if (efmp == efm + 1) /* analyse prefix */
+ {
+ if (vim_strchr((char_u *)"+-", *efmp) != NULL)
+ fmt_ptr->flags = *efmp++;
+ if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL)
+ fmt_ptr->prefix = *efmp;
+ else
+ {
+ sprintf((char *)errmsg,
+ _("E376: Invalid %%%c in format string prefix"), *efmp);
+ EMSG(errmsg);
+ goto error2;
+ }
+ }
+ else
+ {
+ sprintf((char *)errmsg,
+ _("E377: Invalid %%%c in format string"), *efmp);
+ EMSG(errmsg);
+ goto error2;
+ }
+ }
+ else /* copy normal character */
+ {
+ if (*efmp == '\\' && efmp + 1 < efm + len)
+ ++efmp;
+ else if (vim_strchr((char_u *)".*^$~[", *efmp) != NULL)
+ *ptr++ = '\\'; /* escape regexp atoms */
+ if (*efmp)
+ *ptr++ = *efmp;
+ }
+ }
+ *ptr++ = '$';
+ *ptr = NUL;
+ if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL)
+ goto error2;
+ /*
+ * Advance to next part
+ */
+ efm = skip_to_option_part(efm + len); /* skip comma and spaces */
+ }
+ if (fmt_first == NULL) /* nothing found */
+ {
+ EMSG(_("E378: 'errorformat' contains no pattern"));
+ goto error2;
+ }
+
+ /*
+ * got_int is reset here, because it was probably set when killing the
+ * ":make" command, but we still want to read the errorfile then.
+ */
+ got_int = FALSE;
+
+ /* Always ignore case when looking for a matching error. */
+ regmatch.rm_ic = TRUE;
+
+ /*
+ * Read the lines in the error file one by one.
+ * Try to recognize one of the error formats in each line.
+ */
+ while (fgets((char *)IObuff, CMDBUFFSIZE - 2, fd) != NULL && !got_int)
+ {
+ IObuff[CMDBUFFSIZE - 2] = NUL; /* for very long lines */
+ if ((efmp = vim_strrchr(IObuff, '\n')) != NULL)
+ *efmp = NUL;
+#ifdef USE_CRNL
+ if ((efmp = vim_strrchr(IObuff, '\r')) != NULL)
+ *efmp = NUL;
+#endif
+
+ /*
+ * Try to match each part of 'errorformat' until we find a complete
+ * match or no match.
+ */
+ valid = TRUE;
+restofline:
+ for (fmt_ptr = fmt_first; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next)
+ {
+ idx = fmt_ptr->prefix;
+ if (multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL)
+ continue;
+ namebuf[0] = NUL;
+ if (!multiscan)
+ errmsg[0] = NUL;
+ lnum = 0;
+ col = 0;
+ use_virt_col = FALSE;
+ enr = -1;
+ type = 0;
+ tail = NULL;
+
+ regmatch.regprog = fmt_ptr->prog;
+ if (vim_regexec(&regmatch, IObuff, (colnr_T)0))
+ {
+ if ((idx == 'C' || idx == 'Z') && !multiline)
+ continue;
+ if (vim_strchr((char_u *)"EWI", idx) != NULL)
+ type = idx;
+ else
+ type = 0;
+ /*
+ * Extract error message data from matched line
+ */
+ if ((i = (int)fmt_ptr->addr[0]) > 0) /* %f */
+ {
+ len = (int)(regmatch.endp[i] - regmatch.startp[i]);
+ STRNCPY(namebuf, regmatch.startp[i], len);
+ namebuf[len] = NUL;
+ if (vim_strchr((char_u *)"OPQ", idx) != NULL
+ && mch_getperm(namebuf) == -1)
+ continue;
+ }
+ if ((i = (int)fmt_ptr->addr[1]) > 0) /* %n */
+ enr = (int)atol((char *)regmatch.startp[i]);
+ if ((i = (int)fmt_ptr->addr[2]) > 0) /* %l */
+ lnum = atol((char *)regmatch.startp[i]);
+ if ((i = (int)fmt_ptr->addr[3]) > 0) /* %c */
+ col = (int)atol((char *)regmatch.startp[i]);
+ if ((i = (int)fmt_ptr->addr[4]) > 0) /* %t */
+ type = *regmatch.startp[i];
+ if (fmt_ptr->flags == '+' && !multiscan) /* %+ */
+ STRCPY(errmsg, IObuff);
+ else if ((i = (int)fmt_ptr->addr[5]) > 0) /* %m */
+ {
+ len = (int)(regmatch.endp[i] - regmatch.startp[i]);
+ STRNCPY(errmsg, regmatch.startp[i], len);
+ errmsg[len] = NUL;
+ }
+ if ((i = (int)fmt_ptr->addr[6]) > 0) /* %r */
+ tail = regmatch.startp[i];
+ if ((i = (int)fmt_ptr->addr[7]) > 0) /* %p */
+ {
+ col = (int)(regmatch.endp[i] - regmatch.startp[i] + 1);
+ if (*((char_u *)regmatch.startp[i]) != TAB)
+ use_virt_col = TRUE;
+ }
+ if ((i = (int)fmt_ptr->addr[8]) > 0) /* %v */
+ {
+ col = (int)atol((char *)regmatch.startp[i]);
+ use_virt_col = TRUE;
+ }
+ break;
+ }
+ }
+ multiscan = FALSE;
+ if (!fmt_ptr || idx == 'D' || idx == 'X')
+ {
+ if (fmt_ptr)
+ {
+ if (idx == 'D') /* enter directory */
+ {
+ if (*namebuf == NUL)
+ {
+ EMSG(_("E379: Missing or empty directory name"));
+ goto error2;
+ }
+ if ((directory = qf_push_dir(namebuf, &dir_stack)) == NULL)
+ goto error2;
+ }
+ else if (idx == 'X') /* leave directory */
+ directory = qf_pop_dir(&dir_stack);
+ }
+ namebuf[0] = NUL; /* no match found, remove file name */
+ lnum = 0; /* don't jump to this line */
+ valid = FALSE;
+ STRCPY(errmsg, IObuff); /* copy whole line to error message */
+ if (!fmt_ptr)
+ multiline = multiignore = FALSE;
+ }
+ else if (fmt_ptr)
+ {
+ if (vim_strchr((char_u *)"AEWI", idx) != NULL)
+ multiline = TRUE; /* start of a multi-line message */
+ else if (vim_strchr((char_u *)"CZ", idx) != NULL)
+ { /* continuation of multi-line msg */
+ if (qfprev == NULL)
+ goto error2;
+ if (*errmsg && !multiignore)
+ {
+ len = (int)STRLEN(qfprev->qf_text);
+ if ((ptr = alloc((unsigned)(len + STRLEN(errmsg) + 2)))
+ == NULL)
+ goto error2;
+ STRCPY(ptr, qfprev->qf_text);
+ vim_free(qfprev->qf_text);
+ qfprev->qf_text = ptr;
+ *(ptr += len) = '\n';
+ STRCPY(++ptr, errmsg);
+ }
+ if (qfprev->qf_nr == -1)
+ qfprev->qf_nr = enr;
+ if (vim_isprintc(type) && !qfprev->qf_type)
+ qfprev->qf_type = type; /* only printable chars allowed */
+ if (!qfprev->qf_lnum)
+ qfprev->qf_lnum = lnum;
+ if (!qfprev->qf_col)
+ qfprev->qf_col = col;
+ qfprev->qf_virt_col = use_virt_col;
+ if (!qfprev->qf_fnum)
+ qfprev->qf_fnum = qf_get_fnum(directory,
+ *namebuf || directory ? namebuf
+ : currfile && valid ? currfile : 0);
+ if (idx == 'Z')
+ multiline = multiignore = FALSE;
+ line_breakcheck();
+ continue;
+ }
+ else if (vim_strchr((char_u *)"OPQ", idx) != NULL)
+ {
+ /* global file names */
+ valid = FALSE;
+ if (*namebuf == NUL || mch_getperm(namebuf) >= 0)
+ {
+ if (*namebuf && idx == 'P')
+ currfile = qf_push_dir(namebuf, &file_stack);
+ else if (idx == 'Q')
+ currfile = qf_pop_dir(&file_stack);
+ *namebuf = NUL;
+ if (tail && *tail)
+ {
+ STRCPY(IObuff, skipwhite(tail));
+ multiscan = TRUE;
+ goto restofline;
+ }
+ }
+ }
+ if (fmt_ptr->flags == '-') /* generally exclude this line */
+ {
+ if (multiline)
+ multiignore = TRUE; /* also exclude continuation lines */
+ continue;
+ }
+ }
+
+ if (qf_add_entry(&qfprev,
+ directory,
+ *namebuf || directory
+ ? namebuf
+ : currfile && valid ? currfile : NULL,
+ errmsg,
+ lnum,
+ col,
+ use_virt_col,
+ enr,
+ type,
+ valid) == FAIL)
+ goto error2;
+ line_breakcheck();
+ }
+ if (!ferror(fd))
+ {
+ if (qf_lists[qf_curlist].qf_index == 0) /* no valid entry found */
+ {
+ qf_lists[qf_curlist].qf_ptr = qf_lists[qf_curlist].qf_start;
+ qf_lists[qf_curlist].qf_index = 1;
+ qf_lists[qf_curlist].qf_nonevalid = TRUE;
+ }
+ else
+ {
+ qf_lists[qf_curlist].qf_nonevalid = FALSE;
+ if (qf_lists[qf_curlist].qf_ptr == NULL)
+ qf_lists[qf_curlist].qf_ptr = qf_lists[qf_curlist].qf_start;
+ }
+ retval = qf_lists[qf_curlist].qf_count; /* return number of matches */
+ goto qf_init_ok;
+ }
+ EMSG(_(e_readerrf));
+error2:
+ qf_free(qf_curlist);
+ qf_listcount--;
+ if (qf_curlist > 0)
+ --qf_curlist;
+qf_init_ok:
+ fclose(fd);
+ for (fmt_ptr = fmt_first; fmt_ptr != NULL; fmt_ptr = fmt_first)
+ {
+ fmt_first = fmt_ptr->next;
+ vim_free(fmt_ptr->prog);
+ vim_free(fmt_ptr);
+ }
+ qf_clean_dir_stack(&dir_stack);
+ qf_clean_dir_stack(&file_stack);
+qf_init_end:
+ vim_free(namebuf);
+ vim_free(errmsg);
+ vim_free(fmtstr);
+
+#ifdef FEAT_WINDOWS
+ qf_update_buffer();
+#endif
+
+ return retval;
+}
+
+/*
+ * Prepare for adding a new quickfix list.
+ */
+ static void
+qf_new_list()
+{
+ int i;
+
+ /*
+ * If the current entry is not the last entry, delete entries below
+ * the current entry. This makes it possible to browse in a tree-like
+ * way with ":grep'.
+ */
+ while (qf_listcount > qf_curlist + 1)
+ qf_free(--qf_listcount);
+
+ /*
+ * When the stack is full, remove to oldest entry
+ * Otherwise, add a new entry.
+ */
+ if (qf_listcount == LISTCOUNT)
+ {
+ qf_free(0);
+ for (i = 1; i < LISTCOUNT; ++i)
+ qf_lists[i - 1] = qf_lists[i];
+ qf_curlist = LISTCOUNT - 1;
+ }
+ else
+ qf_curlist = qf_listcount++;
+ qf_lists[qf_curlist].qf_index = 0;
+ qf_lists[qf_curlist].qf_count = 0;
+}
+
+/*
+ * Add an entry to the end of the list of errors.
+ * Returns OK or FAIL.
+ */
+ static int
+qf_add_entry(prevp, dir, fname, mesg, lnum, col, virt_col, nr, type, valid)
+ struct qf_line **prevp; /* pointer to previously added entry or NULL */
+ char_u *dir; /* optional directory name */
+ char_u *fname; /* file name or NULL */
+ char_u *mesg; /* message */
+ long lnum; /* line number */
+ int col; /* column */
+ int virt_col; /* using virtual column */
+ int nr; /* error number */
+ int type; /* type character */
+ int valid; /* valid entry */
+{
+ struct qf_line *qfp;
+
+ if ((qfp = (struct qf_line *)alloc((unsigned)sizeof(struct qf_line)))
+ == NULL)
+ return FAIL;
+ qfp->qf_fnum = qf_get_fnum(dir, fname);
+ if ((qfp->qf_text = vim_strsave(mesg)) == NULL)
+ {
+ vim_free(qfp);
+ return FAIL;
+ }
+ qfp->qf_lnum = lnum;
+ qfp->qf_col = col;
+ qfp->qf_virt_col = virt_col;
+ qfp->qf_nr = nr;
+ if (type != 1 && !vim_isprintc(type)) /* only printable chars allowed */
+ type = 0;
+ qfp->qf_type = type;
+ qfp->qf_valid = valid;
+
+ if (qf_lists[qf_curlist].qf_count == 0) /* first element in the list */
+ {
+ qf_lists[qf_curlist].qf_start = qfp;
+ qfp->qf_prev = qfp; /* first element points to itself */
+ }
+ else
+ {
+ qfp->qf_prev = *prevp;
+ (*prevp)->qf_next = qfp;
+ }
+ qfp->qf_next = qfp; /* last element points to itself */
+ qfp->qf_cleared = FALSE;
+ *prevp = qfp;
+ ++qf_lists[qf_curlist].qf_count;
+ if (qf_lists[qf_curlist].qf_index == 0 && qfp->qf_valid)
+ /* first valid entry */
+ {
+ qf_lists[qf_curlist].qf_index = qf_lists[qf_curlist].qf_count;
+ qf_lists[qf_curlist].qf_ptr = qfp;
+ }
+
+ return OK;
+}
+
+/*
+ * get buffer number for file "dir.name"
+ */
+ static int
+qf_get_fnum(directory, fname)
+ char_u *directory;
+ char_u *fname;
+{
+ if (fname == NULL || *fname == NUL) /* no file name */
+ return 0;
+ {
+#ifdef RISCOS
+ /* Name is reported as `main.c', but file is `c.main' */
+ return ro_buflist_add(fname);
+#else
+ char_u *ptr;
+ int fnum;
+
+# ifdef VMS
+ vms_remove_version(fname);
+# endif
+# ifdef BACKSLASH_IN_FILENAME
+ if (directory != NULL)
+ slash_adjust(directory);
+ slash_adjust(fname);
+# endif
+ if (directory != NULL && !vim_isAbsName(fname)
+ && (ptr = concat_fnames(directory, fname, TRUE)) != NULL)
+ {
+ /*
+ * Here we check if the file really exists.
+ * This should normally be true, but if make works without
+ * "leaving directory"-messages we might have missed a
+ * directory change.
+ */
+ if (mch_getperm(ptr) < 0)
+ {
+ vim_free(ptr);
+ directory = qf_guess_filepath(fname);
+ if (directory)
+ ptr = concat_fnames(directory, fname, TRUE);
+ else
+ ptr = vim_strsave(fname);
+ }
+ /* Use concatenated directory name and file name */
+ fnum = buflist_add(ptr, 0);
+ vim_free(ptr);
+ return fnum;
+ }
+ return buflist_add(fname, 0);
+#endif
+ }
+}
+
+/*
+ * push dirbuf onto the directory stack and return pointer to actual dir or
+ * NULL on error
+ */
+ static char_u *
+qf_push_dir(dirbuf, stackptr)
+ char_u *dirbuf;
+ struct dir_stack_T **stackptr;
+{
+ struct dir_stack_T *ds_new;
+ struct dir_stack_T *ds_ptr;
+
+ /* allocate new stack element and hook it in */
+ ds_new = (struct dir_stack_T *)alloc((unsigned)sizeof(struct dir_stack_T));
+ if (ds_new == NULL)
+ return NULL;
+
+ ds_new->next = *stackptr;
+ *stackptr = ds_new;
+
+ /* store directory on the stack */
+ if (vim_isAbsName(dirbuf)
+ || (*stackptr)->next == NULL
+ || (*stackptr && dir_stack != *stackptr))
+ (*stackptr)->dirname = vim_strsave(dirbuf);
+ else
+ {
+ /* Okay we don't have an absolute path.
+ * dirbuf must be a subdir of one of the directories on the stack.
+ * Let's search...
+ */
+ ds_new = (*stackptr)->next;
+ (*stackptr)->dirname = NULL;
+ while (ds_new)
+ {
+ vim_free((*stackptr)->dirname);
+ (*stackptr)->dirname = concat_fnames(ds_new->dirname, dirbuf,
+ TRUE);
+ if (mch_isdir((*stackptr)->dirname) == TRUE)
+ break;
+
+ ds_new = ds_new->next;
+ }
+
+ /* clean up all dirs we already left */
+ while ((*stackptr)->next != ds_new)
+ {
+ ds_ptr = (*stackptr)->next;
+ (*stackptr)->next = (*stackptr)->next->next;
+ vim_free(ds_ptr->dirname);
+ vim_free(ds_ptr);
+ }
+
+ /* Nothing found -> it must be on top level */
+ if (ds_new == NULL)
+ {
+ vim_free((*stackptr)->dirname);
+ (*stackptr)->dirname = vim_strsave(dirbuf);
+ }
+ }
+
+ if ((*stackptr)->dirname != NULL)
+ return (*stackptr)->dirname;
+ else
+ {
+ ds_ptr = *stackptr;
+ *stackptr = (*stackptr)->next;
+ vim_free(ds_ptr);
+ return NULL;
+ }
+}
+
+
+/*
+ * pop dirbuf from the directory stack and return previous directory or NULL if
+ * stack is empty
+ */
+ static char_u *
+qf_pop_dir(stackptr)
+ struct dir_stack_T **stackptr;
+{
+ struct dir_stack_T *ds_ptr;
+
+ /* TODO: Should we check if dirbuf is the directory on top of the stack?
+ * What to do if it isn't? */
+
+ /* pop top element and free it */
+ if (*stackptr != NULL)
+ {
+ ds_ptr = *stackptr;
+ *stackptr = (*stackptr)->next;
+ vim_free(ds_ptr->dirname);
+ vim_free(ds_ptr);
+ }
+
+ /* return NEW top element as current dir or NULL if stack is empty*/
+ return *stackptr ? (*stackptr)->dirname : NULL;
+}
+
+/*
+ * clean up directory stack
+ */
+ static void
+qf_clean_dir_stack(stackptr)
+ struct dir_stack_T **stackptr;
+{
+ struct dir_stack_T *ds_ptr;
+
+ while ((ds_ptr = *stackptr) != NULL)
+ {
+ *stackptr = (*stackptr)->next;
+ vim_free(ds_ptr->dirname);
+ vim_free(ds_ptr);
+ }
+}
+
+/*
+ * Check in which directory of the directory stack the given file can be
+ * found.
+ * Returns a pointer to the directory name or NULL if not found
+ * Cleans up intermediate directory entries.
+ *
+ * TODO: How to solve the following problem?
+ * If we have the this directory tree:
+ * ./
+ * ./aa
+ * ./aa/bb
+ * ./bb
+ * ./bb/x.c
+ * and make says:
+ * making all in aa
+ * making all in bb
+ * x.c:9: Error
+ * Then qf_push_dir thinks we are in ./aa/bb, but we are in ./bb.
+ * qf_guess_filepath will return NULL.
+ */
+ static char_u *
+qf_guess_filepath(filename)
+ char_u *filename;
+{
+ struct dir_stack_T *ds_ptr;
+ struct dir_stack_T *ds_tmp;
+ char_u *fullname;
+
+ /* no dirs on the stack - there's nothing we can do */
+ if (dir_stack == NULL)
+ return NULL;
+
+ ds_ptr = dir_stack->next;
+ fullname = NULL;
+ while (ds_ptr)
+ {
+ vim_free(fullname);
+ fullname = concat_fnames(ds_ptr->dirname, filename, TRUE);
+
+ /* If concat_fnames failed, just go on. The worst thing that can happen
+ * is that we delete the entire stack.
+ */
+ if ((fullname != NULL) && (mch_getperm(fullname) >= 0))
+ break;
+
+ ds_ptr = ds_ptr->next;
+ }
+
+ vim_free(fullname);
+
+ /* clean up all dirs we already left */
+ while (dir_stack->next != ds_ptr)
+ {
+ ds_tmp = dir_stack->next;
+ dir_stack->next = dir_stack->next->next;
+ vim_free(ds_tmp->dirname);
+ vim_free(ds_tmp);
+ }
+
+ return ds_ptr==NULL? NULL: ds_ptr->dirname;
+
+}
+
+/*
+ * jump to a quickfix line
+ * if dir == FORWARD go "errornr" valid entries forward
+ * if dir == BACKWARD go "errornr" valid entries backward
+ * if dir == FORWARD_FILE go "errornr" valid entries files backward
+ * if dir == BACKWARD_FILE go "errornr" valid entries files backward
+ * else if "errornr" is zero, redisplay the same line
+ * else go to entry "errornr"
+ */
+ void
+qf_jump(dir, errornr, forceit)
+ int dir;
+ int errornr;
+ int forceit;
+{
+ struct qf_line *qf_ptr;
+ struct qf_line *old_qf_ptr;
+ int qf_index;
+ int old_qf_fnum;
+ int old_qf_index;
+ int prev_index;
+ static char_u *e_no_more_items = (char_u *)N_("E553: No more items");
+ char_u *err = e_no_more_items;
+ linenr_T i;
+ buf_T *old_curbuf;
+ linenr_T old_lnum;
+ char_u *old_swb = p_swb;
+ colnr_T screen_col;
+ colnr_T char_col;
+ char_u *line;
+#ifdef FEAT_WINDOWS
+ int opened_window = FALSE;
+ win_T *win;
+ win_T *altwin;
+#endif
+ int print_message = TRUE;
+ int len;
+#ifdef FEAT_FOLDING
+ int old_KeyTyped = KeyTyped; /* getting file may reset it */
+#endif
+
+ if (qf_curlist >= qf_listcount || qf_lists[qf_curlist].qf_count == 0)
+ {
+ EMSG(_(e_quickfix));
+ return;
+ }
+
+ qf_ptr = qf_lists[qf_curlist].qf_ptr;
+ old_qf_ptr = qf_ptr;
+ qf_index = qf_lists[qf_curlist].qf_index;
+ old_qf_index = qf_index;
+ if (dir == FORWARD || dir == FORWARD_FILE) /* next valid entry */
+ {
+ while (errornr--)
+ {
+ old_qf_ptr = qf_ptr;
+ prev_index = qf_index;
+ old_qf_fnum = qf_ptr->qf_fnum;
+ do
+ {
+ if (qf_index == qf_lists[qf_curlist].qf_count
+ || qf_ptr->qf_next == NULL)
+ {
+ qf_ptr = old_qf_ptr;
+ qf_index = prev_index;
+ if (err != NULL)
+ {
+ EMSG(_(err));
+ goto theend;
+ }
+ errornr = 0;
+ break;
+ }
+ ++qf_index;
+ qf_ptr = qf_ptr->qf_next;
+ } while ((!qf_lists[qf_curlist].qf_nonevalid && !qf_ptr->qf_valid)
+ || (dir == FORWARD_FILE && qf_ptr->qf_fnum == old_qf_fnum));
+ err = NULL;
+ }
+ }
+ else if (dir == BACKWARD || dir == BACKWARD_FILE) /* prev. valid entry */
+ {
+ while (errornr--)
+ {
+ old_qf_ptr = qf_ptr;
+ prev_index = qf_index;
+ old_qf_fnum = qf_ptr->qf_fnum;
+ do
+ {
+ if (qf_index == 1 || qf_ptr->qf_prev == NULL)
+ {
+ qf_ptr = old_qf_ptr;
+ qf_index = prev_index;
+ if (err != NULL)
+ {
+ EMSG(_(err));
+ goto theend;
+ }
+ errornr = 0;
+ break;
+ }
+ --qf_index;
+ qf_ptr = qf_ptr->qf_prev;
+ } while ((!qf_lists[qf_curlist].qf_nonevalid && !qf_ptr->qf_valid)
+ || (dir == BACKWARD_FILE && qf_ptr->qf_fnum == old_qf_fnum));
+ err = NULL;
+ }
+ }
+ else if (errornr != 0) /* go to specified number */
+ {
+ while (errornr < qf_index && qf_index > 1 && qf_ptr->qf_prev != NULL)
+ {
+ --qf_index;
+ qf_ptr = qf_ptr->qf_prev;
+ }
+ while (errornr > qf_index && qf_index < qf_lists[qf_curlist].qf_count
+ && qf_ptr->qf_next != NULL)
+ {
+ ++qf_index;
+ qf_ptr = qf_ptr->qf_next;
+ }
+ }
+
+#ifdef FEAT_WINDOWS
+ qf_lists[qf_curlist].qf_index = qf_index;
+ if (qf_win_pos_update(old_qf_index))
+ /* No need to print the error message if it's visible in the error
+ * window */
+ print_message = FALSE;
+
+ /*
+ * If currently in the quickfix window, find another window to show the
+ * file in.
+ */
+ if (bt_quickfix(curbuf))
+ {
+ /*
+ * If there is no file specified, we don't know where to go.
+ * But do advance, otherwise ":cn" gets stuck.
+ */
+ if (qf_ptr->qf_fnum == 0)
+ goto theend;
+
+ /*
+ * If there is only one window, create a new one above the quickfix
+ * window.
+ */
+ if (firstwin == lastwin)
+ {
+ if (win_split(0, WSP_ABOVE) == FAIL)
+ goto failed; /* not enough room for window */
+ opened_window = TRUE; /* close it when fail */
+ p_swb = empty_option; /* don't split again */
+# ifdef FEAT_SCROLLBIND
+ curwin->w_p_scb = FALSE;
+# endif
+ }
+ else
+ {
+ /*
+ * Try to find a window that shows the right buffer.
+ * Default to the window just above the quickfix buffer.
+ */
+ win = curwin;
+ altwin = NULL;
+ for (;;)
+ {
+ if (win->w_buffer->b_fnum == qf_ptr->qf_fnum)
+ break;
+ if (win->w_prev == NULL)
+ win = lastwin; /* wrap around the top */
+ else
+ win = win->w_prev; /* go to previous window */
+
+ if (bt_quickfix(win->w_buffer))
+ {
+ /* Didn't find it, go to the window before the quickfix
+ * window. */
+ if (altwin != NULL)
+ win = altwin;
+ else if (curwin->w_prev != NULL)
+ win = curwin->w_prev;
+ else
+ win = curwin->w_next;
+ break;
+ }
+
+ /* Remember a usable window. */
+ if (altwin == NULL && !win->w_p_pvw
+ && win->w_buffer->b_p_bt[0] == NUL)
+ altwin = win;
+ }
+
+ win_goto(win);
+ }
+ }
+#endif
+
+ /*
+ * If there is a file name,
+ * read the wanted file if needed, and check autowrite etc.
+ */
+ old_curbuf = curbuf;
+ old_lnum = curwin->w_cursor.lnum;
+ if (qf_ptr->qf_fnum == 0 || buflist_getfile(qf_ptr->qf_fnum,
+ (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit) == OK)
+ {
+ /* When not switched to another buffer, still need to set pc mark */
+ if (curbuf == old_curbuf)
+ setpcmark();
+
+ /*
+ * Go to line with error, unless qf_lnum is 0.
+ */
+ i = qf_ptr->qf_lnum;
+ if (i > 0)
+ {
+ if (i > curbuf->b_ml.ml_line_count)
+ i = curbuf->b_ml.ml_line_count;
+ curwin->w_cursor.lnum = i;
+ }
+ if (qf_ptr->qf_col > 0)
+ {
+ curwin->w_cursor.col = qf_ptr->qf_col - 1;
+ if (qf_ptr->qf_virt_col == TRUE)
+ {
+ /*
+ * Check each character from the beginning of the error
+ * line up to the error column. For each tab character
+ * found, reduce the error column value by the length of
+ * a tab character.
+ */
+ line = ml_get_curline();
+ screen_col = 0;
+ for (char_col = 0; char_col < curwin->w_cursor.col; ++char_col)
+ {
+ if (*line == NUL)
+ break;
+ if (*line++ == '\t')
+ {
+ curwin->w_cursor.col -= 7 - (screen_col % 8);
+ screen_col += 8 - (screen_col % 8);
+ }
+ else
+ ++screen_col;
+ }
+ }
+ check_cursor();
+ }
+ else
+ beginline(BL_WHITE | BL_FIX);
+
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_QUICKFIX) && old_KeyTyped)
+ foldOpenCursor();
+#endif
+ if (print_message)
+ {
+ /* Update the screen before showing the message */
+ update_topline_redraw();
+ sprintf((char *)IObuff, _("(%d of %d)%s%s: "), qf_index,
+ qf_lists[qf_curlist].qf_count,
+ qf_ptr->qf_cleared ? _(" (line deleted)") : "",
+ (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr));
+ /* Add the message, skipping leading whitespace and newlines. */
+ len = (int)STRLEN(IObuff);
+ qf_fmt_text(skipwhite(qf_ptr->qf_text), IObuff + len, IOSIZE - len);
+
+ /* Output the message. Overwrite to avoid scrolling when the 'O'
+ * flag is present in 'shortmess'; But when not jumping, print the
+ * whole message. */
+ i = msg_scroll;
+ if (curbuf == old_curbuf && curwin->w_cursor.lnum == old_lnum)
+ msg_scroll = TRUE;
+ else if (!msg_scrolled && shortmess(SHM_OVERALL))
+ msg_scroll = FALSE;
+ msg_attr_keep(IObuff, 0, TRUE);
+ msg_scroll = i;
+ }
+ }
+ else
+ {
+#ifdef FEAT_WINDOWS
+ if (opened_window)
+ win_close(curwin, TRUE); /* Close opened window */
+#endif
+ if (qf_ptr->qf_fnum != 0)
+ {
+ /*
+ * Couldn't open file, so put index back where it was. This could
+ * happen if the file was readonly and we changed something.
+ */
+#ifdef FEAT_WINDOWS
+failed:
+#endif
+ qf_ptr = old_qf_ptr;
+ qf_index = old_qf_index;
+ }
+ }
+theend:
+ qf_lists[qf_curlist].qf_ptr = qf_ptr;
+ qf_lists[qf_curlist].qf_index = qf_index;
+#ifdef FEAT_WINDOWS
+ if (p_swb != old_swb && opened_window)
+ {
+ /* Restore old 'switchbuf' value, but not when an autocommand or
+ * modeline has changed the value. */
+ if (p_swb == empty_option)
+ p_swb = old_swb;
+ else
+ free_string_option(old_swb);
+ }
+#endif
+}
+
+/*
+ * ":clist": list all errors
+ */
+ void
+qf_list(eap)
+ exarg_T *eap;
+{
+ buf_T *buf;
+ char_u *fname;
+ struct qf_line *qfp;
+ int i;
+ int idx1 = 1;
+ int idx2 = -1;
+ int need_return = TRUE;
+ int last_printed = 1;
+ char_u *arg = eap->arg;
+ int all = eap->forceit; /* if not :cl!, only show
+ recognised errors */
+
+ if (qf_curlist >= qf_listcount || qf_lists[qf_curlist].qf_count == 0)
+ {
+ EMSG(_(e_quickfix));
+ return;
+ }
+ if (!get_list_range(&arg, &idx1, &idx2) || *arg != NUL)
+ {
+ EMSG(_(e_trailing));
+ return;
+ }
+ i = qf_lists[qf_curlist].qf_count;
+ if (idx1 < 0)
+ idx1 = (-idx1 > i) ? 0 : idx1 + i + 1;
+ if (idx2 < 0)
+ idx2 = (-idx2 > i) ? 0 : idx2 + i + 1;
+
+ more_back_used = TRUE;
+ if (qf_lists[qf_curlist].qf_nonevalid)
+ all = TRUE;
+ qfp = qf_lists[qf_curlist].qf_start;
+ for (i = 1; !got_int && i <= qf_lists[qf_curlist].qf_count; )
+ {
+ if ((qfp->qf_valid || all) && idx1 <= i && i <= idx2)
+ {
+ if (need_return)
+ {
+ msg_putchar('\n');
+ need_return = FALSE;
+ }
+ if (more_back == 0)
+ {
+ fname = NULL;
+ if (qfp->qf_fnum != 0
+ && (buf = buflist_findnr(qfp->qf_fnum)) != NULL)
+ {
+ fname = buf->b_fname;
+ if (qfp->qf_type == 1) /* :helpgrep */
+ fname = gettail(fname);
+ }
+ if (fname == NULL)
+ sprintf((char *)IObuff, "%2d", i);
+ else
+ sprintf((char *)IObuff, "%2d %s", i, (char *)fname);
+ msg_outtrans_attr(IObuff, i == qf_lists[qf_curlist].qf_index
+ ? hl_attr(HLF_L) : hl_attr(HLF_D));
+ if (qfp->qf_lnum == 0)
+ IObuff[0] = NUL;
+ else if (qfp->qf_col == 0)
+ sprintf((char *)IObuff, ":%ld", qfp->qf_lnum);
+ else
+ sprintf((char *)IObuff, ":%ld col %d",
+ qfp->qf_lnum, qfp->qf_col);
+ sprintf((char *)IObuff + STRLEN(IObuff), "%s: ",
+ (char *)qf_types(qfp->qf_type, qfp->qf_nr));
+ msg_puts_attr(IObuff, hl_attr(HLF_N));
+ /* Remove newlines and leading whitespace from the text.
+ * For an unrecognized line keep the indent, the compiler may
+ * mark a word with ^^^^. */
+ qf_fmt_text((fname != NULL || qfp->qf_lnum != 0)
+ ? skipwhite(qfp->qf_text) : qfp->qf_text,
+ IObuff, IOSIZE);
+ msg_prt_line(IObuff);
+ out_flush(); /* show one line at a time */
+ need_return = TRUE;
+ last_printed = i;
+ }
+ }
+ if (more_back)
+ {
+ /* scrolling backwards from the more-prompt */
+ /* TODO: compute the number of items from the screen lines */
+ more_back = more_back * 2 - 1;
+ while (i > last_printed - more_back && i > idx1)
+ {
+ do
+ {
+ qfp = qfp->qf_prev;
+ --i;
+ }
+ while (i > idx1 && !qfp->qf_valid && !all);
+ }
+ more_back = 0;
+ }
+ else
+ {
+ qfp = qfp->qf_next;
+ ++i;
+ }
+ ui_breakcheck();
+ }
+ more_back_used = FALSE;
+}
+
+/*
+ * Remove newlines and leading whitespace from an error message.
+ * Put the result in "buf[bufsize]".
+ */
+ static void
+qf_fmt_text(text, buf, bufsize)
+ char_u *text;
+ char_u *buf;
+ int bufsize;
+{
+ int i;
+ char_u *p = text;
+
+ for (i = 0; *p != NUL && i < bufsize - 1; ++i)
+ {
+ if (*p == '\n')
+ {
+ buf[i] = ' ';
+ while (*++p != NUL)
+ if (!vim_iswhite(*p) && *p != '\n')
+ break;
+ }
+ else
+ buf[i] = *p++;
+ }
+ buf[i] = NUL;
+}
+
+/*
+ * ":colder [count]": Up in the quickfix stack.
+ * ":cnewer [count]": Down in the quickfix stack.
+ */
+ void
+qf_age(eap)
+ exarg_T *eap;
+{
+ int count;
+
+ if (eap->addr_count != 0)
+ count = eap->line2;
+ else
+ count = 1;
+ while (count--)
+ {
+ if (eap->cmdidx == CMD_colder)
+ {
+ if (qf_curlist == 0)
+ {
+ EMSG(_("E380: At bottom of quickfix stack"));
+ return;
+ }
+ --qf_curlist;
+ }
+ else
+ {
+ if (qf_curlist >= qf_listcount - 1)
+ {
+ EMSG(_("E381: At top of quickfix stack"));
+ return;
+ }
+ ++qf_curlist;
+ }
+ }
+ qf_msg();
+}
+
+ static void
+qf_msg()
+{
+ smsg((char_u *)_("error list %d of %d; %d errors"),
+ qf_curlist + 1, qf_listcount, qf_lists[qf_curlist].qf_count);
+#ifdef FEAT_WINDOWS
+ qf_update_buffer();
+#endif
+}
+
+/*
+ * free the error list
+ */
+ static void
+qf_free(idx)
+ int idx;
+{
+ struct qf_line *qfp;
+
+ while (qf_lists[idx].qf_count)
+ {
+ qfp = qf_lists[idx].qf_start->qf_next;
+ vim_free(qf_lists[idx].qf_start->qf_text);
+ vim_free(qf_lists[idx].qf_start);
+ qf_lists[idx].qf_start = qfp;
+ --qf_lists[idx].qf_count;
+ }
+}
+
+/*
+ * qf_mark_adjust: adjust marks
+ */
+ void
+qf_mark_adjust(line1, line2, amount, amount_after)
+ linenr_T line1;
+ linenr_T line2;
+ long amount;
+ long amount_after;
+{
+ int i;
+ struct qf_line *qfp;
+ int idx;
+
+ for (idx = 0; idx < qf_listcount; ++idx)
+ if (qf_lists[idx].qf_count)
+ for (i = 0, qfp = qf_lists[idx].qf_start;
+ i < qf_lists[idx].qf_count; ++i, qfp = qfp->qf_next)
+ if (qfp->qf_fnum == curbuf->b_fnum)
+ {
+ if (qfp->qf_lnum >= line1 && qfp->qf_lnum <= line2)
+ {
+ if (amount == MAXLNUM)
+ qfp->qf_cleared = TRUE;
+ else
+ qfp->qf_lnum += amount;
+ }
+ else if (amount_after && qfp->qf_lnum > line2)
+ qfp->qf_lnum += amount_after;
+ }
+}
+
+/*
+ * Make a nice message out of the error character and the error number:
+ * char number message
+ * e or E 0 " error"
+ * w or W 0 " warning"
+ * i or I 0 " info"
+ * 0 0 ""
+ * other 0 " c"
+ * e or E n " error n"
+ * w or W n " warning n"
+ * i or I n " info n"
+ * 0 n " error n"
+ * other n " c n"
+ * 1 x "" :helpgrep
+ */
+ static char_u *
+qf_types(c, nr)
+ int c, nr;
+{
+ static char_u buf[20];
+ static char_u cc[3];
+ char_u *p;
+
+ if (c == 'W' || c == 'w')
+ p = (char_u *)" warning";
+ else if (c == 'I' || c == 'i')
+ p = (char_u *)" info";
+ else if (c == 'E' || c == 'e' || (c == 0 && nr > 0))
+ p = (char_u *)" error";
+ else if (c == 0 || c == 1)
+ p = (char_u *)"";
+ else
+ {
+ cc[0] = ' ';
+ cc[1] = c;
+ cc[2] = NUL;
+ p = cc;
+ }
+
+ if (nr <= 0)
+ return p;
+
+ sprintf((char *)buf, "%s %3d", (char *)p, nr);
+ return buf;
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * ":cwindow": open the quickfix window if we have errors to display,
+ * close it if not.
+ */
+ void
+ex_cwindow(eap)
+ exarg_T *eap;
+{
+ win_T *win;
+
+ /*
+ * Look for an existing quickfix window.
+ */
+ for (win = firstwin; win != NULL; win = win->w_next)
+ if (bt_quickfix(win->w_buffer))
+ break;
+
+ /*
+ * If a quickfix window is open but we have no errors to display,
+ * close the window. If a quickfix window is not open, then open
+ * it if we have errors; otherwise, leave it closed.
+ */
+ if (qf_lists[qf_curlist].qf_nonevalid || qf_curlist >= qf_listcount)
+ {
+ if (win != NULL)
+ ex_cclose(eap);
+ }
+ else if (win == NULL)
+ ex_copen(eap);
+}
+
+/*
+ * ":cclose": close the window showing the list of errors.
+ */
+/*ARGSUSED*/
+ void
+ex_cclose(eap)
+ exarg_T *eap;
+{
+ win_T *win;
+
+ /*
+ * Find existing quickfix window and close it.
+ */
+ for (win = firstwin; win != NULL; win = win->w_next)
+ if (bt_quickfix(win->w_buffer))
+ break;
+
+ if (win != NULL)
+ win_close(win, FALSE);
+}
+
+/*
+ * ":copen": open a window that shows the list of errors.
+ */
+ void
+ex_copen(eap)
+ exarg_T *eap;
+{
+ int height;
+ buf_T *buf;
+ win_T *win;
+
+ if (eap->addr_count != 0)
+ height = eap->line2;
+ else
+ height = QF_WINHEIGHT;
+
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+
+ /*
+ * Find existing quickfix window, or open a new one.
+ */
+ for (win = firstwin; win != NULL; win = win->w_next)
+ if (bt_quickfix(win->w_buffer))
+ break;
+ if (win != NULL)
+ win_goto(win);
+ else
+ {
+ /* The current window becomes the previous window afterwards. */
+ win = curwin;
+
+ /* Create the new window at the very bottom. */
+ win_goto(lastwin);
+ if (win_split(height, WSP_BELOW) == FAIL)
+ return; /* not enough room for window */
+#ifdef FEAT_SCROLLBIND
+ curwin->w_p_scb = FALSE;
+#endif
+
+ /*
+ * Find existing quickfix buffer, or create a new one.
+ */
+ buf = qf_find_buf();
+ if (buf == NULL)
+ {
+ (void)do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE);
+ /* switch off 'swapfile' */
+ set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
+ set_option_value((char_u *)"bt", 0L, (char_u *)"quickfix",
+ OPT_LOCAL);
+ set_option_value((char_u *)"bh", 0L, (char_u *)"delete", OPT_LOCAL);
+ set_option_value((char_u *)"diff", 0L, (char_u *)"", OPT_LOCAL);
+ }
+ else if (buf != curbuf)
+ set_curbuf(buf, DOBUF_GOTO);
+
+ /* Only set the height when there is no window to the side. */
+ if (curwin->w_width == Columns)
+ win_setheight(height);
+ curwin->w_p_wfh = TRUE; /* set 'winfixheight' */
+ if (win_valid(win))
+ prevwin = win;
+ }
+
+ /*
+ * Fill the buffer with the quickfix list.
+ */
+ qf_fill_buffer();
+
+ curwin->w_cursor.lnum = qf_lists[qf_curlist].qf_index;
+ curwin->w_cursor.col = 0;
+ check_cursor();
+ update_topline(); /* scroll to show the line */
+}
+
+/*
+ * Return the number of the current entry (line number in the quickfix
+ * window).
+ */
+ linenr_T
+qf_current_entry()
+{
+ return qf_lists[qf_curlist].qf_index;
+}
+
+/*
+ * Update the cursor position in the quickfix window to the current error.
+ * Return TRUE if there is a quickfix window.
+ */
+ static int
+qf_win_pos_update(old_qf_index)
+ int old_qf_index; /* previous qf_index or zero */
+{
+ win_T *win;
+ int qf_index = qf_lists[qf_curlist].qf_index;
+
+ /*
+ * Put the cursor on the current error in the quickfix window, so that
+ * it's viewable.
+ */
+ for (win = firstwin; win != NULL; win = win->w_next)
+ if (bt_quickfix(win->w_buffer))
+ break;
+ if (win != NULL
+ && qf_index <= win->w_buffer->b_ml.ml_line_count
+ && old_qf_index != qf_index)
+ {
+ win_T *old_curwin = curwin;
+
+ curwin = win;
+ curbuf = win->w_buffer;
+ if (qf_index > old_qf_index)
+ {
+ curwin->w_redraw_top = old_qf_index;
+ curwin->w_redraw_bot = qf_index;
+ }
+ else
+ {
+ curwin->w_redraw_top = qf_index;
+ curwin->w_redraw_bot = old_qf_index;
+ }
+ curwin->w_cursor.lnum = qf_index;
+ curwin->w_cursor.col = 0;
+ update_topline(); /* scroll to show the line */
+ redraw_later(VALID);
+ curwin->w_redr_status = TRUE; /* update ruler */
+ curwin = old_curwin;
+ curbuf = curwin->w_buffer;
+ }
+ return win != NULL;
+}
+
+/*
+ * Find quickfix buffer.
+ */
+ static buf_T *
+qf_find_buf()
+{
+ buf_T *buf;
+
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ if (bt_quickfix(buf))
+ break;
+ return buf;
+}
+
+/*
+ * Find the quickfix buffer. If it exists, update the contents.
+ */
+ static void
+qf_update_buffer()
+{
+ buf_T *buf;
+#ifdef FEAT_AUTOCMD
+ aco_save_T aco;
+#else
+ buf_T *save_curbuf;
+#endif
+
+ /* Check if a buffer for the quickfix list exists. Update it. */
+ buf = qf_find_buf();
+ if (buf != NULL)
+ {
+#ifdef FEAT_AUTOCMD
+ /* set curwin/curbuf to buf and save a few things */
+ aucmd_prepbuf(&aco, buf);
+#else
+ save_curbuf = curbuf;
+ curbuf = buf;
+#endif
+
+ qf_fill_buffer();
+
+#ifdef FEAT_AUTOCMD
+ /* restore curwin/curbuf and a few other things */
+ aucmd_restbuf(&aco);
+#else
+ curbuf = save_curbuf;
+#endif
+
+ (void)qf_win_pos_update(0);
+ }
+}
+
+/*
+ * Fill current buffer with quickfix errors, replacing any previous contents.
+ * curbuf must be the quickfix buffer!
+ */
+ static void
+qf_fill_buffer()
+{
+ linenr_T lnum;
+ struct qf_line *qfp;
+ buf_T *errbuf;
+ int len;
+ int old_KeyTyped = KeyTyped;
+
+ /* delete all existing lines */
+ while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0)
+ (void)ml_delete((linenr_T)1, FALSE);
+
+ /* Check if there is anything to display */
+ if (qf_curlist < qf_listcount)
+ {
+ /* Add one line for each error */
+ qfp = qf_lists[qf_curlist].qf_start;
+ for (lnum = 0; lnum < qf_lists[qf_curlist].qf_count; ++lnum)
+ {
+ if (qfp->qf_fnum != 0
+ && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL
+ && errbuf->b_fname != NULL)
+ {
+ if (qfp->qf_type == 1) /* :helpgrep */
+ STRCPY(IObuff, gettail(errbuf->b_fname));
+ else
+ STRCPY(IObuff, errbuf->b_fname);
+ len = (int)STRLEN(IObuff);
+ }
+ else
+ len = 0;
+ IObuff[len++] = '|';
+
+ if (qfp->qf_lnum > 0)
+ {
+ sprintf((char *)IObuff + len, "%ld", qfp->qf_lnum);
+ len += (int)STRLEN(IObuff + len);
+
+ if (qfp->qf_col > 0)
+ {
+ sprintf((char *)IObuff + len, " col %d", qfp->qf_col);
+ len += (int)STRLEN(IObuff + len);
+ }
+
+ sprintf((char *)IObuff + len, "%s",
+ (char *)qf_types(qfp->qf_type, qfp->qf_nr));
+ len += (int)STRLEN(IObuff + len);
+ }
+ IObuff[len++] = '|';
+ IObuff[len++] = ' ';
+
+ /* Remove newlines and leading whitespace from the text.
+ * For an unrecognized line keep the indent, the compiler may
+ * mark a word with ^^^^. */
+ qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text,
+ IObuff + len, IOSIZE - len);
+
+ if (ml_append(lnum, IObuff, (colnr_T)STRLEN(IObuff) + 1, FALSE)
+ == FAIL)
+ break;
+ qfp = qfp->qf_next;
+ }
+ /* Delete the empty line which is now at the end */
+ (void)ml_delete(lnum + 1, FALSE);
+ }
+
+ /* correct cursor position */
+ check_lnums(TRUE);
+
+ /* Set the 'filetype' to "qf" each time after filling the buffer. This
+ * resembles reading a file into a buffer, it's more logical when using
+ * autocommands. */
+ set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL);
+ curbuf->b_p_ma = FALSE;
+
+#ifdef FEAT_AUTOCMD
+ apply_autocmds(EVENT_BUFREADPOST, (char_u *)"quickfix", NULL,
+ FALSE, curbuf);
+ apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL,
+ FALSE, curbuf);
+#endif
+
+ /* make sure it will be redrawn */
+ redraw_curbuf_later(NOT_VALID);
+
+ /* Restore KeyTyped, setting 'filetype' may reset it. */
+ KeyTyped = old_KeyTyped;
+}
+
+#endif /* FEAT_WINDOWS */
+
+/*
+ * Return TRUE if "buf" is the quickfix buffer.
+ */
+ int
+bt_quickfix(buf)
+ buf_T *buf;
+{
+ return (buf->b_p_bt[0] == 'q');
+}
+
+/*
+ * Return TRUE if "buf" is a "nofile" buffer.
+ */
+ int
+bt_nofile(buf)
+ buf_T *buf;
+{
+ return (buf->b_p_bt[0] == 'n' && buf->b_p_bt[2] == 'f');
+}
+
+/*
+ * Return TRUE if "buf" is a "nowrite" or "nofile" buffer.
+ */
+ int
+bt_dontwrite(buf)
+ buf_T *buf;
+{
+ return (buf->b_p_bt[0] == 'n');
+}
+
+ int
+bt_dontwrite_msg(buf)
+ buf_T *buf;
+{
+ if (bt_dontwrite(buf))
+ {
+ EMSG(_("E382: Cannot write, 'buftype' option is set"));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Return TRUE if the buffer should be hidden, according to 'hidden', ":hide"
+ * and 'bufhidden'.
+ */
+ int
+buf_hide(buf)
+ buf_T *buf;
+{
+ /* 'bufhidden' overrules 'hidden' and ":hide", check it first */
+ switch (buf->b_p_bh[0])
+ {
+ case 'u': /* "unload" */
+ case 'w': /* "wipe" */
+ case 'd': return FALSE; /* "delete" */
+ case 'h': return TRUE; /* "hide" */
+ }
+ return (p_hid || cmdmod.hide);
+}
+
+/*
+ * Used for ":make", ":grep" and ":grepadd".
+ */
+ void
+ex_make(eap)
+ exarg_T *eap;
+{
+ char_u *name;
+ char_u *cmd;
+ unsigned len;
+
+ autowrite_all();
+ name = get_mef_name();
+ if (name == NULL)
+ return;
+ mch_remove(name); /* in case it's not unique */
+
+ /*
+ * If 'shellpipe' empty: don't redirect to 'errorfile'.
+ */
+ len = (unsigned)STRLEN(p_shq) * 2 + (unsigned)STRLEN(eap->arg) + 1;
+ if (*p_sp != NUL)
+ len += (unsigned)STRLEN(p_sp) + (unsigned)STRLEN(name) + 3;
+ cmd = alloc(len);
+ if (cmd == NULL)
+ return;
+ sprintf((char *)cmd, "%s%s%s", (char *)p_shq, (char *)eap->arg,
+ (char *)p_shq);
+ if (*p_sp != NUL)
+ append_redir(cmd, p_sp, name);
+ /*
+ * Output a newline if there's something else than the :make command that
+ * was typed (in which case the cursor is in column 0).
+ */
+ if (msg_col == 0)
+ msg_didout = FALSE;
+ msg_start();
+ MSG_PUTS(":!");
+ msg_outtrans(cmd); /* show what we are doing */
+
+ /* let the shell know if we are redirecting output or not */
+ do_shell(cmd, *p_sp != NUL ? SHELL_DOOUT : 0);
+
+#ifdef AMIGA
+ out_flush();
+ /* read window status report and redraw before message */
+ (void)char_avail();
+#endif
+
+ if (qf_init(name, eap->cmdidx != CMD_make ? p_gefm : p_efm,
+ eap->cmdidx != CMD_grepadd) > 0
+ && !eap->forceit)
+ qf_jump(0, 0, FALSE); /* display first error */
+
+ mch_remove(name);
+ vim_free(name);
+ vim_free(cmd);
+}
+
+/*
+ * Return the name for the errorfile, in allocated memory.
+ * Find a new unique name when 'makeef' contains "##".
+ * Returns NULL for error.
+ */
+ static char_u *
+get_mef_name()
+{
+ char_u *p;
+ char_u *name;
+ static int start = -1;
+ static int off = 0;
+#ifdef HAVE_LSTAT
+ struct stat sb;
+#endif
+
+ if (*p_mef == NUL)
+ {
+ name = vim_tempname('e');
+ if (name == NULL)
+ EMSG(_(e_notmp));
+ return name;
+ }
+
+ for (p = p_mef; *p; ++p)
+ if (p[0] == '#' && p[1] == '#')
+ break;
+
+ if (*p == NUL)
+ return vim_strsave(p_mef);
+
+ /* Keep trying until the name doesn't exist yet. */
+ for (;;)
+ {
+ if (start == -1)
+ start = mch_get_pid();
+ else
+ off += 19;
+
+ name = alloc((unsigned)STRLEN(p_mef) + 30);
+ if (name == NULL)
+ break;
+ STRCPY(name, p_mef);
+ sprintf((char *)name + (p - p_mef), "%d%d", start, off);
+ STRCAT(name, p + 2);
+ if (mch_getperm(name) < 0
+#ifdef HAVE_LSTAT
+ /* Don't accept a symbolic link, its a security risk. */
+ && mch_lstat((char *)name, &sb) < 0
+#endif
+ )
+ break;
+ vim_free(name);
+ }
+ return name;
+}
+
+/*
+ * ":cc", ":crewind", ":cfirst" and ":clast".
+ */
+ void
+ex_cc(eap)
+ exarg_T *eap;
+{
+ qf_jump(0,
+ eap->addr_count > 0
+ ? (int)eap->line2
+ : eap->cmdidx == CMD_cc
+ ? 0
+ : (eap->cmdidx == CMD_crewind || eap->cmdidx == CMD_cfirst)
+ ? 1
+ : 32767,
+ eap->forceit);
+}
+
+/*
+ * ":cnext", ":cnfile", ":cNext" and ":cprevious".
+ */
+ void
+ex_cnext(eap)
+ exarg_T *eap;
+{
+ qf_jump(eap->cmdidx == CMD_cnext
+ ? FORWARD
+ : eap->cmdidx == CMD_cnfile
+ ? FORWARD_FILE
+ : (eap->cmdidx == CMD_cpfile || eap->cmdidx == CMD_cNfile)
+ ? BACKWARD_FILE
+ : BACKWARD,
+ eap->addr_count > 0 ? (int)eap->line2 : 1, eap->forceit);
+}
+
+/*
+ * ":cfile" command.
+ */
+ void
+ex_cfile(eap)
+ exarg_T *eap;
+{
+ if (*eap->arg != NUL)
+ set_string_option_direct((char_u *)"ef", -1, eap->arg, OPT_FREE);
+ if (qf_init(p_ef, p_efm, TRUE) > 0 && eap->cmdidx == CMD_cfile)
+ qf_jump(0, 0, eap->forceit); /* display first error */
+}
+
+/*
+ * ":helpgrep {pattern}"
+ */
+ void
+ex_helpgrep(eap)
+ exarg_T *eap;
+{
+ regmatch_T regmatch;
+ char_u *save_cpo;
+ char_u *p;
+ int fcount;
+ char_u **fnames;
+ FILE *fd;
+ int fi;
+ struct qf_line *prevp = NULL;
+ long lnum;
+
+ /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
+ save_cpo = p_cpo;
+ p_cpo = (char_u *)"";
+
+ regmatch.regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING);
+ regmatch.rm_ic = FALSE;
+ if (regmatch.regprog != NULL)
+ {
+ /* create a new quickfix list */
+ qf_new_list();
+
+ /* Go through all directories in 'runtimepath' */
+ p = p_rtp;
+ while (*p != NUL && !got_int)
+ {
+ copy_option_part(&p, NameBuff, MAXPATHL, ",");
+
+ /* Find all "*.txt" and "*.??x" files in the "doc" directory. */
+ add_pathsep(NameBuff);
+ STRCAT(NameBuff, "doc/*.\\(txt\\|??x\\)");
+ if (gen_expand_wildcards(1, &NameBuff, &fcount,
+ &fnames, EW_FILE|EW_SILENT) == OK
+ && fcount > 0)
+ {
+ for (fi = 0; fi < fcount && !got_int; ++fi)
+ {
+ fd = fopen((char *)fnames[fi], "r");
+ if (fd != NULL)
+ {
+ lnum = 1;
+ while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int)
+ {
+ if (vim_regexec(&regmatch, IObuff, (colnr_T)0))
+ {
+ int l = STRLEN(IObuff);
+
+ /* remove trailing CR, LF, spaces, etc. */
+ while (l > 0 && IObuff[l - 1] <= ' ')
+ IObuff[--l] = NUL;
+
+ if (qf_add_entry(&prevp,
+ NULL, /* dir */
+ fnames[fi],
+ IObuff,
+ lnum,
+ 0, /* col */
+ FALSE, /* virt_col */
+ 0, /* nr */
+ 1, /* type */
+ TRUE /* valid */
+ ) == FAIL)
+ {
+ got_int = TRUE;
+ break;
+ }
+ }
+ ++lnum;
+ line_breakcheck();
+ }
+ fclose(fd);
+ }
+ }
+ FreeWild(fcount, fnames);
+ }
+ }
+ vim_free(regmatch.regprog);
+
+ qf_lists[qf_curlist].qf_nonevalid = FALSE;
+ qf_lists[qf_curlist].qf_ptr = qf_lists[qf_curlist].qf_start;
+ qf_lists[qf_curlist].qf_index = 1;
+ }
+
+ p_cpo = save_cpo;
+
+#ifdef FEAT_WINDOWS
+ qf_update_buffer();
+#endif
+
+ /* Jump to first match. */
+ if (qf_lists[qf_curlist].qf_count > 0)
+ qf_jump(0, 0, FALSE);
+}
+
+#endif /* FEAT_QUICKFIX */
diff --git a/src/regexp.c b/src/regexp.c
new file mode 100644
index 000000000..9715a1ea5
--- /dev/null
+++ b/src/regexp.c
@@ -0,0 +1,6115 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * Handling of regular expressions: vim_regcomp(), vim_regexec(), vim_regsub()
+ *
+ * NOTICE:
+ *
+ * This is NOT the original regular expression code as written by Henry
+ * Spencer. This code has been modified specifically for use with the VIM
+ * editor, and should not be used separately from Vim. If you want a good
+ * regular expression library, get the original code. The copyright notice
+ * that follows is from the original.
+ *
+ * END NOTICE
+ *
+ * Copyright (c) 1986 by University of Toronto.
+ * Written by Henry Spencer. Not derived from licensed software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose on any computer system, and to redistribute it freely,
+ * subject to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of
+ * this software, no matter how awful, even if they arise
+ * from defects in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either
+ * by explicit claim or by omission.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * Beware that some of this code is subtly aware of the way operator
+ * precedence is structured in regular expressions. Serious changes in
+ * regular-expression syntax might require a total rethink.
+ *
+ * Changes have been made by Tony Andrews, Olaf 'Rhialto' Seibert, Robert Webb
+ * and Bram Moolenaar.
+ * Named character class support added by Walter Briscoe (1998 Jul 01)
+ */
+
+#include "vim.h"
+
+#undef DEBUG
+
+/*
+ * The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases. They are:
+ *
+ * regstart char that must begin a match; NUL if none obvious; Can be a
+ * multi-byte character.
+ * reganch is the match anchored (at beginning-of-line only)?
+ * regmust string (pointer into program) that match must include, or NULL
+ * regmlen length of regmust string
+ * regflags RF_ values or'ed together
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot. Regmust permits fast rejection
+ * of lines that cannot possibly match. The regmust tests are costly enough
+ * that vim_regcomp() supplies a regmust only if the r.e. contains something
+ * potentially expensive (at present, the only such thing detected is * or +
+ * at the start of the r.e., which can involve a lot of backup). Regmlen is
+ * supplied because the test in vim_regexec() needs it and vim_regcomp() is
+ * computing it anyway.
+ */
+
+/*
+ * Structure for regexp "program". This is essentially a linear encoding
+ * of a nondeterministic finite-state machine (aka syntax charts or
+ * "railroad normal form" in parsing technology). Each node is an opcode
+ * plus a "next" pointer, possibly plus an operand. "Next" pointers of
+ * all nodes except BRANCH and BRACES_COMPLEX implement concatenation; a "next"
+ * pointer with a BRANCH on both ends of it is connecting two alternatives.
+ * (Here we have one of the subtle syntax dependencies: an individual BRANCH
+ * (as opposed to a collection of them) is never concatenated with anything
+ * because of operator precedence). The "next" pointer of a BRACES_COMPLEX
+ * node points to the node after the stuff to be repeated. The operand of some
+ * types of node is a literal string; for others, it is a node leading into a
+ * sub-FSM. In particular, the operand of a BRANCH node is the first node of
+ * the branch. (NB this is *not* a tree structure: the tail of the branch
+ * connects to the thing following the set of BRANCHes.)
+ *
+ * pattern is coded like:
+ *
+ * +-----------------+
+ * | V
+ * <aa>\|<bb> BRANCH <aa> BRANCH <bb> --> END
+ * | ^ | ^
+ * +------+ +----------+
+ *
+ *
+ * +------------------+
+ * V |
+ * <aa>* BRANCH BRANCH <aa> --> BACK BRANCH --> NOTHING --> END
+ * | | ^ ^
+ * | +---------------+ |
+ * +---------------------------------------------+
+ *
+ *
+ * +-------------------------+
+ * V |
+ * <aa>\{} BRANCH BRACE_LIMITS --> BRACE_COMPLEX <aa> --> BACK END
+ * | | ^
+ * | +----------------+
+ * +-----------------------------------------------+
+ *
+ *
+ * <aa>\@!<bb> BRANCH NOMATCH <aa> --> END <bb> --> END
+ * | | ^ ^
+ * | +----------------+ |
+ * +--------------------------------+
+ *
+ * +---------+
+ * | V
+ * \z[abc] BRANCH BRANCH a BRANCH b BRANCH c BRANCH NOTHING --> END
+ * | | | | ^ ^
+ * | | | +-----+ |
+ * | | +----------------+ |
+ * | +---------------------------+ |
+ * +------------------------------------------------------+
+ *
+ * They all start with a BRANCH for "\|" alternaties, even when there is only
+ * one alternative.
+ */
+
+/*
+ * The opcodes are:
+ */
+
+/* definition number opnd? meaning */
+#define END 0 /* End of program or NOMATCH operand. */
+#define BOL 1 /* Match "" at beginning of line. */
+#define EOL 2 /* Match "" at end of line. */
+#define BRANCH 3 /* node Match this alternative, or the
+ * next... */
+#define BACK 4 /* Match "", "next" ptr points backward. */
+#define EXACTLY 5 /* str Match this string. */
+#define NOTHING 6 /* Match empty string. */
+#define STAR 7 /* node Match this (simple) thing 0 or more
+ * times. */
+#define PLUS 8 /* node Match this (simple) thing 1 or more
+ * times. */
+#define MATCH 9 /* node match the operand zero-width */
+#define NOMATCH 10 /* node check for no match with operand */
+#define BEHIND 11 /* node look behind for a match with operand */
+#define NOBEHIND 12 /* node look behind for no match with operand */
+#define SUBPAT 13 /* node match the operand here */
+#define BRACE_SIMPLE 14 /* node Match this (simple) thing between m and
+ * n times (\{m,n\}). */
+#define BOW 15 /* Match "" after [^a-zA-Z0-9_] */
+#define EOW 16 /* Match "" at [^a-zA-Z0-9_] */
+#define BRACE_LIMITS 17 /* nr nr define the min & max for BRACE_SIMPLE
+ * and BRACE_COMPLEX. */
+#define NEWL 18 /* Match line-break */
+#define BHPOS 19 /* End position for BEHIND or NOBEHIND */
+
+
+/* character classes: 20-48 normal, 50-78 include a line-break */
+#define ADD_NL 30
+#define FIRST_NL ANY + ADD_NL
+#define ANY 20 /* Match any one character. */
+#define ANYOF 21 /* str Match any character in this string. */
+#define ANYBUT 22 /* str Match any character not in this
+ * string. */
+#define IDENT 23 /* Match identifier char */
+#define SIDENT 24 /* Match identifier char but no digit */
+#define KWORD 25 /* Match keyword char */
+#define SKWORD 26 /* Match word char but no digit */
+#define FNAME 27 /* Match file name char */
+#define SFNAME 28 /* Match file name char but no digit */
+#define PRINT 29 /* Match printable char */
+#define SPRINT 30 /* Match printable char but no digit */
+#define WHITE 31 /* Match whitespace char */
+#define NWHITE 32 /* Match non-whitespace char */
+#define DIGIT 33 /* Match digit char */
+#define NDIGIT 34 /* Match non-digit char */
+#define HEX 35 /* Match hex char */
+#define NHEX 36 /* Match non-hex char */
+#define OCTAL 37 /* Match octal char */
+#define NOCTAL 38 /* Match non-octal char */
+#define WORD 39 /* Match word char */
+#define NWORD 40 /* Match non-word char */
+#define HEAD 41 /* Match head char */
+#define NHEAD 42 /* Match non-head char */
+#define ALPHA 43 /* Match alpha char */
+#define NALPHA 44 /* Match non-alpha char */
+#define LOWER 45 /* Match lowercase char */
+#define NLOWER 46 /* Match non-lowercase char */
+#define UPPER 47 /* Match uppercase char */
+#define NUPPER 48 /* Match non-uppercase char */
+#define LAST_NL NUPPER + ADD_NL
+#define WITH_NL(op) ((op) >= FIRST_NL && (op) <= LAST_NL)
+
+#define MOPEN 80 /* -89 Mark this point in input as start of
+ * \( subexpr. MOPEN + 0 marks start of
+ * match. */
+#define MCLOSE 90 /* -99 Analogous to MOPEN. MCLOSE + 0 marks
+ * end of match. */
+#define BACKREF 100 /* -109 node Match same string again \1-\9 */
+
+#ifdef FEAT_SYN_HL
+# define ZOPEN 110 /* -119 Mark this point in input as start of
+ * \z( subexpr. */
+# define ZCLOSE 120 /* -129 Analogous to ZOPEN. */
+# define ZREF 130 /* -139 node Match external submatch \z1-\z9 */
+#endif
+
+#define BRACE_COMPLEX 140 /* -149 node Match nodes between m & n times */
+
+#define NOPEN 150 /* Mark this point in input as start of
+ \%( subexpr. */
+#define NCLOSE 151 /* Analogous to NOPEN. */
+
+#define MULTIBYTECODE 200 /* mbc Match one multi-byte character */
+#define RE_BOF 201 /* Match "" at beginning of file. */
+#define RE_EOF 202 /* Match "" at end of file. */
+#define CURSOR 203 /* Match location of cursor. */
+
+#define RE_LNUM 204 /* nr cmp Match line number */
+#define RE_COL 205 /* nr cmp Match column number */
+#define RE_VCOL 206 /* nr cmp Match virtual column number */
+
+/*
+ * Magic characters have a special meaning, they don't match literally.
+ * Magic characters are negative. This separates them from literal characters
+ * (possibly multi-byte). Only ASCII characters can be Magic.
+ */
+#define Magic(x) ((int)(x) - 256)
+#define un_Magic(x) ((x) + 256)
+#define is_Magic(x) ((x) < 0)
+
+static int no_Magic __ARGS((int x));
+static int toggle_Magic __ARGS((int x));
+
+ static int
+no_Magic(x)
+ int x;
+{
+ if (is_Magic(x))
+ return un_Magic(x);
+ return x;
+}
+
+ static int
+toggle_Magic(x)
+ int x;
+{
+ if (is_Magic(x))
+ return un_Magic(x);
+ return Magic(x);
+}
+
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte. It's used to catch the
+ * most severe mutilation of the program by the caller.
+ */
+
+#define REGMAGIC 0234
+
+/*
+ * Opcode notes:
+ *
+ * BRANCH The set of branches constituting a single choice are hooked
+ * together with their "next" pointers, since precedence prevents
+ * anything being concatenated to any individual branch. The
+ * "next" pointer of the last BRANCH in a choice points to the
+ * thing following the whole choice. This is also where the
+ * final "next" pointer of each individual branch points; each
+ * branch starts with the operand node of a BRANCH node.
+ *
+ * BACK Normal "next" pointers all implicitly point forward; BACK
+ * exists to make loop structures possible.
+ *
+ * STAR,PLUS '=', and complex '*' and '+', are implemented as circular
+ * BRANCH structures using BACK. Simple cases (one character
+ * per match) are implemented with STAR and PLUS for speed
+ * and to minimize recursive plunges.
+ *
+ * BRACE_LIMITS This is always followed by a BRACE_SIMPLE or BRACE_COMPLEX
+ * node, and defines the min and max limits to be used for that
+ * node.
+ *
+ * MOPEN,MCLOSE ...are numbered at compile time.
+ * ZOPEN,ZCLOSE ...ditto
+ */
+
+/*
+ * A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit bytes, high order first. The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node. (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+#define OP(p) ((int)*(p))
+#define NEXT(p) (((*((p) + 1) & 0377) << 8) + (*((p) + 2) & 0377))
+#define OPERAND(p) ((p) + 3)
+/* Obtain an operand that was stored as four bytes, MSB first. */
+#define OPERAND_MIN(p) (((long)(p)[3] << 24) + ((long)(p)[4] << 16) \
+ + ((long)(p)[5] << 8) + (long)(p)[6])
+/* Obtain a second operand stored as four bytes. */
+#define OPERAND_MAX(p) OPERAND_MIN((p) + 4)
+/* Obtain a second single-byte operand stored after a four bytes operand. */
+#define OPERAND_CMP(p) (p)[7]
+
+/*
+ * Utility definitions.
+ */
+#define UCHARAT(p) ((int)*(char_u *)(p))
+
+/* Used for an error (down from) vim_regcomp(): give the error message, set
+ * rc_did_emsg and return NULL */
+#define EMSG_RET_NULL(m) { EMSG(m); rc_did_emsg = TRUE; return NULL; }
+#define EMSG_M_RET_NULL(m, c) { EMSG2(m, c ? "" : "\\"); rc_did_emsg = TRUE; return NULL; }
+#define EMSG_RET_FAIL(m) { EMSG(m); rc_did_emsg = TRUE; return FAIL; }
+#define EMSG_ONE_RET_NULL EMSG_M_RET_NULL(_("E369: invalid item in %s%%[]"), reg_magic == MAGIC_ALL)
+
+#define MAX_LIMIT (32767L << 16L)
+
+static int re_multi_type __ARGS((int));
+static int cstrncmp __ARGS((char_u *s1, char_u *s2, int *n));
+static char_u *cstrchr __ARGS((char_u *, int));
+
+#ifdef DEBUG
+static void regdump __ARGS((char_u *, regprog_T *));
+static char_u *regprop __ARGS((char_u *));
+#endif
+
+#define NOT_MULTI 0
+#define MULTI_ONE 1
+#define MULTI_MULT 2
+/*
+ * Return NOT_MULTI if c is not a "multi" operator.
+ * Return MULTI_ONE if c is a single "multi" operator.
+ * Return MULTI_MULT if c is a multi "multi" operator.
+ */
+ static int
+re_multi_type(c)
+ int c;
+{
+ if (c == Magic('@') || c == Magic('=') || c == Magic('?'))
+ return MULTI_ONE;
+ if (c == Magic('*') || c == Magic('+') || c == Magic('{'))
+ return MULTI_MULT;
+ return NOT_MULTI;
+}
+
+/*
+ * Flags to be passed up and down.
+ */
+#define HASWIDTH 0x1 /* Known never to match null string. */
+#define SIMPLE 0x2 /* Simple enough to be STAR/PLUS operand. */
+#define SPSTART 0x4 /* Starts with * or +. */
+#define HASNL 0x8 /* Contains some \n. */
+#define HASLOOKBH 0x10 /* Contains "\@<=" or "\@<!". */
+#define WORST 0 /* Worst case. */
+
+/*
+ * When regcode is set to this value, code is not emitted and size is computed
+ * instead.
+ */
+#define JUST_CALC_SIZE ((char_u *) -1)
+
+static char_u *reg_prev_sub;
+
+/*
+ * REGEXP_INRANGE contains all characters which are always special in a []
+ * range after '\'.
+ * REGEXP_ABBR contains all characters which act as abbreviations after '\'.
+ * These are:
+ * \n - New line (NL).
+ * \r - Carriage Return (CR).
+ * \t - Tab (TAB).
+ * \e - Escape (ESC).
+ * \b - Backspace (Ctrl_H).
+ */
+static char_u REGEXP_INRANGE[] = "]^-n\\";
+static char_u REGEXP_ABBR[] = "nrteb";
+
+static int backslash_trans __ARGS((int c));
+static int skip_class_name __ARGS((char_u **pp));
+static char_u *skip_anyof __ARGS((char_u *p));
+static void init_class_tab __ARGS((void));
+
+/*
+ * Translate '\x' to its control character, except "\n", which is Magic.
+ */
+ static int
+backslash_trans(c)
+ int c;
+{
+ switch (c)
+ {
+ case 'r': return CAR;
+ case 't': return TAB;
+ case 'e': return ESC;
+ case 'b': return BS;
+ }
+ return c;
+}
+
+/*
+ * Check for a character class name. "pp" points to the '['.
+ * Returns one of the CLASS_ items. CLASS_NONE means that no item was
+ * recognized. Otherwise "pp" is advanced to after the item.
+ */
+ static int
+skip_class_name(pp)
+ char_u **pp;
+{
+ static const char *(class_names[]) =
+ {
+ "alnum:]",
+#define CLASS_ALNUM 0
+ "alpha:]",
+#define CLASS_ALPHA 1
+ "blank:]",
+#define CLASS_BLANK 2
+ "cntrl:]",
+#define CLASS_CNTRL 3
+ "digit:]",
+#define CLASS_DIGIT 4
+ "graph:]",
+#define CLASS_GRAPH 5
+ "lower:]",
+#define CLASS_LOWER 6
+ "print:]",
+#define CLASS_PRINT 7
+ "punct:]",
+#define CLASS_PUNCT 8
+ "space:]",
+#define CLASS_SPACE 9
+ "upper:]",
+#define CLASS_UPPER 10
+ "xdigit:]",
+#define CLASS_XDIGIT 11
+ "tab:]",
+#define CLASS_TAB 12
+ "return:]",
+#define CLASS_RETURN 13
+ "backspace:]",
+#define CLASS_BACKSPACE 14
+ "escape:]",
+#define CLASS_ESCAPE 15
+ };
+#define CLASS_NONE 99
+ int i;
+
+ if ((*pp)[1] == ':')
+ {
+ for (i = 0; i < sizeof(class_names) / sizeof(*class_names); ++i)
+ if (STRNCMP(*pp + 2, class_names[i], STRLEN(class_names[i])) == 0)
+ {
+ *pp += STRLEN(class_names[i]) + 2;
+ return i;
+ }
+ }
+ return CLASS_NONE;
+}
+
+/*
+ * Skip over a "[]" range.
+ * "p" must point to the character after the '['.
+ * The returned pointer is on the matching ']', or the terminating NUL.
+ */
+ static char_u *
+skip_anyof(p)
+ char_u *p;
+{
+ int cpo_lit; /* 'cpoptions' contains 'l' flag */
+#ifdef FEAT_MBYTE
+ int l;
+#endif
+
+ cpo_lit = (!reg_syn && vim_strchr(p_cpo, CPO_LITERAL) != NULL);
+
+ if (*p == '^') /* Complement of range. */
+ ++p;
+ if (*p == ']' || *p == '-')
+ ++p;
+ while (*p != NUL && *p != ']')
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
+ p += l;
+ else
+#endif
+ if (*p == '-')
+ {
+ ++p;
+ if (*p != ']' && *p != NUL)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p);
+ else
+#endif
+ ++p;
+ }
+ }
+ else if (*p == '\\'
+ && (vim_strchr(REGEXP_INRANGE, p[1]) != NULL
+ || (!cpo_lit && vim_strchr(REGEXP_ABBR, p[1]) != NULL)))
+ p += 2;
+ else if (*p == '[')
+ {
+ if (skip_class_name(&p) == CLASS_NONE)
+ ++p; /* It was not a class name */
+ }
+ else
+ ++p;
+ }
+
+ return p;
+}
+
+/*
+ * Specific version of character class functions.
+ * Using a table to keep this fast.
+ */
+static short class_tab[256];
+
+#define RI_DIGIT 0x01
+#define RI_HEX 0x02
+#define RI_OCTAL 0x04
+#define RI_WORD 0x08
+#define RI_HEAD 0x10
+#define RI_ALPHA 0x20
+#define RI_LOWER 0x40
+#define RI_UPPER 0x80
+#define RI_WHITE 0x100
+
+ static void
+init_class_tab()
+{
+ int i;
+ static int done = FALSE;
+
+ if (done)
+ return;
+
+ for (i = 0; i < 256; ++i)
+ {
+ if (i >= '0' && i <= '7')
+ class_tab[i] = RI_DIGIT + RI_HEX + RI_OCTAL + RI_WORD;
+ else if (i >= '8' && i <= '9')
+ class_tab[i] = RI_DIGIT + RI_HEX + RI_WORD;
+ else if (i >= 'a' && i <= 'f')
+ class_tab[i] = RI_HEX + RI_WORD + RI_HEAD + RI_ALPHA + RI_LOWER;
+#ifdef EBCDIC
+ else if ((i >= 'g' && i <= 'i') || (i >= 'j' && i <= 'r')
+ || (i >= 's' && i <= 'z'))
+#else
+ else if (i >= 'g' && i <= 'z')
+#endif
+ class_tab[i] = RI_WORD + RI_HEAD + RI_ALPHA + RI_LOWER;
+ else if (i >= 'A' && i <= 'F')
+ class_tab[i] = RI_HEX + RI_WORD + RI_HEAD + RI_ALPHA + RI_UPPER;
+#ifdef EBCDIC
+ else if ((i >= 'G' && i <= 'I') || ( i >= 'J' && i <= 'R')
+ || (i >= 'S' && i <= 'Z'))
+#else
+ else if (i >= 'G' && i <= 'Z')
+#endif
+ class_tab[i] = RI_WORD + RI_HEAD + RI_ALPHA + RI_UPPER;
+ else if (i == '_')
+ class_tab[i] = RI_WORD + RI_HEAD;
+ else
+ class_tab[i] = 0;
+ }
+ class_tab[' '] |= RI_WHITE;
+ class_tab['\t'] |= RI_WHITE;
+ done = TRUE;
+}
+
+#ifdef FEAT_MBYTE
+# define ri_digit(c) (c < 0x100 && (class_tab[c] & RI_DIGIT))
+# define ri_hex(c) (c < 0x100 && (class_tab[c] & RI_HEX))
+# define ri_octal(c) (c < 0x100 && (class_tab[c] & RI_OCTAL))
+# define ri_word(c) (c < 0x100 && (class_tab[c] & RI_WORD))
+# define ri_head(c) (c < 0x100 && (class_tab[c] & RI_HEAD))
+# define ri_alpha(c) (c < 0x100 && (class_tab[c] & RI_ALPHA))
+# define ri_lower(c) (c < 0x100 && (class_tab[c] & RI_LOWER))
+# define ri_upper(c) (c < 0x100 && (class_tab[c] & RI_UPPER))
+# define ri_white(c) (c < 0x100 && (class_tab[c] & RI_WHITE))
+#else
+# define ri_digit(c) (class_tab[c] & RI_DIGIT)
+# define ri_hex(c) (class_tab[c] & RI_HEX)
+# define ri_octal(c) (class_tab[c] & RI_OCTAL)
+# define ri_word(c) (class_tab[c] & RI_WORD)
+# define ri_head(c) (class_tab[c] & RI_HEAD)
+# define ri_alpha(c) (class_tab[c] & RI_ALPHA)
+# define ri_lower(c) (class_tab[c] & RI_LOWER)
+# define ri_upper(c) (class_tab[c] & RI_UPPER)
+# define ri_white(c) (class_tab[c] & RI_WHITE)
+#endif
+
+/* flags for regflags */
+#define RF_ICASE 1 /* ignore case */
+#define RF_NOICASE 2 /* don't ignore case */
+#define RF_HASNL 4 /* can match a NL */
+#define RF_ICOMBINE 8 /* ignore combining characters */
+#define RF_LOOKBH 16 /* uses "\@<=" or "\@<!" */
+
+/*
+ * Global work variables for vim_regcomp().
+ */
+
+static char_u *regparse; /* Input-scan pointer. */
+static int prevchr_len; /* byte length of previous char */
+static int num_complex_braces; /* Complex \{...} count */
+static int regnpar; /* () count. */
+#ifdef FEAT_SYN_HL
+static int regnzpar; /* \z() count. */
+static int re_has_z; /* \z item detected */
+#endif
+static char_u *regcode; /* Code-emit pointer, or JUST_CALC_SIZE */
+static long regsize; /* Code size. */
+static char_u had_endbrace[NSUBEXP]; /* flags, TRUE if end of () found */
+static unsigned regflags; /* RF_ flags for prog */
+static long brace_min[10]; /* Minimums for complex brace repeats */
+static long brace_max[10]; /* Maximums for complex brace repeats */
+static int brace_count[10]; /* Current counts for complex brace repeats */
+#if defined(FEAT_SYN_HL) || defined(PROTO)
+static int had_eol; /* TRUE when EOL found by vim_regcomp() */
+#endif
+static int one_exactly = FALSE; /* only do one char for EXACTLY */
+
+static int reg_magic; /* magicness of the pattern: */
+#define MAGIC_NONE 1 /* "\V" very unmagic */
+#define MAGIC_OFF 2 /* "\M" or 'magic' off */
+#define MAGIC_ON 3 /* "\m" or 'magic' */
+#define MAGIC_ALL 4 /* "\v" very magic */
+
+static int reg_string; /* matching with a string instead of a buffer
+ line */
+
+/*
+ * META contains all characters that may be magic, except '^' and '$'.
+ */
+
+#ifdef EBCDIC
+static char_u META[] = "%&()*+.123456789<=>?@ACDFHIKLMOPSUVWX[_acdfhiklmnopsuvwxz{|~";
+#else
+/* META[] is used often enough to justify turning it into a table. */
+static char_u META_flags[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* % & ( ) * + . */
+ 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0,
+/* 1 2 3 4 5 6 7 8 9 < = > ? */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1,
+/* @ A C D F H I K L M O */
+ 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1,
+/* P S U V W X Z [ _ */
+ 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1,
+/* a c d f h i k l m n o */
+ 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
+/* p s u v w x z { | ~ */
+ 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1
+};
+#endif
+
+static int curchr;
+
+/* arguments for reg() */
+#define REG_NOPAREN 0 /* toplevel reg() */
+#define REG_PAREN 1 /* \(\) */
+#define REG_ZPAREN 2 /* \z(\) */
+#define REG_NPAREN 3 /* \%(\) */
+
+/*
+ * Forward declarations for vim_regcomp()'s friends.
+ */
+static void initchr __ARGS((char_u *));
+static int getchr __ARGS((void));
+static void skipchr_keepstart __ARGS((void));
+static int peekchr __ARGS((void));
+static void skipchr __ARGS((void));
+static void ungetchr __ARGS((void));
+static void regcomp_start __ARGS((char_u *expr, int flags));
+static char_u *reg __ARGS((int, int *));
+static char_u *regbranch __ARGS((int *flagp));
+static char_u *regconcat __ARGS((int *flagp));
+static char_u *regpiece __ARGS((int *));
+static char_u *regatom __ARGS((int *));
+static char_u *regnode __ARGS((int));
+static int prog_magic_wrong __ARGS((void));
+static char_u *regnext __ARGS((char_u *));
+static void regc __ARGS((int b));
+#ifdef FEAT_MBYTE
+static void regmbc __ARGS((int c));
+#endif
+static void reginsert __ARGS((int, char_u *));
+static void reginsert_limits __ARGS((int, long, long, char_u *));
+static char_u *re_put_long __ARGS((char_u *pr, long_u val));
+static int read_limits __ARGS((long *, long *));
+static void regtail __ARGS((char_u *, char_u *));
+static void regoptail __ARGS((char_u *, char_u *));
+
+/*
+ * Return TRUE if compiled regular expression "prog" can match a line break.
+ */
+ int
+re_multiline(prog)
+ regprog_T *prog;
+{
+ return (prog->regflags & RF_HASNL);
+}
+
+/*
+ * Return TRUE if compiled regular expression "prog" looks before the start
+ * position (pattern contains "\@<=" or "\@<!").
+ */
+ int
+re_lookbehind(prog)
+ regprog_T *prog;
+{
+ return (prog->regflags & RF_LOOKBH);
+}
+
+/*
+ * Skip past regular expression.
+ * Stop at end of 'p' of where 'dirc' is found ('/', '?', etc).
+ * Take care of characters with a backslash in front of it.
+ * Skip strings inside [ and ].
+ * When "newp" is not NULL and "dirc" is '?', make an allocated copy of the
+ * expression and change "\?" to "?". If "*newp" is not NULL the expression
+ * is changed in-place.
+ */
+ char_u *
+skip_regexp(startp, dirc, magic, newp)
+ char_u *startp;
+ int dirc;
+ int magic;
+ char_u **newp;
+{
+ int mymagic;
+ char_u *p = startp;
+
+ if (magic)
+ mymagic = MAGIC_ON;
+ else
+ mymagic = MAGIC_OFF;
+
+ for (; p[0] != NUL; ++p)
+ {
+ if (p[0] == dirc) /* found end of regexp */
+ break;
+ if ((p[0] == '[' && mymagic >= MAGIC_ON)
+ || (p[0] == '\\' && p[1] == '[' && mymagic <= MAGIC_OFF))
+ {
+ p = skip_anyof(p + 1);
+ if (p[0] == NUL)
+ break;
+ }
+ else if (p[0] == '\\' && p[1] != NUL)
+ {
+ if (dirc == '?' && newp != NULL && p[1] == '?')
+ {
+ /* change "\?" to "?", make a copy first. */
+ if (*newp == NULL)
+ {
+ *newp = vim_strsave(startp);
+ if (*newp != NULL)
+ p = *newp + (p - startp);
+ }
+ if (*newp != NULL)
+ mch_memmove(p, p + 1, STRLEN(p));
+ else
+ ++p;
+ }
+ else
+ ++p; /* skip next character */
+ if (*p == 'v')
+ mymagic = MAGIC_ALL;
+ else if (*p == 'V')
+ mymagic = MAGIC_NONE;
+ }
+#ifdef FEAT_MBYTE
+ else if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ return p;
+}
+
+/*
+ * vim_regcomp - compile a regular expression into internal code
+ *
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code. So we cheat: we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it. (Note that it has to be in
+ * one piece because vim_free() must be able to free it all.)
+ *
+ * Whether upper/lower case is to be ignored is decided when executing the
+ * program, it does not matter here.
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ * "re_flags": RE_MAGIC and/or RE_STRING.
+ */
+ regprog_T *
+vim_regcomp(expr, re_flags)
+ char_u *expr;
+ int re_flags;
+{
+ regprog_T *r;
+ char_u *scan;
+ char_u *longest;
+ int len;
+ int flags;
+
+ if (expr == NULL)
+ EMSG_RET_NULL(_(e_null));
+
+ init_class_tab();
+
+ /*
+ * First pass: determine size, legality.
+ */
+ regcomp_start(expr, re_flags);
+ regcode = JUST_CALC_SIZE;
+ regc(REGMAGIC);
+ if (reg(REG_NOPAREN, &flags) == NULL)
+ return NULL;
+
+ /* Small enough for pointer-storage convention? */
+#ifdef SMALL_MALLOC /* 16 bit storage allocation */
+ if (regsize >= 65536L - 256L)
+ EMSG_RET_NULL(_("E339: Pattern too long"));
+#endif
+
+ /* Allocate space. */
+ r = (regprog_T *)lalloc(sizeof(regprog_T) + regsize, TRUE);
+ if (r == NULL)
+ return NULL;
+
+ /*
+ * Second pass: emit code.
+ */
+ regcomp_start(expr, re_flags);
+ regcode = r->program;
+ regc(REGMAGIC);
+ if (reg(REG_NOPAREN, &flags) == NULL)
+ {
+ vim_free(r);
+ return NULL;
+ }
+
+ /* Dig out information for optimizations. */
+ r->regstart = NUL; /* Worst-case defaults. */
+ r->reganch = 0;
+ r->regmust = NULL;
+ r->regmlen = 0;
+ r->regflags = regflags;
+ if (flags & HASNL)
+ r->regflags |= RF_HASNL;
+ if (flags & HASLOOKBH)
+ r->regflags |= RF_LOOKBH;
+#ifdef FEAT_SYN_HL
+ /* Remember whether this pattern has any \z specials in it. */
+ r->reghasz = re_has_z;
+#endif
+ scan = r->program + 1; /* First BRANCH. */
+ if (OP(regnext(scan)) == END) /* Only one top-level choice. */
+ {
+ scan = OPERAND(scan);
+
+ /* Starting-point info. */
+ if (OP(scan) == BOL || OP(scan) == RE_BOF)
+ {
+ r->reganch++;
+ scan = regnext(scan);
+ }
+
+ if (OP(scan) == EXACTLY)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ r->regstart = (*mb_ptr2char)(OPERAND(scan));
+ else
+#endif
+ r->regstart = *OPERAND(scan);
+ }
+ else if ((OP(scan) == BOW
+ || OP(scan) == EOW
+ || OP(scan) == NOTHING
+ || OP(scan) == MOPEN + 0 || OP(scan) == NOPEN
+ || OP(scan) == MCLOSE + 0 || OP(scan) == NCLOSE)
+ && OP(regnext(scan)) == EXACTLY)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ r->regstart = (*mb_ptr2char)(OPERAND(regnext(scan)));
+ else
+#endif
+ r->regstart = *OPERAND(regnext(scan));
+ }
+
+ /*
+ * If there's something expensive in the r.e., find the longest
+ * literal string that must appear and make it the regmust. Resolve
+ * ties in favor of later strings, since the regstart check works
+ * with the beginning of the r.e. and avoiding duplication
+ * strengthens checking. Not a strong reason, but sufficient in the
+ * absence of others.
+ */
+ /*
+ * When the r.e. starts with BOW, it is faster to look for a regmust
+ * first. Used a lot for "#" and "*" commands. (Added by mool).
+ */
+ if ((flags & SPSTART || OP(scan) == BOW || OP(scan) == EOW)
+ && !(flags & HASNL))
+ {
+ longest = NULL;
+ len = 0;
+ for (; scan != NULL; scan = regnext(scan))
+ if (OP(scan) == EXACTLY && STRLEN(OPERAND(scan)) >= (size_t)len)
+ {
+ longest = OPERAND(scan);
+ len = (int)STRLEN(OPERAND(scan));
+ }
+ r->regmust = longest;
+ r->regmlen = len;
+ }
+ }
+#ifdef DEBUG
+ regdump(expr, r);
+#endif
+ return r;
+}
+
+/*
+ * Setup to parse the regexp. Used once to get the length and once to do it.
+ */
+ static void
+regcomp_start(expr, re_flags)
+ char_u *expr;
+ int re_flags; /* see vim_regcomp() */
+{
+ initchr(expr);
+ if (re_flags & RE_MAGIC)
+ reg_magic = MAGIC_ON;
+ else
+ reg_magic = MAGIC_OFF;
+ reg_string = (re_flags & RE_STRING);
+
+ num_complex_braces = 0;
+ regnpar = 1;
+ vim_memset(had_endbrace, 0, sizeof(had_endbrace));
+#ifdef FEAT_SYN_HL
+ regnzpar = 1;
+ re_has_z = 0;
+#endif
+ regsize = 0L;
+ regflags = 0;
+#if defined(FEAT_SYN_HL) || defined(PROTO)
+ had_eol = FALSE;
+#endif
+}
+
+#if defined(FEAT_SYN_HL) || defined(PROTO)
+/*
+ * Check if during the previous call to vim_regcomp the EOL item "$" has been
+ * found. This is messy, but it works fine.
+ */
+ int
+vim_regcomp_had_eol()
+{
+ return had_eol;
+}
+#endif
+
+/*
+ * reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+ static char_u *
+reg(paren, flagp)
+ int paren; /* REG_NOPAREN, REG_PAREN, REG_NPAREN or REG_ZPAREN */
+ int *flagp;
+{
+ char_u *ret;
+ char_u *br;
+ char_u *ender;
+ int parno = 0;
+ int flags;
+
+ *flagp = HASWIDTH; /* Tentatively. */
+
+#ifdef FEAT_SYN_HL
+ if (paren == REG_ZPAREN)
+ {
+ /* Make a ZOPEN node. */
+ if (regnzpar >= NSUBEXP)
+ EMSG_RET_NULL(_("E50: Too many \\z("));
+ parno = regnzpar;
+ regnzpar++;
+ ret = regnode(ZOPEN + parno);
+ }
+ else
+#endif
+ if (paren == REG_PAREN)
+ {
+ /* Make a MOPEN node. */
+ if (regnpar >= NSUBEXP)
+ EMSG_M_RET_NULL(_("E51: Too many %s("), reg_magic == MAGIC_ALL);
+ parno = regnpar;
+ ++regnpar;
+ ret = regnode(MOPEN + parno);
+ }
+ else if (paren == REG_NPAREN)
+ {
+ /* Make a NOPEN node. */
+ ret = regnode(NOPEN);
+ }
+ else
+ ret = NULL;
+
+ /* Pick up the branches, linking them together. */
+ br = regbranch(&flags);
+ if (br == NULL)
+ return NULL;
+ if (ret != NULL)
+ regtail(ret, br); /* [MZ]OPEN -> first. */
+ else
+ ret = br;
+ /* If one of the branches can be zero-width, the whole thing can.
+ * If one of the branches has * at start or matches a line-break, the
+ * whole thing can. */
+ if (!(flags & HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags & (SPSTART | HASNL | HASLOOKBH);
+ while (peekchr() == Magic('|'))
+ {
+ skipchr();
+ br = regbranch(&flags);
+ if (br == NULL)
+ return NULL;
+ regtail(ret, br); /* BRANCH -> BRANCH. */
+ if (!(flags & HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags & (SPSTART | HASNL | HASLOOKBH);
+ }
+
+ /* Make a closing node, and hook it on the end. */
+ ender = regnode(
+#ifdef FEAT_SYN_HL
+ paren == REG_ZPAREN ? ZCLOSE + parno :
+#endif
+ paren == REG_PAREN ? MCLOSE + parno :
+ paren == REG_NPAREN ? NCLOSE : END);
+ regtail(ret, ender);
+
+ /* Hook the tails of the branches to the closing node. */
+ for (br = ret; br != NULL; br = regnext(br))
+ regoptail(br, ender);
+
+ /* Check for proper termination. */
+ if (paren != REG_NOPAREN && getchr() != Magic(')'))
+ {
+#ifdef FEAT_SYN_HL
+ if (paren == REG_ZPAREN)
+ EMSG_RET_NULL(_("E52: Unmatched \\z("))
+ else
+#endif
+ if (paren == REG_NPAREN)
+ EMSG_M_RET_NULL(_("E53: Unmatched %s%%("), reg_magic == MAGIC_ALL)
+ else
+ EMSG_M_RET_NULL(_("E54: Unmatched %s("), reg_magic == MAGIC_ALL)
+ }
+ else if (paren == REG_NOPAREN && peekchr() != NUL)
+ {
+ if (curchr == Magic(')'))
+ EMSG_M_RET_NULL(_("E55: Unmatched %s)"), reg_magic == MAGIC_ALL)
+ else
+ EMSG_RET_NULL(_(e_trailing)) /* "Can't happen". */
+ /* NOTREACHED */
+ }
+ /*
+ * Here we set the flag allowing back references to this set of
+ * parentheses.
+ */
+ if (paren == REG_PAREN)
+ had_endbrace[parno] = TRUE; /* have seen the close paren */
+ return ret;
+}
+
+/*
+ * regbranch - one alternative of an | operator
+ *
+ * Implements the & operator.
+ */
+ static char_u *
+regbranch(flagp)
+ int *flagp;
+{
+ char_u *ret;
+ char_u *chain = NULL;
+ char_u *latest;
+ int flags;
+
+ *flagp = WORST | HASNL; /* Tentatively. */
+
+ ret = regnode(BRANCH);
+ for (;;)
+ {
+ latest = regconcat(&flags);
+ if (latest == NULL)
+ return NULL;
+ /* If one of the branches has width, the whole thing has. If one of
+ * the branches anchors at start-of-line, the whole thing does.
+ * If one of the branches uses look-behind, the whole thing does. */
+ *flagp |= flags & (HASWIDTH | SPSTART | HASLOOKBH);
+ /* If one of the branches doesn't match a line-break, the whole thing
+ * doesn't. */
+ *flagp &= ~HASNL | (flags & HASNL);
+ if (chain != NULL)
+ regtail(chain, latest);
+ if (peekchr() != Magic('&'))
+ break;
+ skipchr();
+ regtail(latest, regnode(END)); /* operand ends */
+ reginsert(MATCH, latest);
+ chain = latest;
+ }
+
+ return ret;
+}
+
+/*
+ * regbranch - one alternative of an | or & operator
+ *
+ * Implements the concatenation operator.
+ */
+ static char_u *
+regconcat(flagp)
+ int *flagp;
+{
+ char_u *first = NULL;
+ char_u *chain = NULL;
+ char_u *latest;
+ int flags;
+ int cont = TRUE;
+
+ *flagp = WORST; /* Tentatively. */
+
+ while (cont)
+ {
+ switch (peekchr())
+ {
+ case NUL:
+ case Magic('|'):
+ case Magic('&'):
+ case Magic(')'):
+ cont = FALSE;
+ break;
+ case Magic('Z'):
+#ifdef FEAT_MBYTE
+ regflags |= RF_ICOMBINE;
+#endif
+ skipchr_keepstart();
+ break;
+ case Magic('c'):
+ regflags |= RF_ICASE;
+ skipchr_keepstart();
+ break;
+ case Magic('C'):
+ regflags |= RF_NOICASE;
+ skipchr_keepstart();
+ break;
+ case Magic('v'):
+ reg_magic = MAGIC_ALL;
+ skipchr_keepstart();
+ curchr = -1;
+ break;
+ case Magic('m'):
+ reg_magic = MAGIC_ON;
+ skipchr_keepstart();
+ curchr = -1;
+ break;
+ case Magic('M'):
+ reg_magic = MAGIC_OFF;
+ skipchr_keepstart();
+ curchr = -1;
+ break;
+ case Magic('V'):
+ reg_magic = MAGIC_NONE;
+ skipchr_keepstart();
+ curchr = -1;
+ break;
+ default:
+ latest = regpiece(&flags);
+ if (latest == NULL)
+ return NULL;
+ *flagp |= flags & (HASWIDTH | HASNL | HASLOOKBH);
+ if (chain == NULL) /* First piece. */
+ *flagp |= flags & SPSTART;
+ else
+ regtail(chain, latest);
+ chain = latest;
+ if (first == NULL)
+ first = latest;
+ break;
+ }
+ }
+ if (first == NULL) /* Loop ran zero times. */
+ first = regnode(NOTHING);
+ return first;
+}
+
+/*
+ * regpiece - something followed by possible [*+=]
+ *
+ * Note that the branching code sequences used for = and the general cases
+ * of * and + are somewhat optimized: they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+ static char_u *
+regpiece(flagp)
+ int *flagp;
+{
+ char_u *ret;
+ int op;
+ char_u *next;
+ int flags;
+ long minval;
+ long maxval;
+
+ ret = regatom(&flags);
+ if (ret == NULL)
+ return NULL;
+
+ op = peekchr();
+ if (re_multi_type(op) == NOT_MULTI)
+ {
+ *flagp = flags;
+ return ret;
+ }
+ if (!(flags & HASWIDTH) && re_multi_type(op) == MULTI_MULT)
+ {
+ if (op == Magic('*'))
+ EMSG_M_RET_NULL(_("E56: %s* operand could be empty"),
+ reg_magic >= MAGIC_ON);
+ if (op == Magic('+'))
+ EMSG_M_RET_NULL(_("E57: %s+ operand could be empty"),
+ reg_magic == MAGIC_ALL);
+ /* "\{}" is checked below, it's allowed when there is an upper limit */
+ }
+ /* default flags */
+ *flagp = (WORST | SPSTART | (flags & (HASNL | HASLOOKBH)));
+
+ skipchr();
+ switch (op)
+ {
+ case Magic('*'):
+ if (flags & SIMPLE)
+ reginsert(STAR, ret);
+ else
+ {
+ /* Emit x* as (x&|), where & means "self". */
+ reginsert(BRANCH, ret); /* Either x */
+ regoptail(ret, regnode(BACK)); /* and loop */
+ regoptail(ret, ret); /* back */
+ regtail(ret, regnode(BRANCH)); /* or */
+ regtail(ret, regnode(NOTHING)); /* null. */
+ }
+ break;
+
+ case Magic('+'):
+ if (flags & SIMPLE)
+ reginsert(PLUS, ret);
+ else
+ {
+ /* Emit x+ as x(&|), where & means "self". */
+ next = regnode(BRANCH); /* Either */
+ regtail(ret, next);
+ regtail(regnode(BACK), ret); /* loop back */
+ regtail(next, regnode(BRANCH)); /* or */
+ regtail(ret, regnode(NOTHING)); /* null. */
+ }
+ *flagp = (WORST | HASWIDTH | (flags & (HASNL | HASLOOKBH)));
+ break;
+
+ case Magic('@'):
+ {
+ int lop = END;
+
+ switch (no_Magic(getchr()))
+ {
+ case '=': lop = MATCH; break; /* \@= */
+ case '!': lop = NOMATCH; break; /* \@! */
+ case '>': lop = SUBPAT; break; /* \@> */
+ case '<': switch (no_Magic(getchr()))
+ {
+ case '=': lop = BEHIND; break; /* \@<= */
+ case '!': lop = NOBEHIND; break; /* \@<! */
+ }
+ }
+ if (lop == END)
+ EMSG_M_RET_NULL(_("E59: invalid character after %s@"),
+ reg_magic == MAGIC_ALL);
+ /* Look behind must match with behind_pos. */
+ if (lop == BEHIND || lop == NOBEHIND)
+ {
+ regtail(ret, regnode(BHPOS));
+ *flagp |= HASLOOKBH;
+ }
+ regtail(ret, regnode(END)); /* operand ends */
+ reginsert(lop, ret);
+ break;
+ }
+
+ case Magic('?'):
+ case Magic('='):
+ /* Emit x= as (x|) */
+ reginsert(BRANCH, ret); /* Either x */
+ regtail(ret, regnode(BRANCH)); /* or */
+ next = regnode(NOTHING); /* null. */
+ regtail(ret, next);
+ regoptail(ret, next);
+ break;
+
+ case Magic('{'):
+ if (!read_limits(&minval, &maxval))
+ return NULL;
+ if (!(flags & HASWIDTH) && (maxval > minval
+ ? maxval >= MAX_LIMIT : minval >= MAX_LIMIT))
+ EMSG_M_RET_NULL(_("E58: %s{ operand could be empty"),
+ reg_magic == MAGIC_ALL);
+ if (flags & SIMPLE)
+ {
+ reginsert(BRACE_SIMPLE, ret);
+ reginsert_limits(BRACE_LIMITS, minval, maxval, ret);
+ }
+ else
+ {
+ if (num_complex_braces >= 10)
+ EMSG_M_RET_NULL(_("E60: Too many complex %s{...}s"),
+ reg_magic == MAGIC_ALL);
+ reginsert(BRACE_COMPLEX + num_complex_braces, ret);
+ regoptail(ret, regnode(BACK));
+ regoptail(ret, ret);
+ reginsert_limits(BRACE_LIMITS, minval, maxval, ret);
+ ++num_complex_braces;
+ }
+ if (minval > 0 && maxval > 0)
+ *flagp = (HASWIDTH | (flags & (HASNL | HASLOOKBH)));
+ break;
+ }
+ if (re_multi_type(peekchr()) != NOT_MULTI)
+ {
+ /* Can't have a multi follow a multi. */
+ if (peekchr() == Magic('*'))
+ sprintf((char *)IObuff, _("E61: Nested %s*"),
+ reg_magic >= MAGIC_ON ? "" : "\\");
+ else
+ sprintf((char *)IObuff, _("E62: Nested %s%c"),
+ reg_magic == MAGIC_ALL ? "" : "\\", no_Magic(peekchr()));
+ EMSG_RET_NULL(IObuff);
+ }
+
+ return ret;
+}
+
+/*
+ * regatom - the lowest level
+ *
+ * Optimization: gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run. Don't do this when one_exactly is set.
+ */
+ static char_u *
+regatom(flagp)
+ int *flagp;
+{
+ char_u *ret;
+ int flags;
+ int cpo_lit; /* 'cpoptions' contains 'l' flag */
+ int c;
+ static char_u *classchars = (char_u *)".iIkKfFpPsSdDxXoOwWhHaAlLuU";
+ static int classcodes[] = {ANY, IDENT, SIDENT, KWORD, SKWORD,
+ FNAME, SFNAME, PRINT, SPRINT,
+ WHITE, NWHITE, DIGIT, NDIGIT,
+ HEX, NHEX, OCTAL, NOCTAL,
+ WORD, NWORD, HEAD, NHEAD,
+ ALPHA, NALPHA, LOWER, NLOWER,
+ UPPER, NUPPER
+ };
+ char_u *p;
+ int extra = 0;
+
+ *flagp = WORST; /* Tentatively. */
+ cpo_lit = (!reg_syn && vim_strchr(p_cpo, CPO_LITERAL) != NULL);
+
+ c = getchr();
+ switch (c)
+ {
+ case Magic('^'):
+ ret = regnode(BOL);
+ break;
+
+ case Magic('$'):
+ ret = regnode(EOL);
+#if defined(FEAT_SYN_HL) || defined(PROTO)
+ had_eol = TRUE;
+#endif
+ break;
+
+ case Magic('<'):
+ ret = regnode(BOW);
+ break;
+
+ case Magic('>'):
+ ret = regnode(EOW);
+ break;
+
+ case Magic('_'):
+ c = no_Magic(getchr());
+ if (c == '^') /* "\_^" is start-of-line */
+ {
+ ret = regnode(BOL);
+ break;
+ }
+ if (c == '$') /* "\_$" is end-of-line */
+ {
+ ret = regnode(EOL);
+#if defined(FEAT_SYN_HL) || defined(PROTO)
+ had_eol = TRUE;
+#endif
+ break;
+ }
+
+ extra = ADD_NL;
+ *flagp |= HASNL;
+
+ /* "\_[" is character range plus newline */
+ if (c == '[')
+ goto collection;
+
+ /* "\_x" is character class plus newline */
+ /*FALLTHROUGH*/
+
+ /*
+ * Character classes.
+ */
+ case Magic('.'):
+ case Magic('i'):
+ case Magic('I'):
+ case Magic('k'):
+ case Magic('K'):
+ case Magic('f'):
+ case Magic('F'):
+ case Magic('p'):
+ case Magic('P'):
+ case Magic('s'):
+ case Magic('S'):
+ case Magic('d'):
+ case Magic('D'):
+ case Magic('x'):
+ case Magic('X'):
+ case Magic('o'):
+ case Magic('O'):
+ case Magic('w'):
+ case Magic('W'):
+ case Magic('h'):
+ case Magic('H'):
+ case Magic('a'):
+ case Magic('A'):
+ case Magic('l'):
+ case Magic('L'):
+ case Magic('u'):
+ case Magic('U'):
+ p = vim_strchr(classchars, no_Magic(c));
+ if (p == NULL)
+ EMSG_RET_NULL(_("E63: invalid use of \\_"));
+ ret = regnode(classcodes[p - classchars] + extra);
+ *flagp |= HASWIDTH | SIMPLE;
+ break;
+
+ case Magic('n'):
+ if (reg_string)
+ {
+ /* In a string "\n" matches a newline character. */
+ ret = regnode(EXACTLY);
+ regc(NL);
+ regc(NUL);
+ *flagp |= HASWIDTH | SIMPLE;
+ }
+ else
+ {
+ /* In buffer text "\n" matches the end of a line. */
+ ret = regnode(NEWL);
+ *flagp |= HASWIDTH | HASNL;
+ }
+ break;
+
+ case Magic('('):
+ if (one_exactly)
+ EMSG_ONE_RET_NULL;
+ ret = reg(REG_PAREN, &flags);
+ if (ret == NULL)
+ return NULL;
+ *flagp |= flags & (HASWIDTH | SPSTART | HASNL | HASLOOKBH);
+ break;
+
+ case NUL:
+ case Magic('|'):
+ case Magic('&'):
+ case Magic(')'):
+ EMSG_RET_NULL(_(e_internal)); /* Supposed to be caught earlier. */
+ /* NOTREACHED */
+
+ case Magic('='):
+ case Magic('?'):
+ case Magic('+'):
+ case Magic('@'):
+ case Magic('{'):
+ case Magic('*'):
+ c = no_Magic(c);
+ sprintf((char *)IObuff, _("E64: %s%c follows nothing"),
+ (c == '*' ? reg_magic >= MAGIC_ON : reg_magic == MAGIC_ALL)
+ ? "" : "\\", c);
+ EMSG_RET_NULL(IObuff);
+ /* NOTREACHED */
+
+ case Magic('~'): /* previous substitute pattern */
+ if (reg_prev_sub)
+ {
+ char_u *lp;
+
+ ret = regnode(EXACTLY);
+ lp = reg_prev_sub;
+ while (*lp != NUL)
+ regc(*lp++);
+ regc(NUL);
+ if (*reg_prev_sub != NUL)
+ {
+ *flagp |= HASWIDTH;
+ if ((lp - reg_prev_sub) == 1)
+ *flagp |= SIMPLE;
+ }
+ }
+ else
+ EMSG_RET_NULL(_(e_nopresub));
+ break;
+
+ case Magic('1'):
+ case Magic('2'):
+ case Magic('3'):
+ case Magic('4'):
+ case Magic('5'):
+ case Magic('6'):
+ case Magic('7'):
+ case Magic('8'):
+ case Magic('9'):
+ {
+ int refnum;
+
+ refnum = c - Magic('0');
+ /*
+ * Check if the back reference is legal. We must have seen the
+ * close brace.
+ * TODO: Should also check that we don't refer to something
+ * that is repeated (+*=): what instance of the repetition
+ * should we match?
+ */
+ if (!had_endbrace[refnum])
+ {
+ /* Trick: check if "@<=" or "@<!" follows, in which case
+ * the \1 can appear before the referenced match. */
+ for (p = regparse; *p != NUL; ++p)
+ if (p[0] == '@' && p[1] == '<'
+ && (p[2] == '!' || p[2] == '='))
+ break;
+ if (*p == NUL)
+ EMSG_RET_NULL(_("E65: Illegal back reference"));
+ }
+ ret = regnode(BACKREF + refnum);
+ }
+ break;
+
+#ifdef FEAT_SYN_HL
+ case Magic('z'):
+ {
+ c = no_Magic(getchr());
+ switch (c)
+ {
+ case '(': if (reg_do_extmatch != REX_SET)
+ EMSG_RET_NULL(_("E66: \\z( not allowed here"));
+ if (one_exactly)
+ EMSG_ONE_RET_NULL;
+ ret = reg(REG_ZPAREN, &flags);
+ if (ret == NULL)
+ return NULL;
+ *flagp |= flags & (HASWIDTH|SPSTART|HASNL|HASLOOKBH);
+ re_has_z = REX_SET;
+ break;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': if (reg_do_extmatch != REX_USE)
+ EMSG_RET_NULL(_("E67: \\z1 et al. not allowed here"));
+ ret = regnode(ZREF + c - '0');
+ re_has_z = REX_USE;
+ break;
+
+ case 's': ret = regnode(MOPEN + 0);
+ break;
+
+ case 'e': ret = regnode(MCLOSE + 0);
+ break;
+
+ default: EMSG_RET_NULL(_("E68: Invalid character after \\z"));
+ }
+ }
+ break;
+#endif
+
+ case Magic('%'):
+ {
+ c = no_Magic(getchr());
+ switch (c)
+ {
+ /* () without a back reference */
+ case '(':
+ if (one_exactly)
+ EMSG_ONE_RET_NULL;
+ ret = reg(REG_NPAREN, &flags);
+ if (ret == NULL)
+ return NULL;
+ *flagp |= flags & (HASWIDTH | SPSTART | HASNL | HASLOOKBH);
+ break;
+
+ /* Catch \%^ and \%$ regardless of where they appear in the
+ * pattern -- regardless of whether or not it makes sense. */
+ case '^':
+ ret = regnode(RE_BOF);
+ break;
+
+ case '$':
+ ret = regnode(RE_EOF);
+ break;
+
+ case '#':
+ ret = regnode(CURSOR);
+ break;
+
+ /* \%[abc]: Emit as a list of branches, all ending at the last
+ * branch which matches nothing. */
+ case '[':
+ if (one_exactly) /* doesn't nest */
+ EMSG_ONE_RET_NULL;
+ {
+ char_u *lastbranch;
+ char_u *lastnode = NULL;
+ char_u *br;
+
+ ret = NULL;
+ while ((c = getchr()) != ']')
+ {
+ if (c == NUL)
+ EMSG_M_RET_NULL(_("E69: Missing ] after %s%%["),
+ reg_magic == MAGIC_ALL);
+ br = regnode(BRANCH);
+ if (ret == NULL)
+ ret = br;
+ else
+ regtail(lastnode, br);
+
+ ungetchr();
+ one_exactly = TRUE;
+ lastnode = regatom(flagp);
+ one_exactly = FALSE;
+ if (lastnode == NULL)
+ return NULL;
+ }
+ if (ret == NULL)
+ EMSG_M_RET_NULL(_("E70: Empty %s%%[]"),
+ reg_magic == MAGIC_ALL);
+ lastbranch = regnode(BRANCH);
+ br = regnode(NOTHING);
+ if (ret != JUST_CALC_SIZE)
+ {
+ regtail(lastnode, br);
+ regtail(lastbranch, br);
+ /* connect all branches to the NOTHING
+ * branch at the end */
+ for (br = ret; br != lastnode; )
+ {
+ if (OP(br) == BRANCH)
+ {
+ regtail(br, lastbranch);
+ br = OPERAND(br);
+ }
+ else
+ br = regnext(br);
+ }
+ }
+ *flagp &= ~HASWIDTH;
+ break;
+ }
+
+ default:
+ if (VIM_ISDIGIT(c) || c == '<' || c == '>')
+ {
+ long_u n = 0;
+ int cmp;
+
+ cmp = c;
+ if (cmp == '<' || cmp == '>')
+ c = getchr();
+ while (VIM_ISDIGIT(c))
+ {
+ n = n * 10 + (c - '0');
+ c = getchr();
+ }
+ if (c == 'l' || c == 'c' || c == 'v')
+ {
+ if (c == 'l')
+ ret = regnode(RE_LNUM);
+ else if (c == 'c')
+ ret = regnode(RE_COL);
+ else
+ ret = regnode(RE_VCOL);
+ if (ret == JUST_CALC_SIZE)
+ regsize += 5;
+ else
+ {
+ /* put the number and the optional
+ * comparator after the opcode */
+ regcode = re_put_long(regcode, n);
+ *regcode++ = cmp;
+ }
+ break;
+ }
+ }
+
+ EMSG_M_RET_NULL(_("E71: Invalid character after %s%%"),
+ reg_magic == MAGIC_ALL);
+ }
+ }
+ break;
+
+ case Magic('['):
+collection:
+ {
+ char_u *lp;
+
+ /*
+ * If there is no matching ']', we assume the '[' is a normal
+ * character. This makes 'incsearch' and ":help [" work.
+ */
+ lp = skip_anyof(regparse);
+ if (*lp == ']') /* there is a matching ']' */
+ {
+ int startc = -1; /* > 0 when next '-' is a range */
+ int endc;
+
+ /*
+ * In a character class, different parsing rules apply.
+ * Not even \ is special anymore, nothing is.
+ */
+ if (*regparse == '^') /* Complement of range. */
+ {
+ ret = regnode(ANYBUT + extra);
+ regparse++;
+ }
+ else
+ ret = regnode(ANYOF + extra);
+
+ /* At the start ']' and '-' mean the literal character. */
+ if (*regparse == ']' || *regparse == '-')
+ regc(*regparse++);
+
+ while (*regparse != NUL && *regparse != ']')
+ {
+ if (*regparse == '-')
+ {
+ ++regparse;
+ /* The '-' is not used for a range at the end and
+ * after or before a '\n'. */
+ if (*regparse == ']' || *regparse == NUL
+ || startc == -1
+ || (regparse[0] == '\\' && regparse[1] == 'n'))
+ {
+ regc('-');
+ startc = '-'; /* [--x] is a range */
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ endc = mb_ptr2char_adv(&regparse);
+ else
+#endif
+ endc = *regparse++;
+ if (startc > endc)
+ EMSG_RET_NULL(_(e_invrange));
+#ifdef FEAT_MBYTE
+ if (has_mbyte && ((*mb_char2len)(startc) > 1
+ || (*mb_char2len)(endc) > 1))
+ {
+ /* Limit to a range of 256 chars */
+ if (endc > startc + 256)
+ EMSG_RET_NULL(_(e_invrange));
+ while (++startc <= endc)
+ regmbc(startc);
+ }
+ else
+#endif
+ {
+#ifdef EBCDIC
+ int alpha_only = FALSE;
+
+ /* for alphabetical range skip the gaps
+ * 'i'-'j', 'r'-'s', 'I'-'J' and 'R'-'S'. */
+ if (isalpha(startc) && isalpha(endc))
+ alpha_only = TRUE;
+#endif
+ while (++startc <= endc)
+#ifdef EBCDIC
+ if (!alpha_only || isalpha(startc))
+#endif
+ regc(startc);
+ }
+ startc = -1;
+ }
+ }
+ /*
+ * Only "\]", "\^", "\]" and "\\" are special in Vi. Vim
+ * accepts "\t", "\e", etc., but only when the 'l' flag in
+ * 'cpoptions' is not included.
+ */
+ else if (*regparse == '\\'
+ && (vim_strchr(REGEXP_INRANGE, regparse[1]) != NULL
+ || (!cpo_lit
+ && vim_strchr(REGEXP_ABBR,
+ regparse[1]) != NULL)))
+ {
+ regparse++;
+ if (*regparse == 'n')
+ {
+ /* '\n' in range: also match NL */
+ if (ret != JUST_CALC_SIZE)
+ {
+ if (*ret == ANYBUT)
+ *ret = ANYBUT + ADD_NL;
+ else if (*ret == ANYOF)
+ *ret = ANYOF + ADD_NL;
+ /* else: must have had a \n already */
+ }
+ *flagp |= HASNL;
+ regparse++;
+ startc = -1;
+ }
+ else
+ {
+ startc = backslash_trans(*regparse++);
+ regc(startc);
+ }
+ }
+ else if (*regparse == '[')
+ {
+ int c_class;
+ int cu;
+
+ c_class = skip_class_name(&regparse);
+ startc = -1;
+ /* Characters assumed to be 8 bits! */
+ switch (c_class)
+ {
+ case CLASS_NONE:
+ /* literal '[', allow [[-x] as a range */
+ startc = *regparse++;
+ regc(startc);
+ break;
+ case CLASS_ALNUM:
+ for (cu = 1; cu <= 255; cu++)
+ if (isalnum(cu))
+ regc(cu);
+ break;
+ case CLASS_ALPHA:
+ for (cu = 1; cu <= 255; cu++)
+ if (isalpha(cu))
+ regc(cu);
+ break;
+ case CLASS_BLANK:
+ regc(' ');
+ regc('\t');
+ break;
+ case CLASS_CNTRL:
+ for (cu = 1; cu <= 255; cu++)
+ if (iscntrl(cu))
+ regc(cu);
+ break;
+ case CLASS_DIGIT:
+ for (cu = 1; cu <= 255; cu++)
+ if (VIM_ISDIGIT(cu))
+ regc(cu);
+ break;
+ case CLASS_GRAPH:
+ for (cu = 1; cu <= 255; cu++)
+ if (isgraph(cu))
+ regc(cu);
+ break;
+ case CLASS_LOWER:
+ for (cu = 1; cu <= 255; cu++)
+ if (islower(cu))
+ regc(cu);
+ break;
+ case CLASS_PRINT:
+ for (cu = 1; cu <= 255; cu++)
+ if (vim_isprintc(cu))
+ regc(cu);
+ break;
+ case CLASS_PUNCT:
+ for (cu = 1; cu <= 255; cu++)
+ if (ispunct(cu))
+ regc(cu);
+ break;
+ case CLASS_SPACE:
+ for (cu = 9; cu <= 13; cu++)
+ regc(cu);
+ regc(' ');
+ break;
+ case CLASS_UPPER:
+ for (cu = 1; cu <= 255; cu++)
+ if (isupper(cu))
+ regc(cu);
+ break;
+ case CLASS_XDIGIT:
+ for (cu = 1; cu <= 255; cu++)
+ if (vim_isxdigit(cu))
+ regc(cu);
+ break;
+ case CLASS_TAB:
+ regc('\t');
+ break;
+ case CLASS_RETURN:
+ regc('\r');
+ break;
+ case CLASS_BACKSPACE:
+ regc('\b');
+ break;
+ case CLASS_ESCAPE:
+ regc('\033');
+ break;
+ }
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int len;
+
+ /* produce a multibyte character, including any
+ * following composing characters */
+ startc = mb_ptr2char(regparse);
+ len = (*mb_ptr2len_check)(regparse);
+ if (enc_utf8 && utf_char2len(startc) != len)
+ startc = -1; /* composing chars */
+ while (--len >= 0)
+ regc(*regparse++);
+ }
+ else
+#endif
+ {
+ startc = *regparse++;
+ regc(startc);
+ }
+ }
+ }
+ regc(NUL);
+ prevchr_len = 1; /* last char was the ']' */
+ if (*regparse != ']')
+ EMSG_RET_NULL(_(e_toomsbra)); /* Cannot happen? */
+ skipchr(); /* let's be friends with the lexer again */
+ *flagp |= HASWIDTH | SIMPLE;
+ break;
+ }
+ }
+ /* FALLTHROUGH */
+
+ default:
+ {
+ int len;
+
+#ifdef FEAT_MBYTE
+ /* A multi-byte character is handled as a separate atom if it's
+ * before a multi. */
+ if (has_mbyte && (*mb_char2len)(c) > 1
+ && re_multi_type(peekchr()) != NOT_MULTI)
+ {
+ ret = regnode(MULTIBYTECODE);
+ regmbc(c);
+ *flagp |= HASWIDTH | SIMPLE;
+ break;
+ }
+#endif
+
+ ret = regnode(EXACTLY);
+
+ /*
+ * Append characters as long as:
+ * - there is no following multi, we then need the character in
+ * front of it as a single character operand
+ * - not running into a Magic character
+ * - "one_exactly" is not set
+ * But always emit at least one character. Might be a Multi,
+ * e.g., a "[" without matching "]".
+ */
+ for (len = 0; c != NUL && (len == 0
+ || (re_multi_type(peekchr()) == NOT_MULTI
+ && !one_exactly
+ && !is_Magic(c))); ++len)
+ {
+ c = no_Magic(c);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ regmbc(c);
+ if (enc_utf8)
+ {
+ int off;
+ int l;
+
+ /* Need to get composing character too, directly
+ * access regparse for that, because skipchr() skips
+ * over composing chars. */
+ ungetchr();
+ if (*regparse == '\\' && regparse[1] != NUL)
+ off = 1;
+ else
+ off = 0;
+ for (;;)
+ {
+ l = utf_ptr2len_check(regparse + off);
+ if (!UTF_COMPOSINGLIKE(regparse + off,
+ regparse + off + l))
+ break;
+ off += l;
+ regmbc(utf_ptr2char(regparse + off));
+ }
+ skipchr();
+ }
+ }
+ else
+#endif
+ regc(c);
+ c = getchr();
+ }
+ ungetchr();
+
+ regc(NUL);
+ *flagp |= HASWIDTH;
+ if (len == 1)
+ *flagp |= SIMPLE;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * emit a node
+ * Return pointer to generated code.
+ */
+ static char_u *
+regnode(op)
+ int op;
+{
+ char_u *ret;
+
+ ret = regcode;
+ if (ret == JUST_CALC_SIZE)
+ regsize += 3;
+ else
+ {
+ *regcode++ = op;
+ *regcode++ = NUL; /* Null "next" pointer. */
+ *regcode++ = NUL;
+ }
+ return ret;
+}
+
+/*
+ * Emit (if appropriate) a byte of code
+ */
+ static void
+regc(b)
+ int b;
+{
+ if (regcode == JUST_CALC_SIZE)
+ regsize++;
+ else
+ *regcode++ = b;
+}
+
+#ifdef FEAT_MBYTE
+/*
+ * Emit (if appropriate) a multi-byte character of code
+ */
+ static void
+regmbc(c)
+ int c;
+{
+ if (regcode == JUST_CALC_SIZE)
+ regsize += (*mb_char2len)(c);
+ else
+ regcode += (*mb_char2bytes)(c, regcode);
+}
+#endif
+
+/*
+ * reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+ static void
+reginsert(op, opnd)
+ int op;
+ char_u *opnd;
+{
+ char_u *src;
+ char_u *dst;
+ char_u *place;
+
+ if (regcode == JUST_CALC_SIZE)
+ {
+ regsize += 3;
+ return;
+ }
+ src = regcode;
+ regcode += 3;
+ dst = regcode;
+ while (src > opnd)
+ *--dst = *--src;
+
+ place = opnd; /* Op node, where operand used to be. */
+ *place++ = op;
+ *place++ = NUL;
+ *place = NUL;
+}
+
+/*
+ * reginsert_limits - insert an operator in front of already-emitted operand.
+ * The operator has the given limit values as operands. Also set next pointer.
+ *
+ * Means relocating the operand.
+ */
+ static void
+reginsert_limits(op, minval, maxval, opnd)
+ int op;
+ long minval;
+ long maxval;
+ char_u *opnd;
+{
+ char_u *src;
+ char_u *dst;
+ char_u *place;
+
+ if (regcode == JUST_CALC_SIZE)
+ {
+ regsize += 11;
+ return;
+ }
+ src = regcode;
+ regcode += 11;
+ dst = regcode;
+ while (src > opnd)
+ *--dst = *--src;
+
+ place = opnd; /* Op node, where operand used to be. */
+ *place++ = op;
+ *place++ = NUL;
+ *place++ = NUL;
+ place = re_put_long(place, (long_u)minval);
+ place = re_put_long(place, (long_u)maxval);
+ regtail(opnd, place);
+}
+
+/*
+ * Write a long as four bytes at "p" and return pointer to the next char.
+ */
+ static char_u *
+re_put_long(p, val)
+ char_u *p;
+ long_u val;
+{
+ *p++ = (char_u) ((val >> 24) & 0377);
+ *p++ = (char_u) ((val >> 16) & 0377);
+ *p++ = (char_u) ((val >> 8) & 0377);
+ *p++ = (char_u) (val & 0377);
+ return p;
+}
+
+/*
+ * regtail - set the next-pointer at the end of a node chain
+ */
+ static void
+regtail(p, val)
+ char_u *p;
+ char_u *val;
+{
+ char_u *scan;
+ char_u *temp;
+ int offset;
+
+ if (p == JUST_CALC_SIZE)
+ return;
+
+ /* Find last node. */
+ scan = p;
+ for (;;)
+ {
+ temp = regnext(scan);
+ if (temp == NULL)
+ break;
+ scan = temp;
+ }
+
+ if (OP(scan) == BACK)
+ offset = (int)(scan - val);
+ else
+ offset = (int)(val - scan);
+ *(scan + 1) = (char_u) (((unsigned)offset >> 8) & 0377);
+ *(scan + 2) = (char_u) (offset & 0377);
+}
+
+/*
+ * regoptail - regtail on item after a BRANCH; nop if none
+ */
+ static void
+regoptail(p, val)
+ char_u *p;
+ char_u *val;
+{
+ /* When op is neither BRANCH nor BRACE_COMPLEX0-9, it is "operandless" */
+ if (p == NULL || p == JUST_CALC_SIZE
+ || (OP(p) != BRANCH
+ && (OP(p) < BRACE_COMPLEX || OP(p) > BRACE_COMPLEX + 9)))
+ return;
+ regtail(OPERAND(p), val);
+}
+
+/*
+ * getchr() - get the next character from the pattern. We know about
+ * magic and such, so therefore we need a lexical analyzer.
+ */
+
+/* static int curchr; */
+static int prevprevchr;
+static int prevchr;
+static int nextchr; /* used for ungetchr() */
+/*
+ * Note: prevchr is sometimes -1 when we are not at the start,
+ * eg in /[ ^I]^ the pattern was never found even if it existed, because ^ was
+ * taken to be magic -- webb
+ */
+static int at_start; /* True when on the first character */
+static int prev_at_start; /* True when on the second character */
+
+ static void
+initchr(str)
+ char_u *str;
+{
+ regparse = str;
+ prevchr_len = 0;
+ curchr = prevprevchr = prevchr = nextchr = -1;
+ at_start = TRUE;
+ prev_at_start = FALSE;
+}
+
+ static int
+peekchr()
+{
+ if (curchr == -1)
+ {
+ switch (curchr = regparse[0])
+ {
+ case '.':
+ case '[':
+ case '~':
+ /* magic when 'magic' is on */
+ if (reg_magic >= MAGIC_ON)
+ curchr = Magic(curchr);
+ break;
+ case '(':
+ case ')':
+ case '{':
+ case '%':
+ case '+':
+ case '=':
+ case '?':
+ case '@':
+ case '!':
+ case '&':
+ case '|':
+ case '<':
+ case '>':
+ case '#': /* future ext. */
+ case '"': /* future ext. */
+ case '\'': /* future ext. */
+ case ',': /* future ext. */
+ case '-': /* future ext. */
+ case ':': /* future ext. */
+ case ';': /* future ext. */
+ case '`': /* future ext. */
+ case '/': /* Can't be used in / command */
+ /* magic only after "\v" */
+ if (reg_magic == MAGIC_ALL)
+ curchr = Magic(curchr);
+ break;
+ case '*':
+ /* * is not magic as the very first character, eg "?*ptr" and when
+ * after '^', eg "/^*ptr" */
+ if (reg_magic >= MAGIC_ON && !at_start
+ && !(prev_at_start && prevchr == Magic('^')))
+ curchr = Magic('*');
+ break;
+ case '^':
+ /* '^' is only magic as the very first character and if it's after
+ * "\(", "\|", "\&' or "\n" */
+ if (reg_magic >= MAGIC_OFF
+ && (at_start
+ || reg_magic == MAGIC_ALL
+ || prevchr == Magic('(')
+ || prevchr == Magic('|')
+ || prevchr == Magic('&')
+ || prevchr == Magic('n')
+ || (no_Magic(prevchr) == '('
+ && prevprevchr == Magic('%'))))
+ {
+ curchr = Magic('^');
+ at_start = TRUE;
+ prev_at_start = FALSE;
+ }
+ break;
+ case '$':
+ /* '$' is only magic as the very last char and if it's in front of
+ * either "\|", "\)", "\&", or "\n" */
+ if (reg_magic >= MAGIC_OFF)
+ {
+ char_u *p = regparse + 1;
+
+ /* ignore \c \C \m and \M after '$' */
+ while (p[0] == '\\' && (p[1] == 'c' || p[1] == 'C'
+ || p[1] == 'm' || p[1] == 'M' || p[1] == 'Z'))
+ p += 2;
+ if (p[0] == NUL
+ || (p[0] == '\\'
+ && (p[1] == '|' || p[1] == '&' || p[1] == ')'
+ || p[1] == 'n'))
+ || reg_magic == MAGIC_ALL)
+ curchr = Magic('$');
+ }
+ break;
+ case '\\':
+ {
+ int c = regparse[1];
+
+ if (c == NUL)
+ curchr = '\\'; /* trailing '\' */
+ else if (
+#ifdef EBCDIC
+ vim_strchr(META, c)
+#else
+ c <= '~' && META_flags[c]
+#endif
+ )
+ {
+ /*
+ * META contains everything that may be magic sometimes,
+ * except ^ and $ ("\^" and "\$" are only magic after
+ * "\v"). We now fetch the next character and toggle its
+ * magicness. Therefore, \ is so meta-magic that it is
+ * not in META.
+ */
+ curchr = -1;
+ prev_at_start = at_start;
+ at_start = FALSE; /* be able to say "/\*ptr" */
+ ++regparse;
+ peekchr();
+ --regparse;
+ curchr = toggle_Magic(curchr);
+ }
+ else if (vim_strchr(REGEXP_ABBR, c))
+ {
+ /*
+ * Handle abbreviations, like "\t" for TAB -- webb
+ */
+ curchr = backslash_trans(c);
+ }
+ else if (reg_magic == MAGIC_NONE && (c == '$' || c == '^'))
+ curchr = toggle_Magic(c);
+ else
+ {
+ /*
+ * Next character can never be (made) magic?
+ * Then backslashing it won't do anything.
+ */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ curchr = (*mb_ptr2char)(regparse + 1);
+ else
+#endif
+ curchr = c;
+ }
+ break;
+ }
+
+#ifdef FEAT_MBYTE
+ default:
+ if (has_mbyte)
+ curchr = (*mb_ptr2char)(regparse);
+#endif
+ }
+ }
+
+ return curchr;
+}
+
+/*
+ * Eat one lexed character. Do this in a way that we can undo it.
+ */
+ static void
+skipchr()
+{
+ /* peekchr() eats a backslash, do the same here */
+ if (*regparse == '\\')
+ prevchr_len = 1;
+ else
+ prevchr_len = 0;
+ if (regparse[prevchr_len] != NUL)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ prevchr_len += (*mb_ptr2len_check)(regparse + prevchr_len);
+ else
+#endif
+ ++prevchr_len;
+ }
+ regparse += prevchr_len;
+ prev_at_start = at_start;
+ at_start = FALSE;
+ prevprevchr = prevchr;
+ prevchr = curchr;
+ curchr = nextchr; /* use previously unget char, or -1 */
+ nextchr = -1;
+}
+
+/*
+ * Skip a character while keeping the value of prev_at_start for at_start.
+ * prevchr and prevprevchr are also kept.
+ */
+ static void
+skipchr_keepstart()
+{
+ int as = prev_at_start;
+ int pr = prevchr;
+ int prpr = prevprevchr;
+
+ skipchr();
+ at_start = as;
+ prevchr = pr;
+ prevprevchr = prpr;
+}
+
+ static int
+getchr()
+{
+ int chr = peekchr();
+
+ skipchr();
+ return chr;
+}
+
+/*
+ * put character back. Works only once!
+ */
+ static void
+ungetchr()
+{
+ nextchr = curchr;
+ curchr = prevchr;
+ prevchr = prevprevchr;
+ at_start = prev_at_start;
+ prev_at_start = FALSE;
+
+ /* Backup regparse, so that it's at the same position as before the
+ * getchr(). */
+ regparse -= prevchr_len;
+}
+
+/*
+ * read_limits - Read two integers to be taken as a minimum and maximum.
+ * If the first character is '-', then the range is reversed.
+ * Should end with 'end'. If minval is missing, zero is default, if maxval is
+ * missing, a very big number is the default.
+ */
+ static int
+read_limits(minval, maxval)
+ long *minval;
+ long *maxval;
+{
+ int reverse = FALSE;
+ char_u *first_char;
+ long tmp;
+
+ if (*regparse == '-')
+ {
+ /* Starts with '-', so reverse the range later */
+ regparse++;
+ reverse = TRUE;
+ }
+ first_char = regparse;
+ *minval = getdigits(&regparse);
+ if (*regparse == ',') /* There is a comma */
+ {
+ if (vim_isdigit(*++regparse))
+ *maxval = getdigits(&regparse);
+ else
+ *maxval = MAX_LIMIT;
+ }
+ else if (VIM_ISDIGIT(*first_char))
+ *maxval = *minval; /* It was \{n} or \{-n} */
+ else
+ *maxval = MAX_LIMIT; /* It was \{} or \{-} */
+ if (*regparse == '\\')
+ regparse++; /* Allow either \{...} or \{...\} */
+ if (*regparse != '}' || (*maxval == 0 && *minval == 0))
+ {
+ sprintf((char *)IObuff, _("E554: Syntax error in %s{...}"),
+ reg_magic == MAGIC_ALL ? "" : "\\");
+ EMSG_RET_FAIL(IObuff);
+ }
+
+ /*
+ * Reverse the range if there was a '-', or make sure it is in the right
+ * order otherwise.
+ */
+ if ((!reverse && *minval > *maxval) || (reverse && *minval < *maxval))
+ {
+ tmp = *minval;
+ *minval = *maxval;
+ *maxval = tmp;
+ }
+ skipchr(); /* let's be friends with the lexer again */
+ return OK;
+}
+
+/*
+ * vim_regexec and friends
+ */
+
+/*
+ * Global work variables for vim_regexec().
+ */
+
+/* The current match-position is remembered with these variables: */
+static linenr_T reglnum; /* line number, relative to first line */
+static char_u *regline; /* start of current line */
+static char_u *reginput; /* current input, points into "regline" */
+
+static int need_clear_subexpr; /* subexpressions still need to be
+ * cleared */
+#ifdef FEAT_SYN_HL
+static int need_clear_zsubexpr = FALSE; /* extmatch subexpressions
+ * still need to be cleared */
+#endif
+
+static int out_of_stack; /* TRUE when ran out of stack space */
+
+/*
+ * Structure used to save the current input state, when it needs to be
+ * restored after trying a match. Used by reg_save() and reg_restore().
+ */
+typedef struct
+{
+ union
+ {
+ char_u *ptr; /* reginput pointer, for single-line regexp */
+ lpos_T pos; /* reginput pos, for multi-line regexp */
+ } rs_u;
+} regsave_T;
+
+/* struct to save start/end pointer/position in for \(\) */
+typedef struct
+{
+ union
+ {
+ char_u *ptr;
+ lpos_T pos;
+ } se_u;
+} save_se_T;
+
+static char_u *reg_getline __ARGS((linenr_T lnum));
+static long vim_regexec_both __ARGS((char_u *line, colnr_T col));
+static long regtry __ARGS((regprog_T *prog, colnr_T col));
+static void cleanup_subexpr __ARGS((void));
+#ifdef FEAT_SYN_HL
+static void cleanup_zsubexpr __ARGS((void));
+#endif
+static void reg_nextline __ARGS((void));
+static void reg_save __ARGS((regsave_T *save));
+static void reg_restore __ARGS((regsave_T *save));
+static int reg_save_equal __ARGS((regsave_T *save));
+static void save_se_multi __ARGS((save_se_T *savep, lpos_T *posp));
+static void save_se_one __ARGS((save_se_T *savep, char_u **pp));
+
+/* Save the sub-expressions before attempting a match. */
+#define save_se(savep, posp, pp) \
+ REG_MULTI ? save_se_multi((savep), (posp)) : save_se_one((savep), (pp))
+
+/* After a failed match restore the sub-expressions. */
+#define restore_se(savep, posp, pp) { \
+ if (REG_MULTI) \
+ *(posp) = (savep)->se_u.pos; \
+ else \
+ *(pp) = (savep)->se_u.ptr; }
+
+static int re_num_cmp __ARGS((long_u val, char_u *scan));
+static int regmatch __ARGS((char_u *prog));
+static int regrepeat __ARGS((char_u *p, long maxcount));
+
+#ifdef DEBUG
+int regnarrate = 0;
+#endif
+
+/*
+ * Internal copy of 'ignorecase'. It is set at each call to vim_regexec().
+ * Normally it gets the value of "rm_ic" or "rmm_ic", but when the pattern
+ * contains '\c' or '\C' the value is overruled.
+ */
+static int ireg_ic;
+
+#ifdef FEAT_MBYTE
+/*
+ * Similar to ireg_ic, but only for 'combining' characters. Set with \Z flag
+ * in the regexp. Defaults to false, always.
+ */
+static int ireg_icombine;
+#endif
+
+/*
+ * Sometimes need to save a copy of a line. Since alloc()/free() is very
+ * slow, we keep one allocated piece of memory and only re-allocate it when
+ * it's too small. It's freed in vim_regexec_both() when finished.
+ */
+static char_u *reg_tofree;
+static unsigned reg_tofreelen;
+
+/*
+ * These variables are set when executing a regexp to speed up the execution.
+ * Which ones are set depends on whethere a single-line or multi-line match is
+ * done:
+ * single-line multi-line
+ * reg_match &regmatch_T NULL
+ * reg_mmatch NULL &regmmatch_T
+ * reg_startp reg_match->startp <invalid>
+ * reg_endp reg_match->endp <invalid>
+ * reg_startpos <invalid> reg_mmatch->startpos
+ * reg_endpos <invalid> reg_mmatch->endpos
+ * reg_win NULL window in which to search
+ * reg_buf <invalid> buffer in which to search
+ * reg_firstlnum <invalid> first line in which to search
+ * reg_maxline 0 last line nr
+ * reg_line_lbr FALSE or TRUE FALSE
+ */
+static regmatch_T *reg_match;
+static regmmatch_T *reg_mmatch;
+static char_u **reg_startp = NULL;
+static char_u **reg_endp = NULL;
+static lpos_T *reg_startpos = NULL;
+static lpos_T *reg_endpos = NULL;
+static win_T *reg_win;
+static buf_T *reg_buf;
+static linenr_T reg_firstlnum;
+static linenr_T reg_maxline;
+static int reg_line_lbr; /* "\n" in string is line break */
+
+/*
+ * Get pointer to the line "lnum", which is relative to "reg_firstlnum".
+ */
+ static char_u *
+reg_getline(lnum)
+ linenr_T lnum;
+{
+ /* when looking behind for a match/no-match lnum is negative. But we
+ * can't go before line 1 */
+ if (reg_firstlnum + lnum < 1)
+ return NULL;
+ return ml_get_buf(reg_buf, reg_firstlnum + lnum, FALSE);
+}
+
+static regsave_T behind_pos;
+
+#ifdef FEAT_SYN_HL
+static char_u *reg_startzp[NSUBEXP]; /* Workspace to mark beginning */
+static char_u *reg_endzp[NSUBEXP]; /* and end of \z(...\) matches */
+static lpos_T reg_startzpos[NSUBEXP]; /* idem, beginning pos */
+static lpos_T reg_endzpos[NSUBEXP]; /* idem, end pos */
+#endif
+
+/* TRUE if using multi-line regexp. */
+#define REG_MULTI (reg_match == NULL)
+
+/*
+ * Match a regexp against a string.
+ * "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
+ * Uses curbuf for line count and 'iskeyword'.
+ *
+ * Return TRUE if there is a match, FALSE if not.
+ */
+ int
+vim_regexec(rmp, line, col)
+ regmatch_T *rmp;
+ char_u *line; /* string to match against */
+ colnr_T col; /* column to start looking for match */
+{
+ reg_match = rmp;
+ reg_mmatch = NULL;
+ reg_maxline = 0;
+ reg_line_lbr = FALSE;
+ reg_win = NULL;
+ ireg_ic = rmp->rm_ic;
+#ifdef FEAT_MBYTE
+ ireg_icombine = FALSE;
+#endif
+ return (vim_regexec_both(line, col) != 0);
+}
+
+#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Like vim_regexec(), but consider a "\n" in "line" to be a line break.
+ */
+ int
+vim_regexec_nl(rmp, line, col)
+ regmatch_T *rmp;
+ char_u *line; /* string to match against */
+ colnr_T col; /* column to start looking for match */
+{
+ reg_match = rmp;
+ reg_mmatch = NULL;
+ reg_maxline = 0;
+ reg_line_lbr = TRUE;
+ reg_win = NULL;
+ ireg_ic = rmp->rm_ic;
+#ifdef FEAT_MBYTE
+ ireg_icombine = FALSE;
+#endif
+ return (vim_regexec_both(line, col) != 0);
+}
+#endif
+
+/*
+ * Match a regexp against multiple lines.
+ * "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
+ * Uses curbuf for line count and 'iskeyword'.
+ *
+ * Return zero if there is no match. Return number of lines contained in the
+ * match otherwise.
+ */
+ long
+vim_regexec_multi(rmp, win, buf, lnum, col)
+ regmmatch_T *rmp;
+ win_T *win; /* window in which to search or NULL */
+ buf_T *buf; /* buffer in which to search */
+ linenr_T lnum; /* nr of line to start looking for match */
+ colnr_T col; /* column to start looking for match */
+{
+ long r;
+ buf_T *save_curbuf = curbuf;
+
+ reg_match = NULL;
+ reg_mmatch = rmp;
+ reg_buf = buf;
+ reg_win = win;
+ reg_firstlnum = lnum;
+ reg_maxline = reg_buf->b_ml.ml_line_count - lnum;
+ reg_line_lbr = FALSE;
+ ireg_ic = rmp->rmm_ic;
+#ifdef FEAT_MBYTE
+ ireg_icombine = FALSE;
+#endif
+
+ /* Need to switch to buffer "buf" to make vim_iswordc() work. */
+ curbuf = buf;
+ r = vim_regexec_both(NULL, col);
+ curbuf = save_curbuf;
+
+ return r;
+}
+
+/*
+ * Match a regexp against a string ("line" points to the string) or multiple
+ * lines ("line" is NULL, use reg_getline()).
+ */
+#ifdef HAVE_SETJMP_H
+ static long
+vim_regexec_both(line_arg, col_arg)
+ char_u *line_arg;
+ colnr_T col_arg; /* column to start looking for match */
+#else
+ static long
+vim_regexec_both(line, col)
+ char_u *line;
+ colnr_T col; /* column to start looking for match */
+#endif
+{
+ regprog_T *prog;
+ char_u *s;
+ long retval;
+#ifdef HAVE_SETJMP_H
+ char_u *line;
+ colnr_T col;
+#endif
+
+ reg_tofree = NULL;
+
+#ifdef HAVE_TRY_EXCEPT
+ __try
+ {
+#endif
+
+#ifdef HAVE_SETJMP_H
+ /*
+ * Matching with a regexp may cause a very deep recursive call of
+ * regmatch(). Vim will crash when running out of stack space. Catch
+ * this here if the system supports it.
+ */
+ mch_startjmp();
+ if (SETJMP(lc_jump_env) != 0)
+ {
+ mch_didjmp();
+# ifdef SIGHASARG
+ if (lc_signal != SIGINT)
+# endif
+ EMSG(_("E361: Crash intercepted; regexp too complex?"));
+ retval = 0L;
+ goto theend;
+ }
+
+ /* Trick to avoid "might be clobbered by `longjmp'" warning from gcc. */
+ line = line_arg;
+ col = col_arg;
+#endif
+ retval = 0L;
+
+ if (REG_MULTI)
+ {
+ prog = reg_mmatch->regprog;
+ line = reg_getline((linenr_T)0);
+ reg_startpos = reg_mmatch->startpos;
+ reg_endpos = reg_mmatch->endpos;
+ }
+ else
+ {
+ prog = reg_match->regprog;
+ reg_startp = reg_match->startp;
+ reg_endp = reg_match->endp;
+ }
+
+ /* Be paranoid... */
+ if (prog == NULL || line == NULL)
+ {
+ EMSG(_(e_null));
+ goto theend;
+ }
+
+ /* Check validity of program. */
+ if (prog_magic_wrong())
+ goto theend;
+
+ /* If pattern contains "\c" or "\C": overrule value of ireg_ic */
+ if (prog->regflags & RF_ICASE)
+ ireg_ic = TRUE;
+ else if (prog->regflags & RF_NOICASE)
+ ireg_ic = FALSE;
+
+#ifdef FEAT_MBYTE
+ /* If pattern contains "\Z" overrule value of ireg_icombine */
+ if (prog->regflags & RF_ICOMBINE)
+ ireg_icombine = TRUE;
+#endif
+
+ /* If there is a "must appear" string, look for it. */
+ if (prog->regmust != NULL)
+ {
+ int c;
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ c = (*mb_ptr2char)(prog->regmust);
+ else
+#endif
+ c = *prog->regmust;
+ s = line + col;
+ while ((s = cstrchr(s, c)) != NULL)
+ {
+ if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0)
+ break; /* Found it. */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ s += (*mb_ptr2len_check)(s);
+ else
+#endif
+ ++s;
+ }
+ if (s == NULL) /* Not present. */
+ goto theend;
+ }
+
+ regline = line;
+ reglnum = 0;
+ out_of_stack = FALSE;
+
+ /* Simplest case: Anchored match need be tried only once. */
+ if (prog->reganch)
+ {
+ int c;
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ c = (*mb_ptr2char)(regline + col);
+ else
+#endif
+ c = regline[col];
+ if (prog->regstart == NUL
+ || prog->regstart == c
+ || (ireg_ic && ((
+#ifdef FEAT_MBYTE
+ (enc_utf8 && utf_fold(prog->regstart) == utf_fold(c)))
+ || (c < 255 && prog->regstart < 255 &&
+#endif
+ TOLOWER_LOC(prog->regstart) == TOLOWER_LOC(c)))))
+ retval = regtry(prog, col);
+ else
+ retval = 0;
+ }
+ else
+ {
+ /* Messy cases: unanchored match. */
+ while (!got_int && !out_of_stack)
+ {
+ if (prog->regstart != NUL)
+ {
+ /* Skip until the char we know it must start with. */
+ s = cstrchr(regline + col, prog->regstart);
+ if (s == NULL)
+ {
+ retval = 0;
+ break;
+ }
+ col = (int)(s - regline);
+ }
+
+ retval = regtry(prog, col);
+ if (retval > 0)
+ break;
+
+ /* if not currently on the first line, get it again */
+ if (reglnum != 0)
+ {
+ regline = reg_getline((linenr_T)0);
+ reglnum = 0;
+ }
+ if (regline[col] == NUL)
+ break;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ col += (*mb_ptr2len_check)(regline + col);
+ else
+#endif
+ ++col;
+ }
+ }
+
+ if (out_of_stack)
+ EMSG(_("E363: pattern caused out-of-stack error"));
+
+#ifdef HAVE_TRY_EXCEPT
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW)
+ {
+ RESETSTKOFLW();
+ EMSG(_("E363: pattern caused out-of-stack error"));
+ }
+ else
+ EMSG(_("E361: Crash intercepted; regexp too complex?"));
+ retval = 0L;
+ }
+#endif
+
+theend:
+ /* Didn't find a match. */
+ vim_free(reg_tofree);
+#ifdef HAVE_SETJMP_H
+ mch_endjmp();
+#endif
+ return retval;
+}
+
+#ifdef FEAT_SYN_HL
+static reg_extmatch_T *make_extmatch __ARGS((void));
+
+/*
+ * Create a new extmatch and mark it as referenced once.
+ */
+ static reg_extmatch_T *
+make_extmatch()
+{
+ reg_extmatch_T *em;
+
+ em = (reg_extmatch_T *)alloc_clear((unsigned)sizeof(reg_extmatch_T));
+ if (em != NULL)
+ em->refcnt = 1;
+ return em;
+}
+
+/*
+ * Add a reference to an extmatch.
+ */
+ reg_extmatch_T *
+ref_extmatch(em)
+ reg_extmatch_T *em;
+{
+ if (em != NULL)
+ em->refcnt++;
+ return em;
+}
+
+/*
+ * Remove a reference to an extmatch. If there are no references left, free
+ * the info.
+ */
+ void
+unref_extmatch(em)
+ reg_extmatch_T *em;
+{
+ int i;
+
+ if (em != NULL && --em->refcnt <= 0)
+ {
+ for (i = 0; i < NSUBEXP; ++i)
+ vim_free(em->matches[i]);
+ vim_free(em);
+ }
+}
+#endif
+
+/*
+ * regtry - try match of "prog" with at regline["col"].
+ * Returns 0 for failure, number of lines contained in the match otherwise.
+ */
+ static long
+regtry(prog, col)
+ regprog_T *prog;
+ colnr_T col;
+{
+ reginput = regline + col;
+ need_clear_subexpr = TRUE;
+#ifdef FEAT_SYN_HL
+ /* Clear the external match subpointers if necessary. */
+ if (prog->reghasz == REX_SET)
+ need_clear_zsubexpr = TRUE;
+#endif
+
+ if (regmatch(prog->program + 1))
+ {
+ cleanup_subexpr();
+ if (REG_MULTI)
+ {
+ if (reg_startpos[0].lnum < 0)
+ {
+ reg_startpos[0].lnum = 0;
+ reg_startpos[0].col = col;
+ }
+ if (reg_endpos[0].lnum < 0)
+ {
+ reg_endpos[0].lnum = reglnum;
+ reg_endpos[0].col = (int)(reginput - regline);
+ }
+ else
+ /* Use line number of "\ze". */
+ reglnum = reg_endpos[0].lnum;
+ }
+ else
+ {
+ if (reg_startp[0] == NULL)
+ reg_startp[0] = regline + col;
+ if (reg_endp[0] == NULL)
+ reg_endp[0] = reginput;
+ }
+#ifdef FEAT_SYN_HL
+ /* Package any found \z(...\) matches for export. Default is none. */
+ unref_extmatch(re_extmatch_out);
+ re_extmatch_out = NULL;
+
+ if (prog->reghasz == REX_SET)
+ {
+ int i;
+
+ cleanup_zsubexpr();
+ re_extmatch_out = make_extmatch();
+ for (i = 0; i < NSUBEXP; i++)
+ {
+ if (REG_MULTI)
+ {
+ /* Only accept single line matches. */
+ if (reg_startzpos[i].lnum >= 0
+ && reg_endzpos[i].lnum == reg_startzpos[i].lnum)
+ re_extmatch_out->matches[i] =
+ vim_strnsave(reg_getline(reg_startzpos[i].lnum)
+ + reg_startzpos[i].col,
+ reg_endzpos[i].col - reg_startzpos[i].col);
+ }
+ else
+ {
+ if (reg_startzp[i] != NULL && reg_endzp[i] != NULL)
+ re_extmatch_out->matches[i] =
+ vim_strnsave(reg_startzp[i],
+ (int)(reg_endzp[i] - reg_startzp[i]));
+ }
+ }
+ }
+#endif
+ return 1 + reglnum;
+ }
+ return 0;
+}
+
+#ifdef FEAT_MBYTE
+/* multi-byte: advance reginput with a function */
+# define ADVANCE_REGINPUT() advance_reginput()
+
+static void advance_reginput __ARGS((void));
+static int reg_prev_class __ARGS((void));
+
+ static void
+advance_reginput()
+{
+ if (has_mbyte)
+ reginput += (*mb_ptr2len_check)(reginput);
+ else
+ ++reginput;
+}
+
+/*
+ * Get class of previous character.
+ */
+ static int
+reg_prev_class()
+{
+ if (reginput > regline)
+ return mb_get_class(reginput - 1
+ - (*mb_head_off)(regline, reginput - 1));
+ return -1;
+}
+
+#else
+/* No multi-byte: It's too simple to make a function for. */
+# define ADVANCE_REGINPUT() ++reginput
+#endif
+
+/*
+ * The arguments from BRACE_LIMITS are stored here. They are actually local
+ * to regmatch(), but they are here to reduce the amount of stack space used
+ * (it can be called recursively many times).
+ */
+static long bl_minval;
+static long bl_maxval;
+
+/*
+ * regmatch - main matching routine
+ *
+ * Conceptually the strategy is simple: Check to see whether the current
+ * node matches, call self recursively to see whether the rest matches,
+ * and then act accordingly. In practice we make some effort to avoid
+ * recursion, in particular by going through "ordinary" nodes (that don't
+ * need to know whether the rest of the match failed) by a loop instead of
+ * by recursion.
+ *
+ * Returns TRUE when there is a match. Leaves reginput and reglnum just after
+ * the last matched character.
+ * Returns FALSE when there is no match. Leaves reginput and reglnum in an
+ * undefined state!
+ */
+ static int
+regmatch(scan)
+ char_u *scan; /* Current node. */
+{
+ char_u *next; /* Next node. */
+ int op;
+ int c;
+
+#ifdef HAVE_GETRLIMIT
+ /* Check if we are running out of stack space. Could be caused by
+ * recursively calling ourselves. */
+ if (out_of_stack || mch_stackcheck((char *)&op) == FAIL)
+ {
+ out_of_stack = TRUE;
+ return FALSE;
+ }
+#endif
+
+ /* Some patterns my cause a long time to match, even though they are not
+ * illegal. E.g., "\([a-z]\+\)\+Q". Allow breaking them with CTRL-C. */
+ fast_breakcheck();
+
+#ifdef DEBUG
+ if (scan != NULL && regnarrate)
+ {
+ mch_errmsg(regprop(scan));
+ mch_errmsg("(\n");
+ }
+#endif
+ while (scan != NULL)
+ {
+ if (got_int || out_of_stack)
+ return FALSE;
+#ifdef DEBUG
+ if (regnarrate)
+ {
+ mch_errmsg(regprop(scan));
+ mch_errmsg("...\n");
+# ifdef FEAT_SYN_HL
+ if (re_extmatch_in != NULL)
+ {
+ int i;
+
+ mch_errmsg(_("External submatches:\n"));
+ for (i = 0; i < NSUBEXP; i++)
+ {
+ mch_errmsg(" \"");
+ if (re_extmatch_in->matches[i] != NULL)
+ mch_errmsg(re_extmatch_in->matches[i]);
+ mch_errmsg("\"\n");
+ }
+ }
+# endif
+ }
+#endif
+ next = regnext(scan);
+
+ op = OP(scan);
+ /* Check for character class with NL added. */
+ if (WITH_NL(op) && *reginput == NUL && reglnum < reg_maxline)
+ {
+ reg_nextline();
+ }
+ else if (reg_line_lbr && WITH_NL(op) && *reginput == '\n')
+ {
+ ADVANCE_REGINPUT();
+ }
+ else
+ {
+ if (WITH_NL(op))
+ op -= ADD_NL;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ c = (*mb_ptr2char)(reginput);
+ else
+#endif
+ c = *reginput;
+ switch (op)
+ {
+ case BOL:
+ if (reginput != regline)
+ return FALSE;
+ break;
+
+ case EOL:
+ if (c != NUL)
+ return FALSE;
+ break;
+
+ case RE_BOF:
+ /* Passing -1 to the getline() function provided for the search
+ * should always return NULL if the current line is the first
+ * line of the file. */
+ if (reglnum != 0 || reginput != regline
+ || (REG_MULTI && reg_getline((linenr_T)-1) != NULL))
+ return FALSE;
+ break;
+
+ case RE_EOF:
+ if (reglnum != reg_maxline || c != NUL)
+ return FALSE;
+ break;
+
+ case CURSOR:
+ /* Check if the buffer is in a window and compare the
+ * reg_win->w_cursor position to the match position. */
+ if (reg_win == NULL
+ || (reglnum + reg_firstlnum != reg_win->w_cursor.lnum)
+ || ((colnr_T)(reginput - regline) != reg_win->w_cursor.col))
+ return FALSE;
+ break;
+
+ case RE_LNUM:
+ if (!REG_MULTI || !re_num_cmp((long_u)(reglnum + reg_firstlnum),
+ scan))
+ return FALSE;
+ break;
+
+ case RE_COL:
+ if (!re_num_cmp((long_u)(reginput - regline) + 1, scan))
+ return FALSE;
+ break;
+
+ case RE_VCOL:
+ if (!re_num_cmp((long_u)win_linetabsize(
+ reg_win == NULL ? curwin : reg_win,
+ regline, (colnr_T)(reginput - regline)) + 1, scan))
+ return FALSE;
+ break;
+
+ case BOW: /* \<word; reginput points to w */
+ if (c == NUL) /* Can't match at end of line */
+ return FALSE;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int this_class;
+
+ /* Get class of current and previous char (if it exists). */
+ this_class = mb_get_class(reginput);
+ if (this_class <= 1)
+ return FALSE; /* not on a word at all */
+ if (reg_prev_class() == this_class)
+ return FALSE; /* previous char is in same word */
+ }
+#endif
+ else
+ {
+ if (!vim_iswordc(c)
+ || (reginput > regline && vim_iswordc(reginput[-1])))
+ return FALSE;
+ }
+ break;
+
+ case EOW: /* word\>; reginput points after d */
+ if (reginput == regline) /* Can't match at start of line */
+ return FALSE;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int this_class, prev_class;
+
+ /* Get class of current and previous char (if it exists). */
+ this_class = mb_get_class(reginput);
+ prev_class = reg_prev_class();
+ if (this_class == prev_class)
+ return FALSE;
+ if (prev_class == 0 || prev_class == 1)
+ return FALSE;
+ }
+ else
+#endif
+ {
+ if (!vim_iswordc(reginput[-1]))
+ return FALSE;
+ if (reginput[0] != NUL && vim_iswordc(c))
+ return FALSE;
+ }
+ break; /* Matched with EOW */
+
+ case ANY:
+ if (c == NUL)
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case IDENT:
+ if (!vim_isIDc(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case SIDENT:
+ if (VIM_ISDIGIT(*reginput) || !vim_isIDc(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case KWORD:
+ if (!vim_iswordp(reginput))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case SKWORD:
+ if (VIM_ISDIGIT(*reginput) || !vim_iswordp(reginput))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case FNAME:
+ if (!vim_isfilec(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case SFNAME:
+ if (VIM_ISDIGIT(*reginput) || !vim_isfilec(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case PRINT:
+ if (ptr2cells(reginput) != 1)
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case SPRINT:
+ if (VIM_ISDIGIT(*reginput) || ptr2cells(reginput) != 1)
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case WHITE:
+ if (!vim_iswhite(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case NWHITE:
+ if (c == NUL || vim_iswhite(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case DIGIT:
+ if (!ri_digit(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case NDIGIT:
+ if (c == NUL || ri_digit(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case HEX:
+ if (!ri_hex(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case NHEX:
+ if (c == NUL || ri_hex(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case OCTAL:
+ if (!ri_octal(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case NOCTAL:
+ if (c == NUL || ri_octal(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case WORD:
+ if (!ri_word(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case NWORD:
+ if (c == NUL || ri_word(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case HEAD:
+ if (!ri_head(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case NHEAD:
+ if (c == NUL || ri_head(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case ALPHA:
+ if (!ri_alpha(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case NALPHA:
+ if (c == NUL || ri_alpha(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case LOWER:
+ if (!ri_lower(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case NLOWER:
+ if (c == NUL || ri_lower(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case UPPER:
+ if (!ri_upper(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case NUPPER:
+ if (c == NUL || ri_upper(c))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+ case EXACTLY:
+ {
+ int len;
+ char_u *opnd;
+
+ opnd = OPERAND(scan);
+ /* Inline the first byte, for speed. */
+ if (*opnd != *reginput
+ && (!ireg_ic || (
+#ifdef FEAT_MBYTE
+ !enc_utf8 &&
+#endif
+ TOLOWER_LOC(*opnd) != TOLOWER_LOC(*reginput))))
+ return FALSE;
+ if (*opnd == NUL)
+ {
+ /* match empty string always works; happens when "~" is
+ * empty. */
+ }
+ else if (opnd[1] == NUL
+#ifdef FEAT_MBYTE
+ && !(enc_utf8 && ireg_ic)
+#endif
+ )
+ ++reginput; /* matched a single char */
+ else
+ {
+ len = (int)STRLEN(opnd);
+ /* Need to match first byte again for multi-byte. */
+ if (cstrncmp(opnd, reginput, &len) != 0)
+ return FALSE;
+#ifdef FEAT_MBYTE
+ /* Check for following composing character. */
+ if (enc_utf8 && UTF_COMPOSINGLIKE(reginput, reginput + len))
+ {
+ /* raaron: This code makes a composing character get
+ * ignored, which is the correct behavior (sometimes)
+ * for voweled Hebrew texts. */
+ if (!ireg_icombine)
+ return FALSE;
+ }
+ else
+#endif
+ reginput += len;
+ }
+ }
+ break;
+
+ case ANYOF:
+ case ANYBUT:
+ if (c == NUL)
+ return FALSE;
+ if ((cstrchr(OPERAND(scan), c) == NULL) == (op == ANYOF))
+ return FALSE;
+ ADVANCE_REGINPUT();
+ break;
+
+#ifdef FEAT_MBYTE
+ case MULTIBYTECODE:
+ if (has_mbyte)
+ {
+ int i, len;
+ char_u *opnd;
+
+ opnd = OPERAND(scan);
+ /* Safety check (just in case 'encoding' was changed since
+ * compiling the program). */
+ if ((len = (*mb_ptr2len_check)(opnd)) < 2)
+ return FALSE;
+ for (i = 0; i < len; ++i)
+ if (opnd[i] != reginput[i])
+ return FALSE;
+ reginput += len;
+ }
+ else
+ return FALSE;
+ break;
+#endif
+
+ case NOTHING:
+ break;
+
+ case BACK:
+ break;
+
+ case MOPEN + 0: /* Match start: \zs */
+ case MOPEN + 1: /* \( */
+ case MOPEN + 2:
+ case MOPEN + 3:
+ case MOPEN + 4:
+ case MOPEN + 5:
+ case MOPEN + 6:
+ case MOPEN + 7:
+ case MOPEN + 8:
+ case MOPEN + 9:
+ {
+ int no;
+ save_se_T save;
+
+ no = op - MOPEN;
+ cleanup_subexpr();
+ save_se(&save, &reg_startpos[no], &reg_startp[no]);
+
+ if (regmatch(next))
+ return TRUE;
+
+ restore_se(&save, &reg_startpos[no], &reg_startp[no]);
+ return FALSE;
+ }
+ /* break; Not Reached */
+
+ case NOPEN: /* \%( */
+ case NCLOSE: /* \) after \%( */
+ if (regmatch(next))
+ return TRUE;
+ return FALSE;
+ /* break; Not Reached */
+
+#ifdef FEAT_SYN_HL
+ case ZOPEN + 1:
+ case ZOPEN + 2:
+ case ZOPEN + 3:
+ case ZOPEN + 4:
+ case ZOPEN + 5:
+ case ZOPEN + 6:
+ case ZOPEN + 7:
+ case ZOPEN + 8:
+ case ZOPEN + 9:
+ {
+ int no;
+ save_se_T save;
+
+ no = op - ZOPEN;
+ cleanup_zsubexpr();
+ save_se(&save, &reg_startzpos[no], &reg_startzp[no]);
+
+ if (regmatch(next))
+ return TRUE;
+
+ restore_se(&save, &reg_startzpos[no], &reg_startzp[no]);
+ return FALSE;
+ }
+ /* break; Not Reached */
+#endif
+
+ case MCLOSE + 0: /* Match end: \ze */
+ case MCLOSE + 1: /* \) */
+ case MCLOSE + 2:
+ case MCLOSE + 3:
+ case MCLOSE + 4:
+ case MCLOSE + 5:
+ case MCLOSE + 6:
+ case MCLOSE + 7:
+ case MCLOSE + 8:
+ case MCLOSE + 9:
+ {
+ int no;
+ save_se_T save;
+
+ no = op - MCLOSE;
+ cleanup_subexpr();
+ save_se(&save, &reg_endpos[no], &reg_endp[no]);
+
+ if (regmatch(next))
+ return TRUE;
+
+ restore_se(&save, &reg_endpos[no], &reg_endp[no]);
+ return FALSE;
+ }
+ /* break; Not Reached */
+
+#ifdef FEAT_SYN_HL
+ case ZCLOSE + 1: /* \) after \z( */
+ case ZCLOSE + 2:
+ case ZCLOSE + 3:
+ case ZCLOSE + 4:
+ case ZCLOSE + 5:
+ case ZCLOSE + 6:
+ case ZCLOSE + 7:
+ case ZCLOSE + 8:
+ case ZCLOSE + 9:
+ {
+ int no;
+ save_se_T save;
+
+ no = op - ZCLOSE;
+ cleanup_zsubexpr();
+ save_se(&save, &reg_endzpos[no], &reg_endzp[no]);
+
+ if (regmatch(next))
+ return TRUE;
+
+ restore_se(&save, &reg_endzpos[no], &reg_endzp[no]);
+ return FALSE;
+ }
+ /* break; Not Reached */
+#endif
+
+ case BACKREF + 1:
+ case BACKREF + 2:
+ case BACKREF + 3:
+ case BACKREF + 4:
+ case BACKREF + 5:
+ case BACKREF + 6:
+ case BACKREF + 7:
+ case BACKREF + 8:
+ case BACKREF + 9:
+ {
+ int no;
+ int len;
+ linenr_T clnum;
+ colnr_T ccol;
+ char_u *p;
+
+ no = op - BACKREF;
+ cleanup_subexpr();
+ if (!REG_MULTI) /* Single-line regexp */
+ {
+ if (reg_endp[no] == NULL)
+ {
+ /* Backref was not set: Match an empty string. */
+ len = 0;
+ }
+ else
+ {
+ /* Compare current input with back-ref in the same
+ * line. */
+ len = (int)(reg_endp[no] - reg_startp[no]);
+ if (cstrncmp(reg_startp[no], reginput, &len) != 0)
+ return FALSE;
+ }
+ }
+ else /* Multi-line regexp */
+ {
+ if (reg_endpos[no].lnum < 0)
+ {
+ /* Backref was not set: Match an empty string. */
+ len = 0;
+ }
+ else
+ {
+ if (reg_startpos[no].lnum == reglnum
+ && reg_endpos[no].lnum == reglnum)
+ {
+ /* Compare back-ref within the current line. */
+ len = reg_endpos[no].col - reg_startpos[no].col;
+ if (cstrncmp(regline + reg_startpos[no].col,
+ reginput, &len) != 0)
+ return FALSE;
+ }
+ else
+ {
+ /* Messy situation: Need to compare between two
+ * lines. */
+ ccol = reg_startpos[no].col;
+ clnum = reg_startpos[no].lnum;
+ for (;;)
+ {
+ /* Since getting one line may invalidate
+ * the other, need to make copy. Slow! */
+ if (regline != reg_tofree)
+ {
+ len = (int)STRLEN(regline);
+ if (reg_tofree == NULL
+ || len >= (int)reg_tofreelen)
+ {
+ len += 50; /* get some extra */
+ vim_free(reg_tofree);
+ reg_tofree = alloc(len);
+ if (reg_tofree == NULL)
+ return FALSE; /* out of memory! */
+ reg_tofreelen = len;
+ }
+ STRCPY(reg_tofree, regline);
+ reginput = reg_tofree
+ + (reginput - regline);
+ regline = reg_tofree;
+ }
+
+ /* Get the line to compare with. */
+ p = reg_getline(clnum);
+ if (clnum == reg_endpos[no].lnum)
+ len = reg_endpos[no].col - ccol;
+ else
+ len = (int)STRLEN(p + ccol);
+
+ if (cstrncmp(p + ccol, reginput, &len) != 0)
+ return FALSE; /* doesn't match */
+ if (clnum == reg_endpos[no].lnum)
+ break; /* match and at end! */
+ if (reglnum == reg_maxline)
+ return FALSE; /* text too short */
+
+ /* Advance to next line. */
+ reg_nextline();
+ ++clnum;
+ ccol = 0;
+ if (got_int || out_of_stack)
+ return FALSE;
+ }
+
+ /* found a match! Note that regline may now point
+ * to a copy of the line, that should not matter. */
+ }
+ }
+ }
+
+ /* Matched the backref, skip over it. */
+ reginput += len;
+ }
+ break;
+
+#ifdef FEAT_SYN_HL
+ case ZREF + 1:
+ case ZREF + 2:
+ case ZREF + 3:
+ case ZREF + 4:
+ case ZREF + 5:
+ case ZREF + 6:
+ case ZREF + 7:
+ case ZREF + 8:
+ case ZREF + 9:
+ {
+ int no;
+ int len;
+
+ cleanup_zsubexpr();
+ no = op - ZREF;
+ if (re_extmatch_in != NULL
+ && re_extmatch_in->matches[no] != NULL)
+ {
+ len = (int)STRLEN(re_extmatch_in->matches[no]);
+ if (cstrncmp(re_extmatch_in->matches[no],
+ reginput, &len) != 0)
+ return FALSE;
+ reginput += len;
+ }
+ else
+ {
+ /* Backref was not set: Match an empty string. */
+ }
+ }
+ break;
+#endif
+
+ case BRANCH:
+ {
+ if (OP(next) != BRANCH) /* No choice. */
+ next = OPERAND(scan); /* Avoid recursion. */
+ else
+ {
+ regsave_T save;
+
+ do
+ {
+ reg_save(&save);
+ if (regmatch(OPERAND(scan)))
+ return TRUE;
+ reg_restore(&save);
+ scan = regnext(scan);
+ } while (scan != NULL && OP(scan) == BRANCH);
+ return FALSE;
+ /* NOTREACHED */
+ }
+ }
+ break;
+
+ case BRACE_LIMITS:
+ {
+ int no;
+
+ if (OP(next) == BRACE_SIMPLE)
+ {
+ bl_minval = OPERAND_MIN(scan);
+ bl_maxval = OPERAND_MAX(scan);
+ }
+ else if (OP(next) >= BRACE_COMPLEX
+ && OP(next) < BRACE_COMPLEX + 10)
+ {
+ no = OP(next) - BRACE_COMPLEX;
+ brace_min[no] = OPERAND_MIN(scan);
+ brace_max[no] = OPERAND_MAX(scan);
+ brace_count[no] = 0;
+ }
+ else
+ {
+ EMSG(_(e_internal)); /* Shouldn't happen */
+ return FALSE;
+ }
+ }
+ break;
+
+ case BRACE_COMPLEX + 0:
+ case BRACE_COMPLEX + 1:
+ case BRACE_COMPLEX + 2:
+ case BRACE_COMPLEX + 3:
+ case BRACE_COMPLEX + 4:
+ case BRACE_COMPLEX + 5:
+ case BRACE_COMPLEX + 6:
+ case BRACE_COMPLEX + 7:
+ case BRACE_COMPLEX + 8:
+ case BRACE_COMPLEX + 9:
+ {
+ int no;
+ regsave_T save;
+
+ no = op - BRACE_COMPLEX;
+ ++brace_count[no];
+
+ /* If not matched enough times yet, try one more */
+ if (brace_count[no] <= (brace_min[no] <= brace_max[no]
+ ? brace_min[no] : brace_max[no]))
+ {
+ reg_save(&save);
+ if (regmatch(OPERAND(scan)))
+ return TRUE;
+ reg_restore(&save);
+ --brace_count[no]; /* failed, decrement match count */
+ return FALSE;
+ }
+
+ /* If matched enough times, may try matching some more */
+ if (brace_min[no] <= brace_max[no])
+ {
+ /* Range is the normal way around, use longest match */
+ if (brace_count[no] <= brace_max[no])
+ {
+ reg_save(&save);
+ if (regmatch(OPERAND(scan)))
+ return TRUE; /* matched some more times */
+ reg_restore(&save);
+ --brace_count[no]; /* matched just enough times */
+ /* continue with the items after \{} */
+ }
+ }
+ else
+ {
+ /* Range is backwards, use shortest match first */
+ if (brace_count[no] <= brace_min[no])
+ {
+ reg_save(&save);
+ if (regmatch(next))
+ return TRUE;
+ reg_restore(&save);
+ next = OPERAND(scan);
+ /* must try to match one more item */
+ }
+ }
+ }
+ break;
+
+ case BRACE_SIMPLE:
+ case STAR:
+ case PLUS:
+ {
+ int nextb; /* next byte */
+ int nextb_ic; /* next byte reverse case */
+ long count;
+ regsave_T save;
+ long minval;
+ long maxval;
+
+ /*
+ * Lookahead to avoid useless match attempts when we know
+ * what character comes next.
+ */
+ if (OP(next) == EXACTLY)
+ {
+ nextb = *OPERAND(next);
+ if (ireg_ic)
+ {
+ if (isupper(nextb))
+ nextb_ic = TOLOWER_LOC(nextb);
+ else
+ nextb_ic = TOUPPER_LOC(nextb);
+ }
+ else
+ nextb_ic = nextb;
+ }
+ else
+ {
+ nextb = NUL;
+ nextb_ic = NUL;
+ }
+ if (op != BRACE_SIMPLE)
+ {
+ minval = (op == STAR) ? 0 : 1;
+ maxval = MAX_LIMIT;
+ }
+ else
+ {
+ minval = bl_minval;
+ maxval = bl_maxval;
+ }
+
+ /*
+ * When maxval > minval, try matching as much as possible, up
+ * to maxval. When maxval < minval, try matching at least the
+ * minimal number (since the range is backwards, that's also
+ * maxval!).
+ */
+ count = regrepeat(OPERAND(scan), maxval);
+ if (got_int)
+ return FALSE;
+ if (minval <= maxval)
+ {
+ /* Range is the normal way around, use longest match */
+ while (count >= minval)
+ {
+ /* If it could match, try it. */
+ if (nextb == NUL || *reginput == nextb
+ || *reginput == nextb_ic)
+ {
+ reg_save(&save);
+ if (regmatch(next))
+ return TRUE;
+ reg_restore(&save);
+ }
+ /* Couldn't or didn't match -- back up one char. */
+ if (--count < minval)
+ break;
+ if (reginput == regline)
+ {
+ /* backup to last char of previous line */
+ --reglnum;
+ regline = reg_getline(reglnum);
+ /* Just in case regrepeat() didn't count right. */
+ if (regline == NULL)
+ return FALSE;
+ reginput = regline + STRLEN(regline);
+ fast_breakcheck();
+ if (got_int || out_of_stack)
+ return FALSE;
+ }
+ else
+ {
+ --reginput;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ reginput -= (*mb_head_off)(regline, reginput);
+#endif
+ }
+ }
+ }
+ else
+ {
+ /* Range is backwards, use shortest match first.
+ * Careful: maxval and minval are exchanged! */
+ if (count < maxval)
+ return FALSE;
+ for (;;)
+ {
+ /* If it could work, try it. */
+ if (nextb == NUL || *reginput == nextb
+ || *reginput == nextb_ic)
+ {
+ reg_save(&save);
+ if (regmatch(next))
+ return TRUE;
+ reg_restore(&save);
+ }
+ /* Couldn't or didn't match: try advancing one char. */
+ if (count == minval
+ || regrepeat(OPERAND(scan), 1L) == 0)
+ break;
+ ++count;
+ if (got_int || out_of_stack)
+ return FALSE;
+ }
+ }
+ return FALSE;
+ }
+ /* break; Not Reached */
+
+ case NOMATCH:
+ {
+ regsave_T save;
+
+ /* If the operand matches, we fail. Otherwise backup and
+ * continue with the next item. */
+ reg_save(&save);
+ if (regmatch(OPERAND(scan)))
+ return FALSE;
+ reg_restore(&save);
+ }
+ break;
+
+ case MATCH:
+ case SUBPAT:
+ {
+ regsave_T save;
+
+ /* If the operand doesn't match, we fail. Otherwise backup
+ * and continue with the next item. */
+ reg_save(&save);
+ if (!regmatch(OPERAND(scan)))
+ return FALSE;
+ if (op == MATCH) /* zero-width */
+ reg_restore(&save);
+ }
+ break;
+
+ case BEHIND:
+ case NOBEHIND:
+ {
+ regsave_T save_after, save_start;
+ regsave_T save_behind_pos;
+ int needmatch = (op == BEHIND);
+
+ /*
+ * Look back in the input of the operand matches or not. This
+ * must be done at every position in the input and checking if
+ * the match ends at the current position.
+ * First check if the next item matches, that's probably
+ * faster.
+ */
+ reg_save(&save_start);
+ if (regmatch(next))
+ {
+ /* save the position after the found match for next */
+ reg_save(&save_after);
+
+ /* start looking for a match with operand at the current
+ * postion. Go back one character until we find the
+ * result, hitting the start of the line or the previous
+ * line (for multi-line matching).
+ * Set behind_pos to where the match should end, BHPOS
+ * will match it. */
+ save_behind_pos = behind_pos;
+ behind_pos = save_start;
+ for (;;)
+ {
+ reg_restore(&save_start);
+ if (regmatch(OPERAND(scan))
+ && reg_save_equal(&behind_pos))
+ {
+ behind_pos = save_behind_pos;
+ /* found a match that ends where "next" started */
+ if (needmatch)
+ {
+ reg_restore(&save_after);
+ return TRUE;
+ }
+ return FALSE;
+ }
+ /*
+ * No match: Go back one character. May go to
+ * previous line once.
+ */
+ if (REG_MULTI)
+ {
+ if (save_start.rs_u.pos.col == 0)
+ {
+ if (save_start.rs_u.pos.lnum
+ < behind_pos.rs_u.pos.lnum
+ || reg_getline(
+ --save_start.rs_u.pos.lnum) == NULL)
+ break;
+ reg_restore(&save_start);
+ save_start.rs_u.pos.col =
+ (colnr_T)STRLEN(regline);
+ }
+ else
+ --save_start.rs_u.pos.col;
+ }
+ else
+ {
+ if (save_start.rs_u.ptr == regline)
+ break;
+ --save_start.rs_u.ptr;
+ }
+ }
+
+ /* NOBEHIND succeeds when no match was found */
+ behind_pos = save_behind_pos;
+ if (!needmatch)
+ {
+ reg_restore(&save_after);
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+
+ case BHPOS:
+ if (REG_MULTI)
+ {
+ if (behind_pos.rs_u.pos.col != (colnr_T)(reginput - regline)
+ || behind_pos.rs_u.pos.lnum != reglnum)
+ return FALSE;
+ }
+ else if (behind_pos.rs_u.ptr != reginput)
+ return FALSE;
+ break;
+
+ case NEWL:
+ if ((c != NUL || reglnum == reg_maxline)
+ && (c != '\n' || !reg_line_lbr))
+ return FALSE;
+ if (reg_line_lbr)
+ ADVANCE_REGINPUT();
+ else
+ reg_nextline();
+ break;
+
+ case END:
+ return TRUE; /* Success! */
+
+ default:
+ EMSG(_(e_re_corr));
+#ifdef DEBUG
+ printf("Illegal op code %d\n", op);
+#endif
+ return FALSE;
+ }
+ }
+
+ scan = next;
+ }
+
+ /*
+ * We get here only if there's trouble -- normally "case END" is the
+ * terminating point.
+ */
+ EMSG(_(e_re_corr));
+#ifdef DEBUG
+ printf("Premature EOL\n");
+#endif
+ return FALSE;
+}
+
+#ifdef FEAT_MBYTE
+# define ADVANCE_P(x) if (has_mbyte) x += (*mb_ptr2len_check)(x); else ++x
+#else
+# define ADVANCE_P(x) ++x
+#endif
+
+/*
+ * regrepeat - repeatedly match something simple, return how many.
+ * Advances reginput (and reglnum) to just after the matched chars.
+ */
+ static int
+regrepeat(p, maxcount)
+ char_u *p;
+ long maxcount; /* maximum number of matches allowed */
+{
+ long count = 0;
+ char_u *scan;
+ char_u *opnd;
+ int mask;
+ int testval = 0;
+
+ scan = reginput; /* Make local copy of reginput for speed. */
+ opnd = OPERAND(p);
+ switch (OP(p))
+ {
+ case ANY:
+ case ANY + ADD_NL:
+ while (count < maxcount)
+ {
+ /* Matching anything means we continue until end-of-line (or
+ * end-of-file for ANY + ADD_NL), only limited by maxcount. */
+ while (*scan != NUL && count < maxcount)
+ {
+ ++count;
+ ADVANCE_P(scan);
+ }
+ if (!WITH_NL(OP(p)) || reglnum == reg_maxline || count == maxcount)
+ break;
+ ++count; /* count the line-break */
+ reg_nextline();
+ scan = reginput;
+ if (got_int)
+ break;
+ }
+ break;
+
+ case IDENT:
+ case IDENT + ADD_NL:
+ testval = TRUE;
+ /*FALLTHROUGH*/
+ case SIDENT:
+ case SIDENT + ADD_NL:
+ while (count < maxcount)
+ {
+ if (vim_isIDc(*scan) && (testval || !VIM_ISDIGIT(*scan)))
+ {
+ ADVANCE_P(scan);
+ }
+ else if (*scan == NUL)
+ {
+ if (!WITH_NL(OP(p)) || reglnum == reg_maxline)
+ break;
+ reg_nextline();
+ scan = reginput;
+ if (got_int)
+ break;
+ }
+ else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
+ ++scan;
+ else
+ break;
+ ++count;
+ }
+ break;
+
+ case KWORD:
+ case KWORD + ADD_NL:
+ testval = TRUE;
+ /*FALLTHROUGH*/
+ case SKWORD:
+ case SKWORD + ADD_NL:
+ while (count < maxcount)
+ {
+ if (vim_iswordp(scan) && (testval || !VIM_ISDIGIT(*scan)))
+ {
+ ADVANCE_P(scan);
+ }
+ else if (*scan == NUL)
+ {
+ if (!WITH_NL(OP(p)) || reglnum == reg_maxline)
+ break;
+ reg_nextline();
+ scan = reginput;
+ if (got_int)
+ break;
+ }
+ else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
+ ++scan;
+ else
+ break;
+ ++count;
+ }
+ break;
+
+ case FNAME:
+ case FNAME + ADD_NL:
+ testval = TRUE;
+ /*FALLTHROUGH*/
+ case SFNAME:
+ case SFNAME + ADD_NL:
+ while (count < maxcount)
+ {
+ if (vim_isfilec(*scan) && (testval || !VIM_ISDIGIT(*scan)))
+ {
+ ADVANCE_P(scan);
+ }
+ else if (*scan == NUL)
+ {
+ if (!WITH_NL(OP(p)) || reglnum == reg_maxline)
+ break;
+ reg_nextline();
+ scan = reginput;
+ if (got_int)
+ break;
+ }
+ else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
+ ++scan;
+ else
+ break;
+ ++count;
+ }
+ break;
+
+ case PRINT:
+ case PRINT + ADD_NL:
+ testval = TRUE;
+ /*FALLTHROUGH*/
+ case SPRINT:
+ case SPRINT + ADD_NL:
+ while (count < maxcount)
+ {
+ if (*scan == NUL)
+ {
+ if (!WITH_NL(OP(p)) || reglnum == reg_maxline)
+ break;
+ reg_nextline();
+ scan = reginput;
+ if (got_int)
+ break;
+ }
+ else if (ptr2cells(scan) == 1 && (testval || !VIM_ISDIGIT(*scan)))
+ {
+ ADVANCE_P(scan);
+ }
+ else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
+ ++scan;
+ else
+ break;
+ ++count;
+ }
+ break;
+
+ case WHITE:
+ case WHITE + ADD_NL:
+ testval = mask = RI_WHITE;
+do_class:
+ while (count < maxcount)
+ {
+#ifdef FEAT_MBYTE
+ int l;
+#endif
+ if (*scan == NUL)
+ {
+ if (!WITH_NL(OP(p)) || reglnum == reg_maxline)
+ break;
+ reg_nextline();
+ scan = reginput;
+ if (got_int)
+ break;
+ }
+#ifdef FEAT_MBYTE
+ else if (has_mbyte && (l = (*mb_ptr2len_check)(scan)) > 1)
+ {
+ if (testval != 0)
+ break;
+ scan += l;
+ }
+#endif
+ else if ((class_tab[*scan] & mask) == testval)
+ ++scan;
+ else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
+ ++scan;
+ else
+ break;
+ ++count;
+ }
+ break;
+
+ case NWHITE:
+ case NWHITE + ADD_NL:
+ mask = RI_WHITE;
+ goto do_class;
+ case DIGIT:
+ case DIGIT + ADD_NL:
+ testval = mask = RI_DIGIT;
+ goto do_class;
+ case NDIGIT:
+ case NDIGIT + ADD_NL:
+ mask = RI_DIGIT;
+ goto do_class;
+ case HEX:
+ case HEX + ADD_NL:
+ testval = mask = RI_HEX;
+ goto do_class;
+ case NHEX:
+ case NHEX + ADD_NL:
+ mask = RI_HEX;
+ goto do_class;
+ case OCTAL:
+ case OCTAL + ADD_NL:
+ testval = mask = RI_OCTAL;
+ goto do_class;
+ case NOCTAL:
+ case NOCTAL + ADD_NL:
+ mask = RI_OCTAL;
+ goto do_class;
+ case WORD:
+ case WORD + ADD_NL:
+ testval = mask = RI_WORD;
+ goto do_class;
+ case NWORD:
+ case NWORD + ADD_NL:
+ mask = RI_WORD;
+ goto do_class;
+ case HEAD:
+ case HEAD + ADD_NL:
+ testval = mask = RI_HEAD;
+ goto do_class;
+ case NHEAD:
+ case NHEAD + ADD_NL:
+ mask = RI_HEAD;
+ goto do_class;
+ case ALPHA:
+ case ALPHA + ADD_NL:
+ testval = mask = RI_ALPHA;
+ goto do_class;
+ case NALPHA:
+ case NALPHA + ADD_NL:
+ mask = RI_ALPHA;
+ goto do_class;
+ case LOWER:
+ case LOWER + ADD_NL:
+ testval = mask = RI_LOWER;
+ goto do_class;
+ case NLOWER:
+ case NLOWER + ADD_NL:
+ mask = RI_LOWER;
+ goto do_class;
+ case UPPER:
+ case UPPER + ADD_NL:
+ testval = mask = RI_UPPER;
+ goto do_class;
+ case NUPPER:
+ case NUPPER + ADD_NL:
+ mask = RI_UPPER;
+ goto do_class;
+
+ case EXACTLY:
+ {
+ int cu, cl;
+
+ /* This doesn't do a multi-byte character, because a MULTIBYTECODE
+ * would have been used for it. */
+ if (ireg_ic)
+ {
+ cu = TOUPPER_LOC(*opnd);
+ cl = TOLOWER_LOC(*opnd);
+ while (count < maxcount && (*scan == cu || *scan == cl))
+ {
+ count++;
+ scan++;
+ }
+ }
+ else
+ {
+ cu = *opnd;
+ while (count < maxcount && *scan == cu)
+ {
+ count++;
+ scan++;
+ }
+ }
+ break;
+ }
+
+#ifdef FEAT_MBYTE
+ case MULTIBYTECODE:
+ {
+ int i, len, cf = 0;
+
+ /* Safety check (just in case 'encoding' was changed since
+ * compiling the program). */
+ if ((len = (*mb_ptr2len_check)(opnd)) > 1)
+ {
+ if (ireg_ic && enc_utf8)
+ cf = utf_fold(utf_ptr2char(opnd));
+ while (count < maxcount)
+ {
+ for (i = 0; i < len; ++i)
+ if (opnd[i] != scan[i])
+ break;
+ if (i < len && (!ireg_ic || !enc_utf8
+ || utf_fold(utf_ptr2char(scan)) != cf))
+ break;
+ scan += len;
+ ++count;
+ }
+ }
+ }
+ break;
+#endif
+
+ case ANYOF:
+ case ANYOF + ADD_NL:
+ testval = TRUE;
+ /*FALLTHROUGH*/
+
+ case ANYBUT:
+ case ANYBUT + ADD_NL:
+ while (count < maxcount)
+ {
+#ifdef FEAT_MBYTE
+ int len;
+#endif
+ if (*scan == NUL)
+ {
+ if (!WITH_NL(OP(p)) || reglnum == reg_maxline)
+ break;
+ reg_nextline();
+ scan = reginput;
+ if (got_int)
+ break;
+ }
+ else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
+ ++scan;
+#ifdef FEAT_MBYTE
+ else if (has_mbyte && (len = (*mb_ptr2len_check)(scan)) > 1)
+ {
+ if ((cstrchr(opnd, (*mb_ptr2char)(scan)) == NULL) == testval)
+ break;
+ scan += len;
+ }
+#endif
+ else
+ {
+ if ((cstrchr(opnd, *scan) == NULL) == testval)
+ break;
+ ++scan;
+ }
+ ++count;
+ }
+ break;
+
+ case NEWL:
+ while (count < maxcount
+ && ((*scan == NUL && reglnum < reg_maxline)
+ || (*scan == '\n' && reg_line_lbr)))
+ {
+ count++;
+ if (reg_line_lbr)
+ ADVANCE_REGINPUT();
+ else
+ reg_nextline();
+ scan = reginput;
+ if (got_int)
+ break;
+ }
+ break;
+
+ default: /* Oh dear. Called inappropriately. */
+ EMSG(_(e_re_corr));
+#ifdef DEBUG
+ printf("Called regrepeat with op code %d\n", OP(p));
+#endif
+ break;
+ }
+
+ reginput = scan;
+
+ return (int)count;
+}
+
+/*
+ * regnext - dig the "next" pointer out of a node
+ */
+ static char_u *
+regnext(p)
+ char_u *p;
+{
+ int offset;
+
+ if (p == JUST_CALC_SIZE)
+ return NULL;
+
+ offset = NEXT(p);
+ if (offset == 0)
+ return NULL;
+
+ if (OP(p) == BACK)
+ return p - offset;
+ else
+ return p + offset;
+}
+
+/*
+ * Check the regexp program for its magic number.
+ * Return TRUE if it's wrong.
+ */
+ static int
+prog_magic_wrong()
+{
+ if (UCHARAT(REG_MULTI
+ ? reg_mmatch->regprog->program
+ : reg_match->regprog->program) != REGMAGIC)
+ {
+ EMSG(_(e_re_corr));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Cleanup the subexpressions, if this wasn't done yet.
+ * This construction is used to clear the subexpressions only when they are
+ * used (to increase speed).
+ */
+ static void
+cleanup_subexpr()
+{
+ if (need_clear_subexpr)
+ {
+ if (REG_MULTI)
+ {
+ /* Use 0xff to set lnum to -1 */
+ vim_memset(reg_startpos, 0xff, sizeof(lpos_T) * NSUBEXP);
+ vim_memset(reg_endpos, 0xff, sizeof(lpos_T) * NSUBEXP);
+ }
+ else
+ {
+ vim_memset(reg_startp, 0, sizeof(char_u *) * NSUBEXP);
+ vim_memset(reg_endp, 0, sizeof(char_u *) * NSUBEXP);
+ }
+ need_clear_subexpr = FALSE;
+ }
+}
+
+#ifdef FEAT_SYN_HL
+ static void
+cleanup_zsubexpr()
+{
+ if (need_clear_zsubexpr)
+ {
+ if (REG_MULTI)
+ {
+ /* Use 0xff to set lnum to -1 */
+ vim_memset(reg_startzpos, 0xff, sizeof(lpos_T) * NSUBEXP);
+ vim_memset(reg_endzpos, 0xff, sizeof(lpos_T) * NSUBEXP);
+ }
+ else
+ {
+ vim_memset(reg_startzp, 0, sizeof(char_u *) * NSUBEXP);
+ vim_memset(reg_endzp, 0, sizeof(char_u *) * NSUBEXP);
+ }
+ need_clear_zsubexpr = FALSE;
+ }
+}
+#endif
+
+/*
+ * Advance reglnum, regline and reginput to the next line.
+ */
+ static void
+reg_nextline()
+{
+ regline = reg_getline(++reglnum);
+ reginput = regline;
+ fast_breakcheck();
+}
+
+/*
+ * Save the input line and position in a regsave_T.
+ */
+ static void
+reg_save(save)
+ regsave_T *save;
+{
+ if (REG_MULTI)
+ {
+ save->rs_u.pos.col = (colnr_T)(reginput - regline);
+ save->rs_u.pos.lnum = reglnum;
+ }
+ else
+ save->rs_u.ptr = reginput;
+}
+
+/*
+ * Restore the input line and position from a regsave_T.
+ */
+ static void
+reg_restore(save)
+ regsave_T *save;
+{
+ if (REG_MULTI)
+ {
+ if (reglnum != save->rs_u.pos.lnum)
+ {
+ /* only call reg_getline() when the line number changed to save
+ * a bit of time */
+ reglnum = save->rs_u.pos.lnum;
+ regline = reg_getline(reglnum);
+ }
+ reginput = regline + save->rs_u.pos.col;
+ }
+ else
+ reginput = save->rs_u.ptr;
+}
+
+/*
+ * Return TRUE if current position is equal to saved position.
+ */
+ static int
+reg_save_equal(save)
+ regsave_T *save;
+{
+ if (REG_MULTI)
+ return reglnum == save->rs_u.pos.lnum
+ && reginput == regline + save->rs_u.pos.col;
+ return reginput == save->rs_u.ptr;
+}
+
+/*
+ * Tentatively set the sub-expression start to the current position (after
+ * calling regmatch() they will have changed). Need to save the existing
+ * values for when there is no match.
+ * Use se_save() to use pointer (save_se_multi()) or position (save_se_one()),
+ * depending on REG_MULTI.
+ */
+ static void
+save_se_multi(savep, posp)
+ save_se_T *savep;
+ lpos_T *posp;
+{
+ savep->se_u.pos = *posp;
+ posp->lnum = reglnum;
+ posp->col = (colnr_T)(reginput - regline);
+}
+
+ static void
+save_se_one(savep, pp)
+ save_se_T *savep;
+ char_u **pp;
+{
+ savep->se_u.ptr = *pp;
+ *pp = reginput;
+}
+
+/*
+ * Compare a number with the operand of RE_LNUM, RE_COL or RE_VCOL.
+ */
+ static int
+re_num_cmp(val, scan)
+ long_u val;
+ char_u *scan;
+{
+ long_u n = OPERAND_MIN(scan);
+
+ if (OPERAND_CMP(scan) == '>')
+ return val > n;
+ if (OPERAND_CMP(scan) == '<')
+ return val < n;
+ return val == n;
+}
+
+
+#ifdef DEBUG
+
+/*
+ * regdump - dump a regexp onto stdout in vaguely comprehensible form
+ */
+ static void
+regdump(pattern, r)
+ char_u *pattern;
+ regprog_T *r;
+{
+ char_u *s;
+ int op = EXACTLY; /* Arbitrary non-END op. */
+ char_u *next;
+ char_u *end = NULL;
+
+ printf("\r\nregcomp(%s):\r\n", pattern);
+
+ s = r->program + 1;
+ /*
+ * Loop until we find the END that isn't before a referred next (an END
+ * can also appear in a NOMATCH operand).
+ */
+ while (op != END || s <= end)
+ {
+ op = OP(s);
+ printf("%2d%s", (int)(s - r->program), regprop(s)); /* Where, what. */
+ next = regnext(s);
+ if (next == NULL) /* Next ptr. */
+ printf("(0)");
+ else
+ printf("(%d)", (int)((s - r->program) + (next - s)));
+ if (end < next)
+ end = next;
+ if (op == BRACE_LIMITS)
+ {
+ /* Two short ints */
+ printf(" minval %ld, maxval %ld", OPERAND_MIN(s), OPERAND_MAX(s));
+ s += 8;
+ }
+ s += 3;
+ if (op == ANYOF || op == ANYOF + ADD_NL
+ || op == ANYBUT || op == ANYBUT + ADD_NL
+ || op == EXACTLY)
+ {
+ /* Literal string, where present. */
+ while (*s != NUL)
+ printf("%c", *s++);
+ s++;
+ }
+ printf("\r\n");
+ }
+
+ /* Header fields of interest. */
+ if (r->regstart != NUL)
+ printf("start `%s' 0x%x; ", r->regstart < 256
+ ? (char *)transchar(r->regstart)
+ : "multibyte", r->regstart);
+ if (r->reganch)
+ printf("anchored; ");
+ if (r->regmust != NULL)
+ printf("must have \"%s\"", r->regmust);
+ printf("\r\n");
+}
+
+/*
+ * regprop - printable representation of opcode
+ */
+ static char_u *
+regprop(op)
+ char_u *op;
+{
+ char_u *p;
+ static char_u buf[50];
+
+ (void) strcpy(buf, ":");
+
+ switch (OP(op))
+ {
+ case BOL:
+ p = "BOL";
+ break;
+ case EOL:
+ p = "EOL";
+ break;
+ case RE_BOF:
+ p = "BOF";
+ break;
+ case RE_EOF:
+ p = "EOF";
+ break;
+ case CURSOR:
+ p = "CURSOR";
+ break;
+ case RE_LNUM:
+ p = "RE_LNUM";
+ break;
+ case RE_COL:
+ p = "RE_COL";
+ break;
+ case RE_VCOL:
+ p = "RE_VCOL";
+ break;
+ case BOW:
+ p = "BOW";
+ break;
+ case EOW:
+ p = "EOW";
+ break;
+ case ANY:
+ p = "ANY";
+ break;
+ case ANY + ADD_NL:
+ p = "ANY+NL";
+ break;
+ case ANYOF:
+ p = "ANYOF";
+ break;
+ case ANYOF + ADD_NL:
+ p = "ANYOF+NL";
+ break;
+ case ANYBUT:
+ p = "ANYBUT";
+ break;
+ case ANYBUT + ADD_NL:
+ p = "ANYBUT+NL";
+ break;
+ case IDENT:
+ p = "IDENT";
+ break;
+ case IDENT + ADD_NL:
+ p = "IDENT+NL";
+ break;
+ case SIDENT:
+ p = "SIDENT";
+ break;
+ case SIDENT + ADD_NL:
+ p = "SIDENT+NL";
+ break;
+ case KWORD:
+ p = "KWORD";
+ break;
+ case KWORD + ADD_NL:
+ p = "KWORD+NL";
+ break;
+ case SKWORD:
+ p = "SKWORD";
+ break;
+ case SKWORD + ADD_NL:
+ p = "SKWORD+NL";
+ break;
+ case FNAME:
+ p = "FNAME";
+ break;
+ case FNAME + ADD_NL:
+ p = "FNAME+NL";
+ break;
+ case SFNAME:
+ p = "SFNAME";
+ break;
+ case SFNAME + ADD_NL:
+ p = "SFNAME+NL";
+ break;
+ case PRINT:
+ p = "PRINT";
+ break;
+ case PRINT + ADD_NL:
+ p = "PRINT+NL";
+ break;
+ case SPRINT:
+ p = "SPRINT";
+ break;
+ case SPRINT + ADD_NL:
+ p = "SPRINT+NL";
+ break;
+ case WHITE:
+ p = "WHITE";
+ break;
+ case WHITE + ADD_NL:
+ p = "WHITE+NL";
+ break;
+ case NWHITE:
+ p = "NWHITE";
+ break;
+ case NWHITE + ADD_NL:
+ p = "NWHITE+NL";
+ break;
+ case DIGIT:
+ p = "DIGIT";
+ break;
+ case DIGIT + ADD_NL:
+ p = "DIGIT+NL";
+ break;
+ case NDIGIT:
+ p = "NDIGIT";
+ break;
+ case NDIGIT + ADD_NL:
+ p = "NDIGIT+NL";
+ break;
+ case HEX:
+ p = "HEX";
+ break;
+ case HEX + ADD_NL:
+ p = "HEX+NL";
+ break;
+ case NHEX:
+ p = "NHEX";
+ break;
+ case NHEX + ADD_NL:
+ p = "NHEX+NL";
+ break;
+ case OCTAL:
+ p = "OCTAL";
+ break;
+ case OCTAL + ADD_NL:
+ p = "OCTAL+NL";
+ break;
+ case NOCTAL:
+ p = "NOCTAL";
+ break;
+ case NOCTAL + ADD_NL:
+ p = "NOCTAL+NL";
+ break;
+ case WORD:
+ p = "WORD";
+ break;
+ case WORD + ADD_NL:
+ p = "WORD+NL";
+ break;
+ case NWORD:
+ p = "NWORD";
+ break;
+ case NWORD + ADD_NL:
+ p = "NWORD+NL";
+ break;
+ case HEAD:
+ p = "HEAD";
+ break;
+ case HEAD + ADD_NL:
+ p = "HEAD+NL";
+ break;
+ case NHEAD:
+ p = "NHEAD";
+ break;
+ case NHEAD + ADD_NL:
+ p = "NHEAD+NL";
+ break;
+ case ALPHA:
+ p = "ALPHA";
+ break;
+ case ALPHA + ADD_NL:
+ p = "ALPHA+NL";
+ break;
+ case NALPHA:
+ p = "NALPHA";
+ break;
+ case NALPHA + ADD_NL:
+ p = "NALPHA+NL";
+ break;
+ case LOWER:
+ p = "LOWER";
+ break;
+ case LOWER + ADD_NL:
+ p = "LOWER+NL";
+ break;
+ case NLOWER:
+ p = "NLOWER";
+ break;
+ case NLOWER + ADD_NL:
+ p = "NLOWER+NL";
+ break;
+ case UPPER:
+ p = "UPPER";
+ break;
+ case UPPER + ADD_NL:
+ p = "UPPER+NL";
+ break;
+ case NUPPER:
+ p = "NUPPER";
+ break;
+ case NUPPER + ADD_NL:
+ p = "NUPPER+NL";
+ break;
+ case BRANCH:
+ p = "BRANCH";
+ break;
+ case EXACTLY:
+ p = "EXACTLY";
+ break;
+ case NOTHING:
+ p = "NOTHING";
+ break;
+ case BACK:
+ p = "BACK";
+ break;
+ case END:
+ p = "END";
+ break;
+ case MOPEN + 0:
+ p = "MATCH START";
+ break;
+ case MOPEN + 1:
+ case MOPEN + 2:
+ case MOPEN + 3:
+ case MOPEN + 4:
+ case MOPEN + 5:
+ case MOPEN + 6:
+ case MOPEN + 7:
+ case MOPEN + 8:
+ case MOPEN + 9:
+ sprintf(buf + STRLEN(buf), "MOPEN%d", OP(op) - MOPEN);
+ p = NULL;
+ break;
+ case MCLOSE + 0:
+ p = "MATCH END";
+ break;
+ case MCLOSE + 1:
+ case MCLOSE + 2:
+ case MCLOSE + 3:
+ case MCLOSE + 4:
+ case MCLOSE + 5:
+ case MCLOSE + 6:
+ case MCLOSE + 7:
+ case MCLOSE + 8:
+ case MCLOSE + 9:
+ sprintf(buf + STRLEN(buf), "MCLOSE%d", OP(op) - MCLOSE);
+ p = NULL;
+ break;
+ case BACKREF + 1:
+ case BACKREF + 2:
+ case BACKREF + 3:
+ case BACKREF + 4:
+ case BACKREF + 5:
+ case BACKREF + 6:
+ case BACKREF + 7:
+ case BACKREF + 8:
+ case BACKREF + 9:
+ sprintf(buf + STRLEN(buf), "BACKREF%d", OP(op) - BACKREF);
+ p = NULL;
+ break;
+ case NOPEN:
+ p = "NOPEN";
+ break;
+ case NCLOSE:
+ p = "NCLOSE";
+ break;
+#ifdef FEAT_SYN_HL
+ case ZOPEN + 1:
+ case ZOPEN + 2:
+ case ZOPEN + 3:
+ case ZOPEN + 4:
+ case ZOPEN + 5:
+ case ZOPEN + 6:
+ case ZOPEN + 7:
+ case ZOPEN + 8:
+ case ZOPEN + 9:
+ sprintf(buf + STRLEN(buf), "ZOPEN%d", OP(op) - ZOPEN);
+ p = NULL;
+ break;
+ case ZCLOSE + 1:
+ case ZCLOSE + 2:
+ case ZCLOSE + 3:
+ case ZCLOSE + 4:
+ case ZCLOSE + 5:
+ case ZCLOSE + 6:
+ case ZCLOSE + 7:
+ case ZCLOSE + 8:
+ case ZCLOSE + 9:
+ sprintf(buf + STRLEN(buf), "ZCLOSE%d", OP(op) - ZCLOSE);
+ p = NULL;
+ break;
+ case ZREF + 1:
+ case ZREF + 2:
+ case ZREF + 3:
+ case ZREF + 4:
+ case ZREF + 5:
+ case ZREF + 6:
+ case ZREF + 7:
+ case ZREF + 8:
+ case ZREF + 9:
+ sprintf(buf + STRLEN(buf), "ZREF%d", OP(op) - ZREF);
+ p = NULL;
+ break;
+#endif
+ case STAR:
+ p = "STAR";
+ break;
+ case PLUS:
+ p = "PLUS";
+ break;
+ case NOMATCH:
+ p = "NOMATCH";
+ break;
+ case MATCH:
+ p = "MATCH";
+ break;
+ case BEHIND:
+ p = "BEHIND";
+ break;
+ case NOBEHIND:
+ p = "NOBEHIND";
+ break;
+ case SUBPAT:
+ p = "SUBPAT";
+ break;
+ case BRACE_LIMITS:
+ p = "BRACE_LIMITS";
+ break;
+ case BRACE_SIMPLE:
+ p = "BRACE_SIMPLE";
+ break;
+ case BRACE_COMPLEX + 0:
+ case BRACE_COMPLEX + 1:
+ case BRACE_COMPLEX + 2:
+ case BRACE_COMPLEX + 3:
+ case BRACE_COMPLEX + 4:
+ case BRACE_COMPLEX + 5:
+ case BRACE_COMPLEX + 6:
+ case BRACE_COMPLEX + 7:
+ case BRACE_COMPLEX + 8:
+ case BRACE_COMPLEX + 9:
+ sprintf(buf + STRLEN(buf), "BRACE_COMPLEX%d", OP(op) - BRACE_COMPLEX);
+ p = NULL;
+ break;
+#ifdef FEAT_MBYTE
+ case MULTIBYTECODE:
+ p = "MULTIBYTECODE";
+ break;
+#endif
+ case NEWL:
+ p = "NEWL";
+ break;
+ default:
+ sprintf(buf + STRLEN(buf), "corrupt %d", OP(op));
+ p = NULL;
+ break;
+ }
+ if (p != NULL)
+ (void) strcat(buf, p);
+ return buf;
+}
+#endif
+
+#ifdef FEAT_MBYTE
+static void mb_decompose __ARGS((int c, int *c1, int *c2, int *c3));
+
+typedef struct
+{
+ int a, b, c;
+} decomp_T;
+
+
+/* 0xfb20 - 0xfb4f */
+decomp_T decomp_table[0xfb4f-0xfb20+1] =
+{
+ {0x5e2,0,0}, /* 0xfb20 alt ayin */
+ {0x5d0,0,0}, /* 0xfb21 alt alef */
+ {0x5d3,0,0}, /* 0xfb22 alt dalet */
+ {0x5d4,0,0}, /* 0xfb23 alt he */
+ {0x5db,0,0}, /* 0xfb24 alt kaf */
+ {0x5dc,0,0}, /* 0xfb25 alt lamed */
+ {0x5dd,0,0}, /* 0xfb26 alt mem-sofit */
+ {0x5e8,0,0}, /* 0xfb27 alt resh */
+ {0x5ea,0,0}, /* 0xfb28 alt tav */
+ {'+', 0, 0}, /* 0xfb29 alt plus */
+ {0x5e9, 0x5c1, 0}, /* 0xfb2a shin+shin-dot */
+ {0x5e9, 0x5c2, 0}, /* 0xfb2b shin+sin-dot */
+ {0x5e9, 0x5c1, 0x5bc}, /* 0xfb2c shin+shin-dot+dagesh */
+ {0x5e9, 0x5c2, 0x5bc}, /* 0xfb2d shin+sin-dot+dagesh */
+ {0x5d0, 0x5b7, 0}, /* 0xfb2e alef+patah */
+ {0x5d0, 0x5b8, 0}, /* 0xfb2f alef+qamats */
+ {0x5d0, 0x5b4, 0}, /* 0xfb30 alef+hiriq */
+ {0x5d1, 0x5bc, 0}, /* 0xfb31 bet+dagesh */
+ {0x5d2, 0x5bc, 0}, /* 0xfb32 gimel+dagesh */
+ {0x5d3, 0x5bc, 0}, /* 0xfb33 dalet+dagesh */
+ {0x5d4, 0x5bc, 0}, /* 0xfb34 he+dagesh */
+ {0x5d5, 0x5bc, 0}, /* 0xfb35 vav+dagesh */
+ {0x5d6, 0x5bc, 0}, /* 0xfb36 zayin+dagesh */
+ {0xfb37, 0, 0}, /* 0xfb37 -- UNUSED */
+ {0x5d8, 0x5bc, 0}, /* 0xfb38 tet+dagesh */
+ {0x5d9, 0x5bc, 0}, /* 0xfb39 yud+dagesh */
+ {0x5da, 0x5bc, 0}, /* 0xfb3a kaf sofit+dagesh */
+ {0x5db, 0x5bc, 0}, /* 0xfb3b kaf+dagesh */
+ {0x5dc, 0x5bc, 0}, /* 0xfb3c lamed+dagesh */
+ {0xfb3d, 0, 0}, /* 0xfb3d -- UNUSED */
+ {0x5de, 0x5bc, 0}, /* 0xfb3e mem+dagesh */
+ {0xfb3f, 0, 0}, /* 0xfb3f -- UNUSED */
+ {0x5e0, 0x5bc, 0}, /* 0xfb40 nun+dagesh */
+ {0x5e1, 0x5bc, 0}, /* 0xfb41 samech+dagesh */
+ {0xfb42, 0, 0}, /* 0xfb42 -- UNUSED */
+ {0x5e3, 0x5bc, 0}, /* 0xfb43 pe sofit+dagesh */
+ {0x5e4, 0x5bc,0}, /* 0xfb44 pe+dagesh */
+ {0xfb45, 0, 0}, /* 0xfb45 -- UNUSED */
+ {0x5e6, 0x5bc, 0}, /* 0xfb46 tsadi+dagesh */
+ {0x5e7, 0x5bc, 0}, /* 0xfb47 qof+dagesh */
+ {0x5e8, 0x5bc, 0}, /* 0xfb48 resh+dagesh */
+ {0x5e9, 0x5bc, 0}, /* 0xfb49 shin+dagesh */
+ {0x5ea, 0x5bc, 0}, /* 0xfb4a tav+dagesh */
+ {0x5d5, 0x5b9, 0}, /* 0xfb4b vav+holam */
+ {0x5d1, 0x5bf, 0}, /* 0xfb4c bet+rafe */
+ {0x5db, 0x5bf, 0}, /* 0xfb4d kaf+rafe */
+ {0x5e4, 0x5bf, 0}, /* 0xfb4e pe+rafe */
+ {0x5d0, 0x5dc, 0} /* 0xfb4f alef-lamed */
+};
+
+ static void
+mb_decompose(c, c1, c2, c3)
+ int c, *c1, *c2, *c3;
+{
+ decomp_T d;
+
+ if (c >= 0x4b20 && c <= 0xfb4f)
+ {
+ d = decomp_table[c - 0xfb20];
+ *c1 = d.a;
+ *c2 = d.b;
+ *c3 = d.c;
+ }
+ else
+ {
+ *c1 = c;
+ *c2 = *c3 = 0;
+ }
+}
+#endif
+
+/*
+ * Compare two strings, ignore case if ireg_ic set.
+ * Return 0 if strings match, non-zero otherwise.
+ * Correct the length "*n" when composing characters are ignored.
+ */
+ static int
+cstrncmp(s1, s2, n)
+ char_u *s1, *s2;
+ int *n;
+{
+ int result;
+
+ if (!ireg_ic)
+ result = STRNCMP(s1, s2, *n);
+ else
+ result = MB_STRNICMP(s1, s2, *n);
+
+#ifdef FEAT_MBYTE
+ /* if it failed and it's utf8 and we want to combineignore: */
+ if (result != 0 && enc_utf8 && ireg_icombine)
+ {
+ char_u *str1, *str2;
+ int c1, c2, c11, c12;
+ int ix;
+ int junk;
+
+ /* we have to handle the strcmp ourselves, since it is necessary to
+ * deal with the composing characters by ignoring them: */
+ str1 = s1;
+ str2 = s2;
+ c1 = c2 = 0;
+ for (ix = 0; ix < *n; )
+ {
+ c1 = mb_ptr2char_adv(&str1);
+ c2 = mb_ptr2char_adv(&str2);
+ ix += utf_char2len(c1);
+
+ /* decompose the character if necessary, into 'base' characters
+ * because I don't care about Arabic, I will hard-code the Hebrew
+ * which I *do* care about! So sue me... */
+ if (c1 != c2 && (!ireg_ic || utf_fold(c1) != utf_fold(c2)))
+ {
+ /* decomposition necessary? */
+ mb_decompose(c1, &c11, &junk, &junk);
+ mb_decompose(c2, &c12, &junk, &junk);
+ c1 = c11;
+ c2 = c12;
+ if (c11 != c12 && (!ireg_ic || utf_fold(c11) != utf_fold(c12)))
+ break;
+ }
+ }
+ result = c2 - c1;
+ if (result == 0)
+ *n = (int)(str2 - s2);
+ }
+#endif
+
+ return result;
+}
+
+/*
+ * cstrchr: This function is used a lot for simple searches, keep it fast!
+ */
+ static char_u *
+cstrchr(s, c)
+ char_u *s;
+ int c;
+{
+ char_u *p;
+ int cc;
+
+ if (!ireg_ic
+#ifdef FEAT_MBYTE
+ || (!enc_utf8 && mb_char2len(c) > 1)
+#endif
+ )
+ return vim_strchr(s, c);
+
+ /* tolower() and toupper() can be slow, comparing twice should be a lot
+ * faster (esp. when using MS Visual C++!).
+ * For UTF-8 need to use folded case. */
+#ifdef FEAT_MBYTE
+ if (enc_utf8 && c > 0x80)
+ cc = utf_fold(c);
+ else
+#endif
+ if (isupper(c))
+ cc = TOLOWER_LOC(c);
+ else if (islower(c))
+ cc = TOUPPER_LOC(c);
+ else
+ return vim_strchr(s, c);
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ for (p = s; *p != NUL; p += (*mb_ptr2len_check)(p))
+ {
+ if (enc_utf8 && c > 0x80)
+ {
+ if (utf_fold(utf_ptr2char(p)) == cc)
+ return p;
+ }
+ else if (*p == c || *p == cc)
+ return p;
+ }
+ }
+ else
+#endif
+ /* Faster version for when there are no multi-byte characters. */
+ for (p = s; *p != NUL; ++p)
+ if (*p == c || *p == cc)
+ return p;
+
+ return NULL;
+}
+
+/***************************************************************
+ * regsub stuff *
+ ***************************************************************/
+
+/* This stuff below really confuses cc on an SGI -- webb */
+#ifdef __sgi
+# undef __ARGS
+# define __ARGS(x) ()
+#endif
+
+/*
+ * We should define ftpr as a pointer to a function returning a pointer to
+ * a function returning a pointer to a function ...
+ * This is impossible, so we declare a pointer to a function returning a
+ * pointer to a function returning void. This should work for all compilers.
+ */
+typedef void (*(*fptr) __ARGS((char_u *, int)))();
+
+static fptr do_upper __ARGS((char_u *, int));
+static fptr do_Upper __ARGS((char_u *, int));
+static fptr do_lower __ARGS((char_u *, int));
+static fptr do_Lower __ARGS((char_u *, int));
+
+static int vim_regsub_both __ARGS((char_u *source, char_u *dest, int copy, int magic, int backslash));
+
+ static fptr
+do_upper(d, c)
+ char_u *d;
+ int c;
+{
+ *d = TOUPPER_LOC(c);
+
+ return (fptr)NULL;
+}
+
+ static fptr
+do_Upper(d, c)
+ char_u *d;
+ int c;
+{
+ *d = TOUPPER_LOC(c);
+
+ return (fptr)do_Upper;
+}
+
+ static fptr
+do_lower(d, c)
+ char_u *d;
+ int c;
+{
+ *d = TOLOWER_LOC(c);
+
+ return (fptr)NULL;
+}
+
+ static fptr
+do_Lower(d, c)
+ char_u *d;
+ int c;
+{
+ *d = TOLOWER_LOC(c);
+
+ return (fptr)do_Lower;
+}
+
+/*
+ * regtilde(): Replace tildes in the pattern by the old pattern.
+ *
+ * Short explanation of the tilde: It stands for the previous replacement
+ * pattern. If that previous pattern also contains a ~ we should go back a
+ * step further... But we insert the previous pattern into the current one
+ * and remember that.
+ * This still does not handle the case where "magic" changes. TODO?
+ *
+ * The tildes are parsed once before the first call to vim_regsub().
+ */
+ char_u *
+regtilde(source, magic)
+ char_u *source;
+ int magic;
+{
+ char_u *newsub = source;
+ char_u *tmpsub;
+ char_u *p;
+ int len;
+ int prevlen;
+
+ for (p = newsub; *p; ++p)
+ {
+ if ((*p == '~' && magic) || (*p == '\\' && *(p + 1) == '~' && !magic))
+ {
+ if (reg_prev_sub != NULL)
+ {
+ /* length = len(newsub) - 1 + len(prev_sub) + 1 */
+ prevlen = (int)STRLEN(reg_prev_sub);
+ tmpsub = alloc((unsigned)(STRLEN(newsub) + prevlen));
+ if (tmpsub != NULL)
+ {
+ /* copy prefix */
+ len = (int)(p - newsub); /* not including ~ */
+ mch_memmove(tmpsub, newsub, (size_t)len);
+ /* interpretate tilde */
+ mch_memmove(tmpsub + len, reg_prev_sub, (size_t)prevlen);
+ /* copy postfix */
+ if (!magic)
+ ++p; /* back off \ */
+ STRCPY(tmpsub + len + prevlen, p + 1);
+
+ if (newsub != source) /* already allocated newsub */
+ vim_free(newsub);
+ newsub = tmpsub;
+ p = newsub + len + prevlen;
+ }
+ }
+ else if (magic)
+ STRCPY(p, p + 1); /* remove '~' */
+ else
+ STRCPY(p, p + 2); /* remove '\~' */
+ --p;
+ }
+ else
+ {
+ if (*p == '\\' && p[1]) /* skip escaped characters */
+ ++p;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ p += (*mb_ptr2len_check)(p) - 1;
+#endif
+ }
+ }
+
+ vim_free(reg_prev_sub);
+ if (newsub != source) /* newsub was allocated, just keep it */
+ reg_prev_sub = newsub;
+ else /* no ~ found, need to save newsub */
+ reg_prev_sub = vim_strsave(newsub);
+ return newsub;
+}
+
+#ifdef FEAT_EVAL
+static int can_f_submatch = FALSE; /* TRUE when submatch() can be used */
+
+/* These pointers are used instead of reg_match and reg_mmatch for
+ * reg_submatch(). Needed for when the substitution string is an expression
+ * that contains a call to substitute() and submatch(). */
+static regmatch_T *submatch_match;
+static regmmatch_T *submatch_mmatch;
+#endif
+
+#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * vim_regsub() - perform substitutions after a vim_regexec() or
+ * vim_regexec_multi() match.
+ *
+ * If "copy" is TRUE really copy into "dest".
+ * If "copy" is FALSE nothing is copied, this is just to find out the length
+ * of the result.
+ *
+ * If "backslash" is TRUE, a backslash will be removed later, need to double
+ * them to keep them, and insert a backslash before a CR to avoid it being
+ * replaced with a line break later.
+ *
+ * Note: The matched text must not change between the call of
+ * vim_regexec()/vim_regexec_multi() and vim_regsub()! It would make the back
+ * references invalid!
+ *
+ * Returns the size of the replacement, including terminating NUL.
+ */
+ int
+vim_regsub(rmp, source, dest, copy, magic, backslash)
+ regmatch_T *rmp;
+ char_u *source;
+ char_u *dest;
+ int copy;
+ int magic;
+ int backslash;
+{
+ reg_match = rmp;
+ reg_mmatch = NULL;
+ reg_maxline = 0;
+ return vim_regsub_both(source, dest, copy, magic, backslash);
+}
+#endif
+
+ int
+vim_regsub_multi(rmp, lnum, source, dest, copy, magic, backslash)
+ regmmatch_T *rmp;
+ linenr_T lnum;
+ char_u *source;
+ char_u *dest;
+ int copy;
+ int magic;
+ int backslash;
+{
+ reg_match = NULL;
+ reg_mmatch = rmp;
+ reg_buf = curbuf; /* always works on the current buffer! */
+ reg_firstlnum = lnum;
+ reg_maxline = curbuf->b_ml.ml_line_count - lnum;
+ return vim_regsub_both(source, dest, copy, magic, backslash);
+}
+
+ static int
+vim_regsub_both(source, dest, copy, magic, backslash)
+ char_u *source;
+ char_u *dest;
+ int copy;
+ int magic;
+ int backslash;
+{
+ char_u *src;
+ char_u *dst;
+ char_u *s;
+ int c;
+ int no = -1;
+ fptr func = (fptr)NULL;
+ linenr_T clnum = 0; /* init for GCC */
+ int len = 0; /* init for GCC */
+#ifdef FEAT_EVAL
+ static char_u *eval_result = NULL;
+#endif
+#ifdef FEAT_MBYTE
+ int l;
+#endif
+
+
+ /* Be paranoid... */
+ if (source == NULL || dest == NULL)
+ {
+ EMSG(_(e_null));
+ return 0;
+ }
+ if (prog_magic_wrong())
+ return 0;
+ src = source;
+ dst = dest;
+
+ /*
+ * When the substitute part starts with "\=" evaluate it as an expression.
+ */
+ if (source[0] == '\\' && source[1] == '='
+#ifdef FEAT_EVAL
+ && !can_f_submatch /* can't do this recursively */
+#endif
+ )
+ {
+#ifdef FEAT_EVAL
+ /* To make sure that the length doesn't change between checking the
+ * length and copying the string, and to speed up things, the
+ * resulting string is saved from the call with "copy" == FALSE to the
+ * call with "copy" == TRUE. */
+ if (copy)
+ {
+ if (eval_result != NULL)
+ {
+ STRCPY(dest, eval_result);
+ dst += STRLEN(eval_result);
+ vim_free(eval_result);
+ eval_result = NULL;
+ }
+ }
+ else
+ {
+ linenr_T save_reg_maxline;
+ win_T *save_reg_win;
+ int save_ireg_ic;
+
+ vim_free(eval_result);
+
+ /* The expression may contain substitute(), which calls us
+ * recursively. Make sure submatch() gets the text from the first
+ * level. Don't need to save "reg_buf", because
+ * vim_regexec_multi() can't be called recursively. */
+ submatch_match = reg_match;
+ submatch_mmatch = reg_mmatch;
+ save_reg_maxline = reg_maxline;
+ save_reg_win = reg_win;
+ save_ireg_ic = ireg_ic;
+ can_f_submatch = TRUE;
+
+ eval_result = eval_to_string(source + 2, NULL);
+ if (eval_result != NULL)
+ {
+ for (s = eval_result; *s != NUL; ++s)
+ {
+ /* Change NL to CR, so that it becomes a line break.
+ * Skip over a backslashed character. */
+ if (*s == NL)
+ *s = CAR;
+ else if (*s == '\\' && s[1] != NUL)
+ ++s;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ s += (*mb_ptr2len_check)(s) - 1;
+#endif
+ }
+
+ dst += STRLEN(eval_result);
+ }
+
+ reg_match = submatch_match;
+ reg_mmatch = submatch_mmatch;
+ reg_maxline = save_reg_maxline;
+ reg_win = save_reg_win;
+ ireg_ic = save_ireg_ic;
+ can_f_submatch = FALSE;
+ }
+#endif
+ }
+ else
+ while ((c = *src++) != NUL)
+ {
+ if (c == '&' && magic)
+ no = 0;
+ else if (c == '\\' && *src != NUL)
+ {
+ if (*src == '&' && !magic)
+ {
+ ++src;
+ no = 0;
+ }
+ else if ('0' <= *src && *src <= '9')
+ {
+ no = *src++ - '0';
+ }
+ else if (vim_strchr((char_u *)"uUlLeE", *src))
+ {
+ switch (*src++)
+ {
+ case 'u': func = (fptr)do_upper;
+ continue;
+ case 'U': func = (fptr)do_Upper;
+ continue;
+ case 'l': func = (fptr)do_lower;
+ continue;
+ case 'L': func = (fptr)do_Lower;
+ continue;
+ case 'e':
+ case 'E': func = (fptr)NULL;
+ continue;
+ }
+ }
+ }
+ if (no < 0) /* Ordinary character. */
+ {
+ if (c == '\\' && *src != NUL)
+ {
+ /* Check for abbreviations -- webb */
+ switch (*src)
+ {
+ case 'r': c = CAR; ++src; break;
+ case 'n': c = NL; ++src; break;
+ case 't': c = TAB; ++src; break;
+ /* Oh no! \e already has meaning in subst pat :-( */
+ /* case 'e': c = ESC; ++src; break; */
+ case 'b': c = Ctrl_H; ++src; break;
+
+ /* If "backslash" is TRUE the backslash will be removed
+ * later. Used to insert a literal CR. */
+ default: if (backslash)
+ {
+ if (copy)
+ *dst = '\\';
+ ++dst;
+ }
+ c = *src++;
+ }
+ }
+
+ /* Write to buffer, if copy is set. */
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (l = (*mb_ptr2len_check)(src - 1)) > 1)
+ {
+ /* TODO: should use "func" here. */
+ if (copy)
+ mch_memmove(dst, src - 1, l);
+ dst += l - 1;
+ src += l - 1;
+ }
+ else
+ {
+#endif
+ if (copy)
+ {
+ if (func == (fptr)NULL) /* just copy */
+ *dst = c;
+ else /* change case */
+ func = (fptr)(func(dst, c));
+ /* Turbo C complains without the typecast */
+ }
+#ifdef FEAT_MBYTE
+ }
+#endif
+ dst++;
+ }
+ else
+ {
+ if (REG_MULTI)
+ {
+ clnum = reg_mmatch->startpos[no].lnum;
+ if (clnum < 0 || reg_mmatch->endpos[no].lnum < 0)
+ s = NULL;
+ else
+ {
+ s = reg_getline(clnum) + reg_mmatch->startpos[no].col;
+ if (reg_mmatch->endpos[no].lnum == clnum)
+ len = reg_mmatch->endpos[no].col
+ - reg_mmatch->startpos[no].col;
+ else
+ len = (int)STRLEN(s);
+ }
+ }
+ else
+ {
+ s = reg_match->startp[no];
+ if (reg_match->endp[no] == NULL)
+ s = NULL;
+ else
+ len = (int)(reg_match->endp[no] - s);
+ }
+ if (s != NULL)
+ {
+ for (;;)
+ {
+ if (len == 0)
+ {
+ if (REG_MULTI)
+ {
+ if (reg_mmatch->endpos[no].lnum == clnum)
+ break;
+ if (copy)
+ *dst = CAR;
+ ++dst;
+ s = reg_getline(++clnum);
+ if (reg_mmatch->endpos[no].lnum == clnum)
+ len = reg_mmatch->endpos[no].col;
+ else
+ len = (int)STRLEN(s);
+ }
+ else
+ break;
+ }
+ else if (*s == NUL) /* we hit NUL. */
+ {
+ if (copy)
+ EMSG(_(e_re_damg));
+ goto exit;
+ }
+ else
+ {
+ if (backslash && (*s == CAR || *s == '\\'))
+ {
+ /*
+ * Insert a backslash in front of a CR, otherwise
+ * it will be replaced by a line break.
+ * Number of backslashes will be halved later,
+ * double them here.
+ */
+ if (copy)
+ {
+ dst[0] = '\\';
+ dst[1] = *s;
+ }
+ dst += 2;
+ }
+#ifdef FEAT_MBYTE
+ else if (has_mbyte && (l = (*mb_ptr2len_check)(s)) > 1)
+ {
+ /* TODO: should use "func" here. */
+ if (copy)
+ mch_memmove(dst, s, l);
+ dst += l;
+ s += l - 1;
+ len -= l - 1;
+ }
+#endif
+ else
+ {
+ if (copy)
+ {
+ if (func == (fptr)NULL) /* just copy */
+ *dst = *s;
+ else /* change case */
+ func = (fptr)(func(dst, *s));
+ /* Turbo C complains without the typecast */
+ }
+ ++dst;
+ }
+ ++s;
+ --len;
+ }
+ }
+ }
+ no = -1;
+ }
+ }
+ if (copy)
+ *dst = NUL;
+
+exit:
+ return (int)((dst - dest) + 1);
+}
+
+#ifdef FEAT_EVAL
+/*
+ * Used for the submatch() function: get the string from tne n'th submatch in
+ * allocated memory.
+ * Returns NULL when not in a ":s" command and for a non-existing submatch.
+ */
+ char_u *
+reg_submatch(no)
+ int no;
+{
+ char_u *retval = NULL;
+ char_u *s;
+ int len;
+ int round;
+ linenr_T lnum;
+
+ if (!can_f_submatch)
+ return NULL;
+
+ if (submatch_match == NULL)
+ {
+ /*
+ * First round: compute the length and allocate memory.
+ * Second round: copy the text.
+ */
+ for (round = 1; round <= 2; ++round)
+ {
+ lnum = submatch_mmatch->startpos[no].lnum;
+ if (lnum < 0 || submatch_mmatch->endpos[no].lnum < 0)
+ return NULL;
+
+ s = reg_getline(lnum) + submatch_mmatch->startpos[no].col;
+ if (s == NULL) /* anti-crash check, cannot happen? */
+ break;
+ if (submatch_mmatch->endpos[no].lnum == lnum)
+ {
+ /* Within one line: take form start to end col. */
+ len = submatch_mmatch->endpos[no].col
+ - submatch_mmatch->startpos[no].col;
+ if (round == 2)
+ {
+ STRNCPY(retval, s, len);
+ retval[len] = NUL;
+ }
+ ++len;
+ }
+ else
+ {
+ /* Multiple lines: take start line from start col, middle
+ * lines completely and end line up to end col. */
+ len = (int)STRLEN(s);
+ if (round == 2)
+ {
+ STRCPY(retval, s);
+ retval[len] = '\n';
+ }
+ ++len;
+ ++lnum;
+ while (lnum < submatch_mmatch->endpos[no].lnum)
+ {
+ s = reg_getline(lnum++);
+ if (round == 2)
+ STRCPY(retval + len, s);
+ len += (int)STRLEN(s);
+ if (round == 2)
+ retval[len] = '\n';
+ ++len;
+ }
+ if (round == 2)
+ STRNCPY(retval + len, reg_getline(lnum),
+ submatch_mmatch->endpos[no].col);
+ len += submatch_mmatch->endpos[no].col;
+ if (round == 2)
+ retval[len] = NUL;
+ ++len;
+ }
+
+ if (round == 1)
+ {
+ retval = lalloc((long_u)len, TRUE);
+ if (s == NULL)
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ if (submatch_match->endp[no] == NULL)
+ retval = NULL;
+ else
+ {
+ s = submatch_match->startp[no];
+ retval = vim_strnsave(s, (int)(submatch_match->endp[no] - s));
+ }
+ }
+
+ return retval;
+}
+#endif
diff --git a/src/regexp.h b/src/regexp.h
new file mode 100644
index 000000000..15611ed81
--- /dev/null
+++ b/src/regexp.h
@@ -0,0 +1,80 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
+ *
+ * This is NOT the original regular expression code as written by Henry
+ * Spencer. This code has been modified specifically for use with Vim, and
+ * should not be used apart from compiling Vim. If you want a good regular
+ * expression library, get the original code.
+ *
+ * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
+ */
+
+#ifndef _REGEXP_H
+#define _REGEXP_H
+
+/*
+ * The number of sub-matches is limited to 10.
+ * The first one (index 0) is the whole match, referenced with "\0".
+ * The second one (index 1) is the first sub-match, referenced with "\1".
+ * This goes up to the tenth (index 9), referenced with "\9".
+ */
+#define NSUBEXP 10
+
+/*
+ * Structure returned by vim_regcomp() to pass on to vim_regexec().
+ * These fields are only to be used in regexp.c!
+ * See regep.c for an explanation.
+ */
+typedef struct
+{
+ int regstart;
+ char_u reganch;
+ char_u *regmust;
+ int regmlen;
+ unsigned regflags;
+ char_u reghasz;
+ char_u program[1]; /* actually longer.. */
+} regprog_T;
+
+/*
+ * Structure to be used for single-line matching.
+ * Sub-match "no" starts at "startp[no]" and ends just before "endp[no]".
+ * When there is no match, the pointer is NULL.
+ */
+typedef struct
+{
+ regprog_T *regprog;
+ char_u *startp[NSUBEXP];
+ char_u *endp[NSUBEXP];
+ int rm_ic;
+} regmatch_T;
+
+/*
+ * Structure to be used for multi-line matching.
+ * Sub-match "no" starts in line "startpos[no].lnum" column "startpos[no].col"
+ * and ends in line "endpos[no].lnum" just before column "endpos[no].col".
+ * The line numbers are relative to the first line, thus startpos[0].lnum is
+ * always 0.
+ * When there is no match, the line number is -1.
+ */
+typedef struct
+{
+ regprog_T *regprog;
+ lpos_T startpos[NSUBEXP];
+ lpos_T endpos[NSUBEXP];
+ int rmm_ic;
+} regmmatch_T;
+
+/*
+ * Structure used to store external references: "\z\(\)" to "\z\1".
+ * Use a reference count to avoid the need to copy this around. When it goes
+ * from 1 to zero the matches need to be freed.
+ */
+typedef struct
+{
+ short refcnt;
+ char_u *matches[NSUBEXP];
+} reg_extmatch_T;
+
+#endif /* _REGEXP_H */
diff --git a/src/screen.c b/src/screen.c
new file mode 100644
index 000000000..594c42479
--- /dev/null
+++ b/src/screen.c
@@ -0,0 +1,8437 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * screen.c: code for displaying on the screen
+ *
+ * Output to the screen (console, terminal emulator or GUI window) is minimized
+ * by remembering what is already on the screen, and only updating the parts
+ * that changed.
+ *
+ * ScreenLines[off] Contains a copy of the whole screen, as it is currently
+ * displayed (excluding text written by external commands).
+ * ScreenAttrs[off] Contains the associated attributes.
+ * LineOffset[row] Contains the offset into ScreenLines*[] and ScreenAttrs[]
+ * for each line.
+ * LineWraps[row] Flag for each line whether it wraps to the next line.
+ *
+ * For double-byte characters, two consecutive bytes in ScreenLines[] can form
+ * one character which occupies two display cells.
+ * For UTF-8 a multi-byte character is converted to Unicode and stored in
+ * ScreenLinesUC[]. ScreenLines[] contains the first byte only. For an ASCII
+ * character without composing chars ScreenLinesUC[] will be 0. When the
+ * character occupies two display cells the next byte in ScreenLines[] is 0.
+ * ScreenLinesC1[] and ScreenLinesC2[] contain up to two composing characters
+ * (drawn on top of the first character). They are 0 when not used.
+ * ScreenLines2[] is only used for euc-jp to store the second byte if the
+ * first byte is 0x8e (single-width character).
+ *
+ * The screen_*() functions write to the screen and handle updating
+ * ScreenLines[].
+ *
+ * update_screen() is the function that updates all windows and status lines.
+ * It is called form the main loop when must_redraw is non-zero. It may be
+ * called from other places when an immediated screen update is needed.
+ *
+ * The part of the buffer that is displayed in a window is set with:
+ * - w_topline (first buffer line in window)
+ * - w_topfill (filler line above the first line)
+ * - w_leftcol (leftmost window cell in window),
+ * - w_skipcol (skipped window cells of first line)
+ *
+ * Commands that only move the cursor around in a window, do not need to take
+ * action to update the display. The main loop will check if w_topline is
+ * valid and update it (scroll the window) when needed.
+ *
+ * Commands that scroll a window change w_topline and must call
+ * check_cursor() to move the cursor into the visible part of the window, and
+ * call redraw_later(VALID) to have the window displayed by update_screen()
+ * later.
+ *
+ * Commands that change text in the buffer must call changed_bytes() or
+ * changed_lines() to mark the area that changed and will require updating
+ * later. The main loop will call update_screen(), which will update each
+ * window that shows the changed buffer. This assumes text above the change
+ * can remain displayed as it is. Text after the change may need updating for
+ * scrolling, folding and syntax highlighting.
+ *
+ * Commands that change how a window is displayed (e.g., setting 'list') or
+ * invalidate the contents of a window in another way (e.g., change fold
+ * settings), must call redraw_later(NOT_VALID) to have the whole window
+ * redisplayed by update_screen() later.
+ *
+ * Commands that change how a buffer is displayed (e.g., setting 'tabstop')
+ * must call redraw_curbuf_later(NOT_VALID) to have all the windows for the
+ * buffer redisplayed by update_screen() later.
+ *
+ * Commands that move the window position must call redraw_later(NOT_VALID).
+ * TODO: should minimize redrawing by scrolling when possible.
+ *
+ * Commands that change everything (e.g., resizing the screen) must call
+ * redraw_all_later(NOT_VALID) or redraw_all_later(CLEAR).
+ *
+ * Things that are handled indirectly:
+ * - When messages scroll the screen up, msg_scrolled will be set and
+ * update_screen() called to redraw.
+ */
+
+#include "vim.h"
+
+/*
+ * The attributes that are actually active for writing to the screen.
+ */
+static int screen_attr = 0;
+
+/*
+ * Positioning the cursor is reduced by remembering the last position.
+ * Mostly used by windgoto() and screen_char().
+ */
+static int screen_cur_row, screen_cur_col; /* last known cursor position */
+
+#ifdef FEAT_SEARCH_EXTRA
+/*
+ * Struct used for highlighting 'hlsearch' matches for the last use search
+ * pattern or a ":match" item.
+ * For 'hlsearch' there is one pattern for all windows. For ":match" there is
+ * a different pattern for each window.
+ */
+typedef struct
+{
+ regmmatch_T rm; /* points to the regexp program; contains last found
+ match (may continue in next line) */
+ buf_T *buf; /* the buffer to search for a match */
+ linenr_T lnum; /* the line to search for a match */
+ int attr; /* attributes to be used for a match */
+ int attr_cur; /* attributes currently active in win_line() */
+ linenr_T first_lnum; /* first lnum to search for multi-line pat */
+ char_u *startp; /* in win_line() points to char where HL starts */
+ char_u *endp; /* in win_line() points to char where HL ends */
+} match_T;
+
+static match_T search_hl; /* used for 'hlsearch' highlight matching */
+static match_T match_hl; /* used for ":match" highlight matching */
+#endif
+
+#ifdef FEAT_FOLDING
+static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */
+#endif
+
+/*
+ * Buffer for one screen line (characters and attributes).
+ */
+static schar_T *current_ScreenLine;
+
+static void win_update __ARGS((win_T *wp));
+static void win_draw_end __ARGS((win_T *wp, int c1, int c2, int row, int endrow, enum hlf_value hl));
+#ifdef FEAT_FOLDING
+static void fold_line __ARGS((win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T lnum, int row));
+static void fill_foldcolumn __ARGS((char_u *p, win_T *wp, int closed, linenr_T lnum));
+static void copy_text_attr __ARGS((int off, char_u *buf, int len, int attr));
+#endif
+static int win_line __ARGS((win_T *, linenr_T, int, int));
+static int char_needs_redraw __ARGS((int off_from, int off_to, int cols));
+#ifdef FEAT_RIGHTLEFT
+static void screen_line __ARGS((int row, int coloff, int endcol, int clear_width, int rlflag));
+# define SCREEN_LINE(r, o, e, c, rl) screen_line((r), (o), (e), (c), (rl))
+#else
+static void screen_line __ARGS((int row, int coloff, int endcol, int clear_width));
+# define SCREEN_LINE(r, o, e, c, rl) screen_line((r), (o), (e), (c))
+#endif
+#ifdef FEAT_RIGHTLEFT
+static void rl_mirror __ARGS((char_u *str));
+#endif
+#ifdef FEAT_VERTSPLIT
+static void draw_vsep_win __ARGS((win_T *wp, int row));
+#endif
+#ifdef FEAT_SEARCH_EXTRA
+static void start_search_hl __ARGS((void));
+static void end_search_hl __ARGS((void));
+static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum));
+static void next_search_hl __ARGS((win_T *win, match_T *shl, linenr_T lnum, colnr_T mincol));
+#endif
+static void screen_start_highlight __ARGS((int attr));
+static void screen_char __ARGS((unsigned off, int row, int col));
+#ifdef FEAT_MBYTE
+static void screen_char_2 __ARGS((unsigned off, int row, int col));
+#endif
+static void screenclear2 __ARGS((void));
+static void lineclear __ARGS((unsigned off, int width));
+static void lineinvalid __ARGS((unsigned off, int width));
+#ifdef FEAT_VERTSPLIT
+static void linecopy __ARGS((int to, int from, win_T *wp));
+static void redraw_block __ARGS((int row, int end, win_T *wp));
+#endif
+static int win_do_lines __ARGS((win_T *wp, int row, int line_count, int mayclear, int del));
+static void win_rest_invalid __ARGS((win_T *wp));
+static int screen_ins_lines __ARGS((int, int, int, int, win_T *wp));
+static void msg_pos_mode __ARGS((void));
+#if defined(FEAT_WINDOWS) || defined(FEAT_WILDMENU) || defined(FEAT_STL_OPT)
+static int fillchar_status __ARGS((int *attr, int is_curwin));
+#endif
+#ifdef FEAT_VERTSPLIT
+static int fillchar_vsep __ARGS((int *attr));
+#endif
+#ifdef FEAT_STL_OPT
+static void win_redr_custom __ARGS((win_T *wp, int Ruler));
+#endif
+#ifdef FEAT_CMDL_INFO
+static void win_redr_ruler __ARGS((win_T *wp, int always));
+#endif
+
+#if defined(FEAT_CLIPBOARD) || defined(FEAT_VERTSPLIT)
+/* Ugly global: overrule attribute used by screen_char() */
+static int screen_char_attr = 0;
+#endif
+
+/*
+ * Redraw the current window later, with update_screen(type).
+ * Set must_redraw only if not already set to a higher value.
+ * e.g. if must_redraw is CLEAR, type NOT_VALID will do nothing.
+ */
+ void
+redraw_later(type)
+ int type;
+{
+ redraw_win_later(curwin, type);
+}
+
+ void
+redraw_win_later(wp, type)
+ win_T *wp;
+ int type;
+{
+ if (wp->w_redr_type < type)
+ {
+ wp->w_redr_type = type;
+ if (type >= NOT_VALID)
+ wp->w_lines_valid = 0;
+ if (must_redraw < type) /* must_redraw is the maximum of all windows */
+ must_redraw = type;
+ }
+}
+
+/*
+ * Force a complete redraw later. Also resets the highlighting. To be used
+ * after executing a shell command that messes up the screen.
+ */
+ void
+redraw_later_clear()
+{
+ redraw_all_later(CLEAR);
+ screen_attr = HL_BOLD | HL_UNDERLINE;
+}
+
+/*
+ * Mark all windows to be redrawn later.
+ */
+ void
+redraw_all_later(type)
+ int type;
+{
+ win_T *wp;
+
+ FOR_ALL_WINDOWS(wp)
+ {
+ redraw_win_later(wp, type);
+ }
+}
+
+/*
+ * Mark all windows that are editing the current buffer to be udpated later.
+ */
+ void
+redraw_curbuf_later(type)
+ int type;
+{
+ redraw_buf_later(curbuf, type);
+}
+
+ void
+redraw_buf_later(buf, type)
+ buf_T *buf;
+ int type;
+{
+ win_T *wp;
+
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_buffer == buf)
+ redraw_win_later(wp, type);
+ }
+}
+
+/*
+ * Changed something in the current window, at buffer line "lnum", that
+ * requires that line and possibly other lines to be redrawn.
+ * Used when entering/leaving Insert mode with the cursor on a folded line.
+ * Used to remove the "$" from a change command.
+ * Note that when also inserting/deleting lines w_redraw_top and w_redraw_bot
+ * may become invalid and the whole window will have to be redrawn.
+ */
+/*ARGSUSED*/
+ void
+redrawWinline(lnum, invalid)
+ linenr_T lnum;
+ int invalid; /* window line height is invalid now */
+{
+#ifdef FEAT_FOLDING
+ int i;
+#endif
+
+ if (curwin->w_redraw_top == 0 || curwin->w_redraw_top > lnum)
+ curwin->w_redraw_top = lnum;
+ if (curwin->w_redraw_bot == 0 || curwin->w_redraw_bot < lnum)
+ curwin->w_redraw_bot = lnum;
+ redraw_later(VALID);
+
+#ifdef FEAT_FOLDING
+ if (invalid)
+ {
+ /* A w_lines[] entry for this lnum has become invalid. */
+ i = find_wl_entry(curwin, lnum);
+ if (i >= 0)
+ curwin->w_lines[i].wl_valid = FALSE;
+ }
+#endif
+}
+
+/*
+ * update all windows that are editing the current buffer
+ */
+ void
+update_curbuf(type)
+ int type;
+{
+ redraw_curbuf_later(type);
+ update_screen(type);
+}
+
+/*
+ * update_screen()
+ *
+ * Based on the current value of curwin->w_topline, transfer a screenfull
+ * of stuff from Filemem to ScreenLines[], and update curwin->w_botline.
+ */
+ void
+update_screen(type)
+ int type;
+{
+ win_T *wp;
+ static int did_intro = FALSE;
+#if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_CLIPBOARD)
+ int did_one;
+#endif
+
+ if (!screen_valid(TRUE))
+ return;
+
+ if (must_redraw)
+ {
+ if (type < must_redraw) /* use maximal type */
+ type = must_redraw;
+ must_redraw = 0;
+ }
+
+ /* Need to update w_lines[]. */
+ if (curwin->w_lines_valid == 0 && type < NOT_VALID)
+ type = NOT_VALID;
+
+ if (!redrawing())
+ {
+ redraw_later(type); /* remember type for next time */
+ must_redraw = type;
+ if (type > INVERTED_ALL)
+ curwin->w_lines_valid = 0; /* don't use w_lines[].wl_size now */
+ return;
+ }
+
+ updating_screen = TRUE;
+#ifdef FEAT_SYN_HL
+ ++display_tick; /* let syntax code know we're in a next round of
+ * display updating */
+#endif
+
+ /*
+ * if the screen was scrolled up when displaying a message, scroll it down
+ */
+ if (msg_scrolled)
+ {
+ clear_cmdline = TRUE;
+ if (msg_scrolled > Rows - 5) /* clearing is faster */
+ type = CLEAR;
+ else if (type != CLEAR)
+ {
+ check_for_delay(FALSE);
+ if (screen_ins_lines(0, 0, msg_scrolled, (int)Rows, NULL) == FAIL)
+ type = CLEAR;
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (W_WINROW(wp) < msg_scrolled)
+ {
+ if (W_WINROW(wp) + wp->w_height > msg_scrolled
+ && wp->w_redr_type < REDRAW_TOP
+ && wp->w_lines_valid > 0
+ && wp->w_topline == wp->w_lines[0].wl_lnum)
+ {
+ wp->w_upd_rows = msg_scrolled - W_WINROW(wp);
+ wp->w_redr_type = REDRAW_TOP;
+ }
+ else
+ {
+ wp->w_redr_type = NOT_VALID;
+#ifdef FEAT_WINDOWS
+ if (W_WINROW(wp) + wp->w_height + W_STATUS_HEIGHT(wp)
+ <= msg_scrolled)
+ wp->w_redr_status = TRUE;
+#endif
+ }
+ }
+ }
+ redraw_cmdline = TRUE;
+ }
+ msg_scrolled = 0;
+ need_wait_return = FALSE;
+ }
+
+ /* reset cmdline_row now (may have been changed temporarily) */
+ compute_cmdrow();
+
+ /* Check for changed highlighting */
+ if (need_highlight_changed)
+ highlight_changed();
+
+ if (type == CLEAR) /* first clear screen */
+ {
+ screenclear(); /* will reset clear_cmdline */
+ type = NOT_VALID;
+ }
+
+ if (clear_cmdline) /* going to clear cmdline (done below) */
+ check_for_delay(FALSE);
+
+ /*
+ * Only start redrawing if there is really something to do.
+ */
+ if (type == INVERTED)
+ update_curswant();
+ if (curwin->w_redr_type < type
+ && !((type == VALID
+ && curwin->w_lines[0].wl_valid
+#ifdef FEAT_DIFF
+ && curwin->w_topfill == curwin->w_old_topfill
+ && curwin->w_botfill == curwin->w_old_botfill
+#endif
+ && curwin->w_topline == curwin->w_lines[0].wl_lnum)
+#ifdef FEAT_VISUAL
+ || (type == INVERTED
+ && curwin->w_old_cursor_lnum == curwin->w_cursor.lnum
+ && curwin->w_old_visual_mode == VIsual_mode
+ && (curwin->w_valid & VALID_VIRTCOL)
+ && curwin->w_old_curswant == curwin->w_curswant)
+#endif
+ ))
+ curwin->w_redr_type = type;
+
+#ifdef FEAT_SYN_HL
+ /*
+ * Correct stored syntax highlighting info for changes in each displayed
+ * buffer. Each buffer must only be done once.
+ */
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_buffer->b_mod_set)
+ {
+# ifdef FEAT_WINDOWS
+ win_T *wwp;
+
+ /* Check if we already did this buffer. */
+ for (wwp = firstwin; wwp != wp; wwp = wwp->w_next)
+ if (wwp->w_buffer == wp->w_buffer)
+ break;
+# endif
+ if (
+# ifdef FEAT_WINDOWS
+ wwp == wp &&
+# endif
+ syntax_present(wp->w_buffer))
+ syn_stack_apply_changes(wp->w_buffer);
+ }
+ }
+#endif
+
+ /*
+ * Go from top to bottom through the windows, redrawing the ones that need
+ * it.
+ */
+#if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_CLIPBOARD)
+ did_one = FALSE;
+#endif
+#ifdef FEAT_SEARCH_EXTRA
+ search_hl.rm.regprog = NULL;
+#endif
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_redr_type != 0)
+ {
+ cursor_off();
+#if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_CLIPBOARD)
+ if (!did_one)
+ {
+ did_one = TRUE;
+# ifdef FEAT_SEARCH_EXTRA
+ start_search_hl();
+# endif
+# ifdef FEAT_CLIPBOARD
+ /* When Visual area changed, may have to update selection. */
+ if (clip_star.available && clip_isautosel())
+ clip_update_selection();
+# endif
+#ifdef FEAT_GUI
+ /* Remove the cursor before starting to do anything, because
+ * scrolling may make it difficult to redraw the text under
+ * it. */
+ if (gui.in_use)
+ gui_undraw_cursor();
+#endif
+ }
+#endif
+ win_update(wp);
+ }
+
+#ifdef FEAT_WINDOWS
+ /* redraw status line after the window to minimize cursor movement */
+ if (wp->w_redr_status)
+ {
+ cursor_off();
+ win_redr_status(wp);
+ }
+#endif
+ }
+#if defined(FEAT_SEARCH_EXTRA)
+ end_search_hl();
+#endif
+
+#ifdef FEAT_WINDOWS
+ /* Reset b_mod_set flags. Going through all windows is probably faster
+ * than going through all buffers (there could be many buffers). */
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ wp->w_buffer->b_mod_set = FALSE;
+#else
+ curbuf->b_mod_set = FALSE;
+#endif
+
+ updating_screen = FALSE;
+#ifdef FEAT_GUI
+ gui_may_resize_shell();
+#endif
+
+ /* Clear or redraw the command line. Done last, because scrolling may
+ * mess up the command line. */
+ if (clear_cmdline || redraw_cmdline)
+ showmode();
+
+ /* May put up an introductory message when not editing a file */
+ if (!did_intro && bufempty()
+ && curbuf->b_fname == NULL
+#ifdef FEAT_WINDOWS
+ && firstwin->w_next == NULL
+#endif
+ && vim_strchr(p_shm, SHM_INTRO) == NULL)
+ intro_message(FALSE);
+ did_intro = TRUE;
+
+#ifdef FEAT_GUI
+ /* Redraw the cursor and update the scrollbars when all screen updating is
+ * done. */
+ if (gui.in_use)
+ {
+ out_flush(); /* required before updating the cursor */
+ if (did_one)
+ gui_update_cursor(FALSE, FALSE);
+ gui_update_scrollbars(FALSE);
+ }
+#endif
+}
+
+#if defined(FEAT_SIGNS) || defined(FEAT_GUI)
+static void update_prepare __ARGS((void));
+static void update_finish __ARGS((void));
+
+/*
+ * Prepare for updating one or more windows.
+ */
+ static void
+update_prepare()
+{
+ cursor_off();
+ updating_screen = TRUE;
+#ifdef FEAT_GUI
+ /* Remove the cursor before starting to do anything, because scrolling may
+ * make it difficult to redraw the text under it. */
+ if (gui.in_use)
+ gui_undraw_cursor();
+#endif
+#ifdef FEAT_SEARCH_EXTRA
+ start_search_hl();
+#endif
+}
+
+/*
+ * Finish updating one or more windows.
+ */
+ static void
+update_finish()
+{
+ if (redraw_cmdline)
+ showmode();
+
+# ifdef FEAT_SEARCH_EXTRA
+ end_search_hl();
+# endif
+
+ updating_screen = FALSE;
+
+# ifdef FEAT_GUI
+ gui_may_resize_shell();
+
+ /* Redraw the cursor and update the scrollbars when all screen updating is
+ * done. */
+ if (gui.in_use)
+ {
+ out_flush(); /* required before updating the cursor */
+ gui_update_cursor(FALSE, FALSE);
+ gui_update_scrollbars(FALSE);
+ }
+# endif
+}
+#endif
+
+#if defined(FEAT_SIGNS) || defined(PROTO)
+ void
+update_debug_sign(buf, lnum)
+ buf_T *buf;
+ linenr_T lnum;
+{
+ win_T *wp;
+ int doit = FALSE;
+
+# ifdef FEAT_FOLDING
+ win_foldinfo.fi_level = 0;
+# endif
+
+ /* update/delete a specific mark */
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (buf != NULL && lnum > 0)
+ {
+ if (wp->w_buffer == buf && lnum >= wp->w_topline
+ && lnum < wp->w_botline)
+ {
+ if (wp->w_redraw_top == 0 || wp->w_redraw_top > lnum)
+ wp->w_redraw_top = lnum;
+ if (wp->w_redraw_bot == 0 || wp->w_redraw_bot < lnum)
+ wp->w_redraw_bot = lnum;
+ redraw_win_later(wp, VALID);
+ }
+ }
+ else
+ redraw_win_later(wp, VALID);
+ if (wp->w_redr_type != 0)
+ doit = TRUE;
+ }
+
+ if (!doit)
+ return;
+
+ /* update all windows that need updating */
+ update_prepare();
+
+# ifdef FEAT_WINDOWS
+ for (wp = firstwin; wp; wp = wp->w_next)
+ {
+ if (wp->w_redr_type != 0)
+ win_update(wp);
+ if (wp->w_redr_status)
+ win_redr_status(wp);
+ }
+# else
+ if (curwin->w_redr_type != 0)
+ win_update(curwin);
+# endif
+
+ update_finish();
+}
+#endif
+
+
+#if defined(FEAT_GUI) || defined(PROTO)
+/*
+ * Update a single window, its status line and maybe the command line msg.
+ * Used for the GUI scrollbar.
+ */
+ void
+updateWindow(wp)
+ win_T *wp;
+{
+ update_prepare();
+
+#ifdef FEAT_CLIPBOARD
+ /* When Visual area changed, may have to update selection. */
+ if (clip_star.available && clip_isautosel())
+ clip_update_selection();
+#endif
+ win_update(wp);
+#ifdef FEAT_WINDOWS
+ if (wp->w_redr_status
+# ifdef FEAT_CMDL_INFO
+ || p_ru
+# endif
+# ifdef FEAT_STL_OPT
+ || *p_stl
+# endif
+ )
+ win_redr_status(wp);
+#endif
+
+ update_finish();
+}
+#endif
+
+/*
+ * Update a single window.
+ *
+ * This may cause the windows below it also to be redrawn (when clearing the
+ * screen or scrolling lines).
+ *
+ * How the window is redrawn depends on wp->w_redr_type. Each type also
+ * implies the one below it.
+ * NOT_VALID redraw the whole window
+ * REDRAW_TOP redraw the top w_upd_rows window lines, otherwise like VALID
+ * INVERTED redraw the changed part of the Visual area
+ * INVERTED_ALL redraw the whole Visual area
+ * VALID 1. scroll up/down to adjust for a changed w_topline
+ * 2. update lines at the top when scrolled down
+ * 3. redraw changed text:
+ * - if wp->w_buffer->b_mod_set set, udpate lines between
+ * b_mod_top and b_mod_bot.
+ * - if wp->w_redraw_top non-zero, redraw lines between
+ * wp->w_redraw_top and wp->w_redr_bot.
+ * - continue redrawing when syntax status is invalid.
+ * 4. if scrolled up, update lines at the bottom.
+ * This results in three areas that may need updating:
+ * top: from first row to top_end (when scrolled down)
+ * mid: from mid_start to mid_end (update inversion or changed text)
+ * bot: from bot_start to last row (when scrolled up)
+ */
+ static void
+win_update(wp)
+ win_T *wp;
+{
+ buf_T *buf = wp->w_buffer;
+ int type;
+ int top_end = 0; /* Below last row of the top area that needs
+ updating. 0 when no top area updating. */
+ int mid_start = 999;/* first row of the mid area that needs
+ updating. 999 when no mid area updating. */
+ int mid_end = 0; /* Below last row of the mid area that needs
+ updating. 0 when no mid area updating. */
+ int bot_start = 999;/* first row of the bot area that needs
+ updating. 999 when no bot area updating */
+#ifdef FEAT_VISUAL
+ int scrolled_down = FALSE; /* TRUE when scrolled down when
+ w_topline got smaller a bit */
+#endif
+#ifdef FEAT_SEARCH_EXTRA
+ int top_to_mod = FALSE; /* redraw above mod_top */
+#endif
+
+ int row; /* current window row to display */
+ linenr_T lnum; /* current buffer lnum to display */
+ int idx; /* current index in w_lines[] */
+ int srow; /* starting row of the current line */
+
+ int eof = FALSE; /* if TRUE, we hit the end of the file */
+ int didline = FALSE; /* if TRUE, we finished the last line */
+ int i;
+ long j;
+ static int recursive = FALSE; /* being called recursively */
+ int old_botline = wp->w_botline;
+#ifdef FEAT_FOLDING
+ long fold_count;
+#endif
+#ifdef FEAT_SYN_HL
+ /* remember what happened to the previous line, to know if
+ * check_visual_highlight() can be used */
+#define DID_NONE 1 /* didn't update a line */
+#define DID_LINE 2 /* updated a normal line */
+#define DID_FOLD 3 /* updated a folded line */
+ int did_update = DID_NONE;
+ linenr_T syntax_last_parsed = 0; /* last parsed text line */
+#endif
+ linenr_T mod_top = 0;
+ linenr_T mod_bot = 0;
+#if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA)
+ int save_got_int;
+#endif
+
+ type = wp->w_redr_type;
+
+ if (type == NOT_VALID)
+ {
+#ifdef FEAT_WINDOWS
+ wp->w_redr_status = TRUE;
+#endif
+ wp->w_lines_valid = 0;
+ }
+
+ /* Window is zero-height: nothing to draw. */
+ if (wp->w_height == 0)
+ {
+ wp->w_redr_type = 0;
+ return;
+ }
+
+#ifdef FEAT_VERTSPLIT
+ /* Window is zero-width: Only need to draw the separator. */
+ if (wp->w_width == 0)
+ {
+ /* draw the vertical separator right of this window */
+ draw_vsep_win(wp, 0);
+ wp->w_redr_type = 0;
+ return;
+ }
+#endif
+
+#ifdef FEAT_SEARCH_EXTRA
+ /* Setup for ":match" highlighting. Disable any previous match */
+ match_hl.rm = wp->w_match;
+ if (wp->w_match_id == 0)
+ match_hl.attr = 0;
+ else
+ match_hl.attr = syn_id2attr(wp->w_match_id);
+ match_hl.buf = buf;
+ match_hl.lnum = 0;
+ search_hl.buf = buf;
+ search_hl.lnum = 0;
+ search_hl.first_lnum = 0;
+#endif
+
+ if (buf->b_mod_set && buf->b_mod_xlines != 0 && wp->w_redraw_top != 0)
+ {
+ /*
+ * When there are both inserted/deleted lines and specific lines to be
+ * redrawn, w_redraw_top and w_redraw_bot may be invalid, just redraw
+ * everything (only happens when redrawing is off for while).
+ */
+ type = NOT_VALID;
+ }
+ else
+ {
+ /*
+ * Set mod_top to the first line that needs displaying because of
+ * changes. Set mod_bot to the first line after the changes.
+ */
+ mod_top = wp->w_redraw_top;
+ if (wp->w_redraw_bot != 0)
+ mod_bot = wp->w_redraw_bot + 1;
+ else
+ mod_bot = 0;
+ wp->w_redraw_top = 0; /* reset for next time */
+ wp->w_redraw_bot = 0;
+ if (buf->b_mod_set)
+ {
+ if (mod_top == 0 || mod_top > buf->b_mod_top)
+ {
+ mod_top = buf->b_mod_top;
+#ifdef FEAT_SYN_HL
+ /* Need to redraw lines above the change that may be included
+ * in a pattern match. */
+ if (syntax_present(buf))
+ {
+ mod_top -= buf->b_syn_sync_linebreaks;
+ if (mod_top < 1)
+ mod_top = 1;
+ }
+#endif
+ }
+ if (mod_bot == 0 || mod_bot < buf->b_mod_bot)
+ mod_bot = buf->b_mod_bot;
+
+#ifdef FEAT_SEARCH_EXTRA
+ /* When 'hlsearch' is on and using a multi-line search pattern, a
+ * change in one line may make the Search highlighting in a
+ * previous line invalid. Simple solution: redraw all visible
+ * lines above the change.
+ * Same for a ":match" pattern.
+ */
+ if ((search_hl.rm.regprog != NULL
+ && re_multiline(search_hl.rm.regprog))
+ || (match_hl.rm.regprog != NULL
+ && re_multiline(match_hl.rm.regprog)))
+ top_to_mod = TRUE;
+#endif
+ }
+#ifdef FEAT_FOLDING
+ if (mod_top != 0 && hasAnyFolding(wp))
+ {
+ linenr_T lnumt, lnumb;
+
+ /*
+ * A change in a line can cause lines above it to become folded or
+ * unfolded. Find the top most buffer line that may be affected.
+ * If the line was previously folded and displayed, get the first
+ * line of that fold. If the line is folded now, get the first
+ * folded line. Use the minimum of these two.
+ */
+
+ /* Find last valid w_lines[] entry above mod_top. Set lnumt to
+ * the line below it. If there is no valid entry, use w_topline.
+ * Find the first valid w_lines[] entry below mod_bot. Set lnumb
+ * to this line. If there is no valid entry, use MAXLNUM. */
+ lnumt = wp->w_topline;
+ lnumb = MAXLNUM;
+ for (i = 0; i < wp->w_lines_valid; ++i)
+ if (wp->w_lines[i].wl_valid)
+ {
+ if (wp->w_lines[i].wl_lastlnum < mod_top)
+ lnumt = wp->w_lines[i].wl_lastlnum + 1;
+ if (lnumb == MAXLNUM && wp->w_lines[i].wl_lnum >= mod_bot)
+ {
+ lnumb = wp->w_lines[i].wl_lnum;
+ /* When there is a fold column it might need updating
+ * in the next line ("J" just above an open fold). */
+ if (wp->w_p_fdc > 0)
+ ++lnumb;
+ }
+ }
+
+ (void)hasFoldingWin(wp, mod_top, &mod_top, NULL, TRUE, NULL);
+ if (mod_top > lnumt)
+ mod_top = lnumt;
+
+ /* Now do the same for the bottom line (one above mod_bot). */
+ --mod_bot;
+ (void)hasFoldingWin(wp, mod_bot, NULL, &mod_bot, TRUE, NULL);
+ ++mod_bot;
+ if (mod_bot < lnumb)
+ mod_bot = lnumb;
+ }
+#endif
+
+ /* When a change starts above w_topline and the end is below
+ * w_topline, start redrawing at w_topline.
+ * If the end of the change is above w_topline: do like no changes was
+ * maded, but redraw the first line to find changes in syntax. */
+ if (mod_top != 0 && mod_top < wp->w_topline)
+ {
+ if (mod_bot > wp->w_topline)
+ mod_top = wp->w_topline;
+#ifdef FEAT_SYN_HL
+ else if (syntax_present(buf))
+ top_end = 1;
+#endif
+ }
+ }
+
+ /*
+ * When only displaying the lines at the top, set top_end. Used when
+ * window has scrolled down for msg_scrolled.
+ */
+ if (type == REDRAW_TOP)
+ {
+ j = 0;
+ for (i = 0; i < wp->w_lines_valid; ++i)
+ {
+ j += wp->w_lines[i].wl_size;
+ if (j >= wp->w_upd_rows)
+ {
+ top_end = j;
+ break;
+ }
+ }
+ if (top_end == 0)
+ /* not found (cannot happen?): redraw everything */
+ type = NOT_VALID;
+ else
+ /* top area defined, the rest is VALID */
+ type = VALID;
+ }
+
+ /*
+ * If there are no changes on the screen that require a complete redraw,
+ * handle three cases:
+ * 1: we are off the top of the screen by a few lines: scroll down
+ * 2: wp->w_topline is below wp->w_lines[0].wl_lnum: may scroll up
+ * 3: wp->w_topline is wp->w_lines[0].wl_lnum: find first entry in
+ * w_lines[] that needs updating.
+ */
+ if ((type == VALID || type == INVERTED || type == INVERTED_ALL)
+#ifdef FEAT_DIFF
+ && !wp->w_botfill && !wp->w_old_botfill
+#endif
+ )
+ {
+ if (mod_top != 0 && wp->w_topline == mod_top)
+ {
+ /*
+ * w_topline is the first changed line, the scrolling will be done
+ * further down.
+ */
+ }
+ else if (wp->w_lines[0].wl_valid
+ && (wp->w_topline < wp->w_lines[0].wl_lnum
+#ifdef FEAT_DIFF
+ || (wp->w_topline == wp->w_lines[0].wl_lnum
+ && wp->w_topfill > wp->w_old_topfill)
+#endif
+ ))
+ {
+ /*
+ * New topline is above old topline: May scroll down.
+ */
+#ifdef FEAT_FOLDING
+ if (hasAnyFolding(wp))
+ {
+ linenr_T ln;
+
+ /* count the number of lines we are off, counting a sequence
+ * of folded lines as one */
+ j = 0;
+ for (ln = wp->w_topline; ln < wp->w_lines[0].wl_lnum; ++ln)
+ {
+ ++j;
+ if (j >= wp->w_height - 2)
+ break;
+ (void)hasFoldingWin(wp, ln, NULL, &ln, TRUE, NULL);
+ }
+ }
+ else
+#endif
+ j = wp->w_lines[0].wl_lnum - wp->w_topline;
+ if (j < wp->w_height - 2) /* not too far off */
+ {
+ i = plines_m_win(wp, wp->w_topline, wp->w_lines[0].wl_lnum - 1);
+#ifdef FEAT_DIFF
+ /* insert extra lines for previously invisible filler lines */
+ if (wp->w_lines[0].wl_lnum != wp->w_topline)
+ i += diff_check_fill(wp, wp->w_lines[0].wl_lnum)
+ - wp->w_old_topfill;
+#endif
+ if (i < wp->w_height - 2) /* less than a screen off */
+ {
+ /*
+ * Try to insert the correct number of lines.
+ * If not the last window, delete the lines at the bottom.
+ * win_ins_lines may fail when the terminal can't do it.
+ */
+ if (i > 0)
+ check_for_delay(FALSE);
+ if (win_ins_lines(wp, 0, i, FALSE, wp == firstwin) == OK)
+ {
+ if (wp->w_lines_valid != 0)
+ {
+ /* Need to update rows that are new, stop at the
+ * first one that scrolled down. */
+ top_end = i;
+#ifdef FEAT_VISUAL
+ scrolled_down = TRUE;
+#endif
+
+ /* Move the entries that were scrolled, disable
+ * the entries for the lines to be redrawn. */
+ if ((wp->w_lines_valid += j) > wp->w_height)
+ wp->w_lines_valid = wp->w_height;
+ for (idx = wp->w_lines_valid; idx - j >= 0; idx--)
+ wp->w_lines[idx] = wp->w_lines[idx - j];
+ while (idx >= 0)
+ wp->w_lines[idx--].wl_valid = FALSE;
+ }
+ }
+ else
+ mid_start = 0; /* redraw all lines */
+ }
+ else
+ mid_start = 0; /* redraw all lines */
+ }
+ else
+ mid_start = 0; /* redraw all lines */
+ }
+ else
+ {
+ /*
+ * New topline is at or below old topline: May scroll up.
+ * When topline didn't change, find first entry in w_lines[] that
+ * needs updating.
+ */
+
+ /* try to find wp->w_topline in wp->w_lines[].wl_lnum */
+ j = -1;
+ row = 0;
+ for (i = 0; i < wp->w_lines_valid; i++)
+ {
+ if (wp->w_lines[i].wl_valid
+ && wp->w_lines[i].wl_lnum == wp->w_topline)
+ {
+ j = i;
+ break;
+ }
+ row += wp->w_lines[i].wl_size;
+ }
+ if (j == -1)
+ {
+ /* if wp->w_topline is not in wp->w_lines[].wl_lnum redraw all
+ * lines */
+ mid_start = 0;
+ }
+ else
+ {
+ /*
+ * Try to delete the correct number of lines.
+ * wp->w_topline is at wp->w_lines[i].wl_lnum.
+ */
+#ifdef FEAT_DIFF
+ /* If the topline didn't change, delete old filler lines,
+ * otherwise delete filler lines of the new topline... */
+ if (wp->w_lines[0].wl_lnum == wp->w_topline)
+ row += wp->w_old_topfill;
+ else
+ row += diff_check_fill(wp, wp->w_topline);
+ /* ... but don't delete new filler lines. */
+ row -= wp->w_topfill;
+#endif
+ if (row > 0)
+ {
+ check_for_delay(FALSE);
+ if (win_del_lines(wp, 0, row, FALSE, wp == firstwin) == OK)
+ bot_start = wp->w_height - row;
+ else
+ mid_start = 0; /* redraw all lines */
+ }
+ if ((row == 0 || bot_start < 999) && wp->w_lines_valid != 0)
+ {
+ /*
+ * Skip the lines (below the deleted lines) that are still
+ * valid and don't need redrawing. Copy their info
+ * upwards, to compensate for the deleted lines. Set
+ * bot_start to the first row that needs redrawing.
+ */
+ bot_start = 0;
+ idx = 0;
+ for (;;)
+ {
+ wp->w_lines[idx] = wp->w_lines[j];
+ /* stop at line that didn't fit, unless it is still
+ * valid (no lines deleted) */
+ if (row > 0 && bot_start + row
+ + (int)wp->w_lines[j].wl_size > wp->w_height)
+ {
+ wp->w_lines_valid = idx + 1;
+ break;
+ }
+ bot_start += wp->w_lines[idx++].wl_size;
+
+ /* stop at the last valid entry in w_lines[].wl_size */
+ if (++j >= wp->w_lines_valid)
+ {
+ wp->w_lines_valid = idx;
+ break;
+ }
+ }
+#ifdef FEAT_DIFF
+ /* Correct the first entry for filler lines at the top
+ * when it won't get updated below. */
+ if (wp->w_p_diff && bot_start > 0)
+ wp->w_lines[0].wl_size =
+ plines_win_nofill(wp, wp->w_topline, TRUE)
+ + wp->w_topfill;
+#endif
+ }
+ }
+ }
+
+ /* When starting redraw in the first line, redraw all lines. When
+ * there is only one window it's probably faster to clear the screen
+ * first. */
+ if (mid_start == 0)
+ {
+ mid_end = wp->w_height;
+ if (lastwin == firstwin)
+ screenclear();
+ }
+ }
+ else
+ {
+ /* Not VALID or INVERTED: redraw all lines. */
+ mid_start = 0;
+ mid_end = wp->w_height;
+ }
+
+#ifdef FEAT_VISUAL
+ /* check if we are updating or removing the inverted part */
+ if ((VIsual_active && buf == curwin->w_buffer)
+ || (wp->w_old_cursor_lnum != 0 && type != NOT_VALID))
+ {
+ linenr_T from, to;
+
+ if (VIsual_active)
+ {
+ if (VIsual_active
+ && (VIsual_mode != wp->w_old_visual_mode
+ || type == INVERTED_ALL))
+ {
+ /*
+ * If the type of Visual selection changed, redraw the whole
+ * selection. Also when the ownership of the X selection is
+ * gained or lost.
+ */
+ if (curwin->w_cursor.lnum < VIsual.lnum)
+ {
+ from = curwin->w_cursor.lnum;
+ to = VIsual.lnum;
+ }
+ else
+ {
+ from = VIsual.lnum;
+ to = curwin->w_cursor.lnum;
+ }
+ /* redraw more when the cursor moved as well */
+ if (wp->w_old_cursor_lnum < from)
+ from = wp->w_old_cursor_lnum;
+ if (wp->w_old_cursor_lnum > to)
+ to = wp->w_old_cursor_lnum;
+ if (wp->w_old_visual_lnum < from)
+ from = wp->w_old_visual_lnum;
+ if (wp->w_old_visual_lnum > to)
+ to = wp->w_old_visual_lnum;
+ }
+ else
+ {
+ /*
+ * Find the line numbers that need to be updated: The lines
+ * between the old cursor position and the current cursor
+ * position. Also check if the Visual position changed.
+ */
+ if (curwin->w_cursor.lnum < wp->w_old_cursor_lnum)
+ {
+ from = curwin->w_cursor.lnum;
+ to = wp->w_old_cursor_lnum;
+ }
+ else
+ {
+ from = wp->w_old_cursor_lnum;
+ to = curwin->w_cursor.lnum;
+ if (from == 0) /* Visual mode just started */
+ from = to;
+ }
+
+ if (VIsual.lnum != wp->w_old_visual_lnum)
+ {
+ if (wp->w_old_visual_lnum < from
+ && wp->w_old_visual_lnum != 0)
+ from = wp->w_old_visual_lnum;
+ if (wp->w_old_visual_lnum > to)
+ to = wp->w_old_visual_lnum;
+ if (VIsual.lnum < from)
+ from = VIsual.lnum;
+ if (VIsual.lnum > to)
+ to = VIsual.lnum;
+ }
+ }
+
+ /*
+ * If in block mode and changed column or curwin->w_curswant:
+ * update all lines.
+ * First compute the actual start and end column.
+ */
+ if (VIsual_mode == Ctrl_V)
+ {
+ colnr_T fromc, toc;
+
+ getvcols(wp, &VIsual, &curwin->w_cursor, &fromc, &toc);
+ ++toc;
+ if (curwin->w_curswant == MAXCOL)
+ toc = MAXCOL;
+
+ if (fromc != wp->w_old_cursor_fcol
+ || toc != wp->w_old_cursor_lcol)
+ {
+ if (from > VIsual.lnum)
+ from = VIsual.lnum;
+ if (to < VIsual.lnum)
+ to = VIsual.lnum;
+ }
+ wp->w_old_cursor_fcol = fromc;
+ wp->w_old_cursor_lcol = toc;
+ }
+ }
+ else
+ {
+ /* Use the line numbers of the old Visual area. */
+ if (wp->w_old_cursor_lnum < wp->w_old_visual_lnum)
+ {
+ from = wp->w_old_cursor_lnum;
+ to = wp->w_old_visual_lnum;
+ }
+ else
+ {
+ from = wp->w_old_visual_lnum;
+ to = wp->w_old_cursor_lnum;
+ }
+ }
+
+ /*
+ * There is no need to update lines above the top of the window.
+ */
+ if (from < wp->w_topline)
+ from = wp->w_topline;
+
+ /*
+ * If we know the value of w_botline, use it to restrict the update to
+ * the lines that are visible in the window.
+ */
+ if (wp->w_valid & VALID_BOTLINE)
+ {
+ if (from >= wp->w_botline)
+ from = wp->w_botline - 1;
+ if (to >= wp->w_botline)
+ to = wp->w_botline - 1;
+ }
+
+ /*
+ * Find the minimal part to be updated.
+ * Watch out for scrolling that made entries in w_lines[] invalid.
+ * E.g., CTRL-U makes the first half of w_lines[] invalid and sets
+ * top_end; need to redraw from top_end to the "to" line.
+ * A middle mouse click with a Visual selection may change the text
+ * above the Visual area and reset wl_valid, do count these for
+ * mid_end (in srow).
+ */
+ if (mid_start > 0)
+ {
+ lnum = wp->w_topline;
+ idx = 0;
+ srow = 0;
+ if (scrolled_down)
+ mid_start = top_end;
+ else
+ mid_start = 0;
+ while (lnum < from && idx < wp->w_lines_valid) /* find start */
+ {
+ if (wp->w_lines[idx].wl_valid)
+ mid_start += wp->w_lines[idx].wl_size;
+ else if (!scrolled_down)
+ srow += wp->w_lines[idx].wl_size;
+ ++idx;
+# ifdef FEAT_FOLDING
+ if (idx < wp->w_lines_valid && wp->w_lines[idx].wl_valid)
+ lnum = wp->w_lines[idx].wl_lnum;
+ else
+# endif
+ ++lnum;
+ }
+ srow += mid_start;
+ mid_end = wp->w_height;
+ for ( ; idx < wp->w_lines_valid; ++idx) /* find end */
+ {
+ if (wp->w_lines[idx].wl_valid
+ && wp->w_lines[idx].wl_lnum >= to + 1)
+ {
+ /* Only update until first row of this line */
+ mid_end = srow;
+ break;
+ }
+ srow += wp->w_lines[idx].wl_size;
+ }
+ }
+ }
+
+ if (VIsual_active && buf == curwin->w_buffer)
+ {
+ wp->w_old_visual_mode = VIsual_mode;
+ wp->w_old_cursor_lnum = curwin->w_cursor.lnum;
+ wp->w_old_visual_lnum = VIsual.lnum;
+ wp->w_old_curswant = curwin->w_curswant;
+ }
+ else
+ {
+ wp->w_old_visual_mode = 0;
+ wp->w_old_cursor_lnum = 0;
+ wp->w_old_visual_lnum = 0;
+ }
+#endif /* FEAT_VISUAL */
+
+#if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA)
+ /* reset got_int, otherwise regexp won't work */
+ save_got_int = got_int;
+ got_int = 0;
+#endif
+#ifdef FEAT_FOLDING
+ win_foldinfo.fi_level = 0;
+#endif
+
+ /*
+ * Update all the window rows.
+ */
+ idx = 0; /* first entry in w_lines[].wl_size */
+ row = 0;
+ srow = 0;
+ lnum = wp->w_topline; /* first line shown in window */
+ for (;;)
+ {
+ /* stop updating when reached the end of the window (check for _past_
+ * the end of the window is at the end of the loop) */
+ if (row == wp->w_height)
+ {
+ didline = TRUE;
+ break;
+ }
+
+ /* stop updating when hit the end of the file */
+ if (lnum > buf->b_ml.ml_line_count)
+ {
+ eof = TRUE;
+ break;
+ }
+
+ /* Remember the starting row of the line that is going to be dealt
+ * with. It is used further down when the line doesn't fit. */
+ srow = row;
+
+ /*
+ * Update a line when it is in an area that needs updating, when it
+ * has changes or w_lines[idx] is invalid.
+ * bot_start may be halfway a wrapped line after using
+ * win_del_lines(), check if the current line includes it.
+ * When syntax folding is being used, the saved syntax states will
+ * already have been updated, we can't see where the syntax state is
+ * the same again, just update until the end of the window.
+ */
+ if (row < top_end
+ || (row >= mid_start && row < mid_end)
+#ifdef FEAT_SEARCH_EXTRA
+ || top_to_mod
+#endif
+ || idx >= wp->w_lines_valid
+ || (row + wp->w_lines[idx].wl_size > bot_start)
+ || (mod_top != 0
+ && (lnum == mod_top
+ || (lnum >= mod_top
+ && (lnum < mod_bot
+#ifdef FEAT_SYN_HL
+ || did_update == DID_FOLD
+ || (did_update == DID_LINE
+ && syntax_present(buf)
+ && (
+# ifdef FEAT_FOLDING
+ (foldmethodIsSyntax(wp)
+ && hasAnyFolding(wp)) ||
+# endif
+ syntax_check_changed(lnum)))
+#endif
+ )))))
+ {
+#ifdef FEAT_SEARCH_EXTRA
+ if (lnum == mod_top)
+ top_to_mod = FALSE;
+#endif
+
+ /*
+ * When at start of changed lines: May scroll following lines
+ * up or down to minimize redrawing.
+ * Don't do this when the change continues until the end.
+ * Don't scroll when dollar_vcol is non-zero, keep the "$".
+ */
+ if (lnum == mod_top
+ && mod_bot != MAXLNUM
+ && !(dollar_vcol != 0 && mod_bot == mod_top + 1))
+ {
+ int old_rows = 0;
+ int new_rows = 0;
+ int xtra_rows;
+ linenr_T l;
+
+ /* Count the old number of window rows, using w_lines[], which
+ * should still contain the sizes for the lines as they are
+ * currently displayed. */
+ for (i = idx; i < wp->w_lines_valid; ++i)
+ {
+ /* Only valid lines have a meaningful wl_lnum. Invalid
+ * lines are part of the changed area. */
+ if (wp->w_lines[i].wl_valid
+ && wp->w_lines[i].wl_lnum == mod_bot)
+ break;
+ old_rows += wp->w_lines[i].wl_size;
+#ifdef FEAT_FOLDING
+ if (wp->w_lines[i].wl_valid
+ && wp->w_lines[i].wl_lastlnum + 1 == mod_bot)
+ {
+ /* Must have found the last valid entry above mod_bot.
+ * Add following invalid entries. */
+ ++i;
+ while (i < wp->w_lines_valid
+ && !wp->w_lines[i].wl_valid)
+ old_rows += wp->w_lines[i++].wl_size;
+ break;
+ }
+#endif
+ }
+
+ if (i >= wp->w_lines_valid)
+ {
+ /* We can't find a valid line below the changed lines,
+ * need to redraw until the end of the window.
+ * Inserting/deleting lines has no use. */
+ bot_start = 0;
+ }
+ else
+ {
+ /* Able to count old number of rows: Count new window
+ * rows, and may insert/delete lines */
+ j = idx;
+ for (l = lnum; l < mod_bot; ++l)
+ {
+#ifdef FEAT_FOLDING
+ if (hasFoldingWin(wp, l, NULL, &l, TRUE, NULL))
+ ++new_rows;
+ else
+#endif
+#ifdef FEAT_DIFF
+ if (l == wp->w_topline)
+ new_rows += plines_win_nofill(wp, l, TRUE)
+ + wp->w_topfill;
+ else
+#endif
+ new_rows += plines_win(wp, l, TRUE);
+ ++j;
+ if (new_rows > wp->w_height - row - 2)
+ {
+ /* it's getting too much, must redraw the rest */
+ new_rows = 9999;
+ break;
+ }
+ }
+ xtra_rows = new_rows - old_rows;
+ if (xtra_rows < 0)
+ {
+ /* May scroll text up. If there is not enough
+ * remaining text or scrolling fails, must redraw the
+ * rest. If scrolling works, must redraw the text
+ * below the scrolled text. */
+ if (row - xtra_rows >= wp->w_height - 2)
+ mod_bot = MAXLNUM;
+ else
+ {
+ check_for_delay(FALSE);
+ if (win_del_lines(wp, row,
+ -xtra_rows, FALSE, FALSE) == FAIL)
+ mod_bot = MAXLNUM;
+ else
+ bot_start = wp->w_height + xtra_rows;
+ }
+ }
+ else if (xtra_rows > 0)
+ {
+ /* May scroll text down. If there is not enough
+ * remaining text of scrolling fails, must redraw the
+ * rest. */
+ if (row + xtra_rows >= wp->w_height - 2)
+ mod_bot = MAXLNUM;
+ else
+ {
+ check_for_delay(FALSE);
+ if (win_ins_lines(wp, row + old_rows,
+ xtra_rows, FALSE, FALSE) == FAIL)
+ mod_bot = MAXLNUM;
+ else if (top_end > row + old_rows)
+ /* Scrolled the part at the top that requires
+ * updating down. */
+ top_end += xtra_rows;
+ }
+ }
+
+ /* When not updating the rest, may need to move w_lines[]
+ * entries. */
+ if (mod_bot != MAXLNUM && i != j)
+ {
+ if (j < i)
+ {
+ int x = row + new_rows;
+
+ /* move entries in w_lines[] upwards */
+ for (;;)
+ {
+ /* stop at last valid entry in w_lines[] */
+ if (i >= wp->w_lines_valid)
+ {
+ wp->w_lines_valid = j;
+ break;
+ }
+ wp->w_lines[j] = wp->w_lines[i];
+ /* stop at a line that won't fit */
+ if (x + (int)wp->w_lines[j].wl_size
+ > wp->w_height)
+ {
+ wp->w_lines_valid = j + 1;
+ break;
+ }
+ x += wp->w_lines[j++].wl_size;
+ ++i;
+ }
+ if (bot_start > x)
+ bot_start = x;
+ }
+ else /* j > i */
+ {
+ /* move entries in w_lines[] downwards */
+ j -= i;
+ wp->w_lines_valid += j;
+ if (wp->w_lines_valid > wp->w_height)
+ wp->w_lines_valid = wp->w_height;
+ for (i = wp->w_lines_valid; i - j >= idx; --i)
+ wp->w_lines[i] = wp->w_lines[i - j];
+
+ /* The w_lines[] entries for inserted lines are
+ * now invalid, but wl_size may be used above.
+ * Reset to zero. */
+ while (i >= idx)
+ {
+ wp->w_lines[i].wl_size = 0;
+ wp->w_lines[i--].wl_valid = FALSE;
+ }
+ }
+ }
+ }
+
+ /* When inserting or deleting lines and 'number' is set:
+ * Redraw all lines below the change to update the line
+ * numbers. */
+ if (buf->b_mod_xlines != 0 && wp->w_p_nu)
+ bot_start = 0;
+ }
+
+#ifdef FEAT_FOLDING
+ /*
+ * When lines are folded, display one line for all of them.
+ * Otherwise, display normally (can be several display lines when
+ * 'wrap' is on).
+ */
+ fold_count = foldedCount(wp, lnum, &win_foldinfo);
+ if (fold_count != 0)
+ {
+ fold_line(wp, fold_count, &win_foldinfo, lnum, row);
+ ++row;
+ --fold_count;
+ wp->w_lines[idx].wl_folded = TRUE;
+ wp->w_lines[idx].wl_lastlnum = lnum + fold_count;
+# ifdef FEAT_SYN_HL
+ did_update = DID_FOLD;
+# endif
+ }
+ else
+#endif
+ if (idx < wp->w_lines_valid
+ && wp->w_lines[idx].wl_valid
+ && wp->w_lines[idx].wl_lnum == lnum
+ && lnum > wp->w_topline
+ && !(dy_flags & DY_LASTLINE)
+ && srow + wp->w_lines[idx].wl_size > wp->w_height
+#ifdef FEAT_DIFF
+ && diff_check_fill(wp, lnum) == 0
+#endif
+ )
+ {
+ /* This line is not going to fit. Don't draw anything here,
+ * will draw "@ " lines below. */
+ row = wp->w_height + 1;
+ }
+ else
+ {
+#ifdef FEAT_SEARCH_EXTRA
+ prepare_search_hl(wp, lnum);
+#endif
+#ifdef FEAT_SYN_HL
+ /* Let the syntax stuff know we skipped a few lines. */
+ if (syntax_last_parsed != 0 && syntax_last_parsed + 1 < lnum
+ && syntax_present(buf))
+ syntax_end_parsing(syntax_last_parsed + 1);
+#endif
+
+ /*
+ * Display one line.
+ */
+ row = win_line(wp, lnum, srow, wp->w_height);
+
+#ifdef FEAT_FOLDING
+ wp->w_lines[idx].wl_folded = FALSE;
+ wp->w_lines[idx].wl_lastlnum = lnum;
+#endif
+#ifdef FEAT_SYN_HL
+ did_update = DID_LINE;
+ syntax_last_parsed = lnum;
+#endif
+ }
+
+ wp->w_lines[idx].wl_lnum = lnum;
+ wp->w_lines[idx].wl_valid = TRUE;
+ if (row > wp->w_height) /* past end of screen */
+ {
+ /* we may need the size of that too long line later on */
+ if (dollar_vcol == 0)
+ wp->w_lines[idx].wl_size = plines_win(wp, lnum, TRUE);
+ ++idx;
+ break;
+ }
+ if (dollar_vcol == 0)
+ wp->w_lines[idx].wl_size = row - srow;
+ ++idx;
+#ifdef FEAT_FOLDING
+ lnum += fold_count + 1;
+#else
+ ++lnum;
+#endif
+ }
+ else
+ {
+ /* This line does not need updating, advance to the next one */
+ row += wp->w_lines[idx++].wl_size;
+ if (row > wp->w_height) /* past end of screen */
+ break;
+#ifdef FEAT_FOLDING
+ lnum = wp->w_lines[idx - 1].wl_lastlnum + 1;
+#else
+ ++lnum;
+#endif
+#ifdef FEAT_SYN_HL
+ did_update = DID_NONE;
+#endif
+ }
+
+ if (lnum > buf->b_ml.ml_line_count)
+ {
+ eof = TRUE;
+ break;
+ }
+ }
+ /*
+ * End of loop over all window lines.
+ */
+
+
+ if (idx > wp->w_lines_valid)
+ wp->w_lines_valid = idx;
+
+#ifdef FEAT_SYN_HL
+ /*
+ * Let the syntax stuff know we stop parsing here.
+ */
+ if (syntax_last_parsed != 0 && syntax_present(buf))
+ syntax_end_parsing(syntax_last_parsed + 1);
+#endif
+
+ /*
+ * If we didn't hit the end of the file, and we didn't finish the last
+ * line we were working on, then the line didn't fit.
+ */
+ wp->w_empty_rows = 0;
+#ifdef FEAT_DIFF
+ wp->w_filler_rows = 0;
+#endif
+ if (!eof && !didline)
+ {
+ if (lnum == wp->w_topline)
+ {
+ /*
+ * Single line that does not fit!
+ * Don't overwrite it, it can be edited.
+ */
+ wp->w_botline = lnum + 1;
+ }
+#ifdef FEAT_DIFF
+ else if (diff_check_fill(wp, lnum) >= wp->w_height - srow)
+ {
+ /* Window ends in filler lines. */
+ wp->w_botline = lnum;
+ wp->w_filler_rows = wp->w_height - srow;
+ }
+#endif
+ else if (dy_flags & DY_LASTLINE) /* 'display' has "lastline" */
+ {
+ /*
+ * Last line isn't finished: Display "@@@" at the end.
+ */
+ screen_fill(W_WINROW(wp) + wp->w_height - 1,
+ W_WINROW(wp) + wp->w_height,
+ (int)W_ENDCOL(wp) - 3, (int)W_ENDCOL(wp),
+ '@', '@', hl_attr(HLF_AT));
+ set_empty_rows(wp, srow);
+ wp->w_botline = lnum;
+ }
+ else
+ {
+ win_draw_end(wp, '@', ' ', srow, wp->w_height, HLF_AT);
+ wp->w_botline = lnum;
+ }
+ }
+ else
+ {
+#ifdef FEAT_VERTSPLIT
+ draw_vsep_win(wp, row);
+#endif
+ if (eof) /* we hit the end of the file */
+ {
+ wp->w_botline = buf->b_ml.ml_line_count + 1;
+#ifdef FEAT_DIFF
+ j = diff_check_fill(wp, wp->w_botline);
+ if (j > 0 && !wp->w_botfill)
+ {
+ /*
+ * Display filler lines at the end of the file
+ */
+ if (char2cells(fill_diff) > 1)
+ i = '-';
+ else
+ i = fill_diff;
+ if (row + j > wp->w_height)
+ j = wp->w_height - row;
+ win_draw_end(wp, i, i, row, row + (int)j, HLF_DED);
+ row += j;
+ }
+#endif
+ }
+ else if (dollar_vcol == 0)
+ wp->w_botline = lnum;
+
+ /* make sure the rest of the screen is blank */
+ /* put '~'s on rows that aren't part of the file. */
+ win_draw_end(wp, '~', ' ', row, wp->w_height, HLF_AT);
+ }
+
+ /* Reset the type of redrawing required, the window has been updated. */
+ wp->w_redr_type = 0;
+#ifdef FEAT_DIFF
+ wp->w_old_topfill = wp->w_topfill;
+ wp->w_old_botfill = wp->w_botfill;
+#endif
+
+ if (dollar_vcol == 0)
+ {
+ /*
+ * There is a trick with w_botline. If we invalidate it on each
+ * change that might modify it, this will cause a lot of expensive
+ * calls to plines() in update_topline() each time. Therefore the
+ * value of w_botline is often approximated, and this value is used to
+ * compute the value of w_topline. If the value of w_botline was
+ * wrong, check that the value of w_topline is correct (cursor is on
+ * the visible part of the text). If it's not, we need to redraw
+ * again. Mostly this just means scrolling up a few lines, so it
+ * doesn't look too bad. Only do this for the current window (where
+ * changes are relevant).
+ */
+ wp->w_valid |= VALID_BOTLINE;
+ if (wp == curwin && wp->w_botline != old_botline && !recursive)
+ {
+ recursive = TRUE;
+ curwin->w_valid &= ~VALID_TOPLINE;
+ update_topline(); /* may invalidate w_botline again */
+ if (must_redraw != 0)
+ {
+ /* Don't update for changes in buffer again. */
+ i = curbuf->b_mod_set;
+ curbuf->b_mod_set = FALSE;
+ win_update(curwin);
+ must_redraw = 0;
+ curbuf->b_mod_set = i;
+ }
+ recursive = FALSE;
+ }
+ }
+
+#if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA)
+ /* restore got_int, unless CTRL-C was hit while redrawing */
+ if (!got_int)
+ got_int = save_got_int;
+#endif
+}
+
+#ifdef FEAT_SIGNS
+static int draw_signcolumn __ARGS((win_T *wp));
+
+/*
+ * Return TRUE when window "wp" has a column to draw signs in.
+ */
+ static int
+draw_signcolumn(wp)
+ win_T *wp;
+{
+ return (wp->w_buffer->b_signlist != NULL
+# ifdef FEAT_NETBEANS_INTG
+ || usingNetbeans
+# endif
+ );
+}
+#endif
+
+/*
+ * Clear the rest of the window and mark the unused lines with "c1". use "c2"
+ * as the filler character.
+ */
+ static void
+win_draw_end(wp, c1, c2, row, endrow, hl)
+ win_T *wp;
+ int c1;
+ int c2;
+ int row;
+ int endrow;
+ enum hlf_value hl;
+{
+#if defined(FEAT_FOLDING) || defined(FEAT_SIGNS) || defined(FEAT_CMDWIN)
+ int n = 0;
+# define FDC_OFF n
+#else
+# define FDC_OFF 0
+#endif
+
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ {
+ /* No check for cmdline window: should never be right-left. */
+# ifdef FEAT_FOLDING
+ n = wp->w_p_fdc;
+
+ if (n > 0)
+ {
+ /* draw the fold column at the right */
+ if (n > wp->w_width)
+ n = wp->w_width;
+ screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
+ W_ENDCOL(wp) - n, (int)W_ENDCOL(wp),
+ ' ', ' ', hl_attr(HLF_FC));
+ }
+# endif
+# ifdef FEAT_SIGNS
+ if (draw_signcolumn(wp))
+ {
+ int nn = n + 2;
+
+ /* draw the sign column left of the fold column */
+ if (nn > wp->w_width)
+ nn = wp->w_width;
+ screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
+ W_ENDCOL(wp) - nn, (int)W_ENDCOL(wp) - n,
+ ' ', ' ', hl_attr(HLF_SC));
+ n = nn;
+ }
+# endif
+ screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
+ W_WINCOL(wp), W_ENDCOL(wp) - 1 - FDC_OFF,
+ c2, c2, hl_attr(hl));
+ screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
+ W_ENDCOL(wp) - 1 - FDC_OFF, W_ENDCOL(wp) - FDC_OFF,
+ c1, c2, hl_attr(hl));
+ }
+ else
+#endif
+ {
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0 && wp == curwin)
+ {
+ /* draw the cmdline character in the leftmost column */
+ n = 1;
+ if (n > wp->w_width)
+ n = wp->w_width;
+ screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
+ W_WINCOL(wp), (int)W_WINCOL(wp) + n,
+ cmdwin_type, ' ', hl_attr(HLF_AT));
+ }
+#endif
+#ifdef FEAT_FOLDING
+ if (wp->w_p_fdc > 0)
+ {
+ int nn = n + wp->w_p_fdc;
+
+ /* draw the fold column at the left */
+ if (nn > W_WIDTH(wp))
+ nn = W_WIDTH(wp);
+ screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
+ W_WINCOL(wp) + n, (int)W_WINCOL(wp) + nn,
+ ' ', ' ', hl_attr(HLF_FC));
+ n = nn;
+ }
+#endif
+#ifdef FEAT_SIGNS
+ if (draw_signcolumn(wp))
+ {
+ int nn = n + 2;
+
+ /* draw the sign column after the fold column */
+ if (nn > W_WIDTH(wp))
+ nn = W_WIDTH(wp);
+ screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
+ W_WINCOL(wp) + n, (int)W_WINCOL(wp) + nn,
+ ' ', ' ', hl_attr(HLF_SC));
+ n = nn;
+ }
+#endif
+ screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
+ W_WINCOL(wp) + FDC_OFF, (int)W_ENDCOL(wp),
+ c1, c2, hl_attr(hl));
+ }
+ set_empty_rows(wp, row);
+}
+
+#ifdef FEAT_FOLDING
+/*
+ * Display one folded line.
+ */
+ static void
+fold_line(wp, fold_count, foldinfo, lnum, row)
+ win_T *wp;
+ long fold_count;
+ foldinfo_T *foldinfo;
+ linenr_T lnum;
+ int row;
+{
+ char_u buf[51];
+ pos_T *top, *bot;
+ linenr_T lnume = lnum + fold_count - 1;
+ int len;
+ char_u *p;
+ char_u *text = NULL;
+ int fdc;
+ int level;
+ int col;
+ int txtcol;
+ int off = (int)(current_ScreenLine - ScreenLines);
+
+ /* Build the fold line:
+ * 1. Add the cmdwin_type for the command-line window
+ * 2. Add the 'foldcolumn'
+ * 3. Add the 'number' column
+ * 4. Compose the text
+ * 5. Add the text
+ * 6. set highlighting for the Visual area an other text
+ */
+ col = 0;
+
+ /*
+ * 1. Add the cmdwin_type for the command-line window
+ * Ignores 'rightleft', this window is never right-left.
+ */
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0 && wp == curwin)
+ {
+ ScreenLines[off] = cmdwin_type;
+ ScreenAttrs[off] = hl_attr(HLF_AT);
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ ScreenLinesUC[off] = 0;
+#endif
+ ++col;
+ }
+#endif
+
+ /*
+ * 2. Add the 'foldcolumn'
+ */
+ fdc = wp->w_p_fdc;
+ if (fdc > W_WIDTH(wp) - col)
+ fdc = W_WIDTH(wp) - col;
+ if (fdc > 0)
+ {
+ fill_foldcolumn(buf, wp, TRUE, lnum);
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ {
+ int i;
+
+ copy_text_attr(off + W_WIDTH(wp) - fdc - col, buf, fdc,
+ hl_attr(HLF_FC));
+ /* reverse the fold column */
+ for (i = 0; i < fdc; ++i)
+ ScreenLines[off + W_WIDTH(wp) - i - 1 - col] = buf[i];
+ }
+ else
+#endif
+ copy_text_attr(off + col, buf, fdc, hl_attr(HLF_FC));
+ col += fdc;
+ }
+
+#ifdef FEAT_RIGHTLEFT
+# define RL_MEMSET(p, v, l) vim_memset(ScreenAttrs + off + (wp->w_p_rl ? (W_WIDTH(wp) - (p) - (l)) : (p)), v, l)
+#else
+# define RL_MEMSET(p, v, l) vim_memset(ScreenAttrs + off + p, v, l)
+#endif
+
+ /* Set all attributes of the 'number' column and the text */
+ RL_MEMSET(col, hl_attr(HLF_FL), (size_t)(W_WIDTH(wp) - col));
+
+#ifdef FEAT_SIGNS
+ /* If signs are being displayed, add two spaces. */
+ if (draw_signcolumn(wp))
+ {
+ len = W_WIDTH(wp) - col;
+ if (len > 0)
+ {
+ if (len > 2)
+ len = 2;
+# ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ /* the line number isn't reversed */
+ copy_text_attr(off + W_WIDTH(wp) - len - col,
+ (char_u *)" ", len, hl_attr(HLF_FL));
+ else
+# endif
+ copy_text_attr(off + col, (char_u *)" ", len, hl_attr(HLF_FL));
+ col += len;
+ }
+ }
+#endif
+
+ /*
+ * 3. Add the 'number' column
+ */
+ if (wp->w_p_nu)
+ {
+ len = W_WIDTH(wp) - col;
+ if (len > 0)
+ {
+ if (len > 8)
+ len = 8;
+ sprintf((char *)buf, "%7ld ", (long)lnum);
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ /* the line number isn't reversed */
+ copy_text_attr(off + W_WIDTH(wp) - len - col, buf, len,
+ hl_attr(HLF_FL));
+ else
+#endif
+ copy_text_attr(off + col, buf, len, hl_attr(HLF_FL));
+ col += len;
+ }
+ }
+
+ /*
+ * 4. Compose the folded-line string with 'foldtext', if set.
+ */
+#ifdef FEAT_EVAL
+ if (*wp->w_p_fdt != NUL)
+ {
+ char_u dashes[51];
+ win_T *save_curwin;
+
+ /* Set "v:foldstart" and "v:foldend". */
+ set_vim_var_nr(VV_FOLDSTART, lnum);
+ set_vim_var_nr(VV_FOLDEND, lnume);
+
+ /* Set "v:folddashes" to a string of "level" dashes. */
+ /* Set "v:foldlevel" to "level". */
+ level = foldinfo->fi_level;
+ if (level > 50)
+ level = 50;
+ vim_memset(dashes, '-', (size_t)level);
+ dashes[level] = NUL;
+ set_vim_var_string(VV_FOLDDASHES, dashes, -1);
+ set_vim_var_nr(VV_FOLDLEVEL, (long)level);
+ save_curwin = curwin;
+ curwin = wp;
+ curbuf = wp->w_buffer;
+
+ ++emsg_off;
+ text = eval_to_string_safe(wp->w_p_fdt, NULL);
+ --emsg_off;
+
+ curwin = save_curwin;
+ curbuf = curwin->w_buffer;
+ set_vim_var_string(VV_FOLDDASHES, NULL, -1);
+
+ if (text != NULL)
+ {
+ /* Replace unprintable characters, if there are any. But
+ * replace a TAB with a space. */
+ for (p = text; *p != NUL; ++p)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (len = (*mb_ptr2len_check)(p)) > 1)
+ {
+ if (!vim_isprintc((*mb_ptr2char)(p)))
+ break;
+ p += len - 1;
+ }
+ else
+#endif
+ if (*p == TAB)
+ *p = ' ';
+ else if (ptr2cells(p) > 1)
+ break;
+ }
+ if (*p != NUL)
+ {
+ p = transstr(text);
+ vim_free(text);
+ text = p;
+ }
+ }
+ }
+ if (text == NULL)
+#endif
+ {
+ sprintf((char *)buf, _("+--%3ld lines folded "), fold_count);
+ text = buf;
+ }
+
+ txtcol = col; /* remember where text starts */
+
+ /*
+ * 5. move the text to current_ScreenLine. Fill up with "fill_fold".
+ * Right-left text is put in columns 0 - number-col, normal text is put
+ * in columns number-col - window-width.
+ */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int cells;
+ int u8c, u8c_c1, u8c_c2;
+ int idx;
+ int c_len;
+# ifdef FEAT_ARABIC
+ int prev_c = 0; /* previous Arabic character */
+ int prev_c1 = 0; /* first composing char for prev_c */
+# endif
+
+# ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ idx = off;
+ else
+# endif
+ idx = off + col;
+
+ /* Store multibyte characters in ScreenLines[] et al. correctly. */
+ for (p = text; *p != NUL; )
+ {
+ cells = (*mb_ptr2cells)(p);
+ c_len = (*mb_ptr2len_check)(p);
+ if (col + cells > W_WIDTH(wp)
+# ifdef FEAT_RIGHTLEFT
+ - (wp->w_p_rl ? col : 0)
+# endif
+ )
+ break;
+ ScreenLines[idx] = *p;
+ if (enc_utf8)
+ {
+ u8c = utfc_ptr2char(p, &u8c_c1, &u8c_c2);
+ if (*p < 0x80 && u8c_c1 == 0 && u8c_c2 == 0)
+ {
+ ScreenLinesUC[idx] = 0;
+#ifdef FEAT_ARABIC
+ prev_c = u8c;
+#endif
+ }
+ else
+ {
+#ifdef FEAT_ARABIC
+ if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c))
+ {
+ /* Do Arabic shaping. */
+ int pc, pc1, nc, dummy;
+ int firstbyte = *p;
+
+ /* The idea of what is the previous and next
+ * character depends on 'rightleft'. */
+ if (wp->w_p_rl)
+ {
+ pc = prev_c;
+ pc1 = prev_c1;
+ nc = utf_ptr2char(p + c_len);
+ prev_c1 = u8c_c1;
+ }
+ else
+ {
+ pc = utfc_ptr2char(p + c_len, &pc1, &dummy);
+ nc = prev_c;
+ }
+ prev_c = u8c;
+
+ u8c = arabic_shape(u8c, &firstbyte, &u8c_c1,
+ pc, pc1, nc);
+ ScreenLines[idx] = firstbyte;
+ }
+ else
+ prev_c = u8c;
+#endif
+ /* Non-BMP character: display as ? or fullwidth ?. */
+ if (u8c >= 0x10000)
+ ScreenLinesUC[idx] = (cells == 2) ? 0xff1f : (int)'?';
+ else
+ ScreenLinesUC[idx] = u8c;
+ ScreenLinesC1[idx] = u8c_c1;
+ ScreenLinesC2[idx] = u8c_c2;
+ }
+ if (cells > 1)
+ ScreenLines[idx + 1] = 0;
+ }
+ else if (cells > 1) /* double-byte character */
+ {
+ if (enc_dbcs == DBCS_JPNU && *p == 0x8e)
+ ScreenLines2[idx] = p[1];
+ else
+ ScreenLines[idx + 1] = p[1];
+ }
+ col += cells;
+ idx += cells;
+ p += c_len;
+ }
+ }
+ else
+#endif
+ {
+ len = (int)STRLEN(text);
+ if (len > W_WIDTH(wp) - col)
+ len = W_WIDTH(wp) - col;
+ if (len > 0)
+ {
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ STRNCPY(current_ScreenLine, text, len);
+ else
+#endif
+ STRNCPY(current_ScreenLine + col, text, len);
+ col += len;
+ }
+ }
+
+ /* Fill the rest of the line with the fold filler */
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ col -= txtcol;
+#endif
+ while (col < W_WIDTH(wp)
+#ifdef FEAT_RIGHTLEFT
+ - (wp->w_p_rl ? txtcol : 0)
+#endif
+ )
+ {
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ {
+ if (fill_fold >= 0x80)
+ {
+ ScreenLinesUC[off + col] = fill_fold;
+ ScreenLinesC1[off + col] = 0;
+ ScreenLinesC2[off + col] = 0;
+ }
+ else
+ ScreenLinesUC[off + col] = 0;
+ }
+#endif
+ ScreenLines[off + col++] = fill_fold;
+ }
+
+ if (text != buf)
+ vim_free(text);
+
+ /*
+ * 6. set highlighting for the Visual area an other text.
+ * If all folded lines are in the Visual area, highlight the line.
+ */
+#ifdef FEAT_VISUAL
+ if (VIsual_active && wp->w_buffer == curwin->w_buffer)
+ {
+ if (ltoreq(curwin->w_cursor, VIsual))
+ {
+ /* Visual is after curwin->w_cursor */
+ top = &curwin->w_cursor;
+ bot = &VIsual;
+ }
+ else
+ {
+ /* Visual is before curwin->w_cursor */
+ top = &VIsual;
+ bot = &curwin->w_cursor;
+ }
+ if (lnum >= top->lnum
+ && lnume <= bot->lnum
+ && (VIsual_mode != 'v'
+ || ((lnum > top->lnum
+ || (lnum == top->lnum
+ && top->col == 0))
+ && (lnume < bot->lnum
+ || (lnume == bot->lnum
+ && (bot->col - (*p_sel == 'e'))
+ >= STRLEN(ml_get_buf(wp->w_buffer, lnume, FALSE)))))))
+ {
+ if (VIsual_mode == Ctrl_V)
+ {
+ /* Visual block mode: highlight the chars part of the block */
+ if (wp->w_old_cursor_fcol + txtcol < (colnr_T)W_WIDTH(wp))
+ {
+ if (wp->w_old_cursor_lcol + txtcol < (colnr_T)W_WIDTH(wp))
+ len = wp->w_old_cursor_lcol;
+ else
+ len = W_WIDTH(wp) - txtcol;
+ RL_MEMSET(wp->w_old_cursor_fcol + txtcol, hl_attr(HLF_V),
+ (size_t)(len - wp->w_old_cursor_fcol));
+ }
+ }
+ else
+ /* Set all attributes of the text */
+ RL_MEMSET(txtcol, hl_attr(HLF_V),
+ (size_t)(W_WIDTH(wp) - txtcol));
+ }
+ }
+#endif
+
+
+ SCREEN_LINE(row + W_WINROW(wp), W_WINCOL(wp), (int)W_WIDTH(wp),
+ (int)W_WIDTH(wp), FALSE);
+
+ /*
+ * Update w_cline_height and w_cline_folded if the cursor line was
+ * updated (saves a call to plines() later).
+ */
+ if (wp == curwin
+ && lnum <= curwin->w_cursor.lnum
+ && lnume >= curwin->w_cursor.lnum)
+ {
+ curwin->w_cline_row = row;
+ curwin->w_cline_height = 1;
+ curwin->w_cline_folded = TRUE;
+ curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW);
+ }
+}
+
+/*
+ * Copy "buf[len]" to ScreenLines["off"] and set attributes to "attr".
+ */
+ static void
+copy_text_attr(off, buf, len, attr)
+ int off;
+ char_u *buf;
+ int len;
+ int attr;
+{
+ mch_memmove(ScreenLines + off, buf, (size_t)len);
+# ifdef FEAT_MBYTE
+ if (enc_utf8)
+ vim_memset(ScreenLinesUC + off, 0, sizeof(u8char_T) * (size_t)len);
+# endif
+ vim_memset(ScreenAttrs + off, attr, (size_t)len);
+}
+
+/*
+ * Fill the foldcolumn at "p" for window "wp".
+ */
+ static void
+fill_foldcolumn(p, wp, closed, lnum)
+ char_u *p;
+ win_T *wp;
+ int closed; /* TRUE of FALSE */
+ linenr_T lnum; /* current line number */
+{
+ int i = 0;
+ int level;
+ int first_level;
+
+ /* Init to all spaces. */
+ copy_spaces(p, (size_t)wp->w_p_fdc);
+
+ level = win_foldinfo.fi_level;
+ if (level > 0)
+ {
+ /* If the column is too narrow, we start at the lowest level that
+ * fits and use numbers to indicated the depth. */
+ first_level = level - wp->w_p_fdc - closed + 2;
+ if (first_level < 1)
+ first_level = 1;
+
+ for (i = 0; i + 1 < wp->w_p_fdc; ++i)
+ {
+ if (win_foldinfo.fi_lnum == lnum
+ && first_level + i >= win_foldinfo.fi_low_level)
+ p[i] = '-';
+ else if (first_level == 1)
+ p[i] = '|';
+ else if (first_level + i <= 9)
+ p[i] = '0' + first_level + i;
+ else
+ p[i] = '>';
+ if (first_level + i == level)
+ break;
+ }
+ }
+ if (closed)
+ p[i] = '+';
+}
+#endif /* FEAT_FOLDING */
+
+/*
+ * Display line "lnum" of window 'wp' on the screen.
+ * Start at row "startrow", stop when "endrow" is reached.
+ * wp->w_virtcol needs to be valid.
+ *
+ * Return the number of last row the line occupies.
+ */
+ static int
+win_line(wp, lnum, startrow, endrow)
+ win_T *wp;
+ linenr_T lnum;
+ int startrow;
+ int endrow;
+{
+ int col; /* visual column on screen */
+ unsigned off; /* offset in ScreenLines/ScreenAttrs */
+ int c = 0; /* init for GCC */
+ long vcol = 0; /* virtual column (for tabs) */
+ long vcol_prev = -1; /* "vcol" of previous character */
+ char_u *line; /* current line */
+ char_u *ptr; /* current position in "line" */
+ int row; /* row in the window, excl w_winrow */
+ int screen_row; /* row on the screen, incl w_winrow */
+
+ char_u extra[18]; /* "%ld" and 'fdc' must fit in here */
+ int n_extra = 0; /* number of extra chars */
+ char_u *p_extra = NULL; /* string of extra chars */
+ int c_extra = NUL; /* extra chars, all the same */
+ int extra_attr = 0; /* attributes when n_extra != 0 */
+ static char_u *at_end_str = (char_u *)""; /* used for p_extra when
+ displaying lcs_eol at end-of-line */
+ int lcs_eol_one = lcs_eol; /* lcs_eol until it's been used */
+ int lcs_prec_todo = lcs_prec; /* lcs_prec until it's been used */
+
+ /* saved "extra" items for when draw_state becomes WL_LINE (again) */
+ int saved_n_extra = 0;
+ char_u *saved_p_extra = NULL;
+ int saved_c_extra = 0;
+ int saved_char_attr = 0;
+
+ int n_attr = 0; /* chars with special attr */
+ int saved_attr2 = 0; /* char_attr saved for n_attr */
+ int n_attr3 = 0; /* chars with overruling special attr */
+ int saved_attr3 = 0; /* char_attr saved for n_attr3 */
+
+ int n_skip = 0; /* nr of chars to skip for 'nowrap' */
+
+ int fromcol, tocol; /* start/end of inverting */
+ int fromcol_prev = -2; /* start of inverting after cursor */
+ int noinvcur = FALSE; /* don't invert the cursor */
+#ifdef FEAT_VISUAL
+ pos_T *top, *bot;
+#endif
+ pos_T pos;
+ long v;
+
+ int char_attr = 0; /* attributes for next character */
+ int area_highlighting = FALSE; /* Visual or incsearch highlighting
+ in this line */
+ int attr = 0; /* attributes for area highlighting */
+ int area_attr = 0; /* attributes desired by highlighting */
+ int search_attr = 0; /* attributes desired by 'hlsearch' */
+#ifdef FEAT_SYN_HL
+ int syntax_attr = 0; /* attributes desired by syntax */
+ int has_syntax = FALSE; /* this buffer has syntax highl. */
+ int save_did_emsg;
+#endif
+ int extra_check; /* has syntax or linebreak */
+#ifdef FEAT_MBYTE
+ int multi_attr = 0; /* attributes desired by multibyte */
+ int mb_l = 1; /* multi-byte byte length */
+ int mb_c = 0; /* decoded multi-byte character */
+ int mb_utf8 = FALSE; /* screen char is UTF-8 char */
+ int u8c_c1 = 0; /* first composing UTF-8 char */
+ int u8c_c2 = 0; /* second composing UTF-8 char */
+#endif
+#ifdef FEAT_DIFF
+ int filler_lines; /* nr of filler lines to be drawn */
+ int filler_todo; /* nr of filler lines still to do + 1 */
+ enum hlf_value diff_hlf = (enum hlf_value)0; /* type of diff highlighting */
+ int change_start = MAXCOL; /* first col of changed area */
+ int change_end = -1; /* last col of changed area */
+#endif
+ colnr_T trailcol = MAXCOL; /* start of trailing spaces */
+#ifdef FEAT_LINEBREAK
+ int need_showbreak = FALSE;
+#endif
+#if defined(FEAT_SIGNS) || (defined(FEAT_QUICKFIX) && defined(FEAT_WINDOWS))
+# define LINE_ATTR
+ int line_attr = 0; /* atrribute for the whole line */
+#endif
+#ifdef FEAT_SEARCH_EXTRA
+ match_T *shl; /* points to search_hl or match_hl */
+#endif
+#ifdef FEAT_ARABIC
+ int prev_c = 0; /* previous Arabic character */
+ int prev_c1 = 0; /* first composing char for prev_c */
+#endif
+
+ /* draw_state: items that are drawn in sequence: */
+#define WL_START 0 /* nothing done yet */
+#ifdef FEAT_CMDWIN
+# define WL_CMDLINE WL_START + 1 /* cmdline window column */
+#else
+# define WL_CMDLINE WL_START
+#endif
+#ifdef FEAT_FOLDING
+# define WL_FOLD WL_CMDLINE + 1 /* 'foldcolumn' */
+#else
+# define WL_FOLD WL_CMDLINE
+#endif
+#ifdef FEAT_SIGNS
+# define WL_SIGN WL_FOLD + 1 /* column for signs */
+#else
+# define WL_SIGN WL_FOLD /* column for signs */
+#endif
+#define WL_NR WL_SIGN + 1 /* line number */
+#if defined(FEAT_LINEBREAK) || defined(FEAT_DIFF)
+# define WL_SBR WL_NR + 1 /* 'showbreak' or 'diff' */
+#else
+# define WL_SBR WL_NR
+#endif
+#define WL_LINE WL_SBR + 1 /* text in the line */
+ int draw_state = WL_START; /* what to draw next */
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+ int feedback_col = 0;
+ int feedback_old_attr = -1;
+#endif
+
+
+ if (startrow > endrow) /* past the end already! */
+ return startrow;
+
+ row = startrow;
+ screen_row = row + W_WINROW(wp);
+
+ /*
+ * To speed up the loop below, set extra_check when there is linebreak,
+ * trailing white space and/or syntax processing to be done.
+ */
+#ifdef FEAT_LINEBREAK
+ extra_check = wp->w_p_lbr;
+#else
+ extra_check = 0;
+#endif
+#ifdef FEAT_SYN_HL
+ if (syntax_present(wp->w_buffer))
+ {
+ /* Prepare for syntax highlighting in this line. When there is an
+ * error, stop syntax highlighting. */
+ save_did_emsg = did_emsg;
+ did_emsg = FALSE;
+ syntax_start(wp, lnum);
+ if (did_emsg)
+ syntax_clear(wp->w_buffer);
+ else
+ {
+ did_emsg = save_did_emsg;
+ has_syntax = TRUE;
+ extra_check = TRUE;
+ }
+ }
+#endif
+
+ /*
+ * handle visual active in this window
+ */
+ fromcol = -10;
+ tocol = MAXCOL;
+#ifdef FEAT_VISUAL
+ if (VIsual_active && wp->w_buffer == curwin->w_buffer)
+ {
+ /* Visual is after curwin->w_cursor */
+ if (ltoreq(curwin->w_cursor, VIsual))
+ {
+ top = &curwin->w_cursor;
+ bot = &VIsual;
+ }
+ else /* Visual is before curwin->w_cursor */
+ {
+ top = &VIsual;
+ bot = &curwin->w_cursor;
+ }
+ if (VIsual_mode == Ctrl_V) /* block mode */
+ {
+ if (lnum >= top->lnum && lnum <= bot->lnum)
+ {
+ fromcol = wp->w_old_cursor_fcol;
+ tocol = wp->w_old_cursor_lcol;
+ }
+ }
+ else /* non-block mode */
+ {
+ if (lnum > top->lnum && lnum <= bot->lnum)
+ fromcol = 0;
+ else if (lnum == top->lnum)
+ {
+ if (VIsual_mode == 'V') /* linewise */
+ fromcol = 0;
+ else
+ {
+ getvvcol(wp, top, (colnr_T *)&fromcol, NULL, NULL);
+ if (gchar_pos(top) == NUL)
+ tocol = fromcol + 1;
+ }
+ }
+ if (VIsual_mode != 'V' && lnum == bot->lnum)
+ {
+ if (*p_sel == 'e' && bot->col == 0
+#ifdef FEAT_VIRTUALEDIT
+ && bot->coladd == 0
+#endif
+ )
+ {
+ fromcol = -10;
+ tocol = MAXCOL;
+ }
+ else
+ {
+ pos = *bot;
+ if (*p_sel == 'e')
+ getvvcol(wp, &pos, (colnr_T *)&tocol, NULL, NULL);
+ else
+ {
+ getvvcol(wp, &pos, NULL, NULL, (colnr_T *)&tocol);
+ ++tocol;
+ }
+ }
+ }
+ }
+
+#ifndef MSDOS
+ /* Check if the character under the cursor should not be inverted */
+ if (!highlight_match && lnum == curwin->w_cursor.lnum && wp == curwin
+# ifdef FEAT_GUI
+ && !gui.in_use
+# endif
+ )
+ noinvcur = TRUE;
+#endif
+
+ /* if inverting in this line set area_highlighting */
+ if (fromcol >= 0)
+ {
+ area_highlighting = TRUE;
+ attr = hl_attr(HLF_V);
+#if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
+ if (clip_star.available && !clip_star.owned && clip_isautosel())
+ attr = hl_attr(HLF_VNC);
+#endif
+ }
+ }
+
+ /*
+ * handle 'insearch' and ":s///c" highlighting
+ */
+ else
+#endif /* FEAT_VISUAL */
+ if (highlight_match
+ && wp == curwin
+ && lnum >= curwin->w_cursor.lnum
+ && lnum <= curwin->w_cursor.lnum + search_match_lines)
+ {
+ if (lnum == curwin->w_cursor.lnum)
+ getvcol(curwin, &(curwin->w_cursor),
+ (colnr_T *)&fromcol, NULL, NULL);
+ else
+ fromcol = 0;
+ if (lnum == curwin->w_cursor.lnum + search_match_lines)
+ {
+ pos.lnum = lnum;
+ pos.col = search_match_endcol;
+ getvcol(curwin, &pos, (colnr_T *)&tocol, NULL, NULL);
+ }
+ else
+ tocol = MAXCOL;
+ if (fromcol == tocol) /* do at least one character */
+ tocol = fromcol + 1; /* happens when past end of line */
+ area_highlighting = TRUE;
+ attr = hl_attr(HLF_I);
+ }
+
+#ifdef FEAT_DIFF
+ filler_lines = diff_check(wp, lnum);
+ if (filler_lines < 0)
+ {
+ if (filler_lines == -1)
+ {
+ if (diff_find_change(wp, lnum, &change_start, &change_end))
+ diff_hlf = HLF_ADD; /* added line */
+ else if (change_start == 0)
+ diff_hlf = HLF_TXD; /* changed text */
+ else
+ diff_hlf = HLF_CHD; /* changed line */
+ }
+ else
+ diff_hlf = HLF_ADD; /* added line */
+ filler_lines = 0;
+ area_highlighting = TRUE;
+ }
+ if (lnum == wp->w_topline)
+ filler_lines = wp->w_topfill;
+ filler_todo = filler_lines;
+#endif
+
+#ifdef LINE_ATTR
+# ifdef FEAT_SIGNS
+ /* If this line has a sign with line highlighting set line_attr. */
+ v = buf_getsigntype(wp->w_buffer, lnum, SIGN_LINEHL);
+ if (v != 0)
+ line_attr = sign_get_attr((int)v, TRUE);
+# endif
+# if defined(FEAT_QUICKFIX) && defined(FEAT_WINDOWS)
+ /* Highlight the current line in the quickfix window. */
+ if (bt_quickfix(wp->w_buffer) && qf_current_entry() == lnum)
+ line_attr = hl_attr(HLF_L);
+# endif
+ if (line_attr != 0)
+ area_highlighting = TRUE;
+#endif
+
+ line = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ ptr = line;
+
+ /* find start of trailing whitespace */
+ if (wp->w_p_list && lcs_trail)
+ {
+ trailcol = (colnr_T)STRLEN(ptr);
+ while (trailcol > (colnr_T)0 && vim_iswhite(ptr[trailcol - 1]))
+ --trailcol;
+ trailcol += (colnr_T) (ptr - line);
+ extra_check = TRUE;
+ }
+
+ /*
+ * 'nowrap' or 'wrap' and a single line that doesn't fit: Advance to the
+ * first character to be displayed.
+ */
+ if (wp->w_p_wrap)
+ v = wp->w_skipcol;
+ else
+ v = wp->w_leftcol;
+ if (v > 0)
+ {
+#ifdef FEAT_MBYTE
+ char_u *prev_ptr = ptr;
+#endif
+ while (vcol < v && *ptr != NUL)
+ {
+ c = win_lbr_chartabsize(wp, ptr, (colnr_T)vcol, NULL);
+ vcol += c;
+#ifdef FEAT_MBYTE
+ prev_ptr = ptr;
+ if (has_mbyte)
+ ptr += (*mb_ptr2len_check)(ptr);
+ else
+#endif
+ ++ptr;
+ }
+
+#ifdef FEAT_VIRTUALEDIT
+ /* When 'virtualedit' is set the end of the line may be before the
+ * start of the displayed part. */
+ if (vcol < v && *ptr == NUL && virtual_active())
+ vcol = v;
+#endif
+
+ /* Handle a character that's not completely on the screen: Put ptr at
+ * that character but skip the first few screen characters. */
+ if (vcol > v)
+ {
+ vcol -= c;
+#ifdef FEAT_MBYTE
+ ptr = prev_ptr;
+#else
+ --ptr;
+#endif
+ n_skip = v - vcol;
+ }
+
+ /*
+ * Adjust for when the inverted text is before the screen,
+ * and when the start of the inverted text is before the screen.
+ */
+ if (tocol <= vcol)
+ fromcol = 0;
+ else if (fromcol >= 0 && fromcol < vcol)
+ fromcol = vcol;
+
+#ifdef FEAT_LINEBREAK
+ /* When w_skipcol is non-zero, first line needs 'showbreak' */
+ if (wp->w_p_wrap)
+ need_showbreak = TRUE;
+#endif
+ }
+
+ /*
+ * Correct highlighting for cursor that can't be disabled.
+ * Avoids having to check this for each character.
+ */
+ if (fromcol >= 0)
+ {
+ if (noinvcur)
+ {
+ if ((colnr_T)fromcol == wp->w_virtcol)
+ {
+ /* highlighting starts at cursor, let it start just after the
+ * cursor */
+ fromcol_prev = fromcol;
+ fromcol = -1;
+ }
+ else if ((colnr_T)fromcol < wp->w_virtcol)
+ /* restart highlighting after the cursor */
+ fromcol_prev = wp->w_virtcol;
+ }
+ if (fromcol >= tocol)
+ fromcol = -1;
+ }
+
+#ifdef FEAT_SEARCH_EXTRA
+ /*
+ * Handle highlighting the last used search pattern.
+ * Do this for both search_hl and match_hl.
+ */
+ shl = &search_hl;
+ for (;;)
+ {
+ shl->startp = NULL;
+ shl->endp = NULL;
+ shl->attr_cur = 0;
+ if (shl->rm.regprog != NULL)
+ {
+ v = (long)(ptr - line);
+ next_search_hl(wp, shl, lnum, (colnr_T)v);
+
+ /* Need to get the line again, a multi-line regexp may have made it
+ * invalid. */
+ line = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ ptr = line + v;
+
+ if (shl->lnum != 0 && shl->lnum <= lnum)
+ {
+ if (shl->lnum == lnum)
+ shl->startp = line + shl->rm.startpos[0].col;
+ else
+ shl->startp = line;
+ if (lnum == shl->lnum + shl->rm.endpos[0].lnum
+ - shl->rm.startpos[0].lnum)
+ shl->endp = line + shl->rm.endpos[0].col;
+ else
+ shl->endp = line + MAXCOL;
+ /* Highlight one character for an empty match. */
+ if (shl->startp == shl->endp)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && *shl->endp != NUL)
+ shl->endp += (*mb_ptr2len_check)(shl->endp);
+ else
+#endif
+ ++shl->endp;
+ }
+ if (shl->startp < ptr) /* match at leftcol */
+ {
+ shl->attr_cur = shl->attr;
+ search_attr = shl->attr;
+ }
+ area_highlighting = TRUE;
+ }
+ }
+ if (shl == &match_hl)
+ break;
+ shl = &match_hl;
+ }
+#endif
+
+ off = (unsigned) (current_ScreenLine - ScreenLines);
+ col = 0;
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ {
+ /* Rightleft window: process the text in the normal direction, but put
+ * it in current_ScreenLine[] from right to left. Start at the
+ * rightmost column of the window. */
+ col = W_WIDTH(wp) - 1;
+ off += col;
+ }
+#endif
+
+ /*
+ * Repeat for the whole displayed line.
+ */
+ for (;;)
+ {
+ /* Skip this quickly when working on the text. */
+ if (draw_state != WL_LINE)
+ {
+#ifdef FEAT_CMDWIN
+ if (draw_state == WL_CMDLINE - 1 && n_extra == 0)
+ {
+ draw_state = WL_CMDLINE;
+ if (cmdwin_type != 0 && wp == curwin)
+ {
+ /* Draw the cmdline character. */
+ *extra = cmdwin_type;
+ n_extra = 1;
+ p_extra = extra;
+ c_extra = NUL;
+ char_attr = hl_attr(HLF_AT);
+ }
+ }
+#endif
+
+#ifdef FEAT_FOLDING
+ if (draw_state == WL_FOLD - 1 && n_extra == 0)
+ {
+ draw_state = WL_FOLD;
+ if (wp->w_p_fdc > 0)
+ {
+ /* Draw the 'foldcolumn'. */
+ fill_foldcolumn(extra, wp, FALSE, lnum);
+ n_extra = wp->w_p_fdc;
+ p_extra = extra;
+ c_extra = NUL;
+ char_attr = hl_attr(HLF_FC);
+ }
+ }
+#endif
+
+#ifdef FEAT_SIGNS
+ if (draw_state == WL_SIGN - 1 && n_extra == 0)
+ {
+ draw_state = WL_SIGN;
+ /* Show the sign column when there are any signs in this
+ * buffer or when using Netbeans. */
+ if (draw_signcolumn(wp)
+# ifdef FEAT_DIFF
+ && filler_todo <= 0
+# endif
+ )
+ {
+ int_u text_sign;
+# ifdef FEAT_SIGN_ICONS
+ int_u icon_sign;
+# endif
+
+ /* Draw two cells with the sign value or blank. */
+ c_extra = ' ';
+ char_attr = hl_attr(HLF_SC);
+ n_extra = 2;
+
+ if (row == startrow)
+ {
+ text_sign = buf_getsigntype(wp->w_buffer, lnum,
+ SIGN_TEXT);
+# ifdef FEAT_SIGN_ICONS
+ icon_sign = buf_getsigntype(wp->w_buffer, lnum,
+ SIGN_ICON);
+ if (gui.in_use && icon_sign != 0)
+ {
+ /* Use the image in this position. */
+ c_extra = SIGN_BYTE;
+# ifdef FEAT_NETBEANS_INTG
+ if (buf_signcount(wp->w_buffer, lnum) > 1)
+ c_extra = MULTISIGN_BYTE;
+# endif
+ char_attr = icon_sign;
+ }
+ else
+# endif
+ if (text_sign != 0)
+ {
+ p_extra = sign_get_text(text_sign);
+ if (p_extra != NULL)
+ {
+ c_extra = NUL;
+ n_extra = STRLEN(p_extra);
+ }
+ char_attr = sign_get_attr(text_sign, FALSE);
+ }
+ }
+ }
+ }
+#endif
+
+ if (draw_state == WL_NR - 1 && n_extra == 0)
+ {
+ draw_state = WL_NR;
+ /* Display the line number. After the first fill with blanks
+ * when the 'n' flag isn't in 'cpo' */
+ if (wp->w_p_nu
+ && (row == startrow
+#ifdef FEAT_DIFF
+ + filler_lines
+#endif
+ || vim_strchr(p_cpo, CPO_NUMCOL) == NULL))
+ {
+ /* Draw the line number (empty space after wrapping). */
+ if (row == startrow
+#ifdef FEAT_DIFF
+ + filler_lines
+#endif
+ )
+ {
+ sprintf((char *)extra, "%7ld ", (long)lnum);
+ if (wp->w_skipcol > 0)
+ for (p_extra = extra; *p_extra == ' '; ++p_extra)
+ *p_extra = '-';
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl) /* reverse line numbers */
+ rl_mirror(extra);
+#endif
+ p_extra = extra;
+ c_extra = NUL;
+ }
+ else
+ c_extra = ' ';
+ n_extra = 8;
+ char_attr = hl_attr(HLF_N);
+ }
+ }
+
+#if defined(FEAT_LINEBREAK) || defined(FEAT_DIFF)
+ if (draw_state == WL_SBR - 1 && n_extra == 0)
+ {
+ draw_state = WL_SBR;
+# ifdef FEAT_DIFF
+ if (filler_todo > 0)
+ {
+ /* Draw "deleted" diff line(s). */
+ if (char2cells(fill_diff) > 1)
+ c_extra = '-';
+ else
+ c_extra = fill_diff;
+# ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ n_extra = col + 1;
+ else
+# endif
+ n_extra = W_WIDTH(wp) - col;
+ char_attr = hl_attr(HLF_DED);
+ }
+# endif
+# ifdef FEAT_LINEBREAK
+ if (*p_sbr != NUL && need_showbreak)
+ {
+ /* Draw 'showbreak' at the start of each broken line. */
+ p_extra = p_sbr;
+ c_extra = NUL;
+ n_extra = (int)STRLEN(p_sbr);
+ char_attr = hl_attr(HLF_AT);
+ need_showbreak = FALSE;
+ /* Correct end of highlighted area for 'showbreak',
+ * required when 'linebreak' is also set. */
+ if (tocol == vcol)
+ tocol += n_extra;
+ }
+# endif
+ }
+#endif
+
+ if (draw_state == WL_LINE - 1 && n_extra == 0)
+ {
+ draw_state = WL_LINE;
+ if (saved_n_extra)
+ {
+ /* Continue item from end of wrapped line. */
+ n_extra = saved_n_extra;
+ c_extra = saved_c_extra;
+ p_extra = saved_p_extra;
+ char_attr = saved_char_attr;
+ }
+ else
+ char_attr = 0;
+ }
+ }
+
+ /* When still displaying '$' of change command, stop at cursor */
+ if (dollar_vcol != 0 && wp == curwin && vcol >= (long)wp->w_virtcol
+#ifdef FEAT_DIFF
+ && filler_todo <= 0
+#endif
+ )
+ {
+ SCREEN_LINE(screen_row, W_WINCOL(wp), col, -(int)W_WIDTH(wp),
+ wp->w_p_rl);
+ /* Pretend we have finished updating the window. */
+ row = wp->w_height;
+ break;
+ }
+
+ if (draw_state == WL_LINE && area_highlighting)
+ {
+ /* handle Visual or match highlighting in this line */
+ if (vcol == fromcol
+#ifdef FEAT_MBYTE
+ || (has_mbyte && vcol + 1 == fromcol && n_extra == 0
+ && (*mb_ptr2cells)(ptr) > 1)
+#endif
+ || ((int)vcol_prev == fromcol_prev
+ && vcol < tocol))
+ area_attr = attr; /* start highlighting */
+ else if (area_attr != 0
+ && (vcol == tocol
+ || (noinvcur && (colnr_T)vcol == wp->w_virtcol)))
+#ifdef LINE_ATTR
+ area_attr = line_attr; /* stop highlighting */
+ else if (line_attr && ((fromcol == -10 && tocol == MAXCOL)
+ || (vcol < fromcol || vcol > tocol)))
+ area_attr = line_attr;
+#else
+ area_attr = 0; /* stop highlighting */
+#endif
+
+#ifdef FEAT_SEARCH_EXTRA
+ if (!n_extra)
+ {
+ /*
+ * Check for start/end of search pattern match.
+ * After end, check for start/end of next match.
+ * When another match, have to check for start again.
+ * Watch out for matching an empty string!
+ * Do this first for search_hl, then for match_hl, so that
+ * ":match" overrules 'hlsearch'.
+ */
+ shl = &search_hl;
+ for (;;)
+ {
+ while (shl->rm.regprog != NULL)
+ {
+ if (shl->startp != NULL
+ && ptr >= shl->startp
+ && ptr < shl->endp)
+ {
+ shl->attr_cur = shl->attr;
+ }
+ else if (ptr == shl->endp)
+ {
+ shl->attr_cur = 0;
+
+ v = (long)(ptr - line);
+ next_search_hl(wp, shl, lnum, (colnr_T)v);
+
+ /* Need to get the line again, a multi-line regexp
+ * may have made it invalid. */
+ line = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ ptr = line + v;
+
+ if (shl->lnum == lnum)
+ {
+ shl->startp = line + shl->rm.startpos[0].col;
+ if (shl->rm.endpos[0].lnum == 0)
+ shl->endp = line + shl->rm.endpos[0].col;
+ else
+ shl->endp = line + MAXCOL;
+
+ if (shl->startp == shl->endp)
+ {
+ /* highlight empty match, try again after
+ * it */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ shl->endp +=
+ (*mb_ptr2len_check)(shl->endp);
+ else
+#endif
+ ++shl->endp;
+ }
+
+ /* Loop to check if the match starts at the
+ * current position */
+ continue;
+ }
+ }
+ break;
+ }
+ if (shl == &match_hl)
+ break;
+ shl = &match_hl;
+ }
+ /* ":match" highlighting overrules 'hlsearch' */
+ if (match_hl.attr_cur != 0)
+ search_attr = match_hl.attr_cur;
+ else
+ search_attr = search_hl.attr_cur;
+ }
+#endif
+
+ if (area_attr != 0)
+ char_attr = area_attr;
+#ifdef FEAT_SYN_HL
+ else if (search_attr == 0 && has_syntax)
+ char_attr = syntax_attr;
+#endif
+ else
+ char_attr = search_attr;
+
+#ifdef FEAT_DIFF
+ if (diff_hlf != (enum hlf_value)0 && n_extra == 0)
+ {
+ if (diff_hlf == HLF_CHD && ptr - line >= change_start)
+ diff_hlf = HLF_TXD; /* changed text */
+ if (diff_hlf == HLF_TXD && ptr - line > change_end)
+ diff_hlf = HLF_CHD; /* changed line */
+ if (attr == 0 || area_attr != attr)
+ area_attr = hl_attr(diff_hlf);
+ if (attr == 0 || char_attr != attr)
+ {
+ if (search_attr != 0)
+ char_attr = search_attr;
+ else
+ char_attr = hl_attr(diff_hlf);
+ }
+ }
+#endif
+ }
+
+ /*
+ * Get the next character to put on the screen.
+ */
+ /*
+ * The 'extra' array contains the extra stuff that is inserted to
+ * represent special characters (non-printable stuff). When all
+ * characters are the same, c_extra is used.
+ * For the '$' of the 'list' option, n_extra == 1, p_extra == "".
+ */
+ if (n_extra > 0)
+ {
+ if (c_extra != NUL)
+ {
+ c = c_extra;
+#ifdef FEAT_MBYTE
+ mb_c = c; /* doesn't handle non-utf-8 multi-byte! */
+ if (enc_utf8 && (*mb_char2len)(c) > 1)
+ {
+ mb_utf8 = TRUE;
+ u8c_c1 = u8c_c2 = 0;
+ }
+ else
+ mb_utf8 = FALSE;
+#endif
+ }
+ else
+ {
+ c = *p_extra;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ mb_c = c;
+ if (enc_utf8)
+ {
+ /* If the UTF-8 character is more than one byte:
+ * Decode it into "mb_c". */
+ mb_l = (*mb_ptr2len_check)(p_extra);
+ mb_utf8 = FALSE;
+ if (mb_l > n_extra)
+ mb_l = 1;
+ else if (mb_l > 1)
+ {
+ mb_c = utfc_ptr2char(p_extra, &u8c_c1, &u8c_c2);
+ mb_utf8 = TRUE;
+ }
+ }
+ else
+ {
+ /* if this is a DBCS character, put it in "mb_c" */
+ mb_l = MB_BYTE2LEN(c);
+ if (mb_l >= n_extra)
+ mb_l = 1;
+ else if (mb_l > 1)
+ mb_c = (c << 8) + p_extra[1];
+ }
+ /* If a double-width char doesn't fit display a '>' in the
+ * last column. */
+ if (
+# ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? (col <= 0) :
+# endif
+ (col >= W_WIDTH(wp) - 1)
+ && (*mb_char2cells)(mb_c) == 2)
+ {
+ c = '>';
+ mb_c = c;
+ mb_l = 1;
+ mb_utf8 = FALSE;
+ multi_attr = hl_attr(HLF_AT);
+ /* put the pointer back to output the double-width
+ * character at the start of the next line. */
+ ++n_extra;
+ --p_extra;
+ }
+ else
+ {
+ n_extra -= mb_l - 1;
+ p_extra += mb_l - 1;
+ }
+ }
+#endif
+ ++p_extra;
+ }
+ --n_extra;
+ }
+ else
+ {
+ /*
+ * Get a character from the line itself.
+ */
+ c = *ptr;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ mb_c = c;
+ if (enc_utf8)
+ {
+ /* If the UTF-8 character is more than one byte: Decode it
+ * into "mb_c". */
+ mb_l = (*mb_ptr2len_check)(ptr);
+ mb_utf8 = FALSE;
+ if (mb_l > 1)
+ {
+ mb_c = utfc_ptr2char(ptr, &u8c_c1, &u8c_c2);
+ /* Overlong encoded ASCII or ASCII with composing char
+ * is displayed normally, except a NUL. */
+ if (mb_c < 0x80)
+ c = mb_c;
+ mb_utf8 = TRUE;
+ }
+
+ if ((mb_l == 1 && c >= 0x80)
+ || (mb_l >= 1 && mb_c == 0)
+ || (mb_l > 1 && (!vim_isprintc(mb_c)
+ || mb_c >= 0x10000)))
+ {
+ /*
+ * Illegal UTF-8 byte: display as <xx>.
+ * Non-BMP character : display as ? or fullwidth ?.
+ */
+ if (mb_c < 0x10000)
+ {
+ transchar_hex(extra, mb_c);
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl) /* reverse */
+ rl_mirror(extra);
+#endif
+ }
+ else if (utf_char2cells(mb_c) != 2)
+ STRCPY(extra, "?");
+ else
+ /* 0xff1f in UTF-8: full-width '?' */
+ STRCPY(extra, "\357\274\237");
+
+ p_extra = extra;
+ c = *p_extra;
+ mb_c = mb_ptr2char_adv(&p_extra);
+ mb_utf8 = (c >= 0x80);
+ n_extra = (int)STRLEN(p_extra);
+ c_extra = NUL;
+ if (area_attr == 0 && search_attr == 0)
+ {
+ n_attr = n_extra + 1;
+ extra_attr = hl_attr(HLF_8);
+ saved_attr2 = char_attr; /* save current attr */
+ }
+ }
+ else if (mb_l == 0) /* at the NUL at end-of-line */
+ mb_l = 1;
+#ifdef FEAT_ARABIC
+ else if (p_arshape && !p_tbidi && ARABIC_CHAR(mb_c))
+ {
+ /* Do Arabic shaping. */
+ int pc, pc1, nc, dummy;
+
+ /* The idea of what is the previous and next
+ * character depends on 'rightleft'. */
+ if (wp->w_p_rl)
+ {
+ pc = prev_c;
+ pc1 = prev_c1;
+ nc = utf_ptr2char(ptr + mb_l);
+ prev_c1 = u8c_c1;
+ }
+ else
+ {
+ pc = utfc_ptr2char(ptr + mb_l, &pc1, &dummy);
+ nc = prev_c;
+ }
+ prev_c = mb_c;
+
+ mb_c = arabic_shape(mb_c, &c, &u8c_c1, pc, pc1, nc);
+ }
+ else
+ prev_c = mb_c;
+#endif
+ }
+ else /* enc_dbcs */
+ {
+ mb_l = MB_BYTE2LEN(c);
+ if (mb_l == 0) /* at the NUL at end-of-line */
+ mb_l = 1;
+ else if (mb_l > 1)
+ {
+ /* We assume a second byte below 32 is illegal.
+ * Hopefully this is OK for all double-byte encodings!
+ */
+ if (ptr[1] >= 32)
+ mb_c = (c << 8) + ptr[1];
+ else
+ {
+ if (ptr[1] == NUL)
+ {
+ /* head byte at end of line */
+ mb_l = 1;
+ transchar_nonprint(extra, c);
+ }
+ else
+ {
+ /* illegal tail byte */
+ mb_l = 2;
+ STRCPY(extra, "XX");
+ }
+ p_extra = extra;
+ n_extra = (int)STRLEN(extra) - 1;
+ c_extra = NUL;
+ c = *p_extra++;
+ if (area_attr == 0 && search_attr == 0)
+ {
+ n_attr = n_extra + 1;
+ extra_attr = hl_attr(HLF_8);
+ saved_attr2 = char_attr; /* save current attr */
+ }
+ mb_c = c;
+ }
+ }
+ }
+ /* If a double-width char doesn't fit display a '>' in the
+ * last column; the character is displayed at the start of the
+ * next line. */
+ if ((
+# ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? (col <= 0) :
+# endif
+ (col >= W_WIDTH(wp) - 1))
+ && (*mb_char2cells)(mb_c) == 2)
+ {
+ c = '>';
+ mb_c = c;
+ mb_utf8 = FALSE;
+ mb_l = 1;
+ multi_attr = hl_attr(HLF_AT);
+ /* Put pointer back so that the character will be
+ * displayed at the start of the next line. */
+ --ptr;
+ }
+ else if (*ptr != NUL)
+ ptr += mb_l - 1;
+
+ /* If a double-width char doesn't fit at the left side display
+ * a '<' in the first column. */
+ if (n_skip > 0 && mb_l > 1)
+ {
+ extra[0] = '<';
+ p_extra = extra;
+ n_extra = 1;
+ c_extra = NUL;
+ c = ' ';
+ if (area_attr == 0 && search_attr == 0)
+ {
+ n_attr = n_extra + 1;
+ extra_attr = hl_attr(HLF_AT);
+ saved_attr2 = char_attr; /* save current attr */
+ }
+ mb_c = c;
+ mb_utf8 = FALSE;
+ mb_l = 1;
+ }
+
+ }
+#endif
+ ++ptr;
+
+ if (extra_check)
+ {
+#ifdef FEAT_SYN_HL
+ /* Get syntax attribute, unless still at the start of the line
+ * (double-wide char that doesn't fit). */
+ if (has_syntax && (v = (long)(ptr - line)) > 0)
+ {
+ /* Get the syntax attribute for the character. If there
+ * is an error, disable syntax highlighting. */
+ save_did_emsg = did_emsg;
+ did_emsg = FALSE;
+
+ syntax_attr = get_syntax_attr((colnr_T)v - 1);
+
+ if (did_emsg)
+ syntax_clear(wp->w_buffer);
+ else
+ did_emsg = save_did_emsg;
+
+ /* Need to get the line again, a multi-line regexp may
+ * have made it invalid. */
+ line = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ ptr = line + v;
+
+ if (area_attr == 0 && search_attr == 0)
+ char_attr = syntax_attr;
+ }
+#endif
+#ifdef FEAT_LINEBREAK
+ /*
+ * Found last space before word: check for line break
+ */
+ if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(*ptr)
+ && !wp->w_p_list)
+ {
+ n_extra = win_lbr_chartabsize(wp, ptr - (
+# ifdef FEAT_MBYTE
+ has_mbyte ? mb_l :
+# endif
+ 1), (colnr_T)vcol, NULL) - 1;
+ c_extra = ' ';
+ if (vim_iswhite(c))
+ c = ' ';
+ }
+#endif
+
+ if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ')
+ {
+ c = lcs_trail;
+ if (area_attr == 0 && search_attr == 0)
+ {
+ n_attr = 1;
+ extra_attr = hl_attr(HLF_8);
+ saved_attr2 = char_attr; /* save current attr */
+ }
+#ifdef FEAT_MBYTE
+ mb_c = c;
+ if (enc_utf8 && (*mb_char2len)(c) > 1)
+ {
+ mb_utf8 = TRUE;
+ u8c_c1 = u8c_c2 = 0;
+ }
+ else
+ mb_utf8 = FALSE;
+#endif
+ }
+ }
+
+ /*
+ * Handling of non-printable characters.
+ */
+ if (!(chartab[c] & CT_PRINT_CHAR))
+ {
+ /*
+ * when getting a character from the file, we may have to
+ * turn it into something else on the way to putting it
+ * into "ScreenLines".
+ */
+ if (c == TAB && (!wp->w_p_list || lcs_tab1))
+ {
+ /* tab amount depends on current column */
+ n_extra = (int)wp->w_buffer->b_p_ts
+ - vcol % (int)wp->w_buffer->b_p_ts - 1;
+#ifdef FEAT_MBYTE
+ mb_utf8 = FALSE; /* don't draw as UTF-8 */
+#endif
+ if (wp->w_p_list)
+ {
+ c = lcs_tab1;
+ c_extra = lcs_tab2;
+ n_attr = n_extra + 1;
+ extra_attr = hl_attr(HLF_8);
+ saved_attr2 = char_attr; /* save current attr */
+#ifdef FEAT_MBYTE
+ mb_c = c;
+ if (enc_utf8 && (*mb_char2len)(c) > 1)
+ {
+ mb_utf8 = TRUE;
+ u8c_c1 = u8c_c2 = 0;
+ }
+#endif
+ }
+ else
+ {
+ c_extra = ' ';
+ c = ' ';
+ }
+ }
+ else if (c == NUL && wp->w_p_list && lcs_eol_one > 0)
+ {
+#if defined(FEAT_DIFF) || defined(LINE_ATTR)
+ /* For a diff line the highlighting continues after the
+ * "$". */
+ if (
+# ifdef FEAT_DIFF
+ diff_hlf == (enum hlf_value)0
+# ifdef LINE_ATTR
+ &&
+# endif
+# endif
+# ifdef LINE_ATTR
+ line_attr == 0
+# endif
+ )
+#endif
+ {
+#ifdef FEAT_VIRTUALEDIT
+ /* In virtualedit, visual selections may extend
+ * beyond end of line. */
+ if (area_highlighting && virtual_active()
+ && tocol != MAXCOL && vcol < tocol)
+ n_extra = 0;
+ else
+#endif
+ {
+ p_extra = at_end_str;
+ n_extra = 1;
+ c_extra = NUL;
+ }
+ }
+ c = lcs_eol;
+ lcs_eol_one = -1;
+ --ptr; /* put it back at the NUL */
+ if (area_attr == 0 && search_attr == 0)
+ {
+ extra_attr = hl_attr(HLF_AT);
+ n_attr = 1;
+ }
+#ifdef FEAT_MBYTE
+ mb_c = c;
+ if (enc_utf8 && (*mb_char2len)(c) > 1)
+ {
+ mb_utf8 = TRUE;
+ u8c_c1 = u8c_c2 = 0;
+ }
+ else
+ mb_utf8 = FALSE; /* don't draw as UTF-8 */
+#endif
+ }
+ else if (c != NUL)
+ {
+ p_extra = transchar(c);
+#ifdef FEAT_RIGHTLEFT
+ if ((dy_flags & DY_UHEX) && wp->w_p_rl)
+ rl_mirror(p_extra); /* reverse "<12>" */
+#endif
+ n_extra = byte2cells(c) - 1;
+ c_extra = NUL;
+ c = *p_extra++;
+ if (area_attr == 0 && search_attr == 0)
+ {
+ n_attr = n_extra + 1;
+ extra_attr = hl_attr(HLF_8);
+ saved_attr2 = char_attr; /* save current attr */
+ }
+#ifdef FEAT_MBYTE
+ mb_utf8 = FALSE; /* don't draw as UTF-8 */
+#endif
+ }
+#ifdef FEAT_VIRTUALEDIT
+ else if (VIsual_active
+ && (VIsual_mode == Ctrl_V
+ || VIsual_mode == 'v')
+ && virtual_active()
+ && tocol != MAXCOL
+ && vcol < tocol
+ && (
+# ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? (col >= 0) :
+# endif
+ (col < W_WIDTH(wp))))
+ {
+ c = ' ';
+ --ptr; /* put it back at the NUL */
+ }
+#endif
+#if defined(FEAT_DIFF) || defined(LINE_ATTR)
+ else if ((
+# ifdef FEAT_DIFF
+ diff_hlf != (enum hlf_value)0
+# ifdef LINE_ATTR
+ ||
+# endif
+# endif
+# ifdef LINE_ATTR
+ line_attr != 0
+# endif
+ ) && (
+# ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? (col >= 0) :
+# endif
+ (col < W_WIDTH(wp))))
+ {
+ /* Highlight until the right side of the window */
+ c = ' ';
+ --ptr; /* put it back at the NUL */
+# ifdef FEAT_DIFF
+ if (diff_hlf == HLF_TXD)
+ {
+ diff_hlf = HLF_CHD;
+ if (attr == 0 || char_attr != attr)
+ char_attr = hl_attr(diff_hlf);
+ }
+# endif
+ }
+#endif
+ }
+ }
+
+ /* Don't override visual selection highlighting. */
+ if (n_attr > 0
+ && draw_state == WL_LINE
+ && (area_attr == 0 || char_attr != area_attr)
+ && (search_attr == 0 || char_attr != search_attr))
+ char_attr = extra_attr;
+
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+ /* XIM don't send preedit_start and preedit_end, but they send
+ * preedit_changed and commit. Thus Vim can't set "im_is_active", use
+ * im_is_preediting() here. */
+ if (xic != NULL
+ && lnum == curwin->w_cursor.lnum
+ && (State & INSERT)
+ && !p_imdisable
+ && im_is_preediting()
+ && draw_state == WL_LINE)
+ {
+ colnr_T tcol;
+
+ if (preedit_end_col == MAXCOL)
+ getvcol(curwin, &(curwin->w_cursor), &tcol, NULL, NULL);
+ else
+ tcol = preedit_end_col;
+ if ((long)preedit_start_col <= vcol && vcol < (long)tcol)
+ {
+ if (feedback_old_attr < 0)
+ {
+ feedback_col = 0;
+ feedback_old_attr = char_attr;
+ }
+ char_attr = im_get_feedback_attr(feedback_col);
+ if (char_attr < 0)
+ char_attr = feedback_old_attr;
+ feedback_col++;
+ }
+ else if (feedback_old_attr >= 0)
+ {
+ char_attr = feedback_old_attr;
+ feedback_old_attr = -1;
+ feedback_col = 0;
+ }
+ }
+#endif
+ /*
+ * Handle the case where we are in column 0 but not on the first
+ * character of the line and the user wants us to show us a
+ * special character (via 'listchars' option "precedes:<char>".
+ */
+ if (lcs_prec_todo != NUL
+ && (wp->w_p_wrap ? wp->w_skipcol > 0 : wp->w_leftcol > 0)
+#ifdef FEAT_DIFF
+ && filler_todo <= 0
+#endif
+ && draw_state > WL_NR
+ && c != NUL)
+ {
+ c = lcs_prec;
+ lcs_prec_todo = NUL;
+#ifdef FEAT_MBYTE
+ mb_c = c;
+ if (enc_utf8 && (*mb_char2len)(c) > 1)
+ {
+ mb_utf8 = TRUE;
+ u8c_c1 = u8c_c2 = 0;
+ }
+ else
+ mb_utf8 = FALSE; /* don't draw as UTF-8 */
+#endif
+ if ((area_attr == 0 || char_attr != area_attr)
+ && (search_attr == 0 || char_attr != search_attr))
+ {
+ saved_attr3 = char_attr; /* save current attr */
+ char_attr = hl_attr(HLF_AT); /* later copied to char_attr */
+ n_attr3 = 1;
+ }
+ }
+
+ /*
+ * At end of the text line.
+ */
+ if (c == NUL)
+ {
+ /* invert at least one char, used for Visual and empty line or
+ * highlight match at end of line. If it's beyond the last
+ * char on the screen, just overwrite that one (tricky!) Not
+ * needed when a '$' was displayed for 'list'. */
+ if (lcs_eol == lcs_eol_one
+ && ((area_attr != 0 && vcol == fromcol)
+#ifdef FEAT_SEARCH_EXTRA
+ /* highlight 'hlsearch' match at end of line */
+ || ptr - 1 == search_hl.startp
+ || ptr - 1 == match_hl.startp
+#endif
+ ))
+ {
+ int n = 0;
+
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ {
+ if (col < 0)
+ n = 1;
+ }
+ else
+#endif
+ {
+ if (col >= W_WIDTH(wp))
+ n = -1;
+ }
+ if (n != 0)
+ {
+ /* At the window boundary, highlight the last character
+ * instead (better than nothing). */
+ off += n;
+ col += n;
+ }
+ else
+ {
+ /* Add a blank character to highlight. */
+ ScreenLines[off] = ' ';
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ ScreenLinesUC[off] = 0;
+#endif
+ }
+#ifdef FEAT_SEARCH_EXTRA
+ if (area_attr == 0)
+ {
+ if (ptr - 1 == match_hl.startp)
+ char_attr = match_hl.attr;
+ else
+ char_attr = search_hl.attr;
+ }
+#endif
+ ScreenAttrs[off] = char_attr;
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ --col;
+ else
+#endif
+ ++col;
+ }
+
+ SCREEN_LINE(screen_row, W_WINCOL(wp), col, (int)W_WIDTH(wp),
+ wp->w_p_rl);
+ row++;
+
+ /*
+ * Update w_cline_height and w_cline_folded if the cursor line was
+ * updated (saves a call to plines() later).
+ */
+ if (wp == curwin && lnum == curwin->w_cursor.lnum)
+ {
+ curwin->w_cline_row = startrow;
+ curwin->w_cline_height = row - startrow;
+#ifdef FEAT_FOLDING
+ curwin->w_cline_folded = FALSE;
+#endif
+ curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW);
+ }
+
+ break;
+ }
+
+ /* line continues beyond line end */
+ if (lcs_ext
+ && !wp->w_p_wrap
+#ifdef FEAT_DIFF
+ && filler_todo <= 0
+#endif
+ && (
+#ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? col == 0 :
+#endif
+ col == W_WIDTH(wp) - 1)
+ && (*ptr != NUL
+ || (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str)
+ || (n_extra && (c_extra != NUL || *p_extra != NUL))))
+ {
+ c = lcs_ext;
+ char_attr = hl_attr(HLF_AT);
+#ifdef FEAT_MBYTE
+ mb_c = c;
+ if (enc_utf8 && (*mb_char2len)(c) > 1)
+ {
+ mb_utf8 = TRUE;
+ u8c_c1 = u8c_c2 = 0;
+ }
+ else
+ mb_utf8 = FALSE;
+#endif
+ }
+
+ /*
+ * Store character to be displayed.
+ * Skip characters that are left of the screen for 'nowrap'.
+ */
+ vcol_prev = vcol;
+ if (draw_state < WL_LINE || n_skip <= 0)
+ {
+ /*
+ * Store the character.
+ */
+#if defined(FEAT_RIGHTLEFT) && defined(FEAT_MBYTE)
+ if (has_mbyte && wp->w_p_rl && (*mb_char2cells)(mb_c) > 1)
+ {
+ /* A double-wide character is: put first halve in left cell. */
+ --off;
+ --col;
+ }
+#endif
+ ScreenLines[off] = c;
+#ifdef FEAT_MBYTE
+ if (enc_dbcs == DBCS_JPNU)
+ ScreenLines2[off] = mb_c & 0xff;
+ else if (enc_utf8)
+ {
+ if (mb_utf8)
+ {
+ ScreenLinesUC[off] = mb_c;
+ ScreenLinesC1[off] = u8c_c1;
+ ScreenLinesC2[off] = u8c_c2;
+ }
+ else
+ ScreenLinesUC[off] = 0;
+ }
+ if (multi_attr)
+ {
+ ScreenAttrs[off] = multi_attr;
+ multi_attr = 0;
+ }
+ else
+#endif
+ ScreenAttrs[off] = char_attr;
+
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (*mb_char2cells)(mb_c) > 1)
+ {
+ /* Need to fill two screen columns. */
+ ++off;
+ ++col;
+ if (enc_utf8)
+ /* UTF-8: Put a 0 in the second screen char. */
+ ScreenLines[off] = 0;
+ else
+ /* DBCS: Put second byte in the second screen char. */
+ ScreenLines[off] = mb_c & 0xff;
+ ++vcol;
+ /* When "tocol" is halfway a character, set it to the end of
+ * the character, otherwise highlighting won't stop. */
+ if (tocol == vcol)
+ ++tocol;
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ {
+ /* now it's time to backup one cell */
+ --off;
+ --col;
+ }
+#endif
+ }
+#endif
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ {
+ --off;
+ --col;
+ }
+ else
+#endif
+ {
+ ++off;
+ ++col;
+ }
+ }
+ else
+ --n_skip;
+
+ /* Only advance the "vcol" when after the 'number' column. */
+ if (draw_state >= WL_SBR
+#ifdef FEAT_DIFF
+ && filler_todo <= 0
+#endif
+ )
+ ++vcol;
+
+ /* restore attributes after "predeces" in 'listchars' */
+ if (draw_state > WL_NR && n_attr3 > 0 && --n_attr3 == 0)
+ char_attr = saved_attr3;
+
+ /* restore attributes after last 'listchars' or 'number' char */
+ if (n_attr > 0 && draw_state == WL_LINE && --n_attr == 0)
+ char_attr = saved_attr2;
+
+ /*
+ * At end of screen line and there is more to come: Display the line
+ * so far. If there is no more to display it is catched above.
+ */
+ if ((
+#ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? (col < 0) :
+#endif
+ (col >= W_WIDTH(wp)))
+ && (*ptr != NUL
+#ifdef FEAT_DIFF
+ || filler_todo > 0
+#endif
+ || (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str)
+ || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL)))
+ )
+ {
+ SCREEN_LINE(screen_row, W_WINCOL(wp), col, (int)W_WIDTH(wp),
+ wp->w_p_rl);
+ ++row;
+ ++screen_row;
+
+ /* When not wrapping and finished diff lines, or when displayed
+ * '$' and highlighting until last column, break here. */
+ if ((!wp->w_p_wrap
+#ifdef FEAT_DIFF
+ && filler_todo <= 0
+#endif
+ ) || lcs_eol_one == -1)
+ break;
+
+ /* When the window is too narrow draw all "@" lines. */
+ if (draw_state != WL_LINE
+#ifdef FEAT_DIFF
+ && filler_todo <= 0
+#endif
+ )
+ {
+ win_draw_end(wp, '@', ' ', row, wp->w_height, HLF_AT);
+#ifdef FEAT_VERTSPLIT
+ draw_vsep_win(wp, row);
+#endif
+ row = endrow;
+ }
+
+ /* When line got too long for screen break here. */
+ if (row == endrow)
+ {
+ ++row;
+ break;
+ }
+
+ if (screen_cur_row == screen_row - 1
+#ifdef FEAT_DIFF
+ && filler_todo <= 0
+#endif
+ && W_WIDTH(wp) == Columns)
+ {
+ /* Remember that the line wraps, used for modeless copy. */
+ LineWraps[screen_row - 1] = TRUE;
+
+ /*
+ * Special trick to make copy/paste of wrapped lines work with
+ * xterm/screen: write an extra character beyond the end of
+ * the line. This will work with all terminal types
+ * (regardless of the xn,am settings).
+ * Only do this on a fast tty.
+ * Only do this if the cursor is on the current line
+ * (something has been written in it).
+ * Don't do this for the GUI.
+ * Don't do this for double-width characters.
+ * Don't do this for a window not at the right screen border.
+ */
+ if (p_tf
+#ifdef FEAT_GUI
+ && !gui.in_use
+#endif
+#ifdef FEAT_MBYTE
+ && !(has_mbyte
+ && ((*mb_off2cells)(LineOffset[screen_row]) == 2
+ || (*mb_off2cells)(LineOffset[screen_row - 1]
+ + (int)Columns - 2) == 2))
+#endif
+ )
+ {
+ /* First make sure we are at the end of the screen line,
+ * then output the same character again to let the
+ * terminal know about the wrap. If the terminal doesn't
+ * auto-wrap, we overwrite the character. */
+ if (screen_cur_col != W_WIDTH(wp))
+ screen_char(LineOffset[screen_row - 1]
+ + (unsigned)Columns - 1,
+ screen_row - 1, (int)(Columns - 1));
+
+#ifdef FEAT_MBYTE
+ /* When there is a multi-byte character, just output a
+ * space to keep it simple. */
+ if (has_mbyte && mb_off2cells(LineOffset[screen_row - 1]
+ + (unsigned)Columns - 1) != 1)
+ out_char(' ');
+ else
+#endif
+ out_char(ScreenLines[LineOffset[screen_row - 1]
+ + (Columns - 1)]);
+ /* force a redraw of the first char on the next line */
+ ScreenAttrs[LineOffset[screen_row]] = (sattr_T)-1;
+ screen_start(); /* don't know where cursor is now */
+ }
+ }
+
+ col = 0;
+ off = (unsigned)(current_ScreenLine - ScreenLines);
+#ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ {
+ col = W_WIDTH(wp) - 1; /* col is not used if breaking! */
+ off += col;
+ }
+#endif
+
+ /* reset the drawing state for the start of a wrapped line */
+ draw_state = WL_START;
+ saved_n_extra = n_extra;
+ saved_p_extra = p_extra;
+ saved_c_extra = c_extra;
+ saved_char_attr = char_attr;
+ n_extra = 0;
+ lcs_prec_todo = lcs_prec;
+#ifdef FEAT_LINEBREAK
+# ifdef FEAT_DIFF
+ if (filler_todo <= 0)
+# endif
+ need_showbreak = TRUE;
+#endif
+#ifdef FEAT_DIFF
+ --filler_todo;
+ /* When the filler lines are actually below the last line of the
+ * file, don't draw the line itself, break here. */
+ if (filler_todo == 0 && wp->w_botfill)
+ break;
+#endif
+ }
+
+ } /* for every character in the line */
+
+ return row;
+}
+
+/*
+ * Check whether the given character needs redrawing:
+ * - the (first byte of the) character is different
+ * - the attributes are different
+ * - the character is multi-byte and the next byte is different
+ */
+ static int
+char_needs_redraw(off_from, off_to, cols)
+ int off_from;
+ int off_to;
+ int cols;
+{
+ if (cols > 0
+ && ((ScreenLines[off_from] != ScreenLines[off_to]
+ || ScreenAttrs[off_from] != ScreenAttrs[off_to])
+
+#ifdef FEAT_MBYTE
+ || (enc_dbcs != 0
+ && MB_BYTE2LEN(ScreenLines[off_from]) > 1
+ && (enc_dbcs == DBCS_JPNU && ScreenLines[off_from] == 0x8e
+ ? ScreenLines2[off_from] != ScreenLines2[off_to]
+ : (cols > 1 && ScreenLines[off_from + 1]
+ != ScreenLines[off_to + 1])))
+ || (enc_utf8
+ && (ScreenLinesUC[off_from] != ScreenLinesUC[off_to]
+ || (ScreenLinesUC[off_from] != 0
+ && (ScreenLinesC1[off_from]
+ != ScreenLinesC1[off_to]
+ || ScreenLinesC2[off_from]
+ != ScreenLinesC2[off_to]))))
+#endif
+ ))
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Move one "cooked" screen line to the screen, but only the characters that
+ * have actually changed. Handle insert/delete character.
+ * "coloff" gives the first column on the screen for this line.
+ * "endcol" gives the columns where valid characters are.
+ * "clear_width" is the width of the window. It's > 0 if the rest of the line
+ * needs to be cleared, negative otherwise.
+ * "rlflag" is TRUE in a rightleft window:
+ * When TRUE and "clear_width" > 0, clear columns 0 to "endcol"
+ * When FALSE and "clear_width" > 0, clear columns "endcol" to "clear_width"
+ */
+ static void
+screen_line(row, coloff, endcol, clear_width
+#ifdef FEAT_RIGHTLEFT
+ , rlflag
+#endif
+ )
+ int row;
+ int coloff;
+ int endcol;
+ int clear_width;
+#ifdef FEAT_RIGHTLEFT
+ int rlflag;
+#endif
+{
+ unsigned off_from;
+ unsigned off_to;
+ int col = 0;
+#if defined(FEAT_GUI) || defined(UNIX) || defined(FEAT_VERTSPLIT)
+ int hl;
+#endif
+ int force = FALSE; /* force update rest of the line */
+ int redraw_this /* bool: does character need redraw? */
+#ifdef FEAT_GUI
+ = TRUE /* For GUI when while-loop empty */
+#endif
+ ;
+ int redraw_next; /* redraw_this for next character */
+#ifdef FEAT_MBYTE
+ int clear_next = FALSE;
+ int char_cells; /* 1: normal char */
+ /* 2: occupies two display cells */
+# define CHAR_CELLS char_cells
+#else
+# define CHAR_CELLS 1
+#endif
+
+# ifdef FEAT_CLIPBOARD
+ clip_may_clear_selection(row, row);
+# endif
+
+ off_from = (unsigned)(current_ScreenLine - ScreenLines);
+ off_to = LineOffset[row] + coloff;
+
+#ifdef FEAT_RIGHTLEFT
+ if (rlflag)
+ {
+ /* Clear rest first, because it's left of the text. */
+ if (clear_width > 0)
+ {
+ while (col <= endcol && ScreenLines[off_to] == ' '
+ && ScreenAttrs[off_to] == 0
+# ifdef FEAT_MBYTE
+ && (!enc_utf8 || ScreenLinesUC[off_to] == 0)
+# endif
+ )
+ {
+ ++off_to;
+ ++col;
+ }
+ if (col <= endcol)
+ screen_fill(row, row + 1, col + coloff,
+ endcol + coloff + 1, ' ', ' ', 0);
+ }
+ col = endcol + 1;
+ off_to = LineOffset[row] + col + coloff;
+ off_from += col;
+ endcol = (clear_width > 0 ? clear_width : -clear_width);
+ }
+#endif /* FEAT_RIGHTLEFT */
+
+ redraw_next = char_needs_redraw(off_from, off_to, endcol - col);
+
+ while (col < endcol)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (col + 1 < endcol))
+ char_cells = (*mb_off2cells)(off_from);
+ else
+ char_cells = 1;
+#endif
+
+ redraw_this = redraw_next;
+ redraw_next = force || char_needs_redraw(off_from + CHAR_CELLS,
+ off_to + CHAR_CELLS, endcol - col - CHAR_CELLS);
+
+#ifdef FEAT_GUI
+ /* If the next character was bold, then redraw the current character to
+ * remove any pixels that might have spilt over into us. This only
+ * happens in the GUI.
+ */
+ if (redraw_next && gui.in_use)
+ {
+ hl = ScreenAttrs[off_to + CHAR_CELLS];
+ if (hl > HL_ALL || (hl & HL_BOLD))
+ redraw_this = TRUE;
+ }
+#endif
+
+ if (redraw_this)
+ {
+ /*
+ * Special handling when 'xs' termcap flag set (hpterm):
+ * Attributes for characters are stored at the position where the
+ * cursor is when writing the highlighting code. The
+ * start-highlighting code must be written with the cursor on the
+ * first highlighted character. The stop-highlighting code must
+ * be written with the cursor just after the last highlighted
+ * character.
+ * Overwriting a character doesn't remove it's highlighting. Need
+ * to clear the rest of the line, and force redrawing it
+ * completely.
+ */
+ if ( p_wiv
+ && !force
+#ifdef FEAT_GUI
+ && !gui.in_use
+#endif
+ && ScreenAttrs[off_to] != 0
+ && ScreenAttrs[off_from] != ScreenAttrs[off_to])
+ {
+ /*
+ * Need to remove highlighting attributes here.
+ */
+ windgoto(row, col + coloff);
+ out_str(T_CE); /* clear rest of this screen line */
+ screen_start(); /* don't know where cursor is now */
+ force = TRUE; /* force redraw of rest of the line */
+ redraw_next = TRUE; /* or else next char would miss out */
+
+ /*
+ * If the previous character was highlighted, need to stop
+ * highlighting at this character.
+ */
+ if (col + coloff > 0 && ScreenAttrs[off_to - 1] != 0)
+ {
+ screen_attr = ScreenAttrs[off_to - 1];
+ term_windgoto(row, col + coloff);
+ screen_stop_highlight();
+ }
+ else
+ screen_attr = 0; /* highlighting has stopped */
+ }
+#ifdef FEAT_MBYTE
+ if (enc_dbcs != 0)
+ {
+ /* Check if overwriting a double-byte with a single-byte or
+ * the other way around requires another character to be
+ * redrawn. For UTF-8 this isn't needed, because comparing
+ * ScreenLinesUC[] is sufficient. */
+ if (char_cells == 1
+ && col + 1 < endcol
+ && (*mb_off2cells)(off_to) > 1)
+ {
+ /* Writing a single-cell character over a double-cell
+ * character: need to redraw the next cell. */
+ ScreenLines[off_to + 1] = 0;
+ redraw_next = TRUE;
+ }
+ else if (char_cells == 2
+ && col + 2 < endcol
+ && (*mb_off2cells)(off_to) == 1
+ && (*mb_off2cells)(off_to + 1) > 1)
+ {
+ /* Writing the second half of a double-cell character over
+ * a double-cell character: need to redraw the second
+ * cell. */
+ ScreenLines[off_to + 2] = 0;
+ redraw_next = TRUE;
+ }
+
+ if (enc_dbcs == DBCS_JPNU)
+ ScreenLines2[off_to] = ScreenLines2[off_from];
+ }
+ /* When writing a single-width character over a double-width
+ * character and at the end of the redrawn text, need to clear out
+ * the right halve of the old character.
+ * Also required when writing the right halve of a double-width
+ * char over the left halve of an existing one. */
+ if (has_mbyte && col + char_cells == endcol
+ && ((char_cells == 1
+ && (*mb_off2cells)(off_to) > 1)
+ || (char_cells == 2
+ && (*mb_off2cells)(off_to) == 1
+ && (*mb_off2cells)(off_to + 1) > 1)))
+ clear_next = TRUE;
+#endif
+
+ ScreenLines[off_to] = ScreenLines[off_from];
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ {
+ ScreenLinesUC[off_to] = ScreenLinesUC[off_from];
+ if (ScreenLinesUC[off_from] != 0)
+ {
+ ScreenLinesC1[off_to] = ScreenLinesC1[off_from];
+ ScreenLinesC2[off_to] = ScreenLinesC2[off_from];
+ }
+ }
+ if (char_cells == 2)
+ ScreenLines[off_to + 1] = ScreenLines[off_from + 1];
+#endif
+
+#if defined(FEAT_GUI) || defined(UNIX)
+ /* The bold trick makes a single row of pixels appear in the next
+ * character. When a bold character is removed, the next
+ * character should be redrawn too. This happens for our own GUI
+ * and for some xterms. */
+ if (
+# ifdef FEAT_GUI
+ gui.in_use
+# endif
+# if defined(FEAT_GUI) && defined(UNIX)
+ ||
+# endif
+# ifdef UNIX
+ term_is_xterm
+# endif
+ )
+ {
+ hl = ScreenAttrs[off_to];
+ if (hl > HL_ALL || (hl & HL_BOLD))
+ redraw_next = TRUE;
+ }
+#endif
+ ScreenAttrs[off_to] = ScreenAttrs[off_from];
+#ifdef FEAT_MBYTE
+ if (enc_dbcs != 0 && char_cells == 2)
+ {
+ /* just a hack: It makes two bytes of DBCS have same attr */
+ ScreenAttrs[off_to + 1] = ScreenAttrs[off_from];
+ screen_char_2(off_to, row, col + coloff);
+ }
+ else
+#endif
+ screen_char(off_to, row, col + coloff);
+ }
+ else if ( p_wiv
+#ifdef FEAT_GUI
+ && !gui.in_use
+#endif
+ && col + coloff > 0)
+ {
+ if (ScreenAttrs[off_to] == ScreenAttrs[off_to - 1])
+ {
+ /*
+ * Don't output stop-highlight when moving the cursor, it will
+ * stop the highlighting when it should continue.
+ */
+ screen_attr = 0;
+ }
+ else if (screen_attr != 0)
+ screen_stop_highlight();
+ }
+
+ off_to += CHAR_CELLS;
+ off_from += CHAR_CELLS;
+ col += CHAR_CELLS;
+ }
+
+#ifdef FEAT_MBYTE
+ if (clear_next)
+ {
+ /* Clear the second half of a double-wide character of which the left
+ * half was overwritten with a single-wide character. */
+ ScreenLines[off_to] = ' ';
+ if (enc_utf8)
+ ScreenLinesUC[off_to] = 0;
+ screen_char(off_to, row, col + coloff);
+ }
+#endif
+
+ if (clear_width > 0
+#ifdef FEAT_RIGHTLEFT
+ && !rlflag
+#endif
+ )
+ {
+#ifdef FEAT_GUI
+ int startCol = col;
+#endif
+
+ /* blank out the rest of the line */
+ while (col < clear_width && ScreenLines[off_to] == ' '
+ && ScreenAttrs[off_to] == 0
+#ifdef FEAT_MBYTE
+ && (!enc_utf8 || ScreenLinesUC[off_to] == 0)
+#endif
+ )
+ {
+ ++off_to;
+ ++col;
+ }
+ if (col < clear_width)
+ {
+#ifdef FEAT_GUI
+ /*
+ * In the GUI, clearing the rest of the line may leave pixels
+ * behind if the first character cleared was bold. Some bold
+ * fonts spill over the left. In this case we redraw the previous
+ * character too. If we didn't skip any blanks above, then we
+ * only redraw if the character wasn't already redrawn anyway.
+ */
+ if (gui.in_use && (col > startCol || !redraw_this)
+# ifdef FEAT_MBYTE
+ && enc_dbcs == 0
+# endif
+ )
+ {
+ hl = ScreenAttrs[off_to];
+ if (hl > HL_ALL || (hl & HL_BOLD))
+ screen_char(off_to - 1, row, col + coloff - 1);
+ }
+#endif
+ screen_fill(row, row + 1, col + coloff, clear_width + coloff,
+ ' ', ' ', 0);
+#ifdef FEAT_VERTSPLIT
+ off_to += clear_width - col;
+ col = clear_width;
+#endif
+ }
+ }
+
+ if (clear_width > 0)
+ {
+#ifdef FEAT_VERTSPLIT
+ /* For a window that's left of another, draw the separator char. */
+ if (col + coloff < Columns)
+ {
+ int c;
+
+ c = fillchar_vsep(&hl);
+ if (ScreenLines[off_to] != c
+# ifdef FEAT_MBYTE
+ || (enc_utf8
+ && ScreenLinesUC[off_to] != (c >= 0x80 ? c : 0))
+# endif
+ || ScreenAttrs[off_to] != hl)
+ {
+ ScreenLines[off_to] = c;
+ ScreenAttrs[off_to] = hl;
+# ifdef FEAT_MBYTE
+ if (enc_utf8)
+ {
+ if (c >= 0x80)
+ {
+ ScreenLinesUC[off_to] = c;
+ ScreenLinesC1[off_to] = 0;
+ ScreenLinesC2[off_to] = 0;
+ }
+ else
+ ScreenLinesUC[off_to] = 0;
+ }
+# endif
+ screen_char(off_to, row, col + coloff);
+ }
+ }
+ else
+#endif
+ LineWraps[row] = FALSE;
+ }
+}
+
+#ifdef FEAT_RIGHTLEFT
+/*
+ * Mirror text "str" for right-lieft displaying.
+ */
+ static void
+rl_mirror(str)
+ char_u *str;
+{
+ char_u *p1, *p2;
+ int t;
+
+ for (p1 = str, p2 = str + STRLEN(str) - 1; p1 < p2; ++p1, --p2)
+ {
+ t = *p1;
+ *p1 = *p2;
+ *p2 = t;
+ }
+}
+#endif
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * mark all status lines for redraw; used after first :cd
+ */
+ void
+status_redraw_all()
+{
+ win_T *wp;
+
+ for (wp = firstwin; wp; wp = wp->w_next)
+ if (wp->w_status_height)
+ {
+ wp->w_redr_status = TRUE;
+ redraw_later(VALID);
+ }
+}
+
+/*
+ * mark all status lines of the current buffer for redraw
+ */
+ void
+status_redraw_curbuf()
+{
+ win_T *wp;
+
+ for (wp = firstwin; wp; wp = wp->w_next)
+ if (wp->w_status_height != 0 && wp->w_buffer == curbuf)
+ {
+ wp->w_redr_status = TRUE;
+ redraw_later(VALID);
+ }
+}
+
+/*
+ * Redraw all status lines that need to be redrawn.
+ */
+ void
+redraw_statuslines()
+{
+ win_T *wp;
+
+ for (wp = firstwin; wp; wp = wp->w_next)
+ if (wp->w_redr_status)
+ win_redr_status(wp);
+}
+#endif
+
+#if (defined(FEAT_WILDMENU) && defined(FEAT_VERTSPLIT)) || defined(PROTO)
+/*
+ * Redraw all status lines at the bottom of frame "frp".
+ */
+ void
+win_redraw_last_status(frp)
+ frame_T *frp;
+{
+ if (frp->fr_layout == FR_LEAF)
+ frp->fr_win->w_redr_status = TRUE;
+ else if (frp->fr_layout == FR_ROW)
+ {
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
+ win_redraw_last_status(frp);
+ }
+ else /* frp->fr_layout == FR_COL */
+ {
+ frp = frp->fr_child;
+ while (frp->fr_next != NULL)
+ frp = frp->fr_next;
+ win_redraw_last_status(frp);
+ }
+}
+#endif
+
+#ifdef FEAT_VERTSPLIT
+/*
+ * Draw the verticap separator right of window "wp" starting with line "row".
+ */
+ static void
+draw_vsep_win(wp, row)
+ win_T *wp;
+ int row;
+{
+ int hl;
+ int c;
+
+ if (wp->w_vsep_width)
+ {
+ /* draw the vertical separator right of this window */
+ c = fillchar_vsep(&hl);
+ screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + wp->w_height,
+ W_ENDCOL(wp), W_ENDCOL(wp) + 1,
+ c, ' ', hl);
+ }
+}
+#endif
+
+#ifdef FEAT_WILDMENU
+static int status_match_len __ARGS((expand_T *xp, char_u *s));
+
+/*
+ * Get the lenght of an item as it will be shown in the status line.
+ */
+ static int
+status_match_len(xp, s)
+ expand_T *xp;
+ char_u *s;
+{
+ int len = 0;
+
+#ifdef FEAT_MENU
+ int emenu = (xp->xp_context == EXPAND_MENUS
+ || xp->xp_context == EXPAND_MENUNAMES);
+
+ /* Check for menu separators - replace with '|'. */
+ if (emenu && menu_is_separator(s))
+ return 1;
+#endif
+
+ while (*s != NUL)
+ {
+ /* Don't display backslashes used for escaping, they look ugly. */
+ if (rem_backslash(s)
+#ifdef FEAT_MENU
+ || (emenu && (s[0] == '\\' && s[1] != NUL))
+#endif
+ )
+ ++s;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ len += ptr2cells(s);
+ s += (*mb_ptr2len_check)(s);
+ }
+ else
+#endif
+ len += ptr2cells(s++);
+
+ }
+
+ return len;
+}
+
+/*
+ * Show wildchar matches in the status line.
+ * Show at least the "match" item.
+ * We start at item 'first_match' in the list and show all matches that fit.
+ *
+ * If inversion is possible we use it. Else '=' characters are used.
+ */
+ void
+win_redr_status_matches(xp, num_matches, matches, match, showtail)
+ expand_T *xp;
+ int num_matches;
+ char_u **matches; /* list of matches */
+ int match;
+ int showtail;
+{
+#define L_MATCH(m) (showtail ? sm_gettail(matches[m]) : matches[m])
+ int row;
+ char_u *buf;
+ int len;
+ int clen; /* lenght in screen cells */
+ int fillchar;
+ int attr;
+ int i;
+ int highlight = TRUE;
+ char_u *selstart = NULL;
+ int selstart_col = 0;
+ char_u *selend = NULL;
+ static int first_match = 0;
+ int add_left = FALSE;
+ char_u *s;
+#ifdef FEAT_MENU
+ int emenu;
+#endif
+#if defined(FEAT_MBYTE) || defined(FEAT_MENU)
+ int l;
+#endif
+
+ if (matches == NULL) /* interrupted completion? */
+ return;
+
+ buf = alloc((unsigned)Columns + 1);
+ if (buf == NULL)
+ return;
+
+ if (match == -1) /* don't show match but original text */
+ {
+ match = 0;
+ highlight = FALSE;
+ }
+ /* count 1 for the ending ">" */
+ clen = status_match_len(xp, L_MATCH(match)) + 3;
+ if (match == 0)
+ first_match = 0;
+ else if (match < first_match)
+ {
+ /* jumping left, as far as we can go */
+ first_match = match;
+ add_left = TRUE;
+ }
+ else
+ {
+ /* check if match fits on the screen */
+ for (i = first_match; i < match; ++i)
+ clen += status_match_len(xp, L_MATCH(i)) + 2;
+ if (first_match > 0)
+ clen += 2;
+ /* jumping right, put match at the left */
+ if ((long)clen > Columns)
+ {
+ first_match = match;
+ /* if showing the last match, we can add some on the left */
+ clen = 2;
+ for (i = match; i < num_matches; ++i)
+ {
+ clen += status_match_len(xp, L_MATCH(i)) + 2;
+ if ((long)clen >= Columns)
+ break;
+ }
+ if (i == num_matches)
+ add_left = TRUE;
+ }
+ }
+ if (add_left)
+ while (first_match > 0)
+ {
+ clen += status_match_len(xp, L_MATCH(first_match - 1)) + 2;
+ if ((long)clen >= Columns)
+ break;
+ --first_match;
+ }
+
+ fillchar = fillchar_status(&attr, TRUE);
+
+ if (first_match == 0)
+ {
+ *buf = NUL;
+ len = 0;
+ }
+ else
+ {
+ STRCPY(buf, "< ");
+ len = 2;
+ }
+ clen = len;
+
+ i = first_match;
+ while ((long)(clen + status_match_len(xp, L_MATCH(i)) + 2) < Columns)
+ {
+ if (i == match)
+ {
+ selstart = buf + len;
+ selstart_col = clen;
+ }
+
+ s = L_MATCH(i);
+ /* Check for menu separators - replace with '|' */
+#ifdef FEAT_MENU
+ emenu = (xp->xp_context == EXPAND_MENUS
+ || xp->xp_context == EXPAND_MENUNAMES);
+ if (emenu && menu_is_separator(s))
+ {
+ STRCPY(buf + len, transchar('|'));
+ l = (int)STRLEN(buf + len);
+ len += l;
+ clen += l;
+ }
+ else
+#endif
+ for ( ; *s != NUL; ++s)
+ {
+ /* Don't display backslashes used for escaping, they look ugly. */
+ if (rem_backslash(s)
+#ifdef FEAT_MENU
+ || (emenu
+ && (s[0] == '\t' || (s[0] == '\\' && s[1] != NUL)))
+#endif
+ )
+ ++s;
+ clen += ptr2cells(s);
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (l = (*mb_ptr2len_check)(s)) > 1)
+ {
+ STRNCPY(buf + len, s, l);
+ s += l - 1;
+ len += l;
+ }
+ else
+#endif
+ {
+ STRCPY(buf + len, transchar_byte(*s));
+ len += (int)STRLEN(buf + len);
+ }
+ }
+ if (i == match)
+ selend = buf + len;
+
+ *(buf + len++) = ' ';
+ *(buf + len++) = ' ';
+ clen += 2;
+ if (++i == num_matches)
+ break;
+ }
+
+ if (i != num_matches)
+ {
+ *(buf + len++) = '>';
+ ++clen;
+ }
+
+ buf[len] = NUL;
+
+ row = cmdline_row - 1;
+ if (row >= 0)
+ {
+ if (wild_menu_showing == 0)
+ {
+ if (msg_scrolled > 0)
+ {
+ /* Put the wildmenu just above the command line. If there is
+ * no room, scroll the screen one line up. */
+ if (cmdline_row == Rows - 1)
+ {
+ screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL);
+ ++msg_scrolled;
+ }
+ else
+ {
+ ++cmdline_row;
+ ++row;
+ }
+ wild_menu_showing = WM_SCROLLED;
+ }
+ else
+ {
+ /* Create status line if needed by setting 'laststatus' to 2.
+ * Set 'winminheight' to zero to avoid that the window is
+ * resized. */
+ if (lastwin->w_status_height == 0)
+ {
+ save_p_ls = p_ls;
+ save_p_wmh = p_wmh;
+ p_ls = 2;
+ p_wmh = 0;
+ last_status(FALSE);
+ }
+ wild_menu_showing = WM_SHOWN;
+ }
+ }
+
+ screen_puts(buf, row, 0, attr);
+ if (selstart != NULL && highlight)
+ {
+ *selend = NUL;
+ screen_puts(selstart, row, selstart_col, hl_attr(HLF_WM));
+ }
+
+ screen_fill(row, row + 1, clen, (int)Columns, fillchar, fillchar, attr);
+ }
+
+#ifdef FEAT_VERTSPLIT
+ win_redraw_last_status(topframe);
+#else
+ lastwin->w_redr_status = TRUE;
+#endif
+ vim_free(buf);
+}
+#endif
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * Redraw the status line of window wp.
+ *
+ * If inversion is possible we use it. Else '=' characters are used.
+ */
+ void
+win_redr_status(wp)
+ win_T *wp;
+{
+ int row;
+ char_u *p;
+ int len;
+ int fillchar;
+ int attr;
+ int this_ru_col;
+
+ wp->w_redr_status = FALSE;
+ if (wp->w_status_height == 0)
+ {
+ /* no status line, can only be last window */
+ redraw_cmdline = TRUE;
+ }
+ else if (!redrawing())
+ {
+ /* Don't redraw right now, do it later. */
+ wp->w_redr_status = TRUE;
+ }
+#ifdef FEAT_STL_OPT
+ else if (*p_stl)
+ {
+ /* redraw custom status line */
+ win_redr_custom(wp, FALSE);
+ }
+#endif
+ else
+ {
+ fillchar = fillchar_status(&attr, wp == curwin);
+
+ if (buf_spname(wp->w_buffer) != NULL)
+ STRCPY(NameBuff, buf_spname(wp->w_buffer));
+ else
+ home_replace(wp->w_buffer, wp->w_buffer->b_fname, NameBuff,
+ MAXPATHL, TRUE);
+ trans_characters(NameBuff, MAXPATHL);
+ p = NameBuff;
+ len = (int)STRLEN(p);
+
+ if (wp->w_buffer->b_help
+#ifdef FEAT_QUICKFIX
+ || wp->w_p_pvw
+#endif
+ || bufIsChanged(wp->w_buffer)
+ || wp->w_buffer->b_p_ro)
+ *(p + len++) = ' ';
+ if (wp->w_buffer->b_help)
+ {
+ STRCPY(p + len, _("[help]"));
+ len += (int)STRLEN(p + len);
+ }
+#ifdef FEAT_QUICKFIX
+ if (wp->w_p_pvw)
+ {
+ STRCPY(p + len, _("[Preview]"));
+ len += (int)STRLEN(p + len);
+ }
+#endif
+ if (bufIsChanged(wp->w_buffer))
+ {
+ STRCPY(p + len, "[+]");
+ len += 3;
+ }
+ if (wp->w_buffer->b_p_ro)
+ {
+ STRCPY(p + len, "[RO]");
+ len += 4;
+ }
+
+#ifndef FEAT_VERTSPLIT
+ this_ru_col = ru_col;
+ if (this_ru_col < (Columns + 1) / 2)
+ this_ru_col = (Columns + 1) / 2;
+#else
+ this_ru_col = ru_col - (Columns - W_WIDTH(wp));
+ if (this_ru_col < (W_WIDTH(wp) + 1) / 2)
+ this_ru_col = (W_WIDTH(wp) + 1) / 2;
+ if (this_ru_col <= 1)
+ {
+ p = (char_u *)"<"; /* No room for file name! */
+ len = 1;
+ }
+ else
+#endif
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int clen = 0, i;
+
+ /* Count total number of display cells. */
+ for (i = 0; p[i] != NUL; i += (*mb_ptr2len_check)(p + i))
+ clen += (*mb_ptr2cells)(p + i);
+ /* Find first character that will fit.
+ * Going from start to end is much faster for DBCS. */
+ for (i = 0; p[i] != NUL && clen >= this_ru_col - 1;
+ i += (*mb_ptr2len_check)(p + i))
+ clen -= (*mb_ptr2cells)(p + i);
+ len = clen;
+ if (i > 0)
+ {
+ p = p + i - 1;
+ *p = '<';
+ ++len;
+ }
+
+ }
+ else
+#endif
+ if (len > this_ru_col - 1)
+ {
+ p += len - (this_ru_col - 1);
+ *p = '<';
+ len = this_ru_col - 1;
+ }
+
+ row = W_WINROW(wp) + wp->w_height;
+ screen_puts(p, row, W_WINCOL(wp), attr);
+ screen_fill(row, row + 1, len + W_WINCOL(wp),
+ this_ru_col + W_WINCOL(wp), fillchar, fillchar, attr);
+
+ if (get_keymap_str(wp, NameBuff, MAXPATHL)
+ && (int)(this_ru_col - len) > (int)(STRLEN(NameBuff) + 1))
+ screen_puts(NameBuff, row, (int)(this_ru_col - STRLEN(NameBuff)
+ - 1 + W_WINCOL(wp)), attr);
+
+#ifdef FEAT_CMDL_INFO
+ win_redr_ruler(wp, TRUE);
+#endif
+ }
+
+#ifdef FEAT_VERTSPLIT
+ /*
+ * May need to draw the character below the vertical separator.
+ */
+ if (wp->w_vsep_width != 0 && wp->w_status_height != 0 && redrawing())
+ {
+ if (stl_connected(wp))
+ fillchar = fillchar_status(&attr, wp == curwin);
+ else
+ fillchar = fillchar_vsep(&attr);
+ screen_putchar(fillchar, W_WINROW(wp) + wp->w_height, W_ENDCOL(wp),
+ attr);
+ }
+#endif
+}
+
+# ifdef FEAT_VERTSPLIT
+/*
+ * Return TRUE if the status line of window "wp" is connected to the status
+ * line of the window right of it. If not, then it's a vertical separator.
+ * Only call if (wp->w_vsep_width != 0).
+ */
+ int
+stl_connected(wp)
+ win_T *wp;
+{
+ frame_T *fr;
+
+ fr = wp->w_frame;
+ while (fr->fr_parent != NULL)
+ {
+ if (fr->fr_parent->fr_layout == FR_COL)
+ {
+ if (fr->fr_next != NULL)
+ break;
+ }
+ else
+ {
+ if (fr->fr_next != NULL)
+ return TRUE;
+ }
+ fr = fr->fr_parent;
+ }
+ return FALSE;
+}
+# endif
+
+#endif /* FEAT_WINDOWS */
+
+#if defined(FEAT_WINDOWS) || defined(FEAT_STL_OPT) || defined(PROTO)
+/*
+ * Get the value to show for the language mappings, active 'keymap'.
+ */
+ int
+get_keymap_str(wp, buf, len)
+ win_T *wp;
+ char_u *buf; /* buffer for the result */
+ int len; /* length of buffer */
+{
+ char_u *p;
+
+ if (wp->w_buffer->b_p_iminsert != B_IMODE_LMAP)
+ return FALSE;
+
+ {
+#ifdef FEAT_EVAL
+ buf_T *old_curbuf = curbuf;
+ win_T *old_curwin = curwin;
+ char_u *s;
+
+ curbuf = wp->w_buffer;
+ curwin = wp;
+ STRCPY(buf, "b:keymap_name"); /* must be writable */
+ ++emsg_skip;
+ s = p = eval_to_string(buf, NULL);
+ --emsg_skip;
+ curbuf = old_curbuf;
+ curwin = old_curwin;
+ if (p == NULL || *p == NUL)
+#endif
+ {
+#ifdef FEAT_KEYMAP
+ if (wp->w_buffer->b_kmap_state & KEYMAP_LOADED)
+ p = wp->w_buffer->b_p_keymap;
+ else
+#endif
+ p = (char_u *)"lang";
+ }
+ if ((int)(STRLEN(p) + 3) < len)
+ sprintf((char *)buf, "<%s>", p);
+ else
+ buf[0] = NUL;
+#ifdef FEAT_EVAL
+ vim_free(s);
+#endif
+ }
+ return buf[0] != NUL;
+}
+#endif
+
+#if defined(FEAT_STL_OPT) || defined(PROTO)
+/*
+ * Redraw the status line or ruler of window wp.
+ */
+ static void
+win_redr_custom(wp, Ruler)
+ win_T *wp;
+ int Ruler;
+{
+ int attr;
+ int curattr;
+ int row;
+ int col = 0;
+ int maxwidth;
+ int width;
+ int n;
+ int len;
+ int fillchar;
+ char_u buf[MAXPATHL];
+ char_u *p;
+ struct stl_hlrec hl[STL_MAX_ITEM];
+
+ /* setup environment for the task at hand */
+ row = W_WINROW(wp) + wp->w_height;
+ fillchar = fillchar_status(&attr, wp == curwin);
+ maxwidth = W_WIDTH(wp);
+ p = p_stl;
+ if (Ruler)
+ {
+ p = p_ruf;
+ /* advance past any leading group spec - implicit in ru_col */
+ if (*p == '%')
+ {
+ if (*++p == '-')
+ p++;
+ if (atoi((char *) p))
+ while (VIM_ISDIGIT(*p))
+ p++;
+ if (*p++ != '(')
+ p = p_ruf;
+ }
+#ifdef FEAT_VERTSPLIT
+ col = ru_col - (Columns - W_WIDTH(wp));
+ if (col < (W_WIDTH(wp) + 1) / 2)
+ col = (W_WIDTH(wp) + 1) / 2;
+#else
+ col = ru_col;
+ if (col > (Columns + 1) / 2)
+ col = (Columns + 1) / 2;
+#endif
+ maxwidth = W_WIDTH(wp) - col;
+#ifdef FEAT_WINDOWS
+ if (!wp->w_status_height)
+#endif
+ {
+ row = Rows - 1;
+ --maxwidth; /* writing in last column may cause scrolling */
+ fillchar = ' ';
+ attr = 0;
+ }
+ }
+ if (maxwidth <= 0)
+ return;
+#ifdef FEAT_VERTSPLIT
+ col += W_WINCOL(wp);
+#endif
+
+ width = build_stl_str_hl(wp, buf, sizeof(buf), p, fillchar, maxwidth, hl);
+ len = STRLEN(buf);
+
+ while (width < maxwidth && len < sizeof(buf) - 1)
+ {
+#ifdef FEAT_MBYTE
+ len += (*mb_char2bytes)(fillchar, buf + len);
+#else
+ buf[len++] = fillchar;
+#endif
+ ++width;
+ }
+ buf[len] = NUL;
+
+ curattr = attr;
+ p = buf;
+ for (n = 0; hl[n].start != NULL; n++)
+ {
+ len = (int)(hl[n].start - p);
+ screen_puts_len(p, len, row, col, curattr);
+ col += vim_strnsize(p, len);
+ p = hl[n].start;
+
+ if (hl[n].userhl == 0)
+ curattr = attr;
+#ifdef FEAT_WINDOWS
+ else if (wp != curwin && wp->w_status_height != 0)
+ curattr = highlight_stlnc[hl[n].userhl - 1];
+#endif
+ else
+ curattr = highlight_user[hl[n].userhl - 1];
+ }
+ screen_puts(p, row, col, curattr);
+}
+
+#endif /* FEAT_STL_OPT */
+
+/*
+ * Output a single character directly to the screen and update ScreenLines.
+ */
+ void
+screen_putchar(c, row, col, attr)
+ int c;
+ int row, col;
+ int attr;
+{
+#ifdef FEAT_MBYTE
+ char_u buf[MB_MAXBYTES + 1];
+
+ buf[(*mb_char2bytes)(c, buf)] = NUL;
+#else
+ char_u buf[2];
+
+ buf[0] = c;
+ buf[1] = NUL;
+#endif
+ screen_puts(buf, row, col, attr);
+}
+
+/*
+ * Get a single character directly from ScreenLines into "bytes[]".
+ * Also return its attribute in *attrp;
+ */
+ void
+screen_getbytes(row, col, bytes, attrp)
+ int row, col;
+ char_u *bytes;
+ int *attrp;
+{
+ unsigned off;
+
+ /* safety check */
+ if (ScreenLines != NULL && row < screen_Rows && col < screen_Columns)
+ {
+ off = LineOffset[row] + col;
+ *attrp = ScreenAttrs[off];
+ bytes[0] = ScreenLines[off];
+ bytes[1] = NUL;
+
+#ifdef FEAT_MBYTE
+ if (enc_utf8 && ScreenLinesUC[off] != 0)
+ bytes[utfc_char2bytes(off, bytes)] = NUL;
+ else if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e)
+ {
+ bytes[0] = ScreenLines[off];
+ bytes[1] = ScreenLines2[off];
+ bytes[2] = NUL;
+ }
+ else if (enc_dbcs && MB_BYTE2LEN(bytes[0]) > 1)
+ {
+ bytes[1] = ScreenLines[off + 1];
+ bytes[2] = NUL;
+ }
+#endif
+ }
+}
+
+/*
+ * Put string '*text' on the screen at position 'row' and 'col', with
+ * attributes 'attr', and update ScreenLines[] and ScreenAttrs[].
+ * Note: only outputs within one row, message is truncated at screen boundary!
+ * Note: if ScreenLines[], row and/or col is invalid, nothing is done.
+ */
+ void
+screen_puts(text, row, col, attr)
+ char_u *text;
+ int row;
+ int col;
+ int attr;
+{
+ screen_puts_len(text, -1, row, col, attr);
+}
+
+/*
+ * Like screen_puts(), but output "text[len]". When "len" is -1 output up to
+ * a NUL.
+ */
+ void
+screen_puts_len(text, len, row, col, attr)
+ char_u *text;
+ int len;
+ int row;
+ int col;
+ int attr;
+{
+ unsigned off;
+ char_u *ptr = text;
+ int c;
+#ifdef FEAT_MBYTE
+ int mbyte_blen = 1;
+ int mbyte_cells = 1;
+ int u8c = 0;
+ int u8c_c1 = 0;
+ int u8c_c2 = 0;
+ int clear_next_cell = FALSE;
+# ifdef FEAT_ARABIC
+ int prev_c = 0; /* previous Arabic character */
+ int pc, nc, nc1, dummy;
+# endif
+#endif
+
+ if (ScreenLines == NULL || row >= screen_Rows) /* safety check */
+ return;
+
+ off = LineOffset[row] + col;
+ while (*ptr != NUL && col < screen_Columns
+ && (len < 0 || (int)(ptr - text) < len))
+ {
+ c = *ptr;
+#ifdef FEAT_MBYTE
+ /* check if this is the first byte of a multibyte */
+ if (has_mbyte)
+ {
+ if (enc_utf8 && len > 0)
+ mbyte_blen = utfc_ptr2len_check_len(ptr,
+ (int)((text + len) - ptr));
+ else
+ mbyte_blen = (*mb_ptr2len_check)(ptr);
+ if (enc_dbcs == DBCS_JPNU && c == 0x8e)
+ mbyte_cells = 1;
+ else if (enc_dbcs != 0)
+ mbyte_cells = mbyte_blen;
+ else /* enc_utf8 */
+ {
+ if (len >= 0)
+ u8c = utfc_ptr2char_len(ptr, &u8c_c1, &u8c_c2,
+ (int)((text + len) - ptr));
+ else
+ u8c = utfc_ptr2char(ptr, &u8c_c1, &u8c_c2);
+ mbyte_cells = utf_char2cells(u8c);
+ /* Non-BMP character: display as ? or fullwidth ?. */
+ if (u8c >= 0x10000)
+ {
+ u8c = (mbyte_cells == 2) ? 0xff1f : (int)'?';
+ if (attr == 0)
+ attr = hl_attr(HLF_8);
+ }
+# ifdef FEAT_ARABIC
+ if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c))
+ {
+ /* Do Arabic shaping. */
+ if (len >= 0 && (int)(ptr - text) + mbyte_blen >= len)
+ {
+ /* Past end of string to be displayed. */
+ nc = NUL;
+ nc1 = NUL;
+ }
+ else
+ nc = utfc_ptr2char(ptr + mbyte_blen, &nc1, &dummy);
+ pc = prev_c;
+ prev_c = u8c;
+ u8c = arabic_shape(u8c, &c, &u8c_c1, nc, nc1, pc);
+ }
+ else
+ prev_c = u8c;
+# endif
+ }
+ }
+#endif
+
+ if (ScreenLines[off] != c
+#ifdef FEAT_MBYTE
+ || (mbyte_cells == 2
+ && ScreenLines[off + 1] != (enc_dbcs ? ptr[1] : 0))
+ || (enc_dbcs == DBCS_JPNU
+ && c == 0x8e
+ && ScreenLines2[off] != ptr[1])
+ || (enc_utf8
+ && mbyte_blen > 1
+ && (ScreenLinesUC[off] != u8c
+ || ScreenLinesC1[off] != u8c_c1
+ || ScreenLinesC2[off] != u8c_c2))
+#endif
+ || ScreenAttrs[off] != attr
+ || exmode_active
+ )
+ {
+#if defined(FEAT_GUI) || defined(UNIX)
+ /* The bold trick makes a single row of pixels appear in the next
+ * character. When a bold character is removed, the next
+ * character should be redrawn too. This happens for our own GUI
+ * and for some xterms.
+ * Force the redraw by setting the attribute to a different value
+ * than "attr", the contents of ScreenLines[] may be needed by
+ * mb_off2cells() further on.
+ * Don't do this for the last drawn character, because the next
+ * character may not be redrawn. */
+ if (
+# ifdef FEAT_GUI
+ gui.in_use
+# endif
+# if defined(FEAT_GUI) && defined(UNIX)
+ ||
+# endif
+# ifdef UNIX
+ term_is_xterm
+# endif
+ )
+ {
+ int n;
+
+ n = ScreenAttrs[off];
+# ifdef FEAT_MBYTE
+ if (col + mbyte_cells < screen_Columns
+ && (n > HL_ALL || (n & HL_BOLD))
+ && (len < 0 ? ptr[mbyte_blen] != NUL
+ : ptr + mbyte_blen < text + len))
+ ScreenAttrs[off + mbyte_cells] = attr + 1;
+# else
+ if (col + 1 < screen_Columns
+ && (n > HL_ALL || (n & HL_BOLD))
+ && (len < 0 ? ptr[1] != NUL : ptr + 1 < text + len))
+ ScreenLines[off + 1] = 0;
+# endif
+ }
+#endif
+#ifdef FEAT_MBYTE
+ /* When at the end of the text and overwriting a two-cell
+ * character with a one-cell character, need to clear the next
+ * cell. Also when overwriting the left halve of a two-cell char
+ * with the right halve of a two-cell char. Do this only once
+ * (mb_off2cells() may return 2 on the right halve). */
+ if (clear_next_cell)
+ clear_next_cell = FALSE;
+ else if (has_mbyte
+ && (len < 0 ? ptr[mbyte_blen] == NUL
+ : ptr + mbyte_blen >= text + len)
+ && ((mbyte_cells == 1 && (*mb_off2cells)(off) > 1)
+ || (mbyte_cells == 2
+ && (*mb_off2cells)(off) == 1
+ && (*mb_off2cells)(off + 1) > 1)))
+ clear_next_cell = TRUE;
+
+ /* Make sure we never leave a second byte of a double-byte behind,
+ * it confuses mb_off2cells(). */
+ if (enc_dbcs
+ && ((mbyte_cells == 1 && (*mb_off2cells)(off) > 1)
+ || (mbyte_cells == 2
+ && (*mb_off2cells)(off) == 1
+ && (*mb_off2cells)(off + 1) > 1)))
+ ScreenLines[off + mbyte_blen] = 0;
+#endif
+ ScreenLines[off] = c;
+ ScreenAttrs[off] = attr;
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ {
+ if (c < 0x80 && u8c_c1 == 0 && u8c_c2 == 0)
+ ScreenLinesUC[off] = 0;
+ else
+ {
+ ScreenLinesUC[off] = u8c;
+ ScreenLinesC1[off] = u8c_c1;
+ ScreenLinesC2[off] = u8c_c2;
+ }
+ if (mbyte_cells == 2)
+ {
+ ScreenLines[off + 1] = 0;
+ ScreenAttrs[off + 1] = attr;
+ }
+ screen_char(off, row, col);
+ }
+ else if (mbyte_cells == 2)
+ {
+ ScreenLines[off + 1] = ptr[1];
+ ScreenAttrs[off + 1] = attr;
+ screen_char_2(off, row, col);
+ }
+ else if (enc_dbcs == DBCS_JPNU && c == 0x8e)
+ {
+ ScreenLines2[off] = ptr[1];
+ screen_char(off, row, col);
+ }
+ else
+#endif
+ screen_char(off, row, col);
+ }
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ off += mbyte_cells;
+ col += mbyte_cells;
+ ptr += mbyte_blen;
+ if (clear_next_cell)
+ ptr = (char_u *)" ";
+ }
+ else
+#endif
+ {
+ ++off;
+ ++col;
+ ++ptr;
+ }
+ }
+}
+
+#ifdef FEAT_SEARCH_EXTRA
+/*
+ * Prepare for 'searchhl' highlighting.
+ */
+ static void
+start_search_hl()
+{
+ if (p_hls && !no_hlsearch)
+ {
+ last_pat_prog(&search_hl.rm);
+ search_hl.attr = hl_attr(HLF_L);
+ }
+}
+
+/*
+ * Clean up for 'searchhl' highlighting.
+ */
+ static void
+end_search_hl()
+{
+ if (search_hl.rm.regprog != NULL)
+ {
+ vim_free(search_hl.rm.regprog);
+ search_hl.rm.regprog = NULL;
+ }
+}
+
+/*
+ * Advance to the match in window "wp" line "lnum" or past it.
+ */
+ static void
+prepare_search_hl(wp, lnum)
+ win_T *wp;
+ linenr_T lnum;
+{
+ match_T *shl; /* points to search_hl or match_hl */
+ int n;
+
+ /*
+ * When using a multi-line pattern, start searching at the top
+ * of the window or just after a closed fold.
+ * Do this both for search_hl and match_hl.
+ */
+ shl = &search_hl;
+ for (;;)
+ {
+ if (shl->rm.regprog != NULL
+ && shl->lnum == 0
+ && re_multiline(shl->rm.regprog))
+ {
+ if (shl->first_lnum == 0)
+ {
+# ifdef FEAT_FOLDING
+ for (shl->first_lnum = lnum;
+ shl->first_lnum > wp->w_topline; --shl->first_lnum)
+ if (hasFoldingWin(wp, shl->first_lnum - 1,
+ NULL, NULL, TRUE, NULL))
+ break;
+# else
+ shl->first_lnum = wp->w_topline;
+# endif
+ }
+ n = 0;
+ while (shl->first_lnum < lnum && shl->rm.regprog != NULL)
+ {
+ next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n);
+ if (shl->lnum != 0)
+ {
+ shl->first_lnum = shl->lnum
+ + shl->rm.endpos[0].lnum
+ - shl->rm.startpos[0].lnum;
+ n = shl->rm.endpos[0].col;
+ }
+ else
+ {
+ ++shl->first_lnum;
+ n = 0;
+ }
+ }
+ }
+ if (shl == &match_hl)
+ break;
+ shl = &match_hl;
+ }
+}
+
+/*
+ * Search for a next 'searchl' or ":match" match.
+ * Uses shl->buf.
+ * Sets shl->lnum and shl->rm contents.
+ * Note: Assumes a previous match is always before "lnum", unless
+ * shl->lnum is zero.
+ * Careful: Any pointers for buffer lines will become invalid.
+ */
+ static void
+next_search_hl(win, shl, lnum, mincol)
+ win_T *win;
+ match_T *shl; /* points to search_hl or match_hl */
+ linenr_T lnum;
+ colnr_T mincol; /* minimal column for a match */
+{
+ linenr_T l;
+ colnr_T matchcol;
+ long nmatched;
+
+ if (shl->lnum != 0)
+ {
+ /* Check for three situations:
+ * 1. If the "lnum" is below a previous match, start a new search.
+ * 2. If the previous match includes "mincol", use it.
+ * 3. Continue after the previous match.
+ */
+ l = shl->lnum + shl->rm.endpos[0].lnum - shl->rm.startpos[0].lnum;
+ if (lnum > l)
+ shl->lnum = 0;
+ else if (lnum < l || shl->rm.endpos[0].col > mincol)
+ return;
+ }
+
+ /*
+ * Repeat searching for a match until one is found that includes "mincol"
+ * or none is found in this line.
+ */
+ called_emsg = FALSE;
+ for (;;)
+ {
+ /* Three situations:
+ * 1. No useful previous match: search from start of line.
+ * 2. Not Vi compatible or empty match: continue at next character.
+ * Break the loop if this is beyond the end of the line.
+ * 3. Vi compatible searching: continue at end of previous match.
+ */
+ if (shl->lnum == 0)
+ matchcol = 0;
+ else if (vim_strchr(p_cpo, CPO_SEARCH) == NULL
+ || (shl->rm.endpos[0].lnum == 0
+ && shl->rm.endpos[0].col == shl->rm.startpos[0].col))
+ {
+ matchcol = shl->rm.startpos[0].col + 1;
+ if (ml_get_buf(shl->buf, lnum, FALSE)[matchcol - 1] == NUL)
+ {
+ shl->lnum = 0;
+ break;
+ }
+ }
+ else
+ matchcol = shl->rm.endpos[0].col;
+
+ shl->lnum = lnum;
+ nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol);
+ if (called_emsg)
+ {
+ /* Error while handling regexp: stop using this regexp. */
+ vim_free(shl->rm.regprog);
+ shl->rm.regprog = NULL;
+ no_hlsearch = TRUE;
+ break;
+ }
+ if (nmatched == 0)
+ {
+ shl->lnum = 0; /* no match found */
+ break;
+ }
+ if (shl->rm.startpos[0].lnum > 0
+ || shl->rm.startpos[0].col >= mincol
+ || nmatched > 1
+ || shl->rm.endpos[0].col > mincol)
+ {
+ shl->lnum += shl->rm.startpos[0].lnum;
+ break; /* useful match found */
+ }
+ }
+}
+#endif
+
+ static void
+screen_start_highlight(attr)
+ int attr;
+{
+ attrentry_T *aep = NULL;
+
+ screen_attr = attr;
+ if (full_screen
+#ifdef WIN3264
+ && termcap_active
+#endif
+ )
+ {
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ char buf[20];
+
+ sprintf(buf, IF_EB("\033|%dh", ESC_STR "|%dh"), attr); /* internal GUI code */
+ OUT_STR(buf);
+ }
+ else
+#endif
+ {
+ if (attr > HL_ALL) /* special HL attr. */
+ {
+ if (t_colors > 1)
+ aep = syn_cterm_attr2entry(attr);
+ else
+ aep = syn_term_attr2entry(attr);
+ if (aep == NULL) /* did ":syntax clear" */
+ attr = 0;
+ else
+ attr = aep->ae_attr;
+ }
+ if ((attr & HL_BOLD) && T_MD != NULL) /* bold */
+ out_str(T_MD);
+ if ((attr & HL_STANDOUT) && T_SO != NULL) /* standout */
+ out_str(T_SO);
+ if ((attr & HL_UNDERLINE) && T_US != NULL) /* underline */
+ out_str(T_US);
+ if ((attr & HL_ITALIC) && T_CZH != NULL) /* italic */
+ out_str(T_CZH);
+ if ((attr & HL_INVERSE) && T_MR != NULL) /* inverse (reverse) */
+ out_str(T_MR);
+
+ /*
+ * Output the color or start string after bold etc., in case the
+ * bold etc. override the color setting.
+ */
+ if (aep != NULL)
+ {
+ if (t_colors > 1)
+ {
+ if (aep->ae_u.cterm.fg_color)
+ term_fg_color(aep->ae_u.cterm.fg_color - 1);
+ if (aep->ae_u.cterm.bg_color)
+ term_bg_color(aep->ae_u.cterm.bg_color - 1);
+ }
+ else
+ {
+ if (aep->ae_u.term.start != NULL)
+ out_str(aep->ae_u.term.start);
+ }
+ }
+ }
+ }
+}
+
+ void
+screen_stop_highlight()
+{
+ int do_ME = FALSE; /* output T_ME code */
+
+ if (screen_attr != 0
+#ifdef WIN3264
+ && termcap_active
+#endif
+ )
+ {
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ char buf[20];
+
+ /* use internal GUI code */
+ sprintf(buf, IF_EB("\033|%dH", ESC_STR "|%dH"), screen_attr);
+ OUT_STR(buf);
+ }
+ else
+#endif
+ {
+ if (screen_attr > HL_ALL) /* special HL attr. */
+ {
+ attrentry_T *aep;
+
+ if (t_colors > 1)
+ {
+ /*
+ * Assume that t_me restores the original colors!
+ */
+ aep = syn_cterm_attr2entry(screen_attr);
+ if (aep != NULL && (aep->ae_u.cterm.fg_color
+ || aep->ae_u.cterm.bg_color))
+ do_ME = TRUE;
+ }
+ else
+ {
+ aep = syn_term_attr2entry(screen_attr);
+ if (aep != NULL && aep->ae_u.term.stop != NULL)
+ {
+ if (STRCMP(aep->ae_u.term.stop, T_ME) == 0)
+ do_ME = TRUE;
+ else
+ out_str(aep->ae_u.term.stop);
+ }
+ }
+ if (aep == NULL) /* did ":syntax clear" */
+ screen_attr = 0;
+ else
+ screen_attr = aep->ae_attr;
+ }
+
+ /*
+ * Often all ending-codes are equal to T_ME. Avoid outputting the
+ * same sequence several times.
+ */
+ if (screen_attr & HL_STANDOUT)
+ {
+ if (STRCMP(T_SE, T_ME) == 0)
+ do_ME = TRUE;
+ else
+ out_str(T_SE);
+ }
+ if (screen_attr & HL_UNDERLINE)
+ {
+ if (STRCMP(T_UE, T_ME) == 0)
+ do_ME = TRUE;
+ else
+ out_str(T_UE);
+ }
+ if (screen_attr & HL_ITALIC)
+ {
+ if (STRCMP(T_CZR, T_ME) == 0)
+ do_ME = TRUE;
+ else
+ out_str(T_CZR);
+ }
+ if (do_ME || (screen_attr & (HL_BOLD | HL_INVERSE)))
+ out_str(T_ME);
+
+ if (t_colors > 1)
+ {
+ /* set Normal cterm colors */
+ if (cterm_normal_fg_color != 0)
+ term_fg_color(cterm_normal_fg_color - 1);
+ if (cterm_normal_bg_color != 0)
+ term_bg_color(cterm_normal_bg_color - 1);
+ if (cterm_normal_fg_bold)
+ out_str(T_MD);
+ }
+ }
+ }
+ screen_attr = 0;
+}
+
+/*
+ * Reset the colors for a cterm. Used when leaving Vim.
+ * The machine specific code may override this again.
+ */
+ void
+reset_cterm_colors()
+{
+ if (t_colors > 1)
+ {
+ /* set Normal cterm colors */
+ if (cterm_normal_fg_color > 0 || cterm_normal_bg_color > 0)
+ {
+ out_str(T_OP);
+ screen_attr = -1;
+ }
+ if (cterm_normal_fg_bold)
+ {
+ out_str(T_ME);
+ screen_attr = -1;
+ }
+ }
+}
+
+/*
+ * Put character ScreenLines["off"] on the screen at position "row" and "col",
+ * using the attributes from ScreenAttrs["off"].
+ */
+ static void
+screen_char(off, row, col)
+ unsigned off;
+ int row;
+ int col;
+{
+ int attr;
+
+ /* Check for illegal values, just in case (could happen just after
+ * resizing). */
+ if (row >= screen_Rows || col >= screen_Columns)
+ return;
+
+ /* Outputting the last character on the screen may scrollup the screen.
+ * Don't to it! Mark the character invalid (update it when scrolled up) */
+ if (row == screen_Rows - 1 && col == screen_Columns - 1
+#ifdef FEAT_RIGHTLEFT
+ /* account for first command-line character in rightleft mode */
+ && !cmdmsg_rl
+#endif
+ )
+ {
+ ScreenAttrs[off] = (sattr_T)-1;
+ return;
+ }
+
+ /*
+ * Stop highlighting first, so it's easier to move the cursor.
+ */
+#if defined(FEAT_CLIPBOARD) || defined(FEAT_VERTSPLIT)
+ if (screen_char_attr != 0)
+ attr = screen_char_attr;
+ else
+#endif
+ attr = ScreenAttrs[off];
+ if (screen_attr != attr)
+ screen_stop_highlight();
+
+ windgoto(row, col);
+
+ if (screen_attr != attr)
+ screen_start_highlight(attr);
+
+#ifdef FEAT_MBYTE
+ if (enc_utf8 && ScreenLinesUC[off] != 0)
+ {
+ char_u buf[MB_MAXBYTES + 1];
+
+ /* Convert UTF-8 character to bytes and write it. */
+
+ buf[utfc_char2bytes(off, buf)] = NUL;
+
+ out_str(buf);
+ if (utf_char2cells(ScreenLinesUC[off]) > 1)
+ ++screen_cur_col;
+ }
+ else
+#endif
+ {
+#ifdef FEAT_MBYTE
+ out_flush_check();
+#endif
+ out_char(ScreenLines[off]);
+#ifdef FEAT_MBYTE
+ /* double-byte character in single-width cell */
+ if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e)
+ out_char(ScreenLines2[off]);
+#endif
+ }
+
+ screen_cur_col++;
+}
+
+#ifdef FEAT_MBYTE
+
+/*
+ * Used for enc_dbcs only: Put one double-wide character at ScreenLines["off"]
+ * on the screen at position 'row' and 'col'.
+ * The attributes of the first byte is used for all. This is required to
+ * output the two bytes of a double-byte character with nothing in between.
+ */
+ static void
+screen_char_2(off, row, col)
+ unsigned off;
+ int row;
+ int col;
+{
+ /* Check for illegal values (could be wrong when screen was resized). */
+ if (off + 1 >= (unsigned)(screen_Rows * screen_Columns))
+ return;
+
+ /* Outputting the last character on the screen may scrollup the screen.
+ * Don't to it! Mark the character invalid (update it when scrolled up) */
+ if (row == screen_Rows - 1 && col >= screen_Columns - 2)
+ {
+ ScreenAttrs[off] = (sattr_T)-1;
+ return;
+ }
+
+ /* Output the first byte normally (positions the cursor), then write the
+ * second byte directly. */
+ screen_char(off, row, col);
+ out_char(ScreenLines[off + 1]);
+ ++screen_cur_col;
+}
+#endif
+
+#if defined(FEAT_CLIPBOARD) || defined(FEAT_VERTSPLIT) || defined(PROTO)
+/*
+ * Draw a rectangle of the screen, inverted when "invert" is TRUE.
+ * This uses the contents of ScreenLines[] and doesn't change it.
+ */
+ void
+screen_draw_rectangle(row, col, height, width, invert)
+ int row;
+ int col;
+ int height;
+ int width;
+ int invert;
+{
+ int r, c;
+ int off;
+
+ if (invert)
+ screen_char_attr = HL_INVERSE;
+ for (r = row; r < row + height; ++r)
+ {
+ off = LineOffset[r];
+ for (c = col; c < col + width; ++c)
+ {
+#ifdef FEAT_MBYTE
+ if (enc_dbcs != 0 && dbcs_off2cells(off + c) > 1)
+ {
+ screen_char_2(off + c, r, c);
+ ++c;
+ }
+ else
+#endif
+ {
+ screen_char(off + c, r, c);
+#ifdef FEAT_MBYTE
+ if (utf_off2cells(off + c) > 1)
+ ++c;
+#endif
+ }
+ }
+ }
+ screen_char_attr = 0;
+}
+#endif
+
+#ifdef FEAT_VERTSPLIT
+/*
+ * Redraw the characters for a vertically split window.
+ */
+ static void
+redraw_block(row, end, wp)
+ int row;
+ int end;
+ win_T *wp;
+{
+ int col;
+ int width;
+
+# ifdef FEAT_CLIPBOARD
+ clip_may_clear_selection(row, end - 1);
+# endif
+
+ if (wp == NULL)
+ {
+ col = 0;
+ width = Columns;
+ }
+ else
+ {
+ col = wp->w_wincol;
+ width = wp->w_width;
+ }
+ screen_draw_rectangle(row, col, end - row, width, FALSE);
+}
+#endif
+
+/*
+ * Fill the screen from 'start_row' to 'end_row', from 'start_col' to 'end_col'
+ * with character 'c1' in first column followed by 'c2' in the other columns.
+ * Use attributes 'attr'.
+ */
+ void
+screen_fill(start_row, end_row, start_col, end_col, c1, c2, attr)
+ int start_row, end_row;
+ int start_col, end_col;
+ int c1, c2;
+ int attr;
+{
+ int row;
+ int col;
+ int off;
+ int end_off;
+ int did_delete;
+ int c;
+ int norm_term;
+#if defined(FEAT_GUI) || defined(UNIX)
+ int force_next = FALSE;
+#endif
+
+ if (end_row > screen_Rows) /* safety check */
+ end_row = screen_Rows;
+ if (end_col > screen_Columns) /* safety check */
+ end_col = screen_Columns;
+ if (ScreenLines == NULL
+ || start_row >= end_row
+ || start_col >= end_col) /* nothing to do */
+ return;
+
+ /* it's a "normal" terminal when not in a GUI or cterm */
+ norm_term = (
+#ifdef FEAT_GUI
+ !gui.in_use &&
+#endif
+ t_colors <= 1);
+ for (row = start_row; row < end_row; ++row)
+ {
+ /*
+ * Try to use delete-line termcap code, when no attributes or in a
+ * "normal" terminal, where a bold/italic space is just a
+ * space.
+ */
+ did_delete = FALSE;
+ if (c2 == ' '
+ && end_col == Columns
+ && can_clear(T_CE)
+ && (attr == 0
+ || (norm_term
+ && attr <= HL_ALL
+ && ((attr & ~(HL_BOLD | HL_ITALIC)) == 0))))
+ {
+ /*
+ * check if we really need to clear something
+ */
+ col = start_col;
+ if (c1 != ' ') /* don't clear first char */
+ ++col;
+
+ off = LineOffset[row] + col;
+ end_off = LineOffset[row] + end_col;
+
+ /* skip blanks (used often, keep it fast!) */
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ while (off < end_off && ScreenLines[off] == ' '
+ && ScreenAttrs[off] == 0 && ScreenLinesUC[off] == 0)
+ ++off;
+ else
+#endif
+ while (off < end_off && ScreenLines[off] == ' '
+ && ScreenAttrs[off] == 0)
+ ++off;
+ if (off < end_off) /* something to be cleared */
+ {
+ col = off - LineOffset[row];
+ screen_stop_highlight();
+ term_windgoto(row, col);/* clear rest of this screen line */
+ out_str(T_CE);
+ screen_start(); /* don't know where cursor is now */
+ col = end_col - col;
+ while (col--) /* clear chars in ScreenLines */
+ {
+ ScreenLines[off] = ' ';
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ ScreenLinesUC[off] = 0;
+#endif
+ ScreenAttrs[off] = 0;
+ ++off;
+ }
+ }
+ did_delete = TRUE; /* the chars are cleared now */
+ }
+
+ off = LineOffset[row] + start_col;
+ c = c1;
+ for (col = start_col; col < end_col; ++col)
+ {
+ if (ScreenLines[off] != c
+#ifdef FEAT_MBYTE
+ || (enc_utf8 && ScreenLinesUC[off] != (c >= 0x80 ? c : 0))
+#endif
+ || ScreenAttrs[off] != attr
+#if defined(FEAT_GUI) || defined(UNIX)
+ || force_next
+#endif
+ )
+ {
+#if defined(FEAT_GUI) || defined(UNIX)
+ /* The bold trick may make a single row of pixels appear in
+ * the next character. When a bold character is removed, the
+ * next character should be redrawn too. This happens for our
+ * own GUI and for some xterms. */
+ if (
+# ifdef FEAT_GUI
+ gui.in_use
+# endif
+# if defined(FEAT_GUI) && defined(UNIX)
+ ||
+# endif
+# ifdef UNIX
+ term_is_xterm
+# endif
+ )
+ {
+ if (ScreenLines[off] != ' '
+ && (ScreenAttrs[off] > HL_ALL
+ || ScreenAttrs[off] & HL_BOLD))
+ force_next = TRUE;
+ else
+ force_next = FALSE;
+ }
+#endif
+ ScreenLines[off] = c;
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ {
+ if (c >= 0x80)
+ {
+ ScreenLinesUC[off] = c;
+ ScreenLinesC1[off] = 0;
+ ScreenLinesC2[off] = 0;
+ }
+ else
+ ScreenLinesUC[off] = 0;
+ }
+#endif
+ ScreenAttrs[off] = attr;
+ if (!did_delete || c != ' ')
+ screen_char(off, row, col);
+ }
+ ++off;
+ if (col == start_col)
+ {
+ if (did_delete)
+ break;
+ c = c2;
+ }
+ }
+ if (end_col == Columns)
+ LineWraps[row] = FALSE;
+ if (row == Rows - 1) /* overwritten the command line */
+ {
+ redraw_cmdline = TRUE;
+ if (c1 == ' ' && c2 == ' ')
+ clear_cmdline = FALSE; /* command line has been cleared */
+ }
+ }
+}
+
+/*
+ * Check if there should be a delay. Used before clearing or redrawing the
+ * screen or the command line.
+ */
+ void
+check_for_delay(check_msg_scroll)
+ int check_msg_scroll;
+{
+ if ((emsg_on_display || (check_msg_scroll && msg_scroll))
+ && !did_wait_return
+ && emsg_silent == 0)
+ {
+ out_flush();
+ ui_delay(1000L, TRUE);
+ emsg_on_display = FALSE;
+ if (check_msg_scroll)
+ msg_scroll = FALSE;
+ }
+}
+
+/*
+ * screen_valid - allocate screen buffers if size changed
+ * If "clear" is TRUE: clear screen if it has been resized.
+ * Returns TRUE if there is a valid screen to write to.
+ * Returns FALSE when starting up and screen not initialized yet.
+ */
+ int
+screen_valid(clear)
+ int clear;
+{
+ screenalloc(clear); /* allocate screen buffers if size changed */
+ return (ScreenLines != NULL);
+}
+
+/*
+ * Resize the shell to Rows and Columns.
+ * Allocate ScreenLines[] and associated items.
+ *
+ * There may be some time between setting Rows and Columns and (re)allocating
+ * ScreenLines[]. This happens when starting up and when (manually) changing
+ * the shell size. Always use screen_Rows and screen_Columns to access items
+ * in ScreenLines[]. Use Rows and Columns for positioning text etc. where the
+ * final size of the shell is needed.
+ */
+ void
+screenalloc(clear)
+ int clear;
+{
+ int new_row, old_row;
+#ifdef FEAT_GUI
+ int old_Rows;
+#endif
+ win_T *wp;
+ int outofmem = FALSE;
+ int len;
+ schar_T *new_ScreenLines;
+#ifdef FEAT_MBYTE
+ u8char_T *new_ScreenLinesUC = NULL;
+ u8char_T *new_ScreenLinesC1 = NULL;
+ u8char_T *new_ScreenLinesC2 = NULL;
+ schar_T *new_ScreenLines2 = NULL;
+#endif
+ sattr_T *new_ScreenAttrs;
+ unsigned *new_LineOffset;
+ char_u *new_LineWraps;
+ static int entered = FALSE; /* avoid recursiveness */
+
+ /*
+ * Allocation of the screen buffers is done only when the size changes and
+ * when Rows and Columns have been set and we have started doing full
+ * screen stuff.
+ */
+ if ((ScreenLines != NULL
+ && Rows == screen_Rows
+ && Columns == screen_Columns
+#ifdef FEAT_MBYTE
+ && enc_utf8 == (ScreenLinesUC != NULL)
+ && (enc_dbcs == DBCS_JPNU) == (ScreenLines2 != NULL)
+#endif
+ )
+ || Rows == 0
+ || Columns == 0
+ || (!full_screen && ScreenLines == NULL))
+ return;
+
+ /*
+ * It's possible that we produce an out-of-memory message below, which
+ * will cause this function to be called again. To break the loop, just
+ * return here.
+ */
+ if (entered)
+ return;
+ entered = TRUE;
+
+ win_new_shellsize(); /* fit the windows in the new sized shell */
+
+#ifdef FEAT_GUI_BEOS
+ vim_lock_screen(); /* be safe, put it here */
+#endif
+
+ comp_col(); /* recompute columns for shown command and ruler */
+
+ /*
+ * We're changing the size of the screen.
+ * - Allocate new arrays for ScreenLines and ScreenAttrs.
+ * - Move lines from the old arrays into the new arrays, clear extra
+ * lines (unless the screen is going to be cleared).
+ * - Free the old arrays.
+ *
+ * If anything fails, make ScreenLines NULL, so we don't do anything!
+ * Continuing with the old ScreenLines may result in a crash, because the
+ * size is wrong.
+ */
+#ifdef FEAT_WINDOWS
+ for (wp = firstwin; wp; wp = wp->w_next)
+ win_free_lsize(wp);
+#else
+ win_free_lsize(curwin);
+#endif
+
+ new_ScreenLines = (schar_T *)lalloc((long_u)(
+ (Rows + 1) * Columns * sizeof(schar_T)), FALSE);
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ {
+ new_ScreenLinesUC = (u8char_T *)lalloc((long_u)(
+ (Rows + 1) * Columns * sizeof(u8char_T)), FALSE);
+ new_ScreenLinesC1 = (u8char_T *)lalloc((long_u)(
+ (Rows + 1) * Columns * sizeof(u8char_T)), FALSE);
+ new_ScreenLinesC2 = (u8char_T *)lalloc((long_u)(
+ (Rows + 1) * Columns * sizeof(u8char_T)), FALSE);
+ }
+ if (enc_dbcs == DBCS_JPNU)
+ new_ScreenLines2 = (schar_T *)lalloc((long_u)(
+ (Rows + 1) * Columns * sizeof(schar_T)), FALSE);
+#endif
+ new_ScreenAttrs = (sattr_T *)lalloc((long_u)(
+ (Rows + 1) * Columns * sizeof(sattr_T)), FALSE);
+ new_LineOffset = (unsigned *)lalloc((long_u)(
+ Rows * sizeof(unsigned)), FALSE);
+ new_LineWraps = (char_u *)lalloc((long_u)(Rows * sizeof(char_u)), FALSE);
+
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (win_alloc_lines(wp) == FAIL)
+ {
+ outofmem = TRUE;
+#ifdef FEAT_WINDOWS
+ break;
+#endif
+ }
+ }
+
+ if (new_ScreenLines == NULL
+#ifdef FEAT_MBYTE
+ || (enc_utf8 && (new_ScreenLinesUC == NULL
+ || new_ScreenLinesC1 == NULL || new_ScreenLinesC2 == NULL))
+ || (enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL)
+#endif
+ || new_ScreenAttrs == NULL
+ || new_LineOffset == NULL
+ || new_LineWraps == NULL
+ || outofmem)
+ {
+ do_outofmem_msg((long_u)((Rows + 1) * Columns)); /* guess the size */
+ vim_free(new_ScreenLines);
+ new_ScreenLines = NULL;
+#ifdef FEAT_MBYTE
+ vim_free(new_ScreenLinesUC);
+ new_ScreenLinesUC = NULL;
+ vim_free(new_ScreenLinesC1);
+ new_ScreenLinesC1 = NULL;
+ vim_free(new_ScreenLinesC2);
+ new_ScreenLinesC2 = NULL;
+ vim_free(new_ScreenLines2);
+ new_ScreenLines2 = NULL;
+#endif
+ vim_free(new_ScreenAttrs);
+ new_ScreenAttrs = NULL;
+ vim_free(new_LineOffset);
+ new_LineOffset = NULL;
+ vim_free(new_LineWraps);
+ new_LineWraps = NULL;
+ }
+ else
+ {
+ for (new_row = 0; new_row < Rows; ++new_row)
+ {
+ new_LineOffset[new_row] = new_row * Columns;
+ new_LineWraps[new_row] = FALSE;
+
+ /*
+ * If the screen is not going to be cleared, copy as much as
+ * possible from the old screen to the new one and clear the rest
+ * (used when resizing the window at the "--more--" prompt or when
+ * executing an external command, for the GUI).
+ */
+ if (!clear)
+ {
+ (void)vim_memset(new_ScreenLines + new_row * Columns,
+ ' ', (size_t)Columns * sizeof(schar_T));
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ {
+ (void)vim_memset(new_ScreenLinesUC + new_row * Columns,
+ 0, (size_t)Columns * sizeof(u8char_T));
+ (void)vim_memset(new_ScreenLinesC1 + new_row * Columns,
+ 0, (size_t)Columns * sizeof(u8char_T));
+ (void)vim_memset(new_ScreenLinesC2 + new_row * Columns,
+ 0, (size_t)Columns * sizeof(u8char_T));
+ }
+ if (enc_dbcs == DBCS_JPNU)
+ (void)vim_memset(new_ScreenLines2 + new_row * Columns,
+ 0, (size_t)Columns * sizeof(schar_T));
+#endif
+ (void)vim_memset(new_ScreenAttrs + new_row * Columns,
+ 0, (size_t)Columns * sizeof(sattr_T));
+ old_row = new_row + (screen_Rows - Rows);
+ if (old_row >= 0)
+ {
+ if (screen_Columns < Columns)
+ len = screen_Columns;
+ else
+ len = Columns;
+ mch_memmove(new_ScreenLines + new_LineOffset[new_row],
+ ScreenLines + LineOffset[old_row],
+ (size_t)len * sizeof(schar_T));
+#ifdef FEAT_MBYTE
+ if (enc_utf8 && ScreenLinesUC != NULL)
+ {
+ mch_memmove(new_ScreenLinesUC + new_LineOffset[new_row],
+ ScreenLinesUC + LineOffset[old_row],
+ (size_t)len * sizeof(u8char_T));
+ mch_memmove(new_ScreenLinesC1 + new_LineOffset[new_row],
+ ScreenLinesC1 + LineOffset[old_row],
+ (size_t)len * sizeof(u8char_T));
+ mch_memmove(new_ScreenLinesC2 + new_LineOffset[new_row],
+ ScreenLinesC2 + LineOffset[old_row],
+ (size_t)len * sizeof(u8char_T));
+ }
+ if (enc_dbcs == DBCS_JPNU && ScreenLines2 != NULL)
+ mch_memmove(new_ScreenLines2 + new_LineOffset[new_row],
+ ScreenLines2 + LineOffset[old_row],
+ (size_t)len * sizeof(schar_T));
+#endif
+ mch_memmove(new_ScreenAttrs + new_LineOffset[new_row],
+ ScreenAttrs + LineOffset[old_row],
+ (size_t)len * sizeof(sattr_T));
+ }
+ }
+ }
+ /* Use the last line of the screen for the current line. */
+ current_ScreenLine = new_ScreenLines + Rows * Columns;
+ }
+
+ vim_free(ScreenLines);
+#ifdef FEAT_MBYTE
+ vim_free(ScreenLinesUC);
+ vim_free(ScreenLinesC1);
+ vim_free(ScreenLinesC2);
+ vim_free(ScreenLines2);
+#endif
+ vim_free(ScreenAttrs);
+ vim_free(LineOffset);
+ vim_free(LineWraps);
+ ScreenLines = new_ScreenLines;
+#ifdef FEAT_MBYTE
+ ScreenLinesUC = new_ScreenLinesUC;
+ ScreenLinesC1 = new_ScreenLinesC1;
+ ScreenLinesC2 = new_ScreenLinesC2;
+ ScreenLines2 = new_ScreenLines2;
+#endif
+ ScreenAttrs = new_ScreenAttrs;
+ LineOffset = new_LineOffset;
+ LineWraps = new_LineWraps;
+
+ /* It's important that screen_Rows and screen_Columns reflect the actual
+ * size of ScreenLines[]. Set them before calling anything. */
+#ifdef FEAT_GUI
+ old_Rows = screen_Rows;
+#endif
+ screen_Rows = Rows;
+ screen_Columns = Columns;
+
+ must_redraw = CLEAR; /* need to clear the screen later */
+ if (clear)
+ screenclear2();
+
+#ifdef FEAT_GUI
+ else if (gui.in_use
+ && !gui.starting
+ && ScreenLines != NULL
+ && old_Rows != Rows)
+ {
+ (void)gui_redraw_block(0, 0, (int)Rows - 1, (int)Columns - 1, 0);
+ /*
+ * Adjust the position of the cursor, for when executing an external
+ * command.
+ */
+ if (msg_row >= Rows) /* Rows got smaller */
+ msg_row = Rows - 1; /* put cursor at last row */
+ else if (Rows > old_Rows) /* Rows got bigger */
+ msg_row += Rows - old_Rows; /* put cursor in same place */
+ if (msg_col >= Columns) /* Columns got smaller */
+ msg_col = Columns - 1; /* put cursor at last column */
+ }
+#endif
+
+#ifdef FEAT_GUI_BEOS
+ vim_unlock_screen();
+#endif
+ entered = FALSE;
+}
+
+ void
+screenclear()
+{
+ check_for_delay(FALSE);
+ screenalloc(FALSE); /* allocate screen buffers if size changed */
+ screenclear2(); /* clear the screen */
+}
+
+ static void
+screenclear2()
+{
+ int i;
+
+ if (starting == NO_SCREEN || ScreenLines == NULL
+#ifdef FEAT_GUI
+ || (gui.in_use && gui.starting)
+#endif
+ )
+ return;
+
+#ifdef FEAT_GUI
+ if (!gui.in_use)
+#endif
+ screen_attr = -1; /* force setting the Normal colors */
+ screen_stop_highlight(); /* don't want highlighting here */
+
+#ifdef FEAT_CLIPBOARD
+ /* disable selection without redrawing it */
+ clip_scroll_selection(9999);
+#endif
+
+ /* blank out ScreenLines */
+ for (i = 0; i < Rows; ++i)
+ {
+ lineclear(LineOffset[i], (int)Columns);
+ LineWraps[i] = FALSE;
+ }
+
+ if (can_clear(T_CL))
+ {
+ out_str(T_CL); /* clear the display */
+ clear_cmdline = FALSE;
+ }
+ else
+ {
+ /* can't clear the screen, mark all chars with invalid attributes */
+ for (i = 0; i < Rows; ++i)
+ lineinvalid(LineOffset[i], (int)Columns);
+ clear_cmdline = TRUE;
+ }
+
+ screen_cleared = TRUE; /* can use contents of ScreenLines now */
+
+ win_rest_invalid(firstwin);
+ redraw_cmdline = TRUE;
+ if (must_redraw == CLEAR) /* no need to clear again */
+ must_redraw = NOT_VALID;
+ compute_cmdrow();
+ msg_row = cmdline_row; /* put cursor on last line for messages */
+ msg_col = 0;
+ screen_start(); /* don't know where cursor is now */
+ msg_scrolled = 0; /* can't scroll back */
+ msg_didany = FALSE;
+ msg_didout = FALSE;
+}
+
+/*
+ * Clear one line in ScreenLines.
+ */
+ static void
+lineclear(off, width)
+ unsigned off;
+ int width;
+{
+ (void)vim_memset(ScreenLines + off, ' ', (size_t)width * sizeof(schar_T));
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ (void)vim_memset(ScreenLinesUC + off, 0,
+ (size_t)width * sizeof(u8char_T));
+#endif
+ (void)vim_memset(ScreenAttrs + off, 0, (size_t)width * sizeof(sattr_T));
+}
+
+/*
+ * Mark one line in ScreenLines invalid by setting the attributes to an
+ * invalid value.
+ */
+ static void
+lineinvalid(off, width)
+ unsigned off;
+ int width;
+{
+ (void)vim_memset(ScreenAttrs + off, -1, (size_t)width * sizeof(sattr_T));
+}
+
+#ifdef FEAT_VERTSPLIT
+/*
+ * Copy part of a Screenline for vertically split window "wp".
+ */
+ static void
+linecopy(to, from, wp)
+ int to;
+ int from;
+ win_T *wp;
+{
+ unsigned off_to = LineOffset[to] + wp->w_wincol;
+ unsigned off_from = LineOffset[from] + wp->w_wincol;
+
+ mch_memmove(ScreenLines + off_to, ScreenLines + off_from,
+ wp->w_width * sizeof(schar_T));
+# ifdef FEAT_MBYTE
+ if (enc_utf8)
+ {
+ mch_memmove(ScreenLinesUC + off_to, ScreenLinesUC + off_from,
+ wp->w_width * sizeof(u8char_T));
+ mch_memmove(ScreenLinesC1 + off_to, ScreenLinesC1 + off_from,
+ wp->w_width * sizeof(u8char_T));
+ mch_memmove(ScreenLinesC2 + off_to, ScreenLinesC2 + off_from,
+ wp->w_width * sizeof(u8char_T));
+ }
+ if (enc_dbcs == DBCS_JPNU)
+ mch_memmove(ScreenLines2 + off_to, ScreenLines2 + off_from,
+ wp->w_width * sizeof(schar_T));
+# endif
+ mch_memmove(ScreenAttrs + off_to, ScreenAttrs + off_from,
+ wp->w_width * sizeof(sattr_T));
+}
+#endif
+
+/*
+ * Return TRUE if clearing with term string "p" would work.
+ * It can't work when the string is empty or it won't set the right background.
+ */
+ int
+can_clear(p)
+ char_u *p;
+{
+ return (*p != NUL && (t_colors <= 1
+#ifdef FEAT_GUI
+ || gui.in_use
+#endif
+ || cterm_normal_bg_color == 0 || *T_UT != NUL));
+}
+
+/*
+ * Reset cursor position. Use whenever cursor was moved because of outputting
+ * something directly to the screen (shell commands) or a terminal control
+ * code.
+ */
+ void
+screen_start()
+{
+ screen_cur_row = screen_cur_col = 9999;
+}
+
+/*
+ * Note that the cursor has gone down to the next line, column 0.
+ * Used for Ex mode.
+ */
+ void
+screen_down()
+{
+ screen_cur_col = 0;
+ if (screen_cur_row < Rows - 1)
+ ++screen_cur_row;
+}
+
+/*
+ * Move the cursor to position "row","col" in the screen.
+ * This tries to find the most efficient way to move, minimizing the number of
+ * characters sent to the terminal.
+ */
+ void
+windgoto(row, col)
+ int row;
+ int col;
+{
+ char_u *p;
+ int i;
+ int plan;
+ int cost;
+ int wouldbe_col;
+ int noinvcurs;
+ char_u *bs;
+ int goto_cost;
+ int attr;
+
+#define GOTO_COST 7 /* asssume a term_windgoto() takes about 7 chars */
+#define HIGHL_COST 5 /* assume unhighlight takes 5 chars */
+
+#define PLAN_LE 1
+#define PLAN_CR 2
+#define PLAN_NL 3
+#define PLAN_WRITE 4
+ /* Can't use ScreenLines unless initialized */
+ if (ScreenLines == NULL)
+ return;
+
+ if (col != screen_cur_col || row != screen_cur_row)
+ {
+ /* Check for valid position. */
+ if (row < 0) /* window without text lines? */
+ row = 0;
+ if (row >= screen_Rows)
+ row = screen_Rows - 1;
+ if (col >= screen_Columns)
+ col = screen_Columns - 1;
+
+ /* check if no cursor movement is allowed in highlight mode */
+ if (screen_attr && *T_MS == NUL)
+ noinvcurs = HIGHL_COST;
+ else
+ noinvcurs = 0;
+ goto_cost = GOTO_COST + noinvcurs;
+
+ /*
+ * Plan how to do the positioning:
+ * 1. Use CR to move it to column 0, same row.
+ * 2. Use T_LE to move it a few columns to the left.
+ * 3. Use NL to move a few lines down, column 0.
+ * 4. Move a few columns to the right with T_ND or by writing chars.
+ *
+ * Don't do this if the cursor went beyond the last column, the cursor
+ * position is unknown then (some terminals wrap, some don't )
+ *
+ * First check if the highlighting attibutes allow us to write
+ * characters to move the cursor to the right.
+ */
+ if (row >= screen_cur_row && screen_cur_col < Columns)
+ {
+ /*
+ * If the cursor is in the same row, bigger col, we can use CR
+ * or T_LE.
+ */
+ bs = NULL; /* init for GCC */
+ attr = screen_attr;
+ if (row == screen_cur_row && col < screen_cur_col)
+ {
+ /* "le" is preferred over "bc", because "bc" is obsolete */
+ if (*T_LE)
+ bs = T_LE; /* "cursor left" */
+ else
+ bs = T_BC; /* "backspace character (old) */
+ if (*bs)
+ cost = (screen_cur_col - col) * (int)STRLEN(bs);
+ else
+ cost = 999;
+ if (col + 1 < cost) /* using CR is less characters */
+ {
+ plan = PLAN_CR;
+ wouldbe_col = 0;
+ cost = 1; /* CR is just one character */
+ }
+ else
+ {
+ plan = PLAN_LE;
+ wouldbe_col = col;
+ }
+ if (noinvcurs) /* will stop highlighting */
+ {
+ cost += noinvcurs;
+ attr = 0;
+ }
+ }
+
+ /*
+ * If the cursor is above where we want to be, we can use CR LF.
+ */
+ else if (row > screen_cur_row)
+ {
+ plan = PLAN_NL;
+ wouldbe_col = 0;
+ cost = (row - screen_cur_row) * 2; /* CR LF */
+ if (noinvcurs) /* will stop highlighting */
+ {
+ cost += noinvcurs;
+ attr = 0;
+ }
+ }
+
+ /*
+ * If the cursor is in the same row, smaller col, just use write.
+ */
+ else
+ {
+ plan = PLAN_WRITE;
+ wouldbe_col = screen_cur_col;
+ cost = 0;
+ }
+
+ /*
+ * Check if any characters that need to be written have the
+ * correct attributes. Also avoid UTF-8 characters.
+ */
+ i = col - wouldbe_col;
+ if (i > 0)
+ cost += i;
+ if (cost < goto_cost && i > 0)
+ {
+ /*
+ * Check if the attributes are correct without additionally
+ * stopping highlighting.
+ */
+ p = ScreenAttrs + LineOffset[row] + wouldbe_col;
+ while (i && *p++ == attr)
+ --i;
+ if (i != 0)
+ {
+ /*
+ * Try if it works when highlighting is stopped here.
+ */
+ if (*--p == 0)
+ {
+ cost += noinvcurs;
+ while (i && *p++ == 0)
+ --i;
+ }
+ if (i != 0)
+ cost = 999; /* different attributes, don't do it */
+ }
+#ifdef FEAT_MBYTE
+ if (enc_utf8)
+ {
+ /* Don't use an UTF-8 char for positioning, it's slow. */
+ for (i = wouldbe_col; i < col; ++i)
+ if (ScreenLinesUC[LineOffset[row] + i] != 0)
+ {
+ cost = 999;
+ break;
+ }
+ }
+#endif
+ }
+
+ /*
+ * We can do it without term_windgoto()!
+ */
+ if (cost < goto_cost)
+ {
+ if (plan == PLAN_LE)
+ {
+ if (noinvcurs)
+ screen_stop_highlight();
+ while (screen_cur_col > col)
+ {
+ out_str(bs);
+ --screen_cur_col;
+ }
+ }
+ else if (plan == PLAN_CR)
+ {
+ if (noinvcurs)
+ screen_stop_highlight();
+ out_char('\r');
+ screen_cur_col = 0;
+ }
+ else if (plan == PLAN_NL)
+ {
+ if (noinvcurs)
+ screen_stop_highlight();
+ while (screen_cur_row < row)
+ {
+ out_char('\n');
+ ++screen_cur_row;
+ }
+ screen_cur_col = 0;
+ }
+
+ i = col - screen_cur_col;
+ if (i > 0)
+ {
+ /*
+ * Use cursor-right if it's one character only. Avoids
+ * removing a line of pixels from the last bold char, when
+ * using the bold trick in the GUI.
+ */
+ if (T_ND[0] != NUL && T_ND[1] == NUL)
+ {
+ while (i-- > 0)
+ out_char(*T_ND);
+ }
+ else
+ {
+ int off;
+
+ off = LineOffset[row] + screen_cur_col;
+ while (i-- > 0)
+ {
+ if (ScreenAttrs[off] != screen_attr)
+ screen_stop_highlight();
+#ifdef FEAT_MBYTE
+ out_flush_check();
+#endif
+ out_char(ScreenLines[off]);
+#ifdef FEAT_MBYTE
+ if (enc_dbcs == DBCS_JPNU
+ && ScreenLines[off] == 0x8e)
+ out_char(ScreenLines2[off]);
+#endif
+ ++off;
+ }
+ }
+ }
+ }
+ }
+ else
+ cost = 999;
+
+ if (cost >= goto_cost)
+ {
+ if (noinvcurs)
+ screen_stop_highlight();
+ if (row == screen_cur_row && (col > screen_cur_col) &&
+ *T_CRI != NUL)
+ term_cursor_right(col - screen_cur_col);
+ else
+ term_windgoto(row, col);
+ }
+ screen_cur_row = row;
+ screen_cur_col = col;
+ }
+}
+
+/*
+ * Set cursor to its position in the current window.
+ */
+ void
+setcursor()
+{
+ if (redrawing())
+ {
+ validate_cursor();
+ windgoto(W_WINROW(curwin) + curwin->w_wrow,
+ W_WINCOL(curwin) + (
+#ifdef FEAT_RIGHTLEFT
+ curwin->w_p_rl ? ((int)W_WIDTH(curwin) - curwin->w_wcol - (
+# ifdef FEAT_MBYTE
+ has_mbyte ? (*mb_ptr2cells)(ml_get_cursor()) :
+# endif
+ 1)) :
+#endif
+ curwin->w_wcol));
+ }
+}
+
+
+/*
+ * insert 'line_count' lines at 'row' in window 'wp'
+ * if 'invalid' is TRUE the wp->w_lines[].wl_lnum is invalidated.
+ * if 'mayclear' is TRUE the screen will be cleared if it is faster than
+ * scrolling.
+ * Returns FAIL if the lines are not inserted, OK for success.
+ */
+ int
+win_ins_lines(wp, row, line_count, invalid, mayclear)
+ win_T *wp;
+ int row;
+ int line_count;
+ int invalid;
+ int mayclear;
+{
+ int did_delete;
+ int nextrow;
+ int lastrow;
+ int retval;
+
+ if (invalid)
+ wp->w_lines_valid = 0;
+
+ if (wp->w_height < 5)
+ return FAIL;
+
+ if (line_count > wp->w_height - row)
+ line_count = wp->w_height - row;
+
+ retval = win_do_lines(wp, row, line_count, mayclear, FALSE);
+ if (retval != MAYBE)
+ return retval;
+
+ /*
+ * If there is a next window or a status line, we first try to delete the
+ * lines at the bottom to avoid messing what is after the window.
+ * If this fails and there are following windows, don't do anything to avoid
+ * messing up those windows, better just redraw.
+ */
+ did_delete = FALSE;
+#ifdef FEAT_WINDOWS
+ if (wp->w_next != NULL || wp->w_status_height)
+ {
+ if (screen_del_lines(0, W_WINROW(wp) + wp->w_height - line_count,
+ line_count, (int)Rows, FALSE, NULL) == OK)
+ did_delete = TRUE;
+ else if (wp->w_next)
+ return FAIL;
+ }
+#endif
+ /*
+ * if no lines deleted, blank the lines that will end up below the window
+ */
+ if (!did_delete)
+ {
+#ifdef FEAT_WINDOWS
+ wp->w_redr_status = TRUE;
+#endif
+ redraw_cmdline = TRUE;
+ nextrow = W_WINROW(wp) + wp->w_height + W_STATUS_HEIGHT(wp);
+ lastrow = nextrow + line_count;
+ if (lastrow > Rows)
+ lastrow = Rows;
+ screen_fill(nextrow - line_count, lastrow - line_count,
+ W_WINCOL(wp), (int)W_ENDCOL(wp),
+ ' ', ' ', 0);
+ }
+
+ if (screen_ins_lines(0, W_WINROW(wp) + row, line_count, (int)Rows, NULL)
+ == FAIL)
+ {
+ /* deletion will have messed up other windows */
+ if (did_delete)
+ {
+#ifdef FEAT_WINDOWS
+ wp->w_redr_status = TRUE;
+#endif
+ win_rest_invalid(W_NEXT(wp));
+ }
+ return FAIL;
+ }
+
+ return OK;
+}
+
+/*
+ * delete "line_count" window lines at "row" in window "wp"
+ * If "invalid" is TRUE curwin->w_lines[] is invalidated.
+ * If "mayclear" is TRUE the screen will be cleared if it is faster than
+ * scrolling
+ * Return OK for success, FAIL if the lines are not deleted.
+ */
+ int
+win_del_lines(wp, row, line_count, invalid, mayclear)
+ win_T *wp;
+ int row;
+ int line_count;
+ int invalid;
+ int mayclear;
+{
+ int retval;
+
+ if (invalid)
+ wp->w_lines_valid = 0;
+
+ if (line_count > wp->w_height - row)
+ line_count = wp->w_height - row;
+
+ retval = win_do_lines(wp, row, line_count, mayclear, TRUE);
+ if (retval != MAYBE)
+ return retval;
+
+ if (screen_del_lines(0, W_WINROW(wp) + row, line_count,
+ (int)Rows, FALSE, NULL) == FAIL)
+ return FAIL;
+
+#ifdef FEAT_WINDOWS
+ /*
+ * If there are windows or status lines below, try to put them at the
+ * correct place. If we can't do that, they have to be redrawn.
+ */
+ if (wp->w_next || wp->w_status_height || cmdline_row < Rows - 1)
+ {
+ if (screen_ins_lines(0, W_WINROW(wp) + wp->w_height - line_count,
+ line_count, (int)Rows, NULL) == FAIL)
+ {
+ wp->w_redr_status = TRUE;
+ win_rest_invalid(wp->w_next);
+ }
+ }
+ /*
+ * If this is the last window and there is no status line, redraw the
+ * command line later.
+ */
+ else
+#endif
+ redraw_cmdline = TRUE;
+ return OK;
+}
+
+/*
+ * Common code for win_ins_lines() and win_del_lines().
+ * Returns OK or FAIL when the work has been done.
+ * Returns MAYBE when not finished yet.
+ */
+ static int
+win_do_lines(wp, row, line_count, mayclear, del)
+ win_T *wp;
+ int row;
+ int line_count;
+ int mayclear;
+ int del;
+{
+ int retval;
+
+ if (!redrawing() || line_count <= 0)
+ return FAIL;
+
+ /* only a few lines left: redraw is faster */
+ if (mayclear && Rows - line_count < 5
+#ifdef FEAT_VERTSPLIT
+ && wp->w_width == Columns
+#endif
+ )
+ {
+ screenclear(); /* will set wp->w_lines_valid to 0 */
+ return FAIL;
+ }
+
+ /*
+ * Delete all remaining lines
+ */
+ if (row + line_count >= wp->w_height)
+ {
+ screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + wp->w_height,
+ W_WINCOL(wp), (int)W_ENDCOL(wp),
+ ' ', ' ', 0);
+ return OK;
+ }
+
+ /*
+ * when scrolling, the message on the command line should be cleared,
+ * otherwise it will stay there forever.
+ */
+ clear_cmdline = TRUE;
+
+ /*
+ * If the terminal can set a scroll region, use that.
+ * Always do this in a vertically split window. This will redraw from
+ * ScreenLines[] when t_CV isn't defined. That's faster than using
+ * win_line().
+ * Don't use a scroll region when we are going to redraw the text, writing
+ * a character in the lower right corner of the scroll region causes a
+ * scroll-up in the DJGPP version.
+ */
+ if (scroll_region
+#ifdef FEAT_VERTSPLIT
+ || W_WIDTH(wp) != Columns
+#endif
+ )
+ {
+#ifdef FEAT_VERTSPLIT
+ if (scroll_region && (wp->w_width == Columns || *T_CSV != NUL))
+#endif
+ scroll_region_set(wp, row);
+ if (del)
+ retval = screen_del_lines(W_WINROW(wp) + row, 0, line_count,
+ wp->w_height - row, FALSE, wp);
+ else
+ retval = screen_ins_lines(W_WINROW(wp) + row, 0, line_count,
+ wp->w_height - row, wp);
+#ifdef FEAT_VERTSPLIT
+ if (scroll_region && (wp->w_width == Columns || *T_CSV != NUL))
+#endif
+ scroll_region_reset();
+ return retval;
+ }
+
+#ifdef FEAT_WINDOWS
+ if (wp->w_next != NULL && p_tf) /* don't delete/insert on fast terminal */
+ return FAIL;
+#endif
+
+ return MAYBE;
+}
+
+/*
+ * window 'wp' and everything after it is messed up, mark it for redraw
+ */
+ static void
+win_rest_invalid(wp)
+ win_T *wp;
+{
+#ifdef FEAT_WINDOWS
+ while (wp != NULL)
+#else
+ if (wp != NULL)
+#endif
+ {
+ redraw_win_later(wp, NOT_VALID);
+#ifdef FEAT_WINDOWS
+ wp->w_redr_status = TRUE;
+ wp = wp->w_next;
+#endif
+ }
+ redraw_cmdline = TRUE;
+}
+
+/*
+ * The rest of the routines in this file perform screen manipulations. The
+ * given operation is performed physically on the screen. The corresponding
+ * change is also made to the internal screen image. In this way, the editor
+ * anticipates the effect of editing changes on the appearance of the screen.
+ * That way, when we call screenupdate a complete redraw isn't usually
+ * necessary. Another advantage is that we can keep adding code to anticipate
+ * screen changes, and in the meantime, everything still works.
+ */
+
+/*
+ * types for inserting or deleting lines
+ */
+#define USE_T_CAL 1
+#define USE_T_CDL 2
+#define USE_T_AL 3
+#define USE_T_CE 4
+#define USE_T_DL 5
+#define USE_T_SR 6
+#define USE_NL 7
+#define USE_T_CD 8
+#define USE_REDRAW 9
+
+/*
+ * insert lines on the screen and update ScreenLines[]
+ * 'end' is the line after the scrolled part. Normally it is Rows.
+ * When scrolling region used 'off' is the offset from the top for the region.
+ * 'row' and 'end' are relative to the start of the region.
+ *
+ * return FAIL for failure, OK for success.
+ */
+ static int
+screen_ins_lines(off, row, line_count, end, wp)
+ int off;
+ int row;
+ int line_count;
+ int end;
+ win_T *wp; /* NULL or window to use width from */
+{
+ int i;
+ int j;
+ unsigned temp;
+ int cursor_row;
+ int type;
+ int result_empty;
+ int can_ce = can_clear(T_CE);
+
+ /*
+ * FAIL if
+ * - there is no valid screen
+ * - the screen has to be redrawn completely
+ * - the line count is less than one
+ * - the line count is more than 'ttyscroll'
+ */
+ if (!screen_valid(TRUE) || line_count <= 0 || line_count > p_ttyscroll)
+ return FAIL;
+
+ /*
+ * There are seven ways to insert lines:
+ * 0. When in a vertically split window and t_CV isn't set, redraw the
+ * characters from ScreenLines[].
+ * 1. Use T_CD (clear to end of display) if it exists and the result of
+ * the insert is just empty lines
+ * 2. Use T_CAL (insert multiple lines) if it exists and T_AL is not
+ * present or line_count > 1. It looks better if we do all the inserts
+ * at once.
+ * 3. Use T_CDL (delete multiple lines) if it exists and the result of the
+ * insert is just empty lines and T_CE is not present or line_count >
+ * 1.
+ * 4. Use T_AL (insert line) if it exists.
+ * 5. Use T_CE (erase line) if it exists and the result of the insert is
+ * just empty lines.
+ * 6. Use T_DL (delete line) if it exists and the result of the insert is
+ * just empty lines.
+ * 7. Use T_SR (scroll reverse) if it exists and inserting at row 0 and
+ * the 'da' flag is not set or we have clear line capability.
+ * 8. redraw the characters from ScreenLines[].
+ *
+ * Careful: In a hpterm scroll reverse doesn't work as expected, it moves
+ * the scrollbar for the window. It does have insert line, use that if it
+ * exists.
+ */
+ result_empty = (row + line_count >= end);
+#ifdef FEAT_VERTSPLIT
+ if (wp != NULL && wp->w_width != Columns && *T_CSV == NUL)
+ type = USE_REDRAW;
+ else
+#endif
+ if (can_clear(T_CD) && result_empty)
+ type = USE_T_CD;
+ else if (*T_CAL != NUL && (line_count > 1 || *T_AL == NUL))
+ type = USE_T_CAL;
+ else if (*T_CDL != NUL && result_empty && (line_count > 1 || !can_ce))
+ type = USE_T_CDL;
+ else if (*T_AL != NUL)
+ type = USE_T_AL;
+ else if (can_ce && result_empty)
+ type = USE_T_CE;
+ else if (*T_DL != NUL && result_empty)
+ type = USE_T_DL;
+ else if (*T_SR != NUL && row == 0 && (*T_DA == NUL || can_ce))
+ type = USE_T_SR;
+ else
+ return FAIL;
+
+ /*
+ * For clearing the lines screen_del_lines() is used. This will also take
+ * care of t_db if necessary.
+ */
+ if (type == USE_T_CD || type == USE_T_CDL ||
+ type == USE_T_CE || type == USE_T_DL)
+ return screen_del_lines(off, row, line_count, end, FALSE, wp);
+
+ /*
+ * If text is retained below the screen, first clear or delete as many
+ * lines at the bottom of the window as are about to be inserted so that
+ * the deleted lines won't later surface during a screen_del_lines.
+ */
+ if (*T_DB)
+ screen_del_lines(off, end - line_count, line_count, end, FALSE, wp);
+
+#ifdef FEAT_CLIPBOARD
+ /* Remove a modeless selection when inserting lines halfway the screen
+ * or not the full width of the screen. */
+ if (off + row > 0
+# ifdef FEAT_VERTSPLIT
+ || (wp != NULL && wp->w_width != Columns)
+# endif
+ )
+ clip_clear_selection();
+ else
+ clip_scroll_selection(-line_count);
+#endif
+
+#ifdef FEAT_GUI_BEOS
+ vim_lock_screen();
+#endif
+#ifdef FEAT_GUI
+ /* Don't update the GUI cursor here, ScreenLines[] is invalid until the
+ * scrolling is actually carried out. */
+ gui_dont_update_cursor();
+#endif
+
+ if (*T_CCS != NUL) /* cursor relative to region */
+ cursor_row = row;
+ else
+ cursor_row = row + off;
+
+ /*
+ * Shift LineOffset[] line_count down to reflect the inserted lines.
+ * Clear the inserted lines in ScreenLines[].
+ */
+ row += off;
+ end += off;
+ for (i = 0; i < line_count; ++i)
+ {
+#ifdef FEAT_VERTSPLIT
+ if (wp != NULL && wp->w_width != Columns)
+ {
+ /* need to copy part of a line */
+ j = end - 1 - i;
+ while ((j -= line_count) >= row)
+ linecopy(j + line_count, j, wp);
+ j += line_count;
+ if (can_clear((char_u *)" "))
+ lineclear(LineOffset[j] + wp->w_wincol, wp->w_width);
+ else
+ lineinvalid(LineOffset[j] + wp->w_wincol, wp->w_width);
+ LineWraps[j] = FALSE;
+ }
+ else
+#endif
+ {
+ j = end - 1 - i;
+ temp = LineOffset[j];
+ while ((j -= line_count) >= row)
+ {
+ LineOffset[j + line_count] = LineOffset[j];
+ LineWraps[j + line_count] = LineWraps[j];
+ }
+ LineOffset[j + line_count] = temp;
+ LineWraps[j + line_count] = FALSE;
+ if (can_clear((char_u *)" "))
+ lineclear(temp, (int)Columns);
+ else
+ lineinvalid(temp, (int)Columns);
+ }
+ }
+#ifdef FEAT_GUI_BEOS
+ vim_unlock_screen();
+#endif
+
+ screen_stop_highlight();
+ windgoto(cursor_row, 0);
+
+#ifdef FEAT_VERTSPLIT
+ /* redraw the characters */
+ if (type == USE_REDRAW)
+ redraw_block(row, end, wp);
+ else
+#endif
+ if (type == USE_T_CAL)
+ {
+ term_append_lines(line_count);
+ screen_start(); /* don't know where cursor is now */
+ }
+ else
+ {
+ for (i = 0; i < line_count; i++)
+ {
+ if (type == USE_T_AL)
+ {
+ if (i && cursor_row != 0)
+ windgoto(cursor_row, 0);
+ out_str(T_AL);
+ }
+ else /* type == USE_T_SR */
+ out_str(T_SR);
+ screen_start(); /* don't know where cursor is now */
+ }
+ }
+
+ /*
+ * With scroll-reverse and 'da' flag set we need to clear the lines that
+ * have been scrolled down into the region.
+ */
+ if (type == USE_T_SR && *T_DA)
+ {
+ for (i = 0; i < line_count; ++i)
+ {
+ windgoto(off + i, 0);
+ out_str(T_CE);
+ screen_start(); /* don't know where cursor is now */
+ }
+ }
+
+#ifdef FEAT_GUI
+ gui_can_update_cursor();
+ if (gui.in_use)
+ out_flush(); /* always flush after a scroll */
+#endif
+ return OK;
+}
+
+/*
+ * delete lines on the screen and update ScreenLines[]
+ * 'end' is the line after the scrolled part. Normally it is Rows.
+ * When scrolling region used 'off' is the offset from the top for the region.
+ * 'row' and 'end' are relative to the start of the region.
+ *
+ * Return OK for success, FAIL if the lines are not deleted.
+ */
+/*ARGSUSED*/
+ int
+screen_del_lines(off, row, line_count, end, force, wp)
+ int off;
+ int row;
+ int line_count;
+ int end;
+ int force; /* even when line_count > p_ttyscroll */
+ win_T *wp; /* NULL or window to use width from */
+{
+ int j;
+ int i;
+ unsigned temp;
+ int cursor_row;
+ int cursor_end;
+ int result_empty; /* result is empty until end of region */
+ int can_delete; /* deleting line codes can be used */
+ int type;
+
+ /*
+ * FAIL if
+ * - there is no valid screen
+ * - the screen has to be redrawn completely
+ * - the line count is less than one
+ * - the line count is more than 'ttyscroll'
+ */
+ if (!screen_valid(TRUE) || line_count <= 0 ||
+ (!force && line_count > p_ttyscroll))
+ return FAIL;
+
+ /*
+ * Check if the rest of the current region will become empty.
+ */
+ result_empty = row + line_count >= end;
+
+ /*
+ * We can delete lines only when 'db' flag not set or when 'ce' option
+ * available.
+ */
+ can_delete = (*T_DB == NUL || can_clear(T_CE));
+
+ /*
+ * There are six ways to delete lines:
+ * 0. When in a vertically split window and t_CV isn't set, redraw the
+ * characters from ScreenLines[].
+ * 1. Use T_CD if it exists and the result is empty.
+ * 2. Use newlines if row == 0 and count == 1 or T_CDL does not exist.
+ * 3. Use T_CDL (delete multiple lines) if it exists and line_count > 1 or
+ * none of the other ways work.
+ * 4. Use T_CE (erase line) if the result is empty.
+ * 5. Use T_DL (delete line) if it exists.
+ * 6. redraw the characters from ScreenLines[].
+ */
+#ifdef FEAT_VERTSPLIT
+ if (wp != NULL && wp->w_width != Columns && *T_CSV == NUL)
+ type = USE_REDRAW;
+ else
+#endif
+ if (can_clear(T_CD) && result_empty)
+ type = USE_T_CD;
+#if defined(__BEOS__) && defined(BEOS_DR8)
+ /*
+ * USE_NL does not seem to work in Terminal of DR8 so we set T_DB="" in
+ * its internal termcap... this works okay for tests which test *T_DB !=
+ * NUL. It has the disadvantage that the user cannot use any :set t_*
+ * command to get T_DB (back) to empty_option, only :set term=... will do
+ * the trick...
+ * Anyway, this hack will hopefully go away with the next OS release.
+ * (Olaf Seibert)
+ */
+ else if (row == 0 && T_DB == empty_option
+ && (line_count == 1 || *T_CDL == NUL))
+#else
+ else if (row == 0 && (
+#ifndef AMIGA
+ /* On the Amiga, somehow '\n' on the last line doesn't always scroll
+ * up, so use delete-line command */
+ line_count == 1 ||
+#endif
+ *T_CDL == NUL))
+#endif
+ type = USE_NL;
+ else if (*T_CDL != NUL && line_count > 1 && can_delete)
+ type = USE_T_CDL;
+ else if (can_clear(T_CE) && result_empty
+#ifdef FEAT_VERTSPLIT
+ && (wp == NULL || wp->w_width == Columns)
+#endif
+ )
+ type = USE_T_CE;
+ else if (*T_DL != NUL && can_delete)
+ type = USE_T_DL;
+ else if (*T_CDL != NUL && can_delete)
+ type = USE_T_CDL;
+ else
+ return FAIL;
+
+#ifdef FEAT_CLIPBOARD
+ /* Remove a modeless selection when deleting lines halfway the screen or
+ * not the full width of the screen. */
+ if (off + row > 0
+# ifdef FEAT_VERTSPLIT
+ || (wp != NULL && wp->w_width != Columns)
+# endif
+ )
+ clip_clear_selection();
+ else
+ clip_scroll_selection(line_count);
+#endif
+
+#ifdef FEAT_GUI_BEOS
+ vim_lock_screen();
+#endif
+#ifdef FEAT_GUI
+ /* Don't update the GUI cursor here, ScreenLines[] is invalid until the
+ * scrolling is actually carried out. */
+ gui_dont_update_cursor();
+#endif
+
+ if (*T_CCS != NUL) /* cursor relative to region */
+ {
+ cursor_row = row;
+ cursor_end = end;
+ }
+ else
+ {
+ cursor_row = row + off;
+ cursor_end = end + off;
+ }
+
+ /*
+ * Now shift LineOffset[] line_count up to reflect the deleted lines.
+ * Clear the inserted lines in ScreenLines[].
+ */
+ row += off;
+ end += off;
+ for (i = 0; i < line_count; ++i)
+ {
+#ifdef FEAT_VERTSPLIT
+ if (wp != NULL && wp->w_width != Columns)
+ {
+ /* need to copy part of a line */
+ j = row + i;
+ while ((j += line_count) <= end - 1)
+ linecopy(j - line_count, j, wp);
+ j -= line_count;
+ if (can_clear((char_u *)" "))
+ lineclear(LineOffset[j] + wp->w_wincol, wp->w_width);
+ else
+ lineinvalid(LineOffset[j] + wp->w_wincol, wp->w_width);
+ LineWraps[j] = FALSE;
+ }
+ else
+#endif
+ {
+ /* whole width, moving the line pointers is faster */
+ j = row + i;
+ temp = LineOffset[j];
+ while ((j += line_count) <= end - 1)
+ {
+ LineOffset[j - line_count] = LineOffset[j];
+ LineWraps[j - line_count] = LineWraps[j];
+ }
+ LineOffset[j - line_count] = temp;
+ LineWraps[j - line_count] = FALSE;
+ if (can_clear((char_u *)" "))
+ lineclear(temp, (int)Columns);
+ else
+ lineinvalid(temp, (int)Columns);
+ }
+ }
+#ifdef FEAT_GUI_BEOS
+ vim_unlock_screen();
+#endif
+
+ screen_stop_highlight();
+
+#ifdef FEAT_VERTSPLIT
+ /* redraw the characters */
+ if (type == USE_REDRAW)
+ redraw_block(row, end, wp);
+ else
+#endif
+ if (type == USE_T_CD) /* delete the lines */
+ {
+ windgoto(cursor_row, 0);
+ out_str(T_CD);
+ screen_start(); /* don't know where cursor is now */
+ }
+ else if (type == USE_T_CDL)
+ {
+ windgoto(cursor_row, 0);
+ term_delete_lines(line_count);
+ screen_start(); /* don't know where cursor is now */
+ }
+ /*
+ * Deleting lines at top of the screen or scroll region: Just scroll
+ * the whole screen (scroll region) up by outputting newlines on the
+ * last line.
+ */
+ else if (type == USE_NL)
+ {
+ windgoto(cursor_end - 1, 0);
+ for (i = line_count; --i >= 0; )
+ out_char('\n'); /* cursor will remain on same line */
+ }
+ else
+ {
+ for (i = line_count; --i >= 0; )
+ {
+ if (type == USE_T_DL)
+ {
+ windgoto(cursor_row, 0);
+ out_str(T_DL); /* delete a line */
+ }
+ else /* type == USE_T_CE */
+ {
+ windgoto(cursor_row + i, 0);
+ out_str(T_CE); /* erase a line */
+ }
+ screen_start(); /* don't know where cursor is now */
+ }
+ }
+
+ /*
+ * If the 'db' flag is set, we need to clear the lines that have been
+ * scrolled up at the bottom of the region.
+ */
+ if (*T_DB && (type == USE_T_DL || type == USE_T_CDL))
+ {
+ for (i = line_count; i > 0; --i)
+ {
+ windgoto(cursor_end - i, 0);
+ out_str(T_CE); /* erase a line */
+ screen_start(); /* don't know where cursor is now */
+ }
+ }
+
+#ifdef FEAT_GUI
+ gui_can_update_cursor();
+ if (gui.in_use)
+ out_flush(); /* always flush after a scroll */
+#endif
+
+ return OK;
+}
+
+/*
+ * show the current mode and ruler
+ *
+ * If clear_cmdline is TRUE, clear the rest of the cmdline.
+ * If clear_cmdline is FALSE there may be a message there that needs to be
+ * cleared only if a mode is shown.
+ * Return the length of the message (0 if no message).
+ */
+ int
+showmode()
+{
+ int need_clear;
+ int length = 0;
+ int do_mode;
+ int attr;
+ int nwr_save;
+#ifdef FEAT_INS_EXPAND
+ int sub_attr;
+#endif
+
+ do_mode = (p_smd && ((State & INSERT) || restart_edit
+#ifdef FEAT_VISUAL
+ || VIsual_active
+#endif
+ ));
+ if (do_mode || Recording)
+ {
+ /*
+ * Don't show mode right now, when not redrawing or inside a mapping.
+ * Call char_avail() only when we are going to show something, because
+ * it takes a bit of time.
+ */
+ if (!redrawing() || (char_avail() && !KeyTyped) || msg_silent != 0)
+ {
+ redraw_cmdline = TRUE; /* show mode later */
+ return 0;
+ }
+
+ nwr_save = need_wait_return;
+
+ /* wait a bit before overwriting an important message */
+ check_for_delay(FALSE);
+
+ /* if the cmdline is more than one line high, erase top lines */
+ need_clear = clear_cmdline;
+ if (clear_cmdline && cmdline_row < Rows - 1)
+ msg_clr_cmdline(); /* will reset clear_cmdline */
+
+ /* Position on the last line in the window, column 0 */
+ msg_pos_mode();
+ cursor_off();
+ attr = hl_attr(HLF_CM); /* Highlight mode */
+ if (do_mode)
+ {
+ MSG_PUTS_ATTR("--", attr);
+#if defined(FEAT_XIM)
+ if (xic != NULL && im_get_status() && !p_imdisable
+ && curbuf->b_p_iminsert == B_IMODE_IM)
+# ifdef HAVE_GTK2 /* most of the time, it's not XIM being used */
+ MSG_PUTS_ATTR(" IM", attr);
+# else
+ MSG_PUTS_ATTR(" XIM", attr);
+# endif
+#endif
+#if defined(FEAT_HANGULIN) && defined(FEAT_GUI)
+ if (gui.in_use)
+ {
+ if (hangul_input_state_get())
+ MSG_PUTS_ATTR(" ÇѱÛ", attr); /* HANGUL */
+ }
+#endif
+#ifdef FEAT_INS_EXPAND
+ if (edit_submode != NULL) /* CTRL-X in Insert mode */
+ {
+ /* These messages can get long, avoid a wrap in a narrow
+ * window. Prefer showing edit_submode_extra. */
+ length = (Rows - msg_row) * Columns - 3;
+ if (edit_submode_extra != NULL)
+ length -= vim_strsize(edit_submode_extra);
+ if (length > 0)
+ {
+ if (edit_submode_pre != NULL)
+ length -= vim_strsize(edit_submode_pre);
+ if (length - vim_strsize(edit_submode) > 0)
+ {
+ if (edit_submode_pre != NULL)
+ msg_puts_attr(edit_submode_pre, attr);
+ msg_puts_attr(edit_submode, attr);
+ }
+ if (edit_submode_extra != NULL)
+ {
+ MSG_PUTS_ATTR(" ", attr); /* add a space in between */
+ if ((int)edit_submode_highl < (int)HLF_COUNT)
+ sub_attr = hl_attr(edit_submode_highl);
+ else
+ sub_attr = attr;
+ msg_puts_attr(edit_submode_extra, sub_attr);
+ }
+ }
+ length = 0;
+ }
+ else
+#endif
+ {
+#ifdef FEAT_VREPLACE
+ if (State & VREPLACE_FLAG)
+ MSG_PUTS_ATTR(_(" VREPLACE"), attr);
+ else
+#endif
+ if (State & REPLACE_FLAG)
+ MSG_PUTS_ATTR(_(" REPLACE"), attr);
+ else if (State & INSERT)
+ {
+#ifdef FEAT_RIGHTLEFT
+ if (p_ri)
+ MSG_PUTS_ATTR(_(" REVERSE"), attr);
+#endif
+ MSG_PUTS_ATTR(_(" INSERT"), attr);
+ }
+ else if (restart_edit == 'I')
+ MSG_PUTS_ATTR(_(" (insert)"), attr);
+ else if (restart_edit == 'R')
+ MSG_PUTS_ATTR(_(" (replace)"), attr);
+ else if (restart_edit == 'V')
+ MSG_PUTS_ATTR(_(" (vreplace)"), attr);
+#ifdef FEAT_RIGHTLEFT
+ if (p_hkmap)
+ MSG_PUTS_ATTR(_(" Hebrew"), attr);
+# ifdef FEAT_FKMAP
+ if (p_fkmap)
+ MSG_PUTS_ATTR(farsi_text_5, attr);
+# endif
+#endif
+#ifdef FEAT_KEYMAP
+ if (State & LANGMAP)
+ {
+# ifdef FEAT_ARABIC
+ if (curwin->w_p_arab)
+ MSG_PUTS_ATTR(_(" Arabic"), attr);
+ else
+# endif
+ MSG_PUTS_ATTR(_(" (lang)"), attr);
+ }
+#endif
+ if ((State & INSERT) && p_paste)
+ MSG_PUTS_ATTR(_(" (paste)"), attr);
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ char *p;
+
+ /* Don't concatenate separate words to avoid translation
+ * problems. */
+ switch ((VIsual_select ? 4 : 0)
+ + (VIsual_mode == Ctrl_V) * 2
+ + (VIsual_mode == 'V'))
+ {
+ case 0: p = N_(" VISUAL"); break;
+ case 1: p = N_(" VISUAL LINE"); break;
+ case 2: p = N_(" VISUAL BLOCK"); break;
+ case 4: p = N_(" SELECT"); break;
+ case 5: p = N_(" SELECT LINE"); break;
+ default: p = N_(" SELECT BLOCK"); break;
+ }
+ MSG_PUTS_ATTR(_(p), attr);
+ }
+#endif
+ MSG_PUTS_ATTR(" --", attr);
+ }
+ need_clear = TRUE;
+ }
+ if (Recording
+#ifdef FEAT_INS_EXPAND
+ && edit_submode == NULL /* otherwise it gets too long */
+#endif
+ )
+ {
+ MSG_PUTS_ATTR(_("recording"), attr);
+ need_clear = TRUE;
+ }
+ if (need_clear || clear_cmdline)
+ msg_clr_eos();
+ msg_didout = FALSE; /* overwrite this message */
+ length = msg_col;
+ msg_col = 0;
+ need_wait_return = nwr_save; /* never ask for hit-return for this */
+ }
+ else if (clear_cmdline && msg_silent == 0)
+ /* Clear the whole command line. Will reset "clear_cmdline". */
+ msg_clr_cmdline();
+
+#ifdef FEAT_CMDL_INFO
+# ifdef FEAT_VISUAL
+ /* In Visual mode the size of the selected area must be redrawn. */
+ if (VIsual_active)
+ clear_showcmd();
+# endif
+
+ /* If the last window has no status line, the ruler is after the mode
+ * message and must be redrawn */
+ if (redrawing()
+# ifdef FEAT_WINDOWS
+ && lastwin->w_status_height == 0
+# endif
+ )
+ win_redr_ruler(lastwin, TRUE);
+#endif
+ redraw_cmdline = FALSE;
+ clear_cmdline = FALSE;
+
+ return length;
+}
+
+/*
+ * Position for a mode message.
+ */
+ static void
+msg_pos_mode()
+{
+ msg_col = 0;
+ msg_row = Rows - 1;
+}
+
+/*
+ * Delete mode message. Used when ESC is typed which is expected to end
+ * Insert mode (but Insert mode didn't end yet!).
+ */
+ void
+unshowmode(force)
+ int force;
+{
+ /*
+ * Don't delete it right now, when not redrawing or insided a mapping.
+ */
+ if (!redrawing() || (!force && char_avail() && !KeyTyped))
+ redraw_cmdline = TRUE; /* delete mode later */
+ else
+ {
+ msg_pos_mode();
+ if (Recording)
+ MSG_PUTS_ATTR(_("recording"), hl_attr(HLF_CM));
+ msg_clr_eos();
+ }
+}
+
+#if defined(FEAT_WINDOWS) || defined(FEAT_WILDMENU) || defined(FEAT_STL_OPT)
+/*
+ * Get the character to use in a status line. Get its attributes in "*attr".
+ */
+ static int
+fillchar_status(attr, is_curwin)
+ int *attr;
+ int is_curwin;
+{
+ int fill;
+ if (is_curwin)
+ {
+ *attr = hl_attr(HLF_S);
+ fill = fill_stl;
+ }
+ else
+ {
+ *attr = hl_attr(HLF_SNC);
+ fill = fill_stlnc;
+ }
+ /* Use fill when there is highlighting, and highlighting of current
+ * window differs, or the fillchars differ, or this is not the
+ * current window */
+ if (*attr != 0 && ((hl_attr(HLF_S) != hl_attr(HLF_SNC)
+ || !is_curwin || firstwin == lastwin)
+ || (fill_stl != fill_stlnc)))
+ return fill;
+ if (is_curwin)
+ return '^';
+ return '=';
+}
+#endif
+
+#ifdef FEAT_VERTSPLIT
+/*
+ * Get the character to use in a separator between vertically split windows.
+ * Get its attributes in "*attr".
+ */
+ static int
+fillchar_vsep(attr)
+ int *attr;
+{
+ *attr = hl_attr(HLF_C);
+ if (*attr == 0 && fill_vert == ' ')
+ return '|';
+ else
+ return fill_vert;
+}
+#endif
+
+/*
+ * Return TRUE if redrawing should currently be done.
+ */
+ int
+redrawing()
+{
+ return (!RedrawingDisabled
+ && !(p_lz && char_avail() && !KeyTyped && !do_redraw));
+}
+
+/*
+ * Return TRUE if printing messages should currently be done.
+ */
+ int
+messaging()
+{
+ return (!(p_lz && char_avail() && !KeyTyped));
+}
+
+/*
+ * Show current status info in ruler and various other places
+ * If always is FALSE, only show ruler if position has changed.
+ */
+ void
+showruler(always)
+ int always;
+{
+ if (!always && !redrawing())
+ return;
+#if defined(FEAT_STL_OPT) && defined(FEAT_WINDOWS)
+ if (*p_stl && curwin->w_status_height)
+ win_redr_custom(curwin, FALSE);
+ else
+#endif
+#ifdef FEAT_CMDL_INFO
+ win_redr_ruler(curwin, always);
+#endif
+
+#ifdef FEAT_TITLE
+ if (need_maketitle
+# ifdef FEAT_STL_OPT
+ || (p_icon && (stl_syntax & STL_IN_ICON))
+ || (p_title && (stl_syntax & STL_IN_TITLE))
+# endif
+ )
+ maketitle();
+#endif
+}
+
+#ifdef FEAT_CMDL_INFO
+ static void
+win_redr_ruler(wp, always)
+ win_T *wp;
+ int always;
+{
+ char_u buffer[70];
+ int row;
+ int fillchar;
+ int attr;
+ int empty_line = FALSE;
+ colnr_T virtcol;
+ int i;
+ int o;
+#ifdef FEAT_VERTSPLIT
+ int this_ru_col;
+ int off = 0;
+ int width = Columns;
+# define WITH_OFF(x) x
+# define WITH_WIDTH(x) x
+#else
+# define WITH_OFF(x) 0
+# define WITH_WIDTH(x) Columns
+# define this_ru_col ru_col
+#endif
+
+ /* If 'ruler' off or redrawing disabled, don't do anything */
+ if (!p_ru)
+ return;
+
+ /*
+ * Check if cursor.lnum is valid, since win_redr_ruler() may be called
+ * after deleting lines, before cursor.lnum is corrected.
+ */
+ if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count)
+ return;
+
+#ifdef FEAT_INS_EXPAND
+ /* Don't draw the ruler while doing insert-completion, it might overwrite
+ * the (long) mode message. */
+# ifdef FEAT_WINDOWS
+ if (wp == lastwin && lastwin->w_status_height == 0)
+# endif
+ if (edit_submode != NULL)
+ return;
+#endif
+
+#ifdef FEAT_STL_OPT
+ if (*p_ruf)
+ {
+ win_redr_custom(wp, TRUE);
+ return;
+ }
+#endif
+
+ /*
+ * Check if not in Insert mode and the line is empty (will show "0-1").
+ */
+ if (!(State & INSERT)
+ && *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum, FALSE) == NUL)
+ empty_line = TRUE;
+
+ /*
+ * Only draw the ruler when something changed.
+ */
+ validate_virtcol_win(wp);
+ if ( redraw_cmdline
+ || always
+ || wp->w_cursor.lnum != wp->w_ru_cursor.lnum
+ || wp->w_cursor.col != wp->w_ru_cursor.col
+ || wp->w_virtcol != wp->w_ru_virtcol
+#ifdef FEAT_VIRTUALEDIT
+ || wp->w_cursor.coladd != wp->w_ru_cursor.coladd
+#endif
+ || wp->w_topline != wp->w_ru_topline
+ || wp->w_buffer->b_ml.ml_line_count != wp->w_ru_line_count
+#ifdef FEAT_DIFF
+ || wp->w_topfill != wp->w_ru_topfill
+#endif
+ || empty_line != wp->w_ru_empty)
+ {
+ cursor_off();
+#ifdef FEAT_WINDOWS
+ if (wp->w_status_height)
+ {
+ row = W_WINROW(wp) + wp->w_height;
+ fillchar = fillchar_status(&attr, wp == curwin);
+# ifdef FEAT_VERTSPLIT
+ off = W_WINCOL(wp);
+ width = W_WIDTH(wp);
+# endif
+ }
+ else
+#endif
+ {
+ row = Rows - 1;
+ fillchar = ' ';
+ attr = 0;
+#ifdef FEAT_VERTSPLIT
+ width = Columns;
+ off = 0;
+#endif
+ }
+
+ /* In list mode virtcol needs to be recomputed */
+ virtcol = wp->w_virtcol;
+ if (wp->w_p_list && lcs_tab1 == NUL)
+ {
+ wp->w_p_list = FALSE;
+ getvvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL);
+ wp->w_p_list = TRUE;
+ }
+
+ /*
+ * Some sprintfs return the length, some return a pointer.
+ * To avoid portability problems we use strlen() here.
+ */
+ sprintf((char *)buffer, "%ld,",
+ (wp->w_buffer->b_ml.ml_flags & ML_EMPTY)
+ ? 0L
+ : (long)(wp->w_cursor.lnum));
+ col_print(buffer + STRLEN(buffer),
+ empty_line ? 0 : (int)wp->w_cursor.col + 1,
+ (int)virtcol + 1);
+
+ /*
+ * Add a "50%" if there is room for it.
+ * On the last line, don't print in the last column (scrolls the
+ * screen up on some terminals).
+ */
+ i = (int)STRLEN(buffer);
+ get_rel_pos(wp, buffer + i + 1);
+ o = i + vim_strsize(buffer + i + 1);
+#ifdef FEAT_WINDOWS
+ if (wp->w_status_height == 0) /* can't use last char of screen */
+#endif
+ ++o;
+#ifdef FEAT_VERTSPLIT
+ this_ru_col = ru_col - (Columns - width);
+ if (this_ru_col < 0)
+ this_ru_col = 0;
+#endif
+ /* Never use more than half the window/screen width, leave the other
+ * half for the filename. */
+ if (this_ru_col < (WITH_WIDTH(width) + 1) / 2)
+ this_ru_col = (WITH_WIDTH(width) + 1) / 2;
+ if (this_ru_col + o < WITH_WIDTH(width))
+ {
+ while (this_ru_col + o < WITH_WIDTH(width))
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ i += (*mb_char2bytes)(fillchar, buffer + i);
+ else
+#endif
+ buffer[i++] = fillchar;
+ ++o;
+ }
+ get_rel_pos(wp, buffer + i);
+ }
+ /* Truncate at window boundary. */
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ o = 0;
+ for (i = 0; buffer[i] != NUL; i += (*mb_ptr2len_check)(buffer + i))
+ {
+ o += (*mb_ptr2cells)(buffer + i);
+ if (this_ru_col + o > WITH_WIDTH(width))
+ {
+ buffer[i] = NUL;
+ break;
+ }
+ }
+ }
+ else
+#endif
+ if (this_ru_col + (int)STRLEN(buffer) > WITH_WIDTH(width))
+ buffer[WITH_WIDTH(width) - this_ru_col] = NUL;
+
+ screen_puts(buffer, row, this_ru_col + WITH_OFF(off), attr);
+ i = redraw_cmdline;
+ screen_fill(row, row + 1,
+ this_ru_col + WITH_OFF(off) + (int)STRLEN(buffer),
+ (int)(WITH_OFF(off) + WITH_WIDTH(width)),
+ fillchar, fillchar, attr);
+ /* don't redraw the cmdline because of showing the ruler */
+ redraw_cmdline = i;
+ wp->w_ru_cursor = wp->w_cursor;
+ wp->w_ru_virtcol = wp->w_virtcol;
+ wp->w_ru_empty = empty_line;
+ wp->w_ru_topline = wp->w_topline;
+ wp->w_ru_line_count = wp->w_buffer->b_ml.ml_line_count;
+#ifdef FEAT_DIFF
+ wp->w_ru_topfill = wp->w_topfill;
+#endif
+ }
+}
+#endif
diff --git a/src/search.c b/src/search.c
new file mode 100644
index 000000000..924f9e4fa
--- /dev/null
+++ b/src/search.c
@@ -0,0 +1,4487 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * search.c: code for normal mode searching commands
+ */
+
+#include "vim.h"
+
+static void save_re_pat __ARGS((int idx, char_u *pat, int magic));
+#ifdef FEAT_EVAL
+static int first_submatch __ARGS((regmmatch_T *rp));
+#endif
+static int check_prevcol __ARGS((char_u *linep, int col, int ch, int *prevcol));
+static int inmacro __ARGS((char_u *, char_u *));
+static int check_linecomment __ARGS((char_u *line));
+static int cls __ARGS((void));
+static int skip_chars __ARGS((int, int));
+#ifdef FEAT_TEXTOBJ
+static void back_in_line __ARGS((void));
+static void find_first_blank __ARGS((pos_T *));
+static void findsent_forward __ARGS((long count, int at_start_sent));
+#endif
+#ifdef FEAT_FIND_ID
+static void show_pat_in_path __ARGS((char_u *, int,
+ int, int, FILE *, linenr_T *, long));
+#endif
+#ifdef FEAT_VIMINFO
+static void wvsp_one __ARGS((FILE *fp, int idx, char *s, int sc));
+#endif
+
+static char_u *top_bot_msg = (char_u *)N_("search hit TOP, continuing at BOTTOM");
+static char_u *bot_top_msg = (char_u *)N_("search hit BOTTOM, continuing at TOP");
+
+/*
+ * This file contains various searching-related routines. These fall into
+ * three groups:
+ * 1. string searches (for /, ?, n, and N)
+ * 2. character searches within a single line (for f, F, t, T, etc)
+ * 3. "other" kinds of searches like the '%' command, and 'word' searches.
+ */
+
+/*
+ * String searches
+ *
+ * The string search functions are divided into two levels:
+ * lowest: searchit(); uses an pos_T for starting position and found match.
+ * Highest: do_search(); uses curwin->w_cursor; calls searchit().
+ *
+ * The last search pattern is remembered for repeating the same search.
+ * This pattern is shared between the :g, :s, ? and / commands.
+ * This is in search_regcomp().
+ *
+ * The actual string matching is done using a heavily modified version of
+ * Henry Spencer's regular expression library. See regexp.c.
+ */
+
+/* The offset for a search command is store in a soff struct */
+/* Note: only spats[0].off is really used */
+struct soffset
+{
+ int dir; /* search direction */
+ int line; /* search has line offset */
+ int end; /* search set cursor at end */
+ long off; /* line or char offset */
+};
+
+/* A search pattern and its attributes are stored in a spat struct */
+struct spat
+{
+ char_u *pat; /* the pattern (in allocated memory) or NULL */
+ int magic; /* magicness of the pattern */
+ int no_scs; /* no smarcase for this pattern */
+ struct soffset off;
+};
+
+/*
+ * Two search patterns are remembered: One for the :substitute command and
+ * one for other searches. last_idx points to the one that was used the last
+ * time.
+ */
+static struct spat spats[2] =
+{
+ {NULL, TRUE, FALSE, {'/', 0, 0, 0L}}, /* last used search pat */
+ {NULL, TRUE, FALSE, {'/', 0, 0, 0L}} /* last used substitute pat */
+};
+
+static int last_idx = 0; /* index in spats[] for RE_LAST */
+
+#if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO)
+/* copy of spats[], for keeping the search patterns while executing autocmds */
+static struct spat saved_spats[2];
+static int saved_last_idx = 0;
+# ifdef FEAT_SEARCH_EXTRA
+static int saved_no_hlsearch = 0;
+# endif
+#endif
+
+static char_u *mr_pattern = NULL; /* pattern used by search_regcomp() */
+#ifdef FEAT_RIGHTLEFT
+static int mr_pattern_alloced = FALSE; /* mr_pattern was allocated */
+static char_u *reverse_text __ARGS((char_u *s));
+#endif
+
+#ifdef FEAT_FIND_ID
+/*
+ * Type used by find_pattern_in_path() to remember which included files have
+ * been searched already.
+ */
+typedef struct SearchedFile
+{
+ FILE *fp; /* File pointer */
+ char_u *name; /* Full name of file */
+ linenr_T lnum; /* Line we were up to in file */
+ int matched; /* Found a match in this file */
+} SearchedFile;
+#endif
+
+/*
+ * translate search pattern for vim_regcomp()
+ *
+ * pat_save == RE_SEARCH: save pat in spats[RE_SEARCH].pat (normal search cmd)
+ * pat_save == RE_SUBST: save pat in spats[RE_SUBST].pat (:substitute command)
+ * pat_save == RE_BOTH: save pat in both patterns (:global command)
+ * pat_use == RE_SEARCH: use previous search pattern if "pat" is NULL
+ * pat_use == RE_SUBST: use previous sustitute pattern if "pat" is NULL
+ * pat_use == RE_LAST: use last used pattern if "pat" is NULL
+ * options & SEARCH_HIS: put search string in history
+ * options & SEARCH_KEEP: keep previous search pattern
+ *
+ * returns FAIL if failed, OK otherwise.
+ */
+ int
+search_regcomp(pat, pat_save, pat_use, options, regmatch)
+ char_u *pat;
+ int pat_save;
+ int pat_use;
+ int options;
+ regmmatch_T *regmatch; /* return: pattern and ignore-case flag */
+{
+ int magic;
+ int i;
+
+ rc_did_emsg = FALSE;
+ magic = p_magic;
+
+ /*
+ * If no pattern given, use a previously defined pattern.
+ */
+ if (pat == NULL || *pat == NUL)
+ {
+ if (pat_use == RE_LAST)
+ i = last_idx;
+ else
+ i = pat_use;
+ if (spats[i].pat == NULL) /* pattern was never defined */
+ {
+ if (pat_use == RE_SUBST)
+ EMSG(_(e_nopresub));
+ else
+ EMSG(_(e_noprevre));
+ rc_did_emsg = TRUE;
+ return FAIL;
+ }
+ pat = spats[i].pat;
+ magic = spats[i].magic;
+ no_smartcase = spats[i].no_scs;
+ }
+#ifdef FEAT_CMDHIST
+ else if (options & SEARCH_HIS) /* put new pattern in history */
+ add_to_history(HIST_SEARCH, pat, TRUE, NUL);
+#endif
+
+#ifdef FEAT_RIGHTLEFT
+ if (mr_pattern_alloced)
+ {
+ vim_free(mr_pattern);
+ mr_pattern_alloced = FALSE;
+ }
+
+ if (curwin->w_p_rl && *curwin->w_p_rlc == 's')
+ {
+ char_u *rev_pattern;
+
+ rev_pattern = reverse_text(pat);
+ if (rev_pattern == NULL)
+ mr_pattern = pat; /* out of memory, keep normal pattern. */
+ else
+ {
+ mr_pattern = rev_pattern;
+ mr_pattern_alloced = TRUE;
+ }
+ }
+ else
+#endif
+ mr_pattern = pat;
+
+ /*
+ * Save the currently used pattern in the appropriate place,
+ * unless the pattern should not be remembered.
+ */
+ if (!(options & SEARCH_KEEP))
+ {
+ /* search or global command */
+ if (pat_save == RE_SEARCH || pat_save == RE_BOTH)
+ save_re_pat(RE_SEARCH, pat, magic);
+ /* substitute or global command */
+ if (pat_save == RE_SUBST || pat_save == RE_BOTH)
+ save_re_pat(RE_SUBST, pat, magic);
+ }
+
+ regmatch->rmm_ic = ignorecase(pat);
+ regmatch->regprog = vim_regcomp(pat, magic ? RE_MAGIC : 0);
+ if (regmatch->regprog == NULL)
+ return FAIL;
+ return OK;
+}
+
+/*
+ * Get search pattern used by search_regcomp().
+ */
+ char_u *
+get_search_pat()
+{
+ return mr_pattern;
+}
+
+#ifdef FEAT_RIGHTLEFT
+/*
+ * Reverse text into allocated memory.
+ * Returns the allocated string, NULL when out of memory.
+ */
+ static char_u *
+reverse_text(s)
+ char_u *s;
+{
+ unsigned len;
+ unsigned s_i, rev_i;
+ char_u *rev;
+
+ /*
+ * Reverse the pattern.
+ */
+ len = (unsigned)STRLEN(s);
+ rev = alloc(len + 1);
+ if (rev != NULL)
+ {
+ rev_i = len;
+ for (s_i = 0; s_i < len; ++s_i)
+ {
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int mb_len;
+
+ mb_len = (*mb_ptr2len_check)(s + s_i);
+ rev_i -= mb_len;
+ mch_memmove(rev + rev_i, s + s_i, mb_len);
+ s_i += mb_len - 1;
+ }
+ else
+# endif
+ rev[--rev_i] = s[s_i];
+
+ }
+ rev[len] = NUL;
+ }
+ return rev;
+}
+#endif
+
+ static void
+save_re_pat(idx, pat, magic)
+ int idx;
+ char_u *pat;
+ int magic;
+{
+ if (spats[idx].pat != pat)
+ {
+ vim_free(spats[idx].pat);
+ spats[idx].pat = vim_strsave(pat);
+ spats[idx].magic = magic;
+ spats[idx].no_scs = no_smartcase;
+ last_idx = idx;
+#ifdef FEAT_SEARCH_EXTRA
+ /* If 'hlsearch' set and search pat changed: need redraw. */
+ if (p_hls)
+ redraw_all_later(NOT_VALID);
+ no_hlsearch = FALSE;
+#endif
+ }
+}
+
+#if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Save the search patterns, so they can be restored later.
+ * Used before/after executing autocommands and user functions.
+ */
+static int save_level = 0;
+
+ void
+save_search_patterns()
+{
+ if (save_level++ == 0)
+ {
+ saved_spats[0] = spats[0];
+ if (spats[0].pat != NULL)
+ saved_spats[0].pat = vim_strsave(spats[0].pat);
+ saved_spats[1] = spats[1];
+ if (spats[1].pat != NULL)
+ saved_spats[1].pat = vim_strsave(spats[1].pat);
+ saved_last_idx = last_idx;
+# ifdef FEAT_SEARCH_EXTRA
+ saved_no_hlsearch = no_hlsearch;
+# endif
+ }
+}
+
+ void
+restore_search_patterns()
+{
+ if (--save_level == 0)
+ {
+ vim_free(spats[0].pat);
+ spats[0] = saved_spats[0];
+ vim_free(spats[1].pat);
+ spats[1] = saved_spats[1];
+ last_idx = saved_last_idx;
+# ifdef FEAT_SEARCH_EXTRA
+ no_hlsearch = saved_no_hlsearch;
+# endif
+ }
+}
+#endif
+
+/*
+ * Return TRUE when case should be ignored for search pattern "pat".
+ * Uses the 'ignorecase' and 'smartcase' options.
+ */
+ int
+ignorecase(pat)
+ char_u *pat;
+{
+ char_u *p;
+ int ic;
+
+ ic = p_ic;
+ if (ic && !no_smartcase && p_scs
+#ifdef FEAT_INS_EXPAND
+ && !(ctrl_x_mode && curbuf->b_p_inf)
+#endif
+ )
+ {
+ /* don't ignore case if pattern has uppercase */
+ for (p = pat; *p; )
+ {
+#ifdef FEAT_MBYTE
+ int l;
+
+ if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
+ {
+ if (enc_utf8 && utf_isupper(utf_ptr2char(p)))
+ {
+ ic = FALSE;
+ break;
+ }
+ p += l;
+ }
+ else
+#endif
+ if (*p == '\\' && p[1] != NUL) /* skip "\S" et al. */
+ p += 2;
+ else if (isupper(*p++))
+ {
+ ic = FALSE;
+ break;
+ }
+ }
+ }
+ no_smartcase = FALSE;
+
+ return ic;
+}
+
+ char_u *
+last_search_pat()
+{
+ return spats[last_idx].pat;
+}
+
+/*
+ * Reset search direction to forward. For "gd" and "gD" commands.
+ */
+ void
+reset_search_dir()
+{
+ spats[0].off.dir = '/';
+}
+
+#if defined(FEAT_EVAL) || defined(FEAT_VIMINFO)
+/*
+ * Set the last search pattern. For ":let @/ =" and viminfo.
+ * Also set the saved search pattern, so that this works in an autocommand.
+ */
+ void
+set_last_search_pat(s, idx, magic, setlast)
+ char_u *s;
+ int idx;
+ int magic;
+ int setlast;
+{
+ vim_free(spats[idx].pat);
+ /* An empty string means that nothing should be matched. */
+ if (*s == NUL)
+ spats[idx].pat = NULL;
+ else
+ spats[idx].pat = vim_strsave(s);
+ spats[idx].magic = magic;
+ spats[idx].no_scs = FALSE;
+ spats[idx].off.dir = '/';
+ spats[idx].off.line = FALSE;
+ spats[idx].off.end = FALSE;
+ spats[idx].off.off = 0;
+ if (setlast)
+ last_idx = idx;
+ if (save_level)
+ {
+ vim_free(saved_spats[idx].pat);
+ saved_spats[idx] = spats[0];
+ if (spats[idx].pat == NULL)
+ saved_spats[idx].pat = NULL;
+ else
+ saved_spats[idx].pat = vim_strsave(spats[idx].pat);
+ saved_last_idx = last_idx;
+ }
+# ifdef FEAT_SEARCH_EXTRA
+ /* If 'hlsearch' set and search pat changed: need redraw. */
+ if (p_hls && idx == last_idx && !no_hlsearch)
+ redraw_all_later(NOT_VALID);
+# endif
+}
+#endif
+
+#ifdef FEAT_SEARCH_EXTRA
+/*
+ * Get a regexp program for the last used search pattern.
+ * This is used for highlighting all matches in a window.
+ * Values returned in regmatch->regprog and regmatch->rmm_ic.
+ */
+ void
+last_pat_prog(regmatch)
+ regmmatch_T *regmatch;
+{
+ if (spats[last_idx].pat == NULL)
+ {
+ regmatch->regprog = NULL;
+ return;
+ }
+ ++emsg_off; /* So it doesn't beep if bad expr */
+ (void)search_regcomp((char_u *)"", 0, last_idx, SEARCH_KEEP, regmatch);
+ --emsg_off;
+}
+#endif
+
+/*
+ * lowest level search function.
+ * Search for 'count'th occurrence of pattern 'pat' in direction 'dir'.
+ * Start at position 'pos' and return the found position in 'pos'.
+ *
+ * if (options & SEARCH_MSG) == 0 don't give any messages
+ * if (options & SEARCH_MSG) == SEARCH_NFMSG don't give 'notfound' messages
+ * if (options & SEARCH_MSG) == SEARCH_MSG give all messages
+ * if (options & SEARCH_HIS) put search pattern in history
+ * if (options & SEARCH_END) return position at end of match
+ * if (options & SEARCH_START) accept match at pos itself
+ * if (options & SEARCH_KEEP) keep previous search pattern
+ * if (options & SEARCH_FOLD) match only once in a closed fold
+ * if (options & SEARCH_PEEK) check for typed char, cancel search
+ *
+ * Return FAIL (zero) for failure, non-zero for success.
+ * When FEAT_EVAL is defined, returns the index of the first matching
+ * subpattern plus one; one if there was none.
+ */
+ int
+searchit(win, buf, pos, dir, pat, count, options, pat_use)
+ win_T *win; /* window to search in; can be NULL for a
+ buffer without a window! */
+ buf_T *buf;
+ pos_T *pos;
+ int dir;
+ char_u *pat;
+ long count;
+ int options;
+ int pat_use;
+{
+ int found;
+ linenr_T lnum; /* no init to shut up Apollo cc */
+ regmmatch_T regmatch;
+ char_u *ptr;
+ colnr_T matchcol;
+ colnr_T startcol;
+ lpos_T endpos;
+ int loop;
+ pos_T start_pos;
+ int at_first_line;
+ int extra_col;
+ int match_ok;
+ long nmatched;
+ int submatch = 0;
+ linenr_T first_lnum;
+#ifdef FEAT_SEARCH_EXTRA
+ int break_loop = FALSE;
+#else
+# define break_loop FALSE
+#endif
+
+ if (search_regcomp(pat, RE_SEARCH, pat_use,
+ (options & (SEARCH_HIS + SEARCH_KEEP)), &regmatch) == FAIL)
+ {
+ if ((options & SEARCH_MSG) && !rc_did_emsg)
+ EMSG2(_("E383: Invalid search string: %s"), mr_pattern);
+ return FAIL;
+ }
+
+ if (options & SEARCH_START)
+ extra_col = 0;
+#ifdef FEAT_MBYTE
+ /* Watch out for the "col" being MAXCOL - 2, used in a closed fold. */
+ else if (has_mbyte && pos->lnum >= 1 && pos->lnum <= buf->b_ml.ml_line_count
+ && pos->col < MAXCOL - 2)
+ extra_col = (*mb_ptr2len_check)(ml_get_buf(buf, pos->lnum, FALSE)
+ + pos->col);
+#endif
+ else
+ extra_col = 1;
+
+/*
+ * find the string
+ */
+ called_emsg = FALSE;
+ do /* loop for count */
+ {
+ start_pos = *pos; /* remember start pos for detecting no match */
+ found = 0; /* default: not found */
+ at_first_line = TRUE; /* default: start in first line */
+ if (pos->lnum == 0) /* correct lnum for when starting in line 0 */
+ {
+ pos->lnum = 1;
+ pos->col = 0;
+ at_first_line = FALSE; /* not in first line now */
+ }
+
+ /*
+ * Start searching in current line, unless searching backwards and
+ * we're in column 0.
+ */
+ if (dir == BACKWARD && start_pos.col == 0)
+ {
+ lnum = pos->lnum - 1;
+ at_first_line = FALSE;
+ }
+ else
+ lnum = pos->lnum;
+
+ for (loop = 0; loop <= 1; ++loop) /* loop twice if 'wrapscan' set */
+ {
+ for ( ; lnum > 0 && lnum <= buf->b_ml.ml_line_count;
+ lnum += dir, at_first_line = FALSE)
+ {
+ /*
+ * Look for a match somewhere in the line.
+ */
+ first_lnum = lnum;
+ nmatched = vim_regexec_multi(&regmatch, win, buf,
+ lnum, (colnr_T)0);
+ /* Abort searching on an error (e.g., out of stack). */
+ if (called_emsg)
+ break;
+ if (nmatched > 0)
+ {
+ /* match may actually be in another line when using \zs */
+ lnum += regmatch.startpos[0].lnum;
+ ptr = ml_get_buf(buf, lnum, FALSE);
+ startcol = regmatch.startpos[0].col;
+ endpos = regmatch.endpos[0];
+# ifdef FEAT_EVAL
+ submatch = first_submatch(&regmatch);
+# endif
+
+ /*
+ * Forward search in the first line: match should be after
+ * the start position. If not, continue at the end of the
+ * match (this is vi compatible) or on the next char.
+ */
+ if (dir == FORWARD && at_first_line)
+ {
+ match_ok = TRUE;
+ /*
+ * When match lands on a NUL the cursor will be put
+ * one back afterwards, compare with that position,
+ * otherwise "/$" will get stuck on end of line.
+ */
+ while ((options & SEARCH_END)
+ ? (nmatched == 1
+ && (int)endpos.col - 1
+ < (int)start_pos.col + extra_col)
+ : ((int)startcol - (ptr[startcol] == NUL)
+ < (int)start_pos.col + extra_col))
+ {
+ /*
+ * If vi-compatible searching, continue at the end
+ * of the match, otherwise continue one position
+ * forward.
+ */
+ if (vim_strchr(p_cpo, CPO_SEARCH) != NULL)
+ {
+ if (nmatched > 1)
+ {
+ /* end is in next line, thus no match in
+ * this line */
+ match_ok = FALSE;
+ break;
+ }
+ matchcol = endpos.col;
+ /* for empty match: advance one char */
+ if (matchcol == startcol
+ && ptr[matchcol] != NUL)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ matchcol +=
+ (*mb_ptr2len_check)(ptr + matchcol);
+ else
+#endif
+ ++matchcol;
+ }
+ }
+ else
+ {
+ matchcol = startcol;
+ if (ptr[matchcol] != NUL)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ matchcol += (*mb_ptr2len_check)(ptr
+ + matchcol);
+ else
+#endif
+ ++matchcol;
+ }
+ }
+ if (ptr[matchcol] == NUL
+ || (nmatched = vim_regexec_multi(&regmatch,
+ win, buf, lnum, matchcol)) == 0)
+ {
+ match_ok = FALSE;
+ break;
+ }
+ startcol = regmatch.startpos[0].col;
+ endpos = regmatch.endpos[0];
+# ifdef FEAT_EVAL
+ submatch = first_submatch(&regmatch);
+# endif
+
+ /* Need to get the line pointer again, a
+ * multi-line search may have made it invalid. */
+ ptr = ml_get_buf(buf, lnum, FALSE);
+ }
+ if (!match_ok)
+ continue;
+ }
+ if (dir == BACKWARD)
+ {
+ /*
+ * Now, if there are multiple matches on this line,
+ * we have to get the last one. Or the last one before
+ * the cursor, if we're on that line.
+ * When putting the new cursor at the end, compare
+ * relative to the end of the match.
+ */
+ match_ok = FALSE;
+ for (;;)
+ {
+ if (!at_first_line
+ || ((options & SEARCH_END)
+ ? (nmatched == 1
+ && (int)regmatch.endpos[0].col - 1
+ + extra_col
+ <= (int)start_pos.col)
+ : ((int)regmatch.startpos[0].col
+ + extra_col
+ <= (int)start_pos.col)))
+ {
+ /* Remember this position, we use it if it's
+ * the last match in the line. */
+ match_ok = TRUE;
+ startcol = regmatch.startpos[0].col;
+ endpos = regmatch.endpos[0];
+# ifdef FEAT_EVAL
+ submatch = first_submatch(&regmatch);
+# endif
+ }
+ else
+ break;
+
+ /*
+ * We found a valid match, now check if there is
+ * another one after it.
+ * If vi-compatible searching, continue at the end
+ * of the match, otherwise continue one position
+ * forward.
+ */
+ if (vim_strchr(p_cpo, CPO_SEARCH) != NULL)
+ {
+ if (nmatched > 1)
+ break;
+ matchcol = endpos.col;
+ /* for empty match: advance one char */
+ if (matchcol == startcol
+ && ptr[matchcol] != NUL)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ matchcol +=
+ (*mb_ptr2len_check)(ptr + matchcol);
+ else
+#endif
+ ++matchcol;
+ }
+ }
+ else
+ {
+ matchcol = startcol;
+ if (ptr[matchcol] != NUL)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ matchcol +=
+ (*mb_ptr2len_check)(ptr + matchcol);
+ else
+#endif
+ ++matchcol;
+ }
+ }
+ if (ptr[matchcol] == NUL
+ || (nmatched = vim_regexec_multi(&regmatch,
+ win, buf, lnum, matchcol)) == 0)
+ break;
+
+ /* Need to get the line pointer again, a
+ * multi-line search may have made it invalid. */
+ ptr = ml_get_buf(buf, lnum, FALSE);
+ }
+
+ /*
+ * If there is only a match after the cursor, skip
+ * this match.
+ */
+ if (!match_ok)
+ continue;
+ }
+
+ if (options & SEARCH_END && !(options & SEARCH_NOOF))
+ {
+ pos->lnum = endpos.lnum + first_lnum;
+ pos->col = endpos.col - 1;
+ }
+ else
+ {
+ pos->lnum = lnum;
+ pos->col = startcol;
+ }
+#ifdef FEAT_VIRTUALEDIT
+ pos->coladd = 0;
+#endif
+ found = 1;
+
+ /* Set variables used for 'incsearch' highlighting. */
+ search_match_lines = endpos.lnum - (lnum - first_lnum);
+ search_match_endcol = endpos.col;
+ break;
+ }
+ line_breakcheck(); /* stop if ctrl-C typed */
+ if (got_int)
+ break;
+
+#ifdef FEAT_SEARCH_EXTRA
+ /* Cancel searching if a character was typed. Used for
+ * 'incsearch'. Don't check too often, that would slowdown
+ * searching too much. */
+ if ((options & SEARCH_PEEK)
+ && ((lnum - pos->lnum) & 0x3f) == 0
+ && char_avail())
+ {
+ break_loop = TRUE;
+ break;
+ }
+#endif
+
+ if (loop && lnum == start_pos.lnum)
+ break; /* if second loop, stop where started */
+ }
+ at_first_line = FALSE;
+
+ /*
+ * Stop the search if wrapscan isn't set, after an interrupt,
+ * after a match and after looping twice.
+ */
+ if (!p_ws || got_int || called_emsg || break_loop || found || loop)
+ break;
+
+ /*
+ * If 'wrapscan' is set we continue at the other end of the file.
+ * If 'shortmess' does not contain 's', we give a message.
+ * This message is also remembered in keep_msg for when the screen
+ * is redrawn. The keep_msg is cleared whenever another message is
+ * written.
+ */
+ if (dir == BACKWARD) /* start second loop at the other end */
+ {
+ lnum = buf->b_ml.ml_line_count;
+ if (!shortmess(SHM_SEARCH) && (options & SEARCH_MSG))
+ give_warning((char_u *)_(top_bot_msg), TRUE);
+ }
+ else
+ {
+ lnum = 1;
+ if (!shortmess(SHM_SEARCH) && (options & SEARCH_MSG))
+ give_warning((char_u *)_(bot_top_msg), TRUE);
+ }
+ }
+ if (got_int || called_emsg || break_loop)
+ break;
+ }
+ while (--count > 0 && found); /* stop after count matches or no match */
+
+ vim_free(regmatch.regprog);
+
+ if (!found) /* did not find it */
+ {
+ if (got_int)
+ EMSG(_(e_interr));
+ else if ((options & SEARCH_MSG) == SEARCH_MSG)
+ {
+ if (p_ws)
+ EMSG2(_(e_patnotf2), mr_pattern);
+ else if (lnum == 0)
+ EMSG2(_("E384: search hit TOP without match for: %s"),
+ mr_pattern);
+ else
+ EMSG2(_("E385: search hit BOTTOM without match for: %s"),
+ mr_pattern);
+ }
+ return FAIL;
+ }
+
+ return submatch + 1;
+}
+
+#ifdef FEAT_EVAL
+/*
+ * Return the number of the first subpat that matched.
+ */
+ static int
+first_submatch(rp)
+ regmmatch_T *rp;
+{
+ int submatch;
+
+ for (submatch = 1; ; ++submatch)
+ {
+ if (rp->startpos[submatch].lnum >= 0)
+ break;
+ if (submatch == 9)
+ {
+ submatch = 0;
+ break;
+ }
+ }
+ return submatch;
+}
+#endif
+
+/*
+ * Highest level string search function.
+ * Search for the 'count'th occurence of pattern 'pat' in direction 'dirc'
+ * If 'dirc' is 0: use previous dir.
+ * If 'pat' is NULL or empty : use previous string.
+ * If 'options & SEARCH_REV' : go in reverse of previous dir.
+ * If 'options & SEARCH_ECHO': echo the search command and handle options
+ * If 'options & SEARCH_MSG' : may give error message
+ * If 'options & SEARCH_OPT' : interpret optional flags
+ * If 'options & SEARCH_HIS' : put search pattern in history
+ * If 'options & SEARCH_NOOF': don't add offset to position
+ * If 'options & SEARCH_MARK': set previous context mark
+ * If 'options & SEARCH_KEEP': keep previous search pattern
+ * If 'options & SEARCH_START': accept match at curpos itself
+ * If 'options & SEARCH_PEEK': check for typed char, cancel search
+ *
+ * Careful: If spats[0].off.line == TRUE and spats[0].off.off == 0 this
+ * makes the movement linewise without moving the match position.
+ *
+ * return 0 for failure, 1 for found, 2 for found and line offset added
+ */
+ int
+do_search(oap, dirc, pat, count, options)
+ oparg_T *oap; /* can be NULL */
+ int dirc; /* '/' or '?' */
+ char_u *pat;
+ long count;
+ int options;
+{
+ pos_T pos; /* position of the last match */
+ char_u *searchstr;
+ struct soffset old_off;
+ int retval; /* Return value */
+ char_u *p;
+ long c;
+ char_u *dircp;
+ char_u *strcopy = NULL;
+ char_u *ps;
+
+ /*
+ * A line offset is not remembered, this is vi compatible.
+ */
+ if (spats[0].off.line && vim_strchr(p_cpo, CPO_LINEOFF) != NULL)
+ {
+ spats[0].off.line = FALSE;
+ spats[0].off.off = 0;
+ }
+
+ /*
+ * Save the values for when (options & SEARCH_KEEP) is used.
+ * (there is no "if ()" around this because gcc wants them initialized)
+ */
+ old_off = spats[0].off;
+
+ pos = curwin->w_cursor; /* start searching at the cursor position */
+
+ /*
+ * Find out the direction of the search.
+ */
+ if (dirc == 0)
+ dirc = spats[0].off.dir;
+ else
+ spats[0].off.dir = dirc;
+ if (options & SEARCH_REV)
+ {
+#ifdef WIN32
+ /* There is a bug in the Visual C++ 2.2 compiler which means that
+ * dirc always ends up being '/' */
+ dirc = (dirc == '/') ? '?' : '/';
+#else
+ if (dirc == '/')
+ dirc = '?';
+ else
+ dirc = '/';
+#endif
+ }
+
+#ifdef FEAT_FOLDING
+ /* If the cursor is in a closed fold, don't find another match in the same
+ * fold. */
+ if (dirc == '/')
+ {
+ if (hasFolding(pos.lnum, NULL, &pos.lnum))
+ pos.col = MAXCOL - 2; /* avoid overflow when adding 1 */
+ }
+ else
+ {
+ if (hasFolding(pos.lnum, &pos.lnum, NULL))
+ pos.col = 0;
+ }
+#endif
+
+#ifdef FEAT_SEARCH_EXTRA
+ /*
+ * Turn 'hlsearch' highlighting back on.
+ */
+ if (no_hlsearch && !(options & SEARCH_KEEP))
+ {
+ redraw_all_later(NOT_VALID);
+ no_hlsearch = FALSE;
+ }
+#endif
+
+ /*
+ * Repeat the search when pattern followed by ';', e.g. "/foo/;?bar".
+ */
+ for (;;)
+ {
+ searchstr = pat;
+ dircp = NULL;
+ /* use previous pattern */
+ if (pat == NULL || *pat == NUL || *pat == dirc)
+ {
+ if (spats[RE_SEARCH].pat == NULL) /* no previous pattern */
+ {
+ EMSG(_(e_noprevre));
+ retval = 0;
+ goto end_do_search;
+ }
+ /* make search_regcomp() use spats[RE_SEARCH].pat */
+ searchstr = (char_u *)"";
+ }
+
+ if (pat != NULL && *pat != NUL) /* look for (new) offset */
+ {
+ /*
+ * Find end of regular expression.
+ * If there is a matching '/' or '?', toss it.
+ */
+ ps = strcopy;
+ p = skip_regexp(pat, dirc, (int)p_magic, &strcopy);
+ if (strcopy != ps)
+ {
+ /* made a copy of "pat" to change "\?" to "?" */
+ searchcmdlen += STRLEN(pat) - STRLEN(strcopy);
+ pat = strcopy;
+ searchstr = strcopy;
+ }
+ if (*p == dirc)
+ {
+ dircp = p; /* remember where we put the NUL */
+ *p++ = NUL;
+ }
+ spats[0].off.line = FALSE;
+ spats[0].off.end = FALSE;
+ spats[0].off.off = 0;
+ /*
+ * Check for a line offset or a character offset.
+ * For get_address (echo off) we don't check for a character
+ * offset, because it is meaningless and the 's' could be a
+ * substitute command.
+ */
+ if (*p == '+' || *p == '-' || VIM_ISDIGIT(*p))
+ spats[0].off.line = TRUE;
+ else if ((options & SEARCH_OPT) &&
+ (*p == 'e' || *p == 's' || *p == 'b'))
+ {
+ if (*p == 'e') /* end */
+ spats[0].off.end = SEARCH_END;
+ ++p;
+ }
+ if (VIM_ISDIGIT(*p) || *p == '+' || *p == '-') /* got an offset */
+ {
+ /* 'nr' or '+nr' or '-nr' */
+ if (VIM_ISDIGIT(*p) || VIM_ISDIGIT(*(p + 1)))
+ spats[0].off.off = atol((char *)p);
+ else if (*p == '-') /* single '-' */
+ spats[0].off.off = -1;
+ else /* single '+' */
+ spats[0].off.off = 1;
+ ++p;
+ while (VIM_ISDIGIT(*p)) /* skip number */
+ ++p;
+ }
+
+ /* compute length of search command for get_address() */
+ searchcmdlen += (int)(p - pat);
+
+ pat = p; /* put pat after search command */
+ }
+
+ if ((options & SEARCH_ECHO) && messaging()
+ && !cmd_silent && msg_silent == 0)
+ {
+ char_u *msgbuf;
+ char_u *trunc;
+
+ if (*searchstr == NUL)
+ p = spats[last_idx].pat;
+ else
+ p = searchstr;
+ msgbuf = alloc((unsigned)(STRLEN(p) + 40));
+ if (msgbuf != NULL)
+ {
+ msgbuf[0] = dirc;
+ STRCPY(msgbuf + 1, p);
+ if (spats[0].off.line || spats[0].off.end || spats[0].off.off)
+ {
+ p = msgbuf + STRLEN(msgbuf);
+ *p++ = dirc;
+ if (spats[0].off.end)
+ *p++ = 'e';
+ else if (!spats[0].off.line)
+ *p++ = 's';
+ if (spats[0].off.off > 0 || spats[0].off.line)
+ *p++ = '+';
+ if (spats[0].off.off != 0 || spats[0].off.line)
+ sprintf((char *)p, "%ld", spats[0].off.off);
+ else
+ *p = NUL;
+ }
+
+ msg_start();
+ trunc = msg_strtrunc(msgbuf);
+
+#ifdef FEAT_RIGHTLEFT
+ /* The search pattern could be shown on the right in rightleft
+ * mode, but the 'ruler' and 'showcmd' area use it too, thus
+ * it would be blanked out again very soon. Show it on the
+ * left, but do reverse the text. */
+ if (curwin->w_p_rl && *curwin->w_p_rlc == 's')
+ {
+ char_u *r;
+
+ r = reverse_text(trunc != NULL ? trunc : msgbuf);
+ if (r != NULL)
+ {
+ vim_free(trunc);
+ trunc = r;
+ }
+ }
+#endif
+ if (trunc != NULL)
+ {
+ msg_outtrans(trunc);
+ vim_free(trunc);
+ }
+ else
+ msg_outtrans(msgbuf);
+ msg_clr_eos();
+ msg_check();
+ vim_free(msgbuf);
+
+ gotocmdline(FALSE);
+ out_flush();
+ msg_nowait = TRUE; /* don't wait for this message */
+ }
+ }
+
+ /*
+ * If there is a character offset, subtract it from the current
+ * position, so we don't get stuck at "?pat?e+2" or "/pat/s-2".
+ * This is not done for a line offset, because then we would not be vi
+ * compatible.
+ */
+ if (!spats[0].off.line && spats[0].off.off)
+ {
+ if (spats[0].off.off > 0)
+ {
+ for (c = spats[0].off.off; c; --c)
+ if (decl(&pos) == -1)
+ break;
+ if (c) /* at start of buffer */
+ {
+ pos.lnum = 0; /* allow lnum == 0 here */
+ pos.col = MAXCOL;
+ }
+ }
+ else
+ {
+ for (c = spats[0].off.off; c; ++c)
+ if (incl(&pos) == -1)
+ break;
+ if (c) /* at end of buffer */
+ {
+ pos.lnum = curbuf->b_ml.ml_line_count + 1;
+ pos.col = 0;
+ }
+ }
+ }
+
+#ifdef FEAT_FKMAP /* when in Farsi mode, reverse the character flow */
+ if (p_altkeymap && curwin->w_p_rl)
+ lrFswap(searchstr,0);
+#endif
+
+ c = searchit(curwin, curbuf, &pos, dirc == '/' ? FORWARD : BACKWARD,
+ searchstr, count, spats[0].off.end + (options &
+ (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS
+ + SEARCH_MSG + SEARCH_START
+ + ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))),
+ RE_LAST);
+
+ if (dircp != NULL)
+ *dircp = dirc; /* restore second '/' or '?' for normal_cmd() */
+ if (c == FAIL)
+ {
+ retval = 0;
+ goto end_do_search;
+ }
+ if (spats[0].off.end && oap != NULL)
+ oap->inclusive = TRUE; /* 'e' includes last character */
+
+ retval = 1; /* pattern found */
+
+ /*
+ * Add character and/or line offset
+ */
+ if (!(options & SEARCH_NOOF) || *pat == ';')
+ {
+ if (spats[0].off.line) /* Add the offset to the line number. */
+ {
+ c = pos.lnum + spats[0].off.off;
+ if (c < 1)
+ pos.lnum = 1;
+ else if (c > curbuf->b_ml.ml_line_count)
+ pos.lnum = curbuf->b_ml.ml_line_count;
+ else
+ pos.lnum = c;
+ pos.col = 0;
+
+ retval = 2; /* pattern found, line offset added */
+ }
+ else
+ {
+ /* to the right, check for end of file */
+ if (spats[0].off.off > 0)
+ {
+ for (c = spats[0].off.off; c; --c)
+ if (incl(&pos) == -1)
+ break;
+ }
+ /* to the left, check for start of file */
+ else
+ {
+ if ((c = pos.col + spats[0].off.off) >= 0)
+ pos.col = c;
+ else
+ for (c = spats[0].off.off; c; ++c)
+ if (decl(&pos) == -1)
+ break;
+ }
+ }
+ }
+
+ /*
+ * The search command can be followed by a ';' to do another search.
+ * For example: "/pat/;/foo/+3;?bar"
+ * This is like doing another search command, except:
+ * - The remembered direction '/' or '?' is from the first search.
+ * - When an error happens the cursor isn't moved at all.
+ * Don't do this when called by get_address() (it handles ';' itself).
+ */
+ if (!(options & SEARCH_OPT) || pat == NULL || *pat != ';')
+ break;
+
+ dirc = *++pat;
+ if (dirc != '?' && dirc != '/')
+ {
+ retval = 0;
+ EMSG(_("E386: Expected '?' or '/' after ';'"));
+ goto end_do_search;
+ }
+ ++pat;
+ }
+
+ if (options & SEARCH_MARK)
+ setpcmark();
+ curwin->w_cursor = pos;
+ curwin->w_set_curswant = TRUE;
+
+end_do_search:
+ if (options & SEARCH_KEEP)
+ spats[0].off = old_off;
+ vim_free(strcopy);
+
+ return retval;
+}
+
+#if defined(FEAT_INS_EXPAND) || defined(PROTO)
+/*
+ * search_for_exact_line(buf, pos, dir, pat)
+ *
+ * Search for a line starting with the given pattern (ignoring leading
+ * white-space), starting from pos and going in direction dir. pos will
+ * contain the position of the match found. Blank lines match only if
+ * ADDING is set. if p_ic is set then the pattern must be in lowercase.
+ * Return OK for success, or FAIL if no line found.
+ */
+ int
+search_for_exact_line(buf, pos, dir, pat)
+ buf_T *buf;
+ pos_T *pos;
+ int dir;
+ char_u *pat;
+{
+ linenr_T start = 0;
+ char_u *ptr;
+ char_u *p;
+
+ if (buf->b_ml.ml_line_count == 0)
+ return FAIL;
+ for (;;)
+ {
+ pos->lnum += dir;
+ if (pos->lnum < 1)
+ {
+ if (p_ws)
+ {
+ pos->lnum = buf->b_ml.ml_line_count;
+ if (!shortmess(SHM_SEARCH))
+ give_warning((char_u *)_(top_bot_msg), TRUE);
+ }
+ else
+ {
+ pos->lnum = 1;
+ break;
+ }
+ }
+ else if (pos->lnum > buf->b_ml.ml_line_count)
+ {
+ if (p_ws)
+ {
+ pos->lnum = 1;
+ if (!shortmess(SHM_SEARCH))
+ give_warning((char_u *)_(bot_top_msg), TRUE);
+ }
+ else
+ {
+ pos->lnum = 1;
+ break;
+ }
+ }
+ if (pos->lnum == start)
+ break;
+ if (start == 0)
+ start = pos->lnum;
+ ptr = ml_get_buf(buf, pos->lnum, FALSE);
+ p = skipwhite(ptr);
+ pos->col = (colnr_T) (p - ptr);
+
+ /* when adding lines the matching line may be empty but it is not
+ * ignored because we are interested in the next line -- Acevedo */
+ if ((continue_status & CONT_ADDING) && !(continue_status & CONT_SOL))
+ {
+ if ((p_ic ? MB_STRICMP(p, pat) : STRCMP(p, pat)) == 0)
+ return OK;
+ }
+ else if (*p != NUL) /* ignore empty lines */
+ { /* expanding lines or words */
+ if ((p_ic ? MB_STRNICMP(p, pat, completion_length)
+ : STRNCMP(p, pat, completion_length)) == 0)
+ return OK;
+ }
+ }
+ return FAIL;
+}
+#endif /* FEAT_INS_EXPAND */
+
+/*
+ * Character Searches
+ */
+
+/*
+ * Search for a character in a line. If "t_cmd" is FALSE, move to the
+ * position of the character, otherwise move to just before the char.
+ * Do this "cap->count1" times.
+ * Return FAIL or OK.
+ */
+ int
+searchc(cap, t_cmd)
+ cmdarg_T *cap;
+ int t_cmd;
+{
+ int c = cap->nchar; /* char to search for */
+ int dir = cap->arg; /* TRUE for searching forward */
+ long count = cap->count1; /* repeat count */
+ static int lastc = NUL; /* last character searched for */
+ static int lastcdir; /* last direction of character search */
+ static int last_t_cmd; /* last search t_cmd */
+ int col;
+ char_u *p;
+ int len;
+#ifdef FEAT_MBYTE
+ static char_u bytes[MB_MAXBYTES];
+ static int bytelen = 1; /* >1 for multi-byte char */
+#endif
+
+ if (c != NUL) /* normal search: remember args for repeat */
+ {
+ if (!KeyStuffed) /* don't remember when redoing */
+ {
+ lastc = c;
+ lastcdir = dir;
+ last_t_cmd = t_cmd;
+#ifdef FEAT_MBYTE
+ bytelen = (*mb_char2bytes)(c, bytes);
+ if (cap->ncharC1 != 0)
+ {
+ bytelen += (*mb_char2bytes)(cap->ncharC1, bytes + bytelen);
+ if (cap->ncharC2 != 0)
+ bytelen += (*mb_char2bytes)(cap->ncharC2, bytes + bytelen);
+ }
+#endif
+ }
+ }
+ else /* repeat previous search */
+ {
+ if (lastc == NUL)
+ return FAIL;
+ if (dir) /* repeat in opposite direction */
+ dir = -lastcdir;
+ else
+ dir = lastcdir;
+ t_cmd = last_t_cmd;
+ c = lastc;
+ /* For multi-byte re-use last bytes[] and bytelen. */
+ }
+
+ p = ml_get_curline();
+ col = curwin->w_cursor.col;
+ len = (int)STRLEN(p);
+
+ while (count--)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ for (;;)
+ {
+ if (dir > 0)
+ {
+ col += (*mb_ptr2len_check)(p + col);
+ if (col >= len)
+ return FAIL;
+ }
+ else
+ {
+ if (col == 0)
+ return FAIL;
+ col -= (*mb_head_off)(p, p + col - 1) + 1;
+ }
+ if (bytelen == 1)
+ {
+ if (p[col] == c)
+ break;
+ }
+ else
+ {
+ if (vim_memcmp(p + col, bytes, bytelen) == 0)
+ break;
+ }
+ }
+ }
+ else
+#endif
+ {
+ for (;;)
+ {
+ if ((col += dir) < 0 || col >= len)
+ return FAIL;
+ if (p[col] == c)
+ break;
+ }
+ }
+ }
+
+ if (t_cmd)
+ {
+ /* backup to before the character (possibly double-byte) */
+ col -= dir;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ if (dir < 0)
+ /* Landed on the search char which is bytelen long */
+ col += bytelen - 1;
+ else
+ /* To previous char, which may be multi-byte. */
+ col -= (*mb_head_off)(p, p + col);
+ }
+#endif
+ }
+ curwin->w_cursor.col = col;
+
+ return OK;
+}
+
+/*
+ * "Other" Searches
+ */
+
+/*
+ * findmatch - find the matching paren or brace
+ *
+ * Improvement over vi: Braces inside quotes are ignored.
+ */
+ pos_T *
+findmatch(oap, initc)
+ oparg_T *oap;
+ int initc;
+{
+ return findmatchlimit(oap, initc, 0, 0);
+}
+
+/*
+ * Return TRUE if the character before "linep[col]" equals "ch".
+ * Return FALSE if "col" is zero.
+ * Update "*prevcol" to the column of the previous character, unless "prevcol"
+ * is NULL.
+ * Handles multibyte string correctly.
+ */
+ static int
+check_prevcol(linep, col, ch, prevcol)
+ char_u *linep;
+ int col;
+ int ch;
+ int *prevcol;
+{
+ --col;
+#ifdef FEAT_MBYTE
+ if (col > 0 && has_mbyte)
+ col -= (*mb_head_off)(linep, linep + col);
+#endif
+ if (prevcol)
+ *prevcol = col;
+ return (col >= 0 && linep[col] == ch) ? TRUE : FALSE;
+}
+
+/*
+ * findmatchlimit -- find the matching paren or brace, if it exists within
+ * maxtravel lines of here. A maxtravel of 0 means search until falling off
+ * the edge of the file.
+ *
+ * "initc" is the character to find a match for. NUL means to find the
+ * character at or after the cursor.
+ *
+ * flags: FM_BACKWARD search backwards (when initc is '/', '*' or '#')
+ * FM_FORWARD search forwards (when initc is '/', '*' or '#')
+ * FM_BLOCKSTOP stop at start/end of block ({ or } in column 0)
+ * FM_SKIPCOMM skip comments (not implemented yet!)
+ */
+
+ pos_T *
+findmatchlimit(oap, initc, flags, maxtravel)
+ oparg_T *oap;
+ int initc;
+ int flags;
+ int maxtravel;
+{
+ static pos_T pos; /* current search position */
+ int findc = 0; /* matching brace */
+ int c;
+ int count = 0; /* cumulative number of braces */
+ int backwards = FALSE; /* init for gcc */
+ int inquote = FALSE; /* TRUE when inside quotes */
+ char_u *linep; /* pointer to current line */
+ char_u *ptr;
+ int do_quotes; /* check for quotes in current line */
+ int at_start; /* do_quotes value at start position */
+ int hash_dir = 0; /* Direction searched for # things */
+ int comment_dir = 0; /* Direction searched for comments */
+ pos_T match_pos; /* Where last slash-star was found */
+ int start_in_quotes; /* start position is in quotes */
+ int traveled = 0; /* how far we've searched so far */
+ int ignore_cend = FALSE; /* ignore comment end */
+ int cpo_match; /* vi compatible matching */
+ int cpo_bsl; /* don't recognize backslashes */
+ int match_escaped = 0; /* search for escaped match */
+ int dir; /* Direction to search */
+ int comment_col = MAXCOL; /* start of / / comment */
+
+ pos = curwin->w_cursor;
+ linep = ml_get(pos.lnum);
+
+ cpo_match = (vim_strchr(p_cpo, CPO_MATCH) != NULL);
+ cpo_bsl = (vim_strchr(p_cpo, CPO_MATCHBSL) != NULL);
+
+ /* Direction to search when initc is '/', '*' or '#' */
+ if (flags & FM_BACKWARD)
+ dir = BACKWARD;
+ else if (flags & FM_FORWARD)
+ dir = FORWARD;
+ else
+ dir = 0;
+
+ /*
+ * if initc given, look in the table for the matching character
+ * '/' and '*' are special cases: look for start or end of comment.
+ * When '/' is used, we ignore running backwards into an star-slash, for
+ * "[*" command, we just want to find any comment.
+ */
+ if (initc == '/' || initc == '*')
+ {
+ comment_dir = dir;
+ if (initc == '/')
+ ignore_cend = TRUE;
+ backwards = (dir == FORWARD) ? FALSE : TRUE;
+ initc = NUL;
+ }
+ else if (initc != '#' && initc != NUL)
+ {
+ /* 'matchpairs' is "x:y,x:y" */
+ for (ptr = curbuf->b_p_mps; *ptr; ptr += 2)
+ {
+ if (*ptr == initc)
+ {
+ findc = initc;
+ initc = ptr[2];
+ backwards = TRUE;
+ break;
+ }
+ ptr += 2;
+ if (*ptr == initc)
+ {
+ findc = initc;
+ initc = ptr[-2];
+ backwards = FALSE;
+ break;
+ }
+ if (ptr[1] != ',')
+ break;
+ }
+ if (!findc) /* invalid initc! */
+ return NULL;
+ }
+ /*
+ * Either initc is '#', or no initc was given and we need to look under the
+ * cursor.
+ */
+ else
+ {
+ if (initc == '#')
+ {
+ hash_dir = dir;
+ }
+ else
+ {
+ /*
+ * initc was not given, must look for something to match under
+ * or near the cursor.
+ * Only check for special things when 'cpo' doesn't have '%'.
+ */
+ if (!cpo_match)
+ {
+ /* Are we before or at #if, #else etc.? */
+ ptr = skipwhite(linep);
+ if (*ptr == '#' && pos.col <= (colnr_T)(ptr - linep))
+ {
+ ptr = skipwhite(ptr + 1);
+ if ( STRNCMP(ptr, "if", 2) == 0
+ || STRNCMP(ptr, "endif", 5) == 0
+ || STRNCMP(ptr, "el", 2) == 0)
+ hash_dir = 1;
+ }
+
+ /* Are we on a comment? */
+ else if (linep[pos.col] == '/')
+ {
+ if (linep[pos.col + 1] == '*')
+ {
+ comment_dir = FORWARD;
+ backwards = FALSE;
+ pos.col++;
+ }
+ else if (pos.col > 0 && linep[pos.col - 1] == '*')
+ {
+ comment_dir = BACKWARD;
+ backwards = TRUE;
+ pos.col--;
+ }
+ }
+ else if (linep[pos.col] == '*')
+ {
+ if (linep[pos.col + 1] == '/')
+ {
+ comment_dir = BACKWARD;
+ backwards = TRUE;
+ }
+ else if (pos.col > 0 && linep[pos.col - 1] == '/')
+ {
+ comment_dir = FORWARD;
+ backwards = FALSE;
+ }
+ }
+ }
+
+ /*
+ * If we are not on a comment or the # at the start of a line, then
+ * look for brace anywhere on this line after the cursor.
+ */
+ if (!hash_dir && !comment_dir)
+ {
+ /*
+ * Find the brace under or after the cursor.
+ * If beyond the end of the line, use the last character in
+ * the line.
+ */
+ if (linep[pos.col] == NUL && pos.col)
+ --pos.col;
+ for (;;)
+ {
+ initc = linep[pos.col];
+ if (initc == NUL)
+ break;
+
+ for (ptr = curbuf->b_p_mps; *ptr; ++ptr)
+ {
+ if (*ptr == initc)
+ {
+ findc = ptr[2];
+ backwards = FALSE;
+ break;
+ }
+ ptr += 2;
+ if (*ptr == initc)
+ {
+ findc = ptr[-2];
+ backwards = TRUE;
+ break;
+ }
+ if (!*++ptr)
+ break;
+ }
+ if (findc)
+ break;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ pos.col += (*mb_ptr2len_check)(linep + pos.col);
+ else
+#endif
+ ++pos.col;
+ }
+ if (!findc)
+ {
+ /* no brace in the line, maybe use " #if" then */
+ if (!cpo_match && *skipwhite(linep) == '#')
+ hash_dir = 1;
+ else
+ return NULL;
+ }
+ else if (!cpo_bsl)
+ {
+ int col, bslcnt = 0;
+
+ /* Set "match_escaped" if there are an odd number of
+ * backslashes. */
+ for (col = pos.col; check_prevcol(linep, col, '\\', &col);)
+ bslcnt++;
+ match_escaped = (bslcnt & 1);
+ }
+ }
+ }
+ if (hash_dir)
+ {
+ /*
+ * Look for matching #if, #else, #elif, or #endif
+ */
+ if (oap != NULL)
+ oap->motion_type = MLINE; /* Linewise for this case only */
+ if (initc != '#')
+ {
+ ptr = skipwhite(skipwhite(linep) + 1);
+ if (STRNCMP(ptr, "if", 2) == 0 || STRNCMP(ptr, "el", 2) == 0)
+ hash_dir = 1;
+ else if (STRNCMP(ptr, "endif", 5) == 0)
+ hash_dir = -1;
+ else
+ return NULL;
+ }
+ pos.col = 0;
+ while (!got_int)
+ {
+ if (hash_dir > 0)
+ {
+ if (pos.lnum == curbuf->b_ml.ml_line_count)
+ break;
+ }
+ else if (pos.lnum == 1)
+ break;
+ pos.lnum += hash_dir;
+ linep = ml_get(pos.lnum);
+ line_breakcheck(); /* check for CTRL-C typed */
+ ptr = skipwhite(linep);
+ if (*ptr != '#')
+ continue;
+ pos.col = (colnr_T) (ptr - linep);
+ ptr = skipwhite(ptr + 1);
+ if (hash_dir > 0)
+ {
+ if (STRNCMP(ptr, "if", 2) == 0)
+ count++;
+ else if (STRNCMP(ptr, "el", 2) == 0)
+ {
+ if (count == 0)
+ return &pos;
+ }
+ else if (STRNCMP(ptr, "endif", 5) == 0)
+ {
+ if (count == 0)
+ return &pos;
+ count--;
+ }
+ }
+ else
+ {
+ if (STRNCMP(ptr, "if", 2) == 0)
+ {
+ if (count == 0)
+ return &pos;
+ count--;
+ }
+ else if (initc == '#' && STRNCMP(ptr, "el", 2) == 0)
+ {
+ if (count == 0)
+ return &pos;
+ }
+ else if (STRNCMP(ptr, "endif", 5) == 0)
+ count++;
+ }
+ }
+ return NULL;
+ }
+ }
+
+#ifdef FEAT_RIGHTLEFT
+ /* This is just guessing: when 'rightleft' is set, search for a maching
+ * paren/brace in the other direction. */
+ if (curwin->w_p_rl && vim_strchr((char_u *)"()[]{}<>", initc) != NULL)
+ backwards = !backwards;
+#endif
+
+ do_quotes = -1;
+ start_in_quotes = MAYBE;
+ /* backward search: Check if this line contains a single-line comment */
+ if (backwards && comment_dir)
+ comment_col = check_linecomment(linep);
+ while (!got_int)
+ {
+ /*
+ * Go to the next position, forward or backward. We could use
+ * inc() and dec() here, but that is much slower
+ */
+ if (backwards)
+ {
+ if (pos.col == 0) /* at start of line, go to prev. one */
+ {
+ if (pos.lnum == 1) /* start of file */
+ break;
+ --pos.lnum;
+
+ if (maxtravel && traveled++ > maxtravel)
+ break;
+
+ linep = ml_get(pos.lnum);
+ pos.col = (colnr_T)STRLEN(linep); /* pos.col on trailing NUL */
+ do_quotes = -1;
+ line_breakcheck();
+
+ /* Check if this line contains a single-line comment */
+ if (comment_dir)
+ comment_col = check_linecomment(linep);
+ }
+ else
+ {
+ --pos.col;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ pos.col -= (*mb_head_off)(linep, linep + pos.col);
+#endif
+ }
+ }
+ else /* forward search */
+ {
+ if (linep[pos.col] == NUL) /* at end of line, go to next one */
+ {
+ if (pos.lnum == curbuf->b_ml.ml_line_count) /* end of file */
+ break;
+ ++pos.lnum;
+
+ if (maxtravel && traveled++ > maxtravel)
+ break;
+
+ linep = ml_get(pos.lnum);
+ pos.col = 0;
+ do_quotes = -1;
+ line_breakcheck();
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ pos.col += (*mb_ptr2len_check)(linep + pos.col);
+ else
+#endif
+ ++pos.col;
+ }
+ }
+
+ /*
+ * If FM_BLOCKSTOP given, stop at a '{' or '}' in column 0.
+ */
+ if (pos.col == 0 && (flags & FM_BLOCKSTOP) &&
+ (linep[0] == '{' || linep[0] == '}'))
+ {
+ if (linep[0] == findc && count == 0) /* match! */
+ return &pos;
+ break; /* out of scope */
+ }
+
+ if (comment_dir)
+ {
+ /* Note: comments do not nest, and we ignore quotes in them */
+ /* TODO: ignore comment brackets inside strings */
+ if (comment_dir == FORWARD)
+ {
+ if (linep[pos.col] == '*' && linep[pos.col + 1] == '/')
+ {
+ pos.col++;
+ return &pos;
+ }
+ }
+ else /* Searching backwards */
+ {
+ /*
+ * A comment may contain / * or / /, it may also start or end
+ * with / * /. Ignore a / * after / /.
+ */
+ if (pos.col == 0)
+ continue;
+ else if ( linep[pos.col - 1] == '/'
+ && linep[pos.col] == '*'
+ && (int)pos.col < comment_col)
+ {
+ count++;
+ match_pos = pos;
+ match_pos.col--;
+ }
+ else if (linep[pos.col - 1] == '*' && linep[pos.col] == '/')
+ {
+ if (count > 0)
+ pos = match_pos;
+ else if (pos.col > 1 && linep[pos.col - 2] == '/'
+ && (int)pos.col <= comment_col)
+ pos.col -= 2;
+ else if (ignore_cend)
+ continue;
+ else
+ return NULL;
+ return &pos;
+ }
+ }
+ continue;
+ }
+
+ /*
+ * If smart matching ('cpoptions' does not contain '%'), braces inside
+ * of quotes are ignored, but only if there is an even number of
+ * quotes in the line.
+ */
+ if (cpo_match)
+ do_quotes = 0;
+ else if (do_quotes == -1)
+ {
+ /*
+ * Count the number of quotes in the line, skipping \" and '"'.
+ * Watch out for "\\".
+ */
+ at_start = do_quotes;
+ for (ptr = linep; *ptr; ++ptr)
+ {
+ if (ptr == linep + pos.col + backwards)
+ at_start = (do_quotes & 1);
+ if (*ptr == '"'
+ && (ptr == linep || ptr[-1] != '\'' || ptr[1] != '\''))
+ ++do_quotes;
+ if (*ptr == '\\' && ptr[1] != NUL)
+ ++ptr;
+ }
+ do_quotes &= 1; /* result is 1 with even number of quotes */
+
+ /*
+ * If we find an uneven count, check current line and previous
+ * one for a '\' at the end.
+ */
+ if (!do_quotes)
+ {
+ inquote = FALSE;
+ if (ptr[-1] == '\\')
+ {
+ do_quotes = 1;
+ if (start_in_quotes == MAYBE)
+ {
+ /* Do we need to use at_start here? */
+ inquote = TRUE;
+ start_in_quotes = TRUE;
+ }
+ else if (backwards)
+ inquote = TRUE;
+ }
+ if (pos.lnum > 1)
+ {
+ ptr = ml_get(pos.lnum - 1);
+ if (*ptr && *(ptr + STRLEN(ptr) - 1) == '\\')
+ {
+ do_quotes = 1;
+ if (start_in_quotes == MAYBE)
+ {
+ inquote = at_start;
+ if (inquote)
+ start_in_quotes = TRUE;
+ }
+ else if (!backwards)
+ inquote = TRUE;
+ }
+ }
+ }
+ }
+ if (start_in_quotes == MAYBE)
+ start_in_quotes = FALSE;
+
+ /*
+ * If 'smartmatch' is set:
+ * Things inside quotes are ignored by setting 'inquote'. If we
+ * find a quote without a preceding '\' invert 'inquote'. At the
+ * end of a line not ending in '\' we reset 'inquote'.
+ *
+ * In lines with an uneven number of quotes (without preceding '\')
+ * we do not know which part to ignore. Therefore we only set
+ * inquote if the number of quotes in a line is even, unless this
+ * line or the previous one ends in a '\'. Complicated, isn't it?
+ */
+ switch (c = linep[pos.col])
+ {
+ case NUL:
+ /* at end of line without trailing backslash, reset inquote */
+ if (pos.col == 0 || linep[pos.col - 1] != '\\')
+ {
+ inquote = FALSE;
+ start_in_quotes = FALSE;
+ }
+ break;
+
+ case '"':
+ /* a quote that is preceded with an odd number of backslashes is
+ * ignored */
+ if (do_quotes)
+ {
+ int col;
+
+ for (col = pos.col - 1; col >= 0; --col)
+ if (linep[col] != '\\')
+ break;
+ if ((((int)pos.col - 1 - col) & 1) == 0)
+ {
+ inquote = !inquote;
+ start_in_quotes = FALSE;
+ }
+ }
+ break;
+
+ /*
+ * If smart matching ('cpoptions' does not contain '%'):
+ * Skip things in single quotes: 'x' or '\x'. Be careful for single
+ * single quotes, eg jon's. Things like '\233' or '\x3f' are not
+ * skipped, there is never a brace in them.
+ * Ignore this when finding matches for `'.
+ */
+ case '\'':
+ if (!cpo_match && initc != '\'' && findc != '\'')
+ {
+ if (backwards)
+ {
+ if (pos.col > 1)
+ {
+ if (linep[pos.col - 2] == '\'')
+ {
+ pos.col -= 2;
+ break;
+ }
+ else if (linep[pos.col - 2] == '\\' &&
+ pos.col > 2 && linep[pos.col - 3] == '\'')
+ {
+ pos.col -= 3;
+ break;
+ }
+ }
+ }
+ else if (linep[pos.col + 1]) /* forward search */
+ {
+ if (linep[pos.col + 1] == '\\' &&
+ linep[pos.col + 2] && linep[pos.col + 3] == '\'')
+ {
+ pos.col += 3;
+ break;
+ }
+ else if (linep[pos.col + 2] == '\'')
+ {
+ pos.col += 2;
+ break;
+ }
+ }
+ }
+ /* FALLTHROUGH */
+
+ default:
+#ifdef FEAT_LISP
+ /* For Lisp skip over backslashed (), {} and []. */
+ if (curbuf->b_p_lisp
+ && vim_strchr((char_u *)"(){}[]", c) != NULL
+ && pos.col > 0
+ && check_prevcol(linep, pos.col, '\\', NULL))
+ break;
+#endif
+
+ /* Check for match outside of quotes, and inside of
+ * quotes when the start is also inside of quotes. */
+ if ((!inquote || start_in_quotes == TRUE)
+ && (c == initc || c == findc))
+ {
+ int col, bslcnt = 0;
+
+ if (!cpo_bsl)
+ {
+ for (col = pos.col; check_prevcol(linep, col, '\\', &col);)
+ bslcnt++;
+ }
+ /* Only accept a match when 'M' is in 'cpo' or when ecaping is
+ * what we expect. */
+ if (cpo_bsl || (bslcnt & 1) == match_escaped)
+ {
+ if (c == initc)
+ count++;
+ else
+ {
+ if (count == 0)
+ return &pos;
+ count--;
+ }
+ }
+ }
+ }
+ }
+
+ if (comment_dir == BACKWARD && count > 0)
+ {
+ pos = match_pos;
+ return &pos;
+ }
+ return (pos_T *)NULL; /* never found it */
+}
+
+/*
+ * Check if line[] contains a / / comment.
+ * Return MAXCOL if not, otherwise return the column.
+ * TODO: skip strings.
+ */
+ static int
+check_linecomment(line)
+ char_u *line;
+{
+ char_u *p;
+
+ p = line;
+ while ((p = vim_strchr(p, '/')) != NULL)
+ {
+ if (p[1] == '/')
+ break;
+ ++p;
+ }
+
+ if (p == NULL)
+ return MAXCOL;
+ return (int)(p - line);
+}
+
+/*
+ * Move cursor briefly to character matching the one under the cursor.
+ * Used for Insert mode and "r" command.
+ * Show the match only if it is visible on the screen.
+ * If there isn't a match, then beep.
+ */
+ void
+showmatch(c)
+ int c; /* char to show match for */
+{
+ pos_T *lpos, save_cursor;
+ pos_T mpos;
+ colnr_T vcol;
+ long save_so;
+ long save_siso;
+#ifdef CURSOR_SHAPE
+ int save_state;
+#endif
+ colnr_T save_dollar_vcol;
+ char_u *p;
+
+ /*
+ * Only show match for chars in the 'matchpairs' option.
+ */
+ /* 'matchpairs' is "x:y,x:y" */
+ for (p = curbuf->b_p_mps; *p != NUL; p += 2)
+ {
+#ifdef FEAT_RIGHTLEFT
+ if (*p == c && (curwin->w_p_rl ^ p_ri))
+ break;
+#endif
+ p += 2;
+ if (*p == c
+#ifdef FEAT_RIGHTLEFT
+ && !(curwin->w_p_rl ^ p_ri)
+#endif
+ )
+ break;
+ if (p[1] != ',')
+ return;
+ }
+
+ if ((lpos = findmatch(NULL, NUL)) == NULL) /* no match, so beep */
+ vim_beep();
+ else if (lpos->lnum >= curwin->w_topline)
+ {
+ if (!curwin->w_p_wrap)
+ getvcol(curwin, lpos, NULL, &vcol, NULL);
+ if (curwin->w_p_wrap || (vcol >= curwin->w_leftcol
+ && vcol < curwin->w_leftcol + W_WIDTH(curwin)))
+ {
+ mpos = *lpos; /* save the pos, update_screen() may change it */
+ save_cursor = curwin->w_cursor;
+ save_so = p_so;
+ save_siso = p_siso;
+ /* Handle "$" in 'cpo': If the ')' is typed on top of the "$",
+ * stop displaying the "$". */
+ if (dollar_vcol > 0 && dollar_vcol == curwin->w_virtcol)
+ dollar_vcol = 0;
+ ++curwin->w_virtcol; /* do display ')' just before "$" */
+ update_screen(VALID); /* show the new char first */
+
+ save_dollar_vcol = dollar_vcol;
+#ifdef CURSOR_SHAPE
+ save_state = State;
+ State = SHOWMATCH;
+ ui_cursor_shape(); /* may show different cursor shape */
+#endif
+ curwin->w_cursor = mpos; /* move to matching char */
+ p_so = 0; /* don't use 'scrolloff' here */
+ p_siso = 0; /* don't use 'sidescrolloff' here */
+ showruler(FALSE);
+ setcursor();
+ cursor_on(); /* make sure that the cursor is shown */
+ out_flush();
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ gui_update_cursor(TRUE, FALSE);
+ gui_mch_flush();
+ }
+#endif
+ /* Restore dollar_vcol(), because setcursor() may call curs_rows()
+ * which resets it if the matching position is in a previous line
+ * and has a higher column number. */
+ dollar_vcol = save_dollar_vcol;
+
+ /*
+ * brief pause, unless 'm' is present in 'cpo' and a character is
+ * available.
+ */
+ if (vim_strchr(p_cpo, CPO_SHOWMATCH) != NULL)
+ ui_delay(p_mat * 100L, TRUE);
+ else if (!char_avail())
+ ui_delay(p_mat * 100L, FALSE);
+ curwin->w_cursor = save_cursor; /* restore cursor position */
+ p_so = save_so;
+ p_siso = save_siso;
+#ifdef CURSOR_SHAPE
+ State = save_state;
+ ui_cursor_shape(); /* may show different cursor shape */
+#endif
+ }
+ }
+}
+
+/*
+ * findsent(dir, count) - Find the start of the next sentence in direction
+ * 'dir' Sentences are supposed to end in ".", "!" or "?" followed by white
+ * space or a line break. Also stop at an empty line.
+ * Return OK if the next sentence was found.
+ */
+ int
+findsent(dir, count)
+ int dir;
+ long count;
+{
+ pos_T pos, tpos;
+ int c;
+ int (*func) __ARGS((pos_T *));
+ int startlnum;
+ int noskip = FALSE; /* do not skip blanks */
+ int cpo_J;
+
+ pos = curwin->w_cursor;
+ if (dir == FORWARD)
+ func = incl;
+ else
+ func = decl;
+
+ while (count--)
+ {
+ /*
+ * if on an empty line, skip upto a non-empty line
+ */
+ if (gchar_pos(&pos) == NUL)
+ {
+ do
+ if ((*func)(&pos) == -1)
+ break;
+ while (gchar_pos(&pos) == NUL);
+ if (dir == FORWARD)
+ goto found;
+ }
+ /*
+ * if on the start of a paragraph or a section and searching forward,
+ * go to the next line
+ */
+ else if (dir == FORWARD && pos.col == 0 &&
+ startPS(pos.lnum, NUL, FALSE))
+ {
+ if (pos.lnum == curbuf->b_ml.ml_line_count)
+ return FAIL;
+ ++pos.lnum;
+ goto found;
+ }
+ else if (dir == BACKWARD)
+ decl(&pos);
+
+ /* go back to the previous non-blank char */
+ while ((c = gchar_pos(&pos)) == ' ' || c == '\t' ||
+ (dir == BACKWARD && vim_strchr((char_u *)".!?)]\"'", c) != NULL))
+ {
+ if (decl(&pos) == -1)
+ break;
+ /* when going forward: Stop in front of empty line */
+ if (lineempty(pos.lnum) && dir == FORWARD)
+ {
+ incl(&pos);
+ goto found;
+ }
+ }
+
+ /* remember the line where the search started */
+ startlnum = pos.lnum;
+ cpo_J = vim_strchr(p_cpo, CPO_ENDOFSENT) != NULL;
+
+ for (;;) /* find end of sentence */
+ {
+ c = gchar_pos(&pos);
+ if (c == NUL || (pos.col == 0 && startPS(pos.lnum, NUL, FALSE)))
+ {
+ if (dir == BACKWARD && pos.lnum != startlnum)
+ ++pos.lnum;
+ break;
+ }
+ if (c == '.' || c == '!' || c == '?')
+ {
+ tpos = pos;
+ do
+ if ((c = inc(&tpos)) == -1)
+ break;
+ while (vim_strchr((char_u *)")]\"'", c = gchar_pos(&tpos))
+ != NULL);
+ if (c == -1 || (!cpo_J && (c == ' ' || c == '\t')) || c == NUL
+ || (cpo_J && (c == ' ' && inc(&tpos) >= 0
+ && gchar_pos(&tpos) == ' ')))
+ {
+ pos = tpos;
+ if (gchar_pos(&pos) == NUL) /* skip NUL at EOL */
+ inc(&pos);
+ break;
+ }
+ }
+ if ((*func)(&pos) == -1)
+ {
+ if (count)
+ return FAIL;
+ noskip = TRUE;
+ break;
+ }
+ }
+found:
+ /* skip white space */
+ while (!noskip && ((c = gchar_pos(&pos)) == ' ' || c == '\t'))
+ if (incl(&pos) == -1)
+ break;
+ }
+
+ setpcmark();
+ curwin->w_cursor = pos;
+ return OK;
+}
+
+/*
+ * findpar(dir, count, what) - Find the next paragraph in direction 'dir'
+ * Paragraphs are currently supposed to be separated by empty lines.
+ * Return TRUE if the next paragraph was found.
+ * If 'what' is '{' or '}' we go to the next section.
+ * If 'both' is TRUE also stop at '}'.
+ */
+ int
+findpar(oap, dir, count, what, both)
+ oparg_T *oap;
+ int dir;
+ long count;
+ int what;
+ int both;
+{
+ linenr_T curr;
+ int did_skip; /* TRUE after separating lines have been skipped */
+ int first; /* TRUE on first line */
+#ifdef FEAT_FOLDING
+ linenr_T fold_first; /* first line of a closed fold */
+ linenr_T fold_last; /* last line of a closed fold */
+ int fold_skipped; /* TRUE if a closed fold was skipped this
+ iteration */
+#endif
+
+ curr = curwin->w_cursor.lnum;
+
+ while (count--)
+ {
+ did_skip = FALSE;
+ for (first = TRUE; ; first = FALSE)
+ {
+ if (*ml_get(curr) != NUL)
+ did_skip = TRUE;
+
+#ifdef FEAT_FOLDING
+ /* skip folded lines */
+ fold_skipped = FALSE;
+ if (first && hasFolding(curr, &fold_first, &fold_last))
+ {
+ curr = ((dir > 0) ? fold_last : fold_first) + dir;
+ fold_skipped = TRUE;
+ }
+#endif
+
+ if (!first && did_skip && startPS(curr, what, both))
+ break;
+
+#ifdef FEAT_FOLDING
+ if (fold_skipped)
+ curr -= dir;
+#endif
+ if ((curr += dir) < 1 || curr > curbuf->b_ml.ml_line_count)
+ {
+ if (count)
+ return FALSE;
+ curr -= dir;
+ break;
+ }
+ }
+ }
+ setpcmark();
+ if (both && *ml_get(curr) == '}') /* include line with '}' */
+ ++curr;
+ curwin->w_cursor.lnum = curr;
+ if (curr == curbuf->b_ml.ml_line_count && what != '}')
+ {
+ if ((curwin->w_cursor.col = (colnr_T)STRLEN(ml_get(curr))) != 0)
+ {
+ --curwin->w_cursor.col;
+ oap->inclusive = TRUE;
+ }
+ }
+ else
+ curwin->w_cursor.col = 0;
+ return TRUE;
+}
+
+/*
+ * check if the string 's' is a nroff macro that is in option 'opt'
+ */
+ static int
+inmacro(opt, s)
+ char_u *opt;
+ char_u *s;
+{
+ char_u *macro;
+
+ for (macro = opt; macro[0]; ++macro)
+ {
+ /* Accept two characters in the option being equal to two characters
+ * in the line. A space in the option matches with a space in the
+ * line or the line having ended. */
+ if ( (macro[0] == s[0]
+ || (macro[0] == ' '
+ && (s[0] == NUL || s[0] == ' ')))
+ && (macro[1] == s[1]
+ || ((macro[1] == NUL || macro[1] == ' ')
+ && (s[0] == NUL || s[1] == NUL || s[1] == ' '))))
+ break;
+ ++macro;
+ if (macro[0] == NUL)
+ break;
+ }
+ return (macro[0] != NUL);
+}
+
+/*
+ * startPS: return TRUE if line 'lnum' is the start of a section or paragraph.
+ * If 'para' is '{' or '}' only check for sections.
+ * If 'both' is TRUE also stop at '}'
+ */
+ int
+startPS(lnum, para, both)
+ linenr_T lnum;
+ int para;
+ int both;
+{
+ char_u *s;
+
+ s = ml_get(lnum);
+ if (*s == para || *s == '\f' || (both && *s == '}'))
+ return TRUE;
+ if (*s == '.' && (inmacro(p_sections, s + 1) ||
+ (!para && inmacro(p_para, s + 1))))
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * The following routines do the word searches performed by the 'w', 'W',
+ * 'b', 'B', 'e', and 'E' commands.
+ */
+
+/*
+ * To perform these searches, characters are placed into one of three
+ * classes, and transitions between classes determine word boundaries.
+ *
+ * The classes are:
+ *
+ * 0 - white space
+ * 1 - punctuation
+ * 2 or higher - keyword characters (letters, digits and underscore)
+ */
+
+static int cls_bigword; /* TRUE for "W", "B" or "E" */
+
+/*
+ * cls() - returns the class of character at curwin->w_cursor
+ *
+ * If a 'W', 'B', or 'E' motion is being done (cls_bigword == TRUE), chars
+ * from class 2 and higher are reported as class 1 since only white space
+ * boundaries are of interest.
+ */
+ static int
+cls()
+{
+ int c;
+
+ c = gchar_cursor();
+#ifdef FEAT_FKMAP /* when 'akm' (Farsi mode), take care of Farsi blank */
+ if (p_altkeymap && c == F_BLANK)
+ return 0;
+#endif
+ if (c == ' ' || c == '\t' || c == NUL)
+ return 0;
+#ifdef FEAT_MBYTE
+ if (enc_dbcs != 0 && c > 0xFF)
+ {
+ /* If cls_bigword, report multi-byte chars as class 1. */
+ if (enc_dbcs == DBCS_KOR && cls_bigword)
+ return 1;
+
+ /* process code leading/trailing bytes */
+ return dbcs_class(((unsigned)c >> 8), (c & 0xFF));
+ }
+ if (enc_utf8)
+ {
+ c = utf_class(c);
+ if (c != 0 && cls_bigword)
+ return 1;
+ return c;
+ }
+#endif
+
+ /* If cls_bigword is TRUE, report all non-blanks as class 1. */
+ if (cls_bigword)
+ return 1;
+
+ if (vim_iswordc(c))
+ return 2;
+ return 1;
+}
+
+
+/*
+ * fwd_word(count, type, eol) - move forward one word
+ *
+ * Returns FAIL if the cursor was already at the end of the file.
+ * If eol is TRUE, last word stops at end of line (for operators).
+ */
+ int
+fwd_word(count, bigword, eol)
+ long count;
+ int bigword; /* "W", "E" or "B" */
+ int eol;
+{
+ int sclass; /* starting class */
+ int i;
+ int last_line;
+
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ cls_bigword = bigword;
+ while (--count >= 0)
+ {
+#ifdef FEAT_FOLDING
+ /* When inside a range of folded lines, move to the last char of the
+ * last line. */
+ if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum))
+ coladvance((colnr_T)MAXCOL);
+#endif
+ sclass = cls();
+
+ /*
+ * We always move at least one character, unless on the last
+ * character in the buffer.
+ */
+ last_line = (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count);
+ i = inc_cursor();
+ if (i == -1 || (i >= 1 && last_line)) /* started at last char in file */
+ return FAIL;
+ if (i == 1 && eol && count == 0) /* started at last char in line */
+ return OK;
+
+ /*
+ * Go one char past end of current word (if any)
+ */
+ if (sclass != 0)
+ while (cls() == sclass)
+ {
+ i = inc_cursor();
+ if (i == -1 || (i >= 1 && eol && count == 0))
+ return OK;
+ }
+
+ /*
+ * go to next non-white
+ */
+ while (cls() == 0)
+ {
+ /*
+ * We'll stop if we land on a blank line
+ */
+ if (curwin->w_cursor.col == 0 && *ml_get_curline() == NUL)
+ break;
+
+ i = inc_cursor();
+ if (i == -1 || (i >= 1 && eol && count == 0))
+ return OK;
+ }
+ }
+ return OK;
+}
+
+/*
+ * bck_word() - move backward 'count' words
+ *
+ * If stop is TRUE and we are already on the start of a word, move one less.
+ *
+ * Returns FAIL if top of the file was reached.
+ */
+ int
+bck_word(count, bigword, stop)
+ long count;
+ int bigword;
+ int stop;
+{
+ int sclass; /* starting class */
+
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ cls_bigword = bigword;
+ while (--count >= 0)
+ {
+#ifdef FEAT_FOLDING
+ /* When inside a range of folded lines, move to the first char of the
+ * first line. */
+ if (hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL))
+ curwin->w_cursor.col = 0;
+#endif
+ sclass = cls();
+ if (dec_cursor() == -1) /* started at start of file */
+ return FAIL;
+
+ if (!stop || sclass == cls() || sclass == 0)
+ {
+ /*
+ * Skip white space before the word.
+ * Stop on an empty line.
+ */
+ while (cls() == 0)
+ {
+ if (curwin->w_cursor.col == 0
+ && lineempty(curwin->w_cursor.lnum))
+ goto finished;
+ if (dec_cursor() == -1) /* hit start of file, stop here */
+ return OK;
+ }
+
+ /*
+ * Move backward to start of this word.
+ */
+ if (skip_chars(cls(), BACKWARD))
+ return OK;
+ }
+
+ inc_cursor(); /* overshot - forward one */
+finished:
+ stop = FALSE;
+ }
+ return OK;
+}
+
+/*
+ * end_word() - move to the end of the word
+ *
+ * There is an apparent bug in the 'e' motion of the real vi. At least on the
+ * System V Release 3 version for the 80386. Unlike 'b' and 'w', the 'e'
+ * motion crosses blank lines. When the real vi crosses a blank line in an
+ * 'e' motion, the cursor is placed on the FIRST character of the next
+ * non-blank line. The 'E' command, however, works correctly. Since this
+ * appears to be a bug, I have not duplicated it here.
+ *
+ * Returns FAIL if end of the file was reached.
+ *
+ * If stop is TRUE and we are already on the end of a word, move one less.
+ * If empty is TRUE stop on an empty line.
+ */
+ int
+end_word(count, bigword, stop, empty)
+ long count;
+ int bigword;
+ int stop;
+ int empty;
+{
+ int sclass; /* starting class */
+
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ cls_bigword = bigword;
+ while (--count >= 0)
+ {
+#ifdef FEAT_FOLDING
+ /* When inside a range of folded lines, move to the last char of the
+ * last line. */
+ if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum))
+ coladvance((colnr_T)MAXCOL);
+#endif
+ sclass = cls();
+ if (inc_cursor() == -1)
+ return FAIL;
+
+ /*
+ * If we're in the middle of a word, we just have to move to the end
+ * of it.
+ */
+ if (cls() == sclass && sclass != 0)
+ {
+ /*
+ * Move forward to end of the current word
+ */
+ if (skip_chars(sclass, FORWARD))
+ return FAIL;
+ }
+ else if (!stop || sclass == 0)
+ {
+ /*
+ * We were at the end of a word. Go to the end of the next word.
+ * First skip white space, if 'empty' is TRUE, stop at empty line.
+ */
+ while (cls() == 0)
+ {
+ if (empty && curwin->w_cursor.col == 0
+ && lineempty(curwin->w_cursor.lnum))
+ goto finished;
+ if (inc_cursor() == -1) /* hit end of file, stop here */
+ return FAIL;
+ }
+
+ /*
+ * Move forward to the end of this word.
+ */
+ if (skip_chars(cls(), FORWARD))
+ return FAIL;
+ }
+ dec_cursor(); /* overshot - one char backward */
+finished:
+ stop = FALSE; /* we move only one word less */
+ }
+ return OK;
+}
+
+/*
+ * Move back to the end of the word.
+ *
+ * Returns FAIL if start of the file was reached.
+ */
+ int
+bckend_word(count, bigword, eol)
+ long count;
+ int bigword; /* TRUE for "B" */
+ int eol; /* TRUE: stop at end of line. */
+{
+ int sclass; /* starting class */
+ int i;
+
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ cls_bigword = bigword;
+ while (--count >= 0)
+ {
+ sclass = cls();
+ if ((i = dec_cursor()) == -1)
+ return FAIL;
+ if (eol && i == 1)
+ return OK;
+
+ /*
+ * Move backward to before the start of this word.
+ */
+ if (sclass != 0)
+ {
+ while (cls() == sclass)
+ if ((i = dec_cursor()) == -1 || (eol && i == 1))
+ return OK;
+ }
+
+ /*
+ * Move backward to end of the previous word
+ */
+ while (cls() == 0)
+ {
+ if (curwin->w_cursor.col == 0 && lineempty(curwin->w_cursor.lnum))
+ break;
+ if ((i = dec_cursor()) == -1 || (eol && i == 1))
+ return OK;
+ }
+ }
+ return OK;
+}
+
+/*
+ * Skip a row of characters of the same class.
+ * Return TRUE when end-of-file reached, FALSE otherwise.
+ */
+ static int
+skip_chars(cclass, dir)
+ int cclass;
+ int dir;
+{
+ while (cls() == cclass)
+ if ((dir == FORWARD ? inc_cursor() : dec_cursor()) == -1)
+ return TRUE;
+ return FALSE;
+}
+
+#ifdef FEAT_TEXTOBJ
+/*
+ * Go back to the start of the word or the start of white space
+ */
+ static void
+back_in_line()
+{
+ int sclass; /* starting class */
+
+ sclass = cls();
+ for (;;)
+ {
+ if (curwin->w_cursor.col == 0) /* stop at start of line */
+ break;
+ dec_cursor();
+ if (cls() != sclass) /* stop at start of word */
+ {
+ inc_cursor();
+ break;
+ }
+ }
+}
+
+ static void
+find_first_blank(posp)
+ pos_T *posp;
+{
+ int c;
+
+ while (decl(posp) != -1)
+ {
+ c = gchar_pos(posp);
+ if (!vim_iswhite(c))
+ {
+ incl(posp);
+ break;
+ }
+ }
+}
+
+/*
+ * Skip count/2 sentences and count/2 separating white spaces.
+ */
+ static void
+findsent_forward(count, at_start_sent)
+ long count;
+ int at_start_sent; /* cursor is at start of sentence */
+{
+ while (count--)
+ {
+ findsent(FORWARD, 1L);
+ if (at_start_sent)
+ find_first_blank(&curwin->w_cursor);
+ if (count == 0 || at_start_sent)
+ decl(&curwin->w_cursor);
+ at_start_sent = !at_start_sent;
+ }
+}
+
+/*
+ * Find word under cursor, cursor at end.
+ * Used while an operator is pending, and in Visual mode.
+ */
+ int
+current_word(oap, count, include, bigword)
+ oparg_T *oap;
+ long count;
+ int include; /* TRUE: include word and white space */
+ int bigword; /* FALSE == word, TRUE == WORD */
+{
+ pos_T start_pos;
+ pos_T pos;
+ int inclusive = TRUE;
+ int include_white = FALSE;
+
+ cls_bigword = bigword;
+
+#ifdef FEAT_VISUAL
+ /* Correct cursor when 'selection' is exclusive */
+ if (VIsual_active && *p_sel == 'e' && lt(VIsual, curwin->w_cursor))
+ dec_cursor();
+
+ /*
+ * When Visual mode is not active, or when the VIsual area is only one
+ * character, select the word and/or white space under the cursor.
+ */
+ if (!VIsual_active || equalpos(curwin->w_cursor, VIsual))
+#endif
+ {
+ /*
+ * Go to start of current word or white space.
+ */
+ back_in_line();
+ start_pos = curwin->w_cursor;
+
+ /*
+ * If the start is on white space, and white space should be included
+ * (" word"), or start is not on white space, and white space should
+ * not be included ("word"), find end of word.
+ */
+ if ((cls() == 0) == include)
+ {
+ if (end_word(1L, bigword, TRUE, TRUE) == FAIL)
+ return FAIL;
+ }
+ else
+ {
+ /*
+ * If the start is not on white space, and white space should be
+ * included ("word "), or start is on white space and white
+ * space should not be included (" "), find start of word.
+ * If we end up in the first column of the next line (single char
+ * word) back up to end of the line.
+ */
+ fwd_word(1L, bigword, TRUE);
+ if (curwin->w_cursor.col == 0)
+ decl(&curwin->w_cursor);
+ else
+ oneleft();
+
+ if (include)
+ include_white = TRUE;
+ }
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ /* should do something when inclusive == FALSE ! */
+ VIsual = start_pos;
+ redraw_curbuf_later(INVERTED); /* update the inversion */
+ }
+ else
+#endif
+ {
+ oap->start = start_pos;
+ oap->motion_type = MCHAR;
+ }
+ --count;
+ }
+
+ /*
+ * When count is still > 0, extend with more objects.
+ */
+ while (count > 0)
+ {
+ inclusive = TRUE;
+#ifdef FEAT_VISUAL
+ if (VIsual_active && lt(curwin->w_cursor, VIsual))
+ {
+ /*
+ * In Visual mode, with cursor at start: move cursor back.
+ */
+ if (decl(&curwin->w_cursor) == -1)
+ return FAIL;
+ if (include != (cls() != 0))
+ {
+ if (bck_word(1L, bigword, TRUE) == FAIL)
+ return FAIL;
+ }
+ else
+ {
+ if (bckend_word(1L, bigword, TRUE) == FAIL)
+ return FAIL;
+ (void)incl(&curwin->w_cursor);
+ }
+ }
+ else
+#endif
+ {
+ /*
+ * Move cursor forward one word and/or white area.
+ */
+ if (incl(&curwin->w_cursor) == -1)
+ return FAIL;
+ if (include != (cls() == 0))
+ {
+ if (fwd_word(1L, bigword, TRUE) == FAIL)
+ return FAIL;
+ /*
+ * If end is just past a new-line, we don't want to include
+ * the first character on the line
+ */
+ if (oneleft() == FAIL) /* put cursor on last char of white */
+ inclusive = FALSE;
+ }
+ else
+ {
+ if (end_word(1L, bigword, TRUE, TRUE) == FAIL)
+ return FAIL;
+ }
+ }
+ --count;
+ }
+
+ if (include_white && cls() != 0)
+ {
+ /*
+ * If we don't include white space at the end, move the start
+ * to include some white space there. This makes "daw" work
+ * better on the last word in a sentence (and "2daw" on last-but-one
+ * word). But don't delete white space at start of line (indent).
+ */
+ pos = curwin->w_cursor; /* save cursor position */
+ curwin->w_cursor = start_pos;
+ if (oneleft() == OK)
+ {
+ back_in_line();
+ if (cls() == 0 && curwin->w_cursor.col > 0)
+ {
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ VIsual = curwin->w_cursor;
+ else
+#endif
+ oap->start = curwin->w_cursor;
+ }
+ }
+ curwin->w_cursor = pos; /* put cursor back at end */
+ }
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ if (*p_sel == 'e' && inclusive && ltoreq(VIsual, curwin->w_cursor))
+ inc_cursor();
+ if (VIsual_mode == 'V')
+ {
+ VIsual_mode = 'v';
+ redraw_cmdline = TRUE; /* show mode later */
+ }
+ }
+ else
+#endif
+ oap->inclusive = inclusive;
+
+ return OK;
+}
+
+/*
+ * Find sentence(s) under the cursor, cursor at end.
+ * When Visual active, extend it by one or more sentences.
+ */
+ int
+current_sent(oap, count, include)
+ oparg_T *oap;
+ long count;
+ int include;
+{
+ pos_T start_pos;
+ pos_T pos;
+ int start_blank;
+ int c;
+ int at_start_sent;
+ long ncount;
+
+ start_pos = curwin->w_cursor;
+ pos = start_pos;
+ findsent(FORWARD, 1L); /* Find start of next sentence. */
+
+#ifdef FEAT_VISUAL
+ /*
+ * When visual area is bigger than one character: Extend it.
+ */
+ if (VIsual_active && !equalpos(start_pos, VIsual))
+ {
+extend:
+ if (lt(start_pos, VIsual))
+ {
+ /*
+ * Cursor at start of Visual area.
+ * Find out where we are:
+ * - in the white space before a sentence
+ * - in a sentence or just after it
+ * - at the start of a sentence
+ */
+ at_start_sent = TRUE;
+ decl(&pos);
+ while (lt(pos, curwin->w_cursor))
+ {
+ c = gchar_pos(&pos);
+ if (!vim_iswhite(c))
+ {
+ at_start_sent = FALSE;
+ break;
+ }
+ incl(&pos);
+ }
+ if (!at_start_sent)
+ {
+ findsent(BACKWARD, 1L);
+ if (equalpos(curwin->w_cursor, start_pos))
+ at_start_sent = TRUE; /* exactly at start of sentence */
+ else
+ /* inside a sentence, go to its end (start of next) */
+ findsent(FORWARD, 1L);
+ }
+ if (include) /* "as" gets twice as much as "is" */
+ count *= 2;
+ while (count--)
+ {
+ if (at_start_sent)
+ find_first_blank(&curwin->w_cursor);
+ c = gchar_cursor();
+ if (!at_start_sent || (!include && !vim_iswhite(c)))
+ findsent(BACKWARD, 1L);
+ at_start_sent = !at_start_sent;
+ }
+ }
+ else
+ {
+ /*
+ * Cursor at end of Visual area.
+ * Find out where we are:
+ * - just before a sentence
+ * - just before or in the white space before a sentence
+ * - in a sentence
+ */
+ incl(&pos);
+ at_start_sent = TRUE;
+ if (!equalpos(pos, curwin->w_cursor)) /* not just before a sentence */
+ {
+ at_start_sent = FALSE;
+ while (lt(pos, curwin->w_cursor))
+ {
+ c = gchar_pos(&pos);
+ if (!vim_iswhite(c))
+ {
+ at_start_sent = TRUE;
+ break;
+ }
+ incl(&pos);
+ }
+ if (at_start_sent) /* in the sentence */
+ findsent(BACKWARD, 1L);
+ else /* in/before white before a sentence */
+ curwin->w_cursor = start_pos;
+ }
+
+ if (include) /* "as" gets twice as much as "is" */
+ count *= 2;
+ findsent_forward(count, at_start_sent);
+ if (*p_sel == 'e')
+ ++curwin->w_cursor.col;
+ }
+ return OK;
+ }
+#endif
+
+ /*
+ * If cursor started on blank, check if it is just before the start of the
+ * next sentence.
+ */
+ while (c = gchar_pos(&pos), vim_iswhite(c)) /* vim_iswhite() is a macro */
+ incl(&pos);
+ if (equalpos(pos, curwin->w_cursor))
+ {
+ start_blank = TRUE;
+ find_first_blank(&start_pos); /* go back to first blank */
+ }
+ else
+ {
+ start_blank = FALSE;
+ findsent(BACKWARD, 1L);
+ start_pos = curwin->w_cursor;
+ }
+ if (include)
+ ncount = count * 2;
+ else
+ {
+ ncount = count;
+ if (start_blank)
+ --ncount;
+ }
+ if (ncount)
+ findsent_forward(ncount, TRUE);
+ else
+ decl(&curwin->w_cursor);
+
+ if (include)
+ {
+ /*
+ * If the blank in front of the sentence is included, exclude the
+ * blanks at the end of the sentence, go back to the first blank.
+ * If there are no trailing blanks, try to include leading blanks.
+ */
+ if (start_blank)
+ {
+ find_first_blank(&curwin->w_cursor);
+ c = gchar_pos(&curwin->w_cursor); /* vim_iswhite() is a macro */
+ if (vim_iswhite(c))
+ decl(&curwin->w_cursor);
+ }
+ else if (c = gchar_cursor(), !vim_iswhite(c))
+ find_first_blank(&start_pos);
+ }
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ /* avoid getting stuck with "is" on a single space before a sent. */
+ if (equalpos(start_pos, curwin->w_cursor))
+ goto extend;
+ if (*p_sel == 'e')
+ ++curwin->w_cursor.col;
+ VIsual = start_pos;
+ VIsual_mode = 'v';
+ redraw_curbuf_later(INVERTED); /* update the inversion */
+ }
+ else
+#endif
+ {
+ /* include a newline after the sentence, if there is one */
+ if (incl(&curwin->w_cursor) == -1)
+ oap->inclusive = TRUE;
+ else
+ oap->inclusive = FALSE;
+ oap->start = start_pos;
+ oap->motion_type = MCHAR;
+ }
+ return OK;
+}
+
+ int
+current_block(oap, count, include, what, other)
+ oparg_T *oap;
+ long count;
+ int include; /* TRUE == include white space */
+ int what; /* '(', '{', etc. */
+ int other; /* ')', '}', etc. */
+{
+ pos_T old_pos;
+ pos_T *pos = NULL;
+ pos_T start_pos;
+ pos_T *end_pos;
+ pos_T old_start, old_end;
+ char_u *save_cpo;
+ int sol = FALSE; /* { at start of line */
+
+ old_pos = curwin->w_cursor;
+ old_end = curwin->w_cursor; /* remember where we started */
+ old_start = old_end;
+
+ /*
+ * If we start on '(', '{', ')', '}', etc., use the whole block inclusive.
+ */
+#ifdef FEAT_VISUAL
+ if (!VIsual_active || equalpos(VIsual, curwin->w_cursor))
+#endif
+ {
+ setpcmark();
+ if (what == '{') /* ignore indent */
+ while (inindent(1))
+ if (inc_cursor() != 0)
+ break;
+ if (gchar_cursor() == what) /* cursor on '(' or '{' */
+ ++curwin->w_cursor.col;
+ }
+#ifdef FEAT_VISUAL
+ else if (lt(VIsual, curwin->w_cursor))
+ {
+ old_start = VIsual;
+ curwin->w_cursor = VIsual; /* cursor at low end of Visual */
+ }
+ else
+ old_end = VIsual;
+#endif
+
+ /*
+ * Search backwards for unclosed '(', '{', etc..
+ * Put this position in start_pos.
+ * Ignory quotes here.
+ */
+ save_cpo = p_cpo;
+ p_cpo = (char_u *)"%";
+ while (count-- > 0)
+ {
+ if ((pos = findmatch(NULL, what)) == NULL)
+ break;
+ curwin->w_cursor = *pos;
+ start_pos = *pos; /* the findmatch for end_pos will overwrite *pos */
+ }
+ p_cpo = save_cpo;
+
+ /*
+ * Search for matching ')', '}', etc.
+ * Put this position in curwin->w_cursor.
+ */
+ if (pos == NULL || (end_pos = findmatch(NULL, other)) == NULL)
+ {
+ curwin->w_cursor = old_pos;
+ return FAIL;
+ }
+ curwin->w_cursor = *end_pos;
+
+ /*
+ * Try to exclude the '(', '{', ')', '}', etc. when "include" is FALSE.
+ * If the ending '}' is only preceded by indent, skip that indent.
+ * But only if the resulting area is not smaller than what we started with.
+ */
+ while (!include)
+ {
+ incl(&start_pos);
+ sol = (curwin->w_cursor.col == 0);
+ decl(&curwin->w_cursor);
+ if (what == '{')
+ while (inindent(1))
+ {
+ sol = TRUE;
+ if (decl(&curwin->w_cursor) != 0)
+ break;
+ }
+#ifdef FEAT_VISUAL
+ /*
+ * In Visual mode, when the resulting area is not bigger than what we
+ * started with, extend it to the next block, and then exclude again.
+ */
+ if (!lt(start_pos, old_start) && !lt(old_end, curwin->w_cursor)
+ && VIsual_active)
+ {
+ curwin->w_cursor = old_start;
+ decl(&curwin->w_cursor);
+ if ((pos = findmatch(NULL, what)) == NULL)
+ {
+ curwin->w_cursor = old_pos;
+ return FAIL;
+ }
+ start_pos = *pos;
+ curwin->w_cursor = *pos;
+ if ((end_pos = findmatch(NULL, other)) == NULL)
+ {
+ curwin->w_cursor = old_pos;
+ return FAIL;
+ }
+ curwin->w_cursor = *end_pos;
+ }
+ else
+#endif
+ break;
+ }
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ if (*p_sel == 'e')
+ ++curwin->w_cursor.col;
+ if (sol)
+ inc(&curwin->w_cursor); /* include the line break */
+ VIsual = start_pos;
+ VIsual_mode = 'v';
+ redraw_curbuf_later(INVERTED); /* update the inversion */
+ showmode();
+ }
+ else
+#endif
+ {
+ oap->start = start_pos;
+ oap->motion_type = MCHAR;
+ if (sol)
+ {
+ incl(&curwin->w_cursor);
+ oap->inclusive = FALSE;
+ }
+ else
+ oap->inclusive = TRUE;
+ }
+
+ return OK;
+}
+
+ int
+current_par(oap, count, include, type)
+ oparg_T *oap;
+ long count;
+ int include; /* TRUE == include white space */
+ int type; /* 'p' for paragraph, 'S' for section */
+{
+ linenr_T start_lnum;
+ linenr_T end_lnum;
+ int white_in_front;
+ int dir;
+ int start_is_white;
+ int prev_start_is_white;
+ int retval = OK;
+ int do_white = FALSE;
+ int t;
+ int i;
+
+ if (type == 'S') /* not implemented yet */
+ return FAIL;
+
+ start_lnum = curwin->w_cursor.lnum;
+
+#ifdef FEAT_VISUAL
+ /*
+ * When visual area is more than one line: extend it.
+ */
+ if (VIsual_active && start_lnum != VIsual.lnum)
+ {
+extend:
+ if (start_lnum < VIsual.lnum)
+ dir = BACKWARD;
+ else
+ dir = FORWARD;
+ for (i = count; --i >= 0; )
+ {
+ if (start_lnum ==
+ (dir == BACKWARD ? 1 : curbuf->b_ml.ml_line_count))
+ {
+ retval = FAIL;
+ break;
+ }
+
+ prev_start_is_white = -1;
+ for (t = 0; t < 2; ++t)
+ {
+ start_lnum += dir;
+ start_is_white = linewhite(start_lnum);
+ if (prev_start_is_white == start_is_white)
+ {
+ start_lnum -= dir;
+ break;
+ }
+ for (;;)
+ {
+ if (start_lnum == (dir == BACKWARD
+ ? 1 : curbuf->b_ml.ml_line_count))
+ break;
+ if (start_is_white != linewhite(start_lnum + dir)
+ || (!start_is_white
+ && startPS(start_lnum + (dir > 0
+ ? 1 : 0), 0, 0)))
+ break;
+ start_lnum += dir;
+ }
+ if (!include)
+ break;
+ if (start_lnum == (dir == BACKWARD
+ ? 1 : curbuf->b_ml.ml_line_count))
+ break;
+ prev_start_is_white = start_is_white;
+ }
+ }
+ curwin->w_cursor.lnum = start_lnum;
+ curwin->w_cursor.col = 0;
+ return retval;
+ }
+#endif
+
+ /*
+ * First move back to the start_lnum of the paragraph or white lines
+ */
+ white_in_front = linewhite(start_lnum);
+ while (start_lnum > 1)
+ {
+ if (white_in_front) /* stop at first white line */
+ {
+ if (!linewhite(start_lnum - 1))
+ break;
+ }
+ else /* stop at first non-white line of start of paragraph */
+ {
+ if (linewhite(start_lnum - 1) || startPS(start_lnum, 0, 0))
+ break;
+ }
+ --start_lnum;
+ }
+
+ /*
+ * Move past the end of any white lines.
+ */
+ end_lnum = start_lnum;
+ while (linewhite(end_lnum) && end_lnum < curbuf->b_ml.ml_line_count)
+ ++end_lnum;
+
+ --end_lnum;
+ i = count;
+ if (!include && white_in_front)
+ --i;
+ while (i--)
+ {
+ if (end_lnum == curbuf->b_ml.ml_line_count)
+ return FAIL;
+
+ if (!include)
+ do_white = linewhite(end_lnum + 1);
+
+ if (include || !do_white)
+ {
+ ++end_lnum;
+ /*
+ * skip to end of paragraph
+ */
+ while (end_lnum < curbuf->b_ml.ml_line_count
+ && !linewhite(end_lnum + 1)
+ && !startPS(end_lnum + 1, 0, 0))
+ ++end_lnum;
+ }
+
+ if (i == 0 && white_in_front && include)
+ break;
+
+ /*
+ * skip to end of white lines after paragraph
+ */
+ if (include || do_white)
+ while (end_lnum < curbuf->b_ml.ml_line_count
+ && linewhite(end_lnum + 1))
+ ++end_lnum;
+ }
+
+ /*
+ * If there are no empty lines at the end, try to find some empty lines at
+ * the start (unless that has been done already).
+ */
+ if (!white_in_front && !linewhite(end_lnum) && include)
+ while (start_lnum > 1 && linewhite(start_lnum - 1))
+ --start_lnum;
+
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ /* Problem: when doing "Vipipip" nothing happens in a single white
+ * line, we get stuck there. Trap this here. */
+ if (VIsual_mode == 'V' && start_lnum == curwin->w_cursor.lnum)
+ goto extend;
+ VIsual.lnum = start_lnum;
+ VIsual_mode = 'V';
+ redraw_curbuf_later(INVERTED); /* update the inversion */
+ showmode();
+ }
+ else
+#endif
+ {
+ oap->start.lnum = start_lnum;
+ oap->start.col = 0;
+ oap->motion_type = MLINE;
+ }
+ curwin->w_cursor.lnum = end_lnum;
+ curwin->w_cursor.col = 0;
+
+ return OK;
+}
+#endif
+
+#if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(FEAT_TEXTOBJ) \
+ || defined(PROTO)
+/*
+ * return TRUE if line 'lnum' is empty or has white chars only.
+ */
+ int
+linewhite(lnum)
+ linenr_T lnum;
+{
+ char_u *p;
+
+ p = skipwhite(ml_get(lnum));
+ return (*p == NUL);
+}
+#endif
+
+#if defined(FEAT_FIND_ID) || defined(PROTO)
+/*
+ * Find identifiers or defines in included files.
+ * if p_ic && (continue_status & CONT_SOL) then ptr must be in lowercase.
+ */
+/*ARGSUSED*/
+ void
+find_pattern_in_path(ptr, dir, len, whole, skip_comments,
+ type, count, action, start_lnum, end_lnum)
+ char_u *ptr; /* pointer to search pattern */
+ int dir; /* direction of expansion */
+ int len; /* length of search pattern */
+ int whole; /* match whole words only */
+ int skip_comments; /* don't match inside comments */
+ int type; /* Type of search; are we looking for a type?
+ a macro? */
+ long count;
+ int action; /* What to do when we find it */
+ linenr_T start_lnum; /* first line to start searching */
+ linenr_T end_lnum; /* last line for searching */
+{
+ SearchedFile *files; /* Stack of included files */
+ SearchedFile *bigger; /* When we need more space */
+ int max_path_depth = 50;
+ long match_count = 1;
+
+ char_u *pat;
+ char_u *new_fname;
+ char_u *curr_fname = curbuf->b_fname;
+ char_u *prev_fname = NULL;
+ linenr_T lnum;
+ int depth;
+ int depth_displayed; /* For type==CHECK_PATH */
+ int old_files;
+ int already_searched;
+ char_u *file_line;
+ char_u *line;
+ char_u *p;
+ char_u save_char;
+ int define_matched;
+ regmatch_T regmatch;
+ regmatch_T incl_regmatch;
+ regmatch_T def_regmatch;
+ int matched = FALSE;
+ int did_show = FALSE;
+ int found = FALSE;
+ int i;
+ char_u *already = NULL;
+ char_u *startp = NULL;
+#ifdef RISCOS
+ int previous_munging = __riscosify_control;
+#endif
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ win_T *curwin_save = NULL;
+#endif
+
+ regmatch.regprog = NULL;
+ incl_regmatch.regprog = NULL;
+ def_regmatch.regprog = NULL;
+
+ file_line = alloc(LSIZE);
+ if (file_line == NULL)
+ return;
+
+#ifdef RISCOS
+ /* UnixLib knows best how to munge c file names - turn munging back on. */
+ __riscosify_control = __RISCOSIFY_LONG_TRUNCATE;
+#endif
+
+ if (type != CHECK_PATH && type != FIND_DEFINE
+#ifdef FEAT_INS_EXPAND
+ /* when CONT_SOL is set compare "ptr" with the beginning of the line
+ * is faster than quote_meta/regcomp/regexec "ptr" -- Acevedo */
+ && !(continue_status & CONT_SOL)
+#endif
+ )
+ {
+ pat = alloc(len + 5);
+ if (pat == NULL)
+ goto fpip_end;
+ sprintf((char *)pat, whole ? "\\<%.*s\\>" : "%.*s", len, ptr);
+ /* ignore case according to p_ic, p_scs and pat */
+ regmatch.rm_ic = ignorecase(pat);
+ regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
+ vim_free(pat);
+ if (regmatch.regprog == NULL)
+ goto fpip_end;
+ }
+ if (*curbuf->b_p_inc != NUL || *p_inc != NUL)
+ {
+ incl_regmatch.regprog = vim_regcomp(*curbuf->b_p_inc == NUL
+ ? p_inc : curbuf->b_p_inc, p_magic ? RE_MAGIC : 0);
+ if (incl_regmatch.regprog == NULL)
+ goto fpip_end;
+ incl_regmatch.rm_ic = FALSE; /* don't ignore case in incl. pat. */
+ }
+ if (type == FIND_DEFINE && (*curbuf->b_p_def != NUL || *p_def != NUL))
+ {
+ def_regmatch.regprog = vim_regcomp(*curbuf->b_p_def == NUL
+ ? p_def : curbuf->b_p_def, p_magic ? RE_MAGIC : 0);
+ if (def_regmatch.regprog == NULL)
+ goto fpip_end;
+ def_regmatch.rm_ic = FALSE; /* don't ignore case in define pat. */
+ }
+ files = (SearchedFile *)lalloc_clear((long_u)
+ (max_path_depth * sizeof(SearchedFile)), TRUE);
+ if (files == NULL)
+ goto fpip_end;
+ old_files = max_path_depth;
+ depth = depth_displayed = -1;
+
+ lnum = start_lnum;
+ if (end_lnum > curbuf->b_ml.ml_line_count)
+ end_lnum = curbuf->b_ml.ml_line_count;
+ if (lnum > end_lnum) /* do at least one line */
+ lnum = end_lnum;
+ line = ml_get(lnum);
+
+ for (;;)
+ {
+ if (incl_regmatch.regprog != NULL
+ && vim_regexec(&incl_regmatch, line, (colnr_T)0))
+ {
+ new_fname = file_name_in_line(incl_regmatch.endp[0],
+ 0, FNAME_EXP|FNAME_INCL|FNAME_REL, 1L,
+ curr_fname == curbuf->b_fname
+ ? curbuf->b_ffname : curr_fname);
+ already_searched = FALSE;
+ if (new_fname != NULL)
+ {
+ /* Check whether we have already searched in this file */
+ for (i = 0;; i++)
+ {
+ if (i == depth + 1)
+ i = old_files;
+ if (i == max_path_depth)
+ break;
+ if (fullpathcmp(new_fname, files[i].name, TRUE) & FPC_SAME)
+ {
+ if (type != CHECK_PATH &&
+ action == ACTION_SHOW_ALL && files[i].matched)
+ {
+ msg_putchar('\n'); /* cursor below last one */
+ if (!got_int) /* don't display if 'q'
+ typed at "--more--"
+ mesage */
+ {
+ msg_home_replace_hl(new_fname);
+ MSG_PUTS(_(" (includes previously listed match)"));
+ prev_fname = NULL;
+ }
+ }
+ vim_free(new_fname);
+ new_fname = NULL;
+ already_searched = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (type == CHECK_PATH && (action == ACTION_SHOW_ALL
+ || (new_fname == NULL && !already_searched)))
+ {
+ if (did_show)
+ msg_putchar('\n'); /* cursor below last one */
+ else
+ {
+ gotocmdline(TRUE); /* cursor at status line */
+ MSG_PUTS_TITLE(_("--- Included files "));
+ if (action != ACTION_SHOW_ALL)
+ MSG_PUTS_TITLE(_("not found "));
+ MSG_PUTS_TITLE(_("in path ---\n"));
+ }
+ did_show = TRUE;
+ while (depth_displayed < depth && !got_int)
+ {
+ ++depth_displayed;
+ for (i = 0; i < depth_displayed; i++)
+ MSG_PUTS(" ");
+ msg_home_replace(files[depth_displayed].name);
+ MSG_PUTS(" -->\n");
+ }
+ if (!got_int) /* don't display if 'q' typed
+ for "--more--" message */
+ {
+ for (i = 0; i <= depth_displayed; i++)
+ MSG_PUTS(" ");
+ if (new_fname != NULL)
+ {
+ /* using "new_fname" is more reliable, e.g., when
+ * 'includeexpr' is set. */
+ msg_outtrans_attr(new_fname, hl_attr(HLF_D));
+ }
+ else
+ {
+ /*
+ * Isolate the file name.
+ * Include the surrounding "" or <> if present.
+ */
+ for (p = incl_regmatch.endp[0]; !vim_isfilec(*p); p++)
+ ;
+ for (i = 0; vim_isfilec(p[i]); i++)
+ ;
+ if (i == 0)
+ {
+ /* Nothing found, use the rest of the line. */
+ p = incl_regmatch.endp[0];
+ i = STRLEN(p);
+ }
+ else
+ {
+ if (p[-1] == '"' || p[-1] == '<')
+ {
+ --p;
+ ++i;
+ }
+ if (p[i] == '"' || p[i] == '>')
+ ++i;
+ }
+ save_char = p[i];
+ p[i] = NUL;
+ msg_outtrans_attr(p, hl_attr(HLF_D));
+ p[i] = save_char;
+ }
+
+ if (new_fname == NULL && action == ACTION_SHOW_ALL)
+ {
+ if (already_searched)
+ MSG_PUTS(_(" (Already listed)"));
+ else
+ MSG_PUTS(_(" NOT FOUND"));
+ }
+ }
+ out_flush(); /* output each line directly */
+ }
+
+ if (new_fname != NULL)
+ {
+ /* Push the new file onto the file stack */
+ if (depth + 1 == old_files)
+ {
+ bigger = (SearchedFile *)lalloc((long_u)(
+ max_path_depth * 2 * sizeof(SearchedFile)), TRUE);
+ if (bigger != NULL)
+ {
+ for (i = 0; i <= depth; i++)
+ bigger[i] = files[i];
+ for (i = depth + 1; i < old_files + max_path_depth; i++)
+ {
+ bigger[i].fp = NULL;
+ bigger[i].name = NULL;
+ bigger[i].lnum = 0;
+ bigger[i].matched = FALSE;
+ }
+ for (i = old_files; i < max_path_depth; i++)
+ bigger[i + max_path_depth] = files[i];
+ old_files += max_path_depth;
+ max_path_depth *= 2;
+ vim_free(files);
+ files = bigger;
+ }
+ }
+ if ((files[depth + 1].fp = mch_fopen((char *)new_fname, "r"))
+ == NULL)
+ vim_free(new_fname);
+ else
+ {
+ if (++depth == old_files)
+ {
+ /*
+ * lalloc() for 'bigger' must have failed above. We
+ * will forget one of our already visited files now.
+ */
+ vim_free(files[old_files].name);
+ ++old_files;
+ }
+ files[depth].name = curr_fname = new_fname;
+ files[depth].lnum = 0;
+ files[depth].matched = FALSE;
+#ifdef FEAT_INS_EXPAND
+ if (action == ACTION_EXPAND)
+ {
+ sprintf((char*)IObuff, _("Scanning included file: %s"),
+ (char *)new_fname);
+ msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
+ }
+#endif
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Check if the line is a define (type == FIND_DEFINE)
+ */
+ p = line;
+search_line:
+ define_matched = FALSE;
+ if (def_regmatch.regprog != NULL
+ && vim_regexec(&def_regmatch, line, (colnr_T)0))
+ {
+ /*
+ * Pattern must be first identifier after 'define', so skip
+ * to that position before checking for match of pattern. Also
+ * don't let it match beyond the end of this identifier.
+ */
+ p = def_regmatch.endp[0];
+ while (*p && !vim_iswordc(*p))
+ p++;
+ define_matched = TRUE;
+ }
+
+ /*
+ * Look for a match. Don't do this if we are looking for a
+ * define and this line didn't match define_prog above.
+ */
+ if (def_regmatch.regprog == NULL || define_matched)
+ {
+ if (define_matched
+#ifdef FEAT_INS_EXPAND
+ || (continue_status & CONT_SOL)
+#endif
+ )
+ {
+ /* compare the first "len" chars from "ptr" */
+ startp = skipwhite(p);
+ if (p_ic)
+ matched = !MB_STRNICMP(startp, ptr, len);
+ else
+ matched = !STRNCMP(startp, ptr, len);
+ if (matched && define_matched && whole
+ && vim_iswordc(startp[len]))
+ matched = FALSE;
+ }
+ else if (regmatch.regprog != NULL
+ && vim_regexec(&regmatch, line, (colnr_T)(p - line)))
+ {
+ matched = TRUE;
+ startp = regmatch.startp[0];
+ /*
+ * Check if the line is not a comment line (unless we are
+ * looking for a define). A line starting with "# define"
+ * is not considered to be a comment line.
+ */
+ if (!define_matched && skip_comments)
+ {
+#ifdef FEAT_COMMENTS
+ if ((*line != '#' ||
+ STRNCMP(skipwhite(line + 1), "define", 6) != 0)
+ && get_leader_len(line, NULL, FALSE))
+ matched = FALSE;
+
+ /*
+ * Also check for a "/ *" or "/ /" before the match.
+ * Skips lines like "int backwards; / * normal index
+ * * /" when looking for "normal".
+ * Note: Doesn't skip "/ *" in comments.
+ */
+ p = skipwhite(line);
+ if (matched
+ || (p[0] == '/' && p[1] == '*') || p[0] == '*')
+#endif
+ for (p = line; *p && p < startp; ++p)
+ {
+ if (matched
+ && p[0] == '/'
+ && (p[1] == '*' || p[1] == '/'))
+ {
+ matched = FALSE;
+ /* After "//" all text is comment */
+ if (p[1] == '/')
+ break;
+ ++p;
+ }
+ else if (!matched && p[0] == '*' && p[1] == '/')
+ {
+ /* Can find match after "* /". */
+ matched = TRUE;
+ ++p;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (matched)
+ {
+#ifdef FEAT_INS_EXPAND
+ if (action == ACTION_EXPAND)
+ {
+ int reuse = 0;
+ int add_r;
+ char_u *aux;
+
+ if (depth == -1 && lnum == curwin->w_cursor.lnum)
+ break;
+ found = TRUE;
+ aux = p = startp;
+ if (continue_status & CONT_ADDING)
+ {
+ p += completion_length;
+ if (vim_iswordp(p))
+ goto exit_matched;
+ p = find_word_start(p);
+ }
+ p = find_word_end(p);
+ i = (int)(p - aux);
+
+ if ((continue_status & CONT_ADDING) && i == completion_length)
+ {
+ /* get the next line */
+ /* IOSIZE > completion_length, so the STRNCPY works */
+ STRNCPY(IObuff, aux, i);
+ if (!( depth < 0
+ && lnum < end_lnum
+ && (line = ml_get(++lnum)) != NULL)
+ && !( depth >= 0
+ && !vim_fgets(line = file_line,
+ LSIZE, files[depth].fp)))
+ goto exit_matched;
+
+ /* we read a line, set "already" to check this "line" later
+ * if depth >= 0 we'll increase files[depth].lnum far
+ * bellow -- Acevedo */
+ already = aux = p = skipwhite(line);
+ p = find_word_start(p);
+ p = find_word_end(p);
+ if (p > aux)
+ {
+ if (*aux != ')' && IObuff[i-1] != TAB)
+ {
+ if (IObuff[i-1] != ' ')
+ IObuff[i++] = ' ';
+ /* IObuf =~ "\(\k\|\i\).* ", thus i >= 2*/
+ if (p_js
+ && (IObuff[i-2] == '.'
+ || (vim_strchr(p_cpo, CPO_JOINSP) == NULL
+ && (IObuff[i-2] == '?'
+ || IObuff[i-2] == '!'))))
+ IObuff[i++] = ' ';
+ }
+ /* copy as much as posible of the new word */
+ if (p - aux >= IOSIZE - i)
+ p = aux + IOSIZE - i - 1;
+ STRNCPY(IObuff + i, aux, p - aux);
+ i += (int)(p - aux);
+ reuse |= CONT_S_IPOS;
+ }
+ IObuff[i] = NUL;
+ aux = IObuff;
+
+ if (i == completion_length)
+ goto exit_matched;
+ }
+
+ add_r = ins_compl_add_infercase(aux, i,
+ curr_fname == curbuf->b_fname ? NULL : curr_fname,
+ dir, reuse);
+ if (add_r == OK)
+ /* if dir was BACKWARD then honor it just once */
+ dir = FORWARD;
+ else if (add_r == RET_ERROR)
+ break;
+ }
+ else
+#endif
+ if (action == ACTION_SHOW_ALL)
+ {
+ found = TRUE;
+ if (!did_show)
+ gotocmdline(TRUE); /* cursor at status line */
+ if (curr_fname != prev_fname)
+ {
+ if (did_show)
+ msg_putchar('\n'); /* cursor below last one */
+ if (!got_int) /* don't display if 'q' typed
+ at "--more--" mesage */
+ msg_home_replace_hl(curr_fname);
+ prev_fname = curr_fname;
+ }
+ did_show = TRUE;
+ if (!got_int)
+ show_pat_in_path(line, type, TRUE, action,
+ (depth == -1) ? NULL : files[depth].fp,
+ (depth == -1) ? &lnum : &files[depth].lnum,
+ match_count++);
+
+ /* Set matched flag for this file and all the ones that
+ * include it */
+ for (i = 0; i <= depth; ++i)
+ files[i].matched = TRUE;
+ }
+ else if (--count <= 0)
+ {
+ found = TRUE;
+ if (depth == -1 && lnum == curwin->w_cursor.lnum
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ && g_do_tagpreview == 0
+#endif
+ )
+ EMSG(_("E387: Match is on current line"));
+ else if (action == ACTION_SHOW)
+ {
+ show_pat_in_path(line, type, did_show, action,
+ (depth == -1) ? NULL : files[depth].fp,
+ (depth == -1) ? &lnum : &files[depth].lnum, 1L);
+ did_show = TRUE;
+ }
+ else
+ {
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ /* ":psearch" uses the preview window */
+ if (g_do_tagpreview != 0)
+ {
+ curwin_save = curwin;
+ prepare_tagpreview();
+ }
+#endif
+ if (action == ACTION_SPLIT)
+ {
+#ifdef FEAT_WINDOWS
+ if (win_split(0, 0) == FAIL)
+#endif
+ break;
+#ifdef FEAT_SCROLLBIND
+ curwin->w_p_scb = FALSE;
+#endif
+ }
+ if (depth == -1)
+ {
+ /* match in current file */
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ if (g_do_tagpreview != 0)
+ {
+ if (getfile(0, curwin_save->w_buffer->b_fname,
+ NULL, TRUE, lnum, FALSE) > 0)
+ break; /* failed to jump to file */
+ }
+ else
+#endif
+ setpcmark();
+ curwin->w_cursor.lnum = lnum;
+ }
+ else
+ {
+ if (getfile(0, files[depth].name, NULL, TRUE,
+ files[depth].lnum, FALSE) > 0)
+ break; /* failed to jump to file */
+ /* autocommands may have changed the lnum, we don't
+ * want that here */
+ curwin->w_cursor.lnum = files[depth].lnum;
+ }
+ }
+ if (action != ACTION_SHOW)
+ {
+ curwin->w_cursor.col = (colnr_T) (startp - line);
+ curwin->w_set_curswant = TRUE;
+ }
+
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ if (g_do_tagpreview != 0
+ && curwin != curwin_save && win_valid(curwin_save))
+ {
+ /* Return cursor to where we were */
+ validate_cursor();
+ redraw_later(VALID);
+ win_enter(curwin_save, TRUE);
+ }
+#endif
+ break;
+ }
+#ifdef FEAT_INS_EXPAND
+exit_matched:
+#endif
+ matched = FALSE;
+ /* look for other matches in the rest of the line if we
+ * are not at the end of it already */
+ if (def_regmatch.regprog == NULL
+#ifdef FEAT_INS_EXPAND
+ && action == ACTION_EXPAND
+ && !(continue_status & CONT_SOL)
+#endif
+ && *(p = startp + 1))
+ goto search_line;
+ }
+ line_breakcheck();
+#ifdef FEAT_INS_EXPAND
+ if (action == ACTION_EXPAND)
+ ins_compl_check_keys();
+ if (got_int || completion_interrupted)
+#else
+ if (got_int)
+#endif
+ break;
+
+ /*
+ * Read the next line. When reading an included file and encountering
+ * end-of-file, close the file and continue in the file that included
+ * it.
+ */
+ while (depth >= 0 && !already
+ && vim_fgets(line = file_line, LSIZE, files[depth].fp))
+ {
+ fclose(files[depth].fp);
+ --old_files;
+ files[old_files].name = files[depth].name;
+ files[old_files].matched = files[depth].matched;
+ --depth;
+ curr_fname = (depth == -1) ? curbuf->b_fname
+ : files[depth].name;
+ if (depth < depth_displayed)
+ depth_displayed = depth;
+ }
+ if (depth >= 0) /* we could read the line */
+ files[depth].lnum++;
+ else if (!already)
+ {
+ if (++lnum > end_lnum)
+ break;
+ line = ml_get(lnum);
+ }
+ already = NULL;
+ }
+ /* End of big for (;;) loop. */
+
+ /* Close any files that are still open. */
+ for (i = 0; i <= depth; i++)
+ {
+ fclose(files[i].fp);
+ vim_free(files[i].name);
+ }
+ for (i = old_files; i < max_path_depth; i++)
+ vim_free(files[i].name);
+ vim_free(files);
+
+ if (type == CHECK_PATH)
+ {
+ if (!did_show)
+ {
+ if (action != ACTION_SHOW_ALL)
+ MSG(_("All included files were found"));
+ else
+ MSG(_("No included files"));
+ }
+ }
+ else if (!found
+#ifdef FEAT_INS_EXPAND
+ && action != ACTION_EXPAND
+#endif
+ )
+ {
+#ifdef FEAT_INS_EXPAND
+ if (got_int || completion_interrupted)
+#else
+ if (got_int)
+#endif
+ EMSG(_(e_interr));
+ else if (type == FIND_DEFINE)
+ EMSG(_("E388: Couldn't find definition"));
+ else
+ EMSG(_("E389: Couldn't find pattern"));
+ }
+ if (action == ACTION_SHOW || action == ACTION_SHOW_ALL)
+ msg_end();
+
+fpip_end:
+ vim_free(file_line);
+ vim_free(regmatch.regprog);
+ vim_free(incl_regmatch.regprog);
+ vim_free(def_regmatch.regprog);
+
+#ifdef RISCOS
+ /* Restore previous file munging state. */
+ __riscosify_control = previous_munging;
+#endif
+}
+
+ static void
+show_pat_in_path(line, type, did_show, action, fp, lnum, count)
+ char_u *line;
+ int type;
+ int did_show;
+ int action;
+ FILE *fp;
+ linenr_T *lnum;
+ long count;
+{
+ char_u *p;
+
+ if (did_show)
+ msg_putchar('\n'); /* cursor below last one */
+ else
+ gotocmdline(TRUE); /* cursor at status line */
+ if (got_int) /* 'q' typed at "--more--" message */
+ return;
+ for (;;)
+ {
+ p = line + STRLEN(line) - 1;
+ if (fp != NULL)
+ {
+ /* We used fgets(), so get rid of newline at end */
+ if (p >= line && *p == '\n')
+ --p;
+ if (p >= line && *p == '\r')
+ --p;
+ *(p + 1) = NUL;
+ }
+ if (action == ACTION_SHOW_ALL)
+ {
+ sprintf((char *)IObuff, "%3ld: ", count); /* show match nr */
+ msg_puts(IObuff);
+ sprintf((char *)IObuff, "%4ld", *lnum); /* show line nr */
+ /* Highlight line numbers */
+ msg_puts_attr(IObuff, hl_attr(HLF_N));
+ MSG_PUTS(" ");
+ }
+ msg_prt_line(line);
+ out_flush(); /* show one line at a time */
+
+ /* Definition continues until line that doesn't end with '\' */
+ if (got_int || type != FIND_DEFINE || p < line || *p != '\\')
+ break;
+
+ if (fp != NULL)
+ {
+ if (vim_fgets(line, LSIZE, fp)) /* end of file */
+ break;
+ ++*lnum;
+ }
+ else
+ {
+ if (++*lnum > curbuf->b_ml.ml_line_count)
+ break;
+ line = ml_get(*lnum);
+ }
+ msg_putchar('\n');
+ }
+}
+#endif
+
+#ifdef FEAT_VIMINFO
+ int
+read_viminfo_search_pattern(virp, force)
+ vir_T *virp;
+ int force;
+{
+ char_u *lp;
+ int idx = -1;
+ int magic = FALSE;
+ int no_scs = FALSE;
+ int off_line = FALSE;
+ int off_end = FALSE;
+ long off = 0;
+ int setlast = FALSE;
+#ifdef FEAT_SEARCH_EXTRA
+ static int hlsearch_on = FALSE;
+#endif
+ char_u *val;
+
+ /*
+ * Old line types:
+ * "/pat", "&pat": search/subst. pat
+ * "~/pat", "~&pat": last used search/subst. pat
+ * New line types:
+ * "~h", "~H": hlsearch highlighting off/on
+ * "~<magic><smartcase><line><end><off><last><which>pat"
+ * <magic>: 'm' off, 'M' on
+ * <smartcase>: 's' off, 'S' on
+ * <line>: 'L' line offset, 'l' char offset
+ * <end>: 'E' from end, 'e' from start
+ * <off>: decimal, offset
+ * <last>: '~' last used pattern
+ * <which>: '/' search pat, '&' subst. pat
+ */
+ lp = virp->vir_line;
+ if (lp[0] == '~' && (lp[1] == 'm' || lp[1] == 'M')) /* new line type */
+ {
+ if (lp[1] == 'M') /* magic on */
+ magic = TRUE;
+ if (lp[2] == 's')
+ no_scs = TRUE;
+ if (lp[3] == 'L')
+ off_line = TRUE;
+ if (lp[4] == 'E')
+ off_end = TRUE;
+ lp += 5;
+ off = getdigits(&lp);
+ }
+ if (lp[0] == '~') /* use this pattern for last-used pattern */
+ {
+ setlast = TRUE;
+ lp++;
+ }
+ if (lp[0] == '/')
+ idx = RE_SEARCH;
+ else if (lp[0] == '&')
+ idx = RE_SUBST;
+#ifdef FEAT_SEARCH_EXTRA
+ else if (lp[0] == 'h') /* ~h: 'hlsearch' highlighting off */
+ hlsearch_on = FALSE;
+ else if (lp[0] == 'H') /* ~H: 'hlsearch' highlighting on */
+ hlsearch_on = TRUE;
+#endif
+ if (idx >= 0)
+ {
+ if (force || spats[idx].pat == NULL)
+ {
+ val = viminfo_readstring(virp, (int)(lp - virp->vir_line + 1),
+ TRUE);
+ if (val != NULL)
+ {
+ set_last_search_pat(val, idx, magic, setlast);
+ vim_free(val);
+ spats[idx].no_scs = no_scs;
+ spats[idx].off.line = off_line;
+ spats[idx].off.end = off_end;
+ spats[idx].off.off = off;
+#ifdef FEAT_SEARCH_EXTRA
+ if (setlast)
+ no_hlsearch = !hlsearch_on;
+#endif
+ }
+ }
+ }
+ return viminfo_readline(virp);
+}
+
+ void
+write_viminfo_search_pattern(fp)
+ FILE *fp;
+{
+ if (get_viminfo_parameter('/') != 0)
+ {
+#ifdef FEAT_SEARCH_EXTRA
+ fprintf(fp, "\n# hlsearch on (H) or off (h):\n~%c",
+ (no_hlsearch || find_viminfo_parameter('h') != NULL) ? 'h' : 'H');
+#endif
+ wvsp_one(fp, RE_SEARCH, "", '/');
+ wvsp_one(fp, RE_SUBST, "Substitute ", '&');
+ }
+}
+
+ static void
+wvsp_one(fp, idx, s, sc)
+ FILE *fp; /* file to write to */
+ int idx; /* spats[] index */
+ char *s; /* search pat */
+ int sc; /* dir char */
+{
+ if (spats[idx].pat != NULL)
+ {
+ fprintf(fp, "\n# Last %sSearch Pattern:\n~", s);
+ /* off.dir is not stored, it's reset to forward */
+ fprintf(fp, "%c%c%c%c%ld%s%c",
+ spats[idx].magic ? 'M' : 'm', /* magic */
+ spats[idx].no_scs ? 's' : 'S', /* smartcase */
+ spats[idx].off.line ? 'L' : 'l', /* line offset */
+ spats[idx].off.end ? 'E' : 'e', /* offset from end */
+ spats[idx].off.off, /* offset */
+ last_idx == idx ? "~" : "", /* last used pat */
+ sc);
+ viminfo_writestring(fp, spats[idx].pat);
+ }
+}
+#endif /* FEAT_VIMINFO */
diff --git a/src/structs.h b/src/structs.h
new file mode 100644
index 000000000..ac0a795cb
--- /dev/null
+++ b/src/structs.h
@@ -0,0 +1,1887 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * This file contains various definitions of structures that are used by Vim
+ */
+
+/*
+ * There is something wrong in the SAS compiler that makes typedefs not
+ * valid in include files. Has been fixed in version 6.58.
+ */
+#if defined(SASC) && SASC < 658
+typedef long linenr_T;
+typedef unsigned colnr_T;
+typedef unsigned short short_u;
+#endif
+
+/*
+ * position in file or buffer
+ */
+typedef struct
+{
+ linenr_T lnum; /* line number */
+ colnr_T col; /* column number */
+#ifdef FEAT_VIRTUALEDIT
+ colnr_T coladd;
+#endif
+} pos_T;
+
+#ifdef FEAT_VIRTUALEDIT
+# define INIT_POS_T {0, 0, 0}
+#else
+# define INIT_POS_T {0, 0}
+#endif
+
+/*
+ * Same, but without coladd.
+ */
+typedef struct
+{
+ linenr_T lnum; /* line number */
+ colnr_T col; /* column number */
+} lpos_T;
+
+/*
+ * Structure used for growing arrays.
+ * This is used to store information that only grows, is deleted all at
+ * once, and needs to be accessed by index. See ga_clear() and ga_grow().
+ */
+typedef struct growarray
+{
+ int ga_len; /* current number of items used */
+ int ga_room; /* number of unused items at the end */
+ int ga_itemsize; /* sizeof one item */
+ int ga_growsize; /* number of items to grow each time */
+ void *ga_data; /* pointer to the first item */
+} garray_T;
+
+#define GA_EMPTY {0, 0, 0, 0, NULL}
+
+/*
+ * This is here because regexp.h needs pos_T and below regprog_T is used.
+ */
+#include "regexp.h"
+
+typedef struct window win_T;
+typedef struct wininfo wininfo_T;
+typedef struct frame frame_T;
+typedef int scid_T; /* script ID */
+
+/*
+ * This is here because gui.h needs the pos_T and win_T, and win_T needs gui.h
+ * for scrollbar_T.
+ */
+#ifdef FEAT_GUI
+# include "gui.h"
+#else
+# ifdef FEAT_XCLIPBOARD
+# include <X11/Intrinsic.h>
+# endif
+# define guicolor_T int /* avoid error in prototypes */
+#endif
+
+/*
+ * marks: positions in a file
+ * (a normal mark is a lnum/col pair, the same as a file position)
+ */
+
+/* (Note: for EBCDIC there are more than 26, because there are gaps in the
+ * alphabet coding. To minimize changes to the code, I decided to just
+ * increase the number of possible marks. */
+#define NMARKS ('z' - 'a' + 1) /* max. # of named marks */
+#define JUMPLISTSIZE 100 /* max. # of marks in jump list */
+#define TAGSTACKSIZE 20 /* max. # of tags in tag stack */
+
+typedef struct filemark
+{
+ pos_T mark; /* cursor position */
+ int fnum; /* file number */
+} fmark_T;
+
+/* Xtended file mark: also has a file name */
+typedef struct xfilemark
+{
+ fmark_T fmark;
+ char_u *fname; /* file name, used when fnum == 0 */
+} xfmark_T;
+
+/*
+ * The taggy struct is used to store the information about a :tag command.
+ */
+typedef struct taggy
+{
+ char_u *tagname; /* tag name */
+ fmark_T fmark; /* cursor position BEFORE ":tag" */
+ int cur_match; /* match number */
+ int cur_fnum; /* buffer number used for cur_match */
+} taggy_T;
+
+/*
+ * Structure that contains all options that are local to a window.
+ * Used twice in a window: for the current buffer and for all buffers.
+ * Also used in wininfo_T.
+ */
+typedef struct
+{
+#ifdef FEAT_ARABIC
+ int wo_arab;
+# define w_p_arab w_onebuf_opt.wo_arab /* 'arabic' */
+#endif
+#ifdef FEAT_DIFF
+ int wo_diff;
+# define w_p_diff w_onebuf_opt.wo_diff /* 'diff' */
+#endif
+#ifdef FEAT_FOLDING
+ long wo_fdc;
+# define w_p_fdc w_onebuf_opt.wo_fdc /* 'foldcolumn' */
+ int wo_fen;
+# define w_p_fen w_onebuf_opt.wo_fen /* 'foldenable' */
+ char_u *wo_fdi;
+# define w_p_fdi w_onebuf_opt.wo_fdi /* 'foldignore' */
+ long wo_fdl;
+# define w_p_fdl w_onebuf_opt.wo_fdl /* 'foldlevel' */
+ char_u *wo_fdm;
+# define w_p_fdm w_onebuf_opt.wo_fdm /* 'foldmethod' */
+ long wo_fml;
+# define w_p_fml w_onebuf_opt.wo_fml /* 'foldminlines' */
+ long wo_fdn;
+# define w_p_fdn w_onebuf_opt.wo_fdn /* 'foldnextmax' */
+# ifdef FEAT_EVAL
+ char_u *wo_fde;
+# define w_p_fde w_onebuf_opt.wo_fde /* 'foldexpr' */
+ char_u *wo_fdt;
+# define w_p_fdt w_onebuf_opt.wo_fdt /* 'foldtext' */
+# endif
+ char_u *wo_fmr;
+# define w_p_fmr w_onebuf_opt.wo_fmr /* 'foldmarker' */
+#endif
+#ifdef FEAT_LINEBREAK
+ int wo_lbr;
+# define w_p_lbr w_onebuf_opt.wo_lbr /* 'linebreak' */
+#endif
+ int wo_list;
+#define w_p_list w_onebuf_opt.wo_list /* 'list' */
+ int wo_nu;
+#define w_p_nu w_onebuf_opt.wo_nu /* 'number' */
+#if defined(FEAT_WINDOWS)
+ int wo_wfh;
+# define w_p_wfh w_onebuf_opt.wo_wfh /* 'winfixheight' */
+#endif
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ int wo_pvw;
+# define w_p_pvw w_onebuf_opt.wo_pvw /* 'previewwindow' */
+#endif
+#ifdef FEAT_RIGHTLEFT
+ int wo_rl;
+# define w_p_rl w_onebuf_opt.wo_rl /* 'rightleft' */
+ char_u *wo_rlc;
+# define w_p_rlc w_onebuf_opt.wo_rlc /* 'rightleftcmd' */
+#endif
+ long wo_scr;
+#define w_p_scr w_onebuf_opt.wo_scr /* 'scroll' */
+#ifdef FEAT_SCROLLBIND
+ int wo_scb;
+# define w_p_scb w_onebuf_opt.wo_scb /* 'scrollbind' */
+#endif
+ int wo_wrap;
+#define w_p_wrap w_onebuf_opt.wo_wrap /* 'wrap' */
+} winopt_T;
+
+/*
+ * Window info stored with a buffer.
+ *
+ * Two types of info are kept for a buffer which are associated with a
+ * specific window:
+ * 1. Each window can have a different line number associated with a buffer.
+ * 2. The window-local options for a buffer work in a similar way.
+ * The window-info is kept in a list at b_wininfo. It is kept in
+ * most-recently-used order.
+ */
+struct wininfo
+{
+ wininfo_T *wi_next; /* next entry or NULL for last entry */
+ wininfo_T *wi_prev; /* previous entry or NULL for first entry */
+ win_T *wi_win; /* pointer to window that did set wi_lnum */
+ pos_T wi_fpos; /* last cursor position in the file */
+ int wi_optset; /* TRUE when wi_opt has useful values */
+ winopt_T wi_opt; /* local window options */
+#ifdef FEAT_FOLDING
+ int wi_fold_manual; /* copy of w_fold_manual */
+ garray_T wi_folds; /* clone of w_folds */
+#endif
+};
+
+/*
+ * Info used to pass info about a fold from the fold-detection code to the
+ * code that displays the foldcolumn.
+ */
+typedef struct foldinfo
+{
+ int fi_level; /* level of the fold; when this is zero the
+ other fields are invalid */
+ int fi_lnum; /* line number where fold starts */
+ int fi_low_level; /* lowest fold level that starts in the same
+ line */
+} foldinfo_T;
+
+/*
+ * stuctures used for undo
+ */
+
+typedef struct u_entry u_entry_T;
+typedef struct u_header u_header_T;
+struct u_entry
+{
+ u_entry_T *ue_next; /* pointer to next entry in list */
+ linenr_T ue_top; /* number of line above undo block */
+ linenr_T ue_bot; /* number of line below undo block */
+ linenr_T ue_lcount; /* linecount when u_save called */
+ char_u **ue_array; /* array of lines in undo block */
+ long ue_size; /* number of lines in ue_array */
+};
+
+struct u_header
+{
+ u_header_T *uh_next; /* pointer to next header in list */
+ u_header_T *uh_prev; /* pointer to previous header in list */
+ u_entry_T *uh_entry; /* pointer to first entry */
+ u_entry_T *uh_getbot_entry; /* pointer to where ue_bot must be set */
+ pos_T uh_cursor; /* cursor position before saving */
+#ifdef FEAT_VIRTUALEDIT
+ long uh_cursor_vcol;
+#endif
+ int uh_flags; /* see below */
+ pos_T uh_namedm[NMARKS]; /* marks before undo/after redo */
+};
+
+/* values for uh_flags */
+#define UH_CHANGED 0x01 /* b_changed flag before undo/after redo */
+#define UH_EMPTYBUF 0x02 /* buffer was empty */
+
+/*
+ * stuctures used in undo.c
+ */
+#if SIZEOF_INT > 2
+# define ALIGN_LONG /* longword alignment and use filler byte */
+# define ALIGN_SIZE (sizeof(long))
+#else
+# define ALIGN_SIZE (sizeof(short))
+#endif
+
+#define ALIGN_MASK (ALIGN_SIZE - 1)
+
+typedef struct m_info minfo_T;
+
+/*
+ * stucture used to link chunks in one of the free chunk lists.
+ */
+struct m_info
+{
+#ifdef ALIGN_LONG
+ long_u m_size; /* size of the chunk (including m_info) */
+#else
+ short_u m_size; /* size of the chunk (including m_info) */
+#endif
+ minfo_T *m_next; /* pointer to next free chunk in the list */
+};
+
+/*
+ * structure used to link blocks in the list of allocated blocks.
+ */
+typedef struct m_block mblock_T;
+struct m_block
+{
+ mblock_T *mb_next; /* pointer to next allocated block */
+ size_t mb_size; /* total size of all chunks in this block */
+ minfo_T mb_info; /* head of free chuck list for this block */
+};
+
+/*
+ * things used in memfile.c
+ */
+
+typedef struct block_hdr bhdr_T;
+typedef struct memfile memfile_T;
+typedef long blocknr_T;
+
+/*
+ * for each (previously) used block in the memfile there is one block header.
+ *
+ * The block may be linked in the used list OR in the free list.
+ * The used blocks are also kept in hash lists.
+ *
+ * The used list is a doubly linked list, most recently used block first.
+ * The blocks in the used list have a block of memory allocated.
+ * mf_used_count is the number of pages in the used list.
+ * The hash lists are used to quickly find a block in the used list.
+ * The free list is a single linked list, not sorted.
+ * The blocks in the free list have no block of memory allocated and
+ * the contents of the block in the file (if any) is irrelevant.
+ */
+
+struct block_hdr
+{
+ bhdr_T *bh_next; /* next block_hdr in free or used list */
+ bhdr_T *bh_prev; /* previous block_hdr in used list */
+ bhdr_T *bh_hash_next; /* next block_hdr in hash list */
+ bhdr_T *bh_hash_prev; /* previous block_hdr in hash list */
+ blocknr_T bh_bnum; /* block number */
+ char_u *bh_data; /* pointer to memory (for used block) */
+ int bh_page_count; /* number of pages in this block */
+
+#define BH_DIRTY 1
+#define BH_LOCKED 2
+ char bh_flags; /* BH_DIRTY or BH_LOCKED */
+};
+
+/*
+ * when a block with a negative number is flushed to the file, it gets
+ * a positive number. Because the reference to the block is still the negative
+ * number, we remember the translation to the new positive number in the
+ * double linked trans lists. The structure is the same as the hash lists.
+ */
+typedef struct nr_trans NR_TRANS;
+
+struct nr_trans
+{
+ NR_TRANS *nt_next; /* next nr_trans in hash list */
+ NR_TRANS *nt_prev; /* previous nr_trans in hash list */
+ blocknr_T nt_old_bnum; /* old, negative, number */
+ blocknr_T nt_new_bnum; /* new, positive, number */
+};
+
+/*
+ * structure used to store one block of the stuff/redo/recording buffers
+ */
+struct buffblock
+{
+ struct buffblock *b_next; /* pointer to next buffblock */
+ char_u b_str[1]; /* contents (actually longer) */
+};
+
+/*
+ * header used for the stuff buffer and the redo buffer
+ */
+struct buffheader
+{
+ struct buffblock bh_first; /* first (dummy) block of list */
+ struct buffblock *bh_curr; /* buffblock for appending */
+ int bh_index; /* index for reading */
+ int bh_space; /* space in bh_curr for appending */
+};
+
+/*
+ * used for completion on the command line
+ */
+typedef struct expand
+{
+ int xp_context; /* type of expansion */
+ char_u *xp_pattern; /* start of item to expand */
+#if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
+ char_u *xp_arg; /* completion function */
+ int xp_scriptID; /* SID for completion function */
+#endif
+ int xp_backslash; /* one of the XP_BS_ values */
+ int xp_numfiles; /* number of files found by
+ file name completion */
+ char_u **xp_files; /* list of files */
+} expand_T;
+
+/* values for xp_backslash */
+#define XP_BS_NONE 0 /* nothing special for backslashes */
+#define XP_BS_ONE 1 /* uses one backslash before a space */
+#define XP_BS_THREE 2 /* uses three backslashes before a space */
+
+/*
+ * Command modifiers ":vertical", ":browse", ":confirm" and ":hide" set a flag.
+ * This needs to be saved for recursive commands, put them in a structure for
+ * easy manipulation.
+ */
+typedef struct
+{
+ int hide; /* TRUE when ":hide" was used */
+# ifdef FEAT_BROWSE
+ int browse; /* TRUE to invoke file dialog */
+# endif
+# ifdef FEAT_WINDOWS
+ int split; /* flags for win_split() */
+# endif
+# if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ int confirm; /* TRUE to invoke yes/no dialog */
+# endif
+ int keepmarks; /* TRUE when ":keepmarks" was used */
+ int keepjumps; /* TRUE when ":keepjumps" was used */
+ int lockmarks; /* TRUE when ":lockmarks" was used */
+} cmdmod_T;
+
+/*
+ * Simplistic hashing scheme to quickly locate the blocks in the used list.
+ * 64 blocks are found directly (64 * 4K = 256K, most files are smaller).
+ */
+#define MEMHASHSIZE 64
+#define MEMHASH(nr) ((nr) & (MEMHASHSIZE - 1))
+
+struct memfile
+{
+ char_u *mf_fname; /* name of the file */
+ char_u *mf_ffname; /* idem, full path */
+ int mf_fd; /* file descriptor */
+ bhdr_T *mf_free_first; /* first block_hdr in free list */
+ bhdr_T *mf_used_first; /* mru block_hdr in used list */
+ bhdr_T *mf_used_last; /* lru block_hdr in used list */
+ unsigned mf_used_count; /* number of pages in used list */
+ unsigned mf_used_count_max; /* maximum number of pages in memory */
+ bhdr_T *mf_hash[MEMHASHSIZE]; /* array of hash lists */
+ NR_TRANS *mf_trans[MEMHASHSIZE]; /* array of trans lists */
+ blocknr_T mf_blocknr_max; /* highest positive block number + 1*/
+ blocknr_T mf_blocknr_min; /* lowest negative block number - 1 */
+ blocknr_T mf_neg_count; /* number of negative blocks numbers */
+ blocknr_T mf_infile_count; /* number of pages in the file */
+ unsigned mf_page_size; /* number of bytes in a page */
+ int mf_dirty; /* TRUE if there are dirty blocks */
+};
+
+/*
+ * things used in memline.c
+ */
+/*
+ * When searching for a specific line, we remember what blocks in the tree
+ * are the branches leading to that block. This is stored in ml_stack. Each
+ * entry is a pointer to info in a block (may be data block or pointer block)
+ */
+typedef struct info_pointer
+{
+ blocknr_T ip_bnum; /* block number */
+ linenr_T ip_low; /* lowest lnum in this block */
+ linenr_T ip_high; /* highest lnum in this block */
+ int ip_index; /* index for block with current lnum */
+} infoptr_T; /* block/index pair */
+
+#ifdef FEAT_BYTEOFF
+typedef struct ml_chunksize
+{
+ int mlcs_numlines;
+ long mlcs_totalsize;
+} chunksize_T;
+
+ /* Flags when calling ml_updatechunk() */
+
+#define ML_CHNK_ADDLINE 1
+#define ML_CHNK_DELLINE 2
+#define ML_CHNK_UPDLINE 3
+#endif
+
+/*
+ * the memline structure holds all the information about a memline
+ */
+typedef struct memline
+{
+ linenr_T ml_line_count; /* number of lines in the buffer */
+
+ memfile_T *ml_mfp; /* pointer to associated memfile */
+
+#define ML_EMPTY 1 /* empty buffer */
+#define ML_LINE_DIRTY 2 /* cached line was changed and allocated */
+#define ML_LOCKED_DIRTY 4 /* ml_locked was changed */
+#define ML_LOCKED_POS 8 /* ml_locked needs positive block number */
+ int ml_flags;
+
+ infoptr_T *ml_stack; /* stack of pointer blocks (array of IPTRs) */
+ int ml_stack_top; /* current top if ml_stack */
+ int ml_stack_size; /* total number of entries in ml_stack */
+
+ linenr_T ml_line_lnum; /* line number of cached line, 0 if not valid */
+ char_u *ml_line_ptr; /* pointer to cached line */
+
+ bhdr_T *ml_locked; /* block used by last ml_get */
+ linenr_T ml_locked_low; /* first line in ml_locked */
+ linenr_T ml_locked_high; /* last line in ml_locked */
+ int ml_locked_lineadd; /* number of lines inserted in ml_locked */
+#ifdef FEAT_BYTEOFF
+ chunksize_T *ml_chunksize;
+ int ml_numchunks;
+ int ml_usedchunks;
+#endif
+} memline_T;
+
+#if defined(FEAT_SIGNS) || defined(PROTO)
+typedef struct signlist signlist_T;
+
+struct signlist
+{
+ int id; /* unique identifier for each placed sign */
+ linenr_T lnum; /* line number which has this sign */
+ int typenr; /* typenr of sign */
+ signlist_T *next; /* next signlist entry */
+# ifdef FEAT_NETBEANS_INTG
+ signlist_T *prev; /* previous entry -- for easy reordering */
+# endif
+};
+
+/* type argument for buf_getsigntype() */
+#define SIGN_ANY 0
+#define SIGN_LINEHL 1
+#define SIGN_ICON 2
+#define SIGN_TEXT 3
+#endif
+
+/*
+ * Argument list: Array of file names.
+ * Used for the global argument list and the argument lists local to a window.
+ */
+typedef struct arglist
+{
+ garray_T al_ga; /* growarray with the array of file names */
+ int al_refcount; /* number of windows using this arglist */
+} alist_T;
+
+/*
+ * For each argument remember the file name as it was given, and the buffer
+ * number that contains the expanded file name (required for when ":cd" is
+ * used.
+ */
+typedef struct argentry
+{
+ char_u *ae_fname; /* file name as specified */
+ int ae_fnum; /* buffer number with expanded file name */
+} aentry_T;
+
+#ifdef FEAT_WINDOWS
+# define ALIST(win) (win)->w_alist
+#else
+# define ALIST(win) (&global_alist)
+#endif
+#define GARGLIST ((aentry_T *)global_alist.al_ga.ga_data)
+#define ARGLIST ((aentry_T *)ALIST(curwin)->al_ga.ga_data)
+#define WARGLIST(wp) ((aentry_T *)ALIST(wp)->al_ga.ga_data)
+#define AARGLIST(al) ((aentry_T *)((al)->al_ga.ga_data))
+#define GARGCOUNT (global_alist.al_ga.ga_len)
+#define ARGCOUNT (ALIST(curwin)->al_ga.ga_len)
+#define WARGCOUNT(wp) (ALIST(wp)->al_ga.ga_len)
+
+/*
+ * A list used for saving values of "emsg_silent". Used by ex_try() to save the
+ * value of "emsg_silent" if it was non-zero. When this is done, the CSF_SILENT
+ * flag below is set.
+ */
+
+typedef struct eslist_elem eslist_T;
+struct eslist_elem
+{
+ int saved_emsg_silent; /* saved value of "emsg_silent" */
+ eslist_T *next; /* next element on the list */
+};
+
+/*
+ * For conditional commands a stack is kept of nested conditionals.
+ * When cs_idx < 0, there is no conditional command.
+ */
+#define CSTACK_LEN 50
+
+struct condstack
+{
+ char cs_flags[CSTACK_LEN]; /* CSF_ flags */
+ char cs_pending[CSTACK_LEN]; /* CSTP_: what's pending in ":finally"*/
+ union {
+ void *cs_pend_rv[CSTACK_LEN]; /* returnval for pending return */
+ void *cs_pend_ex[CSTACK_LEN]; /* exception for pending throw */
+ } cs_pend;
+ int cs_line[CSTACK_LEN]; /* line number of ":while" line */
+ int cs_idx; /* current entry, or -1 if none */
+ int cs_whilelevel; /* number of nested ":while"s */
+ int cs_trylevel; /* number of nested ":try"s */
+ eslist_T *cs_emsg_silent_list; /* saved values of "emsg_silent" */
+ char cs_had_while; /* just found ":while" */
+ char cs_had_continue; /* just found ":continue" */
+ char cs_had_endwhile; /* just found ":endwhile" */
+ char cs_had_finally; /* just found ":finally" */
+};
+# define cs_retvar cs_pend.cs_pend_rv
+# define cs_exception cs_pend.cs_pend_ex
+
+# define CSF_TRUE 1 /* condition was TRUE */
+# define CSF_ACTIVE 2 /* current state is active */
+# define CSF_ELSE 4 /* ":else" has been passed */
+# define CSF_WHILE 8 /* is a ":while" */
+# define CSF_TRY 16 /* is a ":try" */
+# define CSF_FINALLY 32 /* ":finally" has been passed */
+# define CSF_THROWN 64 /* exception thrown to this try conditional */
+# define CSF_CAUGHT 128 /* exception caught by this try conditional */
+# define CSF_SILENT 4 /* "emsg_silent" reset by ":try" */
+/* Note that CSF_ELSE is only used when CSF_TRY and CSF_WHILE are unset
+ * (an ":if"), and CSF_SILENT is only used when CSF_TRY is set. */
+
+/*
+ * What's pending for being reactivated at the ":endtry" of this try
+ * conditional:
+ */
+# define CSTP_NONE 0 /* nothing pending in ":finally" clause */
+# define CSTP_ERROR 1 /* an error is pending */
+# define CSTP_INTERRUPT 2 /* an interrupt is pending */
+# define CSTP_THROW 4 /* a throw is pending */
+# define CSTP_BREAK 8 /* ":break" is pending */
+# define CSTP_CONTINUE 16 /* ":continue" is pending */
+# define CSTP_RETURN 24 /* ":return" is pending */
+# define CSTP_FINISH 32 /* ":finish" is pending */
+
+/*
+ * A list of error messages that can be converted to an exception. "throw_msg"
+ * is only set in the first element of the list. Usually, it points to the
+ * original message stored in that element, but sometimes it points to a later
+ * message in the list. See cause_errthrow() below.
+ */
+struct msglist
+{
+ char_u *msg; /* original message */
+ char_u *throw_msg; /* msg to throw: usually original one */
+ struct msglist *next; /* next of several messages in a row */
+};
+
+/*
+ * Structure describing an exception.
+ * (don't use "struct exception", it's used by the math library).
+ */
+typedef struct vim_exception except_T;
+struct vim_exception
+{
+ int type; /* exception type */
+ char_u *value; /* exception value */
+ struct msglist *messages; /* message(s) causing error exception */
+ char_u *throw_name; /* name of the throw point */
+ linenr_T throw_lnum; /* line number of the throw point */
+ except_T *caught; /* next exception on the caught stack */
+};
+
+/*
+ * The exception types.
+ */
+#define ET_USER 0 /* exception caused by ":throw" command */
+#define ET_ERROR 1 /* error exception */
+#define ET_INTERRUPT 2 /* interrupt exception triggered by Ctrl-C */
+
+
+#ifdef FEAT_SYN_HL
+/* struct passed to in_id_list() */
+struct sp_syn
+{
+ int inc_tag; /* ":syn include" unique tag */
+ short id; /* highlight group ID of item */
+ short *cont_in_list; /* cont.in group IDs, if non-zero */
+};
+
+/*
+ * Each keyword has one keyentry, which is linked in a hash list.
+ */
+typedef struct keyentry keyentry_T;
+
+struct keyentry
+{
+ keyentry_T *next; /* next keyword in the hash list */
+ struct sp_syn k_syn; /* struct passed to in_id_list() */
+ short *next_list; /* ID list for next match (if non-zero) */
+ short flags; /* see syntax.c */
+ char_u keyword[1]; /* actually longer */
+};
+
+/*
+ * Struct used to store one state of the state stack.
+ */
+typedef struct buf_state
+{
+ int bs_idx; /* index of pattern */
+ long bs_flags; /* flags for pattern */
+ reg_extmatch_T *bs_extmatch; /* external matches from start pattern */
+} bufstate_T;
+
+/*
+ * syn_state contains the syntax state stack for the start of one line.
+ * Used by b_sst_array[].
+ */
+typedef struct syn_state synstate_T;
+
+struct syn_state
+{
+ synstate_T *sst_next; /* next entry in used or free list */
+ linenr_T sst_lnum; /* line number for this state */
+ union
+ {
+ bufstate_T sst_stack[SST_FIX_STATES]; /* short state stack */
+ garray_T sst_ga; /* growarray for long state stack */
+ } sst_union;
+ int sst_next_flags; /* flags for sst_next_list */
+ short *sst_next_list; /* "nextgroup" list in this state
+ * (this is a copy, don't free it! */
+ short sst_stacksize; /* number of states on the stack */
+ disptick_T sst_tick; /* tick when last displayed */
+ linenr_T sst_change_lnum;/* when non-zero, change in this line
+ * may have made the state invalid */
+};
+#endif /* FEAT_SYN_HL */
+
+/*
+ * Structure shared between syntax.c, screen.c and gui_x11.c.
+ */
+typedef struct attr_entry
+{
+ short ae_attr; /* HL_BOLD, etc. */
+ union
+ {
+ struct
+ {
+ char_u *start; /* start escape sequence */
+ char_u *stop; /* stop escape sequence */
+ } term;
+ struct
+ {
+ char_u fg_color; /* foreground color number */
+ char_u bg_color; /* background color number */
+ } cterm;
+# ifdef FEAT_GUI
+ struct
+ {
+ guicolor_T fg_color; /* foreground color handle */
+ guicolor_T bg_color; /* background color handle */
+ GuiFont font; /* font handle */
+# ifdef FEAT_XFONTSET
+ GuiFontset fontset; /* fontset handle */
+# endif
+ } gui;
+# endif
+ } ae_u;
+} attrentry_T;
+
+#ifdef USE_ICONV
+# ifdef HAVE_ICONV_H
+# include <iconv.h>
+# else
+# if defined(MACOS_X)
+# include <sys/errno.h>
+# define EILSEQ ENOENT /* MacOS X does not have EILSEQ */
+typedef struct _iconv_t *iconv_t;
+# else
+# if defined(MACOS_CLASSIC)
+typedef struct _iconv_t *iconv_t;
+# define EINVAL 22
+# define E2BIG 7
+# define ENOENT 2
+# define EFAULT 14
+# define EILSEQ 123
+# else
+# include <errno.h>
+# endif
+# endif
+typedef void *iconv_t;
+# endif
+#endif
+
+/*
+ * Used for the typeahead buffer: typebuf.
+ */
+typedef struct
+{
+ char_u *tb_buf; /* buffer for typed characters */
+ char_u *tb_noremap; /* mapping flags for characters in tb_buf[] */
+ int tb_buflen; /* size of tb_buf[] */
+ int tb_off; /* current position in tb_buf[] */
+ int tb_len; /* number of valid bytes in tb_buf[] */
+ int tb_maplen; /* nr of mapped bytes in tb_buf[] */
+ int tb_silent; /* nr of silently mapped bytes in tb_buf[] */
+ int tb_no_abbr_cnt; /* nr of bytes without abbrev. in tb_buf[] */
+ int tb_change_cnt; /* nr of time tb_buf was changed; never zero */
+} typebuf_T;
+
+/* Struct to hold the saved typeahead for save_typeahead(). */
+typedef struct
+{
+ typebuf_T save_typebuf;
+ int typebuf_valid; /* TRUE when save_typebuf valid */
+ struct buffheader save_stuffbuff;
+#ifdef USE_INPUT_BUF
+ char_u *save_inputbuf;
+#endif
+} tasave_T;
+
+/*
+ * Used for conversion of terminal I/O and script files.
+ */
+typedef struct
+{
+ int vc_type; /* zero or one of the CONV_ values */
+ int vc_factor; /* max. expansion factor */
+# ifdef WIN3264
+ int vc_cpfrom; /* codepage to convert from (CONV_CODEPAGE) */
+ int vc_cpto; /* codepage to convert to (CONV_CODEPAGE) */
+# endif
+# ifdef USE_ICONV
+ iconv_t vc_fd; /* for CONV_ICONV */
+# endif
+ int vc_fail; /* fail for invalid char, don't use '?' */
+} vimconv_T;
+
+/*
+ * Structure used for reading from the viminfo file.
+ */
+typedef struct
+{
+ char_u *vir_line; /* text of the current line */
+ FILE *vir_fd; /* file descriptor */
+#ifdef FEAT_MBYTE
+ vimconv_T vir_conv; /* encoding conversion */
+#endif
+} vir_T;
+
+#define CONV_NONE 0
+#define CONV_TO_UTF8 1
+#define CONV_TO_LATIN1 2
+#define CONV_ICONV 3
+#ifdef WIN3264
+# define CONV_CODEPAGE 4 /* codepage -> codepage */
+#endif
+#ifdef MACOS_X
+# define CONV_MAC_LATIN1 5
+# define CONV_LATIN1_MAC 6
+# define CONV_MAC_UTF8 7
+# define CONV_UTF8_MAC 8
+#endif
+
+/*
+ * Structure used for mappings and abbreviations.
+ */
+typedef struct mapblock mapblock_T;
+struct mapblock
+{
+ mapblock_T *m_next; /* next mapblock in list */
+ char_u *m_keys; /* mapped from */
+ int m_keylen; /* strlen(m_keys) */
+ char_u *m_str; /* mapped to */
+ int m_mode; /* valid mode */
+ int m_noremap; /* if non-zero no re-mapping for m_str */
+ char m_silent; /* <silent> used, don't echo commands */
+#if 0 /* Not used yet */
+ scid_T m_script_ID; /* ID of script where map was defined,
+ used for s: variables and functions */
+#endif
+};
+
+/*
+ * Used for highlighting in the status line.
+ */
+struct stl_hlrec
+{
+ char_u *start;
+ int userhl;
+};
+
+/*
+ * buffer: structure that holds information about one file
+ *
+ * Several windows can share a single Buffer
+ * A buffer is unallocated if there is no memfile for it.
+ * A buffer is new if the associated file has never been loaded yet.
+ */
+
+typedef struct file_buffer buf_T;
+
+struct file_buffer
+{
+ memline_T b_ml; /* associated memline (also contains line
+ count) */
+
+ buf_T *b_next; /* links in list of buffers */
+ buf_T *b_prev;
+
+ int b_nwindows; /* nr of windows open on this buffer */
+
+ int b_flags; /* various BF_ flags */
+
+ /*
+ * b_ffname has the full path of the file (NULL for no name).
+ * b_sfname is the name as the user typed it (or NULL).
+ * b_fname is the same as b_sfname, unless ":cd" has been done,
+ * then it is the same as b_ffname (NULL for no name).
+ */
+ char_u *b_ffname; /* full path file name */
+ char_u *b_sfname; /* short file name */
+ char_u *b_fname; /* current file name */
+
+#ifdef UNIX
+ int b_dev; /* device number (-1 if not set) */
+ ino_t b_ino; /* inode number */
+#endif
+#ifdef FEAT_CW_EDITOR
+ FSSpec b_FSSpec; /* MacOS File Identification */
+#endif
+#ifdef VMS
+ char b_fab_rfm; /* Record format */
+#endif
+#ifdef FEAT_SNIFF
+ int b_sniff; /* file was loaded through Sniff */
+#endif
+
+ int b_fnum; /* buffer number for this file. */
+
+ int b_changed; /* 'modified': Set to TRUE if something in the
+ file has been changed and not written out. */
+ int b_changedtick; /* incremented for each change, also for undo */
+
+ int b_saving; /* Set to TRUE if we are in the middle of
+ saving the buffer. */
+
+ /*
+ * Changes to a buffer require updating of the display. To minimize the
+ * work, remember changes made and update everything at once.
+ */
+ int b_mod_set; /* TRUE when there are changes since the last
+ time the display was updated */
+ linenr_T b_mod_top; /* topmost lnum that was changed */
+ linenr_T b_mod_bot; /* lnum below last changed line, AFTER the
+ change */
+ long b_mod_xlines; /* number of extra buffer lines inserted;
+ negative when lines were deleted */
+
+ wininfo_T *b_wininfo; /* list of last used info for each window */
+
+ long b_mtime; /* last change time of original file */
+ long b_mtime_read; /* last change time when reading */
+ size_t b_orig_size; /* size of original file in bytes */
+ int b_orig_mode; /* mode of original file */
+
+ pos_T b_namedm[NMARKS]; /* current named marks (mark.c) */
+
+#ifdef FEAT_VISUAL
+ /* These variables are set when VIsual_active becomes FALSE */
+ pos_T b_visual_start; /* start pos of last VIsual */
+ pos_T b_visual_end; /* end position of last VIsual */
+ int b_visual_mode; /* VIsual_mode of last VIsual */
+# ifdef FEAT_EVAL
+ int b_visual_mode_eval; /* b_visual_mode for visualmode() */
+# endif
+ colnr_T b_visual_curswant; /* MAXCOL from w_curswant */
+#endif
+
+ pos_T b_last_cursor; /* cursor position when last unloading this
+ buffer */
+ pos_T b_last_insert; /* where Insert mode was left */
+ pos_T b_last_change; /* position of last change: '. mark */
+
+#ifdef FEAT_JUMPLIST
+ /*
+ * the changelist contains old change positions
+ */
+ pos_T b_changelist[JUMPLISTSIZE];
+ int b_changelistlen; /* number of active entries */
+ int b_new_change; /* set by u_savecommon() */
+#endif
+
+ /*
+ * Character table, only used in charset.c for 'iskeyword'
+ * 32 bytes of 8 bits: 1 bit per character 0-255.
+ */
+ char_u b_chartab[32];
+
+#ifdef FEAT_LOCALMAP
+ /* Table used for mappings local to a buffer. */
+ mapblock_T *(b_maphash[256]);
+
+ /* First abbreviation local to a buffer. */
+ mapblock_T *b_first_abbr;
+#endif
+#ifdef FEAT_USR_CMDS
+ /* User commands local to the buffer. */
+ garray_T b_ucmds;
+#endif
+ /*
+ * start and end of an operator, also used for '[ and ']
+ */
+ pos_T b_op_start;
+ pos_T b_op_end;
+
+#ifdef FEAT_VIMINFO
+ int b_marks_read; /* Have we read viminfo marks yet? */
+#endif
+
+ /*
+ * The following only used in undo.c.
+ */
+ u_header_T *b_u_oldhead; /* pointer to oldest header */
+ u_header_T *b_u_newhead; /* pointer to newest header */
+ u_header_T *b_u_curhead; /* pointer to current header */
+ int b_u_numhead; /* current number of headers */
+ int b_u_synced; /* entry lists are synced */
+
+ /*
+ * variables for "U" command in undo.c
+ */
+ char_u *b_u_line_ptr; /* saved line for "U" command */
+ linenr_T b_u_line_lnum; /* line number of line in u_line */
+ colnr_T b_u_line_colnr; /* optional column number */
+
+ /*
+ * The following only used in undo.c
+ */
+ mblock_T b_block_head; /* head of allocated memory block list */
+ minfo_T *b_m_search; /* pointer to chunk before previously
+ allocated/freed chunk */
+ mblock_T *b_mb_current; /* block where m_search points in */
+#ifdef FEAT_INS_EXPAND
+ int b_scanned; /* ^N/^P have scanned this buffer */
+#endif
+
+ /* flags for use of ":lmap" and IM control */
+ long b_p_iminsert; /* input mode for insert */
+ long b_p_imsearch; /* input mode for search */
+#define B_IMODE_USE_INSERT -1 /* Use b_p_iminsert value for search */
+#define B_IMODE_NONE 0 /* Input via none */
+#define B_IMODE_LMAP 1 /* Input via langmap */
+#ifndef USE_IM_CONTROL
+# define B_IMODE_LAST 1
+#else
+# define B_IMODE_IM 2 /* Input via input method */
+# define B_IMODE_LAST 2
+#endif
+
+#ifdef FEAT_KEYMAP
+ short b_kmap_state; /* using "lmap" mappings */
+# define KEYMAP_INIT 1 /* 'keymap' was set, call keymap_init() */
+# define KEYMAP_LOADED 2 /* 'keymap' mappings have been loaded */
+ garray_T b_kmap_ga; /* the keymap table */
+#endif
+
+ /*
+ * Options local to a buffer.
+ * They are here because their value depends on the type of file
+ * or contents of the file being edited.
+ */
+ int b_p_initialized; /* set when options initialized */
+
+ int b_p_ai; /* 'autoindent' */
+ int b_p_ai_nopaste; /* b_p_ai saved for paste mode */
+ int b_p_ci; /* 'copyindent' */
+ int b_p_bin; /* 'binary' */
+#ifdef FEAT_MBYTE
+ int b_p_bomb; /* 'bomb' */
+#endif
+#if defined(FEAT_QUICKFIX)
+ char_u *b_p_bh; /* 'bufhidden' */
+ char_u *b_p_bt; /* 'buftype' */
+#endif
+ int b_p_bl; /* 'buflisted' */
+#ifdef FEAT_CINDENT
+ int b_p_cin; /* 'cindent' */
+ char_u *b_p_cino; /* 'cinoptions' */
+ char_u *b_p_cink; /* 'cinkeys' */
+#endif
+#if defined(FEAT_CINDENT) || defined(FEAT_SMARTINDENT)
+ char_u *b_p_cinw; /* 'cinwords' */
+#endif
+#ifdef FEAT_COMMENTS
+ char_u *b_p_com; /* 'comments' */
+#endif
+#ifdef FEAT_FOLDING
+ char_u *b_p_cms; /* 'commentstring' */
+#endif
+#ifdef FEAT_INS_EXPAND
+ char_u *b_p_cpt; /* 'complete' */
+#endif
+ int b_p_eol; /* 'endofline' */
+ int b_p_et; /* 'expandtab' */
+ int b_p_et_nobin; /* b_p_et saved for binary mode */
+#ifdef FEAT_MBYTE
+ char_u *b_p_fenc; /* 'fileencoding' */
+#endif
+ char_u *b_p_ff; /* 'fileformat' */
+#ifdef FEAT_AUTOCMD
+ char_u *b_p_ft; /* 'filetype' */
+#endif
+ char_u *b_p_fo; /* 'formatoptions' */
+ int b_p_inf; /* 'infercase' */
+ char_u *b_p_isk; /* 'iskeyword' */
+#ifdef FEAT_FIND_ID
+ char_u *b_p_def; /* 'define' local value */
+ char_u *b_p_inc; /* 'include' */
+# ifdef FEAT_EVAL
+ char_u *b_p_inex; /* 'includeexpr' */
+# endif
+#endif
+#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
+ char_u *b_p_inde; /* 'indentexpr' */
+ char_u *b_p_indk; /* 'indentkeys' */
+#endif
+#ifdef FEAT_CRYPT
+ char_u *b_p_key; /* 'key' */
+#endif
+ char_u *b_p_kp; /* 'keywordprg' */
+#ifdef FEAT_LISP
+ int b_p_lisp; /* 'lisp' */
+#endif
+ char_u *b_p_mps; /* 'matchpairs' */
+ int b_p_ml; /* 'modeline' */
+ int b_p_ml_nobin; /* b_p_ml saved for binary mode */
+ int b_p_ma; /* 'modifiable' */
+ char_u *b_p_nf; /* 'nrformats' */
+#ifdef FEAT_OSFILETYPE
+ char_u *b_p_oft; /* 'osfiletype' */
+#endif
+ int b_p_pi; /* 'preserveindent' */
+ int b_p_ro; /* 'readonly' */
+ long b_p_sw; /* 'shiftwidth' */
+#ifndef SHORT_FNAME
+ int b_p_sn; /* 'shortname' */
+#endif
+#ifdef FEAT_SMARTINDENT
+ int b_p_si; /* 'smartindent' */
+#endif
+ long b_p_sts; /* 'softtabstop' */
+ long b_p_sts_nopaste; /* b_p_sts saved for paste mode */
+#ifdef FEAT_SEARCHPATH
+ char_u *b_p_sua; /* 'suffixesadd' */
+#endif
+ int b_p_swf; /* 'swapfile' */
+#ifdef FEAT_SYN_HL
+ char_u *b_p_syn; /* 'syntax' */
+#endif
+ long b_p_ts; /* 'tabstop' */
+ int b_p_tx; /* 'textmode' */
+ long b_p_tw; /* 'textwidth' */
+ long b_p_tw_nobin; /* b_p_tw saved for binary mode */
+ long b_p_tw_nopaste; /* b_p_tw saved for paste mode */
+ long b_p_wm; /* 'wrapmargin' */
+ long b_p_wm_nobin; /* b_p_wm saved for binary mode */
+ long b_p_wm_nopaste; /* b_p_wm saved for paste mode */
+#ifdef FEAT_KEYMAP
+ char_u *b_p_keymap; /* 'keymap' */
+#endif
+
+ /* local values for options which are normally global */
+#ifdef FEAT_QUICKFIX
+ char_u *b_p_gp; /* 'grepprg' local value */
+ char_u *b_p_mp; /* 'makeprg' local value */
+ char_u *b_p_efm; /* 'errorformat' local value */
+#endif
+ char_u *b_p_ep; /* 'equalprg' local value */
+ char_u *b_p_path; /* 'path' local value */
+ int b_p_ar; /* 'autoread' local value */
+ char_u *b_p_tags; /* 'tags' local value */
+#ifdef FEAT_INS_EXPAND
+ char_u *b_p_dict; /* 'dictionary' local value */
+ char_u *b_p_tsr; /* 'thesaurus' local value */
+#endif
+
+ /* end of buffer options */
+
+ int b_start_eol; /* last line had eol when it was read */
+ int b_start_ffc; /* first char of 'ff' when edit started */
+#ifdef FEAT_MBYTE
+ char_u *b_start_fenc; /* 'fileencoding' when edit started or NULL */
+#endif
+
+#ifdef FEAT_EVAL
+ garray_T b_vars; /* internal variables, local to buffer */
+#endif
+
+ /* When a buffer is created, it starts without a swap file. b_may_swap is
+ * then set to indicate that a swap file may be opened later. It is reset
+ * if a swap file could not be opened.
+ */
+ int b_may_swap;
+ int b_did_warn; /* Set to 1 if user has been warned on first
+ change of a read-only file */
+ int b_help; /* buffer for help file (when set b_p_bt is
+ "help") */
+
+#ifndef SHORT_FNAME
+ int b_shortname; /* this file has an 8.3 file name */
+#endif
+
+#ifdef FEAT_PERL
+ void *perl_private;
+#endif
+
+#ifdef FEAT_PYTHON
+ void *python_ref; /* The Python value referring to this buffer */
+#endif
+
+#ifdef FEAT_TCL
+ void *tcl_ref;
+#endif
+
+#ifdef FEAT_RUBY
+ void *ruby_ref;
+#endif
+
+#ifdef FEAT_SYN_HL
+ keyentry_T **b_keywtab; /* syntax keywords hash table */
+ keyentry_T **b_keywtab_ic; /* idem, ignore case */
+ int b_syn_ic; /* ignore case for :syn cmds */
+ garray_T b_syn_patterns; /* table for syntax patterns */
+ garray_T b_syn_clusters; /* table for syntax clusters */
+ int b_syn_containedin; /* TRUE when there is an item with a
+ "containedin" argument */
+ int b_syn_sync_flags; /* flags about how to sync */
+ short b_syn_sync_id; /* group to sync on */
+ long b_syn_sync_minlines; /* minimal sync lines offset */
+ long b_syn_sync_maxlines; /* maximal sync lines offset */
+ long b_syn_sync_linebreaks; /* offset for multi-line pattern */
+ char_u *b_syn_linecont_pat; /* line continuation pattern */
+ regprog_T *b_syn_linecont_prog; /* line continuation program */
+ int b_syn_linecont_ic; /* ignore-case flag for above */
+ int b_syn_topgrp; /* for ":syntax include" */
+# ifdef FEAT_FOLDING
+ int b_syn_folditems; /* number of patterns with the HL_FOLD
+ flag set */
+# endif
+/*
+ * b_sst_array[] contains the state stack for a number of lines, for the start
+ * of that line (col == 0). This avoids having to recompute the syntax state
+ * too often.
+ * b_sst_array[] is allocated to hold the state for all displayed lines, and
+ * states for 1 out of about 20 other lines.
+ * b_sst_array pointer to an array of synstate_T
+ * b_sst_len number of entries in b_sst_array[]
+ * b_sst_first pointer to first used entry in b_sst_array[] or NULL
+ * b_sst_firstfree pointer to first free entry in b_sst_array[] or NULL
+ * b_sst_freecount number of free entries in b_sst_array[]
+ * b_sst_check_lnum entries after this lnum need to be checked for
+ * validity (MAXLNUM means no check needed)
+ */
+ synstate_T *b_sst_array;
+ int b_sst_len;
+ synstate_T *b_sst_first;
+ synstate_T *b_sst_firstfree;
+ int b_sst_freecount;
+ linenr_T b_sst_check_lnum;
+ short_u b_sst_lasttick; /* last display tick */
+#endif /* FEAT_SYN_HL */
+
+#ifdef FEAT_SIGNS
+ signlist_T *b_signlist; /* list of signs to draw */
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+ int b_netbeans_file; /* TRUE when buffer is owned by NetBeans */
+ int b_was_netbeans_file;/* TRUE if b_netbeans_file was once set */
+#endif
+
+};
+
+/*
+ * Structure to cache info for displayed lines in w_lines[].
+ * Each logical line has one entry.
+ * The entry tells how the logical line is currently displayed in the window.
+ * This is updated when displaying the window.
+ * When the display is changed (e.g., when clearing the screen) w_lines_valid
+ * is changed to exclude invalid entries.
+ * When making changes to the buffer, wl_valid is reset to indicate wl_size
+ * may not reflect what is actually in the buffer. When wl_valid is FALSE,
+ * the entries can only be used to count the number of displayed lines used.
+ * wl_lnum and wl_lastlnum are invalid too.
+ */
+typedef struct w_line
+{
+ linenr_T wl_lnum; /* buffer line number for logical line */
+ short_u wl_size; /* height in screen lines */
+ char wl_valid; /* TRUE values are valid for text in buffer */
+#ifdef FEAT_FOLDING
+ char wl_folded; /* TRUE when this is a range of folded lines */
+ linenr_T wl_lastlnum; /* last buffer line number for logical line */
+#endif
+} wline_T;
+
+/*
+ * Windows are kept in a tree of frames. Each frame has a column (FR_COL)
+ * or row (FR_ROW) layout or is a leaf, which has a window.
+ */
+struct frame
+{
+ char fr_layout; /* FR_LEAF, FR_COL or FR_ROW */
+#ifdef FEAT_VERTSPLIT
+ int fr_width;
+#endif
+ int fr_height;
+ int fr_newheight; /* new height used in win_equal_rec() */
+ frame_T *fr_parent; /* containing frame or NULL */
+ frame_T *fr_next; /* frame right or below in same parent, NULL
+ for first */
+ frame_T *fr_prev; /* frame left or above in same parent, NULL
+ for last */
+ /* fr_child and fr_win are mutually exclusive */
+ frame_T *fr_child; /* first contained frame */
+ win_T *fr_win; /* window that fills this frame */
+};
+
+#define FR_LEAF 0 /* frame is a leaf */
+#define FR_ROW 1 /* frame with a row of windows */
+#define FR_COL 2 /* frame with a column of windows */
+
+/*
+ * Structure which contains all information that belongs to a window
+ *
+ * All row numbers are relative to the start of the window, except w_winrow.
+ */
+struct window
+{
+ buf_T *w_buffer; /* buffer we are a window into (used
+ often, keep it the first item!) */
+
+#ifdef FEAT_WINDOWS
+ win_T *w_prev; /* link to previous window */
+ win_T *w_next; /* link to next window */
+#endif
+
+ frame_T *w_frame; /* frame containing this window */
+
+ pos_T w_cursor; /* cursor position in buffer */
+
+ colnr_T w_curswant; /* The column we'd like to be at. This is
+ used to try to stay in the same column
+ for up/down cursor motions. */
+
+ int w_set_curswant; /* If set, then update w_curswant the next
+ time through cursupdate() to the
+ current virtual column */
+
+#ifdef FEAT_VISUAL
+ /*
+ * the next six are used to update the visual part
+ */
+ char w_old_visual_mode; /* last known VIsual_mode */
+ linenr_T w_old_cursor_lnum; /* last known end of visual part */
+ colnr_T w_old_cursor_fcol; /* first column for block visual part */
+ colnr_T w_old_cursor_lcol; /* last column for block visual part */
+ linenr_T w_old_visual_lnum; /* last known start of visual part */
+ colnr_T w_old_curswant; /* last known value of Curswant */
+#endif
+
+ /*
+ * The next three specify the offsets for displaying the buffer:
+ */
+ linenr_T w_topline; /* buffer line number of the line at the
+ top of the window */
+#ifdef FEAT_DIFF
+ int w_topfill; /* number of filler lines above w_topline */
+ int w_old_topfill; /* w_topfill at last redraw */
+ int w_botfill; /* TRUE when filler lines are actually
+ below w_topline (at end of file) */
+ int w_old_botfill; /* w_botfill at last redraw */
+#endif
+ colnr_T w_leftcol; /* window column number of the left most
+ character in the window; used when
+ 'wrap' is off */
+ colnr_T w_skipcol; /* starting column when a single line
+ doesn't fit in the window */
+
+ /*
+ * Layout of the window in the screen.
+ * May need to add "msg_scrolled" to "w_winrow" in rare situations.
+ */
+#ifdef FEAT_WINDOWS
+ int w_winrow; /* first row of window in screen */
+#endif
+ int w_height; /* number of rows in window, excluding
+ status/command line(s) */
+#ifdef FEAT_WINDOWS
+ int w_status_height; /* number of status lines (0 or 1) */
+#endif
+#ifdef FEAT_VERTSPLIT
+ int w_wincol; /* Leftmost column of window in screen.
+ use W_WINCOL() */
+ int w_width; /* Width of window, excluding separation.
+ use W_WIDTH() */
+ int w_vsep_width; /* Number of separator columns (0 or 1).
+ use W_VSEP_WIDTH() */
+#endif
+
+ /*
+ * === start of cached values ====
+ */
+ /*
+ * Recomputing is minimized by storing the result of computations.
+ * Use functions in screen.c to check if they are valid and to update.
+ * w_valid is a bitfield of flags, which indicate if specific values are
+ * valid or need to be recomputed. See screen.c for values.
+ */
+ int w_valid;
+ pos_T w_valid_cursor; /* last known position of w_cursor, used
+ to adjust w_valid */
+ colnr_T w_valid_leftcol; /* last known w_leftcol */
+
+ /*
+ * w_cline_height is the number of physical lines taken by the buffer line
+ * that the cursor is on. We use this to avoid extra calls to plines().
+ */
+ int w_cline_height; /* current size of cursor line */
+#ifdef FEAT_FOLDING
+ int w_cline_folded; /* cursor line is folded */
+#endif
+
+ int w_cline_row; /* starting row of the cursor line */
+
+ colnr_T w_virtcol; /* column number of the cursor in the
+ buffer line, as opposed to the column
+ number we're at on the screen. This
+ makes a difference on lines which span
+ more than one screen line or when
+ w_leftcol is non-zero */
+
+ /*
+ * w_wrow and w_wcol specify the cursor position in the window.
+ * This is related to positions in the window, not in the display or
+ * buffer, thus w_wrow is relative to w_winrow.
+ */
+ int w_wrow, w_wcol; /* cursor position in window */
+
+ linenr_T w_botline; /* number of the line below the bottom of
+ the screen */
+ int w_empty_rows; /* number of ~ rows in window */
+#ifdef FEAT_DIFF
+ int w_filler_rows; /* number of filler rows at the end of the
+ window */
+#endif
+
+ /*
+ * Info about the lines currently in the window is remembered to avoid
+ * recomputing it every time. The allocated size of w_lines[] is Rows.
+ * Only the w_lines_valid entries are actually valid.
+ * When the display is up-to-date w_lines[0].wl_lnum is equal to w_topline
+ * and w_lines[w_lines_valid - 1].wl_lnum is equal to w_botline.
+ * Between changing text and updating the display w_lines[] represents
+ * what is currently displayed. wl_valid is reset to indicated this.
+ * This is used for efficient redrawing.
+ */
+ int w_lines_valid; /* number of valid entries */
+ wline_T *w_lines;
+
+#ifdef FEAT_FOLDING
+ garray_T w_folds; /* array of nested folds */
+ char w_fold_manual; /* when TRUE: some folds are opened/closed
+ manually */
+ char w_foldinvalid; /* when TRUE: folding needs to be
+ recomputed */
+#endif
+
+ /*
+ * === end of cached values ===
+ */
+
+ int w_redr_type; /* type of redraw to be performed on win */
+ int w_upd_rows; /* number of window lines to update when
+ w_redr_type is REDRAW_TOP */
+ linenr_T w_redraw_top; /* when != 0: first line needing redraw */
+ linenr_T w_redraw_bot; /* when != 0: last line needing redraw */
+#ifdef FEAT_WINDOWS
+ int w_redr_status; /* if TRUE status line must be redrawn */
+#endif
+
+#ifdef FEAT_CMDL_INFO
+ /* remember what is shown in the ruler for this window (if 'ruler' set) */
+ pos_T w_ru_cursor; /* cursor position shown in ruler */
+ colnr_T w_ru_virtcol; /* virtcol shown in ruler */
+ linenr_T w_ru_topline; /* topline shown in ruler */
+ linenr_T w_ru_line_count; /* line count used for ruler */
+# ifdef FEAT_DIFF
+ int w_ru_topfill; /* topfill shown in ruler */
+# endif
+ char w_ru_empty; /* TRUE if ruler shows 0-1 (empty line) */
+#endif
+
+ int w_alt_fnum; /* alternate file (for # and CTRL-^) */
+
+#ifdef FEAT_WINDOWS
+ alist_T *w_alist; /* pointer to arglist for this window */
+#endif
+ int w_arg_idx; /* current index in argument list (can be
+ out of range!) */
+ int w_arg_idx_invalid; /* editing another file than w_arg_idx */
+
+ char_u *w_localdir; /* absolute path of local directory or
+ NULL */
+ /*
+ * Options local to a window.
+ * They are local because they influence the layout of the window or
+ * depend on the window layout.
+ * There are two values: w_onebuf_opt is local to the buffer currently in
+ * this window, w_allbuf_opt is for all buffers in this window.
+ */
+ winopt_T w_onebuf_opt;
+ winopt_T w_allbuf_opt;
+
+ /* transform a pointer to a "onebuf" option into a "allbuf" option */
+#define GLOBAL_WO(p) ((char *)p + sizeof(winopt_T))
+
+#ifdef FEAT_SCROLLBIND
+ long w_scbind_pos;
+#endif
+
+#ifdef FEAT_EVAL
+ garray_T w_vars; /* internal variables, local to window */
+#endif
+
+#if defined(FEAT_RIGHTLEFT) && defined(FEAT_FKMAP)
+ int w_farsi; /* for the window dependent Farsi functions */
+#endif
+
+ /*
+ * The w_prev_pcmark field is used to check whether we really did jump to
+ * a new line after setting the w_pcmark. If not, then we revert to
+ * using the previous w_pcmark.
+ */
+ pos_T w_pcmark; /* previous context mark */
+ pos_T w_prev_pcmark; /* previous w_pcmark */
+
+#ifdef FEAT_JUMPLIST
+ /*
+ * the jumplist contains old cursor positions
+ */
+ xfmark_T w_jumplist[JUMPLISTSIZE];
+ int w_jumplistlen; /* number of active entries */
+ int w_jumplistidx; /* current position */
+
+ int w_changelistidx; /* current position in b_changelist */
+#endif
+
+#ifdef FEAT_SEARCH_EXTRA
+ regmmatch_T w_match; /* regexp program for ":match" */
+ int w_match_id; /* highlight ID for ":match" */
+#endif
+
+ /*
+ * the tagstack grows from 0 upwards:
+ * entry 0: older
+ * entry 1: newer
+ * entry 2: newest
+ */
+ taggy_T w_tagstack[TAGSTACKSIZE]; /* the tag stack */
+ int w_tagstackidx; /* idx just below activ entry */
+ int w_tagstacklen; /* number of tags on stack */
+
+ /*
+ * w_fraction is the fractional row of the cursor within the window, from
+ * 0 at the top row to FRACTION_MULT at the last row.
+ * w_prev_fraction_row was the actual cursor row when w_fraction was last
+ * calculated.
+ */
+ int w_fraction;
+ int w_prev_fraction_row;
+
+#ifdef FEAT_GUI
+ scrollbar_T w_scrollbars[2]; /* vert. Scrollbars for this window */
+#endif
+
+#ifdef FEAT_PERL
+ void *perl_private;
+#endif
+
+#ifdef FEAT_PYTHON
+ void *python_ref; /* The Python value referring to this
+ window */
+#endif
+
+#ifdef FEAT_TCL
+ void *tcl_ref;
+#endif
+
+#ifdef FEAT_RUBY
+ void *ruby_ref;
+#endif
+};
+
+/*
+ * Arguments for operators.
+ */
+typedef struct oparg
+{
+ int op_type; /* current pending operator type */
+ int regname; /* register to use for the operator */
+ int motion_type; /* type of the current cursor motion */
+ int motion_force; /* force motion type: 'v', 'V' or CTRL-V */
+ int use_reg_one; /* TRUE if delete uses reg 1 even when not
+ linewise */
+ int inclusive; /* TRUE if char motion is inclusive (only
+ valid when motion_type is MCHAR */
+ int end_adjusted; /* backuped b_op_end one char (only used by
+ do_format()) */
+ pos_T start; /* start of the operator */
+ pos_T end; /* end of the operator */
+ pos_T cursor_start; /* cursor position before motion for "gw" */
+
+ long line_count; /* number of lines from op_start to op_end
+ (inclusive) */
+ int empty; /* op_start and op_end the same (only used by
+ do_change()) */
+#ifdef FEAT_VISUAL
+ int is_VIsual; /* operator on Visual area */
+ int block_mode; /* current operator is Visual block mode */
+#endif
+ colnr_T start_vcol; /* start col for block mode operator */
+ colnr_T end_vcol; /* end col for block mode operator */
+} oparg_T;
+
+/*
+ * Arguments for Normal mode commands.
+ */
+typedef struct cmdarg
+{
+ oparg_T *oap; /* Operator arguments */
+ int prechar; /* prefix character (optional, always 'g') */
+ int cmdchar; /* command character */
+ int nchar; /* next command character (optional) */
+#ifdef FEAT_MBYTE
+ int ncharC1; /* first composing character (optional) */
+ int ncharC2; /* second composing character (optional) */
+#endif
+ int extra_char; /* yet another character (optional) */
+ long opcount; /* count before an operator */
+ long count0; /* count before command, default 0 */
+ long count1; /* count before command, default 1 */
+ int arg; /* extra argument from nv_cmds[] */
+ int retval; /* return: CA_* values */
+ char_u *searchbuf; /* return: pointer to search pattern or NULL */
+} cmdarg_T;
+
+/* values for retval: */
+#define CA_COMMAND_BUSY 1 /* skip restarting edit() once */
+#define CA_NO_ADJ_OP_END 2 /* don't adjust operator end */
+
+#ifdef CURSOR_SHAPE
+/*
+ * struct to store values from 'guicursor' and 'mouseshape'
+ */
+/* Indexes in shape_table[] */
+#define SHAPE_IDX_N 0 /* Normal mode */
+#define SHAPE_IDX_V 1 /* Visual mode */
+#define SHAPE_IDX_I 2 /* Insert mode */
+#define SHAPE_IDX_R 3 /* Replace mode */
+#define SHAPE_IDX_C 4 /* Command line Normal mode */
+#define SHAPE_IDX_CI 5 /* Command line Insert mode */
+#define SHAPE_IDX_CR 6 /* Command line Replace mode */
+#define SHAPE_IDX_O 7 /* Operator-pending mode */
+#define SHAPE_IDX_VE 8 /* Visual mode with 'seleciton' exclusive */
+#define SHAPE_IDX_CLINE 9 /* On command line */
+#define SHAPE_IDX_STATUS 10 /* A status line */
+#define SHAPE_IDX_SDRAG 11 /* dragging a status line */
+#define SHAPE_IDX_VSEP 12 /* A vertical separator line */
+#define SHAPE_IDX_VDRAG 13 /* dragging a vertical separator line */
+#define SHAPE_IDX_MORE 14 /* Hit-return or More */
+#define SHAPE_IDX_MOREL 15 /* Hit-return or More in last line */
+#define SHAPE_IDX_SM 16 /* showing matching paren */
+#define SHAPE_IDX_COUNT 17
+
+#define SHAPE_BLOCK 0 /* block cursor */
+#define SHAPE_HOR 1 /* horizontal bar cursor */
+#define SHAPE_VER 2 /* vertical bar cursor */
+
+#define MSHAPE_NUMBERED 1000 /* offset for shapes identified by number */
+#define MSHAPE_HIDE 1 /* hide mouse pointer */
+
+#define SHAPE_MOUSE 1 /* used for mouse pointer shape */
+#define SHAPE_CURSOR 2 /* used for text cursor shape */
+
+typedef struct cursor_entry
+{
+ int shape; /* one of the SHAPE_ defines */
+ int mshape; /* one of the MSHAPE defines */
+ int percentage; /* percentage of cell for bar */
+ long blinkwait; /* blinking, wait time before blinking starts */
+ long blinkon; /* blinking, on time */
+ long blinkoff; /* blinking, off time */
+ int id; /* highlight group ID */
+ int id_lm; /* highlight group ID for :lmap mode */
+ char *name; /* mode name (fixed) */
+ char used_for; /* SHAPE_MOUSE and/or SHAPE_CURSOR */
+} cursorentry_T;
+#endif /* CURSOR_SHAPE */
+
+#ifdef FEAT_MENU
+
+/* Indices into vimmenu_T->strings[] and vimmenu_T->noremap[] for each mode */
+#define MENU_INDEX_INVALID -1
+#define MENU_INDEX_NORMAL 0
+#define MENU_INDEX_VISUAL 1
+#define MENU_INDEX_OP_PENDING 2
+#define MENU_INDEX_INSERT 3
+#define MENU_INDEX_CMDLINE 4
+#define MENU_INDEX_TIP 5
+#define MENU_MODES 6
+
+/* Menu modes */
+#define MENU_NORMAL_MODE (1 << MENU_INDEX_NORMAL)
+#define MENU_VISUAL_MODE (1 << MENU_INDEX_VISUAL)
+#define MENU_OP_PENDING_MODE (1 << MENU_INDEX_OP_PENDING)
+#define MENU_INSERT_MODE (1 << MENU_INDEX_INSERT)
+#define MENU_CMDLINE_MODE (1 << MENU_INDEX_CMDLINE)
+#define MENU_TIP_MODE (1 << MENU_INDEX_TIP)
+#define MENU_ALL_MODES ((1 << MENU_INDEX_TIP) - 1)
+/*note MENU_INDEX_TIP is not a 'real' mode*/
+
+/* Start a menu name with this to not include it on the main menu bar */
+#define MNU_HIDDEN_CHAR ']'
+
+typedef struct VimMenu vimmenu_T;
+
+struct VimMenu
+{
+ int modes; /* Which modes is this menu visible for? */
+ int enabled; /* for which modes the menu is enabled */
+ char_u *name; /* Name of menu */
+ char_u *dname; /* Displayed Name (without '&') */
+ int mnemonic; /* mnemonic key (after '&') */
+ char_u *actext; /* accelerator text (after TAB) */
+ int priority; /* Menu order priority */
+#ifdef FEAT_GUI
+ void (*cb)(); /* Call-back routine */
+#endif
+#ifdef FEAT_TOOLBAR
+ char_u *iconfile; /* name of file for icon or NULL */
+ int iconidx; /* icon index (-1 if not set) */
+ int icon_builtin; /* icon names is BuiltIn{nr} */
+#endif
+ char_u *strings[MENU_MODES]; /* Mapped string for each mode */
+ int noremap[MENU_MODES]; /* A REMAP_ flag for each mode */
+ char silent[MENU_MODES]; /* A silent flag for each mode */
+ vimmenu_T *children; /* Children of sub-menu */
+ vimmenu_T *parent; /* Parent of menu */
+ vimmenu_T *next; /* Next item in menu */
+#ifdef FEAT_GUI_X11
+ Widget id; /* Manage this to enable item */
+ Widget submenu_id; /* If this is submenu, add children here */
+#endif
+#ifdef FEAT_GUI_GTK
+ GtkWidget *id; /* Manage this to enable item */
+ GtkWidget *submenu_id; /* If this is submenu, add children here */
+ GtkWidget *tearoff_handle;
+ GtkWidget *label; /* Used by "set wak=" code. */
+#endif
+#ifdef FEAT_GUI_MOTIF
+ int sensitive; /* turn button on/off */
+#endif
+#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF)
+ Pixmap image; /* Toolbar image */
+#endif
+#ifdef FEAT_GUI_MOTIF
+ Pixmap image_ins; /* Toolbar image insensitive */
+#endif
+#ifdef FEAT_BEVAL_TIP
+ BalloonEval *tip; /* tooltip for this menu item */
+#endif
+#ifdef FEAT_GUI_W16
+ UINT id; /* Id of menu item */
+ HMENU submenu_id; /* If this is submenu, add children here */
+#endif
+#ifdef FEAT_GUI_W32
+ UINT id; /* Id of menu item */
+ HMENU submenu_id; /* If this is submenu, add children here */
+ HWND tearoff_handle; /* hWnd of tearoff if created */
+#endif
+#if FEAT_GUI_BEOS
+ BMenuItem *id; /* Id of menu item */
+ BMenu *submenu_id; /* If this is submenu, add children here */
+#endif
+#ifdef FEAT_GUI_MAC
+/* MenuHandle id; */
+/* short index; */ /* the item index within the father menu */
+ short menu_id; /* the menu id to which this item belong */
+ short submenu_id; /* the menu id of the children (could be
+ get throught some tricks) */
+ MenuHandle menu_handle;
+ MenuHandle submenu_handle;
+#endif
+#if defined(FEAT_GUI_AMIGA)
+ /* only one of these will ever be set, but
+ * they are used to allow the menu routine
+ * to easily get a hold of the parent menu
+ * pointer which is needed by all items to
+ * form the chain correctly */
+ int id; /* unused by the amiga, but used in the
+ * code kept for compatibility */
+ struct Menu *menuPtr;
+ struct MenuItem *menuItemPtr;
+#endif
+#ifdef RISCOS
+ int *id; /* Not used, but gui.c needs it */
+ int greyed_out; /* Flag */
+ int hidden;
+#endif
+#ifdef FEAT_GUI_PHOTON
+ PtWidget_t *id;
+ PtWidget_t *submenu_id;
+#endif
+};
+#else
+/* For generating prototypes when FEAT_MENU isn't defined. */
+typedef int vimmenu_T;
+
+#endif /* FEAT_MENU */
+
+/*
+ * Struct to save values in before executing autocommands for a buffer that is
+ * not the current buffer.
+ */
+typedef struct
+{
+ buf_T *save_buf; /* saved curbuf */
+ buf_T *new_curbuf; /* buffer to be used */
+ win_T *save_curwin; /* saved curwin, NULL if it didn't change */
+ win_T *new_curwin; /* new curwin if save_curwin != NULL */
+ pos_T save_cursor; /* saved cursor pos of save_curwin */
+ linenr_T save_topline; /* saved topline of save_curwin */
+#ifdef FEAT_DIFF
+ int save_topfill; /* saved topfill of save_curwin */
+#endif
+} aco_save_T;
+
+/*
+ * Generic option table item, only used for printer at the moment.
+ */
+typedef struct
+{
+ const char *name;
+ int hasnum;
+ long number;
+ char_u *string; /* points into option string */
+ int strlen;
+ int present;
+} option_table_T;
+
+/*
+ * Structure to hold printing color and font attributes.
+ */
+typedef struct
+{
+ long_u fg_color;
+ long_u bg_color;
+ int bold;
+ int italic;
+ int underline;
+} prt_text_attr_T;
+
+/*
+ * Structure passed back to the generic printer code.
+ */
+typedef struct
+{
+ int n_collated_copies;
+ int n_uncollated_copies;
+ int duplex;
+ int chars_per_line;
+ int lines_per_page;
+ int has_color;
+ prt_text_attr_T number;
+#ifdef FEAT_SYN_HL
+ int modec;
+ int do_syntax;
+#endif
+ int user_abort;
+ char_u *jobname;
+#ifdef FEAT_POSTSCRIPT
+ char_u *outfile;
+ char_u *arguments;
+#endif
+} prt_settings_T;
+
+#define PRINT_NUMBER_WIDTH 8
diff --git a/src/swis.s b/src/swis.s
new file mode 100644
index 000000000..562747adb
--- /dev/null
+++ b/src/swis.s
@@ -0,0 +1,143 @@
+; Thomas Leonard
+; 24/5/98
+
+ar0 rn 0
+ar1 rn 1
+ar2 rn 2
+ar3 rn 3
+ar4 rn 4
+ar5 rn 5
+ar6 rn 6
+ar7 rn 7
+ar10 rn 10
+ar11 rn 11
+lk rn 14
+ar15 rn 15
+
+ AREA DATA
+ align 4
+
+ export |r0|
+r0: dcd 0
+
+ export |r1|
+r1: dcd 0
+
+ export |r2|
+r2: dcd 0
+
+ export |r3|
+r3: dcd 0
+
+ export |r4|
+r4: dcd 0
+
+ export |r5|
+r5: dcd 0
+
+ export |r6|
+r6: dcd 0
+
+ export |r7|
+r7: dcd 0
+
+ export |time_of_last_poll|
+time_of_last_poll: dcd 0
+
+ AREA CODE, READONLY
+ align 4
+ import |r0|
+ export |swi|
+ = "swi"
+ align 4
+swi:
+ ; r0 = swi number
+ stmfd sp!,{ar4-ar10,lk}
+ orr ar10,ar0,#1<<17 ;always use the X form
+ mov ar0,ar1
+ mov ar1,ar2
+ mov ar2,ar3
+ add ar3,sp,#4*8
+ ldmia ar3,{ar3-ar7}
+ swi 0x6f ; OS_CallASWI
+ ldr ar10,regs_addr
+ stmia ar10,{ar0-ar7}
+ ldmvcfd sp!,{ar4-ar10,pc}^
+ ; report the error and quit on Cancel
+ mov r1,#0x17
+ adr r2,s_title
+ swi 0x400df ; Wimp_ReportError
+ cmp r1,#1 ;OK selected?
+ ldmeqfd sp!,{ar4-ar10,pc}^ ;yes - try to continue
+ swi 0x11 ;no - die (OS_Exit)
+s_title:
+ = "Nasty error - Cancel to quit"
+ = 0
+
+ align 4
+ export |xswi|
+ = "xswi"
+ align 4
+xswi:
+ ; r0 = swi number
+ stmfd sp!,{ar4-ar10,lk}
+ orr ar10,ar0,#1<<17 ;always use the X form
+ mov ar0,ar1
+ mov ar1,ar2
+ mov ar2,ar3
+ add ar3,sp,#4*8
+ ldmia ar3,{ar3-ar7}
+ swi 0x6f ; OS_CallASWI
+ ldr ar10,regs_addr
+ stmia ar10,{ar0-ar7}
+ mov ar0,#0
+ orr ar0,ar0,ar15
+ ldmfd sp!,{ar4-ar10,pc}^
+
+regs_addr:
+ dcd r0
+
+ ; The Wimp_Poll swis have to be done specially because,
+ ; for some reason, r13 sometimes gets corrupted by Wimp_Poll
+ ; (eg when running FileFind)
+ AREA CODE, READONLY
+ align 4
+ import |time_of_last_poll|
+ export |wimp_poll|
+ = "wimp_poll"
+ align 4
+wimp_poll:
+ mov ar3,sp
+ swi 0x400c7 ; Wimp_Poll
+ mov sp,ar3
+
+ mov ar3,ar0
+ swi 0x42 ; OS_ReadMonotonicTime
+ ldr ar2,addr_time
+ str ar0,[ar2]
+ mov ar0,ar3
+
+ mov ar2,#0
+ wfs ar2 ; Write floating point status. Needed?
+ movs pc,lk
+
+ align 4
+ export |wimp_pollidle|
+ = "wimp_pollidle"
+ align 4
+wimp_pollidle:
+ mov ar3,sp
+ swi 0x400e1 ; Wimp_PollIdle
+ mov sp,ar3
+
+ mov ar3,ar0
+ swi 0x42 ; OS_ReadMonotonicTime
+ ldr ar2,addr_time
+ str ar0,[ar2]
+ mov ar0,ar3
+
+ mov ar2,#0
+ wfs ar2 ; Write floating point status. Needed?
+ movs pc,lk
+
+addr_time: dcd time_of_last_poll
diff --git a/src/syntax.c b/src/syntax.c
new file mode 100644
index 000000000..31ff7617b
--- /dev/null
+++ b/src/syntax.c
@@ -0,0 +1,8456 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * syntax.c: code for syntax highlighting
+ */
+
+#include "vim.h"
+
+/*
+ * Structure that stores information about a highlight group.
+ * The ID of a highlight group is also called group ID. It is the index in
+ * the highlight_ga array PLUS ONE.
+ */
+struct hl_group
+{
+ char_u *sg_name; /* highlight group name */
+ char_u *sg_name_u; /* uppercase of sg_name */
+/* for normal terminals */
+ int sg_term; /* "term=" highlighting attributes */
+ char_u *sg_start; /* terminal string for start highl */
+ char_u *sg_stop; /* terminal string for stop highl */
+ int sg_term_attr; /* Screen attr for term mode */
+/* for color terminals */
+ int sg_cterm; /* "cterm=" highlighting attr */
+ int sg_cterm_bold; /* bold attr was set for light color */
+ int sg_cterm_fg; /* terminal fg color number + 1 */
+ int sg_cterm_bg; /* terminal bg color number + 1 */
+ int sg_cterm_attr; /* Screen attr for color term mode */
+#ifdef FEAT_GUI
+/* for when using the GUI */
+ int sg_gui; /* "gui=" highlighting attributes */
+ guicolor_T sg_gui_fg; /* GUI foreground color handle */
+ char_u *sg_gui_fg_name;/* GUI foreground color name */
+ guicolor_T sg_gui_bg; /* GUI background color handle */
+ char_u *sg_gui_bg_name;/* GUI background color name */
+ GuiFont sg_font; /* GUI font handle */
+#ifdef FEAT_XFONTSET
+ GuiFontset sg_fontset; /* GUI fontset handle */
+#endif
+ char_u *sg_font_name; /* GUI font or fontset name */
+ int sg_gui_attr; /* Screen attr for GUI mode */
+#endif
+ int sg_link; /* link to this highlight group ID */
+ int sg_set; /* combination of SG_* flags */
+};
+
+#define SG_TERM 1 /* term has been set */
+#define SG_CTERM 2 /* cterm has been set */
+#define SG_GUI 4 /* gui has been set */
+#define SG_LINK 8 /* link has been set */
+
+static garray_T highlight_ga; /* highlight groups for 'highlight' option */
+
+#define HL_TABLE() ((struct hl_group *)((highlight_ga.ga_data)))
+
+#ifdef FEAT_CMDL_COMPL
+static int include_default = FALSE; /* include "default" for expansion */
+static int include_link = FALSE; /* include "link" for expansion */
+#endif
+
+/*
+ * The "term", "cterm" and "gui" arguments can be any combination of the
+ * following names, separated by commas (but no spaces!).
+ */
+static char *(hl_name_table[]) =
+ {"bold", "standout", "underline", "italic", "reverse", "inverse", "NONE"};
+static int hl_attr_table[] =
+ {HL_BOLD, HL_STANDOUT, HL_UNDERLINE, HL_ITALIC, HL_INVERSE, HL_INVERSE, 0};
+
+static int get_attr_entry __ARGS((garray_T *table, attrentry_T *aep));
+static void syn_unadd_group __ARGS((void));
+static void set_hl_attr __ARGS((int idx));
+static void highlight_list_one __ARGS((int id));
+static int highlight_list_arg __ARGS((int id, int didh, int type, int iarg, char_u *sarg, char *name));
+static int syn_add_group __ARGS((char_u *name));
+static int syn_list_header __ARGS((int did_header, int outlen, int id));
+static int hl_has_settings __ARGS((int idx, int check_link));
+static void highlight_clear __ARGS((int idx));
+
+#ifdef FEAT_GUI
+static void gui_do_one_color __ARGS((int idx, int do_menu, int do_tooltip));
+static int set_group_colors __ARGS((char_u *name, guicolor_T *fgp, guicolor_T *bgp, int do_menu, int use_norm, int do_tooltip));
+static guicolor_T color_name2handle __ARGS((char_u *name));
+static GuiFont font_name2handle __ARGS((char_u *name));
+# ifdef FEAT_XFONTSET
+static GuiFontset fontset_name2handle __ARGS((char_u *name, int fixed_width));
+# endif
+static void hl_do_font __ARGS((int idx, char_u *arg, int do_normal, int do_menu, int do_tooltip));
+#endif
+
+/*
+ * An attribute number is the index in attr_table plus ATTR_OFF.
+ */
+#define ATTR_OFF (HL_ALL + 1)
+
+#if defined(FEAT_SYN_HL) || defined(PROTO)
+
+#define SYN_NAMELEN 50 /* maximum length of a syntax name */
+
+/* different types of offsets that are possible */
+#define SPO_MS_OFF 0 /* match start offset */
+#define SPO_ME_OFF 1 /* match end offset */
+#define SPO_HS_OFF 2 /* highl. start offset */
+#define SPO_HE_OFF 3 /* highl. end offset */
+#define SPO_RS_OFF 4 /* region start offset */
+#define SPO_RE_OFF 5 /* region end offset */
+#define SPO_LC_OFF 6 /* leading context offset */
+#define SPO_COUNT 7
+
+static char *(spo_name_tab[SPO_COUNT]) =
+ {"ms=", "me=", "hs=", "he=", "rs=", "re=", "lc="};
+
+/*
+ * The patterns that are being searched for are stored in a syn_pattern.
+ * A match item consists of one pattern.
+ * A start/end item consists of n start patterns and m end patterns.
+ * A start/skip/end item consists of n start patterns, one skip pattern and m
+ * end patterns.
+ * For the latter two, the patterns are always consecutive: start-skip-end.
+ *
+ * A character offset can be given for the matched text (_m_start and _m_end)
+ * and for the actually highlighted text (_h_start and _h_end).
+ */
+typedef struct syn_pattern
+{
+ char sp_type; /* see SPTYPE_ defines below */
+ char sp_syncing; /* this item used for syncing */
+ short sp_flags; /* see HL_ defines below */
+ struct sp_syn sp_syn; /* struct passed to in_id_list() */
+ short sp_syn_match_id; /* highlight group ID of pattern */
+ char_u *sp_pattern; /* regexp to match, pattern */
+ regprog_T *sp_prog; /* regexp to match, program */
+ int sp_ic; /* ignore-case flag for sp_prog */
+ short sp_off_flags; /* see below */
+ int sp_offsets[SPO_COUNT]; /* offsets */
+ short *sp_cont_list; /* cont. group IDs, if non-zero */
+ short *sp_next_list; /* next group IDs, if non-zero */
+ int sp_sync_idx; /* sync item index (syncing only) */
+ int sp_line_id; /* ID of last line where tried */
+ int sp_startcol; /* next match in sp_line_id line */
+} synpat_T;
+
+/* The sp_off_flags are computed like this:
+ * offset from the start of the matched text: (1 << SPO_XX_OFF)
+ * offset from the end of the matched text: (1 << (SPO_XX_OFF + SPO_COUNT))
+ * When both are present, only one is used.
+ */
+
+#define SPTYPE_MATCH 1 /* match keyword with this group ID */
+#define SPTYPE_START 2 /* match a regexp, start of item */
+#define SPTYPE_END 3 /* match a regexp, end of item */
+#define SPTYPE_SKIP 4 /* match a regexp, skip within item */
+
+#define HL_CONTAINED 0x01 /* not used on toplevel */
+#define HL_TRANSP 0x02 /* has no highlighting */
+#define HL_ONELINE 0x04 /* match within one line only */
+#define HL_HAS_EOL 0x08 /* end pattern that matches with $ */
+#define HL_SYNC_HERE 0x10 /* sync point after this item (syncing only) */
+#define HL_SYNC_THERE 0x20 /* sync point at current line (syncing only) */
+#define HL_MATCH 0x40 /* use match ID instead of item ID */
+#define HL_SKIPNL 0x80 /* nextgroup can skip newlines */
+#define HL_SKIPWHITE 0x100 /* nextgroup can skip white space */
+#define HL_SKIPEMPTY 0x200 /* nextgroup can skip empty lines */
+#define HL_KEEPEND 0x400 /* end match always kept */
+#define HL_EXCLUDENL 0x800 /* exclude NL from match */
+#define HL_DISPLAY 0x1000 /* only used for displaying, not syncing */
+#define HL_FOLD 0x2000 /* define fold */
+#define HL_EXTEND 0x4000 /* ignore a keepend */
+/* These don't fit in a short, thus can't be used for syntax items, only for
+ * si_flags and bs_flags. */
+#define HL_MATCHCONT 0x8000 /* match continued from previous line */
+#define HL_TRANS_CONT 0x10000L /* transparent item without contains arg */
+
+#define SYN_ITEMS(buf) ((synpat_T *)((buf)->b_syn_patterns.ga_data))
+
+#define NONE_IDX -2 /* value of sp_sync_idx for "NONE" */
+
+/*
+ * Flags for b_syn_sync_flags:
+ */
+#define SF_CCOMMENT 0x01 /* sync on a C-style comment */
+#define SF_MATCH 0x02 /* sync by matching a pattern */
+
+#define SYN_STATE_P(ssp) ((bufstate_T *)((ssp)->ga_data))
+
+/*
+ * Settings for keyword hash table. It uses a simplistic hash function: add
+ * all characters together, modulo KHASH_SIZE.
+ */
+#define KHASH_SIZE 512
+#define KHASH_MASK (KHASH_SIZE - 1)
+#define MAXKEYWLEN 80 /* maximum length of a keyword */
+
+/*
+ * The attributes of the syntax item that has been recognized.
+ */
+static int current_attr = 0; /* attr of current syntax word */
+#ifdef FEAT_EVAL
+static int current_id = 0; /* ID of current char for syn_get_id() */
+static int current_trans_id = 0; /* idem, transparancy removed */
+#endif
+
+struct syn_cluster
+{
+ char_u *scl_name; /* syntax cluster name */
+ char_u *scl_name_u; /* uppercase of scl_name */
+ short *scl_list; /* IDs in this syntax cluster */
+};
+
+/*
+ * Methods of combining two clusters
+ */
+#define CLUSTER_REPLACE 1 /* replace first list with second */
+#define CLUSTER_ADD 2 /* add second list to first */
+#define CLUSTER_SUBTRACT 3 /* subtract second list from first */
+
+#define SYN_CLSTR(buf) ((struct syn_cluster *)((buf)->b_syn_clusters.ga_data))
+
+/*
+ * Syntax group IDs have different types:
+ * 0 - 9999 normal syntax groups
+ * 10000 - 14999 ALLBUT indicator (current_syn_inc_tag added)
+ * 15000 - 19999 TOP indicator (current_syn_inc_tag added)
+ * 20000 - 24999 CONTAINED indicator (current_syn_inc_tag added)
+ * >= 25000 cluster IDs (subtract SYNID_CLUSTER for the cluster ID)
+ */
+#define SYNID_ALLBUT 10000 /* syntax group ID for contains=ALLBUT */
+#define SYNID_TOP 15000 /* syntax group ID for contains=TOP */
+#define SYNID_CONTAINED 20000 /* syntax group ID for contains=CONTAINED */
+#define SYNID_CLUSTER 25000 /* first syntax group ID for clusters */
+
+/*
+ * Annoying Hack(TM): ":syn include" needs this pointer to pass to
+ * expand_filename(). Most of the other syntax commands don't need it, so
+ * instead of passing it to them, we stow it here.
+ */
+static char_u **syn_cmdlinep;
+
+/*
+ * Another Annoying Hack(TM): To prevent rules from other ":syn include"'d
+ * files from from leaking into ALLBUT lists, we assign a unique ID to the
+ * rules in each ":syn include"'d file.
+ */
+static int current_syn_inc_tag = 0;
+static int running_syn_inc_tag = 0;
+
+/*
+ * To reduce the time spent in keepend(), remember at which level in the state
+ * stack the first item with "keepend" is present. When "-1", there is no
+ * "keepend" on the stack.
+ */
+static int keepend_level = -1;
+
+/*
+ * For the current state we need to remember more than just the idx.
+ * When si_m_endpos.lnum is 0, the items other than si_idx are unknown.
+ * (The end positions have the column number of the next char)
+ */
+typedef struct state_item
+{
+ int si_idx; /* index of syntax pattern */
+ int si_id; /* highlight group ID for keywords */
+ int si_trans_id; /* idem, transparancy removed */
+ int si_m_lnum; /* lnum of the match */
+ int si_m_startcol; /* starting column of the match */
+ lpos_T si_m_endpos; /* just after end posn of the match */
+ lpos_T si_h_startpos; /* start position of the highlighting */
+ lpos_T si_h_endpos; /* end position of the highlighting */
+ lpos_T si_eoe_pos; /* end position of end pattern */
+ int si_end_idx; /* group ID for end pattern or zero */
+ int si_ends; /* if match ends before si_m_endpos */
+ int si_attr; /* attributes in this state */
+ long si_flags; /* HL_HAS_EOL flag in this state, and
+ * HL_SKIP* for si_next_list */
+ short *si_cont_list; /* list of contained groups */
+ short *si_next_list; /* nextgroup IDs after this item ends */
+ reg_extmatch_T *si_extmatch; /* \z(...\) matches from start
+ * pattern */
+} stateitem_T;
+
+#define KEYWORD_IDX -1 /* value of si_idx for keywords */
+#define ID_LIST_ALL (short *)-1 /* valid of si_cont_list for containing all
+ but contained groups */
+
+/*
+ * The next possible match in the current line for any pattern is remembered,
+ * to avoid having to try for a match in each column.
+ * If next_match_idx == -1, not tried (in this line) yet.
+ * If next_match_col == MAXCOL, no match found in this line.
+ * (All end positions have the column of the char after the end)
+ */
+static int next_match_col; /* column for start of next match */
+static lpos_T next_match_m_endpos; /* position for end of next match */
+static lpos_T next_match_h_startpos; /* pos. for highl. start of next match */
+static lpos_T next_match_h_endpos; /* pos. for highl. end of next match */
+static int next_match_idx; /* index of matched item */
+static long next_match_flags; /* flags for next match */
+static lpos_T next_match_eos_pos; /* end of start pattn (start region) */
+static lpos_T next_match_eoe_pos; /* pos. for end of end pattern */
+static int next_match_end_idx; /* ID of group for end pattn or zero */
+static reg_extmatch_T *next_match_extmatch = NULL;
+
+/*
+ * A state stack is an array of integers or stateitem_T, stored in a
+ * garray_T. A state stack is invalid if it's itemsize entry is zero.
+ */
+#define INVALID_STATE(ssp) ((ssp)->ga_itemsize == 0)
+#define VALID_STATE(ssp) ((ssp)->ga_itemsize != 0)
+
+/*
+ * The current state (within the line) of the recognition engine.
+ * When current_state.ga_itemsize is 0 the current state is invalid.
+ */
+static win_T *syn_win; /* current window for highlighting */
+static buf_T *syn_buf; /* current buffer for highlighting */
+static linenr_T current_lnum = 0; /* lnum of current state */
+static colnr_T current_col = 0; /* column of current state */
+static int current_state_stored = 0; /* TRUE if stored current state
+ * after setting current_finished */
+static int current_finished = 0; /* current line has been finished */
+static garray_T current_state /* current stack of state_items */
+ = {0, 0, 0, 0, NULL};
+static short *current_next_list = NULL; /* when non-zero, nextgroup list */
+static int current_next_flags = 0; /* flags for current_next_list */
+static int current_line_id = 0; /* unique number for current line */
+
+#define CUR_STATE(idx) ((stateitem_T *)(current_state.ga_data))[idx]
+
+static void syn_sync __ARGS((win_T *wp, linenr_T lnum, synstate_T *last_valid));
+static int syn_match_linecont __ARGS((linenr_T lnum));
+static void syn_start_line __ARGS((void));
+static void syn_update_ends __ARGS((int startofline));
+static void syn_stack_alloc __ARGS((void));
+static int syn_stack_cleanup __ARGS((void));
+static void syn_stack_free_entry __ARGS((buf_T *buf, synstate_T *p));
+static synstate_T *syn_stack_find_entry __ARGS((linenr_T lnum));
+static synstate_T *store_current_state __ARGS((synstate_T *sp));
+static void load_current_state __ARGS((synstate_T *from));
+static void invalidate_current_state __ARGS((void));
+static int syn_stack_equal __ARGS((synstate_T *sp));
+static void validate_current_state __ARGS((void));
+static int syn_finish_line __ARGS((int syncing));
+static int syn_current_attr __ARGS((int syncing, int displaying));
+static int did_match_already __ARGS((int idx, garray_T *gap));
+static stateitem_T *push_next_match __ARGS((stateitem_T *cur_si));
+static void check_state_ends __ARGS((void));
+static void update_si_attr __ARGS((int idx));
+static void check_keepend __ARGS((void));
+static void update_si_end __ARGS((stateitem_T *sip, int startcol, int force));
+static short *copy_id_list __ARGS((short *list));
+static int in_id_list __ARGS((stateitem_T *item, short *cont_list, struct sp_syn *ssp, int contained));
+static int push_current_state __ARGS((int idx));
+static void pop_current_state __ARGS((void));
+
+static void find_endpos __ARGS((int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_endpos, long *flagsp, lpos_T *end_endpos, int *end_idx, reg_extmatch_T *start_ext));
+static void clear_syn_state __ARGS((synstate_T *p));
+static void clear_current_state __ARGS((void));
+
+static void limit_pos __ARGS((lpos_T *pos, lpos_T *limit));
+static void limit_pos_zero __ARGS((lpos_T *pos, lpos_T *limit));
+static void syn_add_end_off __ARGS((lpos_T *result, regmmatch_T *regmatch, synpat_T *spp, int idx, int extra));
+static void syn_add_start_off __ARGS((lpos_T *result, regmmatch_T *regmatch, synpat_T *spp, int idx, int extra));
+static char_u *syn_getcurline __ARGS((void));
+static int syn_regexec __ARGS((regmmatch_T *rmp, linenr_T lnum, colnr_T col));
+static int check_keyword_id __ARGS((char_u *line, int startcol, int *endcol, long *flags, short **next_list, stateitem_T *cur_si));
+static void syn_cmd_case __ARGS((exarg_T *eap, int syncing));
+static void syntax_sync_clear __ARGS((void));
+static void syn_remove_pattern __ARGS((buf_T *buf, int idx));
+static void syn_clear_pattern __ARGS((buf_T *buf, int i));
+static void syn_clear_cluster __ARGS((buf_T *buf, int i));
+static void syn_cmd_clear __ARGS((exarg_T *eap, int syncing));
+static void syn_clear_one __ARGS((int id, int syncing));
+static void syn_cmd_on __ARGS((exarg_T *eap, int syncing));
+static void syn_cmd_enable __ARGS((exarg_T *eap, int syncing));
+static void syn_cmd_reset __ARGS((exarg_T *eap, int syncing));
+static void syn_cmd_manual __ARGS((exarg_T *eap, int syncing));
+static void syn_cmd_off __ARGS((exarg_T *eap, int syncing));
+static void syn_cmd_onoff __ARGS((exarg_T *eap, char *name));
+static void syn_cmd_list __ARGS((exarg_T *eap, int syncing));
+static void syn_lines_msg __ARGS((void));
+static void syn_match_msg __ARGS((void));
+static void syn_list_one __ARGS((int id, int syncing, int link_only));
+static void syn_list_cluster __ARGS((int id));
+static void put_id_list __ARGS((char_u *name, short *list, int attr));
+static void put_pattern __ARGS((char *s, int c, synpat_T *spp, int attr));
+static int syn_list_keywords __ARGS((int id, keyentry_T **ktabp, int did_header, int attr));
+static void syn_clear_keyword __ARGS((int id, keyentry_T **ktabp));
+static void free_keywtab __ARGS((keyentry_T **ktabp));
+static void add_keyword __ARGS((char_u *name, int id, int flags, short *cont_in_list, short *next_list));
+static int syn_khash __ARGS((char_u *p));
+static char_u *get_group_name __ARGS((char_u *arg, char_u **name_end));
+static char_u *get_syn_options __ARGS((char_u *arg, int *flagsp, int keyword, int *sync_idx, short **cont_list, short **cont_in_list, short **next_list));
+static void syn_cmd_include __ARGS((exarg_T *eap, int syncing));
+static void syn_cmd_keyword __ARGS((exarg_T *eap, int syncing));
+static void syn_cmd_match __ARGS((exarg_T *eap, int syncing));
+static void syn_cmd_region __ARGS((exarg_T *eap, int syncing));
+#ifdef __BORLANDC__
+static int _RTLENTRYF syn_compare_stub __ARGS((const void *v1, const void *v2));
+#else
+static int syn_compare_stub __ARGS((const void *v1, const void *v2));
+#endif
+static void syn_cmd_cluster __ARGS((exarg_T *eap, int syncing));
+static int syn_scl_name2id __ARGS((char_u *name));
+static int syn_scl_namen2id __ARGS((char_u *linep, int len));
+static int syn_check_cluster __ARGS((char_u *pp, int len));
+static int syn_add_cluster __ARGS((char_u *name));
+static void init_syn_patterns __ARGS((void));
+static char_u *get_syn_pattern __ARGS((char_u *arg, synpat_T *ci));
+static void syn_cmd_sync __ARGS((exarg_T *eap, int syncing));
+static int get_id_list __ARGS((char_u **arg, int keylen, short **list));
+static void syn_combine_list __ARGS((short **clstr1, short **clstr2, int list_op));
+static void syn_incl_toplevel __ARGS((int id, int *flagsp));
+
+/*
+ * Start the syntax recognition for a line. This function is normally called
+ * from the screen updating, once for each displayed line.
+ * The buffer is remembered in syn_buf, because get_syntax_attr() doesn't get
+ * it. Careful: curbuf and curwin are likely to point to another buffer and
+ * window.
+ */
+ void
+syntax_start(wp, lnum)
+ win_T *wp;
+ linenr_T lnum;
+{
+ synstate_T *p;
+ synstate_T *last_valid = NULL;
+ synstate_T *last_min_valid = NULL;
+ synstate_T *sp, *prev;
+ linenr_T parsed_lnum;
+ linenr_T first_stored;
+ int dist;
+
+ reg_syn = TRUE; /* let vim_regexec() know we're using syntax */
+
+ /*
+ * After switching buffers, invalidate current_state.
+ */
+ if (syn_buf != wp->w_buffer)
+ {
+ invalidate_current_state();
+ syn_buf = wp->w_buffer;
+ }
+ syn_win = wp;
+
+ /*
+ * Allocate syntax stack when needed.
+ */
+ syn_stack_alloc();
+ if (syn_buf->b_sst_array == NULL)
+ goto theend; /* out of memory */
+ syn_buf->b_sst_lasttick = display_tick;
+
+ /*
+ * If the state of the end of the previous line is useful, store it.
+ */
+ if (VALID_STATE(&current_state)
+ && current_lnum < lnum
+ && current_lnum < syn_buf->b_ml.ml_line_count)
+ {
+ (void)syn_finish_line(FALSE);
+ if (!current_state_stored)
+ {
+ ++current_lnum;
+ (void)store_current_state(NULL);
+ }
+
+ /*
+ * If the current_lnum is now the same as "lnum", keep the current
+ * state (this happens very often!). Otherwise invalidate
+ * current_state and figure it out below.
+ */
+ if (current_lnum != lnum)
+ invalidate_current_state();
+ }
+ else
+ invalidate_current_state();
+
+ /*
+ * Try to synchronize from a saved state in b_sst_array[].
+ * Only do this if lnum is not before and not to far beyond a saved state.
+ */
+ if (INVALID_STATE(&current_state) && syn_buf->b_sst_array != NULL)
+ {
+ /* Find last valid saved state before start_lnum. */
+ for (p = syn_buf->b_sst_first; p != NULL; p = p->sst_next)
+ {
+ if (p->sst_lnum > lnum)
+ break;
+ if (p->sst_lnum <= lnum && p->sst_change_lnum == 0)
+ {
+ last_valid = p;
+ if (p->sst_lnum >= lnum - syn_buf->b_syn_sync_minlines)
+ last_min_valid = p;
+ }
+ }
+ if (last_min_valid != NULL)
+ load_current_state(last_min_valid);
+ }
+
+ /*
+ * If "lnum" is before or far beyond a line with a saved state, need to
+ * re-synchronize.
+ */
+ if (INVALID_STATE(&current_state))
+ {
+ syn_sync(wp, lnum, last_valid);
+ first_stored = current_lnum + syn_buf->b_syn_sync_minlines;
+ }
+ else
+ first_stored = current_lnum;
+
+ /*
+ * Advance from the sync point or saved state until the current line.
+ * Save some entries for syncing with later on.
+ */
+ dist = syn_buf->b_ml.ml_line_count / (syn_buf->b_sst_len - Rows) + 1;
+ prev = syn_stack_find_entry(current_lnum);
+ while (current_lnum < lnum)
+ {
+ syn_start_line();
+ (void)syn_finish_line(FALSE);
+ ++current_lnum;
+
+ /* If we parsed at least "minlines" lines or started at a valid
+ * state, the current state is considered valid. */
+ if (current_lnum >= first_stored)
+ {
+ /* Check if the saved state entry is for the current line and is
+ * equal to the current state. If so, then validate all saved
+ * states that depended on a change before the parsed line. */
+ if (prev == NULL)
+ sp = syn_buf->b_sst_first;
+ else
+ sp = prev->sst_next;
+ if (sp != NULL
+ && sp->sst_lnum == current_lnum
+ && syn_stack_equal(sp))
+ {
+ parsed_lnum = current_lnum;
+ prev = sp;
+ while (sp != NULL && sp->sst_change_lnum <= parsed_lnum)
+ {
+ if (sp->sst_lnum <= lnum)
+ /* valid state before desired line, use this one */
+ prev = sp;
+ else if (sp->sst_change_lnum == 0)
+ /* past saved states depending on change, break here. */
+ break;
+ sp->sst_change_lnum = 0;
+ sp = sp->sst_next;
+ }
+ load_current_state(prev);
+ }
+ /* Store the state at this line when it's the first one, the line
+ * where we start parsing, or some distance from the previously
+ * saved state. But only when parsed at least 'minlines'. */
+ else if (prev == NULL
+ || current_lnum == lnum
+ || current_lnum >= prev->sst_lnum + dist)
+ prev = store_current_state(prev);
+ }
+
+ /* This can take a long time: break when CTRL-C pressed. The current
+ * state will be wrong then. */
+ line_breakcheck();
+ if (got_int)
+ {
+ current_lnum = lnum;
+ break;
+ }
+ }
+
+ syn_start_line();
+
+theend:
+ reg_syn = FALSE;
+}
+
+/*
+ * We cannot simply discard growarrays full of state_items or buf_states; we
+ * have to manually release their extmatch pointers first.
+ */
+ static void
+clear_syn_state(p)
+ synstate_T *p;
+{
+ int i;
+ garray_T *gap;
+
+ if (p->sst_stacksize > SST_FIX_STATES)
+ {
+ gap = &(p->sst_union.sst_ga);
+ for (i = 0; i < gap->ga_len; i++)
+ unref_extmatch(SYN_STATE_P(gap)[i].bs_extmatch);
+ ga_clear(gap);
+ }
+ else
+ {
+ for (i = 0; i < p->sst_stacksize; i++)
+ unref_extmatch(p->sst_union.sst_stack[i].bs_extmatch);
+ }
+}
+
+/*
+ * Cleanup the current_state stack.
+ */
+ static void
+clear_current_state()
+{
+ int i;
+ stateitem_T *sip;
+
+ sip = (stateitem_T *)(current_state.ga_data);
+ for (i = 0; i < current_state.ga_len; i++)
+ unref_extmatch(sip[i].si_extmatch);
+ ga_clear(&current_state);
+}
+
+/*
+ * Try to find a synchronisation point for line "lnum".
+ *
+ * This sets current_lnum and the current state. One of three methods is
+ * used:
+ * 1. Search backwards for the end of a C-comment.
+ * 2. Search backwards for given sync patterns.
+ * 3. Simply start on a given number of lines above "lnum".
+ */
+ static void
+syn_sync(wp, start_lnum, last_valid)
+ win_T *wp;
+ linenr_T start_lnum;
+ synstate_T *last_valid;
+{
+ buf_T *curbuf_save;
+ win_T *curwin_save;
+ pos_T cursor_save;
+ int idx;
+ linenr_T lnum;
+ linenr_T end_lnum;
+ linenr_T break_lnum;
+ int had_sync_point;
+ stateitem_T *cur_si;
+ synpat_T *spp;
+ char_u *line;
+ int found_flags = 0;
+ int found_match_idx = 0;
+ linenr_T found_current_lnum = 0;
+ int found_current_col= 0;
+ lpos_T found_m_endpos;
+
+ /*
+ * Clear any current state that might be hanging around.
+ */
+ invalidate_current_state();
+
+ /*
+ * Start at least "minlines" back. Default starting point for parsing is
+ * there.
+ * Start further back, to avoid that scrolling backwards will result in
+ * resyncing for every line. Now it resyncs only one out of N lines,
+ * where N is minlines * 1.5, or minlines * 2 if minlines is small.
+ * Watch out for overflow when minlines is MAXLNUM.
+ */
+ if (syn_buf->b_syn_sync_minlines > start_lnum)
+ start_lnum = 1;
+ else
+ {
+ if (syn_buf->b_syn_sync_minlines == 1)
+ lnum = 1;
+ else if (syn_buf->b_syn_sync_minlines < 10)
+ lnum = syn_buf->b_syn_sync_minlines * 2;
+ else
+ lnum = syn_buf->b_syn_sync_minlines * 3 / 2;
+ if (syn_buf->b_syn_sync_maxlines != 0
+ && lnum > syn_buf->b_syn_sync_maxlines)
+ lnum = syn_buf->b_syn_sync_maxlines;
+ if (lnum >= start_lnum)
+ start_lnum = 1;
+ else
+ start_lnum -= lnum;
+ }
+ current_lnum = start_lnum;
+
+ /*
+ * 1. Search backwards for the end of a C-style comment.
+ */
+ if (syn_buf->b_syn_sync_flags & SF_CCOMMENT)
+ {
+ /* Need to make syn_buf the current buffer for a moment, to be able to
+ * use find_start_comment(). */
+ curwin_save = curwin;
+ curwin = wp;
+ curbuf_save = curbuf;
+ curbuf = syn_buf;
+
+ /*
+ * Skip lines that end in a backslash.
+ */
+ for ( ; start_lnum > 1; --start_lnum)
+ {
+ line = ml_get(start_lnum - 1);
+ if (*line == NUL || *(line + STRLEN(line) - 1) != '\\')
+ break;
+ }
+ current_lnum = start_lnum;
+
+ /* set cursor to start of search */
+ cursor_save = wp->w_cursor;
+ wp->w_cursor.lnum = start_lnum;
+ wp->w_cursor.col = 0;
+
+ /*
+ * If the line is inside a comment, need to find the syntax item that
+ * defines the comment.
+ * Restrict the search for the end of a comment to b_syn_sync_maxlines.
+ */
+ if (find_start_comment((int)syn_buf->b_syn_sync_maxlines) != NULL)
+ {
+ for (idx = syn_buf->b_syn_patterns.ga_len; --idx >= 0; )
+ if (SYN_ITEMS(syn_buf)[idx].sp_syn.id == syn_buf->b_syn_sync_id
+ && SYN_ITEMS(syn_buf)[idx].sp_type == SPTYPE_START)
+ {
+ validate_current_state();
+ if (push_current_state(idx) == OK)
+ update_si_attr(current_state.ga_len - 1);
+ break;
+ }
+ }
+
+ /* restore cursor and buffer */
+ wp->w_cursor = cursor_save;
+ curwin = curwin_save;
+ curbuf = curbuf_save;
+ }
+
+ /*
+ * 2. Search backwards for given sync patterns.
+ */
+ else if (syn_buf->b_syn_sync_flags & SF_MATCH)
+ {
+ if (syn_buf->b_syn_sync_maxlines != 0
+ && start_lnum > syn_buf->b_syn_sync_maxlines)
+ break_lnum = start_lnum - syn_buf->b_syn_sync_maxlines;
+ else
+ break_lnum = 0;
+
+ end_lnum = start_lnum;
+ lnum = start_lnum;
+ while (--lnum > break_lnum)
+ {
+ /* This can take a long time: break when CTRL-C pressed. */
+ line_breakcheck();
+ if (got_int)
+ {
+ invalidate_current_state();
+ current_lnum = start_lnum;
+ break;
+ }
+
+ /* Check if we have run into a valid saved state stack now. */
+ if (last_valid != NULL && lnum == last_valid->sst_lnum)
+ {
+ load_current_state(last_valid);
+ break;
+ }
+
+ /*
+ * Check if the previous line has the line-continuation pattern.
+ */
+ if (lnum > 1 && syn_match_linecont(lnum - 1))
+ continue;
+
+ /*
+ * Start with nothing on the state stack
+ */
+ validate_current_state();
+
+ for (current_lnum = lnum; current_lnum < end_lnum; ++current_lnum)
+ {
+ syn_start_line();
+ for (;;)
+ {
+ had_sync_point = syn_finish_line(TRUE);
+ /*
+ * When a sync point has been found, remember where, and
+ * continue to look for another one, further on in the line.
+ */
+ if (had_sync_point && current_state.ga_len)
+ {
+ cur_si = &CUR_STATE(current_state.ga_len - 1);
+ if (cur_si->si_m_endpos.lnum > start_lnum)
+ {
+ /* ignore match that goes to after where started */
+ current_lnum = end_lnum;
+ break;
+ }
+ spp = &(SYN_ITEMS(syn_buf)[cur_si->si_idx]);
+ found_flags = spp->sp_flags;
+ found_match_idx = spp->sp_sync_idx;
+ found_current_lnum = current_lnum;
+ found_current_col = current_col;
+ found_m_endpos = cur_si->si_m_endpos;
+ /*
+ * Continue after the match (be aware of a zero-length
+ * match).
+ */
+ if (found_m_endpos.lnum > current_lnum)
+ {
+ current_lnum = found_m_endpos.lnum;
+ current_col = found_m_endpos.col;
+ if (current_lnum >= end_lnum)
+ break;
+ }
+ else if (found_m_endpos.col > current_col)
+ current_col = found_m_endpos.col;
+ else
+ ++current_col;
+
+ /* syn_current_attr() will have skipped the check for
+ * an item that ends here, need to do that now. */
+ ++current_col;
+ check_state_ends();
+ --current_col;
+ }
+ else
+ break;
+ }
+ }
+
+ /*
+ * If a sync point was encountered, break here.
+ */
+ if (found_flags)
+ {
+ /*
+ * Put the item that was specified by the sync point on the
+ * state stack. If there was no item specified, make the
+ * state stack empty.
+ */
+ clear_current_state();
+ if (found_match_idx >= 0
+ && push_current_state(found_match_idx) == OK)
+ update_si_attr(current_state.ga_len - 1);
+
+ /*
+ * When using "grouphere", continue from the sync point
+ * match, until the end of the line. Parsing starts at
+ * the next line.
+ * For "groupthere" the parsing starts at start_lnum.
+ */
+ if (found_flags & HL_SYNC_HERE)
+ {
+ if (current_state.ga_len)
+ {
+ cur_si = &CUR_STATE(current_state.ga_len - 1);
+ cur_si->si_h_startpos.lnum = found_current_lnum;
+ cur_si->si_h_startpos.col = found_current_col;
+ update_si_end(cur_si, (int)current_col, TRUE);
+ check_keepend();
+ }
+ current_col = found_m_endpos.col;
+ current_lnum = found_m_endpos.lnum;
+ (void)syn_finish_line(FALSE);
+ ++current_lnum;
+ }
+ else
+ current_lnum = start_lnum;
+
+ break;
+ }
+
+ end_lnum = lnum;
+ invalidate_current_state();
+ }
+
+ /* Ran into start of the file or exceeded maximum number of lines */
+ if (lnum <= break_lnum)
+ {
+ invalidate_current_state();
+ current_lnum = break_lnum + 1;
+ }
+ }
+
+ validate_current_state();
+}
+
+/*
+ * Return TRUE if the line-continuation pattern matches in line "lnum".
+ */
+ static int
+syn_match_linecont(lnum)
+ linenr_T lnum;
+{
+ regmmatch_T regmatch;
+
+ if (syn_buf->b_syn_linecont_prog != NULL)
+ {
+ regmatch.rmm_ic = syn_buf->b_syn_linecont_ic;
+ regmatch.regprog = syn_buf->b_syn_linecont_prog;
+ return syn_regexec(&regmatch, lnum, (colnr_T)0);
+ }
+ return FALSE;
+}
+
+/*
+ * Prepare the current state for the start of a line.
+ */
+ static void
+syn_start_line()
+{
+ current_finished = FALSE;
+ current_col = 0;
+
+ /*
+ * Need to update the end of a start/skip/end that continues from the
+ * previous line and regions that have "keepend".
+ */
+ if (current_state.ga_len > 0)
+ syn_update_ends(TRUE);
+
+ next_match_idx = -1;
+ ++current_line_id;
+}
+
+/*
+ * Check for items in the stack that need their end updated.
+ * When "startofline" is TRUE the last item is always updated.
+ * When "startofline" is FALSE the item with "keepend" is forcefully updated.
+ */
+ static void
+syn_update_ends(startofline)
+ int startofline;
+{
+ stateitem_T *cur_si;
+ int i;
+
+ if (startofline)
+ {
+ /* Check for a match carried over from a previous line with a
+ * contained region. The match ends as soon as the region ends. */
+ for (i = 0; i < current_state.ga_len; ++i)
+ {
+ cur_si = &CUR_STATE(i);
+ if (cur_si->si_idx >= 0
+ && (SYN_ITEMS(syn_buf)[cur_si->si_idx]).sp_type
+ == SPTYPE_MATCH
+ && cur_si->si_m_endpos.lnum < current_lnum)
+ {
+ cur_si->si_flags |= HL_MATCHCONT;
+ cur_si->si_m_endpos.lnum = 0;
+ cur_si->si_m_endpos.col = 0;
+ cur_si->si_h_endpos = cur_si->si_m_endpos;
+ cur_si->si_ends = TRUE;
+ }
+ }
+ }
+
+ /*
+ * Need to update the end of a start/skip/end that continues from the
+ * previous line. And regions that have "keepend", because they may
+ * influence contained items.
+ * Then check for items ending in column 0.
+ */
+ i = current_state.ga_len - 1;
+ if (keepend_level >= 0)
+ for ( ; i > keepend_level; --i)
+ if (CUR_STATE(i).si_flags & HL_EXTEND)
+ break;
+ for ( ; i < current_state.ga_len; ++i)
+ {
+ cur_si = &CUR_STATE(i);
+ if ((cur_si->si_flags & HL_KEEPEND)
+ || (i == current_state.ga_len - 1 && startofline))
+ {
+ cur_si->si_h_startpos.col = 0; /* start highl. in col 0 */
+ cur_si->si_h_startpos.lnum = current_lnum;
+
+ if (!(cur_si->si_flags & HL_MATCHCONT))
+ update_si_end(cur_si, (int)current_col, !startofline);
+ }
+ }
+ check_keepend();
+ check_state_ends();
+}
+
+/****************************************
+ * Handling of the state stack cache.
+ */
+
+/*
+ * EXPLANATION OF THE SYNTAX STATE STACK CACHE
+ *
+ * To speed up syntax highlighting, the state stack for the start of some
+ * lines is cached. These entries can be used to start parsing at that point.
+ *
+ * The stack is kept in b_sst_array[] for each buffer. There is a list of
+ * valid entries. b_sst_first points to the first one, then follow sst_next.
+ * The entries are sorted on line number. The first entry is often for line 2
+ * (line 1 always starts with an empty stack).
+ * There is also a list for free entries. This construction is used to avoid
+ * having to allocate and free memory blocks too often.
+ *
+ * When making changes to the buffer, this is logged in b_mod_*. When calling
+ * update_screen() to update the display, it will call
+ * syn_stack_apply_changes() for each displayed buffer to adjust the cached
+ * entries. The entries which are inside the changed area are removed,
+ * because they must be recomputed. Entries below the changed have their line
+ * number adjusted for deleted/inserted lines, and have their sst_change_lnum
+ * set to indicate that a check must be made if the changed lines would change
+ * the cached entry.
+ *
+ * When later displaying lines, an entry is stored for each line. Displayed
+ * lines are likely to be displayed again, in which case the state at the
+ * start of the line is needed.
+ * For not displayed lines, an entry is stored for every so many lines. These
+ * entries will be used e.g., when scrolling backwards. The distance between
+ * entries depends on the number of lines in the buffer. For small buffers
+ * the distance is fixed at SST_DIST, for large buffers there is a fixed
+ * number of entries SST_MAX_ENTRIES, and the distance is computed.
+ */
+
+/*
+ * Free b_sst_array[] for buffer "buf".
+ * Used when syntax items changed to force resyncing everywhere.
+ */
+ void
+syn_stack_free_all(buf)
+ buf_T *buf;
+{
+ synstate_T *p;
+ win_T *wp;
+
+ if (buf->b_sst_array != NULL)
+ {
+ for (p = buf->b_sst_first; p != NULL; p = p->sst_next)
+ clear_syn_state(p);
+ vim_free(buf->b_sst_array);
+ buf->b_sst_array = NULL;
+ buf->b_sst_len = 0;
+ }
+#ifdef FEAT_FOLDING
+ /* When using "syntax" fold method, must update all folds. */
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_buffer == buf && foldmethodIsSyntax(wp))
+ foldUpdateAll(wp);
+ }
+#endif
+}
+
+/*
+ * Allocate the syntax state stack for syn_buf when needed.
+ * If the number of entries in b_sst_array[] is much too big or a bit too
+ * small, reallocate it.
+ * Also used to allocate b_sst_array[] for the first time.
+ */
+ static void
+syn_stack_alloc()
+{
+ long len;
+ synstate_T *to, *from;
+ synstate_T *sstp;
+
+ len = syn_buf->b_ml.ml_line_count / SST_DIST + Rows * 2;
+ if (len < SST_MIN_ENTRIES)
+ len = SST_MIN_ENTRIES;
+ else if (len > SST_MAX_ENTRIES)
+ len = SST_MAX_ENTRIES;
+ if (syn_buf->b_sst_len > len * 2 || syn_buf->b_sst_len < len)
+ {
+ /* Allocate 50% too much, to avoid reallocating too often. */
+ len = syn_buf->b_ml.ml_line_count;
+ len = (len + len / 2) / SST_DIST + Rows * 2;
+ if (len < SST_MIN_ENTRIES)
+ len = SST_MIN_ENTRIES;
+ else if (len > SST_MAX_ENTRIES)
+ len = SST_MAX_ENTRIES;
+
+ if (syn_buf->b_sst_array != NULL)
+ {
+ /* When shrinking the array, cleanup the existing stack.
+ * Make sure that all valid entries fit in the new array. */
+ while (syn_buf->b_sst_len - syn_buf->b_sst_freecount + 2 > len
+ && syn_stack_cleanup())
+ ;
+ if (len < syn_buf->b_sst_len - syn_buf->b_sst_freecount + 2)
+ len = syn_buf->b_sst_len - syn_buf->b_sst_freecount + 2;
+ }
+
+ sstp = (synstate_T *)alloc_clear((unsigned)(len * sizeof(synstate_T)));
+ if (sstp == NULL) /* out of memory! */
+ return;
+
+ to = sstp - 1;
+ if (syn_buf->b_sst_array != NULL)
+ {
+ /* Move the states from the old array to the new one. */
+ for (from = syn_buf->b_sst_first; from != NULL;
+ from = from->sst_next)
+ {
+ ++to;
+ *to = *from;
+ to->sst_next = to + 1;
+ }
+ }
+ if (to != sstp - 1)
+ {
+ to->sst_next = NULL;
+ syn_buf->b_sst_first = sstp;
+ syn_buf->b_sst_freecount = len - (int)(to - sstp) - 1;
+ }
+ else
+ {
+ syn_buf->b_sst_first = NULL;
+ syn_buf->b_sst_freecount = len;
+ }
+
+ /* Create the list of free entries. */
+ syn_buf->b_sst_firstfree = to + 1;
+ while (++to < sstp + len)
+ to->sst_next = to + 1;
+ (sstp + len - 1)->sst_next = NULL;
+
+ vim_free(syn_buf->b_sst_array);
+ syn_buf->b_sst_array = sstp;
+ syn_buf->b_sst_len = len;
+ }
+}
+
+/*
+ * Check for changes in a buffer to affect stored syntax states. Uses the
+ * b_mod_* fields.
+ * Called from update_screen(), before screen is being updated, once for each
+ * displayed buffer.
+ */
+ void
+syn_stack_apply_changes(buf)
+ buf_T *buf;
+{
+ synstate_T *p, *prev, *np;
+ linenr_T n;
+
+ if (buf->b_sst_array == NULL) /* nothing to do */
+ return;
+
+ prev = NULL;
+ for (p = buf->b_sst_first; p != NULL; )
+ {
+ if (p->sst_lnum + syn_buf->b_syn_sync_linebreaks > buf->b_mod_top)
+ {
+ n = p->sst_lnum + buf->b_mod_xlines;
+ if (n <= buf->b_mod_bot)
+ {
+ /* this state is inside the changed area, remove it */
+ np = p->sst_next;
+ if (prev == NULL)
+ buf->b_sst_first = np;
+ else
+ prev->sst_next = np;
+ syn_stack_free_entry(buf, p);
+ p = np;
+ continue;
+ }
+ /* This state is below the changed area. Remember the line
+ * that needs to be parsed before this entry can be made valid
+ * again. */
+ if (p->sst_change_lnum != 0 && p->sst_change_lnum > buf->b_mod_top)
+ {
+ if (p->sst_change_lnum + buf->b_mod_xlines > buf->b_mod_top)
+ p->sst_change_lnum += buf->b_mod_xlines;
+ else
+ p->sst_change_lnum = buf->b_mod_top;
+ }
+ if (p->sst_change_lnum == 0
+ || p->sst_change_lnum < buf->b_mod_bot)
+ p->sst_change_lnum = buf->b_mod_bot;
+
+ p->sst_lnum = n;
+ }
+ prev = p;
+ p = p->sst_next;
+ }
+}
+
+/*
+ * Reduce the number of entries in the state stack for syn_buf.
+ * Returns TRUE if at least one entry was freed.
+ */
+ static int
+syn_stack_cleanup()
+{
+ synstate_T *p, *prev;
+ disptick_T tick;
+ int above;
+ int dist;
+ int retval = FALSE;
+
+ if (syn_buf->b_sst_array == NULL || syn_buf->b_sst_first == NULL)
+ return retval;
+
+ /* Compute normal distance between non-displayed entries. */
+ dist = syn_buf->b_ml.ml_line_count / (syn_buf->b_sst_len - Rows) + 1;
+
+ /*
+ * Go throught the list to find the "tick" for the oldest entry that can
+ * be removed. Set "above" when the "tick" for the oldest entry is above
+ * "b_sst_lasttick" (the display tick wraps around).
+ */
+ tick = syn_buf->b_sst_lasttick;
+ above = FALSE;
+ prev = syn_buf->b_sst_first;
+ for (p = prev->sst_next; p != NULL; prev = p, p = p->sst_next)
+ {
+ if (prev->sst_lnum + dist > p->sst_lnum)
+ {
+ if (p->sst_tick > syn_buf->b_sst_lasttick)
+ {
+ if (!above || p->sst_tick < tick)
+ tick = p->sst_tick;
+ above = TRUE;
+ }
+ else if (!above && p->sst_tick < tick)
+ tick = p->sst_tick;
+ }
+ }
+
+ /*
+ * Go through the list to make the entries for the oldest tick at an
+ * interval of several lines.
+ */
+ prev = syn_buf->b_sst_first;
+ for (p = prev->sst_next; p != NULL; prev = p, p = p->sst_next)
+ {
+ if (p->sst_tick == tick && prev->sst_lnum + dist > p->sst_lnum)
+ {
+ /* Move this entry from used list to free list */
+ prev->sst_next = p->sst_next;
+ syn_stack_free_entry(syn_buf, p);
+ p = prev;
+ retval = TRUE;
+ }
+ }
+ return retval;
+}
+
+/*
+ * Free the allocated memory for a syn_state item.
+ * Move the entry into the free list.
+ */
+ static void
+syn_stack_free_entry(buf, p)
+ buf_T *buf;
+ synstate_T *p;
+{
+ clear_syn_state(p);
+ p->sst_next = buf->b_sst_firstfree;
+ buf->b_sst_firstfree = p;
+ ++buf->b_sst_freecount;
+}
+
+/*
+ * Find an entry in the list of state stacks at or before "lnum".
+ * Returns NULL when there is no entry or the first entry is after "lnum".
+ */
+ static synstate_T *
+syn_stack_find_entry(lnum)
+ linenr_T lnum;
+{
+ synstate_T *p, *prev;
+
+ prev = NULL;
+ for (p = syn_buf->b_sst_first; p != NULL; prev = p, p = p->sst_next)
+ {
+ if (p->sst_lnum == lnum)
+ return p;
+ if (p->sst_lnum > lnum)
+ break;
+ }
+ return prev;
+}
+
+/*
+ * Try saving the current state in b_sst_array[].
+ * The current state must be valid for the start of the current_lnum line!
+ */
+ static synstate_T *
+store_current_state(sp)
+ synstate_T *sp; /* at or before where state is to be saved or
+ NULL */
+{
+ int i;
+ synstate_T *p;
+ bufstate_T *bp;
+ stateitem_T *cur_si;
+
+ if (sp == NULL)
+ sp = syn_stack_find_entry(current_lnum);
+
+ /*
+ * If the current state contains a start or end pattern that continues
+ * from the previous line, we can't use it. Don't store it then.
+ */
+ for (i = current_state.ga_len - 1; i >= 0; --i)
+ {
+ cur_si = &CUR_STATE(i);
+ if (cur_si->si_h_startpos.lnum >= current_lnum
+ || cur_si->si_m_endpos.lnum >= current_lnum
+ || cur_si->si_h_endpos.lnum >= current_lnum
+ || (cur_si->si_end_idx
+ && cur_si->si_eoe_pos.lnum >= current_lnum))
+ break;
+ }
+ if (i >= 0)
+ {
+ if (sp != NULL)
+ {
+ /* find "sp" in the list and remove it */
+ if (syn_buf->b_sst_first == sp)
+ /* it's the first entry */
+ syn_buf->b_sst_first = sp->sst_next;
+ else
+ {
+ /* find the entry just before this one to adjust sst_next */
+ for (p = syn_buf->b_sst_first; p != NULL; p = p->sst_next)
+ if (p->sst_next == sp)
+ break;
+ p->sst_next = sp->sst_next;
+ }
+ syn_stack_free_entry(syn_buf, sp);
+ sp = NULL;
+ }
+ }
+ else if (sp == NULL || sp->sst_lnum != current_lnum)
+ {
+ /*
+ * Add a new entry
+ */
+ /* If no free items, cleanup the array first. */
+ if (syn_buf->b_sst_freecount == 0)
+ {
+ (void)syn_stack_cleanup();
+ /* "sp" may have been moved to the freelist now */
+ sp = syn_stack_find_entry(current_lnum);
+ }
+ /* Still no free items? Must be a strange problem... */
+ if (syn_buf->b_sst_freecount == 0)
+ sp = NULL;
+ else
+ {
+ /* Take the first item from the free list and put it in the used
+ * list, after *sp */
+ p = syn_buf->b_sst_firstfree;
+ syn_buf->b_sst_firstfree = p->sst_next;
+ --syn_buf->b_sst_freecount;
+ if (sp == NULL)
+ {
+ /* Insert in front of the list */
+ p->sst_next = syn_buf->b_sst_first;
+ syn_buf->b_sst_first = p;
+ }
+ else
+ {
+ /* insert in list after *sp */
+ p->sst_next = sp->sst_next;
+ sp->sst_next = p;
+ }
+ sp = p;
+ sp->sst_stacksize = 0;
+ sp->sst_lnum = current_lnum;
+ }
+ }
+ if (sp != NULL)
+ {
+ /* When overwriting an existing state stack, clear it first */
+ clear_syn_state(sp);
+ sp->sst_stacksize = current_state.ga_len;
+ if (current_state.ga_len > SST_FIX_STATES)
+ {
+ /* Need to clear it, might be something remaining from when the
+ * length was less than SST_FIX_STATES. */
+ ga_init2(&sp->sst_union.sst_ga, (int)sizeof(bufstate_T), 1);
+ if (ga_grow(&sp->sst_union.sst_ga, current_state.ga_len) == FAIL)
+ sp->sst_stacksize = 0;
+ else
+ {
+ sp->sst_union.sst_ga.ga_len = current_state.ga_len;
+ sp->sst_union.sst_ga.ga_room -= current_state.ga_len;
+ }
+ bp = SYN_STATE_P(&(sp->sst_union.sst_ga));
+ }
+ else
+ bp = sp->sst_union.sst_stack;
+ for (i = 0; i < sp->sst_stacksize; ++i)
+ {
+ bp[i].bs_idx = CUR_STATE(i).si_idx;
+ bp[i].bs_flags = CUR_STATE(i).si_flags;
+ bp[i].bs_extmatch = ref_extmatch(CUR_STATE(i).si_extmatch);
+ }
+ sp->sst_next_flags = current_next_flags;
+ sp->sst_next_list = current_next_list;
+ sp->sst_tick = display_tick;
+ sp->sst_change_lnum = 0;
+ }
+ current_state_stored = TRUE;
+ return sp;
+}
+
+/*
+ * Copy a state stack from "from" in b_sst_array[] to current_state;
+ */
+ static void
+load_current_state(from)
+ synstate_T *from;
+{
+ int i;
+ bufstate_T *bp;
+
+ clear_current_state();
+ validate_current_state();
+ keepend_level = -1;
+ if (from->sst_stacksize
+ && ga_grow(&current_state, from->sst_stacksize) != FAIL)
+ {
+ if (from->sst_stacksize > SST_FIX_STATES)
+ bp = SYN_STATE_P(&(from->sst_union.sst_ga));
+ else
+ bp = from->sst_union.sst_stack;
+ for (i = 0; i < from->sst_stacksize; ++i)
+ {
+ CUR_STATE(i).si_idx = bp[i].bs_idx;
+ CUR_STATE(i).si_flags = bp[i].bs_flags;
+ CUR_STATE(i).si_extmatch = ref_extmatch(bp[i].bs_extmatch);
+ if (keepend_level < 0 && (CUR_STATE(i).si_flags & HL_KEEPEND))
+ keepend_level = i;
+ CUR_STATE(i).si_ends = FALSE;
+ CUR_STATE(i).si_m_lnum = 0;
+ if (CUR_STATE(i).si_idx >= 0)
+ CUR_STATE(i).si_next_list =
+ (SYN_ITEMS(syn_buf)[CUR_STATE(i).si_idx]).sp_next_list;
+ else
+ CUR_STATE(i).si_next_list = NULL;
+ update_si_attr(i);
+ }
+ current_state.ga_len = from->sst_stacksize;
+ current_state.ga_room -= current_state.ga_len;
+ }
+ current_next_list = from->sst_next_list;
+ current_next_flags = from->sst_next_flags;
+ current_lnum = from->sst_lnum;
+}
+
+/*
+ * Compare saved state stack "*sp" with the current state.
+ * Return TRUE when they are equal.
+ */
+ static int
+syn_stack_equal(sp)
+ synstate_T *sp;
+{
+ int i, j;
+ bufstate_T *bp;
+ reg_extmatch_T *six, *bsx;
+
+ /* First a quick check if the stacks have the same size end nextlist. */
+ if (sp->sst_stacksize == current_state.ga_len
+ && sp->sst_next_list == current_next_list)
+ {
+ /* Need to compare all states on both stacks. */
+ if (sp->sst_stacksize > SST_FIX_STATES)
+ bp = SYN_STATE_P(&(sp->sst_union.sst_ga));
+ else
+ bp = sp->sst_union.sst_stack;
+
+ for (i = current_state.ga_len; --i >= 0; )
+ {
+ /* If the item has another index the state is different. */
+ if (bp[i].bs_idx != CUR_STATE(i).si_idx)
+ break;
+ if (bp[i].bs_extmatch != CUR_STATE(i).si_extmatch)
+ {
+ /* When the extmatch pointers are different, the strings in
+ * them can still be the same. Check if the extmatch
+ * references are equal. */
+ bsx = bp[i].bs_extmatch;
+ six = CUR_STATE(i).si_extmatch;
+ /* If one of the extmatch pointers is NULL the states are
+ * different. */
+ if (bsx == NULL || six == NULL)
+ break;
+ for (j = 0; j < NSUBEXP; ++j)
+ {
+ /* Check each referenced match string. They must all be
+ * equal. */
+ if (bsx->matches[j] != six->matches[j])
+ {
+ /* If the pointer is different it can still be the
+ * same text. Compare the strings, ignore case when
+ * the start item has the sp_ic flag set. */
+ if (bsx->matches[j] == NULL
+ || six->matches[j] == NULL)
+ break;
+ if ((SYN_ITEMS(syn_buf)[CUR_STATE(i).si_idx]).sp_ic
+ ? MB_STRICMP(bsx->matches[j],
+ six->matches[j]) != 0
+ : STRCMP(bsx->matches[j], six->matches[j]) != 0)
+ break;
+ }
+ }
+ if (j != NSUBEXP)
+ break;
+ }
+ }
+ if (i < 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * We stop parsing syntax above line "lnum". If the stored state at or below
+ * this line depended on a change before it, it now depends on the line below
+ * the last parsed line.
+ * The window looks like this:
+ * line which changed
+ * displayed line
+ * displayed line
+ * lnum -> line below window
+ */
+ void
+syntax_end_parsing(lnum)
+ linenr_T lnum;
+{
+ synstate_T *sp;
+
+ sp = syn_stack_find_entry(lnum);
+ if (sp != NULL && sp->sst_lnum < lnum)
+ sp = sp->sst_next;
+
+ if (sp != NULL && sp->sst_change_lnum != 0)
+ sp->sst_change_lnum = lnum;
+}
+
+/*
+ * End of handling of the state stack.
+ ****************************************/
+
+ static void
+invalidate_current_state()
+{
+ clear_current_state();
+ current_state.ga_itemsize = 0; /* mark current_state invalid */
+ current_next_list = NULL;
+ keepend_level = -1;
+}
+
+ static void
+validate_current_state()
+{
+ current_state.ga_itemsize = sizeof(stateitem_T);
+ current_state.ga_growsize = 3;
+}
+
+/*
+ * Return TRUE if the syntax at start of lnum changed since last time.
+ * This will only be called just after get_syntax_attr() for the previous
+ * line, to check if the next line needs to be redrawn too.
+ */
+ int
+syntax_check_changed(lnum)
+ linenr_T lnum;
+{
+ int retval = TRUE;
+ synstate_T *sp;
+
+ reg_syn = TRUE; /* let vim_regexec() know we're using syntax */
+
+ /*
+ * Check the state stack when:
+ * - lnum is just below the previously syntaxed line.
+ * - lnum is not before the lines with saved states.
+ * - lnum is not past the lines with saved states.
+ * - lnum is at or before the last changed line.
+ */
+ if (VALID_STATE(&current_state) && lnum == current_lnum + 1)
+ {
+ sp = syn_stack_find_entry(lnum);
+ if (sp != NULL && sp->sst_lnum == lnum)
+ {
+ /*
+ * finish the previous line (needed when not all of the line was
+ * drawn)
+ */
+ (void)syn_finish_line(FALSE);
+
+ /*
+ * Compare the current state with the previously saved state of
+ * the line.
+ */
+ if (syn_stack_equal(sp))
+ retval = FALSE;
+
+ /*
+ * Store the current state in b_sst_array[] for later use.
+ */
+ ++current_lnum;
+ (void)store_current_state(NULL);
+ }
+ }
+
+ reg_syn = FALSE;
+
+ return retval;
+}
+
+/*
+ * Finish the current line.
+ * This doesn't return any attributes, it only gets the state at the end of
+ * the line. It can start anywhere in the line, as long as the current state
+ * is valid.
+ */
+ static int
+syn_finish_line(syncing)
+ int syncing; /* called for syncing */
+{
+ stateitem_T *cur_si;
+
+ if (!current_finished)
+ {
+ while (!current_finished)
+ {
+ (void)syn_current_attr(syncing, FALSE);
+ /*
+ * When syncing, and found some item, need to check the item.
+ */
+ if (syncing && current_state.ga_len)
+ {
+ /*
+ * Check for match with sync item.
+ */
+ cur_si = &CUR_STATE(current_state.ga_len - 1);
+ if (cur_si->si_idx >= 0
+ && (SYN_ITEMS(syn_buf)[cur_si->si_idx].sp_flags
+ & (HL_SYNC_HERE|HL_SYNC_THERE)))
+ return TRUE;
+
+ /* syn_current_attr() will have skipped the check for an item
+ * that ends here, need to do that now. */
+ ++current_col;
+ check_state_ends();
+ --current_col;
+ }
+ ++current_col;
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * Return highlight attributes for next character.
+ * Must first call syntax_start() once for the line.
+ * "col" is normally 0 for the first use in a line, and increments by one each
+ * time. It's allowed to skip characters and to stop before the end of the
+ * line. But only a "col" after a previously used column is allowed.
+ */
+ int
+get_syntax_attr(col)
+ colnr_T col;
+{
+ int attr = 0;
+
+ /* check for out of memory situation */
+ if (syn_buf->b_sst_array == NULL)
+ return 0;
+
+ reg_syn = TRUE; /* let vim_regexec() know we're using syntax */
+
+ /* Make sure current_state is valid */
+ if (INVALID_STATE(&current_state))
+ validate_current_state();
+
+ /*
+ * Skip from the current column to "col", get the attributes for "col".
+ */
+ while (current_col <= col)
+ {
+ attr = syn_current_attr(FALSE, TRUE);
+ ++current_col;
+ }
+
+ reg_syn = FALSE;
+ return attr;
+}
+
+/*
+ * Get syntax attributes for current_lnum, current_col.
+ */
+ static int
+syn_current_attr(syncing, displaying)
+ int syncing; /* When 1: called for syncing */
+ int displaying; /* result will be displayed */
+{
+ int syn_id;
+ lpos_T endpos; /* was: char_u *endp; */
+ lpos_T hl_startpos; /* was: int hl_startcol; */
+ lpos_T hl_endpos;
+ lpos_T eos_pos; /* end-of-start match (start region) */
+ lpos_T eoe_pos; /* end-of-end pattern */
+ int end_idx; /* group ID for end pattern */
+ int idx;
+ synpat_T *spp;
+ stateitem_T *cur_si, *sip;
+ int startcol;
+ int endcol;
+ long flags;
+ short *next_list;
+ int found_match; /* found usable match */
+ static int try_next_column = FALSE; /* must try in next col */
+ int do_keywords;
+ regmmatch_T regmatch;
+ lpos_T pos;
+ int lc_col;
+ reg_extmatch_T *cur_extmatch = NULL;
+ char_u *line; /* current line. NOTE: becomes invalid after
+ looking for a pattern match! */
+
+ /* variables for zero-width matches that have a "nextgroup" argument */
+ int keep_next_list;
+ int zero_width_next_list = FALSE;
+ garray_T zero_width_next_ga;
+
+ /*
+ * No character, no attributes! Past end of line?
+ * Do try matching with an empty line (could be the start of a region).
+ */
+ line = syn_getcurline();
+ if (line[current_col] == NUL && current_col != 0)
+ {
+ /*
+ * If we found a match after the last column, use it.
+ */
+ if (next_match_idx >= 0 && next_match_col >= (int)current_col
+ && next_match_col != MAXCOL)
+ (void)push_next_match(NULL);
+
+ current_finished = TRUE;
+ current_state_stored = FALSE;
+ return 0;
+ }
+
+ /* if the current or next character is NUL, we will finish the line now */
+ if (line[current_col] == NUL || line[current_col + 1] == NUL)
+ {
+ current_finished = TRUE;
+ current_state_stored = FALSE;
+ }
+
+ /*
+ * When in the previous column there was a match but it could not be used
+ * (empty match or already matched in this column) need to try again in
+ * the next column.
+ */
+ if (try_next_column)
+ {
+ next_match_idx = -1;
+ try_next_column = FALSE;
+ }
+
+ /* Only check for keywords when not syncing and there are some. */
+ do_keywords = !syncing
+ && (syn_buf->b_keywtab != NULL
+ || syn_buf->b_keywtab_ic != NULL);
+
+ /* Init the list of zero-width matches with a nextlist. This is used to
+ * avoid matching the same item in the same position twice. */
+ ga_init2(&zero_width_next_ga, (int)sizeof(int), 10);
+
+ /*
+ * Repeat matching keywords and patterns, to find contained items at the
+ * same column. This stops when there are no extra matches at the current
+ * column.
+ */
+ do
+ {
+ found_match = FALSE;
+ keep_next_list = FALSE;
+ syn_id = 0;
+
+ /*
+ * 1. Check for a current state.
+ * Only when there is no current state, or if the current state may
+ * contain other things, we need to check for keywords and patterns.
+ * Always need to check for contained items if some item has the
+ * "containedin" argument (takes extra time!).
+ */
+ if (current_state.ga_len)
+ cur_si = &CUR_STATE(current_state.ga_len - 1);
+ else
+ cur_si = NULL;
+
+ if (syn_buf->b_syn_containedin || cur_si == NULL
+ || cur_si->si_cont_list != NULL)
+ {
+ /*
+ * 2. Check for keywords, if on a keyword char after a non-keyword
+ * char. Don't do this when syncing.
+ */
+ if (do_keywords)
+ {
+ line = syn_getcurline();
+ if (vim_iswordc_buf(line + current_col, syn_buf)
+ && (current_col == 0
+ || !vim_iswordc_buf(line + current_col - 1
+#ifdef FEAT_MBYTE
+ - (has_mbyte
+ ? (*mb_head_off)(line, line + current_col - 1)
+ : 0)
+#endif
+ , syn_buf)))
+ {
+ syn_id = check_keyword_id(line, (int)current_col,
+ &endcol, &flags, &next_list, cur_si);
+ if (syn_id)
+ {
+ if (push_current_state(KEYWORD_IDX) == OK)
+ {
+ cur_si = &CUR_STATE(current_state.ga_len - 1);
+ cur_si->si_m_startcol = current_col;
+ cur_si->si_h_startpos.lnum = current_lnum;
+ cur_si->si_h_startpos.col = 0; /* starts right away */
+ cur_si->si_m_endpos.lnum = current_lnum;
+ cur_si->si_m_endpos.col = endcol;
+ cur_si->si_h_endpos.lnum = current_lnum;
+ cur_si->si_h_endpos.col = endcol;
+ cur_si->si_ends = TRUE;
+ cur_si->si_end_idx = 0;
+ cur_si->si_flags = flags;
+ cur_si->si_id = syn_id;
+ cur_si->si_trans_id = syn_id;
+ if (flags & HL_TRANSP)
+ {
+ if (current_state.ga_len < 2)
+ {
+ cur_si->si_attr = 0;
+ cur_si->si_trans_id = 0;
+ }
+ else
+ {
+ cur_si->si_attr = CUR_STATE(
+ current_state.ga_len - 2).si_attr;
+ cur_si->si_trans_id = CUR_STATE(
+ current_state.ga_len - 2).si_trans_id;
+ }
+ }
+ else
+ cur_si->si_attr = syn_id2attr(syn_id);
+ cur_si->si_cont_list = NULL;
+ cur_si->si_next_list = next_list;
+ check_keepend();
+ }
+ else
+ vim_free(next_list);
+ }
+ }
+ }
+
+ /*
+ * 3. Check for patterns (only if not found a keyword).
+ */
+ if (syn_id == 0 && syn_buf->b_syn_patterns.ga_len)
+ {
+ /*
+ * If we didn't check for a match yet, or we are past it, check
+ * for any match with a pattern.
+ */
+ if (next_match_idx < 0 || next_match_col < (int)current_col)
+ {
+ /*
+ * Check all relevant patterns for a match at this
+ * position. This is complicated, because matching with a
+ * pattern takes quite a bit of time, thus we want to
+ * avoid doing it when it's not needed.
+ */
+ next_match_idx = 0; /* no match in this line yet */
+ next_match_col = MAXCOL;
+ for (idx = syn_buf->b_syn_patterns.ga_len; --idx >= 0; )
+ {
+ spp = &(SYN_ITEMS(syn_buf)[idx]);
+ if ( spp->sp_syncing == syncing
+ && (displaying || !(spp->sp_flags & HL_DISPLAY))
+ && (spp->sp_type == SPTYPE_MATCH
+ || spp->sp_type == SPTYPE_START)
+ && (current_next_list != NULL
+ ? in_id_list(NULL, current_next_list,
+ &spp->sp_syn, 0)
+ : (cur_si == NULL
+ ? !(spp->sp_flags & HL_CONTAINED)
+ : in_id_list(cur_si,
+ cur_si->si_cont_list, &spp->sp_syn,
+ spp->sp_flags & HL_CONTAINED))))
+ {
+ /* If we already tried matching in this line, and
+ * there isn't a match before next_match_col, skip
+ * this item. */
+ if (spp->sp_line_id == current_line_id
+ && spp->sp_startcol >= next_match_col)
+ continue;
+ spp->sp_line_id = current_line_id;
+
+ lc_col = current_col - spp->sp_offsets[SPO_LC_OFF];
+ if (lc_col < 0)
+ lc_col = 0;
+
+ regmatch.rmm_ic = spp->sp_ic;
+ regmatch.regprog = spp->sp_prog;
+ if (!syn_regexec(&regmatch, current_lnum,
+ (colnr_T)lc_col))
+ {
+ /* no match in this line, try another one */
+ spp->sp_startcol = MAXCOL;
+ continue;
+ }
+
+ /*
+ * Compute the first column of the match.
+ */
+ syn_add_start_off(&pos, &regmatch,
+ spp, SPO_MS_OFF, -1);
+ if (pos.lnum > current_lnum)
+ {
+ /* must have used end of match in a next line,
+ * we can't handle that */
+ spp->sp_startcol = MAXCOL;
+ continue;
+ }
+ startcol = pos.col;
+
+ /* remember the next column where this pattern
+ * matches in the current line */
+ spp->sp_startcol = startcol;
+
+ /*
+ * If a previously found match starts at a lower
+ * column number, don't use this one.
+ */
+ if (startcol >= next_match_col)
+ continue;
+
+ /*
+ * If we matched this pattern at this position
+ * before, skip it. Must retry in the next
+ * column, because it may match from there.
+ */
+ if (did_match_already(idx, &zero_width_next_ga))
+ {
+ try_next_column = TRUE;
+ continue;
+ }
+
+ endpos.lnum = regmatch.endpos[0].lnum;
+ endpos.col = regmatch.endpos[0].col;
+
+ /* Compute the highlight start. */
+ syn_add_start_off(&hl_startpos, &regmatch,
+ spp, SPO_HS_OFF, -1);
+
+ /* Compute the region start. */
+ /* Default is to use the end of the match. */
+ syn_add_end_off(&eos_pos, &regmatch,
+ spp, SPO_RS_OFF, 0);
+
+ /*
+ * Grab the external submatches before they get
+ * overwritten. Reference count doesn't change.
+ */
+ unref_extmatch(cur_extmatch);
+ cur_extmatch = re_extmatch_out;
+ re_extmatch_out = NULL;
+
+ flags = 0;
+ eoe_pos.lnum = 0; /* avoid warning */
+ eoe_pos.col = 0;
+ end_idx = 0;
+ hl_endpos.lnum = 0;
+
+ /*
+ * For a "oneline" the end must be found in the
+ * same line too. Search for it after the end of
+ * the match with the start pattern. Set the
+ * resulting end positions at the same time.
+ */
+ if (spp->sp_type == SPTYPE_START
+ && (spp->sp_flags & HL_ONELINE))
+ {
+ lpos_T startpos;
+
+ startpos = endpos;
+ find_endpos(idx, &startpos, &endpos, &hl_endpos,
+ &flags, &eoe_pos, &end_idx, cur_extmatch);
+ if (endpos.lnum == 0)
+ continue; /* not found */
+ }
+
+ /*
+ * For a "match" the size must be > 0 after the
+ * end offset needs has been added. Except when
+ * syncing.
+ */
+ else if (spp->sp_type == SPTYPE_MATCH)
+ {
+ syn_add_end_off(&hl_endpos, &regmatch, spp,
+ SPO_HE_OFF, 0);
+ syn_add_end_off(&endpos, &regmatch, spp,
+ SPO_ME_OFF, 0);
+ if (endpos.lnum == current_lnum
+ && (int)endpos.col + syncing < startcol)
+ {
+ /*
+ * If an empty string is matched, may need
+ * to try matching again at next column.
+ */
+ if (regmatch.startpos[0].col
+ == regmatch.endpos[0].col)
+ try_next_column = TRUE;
+ continue;
+ }
+ }
+
+ /*
+ * keep the best match so far in next_match_*
+ */
+ /* Highlighting must start after startpos and end
+ * before endpos. */
+ if (hl_startpos.lnum == current_lnum
+ && (int)hl_startpos.col < startcol)
+ hl_startpos.col = startcol;
+ limit_pos_zero(&hl_endpos, &endpos);
+
+ next_match_idx = idx;
+ next_match_col = startcol;
+ next_match_m_endpos = endpos;
+ next_match_h_endpos = hl_endpos;
+ next_match_h_startpos = hl_startpos;
+ next_match_flags = flags;
+ next_match_eos_pos = eos_pos;
+ next_match_eoe_pos = eoe_pos;
+ next_match_end_idx = end_idx;
+ unref_extmatch(next_match_extmatch);
+ next_match_extmatch = cur_extmatch;
+ cur_extmatch = NULL;
+ }
+ }
+ }
+
+ /*
+ * If we found a match at the current column, use it.
+ */
+ if (next_match_idx >= 0 && next_match_col == (int)current_col)
+ {
+ synpat_T *lspp;
+
+ /* When a zero-width item matched which has a nextgroup,
+ * don't push the item but set nextgroup. */
+ lspp = &(SYN_ITEMS(syn_buf)[next_match_idx]);
+ if (next_match_m_endpos.lnum == current_lnum
+ && next_match_m_endpos.col == current_col
+ && lspp->sp_next_list != NULL)
+ {
+ current_next_list = lspp->sp_next_list;
+ current_next_flags = lspp->sp_flags;
+ keep_next_list = TRUE;
+ zero_width_next_list = TRUE;
+
+ /* Add the index to a list, so that we can check
+ * later that we don't match it again (and cause an
+ * endless loop). */
+ if (ga_grow(&zero_width_next_ga, 1) == OK)
+ {
+ ((int *)(zero_width_next_ga.ga_data))
+ [zero_width_next_ga.ga_len++] = next_match_idx;
+ --zero_width_next_ga.ga_room;
+ }
+ next_match_idx = -1;
+ }
+ else
+ cur_si = push_next_match(cur_si);
+ found_match = TRUE;
+ }
+ }
+ }
+
+ /*
+ * Handle searching for nextgroup match.
+ */
+ if (current_next_list != NULL && !keep_next_list)
+ {
+ /*
+ * If a nextgroup was not found, continue looking for one if:
+ * - this is an empty line and the "skipempty" option was given
+ * - we are on white space and the "skipwhite" option was given
+ */
+ if (!found_match)
+ {
+ line = syn_getcurline();
+ if (((current_next_flags & HL_SKIPWHITE)
+ && vim_iswhite(line[current_col]))
+ || ((current_next_flags & HL_SKIPEMPTY)
+ && *line == NUL))
+ break;
+ }
+
+ /*
+ * If a nextgroup was found: Use it, and continue looking for
+ * contained matches.
+ * If a nextgroup was not found: Continue looking for a normal
+ * match.
+ * When did set current_next_list for a zero-width item and no
+ * match was found don't loop (would get stuck).
+ */
+ current_next_list = NULL;
+ next_match_idx = -1;
+ if (!zero_width_next_list)
+ found_match = TRUE;
+ }
+
+ } while (found_match);
+
+ /*
+ * Use attributes from the current state, if within its highlighting.
+ * If not, use attributes from the current-but-one state, etc.
+ */
+ current_attr = 0;
+#ifdef FEAT_EVAL
+ current_id = 0;
+ current_trans_id = 0;
+#endif
+ if (cur_si != NULL)
+ {
+ for (idx = current_state.ga_len - 1; idx >= 0; --idx)
+ {
+ sip = &CUR_STATE(idx);
+ if ((current_lnum > sip->si_h_startpos.lnum
+ || (current_lnum == sip->si_h_startpos.lnum
+ && current_col >= sip->si_h_startpos.col))
+ && (sip->si_h_endpos.lnum == 0
+ || current_lnum < sip->si_h_endpos.lnum
+ || (current_lnum == sip->si_h_endpos.lnum
+ && current_col < sip->si_h_endpos.col)))
+ {
+ current_attr = sip->si_attr;
+#ifdef FEAT_EVAL
+ current_id = sip->si_id;
+ current_trans_id = sip->si_trans_id;
+#endif
+ break;
+ }
+ }
+
+ /*
+ * Check for end of current state (and the states before it) at the
+ * next column. Don't do this for syncing, because we would miss a
+ * single character match.
+ * First check if the current state ends at the current column. It
+ * may be for an empty match and a containing item might end in the
+ * current column.
+ */
+ if (!syncing)
+ {
+ check_state_ends();
+ if (current_state.ga_len > 0)
+ {
+ ++current_col;
+ check_state_ends();
+ --current_col;
+ }
+ }
+ }
+
+ /* nextgroup ends at end of line, unless "skipnl" or "skipemtpy" present */
+ if (current_next_list != NULL
+ && syn_getcurline()[current_col + 1] == NUL
+ && !(current_next_flags & (HL_SKIPNL | HL_SKIPEMPTY)))
+ current_next_list = NULL;
+
+ if (zero_width_next_ga.ga_len > 0)
+ ga_clear(&zero_width_next_ga);
+
+ /* No longer need external matches. But keep next_match_extmatch. */
+ unref_extmatch(re_extmatch_out);
+ re_extmatch_out = NULL;
+ unref_extmatch(cur_extmatch);
+
+ return current_attr;
+}
+
+
+/*
+ * Check if we already matched pattern "idx" at the current column.
+ */
+ static int
+did_match_already(idx, gap)
+ int idx;
+ garray_T *gap;
+{
+ int i;
+
+ for (i = current_state.ga_len; --i >= 0; )
+ if (CUR_STATE(i).si_m_startcol == (int)current_col
+ && CUR_STATE(i).si_m_lnum == (int)current_lnum
+ && CUR_STATE(i).si_idx == idx)
+ return TRUE;
+
+ /* Zero-width matches with a nextgroup argument are not put on the syntax
+ * stack, and can only be matched once anyway. */
+ for (i = gap->ga_len; --i >= 0; )
+ if (((int *)(gap->ga_data))[i] == idx)
+ return TRUE;
+
+ return FALSE;
+}
+
+/*
+ * Push the next match onto the stack.
+ */
+ static stateitem_T *
+push_next_match(cur_si)
+ stateitem_T *cur_si;
+{
+ synpat_T *spp;
+
+ spp = &(SYN_ITEMS(syn_buf)[next_match_idx]);
+
+ /*
+ * Push the item in current_state stack;
+ */
+ if (push_current_state(next_match_idx) == OK)
+ {
+ /*
+ * If it's a start-skip-end type that crosses lines, figure out how
+ * much it continues in this line. Otherwise just fill in the length.
+ */
+ cur_si = &CUR_STATE(current_state.ga_len - 1);
+ cur_si->si_h_startpos = next_match_h_startpos;
+ cur_si->si_m_startcol = current_col;
+ cur_si->si_m_lnum = current_lnum;
+ cur_si->si_flags = spp->sp_flags;
+ cur_si->si_next_list = spp->sp_next_list;
+ cur_si->si_extmatch = ref_extmatch(next_match_extmatch);
+ if (spp->sp_type == SPTYPE_START && !(spp->sp_flags & HL_ONELINE))
+ {
+ /* Try to find the end pattern in the current line */
+ update_si_end(cur_si, (int)(next_match_m_endpos.col), TRUE);
+ check_keepend();
+ }
+ else
+ {
+ cur_si->si_m_endpos = next_match_m_endpos;
+ cur_si->si_h_endpos = next_match_h_endpos;
+ cur_si->si_ends = TRUE;
+ cur_si->si_flags |= next_match_flags;
+ cur_si->si_eoe_pos = next_match_eoe_pos;
+ cur_si->si_end_idx = next_match_end_idx;
+ }
+ if (keepend_level < 0 && (cur_si->si_flags & HL_KEEPEND))
+ keepend_level = current_state.ga_len - 1;
+ check_keepend();
+ update_si_attr(current_state.ga_len - 1);
+
+ /*
+ * If the start pattern has another highlight group, push another item
+ * on the stack for the start pattern.
+ */
+ if ( spp->sp_type == SPTYPE_START
+ && spp->sp_syn_match_id != 0
+ && push_current_state(next_match_idx) == OK)
+ {
+ cur_si = &CUR_STATE(current_state.ga_len - 1);
+ cur_si->si_h_startpos = next_match_h_startpos;
+ cur_si->si_m_startcol = current_col;
+ cur_si->si_m_lnum = current_lnum;
+ cur_si->si_m_endpos = next_match_eos_pos;
+ cur_si->si_h_endpos = next_match_eos_pos;
+ cur_si->si_ends = TRUE;
+ cur_si->si_end_idx = 0;
+ cur_si->si_flags = HL_MATCH;
+ cur_si->si_next_list = NULL;
+ check_keepend();
+ update_si_attr(current_state.ga_len - 1);
+ }
+ }
+
+ next_match_idx = -1; /* try other match next time */
+
+ return cur_si;
+}
+
+/*
+ * Check for end of current state (and the states before it).
+ */
+ static void
+check_state_ends()
+{
+ stateitem_T *cur_si;
+ int had_extend = FALSE;
+
+ cur_si = &CUR_STATE(current_state.ga_len - 1);
+ for (;;)
+ {
+ if (cur_si->si_ends
+ && (cur_si->si_m_endpos.lnum < current_lnum
+ || (cur_si->si_m_endpos.lnum == current_lnum
+ && cur_si->si_m_endpos.col <= current_col)))
+ {
+ /*
+ * If there is an end pattern group ID, highlight the end pattern
+ * now. No need to pop the current item from the stack.
+ * Only do this if the end pattern continues beyond the current
+ * position.
+ */
+ if (cur_si->si_end_idx
+ && (cur_si->si_eoe_pos.lnum > current_lnum
+ || (cur_si->si_eoe_pos.lnum == current_lnum
+ && cur_si->si_eoe_pos.col > current_col)))
+ {
+ cur_si->si_idx = cur_si->si_end_idx;
+ cur_si->si_end_idx = 0;
+ cur_si->si_m_endpos = cur_si->si_eoe_pos;
+ cur_si->si_h_endpos = cur_si->si_eoe_pos;
+ cur_si->si_flags |= HL_MATCH;
+ update_si_attr(current_state.ga_len - 1);
+ break;
+ }
+ else
+ {
+ /* handle next_list, unless at end of line and no "skipnl" or
+ * "skipempty" */
+ current_next_list = cur_si->si_next_list;
+ current_next_flags = cur_si->si_flags;
+ if (!(current_next_flags & (HL_SKIPNL | HL_SKIPEMPTY))
+ && syn_getcurline()[current_col] == NUL)
+ current_next_list = NULL;
+
+ /* When the ended item has "extend", another item with
+ * "keepend" now needs to check for its end. */
+ if (cur_si->si_flags & HL_EXTEND)
+ had_extend = TRUE;
+
+ pop_current_state();
+
+ if (current_state.ga_len == 0)
+ break;
+
+ if (had_extend)
+ {
+ syn_update_ends(FALSE);
+ if (current_state.ga_len == 0)
+ break;
+ }
+
+ cur_si = &CUR_STATE(current_state.ga_len - 1);
+
+ /*
+ * Only for a region the search for the end continues after
+ * the end of the contained item. If the contained match
+ * included the end-of-line, break here, the region continues.
+ * Don't do this when:
+ * - "keepend" is used for the contained item
+ * - not at the end of the line (could be end="x$"me=e-1).
+ * - "excludenl" is used (HL_HAS_EOL won't be set)
+ */
+ if (cur_si->si_idx >= 0
+ && SYN_ITEMS(syn_buf)[cur_si->si_idx].sp_type
+ == SPTYPE_START
+ && !(cur_si->si_flags & (HL_MATCH | HL_KEEPEND)))
+ {
+ update_si_end(cur_si, (int)current_col, TRUE);
+ check_keepend();
+ if ((current_next_flags & HL_HAS_EOL)
+ && keepend_level < 0
+ && syn_getcurline()[current_col] == NUL)
+ break;
+ }
+ }
+ }
+ else
+ break;
+ }
+}
+
+/*
+ * Update an entry in the current_state stack for a match or region. This
+ * fills in si_attr, si_next_list and si_cont_list.
+ */
+ static void
+update_si_attr(idx)
+ int idx;
+{
+ stateitem_T *sip = &CUR_STATE(idx);
+ synpat_T *spp;
+
+ spp = &(SYN_ITEMS(syn_buf)[sip->si_idx]);
+ if (sip->si_flags & HL_MATCH)
+ sip->si_id = spp->sp_syn_match_id;
+ else
+ sip->si_id = spp->sp_syn.id;
+ sip->si_attr = syn_id2attr(sip->si_id);
+ sip->si_trans_id = sip->si_id;
+ if (sip->si_flags & HL_MATCH)
+ sip->si_cont_list = NULL;
+ else
+ sip->si_cont_list = spp->sp_cont_list;
+
+ /*
+ * For transparent items, take attr from outer item.
+ * Also take cont_list, if there is none.
+ * Don't do this for the matchgroup of a start or end pattern.
+ */
+ if ((spp->sp_flags & HL_TRANSP) && !(sip->si_flags & HL_MATCH))
+ {
+ if (idx == 0)
+ {
+ sip->si_attr = 0;
+ sip->si_trans_id = 0;
+ if (sip->si_cont_list == NULL)
+ sip->si_cont_list = ID_LIST_ALL;
+ }
+ else
+ {
+ sip->si_attr = CUR_STATE(idx - 1).si_attr;
+ sip->si_trans_id = CUR_STATE(idx - 1).si_trans_id;
+ if (sip->si_cont_list == NULL)
+ {
+ sip->si_flags |= HL_TRANS_CONT;
+ sip->si_cont_list = CUR_STATE(idx - 1).si_cont_list;
+ }
+ }
+ }
+}
+
+/*
+ * Check the current stack for patterns with "keepend" flag.
+ * Propagate the match-end to contained items, until a "skipend" item is found.
+ */
+ static void
+check_keepend()
+{
+ int i;
+ lpos_T maxpos;
+ stateitem_T *sip;
+
+ /*
+ * This check can consume a lot of time; only do it from the level where
+ * there really is a keepend.
+ */
+ if (keepend_level < 0)
+ return;
+
+ /*
+ * Find the last index of an "extend" item. "keepend" items before that
+ * won't do anything. If there is no "extend" item "i" will be
+ * "keepend_level" and all "keepend" items will work normally.
+ */
+ for (i = current_state.ga_len - 1; i > keepend_level; --i)
+ if (CUR_STATE(i).si_flags & HL_EXTEND)
+ break;
+
+ maxpos.lnum = 0;
+ for ( ; i < current_state.ga_len; ++i)
+ {
+ sip = &CUR_STATE(i);
+ if (maxpos.lnum != 0)
+ {
+ limit_pos_zero(&sip->si_m_endpos, &maxpos);
+ limit_pos_zero(&sip->si_h_endpos, &maxpos);
+ limit_pos_zero(&sip->si_eoe_pos, &maxpos);
+ sip->si_ends = TRUE;
+ }
+ if (sip->si_ends
+ && (sip->si_flags & HL_KEEPEND)
+ && (maxpos.lnum == 0
+ || maxpos.lnum > sip->si_m_endpos.lnum
+ || (maxpos.lnum == sip->si_m_endpos.lnum
+ && maxpos.col > sip->si_m_endpos.col)))
+ maxpos = sip->si_m_endpos;
+ }
+}
+
+/*
+ * Update an entry in the current_state stack for a start-skip-end pattern.
+ * This finds the end of the current item, if it's in the current line.
+ *
+ * Return the flags for the matched END.
+ */
+ static void
+update_si_end(sip, startcol, force)
+ stateitem_T *sip;
+ int startcol; /* where to start searching for the end */
+ int force; /* when TRUE overrule a previous end */
+{
+ lpos_T startpos;
+ lpos_T endpos;
+ lpos_T hl_endpos;
+ lpos_T end_endpos;
+ int end_idx;
+
+ /* Don't update when it's already done. Can be a match of an end pattern
+ * that started in a previous line. Watch out: can also be a "keepend"
+ * from a containing item. */
+ if (!force && sip->si_m_endpos.lnum >= current_lnum)
+ return;
+
+ /*
+ * We need to find the end of the region. It may continue in the next
+ * line.
+ */
+ end_idx = 0;
+ startpos.lnum = current_lnum;
+ startpos.col = startcol;
+ find_endpos(sip->si_idx, &startpos, &endpos, &hl_endpos,
+ &(sip->si_flags), &end_endpos, &end_idx, sip->si_extmatch);
+
+ if (endpos.lnum == 0)
+ {
+ /* No end pattern matched. */
+ if (SYN_ITEMS(syn_buf)[sip->si_idx].sp_flags & HL_ONELINE)
+ {
+ /* a "oneline" never continues in the next line */
+ sip->si_ends = TRUE;
+ sip->si_m_endpos.lnum = current_lnum;
+ sip->si_m_endpos.col = (colnr_T)STRLEN(syn_getcurline());
+ }
+ else
+ {
+ /* continues in the next line */
+ sip->si_ends = FALSE;
+ sip->si_m_endpos.lnum = 0;
+ }
+ sip->si_h_endpos = sip->si_m_endpos;
+ }
+ else
+ {
+ /* match within this line */
+ sip->si_m_endpos = endpos;
+ sip->si_h_endpos = hl_endpos;
+ sip->si_eoe_pos = end_endpos;
+ sip->si_ends = TRUE;
+ sip->si_end_idx = end_idx;
+ }
+}
+
+/*
+ * Add a new state to the current state stack.
+ * It is cleared and the index set to "idx".
+ * Return FAIL if it's not possible (out of memory).
+ */
+ static int
+push_current_state(idx)
+ int idx;
+{
+ if (ga_grow(&current_state, 1) == FAIL)
+ return FAIL;
+ vim_memset(&CUR_STATE(current_state.ga_len), 0, sizeof(stateitem_T));
+ CUR_STATE(current_state.ga_len).si_idx = idx;
+ ++current_state.ga_len;
+ --current_state.ga_room;
+ return OK;
+}
+
+/*
+ * Remove a state from the current_state stack.
+ */
+ static void
+pop_current_state()
+{
+ if (current_state.ga_len)
+ {
+ unref_extmatch(CUR_STATE(current_state.ga_len - 1).si_extmatch);
+ --current_state.ga_len;
+ ++current_state.ga_room;
+ }
+ /* after the end of a pattern, try matching a keyword or pattern */
+ next_match_idx = -1;
+
+ /* if first state with "keepend" is popped, reset keepend_level */
+ if (keepend_level >= current_state.ga_len)
+ keepend_level = -1;
+}
+
+/*
+ * Find the end of a start/skip/end syntax region after "startpos".
+ * Only checks one line.
+ * Also handles a match item that continued from a previous line.
+ * If not found, the syntax item continues in the next line. m_endpos->lnum
+ * will be 0.
+ * If found, the end of the region and the end of the highlighting is
+ * computed.
+ */
+ static void
+find_endpos(idx, startpos, m_endpos, hl_endpos, flagsp, end_endpos,
+ end_idx, start_ext)
+ int idx; /* index of the pattern */
+ lpos_T *startpos; /* where to start looking for an END match */
+ lpos_T *m_endpos; /* return: end of match */
+ lpos_T *hl_endpos; /* return: end of highlighting */
+ long *flagsp; /* return: flags of matching END */
+ lpos_T *end_endpos; /* return: end of end pattern match */
+ int *end_idx; /* return: group ID for end pat. match, or 0 */
+ reg_extmatch_T *start_ext; /* submatches from the start pattern */
+{
+ colnr_T matchcol;
+ synpat_T *spp, *spp_skip;
+ int start_idx;
+ int best_idx;
+ regmmatch_T regmatch;
+ regmmatch_T best_regmatch; /* startpos/endpos of best match */
+ lpos_T pos;
+ char_u *line;
+ int had_match = FALSE;
+
+ /*
+ * Check for being called with a START pattern.
+ * Can happen with a match that continues to the next line, because it
+ * contained a region.
+ */
+ spp = &(SYN_ITEMS(syn_buf)[idx]);
+ if (spp->sp_type != SPTYPE_START)
+ {
+ *hl_endpos = *startpos;
+ return;
+ }
+
+ /*
+ * Find the SKIP or first END pattern after the last START pattern.
+ */
+ for (;;)
+ {
+ spp = &(SYN_ITEMS(syn_buf)[idx]);
+ if (spp->sp_type != SPTYPE_START)
+ break;
+ ++idx;
+ }
+
+ /*
+ * Lookup the SKIP pattern (if present)
+ */
+ if (spp->sp_type == SPTYPE_SKIP)
+ {
+ spp_skip = spp;
+ ++idx;
+ }
+ else
+ spp_skip = NULL;
+
+ /* Setup external matches for syn_regexec(). */
+ unref_extmatch(re_extmatch_in);
+ re_extmatch_in = ref_extmatch(start_ext);
+
+ matchcol = startpos->col; /* start looking for a match at sstart */
+ start_idx = idx; /* remember the first END pattern. */
+ best_regmatch.startpos[0].col = 0; /* avoid compiler warning */
+ for (;;)
+ {
+ /*
+ * Find end pattern that matches first after "matchcol".
+ */
+ best_idx = -1;
+ for (idx = start_idx; idx < syn_buf->b_syn_patterns.ga_len; ++idx)
+ {
+ int lc_col = matchcol;
+
+ spp = &(SYN_ITEMS(syn_buf)[idx]);
+ if (spp->sp_type != SPTYPE_END) /* past last END pattern */
+ break;
+ lc_col -= spp->sp_offsets[SPO_LC_OFF];
+ if (lc_col < 0)
+ lc_col = 0;
+
+ regmatch.rmm_ic = spp->sp_ic;
+ regmatch.regprog = spp->sp_prog;
+ if (syn_regexec(&regmatch, startpos->lnum, lc_col))
+ {
+ if (best_idx == -1 || regmatch.startpos[0].col
+ < best_regmatch.startpos[0].col)
+ {
+ best_idx = idx;
+ best_regmatch.startpos[0] = regmatch.startpos[0];
+ best_regmatch.endpos[0] = regmatch.endpos[0];
+ }
+ }
+ }
+
+ /*
+ * If all end patterns have been tried, and there is no match, the
+ * item continues until end-of-line.
+ */
+ if (best_idx == -1)
+ break;
+
+ /*
+ * If the skip pattern matches before the end pattern,
+ * continue searching after the skip pattern.
+ */
+ if (spp_skip != NULL)
+ {
+ int lc_col = matchcol - spp_skip->sp_offsets[SPO_LC_OFF];
+
+ if (lc_col < 0)
+ lc_col = 0;
+ regmatch.rmm_ic = spp_skip->sp_ic;
+ regmatch.regprog = spp_skip->sp_prog;
+ if (syn_regexec(&regmatch, startpos->lnum, lc_col)
+ && regmatch.startpos[0].col
+ <= best_regmatch.startpos[0].col)
+ {
+ /* Add offset to skip pattern match */
+ syn_add_end_off(&pos, &regmatch, spp_skip, SPO_ME_OFF, 1);
+
+ /* If the skip pattern goes on to the next line, there is no
+ * match with an end pattern in this line. */
+ if (pos.lnum > startpos->lnum)
+ break;
+
+ line = ml_get_buf(syn_buf, startpos->lnum, FALSE);
+
+ /* take care of an empty match or negative offset */
+ if (pos.col <= matchcol)
+ ++matchcol;
+ else if (pos.col <= regmatch.endpos[0].col)
+ matchcol = pos.col;
+ else
+ /* Be careful not to jump over the NUL at the end-of-line */
+ for (matchcol = regmatch.endpos[0].col;
+ line[matchcol] != NUL && matchcol < pos.col;
+ ++matchcol)
+ ;
+
+ /* if the skip pattern includes end-of-line, break here */
+ if (line[matchcol] == NUL)
+ break;
+
+ continue; /* start with first end pattern again */
+ }
+ }
+
+ /*
+ * Match from start pattern to end pattern.
+ * Correct for match and highlight offset of end pattern.
+ */
+ spp = &(SYN_ITEMS(syn_buf)[best_idx]);
+ syn_add_end_off(m_endpos, &best_regmatch, spp, SPO_ME_OFF, 1);
+ /* can't end before the start */
+ if (m_endpos->lnum == startpos->lnum && m_endpos->col < startpos->col)
+ m_endpos->col = startpos->col;
+
+ syn_add_end_off(end_endpos, &best_regmatch, spp, SPO_HE_OFF, 1);
+ /* can't end before the start */
+ if (end_endpos->lnum == startpos->lnum
+ && end_endpos->col < startpos->col)
+ end_endpos->col = startpos->col;
+ /* can't end after the match */
+ limit_pos(end_endpos, m_endpos);
+
+ /*
+ * If the end group is highlighted differently, adjust the pointers.
+ */
+ if (spp->sp_syn_match_id != spp->sp_syn.id && spp->sp_syn_match_id != 0)
+ {
+ *end_idx = best_idx;
+ if (spp->sp_off_flags & (1 << (SPO_RE_OFF + SPO_COUNT)))
+ {
+ hl_endpos->lnum = best_regmatch.endpos[0].lnum;
+ hl_endpos->col = best_regmatch.endpos[0].col;
+ }
+ else
+ {
+ hl_endpos->lnum = best_regmatch.startpos[0].lnum;
+ hl_endpos->col = best_regmatch.startpos[0].col;
+ }
+ hl_endpos->col += spp->sp_offsets[SPO_RE_OFF];
+
+ /* can't end before the start */
+ if (hl_endpos->lnum == startpos->lnum
+ && hl_endpos->col < startpos->col)
+ hl_endpos->col = startpos->col;
+ limit_pos(hl_endpos, m_endpos);
+
+ /* now the match ends where the highlighting ends, it is turned
+ * into the matchgroup for the end */
+ *m_endpos = *hl_endpos;
+ }
+ else
+ {
+ *end_idx = 0;
+ *hl_endpos = *end_endpos;
+ }
+
+ *flagsp = spp->sp_flags;
+
+ had_match = TRUE;
+ break;
+ }
+
+ /* no match for an END pattern in this line */
+ if (!had_match)
+ m_endpos->lnum = 0;
+
+ /* Remove external matches. */
+ unref_extmatch(re_extmatch_in);
+ re_extmatch_in = NULL;
+}
+
+/*
+ * Limit "pos" not to be after "limit".
+ */
+ static void
+limit_pos(pos, limit)
+ lpos_T *pos;
+ lpos_T *limit;
+{
+ if (pos->lnum > limit->lnum)
+ *pos = *limit;
+ else if (pos->lnum == limit->lnum && pos->col > limit->col)
+ pos->col = limit->col;
+}
+
+/*
+ * Limit "pos" not to be after "limit", unless pos->lnum is zero.
+ */
+ static void
+limit_pos_zero(pos, limit)
+ lpos_T *pos;
+ lpos_T *limit;
+{
+ if (pos->lnum == 0)
+ *pos = *limit;
+ else
+ limit_pos(pos, limit);
+}
+
+/*
+ * Add offset to matched text for end of match or highlight.
+ */
+ static void
+syn_add_end_off(result, regmatch, spp, idx, extra)
+ lpos_T *result; /* returned position */
+ regmmatch_T *regmatch; /* start/end of match */
+ synpat_T *spp; /* matched pattern */
+ int idx; /* index of offset */
+ int extra; /* extra chars for offset to start */
+{
+ int col;
+
+ if (spp->sp_off_flags & (1 << idx))
+ {
+ result->lnum = regmatch->startpos[0].lnum;
+ col = regmatch->startpos[0].col + extra;
+ }
+ else
+ {
+ result->lnum = regmatch->endpos[0].lnum;
+ col = regmatch->endpos[0].col;
+ }
+ col += spp->sp_offsets[idx];
+ if (col < 0)
+ result->col = 0;
+ else
+ result->col = col;
+}
+
+/*
+ * Add offset to matched text for start of match or highlight.
+ * Avoid resulting column to become negative.
+ */
+ static void
+syn_add_start_off(result, regmatch, spp, idx, extra)
+ lpos_T *result; /* returned position */
+ regmmatch_T *regmatch; /* start/end of match */
+ synpat_T *spp;
+ int idx;
+ int extra; /* extra chars for offset to end */
+{
+ int col;
+
+ if (spp->sp_off_flags & (1 << (idx + SPO_COUNT)))
+ {
+ result->lnum = regmatch->endpos[0].lnum;
+ col = regmatch->endpos[0].col + extra;
+ }
+ else
+ {
+ result->lnum = regmatch->startpos[0].lnum;
+ col = regmatch->startpos[0].col;
+ }
+ col += spp->sp_offsets[idx];
+ if (col < 0)
+ result->col = 0;
+ else
+ result->col = col;
+}
+
+/*
+ * Get current line in syntax buffer.
+ */
+ static char_u *
+syn_getcurline()
+{
+ return ml_get_buf(syn_buf, current_lnum, FALSE);
+}
+
+/*
+ * Call vim_regexec() to match in syn_buf.
+ * Returns TRUE when there is a match.
+ */
+ static int
+syn_regexec(rmp, lnum, col)
+ regmmatch_T *rmp;
+ linenr_T lnum;
+ colnr_T col;
+{
+ if (vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col) > 0)
+ {
+ rmp->startpos[0].lnum += lnum;
+ rmp->endpos[0].lnum += lnum;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Check one position in a line for a matching keyword.
+ * The caller must check if a keyword can start at startcol.
+ * Return it's ID if found, 0 otherwise.
+ */
+ static int
+check_keyword_id(line, startcol, endcolp, flagsp, next_listp, cur_si)
+ char_u *line;
+ int startcol; /* position in line to check for keyword */
+ int *endcolp; /* return: character after found keyword */
+ long *flagsp; /* return: flags of matching keyword */
+ short **next_listp; /* return: next_list of matching keyword */
+ stateitem_T *cur_si; /* item at the top of the stack */
+{
+ keyentry_T *ktab;
+ char_u *p;
+ int round;
+ int len;
+ char_u keyword[MAXKEYWLEN + 1]; /* assume max. keyword len is 80 */
+
+ /* Find first character after the keyword. First character was already
+ * checked. */
+ p = line + startcol;
+ len = 0;
+ do
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ len += (*mb_ptr2len_check)(p + len);
+ else
+#endif
+ ++len;
+ }
+ while (vim_iswordc_buf(p + len, syn_buf));
+
+ if (len > MAXKEYWLEN)
+ return 0;
+
+ /*
+ * Must make a copy of the keyword, so we can add a NUL and make it
+ * lowercase.
+ */
+ STRNCPY(keyword, p, len);
+ keyword[len] = NUL;
+
+ /*
+ * Try twice:
+ * 1. matching case
+ * 2. ignoring case
+ */
+ for (round = 1; round <= 2; ++round)
+ {
+ if ((round == 1 ? syn_buf->b_keywtab : syn_buf->b_keywtab_ic) == NULL)
+ continue;
+ if (round == 1) /* match case */
+ ktab = syn_buf->b_keywtab[syn_khash(keyword)];
+ else /* round == 2, ignore case */
+ {
+ p = str_foldcase(keyword, (int)STRLEN(keyword));
+ if (p != NULL)
+ {
+ STRNCPY(keyword, p, MAXKEYWLEN);
+ keyword[MAXKEYWLEN] = NUL;
+ vim_free(p);
+ }
+ ktab = syn_buf->b_keywtab_ic[syn_khash(keyword)];
+ }
+
+ /*
+ * Find keywords that match.
+ * When current_next_list is non-zero accept only that group, otherwise:
+ * Accept a not-contained keyword at toplevel.
+ * Accept a keyword at other levels only if it is in the contains list.
+ */
+ for ( ; ktab != NULL; ktab = ktab->next)
+ if ( STRCMP(keyword, ktab->keyword) == 0
+ && (current_next_list != 0
+ ? in_id_list(NULL, current_next_list, &ktab->k_syn, 0)
+ : (cur_si == NULL
+ ? !(ktab->flags & HL_CONTAINED)
+ : in_id_list(cur_si, cur_si->si_cont_list,
+ &ktab->k_syn, ktab->flags & HL_CONTAINED))))
+ {
+ *endcolp = startcol + len;
+ *flagsp = ktab->flags;
+ *next_listp = ktab->next_list;
+ return ktab->k_syn.id;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Handle ":syntax case" command.
+ */
+/* ARGSUSED */
+ static void
+syn_cmd_case(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* not used */
+{
+ char_u *arg = eap->arg;
+ char_u *next;
+
+ eap->nextcmd = find_nextcmd(arg);
+ if (eap->skip)
+ return;
+
+ next = skiptowhite(arg);
+ if (STRNICMP(arg, "match", 5) == 0 && next - arg == 5)
+ curbuf->b_syn_ic = FALSE;
+ else if (STRNICMP(arg, "ignore", 6) == 0 && next - arg == 6)
+ curbuf->b_syn_ic = TRUE;
+ else
+ EMSG2(_("E390: Illegal argument: %s"), arg);
+}
+
+/*
+ * Clear all syntax info for one buffer.
+ */
+ void
+syntax_clear(buf)
+ buf_T *buf;
+{
+ int i;
+
+ curbuf->b_syn_ic = FALSE; /* Use case, by default */
+ curbuf->b_syn_containedin = FALSE;
+
+ /* free the keywords */
+ free_keywtab(buf->b_keywtab);
+ buf->b_keywtab = NULL;
+ free_keywtab(buf->b_keywtab_ic);
+ buf->b_keywtab_ic = NULL;
+
+ /* free the syntax patterns */
+ for (i = buf->b_syn_patterns.ga_len; --i >= 0; )
+ syn_clear_pattern(buf, i);
+ ga_clear(&buf->b_syn_patterns);
+
+ /* free the syntax clusters */
+ for (i = buf->b_syn_clusters.ga_len; --i >= 0; )
+ syn_clear_cluster(buf, i);
+ ga_clear(&buf->b_syn_clusters);
+
+ buf->b_syn_sync_flags = 0;
+ buf->b_syn_sync_minlines = 0;
+ buf->b_syn_sync_maxlines = 0;
+ buf->b_syn_sync_linebreaks = 0;
+
+ vim_free(buf->b_syn_linecont_prog);
+ buf->b_syn_linecont_prog = NULL;
+ vim_free(buf->b_syn_linecont_pat);
+ buf->b_syn_linecont_pat = NULL;
+#ifdef FEAT_FOLDING
+ buf->b_syn_folditems = 0;
+#endif
+
+ /* free the stored states */
+ syn_stack_free_all(buf);
+ invalidate_current_state();
+}
+
+/*
+ * Clear syncing info for one buffer.
+ */
+ static void
+syntax_sync_clear()
+{
+ int i;
+
+ /* free the syntax patterns */
+ for (i = curbuf->b_syn_patterns.ga_len; --i >= 0; )
+ if (SYN_ITEMS(curbuf)[i].sp_syncing)
+ syn_remove_pattern(curbuf, i);
+
+ curbuf->b_syn_sync_flags = 0;
+ curbuf->b_syn_sync_minlines = 0;
+ curbuf->b_syn_sync_maxlines = 0;
+ curbuf->b_syn_sync_linebreaks = 0;
+
+ vim_free(curbuf->b_syn_linecont_prog);
+ curbuf->b_syn_linecont_prog = NULL;
+ vim_free(curbuf->b_syn_linecont_pat);
+ curbuf->b_syn_linecont_pat = NULL;
+
+ syn_stack_free_all(curbuf); /* Need to recompute all syntax. */
+}
+
+/*
+ * Remove one pattern from the buffer's pattern list.
+ */
+ static void
+syn_remove_pattern(buf, idx)
+ buf_T *buf;
+ int idx;
+{
+ synpat_T *spp;
+
+ spp = &(SYN_ITEMS(buf)[idx]);
+#ifdef FEAT_FOLDING
+ if (spp->sp_flags & HL_FOLD)
+ --buf->b_syn_folditems;
+#endif
+ syn_clear_pattern(buf, idx);
+ mch_memmove(spp, spp + 1,
+ sizeof(synpat_T) * (buf->b_syn_patterns.ga_len - idx - 1));
+ --buf->b_syn_patterns.ga_len;
+ --buf->b_syn_patterns.ga_room;
+}
+
+/*
+ * Clear and free one syntax pattern. When clearing all, must be called from
+ * last to first!
+ */
+ static void
+syn_clear_pattern(buf, i)
+ buf_T *buf;
+ int i;
+{
+ vim_free(SYN_ITEMS(buf)[i].sp_pattern);
+ vim_free(SYN_ITEMS(buf)[i].sp_prog);
+ /* Only free sp_cont_list and sp_next_list of first start pattern */
+ if (i == 0 || SYN_ITEMS(buf)[i - 1].sp_type != SPTYPE_START)
+ {
+ vim_free(SYN_ITEMS(buf)[i].sp_cont_list);
+ vim_free(SYN_ITEMS(buf)[i].sp_next_list);
+ }
+}
+
+/*
+ * Clear and free one syntax cluster.
+ */
+ static void
+syn_clear_cluster(buf, i)
+ buf_T *buf;
+ int i;
+{
+ vim_free(SYN_CLSTR(buf)[i].scl_name);
+ vim_free(SYN_CLSTR(buf)[i].scl_name_u);
+ vim_free(SYN_CLSTR(buf)[i].scl_list);
+}
+
+/*
+ * Handle ":syntax clear" command.
+ */
+ static void
+syn_cmd_clear(eap, syncing)
+ exarg_T *eap;
+ int syncing;
+{
+ char_u *arg = eap->arg;
+ char_u *arg_end;
+ int id;
+
+ eap->nextcmd = find_nextcmd(arg);
+ if (eap->skip)
+ return;
+
+ /*
+ * We have to disable this within ":syn include @group filename",
+ * because otherwise @group would get deleted.
+ * Only required for Vim 5.x syntax files, 6.0 ones don't contain ":syn
+ * clear".
+ */
+ if (curbuf->b_syn_topgrp != 0)
+ return;
+
+ if (ends_excmd(*arg))
+ {
+ /*
+ * No argument: Clear all syntax items.
+ */
+ if (syncing)
+ syntax_sync_clear();
+ else
+ {
+ syntax_clear(curbuf);
+ do_unlet((char_u *)"b:current_syntax");
+ }
+ }
+ else
+ {
+ /*
+ * Clear the group IDs that are in the argument.
+ */
+ while (!ends_excmd(*arg))
+ {
+ arg_end = skiptowhite(arg);
+ if (*arg == '@')
+ {
+ id = syn_scl_namen2id(arg + 1, (int)(arg_end - arg - 1));
+ if (id == 0)
+ {
+ EMSG2(_("E391: No such syntax cluster: %s"), arg);
+ break;
+ }
+ else
+ {
+ /*
+ * We can't physically delete a cluster without changing
+ * the IDs of other clusters, so we do the next best thing
+ * and make it empty.
+ */
+ short scl_id = id - SYNID_CLUSTER;
+
+ vim_free(SYN_CLSTR(curbuf)[scl_id].scl_list);
+ SYN_CLSTR(curbuf)[scl_id].scl_list = NULL;
+ }
+ }
+ else
+ {
+ id = syn_namen2id(arg, (int)(arg_end - arg));
+ if (id == 0)
+ {
+ EMSG2(_(e_nogroup), arg);
+ break;
+ }
+ else
+ syn_clear_one(id, syncing);
+ }
+ arg = skipwhite(arg_end);
+ }
+ }
+ redraw_curbuf_later(NOT_VALID);
+ syn_stack_free_all(curbuf); /* Need to recompute all syntax. */
+}
+
+/*
+ * Clear one syntax group for the current buffer.
+ */
+ static void
+syn_clear_one(id, syncing)
+ int id;
+ int syncing;
+{
+ synpat_T *spp;
+ int idx;
+
+ /* Clear keywords only when not ":syn sync clear group-name" */
+ if (!syncing)
+ {
+ (void)syn_clear_keyword(id, curbuf->b_keywtab);
+ (void)syn_clear_keyword(id, curbuf->b_keywtab_ic);
+ }
+
+ /* clear the patterns for "id" */
+ for (idx = curbuf->b_syn_patterns.ga_len; --idx >= 0; )
+ {
+ spp = &(SYN_ITEMS(curbuf)[idx]);
+ if (spp->sp_syn.id != id || spp->sp_syncing != syncing)
+ continue;
+ syn_remove_pattern(curbuf, idx);
+ }
+}
+
+/*
+ * Handle ":syntax on" command.
+ */
+/* ARGSUSED */
+ static void
+syn_cmd_on(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* not used */
+{
+ syn_cmd_onoff(eap, "syntax");
+}
+
+/*
+ * Handle ":syntax enable" command.
+ */
+/* ARGSUSED */
+ static void
+syn_cmd_enable(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* not used */
+{
+ set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"enable");
+ syn_cmd_onoff(eap, "syntax");
+ do_unlet((char_u *)"g:syntax_cmd");
+}
+
+/*
+ * Handle ":syntax reset" command.
+ */
+/* ARGSUSED */
+ static void
+syn_cmd_reset(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* not used */
+{
+ eap->nextcmd = check_nextcmd(eap->arg);
+ if (!eap->skip)
+ {
+ set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"reset");
+ do_cmdline_cmd((char_u *)"runtime! syntax/syncolor.vim");
+ do_unlet((char_u *)"g:syntax_cmd");
+ }
+}
+
+/*
+ * Handle ":syntax manual" command.
+ */
+/* ARGSUSED */
+ static void
+syn_cmd_manual(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* not used */
+{
+ syn_cmd_onoff(eap, "manual");
+}
+
+/*
+ * Handle ":syntax off" command.
+ */
+/* ARGSUSED */
+ static void
+syn_cmd_off(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* not used */
+{
+ syn_cmd_onoff(eap, "nosyntax");
+}
+
+ static void
+syn_cmd_onoff(eap, name)
+ exarg_T *eap;
+ char *name;
+{
+ char_u buf[100];
+
+ eap->nextcmd = check_nextcmd(eap->arg);
+ if (!eap->skip)
+ {
+ STRCPY(buf, "so ");
+ sprintf((char *)buf + 3, SYNTAX_FNAME, name);
+ do_cmdline_cmd(buf);
+ }
+}
+
+/*
+ * Handle ":syntax [list]" command: list current syntax words.
+ */
+ static void
+syn_cmd_list(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* when TRUE: list syncing items */
+{
+ char_u *arg = eap->arg;
+ int id;
+ char_u *arg_end;
+
+ eap->nextcmd = find_nextcmd(arg);
+ if (eap->skip)
+ return;
+
+ if (!syntax_present(curbuf))
+ {
+ MSG(_("No Syntax items defined for this buffer"));
+ return;
+ }
+
+ if (syncing)
+ {
+ if (curbuf->b_syn_sync_flags & SF_CCOMMENT)
+ {
+ MSG_PUTS(_("syncing on C-style comments"));
+ syn_lines_msg();
+ syn_match_msg();
+ return;
+ }
+ else if (!(curbuf->b_syn_sync_flags & SF_MATCH))
+ {
+ if (curbuf->b_syn_sync_minlines == 0)
+ MSG_PUTS(_("no syncing"));
+ else
+ {
+ MSG_PUTS(_("syncing starts "));
+ msg_outnum(curbuf->b_syn_sync_minlines);
+ MSG_PUTS(_(" lines before top line"));
+ syn_match_msg();
+ }
+ return;
+ }
+ MSG_PUTS_TITLE(_("\n--- Syntax sync items ---"));
+ if (curbuf->b_syn_sync_minlines > 0
+ || curbuf->b_syn_sync_maxlines > 0
+ || curbuf->b_syn_sync_linebreaks > 0)
+ {
+ MSG_PUTS(_("\nsyncing on items"));
+ syn_lines_msg();
+ syn_match_msg();
+ }
+ }
+ else
+ MSG_PUTS_TITLE(_("\n--- Syntax items ---"));
+ if (ends_excmd(*arg))
+ {
+ /*
+ * No argument: List all group IDs and all syntax clusters.
+ */
+ for (id = 1; id <= highlight_ga.ga_len && !got_int; ++id)
+ syn_list_one(id, syncing, FALSE);
+ for (id = 0; id < curbuf->b_syn_clusters.ga_len && !got_int; ++id)
+ syn_list_cluster(id);
+ }
+ else
+ {
+ /*
+ * List the group IDs and syntax clusters that are in the argument.
+ */
+ while (!ends_excmd(*arg) && !got_int)
+ {
+ arg_end = skiptowhite(arg);
+ if (*arg == '@')
+ {
+ id = syn_scl_namen2id(arg + 1, (int)(arg_end - arg - 1));
+ if (id == 0)
+ EMSG2(_("E392: No such syntax cluster: %s"), arg);
+ else
+ syn_list_cluster(id - SYNID_CLUSTER);
+ }
+ else
+ {
+ id = syn_namen2id(arg, (int)(arg_end - arg));
+ if (id == 0)
+ EMSG2(_(e_nogroup), arg);
+ else
+ syn_list_one(id, syncing, TRUE);
+ }
+ arg = skipwhite(arg_end);
+ }
+ }
+ eap->nextcmd = check_nextcmd(arg);
+}
+
+ static void
+syn_lines_msg()
+{
+ if (curbuf->b_syn_sync_maxlines > 0 || curbuf->b_syn_sync_minlines > 0)
+ {
+ MSG_PUTS("; ");
+ if (curbuf->b_syn_sync_minlines > 0)
+ {
+ MSG_PUTS(_("minimal "));
+ msg_outnum(curbuf->b_syn_sync_minlines);
+ if (curbuf->b_syn_sync_maxlines)
+ MSG_PUTS(", ");
+ }
+ if (curbuf->b_syn_sync_maxlines > 0)
+ {
+ MSG_PUTS(_("maximal "));
+ msg_outnum(curbuf->b_syn_sync_maxlines);
+ }
+ MSG_PUTS(_(" lines before top line"));
+ }
+}
+
+ static void
+syn_match_msg()
+{
+ if (curbuf->b_syn_sync_linebreaks > 0)
+ {
+ MSG_PUTS(_("; match "));
+ msg_outnum(curbuf->b_syn_sync_linebreaks);
+ MSG_PUTS(_(" line breaks"));
+ }
+}
+
+static int last_matchgroup;
+
+struct name_list
+{
+ int flag;
+ char *name;
+};
+
+static void syn_list_flags __ARGS((struct name_list *nl, int flags, int attr));
+
+/*
+ * List one syntax item, for ":syntax" or "syntax list syntax_name".
+ */
+ static void
+syn_list_one(id, syncing, link_only)
+ int id;
+ int syncing; /* when TRUE: list syncing items */
+ int link_only; /* when TRUE; list link-only too */
+{
+ int attr;
+ int idx;
+ int did_header = FALSE;
+ synpat_T *spp;
+ static struct name_list namelist1[] =
+ {
+ {HL_DISPLAY, "display"},
+ {HL_CONTAINED, "contained"},
+ {HL_ONELINE, "oneline"},
+ {HL_KEEPEND, "keepend"},
+ {HL_EXTEND, "extend"},
+ {HL_EXCLUDENL, "excludenl"},
+ {HL_TRANSP, "transparent"},
+ {HL_FOLD, "fold"},
+ {0, NULL}
+ };
+ static struct name_list namelist2[] =
+ {
+ {HL_SKIPWHITE, "skipwhite"},
+ {HL_SKIPNL, "skipnl"},
+ {HL_SKIPEMPTY, "skipempty"},
+ {0, NULL}
+ };
+
+ attr = hl_attr(HLF_D); /* highlight like directories */
+
+ /* list the keywords for "id" */
+ if (!syncing)
+ {
+ did_header = syn_list_keywords(id, curbuf->b_keywtab, FALSE, attr);
+ did_header = syn_list_keywords(id, curbuf->b_keywtab_ic,
+ did_header, attr);
+ }
+
+ /* list the patterns for "id" */
+ for (idx = 0; idx < curbuf->b_syn_patterns.ga_len && !got_int; ++idx)
+ {
+ spp = &(SYN_ITEMS(curbuf)[idx]);
+ if (spp->sp_syn.id != id || spp->sp_syncing != syncing)
+ continue;
+
+ (void)syn_list_header(did_header, 999, id);
+ did_header = TRUE;
+ last_matchgroup = 0;
+ if (spp->sp_type == SPTYPE_MATCH)
+ {
+ put_pattern("match", ' ', spp, attr);
+ msg_putchar(' ');
+ }
+ else if (spp->sp_type == SPTYPE_START)
+ {
+ while (SYN_ITEMS(curbuf)[idx].sp_type == SPTYPE_START)
+ put_pattern("start", '=', &SYN_ITEMS(curbuf)[idx++], attr);
+ if (SYN_ITEMS(curbuf)[idx].sp_type == SPTYPE_SKIP)
+ put_pattern("skip", '=', &SYN_ITEMS(curbuf)[idx++], attr);
+ while (idx < curbuf->b_syn_patterns.ga_len
+ && SYN_ITEMS(curbuf)[idx].sp_type == SPTYPE_END)
+ put_pattern("end", '=', &SYN_ITEMS(curbuf)[idx++], attr);
+ --idx;
+ msg_putchar(' ');
+ }
+ syn_list_flags(namelist1, spp->sp_flags, attr);
+
+ if (spp->sp_cont_list != NULL)
+ put_id_list((char_u *)"contains", spp->sp_cont_list, attr);
+
+ if (spp->sp_syn.cont_in_list != NULL)
+ put_id_list((char_u *)"containedin",
+ spp->sp_syn.cont_in_list, attr);
+
+ if (spp->sp_next_list != NULL)
+ {
+ put_id_list((char_u *)"nextgroup", spp->sp_next_list, attr);
+ syn_list_flags(namelist2, spp->sp_flags, attr);
+ }
+ if (spp->sp_flags & (HL_SYNC_HERE|HL_SYNC_THERE))
+ {
+ if (spp->sp_flags & HL_SYNC_HERE)
+ msg_puts_attr((char_u *)"grouphere", attr);
+ else
+ msg_puts_attr((char_u *)"groupthere", attr);
+ msg_putchar(' ');
+ if (spp->sp_sync_idx >= 0)
+ msg_outtrans(HL_TABLE()[SYN_ITEMS(curbuf)
+ [spp->sp_sync_idx].sp_syn.id - 1].sg_name);
+ else
+ MSG_PUTS("NONE");
+ msg_putchar(' ');
+ }
+ }
+
+ /* list the link, if there is one */
+ if (HL_TABLE()[id - 1].sg_link && (did_header || link_only) && !got_int)
+ {
+ (void)syn_list_header(did_header, 999, id);
+ msg_puts_attr((char_u *)"links to", attr);
+ msg_putchar(' ');
+ msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
+ }
+}
+
+ static void
+syn_list_flags(nl, flags, attr)
+ struct name_list *nl;
+ int flags;
+ int attr;
+{
+ int i;
+
+ for (i = 0; nl[i].flag != 0; ++i)
+ if (flags & nl[i].flag)
+ {
+ msg_puts_attr((char_u *)nl[i].name, attr);
+ msg_putchar(' ');
+ }
+}
+
+/*
+ * List one syntax cluster, for ":syntax" or "syntax list syntax_name".
+ */
+ static void
+syn_list_cluster(id)
+ int id;
+{
+ int endcol = 15;
+
+ /* slight hack: roughly duplicate the guts of syn_list_header() */
+ msg_putchar('\n');
+ msg_outtrans(SYN_CLSTR(curbuf)[id].scl_name);
+
+ if (msg_col >= endcol) /* output at least one space */
+ endcol = msg_col + 1;
+ if (Columns <= endcol) /* avoid hang for tiny window */
+ endcol = Columns - 1;
+
+ msg_advance(endcol);
+ if (SYN_CLSTR(curbuf)[id].scl_list != NULL)
+ {
+ put_id_list((char_u *)"cluster", SYN_CLSTR(curbuf)[id].scl_list,
+ hl_attr(HLF_D));
+ }
+ else
+ {
+ msg_puts_attr((char_u *)"cluster", hl_attr(HLF_D));
+ msg_puts((char_u *)"=NONE");
+ }
+}
+
+ static void
+put_id_list(name, list, attr)
+ char_u *name;
+ short *list;
+ int attr;
+{
+ short *p;
+
+ msg_puts_attr(name, attr);
+ msg_putchar('=');
+ for (p = list; *p; ++p)
+ {
+ if (*p >= SYNID_ALLBUT && *p < SYNID_TOP)
+ {
+ if (p[1])
+ MSG_PUTS("ALLBUT");
+ else
+ MSG_PUTS("ALL");
+ }
+ else if (*p >= SYNID_TOP && *p < SYNID_CONTAINED)
+ {
+ MSG_PUTS("TOP");
+ }
+ else if (*p >= SYNID_CONTAINED && *p < SYNID_CLUSTER)
+ {
+ MSG_PUTS("CONTAINED");
+ }
+ else if (*p >= SYNID_CLUSTER)
+ {
+ short scl_id = *p - SYNID_CLUSTER;
+
+ msg_putchar('@');
+ msg_outtrans(SYN_CLSTR(curbuf)[scl_id].scl_name);
+ }
+ else
+ msg_outtrans(HL_TABLE()[*p - 1].sg_name);
+ if (p[1])
+ msg_putchar(',');
+ }
+ msg_putchar(' ');
+}
+
+ static void
+put_pattern(s, c, spp, attr)
+ char *s;
+ int c;
+ synpat_T *spp;
+ int attr;
+{
+ long n;
+ int mask;
+ int first;
+ static char *sepchars = "/+=-#@\"|'^&";
+ int i;
+
+ /* May have to write "matchgroup=group" */
+ if (last_matchgroup != spp->sp_syn_match_id)
+ {
+ last_matchgroup = spp->sp_syn_match_id;
+ msg_puts_attr((char_u *)"matchgroup", attr);
+ msg_putchar('=');
+ if (last_matchgroup == 0)
+ msg_outtrans((char_u *)"NONE");
+ else
+ msg_outtrans(HL_TABLE()[last_matchgroup - 1].sg_name);
+ msg_putchar(' ');
+ }
+
+ /* output the name of the pattern and an '=' or ' ' */
+ msg_puts_attr((char_u *)s, attr);
+ msg_putchar(c);
+
+ /* output the pattern, in between a char that is not in the pattern */
+ for (i = 0; vim_strchr(spp->sp_pattern, sepchars[i]) != NULL; )
+ if (sepchars[++i] == NUL)
+ {
+ i = 0; /* no good char found, just use the first one */
+ break;
+ }
+ msg_putchar(sepchars[i]);
+ msg_outtrans(spp->sp_pattern);
+ msg_putchar(sepchars[i]);
+
+ /* output any pattern options */
+ first = TRUE;
+ for (i = 0; i < SPO_COUNT; ++i)
+ {
+ mask = (1 << i);
+ if (spp->sp_off_flags & (mask + (mask << SPO_COUNT)))
+ {
+ if (!first)
+ msg_putchar(','); /* separate with commas */
+ msg_puts((char_u *)spo_name_tab[i]);
+ n = spp->sp_offsets[i];
+ if (i != SPO_LC_OFF)
+ {
+ if (spp->sp_off_flags & mask)
+ msg_putchar('s');
+ else
+ msg_putchar('e');
+ if (n > 0)
+ msg_putchar('+');
+ }
+ if (n || i == SPO_LC_OFF)
+ msg_outnum(n);
+ first = FALSE;
+ }
+ }
+ msg_putchar(' ');
+}
+
+/*
+ * List or clear the keywords for one syntax group.
+ * Return TRUE if the header has been printed.
+ */
+ static int
+syn_list_keywords(id, ktabp, did_header, attr)
+ int id;
+ keyentry_T **ktabp;
+ int did_header; /* header has already been printed */
+ int attr;
+{
+ int i;
+ int outlen;
+ keyentry_T *ktab;
+ int prev_contained = 0;
+ short *prev_next_list = NULL;
+ short *prev_cont_in_list = NULL;
+ int prev_skipnl = 0;
+ int prev_skipwhite = 0;
+ int prev_skipempty = 0;
+
+ if (ktabp == NULL)
+ return did_header;
+
+ /*
+ * Unfortunately, this list of keywords is not sorted on alphabet but on
+ * hash value...
+ */
+ for (i = 0; i < KHASH_SIZE; ++i)
+ {
+ for (ktab = ktabp[i]; ktab != NULL && !got_int; ktab = ktab->next)
+ {
+ if (ktab->k_syn.id == id)
+ {
+ if (prev_contained != (ktab->flags & HL_CONTAINED)
+ || prev_skipnl != (ktab->flags & HL_SKIPNL)
+ || prev_skipwhite != (ktab->flags & HL_SKIPWHITE)
+ || prev_skipempty != (ktab->flags & HL_SKIPEMPTY)
+ || prev_cont_in_list != ktab->k_syn.cont_in_list
+ || prev_next_list != ktab->next_list)
+ outlen = 9999;
+ else
+ outlen = (int)STRLEN(ktab->keyword);
+ /* output "contained" and "nextgroup" on each line */
+ if (syn_list_header(did_header, outlen, id))
+ {
+ prev_contained = 0;
+ prev_next_list = NULL;
+ prev_cont_in_list = NULL;
+ prev_skipnl = 0;
+ prev_skipwhite = 0;
+ prev_skipempty = 0;
+ }
+ did_header = TRUE;
+ if (prev_contained != (ktab->flags & HL_CONTAINED))
+ {
+ msg_puts_attr((char_u *)"contained", attr);
+ msg_putchar(' ');
+ prev_contained = (ktab->flags & HL_CONTAINED);
+ }
+ if (ktab->k_syn.cont_in_list != prev_cont_in_list)
+ {
+ put_id_list((char_u *)"containedin",
+ ktab->k_syn.cont_in_list, attr);
+ msg_putchar(' ');
+ prev_cont_in_list = ktab->k_syn.cont_in_list;
+ }
+ if (ktab->next_list != prev_next_list)
+ {
+ put_id_list((char_u *)"nextgroup", ktab->next_list, attr);
+ msg_putchar(' ');
+ prev_next_list = ktab->next_list;
+ if (ktab->flags & HL_SKIPNL)
+ {
+ msg_puts_attr((char_u *)"skipnl", attr);
+ msg_putchar(' ');
+ prev_skipnl = (ktab->flags & HL_SKIPNL);
+ }
+ if (ktab->flags & HL_SKIPWHITE)
+ {
+ msg_puts_attr((char_u *)"skipwhite", attr);
+ msg_putchar(' ');
+ prev_skipwhite = (ktab->flags & HL_SKIPWHITE);
+ }
+ if (ktab->flags & HL_SKIPEMPTY)
+ {
+ msg_puts_attr((char_u *)"skipempty", attr);
+ msg_putchar(' ');
+ prev_skipempty = (ktab->flags & HL_SKIPEMPTY);
+ }
+ }
+ msg_outtrans(ktab->keyword);
+ }
+ }
+ }
+
+ return did_header;
+}
+
+ static void
+syn_clear_keyword(id, ktabp)
+ int id;
+ keyentry_T **ktabp;
+{
+ int i;
+ keyentry_T *ktab;
+ keyentry_T *ktab_prev;
+ keyentry_T *ktab_next;
+
+ if (ktabp == NULL) /* no keywords present */
+ return;
+
+ for (i = 0; i < KHASH_SIZE; ++i)
+ {
+ ktab_prev = NULL;
+ for (ktab = ktabp[i]; ktab != NULL; )
+ {
+ if (ktab->k_syn.id == id)
+ {
+ ktab_next = ktab->next;
+ if (ktab_prev == NULL)
+ ktabp[i] = ktab_next;
+ else
+ ktab_prev->next = ktab_next;
+ vim_free(ktab);
+ ktab = ktab_next;
+ }
+ else
+ {
+ ktab_prev = ktab;
+ ktab = ktab->next;
+ }
+ }
+ }
+}
+
+/*
+ * Recursive function to free() a branch of a kwordtab.
+ */
+ static void
+free_keywtab(ktabp)
+ keyentry_T **ktabp;
+{
+ int i;
+ keyentry_T *ktab;
+ keyentry_T *ktab_next;
+
+ if (ktabp != NULL)
+ {
+ for (i = 0; i < KHASH_SIZE; ++i)
+ for (ktab = ktabp[i]; ktab != NULL; ktab = ktab_next)
+ {
+ ktab_next = ktab->next;
+ vim_free(ktab->next_list);
+ vim_free(ktab->k_syn.cont_in_list);
+ vim_free(ktab);
+ }
+ vim_free(ktabp);
+ }
+}
+
+/*
+ * Add a keyword to the list of keywords.
+ */
+ static void
+add_keyword(name, id, flags, cont_in_list, next_list)
+ char_u *name; /* name of keyword */
+ int id; /* group ID for this keyword */
+ int flags; /* flags for this keyword */
+ short *cont_in_list; /* containedin for this keyword */
+ short *next_list; /* nextgroup for this keyword */
+{
+ keyentry_T *ktab;
+ keyentry_T ***ktabpp;
+ int hash;
+ char_u *name_ic = name;
+
+ if (curbuf->b_syn_ic)
+ {
+ name_ic = str_foldcase(name, (int)STRLEN(name));
+ if (name_ic == NULL)
+ name_ic = name;
+ }
+ ktab = (keyentry_T *)alloc((int)(sizeof(keyentry_T) + STRLEN(name_ic)));
+ if (ktab == NULL)
+ return;
+ STRCPY(ktab->keyword, name_ic);
+ if (name_ic != name)
+ vim_free(name_ic);
+ ktab->k_syn.id = id;
+ ktab->k_syn.inc_tag = current_syn_inc_tag;
+ ktab->flags = flags;
+ ktab->k_syn.cont_in_list = copy_id_list(cont_in_list);
+ if (cont_in_list != NULL)
+ curbuf->b_syn_containedin = TRUE;
+ ktab->next_list = copy_id_list(next_list);
+
+ if (curbuf->b_syn_ic)
+ ktabpp = &curbuf->b_keywtab_ic;
+ else
+ ktabpp = &curbuf->b_keywtab;
+
+ if (*ktabpp == NULL)
+ {
+ *ktabpp = (keyentry_T **)alloc_clear(
+ (int)(sizeof(keyentry_T *) * KHASH_SIZE));
+ if (*ktabpp == NULL)
+ return;
+ }
+
+ hash = syn_khash(ktab->keyword);
+ ktab->next = (*ktabpp)[hash];
+ (*ktabpp)[hash] = ktab;
+}
+
+/*
+ * Compute a hash value for a keyword. Uses the ElfHash algorithm, which is
+ * supposed to have an even distribution (suggested by Charles Campbell).
+ */
+ static int
+syn_khash(p)
+ char_u *p;
+{
+ long_u hash = 0;
+ long_u g;
+
+ while (*p != NUL)
+ {
+ hash = (hash << 4) + *p++; /* clear low 4 bits of hash, add char */
+ g = hash & 0xf0000000L; /* g has high 4 bits of hash only */
+ if (g != 0)
+ hash ^= g >> 24; /* xor g's high 4 bits into hash */
+ }
+
+ return (int)(hash & KHASH_MASK);
+}
+
+/*
+ * Get the start and end of the group name argument.
+ * Return a pointer to the first argument.
+ * Return NULL if the end of the command was found instead of further args.
+ */
+ static char_u *
+get_group_name(arg, name_end)
+ char_u *arg; /* start of the argument */
+ char_u **name_end; /* pointer to end of the name */
+{
+ char_u *rest;
+
+ *name_end = skiptowhite(arg);
+ rest = skipwhite(*name_end);
+
+ /*
+ * Check if there are enough arguments. The first argument may be a
+ * pattern, where '|' is allowed, so only check for NUL.
+ */
+ if (ends_excmd(*arg) || *rest == NUL)
+ return NULL;
+ return rest;
+}
+
+/*
+ * Check for syntax command option arguments.
+ * This can be called at any place in the list of arguments, and just picks
+ * out the arguments that are known. Can be called several times in a row to
+ * collect all options in between other arguments.
+ * Return a pointer to the next argument (which isn't an option).
+ * Return NULL for any error;
+ */
+ static char_u *
+get_syn_options(arg, flagsp, keyword, sync_idx, cont_list,
+ cont_in_list, next_list)
+ char_u *arg; /* next argument */
+ int *flagsp; /* flags for contained and transpartent */
+ int keyword; /* TRUE for ":syn keyword" */
+ int *sync_idx; /* syntax item for "grouphere" argument, NULL
+ if not allowed */
+ short **cont_list; /* group IDs for "contains" argument, NULL if
+ not allowed */
+ short **cont_in_list; /* group IDs for "containedin" argument, NULL
+ if not allowed */
+ short **next_list; /* group IDs for "nextgroup" argument */
+{
+ int flags;
+ char_u *gname_start, *gname;
+ int syn_id;
+ int len;
+ int i;
+ int fidx;
+ static struct flag
+ {
+ char *name;
+ int len;
+ int val;
+ } flagtab[] = { {"contained", 9, HL_CONTAINED},
+ {"oneline", 7, HL_ONELINE},
+ {"keepend", 7, HL_KEEPEND},
+ {"extend", 6, HL_EXTEND},
+ {"excludenl", 9, HL_EXCLUDENL},
+ {"transparent", 11, HL_TRANSP},
+ {"skipnl", 6, HL_SKIPNL},
+ {"skipwhite", 9, HL_SKIPWHITE},
+ {"skipempty", 9, HL_SKIPEMPTY},
+ {"grouphere", 9, HL_SYNC_HERE},
+ {"groupthere", 10, HL_SYNC_THERE},
+ {"display", 7, HL_DISPLAY},
+ {"fold", 4, HL_FOLD},
+ };
+#define MLEN 12
+ char lowname[MLEN];
+ int llen;
+
+ if (arg == NULL) /* already detected error */
+ return NULL;
+
+ flags = *flagsp;
+ for (;;)
+ {
+ /* STRNICMP() is a bit slow, change arg to lowercase first and use
+ * STRNCMP() */
+ for (llen = 0; llen < MLEN; ++llen)
+ {
+ if (!isalpha(arg[llen]))
+ break;
+ lowname[llen] = TOLOWER_ASC(arg[llen]);
+ }
+
+ for (fidx = sizeof(flagtab) / sizeof(struct flag); --fidx >= 0; )
+ {
+ len = flagtab[fidx].len;
+ if (len == llen
+ && STRNCMP(lowname, flagtab[fidx].name, len) == 0
+ && (ends_excmd(arg[len]) || vim_iswhite(arg[len])))
+ {
+ if (keyword
+ && (flagtab[fidx].val == HL_DISPLAY
+ || flagtab[fidx].val == HL_FOLD
+ || flagtab[fidx].val == HL_EXTEND))
+ {
+ /* treat "display", "fold" and "extend" as a keyword */
+ fidx = -1;
+ break;
+ }
+
+ flags |= flagtab[fidx].val;
+ arg = skipwhite(arg + len);
+
+ if (flagtab[fidx].val == HL_SYNC_HERE
+ || flagtab[fidx].val == HL_SYNC_THERE)
+ {
+ if (sync_idx == NULL)
+ {
+ EMSG(_("E393: group[t]here not accepted here"));
+ return NULL;
+ }
+ gname_start = arg;
+ arg = skiptowhite(arg);
+ if (gname_start == arg)
+ return NULL;
+ gname = vim_strnsave(gname_start, (int)(arg - gname_start));
+ if (gname == NULL)
+ return NULL;
+ if (STRCMP(gname, "NONE") == 0)
+ *sync_idx = NONE_IDX;
+ else
+ {
+ syn_id = syn_name2id(gname);
+ for (i = curbuf->b_syn_patterns.ga_len; --i >= 0; )
+ if (SYN_ITEMS(curbuf)[i].sp_syn.id == syn_id
+ && SYN_ITEMS(curbuf)[i].sp_type == SPTYPE_START)
+ {
+ *sync_idx = i;
+ break;
+ }
+ if (i < 0)
+ {
+ EMSG2(_("E394: Didn't find region item for %s"), gname);
+ vim_free(gname);
+ return NULL;
+ }
+ }
+
+ vim_free(gname);
+ arg = skipwhite(arg);
+ }
+#ifdef FEAT_FOLDING
+ else if (flagtab[fidx].val == HL_FOLD
+ && foldmethodIsSyntax(curwin))
+ {
+ /* Need to update folds later. */
+ foldUpdateAll(curwin);
+ }
+#endif
+ break;
+ }
+ }
+ if (fidx >= 0)
+ continue;
+
+ if (llen == 8 && STRNCMP(lowname, "contains", 8) == 0
+ && (vim_iswhite(arg[8]) || arg[8] == '='))
+ {
+ if (cont_list == NULL)
+ {
+ EMSG(_("E395: contains argument not accepted here"));
+ return NULL;
+ }
+ if (get_id_list(&arg, 8, cont_list) == FAIL)
+ return NULL;
+ }
+ else if (llen == 11 && STRNCMP(lowname, "containedin", 11) == 0
+ && (vim_iswhite(arg[11]) || arg[11] == '='))
+ {
+ if (cont_in_list == NULL)
+ {
+ EMSG(_("E396: containedin argument not accepted here"));
+ return NULL;
+ }
+ if (get_id_list(&arg, 11, cont_in_list) == FAIL)
+ return NULL;
+ }
+ else if (llen == 9 && STRNCMP(lowname, "nextgroup", 9) == 0
+ && (vim_iswhite(arg[9]) || arg[9] == '='))
+ {
+ if (get_id_list(&arg, 9, next_list) == FAIL)
+ return NULL;
+ }
+ else
+ break;
+ }
+
+ *flagsp = flags;
+
+ return arg;
+}
+
+/*
+ * Adjustments to syntax item when declared in a ":syn include"'d file.
+ * Set the contained flag, and if the item is not already contained, add it
+ * to the specified top-level group, if any.
+ */
+ static void
+syn_incl_toplevel(id, flagsp)
+ int id;
+ int *flagsp;
+{
+ if ((*flagsp & HL_CONTAINED) || curbuf->b_syn_topgrp == 0)
+ return;
+ *flagsp |= HL_CONTAINED;
+ if (curbuf->b_syn_topgrp >= SYNID_CLUSTER)
+ {
+ /* We have to alloc this, because syn_combine_list() will free it. */
+ short *grp_list = (short *)alloc((unsigned)(2 * sizeof(short)));
+ int tlg_id = curbuf->b_syn_topgrp - SYNID_CLUSTER;
+
+ if (grp_list != NULL)
+ {
+ grp_list[0] = id;
+ grp_list[1] = 0;
+ syn_combine_list(&SYN_CLSTR(curbuf)[tlg_id].scl_list, &grp_list,
+ CLUSTER_ADD);
+ }
+ }
+}
+
+/*
+ * Handle ":syntax include [@{group-name}] filename" command.
+ */
+/* ARGSUSED */
+ static void
+syn_cmd_include(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* not used */
+{
+ char_u *arg = eap->arg;
+ int sgl_id = 1;
+ char_u *group_name_end;
+ char_u *rest;
+ char_u *errormsg = NULL;
+ int prev_toplvl_grp;
+ int prev_syn_inc_tag;
+ int source = FALSE;
+
+ eap->nextcmd = find_nextcmd(arg);
+ if (eap->skip)
+ return;
+
+ if (arg[0] == '@')
+ {
+ ++arg;
+ rest = get_group_name(arg, &group_name_end);
+ if (rest == NULL)
+ {
+ EMSG((char_u *)_("E397: Filename required"));
+ return;
+ }
+ sgl_id = syn_check_cluster(arg, (int)(group_name_end - arg));
+ /* separate_nextcmd() and expand_filename() depend on this */
+ eap->arg = rest;
+ }
+
+ /*
+ * Everything that's left, up to the next command, should be the
+ * filename to include.
+ */
+ eap->argt |= (XFILE | NOSPC);
+ separate_nextcmd(eap);
+ if (*eap->arg == '<' || *eap->arg == '$' || mch_isFullName(eap->arg))
+ {
+ /* For an absolute path, "$VIM/..." or "<sfile>.." we ":source" the
+ * file. Need to expand the file name first. In other cases
+ * ":runtime!" is used. */
+ source = TRUE;
+ if (expand_filename(eap, syn_cmdlinep, &errormsg) == FAIL)
+ {
+ if (errormsg != NULL)
+ EMSG(errormsg);
+ return;
+ }
+ }
+
+ /*
+ * Save and restore the existing top-level grouplist id and ":syn
+ * include" tag around the actual inclusion.
+ */
+ prev_syn_inc_tag = current_syn_inc_tag;
+ current_syn_inc_tag = ++running_syn_inc_tag;
+ prev_toplvl_grp = curbuf->b_syn_topgrp;
+ curbuf->b_syn_topgrp = sgl_id;
+ if (source ? do_source(eap->arg, FALSE, FALSE) == FAIL
+ : cmd_runtime(eap->arg, TRUE) == FAIL)
+ EMSG2(_(e_notopen), eap->arg);
+ curbuf->b_syn_topgrp = prev_toplvl_grp;
+ current_syn_inc_tag = prev_syn_inc_tag;
+}
+
+/*
+ * Handle ":syntax keyword {group-name} [{option}] keyword .." command.
+ */
+/* ARGSUSED */
+ static void
+syn_cmd_keyword(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* not used */
+{
+ char_u *arg = eap->arg;
+ char_u *group_name_end;
+ int syn_id;
+ char_u *rest;
+ char_u *keyword_copy;
+ char_u *p;
+ char_u *first_arg;
+ int round;
+ int flags = 0;
+ short *next_list = NULL;
+ short *cont_in_list = NULL;
+
+ rest = get_group_name(arg, &group_name_end);
+
+ if (rest != NULL)
+ {
+ syn_id = syn_check_group(arg, (int)(group_name_end - arg));
+
+ /* allocate a buffer, for removing the backslashes in the keyword */
+ keyword_copy = alloc((unsigned)STRLEN(rest) + 1);
+ if (keyword_copy != NULL)
+ {
+ /*
+ * The options given apply to ALL keywords, so all options must be
+ * found before keywords can be created.
+ * round 1: collect the options.
+ * round 2: create the keywords.
+ */
+ first_arg = rest;
+ for (round = 1; round <= 2; ++round)
+ {
+ /*
+ * Isolate each keyword and add an entry for it.
+ */
+ for (rest = first_arg; rest != NULL && !ends_excmd(*rest);
+ rest = skipwhite(rest))
+ {
+ rest = get_syn_options(rest, &flags, TRUE, NULL,
+ NULL, &cont_in_list, &next_list);
+ if (rest == NULL || ends_excmd(*rest))
+ break;
+ p = keyword_copy;
+ while (*rest != 0 && !vim_iswhite(*rest))
+ {
+ if (*rest == '\\' && rest[1] != NUL)
+ ++rest;
+ *p++ = *rest++;
+ }
+ *p = NUL;
+ if (round == 2 && !eap->skip)
+ {
+ for (p = vim_strchr(keyword_copy, '['); ; )
+ {
+ if (p != NULL)
+ *p = NUL;
+ add_keyword(keyword_copy, syn_id, flags,
+ cont_in_list, next_list);
+ if (p == NULL || p[1] == NUL || p[1] == ']')
+ break;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ int l = (*mb_ptr2len_check)(p + 1);
+
+ mch_memmove(p, p + 1, l);
+ p += l;
+ }
+ else
+#endif
+ {
+ p[0] = p[1];
+ ++p;
+ }
+ }
+ }
+ }
+ if (round == 1)
+ syn_incl_toplevel(syn_id, &flags);
+ }
+ vim_free(keyword_copy);
+ }
+ }
+
+ if (rest != NULL)
+ eap->nextcmd = check_nextcmd(rest);
+ else
+ EMSG2(_(e_invarg2), arg);
+
+ vim_free(cont_in_list);
+ vim_free(next_list);
+ redraw_curbuf_later(NOT_VALID);
+ syn_stack_free_all(curbuf); /* Need to recompute all syntax. */
+}
+
+/*
+ * Handle ":syntax match {name} [{options}] {pattern} [{options}]".
+ *
+ * Also ":syntax sync match {name} [[grouphere | groupthere] {group-name}] .."
+ */
+ static void
+syn_cmd_match(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* TRUE for ":syntax sync match .. " */
+{
+ char_u *arg = eap->arg;
+ char_u *group_name_end;
+ char_u *rest;
+ synpat_T item; /* the item found in the line */
+ int syn_id;
+ int idx;
+ int flags = 0;
+ int sync_idx = 0;
+ short *cont_list = NULL;
+ short *cont_in_list = NULL;
+ short *next_list = NULL;
+
+ /* Isolate the group name, check for validity */
+ rest = get_group_name(arg, &group_name_end);
+
+ /* Get options before the pattern */
+ rest = get_syn_options(rest, &flags, FALSE,
+ syncing ? &sync_idx : NULL, &cont_list, &cont_in_list, &next_list);
+
+ /* get the pattern. */
+ init_syn_patterns();
+ vim_memset(&item, 0, sizeof(item));
+ rest = get_syn_pattern(rest, &item);
+ if (vim_regcomp_had_eol() && !(flags & HL_EXCLUDENL))
+ flags |= HL_HAS_EOL;
+
+ /* Get options after the pattern */
+ rest = get_syn_options(rest, &flags, FALSE,
+ syncing ? &sync_idx : NULL, &cont_list, &cont_in_list, &next_list);
+
+ if (rest != NULL) /* all arguments are valid */
+ {
+ /*
+ * Check for trailing command and illegal trailing arguments.
+ */
+ eap->nextcmd = check_nextcmd(rest);
+ if (!ends_excmd(*rest) || eap->skip)
+ rest = NULL;
+ else if (ga_grow(&curbuf->b_syn_patterns, 1) != FAIL
+ && (syn_id = syn_check_group(arg,
+ (int)(group_name_end - arg))) != 0)
+ {
+ syn_incl_toplevel(syn_id, &flags);
+ /*
+ * Store the pattern in the syn_items list
+ */
+ idx = curbuf->b_syn_patterns.ga_len;
+ SYN_ITEMS(curbuf)[idx] = item;
+ SYN_ITEMS(curbuf)[idx].sp_syncing = syncing;
+ SYN_ITEMS(curbuf)[idx].sp_type = SPTYPE_MATCH;
+ SYN_ITEMS(curbuf)[idx].sp_syn.id = syn_id;
+ SYN_ITEMS(curbuf)[idx].sp_syn.inc_tag = current_syn_inc_tag;
+ SYN_ITEMS(curbuf)[idx].sp_flags = flags;
+ SYN_ITEMS(curbuf)[idx].sp_sync_idx = sync_idx;
+ SYN_ITEMS(curbuf)[idx].sp_cont_list = cont_list;
+ SYN_ITEMS(curbuf)[idx].sp_syn.cont_in_list = cont_in_list;
+ if (cont_in_list != NULL)
+ curbuf->b_syn_containedin = TRUE;
+ SYN_ITEMS(curbuf)[idx].sp_next_list = next_list;
+ ++curbuf->b_syn_patterns.ga_len;
+ --curbuf->b_syn_patterns.ga_room;
+
+ /* remember that we found a match for syncing on */
+ if (flags & (HL_SYNC_HERE|HL_SYNC_THERE))
+ curbuf->b_syn_sync_flags |= SF_MATCH;
+#ifdef FEAT_FOLDING
+ if (flags & HL_FOLD)
+ ++curbuf->b_syn_folditems;
+#endif
+
+ redraw_curbuf_later(NOT_VALID);
+ syn_stack_free_all(curbuf); /* Need to recompute all syntax. */
+ return; /* don't free the progs and patterns now */
+ }
+ }
+
+ /*
+ * Something failed, free the allocated memory.
+ */
+ vim_free(item.sp_prog);
+ vim_free(item.sp_pattern);
+ vim_free(cont_list);
+ vim_free(cont_in_list);
+ vim_free(next_list);
+
+ if (rest == NULL)
+ EMSG2(_(e_invarg2), arg);
+}
+
+/*
+ * Handle ":syntax region {group-name} [matchgroup={group-name}]
+ * start {start} .. [skip {skip}] end {end} .. [{options}]".
+ */
+ static void
+syn_cmd_region(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* TRUE for ":syntax sync region .." */
+{
+ char_u *arg = eap->arg;
+ char_u *group_name_end;
+ char_u *rest; /* next arg, NULL on error */
+ char_u *key_end;
+ char_u *key = NULL;
+ char_u *p;
+ int item;
+#define ITEM_START 0
+#define ITEM_SKIP 1
+#define ITEM_END 2
+#define ITEM_MATCHGROUP 3
+ struct pat_ptr
+ {
+ synpat_T *pp_synp; /* pointer to syn_pattern */
+ int pp_matchgroup_id; /* matchgroup ID */
+ struct pat_ptr *pp_next; /* pointer to next pat_ptr */
+ } *(pat_ptrs[3]);
+ /* patterns found in the line */
+ struct pat_ptr *ppp;
+ struct pat_ptr *ppp_next;
+ int pat_count = 0; /* nr of syn_patterns found */
+ int syn_id;
+ int matchgroup_id = 0;
+ int not_enough = FALSE; /* not enough arguments */
+ int illegal = FALSE; /* illegal arguments */
+ int success = FALSE;
+ int idx;
+ int flags = 0;
+ short *cont_list = NULL;
+ short *cont_in_list = NULL;
+ short *next_list = NULL;
+
+ /* Isolate the group name, check for validity */
+ rest = get_group_name(arg, &group_name_end);
+
+ pat_ptrs[0] = NULL;
+ pat_ptrs[1] = NULL;
+ pat_ptrs[2] = NULL;
+
+ init_syn_patterns();
+
+ /*
+ * get the options, patterns and matchgroup.
+ */
+ while (rest != NULL && !ends_excmd(*rest))
+ {
+ /* Check for option arguments */
+ rest = get_syn_options(rest, &flags, FALSE, NULL,
+ &cont_list, &cont_in_list, &next_list);
+ if (rest == NULL || ends_excmd(*rest))
+ break;
+
+ /* must be a pattern or matchgroup then */
+ key_end = rest;
+ while (*key_end && !vim_iswhite(*key_end) && *key_end != '=')
+ ++key_end;
+ vim_free(key);
+ key = vim_strnsave_up(rest, (int)(key_end - rest));
+ if (key == NULL) /* out of memory */
+ {
+ rest = NULL;
+ break;
+ }
+ if (STRCMP(key, "MATCHGROUP") == 0)
+ item = ITEM_MATCHGROUP;
+ else if (STRCMP(key, "START") == 0)
+ item = ITEM_START;
+ else if (STRCMP(key, "END") == 0)
+ item = ITEM_END;
+ else if (STRCMP(key, "SKIP") == 0)
+ {
+ if (pat_ptrs[ITEM_SKIP] != NULL) /* one skip pattern allowed */
+ {
+ illegal = TRUE;
+ break;
+ }
+ item = ITEM_SKIP;
+ }
+ else
+ break;
+ rest = skipwhite(key_end);
+ if (*rest != '=')
+ {
+ rest = NULL;
+ EMSG2(_("E398: Missing '=': %s"), arg);
+ break;
+ }
+ rest = skipwhite(rest + 1);
+ if (*rest == NUL)
+ {
+ not_enough = TRUE;
+ break;
+ }
+
+ if (item == ITEM_MATCHGROUP)
+ {
+ p = skiptowhite(rest);
+ if ((p - rest == 4 && STRNCMP(rest, "NONE", 4) == 0) || eap->skip)
+ matchgroup_id = 0;
+ else
+ {
+ matchgroup_id = syn_check_group(rest, (int)(p - rest));
+ if (matchgroup_id == 0)
+ {
+ illegal = TRUE;
+ break;
+ }
+ }
+ rest = skipwhite(p);
+ }
+ else
+ {
+ /*
+ * Allocate room for a syn_pattern, and link it in the list of
+ * syn_patterns for this item, at the start (because the list is
+ * used from end to start).
+ */
+ ppp = (struct pat_ptr *)alloc((unsigned)sizeof(struct pat_ptr));
+ if (ppp == NULL)
+ {
+ rest = NULL;
+ break;
+ }
+ ppp->pp_next = pat_ptrs[item];
+ pat_ptrs[item] = ppp;
+ ppp->pp_synp = (synpat_T *)alloc_clear((unsigned)sizeof(synpat_T));
+ if (ppp->pp_synp == NULL)
+ {
+ rest = NULL;
+ break;
+ }
+
+ /*
+ * Get the syntax pattern and the following offset(s).
+ */
+ /* Enable the appropriate \z specials. */
+ if (item == ITEM_START)
+ reg_do_extmatch = REX_SET;
+ else if (item == ITEM_SKIP || item == ITEM_END)
+ reg_do_extmatch = REX_USE;
+ rest = get_syn_pattern(rest, ppp->pp_synp);
+ reg_do_extmatch = 0;
+ if (item == ITEM_END && vim_regcomp_had_eol()
+ && !(flags & HL_EXCLUDENL))
+ ppp->pp_synp->sp_flags |= HL_HAS_EOL;
+ ppp->pp_matchgroup_id = matchgroup_id;
+ ++pat_count;
+ }
+ }
+ vim_free(key);
+ if (illegal || not_enough)
+ rest = NULL;
+
+ /*
+ * Must have a "start" and "end" pattern.
+ */
+ if (rest != NULL && (pat_ptrs[ITEM_START] == NULL ||
+ pat_ptrs[ITEM_END] == NULL))
+ {
+ not_enough = TRUE;
+ rest = NULL;
+ }
+
+ if (rest != NULL)
+ {
+ /*
+ * Check for trailing garbage or command.
+ * If OK, add the item.
+ */
+ eap->nextcmd = check_nextcmd(rest);
+ if (!ends_excmd(*rest) || eap->skip)
+ rest = NULL;
+ else if (ga_grow(&(curbuf->b_syn_patterns), pat_count) != FAIL
+ && (syn_id = syn_check_group(arg,
+ (int)(group_name_end - arg))) != 0)
+ {
+ syn_incl_toplevel(syn_id, &flags);
+ /*
+ * Store the start/skip/end in the syn_items list
+ */
+ idx = curbuf->b_syn_patterns.ga_len;
+ for (item = ITEM_START; item <= ITEM_END; ++item)
+ {
+ for (ppp = pat_ptrs[item]; ppp != NULL; ppp = ppp->pp_next)
+ {
+ SYN_ITEMS(curbuf)[idx] = *(ppp->pp_synp);
+ SYN_ITEMS(curbuf)[idx].sp_syncing = syncing;
+ SYN_ITEMS(curbuf)[idx].sp_type =
+ (item == ITEM_START) ? SPTYPE_START :
+ (item == ITEM_SKIP) ? SPTYPE_SKIP : SPTYPE_END;
+ SYN_ITEMS(curbuf)[idx].sp_flags |= flags;
+ SYN_ITEMS(curbuf)[idx].sp_syn.id = syn_id;
+ SYN_ITEMS(curbuf)[idx].sp_syn.inc_tag = current_syn_inc_tag;
+ SYN_ITEMS(curbuf)[idx].sp_syn_match_id =
+ ppp->pp_matchgroup_id;
+ if (item == ITEM_START)
+ {
+ SYN_ITEMS(curbuf)[idx].sp_cont_list = cont_list;
+ SYN_ITEMS(curbuf)[idx].sp_syn.cont_in_list =
+ cont_in_list;
+ if (cont_in_list != NULL)
+ curbuf->b_syn_containedin = TRUE;
+ SYN_ITEMS(curbuf)[idx].sp_next_list = next_list;
+ }
+ ++curbuf->b_syn_patterns.ga_len;
+ --curbuf->b_syn_patterns.ga_room;
+ ++idx;
+#ifdef FEAT_FOLDING
+ if (flags & HL_FOLD)
+ ++curbuf->b_syn_folditems;
+#endif
+ }
+ }
+
+ redraw_curbuf_later(NOT_VALID);
+ syn_stack_free_all(curbuf); /* Need to recompute all syntax. */
+ success = TRUE; /* don't free the progs and patterns now */
+ }
+ }
+
+ /*
+ * Free the allocated memory.
+ */
+ for (item = ITEM_START; item <= ITEM_END; ++item)
+ for (ppp = pat_ptrs[item]; ppp != NULL; ppp = ppp_next)
+ {
+ if (!success)
+ {
+ vim_free(ppp->pp_synp->sp_prog);
+ vim_free(ppp->pp_synp->sp_pattern);
+ }
+ vim_free(ppp->pp_synp);
+ ppp_next = ppp->pp_next;
+ vim_free(ppp);
+ }
+
+ if (!success)
+ {
+ vim_free(cont_list);
+ vim_free(cont_in_list);
+ vim_free(next_list);
+ if (not_enough)
+ EMSG2(_("E399: Not enough arguments: syntax region %s"), arg);
+ else if (illegal || rest == NULL)
+ EMSG2(_(e_invarg2), arg);
+ }
+}
+
+/*
+ * A simple syntax group ID comparison function suitable for use in qsort()
+ */
+ static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+syn_compare_stub(v1, v2)
+ const void *v1;
+ const void *v2;
+{
+ const short *s1 = v1;
+ const short *s2 = v2;
+
+ return (*s1 > *s2 ? 1 : *s1 < *s2 ? -1 : 0);
+}
+
+/*
+ * Combines lists of syntax clusters.
+ * *clstr1 and *clstr2 must both be allocated memory; they will be consumed.
+ */
+ static void
+syn_combine_list(clstr1, clstr2, list_op)
+ short **clstr1;
+ short **clstr2;
+ int list_op;
+{
+ int count1 = 0;
+ int count2 = 0;
+ short *g1;
+ short *g2;
+ short *clstr = NULL;
+ int count;
+ int round;
+
+ /*
+ * Handle degenerate cases.
+ */
+ if (*clstr2 == NULL)
+ return;
+ if (*clstr1 == NULL || list_op == CLUSTER_REPLACE)
+ {
+ if (list_op == CLUSTER_REPLACE)
+ vim_free(*clstr1);
+ if (list_op == CLUSTER_REPLACE || list_op == CLUSTER_ADD)
+ *clstr1 = *clstr2;
+ else
+ vim_free(*clstr2);
+ return;
+ }
+
+ for (g1 = *clstr1; *g1; g1++)
+ ++count1;
+ for (g2 = *clstr2; *g2; g2++)
+ ++count2;
+
+ /*
+ * For speed purposes, sort both lists.
+ */
+ qsort(*clstr1, (size_t)count1, sizeof(short), syn_compare_stub);
+ qsort(*clstr2, (size_t)count2, sizeof(short), syn_compare_stub);
+
+ /*
+ * We proceed in two passes; in round 1, we count the elements to place
+ * in the new list, and in round 2, we allocate and populate the new
+ * list. For speed, we use a mergesort-like method, adding the smaller
+ * of the current elements in each list to the new list.
+ */
+ for (round = 1; round <= 2; round++)
+ {
+ g1 = *clstr1;
+ g2 = *clstr2;
+ count = 0;
+
+ /*
+ * First, loop through the lists until one of them is empty.
+ */
+ while (*g1 && *g2)
+ {
+ /*
+ * We always want to add from the first list.
+ */
+ if (*g1 < *g2)
+ {
+ if (round == 2)
+ clstr[count] = *g1;
+ count++;
+ g1++;
+ continue;
+ }
+ /*
+ * We only want to add from the second list if we're adding the
+ * lists.
+ */
+ if (list_op == CLUSTER_ADD)
+ {
+ if (round == 2)
+ clstr[count] = *g2;
+ count++;
+ }
+ if (*g1 == *g2)
+ g1++;
+ g2++;
+ }
+
+ /*
+ * Now add the leftovers from whichever list didn't get finished
+ * first. As before, we only want to add from the second list if
+ * we're adding the lists.
+ */
+ for (; *g1; g1++, count++)
+ if (round == 2)
+ clstr[count] = *g1;
+ if (list_op == CLUSTER_ADD)
+ for (; *g2; g2++, count++)
+ if (round == 2)
+ clstr[count] = *g2;
+
+ if (round == 1)
+ {
+ /*
+ * If the group ended up empty, we don't need to allocate any
+ * space for it.
+ */
+ if (count == 0)
+ {
+ clstr = NULL;
+ break;
+ }
+ clstr = (short *)alloc((unsigned)((count + 1) * sizeof(short)));
+ if (clstr == NULL)
+ break;
+ clstr[count] = 0;
+ }
+ }
+
+ /*
+ * Finally, put the new list in place.
+ */
+ vim_free(*clstr1);
+ vim_free(*clstr2);
+ *clstr1 = clstr;
+}
+
+/*
+ * Lookup a syntax cluster name and return it's ID.
+ * If it is not found, 0 is returned.
+ */
+ static int
+syn_scl_name2id(name)
+ char_u *name;
+{
+ int i;
+ char_u *name_u;
+
+ /* Avoid using stricmp() too much, it's slow on some systems */
+ name_u = vim_strsave_up(name);
+ if (name_u == NULL)
+ return 0;
+ for (i = curbuf->b_syn_clusters.ga_len; --i >= 0; )
+ if (SYN_CLSTR(curbuf)[i].scl_name_u != NULL
+ && STRCMP(name_u, SYN_CLSTR(curbuf)[i].scl_name_u) == 0)
+ break;
+ vim_free(name_u);
+ return (i < 0 ? 0 : i + SYNID_CLUSTER);
+}
+
+/*
+ * Like syn_scl_name2id(), but take a pointer + length argument.
+ */
+ static int
+syn_scl_namen2id(linep, len)
+ char_u *linep;
+ int len;
+{
+ char_u *name;
+ int id = 0;
+
+ name = vim_strnsave(linep, len);
+ if (name != NULL)
+ {
+ id = syn_scl_name2id(name);
+ vim_free(name);
+ }
+ return id;
+}
+
+/*
+ * Find syntax cluster name in the table and return it's ID.
+ * The argument is a pointer to the name and the length of the name.
+ * If it doesn't exist yet, a new entry is created.
+ * Return 0 for failure.
+ */
+ static int
+syn_check_cluster(pp, len)
+ char_u *pp;
+ int len;
+{
+ int id;
+ char_u *name;
+
+ name = vim_strnsave(pp, len);
+ if (name == NULL)
+ return 0;
+
+ id = syn_scl_name2id(name);
+ if (id == 0) /* doesn't exist yet */
+ id = syn_add_cluster(name);
+ else
+ vim_free(name);
+ return id;
+}
+
+/*
+ * Add new syntax cluster and return it's ID.
+ * "name" must be an allocated string, it will be consumed.
+ * Return 0 for failure.
+ */
+ static int
+syn_add_cluster(name)
+ char_u *name;
+{
+ int len;
+
+ /*
+ * First call for this growarray: init growing array.
+ */
+ if (curbuf->b_syn_clusters.ga_data == NULL)
+ {
+ curbuf->b_syn_clusters.ga_itemsize = sizeof(struct syn_cluster);
+ curbuf->b_syn_clusters.ga_growsize = 10;
+ }
+
+ /*
+ * Make room for at least one other cluster entry.
+ */
+ if (ga_grow(&curbuf->b_syn_clusters, 1) == FAIL)
+ {
+ vim_free(name);
+ return 0;
+ }
+ len = curbuf->b_syn_clusters.ga_len;
+
+ vim_memset(&(SYN_CLSTR(curbuf)[len]), 0, sizeof(struct syn_cluster));
+ SYN_CLSTR(curbuf)[len].scl_name = name;
+ SYN_CLSTR(curbuf)[len].scl_name_u = vim_strsave_up(name);
+ SYN_CLSTR(curbuf)[len].scl_list = NULL;
+ ++curbuf->b_syn_clusters.ga_len;
+ --curbuf->b_syn_clusters.ga_room;
+
+ return len + SYNID_CLUSTER;
+}
+
+/*
+ * Handle ":syntax cluster {cluster-name} [contains={groupname},..]
+ * [add={groupname},..] [remove={groupname},..]".
+ */
+/* ARGSUSED */
+ static void
+syn_cmd_cluster(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* not used */
+{
+ char_u *arg = eap->arg;
+ char_u *group_name_end;
+ char_u *rest;
+ int scl_id;
+ short *clstr_list;
+ int got_clstr = FALSE;
+ int opt_len;
+ int list_op;
+
+ eap->nextcmd = find_nextcmd(arg);
+ if (eap->skip)
+ return;
+
+ rest = get_group_name(arg, &group_name_end);
+
+ if (rest != NULL)
+ {
+ scl_id = syn_check_cluster(arg, (int)(group_name_end - arg))
+ - SYNID_CLUSTER;
+
+ for (;;)
+ {
+ if (STRNICMP(rest, "add", 3) == 0
+ && (vim_iswhite(rest[3]) || rest[3] == '='))
+ {
+ opt_len = 3;
+ list_op = CLUSTER_ADD;
+ }
+ else if (STRNICMP(rest, "remove", 6) == 0
+ && (vim_iswhite(rest[6]) || rest[6] == '='))
+ {
+ opt_len = 6;
+ list_op = CLUSTER_SUBTRACT;
+ }
+ else if (STRNICMP(rest, "contains", 8) == 0
+ && (vim_iswhite(rest[8]) || rest[8] == '='))
+ {
+ opt_len = 8;
+ list_op = CLUSTER_REPLACE;
+ }
+ else
+ break;
+
+ clstr_list = NULL;
+ if (get_id_list(&rest, opt_len, &clstr_list) == FAIL)
+ {
+ EMSG2(_(e_invarg2), rest);
+ break;
+ }
+ syn_combine_list(&SYN_CLSTR(curbuf)[scl_id].scl_list,
+ &clstr_list, list_op);
+ got_clstr = TRUE;
+ }
+
+ if (got_clstr)
+ {
+ redraw_curbuf_later(NOT_VALID);
+ syn_stack_free_all(curbuf); /* Need to recompute all syntax. */
+ }
+ }
+
+ if (!got_clstr)
+ EMSG(_("E400: No cluster specified"));
+ if (rest == NULL || !ends_excmd(*rest))
+ EMSG2(_(e_invarg2), arg);
+}
+
+/*
+ * On first call for current buffer: Init growing array.
+ */
+ static void
+init_syn_patterns()
+{
+ curbuf->b_syn_patterns.ga_itemsize = sizeof(synpat_T);
+ curbuf->b_syn_patterns.ga_growsize = 10;
+}
+
+/*
+ * Get one pattern for a ":syntax match" or ":syntax region" command.
+ * Stores the pattern and program in a synpat_T.
+ * Returns a pointer to the next argument, or NULL in case of an error.
+ */
+ static char_u *
+get_syn_pattern(arg, ci)
+ char_u *arg;
+ synpat_T *ci;
+{
+ char_u *end;
+ int *p;
+ int idx;
+ char_u *cpo_save;
+
+ /* need at least three chars */
+ if (arg == NULL || arg[1] == NUL || arg[2] == NUL)
+ return NULL;
+
+ end = skip_regexp(arg + 1, *arg, TRUE, NULL);
+ if (*end != *arg) /* end delimiter not found */
+ {
+ EMSG2(_("E401: Pattern delimiter not found: %s"), arg);
+ return NULL;
+ }
+ /* store the pattern and compiled regexp program */
+ if ((ci->sp_pattern = vim_strnsave(arg + 1, (int)(end - arg - 1))) == NULL)
+ return NULL;
+
+ /* Make 'cpoptions' empty, to avoid the 'l' flag */
+ cpo_save = p_cpo;
+ p_cpo = (char_u *)"";
+ ci->sp_prog = vim_regcomp(ci->sp_pattern, RE_MAGIC);
+ p_cpo = cpo_save;
+
+ if (ci->sp_prog == NULL)
+ return NULL;
+ ci->sp_ic = curbuf->b_syn_ic;
+
+ /*
+ * Check for a match, highlight or region offset.
+ */
+ ++end;
+ do
+ {
+ for (idx = SPO_COUNT; --idx >= 0; )
+ if (STRNCMP(end, spo_name_tab[idx], 3) == 0)
+ break;
+ if (idx >= 0)
+ {
+ p = &(ci->sp_offsets[idx]);
+ if (idx != SPO_LC_OFF)
+ switch (end[3])
+ {
+ case 's': break;
+ case 'b': break;
+ case 'e': idx += SPO_COUNT; break;
+ default: idx = -1; break;
+ }
+ if (idx >= 0)
+ {
+ ci->sp_off_flags |= (1 << idx);
+ if (idx == SPO_LC_OFF) /* lc=99 */
+ {
+ end += 3;
+ *p = getdigits(&end);
+
+ /* "lc=" offset automatically sets "ms=" offset */
+ if (!(ci->sp_off_flags & (1 << SPO_MS_OFF)))
+ {
+ ci->sp_off_flags |= (1 << SPO_MS_OFF);
+ ci->sp_offsets[SPO_MS_OFF] = *p;
+ }
+ }
+ else /* yy=x+99 */
+ {
+ end += 4;
+ if (*end == '+')
+ {
+ ++end;
+ *p = getdigits(&end); /* positive offset */
+ }
+ else if (*end == '-')
+ {
+ ++end;
+ *p = -getdigits(&end); /* negative offset */
+ }
+ }
+ if (*end != ',')
+ break;
+ ++end;
+ }
+ }
+ } while (idx >= 0);
+
+ if (!ends_excmd(*end) && !vim_iswhite(*end))
+ {
+ EMSG2(_("E402: Garbage after pattern: %s"), arg);
+ return NULL;
+ }
+ return skipwhite(end);
+}
+
+/*
+ * Handle ":syntax sync .." command.
+ */
+/* ARGSUSED */
+ static void
+syn_cmd_sync(eap, syncing)
+ exarg_T *eap;
+ int syncing; /* not used */
+{
+ char_u *arg_start = eap->arg;
+ char_u *arg_end;
+ char_u *key = NULL;
+ char_u *next_arg;
+ int illegal = FALSE;
+ int finished = FALSE;
+ long n;
+ char_u *cpo_save;
+
+ if (ends_excmd(*arg_start))
+ {
+ syn_cmd_list(eap, TRUE);
+ return;
+ }
+
+ while (!ends_excmd(*arg_start))
+ {
+ arg_end = skiptowhite(arg_start);
+ next_arg = skipwhite(arg_end);
+ vim_free(key);
+ key = vim_strnsave_up(arg_start, (int)(arg_end - arg_start));
+ if (STRCMP(key, "CCOMMENT") == 0)
+ {
+ if (!eap->skip)
+ curbuf->b_syn_sync_flags |= SF_CCOMMENT;
+ if (!ends_excmd(*next_arg))
+ {
+ arg_end = skiptowhite(next_arg);
+ if (!eap->skip)
+ curbuf->b_syn_sync_id = syn_check_group(next_arg,
+ (int)(arg_end - next_arg));
+ next_arg = skipwhite(arg_end);
+ }
+ else if (!eap->skip)
+ curbuf->b_syn_sync_id = syn_name2id((char_u *)"Comment");
+ }
+ else if ( STRNCMP(key, "LINES", 5) == 0
+ || STRNCMP(key, "MINLINES", 8) == 0
+ || STRNCMP(key, "MAXLINES", 8) == 0
+ || STRNCMP(key, "LINEBREAKS", 10) == 0)
+ {
+ if (key[4] == 'S')
+ arg_end = key + 6;
+ else if (key[0] == 'L')
+ arg_end = key + 11;
+ else
+ arg_end = key + 9;
+ if (arg_end[-1] != '=' || !VIM_ISDIGIT(*arg_end))
+ {
+ illegal = TRUE;
+ break;
+ }
+ n = getdigits(&arg_end);
+ if (!eap->skip)
+ {
+ if (key[4] == 'B')
+ curbuf->b_syn_sync_linebreaks = n;
+ else if (key[1] == 'A')
+ curbuf->b_syn_sync_maxlines = n;
+ else
+ curbuf->b_syn_sync_minlines = n;
+ }
+ }
+ else if (STRCMP(key, "FROMSTART") == 0)
+ {
+ if (!eap->skip)
+ {
+ curbuf->b_syn_sync_minlines = MAXLNUM;
+ curbuf->b_syn_sync_maxlines = 0;
+ }
+ }
+ else if (STRCMP(key, "LINECONT") == 0)
+ {
+ if (curbuf->b_syn_linecont_pat != NULL)
+ {
+ EMSG(_("E403: syntax sync: line continuations pattern specified twice"));
+ finished = TRUE;
+ break;
+ }
+ arg_end = skip_regexp(next_arg + 1, *next_arg, TRUE, NULL);
+ if (*arg_end != *next_arg) /* end delimiter not found */
+ {
+ illegal = TRUE;
+ break;
+ }
+
+ if (!eap->skip)
+ {
+ /* store the pattern and compiled regexp program */
+ if ((curbuf->b_syn_linecont_pat = vim_strnsave(next_arg + 1,
+ (int)(arg_end - next_arg - 1))) == NULL)
+ {
+ finished = TRUE;
+ break;
+ }
+ curbuf->b_syn_linecont_ic = curbuf->b_syn_ic;
+
+ /* Make 'cpoptions' empty, to avoid the 'l' flag */
+ cpo_save = p_cpo;
+ p_cpo = (char_u *)"";
+ curbuf->b_syn_linecont_prog =
+ vim_regcomp(curbuf->b_syn_linecont_pat, RE_MAGIC);
+ p_cpo = cpo_save;
+
+ if (curbuf->b_syn_linecont_prog == NULL)
+ {
+ vim_free(curbuf->b_syn_linecont_pat);
+ curbuf->b_syn_linecont_pat = NULL;
+ finished = TRUE;
+ break;
+ }
+ }
+ next_arg = skipwhite(arg_end + 1);
+ }
+ else
+ {
+ eap->arg = next_arg;
+ if (STRCMP(key, "MATCH") == 0)
+ syn_cmd_match(eap, TRUE);
+ else if (STRCMP(key, "REGION") == 0)
+ syn_cmd_region(eap, TRUE);
+ else if (STRCMP(key, "CLEAR") == 0)
+ syn_cmd_clear(eap, TRUE);
+ else
+ illegal = TRUE;
+ finished = TRUE;
+ break;
+ }
+ arg_start = next_arg;
+ }
+ vim_free(key);
+ if (illegal)
+ EMSG2(_("E404: Illegal arguments: %s"), arg_start);
+ else if (!finished)
+ {
+ eap->nextcmd = check_nextcmd(arg_start);
+ redraw_curbuf_later(NOT_VALID);
+ syn_stack_free_all(curbuf); /* Need to recompute all syntax. */
+ }
+}
+
+/*
+ * Convert a line of highlight group names into a list of group ID numbers.
+ * "arg" should point to the "contains" or "nextgroup" keyword.
+ * "arg" is advanced to after the last group name.
+ * Careful: the argument is modified (NULs added).
+ * returns FAIL for some error, OK for success.
+ */
+ static int
+get_id_list(arg, keylen, list)
+ char_u **arg;
+ int keylen; /* length of keyword */
+ short **list; /* where to store the resulting list, if not
+ NULL, the list is silently skipped! */
+{
+ char_u *p = NULL;
+ char_u *end;
+ int round;
+ int count;
+ int total_count = 0;
+ short *retval = NULL;
+ char_u *name;
+ regmatch_T regmatch;
+ int id;
+ int i;
+ int failed = FALSE;
+
+ /*
+ * We parse the list twice:
+ * round == 1: count the number of items, allocate the array.
+ * round == 2: fill the array with the items.
+ * In round 1 new groups may be added, causing the number of items to
+ * grow when a regexp is used. In that case round 1 is done once again.
+ */
+ for (round = 1; round <= 2; ++round)
+ {
+ /*
+ * skip "contains"
+ */
+ p = skipwhite(*arg + keylen);
+ if (*p != '=')
+ {
+ EMSG2(_("E405: Missing equal sign: %s"), *arg);
+ break;
+ }
+ p = skipwhite(p + 1);
+ if (ends_excmd(*p))
+ {
+ EMSG2(_("E406: Empty argument: %s"), *arg);
+ break;
+ }
+
+ /*
+ * parse the arguments after "contains"
+ */
+ count = 0;
+ while (!ends_excmd(*p))
+ {
+ for (end = p; *end && !vim_iswhite(*end) && *end != ','; ++end)
+ ;
+ name = alloc((int)(end - p + 3)); /* leave room for "^$" */
+ if (name == NULL)
+ {
+ failed = TRUE;
+ break;
+ }
+ STRNCPY(name + 1, p, end - p);
+ name[end - p + 1] = NUL;
+ if ( STRCMP(name + 1, "ALLBUT") == 0
+ || STRCMP(name + 1, "ALL") == 0
+ || STRCMP(name + 1, "TOP") == 0
+ || STRCMP(name + 1, "CONTAINED") == 0)
+ {
+ if (TOUPPER_ASC(**arg) != 'C')
+ {
+ EMSG2(_("E407: %s not allowed here"), name + 1);
+ failed = TRUE;
+ vim_free(name);
+ break;
+ }
+ if (count != 0)
+ {
+ EMSG2(_("E408: %s must be first in contains list"), name + 1);
+ failed = TRUE;
+ vim_free(name);
+ break;
+ }
+ if (name[1] == 'A')
+ id = SYNID_ALLBUT;
+ else if (name[1] == 'T')
+ id = SYNID_TOP;
+ else
+ id = SYNID_CONTAINED;
+ id += current_syn_inc_tag;
+ }
+ else if (name[1] == '@')
+ {
+ id = syn_check_cluster(name + 2, (int)(end - p - 1));
+ }
+ else
+ {
+ /*
+ * Handle full group name.
+ */
+ if (vim_strpbrk(name + 1, (char_u *)"\\.*^$~[") == NULL)
+ id = syn_check_group(name + 1, (int)(end - p));
+ else
+ {
+ /*
+ * Handle match of regexp with group names.
+ */
+ *name = '^';
+ STRCAT(name, "$");
+ regmatch.regprog = vim_regcomp(name, RE_MAGIC);
+ if (regmatch.regprog == NULL)
+ {
+ failed = TRUE;
+ vim_free(name);
+ break;
+ }
+
+ regmatch.rm_ic = TRUE;
+ id = 0;
+ for (i = highlight_ga.ga_len; --i >= 0; )
+ {
+ if (vim_regexec(&regmatch, HL_TABLE()[i].sg_name,
+ (colnr_T)0))
+ {
+ if (round == 2)
+ {
+ /* Got more items than expected; can happen
+ * when adding items that match:
+ * "contains=a.*b,axb".
+ * Go back to first round */
+ if (count >= total_count)
+ {
+ vim_free(retval);
+ round = 1;
+ }
+ else
+ retval[count] = i + 1;
+ }
+ ++count;
+ id = -1; /* remember that we found one */
+ }
+ }
+ vim_free(regmatch.regprog);
+ }
+ }
+ vim_free(name);
+ if (id == 0)
+ {
+ EMSG2(_("E409: Unknown group name: %s"), p);
+ failed = TRUE;
+ break;
+ }
+ if (id > 0)
+ {
+ if (round == 2)
+ {
+ /* Got more items than expected, go back to first round */
+ if (count >= total_count)
+ {
+ vim_free(retval);
+ round = 1;
+ }
+ else
+ retval[count] = id;
+ }
+ ++count;
+ }
+ p = skipwhite(end);
+ if (*p != ',')
+ break;
+ p = skipwhite(p + 1); /* skip comma in between arguments */
+ }
+ if (failed)
+ break;
+ if (round == 1)
+ {
+ retval = (short *)alloc((unsigned)((count + 1) * sizeof(short)));
+ if (retval == NULL)
+ break;
+ retval[count] = 0; /* zero means end of the list */
+ total_count = count;
+ }
+ }
+
+ *arg = p;
+ if (failed || retval == NULL)
+ {
+ vim_free(retval);
+ return FAIL;
+ }
+
+ if (*list == NULL)
+ *list = retval;
+ else
+ vim_free(retval); /* list already found, don't overwrite it */
+
+ return OK;
+}
+
+/*
+ * Make a copy of an ID list.
+ */
+ static short *
+copy_id_list(list)
+ short *list;
+{
+ int len;
+ int count;
+ short *retval;
+
+ if (list == NULL)
+ return NULL;
+
+ for (count = 0; list[count]; ++count)
+ ;
+ len = (count + 1) * sizeof(short);
+ retval = (short *)alloc((unsigned)len);
+ if (retval != NULL)
+ mch_memmove(retval, list, (size_t)len);
+
+ return retval;
+}
+
+/*
+ * Check if syntax group "ssp" is in the ID list "list" of "cur_si".
+ * "cur_si" can be NULL if not checking the "containedin" list.
+ * Used to check if a syntax item is in the "contains" or "nextgroup" list of
+ * the current item.
+ * This function is called very often, keep it fast!!
+ */
+ static int
+in_id_list(cur_si, list, ssp, contained)
+ stateitem_T *cur_si; /* current item or NULL */
+ short *list; /* id list */
+ struct sp_syn *ssp; /* group id and ":syn include" tag of group */
+ int contained; /* group id is contained */
+{
+ int retval;
+ short *scl_list;
+ short item;
+ short id = ssp->id;
+ static int depth = 0;
+ int r;
+
+ /* If spp has a "containedin" list and "cur_si" is in it, return TRUE. */
+ if (cur_si != NULL && ssp->cont_in_list != NULL)
+ {
+ /* Ignore transparent items without a contains argument. Double check
+ * that we don't go back past the first one. */
+ while ((cur_si->si_flags & HL_TRANS_CONT)
+ && cur_si > (stateitem_T *)(current_state.ga_data))
+ --cur_si;
+ /* cur_si->si_idx is -1 for keywords, these never contain anything. */
+ if (cur_si->si_idx >= 0 && in_id_list(NULL, ssp->cont_in_list,
+ &(SYN_ITEMS(syn_buf)[cur_si->si_idx].sp_syn),
+ SYN_ITEMS(syn_buf)[cur_si->si_idx].sp_flags & HL_CONTAINED))
+ return TRUE;
+ }
+
+ if (list == NULL)
+ return FALSE;
+
+ /*
+ * If list is ID_LIST_ALL, we are in a transparent item that isn't
+ * inside anything. Only allow not-contained groups.
+ */
+ if (list == ID_LIST_ALL)
+ return !contained;
+
+ /*
+ * If the first item is "ALLBUT", return TRUE if "id" is NOT in the
+ * contains list. We also require that "id" is at the same ":syn include"
+ * level as the list.
+ */
+ item = *list;
+ if (item >= SYNID_ALLBUT && item < SYNID_CLUSTER)
+ {
+ if (item < SYNID_TOP)
+ {
+ /* ALL or ALLBUT: accept all groups in the same file */
+ if (item - SYNID_ALLBUT != ssp->inc_tag)
+ return FALSE;
+ }
+ else if (item < SYNID_CONTAINED)
+ {
+ /* TOP: accept all not-contained groups in the same file */
+ if (item - SYNID_TOP != ssp->inc_tag || contained)
+ return FALSE;
+ }
+ else
+ {
+ /* CONTAINED: accept all contained groups in the same file */
+ if (item - SYNID_CONTAINED != ssp->inc_tag || !contained)
+ return FALSE;
+ }
+ item = *++list;
+ retval = FALSE;
+ }
+ else
+ retval = TRUE;
+
+ /*
+ * Return "retval" if id is in the contains list.
+ */
+ while (item != 0)
+ {
+ if (item == id)
+ return retval;
+ if (item >= SYNID_CLUSTER)
+ {
+ scl_list = SYN_CLSTR(syn_buf)[item - SYNID_CLUSTER].scl_list;
+ /* restrict recursiveness to 30 to avoid an endless loop for a
+ * cluster that includes itself (indirectly) */
+ if (scl_list != NULL && depth < 30)
+ {
+ ++depth;
+ r = in_id_list(NULL, scl_list, ssp, contained);
+ --depth;
+ if (r)
+ return retval;
+ }
+ }
+ item = *++list;
+ }
+ return !retval;
+}
+
+struct subcommand
+{
+ char *name; /* subcommand name */
+ void (*func)__ARGS((exarg_T *, int)); /* function to call */
+};
+
+static struct subcommand subcommands[] =
+{
+ {"case", syn_cmd_case},
+ {"clear", syn_cmd_clear},
+ {"cluster", syn_cmd_cluster},
+ {"enable", syn_cmd_enable},
+ {"include", syn_cmd_include},
+ {"keyword", syn_cmd_keyword},
+ {"list", syn_cmd_list},
+ {"manual", syn_cmd_manual},
+ {"match", syn_cmd_match},
+ {"on", syn_cmd_on},
+ {"off", syn_cmd_off},
+ {"region", syn_cmd_region},
+ {"reset", syn_cmd_reset},
+ {"sync", syn_cmd_sync},
+ {"", syn_cmd_list},
+ {NULL, NULL}
+};
+
+/*
+ * ":syntax".
+ * This searches the subcommands[] table for the subcommand name, and calls a
+ * syntax_subcommand() function to do the rest.
+ */
+ void
+ex_syntax(eap)
+ exarg_T *eap;
+{
+ char_u *arg = eap->arg;
+ char_u *subcmd_end;
+ char_u *subcmd_name;
+ int i;
+
+ syn_cmdlinep = eap->cmdlinep;
+
+ /* isolate subcommand name */
+ for (subcmd_end = arg; ASCII_ISALPHA(*subcmd_end); ++subcmd_end)
+ ;
+ subcmd_name = vim_strnsave(arg, (int)(subcmd_end - arg));
+ if (subcmd_name != NULL)
+ {
+ if (eap->skip) /* skip error messages for all subcommands */
+ ++emsg_skip;
+ for (i = 0; ; ++i)
+ {
+ if (subcommands[i].name == NULL)
+ {
+ EMSG2(_("E410: Invalid :syntax subcommand: %s"), subcmd_name);
+ break;
+ }
+ if (STRCMP(subcmd_name, (char_u *)subcommands[i].name) == 0)
+ {
+ eap->arg = skipwhite(subcmd_end);
+ (subcommands[i].func)(eap, FALSE);
+ break;
+ }
+ }
+ vim_free(subcmd_name);
+ if (eap->skip)
+ --emsg_skip;
+ }
+}
+
+ int
+syntax_present(buf)
+ buf_T *buf;
+{
+ return (buf->b_syn_patterns.ga_len != 0
+ || buf->b_syn_clusters.ga_len != 0
+ || curbuf->b_keywtab != NULL
+ || curbuf->b_keywtab_ic != NULL);
+}
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+
+static enum
+{
+ EXP_SUBCMD, /* expand ":syn" sub-commands */
+ EXP_CASE /* expand ":syn case" arguments */
+} expand_what;
+
+
+/*
+ * Handle command line completion for :syntax command.
+ */
+ void
+set_context_in_syntax_cmd(xp, arg)
+ expand_T *xp;
+ char_u *arg;
+{
+ char_u *p;
+
+ /* Default: expand subcommands */
+ xp->xp_context = EXPAND_SYNTAX;
+ expand_what = EXP_SUBCMD;
+ xp->xp_pattern = arg;
+ include_link = FALSE;
+ include_default = FALSE;
+
+ /* (part of) subcommand already typed */
+ if (*arg != NUL)
+ {
+ p = skiptowhite(arg);
+ if (*p != NUL) /* past first word */
+ {
+ xp->xp_pattern = skipwhite(p);
+ if (*skiptowhite(xp->xp_pattern) != NUL)
+ xp->xp_context = EXPAND_NOTHING;
+ else if (STRNICMP(arg, "case", p - arg) == 0)
+ expand_what = EXP_CASE;
+ else if ( STRNICMP(arg, "keyword", p - arg) == 0
+ || STRNICMP(arg, "region", p - arg) == 0
+ || STRNICMP(arg, "match", p - arg) == 0
+ || STRNICMP(arg, "list", p - arg) == 0)
+ xp->xp_context = EXPAND_HIGHLIGHT;
+ else
+ xp->xp_context = EXPAND_NOTHING;
+ }
+ }
+}
+
+static char *(case_args[]) = {"match", "ignore", NULL};
+
+/*
+ * Function given to ExpandGeneric() to obtain the list syntax names for
+ * expansion.
+ */
+/*ARGSUSED*/
+ char_u *
+get_syntax_name(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ if (expand_what == EXP_SUBCMD)
+ return (char_u *)subcommands[idx].name;
+ return (char_u *)case_args[idx];
+}
+
+#endif /* FEAT_CMDL_COMPL */
+
+#if defined(FEAT_EVAL) || defined(FEAT_PRINTER) || defined(PROTO)
+/*
+ * Function called for expression evaluation: get syntax ID at file position.
+ */
+ int
+syn_get_id(lnum, col, trans)
+ long lnum;
+ long col;
+ int trans; /* remove transparancy */
+{
+ /* When the position is not after the current position and in the same
+ * line of the same buffer, need to restart parsing. */
+ if (curwin->w_buffer != syn_buf
+ || lnum != current_lnum
+ || col < (long)current_col)
+ syntax_start(curwin, lnum);
+
+ (void)get_syntax_attr((colnr_T)col);
+
+ return (trans ? current_trans_id : current_id);
+}
+#endif
+
+#if defined(FEAT_FOLDING) || defined(PROTO)
+/*
+ * Function called to get folding level for line "lnum" in window "wp".
+ */
+ int
+syn_get_foldlevel(wp, lnum)
+ win_T *wp;
+ long lnum;
+{
+ int level = 0;
+ int i;
+
+ /* Return quickly when there are no fold items at all. */
+ if (wp->w_buffer->b_syn_folditems != 0)
+ {
+ syntax_start(wp, lnum);
+
+ for (i = 0; i < current_state.ga_len; ++i)
+ if (CUR_STATE(i).si_flags & HL_FOLD)
+ ++level;
+ }
+ if (level > wp->w_p_fdn)
+ level = wp->w_p_fdn;
+ return level;
+}
+#endif
+
+#endif /* FEAT_SYN_HL */
+
+
+/**************************************
+ * Highlighting stuff *
+ **************************************/
+
+/*
+ * The default highlight groups. These are compiled-in for fast startup and
+ * they still work when the runtime files can't be found.
+ * When making changes here, also change runtime/colors/default.vim!
+ */
+static char *(highlight_init_both[]) =
+ {
+#ifdef FEAT_GUI
+ "Cursor guibg=fg guifg=bg",
+ "lCursor guibg=fg guifg=bg", /* should be different, but what? */
+#endif
+ "ErrorMsg term=standout ctermbg=DarkRed ctermfg=White guibg=Red guifg=White",
+ "IncSearch term=reverse cterm=reverse gui=reverse",
+ "ModeMsg term=bold cterm=bold gui=bold",
+ "NonText term=bold ctermfg=Blue gui=bold guifg=Blue",
+ "StatusLine term=reverse,bold cterm=reverse,bold gui=reverse,bold",
+ "StatusLineNC term=reverse cterm=reverse gui=reverse",
+ "VertSplit term=reverse cterm=reverse gui=reverse",
+ "Visual term=reverse cterm=reverse gui=reverse guifg=Grey guibg=fg",
+ "VisualNOS term=underline,bold cterm=underline,bold gui=underline,bold",
+ "DiffText term=reverse cterm=bold ctermbg=Red gui=bold guibg=Red",
+ NULL
+ };
+
+static char *(highlight_init_light[]) =
+ {
+ "Directory term=bold ctermfg=DarkBlue guifg=Blue",
+ "LineNr term=underline ctermfg=Brown guifg=Brown",
+ "MoreMsg term=bold ctermfg=DarkGreen gui=bold guifg=SeaGreen",
+ "Normal gui=NONE",
+ "Question term=standout ctermfg=DarkGreen gui=bold guifg=SeaGreen",
+ "Search term=reverse ctermbg=Yellow ctermfg=NONE guibg=Yellow guifg=NONE",
+ "SpecialKey term=bold ctermfg=DarkBlue guifg=Blue",
+ "Title term=bold ctermfg=DarkMagenta gui=bold guifg=Magenta",
+ "WarningMsg term=standout ctermfg=DarkRed guifg=Red",
+ "WildMenu term=standout ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black",
+ "Folded term=standout ctermbg=Grey ctermfg=DarkBlue guibg=LightGrey guifg=DarkBlue",
+ "FoldColumn term=standout ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue",
+ "SignColumn term=standout ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue",
+ "DiffAdd term=bold ctermbg=LightBlue guibg=LightBlue",
+ "DiffChange term=bold ctermbg=LightMagenta guibg=LightMagenta",
+ "DiffDelete term=bold ctermfg=Blue ctermbg=LightCyan gui=bold guifg=Blue guibg=LightCyan",
+ NULL
+ };
+
+static char *(highlight_init_dark[]) =
+ {
+ "Directory term=bold ctermfg=LightCyan guifg=Cyan",
+ "LineNr term=underline ctermfg=Yellow guifg=Yellow",
+ "MoreMsg term=bold ctermfg=LightGreen gui=bold guifg=SeaGreen",
+ "Normal gui=NONE",
+ "Question term=standout ctermfg=LightGreen gui=bold guifg=Green",
+ "Search term=reverse ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black",
+ "SpecialKey term=bold ctermfg=LightBlue guifg=Cyan",
+ "Title term=bold ctermfg=LightMagenta gui=bold guifg=Magenta",
+ "WarningMsg term=standout ctermfg=LightRed guifg=Red",
+ "WildMenu term=standout ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black",
+ "Folded term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=DarkGrey guifg=Cyan",
+ "FoldColumn term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan",
+ "SignColumn term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan",
+ "DiffAdd term=bold ctermbg=DarkBlue guibg=DarkBlue",
+ "DiffChange term=bold ctermbg=DarkMagenta guibg=DarkMagenta",
+ "DiffDelete term=bold ctermfg=Blue ctermbg=DarkCyan gui=bold guifg=Blue guibg=DarkCyan",
+ NULL
+ };
+
+ void
+init_highlight(both, reset)
+ int both; /* include groups where 'bg' doesn't matter */
+ int reset; /* clear group first */
+{
+ int i;
+ char **pp;
+ static int had_both = FALSE;
+#ifdef FEAT_EVAL
+ char_u *p;
+
+ /*
+ * Try finding the color scheme file. Used when a color file was loaded
+ * and 'background' or 't_Co' is changed.
+ */
+ p = get_var_value((char_u *)"g:colors_name");
+ if (p != NULL && load_colors(p) == OK)
+ return;
+#endif
+
+ /*
+ * Didn't use a color file, use the compiled-in colors.
+ */
+ if (both)
+ {
+ had_both = TRUE;
+ pp = highlight_init_both;
+ for (i = 0; pp[i] != NULL; ++i)
+ do_highlight((char_u *)pp[i], reset, TRUE);
+ }
+ else if (!had_both)
+ /* Don't do anything before the call with both == TRUE from main().
+ * Not everything has been setup then, and that call will overrule
+ * everything anyway. */
+ return;
+
+ if (*p_bg == 'l')
+ pp = highlight_init_light;
+ else
+ pp = highlight_init_dark;
+ for (i = 0; pp[i] != NULL; ++i)
+ do_highlight((char_u *)pp[i], reset, TRUE);
+
+#ifdef FEAT_SYN_HL
+ /*
+ * If syntax highlighting is enabled load the highlighting for it.
+ */
+ if (get_var_value((char_u *)"g:syntax_on") != NULL)
+ (void)cmd_runtime((char_u *)"syntax/syncolor.vim", TRUE);
+#endif
+}
+
+/*
+ * Load color file "p".
+ * Return OK for success, FAIL for failure.
+ */
+ int
+load_colors(p)
+ char_u *p;
+{
+ char_u *buf;
+ int retval = FAIL;
+ static int recursive = FALSE;
+
+ /* When being called recursively, this is probably because setting
+ * 'background' caused the highlighting to be reloaded. This means it is
+ * working, thus we should return OK. */
+ if (recursive)
+ return OK;
+
+ recursive = TRUE;
+ buf = alloc((unsigned)(STRLEN(p) + 12));
+ if (buf != NULL)
+ {
+ sprintf((char *)buf, "colors/%s.vim", p);
+ retval = cmd_runtime(buf, FALSE);
+ vim_free(buf);
+ }
+ recursive = FALSE;
+
+ return retval;
+}
+
+/*
+ * Handle the ":highlight .." command.
+ * When using ":hi clear" this is called recursively for each group with
+ * "forceit" and "init" both TRUE.
+ */
+ void
+do_highlight(line, forceit, init)
+ char_u *line;
+ int forceit;
+ int init; /* TRUE when called for initializing */
+{
+ char_u *name_end;
+ char_u *p;
+ char_u *linep;
+ char_u *key_start;
+ char_u *arg_start;
+ char_u *key = NULL, *arg = NULL;
+ long i;
+ int off;
+ int len;
+ int attr;
+ int id;
+ int idx;
+ int dodefault = FALSE;
+ int doclear = FALSE;
+ int dolink = FALSE;
+ int error = FALSE;
+ int color;
+ int is_normal_group = FALSE; /* "Normal" group */
+#ifdef FEAT_GUI_X11
+ int is_menu_group = FALSE; /* "Menu" group */
+ int is_scrollbar_group = FALSE; /* "Scrollbar" group */
+ int is_tooltip_group = FALSE; /* "Tooltip" group */
+ int do_colors = FALSE; /* need to update colors? */
+#else
+# define is_menu_group 0
+# define is_tooltip_group 0
+#endif
+
+ /*
+ * If no argument, list current highlighting.
+ */
+ if (ends_excmd(*line))
+ {
+ for (i = 1; i <= highlight_ga.ga_len && !got_int; ++i)
+ /* TODO: only call when the group has attributes set */
+ highlight_list_one((int)i);
+ return;
+ }
+
+ /*
+ * Isolate the name.
+ */
+ name_end = skiptowhite(line);
+ linep = skipwhite(name_end);
+
+ /*
+ * Check for "default" argument.
+ */
+ if (STRNCMP(line, "default", name_end - line) == 0)
+ {
+ dodefault = TRUE;
+ line = linep;
+ name_end = skiptowhite(line);
+ linep = skipwhite(name_end);
+ }
+
+ /*
+ * Check for "clear" or "link" argument.
+ */
+ if (STRNCMP(line, "clear", name_end - line) == 0)
+ doclear = TRUE;
+ if (STRNCMP(line, "link", name_end - line) == 0)
+ dolink = TRUE;
+
+ /*
+ * ":highlight {group-name}": list highlighting for one group.
+ */
+ if (!doclear && !dolink && ends_excmd(*linep))
+ {
+ id = syn_namen2id(line, (int)(name_end - line));
+ if (id == 0)
+ EMSG2(_("E411: highlight group not found: %s"), line);
+ else
+ highlight_list_one(id);
+ return;
+ }
+
+ /*
+ * Handle ":highlight link {from} {to}" command.
+ */
+ if (dolink)
+ {
+ char_u *from_start = linep;
+ char_u *from_end;
+ char_u *to_start;
+ char_u *to_end;
+ int from_id;
+ int to_id;
+
+ from_end = skiptowhite(from_start);
+ to_start = skipwhite(from_end);
+ to_end = skiptowhite(to_start);
+
+ if (ends_excmd(*from_start) || ends_excmd(*to_start))
+ {
+ EMSG2(_("E412: Not enough arguments: \":highlight link %s\""),
+ from_start);
+ return;
+ }
+
+ if (!ends_excmd(*skipwhite(to_end)))
+ {
+ EMSG2(_("E413: Too many arguments: \":highlight link %s\""), from_start);
+ return;
+ }
+
+ from_id = syn_check_group(from_start, (int)(from_end - from_start));
+ if (STRNCMP(to_start, "NONE", 4) == 0)
+ to_id = 0;
+ else
+ to_id = syn_check_group(to_start, (int)(to_end - to_start));
+
+ if (from_id > 0 && (!init || HL_TABLE()[from_id - 1].sg_set == 0))
+ {
+ /*
+ * Don't allow a link when there already is some highlighting
+ * for the group, unless '!' is used
+ */
+ if (to_id > 0 && !forceit && !init
+ && hl_has_settings(from_id - 1, dodefault))
+ {
+ if (sourcing_name == NULL && !dodefault)
+ EMSG(_("E414: group has settings, highlight link ignored"));
+ }
+ else
+ {
+ if (!init)
+ HL_TABLE()[from_id - 1].sg_set |= SG_LINK;
+ HL_TABLE()[from_id - 1].sg_link = to_id;
+ redraw_all_later(NOT_VALID);
+ }
+ }
+
+ /* Only call highlight_changed() once, after sourcing a syntax file */
+ need_highlight_changed = TRUE;
+
+ return;
+ }
+
+ if (doclear)
+ {
+ /*
+ * ":highlight clear [group]" command.
+ */
+ line = linep;
+ if (ends_excmd(*line))
+ {
+#ifdef FEAT_GUI
+ /* First, we do not destroy the old values, but allocate the new
+ * ones and update the display. THEN we destroy the old values.
+ * If we destroy the old values first, then the old values
+ * (such as GuiFont's or GuiFontset's) will still be displayed but
+ * invalid because they were free'd.
+ */
+ if (gui.in_use)
+ {
+# ifdef FEAT_BEVAL_TIP
+ gui_init_tooltip_font();
+# endif
+# if defined(FEAT_MENU) && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF))
+ gui_init_menu_font();
+# endif
+ }
+# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_X11)
+ gui_mch_def_colors();
+# endif
+# ifdef FEAT_GUI_X11
+# ifdef FEAT_MENU
+
+ /* This only needs to be done when there is no Menu highlight
+ * group defined by default, which IS currently the case.
+ */
+ gui_mch_new_menu_colors();
+# endif
+ if (gui.in_use)
+ {
+ gui_new_scrollbar_colors();
+# ifdef FEAT_BEVAL
+ gui_mch_new_tooltip_colors();
+# endif
+# ifdef FEAT_MENU
+ gui_mch_new_menu_font();
+# endif
+ }
+# endif
+
+ /* Ok, we're done allocating the new default graphics items.
+ * The screen should already be refreshed at this point.
+ * It is now Ok to clear out the old data.
+ */
+#endif
+#ifdef FEAT_EVAL
+ do_unlet((char_u *)"colors_name");
+#endif
+ restore_cterm_colors();
+
+ /*
+ * Clear all default highlight groups and load the defaults.
+ */
+ for (idx = 0; idx < highlight_ga.ga_len; ++idx)
+ highlight_clear(idx);
+ init_highlight(TRUE, TRUE);
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ highlight_gui_started();
+#endif
+ highlight_changed();
+ redraw_later_clear();
+ return;
+ }
+ name_end = skiptowhite(line);
+ linep = skipwhite(name_end);
+ }
+
+ /*
+ * Find the group name in the table. If it does not exist yet, add it.
+ */
+ id = syn_check_group(line, (int)(name_end - line));
+ if (id == 0) /* failed (out of memory) */
+ return;
+ idx = id - 1; /* index is ID minus one */
+
+ /* Return if "default" was used and the group already has settings. */
+ if (dodefault && hl_has_settings(idx, TRUE))
+ return;
+
+ if (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0)
+ is_normal_group = TRUE;
+#ifdef FEAT_GUI_X11
+ else if (STRCMP(HL_TABLE()[idx].sg_name_u, "MENU") == 0)
+ is_menu_group = TRUE;
+ else if (STRCMP(HL_TABLE()[idx].sg_name_u, "SCROLLBAR") == 0)
+ is_scrollbar_group = TRUE;
+ else if (STRCMP(HL_TABLE()[idx].sg_name_u, "TOOLTIP") == 0)
+ is_tooltip_group = TRUE;
+#endif
+
+ /* Clear the highlighting for ":hi clear {group}" and ":hi clear". */
+ if (doclear || (forceit && init))
+ {
+ highlight_clear(idx);
+ if (!doclear)
+ HL_TABLE()[idx].sg_set = 0;
+ }
+
+ if (!doclear)
+ while (!ends_excmd(*linep))
+ {
+ key_start = linep;
+ if (*linep == '=')
+ {
+ EMSG2(_("E415: unexpected equal sign: %s"), key_start);
+ error = TRUE;
+ break;
+ }
+
+ /*
+ * Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg" or
+ * "guibg").
+ */
+ while (*linep && !vim_iswhite(*linep) && *linep != '=')
+ ++linep;
+ vim_free(key);
+ key = vim_strnsave_up(key_start, (int)(linep - key_start));
+ if (key == NULL)
+ {
+ error = TRUE;
+ break;
+ }
+ linep = skipwhite(linep);
+
+ if (STRCMP(key, "NONE") == 0)
+ {
+ if (!init || HL_TABLE()[idx].sg_set == 0)
+ {
+ if (!init)
+ HL_TABLE()[idx].sg_set |= SG_TERM+SG_CTERM+SG_GUI;
+ highlight_clear(idx);
+ }
+ continue;
+ }
+
+ /*
+ * Check for the equal sign.
+ */
+ if (*linep != '=')
+ {
+ EMSG2(_("E416: missing equal sign: %s"), key_start);
+ error = TRUE;
+ break;
+ }
+ ++linep;
+
+ /*
+ * Isolate the argument.
+ */
+ linep = skipwhite(linep);
+ if (*linep == '\'') /* guifg='color name' */
+ {
+ arg_start = ++linep;
+ linep = vim_strchr(linep, '\'');
+ if (linep == NULL)
+ {
+ EMSG2(_(e_invarg2), key_start);
+ error = TRUE;
+ break;
+ }
+ }
+ else
+ {
+ arg_start = linep;
+ linep = skiptowhite(linep);
+ }
+ if (linep == arg_start)
+ {
+ EMSG2(_("E417: missing argument: %s"), key_start);
+ error = TRUE;
+ break;
+ }
+ vim_free(arg);
+ arg = vim_strnsave(arg_start, (int)(linep - arg_start));
+ if (arg == NULL)
+ {
+ error = TRUE;
+ break;
+ }
+ if (*linep == '\'')
+ ++linep;
+
+ /*
+ * Store the argument.
+ */
+ if ( STRCMP(key, "TERM") == 0
+ || STRCMP(key, "CTERM") == 0
+ || STRCMP(key, "GUI") == 0)
+ {
+ attr = 0;
+ off = 0;
+ while (arg[off] != NUL)
+ {
+ for (i = sizeof(hl_attr_table) / sizeof(int); --i >= 0; )
+ {
+ len = (int)STRLEN(hl_name_table[i]);
+ if (STRNICMP(arg + off, hl_name_table[i], len) == 0)
+ {
+ attr |= hl_attr_table[i];
+ off += len;
+ break;
+ }
+ }
+ if (i < 0)
+ {
+ EMSG2(_("E418: Illegal value: %s"), arg);
+ error = TRUE;
+ break;
+ }
+ if (arg[off] == ',') /* another one follows */
+ ++off;
+ }
+ if (error)
+ break;
+ if (*key == 'T')
+ {
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_TERM))
+ {
+ if (!init)
+ HL_TABLE()[idx].sg_set |= SG_TERM;
+ HL_TABLE()[idx].sg_term = attr;
+ }
+ }
+ else if (*key == 'C')
+ {
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM))
+ {
+ if (!init)
+ HL_TABLE()[idx].sg_set |= SG_CTERM;
+ HL_TABLE()[idx].sg_cterm = attr;
+ HL_TABLE()[idx].sg_cterm_bold = FALSE;
+ }
+ }
+#ifdef FEAT_GUI
+ else
+ {
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
+ {
+ if (!init)
+ HL_TABLE()[idx].sg_set |= SG_GUI;
+ HL_TABLE()[idx].sg_gui = attr;
+ }
+ }
+#endif
+ }
+ else if (STRCMP(key, "FONT") == 0)
+ {
+ /* in non-GUI fonts are simply ignored */
+#ifdef FEAT_GUI
+ if (!gui.shell_created)
+ {
+ /* GUI not started yet, always accept the name. */
+ vim_free(HL_TABLE()[idx].sg_font_name);
+ HL_TABLE()[idx].sg_font_name = vim_strsave(arg);
+ }
+ else
+ {
+ GuiFont temp_sg_font = HL_TABLE()[idx].sg_font;
+# ifdef FEAT_XFONTSET
+ GuiFontset temp_sg_fontset = HL_TABLE()[idx].sg_fontset;
+# endif
+ /* First, save the current font/fontset.
+ * Then try to allocate the font/fontset.
+ * If the allocation fails, HL_TABLE()[idx].sg_font OR
+ * sg_fontset will be set to NOFONT or NOFONTSET respectively.
+ */
+
+ HL_TABLE()[idx].sg_font = NOFONT;
+# ifdef FEAT_XFONTSET
+ HL_TABLE()[idx].sg_fontset = NOFONTSET;
+# endif
+ hl_do_font(idx, arg, is_normal_group, is_menu_group,
+ is_tooltip_group);
+
+# ifdef FEAT_XFONTSET
+ if (HL_TABLE()[idx].sg_fontset != NOFONTSET)
+ {
+ /* New fontset was accepted. Free the old one, if there was
+ * one.
+ */
+ gui_mch_free_fontset(temp_sg_fontset);
+ vim_free(HL_TABLE()[idx].sg_font_name);
+ HL_TABLE()[idx].sg_font_name = vim_strsave(arg);
+ }
+ else
+ HL_TABLE()[idx].sg_fontset = temp_sg_fontset;
+# endif
+ if (HL_TABLE()[idx].sg_font != NOFONT)
+ {
+ /* New font was accepted. Free the old one, if there was
+ * one.
+ */
+ gui_mch_free_font(temp_sg_font);
+ vim_free(HL_TABLE()[idx].sg_font_name);
+ HL_TABLE()[idx].sg_font_name = vim_strsave(arg);
+ }
+ else
+ HL_TABLE()[idx].sg_font = temp_sg_font;
+ }
+#endif
+ }
+ else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0)
+ {
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM))
+ {
+ if (!init)
+ HL_TABLE()[idx].sg_set |= SG_CTERM;
+
+ /* When setting the foreground color, and previously the "bold"
+ * flag was set for a light color, reset it now */
+ if (key[5] == 'F' && HL_TABLE()[idx].sg_cterm_bold)
+ {
+ HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
+ HL_TABLE()[idx].sg_cterm_bold = FALSE;
+ }
+
+ if (VIM_ISDIGIT(*arg))
+ color = atoi((char *)arg);
+ else if (STRICMP(arg, "fg") == 0)
+ {
+ if (cterm_normal_fg_color)
+ color = cterm_normal_fg_color - 1;
+ else
+ {
+ EMSG(_("E419: FG color unknown"));
+ error = TRUE;
+ break;
+ }
+ }
+ else if (STRICMP(arg, "bg") == 0)
+ {
+ if (cterm_normal_bg_color > 0)
+ color = cterm_normal_bg_color - 1;
+ else
+ {
+ EMSG(_("E420: BG color unknown"));
+ error = TRUE;
+ break;
+ }
+ }
+ else
+ {
+ static char *(color_names[28]) = {
+ "Black", "DarkBlue", "DarkGreen", "DarkCyan",
+ "DarkRed", "DarkMagenta", "Brown", "DarkYellow",
+ "Gray", "Grey",
+ "LightGray", "LightGrey", "DarkGray", "DarkGrey",
+ "Blue", "LightBlue", "Green", "LightGreen",
+ "Cyan", "LightCyan", "Red", "LightRed", "Magenta",
+ "LightMagenta", "Yellow", "LightYellow", "White", "NONE"};
+ static int color_numbers_16[28] = {0, 1, 2, 3,
+ 4, 5, 6, 6,
+ 7, 7,
+ 7, 7, 8, 8,
+ 9, 9, 10, 10,
+ 11, 11, 12, 12, 13,
+ 13, 14, 14, 15, -1};
+ /* for xterm with 88 colors... */
+ static int color_numbers_88[28] = {0, 4, 2, 6,
+ 1, 5, 32, 72,
+ 84, 84,
+ 7, 7, 82, 82,
+ 12, 43, 10, 61,
+ 14, 63, 9, 74, 13,
+ 75, 11, 78, 15, -1};
+ /* for xterm with 256 colors... */
+ static int color_numbers_256[28] = {0, 4, 2, 6,
+ 1, 5, 130, 130,
+ 248, 248,
+ 7, 7, 242, 242,
+ 12, 81, 10, 121,
+ 14, 159, 9, 224, 13,
+ 225, 11, 229, 15, -1};
+ /* for terminals with less than 16 colors... */
+ static int color_numbers_8[28] = {0, 4, 2, 6,
+ 1, 5, 3, 3,
+ 7, 7,
+ 7, 7, 0+8, 0+8,
+ 4+8, 4+8, 2+8, 2+8,
+ 6+8, 6+8, 1+8, 1+8, 5+8,
+ 5+8, 3+8, 3+8, 7+8, -1};
+#if defined(__QNXNTO__)
+ static int *color_numbers_8_qansi = color_numbers_8;
+ /* On qnx, the 8 & 16 color arrays are the same */
+ if (STRNCMP(T_NAME, "qansi", 5) == 0)
+ color_numbers_8_qansi = color_numbers_16;
+#endif
+
+ /* reduce calls to STRICMP a bit, it can be slow */
+ off = TOUPPER_ASC(*arg);
+ for (i = (sizeof(color_names) / sizeof(char *)); --i >= 0; )
+ if (off == color_names[i][0]
+ && STRICMP(arg + 1, color_names[i] + 1) == 0)
+ break;
+ if (i < 0)
+ {
+ EMSG2(_("E421: Color name or number not recognized: %s"), key_start);
+ error = TRUE;
+ break;
+ }
+
+ /* Use the _16 table to check if its a valid color name. */
+ color = color_numbers_16[i];
+ if (color >= 0)
+ {
+ if (t_colors == 8)
+ {
+ /* t_Co is 8: use the 8 colors table */
+#if defined(__QNXNTO__)
+ color = color_numbers_8_qansi[i];
+#else
+ color = color_numbers_8[i];
+#endif
+ if (key[5] == 'F')
+ {
+ /* set/reset bold attribute to get light foreground
+ * colors (on some terminals, e.g. "linux") */
+ if (color & 8)
+ {
+ HL_TABLE()[idx].sg_cterm |= HL_BOLD;
+ HL_TABLE()[idx].sg_cterm_bold = TRUE;
+ }
+ else
+ HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
+ }
+ color &= 7; /* truncate to 8 colors */
+ }
+ else if (t_colors == 16 || t_colors == 88
+ || t_colors == 256)
+ {
+ /*
+ * Guess: if the termcap entry ends in 'm', it is
+ * probably an xterm-like terminal. Use the changed
+ * order for colors.
+ */
+ if (*T_CAF != NUL)
+ p = T_CAF;
+ else
+ p = T_CSF;
+ if (*p != NUL && *(p + STRLEN(p) - 1) == 'm')
+ switch (t_colors)
+ {
+ case 16:
+ color = color_numbers_8[i];
+ break;
+ case 88:
+ color = color_numbers_88[i];
+ break;
+ case 256:
+ color = color_numbers_256[i];
+ break;
+ }
+ }
+ }
+ }
+ /* Add one to the argument, to avoid zero */
+ if (key[5] == 'F')
+ {
+ HL_TABLE()[idx].sg_cterm_fg = color + 1;
+ if (is_normal_group)
+ {
+ cterm_normal_fg_color = color + 1;
+ cterm_normal_fg_bold = (HL_TABLE()[idx].sg_cterm & HL_BOLD);
+#ifdef FEAT_GUI
+ /* Don't do this if the GUI is used. */
+ if (!gui.in_use && !gui.starting)
+#endif
+ {
+ must_redraw = CLEAR;
+ if (termcap_active)
+ term_fg_color(color);
+ }
+ }
+ }
+ else
+ {
+ HL_TABLE()[idx].sg_cterm_bg = color + 1;
+ if (is_normal_group)
+ {
+ cterm_normal_bg_color = color + 1;
+#ifdef FEAT_GUI
+ /* Don't mess with 'background' if the GUI is used. */
+ if (!gui.in_use && !gui.starting)
+#endif
+ {
+ must_redraw = CLEAR;
+ if (termcap_active)
+ term_bg_color(color);
+ if (t_colors < 16)
+ i = (color == 0 || color == 4);
+ else
+ i = (color < 7 || color == 8);
+ /* Set the 'background' option if the value is wrong. */
+ if (i != (*p_bg == 'd'))
+ set_option_value((char_u *)"bg", 0L,
+ i ? (char_u *)"dark" : (char_u *)"light", 0);
+ }
+ }
+ }
+ }
+ }
+ else if (STRCMP(key, "GUIFG") == 0)
+ {
+#ifdef FEAT_GUI /* in non-GUI guifg colors are simply ignored */
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
+ {
+ if (!init)
+ HL_TABLE()[idx].sg_set |= SG_GUI;
+
+ i = color_name2handle(arg);
+ if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !gui.in_use)
+ {
+ HL_TABLE()[idx].sg_gui_fg = i;
+ vim_free(HL_TABLE()[idx].sg_gui_fg_name);
+ if (STRCMP(arg, "NONE"))
+ HL_TABLE()[idx].sg_gui_fg_name = vim_strsave(arg);
+ else
+ HL_TABLE()[idx].sg_gui_fg_name = NULL;
+# ifdef FEAT_GUI_X11
+ if (is_menu_group)
+ gui.menu_fg_pixel = i;
+ if (is_scrollbar_group)
+ gui.scroll_fg_pixel = i;
+# ifdef FEAT_BEVAL
+ if (is_tooltip_group)
+ gui.tooltip_fg_pixel = i;
+# endif
+ do_colors = TRUE;
+# endif
+ }
+ }
+#endif
+ }
+ else if (STRCMP(key, "GUIBG") == 0)
+ {
+#ifdef FEAT_GUI /* in non-GUI guibg colors are simply ignored */
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
+ {
+ if (!init)
+ HL_TABLE()[idx].sg_set |= SG_GUI;
+
+ i = color_name2handle(arg);
+ if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !gui.in_use)
+ {
+ HL_TABLE()[idx].sg_gui_bg = i;
+ vim_free(HL_TABLE()[idx].sg_gui_bg_name);
+ if (STRCMP(arg, "NONE"))
+ HL_TABLE()[idx].sg_gui_bg_name = vim_strsave(arg);
+ else
+ HL_TABLE()[idx].sg_gui_bg_name = NULL;
+# ifdef FEAT_GUI_X11
+ if (is_menu_group)
+ gui.menu_bg_pixel = i;
+ if (is_scrollbar_group)
+ gui.scroll_bg_pixel = i;
+# ifdef FEAT_BEVAL
+ if (is_tooltip_group)
+ gui.tooltip_bg_pixel = i;
+# endif
+ do_colors = TRUE;
+# endif
+ }
+ }
+#endif
+ }
+ else if (STRCMP(key, "START") == 0 || STRCMP(key, "STOP") == 0)
+ {
+ char_u buf[100];
+ char_u *tname;
+
+ if (!init)
+ HL_TABLE()[idx].sg_set |= SG_TERM;
+
+ /*
+ * The "start" and "stop" arguments can be a literal escape
+ * sequence, or a comma seperated list of terminal codes.
+ */
+ if (STRNCMP(arg, "t_", 2) == 0)
+ {
+ off = 0;
+ buf[0] = 0;
+ while (arg[off] != NUL)
+ {
+ /* Isolate one termcap name */
+ for (len = 0; arg[off + len] &&
+ arg[off + len] != ','; ++len)
+ ;
+ tname = vim_strnsave(arg + off, len);
+ if (tname == NULL) /* out of memory */
+ {
+ error = TRUE;
+ break;
+ }
+ /* lookup the escape sequence for the item */
+ p = get_term_code(tname);
+ vim_free(tname);
+ if (p == NULL) /* ignore non-existing things */
+ p = (char_u *)"";
+
+ /* Append it to the already found stuff */
+ if ((int)(STRLEN(buf) + STRLEN(p)) >= 99)
+ {
+ EMSG2(_("E422: terminal code too long: %s"), arg);
+ error = TRUE;
+ break;
+ }
+ STRCAT(buf, p);
+
+ /* Advance to the next item */
+ off += len;
+ if (arg[off] == ',') /* another one follows */
+ ++off;
+ }
+ }
+ else
+ {
+ /*
+ * Copy characters from arg[] to buf[], translating <> codes.
+ */
+ for (p = arg, off = 0; off < 100 && *p; )
+ {
+ len = trans_special(&p, buf + off, FALSE);
+ if (len) /* recognized special char */
+ off += len;
+ else /* copy as normal char */
+ buf[off++] = *p++;
+ }
+ buf[off] = NUL;
+ }
+ if (error)
+ break;
+
+ if (STRCMP(buf, "NONE") == 0) /* resetting the value */
+ p = NULL;
+ else
+ p = vim_strsave(buf);
+ if (key[2] == 'A')
+ {
+ vim_free(HL_TABLE()[idx].sg_start);
+ HL_TABLE()[idx].sg_start = p;
+ }
+ else
+ {
+ vim_free(HL_TABLE()[idx].sg_stop);
+ HL_TABLE()[idx].sg_stop = p;
+ }
+ }
+ else
+ {
+ EMSG2(_("E423: Illegal argument: %s"), key_start);
+ error = TRUE;
+ break;
+ }
+
+ /*
+ * When highlighting has been given for a group, don't link it.
+ */
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK))
+ HL_TABLE()[idx].sg_link = 0;
+
+ /*
+ * Continue with next argument.
+ */
+ linep = skipwhite(linep);
+ }
+
+ /*
+ * If there is an error, and it's a new entry, remove it from the table.
+ */
+ if (error && idx == highlight_ga.ga_len)
+ syn_unadd_group();
+ else
+ {
+ if (is_normal_group)
+ {
+ HL_TABLE()[idx].sg_term_attr = 0;
+ HL_TABLE()[idx].sg_cterm_attr = 0;
+#ifdef FEAT_GUI
+ HL_TABLE()[idx].sg_gui_attr = 0;
+ /*
+ * Need to update all groups, because they might be using "bg"
+ * and/or "fg", which have been changed now.
+ */
+ if (gui.in_use)
+ highlight_gui_started();
+#endif
+ }
+#ifdef FEAT_GUI_X11
+# ifdef FEAT_MENU
+ else if (is_menu_group)
+ {
+ if (gui.in_use && do_colors)
+ gui_mch_new_menu_colors();
+ }
+# endif
+ else if (is_scrollbar_group)
+ {
+ if (gui.in_use && do_colors)
+ gui_new_scrollbar_colors();
+ }
+# ifdef FEAT_BEVAL
+ else if (is_tooltip_group)
+ {
+ if (gui.in_use && do_colors)
+ gui_mch_new_tooltip_colors();
+ }
+# endif
+#endif
+ else
+ set_hl_attr(idx);
+ redraw_all_later(NOT_VALID);
+ }
+ vim_free(key);
+ vim_free(arg);
+
+ /* Only call highlight_changed() once, after sourcing a syntax file */
+ need_highlight_changed = TRUE;
+}
+
+/*
+ * Reset the cterm colors to what they were before Vim was started, if
+ * possible. Otherwise reset them to zero.
+ */
+ void
+restore_cterm_colors()
+{
+#if defined(MSDOS) || (defined(WIN3264) && !defined(FEAT_GUI_W32))
+ /* Since t_me has been set, this probably means that the user
+ * wants to use this as default colors. Need to reset default
+ * background/foreground colors. */
+ mch_set_normal_colors();
+#else
+ cterm_normal_fg_color = 0;
+ cterm_normal_fg_bold = 0;
+ cterm_normal_bg_color = 0;
+#endif
+}
+
+/*
+ * Return TRUE if highlight group "idx" has any settings.
+ * When "check_link" is TRUE also check for an existing link.
+ */
+ static int
+hl_has_settings(idx, check_link)
+ int idx;
+ int check_link;
+{
+ return ( HL_TABLE()[idx].sg_term_attr != 0
+ || HL_TABLE()[idx].sg_cterm_attr != 0
+#ifdef FEAT_GUI
+ || HL_TABLE()[idx].sg_gui_attr != 0
+#endif
+ || (check_link && (HL_TABLE()[idx].sg_set & SG_LINK)));
+}
+
+/*
+ * Clear highlighting for one group.
+ */
+ static void
+highlight_clear(idx)
+ int idx;
+{
+ HL_TABLE()[idx].sg_term = 0;
+ vim_free(HL_TABLE()[idx].sg_start);
+ HL_TABLE()[idx].sg_start = NULL;
+ vim_free(HL_TABLE()[idx].sg_stop);
+ HL_TABLE()[idx].sg_stop = NULL;
+ HL_TABLE()[idx].sg_term_attr = 0;
+ HL_TABLE()[idx].sg_cterm = 0;
+ HL_TABLE()[idx].sg_cterm_bold = FALSE;
+ HL_TABLE()[idx].sg_cterm_fg = 0;
+ HL_TABLE()[idx].sg_cterm_bg = 0;
+ HL_TABLE()[idx].sg_cterm_attr = 0;
+#ifdef FEAT_GUI /* in non-GUI fonts are simply ignored */
+ HL_TABLE()[idx].sg_gui = 0;
+ HL_TABLE()[idx].sg_gui_fg = INVALCOLOR;
+ vim_free(HL_TABLE()[idx].sg_gui_fg_name);
+ HL_TABLE()[idx].sg_gui_fg_name = NULL;
+ HL_TABLE()[idx].sg_gui_bg = INVALCOLOR;
+ vim_free(HL_TABLE()[idx].sg_gui_bg_name);
+ HL_TABLE()[idx].sg_gui_bg_name = NULL;
+ gui_mch_free_font(HL_TABLE()[idx].sg_font);
+ HL_TABLE()[idx].sg_font = NOFONT;
+# ifdef FEAT_XFONTSET
+ gui_mch_free_fontset(HL_TABLE()[idx].sg_fontset);
+ HL_TABLE()[idx].sg_fontset = NOFONTSET;
+# endif
+ vim_free(HL_TABLE()[idx].sg_font_name);
+ HL_TABLE()[idx].sg_font_name = NULL;
+ HL_TABLE()[idx].sg_gui_attr = 0;
+#endif
+}
+
+#if defined(FEAT_GUI) || defined(PROTO)
+/*
+ * Set the normal foreground and background colors according to the "Normal"
+ * highlighighting group. For X11 also set "Menu", "Scrollbar", and
+ * "Tooltip" colors.
+ */
+ void
+set_normal_colors()
+{
+ if (set_group_colors((char_u *)"Normal",
+ &gui.norm_pixel, &gui.back_pixel, FALSE, TRUE,
+ FALSE))
+ {
+ gui_mch_new_colors();
+ must_redraw = CLEAR;
+ }
+#ifdef FEAT_GUI_X11
+ if (set_group_colors((char_u *)"Menu",
+ &gui.menu_fg_pixel, &gui.menu_bg_pixel, TRUE, FALSE,
+ FALSE))
+ {
+# ifdef FEAT_MENU
+ gui_mch_new_menu_colors();
+# endif
+ must_redraw = CLEAR;
+ }
+# ifdef FEAT_BEVAL
+ if (set_group_colors((char_u *)"Tooltip",
+ &gui.tooltip_fg_pixel, &gui.tooltip_bg_pixel,
+ FALSE, FALSE, TRUE))
+ {
+# ifdef FEAT_TOOLBAR
+ gui_mch_new_tooltip_colors();
+# endif
+ must_redraw = CLEAR;
+ }
+#endif
+ if (set_group_colors((char_u *)"Scrollbar",
+ &gui.scroll_fg_pixel, &gui.scroll_bg_pixel, FALSE, FALSE,
+ FALSE))
+ {
+ gui_new_scrollbar_colors();
+ must_redraw = CLEAR;
+ }
+#endif
+}
+
+/*
+ * Set the colors for "Normal", "Menu", "Tooltip" or "Scrollbar".
+ */
+ static int
+set_group_colors(name, fgp, bgp, do_menu, use_norm, do_tooltip)
+ char_u *name;
+ guicolor_T *fgp;
+ guicolor_T *bgp;
+ int do_menu;
+ int use_norm;
+ int do_tooltip;
+{
+ int idx;
+
+ idx = syn_name2id(name) - 1;
+ if (idx >= 0)
+ {
+ gui_do_one_color(idx, do_menu, do_tooltip);
+
+ if (HL_TABLE()[idx].sg_gui_fg != INVALCOLOR)
+ *fgp = HL_TABLE()[idx].sg_gui_fg;
+ else if (use_norm)
+ *fgp = gui.def_norm_pixel;
+ if (HL_TABLE()[idx].sg_gui_bg != INVALCOLOR)
+ *bgp = HL_TABLE()[idx].sg_gui_bg;
+ else if (use_norm)
+ *bgp = gui.def_back_pixel;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Get the font of the "Normal" group.
+ * Returns "" when it's not found or not set.
+ */
+ char_u *
+hl_get_font_name()
+{
+ int id;
+ char_u *s;
+
+ id = syn_name2id((char_u *)"Normal");
+ if (id > 0)
+ {
+ s = HL_TABLE()[id - 1].sg_font_name;
+ if (s != NULL)
+ return s;
+ }
+ return (char_u *)"";
+}
+
+/*
+ * Set font for "Normal" group. Called by gui_mch_init_font() when a font has
+ * actually chosen to be used.
+ */
+ void
+hl_set_font_name(font_name)
+ char_u *font_name;
+{
+ int id;
+
+ id = syn_name2id((char_u *)"Normal");
+ if (id > 0)
+ {
+ vim_free(HL_TABLE()[id - 1].sg_font_name);
+ HL_TABLE()[id - 1].sg_font_name = vim_strsave(font_name);
+ }
+}
+
+/*
+ * Set background color for "Normal" group. Called by gui_set_bg_color()
+ * when the color is known.
+ */
+ void
+hl_set_bg_color_name(name)
+ char_u *name; /* must have been allocated */
+{
+ int id;
+
+ if (name != NULL)
+ {
+ id = syn_name2id((char_u *)"Normal");
+ if (id > 0)
+ {
+ vim_free(HL_TABLE()[id - 1].sg_gui_bg_name);
+ HL_TABLE()[id - 1].sg_gui_bg_name = name;
+ }
+ }
+}
+
+/*
+ * Set foreground color for "Normal" group. Called by gui_set_fg_color()
+ * when the color is known.
+ */
+ void
+hl_set_fg_color_name(name)
+ char_u *name; /* must have been allocated */
+{
+ int id;
+
+ if (name != NULL)
+ {
+ id = syn_name2id((char_u *)"Normal");
+ if (id > 0)
+ {
+ vim_free(HL_TABLE()[id - 1].sg_gui_fg_name);
+ HL_TABLE()[id - 1].sg_gui_fg_name = name;
+ }
+ }
+}
+
+/*
+ * Return the handle for a color name.
+ * Returns INVALCOLOR when failed.
+ */
+ static guicolor_T
+color_name2handle(name)
+ char_u *name;
+{
+ if (STRCMP(name, "NONE") == 0)
+ return INVALCOLOR;
+
+ if (STRICMP(name, "fg") == 0 || STRICMP(name, "foreground") == 0)
+ return gui.norm_pixel;
+ if (STRICMP(name, "bg") == 0 || STRICMP(name, "background") == 0)
+ return gui.back_pixel;
+
+ return gui_get_color(name);
+}
+
+/*
+ * Return the handle for a font name.
+ * Returns NOFONT when failed.
+ */
+ static GuiFont
+font_name2handle(name)
+ char_u *name;
+{
+ if (STRCMP(name, "NONE") == 0)
+ return NOFONT;
+
+ return gui_mch_get_font(name, TRUE);
+}
+
+# ifdef FEAT_XFONTSET
+/*
+ * Return the handle for a fontset name.
+ * Returns NOFONTSET when failed.
+ */
+ static GuiFontset
+fontset_name2handle(name, fixed_width)
+ char_u *name;
+ int fixed_width;
+{
+ if (STRCMP(name, "NONE") == 0)
+ return NOFONTSET;
+
+ return gui_mch_get_fontset(name, TRUE, fixed_width);
+}
+# endif
+
+/*
+ * Get the font or fontset for one highlight group.
+ */
+/*ARGSUSED*/
+ static void
+hl_do_font(idx, arg, do_normal, do_menu, do_tooltip)
+ int idx;
+ char_u *arg;
+ int do_normal; /* set normal font */
+ int do_menu; /* set menu font */
+ int do_tooltip; /* set tooltip font */
+{
+# ifdef FEAT_XFONTSET
+ /* If 'guifontset' is not empty, first try using the name as a
+ * fontset. If that doesn't work, use it as a font name. */
+ if (*p_guifontset != NUL
+# ifdef FONTSET_ALWAYS
+ || do_menu
+# endif
+# ifdef FEAT_BEVAL_TIP
+ /* In Athena & Motif, the Tooltip highlight group is always a fontset */
+ || do_tooltip
+# endif
+ )
+ HL_TABLE()[idx].sg_fontset = fontset_name2handle(arg, 0
+# ifdef FONTSET_ALWAYS
+ || do_menu
+# endif
+# ifdef FEAT_BEVAL_TIP
+ || do_tooltip
+# endif
+ );
+ if (HL_TABLE()[idx].sg_fontset != NOFONTSET)
+ {
+ /* If it worked and it's the Normal group, use it as the
+ * normal fontset. Same for the Menu group. */
+ if (do_normal)
+ gui_init_font(arg, TRUE);
+# if (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) && defined(FEAT_MENU)
+ if (do_menu)
+ {
+# ifdef FONTSET_ALWAYS
+ gui.menu_fontset = HL_TABLE()[idx].sg_fontset;
+# else
+ /* YIKES! This is a bug waiting to crash the program */
+ gui.menu_font = HL_TABLE()[idx].sg_fontset;
+# endif
+ gui_mch_new_menu_font();
+ }
+# ifdef FEAT_BEVAL
+ if (do_tooltip)
+ {
+ /* The Athena widget set cannot currently handle switching between
+ * displaying a single font and a fontset.
+ * If the XtNinternational resource is set to True at widget
+ * creation, then a fontset is always used, othwise an
+ * XFontStruct is used.
+ */
+ gui.tooltip_fontset = (XFontSet)HL_TABLE()[idx].sg_fontset;
+ gui_mch_new_tooltip_font();
+ }
+# endif
+# endif
+ }
+ else
+# endif
+ {
+ HL_TABLE()[idx].sg_font = font_name2handle(arg);
+ /* If it worked and it's the Normal group, use it as the
+ * normal font. Same for the Menu group. */
+ if (HL_TABLE()[idx].sg_font != NOFONT)
+ {
+ if (do_normal)
+ gui_init_font(arg, FALSE);
+#ifndef FONTSET_ALWAYS
+# if (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) && defined(FEAT_MENU)
+ if (do_menu)
+ {
+ gui.menu_font = HL_TABLE()[idx].sg_font;
+ gui_mch_new_menu_font();
+ }
+# endif
+#endif
+ }
+ }
+}
+
+#endif /* FEAT_GUI */
+
+/*
+ * Table with the specifications for an attribute number.
+ * Note that this table is used by ALL buffers. This is required because the
+ * GUI can redraw at any time for any buffer.
+ */
+garray_T term_attr_table = {0, 0, 0, 0, NULL};
+
+#define TERM_ATTR_ENTRY(idx) ((attrentry_T *)term_attr_table.ga_data)[idx]
+
+garray_T cterm_attr_table = {0, 0, 0, 0, NULL};
+
+#define CTERM_ATTR_ENTRY(idx) ((attrentry_T *)cterm_attr_table.ga_data)[idx]
+
+#ifdef FEAT_GUI
+garray_T gui_attr_table = {0, 0, 0, 0, NULL};
+
+#define GUI_ATTR_ENTRY(idx) ((attrentry_T *)gui_attr_table.ga_data)[idx]
+#endif
+
+/*
+ * Return the attr number for a set of colors and font.
+ * Add a new entry to the term_attr_table, cterm_attr_table or gui_attr_table
+ * if the combination is new.
+ * Return 0 for error (no more room).
+ */
+ static int
+get_attr_entry(table, aep)
+ garray_T *table;
+ attrentry_T *aep;
+{
+ int i;
+ attrentry_T *gap;
+ static int recursive = FALSE;
+
+ /*
+ * Init the table, in case it wasn't done yet.
+ */
+ table->ga_itemsize = sizeof(attrentry_T);
+ table->ga_growsize = 7;
+
+ /*
+ * Try to find an entry with the same specifications.
+ */
+ for (i = 0; i < table->ga_len; ++i)
+ {
+ gap = &(((attrentry_T *)table->ga_data)[i]);
+ if ( aep->ae_attr == gap->ae_attr
+ && (
+#ifdef FEAT_GUI
+ (table == &gui_attr_table
+ && (aep->ae_u.gui.fg_color == gap->ae_u.gui.fg_color
+ && aep->ae_u.gui.bg_color == gap->ae_u.gui.bg_color
+ && aep->ae_u.gui.font == gap->ae_u.gui.font
+# ifdef FEAT_XFONTSET
+ && aep->ae_u.gui.fontset == gap->ae_u.gui.fontset
+# endif
+ ))
+ ||
+#endif
+ (table == &term_attr_table
+ && (aep->ae_u.term.start == NULL) ==
+ (gap->ae_u.term.start == NULL)
+ && (aep->ae_u.term.start == NULL
+ || STRCMP(aep->ae_u.term.start,
+ gap->ae_u.term.start) == 0)
+ && (aep->ae_u.term.stop == NULL) ==
+ (gap->ae_u.term.stop == NULL)
+ && (aep->ae_u.term.stop == NULL
+ || STRCMP(aep->ae_u.term.stop,
+ gap->ae_u.term.stop) == 0))
+ || (table == &cterm_attr_table
+ && aep->ae_u.cterm.fg_color == gap->ae_u.cterm.fg_color
+ && aep->ae_u.cterm.bg_color == gap->ae_u.cterm.bg_color)
+ ))
+
+ return i + ATTR_OFF;
+ }
+
+ if (table->ga_len + ATTR_OFF == 256)
+ {
+ /*
+ * Running out of attribute entries! remove all attributes, and
+ * compute new ones for all groups.
+ * When called recursively, we are really out of numbers.
+ */
+ if (recursive)
+ {
+ EMSG(_("E424: Too many different highlighting attributes in use"));
+ return 0;
+ }
+ recursive = TRUE;
+
+#ifdef FEAT_GUI
+ ga_clear(&gui_attr_table);
+#endif
+ ga_clear(&term_attr_table);
+ ga_clear(&cterm_attr_table);
+ must_redraw = CLEAR;
+
+ for (i = 0; i < highlight_ga.ga_len; ++i)
+ set_hl_attr(i);
+
+ recursive = FALSE;
+ }
+
+ /*
+ * This is a new combination of colors and font, add an entry.
+ */
+ if (ga_grow(table, 1) == FAIL)
+ return 0;
+
+ gap = &(((attrentry_T *)table->ga_data)[table->ga_len]);
+ vim_memset(gap, 0, sizeof(attrentry_T));
+ gap->ae_attr = aep->ae_attr;
+#ifdef FEAT_GUI
+ if (table == &gui_attr_table)
+ {
+ gap->ae_u.gui.fg_color = aep->ae_u.gui.fg_color;
+ gap->ae_u.gui.bg_color = aep->ae_u.gui.bg_color;
+ gap->ae_u.gui.font = aep->ae_u.gui.font;
+# ifdef FEAT_XFONTSET
+ gap->ae_u.gui.fontset = aep->ae_u.gui.fontset;
+# endif
+ }
+#endif
+ if (table == &term_attr_table)
+ {
+ if (aep->ae_u.term.start == NULL)
+ gap->ae_u.term.start = NULL;
+ else
+ gap->ae_u.term.start = vim_strsave(aep->ae_u.term.start);
+ if (aep->ae_u.term.stop == NULL)
+ gap->ae_u.term.stop = NULL;
+ else
+ gap->ae_u.term.stop = vim_strsave(aep->ae_u.term.stop);
+ }
+ else if (table == &cterm_attr_table)
+ {
+ gap->ae_u.cterm.fg_color = aep->ae_u.cterm.fg_color;
+ gap->ae_u.cterm.bg_color = aep->ae_u.cterm.bg_color;
+ }
+ ++table->ga_len;
+ --table->ga_room;
+ return (table->ga_len - 1 + ATTR_OFF);
+}
+
+#ifdef FEAT_GUI
+
+ attrentry_T *
+syn_gui_attr2entry(attr)
+ int attr;
+{
+ attr -= ATTR_OFF;
+ if (attr >= gui_attr_table.ga_len) /* did ":syntax clear" */
+ return NULL;
+ return &(GUI_ATTR_ENTRY(attr));
+}
+
+#endif /* FEAT_GUI */
+
+ attrentry_T *
+syn_term_attr2entry(attr)
+ int attr;
+{
+ attr -= ATTR_OFF;
+ if (attr >= term_attr_table.ga_len) /* did ":syntax clear" */
+ return NULL;
+ return &(TERM_ATTR_ENTRY(attr));
+}
+
+ attrentry_T *
+syn_cterm_attr2entry(attr)
+ int attr;
+{
+ attr -= ATTR_OFF;
+ if (attr >= cterm_attr_table.ga_len) /* did ":syntax clear" */
+ return NULL;
+ return &(CTERM_ATTR_ENTRY(attr));
+}
+
+#define LIST_ATTR 1
+#define LIST_STRING 2
+#define LIST_INT 3
+
+ static void
+highlight_list_one(id)
+ int id;
+{
+ struct hl_group *sgp;
+ int didh = FALSE;
+
+ sgp = &HL_TABLE()[id - 1]; /* index is ID minus one */
+
+ didh = highlight_list_arg(id, didh, LIST_ATTR,
+ sgp->sg_term, NULL, "term");
+ didh = highlight_list_arg(id, didh, LIST_STRING,
+ 0, sgp->sg_start, "start");
+ didh = highlight_list_arg(id, didh, LIST_STRING,
+ 0, sgp->sg_stop, "stop");
+
+ didh = highlight_list_arg(id, didh, LIST_ATTR,
+ sgp->sg_cterm, NULL, "cterm");
+ didh = highlight_list_arg(id, didh, LIST_INT,
+ sgp->sg_cterm_fg, NULL, "ctermfg");
+ didh = highlight_list_arg(id, didh, LIST_INT,
+ sgp->sg_cterm_bg, NULL, "ctermbg");
+
+#ifdef FEAT_GUI
+ didh = highlight_list_arg(id, didh, LIST_ATTR,
+ sgp->sg_gui, NULL, "gui");
+ didh = highlight_list_arg(id, didh, LIST_STRING,
+ 0, sgp->sg_gui_fg_name, "guifg");
+ didh = highlight_list_arg(id, didh, LIST_STRING,
+ 0, sgp->sg_gui_bg_name, "guibg");
+ didh = highlight_list_arg(id, didh, LIST_STRING,
+ 0, sgp->sg_font_name, "font");
+#endif
+
+ if (sgp->sg_link)
+ {
+ (void)syn_list_header(didh, 9999, id);
+ msg_puts_attr((char_u *)"links to", hl_attr(HLF_D));
+ msg_putchar(' ');
+ msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
+ }
+}
+
+ static int
+highlight_list_arg(id, didh, type, iarg, sarg, name)
+ int id;
+ int didh;
+ int type;
+ int iarg;
+ char_u *sarg;
+ char *name;
+{
+ char_u buf[100];
+ char_u *ts;
+ int i;
+
+ if (type == LIST_STRING ? (sarg != NULL) : (iarg != 0))
+ {
+ ts = buf;
+ if (type == LIST_INT)
+ sprintf((char *)buf, "%d", iarg - 1);
+ else if (type == LIST_STRING)
+ ts = sarg;
+ else /* type == LIST_ATTR */
+ {
+ buf[0] = NUL;
+ for (i = 0; hl_attr_table[i] != 0; ++i)
+ {
+ if (iarg & hl_attr_table[i])
+ {
+ if (buf[0] != NUL)
+ STRCAT(buf, ",");
+ STRCAT(buf, hl_name_table[i]);
+ iarg &= ~hl_attr_table[i]; /* don't want "inverse" */
+ }
+ }
+ }
+
+ (void)syn_list_header(didh,
+ (int)(vim_strsize(ts) + STRLEN(name) + 1), id);
+ didh = TRUE;
+
+ MSG_PUTS_ATTR(name, hl_attr(HLF_D));
+ MSG_PUTS_ATTR("=", hl_attr(HLF_D));
+ msg_outtrans(ts);
+ }
+ return didh;
+}
+
+#if (((defined(FEAT_EVAL) || defined(FEAT_PRINTER))) && defined(FEAT_SYN_HL)) || defined(PROTO)
+/*
+ * Return "1" if highlight group "id" has attribute "flag".
+ * Return NULL otherwise.
+ */
+ char_u *
+highlight_has_attr(id, flag, modec)
+ int id;
+ int flag;
+ int modec; /* 'g' for GUI, 'c' for cterm, 't' for term */
+{
+ int attr;
+
+ if (id <= 0 || id > highlight_ga.ga_len)
+ return NULL;
+
+#ifdef FEAT_GUI
+ if (modec == 'g')
+ attr = HL_TABLE()[id - 1].sg_gui;
+ else
+#endif
+ if (modec == 'c')
+ attr = HL_TABLE()[id - 1].sg_cterm;
+ else
+ attr = HL_TABLE()[id - 1].sg_term;
+
+ if (attr & flag)
+ return (char_u *)"1";
+ return NULL;
+}
+#endif
+
+#if (defined(FEAT_SYN_HL) && defined(FEAT_EVAL)) || defined(PROTO)
+/*
+ * Return color name of highlight group "id".
+ */
+ char_u *
+highlight_color(id, what, modec)
+ int id;
+ char_u *what; /* "fg", "bg", "fg#" or "bg#" */
+ int modec; /* 'g' for GUI, 'c' for cterm, 't' for term */
+{
+ static char_u name[20];
+ int n;
+ int fg;
+
+ if (id <= 0 || id > highlight_ga.ga_len)
+ return NULL;
+
+ if (TOLOWER_ASC(what[0]) == 'f')
+ fg = TRUE;
+ else
+ fg = FALSE;
+#ifdef FEAT_GUI
+ if (modec == 'g')
+ {
+ /* return #RRGGBB form (only possible when GUI is running) */
+ if (gui.in_use && what[1] && what[2] == '#')
+ {
+ guicolor_T color;
+ long_u rgb;
+ static char_u buf[10];
+
+ if (fg)
+ color = HL_TABLE()[id - 1].sg_gui_fg;
+ else
+ color = HL_TABLE()[id - 1].sg_gui_bg;
+ if (color == INVALCOLOR)
+ return NULL;
+ rgb = gui_mch_get_rgb(color);
+ sprintf((char *)buf, "#%02x%02x%02x",
+ (unsigned)(rgb >> 16),
+ (unsigned)(rgb >> 8) & 255,
+ (unsigned)rgb & 255);
+ return buf;
+ }
+ if (fg)
+ return (HL_TABLE()[id - 1].sg_gui_fg_name);
+ return (HL_TABLE()[id - 1].sg_gui_bg_name);
+ }
+#endif
+ if (modec == 'c')
+ {
+ if (fg)
+ n = HL_TABLE()[id - 1].sg_cterm_fg - 1;
+ else
+ n = HL_TABLE()[id - 1].sg_cterm_bg - 1;
+ sprintf((char *)name, "%d", n);
+ return name;
+ }
+ /* term doesn't have color */
+ return NULL;
+}
+#endif
+
+#if (defined(FEAT_SYN_HL) && defined(FEAT_GUI) && defined(FEAT_PRINTER)) \
+ || defined(PROTO)
+/*
+ * Return color name of highlight group "id" as RGB value.
+ */
+ long_u
+highlight_gui_color_rgb(id, fg)
+ int id;
+ int fg; /* TRUE = fg, FALSE = bg */
+{
+ guicolor_T color;
+
+ if (id <= 0 || id > highlight_ga.ga_len)
+ return 0L;
+
+ if (fg)
+ color = HL_TABLE()[id - 1].sg_gui_fg;
+ else
+ color = HL_TABLE()[id - 1].sg_gui_bg;
+
+ if (color == INVALCOLOR)
+ return 0L;
+
+ return gui_mch_get_rgb(color);
+}
+#endif
+
+/*
+ * Output the syntax list header.
+ * Return TRUE when started a new line.
+ */
+ static int
+syn_list_header(did_header, outlen, id)
+ int did_header; /* did header already */
+ int outlen; /* length of string that comes */
+ int id; /* highlight group id */
+{
+ int endcol = 19;
+ int newline = TRUE;
+
+ if (!did_header)
+ {
+ msg_putchar('\n');
+ msg_outtrans(HL_TABLE()[id - 1].sg_name);
+ endcol = 15;
+ }
+ else if (msg_col + outlen + 1 >= Columns)
+ msg_putchar('\n');
+ else
+ {
+ if (msg_col >= endcol) /* wrap around is like starting a new line */
+ newline = FALSE;
+ }
+
+ if (msg_col >= endcol) /* output at least one space */
+ endcol = msg_col + 1;
+ if (Columns <= endcol) /* avoid hang for tiny window */
+ endcol = Columns - 1;
+
+ msg_advance(endcol);
+
+ /* Show "xxx" with the attributes. */
+ if (!did_header)
+ {
+ msg_puts_attr((char_u *)"xxx", syn_id2attr(id));
+ msg_putchar(' ');
+ }
+
+ return newline;
+}
+
+/*
+ * Set the attribute numbers for a highlight group.
+ * Called after one of the attributes has changed.
+ */
+ static void
+set_hl_attr(idx)
+ int idx; /* index in array */
+{
+ attrentry_T at_en;
+ struct hl_group *sgp = HL_TABLE() + idx;
+
+ /* The "Normal" group doesn't need an attribute number */
+ if (sgp->sg_name_u != NULL && STRCMP(sgp->sg_name_u, "NORMAL") == 0)
+ return;
+
+#ifdef FEAT_GUI
+ /*
+ * For the GUI mode: If there are other than "normal" highlighting
+ * attributes, need to allocate an attr number.
+ */
+ if (sgp->sg_gui_fg == INVALCOLOR
+ && sgp->sg_gui_bg == INVALCOLOR
+ && sgp->sg_font == NOFONT
+# ifdef FEAT_XFONTSET
+ && sgp->sg_fontset == NOFONTSET
+# endif
+ )
+ {
+ sgp->sg_gui_attr = sgp->sg_gui;
+ }
+ else
+ {
+ at_en.ae_attr = sgp->sg_gui;
+ at_en.ae_u.gui.fg_color = sgp->sg_gui_fg;
+ at_en.ae_u.gui.bg_color = sgp->sg_gui_bg;
+ at_en.ae_u.gui.font = sgp->sg_font;
+# ifdef FEAT_XFONTSET
+ at_en.ae_u.gui.fontset = sgp->sg_fontset;
+# endif
+ sgp->sg_gui_attr = get_attr_entry(&gui_attr_table, &at_en);
+ }
+#endif
+ /*
+ * For the term mode: If there are other than "normal" highlighting
+ * attributes, need to allocate an attr number.
+ */
+ if (sgp->sg_start == NULL && sgp->sg_stop == NULL)
+ sgp->sg_term_attr = sgp->sg_term;
+ else
+ {
+ at_en.ae_attr = sgp->sg_term;
+ at_en.ae_u.term.start = sgp->sg_start;
+ at_en.ae_u.term.stop = sgp->sg_stop;
+ sgp->sg_term_attr = get_attr_entry(&term_attr_table, &at_en);
+ }
+
+ /*
+ * For the color term mode: If there are other than "normal"
+ * highlighting attributes, need to allocate an attr number.
+ */
+ if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0)
+ sgp->sg_cterm_attr = sgp->sg_cterm;
+ else
+ {
+ at_en.ae_attr = sgp->sg_cterm;
+ at_en.ae_u.cterm.fg_color = sgp->sg_cterm_fg;
+ at_en.ae_u.cterm.bg_color = sgp->sg_cterm_bg;
+ sgp->sg_cterm_attr = get_attr_entry(&cterm_attr_table, &at_en);
+ }
+}
+
+/*
+ * Lookup a highlight group name and return it's ID.
+ * If it is not found, 0 is returned.
+ */
+ int
+syn_name2id(name)
+ char_u *name;
+{
+ int i;
+ char_u name_u[200];
+
+ /* Avoid using stricmp() too much, it's slow on some systems */
+ /* Avoid alloc()/free(), these are slow too. ID names over 200 chars
+ * don't deserve to be found! */
+ STRNCPY(name_u, name, 199);
+ name_u[199] = NUL;
+ vim_strup(name_u);
+ for (i = highlight_ga.ga_len; --i >= 0; )
+ if (HL_TABLE()[i].sg_name_u != NULL
+ && STRCMP(name_u, HL_TABLE()[i].sg_name_u) == 0)
+ break;
+ return i + 1;
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return TRUE if highlight group "name" exists.
+ */
+ int
+highlight_exists(name)
+ char_u *name;
+{
+ return (syn_name2id(name) > 0);
+}
+#endif
+
+/*
+ * Like syn_name2id(), but take a pointer + length argument.
+ */
+ int
+syn_namen2id(linep, len)
+ char_u *linep;
+ int len;
+{
+ char_u *name;
+ int id = 0;
+
+ name = vim_strnsave(linep, len);
+ if (name != NULL)
+ {
+ id = syn_name2id(name);
+ vim_free(name);
+ }
+ return id;
+}
+
+/*
+ * Find highlight group name in the table and return it's ID.
+ * The argument is a pointer to the name and the length of the name.
+ * If it doesn't exist yet, a new entry is created.
+ * Return 0 for failure.
+ */
+ int
+syn_check_group(pp, len)
+ char_u *pp;
+ int len;
+{
+ int id;
+ char_u *name;
+
+ name = vim_strnsave(pp, len);
+ if (name == NULL)
+ return 0;
+
+ id = syn_name2id(name);
+ if (id == 0) /* doesn't exist yet */
+ id = syn_add_group(name);
+ else
+ vim_free(name);
+ return id;
+}
+
+/*
+ * Add new highlight group and return it's ID.
+ * "name" must be an allocated string, it will be consumed.
+ * Return 0 for failure.
+ */
+ static int
+syn_add_group(name)
+ char_u *name;
+{
+ char_u *p;
+
+ /* Check that the name is ASCII letters, digits and underscore. */
+ for (p = name; *p != NUL; ++p)
+ {
+ if (!vim_isprintc(*p))
+ {
+ EMSG(_("E669: Unprintable character in group name"));
+ return 0;
+ }
+ else if (!ASCII_ISALNUM(*p) && *p != '_')
+ {
+ /* This is an error, but since there previously was no check only
+ * give a warning. */
+ MSG(_("W18: Invalid character in group name"));
+ break;
+ }
+ }
+
+ /*
+ * First call for this growarray: init growing array.
+ */
+ if (highlight_ga.ga_data == NULL)
+ {
+ highlight_ga.ga_itemsize = sizeof(struct hl_group);
+ highlight_ga.ga_growsize = 10;
+ }
+
+ /*
+ * Make room for at least one other syntax_highlight entry.
+ */
+ if (ga_grow(&highlight_ga, 1) == FAIL)
+ {
+ vim_free(name);
+ return 0;
+ }
+
+ vim_memset(&(HL_TABLE()[highlight_ga.ga_len]), 0, sizeof(struct hl_group));
+ HL_TABLE()[highlight_ga.ga_len].sg_name = name;
+ HL_TABLE()[highlight_ga.ga_len].sg_name_u = vim_strsave_up(name);
+#ifdef FEAT_GUI
+ HL_TABLE()[highlight_ga.ga_len].sg_gui_bg = INVALCOLOR;
+ HL_TABLE()[highlight_ga.ga_len].sg_gui_fg = INVALCOLOR;
+#endif
+ ++highlight_ga.ga_len;
+ --highlight_ga.ga_room;
+
+ return highlight_ga.ga_len; /* ID is index plus one */
+}
+
+/*
+ * When, just after calling syn_add_group(), an error is discovered, this
+ * function deletes the new name.
+ */
+ static void
+syn_unadd_group()
+{
+ --highlight_ga.ga_len;
+ ++highlight_ga.ga_room;
+ vim_free(HL_TABLE()[highlight_ga.ga_len].sg_name);
+ vim_free(HL_TABLE()[highlight_ga.ga_len].sg_name_u);
+}
+
+/*
+ * Translate a group ID to highlight attributes.
+ */
+ int
+syn_id2attr(hl_id)
+ int hl_id;
+{
+ int attr;
+ struct hl_group *sgp;
+
+ hl_id = syn_get_final_id(hl_id);
+ sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */
+
+#ifdef FEAT_GUI
+ /*
+ * Only use GUI attr when the GUI is being used.
+ */
+ if (gui.in_use)
+ attr = sgp->sg_gui_attr;
+ else
+#endif
+ if (t_colors > 1)
+ attr = sgp->sg_cterm_attr;
+ else
+ attr = sgp->sg_term_attr;
+
+ return attr;
+}
+
+#ifdef FEAT_GUI
+/*
+ * Get the GUI colors and attributes for a group ID.
+ * NOTE: the colors will be INVALCOLOR when not set, the color otherwise.
+ */
+ int
+syn_id2colors(hl_id, fgp, bgp)
+ int hl_id;
+ guicolor_T *fgp;
+ guicolor_T *bgp;
+{
+ struct hl_group *sgp;
+
+ hl_id = syn_get_final_id(hl_id);
+ sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */
+
+ *fgp = sgp->sg_gui_fg;
+ *bgp = sgp->sg_gui_bg;
+ return sgp->sg_gui;
+}
+#endif
+
+/*
+ * Translate a group ID to the final group ID (following links).
+ */
+ int
+syn_get_final_id(hl_id)
+ int hl_id;
+{
+ int count;
+ struct hl_group *sgp;
+
+ if (hl_id > highlight_ga.ga_len || hl_id < 1)
+ return 0; /* Can be called from eval!! */
+
+ /*
+ * Follow links until there is no more.
+ * Look out for loops! Break after 100 links.
+ */
+ for (count = 100; --count >= 0; )
+ {
+ sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */
+ if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len)
+ break;
+ hl_id = sgp->sg_link;
+ }
+
+ return hl_id;
+}
+
+#ifdef FEAT_GUI
+/*
+ * Call this function just after the GUI has started.
+ * It finds the font and color handles for the highlighting groups.
+ */
+ void
+highlight_gui_started()
+{
+ int idx;
+
+ /* First get the colors from the "Normal" and "Menu" group, if set */
+ set_normal_colors();
+
+ for (idx = 0; idx < highlight_ga.ga_len; ++idx)
+ gui_do_one_color(idx, FALSE, FALSE);
+
+ highlight_changed();
+}
+
+ static void
+gui_do_one_color(idx, do_menu, do_tooltip)
+ int idx;
+ int do_menu; /* TRUE: might set the menu font */
+ int do_tooltip; /* TRUE: might set the tooltip font */
+{
+ int didit = FALSE;
+
+ if (HL_TABLE()[idx].sg_font_name != NULL)
+ {
+ hl_do_font(idx, HL_TABLE()[idx].sg_font_name, FALSE, do_menu,
+ do_tooltip);
+ didit = TRUE;
+ }
+ if (HL_TABLE()[idx].sg_gui_fg_name != NULL)
+ {
+ HL_TABLE()[idx].sg_gui_fg =
+ color_name2handle(HL_TABLE()[idx].sg_gui_fg_name);
+ didit = TRUE;
+ }
+ if (HL_TABLE()[idx].sg_gui_bg_name != NULL)
+ {
+ HL_TABLE()[idx].sg_gui_bg =
+ color_name2handle(HL_TABLE()[idx].sg_gui_bg_name);
+ didit = TRUE;
+ }
+ if (didit) /* need to get a new attr number */
+ set_hl_attr(idx);
+}
+
+#endif
+
+/*
+ * Translate the 'highlight' option into attributes in highlight_attr[] and
+ * set up the user highlights User1..9. If FEAT_STL_OPT is in use, a set of
+ * corresponding highlights to use on top of HLF_SNC is computed.
+ * Called only when the 'highlight' option has been changed and upon first
+ * screen redraw after any :highlight command.
+ * Return FAIL when an invalid flag is found in 'highlight'. OK otherwise.
+ */
+ int
+highlight_changed()
+{
+ int hlf;
+ int i;
+ char_u *p;
+ int attr;
+ char_u *end;
+ int id;
+#ifdef USER_HIGHLIGHT
+ char_u userhl[10];
+# ifdef FEAT_STL_OPT
+ int id_SNC = -1;
+ int id_S = -1;
+ int hlcnt;
+# endif
+#endif
+ static int hl_flags[HLF_COUNT] = HL_FLAGS;
+
+ need_highlight_changed = FALSE;
+
+ /*
+ * Clear all attributes.
+ */
+ for (hlf = 0; hlf < (int)HLF_COUNT; ++hlf)
+ highlight_attr[hlf] = 0;
+
+ /*
+ * First set all attributes to their default value.
+ * Then use the attributes from the 'highlight' option.
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ if (i)
+ p = p_hl;
+ else
+ p = get_highlight_default();
+ if (p == NULL) /* just in case */
+ continue;
+
+ while (*p)
+ {
+ for (hlf = 0; hlf < (int)HLF_COUNT; ++hlf)
+ if (hl_flags[hlf] == *p)
+ break;
+ ++p;
+ if (hlf == (int)HLF_COUNT || *p == NUL)
+ return FAIL;
+
+ /*
+ * Allow several hl_flags to be combined, like "bu" for
+ * bold-underlined.
+ */
+ attr = 0;
+ for ( ; *p && *p != ','; ++p) /* parse upto comma */
+ {
+ if (vim_iswhite(*p)) /* ignore white space */
+ continue;
+
+ if (attr > HL_ALL) /* Combination with ':' is not allowed. */
+ return FAIL;
+
+ switch (*p)
+ {
+ case 'b': attr |= HL_BOLD;
+ break;
+ case 'i': attr |= HL_ITALIC;
+ break;
+ case '-':
+ case 'n': /* no highlighting */
+ break;
+ case 'r': attr |= HL_INVERSE;
+ break;
+ case 's': attr |= HL_STANDOUT;
+ break;
+ case 'u': attr |= HL_UNDERLINE;
+ break;
+ case ':': ++p; /* highlight group name */
+ if (attr || *p == NUL) /* no combinations */
+ return FAIL;
+ end = vim_strchr(p, ',');
+ if (end == NULL)
+ end = p + STRLEN(p);
+ id = syn_check_group(p, (int)(end - p));
+ if (id == 0)
+ return FAIL;
+ attr = syn_id2attr(id);
+ p = end - 1;
+#if defined(FEAT_STL_OPT) && defined(USER_HIGHLIGHT)
+ if (hlf == (int)HLF_SNC)
+ id_SNC = syn_get_final_id(id);
+ else if (hlf == (int)HLF_S)
+ id_S = syn_get_final_id(id);
+#endif
+ break;
+ default: return FAIL;
+ }
+ }
+ highlight_attr[hlf] = attr;
+
+ p = skip_to_option_part(p); /* skip comma and spaces */
+ }
+ }
+
+#ifdef USER_HIGHLIGHT
+ /* Setup the user highlights
+ *
+ * Temporarily utilize 10 more hl entries. Have to be in there
+ * simultaneously in case of table overflows in get_attr_entry()
+ */
+# ifdef FEAT_STL_OPT
+ if (ga_grow(&highlight_ga, 10) == FAIL)
+ return FAIL;
+ hlcnt = highlight_ga.ga_len;
+ if (id_S == 0)
+ { /* Make sure id_S is always valid to simplify code below */
+ memset(&HL_TABLE()[hlcnt + 9], 0, sizeof(struct hl_group));
+ HL_TABLE()[hlcnt + 9].sg_term = highlight_attr[HLF_S];
+ id_S = hlcnt + 10;
+ }
+# endif
+ for (i = 0; i < 9; i++)
+ {
+ sprintf((char *)userhl, "User%d", i + 1);
+ id = syn_name2id(userhl);
+ if (id == 0)
+ {
+ highlight_user[i] = 0;
+# ifdef FEAT_STL_OPT
+ highlight_stlnc[i] = 0;
+# endif
+ }
+ else
+ {
+# ifdef FEAT_STL_OPT
+ struct hl_group *hlt = HL_TABLE();
+# endif
+
+ highlight_user[i] = syn_id2attr(id);
+# ifdef FEAT_STL_OPT
+ if (id_SNC == 0)
+ {
+ memset(&hlt[hlcnt + i], 0, sizeof(struct hl_group));
+ hlt[hlcnt + i].sg_term = highlight_attr[HLF_SNC];
+ hlt[hlcnt + i].sg_cterm = highlight_attr[HLF_SNC];
+# ifdef FEAT_GUI
+ hlt[hlcnt + i].sg_gui = highlight_attr[HLF_SNC];
+# endif
+ }
+ else
+ mch_memmove(&hlt[hlcnt + i],
+ &hlt[id_SNC - 1],
+ sizeof(struct hl_group));
+ hlt[hlcnt + i].sg_link = 0;
+
+ /* Apply difference between UserX and HLF_S to HLF_SNC */
+ hlt[hlcnt + i].sg_term ^=
+ hlt[id - 1].sg_term ^ hlt[id_S - 1].sg_term;
+ if (hlt[id - 1].sg_start != hlt[id_S - 1].sg_start)
+ hlt[hlcnt + i].sg_start = hlt[id - 1].sg_start;
+ if (hlt[id - 1].sg_stop != hlt[id_S - 1].sg_stop)
+ hlt[hlcnt + i].sg_stop = hlt[id - 1].sg_stop;
+ hlt[hlcnt + i].sg_cterm ^=
+ hlt[id - 1].sg_cterm ^ hlt[id_S - 1].sg_cterm;
+ if (hlt[id - 1].sg_cterm_fg != hlt[id_S - 1].sg_cterm_fg)
+ hlt[hlcnt + i].sg_cterm_fg = hlt[id - 1].sg_cterm_fg;
+ if (hlt[id - 1].sg_cterm_bg != hlt[id_S - 1].sg_cterm_bg)
+ hlt[hlcnt + i].sg_cterm_bg = hlt[id - 1].sg_cterm_bg;
+# ifdef FEAT_GUI
+ hlt[hlcnt + i].sg_gui ^=
+ hlt[id - 1].sg_gui ^ hlt[id_S - 1].sg_gui;
+ if (hlt[id - 1].sg_gui_fg != hlt[id_S - 1].sg_gui_fg)
+ hlt[hlcnt + i].sg_gui_fg = hlt[id - 1].sg_gui_fg;
+ if (hlt[id - 1].sg_gui_bg != hlt[id_S - 1].sg_gui_bg)
+ hlt[hlcnt + i].sg_gui_bg = hlt[id - 1].sg_gui_bg;
+ if (hlt[id - 1].sg_font != hlt[id_S - 1].sg_font)
+ hlt[hlcnt + i].sg_font = hlt[id - 1].sg_font;
+# ifdef FEAT_XFONTSET
+ if (hlt[id - 1].sg_fontset != hlt[id_S - 1].sg_fontset)
+ hlt[hlcnt + i].sg_fontset = hlt[id - 1].sg_fontset;
+# endif
+# endif
+ highlight_ga.ga_len = hlcnt + i + 1;
+ set_hl_attr(hlcnt + i); /* At long last we can apply */
+ highlight_stlnc[i] = syn_id2attr(hlcnt + i + 1);
+# endif
+ }
+ }
+# ifdef FEAT_STL_OPT
+ highlight_ga.ga_len = hlcnt;
+# endif
+
+#endif /* USER_HIGHLIGHT */
+
+ return OK;
+}
+
+#ifdef FEAT_CMDL_COMPL
+
+static void highlight_list __ARGS((void));
+static void highlight_list_two __ARGS((int cnt, int attr));
+
+/*
+ * Handle command line completion for :highlight command.
+ */
+ void
+set_context_in_highlight_cmd(xp, arg)
+ expand_T *xp;
+ char_u *arg;
+{
+ char_u *p;
+
+ /* Default: expand group names */
+ xp->xp_context = EXPAND_HIGHLIGHT;
+ xp->xp_pattern = arg;
+ include_link = TRUE;
+ include_default = TRUE;
+
+ /* (part of) subcommand already typed */
+ if (*arg != NUL)
+ {
+ p = skiptowhite(arg);
+ if (*p != NUL) /* past "default" or group name */
+ {
+ include_default = FALSE;
+ if (STRNCMP("default", arg, p - arg) == 0)
+ {
+ arg = skipwhite(p);
+ xp->xp_pattern = arg;
+ p = skiptowhite(arg);
+ }
+ if (*p != NUL) /* past group name */
+ {
+ include_link = FALSE;
+ if (arg[1] == 'i' && arg[0] == 'N')
+ highlight_list();
+ if (STRNCMP("link", arg, p - arg) == 0
+ || STRNCMP("clear", arg, p - arg) == 0)
+ {
+ xp->xp_pattern = skipwhite(p);
+ p = skiptowhite(xp->xp_pattern);
+ if (*p != NUL) /* past first group name */
+ {
+ xp->xp_pattern = skipwhite(p);
+ p = skiptowhite(xp->xp_pattern);
+ }
+ }
+ if (*p != NUL) /* past group name(s) */
+ xp->xp_context = EXPAND_NOTHING;
+ }
+ }
+ }
+}
+
+/*
+ * List highlighting matches in a nice way.
+ */
+ static void
+highlight_list()
+{
+ int i;
+
+ for (i = 10; --i >= 0; )
+ highlight_list_two(i, hl_attr(HLF_D));
+ for (i = 40; --i >= 0; )
+ highlight_list_two(99, 0);
+}
+
+ static void
+highlight_list_two(cnt, attr)
+ int cnt;
+ int attr;
+{
+ msg_puts_attr((char_u *)("N \bI \b! \b" + cnt / 11), attr);
+ msg_clr_eos();
+ out_flush();
+ ui_delay(cnt == 99 ? 40L : (long)cnt * 50L, FALSE);
+}
+
+#endif /* FEAT_CMDL_COMPL */
+
+#if defined(FEAT_CMDL_COMPL) || (defined(FEAT_SYN_HL) && defined(FEAT_EVAL)) \
+ || defined(FEAT_SIGNS) || defined(PROTO)
+/*
+ * Function given to ExpandGeneric() to obtain the list of group names.
+ * Also used for synIDattr() function.
+ */
+/*ARGSUSED*/
+ char_u *
+get_highlight_name(xp, idx)
+ expand_T *xp;
+ int idx;
+{
+ if (idx == highlight_ga.ga_len
+#ifdef FEAT_CMDL_COMPL
+ && include_link
+#endif
+ )
+ return (char_u *)"link";
+ if (idx == highlight_ga.ga_len + 1
+#ifdef FEAT_CMDL_COMPL
+ && include_link
+#endif
+ )
+ return (char_u *)"clear";
+ if (idx == highlight_ga.ga_len + 2
+#ifdef FEAT_CMDL_COMPL
+ && include_default
+#endif
+ )
+ return (char_u *)"default";
+ if (idx < 0 || idx >= highlight_ga.ga_len)
+ return NULL;
+ return HL_TABLE()[idx].sg_name;
+}
+#endif
+
+#ifdef FEAT_GUI
+/*
+ * Free all the highlight group fonts.
+ * Used when quitting for systems which need it.
+ */
+ void
+free_highlight_fonts()
+{
+ int idx;
+
+ for (idx = 0; idx < highlight_ga.ga_len; ++idx)
+ {
+ gui_mch_free_font(HL_TABLE()[idx].sg_font);
+ HL_TABLE()[idx].sg_font = NOFONT;
+# ifdef FEAT_XFONTSET
+ gui_mch_free_fontset(HL_TABLE()[idx].sg_fontset);
+ HL_TABLE()[idx].sg_fontset = NOFONTSET;
+# endif
+ }
+
+ gui_mch_free_font(gui.norm_font);
+# ifdef FEAT_XFONTSET
+ gui_mch_free_fontset(gui.fontset);
+# endif
+# ifndef HAVE_GTK2
+ gui_mch_free_font(gui.bold_font);
+ gui_mch_free_font(gui.ital_font);
+ gui_mch_free_font(gui.boldital_font);
+# endif
+}
+#endif
+
+/**************************************
+ * End of Highlighting stuff *
+ **************************************/
diff --git a/src/tag.c b/src/tag.c
new file mode 100644
index 000000000..1e6d5ac5d
--- /dev/null
+++ b/src/tag.c
@@ -0,0 +1,3534 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * Code to handle tags and the tag stack
+ */
+
+#if defined MSDOS || defined WIN32 || defined(_WIN64)
+# include <io.h> /* for lseek(), must be before vim.h */
+#endif
+
+#include "vim.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h> /* for lseek() */
+#endif
+
+/*
+ * Structure to hold pointers to various items in a tag line.
+ */
+typedef struct tag_pointers
+{
+ /* filled in by parse_tag_line(): */
+ char_u *tagname; /* start of tag name (skip "file:") */
+ char_u *tagname_end; /* char after tag name */
+ char_u *fname; /* first char of file name */
+ char_u *fname_end; /* char after file name */
+ char_u *command; /* first char of command */
+ /* filled in by parse_match(): */
+ char_u *command_end; /* first char after command */
+ char_u *tag_fname; /* file name of the tags file */
+#ifdef FEAT_EMACS_TAGS
+ int is_etag; /* TRUE for emacs tag */
+#endif
+ char_u *tagkind; /* "kind:" value */
+ char_u *tagkind_end; /* end of tagkind */
+} tagptrs_T;
+
+/*
+ * The matching tags are first stored in ga_match[]. In which one depends on
+ * the priority of the match.
+ * At the end, the matches from ga_match[] are concatenated, to make a list
+ * sorted on priority.
+ */
+#define MT_ST_CUR 0 /* static match in current file */
+#define MT_GL_CUR 1 /* global match in current file */
+#define MT_GL_OTH 2 /* global match in other file */
+#define MT_ST_OTH 3 /* static match in other file */
+#define MT_IC_ST_CUR 4 /* icase static match in current file */
+#define MT_IC_GL_CUR 5 /* icase global match in current file */
+#define MT_IC_GL_OTH 6 /* icase global match in other file */
+#define MT_IC_ST_OTH 7 /* icase static match in other file */
+#define MT_IC_OFF 4 /* add for icase match */
+#define MT_RE_OFF 8 /* add for regexp match */
+#define MT_MASK 7 /* mask for printing priority */
+#define MT_COUNT 16
+
+static char *mt_names[MT_COUNT/2] =
+ {"FSC", "F C", "F ", "FS ", " SC", " C", " ", " S "};
+
+#define NOTAGFILE 99 /* return value for jumpto_tag */
+static char_u *nofile_fname = NULL; /* fname for NOTAGFILE error */
+
+static void taglen_advance __ARGS((int l));
+static int get_tagfname __ARGS((int first, char_u *buf));
+
+static int jumpto_tag __ARGS((char_u *lbuf, int forceit, int keep_help));
+#ifdef FEAT_EMACS_TAGS
+static int parse_tag_line __ARGS((char_u *lbuf, int is_etag, tagptrs_T *tagp));
+#else
+static int parse_tag_line __ARGS((char_u *lbuf, tagptrs_T *tagp));
+#endif
+static int test_for_static __ARGS((tagptrs_T *));
+static int parse_match __ARGS((char_u *lbuf, tagptrs_T *tagp));
+static char_u *tag_full_fname __ARGS((tagptrs_T *tagp));
+static char_u *expand_tag_fname __ARGS((char_u *fname, char_u *tag_fname, int expand));
+#ifdef FEAT_EMACS_TAGS
+static int test_for_current __ARGS((int, char_u *, char_u *, char_u *, char_u *));
+#else
+static int test_for_current __ARGS((char_u *, char_u *, char_u *, char_u *));
+#endif
+static int find_extra __ARGS((char_u **pp));
+
+static char_u *bottommsg = (char_u *)N_("E555: at bottom of tag stack");
+static char_u *topmsg = (char_u *)N_("E556: at top of tag stack");
+
+static char_u *tagmatchname = NULL; /* name of last used tag */
+
+/*
+ * We use ftello() here, if available. It returns off_t instead of long,
+ * which helps if long is 32 bit and off_t is 64 bit.
+ */
+#ifdef HAVE_FTELLO
+# define ftell ftello
+#endif
+
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+/*
+ * Tag for preview window is remembered separately, to avoid messing up the
+ * normal tagstack.
+ */
+static taggy_T ptag_entry = {NULL};
+#endif
+
+/*
+ * Jump to tag; handling of tag commands and tag stack
+ *
+ * *tag != NUL: ":tag {tag}", jump to new tag, add to tag stack
+ *
+ * type == DT_TAG: ":tag [tag]", jump to newer position or same tag again
+ * type == DT_HELP: like DT_TAG, but don't use regexp.
+ * type == DT_POP: ":pop" or CTRL-T, jump to old position
+ * type == DT_NEXT: jump to next match of same tag
+ * type == DT_PREV: jump to previous match of same tag
+ * type == DT_FIRST: jump to first match of same tag
+ * type == DT_LAST: jump to last match of same tag
+ * type == DT_SELECT: ":tselect [tag]", select tag from a list of all matches
+ * type == DT_JUMP: ":tjump [tag]", jump to tag or select tag from a list
+ * type == DT_CSCOPE: use cscope to find the tag.
+ *
+ * for cscope, returns TRUE if we jumped to tag or aborted, FALSE otherwise
+ */
+ int
+do_tag(tag, type, count, forceit, verbose)
+ char_u *tag; /* tag (pattern) to jump to */
+ int type;
+ int count;
+ int forceit; /* :ta with ! */
+ int verbose; /* print "tag not found" message */
+{
+ taggy_T *tagstack = curwin->w_tagstack;
+ int tagstackidx = curwin->w_tagstackidx;
+ int tagstacklen = curwin->w_tagstacklen;
+ int cur_match = 0;
+ int cur_fnum = curbuf->b_fnum;
+ int oldtagstackidx = tagstackidx;
+ int prevtagstackidx = tagstackidx;
+ int prev_num_matches;
+ int new_tag = FALSE;
+ int other_name;
+ int i, j, k;
+ int idx;
+ int ic;
+ char_u *p;
+ char_u *name;
+ int no_regexp = FALSE;
+ int error_cur_match = 0;
+ char_u *command_end;
+ int save_pos = FALSE;
+ fmark_T saved_fmark;
+ int taglen;
+#ifdef FEAT_CSCOPE
+ int jumped_to_tag = FALSE;
+#endif
+ tagptrs_T tagp, tagp2;
+ int new_num_matches;
+ char_u **new_matches;
+ int attr;
+ int use_tagstack;
+ int skip_msg = FALSE;
+ char_u *buf_ffname = curbuf->b_ffname; /* name to use for
+ priority computation */
+
+ /* remember the matches for the last used tag */
+ static int num_matches = 0;
+ static int max_num_matches = 0; /* limit used for match search */
+ static char_u **matches = NULL;
+ static int flags;
+
+ if (type == DT_HELP)
+ {
+ type = DT_TAG;
+ no_regexp = TRUE;
+ }
+
+ prev_num_matches = num_matches;
+ free_string_option(nofile_fname);
+ nofile_fname = NULL;
+
+ /*
+ * Don't add a tag to the tagstack if 'tagstack' has been reset.
+ */
+ if ((!p_tgst && *tag != NUL))
+ {
+ use_tagstack = FALSE;
+ new_tag = TRUE;
+ }
+ else
+ {
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ if (g_do_tagpreview)
+ use_tagstack = FALSE;
+ else
+#endif
+ use_tagstack = TRUE;
+
+ /* new pattern, add to the tag stack */
+ if (*tag && (type == DT_TAG || type == DT_SELECT || type == DT_JUMP
+#ifdef FEAT_CSCOPE
+ || type == DT_CSCOPE
+#endif
+ ))
+ {
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ if (g_do_tagpreview)
+ {
+ if (ptag_entry.tagname != NULL
+ && STRCMP(ptag_entry.tagname, tag) == 0)
+ {
+ /* Jumping to same tag: keep the current match, so that
+ * the CursorHold autocommand example works. */
+ cur_match = ptag_entry.cur_match;
+ cur_fnum = ptag_entry.cur_fnum;
+ }
+ else
+ {
+ vim_free(ptag_entry.tagname);
+ if ((ptag_entry.tagname = vim_strsave(tag)) == NULL)
+ goto end_do_tag;
+ }
+ }
+ else
+#endif
+ {
+ /*
+ * If the last used entry is not at the top, delete all tag
+ * stack entries above it.
+ */
+ while (tagstackidx < tagstacklen)
+ vim_free(tagstack[--tagstacklen].tagname);
+
+ /* if the tagstack is full: remove oldest entry */
+ if (++tagstacklen > TAGSTACKSIZE)
+ {
+ tagstacklen = TAGSTACKSIZE;
+ vim_free(tagstack[0].tagname);
+ for (i = 1; i < tagstacklen; ++i)
+ tagstack[i - 1] = tagstack[i];
+ --tagstackidx;
+ }
+
+ /*
+ * put the tag name in the tag stack
+ */
+ if ((tagstack[tagstackidx].tagname = vim_strsave(tag)) == NULL)
+ {
+ curwin->w_tagstacklen = tagstacklen - 1;
+ goto end_do_tag;
+ }
+ curwin->w_tagstacklen = tagstacklen;
+
+ save_pos = TRUE; /* save the cursor position below */
+ }
+
+ new_tag = TRUE;
+ }
+ else
+ {
+ if (
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ g_do_tagpreview ? ptag_entry.tagname == NULL :
+#endif
+ tagstacklen == 0)
+ {
+ /* empty stack */
+ EMSG(_(e_tagstack));
+ goto end_do_tag;
+ }
+
+ if (type == DT_POP) /* go to older position */
+ {
+#ifdef FEAT_FOLDING
+ int old_KeyTyped = KeyTyped;
+#endif
+ if ((tagstackidx -= count) < 0)
+ {
+ EMSG(_(bottommsg));
+ if (tagstackidx + count == 0)
+ {
+ /* We did [num]^T from the bottom of the stack */
+ tagstackidx = 0;
+ goto end_do_tag;
+ }
+ /* We weren't at the bottom of the stack, so jump all the
+ * way to the bottom now.
+ */
+ tagstackidx = 0;
+ }
+ else if (tagstackidx >= tagstacklen) /* count == 0? */
+ {
+ EMSG(_(topmsg));
+ goto end_do_tag;
+ }
+
+ /* Make a copy of the fmark, autocommands may invalidate the
+ * tagstack before it's used. */
+ saved_fmark = tagstack[tagstackidx].fmark;
+ if (saved_fmark.fnum != curbuf->b_fnum)
+ {
+ /*
+ * Jump to other file. If this fails (e.g. because the
+ * file was changed) keep original position in tag stack.
+ */
+ if (buflist_getfile(saved_fmark.fnum, saved_fmark.mark.lnum,
+ GETF_SETMARK, forceit) == FAIL)
+ {
+ tagstackidx = oldtagstackidx; /* back to old posn */
+ goto end_do_tag;
+ }
+ /* An BufReadPost autocommand may jump to the '" mark, but
+ * we don't what that here. */
+ curwin->w_cursor.lnum = saved_fmark.mark.lnum;
+ }
+ else
+ {
+ setpcmark();
+ curwin->w_cursor.lnum = saved_fmark.mark.lnum;
+ }
+ curwin->w_cursor.col = saved_fmark.mark.col;
+ curwin->w_set_curswant = TRUE;
+ check_cursor();
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_TAG) && old_KeyTyped)
+ foldOpenCursor();
+#endif
+
+ /* remove the old list of matches */
+ FreeWild(num_matches, matches);
+#ifdef FEAT_CSCOPE
+ cs_free_tags();
+#endif
+ num_matches = 0;
+ goto end_do_tag;
+ }
+
+ if (type == DT_TAG)
+ {
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ if (g_do_tagpreview)
+ {
+ cur_match = ptag_entry.cur_match;
+ cur_fnum = ptag_entry.cur_fnum;
+ }
+ else
+#endif
+ {
+ /* ":tag" (no argument): go to newer pattern */
+ save_pos = TRUE; /* save the cursor position below */
+ if ((tagstackidx += count - 1) >= tagstacklen)
+ {
+ /*
+ * Beyond the last one, just give an error message and
+ * go to the last one. Don't store the cursor
+ * postition.
+ */
+ tagstackidx = tagstacklen - 1;
+ EMSG(_(topmsg));
+ save_pos = FALSE;
+ }
+ else if (tagstackidx < 0) /* must have been count == 0 */
+ {
+ EMSG(_(bottommsg));
+ tagstackidx = 0;
+ goto end_do_tag;
+ }
+ cur_match = tagstack[tagstackidx].cur_match;
+ cur_fnum = tagstack[tagstackidx].cur_fnum;
+ }
+ new_tag = TRUE;
+ }
+ else /* go to other matching tag */
+ {
+ /* Save index for when selection is cancelled. */
+ prevtagstackidx = tagstackidx;
+
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ if (g_do_tagpreview)
+ {
+ cur_match = ptag_entry.cur_match;
+ cur_fnum = ptag_entry.cur_fnum;
+ }
+ else
+#endif
+ {
+ if (--tagstackidx < 0)
+ tagstackidx = 0;
+ cur_match = tagstack[tagstackidx].cur_match;
+ cur_fnum = tagstack[tagstackidx].cur_fnum;
+ }
+ switch (type)
+ {
+ case DT_FIRST: cur_match = count - 1; break;
+ case DT_SELECT:
+ case DT_JUMP:
+#ifdef FEAT_CSCOPE
+ case DT_CSCOPE:
+#endif
+ case DT_LAST: cur_match = MAXCOL - 1; break;
+ case DT_NEXT: cur_match += count; break;
+ case DT_PREV: cur_match -= count; break;
+ }
+ if (cur_match >= MAXCOL)
+ cur_match = MAXCOL - 1;
+ else if (cur_match < 0)
+ {
+ EMSG(_("E425: Cannot go before first matching tag"));
+ skip_msg = TRUE;
+ cur_match = 0;
+ cur_fnum = curbuf->b_fnum;
+ }
+ }
+ }
+
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ if (g_do_tagpreview)
+ {
+ if (type != DT_SELECT && type != DT_JUMP)
+ {
+ ptag_entry.cur_match = cur_match;
+ ptag_entry.cur_fnum = cur_fnum;
+ }
+ }
+ else
+#endif
+ {
+ /*
+ * For ":tag [arg]" or ":tselect" remember position before the jump.
+ */
+ saved_fmark = tagstack[tagstackidx].fmark;
+ if (save_pos)
+ {
+ tagstack[tagstackidx].fmark.mark = curwin->w_cursor;
+ tagstack[tagstackidx].fmark.fnum = curbuf->b_fnum;
+ }
+
+ /* Curwin will change in the call to jumpto_tag() if ":stag" was
+ * used or an autocommand jumps to another window; store value of
+ * tagstackidx now. */
+ curwin->w_tagstackidx = tagstackidx;
+ if (type != DT_SELECT && type != DT_JUMP)
+ {
+ curwin->w_tagstack[tagstackidx].cur_match = cur_match;
+ curwin->w_tagstack[tagstackidx].cur_fnum = cur_fnum;
+ }
+ }
+ }
+
+ /* When not using the current buffer get the name of buffer "cur_fnum".
+ * Makes sure that the tag order doesn't change when using a remembered
+ * position for "cur_match". */
+ if (cur_fnum != curbuf->b_fnum)
+ {
+ buf_T *buf = buflist_findnr(cur_fnum);
+
+ if (buf != NULL)
+ buf_ffname = buf->b_ffname;
+ }
+
+ /*
+ * Repeat searching for tags, when a file has not been found.
+ */
+ for (;;)
+ {
+ /*
+ * When desired match not found yet, try to find it (and others).
+ */
+ if (use_tagstack)
+ name = tagstack[tagstackidx].tagname;
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ else if (g_do_tagpreview)
+ name = ptag_entry.tagname;
+#endif
+ else
+ name = tag;
+ other_name = (tagmatchname == NULL || STRCMP(tagmatchname, name) != 0);
+ if (new_tag
+ || (cur_match >= num_matches && max_num_matches != MAXCOL)
+ || other_name)
+ {
+ if (other_name)
+ {
+ vim_free(tagmatchname);
+ tagmatchname = vim_strsave(name);
+ }
+
+ if (type == DT_SELECT || type == DT_JUMP)
+ cur_match = MAXCOL - 1;
+ max_num_matches = cur_match + 1;
+
+ /* when the argument starts with '/', use it as a regexp */
+ if (!no_regexp && *name == '/')
+ {
+ flags = TAG_REGEXP;
+ ++name;
+ }
+ else
+ flags = TAG_NOIC;
+
+#ifdef FEAT_CSCOPE
+ if (type == DT_CSCOPE)
+ flags = TAG_CSCOPE;
+#endif
+ if (verbose)
+ flags |= TAG_VERBOSE;
+ if (find_tags(name, &new_num_matches, &new_matches, flags,
+ max_num_matches, buf_ffname) == OK
+ && new_num_matches < max_num_matches)
+ max_num_matches = MAXCOL; /* If less than max_num_matches
+ found: all matches found. */
+
+ /* If there already were some matches for the same name, move them
+ * to the start. Avoids that the order changes when using
+ * ":tnext" and jumping to another file. */
+ if (!new_tag && !other_name)
+ {
+ /* Find the position of each old match in the new list. Need
+ * to use parse_match() to find the tag line. */
+ idx = 0;
+ for (j = 0; j < num_matches; ++j)
+ {
+ parse_match(matches[j], &tagp);
+ for (i = idx; i < new_num_matches; ++i)
+ {
+ parse_match(new_matches[i], &tagp2);
+ if (STRCMP(tagp.tagname, tagp2.tagname) == 0)
+ {
+ p = new_matches[i];
+ for (k = i; k > idx; --k)
+ new_matches[k] = new_matches[k - 1];
+ new_matches[idx++] = p;
+ break;
+ }
+ }
+ }
+ }
+ FreeWild(num_matches, matches);
+ num_matches = new_num_matches;
+ matches = new_matches;
+ }
+
+ if (num_matches <= 0)
+ {
+ if (verbose)
+ EMSG2(_("E426: tag not found: %s"), name);
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ g_do_tagpreview = 0;
+#endif
+ }
+ else
+ {
+ int ask_for_selection = FALSE;
+
+#ifdef FEAT_CSCOPE
+ if (type == DT_CSCOPE && num_matches > 1)
+ {
+ cs_print_tags();
+ ask_for_selection = TRUE;
+ }
+ else
+#endif
+ if (type == DT_SELECT || (type == DT_JUMP && num_matches > 1))
+ {
+ /*
+ * List all the matching tags.
+ * Assume that the first match indicates how long the tags can
+ * be, and align the file names to that.
+ */
+ parse_match(matches[0], &tagp);
+ taglen = (int)(tagp.tagname_end - tagp.tagname + 2);
+ if (taglen < 18)
+ taglen = 18;
+ if (taglen > Columns - 25)
+ taglen = MAXCOL;
+ if (msg_col == 0)
+ msg_didout = FALSE; /* overwrite previous message */
+ msg_start();
+ MSG_PUTS_ATTR(_(" # pri kind tag"), hl_attr(HLF_T));
+ msg_clr_eos();
+ taglen_advance(taglen);
+ MSG_PUTS_ATTR(_("file\n"), hl_attr(HLF_T));
+
+ for (i = 0; i < num_matches; ++i)
+ {
+ parse_match(matches[i], &tagp);
+ if (!new_tag && (
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ (g_do_tagpreview
+ && i == ptag_entry.cur_match) ||
+#endif
+ (use_tagstack
+ && i == tagstack[tagstackidx].cur_match)))
+ *IObuff = '>';
+ else
+ *IObuff = ' ';
+ sprintf((char *)IObuff + 1, "%2d %s ", i + 1,
+ mt_names[matches[i][0] & MT_MASK]);
+ msg_puts(IObuff);
+ if (tagp.tagkind != NULL)
+ msg_outtrans_len(tagp.tagkind,
+ (int)(tagp.tagkind_end - tagp.tagkind));
+ msg_advance(13);
+ msg_outtrans_len_attr(tagp.tagname,
+ (int)(tagp.tagname_end - tagp.tagname),
+ hl_attr(HLF_T));
+ msg_putchar(' ');
+ taglen_advance(taglen);
+
+ /* Find out the actual file name. If it is long, truncate
+ * it and put "..." in the middle */
+ p = tag_full_fname(&tagp);
+ if (p != NULL)
+ {
+ msg_puts_long_attr(p, hl_attr(HLF_D));
+ vim_free(p);
+ }
+ if (msg_col > 0)
+ msg_putchar('\n');
+ msg_advance(15);
+
+ /* print any extra fields */
+ command_end = tagp.command_end;
+ if (command_end != NULL)
+ {
+ p = command_end + 3;
+ while (*p && *p != '\r' && *p != '\n')
+ {
+ while (*p == TAB)
+ ++p;
+
+ /* skip "file:" without a value (static tag) */
+ if (STRNCMP(p, "file:", 5) == 0
+ && vim_isspace(p[5]))
+ {
+ p += 5;
+ continue;
+ }
+ /* skip "kind:<kind>" and "<kind>" */
+ if (p == tagp.tagkind
+ || (p + 5 == tagp.tagkind
+ && STRNCMP(p, "kind:", 5) == 0))
+ {
+ p = tagp.tagkind_end;
+ continue;
+ }
+ /* print all other extra fields */
+ attr = hl_attr(HLF_CM);
+ while (*p && *p != '\r' && *p != '\n')
+ {
+ if (msg_col + ptr2cells(p) >= Columns)
+ {
+ msg_putchar('\n');
+ msg_advance(15);
+ }
+ p = msg_outtrans_one(p, attr);
+ if (*p == TAB)
+ {
+ msg_puts_attr((char_u *)" ", attr);
+ break;
+ }
+ if (*p == ':')
+ attr = 0;
+ }
+ }
+ if (msg_col > 15)
+ {
+ msg_putchar('\n');
+ msg_advance(15);
+ }
+ }
+ else
+ {
+ for (p = tagp.command;
+ *p && *p != '\r' && *p != '\n'; ++p)
+ ;
+ command_end = p;
+ }
+
+ /*
+ * Put the info (in several lines) at column 15.
+ * Don't display "/^" and "?^".
+ */
+ p = tagp.command;
+ if (*p == '/' || *p == '?')
+ {
+ ++p;
+ if (*p == '^')
+ ++p;
+ }
+ /* Remove leading whitespace from pattern */
+ while (p != command_end && vim_isspace(*p))
+ ++p;
+
+ while (p != command_end)
+ {
+ if (msg_col + (*p == TAB ? 1 : ptr2cells(p)) > Columns)
+ msg_putchar('\n');
+ msg_advance(15);
+
+ /* skip backslash used for escaping command char */
+ if (*p == '\\' && *(p + 1) == *tagp.command)
+ ++p;
+
+ if (*p == TAB)
+ {
+ msg_putchar(' ');
+ ++p;
+ }
+ else
+ p = msg_outtrans_one(p, 0);
+
+ /* don't display the "$/;\"" and "$?;\"" */
+ if (p == command_end - 2 && *p == '$'
+ && *(p + 1) == *tagp.command)
+ break;
+ /* don't display matching '/' or '?' */
+ if (p == command_end - 1 && *p == *tagp.command
+ && (*p == '/' || *p == '?'))
+ break;
+ }
+ if (msg_col)
+ msg_putchar('\n');
+ ui_breakcheck();
+ if (got_int)
+ {
+ got_int = FALSE; /* only stop the listing */
+ break;
+ }
+ }
+ ask_for_selection = TRUE;
+ }
+
+ if (ask_for_selection == TRUE)
+ {
+ /*
+ * Ask to select a tag from the list.
+ * When using ":silent" assume that <CR> was entered.
+ */
+ MSG_PUTS(_("Enter nr of choice (<CR> to abort): "));
+ i = get_number(TRUE);
+ if (KeyTyped) /* don't call wait_return() now */
+ {
+ msg_putchar('\n');
+ cmdline_row = msg_row - 1;
+ need_wait_return = FALSE;
+ msg_didany = FALSE;
+ }
+ if (i <= 0 || i > num_matches || got_int)
+ {
+ /* no valid choice: don't change anything */
+ if (use_tagstack)
+ {
+ tagstack[tagstackidx].fmark = saved_fmark;
+ tagstackidx = prevtagstackidx;
+ }
+#ifdef FEAT_CSCOPE
+ cs_free_tags();
+ jumped_to_tag = TRUE;
+#endif
+ break;
+ }
+#if 0
+ /* avoid the need to hit <CR> when jumping to another file */
+ msg_scrolled = 0;
+ redraw_all_later(NOT_VALID);
+#endif
+ cur_match = i - 1;
+ }
+
+ if (cur_match >= num_matches)
+ {
+ /* Avoid giving this error when a file wasn't found and we're
+ * looking for a match in another file, which wasn't found.
+ * There will be an EMSG("file doesn't exist") below then. */
+ if ((type == DT_NEXT || type == DT_FIRST)
+ && nofile_fname == NULL)
+ {
+ if (num_matches == 1)
+ EMSG(_("E427: There is only one matching tag"));
+ else
+ EMSG(_("E428: Cannot go beyond last matching tag"));
+ skip_msg = TRUE;
+ }
+ cur_match = num_matches - 1;
+ }
+ if (use_tagstack)
+ {
+ tagstack[tagstackidx].cur_match = cur_match;
+ tagstack[tagstackidx].cur_fnum = cur_fnum;
+ ++tagstackidx;
+ }
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ else if (g_do_tagpreview)
+ {
+ ptag_entry.cur_match = cur_match;
+ ptag_entry.cur_fnum = cur_fnum;
+ }
+#endif
+
+ /*
+ * Only when going to try the next match, report that the previous
+ * file didn't exist. Otherwise an EMSG() is given below.
+ */
+ if (nofile_fname != NULL && error_cur_match != cur_match)
+ msg_str((char_u *)_("File \"%s\" does not exist"),
+ nofile_fname);
+
+
+ ic = (matches[cur_match][0] & MT_IC_OFF);
+ if (type != DT_SELECT && type != DT_JUMP
+#ifdef FEAT_CSCOPE
+ && type != DT_CSCOPE
+#endif
+ && (num_matches > 1 || ic)
+ && !skip_msg)
+ {
+ /* Give an indication of the number of matching tags */
+ sprintf((char *)IObuff, _("tag %d of %d%s"),
+ cur_match + 1,
+ num_matches,
+ max_num_matches != MAXCOL ? _(" or more") : "");
+ if (ic)
+ STRCAT(IObuff, _(" Using tag with different case!"));
+ if ((num_matches > prev_num_matches || new_tag)
+ && num_matches > 1)
+ {
+ if (ic)
+ msg_attr(IObuff, hl_attr(HLF_W));
+ else
+ msg(IObuff);
+ msg_scroll = TRUE; /* don't overwrite this message */
+ }
+ else
+ give_warning(IObuff, ic);
+ if (ic && !msg_scrolled && msg_silent == 0)
+ {
+ out_flush();
+ ui_delay(1000L, TRUE);
+ }
+ }
+
+ /*
+ * Jump to the desired match.
+ */
+ if (jumpto_tag(matches[cur_match], forceit, type != DT_CSCOPE)
+ == NOTAGFILE)
+ {
+ /* File not found: try again with another matching tag */
+ if ((type == DT_PREV && cur_match > 0)
+ || ((type == DT_TAG || type == DT_NEXT
+ || type == DT_FIRST)
+ && (max_num_matches != MAXCOL
+ || cur_match < num_matches - 1)))
+ {
+ error_cur_match = cur_match;
+ if (use_tagstack)
+ --tagstackidx;
+ if (type == DT_PREV)
+ --cur_match;
+ else
+ {
+ type = DT_NEXT;
+ ++cur_match;
+ }
+ continue;
+ }
+ EMSG2(_("E429: File \"%s\" does not exist"), nofile_fname);
+ }
+ else
+ {
+ /* We may have jumped to another window, check that
+ * tagstackidx is still valid. */
+ if (use_tagstack && tagstackidx > curwin->w_tagstacklen)
+ tagstackidx = curwin->w_tagstackidx;
+#ifdef FEAT_CSCOPE
+ jumped_to_tag = TRUE;
+#endif
+ }
+ }
+ break;
+ }
+
+end_do_tag:
+ /* Only store the new index when using the tagstack and it's valid. */
+ if (use_tagstack && tagstackidx <= curwin->w_tagstacklen)
+ curwin->w_tagstackidx = tagstackidx;
+#ifdef FEAT_WINDOWS
+ postponed_split = 0; /* don't split next time */
+#endif
+
+#ifdef FEAT_CSCOPE
+ return jumped_to_tag;
+#else
+ return FALSE;
+#endif
+}
+
+/*
+ * Free cached tags.
+ */
+ void
+tag_freematch()
+{
+ vim_free(tagmatchname);
+ tagmatchname = NULL;
+}
+
+ static void
+taglen_advance(l)
+ int l;
+{
+ if (l == MAXCOL)
+ {
+ msg_putchar('\n');
+ msg_advance(24);
+ }
+ else
+ msg_advance(13 + l);
+}
+
+/*
+ * Print the tag stack
+ */
+/*ARGSUSED*/
+ void
+do_tags(eap)
+ exarg_T *eap;
+{
+ int i;
+ char_u *name;
+ taggy_T *tagstack = curwin->w_tagstack;
+ int tagstackidx = curwin->w_tagstackidx;
+ int tagstacklen = curwin->w_tagstacklen;
+
+ /* Highlight title */
+ MSG_PUTS_TITLE(_("\n # TO tag FROM line in file/text"));
+ for (i = 0; i < tagstacklen; ++i)
+ {
+ if (tagstack[i].tagname != NULL)
+ {
+ name = fm_getname(&(tagstack[i].fmark), 30);
+ if (name == NULL) /* file name not available */
+ continue;
+
+ msg_putchar('\n');
+ sprintf((char *)IObuff, "%c%2d %2d %-15s %5ld ",
+ i == tagstackidx ? '>' : ' ',
+ i + 1,
+ tagstack[i].cur_match + 1,
+ tagstack[i].tagname,
+ tagstack[i].fmark.mark.lnum);
+ msg_outtrans(IObuff);
+ msg_outtrans_attr(name, tagstack[i].fmark.fnum == curbuf->b_fnum
+ ? hl_attr(HLF_D) : 0);
+ vim_free(name);
+ }
+ out_flush(); /* show one line at a time */
+ }
+ if (tagstackidx == tagstacklen) /* idx at top of stack */
+ MSG_PUTS("\n>");
+}
+
+/* When not using a CR for line separator, use vim_fgets() to read tag lines.
+ * For the Mac use tag_fgets(). It can handle any line separator, but is much
+ * slower than vim_fgets().
+ */
+#ifndef USE_CR
+# define tag_fgets vim_fgets
+#endif
+
+#ifdef FEAT_TAG_BINS
+static int tag_strnicmp __ARGS((char_u *s1, char_u *s2, size_t len));
+
+/*
+ * Compare two strings, for length "len", ignoring case the ASCII way.
+ * return 0 for match, < 0 for smaller, > 0 for bigger
+ * Make sure case is folded to uppercase in comparison (like for 'sort -f')
+ */
+ static int
+tag_strnicmp(s1, s2, len)
+ char_u *s1;
+ char_u *s2;
+ size_t len;
+{
+ int i;
+
+ while (len > 0)
+ {
+ i = (int)TOUPPER_ASC(*s1) - (int)TOUPPER_ASC(*s2);
+ if (i != 0)
+ return i; /* this character different */
+ if (*s1 == NUL)
+ break; /* strings match until NUL */
+ ++s1;
+ ++s2;
+ --len;
+ }
+ return 0; /* strings match */
+}
+#endif
+
+/*
+ * Structure to hold info about the tag pattern being used.
+ */
+typedef struct
+{
+ char_u *pat; /* the pattern */
+ int len; /* length of pat[] */
+ char_u *head; /* start of pattern head */
+ int headlen; /* length of head[] */
+ regmatch_T regmatch; /* regexp program, may be NULL */
+} pat_T;
+
+static void prepare_pats __ARGS((pat_T *pats, int has_re));
+
+/*
+ * Extract info from the tag search pattern "pats->pat".
+ */
+ static void
+prepare_pats(pats, has_re)
+ pat_T *pats;
+ int has_re;
+{
+ pats->head = pats->pat;
+ pats->headlen = pats->len;
+ if (has_re)
+ {
+ /* When the pattern starts with '^' or "\\<", binary searching can be
+ * used (much faster). */
+ if (pats->pat[0] == '^')
+ pats->head = pats->pat + 1;
+ else if (pats->pat[0] == '\\' && pats->pat[1] == '<')
+ pats->head = pats->pat + 2;
+ if (pats->head == pats->pat)
+ pats->headlen = 0;
+ else
+ for (pats->headlen = 0; pats->head[pats->headlen] != NUL;
+ ++pats->headlen)
+ if (vim_strchr((char_u *)(p_magic ? ".[~*\\$" : "\\$"),
+ pats->head[pats->headlen]) != NULL)
+ break;
+ if (p_tl != 0 && pats->headlen > p_tl) /* adjust for 'taglength' */
+ pats->headlen = p_tl;
+ }
+
+ if (has_re)
+ pats->regmatch.regprog = vim_regcomp(pats->pat, p_magic ? RE_MAGIC : 0);
+ else
+ pats->regmatch.regprog = NULL;
+}
+
+/*
+ * find_tags() - search for tags in tags files
+ *
+ * Return FAIL if search completely failed (*num_matches will be 0, *matchesp
+ * will be NULL), OK otherwise.
+ *
+ * There is a priority in which type of tag is recognized.
+ *
+ * 6. A static or global tag with a full matching tag for the current file.
+ * 5. A global tag with a full matching tag for another file.
+ * 4. A static tag with a full matching tag for another file.
+ * 3. A static or global tag with an ignore-case matching tag for the
+ * current file.
+ * 2. A global tag with an ignore-case matching tag for another file.
+ * 1. A static tag with an ignore-case matching tag for another file.
+ *
+ * Tags in an emacs-style tags file are always global.
+ *
+ * flags:
+ * TAG_HELP only search for help tags
+ * TAG_NAMES only return name of tag
+ * TAG_REGEXP use "pat" as a regexp
+ * TAG_NOIC don't always ignore case
+ * TAG_KEEP_LANG keep language
+ */
+ int
+find_tags(pat, num_matches, matchesp, flags, mincount, buf_ffname)
+ char_u *pat; /* pattern to search for */
+ int *num_matches; /* return: number of matches found */
+ char_u ***matchesp; /* return: array of matches found */
+ int flags;
+ int mincount; /* MAXCOL: find all matches
+ other: minimal number of matches */
+ char_u *buf_ffname; /* name of buffer for priority */
+{
+ FILE *fp;
+ char_u *lbuf; /* line buffer */
+ char_u *tag_fname; /* name of tag file */
+ int first_file; /* trying first tag file */
+ tagptrs_T tagp;
+ int did_open = FALSE; /* did open a tag file */
+ int stop_searching = FALSE; /* stop when match found or error */
+ int retval = FAIL; /* return value */
+ int is_static; /* current tag line is static */
+ int is_current; /* file name matches */
+ int eof = FALSE; /* found end-of-file */
+ char_u *p;
+ char_u *s;
+ int i;
+#ifdef FEAT_TAG_BINS
+ struct tag_search_info /* Binary search file offsets */
+ {
+ off_t low_offset; /* offset for first char of first line that
+ could match */
+ off_t high_offset; /* offset of char after last line that could
+ match */
+ off_t curr_offset; /* Current file offset in search range */
+ off_t curr_offset_used; /* curr_offset used when skipping back */
+ off_t match_offset; /* Where the binary search found a tag */
+ int low_char; /* first char at low_offset */
+ int high_char; /* first char at high_offset */
+ } search_info;
+ off_t filesize;
+ int tagcmp;
+ off_t offset;
+ int round;
+#endif
+ enum
+ {
+ TS_START, /* at start of file */
+ TS_LINEAR /* linear searching forward, till EOF */
+#ifdef FEAT_TAG_BINS
+ , TS_BINARY, /* binary searching */
+ TS_SKIP_BACK, /* skipping backwards */
+ TS_STEP_FORWARD /* stepping forwards */
+#endif
+ } state; /* Current search state */
+
+ int cmplen;
+ int match; /* matches */
+ int match_no_ic = 0;/* matches with rm_ic == FALSE */
+ int match_re; /* match with regexp */
+ int matchoff = 0;
+
+#ifdef FEAT_EMACS_TAGS
+ /*
+ * Stack for included emacs-tags file.
+ * It has a fixed size, to truncate cyclic includes. jw
+ */
+# define INCSTACK_SIZE 42
+ struct
+ {
+ FILE *fp;
+ char_u *etag_fname;
+ } incstack[INCSTACK_SIZE];
+
+ int incstack_idx = 0; /* index in incstack */
+ char_u *ebuf; /* aditional buffer for etag fname */
+ int is_etag; /* current file is emaces style */
+#endif
+
+ struct match_found
+ {
+ int len; /* nr of chars of match[] to be compared */
+ char_u match[1]; /* actually longer */
+ } *mfp, *mfp2;
+ garray_T ga_match[MT_COUNT];
+ int match_count = 0; /* number of matches found */
+ char_u **matches;
+ int mtt;
+ int len;
+ int help_save;
+#ifdef FEAT_MULTI_LANG
+ int help_pri = 0;
+ char_u *help_lang_find = NULL; /* lang to be found */
+ char_u help_lang[3]; /* lang of current tags file */
+ char_u *saved_pat = NULL; /* copy of pat[] */
+#endif
+
+ /* Use two sets of variables for the pattern: "orgpat" holds the values
+ * for the original pattern and "convpat" converted from 'encoding' to
+ * encoding of the tags file. "pats" point to either one of these. */
+ pat_T *pats;
+ pat_T orgpat; /* holds unconverted pattern info */
+#ifdef FEAT_MBYTE
+ pat_T convpat; /* holds converted pattern info */
+ vimconv_T vimconv;
+#endif
+
+#ifdef FEAT_TAG_BINS
+ int findall = (mincount == MAXCOL || mincount == TAG_MANY);
+ /* find all matching tags */
+ int sort_error = FALSE; /* tags file not sorted */
+ int linear; /* do a linear search */
+ int sortic = FALSE; /* tag file sorted in nocase */
+#endif
+ int line_error = FALSE; /* syntax error */
+ int has_re = (flags & TAG_REGEXP); /* regexp used */
+ int help_only = (flags & TAG_HELP);
+ int name_only = (flags & TAG_NAMES);
+ int noic = (flags & TAG_NOIC);
+ int get_it_again = FALSE;
+#ifdef FEAT_CSCOPE
+ int use_cscope = (flags & TAG_CSCOPE);
+#endif
+ int verbose = (flags & TAG_VERBOSE);
+
+ help_save = curbuf->b_help;
+ orgpat.pat = pat;
+ pats = &orgpat;
+#ifdef FEAT_MBYTE
+ vimconv.vc_type = CONV_NONE;
+#endif
+
+/*
+ * Allocate memory for the buffers that are used
+ */
+ lbuf = alloc(LSIZE);
+ tag_fname = alloc(MAXPATHL + 1);
+#ifdef FEAT_EMACS_TAGS
+ ebuf = alloc(LSIZE);
+#endif
+ for (mtt = 0; mtt < MT_COUNT; ++mtt)
+ ga_init2(&ga_match[mtt], (int)sizeof(struct match_found *), 100);
+
+ /* check for out of memory situation */
+ if (lbuf == NULL || tag_fname == NULL
+#ifdef FEAT_EMACS_TAGS
+ || ebuf == NULL
+#endif
+ )
+ goto findtag_end;
+
+#ifdef FEAT_CSCOPE
+ STRCPY(tag_fname, "from cscope"); /* for error messages */
+#endif
+
+ /*
+ * Initialize a few variables
+ */
+ if (help_only) /* want tags from help file */
+ curbuf->b_help = TRUE; /* will be restored later */
+
+ pats->len = (int)STRLEN(pat);
+#ifdef FEAT_MULTI_LANG
+ if (curbuf->b_help)
+ {
+ /* When "@ab" is specified use only the "ab" language, otherwise
+ * search all languages. */
+ if (pats->len > 3 && pat[pats->len - 3] == '@'
+ && ASCII_ISALPHA(pat[pats->len - 2])
+ && ASCII_ISALPHA(pat[pats->len - 1]))
+ {
+ saved_pat = vim_strnsave(pat, pats->len - 3);
+ if (saved_pat != NULL)
+ {
+ help_lang_find = &pat[pats->len - 2];
+ pats->pat = saved_pat;
+ pats->len -= 3;
+ }
+ }
+ }
+#endif
+ if (p_tl != 0 && pats->len > p_tl) /* adjust for 'taglength' */
+ pats->len = p_tl;
+
+ prepare_pats(pats, has_re);
+
+#ifdef FEAT_TAG_BINS
+ /* This is only to avoid a compiler warning for using search_info
+ * uninitialised. */
+ vim_memset(&search_info, 0, (size_t)1);
+#endif
+
+/*
+ * When finding a specified number of matches, first try with matching case,
+ * so binary search can be used, and try ignore-case matches in a second loop.
+ * When finding all matches, 'tagbsearch' is off, or there is no fixed string
+ * to look for, ignore case right away to avoid going though the tags files
+ * twice.
+ * When the tag file is case-fold sorted, it is either one or the other.
+ * Only ignore case when TAG_NOIC not used or 'ignorecase' set.
+ */
+#ifdef FEAT_TAG_BINS
+ pats->regmatch.rm_ic = ((p_ic || !noic)
+ && (findall || pats->headlen == 0 || !p_tbs));
+ for (round = 1; round <= 2; ++round)
+ {
+ linear = (pats->headlen == 0 || !p_tbs || round == 2);
+#else
+ pats->regmatch.rm_ic = (p_ic || !noic);
+#endif
+
+ /*
+ * Try tag file names from tags option one by one.
+ */
+ for (first_file = TRUE;
+#ifdef FEAT_CSCOPE
+ use_cscope ||
+#endif
+ get_tagfname(first_file, tag_fname) == OK; first_file = FALSE)
+ {
+ /*
+ * A file that doesn't exist is silently ignored. Only when not a
+ * single file is found, an error message is given (further on).
+ */
+#ifdef FEAT_CSCOPE
+ if (use_cscope)
+ fp = NULL; /* avoid GCC warning */
+ else
+#endif
+ {
+#ifdef FEAT_MULTI_LANG
+ if (curbuf->b_help)
+ {
+ /* Prefer help tags according to 'helplang'. Put the
+ * two-letter language name in help_lang[]. */
+ i = STRLEN(tag_fname);
+ if (i > 3 && tag_fname[i - 3] == '-')
+ STRCPY(help_lang, tag_fname + i - 2);
+ else
+ STRCPY(help_lang, "en");
+
+ /* When searching for a specific language skip tags files
+ * for other languages. */
+ if (help_lang_find != NULL
+ && STRICMP(help_lang, help_lang_find) != 0)
+ continue;
+
+ /* For CTRL-] in a help file prefer a match with the same
+ * language. */
+ if ((flags & TAG_KEEP_LANG)
+ && help_lang_find == NULL
+ && curbuf->b_fname != NULL
+ && (i = STRLEN(curbuf->b_fname)) > 4
+ && curbuf->b_fname[i - 1] == 'x'
+ && curbuf->b_fname[i - 4] == '.'
+ && STRNICMP(curbuf->b_fname + i - 3, help_lang, 2) == 0)
+ help_pri = 0;
+ else
+ {
+ help_pri = 1;
+ for (s = p_hlg; *s != NUL; ++s)
+ {
+ if (STRNICMP(s, help_lang, 2) == 0)
+ break;
+ ++help_pri;
+ if ((s = vim_strchr(s, ',')) == NULL)
+ break;
+ }
+ if (s == NULL || *s == NUL)
+ {
+ /* Language not in 'helplang': use last, prefer English,
+ * unless found already. */
+ ++help_pri;
+ if (STRICMP(help_lang, "en") != 0)
+ ++help_pri;
+ }
+ }
+ }
+#endif
+
+ if ((fp = mch_fopen((char *)tag_fname, "r")) == NULL)
+ continue;
+
+ if (p_verbose >= 5)
+ msg_str((char_u *)_("Searching tags file %s"), tag_fname);
+ }
+ did_open = TRUE; /* remember that we found at least one file */
+
+ state = TS_START; /* we're at the start of the file */
+#ifdef FEAT_EMACS_TAGS
+ is_etag = 0; /* default is: not emacs style */
+#endif
+
+ /*
+ * Read and parse the lines in the file one by one
+ */
+ for (;;)
+ {
+ line_breakcheck(); /* check for CTRL-C typed */
+#ifdef FEAT_INS_EXPAND
+ if ((flags & TAG_INS_COMP)) /* Double brackets for gcc */
+ ins_compl_check_keys();
+ if (got_int || completion_interrupted)
+#else
+ if (got_int)
+#endif
+ {
+ stop_searching = TRUE;
+ break;
+ }
+ /* When mincount is TAG_MANY, stop when enough matches have been
+ * found (for completion). */
+ if (mincount == TAG_MANY && match_count >= TAG_MANY)
+ {
+ stop_searching = TRUE;
+ retval = OK;
+ break;
+ }
+ if (get_it_again)
+ goto line_read_in;
+#ifdef FEAT_TAG_BINS
+ /*
+ * For binary search: compute the next offset to use.
+ */
+ if (state == TS_BINARY)
+ {
+ offset = search_info.low_offset + ((search_info.high_offset
+ - search_info.low_offset) / 2);
+ if (offset == search_info.curr_offset)
+ break; /* End the binary search without a match. */
+ else
+ search_info.curr_offset = offset;
+ }
+
+ /*
+ * Skipping back (after a match during binary search).
+ */
+ else if (state == TS_SKIP_BACK)
+ {
+ search_info.curr_offset -= LSIZE * 2;
+ if (search_info.curr_offset < 0)
+ {
+ search_info.curr_offset = 0;
+ rewind(fp);
+ state = TS_STEP_FORWARD;
+ }
+ }
+
+ /*
+ * When jumping around in the file, first read a line to find the
+ * start of the next line.
+ */
+ if (state == TS_BINARY || state == TS_SKIP_BACK)
+ {
+ /* Adjust the search file offset to the correct position */
+ search_info.curr_offset_used = search_info.curr_offset;
+#ifdef HAVE_FSEEKO
+ fseeko(fp, search_info.curr_offset, SEEK_SET);
+#else
+ fseek(fp, (long)search_info.curr_offset, SEEK_SET);
+#endif
+ eof = tag_fgets(lbuf, LSIZE, fp);
+ if (!eof && search_info.curr_offset != 0)
+ {
+ search_info.curr_offset = ftell(fp);
+ if (search_info.curr_offset == search_info.high_offset)
+ {
+ /* oops, gone a bit too far; try from low offset */
+#ifdef HAVE_FSEEKO
+ fseeko(fp, search_info.low_offset, SEEK_SET);
+#else
+ fseek(fp, (long)search_info.low_offset, SEEK_SET);
+#endif
+ search_info.curr_offset = search_info.low_offset;
+ }
+ eof = tag_fgets(lbuf, LSIZE, fp);
+ }
+ /* skip empty and blank lines */
+ while (!eof && vim_isblankline(lbuf))
+ {
+ search_info.curr_offset = ftell(fp);
+ eof = tag_fgets(lbuf, LSIZE, fp);
+ }
+ if (eof)
+ {
+ /* Hit end of file. Skip backwards. */
+ state = TS_SKIP_BACK;
+ search_info.match_offset = ftell(fp);
+ search_info.curr_offset = search_info.curr_offset_used;
+ continue;
+ }
+ }
+
+ /*
+ * Not jumping around in the file: Read the next line.
+ */
+ else
+#endif
+ {
+ /* skip empty and blank lines */
+ do
+ {
+#ifdef FEAT_CSCOPE
+ if (use_cscope)
+ eof = cs_fgets(lbuf, LSIZE);
+ else
+#endif
+ eof = tag_fgets(lbuf, LSIZE, fp);
+ } while (!eof && vim_isblankline(lbuf));
+
+ if (eof)
+ {
+#ifdef FEAT_EMACS_TAGS
+ if (incstack_idx) /* this was an included file */
+ {
+ --incstack_idx;
+ fclose(fp); /* end of this file ... */
+ fp = incstack[incstack_idx].fp;
+ STRCPY(tag_fname, incstack[incstack_idx].etag_fname);
+ vim_free(incstack[incstack_idx].etag_fname);
+ is_etag = 1; /* (only etags can include) */
+ continue; /* ... continue with parent file */
+ }
+ else
+#endif
+ break; /* end of file */
+ }
+ }
+line_read_in:
+
+#ifdef FEAT_EMACS_TAGS
+ /*
+ * Emacs tags line with CTRL-L: New file name on next line.
+ * The file name is followed by a ','.
+ */
+ if (*lbuf == Ctrl_L) /* remember etag file name in ebuf */
+ {
+ is_etag = 1; /* in case at the start */
+ state = TS_LINEAR;
+ if (!tag_fgets(ebuf, LSIZE, fp))
+ {
+ for (p = ebuf; *p && *p != ','; p++)
+ ;
+ *p = NUL;
+
+ /*
+ * atoi(p+1) is the number of bytes before the next ^L
+ * unless it is an include statement.
+ */
+ if (STRNCMP(p + 1, "include", 7) == 0
+ && incstack_idx < INCSTACK_SIZE)
+ {
+ /* Save current "fp" and "tag_fname" in the stack. */
+ if ((incstack[incstack_idx].etag_fname =
+ vim_strsave(tag_fname)) != NULL)
+ {
+ char_u *fullpath_ebuf;
+
+ incstack[incstack_idx].fp = fp;
+ fp = NULL;
+
+ /* Figure out "tag_fname" and "fp" to use for
+ * included file. */
+ fullpath_ebuf = expand_tag_fname(ebuf,
+ tag_fname, FALSE);
+ if (fullpath_ebuf != NULL)
+ {
+ fp = mch_fopen((char *)fullpath_ebuf, "r");
+ if (fp != NULL)
+ {
+ if (STRLEN(fullpath_ebuf) > LSIZE)
+ EMSG2(_("E430: Tag file path truncated for %s\n"), ebuf);
+ STRNCPY(tag_fname, fullpath_ebuf, LSIZE);
+ tag_fname[LSIZE] = NUL;
+ ++incstack_idx;
+ is_etag = 0; /* we can include anything */
+ }
+ vim_free(fullpath_ebuf);
+ }
+ if (fp == NULL)
+ {
+ /* Can't open the included file, skip it and
+ * restore old value of "fp". */
+ fp = incstack[incstack_idx].fp;
+ vim_free(incstack[incstack_idx].etag_fname);
+ }
+ }
+ }
+ }
+ continue;
+ }
+#endif
+
+ /*
+ * When still at the start of the file, check for Emacs tags file
+ * format, and for "not sorted" flag.
+ */
+ if (state == TS_START)
+ {
+#ifdef FEAT_TAG_BINS
+ /*
+ * When there is no tag head, or ignoring case, need to do a
+ * linear search.
+ * When no "!_TAG_" is found, default to binary search. If
+ * the tag file isn't sorted, the second loop will find it.
+ * When "!_TAG_FILE_SORTED" found: start binary search if
+ * flag set.
+ * For cscope, it's always linear.
+ */
+# ifdef FEAT_CSCOPE
+ if (linear || use_cscope)
+# else
+ if (linear)
+# endif
+ state = TS_LINEAR;
+ else if (STRNCMP(lbuf, "!_TAG_", 6) > 0)
+ state = TS_BINARY;
+ else if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0)
+ {
+ /* Check sorted flag */
+ if (lbuf[18] == '1')
+ state = TS_BINARY;
+ else if (lbuf[18] == '2')
+ {
+ state = TS_BINARY;
+ sortic = TRUE;
+ pats->regmatch.rm_ic = (p_ic || !noic);
+ }
+ else
+ state = TS_LINEAR;
+ }
+
+ if (state == TS_BINARY && pats->regmatch.rm_ic && !sortic)
+ {
+ /* binary search won't work for ignoring case, use linear
+ * search. */
+ linear = TRUE;
+ state = TS_LINEAR;
+ }
+#else
+ state = TS_LINEAR;
+#endif
+
+#ifdef FEAT_TAG_BINS
+ /*
+ * When starting a binary search, get the size of the file and
+ * compute the first offset.
+ */
+ if (state == TS_BINARY)
+ {
+ /* Get the tag file size (don't use mch_fstat(), it's not
+ * portable). */
+ if ((filesize = lseek(fileno(fp),
+ (off_t)0L, SEEK_END)) <= 0)
+ state = TS_LINEAR;
+ else
+ {
+ lseek(fileno(fp), (off_t)0L, SEEK_SET);
+
+ /* Calculate the first read offset in the file. Start
+ * the search in the middle of the file. */
+ search_info.low_offset = 0;
+ search_info.low_char = 0;
+ search_info.high_offset = filesize;
+ search_info.curr_offset = 0;
+ search_info.high_char = 0xff;
+ }
+ continue;
+ }
+#endif
+ }
+
+#ifdef FEAT_MBYTE
+ if (lbuf[0] == '!' && pats == &orgpat
+ && STRNCMP(lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0)
+ {
+ /* Convert the search pattern from 'encoding' to the
+ * specified encoding. */
+ for (p = lbuf + 20; *p > ' ' && *p < 127; ++p)
+ ;
+ *p = NUL;
+ convert_setup(&vimconv, p_enc, lbuf + 20);
+ if (vimconv.vc_type != CONV_NONE)
+ {
+ convpat.pat = string_convert(&vimconv, pats->pat, NULL);
+ if (convpat.pat != NULL)
+ {
+ pats = &convpat;
+ pats->len = (int)STRLEN(pats->pat);
+ prepare_pats(pats, has_re);
+ pats->regmatch.rm_ic = orgpat.regmatch.rm_ic;
+ }
+ }
+
+ /* Prepare for converting a match the other way around. */
+ convert_setup(&vimconv, lbuf + 20, p_enc);
+ continue;
+ }
+#endif
+
+ /*
+ * Figure out where the different strings are in this line.
+ * For "normal" tags: Do a quick check if the tag matches.
+ * This speeds up tag searching a lot!
+ */
+ if (pats->headlen
+#ifdef FEAT_EMACS_TAGS
+ && !is_etag
+#endif
+ )
+ {
+ tagp.tagname = lbuf;
+#ifdef FEAT_TAG_ANYWHITE
+ tagp.tagname_end = skiptowhite(lbuf);
+ if (*tagp.tagname_end == NUL) /* corrupted tag line */
+#else
+ tagp.tagname_end = vim_strchr(lbuf, TAB);
+ if (tagp.tagname_end == NULL) /* corrupted tag line */
+#endif
+ {
+ line_error = TRUE;
+ break;
+ }
+
+#ifdef FEAT_TAG_OLDSTATIC
+ /*
+ * Check for old style static tag: "file:tag file .."
+ */
+ tagp.fname = NULL;
+ for (p = lbuf; p < tagp.tagname_end; ++p)
+ {
+ if (*p == ':')
+ {
+ if (tagp.fname == NULL)
+#ifdef FEAT_TAG_ANYWHITE
+ tagp.fname = skipwhite(tagp.tagname_end);
+#else
+ tagp.fname = tagp.tagname_end + 1;
+#endif
+ if ( fnamencmp(lbuf, tagp.fname, p - lbuf) == 0
+#ifdef FEAT_TAG_ANYWHITE
+ && vim_iswhite(tagp.fname[p - lbuf])
+#else
+ && tagp.fname[p - lbuf] == TAB
+#endif
+ )
+ {
+ /* found one */
+ tagp.tagname = p + 1;
+ break;
+ }
+ }
+ }
+#endif
+
+ /*
+ * Skip this line if the length of the tag is different and
+ * there is no regexp, or the tag is too short.
+ */
+ cmplen = (int)(tagp.tagname_end - tagp.tagname);
+ if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */
+ cmplen = p_tl;
+ if (has_re && pats->headlen < cmplen)
+ cmplen = pats->headlen;
+ else if (state == TS_LINEAR && pats->headlen != cmplen)
+ continue;
+
+#ifdef FEAT_TAG_BINS
+ if (state == TS_BINARY)
+ {
+ /*
+ * Simplistic check for unsorted tags file.
+ */
+ i = (int)tagp.tagname[0];
+ if (sortic)
+ i = (int)TOUPPER_ASC(tagp.tagname[0]);
+ if (i < search_info.low_char || i > search_info.high_char)
+ sort_error = TRUE;
+
+ /*
+ * Compare the current tag with the searched tag.
+ */
+ if (sortic)
+ tagcmp = tag_strnicmp(tagp.tagname, pats->head,
+ (size_t)cmplen);
+ else
+ tagcmp = STRNCMP(tagp.tagname, pats->head, cmplen);
+
+ /*
+ * A match with a shorter tag means to search forward.
+ * A match with a longer tag means to search backward.
+ */
+ if (tagcmp == 0)
+ {
+ if (cmplen < pats->headlen)
+ tagcmp = -1;
+ else if (cmplen > pats->headlen)
+ tagcmp = 1;
+ }
+
+ if (tagcmp == 0)
+ {
+ /* We've located the tag, now skip back and search
+ * forward until the first matching tag is found.
+ */
+ state = TS_SKIP_BACK;
+ search_info.match_offset = search_info.curr_offset;
+ continue;
+ }
+ if (tagcmp < 0)
+ {
+ search_info.curr_offset = ftell(fp);
+ if (search_info.curr_offset < search_info.high_offset)
+ {
+ search_info.low_offset = search_info.curr_offset;
+ if (sortic)
+ search_info.low_char =
+ TOUPPER_ASC(tagp.tagname[0]);
+ else
+ search_info.low_char = tagp.tagname[0];
+ continue;
+ }
+ }
+ if (tagcmp > 0
+ && search_info.curr_offset != search_info.high_offset)
+ {
+ search_info.high_offset = search_info.curr_offset;
+ if (sortic)
+ search_info.high_char =
+ TOUPPER_ASC(tagp.tagname[0]);
+ else
+ search_info.high_char = tagp.tagname[0];
+ continue;
+ }
+
+ /* No match yet and are at the end of the binary search. */
+ break;
+ }
+ else if (state == TS_SKIP_BACK)
+ {
+ if (MB_STRNICMP(tagp.tagname, pats->head, cmplen) != 0)
+ state = TS_STEP_FORWARD;
+ else
+ /* Have to skip back more. Restore the curr_offset
+ * used, otherwise we get stuck at a long line. */
+ search_info.curr_offset = search_info.curr_offset_used;
+ continue;
+ }
+ else if (state == TS_STEP_FORWARD)
+ {
+ if (MB_STRNICMP(tagp.tagname, pats->head, cmplen) != 0)
+ {
+ if ((off_t)ftell(fp) > search_info.match_offset)
+ break; /* past last match */
+ else
+ continue; /* before first match */
+ }
+ }
+ else
+#endif
+ /* skip this match if it can't match */
+ if (MB_STRNICMP(tagp.tagname, pats->head, cmplen) != 0)
+ continue;
+
+ /*
+ * Can be a matching tag, isolate the file name and command.
+ */
+#ifdef FEAT_TAG_OLDSTATIC
+ if (tagp.fname == NULL)
+#endif
+#ifdef FEAT_TAG_ANYWHITE
+ tagp.fname = skipwhite(tagp.tagname_end);
+#else
+ tagp.fname = tagp.tagname_end + 1;
+#endif
+#ifdef FEAT_TAG_ANYWHITE
+ tagp.fname_end = skiptowhite(tagp.fname);
+ tagp.command = skipwhite(tagp.fname_end);
+ if (*tagp.command == NUL)
+#else
+ tagp.fname_end = vim_strchr(tagp.fname, TAB);
+ tagp.command = tagp.fname_end + 1;
+ if (tagp.fname_end == NULL)
+#endif
+ i = FAIL;
+ else
+ i = OK;
+ }
+ else
+ i = parse_tag_line(lbuf,
+#ifdef FEAT_EMACS_TAGS
+ is_etag,
+#endif
+ &tagp);
+ if (i == FAIL)
+ {
+ line_error = TRUE;
+ break;
+ }
+
+#ifdef FEAT_EMACS_TAGS
+ if (is_etag)
+ tagp.fname = ebuf;
+#endif
+ /*
+ * First try matching with the pattern literally (also when it is
+ * a regexp).
+ */
+ cmplen = (int)(tagp.tagname_end - tagp.tagname);
+ if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */
+ cmplen = p_tl;
+ /* if tag length does not match, don't try comparing */
+ if (pats->len != cmplen)
+ match = FALSE;
+ else
+ {
+ if (pats->regmatch.rm_ic)
+ {
+ match = (MB_STRNICMP(tagp.tagname, pats->pat, cmplen) == 0);
+ if (match)
+ match_no_ic = (STRNCMP(tagp.tagname, pats->pat,
+ cmplen) == 0);
+ }
+ else
+ match = (STRNCMP(tagp.tagname, pats->pat, cmplen) == 0);
+ }
+
+ /*
+ * Has a regexp: Also find tags matching regexp.
+ */
+ match_re = FALSE;
+ if (!match && pats->regmatch.regprog != NULL)
+ {
+ int cc;
+
+ cc = *tagp.tagname_end;
+ *tagp.tagname_end = NUL;
+ match = vim_regexec(&pats->regmatch, tagp.tagname, (colnr_T)0);
+ if (match)
+ {
+ matchoff = (int)(pats->regmatch.startp[0] - tagp.tagname);
+ if (pats->regmatch.rm_ic)
+ {
+ pats->regmatch.rm_ic = FALSE;
+ match_no_ic = vim_regexec(&pats->regmatch, tagp.tagname,
+ (colnr_T)0);
+ pats->regmatch.rm_ic = TRUE;
+ }
+ }
+ *tagp.tagname_end = cc;
+ match_re = TRUE;
+ }
+
+ /*
+ * If a match is found, add it to ga_match[].
+ */
+ if (match)
+ {
+#ifdef FEAT_CSCOPE
+ if (use_cscope)
+ {
+ /* Don't change the ordering, always use the same table. */
+ mtt = MT_GL_OTH;
+ }
+ else
+#endif
+ {
+ /* Decide in which array to store this match. */
+ is_current = test_for_current(
+#ifdef FEAT_EMACS_TAGS
+ is_etag,
+#endif
+ tagp.fname, tagp.fname_end, tag_fname,
+ buf_ffname);
+#ifdef FEAT_EMACS_TAGS
+ is_static = FALSE;
+ if (!is_etag) /* emacs tags are never static */
+#endif
+ {
+#ifdef FEAT_TAG_OLDSTATIC
+ if (tagp.tagname != lbuf)
+ is_static = TRUE; /* detected static tag before */
+ else
+#endif
+ is_static = test_for_static(&tagp);
+ }
+
+ /* decide in which of the sixteen tables to store this
+ * match */
+ if (is_static)
+ {
+ if (is_current)
+ mtt = MT_ST_CUR;
+ else
+ mtt = MT_ST_OTH;
+ }
+ else
+ {
+ if (is_current)
+ mtt = MT_GL_CUR;
+ else
+ mtt = MT_GL_OTH;
+ }
+ if (pats->regmatch.rm_ic && !match_no_ic)
+ mtt += MT_IC_OFF;
+ if (match_re)
+ mtt += MT_RE_OFF;
+ }
+
+ /*
+ * Add the found match in ga_match[mtt], avoiding duplicates.
+ * Store the info we need later, which depends on the kind of
+ * tags we are dealing with.
+ */
+ if (ga_grow(&ga_match[mtt], 1) == OK)
+ {
+#ifdef FEAT_MBYTE
+ char_u *conv_line = NULL;
+ char_u *lbuf_line = lbuf;
+
+ if (vimconv.vc_type != CONV_NONE)
+ {
+ /* Convert the tag line from the encoding of the tags
+ * file to 'encoding'. Then parse the line again. */
+ conv_line = string_convert(&vimconv, lbuf, NULL);
+ if (conv_line != NULL)
+ {
+ if (parse_tag_line(conv_line,
+#ifdef FEAT_EMACS_TAGS
+ is_etag,
+#endif
+ &tagp) == OK)
+ lbuf_line = conv_line;
+ else
+ /* doesn't work, go back to unconverted line. */
+ (void)parse_tag_line(lbuf,
+#ifdef FEAT_EMACS_TAGS
+ is_etag,
+#endif
+ &tagp);
+ }
+ }
+#else
+# define lbuf_line lbuf
+#endif
+ if (help_only)
+ {
+#ifdef FEAT_MULTI_LANG
+# define ML_EXTRA 3
+#else
+# define ML_EXTRA 0
+#endif
+ /*
+ * Append the help-heuristic number after the
+ * tagname, for sorting it later.
+ */
+ *tagp.tagname_end = NUL;
+ len = (int)(tagp.tagname_end - tagp.tagname);
+ mfp = (struct match_found *)
+ alloc((int)sizeof(struct match_found) + len
+ + 10 + ML_EXTRA);
+ if (mfp != NULL)
+ {
+ /* "len" includes the language and the NUL, but
+ * not the priority. */
+ mfp->len = len + ML_EXTRA + 1;
+#define ML_HELP_LEN 6
+ p = mfp->match;
+ STRCPY(p, tagp.tagname);
+#ifdef FEAT_MULTI_LANG
+ p[len] = '@';
+ STRCPY(p + len + 1, help_lang);
+#endif
+ sprintf((char *)p + len + 1 + ML_EXTRA, "%06d",
+ help_heuristic(tagp.tagname,
+ match_re ? matchoff : 0, !match_no_ic)
+#ifdef FEAT_MULTI_LANG
+ + help_pri
+#endif
+ );
+ }
+ *tagp.tagname_end = TAB;
+ }
+ else if (name_only)
+ {
+ if (get_it_again)
+ {
+ char_u *temp_end = tagp.command;
+
+ if (*temp_end == '/')
+ while (*temp_end && *temp_end != '\r'
+ && *temp_end != '\n'
+ && *temp_end != '$')
+ temp_end++;
+
+ if (tagp.command + 2 < temp_end)
+ {
+ len = (int)(temp_end - tagp.command - 2);
+ mfp = (struct match_found *)alloc(
+ (int)sizeof(struct match_found) + len);
+ if (mfp != NULL)
+ {
+ mfp->len = len + 1; /* include the NUL */
+ p = mfp->match;
+ STRNCPY(p, tagp.command + 2, len);
+ p[len] = NUL;
+ }
+ }
+ else
+ mfp = NULL;
+ get_it_again = FALSE;
+ }
+ else
+ {
+ len = (int)(tagp.tagname_end - tagp.tagname);
+ mfp = (struct match_found *)alloc(
+ (int)sizeof(struct match_found) + len);
+ if (mfp != NULL)
+ {
+ mfp->len = len + 1; /* include the NUL */
+ p = mfp->match;
+ STRNCPY(p, tagp.tagname, len);
+ p[len] = NUL;
+ }
+
+ /* if wanted, re-read line to get long form too */
+ if (State & INSERT)
+ get_it_again = p_sft;
+ }
+ }
+ else
+ {
+ /* Save the tag in a buffer.
+ * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf>
+ * other tag: <mtt><tag_fname><NUL><NUL><lbuf>
+ * without Emacs tags: <mtt><tag_fname><NUL><lbuf>
+ */
+ len = (int)STRLEN(tag_fname) + (int)STRLEN(lbuf_line) + 3;
+#ifdef FEAT_EMACS_TAGS
+ if (is_etag)
+ len += (int)STRLEN(ebuf) + 1;
+ else
+ ++len;
+#endif
+ mfp = (struct match_found *)alloc(
+ (int)sizeof(struct match_found) + len);
+ if (mfp != NULL)
+ {
+ mfp->len = len;
+ p = mfp->match;
+ p[0] = mtt;
+ STRCPY(p + 1, tag_fname);
+#ifdef BACKSLASH_IN_FILENAME
+ /* Ignore differences in slashes, avoid adding
+ * both path/file and path\file. */
+ slash_adjust(p + 1);
+#endif
+ s = p + 1 + STRLEN(tag_fname) + 1;
+#ifdef FEAT_EMACS_TAGS
+ if (is_etag)
+ {
+ STRCPY(s, ebuf);
+ s += STRLEN(ebuf) + 1;
+ }
+ else
+ *s++ = NUL;
+#endif
+ STRCPY(s, lbuf_line);
+ }
+ }
+
+ if (mfp != NULL)
+ {
+ /*
+ * Don't add identical matches.
+ * This can take a lot of time when finding many
+ * matches, check for CTRL-C now and then.
+ * Add all cscope tags, because they are all listed.
+ */
+#ifdef FEAT_CSCOPE
+ if (use_cscope)
+ i = -1;
+ else
+#endif
+ for (i = ga_match[mtt].ga_len; --i >= 0 && !got_int; )
+ {
+ mfp2 = ((struct match_found **)
+ (ga_match[mtt].ga_data))[i];
+ if (mfp2->len == mfp->len
+ && vim_memcmp(mfp2->match, mfp->match,
+ (size_t)mfp->len) == 0)
+ break;
+ line_breakcheck();
+ }
+ if (i < 0)
+ {
+ ((struct match_found **)(ga_match[mtt].ga_data))
+ [ga_match[mtt].ga_len++] = mfp;
+ ga_match[mtt].ga_room--;
+ ++match_count;
+ }
+ else
+ vim_free(mfp);
+ }
+#ifdef FEAT_MBYTE
+ /* Note: this makes the values in "tagp" invalid! */
+ vim_free(conv_line);
+#endif
+ }
+ else /* Out of memory! Just forget about the rest. */
+ {
+ retval = OK;
+ stop_searching = TRUE;
+ break;
+ }
+ }
+#ifdef FEAT_CSCOPE
+ if (use_cscope && eof)
+ break;
+#endif
+ } /* forever */
+
+ if (line_error)
+ {
+ EMSG2(_("E431: Format error in tags file \"%s\""), tag_fname);
+#ifdef FEAT_CSCOPE
+ if (!use_cscope)
+#endif
+ EMSGN(_("Before byte %ld"), (long)ftell(fp));
+ stop_searching = TRUE;
+ line_error = FALSE;
+ }
+
+#ifdef FEAT_CSCOPE
+ if (!use_cscope)
+#endif
+ fclose(fp);
+#ifdef FEAT_EMACS_TAGS
+ while (incstack_idx)
+ {
+ --incstack_idx;
+ fclose(incstack[incstack_idx].fp);
+ vim_free(incstack[incstack_idx].etag_fname);
+ }
+#endif
+#ifdef FEAT_MBYTE
+ if (pats == &convpat)
+ {
+ /* Go back from converted pattern to original pattern. */
+ vim_free(pats->pat);
+ vim_free(pats->regmatch.regprog);
+ orgpat.regmatch.rm_ic = pats->regmatch.rm_ic;
+ pats = &orgpat;
+ }
+ if (vimconv.vc_type != CONV_NONE)
+ convert_setup(&vimconv, NULL, NULL);
+#endif
+
+#ifdef FEAT_TAG_BINS
+ if (sort_error)
+ {
+ EMSG2(_("E432: Tags file not sorted: %s"), tag_fname);
+ sort_error = FALSE;
+ }
+#endif
+
+ /*
+ * Stop searching if sufficient tags have been found.
+ */
+ if (match_count >= mincount)
+ {
+ retval = OK;
+ stop_searching = TRUE;
+ }
+
+#ifdef FEAT_CSCOPE
+ if (stop_searching || use_cscope)
+#else
+ if (stop_searching)
+#endif
+ break;
+
+ } /* end of for-each-file loop */
+
+#ifdef FEAT_TAG_BINS
+ /* stop searching when already did a linear search, or when
+ * TAG_NOIC used, and 'ignorecase' not set
+ * or already did case-ignore search */
+ if (stop_searching || linear || (!p_ic && noic) || pats->regmatch.rm_ic)
+ break;
+# ifdef FEAT_CSCOPE
+ if (use_cscope)
+ break;
+# endif
+ pats->regmatch.rm_ic = TRUE; /* try another time while ignoring case */
+ }
+#endif
+
+ if (!stop_searching)
+ {
+ if (!did_open && verbose) /* never opened any tags file */
+ EMSG(_("E433: No tags file"));
+ retval = OK; /* It's OK even when no tag found */
+ }
+
+findtag_end:
+ vim_free(lbuf);
+ vim_free(pats->regmatch.regprog);
+ vim_free(tag_fname);
+#ifdef FEAT_EMACS_TAGS
+ vim_free(ebuf);
+#endif
+
+ /*
+ * Move the matches from the ga_match[] arrays into one list of
+ * matches. When retval == FAIL, free the matches.
+ */
+ if (retval == FAIL)
+ match_count = 0;
+
+ if (match_count > 0)
+ matches = (char_u **)lalloc((long_u)(match_count * sizeof(char_u *)),
+ TRUE);
+ else
+ matches = NULL;
+ match_count = 0;
+ for (mtt = 0; mtt < MT_COUNT; ++mtt)
+ {
+ for (i = 0; i < ga_match[mtt].ga_len; ++i)
+ {
+ mfp = ((struct match_found **)(ga_match[mtt].ga_data))[i];
+ if (matches == NULL)
+ vim_free(mfp);
+ else
+ {
+ /* To avoid allocating memory again we turn the struct
+ * match_found into a string. For help the priority was not
+ * included in the length. */
+ mch_memmove(mfp, mfp->match,
+ (size_t)(mfp->len + (help_only ? ML_HELP_LEN : 0)));
+ matches[match_count++] = (char_u *)mfp;
+ }
+ }
+ ga_clear(&ga_match[mtt]);
+ }
+
+ *matchesp = matches;
+ *num_matches = match_count;
+
+ curbuf->b_help = help_save;
+#ifdef FEAT_MULTI_LANG
+ vim_free(saved_pat);
+#endif
+
+ return retval;
+}
+
+static garray_T tag_fnames = GA_EMPTY;
+static void found_tagfile_cb __ARGS((char_u *fname));
+
+/*
+ * Callback function for finding all "tags" and "tags-??" files in
+ * 'runtimepath' doc directories.
+ */
+ static void
+found_tagfile_cb(fname)
+ char_u *fname;
+{
+ if (ga_grow(&tag_fnames, 1) == OK)
+ {
+ ((char_u **)(tag_fnames.ga_data))[tag_fnames.ga_len++] =
+ vim_strsave(fname);
+ --tag_fnames.ga_room;
+ }
+}
+
+/*
+ * Get the next name of a tag file from the tag file list.
+ * For help files, use "tags" file only.
+ *
+ * Return FAIL if no more tag file names, OK otherwise.
+ */
+ static int
+get_tagfname(first, buf)
+ int first; /* TRUE when first file name is wanted */
+ char_u *buf; /* pointer to buffer of MAXPATHL chars */
+{
+ static void *search_ctx = NULL;
+ static char_u *np = NULL;
+ static int did_filefind_init;
+ static int hf_idx = 0;
+ char_u *fname = NULL;
+ char_u *r_ptr;
+
+ if (first)
+ {
+ if (curbuf->b_help)
+ {
+ /*
+ * For a help window find "doc/tags" and "doc/tags-??" in all
+ * directories in 'runtimepath'.
+ */
+ ga_clear_strings(&tag_fnames);
+ ga_init2(&tag_fnames, (int)sizeof(char_u *), 10);
+ do_in_runtimepath((char_u *)
+#ifdef FEAT_MULTI_LANG
+ "doc/tags doc/tags-??"
+#else
+ "doc/tags"
+#endif
+ , TRUE, found_tagfile_cb);
+ hf_idx = 0;
+ }
+ else if (*curbuf->b_p_tags != NUL)
+ np = curbuf->b_p_tags;
+ else
+ np = p_tags;
+ vim_findfile_free_visited(search_ctx);
+ did_filefind_init = FALSE;
+ }
+
+ if (curbuf->b_help)
+ {
+ if (hf_idx >= tag_fnames.ga_len)
+ {
+ /* Not found in 'runtimepath', use 'helpfile', if it exists and
+ * wasn't used yet, replacing "help.txt" with "tags". */
+ if (hf_idx > tag_fnames.ga_len || *p_hf == NUL)
+ return FAIL;
+ ++hf_idx;
+ STRCPY(buf, p_hf);
+ STRCPY(gettail(buf), "tags");
+ }
+ else
+ {
+ STRNCPY(buf, ((char_u **)(tag_fnames.ga_data))[hf_idx++], MAXPATHL);
+ buf[MAXPATHL - 1] = NUL;
+ }
+ }
+ else
+ {
+ /* tried already (or bogus call) */
+ if (np == NULL)
+ return FAIL;
+
+ /*
+ * Loop until we have found a file name that can be used.
+ * There are two states:
+ * did_filefind_init == FALSE: setup for next part in 'tags'.
+ * did_filefind_init == TRUE: find next file in this part.
+ */
+ for (;;)
+ {
+ if (did_filefind_init)
+ {
+ fname = vim_findfile(search_ctx);
+ if (fname != NULL)
+ break;
+
+ did_filefind_init = FALSE;
+ }
+ else
+ {
+ char_u *filename = NULL;
+
+ /* Stop when used all parts of 'tags'. */
+ if (*np == NUL)
+ {
+ vim_findfile_cleanup(search_ctx);
+ search_ctx = NULL;
+ return FAIL;
+ }
+
+ /*
+ * Copy next file name into buf.
+ */
+ buf[0] = NUL;
+ (void)copy_option_part(&np, buf, MAXPATHL - 1, " ,");
+
+#ifdef FEAT_PATH_EXTRA
+ r_ptr = vim_findfile_stopdir(buf);
+#else
+ r_ptr = NULL;
+#endif
+ /* move the filename one char forward and truncate the
+ * filepath with a NUL */
+ filename = gettail(buf);
+ mch_memmove(filename + 1, filename, STRLEN(filename) + 1);
+ *filename++ = NUL;
+
+ search_ctx = vim_findfile_init(buf, filename, r_ptr, 100,
+ FALSE, /* don't free visited list */
+ FALSE, /* we search for a file */
+ search_ctx, TRUE, curbuf->b_ffname);
+ if (search_ctx != NULL)
+ did_filefind_init = TRUE;
+ }
+ }
+ STRCPY(buf, fname);
+ vim_free(fname);
+ }
+
+ return OK;
+}
+
+/*
+ * Parse one line from the tags file. Find start/end of tag name, start/end of
+ * file name and start of search pattern.
+ *
+ * If is_etag is TRUE, tagp->fname and tagp->fname_end are not set.
+ *
+ * Return FAIL if there is a format error in this line, OK otherwise.
+ */
+ static int
+parse_tag_line(lbuf,
+#ifdef FEAT_EMACS_TAGS
+ is_etag,
+#endif
+ tagp)
+ char_u *lbuf; /* line to be parsed */
+#ifdef FEAT_EMACS_TAGS
+ int is_etag;
+#endif
+ tagptrs_T *tagp;
+{
+ char_u *p;
+
+#ifdef FEAT_EMACS_TAGS
+ char_u *p_7f;
+
+ if (is_etag)
+ {
+ /*
+ * There are two formats for an emacs tag line:
+ * 1: struct EnvBase ^?EnvBase^A139,4627
+ * 2: #define ARPB_WILD_WORLD ^?153,5194
+ */
+ p_7f = vim_strchr(lbuf, 0x7f);
+ if (p_7f == NULL)
+ return FAIL;
+
+ /* Find ^A. If not found the line number is after the 0x7f */
+ p = vim_strchr(p_7f, Ctrl_A);
+ if (p == NULL)
+ p = p_7f + 1;
+ else
+ ++p;
+
+ if (!VIM_ISDIGIT(*p)) /* check for start of line number */
+ return FAIL;
+ tagp->command = p;
+
+
+ if (p[-1] == Ctrl_A) /* first format: explicit tagname given */
+ {
+ tagp->tagname = p_7f + 1;
+ tagp->tagname_end = p - 1;
+ }
+ else /* second format: isolate tagname */
+ {
+ /* find end of tagname */
+ for (p = p_7f - 1; !vim_iswordc(*p); --p)
+ if (p == lbuf)
+ return FAIL;
+ tagp->tagname_end = p + 1;
+ while (p >= lbuf && vim_iswordc(*p))
+ --p;
+ tagp->tagname = p + 1;
+ }
+ }
+ else /* not an Emacs tag */
+ {
+#endif
+ /* Isolate the tagname, from lbuf up to the first white */
+ tagp->tagname = lbuf;
+#ifdef FEAT_TAG_ANYWHITE
+ p = skiptowhite(lbuf);
+#else
+ p = vim_strchr(lbuf, TAB);
+ if (p == NULL)
+ return FAIL;
+#endif
+ tagp->tagname_end = p;
+
+ /* Isolate file name, from first to second white space */
+#ifdef FEAT_TAG_ANYWHITE
+ p = skipwhite(p);
+#else
+ if (*p != NUL)
+ ++p;
+#endif
+ tagp->fname = p;
+#ifdef FEAT_TAG_ANYWHITE
+ p = skiptowhite(p);
+#else
+ p = vim_strchr(p, TAB);
+ if (p == NULL)
+ return FAIL;
+#endif
+ tagp->fname_end = p;
+
+ /* find start of search command, after second white space */
+#ifdef FEAT_TAG_ANYWHITE
+ p = skipwhite(p);
+#else
+ if (*p != NUL)
+ ++p;
+#endif
+ if (*p == NUL)
+ return FAIL;
+ tagp->command = p;
+#ifdef FEAT_EMACS_TAGS
+ }
+#endif
+
+ return OK;
+}
+
+/*
+ * Check if tagname is a static tag
+ *
+ * Static tags produced by the older ctags program have the format:
+ * 'file:tag file /pattern'.
+ * This is only recognized when both occurences of 'file' are the same, to
+ * avoid recognizing "string::string" or ":exit".
+ *
+ * Static tags produced by the new ctags program have the format:
+ * 'tag file /pattern/;"<Tab>file:' "
+ *
+ * Return TRUE if it is a static tag and adjust *tagname to the real tag.
+ * Return FALSE if it is not a static tag.
+ */
+ static int
+test_for_static(tagp)
+ tagptrs_T *tagp;
+{
+ char_u *p;
+
+#ifdef FEAT_TAG_OLDSTATIC
+ int len;
+
+ /*
+ * Check for old style static tag: "file:tag file .."
+ */
+ len = (int)(tagp->fname_end - tagp->fname);
+ p = tagp->tagname + len;
+ if ( p < tagp->tagname_end
+ && *p == ':'
+ && fnamencmp(tagp->tagname, tagp->fname, len) == 0)
+ {
+ tagp->tagname = p + 1;
+ return TRUE;
+ }
+#endif
+
+ /*
+ * Check for new style static tag ":...<Tab>file:[<Tab>...]"
+ */
+ p = tagp->command;
+ while ((p = vim_strchr(p, '\t')) != NULL)
+ {
+ ++p;
+ if (STRNCMP(p, "file:", 5) == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * Parse a line from a matching tag. Does not change the line itself.
+ *
+ * The line that we get looks like this:
+ * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf>
+ * other tag: <mtt><tag_fname><NUL><NUL><lbuf>
+ * without Emacs tags: <mtt><tag_fname><NUL><lbuf>
+ *
+ * Return OK or FAIL.
+ */
+ static int
+parse_match(lbuf, tagp)
+ char_u *lbuf; /* input: matching line */
+ tagptrs_T *tagp; /* output: pointers into the line */
+{
+ int retval;
+ char_u *p;
+ char_u *pc, *pt;
+
+ tagp->tag_fname = lbuf + 1;
+ lbuf += STRLEN(tagp->tag_fname) + 2;
+#ifdef FEAT_EMACS_TAGS
+ if (*lbuf)
+ {
+ tagp->is_etag = TRUE;
+ tagp->fname = lbuf;
+ lbuf += STRLEN(lbuf);
+ tagp->fname_end = lbuf++;
+ }
+ else
+ {
+ tagp->is_etag = FALSE;
+ ++lbuf;
+ }
+#endif
+
+ /* Find search pattern and the file name for non-etags. */
+ retval = parse_tag_line(lbuf,
+#ifdef FEAT_EMACS_TAGS
+ tagp->is_etag,
+#endif
+ tagp);
+
+ tagp->tagkind = NULL;
+ tagp->command_end = NULL;
+
+ if (retval == OK)
+ {
+ /* Try to find a kind field: "kind:<kind>" or just "<kind>"*/
+ p = tagp->command;
+ if (find_extra(&p) == OK)
+ {
+ tagp->command_end = p;
+ p += 2; /* skip ";\"" */
+ if (*p++ == TAB)
+ while (ASCII_ISALPHA(*p))
+ {
+ if (STRNCMP(p, "kind:", 5) == 0)
+ {
+ tagp->tagkind = p + 5;
+ break;
+ }
+ pc = vim_strchr(p, ':');
+ pt = vim_strchr(p, '\t');
+ if (pc == NULL || (pt != NULL && pc > pt))
+ {
+ tagp->tagkind = p;
+ break;
+ }
+ if (pt == NULL)
+ break;
+ p = pt + 1;
+ }
+ }
+ if (tagp->tagkind != NULL)
+ {
+ for (p = tagp->tagkind;
+ *p && *p != '\t' && *p != '\r' && *p != '\n'; ++p)
+ ;
+ tagp->tagkind_end = p;
+ }
+ }
+ return retval;
+}
+
+/*
+ * Find out the actual file name of a tag. Concatenate the tags file name
+ * with the matching tag file name.
+ * Returns an allocated string or NULL (out of memory).
+ */
+ static char_u *
+tag_full_fname(tagp)
+ tagptrs_T *tagp;
+{
+ char_u *fullname;
+ int c;
+
+#ifdef FEAT_EMACS_TAGS
+ if (tagp->is_etag)
+ c = 0; /* to shut up GCC */
+ else
+#endif
+ {
+ c = *tagp->fname_end;
+ *tagp->fname_end = NUL;
+ }
+ fullname = expand_tag_fname(tagp->fname, tagp->tag_fname, FALSE);
+
+#ifdef FEAT_EMACS_TAGS
+ if (!tagp->is_etag)
+#endif
+ *tagp->fname_end = c;
+
+ return fullname;
+}
+
+/*
+ * Jump to a tag that has been found in one of the tag files
+ *
+ * returns OK for success, NOTAGFILE when file not found, FAIL otherwise.
+ */
+ static int
+jumpto_tag(lbuf, forceit, keep_help)
+ char_u *lbuf; /* line from the tags file for this tag */
+ int forceit; /* :ta with ! */
+ int keep_help; /* keep help flag (FALSE for cscope) */
+{
+ int save_secure;
+ int save_magic;
+ int save_p_ws, save_p_scs, save_p_ic;
+ linenr_T save_lnum;
+ int csave = 0;
+ char_u *str;
+ char_u *pbuf; /* search pattern buffer */
+ char_u *pbuf_end;
+ char_u *tofree_fname = NULL;
+ char_u *fname;
+ tagptrs_T tagp;
+ int retval = FAIL;
+ int getfile_result;
+ int search_options;
+#ifdef FEAT_SEARCH_EXTRA
+ int save_no_hlsearch;
+#endif
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ win_T *curwin_save = NULL;
+#endif
+ char_u *full_fname = NULL;
+#ifdef FEAT_FOLDING
+ int old_KeyTyped = KeyTyped; /* getting the file may reset it */
+#endif
+
+ pbuf = alloc(LSIZE);
+
+ /* parse the match line into the tagp structure */
+ if (pbuf == NULL || parse_match(lbuf, &tagp) == FAIL)
+ {
+ tagp.fname_end = NULL;
+ goto erret;
+ }
+
+ /* truncate the file name, so it can be used as a string */
+ csave = *tagp.fname_end;
+ *tagp.fname_end = NUL;
+ fname = tagp.fname;
+
+ /* copy the command to pbuf[], remove trailing CR/NL */
+ str = tagp.command;
+ for (pbuf_end = pbuf; *str && *str != '\n' && *str != '\r'; )
+ {
+#ifdef FEAT_EMACS_TAGS
+ if (tagp.is_etag && *str == ',')/* stop at ',' after line number */
+ break;
+#endif
+ *pbuf_end++ = *str++;
+ }
+ *pbuf_end = NUL;
+
+#ifdef FEAT_EMACS_TAGS
+ if (!tagp.is_etag)
+#endif
+ {
+ /*
+ * Remove the "<Tab>fieldname:value" stuff; we don't need it here.
+ */
+ str = pbuf;
+ if (find_extra(&str) == OK)
+ {
+ pbuf_end = str;
+ *pbuf_end = NUL;
+ }
+ }
+
+ /*
+ * Expand file name, when needed (for environment variables).
+ * If 'tagrelative' option set, may change file name.
+ */
+ fname = expand_tag_fname(fname, tagp.tag_fname, TRUE);
+ if (fname == NULL)
+ goto erret;
+ tofree_fname = fname; /* free() it later */
+
+ /*
+ * Check if the file with the tag exists before abandoning the current
+ * file. Also accept a file name for which there is a matching BufReadCmd
+ * autocommand event (e.g., http://sys/file).
+ */
+ if (mch_getperm(fname) < 0
+#ifdef FEAT_AUTOCMD
+ && !has_autocmd(EVENT_BUFREADCMD, fname)
+#endif
+ )
+ {
+ retval = NOTAGFILE;
+ vim_free(nofile_fname);
+ nofile_fname = vim_strsave(fname);
+ if (nofile_fname == NULL)
+ nofile_fname = empty_option;
+ goto erret;
+ }
+
+ ++RedrawingDisabled;
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ if (g_do_tagpreview)
+ {
+ /* don't split again below */
+ postponed_split = 0;
+ /* Save current window */
+ curwin_save = curwin;
+ /*
+ * If we are reusing a window, we may change dir when
+ * entering it (autocommands) so turn the tag filename
+ * into a fullpath
+ */
+ if (!curwin->w_p_pvw)
+ {
+ full_fname = FullName_save(fname, FALSE);
+ fname = full_fname;
+
+ /*
+ * Make the preview window the current window.
+ * Open a preview window when needed.
+ */
+ prepare_tagpreview();
+ }
+ }
+
+ /* if it was a CTRL-W CTRL-] command split window now */
+ if (postponed_split)
+ {
+ win_split(postponed_split > 0 ? postponed_split : 0,
+ postponed_split_flags);
+# ifdef FEAT_SCROLLBIND
+ curwin->w_p_scb = FALSE;
+# endif
+ }
+#endif
+
+ if (keep_help)
+ {
+ /* A :ta from a help file will keep the b_help flag set. For ":ptag"
+ * we need to use the flag from the window where we came from. */
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ if (g_do_tagpreview)
+ keep_help_flag = curwin_save->w_buffer->b_help;
+ else
+#endif
+ keep_help_flag = curbuf->b_help;
+ }
+ getfile_result = getfile(0, fname, NULL, TRUE, (linenr_T)0, forceit);
+ keep_help_flag = FALSE;
+
+ if (getfile_result <= 0) /* got to the right file */
+ {
+ curwin->w_set_curswant = TRUE;
+#ifdef FEAT_WINDOWS
+ postponed_split = 0;
+#endif
+
+ save_secure = secure;
+ secure = 1;
+#ifdef HAVE_SANDBOX
+ ++sandbox;
+#endif
+ save_magic = p_magic;
+ p_magic = FALSE; /* always execute with 'nomagic' */
+#ifdef FEAT_SEARCH_EXTRA
+ /* Save value of no_hlsearch, jumping to a tag is not a real search */
+ save_no_hlsearch = no_hlsearch;
+#endif
+
+ /*
+ * If 'cpoptions' contains 't', store the search pattern for the "n"
+ * command. If 'cpoptions' does not contain 't', the search pattern
+ * is not stored.
+ */
+ if (vim_strchr(p_cpo, CPO_TAGPAT) != NULL)
+ search_options = 0;
+ else
+ search_options = SEARCH_KEEP;
+
+ /*
+ * If the command is a search, try here.
+ *
+ * Reset 'smartcase' for the search, since the search pattern was not
+ * typed by the user.
+ * Only use do_search() when there is a full search command, without
+ * anything following.
+ */
+ str = pbuf;
+ if (pbuf[0] == '/' || pbuf[0] == '?')
+ str = skip_regexp(pbuf + 1, pbuf[0], FALSE, NULL) + 1;
+ if (str > pbuf_end - 1) /* search command with nothing following */
+ {
+ save_p_ws = p_ws;
+ save_p_ic = p_ic;
+ save_p_scs = p_scs;
+ p_ws = TRUE; /* need 'wrapscan' for backward searches */
+ p_ic = FALSE; /* don't ignore case now */
+ p_scs = FALSE;
+#if 0 /* disabled for now */
+#ifdef FEAT_CMDHIST
+ /* put pattern in search history */
+ add_to_history(HIST_SEARCH, pbuf + 1, TRUE, pbuf[0]);
+#endif
+#endif
+ save_lnum = curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum = 0; /* start search before first line */
+ if (do_search(NULL, pbuf[0], pbuf + 1, (long)1, search_options))
+ retval = OK;
+ else
+ {
+ int found = 1;
+ int cc;
+
+ /*
+ * try again, ignore case now
+ */
+ p_ic = TRUE;
+ if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1,
+ search_options))
+ {
+ /*
+ * Failed to find pattern, take a guess: "^func ("
+ */
+ found = 2;
+ (void)test_for_static(&tagp);
+ cc = *tagp.tagname_end;
+ *tagp.tagname_end = NUL;
+ sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname);
+ if (!do_search(NULL, '/', pbuf, (long)1, search_options))
+ {
+ /* Guess again: "^char * \<func (" */
+ sprintf((char *)pbuf, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
+ tagp.tagname);
+ if (!do_search(NULL, '/', pbuf, (long)1,
+ search_options))
+ found = 0;
+ }
+ *tagp.tagname_end = cc;
+ }
+ if (found == 0)
+ {
+ EMSG(_("E434: Can't find tag pattern"));
+ curwin->w_cursor.lnum = save_lnum;
+ }
+ else
+ {
+ /*
+ * Only give a message when really guessed, not when 'ic'
+ * is set and match found while ignoring case.
+ */
+ if (found == 2 || !save_p_ic)
+ {
+ MSG(_("E435: Couldn't find tag, just guessing!"));
+ if (!msg_scrolled && msg_silent == 0)
+ {
+ out_flush();
+ ui_delay(1000L, TRUE);
+ }
+ }
+ retval = OK;
+ }
+ }
+ p_ws = save_p_ws;
+ p_ic = save_p_ic;
+ p_scs = save_p_scs;
+
+ /* A search command may have positioned the cursor beyond the end
+ * of the line. May need to correct that here. */
+ check_cursor();
+ }
+ else
+ {
+ curwin->w_cursor.lnum = 1; /* start command in line 1 */
+ do_cmdline_cmd(pbuf);
+ retval = OK;
+ }
+
+ /*
+ * When the command has done something that is not allowed make sure
+ * the error message can be seen.
+ */
+ if (secure == 2)
+ wait_return(TRUE);
+ secure = save_secure;
+ p_magic = save_magic;
+#ifdef HAVE_SANDBOX
+ --sandbox;
+#endif
+#ifdef FEAT_SEARCH_EXTRA
+ /* restore no_hlsearch when keeping the old search pattern */
+ if (search_options)
+ no_hlsearch = save_no_hlsearch;
+#endif
+
+ /* Return OK if jumped to another file (at least we found the file!). */
+ if (getfile_result == -1)
+ retval = OK;
+
+ if (retval == OK)
+ {
+ /*
+ * For a help buffer: Put the cursor line at the top of the window,
+ * the help subject will be below it.
+ */
+ if (curbuf->b_help)
+ set_topline(curwin, curwin->w_cursor.lnum);
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_TAG) && old_KeyTyped)
+ foldOpenCursor();
+#endif
+ }
+
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ if (g_do_tagpreview && curwin != curwin_save && win_valid(curwin_save))
+ {
+ /* Return cursor to where we were */
+ validate_cursor();
+ redraw_later(VALID);
+ win_enter(curwin_save, TRUE);
+ }
+#endif
+
+ --RedrawingDisabled;
+ }
+ else
+ {
+ --RedrawingDisabled;
+#ifdef FEAT_WINDOWS
+ if (postponed_split) /* close the window */
+ {
+ win_close(curwin, FALSE);
+ postponed_split = 0;
+ }
+#endif
+ }
+
+erret:
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+ g_do_tagpreview = 0; /* For next time */
+#endif
+ if (tagp.fname_end != NULL)
+ *tagp.fname_end = csave;
+ vim_free(pbuf);
+ vim_free(tofree_fname);
+ vim_free(full_fname);
+
+ return retval;
+}
+
+/*
+ * If "expand" is TRUE, expand wildcards in fname.
+ * If 'tagrelative' option set, change fname (name of file containing tag)
+ * according to tag_fname (name of tag file containing fname).
+ * Returns a pointer to allocated memory (or NULL when out of memory).
+ */
+ static char_u *
+expand_tag_fname(fname, tag_fname, expand)
+ char_u *fname;
+ char_u *tag_fname;
+ int expand;
+{
+ char_u *p;
+ char_u *retval;
+ char_u *expanded_fname = NULL;
+ expand_T xpc;
+
+ /*
+ * Expand file name (for environment variables) when needed.
+ */
+ if (expand && mch_has_wildcard(fname))
+ {
+ ExpandInit(&xpc);
+ xpc.xp_context = EXPAND_FILES;
+ expanded_fname = ExpandOne(&xpc, (char_u *)fname, NULL,
+ WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
+ ExpandCleanup(&xpc);
+ if (expanded_fname != NULL)
+ fname = expanded_fname;
+ }
+
+ if ((p_tr || curbuf->b_help)
+ && !vim_isAbsName(fname)
+ && (p = gettail(tag_fname)) != tag_fname)
+ {
+ retval = alloc(MAXPATHL);
+ if (retval != NULL)
+ {
+ STRCPY(retval, tag_fname);
+ STRNCPY(retval + (p - tag_fname), fname,
+ MAXPATHL - (p - tag_fname));
+ /*
+ * Translate names like "src/a/../b/file.c" into "src/b/file.c".
+ */
+ simplify_filename(retval);
+ }
+ }
+ else
+ retval = vim_strsave(fname);
+
+ vim_free(expanded_fname);
+
+ return retval;
+}
+
+/*
+ * Moves the tail part of the path (including the terminating NUL) pointed to
+ * by "tail" to the new location pointed to by "here". This should accomodate
+ * an overlapping move.
+ */
+#define movetail(here, tail) mch_memmove(here, tail, STRLEN(tail) + (size_t)1)
+
+/*
+ * Converts a file name into a canonical form. It simplifies a file name into
+ * its simplest form by stripping out unneeded components, if any. The
+ * resulting file name is simplified in place and will either be the same
+ * length as that supplied, or shorter.
+ */
+ void
+simplify_filename(filename)
+ char_u *filename;
+{
+#ifndef AMIGA /* Amiga doesn't have "..", it uses "/" */
+ int components = 0;
+ char_u *p, *tail, *start;
+ int stripping_disabled = FALSE;
+ int relative = TRUE;
+
+ p = filename;
+#ifdef BACKSLASH_IN_FILENAME
+ if (p[1] == ':') /* skip "x:" */
+ p += 2;
+#endif
+
+ if (vim_ispathsep(*p))
+ {
+ relative = FALSE;
+ do
+ ++p;
+ while (vim_ispathsep(*p));
+ }
+ start = p; /* remember start after "c:/" or "/" or "///" */
+
+ do
+ {
+ /* At this point "p" is pointing to the char following a single "/"
+ * or "p" is at the "start" of the (absolute or relative) path name. */
+#ifdef VMS
+ /* VMS allows device:[path] - don't strip the [ in directory */
+ if ((*p == '[' || *p == '<') && p > filename && p[-1] == ':')
+ {
+ /* :[ or :< composition: vms directory component */
+ ++components;
+ p = getnextcomp(p + 1);
+ }
+ /* allow remote calls as host"user passwd"::device:[path] */
+ else if (p[0] == ':' && p[1] == ':' && p > filename && p[-1] == '"' )
+ {
+ /* ":: composition: vms host/passwd component */
+ ++components;
+ p = getnextcomp(p + 2);
+ }
+ else
+#endif
+ if (vim_ispathsep(*p))
+ movetail(p, p + 1); /* remove duplicate "/" */
+ else if (p[0] == '.' && (vim_ispathsep(p[1]) || p[1] == NUL))
+ {
+ if (p == start && relative)
+ p += 1 + (p[1] != NUL); /* keep single "." or leading "./" */
+ else
+ {
+ /* Strip "./" or ".///". If we are at the end of the file name
+ * and there is no trailing path separator, either strip "/." if
+ * we are after "start", or strip "." if we are at the beginning
+ * of an absolute path name . */
+ tail = p + 1;
+ if (p[1] != NUL)
+ while (vim_ispathsep(*tail))
+ ++tail;
+ else if (p > start)
+ --p; /* strip preceding path separator */
+ movetail(p, tail);
+ }
+ }
+ else if (p[0] == '.' && p[1] == '.' &&
+ (vim_ispathsep(p[2]) || p[2] == NUL))
+ {
+ /* Skip to after ".." or "../" or "..///". */
+ tail = p + 2;
+ while (vim_ispathsep(*tail))
+ ++tail;
+
+ if (components > 0) /* strip one preceding component */
+ {
+ int do_strip = FALSE;
+ char_u saved_char;
+ struct stat st;
+
+ /* Don't strip for an erroneous file name. */
+ if (!stripping_disabled)
+ {
+ /* If the preceding component does not exist in the file
+ * system, we strip it. On Unix, we don't accept a symbolic
+ * link that refers to a non-existent file. */
+ saved_char = p[-1];
+ p[-1] = NUL;
+#ifdef UNIX
+ if (mch_lstat((char *)filename, &st) < 0)
+#else
+ if (mch_stat((char *)filename, &st) < 0)
+#endif
+ do_strip = TRUE;
+ p[-1] = saved_char;
+
+ --p;
+ /* Skip back to after previous '/'. */
+ while (p > start && !vim_ispathsep(p[-1]))
+ --p;
+
+ if (!do_strip)
+ {
+ /* If the component exists in the file system, check
+ * that stripping it won't change the meaning of the
+ * file name. First get information about the
+ * unstripped file name. This may fail if the component
+ * to strip is not a searchable directory (but a regular
+ * file, for instance), since the trailing "/.." cannot
+ * be applied then. We don't strip it then since we
+ * don't want to replace an erroneous file name by
+ * a valid one, and we disable stripping of later
+ * components. */
+ saved_char = *tail;
+ *tail = NUL;
+ if (mch_stat((char *)filename, &st) >= 0)
+ do_strip = TRUE;
+ else
+ stripping_disabled = TRUE;
+ *tail = saved_char;
+#ifdef UNIX
+ if (do_strip)
+ {
+ struct stat new_st;
+
+ /* On Unix, the check for the unstripped file name
+ * above works also for a symbolic link pointing to
+ * a searchable directory. But then the parent of
+ * the directory pointed to by the link must be the
+ * same as the stripped file name. (The latter
+ * exists in the file system since it is the
+ * component's parent directory.) */
+ if (p == start && relative)
+ (void)mch_stat(".", &new_st);
+ else
+ {
+ saved_char = *p;
+ *p = NUL;
+ (void)mch_stat((char *)filename, &new_st);
+ *p = saved_char;
+ }
+
+ if (new_st.st_ino != st.st_ino ||
+ new_st.st_dev != st.st_dev)
+ {
+ do_strip = FALSE;
+ /* We don't disable stripping of later
+ * components since the unstripped path name is
+ * still valid. */
+ }
+ }
+#endif
+ }
+ }
+
+ if (!do_strip)
+ {
+ /* Skip the ".." or "../" and reset the counter for the
+ * components that might be stripped later on. */
+ p = tail;
+ components = 0;
+ }
+ else
+ {
+ /* Strip previous component. If the result would get empty
+ * and there is no trailing path separator, leave a single
+ * "." instead. If we are at the end of the file name and
+ * there is no trailing path separator and a preceding
+ * component is left after stripping, strip its trailing
+ * path separator as well. */
+ if (p == start && relative && tail[-1] == '.')
+ {
+ *p++ = '.';
+ *p = NUL;
+ }
+ else
+ {
+ if (p > start && tail[-1] == '.')
+ --p;
+ movetail(p, tail); /* strip previous component */
+ }
+
+ --components;
+ }
+ }
+ else if (p == start && !relative) /* leading "/.." or "/../" */
+ movetail(p, tail); /* strip ".." or "../" */
+ else
+ {
+ if (p == start + 2 && p[-2] == '.') /* leading "./../" */
+ {
+ movetail(p - 2, p); /* strip leading "./" */
+ tail -= 2;
+ }
+ p = tail; /* skip to char after ".." or "../" */
+ }
+ }
+ else
+ {
+ ++components; /* simple path component */
+ p = getnextcomp(p);
+ }
+ } while (*p != NUL);
+#endif /* !AMIGA */
+}
+
+/*
+ * Check if we have a tag for the buffer with name "buf_ffname".
+ * This is a bit slow, because of the full path compare in fullpathcmp().
+ * Return TRUE if tag for file "fname" if tag file "tag_fname" is for current
+ * file.
+ */
+ static int
+#ifdef FEAT_EMACS_TAGS
+test_for_current(is_etag, fname, fname_end, tag_fname, buf_ffname)
+ int is_etag;
+#else
+test_for_current(fname, fname_end, tag_fname, buf_ffname)
+#endif
+ char_u *fname;
+ char_u *fname_end;
+ char_u *tag_fname;
+ char_u *buf_ffname;
+{
+ int c;
+ int retval = FALSE;
+ char_u *fullname;
+
+ if (buf_ffname != NULL) /* if the buffer has a name */
+ {
+#ifdef FEAT_EMACS_TAGS
+ if (is_etag)
+ c = 0; /* to shut up GCC */
+ else
+#endif
+ {
+ c = *fname_end;
+ *fname_end = NUL;
+ }
+ fullname = expand_tag_fname(fname, tag_fname, TRUE);
+ if (fullname != NULL)
+ {
+ retval = (fullpathcmp(fullname, buf_ffname, TRUE) & FPC_SAME);
+ vim_free(fullname);
+ }
+#ifdef FEAT_EMACS_TAGS
+ if (!is_etag)
+#endif
+ *fname_end = c;
+ }
+
+ return retval;
+}
+
+/*
+ * Find the end of the tagaddress.
+ * Return OK if ";\"" is following, FAIL otherwise.
+ */
+ static int
+find_extra(pp)
+ char_u **pp;
+{
+ char_u *str = *pp;
+
+ /* Repeat for addresses separated with ';' */
+ for (;;)
+ {
+ if (VIM_ISDIGIT(*str))
+ str = skipdigits(str);
+ else if (*str == '/' || *str == '?')
+ {
+ str = skip_regexp(str + 1, *str, FALSE, NULL);
+ if (*str != **pp)
+ str = NULL;
+ else
+ ++str;
+ }
+ else
+ str = NULL;
+ if (str == NULL || *str != ';'
+ || !(VIM_ISDIGIT(str[1]) || str[1] == '/' || str[1] == '?'))
+ break;
+ ++str; /* skip ';' */
+ }
+
+ if (str != NULL && STRNCMP(str, ";\"", 2) == 0)
+ {
+ *pp = str;
+ return OK;
+ }
+ return FAIL;
+}
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+ int
+expand_tags(tagnames, pat, num_file, file)
+ int tagnames; /* expand tag names */
+ char_u *pat;
+ int *num_file;
+ char_u ***file;
+{
+ int i;
+ int c;
+ int tagnmflag;
+ char_u tagnm[100];
+ tagptrs_T t_p;
+ int ret;
+
+ if (tagnames)
+ tagnmflag = TAG_NAMES;
+ else
+ tagnmflag = 0;
+ if (pat[0] == '/')
+ ret = find_tags(pat + 1, num_file, file,
+ TAG_REGEXP | tagnmflag | TAG_VERBOSE,
+ TAG_MANY, curbuf->b_ffname);
+ else
+ ret = find_tags(pat, num_file, file,
+ TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NOIC,
+ TAG_MANY, curbuf->b_ffname);
+ if (ret == OK && !tagnames)
+ {
+ /* Reorganize the tags for display and matching as strings of:
+ * "<tagname>\0<kind>\0<filename>\0"
+ */
+ for (i = 0; i < *num_file; i++)
+ {
+ parse_match((*file)[i], &t_p);
+ c = (int)(t_p.tagname_end - t_p.tagname);
+ mch_memmove(tagnm, t_p.tagname, (size_t)c);
+ tagnm[c++] = 0;
+ tagnm[c++] = (t_p.tagkind != NULL && *t_p.tagkind)
+ ? *t_p.tagkind : 'f';
+ tagnm[c++] = 0;
+ mch_memmove((*file)[i] + c, t_p.fname, t_p.fname_end - t_p.fname);
+ (*file)[i][c + (t_p.fname_end - t_p.fname)] = 0;
+ mch_memmove((*file)[i], tagnm, (size_t)c);
+ }
+ }
+ return ret;
+}
+#endif
diff --git a/src/tearoff.bmp b/src/tearoff.bmp
new file mode 100644
index 000000000..8a4313b1f
--- /dev/null
+++ b/src/tearoff.bmp
Binary files differ
diff --git a/src/tee/Makefile b/src/tee/Makefile
new file mode 100644
index 000000000..951a1cc36
--- /dev/null
+++ b/src/tee/Makefile
@@ -0,0 +1,15 @@
+# A very (if not the most) simplistic Makefile for OS/2
+
+CC=gcc
+CFLAGS=-O2 -fno-strength-reduce
+
+tee.exe: tee.o
+ $(CC) $(CFLAGS) -s -o $@ $<
+
+tee.o: tee.c
+ $(CC) $(CFLAGS) -c $<
+
+clean:
+ - del tee.o
+ - del tee.exe
+
diff --git a/src/tee/tee.c b/src/tee/tee.c
new file mode 100644
index 000000000..6c85766bb
--- /dev/null
+++ b/src/tee/tee.c
@@ -0,0 +1,153 @@
+/* vim:set ts=4 sw=4:
+ *
+ * Copyright (c) 1996, Paul Slootman
+ *
+ * Author: Paul Slootman
+ * (paul@wurtel.hobby.nl, paul@murphy.nl, paulS@toecompst.nl)
+ *
+ * This source code is released into the public domain. It is provided on an
+ * as-is basis and no responsibility is accepted for its failure to perform
+ * as expected. It is worth at least as much as you paid for it!
+ *
+ * tee.c - pipe fitting
+ *
+ * tee reads stdin, and writes what it reads to each of the specified
+ * files. The primary reason of existence for this version is a quick
+ * and dirty implementation to distribute with Vim, to make one of the
+ * most useful features of Vim possible on OS/2: quickfix.
+ *
+ * Of course, not using tee but instead redirecting make's output directly
+ * into a temp file and then processing that is possible, but if we have a
+ * system capable of correctly piping (unlike DOS, for example), why not
+ * use it as well as possible? This tee should also work on other systems,
+ * but it's not been tested there, only on OS/2.
+ *
+ * tee is also available in the GNU shellutils package, which is available
+ * precompiled for OS/2. That one probably works better.
+ */
+
+#include <unistd.h>
+#include <malloc.h>
+#include <stdio.h>
+
+void usage(void)
+{
+ fprintf(stderr,
+"tee usage:\n\
+\ttee [-a] file ... file_n\n\
+\n\
+\t-a\tappend to files instead of truncating\n\
+\nTee reads its input, and writes to each of the specified files,\n\
+as well as to the standard output.\n\
+\n\
+This version supplied with Vim 4.2 to make ':make' possible.\n\
+For a more complete and stable version, consider getting\n\
+[a port of] the GNU shellutils package.\n\
+");
+}
+
+/*
+ * fread only returns when count is read or at EOF.
+ * We could use fgets, but I want to be able to handle binary blubber.
+ */
+
+int
+myfread(char *buf, int elsize /*ignored*/, int max, FILE *fp)
+{
+ int c;
+ int n = 0;
+
+ while ((n < max) && ((c = getchar()) != EOF))
+ {
+ *(buf++) = c;
+ n++;
+ if (c == '\n' || c == '\r')
+ break;
+ }
+ return n;
+}
+
+
+void
+main(int argc, char *argv[])
+{
+ int append = 0;
+ int numfiles;
+ int opt;
+ int maxfiles;
+ FILE **filepointers;
+ int i;
+ char buf[BUFSIZ];
+ int n;
+ extern int optind;
+
+ while ((opt = getopt(argc, argv, "a")) != EOF)
+ {
+ switch (opt)
+ {
+ case 'a': append++;
+ break;
+ default: usage();
+ exit(2);
+ }
+ }
+
+ numfiles = argc - optind;
+
+ if (numfiles == 0)
+ {
+ fprintf(stderr, "doesn't make much sense using tee without any file name arguments...\n");
+ usage();
+ exit(2);
+ }
+
+ maxfiles = sysconf(_SC_OPEN_MAX); /* or fill in 10 or so */
+ if (maxfiles < 0)
+ maxfiles = 10;
+ if (numfiles + 3 > maxfiles) /* +3 accounts for stdin, out, err */
+ {
+ fprintf(stderr, "Sorry, there is a limit of max %d files.\n", maxfiles - 3);
+ exit(1);
+ }
+ filepointers = calloc(numfiles, sizeof(FILE *));
+ if (filepointers == NULL)
+ {
+ fprintf(stderr, "Error allocating memory for %d files\n", numfiles);
+ exit(1);
+ }
+ for (i = 0; i < numfiles; i++)
+ {
+ filepointers[i] = fopen(argv[i+optind], append ? "ab" : "wb");
+ if (filepointers[i] == NULL)
+ {
+ fprintf(stderr, "Can't open \"%s\"\n", argv[i+optind]);
+ exit(1);
+ }
+ }
+ _fsetmode(stdin, "b");
+ fflush(stdout); /* needed for _fsetmode(stdout) */
+ _fsetmode(stdout, "b");
+
+ while ((n = myfread(buf, sizeof(char), sizeof(buf), stdin)) > 0)
+ {
+ fwrite(buf, sizeof(char), n, stdout);
+ fflush(stdout);
+ for (i = 0; i < numfiles; i++)
+ {
+ if (filepointers[i] &&
+ fwrite(buf, sizeof(char), n, filepointers[i]) != n)
+ {
+ fprintf(stderr, "Error writing to file \"%s\"\n", argv[i+optind]);
+ fclose(filepointers[i]);
+ filepointers[i] = NULL;
+ }
+ }
+ }
+ for (i = 0; i < numfiles; i++)
+ {
+ if (filepointers[i])
+ fclose(filepointers[i]);
+ }
+
+ exit(0);
+}
diff --git a/src/term.c b/src/term.c
new file mode 100644
index 000000000..656a40ef4
--- /dev/null
+++ b/src/term.c
@@ -0,0 +1,5381 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ *
+ * term.c: functions for controlling the terminal
+ *
+ * primitive termcap support for Amiga, MSDOS, and Win32 included
+ *
+ * NOTE: padding and variable substitution is not performed,
+ * when compiling without HAVE_TGETENT, we use tputs() and tgoto() dummies.
+ */
+
+/*
+ * Some systems have a prototype for tgetstr() with (char *) instead of
+ * (char **). This define removes that prototype. We include our own prototype
+ * below.
+ */
+
+#define tgetstr tgetstr_defined_wrong
+#include "vim.h"
+
+#ifdef HAVE_TGETENT
+# ifdef HAVE_TERMIOS_H
+# include <termios.h> /* seems to be required for some Linux */
+# endif
+# ifdef HAVE_TERMCAP_H
+# include <termcap.h>
+# endif
+
+/*
+ * A few linux systems define outfuntype in termcap.h to be used as the third
+ * argument for tputs().
+ */
+# ifdef VMS
+# define TPUTSFUNCAST
+# else
+# ifdef HAVE_OUTFUNTYPE
+# define TPUTSFUNCAST (outfuntype)
+# else
+# define TPUTSFUNCAST (int (*)())
+# endif
+# endif
+#endif
+
+#undef tgetstr
+
+/*
+ * Here are the builtin termcap entries. They are not stored as complete
+ * Tcarr structures, as such a structure is too big.
+ *
+ * The entries are compact, therefore they normally are included even when
+ * HAVE_TGETENT is defined. When HAVE_TGETENT is defined, the builtin entries
+ * can be accessed with "builtin_amiga", "builtin_ansi", "builtin_debug", etc.
+ *
+ * Each termcap is a list of builtin_term structures. It always starts with
+ * KS_NAME, which separates the entries. See parse_builtin_tcap() for all
+ * details.
+ * bt_entry is either a KS_xxx code (>= 0), or a K_xxx code.
+ *
+ * Entries marked with "guessed" may be wrong.
+ */
+struct builtin_term
+{
+ int bt_entry;
+ char *bt_string;
+};
+
+/* start of keys that are not directly used by Vim but can be mapped */
+#define BT_EXTRA_KEYS 0x101
+
+static struct builtin_term *find_builtin_term __ARGS((char_u *name));
+static void parse_builtin_tcap __ARGS((char_u *s));
+static void term_color __ARGS((char_u *s, int n));
+static void gather_termleader __ARGS((void));
+#ifdef FEAT_TERMRESPONSE
+static void req_codes_from_term __ARGS((void));
+static void req_more_codes_from_term __ARGS((void));
+static void got_code_from_term __ARGS((char_u *code, int len));
+static void check_for_codes_from_term __ARGS((void));
+#endif
+#if defined(FEAT_GUI) \
+ || (defined(FEAT_MOUSE) && (!defined(UNIX) || defined(FEAT_MOUSE_XTERM)))
+static int get_bytes_from_buf __ARGS((char_u *, char_u *, int));
+#endif
+#ifdef FEAT_TERMRESPONSE
+static void may_req_termresponse __ARGS((void));
+#endif
+static void del_termcode_idx __ARGS((int idx));
+static int term_is_builtin __ARGS((char_u *name));
+static int term_7to8bit __ARGS((char_u *p));
+#ifdef FEAT_TERMRESPONSE
+static void switch_to_8bit __ARGS((void));
+#endif
+
+#ifdef HAVE_TGETENT
+static char_u *tgetent_error __ARGS((char_u *, char_u *));
+
+/*
+ * Here is our own prototype for tgetstr(), any prototypes from the include
+ * files have been disabled by the define at the start of this file.
+ */
+char *tgetstr __ARGS((char *, char **));
+
+# ifdef FEAT_TERMRESPONSE
+/* Request Terminal Version status: */
+# define CRV_GET 1 /* send T_CRV when switched to RAW mode */
+# define CRV_SENT 2 /* did send T_CRV, waiting for answer */
+# define CRV_GOT 3 /* received T_CRV response */
+static int crv_status = CRV_GET;
+# endif
+
+/*
+ * Don't declare these variables if termcap.h contains them.
+ * Autoconf checks if these variables should be declared extern (not all
+ * systems have them).
+ * Some versions define ospeed to be speed_t, but that is incompatible with
+ * BSD, where ospeed is short and speed_t is long.
+ */
+# ifndef HAVE_OSPEED
+# ifdef OSPEED_EXTERN
+extern short ospeed;
+# else
+short ospeed;
+# endif
+# endif
+# ifndef HAVE_UP_BC_PC
+# ifdef UP_BC_PC_EXTERN
+extern char *UP, *BC, PC;
+# else
+char *UP, *BC, PC;
+# endif
+# endif
+
+# define TGETSTR(s, p) vim_tgetstr((s), (p))
+# define TGETENT(b, t) tgetent((char *)(b), (char *)(t))
+static char_u *vim_tgetstr __ARGS((char *s, char_u **pp));
+#endif /* HAVE_TGETENT */
+
+static int detected_8bit = FALSE; /* detected 8-bit terminal */
+
+struct builtin_term builtin_termcaps[] =
+{
+
+#if defined(FEAT_GUI)
+/*
+ * GUI pseudo term-cap.
+ */
+ {(int)KS_NAME, "gui"},
+ {(int)KS_CE, IF_EB("\033|$", ESC_STR "|$")},
+ {(int)KS_AL, IF_EB("\033|i", ESC_STR "|i")},
+# ifdef TERMINFO
+ {(int)KS_CAL, IF_EB("\033|%p1%dI", ESC_STR "|%p1%dI")},
+# else
+ {(int)KS_CAL, IF_EB("\033|%dI", ESC_STR "|%dI")},
+# endif
+ {(int)KS_DL, IF_EB("\033|d", ESC_STR "|d")},
+# ifdef TERMINFO
+ {(int)KS_CDL, IF_EB("\033|%p1%dD", ESC_STR "|%p1%dD")},
+ {(int)KS_CS, IF_EB("\033|%p1%d;%p2%dR", ESC_STR "|%p1%d;%p2%dR")},
+# ifdef FEAT_VERTSPLIT
+ {(int)KS_CSV, IF_EB("\033|%p1%d;%p2%dV", ESC_STR "|%p1%d;%p2%dV")},
+# endif
+# else
+ {(int)KS_CDL, IF_EB("\033|%dD", ESC_STR "|%dD")},
+ {(int)KS_CS, IF_EB("\033|%d;%dR", ESC_STR "|%d;%dR")},
+# ifdef FEAT_VERTSPLIT
+ {(int)KS_CSV, IF_EB("\033|%d;%dV", ESC_STR "|%d;%dV")},
+# endif
+# endif
+ {(int)KS_CL, IF_EB("\033|C", ESC_STR "|C")},
+ /* attributes switched on with 'h', off with * 'H' */
+ {(int)KS_ME, IF_EB("\033|31H", ESC_STR "|31H")}, /* HL_ALL */
+ {(int)KS_MR, IF_EB("\033|1h", ESC_STR "|1h")}, /* HL_INVERSE */
+ {(int)KS_MD, IF_EB("\033|2h", ESC_STR "|2h")}, /* HL_BOLD */
+ {(int)KS_SE, IF_EB("\033|16H", ESC_STR "|16H")}, /* HL_STANDOUT */
+ {(int)KS_SO, IF_EB("\033|16h", ESC_STR "|16h")}, /* HL_STANDOUT */
+ {(int)KS_UE, IF_EB("\033|8H", ESC_STR "|8H")}, /* HL_UNDERLINE */
+ {(int)KS_US, IF_EB("\033|8h", ESC_STR "|8h")}, /* HL_UNDERLINE */
+ {(int)KS_CZR, IF_EB("\033|4H", ESC_STR "|4H")}, /* HL_ITALIC */
+ {(int)KS_CZH, IF_EB("\033|4h", ESC_STR "|4h")}, /* HL_ITALIC */
+ {(int)KS_VB, IF_EB("\033|f", ESC_STR "|f")},
+ {(int)KS_MS, "y"},
+ {(int)KS_UT, "y"},
+ {(int)KS_LE, "\b"}, /* cursor-left = BS */
+ {(int)KS_ND, "\014"}, /* cursor-right = CTRL-L */
+# ifdef TERMINFO
+ {(int)KS_CM, IF_EB("\033|%p1%d;%p2%dM", ESC_STR "|%p1%d;%p2%dM")},
+# else
+ {(int)KS_CM, IF_EB("\033|%d;%dM", ESC_STR "|%d;%dM")},
+# endif
+ /* there are no key sequences here, the GUI sequences are recognized
+ * in check_termcodes() */
+#endif
+
+#ifndef NO_BUILTIN_TCAPS
+# if defined(RISCOS) || defined(ALL_BUILTIN_TCAPS)
+/*
+ * Default for the Acorn.
+ */
+ {(int)KS_NAME, "riscos"},
+ {(int)KS_CL, "\014"}, /* Cls and Home Cursor */
+ {(int)KS_CM, "\001%d\001%d\002"}, /* Position cursor */
+
+ {(int)KS_CCO, "16"}, /* Allow 16 colors */
+
+ {(int)KS_CAF, "\001%d\021"}, /* Set foreground colour */
+ {(int)KS_CAB, "\001%d\022"}, /* Set background colour */
+
+
+ {(int)KS_ME, "\004"}, /* Normal mode */
+ {(int)KS_MR, "\005"}, /* Reverse */
+
+ {(int)KS_VI, "\016"}, /* Cursor invisible */
+ {(int)KS_VE, "\017"}, /* Cursor visible */
+ {(int)KS_VS, "\020"}, /* Cursor very visible */
+
+ {(int)KS_CS, "\001%d\001%d\003"}, /* Set scroll region */
+ {(int)KS_SR, "\023"}, /* Scroll text down */
+ {K_UP, "\217"},
+ {K_DOWN, "\216"},
+ {K_LEFT, "\214"},
+ {K_RIGHT, "\215"},
+ {K_S_UP, "\237"},
+ {K_S_DOWN, "\236"},
+ {K_S_LEFT, "\234"},
+ {K_S_RIGHT, "\235"},
+
+ {K_F1, "\201"},
+ {K_F2, "\202"},
+ {K_F3, "\203"},
+ {K_F4, "\204"},
+ {K_F5, "\205"},
+ {K_F6, "\206"},
+ {K_F7, "\207"},
+ {K_F8, "\210"},
+ {K_F9, "\211"},
+ {K_F10, "\312"},
+ {K_F11, "\313"},
+ {K_F12, "\314"},
+ {K_S_F1, "\221"},
+ {K_S_F2, "\222"},
+ {K_S_F3, "\223"},
+ {K_S_F4, "\224"},
+ {K_S_F5, "\225"},
+ {K_S_F6, "\226"},
+ {K_S_F7, "\227"},
+ {K_S_F8, "\230"},
+ {K_S_F9, "\231"},
+ {K_S_F10, "\332"},
+ {K_S_F11, "\333"},
+ {K_S_F12, "\334"},
+ {K_BS, "\010"},
+ {K_INS, "\315"},
+ {K_DEL, "\177"},
+ {K_HOME, "\036"},
+ {K_END, "\213"},
+ {K_PAGEUP, "\237"},
+ {K_PAGEDOWN, "\236"},
+# endif /* Acorn terminal */
+
+
+# if defined(AMIGA) || defined(ALL_BUILTIN_TCAPS)
+/*
+ * Amiga console window, default for Amiga
+ */
+ {(int)KS_NAME, "amiga"},
+ {(int)KS_CE, "\033[K"},
+ {(int)KS_CD, "\033[J"},
+ {(int)KS_AL, "\033[L"},
+# ifdef TERMINFO
+ {(int)KS_CAL, "\033[%p1%dL"},
+# else
+ {(int)KS_CAL, "\033[%dL"},
+# endif
+ {(int)KS_DL, "\033[M"},
+# ifdef TERMINFO
+ {(int)KS_CDL, "\033[%p1%dM"},
+# else
+ {(int)KS_CDL, "\033[%dM"},
+# endif
+ {(int)KS_CL, "\014"},
+ {(int)KS_VI, "\033[0 p"},
+ {(int)KS_VE, "\033[1 p"},
+ {(int)KS_ME, "\033[0m"},
+ {(int)KS_MR, "\033[7m"},
+ {(int)KS_MD, "\033[1m"},
+ {(int)KS_SE, "\033[0m"},
+ {(int)KS_SO, "\033[33m"},
+ {(int)KS_US, "\033[4m"},
+ {(int)KS_UE, "\033[0m"},
+ {(int)KS_CZH, "\033[3m"},
+ {(int)KS_CZR, "\033[0m"},
+#if defined(__MORPHOS__) || defined(__AROS__)
+ {(int)KS_CCO, "8"}, /* allow 8 colors */
+# ifdef TERMINFO
+ {(int)KS_CAB, "\033[4%p1%dm"},/* set background color */
+ {(int)KS_CAF, "\033[3%p1%dm"},/* set foreground color */
+# else
+ {(int)KS_CAB, "\033[4%dm"}, /* set background color */
+ {(int)KS_CAF, "\033[3%dm"}, /* set foreground color */
+# endif
+ {(int)KS_OP, "\033[m"}, /* reset colors */
+#endif
+ {(int)KS_MS, "y"},
+ {(int)KS_UT, "y"}, /* guessed */
+ {(int)KS_LE, "\b"},
+# ifdef TERMINFO
+ {(int)KS_CM, "\033[%i%p1%d;%p2%dH"},
+# else
+ {(int)KS_CM, "\033[%i%d;%dH"},
+# endif
+#if defined(__MORPHOS__)
+ {(int)KS_SR, "\033M"},
+#endif
+# ifdef TERMINFO
+ {(int)KS_CRI, "\033[%p1%dC"},
+# else
+ {(int)KS_CRI, "\033[%dC"},
+# endif
+ {K_UP, "\233A"},
+ {K_DOWN, "\233B"},
+ {K_LEFT, "\233D"},
+ {K_RIGHT, "\233C"},
+ {K_S_UP, "\233T"},
+ {K_S_DOWN, "\233S"},
+ {K_S_LEFT, "\233 A"},
+ {K_S_RIGHT, "\233 @"},
+ {K_S_TAB, "\233Z"},
+ {K_F1, "\233\060~"},/* some compilers don't dig "\2330" */
+ {K_F2, "\233\061~"},
+ {K_F3, "\233\062~"},
+ {K_F4, "\233\063~"},
+ {K_F5, "\233\064~"},
+ {K_F6, "\233\065~"},
+ {K_F7, "\233\066~"},
+ {K_F8, "\233\067~"},
+ {K_F9, "\233\070~"},
+ {K_F10, "\233\071~"},
+ {K_S_F1, "\233\061\060~"},
+ {K_S_F2, "\233\061\061~"},
+ {K_S_F3, "\233\061\062~"},
+ {K_S_F4, "\233\061\063~"},
+ {K_S_F5, "\233\061\064~"},
+ {K_S_F6, "\233\061\065~"},
+ {K_S_F7, "\233\061\066~"},
+ {K_S_F8, "\233\061\067~"},
+ {K_S_F9, "\233\061\070~"},
+ {K_S_F10, "\233\061\071~"},
+ {K_HELP, "\233?~"},
+ {K_INS, "\233\064\060~"}, /* 101 key keyboard */
+ {K_PAGEUP, "\233\064\061~"}, /* 101 key keyboard */
+ {K_PAGEDOWN, "\233\064\062~"}, /* 101 key keyboard */
+ {K_HOME, "\233\064\064~"}, /* 101 key keyboard */
+ {K_END, "\233\064\065~"}, /* 101 key keyboard */
+
+ {BT_EXTRA_KEYS, ""},
+ {TERMCAP2KEY('#', '2'), "\233\065\064~"}, /* shifted home key */
+ {TERMCAP2KEY('#', '3'), "\233\065\060~"}, /* shifted insert key */
+ {TERMCAP2KEY('*', '7'), "\233\065\065~"}, /* shifted end key */
+# endif
+
+# if defined(__BEOS__) || defined(ALL_BUILTIN_TCAPS)
+/*
+ * almost standard ANSI terminal, default for bebox
+ */
+ {(int)KS_NAME, "beos-ansi"},
+ {(int)KS_CE, "\033[K"},
+ {(int)KS_CD, "\033[J"},
+ {(int)KS_AL, "\033[L"},
+# ifdef TERMINFO
+ {(int)KS_CAL, "\033[%p1%dL"},
+# else
+ {(int)KS_CAL, "\033[%dL"},
+# endif
+ {(int)KS_DL, "\033[M"},
+# ifdef TERMINFO
+ {(int)KS_CDL, "\033[%p1%dM"},
+# else
+ {(int)KS_CDL, "\033[%dM"},
+# endif
+#ifdef BEOS_PR_OR_BETTER
+# ifdef TERMINFO
+ {(int)KS_CS, "\033[%i%p1%d;%p2%dr"},
+# else
+ {(int)KS_CS, "\033[%i%d;%dr"}, /* scroll region */
+# endif
+#endif
+ {(int)KS_CL, "\033[H\033[2J"},
+#ifdef notyet
+ {(int)KS_VI, "[VI]"}, /* cursor invisible, VT320: CSI ? 25 l */
+ {(int)KS_VE, "[VE]"}, /* cursor visible, VT320: CSI ? 25 h */
+#endif
+ {(int)KS_ME, "\033[m"}, /* normal mode */
+ {(int)KS_MR, "\033[7m"}, /* reverse */
+ {(int)KS_MD, "\033[1m"}, /* bold */
+ {(int)KS_SO, "\033[31m"}, /* standout mode: red */
+ {(int)KS_SE, "\033[m"}, /* standout end */
+ {(int)KS_CZH, "\033[35m"}, /* italic: purple */
+ {(int)KS_CZR, "\033[m"}, /* italic end */
+ {(int)KS_US, "\033[4m"}, /* underscore mode */
+ {(int)KS_UE, "\033[m"}, /* underscore end */
+ {(int)KS_CCO, "8"}, /* allow 8 colors */
+# ifdef TERMINFO
+ {(int)KS_CAB, "\033[4%p1%dm"},/* set background color */
+ {(int)KS_CAF, "\033[3%p1%dm"},/* set foreground color */
+# else
+ {(int)KS_CAB, "\033[4%dm"}, /* set background color */
+ {(int)KS_CAF, "\033[3%dm"}, /* set foreground color */
+# endif
+ {(int)KS_OP, "\033[m"}, /* reset colors */
+ {(int)KS_MS, "y"}, /* safe to move cur in reverse mode */
+ {(int)KS_UT, "y"}, /* guessed */
+ {(int)KS_LE, "\b"},
+# ifdef TERMINFO
+ {(int)KS_CM, "\033[%i%p1%d;%p2%dH"},
+# else
+ {(int)KS_CM, "\033[%i%d;%dH"},
+# endif
+ {(int)KS_SR, "\033M"},
+# ifdef TERMINFO
+ {(int)KS_CRI, "\033[%p1%dC"},
+# else
+ {(int)KS_CRI, "\033[%dC"},
+# endif
+#if defined(BEOS_DR8)
+ {(int)KS_DB, ""}, /* hack! see screen.c */
+#endif
+
+ {K_UP, "\033[A"},
+ {K_DOWN, "\033[B"},
+ {K_LEFT, "\033[D"},
+ {K_RIGHT, "\033[C"},
+# endif
+
+# if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS) || defined(__EMX__)
+/*
+ * standard ANSI terminal, default for unix
+ */
+ {(int)KS_NAME, "ansi"},
+ {(int)KS_CE, IF_EB("\033[K", ESC_STR "[K")},
+ {(int)KS_AL, IF_EB("\033[L", ESC_STR "[L")},
+# ifdef TERMINFO
+ {(int)KS_CAL, IF_EB("\033[%p1%dL", ESC_STR "[%p1%dL")},
+# else
+ {(int)KS_CAL, IF_EB("\033[%dL", ESC_STR "[%dL")},
+# endif
+ {(int)KS_DL, IF_EB("\033[M", ESC_STR "[M")},
+# ifdef TERMINFO
+ {(int)KS_CDL, IF_EB("\033[%p1%dM", ESC_STR "[%p1%dM")},
+# else
+ {(int)KS_CDL, IF_EB("\033[%dM", ESC_STR "[%dM")},
+# endif
+ {(int)KS_CL, IF_EB("\033[H\033[2J", ESC_STR "[H" ESC_STR_nc "[2J")},
+ {(int)KS_ME, IF_EB("\033[0m", ESC_STR "[0m")},
+ {(int)KS_MR, IF_EB("\033[7m", ESC_STR "[7m")},
+ {(int)KS_MS, "y"},
+ {(int)KS_UT, "y"}, /* guessed */
+ {(int)KS_LE, "\b"},
+# ifdef TERMINFO
+ {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH", ESC_STR "[%i%p1%d;%p2%dH")},
+# else
+ {(int)KS_CM, IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")},
+# endif
+# ifdef TERMINFO
+ {(int)KS_CRI, IF_EB("\033[%p1%dC", ESC_STR "[%p1%dC")},
+# else
+ {(int)KS_CRI, IF_EB("\033[%dC", ESC_STR "[%dC")},
+# endif
+# endif
+
+# if defined(MSDOS) || defined(ALL_BUILTIN_TCAPS) || defined(__EMX__)
+/*
+ * These codes are valid when nansi.sys or equivalent has been installed.
+ * Function keys on a PC are preceded with a NUL. These are converted into
+ * K_NUL '\316' in mch_inchar(), because we cannot handle NULs in key codes.
+ * CTRL-arrow is used instead of SHIFT-arrow.
+ */
+#ifdef __EMX__
+ {(int)KS_NAME, "os2ansi"},
+#else
+ {(int)KS_NAME, "pcansi"},
+ {(int)KS_DL, "\033[M"},
+ {(int)KS_AL, "\033[L"},
+#endif
+ {(int)KS_CE, "\033[K"},
+ {(int)KS_CL, "\033[2J"},
+ {(int)KS_ME, "\033[0m"},
+ {(int)KS_MR, "\033[5m"}, /* reverse: black on lightgrey */
+ {(int)KS_MD, "\033[1m"}, /* bold: white text */
+ {(int)KS_SE, "\033[0m"}, /* standout end */
+ {(int)KS_SO, "\033[31m"}, /* standout: white on blue */
+ {(int)KS_CZH, "\033[34;43m"}, /* italic mode: blue text on yellow */
+ {(int)KS_CZR, "\033[0m"}, /* italic mode end */
+ {(int)KS_US, "\033[36;41m"}, /* underscore mode: cyan text on red */
+ {(int)KS_UE, "\033[0m"}, /* underscore mode end */
+ {(int)KS_CCO, "8"}, /* allow 8 colors */
+# ifdef TERMINFO
+ {(int)KS_CAB, "\033[4%p1%dm"},/* set background color */
+ {(int)KS_CAF, "\033[3%p1%dm"},/* set foreground color */
+# else
+ {(int)KS_CAB, "\033[4%dm"}, /* set background color */
+ {(int)KS_CAF, "\033[3%dm"}, /* set foreground color */
+# endif
+ {(int)KS_OP, "\033[0m"}, /* reset colors */
+ {(int)KS_MS, "y"},
+ {(int)KS_UT, "y"}, /* guessed */
+ {(int)KS_LE, "\b"},
+# ifdef TERMINFO
+ {(int)KS_CM, "\033[%i%p1%d;%p2%dH"},
+# else
+ {(int)KS_CM, "\033[%i%d;%dH"},
+# endif
+# ifdef TERMINFO
+ {(int)KS_CRI, "\033[%p1%dC"},
+# else
+ {(int)KS_CRI, "\033[%dC"},
+# endif
+ {K_UP, "\316H"},
+ {K_DOWN, "\316P"},
+ {K_LEFT, "\316K"},
+ {K_RIGHT, "\316M"},
+ {K_S_LEFT, "\316s"},
+ {K_S_RIGHT, "\316t"},
+ {K_F1, "\316;"},
+ {K_F2, "\316<"},
+ {K_F3, "\316="},
+ {K_F4, "\316>"},
+ {K_F5, "\316?"},
+ {K_F6, "\316@"},
+ {K_F7, "\316A"},
+ {K_F8, "\316B"},
+ {K_F9, "\316C"},
+ {K_F10, "\316D"},
+ {K_F11, "\316\205"}, /* guessed */
+ {K_F12, "\316\206"}, /* guessed */
+ {K_S_F1, "\316T"},
+ {K_S_F2, "\316U"},
+ {K_S_F3, "\316V"},
+ {K_S_F4, "\316W"},
+ {K_S_F5, "\316X"},
+ {K_S_F6, "\316Y"},
+ {K_S_F7, "\316Z"},
+ {K_S_F8, "\316["},
+ {K_S_F9, "\316\\"},
+ {K_S_F10, "\316]"},
+ {K_S_F11, "\316\207"}, /* guessed */
+ {K_S_F12, "\316\210"}, /* guessed */
+ {K_INS, "\316R"},
+ {K_DEL, "\316S"},
+ {K_HOME, "\316G"},
+ {K_END, "\316O"},
+ {K_PAGEDOWN, "\316Q"},
+ {K_PAGEUP, "\316I"},
+# endif
+
+# if defined(MSDOS)
+/*
+ * These codes are valid for the pc video. The entries that start with ESC |
+ * are translated into conio calls in os_msdos.c. Default for MSDOS.
+ */
+ {(int)KS_NAME, "pcterm"},
+ {(int)KS_CE, "\033|K"},
+ {(int)KS_AL, "\033|L"},
+ {(int)KS_DL, "\033|M"},
+# ifdef TERMINFO
+ {(int)KS_CS, "\033|%i%p1%d;%p2%dr"},
+# ifdef FEAT_VERTSPLIT
+ {(int)KS_CSV, "\033|%i%p1%d;%p2%dV"},
+# endif
+# else
+ {(int)KS_CS, "\033|%i%d;%dr"},
+# ifdef FEAT_VERTSPLIT
+ {(int)KS_CSV, "\033|%i%d;%dV"},
+# endif
+# endif
+ {(int)KS_CL, "\033|J"},
+ {(int)KS_ME, "\033|0m"}, /* normal */
+ {(int)KS_MR, "\033|112m"}, /* reverse: black on lightgrey */
+ {(int)KS_MD, "\033|15m"}, /* bold: white text */
+ {(int)KS_SE, "\033|0m"}, /* standout end */
+ {(int)KS_SO, "\033|31m"}, /* standout: white on blue */
+ {(int)KS_CZH, "\033|225m"}, /* italic mode: blue text on yellow */
+ {(int)KS_CZR, "\033|0m"}, /* italic mode end */
+ {(int)KS_US, "\033|67m"}, /* underscore mode: cyan text on red */
+ {(int)KS_UE, "\033|0m"}, /* underscore mode end */
+ {(int)KS_CCO, "16"}, /* allow 16 colors */
+# ifdef TERMINFO
+ {(int)KS_CAB, "\033|%p1%db"}, /* set background color */
+ {(int)KS_CAF, "\033|%p1%df"}, /* set foreground color */
+# else
+ {(int)KS_CAB, "\033|%db"}, /* set background color */
+ {(int)KS_CAF, "\033|%df"}, /* set foreground color */
+# endif
+ {(int)KS_MS, "y"},
+ {(int)KS_UT, "y"},
+ {(int)KS_LE, "\b"},
+# ifdef TERMINFO
+ {(int)KS_CM, "\033|%i%p1%d;%p2%dH"},
+# else
+ {(int)KS_CM, "\033|%i%d;%dH"},
+# endif
+#ifdef DJGPP
+ {(int)KS_VB, "\033|B"}, /* visual bell */
+#endif
+ {K_UP, "\316H"},
+ {K_DOWN, "\316P"},
+ {K_LEFT, "\316K"},
+ {K_RIGHT, "\316M"},
+ {K_S_LEFT, "\316s"},
+ {K_S_RIGHT, "\316t"},
+ {K_S_TAB, "\316\017"},
+ {K_F1, "\316;"},
+ {K_F2, "\316<"},
+ {K_F3, "\316="},
+ {K_F4, "\316>"},
+ {K_F5, "\316?"},
+ {K_F6, "\316@"},
+ {K_F7, "\316A"},
+ {K_F8, "\316B"},
+ {K_F9, "\316C"},
+ {K_F10, "\316D"},
+ {K_F11, "\316\205"},
+ {K_F12, "\316\206"},
+ {K_S_F1, "\316T"},
+ {K_S_F2, "\316U"},
+ {K_S_F3, "\316V"},
+ {K_S_F4, "\316W"},
+ {K_S_F5, "\316X"},
+ {K_S_F6, "\316Y"},
+ {K_S_F7, "\316Z"},
+ {K_S_F8, "\316["},
+ {K_S_F9, "\316\\"},
+ {K_S_F10, "\316]"},
+ {K_S_F11, "\316\207"},
+ {K_S_F12, "\316\210"},
+ {K_INS, "\316R"},
+ {K_DEL, "\316S"},
+ {K_HOME, "\316G"},
+ {K_END, "\316O"},
+ {K_PAGEDOWN, "\316Q"},
+ {K_PAGEUP, "\316I"},
+ {K_KPLUS, "\316N"},
+ {K_KMINUS, "\316J"},
+ {K_KMULTIPLY, "\3167"},
+ {K_K0, "\316\332"},
+ {K_K1, "\316\336"},
+ {K_K2, "\316\342"},
+ {K_K3, "\316\346"},
+ {K_K4, "\316\352"},
+ {K_K5, "\316\356"},
+ {K_K6, "\316\362"},
+ {K_K7, "\316\366"},
+ {K_K8, "\316\372"},
+ {K_K9, "\316\376"},
+# endif
+
+# if defined(WIN3264) || defined(ALL_BUILTIN_TCAPS) || defined(__EMX__)
+/*
+ * These codes are valid for the Win32 Console . The entries that start with
+ * ESC | are translated into console calls in os_win32.c. The function keys
+ * are also translated in os_win32.c.
+ */
+ {(int)KS_NAME, "win32"},
+ {(int)KS_CE, "\033|K"}, /* clear to end of line */
+ {(int)KS_AL, "\033|L"}, /* add new blank line */
+# ifdef TERMINFO
+ {(int)KS_CAL, "\033|%p1%dL"}, /* add number of new blank lines */
+# else
+ {(int)KS_CAL, "\033|%dL"}, /* add number of new blank lines */
+# endif
+ {(int)KS_DL, "\033|M"}, /* delete line */
+# ifdef TERMINFO
+ {(int)KS_CDL, "\033|%p1%dM"}, /* delete number of lines */
+# else
+ {(int)KS_CDL, "\033|%dM"}, /* delete number of lines */
+# endif
+ {(int)KS_CL, "\033|J"}, /* clear screen */
+ {(int)KS_CD, "\033|j"}, /* clear to end of display */
+ {(int)KS_VI, "\033|v"}, /* cursor invisible */
+ {(int)KS_VE, "\033|V"}, /* cursor visible */
+
+ {(int)KS_ME, "\033|0m"}, /* normal */
+ {(int)KS_MR, "\033|112m"}, /* reverse: black on lightgray */
+ {(int)KS_MD, "\033|15m"}, /* bold: white on black */
+#if 1
+ {(int)KS_SO, "\033|31m"}, /* standout: white on blue */
+ {(int)KS_SE, "\033|0m"}, /* standout end */
+#else
+ {(int)KS_SO, "\033|F"}, /* standout: high intensity */
+ {(int)KS_SE, "\033|f"}, /* standout end */
+#endif
+ {(int)KS_CZH, "\033|225m"}, /* italic: blue text on yellow */
+ {(int)KS_CZR, "\033|0m"}, /* italic end */
+ {(int)KS_US, "\033|67m"}, /* underscore: cyan text on red */
+ {(int)KS_UE, "\033|0m"}, /* underscore end */
+ {(int)KS_CCO, "16"}, /* allow 16 colors */
+# ifdef TERMINFO
+ {(int)KS_CAB, "\033|%p1%db"}, /* set background color */
+ {(int)KS_CAF, "\033|%p1%df"}, /* set foreground color */
+# else
+ {(int)KS_CAB, "\033|%db"}, /* set background color */
+ {(int)KS_CAF, "\033|%df"}, /* set foreground color */
+# endif
+
+ {(int)KS_MS, "y"}, /* save to move cur in reverse mode */
+ {(int)KS_UT, "y"},
+ {(int)KS_LE, "\b"},
+# ifdef TERMINFO
+ {(int)KS_CM, "\033|%i%p1%d;%p2%dH"},/* cursor motion */
+# else
+ {(int)KS_CM, "\033|%i%d;%dH"},/* cursor motion */
+# endif
+ {(int)KS_VB, "\033|B"}, /* visual bell */
+ {(int)KS_TI, "\033|S"}, /* put terminal in termcap mode */
+ {(int)KS_TE, "\033|E"}, /* out of termcap mode */
+# ifdef TERMINFO
+ {(int)KS_CS, "\033|%i%p1%d;%p2%dr"},/* scroll region */
+# else
+ {(int)KS_CS, "\033|%i%d;%dr"},/* scroll region */
+# endif
+
+ {K_UP, "\316H"},
+ {K_DOWN, "\316P"},
+ {K_LEFT, "\316K"},
+ {K_RIGHT, "\316M"},
+ {K_S_UP, "\316\304"},
+ {K_S_DOWN, "\316\317"},
+ {K_S_LEFT, "\316\311"},
+ {K_C_LEFT, "\316s"},
+ {K_S_RIGHT, "\316\313"},
+ {K_C_RIGHT, "\316t"},
+ {K_S_TAB, "\316\017"},
+ {K_F1, "\316;"},
+ {K_F2, "\316<"},
+ {K_F3, "\316="},
+ {K_F4, "\316>"},
+ {K_F5, "\316?"},
+ {K_F6, "\316@"},
+ {K_F7, "\316A"},
+ {K_F8, "\316B"},
+ {K_F9, "\316C"},
+ {K_F10, "\316D"},
+ {K_F11, "\316\205"},
+ {K_F12, "\316\206"},
+ {K_S_F1, "\316T"},
+ {K_S_F2, "\316U"},
+ {K_S_F3, "\316V"},
+ {K_S_F4, "\316W"},
+ {K_S_F5, "\316X"},
+ {K_S_F6, "\316Y"},
+ {K_S_F7, "\316Z"},
+ {K_S_F8, "\316["},
+ {K_S_F9, "\316\\"},
+ {K_S_F10, "\316]"},
+ {K_S_F11, "\316\207"},
+ {K_S_F12, "\316\210"},
+ {K_INS, "\316R"},
+ {K_DEL, "\316S"},
+ {K_HOME, "\316G"},
+ {K_S_HOME, "\316\302"},
+ {K_C_HOME, "\316w"},
+ {K_END, "\316O"},
+ {K_S_END, "\316\315"},
+ {K_C_END, "\316u"},
+ {K_PAGEDOWN, "\316Q"},
+ {K_PAGEUP, "\316I"},
+ {K_KPLUS, "\316N"},
+ {K_KMINUS, "\316J"},
+ {K_KMULTIPLY, "\316\067"},
+ {K_K0, "\316\332"},
+ {K_K1, "\316\336"},
+ {K_K2, "\316\342"},
+ {K_K3, "\316\346"},
+ {K_K4, "\316\352"},
+ {K_K5, "\316\356"},
+ {K_K6, "\316\362"},
+ {K_K7, "\316\366"},
+ {K_K8, "\316\372"},
+ {K_K9, "\316\376"},
+# endif
+
+# if defined(VMS) || defined(ALL_BUILTIN_TCAPS)
+/*
+ * VT320 is working as an ANSI terminal compatible DEC terminal.
+ * (it covers VT1x0, VT2x0 and VT3x0 up to VT320 on VMS as well)
+ * Note: K_F1...K_F5 are for internal use, should not be defined.
+ * TODO:- rewrite ESC[ codes to CSI
+ * - keyboard languages (CSI ? 26 n)
+ */
+ {(int)KS_NAME, "vt320"},
+ {(int)KS_CE, IF_EB("\033[K", ESC_STR "[K")},
+ {(int)KS_AL, IF_EB("\033[L", ESC_STR "[L")},
+# ifdef TERMINFO
+ {(int)KS_CAL, IF_EB("\033[%p1%dL", ESC_STR "[%p1%dL")},
+# else
+ {(int)KS_CAL, IF_EB("\033[%dL", ESC_STR "[%dL")},
+# endif
+ {(int)KS_DL, IF_EB("\033[M", ESC_STR "[M")},
+# ifdef TERMINFO
+ {(int)KS_CDL, IF_EB("\033[%p1%dM", ESC_STR "[%p1%dM")},
+# else
+ {(int)KS_CDL, IF_EB("\033[%dM", ESC_STR "[%dM")},
+# endif
+ {(int)KS_CL, IF_EB("\033[H\033[2J", ESC_STR "[H" ESC_STR_nc "[2J")},
+ {(int)KS_ME, IF_EB("\033[0m", ESC_STR "[0m")},
+ {(int)KS_MR, IF_EB("\033[7m", ESC_STR "[7m")},
+ {(int)KS_MS, "y"},
+ {(int)KS_UT, "y"},
+ {(int)KS_LE, "\b"},
+# ifdef TERMINFO
+ {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH",
+ ESC_STR "[%i%p1%d;%p2%dH")},
+# else
+ {(int)KS_CM, IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")},
+# endif
+# ifdef TERMINFO
+ {(int)KS_CRI, IF_EB("\033[%p1%dC", ESC_STR "[%p1%dC")},
+# else
+ {(int)KS_CRI, IF_EB("\033[%dC", ESC_STR "[%dC")},
+# endif
+ {K_UP, IF_EB("\033[A", ESC_STR "[A")},
+ {K_DOWN, IF_EB("\033[B", ESC_STR "[B")},
+ {K_RIGHT, IF_EB("\033[C", ESC_STR "[C")},
+ {K_LEFT, IF_EB("\033[D", ESC_STR "[D")},
+ {K_F6, IF_EB("\033[17~", ESC_STR "[17~")},
+ {K_F7, IF_EB("\033[18~", ESC_STR "[18~")},
+ {K_F8, IF_EB("\033[19~", ESC_STR "[19~")},
+ {K_F9, IF_EB("\033[20~", ESC_STR "[20~")},
+ {K_F10, IF_EB("\033[21~", ESC_STR "[21~")},
+/* {K_F11, IF_EB("\033[23~", ESC_STR "[23~")},
+ * (ESC) should not define, sometimes does not work */
+ {K_F12, IF_EB("\033[24~", ESC_STR "[24~")},
+ {K_F13, IF_EB("\033[25~", ESC_STR "[25~")},
+ {K_F14, IF_EB("\033[26~", ESC_STR "[26~")},
+ {K_F15, IF_EB("\033[28~", ESC_STR "[28~")}, /* Help */
+ {K_F16, IF_EB("\033[29~", ESC_STR "[29~")}, /* Select */
+ {K_F17, IF_EB("\033[31~", ESC_STR "[31~")},
+ {K_F18, IF_EB("\033[32~", ESC_STR "[32~")},
+ {K_F19, IF_EB("\033[33~", ESC_STR "[33~")},
+ {K_F20, IF_EB("\033[34~", ESC_STR "[34~")},
+ {K_INS, IF_EB("\033[2~", ESC_STR "[2~")},
+ {K_DEL, IF_EB("\033[3~", ESC_STR "[3~")},
+ {K_HOME, IF_EB("\033[1~", ESC_STR "[1~")},
+ {K_END, IF_EB("\033[4~", ESC_STR "[4~")},
+ {K_PAGEUP, IF_EB("\033[5~", ESC_STR "[5~")},
+ {K_PAGEDOWN, IF_EB("\033[6~", ESC_STR "[6~")},
+ {K_KPLUS, IF_EB("\033Ok", ESC_STR "Ok")}, /* keypad plus */
+ {K_KMINUS, IF_EB("\033Om", ESC_STR "Om")}, /* keypad minus */
+ {K_KDIVIDE, IF_EB("\033Oo", ESC_STR "Oo")}, /* keypad / */
+ {K_KMULTIPLY, IF_EB("\033Oj", ESC_STR "Oj")}, /* keypad * */
+ {K_KENTER, IF_EB("\033OM", ESC_STR "OM")}, /* keypad Enter */
+ {K_BS, "\x7f"}, /* for some reason 0177 doesn't work */
+# endif
+
+# if defined(ALL_BUILTIN_TCAPS) || defined(__MINT__)
+/*
+ * Ordinary vt52
+ */
+ {(int)KS_NAME, "vt52"},
+ {(int)KS_CE, IF_EB("\033K", ESC_STR "K")},
+ {(int)KS_CD, IF_EB("\033J", ESC_STR "J")},
+ {(int)KS_CM, IF_EB("\033Y%+ %+ ", ESC_STR "Y%+ %+ ")},
+ {(int)KS_LE, "\b"},
+# ifdef __MINT__
+ {(int)KS_AL, IF_EB("\033L", ESC_STR "L")},
+ {(int)KS_DL, IF_EB("\033M", ESC_STR "M")},
+ {(int)KS_CL, IF_EB("\033E", ESC_STR "E")},
+ {(int)KS_SR, IF_EB("\033I", ESC_STR "I")},
+ {(int)KS_VE, IF_EB("\033e", ESC_STR "e")},
+ {(int)KS_VI, IF_EB("\033f", ESC_STR "f")},
+ {(int)KS_SO, IF_EB("\033p", ESC_STR "p")},
+ {(int)KS_SE, IF_EB("\033q", ESC_STR "q")},
+ {K_UP, IF_EB("\033A", ESC_STR "A")},
+ {K_DOWN, IF_EB("\033B", ESC_STR "B")},
+ {K_LEFT, IF_EB("\033D", ESC_STR "D")},
+ {K_RIGHT, IF_EB("\033C", ESC_STR "C")},
+ {K_S_UP, IF_EB("\033a", ESC_STR "a")},
+ {K_S_DOWN, IF_EB("\033b", ESC_STR "b")},
+ {K_S_LEFT, IF_EB("\033d", ESC_STR "d")},
+ {K_S_RIGHT, IF_EB("\033c", ESC_STR "c")},
+ {K_F1, IF_EB("\033P", ESC_STR "P")},
+ {K_F2, IF_EB("\033Q", ESC_STR "Q")},
+ {K_F3, IF_EB("\033R", ESC_STR "R")},
+ {K_F4, IF_EB("\033S", ESC_STR "S")},
+ {K_F5, IF_EB("\033T", ESC_STR "T")},
+ {K_F6, IF_EB("\033U", ESC_STR "U")},
+ {K_F7, IF_EB("\033V", ESC_STR "V")},
+ {K_F8, IF_EB("\033W", ESC_STR "W")},
+ {K_F9, IF_EB("\033X", ESC_STR "X")},
+ {K_F10, IF_EB("\033Y", ESC_STR "Y")},
+ {K_S_F1, IF_EB("\033p", ESC_STR "p")},
+ {K_S_F2, IF_EB("\033q", ESC_STR "q")},
+ {K_S_F3, IF_EB("\033r", ESC_STR "r")},
+ {K_S_F4, IF_EB("\033s", ESC_STR "s")},
+ {K_S_F5, IF_EB("\033t", ESC_STR "t")},
+ {K_S_F6, IF_EB("\033u", ESC_STR "u")},
+ {K_S_F7, IF_EB("\033v", ESC_STR "v")},
+ {K_S_F8, IF_EB("\033w", ESC_STR "w")},
+ {K_S_F9, IF_EB("\033x", ESC_STR "x")},
+ {K_S_F10, IF_EB("\033y", ESC_STR "y")},
+ {K_INS, IF_EB("\033I", ESC_STR "I")},
+ {K_HOME, IF_EB("\033E", ESC_STR "E")},
+ {K_PAGEDOWN, IF_EB("\033b", ESC_STR "b")},
+ {K_PAGEUP, IF_EB("\033a", ESC_STR "a")},
+# else
+ {(int)KS_AL, IF_EB("\033T", ESC_STR "T")},
+ {(int)KS_DL, IF_EB("\033U", ESC_STR "U")},
+ {(int)KS_CL, IF_EB("\033H\033J", ESC_STR "H" ESC_STR_nc "J")},
+ {(int)KS_ME, IF_EB("\033SO", ESC_STR "SO")},
+ {(int)KS_MR, IF_EB("\033S2", ESC_STR "S2")},
+ {(int)KS_MS, "y"},
+# endif
+# endif
+
+# if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS) || defined(__EMX__)
+/*
+ * The xterm termcap is missing F14 and F15, because they send the same
+ * codes as the undo and help key, although they don't work on all keyboards.
+ */
+ {(int)KS_NAME, "xterm"},
+ {(int)KS_CE, IF_EB("\033[K", ESC_STR "[K")},
+ {(int)KS_AL, IF_EB("\033[L", ESC_STR "[L")},
+# ifdef TERMINFO
+ {(int)KS_CAL, IF_EB("\033[%p1%dL", ESC_STR "[%p1%dL")},
+# else
+ {(int)KS_CAL, IF_EB("\033[%dL", ESC_STR "[%dL")},
+# endif
+ {(int)KS_DL, IF_EB("\033[M", ESC_STR "[M")},
+# ifdef TERMINFO
+ {(int)KS_CDL, IF_EB("\033[%p1%dM", ESC_STR "[%p1%dM")},
+# else
+ {(int)KS_CDL, IF_EB("\033[%dM", ESC_STR "[%dM")},
+# endif
+# ifdef TERMINFO
+ {(int)KS_CS, IF_EB("\033[%i%p1%d;%p2%dr",
+ ESC_STR "[%i%p1%d;%p2%dr")},
+# else
+ {(int)KS_CS, IF_EB("\033[%i%d;%dr", ESC_STR "[%i%d;%dr")},
+# endif
+ {(int)KS_CL, IF_EB("\033[H\033[2J", ESC_STR "[H" ESC_STR_nc "[2J")},
+ {(int)KS_CD, IF_EB("\033[J", ESC_STR "[J")},
+ {(int)KS_ME, IF_EB("\033[m", ESC_STR "[m")},
+ {(int)KS_MR, IF_EB("\033[7m", ESC_STR "[7m")},
+ {(int)KS_MD, IF_EB("\033[1m", ESC_STR "[1m")},
+ {(int)KS_UE, IF_EB("\033[m", ESC_STR "[m")},
+ {(int)KS_US, IF_EB("\033[4m", ESC_STR "[4m")},
+ {(int)KS_MS, "y"},
+ {(int)KS_UT, "y"},
+ {(int)KS_LE, "\b"},
+# ifdef TERMINFO
+ {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH",
+ ESC_STR "[%i%p1%d;%p2%dH")},
+# else
+ {(int)KS_CM, IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")},
+# endif
+ {(int)KS_SR, IF_EB("\033M", ESC_STR "M")},
+# ifdef TERMINFO
+ {(int)KS_CRI, IF_EB("\033[%p1%dC", ESC_STR "[%p1%dC")},
+# else
+ {(int)KS_CRI, IF_EB("\033[%dC", ESC_STR "[%dC")},
+# endif
+ {(int)KS_KS, IF_EB("\033[?1h\033=", ESC_STR "[?1h" ESC_STR_nc "=")},
+ {(int)KS_KE, IF_EB("\033[?1l\033>", ESC_STR "[?1l" ESC_STR_nc ">")},
+# ifdef FEAT_XTERM_SAVE
+ {(int)KS_TI, IF_EB("\0337\033[?47h", ESC_STR "7" ESC_STR_nc "[?47h")},
+ {(int)KS_TE, IF_EB("\033[2J\033[?47l\0338",
+ ESC_STR "[2J" ESC_STR_nc "[?47l" ESC_STR_nc "8")},
+# endif
+ {(int)KS_CIS, IF_EB("\033]1;", ESC_STR "]1;")},
+ {(int)KS_CIE, "\007"},
+ {(int)KS_TS, IF_EB("\033]2;", ESC_STR "]2;")},
+ {(int)KS_FS, "\007"},
+# ifdef TERMINFO
+ {(int)KS_CWS, IF_EB("\033[8;%p1%d;%p2%dt",
+ ESC_STR "[8;%p1%d;%p2%dt")},
+ {(int)KS_CWP, IF_EB("\033[3;%p1%d;%p2%dt",
+ ESC_STR "[3;%p1%d;%p2%dt")},
+# else
+ {(int)KS_CWS, IF_EB("\033[8;%d;%dt", ESC_STR "[8;%d;%dt")},
+ {(int)KS_CWP, IF_EB("\033[3;%d;%dt", ESC_STR "[3;%d;%dt")},
+# endif
+ {(int)KS_CRV, IF_EB("\033[>c", ESC_STR "[>c")},
+ {K_UP, IF_EB("\033OA", ESC_STR "OA")},
+ {K_DOWN, IF_EB("\033OB", ESC_STR "OB")},
+ {K_RIGHT, IF_EB("\033OC", ESC_STR "OC")},
+ {K_LEFT, IF_EB("\033OD", ESC_STR "OD")},
+ {K_S_UP, IF_EB("\033O2A", ESC_STR "O2A")},
+ {K_S_DOWN, IF_EB("\033O2B", ESC_STR "O2B")},
+ {K_S_RIGHT, IF_EB("\033O2C", ESC_STR "O2C")},
+ {K_C_RIGHT, IF_EB("\033O5C", ESC_STR "O5C")},
+ {K_S_LEFT, IF_EB("\033O2D", ESC_STR "O2D")},
+ {K_C_LEFT, IF_EB("\033O5D", ESC_STR "O5D")},
+ /* An extra set of function keys for vt100 mode */
+ {K_XF1, IF_EB("\033OP", ESC_STR "OP")},
+ {K_XF2, IF_EB("\033OQ", ESC_STR "OQ")},
+ {K_XF3, IF_EB("\033OR", ESC_STR "OR")},
+ {K_XF4, IF_EB("\033OS", ESC_STR "OS")},
+ {K_F1, IF_EB("\033[11~", ESC_STR "[11~")},
+ {K_F2, IF_EB("\033[12~", ESC_STR "[12~")},
+ {K_F3, IF_EB("\033[13~", ESC_STR "[13~")},
+ {K_F4, IF_EB("\033[14~", ESC_STR "[14~")},
+ {K_F5, IF_EB("\033[15~", ESC_STR "[15~")},
+ {K_F6, IF_EB("\033[17~", ESC_STR "[17~")},
+ {K_F7, IF_EB("\033[18~", ESC_STR "[18~")},
+ {K_F8, IF_EB("\033[19~", ESC_STR "[19~")},
+ {K_F9, IF_EB("\033[20~", ESC_STR "[20~")},
+ {K_F10, IF_EB("\033[21~", ESC_STR "[21~")},
+ {K_F11, IF_EB("\033[23~", ESC_STR "[23~")},
+ {K_F12, IF_EB("\033[24~", ESC_STR "[24~")},
+ {K_S_XF1, IF_EB("\033O2P", ESC_STR "O2P")},
+ {K_S_XF2, IF_EB("\033O2Q", ESC_STR "O2Q")},
+ {K_S_XF3, IF_EB("\033O2R", ESC_STR "O2R")},
+ {K_S_XF4, IF_EB("\033O2S", ESC_STR "O2S")},
+ {K_S_F1, IF_EB("\033[11;2~", ESC_STR "[11;2~")},
+ {K_S_F2, IF_EB("\033[12;2~", ESC_STR "[12;2~")},
+ {K_S_F3, IF_EB("\033[13;2~", ESC_STR "[13;2~")},
+ {K_S_F4, IF_EB("\033[14;2~", ESC_STR "[14;2~")},
+ {K_S_F5, IF_EB("\033[15;2~", ESC_STR "[15;2~")},
+ {K_S_F6, IF_EB("\033[17;2~", ESC_STR "[17;2~")},
+ {K_S_F7, IF_EB("\033[18;2~", ESC_STR "[18;2~")},
+ {K_S_F8, IF_EB("\033[19;2~", ESC_STR "[19;2~")},
+ {K_S_F9, IF_EB("\033[20;2~", ESC_STR "[20;2~")},
+ {K_S_F10, IF_EB("\033[21;2~", ESC_STR "[21;2~")},
+ {K_S_F11, IF_EB("\033[23;2~", ESC_STR "[23;2~")},
+ {K_S_F12, IF_EB("\033[24;2~", ESC_STR "[24;2~")},
+ {K_S_TAB, IF_EB("\033[Z", ESC_STR "[Z")},
+ {K_HELP, IF_EB("\033[28~", ESC_STR "[28~")},
+ {K_UNDO, IF_EB("\033[26~", ESC_STR "[26~")},
+ {K_INS, IF_EB("\033[2~", ESC_STR "[2~")},
+ {K_HOME, IF_EB("\033[7~", ESC_STR "[7~")},
+ {K_S_HOME, IF_EB("\033O2H", ESC_STR "O2H")},
+ {K_C_HOME, IF_EB("\033O5H", ESC_STR "O5H")},
+ {K_KHOME, IF_EB("\033[1~", ESC_STR "[1~")},
+ {K_XHOME, IF_EB("\033OH", ESC_STR "OH")}, /* alternate Home */
+ {K_END, IF_EB("\033[8~", ESC_STR "[8~")},
+ {K_S_END, IF_EB("\033O2F", ESC_STR "O2F")},
+ {K_C_END, IF_EB("\033O5F", ESC_STR "O5F")},
+ {K_KEND, IF_EB("\033[4~", ESC_STR "[4~")},
+ {K_XEND, IF_EB("\033OF", ESC_STR "OF")}, /* alternate End */
+ {K_PAGEUP, IF_EB("\033[5~", ESC_STR "[5~")},
+ {K_PAGEDOWN, IF_EB("\033[6~", ESC_STR "[6~")},
+ {K_KPLUS, IF_EB("\033Ok", ESC_STR "Ok")}, /* keypad plus */
+ {K_KMINUS, IF_EB("\033Om", ESC_STR "Om")}, /* keypad minus */
+ {K_KDIVIDE, IF_EB("\033Oo", ESC_STR "Oo")}, /* keypad / */
+ {K_KMULTIPLY, IF_EB("\033Oj", ESC_STR "Oj")}, /* keypad * */
+ {K_KENTER, IF_EB("\033OM", ESC_STR "OM")}, /* keypad Enter */
+ {K_KDEL, IF_EB("\033[3~", ESC_STR "[3~")}, /* keypad Del */
+
+ {BT_EXTRA_KEYS, ""},
+ {TERMCAP2KEY('k', '0'), IF_EB("\033[10~", ESC_STR "[10~")}, /* F0 */
+ {TERMCAP2KEY('F', '3'), IF_EB("\033[25~", ESC_STR "[25~")}, /* F13 */
+ {TERMCAP2KEY('F', '6'), IF_EB("\033[29~", ESC_STR "[29~")}, /* F16 */
+ {TERMCAP2KEY('F', '7'), IF_EB("\033[31~", ESC_STR "[31~")}, /* F17 */
+ {TERMCAP2KEY('F', '8'), IF_EB("\033[32~", ESC_STR "[32~")}, /* F18 */
+ {TERMCAP2KEY('F', '9'), IF_EB("\033[33~", ESC_STR "[33~")}, /* F19 */
+ {TERMCAP2KEY('F', 'A'), IF_EB("\033[34~", ESC_STR "[34~")}, /* F20 */
+# endif
+
+# if defined(UNIX) || defined(ALL_BUILTIN_TCAPS)
+/*
+ * iris-ansi for Silicon Graphics machines.
+ */
+ {(int)KS_NAME, "iris-ansi"},
+ {(int)KS_CE, "\033[K"},
+ {(int)KS_CD, "\033[J"},
+ {(int)KS_AL, "\033[L"},
+# ifdef TERMINFO
+ {(int)KS_CAL, "\033[%p1%dL"},
+# else
+ {(int)KS_CAL, "\033[%dL"},
+# endif
+ {(int)KS_DL, "\033[M"},
+# ifdef TERMINFO
+ {(int)KS_CDL, "\033[%p1%dM"},
+# else
+ {(int)KS_CDL, "\033[%dM"},
+# endif
+#if 0 /* The scroll region is not working as Vim expects. */
+# ifdef TERMINFO
+ {(int)KS_CS, "\033[%i%p1%d;%p2%dr"},
+# else
+ {(int)KS_CS, "\033[%i%d;%dr"},
+# endif
+#endif
+ {(int)KS_CL, "\033[H\033[2J"},
+ {(int)KS_VE, "\033[9/y\033[12/y"}, /* These aren't documented */
+ {(int)KS_VS, "\033[10/y\033[=1h\033[=2l"}, /* These aren't documented */
+ {(int)KS_TI, "\033[=6h"},
+ {(int)KS_TE, "\033[=6l"},
+ {(int)KS_SE, "\033[21;27m"},
+ {(int)KS_SO, "\033[1;7m"},
+ {(int)KS_ME, "\033[m"},
+ {(int)KS_MR, "\033[7m"},
+ {(int)KS_MD, "\033[1m"},
+ {(int)KS_CCO, "8"}, /* allow 8 colors */
+ {(int)KS_CZH, "\033[3m"}, /* italic mode on */
+ {(int)KS_CZR, "\033[23m"}, /* italic mode off */
+ {(int)KS_US, "\033[4m"}, /* underline on */
+ {(int)KS_UE, "\033[24m"}, /* underline off */
+# ifdef TERMINFO
+ {(int)KS_CAB, "\033[4%p1%dm"}, /* set background color (ANSI) */
+ {(int)KS_CAF, "\033[3%p1%dm"}, /* set foreground color (ANSI) */
+ {(int)KS_CSB, "\033[102;%p1%dm"}, /* set screen background color */
+ {(int)KS_CSF, "\033[101;%p1%dm"}, /* set screen foreground color */
+# else
+ {(int)KS_CAB, "\033[4%dm"}, /* set background color (ANSI) */
+ {(int)KS_CAF, "\033[3%dm"}, /* set foreground color (ANSI) */
+ {(int)KS_CSB, "\033[102;%dm"}, /* set screen background color */
+ {(int)KS_CSF, "\033[101;%dm"}, /* set screen foreground color */
+# endif
+ {(int)KS_MS, "y"}, /* guessed */
+ {(int)KS_UT, "y"}, /* guessed */
+ {(int)KS_LE, "\b"},
+# ifdef TERMINFO
+ {(int)KS_CM, "\033[%i%p1%d;%p2%dH"},
+# else
+ {(int)KS_CM, "\033[%i%d;%dH"},
+# endif
+ {(int)KS_SR, "\033M"},
+# ifdef TERMINFO
+ {(int)KS_CRI, "\033[%p1%dC"},
+# else
+ {(int)KS_CRI, "\033[%dC"},
+# endif
+ {(int)KS_CIS, "\033P3.y"},
+ {(int)KS_CIE, "\234"}, /* ST "String Terminator" */
+ {(int)KS_TS, "\033P1.y"},
+ {(int)KS_FS, "\234"}, /* ST "String Terminator" */
+# ifdef TERMINFO
+ {(int)KS_CWS, "\033[203;%p1%d;%p2%d/y"},
+ {(int)KS_CWP, "\033[205;%p1%d;%p2%d/y"},
+# else
+ {(int)KS_CWS, "\033[203;%d;%d/y"},
+ {(int)KS_CWP, "\033[205;%d;%d/y"},
+# endif
+ {K_UP, "\033[A"},
+ {K_DOWN, "\033[B"},
+ {K_LEFT, "\033[D"},
+ {K_RIGHT, "\033[C"},
+ {K_S_UP, "\033[161q"},
+ {K_S_DOWN, "\033[164q"},
+ {K_S_LEFT, "\033[158q"},
+ {K_S_RIGHT, "\033[167q"},
+ {K_F1, "\033[001q"},
+ {K_F2, "\033[002q"},
+ {K_F3, "\033[003q"},
+ {K_F4, "\033[004q"},
+ {K_F5, "\033[005q"},
+ {K_F6, "\033[006q"},
+ {K_F7, "\033[007q"},
+ {K_F8, "\033[008q"},
+ {K_F9, "\033[009q"},
+ {K_F10, "\033[010q"},
+ {K_F11, "\033[011q"},
+ {K_F12, "\033[012q"},
+ {K_S_F1, "\033[013q"},
+ {K_S_F2, "\033[014q"},
+ {K_S_F3, "\033[015q"},
+ {K_S_F4, "\033[016q"},
+ {K_S_F5, "\033[017q"},
+ {K_S_F6, "\033[018q"},
+ {K_S_F7, "\033[019q"},
+ {K_S_F8, "\033[020q"},
+ {K_S_F9, "\033[021q"},
+ {K_S_F10, "\033[022q"},
+ {K_S_F11, "\033[023q"},
+ {K_S_F12, "\033[024q"},
+ {K_INS, "\033[139q"},
+ {K_HOME, "\033[H"},
+ {K_END, "\033[146q"},
+ {K_PAGEUP, "\033[150q"},
+ {K_PAGEDOWN, "\033[154q"},
+# endif
+
+# if defined(DEBUG) || defined(ALL_BUILTIN_TCAPS)
+/*
+ * for debugging
+ */
+ {(int)KS_NAME, "debug"},
+ {(int)KS_CE, "[CE]"},
+ {(int)KS_CD, "[CD]"},
+ {(int)KS_AL, "[AL]"},
+# ifdef TERMINFO
+ {(int)KS_CAL, "[CAL%p1%d]"},
+# else
+ {(int)KS_CAL, "[CAL%d]"},
+# endif
+ {(int)KS_DL, "[DL]"},
+# ifdef TERMINFO
+ {(int)KS_CDL, "[CDL%p1%d]"},
+# else
+ {(int)KS_CDL, "[CDL%d]"},
+# endif
+# ifdef TERMINFO
+ {(int)KS_CS, "[%p1%dCS%p2%d]"},
+# else
+ {(int)KS_CS, "[%dCS%d]"},
+# endif
+# ifdef FEAT_VERTSPLIT
+# ifdef TERMINFO
+ {(int)KS_CSV, "[%p1%dCSV%p2%d]"},
+# else
+ {(int)KS_CSV, "[%dCSV%d]"},
+# endif
+# endif
+# ifdef TERMINFO
+ {(int)KS_CAB, "[CAB%p1%d]"},
+ {(int)KS_CAF, "[CAF%p1%d]"},
+ {(int)KS_CSB, "[CSB%p1%d]"},
+ {(int)KS_CSF, "[CSF%p1%d]"},
+# else
+ {(int)KS_CAB, "[CAB%d]"},
+ {(int)KS_CAF, "[CAF%d]"},
+ {(int)KS_CSB, "[CSB%d]"},
+ {(int)KS_CSF, "[CSF%d]"},
+# endif
+ {(int)KS_OP, "[OP]"},
+ {(int)KS_LE, "[LE]"},
+ {(int)KS_CL, "[CL]"},
+ {(int)KS_VI, "[VI]"},
+ {(int)KS_VE, "[VE]"},
+ {(int)KS_VS, "[VS]"},
+ {(int)KS_ME, "[ME]"},
+ {(int)KS_MR, "[MR]"},
+ {(int)KS_MB, "[MB]"},
+ {(int)KS_MD, "[MD]"},
+ {(int)KS_SE, "[SE]"},
+ {(int)KS_SO, "[SO]"},
+ {(int)KS_UE, "[UE]"},
+ {(int)KS_US, "[US]"},
+ {(int)KS_MS, "[MS]"},
+ {(int)KS_UT, "[UT]"},
+# ifdef TERMINFO
+ {(int)KS_CM, "[%p1%dCM%p2%d]"},
+# else
+ {(int)KS_CM, "[%dCM%d]"},
+# endif
+ {(int)KS_SR, "[SR]"},
+# ifdef TERMINFO
+ {(int)KS_CRI, "[CRI%p1%d]"},
+# else
+ {(int)KS_CRI, "[CRI%d]"},
+# endif
+ {(int)KS_VB, "[VB]"},
+ {(int)KS_KS, "[KS]"},
+ {(int)KS_KE, "[KE]"},
+ {(int)KS_TI, "[TI]"},
+ {(int)KS_TE, "[TE]"},
+ {(int)KS_CIS, "[CIS]"},
+ {(int)KS_CIE, "[CIE]"},
+ {(int)KS_TS, "[TS]"},
+ {(int)KS_FS, "[FS]"},
+# ifdef TERMINFO
+ {(int)KS_CWS, "[%p1%dCWS%p2%d]"},
+ {(int)KS_CWP, "[%p1%dCWP%p2%d]"},
+# else
+ {(int)KS_CWS, "[%dCWS%d]"},
+ {(int)KS_CWP, "[%dCWP%d]"},
+# endif
+ {(int)KS_CRV, "[CRV]"},
+ {K_UP, "[KU]"},
+ {K_DOWN, "[KD]"},
+ {K_LEFT, "[KL]"},
+ {K_RIGHT, "[KR]"},
+ {K_S_UP, "[S-KU]"},
+ {K_S_DOWN, "[S-KD]"},
+ {K_S_LEFT, "[S-KL]"},
+ {K_C_LEFT, "[C-KL]"},
+ {K_S_RIGHT, "[S-KR]"},
+ {K_C_RIGHT, "[C-KR]"},
+ {K_F1, "[F1]"},
+ {K_XF1, "[xF1]"},
+ {K_F2, "[F2]"},
+ {K_XF2, "[xF2]"},
+ {K_F3, "[F3]"},
+ {K_XF3, "[xF3]"},
+ {K_F4, "[F4]"},
+ {K_XF4, "[xF4]"},
+ {K_F5, "[F5]"},
+ {K_F6, "[F6]"},
+ {K_F7, "[F7]"},
+ {K_F8, "[F8]"},
+ {K_F9, "[F9]"},
+ {K_F10, "[F10]"},
+ {K_F11, "[F11]"},
+ {K_F12, "[F12]"},
+ {K_S_F1, "[S-F1]"},
+ {K_S_XF1, "[S-xF1]"},
+ {K_S_F2, "[S-F2]"},
+ {K_S_XF2, "[S-xF2]"},
+ {K_S_F3, "[S-F3]"},
+ {K_S_XF3, "[S-xF3]"},
+ {K_S_F4, "[S-F4]"},
+ {K_S_XF4, "[S-xF4]"},
+ {K_S_F5, "[S-F5]"},
+ {K_S_F6, "[S-F6]"},
+ {K_S_F7, "[S-F7]"},
+ {K_S_F8, "[S-F8]"},
+ {K_S_F9, "[S-F9]"},
+ {K_S_F10, "[S-F10]"},
+ {K_S_F11, "[S-F11]"},
+ {K_S_F12, "[S-F12]"},
+ {K_HELP, "[HELP]"},
+ {K_UNDO, "[UNDO]"},
+ {K_BS, "[BS]"},
+ {K_INS, "[INS]"},
+ {K_KINS, "[KINS]"},
+ {K_DEL, "[DEL]"},
+ {K_KDEL, "[KDEL]"},
+ {K_HOME, "[HOME]"},
+ {K_S_HOME, "[C-HOME]"},
+ {K_C_HOME, "[C-HOME]"},
+ {K_KHOME, "[KHOME]"},
+ {K_XHOME, "[XHOME]"},
+ {K_END, "[END]"},
+ {K_S_END, "[C-END]"},
+ {K_C_END, "[C-END]"},
+ {K_KEND, "[KEND]"},
+ {K_XEND, "[XEND]"},
+ {K_PAGEUP, "[PAGEUP]"},
+ {K_PAGEDOWN, "[PAGEDOWN]"},
+ {K_KPAGEUP, "[KPAGEUP]"},
+ {K_KPAGEDOWN, "[KPAGEDOWN]"},
+ {K_MOUSE, "[MOUSE]"},
+ {K_KPLUS, "[KPLUS]"},
+ {K_KMINUS, "[KMINUS]"},
+ {K_KDIVIDE, "[KDIVIDE]"},
+ {K_KMULTIPLY, "[KMULTIPLY]"},
+ {K_KENTER, "[KENTER]"},
+ {K_KPOINT, "[KPOINT]"},
+ {K_K0, "[K0]"},
+ {K_K1, "[K1]"},
+ {K_K2, "[K2]"},
+ {K_K3, "[K3]"},
+ {K_K4, "[K4]"},
+ {K_K5, "[K5]"},
+ {K_K6, "[K6]"},
+ {K_K7, "[K7]"},
+ {K_K8, "[K8]"},
+ {K_K9, "[K9]"},
+# endif
+
+#endif /* NO_BUILTIN_TCAPS */
+
+/*
+ * The most minimal terminal: only clear screen and cursor positioning
+ * Always included.
+ */
+ {(int)KS_NAME, "dumb"},
+ {(int)KS_CL, "\014"},
+#ifdef TERMINFO
+ {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH",
+ ESC_STR "[%i%p1%d;%p2%dH")},
+#else
+ {(int)KS_CM, IF_EB("\033[%i%d;%dH", ESC_STR "[%i%d;%dH")},
+#endif
+
+/*
+ * end marker
+ */
+ {(int)KS_NAME, NULL}
+
+}; /* end of builtin_termcaps */
+
+/*
+ * DEFAULT_TERM is used, when no terminal is specified with -T option or $TERM.
+ */
+#ifdef RISCOS
+# define DEFAULT_TERM (char_u *)"riscos"
+#endif
+
+#ifdef AMIGA
+# define DEFAULT_TERM (char_u *)"amiga"
+#endif
+
+#ifdef MSWIN
+# define DEFAULT_TERM (char_u *)"win32"
+#endif
+
+#ifdef MSDOS
+# define DEFAULT_TERM (char_u *)"pcterm"
+#endif
+
+#if defined(UNIX) && !defined(__MINT__)
+# define DEFAULT_TERM (char_u *)"ansi"
+#endif
+
+#ifdef __MINT__
+# define DEFAULT_TERM (char_u *)"vt52"
+#endif
+
+#ifdef __EMX__
+# define DEFAULT_TERM (char_u *)"os2ansi"
+#endif
+
+#ifdef VMS
+# define DEFAULT_TERM (char_u *)"vt320"
+#endif
+
+#ifdef __BEOS__
+# undef DEFAULT_TERM
+# define DEFAULT_TERM (char_u *)"beos-ansi"
+#endif
+
+#ifndef DEFAULT_TERM
+# define DEFAULT_TERM (char_u *)"dumb"
+#endif
+
+/*
+ * Term_strings contains currently used terminal output strings.
+ * It is initialized with the default values by parse_builtin_tcap().
+ * The values can be changed by setting the option with the same name.
+ */
+char_u *(term_strings[(int)KS_LAST + 1]);
+
+static int need_gather = FALSE; /* need to fill termleader[] */
+static char_u termleader[256 + 1]; /* for check_termcode() */
+#ifdef FEAT_TERMRESPONSE
+static int check_for_codes = FALSE; /* check for key code reponse */
+#endif
+
+ static struct builtin_term *
+find_builtin_term(term)
+ char_u *term;
+{
+ struct builtin_term *p;
+
+ p = builtin_termcaps;
+ while (p->bt_string != NULL)
+ {
+ if (p->bt_entry == (int)KS_NAME)
+ {
+#ifdef UNIX
+ if (STRCMP(p->bt_string, "iris-ansi") == 0 && vim_is_iris(term))
+ return p;
+ else if (STRCMP(p->bt_string, "xterm") == 0 && vim_is_xterm(term))
+ return p;
+ else
+#endif
+#ifdef VMS
+ if (STRCMP(p->bt_string, "vt320") == 0 && vim_is_vt300(term))
+ return p;
+ else
+#endif
+ if (STRCMP(term, p->bt_string) == 0)
+ return p;
+ }
+ ++p;
+ }
+ return p;
+}
+
+/*
+ * Parsing of the builtin termcap entries.
+ * Caller should check if 'name' is a valid builtin term.
+ * The terminal's name is not set, as this is already done in termcapinit().
+ */
+ static void
+parse_builtin_tcap(term)
+ char_u *term;
+{
+ struct builtin_term *p;
+ char_u name[2];
+ int term_8bit;
+
+ p = find_builtin_term(term);
+ term_8bit = term_is_8bit(term);
+
+ /* Do not parse if builtin term not found */
+ if (p->bt_string == NULL)
+ return;
+
+ for (++p; p->bt_entry != (int)KS_NAME && p->bt_entry != BT_EXTRA_KEYS; ++p)
+ {
+ if ((int)p->bt_entry >= 0) /* KS_xx entry */
+ {
+ /* Only set the value if it wasn't set yet. */
+ if (term_strings[p->bt_entry] == NULL
+ || term_strings[p->bt_entry] == empty_option)
+ {
+ /* 8bit terminal: use CSI instead of <Esc>[ */
+ if (term_8bit && term_7to8bit((char_u *)p->bt_string) != 0)
+ {
+ char_u *s, *t;
+
+ s = vim_strsave((char_u *)p->bt_string);
+ if (s != NULL)
+ {
+ for (t = s; *t; ++t)
+ if (term_7to8bit(t))
+ {
+ *t = term_7to8bit(t);
+ STRCPY(t + 1, t + 2);
+ }
+ term_strings[p->bt_entry] = s;
+ set_term_option_alloced(&term_strings[p->bt_entry]);
+ }
+ }
+ else
+ term_strings[p->bt_entry] = (char_u *)p->bt_string;
+ }
+ }
+ else
+ {
+ name[0] = KEY2TERMCAP0((int)p->bt_entry);
+ name[1] = KEY2TERMCAP1((int)p->bt_entry);
+ if (find_termcode(name) == NULL)
+ add_termcode(name, (char_u *)p->bt_string, term_8bit);
+ }
+ }
+}
+#if defined(HAVE_TGETENT) || defined(FEAT_TERMRESPONSE)
+static void set_color_count __ARGS((int nr));
+
+/*
+ * Set number of colors.
+ * Store it as a number in t_colors.
+ * Store it as a string in T_CCO (using nr_colors[]).
+ */
+ static void
+set_color_count(nr)
+ int nr;
+{
+ char_u nr_colors[20]; /* string for number of colors */
+
+ t_colors = nr;
+ if (t_colors > 1)
+ sprintf((char *)nr_colors, "%d", t_colors);
+ else
+ *nr_colors = NUL;
+ set_string_option_direct((char_u *)"t_Co", -1, nr_colors, OPT_FREE);
+}
+#endif
+
+#ifdef HAVE_TGETENT
+static char *(key_names[]) =
+{
+#ifdef FEAT_TERMRESPONSE
+ /* Do this one first, it may cause a screen redraw. */
+ "Co",
+#endif
+ "ku", "kd", "kr", "kl",
+# ifdef ARCHIE
+ "su", "sd", /* Termcap code made up! */
+# endif
+ "#2", "#4", "%i", "*7",
+ "k1", "k2", "k3", "k4", "k5", "k6",
+ "k7", "k8", "k9", "k;", "F1", "F2",
+ "%1", "&8", "kb", "kI", "kD", "kh",
+ "@7", "kP", "kN", "K1", "K3", "K4", "K5", "kB",
+ NULL
+};
+#endif
+
+/*
+ * Set terminal options for terminal "term".
+ * Return OK if terminal 'term' was found in a termcap, FAIL otherwise.
+ *
+ * While doing this, until ttest(), some options may be NULL, be careful.
+ */
+ int
+set_termname(term)
+ char_u *term;
+{
+ struct builtin_term *termp;
+#ifdef HAVE_TGETENT
+ int builtin_first = p_tbi;
+ int try;
+ int termcap_cleared = FALSE;
+#endif
+ int width = 0, height = 0;
+ char_u *error_msg = NULL;
+ char_u *bs_p, *del_p;
+
+ detected_8bit = FALSE; /* reset 8-bit detection */
+
+ if (term_is_builtin(term))
+ {
+ term += 8;
+#ifdef HAVE_TGETENT
+ builtin_first = 1;
+#endif
+ }
+
+/*
+ * If HAVE_TGETENT is not defined, only the builtin termcap is used, otherwise:
+ * If builtin_first is TRUE:
+ * 0. try builtin termcap
+ * 1. try external termcap
+ * 2. if both fail default to a builtin terminal
+ * If builtin_first is FALSE:
+ * 1. try external termcap
+ * 2. try builtin termcap, if both fail default to a builtin terminal
+ */
+#ifdef HAVE_TGETENT
+ for (try = builtin_first ? 0 : 1; try < 3; ++try)
+ {
+ /*
+ * Use external termcap
+ */
+ if (try == 1)
+ {
+ char_u *p;
+ static char_u tstrbuf[TBUFSZ];
+ int i;
+ char_u tbuf[TBUFSZ];
+ char_u *tp;
+ static struct {
+ enum SpecialKey dest; /* index in term_strings[] */
+ char *name; /* termcap name for string */
+ } string_names[] =
+ { {KS_CE, "ce"}, {KS_AL, "al"}, {KS_CAL,"AL"},
+ {KS_DL, "dl"}, {KS_CDL,"DL"}, {KS_CS, "cs"},
+ {KS_CL, "cl"}, {KS_CD, "cd"},
+ {KS_VI, "vi"}, {KS_VE, "ve"}, {KS_MB, "mb"},
+ {KS_VS, "vs"}, {KS_ME, "me"}, {KS_MR, "mr"},
+ {KS_MD, "md"}, {KS_SE, "se"}, {KS_SO, "so"},
+ {KS_CZH,"ZH"}, {KS_CZR,"ZR"}, {KS_UE, "ue"},
+ {KS_US, "us"}, {KS_CM, "cm"}, {KS_SR, "sr"},
+ {KS_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"},
+ {KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"},
+ {KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"},
+ {KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_LE, "le"},
+ {KS_ND, "nd"}, {KS_OP, "op"}, {KS_CRV, "RV"},
+ {KS_CIS, "IS"}, {KS_CIE, "IE"},
+ {KS_TS, "ts"}, {KS_FS, "fs"},
+ {KS_CWP, "WP"}, {KS_CWS, "WS"},
+ {(enum SpecialKey)0, NULL}
+ };
+
+ /*
+ * If the external termcap does not have a matching entry, try the
+ * builtin ones.
+ */
+ if ((error_msg = tgetent_error(tbuf, term)) == NULL)
+ {
+ tp = tstrbuf;
+ if (!termcap_cleared)
+ {
+ clear_termoptions(); /* clear old options */
+ termcap_cleared = TRUE;
+ }
+
+ /* get output strings */
+ for (i = 0; string_names[i].name != NULL; ++i)
+ {
+ if (term_str(string_names[i].dest) == NULL
+ || term_str(string_names[i].dest) == empty_option)
+ term_str(string_names[i].dest) =
+ TGETSTR(string_names[i].name, &tp);
+ }
+
+ /* tgetflag() returns 1 if the flag is present, 0 if not and
+ * possibly -1 if the flag doesn't exist. */
+ if ((T_MS == NULL || T_MS == empty_option)
+ && tgetflag("ms") > 0)
+ T_MS = (char_u *)"y";
+ if ((T_XS == NULL || T_XS == empty_option)
+ && tgetflag("xs") > 0)
+ T_XS = (char_u *)"y";
+ if ((T_DB == NULL || T_DB == empty_option)
+ && tgetflag("db") > 0)
+ T_DB = (char_u *)"y";
+ if ((T_DA == NULL || T_DA == empty_option)
+ && tgetflag("da") > 0)
+ T_DA = (char_u *)"y";
+ if ((T_UT == NULL || T_UT == empty_option)
+ && tgetflag("ut") > 0)
+ T_UT = (char_u *)"y";
+
+
+ /*
+ * get key codes
+ */
+ for (i = 0; key_names[i] != NULL; ++i)
+ {
+ if (find_termcode((char_u *)key_names[i]) == NULL)
+ {
+ p = TGETSTR(key_names[i], &tp);
+ /* if cursor-left == backspace, ignore it (televideo
+ * 925) */
+ if (p != NULL
+ && (*p != Ctrl_H
+ || key_names[i][0] != 'k'
+ || key_names[i][1] != 'l'))
+ add_termcode((char_u *)key_names[i], p, FALSE);
+ }
+ }
+
+ if (height == 0)
+ height = tgetnum("li");
+ if (width == 0)
+ width = tgetnum("co");
+
+ /*
+ * Get number of colors (if not done already).
+ */
+ if (term_str(KS_CCO) == NULL
+ || term_str(KS_CCO) == empty_option)
+ set_color_count(tgetnum("Co"));
+
+# ifndef hpux
+ BC = (char *)TGETSTR("bc", &tp);
+ UP = (char *)TGETSTR("up", &tp);
+ p = TGETSTR("pc", &tp);
+ if (p)
+ PC = *p;
+# endif /* hpux */
+ }
+ }
+ else /* try == 0 || try == 2 */
+#endif /* HAVE_TGETENT */
+ /*
+ * Use builtin termcap
+ */
+ {
+#ifdef HAVE_TGETENT
+ /*
+ * If builtin termcap was already used, there is no need to search
+ * for the builtin termcap again, quit now.
+ */
+ if (try == 2 && builtin_first && termcap_cleared)
+ break;
+#endif
+ /*
+ * search for 'term' in builtin_termcaps[]
+ */
+ termp = find_builtin_term(term);
+ if (termp->bt_string == NULL) /* did not find it */
+ {
+#ifdef HAVE_TGETENT
+ /*
+ * If try == 0, first try the external termcap. If that is not
+ * found we'll get back here with try == 2.
+ * If termcap_cleared is set we used the external termcap,
+ * don't complain about not finding the term in the builtin
+ * termcap.
+ */
+ if (try == 0) /* try external one */
+ continue;
+ if (termcap_cleared) /* found in external termcap */
+ break;
+#endif
+
+ mch_errmsg("\r\n");
+ if (error_msg != NULL)
+ {
+ mch_errmsg((char *)error_msg);
+ mch_errmsg("\r\n");
+ }
+ mch_errmsg("'");
+ mch_errmsg((char *)term);
+ mch_errmsg(_("' not known. Available builtin terminals are:"));
+ mch_errmsg("\r\n");
+ for (termp = &(builtin_termcaps[0]); termp->bt_string != NULL;
+ ++termp)
+ {
+ if (termp->bt_entry == (int)KS_NAME)
+ {
+#ifdef HAVE_TGETENT
+ mch_errmsg(" builtin_");
+#else
+ mch_errmsg(" ");
+#endif
+ mch_errmsg(termp->bt_string);
+ mch_errmsg("\r\n");
+ }
+ }
+ /* when user typed :set term=xxx, quit here */
+ if (starting != NO_SCREEN)
+ {
+ screen_start(); /* don't know where cursor is now */
+ wait_return(TRUE);
+ return FAIL;
+ }
+ term = DEFAULT_TERM;
+ mch_errmsg(_("defaulting to '"));
+ mch_errmsg((char *)term);
+ mch_errmsg("'\r\n");
+ if (emsg_silent == 0)
+ {
+ screen_start(); /* don't know where cursor is now */
+ out_flush();
+ ui_delay(2000L, TRUE);
+ }
+ set_string_option_direct((char_u *)"term", -1, term, OPT_FREE);
+ display_errors();
+ }
+ out_flush();
+#ifdef HAVE_TGETENT
+ if (!termcap_cleared)
+ {
+#endif
+ clear_termoptions(); /* clear old options */
+#ifdef HAVE_TGETENT
+ termcap_cleared = TRUE;
+ }
+#endif
+ parse_builtin_tcap(term);
+#ifdef FEAT_GUI
+ if (term_is_gui(term))
+ {
+ out_flush();
+ gui_init();
+ /* If starting the GUI failed, don't do any of the other
+ * things for this terminal */
+ if (!gui.in_use)
+ return FAIL;
+#ifdef HAVE_TGETENT
+ break; /* don't try using external termcap */
+#endif
+ }
+#endif /* FEAT_GUI */
+ }
+#ifdef HAVE_TGETENT
+ }
+#endif
+
+/*
+ * special: There is no info in the termcap about whether the cursor
+ * positioning is relative to the start of the screen or to the start of the
+ * scrolling region. We just guess here. Only msdos pcterm is known to do it
+ * relative.
+ */
+ if (STRCMP(term, "pcterm") == 0)
+ T_CCS = (char_u *)"yes";
+ else
+ T_CCS = empty_option;
+
+#ifdef UNIX
+/*
+ * Any "stty" settings override the default for t_kb from the termcap.
+ * This is in os_unix.c, because it depends a lot on the version of unix that
+ * is being used.
+ * Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly.
+ */
+#ifdef FEAT_GUI
+ if (!gui.in_use)
+#endif
+ get_stty();
+#endif
+
+/*
+ * If the termcap has no entry for 'bs' and/or 'del' and the ioctl() also
+ * didn't work, use the default CTRL-H
+ * The default for t_kD is DEL, unless t_kb is DEL.
+ * The vim_strsave'd strings are probably lost forever, well it's only two
+ * bytes. Don't do this when the GUI is active, it uses "t_kb" and "t_kD"
+ * directly.
+ */
+#ifdef FEAT_GUI
+ if (!gui.in_use)
+#endif
+ {
+ bs_p = find_termcode((char_u *)"kb");
+ del_p = find_termcode((char_u *)"kD");
+ if (bs_p == NULL || *bs_p == NUL)
+ add_termcode((char_u *)"kb", (bs_p = (char_u *)CTRL_H_STR), FALSE);
+ if ((del_p == NULL || *del_p == NUL) &&
+ (bs_p == NULL || *bs_p != DEL))
+ add_termcode((char_u *)"kD", (char_u *)DEL_STR, FALSE);
+ }
+
+#if defined(UNIX) || defined(VMS)
+ term_is_xterm = vim_is_xterm(term);
+#endif
+
+#ifdef FEAT_MOUSE
+# if defined(UNIX) || defined(VMS)
+# ifdef FEAT_MOUSE_TTY
+ /*
+ * For Unix, set the 'ttymouse' option to the type of mouse to be used.
+ * The termcode for the mouse is added as a side effect in option.c.
+ */
+ {
+ char_u *p;
+
+ p = (char_u *)"";
+# ifdef FEAT_MOUSE_XTERM
+# ifdef FEAT_CLIPBOARD
+# ifdef FEAT_GUI
+ if (!gui.in_use)
+# endif
+ clip_init(FALSE);
+# endif
+ if (term_is_xterm)
+ {
+ if (use_xterm_mouse())
+ p = NULL; /* keep existing value, might be "xterm2" */
+ else
+ p = (char_u *)"xterm";
+ }
+# endif
+ if (p != NULL)
+ set_option_value((char_u *)"ttym", 0L, p, 0);
+ if (p == NULL
+# ifdef FEAT_GUI
+ || gui.in_use
+# endif
+ )
+ check_mouse_termcode(); /* set mouse termcode anyway */
+ }
+# endif
+# else
+ set_mouse_termcode(KS_MOUSE, (char_u *)"\233M");
+# endif
+#endif /* FEAT_MOUSE */
+
+#ifdef FEAT_SNIFF
+ {
+ char_u name[2];
+
+ name[0] = (int)KS_EXTRA;
+ name[1] = (int)KE_SNIFF;
+ add_termcode(name, (char_u *)"\233sniff", FALSE);
+ }
+#endif
+
+#ifdef USE_TERM_CONSOLE
+ /* DEFAULT_TERM indicates that it is the machine console. */
+ if (STRCMP(term, DEFAULT_TERM) != 0)
+ term_console = FALSE;
+ else
+ {
+ term_console = TRUE;
+# ifdef AMIGA
+ win_resize_on(); /* enable window resizing reports */
+# endif
+ }
+#endif
+
+#if defined(UNIX) || defined(VMS)
+ /*
+ * 'ttyfast' is default on for xterm, iris-ansi and a few others.
+ */
+ if (vim_is_fastterm(term))
+ p_tf = TRUE;
+#endif
+#ifdef USE_TERM_CONSOLE
+ /*
+ * 'ttyfast' is default on consoles
+ */
+ if (term_console)
+ p_tf = TRUE;
+#endif
+
+ ttest(TRUE); /* make sure we have a valid set of terminal codes */
+
+ full_screen = TRUE; /* we can use termcap codes from now on */
+ set_term_defaults(); /* use current values as defaults */
+#ifdef FEAT_TERMRESPONSE
+ crv_status = CRV_GET; /* Get terminal version later */
+#endif
+
+ /*
+ * Initialize the terminal with the appropriate termcap codes.
+ * Set the mouse and window title if possible.
+ * Don't do this when starting, need to parse the .vimrc first, because it
+ * may redefine t_TI etc.
+ */
+ if (starting != NO_SCREEN)
+ {
+ starttermcap(); /* may change terminal mode */
+#ifdef FEAT_MOUSE
+ setmouse(); /* may start using the mouse */
+#endif
+#ifdef FEAT_TITLE
+ maketitle(); /* may display window title */
+#endif
+ }
+
+ /* display initial screen after ttest() checking. jw. */
+ if (width <= 0 || height <= 0)
+ {
+ /* termcap failed to report size */
+ /* set defaults, in case ui_get_shellsize() also fails */
+ width = 80;
+#if defined(MSDOS) || defined(WIN3264)
+ height = 25; /* console is often 25 lines */
+#else
+ height = 24; /* most terminals are 24 lines */
+#endif
+ }
+ set_shellsize(width, height, FALSE); /* may change Rows */
+ if (starting != NO_SCREEN)
+ {
+ if (scroll_region)
+ scroll_region_reset(); /* In case Rows changed */
+ check_map_keycodes(); /* check mappings for terminal codes used */
+
+#ifdef FEAT_AUTOCMD
+ {
+ buf_T *old_curbuf;
+
+ /*
+ * Execute the TermChanged autocommands for each buffer that is
+ * loaded.
+ */
+ old_curbuf = curbuf;
+ for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next)
+ {
+ if (curbuf->b_ml.ml_mfp != NULL)
+ apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE,
+ curbuf);
+ }
+ if (buf_valid(old_curbuf))
+ curbuf = old_curbuf;
+ }
+#endif
+ }
+
+#ifdef FEAT_TERMRESPONSE
+ may_req_termresponse();
+#endif
+
+ return OK;
+}
+
+#if defined(FEAT_MOUSE) || defined(PROTO)
+
+# ifdef FEAT_MOUSE_TTY
+# define HMT_NORMAL 1
+# define HMT_NETTERM 2
+# define HMT_DEC 4
+# define HMT_JSBTERM 8
+# define HMT_PTERM 16
+static int has_mouse_termcode = 0;
+# endif
+
+# if (!defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_MOUSE_NET) \
+ || defined(FEAT_MOUSE_DEC)) || defined(FEAT_MOUSE_JSB) \
+ || defined(FEAT_MOUSE_PTERM) || defined(PROTO)
+ void
+set_mouse_termcode(n, s)
+ int n; /* KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE */
+ char_u *s;
+{
+ char_u name[2];
+
+ name[0] = n;
+ name[1] = KE_FILLER;
+ add_termcode(name, s, FALSE);
+# ifdef FEAT_MOUSE_TTY
+# ifdef FEAT_MOUSE_JSB
+ if (n == KS_JSBTERM_MOUSE)
+ has_mouse_termcode |= HMT_JSBTERM;
+ else
+# endif
+# ifdef FEAT_MOUSE_NET
+ if (n == KS_NETTERM_MOUSE)
+ has_mouse_termcode |= HMT_NETTERM;
+ else
+# endif
+# ifdef FEAT_MOUSE_DEC
+ if (n == KS_DEC_MOUSE)
+ has_mouse_termcode |= HMT_DEC;
+ else
+# endif
+# ifdef FEAT_MOUSE_PTERM
+ if (n == KS_PTERM_MOUSE)
+ has_mouse_termcode |= HMT_PTERM;
+ else
+# endif
+ has_mouse_termcode |= HMT_NORMAL;
+# endif
+}
+# endif
+
+# if ((defined(UNIX) || defined(VMS) || defined(OS2)) \
+ && (defined(FEAT_MOUSE_XTERM) || defined(FEAT_MOUSE_DEC) \
+ || defined(FEAT_MOUSE_GPM) || defined(FEAT_MOUSE_PTERM))) \
+ || defined(PROTO)
+ void
+del_mouse_termcode(n)
+ int n; /* KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE */
+{
+ char_u name[2];
+
+ name[0] = n;
+ name[1] = KE_FILLER;
+ del_termcode(name);
+# ifdef FEAT_MOUSE_TTY
+# ifdef FEAT_MOUSE_JSB
+ if (n == KS_JSBTERM_MOUSE)
+ has_mouse_termcode &= ~HMT_JSBTERM;
+ else
+# endif
+# ifdef FEAT_MOUSE_NET
+ if (n == KS_NETTERM_MOUSE)
+ has_mouse_termcode &= ~HMT_NETTERM;
+ else
+# endif
+# ifdef FEAT_MOUSE_DEC
+ if (n == KS_DEC_MOUSE)
+ has_mouse_termcode &= ~HMT_DEC;
+ else
+# endif
+# ifdef FEAT_MOUSE_PTERM
+ if (n == KS_PTERM_MOUSE)
+ has_mouse_termcode &= ~HMT_PTERM;
+ else
+# endif
+ has_mouse_termcode &= ~HMT_NORMAL;
+# endif
+}
+# endif
+#endif
+
+#ifdef HAVE_TGETENT
+/*
+ * Call tgetent()
+ * Return error message if it fails, NULL if it's OK.
+ */
+ static char_u *
+tgetent_error(tbuf, term)
+ char_u *tbuf;
+ char_u *term;
+{
+ int i;
+
+ i = TGETENT(tbuf, term);
+ if (i < 0 /* -1 is always an error */
+# ifdef TGETENT_ZERO_ERR
+ || i == 0 /* sometimes zero is also an error */
+# endif
+ )
+ {
+ /* On FreeBSD tputs() gets a SEGV after a tgetent() which fails. Call
+ * tgetent() with the always existing "dumb" entry to avoid a crash or
+ * hang. */
+ (void)TGETENT(tbuf, "dumb");
+
+ if (i < 0)
+# ifdef TGETENT_ZERO_ERR
+ return (char_u *)_("E557: Cannot open termcap file");
+ if (i == 0)
+# endif
+#ifdef TERMINFO
+ return (char_u *)_("E558: Terminal entry not found in terminfo");
+#else
+ return (char_u *)_("E559: Terminal entry not found in termcap");
+#endif
+ }
+ return NULL;
+}
+
+/*
+ * Some versions of tgetstr() have been reported to return -1 instead of NULL.
+ * Fix that here.
+ */
+ static char_u *
+vim_tgetstr(s, pp)
+ char *s;
+ char_u **pp;
+{
+ char *p;
+
+ p = tgetstr(s, (char **)pp);
+ if (p == (char *)-1)
+ p = NULL;
+ return (char_u *)p;
+}
+#endif /* HAVE_TGETENT */
+
+#if defined(HAVE_TGETENT) && (defined(UNIX) || defined(__EMX__) || defined(VMS) || defined(MACOS_X))
+/*
+ * Get Columns and Rows from the termcap. Used after a window signal if the
+ * ioctl() fails. It doesn't make sense to call tgetent each time if the "co"
+ * and "li" entries never change. But on some systems this works.
+ * Errors while getting the entries are ignored.
+ */
+ void
+getlinecol(cp, rp)
+ long *cp; /* pointer to columns */
+ long *rp; /* pointer to rows */
+{
+ char_u tbuf[TBUFSZ];
+
+ if (T_NAME != NULL && *T_NAME != NUL && tgetent_error(tbuf, T_NAME) == NULL)
+ {
+ if (*cp == 0)
+ *cp = tgetnum("co");
+ if (*rp == 0)
+ *rp = tgetnum("li");
+ }
+}
+#endif /* defined(HAVE_TGETENT) && defined(UNIX) */
+
+/*
+ * Get a string entry from the termcap and add it to the list of termcodes.
+ * Used for <t_xx> special keys.
+ * Give an error message for failure when not sourcing.
+ * If force given, replace an existing entry.
+ * Return FAIL if the entry was not found, OK if the entry was added.
+ */
+ int
+add_termcap_entry(name, force)
+ char_u *name;
+ int force;
+{
+ char_u *term;
+ int key;
+ struct builtin_term *termp;
+#ifdef HAVE_TGETENT
+ char_u *string;
+ int i;
+ int builtin_first;
+ char_u tbuf[TBUFSZ];
+ char_u tstrbuf[TBUFSZ];
+ char_u *tp = tstrbuf;
+ char_u *error_msg = NULL;
+#endif
+
+/*
+ * If the GUI is running or will start in a moment, we only support the keys
+ * that the GUI can produce.
+ */
+#ifdef FEAT_GUI
+ if (gui.in_use || gui.starting)
+ return gui_mch_haskey(name);
+#endif
+
+ if (!force && find_termcode(name) != NULL) /* it's already there */
+ return OK;
+
+ term = T_NAME;
+ if (term == NULL || *term == NUL) /* 'term' not defined yet */
+ return FAIL;
+
+ if (term_is_builtin(term)) /* name starts with "builtin_" */
+ {
+ term += 8;
+#ifdef HAVE_TGETENT
+ builtin_first = TRUE;
+#endif
+ }
+#ifdef HAVE_TGETENT
+ else
+ builtin_first = p_tbi;
+#endif
+
+#ifdef HAVE_TGETENT
+/*
+ * We can get the entry from the builtin termcap and from the external one.
+ * If 'ttybuiltin' is on or the terminal name starts with "builtin_", try
+ * builtin termcap first.
+ * If 'ttybuiltin' is off, try external termcap first.
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ if (!builtin_first == i)
+#endif
+ /*
+ * Search in builtin termcap
+ */
+ {
+ termp = find_builtin_term(term);
+ if (termp->bt_string != NULL) /* found it */
+ {
+ key = TERMCAP2KEY(name[0], name[1]);
+ while (termp->bt_entry != (int)KS_NAME)
+ {
+ if ((int)termp->bt_entry == key)
+ {
+ add_termcode(name, (char_u *)termp->bt_string,
+ term_is_8bit(term));
+ return OK;
+ }
+ ++termp;
+ }
+ }
+ }
+#ifdef HAVE_TGETENT
+ else
+ /*
+ * Search in external termcap
+ */
+ {
+ error_msg = tgetent_error(tbuf, term);
+ if (error_msg == NULL)
+ {
+ string = TGETSTR((char *)name, &tp);
+ if (string != NULL && *string != NUL)
+ {
+ add_termcode(name, string, FALSE);
+ return OK;
+ }
+ }
+ }
+ }
+#endif
+
+ if (sourcing_name == NULL)
+ {
+#ifdef HAVE_TGETENT
+ if (error_msg != NULL)
+ EMSG(error_msg);
+ else
+#endif
+ EMSG2(_("E436: No \"%s\" entry in termcap"), name);
+ }
+ return FAIL;
+}
+
+ static int
+term_is_builtin(name)
+ char_u *name;
+{
+ return (STRNCMP(name, "builtin_", (size_t)8) == 0);
+}
+
+/*
+ * Return TRUE if terminal "name" uses CSI instead of <Esc>[.
+ * Assume that the terminal is using 8-bit controls when the name contains
+ * "8bit", like in "xterm-8bit".
+ */
+ int
+term_is_8bit(name)
+ char_u *name;
+{
+ return (detected_8bit || strstr((char *)name, "8bit") != NULL);
+}
+
+/*
+ * Translate terminal control chars from 7-bit to 8-bit:
+ * <Esc>[ -> CSI
+ * <Esc>] -> <M-C-]>
+ * <Esc>O -> <M-C-O>
+ */
+ static int
+term_7to8bit(p)
+ char_u *p;
+{
+ if (*p == ESC)
+ {
+ if (p[1] == '[')
+ return CSI;
+ if (p[1] == ']')
+ return 0x9d;
+ if (p[1] == 'O')
+ return 0x8f;
+ }
+ return 0;
+}
+
+#ifdef FEAT_GUI
+ int
+term_is_gui(name)
+ char_u *name;
+{
+ return (STRCMP(name, "builtin_gui") == 0 || STRCMP(name, "gui") == 0);
+}
+#endif
+
+#if !defined(HAVE_TGETENT) || defined(AMIGA) || defined(PROTO)
+
+ char_u *
+tltoa(i)
+ unsigned long i;
+{
+ static char_u buf[16];
+ char_u *p;
+
+ p = buf + 15;
+ *p = '\0';
+ do
+ {
+ --p;
+ *p = (char_u) (i % 10 + '0');
+ i /= 10;
+ }
+ while (i > 0 && p > buf);
+ return p;
+}
+#endif
+
+#ifndef HAVE_TGETENT
+
+/*
+ * minimal tgoto() implementation.
+ * no padding and we only parse for %i %d and %+char
+ */
+char *tgoto __ARGS((char *, int, int));
+
+ char *
+tgoto(cm, x, y)
+ char *cm;
+ int x, y;
+{
+ static char buf[30];
+ char *p, *s, *e;
+
+ if (!cm)
+ return "OOPS";
+ e = buf + 29;
+ for (s = buf; s < e && *cm; cm++)
+ {
+ if (*cm != '%')
+ {
+ *s++ = *cm;
+ continue;
+ }
+ switch (*++cm)
+ {
+ case 'd':
+ p = (char *)tltoa((unsigned long)y);
+ y = x;
+ while (*p)
+ *s++ = *p++;
+ break;
+ case 'i':
+ x++;
+ y++;
+ break;
+ case '+':
+ *s++ = (char)(*++cm + y);
+ y = x;
+ break;
+ case '%':
+ *s++ = *cm;
+ break;
+ default:
+ return "OOPS";
+ }
+ }
+ *s = '\0';
+ return buf;
+}
+
+#endif /* HAVE_TGETENT */
+
+/*
+ * Set the terminal name and initialize the terminal options.
+ * If "name" is NULL or empty, get the terminal name from the environment.
+ * If that fails, use the default terminal name.
+ */
+ void
+termcapinit(name)
+ char_u *name;
+{
+ char_u *term;
+
+ if (name != NULL && *name == NUL)
+ name = NULL; /* empty name is equal to no name */
+ term = name;
+
+#ifdef __BEOS__
+ /*
+ * TERM environment variable is normally set to 'ansi' on the Bebox;
+ * Since the BeBox doesn't quite support full ANSI yet, we use our
+ * own custom 'ansi-beos' termcap instead, unless the -T option has
+ * been given on the command line.
+ */
+ if (term == NULL
+ && strcmp((char *)mch_getenv((char_u *)"TERM"), "ansi") == 0)
+ term = DEFAULT_TERM;
+#endif
+#ifndef MSWIN
+ if (term == NULL)
+ term = mch_getenv((char_u *)"TERM");
+#endif
+ if (term == NULL || *term == NUL)
+ term = DEFAULT_TERM;
+ set_string_option_direct((char_u *)"term", -1, term, OPT_FREE);
+
+ /* Set the default terminal name. */
+ set_string_default("term", term);
+ set_string_default("ttytype", term);
+
+ /*
+ * Avoid using "term" here, because the next mch_getenv() may overwrite it.
+ */
+ set_termname(T_NAME != NULL ? T_NAME : term);
+}
+
+/*
+ * the number of calls to ui_write is reduced by using the buffer "out_buf"
+ */
+#ifdef DOS16
+# define OUT_SIZE 255 /* only have 640K total... */
+#else
+# ifdef FEAT_GUI_W16
+# define OUT_SIZE 1023 /* Save precious 1K near data */
+# else
+# define OUT_SIZE 2047
+# endif
+#endif
+ /* Add one to allow mch_write() in os_win32.c to append a NUL */
+static char_u out_buf[OUT_SIZE + 1];
+static int out_pos = 0; /* number of chars in out_buf */
+
+/*
+ * out_flush(): flush the output buffer
+ */
+ void
+out_flush()
+{
+ int len;
+
+ if (out_pos != 0)
+ {
+ /* set out_pos to 0 before ui_write, to avoid recursiveness */
+ len = out_pos;
+ out_pos = 0;
+ ui_write(out_buf, len);
+ }
+}
+
+#if defined(FEAT_MBYTE) || defined(PROTO)
+/*
+ * Sometimes a byte out of a multi-byte character is written with out_char().
+ * To avoid flushing half of the character, call this function first.
+ */
+ void
+out_flush_check()
+{
+ if (enc_dbcs != 0 && out_pos >= OUT_SIZE - MB_MAXBYTES)
+ out_flush();
+}
+#endif
+
+#ifdef FEAT_GUI
+/*
+ * out_trash(): Throw away the contents of the output buffer
+ */
+ void
+out_trash()
+{
+ out_pos = 0;
+}
+#endif
+
+/*
+ * out_char(c): put a byte into the output buffer.
+ * Flush it if it becomes full.
+ * This should not be used for outputting text on the screen (use functions
+ * like msg_puts() and screen_putchar() for that).
+ */
+ void
+out_char(c)
+ unsigned c;
+{
+#if defined(UNIX) || defined(VMS) || defined(AMIGA) || defined(MACOS_X_UNIX)
+ if (c == '\n') /* turn LF into CR-LF (CRMOD doesn't seem to do this) */
+ out_char('\r');
+#endif
+
+ out_buf[out_pos++] = c;
+
+ /* For testing we flush each time. */
+ if (out_pos >= OUT_SIZE || p_wd)
+ out_flush();
+}
+
+static void out_char_nf __ARGS((unsigned));
+
+/*
+ * out_char_nf(c): like out_char(), but don't flush when p_wd is set
+ */
+ static void
+out_char_nf(c)
+ unsigned c;
+{
+#if defined(UNIX) || defined(VMS) || defined(AMIGA) || defined(MACOS_X_UNIX)
+ if (c == '\n') /* turn LF into CR-LF (CRMOD doesn't seem to do this) */
+ out_char_nf('\r');
+#endif
+
+ out_buf[out_pos++] = c;
+
+ if (out_pos >= OUT_SIZE)
+ out_flush();
+}
+
+/*
+ * A never-padding out_str.
+ * use this whenever you don't want to run the string through tputs.
+ * tputs above is harmless, but tputs from the termcap library
+ * is likely to strip off leading digits, that it mistakes for padding
+ * information, and "%i", "%d", etc.
+ * This should only be used for writing terminal codes, not for outputting
+ * normal text (use functions like msg_puts() and screen_putchar() for that).
+ */
+ void
+out_str_nf(s)
+ char_u *s;
+{
+ if (out_pos > OUT_SIZE - 20) /* avoid terminal strings being split up */
+ out_flush();
+ while (*s)
+ out_char_nf(*s++);
+
+ /* For testing we write one string at a time. */
+ if (p_wd)
+ out_flush();
+}
+
+/*
+ * out_str(s): Put a character string a byte at a time into the output buffer.
+ * If HAVE_TGETENT is defined use the termcap parser. (jw)
+ * This should only be used for writing terminal codes, not for outputting
+ * normal text (use functions like msg_puts() and screen_putchar() for that).
+ */
+ void
+out_str(s)
+ char_u *s;
+{
+ if (s != NULL && *s)
+ {
+#ifdef FEAT_GUI
+ /* Don't use tputs() when GUI is used, ncurses crashes. */
+ if (gui.in_use)
+ {
+ out_str_nf(s);
+ return;
+ }
+#endif
+ /* avoid terminal strings being split up */
+ if (out_pos > OUT_SIZE - 20)
+ out_flush();
+#ifdef HAVE_TGETENT
+ tputs((char *)s, 1, TPUTSFUNCAST out_char_nf);
+#else
+ while (*s)
+ out_char_nf(*s++);
+#endif
+
+ /* For testing we write one string at a time. */
+ if (p_wd)
+ out_flush();
+ }
+}
+
+/*
+ * cursor positioning using termcap parser. (jw)
+ */
+ void
+term_windgoto(row, col)
+ int row;
+ int col;
+{
+ OUT_STR(tgoto((char *)T_CM, col, row));
+}
+
+ void
+term_cursor_right(i)
+ int i;
+{
+ OUT_STR(tgoto((char *)T_CRI, 0, i));
+}
+
+ void
+term_append_lines(line_count)
+ int line_count;
+{
+ OUT_STR(tgoto((char *)T_CAL, 0, line_count));
+}
+
+ void
+term_delete_lines(line_count)
+ int line_count;
+{
+ OUT_STR(tgoto((char *)T_CDL, 0, line_count));
+}
+
+#if defined(HAVE_TGETENT) || defined(PROTO)
+ void
+term_set_winpos(x, y)
+ int x;
+ int y;
+{
+ /* Can't handle a negative value here */
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+ OUT_STR(tgoto((char *)T_CWP, y, x));
+}
+
+ void
+term_set_winsize(width, height)
+ int width;
+ int height;
+{
+ OUT_STR(tgoto((char *)T_CWS, height, width));
+}
+#endif
+
+ void
+term_fg_color(n)
+ int n;
+{
+ /* Use "AF" termcap entry if present, "Sf" entry otherwise */
+ if (*T_CAF)
+ term_color(T_CAF, n);
+ else if (*T_CSF)
+ term_color(T_CSF, n);
+}
+
+ void
+term_bg_color(n)
+ int n;
+{
+ /* Use "AB" termcap entry if present, "Sb" entry otherwise */
+ if (*T_CAB)
+ term_color(T_CAB, n);
+ else if (*T_CSB)
+ term_color(T_CSB, n);
+}
+
+ static void
+term_color(s, n)
+ char_u *s;
+ int n;
+{
+ char buf[20];
+ int i = 2; /* index in s[] just after <Esc>[ or CSI */
+
+ /* Special handling of 16 colors, because termcap can't handle it */
+ /* Also accept "\e[3%dm" for TERMINFO, it is sometimes used */
+ /* Also accept CSI instead of <Esc>[ */
+ if (n >= 8 && t_colors >= 16
+ && ((s[0] == ESC && s[1] == '[') || (s[0] == CSI && (i = 1) == 1))
+ && s[i] != NUL
+ && (STRCMP(s + i + 1, "%p1%dm") == 0
+ || STRCMP(s + i + 1, "%dm") == 0)
+ && (s[i] == '3' || s[i] == '4'))
+ {
+ sprintf(buf,
+#ifdef TERMINFO
+ "%s%s%%p1%%dm",
+#else
+ "%s%s%%dm",
+#endif
+ i == 2 ? IF_EB("\033[", ESC_STR "[") : "\233",
+ s[i] == '3' ? (n >= 16 ? "38;5;" : "9")
+ : (n >= 16 ? "48;5;" : "10"));
+ OUT_STR(tgoto(buf, 0, n >= 16 ? n : n - 8));
+ }
+ else
+ OUT_STR(tgoto((char *)s, 0, n));
+}
+
+#if (defined(FEAT_TITLE) && (defined(UNIX) || defined(OS2) || defined(VMS) || defined(MACOS_X))) || defined(PROTO)
+/*
+ * Generic function to set window title, using t_ts and t_fs.
+ */
+ void
+term_settitle(title)
+ char_u *title;
+{
+ /* t_ts takes one argument: column in status line */
+ OUT_STR(tgoto((char *)T_TS, 0, 0)); /* set title start */
+ out_str_nf(title);
+ out_str(T_FS); /* set title end */
+ out_flush();
+}
+#endif
+
+/*
+ * Make sure we have a valid set or terminal options.
+ * Replace all entries that are NULL by empty_option
+ */
+ void
+ttest(pairs)
+ int pairs;
+{
+ check_options(); /* make sure no options are NULL */
+
+ /*
+ * MUST have "cm": cursor motion.
+ */
+ if (*T_CM == NUL)
+ EMSG(_("E437: terminal capability \"cm\" required"));
+
+ /*
+ * if "cs" defined, use a scroll region, it's faster.
+ */
+ if (*T_CS != NUL)
+ scroll_region = TRUE;
+ else
+ scroll_region = FALSE;
+
+ if (pairs)
+ {
+ /*
+ * optional pairs
+ */
+ /* TP goes to normal mode for TI (invert) and TB (bold) */
+ if (*T_ME == NUL)
+ T_ME = T_MR = T_MD = T_MB = empty_option;
+ if (*T_SO == NUL || *T_SE == NUL)
+ T_SO = T_SE = empty_option;
+ if (*T_US == NUL || *T_UE == NUL)
+ T_US = T_UE = empty_option;
+ if (*T_CZH == NUL || *T_CZR == NUL)
+ T_CZH = T_CZR = empty_option;
+
+ /* T_VE is needed even though T_VI is not defined */
+ if (*T_VE == NUL)
+ T_VI = empty_option;
+
+ /* if 'mr' or 'me' is not defined use 'so' and 'se' */
+ if (*T_ME == NUL)
+ {
+ T_ME = T_SE;
+ T_MR = T_SO;
+ T_MD = T_SO;
+ }
+
+ /* if 'so' or 'se' is not defined use 'mr' and 'me' */
+ if (*T_SO == NUL)
+ {
+ T_SE = T_ME;
+ if (*T_MR == NUL)
+ T_SO = T_MD;
+ else
+ T_SO = T_MR;
+ }
+
+ /* if 'ZH' or 'ZR' is not defined use 'mr' and 'me' */
+ if (*T_CZH == NUL)
+ {
+ T_CZR = T_ME;
+ if (*T_MR == NUL)
+ T_CZH = T_MD;
+ else
+ T_CZH = T_MR;
+ }
+
+ /* "Sb" and "Sf" come in pairs */
+ if (*T_CSB == NUL || *T_CSF == NUL)
+ {
+ T_CSB = empty_option;
+ T_CSF = empty_option;
+ }
+
+ /* "AB" and "AF" come in pairs */
+ if (*T_CAB == NUL || *T_CAF == NUL)
+ {
+ T_CAB = empty_option;
+ T_CAF = empty_option;
+ }
+
+ /* if 'Sb' and 'AB' are not defined, reset "Co" */
+ if (*T_CSB == NUL && *T_CAB == NUL)
+ T_CCO = empty_option;
+
+ /* Set 'weirdinvert' according to value of 't_xs' */
+ p_wiv = (*T_XS != NUL);
+ }
+ need_gather = TRUE;
+
+ /* Set t_colors to the value of t_Co. */
+ t_colors = atoi((char *)T_CCO);
+}
+
+#if (defined(FEAT_GUI) && (defined(FEAT_MENU) || !defined(USE_ON_FLY_SCROLL))) \
+ || defined(PROTO)
+/*
+ * Represent the given long_u as individual bytes, with the most significant
+ * byte first, and store them in dst.
+ */
+ void
+add_long_to_buf(val, dst)
+ long_u val;
+ char_u *dst;
+{
+ int i;
+ int shift;
+
+ for (i = 1; i <= sizeof(long_u); i++)
+ {
+ shift = 8 * (sizeof(long_u) - i);
+ dst[i - 1] = (char_u) ((val >> shift) & 0xff);
+ }
+}
+
+static int get_long_from_buf __ARGS((char_u *buf, long_u *val));
+
+/*
+ * Interpret the next string of bytes in buf as a long integer, with the most
+ * significant byte first. Note that it is assumed that buf has been through
+ * inchar(), so that NUL and K_SPECIAL will be represented as three bytes each.
+ * Puts result in val, and returns the number of bytes read from buf
+ * (between sizeof(long_u) and 2 * sizeof(long_u)), or -1 if not enough bytes
+ * were present.
+ */
+ static int
+get_long_from_buf(buf, val)
+ char_u *buf;
+ long_u *val;
+{
+ int len;
+ char_u bytes[sizeof(long_u)];
+ int i;
+ int shift;
+
+ *val = 0;
+ len = get_bytes_from_buf(buf, bytes, (int)sizeof(long_u));
+ if (len != -1)
+ {
+ for (i = 0; i < sizeof(long_u); i++)
+ {
+ shift = 8 * (sizeof(long_u) - 1 - i);
+ *val += (long_u)bytes[i] << shift;
+ }
+ }
+ return len;
+}
+#endif
+
+#if defined(FEAT_GUI) \
+ || (defined(FEAT_MOUSE) && (!defined(UNIX) || defined(FEAT_MOUSE_XTERM)))
+/*
+ * Read the next num_bytes bytes from buf, and store them in bytes. Assume
+ * that buf has been through inchar(). Returns the actual number of bytes used
+ * from buf (between num_bytes and num_bytes*2), or -1 if not enough bytes were
+ * available.
+ */
+ static int
+get_bytes_from_buf(buf, bytes, num_bytes)
+ char_u *buf;
+ char_u *bytes;
+ int num_bytes;
+{
+ int len = 0;
+ int i;
+ char_u c;
+
+ for (i = 0; i < num_bytes; i++)
+ {
+ if ((c = buf[len++]) == NUL)
+ return -1;
+ if (c == K_SPECIAL)
+ {
+ if (buf[len] == NUL || buf[len + 1] == NUL) /* cannot happen? */
+ return -1;
+ if (buf[len++] == (int)KS_ZERO)
+ c = NUL;
+ ++len; /* skip KE_FILLER */
+ /* else it should be KS_SPECIAL, and c already equals K_SPECIAL */
+ }
+ bytes[i] = c;
+ }
+ return len;
+}
+#endif
+
+/*
+ * Check if the new shell size is valid, correct it if it's too small.
+ */
+ void
+check_shellsize()
+{
+ if (Columns < MIN_COLUMNS)
+ Columns = MIN_COLUMNS;
+ if (Rows < min_rows()) /* need room for one window and command line */
+ Rows = min_rows();
+}
+
+ void
+win_new_shellsize()
+{
+ static int old_Rows = 0;
+ static int old_Columns = 0;
+
+ if (old_Rows != Rows || old_Columns != Columns)
+ ui_new_shellsize();
+ if (old_Rows != Rows)
+ {
+ old_Rows = Rows;
+ shell_new_rows(); /* update window sizes */
+ }
+ if (old_Columns != Columns)
+ {
+ old_Columns = Columns;
+#ifdef FEAT_VERTSPLIT
+ shell_new_columns(); /* update window sizes */
+#endif
+ }
+}
+
+/*
+ * Call this function when the Vim shell has been resized in any way.
+ * Will obtain the current size and redraw (also when size didn't change).
+ */
+ void
+shell_resized()
+{
+ set_shellsize(0, 0, FALSE);
+}
+
+/*
+ * Check if the shell size changed. Handle a resize.
+ * When the size didn't change, nothing happens.
+ */
+ void
+shell_resized_check()
+{
+ int old_Rows = Rows;
+ int old_Columns = Columns;
+
+ (void)ui_get_shellsize();
+ check_shellsize();
+ if (old_Rows != Rows || old_Columns != Columns)
+ shell_resized();
+}
+
+/*
+ * Set size of the Vim shell.
+ * If 'mustset' is TRUE, we must set Rows and Columns, do not get the real
+ * window size (this is used for the :win command).
+ * If 'mustset' is FALSE, we may try to get the real window size and if
+ * it fails use 'width' and 'height'.
+ */
+ void
+set_shellsize(width, height, mustset)
+ int width, height;
+ int mustset;
+{
+ static int busy = FALSE;
+
+ /*
+ * Avoid recursiveness, can happen when setting the window size causes
+ * another window-changed signal.
+ */
+ if (busy)
+ return;
+
+ if (width < 0 || height < 0) /* just checking... */
+ return;
+
+ if (State == HITRETURN || State == SETWSIZE) /* postpone the resizing */
+ {
+ State = SETWSIZE;
+ return;
+ }
+
+ ++busy;
+
+#ifdef AMIGA
+ out_flush(); /* must do this before mch_get_shellsize() for
+ some obscure reason */
+#endif
+
+ if (mustset || (ui_get_shellsize() == FAIL && height != 0))
+ {
+ Rows = height;
+ Columns = width;
+ check_shellsize();
+ ui_set_shellsize(mustset);
+ }
+ else
+ check_shellsize();
+
+ /* The window layout used to be adjusted here, but it now happens in
+ * screenalloc() (also invoked from screenclear()). That is because the
+ * "busy" check above may skip this, but not screenalloc(). */
+
+ if (State != ASKMORE && State != EXTERNCMD && State != CONFIRM)
+ screenclear();
+ else
+ screen_start(); /* don't know where cursor is now */
+
+ if (starting != NO_SCREEN)
+ {
+#ifdef FEAT_TITLE
+ maketitle();
+#endif
+ changed_line_abv_curs();
+ invalidate_botline();
+
+ /*
+ * We only redraw when it's needed:
+ * - While at the more prompt or executing an external command, don't
+ * redraw, but position the cursor.
+ * - While editing the command line, only redraw that.
+ * - in Ex mode, don't redraw anything.
+ * - Otherwise, redraw right now, and position the cursor.
+ * Always need to call update_screen() or screenalloc(), to make
+ * sure Rows/Columns and the size of ScreenLines[] is correct!
+ */
+ if (State == ASKMORE || State == EXTERNCMD || State == CONFIRM
+ || exmode_active)
+ {
+ screenalloc(FALSE);
+ repeat_message();
+ }
+ else if (State & CMDLINE)
+ {
+ update_screen(NOT_VALID);
+ redrawcmdline();
+ }
+ else
+ {
+ update_topline();
+ update_screen(NOT_VALID);
+ if (redrawing())
+ setcursor();
+ }
+ cursor_on(); /* redrawing may have switched it off */
+ }
+ out_flush();
+ --busy;
+}
+
+/*
+ * Set the terminal to TMODE_RAW (for Normal mode) or TMODE_COOK (for external
+ * commands and Ex mode).
+ */
+ void
+settmode(tmode)
+ int tmode;
+{
+#ifdef FEAT_GUI
+ /* don't set the term where gvim was started to any mode */
+ if (gui.in_use)
+ return;
+#endif
+
+ if (full_screen)
+ {
+ /* In Ex mode, never set to RAW */
+ if (exmode_active == EXMODE_NORMAL)
+ tmode = TMODE_COOK;
+
+ /*
+ * When returning after calling a shell we want to really set the
+ * terminal to raw mode, even though we think it already is, because
+ * the shell program may have reset the terminal mode.
+ * When we think the terminal is normal, don't try to set it to
+ * normal again, because that causes problems (logout!) on some
+ * machines.
+ */
+ if (tmode != TMODE_COOK || cur_tmode != TMODE_COOK)
+ {
+#ifdef FEAT_TERMRESPONSE
+ /* May need to check for T_CRV response and termcodes, it doesn't
+ * work in Cooked mode, an external program may get them. */
+ if (tmode != TMODE_RAW && crv_status == CRV_SENT)
+ (void)vpeekc_nomap();
+ check_for_codes_from_term();
+#endif
+#ifdef FEAT_MOUSE_TTY
+ if (tmode != TMODE_RAW)
+ mch_setmouse(FALSE); /* switch mouse off */
+#endif
+ out_flush();
+ mch_settmode(tmode); /* machine specific function */
+ cur_tmode = tmode;
+#ifdef FEAT_MOUSE
+ if (tmode == TMODE_RAW)
+ setmouse(); /* may switch mouse on */
+#endif
+ out_flush();
+ }
+#ifdef FEAT_TERMRESPONSE
+ may_req_termresponse();
+#endif
+ }
+}
+
+ void
+starttermcap()
+{
+ if (full_screen && !termcap_active)
+ {
+ out_str(T_TI); /* start termcap mode */
+ out_str(T_KS); /* start "keypad transmit" mode */
+ out_flush();
+ termcap_active = TRUE;
+ screen_start(); /* don't know where cursor is now */
+#ifdef FEAT_TERMRESPONSE
+ may_req_termresponse();
+ /* Immediately check for a response. If t_Co changes, we don't want
+ * to redraw with wrong colors first. */
+ check_for_codes_from_term();
+#endif
+ }
+}
+
+ void
+stoptermcap()
+{
+ screen_stop_highlight();
+ reset_cterm_colors();
+ if (termcap_active)
+ {
+#ifdef FEAT_TERMRESPONSE
+ /* May need to check for T_CRV response. */
+ if (crv_status == CRV_SENT)
+ (void)vpeekc_nomap();
+ /* Check for termcodes first, otherwise an external program may get
+ * them. */
+ check_for_codes_from_term();
+#endif
+ out_str(T_KE); /* stop "keypad transmit" mode */
+ out_flush();
+ termcap_active = FALSE;
+ cursor_on(); /* just in case it is still off */
+ out_str(T_TE); /* stop termcap mode */
+ screen_start(); /* don't know where cursor is now */
+ out_flush();
+ }
+}
+
+#ifdef FEAT_TERMRESPONSE
+/*
+ * Request version string (for xterm) when needed.
+ * Only do this after switching to raw mode, otherwise the result will be
+ * echoed.
+ * Only do this after termcap mode has been started, otherwise the codes for
+ * the cursor keys may be wrong.
+ * The result is caught in check_termcode().
+ */
+ static void
+may_req_termresponse()
+{
+ if (crv_status == CRV_GET
+ && cur_tmode == TMODE_RAW
+ && termcap_active
+#ifdef UNIX
+ && isatty(1)
+#endif
+ && *T_CRV != NUL)
+ {
+ out_str(T_CRV);
+ crv_status = CRV_SENT;
+ /* check for the characters now, otherwise they might be eaten by
+ * get_keystroke() */
+ out_flush();
+ (void)vpeekc_nomap();
+ }
+}
+#endif
+
+/*
+ * Return TRUE when saving and restoring the screen.
+ */
+ int
+swapping_screen()
+{
+ return (full_screen && *T_TI != NUL);
+}
+
+#ifdef FEAT_MOUSE
+/*
+ * setmouse() - switch mouse on/off depending on current mode and 'mouse'
+ */
+ void
+setmouse()
+{
+# ifdef FEAT_MOUSE_TTY
+ int checkfor;
+# endif
+
+# ifdef FEAT_MOUSESHAPE
+ update_mouseshape(-1);
+# endif
+
+# ifdef FEAT_MOUSE_TTY /* Should be outside proc, but may break MOUSESHAPE */
+# ifdef FEAT_GUI
+ /* In the GUI the mouse is always enabled. */
+ if (gui.in_use)
+ return;
+# endif
+ /* be quick when mouse is off */
+ if (*p_mouse == NUL || has_mouse_termcode == 0)
+ return;
+
+ /* don't switch mouse on when not in raw mode (Ex mode) */
+ if (cur_tmode != TMODE_RAW)
+ {
+ mch_setmouse(FALSE);
+ return;
+ }
+
+# ifdef FEAT_VISUAL
+ if (VIsual_active)
+ checkfor = MOUSE_VISUAL;
+ else
+# endif
+ if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
+ checkfor = MOUSE_RETURN;
+ else if (State & INSERT)
+ checkfor = MOUSE_INSERT;
+ else if (State & CMDLINE)
+ checkfor = MOUSE_COMMAND;
+ else if (State == CONFIRM || State == EXTERNCMD)
+ checkfor = ' '; /* don't use mouse for ":confirm" or ":!cmd" */
+ else
+ checkfor = MOUSE_NORMAL; /* assume normal mode */
+
+ if (mouse_has(checkfor))
+ mch_setmouse(TRUE);
+ else
+ mch_setmouse(FALSE);
+# endif
+}
+
+/*
+ * Return TRUE if
+ * - "c" is in 'mouse', or
+ * - 'a' is in 'mouse' and "c" is in MOUSE_A, or
+ * - the current buffer is a help file and 'h' is in 'mouse' and we are in a
+ * normal editing mode (not at hit-return message).
+ */
+ int
+mouse_has(c)
+ int c;
+{
+ char_u *p;
+
+ for (p = p_mouse; *p; ++p)
+ switch (*p)
+ {
+ case 'a': if (vim_strchr((char_u *)MOUSE_A, c) != NULL)
+ return TRUE;
+ break;
+ case MOUSE_HELP: if (c != MOUSE_RETURN && curbuf->b_help)
+ return TRUE;
+ break;
+ default: if (c == *p) return TRUE; break;
+ }
+ return FALSE;
+}
+
+/*
+ * Return TRUE when 'mousemodel' is set to "popup" or "popup_setpos".
+ */
+ int
+mouse_model_popup()
+{
+ return (p_mousem[0] == 'p');
+}
+#endif
+
+/*
+ * By outputting the 'cursor very visible' termcap code, for some windowed
+ * terminals this makes the screen scrolled to the correct position.
+ * Used when starting Vim or returning from a shell.
+ */
+ void
+scroll_start()
+{
+ if (*T_VS != NUL)
+ {
+ out_str(T_VS);
+ out_str(T_VE);
+ screen_start(); /* don't know where cursor is now */
+ }
+}
+
+static int cursor_is_off = FALSE;
+
+/*
+ * Enable the cursor.
+ */
+ void
+cursor_on()
+{
+ if (cursor_is_off)
+ {
+ out_str(T_VE);
+ cursor_is_off = FALSE;
+ }
+}
+
+/*
+ * Disable the cursor.
+ */
+ void
+cursor_off()
+{
+ if (full_screen)
+ {
+ if (!cursor_is_off)
+ out_str(T_VI); /* disable cursor */
+ cursor_is_off = TRUE;
+ }
+}
+
+/*
+ * Set scrolling region for window 'wp'.
+ * The region starts 'off' lines from the start of the window.
+ * Also set the vertical scroll region for a vertically split window. Always
+ * the full width of the window, excluding the vertical separator.
+ */
+ void
+scroll_region_set(wp, off)
+ win_T *wp;
+ int off;
+{
+ OUT_STR(tgoto((char *)T_CS, W_WINROW(wp) + wp->w_height - 1,
+ W_WINROW(wp) + off));
+#ifdef FEAT_VERTSPLIT
+ if (*T_CSV != NUL && wp->w_width != Columns)
+ OUT_STR(tgoto((char *)T_CSV, W_WINCOL(wp) + wp->w_width - 1,
+ W_WINCOL(wp)));
+#endif
+ screen_start(); /* don't know where cursor is now */
+}
+
+/*
+ * Reset scrolling region to the whole screen.
+ */
+ void
+scroll_region_reset()
+{
+ OUT_STR(tgoto((char *)T_CS, (int)Rows - 1, 0));
+#ifdef FEAT_VERTSPLIT
+ if (*T_CSV != NUL)
+ OUT_STR(tgoto((char *)T_CSV, (int)Columns - 1, 0));
+#endif
+ screen_start(); /* don't know where cursor is now */
+}
+
+
+/*
+ * List of terminal codes that are currently recognized.
+ */
+
+struct termcode
+{
+ char_u name[2]; /* termcap name of entry */
+ char_u *code; /* terminal code (in allocated memory) */
+ int len; /* STRLEN(code) */
+} *termcodes = NULL;
+
+static int tc_max_len = 0; /* number of entries that termcodes[] can hold */
+static int tc_len = 0; /* current number of entries in termcodes[] */
+
+ void
+clear_termcodes()
+{
+ while (tc_len > 0)
+ vim_free(termcodes[--tc_len].code);
+ vim_free(termcodes);
+ termcodes = NULL;
+ tc_max_len = 0;
+
+#ifdef HAVE_TGETENT
+ BC = (char *)empty_option;
+ UP = (char *)empty_option;
+ PC = NUL; /* set pad character to NUL */
+ ospeed = 0;
+#endif
+
+ need_gather = TRUE; /* need to fill termleader[] */
+}
+
+/*
+ * Add a new entry to the list of terminal codes.
+ * The list is kept alphabetical for ":set termcap"
+ */
+ void
+add_termcode(name, string, use_8bit)
+ char_u *name;
+ char_u *string;
+ int use_8bit; /* replace 7-bit control by 8-bit one */
+{
+ struct termcode *new_tc;
+ int i, j;
+ char_u *s;
+
+ if (string == NULL || *string == NUL)
+ {
+ del_termcode(name);
+ return;
+ }
+
+ s = vim_strsave(string);
+ if (s == NULL)
+ return;
+
+ /* Change leading <Esc>[ to CSI, change <Esc>O to <M-O>. */
+ if (use_8bit && term_7to8bit(string) != 0)
+ {
+ mch_memmove(s, s + 1, STRLEN(s));
+ s[0] = term_7to8bit(string);
+ }
+
+ need_gather = TRUE; /* need to fill termleader[] */
+
+ /*
+ * need to make space for more entries
+ */
+ if (tc_len == tc_max_len)
+ {
+ tc_max_len += 20;
+ new_tc = (struct termcode *)alloc(
+ (unsigned)(tc_max_len * sizeof(struct termcode)));
+ if (new_tc == NULL)
+ {
+ tc_max_len -= 20;
+ return;
+ }
+ for (i = 0; i < tc_len; ++i)
+ new_tc[i] = termcodes[i];
+ vim_free(termcodes);
+ termcodes = new_tc;
+ }
+
+ /*
+ * Look for existing entry with the same name, it is replaced.
+ * Look for an existing entry that is alphabetical higher, the new entry
+ * is inserted in front of it.
+ */
+ for (i = 0; i < tc_len; ++i)
+ {
+ if (termcodes[i].name[0] < name[0])
+ continue;
+ if (termcodes[i].name[0] == name[0])
+ {
+ if (termcodes[i].name[1] < name[1])
+ continue;
+ /*
+ * Exact match: Replace old code.
+ */
+ if (termcodes[i].name[1] == name[1])
+ {
+ vim_free(termcodes[i].code);
+ --tc_len;
+ break;
+ }
+ }
+ /*
+ * Found alphabetical larger entry, move rest to insert new entry
+ */
+ for (j = tc_len; j > i; --j)
+ termcodes[j] = termcodes[j - 1];
+ break;
+ }
+
+ termcodes[i].name[0] = name[0];
+ termcodes[i].name[1] = name[1];
+ termcodes[i].code = s;
+ termcodes[i].len = (int)STRLEN(s);
+ ++tc_len;
+}
+
+ char_u *
+find_termcode(name)
+ char_u *name;
+{
+ int i;
+
+ for (i = 0; i < tc_len; ++i)
+ if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1])
+ return termcodes[i].code;
+ return NULL;
+}
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+ char_u *
+get_termcode(i)
+ int i;
+{
+ if (i >= tc_len)
+ return NULL;
+ return &termcodes[i].name[0];
+}
+#endif
+
+ void
+del_termcode(name)
+ char_u *name;
+{
+ int i;
+
+ if (termcodes == NULL) /* nothing there yet */
+ return;
+
+ need_gather = TRUE; /* need to fill termleader[] */
+
+ for (i = 0; i < tc_len; ++i)
+ if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1])
+ {
+ del_termcode_idx(i);
+ return;
+ }
+ /* not found. Give error message? */
+}
+
+ static void
+del_termcode_idx(idx)
+ int idx;
+{
+ int i;
+
+ vim_free(termcodes[idx].code);
+ --tc_len;
+ for (i = idx; i < tc_len; ++i)
+ termcodes[i] = termcodes[i + 1];
+}
+
+#ifdef FEAT_TERMRESPONSE
+/*
+ * Called when detected that the terminal sends 8-bit codes.
+ * Convert all 7-bit codes to their 8-bit equivalent.
+ */
+ static void
+switch_to_8bit()
+{
+ int i;
+ int c;
+
+ /* Only need to do something when not already using 8-bit codes. */
+ if (!term_is_8bit(T_NAME))
+ {
+ for (i = 0; i < tc_len; ++i)
+ {
+ c = term_7to8bit(termcodes[i].code);
+ if (c != 0)
+ {
+ mch_memmove(termcodes[i].code + 1, termcodes[i].code + 2,
+ STRLEN(termcodes[i].code + 1));
+ termcodes[i].code[0] = c;
+ }
+ }
+ need_gather = TRUE; /* need to fill termleader[] */
+ }
+ detected_8bit = TRUE;
+}
+#endif
+
+#ifdef CHECK_DOUBLE_CLICK
+static linenr_T orig_topline = 0;
+# ifdef FEAT_DIFF
+static int orig_topfill = 0;
+# endif
+#endif
+#if (defined(FEAT_WINDOWS) && defined(CHECK_DOUBLE_CLICK)) || defined(PROTO)
+/*
+ * Checking for double clicks ourselves.
+ * "orig_topline" is used to avoid detecting a double-click when the window
+ * contents scrolled (e.g., when 'scrolloff' is non-zero).
+ */
+/*
+ * Set orig_topline. Used when jumping to another window, so that a double
+ * click still works.
+ */
+ void
+set_mouse_topline(wp)
+ win_T *wp;
+{
+ orig_topline = wp->w_topline;
+# ifdef FEAT_DIFF
+ orig_topfill = wp->w_topfill;
+# endif
+}
+#endif
+
+/*
+ * Check if typebuf.tb_buf[] contains a terminal key code.
+ * Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off
+ * + max_offset].
+ * Return 0 for no match, -1 for partial match, > 0 for full match.
+ * With a match, the match is removed, the replacement code is inserted in
+ * typebuf.tb_buf[] and the number of characters in typebuf.tb_buf[] is
+ * returned.
+ * When "buf" is not NULL, it is used instead of typebuf.tb_buf[]. "buflen" is
+ * then the length of the string in buf[].
+ */
+ int
+check_termcode(max_offset, buf, buflen)
+ int max_offset;
+ char_u *buf;
+ int buflen;
+{
+ char_u *tp;
+ char_u *p;
+ int slen = 0; /* init for GCC */
+ int len;
+ int offset;
+ char_u key_name[2];
+ int new_slen;
+ int extra;
+ char_u string[MAX_KEY_CODE_LEN + 1];
+ int i, j;
+ int idx = 0;
+#ifdef FEAT_MOUSE
+# if !defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_GUI)
+ char_u bytes[6];
+ int num_bytes;
+# endif
+ int mouse_code = 0; /* init for GCC */
+ int modifiers;
+ int is_click, is_drag;
+ int wheel_code = 0;
+ int current_button;
+ static int held_button = MOUSE_RELEASE;
+ static int orig_num_clicks = 1;
+ static int orig_mouse_code = 0x0;
+# ifdef CHECK_DOUBLE_CLICK
+ static int orig_mouse_col = 0;
+ static int orig_mouse_row = 0;
+ static struct timeval orig_mouse_time = {0, 0};
+ /* time of previous mouse click */
+ struct timeval mouse_time; /* time of current mouse click */
+ long timediff; /* elapsed time in msec */
+# endif
+#endif
+ int cpo_koffset;
+#ifdef FEAT_MOUSE_GPM
+ extern int gpm_flag; /* gpm library variable */
+#endif
+
+ cpo_koffset = (vim_strchr(p_cpo, CPO_KOFFSET) != NULL);
+
+ /*
+ * Speed up the checks for terminal codes by gathering all first bytes
+ * used in termleader[]. Often this is just a single <Esc>.
+ */
+ if (need_gather)
+ gather_termleader();
+
+ /*
+ * Check at several positions in typebuf.tb_buf[], to catch something like
+ * "x<Up>" that can be mapped. Stop at max_offset, because characters
+ * after that cannot be used for mapping, and with @r commands
+ * typebuf.tb_buf[]
+ * can become very long.
+ * This is used often, KEEP IT FAST!
+ */
+ for (offset = 0; offset < max_offset; ++offset)
+ {
+ if (buf == NULL)
+ {
+ if (offset >= typebuf.tb_len)
+ break;
+ tp = typebuf.tb_buf + typebuf.tb_off + offset;
+ len = typebuf.tb_len - offset; /* length of the input */
+ }
+ else
+ {
+ if (offset >= buflen)
+ break;
+ tp = buf + offset;
+ len = buflen - offset;
+ }
+
+ /*
+ * Don't check characters after K_SPECIAL, those are already
+ * translated terminal chars (avoid translating ~@^Hx).
+ */
+ if (*tp == K_SPECIAL)
+ {
+ offset += 2; /* there are always 2 extra characters */
+ continue;
+ }
+
+ /*
+ * Skip this position if the character does not appear as the first
+ * character in term_strings. This speeds up a lot, since most
+ * termcodes start with the same character (ESC or CSI).
+ */
+ i = *tp;
+ for (p = termleader; *p && *p != i; ++p)
+ ;
+ if (*p == NUL)
+ continue;
+
+ /*
+ * Skip this position if p_ek is not set and tp[0] is an ESC and we
+ * are in Insert mode.
+ */
+ if (*tp == ESC && !p_ek && (State & INSERT))
+ continue;
+
+ new_slen = 0; /* Length of what will replace the termcode */
+ key_name[0] = NUL; /* no key name found yet */
+
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ /*
+ * GUI special key codes are all of the form [CSI xx].
+ */
+ if (*tp == CSI) /* Special key from GUI */
+ {
+ if (len < 3)
+ return -1; /* Shouldn't happen */
+ slen = 3;
+ key_name[0] = tp[1];
+ key_name[1] = tp[2];
+ }
+ }
+ else
+#endif /* FEAT_GUI */
+ {
+ for (idx = 0; idx < tc_len; ++idx)
+ {
+ /*
+ * Ignore the entry if we are not at the start of
+ * typebuf.tb_buf[]
+ * and there are not enough characters to make a match.
+ * But only when the 'K' flag is in 'cpoptions'.
+ */
+ slen = termcodes[idx].len;
+ if (cpo_koffset && offset && len < slen)
+ continue;
+ if (STRNCMP(termcodes[idx].code, tp,
+ (size_t)(slen > len ? len : slen)) == 0)
+ {
+ if (len < slen) /* got a partial sequence */
+ return -1; /* need to get more chars */
+
+ /*
+ * When found a keypad key, check if there is another key
+ * that matches and use that one. This makes <Home> to be
+ * found instead of <kHome> when they produce the same
+ * key code.
+ */
+ if (termcodes[idx].name[0] == 'K'
+ && VIM_ISDIGIT(termcodes[idx].name[1]))
+ {
+ for (j = idx + 1; j < tc_len; ++j)
+ if (termcodes[j].len == slen &&
+ STRNCMP(termcodes[idx].code,
+ termcodes[j].code, slen) == 0)
+ {
+ idx = j;
+ break;
+ }
+ }
+
+ key_name[0] = termcodes[idx].name[0];
+ key_name[1] = termcodes[idx].name[1];
+
+ break;
+ }
+ }
+ }
+
+#ifdef FEAT_TERMRESPONSE
+ if (key_name[0] == NUL)
+ {
+ /* Check for xterm version string: "<Esc>[>{x};{vers};{y}c". Also
+ * eat other possible responses to t_RV, rxvt returns
+ * "<Esc>[?1;2c". Also accept CSI instead of <Esc>[. */
+ if (*T_CRV != NUL && ((tp[0] == ESC && tp[1] == '[' && len >= 3)
+ || (tp[0] == CSI && len >= 2)))
+ {
+ j = 0;
+ extra = 0;
+ for (i = 2 + (tp[0] != CSI);
+ i < len && (VIM_ISDIGIT(tp[i])
+ || tp[i] == ';' || tp[i] == '.'); ++i)
+ if (tp[i] == ';' && ++j == 1)
+ extra = atoi((char *)tp + i + 1);
+ if (i == len)
+ return -1; /* not enough characters */
+
+ /* eat it when at least one digit and ending in 'c' */
+ if (i > 2 + (tp[0] != CSI) && tp[i] == 'c')
+ {
+ crv_status = CRV_GOT;
+
+ /* If this code starts with CSI, you can bet that the
+ * terminal uses 8-bit codes. */
+ if (tp[0] == CSI)
+ switch_to_8bit();
+
+ /* rxvt sends its version number: "20703" is 2.7.3.
+ * Ignore it for when the user has set 'term' to xterm,
+ * even though it's an rxvt. */
+ if (extra > 20000)
+ extra = 0;
+
+ if (tp[1 + (tp[0] != CSI)] == '>' && j == 2)
+ {
+ /* if xterm version >= 95 use mouse dragging */
+ if (extra >= 95)
+ set_option_value((char_u *)"ttym", 0L,
+ (char_u *)"xterm2", 0);
+ /* if xterm version >= 141 try to get termcap codes */
+ if (extra >= 141)
+ {
+ check_for_codes = TRUE;
+ need_gather = TRUE;
+ req_codes_from_term();
+ }
+ }
+# ifdef FEAT_EVAL
+ set_vim_var_string(VV_TERMRESPONSE, tp, i + 1);
+# endif
+# ifdef FEAT_AUTOCMD
+ apply_autocmds(EVENT_TERMRESPONSE,
+ NULL, NULL, FALSE, curbuf);
+# endif
+ key_name[0] = (int)KS_EXTRA;
+ key_name[1] = (int)KE_IGNORE;
+ slen = i + 1;
+ }
+ }
+
+ /* Check for '<Esc>P1+r<hex bytes><Esc>\'. A "0" instead of the
+ * "1" means an invalid request. */
+ else if (check_for_codes
+ && ((tp[0] == ESC && tp[1] == 'P' && len >= 2)
+ || tp[0] == DCS))
+ {
+ j = 1 + (tp[0] != DCS);
+ for (i = j; i < len; ++i)
+ if ((tp[i] == ESC && tp[i + 1] == '\\' && i + 1 < len)
+ || tp[i] == STERM)
+ {
+ if (i - j >= 3 && tp[j + 1] == '+' && tp[j + 2] == 'r')
+ got_code_from_term(tp + j, i);
+ key_name[0] = (int)KS_EXTRA;
+ key_name[1] = (int)KE_IGNORE;
+ slen = i + 1 + (tp[i] == ESC);
+ break;
+ }
+
+ if (i == len)
+ return -1; /* not enough characters */
+ }
+ }
+#endif
+
+ if (key_name[0] == NUL)
+ continue; /* No match at this position, try next one */
+
+ /* We only get here when we have a complete termcode match */
+
+#ifdef FEAT_MOUSE
+# ifdef FEAT_GUI
+ /*
+ * Only in the GUI: Fetch the pointer coordinates of the scroll event
+ * so that we know which window to scroll later.
+ */
+ if (gui.in_use
+ && key_name[0] == (int)KS_EXTRA
+ && (key_name[1] == (int)KE_X1MOUSE
+ || key_name[1] == (int)KE_X2MOUSE
+ || key_name[1] == (int)KE_MOUSEDOWN
+ || key_name[1] == (int)KE_MOUSEUP))
+ {
+ num_bytes = get_bytes_from_buf(tp + slen, bytes, 4);
+ if (num_bytes == -1) /* not enough coordinates */
+ return -1;
+ mouse_col = 128 * (bytes[0] - ' ' - 1) + bytes[1] - ' ' - 1;
+ mouse_row = 128 * (bytes[2] - ' ' - 1) + bytes[3] - ' ' - 1;
+ slen += num_bytes;
+ }
+ else
+# endif
+ /*
+ * If it is a mouse click, get the coordinates.
+ */
+ if (key_name[0] == (int)KS_MOUSE
+# ifdef FEAT_MOUSE_JSB
+ || key_name[0] == (int)KS_JSBTERM_MOUSE
+# endif
+# ifdef FEAT_MOUSE_NET
+ || key_name[0] == (int)KS_NETTERM_MOUSE
+# endif
+# ifdef FEAT_MOUSE_DEC
+ || key_name[0] == (int)KS_DEC_MOUSE
+# endif
+# ifdef FEAT_MOUSE_PTERM
+ || key_name[0] == (int)KS_PTERM_MOUSE
+# endif
+ )
+ {
+ is_click = is_drag = FALSE;
+
+# if !defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_GUI)
+ if (key_name[0] == (int)KS_MOUSE)
+ {
+ /*
+ * For xterm and MSDOS we get "<t_mouse>scr", where
+ * s == encoded button state:
+ * 0x20 = left button down
+ * 0x21 = middle button down
+ * 0x22 = right button down
+ * 0x23 = any button release
+ * 0x60 = button 4 down (scroll wheel down)
+ * 0x61 = button 5 down (scroll wheel up)
+ * add 0x04 for SHIFT
+ * add 0x08 for ALT
+ * add 0x10 for CTRL
+ * add 0x20 for mouse drag (0x40 is drag with left button)
+ * c == column + ' ' + 1 == column + 33
+ * r == row + ' ' + 1 == row + 33
+ *
+ * The coordinates are passed on through global variables.
+ * Ugly, but this avoids trouble with mouse clicks at an
+ * unexpected moment and allows for mapping them.
+ */
+ for (;;)
+ {
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ /* GUI uses more bits for columns > 223 */
+ num_bytes = get_bytes_from_buf(tp + slen, bytes, 5);
+ if (num_bytes == -1) /* not enough coordinates */
+ return -1;
+ mouse_code = bytes[0];
+ mouse_col = 128 * (bytes[1] - ' ' - 1)
+ + bytes[2] - ' ' - 1;
+ mouse_row = 128 * (bytes[3] - ' ' - 1)
+ + bytes[4] - ' ' - 1;
+ }
+ else
+#endif
+ {
+ num_bytes = get_bytes_from_buf(tp + slen, bytes, 3);
+ if (num_bytes == -1) /* not enough coordinates */
+ return -1;
+ mouse_code = bytes[0];
+ mouse_col = bytes[1] - ' ' - 1;
+ mouse_row = bytes[2] - ' ' - 1;
+ }
+ slen += num_bytes;
+
+ /* If the following bytes is also a mouse code and it has
+ * the same code, dump this one and get the next. This
+ * makes dragging a whole lot faster. */
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ j = 3;
+ else
+#endif
+ j = termcodes[idx].len;
+ if (STRNCMP(tp, tp + slen, (size_t)j) == 0
+ && tp[slen + j] == mouse_code
+ && tp[slen + j + 1] != NUL
+ && tp[slen + j + 2] != NUL
+#ifdef FEAT_GUI
+ && (!gui.in_use
+ || (tp[slen + j + 3] != NUL
+ && tp[slen + j + 4] != NUL))
+#endif
+ )
+ slen += j;
+ else
+ break;
+ }
+
+# if !defined(MSWIN) && !defined(MSDOS)
+ /*
+ * Handle mouse events.
+ * Recognize the xterm mouse wheel, but not in the GUI, the
+ * Linux console with GPM and the MS-DOS or Win32 console
+ * (multi-clicks use >= 0x60).
+ */
+ if (mouse_code >= MOUSEWHEEL_LOW
+# ifdef FEAT_GUI
+ && !gui.in_use
+# endif
+# ifdef FEAT_MOUSE_GPM
+ && gpm_flag == 0
+# endif
+ )
+ {
+ /* Keep the mouse_code before it's changed, so that we
+ * remember that it was a mouse wheel click. */
+ wheel_code = mouse_code;
+ }
+# ifdef FEAT_MOUSE_XTERM
+ else if (held_button == MOUSE_RELEASE
+# ifdef FEAT_GUI
+ && !gui.in_use
+# endif
+ && (mouse_code == 0x23 || mouse_code == 0x24))
+ {
+ /* Apparently used by rxvt scroll wheel. */
+ wheel_code = mouse_code - 0x23 + MOUSEWHEEL_LOW;
+ }
+# endif
+
+# if defined(UNIX) && defined(FEAT_MOUSE_TTY)
+ else if (use_xterm_mouse() > 1)
+ {
+ if (mouse_code & MOUSE_DRAG_XTERM)
+ mouse_code |= MOUSE_DRAG;
+ }
+# endif
+# ifdef FEAT_XCLIPBOARD
+ else if (!(mouse_code & MOUSE_DRAG & ~MOUSE_CLICK_MASK))
+ {
+ if ((mouse_code & MOUSE_RELEASE) == MOUSE_RELEASE)
+ stop_xterm_trace();
+ else
+ start_xterm_trace(mouse_code);
+ }
+# endif
+# endif
+ }
+# endif /* !UNIX || FEAT_MOUSE_XTERM */
+# ifdef FEAT_MOUSE_NET
+ if (key_name[0] == (int)KS_NETTERM_MOUSE)
+ {
+ int mc, mr;
+
+ /* expect a rather limited sequence like: balancing {
+ * \033}6,45\r
+ * '6' is the row, 45 is the column
+ */
+ p = tp + slen;
+ mr = getdigits(&p);
+ if (*p++ != ',')
+ return -1;
+ mc = getdigits(&p);
+ if (*p++ != '\r')
+ return -1;
+
+ mouse_col = mc - 1;
+ mouse_row = mr - 1;
+ mouse_code = MOUSE_LEFT;
+ slen += (int)(p - (tp + slen));
+ }
+# endif /* FEAT_MOUSE_NET */
+# ifdef FEAT_MOUSE_JSB
+ if (key_name[0] == (int)KS_JSBTERM_MOUSE)
+ {
+ int mult, val, iter, button, status;
+
+ /* JSBTERM Input Model
+ * \033[0~zw uniq escape sequence
+ * (L-x) Left button pressed - not pressed x not reporting
+ * (M-x) Middle button pressed - not pressed x not reporting
+ * (R-x) Right button pressed - not pressed x not reporting
+ * (SDmdu) Single , Double click, m mouse move d button down
+ * u button up
+ * ### X cursor position padded to 3 digits
+ * ### Y cursor position padded to 3 digits
+ * (s-x) SHIFT key pressed - not pressed x not reporting
+ * (c-x) CTRL key pressed - not pressed x not reporting
+ * \033\\ terminateing sequence
+ */
+
+ p = tp + slen;
+ button = mouse_code = 0;
+ switch (*p++)
+ {
+ case 'L': button = 1; break;
+ case '-': break;
+ case 'x': break; /* ignore sequence */
+ default: return -1; /* Unknown Result */
+ }
+ switch (*p++)
+ {
+ case 'M': button |= 2; break;
+ case '-': break;
+ case 'x': break; /* ignore sequence */
+ default: return -1; /* Unknown Result */
+ }
+ switch (*p++)
+ {
+ case 'R': button |= 4; break;
+ case '-': break;
+ case 'x': break; /* ignore sequence */
+ default: return -1; /* Unknown Result */
+ }
+ status = *p++;
+ for (val = 0, mult = 100, iter = 0; iter < 3; iter++,
+ mult /= 10, p++)
+ if (*p >= '0' && *p <= '9')
+ val += (*p - '0') * mult;
+ else
+ return -1;
+ mouse_col = val;
+ for (val = 0, mult = 100, iter = 0; iter < 3; iter++,
+ mult /= 10, p++)
+ if (*p >= '0' && *p <= '9')
+ val += (*p - '0') * mult;
+ else
+ return -1;
+ mouse_row = val;
+ switch (*p++)
+ {
+ case 's': button |= 8; break; /* SHIFT key Pressed */
+ case '-': break; /* Not Pressed */
+ case 'x': break; /* Not Reporting */
+ default: return -1; /* Unknown Result */
+ }
+ switch (*p++)
+ {
+ case 'c': button |= 16; break; /* CTRL key Pressed */
+ case '-': break; /* Not Pressed */
+ case 'x': break; /* Not Reporting */
+ default: return -1; /* Unknown Result */
+ }
+ if (*p++ != '\033')
+ return -1;
+ if (*p++ != '\\')
+ return -1;
+ switch (status)
+ {
+ case 'D': /* Double Click */
+ case 'S': /* Single Click */
+ if (button & 1) mouse_code |= MOUSE_LEFT;
+ if (button & 2) mouse_code |= MOUSE_MIDDLE;
+ if (button & 4) mouse_code |= MOUSE_RIGHT;
+ if (button & 8) mouse_code |= MOUSE_SHIFT;
+ if (button & 16) mouse_code |= MOUSE_CTRL;
+ break;
+ case 'm': /* Mouse move */
+ if (button & 1) mouse_code |= MOUSE_LEFT;
+ if (button & 2) mouse_code |= MOUSE_MIDDLE;
+ if (button & 4) mouse_code |= MOUSE_RIGHT;
+ if (button & 8) mouse_code |= MOUSE_SHIFT;
+ if (button & 16) mouse_code |= MOUSE_CTRL;
+ if ((button & 7) != 0)
+ {
+ held_button = mouse_code;
+ mouse_code |= MOUSE_DRAG;
+ }
+ is_drag = TRUE;
+ showmode();
+ break;
+ case 'd': /* Button Down */
+ if (button & 1) mouse_code |= MOUSE_LEFT;
+ if (button & 2) mouse_code |= MOUSE_MIDDLE;
+ if (button & 4) mouse_code |= MOUSE_RIGHT;
+ if (button & 8) mouse_code |= MOUSE_SHIFT;
+ if (button & 16) mouse_code |= MOUSE_CTRL;
+ break;
+ case 'u': /* Button Up */
+ if (button & 1)
+ mouse_code |= MOUSE_LEFT | MOUSE_RELEASE;
+ if (button & 2)
+ mouse_code |= MOUSE_MIDDLE | MOUSE_RELEASE;
+ if (button & 4)
+ mouse_code |= MOUSE_RIGHT | MOUSE_RELEASE;
+ if (button & 8)
+ mouse_code |= MOUSE_SHIFT;
+ if (button & 16)
+ mouse_code |= MOUSE_CTRL;
+ break;
+ default: return -1; /* Unknown Result */
+ }
+
+ slen += (p - (tp + slen));
+ }
+# endif /* FEAT_MOUSE_JSB */
+# ifdef FEAT_MOUSE_DEC
+ if (key_name[0] == (int)KS_DEC_MOUSE)
+ {
+ /* The DEC Locator Input Model
+ * Netterm delivers the code sequence:
+ * \033[2;4;24;80&w (left button down)
+ * \033[3;0;24;80&w (left button up)
+ * \033[6;1;24;80&w (right button down)
+ * \033[7;0;24;80&w (right button up)
+ * CSI Pe ; Pb ; Pr ; Pc ; Pp & w
+ * Pe is the event code
+ * Pb is the button code
+ * Pr is the row coordinate
+ * Pc is the column coordinate
+ * Pp is the third coordinate (page number)
+ * Pe, the event code indicates what event caused this report
+ * The following event codes are defined:
+ * 0 - request, the terminal received an explicit request
+ * for a locator report, but the locator is unavailable
+ * 1 - request, the terminal received an explicit request
+ * for a locator report
+ * 2 - left button down
+ * 3 - left button up
+ * 4 - middle button down
+ * 5 - middle button up
+ * 6 - right button down
+ * 7 - right button up
+ * 8 - fourth button down
+ * 9 - fourth button up
+ * 10 - locator outside filter rectangle
+ * Pb, the button code, ASCII decimal 0-15 indicating which
+ * buttons are down if any. The state of the four buttons
+ * on the locator correspond to the low four bits of the
+ * decimal value,
+ * "1" means button depressed
+ * 0 - no buttons down,
+ * 1 - right,
+ * 2 - middle,
+ * 4 - left,
+ * 8 - fourth
+ * Pr is the row coordinate of the locator position in the page,
+ * encoded as an ASCII decimal value.
+ * If Pr is omitted, the locator position is undefined
+ * (outside the terminal window for example).
+ * Pc is the column coordinate of the locator position in the
+ * page, encoded as an ASCII decimal value.
+ * If Pc is omitted, the locator position is undefined
+ * (outside the terminal window for example).
+ * Pp is the page coordinate of the locator position
+ * encoded as an ASCII decimal value.
+ * The page coordinate may be omitted if the locator is on
+ * page one (the default). We ignore it anyway.
+ */
+ int Pe, Pb, Pr, Pc;
+
+ p = tp + slen;
+
+ /* get event status */
+ Pe = getdigits(&p);
+ if (*p++ != ';')
+ return -1;
+
+ /* get button status */
+ Pb = getdigits(&p);
+ if (*p++ != ';')
+ return -1;
+
+ /* get row status */
+ Pr = getdigits(&p);
+ if (*p++ != ';')
+ return -1;
+
+ /* get column status */
+ Pc = getdigits(&p);
+
+ /* the page parameter is optional */
+ if (*p == ';')
+ {
+ p++;
+ (void)getdigits(&p);
+ }
+ if (*p++ != '&')
+ return -1;
+ if (*p++ != 'w')
+ return -1;
+
+ mouse_code = 0;
+ switch (Pe)
+ {
+ case 0: return -1; /* position request while unavailable */
+ case 1: /* a response to a locator position request includes
+ the status of all buttons */
+ Pb &= 7; /* mask off and ignore fourth button */
+ if (Pb & 4)
+ mouse_code = MOUSE_LEFT;
+ if (Pb & 2)
+ mouse_code = MOUSE_MIDDLE;
+ if (Pb & 1)
+ mouse_code = MOUSE_RIGHT;
+ if (Pb)
+ {
+ held_button = mouse_code;
+ mouse_code |= MOUSE_DRAG;
+ WantQueryMouse = 1;
+ }
+ is_drag = TRUE;
+ showmode();
+ break;
+ case 2: mouse_code = MOUSE_LEFT;
+ WantQueryMouse = 1;
+ break;
+ case 3: mouse_code = MOUSE_RELEASE | MOUSE_LEFT;
+ break;
+ case 4: mouse_code = MOUSE_MIDDLE;
+ WantQueryMouse = 1;
+ break;
+ case 5: mouse_code = MOUSE_RELEASE | MOUSE_MIDDLE;
+ break;
+ case 6: mouse_code = MOUSE_RIGHT;
+ WantQueryMouse = 1;
+ break;
+ case 7: mouse_code = MOUSE_RELEASE | MOUSE_RIGHT;
+ break;
+ case 8: return -1; /* fourth button down */
+ case 9: return -1; /* fourth button up */
+ case 10: return -1; /* mouse outside of filter rectangle */
+ default: return -1; /* should never occur */
+ }
+
+ mouse_col = Pc - 1;
+ mouse_row = Pr - 1;
+
+ slen += (int)(p - (tp + slen));
+ }
+# endif /* FEAT_MOUSE_DEC */
+# ifdef FEAT_MOUSE_PTERM
+ if (key_name[0] == (int)KS_PTERM_MOUSE)
+ {
+ int button, num_clicks, action, mc, mr;
+
+ p = tp + slen;
+
+ action = getdigits(&p);
+ if (*p++ != ';')
+ return -1;
+
+ mouse_row = getdigits(&p);
+ if (*p++ != ';')
+ return -1;
+ mouse_col = getdigits(&p);
+ if (*p++ != ';')
+ return -1;
+
+ button = getdigits(&p);
+ mouse_code = 0;
+
+ switch( button )
+ {
+ case 4: mouse_code = MOUSE_LEFT; break;
+ case 1: mouse_code = MOUSE_RIGHT; break;
+ case 2: mouse_code = MOUSE_MIDDLE; break;
+ default: return -1;
+ }
+
+ switch( action )
+ {
+ case 31: /* Initial press */
+ if (*p++ != ';')
+ return -1;
+
+ num_clicks = getdigits(&p); /* Not used */
+ break;
+
+ case 32: /* Release */
+ mouse_code |= MOUSE_RELEASE;
+ break;
+
+ case 33: /* Drag */
+ held_button = mouse_code;
+ mouse_code |= MOUSE_DRAG;
+ break;
+
+ default:
+ return -1;
+ }
+
+ if (*p++ != 't')
+ return -1;
+
+ slen += (p - (tp + slen));
+ }
+# endif /* FEAT_MOUSE_PTERM */
+
+ /* Interpret the mouse code */
+ current_button = (mouse_code & MOUSE_CLICK_MASK);
+ if (current_button == MOUSE_RELEASE
+# ifdef FEAT_MOUSE_XTERM
+ && wheel_code == 0
+# endif
+ )
+ {
+ /*
+ * If we get a mouse drag or release event when
+ * there is no mouse button held down (held_button ==
+ * MOUSE_RELEASE), produce a K_IGNORE below.
+ * (can happen when you hold down two buttons
+ * and then let them go, or click in the menu bar, but not
+ * on a menu, and drag into the text).
+ */
+ if ((mouse_code & MOUSE_DRAG) == MOUSE_DRAG)
+ is_drag = TRUE;
+ current_button = held_button;
+ }
+ else if (wheel_code == 0)
+ {
+# ifdef CHECK_DOUBLE_CLICK
+# ifdef FEAT_MOUSE_GPM
+# ifdef FEAT_GUI
+ /*
+ * Only for Unix, when GUI or gpm is not active, we handle
+ * multi-clicks here.
+ */
+ if (gpm_flag == 0 && !gui.in_use)
+# else
+ if (gpm_flag == 0)
+# endif
+# else
+# ifdef FEAT_GUI
+ if (!gui.in_use)
+# endif
+# endif
+ {
+ /*
+ * Compute the time elapsed since the previous mouse click.
+ */
+ gettimeofday(&mouse_time, NULL);
+ timediff = (mouse_time.tv_usec
+ - orig_mouse_time.tv_usec) / 1000;
+ if (timediff < 0)
+ --orig_mouse_time.tv_sec;
+ timediff += (mouse_time.tv_sec
+ - orig_mouse_time.tv_sec) * 1000;
+ orig_mouse_time = mouse_time;
+ if (mouse_code == orig_mouse_code
+ && timediff < p_mouset
+ && orig_num_clicks != 4
+ && orig_mouse_col == mouse_col
+ && orig_mouse_row == mouse_row
+#ifdef FEAT_DIFF
+ && orig_topfill == curwin->w_topfill
+#endif
+ && orig_topline == curwin->w_topline)
+ ++orig_num_clicks;
+ else
+ orig_num_clicks = 1;
+ orig_mouse_col = mouse_col;
+ orig_mouse_row = mouse_row;
+ orig_topline = curwin->w_topline;
+#ifdef FEAT_DIFF
+ orig_topfill = curwin->w_topfill;
+#endif
+ }
+# if defined(FEAT_GUI) || defined(FEAT_MOUSE_GPM)
+ else
+ orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
+# endif
+# else
+ orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
+# endif
+ is_click = TRUE;
+ orig_mouse_code = mouse_code;
+ }
+ if (!is_drag)
+ held_button = mouse_code & MOUSE_CLICK_MASK;
+
+ /*
+ * Translate the actual mouse event into a pseudo mouse event.
+ * First work out what modifiers are to be used.
+ */
+ modifiers = 0x0;
+ if (orig_mouse_code & MOUSE_SHIFT)
+ modifiers |= MOD_MASK_SHIFT;
+ if (orig_mouse_code & MOUSE_CTRL)
+ modifiers |= MOD_MASK_CTRL;
+ if (orig_mouse_code & MOUSE_ALT)
+ modifiers |= MOD_MASK_ALT;
+ if (orig_num_clicks == 2)
+ modifiers |= MOD_MASK_2CLICK;
+ else if (orig_num_clicks == 3)
+ modifiers |= MOD_MASK_3CLICK;
+ else if (orig_num_clicks == 4)
+ modifiers |= MOD_MASK_4CLICK;
+
+ /* Add the modifier codes to our string */
+ if (modifiers != 0)
+ {
+ string[new_slen++] = K_SPECIAL;
+ string[new_slen++] = (int)KS_MODIFIER;
+ string[new_slen++] = modifiers;
+ }
+
+ /* Work out our pseudo mouse event */
+ key_name[0] = (int)KS_EXTRA;
+ if (wheel_code != 0)
+ key_name[1] = (wheel_code & 1)
+ ? (int)KE_MOUSEUP : (int)KE_MOUSEDOWN;
+ else
+ key_name[1] = get_pseudo_mouse_code(current_button,
+ is_click, is_drag);
+ }
+#endif /* FEAT_MOUSE */
+
+#ifdef FEAT_GUI
+ /*
+ * If using the GUI, then we get menu and scrollbar events.
+ *
+ * A menu event is encoded as K_SPECIAL, KS_MENU, KE_FILLER followed by
+ * four bytes which are to be taken as a pointer to the vimmenu_T
+ * structure.
+ *
+ * A scrollbar event is K_SPECIAL, KS_VER_SCROLLBAR, KE_FILLER followed
+ * by one byte representing the scrollbar number, and then four bytes
+ * representing a long_u which is the new value of the scrollbar.
+ *
+ * A horizontal scrollbar event is K_SPECIAL, KS_HOR_SCROLLBAR,
+ * KE_FILLER followed by four bytes representing a long_u which is the
+ * new value of the scrollbar.
+ */
+# ifdef FEAT_MENU
+ else if (key_name[0] == (int)KS_MENU)
+ {
+ long_u val;
+
+ num_bytes = get_long_from_buf(tp + slen, &val);
+ if (num_bytes == -1)
+ return -1;
+ current_menu = (vimmenu_T *)val;
+ slen += num_bytes;
+ }
+# endif
+# ifndef USE_ON_FLY_SCROLL
+ else if (key_name[0] == (int)KS_VER_SCROLLBAR)
+ {
+ long_u val;
+
+ /* Get the last scrollbar event in the queue of the same type */
+ j = 0;
+ for (i = 0; tp[j] == CSI && tp[j + 1] == KS_VER_SCROLLBAR
+ && tp[j + 2] != NUL; ++i)
+ {
+ j += 3;
+ num_bytes = get_bytes_from_buf(tp + j, bytes, 1);
+ if (num_bytes == -1)
+ break;
+ if (i == 0)
+ current_scrollbar = (int)bytes[0];
+ else if (current_scrollbar != (int)bytes[0])
+ break;
+ j += num_bytes;
+ num_bytes = get_long_from_buf(tp + j, &val);
+ if (num_bytes == -1)
+ break;
+ scrollbar_value = val;
+ j += num_bytes;
+ slen = j;
+ }
+ if (i == 0) /* not enough characters to make one */
+ return -1;
+ }
+ else if (key_name[0] == (int)KS_HOR_SCROLLBAR)
+ {
+ long_u val;
+
+ /* Get the last horiz. scrollbar event in the queue */
+ j = 0;
+ for (i = 0; tp[j] == CSI && tp[j + 1] == KS_HOR_SCROLLBAR
+ && tp[j + 2] != NUL; ++i)
+ {
+ j += 3;
+ num_bytes = get_long_from_buf(tp + j, &val);
+ if (num_bytes == -1)
+ break;
+ scrollbar_value = val;
+ j += num_bytes;
+ slen = j;
+ }
+ if (i == 0) /* not enough characters to make one */
+ return -1;
+ }
+# endif /* !USE_ON_FLY_SCROLL */
+#endif /* FEAT_GUI */
+
+ /* Finally, add the special key code to our string */
+ if (key_name[0] == KS_KEY)
+ string[new_slen++] = key_name[1]; /* from ":set <M-b>=xx" */
+ else
+ {
+ string[new_slen++] = K_SPECIAL;
+ string[new_slen++] = key_name[0];
+ string[new_slen++] = key_name[1];
+ }
+ string[new_slen] = NUL;
+ extra = new_slen - slen;
+ if (buf == NULL)
+ {
+ if (extra < 0)
+ /* remove matched chars, taking care of noremap */
+ del_typebuf(-extra, offset);
+ else if (extra > 0)
+ /* insert the extra space we need */
+ ins_typebuf(string + slen, REMAP_YES, offset, FALSE, FALSE);
+
+ /*
+ * Careful: del_typebuf() and ins_typebuf() may have reallocated
+ * typebuf.tb_buf[]!
+ */
+ mch_memmove(typebuf.tb_buf + typebuf.tb_off + offset, string,
+ (size_t)new_slen);
+ }
+ else
+ {
+ if (extra < 0)
+ /* remove matched characters */
+ mch_memmove(buf + offset, buf + offset - extra,
+ (size_t)(buflen + offset + extra));
+ else if (extra > 0)
+ /* insert the extra space we need */
+ mch_memmove(buf + offset + extra, buf + offset,
+ (size_t)(buflen - offset));
+ mch_memmove(buf + offset, string, (size_t)new_slen);
+ }
+ return (len + extra + offset);
+ }
+
+ return 0; /* no match found */
+}
+
+/*
+ * Replace any terminal code strings in from[] with the equivalent internal
+ * vim representation. This is used for the "from" and "to" part of a
+ * mapping, and the "to" part of a menu command.
+ * Any strings like "<C-UP>" are also replaced, unless 'cpoptions' contains
+ * '<'.
+ * K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL KE_FILLER.
+ *
+ * The replacement is done in result[] and finally copied into allocated
+ * memory. If this all works well *bufp is set to the allocated memory and a
+ * pointer to it is returned. If something fails *bufp is set to NULL and from
+ * is returned.
+ *
+ * CTRL-V characters are removed. When "from_part" is TRUE, a trailing CTRL-V
+ * is included, otherwise it is removed (for ":map xx ^V", maps xx to
+ * nothing). When 'cpoptions' does not contain 'B', a backslash can be used
+ * instead of a CTRL-V.
+ */
+ char_u *
+replace_termcodes(from, bufp, from_part, do_lt)
+ char_u *from;
+ char_u **bufp;
+ int from_part;
+ int do_lt; /* also translate <lt> */
+{
+ int i;
+ int slen;
+ int key;
+ int dlen = 0;
+ char_u *src;
+ int do_backslash; /* backslash is a special character */
+ int do_special; /* recognize <> key codes */
+ int do_key_code; /* recognize raw key codes */
+ char_u *result; /* buffer for resulting string */
+
+ do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
+ do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL);
+ do_key_code = (vim_strchr(p_cpo, CPO_KEYCODE) == NULL);
+
+ /*
+ * Allocate space for the translation. Worst case a single character is
+ * replaced by 6 bytes (shifted special key), plus a NUL at the end.
+ */
+ result = alloc((unsigned)STRLEN(from) * 6 + 1);
+ if (result == NULL) /* out of memory */
+ {
+ *bufp = NULL;
+ return from;
+ }
+
+ src = from;
+
+ /*
+ * Check for #n at start only: function key n
+ */
+ if (from_part && src[0] == '#' && VIM_ISDIGIT(src[1])) /* function key */
+ {
+ result[dlen++] = K_SPECIAL;
+ result[dlen++] = 'k';
+ if (src[1] == '0')
+ result[dlen++] = ';'; /* #0 is F10 is "k;" */
+ else
+ result[dlen++] = src[1]; /* #3 is F3 is "k3" */
+ src += 2;
+ }
+
+ /*
+ * Copy each byte from *from to result[dlen]
+ */
+ while (*src != NUL)
+ {
+ /*
+ * If 'cpoptions' does not contain '<', check for special key codes,
+ * like "<C-S-MouseLeft>"
+ */
+ if (do_special && (do_lt || STRNCMP(src, "<lt>", 4) != 0))
+ {
+#ifdef FEAT_EVAL
+ /*
+ * Replace <SID> by K_SNR <script-nr> _.
+ * (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14)
+ */
+ if (STRNICMP(src, "<SID>", 5) == 0)
+ {
+ if (current_SID <= 0)
+ EMSG(_(e_usingsid));
+ else
+ {
+ src += 5;
+ result[dlen++] = K_SPECIAL;
+ result[dlen++] = (int)KS_EXTRA;
+ result[dlen++] = (int)KE_SNR;
+ sprintf((char *)result + dlen, "%ld", (long)current_SID);
+ dlen += (int)STRLEN(result + dlen);
+ result[dlen++] = '_';
+ continue;
+ }
+ }
+#endif
+
+ slen = trans_special(&src, result + dlen, TRUE);
+ if (slen)
+ {
+ dlen += slen;
+ continue;
+ }
+ }
+
+ /*
+ * If 'cpoptions' does not contain 'k', see if it's an actual key-code.
+ * Note that this is also checked after replacing the <> form.
+ * Single character codes are NOT replaced (e.g. ^H or DEL), because
+ * it could be a character in the file.
+ */
+ if (do_key_code)
+ {
+ i = find_term_bykeys(src);
+ if (i >= 0)
+ {
+ result[dlen++] = K_SPECIAL;
+ result[dlen++] = termcodes[i].name[0];
+ result[dlen++] = termcodes[i].name[1];
+ src += termcodes[i].len;
+ /* If terminal code matched, continue after it. */
+ continue;
+ }
+ }
+
+#ifdef FEAT_EVAL
+ if (do_special)
+ {
+ char_u *p, *s, len;
+
+ /*
+ * Replace <Leader> by the value of "mapleader".
+ * Replace <LocalLeader> by the value of "maplocalleader".
+ * If "mapleader" or "maplocalleader" isn't set use a backslash.
+ */
+ if (STRNICMP(src, "<Leader>", 8) == 0)
+ {
+ len = 8;
+ p = get_var_value((char_u *)"g:mapleader");
+ }
+ else if (STRNICMP(src, "<LocalLeader>", 13) == 0)
+ {
+ len = 13;
+ p = get_var_value((char_u *)"g:maplocalleader");
+ }
+ else
+ {
+ len = 0;
+ p = NULL;
+ }
+ if (len != 0)
+ {
+ /* Allow up to 8 * 6 characters for "mapleader". */
+ if (p == NULL || *p == NUL || STRLEN(p) > 8 * 6)
+ s = (char_u *)"\\";
+ else
+ s = p;
+ while (*s != NUL)
+ result[dlen++] = *s++;
+ src += len;
+ continue;
+ }
+ }
+#endif
+
+ /*
+ * Remove CTRL-V and ignore the next character.
+ * For "from" side the CTRL-V at the end is included, for the "to"
+ * part it is removed.
+ * If 'cpoptions' does not contain 'B', also accept a backslash.
+ */
+ key = *src;
+ if (key == Ctrl_V || (do_backslash && key == '\\'))
+ {
+ ++src; /* skip CTRL-V or backslash */
+ if (*src == NUL)
+ {
+ if (from_part)
+ result[dlen++] = key;
+ break;
+ }
+ }
+
+#ifdef FEAT_MBYTE
+ /* skip multibyte char correctly */
+ for (i = (*mb_ptr2len_check)(src); i > 0; --i)
+#endif
+ {
+ /*
+ * If the character is K_SPECIAL, replace it with K_SPECIAL
+ * KS_SPECIAL KE_FILLER.
+ * If compiled with the GUI replace CSI with K_CSI.
+ */
+ if (*src == K_SPECIAL)
+ {
+ result[dlen++] = K_SPECIAL;
+ result[dlen++] = KS_SPECIAL;
+ result[dlen++] = KE_FILLER;
+ }
+# ifdef FEAT_GUI
+ else if (*src == CSI)
+ {
+ result[dlen++] = K_SPECIAL;
+ result[dlen++] = KS_EXTRA;
+ result[dlen++] = (int)KE_CSI;
+ }
+# endif
+ else
+ result[dlen++] = *src;
+ ++src;
+ }
+ }
+ result[dlen] = NUL;
+
+ /*
+ * Copy the new string to allocated memory.
+ * If this fails, just return from.
+ */
+ if ((*bufp = vim_strsave(result)) != NULL)
+ from = *bufp;
+ vim_free(result);
+ return from;
+}
+
+/*
+ * Find a termcode with keys 'src' (must be NUL terminated).
+ * Return the index in termcodes[], or -1 if not found.
+ */
+ int
+find_term_bykeys(src)
+ char_u *src;
+{
+ int i;
+ int slen;
+
+ for (i = 0; i < tc_len; ++i)
+ {
+ slen = termcodes[i].len;
+ if (slen > 1 && STRNCMP(termcodes[i].code, src, (size_t)slen) == 0)
+ return i;
+ }
+ return -1;
+}
+
+/*
+ * Gather the first characters in the terminal key codes into a string.
+ * Used to speed up check_termcode().
+ */
+ static void
+gather_termleader()
+{
+ int i;
+ int len = 0;
+
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ termleader[len++] = CSI; /* the GUI codes are not in termcodes[] */
+#endif
+#ifdef FEAT_TERMRESPONSE
+ if (check_for_codes)
+ termleader[len++] = DCS; /* the termcode response starts with DCS
+ in 8-bit mode */
+#endif
+ termleader[len] = NUL;
+
+ for (i = 0; i < tc_len; ++i)
+ if (vim_strchr(termleader, termcodes[i].code[0]) == NULL)
+ {
+ termleader[len++] = termcodes[i].code[0];
+ termleader[len] = NUL;
+ }
+
+ need_gather = FALSE;
+}
+
+/*
+ * Show all termcodes (for ":set termcap")
+ * This code looks a lot like showoptions(), but is different.
+ */
+ void
+show_termcodes()
+{
+ int col;
+ int *items;
+ int item_count;
+ int run;
+ int row, rows;
+ int cols;
+ int i;
+ int len;
+
+#define INC 27 /* try to make three columns */
+#define GAP 2 /* spaces between columns */
+
+ if (tc_len == 0) /* no terminal codes (must be GUI) */
+ return;
+ items = (int *)alloc((unsigned)(sizeof(int) * tc_len));
+ if (items == NULL)
+ return;
+
+ /* Highlight title */
+ MSG_PUTS_TITLE(_("\n--- Terminal keys ---"));
+
+ /*
+ * do the loop two times:
+ * 1. display the short items (non-strings and short strings)
+ * 2. display the long items (strings)
+ */
+ for (run = 1; run <= 2 && !got_int; ++run)
+ {
+ /*
+ * collect the items in items[]
+ */
+ item_count = 0;
+ for (i = 0; i < tc_len; i++)
+ {
+ len = show_one_termcode(termcodes[i].name,
+ termcodes[i].code, FALSE);
+ if ((len <= INC - GAP && run == 1) || (len > INC - GAP && run == 2))
+ items[item_count++] = i;
+ }
+
+ /*
+ * display the items
+ */
+ if (run == 1)
+ {
+ cols = (Columns + GAP) / INC;
+ if (cols == 0)
+ cols = 1;
+ rows = (item_count + cols - 1) / cols;
+ }
+ else /* run == 2 */
+ rows = item_count;
+ for (row = 0; row < rows && !got_int; ++row)
+ {
+ msg_putchar('\n'); /* go to next line */
+ if (got_int) /* 'q' typed in more */
+ break;
+ col = 0;
+ for (i = row; i < item_count; i += rows)
+ {
+ msg_col = col; /* make columns */
+ show_one_termcode(termcodes[items[i]].name,
+ termcodes[items[i]].code, TRUE);
+ col += INC;
+ }
+ out_flush();
+ ui_breakcheck();
+ }
+ }
+ vim_free(items);
+}
+
+/*
+ * Show one termcode entry.
+ * Output goes into IObuff[]
+ */
+ int
+show_one_termcode(name, code, printit)
+ char_u *name;
+ char_u *code;
+ int printit;
+{
+ char_u *p;
+ int len;
+
+ if (name[0] > '~')
+ {
+ IObuff[0] = ' ';
+ IObuff[1] = ' ';
+ IObuff[2] = ' ';
+ IObuff[3] = ' ';
+ }
+ else
+ {
+ IObuff[0] = 't';
+ IObuff[1] = '_';
+ IObuff[2] = name[0];
+ IObuff[3] = name[1];
+ }
+ IObuff[4] = ' ';
+
+ p = get_special_key_name(TERMCAP2KEY(name[0], name[1]), 0);
+ if (p[1] != 't')
+ STRCPY(IObuff + 5, p);
+ else
+ IObuff[5] = NUL;
+ len = (int)STRLEN(IObuff);
+ do
+ IObuff[len++] = ' ';
+ while (len < 17);
+ IObuff[len] = NUL;
+ if (code == NULL)
+ len += 4;
+ else
+ len += vim_strsize(code);
+
+ if (printit)
+ {
+ msg_puts(IObuff);
+ if (code == NULL)
+ msg_puts((char_u *)"NULL");
+ else
+ msg_outtrans(code);
+ }
+ return len;
+}
+
+#if defined(FEAT_TERMRESPONSE) || defined(PROTO)
+/*
+ * For Xterm >= 140 compiled with OPT_TCAP_QUERY: Obtain the actually used
+ * termcap codes from the terminal itself.
+ * We get them one by one to avoid a very long response string.
+ */
+static int xt_index_in = 0;
+static int xt_index_out = 0;
+
+ static void
+req_codes_from_term()
+{
+ xt_index_out = 0;
+ xt_index_in = 0;
+ req_more_codes_from_term();
+}
+
+ static void
+req_more_codes_from_term()
+{
+ char buf[11];
+ int old_idx = xt_index_out;
+
+ /* Don't do anything when going to exit. */
+ if (exiting)
+ return;
+
+ /* Send up to 10 more requests out than we received. Avoid sending too
+ * many, there can be a buffer overflow somewhere. */
+ while (xt_index_out < xt_index_in + 10 && key_names[xt_index_out] != NULL)
+ {
+ sprintf(buf, "\033P+q%02x%02x\033\\",
+ key_names[xt_index_out][0], key_names[xt_index_out][1]);
+ out_str_nf((char_u *)buf);
+ ++xt_index_out;
+ }
+
+ /* Send the codes out right away. */
+ if (xt_index_out != old_idx)
+ out_flush();
+}
+
+/*
+ * Decode key code response from xterm: '<Esc>P1+r<name>=<string><Esc>\'.
+ * A "0" instead of the "1" indicates a code that isn't supported.
+ * Both <name> and <string> are encoded in hex.
+ * "code" points to the "0" or "1".
+ */
+ static void
+got_code_from_term(code, len)
+ char_u *code;
+ int len;
+{
+#define XT_LEN 100
+ char_u name[3];
+ char_u str[XT_LEN];
+ int i;
+ int j = 0;
+ int c;
+
+ /* A '1' means the code is supported, a '0' means it isn't.
+ * When half the length is > XT_LEN we can't use it.
+ * Our names are currently all 2 characters. */
+ if (code[0] == '1' && code[7] == '=' && len / 2 < XT_LEN)
+ {
+ /* Get the name from the response and find it in the table. */
+ name[0] = hexhex2nr(code + 3);
+ name[1] = hexhex2nr(code + 5);
+ name[2] = NUL;
+ for (i = 0; key_names[i] != NULL; ++i)
+ {
+ if (STRCMP(key_names[i], name) == 0)
+ {
+ xt_index_in = i;
+ break;
+ }
+ }
+ if (key_names[i] != NULL)
+ {
+ for (i = 8; (c = hexhex2nr(code + i)) >= 0; i += 2)
+ str[j++] = c;
+ str[j] = NUL;
+ if (name[0] == 'C' && name[1] == 'o')
+ {
+ /* Color count is not a key code. */
+ i = atoi((char *)str);
+ if (i != t_colors)
+ {
+ /* Nr of colors changed, initialize highlighting and
+ * redraw everything. */
+ set_color_count(i);
+ init_highlight(TRUE, FALSE);
+ redraw_later(CLEAR);
+ }
+ }
+ else
+ {
+ /* First delete any existing entry with the same code. */
+ i = find_term_bykeys(str);
+ if (i >= 0)
+ del_termcode_idx(i);
+ add_termcode(name, str, FALSE);
+ }
+ }
+ }
+
+ /* May request more codes now that we received one. */
+ ++xt_index_in;
+ req_more_codes_from_term();
+}
+
+/*
+ * Check if there are any unanswered requests and deal with them.
+ * This is called before starting an external program or getting direct
+ * keyboard input. We don't want responses to be send to that program or
+ * handled as typed text.
+ */
+ static void
+check_for_codes_from_term()
+{
+ int c;
+
+ /* If no codes requested or all are answered, no need to wait. */
+ if (xt_index_out == 0 || xt_index_out == xt_index_in)
+ return;
+
+ /* Vgetc() will check for and handle any response.
+ * Keep calling vpeekc() until we don't get any responses. */
+ ++no_mapping;
+ ++allow_keys;
+ for (;;)
+ {
+ c = vpeekc();
+ if (c == NUL) /* nothing available */
+ break;
+
+ /* If a response is recognized it's replaced with K_IGNORE, must read
+ * it from the input stream. If there is no K_IGNORE we can't do
+ * anything, break here (there might be some responses further on, but
+ * we don't want to throw away any typed chars). */
+ if (c != K_SPECIAL && c != K_IGNORE)
+ break;
+ c = vgetc();
+ if (c != K_IGNORE)
+ {
+ vungetc(c);
+ break;
+ }
+ }
+ --no_mapping;
+ --allow_keys;
+}
+#endif
+
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+/*
+ * Translate an internal mapping/abbreviation representation into the
+ * corresponding external one recognized by :map/:abbrev commands;
+ * respects the current B/k/< settings of 'cpoption'.
+ *
+ * This function is called when expanding mappings/abbreviations on the
+ * command-line, and for building the "Ambiguous mapping..." error messæge.
+ *
+ * It uses a growarray to build the translation string since the
+ * latter can be wider than the original description. The caller has to
+ * free the string afterwards.
+ *
+ * Returns NULL when there is a problem.
+ */
+ char_u *
+translate_mapping(str, expmap)
+ char_u *str;
+ int expmap; /* TRUE when expanding mappings on command-line */
+{
+ garray_T ga;
+ int c;
+ int modifiers;
+ int cpo_bslash;
+ int cpo_special;
+ int cpo_keycode;
+
+ ga_init(&ga);
+ ga.ga_itemsize = 1;
+ ga.ga_growsize = 40;
+
+ cpo_bslash = (vim_strchr(p_cpo, CPO_BSLASH) != NULL);
+ cpo_special = (vim_strchr(p_cpo, CPO_SPECI) != NULL);
+ cpo_keycode = (vim_strchr(p_cpo, CPO_KEYCODE) == NULL);
+
+ for (; *str; ++str)
+ {
+ c = *str;
+ if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
+ {
+ modifiers = 0;
+ if (str[1] == KS_MODIFIER)
+ {
+ str++;
+ modifiers = *++str;
+ c = *++str;
+ }
+ if (cpo_special && cpo_keycode && c == K_SPECIAL && !modifiers)
+ {
+ int i;
+
+ /* try to find special key in termcodes */
+ for (i = 0; i < tc_len; ++i)
+ if (termcodes[i].name[0] == str[1]
+ && termcodes[i].name[1] == str[2])
+ break;
+ if (i < tc_len)
+ {
+ ga_concat(&ga, termcodes[i].code);
+ str += 2;
+ continue; /* for (str) */
+ }
+ }
+ if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
+ {
+ if (expmap && cpo_special)
+ {
+ ga_clear(&ga);
+ return NULL;
+ }
+ c = TO_SPECIAL(str[1], str[2]);
+ if (c == K_ZERO) /* display <Nul> as ^@ */
+ c = NUL;
+ str += 2;
+ }
+ if (IS_SPECIAL(c) || modifiers) /* special key */
+ {
+ if (expmap && cpo_special)
+ {
+ ga_clear(&ga);
+ return NULL;
+ }
+ ga_concat(&ga, get_special_key_name(c, modifiers));
+ continue; /* for (str) */
+ }
+ }
+ if (c == ' ' || c == '\t' || c == Ctrl_J || c == Ctrl_V
+ || (c == '<' && !cpo_special) || (c == '\\' && !cpo_bslash))
+ ga_append(&ga, cpo_bslash ? Ctrl_V : '\\');
+ if (c)
+ ga_append(&ga, c);
+ }
+ ga_append(&ga, NUL);
+ return (char_u *)(ga.ga_data);
+}
+#endif
+
+#if (defined(WIN3264) && !defined(FEAT_GUI)) || defined(PROTO)
+static char ksme_str[20];
+static char ksmr_str[20];
+static char ksmd_str[20];
+
+/*
+ * For Win32 console: update termcap codes for existing console attributes.
+ */
+ void
+update_tcap(attr)
+ int attr;
+{
+ struct builtin_term *p;
+
+ p = find_builtin_term(DEFAULT_TERM);
+ sprintf(ksme_str, IF_EB("\033|%dm", ESC_STR "|%dm"), attr);
+ sprintf(ksmd_str, IF_EB("\033|%dm", ESC_STR "|%dm"),
+ attr | 0x08); /* FOREGROUND_INTENSITY */
+ sprintf(ksmr_str, IF_EB("\033|%dm", ESC_STR "|%dm"),
+ ((attr & 0x0F) << 4) | ((attr & 0xF0) >> 4));
+
+ while (p->bt_string != NULL)
+ {
+ if (p->bt_entry == (int)KS_ME)
+ p->bt_string = &ksme_str[0];
+ else if (p->bt_entry == (int)KS_MR)
+ p->bt_string = &ksmr_str[0];
+ else if (p->bt_entry == (int)KS_MD)
+ p->bt_string = &ksmd_str[0];
+ ++p;
+ }
+}
+#endif
diff --git a/src/term.h b/src/term.h
new file mode 100644
index 000000000..17b1065ca
--- /dev/null
+++ b/src/term.h
@@ -0,0 +1,156 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * This file contains the defines for the machine dependent escape sequences
+ * that the editor needs to perform various operations. All of the sequences
+ * here are optional, except "cm" (cursor motion).
+ */
+
+#if defined(SASC) && SASC < 658
+/*
+ * The SAS C compiler has a bug that makes typedefs being forgot in include
+ * files. Has been fixed in version 6.58.
+ */
+typedef unsigned char char_u;
+#endif
+
+/*
+ * Index of the termcap codes in the term_strings array.
+ */
+enum SpecialKey
+{
+ KS_NAME = 0,/* name of this terminal entry */
+ KS_CE, /* clear to end of line */
+ KS_AL, /* add new blank line */
+ KS_CAL, /* add number of blank lines */
+ KS_DL, /* delete line */
+ KS_CDL, /* delete number of lines */
+ KS_CS, /* scroll region */
+ KS_CL, /* clear screen */
+ KS_CD, /* clear to end of display */
+ KS_UT, /* clearing uses current background color */
+ KS_DA, /* text may be scrolled down from up */
+ KS_DB, /* text may be scrolled up from down */
+ KS_VI, /* cursor invisible */
+ KS_VE, /* cursor visible */
+ KS_VS, /* cursor very visible */
+ KS_ME, /* normal mode */
+ KS_MR, /* reverse mode */
+ KS_MD, /* bold mode */
+ KS_SE, /* normal mode */
+ KS_SO, /* standout mode */
+ KS_CZH, /* italic mode start */
+ KS_CZR, /* italic mode end */
+ KS_UE, /* exit underscore mode */
+ KS_US, /* underscore mode */
+ KS_MS, /* save to move cur in reverse mode */
+ KS_CM, /* cursor motion */
+ KS_SR, /* scroll reverse (backward) */
+ KS_CRI, /* cursor number of chars right */
+ KS_VB, /* visual bell */
+ KS_KS, /* put term in "keypad transmit" mode */
+ KS_KE, /* out of "keypad transmit" mode */
+ KS_TI, /* put terminal in termcap mode */
+ KS_TE, /* out of termcap mode */
+ KS_BC, /* backspace character (cursor left) */
+ KS_CCS, /* cur is relative to scroll region */
+ KS_CCO, /* number of colors */
+ KS_CSF, /* set foreground color */
+ KS_CSB, /* set background color */
+ KS_XS, /* standout not erased by overwriting (hpterm) */
+ KS_MB, /* blink mode */
+ KS_CAF, /* set foreground color (ANSI) */
+ KS_CAB, /* set background color (ANSI) */
+ KS_LE, /* cursor left (mostly backspace) */
+ KS_ND, /* cursor right */
+ KS_CIS, /* set icon text start */
+ KS_CIE, /* set icon text end */
+ KS_TS, /* set window title start (to status line)*/
+ KS_FS, /* set window title end (from status line) */
+ KS_CWP, /* set window position in pixels */
+ KS_CWS, /* set window size in characters */
+ KS_CRV, /* request version string */
+#ifdef FEAT_VERTSPLIT
+ KS_CSV, /* scroll region vertical */
+#endif
+ KS_OP /* original color pair */
+};
+
+#define KS_LAST KS_OP
+
+/*
+ * the terminal capabilities are stored in this array
+ * IMPORTANT: When making changes, note the following:
+ * - there should be an entry for each code in the builtin termcaps
+ * - there should be an option for each code in option.c
+ * - there should be code in term.c to obtain the value from the termcap
+ */
+
+extern char_u *(term_strings[]); /* current terminal strings */
+
+/*
+ * strings used for terminal
+ */
+#define T_NAME (term_str(KS_NAME)) /* terminal name */
+#define T_CE (term_str(KS_CE)) /* clear to end of line */
+#define T_AL (term_str(KS_AL)) /* add new blank line */
+#define T_CAL (term_str(KS_CAL)) /* add number of blank lines */
+#define T_DL (term_str(KS_DL)) /* delete line */
+#define T_CDL (term_str(KS_CDL)) /* delete number of lines */
+#define T_CS (term_str(KS_CS)) /* scroll region */
+#define T_CSV (term_str(KS_CSV)) /* scroll region vertical */
+#define T_CL (term_str(KS_CL)) /* clear screen */
+#define T_CD (term_str(KS_CD)) /* clear to end of display */
+#define T_UT (term_str(KS_UT)) /* clearing uses background color */
+#define T_DA (term_str(KS_DA)) /* text may be scrolled down from up */
+#define T_DB (term_str(KS_DB)) /* text may be scrolled up from down */
+#define T_VI (term_str(KS_VI)) /* cursor invisible */
+#define T_VE (term_str(KS_VE)) /* cursor visible */
+#define T_VS (term_str(KS_VS)) /* cursor very visible */
+#define T_ME (term_str(KS_ME)) /* normal mode */
+#define T_MR (term_str(KS_MR)) /* reverse mode */
+#define T_MD (term_str(KS_MD)) /* bold mode */
+#define T_SE (term_str(KS_SE)) /* normal mode */
+#define T_SO (term_str(KS_SO)) /* standout mode */
+#define T_CZH (term_str(KS_CZH)) /* italic mode start */
+#define T_CZR (term_str(KS_CZR)) /* italic mode end */
+#define T_UE (term_str(KS_UE)) /* exit underscore mode */
+#define T_US (term_str(KS_US)) /* underscore mode */
+#define T_MS (term_str(KS_MS)) /* save to move cur in reverse mode */
+#define T_CM (term_str(KS_CM)) /* cursor motion */
+#define T_SR (term_str(KS_SR)) /* scroll reverse (backward) */
+#define T_CRI (term_str(KS_CRI)) /* cursor number of chars right */
+#define T_VB (term_str(KS_VB)) /* visual bell */
+#define T_KS (term_str(KS_KS)) /* put term in "keypad transmit" mode */
+#define T_KE (term_str(KS_KE)) /* out of "keypad transmit" mode */
+#define T_TI (term_str(KS_TI)) /* put terminal in termcap mode */
+#define T_TE (term_str(KS_TE)) /* out of termcap mode */
+#define T_BC (term_str(KS_BC)) /* backspace character */
+#define T_CCS (term_str(KS_CCS)) /* cur is relative to scroll region */
+#define T_CCO (term_str(KS_CCO)) /* number of colors */
+#define T_CSF (term_str(KS_CSF)) /* set foreground color */
+#define T_CSB (term_str(KS_CSB)) /* set background color */
+#define T_XS (term_str(KS_XS)) /* standout not erased by overwriting */
+#define T_MB (term_str(KS_MB)) /* blink mode */
+#define T_CAF (term_str(KS_CAF)) /* set foreground color (ANSI) */
+#define T_CAB (term_str(KS_CAB)) /* set background color (ANSI) */
+#define T_LE (term_str(KS_LE)) /* cursor left */
+#define T_ND (term_str(KS_ND)) /* cursor right */
+#define T_CIS (term_str(KS_CIS)) /* set icon text start */
+#define T_CIE (term_str(KS_CIE)) /* set icon text end */
+#define T_TS (term_str(KS_TS)) /* set window title start */
+#define T_FS (term_str(KS_FS)) /* set window title end */
+#define T_CWP (term_str(KS_CWP)) /* window position */
+#define T_CWS (term_str(KS_CWS)) /* window size */
+#define T_CRV (term_str(KS_CRV)) /* request version string */
+#define T_OP (term_str(KS_OP)) /* original color pair */
+
+#define TMODE_COOK 0 /* terminal mode for external cmds and Ex mode */
+#define TMODE_SLEEP 1 /* terminal mode for sleeping (cooked but no echo) */
+#define TMODE_RAW 2 /* terminal mode for Normal and Insert mode */
diff --git a/src/termlib.c b/src/termlib.c
new file mode 100644
index 000000000..a0036c64b
--- /dev/null
+++ b/src/termlib.c
@@ -0,0 +1,628 @@
+/* vi:set ts=8 sts=4 sw=4: */
+/*
+ * The following software is (C) 1984 Peter da Silva, the Mad Australian, in
+ * the public domain. It may be re-distributed for any purpose with the
+ * inclusion of this notice.
+ */
+
+/* Modified by Bram Moolenaar for use with VIM - Vi Improved. */
+/* A few bugs removed by Olaf 'Rhialto' Seibert. */
+
+/* TERMLIB: Terminal independant database. */
+
+#include "vim.h"
+#include "termlib.pro"
+
+#if !defined(AMIGA) && !defined(VMS) && !defined(MACOS) && !defined(RISCOS)
+# include <sgtty.h>
+#endif
+
+static int getent __ARGS((char *, char *, FILE *, int));
+static int nextent __ARGS((char *, FILE *, int));
+static int _match __ARGS((char *, char *));
+static char *_addfmt __ARGS((char *, char *, int));
+static char *_find __ARGS((char *, char *));
+
+/*
+ * Global variables for termlib
+ */
+
+char *tent; /* Pointer to terminal entry, set by tgetent */
+char PC = 0; /* Pad character, default NULL */
+char *UP = 0, *BC = 0; /* Pointers to UP and BC strings from database */
+short ospeed; /* Baud rate (1-16, 1=300, 16=19200), as in stty */
+
+/*
+ * Module: tgetent
+ *
+ * Purpose: Get termcap entry for <term> into buffer at <tbuf>.
+ *
+ * Calling conventions: char tbuf[TBUFSZ+], term=canonical name for terminal.
+ *
+ * Returned values: 1 = success, -1 = can't open file,
+ * 0 = can't find terminal.
+ *
+ * Notes:
+ * - Should probably supply static buffer.
+ * - Uses environment variables "TERM" and "TERMCAP". If TERM = term (that is,
+ * if the argument matches the environment) then it looks at TERMCAP.
+ * - If TERMCAP begins with a slash, then it assumes this is the file to
+ * search rather than /etc/termcap.
+ * - If TERMCAP does not begin with a slash, and it matches TERM, then this is
+ * used as the entry.
+ * - This could be simplified considerably for non-UNIX systems.
+ */
+
+#ifndef TERMCAPFILE
+# ifdef AMIGA
+# define TERMCAPFILE "s:termcap"
+# else
+# ifdef VMS
+# define TERMCAPFILE "VIMRUNTIME:termcap"
+# else
+# define TERMCAPFILE "/etc/termcap"
+# endif
+# endif
+#endif
+
+ int
+tgetent(tbuf, term)
+ char *tbuf; /* Buffer to hold termcap entry, TBUFSZ bytes max */
+ char *term; /* Name of terminal */
+{
+ char tcbuf[32]; /* Temp buffer to handle */
+ char *tcptr = tcbuf; /* extended entries */
+ char *tcap = TERMCAPFILE; /* Default termcap file */
+ char *tmp;
+ FILE *termcap;
+ int retval = 0;
+ int len;
+
+ if ((tmp = (char *)mch_getenv((char_u *)"TERMCAP")) != NULL)
+ {
+ if (*tmp == '/') /* TERMCAP = name of termcap file */
+ {
+ tcap = tmp ;
+#if defined(AMIGA)
+ /* Convert /usr/share/lib/termcap to usr:share/lib/termcap */
+ tcap++;
+ tmp = strchr(tcap, '/');
+ if (tmp)
+ *tmp = ':';
+#endif
+ }
+ else /* TERMCAP = termcap entry itself */
+ {
+ int tlen = strlen(term);
+
+ while (*tmp && *tmp != ':') /* Check if TERM matches */
+ {
+ char *nexttmp;
+
+ while (*tmp == '|')
+ tmp++;
+ nexttmp = _find(tmp, ":|"); /* Rhialto */
+ if (tmp+tlen == nexttmp && _match(tmp, term) == tlen)
+ {
+ strcpy(tbuf, tmp);
+ tent = tbuf;
+ return 1;
+ }
+ else
+ tmp = nexttmp;
+ }
+ }
+ }
+ if (!(termcap = mch_fopen(tcap, "r")))
+ {
+ strcpy(tbuf, tcap);
+ return -1;
+ }
+
+ len = 0;
+ while (getent(tbuf + len, term, termcap, TBUFSZ - len))
+ {
+ tcptr = tcbuf; /* Rhialto */
+ if ((term = tgetstr("tc", &tcptr))) /* extended entry */
+ {
+ rewind(termcap);
+ len = strlen(tbuf);
+ }
+ else
+ {
+ retval = 1;
+ tent = tbuf; /* reset it back to the beginning */
+ break;
+ }
+ }
+ fclose(termcap);
+ return retval;
+}
+
+ static int
+getent(tbuf, term, termcap, buflen)
+ char *tbuf, *term;
+ FILE *termcap;
+ int buflen;
+{
+ char *tptr;
+ int tlen = strlen(term);
+
+ while (nextent(tbuf, termcap, buflen)) /* For each possible entry */
+ {
+ tptr = tbuf;
+ while (*tptr && *tptr != ':') /* : terminates name field */
+ {
+ char *nexttptr;
+
+ while (*tptr == '|') /* | seperates names */
+ tptr++;
+ nexttptr = _find(tptr, ":|"); /* Rhialto */
+ if (tptr + tlen == nexttptr &&
+ _match(tptr, term) == tlen) /* FOUND! */
+ {
+ tent = tbuf;
+ return 1;
+ }
+ else /* Look for next name */
+ tptr = nexttptr;
+ }
+ }
+ return 0;
+}
+
+ static int
+nextent(tbuf, termcap, buflen) /* Read 1 entry from TERMCAP file */
+ char *tbuf;
+ FILE *termcap;
+ int buflen;
+{
+ char *lbuf = tbuf; /* lbuf=line buffer */
+ /* read lines straight into buffer */
+
+ while (lbuf < tbuf+buflen && /* There's room and */
+ fgets(lbuf, (int)(tbuf+buflen-lbuf), termcap)) /* another line */
+ {
+ int llen = strlen(lbuf);
+
+ if (*lbuf == '#') /* eat comments */
+ continue;
+ if (lbuf[-1] == ':' && /* and whitespace */
+ lbuf[0] == '\t' &&
+ lbuf[1] == ':')
+ {
+ strcpy(lbuf, lbuf+2);
+ llen -= 2;
+ }
+ if (lbuf[llen-2] == '\\') /* and continuations */
+ lbuf += llen-2;
+ else
+ {
+ lbuf[llen-1]=0; /* no continuation, return */
+ return 1;
+ }
+ }
+
+ return 0; /* ran into end of file */
+}
+
+/*
+ * Module: tgetflag
+ *
+ * Purpose: returns flag true or false as to the existence of a given entry.
+ * used with 'bs', 'am', etc...
+ *
+ * Calling conventions: id is the 2 character capability id.
+ *
+ * Returned values: 1 for success, 0 for failure.
+ */
+
+ int
+tgetflag(id)
+ char *id;
+{
+ char buf[256], *ptr = buf;
+
+ return tgetstr(id, &ptr) ? 1 : 0;
+}
+
+/*
+ * Module: tgetnum
+ *
+ * Purpose: get numeric value such as 'li' or 'co' from termcap.
+ *
+ * Calling conventions: id = 2 character id.
+ *
+ * Returned values: -1 for failure, else numerical value.
+ */
+
+ int
+tgetnum(id)
+ char *id;
+{
+ char *ptr, buf[256];
+ ptr = buf;
+
+ if (tgetstr(id, &ptr))
+ return atoi(buf);
+ else
+ return 0;
+}
+
+/*
+ * Module: tgetstr
+ *
+ * Purpose: get terminal capability string from database.
+ *
+ * Calling conventions: id is the two character capability id.
+ * (*buf) points into a hold buffer for the
+ * id. the capability is copied into the buffer
+ * and (*buf) is advanced to point to the next
+ * free byte in the buffer.
+ *
+ * Returned values: 0 = no such entry, otherwise returns original
+ * (*buf) (now a pointer to the string).
+ *
+ * Notes
+ * It also decodes certain escape sequences in the buffer.
+ * they should be obvious from the code:
+ * \E = escape.
+ * \n, \r, \t, \f, \b match the 'c' escapes.
+ * ^x matches control-x (^@...^_).
+ * \nnn matches nnn octal.
+ * \x, where x is anything else, matches x. I differ
+ * from the standard library here, in that I allow ^: to match
+ * :.
+ *
+ */
+
+ char *
+tgetstr(id, buf)
+ char *id, **buf;
+{
+ int len = strlen(id);
+ char *tmp=tent;
+ char *hold;
+ int i;
+
+ do {
+ tmp = _find(tmp, ":"); /* For each field */
+ while (*tmp == ':') /* skip empty fields */
+ tmp++;
+ if (!*tmp)
+ break;
+
+ if (_match(id, tmp) == len) {
+ tmp += len; /* find '=' '@' or '#' */
+ if (*tmp == '@') /* :xx@: entry for tc */
+ return 0; /* deleted entry */
+ hold= *buf;
+ while (*++tmp && *tmp != ':') { /* not at end of field */
+ switch(*tmp) {
+ case '\\': /* Expand escapes here */
+ switch(*++tmp) {
+ case 0: /* ignore backslashes */
+ tmp--; /* at end of entry */
+ break; /* shouldn't happen */
+ case 'e':
+ case 'E': /* ESC */
+ *(*buf)++ = ESC;
+ break;
+ case 'n': /* \n */
+ *(*buf)++ = '\n';
+ break;
+ case 'r': /* \r */
+ *(*buf)++ = '\r';
+ break;
+ case 't': /* \t */
+ *(*buf)++ = '\t';
+ break;
+ case 'b': /* \b */
+ *(*buf)++ = '\b';
+ break;
+ case 'f': /* \f */
+ *(*buf)++ = '\f';
+ break;
+ case '0': /* \nnn */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ **buf = 0;
+ /* get up to three digits */
+ for (i = 0; i < 3 && VIM_ISDIGIT(*tmp); ++i)
+ **buf = **buf * 8 + *tmp++ - '0';
+ (*buf)++;
+ tmp--;
+ break;
+ default: /* \x, for all other x */
+ *(*buf)++= *tmp;
+ }
+ break;
+ case '^': /* control characters */
+ ++tmp;
+ *(*buf)++ = Ctrl_chr(*tmp);
+ break;
+ default:
+ *(*buf)++ = *tmp;
+ }
+ }
+ *(*buf)++ = 0;
+ return hold;
+ }
+ } while (*tmp);
+
+ return 0;
+}
+
+/*
+ * Module: tgoto
+ *
+ * Purpose: decode cm cursor motion string.
+ *
+ * Calling conventions: cm is cursor motion string. line, col, are the
+ * desired destination.
+ *
+ * Returned values: a string pointing to the decoded string, or "OOPS" if it
+ * cannot be decoded.
+ *
+ * Notes
+ * The accepted escapes are:
+ * %d as in printf, 0 origin.
+ * %2, %3 like %02d, %03d in printf.
+ * %. like %c
+ * %+x adds <x> to value, then %.
+ * %>xy if value>x, adds y. No output.
+ * %i increments line& col, no output.
+ * %r reverses order of line&col. No output.
+ * %% prints as a single %.
+ * %n exclusive or row & col with 0140.
+ * %B BCD, no output.
+ * %D reverse coding (x-2*(x%16)), no output.
+ */
+
+ char *
+tgoto(cm, col, line)
+ char *cm; /* cm string, from termcap */
+ int col, /* column, x position */
+ line; /* line, y position */
+{
+ char gx, gy, /* x, y */
+ *ptr, /* pointer in 'cm' */
+ reverse = 0, /* reverse flag */
+ *bufp, /* pointer in returned string */
+ addup = 0, /* add upline */
+ addbak = 0, /* add backup */
+ c;
+ static char buffer[32];
+
+ if (!cm)
+ return "OOPS"; /* Kludge, but standard */
+
+ bufp = buffer;
+ ptr = cm;
+
+ while (*ptr) {
+ if ((c = *ptr++) != '%') { /* normal char */
+ *bufp++ = c;
+ } else { /* % escape */
+ switch(c = *ptr++) {
+ case 'd': /* decimal */
+ bufp = _addfmt(bufp, "%d", line);
+ line = col;
+ break;
+ case '2': /* 2 digit decimal */
+ bufp = _addfmt(bufp, "%02d", line);
+ line = col;
+ break;
+ case '3': /* 3 digit decimal */
+ bufp = _addfmt(bufp, "%03d", line);
+ line = col;
+ break;
+ case '>': /* %>xy: if >x, add y */
+ gx = *ptr++;
+ gy = *ptr++;
+ if (col>gx) col += gy;
+ if (line>gx) line += gy;
+ break;
+ case '+': /* %+c: add c */
+ line += *ptr++;
+ case '.': /* print x/y */
+ if (line == '\t' || /* these are */
+ line == '\n' || /* chars that */
+ line == '\004' || /* UNIX hates */
+ line == '\0') {
+ line++; /* so go to next pos */
+ if (reverse == (line == col))
+ addup=1; /* and mark UP */
+ else
+ addbak=1; /* or BC */
+ }
+ *bufp++=line;
+ line = col;
+ break;
+ case 'r': /* r: reverse */
+ gx = line;
+ line = col;
+ col = gx;
+ reverse = 1;
+ break;
+ case 'i': /* increment (1-origin screen) */
+ col++;
+ line++;
+ break;
+ case '%': /* %%=% literally */
+ *bufp++='%';
+ break;
+ case 'n': /* magic DM2500 code */
+ line ^= 0140;
+ col ^= 0140;
+ break;
+ case 'B': /* bcd encoding */
+ line = line/10<<4+line%10;
+ col = col/10<<4+col%10;
+ break;
+ case 'D': /* magic Delta Data code */
+ line = line-2*(line&15);
+ col = col-2*(col&15);
+ break;
+ default: /* Unknown escape */
+ return "OOPS";
+ }
+ }
+ }
+
+ if (addup) /* add upline */
+ if (UP) {
+ ptr=UP;
+ while (VIM_ISDIGIT(*ptr) || *ptr == '.')
+ ptr++;
+ if (*ptr == '*')
+ ptr++;
+ while (*ptr)
+ *bufp++ = *ptr++;
+ }
+
+ if (addbak) /* add backspace */
+ if (BC) {
+ ptr=BC;
+ while (VIM_ISDIGIT(*ptr) || *ptr == '.')
+ ptr++;
+ if (*ptr == '*')
+ ptr++;
+ while (*ptr)
+ *bufp++ = *ptr++;
+ }
+ else
+ *bufp++='\b';
+
+ *bufp = 0;
+
+ return(buffer);
+}
+
+/*
+ * Module: tputs
+ *
+ * Purpose: decode padding information
+ *
+ * Calling conventions: cp = string to be padded, affcnt = # of items affected
+ * (lines, characters, whatever), outc = routine to output 1 character.
+ *
+ * Returned values: none
+ *
+ * Notes
+ * cp has padding information ahead of it, in the form
+ * nnnTEXT or nnn*TEXT. nnn is the number of milliseconds to delay,
+ * and may be a decimal (nnn.mmm). If the asterisk is given, then
+ * the delay is multiplied by afcnt. The delay is produced by outputting
+ * a number of nulls (or other padding char) after printing the
+ * TEXT.
+ *
+ */
+
+long _bauds[16]={
+ 0, 50, 75, 110,
+ 134, 150, 200, 300,
+ 600, 1200, 1800, 2400,
+ 4800, 9600, 19200, 19200 };
+
+ int
+tputs(cp, affcnt, outc)
+ char *cp; /* string to print */
+ int affcnt; /* Number of lines affected */
+ void (*outc) __ARGS((unsigned int));/* routine to output 1 character */
+{
+ long frac, /* 10^(#digits after decimal point) */
+ counter, /* digits */
+ atol __ARGS((const char *));
+
+ if (VIM_ISDIGIT(*cp)) {
+ counter = 0;
+ frac = 1000;
+ while (VIM_ISDIGIT(*cp))
+ counter = counter * 10L + (long)(*cp++ - '0');
+ if (*cp == '.')
+ while (VIM_ISDIGIT(*++cp)) {
+ counter = counter * 10L + (long)(*cp++ - '0');
+ frac = frac * 10;
+ }
+ if (*cp!='*') { /* multiply by affected lines */
+ if (affcnt>1) affcnt = 1;
+ }
+ else
+ cp++;
+
+ /* Calculate number of characters for padding counter/frac ms delay */
+ if (ospeed)
+ counter = (counter * _bauds[ospeed] * (long)affcnt) / frac;
+
+ while (*cp) /* output string */
+ (*outc)(*cp++);
+ if (ospeed)
+ while (counter--) /* followed by pad characters */
+ (*outc)(PC);
+ }
+ else
+ while (*cp)
+ (*outc)(*cp++);
+ return 0;
+}
+
+/*
+ * Module: tutil.c
+ *
+ * Purpose: Utility routines for TERMLIB functions.
+ *
+ */
+ static int
+_match(s1, s2) /* returns length of text common to s1 and s2 */
+ char *s1, *s2;
+{
+ int i = 0;
+
+ while (s1[i] && s1[i] == s2[i])
+ i++;
+
+ return i;
+}
+
+/*
+ * finds next c in s that's a member of set, returns pointer
+ */
+ static char *
+_find(s, set)
+ char *s, *set;
+{
+ for(; *s; s++)
+ {
+ char *ptr = set;
+
+ while (*ptr && *s != *ptr)
+ ptr++;
+
+ if (*ptr)
+ return s;
+ }
+
+ return s;
+}
+
+/*
+ * add val to buf according to format fmt
+ */
+ static char *
+_addfmt(buf, fmt, val)
+ char *buf, *fmt;
+ int val;
+{
+ sprintf(buf, fmt, val);
+ while (*buf)
+ buf++;
+ return buf;
+}
diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak
new file mode 100644
index 000000000..0970b729f
--- /dev/null
+++ b/src/testdir/Make_amiga.mak
@@ -0,0 +1,97 @@
+#
+# Makefile to run al tests for Vim, on Amiga
+#
+# Requires "rm", "csh" and "diff"!
+
+VIMPROG = /vim
+
+# These tests don't work (yet):
+# test2 "\\tmp" doesn't work
+# test10 'errorformat' is different
+# test11 "cat" doesn't work properly
+# test12 can't unlink a swap file
+# test25 uses symbolic link
+# test27 can't edit file with "*"
+# test52 only for Win32
+
+SCRIPTS = test1.out test3.out test4.out test5.out test6.out \
+ test7.out test8.out test9.out \
+ test13.out test14.out test15.out test17.out \
+ test18.out test19.out test20.out test21.out test22.out \
+ test23.out test24.out test26.out \
+ test28.out test29.out test30.out test31.out test32.out \
+ test33.out test34.out test35.out test36.out test37.out \
+ test38.out test39.out test40.out test41.out test42.out \
+ test43.out test44.out test45.out test46.out test47.out \
+ test48.out test51.out
+
+.SUFFIXES: .in .out
+
+nongui: /tmp $(SCRIPTS)
+ csh -c echo ALL DONE
+
+clean:
+ csh -c \rm -rf *.out /tmp/* Xdotest small.vim tiny.vim mbyte.vim test.ok viminfo
+
+.in.out:
+ copy $*.ok test.ok
+ $(VIMPROG) -u amiga.vim -U NONE --noplugin -s dotest.in $*.in
+ diff test.out $*.ok
+ rename test.out $*.out
+ -delete X#? ALL QUIET
+ -delete test.ok
+
+# Create a directory for temp files
+/tmp:
+ makedir /tmp
+
+# Manx requires all dependencies...
+test1.out: test1.in
+test2.out: test2.in
+test3.out: test3.in
+test4.out: test4.in
+test5.out: test5.in
+test6.out: test6.in
+test7.out: test7.in
+test8.out: test8.in
+test9.out: test9.in
+test10.out: test10.in
+test11.out: test11.in
+test12.out: test12.in
+test13.out: test13.in
+test14.out: test14.in
+test15.out: test15.in
+test16.out: test16.in
+test17.out: test17.in
+test18.out: test18.in
+test19.out: test19.in
+test20.out: test20.in
+test21.out: test21.in
+test22.out: test22.in
+test23.out: test23.in
+test24.out: test24.in
+test25.out: test25.in
+test26.out: test26.in
+test27.out: test27.in
+test28.out: test28.in
+test29.out: test29.in
+test30.out: test30.in
+test31.out: test31.in
+test32.out: test32.in
+test33.out: test33.in
+test34.out: test34.in
+test35.out: test35.in
+test36.out: test36.in
+test37.out: test37.in
+test38.out: test38.in
+test39.out: test39.in
+test40.out: test40.in
+test41.out: test41.in
+test42.out: test42.in
+test43.out: test43.in
+test44.out: test44.in
+test45.out: test45.in
+test46.out: test46.in
+test47.out: test47.in
+test48.out: test48.in
+test51.out: test51.in
diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak
new file mode 100644
index 000000000..b15951e6d
--- /dev/null
+++ b/src/testdir/Make_dos.mak
@@ -0,0 +1,64 @@
+#
+# Makefile to run al tests for Vim, on Dos-like machines.
+#
+# Requires a set of Unix tools: echo, diff, etc.
+
+VIMPROG = ..\\vim
+
+# Omitted:
+# test2 "\\tmp" doesn't work.
+# test10 'errorformat' is different
+# test12 can't unlink a swap file
+# test25 uses symbolic link
+# test27 can't edit file with "*" in file name
+# test31 16 bit version runs out of memory...
+
+SCRIPTS16 = test1.out test19.out test20.out test22.out \
+ test23.out test24.out test28.out test29.out \
+ test35.out test36.out test43.out \
+ test44.out test45.out test46.out test47.out \
+ test48.out test51.out
+
+SCRIPTS = test3.out test4.out test5.out test6.out test7.out \
+ test8.out test9.out test11.out test13.out test14.out \
+ test15.out test17.out test18.out test21.out test26.out \
+ test30.out test31.out test32.out test33.out test34.out \
+ test37.out test38.out test39.out test40.out test41.out \
+ test42.out test52.out
+
+SCRIPTS32 = test50.out
+
+SCRIPTS_GUI = test16.out
+
+.SUFFIXES: .in .out
+
+nongui: $(SCRIPTS16) $(SCRIPTS)
+ echo ALL DONE
+
+small: $(SCRIPTS16)
+ echo ALL DONE
+
+gui: $(SCRIPTS16) $(SCRIPTS) $(SCRIPTS_GUI)
+ echo ALL DONE
+
+win32: $(SCRIPTS16) $(SCRIPTS) $(SCRIPTS32)
+ echo ALL DONE
+
+clean:
+ -del *.out
+ -del test.ok
+ -del small.vim
+ -del tiny.vim
+ -del mbyte.vim
+ -del X*
+ -del viminfo
+
+.in.out:
+ copy $*.ok test.ok
+ $(VIMPROG) -u dos.vim -U NONE --noplugin -s dotest.in $*.in
+ diff test.out $*.ok
+ -del $*.out
+ rename test.out $*.out
+ -del X*
+ -del test.ok
+ -del viminfo
diff --git a/src/testdir/Make_os2.mak b/src/testdir/Make_os2.mak
new file mode 100644
index 000000000..af582023a
--- /dev/null
+++ b/src/testdir/Make_os2.mak
@@ -0,0 +1,52 @@
+#
+# Makefile to run al tests for Vim, on OS/2
+#
+# Requires a set of Unix tools: echo, diff, etc.
+
+VIMPROG = ../vim.exe
+
+# Omitted:
+# test2 "\\tmp" doesn't work.
+# test10 'errorformat' is different
+# test11 requires sed
+# test12 can't unlink a swap file
+# test25 uses symbolic link
+# test27 can't edit file with "*" in file name
+# test52 only for Win32
+
+SCRIPTS = test1.out test3.out test4.out test5.out test6.out \
+ test7.out test8.out test9.out \
+ test13.out test14.out test15.out test17.out \
+ test18.out test19.out test20.out test21.out test22.out \
+ test23.out test24.out test26.out \
+ test28.out test29.out test30.out test31.out test32.out \
+ test33.out test34.out test35.out test36.out test37.out \
+ test38.out test39.out test40.out test41.out test42.out \
+ test43.out test44.out test45.out test46.out test47.out \
+ test48.out test51.out
+
+.SUFFIXES: .in .out
+
+all: /tmp $(SCRIPTS)
+ @echo ALL DONE
+
+$(SCRIPTS): $(VIMPROG)
+
+clean:
+ -rm -rf *.out Xdotest test.ok tiny.vim small.vim mbyte.vim viminfo
+
+# Make sure all .in and .out files are in DOS fileformat.
+.in.out:
+ $(VIMPROG) -u NONE -s todos.vim $*.in
+ $(VIMPROG) -u NONE -s todos.vim $*.ok
+ copy $*.ok test.ok
+ $(VIMPROG) -u os2.vim --noplugin -s dotest.in $*.in
+ $(VIMPROG) -u NONE -s todos.vim test.out
+ diff test.out $*.ok
+ rename test.out $*.out
+ -rm -rf X* viminfo
+ -del test.ok
+
+# Create a directory for temp files
+/tmp:
+ -mkdir /tmp
diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms
new file mode 100644
index 000000000..23b0b26fc
--- /dev/null
+++ b/src/testdir/Make_vms.mms
@@ -0,0 +1,124 @@
+#
+# Makefile to run all tests for Vim on VMS
+#
+# Authors: Zoltan Arpadffy, <arpadffy@polarhome.com>
+# Sandor Kopanyi, <sandor.kopanyi@mailbox.hu>
+#
+# Last change: 2004 May 03
+#
+# This has been tested on VMS 6.2 to 7.2 on DEC Alpha and VAX.
+# Edit the lines in the Configuration section below to select.
+#
+# Execute with:
+# mms/descrip=Make_vms.mms
+# Cleanup with:
+# mms/descrip=Make_vms.mms clean
+#
+# Make files are MMK compatible.
+#
+# NOTE: You can run this script just in X/Window environment. It will
+# create a new terminals, therefore you have to set up your DISPLAY
+# logical. More info in VMS documentation or with: help set disp.
+#
+#######################################################################
+# Configuration section.
+#######################################################################
+
+# Uncomment if you want tests in GUI mode. Terminal mode is default.
+# WANT_GUI = YES
+
+# Comment out if you want to run Unix specific tests as well, but please
+# be aware, that on OpenVMS will fail, because of cat, rm, etc commands
+# and directory handling.
+# WANT_UNIX = YES
+
+# Comment out if you have gzip on your system
+# HAVE_GZIP = YES
+
+# Comment out if you have GNU compatible diff on your system
+# HAVE_GDIFF = YES
+
+#######################################################################
+# End of configuration section.
+#
+# Please, do not change anything below without programming experience.
+#######################################################################
+
+VIMPROG = <->vim.exe
+
+.SUFFIXES : .out .in
+
+SCRIPT = test1.out test2.out test3.out test4.out test5.out \
+ test6.out test7.out test8.out test9.out test10a.out\
+ test13.out test14.out test15.out test17.out \
+ test18.out test19.out test20.out test21.out test22.out \
+ test23.out test24.out test26.out \
+ test28.out test29.out test31.out test32.out \
+ test33.out test34.out test35.out test36.out test37.out \
+ test38.out test39.out test40.out test41.out test42.out \
+ test43.out test44.out test45.out test46.out \
+ test48.out test51.out
+
+.IFDEF WANT_GUI
+SCRIPT_GUI = test16.out
+GUI_OPTION = -g
+.ENDIF
+
+.IFDEF WANT_UNIX
+SCRIPT_UNIX = test10.out test12.out test25.out test27.out test30.out test49.out
+.ENDIF
+
+.IFDEF HAVE_GZIP
+SCRIPT_GZIP = test11.out
+.ENDIF
+
+.IFDEF HAVE_GDIFF
+SCRIPT_GDIFF = test47.out
+.ENDIF
+
+.in.out :
+ -@ write sys$output " "
+ -@ write sys$output "-----------------------------------------------"
+ -@ write sys$output " "$*" "
+ -@ write sys$output "-----------------------------------------------"
+ -@ create/term/wait mcr $(VIMPROG) $(GUI_OPTION) -u vms.vim --noplugin -s dotest.in $*.in
+ -@ if "''F$SEARCH("test.out.*")'" .NES. "" then differences test.out $*.ok;
+ -@ if "''F$SEARCH("test.out.*")'" .NES. "" then rename test.out $*.out
+ -@ if "''F$SEARCH("Xdotest.*")'" .NES. "" then delete/noconfirm/nolog Xdotest.*.*
+
+all : clean nolog $(SCRIPT) $(SCRIPT_GUI) $(SCRIPT_UNIX) $(SCRIPT_GZIP) $(SCRIPT_GDIFF)
+ -@ write sys$output " "
+ -@ write sys$output "-----------------------------------------------"
+ -@ write sys$output " All done"
+ -@ write sys$output "-----------------------------------------------"
+ -@ deassign sys$output
+ -@ delete/noconfirm/nolog x*.*.*
+ -@ type test.log
+
+nolog :
+ -@ define sys$output test.log
+ -@ write sys$output "-----------------------------------------------"
+ -@ write sys$output " Standard VIM test cases"
+ -@ write sys$output "-----------------------------------------------"
+ -@ write sys$output " OpenVMS version: ''F$GETSYI("VERSION")'"
+ -@ write sys$output " Vim version:"
+ -@ mcr $(VIMPROG) --version
+ -@ write sys$output " Test date:"
+ -@ show time
+ -@ write sys$output "-----------------------------------------------"
+ -@ write sys$output " Test results:"
+ -@ write sys$output "-----------------------------------------------"
+ -@ write sys$output "MAKE_VMS.MMS options:"
+ -@ write sys$output " WANT_GUI = ""$(WANT_GUI)"" "
+ -@ write sys$output " WANT_UNIX = ""$(WANT_UNIX)"" "
+ -@ write sys$output " HAVE_GZIP = ""$(HAVE_GZIP)"" "
+ -@ write sys$output " HAVE_GDIFF= ""$(HAVE_GDIFF)"" "
+ -@ write sys$output "Default vimrc file is VMS.VIM:
+ -@ write sys$output "-----------------------------------------------"
+ -@ type VMS.VIM
+
+clean :
+ -@ if "''F$SEARCH("*.out")'" .NES. "" then delete/noconfirm/nolog *.out.*
+ -@ if "''F$SEARCH("test.log")'" .NES. "" then delete/noconfirm/nolog test.log.*
+ -@ if "''F$SEARCH("Xdotest.*")'" .NES. "" then delete/noconfirm/nolog Xdotest.*.*
+ -@ if "''F$SEARCH("*.*_sw*")'" .NES. "" then delete/noconfirm/nolog *.*_sw*.*
diff --git a/src/testdir/Makefile b/src/testdir/Makefile
new file mode 100644
index 000000000..7ed97fe21
--- /dev/null
+++ b/src/testdir/Makefile
@@ -0,0 +1,58 @@
+#
+# Makefile to run al tests for Vim
+#
+
+VIMPROG = ../vim
+
+SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \
+ test7.out test8.out test9.out test10.out test11.out \
+ test12.out test13.out test14.out test15.out test17.out \
+ test18.out test19.out test20.out test21.out test22.out \
+ test23.out test24.out test25.out test26.out test27.out \
+ test28.out test29.out test30.out test31.out test32.out \
+ test33.out test34.out test35.out test36.out test37.out \
+ test38.out test39.out test40.out test41.out test42.out \
+ test43.out test44.out test45.out test46.out test47.out \
+ test48.out test49.out test51.out test52.out
+
+SCRIPTS_GUI = test16.out
+
+.SUFFIXES: .in .out
+
+nongui: nolog $(SCRIPTS)
+ @echo
+ @cat test.log
+ @echo ALL DONE
+
+gui: nolog $(SCRIPTS) $(SCRIPTS_GUI)
+ @echo
+ @cat test.log
+ @echo ALL DONE
+
+$(SCRIPTS) $(SCRIPTS_GUI): $(VIMPROG)
+
+clean:
+ -rm -rf *.out *.rej *.orig test.log tiny.vim small.vim mbyte.vim test.ok X* viminfo
+
+test1.out: test1.in
+ -rm -f $*.failed tiny.vim small.vim mbyte.vim test.ok X* viminfo
+ $(VIMPROG) -u unix.vim -U NONE --noplugin -s dotest.in $*.in
+ @/bin/sh -c "if diff test.out $*.ok; \
+ then mv -f test.out $*.out; \
+ else echo; \
+ echo test1 FAILED - Something basic is wrong; \
+ echo; exit 1; fi"
+ -rm -rf X* viminfo
+
+.in.out:
+ -rm -f $*.failed test.ok X*
+ cp $*.ok test.ok
+ $(VIMPROG) -u unix.vim -U NONE --noplugin -s dotest.in $*.in
+ @/bin/sh -c "if diff test.out $*.ok; \
+ then mv -f test.out $*.out; \
+ else echo $* FAILED >>test.log; mv -f test.out $*.failed; \
+ fi"
+ -rm -rf X* test.ok viminfo
+
+nolog:
+ -echo Test results: >test.log
diff --git a/src/testdir/amiga.vim b/src/testdir/amiga.vim
new file mode 100644
index 000000000..e0ca47a8e
--- /dev/null
+++ b/src/testdir/amiga.vim
@@ -0,0 +1,4 @@
+" Settings for test script execution
+set shell=csh
+map! /tmp t:
+cmap !rm !Delete all
diff --git a/src/testdir/dos.vim b/src/testdir/dos.vim
new file mode 100644
index 000000000..27764db9d
--- /dev/null
+++ b/src/testdir/dos.vim
@@ -0,0 +1,7 @@
+" Settings for test script execution
+" Always use "COMMAND.COM", don't use the value of "$SHELL".
+set shell=c:\COMMAND.COM shellquote= shellxquote= shellcmdflag=/c shellredir=>
+" This is used only when the +eval feature is available.
+if executable("cmd.exe")
+ set shell=cmd.exe
+endif
diff --git a/src/testdir/dotest.in b/src/testdir/dotest.in
new file mode 100644
index 000000000..b2a0e1a68
--- /dev/null
+++ b/src/testdir/dotest.in
@@ -0,0 +1,3 @@
+:set cp
+:map dotest /^STARTTEST j:set ff=unix cpo-=A :.,/ENDTEST/-1w! Xdotest :set ff& cpo+=A nj0:so! Xdotest dotest
+dotest
diff --git a/src/testdir/main.aap b/src/testdir/main.aap
new file mode 100644
index 000000000..0293b92f8
--- /dev/null
+++ b/src/testdir/main.aap
@@ -0,0 +1,58 @@
+#
+# Makefile to run al tests for Vim
+#
+
+VimProg ?= ../vim
+
+Scripts = test1.out test2.out test3.out test4.out test5.out test6.out
+ test7.out test8.out test9.out test10.out test11.out
+ test12.out test13.out test14.out test15.out test17.out
+ test18.out test19.out test20.out test21.out test22.out
+ test23.out test24.out test25.out test26.out test27.out
+ test28.out test29.out test30.out test31.out test32.out
+ test33.out test34.out test35.out test36.out test37.out
+ test38.out test39.out test40.out test41.out test42.out
+ test43.out test44.out test45.out test46.out test47.out
+ test48.out test49.out
+
+ScriptsGUI = test16.out
+
+# Build "nongui" when no target was specified.
+nongui: newlog $Scripts
+ :print
+ :cat test.log
+ :print ALL DONE
+
+# Build "ngui" when specified.
+gui: newlog $Scripts $ScriptsGUI
+ :print
+ :cat test.log
+ :print ALL DONE
+
+$Scripts $ScriptsGUI: $VimProg
+
+clean:
+ :del {r}{force} *.out test.log tiny.vim small.vim mbyte.vim test.ok X*
+
+# test1 is special, it checks for features
+test1.out: test1.in
+ :del {force} test1.failed tiny.vim small.vim mbyte.vim
+ :sys {i} $VimProg -u unix.vim -U NONE --noplugin -s dotest.in test1.in
+ @if os.system("diff test.out test1.ok") != 0:
+ :error test1 FAILED - Something basic is wrong
+ :move {force} test.out test1.out
+ :del {r}{force} X*
+
+:rule %.out : %.in
+ :del {force} $(match).failed test.ok
+ :copy $(match).ok test.ok
+ :sys {i} $VimProg -u unix.vim -U NONE --noplugin -s dotest.in $(match).in
+ @if os.system("diff test.out " + match + ".ok") != 0:
+ :print $match FAILED >>test.log
+ :move {force} test.out $(match).failed
+ @else:
+ :move {force} test.out $(match).out
+ :del {r}{force} X* test.ok
+
+newlog:
+ :print Test results: >! test.log
diff --git a/src/testdir/os2.vim b/src/testdir/os2.vim
new file mode 100644
index 000000000..c97ba5d00
--- /dev/null
+++ b/src/testdir/os2.vim
@@ -0,0 +1,3 @@
+" Settings for test script execution
+" Always use "CMD.EXE", don't use the value of "$SHELL".
+set shell=CMD.EXE shellquote= shellxquote= shellcmdflag=/c shellredir=>
diff --git a/src/testdir/test1.in b/src/testdir/test1.in
new file mode 100644
index 000000000..6d1bddee9
--- /dev/null
+++ b/src/testdir/test1.in
@@ -0,0 +1,40 @@
+
+First a simple test to check if the test script works.
+
+If Vim was not compiled with the +eval feature, the small.vim script will be
+set to copy the test.ok file to test.out, so that it looks like the test
+succeeded. Otherwise an empty small.vim is written. small.vim is sourced by
+tests that require the +eval feature or other features that are missing in the
+small version.
+
+If Vim was not compiled with the +windows feature, the tiny.vim script will be
+set like small.vim above. tiny.vim is sourced by tests that require the
++windows feature or other features that are missing in the tiny version.
+
+If Vim was not compiled with the +multi_byte feature, the mbyte.vim script will be set like small.vim above. mbyte.vim is sourced by tests that require the
++multi_byte feature.
+
+STARTTEST
+:" Write a single line to test.out to check if testing works at all.
+:%d
+athis is a test:w! test.out
+:" Create small.vim and tiny.vim empty, create mbyte.vim to skip the test.
+0D:w! small.vim
+:w! tiny.vim
+ae! test.ok
+w! test.out
+qa!
+:w! mbyte.vim
+:" If +multi_byte feature supported, make mbyte.vim empty.
+:if has("multi_byte") | sp another | w! mbyte.vim | q | endif
+:" If +eval feature supported quit here, leaving tiny.vim and small.vim empty.
+:" Otherwise write small.vim to skip the test.
+:if 1 | q! | endif
+:w! small.vim
+:" If +windows feature not supported :sp will fail and tiny.vim will be
+:" written to skip the test.
+:sp another
+:wq! tiny.vim
+:qa!
+ENDTEST
+
diff --git a/src/testdir/test1.ok b/src/testdir/test1.ok
new file mode 100644
index 000000000..90bfcb510
--- /dev/null
+++ b/src/testdir/test1.ok
@@ -0,0 +1 @@
+this is a test
diff --git a/src/testdir/test10.in b/src/testdir/test10.in
new file mode 100644
index 000000000..f15c4f5d2
--- /dev/null
+++ b/src/testdir/test10.in
@@ -0,0 +1,57 @@
+Test for 'errorformat'.
+
+STARTTEST
+:so small.vim
+:/start of errorfile/,/end of errorfile/w! Xerrorfile
+:/start of testfile/,/end of testfile/w! Xtestfile
+:cf Xerrorfile
+rA
+:cn
+rB
+:cn
+rC
+:cn
+rD
+:cn
+rE
+:w! test.out " Write contents of this file
+:qa!
+ENDTEST
+
+start of errorfile
+"Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set.
+"Xtestfile", line 7 col 19; this is an error
+gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include version.c
+Xtestfile:13: parse error before `asd'
+make: *** [vim] Error 1
+in file "Xtestfile" linenr 16: there is an error
+
+2 returned
+"Xtestfile", linenr 19: yet another problem
+
+Does anyone know what is the problem and how to correction it?
+end of errorfile
+
+start of testfile
+line 2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 16 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 19 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+end of testfile
diff --git a/src/testdir/test10.ok b/src/testdir/test10.ok
new file mode 100644
index 000000000..2c86889c1
--- /dev/null
+++ b/src/testdir/test10.ok
@@ -0,0 +1,23 @@
+start of testfile
+line 2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 xxxAxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 7 xxxxxxxxxxBxxxxxxxxxxxxxxxxxxx
+line 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Cine 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Dine 16 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Eine 19 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+end of testfile
diff --git a/src/testdir/test10a.in b/src/testdir/test10a.in
new file mode 100644
index 000000000..19e8652fe
--- /dev/null
+++ b/src/testdir/test10a.in
@@ -0,0 +1,73 @@
+Test for 'errorformat'.
+
+STARTTEST
+:so small.vim
+:/start of errorfile/,/end of errorfile/w! Xerrorfile
+:/start of testfile/,/end of testfile/w! Xtestfile
+:cf Xerrorfile
+rA
+:cn
+rB
+:cn
+rC
+:cn
+rD
+:cn
+rE
+:w! test.out " Write contents of this file
+:qa!
+ENDTEST
+
+start of errorfile
+
+ printf(" %d \n", (number/other)%10 );
+..................^
+%CC-E-NOSEMI, Missing ";".
+at line number 4 in file SYS$DISK:XTESTFILE
+
+ other=10000000;
+.............^
+%CC-E-UNDECLARED, In this statement, "oszt" is not declared.
+at line number 7 in file SYS$DISK:XTESTFILE
+
+ for (i = 0; i<7 ; i++ ){
+..................^
+%CC-E-UNDECLARED, In this statement, "i" is not declared.
+at line number 16 in file SYS$DISK:XTESTFILE
+
+some other error somewhere here.
+...........................^
+%CC-W-WARRING, Sorry, but no expalnation for such an warring.
+at line number 19 in file SYS$DISK:XTESTFILE
+
+and finally some other error exactly here.
+.....................................^
+%CC-I-INFORMATIONAL, It should be some informational message.
+at line number 20 in file SYS$DISK:XTESTFILE
+
+Does anyone know what is the problem and how to correct ?? :)
+end of errorfile
+
+start of testfile
+01234567890123456789012345678901234567
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 16 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 19 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+end of testfile
diff --git a/src/testdir/test10a.ok b/src/testdir/test10a.ok
new file mode 100644
index 000000000..10e78c923
--- /dev/null
+++ b/src/testdir/test10a.ok
@@ -0,0 +1,23 @@
+start of testfile
+01234567890123456789012345678901234567
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 xxxxxxxxxxAxxxxxxxxxxxxxxxxxxx
+line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 7 xxxxxBxxxxxxxxxxxxxxxxxxxxxxxx
+line 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 16 xxxxxxxxxxCxxxxxxxxxxxxxxxxxxx
+line 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 19 xxxxxxxxxxxxxxxxxxxDxxxxxxxxxx
+line 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxE
+line 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+end of testfile
diff --git a/src/testdir/test11.in b/src/testdir/test11.in
new file mode 100644
index 000000000..6b296fd4e
--- /dev/null
+++ b/src/testdir/test11.in
@@ -0,0 +1,77 @@
+Tests for autocommands:
+- FileWritePre writing a compressed file
+- FileReadPost reading a compressed file
+- BufNewFile reading a file template
+- BufReadPre decompressing the file to be read
+- FilterReadPre substituting characters in the temp file
+- FilterReadPost substituting characters after filtering
+- FileReadPre set options for decompression
+- FileReadPost decompress the file
+
+Note: This test will fail if "gzip" is not available.
+$GZIP is made empty, "-v" would cause trouble.
+Use a FileChangedShell autocommand to avoid a prompt for "Xtestfile.gz" being
+modified outside of Vim (noticed on Solaris).
+
+STARTTEST
+:so small.vim
+:let $GZIP = ""
+:au FileChangedShell * echo "caught FileChangedShell"
+:set bin
+:au FileWritePre *.gz '[,']!gzip
+:au FileWritePost *.gz undo
+:/start of testfile/,/end of testfile/w! Xtestfile.gz
+:au FileReadPost *.gz '[,']!gzip -d
+:$r Xtestfile.gz " Read and decompress the testfile
+:?startstart?,$w! test.out " Write contents of this file
+:au BufNewFile *.c read Xtest.c
+gg/^end of testfile
+:/start of test.c/+1,/end of test.c/-1w! Xtest.c
+:e! foo.c " Will load Xtest.c
+:au FileAppendPre *.out '[,']s/new/NEW/
+:au FileAppendPost *.out !cat Xtest.c >>test.out
+:w>>test.out " Append it to the output file
+:au! FileAppendPre
+:" setup autocommands to decompress before reading and re-compress afterwards
+:au BufReadPre *.gz !gzip -d <afile>
+:au BufReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))
+:au BufReadPost *.gz call rename(expand("<afile>"), expand("<afile>:r"))
+:au BufReadPost *.gz !gzip <afile>:r
+:e! Xtestfile.gz " Edit compressed file
+:w>>test.out " Append it to the output file
+:au FilterReadPre *.out call rename(expand("<afile>"), expand("<afile>").".t")
+:au FilterReadPre *.out !sed s/e/E/ <afile>.t ><afile>
+:au FilterReadPre *.out !rm <afile>.t
+:au FilterReadPost *.out '[,']s/x/X/g
+:e! test.out " Edit the output file
+:23,$!cat
+:au! FileReadPre *.gz !gzip -d <afile>
+:au FileReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))
+:au! FileReadPost *.gz '[,']s/l/L/
+:$r Xtestfile.gz " Read compressed file
+:w " write it, after filtering
+:au! " remove all autocommands
+:e " Edit test.out again
+:set nobin ff& " use the default fileformat for writing
+:w
+:qa!
+ENDTEST
+
+startstart
+start of testfile
+line 2 Abcdefghijklmnopqrstuvwxyz
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 Abcdefghijklmnopqrstuvwxyz
+line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 6 Abcdefghijklmnopqrstuvwxyz
+line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 8 Abcdefghijklmnopqrstuvwxyz
+line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 10 Abcdefghijklmnopqrstuvwxyz
+end of testfile
+
+start of test.c
+/*
+ * Here is a new .c file
+ */
+end of test.c
diff --git a/src/testdir/test11.ok b/src/testdir/test11.ok
new file mode 100644
index 000000000..af8c5ce26
--- /dev/null
+++ b/src/testdir/test11.ok
@@ -0,0 +1,61 @@
+startstart
+start of testfile
+line 2 Abcdefghijklmnopqrstuvwxyz
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 Abcdefghijklmnopqrstuvwxyz
+line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 6 Abcdefghijklmnopqrstuvwxyz
+line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 8 Abcdefghijklmnopqrstuvwxyz
+line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 10 Abcdefghijklmnopqrstuvwxyz
+end of testfile
+
+start of test.c
+/*
+ * Here is a new .c file
+ */
+end of test.c
+start of testfile
+line 2 Abcdefghijklmnopqrstuvwxyz
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 Abcdefghijklmnopqrstuvwxyz
+linE 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 6 AbcdefghijklmnopqrstuvwXyz
+linE 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 8 AbcdefghijklmnopqrstuvwXyz
+linE 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 10 AbcdefghijklmnopqrstuvwXyz
+End of testfile
+
+/*
+ * HEre is a NEW .c file
+ */
+/*
+ * HEre is a new .c file
+ */
+start of tEstfile
+linE 2 AbcdefghijklmnopqrstuvwXyz
+linE 3 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 4 AbcdefghijklmnopqrstuvwXyz
+linE 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 6 AbcdefghijklmnopqrstuvwXyz
+linE 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 8 AbcdefghijklmnopqrstuvwXyz
+linE 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 10 AbcdefghijklmnopqrstuvwXyz
+End of testfile
+/*
+ * HEre is a new .c file
+ */
+start of testfiLe
+Line 2 Abcdefghijklmnopqrstuvwxyz
+Line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Line 4 Abcdefghijklmnopqrstuvwxyz
+Line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Line 6 Abcdefghijklmnopqrstuvwxyz
+Line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Line 8 Abcdefghijklmnopqrstuvwxyz
+Line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Line 10 Abcdefghijklmnopqrstuvwxyz
+end of testfiLe
diff --git a/src/testdir/test12.in b/src/testdir/test12.in
new file mode 100644
index 000000000..46e9c45b8
--- /dev/null
+++ b/src/testdir/test12.in
@@ -0,0 +1,52 @@
+Tests for 'directory' option.
+- ".", in same dir as file
+- "./dir", in directory relative to file
+- "dir", in directory relative to current dir
+
+STARTTEST
+:so small.vim
+:set nocompatible viminfo+=nviminfo
+:set dir=.,~
+:/start of testfile/,/end of testfile/w! Xtest1
+:" do an ls of the current dir to find the swap file (should not be there)
+:if has("unix")
+: !ls .X*.swp >test.out
+:else
+: r !ls X*.swp >test.out
+:endif
+:!echo first line >>test.out
+:e Xtest1
+:if has("unix")
+:" Do an ls of the current dir to find the swap file, remove the leading dot
+:" to make the result the same for all systems.
+: r!ls .X*.swp
+: s/\.*X/X/
+: .w >>test.out
+: undo
+:else
+: !ls X*.swp >>test.out
+:endif
+:!echo under Xtest1.swp >>test.out
+:!mkdir Xtest2
+:set dir=./Xtest2,.,~
+:e Xtest1
+:!ls X*.swp >>test.out
+:!echo under under >>test.out
+:!ls Xtest2 >>test.out
+:!echo under Xtest1.swp >>test.out
+:!mkdir Xtest.je
+:/start of testfile/,/end of testfile/w! Xtest2/Xtest3
+:set dir=Xtest.je,~
+:e Xtest2/Xtest3
+:swap
+:!ls Xtest2 >>test.out
+:!echo under Xtest3 >>test.out
+:!ls Xtest.je >>test.out
+:!echo under Xtest3.swp >>test.out
+:qa!
+ENDTEST
+
+start of testfile
+line 2 Abcdefghij
+line 3 Abcdefghij
+end of testfile
diff --git a/src/testdir/test12.ok b/src/testdir/test12.ok
new file mode 100644
index 000000000..605623b11
--- /dev/null
+++ b/src/testdir/test12.ok
@@ -0,0 +1,10 @@
+first line
+Xtest1.swp
+under Xtest1.swp
+under under
+Xtest1.swp
+under Xtest1.swp
+Xtest3
+under Xtest3
+Xtest3.swp
+under Xtest3.swp
diff --git a/src/testdir/test13.in b/src/testdir/test13.in
new file mode 100644
index 000000000..cb8a6fff8
--- /dev/null
+++ b/src/testdir/test13.in
@@ -0,0 +1,58 @@
+Tests for autocommands on :close command
+
+Write three files and open them, each in a window.
+Then go to next window, with autocommand that deletes the previous one.
+Do this twice, writing the file.
+
+Also test deleting the buffer on a Unload event. If this goes wrong there
+will be the ATTENTION prompt.
+
+Also test changing buffers in a BufDel autocommand. If this goes wrong there
+are ml_line errors and/or a Crash.
+
+STARTTEST
+:so small.vim
+:/^start of testfile/,/^end of testfile/w! Xtestje1
+:/^start of testfile/,/^end of testfile/w! Xtestje2
+:/^start of testfile/,/^end of testfile/w! Xtestje3
+:e Xtestje1
+otestje1
+:w
+:sp Xtestje2
+otestje2
+:w
+:sp Xtestje3
+otestje3
+:w
+
+:au WinLeave Xtestje2 bwipe
+
+:w! test.out
+:au WinLeave Xtestje1 bwipe Xtestje3
+:close
+:w >>test.out
+:e Xtestje1
+:bwipe Xtestje2 Xtestje3 test.out
+:au!
+:au! BufUnload Xtestje1 bwipe
+:e Xtestje3
+:w >>test.out
+:e Xtestje2
+:sp Xtestje1
+:e
+:w >>test.out
+:au!
+:only
+:e Xtestje1
+:bwipe Xtestje2 Xtestje3 test.out test13.in
+:au BufWipeout Xtestje1 buf Xtestje1
+:bwipe
+:w >>test.out
+:qa!
+ENDTEST
+
+start of testfile
+ contents
+ contents
+ contents
+end of testfile
diff --git a/src/testdir/test13.ok b/src/testdir/test13.ok
new file mode 100644
index 000000000..0f1fc347a
--- /dev/null
+++ b/src/testdir/test13.ok
@@ -0,0 +1,30 @@
+start of testfile
+testje1
+ contents
+ contents
+ contents
+end of testfile
+start of testfile
+testje1
+ contents
+ contents
+ contents
+end of testfile
+start of testfile
+testje3
+ contents
+ contents
+ contents
+end of testfile
+start of testfile
+testje2
+ contents
+ contents
+ contents
+end of testfile
+start of testfile
+testje1
+ contents
+ contents
+ contents
+end of testfile
diff --git a/src/testdir/test14.in b/src/testdir/test14.in
new file mode 100644
index 000000000..57fb9573f
--- /dev/null
+++ b/src/testdir/test14.in
@@ -0,0 +1,65 @@
+Tests for "vaBiB", end could be wrong.
+Also test ":s/pat/sub/" with different ~s in sub.
+Also test for ^Vxff and ^Vo123 in Insert mode.
+Also test "[m", "]m", "[M" and "]M"
+
+STARTTEST
+:so small.vim
+/Start cursor here
+vaBiBD:?Bug?,/Piece/-2w! test.out
+/^- Bug
+:s/u/~u~/
+:s/i/~u~/
+:s/o/~~~/
+:.w >>test.out
+:if has("ebcdic")
+: let tt = "o\<C-V>193\<C-V>xc2\<C-V>o303 \<C-V>90a\<C-V>xfg\<C-V>o578\<Esc>"
+:else
+: let tt = "o\<C-V>65\<C-V>x42\<C-V>o103 \<C-V>33a\<C-V>xfg\<C-V>o78\<Esc>"
+:endif
+:exe "normal " . tt
+:.w >>test.out
+:set vb
+/^Piece
+2]maA:.w >>test.out
+j]maB:.w >>test.out
+]maC:.w >>test.out
+[maD:.w >>test.out
+k2[maE:.w >>test.out
+3[maF:.w >>test.out
+]MaG:.w >>test.out
+j2]MaH:.w >>test.out
+]M]MaI:.w >>test.out
+2[MaJ:.w >>test.out
+k[MaK:.w >>test.out
+3[MaL:.w >>test.out
+:qa!
+ENDTEST
+
+- Bug in "vPPPP" on this text (Webb):
+ {
+ cmd;
+ {
+ cmd; /* <-- Start cursor here */
+ {
+ }
+ }
+ }
+
+Piece of Java
+{
+ tt m1 {
+ t1;
+ } e1
+
+ tt m2 {
+ t2;
+ } e2
+
+ tt m3 {
+ if (x)
+ {
+ t3;
+ }
+ } e3
+}
diff --git a/src/testdir/test14.ok b/src/testdir/test14.ok
new file mode 100644
index 000000000..e893ba803
--- /dev/null
+++ b/src/testdir/test14.ok
@@ -0,0 +1,17 @@
+- Bug in "vPPPP" on this text (Webb):
+ {
+ }
+- Bug uuun "vPPPP" uuuuuuuuun this text (Webb):
+ABC !ag8
+ tt m1 {A
+ tt m2 {B
+ tt m3 {C
+ tt m3 {DC
+ tt m1 {EA
+{F
+ }G e1
+ }H e3
+}I
+ }JH e3
+ }K e2
+{LF
diff --git a/src/testdir/test15.in b/src/testdir/test15.in
new file mode 100644
index 000000000..366529a55
--- /dev/null
+++ b/src/testdir/test15.in
@@ -0,0 +1,136 @@
+Tests for :right on text with embedded TAB.
+Also test formatting a paragraph.
+Also test undo after ":%s" and formatting.
+
+STARTTEST
+:so small.vim
+:set tw=65
+
+:/^\s*test for :left/,/^\s*test for :center/ left
+:/^\s*test for :center/,/^\s*test for :right/ center
+:/^\s*test for :right/,/^xxx/-1 right
+:set fo+=tcroql tw=72
+/xxxxxxxx$
+0gq6kk
+:set nocp viminfo+=nviminfo
+:" undo/redo here to make the next undo only work on the following changes
+u
+:map gg :.,.+2s/^/x/<CR>kk:set tw=3<CR>gqq
+/^aa
+ggu
+:?test for :left?,$w! test.out
+:qa!
+ENDTEST
+
+ test for :left
+ a a
+ fa a
+ dfa a
+ sdfa a
+ asdfa a
+ xasdfa a
+asxxdfa a
+
+ test for :center
+ a a
+ fa afd asdf
+ dfa a
+ sdfa afd asdf
+ asdfa a
+ xasdfa asdfasdfasdfasdfasdf
+asxxdfa a
+
+ test for :right
+ a a
+ fa a
+ dfa a
+ sdfa a
+ asdfa a
+ xasdfa a
+ asxxdfa a
+ asxa;ofa a
+ asdfaqwer a
+ a ax
+ fa ax
+ dfa ax
+ sdfa ax
+ asdfa ax
+ xasdfa ax
+ asxxdfa ax
+ asxa;ofa ax
+ asdfaqwer ax
+ a axx
+ fa axx
+ dfa axx
+ sdfa axx
+ asdfa axx
+ xasdfa axx
+ asxxdfa axx
+ asxa;ofa axx
+ asdfaqwer axx
+ a axxx
+ fa axxx
+ dfa axxx
+ sdfa axxx
+ asdfa axxx
+ xasdfa axxx
+ asxxdfa axxx
+ asxa;ofa axxx
+ asdfaqwer axxx
+ a axxxo
+ fa axxxo
+ dfa axxxo
+ sdfa axxxo
+ asdfa axxxo
+ xasdfa axxxo
+ asxxdfa axxxo
+ asxa;ofa axxxo
+ asdfaqwer axxxo
+ a axxxoi
+ fa axxxoi
+ dfa axxxoi
+ sdfa axxxoi
+ asdfa axxxoi
+ xasdfa axxxoi
+ asxxdfa axxxoi
+ asxa;ofa axxxoi
+ asdfaqwer axxxoi
+ a axxxoik
+ fa axxxoik
+ dfa axxxoik
+ sdfa axxxoik
+ asdfa axxxoik
+ xasdfa axxxoik
+ asxxdfa axxxoik
+ asxa;ofa axxxoik
+ asdfaqwer axxxoik
+ a axxxoike
+ fa axxxoike
+ dfa axxxoike
+ sdfa axxxoike
+ asdfa axxxoike
+ xasdfa axxxoike
+ asxxdfa axxxoike
+ asxa;ofa axxxoike
+ asdfaqwer axxxoike
+ a axxxoikey
+ fa axxxoikey
+ dfa axxxoikey
+ sdfa axxxoikey
+ asdfa axxxoikey
+ xasdfa axxxoikey
+ asxxdfa axxxoikey
+ asxa;ofa axxxoikey
+ asdfaqwer axxxoikey
+
+xxxxx xx xxxxxx
+xxxxxxx xxxxxxxxx xxx xxxx xxxxx xxxxx xxx xx
+xxxxxxxxxxxxxxxxxx xxxxx xxxx, xxxx xxxx xxxx xxxx xxx xx xx
+xx xxxxxxx. xxxx xxxx.
+
+> xx xx, xxxx xxxx xxx xxxx xxx xxxxx xxx xxx xxxxxxx xxx xxxxx
+> xxxxxx xxxxxxx: xxxx xxxxxxx, xx xxxxxx xxxx xxxxxxxxxx
+
+aa aa aa aa
+bb bb bb bb
+cc cc cc cc
diff --git a/src/testdir/test15.ok b/src/testdir/test15.ok
new file mode 100644
index 000000000..bc09f5e7d
--- /dev/null
+++ b/src/testdir/test15.ok
@@ -0,0 +1,111 @@
+test for :left
+a a
+fa a
+dfa a
+sdfa a
+asdfa a
+xasdfa a
+asxxdfa a
+
+ test for :center
+ a a
+ fa afd asdf
+ dfa a
+ sdfa afd asdf
+ asdfa a
+ xasdfa asdfasdfasdfasdfasdf
+ asxxdfa a
+
+ test for :right
+ a a
+ fa a
+ dfa a
+ sdfa a
+ asdfa a
+ xasdfa a
+ asxxdfa a
+ asxa;ofa a
+ asdfaqwer a
+ a ax
+ fa ax
+ dfa ax
+ sdfa ax
+ asdfa ax
+ xasdfa ax
+ asxxdfa ax
+ asxa;ofa ax
+ asdfaqwer ax
+ a axx
+ fa axx
+ dfa axx
+ sdfa axx
+ asdfa axx
+ xasdfa axx
+ asxxdfa axx
+ asxa;ofa axx
+ asdfaqwer axx
+ a axxx
+ fa axxx
+ dfa axxx
+ sdfa axxx
+ asdfa axxx
+ xasdfa axxx
+ asxxdfa axxx
+ asxa;ofa axxx
+ asdfaqwer axxx
+ a axxxo
+ fa axxxo
+ dfa axxxo
+ sdfa axxxo
+ asdfa axxxo
+ xasdfa axxxo
+ asxxdfa axxxo
+ asxa;ofa axxxo
+ asdfaqwer axxxo
+ a axxxoi
+ fa axxxoi
+ dfa axxxoi
+ sdfa axxxoi
+ asdfa axxxoi
+ xasdfa axxxoi
+ asxxdfa axxxoi
+ asxa;ofa axxxoi
+ asdfaqwer axxxoi
+ a axxxoik
+ fa axxxoik
+ dfa axxxoik
+ sdfa axxxoik
+ asdfa axxxoik
+ xasdfa axxxoik
+ asxxdfa axxxoik
+ asxa;ofa axxxoik
+ asdfaqwer axxxoik
+ a axxxoike
+ fa axxxoike
+ dfa axxxoike
+ sdfa axxxoike
+ asdfa axxxoike
+ xasdfa axxxoike
+ asxxdfa axxxoike
+ asxa;ofa axxxoike
+ asdfaqwer axxxoike
+ a axxxoikey
+ fa axxxoikey
+ dfa axxxoikey
+ sdfa axxxoikey
+ asdfa axxxoikey
+ xasdfa axxxoikey
+ asxxdfa axxxoikey
+ asxa;ofa axxxoikey
+ asdfaqwer axxxoikey
+
+xxxxx xx xxxxxx xxxxxxx xxxxxxxxx xxx xxxx xxxxx xxxxx xxx xx
+xxxxxxxxxxxxxxxxxx xxxxx xxxx, xxxx xxxx xxxx xxxx xxx xx xx xx xxxxxxx.
+xxxx xxxx.
+
+> xx xx, xxxx xxxx xxx xxxx xxx xxxxx xxx xxx xxxxxxx xxx xxxxx xxxxxx
+> xxxxxxx: xxxx xxxxxxx, xx xxxxxx xxxx xxxxxxxxxx
+
+aa aa aa aa
+bb bb bb bb
+cc cc cc cc
diff --git a/src/testdir/test16.in b/src/testdir/test16.in
new file mode 100644
index 000000000..7fc0d50cf
--- /dev/null
+++ b/src/testdir/test16.in
@@ -0,0 +1,10 @@
+Tests for resetting "secure" flag after GUI has started.
+
+STARTTEST
+:set exrc secure
+:gui -f
+:.,$w! test.out
+:qa!
+ENDTEST
+
+ just some text
diff --git a/src/testdir/test16.ok b/src/testdir/test16.ok
new file mode 100644
index 000000000..25e2eea5c
--- /dev/null
+++ b/src/testdir/test16.ok
@@ -0,0 +1,2 @@
+
+ just some text
diff --git a/src/testdir/test17.in b/src/testdir/test17.in
new file mode 100644
index 000000000..e59144ffb
--- /dev/null
+++ b/src/testdir/test17.in
@@ -0,0 +1,27 @@
+Tests for "gf" on ${VAR}
+
+STARTTEST
+:so small.vim
+:if has("ebcdic")
+: set isfname=@,240-249,/,.,-,_,+,,,$,:,~,{,}
+:else
+: set isfname=@,48-57,/,.,-,_,+,,,$,:,~,{,}
+:endif
+:if has("unix")
+:let $CDIR = "."
+/CDIR
+:else
+:if has("amiga")
+:let $TDIR = "/testdir"
+:else
+:let $TDIR = "."
+:endif
+/TDIR
+:endif
+gf
+:w! test.out
+:qa!
+ENDTEST
+
+ ${CDIR}/test17a.in
+ $TDIR/test17a.in
diff --git a/src/testdir/test17.ok b/src/testdir/test17.ok
new file mode 100644
index 000000000..58c3504ad
--- /dev/null
+++ b/src/testdir/test17.ok
@@ -0,0 +1,3 @@
+This file is just to test "gf" in test 17.
+The contents is not importent.
+Just testing!
diff --git a/src/testdir/test17a.in b/src/testdir/test17a.in
new file mode 100644
index 000000000..58c3504ad
--- /dev/null
+++ b/src/testdir/test17a.in
@@ -0,0 +1,3 @@
+This file is just to test "gf" in test 17.
+The contents is not importent.
+Just testing!
diff --git a/src/testdir/test18.in b/src/testdir/test18.in
new file mode 100644
index 000000000..9bfd92234
--- /dev/null
+++ b/src/testdir/test18.in
@@ -0,0 +1,16 @@
+Tests for not doing smart indenting when it isn't set.
+
+STARTTEST
+:so small.vim
+:set nocin nosi ai
+/some
+2cc#test
+:?start?,$w! test.out
+:qa!
+ENDTEST
+
+start text
+ some test text
+ test text
+test text
+ test text
diff --git a/src/testdir/test18.ok b/src/testdir/test18.ok
new file mode 100644
index 000000000..e71971378
--- /dev/null
+++ b/src/testdir/test18.ok
@@ -0,0 +1,4 @@
+start text
+ #test
+test text
+ test text
diff --git a/src/testdir/test19.in b/src/testdir/test19.in
new file mode 100644
index 000000000..0d9b421a2
--- /dev/null
+++ b/src/testdir/test19.in
@@ -0,0 +1,23 @@
+Tests for "r<Tab>" with 'smarttab' and 'expandtab' set/not set.
+
+STARTTEST
+:set smarttab expandtab ts=8 sw=4
+/some
+r :set noexpandtab
+/other
+r
+:" Test replacing with Tabs and then backspacing to undo it
+0wR 
+:" Test replacing with Tabs
+0wR 
+:?^start?,$w! test.out
+:qa!
+ENDTEST
+
+start text
+ some test text
+test text
+ other test text
+ a cde
+ f ghi
+test text
diff --git a/src/testdir/test19.ok b/src/testdir/test19.ok
new file mode 100644
index 000000000..ba4eb63be
--- /dev/null
+++ b/src/testdir/test19.ok
@@ -0,0 +1,7 @@
+start text
+ ome test text
+test text
+ ther test text
+ a cde
+ hi
+test text
diff --git a/src/testdir/test2.in b/src/testdir/test2.in
new file mode 100644
index 000000000..b7b5a5106
--- /dev/null
+++ b/src/testdir/test2.in
@@ -0,0 +1,29 @@
+
+This is a test if a URL is recognized by "gf", with the cursor before and
+after the "://". Also test ":\\".
+
+STARTTEST
+:so small.vim
+/^first
+/tmp
+:call append(0, expand("<cfile>"))
+/^second
+/URL
+:call append(1, expand("<cfile>"))
+:if has("ebcdic")
+: set isf=@,240-249,/,.,-,_,+,,,$,:,~,\
+:else
+: set isf=@,48-57,/,.,-,_,+,,,$,:,~,\
+:endif
+/^third
+/name
+:call append(2, expand("<cfile>"))
+/^fourth
+/URL
+:call append(3, expand("<cfile>"))
+5GdG:wq! test.out
+ENDTEST
+first test for URL://machine.name/tmp/vimtest2a and other text
+second test for URL://machine.name/tmp/vimtest2b. And other text
+third test for URL:\\machine.name\vimtest2c and other text
+fourth test for URL:\\machine.name\tmp\vimtest2d, and other text
diff --git a/src/testdir/test2.ok b/src/testdir/test2.ok
new file mode 100644
index 000000000..32978825f
--- /dev/null
+++ b/src/testdir/test2.ok
@@ -0,0 +1,4 @@
+URL://machine.name/tmp/vimtest2a
+URL://machine.name/tmp/vimtest2b
+URL:\\machine.name\vimtest2c
+URL:\\machine.name\tmp\vimtest2d
diff --git a/src/testdir/test20.in b/src/testdir/test20.in
new file mode 100644
index 000000000..7201c75c2
--- /dev/null
+++ b/src/testdir/test20.in
@@ -0,0 +1,22 @@
+Tests Blockwise Visual when there are TABs before the text.
+First test for undo working properly when executing commands from a register.
+Also test this in an empty buffer.
+
+STARTTEST
+:so tiny.vim
+G0"ay$k@au
+:new
+@auY:quit!
+GP
+/start here$
+jjlld
+:/here$/,$-1w! test.out
+:qa!
+ENDTEST
+
+test text test tex start here
+ some text
+ test text
+test text
+
+OxjAykdd
diff --git a/src/testdir/test20.ok b/src/testdir/test20.ok
new file mode 100644
index 000000000..2604e7cc8
--- /dev/null
+++ b/src/testdir/test20.ok
@@ -0,0 +1,6 @@
+test text test tex rt here
+ somext
+ tesext
+test text
+
+
diff --git a/src/testdir/test21.in b/src/testdir/test21.in
new file mode 100644
index 000000000..491b9f740
--- /dev/null
+++ b/src/testdir/test21.in
@@ -0,0 +1,19 @@
+Tests for [ CTRL-I with a count and CTRL-W CTRL-I with a count
+
+STARTTEST
+:so small.vim
+/start
+6[ :.w! test.out
+?start here
+6 :.w >>test.out
+:qa!
+ENDTEST
+
+#include test21.in
+
+/* test text test tex start here
+ some text
+ test text
+ start OK if found this line
+ start found wrong line
+test text
diff --git a/src/testdir/test21.ok b/src/testdir/test21.ok
new file mode 100644
index 000000000..d9f1b759c
--- /dev/null
+++ b/src/testdir/test21.ok
@@ -0,0 +1,2 @@
+ start OK if found this line
+ start OK if found this line
diff --git a/src/testdir/test22.in b/src/testdir/test22.in
new file mode 100644
index 000000000..f5cc046c6
--- /dev/null
+++ b/src/testdir/test22.in
@@ -0,0 +1,13 @@
+Tests for file with some lines ending in CTRL-M, some not
+
+STARTTEST
+:set ta tx
+:e!
+:$-3,$w! test.out
+:qa!
+ENDTEST
+
+this lines ends in a
+this one doesn't
+this one does
+and the last one doesn't
diff --git a/src/testdir/test22.ok b/src/testdir/test22.ok
new file mode 100644
index 000000000..38ff89eaf
--- /dev/null
+++ b/src/testdir/test22.ok
@@ -0,0 +1,4 @@
+this lines ends in a
+this one doesn't
+this one does
+and the last one doesn't
diff --git a/src/testdir/test23.in b/src/testdir/test23.in
new file mode 100644
index 000000000..0e0e60553
--- /dev/null
+++ b/src/testdir/test23.in
@@ -0,0 +1,15 @@
+Tests for complicated + argument to :edit command
+
+STARTTEST
+:$-1w! Xfile1
+:$w! Xfile2
+:edit +1|s/|/PIPE/|w Xfile1| e Xfile2|1 | s/\//SLASH/|w
+:w! test.out
+:e Xfile1
+:w >> test.out
+:qa!
+ENDTEST
+
+The result should be in Xfile1: "fooPIPEbar", in Xfile2: "fooSLASHbar"
+foo|bar
+foo/bar
diff --git a/src/testdir/test23.ok b/src/testdir/test23.ok
new file mode 100644
index 000000000..f1930abad
--- /dev/null
+++ b/src/testdir/test23.ok
@@ -0,0 +1,2 @@
+fooSLASHbar
+fooPIPEbar
diff --git a/src/testdir/test24.in b/src/testdir/test24.in
new file mode 100644
index 000000000..84721d992
--- /dev/null
+++ b/src/testdir/test24.in
@@ -0,0 +1,21 @@
+Tests for regexp with backslash and other special characters inside []
+
+STARTTEST
+:set nocompatible viminfo+=nviminfo
+/[\x]
+x/[\t\]]
+x/[]y]
+x/[\]]
+x/[y^]
+x/[$y]
+x:?start?,$w! test.out
+:qa!
+ENDTEST
+
+start
+test \text test text
+test text test text
+test text ]test text
+test ]text test text
+test text te^st text
+test te$xt test text
diff --git a/src/testdir/test24.ok b/src/testdir/test24.ok
new file mode 100644
index 000000000..896b50ae5
--- /dev/null
+++ b/src/testdir/test24.ok
@@ -0,0 +1,7 @@
+start
+test text test text
+test text test text
+test text test text
+test text test text
+test text test text
+test text test text
diff --git a/src/testdir/test25.in b/src/testdir/test25.in
new file mode 100644
index 000000000..4139865da
--- /dev/null
+++ b/src/testdir/test25.in
@@ -0,0 +1,31 @@
+Test for jumping to a tag with 'hidden' set, with symbolic link in path of tag.
+This only works for Unix, because of the symbolic link.
+
+STARTTEST
+:so small.vim
+:set hidden
+:" Create a link from test25.dir to the current directory.
+:!rm -f test25.dir
+:!ln -s . test25.dir
+:" Create tags.text, with the current directory name inserted.
+/tags line
+:r !pwd
+d$/test
+hP:.w! tags.test
+:" Try jumping to a tag in the current file, but with a path that contains a
+:" symbolic link. When wrong, this will give the ATTENTION message. The next
+:" space will then be eaten by hit-return, instead of moving the cursor to 'd'.
+:set tags=tags.test
+G x:.w! test.out
+:!rm -f test25.dir tags.test
+:qa!
+ENDTEST
+
+tags line:
+SECTION_OFF /test25.dir/test25.in /^#define SECTION_OFF 3$/
+
+/*tx.c*/
+#define SECTION_OFF 3
+#define NUM_SECTIONS 3
+
+SECTION_OFF
diff --git a/src/testdir/test25.ok b/src/testdir/test25.ok
new file mode 100644
index 000000000..08fc070b7
--- /dev/null
+++ b/src/testdir/test25.ok
@@ -0,0 +1 @@
+#efine SECTION_OFF 3
diff --git a/src/testdir/test26.in b/src/testdir/test26.in
new file mode 100644
index 000000000..df572c897
--- /dev/null
+++ b/src/testdir/test26.in
@@ -0,0 +1,43 @@
+Test for :execute, :while and :if
+
+STARTTEST
+:so small.vim
+mt:let i = 0
+:while i < 12
+: let i = i + 1
+: if has("ebcdic")
+: execute "normal o" . i . "\047"
+: else
+: execute "normal o" . i . "\033"
+: endif
+: if i % 2
+: normal Ax
+: if i == 9
+: break
+: endif
+: if i == 5
+: continue
+: else
+: let j = 9
+: while j > 0
+: if has("ebcdic")
+: execute "normal" j . "a" . j . "\x27"
+: else
+: execute "normal" j . "a" . j . "\x1b"
+: endif
+: let j = j - 1
+: endwhile
+: endif
+: endif
+: if i == 9
+: if has("ebcdic")
+: execute "normal Az\047"
+: else
+: execute "normal Az\033"
+: endif
+: endif
+:endwhile
+:'t,$w! test.out
+:qa!
+ENDTEST
+
diff --git a/src/testdir/test26.ok b/src/testdir/test26.ok
new file mode 100644
index 000000000..bc4476118
--- /dev/null
+++ b/src/testdir/test26.ok
@@ -0,0 +1,10 @@
+
+1x999999999888888887777777666666555554444333221
+2
+3x999999999888888887777777666666555554444333221
+4
+5x
+6
+7x999999999888888887777777666666555554444333221
+8
+9x
diff --git a/src/testdir/test27.in b/src/testdir/test27.in
new file mode 100644
index 000000000..2df16d9ef
--- /dev/null
+++ b/src/testdir/test27.in
@@ -0,0 +1,20 @@
+Test for expanding file names
+
+STARTTEST
+:!mkdir Xdir1
+:!mkdir Xdir2
+:!mkdir Xdir3
+:cd Xdir3
+:!mkdir Xdir4
+:cd ..
+:w Xdir1/file
+:w Xdir3/Xdir4/file
+:n Xdir?/*/file
+Go%:.w! test.out
+:n! Xdir?/*/nofile
+Go%:.w >>test.out
+:e! xx
+:!rm -rf Xdir1 Xdir2 Xdir3
+:qa!
+ENDTEST
+
diff --git a/src/testdir/test27.ok b/src/testdir/test27.ok
new file mode 100644
index 000000000..c35f2438a
--- /dev/null
+++ b/src/testdir/test27.ok
@@ -0,0 +1,2 @@
+Xdir3/Xdir4/file
+Xdir?/*/nofile
diff --git a/src/testdir/test28.in b/src/testdir/test28.in
new file mode 100644
index 000000000..5542c9266
--- /dev/null
+++ b/src/testdir/test28.in
Binary files differ
diff --git a/src/testdir/test28.ok b/src/testdir/test28.ok
new file mode 100644
index 000000000..911d85465
--- /dev/null
+++ b/src/testdir/test28.ok
@@ -0,0 +1,2 @@
+sd
+map __2 asdsecondsdsd0map __5 asd0fifth
diff --git a/src/testdir/test29.in b/src/testdir/test29.in
new file mode 100644
index 000000000..de93ccc22
--- /dev/null
+++ b/src/testdir/test29.in
@@ -0,0 +1,67 @@
+Test for joining lines with 'joinspaces' set or not
+
+STARTTEST
+:set nojoinspaces
+/firstline/
+jJjJjJjJjJjJjJjJjJjJjJjJjJjJ:set joinspaces
+jJjJjJjJjJjJjJjJjJjJjJjJjJjJ:?firstline?+1,$w! test.out
+:qa!
+ENDTEST
+
+firstline
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
diff --git a/src/testdir/test29.ok b/src/testdir/test29.ok
new file mode 100644
index 000000000..076f77c98
--- /dev/null
+++ b/src/testdir/test29.ok
@@ -0,0 +1,28 @@
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
diff --git a/src/testdir/test3.in b/src/testdir/test3.in
new file mode 100644
index 000000000..cd725bffb
--- /dev/null
+++ b/src/testdir/test3.in
@@ -0,0 +1,1217 @@
+/* vim: set cin ts=4 sw=4 : */
+
+Test for 'cindent'
+
+STARTTEST
+:so small.vim
+:set nocompatible viminfo+=nviminfo
+:edit " read modeline
+/start of AUTO
+=/end of AUTO
+ENDTEST
+
+/* start of AUTO matically checked */
+{
+ if (test)
+ cmd1;
+ cmd2;
+}
+
+{
+ if (test)
+ cmd1;
+ else
+ cmd2;
+}
+
+{
+ if (test)
+ {
+ cmd1;
+ cmd2;
+ }
+}
+
+{
+ if (test)
+ {
+ cmd1;
+ else
+ }
+}
+
+{
+ while (this)
+ if (test)
+ cmd1;
+ cmd2;
+}
+
+{
+ while (this)
+ if (test)
+ cmd1;
+ else
+ cmd2;
+}
+
+{
+ if (test)
+ {
+ cmd;
+ }
+
+ if (test)
+ cmd;
+}
+
+{
+ if (test) {
+ cmd;
+ }
+
+ if (test) cmd;
+}
+
+{
+ cmd1;
+ for (blah)
+ while (this)
+ if (test)
+ cmd2;
+ cmd3;
+}
+
+{
+ cmd1;
+ for (blah)
+ while (this)
+ if (test)
+ cmd2;
+ cmd3;
+
+ if (test)
+ {
+ cmd1;
+ cmd2;
+ cmd3;
+ }
+}
+
+
+/* Test for 'cindent' do/while mixed with if/else: */
+
+{
+ do
+ if (asdf)
+ asdfasd;
+ while (cond);
+
+ do
+ if (asdf)
+ while (asdf)
+ asdf;
+ while (asdf);
+}
+
+/* Test for 'cindent' with two ) on a continuation line */
+{
+ if (asdfasdf;asldkfj asdlkfj as;ldkfj sal;d
+ aal;sdkjf ( ;asldfkja;sldfk
+ al;sdjfka ;slkdf ) sa;ldkjfsa dlk;)
+ line up here;
+}
+
+
+/* C++ tests: */
+
+// foo() these three lines should remain in column 0
+// {
+// }
+
+/* Test for continuation and unterminated lines: */
+{
+ i = 99 + 14325 +
+ 21345 +
+ 21345 +
+ 21345 + ( 21345 +
+ 21345) +
+ 2345 +
+ 1234;
+ c = 1;
+}
+
+/*
+ testje for indent with empty line
+
+ here */
+
+{
+ if (testing &&
+ not a joke ||
+ line up here)
+ hay;
+ if (testing &&
+ (not a joke || testing
+ )line up here)
+ hay;
+ if (testing &&
+ (not a joke || testing
+ line up here))
+ hay;
+}
+
+
+{
+ switch (c)
+ {
+ case xx:
+ do
+ if (asdf)
+ do
+ asdfasdf;
+ while (asdf);
+ else
+ asdfasdf;
+ while (cond);
+ case yy:
+ case xx:
+ case zz:
+ testing;
+ }
+}
+
+{
+ if (cond) {
+ foo;
+ }
+ else
+ {
+ bar;
+ }
+}
+
+{
+ if (alskdfj ;alsdkfjal;skdjf (;sadlkfsa ;dlkf j;alksdfj ;alskdjf
+ alsdkfj (asldk;fj
+ awith cino=(0 ;lf this one goes to below the paren with ==
+ ;laksjfd ;lsakdjf ;alskdf asd)
+ asdfasdf;)))
+ asdfasdf;
+}
+
+ int
+func(a, b)
+ int a;
+ int c;
+{
+ if (c1 && (c2 ||
+ c3))
+ foo;
+ if (c1 &&
+ (c2 || c3)
+ )
+}
+
+{
+ while (asd)
+ {
+ if (asdf)
+ if (test)
+ if (that)
+ {
+ if (asdf)
+ do
+ cdasd;
+ while (as
+ df);
+ }
+ else
+ if (asdf)
+ asdf;
+ else
+ asdf;
+ asdf;
+ }
+}
+
+{
+ s = "/*"; b = ';'
+ s = "/*"; b = ';';
+ a = b;
+}
+
+{
+ switch (a)
+ {
+ case a:
+ switch (t)
+ {
+ case 1:
+ cmd;
+ break;
+ case 2:
+ cmd;
+ break;
+ }
+ cmd;
+ break;
+ case b:
+ {
+ int i;
+ cmd;
+ }
+ break;
+ case c: {
+ int i;
+ cmd;
+ }
+ case d: if (cond &&
+ test) { /* this line doesn't work right */
+ int i;
+ cmd;
+ }
+ break;
+ }
+}
+
+{
+ if (!(vim_strchr(p_cpo, CPO_BUFOPTGLOB) != NULL && entering) &&
+ (bp_to->b_p_initialized ||
+ (!entering && vim_strchr(p_cpo, CPO_BUFOPT) != NULL)))
+ return;
+label :
+ asdf = asdf ?
+ asdf : asdf;
+ asdf = asdf ?
+ asdf: asdf;
+}
+
+/* Special Comments : This function has the added complexity (compared */
+/* : to addtolist) of having to check for a detail */
+/* : texture and add that to the list first. */
+
+char *(array[100]) = {
+ "testje",
+ "foo",
+ "bar",
+}
+
+enum soppie
+{
+ yes = 0,
+ no,
+ maybe
+};
+
+typedef enum soppie
+{
+ yes = 0,
+ no,
+ maybe
+};
+
+{
+ int a,
+ b;
+}
+
+{
+ struct Type
+ {
+ int i;
+ char *str;
+ } var[] =
+ {
+ 0, "zero",
+ 1, "one",
+ 2, "two",
+ 3, "three"
+ };
+
+ float matrix[3][3] =
+ {
+ {
+ 0,
+ 1,
+ 2
+ },
+ {
+ 3,
+ 4,
+ 5
+ },
+ {
+ 6,
+ 7,
+ 8
+ }
+ };
+}
+
+{
+ /* blah ( blah */
+ /* where does this go? */
+
+ /* blah ( blah */
+ cmd;
+
+ func(arg1,
+ /* comment */
+ arg2);
+ a;
+ {
+ b;
+ {
+ c; /* Hey, NOW it indents?! */
+ }
+ }
+
+ {
+ func(arg1,
+ arg2,
+ arg3);
+ /* Hey, what am I doing here? Is this coz of the ","? */
+ }
+}
+
+main ()
+{
+ if (cond)
+ {
+ a = b;
+ }
+ if (cond) {
+ a = c;
+ }
+ if (cond)
+ a = d;
+ return;
+}
+
+{
+ case 2: if (asdf &&
+ asdfasdf)
+ aasdf;
+ a = 9;
+ case 3: if (asdf)
+ aasdf;
+ a = 9;
+ case 4: x = 1;
+ y = 2;
+
+label: if (asdf)
+ here;
+
+label: if (asdf &&
+ asdfasdf)
+ {
+ }
+
+label: if (asdf &&
+ asdfasdf) {
+ there;
+ }
+
+label: if (asdf &&
+ asdfasdf)
+ there;
+}
+
+{
+ /*
+ hello with ":set comments= cino=c5"
+ */
+
+ /*
+ hello with ":set comments= cino="
+ */
+}
+
+
+{
+ if (a < b) {
+ a = a + 1;
+ } else
+ a = a + 2;
+
+ if (a)
+ do {
+ testing;
+ } while (asdfasdf);
+ a = b + 1;
+ asdfasdf
+}
+
+class bob
+{
+ int foo() {return 1;}
+ int bar;
+}
+
+main()
+{
+while(1)
+if (foo)
+{
+bar;
+}
+else {
+asdf;
+}
+misplacedline;
+}
+
+{
+ if (clipboard.state == SELECT_DONE
+ && ((row == clipboard.start.lnum
+ && col >= clipboard.start.col)
+ || row > clipboard.start.lnum))
+}
+
+{
+if (1) {i += 4;}
+where_am_i;
+return 0;
+}
+
+{
+{
+} // sdf(asdf
+if (asdf)
+asd;
+}
+
+{
+label1:
+label2:
+}
+
+{
+int fooRet = foo(pBar1, false /*fKB*/,
+ true /*fPTB*/, 3 /*nT*/, false /*fDF*/);
+f() {
+for ( i = 0;
+ i < m;
+ /* c */ i++ ) {
+a = b;
+}
+}
+}
+
+{
+ f1(/*comment*/);
+ f2();
+}
+
+{
+do {
+if (foo) {
+} else
+;
+} while (foo);
+foo(); // was wrong
+}
+
+int x; // no extra indent because of the ;
+void func()
+{
+}
+
+char *tab[] = {"aaa",
+ "};", /* }; */ NULL}
+ int indented;
+{}
+
+char *a[] = {"aaa", "bbb",
+ "ccc", NULL};
+// here
+
+char *tab[] = {"aaa",
+ "xx", /* xx */}; /* asdf */
+int not_indented;
+
+{
+ do {
+ switch (bla)
+ {
+ case 1: if (foo)
+ bar;
+ }
+ } while (boo);
+ wrong;
+}
+
+int foo,
+ bar;
+int foo;
+
+#if defined(foo) \
+ && defined(bar)
+char * xx = "asdf\
+ foo\
+ bor";
+int x;
+
+char *foo = "asdf\
+ asdf\
+ asdf",
+ *bar;
+
+void f()
+{
+#if defined(foo) \
+ && defined(bar)
+char *foo = "asdf\
+ asdf\
+ asdf",
+ *bar;
+ {
+ int i;
+char *foo = "asdf\
+ asdf\
+ asdf",
+ *bar;
+ }
+#endif
+}
+#endif
+
+int y; // comment
+ // comment
+
+ // comment
+
+{
+ Constructor(int a,
+ int b ) : BaseClass(a)
+ {
+ }
+}
+
+void foo()
+{
+ char one,
+ two;
+ struct bla piet,
+ jan;
+ enum foo kees,
+ jannie;
+ static unsigned sdf,
+ krap;
+ unsigned int piet,
+ jan;
+ int
+ kees,
+ jan;
+}
+
+{
+ t(int f,
+ int d); // )
+ d();
+}
+
+Constructor::Constructor(int a,
+ int b
+ ) :
+ BaseClass(a,
+ b,
+ c),
+ mMember(b),
+{
+}
+
+Constructor::Constructor(int a,
+ int b ) :
+ BaseClass(a)
+{
+}
+
+Constructor::Constructor(int a,
+ int b ) /*x*/ : /*x*/ BaseClass(a),
+ member(b)
+{
+}
+
+class CAbc :
+ public BaseClass1,
+ protected BaseClass2
+{
+ int Test() { return FALSE; }
+ int Test1() { return TRUE; }
+
+ CAbc(int a, int b ) :
+ BaseClass(a)
+ {
+ switch(xxx)
+ {
+ case abc:
+ asdf();
+ break;
+
+ case 999:
+ baer();
+ break;
+ }
+ }
+
+public: // <-- this was incoreectly indented before!!
+ void testfall();
+protected:
+ void testfall();
+};
+
+class CAbc : public BaseClass1,
+ protected BaseClass2
+{
+};
+
+static struct
+{
+ int a;
+ int b;
+} variable[COUNT] =
+{
+ {
+ 123,
+ 456
+ },
+ {
+ 123,
+ 456
+ }
+};
+
+static struct
+{
+ int a;
+ int b;
+} variable[COUNT] =
+{
+ { 123, 456 },
+ { 123, 456 }
+};
+
+void asdf() /* ind_maxparen may cause trouble here */
+{
+ if ((0
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1)) break;
+}
+
+/* end of AUTO */
+
+STARTTEST
+:set tw=0 wm=60 columns=80 noai fo=croq
+/serious/e
+a about life, the universe, and the rest
+ENDTEST
+
+{
+
+/* this is
+ * a real serious important big
+ * comment
+ */
+ /* insert " about life, the universe, and the rest" after "serious" */
+}
+
+STARTTEST
+:set nocin
+/comments
+joabout life/happens
+jothere/below
+oline/this
+Ohello
+ENDTEST
+
+{
+ /*
+ * Testing for comments, without 'cin' set
+ */
+
+/*
+* what happens here?
+*/
+
+ /*
+ the end of the comment, try inserting a line below */
+
+ /* how about
+ this one */
+}
+
+STARTTEST
+:set cin
+/vec2
+==
+ENDTEST
+
+{
+ var = this + that + vec[0] * vec[0]
+ + vec[1] * vec[1]
+ + vec2[2] * vec[2];
+}
+
+STARTTEST
+:set cin
+:set cino=}4
+/testing1
+k2==/testing2
+k2==
+ENDTEST
+
+{
+ asdf asdflkajds f;
+ if (tes & ting) {
+ asdf asdf asdf ;
+ asdfa sdf asdf;
+ }
+ testing1;
+ if (tes & ting)
+ {
+ asdf asdf asdf ;
+ asdfa sdf asdf;
+ }
+ testing2;
+}
+
+STARTTEST
+:set cin
+:set cino=(0,)20
+/main
+=][
+ENDTEST
+
+main ( int first_par, /*
+ * Comment for
+ * first par
+ */
+ int second_par /*
+ * Comment for
+ * second par
+ */
+ )
+{
+ func( first_par, /*
+ * Comment for
+ * first par
+ */
+ second_par /*
+ * Comment for
+ * second par
+ */
+ );
+
+}
+
+STARTTEST
+:set cin
+:set cino=
+]]=][
+ENDTEST
+
+{
+ do
+ {
+ if ()
+ {
+ if ()
+ asdf;
+ else
+ asdf;
+ }
+ } while ();
+ cmd; /* this should go under the } */
+}
+
+STARTTEST
+]]=][
+ENDTEST
+
+void f()
+{
+ if ( k() ) {
+ l();
+
+ } else { /* Start (two words) end */
+ m();
+ }
+
+ n();
+}
+
+STARTTEST
+:set cino={s,e-s
+]]=][
+ENDTEST
+
+void f()
+{
+ if ( k() )
+ {
+ l();
+ } else { /* Start (two words) end */
+ m();
+ }
+ n(); /* should be under the if () */
+}
+
+STARTTEST
+:set cino={s,fs
+]]=/ foo
+ENDTEST
+
+void bar(void)
+{
+ static array[2][2] =
+ {
+ { 1, 2 },
+ { 3, 4 },
+ }
+
+ while (a)
+ {
+ foo(&a);
+ }
+
+ {
+ int a;
+ {
+ a = a + 1;
+ }
+ }
+ b = a;
+ }
+
+void func(void)
+ {
+ a = 1;
+ {
+ b = 2;
+ }
+ c = 3;
+ d = 4;
+ }
+/* foo */
+
+STARTTEST
+:set cino=
+/while
+ohere
+ENDTEST
+
+a()
+{
+ do {
+ a = a +
+ a;
+ } while ( a ); /* add text under this line */
+ if ( a )
+ a;
+}
+
+STARTTEST
+:set cino= com=
+/comment
+olabel2: b(); label3 /* post */: /* pre */ label4: f(/*com*/); if (/*com*/) cmd();
+ENDTEST
+
+a()
+{
+label1:
+ /* hmm */
+ // comment
+}
+
+STARTTEST
+:set comments& comments^=s:/*,m:**,ex:*/
+/simple
+=5j
+ENDTEST
+
+/*
+ * A simple comment
+ */
+
+/*
+ ** A different comment
+ */
+
+STARTTEST
+:set cino=c0
+:set comments& comments-=s1:/* comments^=s0:/*
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+
+ /*********
+ A comment.
+*********/
+}
+
+STARTTEST
+:set cino=c0,C1
+:set comments& comments-=s1:/* comments^=s0:/*
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+
+ /*********
+ A comment.
+*********/
+}
+
+STARTTEST
+:set cino=
+]]=][
+ENDTEST
+
+void f()
+{
+ c = c1 &&
+ (
+ c2 ||
+ c3
+ ) && c4;
+}
+
+STARTTEST
+:set cino=(s
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ c = c1 &&
+ (
+ c2 ||
+ c3
+ ) && c4;
+}
+
+STARTTEST
+:set cino=(s,U1
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ c = c1 &&
+ (
+ c2 ||
+ c3
+ ) && c4;
+}
+
+STARTTEST
+:set cino=(0
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ if ( c1
+ && ( c2
+ || c3))
+ foo;
+}
+
+STARTTEST
+:set cino=(0,w1
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ if ( c1
+ && ( c2
+ || c3))
+ foo;
+}
+
+STARTTEST
+:set cino=(s
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ c = c1 && (
+ c2 ||
+ c3
+ ) && c4;
+ if (
+ c1 && c2
+ )
+ foo;
+}
+
+STARTTEST
+:set cino=(s,m1
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ c = c1 && (
+ c2 ||
+ c3
+ ) && c4;
+ if (
+ c1 && c2
+ )
+ foo;
+}
+
+STARTTEST
+:set cino=b1
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ switch (x)
+ {
+ case 1:
+ a = b;
+ break;
+ default:
+ a = 0;
+ break;
+ }
+}
+
+STARTTEST
+:set cino=(0,W5
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ invokeme(
+ argu,
+ ment);
+ invokeme(
+ argu,
+ ment
+ );
+ invokeme(argu,
+ ment
+ );
+}
+
+STARTTEST
+:set cino=/6
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ statement;
+ // comment 1
+ // comment 2
+}
+
+STARTTEST
+:set cino=
+2kdd]]/comment 1/+1
+==
+ENDTEST
+
+void f()
+{
+ statement;
+ // comment 1
+ // comment 2
+}
+
+STARTTEST
+:set cino=g0
+2kdd]]=][
+ENDTEST
+
+class CAbc
+{
+ int Test() { return FALSE; }
+
+public: // comment
+ void testfall();
+protected:
+ void testfall();
+};
+
+STARTTEST
+:set cino=(0,W2s
+2kdd]]=][
+ENDTEST
+
+{
+ averylongfunctionnamelongfunctionnameaverylongfunctionname()->asd(
+ asdasdf,
+ func(asdf,
+ asdfadsf),
+ asdfasdf
+ );
+
+ /* those are ugly, but consequent */
+
+ func()->asd(asdasdf,
+ averylongfunctionname(
+ abc,
+ dec)->averylongfunctionname(
+ asdfadsf,
+ asdfasdf,
+ asdfasdf,
+ ),
+ func(asdfadf,
+ asdfasdf
+ ),
+ asdasdf
+ );
+
+ averylongfunctionnameaverylongfunctionnameavery()->asd(fasdf(
+ abc,
+ dec)->asdfasdfasdf(
+ asdfadsf,
+ asdfasdf,
+ asdfasdf,
+ ),
+ func(asdfadf,
+ asdfasdf),
+ asdasdf
+ );
+}
+
+STARTTEST
+:g/^STARTTEST/.,/^ENDTEST/d
+:1;/start of AUTO/,$wq! test.out
+ENDTEST
diff --git a/src/testdir/test3.ok b/src/testdir/test3.ok
new file mode 100644
index 000000000..570f8f63d
--- /dev/null
+++ b/src/testdir/test3.ok
@@ -0,0 +1,1090 @@
+/* start of AUTO matically checked */
+{
+ if (test)
+ cmd1;
+ cmd2;
+}
+
+{
+ if (test)
+ cmd1;
+ else
+ cmd2;
+}
+
+{
+ if (test)
+ {
+ cmd1;
+ cmd2;
+ }
+}
+
+{
+ if (test)
+ {
+ cmd1;
+ else
+ }
+}
+
+{
+ while (this)
+ if (test)
+ cmd1;
+ cmd2;
+}
+
+{
+ while (this)
+ if (test)
+ cmd1;
+ else
+ cmd2;
+}
+
+{
+ if (test)
+ {
+ cmd;
+ }
+
+ if (test)
+ cmd;
+}
+
+{
+ if (test) {
+ cmd;
+ }
+
+ if (test) cmd;
+}
+
+{
+ cmd1;
+ for (blah)
+ while (this)
+ if (test)
+ cmd2;
+ cmd3;
+}
+
+{
+ cmd1;
+ for (blah)
+ while (this)
+ if (test)
+ cmd2;
+ cmd3;
+
+ if (test)
+ {
+ cmd1;
+ cmd2;
+ cmd3;
+ }
+}
+
+
+/* Test for 'cindent' do/while mixed with if/else: */
+
+{
+ do
+ if (asdf)
+ asdfasd;
+ while (cond);
+
+ do
+ if (asdf)
+ while (asdf)
+ asdf;
+ while (asdf);
+}
+
+/* Test for 'cindent' with two ) on a continuation line */
+{
+ if (asdfasdf;asldkfj asdlkfj as;ldkfj sal;d
+ aal;sdkjf ( ;asldfkja;sldfk
+ al;sdjfka ;slkdf ) sa;ldkjfsa dlk;)
+ line up here;
+}
+
+
+/* C++ tests: */
+
+// foo() these three lines should remain in column 0
+// {
+// }
+
+/* Test for continuation and unterminated lines: */
+{
+ i = 99 + 14325 +
+ 21345 +
+ 21345 +
+ 21345 + ( 21345 +
+ 21345) +
+ 2345 +
+ 1234;
+ c = 1;
+}
+
+/*
+ testje for indent with empty line
+
+ here */
+
+{
+ if (testing &&
+ not a joke ||
+ line up here)
+ hay;
+ if (testing &&
+ (not a joke || testing
+ )line up here)
+ hay;
+ if (testing &&
+ (not a joke || testing
+ line up here))
+ hay;
+}
+
+
+{
+ switch (c)
+ {
+ case xx:
+ do
+ if (asdf)
+ do
+ asdfasdf;
+ while (asdf);
+ else
+ asdfasdf;
+ while (cond);
+ case yy:
+ case xx:
+ case zz:
+ testing;
+ }
+}
+
+{
+ if (cond) {
+ foo;
+ }
+ else
+ {
+ bar;
+ }
+}
+
+{
+ if (alskdfj ;alsdkfjal;skdjf (;sadlkfsa ;dlkf j;alksdfj ;alskdjf
+ alsdkfj (asldk;fj
+ awith cino=(0 ;lf this one goes to below the paren with ==
+ ;laksjfd ;lsakdjf ;alskdf asd)
+ asdfasdf;)))
+ asdfasdf;
+}
+
+ int
+func(a, b)
+ int a;
+ int c;
+{
+ if (c1 && (c2 ||
+ c3))
+ foo;
+ if (c1 &&
+ (c2 || c3)
+ )
+}
+
+{
+ while (asd)
+ {
+ if (asdf)
+ if (test)
+ if (that)
+ {
+ if (asdf)
+ do
+ cdasd;
+ while (as
+ df);
+ }
+ else
+ if (asdf)
+ asdf;
+ else
+ asdf;
+ asdf;
+ }
+}
+
+{
+ s = "/*"; b = ';'
+ s = "/*"; b = ';';
+ a = b;
+}
+
+{
+ switch (a)
+ {
+ case a:
+ switch (t)
+ {
+ case 1:
+ cmd;
+ break;
+ case 2:
+ cmd;
+ break;
+ }
+ cmd;
+ break;
+ case b:
+ {
+ int i;
+ cmd;
+ }
+ break;
+ case c: {
+ int i;
+ cmd;
+ }
+ case d: if (cond &&
+ test) { /* this line doesn't work right */
+ int i;
+ cmd;
+ }
+ break;
+ }
+}
+
+{
+ if (!(vim_strchr(p_cpo, CPO_BUFOPTGLOB) != NULL && entering) &&
+ (bp_to->b_p_initialized ||
+ (!entering && vim_strchr(p_cpo, CPO_BUFOPT) != NULL)))
+ return;
+label :
+ asdf = asdf ?
+ asdf : asdf;
+ asdf = asdf ?
+ asdf: asdf;
+}
+
+/* Special Comments : This function has the added complexity (compared */
+/* : to addtolist) of having to check for a detail */
+/* : texture and add that to the list first. */
+
+char *(array[100]) = {
+ "testje",
+ "foo",
+ "bar",
+}
+
+enum soppie
+{
+ yes = 0,
+ no,
+ maybe
+};
+
+typedef enum soppie
+{
+ yes = 0,
+ no,
+ maybe
+};
+
+{
+ int a,
+ b;
+}
+
+{
+ struct Type
+ {
+ int i;
+ char *str;
+ } var[] =
+ {
+ 0, "zero",
+ 1, "one",
+ 2, "two",
+ 3, "three"
+ };
+
+ float matrix[3][3] =
+ {
+ {
+ 0,
+ 1,
+ 2
+ },
+ {
+ 3,
+ 4,
+ 5
+ },
+ {
+ 6,
+ 7,
+ 8
+ }
+ };
+}
+
+{
+ /* blah ( blah */
+ /* where does this go? */
+
+ /* blah ( blah */
+ cmd;
+
+ func(arg1,
+ /* comment */
+ arg2);
+ a;
+ {
+ b;
+ {
+ c; /* Hey, NOW it indents?! */
+ }
+ }
+
+ {
+ func(arg1,
+ arg2,
+ arg3);
+ /* Hey, what am I doing here? Is this coz of the ","? */
+ }
+}
+
+main ()
+{
+ if (cond)
+ {
+ a = b;
+ }
+ if (cond) {
+ a = c;
+ }
+ if (cond)
+ a = d;
+ return;
+}
+
+{
+ case 2: if (asdf &&
+ asdfasdf)
+ aasdf;
+ a = 9;
+ case 3: if (asdf)
+ aasdf;
+ a = 9;
+ case 4: x = 1;
+ y = 2;
+
+label: if (asdf)
+ here;
+
+label: if (asdf &&
+ asdfasdf)
+ {
+ }
+
+label: if (asdf &&
+ asdfasdf) {
+ there;
+ }
+
+label: if (asdf &&
+ asdfasdf)
+ there;
+}
+
+{
+ /*
+ hello with ":set comments= cino=c5"
+ */
+
+ /*
+ hello with ":set comments= cino="
+ */
+}
+
+
+{
+ if (a < b) {
+ a = a + 1;
+ } else
+ a = a + 2;
+
+ if (a)
+ do {
+ testing;
+ } while (asdfasdf);
+ a = b + 1;
+ asdfasdf
+}
+
+class bob
+{
+ int foo() {return 1;}
+ int bar;
+}
+
+main()
+{
+ while(1)
+ if (foo)
+ {
+ bar;
+ }
+ else {
+ asdf;
+ }
+ misplacedline;
+}
+
+{
+ if (clipboard.state == SELECT_DONE
+ && ((row == clipboard.start.lnum
+ && col >= clipboard.start.col)
+ || row > clipboard.start.lnum))
+}
+
+{
+ if (1) {i += 4;}
+ where_am_i;
+ return 0;
+}
+
+{
+ {
+ } // sdf(asdf
+ if (asdf)
+ asd;
+}
+
+{
+label1:
+label2:
+}
+
+{
+ int fooRet = foo(pBar1, false /*fKB*/,
+ true /*fPTB*/, 3 /*nT*/, false /*fDF*/);
+ f() {
+ for ( i = 0;
+ i < m;
+ /* c */ i++ ) {
+ a = b;
+ }
+ }
+}
+
+{
+ f1(/*comment*/);
+ f2();
+}
+
+{
+ do {
+ if (foo) {
+ } else
+ ;
+ } while (foo);
+ foo(); // was wrong
+}
+
+int x; // no extra indent because of the ;
+void func()
+{
+}
+
+char *tab[] = {"aaa",
+ "};", /* }; */ NULL}
+ int indented;
+{}
+
+char *a[] = {"aaa", "bbb",
+ "ccc", NULL};
+// here
+
+char *tab[] = {"aaa",
+ "xx", /* xx */}; /* asdf */
+int not_indented;
+
+{
+ do {
+ switch (bla)
+ {
+ case 1: if (foo)
+ bar;
+ }
+ } while (boo);
+ wrong;
+}
+
+int foo,
+ bar;
+int foo;
+
+#if defined(foo) \
+ && defined(bar)
+char * xx = "asdf\
+ foo\
+ bor";
+int x;
+
+char *foo = "asdf\
+ asdf\
+ asdf",
+ *bar;
+
+void f()
+{
+#if defined(foo) \
+ && defined(bar)
+ char *foo = "asdf\
+ asdf\
+ asdf",
+ *bar;
+ {
+ int i;
+ char *foo = "asdf\
+ asdf\
+ asdf",
+ *bar;
+ }
+#endif
+}
+#endif
+
+int y; // comment
+// comment
+
+// comment
+
+{
+ Constructor(int a,
+ int b ) : BaseClass(a)
+ {
+ }
+}
+
+void foo()
+{
+ char one,
+ two;
+ struct bla piet,
+ jan;
+ enum foo kees,
+ jannie;
+ static unsigned sdf,
+ krap;
+ unsigned int piet,
+ jan;
+ int
+ kees,
+ jan;
+}
+
+{
+ t(int f,
+ int d); // )
+ d();
+}
+
+Constructor::Constructor(int a,
+ int b
+ ) :
+ BaseClass(a,
+ b,
+ c),
+ mMember(b),
+{
+}
+
+Constructor::Constructor(int a,
+ int b ) :
+ BaseClass(a)
+{
+}
+
+Constructor::Constructor(int a,
+ int b ) /*x*/ : /*x*/ BaseClass(a),
+ member(b)
+{
+}
+
+class CAbc :
+ public BaseClass1,
+ protected BaseClass2
+{
+ int Test() { return FALSE; }
+ int Test1() { return TRUE; }
+
+ CAbc(int a, int b ) :
+ BaseClass(a)
+ {
+ switch(xxx)
+ {
+ case abc:
+ asdf();
+ break;
+
+ case 999:
+ baer();
+ break;
+ }
+ }
+
+ public: // <-- this was incoreectly indented before!!
+ void testfall();
+ protected:
+ void testfall();
+};
+
+class CAbc : public BaseClass1,
+ protected BaseClass2
+{
+};
+
+static struct
+{
+ int a;
+ int b;
+} variable[COUNT] =
+{
+ {
+ 123,
+ 456
+ },
+ {
+ 123,
+ 456
+ }
+};
+
+static struct
+{
+ int a;
+ int b;
+} variable[COUNT] =
+{
+ { 123, 456 },
+ { 123, 456 }
+};
+
+void asdf() /* ind_maxparen may cause trouble here */
+{
+ if ((0
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1)) break;
+}
+
+/* end of AUTO */
+
+
+{
+
+/* this is
+ * a real serious
+ * about life, the
+ * universe, and the
+ * rest important big
+ * comment
+ */
+ /* insert " about life, the universe, and the rest" after "serious" */
+}
+
+
+{
+ /*
+ * Testing for comments, without 'cin' set
+ */
+about life
+
+/*
+* what happens here?
+*/
+there
+
+ /*
+ the end of the comment, try inserting a line below */
+line
+
+ /* how about
+hello
+ this one */
+}
+
+
+{
+ var = this + that + vec[0] * vec[0]
+ + vec[1] * vec[1]
+ + vec2[2] * vec[2];
+}
+
+
+{
+ asdf asdflkajds f;
+ if (tes & ting) {
+ asdf asdf asdf ;
+ asdfa sdf asdf;
+ }
+ testing1;
+ if (tes & ting)
+ {
+ asdf asdf asdf ;
+ asdfa sdf asdf;
+ }
+ testing2;
+}
+
+
+main ( int first_par, /*
+ * Comment for
+ * first par
+ */
+ int second_par /*
+ * Comment for
+ * second par
+ */
+ )
+{
+ func( first_par, /*
+ * Comment for
+ * first par
+ */
+ second_par /*
+ * Comment for
+ * second par
+ */
+ );
+
+}
+
+
+{
+ do
+ {
+ if ()
+ {
+ if ()
+ asdf;
+ else
+ asdf;
+ }
+ } while ();
+ cmd; /* this should go under the } */
+}
+
+
+void f()
+{
+ if ( k() ) {
+ l();
+
+ } else { /* Start (two words) end */
+ m();
+ }
+
+ n();
+}
+
+
+void f()
+ {
+ if ( k() )
+ {
+ l();
+ } else { /* Start (two words) end */
+ m();
+ }
+ n(); /* should be under the if () */
+}
+
+
+void bar(void)
+ {
+ static array[2][2] =
+ {
+ { 1, 2 },
+ { 3, 4 },
+ }
+
+ while (a)
+ {
+ foo(&a);
+ }
+
+ {
+ int a;
+ {
+ a = a + 1;
+ }
+ }
+ b = a;
+ }
+
+void func(void)
+ {
+ a = 1;
+ {
+ b = 2;
+ }
+ c = 3;
+ d = 4;
+ }
+/* foo */
+
+
+a()
+{
+ do {
+ a = a +
+ a;
+ } while ( a ); /* add text under this line */
+ here
+ if ( a )
+ a;
+}
+
+
+a()
+{
+label1:
+ /* hmm */
+ // comment
+label2: b();
+label3 /* post */:
+/* pre */ label4:
+ f(/*com*/);
+ if (/*com*/)
+ cmd();
+}
+
+
+/*
+ * A simple comment
+ */
+
+/*
+** A different comment
+*/
+
+
+void f()
+{
+
+ /*********
+ A comment.
+ *********/
+}
+
+
+void f()
+{
+
+ /*********
+ A comment.
+ *********/
+}
+
+
+void f()
+{
+ c = c1 &&
+ (
+ c2 ||
+ c3
+ ) && c4;
+}
+
+
+void f()
+{
+ c = c1 &&
+ (
+ c2 ||
+ c3
+ ) && c4;
+}
+
+
+void f()
+{
+ c = c1 &&
+ (
+ c2 ||
+ c3
+ ) && c4;
+}
+
+
+void f()
+{
+ if ( c1
+ && ( c2
+ || c3))
+ foo;
+}
+
+
+void f()
+{
+ if ( c1
+ && ( c2
+ || c3))
+ foo;
+}
+
+
+void f()
+{
+ c = c1 && (
+ c2 ||
+ c3
+ ) && c4;
+ if (
+ c1 && c2
+ )
+ foo;
+}
+
+
+void f()
+{
+ c = c1 && (
+ c2 ||
+ c3
+ ) && c4;
+ if (
+ c1 && c2
+ )
+ foo;
+}
+
+
+void f()
+{
+ switch (x)
+ {
+ case 1:
+ a = b;
+ break;
+ default:
+ a = 0;
+ break;
+ }
+}
+
+
+void f()
+{
+ invokeme(
+ argu,
+ ment);
+ invokeme(
+ argu,
+ ment
+ );
+ invokeme(argu,
+ ment
+ );
+}
+
+
+void f()
+{
+ statement;
+ // comment 1
+ // comment 2
+}
+
+
+void f()
+{
+ statement;
+ // comment 1
+ // comment 2
+}
+
+
+class CAbc
+{
+ int Test() { return FALSE; }
+
+public: // comment
+ void testfall();
+protected:
+ void testfall();
+};
+
+
+{
+ averylongfunctionnamelongfunctionnameaverylongfunctionname()->asd(
+ asdasdf,
+ func(asdf,
+ asdfadsf),
+ asdfasdf
+ );
+
+ /* those are ugly, but consequent */
+
+ func()->asd(asdasdf,
+ averylongfunctionname(
+ abc,
+ dec)->averylongfunctionname(
+ asdfadsf,
+ asdfasdf,
+ asdfasdf,
+ ),
+ func(asdfadf,
+ asdfasdf
+ ),
+ asdasdf
+ );
+
+ averylongfunctionnameaverylongfunctionnameavery()->asd(fasdf(
+ abc,
+ dec)->asdfasdfasdf(
+ asdfadsf,
+ asdfasdf,
+ asdfasdf,
+ ),
+ func(asdfadf,
+ asdfasdf),
+ asdasdf
+ );
+}
+
diff --git a/src/testdir/test30.in b/src/testdir/test30.in
new file mode 100644
index 000000000..4e92741c8
--- /dev/null
+++ b/src/testdir/test30.in
@@ -0,0 +1,183 @@
+Test for a lot of variations of the 'fileformats' option
+
+STARTTEST
+:so small.vim
+:" first write three test files, one in each format
+:set fileformat=unix
+:set fileformats=
+:/^1/w! XX1
+:/^2/w! XX2
+:/^3/w! XX3
+:/^4/w! XX4
+:/^5/w! XX5
+:/^6/w! XX6
+:/^7/w! XX7
+:/^8/w! XX8
+:/^9/w! XX9
+:/^10/w! XX10
+:/^unix/;/eof/-1w! XXUnix
+:/^dos/;/eof/-1w! XXDos
+:set bin noeol
+:$w! XXMac
+:set nobin eol
+:bwipe XXUnix XXDos XXMac
+:" create mixed format files
+:!cat XXUnix XXDos >XXUxDs
+:!cat XXUnix XXMac >XXUxMac
+:!cat XXDos XXMac >XXDosMac
+:!cat XXUnix XXDos XXMac >XXUxDsMc
+:"
+:" try reading and writing with 'fileformats' empty
+:set fileformat=unix
+:e! XXUnix
+:w! test.out
+:e! XXDos
+:w! XXtt
+:!cat XXtt >>test.out
+:e! XXMac
+:w! XXtt
+:!cat XXtt >>test.out
+:!cat XX1 >>test.out
+:bwipe XXUnix XXDos XXMac
+:set fileformat=dos
+:e! XXUnix
+:w! XXtt
+:!cat XXtt >>test.out
+:e! XXDos
+:w! XXtt
+:!cat XXtt >>test.out
+:e! XXMac
+:w! XXtt
+:!cat XXtt >>test.out
+:!cat XX2 >>test.out
+:bwipe XXUnix XXDos XXMac
+:set fileformat=mac
+:e! XXUnix
+:w! XXtt
+:!cat XXtt >>test.out
+:e! XXDos
+:w! XXtt
+:!cat XXtt >>test.out
+:e! XXMac
+:w! XXtt
+:!cat XXtt >>test.out
+:!cat XX3 >>test.out
+:bwipe XXUnix XXDos XXMac
+:"
+:" try reading and writing with 'fileformats' set to one format
+:set fileformats=unix
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:set fileformats=dos
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:set fileformats=mac
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:!cat XX4 >>test.out
+:"
+:" try reading and writing with 'fileformats' set to two formats
+:set fileformats=unix,dos
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:e! XXUxMac
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxMac
+:e! XXDosMac
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXDosMac
+:!cat XX5 >>test.out
+:set fileformats=unix,mac
+:e! XXUxDs
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDs
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:e! XXDosMac
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXDosMac
+:!cat XX6 >>test.out
+:set fileformats=dos,mac
+:e! XXUxDs
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDs
+:e! XXUxMac
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxMac
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:!cat XX7 >>test.out
+:"
+:" try reading and writing with 'fileformats' set to three formats
+:set fileformats=unix,dos,mac
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:!cat XX8 >>test.out
+:set fileformats=mac,dos,unix
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:!cat XX9 >>test.out
+:" try with 'binary' set
+:set fileformats=mac,unix,dos
+:set binary
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:set fileformats=mac
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:set fileformats=dos
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:!cat XX10 >>test.out
+:" add a newline at the end
+:!cat XXUnix >>test.out
+:qa!
+ENDTEST
+
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+
+unix
+unix
+eof
+
+dos
+dos
+eof
+
+mac mac
diff --git a/src/testdir/test30.ok b/src/testdir/test30.ok
new file mode 100644
index 000000000..c294483bd
--- /dev/null
+++ b/src/testdir/test30.ok
@@ -0,0 +1,96 @@
+unix
+unix
+dos
+dos
+mac mac
+1
+unix
+unix
+dos
+dos
+mac mac
+2
+unix
+unix
+ dos
+dos
+ mac mac 3
+unix
+unix
+dos
+dos
+mac mac
+unix
+unix
+dos
+dos
+mac mac
+unix
+unix
+dos
+dos
+mac mac 4
+unix
+unix
+dos
+dos
+mac mac
+unix
+unix
+mac mac
+dos
+dos
+mac mac
+5
+unix
+unix
+dos
+dos
+unix
+unix
+dos
+dos
+mac mac
+dos
+dos
+mac mac 6
+unix
+unix
+dos
+dos
+unix
+unix
+mac mac
+unix
+unix
+dos
+dos
+mac mac
+7
+unix
+unix
+dos
+dos
+mac mac
+8
+unix
+unix
+dos
+dos
+mac mac
+9
+unix
+unix
+dos
+dos
+mac mac unix
+unix
+dos
+dos
+mac mac unix
+unix
+dos
+dos
+mac mac 10
+unix
+unix
diff --git a/src/testdir/test31.in b/src/testdir/test31.in
new file mode 100644
index 000000000..cd4d08e81
--- /dev/null
+++ b/src/testdir/test31.in
@@ -0,0 +1,68 @@
+Test for commands that close windows and/or buffers:
+:quit
+:close
+:hide
+:only
+:sall
+:all
+:ball
+:buf
+:edit
+
+STARTTEST
+:so tiny.vim
+GA 1:$w! Xtest1
+$r2:$w! Xtest2
+$r3:$w! Xtest3
+:n! Xtest1 Xtest2
+A 1:set hidden
+:" test for working :n when hidden set; write "testtext 2"
+:n
+:w! test.out
+:" test for failing :rew when hidden not set; write "testtext 2 2"
+:set nohidden
+A 2:rew
+:w >>test.out
+:" test for working :rew when hidden set; write "testtext 1 1"
+:set hidden
+:rew
+:w >>test.out
+:" test for :all keeping a buffer when it's modified; write "testtext 1 1 1"
+:set nohidden
+A 1:sp
+:n Xtest2 Xtest3
+:all
+:w >>test.out
+:" test abandoning changed buffer, should be unloaded even when 'hidden' set
+:" write "testtext 2 2" twice
+:set hidden
+A 1:q!
+:w >>test.out
+:unhide
+:w >>test.out
+:" test ":hide" hides anyway when 'hidden' not set; write "testtext 3"
+:set nohidden
+A 2:hide
+:w >>test.out
+:" test ":edit" failing in modified buffer when 'hidden' not set
+:" write "testtext 3 3"
+A 3:e Xtest1
+:w >>test.out
+:" test ":edit" working in modified buffer when 'hidden' set; write "testtext 1"
+:set hidden
+:e Xtest1
+:w >>test.out
+:" test ":close" not hiding when 'hidden' not set in modified buffer;
+:" write "testtext 3 3 3"
+:sp Xtest3
+:set nohidden
+A 3:close
+:w >>test.out
+:" test ":close!" does hide when 'hidden' not set in modified buffer;
+:" write "testtext 1"
+A 3:close!
+:w >>test.out
+:qa!
+ENDTEST
+
+testtext
diff --git a/src/testdir/test31.ok b/src/testdir/test31.ok
new file mode 100644
index 000000000..3311ad5df
--- /dev/null
+++ b/src/testdir/test31.ok
@@ -0,0 +1,11 @@
+testtext 2
+testtext 2 2
+testtext 1 1
+testtext 1 1 1
+testtext 2 2
+testtext 2 2
+testtext 3
+testtext 3 3
+testtext 1
+testtext 3 3 3
+testtext 1
diff --git a/src/testdir/test32.in b/src/testdir/test32.in
new file mode 100644
index 000000000..0d5405184
--- /dev/null
+++ b/src/testdir/test32.in
@@ -0,0 +1,56 @@
+Test for insert expansion
+
+:se cpt=.,w
+* add-expands (word from next line) from other window
+* add-expands (current buffer first)
+* Local expansion, ends in an empty line (unless it becomes a global expansion)
+* starts Local and switches to global add-expansion
+:se cpt=.,w,i
+* i-add-expands and switches to local
+* add-expands lines (it would end in an empty line if it didn't ignored it self)
+:se cpt=kXtestfile
+* checks k-expansion, and file expansion (use Xtest11 instead of test11,
+* because TEST11.OUT may match first on DOS)
+:se cpt=w
+* checks make_cyclic in other window
+:se cpt=u nohid
+* checks unloaded buffer expansion
+* checks adding mode abortion
+:se cpt=t,d
+* tag expansion, define add-expansion interrupted
+* t-expansion
+
+STARTTEST
+:so small.vim
+:se nocp viminfo+=nviminfo cpt=.,w ff=unix | $-2,$w!Xtestfile | set ff&
+nO#include "Xtestfile"
+ru
+O
+
+
+:se cpt=.,w,i
+kOM
+  
+:se cpt=kXtestfile
+:w Xtest11.one
+:w Xtest11.two
+OIXA
+:se cpt=w
+OST
+:se cpt=u nohid
+oOEN
+unl
+:se cpt=t,d def=^\\k* tags=Xtestfile notagbsearch
+O
+a
+:wq! test.out
+ENDTEST
+
+start of testfile
+run1
+run2
+end of testfile
+
+test11 36Gepeto /Tag/
+asd test11file 36G
+Makefile to run
diff --git a/src/testdir/test32.ok b/src/testdir/test32.ok
new file mode 100644
index 000000000..afc4463fa
--- /dev/null
+++ b/src/testdir/test32.ok
@@ -0,0 +1,15 @@
+#include "Xtestfile"
+run1 run3
+run3 run3
+
+Makefile to run3
+Makefile to run3
+Makefile to run3
+Xtest11.two
+STARTTEST
+ENDTEST
+unless
+test11file 36Gepeto /Tag/ asd
+asd
+run1 run2
+
diff --git a/src/testdir/test33.in b/src/testdir/test33.in
new file mode 100644
index 000000000..564476040
--- /dev/null
+++ b/src/testdir/test33.in
@@ -0,0 +1,34 @@
+Test for 'lisp'
+If the lisp feature is not enabled, this will fail!
+
+STARTTEST
+:so small.vim
+:set lisp
+/^(defun
+=G:/^(defun/,$w! test.out
+:q!
+ENDTEST
+
+(defun html-file (base)
+(format nil "~(~A~).html" base))
+
+(defmacro page (name title &rest body)
+(let ((ti (gensym)))
+`(with-open-file (*standard-output*
+(html-file ,name)
+:direction :output
+:if-exists :supersede)
+(let ((,ti ,title))
+(as title ,ti)
+(with center
+(as h2 (string-upcase ,ti)))
+(brs 3)
+,@body))))
+
+;;; Utilities for generating links
+
+(defmacro with-link (dest &rest body)
+`(progn
+(format t "<a href=\"~A\">" (html-file ,dest))
+,@body
+(princ "</a>")))
diff --git a/src/testdir/test33.ok b/src/testdir/test33.ok
new file mode 100644
index 000000000..cd1d87a14
--- /dev/null
+++ b/src/testdir/test33.ok
@@ -0,0 +1,23 @@
+(defun html-file (base)
+ (format nil "~(~A~).html" base))
+
+(defmacro page (name title &rest body)
+ (let ((ti (gensym)))
+ `(with-open-file (*standard-output*
+ (html-file ,name)
+ :direction :output
+ :if-exists :supersede)
+ (let ((,ti ,title))
+ (as title ,ti)
+ (with center
+ (as h2 (string-upcase ,ti)))
+ (brs 3)
+ ,@body))))
+
+;;; Utilities for generating links
+
+(defmacro with-link (dest &rest body)
+ `(progn
+ (format t "<a href=\"~A\">" (html-file ,dest))
+ ,@body
+ (princ "</a>")))
diff --git a/src/testdir/test34.in b/src/testdir/test34.in
new file mode 100644
index 000000000..676070075
--- /dev/null
+++ b/src/testdir/test34.in
@@ -0,0 +1,31 @@
+Test for user functions
+
+STARTTEST
+:so small.vim
+:function Table(title, ...)
+: let ret = a:title
+: let idx = 1
+: while idx <= a:0
+: exe "let ret = ret . a:" . idx
+: let idx = idx + 1
+: endwhile
+: return ret
+:endfunction
+:function Compute(n1, n2, divname)
+: if a:n2 == 0
+: return "fail"
+: endif
+: exe "let g:" . a:divname . " = ". a:n1 / a:n2
+: return "ok"
+:endfunction
+:let retval = "nop"
+/^here
+C=Table("xxx", 4, "asdf")
+ =Compute(45, 0, "retval")
+ =retval
+ =Compute(45, 5, "retval")
+ =retval
+:.wq! test.out
+ENDTEST
+
+here
diff --git a/src/testdir/test34.ok b/src/testdir/test34.ok
new file mode 100644
index 000000000..6dab52f1d
--- /dev/null
+++ b/src/testdir/test34.ok
@@ -0,0 +1 @@
+xxx4asdf fail nop ok 9
diff --git a/src/testdir/test35.in b/src/testdir/test35.in
new file mode 100644
index 000000000..ba97911a1
--- /dev/null
+++ b/src/testdir/test35.in
@@ -0,0 +1,21 @@
+Test Ctrl-A and Ctrl-X, which increment and decrement decimal, hexadecimal,
+and octal numbers.
+
+STARTTEST
+/^start-here
+:set nrformats=octal,hex
+j102ll64128$
+:set nrformats=octal
+0102l2w65129blx6lD
+:set nrformats=hex
+0101l257Txldt   
+:set nrformats=
+0200l100w78k
+:$-3,$wq! test.out
+ENDTEST
+
+start-here
+100 0x100 077 0
+100 0x100 077
+100 0x100 077 0xfF 0xFf
+100 0x100 077
diff --git a/src/testdir/test35.ok b/src/testdir/test35.ok
new file mode 100644
index 000000000..093ad958a
--- /dev/null
+++ b/src/testdir/test35.ok
@@ -0,0 +1,4 @@
+0 0x0ff 0000 -1
+0 1x100 0777777
+-1 0x0 078 0xFE 0xfe
+-100 -100x100 000
diff --git a/src/testdir/test36.in b/src/testdir/test36.in
new file mode 100644
index 000000000..4c3b6b42f
--- /dev/null
+++ b/src/testdir/test36.in
@@ -0,0 +1,40 @@
+Test character classes in regexp
+
+STARTTEST
+/^start-here
+j:s/\d//g
+j:s/\D//g
+j:s/\o//g
+j:s/\O//g
+j:s/\x//g
+j:s/\X//g
+j:s/\w//g
+j:s/\W//g
+j:s/\h//g
+j:s/\H//g
+j:s/\a//g
+j:s/\A//g
+j:s/\l//g
+j:s/\L//g
+j:s/\u//g
+j:s/\U//g
+:/^start-here/+1,$wq! test.out
+ENDTEST
+
+start-here
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
diff --git a/src/testdir/test36.ok b/src/testdir/test36.ok
new file mode 100644
index 000000000..5f70fc205
--- /dev/null
+++ b/src/testdir/test36.ok
@@ -0,0 +1,16 @@
+ !"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+0123456789
+ !"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+01234567
+ !"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~€‚›¦±¼ÇÓé
+0123456789ABCDEFabcdef
+ !"#$%&'()#+'-./:;<=>?@[\]^`{|}~€‚›¦±¼ÇÓé
+0123456789ABCDEFGHIXYZ_abcdefghiwxyz
+ !"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~€‚›¦±¼ÇÓé
+ABCDEFGHIXYZ_abcdefghiwxyz
+ !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~€‚›¦±¼ÇÓé
+ABCDEFGHIXYZabcdefghiwxyz
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~€‚›¦±¼ÇÓé
+abcdefghiwxyz
+ !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~€‚›¦±¼ÇÓé
+ABCDEFGHIXYZ
diff --git a/src/testdir/test37.in b/src/testdir/test37.in
new file mode 100644
index 000000000..daaea32d0
--- /dev/null
+++ b/src/testdir/test37.in
@@ -0,0 +1,116 @@
+Test for 'scrollbind'. <eralston@computer.org>
+STARTTEST
+:so small.vim
+:set noscrollbind
+:set scrollopt=ver,jump
+:set scrolloff=2
+:set nowrap
+:set noequalalways
+:set splitbelow
+:" TEST using two windows open to one buffer, one extra empty window
+:split
+:new
+t:
+:resize 8
+/^start of window 1$/
+zt:
+:set scrollbind
+j:
+:resize 7
+/^start of window 2$/
+zt:
+:set scrollbind
+:" -- start of tests --
+:" TEST scrolling down
+L5jHyybpr0tHyybpr1tL6jHyybpr2kHyybpr3:
+:" TEST scrolling up
+tH4kjHtHyybpr4kHyybpr5k3ktHjHyybpr6tHyybpr7:
+:" TEST horizontal scrolling
+:set scrollopt+=hor
+gg"zyyG"zpGt015zly$bp"zpGky$bp"zpG:
+k10jH7zhg0y$bp"zpGtHg0y$bp"zpG:
+:set scrollopt-=hor
+:" ****** tests using two different buffers *****
+tj:
+:close
+t:
+:set noscrollbind
+:/^start of window 2$/,/^end of window 2$/y
+:new
+tj4"zpGp:
+t/^start of window 1$/
+zt:
+:set scrollbind
+j:
+/^start of window 2$/
+zt:
+:set scrollbind
+:" -- start of tests --
+:" TEST scrolling down
+L5jHyybpr0tHyybpr1tL6jHyybpr2kHyybpr3:
+:" TEST scrolling up
+tH4kjHtHyybpr4kHyybpr5k3ktHjHyybpr6tHyybpr7:
+:" TEST horizontal scrolling
+:set scrollopt+=hor
+gg"zyyG"zpGt015zly$bp"zpGky$bp"zpG:
+k10jH7zhg0y$bp"zpGtHg0y$bp"zpG:
+:set scrollopt-=hor
+:" TEST syncbind
+t:set noscb
+ggLj:set noscb
+ggL:set scb
+t:set scb
+GjG:syncbind
+HktHjHyybptyybp:
+t:set noscb
+ggLj:set noscb
+ggL:set scb
+t:set scb
+tGjGt:syncbind
+HkjHtHyybptjyybp:
+tH3kjHtHyybptjyybp:
+:" ***** done with tests *****
+:w! test.out " Write contents of this file
+:qa!
+ENDTEST
+
+
+start of window 1
+. line 01 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 01
+. line 02 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02
+. line 03 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 03
+. line 04 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 04
+. line 05 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 05
+. line 06 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 06
+. line 07 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 07
+. line 08 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 08
+. line 09 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 09
+. line 10 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 10
+. line 11 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 11
+. line 12 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 12
+. line 13 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 13
+. line 14 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 14
+. line 15 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 15
+end of window 1
+
+
+start of window 2
+. line 01 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 01
+. line 02 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 02
+. line 03 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 03
+. line 04 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 04
+. line 05 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 05
+. line 06 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 06
+. line 07 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 07
+. line 08 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 08
+. line 09 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 09
+. line 10 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 10
+. line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11
+. line 12 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 12
+. line 13 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 13
+. line 14 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 14
+. line 15 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 15
+. line 16 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 16
+end of window 2
+
+end of test37.in (please don't delete this line)
diff --git a/src/testdir/test37.ok b/src/testdir/test37.ok
new file mode 100644
index 000000000..a9092a402
--- /dev/null
+++ b/src/testdir/test37.ok
@@ -0,0 +1,33 @@
+
+0 line 05 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 05
+1 line 05 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 05
+2 line 11 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 11
+3 line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11
+4 line 06 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 06
+5 line 06 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 06
+6 line 02 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 02
+7 line 02 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02
+56789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02
+UTSRQPONMLKJIHGREDCBA9876543210 02
+. line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11
+. line 11 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 11
+
+0 line 05 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 05
+1 line 05 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 05
+2 line 11 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 11
+3 line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11
+4 line 06 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 06
+5 line 06 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 06
+6 line 02 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 02
+7 line 02 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02
+56789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02
+UTSRQPONMLKJIHGREDCBA9876543210 02
+. line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11
+. line 11 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 11
+
+. line 16 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 16
+:set scrollbind
+zt:
+. line 15 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 15
+:set scrollbind
+. line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11
diff --git a/src/testdir/test38.in b/src/testdir/test38.in
new file mode 100644
index 000000000..885bd0967
--- /dev/null
+++ b/src/testdir/test38.in
@@ -0,0 +1,33 @@
+
+Test Virtual replace mode.
+
+STARTTEST
+:so small.vim
+ggdGa
+abcdefghi
+jk lmn
+ opq rst
+uvwxyz
+gg:set ai
+:set bs=2
+gR0 1
+A
+BCDEFGHIJ
+ KL
+MNO
+PQRG:ka
+o0
+abcdefghi
+jk lmn
+ opq rst
+uvwxyz
+'ajgR0 1
+A
+BCDEFGHIJ
+ KL
+MNO
+PQR:$
+iab cdefghi jkl0gRAB......CDEFGHI.Jo:
+iabcdefghijklmnopqrst0gRAB IJKLMNO QR:wq! test.out
+ENDTEST
+
diff --git a/src/testdir/test38.ok b/src/testdir/test38.ok
new file mode 100644
index 000000000..e10209667
--- /dev/null
+++ b/src/testdir/test38.ok
@@ -0,0 +1,13 @@
+ 1
+ A
+ BCDEFGHIJ
+ KL
+ MNO
+ PQR
+ 1
+abcdefghi
+jk lmn
+ opq rst
+uvwxyz
+AB......CDEFGHI.Jkl
+AB IJKLMNO QRst
diff --git a/src/testdir/test39.in b/src/testdir/test39.in
new file mode 100644
index 000000000..d7f294b3c
--- /dev/null
+++ b/src/testdir/test39.in
@@ -0,0 +1,24 @@
+
+Test Visual block mode commands
+
+STARTTEST
+:so small.vim
+/^abcde
+:" Test shift-right of a block
+jlllljj>wlljlll>
+:" Test shift-left of a block
+G$hhhhkk<
+:" Test block-insert
+GklkkkIxyz
+:" Test block-replace
+Gllllkkklllrq
+:" Test block-change
+G$khhhhhkkcmno
+:$-4,$wq! test.out
+ENDTEST
+
+abcdefghijklm
+abcdefghijklm
+abcdefghijklm
+abcdefghijklm
+abcdefghijklm
diff --git a/src/testdir/test39.ok b/src/testdir/test39.ok
new file mode 100644
index 000000000..6fa2867eb
--- /dev/null
+++ b/src/testdir/test39.ok
@@ -0,0 +1,5 @@
+axyzbcdefghijklm
+axyzqqqq mno ghijklm
+axyzqqqqef mno ghijklm
+axyzqqqqefgmnoklm
+abcdqqqqijklm
diff --git a/src/testdir/test4.in b/src/testdir/test4.in
new file mode 100644
index 000000000..4aa2fe5a8
--- /dev/null
+++ b/src/testdir/test4.in
@@ -0,0 +1,31 @@
+Test for autocommand that changes current buffer on BufEnter event.
+Check if modelines are interpreted for the correct buffer.
+
+STARTTEST
+:so small.vim
+:set nocompatible viminfo+=nviminfo
+:au BufEnter Xxx brew
+/start of
+:.,/end of/w! Xxx " write test file Xxx
+:set ai modeline modelines=3
+:sp Xxx " split to Xxx, autocmd will do :brew
+G?this is a
+othis should be auto-indented
+: " Append text with autoindent to this file
+:au! BufEnter Xxx
+:buf Xxx " go to Xxx, no autocmd anymore
+G?this is a
+othis should be in column 1:wq " append text without autoindent to Xxx
+G:r Xxx " include Xxx in the current file
+:?startstart?,$w! test.out
+:qa!
+ENDTEST
+
+startstart
+start of test file Xxx
+vim: set noai :
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+end of test file Xxx
diff --git a/src/testdir/test4.ok b/src/testdir/test4.ok
new file mode 100644
index 000000000..dffecda4d
--- /dev/null
+++ b/src/testdir/test4.ok
@@ -0,0 +1,17 @@
+startstart
+start of test file Xxx
+vim: set noai :
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+ this should be auto-indented
+end of test file Xxx
+start of test file Xxx
+vim: set noai :
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+this should be in column 1
+end of test file Xxx
diff --git a/src/testdir/test40.in b/src/testdir/test40.in
new file mode 100644
index 000000000..f6fb61245
--- /dev/null
+++ b/src/testdir/test40.in
@@ -0,0 +1,63 @@
+Test for "*Cmd" autocommands
+
+STARTTEST
+:so small.vim
+:/^start/,$w! Xxx " write lines below to Xxx
+:au BufReadCmd testA 0r Xxx|$del
+:e testA " will read text of Xxd instead
+:au BufWriteCmd testA call append(line("$"), "write")
+:w " will append a line to the file
+:r testA " should not read anything
+: " now we have:
+: " 1 start of Xxx
+: " 2 test40
+: " 3 end of Xxx
+: " 4 write
+:au FileReadCmd testB '[r Xxx
+:2r testB " will read Xxx below line 2 instead
+: " 1 start of Xxx
+: " 2 test40
+: " 3 start of Xxx
+: " 4 test40
+: " 5 end of Xxx
+: " 6 end of Xxx
+: " 7 write
+:au FileWriteCmd testC '[,']copy $
+4GA1
+:4,5w testC " will copy lines 4 and 5 to the end
+:r testC " should not read anything
+: " 1 start of Xxx
+: " 2 test40
+: " 3 start of Xxx
+: " 4 test401
+: " 5 end of Xxx
+: " 6 end of Xxx
+: " 7 write
+: " 8 test401
+: " 9 end of Xxx
+:au FILEAppendCmd testD '[,']w! test.out
+:w >>testD " will write all lines to test.out
+:$r testD " should not read anything
+:$w >>test.out " append "end of Xxx" to test.out
+:au BufReadCmd testE 0r test.out|$del
+:sp testE " split window with test.out
+5Goasdf:"
+:au BufWriteCmd testE w! test.out
+:wall " will write other window to test.out
+: " 1 start of Xxx
+: " 2 test40
+: " 3 start of Xxx
+: " 4 test401
+: " 5 end of Xxx
+: " 6 asdf
+: " 7 end of Xxx
+: " 8 write
+: " 9 test401
+: " 10 end of Xxx
+: " 11 end of Xxx
+:qa!
+ENDTEST
+
+start of Xxx
+ test40
+end of Xxx
diff --git a/src/testdir/test40.ok b/src/testdir/test40.ok
new file mode 100644
index 000000000..b6501394f
--- /dev/null
+++ b/src/testdir/test40.ok
@@ -0,0 +1,11 @@
+start of Xxx
+ test40
+start of Xxx
+ test401
+end of Xxx
+asdf
+end of Xxx
+write
+ test401
+end of Xxx
+end of Xxx
diff --git a/src/testdir/test41.in b/src/testdir/test41.in
new file mode 100644
index 000000000..2d294cae0
--- /dev/null
+++ b/src/testdir/test41.in
@@ -0,0 +1,24 @@
+Test for writing and reading a file of over 100 Kbyte
+
+1 line: "This is the start"
+3001 lines: "This is the leader"
+1 line: "This is the middle"
+3001 lines: "This is the trailer"
+1 line: "This is the end"
+
+STARTTEST
+:%d
+aThis is the start
+This is the leader
+This is the middle
+This is the trailer
+This is the endkY3000p2GY3000p
+:w! Xtest
+:%d
+:e! Xtest
+:.w! test.out
+3003G:.w >>test.out
+6005G:.w >>test.out
+:qa!
+ENDTEST
+
diff --git a/src/testdir/test41.ok b/src/testdir/test41.ok
new file mode 100644
index 000000000..988e5f24b
--- /dev/null
+++ b/src/testdir/test41.ok
@@ -0,0 +1,3 @@
+This is the start
+This is the middle
+This is the end
diff --git a/src/testdir/test42.in b/src/testdir/test42.in
new file mode 100644
index 000000000..c35569a76
--- /dev/null
+++ b/src/testdir/test42.in
Binary files differ
diff --git a/src/testdir/test42.ok b/src/testdir/test42.ok
new file mode 100644
index 000000000..16f41e46e
--- /dev/null
+++ b/src/testdir/test42.ok
Binary files differ
diff --git a/src/testdir/test43.in b/src/testdir/test43.in
new file mode 100644
index 000000000..26f0e0c9a
--- /dev/null
+++ b/src/testdir/test43.in
@@ -0,0 +1,27 @@
+Tests for regexp with various magic settings.
+
+STARTTEST
+:set nocompatible viminfo+=nviminfo
+/^1
+/a*b\{2}c\+/e
+x/\Md\*e\{2}f\+/e
+x:set nomagic
+/g\*h\{2}i\+/e
+x/\mj*k\{2}l\+/e
+x/\vm*n{2}o+/e
+x/\V^aa$
+x:set magic
+/\v(a)(b)\2\1\1/e
+x/\V[ab]\(\[xy]\)\1
+x:?^1?,$w! test.out
+:qa!
+ENDTEST
+
+1 a aa abb abbccc
+2 d dd dee deefff
+3 g gg ghh ghhiii
+4 j jj jkk jkklll
+5 m mm mnn mnnooo
+6 x ^aa$ x
+7 (a)(b) abbaa
+8 axx [ab]xx
diff --git a/src/testdir/test43.ok b/src/testdir/test43.ok
new file mode 100644
index 000000000..425316b68
--- /dev/null
+++ b/src/testdir/test43.ok
@@ -0,0 +1,8 @@
+1 a aa abb abbcc
+2 d dd dee deeff
+3 g gg ghh ghhii
+4 j jj jkk jkkll
+5 m mm mnn mnnoo
+6 x aa$ x
+7 (a)(b) abba
+8 axx ab]xx
diff --git a/src/testdir/test44.in b/src/testdir/test44.in
new file mode 100644
index 000000000..d90a962d3
--- /dev/null
+++ b/src/testdir/test44.in
@@ -0,0 +1,37 @@
+Tests for regexp with multi-byte encoding and various magic settings.
+
+STARTTEST
+:so mbyte.vim
+:set nocompatible encoding=utf-8 termencoding=latin1 viminfo+=nviminfo
+/^1
+/a*b\{2}c\+/e
+x/\Md\*e\{2}f\+/e
+x:set nomagic
+/g\*h\{2}i\+/e
+x/\mj*k\{2}l\+/e
+x/\vm*n{2}o+/e
+x/\V^aa$
+x:set magic
+/\v(a)(b)\2\1\1/e
+x/\V[ab]\(\[xy]\)\1
+x:" Now search for multi-byte without composing char
+/ม
+x:" Now search for multi-byte with composing char
+/ม่
+x:" find word by change of word class
+/ã¡\<カヨ\>ã¯
+x:?^1?,$w! test.out
+:qa!
+ENDTEST
+
+1 a aa abb abbccc
+2 d dd dee deefff
+3 g gg ghh ghhiii
+4 j jj jkk jkklll
+5 m mm mnn mnnooo
+6 x ^aa$ x
+7 (a)(b) abbaa
+8 axx [ab]xx
+9 หม่x อมx
+a อมx หม่x
+b ã¡ã‚«ãƒ¨ã¯
diff --git a/src/testdir/test44.ok b/src/testdir/test44.ok
new file mode 100644
index 000000000..af8507606
--- /dev/null
+++ b/src/testdir/test44.ok
@@ -0,0 +1,11 @@
+1 a aa abb abbcc
+2 d dd dee deeff
+3 g gg ghh ghhii
+4 j jj jkk jkkll
+5 m mm mnn mnnoo
+6 x aa$ x
+7 (a)(b) abba
+8 axx ab]xx
+9 หม่x อx
+a อมx หx
+b カヨã¯
diff --git a/src/testdir/test45.in b/src/testdir/test45.in
new file mode 100644
index 000000000..58537f33d
--- /dev/null
+++ b/src/testdir/test45.in
@@ -0,0 +1,72 @@
+Tests for folding. vim: set ft=vim :
+
+STARTTEST
+:so small.vim
+:" We also need the +syntax feature here.
+:if !has("syntax")
+ e! test.ok
+ w! test.out
+ qa!
+:endif
+:" basic test if a fold can be created, opened, moving to the end and closed
+/^1
+zf2j:call append("$", "manual " . getline(foldclosed(".")))
+zo:call append("$", foldclosed("."))
+]z:call append("$", getline("."))
+zc:call append("$", getline(foldclosed(".")))
+:" test folding with markers.
+:set fdm=marker fdl=1 fdc=3
+/^5
+:call append("$", "marker " . foldlevel("."))
+[z:call append("$", foldlevel("."))
+jo{{ r{jj:call append("$", foldlevel("."))
+kYpj:call append("$", foldlevel("."))
+:" test folding with indent
+:set fdm=indent sw=2
+/^2 b
+i jI :call append("$", "indent " . foldlevel("."))
+k:call append("$", foldlevel("."))
+:" test syntax folding
+:set fdm=syntax fdl=0
+:syn region Hup start="dd" end="hh" fold
+Gzk:call append("$", "folding " . getline("."))
+k:call append("$", getline("."))
+:" test expression folding
+:fun Flvl()
+ let l = getline(v:lnum)
+ if l =~ "bb$"
+ return 2
+ elseif l =~ "gg$"
+ return "s1"
+ elseif l =~ "ii$"
+ return ">2"
+ elseif l =~ "kk$"
+ return "0"
+ endif
+ return "="
+endfun
+:set fdm=expr fde=Flvl()
+/bb$
+:call append("$", "expr " . foldlevel("."))
+/hh$
+:call append("$", foldlevel("."))
+/ii$
+:call append("$", foldlevel("."))
+/kk$
+:call append("$", foldlevel("."))
+:/^last/+1,$w! test.out
+:qa!
+ENDTEST
+
+1 aa
+2 bb
+3 cc
+4 dd {{{
+5 ee {{{ }}}
+6 ff }}}
+7 gg
+8 hh
+9 ii
+a jj
+b kk
+last
diff --git a/src/testdir/test45.ok b/src/testdir/test45.ok
new file mode 100644
index 000000000..f5a1380e5
--- /dev/null
+++ b/src/testdir/test45.ok
@@ -0,0 +1,16 @@
+manual 1 aa
+-1
+3 cc
+1 aa
+marker 2
+1
+1
+0
+indent 2
+1
+folding 8 hh
+ 3 cc
+expr 2
+1
+2
+0
diff --git a/src/testdir/test46.in b/src/testdir/test46.in
new file mode 100644
index 000000000..9a9db74d6
--- /dev/null
+++ b/src/testdir/test46.in
@@ -0,0 +1,27 @@
+Tests for multi-line regexps with ":s". vim: set ft=vim :
+
+STARTTEST
+:" test if replacing a line break works with a back reference
+:/^1/,/^2/s/\n\(.\)/ \1/
+:" test if inserting a line break works with a back reference
+:/^3/,/^4/s/\(.\)$/\r\1/
+:" test if replacing a line break with another line break works
+:/^5/,/^6/s/\(\_d\{3}\)/x\1x/
+:/^1/,$w! test.out
+:qa!
+ENDTEST
+
+1 aa
+bb
+cc
+2 dd
+ee
+3 ef
+gh
+4 ij
+5 a8
+8b c9
+9d
+6 e7
+77f
+xxxxx
diff --git a/src/testdir/test46.ok b/src/testdir/test46.ok
new file mode 100644
index 000000000..71b353df1
--- /dev/null
+++ b/src/testdir/test46.ok
@@ -0,0 +1,13 @@
+1 aa bb cc 2 dd ee
+3 e
+f
+g
+h
+4 i
+j
+5 ax8
+8xb cx9
+9xd
+6 ex7
+7x7f
+xxxxx
diff --git a/src/testdir/test47.in b/src/testdir/test47.in
new file mode 100644
index 000000000..35bb9f260
--- /dev/null
+++ b/src/testdir/test47.in
@@ -0,0 +1,44 @@
+Tests for vertical splits and filler lines in diff mode
+
+STARTTEST
+:so small.vim
+/^1
+yG:new
+pkdd:w! Xtest
+ddGpkkrXoxxx:w! Xtest2
+:file Nop
+ggoyyyjjjozzzz
+:vert diffsplit Xtest
+:vert diffsplit Xtest2
+:" jump to second window for a moment to have filler line appear at start of
+:" first window
+ggpgg:let one = winline()
+j:let one = one . "-" . winline()
+j:let one = one . "-" . winline()
+j:let one = one . "-" . winline()
+j:let one = one . "-" . winline()
+j:let one = one . "-" . winline()
+gg:let two = winline()
+j:let two = two . "-" . winline()
+j:let two = two . "-" . winline()
+j:let two = two . "-" . winline()
+j:let two = two . "-" . winline()
+gg:let three = winline()
+j:let three = three . "-" . winline()
+j:let three = three . "-" . winline()
+j:let three = three . "-" . winline()
+j:let three = three . "-" . winline()
+j:let three = three . "-" . winline()
+j:let three = three . "-" . winline()
+:call append("$", one)
+:call append("$", two)
+:call append("$", three)
+:$-2,$w! test.out
+:qa!
+ENDTEST
+
+1 aa
+2 bb
+3 cc
+4 dd
+5 ee
diff --git a/src/testdir/test47.ok b/src/testdir/test47.ok
new file mode 100644
index 000000000..3307b934e
--- /dev/null
+++ b/src/testdir/test47.ok
@@ -0,0 +1,3 @@
+2-4-5-6-8-9
+1-2-4-5-8
+2-3-4-5-6-7-8
diff --git a/src/testdir/test48.in b/src/testdir/test48.in
new file mode 100644
index 000000000..2179fe664
--- /dev/null
+++ b/src/testdir/test48.in
@@ -0,0 +1,74 @@
+This is a test of 'virtualedit'.
+
+STARTTEST
+:so small.vim
+:set noswf
+:set ve=all
+-dgg
+:"
+:" Insert "keyword keyw", ESC, C CTRL-N, shows "keyword ykeyword".
+:" Repeating CTRL-N fixes it. (Mary Ellen Foster)
+2/w
+C
+:"
+:" Using "C" then then <CR> moves the last remaining character to the next
+:" line. (Mary Ellen Foster)
+j^/are
+C are belong to vim
+:"
+:" When past the end of a line that ends in a single character "b" skips
+:" that word.
+^$15lbC7
+:"
+:" Make sure 'i' works
+$4li<-- should be 3 ' '
+:"
+:" Make sure 'C' works
+$4lC<-- should be 3 ' '
+:"
+:" Make sure 'a' works
+$4la<-- should be 4 ' '
+:"
+:" Make sure 'A' works
+$4lA<-- should be 0 ' '
+:"
+:" Make sure 'D' works
+$4lDi<-- 'D' should be intact
+:"
+:" Test for yank bug reported by Mark Waggoner.
+:set ve=block
+^2w3jyGp
+:"
+:" Test "r" beyond the end of the line
+:set ve=all
+/^"r"
+$5lrxa<-- should be 'x'
+:"
+:" Test to make sure 'x' can delete control characters
+:set display=uhex
+^xxxxxxi[This line should contain only the text between the brackets.]
+:set display=
+:"
+:" Test for ^Y/^E due to bad w_virtcol value, reported by
+:" Roy <royl@netropolis.net>.
+^O3li4li4li <-- should show the name of a noted text editor
+^o4li4li4li <-- and its version number-dd
+:"
+:wq! test.out
+ENDTEST
+keyword keyw
+all your base are belong to us
+1 2 3 4 5 6
+'i'
+'C'
+'a'
+'A'
+'D'
+this is a test
+this is a test
+this is a test
+"r"
+ab sd
+abcv6efi.him0kl
+
+
diff --git a/src/testdir/test48.ok b/src/testdir/test48.ok
new file mode 100644
index 000000000..4fcbe5086
--- /dev/null
+++ b/src/testdir/test48.ok
@@ -0,0 +1,21 @@
+keyword keyword
+all your base
+are belong to vim
+1 2 3 4 5 7
+'i' <-- should be 3 ' '
+'C' <-- should be 3 ' '
+'a' <-- should be 4 ' '
+'A'<-- should be 0 ' '
+'D' <-- 'D' should be intact
+this is a test
+this is a test
+this is a test
+"r" x<-- should be 'x'
+[This line should contain only the text between the brackets.]
+ v i m <-- should show the name of a noted text editor
+ 6 . 0 <-- and its version number
+
+a
+a
+a
+
diff --git a/src/testdir/test49.in b/src/testdir/test49.in
new file mode 100644
index 000000000..ec17d2134
--- /dev/null
+++ b/src/testdir/test49.in
@@ -0,0 +1,13 @@
+This is a test of the script language.
+
+If after adding a new test, the test output doesn't appear properly in
+test49.failed, try to add one ore more "G"s at the line before ENDTEST.
+
+STARTTEST
+:so small.vim
+:se nocp nomore viminfo+=nviminfo
+:so test49.vim
+GGGGGGGGGG"rp:.-,$wq! test.out
+ENDTEST
+
+Results of test49.vim:
diff --git a/src/testdir/test49.ok b/src/testdir/test49.ok
new file mode 100644
index 000000000..1842af259
--- /dev/null
+++ b/src/testdir/test49.ok
@@ -0,0 +1,92 @@
+Results of test49.vim:
+*** Test 1: OK (34695)
+*** Test 2: OK (34695)
+*** Test 3: OK (1384648195)
+*** Test 4: OK (32883)
+*** Test 5: OK (32883)
+*** Test 6: OK (603978947)
+*** Test 7: OK (90563)
+*** Test 8: OK (562493431)
+*** Test 9: OK (363)
+*** Test 10: OK (559615)
+*** Test 11: OK (2049)
+*** Test 12: OK (352256)
+*** Test 13: OK (145)
+*** Test 14: OK (42413)
+*** Test 15: OK (42413)
+*** Test 16: OK (8722)
+*** Test 17: OK (285127993)
+*** Test 18: OK (67224583)
+*** Test 19: OK (69275973)
+*** Test 20: OK (1874575085)
+*** Test 21: OK (147932225)
+*** Test 22: OK (4161)
+*** Test 23: OK (49)
+*** Test 24: OK (41)
+*** Test 25: OK (260177811)
+*** Test 26: OK (1681500476)
+*** Test 27: OK (1996459)
+*** Test 28: OK (1996459)
+*** Test 29: OK (170428555)
+*** Test 30: OK (190905173)
+*** Test 31: OK (190905173)
+*** Test 32: OK (354833067)
+--- Test 33: sum = 178275600 (ok)
+*** Test 33: OK (1216907538)
+*** Test 34: OK (2146584868)
+*** Test 35: OK (2146584868)
+*** Test 36: OK (1071644672)
+*** Test 37: OK (1071644672)
+*** Test 38: OK (357908480)
+*** Test 39: OK (357908480)
+*** Test 40: OK (357908480)
+*** Test 41: OK (3076095)
+*** Test 42: OK (1505155949)
+*** Test 43: OK (1157763329)
+*** Test 44: OK (1031761407)
+*** Test 45: OK (1157763329)
+*** Test 46: OK (739407)
+*** Test 47: OK (371213935)
+*** Test 48: OK (756255461)
+*** Test 49: OK (179000669)
+*** Test 50: OK (363550045)
+*** Test 51: OK (40744667)
+*** Test 52: OK (1247112011)
+*** Test 53: OK (131071)
+*** Test 54: OK (2047)
+*** Test 55: OK (1023)
+*** Test 56: OK (511)
+*** Test 57: OK (2147450880)
+*** Test 58: OK (624945)
+*** Test 59: OK (2038431743)
+*** Test 60: OK (311511339)
+*** Test 61: OK (374889517)
+*** Test 62: OK (286331153)
+*** Test 63: OK (236978127)
+*** Test 64: OK (1499645335)
+*** Test 65: OK (70187)
+*** Test 66: OK (5464)
+*** Test 67: OK (212514423)
+*** Test 68: OK (212514423)
+*** Test 69: OK (8995471)
+*** Test 70: OK (69544277)
+*** Test 71: OK (34886997)
+*** Test 72: OK (1789569365)
+*** Test 73: OK (9032615)
+*** Test 74: OK (224907669)
+*** Test 75: OK (2000403408)
+*** Test 76: OK (1610087935)
+*** Test 77: OK (1388671)
+*** Test 78: OK (134217728)
+*** Test 79: OK (70288929)
+*** Test 80: OK (17895765)
+*** Test 81: OK (387)
+*** Test 82: OK (8454401)
+*** Test 83: OK (2835)
+*** Test 84: OK (934782101)
+*** Test 85: OK (198689)
+--- Test 86: All tests were run with throwing exceptions on error.
+ The $VIMNOERRTHROW control is not configured.
+--- Test 86: All tests were run with throwing exceptions on interrupt.
+ The $VIMNOINTTHROW control is not configured.
+*** Test 86: OK (50443995)
diff --git a/src/testdir/test49.vim b/src/testdir/test49.vim
new file mode 100644
index 000000000..e742a9622
--- /dev/null
+++ b/src/testdir/test49.vim
@@ -0,0 +1,9666 @@
+" Vim script language tests
+" Author: Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com>
+" Last Change: 2004 Apr 03
+
+"-------------------------------------------------------------------------------
+" Test environment {{{1
+"-------------------------------------------------------------------------------
+
+
+" Adding new tests easily. {{{2
+"
+" Writing new tests is eased considerably with the following functions and
+" abbreviations (see "Commands for recording the execution path", "Automatic
+" argument generation").
+"
+" To get the abbreviations, execute the command
+"
+" :let test49_set_env = 1 | source test49.vim
+"
+" To get them always (from src/testdir), put a line
+"
+" au! BufRead test49.vim let test49_set_env = 1 | source test49.vim
+"
+" into the local .vimrc file in the src/testdir directory.
+"
+if exists("test49_set_env") && test49_set_env
+
+ " Automatic argument generation for the test environment commands.
+
+ function! Xsum()
+ let addend = substitute(getline("."), '^.*"\s*X:\s*\|^.*', '', "")
+ " Evaluate arithmetic expression.
+ if addend != ""
+ exec "let g:Xsum = g:Xsum + " . addend
+ endif
+ endfunction
+
+ function! Xcheck()
+ let g:Xsum=0
+ ?XpathINIT?,.call Xsum()
+ exec "norm A "
+ return g:Xsum
+ endfunction
+
+ iab Xcheck Xcheck<Space><C-R>=Xcheck()<CR><C-O>x
+
+ function! Xcomment(num)
+ let str = ""
+ let tabwidth = &sts ? &sts : &ts
+ let tabs = (48+tabwidth - a:num - virtcol(".")) / tabwidth
+ while tabs > 0
+ let str = str . "\t"
+ let tabs = tabs - 1
+ endwhile
+ let str = str . '" X:'
+ return str
+ endfunction
+
+ function! Xloop()
+ let back = line(".") . "|norm" . virtcol(".") . "|"
+ norm 0
+ let last = search('X\(loop\|path\)INIT\|Xloop\>', "bW")
+ exec back
+ let theline = getline(last)
+ if theline =~ 'X\(loop\|path\)INIT'
+ let num = 1
+ else
+ let num = 2 * substitute(theline, '.*Xloop\s*\(\d\+\).*', '\1', "")
+ endif
+ ?X\(loop\|path\)INIT?
+ \s/\(XloopINIT!\=\s*\d\+\s\+\)\@<=\(\d\+\)/\=2*submatch(2)/
+ exec back
+ exec "norm a "
+ return num . Xcomment(strlen(num))
+ endfunction
+
+ iab Xloop Xloop<Space><C-R>=Xloop()<CR><C-O>x
+
+ function! Xpath(loopinit)
+ let back = line(".") . "|norm" . virtcol(".") . "|"
+ norm 0
+ let last = search('XpathINIT\|Xpath\>\|XloopINIT', "bW")
+ exec back
+ let theline = getline(last)
+ if theline =~ 'XpathINIT'
+ let num = 1
+ elseif theline =~ 'Xpath\>'
+ let num = 2 * substitute(theline, '.*Xpath\s*\(\d\+\).*', '\1', "")
+ else
+ let pattern = '.*XloopINIT!\=\s*\(\d\+\)\s*\(\d\+\).*'
+ let num = substitute(theline, pattern, '\1', "")
+ let factor = substitute(theline, pattern, '\2', "")
+ " The "<C-O>x" from the "Xpath" iab and the character triggering its
+ " expansion are in the input buffer. Save and clear typeahead so
+ " that it is not read away by the call to "input()" below. Restore
+ " afterwards.
+ call inputsave()
+ let loops = input("Number of iterations in previous loop? ")
+ call inputrestore()
+ while (loops > 0)
+ let num = num * factor
+ let loops = loops - 1
+ endwhile
+ endif
+ exec "norm a "
+ if a:loopinit
+ return num . " 1"
+ endif
+ return num . Xcomment(strlen(num))
+ endfunction
+
+ iab Xpath Xpath<Space><C-R>=Xpath(0)<CR><C-O>x
+ iab XloopINIT XloopINIT<Space><C-R>=Xpath(1)<CR><C-O>x
+
+ " Also useful (see ExtraVim below):
+ aug ExtraVim
+ au!
+ au BufEnter <sfile> syn region ExtraVim
+ \ start=+^if\s\+ExtraVim(.*)+ end=+^endif+
+ \ transparent keepend
+ au BufEnter <sfile> syn match ExtraComment /^"/
+ \ contained containedin=ExtraVim
+ au BufEnter <sfile> hi link ExtraComment vimComment
+ aug END
+
+ aug Xpath
+ au BufEnter <sfile> syn keyword Xpath
+ \ XpathINIT Xpath XloopINIT Xloop XloopNEXT Xcheck Xout
+ au BufEnter <sfile> hi link Xpath Special
+ aug END
+
+ do BufEnter <sfile>
+
+ " Do not execute the tests when sourcing this file for getting the functions
+ " and abbreviations above, which are intended for easily adding new test
+ " cases; they are not needed for test execution. Unlet the variable
+ " controlling this so that an explicit ":source" command for this file will
+ " execute the tests.
+ unlet test49_set_env
+ finish
+
+endif
+
+
+" Commands for recording the execution path. {{{2
+"
+" The Xpath/Xloop commands can be used for computing the eXecution path by
+" adding (different) powers of 2 from those script lines, for which the
+" execution should be checked. Xloop provides different addends for each
+" execution of a loop. Permittable values are 2^0 to 2^30, so that 31 execution
+" points (multiply counted inside loops) can be tested.
+"
+" Note that the arguments of the following commands can be generated
+" automatically, see below.
+"
+" Usage: {{{3
+"
+" - Use XpathINIT at the beginning of the test.
+"
+" - Use Xpath to check if a line is executed.
+" Argument: power of 2 (decimal).
+"
+" - To check multiple execution of loops use Xloop for automatically
+" computing Xpath values:
+"
+" - Use XloopINIT before the loop.
+" Two arguments:
+" - the first Xpath value (power of 2) to be used (Xnext),
+" - factor for computing a new Xnext value when reexecuting a loop
+" (by a ":continue" or ":endwhile"); this should be 2^n where
+" n is the number of Xloop commands inside the loop.
+" If XloopINIT! is used, the first execution of XloopNEXT is
+" a no-operation.
+"
+" - Use Xloop inside the loop:
+" One argument:
+" The argument and the Xnext value are multiplied to build the
+" next Xpath value. No new Xnext value is prepared. The argument
+" should be 2^(n-1) for the nth Xloop command inside the loop.
+" If the loop has only one Xloop command, the argument can be
+" ommitted (default: 1).
+"
+" - Use XloopNEXT before ":continue" and ":endwhile". This computes a new
+" Xnext value for the next execution of the loop by multiplying the old
+" one with the factor specified in the XloopINIT command. No Argument.
+" Alternatively, when XloopINIT! is used, a single XloopNEXT at the
+" beginning of the loop can be used.
+"
+" Nested loops are not supported.
+"
+" - Use Xcheck at end of each test. It prints the test number, the expected
+" execution path value, the test result ("OK" or "FAIL"), and, if the tests
+" fails, the actual execution path.
+" One argument:
+" Expected Xpath/Xloop sum for the correct execution path.
+" In order that this value can be computed automatically, do the
+" following: For each line in the test with an Xpath and Xloop
+" command, add a comment starting with "X:" and specifying an
+" expression that evaluates to the value contributed by this line to
+" the correct execution path. (For copying an Xpath argument of at
+" least two digits into the comment, press <C-P>.) At the end of the
+" test, just type "Xcheck" and press <Esc>.
+"
+" - In order to add additional information to the test output file, use the
+" Xout command. Argument(s) like ":echo".
+"
+" Automatic argument generation: {{{3
+"
+" The arguments of the Xpath, XloopINIT, Xloop, and Xcheck commands can be
+" generated automatically, so that new tests can easily be written without
+" mental arithmetic. The Xcheck argument is computed from the "X:" comments
+" of the preceding Xpath and Xloop commands. See the commands and
+" abbreviations at the beginning of this file.
+"
+" Implementation: {{{3
+" XpathINIT, Xpath, XloopINIT, Xloop, XloopNEXT, Xcheck, Xout.
+"
+" The variants for existing g:ExtraVimResult are needed when executing a script
+" in an extra Vim process, see ExtraVim below.
+
+" EXTRA_VIM_START - do not change or remove this line.
+
+com! XpathINIT let g:Xpath = 0
+
+if exists("g:ExtraVimResult")
+ com! -count -bar Xpath exec "!echo <count> >>" . g:ExtraVimResult
+else
+ com! -count -bar Xpath let g:Xpath = g:Xpath + <count>
+endif
+
+com! -count -nargs=1 -bang
+ \ XloopINIT let g:Xnext = <count> |
+ \ let g:Xfactor = <args> |
+ \ let g:Xskip = strlen("<bang>")
+
+if exists("g:ExtraVimResult")
+ com! -count=1 -bar Xloop exec "!echo " . (g:Xnext * <count>) . " >>" .
+ \ g:ExtraVimResult
+else
+ com! -count=1 -bar Xloop let g:Xpath = g:Xpath + g:Xnext * <count>
+endif
+
+com! XloopNEXT let g:Xnext = g:Xnext *
+ \ (g:Xskip ? 1 : g:Xfactor) |
+ \ let g:Xskip = 0
+
+let @r = ""
+let Xtest = 1
+com! -count Xcheck let Xresult = "*** Test " .
+ \ (Xtest<10?" ":Xtest<100?" ":"") .
+ \ Xtest . ": " . (
+ \ (Xpath==<count>) ? "OK (".Xpath.")" :
+ \ "FAIL (".Xpath." instead of <count>)"
+ \ ) |
+ \ let @R = Xresult . "\n" |
+ \ echo Xresult |
+ \ let Xtest = Xtest + 1
+
+if exists("g:ExtraVimResult")
+ com! -nargs=+ Xout exec "exec \"!echo @R:'\" ."
+ \ 'substitute(substitute("' . <args> .
+ \ '", "' . "'" . '", ' . "'" . '&\\&&' . "'"
+ \ . ', "g"), "\n", "@NL@", "g")'
+ \ ". \"' >>\" . g:ExtraVimResult"
+else
+ com! -nargs=+ Xout exec 'let @R = "--- Test ' .
+ \ (g:Xtest<10?" ":g:Xtest<100?" ":"") .
+ \ g:Xtest . ": " .
+ \ '" . substitute("' . <args> .
+ \ '", "\n", "&\t ", "g") . "\n"'
+endif
+
+" Switch off storing of lines for undoing changes. Speeds things up a little.
+set undolevels=-1
+
+" EXTRA_VIM_STOP - do not change or remove this line.
+
+
+" ExtraVim() - Run a script file in an extra Vim process. {{{2
+"
+" This is useful for testing immediate abortion of the script processing due to
+" an error in a command dynamically enclosed by a :try/:tryend region or when an
+" exception is thrown but not caught or when an interrupt occurs. It can also
+" be used for testing :finish.
+"
+" An interrupt location can be specified by an "INTERRUPT" comment. A number
+" telling how often this location is reached (in a loop or in several function
+" calls) should be specified as argument. When missing, once per script
+" invocation or function call is assumed. INTERRUPT locations are tested by
+" setting a breakpoint in that line and using the ">quit" debug command when
+" the breakpoint is reached. A function for which an INTERRUPT location is
+" specified must be defined before calling it (or executing it as a script by
+" using ExecAsScript below).
+"
+" This function is only called in normal modus ("g:ExtraVimResult" undefined).
+"
+" Tests to be executed as an extra script should be written as follows:
+"
+" column 1 column 1
+" | |
+" v v
+"
+" XpathINIT XpathINIT
+" if ExtraVim() if ExtraVim()
+" ... " ...
+" ... " ...
+" endif endif
+" Xcheck <number> Xcheck <number>
+"
+" Double quotes in column 1 are removed before the script is executed.
+" They should be used if the test has unbalanced conditionals (:if/:endif,
+" :while:/endwhile, :try/:endtry) or for a line with a syntax error. The
+" extra script may use Xpath, XloopINIT, Xloop, XloopNEXT, and Xout as usual.
+"
+" A file name may be specified as argument. All messages of the extra Vim
+" process are then redirected to the file. An existing file is overwritten.
+"
+let ExtraVimCount = 0
+let ExtraVimBase = expand("<sfile>")
+let ExtraVimTestEnv = ""
+"
+function! ExtraVim(...)
+ " Count how often this function is called.
+ let g:ExtraVimCount = g:ExtraVimCount + 1
+
+ " Disable folds to prevent that the ranges in the ":write" commands below
+ " are extended up to the end of a closed fold. This also speeds things up
+ " considerably.
+ set nofoldenable
+
+ " Open a buffer for this test script and copy the test environment to
+ " a temporary file. Take account of parts relevant for the extra script
+ " execution only.
+ let current_buffnr = bufnr("%")
+ execute "view +1" g:ExtraVimBase
+ if g:ExtraVimCount == 1
+ let g:ExtraVimTestEnv = tempname()
+ execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w"
+ \ g:ExtraVimTestEnv "|']+"
+ execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
+ \ g:ExtraVimTestEnv "|']+"
+ execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
+ \ g:ExtraVimTestEnv "|']+"
+ execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
+ \ g:ExtraVimTestEnv "|']+"
+ endif
+
+ " Start the extra Vim script with a ":source" command for the test
+ " environment. The source line number where the extra script will be
+ " appended, needs to be passed as variable "ExtraVimBegin" to the script.
+ let extra_script = tempname()
+ exec "!echo 'source " . g:ExtraVimTestEnv . "' >" . extra_script
+ let extra_begin = 1
+
+ " Starting behind the test environment, skip over the first g:ExtraVimCount
+ " occurrences of "if ExtraVim()" and copy the following lines up to the
+ " matching "endif" to the extra Vim script.
+ execute "/E" . "ND_OF_TEST_ENVIRONMENT/"
+ exec 'norm ' . g:ExtraVimCount . '/^\s*if\s\+ExtraVim(.*)/+' . "\n"
+ execute ".,/^endif/-write >>" . extra_script
+
+ " Open a buffer for the extra Vim script, delete all ^", and write the
+ " script if was actually modified.
+ execute "edit +" . (extra_begin + 1) extra_script
+ ,$s/^"//e
+ update
+
+ " Count the INTERRUPTs and build the breakpoint and quit commands.
+ let breakpoints = ""
+ let debug_quits = ""
+ let in_func = 0
+ exec extra_begin
+ while search(
+ \ '"\s*INTERRUPT\h\@!\|^\s*fu\%[nction]\>!\=\s*\%(\u\|s:\)\w*\s*(\|'
+ \ . '^\s*\\\|^\s*endf\%[unction]\>\|'
+ \ . '\%(^\s*fu\%[nction]!\=\s*\)\@<!\%(\u\|s:\)\w*\s*(\|'
+ \ . 'ExecAsScript\s\+\%(\u\|s:\)\w*',
+ \ "W") > 0
+ let theline = getline(".")
+ if theline =~ '^\s*fu'
+ " Function definition.
+ let in_func = 1
+ let func_start = line(".")
+ let func_name = substitute(theline,
+ \ '^\s*fu\%[nction]!\=\s*\(\%(\u\|s:\)\w*\).*', '\1', "")
+ let func_conts = 0
+ elseif theline =~ '^\s*\\'
+ if in_func
+ let func_conts = func_conts + 1
+ endif
+ elseif theline =~ '^\s*endf'
+ " End of function definition.
+ let in_func = 0
+ else
+ let finding = substitute(theline, '.*\(\%' . col(".") . 'c.*\)',
+ \ '\1', "")
+ if finding =~ '^"\s*INTERRUPT\h\@!'
+ " Interrupt comment. Compose as many quit commands as
+ " specified.
+ let cnt = substitute(finding,
+ \ '^"\s*INTERRUPT\s*\(\d*\).*$', '\1', "")
+ let quits = ""
+ while cnt > 0
+ " Use "\r" rather than "\n" to separate the quit commands.
+ " "\r" is not interpreted as command separator by the ":!"
+ " command below but works to separate commands in the
+ " external vim.
+ let quits = quits . "q\r"
+ let cnt = cnt - 1
+ endwhile
+ if in_func
+ " Add the function breakpoint and note the number of quits
+ " to be used, if specified, or one for every call else.
+ let breakpoints = breakpoints . " -c 'breakadd func " .
+ \ (line(".") - func_start - func_conts) . " " .
+ \ func_name . "'"
+ if quits != ""
+ let debug_quits = debug_quits . quits
+ elseif !exists("quits{func_name}")
+ let quits{func_name} = "q\r"
+ else
+ let quits{func_name} = quits{func_name} . "q\r"
+ endif
+ else
+ " Add the file breakpoint and the quits to be used for it.
+ let breakpoints = breakpoints . " -c 'breakadd file " .
+ \ line(".") . " " . extra_script . "'"
+ if quits == ""
+ let quits = "q\r"
+ endif
+ let debug_quits = debug_quits . quits
+ endif
+ else
+ " Add the quits to be used for calling the function or executing
+ " it as script file.
+ if finding =~ '^ExecAsScript'
+ " Sourcing function as script.
+ let finding = substitute(finding,
+ \ '^ExecAsScript\s\+\(\%(\u\|s:\)\w*\).*', '\1', "")
+ else
+ " Function call.
+ let finding = substitute(finding,
+ \ '^\(\%(\u\|s:\)\w*\).*', '\1', "")
+ endif
+ if exists("quits{finding}")
+ let debug_quits = debug_quits . quits{finding}
+ endif
+ endif
+ endif
+ endwhile
+
+ " Close the buffer for the script and create an (empty) resultfile.
+ bwipeout
+ let resultfile = tempname()
+ exec "!>" . resultfile
+
+ " Run the script in an extra vim. Switch to extra modus by passing the
+ " resultfile in ExtraVimResult. Redirect messages to the file specified as
+ " argument if any. Use ":debuggreedy" so that the commands provided on the
+ " pipe are consumed at the debug prompt. Use "-N" to enable command-line
+ " contiunation ("C" in 'cpo'). Add "nviminfo" to 'viminfo' to avoid
+ " messing up the user's viminfo file.
+ let redirect = a:0 ?
+ \ " -c 'au VimLeave * redir END' -c 'redir\\! >" . a:1 . "'" : ""
+ exec "!echo '" . debug_quits . "q' | ../vim -u NONE -N -Xes" . redirect .
+ \ " -c 'debuggreedy|set viminfo+=nviminfo'" .
+ \ " -c 'let ExtraVimBegin = " . extra_begin . "'" .
+ \ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints .
+ \ " -S " . extra_script
+
+ " Build the resulting sum for resultfile and add it to g:Xpath. Add Xout
+ " information provided by the extra Vim process to the test output.
+ let sum = 0
+ exec "edit" resultfile
+ let line = 1
+ while line <= line("$")
+ let theline = getline(line)
+ if theline =~ '^@R:'
+ exec 'Xout "' . substitute(substitute(
+ \ escape(escape(theline, '"'), '\"'),
+ \ '^@R:', '', ""), '@NL@', "\n", "g") . '"'
+ else
+ let sum = sum + getline(line)
+ endif
+ let line = line + 1
+ endwhile
+ bwipeout
+ let g:Xpath = g:Xpath + sum
+
+ " Delete the extra script and the resultfile.
+ call delete(extra_script)
+ call delete(resultfile)
+
+ " Switch back to the buffer that was active when this function was entered.
+ exec "buffer" current_buffnr
+
+ " Return 0. This protects extra scripts from being run in the main Vim
+ " process.
+ return 0
+endfunction
+
+
+" ExtraVimThrowpoint() - Relative throwpoint in ExtraVim script {{{2
+"
+" Evaluates v:throwpoint and returns the throwpoint relativ to the beginning of
+" an ExtraVim script as passed by ExtraVim() in ExtraVimBegin.
+"
+" EXTRA_VIM_START - do not change or remove this line.
+function! ExtraVimThrowpoint()
+ if !exists("g:ExtraVimBegin")
+ Xout "ExtraVimThrowpoint() used outside ExtraVim() script."
+ return v:throwpoint
+ endif
+
+ if v:throwpoint =~ '^function\>'
+ return v:throwpoint
+ endif
+
+ return "line " .
+ \ (substitute(v:throwpoint, '.*, line ', '', "") - g:ExtraVimBegin) .
+ \ " of ExtraVim() script"
+endfunction
+" EXTRA_VIM_STOP - do not change or remove this line.
+
+
+" MakeScript() - Make a script file from a function. {{{2
+"
+" Create a script that consists of the body of the function a:funcname.
+" Replace any ":return" by a ":finish", any argument variable by a global
+" variable, and and every ":call" by a ":source" for the next following argument
+" in the variable argument list. This function is useful if similar tests are
+" to be made for a ":return" from a function call or a ":finish" in a script
+" file.
+"
+" In order to execute a function specifying an INTERRUPT location (see ExtraVim)
+" as a script file, use ExecAsScript below.
+"
+" EXTRA_VIM_START - do not change or remove this line.
+function! MakeScript(funcname, ...)
+ let script = tempname()
+ execute "redir! >" . script
+ execute "function" a:funcname
+ redir END
+ execute "edit" script
+ " Delete the "function" and the "endfunction" lines. Do not include the
+ " word "function" in the pattern since it might be translated if LANG is
+ " set. When MakeScript() is being debugged, this deletes also the debugging
+ " output of its line 3 and 4.
+ exec '1,/.*' . a:funcname . '(.*)/d'
+ /^\d*\s*endfunction\>/,$d
+ %s/^\d*//e
+ %s/return/finish/e
+ %s/\<a:\(\h\w*\)/g:\1/ge
+ normal gg0
+ let cnt = 0
+ while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
+ let cnt = cnt + 1
+ s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
+ endwhile
+ g/^\s*$/d
+ write
+ bwipeout
+ return script
+endfunction
+" EXTRA_VIM_STOP - do not change or remove this line.
+
+
+" ExecAsScript - Source a temporary script made from a function. {{{2
+"
+" Make a temporary script file from the function a:funcname, ":source" it, and
+" delete it afterwards.
+"
+" When inside ":if ExtraVim()", add a file breakpoint for each INTERRUPT
+" location specified in the function.
+"
+" EXTRA_VIM_START - do not change or remove this line.
+function! ExecAsScript(funcname)
+ " Make a script from the function passed as argument.
+ let script = MakeScript(a:funcname)
+
+ " When running in an extra Vim process, add a file breakpoint for each
+ " function breakpoint set when the extra Vim process was invoked by
+ " ExtraVim().
+ if exists("g:ExtraVimResult")
+ let bplist = tempname()
+ execute "redir! >" . bplist
+ breaklist
+ redir END
+ execute "edit" bplist
+ " Get the line number from the function breakpoint. Works also when
+ " LANG is set.
+ execute 'v/^\s*\d\+\s\+func\s\+' . a:funcname . '\s.*/d'
+ %s/^\s*\d\+\s\+func\s\+\%(\u\|s:\)\w*\s\D*\(\d*\).*/\1/e
+ let cnt = 0
+ while cnt < line("$")
+ let cnt = cnt + 1
+ if getline(cnt) != ""
+ execute "breakadd file" getline(cnt) script
+ endif
+ endwhile
+ bwipeout!
+ call delete(bplist)
+ endif
+
+ " Source and delete the script.
+ exec "source" script
+ call delete(script)
+endfunction
+
+com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
+" EXTRA_VIM_STOP - do not change or remove this line.
+
+
+" END_OF_TEST_ENVIRONMENT - do not change or remove this line.
+
+
+"-------------------------------------------------------------------------------
+" Test 1: :endwhile in function {{{1
+"
+" Detect if a broken loop is (incorrectly) reactivated by the
+" :endwhile. Use a :return to prevent an endless loop, and make
+" this test first to get a meaningful result on an error before other
+" tests will hang.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ Xpath 1 " X: 1
+ let first = 1
+ XloopINIT 2 8
+ while 1
+ Xloop 1 " X: 2 + 0 * 16
+ if first
+ Xloop 2 " X: 4 + 0 * 32
+ let first = 0
+ XloopNEXT
+ break
+ else
+ Xloop 4 " X: 0 + 0 * 64
+ return
+ endif
+ endwhile
+endfunction
+
+call F()
+Xpath 128 " X: 128
+
+function! G()
+ Xpath 256 " X: 256 + 0 * 2048
+ let first = 1
+ XloopINIT 512 8
+ while 1
+ Xloop 1 " X: 512 + 0 * 4096
+ if first
+ Xloop 2 " X: 1024 + 0 * 8192
+ let first = 0
+ XloopNEXT
+ break
+ else
+ Xloop 4 " X: 0 + 0 * 16384
+ return
+ endif
+ if 1 " unmatched :if
+ endwhile
+endfunction
+
+call G()
+Xpath 32768 " X: 32768
+
+Xcheck 34695
+
+" Leave F and G for execution as scripts in the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 2: :endwhile in script {{{1
+"
+" Detect if a broken loop is (incorrectly) reactivated by the
+" :endwhile. Use a :finish to prevent an endless loop, and place
+" this test before others that might hang to get a meaningful result
+" on an error.
+"
+" This test executes the bodies of the functions F and G from the
+" previous test as script files (:return replaced by :finish).
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+ExecAsScript F " X: 1 + 2 + 4
+Xpath 128 " X: 128
+
+ExecAsScript G " X: 256 + 512 + 1024
+Xpath 32768 " X: 32768
+
+unlet first
+delfunction F
+delfunction G
+
+Xcheck 34695
+
+
+"-------------------------------------------------------------------------------
+" Test 3: :if, :elseif, :while, :continue, :break {{{1
+"-------------------------------------------------------------------------------
+
+XpathINIT
+if 1
+ Xpath 1 " X: 1
+ let loops = 3
+ XloopINIT 2 512
+ while loops > -1 " main loop: loops == 3, 2, 1 (which breaks)
+ if loops <= 0
+ let break_err = 1
+ let loops = -1
+ else " 3: 2: 1:
+ Xloop 1 " X: 2 + 2*512 + 2*512*512
+ endif
+ if (loops == 2)
+ while loops == 2 " dummy loop
+ Xloop 2 " X: 4*512
+ let loops = loops - 1
+ continue " stop dummy loop
+ Xloop 4 " X: 0
+ endwhile
+ XloopNEXT
+ continue " continue main loop
+ Xloop 8 " X: 0
+ elseif (loops == 1)
+ let p = 1
+ while p " dummy loop
+ Xloop 16 " X: 32*512*512
+ let p = 0
+ break " break dummy loop
+ Xloop 32 " X: 0
+ endwhile
+ Xloop 64 " X: 128*512*512
+ unlet p
+ break " break main loop
+ Xloop 128 " X: 0
+ endif
+ if (loops > 0)
+ Xloop 256 " X: 512
+ endif
+ while loops == 3 " dummy loop
+ let loops = loops - 1
+ endwhile " end dummy loop
+ XloopNEXT
+ endwhile " end main loop
+ Xpath 268435456 " X: 1024*512*512
+else
+ Xpath 536870912 " X: 0
+endif
+Xpath 1073741824 " X: 4096*512*512
+if exists("break_err")
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ unlet break_err
+endif
+
+unlet loops
+
+Xcheck 1384648195
+
+
+"-------------------------------------------------------------------------------
+" Test 4: :return {{{1
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ if 1
+ Xpath 1 " X: 1
+ let loops = 3
+ XloopINIT 2 16
+ while loops > 0 " 3: 2: 1:
+ Xloop 1 " X: 2 + 2*16 + 0*16*16
+ if (loops == 2)
+ Xloop 2 " X: 4*16
+ return
+ Xloop 4 " X: 0
+ endif
+ Xloop 8 " X: 16
+ let loops = loops - 1
+ XloopNEXT
+ endwhile
+ Xpath 8192 " X: 0
+ else
+ Xpath 16384 " X: 0
+ endif
+endfunction
+
+call F()
+Xpath 32768 " X: 8*16*16*16
+
+Xcheck 32883
+
+" Leave F for execution as a script in the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 5: :finish {{{1
+"
+" This test executes the body of the function F from the previous test
+" as a script file (:return replaced by :finish).
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+ExecAsScript F " X: 1 + 2 + 2*16 + 4*16 + 16
+Xpath 32768 " X: 32768
+
+unlet loops
+delfunction F
+
+Xcheck 32883
+
+
+"-------------------------------------------------------------------------------
+" Test 6: Defining functions in :while loops {{{1
+"
+" Functions can be defined inside other functions. An inner function
+" gets defined when the outer function is executed. Functions may
+" also be defined inside while loops. Expressions in braces for
+" defining the function name are allowed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ " The command CALL collects the argument of all its invocations in "calls"
+ " when used from a function (that is, when the global variable "calls" needs
+ " the "g:" prefix). This is to check that the function code is skipped when
+ " the function is defined. For inner functions, do so only if the outer
+ " function is not being executed.
+ "
+ let calls = ""
+ com! -nargs=1 CALL
+ \ if !exists("calls") && !exists("outer") |
+ \ let g:calls = g:calls . <args> |
+ \ endif
+
+
+ XloopINIT! 1 16
+
+ let i = 0
+ while i < 3
+
+ XloopNEXT
+ let i = i + 1
+
+ if i == 1
+ Xloop 1 " X: 1
+ function! F1(arg)
+ CALL a:arg
+ let outer = 1
+
+ XloopINIT! 4096 4
+ let j = 0
+ while j < 1
+ XloopNEXT
+ Xloop 1 " X: 4096
+ let j = j + 1
+ function! G1(arg)
+ CALL a:arg
+ endfunction
+ Xloop 2 " X: 8192
+ endwhile
+ endfunction
+ Xloop 2 " X: 2
+
+ continue
+ endif
+
+ Xloop 4 " X: 4 * (16 + 256)
+ function! F{i}(i, arg)
+ CALL a:arg
+ let outer = 1
+
+ XloopINIT! 16384 4
+ if a:i == 3
+ XloopNEXT
+ XloopNEXT
+ XloopNEXT
+ endif
+ let k = 0
+ while k < 3
+ XloopNEXT
+ Xloop 1 " X: 16384*(1+4+16+64+256+1024)
+ let k = k + 1
+ function! G{a:i}{k}(arg)
+ CALL a:arg
+ endfunction
+ Xloop 2 " X: 32768*(1+4+16+64+256+1024)
+ endwhile
+ endfunction
+ Xloop 8 " X: 8 * (16 + 256)
+
+ endwhile
+
+ if exists("*G1")
+ Xpath 67108864 " X: 0
+ endif
+ if exists("*F1")
+ call F1("F1")
+ if exists("*G1")
+ call G1("G1")
+ endif
+ endif
+
+ if exists("G21") || exists("G21") || exists("G21")
+ Xpath 134217728 " X: 0
+ endif
+ if exists("*F2")
+ call F2(2, "F2")
+ if exists("*G21")
+ call G21("G21")
+ endif
+ if exists("*G22")
+ call G22("G22")
+ endif
+ if exists("*G23")
+ call G23("G23")
+ endif
+ endif
+
+ if exists("G31") || exists("G31") || exists("G31")
+ Xpath 268435456 " X: 0
+ endif
+ if exists("*F3")
+ call F3(3, "F3")
+ if exists("*G31")
+ call G31("G31")
+ endif
+ if exists("*G32")
+ call G32("G32")
+ endif
+ if exists("*G33")
+ call G33("G33")
+ endif
+ endif
+
+ Xpath 536870912 " X: 536870912
+
+ if calls != "F1G1F2G21G22G23F3G31G32G33"
+ Xpath 1073741824 " X: 0
+ Xout "calls is" calls
+ endif
+
+ delfunction F1
+ delfunction G1
+ delfunction F2
+ delfunction G21
+ delfunction G22
+ delfunction G23
+ delfunction G31
+ delfunction G32
+ delfunction G33
+
+endif
+
+Xcheck 603978947
+
+
+"-------------------------------------------------------------------------------
+" Test 7: Continuing on errors outside functions {{{1
+"
+" On an error outside a function, the script processing continues
+" at the line following the outermost :endif or :endwhile. When not
+" inside an :if or :while, the script processing continues at the next
+" line.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if 1
+ Xpath 1 " X: 1
+ while 1
+ Xpath 2 " X: 2
+ asdf
+ Xpath 4 " X: 0
+ break
+ endwhile | Xpath 8 " X: 0
+ Xpath 16 " X: 0
+endif | Xpath 32 " X: 0
+Xpath 64 " X: 64
+
+while 1
+ Xpath 128 " X: 128
+ if 1
+ Xpath 256 " X: 256
+ asdf
+ Xpath 512 " X: 0
+ endif | Xpath 1024 " X: 0
+ Xpath 2048 " X: 0
+ break
+endwhile | Xpath 4096 " X: 0
+Xpath 8192 " X: 8192
+
+asdf
+Xpath 16384 " X: 16384
+
+asdf | Xpath 32768 " X: 0
+Xpath 65536 " X: 65536
+
+Xcheck 90563
+
+
+"-------------------------------------------------------------------------------
+" Test 8: Aborting and continuing on errors inside functions {{{1
+"
+" On an error inside a function without the "abort" attribute, the
+" script processing continues at the next line (unless the error was
+" in a :return command). On an error inside a function with the
+" "abort" attribute, the function is aborted and the script processing
+" continues after the function call; the value -1 is returned then.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ if 1
+ Xpath 1 " X: 1
+ while 1
+ Xpath 2 " X: 2
+ asdf
+ Xpath 4 " X: 4
+ asdf | Xpath 8 " X: 0
+ Xpath 16 " X: 16
+ break
+ endwhile
+ Xpath 32 " X: 32
+ endif | Xpath 64 " X: 64
+ Xpath 128 " X: 128
+
+ while 1
+ Xpath 256 " X: 256
+ if 1
+ Xpath 512 " X: 512
+ asdf
+ Xpath 1024 " X: 1024
+ asdf | Xpath 2048 " X: 0
+ Xpath 4096 " X: 4096
+ endif
+ Xpath 8192 " X: 8192
+ break
+ endwhile | Xpath 16384 " X: 16384
+ Xpath 32768 " X: 32768
+
+ return novar " returns (default return value 0)
+ Xpath 65536 " X: 0
+ return 1 " not reached
+endfunction
+
+function! G() abort
+ if 1
+ Xpath 131072 " X: 131072
+ while 1
+ Xpath 262144 " X: 262144
+ asdf " returns -1
+ Xpath 524288 " X: 0
+ break
+ endwhile
+ Xpath 1048576 " X: 0
+ endif | Xpath 2097152 " X: 0
+ Xpath Xpath 4194304 " X: 0
+
+ return -4 " not reached
+endfunction
+
+function! H() abort
+ while 1
+ Xpath 8388608 " X: 8388608
+ if 1
+ Xpath 16777216 " X: 16777216
+ asdf " returns -1
+ Xpath 33554432 " X: 0
+ endif
+ Xpath 67108864 " X: 0
+ break
+ endwhile | Xpath 134217728 " X: 0
+ Xpath 268435456 " X: 0
+
+ return -4 " not reached
+endfunction
+
+" Aborted functions (G and H) return -1.
+let sum = (F() + 1) - 4*G() - 8*H()
+Xpath 536870912 " X: 536870912
+if sum != 13
+ Xpath 1073741824 " X: 0
+ Xout "sum is" sum
+endif
+
+unlet sum
+delfunction F
+delfunction G
+delfunction H
+
+Xcheck 562493431
+
+
+"-------------------------------------------------------------------------------
+" Test 9: Continuing after aborted functions {{{1
+"
+" When a function with the "abort" attribute is aborted due to an
+" error, the next function back in the call hierarchy without an
+" "abort" attribute continues; the value -1 is returned then.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F() abort
+ Xpath 1 " X: 1
+ let result = G() " not aborted
+ Xpath 2 " X: 2
+ if result != 2
+ Xpath 4 " X: 0
+ endif
+ return 1
+endfunction
+
+function! G() " no abort attribute
+ Xpath 8 " X: 8
+ if H() != -1 " aborted
+ Xpath 16 " X: 0
+ endif
+ Xpath 32 " X: 32
+ return 2
+endfunction
+
+function! H() abort
+ Xpath 64 " X: 64
+ call I() " aborted
+ Xpath 128 " X: 0
+ return 4
+endfunction
+
+function! I() abort
+ Xpath 256 " X: 256
+ asdf " error
+ Xpath 512 " X: 0
+ return 8
+endfunction
+
+if F() != 1
+ Xpath 1024 " X: 0
+endif
+
+delfunction F
+delfunction G
+delfunction H
+delfunction I
+
+Xcheck 363
+
+
+"-------------------------------------------------------------------------------
+" Test 10: :if, :elseif, :while argument parsing {{{1
+"
+" A '"' or '|' in an argument expression must not be mixed up with
+" a comment or a next command after a bar. Parsing errors should
+" be recognized.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ let match = 1
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ let match = 0
+ if v:errmsg == ""
+ Xout "Message missing."
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Unexpected message:" v:errmsg
+ endif
+ endif
+ return match
+endfunction
+
+if 1 || strlen("\"") | Xpath 1 " X: 1
+ Xpath 2 " X: 2
+endif
+Xpath 4 " X: 4
+
+if 0
+elseif 1 || strlen("\"") | Xpath 8 " X: 8
+ Xpath 16 " X: 16
+endif
+Xpath 32 " X: 32
+
+while 1 || strlen("\"") | Xpath 64 " X: 64
+ Xpath 128 " X: 128
+ break
+endwhile
+Xpath 256 " X: 256
+
+let v:errmsg = ""
+if 1 ||| strlen("\"") | Xpath 512 " X: 0
+ Xpath 1024 " X: 0
+endif
+Xpath 2048 " X: 2048
+if !MSG('E15', "Invalid expression")
+ Xpath 4096 " X: 0
+endif
+
+let v:errmsg = ""
+if 0
+elseif 1 ||| strlen("\"") | Xpath 8192 " X: 0
+ Xpath 16384 " X: 0
+endif
+Xpath 32768 " X: 32768
+if !MSG('E15', "Invalid expression")
+ Xpath 65536 " X: 0
+endif
+
+let v:errmsg = ""
+while 1 ||| strlen("\"") | Xpath 131072 " X: 0
+ Xpath 262144 " X: 0
+ break
+endwhile
+Xpath 524288 " X: 524288
+if !MSG('E15', "Invalid expression")
+ Xpath 1048576 " X: 0
+endif
+
+delfunction MSG
+
+Xcheck 559615
+
+
+"-------------------------------------------------------------------------------
+" Test 11: :if, :elseif, :while argument evaluation after abort {{{1
+"
+" When code is skipped over due to an error, the boolean argument to
+" an :if, :elseif, or :while must not be evaluated.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let calls = 0
+
+function! P(num)
+ let g:calls = g:calls + a:num " side effect on call
+ return 0
+endfunction
+
+if 1
+ Xpath 1 " X: 1
+ asdf " error
+ Xpath 2 " X: 0
+ if P(1) " should not be called
+ Xpath 4 " X: 0
+ elseif !P(2) " should not be called
+ Xpath 8 " X: 0
+ else
+ Xpath 16 " X: 0
+ endif
+ Xpath 32 " X: 0
+ while P(4) " should not be called
+ Xpath 64 " X: 0
+ endwhile
+ Xpath 128 " X: 0
+endif
+
+if calls % 2
+ Xpath 256 " X: 0
+endif
+if (calls/2) % 2
+ Xpath 512 " X: 0
+endif
+if (calls/4) % 2
+ Xpath 1024 " X: 0
+endif
+Xpath 2048 " X: 2048
+
+unlet calls
+delfunction P
+
+Xcheck 2049
+
+
+"-------------------------------------------------------------------------------
+" Test 12: Expressions in braces in skipped code {{{1
+"
+" In code skipped over due to an error or inactive conditional,
+" an expression in braces as part of a variable or function name
+" should not be evaluated.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT 1 8
+
+function! NULL()
+ Xloop 1 " X: 0
+ return 0
+endfunction
+
+function! ZERO()
+ Xloop 2 " X: 0
+ return 0
+endfunction
+
+function! F0()
+ Xloop 4 " X: 0
+endfunction
+
+function! F1(arg)
+ Xpath 4096 " X: 0
+endfunction
+
+let V0 = 1
+
+Xpath 8192 " X: 8192
+echo 0 ? F{NULL() + V{ZERO()}}() : 1
+XloopNEXT
+
+Xpath 16384 " X: 16384
+if 0
+ Xpath 32768 " X: 0
+ call F{NULL() + V{ZERO()}}()
+endif
+XloopNEXT
+
+Xpath 65536 " X: 65536
+if 1
+ asdf " error
+ Xpath 131072 " X: 0
+ call F1(F{NULL() + V{ZERO()}}())
+endif
+XloopNEXT
+
+Xpath 262144 " X: 262144
+if 1
+ asdf " error
+ Xpath 524288 " X: 0
+ call F{NULL() + V{ZERO()}}()
+endif
+
+Xcheck 352256
+
+
+"-------------------------------------------------------------------------------
+" Test 13: Failure in argument evaluation for :while {{{1
+"
+" A failure in the expression evaluation for the condition of a :while
+" causes the whole :while loop until the matching :endwhile being
+" ignored. Continuation is at the next following line.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+Xpath 1 " X: 1
+while asdf
+ Xpath 2 " X: 0
+ while 1
+ Xpath 4 " X: 0
+ break
+ endwhile
+ Xpath 8 " X: 0
+ break
+endwhile
+Xpath 16 " X: 16
+
+while asdf | Xpath 32 | endwhile | Xpath 64 " X: 0
+Xpath 128 " X: 128
+
+Xcheck 145
+
+
+"-------------------------------------------------------------------------------
+" Test 14: Failure in argument evaluation for :if {{{1
+"
+" A failure in the expression evaluation for the condition of an :if
+" does not cause the corresponding :else or :endif being matched to
+" a previous :if/:elseif. Neither of both branches of the failed :if
+" are executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+XloopINIT 1 256
+
+function! F()
+ Xloop 1 " X: 1 + 256 * 1
+ let x = 0
+ if x " false
+ Xloop 2 " X: 0 + 256 * 0
+ elseif !x " always true
+ Xloop 4 " X: 4 + 256 * 4
+ let x = 1
+ if g:boolvar " possibly undefined
+ Xloop 8 " X: 8 + 256 * 0
+ else
+ Xloop 16 " X: 0 + 256 * 0
+ endif
+ Xloop 32 " X: 32 + 256 * 32
+ elseif x " never executed
+ Xloop 64 " X: 0 + 256 * 0
+ endif
+ Xloop 128 " X: 128 + 256 * 128
+endfunction
+
+let boolvar = 1
+call F()
+
+XloopNEXT
+unlet boolvar
+call F()
+
+delfunction F
+
+Xcheck 42413
+
+
+"-------------------------------------------------------------------------------
+" Test 15: Failure in argument evaluation for :if (bar) {{{1
+"
+" Like previous test, except that the failing :if ... | ... | :endif
+" is in a single line.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+XloopINIT 1 256
+
+function! F()
+ Xloop 1 " X: 1 + 256 * 1
+ let x = 0
+ if x " false
+ Xloop 2 " X: 0 + 256 * 0
+ elseif !x " always true
+ Xloop 4 " X: 4 + 256 * 4
+ let x = 1
+ if g:boolvar | Xloop 8 | else | Xloop 16 | endif " X: 8
+ Xloop 32 " X: 32 + 256 * 32
+ elseif x " never executed
+ Xloop 64 " X: 0 + 256 * 0
+ endif
+ Xloop 128 " X: 128 + 256 * 128
+endfunction
+
+let boolvar = 1
+call F()
+
+XloopNEXT
+unlet boolvar
+call F()
+
+delfunction F
+
+Xcheck 42413
+
+
+"-------------------------------------------------------------------------------
+" Test 16: Double :else or :elseif after :else {{{1
+"
+" Multiple :elses or an :elseif after an :else are forbidden.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F() abort
+ if 0
+ Xpath 1 " X: 0
+ else
+ Xpath 2 " X: 2
+ else " aborts function
+ Xpath 4 " X: 0
+ endif
+endfunction
+
+function! G() abort
+ if 0
+ Xpath 8 " X: 0
+ else
+ Xpath 16 " X: 16
+ elseif 1 " aborts function
+ Xpath 32 " X: 0
+ else
+ Xpath 64 " X: 0
+ endif
+endfunction
+
+function! H() abort
+ if 0
+ Xpath 128 " X: 0
+ elseif 0
+ Xpath 256 " X: 0
+ else
+ Xpath 512 " X: 512
+ else " aborts function
+ Xpath 1024 " X: 0
+ endif
+endfunction
+
+function! I() abort
+ if 0
+ Xpath 2048 " X: 0
+ elseif 0
+ Xpath 4096 " X: 0
+ else
+ Xpath 8192 " X: 8192
+ elseif 1 " aborts function
+ Xpath 16384 " X: 0
+ else
+ Xpath 32768 " X: 0
+ endif
+endfunction
+
+call F()
+call G()
+call H()
+call I()
+
+delfunction F
+delfunction G
+delfunction H
+delfunction I
+
+Xcheck 8722
+
+
+"-------------------------------------------------------------------------------
+" Test 17: Nesting of unmatched :if or :endif inside a :while {{{1
+"
+" The :while/:endwhile takes precedence in nesting over an unclosed
+" :if or an unopened :endif.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ let match = 1
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ let match = 0
+ if v:errmsg == ""
+ Xout "Message missing."
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Unexpected message:" v:errmsg
+ endif
+ endif
+ return match
+endfunction
+
+let messages = ""
+
+" While loops inside a function are continued on error.
+function! F()
+ let v:errmsg = ""
+ XloopINIT 1 16
+ let loops = 3
+ while loops > 0
+ let loops = loops - 1 " 2: 1: 0:
+ Xloop 1 " X: 1 + 1*16 + 1*16*16
+ if (loops == 1)
+ Xloop 2 " X: 2*16
+ XloopNEXT
+ continue
+ elseif (loops == 0)
+ Xloop 4 " X: 4*16*16
+ break
+ elseif 1
+ Xloop 8 " X: 8
+ XloopNEXT
+ " endif missing!
+ endwhile " :endwhile after :if 1
+ Xpath 4096 " X: 16*16*16
+ if MSG('E171', "Missing :endif")
+ let g:messages = g:messages . "A"
+ endif
+
+ let v:errmsg = ""
+ XloopINIT! 8192 4
+ let loops = 2
+ while loops > 0 " 2: 1:
+ XloopNEXT
+ let loops = loops - 1
+ Xloop 1 " X: 8192 + 8192*4
+ if 0
+ Xloop 2 " X: 0
+ " endif missing
+ endwhile " :endwhile after :if 0
+ Xpath 131072 " X: 8192*4*4
+ if MSG('E171', "Missing :endif")
+ let g:messages = g:messages . "B"
+ endif
+
+ let v:errmsg = ""
+ XloopINIT 262144 4
+ let loops = 2
+ while loops > 0 " 2: 1:
+ let loops = loops - 1
+ Xloop 1 " X: 262144 + 262144 * 4
+ " if missing!
+ endif " :endif without :if in while
+ Xloop 2 " X: 524288 + 524288 * 4
+ XloopNEXT
+ endwhile
+ Xpath 4194304 " X: 262144*4*4
+ if MSG('E580', ":endif without :if")
+ let g:messages = g:messages . "C"
+ endif
+endfunction
+
+call F()
+
+" Error continuation outside a function is at the outermost :endwhile or :endif.
+let v:errmsg = ""
+XloopINIT! 8388608 4
+let loops = 2
+while loops > 0 " 2: 1:
+ XloopNEXT
+ let loops = loops - 1
+ Xloop 1 " X: 8388608 + 0 * 4
+ if 0
+ Xloop 2 " X: 0
+ " endif missing! Following :endwhile fails.
+endwhile | Xpath 134217728 " X: 0
+Xpath 268435456 " X: 2*8388608*4*4
+if MSG('E171', "Missing :endif")
+ let messages = g:messages . "D"
+endif
+
+if messages != "ABCD"
+ Xpath 536870912 " X: 0
+ Xout "messages is" messages "instead of ABCD"
+endif
+
+unlet loops messages
+delfunction F
+delfunction MSG
+
+Xcheck 285127993
+
+
+"-------------------------------------------------------------------------------
+" Test 18: Interrupt (Ctrl-C pressed) {{{1
+"
+" On an interrupt, the script processing is terminated immediately.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ if 1
+ Xpath 1 " X: 1
+ while 1
+ Xpath 2 " X: 2
+ if 1
+ Xpath 4 " X: 4
+ "INTERRUPT
+ Xpath 8 " X: 0
+ break
+ finish
+ endif | Xpath 16 " X: 0
+ Xpath 32 " X: 0
+ endwhile | Xpath 64 " X: 0
+ Xpath 128 " X: 0
+ endif | Xpath 256 " X: 0
+ Xpath 512 " X: 0
+endif
+
+if ExtraVim()
+ try
+ Xpath 1024 " X: 1024
+ "INTERRUPT
+ Xpath 2048 " X: 0
+ endtry | Xpath 4096 " X: 0
+ Xpath 8192 " X: 0
+endif
+
+if ExtraVim()
+ function! F()
+ if 1
+ Xpath 16384 " X: 16384
+ while 1
+ Xpath 32768 " X: 32768
+ if 1
+ Xpath 65536 " X: 65536
+ "INTERRUPT
+ Xpath 131072 " X: 0
+ break
+ return
+ endif | Xpath 262144 " X: 0
+ Xpath Xpath 524288 " X: 0
+ endwhile | Xpath 1048576 " X: 0
+ Xpath Xpath 2097152 " X: 0
+ endif | Xpath Xpath 4194304 " X: 0
+ Xpath Xpath 8388608 " X: 0
+ endfunction
+
+ call F() | Xpath 16777216 " X: 0
+ Xpath 33554432 " X: 0
+endif
+
+if ExtraVim()
+ function! G()
+ try
+ Xpath 67108864 " X: 67108864
+ "INTERRUPT
+ Xpath 134217728 " X: 0
+ endtry | Xpath 268435456 " X: 0
+ Xpath 536870912 " X: 0
+ endfunction
+
+ call G() | Xpath 1073741824 " X: 0
+ " The Xpath command does not accept 2^31 (negative); display explicitly:
+ exec "!echo 2147483648 >>" . g:ExtraVimResult
+ " X: 0
+endif
+
+Xcheck 67224583
+
+
+"-------------------------------------------------------------------------------
+" Test 19: Aborting on errors inside :try/:endtry {{{1
+"
+" An error in a command dynamically enclosed in a :try/:endtry region
+" aborts script processing immediately. It does not matter whether
+" the failing command is outside or inside a function and whether a
+" function has an "abort" attribute.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ function! F() abort
+ Xpath 1 " X: 1
+ asdf
+ Xpath 2 " X: 0
+ endfunction
+
+ try
+ Xpath 4 " X: 4
+ call F()
+ Xpath 8 " X: 0
+ endtry | Xpath 16 " X: 0
+ Xpath 32 " X: 0
+endif
+
+if ExtraVim()
+ function! G()
+ Xpath 64 " X: 64
+ asdf
+ Xpath 128 " X: 0
+ endfunction
+
+ try
+ Xpath 256 " X: 256
+ call G()
+ Xpath 512 " X: 0
+ endtry | Xpath 1024 " X: 0
+ Xpath 2048 " X: 0
+endif
+
+if ExtraVim()
+ try
+ Xpath 4096 " X: 4096
+ asdf
+ Xpath 8192 " X: 0
+ endtry | Xpath 16384 " X: 0
+ Xpath 32768 " X: 0
+endif
+
+if ExtraVim()
+ if 1
+ try
+ Xpath 65536 " X: 65536
+ asdf
+ Xpath 131072 " X: 0
+ endtry | Xpath 262144 " X: 0
+ endif | Xpath 524288 " X: 0
+ Xpath 1048576 " X: 0
+endif
+
+if ExtraVim()
+ let p = 1
+ while p
+ let p = 0
+ try
+ Xpath 2097152 " X: 2097152
+ asdf
+ Xpath 4194304 " X: 0
+ endtry | Xpath 8388608 " X: 0
+ endwhile | Xpath 16777216 " X: 0
+ Xpath 33554432 " X: 0
+endif
+
+if ExtraVim()
+ let p = 1
+ while p
+ let p = 0
+" try
+ Xpath 67108864 " X: 67108864
+ endwhile | Xpath 134217728 " X: 0
+ Xpath 268435456 " X: 0
+endif
+
+Xcheck 69275973
+"-------------------------------------------------------------------------------
+" Test 20: Aborting on errors after :try/:endtry {{{1
+"
+" When an error occurs after the last active :try/:endtry region has
+" been left, termination behavior is as if no :try/:endtry has been
+" seen.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ let p = 1
+ while p
+ let p = 0
+ try
+ Xpath 1 " X: 1
+ endtry
+ asdf
+ endwhile | Xpath 2 " X: 0
+ Xpath 4 " X: 4
+endif
+
+if ExtraVim()
+ while 1
+ try
+ Xpath 8 " X: 8
+ break
+ Xpath 16 " X: 0
+ endtry
+ endwhile
+ Xpath 32 " X: 32
+ asdf
+ Xpath 64 " X: 64
+endif
+
+if ExtraVim()
+ while 1
+ try
+ Xpath 128 " X: 128
+ break
+ Xpath 256 " X: 0
+ finally
+ Xpath 512 " X: 512
+ endtry
+ endwhile
+ Xpath 1024 " X: 1024
+ asdf
+ Xpath 2048 " X: 2048
+endif
+
+if ExtraVim()
+ while 1
+ try
+ Xpath 4096 " X: 4096
+ finally
+ Xpath 8192 " X: 8192
+ break
+ Xpath 16384 " X: 0
+ endtry
+ endwhile
+ Xpath 32768 " X: 32768
+ asdf
+ Xpath 65536 " X: 65536
+endif
+
+if ExtraVim()
+ let p = 1
+ while p
+ let p = 0
+ try
+ Xpath 131072 " X: 131072
+ continue
+ Xpath 262144 " X: 0
+ endtry
+ endwhile
+ Xpath 524288 " X: 524288
+ asdf
+ Xpath 1048576 " X: 1048576
+endif
+
+if ExtraVim()
+ let p = 1
+ while p
+ let p = 0
+ try
+ Xpath 2097152 " X: 2097152
+ continue
+ Xpath 4194304 " X: 0
+ finally
+ Xpath 8388608 " X: 8388608
+ endtry
+ endwhile
+ Xpath 16777216 " X: 16777216
+ asdf
+ Xpath 33554432 " X: 33554432
+endif
+
+if ExtraVim()
+ let p = 1
+ while p
+ let p = 0
+ try
+ Xpath 67108864 " X: 67108864
+ finally
+ Xpath 134217728 " X: 134217728
+ continue
+ Xpath 268435456 " X: 0
+ endtry
+ endwhile
+ Xpath 536870912 " X: 536870912
+ asdf
+ Xpath 1073741824 " X: 1073741824
+endif
+
+Xcheck 1874575085
+
+
+"-------------------------------------------------------------------------------
+" Test 21: :finally for :try after :continue/:break/:return/:finish {{{1
+"
+" If a :try conditional stays inactive due to a preceding :continue,
+" :break, :return, or :finish, its :finally clause should not be
+" executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ function F()
+ let loops = 2
+ XloopINIT! 1 256
+ while loops > 0
+ XloopNEXT
+ let loops = loops - 1
+ try
+ if loops == 1
+ Xloop 1 " X: 1
+ continue
+ Xloop 2 " X: 0
+ elseif loops == 0
+ Xloop 4 " X: 4*256
+ break
+ Xloop 8 " X: 0
+ endif
+
+ try " inactive
+ Xloop 16 " X: 0
+ finally
+ Xloop 32 " X: 0
+ endtry
+ finally
+ Xloop 64 " X: 64 + 64*256
+ endtry
+ Xloop 128 " X: 0
+ endwhile
+
+ try
+ Xpath 65536 " X: 65536
+ return
+ Xpath 131072 " X: 0
+ try " inactive
+ Xpath 262144 " X: 0
+ finally
+ Xpath 524288 " X: 0
+ endtry
+ finally
+ Xpath 1048576 " X: 1048576
+ endtry
+ Xpath 2097152 " X: 0
+ endfunction
+
+ try
+ Xpath 4194304 " X: 4194304
+ call F()
+ Xpath 8388608 " X: 8388608
+ finish
+ Xpath 16777216 " X: 0
+ try " inactive
+ Xpath 33554432 " X: 0
+ finally
+ Xpath 67108864 " X: 0
+ endtry
+ finally
+ Xpath 134217728 " X: 134217728
+ endtry
+ Xpath 268435456 " X: 0
+endif
+
+Xcheck 147932225
+
+
+"-------------------------------------------------------------------------------
+" Test 22: :finally for a :try after an error/interrupt/:throw {{{1
+"
+" If a :try conditional stays inactive due to a preceding error or
+" interrupt or :throw, its :finally clause should not be executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ function! Error()
+ try
+ asdf " aborting error, triggering error exception
+ endtry
+ endfunction
+
+ Xpath 1 " X: 1
+ call Error()
+ Xpath 2 " X: 0
+
+ if 1 " not active due to error
+ try " not active since :if inactive
+ Xpath 4 " X: 0
+ finally
+ Xpath 8 " X: 0
+ endtry
+ endif
+
+ try " not active due to error
+ Xpath 16 " X: 0
+ finally
+ Xpath 32 " X: 0
+ endtry
+endif
+
+if ExtraVim()
+ function! Interrupt()
+ try
+ "INTERRUPT " triggering interrupt exception
+ endtry
+ endfunction
+
+ Xpath 64 " X: 64
+ call Interrupt()
+ Xpath 128 " X: 0
+
+ if 1 " not active due to interrupt
+ try " not active since :if inactive
+ Xpath 256 " X: 0
+ finally
+ Xpath 512 " X: 0
+ endtry
+ endif
+
+ try " not active due to interrupt
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 0
+ endtry
+endif
+
+if ExtraVim()
+ function! Throw()
+ throw "xyz"
+ endfunction
+
+ Xpath 4096 " X: 4096
+ call Throw()
+ Xpath 8192 " X: 0
+
+ if 1 " not active due to :throw
+ try " not active since :if inactive
+ Xpath 16384 " X: 0
+ finally
+ Xpath 32768 " X: 0
+ endtry
+ endif
+
+ try " not active due to :throw
+ Xpath 65536 " X: 0
+ finally
+ Xpath 131072 " X: 0
+ endtry
+endif
+
+Xcheck 4161
+
+
+"-------------------------------------------------------------------------------
+" Test 23: :catch clauses for a :try after a :throw {{{1
+"
+" If a :try conditional stays inactive due to a preceding :throw,
+" none of its :catch clauses should be executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ try
+ Xpath 1 " X: 1
+ throw "xyz"
+ Xpath 2 " X: 0
+
+ if 1 " not active due to :throw
+ try " not active since :if inactive
+ Xpath 4 " X: 0
+ catch /xyz/
+ Xpath 8 " X: 0
+ endtry
+ endif
+ catch /xyz/
+ Xpath 16 " X: 16
+ endtry
+
+ Xpath 32 " X: 32
+ throw "abc"
+ Xpath 64 " X: 0
+
+ try " not active due to :throw
+ Xpath 128 " X: 0
+ catch /abc/
+ Xpath 256 " X: 0
+ endtry
+endif
+
+Xcheck 49
+
+
+"-------------------------------------------------------------------------------
+" Test 24: :endtry for a :try after a :throw {{{1
+"
+" If a :try conditional stays inactive due to a preceding :throw,
+" its :endtry should not rethrow the exception to the next surrounding
+" active :try conditional.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ try " try 1
+ try " try 2
+ Xpath 1 " X: 1
+ throw "xyz" " makes try 2 inactive
+ Xpath 2 " X: 0
+
+ try " try 3
+ Xpath 4 " X: 0
+ endtry " no rethrow to try 1
+ catch /xyz/ " should catch although try 2 inactive
+ Xpath 8 " X: 8
+ endtry
+ catch /xyz/ " try 1 active, but exception already caught
+ Xpath 16 " X: 0
+ endtry
+ Xpath 32 " X: 32
+endif
+
+Xcheck 41
+
+
+"-------------------------------------------------------------------------------
+" Test 25: Executing :finally clauses on normal control flow {{{1
+"
+" Control flow in a :try conditional should always fall through to its
+" :finally clause. A :finally clause of a :try conditional inside an
+" inactive conditional should never be executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ let loops = 3
+ XloopINIT 1 256
+ while loops > 0 " 3: 2: 1:
+ Xloop 1 " X: 1 + 1*256 + 1*256*256
+ if loops >= 2
+ try
+ Xloop 2 " X: 2 + 2*256
+ if loops == 2
+ try
+ Xloop 4 " X: 4*256
+ finally
+ Xloop 8 " X: 8*256
+ endtry
+ endif
+ finally
+ Xloop 16 " X: 16 + 16*256
+ if loops == 2
+ try
+ Xloop 32 " X: 32*256
+ finally
+ Xloop 64 " X: 64*256
+ endtry
+ endif
+ endtry
+ endif
+ Xloop 128 " X: 128 + 128*256 + 128*256*256
+ let loops = loops - 1
+ XloopNEXT
+ endwhile
+ Xpath 16777216 " X: 16777216
+endfunction
+
+if 1
+ try
+ Xpath 33554432 " X: 33554432
+ call F()
+ Xpath 67108864 " X: 67108864
+ finally
+ Xpath 134217728 " X: 134217728
+ endtry
+else
+ try
+ Xpath 268435456 " X: 0
+ finally
+ Xpath 536870912 " X: 0
+ endtry
+endif
+
+delfunction F
+
+Xcheck 260177811
+
+
+"-------------------------------------------------------------------------------
+" Test 26: Executing :finally clauses after :continue or :break {{{1
+"
+" For a :continue or :break dynamically enclosed in a :try/:endtry
+" region inside the next surrounding :while/:endwhile, if the
+" :continue/:break is before the :finally, the :finally clause is
+" executed first. If the :continue/:break is after the :finally, the
+" :finally clause is broken (like an :if/:endif region).
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+try
+ let loops = 3
+ XloopINIT! 1 32
+ while loops > 0
+ XloopNEXT
+ try
+ try
+ if loops == 2 " 3: 2: 1:
+ Xloop 1 " X: 1*32
+ let loops = loops - 1
+ continue
+ elseif loops == 1
+ Xloop 2 " X: 2*32*32
+ break
+ finish
+ endif
+ Xloop 4 " X: 4
+ endtry
+ finally
+ Xloop 8 " X: 8 + 8*32 + 8*32*32
+ endtry
+ Xloop 16 " X: 16
+ let loops = loops - 1
+ endwhile
+ Xpath 32768 " X: 32768
+finally
+ Xpath 65536 " X: 65536
+ let loops = 3
+ XloopINIT 131072 16
+ while loops > 0
+ try
+ finally
+ try
+ if loops == 2
+ Xloop 1 " X: 131072*16
+ let loops = loops - 1
+ XloopNEXT
+ continue
+ elseif loops == 1
+ Xloop 2 " X: 131072*2*16*16
+ break
+ finish
+ endif
+ endtry
+ Xloop 4 " X: 131072*4
+ endtry
+ Xloop 8 " X: 131072*8
+ let loops = loops - 1
+ XloopNEXT
+ endwhile
+ Xpath 536870912 " X: 536870912
+endtry
+Xpath 1073741824 " X: 1073741824
+
+unlet loops
+
+Xcheck 1681500476
+
+
+"-------------------------------------------------------------------------------
+" Test 27: Executing :finally clauses after :return {{{1
+"
+" For a :return command dynamically enclosed in a :try/:endtry region,
+" :finally clauses are executed and the called function is ended.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ try
+ Xpath 1 " X: 1
+ try
+ Xpath 2 " X: 2
+ return
+ Xpath 4 " X: 0
+ finally
+ Xpath 8 " X: 8
+ endtry
+ Xpath 16 " X: 0
+ finally
+ Xpath 32 " X: 32
+ endtry
+ Xpath 64 " X: 0
+endfunction
+
+function! G()
+ try
+ Xpath 128 " X: 128
+ return
+ Xpath 256 " X: 0
+ finally
+ Xpath 512 " X: 512
+ call F()
+ Xpath 1024 " X: 1024
+ endtry
+ Xpath 2048 " X: 0
+endfunction
+
+function! H()
+ try
+ Xpath 4096 " X: 4096
+ call G()
+ Xpath 8192 " X: 8192
+ finally
+ Xpath 16384 " X: 16384
+ return
+ Xpath 32768 " X: 0
+ endtry
+ Xpath 65536 " X: 0
+endfunction
+
+try
+ Xpath 131072 " X: 131072
+ call H()
+ Xpath 262144 " X: 262144
+finally
+ Xpath 524288 " X: 524288
+endtry
+Xpath 1048576 " X: 1048576
+
+Xcheck 1996459
+
+" Leave F, G, and H for execution as scripts in the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 28: Executing :finally clauses after :finish {{{1
+"
+" For a :finish command dynamically enclosed in a :try/:endtry region,
+" :finally clauses are executed and the sourced file is finished.
+"
+" This test executes the bodies of the functions F, G, and H from the
+" previous test as script files (:return replaced by :finish).
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let scriptF = MakeScript("F") " X: 1 + 2 + 8 + 32
+let scriptG = MakeScript("G", scriptF) " X: 128 + 512 + 1024
+let scriptH = MakeScript("H", scriptG) " X: 4096 + 8192 + 16384
+
+try
+ Xpath 131072 " X: 131072
+ exec "source" scriptH
+ Xpath 262144 " X: 262144
+finally
+ Xpath 524288 " X: 524288
+endtry
+Xpath 1048576 " X: 1048576
+
+call delete(scriptF)
+call delete(scriptG)
+call delete(scriptH)
+unlet scriptF scriptG scriptH
+delfunction F
+delfunction G
+delfunction H
+
+Xcheck 1996459
+
+
+"-------------------------------------------------------------------------------
+" Test 29: Executing :finally clauses on errors {{{1
+"
+" After an error in a command dynamically enclosed in a :try/:endtry
+" region, :finally clauses are executed and the script processing is
+" terminated.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ function! F()
+ while 1
+ try
+ Xpath 1 " X: 1
+ while 1
+ try
+ Xpath 2 " X: 2
+ asdf " error
+ Xpath 4 " X: 0
+ finally
+ Xpath 8 " X: 8
+ endtry | Xpath 16 " X: 0
+ Xpath 32 " X: 0
+ break
+ endwhile
+ Xpath 64 " X: 0
+ finally
+ Xpath 128 " X: 128
+ endtry | Xpath 256 " X: 0
+ Xpath 512 " X: 0
+ break
+ endwhile
+ Xpath 1024 " X: 0
+ endfunction
+
+ while 1
+ try
+ Xpath 2048 " X: 2048
+ while 1
+ call F()
+ Xpath 4096 " X: 0
+ break
+ endwhile | Xpath 8192 " X: 0
+ Xpath 16384 " X: 0
+ finally
+ Xpath 32768 " X: 32768
+ endtry | Xpath 65536 " X: 0
+ endwhile | Xpath 131072 " X: 0
+ Xpath 262144 " X: 0
+endif
+
+if ExtraVim()
+ function! G() abort
+ if 1
+ try
+ Xpath 524288 " X: 524288
+ asdf " error
+ Xpath 1048576 " X: 0
+ finally
+ Xpath 2097152 " X: 2097152
+ endtry | Xpath 4194304 " X: 0
+ endif | Xpath 8388608 " X: 0
+ Xpath 16777216 " X: 0
+ endfunction
+
+ if 1
+ try
+ Xpath 33554432 " X: 33554432
+ call G()
+ Xpath 67108864 " X: 0
+ finally
+ Xpath 134217728 " X: 134217728
+ endtry | Xpath 268435456 " X: 0
+ endif | Xpath 536870912 " X: 0
+ Xpath 1073741824 " X: 0
+endif
+
+Xcheck 170428555
+
+
+"-------------------------------------------------------------------------------
+" Test 30: Executing :finally clauses on interrupt {{{1
+"
+" After an interrupt in a command dynamically enclosed in
+" a :try/:endtry region, :finally clauses are executed and the
+" script processing is terminated.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ XloopINIT 1 16
+
+ function! F()
+ try
+ Xloop 1 " X: 1 + 1*16
+ "INTERRUPT
+ Xloop 2 " X: 0
+ finally
+ Xloop 4 " X: 4 + 4*16
+ endtry
+ Xloop 8 " X: 0
+ endfunction
+
+ try
+ Xpath 256 " X: 256
+ try
+ Xpath 512 " X: 512
+ "INTERRUPT
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ try
+ Xpath 4096 " X: 4096
+ try
+ Xpath 8192 " X: 8192
+ finally
+ Xpath 16384 " X: 16384
+ try
+ Xpath 32768 " X: 32768
+ "INTERRUPT
+ Xpath 65536 " X: 0
+ endtry
+ Xpath 131072 " X: 0
+ endtry
+ Xpath 262144 " X: 0
+ endtry
+ Xpath 524288 " X: 0
+ endtry
+ Xpath 1048576 " X: 0
+ finally
+ Xpath 2097152 " X: 2097152
+ try
+ Xpath 4194304 " X: 4194304
+ call F()
+ Xpath 8388608 " X: 0
+ finally
+ Xpath 16777216 " X: 16777216
+ try
+ Xpath 33554432 " X: 33554432
+ XloopNEXT
+ ExecAsScript F
+ Xpath 67108864 " X: 0
+ finally
+ Xpath 134217728 " X: 134217728
+ endtry
+ Xpath 268435456 " X: 0
+ endtry
+ Xpath 536870912 " X: 0
+ endtry
+ Xpath 1073741824 " X: 0
+endif
+
+Xcheck 190905173
+
+
+"-------------------------------------------------------------------------------
+" Test 31: Executing :finally clauses after :throw {{{1
+"
+" After a :throw dynamically enclosed in a :try/:endtry region,
+" :finally clauses are executed and the script processing is
+" terminated.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ XloopINIT 1 16
+
+ function! F()
+ try
+ Xloop 1 " X: 1 + 1*16
+ throw "exception"
+ Xloop 2 " X: 0
+ finally
+ Xloop 4 " X: 4 + 4*16
+ endtry
+ Xloop 8 " X: 0
+ endfunction
+
+ try
+ Xpath 256 " X: 256
+ try
+ Xpath 512 " X: 512
+ throw "exception"
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ try
+ Xpath 4096 " X: 4096
+ try
+ Xpath 8192 " X: 8192
+ finally
+ Xpath 16384 " X: 16384
+ try
+ Xpath 32768 " X: 32768
+ throw "exception"
+ Xpath 65536 " X: 0
+ endtry
+ Xpath 131072 " X: 0
+ endtry
+ Xpath 262144 " X: 0
+ endtry
+ Xpath 524288 " X: 0
+ endtry
+ Xpath 1048576 " X: 0
+ finally
+ Xpath 2097152 " X: 2097152
+ try
+ Xpath 4194304 " X: 4194304
+ call F()
+ Xpath 8388608 " X: 0
+ finally
+ Xpath 16777216 " X: 16777216
+ try
+ Xpath 33554432 " X: 33554432
+ XloopNEXT
+ ExecAsScript F
+ Xpath 67108864 " X: 0
+ finally
+ Xpath 134217728 " X: 134217728
+ endtry
+ Xpath 268435456 " X: 0
+ endtry
+ Xpath 536870912 " X: 0
+ endtry
+ Xpath 1073741824 " X: 0
+endif
+
+Xcheck 190905173
+
+
+"-------------------------------------------------------------------------------
+" Test 32: Remembering the :return value on :finally {{{1
+"
+" If a :finally clause is executed due to a :return specifying
+" a value, this is the value visible to the caller if not overwritten
+" by a new :return in the :finally clause. A :return without a value
+" in the :finally clause overwrites with value 0.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ try
+ Xpath 1 " X: 1
+ try
+ Xpath 2 " X: 2
+ return "ABCD"
+ Xpath 4 " X: 0
+ finally
+ Xpath 8 " X: 8
+ endtry
+ Xpath 16 " X: 0
+ finally
+ Xpath 32 " X: 32
+ endtry
+ Xpath 64 " X: 0
+endfunction
+
+function! G()
+ try
+ Xpath 128 " X: 128
+ return 8
+ Xpath 256 " X: 0
+ finally
+ Xpath 512 " X: 512
+ return 16 + strlen(F())
+ Xpath 1024 " X: 0
+ endtry
+ Xpath 2048 " X: 0
+endfunction
+
+function! H()
+ try
+ Xpath 4096 " X: 4096
+ return 32
+ Xpath 8192 " X: 0
+ finally
+ Xpath 16384 " X: 16384
+ return
+ Xpath 32768 " X: 0
+ endtry
+ Xpath 65536 " X: 0
+endfunction
+
+function! I()
+ try
+ Xpath 131072 " X: 131072
+ finally
+ Xpath 262144 " X: 262144
+ return G() + H() + 64
+ Xpath 524288 " X: 0
+ endtry
+ Xpath 1048576 " X: 0
+endfunction
+
+let retcode = I()
+Xpath 2097152 " X: 2097152
+
+if retcode < 0
+ Xpath 4194304 " X: 0
+endif
+if retcode % 4
+ Xpath 8388608 " X: 0
+endif
+if (retcode/4) % 2
+ Xpath 16777216 " X: 16777216
+endif
+if (retcode/8) % 2
+ Xpath 33554432 " X: 0
+endif
+if (retcode/16) % 2
+ Xpath 67108864 " X: 67108864
+endif
+if (retcode/32) % 2
+ Xpath 134217728 " X: 0
+endif
+if (retcode/64) % 2
+ Xpath 268435456 " X: 268435456
+endif
+if retcode/128
+ Xpath 536870912 " X: 0
+endif
+
+unlet retcode
+delfunction F
+delfunction G
+delfunction H
+delfunction I
+
+Xcheck 354833067
+
+
+"-------------------------------------------------------------------------------
+" Test 33: :return under :execute or user command and :finally {{{1
+"
+" A :return command may be executed under an ":execute" or from
+" a user command. Executing of :finally clauses and passing through
+" the return code works also then.
+"-------------------------------------------------------------------------------
+XpathINIT
+
+command! -nargs=? RETURN
+ \ try | return <args> | finally | return <args> * 2 | endtry
+
+function! F()
+ try
+ RETURN 8
+ Xpath 1 " X: 0
+ finally
+ Xpath 2 " X: 2
+ endtry
+ Xpath 4 " X: 0
+endfunction
+
+function! G()
+ try
+ RETURN 32
+ Xpath 8 " X: 0
+ finally
+ Xpath 16 " X: 16
+ RETURN 128
+ Xpath 32 " X: 0
+ endtry
+ Xpath 64 " X: 0
+endfunction
+
+function! H()
+ try
+ execute "try | return 512 | finally | return 1024 | endtry"
+ Xpath 128 " X: 0
+ finally
+ Xpath 256 " X: 256
+ endtry
+ Xpath 512 " X: 0
+endfunction
+
+function! I()
+ try
+ execute "try | return 2048 | finally | return 4096 | endtry"
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ execute "try | return 8192 | finally | return 16384 | endtry"
+ Xpath 4096 " X: 0
+ endtry
+ Xpath 8192 " X: 0
+endfunction
+
+function! J()
+ try
+ RETURN 32768
+ Xpath 16384 " X: 0
+ finally
+ Xpath 32768 " X: 32768
+ return
+ Xpath 65536 " X: 0
+ endtry
+ Xpath 131072 " X: 0
+endfunction
+
+function! K()
+ try
+ execute "try | return 131072 | finally | return 262144 | endtry"
+ Xpath 262144 " X: 0
+ finally
+ Xpath 524288 " X: 524288
+ execute "try | return 524288 | finally | return | endtry"
+ Xpath 1048576 " X: 0
+ endtry
+ Xpath 2097152 " X: 0
+endfunction
+
+function! L()
+ try
+ return
+ Xpath 4194304 " X: 0
+ finally
+ Xpath 8388608 " X: 8388608
+ RETURN 1048576
+ Xpath 16777216 " X: 0
+ endtry
+ Xpath 33554432 " X: 0
+endfunction
+
+function! M()
+ try
+ return
+ Xpath 67108864 " X: 0
+ finally
+ Xpath 134217728 " X: 134217728
+ execute "try | return 4194304 | finally | return 8388608 | endtry"
+ Xpath 268435456 " X: 0
+ endtry
+ Xpath 536870912 " X: 0
+endfunction
+
+function! N()
+ RETURN 16777216
+endfunction
+
+function! O()
+ execute "try | return 67108864 | finally | return 134217728 | endtry"
+endfunction
+
+let sum = F() + G() + H() + I() + J() + K() + L() + M()
+let expected = 16 + 256 + 1024 + 16384 + 0 + 0 + 2097152 + 8388608
+let sum = sum + N() + O()
+let expected = expected + 33554432 + 134217728
+
+if sum == expected
+ Xout "sum = " . sum . " (ok)"
+else
+ Xout "sum = " . sum . ", expected: " . expected
+endif
+
+Xpath 1073741824 " X: 1073741824
+
+if sum != expected
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+endif
+
+unlet sum expected
+delfunction F
+delfunction G
+delfunction H
+delfunction I
+delfunction J
+delfunction K
+delfunction L
+delfunction M
+delfunction N
+delfunction O
+
+Xcheck 1216907538
+
+
+"-------------------------------------------------------------------------------
+" Test 34: :finally reason discarded by :continue {{{1
+"
+" When a :finally clause is executed due to a :continue, :break,
+" :return, :finish, error, interrupt or :throw, the jump reason is
+" discarded by a :continue in the finally clause.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ XloopINIT! 1 8
+
+ function! C(jump)
+ XloopNEXT
+ let loop = 0
+ while loop < 2
+ let loop = loop + 1
+ if loop == 1
+ try
+ if a:jump == "continue"
+ continue
+ elseif a:jump == "break"
+ break
+ elseif a:jump == "return" || a:jump == "finish"
+ return
+ elseif a:jump == "error"
+ asdf
+ elseif a:jump == "interrupt"
+ "INTERRUPT
+ let dummy = 0
+ elseif a:jump == "throw"
+ throw "abc"
+ endif
+ finally
+ continue " discards jump that caused the :finally
+ Xloop 1 " X: 0
+ endtry
+ Xloop 2 " X: 0
+ elseif loop == 2
+ Xloop 4 " X: 4*(1+8+64+512+4096+32768+262144)
+ endif
+ endwhile
+ endfunction
+
+ call C("continue")
+ Xpath 2097152 " X: 2097152
+ call C("break")
+ Xpath 4194304 " X: 4194304
+ call C("return")
+ Xpath 8388608 " X: 8388608
+ let g:jump = "finish"
+ ExecAsScript C
+ unlet g:jump
+ Xpath 16777216 " X: 16777216
+ try
+ call C("error")
+ Xpath 33554432 " X: 33554432
+ finally
+ Xpath 67108864 " X: 67108864
+ try
+ call C("interrupt")
+ Xpath 134217728 " X: 134217728
+ finally
+ Xpath 268435456 " X: 268435456
+ call C("throw")
+ Xpath 536870912 " X: 536870912
+ endtry
+ endtry
+ Xpath 1073741824 " X: 1073741824
+
+ delfunction C
+
+endif
+
+Xcheck 2146584868
+
+
+"-------------------------------------------------------------------------------
+" Test 35: :finally reason discarded by :break {{{1
+"
+" When a :finally clause is executed due to a :continue, :break,
+" :return, :finish, error, interrupt or :throw, the jump reason is
+" discarded by a :break in the finally clause.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ XloopINIT! 1 8
+
+ function! B(jump)
+ XloopNEXT
+ let loop = 0
+ while loop < 2
+ let loop = loop + 1
+ if loop == 1
+ try
+ if a:jump == "continue"
+ continue
+ elseif a:jump == "break"
+ break
+ elseif a:jump == "return" || a:jump == "finish"
+ return
+ elseif a:jump == "error"
+ asdf
+ elseif a:jump == "interrupt"
+ "INTERRUPT
+ let dummy = 0
+ elseif a:jump == "throw"
+ throw "abc"
+ endif
+ finally
+ break " discards jump that caused the :finally
+ Xloop 1 " X: 0
+ endtry
+ elseif loop == 2
+ Xloop 2 " X: 0
+ endif
+ endwhile
+ Xloop 4 " X: 4*(1+8+64+512+4096+32768+262144)
+ endfunction
+
+ call B("continue")
+ Xpath 2097152 " X: 2097152
+ call B("break")
+ Xpath 4194304 " X: 4194304
+ call B("return")
+ Xpath 8388608 " X: 8388608
+ let g:jump = "finish"
+ ExecAsScript B
+ unlet g:jump
+ Xpath 16777216 " X: 16777216
+ try
+ call B("error")
+ Xpath 33554432 " X: 33554432
+ finally
+ Xpath 67108864 " X: 67108864
+ try
+ call B("interrupt")
+ Xpath 134217728 " X: 134217728
+ finally
+ Xpath 268435456 " X: 268435456
+ call B("throw")
+ Xpath 536870912 " X: 536870912
+ endtry
+ endtry
+ Xpath 1073741824 " X: 1073741824
+
+ delfunction B
+
+endif
+
+Xcheck 2146584868
+
+
+"-------------------------------------------------------------------------------
+" Test 36: :finally reason discarded by :return {{{1
+"
+" When a :finally clause is executed due to a :continue, :break,
+" :return, :finish, error, interrupt or :throw, the jump reason is
+" discarded by a :return in the finally clause.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ XloopINIT! 1 8
+
+ function! R(jump, retval) abort
+ XloopNEXT
+ let loop = 0
+ while loop < 2
+ let loop = loop + 1
+ if loop == 1
+ try
+ if a:jump == "continue"
+ continue
+ elseif a:jump == "break"
+ break
+ elseif a:jump == "return"
+ return
+ elseif a:jump == "error"
+ asdf
+ elseif a:jump == "interrupt"
+ "INTERRUPT
+ let dummy = 0
+ elseif a:jump == "throw"
+ throw "abc"
+ endif
+ finally
+ return a:retval " discards jump that caused the :finally
+ Xloop 1 " X: 0
+ endtry
+ elseif loop == 2
+ Xloop 2 " X: 0
+ endif
+ endwhile
+ Xloop 4 " X: 0
+ endfunction
+
+ let sum = -R("continue", -8)
+ Xpath 2097152 " X: 2097152
+ let sum = sum - R("break", -16)
+ Xpath 4194304 " X: 4194304
+ let sum = sum - R("return", -32)
+ Xpath 8388608 " X: 8388608
+ try
+ let sum = sum - R("error", -64)
+ Xpath 16777216 " X: 16777216
+ finally
+ Xpath 33554432 " X: 33554432
+ try
+ let sum = sum - R("interrupt", -128)
+ Xpath 67108864 " X: 67108864
+ finally
+ Xpath 134217728 " X: 134217728
+ let sum = sum - R("throw", -256)
+ Xpath 268435456 " X: 268435456
+ endtry
+ endtry
+ Xpath 536870912 " X: 536870912
+
+ let expected = 8 + 16 + 32 + 64 + 128 + 256
+ if sum != expected
+ Xpath 1073741824 " X: 0
+ Xout "sum =" . sum . ", expected: " . expected
+ endif
+
+ unlet sum expected
+ delfunction R
+
+endif
+
+Xcheck 1071644672
+
+
+"-------------------------------------------------------------------------------
+" Test 37: :finally reason discarded by :finish {{{1
+"
+" When a :finally clause is executed due to a :continue, :break,
+" :return, :finish, error, interrupt or :throw, the jump reason is
+" discarded by a :finish in the finally clause.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ XloopINIT! 1 8
+
+ function! F(jump) " not executed as function, transformed to a script
+ XloopNEXT
+ let loop = 0
+ while loop < 2
+ let loop = loop + 1
+ if loop == 1
+ try
+ if a:jump == "continue"
+ continue
+ elseif a:jump == "break"
+ break
+ elseif a:jump == "finish"
+ finish
+ elseif a:jump == "error"
+ asdf
+ elseif a:jump == "interrupt"
+ "INTERRUPT
+ let dummy = 0
+ elseif a:jump == "throw"
+ throw "abc"
+ endif
+ finally
+ finish " discards jump that caused the :finally
+ Xloop 1 " X: 0
+ endtry
+ elseif loop == 2
+ Xloop 2 " X: 0
+ endif
+ endwhile
+ Xloop 4 " X: 0
+ endfunction
+
+ let scriptF = MakeScript("F")
+ delfunction F
+
+ let g:jump = "continue"
+ exec "source" scriptF
+ Xpath 2097152 " X: 2097152
+ let g:jump = "break"
+ exec "source" scriptF
+ Xpath 4194304 " X: 4194304
+ let g:jump = "finish"
+ exec "source" scriptF
+ Xpath 8388608 " X: 8388608
+ try
+ let g:jump = "error"
+ exec "source" scriptF
+ Xpath 16777216 " X: 16777216
+ finally
+ Xpath 33554432 " X: 33554432
+ try
+ let g:jump = "interrupt"
+ exec "source" scriptF
+ Xpath 67108864 " X: 67108864
+ finally
+ Xpath 134217728 " X: 134217728
+ try
+ let g:jump = "throw"
+ exec "source" scriptF
+ Xpath 268435456 " X: 268435456
+ finally
+ Xpath 536870912 " X: 536870912
+ endtry
+ endtry
+ endtry
+ unlet g:jump
+
+ call delete(scriptF)
+ unlet scriptF
+
+endif
+
+Xcheck 1071644672
+
+
+"-------------------------------------------------------------------------------
+" Test 38: :finally reason discarded by an error {{{1
+"
+" When a :finally clause is executed due to a :continue, :break,
+" :return, :finish, error, interrupt or :throw, the jump reason is
+" discarded by an error in the finally clause.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ XloopINIT! 1 4
+
+ function! E(jump)
+ XloopNEXT
+ let loop = 0
+ while loop < 2
+ let loop = loop + 1
+ if loop == 1
+ try
+ if a:jump == "continue"
+ continue
+ elseif a:jump == "break"
+ break
+ elseif a:jump == "return" || a:jump == "finish"
+ return
+ elseif a:jump == "error"
+ asdf
+ elseif a:jump == "interrupt"
+ "INTERRUPT
+ let dummy = 0
+ elseif a:jump == "throw"
+ throw "abc"
+ endif
+ finally
+ asdf " error; discards jump that caused the :finally
+ endtry
+ elseif loop == 2
+ Xloop 1 " X: 0
+ endif
+ endwhile
+ Xloop 2 " X: 0
+ endfunction
+
+ try
+ Xpath 16384 " X: 16384
+ call E("continue")
+ Xpath 32768 " X: 0
+ finally
+ try
+ Xpath 65536 " X: 65536
+ call E("break")
+ Xpath 131072 " X: 0
+ finally
+ try
+ Xpath 262144 " X: 262144
+ call E("return")
+ Xpath 524288 " X: 0
+ finally
+ try
+ Xpath 1048576 " X: 1048576
+ let g:jump = "finish"
+ ExecAsScript E
+ Xpath 2097152 " X: 0
+ finally
+ unlet g:jump
+ try
+ Xpath 4194304 " X: 4194304
+ call E("error")
+ Xpath 8388608 " X: 0
+ finally
+ try
+ Xpath 16777216 " X: 16777216
+ call E("interrupt")
+ Xpath 33554432 " X: 0
+ finally
+ try
+ Xpath 67108864 " X: 67108864
+ call E("throw")
+ Xpath 134217728 " X: 0
+ finally
+ Xpath 268435456 " X: 268435456
+ delfunction E
+ endtry
+ endtry
+ endtry
+ endtry
+ endtry
+ endtry
+ endtry
+ Xpath 536870912 " X: 0
+
+endif
+
+Xcheck 357908480
+
+
+"-------------------------------------------------------------------------------
+" Test 39: :finally reason discarded by an interrupt {{{1
+"
+" When a :finally clause is executed due to a :continue, :break,
+" :return, :finish, error, interrupt or :throw, the jump reason is
+" discarded by an interrupt in the finally clause.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ XloopINIT! 1 4
+
+ function! I(jump)
+ XloopNEXT
+ let loop = 0
+ while loop < 2
+ let loop = loop + 1
+ if loop == 1
+ try
+ if a:jump == "continue"
+ continue
+ elseif a:jump == "break"
+ break
+ elseif a:jump == "return" || a:jump == "finish"
+ return
+ elseif a:jump == "error"
+ asdf
+ elseif a:jump == "interrupt"
+ "INTERRUPT
+ let dummy = 0
+ elseif a:jump == "throw"
+ throw "abc"
+ endif
+ finally
+ "INTERRUPT - discards jump that caused the :finally
+ let dummy = 0
+ endtry
+ elseif loop == 2
+ Xloop 1 " X: 0
+ endif
+ endwhile
+ Xloop 2 " X: 0
+ endfunction
+
+ try
+ Xpath 16384 " X: 16384
+ call I("continue")
+ Xpath 32768 " X: 0
+ finally
+ try
+ Xpath 65536 " X: 65536
+ call I("break")
+ Xpath 131072 " X: 0
+ finally
+ try
+ Xpath 262144 " X: 262144
+ call I("return")
+ Xpath 524288 " X: 0
+ finally
+ try
+ Xpath 1048576 " X: 1048576
+ let g:jump = "finish"
+ ExecAsScript I
+ Xpath 2097152 " X: 0
+ finally
+ unlet g:jump
+ try
+ Xpath 4194304 " X: 4194304
+ call I("error")
+ Xpath 8388608 " X: 0
+ finally
+ try
+ Xpath 16777216 " X: 16777216
+ call I("interrupt")
+ Xpath 33554432 " X: 0
+ finally
+ try
+ Xpath 67108864 " X: 67108864
+ call I("throw")
+ Xpath 134217728 " X: 0
+ finally
+ Xpath 268435456 " X: 268435456
+ delfunction I
+ endtry
+ endtry
+ endtry
+ endtry
+ endtry
+ endtry
+ endtry
+ Xpath 536870912 " X: 0
+
+endif
+
+Xcheck 357908480
+
+
+"-------------------------------------------------------------------------------
+" Test 40: :finally reason discarded by :throw {{{1
+"
+" When a :finally clause is executed due to a :continue, :break,
+" :return, :finish, error, interrupt or :throw, the jump reason is
+" discarded by a :throw in the finally clause.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ XloopINIT! 1 4
+
+ function! T(jump)
+ XloopNEXT
+ let loop = 0
+ while loop < 2
+ let loop = loop + 1
+ if loop == 1
+ try
+ if a:jump == "continue"
+ continue
+ elseif a:jump == "break"
+ break
+ elseif a:jump == "return" || a:jump == "finish"
+ return
+ elseif a:jump == "error"
+ asdf
+ elseif a:jump == "interrupt"
+ "INTERRUPT
+ let dummy = 0
+ elseif a:jump == "throw"
+ throw "abc"
+ endif
+ finally
+ throw "xyz" " discards jump that caused the :finally
+ endtry
+ elseif loop == 2
+ Xloop 1 " X: 0
+ endif
+ endwhile
+ Xloop 2 " X: 0
+ endfunction
+
+ try
+ Xpath 16384 " X: 16384
+ call T("continue")
+ Xpath 32768 " X: 0
+ finally
+ try
+ Xpath 65536 " X: 65536
+ call T("break")
+ Xpath 131072 " X: 0
+ finally
+ try
+ Xpath 262144 " X: 262144
+ call T("return")
+ Xpath 524288 " X: 0
+ finally
+ try
+ Xpath 1048576 " X: 1048576
+ let g:jump = "finish"
+ ExecAsScript T
+ Xpath 2097152 " X: 0
+ finally
+ unlet g:jump
+ try
+ Xpath 4194304 " X: 4194304
+ call T("error")
+ Xpath 8388608 " X: 0
+ finally
+ try
+ Xpath 16777216 " X: 16777216
+ call T("interrupt")
+ Xpath 33554432 " X: 0
+ finally
+ try
+ Xpath 67108864 " X: 67108864
+ call T("throw")
+ Xpath 134217728 " X: 0
+ finally
+ Xpath 268435456 " X: 268435456
+ delfunction T
+ endtry
+ endtry
+ endtry
+ endtry
+ endtry
+ endtry
+ endtry
+ Xpath 536870912 " X: 0
+
+endif
+
+Xcheck 357908480
+
+
+"-------------------------------------------------------------------------------
+" Test 41: Skipped :throw finding next command {{{1
+"
+" A :throw in an inactive conditional must not hide a following
+" command.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ Xpath 1 " X: 1
+ if 0 | throw "never" | endif | Xpath 2 " X: 2
+ Xpath 4 " X: 4
+endfunction
+
+function! G()
+ Xpath 8 " X: 8
+ while 0 | throw "never" | endwhile | Xpath 16 " X: 16
+ Xpath 32 " X: 32
+endfunction
+
+function H()
+ Xpath 64 " X: 64
+ if 0 | try | throw "never" | endtry | endif | Xpath 128 " X: 128
+ Xpath 256 " X: 256
+endfunction
+
+Xpath 512 " X: 512
+
+try
+ Xpath 1024 " X: 1024
+ call F()
+ Xpath 2048 " X: 2048
+catch /.*/
+ Xpath 4096 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 8192 " X: 8192
+
+try
+ Xpath 16384 " X: 16384
+ call G()
+ Xpath 32768 " X: 32768
+catch /.*/
+ Xpath 65536 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 131072 " X: 131072
+
+try
+ Xpath 262144 " X: 262144
+ call H()
+ Xpath 524288 " X: 524288
+catch /.*/
+ Xpath 1048576 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 2097152 " X: 2097152
+
+delfunction F
+delfunction G
+delfunction H
+
+Xcheck 3076095
+
+
+"-------------------------------------------------------------------------------
+" Test 42: Catching number and string exceptions {{{1
+"
+" When a number is thrown, it is converted to a string exception.
+" Numbers and strings may be caught by specifying a regular exception
+" as argument to the :catch command.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+try
+
+ try
+ Xpath 1 " X: 1
+ throw 4711
+ Xpath 2 " X: 0
+ catch /4711/
+ Xpath 4 " X: 4
+ endtry
+
+ try
+ Xpath 8 " X: 8
+ throw 4711
+ Xpath 16 " X: 0
+ catch /^4711$/
+ Xpath 32 " X: 32
+ endtry
+
+ try
+ Xpath 64 " X: 64
+ throw 4711
+ Xpath 128 " X: 0
+ catch /\d/
+ Xpath 256 " X: 256
+ endtry
+
+ try
+ Xpath 512 " X: 512
+ throw 4711
+ Xpath 1024 " X: 0
+ catch /^\d\+$/
+ Xpath 2048 " X: 2048
+ endtry
+
+ try
+ Xpath 4096 " X: 4096
+ throw "arrgh"
+ Xpath 8192 " X: 0
+ catch /arrgh/
+ Xpath 16384 " X: 16384
+ endtry
+
+ try
+ Xpath 32768 " X: 32768
+ throw "arrgh"
+ Xpath 65536 " X: 0
+ catch /^arrgh$/
+ Xpath 131072 " X: 131072
+ endtry
+
+ try
+ Xpath 262144 " X: 262144
+ throw "arrgh"
+ Xpath 524288 " X: 0
+ catch /\l/
+ Xpath 1048576 " X: 1048576
+ endtry
+
+ try
+ Xpath 2097152 " X: 2097152
+ throw "arrgh"
+ Xpath 4194304 " X: 0
+ catch /^\l\+$/
+ Xpath 8388608 " X: 8388608
+ endtry
+
+ try
+ try
+ Xpath 16777216 " X: 16777216
+ throw "ARRGH"
+ Xpath 33554432 " X: 0
+ catch /^arrgh$/
+ Xpath 67108864 " X: 0
+ endtry
+ catch /^\carrgh$/
+ Xpath 134217728 " X: 134217728
+ endtry
+
+ try
+ Xpath 268435456 " X: 268435456
+ throw ""
+ Xpath 536870912 " X: 0
+ catch /^$/
+ Xpath 1073741824 " X: 1073741824
+ endtry
+
+catch /.*/
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xcheck 1505155949
+
+
+"-------------------------------------------------------------------------------
+" Test 43: Selecting the correct :catch clause {{{1
+"
+" When an exception is thrown and there are multiple :catch clauses,
+" the first matching one is taken.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT 1 1024
+let loops = 3
+while loops > 0
+ try
+ if loops == 3
+ Xloop 1 " X: 1
+ throw "a"
+ Xloop 2 " X: 0
+ elseif loops == 2
+ Xloop 4 " X: 4*1024
+ throw "ab"
+ Xloop 8 " X: 0
+ elseif loops == 1
+ Xloop 16 " X: 16*1024*1024
+ throw "abc"
+ Xloop 32 " X: 0
+ endif
+ catch /abc/
+ Xloop 64 " X: 64*1024*1024
+ catch /ab/
+ Xloop 128 " X: 128*1024
+ catch /.*/
+ Xloop 256 " X: 256
+ catch /a/
+ Xloop 512 " X: 0
+ endtry
+
+ let loops = loops - 1
+ XloopNEXT
+endwhile
+Xpath 1073741824 " X: 1073741824
+
+unlet loops
+
+Xcheck 1157763329
+
+
+"-------------------------------------------------------------------------------
+" Test 44: Missing or empty :catch patterns {{{1
+"
+" A missing or empty :catch pattern means the same as /.*/, that is,
+" catches everything. To catch only empty exceptions, /^$/ must be
+" used. A :catch with missing, empty, or /.*/ argument also works
+" when followed by another command separated by a bar on the same
+" line. :catch patterns cannot be specified between ||. But other
+" pattern separators can be used instead of //.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+try
+ try
+ Xpath 1 " X: 1
+ throw ""
+ catch /^$/
+ Xpath 2 " X: 2
+ endtry
+
+ try
+ Xpath 4 " X: 4
+ throw ""
+ catch /.*/
+ Xpath 8 " X: 8
+ endtry
+
+ try
+ Xpath 16 " X: 16
+ throw ""
+ catch //
+ Xpath 32 " X: 32
+ endtry
+
+ try
+ Xpath 64 " X: 64
+ throw ""
+ catch
+ Xpath 128 " X: 128
+ endtry
+
+ try
+ Xpath 256 " X: 256
+ throw "oops"
+ catch /^$/
+ Xpath 512 " X: 0
+ catch /.*/
+ Xpath 1024 " X: 1024
+ endtry
+
+ try
+ Xpath 2048 " X: 2048
+ throw "arrgh"
+ catch /^$/
+ Xpath 4096 " X: 0
+ catch //
+ Xpath 8192 " X: 8192
+ endtry
+
+ try
+ Xpath 16384 " X: 16384
+ throw "brrr"
+ catch /^$/
+ Xpath 32768 " X: 0
+ catch
+ Xpath 65536 " X: 65536
+ endtry
+
+ try | Xpath 131072 | throw "x" | catch /.*/ | Xpath 262144 | endtry
+ " X: 131072 + 262144
+
+ try | Xpath 524288 | throw "y" | catch // | Xpath 1048576 | endtry
+ " X: 524288 + 1048576
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ " Extra try level: if ":catch" without arguments below raises
+ " a syntax error because it misinterprets the "Xpath" as a pattern,
+ " let it be caught by the ":catch /.*/" below.
+ try
+ try | Xpath 2097152 | throw "z" | catch | Xpath 4194304 | :
+ endtry " X: 2097152 + 4194304
+ endtry
+ catch /.*/
+ let caught = 1
+ Xout v:exception "in" v:throwpoint
+ finally
+ if $VIMNOERRTHROW && v:errmsg != ""
+ Xout v:errmsg
+ endif
+ if caught || $VIMNOERRTHROW && v:errmsg != ""
+ Xpath 8388608 " X: 0
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ let cologne = 4711
+ try
+ try
+ Xpath 16777216 " X: 16777216
+ throw "throw cologne"
+ " Next lines catches all and throws 4711:
+ catch |throw cologne|
+ Xpath 33554432 " X: 0
+ endtry
+ catch /4711/
+ Xpath 67108864 " X: 67108864
+ endtry
+
+ try
+ Xpath 134217728 " X: 134217728
+ throw "plus"
+ catch +plus+
+ Xpath 268435456 " X: 268435456
+ endtry
+
+ Xpath 536870912 " X: 536870912
+catch /.*/
+ Xpath 1073741824 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+unlet! caught cologne
+
+Xcheck 1031761407
+
+
+"-------------------------------------------------------------------------------
+" Test 45: Catching exceptions from nested :try blocks {{{1
+"
+" When :try blocks are nested, an exception is caught by the innermost
+" try conditional that has a matching :catch clause.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT 1 1024
+let loops = 3
+while loops > 0
+ try
+ try
+ try
+ try
+ if loops == 3
+ Xloop 1 " X: 1
+ throw "a"
+ Xloop 2 " X: 0
+ elseif loops == 2
+ Xloop 4 " X: 4*1024
+ throw "ab"
+ Xloop 8 " X: 0
+ elseif loops == 1
+ Xloop 16 " X: 16*1024*1024
+ throw "abc"
+ Xloop 32 " X: 0
+ endif
+ catch /abc/
+ Xloop 64 " X: 64*1024*1024
+ endtry
+ catch /ab/
+ Xloop 128 " X: 128*1024
+ endtry
+ catch /.*/
+ Xloop 256 " X: 256
+ endtry
+ catch /a/
+ Xloop 512 " X: 0
+ endtry
+
+ let loops = loops - 1
+ XloopNEXT
+endwhile
+Xpath 1073741824 " X: 1073741824
+
+unlet loops
+
+Xcheck 1157763329
+
+
+"-------------------------------------------------------------------------------
+" Test 46: Executing :finally after a :throw in nested :try {{{1
+"
+" When an exception is thrown from within nested :try blocks, the
+" :finally clauses of the non-catching try conditionals should be
+" executed before the matching :catch of the next surrounding :try
+" gets the control. If this also has a :finally clause, it is
+" executed afterwards.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let sum = 0
+
+try
+ Xpath 1 " X: 1
+ try
+ Xpath 2 " X: 2
+ try
+ Xpath 4 " X: 4
+ try
+ Xpath 8 " X: 8
+ throw "ABC"
+ Xpath 16 " X: 0
+ catch /xyz/
+ Xpath 32 " X: 0
+ finally
+ Xpath 64 " X: 64
+ if sum != 0
+ Xpath 128 " X: 0
+ endif
+ let sum = sum + 1
+ endtry
+ Xpath 256 " X: 0
+ catch /123/
+ Xpath 512 " X: 0
+ catch /321/
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ if sum != 1
+ Xpath 4096 " X: 0
+ endif
+ let sum = sum + 2
+ endtry
+ Xpath 8192 " X: 0
+ finally
+ Xpath 16384 " X: 16384
+ if sum != 3
+ Xpath 32768 " X: 0
+ endif
+ let sum = sum + 4
+ endtry
+ Xpath 65536 " X: 0
+catch /ABC/
+ Xpath 131072 " X: 131072
+ if sum != 7
+ Xpath 262144 " X: 0
+ endif
+ let sum = sum + 8
+finally
+ Xpath 524288 " X: 524288
+ if sum != 15
+ Xpath 1048576 " X: 0
+ endif
+ let sum = sum + 16
+endtry
+Xpath 65536 " X: 65536
+if sum != 31
+ Xpath 131072 " X: 0
+endif
+
+unlet sum
+
+Xcheck 739407
+
+
+"-------------------------------------------------------------------------------
+" Test 47: Throwing exceptions from a :catch clause {{{1
+"
+" When an exception is thrown from a :catch clause, it should not be
+" caught by a :catch of the same :try conditional. After executing
+" the :finally clause (if present), surrounding try conditionals
+" should be checked for a matching :catch.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+Xpath 1 " X: 1
+try
+ Xpath 2 " X: 2
+ try
+ Xpath 4 " X: 4
+ try
+ Xpath 8 " X: 8
+ throw "x1"
+ Xpath 16 " X: 0
+ catch /x1/
+ Xpath 32 " X: 32
+ try
+ Xpath 64 " X: 64
+ throw "x2"
+ Xpath 128 " X: 0
+ catch /x1/
+ Xpath 256 " X: 0
+ catch /x2/
+ Xpath 512 " X: 512
+ try
+ Xpath 1024 " X: 1024
+ throw "x3"
+ Xpath 2048 " X: 0
+ catch /x1/
+ Xpath 4096 " X: 0
+ catch /x2/
+ Xpath 8192 " X: 0
+ finally
+ Xpath 16384 " X: 16384
+ endtry
+ Xpath 32768 " X: 0
+ catch /x3/
+ Xpath 65536 " X: 0
+ endtry
+ Xpath 131072 " X: 0
+ catch /x1/
+ Xpath 262144 " X: 0
+ catch /x2/
+ Xpath 524288 " X: 0
+ catch /x3/
+ Xpath 1048576 " X: 0
+ finally
+ Xpath 2097152 " X: 2097152
+ endtry
+ Xpath 4194304 " X: 0
+ catch /x1/
+ Xpath 8388608 " X: 0
+ catch /x2/
+ Xpath 16777216 " X: 0
+ catch /x3/
+ Xpath 33554432 " X: 33554432
+ endtry
+ Xpath 67108864 " X: 67108864
+catch /.*/
+ Xpath 134217728 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+Xpath 268435456 " X: 268435456
+
+Xcheck 371213935
+
+
+"-------------------------------------------------------------------------------
+" Test 48: Throwing exceptions from a :finally clause {{{1
+"
+" When an exception is thrown from a :finally clause, it should not be
+" caught by a :catch of the same :try conditional. Surrounding try
+" conditionals should be checked for a matching :catch. A previously
+" thrown exception is discarded.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+try
+
+ try
+ try
+ Xpath 1 " X: 1
+ catch /x1/
+ Xpath 2 " X: 0
+ finally
+ Xpath 4 " X: 4
+ throw "x1"
+ Xpath 8 " X: 0
+ endtry
+ Xpath 16 " X: 0
+ catch /x1/
+ Xpath 32 " X: 32
+ endtry
+ Xpath 64 " X: 64
+
+ try
+ try
+ Xpath 128 " X: 128
+ throw "x2"
+ Xpath 256 " X: 0
+ catch /x2/
+ Xpath 512 " X: 512
+ catch /x3/
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ throw "x3"
+ Xpath 4096 " X: 0
+ endtry
+ Xpath 8192 " X: 0
+ catch /x2/
+ Xpath 16384 " X: 0
+ catch /x3/
+ Xpath 32768 " X: 32768
+ endtry
+ Xpath 65536 " X: 65536
+
+ try
+ try
+ try
+ Xpath 131072 " X: 131072
+ throw "x4"
+ Xpath 262144 " X: 0
+ catch /x5/
+ Xpath 524288 " X: 0
+ finally
+ Xpath 1048576 " X: 1048576
+ throw "x5" " discards "x4"
+ Xpath 2097152 " X: 0
+ endtry
+ Xpath 4194304 " X: 0
+ catch /x4/
+ Xpath 8388608 " X: 0
+ finally
+ Xpath 16777216 " X: 16777216
+ endtry
+ Xpath 33554432 " X: 0
+ catch /x5/
+ Xpath 67108864 " X: 67108864
+ endtry
+ Xpath 134217728 " X: 134217728
+
+catch /.*/
+ Xpath 268435456 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+Xpath 536870912 " X: 536870912
+
+Xcheck 756255461
+
+
+"-------------------------------------------------------------------------------
+" Test 49: Throwing exceptions accross functions {{{1
+"
+" When an exception is thrown but not caught inside a function, the
+" caller is checked for a matching :catch clause.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! C()
+ try
+ Xpath 1 " X: 1
+ throw "arrgh"
+ Xpath 2 " X: 0
+ catch /arrgh/
+ Xpath 4 " X: 4
+ endtry
+ Xpath 8 " X: 8
+endfunction
+
+XloopINIT! 16 16
+
+function! T1()
+ XloopNEXT
+ try
+ Xloop 1 " X: 16 + 16*16
+ throw "arrgh"
+ Xloop 2 " X: 0
+ finally
+ Xloop 4 " X: 64 + 64*16
+ endtry
+ Xloop 8 " X: 0
+endfunction
+
+function! T2()
+ try
+ Xpath 4096 " X: 4096
+ call T1()
+ Xpath 8192 " X: 0
+ finally
+ Xpath 16384 " X: 16384
+ endtry
+ Xpath 32768 " X: 0
+endfunction
+
+try
+ Xpath 65536 " X: 65536
+ call C() " throw and catch
+ Xpath 131072 " X: 131072
+catch /.*/
+ Xpath 262144 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+try
+ Xpath 524288 " X: 524288
+ call T1() " throw, one level
+ Xpath 1048576 " X: 0
+catch /arrgh/
+ Xpath 2097152 " X: 2097152
+catch /.*/
+ Xpath 4194304 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+try
+ Xpath 8388608 " X: 8388608
+ call T2() " throw, two levels
+ Xpath 16777216 " X: 0
+catch /arrgh/
+ Xpath 33554432 " X: 33554432
+catch /.*/
+ Xpath 67108864 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+Xpath 134217728 " X: 134217728
+
+Xcheck 179000669
+
+" Leave C, T1, and T2 for execution as scripts in the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 50: Throwing exceptions accross script files {{{1
+"
+" When an exception is thrown but not caught inside a script file,
+" the sourcing script or function is checked for a matching :catch
+" clause.
+"
+" This test executes the bodies of the functions C, T1, and T2 from
+" the previous test as script files (:return replaced by :finish).
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let scriptC = MakeScript("C") " X: 1 + 4 + 8
+delfunction C
+
+XloopINIT! 16 16
+
+let scriptT1 = MakeScript("T1") " X: 16 + 64 + 16*16 + 64*16
+delfunction T1
+
+let scriptT2 = MakeScript("T2", scriptT1) " X: 4096 + 16384
+delfunction T2
+
+function! F()
+ try
+ Xpath 65536 " X: 65536
+ exec "source" g:scriptC
+ Xpath 131072 " X: 131072
+ catch /.*/
+ Xpath 262144 " X: 0
+ Xout v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 524288 " X: 524288
+ exec "source" g:scriptT1
+ Xpath 1048576 " X: 0
+ catch /arrgh/
+ Xpath 2097152 " X: 2097152
+ catch /.*/
+ Xpath 4194304 " X: 0
+ Xout v:exception "in" v:throwpoint
+ endtry
+endfunction
+
+try
+ Xpath 8388608 " X: 8388608
+ call F()
+ Xpath 16777216 " X: 16777216
+ exec "source" scriptT2
+ Xpath 33554432 " X: 0
+catch /arrgh/
+ Xpath 67108864 " X: 67108864
+catch /.*/
+ Xpath 134217728 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+Xpath 268435456 " X: 268435456
+
+call delete(scriptC)
+call delete(scriptT1)
+call delete(scriptT2)
+unlet scriptC scriptT1 scriptT2
+delfunction F
+
+Xcheck 363550045
+
+
+"-------------------------------------------------------------------------------
+" Test 51: Throwing exceptions accross :execute and user commands {{{1
+"
+" A :throw command may be executed under an ":execute" or from
+" a user command.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+command! -nargs=? THROW1 throw <args> | throw 1
+command! -nargs=? THROW2 try | throw <args> | endtry | throw 2
+command! -nargs=? THROW3 try | throw 3 | catch /3/ | throw <args> | endtry
+command! -nargs=? THROW4 try | throw 4 | finally | throw <args> | endtry
+
+try
+
+ try
+ try
+ Xpath 1 " X: 1
+ THROW1 "A"
+ catch /A/
+ Xpath 2 " X: 2
+ endtry
+ catch /1/
+ Xpath 4 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 8 " X: 8
+ THROW2 "B"
+ catch /B/
+ Xpath 16 " X: 16
+ endtry
+ catch /2/
+ Xpath 32 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 64 " X: 64
+ THROW3 "C"
+ catch /C/
+ Xpath 128 " X: 128
+ endtry
+ catch /3/
+ Xpath 256 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 512 " X: 512
+ THROW4 "D"
+ catch /D/
+ Xpath 1024 " X: 1024
+ endtry
+ catch /4/
+ Xpath 2048 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 4096 " X: 4096
+ execute 'throw "E" | throw 5'
+ catch /E/
+ Xpath 8192 " X: 8192
+ endtry
+ catch /5/
+ Xpath 16384 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 32768 " X: 32768
+ execute 'try | throw "F" | endtry | throw 6'
+ catch /F/
+ Xpath 65536 " X: 65536
+ endtry
+ catch /6/
+ Xpath 131072 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 262144 " X: 262144
+ execute'try | throw 7 | catch /7/ | throw "G" | endtry'
+ catch /G/
+ Xpath 524288 " X: 524288
+ endtry
+ catch /7/
+ Xpath 1048576 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 2097152 " X: 2097152
+ execute 'try | throw 8 | finally | throw "H" | endtry'
+ catch /H/
+ Xpath 4194304 " X: 4194304
+ endtry
+ catch /8/
+ Xpath 8388608 " X: 0
+ endtry
+
+catch /.*/
+ Xpath 16777216 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 33554432 " X: 33554432
+
+delcommand THROW1
+delcommand THROW2
+delcommand THROW3
+delcommand THROW4
+
+Xcheck 40744667
+
+
+"-------------------------------------------------------------------------------
+" Test 52: Uncaught exceptions {{{1
+"
+" When an exception is thrown but not caught, an error message is
+" displayed when the script is terminated. In case of an interrupt
+" or error exception, the normal interrupt or error message(s) are
+" displayed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let msgfile = tempname()
+
+function! MESSAGES(...)
+ try
+ exec "edit" g:msgfile
+ catch /^Vim(edit):/
+ return 0
+ endtry
+
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ let match = 1
+ norm gg
+
+ let num = a:0 / 2
+ let cnt = 1
+ while cnt <= num
+ let enr = a:{2*cnt - 1}
+ let emsg= a:{2*cnt}
+ let cnt = cnt + 1
+
+ if enr == ""
+ Xout "TODO: Add message number for:" emsg
+ elseif enr == "INT"
+ let enr = ""
+ endif
+ if enr == "" && !english
+ continue
+ endif
+ let pattern = (enr != "") ? enr . ':.*' : ''
+ if english
+ let pattern = pattern . emsg
+ endif
+ if !search(pattern, "W")
+ let match = 0
+ Xout "No match for:" pattern
+ endif
+ norm $
+ endwhile
+
+ bwipeout!
+ return match
+endfunction
+
+if ExtraVim(msgfile)
+ Xpath 1 " X: 1
+ throw "arrgh"
+endif
+
+Xpath 2 " X: 2
+if !MESSAGES('E605', "Exception not caught")
+ Xpath 4 " X: 0
+endif
+
+if ExtraVim(msgfile)
+ try
+ Xpath 8 " X: 8
+ throw "oops"
+ catch /arrgh/
+ Xpath 16 " X: 0
+ endtry
+ Xpath 32 " X: 0
+endif
+
+Xpath 64 " X: 64
+if !MESSAGES('E605', "Exception not caught")
+ Xpath 128 " X: 0
+endif
+
+if ExtraVim(msgfile)
+ function! T()
+ throw "brrr"
+ endfunction
+
+ try
+ Xpath 256 " X: 256
+ throw "arrgh"
+ catch /.*/
+ Xpath 512 " X: 512
+ call T()
+ endtry
+ Xpath 1024 " X: 0
+endif
+
+Xpath 2048 " X: 2048
+if !MESSAGES('E605', "Exception not caught")
+ Xpath 4096 " X: 0
+endif
+
+if ExtraVim(msgfile)
+ try
+ Xpath 8192 " X: 8192
+ throw "arrgh"
+ finally
+ Xpath 16384 " X: 16384
+ throw "brrr"
+ endtry
+ Xpath 32768 " X: 0
+endif
+
+Xpath 65536 " X: 65536
+if !MESSAGES('E605', "Exception not caught")
+ Xpath 131072 " X: 0
+endif
+
+if ExtraVim(msgfile)
+ try
+ Xpath 262144 " X: 262144
+ "INTERRUPT
+ endtry
+ Xpath 524288 " X: 0
+endif
+
+Xpath 1048576 " X: 1048576
+if !MESSAGES('INT', "Interrupted")
+ Xpath 2097152 " X: 0
+endif
+
+if ExtraVim(msgfile)
+ try
+ Xpath 4194304 " X: 4194304
+ let x = novar " error E121/E15; exception: E121
+ catch /E15:/ " should not catch
+ Xpath 8388608 " X: 0
+ endtry
+ Xpath 16777216 " X: 0
+endif
+
+Xpath 33554432 " X: 33554432
+if !MESSAGES('E121', "Undefined variable", 'E15', "Invalid expression")
+ Xpath 67108864 " X: 0
+endif
+
+if ExtraVim(msgfile)
+ try
+ Xpath 134217728 " X: 134217728
+" unlet novar # " error E108/E488; exception: E488
+ catch /E108:/ " should not catch
+ Xpath 268435456 " X: 0
+ endtry
+ Xpath 536870912 " X: 0
+endif
+
+Xpath 1073741824 " X: 1073741824
+if !MESSAGES('E108', "No such variable", 'E488', "Trailing characters")
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+endif
+
+call delete(msgfile)
+unlet msgfile
+
+Xcheck 1247112011
+
+" Leave MESSAGES() for the next tests.
+
+
+"-------------------------------------------------------------------------------
+" Test 53: Nesting errors: :endif/:else/:elseif {{{1
+"
+" For nesting errors of :if conditionals the correct error messages
+" should be given.
+"
+" This test reuses the function MESSAGES() from the previous test.
+" This functions checks the messages in g:msgfile.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let msgfile = tempname()
+
+if ExtraVim(msgfile)
+" endif
+endif
+if MESSAGES('E580', ":endif without :if")
+ Xpath 1 " X: 1
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" endif
+" endwhile
+endif
+if MESSAGES('E580', ":endif without :if")
+ Xpath 2 " X: 2
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" endif
+" endtry
+endif
+if MESSAGES('E580', ":endif without :if")
+ Xpath 4 " X: 4
+endif
+
+if ExtraVim(msgfile)
+" try
+" endif
+" endtry
+endif
+if MESSAGES('E580', ":endif without :if")
+ Xpath 8 " X: 8
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" endif
+" endtry
+endif
+if MESSAGES('E580', ":endif without :if")
+ Xpath 16 " X: 16
+endif
+
+if ExtraVim(msgfile)
+" else
+endif
+if MESSAGES('E581', ":else without :if")
+ Xpath 32 " X: 32
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" else
+" endwhile
+endif
+if MESSAGES('E581', ":else without :if")
+ Xpath 64 " X: 64
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" else
+" endtry
+endif
+if MESSAGES('E581', ":else without :if")
+ Xpath 128 " X: 128
+endif
+
+if ExtraVim(msgfile)
+" try
+" else
+" endtry
+endif
+if MESSAGES('E581', ":else without :if")
+ Xpath 256 " X: 256
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" else
+" endtry
+endif
+if MESSAGES('E581', ":else without :if")
+ Xpath 512 " X: 512
+endif
+
+if ExtraVim(msgfile)
+" elseif
+endif
+if MESSAGES('E582', ":elseif without :if")
+ Xpath 1024 " X: 1024
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" elseif
+" endwhile
+endif
+if MESSAGES('E582', ":elseif without :if")
+ Xpath 2048 " X: 2048
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" elseif
+" endtry
+endif
+if MESSAGES('E582', ":elseif without :if")
+ Xpath 4096 " X: 4096
+endif
+
+if ExtraVim(msgfile)
+" try
+" elseif
+" endtry
+endif
+if MESSAGES('E582', ":elseif without :if")
+ Xpath 8192 " X: 8192
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" elseif
+" endtry
+endif
+if MESSAGES('E582', ":elseif without :if")
+ Xpath 16384 " X: 16384
+endif
+
+if ExtraVim(msgfile)
+" if 1
+" else
+" else
+" endif
+endif
+if MESSAGES('E583', "multiple :else")
+ Xpath 32768 " X: 32768
+endif
+
+if ExtraVim(msgfile)
+" if 1
+" else
+" elseif 1
+" endif
+endif
+if MESSAGES('E584', ":elseif after :else")
+ Xpath 65536 " X: 65536
+endif
+
+call delete(msgfile)
+unlet msgfile
+
+Xcheck 131071
+
+" Leave MESSAGES() for the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 54: Nesting errors: :while/:endwhile {{{1
+"
+" For nesting errors of :while conditionals the correct error messages
+" should be given.
+"
+" This test reuses the function MESSAGES() from the previous test.
+" This functions checks the messages in g:msgfile.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let msgfile = tempname()
+
+if ExtraVim(msgfile)
+" endwhile
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 1 " X: 1
+endif
+
+if ExtraVim(msgfile)
+" if 1
+" endwhile
+" endif
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 2 " X: 2
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" if 1
+" endwhile
+endif
+if MESSAGES('E171', "Missing :endif")
+ Xpath 4 " X: 4
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" endwhile
+" endtry
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 8 " X: 8
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" try
+" finally
+" endwhile
+endif
+if MESSAGES('E600', "Missing :endtry")
+ Xpath 16 " X: 16
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" if 1
+" try
+" finally
+" endwhile
+endif
+if MESSAGES('E600', "Missing :endtry")
+ Xpath 32 " X: 32
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" try
+" finally
+" if 1
+" endwhile
+endif
+if MESSAGES('E171', "Missing :endif")
+ Xpath 64 " X: 64
+endif
+
+if ExtraVim(msgfile)
+" try
+" endwhile
+" endtry
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 128 " X: 128
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" try
+" endwhile
+" endtry
+" endwhile
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 256 " X: 256
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" endwhile
+" endtry
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 512 " X: 512
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" try
+" throw "a"
+" catch /a/
+" endwhile
+" endtry
+" endwhile
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 1024 " X: 1024
+endif
+
+
+call delete(msgfile)
+unlet msgfile
+
+Xcheck 2047
+
+" Leave MESSAGES() for the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 55: Nesting errors: :continue/:break {{{1
+"
+" For nesting errors of :continue and :break commands the correct
+" error messages should be given.
+"
+" This test reuses the function MESSAGES() from the previous test.
+" This functions checks the messages in g:msgfile.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let msgfile = tempname()
+
+if ExtraVim(msgfile)
+" continue
+endif
+if MESSAGES('E586', ":continue without :while")
+ Xpath 1 " X: 1
+endif
+
+if ExtraVim(msgfile)
+" if 1
+" continue
+" endif
+endif
+if MESSAGES('E586', ":continue without :while")
+ Xpath 2 " X: 2
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" continue
+" endtry
+endif
+if MESSAGES('E586', ":continue without :while")
+ Xpath 4 " X: 4
+endif
+
+if ExtraVim(msgfile)
+" try
+" continue
+" endtry
+endif
+if MESSAGES('E586', ":continue without :while")
+ Xpath 8 " X: 8
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" continue
+" endtry
+endif
+if MESSAGES('E586', ":continue without :while")
+ Xpath 16 " X: 16
+endif
+
+if ExtraVim(msgfile)
+" break
+endif
+if MESSAGES('E587', ":break without :while")
+ Xpath 32 " X: 32
+endif
+
+if ExtraVim(msgfile)
+" if 1
+" break
+" endif
+endif
+if MESSAGES('E587', ":break without :while")
+ Xpath 64 " X: 64
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" break
+" endtry
+endif
+if MESSAGES('E587', ":break without :while")
+ Xpath 128 " X: 128
+endif
+
+if ExtraVim(msgfile)
+" try
+" break
+" endtry
+endif
+if MESSAGES('E587', ":break without :while")
+ Xpath 256 " X: 256
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" break
+" endtry
+endif
+if MESSAGES('E587', ":break without :while")
+ Xpath 512 " X: 512
+endif
+
+call delete(msgfile)
+unlet msgfile
+
+Xcheck 1023
+
+" Leave MESSAGES() for the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 56: Nesting errors: :endtry {{{1
+"
+" For nesting errors of :try conditionals the correct error messages
+" should be given.
+"
+" This test reuses the function MESSAGES() from the previous test.
+" This functions checks the messages in g:msgfile.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let msgfile = tempname()
+
+if ExtraVim(msgfile)
+" endtry
+endif
+if MESSAGES('E602', ":endtry without :try")
+ Xpath 1 " X: 1
+endif
+
+if ExtraVim(msgfile)
+" if 1
+" endtry
+" endif
+endif
+if MESSAGES('E602', ":endtry without :try")
+ Xpath 2 " X: 2
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" endtry
+" endwhile
+endif
+if MESSAGES('E602', ":endtry without :try")
+ Xpath 4 " X: 4
+endif
+
+if ExtraVim(msgfile)
+" try
+" if 1
+" endtry
+endif
+if MESSAGES('E171', "Missing :endif")
+ Xpath 8 " X: 8
+endif
+
+if ExtraVim(msgfile)
+" try
+" while 1
+" endtry
+endif
+if MESSAGES('E170', "Missing :endwhile")
+ Xpath 16 " X: 16
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" if 1
+" endtry
+endif
+if MESSAGES('E171', "Missing :endif")
+ Xpath 32 " X: 32
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" while 1
+" endtry
+endif
+if MESSAGES('E170', "Missing :endwhile")
+ Xpath 64 " X: 64
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" if 1
+" endtry
+endif
+if MESSAGES('E171', "Missing :endif")
+ Xpath 128 " X: 128
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" while 1
+" endtry
+endif
+if MESSAGES('E170', "Missing :endwhile")
+ Xpath 256 " X: 256
+endif
+
+call delete(msgfile)
+unlet msgfile
+
+delfunction MESSAGES
+
+Xcheck 511
+
+
+"-------------------------------------------------------------------------------
+" Test 57: v:exception and v:throwpoint for user exceptions {{{1
+"
+" v:exception evaluates to the value of the exception that was caught
+" most recently and is not finished. (A caught exception is finished
+" when the next ":catch", ":finally", or ":endtry" is reached.)
+" v:throwpoint evaluates to the script/function name and line number
+" where that exception has been thrown.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! FuncException()
+ let g:exception = v:exception
+endfunction
+
+function! FuncThrowpoint()
+ let g:throwpoint = v:throwpoint
+endfunction
+
+let scriptException = MakeScript("FuncException")
+let scriptThrowPoint = MakeScript("FuncThrowpoint")
+
+command! CmdException let g:exception = v:exception
+command! CmdThrowpoint let g:throwpoint = v:throwpoint
+
+XloopINIT! 1 2
+
+function! CHECK(n, exception, throwname, throwline)
+ XloopNEXT
+ let error = 0
+ if v:exception != a:exception
+ Xout a:n.": v:exception is" v:exception "instead of" a:exception
+ let error = 1
+ endif
+ if v:throwpoint !~ a:throwname
+ let name = escape(a:throwname, '\')
+ Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" name
+ let error = 1
+ endif
+ if v:throwpoint !~ a:throwline
+ let line = escape(a:throwline, '\')
+ Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line
+ let error = 1
+ endif
+ if error
+ Xloop 1 " X: 0
+ endif
+endfunction
+
+function! T(arg, line)
+ if a:line == 2
+ throw a:arg " in line 2
+ elseif a:line == 4
+ throw a:arg " in line 4
+ elseif a:line == 6
+ throw a:arg " in line 6
+ elseif a:line == 8
+ throw a:arg " in line 8
+ endif
+endfunction
+
+function! G(arg, line)
+ call T(a:arg, a:line)
+endfunction
+
+function! F(arg, line)
+ call G(a:arg, a:line)
+endfunction
+
+let scriptT = MakeScript("T")
+let scriptG = MakeScript("G", scriptT)
+let scriptF = MakeScript("F", scriptG)
+
+try
+ Xpath 32768 " X: 32768
+ call F("oops", 2)
+catch /.*/
+ Xpath 65536 " X: 65536
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(1, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ exec "let exception = v:exception"
+ exec "let throwpoint = v:throwpoint"
+ call CHECK(2, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ CmdException
+ CmdThrowpoint
+ call CHECK(3, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ call FuncException()
+ call FuncThrowpoint()
+ call CHECK(4, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ exec "source" scriptException
+ exec "source" scriptThrowPoint
+ call CHECK(5, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ try
+ Xpath 131072 " X: 131072
+ call G("arrgh", 4)
+ catch /.*/
+ Xpath 262144 " X: 262144
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(6, "arrgh", '\<G\.\.T\>', '\<4\>')
+ try
+ Xpath 524288 " X: 524288
+ let g:arg = "autsch"
+ let g:line = 6
+ exec "source" scriptF
+ catch /.*/
+ Xpath 1048576 " X: 1048576
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ " Symbolic links in tempname()s are not resolved, whereas resolving
+ " is done for v:throwpoint. Resolve the temporary file name for
+ " scriptT, so that it can be matched against v:throwpoint.
+ call CHECK(7, "autsch", resolve(scriptT), '\<6\>')
+ finally
+ Xpath 2097152 " X: 2097152
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(8, "arrgh", '\<G\.\.T\>', '\<4\>')
+ try
+ Xpath 4194304 " X: 4194304
+ let g:arg = "brrrr"
+ let g:line = 8
+ exec "source" scriptG
+ catch /.*/
+ Xpath 8388608 " X: 8388608
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ " Resolve scriptT for matching it against v:throwpoint.
+ call CHECK(9, "brrrr", resolve(scriptT), '\<8\>')
+ finally
+ Xpath 16777216 " X: 16777216
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(10, "arrgh", '\<G\.\.T\>', '\<4\>')
+ endtry
+ Xpath 33554432 " X: 33554432
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(11, "arrgh", '\<G\.\.T\>', '\<4\>')
+ endtry
+ Xpath 67108864 " X: 67108864
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(12, "arrgh", '\<G\.\.T\>', '\<4\>')
+ finally
+ Xpath 134217728 " X: 134217728
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(13, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ endtry
+ Xpath 268435456 " X: 268435456
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(14, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+finally
+ Xpath 536870912 " X: 536870912
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(15, "", '^$', '^$')
+endtry
+
+Xpath 1073741824 " X: 1073741824
+
+unlet exception throwpoint
+delfunction FuncException
+delfunction FuncThrowpoint
+call delete(scriptException)
+call delete(scriptThrowPoint)
+unlet scriptException scriptThrowPoint
+delcommand CmdException
+delcommand CmdThrowpoint
+delfunction T
+delfunction G
+delfunction F
+call delete(scriptT)
+call delete(scriptG)
+call delete(scriptF)
+unlet scriptT scriptG scriptF
+
+Xcheck 2147450880
+
+
+"-------------------------------------------------------------------------------
+"
+" Test 58: v:exception and v:throwpoint for error/interrupt exceptions {{{1
+"
+" v:exception and v:throwpoint work also for error and interrupt
+" exceptions.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ function! T(line)
+ if a:line == 2
+ delfunction T " error (function in use) in line 2
+ elseif a:line == 4
+ let dummy = 0 " INTERRUPT1 - interrupt in line 4
+ endif
+ endfunction
+
+ while 1
+ try
+ Xpath 1 " X: 1
+ let caught = 0
+ call T(2)
+ catch /.*/
+ let caught = 1
+ if v:exception !~ 'Vim(delfunction):'
+ Xpath 2 " X: 0
+ endif
+ if v:throwpoint !~ '\<T\>'
+ Xpath 4 " X: 0
+ endif
+ if v:throwpoint !~ '\<2\>'
+ Xpath 8 " X: 0
+ endif
+ finally
+ Xpath 16 " X: 16
+ if caught || $VIMNOERRTHROW
+ Xpath 32 " X: 32
+ endif
+ if v:exception != ""
+ Xpath 64 " X: 0
+ endif
+ if v:throwpoint != ""
+ Xpath 128 " X: 0
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ Xpath 256 " X: 256
+ if v:exception != ""
+ Xpath 512 " X: 0
+ endif
+ if v:throwpoint != ""
+ Xpath 1024 " X: 0
+ endif
+
+ while 1
+ try
+ Xpath 2048 " X: 2048
+ let caught = 0
+ call T(4)
+ catch /.*/
+ let caught = 1
+ if v:exception != 'Vim:Interrupt'
+ Xpath 4096 " X: 0
+ endif
+ if v:throwpoint !~ '\<T\>'
+ Xpath 8192 " X: 0
+ endif
+ if v:throwpoint !~ '\<4\>'
+ Xpath 16384 " X: 0
+ endif
+ finally
+ Xpath 32768 " X: 32768
+ if caught || $VIMNOINTTHROW
+ Xpath 65536 " X: 65536
+ endif
+ if v:exception != ""
+ Xpath 131072 " X: 0
+ endif
+ if v:throwpoint != ""
+ Xpath 262144 " X: 0
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ Xpath 524288 " X: 524288
+ if v:exception != ""
+ Xpath 1048576 " X: 0
+ endif
+ if v:throwpoint != ""
+ Xpath 2097152 " X: 0
+ endif
+
+endif
+
+Xcheck 624945
+
+
+"-------------------------------------------------------------------------------
+"
+" Test 59: v:exception and v:throwpoint when discarding exceptions {{{1
+"
+" When a :catch clause is left by a ":break" etc or an error or
+" interrupt exception, v:exception and v:throwpoint are reset. They
+" are not affected by an exception that is discarded before being
+" caught.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ XloopINIT! 1 2
+
+ let sfile = expand("<sfile>")
+
+ function! LineNumber()
+ return substitute(substitute(v:throwpoint, g:sfile, '', ""),
+ \ '\D*\(\d*\).*', '\1', "")
+ endfunction
+
+ command! -nargs=1 SetLineNumber
+ \ try | throw "line" | catch /.*/ | let <args> = LineNumber() | endtry
+
+ " Check v:exception/v:throwpoint against second/fourth parameter if
+ " specified, check for being empty else.
+ function! CHECK(n, ...)
+ XloopNEXT
+ let exception = a:0 != 0 ? a:1 : "" " second parameter (optional)
+ let emsg = a:0 != 0 ? a:2 : "" " third parameter (optional)
+ let line = a:0 != 0 ? a:3 : 0 " fourth parameter (optional)
+ let error = 0
+ if emsg != ""
+ " exception is the error number, emsg the english error message text
+ if exception !~ '^E\d\+$'
+ Xout "TODO: Add message number for:" emsg
+ elseif v:lang == "C" || v:lang =~ '^[Ee]n'
+ if exception == "E492" && emsg == "Not an editor command"
+ let exception = '^Vim:' . exception . ': ' . emsg
+ else
+ let exception = '^Vim(\a\+):' . exception . ': ' . emsg
+ endif
+ else
+ if exception == "E492"
+ let exception = '^Vim:' . exception
+ else
+ let exception = '^Vim(\a\+):' . exception
+ endif
+ endif
+ endif
+ if exception == "" && v:exception != ""
+ Xout a:n.": v:exception is set:" v:exception
+ let error = 1
+ elseif exception != "" && v:exception !~ exception
+ Xout a:n.": v:exception (".v:exception.") does not match" exception
+ let error = 1
+ endif
+ if line == 0 && v:throwpoint != ""
+ Xout a:n.": v:throwpoint is set:" v:throwpoint
+ let error = 1
+ elseif line != 0 && v:throwpoint !~ '\<' . line . '\>'
+ Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line
+ let error = 1
+ endif
+ if !error
+ Xloop 1 " X: 2097151
+ endif
+ endfunction
+
+ while 1
+ try
+ throw "x1"
+ catch /.*/
+ break
+ endtry
+ endwhile
+ call CHECK(1)
+
+ while 1
+ try
+ throw "x2"
+ catch /.*/
+ break
+ finally
+ call CHECK(2)
+ endtry
+ break
+ endwhile
+ call CHECK(3)
+
+ while 1
+ try
+ let errcaught = 0
+ try
+ try
+ throw "x3"
+ catch /.*/
+ SetLineNumber line_before_error
+ asdf
+ endtry
+ catch /.*/
+ let errcaught = 1
+ call CHECK(4, 'E492', "Not an editor command",
+ \ line_before_error + 1)
+ endtry
+ finally
+ if !errcaught && $VIMNOERRTHROW
+ call CHECK(4)
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ call CHECK(5)
+
+ Xpath 2097152 " X: 2097152
+
+ while 1
+ try
+ let intcaught = 0
+ try
+ try
+ throw "x4"
+ catch /.*/
+ SetLineNumber two_lines_before_interrupt
+ "INTERRUPT
+ let dummy = 0
+ endtry
+ catch /.*/
+ let intcaught = 1
+ call CHECK(6, "Vim:Interrupt", '',
+ \ two_lines_before_interrupt + 2)
+ endtry
+ finally
+ if !intcaught && $VIMNOINTTHROW
+ call CHECK(6)
+ endif
+ break " discard interrupt for $VIMNOINTTHROW
+ endtry
+ endwhile
+ call CHECK(7)
+
+ Xpath 4194304 " X: 4194304
+
+ while 1
+ try
+ let errcaught = 0
+ try
+ try
+" if 1
+ SetLineNumber line_before_throw
+ throw "x5"
+ " missing endif
+ catch /.*/
+ Xpath 8388608 " X: 0
+ endtry
+ catch /.*/
+ let errcaught = 1
+ call CHECK(8, 'E171', "Missing :endif", line_before_throw + 3)
+ endtry
+ finally
+ if !errcaught && $VIMNOERRTHROW
+ call CHECK(8)
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ call CHECK(9)
+
+ Xpath 16777216 " X: 16777216
+
+ try
+ while 1
+ try
+ throw "x6"
+ finally
+ break
+ endtry
+ break
+ endwhile
+ catch /.*/
+ Xpath 33554432 " X: 0
+ endtry
+ call CHECK(10)
+
+ try
+ while 1
+ try
+ throw "x7"
+ finally
+ break
+ endtry
+ break
+ endwhile
+ catch /.*/
+ Xpath 67108864 " X: 0
+ finally
+ call CHECK(11)
+ endtry
+ call CHECK(12)
+
+ while 1
+ try
+ let errcaught = 0
+ try
+ try
+ throw "x8"
+ finally
+ SetLineNumber line_before_error
+ asdf
+ endtry
+ catch /.*/
+ let errcaught = 1
+ call CHECK(13, 'E492', "Not an editor command",
+ \ line_before_error + 1)
+ endtry
+ finally
+ if !errcaught && $VIMNOERRTHROW
+ call CHECK(13)
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ call CHECK(14)
+
+ Xpath 134217728 " X: 134217728
+
+ while 1
+ try
+ let intcaught = 0
+ try
+ try
+ throw "x9"
+ finally
+ SetLineNumber two_lines_before_interrupt
+ "INTERRUPT
+ endtry
+ catch /.*/
+ let intcaught = 1
+ call CHECK(15, "Vim:Interrupt", '',
+ \ two_lines_before_interrupt + 2)
+ endtry
+ finally
+ if !intcaught && $VIMNOINTTHROW
+ call CHECK(15)
+ endif
+ break " discard interrupt for $VIMNOINTTHROW
+ endtry
+ endwhile
+ call CHECK(16)
+
+ Xpath 268435456 " X: 268435456
+
+ while 1
+ try
+ let errcaught = 0
+ try
+ try
+" if 1
+ SetLineNumber line_before_throw
+ throw "x10"
+ " missing endif
+ finally
+ call CHECK(17)
+ endtry
+ catch /.*/
+ let errcaught = 1
+ call CHECK(18, 'E171', "Missing :endif", line_before_throw + 3)
+ endtry
+ finally
+ if !errcaught && $VIMNOERRTHROW
+ call CHECK(18)
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ call CHECK(19)
+
+ Xpath 536870912 " X: 536870912
+
+ while 1
+ try
+ let errcaught = 0
+ try
+ try
+" if 1
+ SetLineNumber line_before_throw
+ throw "x11"
+ " missing endif
+ endtry
+ catch /.*/
+ let errcaught = 1
+ call CHECK(20, 'E171', "Missing :endif", line_before_throw + 3)
+ endtry
+ finally
+ if !errcaught && $VIMNOERRTHROW
+ call CHECK(20)
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ call CHECK(21)
+
+ Xpath 1073741824 " X: 1073741824
+
+endif
+
+Xcheck 2038431743
+
+
+"-------------------------------------------------------------------------------
+"
+" Test 60: (Re)throwing v:exception; :echoerr. {{{1
+"
+" A user exception can be rethrown after catching by throwing
+" v:exception. An error or interrupt exception cannot be rethrown
+" because Vim exceptions cannot be faked. A Vim exception using the
+" value of v:exception can, however, be triggered by the :echoerr
+" command.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+try
+ try
+ Xpath 1 " X: 1
+ throw "oops"
+ catch /oops/
+ Xpath 2 " X: 2
+ throw v:exception " rethrow user exception
+ catch /.*/
+ Xpath 4 " X: 0
+ endtry
+catch /^oops$/ " catches rethrown user exception
+ Xpath 8 " X: 8
+catch /.*/
+ Xpath 16 " X: 0
+endtry
+
+function! F()
+ try
+ let caught = 0
+ try
+ Xpath 32 " X: 32
+ write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e
+ Xpath 64 " X: 0
+ Xout "did_emsg was reset before executing " .
+ \ "BufWritePost autocommands."
+ catch /^Vim(write):/
+ let caught = 1
+ throw v:exception " throw error: cannot fake Vim exception
+ catch /.*/
+ Xpath 128 " X: 0
+ finally
+ Xpath 256 " X: 256
+ if !caught && !$VIMNOERRTHROW
+ Xpath 512 " X: 0
+ endif
+ endtry
+ catch /^Vim(throw):/ " catches throw error
+ let caught = caught + 1
+ catch /.*/
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ if caught != 2
+ if !caught && !$VIMNOERRTHROW
+ Xpath 4096 " X: 0
+ elseif caught
+ Xpath 8192 " X: 0
+ endif
+ return | " discard error for $VIMNOERRTHROW
+ endif
+ endtry
+endfunction
+
+call F()
+delfunction F
+
+function! G()
+ try
+ let caught = 0
+ try
+ Xpath 16384 " X: 16384
+ asdf
+ catch /^Vim/ " catch error exception
+ let caught = 1
+ " Trigger Vim error exception with value specified after :echoerr
+ let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
+ echoerr value
+ catch /.*/
+ Xpath 32768 " X: 0
+ finally
+ Xpath 65536 " X: 65536
+ if !caught
+ if !$VIMNOERRTHROW
+ Xpath 131072 " X: 0
+ else
+ let value = "Error"
+ echoerr value
+ endif
+ endif
+ endtry
+ catch /^Vim(echoerr):/
+ let caught = caught + 1
+ if v:exception !~ value
+ Xpath 262144 " X: 0
+ endif
+ catch /.*/
+ Xpath 524288 " X: 0
+ finally
+ Xpath 1048576 " X: 1048576
+ if caught != 2
+ if !caught && !$VIMNOERRTHROW
+ Xpath 2097152 " X: 0
+ elseif caught
+ Xpath 4194304 " X: 0
+ endif
+ return | " discard error for $VIMNOERRTHROW
+ endif
+ endtry
+endfunction
+
+call G()
+delfunction G
+
+unlet! value caught
+
+if ExtraVim()
+ try
+ let errcaught = 0
+ try
+ Xpath 8388608 " X: 8388608
+ let intcaught = 0
+ "INTERRUPT
+ catch /^Vim:/ " catch interrupt exception
+ let intcaught = 1
+ " Trigger Vim error exception with value specified after :echoerr
+ echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
+ catch /.*/
+ Xpath 16777216 " X: 0
+ finally
+ Xpath 33554432 " X: 33554432
+ if !intcaught
+ if !$VIMNOINTTHROW
+ Xpath 67108864 " X: 0
+ else
+ echoerr "Interrupt"
+ endif
+ endif
+ endtry
+ catch /^Vim(echoerr):/
+ let errcaught = 1
+ if v:exception !~ "Interrupt"
+ Xpath 134217728 " X: 0
+ endif
+ finally
+ Xpath 268435456 " X: 268435456
+ if !errcaught && !$VIMNOERRTHROW
+ Xpath 536870912 " X: 0
+ endif
+ endtry
+endif
+
+Xcheck 311511339
+
+
+"-------------------------------------------------------------------------------
+" Test 61: Catching interrupt exceptions {{{1
+"
+" When an interrupt occurs inside a :try/:endtry region, an
+" interrupt exception is thrown and can be caught. Its value is
+" "Vim:Interrupt". If the interrupt occurs after an error or a :throw
+" but before a matching :catch is reached, all following :catches of
+" that try block are ignored, but the interrupt exception can be
+" caught by the next surrounding try conditional. An interrupt is
+" ignored when there is a previous interrupt that has not been caught
+" or causes a :finally clause to be executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ while 1
+ try
+ try
+ Xpath 1 " X: 1
+ let caught = 0
+ "INTERRUPT
+ Xpath 2 " X: 0
+ catch /^Vim:Interrupt$/
+ let caught = 1
+ finally
+ Xpath 4 " X: 4
+ if caught || $VIMNOINTTHROW
+ Xpath 8 " X: 8
+ endif
+ endtry
+ catch /.*/
+ Xpath 16 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard interrupt for $VIMNOINTTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ try
+ let caught = 0
+ try
+ Xpath 32 " X: 32
+ asdf
+ Xpath 64 " X: 0
+ catch /do_not_catch/
+ Xpath 128 " X: 0
+ catch /.*/ "INTERRUPT - throw interrupt if !$VIMNOERRTHROW
+ Xpath 256 " X: 0
+ catch /.*/
+ Xpath 512 " X: 0
+ finally "INTERRUPT - throw interrupt if $VIMNOERRTHROW
+ Xpath 1024 " X: 1024
+ endtry
+ catch /^Vim:Interrupt$/
+ let caught = 1
+ finally
+ Xpath 2048 " X: 2048
+ if caught || $VIMNOINTTHROW
+ Xpath 4096 " X: 4096
+ endif
+ endtry
+ catch /.*/
+ Xpath 8192 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard interrupt for $VIMNOINTTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ try
+ let caught = 0
+ try
+ Xpath 16384 " X: 16384
+ throw "x"
+ Xpath 32768 " X: 0
+ catch /do_not_catch/
+ Xpath 65536 " X: 0
+ catch /x/ "INTERRUPT
+ Xpath 131072 " X: 0
+ catch /.*/
+ Xpath 262144 " X: 0
+ endtry
+ catch /^Vim:Interrupt$/
+ let caught = 1
+ finally
+ Xpath 524288 " X: 524288
+ if caught || $VIMNOINTTHROW
+ Xpath 1048576 " X: 1048576
+ endif
+ endtry
+ catch /.*/
+ Xpath 2097152 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard interrupt for $VIMNOINTTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ let caught = 0
+ try
+ Xpath 4194304 " X: 4194304
+ "INTERRUPT
+ Xpath 8388608 " X: 0
+ catch /do_not_catch/ "INTERRUPT
+ Xpath 16777216 " X: 0
+ catch /^Vim:Interrupt$/
+ let caught = 1
+ finally
+ Xpath 33554432 " X: 33554432
+ if caught || $VIMNOINTTHROW
+ Xpath 67108864 " X: 67108864
+ endif
+ endtry
+ catch /.*/
+ Xpath 134217728 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard interrupt for $VIMNOINTTHROW
+ endtry
+ endwhile
+
+ Xpath 268435456 " X: 268435456
+
+endif
+
+Xcheck 374889517
+
+
+"-------------------------------------------------------------------------------
+" Test 62: Catching error exceptions {{{1
+"
+" An error inside a :try/:endtry region is converted to an exception
+" and can be caught. The error exception has a "Vim(cmdname):" prefix
+" where cmdname is the name of the failing command, or a "Vim:" prefix
+" if no command name is known. The "Vim" prefixes cannot be faked.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ let match = 1
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ let match = 0
+ if v:errmsg == ""
+ Xout "Message missing."
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Unexpected message:" v:errmsg
+ endif
+ endif
+ return match
+endfunction
+
+while 1
+ try
+ try
+ let caught = 0
+ unlet novar
+ catch /^Vim(unlet):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "")
+ finally
+ Xpath 1 " X: 1
+ if !caught && !$VIMNOERRTHROW
+ Xpath 2 " X: 0
+ endif
+ if !MSG('E108', "No such variable")
+ Xpath 4 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 8 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let caught = 0
+ throw novar " error in :throw
+ catch /^Vim(throw):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
+ finally
+ Xpath 16 " X: 16
+ if !caught && !$VIMNOERRTHROW
+ Xpath 32 " X: 0
+ endif
+ if caught ? !MSG('E121', "Undefined variable")
+ \ : !MSG('E15', "Invalid expression")
+ Xpath 64 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 128 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let caught = 0
+ throw "Vim:faked" " error: cannot fake Vim exception
+ catch /^Vim(throw):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
+ finally
+ Xpath 256 " X: 256
+ if !caught && !$VIMNOERRTHROW
+ Xpath 512 " X: 0
+ endif
+ if !MSG('E608', "Cannot :throw exceptions with 'Vim' prefix")
+ Xpath 1024 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 2048 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+function! F()
+ while 1
+ " Missing :endwhile
+endfunction
+
+while 1
+ try
+ try
+ let caught = 0
+ call F()
+ catch /^Vim(endfunction):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "")
+ finally
+ Xpath 4096 " X: 4096
+ if !caught && !$VIMNOERRTHROW
+ Xpath 8192 " X: 0
+ endif
+ if !MSG('E170', "Missing :endwhile")
+ Xpath 16384 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 32768 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let caught = 0
+ ExecAsScript F
+ catch /^Vim:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim:', '', "")
+ finally
+ Xpath 65536 " X: 65536
+ if !caught && !$VIMNOERRTHROW
+ Xpath 131072 " X: 0
+ endif
+ if !MSG('E170', "Missing :endwhile")
+ Xpath 262144 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 524288 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+function! G()
+ call G()
+endfunction
+
+while 1
+ try
+ let mfd_save = &mfd
+ set mfd=3
+ try
+ let caught = 0
+ call G()
+ catch /^Vim(call):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(call):', '', "")
+ finally
+ Xpath 1048576 " X: 1048576
+ if !caught && !$VIMNOERRTHROW
+ Xpath 2097152 " X: 0
+ endif
+ if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'")
+ Xpath 4194304 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 8388608 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ let &mfd = mfd_save
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+function! H()
+ return H()
+endfunction
+
+while 1
+ try
+ let mfd_save = &mfd
+ set mfd=3
+ try
+ let caught = 0
+ call H()
+ catch /^Vim(return):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(return):', '', "")
+ finally
+ Xpath 16777216 " X: 16777216
+ if !caught && !$VIMNOERRTHROW
+ Xpath 33554432 " X: 0
+ endif
+ if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'")
+ Xpath 67108864 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 134217728 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ let &mfd = mfd_save
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+unlet! caught mfd_save
+delfunction F
+delfunction G
+delfunction H
+Xpath 268435456 " X: 268435456
+
+Xcheck 286331153
+
+" Leave MSG() for the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 63: Suppressing error exceptions by :silent!. {{{1
+"
+" A :silent! command inside a :try/:endtry region suppresses the
+" conversion of errors to an exception and the immediate abortion on
+" error. When the commands executed by the :silent! themselves open
+" a new :try/:endtry region, conversion of errors to exception and
+" immediate abortion is switched on again - until the next :silent!
+" etc. The :silent! has the effect of setting v:errmsg to the error
+" message text (without displaying it) and continuing with the next
+" script line.
+"
+" When a command triggering autocommands is executed by :silent!
+" inside a :try/:endtry, the autocommand execution is not suppressed
+" on error.
+"
+" This test reuses the function MSG() from the previous test.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT! 1 4
+
+let taken = ""
+
+function! S(n) abort
+ XloopNEXT
+ let g:taken = g:taken . "E" . a:n
+ let v:errmsg = ""
+ exec "asdf" . a:n
+
+ " Check that ":silent!" continues:
+ Xloop 1
+
+ " Check that ":silent!" sets "v:errmsg":
+ if MSG('E492', "Not an editor command")
+ Xloop 2
+ endif
+endfunction
+
+function! Foo()
+ while 1
+ try
+ try
+ let caught = 0
+ " This is not silent:
+ call S(3) " X: 0 * 16
+ catch /^Vim:/
+ let caught = 1
+ let errmsg3 = substitute(v:exception, '^Vim:', '', "")
+ silent! call S(4) " X: 3 * 64
+ finally
+ if !caught
+ let errmsg3 = v:errmsg
+ " Do call S(4) here if not executed in :catch.
+ silent! call S(4)
+ endif
+ Xpath 1048576 " X: 1048576
+ if !caught && !$VIMNOERRTHROW
+ Xpath 2097152 " X: 0
+ endif
+ let v:errmsg = errmsg3
+ if !MSG('E492', "Not an editor command")
+ Xpath 4194304 " X: 0
+ endif
+ silent! call S(5) " X: 3 * 256
+ " Break out of try conds that cover ":silent!". This also
+ " discards the aborting error when $VIMNOERRTHROW is non-zero.
+ break
+ endtry
+ catch /.*/
+ Xpath 8388608 " X: 0
+ Xout v:exception "in" v:throwpoint
+ endtry
+ endwhile
+ " This is a double ":silent!" (see caller).
+ silent! call S(6) " X: 3 * 1024
+endfunction
+
+function! Bar()
+ try
+ silent! call S(2) " X: 3 * 4
+ " X: 3 * 4096
+ silent! execute "call Foo() | call S(7)"
+ silent! call S(8) " X: 3 * 16384
+ endtry " normal end of try cond that covers ":silent!"
+ " This has a ":silent!" from the caller:
+ call S(9) " X: 3 * 65536
+endfunction
+
+silent! call S(1) " X: 3 * 1
+silent! call Bar()
+silent! call S(10) " X: 3 * 262144
+
+let expected = "E1E2E3E4E5E6E7E8E9E10"
+if taken != expected
+ Xpath 16777216 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+endif
+
+augroup TMP
+ autocmd BufWritePost * Xpath 33554432 " X: 33554432
+augroup END
+
+Xpath 67108864 " X: 67108864
+write /i/m/p/o/s/s/i/b/l/e
+Xpath 134217728 " X: 134217728
+
+autocmd! TMP
+unlet! caught errmsg3 taken expected
+delfunction S
+delfunction Foo
+delfunction Bar
+delfunction MSG
+
+Xcheck 236978127
+
+
+"-------------------------------------------------------------------------------
+" Test 64: Error exceptions after error, interrupt or :throw {{{1
+"
+" When an error occurs after an interrupt or a :throw but before
+" a matching :catch is reached, all following :catches of that try
+" block are ignored, but the error exception can be caught by the next
+" surrounding try conditional. Any previous error exception is
+" discarded. An error is ignored when there is a previous error that
+" has not been caught.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ while 1
+ try
+ try
+ Xpath 1 " X: 1
+ let caught = 0
+ while 1
+" if 1
+ " Missing :endif
+ endwhile " throw error exception
+ catch /^Vim(/
+ let caught = 1
+ finally
+ Xpath 2 " X: 2
+ if caught || $VIMNOERRTHROW
+ Xpath 4 " X: 4
+ endif
+ endtry
+ catch /.*/
+ Xpath 8 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ try
+ Xpath 16 " X: 16
+ let caught = 0
+ try
+" if 1
+ " Missing :endif
+ catch /.*/ " throw error exception
+ Xpath 32 " X: 0
+ catch /.*/
+ Xpath 64 " X: 0
+ endtry
+ catch /^Vim(/
+ let caught = 1
+ finally
+ Xpath 128 " X: 128
+ if caught || $VIMNOERRTHROW
+ Xpath 256 " X: 256
+ endif
+ endtry
+ catch /.*/
+ Xpath 512 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ try
+ let caught = 0
+ try
+ Xpath 1024 " X: 1024
+ "INTERRUPT
+ catch /do_not_catch/
+ Xpath 2048 " X: 0
+" if 1
+ " Missing :endif
+ catch /.*/ " throw error exception
+ Xpath 4096 " X: 0
+ catch /.*/
+ Xpath 8192 " X: 0
+ endtry
+ catch /^Vim(/
+ let caught = 1
+ finally
+ Xpath 16384 " X: 16384
+ if caught || $VIMNOERRTHROW
+ Xpath 32768 " X: 32768
+ endif
+ endtry
+ catch /.*/
+ Xpath 65536 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ try
+ let caught = 0
+ try
+ Xpath 131072 " X: 131072
+ throw "x"
+ catch /do_not_catch/
+ Xpath 262144 " X: 0
+" if 1
+ " Missing :endif
+ catch /x/ " throw error exception
+ Xpath 524288 " X: 0
+ catch /.*/
+ Xpath 1048576 " X: 0
+ endtry
+ catch /^Vim(/
+ let caught = 1
+ finally
+ Xpath 2097152 " X: 2097152
+ if caught || $VIMNOERRTHROW
+ Xpath 4194304 " X: 4194304
+ endif
+ endtry
+ catch /.*/
+ Xpath 8388608 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ try
+ let caught = 0
+ Xpath 16777216 " X: 16777216
+" endif " :endif without :if; throw error exception
+" if 1
+ " Missing :endif
+ catch /do_not_catch/ " ignore new error
+ Xpath 33554432 " X: 0
+ catch /^Vim(endif):/
+ let caught = 1
+ catch /^Vim(/
+ Xpath 67108864 " X: 0
+ finally
+ Xpath 134217728 " X: 134217728
+ if caught || $VIMNOERRTHROW
+ Xpath 268435456 " X: 268435456
+ endif
+ endtry
+ catch /.*/
+ Xpath 536870912 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ Xpath 1073741824 " X: 1073741824
+
+endif
+
+Xcheck 1499645335
+
+
+"-------------------------------------------------------------------------------
+" Test 65: Errors in the /pattern/ argument of a :catch {{{1
+"
+" On an error in the /pattern/ argument of a :catch, the :catch does
+" not match. Any following :catches of the same :try/:endtry don't
+" match either. Finally clauses are executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ let match = 1
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ let match = 0
+ if v:errmsg == ""
+ Xout "Message missing."
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Unexpected message:" v:errmsg
+ endif
+ endif
+ return match
+endfunction
+
+try
+ try
+ Xpath 1 " X: 1
+ throw "oops"
+ catch /^oops$/
+ Xpath 2 " X: 2
+ catch /\)/ " not checked; exception has already been caught
+ Xpath 4 " X: 0
+ endtry
+ Xpath 8 " X: 8
+catch /.*/
+ Xpath 16 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+function! F()
+ try
+ let caught = 0
+ try
+ try
+ Xpath 32 " X: 32
+ throw "ab"
+ catch /abc/ " does not catch
+ Xpath 64 " X: 0
+ catch /\)/ " error; discards exception
+ Xpath 128 " X: 0
+ catch /.*/ " not checked
+ Xpath 256 " X: 0
+ finally
+ Xpath 512 " X: 512
+ endtry
+ Xpath 1024 " X: 0
+ catch /^ab$/ " checked, but original exception is discarded
+ Xpath 2048 " X: 0
+ catch /^Vim(catch):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(catch):', '', "")
+ finally
+ Xpath 4096 " X: 4096
+ if !caught && !$VIMNOERRTHROW
+ Xpath 8192 " X: 0
+ endif
+ if caught ? !MSG('E55', 'Unmatched \\)')
+ \ : !MSG('E475', "Invalid argument")
+ Xpath 16384 " X: 0
+ endif
+ if !caught
+ return | " discard error
+ endif
+ endtry
+ catch /.*/
+ Xpath 32768 " X: 0
+ Xout v:exception "in" v:throwpoint
+ endtry
+endfunction
+
+call F()
+Xpath 65536 " X: 65536
+
+delfunction MSG
+delfunction F
+unlet! caught
+
+Xcheck 70187
+
+
+"-------------------------------------------------------------------------------
+" Test 66: Stop range :call on error, interrupt, or :throw {{{1
+"
+" When a function which is multiply called for a range since it
+" doesn't handle the range itself has an error in a command
+" dynamically enclosed by :try/:endtry or gets an interrupt or
+" executes a :throw, no more calls for the remaining lines in the
+" range are made. On an error in a command not dynamically enclosed
+" by :try/:endtry, the function is executed again for the remaining
+" lines in the range.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ let file = tempname()
+ exec "edit" file
+
+ insert
+line 1
+line 2
+line 3
+.
+
+ XloopINIT! 1 2
+
+ let taken = ""
+ let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)"
+
+ function! F(reason, n) abort
+ let g:taken = g:taken . "F" . a:n .
+ \ substitute(a:reason, '\(\l\).*', '\u\1', "") .
+ \ "(" . line(".") . ")"
+
+ if a:reason == "error"
+ asdf
+ elseif a:reason == "interrupt"
+ "INTERRUPT
+ let dummy = 0
+ elseif a:reason == "throw"
+ throw "xyz"
+ elseif a:reason == "aborting error"
+ XloopNEXT
+ if g:taken != g:expected
+ Xloop 1 " X: 0
+ Xout "'taken' is" g:taken "instead of" g:expected
+ endif
+ try
+ bwipeout!
+ call delete(file)
+ asdf
+ endtry
+ endif
+ endfunction
+
+ function! G(reason, n)
+ let g:taken = g:taken . "G" . a:n .
+ \ substitute(a:reason, '\(\l\).*', '\u\1', "")
+ 1,3call F(a:reason, a:n)
+ endfunction
+
+ Xpath 8 " X: 8
+ call G("error", 1)
+ try
+ Xpath 16 " X: 16
+ try
+ call G("error", 2)
+ Xpath 32 " X: 0
+ finally
+ Xpath 64 " X: 64
+ try
+ call G("interrupt", 3)
+ Xpath 128 " X: 0
+ finally
+ Xpath 256 " X: 256
+ try
+ call G("throw", 4)
+ Xpath 512 " X: 0
+ endtry
+ endtry
+ endtry
+ catch /xyz/
+ Xpath 1024 " X: 1024
+ catch /.*/
+ Xpath 2048 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+ Xpath 4096 " X: 4096
+ call G("aborting error", 5)
+ Xpath 8192 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+
+endif
+
+Xcheck 5464
+
+
+"-------------------------------------------------------------------------------
+" Test 67: :throw accross :call command {{{1
+"
+" On a call command, an exception might be thrown when evaluating the
+" function name, during evaluation of the arguments, or when the
+" function is being executed. The exception can be caught by the
+" caller.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! THROW(x, n)
+ if a:n == 1
+ Xpath 1 " X: 1
+ elseif a:n == 2
+ Xpath 2 " X: 2
+ elseif a:n == 3
+ Xpath 4 " X: 4
+ endif
+ throw a:x
+endfunction
+
+function! NAME(x, n)
+ if a:n == 1
+ Xpath 8 " X: 0
+ elseif a:n == 2
+ Xpath 16 " X: 16
+ elseif a:n == 3
+ Xpath 32 " X: 32
+ elseif a:n == 4
+ Xpath 64 " X: 64
+ endif
+ return a:x
+endfunction
+
+function! ARG(x, n)
+ if a:n == 1
+ Xpath 128 " X: 0
+ elseif a:n == 2
+ Xpath 256 " X: 0
+ elseif a:n == 3
+ Xpath 512 " X: 512
+ elseif a:n == 4
+ Xpath 1024 " X: 1024
+ endif
+ return a:x
+endfunction
+
+function! F(x, n)
+ if a:n == 2
+ Xpath 2048 " X: 0
+ elseif a:n == 4
+ Xpath 4096 " X: 4096
+ endif
+endfunction
+
+try
+
+ try
+ Xpath 8192 " X: 8192
+ call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
+ Xpath 16384 " X: 0
+ catch /^name$/
+ Xpath 32768 " X: 32768
+ catch /.*/
+ Xpath 65536 " X: 0
+ Xout "1:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 131072 " X: 131072
+ call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
+ Xpath 262144 " X: 0
+ catch /^arg$/
+ Xpath 524288 " X: 524288
+ catch /.*/
+ Xpath 1048576 " X: 0
+ Xout "2:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 2097152 " X: 2097152
+ call {NAME("THROW", 3)}(ARG("call", 3), 3)
+ Xpath 4194304 " X: 0
+ catch /^call$/
+ Xpath 8388608 " X: 8388608
+ catch /^0$/ " default return value
+ Xpath 16777216 " X: 0
+ Xout "3:" v:throwpoint
+ catch /.*/
+ Xpath 33554432 " X: 0
+ Xout "3:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 67108864 " X: 67108864
+ call {NAME("F", 4)}(ARG(4711, 4), 4)
+ Xpath 134217728 " X: 134217728
+ catch /.*/
+ Xpath 268435456 " X: 0
+ Xout "4:" v:exception "in" v:throwpoint
+ endtry
+
+catch /^0$/ " default return value
+ Xpath 536870912 " X: 0
+ Xout v:throwpoint
+catch /.*/
+ Xpath 1073741824 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+delfunction F
+
+Xcheck 212514423
+
+" Leave THROW(), NAME(), and ARG() for the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 68: :throw accross function calls in expressions {{{1
+"
+" On a function call within an expression, an exception might be
+" thrown when evaluating the function name, during evaluation of the
+" arguments, or when the function is being executed. The exception
+" can be caught by the caller.
+"
+" This test reuses the functions THROW(), NAME(), and ARG() from the
+" previous test.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F(x, n)
+ if a:n == 2
+ Xpath 2048 " X: 0
+ elseif a:n == 4
+ Xpath 4096 " X: 4096
+ endif
+ return a:x
+endfunction
+
+unlet! var1 var2 var3 var4
+
+try
+
+ try
+ Xpath 8192 " X: 8192
+ let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
+ Xpath 16384 " X: 0
+ catch /^name$/
+ Xpath 32768 " X: 32768
+ catch /.*/
+ Xpath 65536 " X: 0
+ Xout "1:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 131072 " X: 131072
+ let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
+ Xpath 262144 " X: 0
+ catch /^arg$/
+ Xpath 524288 " X: 524288
+ catch /.*/
+ Xpath 1048576 " X: 0
+ Xout "2:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 2097152 " X: 2097152
+ let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3)
+ Xpath 4194304 " X: 0
+ catch /^call$/
+ Xpath 8388608 " X: 8388608
+ catch /^0$/ " default return value
+ Xpath 16777216 " X: 0
+ Xout "3:" v:throwpoint
+ catch /.*/
+ Xpath 33554432 " X: 0
+ Xout "3:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 67108864 " X: 67108864
+ let var4 = {NAME("F", 4)}(ARG(4711, 4), 4)
+ Xpath 134217728 " X: 134217728
+ catch /.*/
+ Xpath 268435456 " X: 0
+ Xout "4:" v:exception "in" v:throwpoint
+ endtry
+
+catch /^0$/ " default return value
+ Xpath 536870912 " X: 0
+ Xout v:throwpoint
+catch /.*/
+ Xpath 1073741824 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+if exists("var1") || exists("var2") || exists("var3") ||
+ \ !exists("var4") || var4 != 4711
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ if exists("var1")
+ Xout "var1 =" var1
+ endif
+ if exists("var2")
+ Xout "var2 =" var2
+ endif
+ if exists("var3")
+ Xout "var3 =" var3
+ endif
+ if !exists("var4")
+ Xout "var4 unset"
+ elseif var4 != 4711
+ Xout "var4 =" var4
+ endif
+endif
+
+unlet! var1 var2 var3 var4
+delfunction THROW
+delfunction NAME
+delfunction ARG
+delfunction F
+
+Xcheck 212514423
+
+
+"-------------------------------------------------------------------------------
+" Test 69: :throw accross :if, :elseif, :while {{{1
+"
+" On an :if, :elseif, or :while command, an exception might be thrown
+" during evaluation of the expression to test. The exception can be
+" caught by the script.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT! 1 2
+
+function! THROW(x)
+ XloopNEXT
+ Xloop 1 " X: 1 + 2 + 4
+ throw a:x
+endfunction
+
+try
+
+ try
+ Xpath 8 " X: 8
+ if 4711 == THROW("if") + 111
+ Xpath 16 " X: 0
+ else
+ Xpath 32 " X: 0
+ endif
+ Xpath 64 " X: 0
+ catch /^if$/
+ Xpath 128 " X: 128
+ catch /.*/
+ Xpath 256 " X: 0
+ Xout "if:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 512 " X: 512
+ if 4711 == 4 + 7 + 1 + 1
+ Xpath 1024 " X: 0
+ elseif 4711 == THROW("elseif") + 222
+ Xpath 2048 " X: 0
+ else
+ Xpath 4096 " X: 0
+ endif
+ Xpath 8192 " X: 0
+ catch /^elseif$/
+ Xpath 16384 " X: 16384
+ catch /.*/
+ Xpath 32768 " X: 0
+ Xout "elseif:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 65536 " X: 65536
+ while 4711 == THROW("while") + 4711
+ Xpath 131072 " X: 0
+ break
+ endwhile
+ Xpath 262144 " X: 0
+ catch /^while$/
+ Xpath 524288 " X: 524288
+ catch /.*/
+ Xpath 1048576 " X: 0
+ Xout "while:" v:exception "in" v:throwpoint
+ endtry
+
+catch /^0$/ " default return value
+ Xpath 2097152 " X: 0
+ Xout v:throwpoint
+catch /.*/
+ Xout v:exception "in" v:throwpoint
+ Xpath 4194304 " X: 0
+endtry
+
+Xpath 8388608 " X: 8388608
+
+delfunction THROW
+
+Xcheck 8995471
+
+
+"-------------------------------------------------------------------------------
+" Test 70: :throw accross :return or :throw {{{1
+"
+" On a :return or :throw command, an exception might be thrown during
+" evaluation of the expression to return or throw, respectively. The
+" exception can be caught by the script.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let taken = ""
+
+function! THROW(x, n)
+ let g:taken = g:taken . "T" . a:n
+ throw a:x
+endfunction
+
+function! F(x, y, n)
+ let g:taken = g:taken . "F" . a:n
+ return a:x + THROW(a:y, a:n)
+endfunction
+
+function! G(x, y, n)
+ let g:taken = g:taken . "G" . a:n
+ throw a:x . THROW(a:y, a:n)
+ return a:x
+endfunction
+
+try
+ try
+ Xpath 1 " X: 1
+ call F(4711, "return", 1)
+ Xpath 2 " X: 0
+ catch /^return$/
+ Xpath 4 " X: 4
+ catch /.*/
+ Xpath 8 " X: 0
+ Xout "return:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 16 " X: 16
+ let var = F(4712, "return-var", 2)
+ Xpath 32 " X: 0
+ catch /^return-var$/
+ Xpath 64 " X: 64
+ catch /.*/
+ Xpath 128 " X: 0
+ Xout "return-var:" v:exception "in" v:throwpoint
+ finally
+ unlet! var
+ endtry
+
+ try
+ Xpath 256 " X: 256
+ throw "except1" . THROW("throw1", 3)
+ Xpath 512 " X: 0
+ catch /^except1/
+ Xpath 1024 " X: 0
+ catch /^throw1$/
+ Xpath 2048 " X: 2048
+ catch /.*/
+ Xpath 4096 " X: 0
+ Xout "throw1:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 8192 " X: 8192
+ call G("except2", "throw2", 4)
+ Xpath 16384 " X: 0
+ catch /^except2/
+ Xpath 32768 " X: 0
+ catch /^throw2$/
+ Xpath 65536 " X: 65536
+ catch /.*/
+ Xpath 131072 " X: 0
+ Xout "throw2:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 262144 " X: 262144
+ let var = G("except3", "throw3", 5)
+ Xpath 524288 " X: 0
+ catch /^except3/
+ Xpath 1048576 " X: 0
+ catch /^throw3$/
+ Xpath 2097152 " X: 2097152
+ catch /.*/
+ Xpath 4194304 " X: 0
+ Xout "throw3:" v:exception "in" v:throwpoint
+ finally
+ unlet! var
+ endtry
+
+ let expected = "F1T1F2T2T3G4T4G5T5"
+ if taken != expected
+ Xpath 8388608 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+ endif
+
+catch /^0$/ " default return value
+ Xpath 16777216 " X: 0
+ Xout v:throwpoint
+catch /.*/
+ Xpath 33554432 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 67108864 " X: 67108864
+
+unlet taken expected
+delfunction THROW
+delfunction F
+delfunction G
+
+Xcheck 69544277
+
+
+"-------------------------------------------------------------------------------
+" Test 71: :throw accross :echo variants and :execute {{{1
+"
+" On an :echo, :echon, :echomsg, :echoerr, or :execute command, an
+" exception might be thrown during evaluation of the arguments to
+" be displayed or executed as a command, respectively. Any following
+" arguments are not evaluated, then. The exception can be caught by
+" the script.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let taken = ""
+
+function! THROW(x, n)
+ let g:taken = g:taken . "T" . a:n
+ throw a:x
+endfunction
+
+function! F(n)
+ let g:taken = g:taken . "F" . a:n
+ return "F" . a:n
+endfunction
+
+try
+ try
+ Xpath 1 " X: 1
+ echo "echo" . THROW("echo-except", 1) F(1)
+ Xpath 2 " X: 0
+ catch /^echo-except$/
+ Xpath 4 " X: 4
+ catch /.*/
+ Xpath 8 " X: 0
+ Xout "echo:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 16 " X: 16
+ echon "echon" . THROW("echon-except", 2) F(2)
+ Xpath 32 " X: 0
+ catch /^echon-except$/
+ Xpath 64 " X: 64
+ catch /.*/
+ Xpath 128 " X: 0
+ Xout "echon:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 256 " X: 256
+ echomsg "echomsg" . THROW("echomsg-except", 3) F(3)
+ Xpath 512 " X: 0
+ catch /^echomsg-except$/
+ Xpath 1024 " X: 1024
+ catch /.*/
+ Xpath 2048 " X: 0
+ Xout "echomsg:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 4096 " X: 4096
+ echoerr "echoerr" . THROW("echoerr-except", 4) F(4)
+ Xpath 8192 " X: 0
+ catch /^echoerr-except$/
+ Xpath 16384 " X: 16384
+ catch /Vim/
+ Xpath 32768 " X: 0
+ catch /echoerr/
+ Xpath 65536 " X: 0
+ catch /.*/
+ Xpath 131072 " X: 0
+ Xout "echoerr:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 262144 " X: 262144
+ execute "echo 'execute" . THROW("execute-except", 5) F(5) "'"
+ Xpath 524288 " X: 0
+ catch /^execute-except$/
+ Xpath 1048576 " X: 1048576
+ catch /.*/
+ Xpath 2097152 " X: 0
+ Xout "execute:" v:exception "in" v:throwpoint
+ endtry
+
+ let expected = "T1T2T3T4T5"
+ if taken != expected
+ Xpath 4194304 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+ endif
+
+catch /^0$/ " default return value
+ Xpath 8388608 " X: 0
+ Xout v:throwpoint
+catch /.*/
+ Xpath 16777216 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 33554432 " X: 33554432
+
+unlet taken expected
+delfunction THROW
+delfunction F
+
+Xcheck 34886997
+
+
+"-------------------------------------------------------------------------------
+" Test 72: :throw accross :let or :unlet {{{1
+"
+" On a :let command, an exception might be thrown during evaluation
+" of the expression to assign. On an :let or :unlet command, the
+" evaluation of the name of the variable to be assigned or list or
+" deleted, respectively, may throw an exception. Any following
+" arguments are not evaluated, then. The exception can be caught by
+" the script.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let throwcount = 0
+
+function! THROW(x)
+ let g:throwcount = g:throwcount + 1
+ throw a:x
+endfunction
+
+try
+ try
+ let $VAR = "old_value"
+ Xpath 1 " X: 1
+ let $VAR = "let(" . THROW("var") . ")"
+ Xpath 2 " X: 0
+ catch /^var$/
+ Xpath 4 " X: 4
+ finally
+ if $VAR != "old_value"
+ Xpath 8 " X: 0
+ endif
+ endtry
+
+ try
+ let @a = "old_value"
+ Xpath 16 " X: 16
+ let @a = "let(" . THROW("reg") . ")"
+ Xpath 32 " X: 0
+ catch /^reg$/
+ try
+ Xpath 64 " X: 64
+ let @A = "let(" . THROW("REG") . ")"
+ Xpath 128 " X: 0
+ catch /^REG$/
+ Xpath 256 " X: 256
+ endtry
+ finally
+ if @a != "old_value"
+ Xpath 512 " X: 0
+ endif
+ if @A != "old_value"
+ Xpath 1024 " X: 0
+ endif
+ endtry
+
+ try
+ let saved_gpath = &g:path
+ let saved_lpath = &l:path
+ Xpath 2048 " X: 2048
+ let &path = "let(" . THROW("opt") . ")"
+ Xpath 4096 " X: 0
+ catch /^opt$/
+ try
+ Xpath 8192 " X: 8192
+ let &g:path = "let(" . THROW("gopt") . ")"
+ Xpath 16384 " X: 0
+ catch /^gopt$/
+ try
+ Xpath 32768 " X: 32768
+ let &l:path = "let(" . THROW("lopt") . ")"
+ Xpath 65536 " X: 0
+ catch /^lopt$/
+ Xpath 131072 " X: 131072
+ endtry
+ endtry
+ finally
+ if &g:path != saved_gpath || &l:path != saved_lpath
+ Xpath 262144 " X: 0
+ endif
+ let &g:path = saved_gpath
+ let &l:path = saved_lpath
+ endtry
+
+ unlet! var1 var2 var3
+
+ try
+ Xpath 524288 " X: 524288
+ let var1 = "let(" . THROW("var1") . ")"
+ Xpath 1048576 " X: 0
+ catch /^var1$/
+ Xpath 2097152 " X: 2097152
+ finally
+ if exists("var1")
+ Xpath 4194304 " X: 0
+ endif
+ endtry
+
+ try
+ let var2 = "old_value"
+ Xpath 8388608 " X: 8388608
+ let var2 = "let(" . THROW("var2"). ")"
+ Xpath 16777216 " X: 0
+ catch /^var2$/
+ Xpath 33554432 " X: 33554432
+ finally
+ if var2 != "old_value"
+ Xpath 67108864 " X: 0
+ endif
+ endtry
+
+ try
+ Xpath 134217728 " X: 134217728
+ let var{THROW("var3")} = 4711
+ Xpath 268435456 " X: 0
+ catch /^var3$/
+ Xpath 536870912 " X: 536870912
+ endtry
+
+ let addpath = ""
+
+ function ADDPATH(p)
+ let g:addpath = g:addpath . a:p
+ endfunction
+
+ try
+ call ADDPATH("T1")
+ let var{THROW("var4")} var{ADDPATH("T2")} | call ADDPATH("T3")
+ call ADDPATH("T4")
+ catch /^var4$/
+ call ADDPATH("T5")
+ endtry
+
+ try
+ call ADDPATH("T6")
+ unlet var{THROW("var5")} var{ADDPATH("T7")} | call ADDPATH("T8")
+ call ADDPATH("T9")
+ catch /^var5$/
+ call ADDPATH("T10")
+ endtry
+
+ if addpath != "T1T5T6T10" || throwcount != 11
+ throw "addpath: " . addpath . ", throwcount: " . throwcount
+ endif
+
+ Xpath 1073741824 " X: 1073741824
+
+catch /.*/
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+unlet! var1 var2 var3 addpath throwcount
+delfunction THROW
+
+Xcheck 1789569365
+
+
+"-------------------------------------------------------------------------------
+" Test 73: :throw accross :function, :delfunction {{{1
+"
+" The :function and :delfunction commands may cause an expression
+" specified in braces to be evaluated. During evaluation, an
+" exception might be thrown. The exception can be caught by the
+" script.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let taken = ""
+
+function! THROW(x, n)
+ let g:taken = g:taken . "T" . a:n
+ throw a:x
+endfunction
+
+function! EXPR(x, n)
+ let g:taken = g:taken . "E" . a:n
+ if a:n % 2 == 0
+ call THROW(a:x, a:n)
+ endif
+ return 2 - a:n % 2
+endfunction
+
+try
+ try
+ " Define function.
+ Xpath 1 " X: 1
+ function! F0()
+ endfunction
+ Xpath 2 " X: 2
+ function! F{EXPR("function-def-ok", 1)}()
+ endfunction
+ Xpath 4 " X: 4
+ function! F{EXPR("function-def", 2)}()
+ endfunction
+ Xpath 8 " X: 0
+ catch /^function-def-ok$/
+ Xpath 16 " X: 0
+ catch /^function-def$/
+ Xpath 32 " X: 32
+ catch /.*/
+ Xpath 64 " X: 0
+ Xout "def:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ " List function.
+ Xpath 128 " X: 128
+ function F0
+ Xpath 256 " X: 256
+ function F{EXPR("function-lst-ok", 3)}
+ Xpath 512 " X: 512
+ function F{EXPR("function-lst", 4)}
+ Xpath 1024 " X: 0
+ catch /^function-lst-ok$/
+ Xpath 2048 " X: 0
+ catch /^function-lst$/
+ Xpath 4096 " X: 4096
+ catch /.*/
+ Xpath 8192 " X: 0
+ Xout "lst:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ " Delete function
+ Xpath 16384 " X: 16384
+ delfunction F0
+ Xpath 32768 " X: 32768
+ delfunction F{EXPR("function-del-ok", 5)}
+ Xpath 65536 " X: 65536
+ delfunction F{EXPR("function-del", 6)}
+ Xpath 131072 " X: 0
+ catch /^function-del-ok$/
+ Xpath 262144 " X: 0
+ catch /^function-del$/
+ Xpath 524288 " X: 524288
+ catch /.*/
+ Xpath 1048576 " X: 0
+ Xout "del:" v:exception "in" v:throwpoint
+ endtry
+
+ let expected = "E1E2T2E3E4T4E5E6T6"
+ if taken != expected
+ Xpath 2097152 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+ endif
+
+catch /.*/
+ Xpath 4194304 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 8388608 " X: 8388608
+
+unlet taken expected
+delfunction THROW
+delfunction EXPR
+
+Xcheck 9032615
+
+
+"-------------------------------------------------------------------------------
+" Test 74: :throw accross builtin functions and commands {{{1
+"
+" Some functions like exists(), searchpair() take expression
+" arguments, other functions or commands like substitute() or
+" :substitute cause an expression (specified in the regular
+" expression) to be evaluated. During evaluation an exception
+" might be thrown. The exception can be caught by the script.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let taken = ""
+
+function! THROW(x, n)
+ let g:taken = g:taken . "T" . a:n
+ throw a:x
+endfunction
+
+function! EXPR(x, n)
+ let g:taken = g:taken . "E" . a:n
+ call THROW(a:x . a:n, a:n)
+ return "EXPR"
+endfunction
+
+function! SKIP(x, n)
+ let g:taken = g:taken . "S" . a:n . "(" . line(".")
+ let theline = getline(".")
+ if theline =~ "skip"
+ let g:taken = g:taken . "s)"
+ return 1
+ elseif theline =~ "throw"
+ let g:taken = g:taken . "t)"
+ call THROW(a:x . a:n, a:n)
+ else
+ let g:taken = g:taken . ")"
+ return 0
+ endif
+endfunction
+
+function! SUBST(x, n)
+ let g:taken = g:taken . "U" . a:n . "(" . line(".")
+ let theline = getline(".")
+ if theline =~ "not" " SUBST() should not be called for this line
+ let g:taken = g:taken . "n)"
+ call THROW(a:x . a:n, a:n)
+ elseif theline =~ "throw"
+ let g:taken = g:taken . "t)"
+ call THROW(a:x . a:n, a:n)
+ else
+ let g:taken = g:taken . ")"
+ return "replaced"
+ endif
+endfunction
+
+try
+ try
+ Xpath 1 " X: 1
+ let result = exists('*{EXPR("exists", 1)}')
+ Xpath 2 " X: 0
+ catch /^exists1$/
+ Xpath 4 " X: 4
+ try
+ let result = exists('{EXPR("exists", 2)}')
+ Xpath 8 " X: 0
+ catch /^exists2$/
+ Xpath 16 " X: 16
+ catch /.*/
+ Xpath 32 " X: 0
+ Xout "exists2:" v:exception "in" v:throwpoint
+ endtry
+ catch /.*/
+ Xpath 64 " X: 0
+ Xout "exists1:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ let file = tempname()
+ exec "edit" file
+ insert
+begin
+ xx
+middle 3
+ xx
+middle 5 skip
+ xx
+middle 7 throw
+ xx
+end
+.
+ normal! gg
+ Xpath 128 " X: 128
+ let result =
+ \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 3)')
+ Xpath 256 " X: 256
+ let result =
+ \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 4)')
+ Xpath 512 " X: 0
+ let result =
+ \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 5)')
+ Xpath 1024 " X: 0
+ catch /^searchpair[35]$/
+ Xpath 2048 " X: 0
+ catch /^searchpair4$/
+ Xpath 4096 " X: 4096
+ catch /.*/
+ Xpath 8192 " X: 0
+ Xout "searchpair:" v:exception "in" v:throwpoint
+ finally
+ bwipeout!
+ call delete(file)
+ endtry
+
+ try
+ let file = tempname()
+ exec "edit" file
+ insert
+subst 1
+subst 2
+not
+subst 4
+subst throw
+subst 6
+.
+ normal! gg
+ Xpath 16384 " X: 16384
+ 1,2substitute/subst/\=SUBST("substitute", 6)/
+ try
+ Xpath 32768 " X: 32768
+ try
+ let v:errmsg = ""
+ 3substitute/subst/\=SUBST("substitute", 7)/
+ finally
+ if v:errmsg != ""
+ " If exceptions are not thrown on errors, fake the error
+ " exception in order to get the same execution path.
+ throw "faked Vim(substitute)"
+ endif
+ endtry
+ catch /Vim(substitute)/ " Pattern not found ('e' flag missing)
+ Xpath 65536 " X: 65536
+ 3substitute/subst/\=SUBST("substitute", 8)/e
+ Xpath 131072 " X: 131072
+ endtry
+ Xpath 262144 " X: 262144
+ 4,6substitute/subst/\=SUBST("substitute", 9)/
+ Xpath 524288 " X: 0
+ catch /^substitute[678]/
+ Xpath 1048576 " X: 0
+ catch /^substitute9/
+ Xpath 2097152 " X: 2097152
+ finally
+ bwipeout!
+ call delete(file)
+ endtry
+
+ try
+ Xpath 4194304 " X: 4194304
+ let var = substitute("sub", "sub", '\=THROW("substitute()y", 10)', '')
+ Xpath 8388608 " X: 0
+ catch /substitute()y/
+ Xpath 16777216 " X: 16777216
+ catch /.*/
+ Xpath 33554432 " X: 0
+ Xout "substitute()y:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 67108864 " X: 67108864
+ let var = substitute("not", "sub", '\=THROW("substitute()n", 11)', '')
+ Xpath 134217728 " X: 134217728
+ catch /substitute()n/
+ Xpath 268435456 " X: 0
+ catch /.*/
+ Xpath 536870912 " X: 0
+ Xout "substitute()n:" v:exception "in" v:throwpoint
+ endtry
+
+ let expected = "E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10"
+ if taken != expected
+ Xpath 1073741824 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+ endif
+
+catch /.*/
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+unlet result var taken expected
+delfunction THROW
+delfunction EXPR
+delfunction SKIP
+delfunction SUBST
+
+Xcheck 224907669
+
+
+"-------------------------------------------------------------------------------
+" Test 75: Errors in builtin functions. {{{1
+"
+" On an error in a builtin function called inside a :try/:endtry
+" region, the evaluation of the expression calling that function and
+" the command containing that expression are abandoned. The error can
+" be caught as an exception.
+"
+" A simple :call of the builtin function is a trivial case. If the
+" builtin function is called in the argument list of another function,
+" no further arguments are evaluated, and the other function is not
+" executed. If the builtin function is called from the argument of
+" a :return command, the :return command is not executed. If the
+" builtin function is called from the argument of a :throw command,
+" the :throw command is not executed. The evaluation of the
+" expression calling the builtin function is abandoned.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F1(arg1)
+ Xpath 1 " X: 0
+endfunction
+
+function! F2(arg1, arg2)
+ Xpath 2 " X: 0
+endfunction
+
+function! G()
+ Xpath 4 " X: 0
+endfunction
+
+function! H()
+ Xpath 8 " X: 0
+endfunction
+
+function! R()
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 16 " X: 16
+ return append(1, "s")
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 32 " X: 0
+ finally
+ Xpath 64 " X: 64
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 128 " X: 128
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ Xpath 256 " X: 256
+endfunction
+
+try
+ set noma " let append() fail with "E21"
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 512 " X: 512
+ call append(1, "s")
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 4096 " X: 4096
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 8192 " X: 8192
+ call F1('x' . append(1, "s"))
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 16384 " X: 0
+ finally
+ Xpath 32768 " X: 32768
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 65536 " X: 65536
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 131072 " X: 131072
+ call F2('x' . append(1, "s"), G())
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 262144 " X: 0
+ finally
+ Xpath 524288 " X: 524288
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 1048576 " X: 1048576
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ call R()
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 2097152 " X: 2097152
+ throw "T" . append(1, "s")
+ catch /E21/
+ let caught = 1
+ catch /^T.*/
+ Xpath 4194304 " X: 0
+ catch /.*/
+ Xpath 8388608 " X: 0
+ finally
+ Xpath 16777216 " X: 16777216
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 33554432 " X: 33554432
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 67108864 " X: 67108864
+ let x = "a"
+ let x = x . "b" . append(1, "s") . H()
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 134217728 " X: 0
+ finally
+ Xpath 268435456 " X: 268435456
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 536870912 " X: 536870912
+ endif
+ if x == "a"
+ Xpath 1073741824 " X: 1073741824
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+catch /.*/
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ Xout v:exception "in" v:throwpoint
+finally
+ set ma&
+endtry
+
+unlet! caught x
+delfunction F1
+delfunction F2
+delfunction G
+delfunction H
+delfunction R
+
+Xcheck 2000403408
+
+
+"-------------------------------------------------------------------------------
+" Test 76: Errors, interupts, :throw during expression evaluation {{{1
+"
+" When a function call made during expression evaluation is aborted
+" due to an error inside a :try/:endtry region or due to an interrupt
+" or a :throw, the expression evaluation is aborted as well. No
+" message is displayed for the cancelled expression evaluation. On an
+" error not inside :try/:endtry, the expression evaluation continues.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ let taken = ""
+
+ function! ERR(n)
+ let g:taken = g:taken . "E" . a:n
+ asdf
+ endfunction
+
+ function! ERRabort(n) abort
+ let g:taken = g:taken . "A" . a:n
+ asdf
+ endfunction " returns -1
+
+ function! INT(n)
+ let g:taken = g:taken . "I" . a:n
+ "INTERRUPT9
+ let dummy = 0
+ endfunction
+
+ function! THR(n)
+ let g:taken = g:taken . "T" . a:n
+ throw "should not be caught"
+ endfunction
+
+ function! CONT(n)
+ let g:taken = g:taken . "C" . a:n
+ endfunction
+
+ function! MSG(n)
+ let g:taken = g:taken . "M" . a:n
+ if (a:n >= 10 && a:n <= 27) ? v:errmsg != "" : v:errmsg !~ "asdf"
+ let g:taken = g:taken . "x"
+ endif
+ let v:errmsg = ""
+ endfunction
+
+ let v:errmsg = ""
+
+ try
+ let t = 1
+ XloopINIT 1 2
+ while t <= 9
+ Xloop 1 " X: 511
+ try
+ if t == 1
+ let v{ERR(t) + CONT(t)} = 0
+ elseif t == 2
+ let v{ERR(t) + CONT(t)}
+ elseif t == 3
+ let var = exists('v{ERR(t) + CONT(t)}')
+ elseif t == 4
+ unlet v{ERR(t) + CONT(t)}
+ elseif t == 5
+ function F{ERR(t) + CONT(t)}()
+ endfunction
+ elseif t == 6
+ function F{ERR(t) + CONT(t)}
+ elseif t == 7
+ let var = exists('*F{ERR(t) + CONT(t)}')
+ elseif t == 8
+ delfunction F{ERR(t) + CONT(t)}
+ elseif t == 9
+ let var = ERR(t) + CONT(t)
+ endif
+ catch /asdf/
+ " v:errmsg is not set when the error message is converted to an
+ " exception. Set it to the original error message.
+ let v:errmsg = substitute(v:exception, '^Vim:', '', "")
+ catch /^Vim\((\a\+)\)\=:/
+ " An error exception has been thrown after the original error.
+ let v:errmsg = ""
+ finally
+ call MSG(t)
+ let t = t + 1
+ XloopNEXT
+ continue " discard an aborting error
+ endtry
+ endwhile
+ catch /.*/
+ Xpath 512 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+
+ try
+ let t = 10
+ XloopINIT 1024 2
+ while t <= 18
+ Xloop 1 " X: 1024 * 511
+ try
+ if t == 10
+ let v{INT(t) + CONT(t)} = 0
+ elseif t == 11
+ let v{INT(t) + CONT(t)}
+ elseif t == 12
+ let var = exists('v{INT(t) + CONT(t)}')
+ elseif t == 13
+ unlet v{INT(t) + CONT(t)}
+ elseif t == 14
+ function F{INT(t) + CONT(t)}()
+ endfunction
+ elseif t == 15
+ function F{INT(t) + CONT(t)}
+ elseif t == 16
+ let var = exists('*F{INT(t) + CONT(t)}')
+ elseif t == 17
+ delfunction F{INT(t) + CONT(t)}
+ elseif t == 18
+ let var = INT(t) + CONT(t)
+ endif
+ catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/
+ " An error exception has been triggered after the interrupt.
+ let v:errmsg = substitute(v:exception,
+ \ '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ call MSG(t)
+ let t = t + 1
+ XloopNEXT
+ continue " discard interrupt
+ endtry
+ endwhile
+ catch /.*/
+ Xpath 524288 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+
+ try
+ let t = 19
+ XloopINIT 1048576 2
+ while t <= 27
+ Xloop 1 " X: 1048576 * 511
+ try
+ if t == 19
+ let v{THR(t) + CONT(t)} = 0
+ elseif t == 20
+ let v{THR(t) + CONT(t)}
+ elseif t == 21
+ let var = exists('v{THR(t) + CONT(t)}')
+ elseif t == 22
+ unlet v{THR(t) + CONT(t)}
+ elseif t == 23
+ function F{THR(t) + CONT(t)}()
+ endfunction
+ elseif t == 24
+ function F{THR(t) + CONT(t)}
+ elseif t == 25
+ let var = exists('*F{THR(t) + CONT(t)}')
+ elseif t == 26
+ delfunction F{THR(t) + CONT(t)}
+ elseif t == 27
+ let var = THR(t) + CONT(t)
+ endif
+ catch /^Vim\((\a\+)\)\=:/
+ " An error exception has been triggered after the :throw.
+ let v:errmsg = substitute(v:exception,
+ \ '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ call MSG(t)
+ let t = t + 1
+ XloopNEXT
+ continue " discard exception
+ endtry
+ endwhile
+ catch /.*/
+ Xpath 536870912 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+
+ let v{ERR(28) + CONT(28)} = 0
+ call MSG(28)
+ let v{ERR(29) + CONT(29)}
+ call MSG(29)
+ let var = exists('v{ERR(30) + CONT(30)}')
+ call MSG(30)
+ unlet v{ERR(31) + CONT(31)}
+ call MSG(31)
+ function F{ERR(32) + CONT(32)}()
+ endfunction
+ call MSG(32)
+ function F{ERR(33) + CONT(33)}
+ call MSG(33)
+ let var = exists('*F{ERR(34) + CONT(34)}')
+ call MSG(34)
+ delfunction F{ERR(35) + CONT(35)}
+ call MSG(35)
+ let var = ERR(36) + CONT(36)
+ call MSG(36)
+
+ let v{ERRabort(37) + CONT(37)} = 0
+ call MSG(37)
+ let v{ERRabort(38) + CONT(38)}
+ call MSG(38)
+ let var = exists('v{ERRabort(39) + CONT(39)}')
+ call MSG(39)
+ unlet v{ERRabort(40) + CONT(40)}
+ call MSG(40)
+ function F{ERRabort(41) + CONT(41)}()
+ endfunction
+ call MSG(41)
+ function F{ERRabort(42) + CONT(42)}
+ call MSG(42)
+ let var = exists('*F{ERRabort(43) + CONT(43)}')
+ call MSG(43)
+ delfunction F{ERRabort(44) + CONT(44)}
+ call MSG(44)
+ let var = ERRabort(45) + CONT(45)
+ call MSG(45)
+
+ Xpath 1073741824 " X: 1073741824
+
+ let expected = ""
+ \ . "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9"
+ \ . "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18"
+ \ . "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27"
+ \ . "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33"
+ \ . "E34C34M34E35C35M35E36C36M36"
+ \ . "A37C37M37A38C38M38A39C39M39A40C40M40A41C41M41A42C42M42"
+ \ . "A43C43M43A44C44M44A45C45M45"
+
+ if taken != expected
+ " The Xpath command does not accept 2^31 (negative); display explicitly:
+ exec "!echo 2147483648 >>" . g:ExtraVimResult
+ " X: 0
+ Xout "'taken' is" taken "instead of" expected
+ if substitute(taken,
+ \ '\(.*\)E3C3M3x\(.*\)E30C30M30x\(.*\)A39C39M39x\(.*\)',
+ \ '\1E3M3\2E30C30M30\3A39C39M39\4',
+ \ "") == expected
+ Xout "Is ++emsg_skip for var with expr_start non-NULL"
+ \ "in f_exists ok?"
+ endif
+ endif
+
+ unlet! var taken expected
+ call delete(WA_t5)
+ call delete(WA_t14)
+ call delete(WA_t23)
+ unlet! WA_t5 WA_t14 WA_t23
+ delfunction WA_t5
+ delfunction WA_t14
+ delfunction WA_t23
+
+endif
+
+Xcheck 1610087935
+
+
+"-------------------------------------------------------------------------------
+" Test 77: Errors, interupts, :throw in name{brace-expression} {{{1
+"
+" When a function call made during evaluation of an expression in
+" braces as part of a function name after ":function" is aborted due
+" to an error inside a :try/:endtry region or due to an interrupt or
+" a :throw, the expression evaluation is aborted as well, and the
+" function definition is ignored, skipping all commands to the
+" ":endfunction". On an error not inside :try/:endtry, the expression
+" evaluation continues and the function gets defined, and can be
+" called and deleted.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT 1 4
+
+function! ERR() abort
+ Xloop 1 " X: 1 + 4 + 16 + 64
+ asdf
+endfunction " returns -1
+
+function! OK()
+ Xloop 2 " X: 2 * (1 + 4 + 16)
+ let v:errmsg = ""
+ return 0
+endfunction
+
+let v:errmsg = ""
+
+Xpath 4096 " X: 4096
+function! F{1 + ERR() + OK()}(arg)
+ " F0 should be defined.
+ if exists("a:arg") && a:arg == "calling"
+ Xpath 8192 " X: 8192
+ else
+ Xpath 16384 " X: 0
+ endif
+endfunction
+if v:errmsg != ""
+ Xpath 32768 " X: 0
+endif
+XloopNEXT
+
+Xpath 65536 " X: 65536
+call F{1 + ERR() + OK()}("calling")
+if v:errmsg != ""
+ Xpath 131072 " X: 0
+endif
+XloopNEXT
+
+Xpath 262144 " X: 262144
+delfunction F{1 + ERR() + OK()}
+if v:errmsg != ""
+ Xpath 524288 " X: 0
+endif
+XloopNEXT
+
+try
+ while 1
+ let caught = 0
+ try
+ Xpath 1048576 " X: 1048576
+ function! G{1 + ERR() + OK()}(arg)
+ " G0 should not be defined, and the function body should be
+ " skipped.
+ if exists("a:arg") && a:arg == "calling"
+ Xpath 2097152 " X: 0
+ else
+ Xpath 4194304 " X: 0
+ endif
+ " Use an unmatched ":finally" to check whether the body is
+ " skipped when an error occurs in ERR(). This works whether or
+ " not the exception is converted to an exception.
+ finally
+ Xpath 8388608 " X: 0
+ Xout "Body of G{1 + ERR() + OK()}() not skipped"
+ " Discard the aborting error or exception, and break the
+ " while loop.
+ break
+ " End the try conditional and start a new one to avoid
+ " ":catch after :finally" errors.
+ endtry
+ try
+ Xpath 16777216 " X: 0
+ endfunction
+
+ " When the function was not defined, this won't be reached - whether
+ " the body was skipped or not. When the function was defined, it
+ " can be called and deleted here.
+ Xpath 33554432 " X: 0
+ Xout "G0() has been defined"
+ XloopNEXT
+ try
+ call G{1 + ERR() + OK()}("calling")
+ catch /.*/
+ Xpath 67108864 " X: 0
+ endtry
+ Xpath 134217728 " X: 0
+ XloopNEXT
+ try
+ delfunction G{1 + ERR() + OK()}
+ catch /.*/
+ Xpath 268435456 " X: 0
+ endtry
+ catch /asdf/
+ " Jumped to when the function is not defined and the body is
+ " skipped.
+ let caught = 1
+ catch /.*/
+ Xpath 536870912 " X: 0
+ finally
+ if !caught && !$VIMNOERRTHROW
+ Xpath 1073741824 " X: 0
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry " jumped to when the body is not skipped
+ endwhile
+catch /.*/
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ Xout "Body of G{1 + ERR() + OK()}() not skipped, exception caught"
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xcheck 1388671
+
+
+"-------------------------------------------------------------------------------
+" Test 78: Messages on parsing errors in expression evaluation {{{1
+"
+" When an expression evaluation detects a parsing error, an error
+" message is given and converted to an exception, and the expression
+" evaluation is aborted.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ let taken = ""
+
+ function! F(n)
+ let g:taken = g:taken . "F" . a:n
+ endfunction
+
+ function! MSG(n, enr, emsg)
+ let g:taken = g:taken . "M" . a:n
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ if v:errmsg == ""
+ Xout "Expr" a:n.": Message missing."
+ let g:taken = g:taken . "x"
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Expr" a:n.": Unexpected message:" v:errmsg
+ let g:taken = g:taken . "X"
+ endif
+ endif
+ endfunction
+
+ function! CONT(n)
+ let g:taken = g:taken . "C" . a:n
+ endfunction
+
+ let v:errmsg = ""
+ XloopINIT 1 2
+
+ try
+ let t = 1
+ while t <= 14
+ let g:taken = g:taken . "T" . t
+ let v:errmsg = ""
+ try
+ let caught = 0
+ if t == 1
+ let v{novar + CONT(t)} = 0
+ elseif t == 2
+ let v{novar + CONT(t)}
+ elseif t == 3
+ let var = exists('v{novar + CONT(t)}')
+ elseif t == 4
+ unlet v{novar + CONT(t)}
+ elseif t == 5
+ function F{novar + CONT(t)}()
+ endfunction
+ elseif t == 6
+ function F{novar + CONT(t)}
+ elseif t == 7
+ let var = exists('*F{novar + CONT(t)}')
+ elseif t == 8
+ delfunction F{novar + CONT(t)}
+ elseif t == 9
+ echo novar + CONT(t)
+ elseif t == 10
+ echo v{novar + CONT(t)}
+ elseif t == 11
+ echo F{novar + CONT(t)}
+ elseif t == 12
+ let var = novar + CONT(t)
+ elseif t == 13
+ let var = v{novar + CONT(t)}
+ elseif t == 14
+ let var = F{novar + CONT(t)}()
+ endif
+ catch /^Vim\((\a\+)\)\=:/
+ " v:errmsg is not set when the error message is converted to an
+ " exception. Set it to the original error message.
+ let v:errmsg = substitute(v:exception,
+ \ '^Vim\((\a\+)\)\=:', '', "")
+ let caught = 1
+ finally
+ if !caught " no error exceptions ($VIMNOERRTHROW set)
+ if t <= 8 && t != 3
+ call MSG(t, 'E475', 'Invalid argument\>')
+ else
+ call MSG(t, 'E15', "Invalid expression")
+ endif
+ else
+ if t == 2 || t == 4
+ call MSG(t, 'E475', 'Invalid argument\>')
+ else
+ call MSG(t, 'E121', "Undefined variable")
+ endif
+ endif
+ let t = t + 1
+ XloopNEXT
+ continue " discard an aborting error
+ endtry
+ endwhile
+ catch /.*/
+ Xloop 1 " X: 0
+ Xout t.":" v:exception "in" ExtraVimThrowpoint()
+ endtry
+
+ function! T(n, expr, enr, emsg)
+ try
+ let g:taken = g:taken . "T" . a:n
+ let v:errmsg = ""
+ try
+ let caught = 0
+ execute "let var = " . a:expr
+ catch /^Vim\((\a\+)\)\=:/
+ " v:errmsg is not set when the error message is converted to an
+ " exception. Set it to the original error message.
+ let v:errmsg = substitute(v:exception,
+ \ '^Vim\((\a\+)\)\=:', '', "")
+ let caught = 1
+ finally
+ if !caught " no error exceptions ($VIMNOERRTHROW set)
+ call MSG(a:n, 'E15', "Invalid expression")
+ else
+ call MSG(a:n, a:enr, a:emsg)
+ endif
+ XloopNEXT
+ " Discard an aborting error:
+ return
+ endtry
+ catch /.*/
+ Xloop 1 " X: 0
+ Xout a:n.":" v:exception "in" ExtraVimThrowpoint()
+ endtry
+ endfunction
+
+ call T(15, 'Nofunc() + CONT(15)', 'E117', "Unknown function")
+ call T(16, 'F(1 2 + CONT(16))', 'E116', "Invalid arguments")
+ call T(17, 'F(1, 2) + CONT(17)', 'E118', "Too many arguments")
+ call T(18, 'F() + CONT(18)', 'E119', "Not enough arguments")
+ call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'")
+ call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'")
+ call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression")
+ call T(22, '1 2 + CONT(22)', 'E15', "Invalid expression")
+ call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'")
+ call T(24, '("abc) + CONT(24)', 'E114', "Missing quote")
+ call T(25, "('abc) + CONT(25)", 'E115', "Missing quote")
+ call T(26, '& + CONT(26)', 'E112', "Option name missing")
+ call T(27, '&asdf + CONT(27)', 'E113', "Unknown option")
+
+ Xpath 134217728 " X: 134217728
+
+ let expected = ""
+ \ . "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14"
+ \ . "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25"
+ \ . "T26M26T27M27"
+
+ if taken != expected
+ Xpath 268435456 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+ if substitute(taken, '\(.*\)T3M3x\(.*\)', '\1T3M3\2', "") == expected
+ Xout "Is ++emsg_skip for var with expr_start non-NULL"
+ \ "in f_exists ok?"
+ endif
+ endif
+
+ unlet! var caught taken expected
+ call delete(WA_t5)
+ unlet! WA_t5
+ delfunction WA_t5
+
+endif
+
+Xcheck 134217728
+
+
+"-------------------------------------------------------------------------------
+" Test 79: Throwing one of several errors for the same command {{{1
+"
+" When several errors appear in a row (for instance during expression
+" evaluation), the first as the most specific one is used when
+" throwing an error exception. If, however, a syntax error is
+" detected afterwards, this one is used for the error exception.
+" On a syntax error, the next command is not executed, on a normal
+" error, however, it is (relevant only in a function without the
+" "abort" flag). v:errmsg is not set.
+"
+" If throwing error exceptions is configured off, v:errmsg is always
+" set to the latest error message, that is, to the more general
+" message or the syntax error, respectively.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT 1 2
+
+function! NEXT(cmd)
+ exec a:cmd . " | Xloop 1"
+endfunction
+
+call NEXT('echo novar') " X: 1 * 1 (checks nextcmd)
+XloopNEXT
+call NEXT('let novar #') " X: 0 * 2 (skips nextcmd)
+XloopNEXT
+call NEXT('unlet novar #') " X: 0 * 4 (skips nextcmd)
+XloopNEXT
+call NEXT('let {novar}') " X: 0 * 8 (skips nextcmd)
+XloopNEXT
+call NEXT('unlet{ novar}') " X: 0 * 16 (skips nextcmd)
+
+function! EXEC(cmd)
+ exec a:cmd
+endfunction
+
+function! MATCH(expected, msg, enr, emsg)
+ let msg = a:msg
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let msg = ":" . msg
+ endif
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if msg !~ '^'.a:enr.':' || (english && msg !~ a:emsg)
+ let match = 0
+ if a:expected " no match although expected
+ if a:msg == ""
+ Xout "Message missing."
+ else
+ let msg = escape(msg, '"')
+ Xout "Unexpected message:" msg
+ endif
+ endif
+ else
+ let match = 1
+ if !a:expected " match although not expected
+ let msg = escape(msg, '"')
+ Xout "Unexpected message:" msg
+ endif
+ endif
+ return match
+endfunction
+
+try
+
+ while 1 " dummy loop
+ try
+ let v:errmsg = ""
+ let caught = 0
+ let thrmsg = ""
+ call EXEC('echo novar') " normal error
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xpath 32 " X: 32
+ if !caught
+ if !$VIMNOERRTHROW
+ Xpath 64 " X: 0
+ endif
+ elseif !MATCH(1, thrmsg, 'E121', "Undefined variable")
+ \ || v:errmsg != ""
+ Xpath 128 " X: 0
+ endif
+ if !caught && !MATCH(1, v:errmsg, 'E15', "Invalid expression")
+ Xpath 256 " X: 0
+ endif
+ break " discard error if $VIMNOERRTHROW == 1
+ endtry
+ endwhile
+
+ Xpath 512 " X: 512
+ let cmd = "let"
+ XloopINIT 1024 32
+ while cmd != ""
+ try
+ let v:errmsg = ""
+ let caught = 0
+ let thrmsg = ""
+ call EXEC(cmd . ' novar #') " normal plus syntax error
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xloop 1 " X: 1024 * (1 + 32)
+ if !caught
+ if !$VIMNOERRTHROW
+ Xloop 2 " X: 0
+ endif
+ else
+ if cmd == "let"
+ let match = MATCH(0, thrmsg, 'E106', "Unknown variable")
+ elseif cmd == "unlet"
+ let match = MATCH(0, thrmsg, 'E108', "No such variable")
+ endif
+ if match " normal error
+ Xloop 4 " X: 0
+ endif
+ if !MATCH(1, thrmsg, 'E488', "Trailing characters")
+ \|| v:errmsg != ""
+ " syntax error
+ Xloop 8 " X: 0
+ endif
+ endif
+ if !caught && !MATCH(1, v:errmsg, 'E488', "Trailing characters")
+ " last error
+ Xloop 16 " X: 0
+ endif
+ if cmd == "let"
+ let cmd = "unlet"
+ else
+ let cmd = ""
+ endif
+ XloopNEXT
+ continue " discard error if $VIMNOERRTHROW == 1
+ endtry
+ endwhile
+
+ Xpath 1048576 " X: 1048576
+ let cmd = "let"
+ XloopINIT 2097152 32
+ while cmd != ""
+ try
+ let v:errmsg = ""
+ let caught = 0
+ let thrmsg = ""
+ call EXEC(cmd . ' {novar}') " normal plus syntax error
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xloop 1 " X: 2097152 * (1 + 32)
+ if !caught
+ if !$VIMNOERRTHROW
+ Xloop 2 " X: 0
+ endif
+ else
+ if MATCH(0, thrmsg, 'E121', "Undefined variable") " normal error
+ Xloop 4 " X: 0
+ endif
+ if !MATCH(1, thrmsg, 'E475', 'Invalid argument\>')
+ \ || v:errmsg != "" " syntax error
+ Xloop 8 " X: 0
+ endif
+ endif
+ if !caught && !MATCH(1, v:errmsg, 'E475', 'Invalid argument\>')
+ " last error
+ Xloop 16 " X: 0
+ endif
+ if cmd == "let"
+ let cmd = "unlet"
+ else
+ let cmd = ""
+ endif
+ XloopNEXT
+ continue " discard error if $VIMNOERRTHROW == 1
+ endtry
+ endwhile
+
+catch /.*/
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+unlet! next_command thrmsg match
+delfunction NEXT
+delfunction EXEC
+delfunction MATCH
+
+Xcheck 70288929
+
+
+"-------------------------------------------------------------------------------
+" Test 80: Syntax error in expression for illegal :elseif {{{1
+"
+" If there is a syntax error in the expression after an illegal
+" :elseif, an error message is given (or an error exception thrown)
+" for the illegal :elseif rather than the expression error.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ let match = 1
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ let match = 0
+ if v:errmsg == ""
+ Xout "Message missing."
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Unexpected message:" v:errmsg
+ endif
+ endif
+ return match
+endfunction
+
+let v:errmsg = ""
+if 0
+else
+elseif 1 ||| 2
+endif
+Xpath 1 " X: 1
+if !MSG('E584', ":elseif after :else")
+ Xpath 2 " X: 0
+endif
+
+let v:errmsg = ""
+if 1
+else
+elseif 1 ||| 2
+endif
+Xpath 4 " X: 4
+if !MSG('E584', ":elseif after :else")
+ Xpath 8 " X: 0
+endif
+
+let v:errmsg = ""
+elseif 1 ||| 2
+Xpath 16 " X: 16
+if !MSG('E582', ":elseif without :if")
+ Xpath 32 " X: 0
+endif
+
+let v:errmsg = ""
+while 1
+ elseif 1 ||| 2
+endwhile
+Xpath 64 " X: 64
+if !MSG('E582', ":elseif without :if")
+ Xpath 128 " X: 0
+endif
+
+while 1
+ try
+ try
+ let v:errmsg = ""
+ let caught = 0
+ if 0
+ else
+ elseif 1 ||| 2
+ endif
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xpath 256 " X: 256
+ if !caught && !$VIMNOERRTHROW
+ Xpath 512 " X: 0
+ endif
+ if !MSG('E584', ":elseif after :else")
+ Xpath 1024 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 2048 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let v:errmsg = ""
+ let caught = 0
+ if 1
+ else
+ elseif 1 ||| 2
+ endif
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xpath 4096 " X: 4096
+ if !caught && !$VIMNOERRTHROW
+ Xpath 8192 " X: 0
+ endif
+ if !MSG('E584', ":elseif after :else")
+ Xpath 16384 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 32768 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let v:errmsg = ""
+ let caught = 0
+ elseif 1 ||| 2
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xpath 65536 " X: 65536
+ if !caught && !$VIMNOERRTHROW
+ Xpath 131072 " X: 0
+ endif
+ if !MSG('E582', ":elseif without :if")
+ Xpath 262144 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 524288 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let v:errmsg = ""
+ let caught = 0
+ while 1
+ elseif 1 ||| 2
+ endwhile
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xpath 1048576 " X: 1048576
+ if !caught && !$VIMNOERRTHROW
+ Xpath 2097152 " X: 0
+ endif
+ if !MSG('E582', ":elseif without :if")
+ Xpath 4194304 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 8388608 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+Xpath 16777216 " X: 16777216
+
+unlet! caught
+delfunction MSG
+
+Xcheck 17895765
+
+
+"-------------------------------------------------------------------------------
+" Test 81: Discarding exceptions after an error or interrupt {{{1
+"
+" When an exception is thrown from inside a :try conditional without
+" :catch and :finally clauses and an error or interrupt occurs before
+" the :endtry is reached, the exception is discarded.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ try
+ Xpath 1 " X: 1
+ try
+ Xpath 2 " X: 2
+ throw "arrgh"
+ Xpath 4 " X: 0
+" if 1
+ Xpath 8 " X: 0
+ " error after :throw: missing :endif
+ endtry
+ Xpath 16 " X: 0
+ catch /arrgh/
+ Xpath 32 " X: 0
+ endtry
+ Xpath 64 " X: 0
+endif
+
+if ExtraVim()
+ try
+ Xpath 128 " X: 128
+ try
+ Xpath 256 " X: 256
+ throw "arrgh"
+ Xpath 512 " X: 0
+ endtry " INTERRUPT
+ Xpath 1024 " X: 0
+ catch /arrgh/
+ Xpath 2048 " X: 0
+ endtry
+ Xpath 4096 " X: 0
+endif
+
+Xcheck 387
+
+
+"-------------------------------------------------------------------------------
+" Test 82: Ignoring :catch clauses after an error or interrupt {{{1
+"
+" When an exception is thrown and an error or interrupt occurs before
+" the matching :catch clause is reached, the exception is discarded
+" and the :catch clause is ignored (also for the error or interrupt
+" exception being thrown then).
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ try
+ try
+ Xpath 1 " X: 1
+ throw "arrgh"
+ Xpath 2 " X: 0
+" if 1
+ Xpath 4 " X: 0
+ " error after :throw: missing :endif
+ catch /.*/
+ Xpath 8 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ catch /.*/
+ Xpath 16 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+ Xpath 32 " X: 0
+ catch /arrgh/
+ Xpath 64 " X: 0
+ endtry
+ Xpath 128 " X: 0
+endif
+
+if ExtraVim()
+ function! E()
+ try
+ try
+ Xpath 256 " X: 256
+ throw "arrgh"
+ Xpath 512 " X: 0
+" if 1
+ Xpath 1024 " X: 0
+ " error after :throw: missing :endif
+ catch /.*/
+ Xpath 2048 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ catch /.*/
+ Xpath 4096 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+ Xpath 8192 " X: 0
+ catch /arrgh/
+ Xpath 16384 " X: 0
+ endtry
+ endfunction
+
+ call E()
+ Xpath 32768 " X: 0
+endif
+
+if ExtraVim()
+ try
+ try
+ Xpath 65536 " X: 65536
+ throw "arrgh"
+ Xpath 131072 " X: 0
+ catch /.*/ "INTERRUPT
+ Xpath 262144 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ catch /.*/
+ Xpath 524288 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+ Xpath 1048576 " X: 0
+ catch /arrgh/
+ Xpath 2097152 " X: 0
+ endtry
+ Xpath 4194304 " X: 0
+endif
+
+if ExtraVim()
+ function I()
+ try
+ try
+ Xpath 8388608 " X: 8388608
+ throw "arrgh"
+ Xpath 16777216 " X: 0
+ catch /.*/ "INTERRUPT
+ Xpath 33554432 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ catch /.*/
+ Xpath 67108864 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+ Xpath 134217728 " X: 0
+ catch /arrgh/
+ Xpath 268435456 " X: 0
+ endtry
+ endfunction
+
+ call I()
+ Xpath 536870912 " X: 0
+endif
+
+Xcheck 8454401
+
+
+"-------------------------------------------------------------------------------
+" Test 83: Executing :finally clauses after an error or interrupt {{{1
+"
+" When an exception is thrown and an error or interrupt occurs before
+" the :finally of the innermost :try is reached, the exception is
+" discarded and the :finally clause is executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ try
+ Xpath 1 " X: 1
+ try
+ Xpath 2 " X: 2
+ throw "arrgh"
+ Xpath 4 " X: 0
+" if 1
+ Xpath 8 " X: 0
+ " error after :throw: missing :endif
+ finally
+ Xpath 16 " X: 16
+ endtry
+ Xpath 32 " X: 0
+ catch /arrgh/
+ Xpath 64 " X: 0
+ endtry
+ Xpath 128 " X: 0
+endif
+
+if ExtraVim()
+ try
+ Xpath 256 " X: 256
+ try
+ Xpath 512 " X: 512
+ throw "arrgh"
+ Xpath 1024 " X: 0
+ finally "INTERRUPT
+ Xpath 2048 " X: 2048
+ endtry
+ Xpath 4096 " X: 0
+ catch /arrgh/
+ Xpath 8192 " X: 0
+ endtry
+ Xpath 16384 " X: 0
+endif
+
+Xcheck 2835
+
+
+"-------------------------------------------------------------------------------
+" Test 84: Exceptions in autocommand sequences. {{{1
+"
+" When an exception occurs in a sequence of autocommands for
+" a specific event, the rest of the sequence is not executed. The
+" command that triggered the autocommand execution aborts, and the
+" exception is propagated to the caller.
+"
+" For the FuncUndefined event under a function call expression or
+" :call command, the function is not exexecuted, even when it has
+" been defined by the autocommands before the exception occurred.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ function! INT()
+ "INTERRUPT
+ let dummy = 0
+ endfunction
+
+ aug TMP
+ autocmd!
+
+ autocmd User x1 Xpath 1 " X: 1
+ autocmd User x1 throw "x1"
+ autocmd User x1 Xpath 2 " X: 0
+
+ autocmd User x2 Xpath 4 " X: 4
+ autocmd User x2 asdf
+ autocmd User x2 Xpath 8 " X: 0
+
+ autocmd User x3 Xpath 16 " X: 16
+ autocmd User x3 call INT()
+ autocmd User x3 Xpath 32 " X: 0
+
+ autocmd FuncUndefined U1 function! U1()
+ autocmd FuncUndefined U1 Xpath 64 " X: 0
+ autocmd FuncUndefined U1 endfunction
+ autocmd FuncUndefined U1 Xpath 128 " X: 128
+ autocmd FuncUndefined U1 throw "U1"
+ autocmd FuncUndefined U1 Xpath 256 " X: 0
+
+ autocmd FuncUndefined U2 function! U2()
+ autocmd FuncUndefined U2 Xpath 512 " X: 0
+ autocmd FuncUndefined U2 endfunction
+ autocmd FuncUndefined U2 Xpath 1024 " X: 1024
+ autocmd FuncUndefined U2 ASDF
+ autocmd FuncUndefined U2 Xpath 2048 " X: 0
+
+ autocmd FuncUndefined U3 function! U3()
+ autocmd FuncUndefined U3 Xpath 4096 " X: 0
+ autocmd FuncUndefined U3 endfunction
+ autocmd FuncUndefined U3 Xpath 8192 " X: 8192
+ autocmd FuncUndefined U3 call INT()
+ autocmd FuncUndefined U3 Xpath 16384 " X: 0
+ aug END
+
+ try
+ try
+ Xpath 32768 " X: 32768
+ doautocmd User x1
+ catch /x1/
+ Xpath 65536 " X: 65536
+ endtry
+
+ while 1
+ try
+ Xpath 131072 " X: 131072
+ let caught = 0
+ doautocmd User x2
+ catch /asdf/
+ let caught = 1
+ finally
+ Xpath 262144 " X: 262144
+ if !caught && !$VIMNOERRTHROW
+ Xpath 524288 " X: 0
+ " Propagate uncaught error exception,
+ else
+ " ... but break loop for caught error exception,
+ " or discard error and break loop if $VIMNOERRTHROW
+ break
+ endif
+ endtry
+ endwhile
+
+ while 1
+ try
+ Xpath 1048576 " X: 1048576
+ let caught = 0
+ doautocmd User x3
+ catch /Vim:Interrupt/
+ let caught = 1
+ finally
+ Xpath 2097152 " X: 2097152
+ if !caught && !$VIMNOINTTHROW
+ Xpath 4194304 " X: 0
+ " Propagate uncaught interrupt exception,
+ else
+ " ... but break loop for caught interrupt exception,
+ " or discard interrupt and break loop if $VIMNOINTTHROW
+ break
+ endif
+ endtry
+ endwhile
+
+ if exists("*U1") | delfunction U1 | endif
+ if exists("*U2") | delfunction U2 | endif
+ if exists("*U3") | delfunction U3 | endif
+
+ try
+ Xpath 8388608 " X: 8388608
+ call U1()
+ catch /U1/
+ Xpath 16777216 " X: 16777216
+ endtry
+
+ while 1
+ try
+ Xpath 33554432 " X: 33554432
+ let caught = 0
+ call U2()
+ catch /ASDF/
+ let caught = 1
+ finally
+ Xpath 67108864 " X: 67108864
+ if !caught && !$VIMNOERRTHROW
+ Xpath 134217728 " X: 0
+ " Propagate uncaught error exception,
+ else
+ " ... but break loop for caught error exception,
+ " or discard error and break loop if $VIMNOERRTHROW
+ break
+ endif
+ endtry
+ endwhile
+
+ while 1
+ try
+ Xpath 268435456 " X: 268435456
+ let caught = 0
+ call U3()
+ catch /Vim:Interrupt/
+ let caught = 1
+ finally
+ Xpath 536870912 " X: 536870912
+ if !caught && !$VIMNOINTTHROW
+ Xpath 1073741824 " X: 0
+ " Propagate uncaught interrupt exception,
+ else
+ " ... but break loop for caught interrupt exception,
+ " or discard interrupt and break loop if $VIMNOINTTHROW
+ break
+ endif
+ endtry
+ endwhile
+ catch /.*/
+ " The Xpath command does not accept 2^31 (negative); display explicitly:
+ exec "!echo 2147483648 >>" . g:ExtraVimResult
+ Xout "Caught" v:exception "in" v:throwpoint
+ endtry
+
+ unlet caught
+ delfunction INT
+ delfunction U1
+ delfunction U2
+ delfunction U3
+ au! TMP
+ aug! TMP
+endif
+
+Xcheck 934782101
+
+
+"-------------------------------------------------------------------------------
+" Test 85: Error exceptions in autocommands for I/O command events {{{1
+"
+" When an I/O command is inside :try/:endtry, autocommands to be
+" executed after it should be skipped on an error (exception) in the
+" command itself or in autocommands to be executed before the command.
+" In the latter case, the I/O command should not be executed either.
+" Example 1: BufWritePre, :write, BufWritePost
+" Example 2: FileReadPre, :read, FileReadPost.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ let match = 1
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ let match = 0
+ if v:errmsg == ""
+ Xout "Message missing."
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Unexpected message:" v:errmsg
+ endif
+ endif
+ return match
+endfunction
+
+" Remove the autocommands for the events specified as arguments in all used
+" autogroups.
+function! Delete_autocommands(...)
+ let augfile = tempname()
+ while 1
+ try
+ exec "redir >" . augfile
+ aug
+ redir END
+ exec "edit" augfile
+ g/^$/d
+ norm G$
+ let wrap = "w"
+ while search('\%( \|^\)\@<=.\{-}\%( \)\@=', wrap) > 0
+ let wrap = "W"
+ exec "norm y/ \n"
+ let argno = 1
+ while argno <= a:0
+ exec "au!" escape(@", " ") a:{argno}
+ let argno = argno + 1
+ endwhile
+ endwhile
+ catch /.*/
+ finally
+ bwipeout!
+ call delete(augfile)
+ break " discard errors for $VIMNOERRTHROW
+ endtry
+ endwhile
+endfunction
+
+call Delete_autocommands("BufWritePre", "BufWritePost")
+
+while 1
+ try
+ try
+ let post = 0
+ aug TMP
+ au! BufWritePost * let post = 1
+ aug END
+ let caught = 0
+ write /n/o/n/e/x/i/s/t/e/n/t
+ catch /^Vim(write):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(write):', '', "")
+ finally
+ Xpath 1 " X: 1
+ if !caught && !$VIMNOERRTHROW
+ Xpath 2 " X: 0
+ endif
+ let v:errmsg = substitute(v:errmsg, '^"/n/o/n/e/x/i/s/t/e/n/t" ',
+ \ '', "")
+ if !MSG('E212', "Can't open file for writing")
+ Xpath 4 " X: 0
+ endif
+ if post
+ Xpath 8 " X: 0
+ Xout "BufWritePost commands executed after write error"
+ endif
+ au! TMP
+ aug! TMP
+ endtry
+ catch /.*/
+ Xpath 16 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let post = 0
+ aug TMP
+ au! BufWritePre * asdf
+ au! BufWritePost * let post = 1
+ aug END
+ let tmpfile = tempname()
+ let caught = 0
+ exec "write" tmpfile
+ catch /^Vim\((write)\)\=:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim\((write)\)\=:', '', "")
+ finally
+ Xpath 32 " X: 32
+ if !caught && !$VIMNOERRTHROW
+ Xpath 64 " X: 0
+ endif
+ let v:errmsg = substitute(v:errmsg, '^"'.tmpfile.'" ', '', "")
+ if !MSG('E492', "Not an editor command")
+ Xpath 128 " X: 0
+ endif
+ if filereadable(tmpfile)
+ Xpath 256 " X: 0
+ Xout ":write command not suppressed after BufWritePre error"
+ endif
+ if post
+ Xpath 512 " X: 0
+ Xout "BufWritePost commands executed after BufWritePre error"
+ endif
+ au! TMP
+ aug! TMP
+ endtry
+ catch /.*/
+ Xpath 1024 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+call delete(tmpfile)
+
+call Delete_autocommands("BufWritePre", "BufWritePost",
+ \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost")
+
+while 1
+ try
+ try
+ let post = 0
+ aug TMP
+ au! FileReadPost * let post = 1
+ aug END
+ let caught = 0
+ read /n/o/n/e/x/i/s/t/e/n/t
+ catch /^Vim(read):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(read):', '', "")
+ finally
+ Xpath 2048 " X: 2048
+ if !caught && !$VIMNOERRTHROW
+ Xpath 4096 " X: 0
+ endif
+ let v:errmsg = substitute(v:errmsg, ' /n/o/n/e/x/i/s/t/e/n/t$',
+ \ '', "")
+ if !MSG('E484', "Can't open file")
+ Xpath 8192 " X: 0
+ endif
+ if post
+ Xpath 16384 " X: 0
+ Xout "FileReadPost commands executed after write error"
+ endif
+ au! TMP
+ aug! TMP
+ endtry
+ catch /.*/
+ Xpath 32768 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ let infile = tempname()
+ let tmpfile = tempname()
+ exec "!echo XYZ >" . infile
+ exec "edit" tmpfile
+ try
+ Xpath 65536 " X: 65536
+ try
+ let post = 0
+ aug TMP
+ au! FileReadPre * asdf
+ au! FileReadPost * let post = 1
+ aug END
+ let caught = 0
+ exec "0read" infile
+ catch /^Vim\((read)\)\=:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim\((read)\)\=:', '',
+ \ "")
+ finally
+ Xpath 131072 " X: 131072
+ if !caught && !$VIMNOERRTHROW
+ Xpath 262144 " X: 0
+ endif
+ let v:errmsg = substitute(v:errmsg, ' '.infile.'$', '', "")
+ if !MSG('E492', "Not an editor command")
+ Xpath 524288 " X: 0
+ endif
+ if getline("1") == "XYZ"
+ Xpath 1048576 " X: 0
+ Xout ":read command not suppressed after FileReadPre error"
+ endif
+ if post
+ Xpath 2097152 " X: 0
+ Xout "FileReadPost commands executed after " .
+ \ "FileReadPre error"
+ endif
+ au! TMP
+ aug! TMP
+ endtry
+ finally
+ bwipeout!
+ endtry
+ catch /.*/
+ Xpath 4194304 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+call delete(infile)
+call delete(tmpfile)
+unlet! caught post infile tmpfile
+delfunction MSG
+delfunction Delete_autocommands
+
+Xcheck 198689
+
+
+"-------------------------------------------------------------------------------
+" Test 86: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1
+"
+" It is possible to configure Vim for throwing exceptions on error
+" or interrupt, controlled by variables $VIMNOERRTHROW and
+" $VIMNOINTTHROW. This is just for increasing the number of tests.
+" All tests here should run for all four combinations of setting
+" these variables to 0 or 1. The variables are intended for the
+" development phase only. In the final release, Vim should be
+" configured to always use error and interrupt exceptions.
+"
+" The test result is "OK",
+"
+" - if the $VIMNOERRTHROW and the $VIMNOINTTHROW control are not
+" configured and exceptions are thrown on error and on
+" interrupt.
+"
+" - if the $VIMNOERRTHROW or the $VIMNOINTTHROW control is
+" configured and works as intended.
+"
+" What actually happens, is shown in the test output.
+"
+" Otherwise, the test result is "FAIL", and the test output describes
+" the problem.
+"
+" IMPORTANT: This must be the last test because it sets $VIMNOERRTHROW and
+" $VIMNOINTTHROW.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ function! ThrowOnError()
+ XloopNEXT
+ let caught = 0
+ try
+ Xloop 1 " X: 1 + 8 + 64
+ asdf
+ catch /.*/
+ let caught = 1 " error exception caught
+ finally
+ Xloop 2 " X: 2 + 16 + 128
+ return caught " discard aborting error
+ endtry
+ Xloop 4 " X: 0
+ endfunction
+
+ let quits_skipped = 0
+
+ function! ThrowOnInterrupt()
+ XloopNEXT
+ let caught = 0
+ try
+ Xloop 1 " X: (1 + 8 + 64) * 512
+ "INTERRUPT3
+ let dummy = 0
+ let g:quits_skipped = g:quits_skipped + 1
+ catch /.*/
+ let caught = 1 " interrupt exception caught
+ finally
+ Xloop 2 " X: (2 + 16 + 128) * 512
+ return caught " discard interrupt
+ endtry
+ Xloop 4 " X: 0
+ endfunction
+
+ function! CheckThrow(Type)
+ execute 'return ThrowOn' . a:Type . '()'
+ endfunction
+
+ function! CheckConfiguration(type) " type is "error" or "interrupt"
+
+ let type = a:type
+ let Type = substitute(type, '.*', '\u&', "")
+ let VAR = '$VIMNO' . substitute(type, '\(...\).*', '\U\1', "") . 'THROW'
+
+ if type == "error"
+ XloopINIT! 1 8
+ elseif type == "interrupt"
+ XloopINIT! 512 8
+ endif
+
+ exec 'let requested_for_tests = exists(VAR) && ' . VAR . ' == 0'
+ exec 'let suppressed_for_tests = ' . VAR . ' != 0'
+ let used_in_tests = CheckThrow(Type)
+
+ exec 'let ' . VAR . ' = 0'
+ let request_works = CheckThrow(Type)
+
+ exec 'let ' . VAR . ' = 1'
+ let suppress_works = !CheckThrow(Type)
+
+ if type == "error"
+ XloopINIT! 262144 8
+ elseif type == "interrupt"
+ XloopINIT! 2097152 8
+
+ if g:quits_skipped != 0
+ Xloop 1 " X: 0*2097152
+ Xout "Test environment error. Interrupt breakpoints skipped: "
+ \ . g:quits_skipped . ".\n"
+ \ . "Cannot check whether interrupt exceptions are thrown."
+ return
+ endif
+ endif
+
+ let failure =
+ \ !suppressed_for_tests && !used_in_tests
+ \ || !request_works
+
+ let contradiction =
+ \ used_in_tests
+ \ ? suppressed_for_tests && !request_works
+ \ : !suppressed_for_tests
+
+ if failure
+ " Failure in configuration.
+ Xloop 2 " X: 0 * 2* (262144 + 2097152)
+ elseif contradiction
+ " Failure in test logic. Should not happen.
+ Xloop 4 " X: 0 * 4 * (262144 + 2097152)
+ endif
+
+ let var_control_configured =
+ \ request_works != used_in_tests
+ \ || suppress_works == used_in_tests
+
+ let var_control_not_configured =
+ \ requested_for_tests || suppressed_for_tests
+ \ ? request_works && !suppress_works
+ \ : request_works == used_in_tests
+ \ && suppress_works != used_in_tests
+
+ let with = used_in_tests ? "with" : "without"
+
+ let set = suppressed_for_tests ? "non-zero" :
+ \ requested_for_tests ? "0" : "unset"
+
+ let although = contradiction && !var_control_not_configured
+ \ ? ",\nalthough "
+ \ : ".\n"
+
+ let output = "All tests were run " . with . " throwing exceptions on "
+ \ . type . although
+
+ if !var_control_not_configured
+ let output = output . VAR . " was " . set . "."
+
+ if !request_works && !requested_for_tests
+ let output = output .
+ \ "\n" . Type . " exceptions are not thrown when " . VAR .
+ \ " is\nset to 0."
+ endif
+
+ if !suppress_works && (!used_in_tests ||
+ \ !request_works &&
+ \ !requested_for_tests && !suppressed_for_tests)
+ let output = output .
+ \ "\n" . Type . " exceptions are thrown when " . VAR .
+ \ " is set to 1."
+ endif
+
+ if !failure && var_control_configured
+ let output = output .
+ \ "\nRun tests also with " . substitute(VAR, '^\$', '', "")
+ \ . "=" . used_in_tests . "."
+ \ . "\nThis is for testing in the development phase only."
+ \ . " Remove the \n"
+ \ . VAR . " control in the final release."
+ endif
+ else
+ let output = output .
+ \ "The " . VAR . " control is not configured."
+ endif
+
+ Xout output
+ endfunction
+
+ call CheckConfiguration("error")
+ Xpath 16777216 " X: 16777216
+ call CheckConfiguration("interrupt")
+ Xpath 33554432 " X: 33554432
+endif
+
+Xcheck 50443995
+
+" IMPORTANT: No test should be added after this test because it changes
+" $VIMNOERRTHROW and $VIMNOINTTHROW.
+
+
+"-------------------------------------------------------------------------------
+" Modelines {{{1
+" vim: ts=8 sw=4 tw=80 fdm=marker
+" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
+"-------------------------------------------------------------------------------
diff --git a/src/testdir/test5.in b/src/testdir/test5.in
new file mode 100644
index 000000000..e19e20d59
--- /dev/null
+++ b/src/testdir/test5.in
@@ -0,0 +1,29 @@
+Test for autocommand that deletes the current buffer on BufLeave event.
+Also test deleting the last buffer, should give a new, empty buffer.
+
+STARTTEST
+:so small.vim
+:au BufLeave Xxx bwipe
+/start of
+:.,/end of/w! Xxx " write test file Xxx
+:sp Xxx " split to Xxx
+:bwipe " delete buffer Xxx, now we're back here
+G?this is a
+othis is some more text
+: " Append some text to this file
+:?start?,$w! test.out " Write current file contents
+:bwipe test.out " delete alternate buffer
+:au bufleave test5.in bwipe
+:bwipe! " delete current buffer, get an empty one
+ithis is another test line:w >>test.out
+: " append an extra line to the output file
+:qa!
+ENDTEST
+
+start of test file Xxx
+vim: set noai :
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+end of test file Xxx
diff --git a/src/testdir/test5.ok b/src/testdir/test5.ok
new file mode 100644
index 000000000..674306079
--- /dev/null
+++ b/src/testdir/test5.ok
@@ -0,0 +1,9 @@
+start of test file Xxx
+vim: set noai :
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+this is some more text
+end of test file Xxx
+this is another test line
diff --git a/src/testdir/test50.in b/src/testdir/test50.in
new file mode 100644
index 000000000..d78ac8e8f
--- /dev/null
+++ b/src/testdir/test50.in
@@ -0,0 +1,85 @@
+Test for shortpathname ':8' extension.
+Only for use on Win32 systems!
+
+STARTTEST
+:so small.vim
+:fun! TestIt(file, bits, expected)
+ let res=fnamemodify(a:file,a:bits)
+ if a:expected == ''
+ echo "'".a:file."'->(".a:bits.")->'".res."'"
+ else
+ if substitute(res,'/','\\', 'g') != substitute( a:expected, '/','\\', 'g')
+ echo "FAILED: '".a:file."'->(".a:bits.")->'".res."'"
+ echo "Expected: '".a:expected."'"
+ else
+ echo "OK"
+ endif
+ endif
+endfun
+:fun! MakeDir( dirname )
+ "exe '!mkdir '.substitute(a:dirname,'/','\\','g')
+ call system('mkdir '.substitute(a:dirname,'/','\\','g'))
+endfun
+:fun! RMDir( dirname)
+ "exe '!rmdir '.substitute(a:dirname,'/','\\','g')
+ call system('rmdir '.substitute(a:dirname,'/','\\','g'))
+endfun
+:fun! MakeFile( filename)
+ "exe '!copy nul '.substitute(a:filename,'/','\\','g')
+ call system('copy nul '.substitute(a:filename,'/','\\','g'))
+endfun
+:fun! TestColonEight()
+ redir! >test.out
+ " This could change for CygWin to //cygdrive/c
+ let dir1='c:/x.x.y'
+ if filereadable(dir1) || isdirectory(dir1)
+ call confirm( "'".dir1."' exists, cannot run test" )
+ return
+ endif
+ let file1=dir1.'/zz.y.txt'
+ let nofile1=dir1.'/z.y.txt'
+ let dir2=dir1.'/VimIsTheGreatestSinceSlicedBread'
+ let file2=dir2.'/z.txt'
+ let nofile2=dir2.'/zz.txt'
+ let resdir1='c:/XX2235~1.Y'
+ let resfile1=resdir1.'/ZZY~1.TXT'
+ let resnofile1=resdir1.'/z.y.txt'
+ let resdir2=resdir1.'/VIMIST~1'
+ let resfile2=resdir2.'/z.txt'
+ let resnofile2=resdir2.'/zz.txt'
+ call MakeDir( dir1 )
+ call MakeDir( dir2 )
+ call MakeFile( file1 )
+ call MakeFile( file2 )
+ call TestIt(file1, ':p:8', resfile1)
+ call TestIt(nofile1, ':p:8', resnofile1)
+ call TestIt(file2, ':p:8', resfile2)
+ call TestIt(nofile2, ':p:8', resnofile2)
+ call TestIt(nofile2, ':p:8:h', fnamemodify(resnofile2,':h'))
+ exe 'cd '.dir1
+ call TestIt(file1, ':.:8', strpart(resfile1,strlen(resdir1)+1))
+ call TestIt(nofile1, ':.:8', strpart(resnofile1,strlen(resdir1)+1))
+ call TestIt(file2, ':.:8', strpart(resfile2,strlen(resdir1)+1))
+ call TestIt(nofile2, ':.:8', strpart(resnofile2,strlen(resdir1)+1))
+ let $HOME=dir1
+ call TestIt(file1, ':~:8', '~'.strpart(resfile1,strlen(resdir1)))
+ call TestIt(nofile1, ':~:8', '~'.strpart(resnofile1,strlen(resdir1)))
+ call TestIt(file2, ':~:8', '~'.strpart(resfile2,strlen(resdir1)))
+ call TestIt(nofile2, ':~:8', '~'.strpart(resnofile2,strlen(resdir1)))
+ cd c:/
+ call delete( file2 )
+ call delete( file1 )
+ call RMDir( dir2 )
+ call RMDir( dir1 )
+ echo
+ redir END
+endfun
+:let dir = getcwd()
+:call TestColonEight()
+:exe "cd " . dir
+:edit! test.out
+:set ff=dos
+:w
+:qa!
+ENDTEST
+
diff --git a/src/testdir/test50.ok b/src/testdir/test50.ok
new file mode 100644
index 000000000..91ef1d660
--- /dev/null
+++ b/src/testdir/test50.ok
@@ -0,0 +1,14 @@
+
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
diff --git a/src/testdir/test51.in b/src/testdir/test51.in
new file mode 100644
index 000000000..a158c8691
--- /dev/null
+++ b/src/testdir/test51.in
@@ -0,0 +1,34 @@
+Tests for ":highlight". vim: set ft=vim :
+
+STARTTEST
+:so small.vim
+:" basic test if ":highlight" doesn't crash
+:highlight
+:hi Search
+:" test setting colors.
+:" test clearing one color and all doesn't generate error or warning
+:hi NewGroup term=bold cterm=italic ctermfg=DarkBlue ctermbg=Grey gui= guifg=#00ff00 guibg=Cyan
+:hi Group2 term= cterm=
+:hi Group3 term=underline cterm=bold
+:redir >test.out
+:hi NewGroup
+:hi Group2
+:hi Group3
+:hi clear NewGroup
+:hi NewGroup
+:hi Group2
+:hi Group2 NONE
+:hi Group2
+:hi clear
+:hi Group3
+:hi Crash term='asdf
+:redir END
+:" filter ctermfg and ctermbg, the numbers depend on the terminal
+:e test.out
+:%s/ctermfg=\d*/ctermfg=2/
+:%s/ctermbg=\d*/ctermbg=3/
+:" filter out possibly translated error message
+:%s/E475: [^:]*:/E475:/
+:wq!
+ENDTEST
+
diff --git a/src/testdir/test51.ok b/src/testdir/test51.ok
new file mode 100644
index 000000000..fae83936c
--- /dev/null
+++ b/src/testdir/test51.ok
@@ -0,0 +1,15 @@
+
+
+NewGroup xxx term=bold cterm=italic ctermfg=2 ctermbg=3
+
+
+Group3 xxx term=underline cterm=bold
+
+
+
+
+
+
+
+
+E475: term='asdf
diff --git a/src/testdir/test52.in b/src/testdir/test52.in
new file mode 100644
index 000000000..206b65a1f
--- /dev/null
+++ b/src/testdir/test52.in
@@ -0,0 +1,65 @@
+Tests for reading and writing files with conversion for Win32.
+
+STARTTEST
+:so mbyte.vim
+:" make this a dummy test for non-Win32 systems
+:if !has("win32") | e! test.ok | wq! test.out | endif
+:"
+:" write tests:
+:" combine three values for 'encoding' with three values for 'fileencoding'
+:" also write files for read tests
+/^1
+:set encoding=utf-8
+:.w! ++enc=utf-8 test.out
+:.w ++enc=cp1251 >>test.out
+:.w ++enc=cp866 >>test.out
+:.w! ++enc=utf-8 Xutf8
+/^2
+:set encoding=cp1251
+:.w ++enc=utf-8 >>test.out
+:.w ++enc=cp1251 >>test.out
+:.w ++enc=cp866 >>test.out
+:.w! ++enc=cp1251 Xcp1251
+/^3
+:set encoding=cp866
+:.w ++enc=utf-8 >>test.out
+:.w ++enc=cp1251 >>test.out
+:.w ++enc=cp866 >>test.out
+:.w! ++enc=cp866 Xcp866
+:"
+:" read three 'fileencoding's with utf-8 'encoding'
+:set encoding=utf-8 fencs=utf-8,cp1251
+:e Xutf8
+:.w ++enc=utf-8 >>test.out
+:e Xcp1251
+:.w ++enc=utf-8 >>test.out
+:set fencs=utf-8,cp866
+:e Xcp866
+:.w ++enc=utf-8 >>test.out
+:"
+:" read three 'fileencoding's with cp1251 'encoding'
+:set encoding=utf-8 fencs=utf-8,cp1251
+:e Xutf8
+:.w ++enc=cp1251 >>test.out
+:e Xcp1251
+:.w ++enc=cp1251 >>test.out
+:set fencs=utf-8,cp866
+:e Xcp866
+:.w ++enc=cp1251 >>test.out
+:"
+:" read three 'fileencoding's with cp866 'encoding'
+:set encoding=cp866 fencs=utf-8,cp1251
+:e Xutf8
+:.w ++enc=cp866 >>test.out
+:e Xcp1251
+:.w ++enc=cp866 >>test.out
+:set fencs=utf-8,cp866
+:e Xcp866
+:.w ++enc=cp866 >>test.out
+:"
+:qa!
+ENDTEST
+
+1 utf-8 text: Ð”Ð»Ñ Vim version 6.2. ПоÑледнее изменение: 1970 Jan 01
+2 cp1251 text: Äëÿ Vim version 6.2. Ïîñëåäíåå èçìåíåíèå: 1970 Jan 01
+3 cp866 text: „«ï Vim version 6.2. ®á«¥¤­¥¥ ¨§¬¥­¥­¨¥: 1970 Jan 01
diff --git a/src/testdir/test52.ok b/src/testdir/test52.ok
new file mode 100644
index 000000000..90b516508
--- /dev/null
+++ b/src/testdir/test52.ok
@@ -0,0 +1,18 @@
+1 utf-8 text: Ð”Ð»Ñ Vim version 6.2. ПоÑледнее изменение: 1970 Jan 01
+1 utf-8 text: Äëÿ Vim version 6.2. Ïîñëåäíåå èçìåíåíèå: 1970 Jan 01
+1 utf-8 text: „«ï Vim version 6.2. ®á«¥¤­¥¥ ¨§¬¥­¥­¨¥: 1970 Jan 01
+2 cp1251 text: Ð”Ð»Ñ Vim version 6.2. ПоÑледнее изменение: 1970 Jan 01
+2 cp1251 text: Äëÿ Vim version 6.2. Ïîñëåäíåå èçìåíåíèå: 1970 Jan 01
+2 cp1251 text: „«ï Vim version 6.2. ®á«¥¤­¥¥ ¨§¬¥­¥­¨¥: 1970 Jan 01
+3 cp866 text: Ð”Ð»Ñ Vim version 6.2. ПоÑледнее изменение: 1970 Jan 01
+3 cp866 text: Äëÿ Vim version 6.2. Ïîñëåäíåå èçìåíåíèå: 1970 Jan 01
+3 cp866 text: „«ï Vim version 6.2. ®á«¥¤­¥¥ ¨§¬¥­¥­¨¥: 1970 Jan 01
+1 utf-8 text: Ð”Ð»Ñ Vim version 6.2. ПоÑледнее изменение: 1970 Jan 01
+2 cp1251 text: Ð”Ð»Ñ Vim version 6.2. ПоÑледнее изменение: 1970 Jan 01
+3 cp866 text: Ð”Ð»Ñ Vim version 6.2. ПоÑледнее изменение: 1970 Jan 01
+1 utf-8 text: Äëÿ Vim version 6.2. Ïîñëåäíåå èçìåíåíèå: 1970 Jan 01
+2 cp1251 text: Äëÿ Vim version 6.2. Ïîñëåäíåå èçìåíåíèå: 1970 Jan 01
+3 cp866 text: Äëÿ Vim version 6.2. Ïîñëåäíåå èçìåíåíèå: 1970 Jan 01
+1 utf-8 text: „«ï Vim version 6.2. ®á«¥¤­¥¥ ¨§¬¥­¥­¨¥: 1970 Jan 01
+2 cp1251 text: „«ï Vim version 6.2. ®á«¥¤­¥¥ ¨§¬¥­¥­¨¥: 1970 Jan 01
+3 cp866 text: „«ï Vim version 6.2. ®á«¥¤­¥¥ ¨§¬¥­¥­¨¥: 1970 Jan 01
diff --git a/src/testdir/test6.in b/src/testdir/test6.in
new file mode 100644
index 000000000..1ebbe2fa5
--- /dev/null
+++ b/src/testdir/test6.in
@@ -0,0 +1,24 @@
+Test for autocommand that redefines the argument list, when doing ":all".
+
+STARTTEST
+:so small.vim
+:au BufReadPost Xxx2 next Xxx2 Xxx1
+/^start of
+A1:.,/end of/w! Xxx1 " write test file Xxx1
+$r2:.,/end of/w! Xxx2 " write test file Xxx2
+$r3:.,/end of/w! Xxx3 " write test file Xxx3
+:next! Xxx1 Xxx2 Xxx3 " redefine arglist; go to Xxx1
+:all " open window for all args
+:w! test.out " Write contents of Xxx1
+:w >>test.out " Append contents of last window (Xxx1)
+:rew " should now be in Xxx2
+:w >>test.out " Append contents of Xxx2
+:qa!
+ENDTEST
+
+start of test file Xxx
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+end of test file Xxx
diff --git a/src/testdir/test6.ok b/src/testdir/test6.ok
new file mode 100644
index 000000000..b6b0c93e4
--- /dev/null
+++ b/src/testdir/test6.ok
@@ -0,0 +1,18 @@
+start of test file Xxx1
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+end of test file Xxx
+start of test file Xxx1
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+end of test file Xxx
+start of test file Xxx2
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+end of test file Xxx
diff --git a/src/testdir/test7.in b/src/testdir/test7.in
new file mode 100644
index 000000000..b9cc0585f
--- /dev/null
+++ b/src/testdir/test7.in
@@ -0,0 +1,26 @@
+Test for autocommand that changes the buffer list, when doing ":ball".
+
+STARTTEST
+:so small.vim
+/^start of
+A1:.,/end of/w! Xxx1 " write test file Xxx1
+:sp Xxx1
+:close
+$r2:.,/end of/w! Xxx2 " write test file Xxx2
+:sp Xxx2
+:close
+$r3:.,/end of/w! Xxx3 " write test file Xxx3
+:sp Xxx3
+:close
+:au BufReadPost Xxx2 bwipe
+$r4:ball " open window for all args, close Xxx2
+:.,$w! test.out " Write contents of this file
+:w >>test.out " Append contents of second window (Xxx1)
+:/^start of/,$w >>test.out " Append contents of last window (this file)
+:qa!
+ENDTEST
+
+start of test file Xxx
+ this is a test
+ this is a test
+end of test file Xxx
diff --git a/src/testdir/test7.ok b/src/testdir/test7.ok
new file mode 100644
index 000000000..a0d1ff94a
--- /dev/null
+++ b/src/testdir/test7.ok
@@ -0,0 +1,12 @@
+start of test file Xxx4
+ this is a test
+ this is a test
+end of test file Xxx
+start of test file Xxx1
+ this is a test
+ this is a test
+end of test file Xxx
+start of test file Xxx4
+ this is a test
+ this is a test
+end of test file Xxx
diff --git a/src/testdir/test8.in b/src/testdir/test8.in
new file mode 100644
index 000000000..6fe171546
--- /dev/null
+++ b/src/testdir/test8.in
@@ -0,0 +1,24 @@
+Test for BufWritePre autocommand that deletes or unloads the buffer.
+
+STARTTEST
+:so small.vim
+:au BufWritePre Xxx1 bunload
+:au BufWritePre Xxx2 bwipe
+/^start of
+A1:.,/end of/w! Xxx1 " write test file Xxx1
+$r2:.,/end of/w! Xxx2 " write test file Xxx2
+:e! Xxx2 " edit Xxx2
+:bdel test8.in " delete this file from the buffer list
+:e Xxx1 " edit Xxx1
+:w " write it, will unload it and give an error msg
+:w! test.out " Write contents of this file
+:e! Xxx2 " start editing Xxx2
+:bwipe test.out " remove test.out from the buffer list
+:w " write it, will delete the buffer and give an error msg
+:w >>test.out " Append contents of this file
+:qa!
+ENDTEST
+
+start of Xxx
+ test
+end of Xxx
diff --git a/src/testdir/test8.ok b/src/testdir/test8.ok
new file mode 100644
index 000000000..29b066a13
--- /dev/null
+++ b/src/testdir/test8.ok
@@ -0,0 +1,6 @@
+start of Xxx2
+ test
+end of Xxx
+start of Xxx1
+ test
+end of Xxx
diff --git a/src/testdir/test9.in b/src/testdir/test9.in
new file mode 100644
index 000000000..84e17943c
--- /dev/null
+++ b/src/testdir/test9.in
@@ -0,0 +1,12 @@
+Test for Bufleave autocommand that deletes the buffer we are about to edit.
+
+STARTTEST
+:so small.vim
+:au BufLeave test9.in bwipe yy
+:e yy
+:/^start of/,$w! test.out " Write contents of this file
+:qa!
+ENDTEST
+
+start of test file xx
+end of test file xx
diff --git a/src/testdir/test9.ok b/src/testdir/test9.ok
new file mode 100644
index 000000000..cccb5f3ef
--- /dev/null
+++ b/src/testdir/test9.ok
@@ -0,0 +1,2 @@
+start of test file xx
+end of test file xx
diff --git a/src/testdir/todos.vim b/src/testdir/todos.vim
new file mode 100644
index 000000000..0256a51c8
--- /dev/null
+++ b/src/testdir/todos.vim
@@ -0,0 +1,3 @@
+:" Script to make sure a file is in "dos" file format.
+:set ff=dos
+:wq
diff --git a/src/testdir/unix.vim b/src/testdir/unix.vim
new file mode 100644
index 000000000..f766e74c3
--- /dev/null
+++ b/src/testdir/unix.vim
@@ -0,0 +1,3 @@
+" Settings for test script execution
+" Always use "sh", don't use the value of "$SHELL".
+set shell=sh
diff --git a/src/testdir/vms.vim b/src/testdir/vms.vim
new file mode 100644
index 000000000..3305a77c2
--- /dev/null
+++ b/src/testdir/vms.vim
@@ -0,0 +1,4 @@
+" Settings for test script execution under OpenVMS
+
+" Do not make any swap files
+set noswapfile
diff --git a/src/toolbar.phi b/src/toolbar.phi
new file mode 100644
index 000000000..cf9043ce2
--- /dev/null
+++ b/src/toolbar.phi
@@ -0,0 +1,1283 @@
+/* Builtin icons for the toolbar in photon */
+
+static PgColor_t tb_palette[] = {
+ PgRGB(0,0,0),
+ PgRGB(128,0,0),
+ PgRGB(128,128,0),
+ PgRGB(128,128,128),
+ PgRGB(192,192,192),
+ PgRGB(255,0,0),
+ PgRGB(255,255,0),
+ PgRGB(255,255,255),
+};
+
+static uint8_t tb_close_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x14,0x44,0x44,0x44,0x14,0x44,0x44,
+ 0x44,0x41,0x51,0x00,0x00,0x01,0x51,0x04,0x44,
+ 0x44,0x15,0x55,0x14,0x44,0x15,0x55,0x13,0x44,
+ 0x44,0x41,0x55,0x51,0x41,0x55,0x51,0x03,0x44,
+ 0x44,0x40,0x15,0x55,0x15,0x55,0x17,0x03,0x44,
+ 0x44,0x40,0x41,0x55,0x55,0x51,0x47,0x03,0x44,
+ 0x44,0x40,0x44,0x15,0x55,0x14,0x47,0x03,0x44,
+ 0x44,0x40,0x41,0x55,0x55,0x51,0x47,0x03,0x44,
+ 0x44,0x40,0x15,0x55,0x15,0x55,0x17,0x03,0x44,
+ 0x44,0x41,0x55,0x51,0x41,0x55,0x51,0x03,0x44,
+ 0x44,0x15,0x55,0x14,0x44,0x15,0x55,0x13,0x44,
+ 0x44,0x41,0x51,0x44,0x44,0x41,0x55,0x51,0x44,
+ 0x44,0x40,0x14,0x44,0x44,0x44,0x15,0x13,0x44,
+ 0x44,0x40,0x77,0x77,0x77,0x77,0x41,0x03,0x44,
+ 0x44,0x40,0x00,0x00,0x00,0x00,0x00,0x03,0x44,
+ 0x44,0x44,0x44,0x33,0x33,0x33,0x33,0x33,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_close_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_close_data
+};
+
+static uint8_t tb_copy_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x40,0x00,0x00,0x00,0x00,0x04,0x44,0x44,0x44,
+ 0x40,0x77,0x77,0x77,0x77,0x03,0x44,0x44,0x44,
+ 0x40,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x44,
+ 0x40,0x77,0x77,0x07,0x77,0x77,0x77,0x70,0x44,
+ 0x40,0x70,0x00,0x07,0x00,0x00,0x00,0x70,0x34,
+ 0x40,0x77,0x77,0x07,0x77,0x77,0x77,0x70,0x34,
+ 0x40,0x70,0x00,0x07,0x00,0x00,0x00,0x70,0x34,
+ 0x40,0x77,0x77,0x07,0x77,0x77,0x77,0x70,0x34,
+ 0x40,0x70,0x07,0x07,0x00,0x00,0x00,0x70,0x34,
+ 0x40,0x77,0x77,0x07,0x77,0x77,0x77,0x70,0x34,
+ 0x40,0x00,0x00,0x07,0x00,0x77,0x77,0x70,0x34,
+ 0x44,0x33,0x33,0x07,0x77,0x77,0x77,0x70,0x34,
+ 0x44,0x44,0x44,0x00,0x00,0x00,0x00,0x00,0x34,
+ 0x44,0x44,0x44,0x44,0x33,0x33,0x33,0x33,0x34,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_copy_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_copy_data
+};
+
+static uint8_t tb_ctags_data[] = {
+ 0x44,0x44,0x40,0x04,0x00,0x00,0x04,0x44,0x44,
+ 0x44,0x44,0x07,0x70,0x77,0x77,0x70,0x44,0x44,
+ 0x44,0x44,0x07,0x77,0x77,0x77,0x77,0x04,0x44,
+ 0x44,0x44,0x07,0x70,0x77,0x77,0x00,0x70,0x44,
+ 0x44,0x44,0x40,0x04,0x00,0x00,0x34,0x00,0x44,
+ 0x44,0x42,0x24,0x42,0x40,0x00,0x42,0x40,0x44,
+ 0x44,0x23,0x66,0x66,0x60,0x00,0x36,0x66,0x03,
+ 0x42,0x36,0x66,0x66,0x60,0x00,0x36,0x66,0x03,
+ 0x23,0x64,0x34,0x66,0x60,0x00,0x36,0x66,0x03,
+ 0x26,0x63,0x03,0x66,0x60,0x00,0x36,0x66,0x03,
+ 0x36,0x64,0x34,0x66,0x60,0x00,0x36,0x66,0x03,
+ 0x30,0x66,0x66,0x66,0x60,0x00,0x36,0x66,0x03,
+ 0x43,0x06,0x66,0x66,0x60,0x00,0x36,0x66,0x03,
+ 0x44,0x30,0x00,0x00,0x00,0x00,0x30,0x00,0x03,
+ 0x44,0x43,0x33,0x33,0x30,0x00,0x33,0x33,0x33,
+ 0x44,0x44,0x44,0x44,0x40,0x00,0x34,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x40,0x00,0x34,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x33,0x34,0x44,0x44,
+};
+
+static PhImage_t tb_ctags_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_ctags_data
+};
+
+static uint8_t tb_cut_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x40,0x44,0x44,0x40,0x34,0x44,0x44,
+ 0x44,0x44,0x40,0x34,0x44,0x40,0x34,0x44,0x44,
+ 0x44,0x44,0x44,0x04,0x44,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x03,0x44,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x40,0x40,0x34,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x40,0x30,0x34,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x03,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x40,0x00,0x34,0x44,0x44,0x44,
+ 0x44,0x44,0x43,0x03,0x44,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x00,0x03,0x44,0x00,0x04,0x44,0x44,
+ 0x44,0x40,0x33,0x03,0x44,0x03,0x40,0x44,0x44,
+ 0x44,0x40,0x44,0x03,0x44,0x03,0x40,0x34,0x44,
+ 0x44,0x40,0x44,0x03,0x44,0x03,0x40,0x34,0x44,
+ 0x44,0x44,0x00,0x33,0x44,0x40,0x03,0x44,0x44,
+ 0x44,0x44,0x33,0x44,0x44,0x43,0x34,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_cut_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_cut_data
+};
+
+static uint8_t tb_find_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x40,0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,
+ 0x40,0x77,0x77,0x77,0x70,0x04,0x44,0x44,0x44,
+ 0x40,0x77,0x77,0x77,0x70,0x40,0x44,0x44,0x44,
+ 0x40,0x77,0x77,0x77,0x70,0x00,0x04,0x44,0x44,
+ 0x40,0x77,0x77,0x77,0x77,0x77,0x04,0x44,0x44,
+ 0x40,0x77,0x77,0x77,0x70,0x00,0x04,0x44,0x44,
+ 0x40,0x77,0x77,0x77,0x04,0x44,0x40,0x44,0x44,
+ 0x40,0x77,0x77,0x70,0x47,0x74,0x44,0x04,0x44,
+ 0x40,0x77,0x77,0x70,0x47,0x44,0x44,0x04,0x44,
+ 0x40,0x77,0x77,0x70,0x44,0x44,0x44,0x04,0x44,
+ 0x40,0x77,0x77,0x70,0x44,0x47,0x44,0x04,0x44,
+ 0x40,0x77,0x77,0x77,0x04,0x44,0x40,0x44,0x44,
+ 0x40,0x77,0x77,0x77,0x70,0x00,0x04,0x00,0x44,
+ 0x40,0x77,0x77,0x77,0x77,0x77,0x04,0x00,0x04,
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x04,0x40,0x04,
+ 0x44,0x44,0x33,0x33,0x33,0x33,0x33,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_find_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_find_data
+};
+
+static uint8_t tb_find_help_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x00,0x00,0x03,0x44,0x44,0x44,0x44,
+ 0x44,0x40,0x04,0x43,0x00,0x34,0x44,0x44,0x44,
+ 0x44,0x00,0x34,0x44,0x00,0x04,0x44,0x44,0x44,
+ 0x44,0x00,0x34,0x44,0x00,0x00,0x44,0x44,0x44,
+ 0x44,0x30,0x04,0x40,0x47,0x74,0x04,0x44,0x44,
+ 0x44,0x44,0x44,0x04,0x44,0x74,0x40,0x44,0x44,
+ 0x44,0x44,0x44,0x07,0x77,0x74,0x70,0x44,0x44,
+ 0x44,0x44,0x40,0x04,0x77,0x44,0x40,0x44,0x44,
+ 0x44,0x44,0x40,0x00,0x47,0x74,0x03,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x00,0x00,0x30,0x04,0x44,
+ 0x44,0x44,0x40,0x03,0x44,0x44,0x40,0x00,0x44,
+ 0x44,0x44,0x40,0x03,0x44,0x44,0x44,0x00,0x44,
+ 0x44,0x44,0x40,0x03,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x33,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_find_help_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_find_help_data
+};
+
+static uint8_t tb_find_next_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x00,0x00,0x00,0x00,0x04,0x44,0x44,0x44,
+ 0x44,0x07,0x77,0x77,0x77,0x00,0x44,0x44,0x44,
+ 0x44,0x07,0x77,0x77,0x77,0x04,0x04,0x44,0x44,
+ 0x44,0x07,0x17,0x77,0x77,0x00,0x00,0x44,0x44,
+ 0x44,0x77,0x11,0x77,0x77,0x77,0x70,0x44,0x44,
+ 0x11,0x11,0x15,0x17,0x77,0x00,0x00,0x44,0x44,
+ 0x15,0x55,0x55,0x51,0x70,0x44,0x44,0x04,0x44,
+ 0x15,0x55,0x55,0x55,0x14,0x77,0x44,0x40,0x44,
+ 0x15,0x55,0x55,0x51,0x04,0x74,0x44,0x40,0x44,
+ 0x11,0x11,0x15,0x17,0x04,0x44,0x44,0x40,0x44,
+ 0x44,0x77,0x11,0x77,0x04,0x44,0x74,0x40,0x44,
+ 0x44,0x07,0x17,0x77,0x70,0x44,0x44,0x04,0x44,
+ 0x44,0x07,0x77,0x77,0x77,0x00,0x00,0x40,0x04,
+ 0x44,0x07,0x77,0x77,0x77,0x77,0x70,0x40,0x00,
+ 0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x00,
+ 0x44,0x44,0x43,0x33,0x33,0x33,0x33,0x34,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_find_next_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_find_next_data
+};
+
+static uint8_t tb_find_prev_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x00,0x00,0x00,0x00,0x04,0x44,0x44,0x44,
+ 0x44,0x07,0x77,0x77,0x77,0x00,0x44,0x44,0x44,
+ 0x44,0x07,0x77,0x77,0x77,0x04,0x04,0x44,0x44,
+ 0x44,0x47,0x17,0x77,0x77,0x00,0x00,0x44,0x44,
+ 0x44,0x71,0x17,0x77,0x77,0x77,0x70,0x44,0x44,
+ 0x44,0x15,0x11,0x11,0x17,0x00,0x00,0x44,0x44,
+ 0x41,0x55,0x55,0x55,0x10,0x44,0x44,0x04,0x44,
+ 0x15,0x55,0x55,0x55,0x04,0x77,0x44,0x40,0x44,
+ 0x41,0x55,0x55,0x55,0x04,0x74,0x44,0x40,0x44,
+ 0x44,0x15,0x11,0x11,0x04,0x44,0x44,0x40,0x44,
+ 0x44,0x71,0x17,0x77,0x04,0x44,0x74,0x40,0x44,
+ 0x44,0x47,0x17,0x77,0x70,0x44,0x44,0x04,0x44,
+ 0x44,0x07,0x77,0x77,0x77,0x00,0x00,0x40,0x04,
+ 0x44,0x07,0x77,0x77,0x77,0x77,0x70,0x40,0x00,
+ 0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x00,
+ 0x44,0x44,0x43,0x33,0x33,0x33,0x33,0x34,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_find_prev_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_find_prev_data
+};
+
+static uint8_t tb_help_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x00,0x00,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x40,0x04,0x43,0x00,0x34,0x44,0x44,
+ 0x44,0x44,0x00,0x34,0x44,0x00,0x04,0x44,0x44,
+ 0x44,0x44,0x00,0x34,0x44,0x00,0x04,0x44,0x44,
+ 0x44,0x44,0x30,0x04,0x43,0x00,0x34,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x40,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x00,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x40,0x03,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x40,0x03,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x40,0x03,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x40,0x03,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x40,0x03,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x33,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_help_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_help_data
+};
+
+static uint8_t tb_jump_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x42,0x22,0x22,0x22,0x22,0x22,0x22,0x24,
+ 0x44,0x23,0x66,0x66,0x66,0x66,0x66,0x66,0x03,
+ 0x42,0x36,0x66,0x66,0x66,0x66,0x66,0x66,0x03,
+ 0x23,0x64,0x34,0x66,0x66,0x66,0x66,0x66,0x03,
+ 0x26,0x63,0x03,0x66,0x66,0x66,0x66,0x66,0x03,
+ 0x36,0x64,0x34,0x66,0x66,0x66,0x66,0x66,0x03,
+ 0x30,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x03,
+ 0x43,0x06,0x66,0x66,0x66,0x66,0x66,0x66,0x03,
+ 0x44,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
+ 0x44,0x43,0x33,0x33,0x33,0x33,0x33,0x33,0x33,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_jump_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_jump_data
+};
+
+static uint8_t tb_load_session_data[] = {
+ 0x44,0x44,0x44,0x44,0x11,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x41,0x55,0x14,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x15,0x55,0x51,0x44,0x44,0x44,
+ 0x44,0x44,0x41,0x11,0x55,0x11,0x14,0x44,0x44,
+ 0x44,0x44,0x44,0x41,0x55,0x14,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x41,0x55,0x14,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x41,0x55,0x14,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x41,0x11,0x14,0x44,0x44,0x44,
+ 0x44,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x44,
+ 0x44,0x07,0x77,0x77,0x77,0x77,0x74,0x43,0x04,
+ 0x40,0x77,0x77,0x77,0x77,0x77,0x77,0x33,0x04,
+ 0x40,0x74,0x44,0x44,0x44,0x44,0x55,0x33,0x04,
+ 0x40,0x74,0x44,0x44,0x44,0x44,0x44,0x33,0x04,
+ 0x40,0x70,0x00,0x00,0x00,0x00,0x04,0x33,0x03,
+ 0x40,0x77,0x77,0x77,0x77,0x77,0x74,0x33,0x03,
+ 0x40,0x43,0x33,0x33,0x33,0x33,0x33,0x30,0x34,
+ 0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x44,
+ 0x44,0x44,0x33,0x33,0x33,0x33,0x33,0x34,0x44,
+};
+
+static PhImage_t tb_load_session_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_load_session_data
+};
+
+static uint8_t tb_macro_data[] = {
+ 0x44,0x44,0x43,0x00,0x34,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x30,0x77,0x03,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x07,0x77,0x70,0x34,0x44,0x44,0x44,
+ 0x44,0x43,0x07,0x77,0x70,0x34,0x44,0x44,0x44,
+ 0x44,0x44,0x30,0x77,0x03,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x40,0x00,0x00,0x34,0x44,0x44,0x44,
+ 0x44,0x40,0x00,0x00,0x70,0x34,0x44,0x44,0x44,
+ 0x44,0x30,0x77,0x77,0x77,0x04,0x44,0x44,0x44,
+ 0x44,0x00,0x77,0x77,0x77,0x00,0x44,0x44,0x44,
+ 0x44,0x43,0x00,0x00,0x77,0x30,0x44,0x44,0x44,
+ 0x44,0x44,0x30,0x00,0x77,0x70,0x34,0x44,0x44,
+ 0x44,0x44,0x00,0x77,0x77,0x70,0x04,0x44,0x44,
+ 0x44,0x43,0x07,0x77,0x77,0x77,0x00,0x44,0x44,
+ 0x44,0x40,0x77,0x70,0x00,0x77,0x70,0x04,0x44,
+ 0x44,0x07,0x77,0x03,0x40,0x07,0x77,0x70,0x44,
+ 0x44,0x07,0x70,0x34,0x44,0x30,0x77,0x70,0x44,
+ 0x44,0x30,0x00,0x44,0x44,0x43,0x00,0x03,0x44,
+ 0x44,0x43,0x34,0x44,0x44,0x44,0x43,0x04,0x44,
+};
+
+static PhImage_t tb_macro_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_macro_data
+};
+
+static uint8_t tb_make_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x00,0x40,0x00,0x00,0x44,0x44,0x44,
+ 0x44,0x40,0x77,0x07,0x77,0x77,0x04,0x44,0x44,
+ 0x44,0x40,0x77,0x77,0x77,0x77,0x70,0x44,0x44,
+ 0x44,0x40,0x73,0x07,0x77,0x70,0x07,0x04,0x44,
+ 0x44,0x44,0x00,0x40,0x00,0x03,0x40,0x04,0x44,
+ 0x44,0x44,0x44,0x44,0x00,0x04,0x44,0x04,0x44,
+ 0x44,0x44,0x44,0x44,0x00,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x00,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x00,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x00,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x00,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x00,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x00,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x00,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x00,0x03,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x43,0x33,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_make_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_make_data
+};
+
+static uint8_t tb_maximize_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x70,0x00,0x00,0x00,0x00,0x00,0x44,0x44,
+ 0x44,0x70,0x44,0x44,0x44,0x44,0x70,0x44,0x44,
+ 0x44,0x70,0x44,0x74,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x47,0x74,0x04,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x40,0x00,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x00,0x00,0x04,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x44,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x44,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x00,0x00,0x04,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x40,0x00,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x44,0x04,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x44,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x44,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x77,0x77,0x77,0x77,0x70,0x34,0x44,
+ 0x44,0x70,0x00,0x00,0x00,0x00,0x00,0x34,0x44,
+ 0x44,0x44,0x43,0x33,0x33,0x33,0x33,0x34,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_maximize_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_maximize_data
+};
+
+static uint8_t tb_maxwidth_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
+ 0x70,0x44,0x44,0x44,0x44,0x44,0x44,0x47,0x04,
+ 0x70,0x44,0x74,0x40,0x44,0x04,0x44,0x47,0x03,
+ 0x70,0x47,0x74,0x00,0x44,0x00,0x44,0x47,0x03,
+ 0x70,0x44,0x40,0x00,0x44,0x00,0x04,0x47,0x03,
+ 0x70,0x44,0x44,0x00,0x44,0x00,0x44,0x47,0x03,
+ 0x70,0x44,0x44,0x40,0x44,0x04,0x44,0x47,0x03,
+ 0x70,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x03,
+ 0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
+ 0x44,0x43,0x33,0x33,0x33,0x33,0x33,0x33,0x33,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_maxwidth_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_maxwidth_data
+};
+
+static uint8_t tb_minimize_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x40,0x00,0x00,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x00,0x04,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x40,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x44,
+ 0x47,0x04,0x44,0x44,0x44,0x44,0x47,0x04,0x44,
+ 0x47,0x04,0x47,0x44,0x44,0x44,0x47,0x03,0x44,
+ 0x47,0x04,0x44,0x44,0x44,0x44,0x47,0x03,0x44,
+ 0x47,0x04,0x44,0x44,0x44,0x44,0x77,0x03,0x44,
+ 0x47,0x07,0x77,0x77,0x77,0x77,0x77,0x03,0x44,
+ 0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x44,
+ 0x44,0x44,0x33,0x33,0x33,0x33,0x33,0x33,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x40,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x00,0x04,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x40,0x00,0x00,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_minimize_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_minimize_data
+};
+
+static uint8_t tb_minwidth_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x47,0x00,0x00,0x00,0x44,0x44,0x44,
+ 0x44,0x44,0x47,0x04,0x44,0x70,0x44,0x44,0x44,
+ 0x40,0x44,0x47,0x04,0x74,0x70,0x34,0x44,0x04,
+ 0x40,0x04,0x47,0x04,0x44,0x70,0x34,0x40,0x04,
+ 0x40,0x00,0x47,0x04,0x44,0x70,0x34,0x00,0x04,
+ 0x40,0x04,0x47,0x04,0x44,0x70,0x34,0x40,0x04,
+ 0x40,0x44,0x47,0x04,0x44,0x70,0x34,0x44,0x04,
+ 0x44,0x44,0x47,0x07,0x77,0x70,0x34,0x44,0x44,
+ 0x44,0x44,0x47,0x00,0x00,0x00,0x34,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x33,0x33,0x34,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_minwidth_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_minwidth_data
+};
+
+static uint8_t tb_new_data[] = {
+ 0x44,0x44,0x44,0x44,0x43,0x44,0x37,0x34,0x44,
+ 0x44,0x44,0x44,0x44,0x47,0x34,0x37,0x34,0x73,
+ 0x44,0x44,0x44,0x44,0x44,0x73,0x07,0x07,0x37,
+ 0x40,0x00,0x00,0x00,0x00,0x07,0x77,0x70,0x33,
+ 0x40,0x44,0x44,0x44,0x44,0x77,0x77,0x77,0x77,
+ 0x40,0x44,0x74,0x44,0x44,0x07,0x07,0x70,0x33,
+ 0x40,0x47,0x74,0x44,0x43,0x47,0x07,0x07,0x44,
+ 0x40,0x44,0x44,0x44,0x34,0x47,0x07,0x33,0x74,
+ 0x40,0x44,0x44,0x44,0x44,0x47,0x07,0x34,0x37,
+ 0x40,0x44,0x44,0x44,0x44,0x47,0x03,0x44,0x43,
+ 0x40,0x44,0x44,0x44,0x44,0x47,0x03,0x44,0x44,
+ 0x40,0x44,0x44,0x44,0x44,0x47,0x03,0x44,0x44,
+ 0x40,0x44,0x44,0x44,0x44,0x47,0x03,0x44,0x44,
+ 0x40,0x44,0x44,0x44,0x44,0x47,0x03,0x44,0x44,
+ 0x40,0x44,0x44,0x44,0x44,0x47,0x03,0x44,0x44,
+ 0x40,0x77,0x77,0x77,0x77,0x77,0x03,0x44,0x44,
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x03,0x44,0x44,
+ 0x44,0x44,0x33,0x33,0x33,0x33,0x33,0x44,0x44,
+};
+
+static PhImage_t tb_new_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_new_data
+};
+
+static uint8_t tb_new_session_data[] = {
+ 0x44,0x44,0x34,0x43,0x73,0x44,0x34,0x44,0x44,
+ 0x44,0x44,0x43,0x40,0x70,0x43,0x44,0x44,0x44,
+ 0x44,0x44,0x33,0x07,0x77,0x03,0x34,0x44,0x44,
+ 0x44,0x44,0x77,0x77,0x77,0x77,0x74,0x44,0x44,
+ 0x44,0x44,0x33,0x07,0x77,0x03,0x34,0x44,0x44,
+ 0x44,0x44,0x43,0x40,0x70,0x43,0x44,0x44,0x44,
+ 0x44,0x44,0x34,0x43,0x73,0x44,0x34,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x34,0x44,0x44,0x44,0x44,
+ 0x44,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x44,
+ 0x44,0x07,0x77,0x77,0x77,0x77,0x74,0x43,0x04,
+ 0x40,0x77,0x77,0x77,0x77,0x77,0x77,0x33,0x04,
+ 0x40,0x74,0x44,0x44,0x44,0x44,0x55,0x33,0x04,
+ 0x40,0x74,0x44,0x44,0x44,0x44,0x44,0x33,0x04,
+ 0x40,0x70,0x00,0x00,0x00,0x00,0x04,0x33,0x03,
+ 0x40,0x77,0x77,0x77,0x77,0x77,0x74,0x33,0x03,
+ 0x40,0x43,0x33,0x33,0x33,0x33,0x33,0x30,0x34,
+ 0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x44,
+ 0x44,0x44,0x33,0x33,0x33,0x33,0x33,0x34,0x44,
+};
+
+static PhImage_t tb_new_session_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_new_session_data
+};
+
+static uint8_t tb_open_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x00,0x00,0x00,0x00,0x03,0x44,0x44,
+ 0x44,0x44,0x07,0x77,0x77,0x70,0x70,0x34,0x44,
+ 0x44,0x44,0x07,0x77,0x77,0x70,0x77,0x03,0x44,
+ 0x44,0x44,0x07,0x77,0x77,0x70,0x00,0x03,0x44,
+ 0x44,0x00,0x07,0x77,0x77,0x77,0x77,0x00,0x04,
+ 0x44,0x04,0x04,0x44,0x44,0x44,0x47,0x04,0x04,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x03,0x03,
+ 0x07,0x77,0x77,0x77,0x77,0x77,0x70,0x03,0x03,
+ 0x40,0x74,0x44,0x44,0x44,0x44,0x43,0x03,0x03,
+ 0x40,0x74,0x44,0x44,0x44,0x44,0x44,0x03,0x03,
+ 0x44,0x07,0x44,0x44,0x44,0x44,0x44,0x30,0x03,
+ 0x44,0x07,0x44,0x44,0x44,0x44,0x44,0x40,0x03,
+ 0x44,0x40,0x73,0x33,0x33,0x33,0x33,0x33,0x03,
+ 0x44,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
+ 0x44,0x44,0x43,0x33,0x33,0x33,0x33,0x33,0x33,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_open_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_open_data
+};
+
+static uint8_t tb_paste_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x40,0x00,0x04,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x40,0x00,0x04,0x44,0x44,0x44,0x44,
+ 0x44,0x00,0x04,0x44,0x40,0x00,0x34,0x44,0x44,
+ 0x40,0x43,0x00,0x00,0x00,0x33,0x03,0x44,0x44,
+ 0x40,0x43,0x33,0x33,0x33,0x33,0x03,0x44,0x44,
+ 0x40,0x43,0x34,0x00,0x00,0x00,0x00,0x00,0x44,
+ 0x40,0x43,0x34,0x07,0x77,0x77,0x77,0x70,0x44,
+ 0x40,0x43,0x34,0x07,0x00,0x00,0x00,0x70,0x34,
+ 0x40,0x43,0x34,0x07,0x77,0x77,0x77,0x70,0x34,
+ 0x40,0x43,0x34,0x07,0x77,0x77,0x77,0x70,0x34,
+ 0x40,0x43,0x34,0x07,0x00,0x00,0x00,0x70,0x34,
+ 0x40,0x43,0x34,0x07,0x77,0x77,0x77,0x70,0x34,
+ 0x44,0x00,0x00,0x07,0x00,0x77,0x77,0x70,0x34,
+ 0x44,0x43,0x33,0x07,0x77,0x77,0x77,0x70,0x34,
+ 0x44,0x44,0x44,0x00,0x00,0x00,0x00,0x00,0x34,
+ 0x44,0x44,0x44,0x44,0x33,0x33,0x33,0x33,0x34,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_paste_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_paste_data
+};
+
+static uint8_t tb_print_data[] = {
+ 0x44,0x40,0x00,0x00,0x00,0x00,0x04,0x44,0x44,
+ 0x44,0x40,0x77,0x77,0x77,0x77,0x04,0x44,0x44,
+ 0x44,0x40,0x70,0x00,0x77,0x77,0x03,0x44,0x44,
+ 0x44,0x40,0x77,0x77,0x77,0x77,0x03,0x44,0x44,
+ 0x44,0x40,0x70,0x00,0x77,0x77,0x03,0x44,0x44,
+ 0x44,0x40,0x77,0x77,0x77,0x77,0x03,0x44,0x44,
+ 0x44,0x40,0x70,0x00,0x00,0x77,0x03,0x44,0x44,
+ 0x44,0x40,0x77,0x77,0x77,0x77,0x03,0x44,0x44,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,
+ 0x07,0x77,0x77,0x77,0x77,0x77,0x77,0x30,0x44,
+ 0x07,0x55,0x44,0x44,0x44,0x44,0x44,0x30,0x34,
+ 0x07,0x44,0x44,0x44,0x44,0x44,0x44,0x30,0x34,
+ 0x07,0x44,0x44,0x44,0x44,0x44,0x44,0x30,0x34,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,
+ 0x40,0x44,0x44,0x44,0x44,0x44,0x44,0x03,0x34,
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x44,
+ 0x44,0x43,0x33,0x33,0x33,0x33,0x33,0x33,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_print_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_print_data
+};
+
+static uint8_t tb_redo_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x00,0x00,0x04,0x40,0x04,0x44,
+ 0x44,0x44,0x00,0x77,0x77,0x70,0x07,0x03,0x44,
+ 0x44,0x40,0x77,0x77,0x77,0x77,0x77,0x03,0x44,
+ 0x44,0x40,0x77,0x00,0x00,0x77,0x77,0x03,0x44,
+ 0x44,0x07,0x70,0x33,0x30,0x77,0x77,0x03,0x44,
+ 0x44,0x07,0x70,0x34,0x07,0x77,0x77,0x03,0x44,
+ 0x44,0x07,0x70,0x34,0x00,0x00,0x00,0x03,0x44,
+ 0x44,0x07,0x70,0x34,0x43,0x33,0x03,0x33,0x44,
+ 0x44,0x07,0x70,0x34,0x44,0x40,0x70,0x44,0x44,
+ 0x44,0x40,0x77,0x00,0x00,0x07,0x70,0x34,0x44,
+ 0x44,0x40,0x77,0x77,0x77,0x77,0x03,0x34,0x44,
+ 0x44,0x44,0x00,0x77,0x77,0x70,0x33,0x44,0x44,
+ 0x44,0x44,0x44,0x00,0x00,0x03,0x34,0x44,0x44,
+ 0x44,0x44,0x44,0x43,0x33,0x33,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_redo_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_redo_data
+};
+
+static uint8_t tb_replace_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x00,0x00,0x00,0x00,0x04,0x44,0x44,0x44,
+ 0x44,0x07,0x77,0x77,0x77,0x00,0x44,0x44,0x44,
+ 0x44,0x07,0x00,0x77,0x77,0x07,0x04,0x44,0x44,
+ 0x44,0x34,0x00,0x37,0x77,0x00,0x00,0x44,0x44,
+ 0x44,0x40,0x70,0x07,0x77,0x77,0x70,0x44,0x44,
+ 0x44,0x30,0x00,0x03,0x77,0x77,0x70,0x34,0x44,
+ 0x44,0x07,0x77,0x00,0x77,0x77,0x70,0x34,0x44,
+ 0x40,0x03,0x73,0x00,0x07,0x77,0x40,0x34,0x44,
+ 0x44,0x47,0x77,0x77,0x77,0x77,0x74,0x34,0x44,
+ 0x44,0x07,0x55,0x44,0x57,0x77,0x00,0x00,0x44,
+ 0x44,0x07,0x35,0x44,0x55,0x77,0x03,0x70,0x04,
+ 0x44,0x07,0x73,0x55,0x55,0x57,0x00,0x00,0x44,
+ 0x44,0x07,0x77,0x77,0x55,0x77,0x03,0x70,0x04,
+ 0x44,0x07,0x77,0x77,0x57,0x77,0x03,0x70,0x04,
+ 0x44,0x00,0x00,0x00,0x40,0x04,0x00,0x00,0x44,
+ 0x44,0x44,0x43,0x33,0x33,0x33,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_replace_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_replace_data
+};
+
+static uint8_t tb_save_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,
+ 0x44,0x04,0x07,0x77,0x77,0x77,0x70,0x40,0x44,
+ 0x44,0x04,0x07,0x77,0x77,0x77,0x70,0x00,0x34,
+ 0x44,0x04,0x07,0x77,0x77,0x77,0x70,0x40,0x34,
+ 0x44,0x04,0x07,0x77,0x77,0x77,0x70,0x40,0x34,
+ 0x44,0x04,0x07,0x77,0x77,0x77,0x70,0x40,0x34,
+ 0x44,0x04,0x07,0x77,0x77,0x77,0x70,0x40,0x34,
+ 0x44,0x04,0x40,0x00,0x00,0x00,0x04,0x40,0x34,
+ 0x44,0x04,0x44,0x44,0x44,0x44,0x44,0x40,0x34,
+ 0x44,0x04,0x40,0x00,0x00,0x00,0x00,0x40,0x34,
+ 0x44,0x04,0x40,0x00,0x00,0x04,0x40,0x40,0x34,
+ 0x44,0x04,0x40,0x00,0x00,0x04,0x40,0x40,0x34,
+ 0x44,0x04,0x40,0x00,0x00,0x04,0x40,0x40,0x34,
+ 0x44,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x34,
+ 0x44,0x44,0x33,0x33,0x33,0x33,0x33,0x33,0x34,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_save_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_save_data
+};
+
+static uint8_t tb_save_all_data[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x44,
+ 0x04,0x07,0x77,0x77,0x77,0x70,0x70,0x44,0x44,
+ 0x04,0x07,0x77,0x77,0x77,0x70,0x00,0x34,0x44,
+ 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
+ 0x04,0x00,0x40,0x77,0x77,0x77,0x77,0x07,0x04,
+ 0x04,0x00,0x40,0x77,0x77,0x77,0x77,0x00,0x03,
+ 0x04,0x00,0x40,0x77,0x77,0x77,0x77,0x04,0x03,
+ 0x04,0x40,0x40,0x77,0x77,0x77,0x77,0x04,0x03,
+ 0x04,0x40,0x40,0x77,0x77,0x77,0x77,0x04,0x03,
+ 0x04,0x40,0x40,0x77,0x77,0x77,0x77,0x04,0x03,
+ 0x04,0x40,0x44,0x00,0x00,0x00,0x00,0x44,0x03,
+ 0x04,0x40,0x44,0x44,0x44,0x44,0x44,0x44,0x03,
+ 0x04,0x40,0x44,0x00,0x00,0x00,0x00,0x04,0x03,
+ 0x40,0x00,0x44,0x00,0x00,0x00,0x77,0x04,0x03,
+ 0x44,0x30,0x44,0x00,0x00,0x00,0x77,0x04,0x03,
+ 0x44,0x40,0x44,0x00,0x00,0x00,0x77,0x04,0x03,
+ 0x44,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
+ 0x44,0x44,0x43,0x33,0x33,0x33,0x33,0x33,0x34,
+};
+
+static PhImage_t tb_save_all_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_save_all_data
+};
+
+static uint8_t tb_save_session_data[] = {
+ 0x44,0x44,0x44,0x41,0x11,0x14,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x41,0x55,0x14,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x41,0x55,0x14,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x41,0x55,0x14,0x44,0x44,0x44,
+ 0x44,0x44,0x41,0x11,0x55,0x11,0x14,0x44,0x44,
+ 0x44,0x44,0x44,0x15,0x55,0x51,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x41,0x55,0x14,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x11,0x44,0x44,0x44,0x44,
+ 0x44,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x44,
+ 0x44,0x07,0x77,0x77,0x77,0x77,0x74,0x43,0x04,
+ 0x40,0x77,0x77,0x77,0x77,0x77,0x77,0x33,0x04,
+ 0x40,0x74,0x44,0x44,0x44,0x44,0x55,0x33,0x04,
+ 0x40,0x74,0x44,0x44,0x44,0x44,0x44,0x33,0x04,
+ 0x40,0x70,0x00,0x00,0x00,0x00,0x04,0x33,0x03,
+ 0x40,0x77,0x77,0x77,0x77,0x77,0x74,0x33,0x03,
+ 0x40,0x43,0x33,0x33,0x33,0x33,0x33,0x30,0x34,
+ 0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x44,
+ 0x44,0x44,0x33,0x33,0x33,0x33,0x33,0x34,0x44,
+};
+
+static PhImage_t tb_save_session_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_save_session_data
+};
+
+static uint8_t tb_shell_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x40,0x00,0x40,0x00,0x44,0x44,0x44,
+ 0x44,0x44,0x03,0x43,0x33,0x43,0x04,0x44,0x44,
+ 0x44,0x40,0x47,0x43,0x03,0x47,0x40,0x44,0x44,
+ 0x44,0x40,0x34,0x74,0x34,0x74,0x30,0x44,0x44,
+ 0x44,0x03,0x44,0x44,0x04,0x44,0x43,0x04,0x44,
+ 0x40,0x34,0x03,0x74,0x34,0x73,0x04,0x30,0x44,
+ 0x40,0x44,0x43,0x74,0x04,0x73,0x44,0x40,0x44,
+ 0x40,0x47,0x40,0x37,0x37,0x30,0x47,0x40,0x34,
+ 0x40,0x34,0x74,0x04,0x04,0x04,0x74,0x30,0x34,
+ 0x44,0x03,0x74,0x34,0x44,0x34,0x73,0x03,0x44,
+ 0x44,0x40,0x34,0x44,0x74,0x44,0x30,0x34,0x44,
+ 0x44,0x44,0x04,0x47,0x77,0x44,0x03,0x44,0x44,
+ 0x44,0x44,0x00,0x34,0x44,0x30,0x03,0x44,0x44,
+ 0x44,0x40,0x34,0x44,0x44,0x44,0x30,0x34,0x44,
+ 0x44,0x40,0x00,0x00,0x00,0x00,0x00,0x34,0x44,
+ 0x44,0x44,0x43,0x33,0x33,0x33,0x33,0x34,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_shell_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_shell_data
+};
+
+static uint8_t tb_split_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x70,0x00,0x00,0x00,0x00,0x00,0x44,0x44,
+ 0x44,0x70,0x44,0x44,0x44,0x44,0x70,0x44,0x44,
+ 0x44,0x70,0x44,0x74,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x47,0x74,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x44,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x44,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x77,0x77,0x77,0x77,0x70,0x34,0x44,
+ 0x44,0x70,0x00,0x00,0x00,0x00,0x00,0x34,0x44,
+ 0x44,0x70,0x33,0x33,0x33,0x33,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x74,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x47,0x74,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x44,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x44,0x44,0x44,0x44,0x70,0x34,0x44,
+ 0x44,0x70,0x77,0x77,0x77,0x77,0x70,0x34,0x44,
+ 0x44,0x70,0x00,0x00,0x00,0x00,0x00,0x34,0x44,
+ 0x44,0x44,0x43,0x33,0x33,0x33,0x33,0x34,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_split_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_split_data
+};
+
+static uint8_t tb_undo_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x00,0x44,0x00,0x00,0x04,0x44,0x44,0x44,
+ 0x44,0x07,0x00,0x77,0x77,0x70,0x04,0x44,0x44,
+ 0x44,0x07,0x77,0x77,0x77,0x77,0x70,0x44,0x44,
+ 0x44,0x07,0x77,0x70,0x00,0x07,0x70,0x34,0x44,
+ 0x44,0x07,0x77,0x70,0x33,0x30,0x77,0x04,0x44,
+ 0x44,0x07,0x77,0x77,0x04,0x40,0x77,0x03,0x44,
+ 0x44,0x00,0x00,0x00,0x03,0x40,0x77,0x03,0x44,
+ 0x44,0x43,0x03,0x33,0x33,0x40,0x77,0x03,0x44,
+ 0x44,0x40,0x70,0x44,0x44,0x40,0x77,0x03,0x44,
+ 0x44,0x40,0x77,0x00,0x00,0x07,0x70,0x33,0x44,
+ 0x44,0x44,0x07,0x77,0x77,0x77,0x70,0x34,0x44,
+ 0x44,0x44,0x40,0x77,0x77,0x70,0x03,0x34,0x44,
+ 0x44,0x44,0x44,0x00,0x00,0x03,0x33,0x44,0x44,
+ 0x44,0x44,0x44,0x43,0x33,0x33,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_undo_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_undo_data
+};
+
+static uint8_t tb_vsplit_data[] = {
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,
+ 0x47,0x04,0x44,0x47,0x03,0x44,0x44,0x70,0x44,
+ 0x47,0x04,0x47,0x47,0x03,0x44,0x74,0x70,0x34,
+ 0x47,0x04,0x77,0x47,0x03,0x47,0x74,0x70,0x34,
+ 0x47,0x04,0x44,0x47,0x03,0x44,0x44,0x70,0x34,
+ 0x47,0x04,0x44,0x47,0x03,0x44,0x44,0x70,0x34,
+ 0x47,0x04,0x44,0x47,0x03,0x44,0x44,0x70,0x34,
+ 0x47,0x04,0x44,0x47,0x03,0x44,0x44,0x70,0x34,
+ 0x47,0x04,0x44,0x47,0x03,0x44,0x44,0x70,0x34,
+ 0x47,0x04,0x44,0x47,0x03,0x44,0x44,0x70,0x34,
+ 0x47,0x04,0x44,0x47,0x03,0x44,0x44,0x70,0x34,
+ 0x47,0x04,0x44,0x47,0x03,0x44,0x44,0x70,0x34,
+ 0x47,0x04,0x44,0x47,0x03,0x44,0x44,0x70,0x34,
+ 0x47,0x07,0x77,0x77,0x07,0x77,0x77,0x70,0x34,
+ 0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,
+ 0x44,0x44,0x33,0x33,0x33,0x33,0x33,0x33,0x34,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+};
+
+static PhImage_t tb_vsplit_phi = {
+ Pg_IMAGE_PALETTE_NIBBLE,
+ 0,
+ 9,
+ { 18,18 },
+ 420393992,
+ 8,
+ NULL,
+ PgGrey(0xc0),
+ 0,
+ Ph_USE_TRANSPARENCY,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ tb_palette,
+ tb_vsplit_data
+};
diff --git a/src/toolcheck b/src/toolcheck
new file mode 100755
index 000000000..b05118a56
--- /dev/null
+++ b/src/toolcheck
@@ -0,0 +1,36 @@
+#!/bin/sh
+# toolcheck -- check for tools that have severe bugs. Good that all the buggy
+# tools identify by version numbers. This is the spirit of GNU :-)
+#
+# 24.7.95 jw.
+
+retval=0
+reply="`sh -version -c exit 2>&1 < /dev/null`"
+case "$reply" in
+ GNU*1.14.3*)
+ echo "- sh is '$reply'";
+ echo " CAUTION: This shell has a buggy 'trap' command.";
+ echo " The configure script may fail silently.";
+ retval=1;
+ ;;
+ GNU*)
+ echo "- sh is '$reply' - probably OK.";
+ ;;
+ *) ;;
+esac
+
+reply="`sed --version 2>&1 < /dev/null`"
+case "$reply" in
+ GNU\ sed\ version\ 2.0[34])
+ echo "- sed is '$reply'";
+ echo " CAUTION: This sed cannot configure screen properly."
+ retval=1;
+ ;;
+ GNU\ sed\ version\ 2.05|GNU\ sed\ version\ 2.03\ kevin)
+ echo "- sed is '$reply' - good.";
+ ;;
+ GNU*) echo "- sed is '$reply'.";
+ ;;
+ *) ;;
+esac
+exit $retval
diff --git a/src/tools.bmp b/src/tools.bmp
new file mode 100644
index 000000000..9a520cdce
--- /dev/null
+++ b/src/tools.bmp
Binary files differ
diff --git a/src/tools16.bmp b/src/tools16.bmp
new file mode 100644
index 000000000..d4fbc511e
--- /dev/null
+++ b/src/tools16.bmp
Binary files differ
diff --git a/src/typemap b/src/typemap
new file mode 100644
index 000000000..40049237b
--- /dev/null
+++ b/src/typemap
@@ -0,0 +1,14 @@
+TYPEMAP
+VIWIN T_VIOBJNOMUNGE
+VIBUF T_VIOBJNOMUNGE
+
+INPUT
+T_VIOBJNOMUNGE
+ if (sv_isa($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = ($type) tmp;
+ if (!tmp)
+ croak(\"$ntype no longer exists\");
+ }
+ else
+ croak(\"$var is not of type ${ntype}\")
diff --git a/src/ui.c b/src/ui.c
new file mode 100644
index 000000000..ebbf85dbb
--- /dev/null
+++ b/src/ui.c
@@ -0,0 +1,3060 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * ui.c: functions that handle the user interface.
+ * 1. Keyboard input stuff, and a bit of windowing stuff. These are called
+ * before the machine specific stuff (mch_*) so that we can call the GUI
+ * stuff instead if the GUI is running.
+ * 2. Clipboard stuff.
+ * 3. Input buffer stuff.
+ */
+
+#include "vim.h"
+
+ void
+ui_write(s, len)
+ char_u *s;
+ int len;
+{
+#ifdef FEAT_GUI
+ if (gui.in_use && !gui.dying && !gui.starting)
+ {
+ gui_write(s, len);
+ if (p_wd)
+ gui_wait_for_chars(p_wd);
+ return;
+ }
+#endif
+#ifndef NO_CONSOLE
+ /* Don't output anything in silent mode ("ex -s") unless 'verbose' set */
+ if (!(silent_mode && p_verbose == 0))
+ {
+#ifdef FEAT_MBYTE
+ char_u *tofree = NULL;
+
+ if (output_conv.vc_type != CONV_NONE)
+ {
+ /* Convert characters from 'encoding' to 'termencoding'. */
+ tofree = string_convert(&output_conv, s, &len);
+ if (tofree != NULL)
+ s = tofree;
+ }
+#endif
+
+ mch_write(s, len);
+
+#ifdef FEAT_MBYTE
+ if (output_conv.vc_type != CONV_NONE)
+ vim_free(tofree);
+#endif
+ }
+#endif
+}
+
+#if (defined(FEAT_GUI) && (defined(UNIX) || defined(VMS))) \
+ || defined(MACOS_X_UNIX) || defined(PROTO)
+/*
+ * When executing an external program, there may be some typed characters that
+ * are not consumed by it. Give them back to ui_inchar() and they are stored
+ * here for the next call.
+ */
+static char_u *ta_str = NULL;
+static int ta_off; /* offset for next char to use when ta_str != NULL */
+static int ta_len; /* length of ta_str when it's not NULL*/
+
+ void
+ui_inchar_undo(s, len)
+ char_u *s;
+ int len;
+{
+ char_u *new;
+ int newlen;
+
+ newlen = len;
+ if (ta_str != NULL)
+ newlen += ta_len - ta_off;
+ new = alloc(newlen);
+ if (new != NULL)
+ {
+ if (ta_str != NULL)
+ {
+ mch_memmove(new, ta_str + ta_off, (size_t)(ta_len - ta_off));
+ mch_memmove(new + ta_len - ta_off, s, (size_t)len);
+ vim_free(ta_str);
+ }
+ else
+ mch_memmove(new, s, (size_t)len);
+ ta_str = new;
+ ta_len = newlen;
+ ta_off = 0;
+ }
+}
+#endif
+
+/*
+ * ui_inchar(): low level input funcion.
+ * Get characters from the keyboard.
+ * Return the number of characters that are available.
+ * If "wtime" == 0 do not wait for characters.
+ * If "wtime" == -1 wait forever for characters.
+ * If "wtime" > 0 wait "wtime" milliseconds for a character.
+ *
+ * "tb_change_cnt" is the value of typebuf.tb_change_cnt if "buf" points into
+ * it. When typebuf.tb_change_cnt changes (e.g., when a message is received
+ * from a remote client) "buf" can no longer be used. "tb_change_cnt" is NULL
+ * otherwise.
+ */
+ int
+ui_inchar(buf, maxlen, wtime, tb_change_cnt)
+ char_u *buf;
+ int maxlen;
+ long wtime; /* don't use "time", MIPS cannot handle it */
+ int tb_change_cnt;
+{
+ int retval = 0;
+
+#if defined(FEAT_GUI) && (defined(UNIX) || defined(VMS))
+ /*
+ * Use the typeahead if there is any.
+ */
+ if (ta_str != NULL)
+ {
+ if (maxlen >= ta_len - ta_off)
+ {
+ mch_memmove(buf, ta_str + ta_off, (size_t)ta_len);
+ vim_free(ta_str);
+ ta_str = NULL;
+ return ta_len;
+ }
+ mch_memmove(buf, ta_str + ta_off, (size_t)maxlen);
+ ta_off += maxlen;
+ return maxlen;
+ }
+#endif
+
+#ifdef NO_CONSOLE_INPUT
+ /* Don't wait for character input when the window hasn't been opened yet.
+ * Do try reading, this works when redirecting stdin from a file.
+ * Must return something, otherwise we'll loop forever. If we run into
+ * this very often we probably got stuck, exit Vim. */
+ if (no_console_input())
+ {
+ static int count = 0;
+
+# ifndef NO_CONSOLE
+ retval = mch_inchar(buf, maxlen, 10L, tb_change_cnt);
+ if (retval > 0 || typebuf_changed(tb_change_cnt))
+ return retval;
+# endif
+ if (wtime == -1 && ++count == 1000)
+ read_error_exit();
+ buf[0] = CAR;
+ return 1;
+ }
+#endif
+
+ /* When doing a blocking wait there is no need for CTRL-C to interrupt
+ * something, don't let it set got_int when it was mapped. */
+ if (mapped_ctrl_c && (wtime == -1 || wtime > 100L))
+ ctrl_c_interrupts = FALSE;
+
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ if (gui_wait_for_chars(wtime) && !typebuf_changed(tb_change_cnt))
+ retval = read_from_input_buf(buf, (long)maxlen);
+ }
+#endif
+#ifndef NO_CONSOLE
+# ifdef FEAT_GUI
+ else
+# endif
+ retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt);
+#endif
+
+ ctrl_c_interrupts = TRUE;
+
+ return retval;
+}
+
+/*
+ * return non-zero if a character is available
+ */
+ int
+ui_char_avail()
+{
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ gui_mch_update();
+ return input_available();
+ }
+#endif
+#ifndef NO_CONSOLE
+# ifdef NO_CONSOLE_INPUT
+ if (no_console_input())
+ return 0;
+# endif
+ return mch_char_avail();
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Delay for the given number of milliseconds. If ignoreinput is FALSE then we
+ * cancel the delay if a key is hit.
+ */
+ void
+ui_delay(msec, ignoreinput)
+ long msec;
+ int ignoreinput;
+{
+#ifdef FEAT_GUI
+ if (gui.in_use && !ignoreinput)
+ gui_wait_for_chars(msec);
+ else
+#endif
+ mch_delay(msec, ignoreinput);
+}
+
+/*
+ * If the machine has job control, use it to suspend the program,
+ * otherwise fake it by starting a new shell.
+ * When running the GUI iconify the window.
+ */
+ void
+ui_suspend()
+{
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ gui_mch_iconify();
+ return;
+ }
+#endif
+ mch_suspend();
+}
+
+#if !defined(UNIX) || !defined(SIGTSTP) || defined(PROTO) || defined(__BEOS__)
+/*
+ * When the OS can't really suspend, call this function to start a shell.
+ * This is never called in the GUI.
+ */
+ void
+suspend_shell()
+{
+ if (*p_sh == NUL)
+ EMSG(_(e_shellempty));
+ else
+ {
+ MSG_PUTS(_("new shell started\n"));
+ do_shell(NULL, 0);
+ }
+}
+#endif
+
+/*
+ * Try to get the current Vim shell size. Put the result in Rows and Columns.
+ * Use the new sizes as defaults for 'columns' and 'lines'.
+ * Return OK when size could be determined, FAIL otherwise.
+ */
+ int
+ui_get_shellsize()
+{
+ int retval;
+
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ retval = gui_get_shellsize();
+ else
+#endif
+ retval = mch_get_shellsize();
+
+ check_shellsize();
+
+ /* adjust the default for 'lines' and 'columns' */
+ if (retval == OK)
+ {
+ set_number_default("lines", Rows);
+ set_number_default("columns", Columns);
+ }
+ return retval;
+}
+
+/*
+ * Set the size of the Vim shell according to Rows and Columns, if possible.
+ * The gui_set_shellsize() or mch_set_shellsize() function will try to set the
+ * new size. If this is not possible, it will adjust Rows and Columns.
+ */
+/*ARGSUSED*/
+ void
+ui_set_shellsize(mustset)
+ int mustset; /* set by the user */
+{
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_set_shellsize(mustset,
+# ifdef WIN3264
+ TRUE
+# else
+ FALSE
+# endif
+ );
+ else
+#endif
+ mch_set_shellsize();
+}
+
+/*
+ * Called when Rows and/or Columns changed. Adjust scroll region and mouse
+ * region.
+ */
+ void
+ui_new_shellsize()
+{
+ if (full_screen && !exiting)
+ {
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_new_shellsize();
+ else
+#endif
+ mch_new_shellsize();
+ }
+}
+
+ void
+ui_breakcheck()
+{
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_mch_update();
+ else
+#endif
+ mch_breakcheck();
+}
+
+/*****************************************************************************
+ * Functions for copying and pasting text between applications.
+ * This is always included in a GUI version, but may also be included when the
+ * clipboard and mouse is available to a terminal version such as xterm.
+ * Note: there are some more functions in ops.c that handle selection stuff.
+ *
+ * Also note that the majority of functions here deal with the X 'primary'
+ * (visible - for Visual mode use) selection, and only that. There are no
+ * versions of these for the 'clipboard' selection, as Visual mode has no use
+ * for them.
+ */
+
+#if defined(FEAT_CLIPBOARD) || defined(PROTO)
+
+/*
+ * Selection stuff using Visual mode, for cutting and pasting text to other
+ * windows.
+ */
+
+/*
+ * Call this to initialise the clipboard. Pass it FALSE if the clipboard code
+ * is included, but the clipboard can not be used, or TRUE if the clipboard can
+ * be used. Eg unix may call this with FALSE, then call it again with TRUE if
+ * the GUI starts.
+ */
+ void
+clip_init(can_use)
+ int can_use;
+{
+ VimClipboard *cb;
+
+ cb = &clip_star;
+ for (;;)
+ {
+ cb->available = can_use;
+ cb->owned = FALSE;
+ cb->start.lnum = 0;
+ cb->start.col = 0;
+ cb->end.lnum = 0;
+ cb->end.col = 0;
+ cb->state = SELECT_CLEARED;
+
+ if (cb == &clip_plus)
+ break;
+ cb = &clip_plus;
+ }
+}
+
+/*
+ * Check whether the VIsual area has changed, and if so try to become the owner
+ * of the selection, and free any old converted selection we may still have
+ * lying around. If the VIsual mode has ended, make a copy of what was
+ * selected so we can still give it to others. Will probably have to make sure
+ * this is called whenever VIsual mode is ended.
+ */
+ void
+clip_update_selection()
+{
+ pos_T start, end;
+
+ /* If visual mode is only due to a redo command ("."), then ignore it */
+ if (!redo_VIsual_busy && VIsual_active && (State & NORMAL))
+ {
+ if (lt(VIsual, curwin->w_cursor))
+ {
+ start = VIsual;
+ end = curwin->w_cursor;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ end.col += (*mb_ptr2len_check)(ml_get_cursor()) - 1;
+#endif
+ }
+ else
+ {
+ start = curwin->w_cursor;
+ end = VIsual;
+ }
+ if (!equalpos(clip_star.start, start)
+ || !equalpos(clip_star.end, end)
+ || clip_star.vmode != VIsual_mode)
+ {
+ clip_clear_selection();
+ clip_star.start = start;
+ clip_star.end = end;
+ clip_star.vmode = VIsual_mode;
+ clip_free_selection(&clip_star);
+ clip_own_selection(&clip_star);
+ clip_gen_set_selection(&clip_star);
+ }
+ }
+}
+
+ void
+clip_own_selection(cbd)
+ VimClipboard *cbd;
+{
+ /*
+ * Also want to check somehow that we are reading from the keyboard rather
+ * than a mapping etc.
+ */
+ if (!cbd->owned && cbd->available)
+ {
+ cbd->owned = (clip_gen_own_selection(cbd) == OK);
+#ifdef FEAT_X11
+ if (cbd == &clip_star)
+ {
+ /* May have to show a different kind of highlighting for the selected
+ * area. There is no specific redraw command for this, just redraw
+ * all windows on the current buffer. */
+ if (cbd->owned
+ && get_real_state() == VISUAL
+ && clip_isautosel()
+ && hl_attr(HLF_V) != hl_attr(HLF_VNC))
+ redraw_curbuf_later(INVERTED_ALL);
+ }
+#endif
+ }
+}
+
+ void
+clip_lose_selection(cbd)
+ VimClipboard *cbd;
+{
+#ifdef FEAT_X11
+ int was_owned = cbd->owned;
+#endif
+ int visual_selection = (cbd == &clip_star);
+
+ clip_free_selection(cbd);
+ cbd->owned = FALSE;
+ if (visual_selection)
+ clip_clear_selection();
+ clip_gen_lose_selection(cbd);
+#ifdef FEAT_X11
+ if (visual_selection)
+ {
+ /* May have to show a different kind of highlighting for the selected
+ * area. There is no specific redraw command for this, just redraw all
+ * windows on the current buffer. */
+ if (was_owned
+ && get_real_state() == VISUAL
+ && clip_isautosel()
+ && hl_attr(HLF_V) != hl_attr(HLF_VNC))
+ {
+ update_curbuf(INVERTED_ALL);
+ setcursor();
+ cursor_on();
+ out_flush();
+# ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_update_cursor(TRUE, FALSE);
+# endif
+ }
+ }
+#endif
+}
+
+ void
+clip_copy_selection()
+{
+ if (VIsual_active && (State & NORMAL) && clip_star.available)
+ {
+ if (clip_isautosel())
+ clip_update_selection();
+ clip_free_selection(&clip_star);
+ clip_own_selection(&clip_star);
+ if (clip_star.owned)
+ clip_get_selection(&clip_star);
+ clip_gen_set_selection(&clip_star);
+ }
+}
+
+/*
+ * Called when Visual mode is ended: update the selection.
+ */
+ void
+clip_auto_select()
+{
+ if (clip_isautosel())
+ clip_copy_selection();
+}
+
+/*
+ * Return TRUE if automatic selection of Visual area is desired.
+ */
+ int
+clip_isautosel()
+{
+ return (
+#ifdef FEAT_GUI
+ gui.in_use ? (vim_strchr(p_go, GO_ASEL) != NULL) :
+#endif
+ clip_autoselect);
+}
+
+
+/*
+ * Stuff for general mouse selection, without using Visual mode.
+ */
+
+static int clip_compare_pos __ARGS((int row1, int col1, int row2, int col2));
+static void clip_invert_area __ARGS((int, int, int, int, int how));
+static void clip_invert_rectangle __ARGS((int row, int col, int height, int width, int invert));
+static void clip_get_word_boundaries __ARGS((VimClipboard *, int, int));
+static int clip_get_line_end __ARGS((int));
+static void clip_update_modeless_selection __ARGS((VimClipboard *, int, int,
+ int, int));
+
+/* flags for clip_invert_area() */
+#define CLIP_CLEAR 1
+#define CLIP_SET 2
+#define CLIP_TOGGLE 3
+
+/*
+ * Start, continue or end a modeless selection. Used when editing the
+ * command-line and in the cmdline window.
+ */
+ void
+clip_modeless(button, is_click, is_drag)
+ int button;
+ int is_click;
+ int is_drag;
+{
+ int repeat;
+
+ repeat = ((clip_star.mode == SELECT_MODE_CHAR
+ || clip_star.mode == SELECT_MODE_LINE)
+ && (mod_mask & MOD_MASK_2CLICK))
+ || (clip_star.mode == SELECT_MODE_WORD
+ && (mod_mask & MOD_MASK_3CLICK));
+ if (is_click && button == MOUSE_RIGHT)
+ {
+ /* Right mouse button: If there was no selection, start one.
+ * Otherwise extend the existing selection. */
+ if (clip_star.state == SELECT_CLEARED)
+ clip_start_selection(mouse_col, mouse_row, FALSE);
+ clip_process_selection(button, mouse_col, mouse_row, repeat);
+ }
+ else if (is_click)
+ clip_start_selection(mouse_col, mouse_row, repeat);
+ else if (is_drag)
+ {
+ /* Don't try extending a selection if there isn't one. Happens when
+ * button-down is in the cmdline and them moving mouse upwards. */
+ if (clip_star.state != SELECT_CLEARED)
+ clip_process_selection(button, mouse_col, mouse_row, repeat);
+ }
+ else /* release */
+ clip_process_selection(MOUSE_RELEASE, mouse_col, mouse_row, FALSE);
+}
+
+/*
+ * Compare two screen positions ala strcmp()
+ */
+ static int
+clip_compare_pos(row1, col1, row2, col2)
+ int row1;
+ int col1;
+ int row2;
+ int col2;
+{
+ if (row1 > row2) return(1);
+ if (row1 < row2) return(-1);
+ if (col1 > col2) return(1);
+ if (col1 < col2) return(-1);
+ return(0);
+}
+
+/*
+ * Start the selection
+ */
+ void
+clip_start_selection(col, row, repeated_click)
+ int col;
+ int row;
+ int repeated_click;
+{
+ VimClipboard *cb = &clip_star;
+
+ if (cb->state == SELECT_DONE)
+ clip_clear_selection();
+
+ row = check_row(row);
+ col = check_col(col);
+#ifdef FEAT_MBYTE
+ col = mb_fix_col(col, row);
+#endif
+
+ cb->start.lnum = row;
+ cb->start.col = col;
+ cb->end = cb->start;
+ cb->origin_row = (short_u)cb->start.lnum;
+ cb->state = SELECT_IN_PROGRESS;
+
+ if (repeated_click)
+ {
+ if (++cb->mode > SELECT_MODE_LINE)
+ cb->mode = SELECT_MODE_CHAR;
+ }
+ else
+ cb->mode = SELECT_MODE_CHAR;
+
+#ifdef FEAT_GUI
+ /* clear the cursor until the selection is made */
+ if (gui.in_use)
+ gui_undraw_cursor();
+#endif
+
+ switch (cb->mode)
+ {
+ case SELECT_MODE_CHAR:
+ cb->origin_start_col = cb->start.col;
+ cb->word_end_col = clip_get_line_end((int)cb->start.lnum);
+ break;
+
+ case SELECT_MODE_WORD:
+ clip_get_word_boundaries(cb, (int)cb->start.lnum, cb->start.col);
+ cb->origin_start_col = cb->word_start_col;
+ cb->origin_end_col = cb->word_end_col;
+
+ clip_invert_area((int)cb->start.lnum, cb->word_start_col,
+ (int)cb->end.lnum, cb->word_end_col, CLIP_SET);
+ cb->start.col = cb->word_start_col;
+ cb->end.col = cb->word_end_col;
+ break;
+
+ case SELECT_MODE_LINE:
+ clip_invert_area((int)cb->start.lnum, 0, (int)cb->start.lnum,
+ (int)Columns, CLIP_SET);
+ cb->start.col = 0;
+ cb->end.col = Columns;
+ break;
+ }
+
+ cb->prev = cb->start;
+
+#ifdef DEBUG_SELECTION
+ printf("Selection started at (%u,%u)\n", cb->start.lnum, cb->start.col);
+#endif
+}
+
+/*
+ * Continue processing the selection
+ */
+ void
+clip_process_selection(button, col, row, repeated_click)
+ int button;
+ int col;
+ int row;
+ int_u repeated_click;
+{
+ VimClipboard *cb = &clip_star;
+ int diff;
+ int slen = 1; /* cursor shape width */
+
+ if (button == MOUSE_RELEASE)
+ {
+ /* Check to make sure we have something selected */
+ if (cb->start.lnum == cb->end.lnum && cb->start.col == cb->end.col)
+ {
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_update_cursor(FALSE, FALSE);
+#endif
+ cb->state = SELECT_CLEARED;
+ return;
+ }
+
+#ifdef DEBUG_SELECTION
+ printf("Selection ended: (%u,%u) to (%u,%u)\n", cb->start.lnum,
+ cb->start.col, cb->end.lnum, cb->end.col);
+#endif
+ if (clip_isautosel()
+ || (
+#ifdef FEAT_GUI
+ gui.in_use ? (vim_strchr(p_go, GO_ASELML) != NULL) :
+#endif
+ clip_autoselectml))
+ clip_copy_modeless_selection(FALSE);
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_update_cursor(FALSE, FALSE);
+#endif
+
+ cb->state = SELECT_DONE;
+ return;
+ }
+
+ row = check_row(row);
+ col = check_col(col);
+#ifdef FEAT_MBYTE
+ col = mb_fix_col(col, row);
+#endif
+
+ if (col == (int)cb->prev.col && row == cb->prev.lnum && !repeated_click)
+ return;
+
+ /*
+ * When extending the selection with the right mouse button, swap the
+ * start and end if the position is before half the selection
+ */
+ if (cb->state == SELECT_DONE && button == MOUSE_RIGHT)
+ {
+ /*
+ * If the click is before the start, or the click is inside the
+ * selection and the start is the closest side, set the origin to the
+ * end of the selection.
+ */
+ if (clip_compare_pos(row, col, (int)cb->start.lnum, cb->start.col) < 0
+ || (clip_compare_pos(row, col,
+ (int)cb->end.lnum, cb->end.col) < 0
+ && (((cb->start.lnum == cb->end.lnum
+ && cb->end.col - col > col - cb->start.col))
+ || ((diff = (cb->end.lnum - row) -
+ (row - cb->start.lnum)) > 0
+ || (diff == 0 && col < (int)(cb->start.col +
+ cb->end.col) / 2)))))
+ {
+ cb->origin_row = (short_u)cb->end.lnum;
+ cb->origin_start_col = cb->end.col - 1;
+ cb->origin_end_col = cb->end.col;
+ }
+ else
+ {
+ cb->origin_row = (short_u)cb->start.lnum;
+ cb->origin_start_col = cb->start.col;
+ cb->origin_end_col = cb->start.col;
+ }
+ if (cb->mode == SELECT_MODE_WORD && !repeated_click)
+ cb->mode = SELECT_MODE_CHAR;
+ }
+
+ /* set state, for when using the right mouse button */
+ cb->state = SELECT_IN_PROGRESS;
+
+#ifdef DEBUG_SELECTION
+ printf("Selection extending to (%d,%d)\n", row, col);
+#endif
+
+ if (repeated_click && ++cb->mode > SELECT_MODE_LINE)
+ cb->mode = SELECT_MODE_CHAR;
+
+ switch (cb->mode)
+ {
+ case SELECT_MODE_CHAR:
+ /* If we're on a different line, find where the line ends */
+ if (row != cb->prev.lnum)
+ cb->word_end_col = clip_get_line_end(row);
+
+ /* See if we are before or after the origin of the selection */
+ if (clip_compare_pos(row, col, cb->origin_row,
+ cb->origin_start_col) >= 0)
+ {
+ if (col >= (int)cb->word_end_col)
+ clip_update_modeless_selection(cb, cb->origin_row,
+ cb->origin_start_col, row, (int)Columns);
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && mb_lefthalve(row, col))
+ slen = 2;
+#endif
+ clip_update_modeless_selection(cb, cb->origin_row,
+ cb->origin_start_col, row, col + slen);
+ }
+ }
+ else
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte
+ && mb_lefthalve(cb->origin_row, cb->origin_start_col))
+ slen = 2;
+#endif
+ if (col >= (int)cb->word_end_col)
+ clip_update_modeless_selection(cb, row, cb->word_end_col,
+ cb->origin_row, cb->origin_start_col + slen);
+ else
+ clip_update_modeless_selection(cb, row, col,
+ cb->origin_row, cb->origin_start_col + slen);
+ }
+ break;
+
+ case SELECT_MODE_WORD:
+ /* If we are still within the same word, do nothing */
+ if (row == cb->prev.lnum && col >= (int)cb->word_start_col
+ && col < (int)cb->word_end_col && !repeated_click)
+ return;
+
+ /* Get new word boundaries */
+ clip_get_word_boundaries(cb, row, col);
+
+ /* Handle being after the origin point of selection */
+ if (clip_compare_pos(row, col, cb->origin_row,
+ cb->origin_start_col) >= 0)
+ clip_update_modeless_selection(cb, cb->origin_row,
+ cb->origin_start_col, row, cb->word_end_col);
+ else
+ clip_update_modeless_selection(cb, row, cb->word_start_col,
+ cb->origin_row, cb->origin_end_col);
+ break;
+
+ case SELECT_MODE_LINE:
+ if (row == cb->prev.lnum && !repeated_click)
+ return;
+
+ if (clip_compare_pos(row, col, cb->origin_row,
+ cb->origin_start_col) >= 0)
+ clip_update_modeless_selection(cb, cb->origin_row, 0, row,
+ (int)Columns);
+ else
+ clip_update_modeless_selection(cb, row, 0, cb->origin_row,
+ (int)Columns);
+ break;
+ }
+
+ cb->prev.lnum = row;
+ cb->prev.col = col;
+
+#ifdef DEBUG_SELECTION
+ printf("Selection is: (%u,%u) to (%u,%u)\n", cb->start.lnum,
+ cb->start.col, cb->end.lnum, cb->end.col);
+#endif
+}
+
+#if 0 /* not used */
+/*
+ * Called after an Expose event to redraw the selection
+ */
+ void
+clip_redraw_selection(x, y, w, h)
+ int x;
+ int y;
+ int w;
+ int h;
+{
+ VimClipboard *cb = &clip_star;
+ int row1, col1, row2, col2;
+ int row;
+ int start;
+ int end;
+
+ if (cb->state == SELECT_CLEARED)
+ return;
+
+ row1 = check_row(Y_2_ROW(y));
+ col1 = check_col(X_2_COL(x));
+ row2 = check_row(Y_2_ROW(y + h - 1));
+ col2 = check_col(X_2_COL(x + w - 1));
+
+ /* Limit the rows that need to be re-drawn */
+ if (cb->start.lnum > row1)
+ row1 = cb->start.lnum;
+ if (cb->end.lnum < row2)
+ row2 = cb->end.lnum;
+
+ /* Look at each row that might need to be re-drawn */
+ for (row = row1; row <= row2; row++)
+ {
+ /* For the first selection row, use the starting selection column */
+ if (row == cb->start.lnum)
+ start = cb->start.col;
+ else
+ start = 0;
+
+ /* For the last selection row, use the ending selection column */
+ if (row == cb->end.lnum)
+ end = cb->end.col;
+ else
+ end = Columns;
+
+ if (col1 > start)
+ start = col1;
+
+ if (col2 < end)
+ end = col2 + 1;
+
+ if (end > start)
+ gui_mch_invert_rectangle(row, start, 1, end - start);
+ }
+}
+#endif
+
+# if defined(FEAT_GUI) || defined(PROTO)
+/*
+ * Redraw part of the selection if character at "row,col" is inside of it.
+ * Only used for the GUI.
+ */
+ void
+clip_may_redraw_selection(row, col, len)
+ int row, col;
+ int len;
+{
+ int start = col;
+ int end = col + len;
+
+ if (clip_star.state != SELECT_CLEARED
+ && row >= clip_star.start.lnum
+ && row <= clip_star.end.lnum)
+ {
+ if (row == clip_star.start.lnum && start < (int)clip_star.start.col)
+ start = clip_star.start.col;
+ if (row == clip_star.end.lnum && end > (int)clip_star.end.col)
+ end = clip_star.end.col;
+ if (end > start)
+ clip_invert_area(row, start, row, end, 0);
+ }
+}
+# endif
+
+/*
+ * Called from outside to clear selected region from the display
+ */
+ void
+clip_clear_selection()
+{
+ VimClipboard *cb = &clip_star;
+
+ if (cb->state == SELECT_CLEARED)
+ return;
+
+ clip_invert_area((int)cb->start.lnum, cb->start.col, (int)cb->end.lnum,
+ cb->end.col, CLIP_CLEAR);
+ cb->state = SELECT_CLEARED;
+}
+
+/*
+ * Clear the selection if any lines from "row1" to "row2" are inside of it.
+ */
+ void
+clip_may_clear_selection(row1, row2)
+ int row1, row2;
+{
+ if (clip_star.state == SELECT_DONE
+ && row2 >= clip_star.start.lnum
+ && row1 <= clip_star.end.lnum)
+ clip_clear_selection();
+}
+
+/*
+ * Called before the screen is scrolled up or down. Adjusts the line numbers
+ * of the selection. Call with big number when clearing the screen.
+ */
+ void
+clip_scroll_selection(rows)
+ int rows; /* negative for scroll down */
+{
+ int lnum;
+
+ if (clip_star.state == SELECT_CLEARED)
+ return;
+
+ lnum = clip_star.start.lnum - rows;
+ if (lnum <= 0)
+ clip_star.start.lnum = 0;
+ else if (lnum >= screen_Rows) /* scrolled off of the screen */
+ clip_star.state = SELECT_CLEARED;
+ else
+ clip_star.start.lnum = lnum;
+
+ lnum = clip_star.end.lnum - rows;
+ if (lnum < 0) /* scrolled off of the screen */
+ clip_star.state = SELECT_CLEARED;
+ else if (lnum >= screen_Rows)
+ clip_star.end.lnum = screen_Rows - 1;
+ else
+ clip_star.end.lnum = lnum;
+}
+
+/*
+ * Invert a region of the display between a starting and ending row and column
+ * Values for "how":
+ * CLIP_CLEAR: undo inversion
+ * CLIP_SET: set inversion
+ * CLIP_TOGGLE: set inversion if pos1 < pos2, undo inversion otherwise.
+ * 0: invert (GUI only).
+ */
+ static void
+clip_invert_area(row1, col1, row2, col2, how)
+ int row1;
+ int col1;
+ int row2;
+ int col2;
+ int how;
+{
+ int invert = FALSE;
+
+ if (how == CLIP_SET)
+ invert = TRUE;
+
+ /* Swap the from and to positions so the from is always before */
+ if (clip_compare_pos(row1, col1, row2, col2) > 0)
+ {
+ int tmp_row, tmp_col;
+
+ tmp_row = row1;
+ tmp_col = col1;
+ row1 = row2;
+ col1 = col2;
+ row2 = tmp_row;
+ col2 = tmp_col;
+ }
+ else if (how == CLIP_TOGGLE)
+ invert = TRUE;
+
+ /* If all on the same line, do it the easy way */
+ if (row1 == row2)
+ {
+ clip_invert_rectangle(row1, col1, 1, col2 - col1, invert);
+ }
+ else
+ {
+ /* Handle a piece of the first line */
+ if (col1 > 0)
+ {
+ clip_invert_rectangle(row1, col1, 1, (int)Columns - col1, invert);
+ row1++;
+ }
+
+ /* Handle a piece of the last line */
+ if (col2 < Columns - 1)
+ {
+ clip_invert_rectangle(row2, 0, 1, col2, invert);
+ row2--;
+ }
+
+ /* Handle the rectangle thats left */
+ if (row2 >= row1)
+ clip_invert_rectangle(row1, 0, row2 - row1 + 1, (int)Columns,
+ invert);
+ }
+}
+
+/*
+ * Invert or un-invert a rectangle of the screen.
+ * "invert" is true if the result is inverted.
+ */
+ static void
+clip_invert_rectangle(row, col, height, width, invert)
+ int row;
+ int col;
+ int height;
+ int width;
+ int invert;
+{
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_mch_invert_rectangle(row, col, height, width);
+ else
+#endif
+ screen_draw_rectangle(row, col, height, width, invert);
+}
+
+/*
+ * Copy the currently selected area into the '*' register so it will be
+ * available for pasting.
+ * When "both" is TRUE also copy to the '+' register.
+ */
+/*ARGSUSED*/
+ void
+clip_copy_modeless_selection(both)
+ int both;
+{
+ char_u *buffer;
+ char_u *bufp;
+ int row;
+ int start_col;
+ int end_col;
+ int line_end_col;
+ int add_newline_flag = FALSE;
+ int len;
+#ifdef FEAT_MBYTE
+ char_u *p;
+ int i;
+#endif
+ int row1 = clip_star.start.lnum;
+ int col1 = clip_star.start.col;
+ int row2 = clip_star.end.lnum;
+ int col2 = clip_star.end.col;
+
+ /*
+ * Make sure row1 <= row2, and if row1 == row2 that col1 <= col2.
+ */
+ if (row1 > row2)
+ {
+ row = row1; row1 = row2; row2 = row;
+ row = col1; col1 = col2; col2 = row;
+ }
+ else if (row1 == row2 && col1 > col2)
+ {
+ row = col1; col1 = col2; col2 = row;
+ }
+#ifdef FEAT_MBYTE
+ /* correct starting point for being on right halve of double-wide char */
+ p = ScreenLines + LineOffset[row1];
+ if (enc_dbcs != 0)
+ col1 -= (*mb_head_off)(p, p + col1);
+ else if (enc_utf8 && p[col1] == 0)
+ --col1;
+#endif
+
+ /* Create a temporary buffer for storing the text */
+ len = (row2 - row1 + 1) * Columns + 1;
+#ifdef FEAT_MBYTE
+ if (enc_dbcs != 0)
+ len *= 2; /* max. 2 bytes per display cell */
+ else if (enc_utf8)
+ len *= 9; /* max. 3 bytes per display cell + 2 composing chars */
+#endif
+ buffer = lalloc((long_u)len, TRUE);
+ if (buffer == NULL) /* out of memory */
+ return;
+
+ /* Process each row in the selection */
+ for (bufp = buffer, row = row1; row <= row2; row++)
+ {
+ if (row == row1)
+ start_col = col1;
+ else
+ start_col = 0;
+
+ if (row == row2)
+ end_col = col2;
+ else
+ end_col = Columns;
+
+ line_end_col = clip_get_line_end(row);
+
+ /* See if we need to nuke some trailing whitespace */
+ if (end_col >= Columns && (row < row2 || end_col > line_end_col))
+ {
+ /* Get rid of trailing whitespace */
+ end_col = line_end_col;
+ if (end_col < start_col)
+ end_col = start_col;
+
+ /* If the last line extended to the end, add an extra newline */
+ if (row == row2)
+ add_newline_flag = TRUE;
+ }
+
+ /* If after the first row, we need to always add a newline */
+ if (row > row1 && !LineWraps[row - 1])
+ *bufp++ = NL;
+
+ if (row < screen_Rows && end_col <= screen_Columns)
+ {
+#ifdef FEAT_MBYTE
+ if (enc_dbcs != 0)
+ {
+ p = ScreenLines + LineOffset[row];
+ for (i = start_col; i < end_col; ++i)
+ if (enc_dbcs == DBCS_JPNU && p[i] == 0x8e)
+ {
+ /* single-width double-byte char */
+ *bufp++ = 0x8e;
+ *bufp++ = ScreenLines2[LineOffset[row] + i];
+ }
+ else
+ {
+ *bufp++ = p[i];
+ if (MB_BYTE2LEN(p[i]) == 2)
+ *bufp++ = p[++i];
+ }
+ }
+ else if (enc_utf8)
+ {
+ int off;
+
+ off = LineOffset[row];
+ for (i = start_col; i < end_col; ++i)
+ {
+ /* The base character is either in ScreenLinesUC[] or
+ * ScreenLines[]. */
+ if (ScreenLinesUC[off + i] == 0)
+ *bufp++ = ScreenLines[off + i];
+ else
+ {
+ bufp += utf_char2bytes(ScreenLinesUC[off + i], bufp);
+ if (ScreenLinesC1[off + i] != 0)
+ {
+ /* Add one or two composing characters. */
+ bufp += utf_char2bytes(ScreenLinesC1[off + i],
+ bufp);
+ if (ScreenLinesC2[off + i] != 0)
+ bufp += utf_char2bytes(ScreenLinesC2[off + i],
+ bufp);
+ }
+ }
+ /* Skip right halve of double-wide character. */
+ if (ScreenLines[off + i + 1] == 0)
+ ++i;
+ }
+ }
+ else
+#endif
+ {
+ STRNCPY(bufp, ScreenLines + LineOffset[row] + start_col,
+ end_col - start_col);
+ bufp += end_col - start_col;
+ }
+ }
+ }
+
+ /* Add a newline at the end if the selection ended there */
+ if (add_newline_flag)
+ *bufp++ = NL;
+
+ /* First cleanup any old selection and become the owner. */
+ clip_free_selection(&clip_star);
+ clip_own_selection(&clip_star);
+
+ /* Yank the text into the '*' register. */
+ clip_yank_selection(MCHAR, buffer, (long)(bufp - buffer), &clip_star);
+
+ /* Make the register contents available to the outside world. */
+ clip_gen_set_selection(&clip_star);
+
+#ifdef FEAT_X11
+ if (both)
+ {
+ /* Do the same for the '+' register. */
+ clip_free_selection(&clip_plus);
+ clip_own_selection(&clip_plus);
+ clip_yank_selection(MCHAR, buffer, (long)(bufp - buffer), &clip_plus);
+ clip_gen_set_selection(&clip_plus);
+ }
+#endif
+ vim_free(buffer);
+}
+
+/*
+ * Find the starting and ending positions of the word at the given row and
+ * column. Only white-separated words are recognized here.
+ */
+#define CHAR_CLASS(c) (c <= ' ' ? ' ' : vim_iswordc(c))
+
+ static void
+clip_get_word_boundaries(cb, row, col)
+ VimClipboard *cb;
+ int row;
+ int col;
+{
+ int start_class;
+ int temp_col;
+ char_u *p;
+#ifdef FEAT_MBYTE
+ int mboff;
+#endif
+
+ if (row >= screen_Rows || col >= screen_Columns)
+ return;
+
+ p = ScreenLines + LineOffset[row];
+#ifdef FEAT_MBYTE
+ /* Correct for starting in the right halve of a double-wide char */
+ if (enc_dbcs != 0)
+ col -= dbcs_screen_head_off(p, p + col);
+ else if (enc_utf8 && p[col] == 0)
+ --col;
+#endif
+ start_class = CHAR_CLASS(p[col]);
+
+ temp_col = col;
+ for ( ; temp_col > 0; temp_col--)
+#ifdef FEAT_MBYTE
+ if (enc_dbcs != 0
+ && (mboff = dbcs_screen_head_off(p, p + temp_col - 1)) > 0)
+ temp_col -= mboff;
+ else
+#endif
+ if (CHAR_CLASS(p[temp_col - 1]) != start_class
+#ifdef FEAT_MBYTE
+ && !(enc_utf8 && p[temp_col - 1] == 0)
+#endif
+ )
+ break;
+ cb->word_start_col = temp_col;
+
+ temp_col = col;
+ for ( ; temp_col < screen_Columns; temp_col++)
+#ifdef FEAT_MBYTE
+ if (enc_dbcs != 0 && dbcs_ptr2cells(p + temp_col) == 2)
+ ++temp_col;
+ else
+#endif
+ if (CHAR_CLASS(p[temp_col]) != start_class
+#ifdef FEAT_MBYTE
+ && !(enc_utf8 && p[temp_col] == 0)
+#endif
+ )
+ break;
+ cb->word_end_col = temp_col;
+}
+
+/*
+ * Find the column position for the last non-whitespace character on the given
+ * line.
+ */
+ static int
+clip_get_line_end(row)
+ int row;
+{
+ int i;
+
+ if (row >= screen_Rows)
+ return 0;
+ for (i = screen_Columns; i > 0; i--)
+ if (ScreenLines[LineOffset[row] + i - 1] != ' ')
+ break;
+ return i;
+}
+
+/*
+ * Update the currently selected region by adding and/or subtracting from the
+ * beginning or end and inverting the changed area(s).
+ */
+ static void
+clip_update_modeless_selection(cb, row1, col1, row2, col2)
+ VimClipboard *cb;
+ int row1;
+ int col1;
+ int row2;
+ int col2;
+{
+ /* See if we changed at the beginning of the selection */
+ if (row1 != cb->start.lnum || col1 != (int)cb->start.col)
+ {
+ clip_invert_area(row1, col1, (int)cb->start.lnum, cb->start.col,
+ CLIP_TOGGLE);
+ cb->start.lnum = row1;
+ cb->start.col = col1;
+ }
+
+ /* See if we changed at the end of the selection */
+ if (row2 != cb->end.lnum || col2 != (int)cb->end.col)
+ {
+ clip_invert_area((int)cb->end.lnum, cb->end.col, row2, col2,
+ CLIP_TOGGLE);
+ cb->end.lnum = row2;
+ cb->end.col = col2;
+ }
+}
+
+ int
+clip_gen_own_selection(cbd)
+ VimClipboard *cbd;
+{
+#ifdef FEAT_XCLIPBOARD
+# ifdef FEAT_GUI
+ if (gui.in_use)
+ return clip_mch_own_selection(cbd);
+ else
+# endif
+ return clip_xterm_own_selection(cbd);
+#else
+ return clip_mch_own_selection(cbd);
+#endif
+}
+
+ void
+clip_gen_lose_selection(cbd)
+ VimClipboard *cbd;
+{
+#ifdef FEAT_XCLIPBOARD
+# ifdef FEAT_GUI
+ if (gui.in_use)
+ clip_mch_lose_selection(cbd);
+ else
+# endif
+ clip_xterm_lose_selection(cbd);
+#else
+ clip_mch_lose_selection(cbd);
+#endif
+}
+
+ void
+clip_gen_set_selection(cbd)
+ VimClipboard *cbd;
+{
+#ifdef FEAT_XCLIPBOARD
+# ifdef FEAT_GUI
+ if (gui.in_use)
+ clip_mch_set_selection(cbd);
+ else
+# endif
+ clip_xterm_set_selection(cbd);
+#else
+ clip_mch_set_selection(cbd);
+#endif
+}
+
+ void
+clip_gen_request_selection(cbd)
+ VimClipboard *cbd;
+{
+#ifdef FEAT_XCLIPBOARD
+# ifdef FEAT_GUI
+ if (gui.in_use)
+ clip_mch_request_selection(cbd);
+ else
+# endif
+ clip_xterm_request_selection(cbd);
+#else
+ clip_mch_request_selection(cbd);
+#endif
+}
+
+#endif /* FEAT_CLIPBOARD */
+
+/*****************************************************************************
+ * Functions that handle the input buffer.
+ * This is used for any GUI version, and the unix terminal version.
+ *
+ * For Unix, the input characters are buffered to be able to check for a
+ * CTRL-C. This should be done with signals, but I don't know how to do that
+ * in a portable way for a tty in RAW mode.
+ *
+ * For the client-server code in the console the received keys are put in the
+ * input buffer.
+ */
+
+#if defined(USE_INPUT_BUF) || defined(PROTO)
+
+/*
+ * Internal typeahead buffer. Includes extra space for long key code
+ * descriptions which would otherwise overflow. The buffer is considered full
+ * when only this extra space (or part of it) remains.
+ */
+#if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \
+ || defined(FEAT_CLIENTSERVER)
+ /*
+ * Sun WorkShop and NetBeans stuff debugger commands into the input buffer.
+ * This requires a larger buffer...
+ * (Madsen) Go with this for remote input as well ...
+ */
+# define INBUFLEN 4096
+#else
+# define INBUFLEN 250
+#endif
+
+static char_u inbuf[INBUFLEN + MAX_KEY_CODE_LEN];
+static int inbufcount = 0; /* number of chars in inbuf[] */
+
+/*
+ * vim_is_input_buf_full(), vim_is_input_buf_empty(), add_to_input_buf(), and
+ * trash_input_buf() are functions for manipulating the input buffer. These
+ * are used by the gui_* calls when a GUI is used to handle keyboard input.
+ */
+
+ int
+vim_is_input_buf_full()
+{
+ return (inbufcount >= INBUFLEN);
+}
+
+ int
+vim_is_input_buf_empty()
+{
+ return (inbufcount == 0);
+}
+
+#if defined(FEAT_OLE) || defined(PROTO)
+ int
+vim_free_in_input_buf()
+{
+ return (INBUFLEN - inbufcount);
+}
+#endif
+
+#if defined(FEAT_GUI_GTK) || defined(PROTO)
+ int
+vim_used_in_input_buf()
+{
+ return inbufcount;
+}
+#endif
+
+#if defined(FEAT_EVAL) || defined(FEAT_EX_EXTRA) || defined(PROTO)
+/*
+ * Return the current contents of the input buffer and make it empty.
+ * The returned pointer must be passed to set_input_buf() later.
+ */
+ char_u *
+get_input_buf()
+{
+ garray_T *gap;
+
+ /* We use a growarray to store the data pointer and the length. */
+ gap = (garray_T *)alloc((unsigned)sizeof(garray_T));
+ if (gap != NULL)
+ {
+ /* Add one to avoid a zero size. */
+ gap->ga_data = alloc((unsigned)inbufcount + 1);
+ if (gap->ga_data != NULL)
+ mch_memmove(gap->ga_data, inbuf, (size_t)inbufcount);
+ gap->ga_len = inbufcount;
+ }
+ trash_input_buf();
+ return (char_u *)gap;
+}
+
+/*
+ * Restore the input buffer with a pointer returned from get_input_buf().
+ * The allocated memory is freed, this only works once!
+ */
+ void
+set_input_buf(p)
+ char_u *p;
+{
+ garray_T *gap = (garray_T *)p;
+
+ if (gap != NULL)
+ {
+ if (gap->ga_data != NULL)
+ {
+ mch_memmove(inbuf, gap->ga_data, gap->ga_len);
+ inbufcount = gap->ga_len;
+ vim_free(gap->ga_data);
+ }
+ vim_free(gap);
+ }
+}
+#endif
+
+#if defined(FEAT_GUI) || defined(FEAT_MOUSE_GPM) \
+ || defined(FEAT_XCLIPBOARD) || defined(VMS) \
+ || defined(FEAT_SNIFF) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
+/*
+ * Add the given bytes to the input buffer
+ * Special keys start with CSI. A real CSI must have been translated to
+ * CSI KS_EXTRA KE_CSI. K_SPECIAL doesn't require translation.
+ */
+ void
+add_to_input_buf(s, len)
+ char_u *s;
+ int len;
+{
+ if (inbufcount + len > INBUFLEN + MAX_KEY_CODE_LEN)
+ return; /* Shouldn't ever happen! */
+
+#ifdef FEAT_HANGULIN
+ if ((State & (INSERT|CMDLINE)) && hangul_input_state_get())
+ if ((len = hangul_input_process(s, len)) == 0)
+ return;
+#endif
+
+ while (len--)
+ inbuf[inbufcount++] = *s++;
+}
+#endif
+
+#if (defined(FEAT_XIM) && defined(FEAT_GUI_GTK)) \
+ || (defined(FEAT_MBYTE) && defined(FEAT_MBYTE_IME)) \
+ || defined(PROTO)
+/*
+ * Add "str[len]" to the input buffer while escaping CSI bytes.
+ */
+ void
+add_to_input_buf_csi(char_u *str, int len)
+{
+ int i;
+ char_u buf[2];
+
+ for (i = 0; i < len; ++i)
+ {
+ add_to_input_buf(str + i, 1);
+ if (str[i] == CSI)
+ {
+ /* Turn CSI into K_CSI. */
+ buf[0] = KS_EXTRA;
+ buf[1] = (int)KE_CSI;
+ add_to_input_buf(buf, 2);
+ }
+ }
+}
+#endif
+
+#if defined(FEAT_HANGULIN) || defined(PROTO)
+ void
+push_raw_key (s, len)
+ char_u *s;
+ int len;
+{
+ while (len--)
+ inbuf[inbufcount++] = *s++;
+}
+#endif
+
+#if defined(FEAT_GUI) || defined(FEAT_EVAL) || defined(FEAT_EX_EXTRA) \
+ || defined(PROTO)
+/* Remove everything from the input buffer. Called when ^C is found */
+ void
+trash_input_buf()
+{
+ inbufcount = 0;
+}
+#endif
+
+/*
+ * Read as much data from the input buffer as possible up to maxlen, and store
+ * it in buf.
+ * Note: this function used to be Read() in unix.c
+ */
+ int
+read_from_input_buf(buf, maxlen)
+ char_u *buf;
+ long maxlen;
+{
+ if (inbufcount == 0) /* if the buffer is empty, fill it */
+ fill_input_buf(TRUE);
+ if (maxlen > inbufcount)
+ maxlen = inbufcount;
+ mch_memmove(buf, inbuf, (size_t)maxlen);
+ inbufcount -= maxlen;
+ if (inbufcount)
+ mch_memmove(inbuf, inbuf + maxlen, (size_t)inbufcount);
+ return (int)maxlen;
+}
+
+ void
+fill_input_buf(exit_on_error)
+ int exit_on_error;
+{
+#if defined(UNIX) || defined(OS2) || defined(VMS) || defined(MACOS_X_UNIX)
+ int len;
+ int try;
+ static int did_read_something = FALSE;
+# ifdef FEAT_MBYTE
+ static char_u *rest = NULL; /* unconverted rest of previous read */
+ static int restlen = 0;
+ int unconverted;
+# endif
+#endif
+
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ gui_mch_update();
+ return;
+ }
+#endif
+#if defined(UNIX) || defined(OS2) || defined(VMS) || defined(MACOS_X_UNIX)
+ if (vim_is_input_buf_full())
+ return;
+ /*
+ * Fill_input_buf() is only called when we really need a character.
+ * If we can't get any, but there is some in the buffer, just return.
+ * If we can't get any, and there isn't any in the buffer, we give up and
+ * exit Vim.
+ */
+# ifdef __BEOS__
+ /*
+ * On the BeBox version (for now), all input is secretly performed within
+ * beos_select() which is called from RealWaitForChar().
+ */
+ while (!vim_is_input_buf_full() && RealWaitForChar(read_cmd_fd, 0, NULL))
+ ;
+ len = inbufcount;
+ inbufcount = 0;
+# else
+
+# ifdef FEAT_SNIFF
+ if (sniff_request_waiting)
+ {
+ add_to_input_buf((char_u *)"\233sniff",6); /* results in K_SNIFF */
+ sniff_request_waiting = 0;
+ want_sniff_request = 0;
+ return;
+ }
+# endif
+
+# ifdef FEAT_MBYTE
+ if (rest != NULL)
+ {
+ /* Use remainder of previous call, starts with an invalid character
+ * that may become valid when reading more. */
+ if (restlen > INBUFLEN - inbufcount)
+ unconverted = INBUFLEN - inbufcount;
+ else
+ unconverted = restlen;
+ mch_memmove(inbuf + inbufcount, rest, unconverted);
+ if (unconverted == restlen)
+ {
+ vim_free(rest);
+ rest = NULL;
+ }
+ else
+ {
+ restlen -= unconverted;
+ mch_memmove(rest, rest + unconverted, restlen);
+ }
+ inbufcount += unconverted;
+ }
+ else
+ unconverted = 0;
+#endif
+
+ len = 0; /* to avoid gcc warning */
+ for (try = 0; try < 100; ++try)
+ {
+# ifdef VMS
+ len = vms_read(
+# else
+ len = read(read_cmd_fd,
+# endif
+ (char *)inbuf + inbufcount, (size_t)((INBUFLEN - inbufcount)
+# ifdef FEAT_MBYTE
+ / input_conv.vc_factor
+# endif
+ ));
+# if 0
+ ) /* avoid syntax highlight error */
+# endif
+ if (len > 0 || got_int)
+ break;
+ /*
+ * If reading stdin results in an error, continue reading stderr.
+ * This helps when using "foo | xargs vim".
+ */
+ if (!did_read_something && !isatty(read_cmd_fd) && read_cmd_fd == 0)
+ {
+ int m = cur_tmode;
+
+ /* We probably set the wrong file descriptor to raw mode. Switch
+ * back to cooked mode, use another descriptor and set the mode to
+ * what it was. */
+ settmode(TMODE_COOK);
+#ifdef HAVE_DUP
+ /* Use stderr for stdin, also works for shell commands. */
+ close(0);
+ dup(2);
+#else
+ read_cmd_fd = 2; /* read from stderr instead of stdin */
+#endif
+ settmode(m);
+ }
+ if (!exit_on_error)
+ return;
+ }
+# endif
+ if (len <= 0 && !got_int)
+ read_error_exit();
+ if (len > 0)
+ did_read_something = TRUE;
+ if (got_int)
+ {
+ /* Interrupted, pretend a CTRL-C was typed. */
+ inbuf[0] = 3;
+ inbufcount = 1;
+ }
+ else
+ {
+# ifdef FEAT_MBYTE
+ /*
+ * May perform conversion on the input characters.
+ * Include the unconverted rest of the previous call.
+ * If there is an incomplete char at the end it is kept for the next
+ * time, reading more bytes should make conversion possible.
+ * Don't do this in the unlikely event that the input buffer is too
+ * small ("rest" still contains more bytes).
+ */
+ if (input_conv.vc_type != CONV_NONE)
+ {
+ inbufcount -= unconverted;
+ len = convert_input_safe(inbuf + inbufcount,
+ len + unconverted, INBUFLEN - inbufcount,
+ rest == NULL ? &rest : NULL, &restlen);
+ }
+# endif
+ while (len-- > 0)
+ {
+ /*
+ * if a CTRL-C was typed, remove it from the buffer and set got_int
+ */
+ if (inbuf[inbufcount] == 3 && ctrl_c_interrupts)
+ {
+ /* remove everything typed before the CTRL-C */
+ mch_memmove(inbuf, inbuf + inbufcount, (size_t)(len + 1));
+ inbufcount = 0;
+ got_int = TRUE;
+ }
+ ++inbufcount;
+ }
+ }
+#endif /* UNIX or OS2 or VMS*/
+}
+#endif /* defined(UNIX) || defined(FEAT_GUI) || defined(OS2) || defined(VMS) */
+
+/*
+ * Exit because of an input read error.
+ */
+ void
+read_error_exit()
+{
+ if (silent_mode) /* Normal way to exit for "ex -s" */
+ getout(0);
+ STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
+ preserve_exit();
+}
+
+#if defined(CURSOR_SHAPE) || defined(PROTO)
+/*
+ * May update the shape of the cursor.
+ */
+ void
+ui_cursor_shape()
+{
+# ifdef FEAT_GUI
+ if (gui.in_use)
+ gui_update_cursor_later();
+# endif
+# ifdef MCH_CURSOR_SHAPE
+ mch_update_cursor();
+# endif
+}
+#endif
+
+#if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(FEAT_RIGHTLEFT) \
+ || defined(PROTO)
+/*
+ * Check bounds for column number
+ */
+ int
+check_col(col)
+ int col;
+{
+ if (col < 0)
+ return 0;
+ if (col >= (int)screen_Columns)
+ return (int)screen_Columns - 1;
+ return col;
+}
+
+/*
+ * Check bounds for row number
+ */
+ int
+check_row(row)
+ int row;
+{
+ if (row < 0)
+ return 0;
+ if (row >= (int)screen_Rows)
+ return (int)screen_Rows - 1;
+ return row;
+}
+#endif
+
+/*
+ * Stuff for the X clipboard. Shared between VMS and Unix.
+ */
+
+#if defined(FEAT_XCLIPBOARD) || defined(FEAT_GUI_X11) || defined(PROTO)
+# include <X11/Xatom.h>
+# include <X11/Intrinsic.h>
+
+/*
+ * Open the application context (if it hasn't been opened yet).
+ * Used for Motif and Athena GUI and the xterm clipboard.
+ */
+ void
+open_app_context()
+{
+ if (app_context == NULL)
+ {
+ XtToolkitInitialize();
+ app_context = XtCreateApplicationContext();
+ }
+}
+
+static Atom vim_atom; /* Vim's own special selection format */
+#ifdef FEAT_MBYTE
+static Atom vimenc_atom; /* Vim's extended selection format */
+#endif
+static Atom compound_text_atom;
+static Atom text_atom;
+static Atom targets_atom;
+
+ void
+x11_setup_atoms(dpy)
+ Display *dpy;
+{
+ vim_atom = XInternAtom(dpy, VIM_ATOM_NAME, False);
+#ifdef FEAT_MBYTE
+ vimenc_atom = XInternAtom(dpy, VIMENC_ATOM_NAME,False);
+#endif
+ compound_text_atom = XInternAtom(dpy, "COMPOUND_TEXT", False);
+ text_atom = XInternAtom(dpy, "TEXT", False);
+ targets_atom = XInternAtom(dpy, "TARGETS", False);
+ clip_star.sel_atom = XA_PRIMARY;
+ clip_plus.sel_atom = XInternAtom(dpy, "CLIPBOARD", False);
+}
+
+/*
+ * X Selection stuff, for cutting and pasting text to other windows.
+ */
+
+static void clip_x11_request_selection_cb __ARGS((Widget, XtPointer, Atom *, Atom *, XtPointer, long_u *, int *));
+
+/* ARGSUSED */
+ static void
+clip_x11_request_selection_cb(w, success, sel_atom, type, value, length,
+ format)
+ Widget w;
+ XtPointer success;
+ Atom *sel_atom;
+ Atom *type;
+ XtPointer value;
+ long_u *length;
+ int *format;
+{
+ int motion_type;
+ long_u len;
+ char_u *p;
+ char **text_list = NULL;
+ VimClipboard *cbd;
+#ifdef FEAT_MBYTE
+ char_u *tmpbuf = NULL;
+#endif
+
+ if (*sel_atom == clip_plus.sel_atom)
+ cbd = &clip_plus;
+ else
+ cbd = &clip_star;
+
+ if (value == NULL || *length == 0)
+ {
+ clip_free_selection(cbd); /* ??? [what's the query?] */
+ *(int *)success = FALSE;
+ return;
+ }
+ motion_type = MCHAR;
+ p = (char_u *)value;
+ len = *length;
+ if (*type == vim_atom)
+ {
+ motion_type = *p++;
+ len--;
+ }
+
+#ifdef FEAT_MBYTE
+ else if (*type == vimenc_atom)
+ {
+ char_u *enc;
+ vimconv_T conv;
+ int convlen;
+
+ motion_type = *p++;
+ --len;
+
+ enc = p;
+ p += STRLEN(p) + 1;
+ len -= p - enc;
+
+ /* If the encoding of the text is different from 'encoding', attempt
+ * converting it. */
+ conv.vc_type = CONV_NONE;
+ convert_setup(&conv, enc, p_enc);
+ if (conv.vc_type != CONV_NONE)
+ {
+ convlen = len; /* Need to use an int here. */
+ tmpbuf = string_convert(&conv, p, &convlen);
+ len = convlen;
+ if (tmpbuf != NULL)
+ p = tmpbuf;
+ convert_setup(&conv, NULL, NULL);
+ }
+ }
+#endif
+
+ else if (*type == compound_text_atom || (
+#ifdef FEAT_MBYTE
+ enc_dbcs != 0 &&
+#endif
+ *type == text_atom))
+ {
+ XTextProperty text_prop;
+ int n_text = 0;
+ int status;
+
+ text_prop.value = (unsigned char *)value;
+ text_prop.encoding = *type;
+ text_prop.format = *format;
+ text_prop.nitems = STRLEN(value);
+ status = XmbTextPropertyToTextList(X_DISPLAY, &text_prop,
+ &text_list, &n_text);
+ if (status != Success || n_text < 1)
+ {
+ *(int *)success = FALSE;
+ return;
+ }
+ p = (char_u *)text_list[0];
+ len = STRLEN(p);
+ }
+ clip_yank_selection(motion_type, p, (long)len, cbd);
+
+ if (text_list != NULL)
+ XFreeStringList(text_list);
+#ifdef FEAT_MBYTE
+ vim_free(tmpbuf);
+#endif
+ XtFree((char *)value);
+ *(int *)success = TRUE;
+}
+
+ void
+clip_x11_request_selection(myShell, dpy, cbd)
+ Widget myShell;
+ Display *dpy;
+ VimClipboard *cbd;
+{
+ XEvent event;
+ Atom type;
+ static int success;
+ int i;
+ int nbytes = 0;
+ char_u *buffer;
+
+ for (i =
+#ifdef FEAT_MBYTE
+ 0
+#else
+ 1
+#endif
+ ; i < 5; i++)
+ {
+ switch (i)
+ {
+#ifdef FEAT_MBYTE
+ case 0: type = vimenc_atom; break;
+#endif
+ case 1: type = vim_atom; break;
+ case 2: type = compound_text_atom; break;
+ case 3: type = text_atom; break;
+ default: type = XA_STRING;
+ }
+ XtGetSelectionValue(myShell, cbd->sel_atom, type,
+ clip_x11_request_selection_cb, (XtPointer)&success, CurrentTime);
+
+ /* Make sure the request for the selection goes out before waiting for
+ * a response. */
+ XFlush(dpy);
+
+ /*
+ * Wait for result of selection request, otherwise if we type more
+ * characters, then they will appear before the one that requested the
+ * paste! Don't worry, we will catch up with any other events later.
+ */
+ for (;;)
+ {
+ if (XCheckTypedEvent(dpy, SelectionNotify, &event))
+ break;
+
+ /* Do we need this? Probably not. */
+ XSync(dpy, False);
+
+ /* Bernhard Walle solved a slow paste response in an X terminal by
+ * adding: usleep(10000); here. */
+ }
+
+ /* this is where clip_x11_request_selection_cb() is actually called */
+ XtDispatchEvent(&event);
+
+ if (success)
+ return;
+ }
+
+ /* Final fallback position - use the X CUT_BUFFER0 store */
+ buffer = (char_u *)XFetchBuffer(dpy, &nbytes, 0);
+ if (nbytes > 0)
+ {
+ /* Got something */
+ clip_yank_selection(MCHAR, buffer, (long)nbytes, cbd);
+ XFree((void *)buffer);
+ if (p_verbose > 0)
+ smsg((char_u *)_("Used CUT_BUFFER0 instead of empty selection") );
+ }
+}
+
+static Boolean clip_x11_convert_selection_cb __ARGS((Widget, Atom *, Atom *, Atom *, XtPointer *, long_u *, int *));
+
+/* ARGSUSED */
+ static Boolean
+clip_x11_convert_selection_cb(w, sel_atom, target, type, value, length, format)
+ Widget w;
+ Atom *sel_atom;
+ Atom *target;
+ Atom *type;
+ XtPointer *value;
+ long_u *length;
+ int *format;
+{
+ char_u *string;
+ char_u *result;
+ int motion_type;
+ VimClipboard *cbd;
+ int i;
+
+ if (*sel_atom == clip_plus.sel_atom)
+ cbd = &clip_plus;
+ else
+ cbd = &clip_star;
+
+ if (!cbd->owned)
+ return False; /* Shouldn't ever happen */
+
+ /* requestor wants to know what target types we support */
+ if (*target == targets_atom)
+ {
+ Atom *array;
+
+ if ((array = (Atom *)XtMalloc((unsigned)(sizeof(Atom) * 6))) == NULL)
+ return False;
+ *value = (XtPointer)array;
+ i = 0;
+ array[i++] = XA_STRING;
+ array[i++] = targets_atom;
+#ifdef FEAT_MBYTE
+ array[i++] = vimenc_atom;
+#endif
+ array[i++] = vim_atom;
+ array[i++] = text_atom;
+ array[i++] = compound_text_atom;
+ *type = XA_ATOM;
+ /* This used to be: *format = sizeof(Atom) * 8; but that caused
+ * crashes on 64 bit machines. (Peter Derr) */
+ *format = 32;
+ *length = i;
+ return True;
+ }
+
+ if ( *target != XA_STRING
+#ifdef FEAT_MBYTE
+ && *target != vimenc_atom
+#endif
+ && *target != vim_atom
+ && *target != text_atom
+ && *target != compound_text_atom)
+ return False;
+
+ clip_get_selection(cbd);
+ motion_type = clip_convert_selection(&string, length, cbd);
+ if (motion_type < 0)
+ return False;
+
+ /* For our own format, the first byte contains the motion type */
+ if (*target == vim_atom)
+ (*length)++;
+
+#ifdef FEAT_MBYTE
+ /* Our own format with encoding: motion 'encoding' NUL text */
+ if (*target == vimenc_atom)
+ *length += STRLEN(p_enc) + 2;
+#endif
+
+ *value = XtMalloc((Cardinal)*length);
+ result = (char_u *)*value;
+ if (result == NULL)
+ {
+ vim_free(string);
+ return False;
+ }
+
+ if (*target == XA_STRING)
+ {
+ mch_memmove(result, string, (size_t)(*length));
+ *type = XA_STRING;
+ }
+ else if (*target == compound_text_atom
+ || *target == text_atom)
+ {
+ XTextProperty text_prop;
+ char *string_nt = (char *)alloc((unsigned)*length + 1);
+
+ /* create NUL terminated string which XmbTextListToTextProperty wants */
+ mch_memmove(string_nt, string, (size_t)*length);
+ string_nt[*length] = NUL;
+ XmbTextListToTextProperty(X_DISPLAY, (char **)&string_nt, 1,
+ XCompoundTextStyle, &text_prop);
+ vim_free(string_nt);
+ XtFree(*value); /* replace with COMPOUND text */
+ *value = (XtPointer)(text_prop.value); /* from plain text */
+ *length = text_prop.nitems;
+ *type = compound_text_atom;
+ }
+
+#ifdef FEAT_MBYTE
+ else if (*target == vimenc_atom)
+ {
+ int l = STRLEN(p_enc);
+
+ result[0] = motion_type;
+ STRCPY(result + 1, p_enc);
+ mch_memmove(result + l + 2, string, (size_t)(*length - l - 2));
+ *type = vimenc_atom;
+ }
+#endif
+
+ else
+ {
+ result[0] = motion_type;
+ mch_memmove(result + 1, string, (size_t)(*length - 1));
+ *type = vim_atom;
+ }
+ *format = 8; /* 8 bits per char */
+ vim_free(string);
+ return True;
+}
+
+static void clip_x11_lose_ownership_cb __ARGS((Widget, Atom *));
+
+/* ARGSUSED */
+ static void
+clip_x11_lose_ownership_cb(w, sel_atom)
+ Widget w;
+ Atom *sel_atom;
+{
+ if (*sel_atom == clip_plus.sel_atom)
+ clip_lose_selection(&clip_plus);
+ else
+ clip_lose_selection(&clip_star);
+}
+
+ void
+clip_x11_lose_selection(myShell, cbd)
+ Widget myShell;
+ VimClipboard *cbd;
+{
+ XtDisownSelection(myShell, cbd->sel_atom, CurrentTime);
+}
+
+ int
+clip_x11_own_selection(myShell, cbd)
+ Widget myShell;
+ VimClipboard *cbd;
+{
+ if (XtOwnSelection(myShell, cbd->sel_atom, CurrentTime,
+ clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb,
+ NULL) == False)
+ return FAIL;
+ return OK;
+}
+
+/*
+ * Send the current selection to the clipboard. Do nothing for X because we
+ * will fill in the selection only when requested by another app.
+ */
+/*ARGSUSED*/
+ void
+clip_x11_set_selection(cbd)
+ VimClipboard *cbd;
+{
+}
+#endif
+
+#if defined(FEAT_MOUSE) || defined(PROTO)
+
+/*
+ * Move the cursor to the specified row and column on the screen.
+ * Change current window if neccesary. Returns an integer with the
+ * CURSOR_MOVED bit set if the cursor has moved or unset otherwise.
+ *
+ * The MOUSE_FOLD_CLOSE bit is set when clicked on the '-' in a fold column.
+ * The MOUSE_FOLD_OPEN bit is set when clicked on the '+' in a fold column.
+ *
+ * If flags has MOUSE_FOCUS, then the current window will not be changed, and
+ * if the mouse is outside the window then the text will scroll, or if the
+ * mouse was previously on a status line, then the status line may be dragged.
+ *
+ * If flags has MOUSE_MAY_VIS, then VIsual mode will be started before the
+ * cursor is moved unless the cursor was on a status line.
+ * This function returns one of IN_UNKNOWN, IN_BUFFER, IN_STATUS_LINE or
+ * IN_SEP_LINE depending on where the cursor was clicked.
+ *
+ * If flags has MOUSE_MAY_STOP_VIS, then Visual mode will be stopped, unless
+ * the mouse is on the status line of the same window.
+ *
+ * If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since
+ * the last call.
+ *
+ * If flags has MOUSE_SETPOS, nothing is done, only the current position is
+ * remembered.
+ */
+ int
+jump_to_mouse(flags, inclusive, which_button)
+ int flags;
+ int *inclusive; /* used for inclusive operator, can be NULL */
+ int which_button; /* MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE */
+{
+ static int on_status_line = 0; /* #lines below bottom of window */
+#ifdef FEAT_VERTSPLIT
+ static int on_sep_line = 0; /* on separator right of window */
+#endif
+ static int prev_row = -1;
+ static int prev_col = -1;
+ static win_T *dragwin = NULL; /* window being dragged */
+ static int did_drag = FALSE; /* drag was noticed */
+
+ win_T *wp, *old_curwin;
+ pos_T old_cursor;
+ int count;
+ int first;
+ int row = mouse_row;
+ int col = mouse_col;
+#ifdef FEAT_FOLDING
+ int mouse_char;
+#endif
+
+ mouse_past_bottom = FALSE;
+ mouse_past_eol = FALSE;
+
+ if (flags & MOUSE_RELEASED)
+ {
+ /* On button release we may change window focus if positioned on a
+ * status line and no dragging happened. */
+ if (dragwin != NULL && !did_drag)
+ flags &= ~(MOUSE_FOCUS | MOUSE_DID_MOVE);
+ dragwin = NULL;
+ did_drag = FALSE;
+ }
+
+ if ((flags & MOUSE_DID_MOVE)
+ && prev_row == mouse_row
+ && prev_col == mouse_col)
+ {
+retnomove:
+ /* before moving the cursor for a left click wich is NOT in a status
+ * line, stop Visual mode */
+ if (on_status_line)
+ return IN_STATUS_LINE;
+#ifdef FEAT_VERTSPLIT
+ if (on_sep_line)
+ return IN_SEP_LINE;
+#endif
+#ifdef FEAT_VISUAL
+ if (flags & MOUSE_MAY_STOP_VIS)
+ {
+ end_visual_mode();
+ redraw_curbuf_later(INVERTED); /* delete the inversion */
+ }
+#endif
+#if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
+ /* Continue a modeless selection in another window. */
+ if (cmdwin_type != 0 && row < W_WINROW(curwin))
+ return IN_OTHER_WIN;
+#endif
+ return IN_BUFFER;
+ }
+
+ prev_row = mouse_row;
+ prev_col = mouse_col;
+
+ if (flags & MOUSE_SETPOS)
+ goto retnomove; /* ugly goto... */
+
+#ifdef FEAT_FOLDING
+ /* Remember the character under the mouse, it might be a '-' or '+' in the
+ * fold column. */
+ if (row >= 0 && row < Rows && col >= 0 && col <= Columns)
+ mouse_char = ScreenLines[LineOffset[row] + col];
+ else
+ mouse_char = ' ';
+#endif
+
+ old_curwin = curwin;
+ old_cursor = curwin->w_cursor;
+
+ if (!(flags & MOUSE_FOCUS))
+ {
+ if (row < 0 || col < 0) /* check if it makes sense */
+ return IN_UNKNOWN;
+
+#ifdef FEAT_WINDOWS
+ /* find the window where the row is in */
+ wp = mouse_find_win(&row, &col);
+#else
+ wp = firstwin;
+#endif
+ dragwin = NULL;
+ /*
+ * winpos and height may change in win_enter()!
+ */
+ if (row >= wp->w_height) /* In (or below) status line */
+ {
+ on_status_line = row - wp->w_height + 1;
+ dragwin = wp;
+ }
+ else
+ on_status_line = 0;
+#ifdef FEAT_VERTSPLIT
+ if (col >= wp->w_width) /* In separator line */
+ {
+ on_sep_line = col - wp->w_width + 1;
+ dragwin = wp;
+ }
+ else
+ on_sep_line = 0;
+
+ /* The rightmost character of the status line might be a vertical
+ * separator character if there is no connecting window to the right. */
+ if (on_status_line && on_sep_line)
+ {
+ if (stl_connected(wp))
+ on_sep_line = 0;
+ else
+ on_status_line = 0;
+ }
+#endif
+
+#ifdef FEAT_VISUAL
+ /* Before jumping to another buffer, or moving the cursor for a left
+ * click, stop Visual mode. */
+ if (VIsual_active
+ && (wp->w_buffer != curwin->w_buffer
+ || (!on_status_line
+# ifdef FEAT_VERTSPLIT
+ && !on_sep_line
+# endif
+# ifdef FEAT_FOLDING
+ && (
+# ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? col < W_WIDTH(wp) - wp->w_p_fdc :
+# endif
+ col >= wp->w_p_fdc
+# ifdef FEAT_CMDWIN
+ + (cmdwin_type == 0 && wp == curwin ? 0 : 1)
+# endif
+ )
+# endif
+ && (flags & MOUSE_MAY_STOP_VIS))))
+ {
+ end_visual_mode();
+ redraw_curbuf_later(INVERTED); /* delete the inversion */
+ }
+#endif
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0 && wp != curwin)
+ {
+ /* A click outside the command-line window: Use modeless
+ * selection if possible. Allow dragging the status line of
+ * windows just above the command-line window. */
+ if (wp->w_winrow + wp->w_height
+ != curwin->w_prev->w_winrow + curwin->w_prev->w_height)
+ {
+ on_status_line = 0;
+ dragwin = NULL;
+ }
+# ifdef FEAT_VERTSPLIT
+ on_sep_line = 0;
+# endif
+# ifdef FEAT_CLIPBOARD
+ if (on_status_line)
+ return IN_STATUS_LINE;
+ return IN_OTHER_WIN;
+# else
+ row = 0;
+ col += wp->w_wincol;
+ wp = curwin;
+# endif
+ }
+#endif
+#ifdef FEAT_WINDOWS
+ /* Only change window focus when not clicking on or dragging the
+ * status line. Do change focus when releasing the mouse button
+ * (MOUSE_FOCUS was set above if we dragged first). */
+ if (dragwin == NULL || (flags & MOUSE_RELEASED))
+ win_enter(wp, TRUE); /* can make wp invalid! */
+# ifdef CHECK_DOUBLE_CLICK
+ /* set topline, to be able to check for double click ourselves */
+ if (curwin != old_curwin)
+ set_mouse_topline(curwin);
+# endif
+#endif
+ if (on_status_line) /* In (or below) status line */
+ {
+ /* Don't use start_arrow() if we're in the same window */
+ if (curwin == old_curwin)
+ return IN_STATUS_LINE;
+ else
+ return IN_STATUS_LINE | CURSOR_MOVED;
+ }
+#ifdef FEAT_VERTSPLIT
+ if (on_sep_line) /* In (or below) status line */
+ {
+ /* Don't use start_arrow() if we're in the same window */
+ if (curwin == old_curwin)
+ return IN_SEP_LINE;
+ else
+ return IN_SEP_LINE | CURSOR_MOVED;
+ }
+#endif
+
+ curwin->w_cursor.lnum = curwin->w_topline;
+#ifdef FEAT_GUI
+ /* remember topline, needed for double click */
+ gui_prev_topline = curwin->w_topline;
+# ifdef FEAT_DIFF
+ gui_prev_topfill = curwin->w_topfill;
+# endif
+#endif
+ }
+ else if (on_status_line && which_button == MOUSE_LEFT)
+ {
+#ifdef FEAT_WINDOWS
+ if (dragwin != NULL)
+ {
+ /* Drag the status line */
+ count = row - dragwin->w_winrow - dragwin->w_height + 1
+ - on_status_line;
+ win_drag_status_line(dragwin, count);
+ did_drag |= count;
+ }
+#endif
+ return IN_STATUS_LINE; /* Cursor didn't move */
+ }
+#ifdef FEAT_VERTSPLIT
+ else if (on_sep_line && which_button == MOUSE_LEFT)
+ {
+ if (dragwin != NULL)
+ {
+ /* Drag the separator column */
+ count = col - dragwin->w_wincol - dragwin->w_width + 1
+ - on_sep_line;
+ win_drag_vsep_line(dragwin, count);
+ did_drag |= count;
+ }
+ return IN_SEP_LINE; /* Cursor didn't move */
+ }
+#endif
+ else /* keep_window_focus must be TRUE */
+ {
+#ifdef FEAT_VISUAL
+ /* before moving the cursor for a left click, stop Visual mode */
+ if (flags & MOUSE_MAY_STOP_VIS)
+ {
+ end_visual_mode();
+ redraw_curbuf_later(INVERTED); /* delete the inversion */
+ }
+#endif
+
+#if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
+ /* Continue a modeless selection in another window. */
+ if (cmdwin_type != 0 && row < W_WINROW(curwin))
+ return IN_OTHER_WIN;
+#endif
+
+ row -= W_WINROW(curwin);
+#ifdef FEAT_VERTSPLIT
+ col -= W_WINCOL(curwin);
+#endif
+
+ /*
+ * When clicking beyond the end of the window, scroll the screen.
+ * Scroll by however many rows outside the window we are.
+ */
+ if (row < 0)
+ {
+ count = 0;
+ for (first = TRUE; curwin->w_topline > 1; )
+ {
+#ifdef FEAT_DIFF
+ if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
+ ++count;
+ else
+#endif
+ count += plines(curwin->w_topline - 1);
+ if (!first && count > -row)
+ break;
+ first = FALSE;
+#ifdef FEAT_FOLDING
+ hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+#endif
+#ifdef FEAT_DIFF
+ if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
+ ++curwin->w_topfill;
+ else
+#endif
+ {
+ --curwin->w_topline;
+#ifdef FEAT_DIFF
+ curwin->w_topfill = 0;
+#endif
+ }
+ }
+#ifdef FEAT_DIFF
+ check_topfill(curwin, FALSE);
+#endif
+ curwin->w_valid &=
+ ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
+ redraw_later(VALID);
+ row = 0;
+ }
+ else if (row >= curwin->w_height)
+ {
+ count = 0;
+ for (first = TRUE; curwin->w_topline < curbuf->b_ml.ml_line_count; )
+ {
+#ifdef FEAT_DIFF
+ if (curwin->w_topfill > 0)
+ ++count;
+ else
+#endif
+ count += plines(curwin->w_topline);
+ if (!first && count > row - curwin->w_height + 1)
+ break;
+ first = FALSE;
+#ifdef FEAT_FOLDING
+ if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline)
+ && curwin->w_topline == curbuf->b_ml.ml_line_count)
+ break;
+#endif
+#ifdef FEAT_DIFF
+ if (curwin->w_topfill > 0)
+ --curwin->w_topfill;
+ else
+#endif
+ {
+ ++curwin->w_topline;
+#ifdef FEAT_DIFF
+ curwin->w_topfill =
+ diff_check_fill(curwin, curwin->w_topline);
+#endif
+ }
+ }
+#ifdef FEAT_DIFF
+ check_topfill(curwin, FALSE);
+#endif
+ redraw_later(VALID);
+ curwin->w_valid &=
+ ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
+ row = curwin->w_height - 1;
+ }
+ else if (row == 0)
+ {
+ /* When dragging the mouse, while the text has been scrolled up as
+ * far as it goes, moving the mouse in the top line should scroll
+ * the text down (done later when recomputing w_topline). */
+ if (mouse_dragging
+ && curwin->w_cursor.lnum
+ == curwin->w_buffer->b_ml.ml_line_count
+ && curwin->w_cursor.lnum == curwin->w_topline)
+ curwin->w_valid &= ~(VALID_TOPLINE);
+ }
+ }
+
+#ifdef FEAT_FOLDING
+ /* Check for position outside of the fold column. */
+ if (
+# ifdef FEAT_RIGHTLEFT
+ curwin->w_p_rl ? col < W_WIDTH(curwin) - curwin->w_p_fdc :
+# endif
+ col >= curwin->w_p_fdc
+# ifdef FEAT_CMDWIN
+ + (cmdwin_type == 0 ? 0 : 1)
+# endif
+ )
+ mouse_char = ' ';
+#endif
+
+ /* compute the position in the buffer line from the posn on the screen */
+ if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum))
+ mouse_past_bottom = TRUE;
+
+#ifdef FEAT_VISUAL
+ /* Start Visual mode before coladvance(), for when 'sel' != "old" */
+ if ((flags & MOUSE_MAY_VIS) && !VIsual_active)
+ {
+ check_visual_highlight();
+ VIsual = old_cursor;
+ VIsual_active = TRUE;
+ VIsual_reselect = TRUE;
+ /* if 'selectmode' contains "mouse", start Select mode */
+ may_start_select('o');
+ setmouse();
+ if (p_smd)
+ redraw_cmdline = TRUE; /* show visual mode later */
+ }
+#endif
+
+ curwin->w_curswant = col;
+ curwin->w_set_curswant = FALSE; /* May still have been TRUE */
+ if (coladvance(col) == FAIL) /* Mouse click beyond end of line */
+ {
+ if (inclusive != NULL)
+ *inclusive = TRUE;
+ mouse_past_eol = TRUE;
+ }
+ else if (inclusive != NULL)
+ *inclusive = FALSE;
+
+ count = IN_BUFFER;
+ if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum
+ || curwin->w_cursor.col != old_cursor.col)
+ count |= CURSOR_MOVED; /* Cursor has moved */
+
+#ifdef FEAT_FOLDING
+ if (mouse_char == '+')
+ count |= MOUSE_FOLD_OPEN;
+ else if (mouse_char != ' ')
+ count |= MOUSE_FOLD_CLOSE;
+#endif
+
+ return count;
+}
+
+/*
+ * Compute the position in the buffer line from the posn on the screen in
+ * window "win".
+ * Returns TRUE if the position is below the last line.
+ */
+ int
+mouse_comp_pos(win, rowp, colp, lnump)
+ win_T *win;
+ int *rowp;
+ int *colp;
+ linenr_T *lnump;
+{
+ int col = *colp;
+ int row = *rowp;
+ linenr_T lnum;
+ int retval = FALSE;
+ int off;
+ int count;
+
+#ifdef FEAT_RIGHTLEFT
+ if (win->w_p_rl)
+ col = W_WIDTH(win) - 1 - col;
+#endif
+
+ lnum = win->w_topline;
+
+ while (row > 0)
+ {
+#ifdef FEAT_DIFF
+ /* Don't include filler lines in "count" */
+ if (win->w_p_diff && !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL))
+ {
+ if (lnum == win->w_topline)
+ row -= win->w_topfill;
+ else
+ row -= diff_check_fill(win, lnum);
+ count = plines_win_nofill(win, lnum, TRUE);
+ }
+ else
+#endif
+ count = plines_win(win, lnum, TRUE);
+ if (count > row)
+ break; /* Position is in this buffer line. */
+#ifdef FEAT_FOLDING
+ (void)hasFoldingWin(win, lnum, NULL, &lnum, TRUE, NULL);
+#endif
+ if (lnum == win->w_buffer->b_ml.ml_line_count)
+ {
+ retval = TRUE;
+ break; /* past end of file */
+ }
+ row -= count;
+ ++lnum;
+ }
+
+ if (!retval)
+ {
+ /* Compute the column without wrapping. */
+ off = win_col_off(win) - win_col_off2(win);
+ if (col < off)
+ col = off;
+ col += row * (W_WIDTH(win) - off);
+ /* add skip column (for long wrapping line) */
+ col += win->w_skipcol;
+ }
+
+ if (!win->w_p_wrap)
+ col += win->w_leftcol;
+
+ /* skip line number and fold column in front of the line */
+ col -= win_col_off(win);
+ if (col < 0)
+ {
+#ifdef FEAT_NETBEANS_INTG
+ if (usingNetbeans)
+ netbeans_gutter_click(lnum);
+#endif
+ col = 0;
+ }
+
+ *colp = col;
+ *rowp = row;
+ *lnump = lnum;
+ return retval;
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * Find the window at screen position "*rowp" and "*colp". The positions are
+ * updated to become relative to the top-left of the window.
+ */
+/*ARGSUSED*/
+ win_T *
+mouse_find_win(rowp, colp)
+ int *rowp;
+ int *colp;
+{
+ frame_T *fp;
+
+ fp = topframe;
+ for (;;)
+ {
+ if (fp->fr_layout == FR_LEAF)
+ break;
+#ifdef FEAT_VERTSPLIT
+ if (fp->fr_layout == FR_ROW)
+ {
+ for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next)
+ {
+ if (*colp < fp->fr_width)
+ break;
+ *colp -= fp->fr_width;
+ }
+ }
+#endif
+ else /* fr_layout == FR_COL */
+ {
+ for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next)
+ {
+ if (*rowp < fp->fr_height)
+ break;
+ *rowp -= fp->fr_height;
+ }
+ }
+ }
+ return fp->fr_win;
+}
+#endif
+
+#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined (FEAT_GUI_MAC) \
+ || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
+ || defined(FEAT_GUI_PHOTON) || defined(PROTO)
+/*
+ * Translate window coordinates to buffer position without any side effects
+ */
+ int
+get_fpos_of_mouse(mpos)
+ pos_T *mpos;
+{
+ win_T *wp;
+ int row = mouse_row;
+ int col = mouse_col;
+
+ if (row < 0 || col < 0) /* check if it makes sense */
+ return IN_UNKNOWN;
+
+#ifdef FEAT_WINDOWS
+ /* find the window where the row is in */
+ wp = mouse_find_win(&row, &col);
+#else
+ wp = firstwin;
+#endif
+ /*
+ * winpos and height may change in win_enter()!
+ */
+ if (row >= wp->w_height) /* In (or below) status line */
+ return IN_STATUS_LINE;
+#ifdef FEAT_VERTSPLIT
+ if (col >= wp->w_width) /* In vertical separator line */
+ return IN_SEP_LINE;
+#endif
+
+ if (wp != curwin)
+ return IN_UNKNOWN;
+
+ /* compute the position in the buffer line from the posn on the screen */
+ if (mouse_comp_pos(curwin, &row, &col, &mpos->lnum))
+ return IN_STATUS_LINE; /* past bottom */
+
+ mpos->col = vcol2col(wp, mpos->lnum, col);
+
+ if (mpos->col > 0)
+ --mpos->col;
+ return IN_BUFFER;
+}
+
+/*
+ * Convert a virtual (screen) column to a character column.
+ * The first column is one.
+ */
+ int
+vcol2col(wp, lnum, vcol)
+ win_T *wp;
+ linenr_T lnum;
+ int vcol;
+{
+ /* try to advance to the specified column */
+ int col = 0;
+ int count = 0;
+ char_u *ptr;
+
+ ptr = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ while (count <= vcol && *ptr != NUL)
+ {
+ ++col;
+ count += win_lbr_chartabsize(wp, ptr, count, NULL);
+# ifdef FEAT_MBYTE
+ if (has_mbyte)
+ ptr += (*mb_ptr2len_check)(ptr);
+ else
+# endif
+ ++ptr;
+ }
+ return col;
+}
+#endif
+
+#endif /* FEAT_MOUSE */
+
+#if defined(FEAT_GUI) || defined(WIN3264) || defined(PROTO)
+/*
+ * Called when focus changed. Used for the GUI or for systems where this can
+ * be done in the console (Win32).
+ */
+ void
+ui_focus_change(in_focus)
+ int in_focus; /* TRUE if focus gained. */
+{
+ static time_t last_time = (time_t)0;
+ int need_redraw = FALSE;
+
+ /* When activated: Check if any file was modified outside of Vim.
+ * Only do this when not done within the last two seconds (could get
+ * several events in a row). */
+ if (in_focus && last_time + 2 < time(NULL))
+ {
+ need_redraw = check_timestamps(
+# ifdef FEAT_GUI
+ gui.in_use
+# else
+ FALSE
+# endif
+ );
+ last_time = time(NULL);
+ }
+
+#ifdef FEAT_AUTOCMD
+ /*
+ * Fire the focus gained/lost autocommand.
+ */
+ need_redraw |= apply_autocmds(in_focus ? EVENT_FOCUSGAINED
+ : EVENT_FOCUSLOST, NULL, NULL, FALSE, curbuf);
+#endif
+
+ if (need_redraw)
+ {
+ /* Something was executed, make sure the cursor is put back where it
+ * belongs. */
+ need_wait_return = FALSE;
+
+ if (State & CMDLINE)
+ redrawcmdline();
+ else if (State == HITRETURN || State == SETWSIZE || State == ASKMORE
+ || State == EXTERNCMD || State == CONFIRM || exmode_active)
+ repeat_message();
+ else if ((State & NORMAL) || (State & INSERT))
+ {
+ if (must_redraw != 0)
+ update_screen(0);
+ setcursor();
+ }
+ cursor_on(); /* redrawing may have switched it off */
+ out_flush();
+# ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ gui_update_cursor(FALSE, TRUE);
+ gui_update_scrollbars(FALSE);
+ }
+# endif
+ }
+#ifdef FEAT_TITLE
+ /* File may have been changed from 'readonly' to 'noreadonly' */
+ if (need_maketitle)
+ maketitle();
+#endif
+}
+#endif
+
+#if defined(USE_IM_CONTROL) || defined(PROTO)
+/*
+ * Save current Input Method status to specified place.
+ */
+ void
+im_save_status(psave)
+ long *psave;
+{
+ /* Don't save when 'imdisable' is set or "xic" is NULL, IM is always
+ * disabled then (but might start later).
+ * Also don't save when inside a mapping, vgetc_im_active has not been set
+ * then.
+ * And don't save when the keys were stuffed (e.g., for a "." command).
+ * And don't save when the GUI is running but our window doesn't have
+ * input focus (e.g., when a find dialog is open). */
+ if (!p_imdisable && KeyTyped && !KeyStuffed
+# ifdef FEAT_XIM
+ && xic != NULL
+# endif
+# ifdef FEAT_GUI
+ && (!gui.in_use || gui.in_focus)
+# endif
+ )
+ {
+ /* Do save when IM is on, or IM is off and saved status is on. */
+ if (vgetc_im_active)
+ *psave = B_IMODE_IM;
+ else if (*psave == B_IMODE_IM)
+ *psave = B_IMODE_NONE;
+ }
+}
+#endif
diff --git a/src/undo.c b/src/undo.c
new file mode 100644
index 000000000..6efcffab4
--- /dev/null
+++ b/src/undo.c
@@ -0,0 +1,1380 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * undo.c: multi level undo facility
+ *
+ * The saved lines are stored in a list of lists (one for each buffer):
+ *
+ * b_u_oldhead------------------------------------------------+
+ * |
+ * V
+ * +--------------+ +--------------+ +--------------+
+ * b_u_newhead--->| u_header | | u_header | | u_header |
+ * | uh_next------>| uh_next------>| uh_next---->NULL
+ * NULL<--------uh_prev |<---------uh_prev |<---------uh_prev |
+ * | uh_entry | | uh_entry | | uh_entry |
+ * +--------|-----+ +--------|-----+ +--------|-----+
+ * | | |
+ * V V V
+ * +--------------+ +--------------+ +--------------+
+ * | u_entry | | u_entry | | u_entry |
+ * | ue_next | | ue_next | | ue_next |
+ * +--------|-----+ +--------|-----+ +--------|-----+
+ * | | |
+ * V V V
+ * +--------------+ NULL NULL
+ * | u_entry |
+ * | ue_next |
+ * +--------|-----+
+ * |
+ * V
+ * etc.
+ *
+ * Each u_entry list contains the information for one undo or redo.
+ * curbuf->b_u_curhead points to the header of the last undo (the next redo),
+ * or is NULL if nothing has been undone.
+ *
+ * All data is allocated with u_alloc_line(), thus it will be freed as soon as
+ * we switch files!
+ */
+
+#include "vim.h"
+
+static u_entry_T *u_get_headentry __ARGS((void));
+static void u_getbot __ARGS((void));
+static int u_savecommon __ARGS((linenr_T, linenr_T, linenr_T));
+static void u_doit __ARGS((int count));
+static void u_undoredo __ARGS((void));
+static void u_undo_end __ARGS((void));
+static void u_freelist __ARGS((struct u_header *));
+static void u_freeentry __ARGS((u_entry_T *, long));
+
+static char_u *u_blockalloc __ARGS((long_u));
+static void u_free_line __ARGS((char_u *, int keep));
+static char_u *u_alloc_line __ARGS((unsigned));
+static char_u *u_save_line __ARGS((linenr_T));
+
+static long u_newcount, u_oldcount;
+
+/*
+ * When 'u' flag included in 'cpoptions', we behave like vi. Need to remember
+ * the action that "u" should do.
+ */
+static int undo_undoes = FALSE;
+
+/*
+ * save the current line for both the "u" and "U" command
+ */
+ int
+u_save_cursor()
+{
+ return (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
+ (linenr_T)(curwin->w_cursor.lnum + 1)));
+}
+
+/*
+ * Save the lines between "top" and "bot" for both the "u" and "U" command.
+ * "top" may be 0 and bot may be curbuf->b_ml.ml_line_count + 1.
+ * Returns FAIL when lines could not be saved, OK otherwise.
+ */
+ int
+u_save(top, bot)
+ linenr_T top, bot;
+{
+ if (undo_off)
+ return OK;
+
+ if (top > curbuf->b_ml.ml_line_count ||
+ top >= bot || bot > curbuf->b_ml.ml_line_count + 1)
+ return FALSE; /* rely on caller to do error messages */
+
+ if (top + 2 == bot)
+ u_saveline((linenr_T)(top + 1));
+
+ return (u_savecommon(top, bot, (linenr_T)0));
+}
+
+/*
+ * save the line "lnum" (used by ":s" and "~" command)
+ * The line is replaced, so the new bottom line is lnum + 1.
+ */
+ int
+u_savesub(lnum)
+ linenr_T lnum;
+{
+ if (undo_off)
+ return OK;
+
+ return (u_savecommon(lnum - 1, lnum + 1, lnum + 1));
+}
+
+/*
+ * a new line is inserted before line "lnum" (used by :s command)
+ * The line is inserted, so the new bottom line is lnum + 1.
+ */
+ int
+u_inssub(lnum)
+ linenr_T lnum;
+{
+ if (undo_off)
+ return OK;
+
+ return (u_savecommon(lnum - 1, lnum, lnum + 1));
+}
+
+/*
+ * save the lines "lnum" - "lnum" + nlines (used by delete command)
+ * The lines are deleted, so the new bottom line is lnum, unless the buffer
+ * becomes empty.
+ */
+ int
+u_savedel(lnum, nlines)
+ linenr_T lnum;
+ long nlines;
+{
+ if (undo_off)
+ return OK;
+
+ return (u_savecommon(lnum - 1, lnum + nlines,
+ nlines == curbuf->b_ml.ml_line_count ? 2 : lnum));
+}
+
+ static int
+u_savecommon(top, bot, newbot)
+ linenr_T top, bot;
+ linenr_T newbot;
+{
+ linenr_T lnum;
+ long i;
+ struct u_header *uhp;
+ u_entry_T *uep;
+ u_entry_T *prev_uep;
+ long size;
+
+ /*
+ * Don't allow changes when 'modifiable' is off. Letting the
+ * undo fail is a crude way to make all change commands fail.
+ */
+ if (!curbuf->b_p_ma)
+ {
+ EMSG(_(e_modifiable));
+ return FAIL;
+ }
+
+#ifdef HAVE_SANDBOX
+ /*
+ * In the sandbox it's not allowed to change the text. Letting the
+ * undo fail is a crude way to make all change commands fail.
+ */
+ if (sandbox != 0)
+ {
+ EMSG(_(e_sandbox));
+ return FAIL;
+ }
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+ /*
+ * Netbeans defines areas that cannot be modified. Bail out here when
+ * trying to change text in a guarded area.
+ */
+ if (usingNetbeans && netbeans_is_guarded(top, bot))
+ {
+ EMSG(_(e_guarded));
+ return FAIL;
+ }
+#endif
+
+#ifdef FEAT_AUTOCMD
+ /*
+ * Saving text for undo means we are going to make a change. Give a
+ * warning for a read-only file before making the change, so that the
+ * FileChangedRO event can replace the buffer with a read-write version
+ * (e.g., obtained from a source control system).
+ */
+ change_warning(0);
+#endif
+
+ size = bot - top - 1;
+
+ /*
+ * if curbuf->b_u_synced == TRUE make a new header
+ */
+ if (curbuf->b_u_synced)
+ {
+#ifdef FEAT_JUMPLIST
+ /* Need to create new entry in b_changelist. */
+ curbuf->b_new_change = TRUE;
+#endif
+
+ /*
+ * if we undid more than we redid, free the entry lists before and
+ * including curbuf->b_u_curhead
+ */
+ while (curbuf->b_u_curhead != NULL)
+ u_freelist(curbuf->b_u_newhead);
+
+ /*
+ * free headers to keep the size right
+ */
+ while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL)
+ u_freelist(curbuf->b_u_oldhead);
+
+ if (p_ul < 0) /* no undo at all */
+ {
+ curbuf->b_u_synced = FALSE;
+ return OK;
+ }
+
+ /*
+ * make a new header entry
+ */
+ uhp = (struct u_header *)u_alloc_line((unsigned)
+ sizeof(struct u_header));
+ if (uhp == NULL)
+ goto nomem;
+ uhp->uh_prev = NULL;
+ uhp->uh_next = curbuf->b_u_newhead;
+ if (curbuf->b_u_newhead != NULL)
+ curbuf->b_u_newhead->uh_prev = uhp;
+ uhp->uh_entry = NULL;
+ uhp->uh_getbot_entry = NULL;
+ uhp->uh_cursor = curwin->w_cursor; /* save cursor pos. for undo */
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_active() && curwin->w_cursor.coladd > 0)
+ uhp->uh_cursor_vcol = getviscol();
+ else
+ uhp->uh_cursor_vcol = -1;
+#endif
+
+ /* save changed and buffer empty flag for undo */
+ uhp->uh_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
+ ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
+
+ /* save named marks for undo */
+ mch_memmove(uhp->uh_namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS);
+ curbuf->b_u_newhead = uhp;
+ if (curbuf->b_u_oldhead == NULL)
+ curbuf->b_u_oldhead = uhp;
+ ++curbuf->b_u_numhead;
+ }
+ else
+ {
+ if (p_ul < 0) /* no undo at all */
+ return OK;
+
+ /*
+ * When saving a single line, and it has been saved just before, it
+ * doesn't make sense saving it again. Saves a lot of memory when
+ * making lots of changes inside the same line.
+ * This is only possible if the previous change didn't increase or
+ * decrease the number of lines.
+ * Check the ten last changes. More doesn't make sense and takes too
+ * long.
+ */
+ if (size == 1)
+ {
+ uep = u_get_headentry();
+ prev_uep = NULL;
+ for (i = 0; i < 10; ++i)
+ {
+ if (uep == NULL)
+ break;
+
+ /* If lines have been inserted/deleted we give up.
+ * Also when the line was included in a multi-line save. */
+ if ((curbuf->b_u_newhead->uh_getbot_entry != uep
+ ? (uep->ue_top + uep->ue_size + 1
+ != (uep->ue_bot == 0
+ ? curbuf->b_ml.ml_line_count + 1
+ : uep->ue_bot))
+ : uep->ue_lcount != curbuf->b_ml.ml_line_count)
+ || (uep->ue_size > 1
+ && top >= uep->ue_top
+ && top + 2 <= uep->ue_top + uep->ue_size + 1))
+ break;
+
+ /* If it's the same line we can skip saving it again. */
+ if (uep->ue_size == 1 && uep->ue_top == top)
+ {
+ if (i > 0)
+ {
+ /* It's not the last entry: get ue_bot for the last
+ * entry now. Following deleted/inserted lines go to
+ * the re-used entry. */
+ u_getbot();
+ curbuf->b_u_synced = FALSE;
+
+ /* Move the found entry to become the last entry. The
+ * order of undo/redo doesn't matter for the entries
+ * we move it over, since they don't change the line
+ * count and don't include this line. It does matter
+ * for the found entry if the line count is changed by
+ * the executed command. */
+ prev_uep->ue_next = uep->ue_next;
+ uep->ue_next = curbuf->b_u_newhead->uh_entry;
+ curbuf->b_u_newhead->uh_entry = uep;
+ }
+
+ /* The executed command may change the line count. */
+ if (newbot != 0)
+ uep->ue_bot = newbot;
+ else if (bot > curbuf->b_ml.ml_line_count)
+ uep->ue_bot = 0;
+ else
+ {
+ uep->ue_lcount = curbuf->b_ml.ml_line_count;
+ curbuf->b_u_newhead->uh_getbot_entry = uep;
+ }
+ return OK;
+ }
+ prev_uep = uep;
+ uep = uep->ue_next;
+ }
+ }
+
+ /* find line number for ue_bot for previous u_save() */
+ u_getbot();
+ }
+
+#if !defined(UNIX) && !defined(DJGPP) && !defined(WIN32) && !defined(__EMX__)
+ /*
+ * With Amiga and MSDOS 16 bit we can't handle big undo's, because
+ * then u_alloc_line would have to allocate a block larger than 32K
+ */
+ if (size >= 8000)
+ goto nomem;
+#endif
+
+ /*
+ * add lines in front of entry list
+ */
+ uep = (u_entry_T *)u_alloc_line((unsigned)sizeof(u_entry_T));
+ if (uep == NULL)
+ goto nomem;
+
+ uep->ue_size = size;
+ uep->ue_top = top;
+ if (newbot != 0)
+ uep->ue_bot = newbot;
+ /*
+ * Use 0 for ue_bot if bot is below last line.
+ * Otherwise we have to compute ue_bot later.
+ */
+ else if (bot > curbuf->b_ml.ml_line_count)
+ uep->ue_bot = 0;
+ else
+ {
+ uep->ue_lcount = curbuf->b_ml.ml_line_count;
+ curbuf->b_u_newhead->uh_getbot_entry = uep;
+ }
+
+ if (size)
+ {
+ if ((uep->ue_array = (char_u **)u_alloc_line(
+ (unsigned)(sizeof(char_u *) * size))) == NULL)
+ {
+ u_freeentry(uep, 0L);
+ goto nomem;
+ }
+ for (i = 0, lnum = top + 1; i < size; ++i)
+ {
+ if ((uep->ue_array[i] = u_save_line(lnum++)) == NULL)
+ {
+ u_freeentry(uep, i);
+ goto nomem;
+ }
+ }
+ }
+ uep->ue_next = curbuf->b_u_newhead->uh_entry;
+ curbuf->b_u_newhead->uh_entry = uep;
+ curbuf->b_u_synced = FALSE;
+ undo_undoes = FALSE;
+
+ return OK;
+
+nomem:
+ msg_silent = 0; /* must display the prompt */
+ if (ask_yesno((char_u *)_("No undo possible; continue anyway"), TRUE)
+ == 'y')
+ {
+ undo_off = TRUE; /* will be reset when character typed */
+ return OK;
+ }
+ do_outofmem_msg((long_u)0);
+ return FAIL;
+}
+
+/*
+ * If 'cpoptions' contains 'u': Undo the previous undo or redo (vi compatible).
+ * If 'cpoptions' does not contain 'u': Always undo.
+ */
+ void
+u_undo(count)
+ int count;
+{
+ /*
+ * If we get an undo command while executing a macro, we behave like the
+ * original vi. If this happens twice in one macro the result will not
+ * be compatible.
+ */
+ if (curbuf->b_u_synced == FALSE)
+ {
+ u_sync();
+ count = 1;
+ }
+
+ if (vim_strchr(p_cpo, CPO_UNDO) == NULL)
+ undo_undoes = TRUE;
+ else
+ undo_undoes = !undo_undoes;
+ u_doit(count);
+}
+
+/*
+ * If 'cpoptions' contains 'u': Repeat the previous undo or redo.
+ * If 'cpoptions' does not contain 'u': Always redo.
+ */
+ void
+u_redo(count)
+ int count;
+{
+ if (vim_strchr(p_cpo, CPO_UNDO) == NULL)
+ undo_undoes = FALSE;
+ u_doit(count);
+}
+
+/*
+ * Undo or redo, depending on 'undo_undoes', 'count' times.
+ */
+ static void
+u_doit(count)
+ int count;
+{
+ /* Don't allow changes when 'modifiable' is off. */
+ if (!curbuf->b_p_ma)
+ {
+ EMSG(_(e_modifiable));
+ return;
+ }
+#ifdef HAVE_SANDBOX
+ /* In the sandbox it's not allowed to change the text. */
+ if (sandbox != 0)
+ {
+ EMSG(_(e_sandbox));
+ return;
+ }
+#endif
+
+ u_newcount = 0;
+ u_oldcount = 0;
+ while (count--)
+ {
+ if (undo_undoes)
+ {
+ if (curbuf->b_u_curhead == NULL) /* first undo */
+ curbuf->b_u_curhead = curbuf->b_u_newhead;
+ else if (p_ul > 0) /* multi level undo */
+ /* get next undo */
+ curbuf->b_u_curhead = curbuf->b_u_curhead->uh_next;
+ /* nothing to undo */
+ if (curbuf->b_u_numhead == 0 || curbuf->b_u_curhead == NULL)
+ {
+ /* stick curbuf->b_u_curhead at end */
+ curbuf->b_u_curhead = curbuf->b_u_oldhead;
+ beep_flush();
+ break;
+ }
+
+ u_undoredo();
+ }
+ else
+ {
+ if (curbuf->b_u_curhead == NULL || p_ul <= 0)
+ {
+ beep_flush(); /* nothing to redo */
+ break;
+ }
+
+ u_undoredo();
+ /* advance for next redo */
+ curbuf->b_u_curhead = curbuf->b_u_curhead->uh_prev;
+ }
+ }
+ u_undo_end();
+}
+
+/*
+ * u_undoredo: common code for undo and redo
+ *
+ * The lines in the file are replaced by the lines in the entry list at
+ * curbuf->b_u_curhead. The replaced lines in the file are saved in the entry
+ * list for the next undo/redo.
+ */
+ static void
+u_undoredo()
+{
+ char_u **newarray = NULL;
+ linenr_T oldsize;
+ linenr_T newsize;
+ linenr_T top, bot;
+ linenr_T lnum;
+ linenr_T newlnum = MAXLNUM;
+ long i;
+ u_entry_T *uep, *nuep;
+ u_entry_T *newlist = NULL;
+ int old_flags;
+ int new_flags;
+ pos_T namedm[NMARKS];
+ int empty_buffer; /* buffer became empty */
+
+ old_flags = curbuf->b_u_curhead->uh_flags;
+ new_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
+ ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
+ setpcmark();
+
+ /*
+ * save marks before undo/redo
+ */
+ mch_memmove(namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS);
+ curbuf->b_op_start.lnum = curbuf->b_ml.ml_line_count;
+ curbuf->b_op_start.col = 0;
+ curbuf->b_op_end.lnum = 0;
+ curbuf->b_op_end.col = 0;
+
+ for (uep = curbuf->b_u_curhead->uh_entry; uep != NULL; uep = nuep)
+ {
+ top = uep->ue_top;
+ bot = uep->ue_bot;
+ if (bot == 0)
+ bot = curbuf->b_ml.ml_line_count + 1;
+ if (top > curbuf->b_ml.ml_line_count || top >= bot
+ || bot > curbuf->b_ml.ml_line_count + 1)
+ {
+ EMSG(_("E438: u_undo: line numbers wrong"));
+ changed(); /* don't want UNCHANGED now */
+ return;
+ }
+
+ oldsize = bot - top - 1; /* number of lines before undo */
+ newsize = uep->ue_size; /* number of lines after undo */
+
+ if (top < newlnum)
+ {
+ /* If the saved cursor is somewhere in this undo block, move it to
+ * the remembered position. Makes "gwap" put the cursor back
+ * where it was. */
+ lnum = curbuf->b_u_curhead->uh_cursor.lnum;
+ if (lnum >= top && lnum <= top + newsize + 1)
+ {
+ curwin->w_cursor = curbuf->b_u_curhead->uh_cursor;
+ newlnum = curwin->w_cursor.lnum - 1;
+ }
+ else
+ {
+ /* Use the first line that actually changed. Avoids that
+ * undoing auto-formatting puts the cursor in the previous
+ * line. */
+ for (i = 0; i < newsize && i < oldsize; ++i)
+ if (STRCMP(uep->ue_array[i], ml_get(top + 1 + i)) != 0)
+ break;
+ if (i == newsize && newlnum == MAXLNUM && uep->ue_next == NULL)
+ {
+ newlnum = top;
+ curwin->w_cursor.lnum = newlnum + 1;
+ }
+ else if (i < newsize)
+ {
+ newlnum = top + i;
+ curwin->w_cursor.lnum = newlnum + 1;
+ }
+ }
+ }
+
+ empty_buffer = FALSE;
+
+ /* delete the lines between top and bot and save them in newarray */
+ if (oldsize)
+ {
+ if ((newarray = (char_u **)u_alloc_line(
+ (unsigned)(sizeof(char_u *) * oldsize))) == NULL)
+ {
+ do_outofmem_msg((long_u)(sizeof(char_u *) * oldsize));
+ /*
+ * We have messed up the entry list, repair is impossible.
+ * we have to free the rest of the list.
+ */
+ while (uep != NULL)
+ {
+ nuep = uep->ue_next;
+ u_freeentry(uep, uep->ue_size);
+ uep = nuep;
+ }
+ break;
+ }
+ /* delete backwards, it goes faster in most cases */
+ for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum)
+ {
+ /* what can we do when we run out of memory? */
+ if ((newarray[i] = u_save_line(lnum)) == NULL)
+ do_outofmem_msg((long_u)0);
+ /* remember we deleted the last line in the buffer, and a
+ * dummy empty line will be inserted */
+ if (curbuf->b_ml.ml_line_count == 1)
+ empty_buffer = TRUE;
+ ml_delete(lnum, FALSE);
+ }
+ }
+
+ /* insert the lines in u_array between top and bot */
+ if (newsize)
+ {
+ for (lnum = top, i = 0; i < newsize; ++i, ++lnum)
+ {
+ /*
+ * If the file is empty, there is an empty line 1 that we
+ * should get rid of, by replacing it with the new line
+ */
+ if (empty_buffer && lnum == 0)
+ ml_replace((linenr_T)1, uep->ue_array[i], TRUE);
+ else
+ ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE);
+ u_free_line(uep->ue_array[i], FALSE);
+ }
+ u_free_line((char_u *)uep->ue_array, FALSE);
+ }
+
+ /* adjust marks */
+ if (oldsize != newsize)
+ {
+ mark_adjust(top + 1, top + oldsize, (long)MAXLNUM,
+ (long)newsize - (long)oldsize);
+ if (curbuf->b_op_start.lnum > top + oldsize)
+ curbuf->b_op_start.lnum += newsize - oldsize;
+ if (curbuf->b_op_end.lnum > top + oldsize)
+ curbuf->b_op_end.lnum += newsize - oldsize;
+ }
+
+ changed_lines(top + 1, 0, bot, newsize - oldsize);
+
+ /* set '[ and '] mark */
+ if (top + 1 < curbuf->b_op_start.lnum)
+ curbuf->b_op_start.lnum = top + 1;
+ if (newsize == 0 && top + 1 > curbuf->b_op_end.lnum)
+ curbuf->b_op_end.lnum = top + 1;
+ else if (top + newsize > curbuf->b_op_end.lnum)
+ curbuf->b_op_end.lnum = top + newsize;
+
+ u_newcount += newsize;
+ u_oldcount += oldsize;
+ uep->ue_size = oldsize;
+ uep->ue_array = newarray;
+ uep->ue_bot = top + newsize + 1;
+
+ /*
+ * insert this entry in front of the new entry list
+ */
+ nuep = uep->ue_next;
+ uep->ue_next = newlist;
+ newlist = uep;
+ }
+
+ curbuf->b_u_curhead->uh_entry = newlist;
+ curbuf->b_u_curhead->uh_flags = new_flags;
+ if ((old_flags & UH_EMPTYBUF) && bufempty())
+ curbuf->b_ml.ml_flags |= ML_EMPTY;
+ if (old_flags & UH_CHANGED)
+ changed();
+ else
+ unchanged(curbuf, FALSE);
+
+ /*
+ * restore marks from before undo/redo
+ */
+ for (i = 0; i < NMARKS; ++i)
+ if (curbuf->b_u_curhead->uh_namedm[i].lnum)
+ {
+ curbuf->b_namedm[i] = curbuf->b_u_curhead->uh_namedm[i];
+ curbuf->b_u_curhead->uh_namedm[i] = namedm[i];
+ }
+
+ /*
+ * If the cursor is only off by one line, put it at the same position as
+ * before starting the change (for the "o" command).
+ * Otherwise the cursor should go to the first undone line.
+ */
+ if (curbuf->b_u_curhead->uh_cursor.lnum + 1 == curwin->w_cursor.lnum
+ && curwin->w_cursor.lnum > 1)
+ --curwin->w_cursor.lnum;
+ if (curbuf->b_u_curhead->uh_cursor.lnum == curwin->w_cursor.lnum)
+ {
+ curwin->w_cursor.col = curbuf->b_u_curhead->uh_cursor.col;
+#ifdef FEAT_VIRTUALEDIT
+ if (virtual_active() && curbuf->b_u_curhead->uh_cursor_vcol >= 0)
+ coladvance((colnr_T)curbuf->b_u_curhead->uh_cursor_vcol);
+ else
+ curwin->w_cursor.coladd = 0;
+#endif
+ }
+ else if (curwin->w_cursor.lnum <= curbuf->b_ml.ml_line_count)
+ beginline(BL_SOL | BL_FIX);
+ else
+ {
+ /* We get here with the current cursor line being past the end (eg
+ * after adding lines at the end of the file, and then undoing it).
+ * check_cursor() will move the cursor to the last line. Move it to
+ * the first column here. */
+ curwin->w_cursor.col = 0;
+#ifdef FEAT_VIRTUALEDIT
+ curwin->w_cursor.coladd = 0;
+#endif
+ }
+
+ /* Make sure the cursor is on an existing line and column. */
+ check_cursor();
+}
+
+/*
+ * If we deleted or added lines, report the number of less/more lines.
+ * Otherwise, report the number of changes (this may be incorrect
+ * in some cases, but it's better than nothing).
+ */
+ static void
+u_undo_end()
+{
+ if ((u_oldcount -= u_newcount) != 0)
+ msgmore(-u_oldcount);
+ else if (u_newcount > p_report)
+ {
+ if (u_newcount == 1)
+ MSG(_("1 change"));
+ else
+ smsg((char_u *)_("%ld changes"), u_newcount);
+ }
+#ifdef FEAT_FOLDING
+ if ((fdo_flags & FDO_UNDO) && KeyTyped)
+ foldOpenCursor();
+#endif
+}
+
+/*
+ * u_sync: stop adding to the current entry list
+ */
+ void
+u_sync()
+{
+ if (curbuf->b_u_synced)
+ return; /* already synced */
+#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+ if (im_is_preediting())
+ return; /* XIM is busy, don't break an undo sequence */
+#endif
+ if (p_ul < 0)
+ curbuf->b_u_synced = TRUE; /* no entries, nothing to do */
+ else
+ {
+ u_getbot(); /* compute ue_bot of previous u_save */
+ curbuf->b_u_curhead = NULL;
+ }
+}
+
+/*
+ * Called after writing the file and setting b_changed to FALSE.
+ * Now an undo means that the buffer is modified.
+ */
+ void
+u_unchanged(buf)
+ buf_T *buf;
+{
+ struct u_header *uh;
+
+ for (uh = buf->b_u_newhead; uh; uh = uh->uh_next)
+ uh->uh_flags |= UH_CHANGED;
+ buf->b_did_warn = FALSE;
+}
+
+/*
+ * Get pointer to last added entry.
+ * If it's not valid, give an error message and return NULL.
+ */
+ static u_entry_T *
+u_get_headentry()
+{
+ if (curbuf->b_u_newhead == NULL || curbuf->b_u_newhead->uh_entry == NULL)
+ {
+ EMSG(_("E439: undo list corrupt"));
+ return NULL;
+ }
+ return curbuf->b_u_newhead->uh_entry;
+}
+
+/*
+ * u_getbot(): compute the line number of the previous u_save
+ * It is called only when b_u_synced is FALSE.
+ */
+ static void
+u_getbot()
+{
+ u_entry_T *uep;
+ linenr_T extra;
+
+ uep = u_get_headentry(); /* check for corrupt undo list */
+ if (uep == NULL)
+ return;
+
+ uep = curbuf->b_u_newhead->uh_getbot_entry;
+ if (uep != NULL)
+ {
+ /*
+ * the new ue_bot is computed from the number of lines that has been
+ * inserted (0 - deleted) since calling u_save. This is equal to the
+ * old line count subtracted from the current line count.
+ */
+ extra = curbuf->b_ml.ml_line_count - uep->ue_lcount;
+ uep->ue_bot = uep->ue_top + uep->ue_size + 1 + extra;
+ if (uep->ue_bot < 1 || uep->ue_bot > curbuf->b_ml.ml_line_count)
+ {
+ EMSG(_("E440: undo line missing"));
+ uep->ue_bot = uep->ue_top + 1; /* assume all lines deleted, will
+ * get all the old lines back
+ * without deleting the current
+ * ones */
+ }
+
+ curbuf->b_u_newhead->uh_getbot_entry = NULL;
+ }
+
+ curbuf->b_u_synced = TRUE;
+}
+
+/*
+ * u_freelist: free one entry list and adjust the pointers
+ */
+ static void
+u_freelist(uhp)
+ struct u_header *uhp;
+{
+ u_entry_T *uep, *nuep;
+
+ for (uep = uhp->uh_entry; uep != NULL; uep = nuep)
+ {
+ nuep = uep->ue_next;
+ u_freeentry(uep, uep->ue_size);
+ }
+
+ if (curbuf->b_u_curhead == uhp)
+ curbuf->b_u_curhead = NULL;
+
+ if (uhp->uh_next == NULL)
+ curbuf->b_u_oldhead = uhp->uh_prev;
+ else
+ uhp->uh_next->uh_prev = uhp->uh_prev;
+
+ if (uhp->uh_prev == NULL)
+ curbuf->b_u_newhead = uhp->uh_next;
+ else
+ uhp->uh_prev->uh_next = uhp->uh_next;
+
+ u_free_line((char_u *)uhp, FALSE);
+ --curbuf->b_u_numhead;
+}
+
+/*
+ * free entry 'uep' and 'n' lines in uep->ue_array[]
+ */
+ static void
+u_freeentry(uep, n)
+ u_entry_T *uep;
+ long n;
+{
+ while (n)
+ u_free_line(uep->ue_array[--n], FALSE);
+ u_free_line((char_u *)uep, FALSE);
+}
+
+/*
+ * invalidate the undo buffer; called when storage has already been released
+ */
+ void
+u_clearall(buf)
+ buf_T *buf;
+{
+ buf->b_u_newhead = buf->b_u_oldhead = buf->b_u_curhead = NULL;
+ buf->b_u_synced = TRUE;
+ buf->b_u_numhead = 0;
+ buf->b_u_line_ptr = NULL;
+ buf->b_u_line_lnum = 0;
+}
+
+/*
+ * save the line "lnum" for the "U" command
+ */
+ void
+u_saveline(lnum)
+ linenr_T lnum;
+{
+ if (lnum == curbuf->b_u_line_lnum) /* line is already saved */
+ return;
+ if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) /* should never happen */
+ return;
+ u_clearline();
+ curbuf->b_u_line_lnum = lnum;
+ if (curwin->w_cursor.lnum == lnum)
+ curbuf->b_u_line_colnr = curwin->w_cursor.col;
+ else
+ curbuf->b_u_line_colnr = 0;
+ if ((curbuf->b_u_line_ptr = u_save_line(lnum)) == NULL)
+ do_outofmem_msg((long_u)0);
+}
+
+/*
+ * clear the line saved for the "U" command
+ * (this is used externally for crossing a line while in insert mode)
+ */
+ void
+u_clearline()
+{
+ if (curbuf->b_u_line_ptr != NULL)
+ {
+ u_free_line(curbuf->b_u_line_ptr, FALSE);
+ curbuf->b_u_line_ptr = NULL;
+ curbuf->b_u_line_lnum = 0;
+ }
+}
+
+/*
+ * Implementation of the "U" command.
+ * Differentiation from vi: "U" can be undone with the next "U".
+ * We also allow the cursor to be in another line.
+ */
+ void
+u_undoline()
+{
+ colnr_T t;
+ char_u *oldp;
+
+ if (undo_off)
+ return;
+
+ if (curbuf->b_u_line_ptr == NULL ||
+ curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count)
+ {
+ beep_flush();
+ return;
+ }
+ /* first save the line for the 'u' command */
+ if (u_savecommon(curbuf->b_u_line_lnum - 1,
+ curbuf->b_u_line_lnum + 1, (linenr_T)0) == FAIL)
+ return;
+ oldp = u_save_line(curbuf->b_u_line_lnum);
+ if (oldp == NULL)
+ {
+ do_outofmem_msg((long_u)0);
+ return;
+ }
+ ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, TRUE);
+ changed_bytes(curbuf->b_u_line_lnum, 0);
+ u_free_line(curbuf->b_u_line_ptr, FALSE);
+ curbuf->b_u_line_ptr = oldp;
+
+ t = curbuf->b_u_line_colnr;
+ if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum)
+ curbuf->b_u_line_colnr = curwin->w_cursor.col;
+ curwin->w_cursor.col = t;
+ curwin->w_cursor.lnum = curbuf->b_u_line_lnum;
+}
+
+/*
+ * storage allocation for the undo lines and blocks of the current file
+ */
+
+/*
+ * Memory is allocated in relatively large blocks. These blocks are linked
+ * in the allocated block list, headed by curbuf->b_block_head. They are all
+ * freed when abandoning a file, so we don't have to free every single line.
+ * The list is kept sorted on memory address.
+ * block_alloc() allocates a block.
+ * m_blockfree() frees all blocks.
+ *
+ * The available chunks of memory are kept in free chunk lists. There is
+ * one free list for each block of allocated memory. The list is kept sorted
+ * on memory address.
+ * u_alloc_line() gets a chunk from the free lists.
+ * u_free_line() returns a chunk to the free lists.
+ * curbuf->b_m_search points to the chunk before the chunk that was
+ * freed/allocated the last time.
+ * curbuf->b_mb_current points to the b_head where curbuf->b_m_search
+ * points into the free list.
+ *
+ *
+ * b_block_head /---> block #1 /---> block #2
+ * mb_next ---/ mb_next ---/ mb_next ---> NULL
+ * mb_info mb_info mb_info
+ * | | |
+ * V V V
+ * NULL free chunk #1.1 free chunk #2.1
+ * | |
+ * V V
+ * free chunk #1.2 NULL
+ * |
+ * V
+ * NULL
+ *
+ * When a single free chunk list would have been used, it could take a lot
+ * of time in u_free_line() to find the correct place to insert a chunk in the
+ * free list. The single free list would become very long when many lines are
+ * changed (e.g. with :%s/^M$//).
+ */
+
+ /*
+ * this blocksize is used when allocating new lines
+ */
+#define MEMBLOCKSIZE 2044
+
+/*
+ * The size field contains the size of the chunk, including the size field
+ * itself.
+ *
+ * When the chunk is not in-use it is preceded with the m_info structure.
+ * The m_next field links it in one of the free chunk lists.
+ *
+ * On most unix systems structures have to be longword (32 or 64 bit) aligned.
+ * On most other systems they are short (16 bit) aligned.
+ */
+
+/* the structure definitions are now in structs.h */
+
+#ifdef ALIGN_LONG
+ /* size of m_size */
+# define M_OFFSET (sizeof(long_u))
+#else
+ /* size of m_size */
+# define M_OFFSET (sizeof(short_u))
+#endif
+
+/*
+ * Allocate a block of memory and link it in the allocated block list.
+ */
+ static char_u *
+u_blockalloc(size)
+ long_u size;
+{
+ mblock_T *p;
+ mblock_T *mp, *next;
+
+ p = (mblock_T *)lalloc(size + sizeof(mblock_T), FALSE);
+ if (p != NULL)
+ {
+ /* Insert the block into the allocated block list, keeping it
+ sorted on address. */
+ for (mp = &curbuf->b_block_head;
+ (next = mp->mb_next) != NULL && next < p;
+ mp = next)
+ ;
+ p->mb_next = next; /* link in block list */
+ p->mb_size = size;
+ mp->mb_next = p;
+ p->mb_info.m_next = NULL; /* clear free list */
+ p->mb_info.m_size = 0;
+ curbuf->b_mb_current = p; /* remember current block */
+ curbuf->b_m_search = NULL;
+ p++; /* return usable memory */
+ }
+ return (char_u *)p;
+}
+
+/*
+ * free all allocated memory blocks for the buffer 'buf'
+ */
+ void
+u_blockfree(buf)
+ buf_T *buf;
+{
+ mblock_T *p, *np;
+
+ for (p = buf->b_block_head.mb_next; p != NULL; p = np)
+ {
+ np = p->mb_next;
+ vim_free(p);
+ }
+ buf->b_block_head.mb_next = NULL;
+ buf->b_m_search = NULL;
+ buf->b_mb_current = NULL;
+}
+
+/*
+ * Free a chunk of memory for the current buffer.
+ * Insert the chunk into the correct free list, keeping it sorted on address.
+ */
+ static void
+u_free_line(ptr, keep)
+ char_u *ptr;
+ int keep; /* don't free the block when it's empty */
+{
+ minfo_T *next;
+ minfo_T *prev, *curr;
+ minfo_T *mp;
+ mblock_T *nextb;
+ mblock_T *prevb;
+
+ if (ptr == NULL || ptr == IObuff)
+ return; /* illegal address can happen in out-of-memory situations */
+
+ mp = (minfo_T *)(ptr - M_OFFSET);
+
+ /* find block where chunk could be a part off */
+ /* if we change curbuf->b_mb_current, curbuf->b_m_search is set to NULL */
+ if (curbuf->b_mb_current == NULL || mp < (minfo_T *)curbuf->b_mb_current)
+ {
+ curbuf->b_mb_current = curbuf->b_block_head.mb_next;
+ curbuf->b_m_search = NULL;
+ }
+ if ((nextb = curbuf->b_mb_current->mb_next) != NULL
+ && (minfo_T *)nextb < mp)
+ {
+ curbuf->b_mb_current = nextb;
+ curbuf->b_m_search = NULL;
+ }
+ while ((nextb = curbuf->b_mb_current->mb_next) != NULL
+ && (minfo_T *)nextb < mp)
+ curbuf->b_mb_current = nextb;
+
+ curr = NULL;
+ /*
+ * If mp is smaller than curbuf->b_m_search->m_next go to the start of
+ * the free list
+ */
+ if (curbuf->b_m_search == NULL || mp < (curbuf->b_m_search->m_next))
+ next = &(curbuf->b_mb_current->mb_info);
+ else
+ next = curbuf->b_m_search;
+ /*
+ * The following loop is executed very often.
+ * Therefore it has been optimized at the cost of readability.
+ * Keep it fast!
+ */
+#ifdef SLOW_BUT_EASY_TO_READ
+ do
+ {
+ prev = curr;
+ curr = next;
+ next = next->m_next;
+ }
+ while (mp > next && next != NULL);
+#else
+ do /* first, middle, last */
+ {
+ prev = next->m_next; /* curr, next, prev */
+ if (prev == NULL || mp <= prev)
+ {
+ prev = curr;
+ curr = next;
+ next = next->m_next;
+ break;
+ }
+ curr = prev->m_next; /* next, prev, curr */
+ if (curr == NULL || mp <= curr)
+ {
+ prev = next;
+ curr = prev->m_next;
+ next = curr->m_next;
+ break;
+ }
+ next = curr->m_next; /* prev, curr, next */
+ }
+ while (mp > next && next != NULL);
+#endif
+
+ /* if *mp and *next are concatenated, join them into one chunk */
+ if ((char_u *)mp + mp->m_size == (char_u *)next)
+ {
+ mp->m_size += next->m_size;
+ mp->m_next = next->m_next;
+ }
+ else
+ mp->m_next = next;
+
+ /* if *curr and *mp are concatenated, join them */
+ if (prev != NULL && (char_u *)curr + curr->m_size == (char_u *)mp)
+ {
+ curr->m_size += mp->m_size;
+ curr->m_next = mp->m_next;
+ curbuf->b_m_search = prev;
+ }
+ else
+ {
+ curr->m_next = mp;
+ curbuf->b_m_search = curr; /* put curbuf->b_m_search before freed
+ chunk */
+ }
+
+ /*
+ * If the block only containes free memory now, release it.
+ */
+ if (!keep && curbuf->b_mb_current->mb_size
+ == curbuf->b_mb_current->mb_info.m_next->m_size)
+ {
+ /* Find the block before the current one to be able to unlink it from
+ * the list of blocks. */
+ prevb = &curbuf->b_block_head;
+ for (nextb = prevb->mb_next; nextb != curbuf->b_mb_current;
+ nextb = nextb->mb_next)
+ prevb = nextb;
+ prevb->mb_next = nextb->mb_next;
+ vim_free(nextb);
+ curbuf->b_mb_current = NULL;
+ curbuf->b_m_search = NULL;
+ }
+}
+
+/*
+ * Allocate and initialize a new line structure with room for at least
+ * 'size' characters plus a terminating NUL.
+ */
+ static char_u *
+u_alloc_line(size)
+ unsigned size;
+{
+ minfo_T *mp, *mprev, *mp2;
+ mblock_T *mbp;
+ int size_align;
+
+ /*
+ * Add room for size field and trailing NUL byte.
+ * Adjust for minimal size (must be able to store minfo_T
+ * plus a trailing NUL, so the chunk can be released again)
+ */
+ size += M_OFFSET + 1;
+ if (size < sizeof(minfo_T) + 1)
+ size = sizeof(minfo_T) + 1;
+
+ /*
+ * round size up for alignment
+ */
+ size_align = (size + ALIGN_MASK) & ~ALIGN_MASK;
+
+ /*
+ * If curbuf->b_m_search is NULL (uninitialized free list) start at
+ * curbuf->b_block_head
+ */
+ if (curbuf->b_mb_current == NULL || curbuf->b_m_search == NULL)
+ {
+ curbuf->b_mb_current = &curbuf->b_block_head;
+ curbuf->b_m_search = &(curbuf->b_block_head.mb_info);
+ }
+
+ /* search for space in free list */
+ mprev = curbuf->b_m_search;
+ mbp = curbuf->b_mb_current;
+ mp = curbuf->b_m_search->m_next;
+ if (mp == NULL)
+ {
+ if (mbp->mb_next)
+ mbp = mbp->mb_next;
+ else
+ mbp = &curbuf->b_block_head;
+ mp = curbuf->b_m_search = &(mbp->mb_info);
+ }
+ while (mp->m_size < size)
+ {
+ if (mp == curbuf->b_m_search) /* back where we started in free
+ chunk list */
+ {
+ if (mbp->mb_next)
+ mbp = mbp->mb_next;
+ else
+ mbp = &curbuf->b_block_head;
+ mp = curbuf->b_m_search = &(mbp->mb_info);
+ if (mbp == curbuf->b_mb_current) /* back where we started in
+ block list */
+ {
+ int n = (size_align > (MEMBLOCKSIZE / 4)
+ ? size_align : MEMBLOCKSIZE);
+
+ mp = (minfo_T *)u_blockalloc((long_u)n);
+ if (mp == NULL)
+ return (NULL);
+ mp->m_size = n;
+ u_free_line((char_u *)mp + M_OFFSET, TRUE);
+ mp = curbuf->b_m_search;
+ mbp = curbuf->b_mb_current;
+ }
+ }
+ mprev = mp;
+ if ((mp = mp->m_next) == NULL) /* at end of the list */
+ mp = &(mbp->mb_info); /* wrap around to begin */
+ }
+
+ /* if the chunk we found is large enough, split it up in two */
+ if ((long)mp->m_size - size_align >= (long)(sizeof(minfo_T) + 1))
+ {
+ mp2 = (minfo_T *)((char_u *)mp + size_align);
+ mp2->m_size = mp->m_size - size_align;
+ mp2->m_next = mp->m_next;
+ mprev->m_next = mp2;
+ mp->m_size = size_align;
+ }
+ else /* remove *mp from the free list */
+ {
+ mprev->m_next = mp->m_next;
+ }
+ curbuf->b_m_search = mprev;
+ curbuf->b_mb_current = mbp;
+
+ mp = (minfo_T *)((char_u *)mp + M_OFFSET);
+ *(char_u *)mp = NUL; /* set the first byte to NUL */
+
+ return ((char_u *)mp);
+}
+
+/*
+ * u_save_line(): allocate memory with u_alloc_line() and copy line 'lnum'
+ * into it.
+ */
+ static char_u *
+u_save_line(lnum)
+ linenr_T lnum;
+{
+ char_u *src;
+ char_u *dst;
+ unsigned len;
+
+ src = ml_get(lnum);
+ len = (unsigned)STRLEN(src);
+ if ((dst = u_alloc_line(len)) != NULL)
+ mch_memmove(dst, src, (size_t)(len + 1));
+ return (dst);
+}
+
+/*
+ * Check if the 'modified' flag is set, or 'ff' has changed (only need to
+ * check the first character, because it can only be "dos", "unix" or "mac").
+ * "nofile" and "scratch" type buffers are considered to always be unchanged.
+ */
+ int
+bufIsChanged(buf)
+ buf_T *buf;
+{
+ return
+#ifdef FEAT_QUICKFIX
+ !bt_dontwrite(buf) &&
+#endif
+ (buf->b_changed || file_ff_differs(buf));
+}
+
+ int
+curbufIsChanged()
+{
+ return
+#ifdef FEAT_QUICKFIX
+ !bt_dontwrite(curbuf) &&
+#endif
+ (curbuf->b_changed || file_ff_differs(curbuf));
+}
diff --git a/src/uninstal.c b/src/uninstal.c
new file mode 100644
index 000000000..23c246b30
--- /dev/null
+++ b/src/uninstal.c
@@ -0,0 +1,438 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * uninstal.c: Minimalistic uninstall program for Vim on MS-Windows
+ * Removes:
+ * - the "Edit with Vim" popup menu entry
+ * - the Vim "Open With..." popup menu entry
+ * - any Vim Batch files in the path
+ * - icons for Vim on the Desktop
+ * - the Vim entry in the Start Menu
+ */
+
+/* Include common code for dosinst.c and uninstal.c. */
+#include "dosinst.h"
+
+/*
+ * Return TRUE if the user types a 'y' or 'Y', FALSE otherwise.
+ */
+ static int
+confirm(void)
+{
+ char answer[10];
+
+ fflush(stdout);
+ return (scanf(" %c", answer) == 1 && toupper(answer[0]) == 'Y');
+}
+
+#ifdef WIN3264
+/*
+ * Check if the popup menu entry exists and what gvim it refers to.
+ * Returns non-zero when it's found.
+ */
+ static int
+popup_gvim_path(char *buf)
+{
+ HKEY key_handle;
+ DWORD value_type;
+ DWORD bufsize = BUFSIZE;
+ int r;
+
+ /* Open the key where the path to gvim.exe is stored. */
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0, KEY_READ,
+ &key_handle) != ERROR_SUCCESS)
+ return 0;
+
+ /* get the DisplayName out of it to show the user */
+ r = RegQueryValueEx(key_handle, "path", 0,
+ &value_type, (LPBYTE)buf, &bufsize);
+ RegCloseKey(key_handle);
+
+ return (r == ERROR_SUCCESS);
+}
+
+/*
+ * Check if the "Open With..." menu entry exists and what gvim it refers to.
+ * Returns non-zero when it's found.
+ */
+ static int
+openwith_gvim_path(char *buf)
+{
+ HKEY key_handle;
+ DWORD value_type;
+ DWORD bufsize = BUFSIZE;
+ int r;
+
+ /* Open the key where the path to gvim.exe is stored. */
+ if (RegOpenKeyEx(HKEY_CLASSES_ROOT,
+ "Applications\\gvim.exe\\shell\\edit\\command", 0, KEY_READ,
+ &key_handle) != ERROR_SUCCESS)
+ return 0;
+
+ /* get the DisplayName out of it to show the user */
+ r = RegQueryValueEx(key_handle, "", 0, &value_type, (LPBYTE)buf, &bufsize);
+ RegCloseKey(key_handle);
+
+ return (r == ERROR_SUCCESS);
+}
+
+ static void
+remove_popup(void)
+{
+ int fail = 0;
+ HKEY kh;
+
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "CLSID\\{51EEE242-AD87-11d3-9C1E-0090278BBD99}\\InProcServer32") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "CLSID\\{51EEE242-AD87-11d3-9C1E-0090278BBD99}") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "*\\shellex\\ContextMenuHandlers\\gvim") != ERROR_SUCCESS)
+ ++fail;
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", 0, KEY_ALL_ACCESS, &kh) != ERROR_SUCCESS)
+ ++fail;
+ else
+ {
+ if (RegDeleteValue(kh, "{51EEE242-AD87-11d3-9C1E-0090278BBD99}") != ERROR_SUCCESS)
+ ++fail;
+ RegCloseKey(kh);
+ }
+ if (RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Vim") != ERROR_SUCCESS)
+ ++fail;
+
+ if (fail == 6)
+ printf("No Vim popup registry entries could be removed\n");
+ else if (fail > 0)
+ printf("Some Vim popup registry entries could not be removed\n");
+ else
+ printf("The Vim popup registry entries have been removed\n");
+}
+
+ static void
+remove_openwith(void)
+{
+ int fail = 0;
+
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "Applications\\gvim.exe\\shell\\edit\\command") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "Applications\\gvim.exe\\shell\\edit") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "Applications\\gvim.exe\\shell") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "Applications\\gvim.exe") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, ".htm\\OpenWithList\\gvim.exe") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, ".vim\\OpenWithList\\gvim.exe") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "*\\OpenWithList\\gvim.exe") != ERROR_SUCCESS)
+ ++fail;
+
+ if (fail == 7)
+ printf("No Vim open-with registry entries could be removed\n");
+ else if (fail > 0)
+ printf("Some Vim open-with registry entries could not be removed\n");
+ else
+ printf("The Vim open-with registry entries have been removed\n");
+}
+#endif
+
+/*
+ * Check if a batch file is really for the current version. Don't delete a
+ * batch file that was written for another (possibly newer) version.
+ */
+ static int
+batfile_thisversion(char *path)
+{
+ FILE *fd;
+ char line[BUFSIZE];
+ char *p;
+ int ver_len = strlen(VIM_VERSION_NODOT);
+ int found = FALSE;
+
+ fd = fopen(path, "r");
+ if (fd != NULL)
+ {
+ while (fgets(line, BUFSIZE, fd) != NULL)
+ {
+ for (p = line; *p != 0; ++p)
+ /* don't accept "vim60an" when looking for "vim60". */
+ if (strnicmp(p, VIM_VERSION_NODOT, ver_len) == 0
+ && !isdigit(p[ver_len])
+ && !isalpha(p[ver_len]))
+ {
+ found = TRUE;
+ break;
+ }
+ if (found)
+ break;
+ }
+ fclose(fd);
+ }
+ return found;
+}
+
+ static int
+remove_batfiles(int doit)
+{
+ char *batfile_path;
+ int i;
+ int found = 0;
+
+ for (i = 1; i < TARGET_COUNT; ++i)
+ {
+ batfile_path = searchpath_save(targets[i].batname);
+ if (batfile_path != NULL && batfile_thisversion(batfile_path))
+ {
+ ++found;
+ if (doit)
+ {
+ printf("removing %s\n", batfile_path);
+ remove(batfile_path);
+ }
+ else
+ printf(" - the batch file %s\n", batfile_path);
+ free(batfile_path);
+ }
+ }
+ return found;
+}
+
+#ifdef WIN3264
+ static void
+remove_if_exists(char *path, char *filename)
+{
+ char buf[BUFSIZE];
+ FILE *fd;
+
+ sprintf(buf, "%s\\%s", path, filename);
+
+ fd = fopen(buf, "r");
+ if (fd != NULL)
+ {
+ fclose(fd);
+ printf("removing %s\n", buf);
+ remove(buf);
+ }
+}
+
+ static void
+remove_icons(void)
+{
+ char path[BUFSIZE];
+ int i;
+
+ if (get_shell_folder_path(path, "desktop"))
+ for (i = 0; i < ICON_COUNT; ++i)
+ remove_if_exists(path, icon_link_names[i]);
+}
+
+ static void
+remove_start_menu(void)
+{
+ char path[BUFSIZE];
+ int i;
+ struct stat st;
+
+ if (get_shell_folder_path(path, VIM_STARTMENU))
+ {
+ for (i = 1; i < TARGET_COUNT; ++i)
+ remove_if_exists(path, targets[i].lnkname);
+ remove_if_exists(path, "uninstall.lnk");
+ remove_if_exists(path, "Help.lnk");
+ /* Win95 uses .pif, WinNT uses .lnk */
+ remove_if_exists(path, "Vim tutor.pif");
+ remove_if_exists(path, "Vim tutor.lnk");
+ remove_if_exists(path, "Vim online.url");
+ if (stat(path, &st) == 0)
+ {
+ printf("removing %s\n", path);
+ rmdir(path);
+ }
+ }
+}
+#endif
+
+#if 0 /* currently not used */
+/*
+ * Return TRUE when we're on Windows 95/98/ME.
+ */
+ static int
+win95(void)
+{
+ static int done = FALSE;
+ static DWORD PlatformId;
+
+ if (!done)
+ {
+ OSVERSIONINFO ovi;
+
+ ovi.dwOSVersionInfoSize = sizeof(ovi);
+ GetVersionEx(&ovi);
+ PlatformId = ovi.dwPlatformId;
+ done = TRUE;
+ }
+ /* Win NT/2000/XP is VER_PLATFORM_WIN32_NT */
+ return PlatformId == VER_PLATFORM_WIN32_WINDOWS;
+}
+#endif
+
+ static void
+delete_uninstall_key(void)
+{
+#ifdef WIN3264
+ RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT);
+#else
+ FILE *fd;
+ char buf[BUFSIZE];
+
+ /*
+ * On DJGPP we delete registry entries by creating a .inf file and
+ * installing it.
+ */
+ fd = fopen("vim.inf", "w");
+ if (fd != NULL)
+ {
+ fprintf(fd, "[version]\n");
+ fprintf(fd, "signature=\"$CHICAGO$\"\n\n");
+ fprintf(fd, "[DefaultInstall]\n");
+ fprintf(fd, "DelReg=DeleteMe\n\n");
+ fprintf(fd, "[DeleteMe]\n");
+ fprintf(fd, "HKLM,\"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT "\"\n");
+ fclose(fd);
+
+ /* Don't know how to detect Win NT with DJGPP. Hack: Just try the Win
+ * 95/98/ME method, since the DJGPP version can't use long filenames
+ * on Win NT anyway. */
+ sprintf(buf, "rundll setupx.dll,InstallHinfSection DefaultInstall 132 %s\\vim.inf", installdir);
+ run_command(buf);
+#if 0
+ /* Windows NT method (untested). */
+ sprintf(buf, "rundll32 syssetup,SetupInfObjectInstallAction DefaultInstall 128 %s\\vim.inf", installdir);
+ run_command(buf);
+#endif
+
+ remove("vim.inf");
+ }
+#endif
+}
+
+ int
+main(int argc, char *argv[])
+{
+ int found = 0;
+ FILE *fd;
+#ifdef WIN3264
+ int i;
+ struct stat st;
+ char icon[BUFSIZE];
+ char path[BUFSIZE];
+ char popup_path[BUFSIZE];
+
+ /* The nsis uninstaller calls us with a "-nsis" argument. */
+ if (argc == 2 && stricmp(argv[1], "-nsis") == 0)
+ interactive = FALSE;
+ else
+#endif
+ interactive = TRUE;
+
+ /* Initialize this program. */
+ do_inits(argv);
+
+ printf("This program will remove the following items:\n");
+
+#ifdef WIN3264
+ if (popup_gvim_path(popup_path))
+ {
+ printf(" - the \"Edit with Vim\" entry in the popup menu\n");
+ printf(" which uses \"%s\"\n", popup_path);
+ printf("\nRemove it (y/n)? ");
+ if (confirm())
+ {
+ remove_popup();
+ /* Assume the "Open With" entry can be removed as well, don't
+ * bother the user with asking him again. */
+ remove_openwith();
+ }
+ }
+ else if (openwith_gvim_path(popup_path))
+ {
+ printf(" - the Vim \"Open With...\" entry in the popup menu\n");
+ printf(" which uses \"%s\"\n", popup_path);
+ printf("\nRemove it (y/n)? ");
+ if (confirm())
+ remove_openwith();
+ }
+
+ if (get_shell_folder_path(path, "desktop"))
+ {
+ printf("\n");
+ for (i = 0; i < ICON_COUNT; ++i)
+ {
+ sprintf(icon, "%s\\%s", path, icon_link_names[i]);
+ if (stat(icon, &st) == 0)
+ {
+ printf(" - the \"%s\" icon on the desktop\n", icon_names[i]);
+ ++found;
+ }
+ }
+ if (found > 0)
+ {
+ if (interactive)
+ printf("\nRemove %s (y/n)? ", found > 1 ? "them" : "it");
+ if (!interactive || confirm())
+ remove_icons();
+ }
+ }
+
+ if (get_shell_folder_path(path, VIM_STARTMENU)
+ && stat(path, &st) == 0)
+ {
+ printf("\n - the \"%s\" entry in the Start Menu\n", VIM_STARTMENU);
+ if (interactive)
+ printf("\nRemove it (y/n)? ");
+ if (!interactive || confirm())
+ remove_start_menu();
+ }
+#endif
+
+ printf("\n");
+ found = remove_batfiles(0);
+ if (found > 0)
+ {
+ if (interactive)
+ printf("\nRemove %s (y/n)? ", found > 1 ? "them" : "it");
+ if (!interactive || confirm())
+ remove_batfiles(1);
+ }
+
+ fd = fopen("gvim.exe", "r");
+ if (fd != NULL)
+ {
+ fclose(fd);
+ printf("gvim.exe detected. Attempting to unregister gvim with OLE\n");
+ system("gvim.exe -silent -unregister");
+ }
+
+ delete_uninstall_key();
+
+ if (interactive)
+ {
+ printf("\nYou may now want to delete the Vim executables and runtime files.\n");
+ printf("(They are still where you unpacked them.)\n");
+ }
+
+ rewind(stdin);
+ printf("\nPress Enter to exit...");
+ (void)getchar();
+
+ return 0;
+}
diff --git a/src/version.c b/src/version.c
new file mode 100644
index 000000000..01293435e
--- /dev/null
+++ b/src/version.c
@@ -0,0 +1,1219 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+
+#ifdef AMIGA
+# include <time.h> /* for time() */
+#endif
+
+/*
+ * Vim originated from Stevie version 3.6 (Fish disk 217) by GRWalter (Fred)
+ * It has been changed beyond recognition since then.
+ *
+ * Differences between version 5.x and 6.x can be found with ":help version6".
+ * Differences between version 4.x and 5.x can be found with ":help version5".
+ * Differences between version 3.0 and 4.x can be found with ":help version4".
+ * All the remarks about older versions have been removed, they are not very
+ * interesting.
+ */
+
+#include "version.h"
+
+char *Version = VIM_VERSION_SHORT;
+char *mediumVersion = VIM_VERSION_MEDIUM;
+
+#if defined(HAVE_DATE_TIME) || defined(PROTO)
+# if (defined(VMS) && defined(VAXC)) || defined(PROTO)
+char longVersion[sizeof(VIM_VERSION_LONG_DATE) + sizeof(__DATE__)
+ + sizeof(__TIME__) + 3];
+ void
+make_version()
+{
+ /*
+ * Construct the long version string. Necessary because
+ * VAX C can't catenate strings in the preprocessor.
+ */
+ strcpy(longVersion, VIM_VERSION_LONG_DATE);
+ strcat(longVersion, __DATE__);
+ strcat(longVersion, " ");
+ strcat(longVersion, __TIME__);
+ strcat(longVersion, ")");
+}
+# else
+char *longVersion = VIM_VERSION_LONG_DATE __DATE__ " " __TIME__ ")";
+# endif
+#else
+char *longVersion = VIM_VERSION_LONG;
+#endif
+
+static void version_msg __ARGS((char *s));
+
+static char *(features[]) =
+{
+#ifdef AMIGA /* only for Amiga systems */
+# ifdef FEAT_ARP
+ "+ARP",
+# else
+ "-ARP",
+# endif
+#endif
+#ifdef FEAT_ARABIC
+ "+arabic",
+#else
+ "-arabic",
+#endif
+#ifdef FEAT_AUTOCMD
+ "+autocmd",
+#else
+ "-autocmd",
+#endif
+#ifdef FEAT_BEVAL
+ "+balloon_eval",
+#else
+ "-balloon_eval",
+#endif
+#ifdef FEAT_BROWSE
+ "+browse",
+#else
+ "-browse",
+#endif
+#ifdef NO_BUILTIN_TCAPS
+ "-builtin_terms",
+#endif
+#ifdef SOME_BUILTIN_TCAPS
+ "+builtin_terms",
+#endif
+#ifdef ALL_BUILTIN_TCAPS
+ "++builtin_terms",
+#endif
+#ifdef FEAT_BYTEOFF
+ "+byte_offset",
+#else
+ "-byte_offset",
+#endif
+#ifdef FEAT_CINDENT
+ "+cindent",
+#else
+ "-cindent",
+#endif
+#ifdef FEAT_CLIENTSERVER
+ "+clientserver",
+#else
+ "-clientserver",
+#endif
+#ifdef FEAT_CLIPBOARD
+ "+clipboard",
+#else
+ "-clipboard",
+#endif
+#ifdef FEAT_CMDL_COMPL
+ "+cmdline_compl",
+#else
+ "-cmdline_compl",
+#endif
+#ifdef FEAT_CMDHIST
+ "+cmdline_hist",
+#else
+ "-cmdline_hist",
+#endif
+#ifdef FEAT_CMDL_INFO
+ "+cmdline_info",
+#else
+ "-cmdline_info",
+#endif
+#ifdef FEAT_COMMENTS
+ "+comments",
+#else
+ "-comments",
+#endif
+#ifdef FEAT_CRYPT
+ "+cryptv",
+#else
+ "-cryptv",
+#endif
+#ifdef FEAT_CSCOPE
+ "+cscope",
+#else
+ "-cscope",
+#endif
+#if defined(FEAT_CON_DIALOG) && defined(FEAT_GUI_DIALOG)
+ "+dialog_con_gui",
+#else
+# if defined(FEAT_CON_DIALOG)
+ "+dialog_con",
+# else
+# if defined(FEAT_GUI_DIALOG)
+ "+dialog_gui",
+# else
+ "-dialog",
+# endif
+# endif
+#endif
+#ifdef FEAT_DIFF
+ "+diff",
+#else
+ "-diff",
+#endif
+#ifdef FEAT_DIGRAPHS
+ "+digraphs",
+#else
+ "-digraphs",
+#endif
+#ifdef FEAT_DND
+ "+dnd",
+#else
+ "-dnd",
+#endif
+#ifdef EBCDIC
+ "+ebcdic",
+#else
+ "-ebcdic",
+#endif
+#ifdef FEAT_EMACS_TAGS
+ "+emacs_tags",
+#else
+ "-emacs_tags",
+#endif
+#ifdef FEAT_EVAL
+ "+eval",
+#else
+ "-eval",
+#endif
+#ifdef FEAT_EX_EXTRA
+ "+ex_extra",
+#else
+ "-ex_extra",
+#endif
+#ifdef FEAT_SEARCH_EXTRA
+ "+extra_search",
+#else
+ "-extra_search",
+#endif
+#ifdef FEAT_FKMAP
+ "+farsi",
+#else
+ "-farsi",
+#endif
+#ifdef FEAT_SEARCHPATH
+ "+file_in_path",
+#else
+ "-file_in_path",
+#endif
+#ifdef FEAT_FIND_ID
+ "+find_in_path",
+#else
+ "-find_in_path",
+#endif
+#ifdef FEAT_FOLDING
+ "+folding",
+#else
+ "-folding",
+#endif
+#ifdef FEAT_FOOTER
+ "+footer",
+#else
+ "-footer",
+#endif
+ /* only interesting on Unix systems */
+#if !defined(USE_SYSTEM) && defined(UNIX)
+ "+fork()",
+#endif
+#ifdef FEAT_GETTEXT
+# ifdef DYNAMIC_GETTEXT
+ "+gettext/dyn",
+# else
+ "+gettext",
+# endif
+#else
+ "-gettext",
+#endif
+#ifdef FEAT_HANGULIN
+ "+hangul_input",
+#else
+ "-hangul_input",
+#endif
+#if (defined(HAVE_ICONV_H) && defined(USE_ICONV)) || defined(DYNAMIC_ICONV)
+# ifdef DYNAMIC_ICONV
+ "+iconv/dyn",
+# else
+ "+iconv",
+# endif
+#else
+ "-iconv",
+#endif
+#ifdef FEAT_INS_EXPAND
+ "+insert_expand",
+#else
+ "-insert_expand",
+#endif
+#ifdef FEAT_JUMPLIST
+ "+jumplist",
+#else
+ "-jumplist",
+#endif
+#ifdef FEAT_KEYMAP
+ "+keymap",
+#else
+ "-keymap",
+#endif
+#ifdef FEAT_LANGMAP
+ "+langmap",
+#else
+ "-langmap",
+#endif
+#ifdef FEAT_LIBCALL
+ "+libcall",
+#else
+ "-libcall",
+#endif
+#ifdef FEAT_LINEBREAK
+ "+linebreak",
+#else
+ "-linebreak",
+#endif
+#ifdef FEAT_LISP
+ "+lispindent",
+#else
+ "-lispindent",
+#endif
+#ifdef FEAT_LISTCMDS
+ "+listcmds",
+#else
+ "-listcmds",
+#endif
+#ifdef FEAT_LOCALMAP
+ "+localmap",
+#else
+ "-localmap",
+#endif
+#ifdef FEAT_MENU
+ "+menu",
+#else
+ "-menu",
+#endif
+#ifdef FEAT_SESSION
+ "+mksession",
+#else
+ "-mksession",
+#endif
+#ifdef FEAT_MODIFY_FNAME
+ "+modify_fname",
+#else
+ "-modify_fname",
+#endif
+#ifdef FEAT_MOUSE
+ "+mouse",
+# ifdef FEAT_MOUSESHAPE
+ "+mouseshape",
+# else
+ "-mouseshape",
+# endif
+# else
+ "-mouse",
+#endif
+#if defined(UNIX) || defined(VMS)
+# ifdef FEAT_MOUSE_DEC
+ "+mouse_dec",
+# else
+ "-mouse_dec",
+# endif
+# ifdef FEAT_MOUSE_GPM
+ "+mouse_gpm",
+# else
+ "-mouse_gpm",
+# endif
+# ifdef FEAT_MOUSE_JSB
+ "+mouse_jsbterm",
+# else
+ "-mouse_jsbterm",
+# endif
+# ifdef FEAT_MOUSE_NET
+ "+mouse_netterm",
+# else
+ "-mouse_netterm",
+# endif
+# ifdef FEAT_MOUSE_XTERM
+ "+mouse_xterm",
+# else
+ "-mouse_xterm",
+# endif
+#endif
+#ifdef __QNX__
+# ifdef FEAT_MOUSE_PTERM
+ "+mouse_pterm",
+# else
+ "-mouse_pterm",
+# endif
+#endif
+#ifdef FEAT_MBYTE_IME
+# ifdef DYNAMIC_IME
+ "+multi_byte_ime/dyn",
+# else
+ "+multi_byte_ime",
+# endif
+#else
+# ifdef FEAT_MBYTE
+ "+multi_byte",
+# else
+ "-multi_byte",
+# endif
+#endif
+#ifdef FEAT_MULTI_LANG
+ "+multi_lang",
+#else
+ "-multi_lang",
+#endif
+#ifdef FEAT_NETBEANS_INTG
+ "+netbeans_intg",
+#else
+ "-netbeans_intg",
+#endif
+#ifdef FEAT_GUI_W32
+# ifdef FEAT_OLE
+ "+ole",
+# else
+ "-ole",
+# endif
+#endif
+#ifdef FEAT_OSFILETYPE
+ "+osfiletype",
+#else
+ "-osfiletype",
+#endif
+#ifdef FEAT_PATH_EXTRA
+ "+path_extra",
+#else
+ "-path_extra",
+#endif
+#ifdef FEAT_PERL
+# ifdef DYNAMIC_PERL
+ "+perl/dyn",
+# else
+ "+perl",
+# endif
+#else
+ "-perl",
+#endif
+#ifdef FEAT_PRINTER
+# ifdef FEAT_POSTSCRIPT
+ "+postscript",
+# else
+ "-postscript",
+# endif
+ "+printer",
+#else
+ "-printer",
+#endif
+#ifdef FEAT_PYTHON
+# ifdef DYNAMIC_PYTHON
+ "+python/dyn",
+# else
+ "+python",
+# endif
+#else
+ "-python",
+#endif
+#ifdef FEAT_QUICKFIX
+ "+quickfix",
+#else
+ "-quickfix",
+#endif
+#ifdef FEAT_RIGHTLEFT
+ "+rightleft",
+#else
+ "-rightleft",
+#endif
+#ifdef FEAT_RUBY
+# ifdef DYNAMIC_RUBY
+ "+ruby/dyn",
+# else
+ "+ruby",
+# endif
+#else
+ "-ruby",
+#endif
+#ifdef FEAT_SCROLLBIND
+ "+scrollbind",
+#else
+ "-scrollbind",
+#endif
+#ifdef FEAT_SIGNS
+ "+signs",
+#else
+ "-signs",
+#endif
+#ifdef FEAT_SMARTINDENT
+ "+smartindent",
+#else
+ "-smartindent",
+#endif
+#ifdef FEAT_SNIFF
+ "+sniff",
+#else
+ "-sniff",
+#endif
+#ifdef FEAT_STL_OPT
+ "+statusline",
+#else
+ "-statusline",
+#endif
+#ifdef FEAT_SUN_WORKSHOP
+ "+sun_workshop",
+#else
+ "-sun_workshop",
+#endif
+#ifdef FEAT_SYN_HL
+ "+syntax",
+#else
+ "-syntax",
+#endif
+ /* only interesting on Unix systems */
+#if defined(USE_SYSTEM) && (defined(UNIX) || defined(__EMX__))
+ "+system()",
+#endif
+#ifdef FEAT_TAG_BINS
+ "+tag_binary",
+#else
+ "-tag_binary",
+#endif
+#ifdef FEAT_TAG_OLDSTATIC
+ "+tag_old_static",
+#else
+ "-tag_old_static",
+#endif
+#ifdef FEAT_TAG_ANYWHITE
+ "+tag_any_white",
+#else
+ "-tag_any_white",
+#endif
+#ifdef FEAT_TCL
+# ifdef DYNAMIC_TCL
+ "+tcl/dyn",
+# else
+ "+tcl",
+# endif
+#else
+ "-tcl",
+#endif
+#if defined(UNIX) || defined(__EMX__)
+/* only Unix (or OS/2 with EMX!) can have terminfo instead of termcap */
+# ifdef TERMINFO
+ "+terminfo",
+# else
+ "-terminfo",
+# endif
+#else /* unix always includes termcap support */
+# ifdef HAVE_TGETENT
+ "+tgetent",
+# else
+ "-tgetent",
+# endif
+#endif
+#ifdef FEAT_TERMRESPONSE
+ "+termresponse",
+#else
+ "-termresponse",
+#endif
+#ifdef FEAT_TEXTOBJ
+ "+textobjects",
+#else
+ "-textobjects",
+#endif
+#ifdef FEAT_TITLE
+ "+title",
+#else
+ "-title",
+#endif
+#ifdef FEAT_TOOLBAR
+ "+toolbar",
+#else
+ "-toolbar",
+#endif
+#ifdef FEAT_USR_CMDS
+ "+user_commands",
+#else
+ "-user_commands",
+#endif
+#ifdef FEAT_VERTSPLIT
+ "+vertsplit",
+#else
+ "-vertsplit",
+#endif
+#ifdef FEAT_VIRTUALEDIT
+ "+virtualedit",
+#else
+ "-virtualedit",
+#endif
+#ifdef FEAT_VISUAL
+ "+visual",
+# ifdef FEAT_VISUALEXTRA
+ "+visualextra",
+# else
+ "-visualextra",
+# endif
+#else
+ "-visual",
+#endif
+#ifdef FEAT_VIMINFO
+ "+viminfo",
+#else
+ "-viminfo",
+#endif
+#ifdef FEAT_VREPLACE
+ "+vreplace",
+#else
+ "-vreplace",
+#endif
+#ifdef FEAT_WILDIGN
+ "+wildignore",
+#else
+ "-wildignore",
+#endif
+#ifdef FEAT_WILDMENU
+ "+wildmenu",
+#else
+ "-wildmenu",
+#endif
+#ifdef FEAT_WINDOWS
+ "+windows",
+#else
+ "-windows",
+#endif
+#ifdef FEAT_WRITEBACKUP
+ "+writebackup",
+#else
+ "-writebackup",
+#endif
+#if defined(UNIX) || defined(VMS)
+# ifdef FEAT_X11
+ "+X11",
+# else
+ "-X11",
+# endif
+#endif
+#ifdef FEAT_XFONTSET
+ "+xfontset",
+#else
+ "-xfontset",
+#endif
+#ifdef FEAT_XIM
+ "+xim",
+#else
+ "-xim",
+#endif
+#if defined(UNIX) || defined(VMS)
+# ifdef USE_XSMP_INTERACT
+ "+xsmp_interact",
+# else
+# ifdef USE_XSMP
+ "+xsmp",
+# else
+ "-xsmp",
+# endif
+# endif
+# ifdef FEAT_XCLIPBOARD
+ "+xterm_clipboard",
+# else
+ "-xterm_clipboard",
+# endif
+#endif
+#ifdef FEAT_XTERM_SAVE
+ "+xterm_save",
+#else
+ "-xterm_save",
+#endif
+#ifdef WIN3264
+# ifdef FEAT_XPM_W32
+ "+xpm_w32",
+# else
+ "-xpm_w32",
+# endif
+#endif
+ NULL
+};
+
+static int included_patches[] =
+{ /* Add new patch number below this line */
+/**/
+ 0
+};
+
+ int
+highest_patch()
+{
+ int i;
+ int h = 0;
+
+ for (i = 0; included_patches[i] != 0; ++i)
+ if (included_patches[i] > h)
+ h = included_patches[i];
+ return h;
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return TRUE if patch "n" has been included.
+ */
+ int
+has_patch(n)
+ int n;
+{
+ int i;
+
+ for (i = 0; included_patches[i] != 0; ++i)
+ if (included_patches[i] == n)
+ return TRUE;
+ return FALSE;
+}
+#endif
+
+ void
+ex_version(eap)
+ exarg_T *eap;
+{
+ /*
+ * Ignore a ":version 9.99" command.
+ */
+ if (*eap->arg == NUL)
+ {
+ msg_putchar('\n');
+ list_version();
+ }
+}
+
+ void
+list_version()
+{
+ int i;
+ int first;
+ char *s = "";
+
+ /*
+ * When adding features here, don't forget to update the list of
+ * internal variables in eval.c!
+ */
+ MSG(longVersion);
+#ifdef WIN3264
+# ifdef FEAT_GUI_W32
+# if defined(_MSC_VER) && (_MSC_VER <= 1010)
+ /* Only MS VC 4.1 and earlier can do Win32s */
+ MSG_PUTS(_("\nMS-Windows 16/32 bit GUI version"));
+# else
+ MSG_PUTS(_("\nMS-Windows 32 bit GUI version"));
+# endif
+ if (gui_is_win32s())
+ MSG_PUTS(_(" in Win32s mode"));
+# ifdef FEAT_OLE
+ MSG_PUTS(_(" with OLE support"));
+# endif
+# else
+ MSG_PUTS(_("\nMS-Windows 32 bit console version"));
+# endif
+#endif
+#ifdef WIN16
+ MSG_PUTS(_("\nMS-Windows 16 bit version"));
+#endif
+#ifdef MSDOS
+# ifdef DJGPP
+ MSG_PUTS(_("\n32 bit MS-DOS version"));
+# else
+ MSG_PUTS(_("\n16 bit MS-DOS version"));
+# endif
+#endif
+#ifdef MACOS
+# ifdef MACOS_X
+# ifdef MACOS_X_UNIX
+ MSG_PUTS(_("\nMacOS X (unix) version"));
+# else
+ MSG_PUTS(_("\nMacOS X version"));
+# endif
+#else
+ MSG_PUTS(_("\nMacOS version"));
+# endif
+#endif
+
+#ifdef RISCOS
+ MSG_PUTS(_("\nRISC OS version"));
+#endif
+#ifdef VMS
+ MSG_PUTS("\nOpenVMS version");
+#endif
+
+ /* Print the list of patch numbers if there is at least one. */
+ /* Print a range when patches are consecutive: "1-10, 12, 15-40, 42-45" */
+ if (included_patches[0] != 0)
+ {
+ MSG_PUTS(_("\nIncluded patches: "));
+ first = -1;
+ /* find last one */
+ for (i = 0; included_patches[i] != 0; ++i)
+ ;
+ while (--i >= 0)
+ {
+ if (first < 0)
+ first = included_patches[i];
+ if (i == 0 || included_patches[i - 1] != included_patches[i] + 1)
+ {
+ MSG_PUTS(s);
+ s = ", ";
+ msg_outnum((long)first);
+ if (first != included_patches[i])
+ {
+ MSG_PUTS("-");
+ msg_outnum((long)included_patches[i]);
+ }
+ first = -1;
+ }
+ }
+ }
+
+#ifdef MODIFIED_BY
+ MSG_PUTS("\n");
+ MSG_PUTS(_("Modified by "));
+ MSG_PUTS(MODIFIED_BY);
+#endif
+
+#ifdef HAVE_PATHDEF
+ if (*compiled_user != NUL || *compiled_sys != NUL)
+ {
+ MSG_PUTS(_("\nCompiled "));
+ if (*compiled_user != NUL)
+ {
+ MSG_PUTS(_("by "));
+ MSG_PUTS(compiled_user);
+ }
+ if (*compiled_sys != NUL)
+ {
+ MSG_PUTS("@");
+ MSG_PUTS(compiled_sys);
+ }
+ }
+#endif
+
+#ifdef FEAT_HUGE
+ MSG_PUTS(_("\nHuge version "));
+#else
+# ifdef FEAT_BIG
+ MSG_PUTS(_("\nBig version "));
+# else
+# ifdef FEAT_NORMAL
+ MSG_PUTS(_("\nNormal version "));
+# else
+# ifdef FEAT_SMALL
+ MSG_PUTS(_("\nSmall version "));
+# else
+ MSG_PUTS(_("\nTiny version "));
+# endif
+# endif
+# endif
+#endif
+#ifndef FEAT_GUI
+ MSG_PUTS(_("without GUI."));
+#else
+# ifdef FEAT_GUI_GTK
+# ifdef FEAT_GUI_GNOME
+# ifdef HAVE_GTK2
+ MSG_PUTS(_("with GTK2-GNOME GUI."));
+# else
+ MSG_PUTS(_("with GTK-GNOME GUI."));
+# endif
+# else
+# ifdef HAVE_GTK2
+ MSG_PUTS(_("with GTK2 GUI."));
+# else
+ MSG_PUTS(_("with GTK GUI."));
+# endif
+# endif
+# else
+# ifdef FEAT_GUI_MOTIF
+ MSG_PUTS(_("with X11-Motif GUI."));
+# else
+# ifdef FEAT_GUI_ATHENA
+# ifdef FEAT_GUI_NEXTAW
+ MSG_PUTS(_("with X11-neXtaw GUI."));
+# else
+ MSG_PUTS(_("with X11-Athena GUI."));
+# endif
+# else
+# ifdef FEAT_GUI_BEOS
+ MSG_PUTS(_("with BeOS GUI."));
+# else
+# ifdef FEAT_GUI_PHOTON
+ MSG_PUTS(_("with Photon GUI."));
+# else
+# if defined(MSWIN)
+ MSG_PUTS(_("with GUI."));
+# else
+# if defined (TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON
+ MSG_PUTS(_("with Carbon GUI."));
+# else
+# if defined (TARGET_API_MAC_OSX) && TARGET_API_MAC_OSX
+ MSG_PUTS(_("with Cocoa GUI."));
+# else
+# if defined (MACOS)
+ MSG_PUTS(_("with (classic) GUI."));
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+#endif
+ version_msg(_(" Features included (+) or not (-):\n"));
+
+ /* print all the features */
+ for (i = 0; features[i] != NULL; ++i)
+ {
+ version_msg(features[i]);
+ if (msg_col > 0)
+ version_msg(" ");
+ }
+
+ version_msg("\n");
+#ifdef SYS_VIMRC_FILE
+ version_msg(_(" system vimrc file: \""));
+ version_msg(SYS_VIMRC_FILE);
+ version_msg("\"\n");
+#endif
+#ifdef USR_VIMRC_FILE
+ version_msg(_(" user vimrc file: \""));
+ version_msg(USR_VIMRC_FILE);
+ version_msg("\"\n");
+#endif
+#ifdef USR_VIMRC_FILE2
+ version_msg(_(" 2nd user vimrc file: \""));
+ version_msg(USR_VIMRC_FILE2);
+ version_msg("\"\n");
+#endif
+#ifdef USR_VIMRC_FILE3
+ version_msg(_(" 3rd user vimrc file: \""));
+ version_msg(USR_VIMRC_FILE3);
+ version_msg("\"\n");
+#endif
+#ifdef USR_EXRC_FILE
+ version_msg(_(" user exrc file: \""));
+ version_msg(USR_EXRC_FILE);
+ version_msg("\"\n");
+#endif
+#ifdef USR_EXRC_FILE2
+ version_msg(_(" 2nd user exrc file: \""));
+ version_msg(USR_EXRC_FILE2);
+ version_msg("\"\n");
+#endif
+#ifdef FEAT_GUI
+# ifdef SYS_GVIMRC_FILE
+ version_msg(_(" system gvimrc file: \""));
+ version_msg(SYS_GVIMRC_FILE);
+ version_msg("\"\n");
+# endif
+ version_msg(_(" user gvimrc file: \""));
+ version_msg(USR_GVIMRC_FILE);
+ version_msg("\"\n");
+# ifdef USR_GVIMRC_FILE2
+ version_msg(_("2nd user gvimrc file: \""));
+ version_msg(USR_GVIMRC_FILE2);
+ version_msg("\"\n");
+# endif
+# ifdef USR_GVIMRC_FILE3
+ version_msg(_("3rd user gvimrc file: \""));
+ version_msg(USR_GVIMRC_FILE3);
+ version_msg("\"\n");
+# endif
+#endif
+#ifdef FEAT_GUI
+# ifdef SYS_MENU_FILE
+ version_msg(_(" system menu file: \""));
+ version_msg(SYS_MENU_FILE);
+ version_msg("\"\n");
+# endif
+#endif
+#ifdef HAVE_PATHDEF
+ if (*default_vim_dir != NUL)
+ {
+ version_msg(_(" fall-back for $VIM: \""));
+ version_msg((char *)default_vim_dir);
+ version_msg("\"\n");
+ }
+ if (*default_vimruntime_dir != NUL)
+ {
+ version_msg(_(" f-b for $VIMRUNTIME: \""));
+ version_msg((char *)default_vimruntime_dir);
+ version_msg("\"\n");
+ }
+ version_msg(_("Compilation: "));
+ version_msg((char *)all_cflags);
+ version_msg("\n");
+#ifdef VMS
+ if (*compiler_version != NUL)
+ {
+ version_msg(_("Compiler: "));
+ version_msg((char *)compiler_version);
+ version_msg("\n");
+ }
+#endif
+ version_msg(_("Linking: "));
+ version_msg((char *)all_lflags);
+#endif
+#ifdef DEBUG
+ version_msg("\n");
+ version_msg(_(" DEBUG BUILD"));
+#endif
+}
+
+/*
+ * Output a string for the version message. If it's going to wrap, output a
+ * newline, unless the message is too long to fit on the screen anyway.
+ */
+ static void
+version_msg(s)
+ char *s;
+{
+ int len = (int)STRLEN(s);
+
+ if (!got_int && len < (int)Columns && msg_col + len >= (int)Columns
+ && *s != '\n')
+ msg_putchar('\n');
+ if (!got_int)
+ MSG_PUTS(s);
+}
+
+static void do_intro_line __ARGS((int row, char_u *mesg, int add_version, int attr));
+
+/*
+ * Give an introductory message about Vim.
+ * Only used when starting Vim on an empty file, without a file name.
+ * Or with the ":intro" command (for Sven :-).
+ */
+ void
+intro_message(colon)
+ int colon; /* TRUE for ":intro" */
+{
+ int i;
+ int row;
+ int blanklines;
+ int sponsor;
+ char *p;
+ static char *(lines[]) =
+ {
+ N_("VIM - Vi IMproved"),
+ "",
+ N_("version "),
+ N_("by Bram Moolenaar et al."),
+#ifdef MODIFIED_BY
+ " ",
+#endif
+ N_("Vim is open source and freely distributable"),
+ "",
+ N_("Help poor children in Uganda!"),
+ N_("type :help iccf<Enter> for information "),
+ "",
+ N_("type :q<Enter> to exit "),
+ N_("type :help<Enter> or <F1> for on-line help"),
+ N_("type :help version6<Enter> for version info"),
+ NULL,
+ "",
+ N_("Running in Vi compatible mode"),
+ N_("type :set nocp<Enter> for Vim defaults"),
+ N_("type :help cp-default<Enter> for info on this"),
+ };
+#ifdef FEAT_GUI
+ static char *(gui_lines[]) =
+ {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+#ifdef MODIFIED_BY
+ NULL,
+#endif
+ NULL,
+ NULL,
+ NULL,
+ N_("menu Help->Orphans for information "),
+ NULL,
+ N_("Running modeless, typed text is inserted"),
+ N_("menu Edit->Global Settings->Toggle Insert Mode "),
+ N_(" for two modes "),
+ NULL,
+ NULL,
+ NULL,
+ N_("menu Edit->Global Settings->Toggle Vi Compatible"),
+ N_(" for Vim defaults "),
+ };
+#endif
+
+ /* blanklines = screen height - # message lines */
+ blanklines = (int)Rows - ((sizeof(lines) / sizeof(char *)) - 1);
+ if (!p_cp)
+ blanklines += 4; /* add 4 for not showing "Vi compatible" message */
+#if defined(WIN3264) && !defined(FEAT_GUI_W32)
+ if (mch_windows95())
+ blanklines -= 3; /* subtract 3 for showing "Windows 95" message */
+#endif
+
+#ifdef FEAT_WINDOWS
+ /* Don't overwrite a statusline. Depends on 'cmdheight'. */
+ if (p_ls > 1)
+ blanklines -= Rows - topframe->fr_height;
+#endif
+ if (blanklines < 0)
+ blanklines = 0;
+
+ /* Show the sponsor and register message one out of four times, the Uganda
+ * message two out of four times. */
+ sponsor = time(NULL);
+ sponsor = ((sponsor & 2) == 0) - ((sponsor & 4) == 0);
+
+ /* start displaying the message lines after half of the blank lines */
+ row = blanklines / 2;
+ if ((row >= 2 && Columns >= 50) || colon)
+ {
+ for (i = 0; i < (int)(sizeof(lines) / sizeof(char *)); ++i)
+ {
+ p = lines[i];
+#ifdef FEAT_GUI
+ if (p_im && gui.in_use && gui_lines[i] != NULL)
+ p = gui_lines[i];
+#endif
+ if (p == NULL)
+ {
+ if (!p_cp)
+ break;
+ continue;
+ }
+ if (sponsor != 0)
+ {
+ if (strstr(p, "children") != NULL)
+ p = sponsor < 0
+ ? N_("Sponsor Vim development!")
+ : N_("Become a registered Vim user!");
+ else if (strstr(p, "iccf") != NULL)
+ p = sponsor < 0
+ ? N_("type :help sponsor<Enter> for information ")
+ : N_("type :help register<Enter> for information ");
+ else if (strstr(p, "Orphans") != NULL)
+ p = N_("menu Help->Sponsor/Register for information ");
+ }
+ if (*p != NUL)
+ do_intro_line(row, (char_u *)_(p), i == 2, 0);
+ ++row;
+ }
+#if defined(WIN3264) && !defined(FEAT_GUI_W32)
+ if (mch_windows95())
+ {
+ do_intro_line(++row,
+ (char_u *)_("WARNING: Windows 95/98/ME detected"),
+ FALSE, hl_attr(HLF_E));
+ do_intro_line(++row,
+ (char_u *)_("type :help windows95<Enter> for info on this"),
+ FALSE, 0);
+ }
+#endif
+ }
+
+ /* Make the wait-return message appear just below the text. */
+ if (colon)
+ msg_row = row;
+}
+
+ static void
+do_intro_line(row, mesg, add_version, attr)
+ int row;
+ char_u *mesg;
+ int add_version;
+ int attr;
+{
+ char_u vers[20];
+ int col;
+ char_u *p;
+ int l;
+ int clen;
+#ifdef MODIFIED_BY
+# define MODBY_LEN 150
+ char_u modby[MODBY_LEN];
+
+ if (*mesg == ' ')
+ {
+ STRNCPY(modby, _("Modified by "), MODBY_LEN);
+ modby[MODBY_LEN - 1] = NUL;
+ l = STRLEN(modby);
+ STRNCPY(modby + l, MODIFIED_BY, MODBY_LEN - l);
+ modby[MODBY_LEN - 1] = NUL;
+ mesg = modby;
+ }
+#endif
+
+ /* Center the message horizontally. */
+ col = vim_strsize(mesg);
+ if (add_version)
+ {
+ STRCPY(vers, mediumVersion);
+ if (highest_patch())
+ {
+ /* Check for 9.9x or 9.9xx, alpha/beta version */
+ if (isalpha((int)mediumVersion[3]))
+ {
+ if (isalpha((int)mediumVersion[4]))
+ sprintf((char *)vers + 5, ".%d%s", highest_patch(),
+ mediumVersion + 5);
+ else
+ sprintf((char *)vers + 4, ".%d%s", highest_patch(),
+ mediumVersion + 4);
+ }
+ else
+ sprintf((char *)vers + 3, ".%d", highest_patch());
+ }
+ col += (int)STRLEN(vers);
+ }
+ col = (Columns - col) / 2;
+ if (col < 0)
+ col = 0;
+
+ /* Split up in parts to highlight <> items differently. */
+ for (p = mesg; *p != NUL; p += l)
+ {
+ clen = 0;
+ for (l = 0; p[l] != NUL
+ && (l == 0 || (p[l] != '<' && p[l - 1] != '>')); ++l)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ {
+ clen += ptr2cells(p + l);
+ l += (*mb_ptr2len_check)(p + l) - 1;
+ }
+ else
+#endif
+ clen += byte2cells(p[l]);
+ }
+ screen_puts_len(p, l, row, col, *p == '<' ? hl_attr(HLF_8) : attr);
+ col += clen;
+ }
+
+ /* Add the version number to the version line. */
+ if (add_version)
+ screen_puts(vers, row, col, 0);
+}
+
+/*
+ * ":intro": clear screen, display intro screen and wait for return.
+ */
+/*ARGSUSED*/
+ void
+ex_intro(eap)
+ exarg_T *eap;
+{
+ screenclear();
+ intro_message(TRUE);
+ wait_return(TRUE);
+}
diff --git a/src/version.h b/src/version.h
new file mode 100644
index 000000000..2d98d2874
--- /dev/null
+++ b/src/version.h
@@ -0,0 +1,40 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+/*
+ * Define the version number, name, etc.
+ * The patchlevel is in included_patches[], in version.c.
+ *
+ * This doesn't use string contatenation, some compilers don't support it.
+ */
+
+#define VIM_VERSION_MAJOR 7
+#define VIM_VERSION_MAJOR_STR "7"
+#define VIM_VERSION_MINOR 0
+#define VIM_VERSION_MINOR_STR "0"
+#define VIM_VERSION_100 (VIM_VERSION_MAJOR * 100 + VIM_VERSION_MINOR)
+
+#define VIM_VERSION_BUILD 256
+#define VIM_VERSION_BUILD_BCD 0x100
+#define VIM_VERSION_BUILD_STR "256"
+#define VIM_VERSION_PATCHLEVEL 0
+#define VIM_VERSION_PATCHLEVEL_STR "0"
+/* Used by MacOS port should be one of: development, alpha, beta, final */
+#define VIM_VERSION_RELEASE alpha
+
+/*
+ * VIM_VERSION_NODOT is used for the runtime directory name.
+ * VIM_VERSION_SHORT is copied into the swap file (max. length is 6 chars).
+ * VIM_VERSION_MEDIUM is used for the startup-screen.
+ * VIM_VERSION_LONG is used for the ":version" command and "Vim -h".
+ */
+#define VIM_VERSION_NODOT "vim70aa"
+#define VIM_VERSION_SHORT "7.0aa"
+#define VIM_VERSION_MEDIUM "7.0aa ALPHA"
+#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2004 June 7)"
+#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2004 June 7, compiled "
diff --git a/src/vim.def b/src/vim.def
new file mode 100644
index 000000000..fec09c719
--- /dev/null
+++ b/src/vim.def
@@ -0,0 +1,4 @@
+CODE PRELOAD EXECUTEONLY
+DATA MULTIPLE SHARED
+DESCRIPTION 'Vim 6.0'
+HEAPSIZE 0,0
diff --git a/src/vim.h b/src/vim.h
new file mode 100644
index 000000000..d85aa0719
--- /dev/null
+++ b/src/vim.h
@@ -0,0 +1,1788 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+#ifndef VIM__H
+# define VIM__H
+
+/* use fastcall for Borland, when compiling for Win32 (not for DOS16) */
+#if defined(__BORLANDC__) && defined(WIN32) && !defined(DEBUG)
+#if defined(FEAT_PERL) || \
+ defined(FEAT_PYTHON) || \
+ defined(FEAT_RUBY) || \
+ defined(FEAT_TCL) || \
+ defined(DYNAMIC_GETTEXT) || \
+ defined(DYNAMIC_ICONV) || \
+ defined(DYNAMIC_IME) || \
+ defined(XPM)
+# pragma option -pc
+# else
+# pragma option -pr
+# endif
+#endif
+
+/* ============ the header file puzzle (ca. 50-100 pieces) ========= */
+
+#ifdef HAVE_CONFIG_H /* GNU autoconf (or something else) was here */
+# include "auto/config.h"
+# define HAVE_PATHDEF
+
+/*
+ * Check if configure correcly managed to find sizeof(int). If this failed,
+ * it becomes zero. This is likely a problem of not being able to run the
+ * test program. Other items from configure may also be wrong then!
+ */
+# if (SIZEOF_INT == 0)
+ Error: configure did not run properly. Check auto/config.log.
+# endif
+
+/*
+ * Cygwin may have fchdir() in a newer rleease, but in most versions it
+ * doesn't work well and avoiding it keeps the binary backward compatible.
+ */
+# if defined(__CYGWIN32__) && defined(HAVE_FCHDIR)
+# undef HAVE_FCHDIR
+# endif
+#endif
+
+#ifdef __EMX__ /* hand-edited config.h for OS/2 with EMX */
+# include "os_os2_cfg.h"
+#endif
+
+/*
+ * MACOS_CLASSIC compiling for MacOS prior to MacOS X
+ * MACOS_X_UNIX compiling for MacOS X (using os_unix.c)
+ * MACOS_X compiling for MacOS X (using os_unix.c or os_mac.c)
+ * MACOS compiling for either one
+ */
+#if defined(macintosh) && !defined(MACOS_CLASSIC)
+# define MACOS_CLASSIC
+#endif
+#if defined(MACOS_X_UNIX)
+# define MACOS_X
+# ifndef HAVE_CONFIG_H
+# define UNIX
+# endif
+#endif
+#if defined(MACOS_X) || defined(MACOS_CLASSIC)
+# define MACOS
+#endif
+#if defined(MACOS_X) && defined(MACOS_CLASSIC)
+ Error: To compile for both MACOS X and Classic use a Classic Carbon
+#endif
+/* Unless made through the Makefile enforce GUI on Mac */
+#if defined(MACOS) && !defined(HAVE_CONFIG_H)
+# define FEAT_GUI_MAC
+#endif
+
+
+#if defined(FEAT_GUI_MOTIF) \
+ || defined(FEAT_GUI_GTK) \
+ || defined(FEAT_GUI_ATHENA) \
+ || defined(FEAT_GUI_MAC) \
+ || defined(FEAT_GUI_W32) \
+ || defined(FEAT_GUI_W16) \
+ || defined(FEAT_GUI_BEOS) \
+ || defined(FEAT_GUI_AMIGA) \
+ || defined(FEAT_GUI_PHOTON)
+# ifndef FEAT_GUI
+# define FEAT_GUI
+# endif
+#endif
+
+#if defined(FEAT_GUI_W32) || defined(FEAT_GUI_W16)
+# define FEAT_GUI_MSWIN
+#endif
+#if defined(WIN16) || defined(WIN32) || defined(_WIN64)
+# define MSWIN
+#endif
+/* Practically everything is common to both Win32 and Win64 */
+#if defined(WIN32) || defined(_WIN64)
+# define WIN3264
+#endif
+
+/*
+ * SIZEOF_INT is used in feature.h, and the system-specific included files
+ * need items from feature.h. Therefore define SIZEOF_INT here.
+ */
+#ifdef WIN3264
+# define SIZEOF_INT 4
+#endif
+#ifdef MSDOS
+# ifdef DJGPP
+# ifndef FEAT_GUI_GTK /* avoid problems when generating prototypes */
+# define SIZEOF_INT 4 /* 32 bit ints */
+# endif
+# define DOS32
+# define FEAT_CLIPBOARD
+# else
+# ifndef FEAT_GUI_GTK /* avoid problems when generating prototypes */
+# define SIZEOF_INT 2 /* 16 bit ints */
+# endif
+# define SMALL_MALLOC /* 16 bit storage allocation */
+# define DOS16
+# endif
+#endif
+
+#ifdef AMIGA
+ /* Be conservative about sizeof(int). It could be 4 too. */
+# ifndef FEAT_GUI_GTK /* avoid problems when generating prototypes */
+# ifdef __GNUC__
+# define SIZEOF_INT 4
+# else
+# define SIZEOF_INT 2
+# endif
+# endif
+#endif
+#ifdef MACOS
+# if defined(__POWERPC__) || defined(__fourbyteints__) \
+ || defined(__MRC__) || defined(__SC__) || defined(__APPLE_CC__)/* MPW Compilers */
+# define SIZEOF_INT 4
+# else
+# define SIZEOF_INT 2
+# endif
+#endif
+#ifdef RISCOS
+# define SIZEOF_INT 4
+#endif
+
+
+#include "feature.h" /* #defines for optionals and features */
+
+/* +x11 is only enabled when it's both available and wanted. */
+#if defined(HAVE_X11) && defined(WANT_X11)
+# define FEAT_X11
+#endif
+
+/* Can't use "PACKAGE" here, conflicts with a Perl include file. */
+#ifndef VIMPACKAGE
+# define VIMPACKAGE "vim"
+#endif
+
+/*
+ * Find out if function definitions should include argument types
+ */
+#ifdef AZTEC_C
+# include <functions.h>
+# define __ARGS(x) x
+#endif
+
+#ifdef SASC
+# include <clib/exec_protos.h>
+# define __ARGS(x) x
+#endif
+
+#ifdef _DCC
+# include <clib/exec_protos.h>
+# define __ARGS(x) x
+#endif
+
+#ifdef __TURBOC__
+# define __ARGS(x) x
+#endif
+
+#ifdef __BEOS__
+# include "os_beos.h"
+# define __ARGS(x) x
+#endif
+
+#if (defined(UNIX) || defined(__EMX__) || defined(VMS)) \
+ && (!defined(MACOS_X) || defined(HAVE_CONFIG_H))
+# include "os_unix.h" /* bring lots of system header files */
+#endif
+
+#if defined(MACOS) && (defined(__MRC__) || defined(__SC__))
+ /* Apple's Compilers support prototypes */
+# define __ARGS(x) x
+#endif
+#ifndef __ARGS
+# if defined(__STDC__) || defined(__GNUC__) || defined(WIN3264)
+# define __ARGS(x) x
+# else
+# define __ARGS(x) ()
+# endif
+#endif
+
+/* __ARGS and __PARMS are the same thing. */
+#ifndef __PARMS
+# define __PARMS(x) __ARGS(x)
+#endif
+
+#if defined(UNIX) && !defined(MACOS_X) /* MACOS_X doesn't yet support osdef.h */
+# include "auto/osdef.h" /* bring missing declarations in */
+#endif
+
+#ifdef __EMX__
+# define getcwd _getcwd2
+# define chdir _chdir2
+# undef CHECK_INODE
+#endif
+
+#ifdef AMIGA
+# include "os_amiga.h"
+#endif
+
+#ifdef MSDOS
+# include "os_msdos.h"
+#endif
+
+#ifdef WIN16
+# include "os_win16.h"
+#endif
+
+#ifdef WIN3264
+# include "os_win32.h"
+#endif
+
+#ifdef __MINT__
+# include "os_mint.h"
+#endif
+
+#if defined(MACOS)
+# if defined(__MRC__) || defined(__SC__) /* MPW Compilers */
+# define HAVE_SETENV
+# endif
+# include "os_mac.h"
+#endif
+
+#ifdef RISCOS
+# include "os_riscos.h"
+#endif
+
+#ifdef __QNX__
+# include "os_qnx.h"
+#endif
+
+#ifdef FEAT_SUN_WORKSHOP
+# include "workshop.h"
+#endif
+
+#ifdef X_LOCALE
+# include <X11/Xlocale.h>
+#else
+# ifdef HAVE_LOCALE_H
+# include <locale.h>
+# endif
+#endif
+
+/*
+ * Maximum length of a path (for non-unix systems) Make it a bit long, to stay
+ * on the safe side. But not too long to put on the stack.
+ */
+#ifndef MAXPATHL
+# ifdef MAXPATHLEN
+# define MAXPATHL MAXPATHLEN
+# else
+# define MAXPATHL 256
+# endif
+#endif
+#ifdef BACKSLASH_IN_FILENAME
+# define PATH_ESC_CHARS ((char_u *)" *?[{`%#")
+#else
+# ifdef COLON_AS_PATHSEP
+# define PATH_ESC_CHARS ((char_u *)" *?[{`$%#/")
+# else
+# define PATH_ESC_CHARS ((char_u *)" *?[{`$\\%#'\"|")
+# endif
+#endif
+
+#define NUMBUFLEN 30 /* length of a buffer to store a number in ASCII */
+
+/*
+ * Shorthand for unsigned variables. Many systems, but not all, have u_char
+ * already defined, so we use char_u to avoid trouble.
+ */
+typedef unsigned char char_u;
+typedef unsigned short short_u;
+typedef unsigned int int_u;
+/* Make sure long_u is big enough to hold a pointer. On Win64 longs are 32
+ * bit and pointers 64 bit. */
+#ifdef _WIN64
+typedef unsigned __int64 long_u;
+#else
+typedef unsigned long long_u;
+#endif
+
+/*
+ * The characters and attributes cached for the screen.
+ * Currently a single byte. The attributes may become larger some day.
+ */
+#define schar_T char_u
+#define sattr_T char_u
+
+/*
+ * The u8char_T can hold one decoded UTF-8 character.
+ * Vim always use an int (32 bits) for characters most places, so that we can
+ * handle 32 bit characters in the file. u8char_T is only used for
+ * displaying. That should be enough, because there is no font for > 16 bits.
+ */
+#ifdef FEAT_MBYTE
+typedef unsigned short u8char_T;
+#endif
+
+#ifndef UNIX /* For Unix this is included in os_unix.h */
+# include <stdio.h>
+# include <ctype.h>
+#endif
+
+#include "ascii.h"
+#include "keymap.h"
+#include "term.h"
+#include "macros.h"
+
+#ifdef LATTICE
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif
+#ifdef _DCC
+# include <sys/stat.h>
+#endif
+#if defined(MSDOS) || defined(MSWIN)
+# include <sys/stat.h>
+#endif
+
+/*
+ * Allow other (non-unix) systems to configure themselves now
+ * These are also in os_unix.h, because osdef.sh needs them there.
+ */
+#ifndef UNIX
+/* Note: Some systems need both string.h and strings.h (Savage). If the
+ * system can't handle this, define NO_STRINGS_WITH_STRING_H. */
+# ifdef HAVE_STRING_H
+# include <string.h>
+# endif
+# if defined(HAVE_STRINGS_H) && !defined(NO_STRINGS_WITH_STRING_H)
+# include <strings.h>
+# endif
+# ifdef HAVE_STAT_H
+# include <stat.h>
+# endif
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif /* NON-UNIX */
+
+#include <assert.h>
+
+/* ================ end of the header file puzzle =============== */
+
+/*
+ * For dynamically loaded imm library. Currently, only for Win32.
+ */
+#ifdef DYNAMIC_IME
+# ifndef FEAT_MBYTE_IME
+# define FEAT_MBYTE_IME
+# endif
+#endif
+
+/*
+ * Check input method control.
+ */
+#if defined(FEAT_XIM) || \
+ (defined(FEAT_GUI) && (defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME)))
+# define USE_IM_CONTROL
+#endif
+
+/*
+ * For dynamically loaded gettext library. Currently, only for Win32.
+ */
+#ifdef DYNAMIC_GETTEXT
+# ifndef FEAT_GETTEXT
+# define FEAT_GETTEXT
+# endif
+/* These are in os_win32.c */
+extern char* (*dyn_libintl_gettext)(const char* msgid);
+extern char* (*dyn_libintl_bindtextdomain)(const char* domainname, const char* dirname);
+extern char* (*dyn_libintl_textdomain)(const char* domainname);
+#endif
+
+
+/*
+ * The _() stuff is for using gettext(). It is a no-op when libintl.h is not
+ * found or the +multilang feature is disabled.
+ */
+#ifdef FEAT_GETTEXT
+# ifdef DYNAMIC_GETTEXT
+# define _(x) (*dyn_libintl_gettext)((char *)(x))
+# define N_(x) x
+# define bindtextdomain(domain,dir) (*dyn_libintl_bindtextdomain)(domain,dir)
+# define textdomain(domain) (*dyn_libintl_textdomain)(domain)
+# else
+# include <libintl.h>
+# define _(x) gettext((char *)(x))
+# ifdef gettext_noop
+# define N_(x) gettext_noop(x)
+# else
+# define N_(x) x
+# endif
+# endif
+#else
+# define _(x) ((char *)(x))
+# define N_(x) x
+# ifdef bindtextdomain
+# undef bindtextdomain
+# endif
+# define bindtextdomain(x, y) /* empty */
+# ifdef textdomain
+# undef textdomain
+# endif
+# define textdomain(x) /* empty */
+#endif
+
+/*
+ * flags for update_screen()
+ * The higher the value, the higher the priority
+ */
+#define VALID 10 /* buffer not changed, or changes marked
+ with b_mod_* */
+#define INVERTED 20 /* redisplay inverted part that changed */
+#define INVERTED_ALL 25 /* redisplay whole inverted part */
+#define REDRAW_TOP 30 /* display first w_upd_rows screen lines */
+#define NOT_VALID 40 /* buffer needs complete redraw */
+#define CLEAR 50 /* screen messed up, clear it */
+
+/*
+ * Hints used to optimize screen updating.
+ */
+#define HINT_NONE 0 /* no current hint */
+#define HINT_DEL_CHAR 1 /* delete character */
+#define HINT_INS_CHAR 2 /* insert character */
+
+/*
+ * Flags for w_valid.
+ * These are set when something in a window structure becomes invalid, except
+ * when the cursor is moved. Call check_cursor_moved() before testing one of
+ * the flags.
+ * These are reset when that thing has been updated and is valid again.
+ *
+ * Every function that invalidates one of these must call one of the
+ * invalidate_* functions.
+ *
+ * w_valid is supposed to be used only in screen.c. From other files, use the
+ * functions that set or reset the flags.
+ *
+ * VALID_BOTLINE VALID_BOTLINE_AP
+ * on on w_botline valid
+ * off on w_botline approximated
+ * off off w_botline not valid
+ * on off not possible
+ */
+#define VALID_WROW 0x01 /* w_wrow (window row) is valid */
+#define VALID_WCOL 0x02 /* w_wcol (window col) is valid */
+#define VALID_VIRTCOL 0x04 /* w_virtcol (file col) is valid */
+#define VALID_CHEIGHT 0x08 /* w_cline_height and w_cline_folded valid */
+#define VALID_CROW 0x10 /* w_cline_row is valid */
+#define VALID_BOTLINE 0x20 /* w_botine and w_empty_rows are valid */
+#define VALID_BOTLINE_AP 0x40 /* w_botine is approximated */
+#define VALID_TOPLINE 0x80 /* w_topline is valid (for cursor position) */
+
+/*
+ * Terminal highlighting attribute bits.
+ * Attibutes above HL_ALL are used for syntax highlighting.
+ */
+#define HL_NORMAL 0x00
+#define HL_INVERSE 0x01
+#define HL_BOLD 0x02
+#define HL_ITALIC 0x04
+#define HL_UNDERLINE 0x08
+#define HL_STANDOUT 0x10
+#define HL_ALL 0x1f
+
+/* special attribute addition: Put message in history */
+#define MSG_HIST 0x1000
+
+/*
+ * values for State
+ *
+ * The lower bits up to 0x20 are used to distinguish normal/visual/op_pending
+ * and cmdline/insert+replace mode. This is used for mapping. If none of
+ * these bits are set, no mapping is done.
+ * The upper bits are used to distinguish between other states.
+ */
+#define NORMAL 0x01 /* Normal mode, command expected */
+#define VISUAL 0x02 /* Visual mode - use get_real_state() */
+#define OP_PENDING 0x04 /* Normal mode, operator is pending - use
+ get_real_state() */
+#define CMDLINE 0x08 /* Editing command line */
+#define INSERT 0x10 /* Insert mode */
+#define LANGMAP 0x20 /* Language mapping, can be combined with
+ INSERT and CMDLINE */
+#define MAP_ALL_MODES 0x3f /* all mode bits used for mapping */
+
+#define REPLACE_FLAG 0x40 /* Replace mode flag */
+#define REPLACE (REPLACE_FLAG + INSERT)
+#ifdef FEAT_VREPLACE
+# define VREPLACE_FLAG 0x80 /* Virtual-replace mode flag */
+# define VREPLACE (REPLACE_FLAG + VREPLACE_FLAG + INSERT)
+#endif
+#define LREPLACE (REPLACE_FLAG + LANGMAP)
+
+#define NORMAL_BUSY (0x100 + NORMAL) /* Normal mode, busy with a command */
+#define HITRETURN (0x200 + NORMAL) /* waiting for return or command */
+#define ASKMORE 0x300 /* Asking if you want --more-- */
+#define SETWSIZE 0x400 /* window size has changed */
+#define ABBREV 0x500 /* abbreviation instead of mapping */
+#define EXTERNCMD 0x600 /* executing an external command */
+#define SHOWMATCH (0x700 + INSERT) /* show matching paren */
+#define CONFIRM 0x800 /* ":confirm" prompt */
+
+/* directions */
+#define FORWARD 1
+#define BACKWARD (-1)
+#define FORWARD_FILE 3
+#define BACKWARD_FILE (-3)
+
+/* return values for functions */
+#if !(defined(OK) && (OK == 1))
+/* OK already defined to 1 in MacOS X curses, skip this */
+# define OK 1
+#endif
+#define FAIL 0
+
+/* flags for b_flags */
+#define BF_RECOVERED 0x01 /* buffer has been recovered */
+#define BF_CHECK_RO 0x02 /* need to check readonly when loading file
+ into buffer (set by ":e", may be reset by
+ ":buf" */
+#define BF_NEVERLOADED 0x04 /* file has never been loaded into buffer,
+ many variables still need to be set */
+#define BF_NOTEDITED 0x08 /* Set when file name is changed after
+ starting to edit, reset when file is
+ written out. */
+#define BF_NEW 0x10 /* file didn't exist when editing started */
+#define BF_NEW_W 0x20 /* Warned for BF_NEW and file created */
+#define BF_READERR 0x40 /* got errors while reading the file */
+
+/* Mask to check for flags that prevent normal writing */
+#define BF_WRITE_MASK (BF_NOTEDITED + BF_NEW + BF_READERR)
+
+/*
+ * values for xp_context when doing command line completion
+ */
+#define CONTEXT_UNKNOWN (-3)
+#define EXPAND_UNSUCCESSFUL (-2)
+#define EXPAND_OK (-1)
+#define EXPAND_NOTHING 0
+#define EXPAND_COMMANDS 1
+#define EXPAND_FILES 2
+#define EXPAND_DIRECTORIES 3
+#define EXPAND_SETTINGS 4
+#define EXPAND_BOOL_SETTINGS 5
+#define EXPAND_TAGS 6
+#define EXPAND_OLD_SETTING 7
+#define EXPAND_HELP 8
+#define EXPAND_BUFFERS 9
+#define EXPAND_EVENTS 10
+#define EXPAND_MENUS 11
+#define EXPAND_SYNTAX 12
+#define EXPAND_HIGHLIGHT 13
+#define EXPAND_AUGROUP 14
+#define EXPAND_USER_VARS 15
+#define EXPAND_MAPPINGS 16
+#define EXPAND_TAGS_LISTFILES 17
+#define EXPAND_FUNCTIONS 18
+#define EXPAND_USER_FUNC 19
+#define EXPAND_EXPRESSION 20
+#define EXPAND_MENUNAMES 21
+#define EXPAND_USER_COMMANDS 22
+#define EXPAND_USER_CMD_FLAGS 23
+#define EXPAND_USER_NARGS 24
+#define EXPAND_USER_COMPLETE 25
+#define EXPAND_ENV_VARS 26
+#define EXPAND_LANGUAGE 27
+#define EXPAND_COLORS 28
+#define EXPAND_COMPILER 29
+#define EXPAND_USER_DEFINED 30
+
+/* Values for exmode_active (0 is no exmode) */
+#define EXMODE_NORMAL 1
+#define EXMODE_VIM 2
+
+/* Values for nextwild() and ExpandOne(). See ExpandOne() for meaning. */
+#define WILD_FREE 1
+#define WILD_EXPAND_FREE 2
+#define WILD_EXPAND_KEEP 3
+#define WILD_NEXT 4
+#define WILD_PREV 5
+#define WILD_ALL 6
+#define WILD_LONGEST 7
+
+#define WILD_LIST_NOTFOUND 1
+#define WILD_HOME_REPLACE 2
+#define WILD_USE_NL 4
+#define WILD_NO_BEEP 8
+#define WILD_ADD_SLASH 16
+#define WILD_KEEP_ALL 32
+#define WILD_SILENT 64
+#define WILD_ESCAPE 128
+
+/* Flags for expand_wildcards() */
+#define EW_DIR 1 /* include directory names */
+#define EW_FILE 2 /* include file names */
+#define EW_NOTFOUND 4 /* include not found names */
+#define EW_ADDSLASH 8 /* append slash to directory name */
+#define EW_KEEPALL 16 /* keep all matches */
+#define EW_SILENT 32 /* don't print "1 returned" from shell */
+/* Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND
+ * is used when executing commands and EW_SILENT for interactive expanding. */
+
+#ifdef FEAT_VERTSPLIT
+# define W_WINCOL(wp) (wp->w_wincol)
+# define W_WIDTH(wp) (wp->w_width)
+# define W_ENDCOL(wp) (wp->w_wincol + wp->w_width)
+# define W_VSEP_WIDTH(wp) (wp->w_vsep_width)
+#else
+# define W_WINCOL(wp) 0
+# define W_WIDTH(wp) Columns
+# define W_ENDCOL(wp) Columns
+# define W_VSEP_WIDTH(wp) 0
+#endif
+#ifdef FEAT_WINDOWS
+# define W_STATUS_HEIGHT(wp) (wp->w_status_height)
+# define W_WINROW(wp) (wp->w_winrow)
+#else
+# define W_STATUS_HEIGHT(wp) 0
+# define W_WINROW(wp) 0
+#endif
+
+#ifdef NO_EXPANDPATH
+# define gen_expand_wildcards mch_expand_wildcards
+#endif
+
+/* Values for the find_pattern_in_path() function args 'type' and 'action': */
+#define FIND_ANY 1
+#define FIND_DEFINE 2
+#define CHECK_PATH 3
+
+#define ACTION_SHOW 1
+#define ACTION_GOTO 2
+#define ACTION_SPLIT 3
+#define ACTION_SHOW_ALL 4
+#ifdef FEAT_INS_EXPAND
+# define ACTION_EXPAND 5
+#endif
+
+#ifdef FEAT_SYN_HL
+# define SST_MIN_ENTRIES 150 /* minimal size for state stack array */
+# ifdef FEAT_GUI_W16
+# define SST_MAX_ENTRIES 500 /* (only up to 64K blocks) */
+# else
+# define SST_MAX_ENTRIES 1000 /* maximal size for state stack array */
+# endif
+# define SST_FIX_STATES 7 /* size of sst_stack[]. */
+# define SST_DIST 16 /* normal distance between entries */
+# define SST_INVALID (synstate_T *)-1 /* invalid syn_state pointer */
+#endif
+
+/* Values for 'options' argument in do_search() and searchit() */
+#define SEARCH_REV 0x01 /* go in reverse of previous dir. */
+#define SEARCH_ECHO 0x02 /* echo the search command and handle options */
+#define SEARCH_MSG 0x0c /* give messages (yes, it's not 0x04) */
+#define SEARCH_NFMSG 0x08 /* give all messages except not found */
+#define SEARCH_OPT 0x10 /* interpret optional flags */
+#define SEARCH_HIS 0x20 /* put search pattern in history */
+#define SEARCH_END 0x40 /* put cursor at end of match */
+#define SEARCH_NOOF 0x80 /* don't add offset to position */
+#define SEARCH_START 0x100 /* start search without col offset */
+#define SEARCH_MARK 0x200 /* set previous context mark */
+#define SEARCH_KEEP 0x400 /* keep previous search pattern */
+#define SEARCH_PEEK 0x800 /* peek for typed char, cancel search */
+
+/* Values for find_ident_under_cursor() */
+#define FIND_IDENT 1 /* find identifier (word) */
+#define FIND_STRING 2 /* find any string (WORD) */
+#define FIND_EVAL 4 /* include "->", "[]" and "." */
+
+/* Values for file_name_in_line() */
+#define FNAME_MESS 1 /* give error message */
+#define FNAME_EXP 2 /* expand to path */
+#define FNAME_HYP 4 /* check for hypertext link */
+#define FNAME_INCL 8 /* apply 'includeexpr' */
+#define FNAME_REL 16 /* ".." and "./" are relative to the (current)
+ file instead of the current directory */
+
+/* Values for buflist_getfile() */
+#define GETF_SETMARK 0x01 /* set pcmark before jumping */
+#define GETF_ALT 0x02 /* jumping to alternate file (not buf num) */
+#define GETF_SWITCH 0x04 /* respect 'switchbuf' settings when jumping */
+
+/* Values for buflist_new() flags */
+#define BLN_CURBUF 1 /* May re-use curbuf for new buffer */
+#define BLN_LISTED 2 /* Put new buffer in buffer list */
+#define BLN_DUMMY 4 /* Allocating dummy buffer */
+#define BLN_FORCE 8 /* Don't abort on error */
+
+/* Values for in_cinkeys() */
+#define KEY_OPEN_FORW 0x101
+#define KEY_OPEN_BACK 0x102
+#define KEY_COMPLETE 0x103 /* end of completion */
+
+/* Values for "noremap" argument of ins_typebuf(). Also used for
+ * map->m_noremap and menu->noremap[]. */
+#define REMAP_YES 0 /* allow remapping */
+#define REMAP_NONE -1 /* no remapping */
+#define REMAP_SCRIPT -2 /* remap script-local mappings only */
+
+/* Values for mch_call_shell() second argument */
+#define SHELL_FILTER 1 /* filtering text */
+#define SHELL_EXPAND 2 /* expanding wildcards */
+#define SHELL_COOKED 4 /* set term to cooked mode */
+#define SHELL_DOOUT 8 /* redirecting output */
+#define SHELL_SILENT 16 /* don't print error returned by command */
+
+/* Values returned by mch_nodetype() */
+#define NODE_NORMAL 0 /* file or directory, check with mch_isdir()*/
+#define NODE_WRITABLE 1 /* something we can write to (character
+ device, fifo, socket, ..) */
+#define NODE_OTHER 2 /* non-writable thing (e.g., block device) */
+
+/* Values for readfile() flags */
+#define READ_NEW 0x01 /* read a file into a new buffer */
+#define READ_FILTER 0x02 /* read filter output */
+#define READ_STDIN 0x04 /* read from stdin */
+#define READ_BUFFER 0x08 /* read from curbuf (converting stdin) */
+#define READ_DUMMY 0x10 /* reading into a dummy buffer */
+
+/* Values for change_indent() */
+#define INDENT_SET 1 /* set indent */
+#define INDENT_INC 2 /* increase indent */
+#define INDENT_DEC 3 /* decrease indent */
+
+/* Values for flags argument for findmatchlimit() */
+#define FM_BACKWARD 0x01 /* search backwards */
+#define FM_FORWARD 0x02 /* search forwards */
+#define FM_BLOCKSTOP 0x04 /* stop at start/end of block */
+#define FM_SKIPCOMM 0x08 /* skip comments */
+
+/* Values for action argument for do_buffer() */
+#define DOBUF_GOTO 0 /* go to specified buffer */
+#define DOBUF_SPLIT 1 /* split window and go to specified buffer */
+#define DOBUF_UNLOAD 2 /* unload specified buffer(s) */
+#define DOBUF_DEL 3 /* delete specified buffer(s) from buflist */
+#define DOBUF_WIPE 4 /* delete specified buffer(s) really */
+
+/* Values for start argument for do_buffer() */
+#define DOBUF_CURRENT 0 /* "count" buffer from current buffer */
+#define DOBUF_FIRST 1 /* "count" buffer from first buffer */
+#define DOBUF_LAST 2 /* "count" buffer from last buffer */
+#define DOBUF_MOD 3 /* "count" mod. buffer from current buffer */
+
+/* Values for sub_cmd and which_pat argument for search_regcomp() */
+/* Also used for which_pat argument for searchit() */
+#define RE_SEARCH 0 /* save/use pat in/from search_pattern */
+#define RE_SUBST 1 /* save/use pat in/from subst_pattern */
+#define RE_BOTH 2 /* save pat in both patterns */
+#define RE_LAST 2 /* use last used pattern if "pat" is NULL */
+
+/* Second argument for vim_regcomp(). */
+#define RE_MAGIC 1 /* 'magic' option */
+#define RE_STRING 2 /* match in string instead of buffer text */
+
+#ifdef FEAT_SYN_HL
+/* values for reg_do_extmatch */
+# define REX_SET 1 /* to allow \z\(...\), */
+# define REX_USE 2 /* to allow \z\1 et al. */
+#endif
+
+/* Return values for fullpathcmp() */
+/* Note: can use (fullpathcmp() & FPC_SAME) to check for equal files */
+#define FPC_SAME 1 /* both exist and are the same file. */
+#define FPC_DIFF 2 /* both exist and are different files. */
+#define FPC_NOTX 4 /* both don't exist. */
+#define FPC_DIFFX 6 /* one of them doesn't exist. */
+#define FPC_SAMEX 7 /* both don't exist and file names are same. */
+
+/* flags for do_ecmd() */
+#define ECMD_HIDE 0x01 /* don't free the current buffer */
+#define ECMD_SET_HELP 0x02 /* set b_help flag of (new) buffer before
+ opening file */
+#define ECMD_OLDBUF 0x04 /* use existing buffer if it exists */
+#define ECMD_FORCEIT 0x08 /* ! used in Ex command */
+#define ECMD_ADDBUF 0x10 /* don't edit, just add to buffer list */
+
+/* for lnum argument in do_ecmd() */
+#define ECMD_LASTL (linenr_T)0 /* use last position in loaded file */
+#define ECMD_LAST (linenr_T)-1 /* use last position in all files */
+#define ECMD_ONE (linenr_T)1 /* use first line */
+
+/* flags for do_cmdline() */
+#define DOCMD_VERBOSE 0x01 /* included command in error message */
+#define DOCMD_NOWAIT 0x02 /* don't call wait_return() and friends */
+#define DOCMD_REPEAT 0x04 /* repeat exec. until getline() returns NULL */
+#define DOCMD_KEYTYPED 0x08 /* don't reset KeyTyped */
+#define DOCMD_EXCRESET 0x10 /* reset exception environment (for debugging)*/
+#define DOCMD_KEEPLINE 0x20 /* keep typed line for repeating with "." */
+
+/* flags for beginline() */
+#define BL_WHITE 1 /* cursor on first non-white in the line */
+#define BL_SOL 2 /* use 'sol' option */
+#define BL_FIX 4 /* don't leave cursor on a NUL */
+
+/* flags for mf_sync() */
+#define MFS_ALL 1 /* also sync blocks with negative numbers */
+#define MFS_STOP 2 /* stop syncing when a character is available */
+#define MFS_FLUSH 4 /* flushed file to disk */
+#define MFS_ZERO 8 /* only write block 0 */
+
+/* flags for buf_copy_options() */
+#define BCO_ENTER 1 /* going to enter the buffer */
+#define BCO_ALWAYS 2 /* always copy the options */
+#define BCO_NOHELP 4 /* don't touch the help related options */
+
+/* flags for do_put() */
+#define PUT_FIXINDENT 1 /* make indent look nice */
+#define PUT_CURSEND 2 /* leave cursor after end of new text */
+#define PUT_LINE 4 /* put register as lines */
+#define PUT_LINE_SPLIT 8 /* split line for linewise register */
+#define PUT_LINE_FORWARD 16 /* put linewise register below Visual sel. */
+
+/* flags for set_indent() */
+#define SIN_CHANGED 1 /* call changed_bytes() when line changed */
+#define SIN_INSERT 2 /* insert indent before existing text */
+#define SIN_UNDO 4 /* save line for undo before changing it */
+
+/* flags for insertchar() */
+#define INSCHAR_FORMAT 1 /* force formatting */
+#define INSCHAR_DO_COM 2 /* format comments */
+#define INSCHAR_CTRLV 4 /* char typed just after CTRL-V */
+
+/* flags for open_line() */
+#define OPENLINE_DELSPACES 1 /* delete spaces after cursor */
+#define OPENLINE_DO_COM 2 /* format comments */
+#define OPENLINE_KEEPTRAIL 4 /* keep trailing spaces */
+#define OPENLINE_MARKFIX 8 /* fix mark positions */
+
+/*
+ * There are four history tables:
+ */
+#define HIST_CMD 0 /* colon commands */
+#define HIST_SEARCH 1 /* search commands */
+#define HIST_EXPR 2 /* expressions (from entering = register) */
+#define HIST_INPUT 3 /* input() lines */
+#define HIST_DEBUG 4 /* debug commands */
+#define HIST_COUNT 5 /* number of history tables */
+
+/*
+ * Flags for chartab[].
+ */
+#define CT_CELL_MASK 0x07 /* mask: nr of display cells (1, 2 or 4) */
+#define CT_PRINT_CHAR 0x10 /* flag: set for printable chars */
+#define CT_ID_CHAR 0x20 /* flag: set for ID chars */
+#define CT_FNAME_CHAR 0x40 /* flag: set for file name chars */
+
+/*
+ * Values for do_tag().
+ */
+#define DT_TAG 1 /* jump to newer position or same tag again */
+#define DT_POP 2 /* jump to older position */
+#define DT_NEXT 3 /* jump to next match of same tag */
+#define DT_PREV 4 /* jump to previous match of same tag */
+#define DT_FIRST 5 /* jump to first match of same tag */
+#define DT_LAST 6 /* jump to first match of same tag */
+#define DT_SELECT 7 /* jump to selection from list */
+#define DT_HELP 8 /* like DT_TAG, but no wildcards */
+#define DT_JUMP 9 /* jump to new tag or selection from list */
+#define DT_CSCOPE 10 /* cscope find command (like tjump) */
+
+/*
+ * flags for find_tags().
+ */
+#define TAG_HELP 1 /* only search for help tags */
+#define TAG_NAMES 2 /* only return name of tag */
+#define TAG_REGEXP 4 /* use tag pattern as regexp */
+#define TAG_NOIC 8 /* don't always ignore case */
+#ifdef FEAT_CSCOPE
+# define TAG_CSCOPE 16 /* cscope tag */
+#endif
+#define TAG_VERBOSE 32 /* message verbosity */
+#define TAG_INS_COMP 64 /* Currently doing insert completion */
+#define TAG_KEEP_LANG 128 /* keep current language */
+
+#define TAG_MANY 200 /* When finding many tags (for completion),
+ find up to this many tags */
+
+/*
+ * Types of dialogs passed to do_vim_dialog().
+ */
+#define VIM_GENERIC 0
+#define VIM_ERROR 1
+#define VIM_WARNING 2
+#define VIM_INFO 3
+#define VIM_QUESTION 4
+#define VIM_LAST_TYPE 4 /* sentinel value */
+
+/*
+ * Return values for functions like gui_yesnocancel()
+ */
+#define VIM_OK 1
+#define VIM_YES 2
+#define VIM_NO 3
+#define VIM_CANCEL 4
+#define VIM_ALL 5
+#define VIM_DISCARDALL 6
+
+/*
+ * arguments for win_split()
+ */
+#define WSP_ROOM 1 /* require enough room */
+#define WSP_VERT 2 /* split vertically */
+#define WSP_TOP 4 /* window at top-left of shell */
+#define WSP_BOT 8 /* window at bottom-right of shell */
+#define WSP_HELP 16 /* creating the help window */
+#define WSP_BELOW 32 /* put new window below/right */
+#define WSP_ABOVE 64 /* put new window above/left */
+
+/*
+ * "flags" values for option-setting functions.
+ * When OPT_GLOBAL and OPT_LOCAL are both missing, set both local and global
+ * values, get local value.
+ */
+#define OPT_FREE 1 /* free old value if it was allocated */
+#define OPT_GLOBAL 2 /* use global value */
+#define OPT_LOCAL 4 /* use local value */
+#define OPT_MODELINE 8 /* option in modeline */
+
+/* Magic chars used in confirm dialog strings */
+#define DLG_BUTTON_SEP '\n'
+#define DLG_HOTKEY_CHAR '&'
+
+/* Values for "starting" */
+#define NO_SCREEN 2 /* no screen updating yet */
+#define NO_BUFFERS 1 /* not all buffers loaded yet */
+/* 0 not starting anymore */
+
+/* Values for swap_exists_action: what to do when swap file already exists */
+#define SEA_NONE 0 /* don't use dialog */
+#define SEA_DIALOG 1 /* use dialog when */
+#define SEA_QUIT 2 /* quit editing the file */
+#define SEA_RECOVER 3 /* recover the file */
+
+/*
+ * Minimal size for block 0 of a swap file.
+ * NOTE: This depends on size of struct block0! It's not done with a sizeof(),
+ * because struct block0 is defined in memline.c (Sorry).
+ * The maximal block size is arbitrary.
+ */
+#define MIN_SWAP_PAGE_SIZE 1048
+#define MAX_SWAP_PAGE_SIZE 50000
+
+/* Special values for current_SID. */
+#define SID_MODELINE -1 /* when using a modeline */
+#define SID_CMDARG -2 /* for "--cmd" argument */
+#define SID_CARG -3 /* for "-c" argument */
+#define SID_ENV -4 /* for sourcing environment variable */
+
+/*
+ * Events for autocommands.
+ */
+enum auto_event
+{
+ EVENT_BUFADD = 0, /* after adding a buffer to the buffer list */
+ EVENT_BUFNEW, /* after creating any buffer */
+ EVENT_BUFDELETE, /* deleting a buffer from the buffer list */
+ EVENT_BUFWIPEOUT, /* just before really deleting a buffer */
+ EVENT_BUFENTER, /* after entering a buffer */
+ EVENT_BUFFILEPOST, /* after renaming a buffer */
+ EVENT_BUFFILEPRE, /* before renaming a buffer */
+ EVENT_BUFLEAVE, /* before leaving a buffer */
+ EVENT_BUFNEWFILE, /* when creating a buffer for a new file */
+ EVENT_BUFREADPOST, /* after reading a buffer */
+ EVENT_BUFREADPRE, /* before reading a buffer */
+ EVENT_BUFREADCMD, /* read buffer using command */
+ EVENT_BUFUNLOAD, /* just before unloading a buffer */
+ EVENT_BUFHIDDEN, /* just after buffer becomes hidden */
+ EVENT_BUFWINENTER, /* after showing a buffer in a window */
+ EVENT_BUFWINLEAVE, /* just after buffer removed from window */
+ EVENT_BUFWRITEPOST, /* after writing a buffer */
+ EVENT_BUFWRITEPRE, /* before writing a buffer */
+ EVENT_BUFWRITECMD, /* write buffer using command */
+ EVENT_CMDWINENTER, /* after entering the cmdline window */
+ EVENT_CMDWINLEAVE, /* before leaving the cmdline window */
+ EVENT_FILEAPPENDPOST, /* after appending to a file */
+ EVENT_FILEAPPENDPRE, /* before appending to a file */
+ EVENT_FILEAPPENDCMD, /* appende to a file using command */
+ EVENT_FILECHANGEDSHELL, /* after shell command that changed file */
+ EVENT_FILECHANGEDRO, /* before first change to read-only file */
+ EVENT_FILEREADPOST, /* after reading a file */
+ EVENT_FILEREADPRE, /* before reading a file */
+ EVENT_FILEREADCMD, /* read from a file using command */
+ EVENT_FILETYPE, /* new file type detected (user defined) */
+ EVENT_FILEWRITEPOST, /* after writing a file */
+ EVENT_FILEWRITEPRE, /* before writing a file */
+ EVENT_FILEWRITECMD, /* write to a file using command */
+ EVENT_FILTERREADPOST, /* after reading from a filter */
+ EVENT_FILTERREADPRE, /* before reading from a filter */
+ EVENT_FILTERWRITEPOST, /* after writing to a filter */
+ EVENT_FILTERWRITEPRE, /* before writing to a filter */
+ EVENT_FOCUSGAINED, /* got the focus */
+ EVENT_FOCUSLOST, /* lost the focus to another app */
+ EVENT_GUIENTER, /* after starting the GUI */
+ EVENT_STDINREADPOST, /* after reading from stdin */
+ EVENT_STDINREADPRE, /* before reading from stdin */
+ EVENT_SYNTAX, /* syntax selected */
+ EVENT_TERMCHANGED, /* after changing 'term' */
+ EVENT_TERMRESPONSE, /* after setting "v:termresponse" */
+ EVENT_USER, /* user defined autocommand */
+ EVENT_VIMENTER, /* after starting Vim */
+ EVENT_VIMLEAVE, /* before exiting Vim */
+ EVENT_VIMLEAVEPRE, /* before exiting Vim and writing .viminfo */
+ EVENT_WINENTER, /* after entering a window */
+ EVENT_WINLEAVE, /* before leaving a window */
+ EVENT_ENCODINGCHANGED, /* after changing the 'encoding' option */
+ EVENT_CURSORHOLD, /* cursor in same position for a while */
+ EVENT_FUNCUNDEFINED, /* if calling a function which doesn't exist */
+ EVENT_REMOTEREPLY, /* upon string reception from a remote vim */
+ NUM_EVENTS /* MUST be the last one */
+};
+
+typedef enum auto_event EVENT_T;
+
+/*
+ * Values for index in highlight_attr[].
+ * When making changes, also update HL_FLAGS below! And update the default
+ * value of 'highlight' in option.c.
+ */
+enum hlf_value
+{
+ HLF_8 = 0 /* Meta & special keys listed with ":map", text that is
+ displayed different from what it is */
+ , HLF_AT /* @ and ~ characters at end of screen, characters that
+ don't really exist in the text */
+ , HLF_D /* directories in CTRL-D listing */
+ , HLF_E /* error messages */
+ , HLF_H /* obsolete, ignored */
+ , HLF_I /* incremental search */
+ , HLF_L /* last search string */
+ , HLF_M /* "--More--" message */
+ , HLF_CM /* Mode (e.g., "-- INSERT --") */
+ , HLF_N /* line number for ":number" and ":#" commands */
+ , HLF_R /* return to continue message and yes/no questions */
+ , HLF_S /* status lines */
+ , HLF_SNC /* status lines of not-current windows */
+ , HLF_C /* column to separate vertically split windows */
+ , HLF_T /* Titles for output from ":set all", ":autocmd" etc. */
+ , HLF_V /* Visual mode */
+ , HLF_VNC /* Visual mode, autoselecting and not clipboard owner */
+ , HLF_W /* warning messages */
+ , HLF_WM /* Wildmenu highlight */
+ , HLF_FL /* Folded line */
+ , HLF_FC /* Fold column */
+ , HLF_ADD /* Added diff line */
+ , HLF_CHD /* Changed diff line */
+ , HLF_DED /* Deleted diff line */
+ , HLF_TXD /* Text Changed in diff line */
+ , HLF_SC /* Sign column */
+ , HLF_COUNT /* MUST be the last one */
+};
+
+/* the HL_FLAGS must be in the same order as the HLF_ enums! */
+#define HL_FLAGS {'8', '@', 'd', 'e', 'h', 'i', 'l', 'm', 'M', \
+ 'n', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', \
+ 'f', 'F', 'A', 'C', 'D', 'T', '>'}
+
+/*
+ * Boolean constants
+ */
+#ifndef TRUE
+# define FALSE 0 /* note: this is an int, not a long! */
+# define TRUE 1
+#endif
+
+#define MAYBE 2 /* sometimes used for a variant on TRUE */
+
+/* May be returned by add_new_completion(): */
+#define RET_ERROR (-1)
+
+/*
+ * Operator IDs; The order must correspond to opchars[] in ops.c!
+ */
+#define OP_NOP 0 /* no pending operation */
+#define OP_DELETE 1 /* "d" delete operator */
+#define OP_YANK 2 /* "y" yank operator */
+#define OP_CHANGE 3 /* "c" change operator */
+#define OP_LSHIFT 4 /* "<" left shift operator */
+#define OP_RSHIFT 5 /* ">" right shift operator */
+#define OP_FILTER 6 /* "!" filter operator */
+#define OP_TILDE 7 /* "g~" switch case operator */
+#define OP_INDENT 8 /* "=" indent operator */
+#define OP_FORMAT 9 /* "gq" format operator */
+#define OP_COLON 10 /* ":" colon operator */
+#define OP_UPPER 11 /* "gU" make upper case operator */
+#define OP_LOWER 12 /* "gu" make lower case operator */
+#define OP_JOIN 13 /* "J" join operator, only for Visual mode */
+#define OP_JOIN_NS 14 /* "gJ" join operator, only for Visual mode */
+#define OP_ROT13 15 /* "g?" rot-13 encoding */
+#define OP_REPLACE 16 /* "r" replace chars, only for Visual mode */
+#define OP_INSERT 17 /* "I" Insert column, only for Visual mode */
+#define OP_APPEND 18 /* "A" Append column, only for Visual mode */
+#define OP_FOLD 19 /* "zf" define a fold */
+#define OP_FOLDOPEN 20 /* "zo" open folds */
+#define OP_FOLDOPENREC 21 /* "zO" open folds recursively */
+#define OP_FOLDCLOSE 22 /* "zc" close folds */
+#define OP_FOLDCLOSEREC 23 /* "zC" close folds recursively */
+#define OP_FOLDDEL 24 /* "zd" delete folds */
+#define OP_FOLDDELREC 25 /* "zD" delete folds recursively */
+#define OP_FORMAT2 26 /* "gw" format operator, keeps cursor pos */
+
+/*
+ * Motion types, used for operators and for yank/delete registers.
+ */
+#define MCHAR 0 /* character-wise movement/register */
+#define MLINE 1 /* line-wise movement/register */
+#define MBLOCK 2 /* block-wise register */
+
+#define MAUTO 0xff /* Decide between MLINE/MCHAR */
+
+/*
+ * Minimum screen size
+ */
+#define MIN_COLUMNS 12 /* minimal columns for screen */
+#define MIN_LINES 2 /* minimal lines for screen */
+#define STATUS_HEIGHT 1 /* height of a status line under a window */
+#define QF_WINHEIGHT 10 /* default height for quickfix window */
+
+/*
+ * Buffer sizes
+ */
+#ifndef CMDBUFFSIZE
+# define CMDBUFFSIZE 256 /* size of the command processing buffer */
+#endif
+
+#define LSIZE 512 /* max. size of a line in the tags file */
+
+#define IOSIZE (1024+1) /* file i/o and sprintf buffer size */
+#define MSG_BUF_LEN 80 /* length of buffer for small messages */
+
+#if defined(AMIGA) || defined(__linux__) || defined(__QNX__) || defined(__CYGWIN32__) || defined(_AIX)
+# define TBUFSZ 2048 /* buffer size for termcap entry */
+#else
+# define TBUFSZ 1024 /* buffer size for termcap entry */
+#endif
+
+/*
+ * Maximum length of key sequence to be mapped.
+ * Must be able to hold an Amiga resize report.
+ */
+#define MAXMAPLEN 50
+
+#ifdef BINARY_FILE_IO
+# define WRITEBIN "wb" /* no CR-LF translation */
+# define READBIN "rb"
+# define APPENDBIN "ab"
+#else
+# define WRITEBIN "w"
+# define READBIN "r"
+# define APPENDBIN "a"
+#endif
+
+/*
+ * EMX doesn't have a global way of making open() use binary I/O.
+ * Use O_BINARY for all open() calls.
+ */
+#if defined(__EMX__) || defined(__CYGWIN32__)
+# define O_EXTRA O_BINARY
+#else
+# define O_EXTRA 0
+#endif
+
+#ifndef W_OK
+# define W_OK 2 /* for systems that don't have W_OK in unistd.h */
+#endif
+#ifndef R_OK
+# define R_OK 4 /* for systems that don't have R_OK in unistd.h */
+#endif
+
+/*
+ * defines to avoid typecasts from (char_u *) to (char *) and back
+ * (vim_strchr() and vim_strrchr() are now in alloc.c)
+ */
+#define STRLEN(s) strlen((char *)(s))
+#define STRCPY(d, s) strcpy((char *)(d), (char *)(s))
+#define STRNCPY(d, s, n) strncpy((char *)(d), (char *)(s), (size_t)(n))
+#define STRCMP(d, s) strcmp((char *)(d), (char *)(s))
+#define STRNCMP(d, s, n) strncmp((char *)(d), (char *)(s), (size_t)(n))
+#ifdef HAVE_STRCASECMP
+# define STRICMP(d, s) strcasecmp((char *)(d), (char *)(s))
+#else
+# ifdef HAVE_STRICMP
+# define STRICMP(d, s) stricmp((char *)(d), (char *)(s))
+# else
+# define STRICMP(d, s) vim_stricmp((char *)(d), (char *)(s))
+# endif
+#endif
+
+#ifdef HAVE_STRNCASECMP
+# define STRNICMP(d, s, n) strncasecmp((char *)(d), (char *)(s), (size_t)(n))
+#else
+# ifdef HAVE_STRNICMP
+# define STRNICMP(d, s, n) strnicmp((char *)(d), (char *)(s), (size_t)(n))
+# else
+# define STRNICMP(d, s, n) vim_strnicmp((char *)(d), (char *)(s), (size_t)(n))
+# endif
+#endif
+
+#ifdef FEAT_MBYTE
+# define MB_STRICMP(d, s) (has_mbyte ? mb_strnicmp((char_u *)(d), (char_u *)(s), (int)MAXCOL) : STRICMP((d), (s)))
+# define MB_STRNICMP(d, s, n) (has_mbyte ? mb_strnicmp((char_u *)(d), (char_u *)(s), (int)(n)) : STRNICMP((d), (s), (n)))
+#else
+# define MB_STRICMP(d, s) STRICMP((d), (s))
+# define MB_STRNICMP(d, s, n) STRNICMP((d), (s), (n))
+# define transchar_byte(c) transchar(c)
+#endif
+
+#define STRCAT(d, s) strcat((char *)(d), (char *)(s))
+#define STRNCAT(d, s, n) strncat((char *)(d), (char *)(s), (size_t)(n))
+
+#ifdef HAVE_STRPBRK
+# define vim_strpbrk(s, cs) (char_u *)strpbrk((char *)(s), (char *)(cs))
+#endif
+
+#define MSG(s) msg((char_u *)(s))
+#define MSG_ATTR(s, attr) msg_attr((char_u *)(s), (attr))
+#define EMSG(s) emsg((char_u *)(s))
+#define EMSG2(s, p) emsg2((char_u *)(s), (char_u *)(p))
+#define EMSG3(s, p, q) emsg3((char_u *)(s), (char_u *)(p), (char_u *)(q))
+#define EMSGN(s, n) emsgn((char_u *)(s), (long)(n))
+#define OUT_STR(s) out_str((char_u *)(s))
+#define OUT_STR_NF(s) out_str_nf((char_u *)(s))
+#define MSG_PUTS(s) msg_puts((char_u *)(s))
+#define MSG_PUTS_ATTR(s, a) msg_puts_attr((char_u *)(s), (a))
+#define MSG_PUTS_TITLE(s) msg_puts_title((char_u *)(s))
+#define MSG_PUTS_LONG(s) msg_puts_long((char_u *)(s))
+#define MSG_PUTS_LONG_ATTR(s, a) msg_puts_long_attr((char_u *)(s), (a))
+
+/* Prefer using emsg3(), because perror() may send the output to the wrong
+ * destination and mess up the screen. */
+#ifdef HAVE_STRERROR
+# define PERROR(msg) (void)emsg3((char_u *)"%s: %s", (char_u *)msg, (char_u *)strerror(errno))
+#else
+# define PERROR(msg) perror(msg)
+#endif
+
+typedef long linenr_T; /* line number type */
+typedef unsigned colnr_T; /* column number type */
+typedef unsigned short disptick_T; /* display tick type */
+
+#define MAXLNUM (0x7fffffffL) /* maximum (invalid) line number */
+
+/*
+ * Well, you won't believe it, but some S/390 machines ("host", now also known
+ * as zServer) us 31 bit pointers. There are also some newer machines, that
+ * use 64 bit pointers. I don't know how to distinguish between 31 and 64 bit
+ * machines, so the best way is to assume 31 bits whenever we detect OS/390
+ * Unix.
+ * With this we restrict the maximum line length to 1073741823. I guess this is
+ * not a real problem. BTW: Longer lines are split.
+ */
+#if SIZEOF_INT >= 4
+# ifdef __MVS__
+# define MAXCOL (0x3fffffffL) /* maximum column number, 30 bits */
+# else
+# define MAXCOL (0x7fffffffL) /* maximum column number, 31 bits */
+# endif
+#else
+# define MAXCOL (0x7fff) /* maximum column number, 15 bits */
+#endif
+
+#define SHOWCMD_COLS 10 /* columns needed by shown command */
+#define STL_MAX_ITEM 80 /* max nr of %<flag> in statusline */
+
+typedef void *vim_acl_T; /* dummy to pass an ACL to a function */
+
+/*
+ * Include a prototype for mch_memmove(), it may not be in alloc.pro.
+ */
+#ifdef VIM_MEMMOVE
+void mch_memmove __ARGS((void *, void *, size_t));
+#else
+# ifndef mch_memmove
+# define mch_memmove(to, from, len) memmove(to, from, len)
+# endif
+#endif
+
+/*
+ * fnamecmp() is used to compare file names.
+ * On some systems case in a file name does not matter, on others it does.
+ * (this does not account for maximum name lengths and things like "../dir",
+ * thus it is not 100% accurate!)
+ */
+#ifdef CASE_INSENSITIVE_FILENAME
+# ifdef BACKSLASH_IN_FILENAME
+# define fnamecmp(x, y) vim_fnamecmp((x), (y))
+# define fnamencmp(x, y, n) vim_fnamencmp((x), (y), (size_t)(n))
+# else
+# define fnamecmp(x, y) MB_STRICMP((x), (y))
+# define fnamencmp(x, y, n) MB_STRNICMP((x), (y), (n))
+# endif
+#else
+# define fnamecmp(x, y) strcmp((char *)(x), (char *)(y))
+# define fnamencmp(x, y, n) strncmp((char *)(x), (char *)(y), (size_t)(n))
+#endif
+
+#ifdef HAVE_MEMSET
+# define vim_memset(ptr, c, size) memset((ptr), (c), (size))
+#else
+void *vim_memset __ARGS((void *, int, size_t));
+#endif
+
+#ifdef HAVE_MEMCMP
+# define vim_memcmp(p1, p2, len) memcmp((p1), (p2), (len))
+#else
+# ifdef HAVE_BCMP
+# define vim_memcmp(p1, p2, len) bcmp((p1), (p2), (len))
+# else
+int vim_memcmp __ARGS((void *, void *, size_t));
+# define VIM_MEMCMP
+# endif
+#endif
+
+#if defined(UNIX) || defined(FEAT_GUI) || defined(OS2) || defined(VMS) \
+ || defined(FEAT_CLIENTSERVER)
+# define USE_INPUT_BUF
+#endif
+
+#ifdef MSWIN
+/* On MS-Windows the third argument isn't size_t. This matters for Win64,
+ * where sizeof(size_t)==8, not 4 */
+# define vim_read(fd, buf, count) read((fd), (char *)(buf), (unsigned int)(count))
+# define vim_write(fd, buf, count) write((fd), (char *)(buf), (unsigned int)(count))
+#else
+# define vim_read(fd, buf, count) read((fd), (char *)(buf), (size_t) (count))
+# define vim_write(fd, buf, count) write((fd), (char *)(buf), (size_t) (count))
+#endif
+
+/*
+ * Enums need a typecast to be used as array index (for Ultrix).
+ */
+#define hl_attr(n) highlight_attr[(int)(n)]
+#define term_str(n) term_strings[(int)(n)]
+
+/*
+ * vim_iswhite() is used for "^" and the like. It differs from isspace()
+ * because it doesn't include <CR> and <LF> and the like.
+ */
+#define vim_iswhite(x) ((x) == ' ' || (x) == '\t')
+
+/* Note that gui.h is included by structs.h */
+
+#include "structs.h" /* file that defines many structures */
+
+#ifdef FEAT_MOUSE
+
+/* Codes for mouse button events in lower three bits: */
+# define MOUSE_LEFT 0x00
+# define MOUSE_MIDDLE 0x01
+# define MOUSE_RIGHT 0x02
+# define MOUSE_RELEASE 0x03
+
+/* bit masks for modifiers: */
+# define MOUSE_SHIFT 0x04
+# define MOUSE_ALT 0x08
+# define MOUSE_CTRL 0x10
+
+/* mouse buttons that are handled like a key press (GUI only) */
+# define MOUSE_4 0x100 /* scroll wheel down */
+# define MOUSE_5 0x200 /* scroll wheel up */
+
+# define MOUSE_X1 0x300 /* Mouse-button X1 (6th) */
+# define MOUSE_X2 0x400 /* Mouse-button X2 */
+
+/* 0x20 is reserved by xterm */
+# define MOUSE_DRAG_XTERM 0x40
+
+# define MOUSE_DRAG (0x40 | MOUSE_RELEASE)
+
+/* Lowest button code for using the mouse wheel (xterm only) */
+# define MOUSEWHEEL_LOW 0x60
+
+# define MOUSE_CLICK_MASK 0x03
+
+# define NUM_MOUSE_CLICKS(code) \
+ (((unsigned)((code) & 0xC0) >> 6) + 1)
+
+# define SET_NUM_MOUSE_CLICKS(code, num) \
+ (code) = ((code) & 0x3f) | ((((num) - 1) & 3) << 6)
+
+/*
+ * jump_to_mouse() returns one of first four these values, possibly with
+ * some of the other three added.
+ */
+# define IN_UNKNOWN 0
+# define IN_BUFFER 1
+# define IN_STATUS_LINE 2 /* on status or command line */
+# define IN_SEP_LINE 4 /* on vertical separator line */
+# define IN_OTHER_WIN 8 /* in other window but can't go there */
+# define CURSOR_MOVED 0x100
+# define MOUSE_FOLD_CLOSE 0x200 /* clicked on '-' in fold column */
+# define MOUSE_FOLD_OPEN 0x400 /* clicked on '+' in fold column */
+
+/* flags for jump_to_mouse() */
+# define MOUSE_FOCUS 0x01 /* need to stay in this window */
+# define MOUSE_MAY_VIS 0x02 /* may start Visual mode */
+# define MOUSE_DID_MOVE 0x04 /* only act when mouse has moved */
+# define MOUSE_SETPOS 0x08 /* only set current mouse position */
+# define MOUSE_MAY_STOP_VIS 0x10 /* may stop Visual mode */
+# define MOUSE_RELEASED 0x20 /* button was released */
+
+# if defined(UNIX) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
+# define CHECK_DOUBLE_CLICK 1 /* Checking for double clicks ourselves. */
+# endif
+
+#endif /* FEAT_MOUSE */
+
+/* defines for eval_vars() */
+#define VALID_PATH 1
+#define VALID_HEAD 2
+
+/* Defines for Vim variables. These must match vimvars[] in eval.c! */
+#define VV_COUNT 0
+#define VV_COUNT1 1
+#define VV_PREVCOUNT 2
+#define VV_ERRMSG 3
+#define VV_WARNINGMSG 4
+#define VV_STATUSMSG 5
+#define VV_SHELL_ERROR 6
+#define VV_THIS_SESSION 7
+#define VV_VERSION 8
+#define VV_LNUM 9
+#define VV_TERMRESPONSE 10
+#define VV_FNAME 11
+#define VV_LANG 12
+#define VV_LC_TIME 13
+#define VV_CTYPE 14
+#define VV_CC_FROM 15
+#define VV_CC_TO 16
+#define VV_FNAME_IN 17
+#define VV_FNAME_OUT 18
+#define VV_FNAME_NEW 19
+#define VV_FNAME_DIFF 20
+#define VV_CMDARG 21
+#define VV_FOLDSTART 22
+#define VV_FOLDEND 23
+#define VV_FOLDDASHES 24
+#define VV_FOLDLEVEL 25
+#define VV_PROGNAME 26
+#define VV_SEND_SERVER 27
+#define VV_DYING 28
+#define VV_EXCEPTION 29
+#define VV_THROWPOINT 30
+#define VV_REG 31
+#define VV_CMDBANG 32
+#define VV_LEN 33 /* number of v: vars */
+
+#ifdef FEAT_CLIPBOARD
+
+/* VIM_ATOM_NAME is the older Vim-specific selection type for X11. Still
+ * supported for when a mix of Vim versions is used. VIMENC_ATOM_NAME includes
+ * the encoding to support Vims using different 'encoding' values. */
+#define VIM_ATOM_NAME "_VIM_TEXT"
+#define VIMENC_ATOM_NAME "_VIMENC_TEXT"
+
+/* Selection states for modeless selection */
+# define SELECT_CLEARED 0
+# define SELECT_IN_PROGRESS 1
+# define SELECT_DONE 2
+
+# define SELECT_MODE_CHAR 0
+# define SELECT_MODE_WORD 1
+# define SELECT_MODE_LINE 2
+
+# ifdef FEAT_GUI_W32
+# ifdef FEAT_OLE
+# define WM_OLE (WM_APP+0)
+# endif
+# ifdef FEAT_NETBEANS_INTG
+ /* message for Netbeans socket event */
+# define WM_NETBEANS (WM_APP+1)
+# endif
+# endif
+
+/* Info about selected text */
+typedef struct VimClipboard
+{
+ int available; /* Is clipboard available? */
+ int owned; /* Flag: do we own the selection? */
+ pos_T start; /* Start of selected area */
+ pos_T end; /* End of selected area */
+ int vmode; /* Visual mode character */
+
+ /* Fields for selection that doesn't use Visual mode */
+ short_u origin_row;
+ short_u origin_start_col;
+ short_u origin_end_col;
+ short_u word_start_col;
+ short_u word_end_col;
+
+ pos_T prev; /* Previous position */
+ short_u state; /* Current selection state */
+ short_u mode; /* Select by char, word, or line. */
+
+# if defined(FEAT_GUI_X11) || defined(FEAT_XCLIPBOARD)
+ Atom sel_atom; /* PRIMARY/CLIPBOARD selection ID */
+# endif
+
+# ifdef FEAT_GUI_GTK
+ GdkAtom gtk_sel_atom; /* PRIMARY/CLIPBOARD selection ID */
+# endif
+
+# ifdef MSWIN
+ int_u format; /* Vim's own special clipboard format */
+ int_u format_raw; /* Vim's raw text clipboard format */
+# endif
+# ifdef FEAT_GUI_BEOS
+ /* no clipboard at the moment */
+# endif
+} VimClipboard;
+#else
+typedef int VimClipboard; /* This is required for the prototypes. */
+#endif
+
+#ifdef __BORLANDC__
+/* work around a bug in the Borland 'stat' function: */
+# include <io.h> /* for access() */
+
+# define stat(a,b) (access(a,0) ? -1 : stat(a,b))
+#endif
+
+/*
+ * EXTERN is only defined in main.c. That's where global variables are
+ * actually defined and initialized.
+ */
+#ifndef EXTERN
+# define EXTERN extern
+# define INIT(x)
+#else
+# ifndef INIT
+# define INIT(x) x
+# define DO_INIT
+# endif
+#endif
+
+#include "option.h" /* option variables and defines */
+#include "ex_cmds.h" /* Ex command defines */
+#include "proto.h" /* function prototypes */
+
+/* This has to go after the include of proto.h, as proto/gui.pro declares
+ * functions of these names. The declarations would break if the defines had
+ * been seen at that stage. But it must be before globals.h, where error_ga
+ * is declared. */
+#if !defined(FEAT_GUI_W32) && !defined(FEAT_GUI_X11) \
+ && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MAC)
+# define mch_errmsg(str) fprintf(stderr, "%s", (str))
+# define display_errors() fflush(stderr)
+# define mch_msg(str) printf("%s", (str))
+#else
+# define USE_MCH_ERRMSG
+#endif
+
+#include "globals.h" /* global variables and messages */
+
+#ifdef FEAT_SNIFF
+# include "if_sniff.h"
+#endif
+
+#ifndef FEAT_VIRTUALEDIT
+# define getvvcol(w, p, s, c, e) getvcol(w, p, s, c, e)
+# define virtual_active() 0
+# define virtual_op FALSE
+#endif
+
+/*
+ * If console dialog not supported, but GUI dialog is, use the GUI one.
+ */
+#if defined(FEAT_GUI_DIALOG) && !defined(FEAT_CON_DIALOG)
+# define do_dialog gui_mch_dialog
+#endif
+
+/*
+ * Default filters for gui_mch_browse().
+ * The filters are almost system independent. Except for the difference
+ * between "*" and "*.*" for MSDOS-like systems.
+ * NOTE: Motif only uses the very first pattern. Therefore
+ * BROWSE_FILTER_DEFAULT should start with a "*" pattern.
+ */
+#ifdef FEAT_BROWSE
+# ifdef BACKSLASH_IN_FILENAME
+# define BROWSE_FILTER_MACROS \
+ (char_u *)"Vim macro files (*.vim)\t*.vim\nAll Files (*.*)\t*.*\n"
+# define BROWSE_FILTER_ALL_FILES (char_u *)"All Files (*.*)\t*.*\n"
+# define BROWSE_FILTER_DEFAULT \
+ (char_u *)"All Files (*.*)\t*.*\nC source (*.c, *.h)\t*.c;*.h\nC++ source (*.cpp, *.hpp)\t*.cpp;*.hpp\nVB code (*.bas, *.frm)\t*.bas;*.frm\nVim files (*.vim, _vimrc, _gvimrc)\t*.vim;_vimrc;_gvimrc\n"
+# else
+# define BROWSE_FILTER_MACROS \
+ (char_u *)"Vim macro files (*.vim)\t*.vim\nAll Files (*)\t*\n"
+# define BROWSE_FILTER_ALL_FILES (char_u *)"All Files (*)\t*\n"
+# define BROWSE_FILTER_DEFAULT \
+ (char_u *)"All Files (*)\t*\nC source (*.c, *.h)\t*.c;*.h\nC++ source (*.cpp, *.hpp)\t*.cpp;*.hpp\nVim files (*.vim, _vimrc, _gvimrc)\t*.vim;_vimrc;_gvimrc\n"
+# endif
+#endif
+
+/* stop using fastcall for Borland */
+#if defined(__BORLANDC__) && defined(WIN32) && !defined(DEBUG)
+# pragma option -p.
+#endif
+
+#if defined(MEM_PROFILE)
+# define vim_realloc(ptr, size) mem_realloc((ptr), (size))
+#else
+# define vim_realloc(ptr, size) realloc((ptr), (size))
+#endif
+
+/*
+ * The following macros stop displat/event loop nesting at the wrong time.
+ */
+#ifdef ALT_X_INPUT
+# define ALT_INPUT_LOCK_OFF suppress_alternate_input = FALSE
+# define ALT_INPUT_LOCK_ON suppress_alternate_input = TRUE
+#endif
+
+#ifdef FEAT_MBYTE
+/* Maximum number of bytes in a multi-byte character. It can be one 32-bit
+ * character of up to 6 bytes, or one 16-bit character of up to three bytes
+ * plus two following composing characters of three bytes each. */
+# define MB_MAXBYTES 9
+
+/*
+ * Return byte length of character that starts with byte "b".
+ * Returns 1 for a single-byte character.
+ * MB_BYTE2LEN_CHECK() can be used to count a special key as one byte.
+ * Don't call MB_BYTE2LEN(b) with b < 0 or b > 255!
+ */
+# define MB_BYTE2LEN(b) mb_bytelen_tab[b]
+# define MB_BYTE2LEN_CHECK(b) (((b) < 0 || (b) > 255) ? 1 : mb_bytelen_tab[b])
+#endif
+
+#if defined(FEAT_MBYTE) || defined(FEAT_POSTSCRIPT)
+/* properties used in enc_canon_table[] (first three mutually exclusive) */
+# define ENC_8BIT 0x01
+# define ENC_DBCS 0x02
+# define ENC_UNICODE 0x04
+
+# define ENC_ENDIAN_B 0x10 /* Unicode: Big endian */
+# define ENC_ENDIAN_L 0x20 /* Unicode: Little endian */
+
+# define ENC_2BYTE 0x40 /* Unicode: UCS-2 */
+# define ENC_4BYTE 0x80 /* Unicode: UCS-4 */
+# define ENC_2WORD 0x100 /* Unicode: UTF-16 */
+
+# define ENC_LATIN1 0x200 /* Latin1 */
+# define ENC_MACROMAN 0x400 /* Mac Roman (not Macro Man! :-) */
+#endif
+
+#ifdef FEAT_MBYTE
+# ifdef USE_ICONV
+# ifndef EILSEQ
+# define EILSEQ 123
+# endif
+# ifdef DYNAMIC_ICONV
+/* On Win32 iconv.dll is dynamically loaded. */
+# define ICONV_ERRNO (*iconv_errno())
+# define ICONV_E2BIG 7
+# define ICONV_EINVAL 22
+# define ICONV_EILSEQ 42
+# else
+# define ICONV_ERRNO errno
+# define ICONV_E2BIG E2BIG
+# define ICONV_EINVAL EINVAL
+# define ICONV_EILSEQ EILSEQ
+# endif
+# endif
+
+#endif
+
+/* ISSYMLINK(mode) tests if a file is a symbolic link. */
+#if (defined(S_IFMT) && defined(S_IFLNK)) || defined(S_ISLNK)
+# define HAVE_ISSYMLINK
+# if defined(S_IFMT) && defined(S_IFLNK)
+# define ISSYMLINK(mode) (((mode) & S_IFMT) == S_IFLNK)
+# else
+# define ISSYMLINK(mode) S_ISLNK(mode)
+# endif
+#endif
+
+#define SIGN_BYTE 1 /* byte value used where sign is displayed;
+ attribute value is sign type */
+
+#ifdef FEAT_NETBEANS_INTG
+# define MULTISIGN_BYTE 2 /* byte value used where sign is displayed if
+ multiple signs exist on the line */
+#endif
+
+#if defined(FEAT_GUI) && defined(FEAT_XCLIPBOARD)
+# ifdef FEAT_GUI_GTK
+ /* Avoid using a global variable for the X display. It's ugly
+ * and is likely to cause trouble in multihead environments. */
+# define X_DISPLAY ((gui.in_use) ? gui_mch_get_display() : xterm_dpy)
+# else
+# define X_DISPLAY (gui.in_use ? gui.dpy : xterm_dpy)
+# endif
+#else
+# ifdef FEAT_GUI
+# ifdef FEAT_GUI_GTK
+# define X_DISPLAY ((gui.in_use) ? gui_mch_get_display() : (Display *)NULL)
+# else
+# define X_DISPLAY gui.dpy
+# endif
+# else
+# define X_DISPLAY xterm_dpy
+# endif
+#endif
+
+#ifdef NBDEBUG /* Netbeans debugging. */
+# include "nbdebug.h"
+#else
+# define nbdebug(a)
+#endif
+
+#ifdef IN_PERL_FILE
+ /*
+ * Avoid clashes between Perl and Vim namespace.
+ */
+# undef NORMAL
+# undef STRLEN
+# undef FF
+# undef OP_DELETE
+# undef OP_JOIN
+# ifdef __BORLANDC__
+# define NOPROTO 1
+# endif
+ /* remove MAX and MIN, included by glib.h, redefined by sys/param.h */
+# ifdef MAX
+# undef MAX
+# endif
+# ifdef MIN
+# undef MIN
+# endif
+ /* We use _() for gettext(), Perl uses it for function prototypes... */
+# ifdef _
+# undef _
+# endif
+# ifdef DEBUG
+# undef DEBUG
+# endif
+# ifdef _DEBUG
+# undef _DEBUG
+# endif
+# ifdef instr
+# undef instr
+# endif
+ /* bool causes trouble on MACOS but is required on a few other systems */
+# if defined(bool) && defined(MACOS)
+# undef bool
+# endif
+
+# ifdef __BORLANDC__
+ /* Borland has the structure stati64 but not _stati64 */
+# define _stati64 stati64
+# endif
+
+# include <EXTERN.h>
+# include <perl.h>
+# include <XSUB.h>
+#endif
+
+#endif /* VIM__H */
diff --git a/src/vim.ico b/src/vim.ico
new file mode 100644
index 000000000..5e94092ac
--- /dev/null
+++ b/src/vim.ico
Binary files differ
diff --git a/src/vim.rc b/src/vim.rc
new file mode 100644
index 000000000..27d35a96b
--- /dev/null
+++ b/src/vim.rc
@@ -0,0 +1,135 @@
+// vim:ts=8:sw=4:sts=4:
+//
+// VIM - Vi IMproved by Bram Moolenaar
+//
+// Do ":help uganda" in Vim to read copying and usage conditions.
+// Do ":help credits" in Vim to see a list of people who contributed.
+
+// vim.rc
+// Icon and version information for the Win32 version of Vim
+// Must be in DOS format <CR><NL>!
+
+#ifdef __MINGW32__
+# include <windows.h>
+# ifndef VS_FFI_FILEFLAGSMASK
+# define VS_FFI_FILEFLAGSMASK 0x0000003FL
+# endif
+# ifndef VOS__WINDOWS32
+# define VOS__WINDOWS32 0x00000004L
+# endif
+#else
+# include <winver.h>
+#endif
+#include "version.h"
+#include "gui_w32_rc.h"
+#if defined(__BORLANDC__) || defined(__CYGWIN32__)
+# include <winresrc.h>
+#else
+# ifndef __MINGW32__
+# include <winres.h>
+# endif
+#endif
+
+//
+// Icons
+//
+IDR_VIM ICON "vim.ico"
+
+#ifdef FEAT_GUI_W32
+IDR_VIM_ERROR ICON "vim_error.ico"
+IDR_VIM_ALERT ICON "vim_alert.ico"
+IDR_VIM_INFO ICON "vim_info.ico"
+IDR_VIM_QUESTION ICON "vim_quest.ico"
+
+//
+// Bitmaps
+//
+IDB_TEAROFF BITMAP DISCARDABLE "tearoff.bmp"
+IDR_TOOLBAR1 BITMAP DISCARDABLE "tools.bmp"
+
+//
+// WinXP theme support
+//
+#ifndef CREATEPROCESS_MANIFEST_RESOURCE_ID
+# define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
+#endif
+#ifndef RT_MANIFEST
+# define RT_MANIFEST 24
+#endif
+
+CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "gvim.exe.mnf"
+#endif // FEAT_GUI_W32
+
+//
+// Type Library
+//
+#ifdef FEAT_OLE
+ 1 TYPELIB "VIM.TLB"
+#endif
+
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VIM_VERSION_MAJOR,VIM_VERSION_MINOR,VIM_VERSION_BUILD,VIM_VERSION_PATCHLEVEL
+ PRODUCTVERSION VIM_VERSION_MAJOR,VIM_VERSION_MINOR,VIM_VERSION_BUILD,VIM_VERSION_PATCHLEVEL
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+
+#if VIM_VERSION_PATCHLEVEL > 0
+ #ifdef _DEBUG
+ FILEFLAGS VS_FF_PRERELEASE | VS_FF_DEBUG | VS_FF_PATCHED
+ #else
+ FILEFLAGS VS_FF_PRERELEASE | VS_FF_PATCHED
+ #endif
+#else
+ #ifdef _DEBUG
+ FILEFLAGS VS_FF_PRERELEASE | VS_FF_DEBUG
+ #else
+ FILEFLAGS VS_FF_PRERELEASE
+ #endif
+#endif
+
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ // 0x0409 == U.S. English; 0x04E4 => Windows Multilingual
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "CompanyName", "Vim Developers\0"
+ VALUE "FileDescription", "Vi Improved - A Text Editor\0"
+ VALUE "FileVersion", VIM_VERSION_MAJOR_STR ", " VIM_VERSION_MINOR_STR ", " VIM_VERSION_BUILD_STR ", " VIM_VERSION_PATCHLEVEL_STR "\0"
+ VALUE "InternalName", "VIM\0"
+ VALUE "LegalCopyright", "Copyright \251 1996-2003\0"
+ VALUE "LegalTrademarks", "Vim\0"
+ VALUE "OriginalFilename", "VIM.EXE\0"
+ VALUE "ProductName", "Vim\0"
+ VALUE "ProductVersion", VIM_VERSION_MAJOR_STR ", " VIM_VERSION_MINOR_STR ", " VIM_VERSION_BUILD_STR ", " VIM_VERSION_PATCHLEVEL_STR "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 0x4E4
+ END
+END
+
+/*
+ * Printing Status Dialog (should only be used when FEAT_PRINTER is defined)
+ */
+#define IDC_BOX1 400
+#define IDC_PRINTTEXT1 401
+#define IDC_PRINTTEXT2 402
+#define IDC_PROGRESS 403
+PRINTDLGBOX DIALOG 115, 63, 210, 80
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+FONT 8, "Helv"
+BEGIN
+ DEFPUSHBUTTON "Cancel", IDCANCEL, 85, 60, 40, 14
+ CTEXT "Printing",IDC_PRINTTEXT1,23,15,157,8
+ CTEXT " ",IDC_PRINTTEXT2,23,25,157,8
+ CTEXT "Initializing...",IDC_PROGRESS,24,38,157,8
+ GROUPBOX "",IDC_BOX1,19,9,170,47
+END
diff --git a/src/vim.tlb b/src/vim.tlb
new file mode 100644
index 000000000..cb2606ce9
--- /dev/null
+++ b/src/vim.tlb
Binary files differ
diff --git a/src/vim16.def b/src/vim16.def
new file mode 100644
index 000000000..13b8c044e
--- /dev/null
+++ b/src/vim16.def
@@ -0,0 +1,5 @@
+CODE PRELOAD EXECUTEONLY
+DATA MULTIPLE SHARED
+DESCRIPTION 'Vim 7.0aa'
+STACKSIZE 16000
+HEAPSIZE 10000
diff --git a/src/vim16.rc b/src/vim16.rc
new file mode 100644
index 000000000..8529e09ea
--- /dev/null
+++ b/src/vim16.rc
@@ -0,0 +1,81 @@
+// vim:ts=8:sw=4:sts=4:
+//
+// VIM - Vi IMproved by Bram Moolenaar
+//
+// Do ":help uganda" in Vim to read copying and usage conditions.
+// Do ":help credits" in Vim to see a list of people who contributed.
+
+// vim.rc
+// Icon and version information for the Win32 version of Vim
+// Must be in DOS format <CR><NL>!
+
+#include "version.h"
+#include "gui_w3~1.h"
+#include "guiw16rc.h"
+
+//
+// Icons
+//
+IDR_VIM ICON "VIM.ICO"
+
+#ifndef FEAT_TINY
+IDR_VIM_ERROR ICON "VIM_ER~1.ICO"
+IDR_VIM_ALERT ICON "VIM_AL~1.ICO"
+IDR_VIM_INFO ICON "VIM_INFO.ICO"
+IDR_VIM_QUESTION ICON "VIM_QU~1.ICO"
+#endif
+
+//
+// Bitmaps
+//
+#ifdef FEAT_TOOLBAR
+IDR_TOOLBAR1 BITMAP DISCARDABLE "tools16.bmp"
+#endif
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VIM_VERSION_MAJOR,VIM_VERSION_MINOR,VIM_VERSION_BUILD,VIM_VERSION_PATCHLEVEL
+ PRODUCTVERSION VIM_VERSION_MAJOR,VIM_VERSION_MINOR,VIM_VERSION_BUILD,VIM_VERSION_PATCHLEVEL
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+
+#if VIM_VERSION_PATCHLEVEL > 0
+ #ifdef _DEBUG
+ FILEFLAGS VS_FF_PRERELEASE | VS_FF_DEBUG | VS_FF_PATCHED
+ #else
+ FILEFLAGS VS_FF_PRERELEASE | VS_FF_PATCHED
+ #endif
+#else
+ #ifdef _DEBUG
+ FILEFLAGS VS_FF_PRERELEASE | VS_FF_DEBUG
+ #else
+ FILEFLAGS VS_FF_PRERELEASE
+ #endif
+#endif
+
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ // 0x0409 == U.S. English; 0x04E4 => Windows Multilingual
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "CompanyName", "Vim Developers\0"
+ VALUE "FileDescription", "Vi Improved - A Text Editor\0"
+ VALUE "FileVersion", VIM_VERSION_MAJOR_STR ", " VIM_VERSION_MINOR_STR ", " VIM_VERSION_BUILD_STR ", " VIM_VERSION_PATCHLEVEL_STR "\0"
+ VALUE "InternalName", "VIM\0"
+ VALUE "LegalCopyright", "Copyright \251 1996-1999\0"
+ VALUE "LegalTrademarks", "Vim\0"
+ VALUE "OriginalFilename", "VIM.EXE\0"
+ VALUE "ProductName", "Vim\0"
+ VALUE "ProductVersion", VIM_VERSION_MAJOR_STR ", " VIM_VERSION_MINOR_STR ", " VIM_VERSION_BUILD_STR ", " VIM_VERSION_PATCHLEVEL_STR "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 0x4E4
+ END
+END
diff --git a/src/vim_alert.ico b/src/vim_alert.ico
new file mode 100644
index 000000000..93d982bff
--- /dev/null
+++ b/src/vim_alert.ico
Binary files differ
diff --git a/src/vim_error.ico b/src/vim_error.ico
new file mode 100644
index 000000000..b3fbacff8
--- /dev/null
+++ b/src/vim_error.ico
Binary files differ
diff --git a/src/vim_icon.xbm b/src/vim_icon.xbm
new file mode 100644
index 000000000..62a24bb45
--- /dev/null
+++ b/src/vim_icon.xbm
@@ -0,0 +1,14 @@
+#define vim_icon_width 32
+#define vim_icon_height 32
+static unsigned char vim_icon_bits[] = {
+ 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0xfc, 0xff, 0xff, 0x3f,
+ 0x04, 0x80, 0x03, 0x20, 0x04, 0x80, 0x0f, 0x40, 0x08, 0xc0, 0x1f, 0x60,
+ 0x10, 0xe0, 0x3f, 0x60, 0x10, 0xe0, 0x1f, 0x30, 0x10, 0xe0, 0x0f, 0x18,
+ 0x10, 0xe0, 0x07, 0x0e, 0x10, 0xe0, 0x03, 0x07, 0x10, 0xe0, 0x81, 0x0f,
+ 0x18, 0xe0, 0x80, 0x1f, 0x1c, 0x60, 0xe0, 0x3f, 0x1e, 0x20, 0xf0, 0x7f,
+ 0x1f, 0x00, 0xf8, 0xff, 0x1f, 0x00, 0xfc, 0xff, 0x1e, 0x00, 0xfc, 0x7f,
+ 0x1c, 0x00, 0xff, 0x3f, 0x18, 0x80, 0xfc, 0x1f, 0x10, 0x80, 0xfc, 0x0f,
+ 0x10, 0xc0, 0xff, 0x5f, 0x10, 0x60, 0x44, 0x24, 0x10, 0x50, 0x0c, 0x40,
+ 0x10, 0x70, 0xce, 0x24, 0x10, 0x7c, 0x6e, 0x26, 0x10, 0x7a, 0x66, 0x26,
+ 0x10, 0x3d, 0x22, 0x13, 0xa0, 0x32, 0x32, 0x67, 0xd0, 0xe1, 0xdf, 0x1c,
+ 0x00, 0xc0, 0x43, 0x00, 0x00, 0x80, 0x01, 0x00};
diff --git a/src/vim_info.ico b/src/vim_info.ico
new file mode 100644
index 000000000..df043a56f
--- /dev/null
+++ b/src/vim_info.ico
Binary files differ
diff --git a/src/vim_mask.xbm b/src/vim_mask.xbm
new file mode 100644
index 000000000..96dd929e8
--- /dev/null
+++ b/src/vim_mask.xbm
@@ -0,0 +1,14 @@
+#define vim_mask_icon_width 32
+#define vim_mask_icon_height 32
+static unsigned char vim_mask_icon_bits[] = {
+ 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0xfc, 0xff, 0xff, 0x3f,
+ 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff, 0x7f,
+ 0xf0, 0xff, 0xff, 0x7f, 0xf0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x1f,
+ 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x0f,
+ 0xf8, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0x7f,
+ 0xfc, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0xff, 0x0f,
+ 0xf0, 0xff, 0xff, 0x5f, 0xf0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x7f,
+ 0xf0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x3f,
+ 0xf0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x7f, 0xd0, 0xe1, 0xdf, 0x1c,
+ 0x00, 0xc0, 0x43, 0x00, 0x00, 0x80, 0x01, 0x00};
diff --git a/src/vim_quest.ico b/src/vim_quest.ico
new file mode 100644
index 000000000..d6c22395b
--- /dev/null
+++ b/src/vim_quest.ico
Binary files differ
diff --git a/src/vimrun.c b/src/vimrun.c
new file mode 100644
index 000000000..fed5076a5
--- /dev/null
+++ b/src/vimrun.c
@@ -0,0 +1,117 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * this file by Vince Negri
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * vimrun.c - Tiny Win32 program to safely run an external command in a
+ * DOS console.
+ * This program is required to avoid that typing CTRL-C in the DOS
+ * console kills Vim. Now it only kills vimrun.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef __CYGWIN__
+# include <conio.h>
+#endif
+
+#ifdef __BORLANDC__
+extern char *
+#ifdef _RTLDLL
+__import
+#endif
+_oscmd;
+# define _kbhit kbhit
+# define _getch getch
+#else
+# ifdef __MINGW32__
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+# else
+# ifdef __CYGWIN__
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+# define _getch getchar
+# else
+extern char *_acmdln;
+# endif
+# endif
+#endif
+
+ int
+main(void)
+{
+ const char *p;
+ int retval;
+ int inquote = 0;
+ int silent = 0;
+
+#ifdef __BORLANDC__
+ p = _oscmd;
+#else
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+ p = (const char *)GetCommandLine();
+# else
+ p = _acmdln;
+# endif
+#endif
+ /*
+ * Skip the executable name, which might be in "".
+ */
+ while (*p)
+ {
+ if (*p == '"')
+ inquote = !inquote;
+ else if (!inquote && *p == ' ')
+ {
+ ++p;
+ break;
+ }
+ ++p;
+ }
+
+ /*
+ * "-s" argument: don't wait for a key hit.
+ */
+ if (p[0] == '-' && p[1] == 's' && p[2] == ' ')
+ {
+ silent = 1;
+ p += 3;
+ while (*p == ' ')
+ ++p;
+ }
+
+ /* Print the command, including quotes and redirection. */
+ puts(p);
+
+ /*
+ * Do it!
+ */
+ retval = system(p);
+
+ if (retval != 0)
+ printf("shell returned %d\n", retval);
+
+ if (!silent)
+ {
+ puts("Hit any key to close this window...");
+
+#ifndef __CYGWIN__
+ while (_kbhit())
+ (void)_getch();
+#endif
+ (void)_getch();
+ }
+
+ return retval;
+}
diff --git a/src/vimtbar.dll b/src/vimtbar.dll
new file mode 100755
index 000000000..6a8dfc95a
--- /dev/null
+++ b/src/vimtbar.dll
Binary files differ
diff --git a/src/vimtbar.h b/src/vimtbar.h
new file mode 100644
index 000000000..7427f6477
--- /dev/null
+++ b/src/vimtbar.h
@@ -0,0 +1,185 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Win16 Toolbar by Vince Negri - External Header
+ * (Based on MS Sample Code)
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+//
+// Button Structure
+//
+typedef struct tagTBBUTTON
+{
+ int iBitmap; // index into bitmap of this button's picture
+ int idCommand; // WM_COMMAND menu ID that this button sends
+ BYTE fsState; // button's state
+ BYTE fsStyle; // button's style
+} TBBUTTON;
+
+typedef TBBUTTON NEAR* PTBBUTTON;
+typedef TBBUTTON FAR* LPTBBUTTON;
+typedef const TBBUTTON FAR* LPCTBBUTTON;
+
+
+//
+// Styles
+//
+#define TBSTYLE_BUTTON 0x00 // this entry is button
+#define TBSTYLE_SEP 0x01 // this entry is a separator
+#define TBSTYLE_CHECK 0x02 // this is a check button (it stays down)
+#define TBSTYLE_GROUP 0x04 // this is a check button (it stays down)
+#define TBSTYLE_CHECKGROUP (TBSTYLE_GROUP | TBSTYLE_CHECK) // this group is a member of a group radio group
+
+//
+// States
+//
+#define TBSTATE_CHECKED 0x01 // radio button is checked
+#define TBSTATE_PRESSED 0x02 // button is being depressed (any style)
+#define TBSTATE_ENABLED 0x04 // button is enabled
+#define TBSTATE_HIDDEN 0x08 // button is hidden
+#define TBSTATE_INDETERMINATE 0x10 // button is indeterminate
+#define TBSTATE_SELECTED 0x20 // mouse hovering over button (for coolbar look)
+
+
+
+typedef struct tagADJUSTINFO
+{
+ TBBUTTON tbButton;
+ char szDescription[1];
+} ADJUSTINFO;
+
+typedef ADJUSTINFO NEAR* PADJUSTINFO;
+typedef ADJUSTINFO FAR* LPADJUSTINFO;
+
+
+HWND WINAPI CreateToolbar(HWND hwnd, DWORD ws, WORD wID, int nBitmaps,
+ HINSTANCE hBMInst, WORD wBMID,
+ LPCTBBUTTON lpButtons, int iNumButtons);
+
+#define CMB_DISCARDABLE 0x01 // create bitmap as discardable
+#define CMB_MASKED 0x02 // create image/mask pair in bitmap
+
+
+#define TB_ENABLEBUTTON (WM_USER + 1)
+// wParam: UINT, button ID
+// lParam: BOOL LOWORD, enable if nonzero; HIWORD not used, 0
+// return: not used
+//
+
+#define TB_CHECKBUTTON (WM_USER + 2)
+// wParam: UINT, button ID
+// lParam: BOOL LOWORD, check if nonzero; HIWORD not used, 0
+// return: not used
+//
+
+#define TB_PRESSBUTTON (WM_USER + 3)
+// wParam: UINT, button ID
+// lParam: BOOL LOWORD, press if nonzero; HIWORD not used, 0
+// return: not used
+//
+
+#define TB_HIDEBUTTON (WM_USER + 4)
+// wParam: UINT, button ID
+// lParam: BOOL LOWORD, hide if nonzero; HIWORD not used, 0
+// return: not used
+//
+#define TB_INDETERMINATE (WM_USER + 5)
+// wParam: UINT, button ID
+// lParam: BOOL LOWORD, make indeterminate if nonzero; HIWORD not used, 0
+// return: not used
+//
+
+#define TB_ISBUTTONENABLED (WM_USER + 9)
+// wParam: UINT, button ID
+// lParam: not used, 0
+// return: BOOL LOWORD, enabled if nonzero; HIWORD not used
+//
+
+#define TB_ISBUTTONCHECKED (WM_USER + 10)
+// wParam: UINT, button ID
+// lParam: not used, 0
+// return: BOOL LOWORD, checked if nonzero; HIWORD not used
+//
+
+#define TB_ISBUTTONPRESSED (WM_USER + 11)
+// wParam: UINT, button ID
+// lParam: not used, 0
+// return: BOOL LOWORD, pressed if nonzero; HIWORD not used
+//
+
+#define TB_ISBUTTONHIDDEN (WM_USER + 12)
+// wParam: UINT, button ID
+// lParam: not used, 0
+// return: BOOL LOWORD, hidden if nonzero; HIWORD not used
+//
+
+#define TB_ISBUTTONINDETERMINATE (WM_USER + 13)
+// wParam: UINT, button ID
+// lParam: not used, 0
+// return: BOOL LOWORD, indeterminate if nonzero; HIWORD not used
+//
+
+#define TB_SETSTATE (WM_USER + 17)
+// wParam: UINT, button ID
+// lParam: UINT LOWORD, state bits; HIWORD not used, 0
+// return: not used
+//
+
+#define TB_GETSTATE (WM_USER + 18)
+// wParam: UINT, button ID
+// lParam: not used, 0
+// return: UINT LOWORD, state bits; HIWORD not used
+//
+
+#define TB_ADDBITMAP (WM_USER + 19)
+// wParam: UINT, number of button graphics in bitmap
+// lParam: one of:
+// HINSTANCE LOWORD, module handle; UINT HIWORD, resource id
+// HINSTANCE LOWORD, NULL; HBITMAP HIWORD, bitmap handle
+// return: one of:
+// int LOWORD, index for first new button; HIWORD not used
+// int LOWORD, -1 indicating error; HIWORD not used
+//
+
+#define TB_ADDBUTTONS (WM_USER + 20)
+// wParam: UINT, number of buttons to add
+// lParam: LPTBBUTTON, pointer to array of TBBUTTON structures
+// return: not used
+//
+
+#define TB_INSERTBUTTON (WM_USER + 21)
+// wParam: UINT, index for insertion (appended if index doesn't exist)
+// lParam: LPTBBUTTON, pointer to one TBBUTTON structure
+// return: not used
+//
+
+#define TB_DELETEBUTTON (WM_USER + 22)
+// wParam: UINT, index of button to delete
+// lParam: not used, 0
+// return: not used
+//
+
+#define TB_GETBUTTON (WM_USER + 23)
+// wParam: UINT, index of button to get
+// lParam: LPTBBUTTON, pointer to TBBUTTON buffer to receive button
+// return: not used
+//
+
+#define TB_BUTTONCOUNT (WM_USER + 24)
+// wParam: not used, 0
+// lParam: not used, 0
+// return: UINT LOWORD, number of buttons; HIWORD not used
+//
+
+#define TB_COMMANDTOINDEX (WM_USER + 25)
+// wParam: UINT, command id
+// lParam: not used, 0
+// return: UINT LOWORD, index of button (-1 if command not found);
+// HIWORD not used
+//
+
+
+#define TBN_BEGINDRAG 0x0201
+#define TBN_ENDDRAG 0x0203
diff --git a/src/vimtbar.lib b/src/vimtbar.lib
new file mode 100644
index 000000000..413b7dac9
--- /dev/null
+++ b/src/vimtbar.lib
Binary files differ
diff --git a/src/vimtutor b/src/vimtutor
new file mode 100755
index 000000000..2fbb1371f
--- /dev/null
+++ b/src/vimtutor
@@ -0,0 +1,61 @@
+#! /bin/sh
+
+# Start Vim on a copy of the tutor file.
+
+# Usage: vimtutor [xx], where xx is a language code like "es" or "nl".
+# When an argument is given, it tries loading that tutor.
+# When this fails or no argument was given, it tries using 'v:lang'
+# When that also fails, it uses the English version.
+
+xx=$1
+export xx
+
+# We need a temp file for the copy. First try using a standard command.
+tmp="${TMPDIR-/tmp}"
+TUTORCOPY=`mktemp $tmp/tutorXXXXXX || tempfile -p tutor || echo none`
+
+# If the standard commands failed then create a directory to put the copy in.
+# That is a secure way to make a temp file.
+if test "$TUTORCOPY" = none; then
+ tmpdir=$tmp/vimtutor$$
+ OLD_UMASK=`umask`
+ umask 077
+ getout=no
+ mkdir $tmpdir || getout=yes
+ umask $OLD_UMASK
+ if test $getout = yes; then
+ echo "Could not create directory for tutor copy, exiting."
+ exit 1
+ fi
+ TUTORCOPY=$tmpdir/tutorcopy
+ touch $TUTORCOPY
+ TODELETE=$tmpdir
+else
+ TODELETE=$TUTORCOPY
+fi
+
+export TUTORCOPY
+
+# remove the copy of the tutor on exit
+trap "rm -rf $TODELETE" 0 1 2 3 9 11 13 15
+
+# Vim could be called "vim" or "vi". Also check for "vim6", for people who
+# have Vim 5.x installed as "vim" and Vim 6.0 as "vim6".
+testvim=`which vim6 2>/dev/null`
+if test -f "$testvim"; then
+ VIM=vim6
+else
+ testvim=`which vim`
+ if test -f "$testvim"; then
+ VIM=vim
+ else
+ VIM=vi
+ fi
+fi
+
+# Use Vim to copy the tutor, it knows the value of $VIMRUNTIME
+# The script tutor.vim tells Vim which file to copy
+$VIM -u NONE -c 'so $VIMRUNTIME/tutor/tutor.vim'
+
+# Start vim without any .vimrc, set 'nocompatible'
+$VIM -u NONE -c "set nocp" $TUTORCOPY
diff --git a/src/which.sh b/src/which.sh
new file mode 100755
index 000000000..8c2c6982c
--- /dev/null
+++ b/src/which.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+#
+# which.sh -- find where an executable is located. It's here because the
+# "which" command is not supported everywhere. Used by Makefile.
+
+IFS=":"
+for ac_dir in $PATH; do
+ if test -f "$ac_dir/$1"; then
+ echo "$ac_dir/$1"
+ break
+ fi
+done
diff --git a/src/window.c b/src/window.c
new file mode 100644
index 000000000..dc63e09d4
--- /dev/null
+++ b/src/window.c
@@ -0,0 +1,4946 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read a list of people who contributed.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h> /* for chdir() */
+#endif
+
+static int path_is_url __ARGS((char_u *p));
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+static int win_split_ins __ARGS((int size, int flags, win_T *newwin, int dir));
+static int win_comp_pos __ARGS((void));
+static void frame_comp_pos __ARGS((frame_T *topfrp, int *row, int *col));
+static void frame_setheight __ARGS((frame_T *curfrp, int height));
+#ifdef FEAT_VERTSPLIT
+static void frame_setwidth __ARGS((frame_T *curfrp, int width));
+#endif
+static void win_exchange __ARGS((long));
+static void win_rotate __ARGS((int, int));
+static void win_totop __ARGS((int size, int flags));
+static void win_equal_rec __ARGS((win_T *next_curwin, int current, frame_T *topfr, int dir, int col, int row, int width, int height));
+static win_T *winframe_remove __ARGS((win_T *win, int *dirp));
+static frame_T *win_altframe __ARGS((win_T *win));
+static win_T *frame2win __ARGS((frame_T *frp));
+static int frame_has_win __ARGS((frame_T *frp, win_T *wp));
+static void frame_new_height __ARGS((frame_T *topfrp, int height, int topfirst, int wfh));
+static int frame_fixed_height __ARGS((frame_T *frp));
+#ifdef FEAT_VERTSPLIT
+static void frame_add_statusline __ARGS((frame_T *frp));
+static void frame_new_width __ARGS((frame_T *topfrp, int width, int leftfirst));
+static void frame_add_vsep __ARGS((frame_T *frp));
+static int frame_minwidth __ARGS((frame_T *topfrp, win_T *next_curwin));
+static void frame_fix_width __ARGS((win_T *wp));
+#endif
+static void frame_fix_height __ARGS((win_T *wp));
+static int frame_minheight __ARGS((frame_T *topfrp, win_T *next_curwin));
+static void win_enter_ext __ARGS((win_T *wp, int undo_sync, int no_curwin));
+static void win_free __ARGS((win_T *wp));
+static void win_append __ARGS((win_T *, win_T *));
+static void win_remove __ARGS((win_T *));
+static void frame_append __ARGS((frame_T *after, frame_T *frp));
+static void frame_insert __ARGS((frame_T *before, frame_T *frp));
+static void frame_remove __ARGS((frame_T *frp));
+#ifdef FEAT_VERTSPLIT
+static void win_new_width __ARGS((win_T *wp, int width));
+static int win_minheight __ARGS((win_T *wp));
+static void win_goto_ver __ARGS((int up, long count));
+static void win_goto_hor __ARGS((int left, long count));
+#endif
+static void frame_add_height __ARGS((frame_T *frp, int n));
+static void last_status_rec __ARGS((frame_T *fr, int statusline));
+
+static void make_snapshot __ARGS((void));
+static void make_snapshot_rec __ARGS((frame_T *fr, frame_T **frp));
+static void clear_snapshot __ARGS((void));
+static void clear_snapshot_rec __ARGS((frame_T *fr));
+static void restore_snapshot __ARGS((int close_curwin));
+static int check_snapshot_rec __ARGS((frame_T *sn, frame_T *fr));
+static win_T *restore_snapshot_rec __ARGS((frame_T *sn, frame_T *fr));
+
+#endif /* FEAT_WINDOWS */
+static win_T *win_alloc __ARGS((win_T *after));
+static void win_new_height __ARGS((win_T *, int));
+
+#define URL_SLASH 1 /* path_is_url() has found "://" */
+#define URL_BACKSLASH 2 /* path_is_url() has found ":\\" */
+
+#define NOWIN (win_T *)-1 /* non-exisiting window */
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * all CTRL-W window commands are handled here, called from normal_cmd().
+ */
+ void
+do_window(nchar, Prenum, xchar)
+ int nchar;
+ long Prenum;
+ int xchar; /* extra char from ":wincmd gx" or NUL */
+{
+ long Prenum1;
+ win_T *wp;
+#if defined(FEAT_SEARCHPATH) || defined(FEAT_FIND_ID)
+ char_u *ptr;
+#endif
+#ifdef FEAT_FIND_ID
+ int type = FIND_DEFINE;
+ int len;
+#endif
+ char_u cbuf[40];
+
+ if (Prenum == 0)
+ Prenum1 = 1;
+ else
+ Prenum1 = Prenum;
+
+#ifdef FEAT_CMDWIN
+# define CHECK_CMDWIN if (cmdwin_type != 0) { EMSG(_(e_cmdwin)); break; }
+#else
+# define CHECK_CMDWIN
+#endif
+
+ switch (nchar)
+ {
+/* split current window in two parts, horizontally */
+ case 'S':
+ case Ctrl_S:
+ case 's':
+ CHECK_CMDWIN
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ win_split((int)Prenum, 0);
+ break;
+
+#ifdef FEAT_VERTSPLIT
+/* split current window in two parts, vertically */
+ case Ctrl_V:
+ case 'v':
+ CHECK_CMDWIN
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ win_split((int)Prenum, WSP_VERT);
+ break;
+#endif
+
+/* split current window and edit alternate file */
+ case Ctrl_HAT:
+ case '^':
+ CHECK_CMDWIN
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+ STRCPY(cbuf, "split #");
+ if (Prenum)
+ sprintf((char *)cbuf + 7, "%ld", Prenum);
+ do_cmdline_cmd(cbuf);
+ break;
+
+/* open new window */
+ case Ctrl_N:
+ case 'n':
+ CHECK_CMDWIN
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+ if (Prenum)
+ sprintf((char *)cbuf, "%ld", Prenum); /* window height */
+ else
+ cbuf[0] = NUL;
+ STRCAT(cbuf, "new");
+ do_cmdline_cmd(cbuf);
+ break;
+
+/* quit current window */
+ case Ctrl_Q:
+ case 'q':
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+ do_cmdline_cmd((char_u *)"quit");
+ break;
+
+/* close current window */
+ case Ctrl_C:
+ case 'c':
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+ do_cmdline_cmd((char_u *)"close");
+ break;
+
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+/* close preview window */
+ case Ctrl_Z:
+ case 'z':
+ CHECK_CMDWIN
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+ do_cmdline_cmd((char_u *)"pclose");
+ break;
+
+/* cursor to preview window */
+ case 'P':
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_p_pvw)
+ break;
+ if (wp == NULL)
+ EMSG(_("E441: There is no preview window"));
+ else
+ win_goto(wp);
+ break;
+#endif
+
+/* close all but current window */
+ case Ctrl_O:
+ case 'o':
+ CHECK_CMDWIN
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+ do_cmdline_cmd((char_u *)"only");
+ break;
+
+/* cursor to next window with wrap around */
+ case Ctrl_W:
+ case 'w':
+/* cursor to previous window with wrap around */
+ case 'W':
+ CHECK_CMDWIN
+ if (lastwin == firstwin && Prenum != 1) /* just one window */
+ beep_flush();
+ else
+ {
+ if (Prenum) /* go to specified window */
+ {
+ for (wp = firstwin; --Prenum > 0; )
+ {
+ if (wp->w_next == NULL)
+ break;
+ else
+ wp = wp->w_next;
+ }
+ }
+ else
+ {
+ if (nchar == 'W') /* go to previous window */
+ {
+ wp = curwin->w_prev;
+ if (wp == NULL)
+ wp = lastwin; /* wrap around */
+ }
+ else /* go to next window */
+ {
+ wp = curwin->w_next;
+ if (wp == NULL)
+ wp = firstwin; /* wrap around */
+ }
+ }
+ win_goto(wp);
+ }
+ break;
+
+/* cursor to window below */
+ case 'j':
+ case K_DOWN:
+ case Ctrl_J:
+ CHECK_CMDWIN
+#ifdef FEAT_VERTSPLIT
+ win_goto_ver(FALSE, Prenum1);
+#else
+ for (wp = curwin; wp->w_next != NULL && Prenum1-- > 0;
+ wp = wp->w_next)
+ ;
+ win_goto(wp);
+#endif
+ break;
+
+/* cursor to window above */
+ case 'k':
+ case K_UP:
+ case Ctrl_K:
+ CHECK_CMDWIN
+#ifdef FEAT_VERTSPLIT
+ win_goto_ver(TRUE, Prenum1);
+#else
+ for (wp = curwin; wp->w_prev != NULL && Prenum1-- > 0;
+ wp = wp->w_prev)
+ ;
+ win_goto(wp);
+#endif
+ break;
+
+#ifdef FEAT_VERTSPLIT
+/* cursor to left window */
+ case 'h':
+ case K_LEFT:
+ case Ctrl_H:
+ case K_BS:
+ CHECK_CMDWIN
+ win_goto_hor(TRUE, Prenum1);
+ break;
+
+/* cursor to right window */
+ case 'l':
+ case K_RIGHT:
+ case Ctrl_L:
+ CHECK_CMDWIN
+ win_goto_hor(FALSE, Prenum1);
+ break;
+#endif
+
+/* cursor to top-left window */
+ case 't':
+ case Ctrl_T:
+ win_goto(firstwin);
+ break;
+
+/* cursor to bottom-right window */
+ case 'b':
+ case Ctrl_B:
+ win_goto(lastwin);
+ break;
+
+/* cursor to last accessed (previous) window */
+ case 'p':
+ case Ctrl_P:
+ if (prevwin == NULL)
+ beep_flush();
+ else
+ win_goto(prevwin);
+ break;
+
+/* exchange current and next window */
+ case 'x':
+ case Ctrl_X:
+ CHECK_CMDWIN
+ win_exchange(Prenum);
+ break;
+
+/* rotate windows downwards */
+ case Ctrl_R:
+ case 'r':
+ CHECK_CMDWIN
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+ win_rotate(FALSE, (int)Prenum1); /* downwards */
+ break;
+
+/* rotate windows upwards */
+ case 'R':
+ CHECK_CMDWIN
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+ win_rotate(TRUE, (int)Prenum1); /* upwards */
+ break;
+
+/* move window to the very top/bottom/left/right */
+ case 'K':
+ case 'J':
+#ifdef FEAT_VERTSPLIT
+ case 'H':
+ case 'L':
+#endif
+ CHECK_CMDWIN
+ win_totop((int)Prenum,
+ ((nchar == 'H' || nchar == 'L') ? WSP_VERT : 0)
+ | ((nchar == 'H' || nchar == 'K') ? WSP_TOP : WSP_BOT));
+ break;
+
+/* make all windows the same height */
+ case '=':
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ win_equal(NULL, FALSE, 'b');
+ break;
+
+/* increase current window height */
+ case '+':
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ win_setheight(curwin->w_height + (int)Prenum1);
+ break;
+
+/* decrease current window height */
+ case '-':
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ win_setheight(curwin->w_height - (int)Prenum1);
+ break;
+
+/* set current window height */
+ case Ctrl__:
+ case '_':
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ win_setheight(Prenum ? (int)Prenum : 9999);
+ break;
+
+#ifdef FEAT_VERTSPLIT
+/* increase current window width */
+ case '>':
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ win_setwidth(curwin->w_width + (int)Prenum1);
+ break;
+
+/* decrease current window width */
+ case '<':
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ win_setwidth(curwin->w_width - (int)Prenum1);
+ break;
+
+/* set current window width */
+ case '|':
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ win_setwidth(Prenum != 0 ? (int)Prenum : 9999);
+ break;
+#endif
+
+/* jump to tag and split window if tag exists (in preview window) */
+#if defined(FEAT_QUICKFIX)
+ case '}':
+ CHECK_CMDWIN
+ if (Prenum)
+ g_do_tagpreview = Prenum;
+ else
+ g_do_tagpreview = p_pvh;
+ /*FALLTHROUGH*/
+#endif
+ case ']':
+ case Ctrl_RSB:
+ CHECK_CMDWIN
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+ if (Prenum)
+ postponed_split = Prenum;
+ else
+ postponed_split = -1;
+
+ /* Execute the command right here, required when
+ * "wincmd ]" was used in a function. */
+ do_nv_ident(Ctrl_RSB, NUL);
+ break;
+
+#ifdef FEAT_SEARCHPATH
+/* edit file name under cursor in a new window */
+ case 'f':
+ case Ctrl_F:
+ CHECK_CMDWIN
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+ ptr = file_name_at_cursor(FNAME_MESS|FNAME_HYP|FNAME_EXP,
+ Prenum1);
+ if (ptr != NULL)
+ {
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ setpcmark();
+ if (win_split(0, 0) == OK)
+ {
+# ifdef FEAT_SCROLLBIND
+ curwin->w_p_scb = FALSE;
+# endif
+ (void)do_ecmd(0, ptr, NULL, NULL, ECMD_LASTL,
+ ECMD_HIDE);
+ }
+ vim_free(ptr);
+ }
+ break;
+#endif
+
+#ifdef FEAT_FIND_ID
+/* Go to the first occurence of the identifier under cursor along path in a
+ * new window -- webb
+ */
+ case 'i': /* Go to any match */
+ case Ctrl_I:
+ type = FIND_ANY;
+ /* FALLTHROUGH */
+ case 'd': /* Go to definition, using 'define' */
+ case Ctrl_D:
+ CHECK_CMDWIN
+ if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0)
+ break;
+ find_pattern_in_path(ptr, 0, len, TRUE,
+ Prenum == 0 ? TRUE : FALSE, type,
+ Prenum1, ACTION_SPLIT, (linenr_T)1, (linenr_T)MAXLNUM);
+ curwin->w_set_curswant = TRUE;
+ break;
+#endif
+
+/* CTRL-W g extended commands */
+ case 'g':
+ case Ctrl_G:
+ CHECK_CMDWIN
+#ifdef USE_ON_FLY_SCROLL
+ dont_scroll = TRUE; /* disallow scrolling here */
+#endif
+ ++no_mapping;
+ ++allow_keys; /* no mapping for xchar, but allow key codes */
+ if (xchar == NUL)
+ xchar = safe_vgetc();
+#ifdef FEAT_LANGMAP
+ LANGMAP_ADJUST(xchar, TRUE);
+#endif
+ --no_mapping;
+ --allow_keys;
+#ifdef FEAT_CMDL_INFO
+ (void)add_to_showcmd(xchar);
+#endif
+ switch (xchar)
+ {
+#if defined(FEAT_QUICKFIX)
+ case '}':
+ xchar = Ctrl_RSB;
+ if (Prenum)
+ g_do_tagpreview = Prenum;
+ else
+ g_do_tagpreview = p_pvh;
+ /*FALLTHROUGH*/
+#endif
+ case ']':
+ case Ctrl_RSB:
+#ifdef FEAT_VISUAL
+ reset_VIsual_and_resel(); /* stop Visual mode */
+#endif
+ if (Prenum)
+ postponed_split = Prenum;
+ else
+ postponed_split = -1;
+
+ /* Execute the command right here, required when
+ * "wincmd g}" was used in a function. */
+ do_nv_ident('g', xchar);
+ break;
+
+ default:
+ beep_flush();
+ break;
+ }
+ break;
+
+ default: beep_flush();
+ break;
+ }
+}
+
+/*
+ * split the current window, implements CTRL-W s and :split
+ *
+ * "size" is the height or width for the new window, 0 to use half of current
+ * height or width.
+ *
+ * "flags":
+ * WSP_ROOM: require enough room for new window
+ * WSP_VERT: vertical split.
+ * WSP_TOP: open window at the top-left of the shell (help window).
+ * WSP_BOT: open window at the bottom-right of the shell (quickfix window).
+ * WSP_HELP: creating the help window, keep layout snapshot
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+win_split(size, flags)
+ int size;
+ int flags;
+{
+ /* Add flags from ":vertical", ":topleft" and ":botright". */
+ flags |= cmdmod.split;
+ if ((flags & WSP_TOP) && (flags & WSP_BOT))
+ {
+ EMSG(_("E442: Can't split topleft and botright at the same time"));
+ return FAIL;
+ }
+
+ /* When creating the help window make a snapshot of the window layout.
+ * Otherwise clear the snapshot, it's now invalid. */
+ if (flags & WSP_HELP)
+ make_snapshot();
+ else
+ clear_snapshot();
+
+ return win_split_ins(size, flags, NULL, 0);
+}
+
+/*
+ * When "newwin" is NULL: split a window in two.
+ * When "newwin" is not NULL: insert this window at the far
+ * top/left/right/bottom.
+ * return FAIL for failure, OK otherwise
+ */
+ static int
+win_split_ins(size, flags, newwin, dir)
+ int size;
+ int flags;
+ win_T *newwin;
+ int dir;
+{
+ win_T *wp = newwin;
+ win_T *oldwin;
+ int new_size = size;
+ int i;
+ int need_status = 0;
+ int do_equal = FALSE;
+ int needed;
+ int available;
+ int oldwin_height = 0;
+ int layout;
+ frame_T *frp, *curfrp;
+ int before;
+
+ if (flags & WSP_TOP)
+ oldwin = firstwin;
+ else if (flags & WSP_BOT)
+ oldwin = lastwin;
+ else
+ oldwin = curwin;
+
+ /* add a status line when p_ls == 1 and splitting the first window */
+ if (lastwin == firstwin && p_ls == 1 && oldwin->w_status_height == 0)
+ {
+ if (oldwin->w_height <= p_wmh && newwin == NULL)
+ {
+ EMSG(_(e_noroom));
+ return FAIL;
+ }
+ need_status = STATUS_HEIGHT;
+ }
+
+#ifdef FEAT_VERTSPLIT
+ if (flags & WSP_VERT)
+ {
+ layout = FR_ROW;
+ do_equal = (p_ea && new_size == 0 && *p_ead != 'v');
+
+ /*
+ * Check if we are able to split the current window and compute its
+ * width.
+ */
+ needed = p_wmw + 1;
+ if (flags & WSP_ROOM)
+ needed += p_wiw - p_wmw;
+ if (p_ea || (flags & (WSP_BOT | WSP_TOP)))
+ {
+ available = topframe->fr_width;
+ needed += frame_minwidth(topframe, NULL);
+ }
+ else
+ available = oldwin->w_width;
+ if (available < needed && newwin == NULL)
+ {
+ EMSG(_(e_noroom));
+ return FAIL;
+ }
+ if (new_size == 0)
+ new_size = oldwin->w_width / 2;
+ if (new_size > oldwin->w_width - p_wmw - 1)
+ new_size = oldwin->w_width - p_wmw - 1;
+ if (new_size < p_wmw)
+ new_size = p_wmw;
+
+ /* if it doesn't fit in the current window, need win_equal() */
+ if (oldwin->w_width - new_size - 1 < p_wmw)
+ do_equal = TRUE;
+ }
+ else
+#endif
+ {
+ layout = FR_COL;
+ do_equal = (p_ea && new_size == 0
+#ifdef FEAT_VERTSPLIT
+ && *p_ead != 'h'
+#endif
+ );
+
+ /*
+ * Check if we are able to split the current window and compute its
+ * height.
+ */
+ needed = p_wmh + STATUS_HEIGHT + need_status;
+ if (flags & WSP_ROOM)
+ needed += p_wh - p_wmh;
+ if (p_ea || (flags & (WSP_BOT | WSP_TOP)))
+ {
+ available = topframe->fr_height;
+ needed += frame_minheight(topframe, NULL);
+ }
+ else
+ {
+ available = oldwin->w_height;
+ needed += p_wmh;
+ }
+ if (available < needed && newwin == NULL)
+ {
+ EMSG(_(e_noroom));
+ return FAIL;
+ }
+ oldwin_height = oldwin->w_height;
+ if (need_status)
+ {
+ oldwin->w_status_height = STATUS_HEIGHT;
+ oldwin_height -= STATUS_HEIGHT;
+ }
+ if (new_size == 0)
+ new_size = oldwin_height / 2;
+
+ if (new_size > oldwin_height - p_wmh - STATUS_HEIGHT)
+ new_size = oldwin_height - p_wmh - STATUS_HEIGHT;
+ if (new_size < p_wmh)
+ new_size = p_wmh;
+
+ /* if it doesn't fit in the current window, need win_equal() */
+ if (oldwin_height - new_size - STATUS_HEIGHT < p_wmh)
+ do_equal = TRUE;
+
+ /* We don't like to take lines for the new window from a
+ * 'winfixheight' window. Take them from a window above or below
+ * instead, if possible. */
+ if (oldwin->w_p_wfh)
+ {
+ win_setheight_win(oldwin->w_height + new_size + STATUS_HEIGHT,
+ oldwin);
+ oldwin_height = oldwin->w_height;
+ if (need_status)
+ oldwin_height -= STATUS_HEIGHT;
+ }
+ }
+
+ /*
+ * allocate new window structure and link it in the window list
+ */
+ if ((flags & WSP_TOP) == 0
+ && ((flags & WSP_BOT)
+ || (flags & WSP_BELOW)
+ || (!(flags & WSP_ABOVE)
+ && (
+#ifdef FEAT_VERTSPLIT
+ (flags & WSP_VERT) ? p_spr :
+#endif
+ p_sb))))
+ {
+ /* new window below/right of current one */
+ if (newwin == NULL)
+ wp = win_alloc(oldwin);
+ else
+ win_append(oldwin, wp);
+ }
+ else
+ {
+ if (newwin == NULL)
+ wp = win_alloc(oldwin->w_prev);
+ else
+ win_append(oldwin->w_prev, wp);
+ }
+
+ if (newwin == NULL)
+ {
+ if (wp == NULL)
+ return FAIL;
+
+ /*
+ * make the contents of the new window the same as the current one
+ */
+ wp->w_buffer = curbuf;
+ curbuf->b_nwindows++;
+ wp->w_cursor = curwin->w_cursor;
+ wp->w_valid = 0;
+ wp->w_curswant = curwin->w_curswant;
+ wp->w_set_curswant = curwin->w_set_curswant;
+ wp->w_topline = curwin->w_topline;
+#ifdef FEAT_DIFF
+ wp->w_topfill = curwin->w_topfill;
+#endif
+ wp->w_leftcol = curwin->w_leftcol;
+ wp->w_pcmark = curwin->w_pcmark;
+ wp->w_prev_pcmark = curwin->w_prev_pcmark;
+ wp->w_alt_fnum = curwin->w_alt_fnum;
+ wp->w_fraction = curwin->w_fraction;
+ wp->w_prev_fraction_row = curwin->w_prev_fraction_row;
+#ifdef FEAT_JUMPLIST
+ copy_jumplist(curwin, wp);
+#endif
+ if (curwin->w_localdir != NULL)
+ wp->w_localdir = vim_strsave(curwin->w_localdir);
+
+ /* Use the same argument list. */
+ wp->w_alist = curwin->w_alist;
+ ++wp->w_alist->al_refcount;
+ wp->w_arg_idx = curwin->w_arg_idx;
+
+ /*
+ * copy tagstack and options from existing window
+ */
+ for (i = 0; i < curwin->w_tagstacklen; i++)
+ {
+ wp->w_tagstack[i] = curwin->w_tagstack[i];
+ if (wp->w_tagstack[i].tagname != NULL)
+ wp->w_tagstack[i].tagname =
+ vim_strsave(wp->w_tagstack[i].tagname);
+ }
+ wp->w_tagstackidx = curwin->w_tagstackidx;
+ wp->w_tagstacklen = curwin->w_tagstacklen;
+ win_copy_options(curwin, wp);
+#ifdef FEAT_FOLDING
+ copyFoldingState(curwin, wp);
+#endif
+ }
+
+ /*
+ * Reorganise the tree of frames to insert the new window.
+ */
+ if (flags & (WSP_TOP | WSP_BOT))
+ {
+#ifdef FEAT_VERTSPLIT
+ if ((topframe->fr_layout == FR_COL && (flags & WSP_VERT) == 0)
+ || (topframe->fr_layout == FR_ROW && (flags & WSP_VERT) != 0))
+#else
+ if (topframe->fr_layout == FR_COL)
+#endif
+ {
+ curfrp = topframe->fr_child;
+ if (flags & WSP_BOT)
+ while (curfrp->fr_next != NULL)
+ curfrp = curfrp->fr_next;
+ }
+ else
+ curfrp = topframe;
+ before = (flags & WSP_TOP);
+ }
+ else
+ {
+ curfrp = oldwin->w_frame;
+ if (flags & WSP_BELOW)
+ before = FALSE;
+ else if (flags & WSP_ABOVE)
+ before = TRUE;
+ else
+#ifdef FEAT_VERTSPLIT
+ if (flags & WSP_VERT)
+ before = !p_spr;
+ else
+#endif
+ before = !p_sb;
+ }
+ if (curfrp->fr_parent == NULL || curfrp->fr_parent->fr_layout != layout)
+ {
+ /* Need to create a new frame in the tree to make a branch. */
+ frp = (frame_T *)alloc_clear((unsigned)sizeof(frame_T));
+ *frp = *curfrp;
+ curfrp->fr_layout = layout;
+ frp->fr_parent = curfrp;
+ frp->fr_next = NULL;
+ frp->fr_prev = NULL;
+ curfrp->fr_child = frp;
+ curfrp->fr_win = NULL;
+ curfrp = frp;
+ if (frp->fr_win != NULL)
+ oldwin->w_frame = frp;
+ else
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
+ frp->fr_parent = curfrp;
+ }
+
+ if (newwin == NULL)
+ {
+ /* Create a frame for the new window. */
+ frp = (frame_T *)alloc_clear((unsigned)sizeof(frame_T));
+ frp->fr_layout = FR_LEAF;
+ frp->fr_win = wp;
+ wp->w_frame = frp;
+ }
+ else
+ frp = newwin->w_frame;
+ frp->fr_parent = curfrp->fr_parent;
+
+ /* Insert the new frame at the right place in the frame list. */
+ if (before)
+ frame_insert(curfrp, frp);
+ else
+ frame_append(curfrp, frp);
+
+#ifdef FEAT_VERTSPLIT
+ if (flags & WSP_VERT)
+ {
+ wp->w_p_scr = curwin->w_p_scr;
+ if (need_status)
+ {
+ --oldwin->w_height;
+ oldwin->w_status_height = need_status;
+ }
+ if (flags & (WSP_TOP | WSP_BOT))
+ {
+ /* set height and row of new window to full height */
+ wp->w_winrow = 0;
+ wp->w_height = curfrp->fr_height - (p_ls > 0);
+ wp->w_status_height = (p_ls > 0);
+ }
+ else
+ {
+ /* height and row of new window is same as current window */
+ wp->w_winrow = oldwin->w_winrow;
+ wp->w_height = oldwin->w_height;
+ wp->w_status_height = oldwin->w_status_height;
+ }
+ frp->fr_height = curfrp->fr_height;
+
+ /* "new_size" of the current window goes to the new window, use
+ * one column for the vertical separator */
+ wp->w_width = new_size;
+ if (before)
+ wp->w_vsep_width = 1;
+ else
+ {
+ wp->w_vsep_width = oldwin->w_vsep_width;
+ oldwin->w_vsep_width = 1;
+ }
+ if (flags & (WSP_TOP | WSP_BOT))
+ {
+ if (flags & WSP_BOT)
+ frame_add_vsep(curfrp);
+ /* Set width of neighbor frame */
+ frame_new_width(curfrp, curfrp->fr_width
+ - (new_size + ((flags & WSP_TOP) != 0)), flags & WSP_TOP);
+ }
+ else
+ oldwin->w_width -= new_size + 1;
+ if (before) /* new window left of current one */
+ {
+ wp->w_wincol = oldwin->w_wincol;
+ oldwin->w_wincol += new_size + 1;
+ }
+ else /* new window right of current one */
+ wp->w_wincol = oldwin->w_wincol + oldwin->w_width + 1;
+ frame_fix_width(oldwin);
+ frame_fix_width(wp);
+ }
+ else
+#endif
+ {
+ /* width and column of new window is same as current window */
+#ifdef FEAT_VERTSPLIT
+ if (flags & (WSP_TOP | WSP_BOT))
+ {
+ wp->w_wincol = 0;
+ wp->w_width = Columns;
+ wp->w_vsep_width = 0;
+ }
+ else
+ {
+ wp->w_wincol = oldwin->w_wincol;
+ wp->w_width = oldwin->w_width;
+ wp->w_vsep_width = oldwin->w_vsep_width;
+ }
+ frp->fr_width = curfrp->fr_width;
+#endif
+
+ /* "new_size" of the current window goes to the new window, use
+ * one row for the status line */
+ win_new_height(wp, new_size);
+ if (flags & (WSP_TOP | WSP_BOT))
+ frame_new_height(curfrp, curfrp->fr_height
+ - (new_size + STATUS_HEIGHT), flags & WSP_TOP, FALSE);
+ else
+ win_new_height(oldwin, oldwin_height - (new_size + STATUS_HEIGHT));
+ if (before) /* new window above current one */
+ {
+ wp->w_winrow = oldwin->w_winrow;
+ wp->w_status_height = STATUS_HEIGHT;
+ oldwin->w_winrow += wp->w_height + STATUS_HEIGHT;
+ }
+ else /* new window below current one */
+ {
+ wp->w_winrow = oldwin->w_winrow + oldwin->w_height + STATUS_HEIGHT;
+ wp->w_status_height = oldwin->w_status_height;
+ oldwin->w_status_height = STATUS_HEIGHT;
+ }
+#ifdef FEAT_VERTSPLIT
+ if (flags & WSP_BOT)
+ frame_add_statusline(curfrp);
+#endif
+ frame_fix_height(wp);
+ frame_fix_height(oldwin);
+ }
+
+ if (flags & (WSP_TOP | WSP_BOT))
+ (void)win_comp_pos();
+
+ /*
+ * Both windows need redrawing
+ */
+ redraw_win_later(wp, NOT_VALID);
+ wp->w_redr_status = TRUE;
+ redraw_win_later(oldwin, NOT_VALID);
+ oldwin->w_redr_status = TRUE;
+
+ if (need_status)
+ {
+ msg_row = Rows - 1;
+ msg_col = sc_col;
+ msg_clr_eos_force(); /* Old command/ruler may still be there */
+ comp_col();
+ msg_row = Rows - 1;
+ msg_col = 0; /* put position back at start of line */
+ }
+
+ /*
+ * make the new window the current window and redraw
+ */
+ if (do_equal || dir != 0)
+ win_equal(wp, TRUE,
+#ifdef FEAT_VERTSPLIT
+ (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
+ : dir == 'h' ? 'b' :
+#endif
+ 'v');
+
+ /* Don't change the window height/width to 'winheight' / 'winwidth' if a
+ * size was given. */
+#ifdef FEAT_VERTSPLIT
+ if (flags & WSP_VERT)
+ {
+ i = p_wiw;
+ if (size != 0)
+ p_wiw = size;
+
+# ifdef FEAT_GUI
+ /* When 'guioptions' includes 'L' or 'R' may have to add scrollbars. */
+ if (gui.in_use)
+ gui_init_which_components(NULL);
+# endif
+ }
+ else
+#endif
+ {
+ i = p_wh;
+ if (size != 0)
+ p_wh = size;
+ }
+ win_enter(wp, FALSE);
+#ifdef FEAT_VERTSPLIT
+ if (flags & WSP_VERT)
+ p_wiw = i;
+ else
+#endif
+ p_wh = i;
+
+ return OK;
+}
+
+#endif /* FEAT_WINDOWS */
+
+#ifdef FEAT_VERTSPLIT
+/*
+ * Return minimal height for window "wp" and windows east of it.
+ * Takes into account the eastbound windws can be split, each of them
+ * requireing p_wmh lines. Doesn't count status lines.
+ */
+ static int
+win_minheight(wp)
+ win_T *wp;
+{
+ int minheight = p_wmh;
+ int n;
+ win_T *wp1, *wp2;
+
+ wp1 = wp;
+ for (;;)
+ {
+ wp1 = wp1->w_next;
+ if (wp1 == NULL)
+ break;
+ n = p_wmh;
+ wp2 = wp1;
+ for (;;)
+ {
+ wp2 = wp2->w_next;
+ if (wp2 == NULL)
+ break;
+ n += win_minheight(wp2);
+ }
+ if (n > minheight)
+ minheight = n;
+ }
+ return minheight;
+}
+
+#endif
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * Check if "win" is a pointer to an existing window.
+ */
+ int
+win_valid(win)
+ win_T *win;
+{
+ win_T *wp;
+
+ if (win == NULL)
+ return FALSE;
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (wp == win)
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Return the number of windows.
+ */
+ int
+win_count()
+{
+ win_T *wp;
+ int count = 0;
+
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ ++count;
+ return count;
+}
+
+/*
+ * Make "count" windows on the screen.
+ * Return actual number of windows on the screen.
+ * Must be called when there is just one window, filling the whole screen
+ * (excluding the command line).
+ */
+/*ARGSUSED*/
+ int
+make_windows(count, vertical)
+ int count;
+ int vertical; /* split windows vertically if TRUE */
+{
+ int maxcount;
+ int todo;
+
+#ifdef FEAT_VERTSPLIT
+ if (vertical)
+ {
+ /* Each windows needs at least 'winminwidth' lines and a separator
+ * column. */
+ maxcount = (curwin->w_width + curwin->w_vsep_width
+ - (p_wiw - p_wmw)) / (p_wmw + 1);
+ }
+ else
+#endif
+ {
+ /* Each window needs at least 'winminheight' lines and a status line. */
+ maxcount = (curwin->w_height + curwin->w_status_height
+ - (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT);
+ }
+
+ if (maxcount < 2)
+ maxcount = 2;
+ if (count > maxcount)
+ count = maxcount;
+
+ /*
+ * add status line now, otherwise first window will be too big
+ */
+ if (count > 1)
+ last_status(TRUE);
+
+#ifdef FEAT_AUTOCMD
+ /*
+ * Don't execute autocommands while creating the windows. Must do that
+ * when putting the buffers in the windows.
+ */
+ ++autocmd_block;
+#endif
+
+ /* todo is number of windows left to create */
+ for (todo = count - 1; todo > 0; --todo)
+#ifdef FEAT_VERTSPLIT
+ if (vertical)
+ {
+ if (win_split(curwin->w_width - (curwin->w_width - todo)
+ / (todo + 1) - 1, WSP_VERT | WSP_ABOVE) == FAIL)
+ break;
+ }
+ else
+#endif
+ {
+ if (win_split(curwin->w_height - (curwin->w_height - todo
+ * STATUS_HEIGHT) / (todo + 1)
+ - STATUS_HEIGHT, WSP_ABOVE) == FAIL)
+ break;
+ }
+
+#ifdef FEAT_AUTOCMD
+ --autocmd_block;
+#endif
+
+ /* return actual number of windows */
+ return (count - todo);
+}
+
+/*
+ * Exchange current and next window
+ */
+ static void
+win_exchange(Prenum)
+ long Prenum;
+{
+ frame_T *frp;
+ frame_T *frp2;
+ win_T *wp;
+ win_T *wp2;
+ int temp;
+
+ if (lastwin == firstwin) /* just one window */
+ {
+ beep_flush();
+ return;
+ }
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+
+ /*
+ * find window to exchange with
+ */
+ if (Prenum)
+ {
+ frp = curwin->w_frame->fr_parent->fr_child;
+ while (frp != NULL && --Prenum > 0)
+ frp = frp->fr_next;
+ }
+ else if (curwin->w_frame->fr_next != NULL) /* Swap with next */
+ frp = curwin->w_frame->fr_next;
+ else /* Swap last window in row/col with previous */
+ frp = curwin->w_frame->fr_prev;
+
+ /* We can only exchange a window with another window, not with a frame
+ * containing windows. */
+ if (frp == NULL || frp->fr_win == NULL || frp->fr_win == curwin)
+ return;
+ wp = frp->fr_win;
+
+/*
+ * 1. remove curwin from the list. Remember after which window it was in wp2
+ * 2. insert curwin before wp in the list
+ * if wp != wp2
+ * 3. remove wp from the list
+ * 4. insert wp after wp2
+ * 5. exchange the status line height and vsep width.
+ */
+ wp2 = curwin->w_prev;
+ frp2 = curwin->w_frame->fr_prev;
+ if (wp->w_prev != curwin)
+ {
+ win_remove(curwin);
+ frame_remove(curwin->w_frame);
+ win_append(wp->w_prev, curwin);
+ frame_insert(frp, curwin->w_frame);
+ }
+ if (wp != wp2)
+ {
+ win_remove(wp);
+ frame_remove(wp->w_frame);
+ win_append(wp2, wp);
+ if (frp2 == NULL)
+ frame_insert(wp->w_frame->fr_parent->fr_child, wp->w_frame);
+ else
+ frame_append(frp2, wp->w_frame);
+ }
+ temp = curwin->w_status_height;
+ curwin->w_status_height = wp->w_status_height;
+ wp->w_status_height = temp;
+#ifdef FEAT_VERTSPLIT
+ temp = curwin->w_vsep_width;
+ curwin->w_vsep_width = wp->w_vsep_width;
+ wp->w_vsep_width = temp;
+
+ /* If the windows are not in the same frame, exchange the sizes to avoid
+ * messing up the window layout. Otherwise fix the frame sizes. */
+ if (curwin->w_frame->fr_parent != wp->w_frame->fr_parent)
+ {
+ temp = curwin->w_height;
+ curwin->w_height = wp->w_height;
+ wp->w_height = temp;
+ temp = curwin->w_width;
+ curwin->w_width = wp->w_width;
+ wp->w_width = temp;
+ }
+ else
+ {
+ frame_fix_height(curwin);
+ frame_fix_height(wp);
+ frame_fix_width(curwin);
+ frame_fix_width(wp);
+ }
+#endif
+
+ (void)win_comp_pos(); /* recompute window positions */
+
+ win_enter(wp, TRUE);
+ redraw_later(CLEAR);
+}
+
+/*
+ * rotate windows: if upwards TRUE the second window becomes the first one
+ * if upwards FALSE the first window becomes the second one
+ */
+ static void
+win_rotate(upwards, count)
+ int upwards;
+ int count;
+{
+ win_T *wp1;
+ win_T *wp2;
+ frame_T *frp;
+ int n;
+
+ if (firstwin == lastwin) /* nothing to do */
+ {
+ beep_flush();
+ return;
+ }
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+
+#ifdef FEAT_VERTSPLIT
+ /* Check if all frames in this row/col have one window. */
+ for (frp = curwin->w_frame->fr_parent->fr_child; frp != NULL;
+ frp = frp->fr_next)
+ if (frp->fr_win == NULL)
+ {
+ EMSG(_("E443: Cannot rotate when another window is split"));
+ return;
+ }
+#endif
+
+ while (count--)
+ {
+ if (upwards) /* first window becomes last window */
+ {
+ /* remove first window/frame from the list */
+ frp = curwin->w_frame->fr_parent->fr_child;
+ wp1 = frp->fr_win;
+ win_remove(wp1);
+ frame_remove(frp);
+
+ /* find last frame and append removed window/frame after it */
+ for ( ; frp->fr_next != NULL; frp = frp->fr_next)
+ ;
+ win_append(frp->fr_win, wp1);
+ frame_append(frp, wp1->w_frame);
+
+ wp2 = frp->fr_win; /* previously last window */
+ }
+ else /* last window becomes first window */
+ {
+ /* find last window/frame in the list and remove it */
+ for (frp = curwin->w_frame; frp->fr_next != NULL;
+ frp = frp->fr_next)
+ ;
+ wp1 = frp->fr_win;
+ wp2 = wp1->w_prev; /* will become last window */
+ win_remove(wp1);
+ frame_remove(frp);
+
+ /* append the removed window/frame before the first in the list */
+ win_append(frp->fr_parent->fr_child->fr_win->w_prev, wp1);
+ frame_insert(frp->fr_parent->fr_child, frp);
+ }
+
+ /* exchange status height and vsep width of old and new last window */
+ n = wp2->w_status_height;
+ wp2->w_status_height = wp1->w_status_height;
+ wp1->w_status_height = n;
+ frame_fix_height(wp1);
+ frame_fix_height(wp2);
+#ifdef FEAT_VERTSPLIT
+ n = wp2->w_vsep_width;
+ wp2->w_vsep_width = wp1->w_vsep_width;
+ wp1->w_vsep_width = n;
+ frame_fix_width(wp1);
+ frame_fix_width(wp2);
+#endif
+
+ /* recompute w_winrow and w_wincol for all windows */
+ (void)win_comp_pos();
+ }
+
+ redraw_later(CLEAR);
+}
+
+/*
+ * Move the current window to the very top/bottom/left/right of the screen.
+ */
+ static void
+win_totop(size, flags)
+ int size;
+ int flags;
+{
+ int dir;
+ int height = curwin->w_height;
+
+ if (lastwin == firstwin)
+ {
+ beep_flush();
+ return;
+ }
+
+ /* Remove the window and frame from the tree of frames. */
+ (void)winframe_remove(curwin, &dir);
+ win_remove(curwin);
+ last_status(FALSE); /* may need to remove last status line */
+ (void)win_comp_pos(); /* recompute window positions */
+
+ /* Split a window on the desired side and put the window there. */
+ (void)win_split_ins(size, flags, curwin, dir);
+ if (!(flags & WSP_VERT))
+ {
+ win_setheight(height);
+ if (p_ea)
+ win_equal(curwin, TRUE, 'v');
+ }
+
+#if defined(FEAT_GUI) && defined(FEAT_VERTSPLIT)
+ /* When 'guioptions' includes 'L' or 'R' may have to remove or add
+ * scrollbars. Have to update them anyway. */
+ if (gui.in_use)
+ {
+ out_flush();
+ gui_init_which_components(NULL);
+ gui_update_scrollbars(TRUE);
+ }
+ need_mouse_correct = TRUE;
+#endif
+
+}
+
+/*
+ * Move window "win1" to below/right of "win2" and make "win1" the current
+ * window. Only works within the same frame!
+ */
+ void
+win_move_after(win1, win2)
+ win_T *win1, *win2;
+{
+ int height;
+
+ /* check if the arguments are reasonable */
+ if (win1 == win2)
+ return;
+
+ /* check if there is something to do */
+ if (win2->w_next != win1)
+ {
+ /* may need move the status line/vertical separator of the last window
+ * */
+ if (win1 == lastwin)
+ {
+ height = win1->w_prev->w_status_height;
+ win1->w_prev->w_status_height = win1->w_status_height;
+ win1->w_status_height = height;
+#ifdef FEAT_VERTSPLIT
+ win1->w_prev->w_vsep_width = 0;
+ win1->w_vsep_width = 1;
+#endif
+ }
+ else if (win2 == lastwin)
+ {
+ height = win1->w_status_height;
+ win1->w_status_height = win2->w_status_height;
+ win2->w_status_height = height;
+#ifdef FEAT_VERTSPLIT
+ win2->w_vsep_width = 1;
+ win1->w_vsep_width = 0;
+#endif
+ }
+ win_remove(win1);
+ frame_remove(win1->w_frame);
+ win_append(win2, win1);
+ frame_append(win2->w_frame, win1->w_frame);
+
+ (void)win_comp_pos(); /* recompute w_winrow for all windows */
+ redraw_later(NOT_VALID);
+ }
+ win_enter(win1, FALSE);
+}
+
+/*
+ * Make all windows the same height.
+ * 'next_curwin' will soon be the current window, make sure it has enough
+ * rows.
+ */
+ void
+win_equal(next_curwin, current, dir)
+ win_T *next_curwin; /* pointer to current window to be or NULL */
+ int current; /* do only frame with current window */
+ int dir; /* 'v' for vertically, 'h' for horizontally,
+ 'b' for both, 0 for using p_ead */
+{
+ if (dir == 0)
+#ifdef FEAT_VERTSPLIT
+ dir = *p_ead;
+#else
+ dir = 'b';
+#endif
+ win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current,
+ topframe, dir, 0, 0, (int)Columns, topframe->fr_height);
+}
+
+/*
+ * Set a frame to a new position and height, spreading the available room
+ * equally over contained frames.
+ * The window "next_curwin" (if not NULL) should at least get the size from
+ * 'winheight' and 'winwidth' if possible.
+ */
+ static void
+win_equal_rec(next_curwin, current, topfr, dir, col, row, width, height)
+ win_T *next_curwin; /* pointer to current window to be or NULL */
+ int current; /* do only frame with current window */
+ frame_T *topfr; /* frame to set size off */
+ int dir; /* 'v', 'h' or 'b', see win_equal() */
+ int col; /* horizontal position for frame */
+ int row; /* vertical position for frame */
+ int width; /* new width of frame */
+ int height; /* new height of frame */
+{
+ int n, m;
+ int extra_sep = 0;
+ int wincount, totwincount = 0;
+ frame_T *fr;
+ int next_curwin_size = 0;
+ int room = 0;
+ int new_size;
+ int has_next_curwin = 0;
+ int hnc;
+
+ if (topfr->fr_layout == FR_LEAF)
+ {
+ /* Set the width/height of this frame.
+ * Redraw when size or position changes */
+ if (topfr->fr_height != height || topfr->fr_win->w_winrow != row
+#ifdef FEAT_VERTSPLIT
+ || topfr->fr_width != width || topfr->fr_win->w_wincol != col
+#endif
+ )
+ {
+ topfr->fr_win->w_winrow = row;
+ frame_new_height(topfr, height, FALSE, FALSE);
+#ifdef FEAT_VERTSPLIT
+ topfr->fr_win->w_wincol = col;
+ frame_new_width(topfr, width, FALSE);
+#endif
+ redraw_all_later(CLEAR);
+ }
+ }
+#ifdef FEAT_VERTSPLIT
+ else if (topfr->fr_layout == FR_ROW)
+ {
+ topfr->fr_width = width;
+ topfr->fr_height = height;
+
+ if (dir != 'v') /* equalize frame widths */
+ {
+ /* Compute the maximum number of windows horizontally in this
+ * frame. */
+ n = frame_minwidth(topfr, NOWIN);
+ /* add one for the rightmost window, it doesn't have a separator */
+ if (col + width == Columns)
+ extra_sep = 1;
+ else
+ extra_sep = 0;
+ totwincount = (n + extra_sep) / (p_wmw + 1);
+
+ /* Compute room available for windows other than "next_curwin" */
+ m = frame_minwidth(topfr, next_curwin);
+ room = width - m;
+ if (room < 0)
+ {
+ next_curwin_size = p_wiw + room;
+ room = 0;
+ }
+ else if (n == m) /* doesn't contain curwin */
+ next_curwin_size = 0;
+ else
+ {
+ next_curwin_size = (room + p_wiw + (totwincount - 1) * p_wmw
+ + (totwincount - 1)) / totwincount;
+ if (next_curwin_size > p_wiw)
+ room -= next_curwin_size - p_wiw;
+ else
+ next_curwin_size = p_wiw;
+ }
+ if (n != m)
+ --totwincount; /* don't count curwin */
+ }
+
+ for (fr = topfr->fr_child; fr != NULL; fr = fr->fr_next)
+ {
+ n = m = 0;
+ wincount = 1;
+ if (fr->fr_next == NULL)
+ /* last frame gets all that remains (avoid roundoff error) */
+ new_size = width;
+ else if (dir == 'v')
+ new_size = fr->fr_width;
+ else
+ {
+ /* Compute the maximum number of windows horiz. in "fr". */
+ n = frame_minwidth(fr, NOWIN);
+ wincount = (n + (fr->fr_next == NULL ? extra_sep : 0))
+ / (p_wmw + 1);
+ m = frame_minwidth(fr, next_curwin);
+ if (n != m) /* don't count next_curwin */
+ --wincount;
+ new_size = (wincount * room + ((unsigned)totwincount >> 1))
+ / totwincount;
+ if (n != m) /* add next_curwin size */
+ {
+ next_curwin_size -= p_wiw - (m - n);
+ new_size += next_curwin_size;
+ }
+ }
+
+ /* Skip frame that is full height when splitting or closing a
+ * window, unless equalizing all frames. */
+ if (!current || dir != 'v' || topfr->fr_parent != NULL
+ || (new_size != fr->fr_width)
+ || frame_has_win(fr, next_curwin))
+ win_equal_rec(next_curwin, current, fr, dir, col, row,
+ new_size + n, height);
+ col += new_size + n;
+ width -= new_size + n;
+ if (n != m) /* contains curwin */
+ room -= new_size - next_curwin_size;
+ else
+ room -= new_size;
+ totwincount -= wincount;
+ }
+ }
+#endif
+ else /* topfr->fr_layout == FR_COL */
+ {
+#ifdef FEAT_VERTSPLIT
+ topfr->fr_width = width;
+#endif
+ topfr->fr_height = height;
+
+ if (dir != 'h') /* equalize frame heights */
+ {
+ /* Compute maximum number of windows vertically in this frame. */
+ n = frame_minheight(topfr, NOWIN);
+ /* add one for the bottom window if it doesn't have a statusline */
+ if (row + height == cmdline_row && p_ls == 0)
+ extra_sep = 1;
+ else
+ extra_sep = 0;
+ totwincount = (n + extra_sep) / (p_wmh + 1);
+ has_next_curwin = frame_has_win(topfr, next_curwin);
+
+ /*
+ * Compute height for "next_curwin" window and room available for
+ * other windows.
+ * "m" is the minimal height when counting p_wh for "next_curwin".
+ */
+ m = frame_minheight(topfr, next_curwin);
+ room = height - m;
+ if (room < 0)
+ {
+ /* The room is less then 'winheight', use all space for the
+ * current window. */
+ next_curwin_size = p_wh + room;
+ room = 0;
+ }
+ else
+ {
+ next_curwin_size = -1;
+ for (fr = topfr->fr_child; fr != NULL; fr = fr->fr_next)
+ {
+ /* If 'winfixheight' set keep the window height if
+ * possible.
+ * Watch out for this window being the next_curwin. */
+ if (frame_fixed_height(fr))
+ {
+ n = frame_minheight(fr, NOWIN);
+ new_size = fr->fr_height;
+ if (frame_has_win(fr, next_curwin))
+ {
+ room += p_wh - p_wmh;
+ next_curwin_size = 0;
+ if (new_size < p_wh)
+ new_size = p_wh;
+ }
+ else
+ /* These windows don't use up room. */
+ totwincount -= (n + (fr->fr_next == NULL
+ ? extra_sep : 0)) / (p_wmh + 1);
+ room -= new_size - n;
+ if (room < 0)
+ {
+ new_size += room;
+ room = 0;
+ }
+ fr->fr_newheight = new_size;
+ }
+ }
+ if (next_curwin_size == -1)
+ {
+ if (!has_next_curwin)
+ next_curwin_size = 0;
+ else if (totwincount > 1
+ && (room + (totwincount - 2))
+ / (totwincount - 1) > p_wh)
+ {
+ next_curwin_size = (room + p_wh + totwincount * p_wmh
+ + (totwincount - 1)) / totwincount;
+ room -= next_curwin_size - p_wh;
+ }
+ else
+ next_curwin_size = p_wh;
+ }
+ }
+
+ if (has_next_curwin)
+ --totwincount; /* don't count curwin */
+ }
+
+ for (fr = topfr->fr_child; fr != NULL; fr = fr->fr_next)
+ {
+ n = m = 0;
+ wincount = 1;
+ if (fr->fr_next == NULL)
+ /* last frame gets all that remains (avoid roundoff error) */
+ new_size = height;
+ else if (dir == 'h')
+ new_size = fr->fr_height;
+ else if (frame_fixed_height(fr))
+ {
+ new_size = fr->fr_newheight;
+ wincount = 0; /* doesn't count as a sizeable window */
+ }
+ else
+ {
+ /* Compute the maximum number of windows vert. in "fr". */
+ n = frame_minheight(fr, NOWIN);
+ wincount = (n + (fr->fr_next == NULL ? extra_sep : 0))
+ / (p_wmh + 1);
+ m = frame_minheight(fr, next_curwin);
+ if (has_next_curwin)
+ hnc = frame_has_win(fr, next_curwin);
+ else
+ hnc = FALSE;
+ if (hnc) /* don't count next_curwin */
+ --wincount;
+ if (totwincount == 0)
+ new_size = room;
+ else
+ new_size = (wincount * room + ((unsigned)totwincount >> 1))
+ / totwincount;
+ if (hnc) /* add next_curwin size */
+ {
+ next_curwin_size -= p_wh - (m - n);
+ new_size += next_curwin_size;
+ room -= new_size - next_curwin_size;
+ }
+ else
+ room -= new_size;
+ new_size += n;
+ }
+ /* Skip frame that is full width when splitting or closing a
+ * window, unless equalizing all frames. */
+ if (!current || dir != 'h' || topfr->fr_parent != NULL
+ || (new_size != fr->fr_height)
+ || frame_has_win(fr, next_curwin))
+ win_equal_rec(next_curwin, current, fr, dir, col, row,
+ width, new_size);
+ row += new_size;
+ height -= new_size;
+ totwincount -= wincount;
+ }
+ }
+}
+
+/*
+ * close all windows for buffer 'buf'
+ */
+ void
+close_windows(buf)
+ buf_T *buf;
+{
+ win_T *win;
+
+ ++RedrawingDisabled;
+ for (win = firstwin; win != NULL && lastwin != firstwin; )
+ {
+ if (win->w_buffer == buf)
+ {
+ win_close(win, FALSE);
+ win = firstwin; /* go back to the start */
+ }
+ else
+ win = win->w_next;
+ }
+ --RedrawingDisabled;
+}
+
+/*
+ * close window "win"
+ * If "free_buf" is TRUE related buffer may be unloaded.
+ *
+ * called by :quit, :close, :xit, :wq and findtag()
+ */
+ void
+win_close(win, free_buf)
+ win_T *win;
+ int free_buf;
+{
+ win_T *wp;
+#ifdef FEAT_AUTOCMD
+ int other_buffer = FALSE;
+#endif
+ int close_curwin = FALSE;
+ frame_T *frp;
+ int dir;
+ int help_window = FALSE;
+
+ if (lastwin == firstwin)
+ {
+ EMSG(_("E444: Cannot close last window"));
+ return;
+ }
+
+ /* When closing the help window, try restoring a snapshot after closing
+ * the window. Otherwise clear the snapshot, it's now invalid. */
+ if (win->w_buffer->b_help)
+ help_window = TRUE;
+ else
+ clear_snapshot();
+
+#ifdef FEAT_AUTOCMD
+ if (win == curwin)
+ {
+ /*
+ * Guess which window is going to be the new current window.
+ * This may change because of the autocommands (sigh).
+ */
+ wp = frame2win(win_altframe(win));
+
+ /*
+ * Be careful: If autocommands delete the window, return now.
+ */
+ if (wp->w_buffer != curbuf)
+ {
+ other_buffer = TRUE;
+ apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
+ if (!win_valid(win) || firstwin == lastwin)
+ return;
+ }
+ apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
+ if (!win_valid(win) || firstwin == lastwin)
+ return;
+# ifdef FEAT_EVAL
+ /* autocmds may abort script processing */
+ if (aborting())
+ return;
+# endif
+ }
+#endif
+
+ /*
+ * Close the link to the buffer.
+ */
+ close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0);
+ /* Autocommands may have closed the window already, or closed the only
+ * other window. */
+ if (!win_valid(win) || firstwin == lastwin)
+ return;
+
+ /* reduce the reference count to the argument list. */
+ alist_unlink(win->w_alist);
+
+ /* remove the window and its frame from the tree of frames. */
+ frp = win->w_frame;
+ wp = winframe_remove(win, &dir);
+ vim_free(frp);
+ win_free(win);
+
+ /* Make sure curwin isn't invalid. It can cause severe trouble when
+ * printing an error message. For win_equal() curbuf needs to be valid
+ * too. */
+ if (win == curwin)
+ {
+ curwin = wp;
+#ifdef FEAT_QUICKFIX
+ if (wp->w_p_pvw || bt_quickfix(wp->w_buffer))
+ {
+ /*
+ * The cursor goes to the preview or the quickfix window, try
+ * finding another window to go to.
+ */
+ for (;;)
+ {
+ if (wp->w_next == NULL)
+ wp = firstwin;
+ else
+ wp = wp->w_next;
+ if (wp == curwin)
+ break;
+ if (!wp->w_p_pvw && !bt_quickfix(wp->w_buffer))
+ {
+ curwin = wp;
+ break;
+ }
+ }
+ }
+#endif
+ curbuf = curwin->w_buffer;
+ close_curwin = TRUE;
+ }
+ if (p_ea)
+ win_equal(curwin, TRUE,
+#ifdef FEAT_VERTSPLIT
+ dir
+#else
+ 0
+#endif
+ );
+ else
+ win_comp_pos();
+ if (close_curwin)
+ {
+ win_enter_ext(wp, FALSE, TRUE);
+#ifdef FEAT_AUTOCMD
+ if (other_buffer)
+ /* careful: after this wp and win may be invalid! */
+ apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
+#endif
+ }
+
+ /*
+ * if last window has a status line now and we don't want one,
+ * remove the status line
+ */
+ last_status(FALSE);
+
+ /* After closing the help window, try restoring the window layout from
+ * before it was opened. */
+ if (help_window)
+ restore_snapshot(close_curwin);
+
+#if defined(FEAT_GUI) && defined(FEAT_VERTSPLIT)
+ /* When 'guioptions' includes 'L' or 'R' may have to remove scrollbars. */
+ if (gui.in_use && !win_hasvertsplit())
+ gui_init_which_components(NULL);
+#endif
+
+ redraw_all_later(NOT_VALID);
+}
+
+/*
+ * Remove a window and its frame from the tree of frames.
+ * Returns a pointer to the window that got the freed up space.
+ */
+/*ARGSUSED*/
+ static win_T *
+winframe_remove(win, dirp)
+ win_T *win;
+ int *dirp; /* set to 'v' or 'h' for direction if 'ea' */
+{
+ frame_T *frp, *frp2, *frp3;
+ frame_T *frp_close = win->w_frame;
+ win_T *wp;
+ int old_height = 0;
+
+ /*
+ * Remove the window from its frame.
+ */
+ frp2 = win_altframe(win);
+ wp = frame2win(frp2);
+
+ /* Remove this frame from the list of frames. */
+ frame_remove(frp_close);
+
+#ifdef FEAT_VERTSPLIT
+ if (frp_close->fr_parent->fr_layout == FR_COL)
+ {
+#endif
+ /* When 'winfixheight' is set, remember its old size and restore
+ * it later (it's a simplistic solution...). Don't do this if the
+ * window will occupy the full height of the screen. */
+ if (frp2->fr_win != NULL
+ && (frp2->fr_next != NULL || frp2->fr_prev != NULL)
+ && frp2->fr_win->w_p_wfh)
+ old_height = frp2->fr_win->w_height;
+ frame_new_height(frp2, frp2->fr_height + frp_close->fr_height,
+ frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE);
+ if (old_height != 0)
+ win_setheight_win(old_height, frp2->fr_win);
+#ifdef FEAT_VERTSPLIT
+ *dirp = 'v';
+ }
+ else
+ {
+ frame_new_width(frp2, frp2->fr_width + frp_close->fr_width,
+ frp2 == frp_close->fr_next ? TRUE : FALSE);
+ *dirp = 'h';
+ }
+#endif
+
+ /* If rows/columns go to a window below/right its positions need to be
+ * updated. Can only be done after the sizes have been updated. */
+ if (frp2 == frp_close->fr_next)
+ {
+ int row = win->w_winrow;
+ int col = W_WINCOL(win);
+
+ frame_comp_pos(frp2, &row, &col);
+ }
+
+ if (frp2->fr_next == NULL && frp2->fr_prev == NULL)
+ {
+ /* There is no other frame in this list, move its info to the parent
+ * and remove it. */
+ frp2->fr_parent->fr_layout = frp2->fr_layout;
+ frp2->fr_parent->fr_child = frp2->fr_child;
+ for (frp = frp2->fr_child; frp != NULL; frp = frp->fr_next)
+ frp->fr_parent = frp2->fr_parent;
+ frp2->fr_parent->fr_win = frp2->fr_win;
+ if (frp2->fr_win != NULL)
+ frp2->fr_win->w_frame = frp2->fr_parent;
+ frp = frp2->fr_parent;
+ vim_free(frp2);
+
+ frp2 = frp->fr_parent;
+ if (frp2 != NULL && frp2->fr_layout == frp->fr_layout)
+ {
+ /* The frame above the parent has the same layout, have to merge
+ * the frames into this list. */
+ if (frp2->fr_child == frp)
+ frp2->fr_child = frp->fr_child;
+ frp->fr_child->fr_prev = frp->fr_prev;
+ if (frp->fr_prev != NULL)
+ frp->fr_prev->fr_next = frp->fr_child;
+ for (frp3 = frp->fr_child; ; frp3 = frp3->fr_next)
+ {
+ frp3->fr_parent = frp2;
+ if (frp3->fr_next == NULL)
+ {
+ frp3->fr_next = frp->fr_next;
+ if (frp->fr_next != NULL)
+ frp->fr_next->fr_prev = frp3;
+ break;
+ }
+ }
+ vim_free(frp);
+ }
+ }
+
+ return wp;
+}
+
+/*
+ * Find out which frame is going to get the freed up space when "win" is
+ * closed.
+ * if 'splitbelow'/'splitleft' the space goes to the window above/left.
+ * if 'nosplitbelow'/'nosplitleft' the space goes to the window below/right.
+ * This makes opening a window and closing it immediately keep the same window
+ * layout.
+ */
+ static frame_T *
+win_altframe(win)
+ win_T *win;
+{
+ frame_T *frp;
+ int b;
+
+ frp = win->w_frame;
+#ifdef FEAT_VERTSPLIT
+ if (frp->fr_parent->fr_layout == FR_ROW)
+ b = p_spr;
+ else
+#endif
+ b = p_sb;
+ if ((!b && frp->fr_next != NULL) || frp->fr_prev == NULL)
+ return frp->fr_next;
+ return frp->fr_prev;
+}
+
+/*
+ * Find the left-upper window in frame "frp".
+ */
+ static win_T *
+frame2win(frp)
+ frame_T *frp;
+{
+ while (frp->fr_win == NULL)
+ frp = frp->fr_child;
+ return frp->fr_win;
+}
+
+/*
+ * Return TRUE if frame "frp" contains window "wp".
+ */
+ static int
+frame_has_win(frp, wp)
+ frame_T *frp;
+ win_T *wp;
+{
+ frame_T *p;
+
+ if (frp->fr_layout == FR_LEAF)
+ return frp->fr_win == wp;
+
+ for (p = frp->fr_child; p != NULL; p = p->fr_next)
+ if (frame_has_win(p, wp))
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Set a new height for a frame. Recursively sets the height for contained
+ * frames and windows. Caller must take care of positions.
+ */
+ static void
+frame_new_height(topfrp, height, topfirst, wfh)
+ frame_T *topfrp;
+ int height;
+ int topfirst; /* resize topmost contained frame first */
+ int wfh; /* obey 'winfixheight' when there is a choice;
+ may cause the height not to be set */
+{
+ frame_T *frp;
+ int extra_lines;
+ int h;
+
+ if (topfrp->fr_win != NULL)
+ {
+ /* Simple case: just one window. */
+ win_new_height(topfrp->fr_win,
+ height - topfrp->fr_win->w_status_height);
+ }
+#ifdef FEAT_VERTSPLIT
+ else if (topfrp->fr_layout == FR_ROW)
+ {
+ do
+ {
+ /* All frames in this row get the same new height. */
+ for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
+ {
+ frame_new_height(frp, height, topfirst, wfh);
+ if (frp->fr_height > height)
+ {
+ /* Could not fit the windows, make the whole row higher. */
+ height = frp->fr_height;
+ break;
+ }
+ }
+ }
+ while (frp != NULL);
+ }
+#endif
+ else
+ {
+ /* Complicated case: Resize a column of frames. Resize the bottom
+ * frame first, frames above that when needed. */
+
+ frp = topfrp->fr_child;
+ if (wfh)
+ /* Advance past frames with one window with 'wfh' set. */
+ while (frame_fixed_height(frp))
+ {
+ frp = frp->fr_next;
+ if (frp == NULL)
+ return; /* no frame without 'wfh', give up */
+ }
+ if (!topfirst)
+ {
+ /* Find the bottom frame of this column */
+ while (frp->fr_next != NULL)
+ frp = frp->fr_next;
+ if (wfh)
+ /* Advance back for frames with one window with 'wfh' set. */
+ while (frame_fixed_height(frp))
+ frp = frp->fr_prev;
+ }
+
+ extra_lines = height - topfrp->fr_height;
+ if (extra_lines < 0)
+ {
+ /* reduce height of contained frames, bottom or top frame first */
+ while (frp != NULL)
+ {
+ h = frame_minheight(frp, NULL);
+ if (frp->fr_height + extra_lines < h)
+ {
+ extra_lines += frp->fr_height - h;
+ frame_new_height(frp, h, topfirst, wfh);
+ }
+ else
+ {
+ frame_new_height(frp, frp->fr_height + extra_lines,
+ topfirst, wfh);
+ break;
+ }
+ if (topfirst)
+ {
+ do
+ frp = frp->fr_next;
+ while (wfh && frp != NULL && frame_fixed_height(frp));
+ }
+ else
+ {
+ do
+ frp = frp->fr_prev;
+ while (wfh && frp != NULL && frame_fixed_height(frp));
+ }
+ /* Increase "height" if we could not reduce enough frames. */
+ if (frp == NULL)
+ height -= extra_lines;
+ }
+ }
+ else if (extra_lines > 0)
+ {
+ /* increase height of bottom or top frame */
+ frame_new_height(frp, frp->fr_height + extra_lines, topfirst, wfh);
+ }
+ }
+ topfrp->fr_height = height;
+}
+
+/*
+ * Return TRUE if height of frame "frp" should not be changed because of
+ * the 'winfixheight' option.
+ */
+ static int
+frame_fixed_height(frp)
+ frame_T *frp;
+{
+ /* frame with one window: fixed height if 'winfixheight' set. */
+ if (frp->fr_win != NULL)
+ return frp->fr_win->w_p_wfh;
+
+ if (frp->fr_layout == FR_ROW)
+ {
+ /* The frame is fixed height if one of the frames in the row is fixed
+ * height. */
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
+ if (frame_fixed_height(frp))
+ return TRUE;
+ return FALSE;
+ }
+
+ /* frp->fr_layout == FR_COL: The frame is fixed height if all of the
+ * frames in the row are fixed height. */
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
+ if (!frame_fixed_height(frp))
+ return FALSE;
+ return TRUE;
+}
+
+#ifdef FEAT_VERTSPLIT
+/*
+ * Add a status line to windows at the bottom of "frp".
+ * Note: Does not check if there is room!
+ */
+ static void
+frame_add_statusline(frp)
+ frame_T *frp;
+{
+ win_T *wp;
+
+ if (frp->fr_layout == FR_LEAF)
+ {
+ wp = frp->fr_win;
+ if (wp->w_status_height == 0)
+ {
+ if (wp->w_height > 0) /* don't make it negative */
+ --wp->w_height;
+ wp->w_status_height = STATUS_HEIGHT;
+ }
+ }
+ else if (frp->fr_layout == FR_ROW)
+ {
+ /* Handle all the frames in the row. */
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
+ frame_add_statusline(frp);
+ }
+ else /* frp->fr_layout == FR_COL */
+ {
+ /* Only need to handle the last frame in the column. */
+ for (frp = frp->fr_child; frp->fr_next != NULL; frp = frp->fr_next)
+ ;
+ frame_add_statusline(frp);
+ }
+}
+
+/*
+ * Set width of a frame. Handles recursively going through contained frames.
+ * May remove separator line for windows at the right side (for win_close()).
+ */
+ static void
+frame_new_width(topfrp, width, leftfirst)
+ frame_T *topfrp;
+ int width;
+ int leftfirst; /* resize leftmost contained frame first */
+{
+ frame_T *frp;
+ int extra_cols;
+ int w;
+ win_T *wp;
+
+ if (topfrp->fr_layout == FR_LEAF)
+ {
+ /* Simple case: just one window. */
+ wp = topfrp->fr_win;
+ /* Find out if there are any windows right of this one. */
+ for (frp = topfrp; frp->fr_parent != NULL; frp = frp->fr_parent)
+ if (frp->fr_parent->fr_layout == FR_ROW && frp->fr_next != NULL)
+ break;
+ if (frp->fr_parent == NULL)
+ wp->w_vsep_width = 0;
+ win_new_width(wp, width - wp->w_vsep_width);
+ }
+ else if (topfrp->fr_layout == FR_COL)
+ {
+ /* All frames in this column get the same new width. */
+ for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
+ frame_new_width(frp, width, leftfirst);
+ }
+ else /* fr_layout == FR_ROW */
+ {
+ /* Complicated case: Resize a row of frames. Resize the rightmost
+ * frame first, frames left of it when needed. */
+
+ /* Find the rightmost frame of this row */
+ frp = topfrp->fr_child;
+ if (!leftfirst)
+ while (frp->fr_next != NULL)
+ frp = frp->fr_next;
+
+ extra_cols = width - topfrp->fr_width;
+ if (extra_cols < 0)
+ {
+ /* reduce frame width, rightmost frame first */
+ while (frp != NULL)
+ {
+ w = frame_minwidth(frp, NULL);
+ if (frp->fr_width + extra_cols < w)
+ {
+ extra_cols += frp->fr_width - w;
+ frame_new_width(frp, w, leftfirst);
+ }
+ else
+ {
+ frame_new_width(frp, frp->fr_width + extra_cols, leftfirst);
+ break;
+ }
+ if (leftfirst)
+ frp = frp->fr_next;
+ else
+ frp = frp->fr_prev;
+ }
+ }
+ else if (extra_cols > 0)
+ {
+ /* increase width of rightmost frame */
+ frame_new_width(frp, frp->fr_width + extra_cols, leftfirst);
+ }
+ }
+ topfrp->fr_width = width;
+}
+
+/*
+ * Add the vertical separator to windows at the right side of "frp".
+ * Note: Does not check if there is room!
+ */
+ static void
+frame_add_vsep(frp)
+ frame_T *frp;
+{
+ win_T *wp;
+
+ if (frp->fr_layout == FR_LEAF)
+ {
+ wp = frp->fr_win;
+ if (wp->w_vsep_width == 0)
+ {
+ if (wp->w_width > 0) /* don't make it negative */
+ --wp->w_width;
+ wp->w_vsep_width = 1;
+ }
+ }
+ else if (frp->fr_layout == FR_COL)
+ {
+ /* Handle all the frames in the column. */
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
+ frame_add_vsep(frp);
+ }
+ else /* frp->fr_layout == FR_ROW */
+ {
+ /* Only need to handle the last frame in the row. */
+ frp = frp->fr_child;
+ while (frp->fr_next != NULL)
+ frp = frp->fr_next;
+ frame_add_vsep(frp);
+ }
+}
+
+/*
+ * Set frame width from the window it contains.
+ */
+ static void
+frame_fix_width(wp)
+ win_T *wp;
+{
+ wp->w_frame->fr_width = wp->w_width + wp->w_vsep_width;
+}
+#endif
+
+/*
+ * Set frame height from the window it contains.
+ */
+ static void
+frame_fix_height(wp)
+ win_T *wp;
+{
+ wp->w_frame->fr_height = wp->w_height + wp->w_status_height;
+}
+
+/*
+ * Compute the minimal height for frame "topfrp".
+ * Uses the 'winminheight' option.
+ * When "next_curwin" isn't NULL, use p_wh for this window.
+ * When "next_curwin" is NOWIN, don't use at least one line for the current
+ * window.
+ */
+ static int
+frame_minheight(topfrp, next_curwin)
+ frame_T *topfrp;
+ win_T *next_curwin;
+{
+ frame_T *frp;
+ int m;
+#ifdef FEAT_VERTSPLIT
+ int n;
+#endif
+
+ if (topfrp->fr_win != NULL)
+ {
+ if (topfrp->fr_win == next_curwin)
+ m = p_wh + topfrp->fr_win->w_status_height;
+ else
+ {
+ /* window: minimal height of the window plus status line */
+ m = p_wmh + topfrp->fr_win->w_status_height;
+ /* Current window is minimal one line high */
+ if (p_wmh == 0 && topfrp->fr_win == curwin && next_curwin == NULL)
+ ++m;
+ }
+ }
+#ifdef FEAT_VERTSPLIT
+ else if (topfrp->fr_layout == FR_ROW)
+ {
+ /* get the minimal height from each frame in this row */
+ m = 0;
+ for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
+ {
+ n = frame_minheight(frp, next_curwin);
+ if (n > m)
+ m = n;
+ }
+ }
+#endif
+ else
+ {
+ /* Add up the minimal heights for all frames in this column. */
+ m = 0;
+ for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
+ m += frame_minheight(frp, next_curwin);
+ }
+
+ return m;
+}
+
+#ifdef FEAT_VERTSPLIT
+/*
+ * Compute the minimal width for frame "topfrp".
+ * When "next_curwin" isn't NULL, use p_wiw for this window.
+ * When "next_curwin" is NOWIN, don't use at least one column for the current
+ * window.
+ */
+ static int
+frame_minwidth(topfrp, next_curwin)
+ frame_T *topfrp;
+ win_T *next_curwin; /* use p_wh and p_wiw for next_curwin */
+{
+ frame_T *frp;
+ int m, n;
+
+ if (topfrp->fr_win != NULL)
+ {
+ if (topfrp->fr_win == next_curwin)
+ m = p_wiw + topfrp->fr_win->w_vsep_width;
+ else
+ {
+ /* window: minimal width of the window plus separator column */
+ m = p_wmw + topfrp->fr_win->w_vsep_width;
+ /* Current window is minimal one column wide */
+ if (p_wmw == 0 && topfrp->fr_win == curwin && next_curwin == NULL)
+ ++m;
+ }
+ }
+ else if (topfrp->fr_layout == FR_COL)
+ {
+ /* get the minimal width from each frame in this column */
+ m = 0;
+ for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
+ {
+ n = frame_minwidth(frp, next_curwin);
+ if (n > m)
+ m = n;
+ }
+ }
+ else
+ {
+ /* Add up the minimal widths for all frames in this row. */
+ m = 0;
+ for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
+ m += frame_minwidth(frp, next_curwin);
+ }
+
+ return m;
+}
+#endif
+
+
+/*
+ * Try to close all windows except current one.
+ * Buffers in the other windows become hidden if 'hidden' is set, or '!' is
+ * used and the buffer was modified.
+ *
+ * Used by ":bdel" and ":only".
+ */
+ void
+close_others(message, forceit)
+ int message;
+ int forceit; /* always hide all other windows */
+{
+ win_T *wp;
+ win_T *nextwp;
+ int r;
+
+ if (lastwin == firstwin)
+ {
+ if (message
+#ifdef FEAT_AUTOCMD
+ && !autocmd_busy
+#endif
+ )
+ MSG(_("Already only one window"));
+ return;
+ }
+
+ /* Be very careful here: autocommands may change the window layout. */
+ for (wp = firstwin; win_valid(wp); wp = nextwp)
+ {
+ nextwp = wp->w_next;
+ if (wp != curwin) /* don't close current window */
+ {
+
+ /* Check if it's allowed to abandon this window */
+ r = can_abandon(wp->w_buffer, forceit);
+#ifdef FEAT_AUTOCMD
+ if (!win_valid(wp)) /* autocommands messed wp up */
+ {
+ nextwp = firstwin;
+ continue;
+ }
+#endif
+ if (!r)
+ {
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ if (message && (p_confirm || cmdmod.confirm) && p_write)
+ {
+ dialog_changed(wp->w_buffer, FALSE);
+# ifdef FEAT_AUTOCMD
+ if (!win_valid(wp)) /* autocommands messed wp up */
+ {
+ nextwp = firstwin;
+ continue;
+ }
+# endif
+ }
+ if (bufIsChanged(wp->w_buffer))
+#endif
+ continue;
+ }
+ win_close(wp, !P_HID(wp->w_buffer) && !bufIsChanged(wp->w_buffer));
+ }
+ }
+
+ /*
+ * If current window has a status line and we don't want one,
+ * remove the status line.
+ */
+ if (lastwin != firstwin)
+ EMSG(_("E445: Other window contains changes"));
+}
+
+#endif /* FEAT_WINDOWS */
+
+/*
+ * init the cursor in the window
+ *
+ * called when a new file is being edited
+ */
+ void
+win_init(wp)
+ win_T *wp;
+{
+ redraw_win_later(wp, NOT_VALID);
+ wp->w_lines_valid = 0;
+ wp->w_cursor.lnum = 1;
+ wp->w_curswant = wp->w_cursor.col = 0;
+#ifdef FEAT_VIRTUALEDIT
+ wp->w_cursor.coladd = 0;
+#endif
+ wp->w_pcmark.lnum = 1; /* pcmark not cleared but set to line 1 */
+ wp->w_pcmark.col = 0;
+ wp->w_prev_pcmark.lnum = 0;
+ wp->w_prev_pcmark.col = 0;
+ wp->w_topline = 1;
+#ifdef FEAT_DIFF
+ wp->w_topfill = 0;
+#endif
+ wp->w_botline = 2;
+#ifdef FEAT_FKMAP
+ if (curwin->w_p_rl)
+ wp->w_farsi = W_CONV + W_R_L;
+ else
+ wp->w_farsi = W_CONV;
+#endif
+}
+
+/*
+ * Allocate the first window and put an empty buffer in it.
+ * Called from main().
+ * When this fails we can't do anything: exit.
+ */
+ void
+win_alloc_first()
+{
+ curwin = win_alloc(NULL);
+ curbuf = buflist_new(NULL, NULL, 1L, BLN_LISTED);
+ if (curwin == NULL || curbuf == NULL)
+ mch_exit(0);
+ curwin->w_buffer = curbuf;
+ curbuf->b_nwindows = 1; /* there is one window */
+#ifdef FEAT_WINDOWS
+ curwin->w_alist = &global_alist;
+#endif
+ win_init(curwin); /* init current window */
+
+ topframe = (frame_T *)alloc_clear((unsigned)sizeof(frame_T));
+ if (topframe == NULL)
+ mch_exit(0);
+ topframe->fr_layout = FR_LEAF;
+#ifdef FEAT_VERTSPLIT
+ topframe->fr_width = Columns;
+#endif
+ topframe->fr_height = Rows - p_ch;
+ topframe->fr_win = curwin;
+ curwin->w_frame = topframe;
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+
+/*
+ * Go to another window.
+ * When jumping to another buffer, stop Visual mode. Do this before
+ * changing windows so we can yank the selection into the '*' register.
+ * When jumping to another window on the same buffer, adjust its cursor
+ * position to keep the same Visual area.
+ */
+ void
+win_goto(wp)
+ win_T *wp;
+{
+#ifdef FEAT_CMDWIN
+ if (cmdwin_type != 0)
+ {
+ beep_flush();
+ return;
+ }
+#endif
+#ifdef FEAT_VISUAL
+ if (wp->w_buffer != curbuf)
+ reset_VIsual_and_resel();
+ else if (VIsual_active)
+ wp->w_cursor = curwin->w_cursor;
+#endif
+
+#ifdef FEAT_GUI
+ need_mouse_correct = TRUE;
+#endif
+ win_enter(wp, TRUE);
+}
+
+#if defined(FEAT_PERL) || defined(PROTO)
+/*
+ * Find window number "winnr" (counting top to bottom).
+ */
+ win_T *
+win_find_nr(winnr)
+ int winnr;
+{
+ win_T *wp;
+
+# ifdef FEAT_WINDOWS
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (--winnr == 0)
+ break;
+ return wp;
+# else
+ return curwin;
+# endif
+}
+#endif
+
+#ifdef FEAT_VERTSPLIT
+/*
+ * Move to window above or below "count" times.
+ */
+ static void
+win_goto_ver(up, count)
+ int up; /* TRUE to go to win above */
+ long count;
+{
+ frame_T *fr;
+ frame_T *nfr;
+ frame_T *foundfr;
+
+ foundfr = curwin->w_frame;
+ while (count--)
+ {
+ /*
+ * First go upwards in the tree of frames until we find a upwards or
+ * downwards neighbor.
+ */
+ fr = foundfr;
+ for (;;)
+ {
+ if (fr == topframe)
+ goto end;
+ if (up)
+ nfr = fr->fr_prev;
+ else
+ nfr = fr->fr_next;
+ if (fr->fr_parent->fr_layout == FR_COL && nfr != NULL)
+ break;
+ fr = fr->fr_parent;
+ }
+
+ /*
+ * Now go downwards to find the bottom or top frame in it.
+ */
+ for (;;)
+ {
+ if (nfr->fr_layout == FR_LEAF)
+ {
+ foundfr = nfr;
+ break;
+ }
+ fr = nfr->fr_child;
+ if (nfr->fr_layout == FR_ROW)
+ {
+ /* Find the frame at the cursor row. */
+ while (fr->fr_next != NULL
+ && frame2win(fr)->w_wincol + fr->fr_width
+ <= curwin->w_wincol + curwin->w_wcol)
+ fr = fr->fr_next;
+ }
+ if (nfr->fr_layout == FR_COL && up)
+ while (fr->fr_next != NULL)
+ fr = fr->fr_next;
+ nfr = fr;
+ }
+ }
+end:
+ if (foundfr != NULL)
+ win_goto(foundfr->fr_win);
+}
+
+/*
+ * Move to left or right window.
+ */
+ static void
+win_goto_hor(left, count)
+ int left; /* TRUE to go to left win */
+ long count;
+{
+ frame_T *fr;
+ frame_T *nfr;
+ frame_T *foundfr;
+
+ foundfr = curwin->w_frame;
+ while (count--)
+ {
+ /*
+ * First go upwards in the tree of frames until we find a left or
+ * right neighbor.
+ */
+ fr = foundfr;
+ for (;;)
+ {
+ if (fr == topframe)
+ goto end;
+ if (left)
+ nfr = fr->fr_prev;
+ else
+ nfr = fr->fr_next;
+ if (fr->fr_parent->fr_layout == FR_ROW && nfr != NULL)
+ break;
+ fr = fr->fr_parent;
+ }
+
+ /*
+ * Now go downwards to find the leftmost or rightmost frame in it.
+ */
+ for (;;)
+ {
+ if (nfr->fr_layout == FR_LEAF)
+ {
+ foundfr = nfr;
+ break;
+ }
+ fr = nfr->fr_child;
+ if (nfr->fr_layout == FR_COL)
+ {
+ /* Find the frame at the cursor row. */
+ while (fr->fr_next != NULL
+ && frame2win(fr)->w_winrow + fr->fr_height
+ <= curwin->w_winrow + curwin->w_wrow)
+ fr = fr->fr_next;
+ }
+ if (nfr->fr_layout == FR_ROW && left)
+ while (fr->fr_next != NULL)
+ fr = fr->fr_next;
+ nfr = fr;
+ }
+ }
+end:
+ if (foundfr != NULL)
+ win_goto(foundfr->fr_win);
+}
+#endif
+
+/*
+ * Make window "wp" the current window.
+ */
+ void
+win_enter(wp, undo_sync)
+ win_T *wp;
+ int undo_sync;
+{
+ win_enter_ext(wp, undo_sync, FALSE);
+}
+
+/*
+ * Make window wp the current window.
+ * Can be called with "curwin_invalid" TRUE, which means that curwin has just
+ * been closed and isn't valid.
+ */
+ static void
+win_enter_ext(wp, undo_sync, curwin_invalid)
+ win_T *wp;
+ int undo_sync;
+ int curwin_invalid;
+{
+#ifdef FEAT_AUTOCMD
+ int other_buffer = FALSE;
+#endif
+
+ if (wp == curwin && !curwin_invalid) /* nothing to do */
+ return;
+
+#ifdef FEAT_AUTOCMD
+ if (!curwin_invalid)
+ {
+ /*
+ * Be careful: If autocommands delete the window, return now.
+ */
+ if (wp->w_buffer != curbuf)
+ {
+ apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
+ other_buffer = TRUE;
+ if (!win_valid(wp))
+ return;
+ }
+ apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
+ if (!win_valid(wp))
+ return;
+# ifdef FEAT_EVAL
+ /* autocmds may abort script processing */
+ if (aborting())
+ return;
+# endif
+ }
+#endif
+
+ /* sync undo before leaving the current buffer */
+ if (undo_sync && curbuf != wp->w_buffer)
+ u_sync();
+ /* may have to copy the buffer options when 'cpo' contains 'S' */
+ if (wp->w_buffer != curbuf)
+ buf_copy_options(wp->w_buffer, BCO_ENTER | BCO_NOHELP);
+ if (!curwin_invalid)
+ {
+ prevwin = curwin; /* remember for CTRL-W p */
+ curwin->w_redr_status = TRUE;
+ }
+ curwin = wp;
+ curbuf = wp->w_buffer;
+ check_cursor();
+#ifdef FEAT_VIRTUALEDIT
+ if (!virtual_active())
+ curwin->w_cursor.coladd = 0;
+#endif
+ changed_line_abv_curs(); /* assume cursor position needs updating */
+
+ if (curwin->w_localdir != NULL)
+ {
+ /* Window has a local directory: Save current directory as global
+ * directory (unless that was done already) and change to the local
+ * directory. */
+ if (globaldir == NULL)
+ {
+ char_u cwd[MAXPATHL];
+
+ if (mch_dirname(cwd, MAXPATHL) == OK)
+ globaldir = vim_strsave(cwd);
+ }
+ mch_chdir((char *)curwin->w_localdir);
+ shorten_fnames(TRUE);
+ }
+ else if (globaldir != NULL)
+ {
+ /* Window doesn't have a local directory and we are not in the global
+ * directory: Change to the global directory. */
+ mch_chdir((char *)globaldir);
+ vim_free(globaldir);
+ globaldir = NULL;
+ shorten_fnames(TRUE);
+ }
+
+#ifdef FEAT_AUTOCMD
+ apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
+ if (other_buffer)
+ apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
+#endif
+
+#ifdef FEAT_TITLE
+ maketitle();
+#endif
+ curwin->w_redr_status = TRUE;
+ if (restart_edit)
+ redraw_later(VALID); /* causes status line redraw */
+
+ /* set window height to desired minimal value */
+ if (curwin->w_height < p_wh && !curwin->w_p_wfh)
+ win_setheight((int)p_wh);
+ else if (curwin->w_height == 0)
+ win_setheight(1);
+
+#ifdef FEAT_VERTSPLIT
+ /* set window width to desired minimal value */
+ if (curwin->w_width < p_wiw)
+ win_setwidth((int)p_wiw);
+#endif
+
+#ifdef FEAT_MOUSE
+ setmouse(); /* in case jumped to/from help buffer */
+#endif
+
+#if defined(FEAT_NETBEANS_INTG) || defined(FEAT_SUN_WORKSHOP)
+ /* Change directories when the acd option is set on and after
+ * switching windows. */
+ if (p_acd && curbuf->b_ffname != NULL
+ && vim_chdirfile(curbuf->b_ffname) == OK)
+ shorten_fnames(TRUE);
+#endif
+}
+
+#endif /* FEAT_WINDOWS */
+
+#if defined(FEAT_WINDOWS) || defined(FEAT_SIGNS) || defined(PROTO)
+/*
+ * Jump to the first open window that contains buffer buf if one exists
+ * TODO: Alternatively jump to last open window? Dependent from 'splitbelow'?
+ * Returns pointer to window if it exists, otherwise NULL.
+ */
+ win_T *
+buf_jump_open_win(buf)
+ buf_T *buf;
+{
+# ifdef FEAT_WINDOWS
+ win_T *wp;
+
+ for (wp = firstwin; wp; wp = wp->w_next)
+ if (wp->w_buffer == buf)
+ break;
+ if (wp != NULL)
+ win_enter(wp, FALSE);
+ return wp;
+# else
+ if (curwin->w_buffer == buf)
+ return curwin;
+ return NULL;
+# endif
+}
+#endif
+
+/*
+ * allocate a window structure and link it in the window list
+ */
+/*ARGSUSED*/
+ static win_T *
+win_alloc(after)
+ win_T *after;
+{
+ win_T *newwin;
+
+ /*
+ * allocate window structure and linesizes arrays
+ */
+ newwin = (win_T *)alloc_clear((unsigned)sizeof(win_T));
+ if (newwin != NULL && win_alloc_lines(newwin) == FAIL)
+ {
+ vim_free(newwin);
+ newwin = NULL;
+ }
+
+ if (newwin != NULL)
+ {
+ /*
+ * link the window in the window list
+ */
+#ifdef FEAT_WINDOWS
+ win_append(after, newwin);
+#endif
+#ifdef FEAT_VERTSPLIT
+ newwin->w_wincol = 0;
+ newwin->w_width = Columns;
+#endif
+
+ /* position the display and the cursor at the top of the file. */
+ newwin->w_topline = 1;
+#ifdef FEAT_DIFF
+ newwin->w_topfill = 0;
+#endif
+ newwin->w_botline = 2;
+ newwin->w_cursor.lnum = 1;
+#ifdef FEAT_SCROLLBIND
+ newwin->w_scbind_pos = 1;
+#endif
+
+ /* We won't calculate w_fraction until resizing the window */
+ newwin->w_fraction = 0;
+ newwin->w_prev_fraction_row = -1;
+
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ out_flush();
+ gui_create_scrollbar(&newwin->w_scrollbars[SBAR_LEFT],
+ SBAR_LEFT, newwin);
+ gui_create_scrollbar(&newwin->w_scrollbars[SBAR_RIGHT],
+ SBAR_RIGHT, newwin);
+ }
+#endif
+#ifdef FEAT_EVAL
+ var_init(&newwin->w_vars); /* init internal variables */
+#endif
+#ifdef FEAT_FOLDING
+ foldInitWin(newwin);
+#endif
+ }
+ return newwin;
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+
+/*
+ * remove window 'wp' from the window list and free the structure
+ */
+ static void
+win_free(wp)
+ win_T *wp;
+{
+ int i;
+
+#ifdef FEAT_PERL
+ perl_win_free(wp);
+#endif
+
+#ifdef FEAT_PYTHON
+ python_window_free(wp);
+#endif
+
+#ifdef FEAT_TCL
+ tcl_window_free(wp);
+#endif
+
+#ifdef FEAT_RUBY
+ ruby_window_free(wp);
+#endif
+
+ clear_winopt(&wp->w_onebuf_opt);
+ clear_winopt(&wp->w_allbuf_opt);
+
+#ifdef FEAT_EVAL
+ var_clear(&wp->w_vars); /* free all internal variables */
+#endif
+
+ if (prevwin == wp)
+ prevwin = NULL;
+ win_free_lsize(wp);
+
+ for (i = 0; i < wp->w_tagstacklen; ++i)
+ vim_free(wp->w_tagstack[i].tagname);
+
+ vim_free(wp->w_localdir);
+#ifdef FEAT_SEARCH_EXTRA
+ vim_free(wp->w_match.regprog);
+#endif
+#ifdef FEAT_JUMPLIST
+ free_jumplist(wp);
+#endif
+
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ out_flush();
+ gui_mch_destroy_scrollbar(&wp->w_scrollbars[SBAR_LEFT]);
+ gui_mch_destroy_scrollbar(&wp->w_scrollbars[SBAR_RIGHT]);
+ }
+#endif /* FEAT_GUI */
+
+ win_remove(wp);
+ vim_free(wp);
+}
+
+/*
+ * Append window "wp" in the window list after window "after".
+ */
+ static void
+win_append(after, wp)
+ win_T *after, *wp;
+{
+ win_T *before;
+
+ if (after == NULL) /* after NULL is in front of the first */
+ before = firstwin;
+ else
+ before = after->w_next;
+
+ wp->w_next = before;
+ wp->w_prev = after;
+ if (after == NULL)
+ firstwin = wp;
+ else
+ after->w_next = wp;
+ if (before == NULL)
+ lastwin = wp;
+ else
+ before->w_prev = wp;
+}
+
+/*
+ * Remove a window from the window list.
+ */
+ static void
+win_remove(wp)
+ win_T *wp;
+{
+ if (wp->w_prev != NULL)
+ wp->w_prev->w_next = wp->w_next;
+ else
+ firstwin = wp->w_next;
+ if (wp->w_next != NULL)
+ wp->w_next->w_prev = wp->w_prev;
+ else
+ lastwin = wp->w_prev;
+}
+
+/*
+ * Append frame "frp" in a frame list after frame "after".
+ */
+ static void
+frame_append(after, frp)
+ frame_T *after, *frp;
+{
+ frp->fr_next = after->fr_next;
+ after->fr_next = frp;
+ if (frp->fr_next != NULL)
+ frp->fr_next->fr_prev = frp;
+ frp->fr_prev = after;
+}
+
+/*
+ * Insert frame "frp" in a frame list before frame "before".
+ */
+ static void
+frame_insert(before, frp)
+ frame_T *before, *frp;
+{
+ frp->fr_next = before;
+ frp->fr_prev = before->fr_prev;
+ before->fr_prev = frp;
+ if (frp->fr_prev != NULL)
+ frp->fr_prev->fr_next = frp;
+ else
+ frp->fr_parent->fr_child = frp;
+}
+
+/*
+ * Remove a frame from a frame list.
+ */
+ static void
+frame_remove(frp)
+ frame_T *frp;
+{
+ if (frp->fr_prev != NULL)
+ frp->fr_prev->fr_next = frp->fr_next;
+ else
+ frp->fr_parent->fr_child = frp->fr_next;
+ if (frp->fr_next != NULL)
+ frp->fr_next->fr_prev = frp->fr_prev;
+}
+
+#endif /* FEAT_WINDOWS */
+
+/*
+ * Allocate w_lines[] for window "wp".
+ * Return FAIL for failure, OK for success.
+ */
+ int
+win_alloc_lines(wp)
+ win_T *wp;
+{
+ wp->w_lines_valid = 0;
+ wp->w_lines = (wline_T *)alloc((unsigned)(Rows * sizeof(wline_T)));
+ if (wp->w_lines == NULL)
+ return FAIL;
+ return OK;
+}
+
+/*
+ * free lsize arrays for a window
+ */
+ void
+win_free_lsize(wp)
+ win_T *wp;
+{
+ vim_free(wp->w_lines);
+ wp->w_lines = NULL;
+}
+
+/*
+ * Called from win_new_shellsize() after Rows changed.
+ */
+ void
+shell_new_rows()
+{
+ int h = (int)(Rows - p_ch);
+
+ if (firstwin == NULL) /* not initialized yet */
+ return;
+#ifdef FEAT_WINDOWS
+ if (h < frame_minheight(topframe, NULL))
+ h = frame_minheight(topframe, NULL);
+ /* First try setting the heights of windows without 'winfixheight'. If
+ * that doesn't result in the right height, forget about that option. */
+ frame_new_height(topframe, h, FALSE, TRUE);
+ if (topframe->fr_height != h)
+ frame_new_height(topframe, h, FALSE, FALSE);
+
+ (void)win_comp_pos(); /* recompute w_winrow and w_wincol */
+#else
+ if (h < 1)
+ h = 1;
+ win_new_height(firstwin, h);
+#endif
+ compute_cmdrow();
+#if 0
+ /* Disabled: don't want making the screen smaller make a window larger. */
+ if (p_ea)
+ win_equal(curwin, FALSE, 'v');
+#endif
+}
+
+#if defined(FEAT_VERTSPLIT) || defined(PROTO)
+/*
+ * Called from win_new_shellsize() after Columns changed.
+ */
+ void
+shell_new_columns()
+{
+ if (firstwin == NULL) /* not initialized yet */
+ return;
+ frame_new_width(topframe, (int)Columns, FALSE);
+ (void)win_comp_pos(); /* recompute w_winrow and w_wincol */
+#if 0
+ /* Disabled: don't want making the screen smaller make a window larger. */
+ if (p_ea)
+ win_equal(curwin, FALSE, 'h');
+#endif
+}
+#endif
+
+#if defined(FEAT_CMDWIN) || defined(PROTO)
+/*
+ * Save the size of all windows in "gap".
+ */
+ void
+win_size_save(gap)
+ garray_T *gap;
+
+{
+ win_T *wp;
+
+ ga_init2(gap, (int)sizeof(int), 1);
+ if (ga_grow(gap, win_count() * 2) == OK)
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ {
+ ((int *)gap->ga_data)[gap->ga_len++] =
+ wp->w_width + wp->w_vsep_width;
+ ((int *)gap->ga_data)[gap->ga_len++] = wp->w_height;
+ }
+}
+
+/*
+ * Restore window sizes, but only if the number of windows is still the same.
+ * Does not free the growarray.
+ */
+ void
+win_size_restore(gap)
+ garray_T *gap;
+{
+ win_T *wp;
+ int i;
+
+ if (win_count() * 2 == gap->ga_len)
+ {
+ i = 0;
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ {
+ frame_setwidth(wp->w_frame, ((int *)gap->ga_data)[i++]);
+ win_setheight_win(((int *)gap->ga_data)[i++], wp);
+ }
+ /* recompute the window positions */
+ (void)win_comp_pos();
+ }
+}
+#endif /* FEAT_CMDWIN */
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * Update the position for all windows, using the width and height of the
+ * frames.
+ * Returns the row just after the last window.
+ */
+ static int
+win_comp_pos()
+{
+ int row = 0;
+ int col = 0;
+
+ frame_comp_pos(topframe, &row, &col);
+ return row;
+}
+
+/*
+ * Update the position of the windows in frame "topfrp", using the width and
+ * height of the frames.
+ * "*row" and "*col" are the top-left position of the frame. They are updated
+ * to the bottom-right position plus one.
+ */
+ static void
+frame_comp_pos(topfrp, row, col)
+ frame_T *topfrp;
+ int *row;
+ int *col;
+{
+ win_T *wp;
+ frame_T *frp;
+#ifdef FEAT_VERTSPLIT
+ int startcol;
+ int startrow;
+#endif
+
+ wp = topfrp->fr_win;
+ if (wp != NULL)
+ {
+ if (wp->w_winrow != *row
+#ifdef FEAT_VERTSPLIT
+ || wp->w_wincol != *col
+#endif
+ )
+ {
+ /* position changed, redraw */
+ wp->w_winrow = *row;
+#ifdef FEAT_VERTSPLIT
+ wp->w_wincol = *col;
+#endif
+ redraw_win_later(wp, NOT_VALID);
+ wp->w_redr_status = TRUE;
+ }
+ *row += wp->w_height + wp->w_status_height;
+#ifdef FEAT_VERTSPLIT
+ *col += wp->w_width + wp->w_vsep_width;
+#endif
+ }
+ else
+ {
+#ifdef FEAT_VERTSPLIT
+ startrow = *row;
+ startcol = *col;
+#endif
+ for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
+ {
+#ifdef FEAT_VERTSPLIT
+ if (topfrp->fr_layout == FR_ROW)
+ *row = startrow; /* all frames are at the same row */
+ else
+ *col = startcol; /* all frames are at the same col */
+#endif
+ frame_comp_pos(frp, row, col);
+ }
+ }
+}
+
+#endif /* FEAT_WINDOWS */
+
+/*
+ * Set current window height and take care of repositioning other windows to
+ * fit around it.
+ */
+ void
+win_setheight(height)
+ int height;
+{
+ win_setheight_win(height, curwin);
+}
+
+/*
+ * Set the window height of window "win" and take care of repositioning other
+ * windows to fit around it.
+ */
+ void
+win_setheight_win(height, win)
+ int height;
+ win_T *win;
+{
+ int row;
+
+ if (win == curwin)
+ {
+ /* Always keep current window at least one line high, even when
+ * 'winminheight' is zero. */
+#ifdef FEAT_WINDOWS
+ if (height < p_wmh)
+ height = p_wmh;
+#endif
+ if (height == 0)
+ height = 1;
+ }
+
+#ifdef FEAT_WINDOWS
+ frame_setheight(win->w_frame, height + win->w_status_height);
+
+ /* recompute the window positions */
+ row = win_comp_pos();
+#else
+ if (height > topframe->fr_height)
+ height = topframe->fr_height;
+ win->w_height = height;
+ row = height;
+#endif
+
+ /*
+ * If there is extra space created between the last window and the command
+ * line, clear it.
+ */
+ if (full_screen && msg_scrolled == 0 && row < cmdline_row)
+ screen_fill(row, cmdline_row, 0, (int)Columns, ' ', ' ', 0);
+ cmdline_row = row;
+ msg_row = row;
+ msg_col = 0;
+
+ redraw_all_later(NOT_VALID);
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+
+/*
+ * Set the height of a frame to "height" and take care that all frames and
+ * windows inside it are resized. Also resize frames on the left and right if
+ * the are in the same FR_ROW frame.
+ *
+ * Strategy:
+ * If the frame is part of a FR_COL frame, try fitting the frame in that
+ * frame. If that doesn't work (the FR_COL frame is too small), recursively
+ * go to containing frames to resize them and make room.
+ * If the frame is part of a FR_ROW frame, all frames must be resized as well.
+ * Check for the minimal height of the FR_ROW frame.
+ * At the top level we can also use change the command line height.
+ */
+ static void
+frame_setheight(curfrp, height)
+ frame_T *curfrp;
+ int height;
+{
+ int room; /* total number of lines available */
+ int take; /* number of lines taken from other windows */
+ int room_cmdline; /* lines available from cmdline */
+ int run;
+ frame_T *frp;
+ int h;
+ int room_reserved;
+
+ /* If the height already is the desired value, nothing to do. */
+ if (curfrp->fr_height == height)
+ return;
+
+ if (curfrp->fr_parent == NULL)
+ {
+ /* topframe: can only change the command line */
+ if (height > Rows - p_ch)
+ height = Rows - p_ch;
+ if (height > 0)
+ frame_new_height(curfrp, height, FALSE, FALSE);
+ }
+ else if (curfrp->fr_parent->fr_layout == FR_ROW)
+ {
+ /* Row of frames: Also need to resize frames left and right of this
+ * one. First check for the minimal height of these. */
+ h = frame_minheight(curfrp->fr_parent, NULL);
+ if (height < h)
+ height = h;
+ frame_setheight(curfrp->fr_parent, height);
+ }
+ else
+ {
+ /*
+ * Column of frames: try to change only frames in this column.
+ */
+#ifdef FEAT_VERTSPLIT
+ /*
+ * Do this twice:
+ * 1: compute room available, if it's not enough try resizing the
+ * containing frame.
+ * 2: compute the room available and adjust the height to it.
+ * Try not to reduce the height of a window with 'winfixheight' set.
+ */
+ for (run = 1; run <= 2; ++run)
+#else
+ for (;;)
+#endif
+ {
+ room = 0;
+ room_reserved = 0;
+ for (frp = curfrp->fr_parent->fr_child; frp != NULL;
+ frp = frp->fr_next)
+ {
+ if (frp != curfrp
+ && frp->fr_win != NULL
+ && frp->fr_win->w_p_wfh)
+ room_reserved += frp->fr_height;
+ room += frp->fr_height;
+ if (frp != curfrp)
+ room -= frame_minheight(frp, NULL);
+ }
+#ifdef FEAT_VERTSPLIT
+ if (curfrp->fr_width != Columns)
+ room_cmdline = 0;
+ else
+#endif
+ {
+ room_cmdline = Rows - p_ch - (lastwin->w_winrow
+ + lastwin->w_height + lastwin->w_status_height);
+ if (room_cmdline < 0)
+ room_cmdline = 0;
+ }
+
+ if (height <= room + room_cmdline)
+ break;
+#ifdef FEAT_VERTSPLIT
+ if (run == 2 || curfrp->fr_width == Columns)
+#endif
+ {
+ if (height > room + room_cmdline)
+ height = room + room_cmdline;
+ break;
+ }
+#ifdef FEAT_VERTSPLIT
+ frame_setheight(curfrp->fr_parent, height
+ + frame_minheight(curfrp->fr_parent, NOWIN) - (int)p_wmh - 1);
+#endif
+ /*NOTREACHED*/
+ }
+
+ /*
+ * Compute the number of lines we will take from others frames (can be
+ * negative!).
+ */
+ take = height - curfrp->fr_height;
+
+ /* If there is not enough room, also reduce the height of a window
+ * with 'winfixheight' set. */
+ if (height > room + room_cmdline - room_reserved)
+ room_reserved = room + room_cmdline - height;
+ /* If there is only a 'winfixheight' window and making the
+ * window smaller, need to make the other window taller. */
+ if (take < 0 && room - curfrp->fr_height < room_reserved)
+ room_reserved = 0;
+
+ if (take > 0 && room_cmdline > 0)
+ {
+ /* use lines from cmdline first */
+ if (take < room_cmdline)
+ room_cmdline = take;
+ take -= room_cmdline;
+ topframe->fr_height += room_cmdline;
+ }
+
+ /*
+ * set the current frame to the new height
+ */
+ frame_new_height(curfrp, height, FALSE, FALSE);
+
+ /*
+ * First take lines from the frames after the current frame. If
+ * that is not enough, takes lines from frames above the current
+ * frame.
+ */
+ for (run = 0; run < 2; ++run)
+ {
+ if (run == 0)
+ frp = curfrp->fr_next; /* 1st run: start with next window */
+ else
+ frp = curfrp->fr_prev; /* 2nd run: start with prev window */
+ while (frp != NULL && take != 0)
+ {
+ h = frame_minheight(frp, NULL);
+ if (room_reserved > 0
+ && frp->fr_win != NULL
+ && frp->fr_win->w_p_wfh)
+ {
+ if (room_reserved >= frp->fr_height)
+ room_reserved -= frp->fr_height;
+ else
+ {
+ if (frp->fr_height - room_reserved > take)
+ room_reserved = frp->fr_height - take;
+ take -= frp->fr_height - room_reserved;
+ frame_new_height(frp, room_reserved, FALSE, FALSE);
+ room_reserved = 0;
+ }
+ }
+ else
+ {
+ if (frp->fr_height - take < h)
+ {
+ take -= frp->fr_height - h;
+ frame_new_height(frp, h, FALSE, FALSE);
+ }
+ else
+ {
+ frame_new_height(frp, frp->fr_height - take,
+ FALSE, FALSE);
+ take = 0;
+ }
+ }
+ if (run == 0)
+ frp = frp->fr_next;
+ else
+ frp = frp->fr_prev;
+ }
+ }
+ }
+}
+
+#if defined(FEAT_VERTSPLIT) || defined(PROTO)
+/*
+ * Set current window width and take care of repositioning other windows to
+ * fit around it.
+ */
+ void
+win_setwidth(width)
+ int width;
+{
+ win_setwidth_win(width, curwin);
+}
+
+ void
+win_setwidth_win(width, wp)
+ int width;
+ win_T *wp;
+{
+ /* Always keep current window at least one column wide, even when
+ * 'winminwidth' is zero. */
+ if (wp == curwin)
+ {
+ if (width < p_wmw)
+ width = p_wmw;
+ if (width == 0)
+ width = 1;
+ }
+
+ frame_setwidth(wp->w_frame, width + wp->w_vsep_width);
+
+ /* recompute the window positions */
+ (void)win_comp_pos();
+
+ redraw_all_later(NOT_VALID);
+}
+
+/*
+ * Set the width of a frame to "width" and take care that all frames and
+ * windows inside it are resized. Also resize frames above and below if the
+ * are in the same FR_ROW frame.
+ *
+ * Strategy is similar to frame_setheight().
+ */
+ static void
+frame_setwidth(curfrp, width)
+ frame_T *curfrp;
+ int width;
+{
+ int room; /* total number of lines available */
+ int take; /* number of lines taken from other windows */
+ int run;
+ frame_T *frp;
+ int w;
+
+ /* If the width already is the desired value, nothing to do. */
+ if (curfrp->fr_width == width)
+ return;
+
+ if (curfrp->fr_parent == NULL)
+ /* topframe: can't change width */
+ return;
+
+ if (curfrp->fr_parent->fr_layout == FR_COL)
+ {
+ /* Column of frames: Also need to resize frames above and below of
+ * this one. First check for the minimal width of these. */
+ w = frame_minwidth(curfrp->fr_parent, NULL);
+ if (width < w)
+ width = w;
+ frame_setwidth(curfrp->fr_parent, width);
+ }
+ else
+ {
+ /*
+ * Row of frames: try to change only frames in this row.
+ *
+ * Do this twice:
+ * 1: compute room available, if it's not enough try resizing the
+ * containing frame.
+ * 2: compute the room available and adjust the width to it.
+ */
+ for (run = 1; run <= 2; ++run)
+ {
+ room = 0;
+ for (frp = curfrp->fr_parent->fr_child; frp != NULL;
+ frp = frp->fr_next)
+ {
+ room += frp->fr_width;
+ if (frp != curfrp)
+ room -= frame_minwidth(frp, NULL);
+ }
+
+ if (width <= room)
+ break;
+ if (run == 2 || curfrp->fr_height >= Rows - p_ch)
+ {
+ if (width > room)
+ width = room;
+ break;
+ }
+ frame_setwidth(curfrp->fr_parent, width
+ + frame_minwidth(curfrp->fr_parent, NOWIN) - (int)p_wmw - 1);
+ }
+
+
+ /*
+ * Compute the number of lines we will take from others frames (can be
+ * negative!).
+ */
+ take = width - curfrp->fr_width;
+
+ /*
+ * set the current frame to the new width
+ */
+ frame_new_width(curfrp, width, FALSE);
+
+ /*
+ * First take lines from the frames right of the current frame. If
+ * that is not enough, takes lines from frames left of the current
+ * frame.
+ */
+ for (run = 0; run < 2; ++run)
+ {
+ if (run == 0)
+ frp = curfrp->fr_next; /* 1st run: start with next window */
+ else
+ frp = curfrp->fr_prev; /* 2nd run: start with prev window */
+ while (frp != NULL && take != 0)
+ {
+ w = frame_minwidth(frp, NULL);
+ if (frp->fr_width - take < w)
+ {
+ take -= frp->fr_width - w;
+ frame_new_width(frp, w, FALSE);
+ }
+ else
+ {
+ frame_new_width(frp, frp->fr_width - take, FALSE);
+ take = 0;
+ }
+ if (run == 0)
+ frp = frp->fr_next;
+ else
+ frp = frp->fr_prev;
+ }
+ }
+ }
+}
+#endif /* FEAT_VERTSPLIT */
+
+/*
+ * Check 'winminheight' for a valid value.
+ */
+ void
+win_setminheight()
+{
+ int room;
+ int first = TRUE;
+ win_T *wp;
+
+ /* loop until there is a 'winminheight' that is possible */
+ while (p_wmh > 0)
+ {
+ /* TODO: handle vertical splits */
+ room = -p_wh;
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ room += wp->w_height - p_wmh;
+ if (room >= 0)
+ break;
+ --p_wmh;
+ if (first)
+ {
+ EMSG(_(e_noroom));
+ first = FALSE;
+ }
+ }
+}
+
+#ifdef FEAT_MOUSE
+
+/*
+ * Status line of dragwin is dragged "offset" lines down (negative is up).
+ */
+ void
+win_drag_status_line(dragwin, offset)
+ win_T *dragwin;
+ int offset;
+{
+ frame_T *curfr;
+ frame_T *fr;
+ int room;
+ int row;
+ int up; /* if TRUE, drag status line up, otherwise down */
+ int n;
+
+ fr = dragwin->w_frame;
+ curfr = fr;
+ if (fr != topframe) /* more than one window */
+ {
+ fr = fr->fr_parent;
+ /* When the parent frame is not a column of frames, its parent should
+ * be. */
+ if (fr->fr_layout != FR_COL)
+ {
+ curfr = fr;
+ if (fr != topframe) /* only a row of windows, may drag statusline */
+ fr = fr->fr_parent;
+ }
+ }
+
+ /* If this is the last frame in a column, may want to resize the parent
+ * frame instead (go two up to skip a row of frames). */
+ while (curfr != topframe && curfr->fr_next == NULL)
+ {
+ if (fr != topframe)
+ fr = fr->fr_parent;
+ curfr = fr;
+ if (fr != topframe)
+ fr = fr->fr_parent;
+ }
+
+ if (offset < 0) /* drag up */
+ {
+ up = TRUE;
+ offset = -offset;
+ /* sum up the room of the current frame and above it */
+ if (fr == curfr)
+ {
+ /* only one window */
+ room = fr->fr_height - frame_minheight(fr, NULL);
+ }
+ else
+ {
+ room = 0;
+ for (fr = fr->fr_child; ; fr = fr->fr_next)
+ {
+ room += fr->fr_height - frame_minheight(fr, NULL);
+ if (fr == curfr)
+ break;
+ }
+ }
+ fr = curfr->fr_next; /* put fr at frame that grows */
+ }
+ else /* drag down */
+ {
+ up = FALSE;
+ /*
+ * Only dragging the last status line can reduce p_ch.
+ */
+ room = Rows - cmdline_row;
+ if (curfr->fr_next == NULL)
+ room -= 1;
+ else
+ room -= p_ch;
+ if (room < 0)
+ room = 0;
+ /* sum up the room of frames below of the current one */
+ for (fr = curfr->fr_next; fr != NULL; fr = fr->fr_next)
+ room += fr->fr_height - frame_minheight(fr, NULL);
+ fr = curfr; /* put fr at window that grows */
+ }
+
+ if (room < offset) /* Not enough room */
+ offset = room; /* Move as far as we can */
+ if (offset <= 0)
+ return;
+
+ /*
+ * Grow frame fr by "offset" lines.
+ * Doesn't happen when dragging the last status line up.
+ */
+ if (fr != NULL)
+ frame_new_height(fr, fr->fr_height + offset, up, FALSE);
+
+ if (up)
+ fr = curfr; /* current frame gets smaller */
+ else
+ fr = curfr->fr_next; /* next frame gets smaller */
+
+ /*
+ * Now make the other frames smaller.
+ */
+ while (fr != NULL && offset > 0)
+ {
+ n = frame_minheight(fr, NULL);
+ if (fr->fr_height - offset <= n)
+ {
+ offset -= fr->fr_height - n;
+ frame_new_height(fr, n, !up, FALSE);
+ }
+ else
+ {
+ frame_new_height(fr, fr->fr_height - offset, !up, FALSE);
+ break;
+ }
+ if (up)
+ fr = fr->fr_prev;
+ else
+ fr = fr->fr_next;
+ }
+ row = win_comp_pos();
+ screen_fill(row, cmdline_row, 0, (int)Columns, ' ', ' ', 0);
+ cmdline_row = row;
+ p_ch = Rows - cmdline_row;
+ if (p_ch < 1)
+ p_ch = 1;
+ redraw_all_later(NOT_VALID);
+ showmode();
+}
+
+#ifdef FEAT_VERTSPLIT
+/*
+ * Separator line of dragwin is dragged "offset" lines right (negative is left).
+ */
+ void
+win_drag_vsep_line(dragwin, offset)
+ win_T *dragwin;
+ int offset;
+{
+ frame_T *curfr;
+ frame_T *fr;
+ int room;
+ int left; /* if TRUE, drag separator line left, otherwise right */
+ int n;
+
+ fr = dragwin->w_frame;
+ if (fr == topframe) /* only one window (cannot happe?) */
+ return;
+ curfr = fr;
+ fr = fr->fr_parent;
+ /* When the parent frame is not a row of frames, its parent should be. */
+ if (fr->fr_layout != FR_ROW)
+ {
+ if (fr == topframe) /* only a column of windows (cannot happen?) */
+ return;
+ curfr = fr;
+ fr = fr->fr_parent;
+ }
+
+ /* If this is the last frame in a row, may want to resize a parent
+ * frame instead. */
+ while (curfr->fr_next == NULL)
+ {
+ if (fr == topframe)
+ break;
+ curfr = fr;
+ fr = fr->fr_parent;
+ if (fr != topframe)
+ {
+ curfr = fr;
+ fr = fr->fr_parent;
+ }
+ }
+
+ if (offset < 0) /* drag left */
+ {
+ left = TRUE;
+ offset = -offset;
+ /* sum up the room of the current frame and left of it */
+ room = 0;
+ for (fr = fr->fr_child; ; fr = fr->fr_next)
+ {
+ room += fr->fr_width - frame_minwidth(fr, NULL);
+ if (fr == curfr)
+ break;
+ }
+ fr = curfr->fr_next; /* put fr at frame that grows */
+ }
+ else /* drag right */
+ {
+ left = FALSE;
+ /* sum up the room of frames right of the current one */
+ room = 0;
+ for (fr = curfr->fr_next; fr != NULL; fr = fr->fr_next)
+ room += fr->fr_width - frame_minwidth(fr, NULL);
+ fr = curfr; /* put fr at window that grows */
+ }
+
+ if (room < offset) /* Not enough room */
+ offset = room; /* Move as far as we can */
+ if (offset <= 0) /* No room at all, quit. */
+ return;
+
+ /* grow frame fr by offset lines */
+ frame_new_width(fr, fr->fr_width + offset, left);
+
+ /* shrink other frames: current and at the left or at the right */
+ if (left)
+ fr = curfr; /* current frame gets smaller */
+ else
+ fr = curfr->fr_next; /* next frame gets smaller */
+
+ while (fr != NULL && offset > 0)
+ {
+ n = frame_minwidth(fr, NULL);
+ if (fr->fr_width - offset <= n)
+ {
+ offset -= fr->fr_width - n;
+ frame_new_width(fr, n, !left);
+ }
+ else
+ {
+ frame_new_width(fr, fr->fr_width - offset, !left);
+ break;
+ }
+ if (left)
+ fr = fr->fr_prev;
+ else
+ fr = fr->fr_next;
+ }
+ (void)win_comp_pos();
+ redraw_all_later(NOT_VALID);
+}
+#endif /* FEAT_VERTSPLIT */
+#endif /* FEAT_MOUSE */
+
+#endif /* FEAT_WINDOWS */
+
+/*
+ * Set the height of a window.
+ * This takes care of the things inside the window, not what happens to the
+ * window position, the frame or to other windows.
+ */
+ static void
+win_new_height(wp, height)
+ win_T *wp;
+ int height;
+{
+ linenr_T lnum;
+ int sline, line_size;
+#define FRACTION_MULT 16384L
+
+ /* Don't want a negative height. Happens when splitting a tiny window.
+ * Will equalize heights soon to fix it. */
+ if (height < 0)
+ height = 0;
+
+ if (wp->w_wrow != wp->w_prev_fraction_row && wp->w_height > 0)
+ wp->w_fraction = ((long)wp->w_wrow * FRACTION_MULT
+ + FRACTION_MULT / 2) / (long)wp->w_height;
+
+ wp->w_height = height;
+ wp->w_skipcol = 0;
+
+ /* Don't change w_topline when height is zero. Don't set w_topline when
+ * 'scrollbind' is set and this isn't the current window. */
+ if (height > 0
+#ifdef FEAT_SCROLLBIND
+ && (!wp->w_p_scb || wp == curwin)
+#endif
+ )
+ {
+ lnum = wp->w_cursor.lnum;
+ if (lnum < 1) /* can happen when starting up */
+ lnum = 1;
+ wp->w_wrow = ((long)wp->w_fraction * (long)height - 1L) / FRACTION_MULT;
+ line_size = plines_win_col(wp, lnum, (long)(wp->w_cursor.col)) - 1;
+ sline = wp->w_wrow - line_size;
+ if (sline < 0)
+ {
+ /*
+ * Cursor line would go off top of screen if w_wrow was this high.
+ */
+ wp->w_wrow = line_size;
+ }
+ else
+ {
+ while (sline > 0 && lnum > 1)
+ {
+#ifdef FEAT_FOLDING
+ hasFoldingWin(wp, lnum, &lnum, NULL, TRUE, NULL);
+ if (lnum == 1)
+ {
+ /* first line in buffer is folded */
+ line_size = 1;
+ --sline;
+ break;
+ }
+#endif
+ --lnum;
+#ifdef FEAT_DIFF
+ if (lnum == wp->w_topline)
+ line_size = plines_win_nofill(wp, lnum, TRUE)
+ + wp->w_topfill;
+ else
+#endif
+ line_size = plines_win(wp, lnum, TRUE);
+ sline -= line_size;
+ }
+ if (sline < 0)
+ {
+ /*
+ * Line we want at top would go off top of screen. Use next
+ * line instead.
+ */
+#ifdef FEAT_FOLDING
+ hasFoldingWin(wp, lnum, NULL, &lnum, TRUE, NULL);
+#endif
+ lnum++;
+ wp->w_wrow -= line_size + sline;
+ }
+ else if (sline > 0)
+ {
+ /* First line of file reached, use that as topline. */
+ lnum = 1;
+ wp->w_wrow -= sline;
+ }
+ }
+ set_topline(wp, lnum);
+ }
+
+ if (wp == curwin)
+ {
+ if (p_so)
+ update_topline();
+ curs_columns(FALSE); /* validate w_wrow */
+ }
+ wp->w_prev_fraction_row = wp->w_wrow;
+
+ win_comp_scroll(wp);
+ redraw_win_later(wp, NOT_VALID);
+#ifdef FEAT_WINDOWS
+ wp->w_redr_status = TRUE;
+#endif
+ invalidate_botline_win(wp);
+}
+
+#ifdef FEAT_VERTSPLIT
+/*
+ * Set the width of a window.
+ */
+ static void
+win_new_width(wp, width)
+ win_T *wp;
+ int width;
+{
+ wp->w_width = width;
+ wp->w_lines_valid = 0;
+ changed_line_abv_curs_win(wp);
+ invalidate_botline_win(wp);
+ if (wp == curwin)
+ {
+ update_topline();
+ curs_columns(TRUE); /* validate w_wrow */
+ }
+ redraw_win_later(wp, NOT_VALID);
+ wp->w_redr_status = TRUE;
+}
+#endif
+
+ void
+win_comp_scroll(wp)
+ win_T *wp;
+{
+ wp->w_p_scr = ((unsigned)wp->w_height >> 1);
+ if (wp->w_p_scr == 0)
+ wp->w_p_scr = 1;
+}
+
+/*
+ * command_height: called whenever p_ch has been changed
+ */
+ void
+command_height(old_p_ch)
+ long old_p_ch;
+{
+#ifdef FEAT_WINDOWS
+ int h;
+ frame_T *frp;
+
+ /* Find bottom frame with width of screen. */
+ frp = lastwin->w_frame;
+# ifdef FEAT_VERTSPLIT
+ while (frp->fr_width != Columns && frp->fr_parent != NULL)
+ frp = frp->fr_parent;
+# endif
+
+ /* Avoid changing the height of a window with 'winfixheight' set. */
+ while (frp->fr_prev != NULL && frp->fr_layout == FR_LEAF
+ && frp->fr_win->w_p_wfh)
+ frp = frp->fr_prev;
+
+ if (starting != NO_SCREEN)
+ {
+ cmdline_row = Rows - p_ch;
+
+ if (p_ch > old_p_ch) /* p_ch got bigger */
+ {
+ while (p_ch > old_p_ch)
+ {
+ if (frp == NULL)
+ {
+ EMSG(_(e_noroom));
+ p_ch = old_p_ch;
+ cmdline_row = Rows - p_ch;
+ break;
+ }
+ h = frp->fr_height - frame_minheight(frp, NULL);
+ if (h > p_ch - old_p_ch)
+ h = p_ch - old_p_ch;
+ old_p_ch += h;
+ frame_add_height(frp, -h);
+ frp = frp->fr_prev;
+ }
+
+ /* Recompute window positions. */
+ (void)win_comp_pos();
+
+ /* clear the lines added to cmdline */
+ if (full_screen)
+ screen_fill((int)(cmdline_row), (int)Rows, 0,
+ (int)Columns, ' ', ' ', 0);
+ msg_row = cmdline_row;
+ redraw_cmdline = TRUE;
+ return;
+ }
+
+ if (msg_row < cmdline_row)
+ msg_row = cmdline_row;
+ redraw_cmdline = TRUE;
+ }
+ frame_add_height(frp, (int)(old_p_ch - p_ch));
+
+ /* Recompute window positions. */
+ if (frp != lastwin->w_frame)
+ (void)win_comp_pos();
+#else
+ win_setheight((int)(firstwin->w_height + old_p_ch - p_ch));
+ cmdline_row = Rows - p_ch;
+#endif
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+/*
+ * Resize frame "frp" to be "n" lines higher (negative for less high).
+ * Also resize the frames it is contained in.
+ */
+ static void
+frame_add_height(frp, n)
+ frame_T *frp;
+ int n;
+{
+ frame_new_height(frp, frp->fr_height + n, FALSE, FALSE);
+ for (;;)
+ {
+ frp = frp->fr_parent;
+ if (frp == NULL)
+ break;
+ frp->fr_height += n;
+ }
+}
+
+/*
+ * Add or remove a status line for the bottom window(s), according to the
+ * value of 'laststatus'.
+ */
+ void
+last_status(morewin)
+ int morewin; /* pretend there are two or more windows */
+{
+ /* Don't make a difference between horizontal or vertical split. */
+ last_status_rec(topframe, (p_ls == 2
+ || (p_ls == 1 && (morewin || lastwin != firstwin))));
+}
+
+ static void
+last_status_rec(fr, statusline)
+ frame_T *fr;
+ int statusline;
+{
+ frame_T *fp;
+ win_T *wp;
+
+ if (fr->fr_layout == FR_LEAF)
+ {
+ wp = fr->fr_win;
+ if (wp->w_status_height != 0 && !statusline)
+ {
+ /* remove status line */
+ win_new_height(wp, wp->w_height + 1);
+ wp->w_status_height = 0;
+ comp_col();
+ }
+ else if (wp->w_status_height == 0 && statusline)
+ {
+ /* Find a frame to take a line from. */
+ fp = fr;
+ while (fp->fr_height <= frame_minheight(fp, NULL))
+ {
+ if (fp == topframe)
+ {
+ EMSG(_(e_noroom));
+ return;
+ }
+ /* In a column of frames: go to frame above. If already at
+ * the top or in a row of frames: go to parent. */
+ if (fp->fr_parent->fr_layout == FR_COL && fp->fr_prev != NULL)
+ fp = fp->fr_prev;
+ else
+ fp = fp->fr_parent;
+ }
+ wp->w_status_height = 1;
+ if (fp != fr)
+ {
+ frame_new_height(fp, fp->fr_height - 1, FALSE, FALSE);
+ frame_fix_height(wp);
+ (void)win_comp_pos();
+ }
+ else
+ win_new_height(wp, wp->w_height - 1);
+ comp_col();
+ redraw_all_later(NOT_VALID);
+ }
+ }
+#ifdef FEAT_VERTSPLIT
+ else if (fr->fr_layout == FR_ROW)
+ {
+ /* vertically split windows, set status line for each one */
+ for (fp = fr->fr_child; fp != NULL; fp = fp->fr_next)
+ last_status_rec(fp, statusline);
+ }
+#endif
+ else
+ {
+ /* horizontally split window, set status line for last one */
+ for (fp = fr->fr_child; fp->fr_next != NULL; fp = fp->fr_next)
+ ;
+ last_status_rec(fp, statusline);
+ }
+}
+
+#endif /* FEAT_WINDOWS */
+
+#if defined(FEAT_SEARCHPATH) || defined(PROTO)
+/*
+ * Return the file name under or after the cursor.
+ *
+ * The 'path' option is searched if the file name is not absolute.
+ * The string returned has been alloc'ed and should be freed by the caller.
+ * NULL is returned if the file name or file is not found.
+ *
+ * options:
+ * FNAME_MESS give error messages
+ * FNAME_EXP expand to path
+ * FNAME_HYP check for hypertext link
+ * FNAME_INCL apply "includeexpr"
+ */
+ char_u *
+file_name_at_cursor(options, count)
+ int options;
+ long count;
+{
+ return file_name_in_line(ml_get_curline(),
+ curwin->w_cursor.col, options, count, curbuf->b_ffname);
+}
+
+/*
+ * Return the name of the file under or after ptr[col].
+ * Otherwise like file_name_at_cursor().
+ */
+ char_u *
+file_name_in_line(line, col, options, count, rel_fname)
+ char_u *line;
+ int col;
+ int options;
+ long count;
+ char_u *rel_fname; /* file we are searching relative to */
+{
+ char_u *ptr;
+ int len;
+
+ /*
+ * search forward for what could be the start of a file name
+ */
+ ptr = line + col;
+ while (*ptr != NUL && !vim_isfilec(*ptr))
+ ++ptr;
+ if (*ptr == NUL) /* nothing found */
+ {
+ if (options & FNAME_MESS)
+ EMSG(_("E446: No file name under cursor"));
+ return NULL;
+ }
+
+ /*
+ * Search backward for first char of the file name.
+ * Go one char back to ":" before "//" even when ':' is not in 'isfname'.
+ */
+ while (ptr > line)
+ {
+#ifdef FEAT_MBYTE
+ if (has_mbyte && (len = (*mb_head_off)(line, ptr - 1)) > 0)
+ ptr -= len + 1;
+ else
+#endif
+ if (vim_isfilec(ptr[-1])
+ || ((options & FNAME_HYP) && path_is_url(ptr - 1)))
+ --ptr;
+ else
+ break;
+ }
+
+ /*
+ * Search forward for the last char of the file name.
+ * Also allow "://" when ':' is not in 'isfname'.
+ */
+ len = 0;
+ while (vim_isfilec(ptr[len])
+ || ((options & FNAME_HYP) && path_is_url(ptr + len)))
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ len += (*mb_ptr2len_check)(ptr + len);
+ else
+#endif
+ ++len;
+
+ /*
+ * If there is trailing punctuation, remove it.
+ * But don't remove "..", could be a directory name.
+ */
+ if (len > 2 && vim_strchr((char_u *)".,:;!", ptr[len - 1]) != NULL
+ && ptr[len - 2] != '.')
+ --len;
+
+ return find_file_name_in_path(ptr, len, options, count, rel_fname);
+}
+
+# if defined(FEAT_FIND_ID) && defined(FEAT_EVAL)
+static char_u *eval_includeexpr __ARGS((char_u *ptr, int len));
+
+ static char_u *
+eval_includeexpr(ptr, len)
+ char_u *ptr;
+ int len;
+{
+ char_u *res;
+
+ set_vim_var_string(VV_FNAME, ptr, len);
+ res = eval_to_string_safe(curbuf->b_p_inex, NULL);
+ set_vim_var_string(VV_FNAME, NULL, 0);
+ return res;
+}
+#endif
+
+/*
+ * Return the name of the file ptr[len] in 'path'.
+ * Otherwise like file_name_at_cursor().
+ */
+ char_u *
+find_file_name_in_path(ptr, len, options, count, rel_fname)
+ char_u *ptr;
+ int len;
+ int options;
+ long count;
+ char_u *rel_fname; /* file we are searching relative to */
+{
+ char_u *file_name;
+ int c;
+# if defined(FEAT_FIND_ID) && defined(FEAT_EVAL)
+ char_u *tofree = NULL;
+
+ if ((options & FNAME_INCL) && *curbuf->b_p_inex != NUL)
+ {
+ tofree = eval_includeexpr(ptr, len);
+ if (tofree != NULL)
+ {
+ ptr = tofree;
+ len = (int)STRLEN(ptr);
+ }
+ }
+# endif
+
+ if (options & FNAME_EXP)
+ {
+ file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
+ TRUE, rel_fname);
+
+# if defined(FEAT_FIND_ID) && defined(FEAT_EVAL)
+ /*
+ * If the file could not be found in a normal way, try applying
+ * 'includeexpr' (unless done already).
+ */
+ if (file_name == NULL
+ && !(options & FNAME_INCL) && *curbuf->b_p_inex != NUL)
+ {
+ tofree = eval_includeexpr(ptr, len);
+ if (tofree != NULL)
+ {
+ ptr = tofree;
+ len = (int)STRLEN(ptr);
+ file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
+ TRUE, rel_fname);
+ }
+ }
+# endif
+ if (file_name == NULL && (options & FNAME_MESS))
+ {
+ c = ptr[len];
+ ptr[len] = NUL;
+ EMSG2(_("E447: Can't find file \"%s\" in path"), ptr);
+ ptr[len] = c;
+ }
+
+ /* Repeat finding the file "count" times. This matters when it
+ * appears several times in the path. */
+ while (file_name != NULL && --count > 0)
+ {
+ vim_free(file_name);
+ file_name = find_file_in_path(ptr, len, options, FALSE, rel_fname);
+ }
+ }
+ else
+ file_name = vim_strnsave(ptr, len);
+
+# if defined(FEAT_FIND_ID) && defined(FEAT_EVAL)
+ vim_free(tofree);
+# endif
+
+ return file_name;
+}
+#endif /* FEAT_SEARCHPATH */
+
+/*
+ * Check if the "://" of a URL is at the pointer, return URL_SLASH.
+ * Also check for ":\\", which MS Internet Explorer accepts, return
+ * URL_BACKSLASH.
+ */
+ static int
+path_is_url(p)
+ char_u *p;
+{
+ if (STRNCMP(p, "://", (size_t)3) == 0)
+ return URL_SLASH;
+ else if (STRNCMP(p, ":\\\\", (size_t)3) == 0)
+ return URL_BACKSLASH;
+ return 0;
+}
+
+/*
+ * Check if "fname" starts with "name://". Return URL_SLASH if it does.
+ * Return URL_BACKSLASH for "name:\\".
+ * Return zero otherwise.
+ */
+ int
+path_with_url(fname)
+ char_u *fname;
+{
+ char_u *p;
+
+ for (p = fname; isalpha(*p); ++p)
+ ;
+ return path_is_url(p);
+}
+
+/*
+ * Return TRUE if "name" is a full (absolute) path name or URL.
+ */
+ int
+vim_isAbsName(name)
+ char_u *name;
+{
+ return (path_with_url(name) != 0 || mch_isFullName(name));
+}
+
+/*
+ * Get absolute file name into buffer 'buf' of length 'len' bytes.
+ *
+ * return FAIL for failure, OK otherwise
+ */
+ int
+vim_FullName(fname, buf, len, force)
+ char_u *fname, *buf;
+ int len;
+ int force;
+{
+ int retval = OK;
+ int url;
+
+ *buf = NUL;
+ if (fname == NULL)
+ return FAIL;
+
+ url = path_with_url(fname);
+ if (!url)
+ retval = mch_FullName(fname, buf, len, force);
+ if (url || retval == FAIL)
+ {
+ /* something failed; use the file name (truncate when too long) */
+ STRNCPY(buf, fname, len);
+ buf[len - 1] = NUL;
+ }
+#if defined(MACOS_CLASSIC) || defined(OS2) || defined(MSDOS) || defined(MSWIN)
+ slash_adjust(buf);
+#endif
+ return retval;
+}
+
+/*
+ * Return the minimal number of rows that is needed on the screen to display
+ * the current number of windows.
+ */
+ int
+min_rows()
+{
+ int total;
+
+ if (firstwin == NULL) /* not initialized yet */
+ return MIN_LINES;
+
+ total = 1; /* count the room for the command line */
+#ifdef FEAT_WINDOWS
+ total += frame_minheight(topframe, NULL);
+#else
+ total += 1; /* at least one window should have a line! */
+#endif
+ return total;
+}
+
+/*
+ * Return TRUE if there is only one window, not counting a help or preview
+ * window, unless it is the current window.
+ */
+ int
+only_one_window()
+{
+#ifdef FEAT_WINDOWS
+ int count = 0;
+ win_T *wp;
+
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if (!(wp->w_buffer->b_help
+# ifdef FEAT_QUICKFIX
+ || wp->w_p_pvw
+# endif
+ ) || wp == curwin)
+ ++count;
+ return (count <= 1);
+#else
+ return TRUE;
+#endif
+}
+
+#if defined(FEAT_WINDOWS) || defined(FEAT_AUTOCMD) || defined(PROTO)
+/*
+ * Correct the cursor line number in other windows. Used after changing the
+ * current buffer, and before applying autocommands.
+ * When "do_curwin" is TRUE, also check current window.
+ */
+ void
+check_lnums(do_curwin)
+ int do_curwin;
+{
+ win_T *wp;
+
+#ifdef FEAT_WINDOWS
+ for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ if ((do_curwin || wp != curwin) && wp->w_buffer == curbuf)
+#else
+ wp = curwin;
+ if (do_curwin)
+#endif
+ {
+ if (wp->w_cursor.lnum > curbuf->b_ml.ml_line_count)
+ wp->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ if (wp->w_topline > curbuf->b_ml.ml_line_count)
+ wp->w_topline = curbuf->b_ml.ml_line_count;
+ }
+}
+#endif
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+
+/*
+ * A snapshot of the window sizes, to restore them after closing the help
+ * window.
+ * Only these fields are used:
+ * fr_layout
+ * fr_width
+ * fr_height
+ * fr_next
+ * fr_child
+ * fr_win (only valid for the old curwin, NULL otherwise)
+ */
+static frame_T *snapshot = NULL;
+
+/*
+ * Create a snapshot of the current frame sizes.
+ */
+ static void
+make_snapshot()
+{
+ clear_snapshot();
+ make_snapshot_rec(topframe, &snapshot);
+}
+
+ static void
+make_snapshot_rec(fr, frp)
+ frame_T *fr;
+ frame_T **frp;
+{
+ *frp = (frame_T *)alloc_clear((unsigned)sizeof(frame_T));
+ if (*frp == NULL)
+ return;
+ (*frp)->fr_layout = fr->fr_layout;
+# ifdef FEAT_VERTSPLIT
+ (*frp)->fr_width = fr->fr_width;
+# endif
+ (*frp)->fr_height = fr->fr_height;
+ if (fr->fr_next != NULL)
+ make_snapshot_rec(fr->fr_next, &((*frp)->fr_next));
+ if (fr->fr_child != NULL)
+ make_snapshot_rec(fr->fr_child, &((*frp)->fr_child));
+ if (fr->fr_layout == FR_LEAF && fr->fr_win == curwin)
+ (*frp)->fr_win = curwin;
+}
+
+/*
+ * Remove any existing snapshot.
+ */
+ static void
+clear_snapshot()
+{
+ clear_snapshot_rec(snapshot);
+ snapshot = NULL;
+}
+
+ static void
+clear_snapshot_rec(fr)
+ frame_T *fr;
+{
+ if (fr != NULL)
+ {
+ clear_snapshot_rec(fr->fr_next);
+ clear_snapshot_rec(fr->fr_child);
+ vim_free(fr);
+ }
+}
+
+/*
+ * Restore a previously created snapshot, if there is any.
+ * This is only done if the screen size didn't change and the window layout is
+ * still the same.
+ */
+ static void
+restore_snapshot(close_curwin)
+ int close_curwin; /* closing current window */
+{
+ win_T *wp;
+
+ if (snapshot != NULL
+# ifdef FEAT_VERTSPLIT
+ && snapshot->fr_width == topframe->fr_width
+# endif
+ && snapshot->fr_height == topframe->fr_height
+ && check_snapshot_rec(snapshot, topframe) == OK)
+ {
+ wp = restore_snapshot_rec(snapshot, topframe);
+ win_comp_pos();
+ if (wp != NULL && close_curwin)
+ win_goto(wp);
+ redraw_all_later(CLEAR);
+ }
+ clear_snapshot();
+}
+
+/*
+ * Check if frames "sn" and "fr" have the same layout, same following frames
+ * and same children.
+ */
+ static int
+check_snapshot_rec(sn, fr)
+ frame_T *sn;
+ frame_T *fr;
+{
+ if (sn->fr_layout != fr->fr_layout
+ || (sn->fr_next == NULL) != (fr->fr_next == NULL)
+ || (sn->fr_child == NULL) != (fr->fr_child == NULL)
+ || (sn->fr_next != NULL
+ && check_snapshot_rec(sn->fr_next, fr->fr_next) == FAIL)
+ || (sn->fr_child != NULL
+ && check_snapshot_rec(sn->fr_child, fr->fr_child) == FAIL))
+ return FAIL;
+ return OK;
+}
+
+/*
+ * Copy the size of snapshot frame "sn" to frame "fr". Do the same for all
+ * following frames and children.
+ * Returns a pointer to the old current window, or NULL.
+ */
+ static win_T *
+restore_snapshot_rec(sn, fr)
+ frame_T *sn;
+ frame_T *fr;
+{
+ win_T *wp = NULL;
+ win_T *wp2;
+
+ fr->fr_height = sn->fr_height;
+# ifdef FEAT_VERTSPLIT
+ fr->fr_width = sn->fr_width;
+# endif
+ if (fr->fr_layout == FR_LEAF)
+ {
+ frame_new_height(fr, fr->fr_height, FALSE, FALSE);
+# ifdef FEAT_VERTSPLIT
+ frame_new_width(fr, fr->fr_width, FALSE);
+# endif
+ wp = sn->fr_win;
+ }
+ if (sn->fr_next != NULL)
+ {
+ wp2 = restore_snapshot_rec(sn->fr_next, fr->fr_next);
+ if (wp2 != NULL)
+ wp = wp2;
+ }
+ if (sn->fr_child != NULL)
+ {
+ wp2 = restore_snapshot_rec(sn->fr_child, fr->fr_child);
+ if (wp2 != NULL)
+ wp = wp2;
+ }
+ return wp;
+}
+
+#endif
+
+#if (defined(FEAT_GUI) && defined(FEAT_VERTSPLIT)) || defined(PROTO)
+/*
+ * Return TRUE if there is any vertically split window.
+ */
+ int
+win_hasvertsplit()
+{
+ frame_T *fr;
+
+ if (topframe->fr_layout == FR_ROW)
+ return TRUE;
+
+ if (topframe->fr_layout == FR_COL)
+ for (fr = topframe->fr_child; fr != NULL; fr = fr->fr_next)
+ if (fr->fr_layout == FR_ROW)
+ return TRUE;
+
+ return FALSE;
+}
+#endif
diff --git a/src/workshop.c b/src/workshop.c
new file mode 100644
index 000000000..10f4ea796
--- /dev/null
+++ b/src/workshop.c
@@ -0,0 +1,1885 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Visual Workshop integration by Gordon Prieur
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "auto/config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef HAVE_LIBGEN_H
+# include <libgen.h>
+#endif
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <X11/Intrinsic.h>
+#include <Xm/Xm.h>
+#include <Xm/PushB.h>
+
+#include "integration.h" /* <EditPlugin/integration.h> */
+
+#include "vim.h"
+#include "version.h"
+#include "gui_beval.h"
+#include "workshop.h"
+
+void workshop_hotkeys(Boolean);
+
+static Boolean isShowing(int);
+static win_T *get_window(buf_T *);
+#if 0
+static int get_buffer_number(buf_T *);
+#endif
+static void updatePriority(Boolean);
+static char *addUniqueMnemonic(char *, char *);
+static char *fixup(char *);
+static char *get_selection(buf_T *);
+static char *append_selection(int, char *, int *, int *);
+static void load_buffer_by_name(char *, int);
+#if 0
+static void load_buffer_by_number(int, int);
+#endif
+static void load_window(char *, int lnum);
+static void warp_to_pc(int);
+#ifdef FEAT_BEVAL
+static void bevalCB(BalloonEval *, int);
+#endif
+static char *fixAccelText(char *);
+static void addMenu(char *, char *, char *);
+static char *lookupVerb(char *, int);
+static int computeIndex(int, char_u *, int);
+static void coloncmd(char *, Boolean);
+
+extern Widget vimShell;
+extern Widget textArea;
+extern XtAppContext app_context;
+
+static int tbpri; /* ToolBar priority */
+int usingSunWorkShop = 0; /* set if -ws flag is used */
+char curMenuName[BUFSIZ];
+char curMenuPriority[BUFSIZ];
+BalloonEval *balloonEval;
+
+static Boolean workshopInitDone = False;
+static Boolean workshopHotKeysEnabled = False;
+
+/*
+ * The following enum is from <gp_dbx/gp_dbx_common.h>. We can't include it
+ * here because its C++.
+ */
+enum
+{
+ GPLineEval_EVALUATE, /* evaluate expression */
+ GPLineEval_INDIRECT, /* evaluate *<expression> */
+ GPLineEval_TYPE /* type of expression */
+};
+
+/*
+ * Store each verb in the MenuMap. This lets us map from a verb to a menu.
+ * There may be multiple matches for a single verb in this table.
+ */
+#define MENU_INC 50 /* menuMap incremental size increases */
+typedef struct
+{
+ char *name; /* name of the menu */
+ char *accel; /* optional accelerator key */
+ char *verb; /* menu verb */
+} MenuMap;
+static MenuMap *menuMap; /* list of verb/menu mappings */
+static int menuMapSize; /* current size of menuMap */
+static int menuMapMax; /* allocated size of menuMap */
+static char *initialFileCmd; /* save command but defer doing it */
+
+
+ void
+workshop_init()
+{
+ char_u buf[64];
+ int is_dirty = FALSE;
+ int width, height;
+ XtInputMask mask;
+
+ /*
+ * Turn on MenuBar, ToolBar, and Footer.
+ */
+ STRCPY(buf, p_go);
+ if (vim_strchr(p_go, GO_MENUS) == NULL)
+ {
+ STRCAT(buf, "m");
+ is_dirty = TRUE;
+ }
+ if (vim_strchr(p_go, GO_TOOLBAR) == NULL)
+ {
+ STRCAT(buf, "T");
+ is_dirty = TRUE;
+ }
+ if (vim_strchr(p_go, GO_FOOTER) == NULL)
+ {
+ STRCAT(buf, "F");
+ is_dirty = TRUE;
+ }
+ if (is_dirty)
+ set_option_value((char_u *)"go", 0L, buf, 0);
+
+ /*
+ * Set size from workshop_get_width_height().
+ */
+ width = height = 0;
+ if (workshop_get_width_height(&width, &height))
+ {
+ XtVaSetValues(vimShell,
+ XmNwidth, width,
+ XmNheight, height,
+ NULL);
+ }
+
+ /*
+ * Now read in the initial messages from eserve.
+ */
+ while ((mask = XtAppPending(app_context))
+ && (mask & XtIMAlternateInput) && !workshopInitDone)
+ XtAppProcessEvent(app_context, (XtInputMask)XtIMAlternateInput);
+}
+
+ void
+workshop_postinit()
+{
+ do_cmdline_cmd((char_u *)initialFileCmd);
+ ALT_INPUT_LOCK_OFF;
+ free(initialFileCmd);
+ initialFileCmd = NULL;
+}
+
+ void
+ex_wsverb(exarg_T *eap)
+{
+ msg_clr_cmdline();
+ workshop_perform_verb((char *) eap->arg, NULL);
+}
+
+/*
+ * Editor name
+ * This string is recognized by eserve and should be all lower case.
+ * This is how the editor detects that it is talking to gvim instead
+ * of NEdit, for example, when the connection is initiated from the editor.
+ */
+ char *
+workshop_get_editor_name()
+{
+ return "gvim";
+}
+
+/*
+ * Version number of the editor.
+ * This number is communicated along with the protocol
+ * version to the application.
+ */
+ char *
+workshop_get_editor_version()
+{
+ return Version;
+}
+
+/*
+ * Answer functions: called by eserve
+ */
+
+/*
+ * Name:
+ * workshop_load_file
+ *
+ * Function:
+ * Load a given file into the WorkShop buffer.
+ */
+/*ARGSUSED*/
+ void
+workshop_load_file(
+ char *filename, /* the file to load */
+ int line, /* an optional line number (or 0) */
+ char *frameid) /* used for multi-frame support */
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_load_file(%s, %d)\n", filename, line);
+#endif
+
+#ifdef FEAT_BEVAL
+ if (balloonEval == NULL)
+ {
+ /*
+ * Set up the Balloon Expression Evaluation area.
+ * It's enabled by default. Disable it when 'ballooneval' is off.
+ */
+# ifdef FEAT_GUI_GTK
+ balloonEval = gui_mch_create_beval_area(gui.drawarea, NULL,
+ &bevalCB, NULL);
+# else
+ balloonEval = gui_mch_create_beval_area(textArea, NULL, bevalCB, NULL);
+# endif
+ if (!p_beval)
+ gui_mch_disable_beval_area(balloonEval);
+ }
+#endif
+
+ load_window(filename, line);
+}
+
+/*
+ * Reload the WorkShop buffer
+ */
+ void
+workshop_reload_file(
+ char *filename,
+ int line)
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_reload_file(%s, %d)\n", filename, line);
+#endif
+ load_window(filename, line);
+}
+
+ void
+workshop_show_file(
+ char *filename)
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_show_file(%s)\n", filename);
+#endif
+
+ load_window(filename, 0);
+}
+
+ void
+workshop_goto_line(
+ char *filename,
+ int lineno)
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_goto_line(%s, %d)\n", filename, lineno);
+#endif
+
+ load_window(filename, lineno);
+}
+
+/*ARGSUSED*/
+ void
+workshop_front_file(
+ char *filename)
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_front_file()\n");
+#endif
+ /*
+ * Assumption: This function will always be called after a call to
+ * workshop_show_file(), so the file is always showing.
+ */
+ if (vimShell != NULL)
+ XRaiseWindow(gui.dpy, XtWindow(vimShell));
+}
+
+ void
+workshop_save_file(
+ char *filename)
+{
+ char cbuf[BUFSIZ]; /* build vim command here */
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_save_file(%s)\n", filename);
+#endif
+
+ /* Save the given file */
+ sprintf(cbuf, "w %s", filename);
+ coloncmd(cbuf, TRUE);
+}
+
+ void
+workshop_save_files()
+{
+ /* Save the given file */
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_save_files()\n");
+#endif
+
+ add_to_input_buf((char_u *) ":wall\n", 6);
+}
+
+ void
+workshop_quit()
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_quit()\n");
+#endif
+
+ add_to_input_buf((char_u *) ":qall\n", 6);
+}
+
+ void
+workshop_minimize()
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_minimize()\n");
+#endif
+ workshop_minimize_shell(vimShell);
+}
+ void
+workshop_maximize()
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_maximize()\n");
+#endif
+
+ workshop_maximize_shell(vimShell);
+}
+
+ void
+workshop_add_mark_type(
+ int idx,
+ char *colorspec,
+ char *sign)
+{
+ char gbuf[BUFSIZ]; /* buffer for sign name */
+ char cibuf[BUFSIZ]; /* color information */
+ char cbuf[BUFSIZ]; /* command buffer */
+ char *bp;
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ {
+ char *cp;
+
+ cp = strrchr(sign, '/');
+ if (cp == NULL)
+ cp = sign;
+ else
+ cp++; /* skip '/' character */
+ wstrace("workshop_add_mark_type(%d, \"%s\", \"%s\")\n", idx,
+ colorspec && *colorspec ? colorspec : "<None>", cp);
+ }
+#endif
+
+ /*
+ * Isolate the basename of sign in gbuf. We will use this for the
+ * GroupName in the highlight command sent to vim.
+ */
+ STRCPY(gbuf, gettail((char_u *)sign));
+ bp = strrchr(gbuf, '.');
+ if (bp != NULL)
+ *bp = NUL;
+
+ if (gbuf[0] != '-' && gbuf[1] != NUL)
+ {
+ if (colorspec != NULL && *colorspec)
+ {
+ sprintf(cbuf, "highlight WS%s guibg=%s", gbuf, colorspec);
+ coloncmd(cbuf, FALSE);
+ sprintf(cibuf, "linehl=WS%s", gbuf);
+ }
+ else
+ cibuf[0] = NUL;
+
+ sprintf(cbuf, "sign define %d %s icon=%s", idx, cibuf, sign);
+ coloncmd(cbuf, TRUE);
+ }
+}
+
+ void
+workshop_set_mark(
+ char *filename, /* filename which gets the mark */
+ int lineno, /* line number which gets the mark */
+ int markId, /* unique mark identifier */
+ int idx) /* which mark to use */
+{
+ char cbuf[BUFSIZ]; /* command buffer */
+
+ /* Set mark in a given file */
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_set_mark(%s, %d (ln), %d (id), %d (idx))\n",
+ filename, lineno, markId, idx);
+#endif
+
+ sprintf(cbuf, "sign place %d line=%d name=%d file=%s",
+ markId, lineno, idx, filename);
+ coloncmd(cbuf, TRUE);
+}
+
+ void
+workshop_change_mark_type(
+ char *filename, /* filename which gets the mark */
+ int markId, /* unique mark identifier */
+ int idx) /* which mark to use */
+{
+ char cbuf[BUFSIZ]; /* command buffer */
+
+ /* Change mark type */
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_change_mark_type(%s, %d, %d)\n",
+ filename, markId, idx);
+#endif
+
+ sprintf(cbuf, "sign place %d name=%d file=%s", markId, idx, filename);
+ coloncmd(cbuf, TRUE);
+}
+
+/*
+ * Goto the given mark in a file (e.g. show it).
+ * If message is not null, display it in the footer.
+ */
+ void
+workshop_goto_mark(
+ char *filename,
+ int markId,
+ char *message)
+{
+ char cbuf[BUFSIZ]; /* command buffer */
+
+ /* Goto mark */
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_goto_mark(%s, %d (id), %s)\n",
+ filename, markId, message && *message &&
+ !(*message == ' ' && message[1] == NULL) ?
+ message : "<None>");
+#endif
+
+ sprintf(cbuf, "sign jump %d file=%s", markId, filename);
+ coloncmd(cbuf, TRUE);
+ if (message != NULL && *message != NUL)
+ gui_mch_set_footer((char_u *)message);
+}
+
+ void
+workshop_delete_mark(
+ char *filename,
+ int markId)
+{
+ char cbuf[BUFSIZ]; /* command buffer */
+
+ /* Delete mark */
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_delete_mark(%s, %d (id))\n",
+ filename, markId);
+#endif
+
+ sprintf(cbuf, "sign unplace %d file=%s", markId, filename);
+ coloncmd(cbuf, TRUE);
+}
+
+#if 0 /* not used */
+ void
+workshop_delete_all_marks(
+ void *window,
+ Boolean doRefresh)
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_delete_all_marks(%#x, %s)\n",
+ window, doRefresh ? "True" : "False");
+#endif
+
+ coloncmd("sign unplace *", TRUE);
+}
+#endif
+
+ int
+workshop_get_mark_lineno(
+ char *filename,
+ int markId)
+{
+ buf_T *buf; /* buffer containing filename */
+ int lineno; /* line number of filename in buf */
+
+ /* Get mark line number */
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_get_mark_lineno(%s, %d)\n",
+ filename, markId);
+#endif
+
+ lineno = 0;
+ buf = buflist_findname((char_u *)filename);
+ if (buf != NULL)
+ lineno = buf_findsign(buf, markId);
+
+ return lineno;
+}
+
+
+#if 0 /* not used */
+ void
+workshop_adjust_marks(Widget *window, int pos,
+ int inserted, int deleted)
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("XXXworkshop_adjust_marks(%s, %d, %d, %d)\n",
+ window ? XtName(window) : "<None>", pos, inserted, deleted);
+#endif
+}
+#endif
+
+/*
+ * Are there any moved marks? If so, call workshop_move_mark on
+ * each of them now. This is how eserve can find out if for example
+ * breakpoints have moved when a program has been recompiled and
+ * reloaded into dbx.
+ */
+/*ARGSUSED*/
+ void
+workshop_moved_marks(char *filename)
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("XXXworkshop_moved_marks(%s)\n", filename);
+#endif
+}
+
+ int
+workshop_get_font_height()
+{
+ XmFontList fontList; /* fontList made from gui.norm_font */
+ XmString str;
+ Dimension w;
+ Dimension h;
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_get_font_height()\n");
+#endif
+
+ /* Pick the proper signs for this font size */
+ fontList = gui_motif_create_fontlist((XFontStruct *)gui.norm_font);
+ h = 0;
+ if (fontList != NULL)
+ {
+ str = XmStringCreateLocalized("A");
+ XmStringExtent(fontList, str, &w, &h);
+ XmStringFree(str);
+ XmFontListFree(fontList);
+ }
+
+ return (int)h;
+}
+
+/*ARGSUSED*/
+ void
+workshop_footer_message(
+ char *message,
+ int severity) /* severity is currently unused */
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_footer_message(%s, %d)\n", message, severity);
+#endif
+
+ gui_mch_set_footer((char_u *) message);
+}
+
+/*
+ * workshop_menu_begin() is passed the menu name. We determine its mnemonic
+ * here and store its name and priority.
+ */
+ void
+workshop_menu_begin(
+ char *label)
+{
+ vimmenu_T *menu; /* pointer to last menu */
+ int menuPriority = 0; /* priority of new menu */
+ char mnembuf[64]; /* store menubar mnemonics here */
+ char *name; /* label with a mnemonic */
+ char *p; /* used to find mnemonics */
+ int idx; /* index into mnembuf */
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_menu_begin()\n");
+#endif
+
+ /*
+ * Look through all existing (non-PopUp and non-Toolbar) menus
+ * and gather their mnemonics. Use this list to decide what
+ * mnemonic should be used for label.
+ */
+
+ idx = 0;
+ mnembuf[idx++] = 'H'; /* H is mnemonic for Help */
+ for (menu = root_menu; menu != NULL; menu = menu->next)
+ {
+ if (menu_is_menubar(menu->name))
+ {
+ p = strchr((char *)menu->name, '&');
+ if (p != NULL)
+ mnembuf[idx++] = *++p;
+ }
+ if (menu->next != NULL
+ && strcmp((char *) menu->next->dname, "Help") == 0)
+ {
+ menuPriority = menu->priority + 10;
+ break;
+ }
+ }
+ mnembuf[idx++] = NUL;
+ name = addUniqueMnemonic(mnembuf, label);
+
+ sprintf(curMenuName, "%s", name);
+ sprintf(curMenuPriority, "%d.0", menuPriority);
+}
+
+/*
+ * Append the name and priority to strings to be used in vim menu commands.
+ */
+ void
+workshop_submenu_begin(
+ char *label)
+{
+#ifdef WSDEBUG_TRACE
+ if (ws_debug && ws_dlevel & WS_TRACE
+ && strncmp(curMenuName, "ToolBar", 7) != 0)
+ wstrace("workshop_submenu_begin(%s)\n", label);
+#endif
+
+ strcat(curMenuName, ".");
+ strcat(curMenuName, fixup(label));
+
+ updatePriority(True);
+}
+
+/*
+ * Remove the submenu name and priority from curMenu*.
+ */
+
+ void
+workshop_submenu_end()
+{
+ char *p;
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)
+ && strncmp(curMenuName, "ToolBar", 7) != 0)
+ wstrace("workshop_submenu_end()\n");
+#endif
+
+ p = strrchr(curMenuPriority, '.');
+ ASSERT(p != NULL);
+ *p = NUL;
+
+ p = strrchr(curMenuName, '.');
+ ASSERT(p != NULL);
+ *p = NUL;
+}
+
+/*
+ * This is where menus are really made. Each item will generate an amenu vim
+ * command. The globals curMenuName and curMenuPriority contain the name and
+ * priority of the parent menu tree.
+ */
+/*ARGSUSED*/
+ void
+workshop_menu_item(
+ char *label,
+ char *verb,
+ char *accelerator,
+ char *acceleratorText,
+ char *name,
+ char *filepos,
+ char *sensitive)
+{
+ char cbuf[BUFSIZ];
+ char namebuf[BUFSIZ];
+ char accText[BUFSIZ];
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE)
+ && strncmp(curMenuName, "ToolBar", 7) != 0)
+ {
+ if (ws_dlevel & WS_TRACE_VERBOSE)
+ wsdebug("workshop_menu_item(\n"
+ "\tlabel = \"%s\",\n"
+ "\tverb = %s,\n"
+ "\taccelerator = %s,\n"
+ "\tacceleratorText = \"%s\",\n"
+ "\tname = %s,\n"
+ "\tfilepos = %s,\n"
+ "\tsensitive = %s)\n",
+ label && *label ? label : "<None>",
+ verb && *verb ? verb : "<None>",
+ accelerator && *accelerator ?
+ accelerator : "<None>",
+ acceleratorText && *acceleratorText ?
+ acceleratorText : "<None>",
+ name && *name ? name : "<None>",
+ filepos && *filepos ? filepos : "<None>",
+ sensitive);
+ else if (ws_dlevel & WS_TRACE)
+ wstrace("workshop_menu_item(\"%s\", %s)\n",
+ label && *label ? label : "<None>",
+ verb && *verb ? verb : "<None>", sensitive);
+ }
+#endif
+#ifdef WSDEBUG_SENSE
+ if (ws_debug)
+ wstrace("menu: %-21.20s%-21.20s(%s)\n", label, verb,
+ *sensitive == '1' ? "Sensitive" : "Insensitive");
+#endif
+
+ if (acceleratorText != NULL)
+ sprintf(accText, "<Tab>%s", acceleratorText);
+ else
+ accText[0] = NUL;
+ updatePriority(False);
+ sprintf(namebuf, "%s.%s", curMenuName, fixup(label));
+ sprintf(cbuf, "amenu %s %s%s\t:wsverb %s<CR>",
+ curMenuPriority, namebuf, accText, verb);
+
+ coloncmd(cbuf, TRUE);
+ addMenu(namebuf, fixAccelText(acceleratorText), verb);
+
+ if (*sensitive == '0')
+ {
+ sprintf(cbuf, "amenu disable %s", namebuf);
+ coloncmd(cbuf, TRUE);
+ }
+}
+
+/*
+ * This function is called when a complete WorkShop menu description has been
+ * sent over from eserve. We do some menu cleanup.
+ */
+
+ void
+workshop_menu_end()
+{
+ Boolean using_tearoff; /* set per current option setting */
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_menu_end()\n");
+#endif
+
+ using_tearoff = vim_strchr(p_go, GO_TEAROFF) != NULL;
+ gui_mch_toggle_tearoffs(using_tearoff);
+}
+
+ void
+workshop_toolbar_begin()
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_toolbar_begin()\n");
+#endif
+
+ coloncmd("aunmenu ToolBar", True);
+ tbpri = 10;
+}
+
+ void
+workshop_toolbar_end()
+{
+ char_u buf[64];
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ {
+ wstrace("workshop_toolbar_end()\n");
+ }
+#endif
+
+ /*
+ * Turn on ToolBar.
+ */
+ STRCPY(buf, p_go);
+ if (vim_strchr(p_go, 'T') == NULL)
+ {
+ STRCAT(buf, "T");
+ set_option_value((char_u *)"go", 0L, buf, 0);
+ }
+ workshopInitDone = True;
+}
+
+/*ARGSUSED*/
+ void
+workshop_toolbar_button(
+ char *label,
+ char *verb,
+ char *senseVerb,
+ char *filepos,
+ char *help,
+ char *sense,
+ char *file,
+ char *left)
+{
+ char cbuf[BUFSIZ + MAXPATHLEN];
+ char namebuf[BUFSIZ];
+ static int tbid = 1;
+ char_u *p;
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE))
+ wsdebug("workshop_toolbar_button(\"%s\", %s, %s,\n"
+ "\t%s, \"%s\", %s,\n\t\"%s\",\n\t<%s>)\n",
+ label && *label ? label : "<None>",
+ verb && *verb ? verb : "<None>",
+ senseVerb && *senseVerb ? senseVerb : "<None>",
+ filepos && *filepos ? filepos : "<None>",
+ help && *help ? help : "<None>",
+ sense && *sense ? sense : "<None>",
+ file && *file ? file : "<None>",
+ left && *left ? left : "<None>");
+ else if (WSDLEVEL(WS_TRACE))
+ wstrace("workshop_toolbar_button(\"%s\", %s)\n",
+ label && *label ? label : "<None>",
+ verb && *verb ? verb : "<None>");
+#endif
+#ifdef WSDEBUG_SENSE
+ if (ws_debug)
+ wsdebug("button: %-21.20s%-21.20s(%s)\n", label, verb,
+ *sense == '1' ? "Sensitive" : "Insensitive");
+#endif
+
+ if (left && *left && atoi(left) > 0)
+ {
+ /* Add a separator (but pass the width passed after the ':') */
+ sprintf(cbuf, "amenu 1.%d ToolBar.-sep%d:%s- <nul>",
+ tbpri - 5, tbid++, left);
+
+ coloncmd(cbuf, True);
+ }
+
+ p = vim_strsave_escaped((char_u *)label, (char_u *)"\\. ");
+ sprintf(namebuf, "ToolBar.%s", p);
+ vim_free(p);
+ STRCPY(cbuf, "amenu <silent> ");
+ if (file != NULL && *file != NUL)
+ {
+ p = vim_strsave_escaped((char_u *)file, (char_u *)" ");
+ sprintf(cbuf + STRLEN(cbuf), "icon=%s ", p);
+ vim_free(p);
+ }
+ sprintf(cbuf + STRLEN(cbuf), "1.%d %s :wsverb %s<CR>",
+ tbpri, namebuf, verb);
+
+ /* Define the menu item */
+ coloncmd(cbuf, True);
+
+ if (*sense == '0')
+ {
+ /* If menu isn't sensitive at startup... */
+ sprintf(cbuf, "amenu disable %s", namebuf);
+ coloncmd(cbuf, True);
+ }
+
+ if (help && *help)
+ {
+ /* Do the tooltip */
+ sprintf(cbuf, "tmenu %s %s", namebuf, help);
+ coloncmd(cbuf, True);
+ }
+
+ addMenu(namebuf, NULL, verb);
+ tbpri += 10;
+}
+
+ void
+workshop_frame_sensitivities(
+ VerbSense *vs) /* list of verbs to (de)sensitize */
+{
+ VerbSense *vp; /* iterate through vs */
+ char *menu_name; /* used in menu lookup */
+ int cnt; /* count of verbs to skip */
+ int len; /* length of nonvariant part of command */
+ char cbuf[4096];
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE) || WSDLEVEL(4))
+ {
+ wsdebug("workshop_frame_sensitivities(\n");
+ for (vp = vs; vp->verb != NULL; vp++)
+ wsdebug("\t%-25s%d\n", vp->verb, vp->sense);
+ wsdebug(")\n");
+ }
+ else if (WSDLEVEL(WS_TRACE))
+ wstrace("workshop_frame_sensitivities()\n");
+#endif
+#ifdef WSDEBUG_SENSE
+ if (ws_debug)
+ for (vp = vs; vp->verb != NULL; vp++)
+ wsdebug("change: %-21.20s%-21.20s(%s)\n",
+ "", vp->verb, vp->sense == 1 ?
+ "Sensitive" : "Insensitive");
+#endif
+
+ /*
+ * Look for all matching menu entries for the verb. There may be more
+ * than one if the verb has both a menu and toolbar entry.
+ */
+ for (vp = vs; vp->verb != NULL; vp++)
+ {
+ cnt = 0;
+ strcpy(cbuf, "amenu");
+ strcat(cbuf, " ");
+ strcat(cbuf, vp->sense ? "enable" : "disable");
+ strcat(cbuf, " ");
+ len = strlen(cbuf);
+ while ((menu_name = lookupVerb(vp->verb, cnt++)) != NULL)
+ {
+ strcpy(&cbuf[len], menu_name);
+ coloncmd(cbuf, FALSE);
+ }
+ }
+ gui_update_menus(0);
+ gui_mch_flush();
+}
+
+ void
+workshop_set_option(
+ char *option, /* name of a supported option */
+ char *value) /* value to set option to */
+{
+ char cbuf[BUFSIZ]; /* command buffer */
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ {
+ wstrace("workshop_set_option(%s, %s)\n", option, value);
+ }
+#endif
+
+ cbuf[0] = NUL;
+ switch (*option) /* switch on 1st letter */
+ {
+ case 's':
+ if (strcmp(option, "syntax") == 0)
+ sprintf(cbuf, "syntax %s", value);
+ else if (strcmp(option, "savefiles") == 0)
+ ; /* XXX - Not yet implemented */
+ break;
+
+ case 'l':
+ if (strcmp(option, "lineno") == 0)
+ sprintf(cbuf, "set %snu",
+ (strcmp(value, "on") == 0) ? "" : "no");
+ break;
+
+ case 'p':
+ if (strcmp(option, "parentheses") == 0)
+ sprintf(cbuf, "set %ssm",
+ (strcmp(value, "on") == 0) ? "" : "no");
+ break;
+
+ case 'w':
+ /* this option is set by a direct call */
+#ifdef WSDEBUG
+ wsdebug("workshop_set_option: "
+ "Got unexpected workshopkeys option");
+#endif
+ break;
+
+ case 'b': /* these options are set from direct calls */
+ if (option[7] == NUL && strcmp(option, "balloon") == 0)
+ {
+#ifdef WSDEBUG
+ /* set by direct call to workshop_balloon_mode */
+ wsdebug("workshop_set_option: "
+ "Got unexpected ballooneval option");
+#endif
+ }
+ else if (strcmp(option, "balloondelay") == 0)
+ {
+#ifdef WSDEBUG
+ /* set by direct call to workshop_balloon_delay */
+ wsdebug("workshop_set_option: "
+ "Got unexpected balloondelay option");
+#endif
+ }
+ break;
+ }
+ if (cbuf[0] != NUL)
+ coloncmd(cbuf, TRUE);
+}
+
+
+ void
+workshop_balloon_mode(
+ Boolean on)
+{
+ char cbuf[BUFSIZ]; /* command buffer */
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_balloon_mode(%s)\n", on ? "True" : "False");
+#endif
+
+ sprintf(cbuf, "set %sbeval", on ? "" : "no");
+ coloncmd(cbuf, TRUE);
+}
+
+
+ void
+workshop_balloon_delay(
+ int delay)
+{
+ char cbuf[BUFSIZ]; /* command buffer */
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_balloon_delay(%d)\n", delay);
+#endif
+
+ sprintf(cbuf, "set bdlay=%d", delay);
+ coloncmd(cbuf, TRUE);
+}
+
+
+ void
+workshop_show_balloon_tip(
+ char *tip)
+{
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_show_balloon_tip(%s)\n", tip);
+#endif
+
+ if (balloonEval != NULL)
+ gui_mch_post_balloon(balloonEval, (char_u *)tip);
+}
+
+
+ void
+workshop_hotkeys(
+ Boolean on)
+{
+ char cbuf[BUFSIZ]; /* command buffer */
+ MenuMap *mp; /* iterate over menuMap entries */
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_hotkeys(%s)\n", on ? "True" : "False");
+#endif
+
+ workshopHotKeysEnabled = on;
+ if (workshopHotKeysEnabled)
+ for (mp = menuMap; mp < &menuMap[menuMapSize]; mp++)
+ {
+ if (mp->accel != NULL)
+ {
+ sprintf(cbuf, "map %s :wsverb %s<CR>", mp->accel, mp->verb);
+ coloncmd(cbuf, TRUE);
+ }
+ }
+ else
+ for (mp = menuMap; mp < &menuMap[menuMapSize]; mp++)
+ {
+ if (mp->accel != NULL)
+ {
+ sprintf(cbuf, "unmap %s", mp->accel);
+ coloncmd(cbuf, TRUE);
+ }
+ }
+}
+
+/*
+ * A button in the toolbar has been pushed.
+ */
+/*ARGSUSED*/
+ int
+workshop_get_positions(
+ void *clientData, /* unused */
+ char **filename, /* output data */
+ int *curLine, /* output data */
+ int *curCol, /* output data */
+ int *selStartLine, /* output data */
+ int *selStartCol, /* output data */
+ int *selEndLine, /* output data */
+ int *selEndCol, /* output data */
+ int *selLength, /* output data */
+ char **selection) /* output data */
+{
+ static char ffname[MAXPATHLEN];
+
+#ifdef WSDEBUG_TRACE
+ if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
+ wstrace("workshop_get_positions(%#x, \"%s\", ...)\n",
+ clientData, (curbuf && curbuf->b_sfname != NULL)
+ ? (char *)curbuf->b_sfname : "<None>");
+#endif
+
+ strcpy(ffname, (char *) curbuf->b_ffname);
+ *filename = ffname; /* copy so nobody can change b_ffname */
+ *curLine = curwin->w_cursor.lnum;
+ *curCol = curwin->w_cursor.col;
+
+ if (curbuf->b_visual_mode == 'v' &&
+ equalpos(curwin->w_cursor, curbuf->b_visual_end))
+ {
+ *selStartLine = curbuf->b_visual_start.lnum;
+ *selStartCol = curbuf->b_visual_start.col;
+ *selEndLine = curbuf->b_visual_end.lnum;
+ *selEndCol = curbuf->b_visual_end.col;
+ *selection = get_selection(curbuf);
+ if (*selection)
+ *selLength = strlen(*selection);
+ else
+ *selLength = 0;
+ }
+ else
+ {
+ *selStartLine = *selEndLine = -1;
+ *selStartCol = *selEndCol = -1;
+ *selLength = 0;
+ *selection = "";
+ }
+
+ return True;
+}
+
+
+
+/************************************************************************
+ * Utility functions
+ ************************************************************************/
+
+ static char *
+get_selection(
+ buf_T *buf) /* buffer whose selection we want */
+{
+ pos_T *start; /* start of the selection */
+ pos_T *end; /* end of the selection */
+ char *lp; /* pointer to actual line data */
+ int llen; /* length of actual line data */
+ char *sp; /* pointer to selection buffer */
+ int slen; /* string length in selection buffer */
+ int size; /* size of selection buffer */
+ char *new_sp; /* temp pointer to new sp */
+ int lnum; /* line number we are appending */
+
+ if (buf->b_visual_mode == 'v')
+ {
+ start = &buf->b_visual_start;
+ end = &buf->b_visual_end;
+ if (start->lnum == end->lnum)
+ {
+ /* selection is all on one line */
+ lp = (char *) ml_get_pos(start);
+ llen = end->col - start->col + 1;
+ sp = (char *) malloc(llen + 1);
+ if (sp != NULL)
+ {
+ strncpy(sp, lp, llen);
+ sp[llen] = NUL;
+ }
+ }
+ else
+ {
+ /* multi-line selection */
+ lp = (char *) ml_get_pos(start);
+ llen = strlen(lp);
+ sp = (char *) malloc(BUFSIZ + llen);
+ if (sp != NULL)
+ {
+ size = BUFSIZ + llen;
+ strcpy(sp, lp);
+ sp[llen] = '\n';
+ slen = llen + 1;
+
+ lnum = start->lnum + 1;
+ while (lnum < end->lnum)
+ sp = append_selection(lnum++, sp, &size, &slen);
+
+ lp = (char *) ml_get(end->lnum);
+ llen = end->col + 1;
+ if ((slen + llen) >= size)
+ {
+ new_sp = (char *)
+ realloc(sp, slen + llen + 1);
+ if (new_sp != NULL)
+ {
+ size += llen + 1;
+ sp = new_sp;
+ }
+ }
+ if ((slen + llen) < size)
+ {
+ strncpy(&sp[slen], lp, llen);
+ sp[slen + llen] = NUL;
+ }
+
+ }
+ }
+ }
+ else
+ sp = NULL;
+
+ return sp;
+}
+
+ static char *
+append_selection(
+ int lnum, /* line number to append */
+ char *sp, /* pointer to selection buffer */
+ int *size, /* ptr to size of sp */
+ int *slen) /* ptr to length of selection string */
+{
+ char *lp; /* line of data from buffer */
+ int llen; /* strlen of lp */
+ char *new_sp; /* temp pointer to new sp */
+
+ lp = (char *)ml_get((linenr_T)lnum);
+ llen = strlen(lp);
+
+ if ((*slen + llen) <= *size)
+ {
+ new_sp = (char *) realloc((void *) sp, BUFSIZ + *slen + llen);
+ if (*new_sp != NUL)
+ {
+ *size = BUFSIZ + *slen + llen;
+ sp = new_sp;
+ }
+ }
+ if ((*slen + llen) > *size)
+ {
+ strcat(&sp[*slen], lp);
+ *slen += llen;
+ sp[*slen++] = '\n';
+ }
+
+ return sp;
+}
+
+
+
+ static void
+load_buffer_by_name(
+ char *filename, /* the file to load */
+ int lnum) /* an optional line number (or 0) */
+{
+ char lnumbuf[16]; /* make line number option for :e */
+ char cbuf[BUFSIZ]; /* command buffer */
+
+ if (lnum > 0)
+ sprintf(lnumbuf, "+%d", lnum);
+ else
+ lnumbuf[0] = NUL;
+
+ sprintf(cbuf, "e %s %s", lnumbuf, filename);
+ coloncmd(cbuf, False);
+}
+
+
+ static void
+load_window(
+ char *filename, /* filename to load */
+ int lnum) /* linenumber to go to */
+{
+ buf_T *buf; /* buffer filename is stored in */
+ win_T *win; /* window filenme is displayed in */
+
+ /*
+ * Make sure filename is displayed and is the current window.
+ */
+
+ buf = buflist_findname((char_u *)filename);
+ if (buf == NULL || (win = get_window(buf)) == NULL)
+ {
+ /* No buffer or buffer is not in current window */
+ /* wsdebug("load_window: load_buffer_by_name(\"%s\", %d)\n",
+ filename, lnum); */
+ load_buffer_by_name(filename, lnum);
+ }
+ else
+ {
+ /* buf is in a window */
+ if (win != curwin)
+ {
+ win_enter(win, False);
+ /* wsdebug("load_window: window endter %s\n",
+ win->w_buffer->b_sfname); */
+ }
+ if (lnum > 0 && win->w_cursor.lnum != lnum)
+ {
+ warp_to_pc(lnum);
+ /* wsdebug("load_window: warp to %s[%d]\n",
+ win->w_buffer->b_sfname, lnum); */
+ }
+ }
+ out_flush();
+}
+
+
+
+ static void
+warp_to_pc(
+ int lnum) /* line number to warp to */
+{
+ char lbuf[256]; /* build line comand here */
+
+ if (lnum > 0)
+ {
+ if (State & INSERT)
+ add_to_input_buf((char_u *) "\033", 1);
+ if (isShowing(lnum))
+ sprintf(lbuf, "%dG", lnum);
+ else
+ sprintf(lbuf, "%dz.", lnum);
+ add_to_input_buf((char_u *) lbuf, strlen(lbuf));
+ }
+}
+
+ static Boolean
+isShowing(
+ int lnum) /* tell if line number is showing */
+{
+ return lnum >= curwin->w_topline && lnum < curwin->w_botline;
+}
+
+
+
+ static win_T *
+get_window(
+ buf_T *buf) /* buffer to find window for */
+{
+ win_T *wp = NULL; /* window filename is in */
+
+ for (wp = firstwin; wp != NULL; wp = W_NEXT(wp))
+ if (buf == wp->w_buffer)
+ break;
+ return wp;
+}
+
+
+#if 0 /* not used */
+ static int
+get_buffer_number(
+ buf_T *buf) /* buffer to get position of */
+{
+ buf_T *bp; /* iterate over buffer list */
+ int pos; /* the position in the buffer list */
+
+ pos = 1;
+ for (bp = firstbuf; bp != NULL; bp = bp->b_next)
+ {
+ if (bp == buf)
+ return pos;
+ pos++;
+ }
+
+ return 1;
+}
+#endif
+
+ static void
+updatePriority(
+ Boolean subMenu) /* if True then start new submenu pri */
+{
+ int pri; /* priority of this menu/item */
+ char *p;
+
+ p = strrchr(curMenuPriority, '.');
+ ASSERT(p != NULL);
+ *p++ = NUL;
+
+ pri = atoi(p) + 10; /* our new priority */
+
+ if (subMenu)
+ sprintf(curMenuPriority, "%s.%d.0", curMenuPriority, pri);
+ else
+ sprintf(curMenuPriority, "%s.%d", curMenuPriority, pri);
+}
+
+ static char *
+addUniqueMnemonic(
+ char *mnemonics, /* currently used mnemonics */
+ char *label) /* label of menu needing mnemonic */
+{
+ static char name[BUFSIZ]; /* buffer for the updated name */
+ char *p; /* pointer into label */
+ char *found; /* pointer to possible mnemonic */
+
+ found = NULL;
+ for (p = label; *p != NUL; p++)
+ if (strchr(mnemonics, *p) == 0)
+ if (found == NULL || (isupper((int)*p) && islower((int)*found)))
+ found = p;
+
+ if (found != NULL)
+ {
+ strncpy(name, label, (found - label));
+ strcat(name, "&");
+ strcat(name, found);
+ }
+ else
+ strcpy(name, label);
+
+ return name;
+}
+
+/*
+ * Some characters in a menu name must be escaped in vim. Since this is vim
+ * specific, it must be done on this side.
+ */
+ static char *
+fixup(
+ char *label)
+{
+ static char buf[BUFSIZ];
+ char *bp; /* pointer into buf */
+ char *lp; /* pointer into label */
+
+ lp = label;
+ bp = buf;
+ while (*lp != NUL)
+ {
+ if (*lp == ' ' || *lp == '.')
+ *bp++ = '\\';
+ *bp++ = *lp++;
+ }
+ *bp = NUL;
+
+ return buf;
+}
+
+
+#ifdef NOHANDS_SUPPORT_FUNCTIONS
+
+/* For the NoHands test suite */
+
+ char *
+workshop_test_getcurrentfile()
+{
+ char *filename, *selection;
+ int curLine, curCol, selStartLine, selStartCol, selEndLine;
+ int selEndCol, selLength;
+
+ if (workshop_get_positions(
+ NULL, &filename, &curLine, &curCol, &selStartLine,
+ &selStartCol, &selEndLine, &selEndCol, &selLength,
+ &selection))
+ return filename;
+ else
+ return NULL;
+}
+
+ int
+workshop_test_getcursorrow()
+{
+ return 0;
+}
+
+ int
+workshop_test_getcursorcol()
+{
+ char *filename, *selection;
+ int curLine, curCol, selStartLine, selStartCol, selEndLine;
+ int selEndCol, selLength;
+
+ if (workshop_get_positions(
+ NULL, &filename, &curLine, &curCol, &selStartLine,
+ &selStartCol, &selEndLine, &selEndCol, &selLength,
+ &selection))
+ return curCol;
+ else
+ return -1;
+}
+
+ char *
+workshop_test_getcursorrowtext()
+{
+ return NULL;
+}
+
+ char *
+workshop_test_getselectedtext()
+{
+ char *filename, *selection;
+ int curLine, curCol, selStartLine, selStartCol, selEndLine;
+ int selEndCol, selLength;
+
+ if (workshop_get_positions(
+ NULL, &filename, &curLine, &curCol, &selStartLine,
+ &selStartCol, &selEndLine, &selEndCol, &selLength,
+ &selection))
+ return selection;
+ else
+ return NULL;
+}
+
+/*ARGSUSED*/
+ void
+workshop_save_sensitivity(char *filename)
+{
+}
+
+#endif
+
+ static char *
+fixAccelText(
+ char *ap) /* original acceleratorText */
+{
+ char buf[256]; /* build in temp buffer */
+ char *shift; /* shift string of "" */
+
+ if (ap == NULL)
+ return NULL;
+
+ /* If the accelerator is shifted use the vim form */
+ if (strncmp("Shift+", ap, 6) == 0)
+ {
+ shift = "S-";
+ ap += 6;
+ }
+ else
+ shift = "";
+
+ if (*ap == 'F' && atoi(&ap[1]) > 0)
+ {
+ sprintf(buf, "<%s%s>", shift, ap);
+ return strdup(buf);
+ }
+ else
+ return NULL;
+}
+
+#ifdef FEAT_BEVAL
+ static void
+bevalCB(
+ BalloonEval *beval,
+ int state)
+{
+ char_u *filename;
+ char_u *text;
+ int type;
+ int line;
+ int col;
+ int idx;
+ char buf[MAXPATHLEN * 2];
+ static int serialNo = -1;
+
+ if (!p_beval)
+ return;
+
+ if (gui_mch_get_beval_info(beval, &filename, &line, &text, &col) == OK)
+ {
+ if (text && text[0])
+ {
+ /* Send debugger request */
+ if (strlen((char *) text) > (MAXPATHLEN/2))
+ {
+ /*
+ * The user has probably selected the entire
+ * buffer or something like that - don't attempt
+ * to evaluate it
+ */
+ return;
+ }
+
+ /*
+ * WorkShop expects the col to be a character index, not
+ * a column number. Compute the index from col. Also set
+ * line to 0 because thats what dbx expects.
+ */
+ idx = computeIndex(col, text, beval->ts);
+ if (idx > 0)
+ {
+ line = 0;
+
+ /*
+ * If successful, it will respond with a balloon cmd.
+ */
+ if (state & ControlMask)
+ /* Evaluate *(expression) */
+ type = (int)GPLineEval_INDIRECT;
+ else if (state & ShiftMask)
+ /* Evaluate type(expression) */
+ type = (int)GPLineEval_TYPE;
+ else
+ /* Evaluate value(expression) */
+ type = (int)GPLineEval_EVALUATE;
+
+ /* Send request to dbx */
+ sprintf(buf, "toolVerb debug.balloonEval "
+ "%s %d,0 %d,0 %d,%d %d %s\n", (char *) filename,
+ line, idx, type, serialNo++,
+ strlen((char *) text), (char *) text);
+ balloonEval = beval;
+ workshop_send_message(buf);
+ }
+ }
+ }
+}
+#endif
+
+
+ static int
+computeIndex(
+ int wantedCol,
+ char_u *line,
+ int ts)
+{
+ int col = 0;
+ int idx = 0;
+
+ while (line[idx])
+ {
+ if (line[idx] == '\t')
+ col += ts - (col % ts);
+ else
+ col++;
+ idx++;
+ if (col >= wantedCol)
+ return idx;
+ }
+
+ return -1;
+}
+
+ static void
+addMenu(
+ char *menu, /* menu name */
+ char *accel, /* accelerator text (optional) */
+ char *verb) /* WorkShop action-verb */
+{
+ MenuMap *newMap;
+ char cbuf[BUFSIZ];
+
+ if (menuMapSize >= menuMapMax)
+ {
+ newMap = realloc(menuMap,
+ sizeof(MenuMap) * (menuMapMax + MENU_INC));
+ if (newMap != NULL)
+ {
+ menuMap = newMap;
+ menuMapMax += MENU_INC;
+ }
+ }
+ if (menuMapSize < menuMapMax)
+ {
+ menuMap[menuMapSize].name = strdup(menu);
+ menuMap[menuMapSize].accel = accel && *accel ? strdup(accel) : NULL;
+ menuMap[menuMapSize++].verb = strdup(verb);
+ if (accel && workshopHotKeysEnabled)
+ {
+ sprintf(cbuf, "map %s :wsverb %s<CR>", accel, verb);
+ coloncmd(cbuf, TRUE);
+ }
+ }
+}
+
+ static char *
+nameStrip(
+ char *raw) /* menu name, possibly with & chars */
+{
+ static char buf[BUFSIZ]; /* build stripped name here */
+ char *bp = buf;
+
+ while (*raw)
+ {
+ if (*raw != '&')
+ *bp++ = *raw;
+ raw++;
+ }
+ *bp = NUL;
+ return buf;
+}
+
+
+ static char *
+lookupVerb(
+ char *verb,
+ int skip) /* number of matches to skip */
+{
+ int i; /* loop iterator */
+
+ for (i = 0; i < menuMapSize; i++)
+ if (strcmp(menuMap[i].verb, verb) == 0 && skip-- == 0)
+ return nameStrip(menuMap[i].name);
+
+ return NULL;
+}
+
+
+ static void
+coloncmd(
+ char *cmd, /* the command to print */
+ Boolean force) /* force cursor update */
+{
+ char_u *cpo_save = p_cpo;
+
+#ifdef WSDEBUG
+ if (WSDLEVEL(WS_TRACE_COLONCMD))
+ wsdebug("Cmd: %s\n", cmd);
+#endif
+
+ p_cpo = empty_option;
+
+ ALT_INPUT_LOCK_ON;
+ do_cmdline_cmd((char_u *)cmd);
+ ALT_INPUT_LOCK_OFF;
+
+ p_cpo = cpo_save;
+
+ if (force)
+ gui_update_screen();
+}
+
+/*
+ * setDollarVim - Given the run directory, search for the vim install
+ * directory and set $VIM.
+ *
+ * We can be running out of SUNWspro/bin or out of
+ * SUNWspro/contrib/contrib6/vim5.6/bin so we check
+ * relative to both of these directories.
+ */
+ static void
+setDollarVim(
+ char *rundir)
+{
+ char buf[MAXPATHLEN];
+ char *cp;
+
+ /*
+ * First case: Running from <install-dir>/SUNWspro/bin
+ */
+ strcpy(buf, rundir);
+ strcat(buf, "/../contrib/contrib6/vim" VIM_VERSION_SHORT "/share/vim/"
+ VIM_VERSION_NODOT "/syntax/syntax.vim");
+ if (access(buf, R_OK) == 0)
+ {
+ strcpy(buf, "SPRO_WSDIR=");
+ strcat(buf, rundir);
+ cp = strrchr(buf, '/');
+ if (cp != NULL)
+ strcpy(cp, "/WS6U2");
+ putenv(strdup(buf));
+
+ strcpy(buf, "VIM=");
+ strcat(buf, rundir);
+ strcat(buf, "/../contrib/contrib6/vim" VIM_VERSION_SHORT "/share/vim/"
+ VIM_VERSION_NODOT);
+ putenv(strdup(buf));
+ return;
+ }
+
+ /*
+ * Second case: Probably running from
+ * <install-dir>/SUNWspro/contrib/contrib6/vim5.6/bin
+ */
+ strcpy(buf, rundir);
+ strcat(buf, "/../../../contrib/contrib6/vim" VIM_VERSION_SHORT
+ "/share/vim/" VIM_VERSION_NODOT "/syntax/syntax.vim");
+ if (access(buf, R_OK) == 0)
+ {
+ strcpy(buf, "SPRO_WSDIR=");
+ strcat(buf, rundir);
+ cp = strrchr(buf, '/');
+ if (cp != NULL)
+ strcpy(cp, "../../../../WS6U2");
+ putenv(strdup(buf));
+
+ strcpy(buf, "VIM=");
+ strcat(buf, rundir);
+ strcat(buf, "/../../../contrib/contrib6/vim" VIM_VERSION_SHORT
+ "/share/vim/" VIM_VERSION_NODOT);
+ putenv(strdup(buf));
+ return;
+ }
+}
+
+/*
+ * findYourself - Find the directory we are running from. This is used to
+ * set $VIM. We need to set this because users can install
+ * the package in a different directory than the compiled
+ * directory. This is a Sun Visual WorkShop requirement!
+ *
+ * Note: We override a user's $VIM because it won't have the
+ * WorkShop specific files. S/he may not like this but its
+ * better than getting the wrong files (especially as the
+ * user is likely to have $VIM set to 5.4 or later).
+ */
+ void
+findYourself(
+ char *argv0)
+{
+ char *runpath = NULL;
+ char *path;
+ char *pathbuf;
+
+ if (*argv0 == '/')
+ runpath = strdup(argv0);
+ else if (*argv0 == '.' || strchr(argv0, '/'))
+ {
+ runpath = (char *) malloc(MAXPATHLEN);
+ getcwd(runpath, MAXPATHLEN);
+ strcat(runpath, "/");
+ strcat(runpath, argv0);
+ }
+ else
+ {
+ path = getenv("PATH");
+ if (path != NULL)
+ {
+ runpath = (char *) malloc(MAXPATHLEN);
+ pathbuf = strdup(path);
+ path = strtok(pathbuf, ":");
+ do
+ {
+ strcpy(runpath, path);
+ strcat(runpath, "/");
+ strcat(runpath, argv0);
+ if (access(runpath, X_OK) == 0)
+ break;
+ } while ((path = strtok(NULL, ":")) != NULL);
+ free(pathbuf);
+ }
+ }
+
+ if (runpath != NULL)
+ {
+ char runbuf[MAXPATHLEN];
+
+ /*
+ * We found the run directory. Now find the install dir.
+ */
+ (void)vim_FullName((char_u *)runpath, (char_u *)runbuf, MAXPATHLEN, 1);
+ path = strrchr(runbuf, '/');
+ if (path != NULL)
+ *path = NUL; /* remove the vim/gvim name */
+ path = strrchr(runbuf, '/');
+ if (path != NULL)
+ {
+ if (strncmp(path, "/bin", 4) == 0)
+ setDollarVim(runbuf);
+ else if (strncmp(path, "/src", 4) == 0)
+ {
+ *path = NUL; /* development tree */
+ setDollarVim(runbuf);
+ }
+ }
+ free(runpath);
+ }
+}
diff --git a/src/workshop.h b/src/workshop.h
new file mode 100644
index 000000000..06b125720
--- /dev/null
+++ b/src/workshop.h
@@ -0,0 +1,28 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Visual Workshop integration by Gordon Prieur
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+#if !defined(WORKSHOP_H) && defined(FEAT_SUN_WORKSHOP)
+#define WORKSHOP_H
+
+#include <X11/Intrinsic.h>
+#include <Xm/Xm.h>
+
+#include "integration.h"
+
+#ifdef WSDEBUG
+# include "wsdebug.h"
+#else
+# ifndef ASSERT
+# define ASSERT(c)
+# endif
+#endif
+
+extern int usingSunWorkShop; /* set if -ws flag is used */
+
+#endif
diff --git a/src/wsdebug.c b/src/wsdebug.c
new file mode 100644
index 000000000..c3dba9931
--- /dev/null
+++ b/src/wsdebug.c
@@ -0,0 +1,179 @@
+/* vi:set ts=8 sts=8 sw=8:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Visual Workshop integration by Gordon Prieur
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * WorkShop Debugging Tools. What are these tools and why are they important?
+ * There are two main tools here. The first tool is a tool for delaying or
+ * stopping gvim during startup. The second tool is a protocol log tool.
+ *
+ * The startup delay tool is called wsdebug_wait(). This is very important for
+ * debugging startup problems because gvim will be started automatically from
+ * workshop and cannot be run directly from a debugger. The only way to debug
+ * a gvim started by workshop is by attaching a debugger to it. Without this
+ * tool all starup code will have completed before you can get the pid and
+ * attach.
+ *
+ * The second tool is a protocol log tool. The workshop editor server and gvim
+ * pass information back and forth during a workshop session. Sometimes it is
+ * very important to peruse this conversation in order to understand what is
+ * happening. The wsdebug_log_init() call sets up this protocol log tool and
+ * wsdebug() and wstrace() calls output the information to the log.
+ *
+ * This code must have WSDEBUG defined for it to be compiled into vim/gvim.
+ */
+
+#ifdef WSDEBUG
+
+#include <stdarg.h>
+
+#include "vim.h"
+
+FILE *ws_debug = NULL;
+u_int ws_dlevel = 0; /* ws_debug verbosity level */
+
+void wsdebug(char *, ...);
+void wstrace(char *, ...);
+
+static int lookup(char *);
+static int errorHandler(Display *, XErrorEvent *);
+
+
+/*
+ * wsdebug_wait - This function can be used to delay or stop execution of vim.
+ * Its normally used to delay startup while attaching a
+ * debugger to a running process. Since workshop starts gvim
+ * from a background process this is the only way to debug
+ * startup problems.
+ */
+
+void wsdebug_wait(
+ u_int wait_flags, /* tells what to do */
+ char *wait_var, /* wait environment variable */
+ u_int wait_secs) /* how many seconds to wait */
+{
+
+ init_homedir(); /* not inited yet */
+#ifdef USE_WDDUMP
+ WDDump(0, 0, 0);
+#endif
+
+ /* for debugging purposes only */
+ if (wait_flags & WT_ENV && wait_var && getenv(wait_var) != NULL) {
+ sleep(atoi(getenv(wait_var)));
+ } else if (wait_flags & WT_WAIT && lookup("~/.gvimwait")) {
+ sleep(wait_secs > 0 && wait_secs < 120 ? wait_secs : 20);
+ } else if (wait_flags & WT_STOP && lookup("~/.gvimstop")) {
+ int w = 1;
+ while (w) {
+ ;
+ }
+ }
+} /* end wsdebug_wait */
+
+
+void
+wsdebug_log_init(
+ char *log_var, /* env var with log file */
+ char *level_var) /* env var with ws_debug level */
+{
+ char *file; /* possible ws_debug output file */
+ char *cp; /* ws_dlevel pointer */
+
+ if (log_var && (file = getenv(log_var)) != NULL) {
+ char buf[BUFSIZ];
+
+ sprintf(buf, "date > %s", file);
+ system(buf);
+ ws_debug = fopen(file, "a");
+ if (level_var && (cp = getenv(level_var)) != NULL) {
+ ws_dlevel = strtoul(cp, NULL, 0);
+ } else {
+ ws_dlevel = WS_TRACE; /* default level */
+ }
+ /* XSetErrorHandler(errorHandler); */
+ }
+
+} /* end wsdebug_log_init */
+
+
+
+
+void
+wstrace(
+ char *fmt,
+ ...)
+{
+ va_list ap;
+
+ if (ws_debug!= NULL && (ws_dlevel & (WS_TRACE | WS_TRACE_VERBOSE))) {
+ va_start(ap, fmt);
+ vfprintf(ws_debug, fmt, ap);
+ va_end(ap);
+ fflush(ws_debug);
+ }
+
+} /* end wstrace */
+
+
+void
+wsdebug(
+ char *fmt,
+ ...)
+{
+ va_list ap;
+
+ if (ws_debug != NULL) {
+ va_start(ap, fmt);
+ vfprintf(ws_debug, fmt, ap);
+ va_end(ap);
+ fflush(ws_debug);
+ }
+
+} /* end wsdebug */
+
+
+static int
+lookup(
+ char *file)
+{
+ char buf[BUFSIZ];
+
+ expand_env((char_u *) file, (char_u *) buf, BUFSIZ);
+ return (access(buf, F_OK) == 0);
+
+} /* end lookup */
+
+static int
+errorHandler(
+ Display *dpy,
+ XErrorEvent *err)
+{
+ char msg[256];
+ char buf[256];
+
+ XGetErrorText(dpy, err->error_code, msg, sizeof(msg));
+ wsdebug("\n\nWSDEBUG Vim: X Error of failed request: %s\n", msg);
+
+ sprintf(buf, "%d", err->request_code);
+ XGetErrorDatabaseText(dpy,
+ "XRequest", buf, "Unknown", msg, sizeof(msg));
+ wsdebug("\tMajor opcode of failed request: %d (%s)\n",
+ err->request_code, msg);
+ if (err->request_code > 128) {
+ wsdebug("\tMinor opcode of failed request: %d\n",
+ err->minor_code);
+ }
+
+ return 0;
+}
+
+
+
+#endif /* WSDEBUG */
diff --git a/src/wsdebug.h b/src/wsdebug.h
new file mode 100644
index 000000000..03da5697c
--- /dev/null
+++ b/src/wsdebug.h
@@ -0,0 +1,81 @@
+/* vi:set ts=8 sts=8 sw=8:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * Visual Workshop integration by Gordon Prieur
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ */
+
+
+#ifndef WSDEBUG_H
+#define WSDEBUG_H
+
+#ifdef WSDEBUG
+
+#ifndef ASSERT
+#define ASSERT(c) \
+ if (!(c)) { \
+ fprintf(stderr, "Assertion failed: line %d, file %s\n", \
+ __LINE__, __FILE__); \
+ fflush(stderr); \
+ abort(); \
+ }
+#endif
+
+#define WS_TRACE 0x00000001
+#define WS_TRACE_VERBOSE 0x00000002
+#define WS_TRACE_COLONCMD 0x00000004
+#define WS_DEBUG_ALL 0xffffffff
+
+#define WSDLEVEL(flags) (ws_debug != NULL && (ws_dlevel & (flags)))
+
+#ifdef USE_WDDUMP
+#include "wdump.h"
+#endif
+
+#define WSDEBUG_TRACE 1
+//#define WSDEBUG_SENSE 2
+
+typedef enum {
+ WT_ENV = 1, /* look for env var if set */
+ WT_WAIT, /* look for ~/.gvimwait if set */
+ WT_STOP /* look for ~/.gvimstop if set */
+} WtWait;
+
+
+void wsdebug(char *, ...);
+void wstrace(char *, ...);
+
+
+extern FILE *ws_debug;
+extern u_int ws_dlevel; /* ws_debug verbosity level */
+
+# else /* not WSDEBUG */
+
+#ifndef ASSERT
+# define ASSERT(c)
+#endif
+
+/*
+ * The following 2 stubs are needed because a macro cannot be used because of
+ * the variable number of arguments.
+ */
+
+void
+wsdebug(
+ char *fmt,
+ ...)
+{
+}
+
+
+void
+wstrace(
+ char *fmt,
+ ...)
+{
+}
+
+#endif /* WSDEBUG */
+#endif /* WSDEBUG_H */
diff --git a/src/xpm_w32.c b/src/xpm_w32.c
new file mode 100644
index 000000000..45765e1f1
--- /dev/null
+++ b/src/xpm_w32.c
@@ -0,0 +1,60 @@
+/*
+ * Load XPM image.
+ *
+ * This function is placed in separate file because Xpm headers conflict with
+ * Vim ones :(
+ *
+ * Written by Sergey Khorev.
+ * http://iamphet.nm.ru/vim/index.html
+ */
+
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+/* reduced def from Vim.h */
+#ifndef __ARGS
+# if defined(__STDC__) || defined(__GNUC__) || defined(WIN3264)
+# define __ARGS(x) x
+# else
+# define __ARGS(x) ()
+# endif
+#endif
+
+#include "xpm_w32.h"
+
+/* Engage Windows support in libXpm */
+#define FOR_MSW
+
+#include "xpm.h"
+
+/*
+ * Tries to load Xpm image from file 'filename'.
+ * If fails return -1.
+ * success - 0 and image and mask BITMAPS
+ */
+ int
+LoadXpmImage(filename, hImage, hShape)
+ char *filename;
+ HBITMAP *hImage;
+ HBITMAP *hShape;
+{
+ XImage *img; /* loaded image */
+ XImage *shp; /* shapeimage */
+ XpmAttributes attr;
+ int res;
+ HDC hdc = CreateCompatibleDC(NULL);
+
+ attr.valuemask = 0;
+ res = XpmReadFileToImage(&hdc, filename, &img, &shp, &attr);
+ DeleteDC(hdc);
+ if (res < 0)
+ return -1;
+ else
+ {
+ *hImage = img->bitmap;
+ *hShape = shp->bitmap;
+ return 0;
+ }
+}
diff --git a/src/xpm_w32.h b/src/xpm_w32.h
new file mode 100644
index 000000000..3fe447586
--- /dev/null
+++ b/src/xpm_w32.h
@@ -0,0 +1,7 @@
+/*
+ * Header file for xpm_w32.c
+ */
+
+#ifndef XPM_W32__H
+int LoadXpmImage __ARGS((char *filename, HBITMAP *hImage, HBITMAP *hShape));
+#endif
diff --git a/src/xxd/Make_amiga.mak b/src/xxd/Make_amiga.mak
new file mode 100644
index 000000000..be382027b
--- /dev/null
+++ b/src/xxd/Make_amiga.mak
@@ -0,0 +1,18 @@
+# Makefile for xxd on the Amiga, using Aztec/Manx C 5.0 or later
+#
+
+#>>>>> choose between debugging (-bs) or optimizing (-so)
+OPTIONS = -so
+#OPTIONS = -bs
+
+#>>>>>> choose -g for debugging
+LN_DEBUG =
+#LN_DEBUG = -g
+
+CFLAGS = $(OPTIONS) -wapruq -ps -qf -DAMIGA -Dconst=
+
+Xxd: xxd.o
+ ln +q -m $(LN_DEBUG) -o Xxd xxd.o -lc16
+
+xxd.o: xxd.c
+ cc $(CFLAGS) xxd.c -o xxd.o
diff --git a/src/xxd/Make_bc3.mak b/src/xxd/Make_bc3.mak
new file mode 100644
index 000000000..dee252171
--- /dev/null
+++ b/src/xxd/Make_bc3.mak
@@ -0,0 +1,31 @@
+# Simple makefile for Borland C++ 4.0
+# 3.1 can NOT be used, it has problems with the fileno() define.
+
+# Command line variables:
+# BOR path to root of Borland C (E:\BORLANDC)
+# DEBUG set to "yes" for debugging (no)
+
+!ifndef BOR
+BOR = e:\bc4
+!endif
+
+!if ("$(DEBUG)" == "yes")
+DEBUG_FLAG = -v -DDEBUG
+!else
+DEBUG_FLAG =
+!endif
+
+CC = $(BOR)\bin\bcc
+INC = -I$(BOR)\include
+LIB = -L$(BOR)\lib
+
+# The following compile options can be changed for better machines.
+# replace -1- with -2 to produce code for a 80286 or higher
+# replace -1- with -3 to produce code for a 80386 or higher
+# add -v for source debugging
+OPTIMIZE= -1- -Ox
+
+CFLAGS = -A -mc -DMSDOS $(DEBUG_FLAG) $(OPTIMIZE) $(INC) $(LIB)
+
+xxd.exe: xxd.c
+ $(CC) $(CFLAGS) xxd.c
diff --git a/src/xxd/Make_bc5.mak b/src/xxd/Make_bc5.mak
new file mode 100644
index 000000000..4f446223e
--- /dev/null
+++ b/src/xxd/Make_bc5.mak
@@ -0,0 +1,18 @@
+# The most simplistic Makefile for Win32 (NT and Windows 95).
+# Used for Borland C++.
+
+!if ("$(BOR)"=="")
+BOR = c:\bc5
+!endif
+!if ("$(BCC)"=="")
+BCC = bcc32
+!endif
+
+xxd: xxd.exe
+
+xxd.exe: xxd.c
+ $(BCC) -I$(BOR)\include -L$(BOR)\lib -DWIN32 xxd.c $(BOR)\lib\wildargs.obj
+
+clean:
+ - del xxd.obj
+ - del xxd.exe
diff --git a/src/xxd/Make_cyg.mak b/src/xxd/Make_cyg.mak
new file mode 100644
index 000000000..f04b7bfde
--- /dev/null
+++ b/src/xxd/Make_cyg.mak
@@ -0,0 +1,27 @@
+# The most simplistic Makefile, for Cygnus gcc on MS-DOS
+
+ifndef USEDLL
+USEDLL = no
+endif
+
+ifeq (yes, $(USEDLL))
+DEFINES =
+LIBS = -lc
+else
+DEFINES = -mno-cygwin
+LIBS =
+endif
+
+CFLAGS = -O2 -Wall -DWIN32 $(DEFINES)
+
+ifneq (sh.exe, $(SHELL))
+DEL = rm
+else
+DEL = del
+endif
+
+xxd.exe: xxd.c
+ gcc $(CFLAGS) -s -o xxd.exe xxd.c $(LIBS)
+
+clean:
+ -$(DEL) xxd.exe
diff --git a/src/xxd/Make_djg.mak b/src/xxd/Make_djg.mak
new file mode 100644
index 000000000..f6eed3130
--- /dev/null
+++ b/src/xxd/Make_djg.mak
@@ -0,0 +1,9 @@
+# The most simplistic Makefile, for DJGPP on MS-DOS
+
+CFLAGS = -O2 -Wall
+
+xxd.exe: xxd.c
+ gcc $(CFLAGS) -s -o xxd.exe xxd.c -lpc
+
+clean:
+ del xxd.exe
diff --git a/src/xxd/Make_mvc.mak b/src/xxd/Make_mvc.mak
new file mode 100644
index 000000000..0c9438aa1
--- /dev/null
+++ b/src/xxd/Make_mvc.mak
@@ -0,0 +1,11 @@
+# The most simplistic Makefile for Win32 using Microsoft Visual C++
+# (NT and Windows 95)
+
+xxd: xxd.exe
+
+xxd.exe: xxd.c
+ cl /nologo -DWIN32 xxd.c /link setargv.obj
+
+clean:
+ - if exist xxd.obj del xxd.obj
+ - if exist xxd.exe del xxd.exe
diff --git a/src/xxd/Make_os2.mak b/src/xxd/Make_os2.mak
new file mode 100644
index 000000000..cb6694e1c
--- /dev/null
+++ b/src/xxd/Make_os2.mak
@@ -0,0 +1,11 @@
+# A very (if most the most) simplistic Makefile for OS/2
+
+CC=gcc
+CFLAGS=-O2 -fno-strength-reduce -DOS2
+
+xxd.exe: xxd.c
+ $(CC) $(CFLAGS) -s -o $@ $<
+
+clean:
+ - del xxd.o
+ - del xxd.exe
diff --git a/src/xxd/Make_vms.mms b/src/xxd/Make_vms.mms
new file mode 100644
index 000000000..872cd75f7
--- /dev/null
+++ b/src/xxd/Make_vms.mms
@@ -0,0 +1,69 @@
+# VMS MM[KS] makefile for XXD
+# tested with MMK and MMS as well.
+#
+# Maintained by Zoltan Arpadffy <arpadffy@polarhome.com>
+#
+# Edit the lines in the Configuration section below to select.
+#
+# To build: use the following command line:
+#
+# mms/descrip=Make_vms.mms
+# or if you use mmk
+# mmk/descrip=Make_vms.mms
+#
+
+######################################################################
+# Configuration section.
+######################################################################
+# Compiler selection.
+# Comment out if you use the VAXC compiler
+######################################################################
+# DECC = YES
+
+#####################################################################
+# Uncomment if want a debug version. Resulting executable is DVIM.EXE
+######################################################################
+# DEBUG = YES
+
+######################################################################
+# End of configuration section.
+#
+# Please, do not change anything below without programming experience.
+######################################################################
+
+CC = cc
+
+.IFDEF DECC
+CC_DEF = $(CC)/decc
+PREFIX = /prefix=all
+.ELSE
+CC_DEF = $(CC)
+PREFIX =
+.ENDIF
+
+LD_DEF = link
+
+.IFDEF DEBUG
+TARGET = dxxd.exe
+CFLAGS = /debug/noopt$(PREFIX)/cross_reference/include=[]
+LDFLAGS = /debug
+.ELSE
+TARGET = xxd.exe
+CFLAGS = /opt$(PREFIX)/include=[]
+LDFLAGS =
+.ENDIF
+
+.SUFFIXES : .obj .c
+
+SOURCES = xxd.c
+OBJ = xxd.obj
+
+.obj.c :
+ $(CC_DEF) $(CFLAGS) $<
+
+$(TARGET) : $(OBJ)
+ $(LD_DEF) $(LDFLAGS) /exe=$(TARGET) $+
+
+clean :
+ -@ if "''F$SEARCH("*.obj")'" .NES. "" then delete/noconfirm/nolog *.obj;*
+ -@ if "''F$SEARCH("*.exe")'" .NES. "" then delete/noconfirm/nolog *.exe;*
diff --git a/src/xxd/Makefile b/src/xxd/Makefile
new file mode 100644
index 000000000..97bbcc77b
--- /dev/null
+++ b/src/xxd/Makefile
@@ -0,0 +1,7 @@
+# The most simplistic Makefile
+
+xxd: xxd.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -DUNIX -o xxd xxd.c
+
+clean:
+ rm -f xxd xxd.o
diff --git a/src/xxd/xxd.c b/src/xxd/xxd.c
new file mode 100644
index 000000000..499f76244
--- /dev/null
+++ b/src/xxd/xxd.c
@@ -0,0 +1,767 @@
+/* xxd: my hexdump facility. jw
+ *
+ * 2.10.90 changed to word output
+ * 3.03.93 new indent style, dumb bug inserted and fixed.
+ * -c option, mls
+ * 26.04.94 better option parser, -ps, -l, -s added.
+ * 1.07.94 -r badly needs - as input file. Per default autoskip over
+ * consequtive lines of zeroes, as unix od does.
+ * -a shows them too.
+ * -i dump as c-style #include "file.h"
+ * 1.11.95 if "xxd -i" knows the filename, an 'unsigned char filename_bits[]'
+ * array is written in correct c-syntax.
+ * -s improved, now defaults to absolute seek, relative requires a '+'.
+ * -r improved, now -r -s -0x... is supported.
+ * change/suppress leading '\0' bytes.
+ * -l n improved: stops exactly after n bytes.
+ * -r improved, better handling of partial lines with trailing garbage.
+ * -r improved, now -r -p works again!
+ * -r improved, less flushing, much faster now! (that was silly)
+ * 3.04.96 Per repeated request of a single person: autoskip defaults to off.
+ * 15.05.96 -v added. They want to know the version.
+ * -a fixed, to show last line inf file ends in all zeros.
+ * -u added: Print upper case hex-letters, as preferred by unix bc.
+ * -h added to usage message. Usage message extended.
+ * Now using outfile if specified even in normal mode, aehem.
+ * No longer mixing of ints and longs. May help doze people.
+ * Added binify ioctl for same reason. (Enough Doze stress for 1996!)
+ * 16.05.96 -p improved, removed occasional superfluous linefeed.
+ * 20.05.96 -l 0 fixed. tried to read anyway.
+ * 21.05.96 -i fixed. now honours -u, and prepends __ to numeric filenames.
+ * compile -DWIN32 for NT or W95. George V. Reilly, * -v improved :-)
+ * support --gnuish-longhorn-options
+ * 25.05.96 MAC support added: CodeWarrior already uses ``outline'' in Types.h
+ * which is included by MacHeaders (Axel Kielhorn). Renamed to
+ * xxdline().
+ * 7.06.96 -i printed 'int' instead of 'char'. *blush*
+ * added Bram's OS2 ifdefs...
+ * 18.07.96 gcc -Wall @ SunOS4 is now slient.
+ * Added osver for MSDOS/DJGPP/WIN32.
+ * 29.08.96 Added size_t to strncmp() for Amiga.
+ * 24.03.97 Windows NT support (Phil Hanna). Clean exit for Amiga WB (Bram)
+ * 02.04.97 Added -E option, to have EBCDIC translation instead of ASCII
+ * (antonio.colombo@jrc.it)
+ * 22.05.97 added -g (group octets) option (jcook@namerica.kla.com).
+ * 23.09.98 nasty -p -r misfeature fixed: slightly wrong output, when -c was
+ * missing or wrong.
+ * 26.09.98 Fixed: 'xxd -i infile outfile' did not truncate outfile.
+ * 27.10.98 Fixed: -g option parser required blank.
+ * option -b added: 01000101 binary output in normal format.
+ * 16.05.00 Added VAXC changes by Stephen P. Wall
+ * 16.05.00 Improved MMS file and merege for VMS by Zoltan Arpadffy
+ *
+ * (c) 1990-1998 by Juergen Weigert (jnweiger@informatik.uni-erlangen.de)
+ *
+ * Small changes made afterwards by Bram Moolenaar et al.
+ *
+ * Distribute freely and credit me,
+ * make money and share with me,
+ * lose money and don't ask me.
+ */
+#include <stdio.h>
+#ifdef VAXC
+# include <file.h>
+#else
+# include <fcntl.h>
+#endif
+#ifdef __TSC__
+# define MSDOS
+#endif
+#if !defined(OS2) && defined(__EMX__)
+# define OS2
+#endif
+#if defined(MSDOS) || defined(WIN32) || defined(OS2) || defined(__BORLANDC__)
+# include <io.h> /* for setmode() */
+#else
+# ifdef UNIX
+# include <unistd.h>
+# endif
+#endif
+#include <stdlib.h>
+#include <string.h> /* for strncmp() */
+#include <ctype.h> /* for isalnum() */
+#if __MWERKS__ && !defined(BEBOX)
+# include <unix.h> /* for fdopen() on MAC */
+#endif
+
+#if defined(__BORLANDC__) && __BORLANDC__ <= 0x0410 && !defined(fileno)
+/* Missing define and prototype grabbed from the BC 4.0 <stdio.h> */
+# define fileno(f) ((f)->fd)
+FILE _FAR *_Cdecl _FARFUNC fdopen(int __handle, char _FAR *__type);
+#endif
+
+
+/* This corrects the problem of missing prototypes for certain functions
+ * in some GNU installations (e.g. SunOS 4.1.x).
+ * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
+ */
+#if defined(__GNUC__) && defined(__STDC__)
+# ifndef __USE_FIXED_PROTOTYPES__
+# define __USE_FIXED_PROTOTYPES__
+# endif
+#endif
+
+#ifndef __USE_FIXED_PROTOTYPES__
+/*
+ * This is historic and works only if the compiler really has no prototypes:
+ *
+ * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
+ * FILE is defined on OS 4.x, not on 5.x (Solaris).
+ * if __SVR4 is defined (some Solaris versions), don't include this.
+ */
+#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
+# define __P(a) a
+/* excerpt from my sun_stdlib.h */
+extern int fprintf __P((FILE *, char *, ...));
+extern int fputs __P((char *, FILE *));
+extern int _flsbuf __P((unsigned char, FILE *));
+extern int _filbuf __P((FILE *));
+extern int fflush __P((FILE *));
+extern int fclose __P((FILE *));
+extern int fseek __P((FILE *, long, int));
+extern int rewind __P((FILE *));
+
+extern void perror __P((char *));
+# endif
+#endif
+
+extern long int strtol();
+extern long int ftell();
+
+char version[] = "xxd V1.10 27oct98 by Juergen Weigert";
+#ifdef WIN32
+char osver[] = " (Win32)";
+#else
+# ifdef DJGPP
+char osver[] = " (dos 32 bit)";
+# else
+# ifdef MSDOS
+char osver[] = " (dos 16 bit)";
+# else
+char osver[] = "";
+# endif
+# endif
+#endif
+
+#if !defined(CYGWIN) && (defined(CYGWIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__))
+# define CYGWIN
+#endif
+#if defined(MSDOS) || defined(WIN32) || defined(OS2) || defined(CYGWIN)
+# define BIN_READ(yes) ((yes) ? "rb" : "rt")
+# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
+# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
+# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
+# if defined(CYGWIN)
+# define PATH_SEP '/'
+# else
+# define PATH_SEP '\\'
+# endif
+#else
+# ifdef VMS
+# define BIN_READ(dummy) "r"
+# define BIN_WRITE(dummy) "w"
+# define BIN_CREAT(dummy) O_CREAT
+# define BIN_ASSIGN(fp, dummy) fp
+# define PATH_SEP ']'
+# define FILE_SEP '.'
+# else
+# define BIN_READ(dummy) "r"
+# define BIN_WRITE(dummy) "w"
+# define BIN_CREAT(dummy) O_CREAT
+# define BIN_ASSIGN(fp, dummy) fp
+# define PATH_SEP '/'
+# endif
+#endif
+
+/* open has only to arguments on the Mac */
+#if __MWERKS__
+# define OPEN(name, mode, umask) open(name, mode)
+#else
+# define OPEN(name, mode, umask) open(name, mode, umask)
+#endif
+
+#ifdef AMIGA
+# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
+#else
+# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
+#endif
+
+#ifndef __P
+# if defined(__STDC__) || defined(MSDOS) || defined(WIN32) || defined(OS2) \
+ || defined(__BORLANDC__)
+# define __P(a) a
+# else
+# define __P(a) ()
+# endif
+#endif
+
+/* Let's collect some prototypes */
+/* CodeWarrior is really picky about missing prototypes */
+static void exit_with_usage __P((char *));
+static int huntype __P((FILE *, FILE *, FILE *, char *, int, int, long));
+static void xxdline __P((FILE *, char *, int));
+
+#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
+#define COLS 256 /* change here, if you ever need more columns */
+#define LLEN (9 + (5*COLS-1)/2 + 2 + COLS)
+
+char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
+
+/* the different hextypes known by this program: */
+#define HEX_NORMAL 0
+#define HEX_POSTSCRIPT 1
+#define HEX_CINCLUDE 2
+#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
+
+static void
+exit_with_usage(pname)
+char *pname;
+{
+ fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
+ fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
+ fprintf(stderr, " -b binary digit dump (incompatible with -p,-i,-r). Default hex.\n");
+ fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
+ fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
+ fprintf(stderr, " -g number of octets per group in normal output. Default 2.\n");
+ fprintf(stderr, " -h print this summary.\n");
+ fprintf(stderr, " -i output in C include file style.\n");
+ fprintf(stderr, " -l len stop after <len> octets.\n");
+ fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
+ fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
+ fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
+ fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
+#ifdef TRY_SEEK
+ "[+][-]", "(or +: rel.) ");
+#else
+ "", "");
+#endif
+ fprintf(stderr, " -u use upper case hex letters.\n");
+ fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
+ exit(1);
+}
+
+/*
+ * Max. cols binary characters are decoded from the input stream per line.
+ * Two adjacent garbage characters after evaluated data delimit valid data.
+ * Everything up to the next newline is discarded.
+ *
+ * The name is historic and came from 'undo type opt h'.
+ */
+static int
+huntype(fpi, fpo, fperr, pname, cols, hextype, base_off)
+FILE *fpi, *fpo, *fperr;
+char *pname;
+int cols, hextype;
+long base_off;
+{
+ int c, ign_garb = 1, n1 = -1, n2 = 0, n3, p = cols;
+ long have_off = 0, want_off = 0;
+
+ rewind(fpi);
+
+ while ((c = getc(fpi)) != EOF)
+ {
+ if (c == '\r') /* Doze style input file? */
+ continue;
+
+ n3 = n2;
+ n2 = n1;
+
+ if (c >= '0' && c <= '9')
+ n1 = c - '0';
+ else if (c >= 'a' && c <= 'f')
+ n1 = c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ n1 = c - 'A' + 10;
+ else
+ {
+ n1 = -1;
+ if (ign_garb)
+ continue;
+ }
+
+ ign_garb = 0;
+
+ if (p >= cols)
+ {
+ if (!hextype)
+ {
+ if (n1 < 0)
+ {
+ p = 0;
+ continue;
+ }
+ want_off = (want_off << 4) | n1;
+ continue;
+ }
+ else
+ p = 0;
+ }
+
+ if (base_off + want_off != have_off)
+ {
+ fflush(fpo);
+#ifdef TRY_SEEK
+ c = fseek(fpo, base_off + want_off - have_off, 1);
+ if (c >= 0)
+ have_off = base_off + want_off;
+#endif
+ if (base_off + want_off < have_off)
+ {
+ fprintf(fperr, "%s: sorry, cannot seek backwards.\n", pname);
+ return 5;
+ }
+ for (; have_off < base_off + want_off; have_off++)
+ putc(0, fpo);
+ }
+
+ if (n2 >= 0 && n1 >= 0)
+ {
+ putc((n2 << 4) | n1, fpo);
+ have_off++;
+ want_off++;
+ n1 = -1;
+ if ((++p >= cols) && !hextype)
+ {
+ /* skip rest of line as garbaga */
+ want_off = 0;
+ while ((c = getc(fpi)) != '\n' && c != EOF)
+ ;
+ ign_garb = 1;
+ }
+ }
+ else if (n1 < 0 && n2 < 0 && n3 < 0)
+ {
+ /* already stumbled into garbage, skip line, wait and see */
+ if (!hextype)
+ want_off = 0;
+ while ((c = getc(fpi)) != '\n' && c != EOF)
+ ;
+ ign_garb = 1;
+ }
+ }
+ fflush(fpo);
+#ifdef TRY_SEEK
+ fseek(fpo, 0L, 2);
+#endif
+ fclose(fpo);
+ fclose(fpi);
+ return 0;
+}
+
+/*
+ * Print line l. If nz is false, xxdline regards the line a line of
+ * zeroes. If there are three or more consecutive lines of zeroes,
+ * they are replaced by a single '*' character.
+ *
+ * If the output ends with more than two lines of zeroes, you
+ * should call xxdline again with l being the last line and nz
+ * negative. This ensures that the last line is shown even when
+ * it is all zeroes.
+ *
+ * If nz is always positive, lines are never suppressed.
+ */
+static void
+xxdline(fp, l, nz)
+FILE *fp;
+char *l;
+int nz;
+{
+ static char z[LLEN+1];
+ static int zero_seen = 0;
+
+ if (!nz && zero_seen == 1)
+ strcpy(z, l);
+
+ if (nz || !zero_seen++)
+ {
+ if (nz)
+ {
+ if (nz < 0)
+ zero_seen--;
+ if (zero_seen == 2)
+ fputs(z, fp);
+ if (zero_seen > 2)
+ fputs("*\n", fp);
+ }
+ if (nz >= 0 || zero_seen > 0)
+ fputs(l, fp);
+ if (nz)
+ zero_seen = 0;
+ }
+}
+
+/* This is an EBCDIC to ASCII conversion table */
+/* from a proposed BTL standard April 16, 1979 */
+static unsigned char etoa64[] =
+{
+ 0040,0240,0241,0242,0243,0244,0245,0246,
+ 0247,0250,0325,0056,0074,0050,0053,0174,
+ 0046,0251,0252,0253,0254,0255,0256,0257,
+ 0260,0261,0041,0044,0052,0051,0073,0176,
+ 0055,0057,0262,0263,0264,0265,0266,0267,
+ 0270,0271,0313,0054,0045,0137,0076,0077,
+ 0272,0273,0274,0275,0276,0277,0300,0301,
+ 0302,0140,0072,0043,0100,0047,0075,0042,
+ 0303,0141,0142,0143,0144,0145,0146,0147,
+ 0150,0151,0304,0305,0306,0307,0310,0311,
+ 0312,0152,0153,0154,0155,0156,0157,0160,
+ 0161,0162,0136,0314,0315,0316,0317,0320,
+ 0321,0345,0163,0164,0165,0166,0167,0170,
+ 0171,0172,0322,0323,0324,0133,0326,0327,
+ 0330,0331,0332,0333,0334,0335,0336,0337,
+ 0340,0341,0342,0343,0344,0135,0346,0347,
+ 0173,0101,0102,0103,0104,0105,0106,0107,
+ 0110,0111,0350,0351,0352,0353,0354,0355,
+ 0175,0112,0113,0114,0115,0116,0117,0120,
+ 0121,0122,0356,0357,0360,0361,0362,0363,
+ 0134,0237,0123,0124,0125,0126,0127,0130,
+ 0131,0132,0364,0365,0366,0367,0370,0371,
+ 0060,0061,0062,0063,0064,0065,0066,0067,
+ 0070,0071,0372,0373,0374,0375,0376,0377
+};
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ FILE *fp, *fpo;
+ int c, e, p = 0, relseek = 1, negseek = 0, revert = 0;
+ int cols = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
+ int ebcdic = 0;
+ int octspergrp = -1; /* number of octets grouped in output */
+ int grplen; /* total chars per octet group */
+ long length = -1, n = 0, seekoff = 0;
+ char l[LLEN+1];
+ char *pname, *pp;
+
+#ifdef AMIGA
+ /* This program doesn't work when started from the Workbench */
+ if (argc == 0)
+ exit(1);
+#endif
+
+ pname = argv[0];
+ for (pp = pname; *pp; )
+ if (*pp++ == PATH_SEP)
+ pname = pp;
+#ifdef FILE_SEP
+ for (pp = pname; *pp; pp++)
+ if (*pp == FILE_SEP)
+ {
+ *pp = '\0';
+ break;
+ }
+#endif
+
+ while (argc >= 2)
+ {
+ pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
+ if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
+ else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
+ else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
+ else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
+ else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
+ else if (!STRNCMP(pp, "-r", 2)) revert++;
+ else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
+ else if (!STRNCMP(pp, "-v", 2))
+ {
+ fprintf(stderr, "%s%s\n", version, osver);
+ exit(0);
+ }
+ else if (!STRNCMP(pp, "-c", 2))
+ {
+ if (pp[2] && STRNCMP("ols", pp + 2, 3))
+ cols = (int)strtol(pp + 2, NULL, 0);
+ else
+ {
+ if (!argv[2])
+ exit_with_usage(pname);
+ cols = (int)strtol(argv[2], NULL, 0);
+ argv++;
+ argc--;
+ }
+ }
+ else if (!STRNCMP(pp, "-g", 2))
+ {
+ if (pp[2] && STRNCMP("group", pp + 2, 5))
+ octspergrp = (int)strtol(pp + 2, NULL, 0);
+ else
+ {
+ if (!argv[2])
+ exit_with_usage(pname);
+ octspergrp = (int)strtol(argv[2], NULL, 0);
+ argv++;
+ argc--;
+ }
+ }
+ else if (!STRNCMP(pp, "-s", 2))
+ {
+ relseek = 0;
+ negseek = 0;
+ if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
+ {
+#ifdef TRY_SEEK
+ if (pp[2] == '+')
+ relseek++;
+ if (pp[2+relseek] == '-')
+ negseek++;
+#endif
+ seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
+ }
+ else
+ {
+ if (!argv[2])
+ exit_with_usage(pname);
+#ifdef TRY_SEEK
+ if (argv[2][0] == '+')
+ relseek++;
+ if (argv[2][relseek] == '-')
+ negseek++;
+#endif
+ seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
+ argv++;
+ argc--;
+ }
+ }
+ else if (!STRNCMP(pp, "-l", 2))
+ {
+ if (pp[2] && STRNCMP("en", pp + 2, 2))
+ length = strtol(pp + 2, (char **)NULL, 0);
+ else
+ {
+ if (!argv[2])
+ exit_with_usage(pname);
+ length = strtol(argv[2], (char **)NULL, 0);
+ argv++;
+ argc--;
+ }
+ }
+ else if (!strcmp(pp, "--")) /* end of options */
+ {
+ argv++;
+ argc--;
+ break;
+ }
+ else if (pp[0] == '-' && pp[1]) /* unknown option */
+ exit_with_usage(pname);
+ else
+ break; /* not an option */
+
+ argv++; /* advance to next argument */
+ argc--;
+ }
+
+ if (!cols)
+ switch (hextype)
+ {
+ case HEX_POSTSCRIPT: cols = 30; break;
+ case HEX_CINCLUDE: cols = 12; break;
+ case HEX_BITS: cols = 6; break;
+ case HEX_NORMAL:
+ default: cols = 16; break;
+ }
+
+ if (octspergrp < 0)
+ switch (hextype)
+ {
+ case HEX_BITS: octspergrp = 1; break;
+ case HEX_NORMAL: octspergrp = 2; break;
+ case HEX_POSTSCRIPT:
+ case HEX_CINCLUDE:
+ default: octspergrp = 0; break;
+ }
+
+ if (cols < 1 || (!hextype && (cols > COLS)))
+ {
+ fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
+ exit(1);
+ }
+
+ if (octspergrp < 1)
+ octspergrp = cols;
+
+ if (argc > 3)
+ exit_with_usage(pname);
+
+ if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
+ BIN_ASSIGN(fp = stdin, !revert);
+ else
+ {
+ if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
+ {
+ fprintf(stderr,"%s: ", pname);
+ perror(argv[1]);
+ return 2;
+ }
+ }
+
+ if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
+ BIN_ASSIGN(fpo = stdout, revert);
+ else
+ {
+ int fd;
+ int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
+
+ if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
+ (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
+ {
+ fprintf(stderr, "%s: ", pname);
+ perror(argv[2]);
+ return 3;
+ }
+ rewind(fpo);
+ }
+
+ if (revert)
+ {
+ if (hextype && (hextype != HEX_POSTSCRIPT))
+ {
+ fprintf(stderr, "%s: sorry, cannot revert this type of hexdump\n", pname);
+ return -1;
+ }
+ return huntype(fp, fpo, stderr, pname, cols, hextype,
+ negseek ? -seekoff : seekoff);
+ }
+
+ if (seekoff || negseek || !relseek)
+ {
+#ifdef TRY_SEEK
+ if (relseek)
+ e = fseek(fp, negseek ? -seekoff : seekoff, 1);
+ else
+ e = fseek(fp, negseek ? -seekoff : seekoff, negseek ? 2 : 0);
+ if (e < 0 && negseek)
+ {
+ fprintf(stderr, "%s: sorry cannot seek.\n", pname);
+ return 4;
+ }
+ if (e >= 0)
+ seekoff = ftell(fp);
+ else
+#endif
+ {
+ long s = seekoff;
+
+ while (s--)
+ (void)getc(fp);
+ }
+ }
+
+ if (hextype == HEX_CINCLUDE)
+ {
+ if (fp != stdin)
+ {
+ fprintf(fpo, "unsigned char %s", isdigit((int)argv[1][0]) ? "__" : "");
+ for (e = 0; (c = argv[1][e]) != 0; e++)
+ putc(isalnum(c) ? c : '_', fpo);
+ fputs("[] = {\n", fpo);
+ }
+
+ p = 0;
+ while ((length < 0 || p < length) && (c = getc(fp)) != EOF)
+ {
+ fprintf(fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
+ (p % cols) ? ", " : ",\n "+2*!p, c);
+ p++;
+ }
+
+ if (p)
+ fputs("\n};\n"+3*(fp == stdin), fpo);
+
+ if (fp != stdin)
+ {
+ fprintf(fpo, "unsigned int %s", isdigit((int)argv[1][0]) ? "__" : "");
+ for (e = 0; (c = argv[1][e]) != 0; e++)
+ putc(isalnum(c) ? c : '_', fpo);
+ fprintf(fpo, "_len = %d;\n", p);
+ }
+
+ fclose(fp);
+ fclose(fpo);
+ return 0;
+ }
+
+ if (hextype == HEX_POSTSCRIPT)
+ {
+ p = cols;
+ while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
+ {
+ putchar(hexx[(e >> 4) & 0xf]);
+ putchar(hexx[(e ) & 0xf]);
+ n++;
+ if (!--p)
+ {
+ putchar('\n');
+ p = cols;
+ }
+ }
+ if (p < cols)
+ putchar('\n');
+ fclose(fp);
+ fclose(fpo);
+ return 0;
+ }
+
+ /* hextype: HEX_NORMAL or HEX_BITS */
+
+ if (hextype == HEX_NORMAL)
+ grplen = octspergrp + octspergrp + 1; /* chars per octet group */
+ else /* hextype == HEX_BITS */
+ grplen = 8 * octspergrp + 1;
+
+ while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
+ {
+ if (p == 0)
+ {
+ sprintf(l, "%07lx: ", n + seekoff);
+ for (c = 9; c < LLEN; l[c++] = ' ');
+ }
+ if (hextype == HEX_NORMAL)
+ {
+ l[c = (9 + (grplen * p) / octspergrp)] = hexx[(e >> 4) & 0xf];
+ l[++c] = hexx[ e & 0xf];
+ }
+ else /* hextype == HEX_BITS */
+ {
+ int i;
+
+ c = (9 + (grplen * p) / octspergrp) - 1;
+ for (i = 7; i >= 0; i--)
+ l[++c] = (e & (1 << i)) ? '1' : '0';
+ }
+ if (ebcdic)
+ e = (e < 64) ? '.' : etoa64[e-64];
+ l[11 + (grplen * cols - 1)/octspergrp + p] =
+#ifdef __MVS__
+ (e >= 64)
+#else
+ (e > 31 && e < 127)
+#endif
+ ? e : '.';
+ if (e)
+ nonzero++;
+ n++;
+ if (++p == cols)
+ {
+ l[c = (11 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
+ xxdline(fpo, l, autoskip ? nonzero : 1);
+ nonzero = 0;
+ p = 0;
+ }
+ }
+ if (p)
+ {
+ l[c = (11 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
+ xxdline(fpo, l, 1);
+ }
+ else if (autoskip)
+ xxdline(fpo, l, -1); /* last chance to flush out supressed lines */
+
+ fclose(fp);
+ fclose(fpo);
+ return 0;
+}